Version 2.12.0-259.1.beta

Merge '2.12.0-259.0.dev' into beta
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 0c72699..3daa83f 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -1,6 +1,6 @@
 {
   "copyright": [
-    "Copyright (c) 2020, the Dart project authors. Please see the AUTHORS ",
+    "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."
   ],
@@ -11,14 +11,14 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2020-12-03T14:26:48.568312",
+  "generated": "2021-01-16T20:34:15.774260",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
       "name": "_fe_analyzer_shared",
       "rootUri": "../pkg/_fe_analyzer_shared",
       "packageUri": "lib/",
-      "languageVersion": "2.6"
+      "languageVersion": "2.12"
     },
     {
       "name": "_fe_analyzer_shared_assigned_variables",
@@ -95,7 +95,7 @@
       "name": "analyzer_utilities",
       "rootUri": "../pkg/analyzer_utilities",
       "packageUri": "lib/",
-      "languageVersion": "2.1"
+      "languageVersion": "2.12"
     },
     {
       "name": "args",
@@ -273,7 +273,7 @@
       "name": "front_end",
       "rootUri": "../pkg/front_end",
       "packageUri": "lib/",
-      "languageVersion": "2.6"
+      "languageVersion": "2.12"
     },
     {
       "name": "front_end_testcases",
@@ -296,7 +296,7 @@
       "name": "html",
       "rootUri": "../third_party/pkg/html",
       "packageUri": "lib/",
-      "languageVersion": "2.3"
+      "languageVersion": "2.8"
     },
     {
       "name": "http",
@@ -354,8 +354,9 @@
     },
     {
       "name": "js_runtime",
-      "rootUri": "../sdk/lib/_internal/js_runtime",
-      "packageUri": "lib/"
+      "rootUri": "../pkg/js_runtime",
+      "packageUri": "lib/",
+      "languageVersion": "2.12"
     },
     {
       "name": "json_rpc_2",
@@ -367,7 +368,7 @@
       "name": "kernel",
       "rootUri": "../pkg/kernel",
       "packageUri": "lib/",
-      "languageVersion": "2.6"
+      "languageVersion": "2.12"
     },
     {
       "name": "language_versioning_2.7_test",
@@ -396,7 +397,7 @@
       "name": "matcher",
       "rootUri": "../third_party/pkg/matcher",
       "packageUri": "lib/",
-      "languageVersion": "2.10"
+      "languageVersion": "2.12"
     },
     {
       "name": "meta",
@@ -408,7 +409,7 @@
       "name": "mime",
       "rootUri": "../third_party/pkg/mime",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "mockito",
@@ -472,7 +473,7 @@
       "name": "package_config",
       "rootUri": "../third_party/pkg_tested/package_config",
       "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "languageVersion": "2.12"
     },
     {
       "name": "package_deps",
@@ -632,7 +633,7 @@
       "name": "sync_http",
       "rootUri": "../third_party/pkg/sync_http",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "telemetry",
@@ -680,7 +681,7 @@
       "name": "test_reflective_loader",
       "rootUri": "../third_party/pkg/test_reflective_loader",
       "packageUri": "lib/",
-      "languageVersion": "1.8"
+      "languageVersion": "2.12"
     },
     {
       "name": "test_runner",
@@ -722,7 +723,7 @@
       "name": "vm_service",
       "rootUri": "../pkg/vm_service",
       "packageUri": "lib/",
-      "languageVersion": "2.6"
+      "languageVersion": "2.12"
     },
     {
       "name": "vm_snapshot_analysis",
@@ -740,7 +741,7 @@
       "name": "watcher",
       "rootUri": "../third_party/pkg/watcher",
       "packageUri": "lib/",
-      "languageVersion": "2.2"
+      "languageVersion": "2.12"
     },
     {
       "name": "web_components",
diff --git a/.packages b/.packages
index d31bc9b..badd487 100644
--- a/.packages
+++ b/.packages
@@ -54,7 +54,7 @@
 intl:third_party/pkg/intl/lib
 js:pkg/js/lib
 js_ast:pkg/js_ast/lib
-js_runtime:sdk/lib/_internal/js_runtime/lib
+js_runtime:pkg/js_runtime/lib
 json_rpc_2:third_party/pkg/json_rpc_2/lib
 kernel:pkg/kernel/lib
 linter:third_party/pkg/linter/lib
diff --git a/BUILD.gn b/BUILD.gn
index 3962d40..1140b668 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -159,16 +159,64 @@
   import("third_party/fuchsia/sdk/linux/build/component.gni")
   import("third_party/fuchsia/sdk/linux/build/package.gni")
 
-  fuchsia_component("fuchsia_test_component") {
-    testonly = true
-    data_deps = [ "runtime/bin:dart" ]
-    manifest = "build/fuchsia/dart.cmx"
+  template("dart_fuchsia_test_package") {
+    fuchsia_package(target_name) {
+      package_name = invoker.package_name
+      if (is_debug) {
+        package_name += "_debug"
+      } else if (is_release) {
+        package_name += "_release"
+      } else if (is_product) {
+        package_name += "_product"
+      }
+      testonly = true
+      deps = invoker.deps
+    }
+  }
 
-    resource_files = [
-      ".dart_tool/package_config.json",
-      "pkg/testing/test/hello_test.dart",
-      "tools/addlatexhash.dart",
-    ]
+  template("dart_fuchsia_test_component") {
+    fuchsia_component(target_name) {
+      testonly = true
+      data_deps = [ "runtime/bin:dart" ]
+      if (defined(invoker.data_deps)) {
+        data_deps += invoker.data_deps
+      }
+      manifest = "build/fuchsia/dart.cmx"
+
+      library_files = []
+      if (defined(invoker.library_files)) {
+        library_files += invoker.library_files
+      }
+      resource_files = [
+        ".dart_tool/package_config.json",
+        "pkg/testing/test/hello_test.dart",
+        "tools/addlatexhash.dart",
+      ]
+      resource_dirs = invoker.resource_dirs
+
+      resources = []
+      foreach(file, library_files) {
+        resources += [
+          {
+            path = root_out_dir + "/" + file
+            dest = "lib/" + file
+          },
+        ]
+      }
+      foreach(file, resource_files) {
+        resources += [
+          {
+            path = file
+            dest = "data/" + file
+          },
+        ]
+      }
+      resources +=
+          exec_script("tools/fuchsia/find_resources.py", resource_dirs, "json")
+    }
+  }
+
+  dart_fuchsia_test_component("fuchsia_test_component") {
     resource_dirs = [
       "tests/standalone_2",
       "pkg/async_helper",
@@ -190,30 +238,32 @@
       "third_party/pkg/string_scanner",
       "third_party/pkg/typed_data",
     ]
-
-    resources = []
-    foreach(file, resource_files) {
-      resources += [
-        {
-          path = file
-          dest = "data/" + file
-        },
-      ]
-    }
-    resources +=
-        exec_script("tools/fuchsia/find_resources.py", resource_dirs, "json")
   }
 
-  fuchsia_package("fuchsia_test_package") {
-    package_name = "dart_test_"
-    if (is_debug) {
-      package_name += "debug"
-    } else if (is_release) {
-      package_name += "release"
-    } else if (is_product) {
-      package_name += "product"
-    }
-    testonly = true
+  dart_fuchsia_test_package("fuchsia_test_package") {
+    package_name = "dart_test"
     deps = [ ":fuchsia_test_component" ]
   }
+
+  dart_fuchsia_test_component("fuchsia_ffi_test_component") {
+    data_deps = [
+      "runtime/bin:ffi_test_dynamic_library",
+      "runtime/bin:ffi_test_functions",
+    ]
+    library_files = [
+      "libffi_test_dynamic_library.so",
+      "libffi_test_functions.so",
+    ]
+    resource_dirs = [
+      "pkg/expect",
+      "pkg/meta",
+      "tests/ffi",
+      "third_party/pkg/ffi",
+    ]
+  }
+
+  dart_fuchsia_test_package("fuchsia_ffi_test_package") {
+    package_name = "dart_ffi_test"
+    deps = [ ":fuchsia_ffi_test_component" ]
+  }
 }
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a0982c4..75ddaaa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,18 +2,42 @@
 
 ### Language
 
-**Breaking Change** [Null
-Safety](https://dart.dev/null-safety/understanding-null-safety) is now enabled
-by default in all packages with a lower sdk constraint of 2.12.0 or greater.
-Files that are not subject to language versioning (whether because they are not
-contained in a pub package, or because the package that they are contained in
-has no lower sdk constraint) are treated as opted into to null safety by default
-and may report new errors.  Pub packages may be opted out of null safety by
-setting a min sdk constraint in pubspec.yaml of 2.9.0 or less.  Files may be
-opted out of null safety by adding `// @dart=2.9` to the beginning of the file.
+*   **Breaking Change** [Null
+    Safety](https://dart.dev/null-safety/understanding-null-safety) is now
+    enabled by default in all packages with a lower sdk constraint of 2.12.0 or
+    greater.  Files that are not subject to language versioning (whether because
+    they are not contained in a pub package, or because the package that they
+    are contained in has no lower sdk constraint) are treated as opted into to
+    null safety by default and may report new errors.  Pub packages may be opted
+    out of null safety by setting a min sdk constraint in pubspec.yaml of 2.9.0
+    or less.  Files may be opted out of null safety by adding `// @dart=2.9` to
+    the beginning of the file.
+
+*   **Breaking Change** [#44660][]: Fixed an implementation bug where `this`
+    would sometimes undergo type promotion in extensions.
+
+[#44660]: https://github.com/dart-lang/sdk/issues/44660
 
 ### Core libraries
 
+#### `dart:async`
+
+* Adds extension method `onError` on `Future` to allow better typing
+  of error handling.
+
+#### `dart:collection`
+
+* Added `UnmodifiableSetView` class, which allows users to guarantee that
+  methods that could change underlying `Set` instance can not be invoked.
+
+* `LinkedList` made it explicit that elements are compared by identity,
+  and updated `contains` to take advantage of this.
+
+#### `dart:core`
+
+* Added `unmodifiable` constructor to class `Set`, which allows users to create
+  unmodifiable `Set` instances.
+
 #### `dart:io`
 
 * `HttpRequest` will now correctly follow HTTP 308 redirects
@@ -25,11 +49,6 @@
   constructors, a name which can be associated with the port and displayed in
   tooling.
 
-#### `dart:collection`
-
-* `LinkedList` made it explicit that elements are compared by identity,
-  and updated `contains` to take advantage of this.
-
 #### `dart:html`
 
 * `EventStreamSubscription.cancel` has been updated to retain its synchronous
@@ -50,6 +69,25 @@
 
 [#42312]: https://github.com/dart-lang/sdk/issues/42312
 
+### Foreign Function Interface (`dart:ffi`)
+
+*   **Breaking Change** [#44621][]: Invocations with a generic `T` of
+    `sizeOf<T>`, `Pointer<T>.elementAt()`, `Pointer<T extends Struct>.ref`, and
+    `Pointer<T extends Struct>[]` are being deprecated in the current stable
+    release (2.12), and are planned to be fully removed in the following stable
+    release (2.13). Consequently, `allocate` in `package:ffi` will no longer be
+    able to invoke `sizeOf<T>` generically, and will be deprecated as well.
+    Instead, the `Allocator` it is introduced to `dart:ffi`, and also requires
+    a constant `T` on invocations. For migration notes see the breaking change
+    request.
+*   **Breaking Change** [#44622][]: Subtypes of `Struct` without any native
+    member are being deprecated in the current stable release (2.12), and are
+    planned to be fully removed in the following stable release (2.13).
+    Migrate opaque types to extend `Opaque` rather than `Struct`.
+
+[#44621]: https://github.com/dart-lang/sdk/issues/44621
+[#44622]: https://github.com/dart-lang/sdk/issues/44622
+
 ### Dart2JS
 
 * Removed `--no-defer-class-types` and `--no-new-deferred-split`.
@@ -61,6 +99,46 @@
 * Removed the `--use-fasta-parser`, `--preview-dart-2`, and
   `--enable-assert-initializers` command line options. These options haven't
   been supported in a while and were no-ops.
+* Report diagnostics regarding the
+  [`@internal`](https://pub.dev/documentation/meta/latest/meta/internal-constant.html)
+  annotation.
+* Improve diagnostic-reporting regarding the
+  [`@doNotStore`](https://pub.dev/documentation/meta/latest/meta/doNotStore-constant.html)
+  annotation.
+* Introduce a diagnostic which is reported when a library member named `main`
+  is not a function.
+* Introduce a diagnostic which is reported when a `main` function's first
+  parameter is not a supertype of `List<String>`.
+* Introduce a diagnostic which is reported when an `// ignore` comment contains
+  an error code which is not being reported.
+* Introduce a diagnostic which is reported when an `// ignore` comment contains
+  an error code which cannot be ignored.
+* Introduce a diagnostic which is reported when an `// ignore` comment contains
+  an error code which is already being ignored.
+* Report diagnostics when using
+  [`@visibleForTesting`](https://pub.dev/documentation/meta/latest/meta/visibleForTesting-constant.html)
+  on top-level variables.
+* Fix false positive reports of "unused element" for top-level setters and
+  getters.
+* Fix false positive reports regarding `@deprecated` field formal parameters at
+  their declaration.
+* For null safety, introduce a diagnostic which reports when a null-check will
+  always fail.
+* Fix false positive reports regarding optional parameters on privat
+  constructors being unused.
+* Introduce a diagnostic which is reported when a constructor includes
+  duplicate field formal parameters.
+* Improve the "unused import" diagnostic when multiple import directives share
+  a common prefix.
+* Fix false positive "unused import" diagnostic regarding an import which
+  provides an extension method which is used.
+* For null safety, improve the messaging of "use of nullable value" diagnostics
+  for eight different contexts.
+* Fix false positive reports regarding `@visibleForTesting` members in a "hide"
+  combinator of an import or export directive.
+* Improve the messaging of "invalid override" diagnostics.
+* Introduce a diagnostic which is reported when `Future<T>.catchError` is
+  called with an `onError` callback which does not return `FutureOr<T>`.
 
 #### dartfmt
 
@@ -69,12 +147,17 @@
 
 #### Linter
 
-Updated the Linter to `0.1.126`, which includes:
+Updated the Linter to `0.1.129`, which includes:
 
-* fixed false negatives for `prefer_collection_literals` when a LinkedHashSet or
+* New lint: `avoid_dynamic_calls`.
+* (Internal): `avoid_type_to_string` updated to use `addArgumentList` registry API.
+* Miscellaneous documentation improvements.
+* Fixed crash in `prefer_collection_literals` when there is no static parameter
+  element.
+* Fixed false negatives for `prefer_collection_literals` when a LinkedHashSet or
   LinkedHashMap instantiation is passed as the argument to a function in any
   position other than the first.
-* fixed false negatives for `prefer_collection_literals` when a LinkedHashSet or
+* Fixed false negatives for `prefer_collection_literals` when a LinkedHashSet or
   LinkedHashMap instantiation is used in a place with a static type other than
   Set or Map.
 * (Internal): test updates to the new `PhysicalResourceProvider` API.
@@ -125,17 +208,47 @@
 * New command `dart pub add` that adds  new dependencies to your `pubspec.yaml`.
 
   And a corresponding `dart pub remove` that removes dependencies.
+* New option `dart pub upgrade --major-versions` will update constraints in
+  your `pubspec.yaml` to match the the _resolvable_ column reported in
+  `dart pub outdated`. This allows users to easily upgrade to latest version for
+  all dependencies where this is possible, even if such upgrade requires an
+  update to the version constraint in `pubspec.yaml`.
+
+  It is also possible to only upgrade the major version for a subset of your
+  dependencies using `dart pub upgrade --major-versions <dependencies...>`.
+* New option `dart pub upgrade --null-safety` will attempt to update constraints
+  in your `pubspec.yaml`, such that only null-safety migrated versions of
+  dependencies are allowed.
 * New option `dart pub outdated --mode=null-safety` that will analyze your
   dependencies for null-safety.
+* `dart pub get` and `dart pub upgrade` will highlight dependencies that have
+  been [discontinued](https://dart.dev/tools/pub/publishing#discontinue) on
+  pub.dev.
 * `dart pub publish` will now check your pubspec keys for likely typos.
+* `dart pub upgrade package_foo` will fetch dependencies, but ignore the
+  `pubspec.lock` for `package_foo`, allowing users to only upgrade a subset of
+  dependencies.
 * New command `dart pub login` that logs in to pub.dev.
 * The `--server` option to `dart pub publish` and `dart pub uploader` have been
   deprecated. Use `publish_to` in your `pubspec.yaml` or set the
   `$PUB_HOSTED_URL` environment variable.
+* `pub global activate no longer re-precompiles if current global installed was
+   same version.
+* The Flutter SDK constraint upper bound is now ignored in pubspecs and
+  deprecated when publishing.
 
+  See: [flutter-upper-bound-deprecation][].
+
+[flutter-upper-bound-deprecation]: https://dart.dev/go/flutter-upper-bound-deprecation
 [#44072]: https://github.com/dart-lang/sdk/issues/44072
 [dart tool]: https://dart.dev/tools/dart-tool
 
+## 2.10.5 - 2020-01-21
+
+This is a patch release that fixes a crash in the Dart VM. (issue [#44563][]).
+
+[#44563]: https://github.com/dart-lang/sdk/issues/44563
+
 ## 2.10.4 - 2020-11-12
 
 This is a patch release that fixes a crash in the Dart VM (issues [#43941][],
@@ -204,6 +317,11 @@
 *   Class `BytesBuilder` is moved from `dart:io` to `dart:typed_data`.
     It's temporarily being exported from `dart:io` as well.
 
+### `dart:uri`
+
+*   [#42564]: Solved inconsistency in `Uri.https` and `Uri.http` constructors'
+    `queryParams` type.
+
 ### Dart VM
 
 *   **Breaking Change** [#42982][]: `dart_api_dl.cc` is renamed to
diff --git a/DEPS b/DEPS
index cd9bba0..00cb7f7 100644
--- a/DEPS
+++ b/DEPS
@@ -39,12 +39,12 @@
 
   # 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.12.0-0.0.dev",
+  "sdk_tag": "version:2.12.0-133.2.beta",
 
   # 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
   # has.
-  "co19_rev": "d8e25398102add0ac1e732850928bd44c78f2447",
+  "co19_rev": "103d027d38472f9871b66fb0c2b01cc91c858c9f",
   "co19_2_rev": "e48b3090826cf40b8037648f19d211e8eab1b4b6",
 
   # The internal benchmarks to use. See go/dart-benchmarks-internal
@@ -68,12 +68,12 @@
   "gperftools_revision": "180bfa10d7cb38e8b3784d60943d50e8fcef0dcb",
 
   # Revisions of /third_party/* dependencies.
-  "args_rev": "139140125126661fac88c9aa5882165936d01c91",
+  "args_rev": "2c6a221f45e4e0ef447b5d09101bf8a52e1ccd36",
   "async_rev": "695b3ac280f107c84adf7488743abfdfaaeea68f",
   "bazel_worker_rev": "060c55a933d39798681a4f533b161b81dc48d77e",
   "benchmark_harness_rev": "ec6b646f5443faa871e126ac1ba248c94ca06257",
   "boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
-  "boringssl_gen_rev": "429ccb1877f7987a6f3988228bc2440e61293499",
+  "boringssl_gen_rev": "aaac86738c4f2d1bdf00f54d197f50f247ffee04",
   "boringssl_rev" : "4dfd5af70191b068aebe567b8e29ce108cee85ce",
   "browser-compat-data_tag": "v1.0.22",
   "charcode_rev": "bcd8a12c315b7a83390e4865ad847ecd9344cba2",
@@ -81,9 +81,9 @@
   "cli_util_rev" : "50cc840b146615899e97b892578848401b2028d5",
   "clock_rev" : "a494269254ba978e7ef8f192c5f7fec3fc05b9d3",
   "collection_rev": "e4bb038ce2d8e66fb15818aa40685c68d53692ab",
-  "convert_rev": "dd3bd28f63be7cb8ab961f38bc73229e4473b555",
-  "crypto_rev": "a5ec902dda5a635a35c6b363ec64458cf84c5872",
-  "csslib_rev": "6f77b3dcee957d3e2d5083f666221a220e9ed1f1",
+  "convert_rev": "6513985a1b1ea8a0b987fbef699250ce2cdc3cca",
+  "crypto_rev": "c89a5be0375875fe7ff71625fa2b79f5a421f06d",
+  "csslib_rev": "e411d862fd8cc50415c1badf2632e017373b3f47",
   "dart2js_info_rev" : "e0acfeb5affdf94c53067e68bd836adf589628fd",
 
   # Note: Updates to dart_style have to be coordinated with the infrastructure
@@ -98,73 +98,73 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-"dart_style_tag": "1.3.10",  # Please see the note above before updating.
+  "dart_style_tag": "1.3.11",  # Please see the note above before updating.
 
   "chromedriver_tag": "83.0.4103.39",
-  "dartdoc_rev" : "d79877d0764ce23ffea7055049f8da5dffce0308",
-  "ffi_rev": "a5d4232cd38562c75a3ed847baa340e399538028",
+  "dartdoc_rev" : "9e61a4f11091aaa8998525a2692b14148dc24ab5",
+  "ffi_rev": "f288e906c92e2ab378768dfa61a40814ede7a2a5",
   "fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba",
   "file_rev": "0e09370f581ab6388d46fda4cdab66638c0171a1",
   "glob_rev": "7c0ef8d4fa086f6b185c4dd724b700e7d7ad8f79",
-  "html_rev": "22f17e97fedeacaa1e945cf84d8016284eed33a6",
+  "html_rev": "7f31979303f916f2aabb9e2091950798abdd9ca1",
   "http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
-  "http_multi_server_rev" : "f1d1c9c024a293ab0a0e16f8b7632e87c708b448",
+  "http_multi_server_rev" : "e8c8be7f15b4fb50757ff5bf29766721fbe24fe4",
   "http_parser_rev": "5dd4d16693242049dfb43b5efa429fedbf932e98",
   "http_retry_tag": "0.1.1",
-  "http_rev": "1617b728fc48f64fb0ed7dc16078c03adcc64179",
+  "http_rev": "3845753a54624b070828cb3eff7a6c2a4e046cfb",
   "http_throttle_tag" : "1.0.2",
   "icu_rev" : "79326efe26e5440f530963704c3c0ff965b3a4ac",
   "idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
   "intl_tag": "0.17.0-nullsafety",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_rev": "b8dfe403fd8528fd14399dee3a6527b55802dd4d",
-  "linter_tag": "0.1.126",
+  "linter_tag": "0.1.129",
   "logging_rev": "e2f633b543ef89c54688554b15ca3d7e425b86a2",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_rev": "6f89681d59541ddb1cf3a58efbdaa2304ffc3f51",
-  "matcher_rev": "9cae8faa7868bf3a88a7ba45eb0bd128e66ac515",
-  "mime_rev": "07635f7774447503248fbc6afb3911e9000a477e",
+  "matcher_rev": "63f1110a657fb5e2dc378db8895fef7b0a13ab30",
+  "mime_rev": "c931f4bed87221beaece356494b43731445ce7b8",
   "mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
   "mustache_rev": "664737ecad027e6b96d0d1e627257efa0e46fcb1",
   "oauth2_tag": "1.6.0",
-  "package_config_rev": "9c586d04bd26fef01215fd10e7ab96a3050cfa64",
+  "package_config_rev": "0e208cb5a9482d780c47627368d3f5bdc409f37b",
   "path_rev": "62ecd5a78ffe5734d14ed0df76d20309084cd04a",
   "pedantic_rev": "a884ea2db943b8756cc94385990bd750aec06928",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
   "protobuf_rev": "0d03fd588df69e9863e2a2efc0059dee8f18d5b2",
-  "pub_rev": "228e69e53862879c283c42b98086aa7536012a66",
+  "pub_rev": "0e657414a472e74ca5dd76ae0db50cc060251dec",
   "pub_semver_rev": "10569a1e867e909cf5db201f73118020453e5db8",
   "resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
   "root_certificates_rev": "7e5ec82c99677a2e5b95ce296c4d68b0d3378ed8",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
-  "shelf_static_rev": "a6168f162df88b0eef7e328629bf020122d5039e",
+  "shelf_static_rev": "779a6e99b320ce9ed4ff6b88bd0cdc40ea5c62c4",
   "shelf_packages_handler_tag": "2.0.0",
   "shelf_proxy_tag": "0.1.0+7",
-  "shelf_rev": "5a77d25861db91db4343b19dfe213b8992e0a837",
-  "shelf_web_socket_rev": "8050a55b16faa5052a3e5d7dcdc170c59b6644f2",
+  "shelf_rev": "fa5afaa38bd51dedeeaa25b7bfd8822cabbcc57f",
+  "shelf_web_socket_rev": "abae6956e2f7d863a416c99aa031d7fa1a7160a7",
   "source_map_stack_trace_rev": "1c3026f69d9771acf2f8c176a1ab750463309cce",
   "source_maps-0.9.4_rev": "38524",
   "source_maps_rev": "53eb92ccfe6e64924054f83038a534b959b12b3e",
   "source_span_rev": "49ff31eabebed0da0ae6634124f8ba5c6fbf57f1",
   "sse_tag": "9a486d058a17e880afa9cc1c3c0dd8bad726bcbc",
   "stack_trace_tag": "6788afc61875079b71b3d1c3e65aeaa6a25cbc2f",
-  "stagehand_tag": "v3.3.11",
+  "stagehand_rev": "e64ac90cac508981011299c4ceb819149e71f1bd",
   "stream_channel_tag": "d7251e61253ec389ee6e045ee1042311bced8f1d",
   "string_scanner_rev": "1b63e6e5db5933d7be0a45da6e1129fe00262734",
-  "sync_http_rev": "a85d7ec764ea485cbbc49f3f3e7f1b43f87a1c74",
+  "sync_http_rev": "b59c134f2e34d12acac110d4f17f83e5a7db4330",
   "test_descriptor_tag": "1.1.1",
   "test_process_tag": "1.0.3",
   "term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347",
-  "test_reflective_loader_tag": "0.1.9",
+  "test_reflective_loader_rev": "b76ae201ab9c6f3b90643958965e7cc215a38e9b",
   "test_rev": "e37a93bbeae23b215972d1659ac865d71287ff6a",
   "typed_data_tag": "f94fc57b8e8c0e4fe4ff6cfd8290b94af52d3719",
-  "usage_tag": "16fbfd90c58f16e016a295a880bc722d2547d2c9",
+  "usage_rev": "6c64d9e7b6b3758d06d030efcb5afe20bfc04dde",
   "vector_math_rev": "0c9f5d68c047813a6dcdeb88ba7a42daddf25025",
-  "watcher_rev": "64e254eba16f56d41f10d72c0b1cb24e130e1f8b",
+  "watcher_rev": "14706140b3670ca1dfeca73480bdd3091b728ce9",
   "webdriver_rev": "5a8d6805d9cf8a3cbb4fcd64849b538b7491e50e",
   "web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
-  "web_socket_channel_rev": "490061ef0e22d3c8460ad2802f9948219365ad6b",
+  "web_socket_channel_rev": "680358915e331fda823908234f80beba1ed4ec83",
   "WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
   "yaml_rev": "cca02c9e4f6826d62644901ed65c6d72b90a0713",
   "zlib_rev": "c44fb7248079cc3d5563b14b3f758aee60d6b415",
@@ -421,7 +421,7 @@
   Var("dart_root") + "/third_party/pkg/stack_trace":
       Var("dart_git") + "stack_trace.git" + "@" + Var("stack_trace_tag"),
   Var("dart_root") + "/third_party/pkg/stagehand":
-      Var("dart_git") + "stagehand.git" + "@" + Var("stagehand_tag"),
+      Var("dart_git") + "stagehand.git" + "@" + Var("stagehand_rev"),
   Var("dart_root") + "/third_party/pkg/stream_channel":
       Var("dart_git") + "stream_channel.git" +
       "@" + Var("stream_channel_tag"),
@@ -440,11 +440,11 @@
       Var("dart_git") + "test_process.git" + "@" + Var("test_process_tag"),
   Var("dart_root") + "/third_party/pkg/test_reflective_loader":
       Var("dart_git") + "test_reflective_loader.git" +
-      "@" + Var("test_reflective_loader_tag"),
+      "@" + 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_root") + "/third_party/pkg/usage":
-      Var("dart_git") + "usage.git" + "@" + Var("usage_tag"),
+      Var("dart_git") + "usage.git" + "@" + Var("usage_rev"),
   Var("dart_root") + "/third_party/pkg/vector_math":
       Var("dart_git") + "external/github.com/google/vector_math.dart.git" +
       "@" + Var("vector_math_rev"),
@@ -565,7 +565,7 @@
     "packages": [
       {
       "package": "fuchsia/sdk/gn/linux-amd64",
-      "version": "git_revision:8d5242d4f6ff8b7634b492700e60b0fd09abefa3"
+      "version": "git_revision:e0a61431eb6e28d31d293cbb0c12f6b3a089bba4"
       }
     ],
     "condition": 'host_os == "linux" and host_cpu == "x64"',
diff --git a/README.md b/README.md
index 924e4c3..79cec90 100644
--- a/README.md
+++ b/README.md
@@ -5,13 +5,13 @@
 Dart is:
 
   * **Optimized for UI**:
-  Develop with a programming language specialized around the needs of user interface creation
+  Develop with a programming language specialized around the needs of user interface creation.
   
   * **Productive**:
-  Make changes iteratively: use hot reload to see the result instantly in your running app
+  Make changes iteratively: use hot reload to see the result instantly in your running app.
   
   * **Fast on all platforms**:
-  Compile to ARM & x64 machine code for mobile,  desktop, and backend. Or compile to JavaScript for the web
+  Compile to ARM & x64 machine code for mobile, desktop, and backend. Or compile to JavaScript for the web.
 
 Dart's flexible compiler technology lets you run Dart code in different ways,
 depending on your target platform and goals:
@@ -34,12 +34,17 @@
 ## Using Dart
 
 Visit [dart.dev][website] to learn more about the
-[language][lang], [tools][tools],
-[getting started][codelab], and more.
+[language][lang], [tools][tools], and to find
+[codelabs][codelabs].
 
 Browse [pub.dev][pubsite] for more packages and libraries contributed
 by the community and the Dart team.
 
+Our API reference documentation is published at [api.dart.dev](https://api.dart.dev),
+based on the stable release. (We also publish docs from our 
+[beta](https://api.dart.dev/beta) and [dev](https://api.dart.dev/dev) channels,
+as well as from the [primary development branch](https://api.dart.dev/be)).
+
 ## Building Dart
 
 If you want to build Dart yourself, here is a guide to
@@ -59,7 +64,7 @@
 [repo]: https://github.com/dart-lang/sdk
 [lang]: https://dart.dev/guides/language/language-tour
 [tools]: https://dart.dev/tools
-[codelab]: https://dart.dev/codelabs
+[codelabs]: https://dart.dev/codelabs
 [dartbug]: http://dartbug.com
 [contrib]: https://github.com/dart-lang/sdk/blob/master/CONTRIBUTING.md
 [pubsite]: https://pub.dev
diff --git a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
index f9e05e7..b3d40c0 100644
--- a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
@@ -31,29 +31,43 @@
 // integers.
 const requiredDigits = 11106;
 
-class ParseBigIntBenchmark extends BenchmarkBase {
-  final int bits;
-  final BigInt seed;
-  final List<String> strings = [];
-
-  ParseBigIntBenchmark(String name, this.bits)
-      : seed = (BigInt.one << bits) - BigInt.one,
+class Benchmark extends BenchmarkBase {
+  final List<String> strings;
+  Benchmark(String name, int bits, {bool forInt = false})
+      : strings = generateStrings(bits, forInt),
         super(name);
 
-  @override
-  void setup() {
+  static List<String> generateStrings(int bits, bool forInt) {
+    final List<String> strings = [];
+    final BigInt seed = (BigInt.one << bits) - BigInt.one;
     var b = seed;
+    var restartDelta = BigInt.zero;
     var totalLength = 0;
     while (totalLength < requiredDigits) {
       if (b.bitLength < bits) {
-        b = seed;
+        restartDelta += seed >> 20;
+        restartDelta += BigInt.one;
+        // Restart from a slighly reduced seed to generate different numbers.
+        b = seed - restartDelta;
       }
-      final string = b.toString();
+      var string = b.toString();
+
+      // Web integers lose precision due to rounding for larger values. Make
+      // sure the string will round-trip correctly.
+      if (forInt) string = int.parse(string).toString();
+
       strings.add(string);
       totalLength += string.length;
-      b = b - (b >> 8);
+      var delta = b >> 8;
+      if (delta == BigInt.zero) delta = BigInt.one;
+      b = b - delta;
     }
+    return strings;
   }
+}
+
+class ParseBigIntBenchmark extends Benchmark {
+  ParseBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -66,31 +80,8 @@
   }
 }
 
-int int64UnsignedBitLength(Int64 i) => i.isNegative ? 64 : i.bitLength;
-
-class ParseInt64Benchmark extends BenchmarkBase {
-  final int bits;
-  final Int64 seed;
-  final List<String> strings = [];
-
-  ParseInt64Benchmark(String name, this.bits)
-      : seed = (Int64.ONE << bits) - Int64.ONE,
-        super(name);
-
-  @override
-  void setup() {
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (int64UnsignedBitLength(b) < bits) {
-        b = seed;
-      }
-      final string = b.toStringUnsigned();
-      strings.add(string);
-      totalLength += string.length;
-      b = b - b.shiftRightUnsigned(8);
-    }
-  }
+class ParseInt64Benchmark extends Benchmark {
+  ParseInt64Benchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -103,33 +94,22 @@
   }
 }
 
-class ParseJsBigIntBenchmark extends BenchmarkBase {
-  final int bits;
-  final Object seed;
-  final List<String> strings = [];
-
-  ParseJsBigIntBenchmark(String name, this.bits)
-      : seed = nativeBigInt.subtract(
-            nativeBigInt.shiftLeft(
-                nativeBigInt.one, nativeBigInt.fromInt(bits)),
-            nativeBigInt.one),
-        super(name);
+class ParseIntBenchmark extends Benchmark {
+  ParseIntBenchmark(String name, int bits) : super(name, bits, forInt: true);
 
   @override
-  void setup() {
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (nativeBigInt.bitLength(b) < bits) {
-        b = seed;
-      }
-      final string = nativeBigInt.toStringMethod(b);
-      strings.add(string);
-      totalLength += string.length;
-      b = nativeBigInt.subtract(
-          b, nativeBigInt.shiftRight(b, nativeBigInt.eight));
+  void run() {
+    for (final s in strings) {
+      final b = int.parse(s);
+      sink1 = s;
+      sink2 = b;
     }
+    check(sink2.isEven);
   }
+}
+
+class ParseJsBigIntBenchmark extends Benchmark {
+  ParseJsBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -142,27 +122,16 @@
   }
 }
 
-class FormatBigIntBenchmark extends BenchmarkBase {
-  final int bits;
-  final BigInt seed;
+class FormatBigIntBenchmark extends Benchmark {
   final List<BigInt> values = [];
 
-  FormatBigIntBenchmark(String name, this.bits)
-      : seed = (BigInt.one << bits) - BigInt.one,
-        super(name);
+  FormatBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void setup() {
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (b.bitLength < bits) {
-        b = seed;
-      }
-      final string = b.toString();
+    for (String s in strings) {
+      final BigInt b = BigInt.parse(s);
       values.add(b - BigInt.one); // We add 'one' back later.
-      totalLength += string.length;
-      b = b - (b >> 8);
     }
   }
 
@@ -181,27 +150,45 @@
   }
 }
 
-class FormatInt64Benchmark extends BenchmarkBase {
-  final int bits;
-  final Int64 seed;
-  final List<Int64> values = [];
+class FormatIntBenchmark extends Benchmark {
+  final List<int> values = [];
 
-  FormatInt64Benchmark(String name, this.bits)
-      : seed = (Int64.ONE << bits) - Int64.ONE,
-        super(name);
+  FormatIntBenchmark(String name, int bits) : super(name, bits, forInt: true);
 
   @override
   void setup() {
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (int64UnsignedBitLength(b) < bits) {
-        b = seed;
-      }
-      final string = b.toStringUnsigned();
-      values.add(b - Int64.ONE);
-      totalLength += string.length;
-      b = b - b.shiftRightUnsigned(8);
+    for (String s in strings) {
+      final int b = int.parse(s);
+      values.add(b - 4096); // We add this back later.
+    }
+  }
+
+  @override
+  void run() {
+    for (final b0 in values) {
+      // Instances might cache `toString()`, so use arithmetic to create a new
+      // instance to try to protect against measuring a cached string.  We use
+      // 4096 to avoid the arithmetic being a no-op due to rounding on web
+      // integers (i.e. doubles).
+      final b = b0 + 4096;
+      final s = b.toString();
+      sink1 = s;
+      sink2 = b;
+    }
+    check(sink2.isEven);
+  }
+}
+
+class FormatInt64Benchmark extends Benchmark {
+  final List<Int64> values = [];
+
+  FormatInt64Benchmark(String name, int bits) : super(name, bits);
+
+  @override
+  void setup() {
+    for (String s in strings) {
+      final b = Int64.parseInt(s);
+      values.add(b - Int64.ONE); // We add this back later.
     }
   }
 
@@ -220,32 +207,17 @@
   }
 }
 
-class FormatJsBigIntBenchmark extends BenchmarkBase {
-  final int bits;
-  final Object seed;
+class FormatJsBigIntBenchmark extends Benchmark {
   final List<Object> values = [];
 
-  FormatJsBigIntBenchmark(String name, this.bits)
-      : seed = nativeBigInt.subtract(
-            nativeBigInt.shiftLeft(
-                nativeBigInt.one, nativeBigInt.fromInt(bits)),
-            nativeBigInt.one),
-        super(name);
+  FormatJsBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void setup() {
     final one = nativeBigInt.one;
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (nativeBigInt.bitLength(b) < bits) {
-        b = seed;
-      }
-      final string = nativeBigInt.toStringMethod(b);
-      values.add(nativeBigInt.subtract(b, one)); // We add 'one' back later.
-      totalLength += string.length;
-      b = nativeBigInt.subtract(
-          b, nativeBigInt.shiftRight(b, nativeBigInt.eight));
+    for (String s in strings) {
+      final b = nativeBigInt.parse(s);
+      values.add(nativeBigInt.subtract(b, one)); // We add this back later.
     }
   }
 
@@ -293,6 +265,12 @@
 
 void main() {
   final benchmarks = [
+    () => ParseIntBenchmark('Int.parse.0009.bits', 9),
+    () => ParseIntBenchmark('Int.parse.0032.bits', 32),
+    // Use '63' bits to avoid 64-bit arithmetic overflowing to negative. Keep
+    // the name as '64' to help comparisons.  The effect of an incorrect number
+    // is reduced since benchmark results are normalized to a 'per digit' score
+    () => ParseIntBenchmark('Int.parse.0064.bits', 63),
     () => ParseInt64Benchmark('Int64.parse.0009.bits', 9),
     () => ParseInt64Benchmark('Int64.parse.0032.bits', 32),
     () => ParseInt64Benchmark('Int64.parse.0064.bits', 64),
@@ -308,6 +286,9 @@
     selectParseNativeBigIntBenchmark('JsBigInt.parse.0256.bits', 256),
     selectParseNativeBigIntBenchmark('JsBigInt.parse.1024.bits', 1024),
     selectParseNativeBigIntBenchmark('JsBigInt.parse.4096.bits', 4096),
+    () => FormatIntBenchmark('Int.toString.0009.bits', 9),
+    () => FormatIntBenchmark('Int.toString.0032.bits', 32),
+    () => FormatIntBenchmark('Int.toString.0064.bits', 63), // '63': See above.
     () => FormatInt64Benchmark('Int64.toString.0009.bits', 9),
     () => FormatInt64Benchmark('Int64.toString.0032.bits', 32),
     () => FormatInt64Benchmark('Int64.toString.0064.bits', 64),
diff --git a/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
index 26a796f..db19b68 100644
--- a/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
@@ -33,29 +33,43 @@
 // integers.
 const requiredDigits = 11106;
 
-class ParseBigIntBenchmark extends BenchmarkBase {
-  final int bits;
-  final BigInt seed;
-  final List<String> strings = [];
-
-  ParseBigIntBenchmark(String name, this.bits)
-      : seed = (BigInt.one << bits) - BigInt.one,
+class Benchmark extends BenchmarkBase {
+  final List<String> strings;
+  Benchmark(String name, int bits, {bool forInt = false})
+      : strings = generateStrings(bits, forInt),
         super(name);
 
-  @override
-  void setup() {
+  static List<String> generateStrings(int bits, bool forInt) {
+    final List<String> strings = [];
+    final BigInt seed = (BigInt.one << bits) - BigInt.one;
     var b = seed;
+    var restartDelta = BigInt.zero;
     var totalLength = 0;
     while (totalLength < requiredDigits) {
       if (b.bitLength < bits) {
-        b = seed;
+        restartDelta += seed >> 20;
+        restartDelta += BigInt.one;
+        // Restart from a slighly reduced seed to generate different numbers.
+        b = seed - restartDelta;
       }
-      final string = b.toString();
+      var string = b.toString();
+
+      // Web integers lose precision due to rounding for larger values. Make
+      // sure the string will round-trip correctly.
+      if (forInt) string = int.parse(string).toString();
+
       strings.add(string);
       totalLength += string.length;
-      b = b - (b >> 8);
+      var delta = b >> 8;
+      if (delta == BigInt.zero) delta = BigInt.one;
+      b = b - delta;
     }
+    return strings;
   }
+}
+
+class ParseBigIntBenchmark extends Benchmark {
+  ParseBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -68,31 +82,8 @@
   }
 }
 
-int int64UnsignedBitLength(Int64 i) => i.isNegative ? 64 : i.bitLength;
-
-class ParseInt64Benchmark extends BenchmarkBase {
-  final int bits;
-  final Int64 seed;
-  final List<String> strings = [];
-
-  ParseInt64Benchmark(String name, this.bits)
-      : seed = (Int64.ONE << bits) - Int64.ONE,
-        super(name);
-
-  @override
-  void setup() {
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (int64UnsignedBitLength(b) < bits) {
-        b = seed;
-      }
-      final string = b.toStringUnsigned();
-      strings.add(string);
-      totalLength += string.length;
-      b = b - b.shiftRightUnsigned(8);
-    }
-  }
+class ParseInt64Benchmark extends Benchmark {
+  ParseInt64Benchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -105,33 +96,22 @@
   }
 }
 
-class ParseJsBigIntBenchmark extends BenchmarkBase {
-  final int bits;
-  final Object seed;
-  final List<String> strings = [];
-
-  ParseJsBigIntBenchmark(String name, this.bits)
-      : seed = nativeBigInt.subtract(
-            nativeBigInt.shiftLeft(
-                nativeBigInt.one, nativeBigInt.fromInt(bits)),
-            nativeBigInt.one),
-        super(name);
+class ParseIntBenchmark extends Benchmark {
+  ParseIntBenchmark(String name, int bits) : super(name, bits, forInt: true);
 
   @override
-  void setup() {
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (nativeBigInt.bitLength(b) < bits) {
-        b = seed;
-      }
-      final string = nativeBigInt.toStringMethod(b);
-      strings.add(string);
-      totalLength += string.length;
-      b = nativeBigInt.subtract(
-          b, nativeBigInt.shiftRight(b, nativeBigInt.eight));
+  void run() {
+    for (final s in strings) {
+      final b = int.parse(s);
+      sink1 = s;
+      sink2 = b;
     }
+    check(sink2.isEven);
   }
+}
+
+class ParseJsBigIntBenchmark extends Benchmark {
+  ParseJsBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -144,27 +124,16 @@
   }
 }
 
-class FormatBigIntBenchmark extends BenchmarkBase {
-  final int bits;
-  final BigInt seed;
+class FormatBigIntBenchmark extends Benchmark {
   final List<BigInt> values = [];
 
-  FormatBigIntBenchmark(String name, this.bits)
-      : seed = (BigInt.one << bits) - BigInt.one,
-        super(name);
+  FormatBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void setup() {
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (b.bitLength < bits) {
-        b = seed;
-      }
-      final string = b.toString();
+    for (String s in strings) {
+      final BigInt b = BigInt.parse(s);
       values.add(b - BigInt.one); // We add 'one' back later.
-      totalLength += string.length;
-      b = b - (b >> 8);
     }
   }
 
@@ -183,27 +152,45 @@
   }
 }
 
-class FormatInt64Benchmark extends BenchmarkBase {
-  final int bits;
-  final Int64 seed;
-  final List<Int64> values = [];
+class FormatIntBenchmark extends Benchmark {
+  final List<int> values = [];
 
-  FormatInt64Benchmark(String name, this.bits)
-      : seed = (Int64.ONE << bits) - Int64.ONE,
-        super(name);
+  FormatIntBenchmark(String name, int bits) : super(name, bits, forInt: true);
 
   @override
   void setup() {
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (int64UnsignedBitLength(b) < bits) {
-        b = seed;
-      }
-      final string = b.toStringUnsigned();
-      values.add(b - Int64.ONE);
-      totalLength += string.length;
-      b = b - b.shiftRightUnsigned(8);
+    for (String s in strings) {
+      final int b = int.parse(s);
+      values.add(b - 4096); // We add this back later.
+    }
+  }
+
+  @override
+  void run() {
+    for (final b0 in values) {
+      // Instances might cache `toString()`, so use arithmetic to create a new
+      // instance to try to protect against measuring a cached string.  We use
+      // 4096 to avoid the arithmetic being a no-op due to rounding on web
+      // integers (i.e. doubles).
+      final b = b0 + 4096;
+      final s = b.toString();
+      sink1 = s;
+      sink2 = b;
+    }
+    check(sink2.isEven);
+  }
+}
+
+class FormatInt64Benchmark extends Benchmark {
+  final List<Int64> values = [];
+
+  FormatInt64Benchmark(String name, int bits) : super(name, bits);
+
+  @override
+  void setup() {
+    for (String s in strings) {
+      final b = Int64.parseInt(s);
+      values.add(b - Int64.ONE); // We add this back later.
     }
   }
 
@@ -222,32 +209,17 @@
   }
 }
 
-class FormatJsBigIntBenchmark extends BenchmarkBase {
-  final int bits;
-  final Object seed;
+class FormatJsBigIntBenchmark extends Benchmark {
   final List<Object> values = [];
 
-  FormatJsBigIntBenchmark(String name, this.bits)
-      : seed = nativeBigInt.subtract(
-            nativeBigInt.shiftLeft(
-                nativeBigInt.one, nativeBigInt.fromInt(bits)),
-            nativeBigInt.one),
-        super(name);
+  FormatJsBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void setup() {
     final one = nativeBigInt.one;
-    var b = seed;
-    var totalLength = 0;
-    while (totalLength < requiredDigits) {
-      if (nativeBigInt.bitLength(b) < bits) {
-        b = seed;
-      }
-      final string = nativeBigInt.toStringMethod(b);
-      values.add(nativeBigInt.subtract(b, one)); // We add 'one' back later.
-      totalLength += string.length;
-      b = nativeBigInt.subtract(
-          b, nativeBigInt.shiftRight(b, nativeBigInt.eight));
+    for (String s in strings) {
+      final b = nativeBigInt.parse(s);
+      values.add(nativeBigInt.subtract(b, one)); // We add this back later.
     }
   }
 
@@ -295,6 +267,12 @@
 
 void main() {
   final benchmarks = [
+    () => ParseIntBenchmark('Int.parse.0009.bits', 9),
+    () => ParseIntBenchmark('Int.parse.0032.bits', 32),
+    // Use '63' bits to avoid 64-bit arithmetic overflowing to negative. Keep
+    // the name as '64' to help comparisons.  The effect of an incorrect number
+    // is reduced since benchmark results are normalized to a 'per digit' score
+    () => ParseIntBenchmark('Int.parse.0064.bits', 63),
     () => ParseInt64Benchmark('Int64.parse.0009.bits', 9),
     () => ParseInt64Benchmark('Int64.parse.0032.bits', 32),
     () => ParseInt64Benchmark('Int64.parse.0064.bits', 64),
@@ -310,6 +288,9 @@
     selectParseNativeBigIntBenchmark('JsBigInt.parse.0256.bits', 256),
     selectParseNativeBigIntBenchmark('JsBigInt.parse.1024.bits', 1024),
     selectParseNativeBigIntBenchmark('JsBigInt.parse.4096.bits', 4096),
+    () => FormatIntBenchmark('Int.toString.0009.bits', 9),
+    () => FormatIntBenchmark('Int.toString.0032.bits', 32),
+    () => FormatIntBenchmark('Int.toString.0064.bits', 63), // '63': See above.
     () => FormatInt64Benchmark('Int64.toString.0009.bits', 9),
     () => FormatInt64Benchmark('Int64.toString.0032.bits', 32),
     () => FormatInt64Benchmark('Int64.toString.0064.bits', 64),
diff --git a/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart b/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart
index 7025194..3249be4 100644
--- a/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart
+++ b/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart
@@ -11,6 +11,7 @@
 import 'package:benchmark_harness/benchmark_harness.dart';
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
 import 'digest.dart';
 import 'types.dart';
 
@@ -26,7 +27,7 @@
   return result;
 }
 
-Uint8List toUint8List(Bytes bytes, int length) {
+Uint8List toUint8List(Pointer<Bytes> bytes, int length) {
   final result = Uint8List(length);
   final uint8bytes = bytes.asUint8Pointer();
   for (int i = 0; i < length; i++) {
@@ -35,7 +36,7 @@
   return result;
 }
 
-void copyFromUint8ListToTarget(Uint8List source, Data target) {
+void copyFromUint8ListToTarget(Uint8List source, Pointer<Data> target) {
   final int length = source.length;
   final uint8target = target.asUint8Pointer();
   for (int i = 0; i < length; i++) {
@@ -48,11 +49,11 @@
   EVP_DigestInit(context, hashAlgorithm);
   EVP_DigestUpdate(context, data, length);
   final int resultSize = EVP_MD_CTX_size(context);
-  final Pointer<Bytes> result = allocate<Uint8>(count: resultSize).cast();
+  final Pointer<Bytes> result = calloc<Uint8>(resultSize).cast();
   EVP_DigestFinal(context, result, nullptr);
   EVP_MD_CTX_free(context);
-  final String hash = base64Encode(toUint8List(result.ref, resultSize));
-  free(result);
+  final String hash = base64Encode(toUint8List(result, resultSize));
+  calloc.free(result);
   return hash;
 }
 
@@ -83,14 +84,14 @@
 
   @override
   void setup() {
-    data = allocate<Uint8>(count: L).cast();
-    copyFromUint8ListToTarget(inventData(L), data.ref);
+    data = calloc<Uint8>(L).cast();
+    copyFromUint8ListToTarget(inventData(L), data);
     hash(data, L, hashAlgorithm);
   }
 
   @override
   void teardown() {
-    free(data);
+    calloc.free(data);
   }
 
   @override
@@ -113,10 +114,10 @@
   @override
   void setup() {
     data = inventData(L);
-    final Pointer<Data> dataInC = allocate<Uint8>(count: L).cast();
-    copyFromUint8ListToTarget(data, dataInC.ref);
+    final Pointer<Data> dataInC = calloc<Uint8>(L).cast();
+    copyFromUint8ListToTarget(data, dataInC);
     hash(dataInC, L, hashAlgorithm);
-    free(dataInC);
+    calloc.free(dataInC);
   }
 
   @override
@@ -124,10 +125,10 @@
 
   @override
   void run() {
-    final Pointer<Data> dataInC = allocate<Uint8>(count: L).cast();
-    copyFromUint8ListToTarget(data, dataInC.ref);
+    final Pointer<Data> dataInC = calloc<Uint8>(L).cast();
+    copyFromUint8ListToTarget(data, dataInC);
     final String result = hash(dataInC, L, hashAlgorithm);
-    free(dataInC);
+    calloc.free(dataInC);
     if (result != expectedHash) {
       throw Exception('$name: Unexpected result: $result');
     }
diff --git a/benchmarks/FfiBoringssl/dart/calloc.dart b/benchmarks/FfiBoringssl/dart/calloc.dart
new file mode 100644
index 0000000..e17238a
--- /dev/null
+++ b/benchmarks/FfiBoringssl/dart/calloc.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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/benchmarks/FfiBoringssl/dart/types.dart b/benchmarks/FfiBoringssl/dart/types.dart
index 2dd5f76..972555e 100644
--- a/benchmarks/FfiBoringssl/dart/types.dart
+++ b/benchmarks/FfiBoringssl/dart/types.dart
@@ -7,21 +7,25 @@
 import 'dart:ffi';
 
 /// digest algorithm.
-class EVP_MD extends Struct {}
+class EVP_MD extends Opaque {}
 
 /// digest context.
-class EVP_MD_CTX extends Struct {}
+class EVP_MD_CTX extends Opaque {}
 
 /// Type for `void*` used to represent opaque data.
-class Data extends Struct {
-  static Data fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>().ref;
+class Data extends Opaque {
+  static Pointer<Data> fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>();
+}
 
-  Pointer<Uint8> asUint8Pointer() => addressOf.cast();
+extension DataPointerAsUint8Pointer on Pointer<Data> {
+  Pointer<Uint8> asUint8Pointer() => cast();
 }
 
 /// Type for `uint8_t*` used to represent byte data.
-class Bytes extends Struct {
-  static Data fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>().ref;
+class Bytes extends Opaque {
+  static Pointer<Data> fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>();
+}
 
-  Pointer<Uint8> asUint8Pointer() => addressOf.cast();
+extension BytesPointerAsUint8Pointer on Pointer<Bytes> {
+  Pointer<Uint8> asUint8Pointer() => cast();
 }
diff --git a/benchmarks/FfiBoringssl/dart2/FfiBoringssl.dart b/benchmarks/FfiBoringssl/dart2/FfiBoringssl.dart
index 7db1f91..c749745 100644
--- a/benchmarks/FfiBoringssl/dart2/FfiBoringssl.dart
+++ b/benchmarks/FfiBoringssl/dart2/FfiBoringssl.dart
@@ -13,6 +13,7 @@
 import 'package:benchmark_harness/benchmark_harness.dart';
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
 import 'digest.dart';
 import 'types.dart';
 
@@ -28,7 +29,7 @@
   return result;
 }
 
-Uint8List toUint8List(Bytes bytes, int length) {
+Uint8List toUint8List(Pointer<Bytes> bytes, int length) {
   final result = Uint8List(length);
   final uint8bytes = bytes.asUint8Pointer();
   for (int i = 0; i < length; i++) {
@@ -37,7 +38,7 @@
   return result;
 }
 
-void copyFromUint8ListToTarget(Uint8List source, Data target) {
+void copyFromUint8ListToTarget(Uint8List source, Pointer<Data> target) {
   final int length = source.length;
   final uint8target = target.asUint8Pointer();
   for (int i = 0; i < length; i++) {
@@ -50,11 +51,11 @@
   EVP_DigestInit(context, hashAlgorithm);
   EVP_DigestUpdate(context, data, length);
   final int resultSize = EVP_MD_CTX_size(context);
-  final Pointer<Bytes> result = allocate<Uint8>(count: resultSize).cast();
+  final Pointer<Bytes> result = calloc<Uint8>(resultSize).cast();
   EVP_DigestFinal(context, result, nullptr);
   EVP_MD_CTX_free(context);
-  final String hash = base64Encode(toUint8List(result.ref, resultSize));
-  free(result);
+  final String hash = base64Encode(toUint8List(result, resultSize));
+  calloc.free(result);
   return hash;
 }
 
@@ -85,14 +86,14 @@
 
   @override
   void setup() {
-    data = allocate<Uint8>(count: L).cast();
-    copyFromUint8ListToTarget(inventData(L), data.ref);
+    data = calloc<Uint8>(L).cast();
+    copyFromUint8ListToTarget(inventData(L), data);
     hash(data, L, hashAlgorithm);
   }
 
   @override
   void teardown() {
-    free(data);
+    calloc.free(data);
   }
 
   @override
@@ -115,10 +116,10 @@
   @override
   void setup() {
     data = inventData(L);
-    final Pointer<Data> dataInC = allocate<Uint8>(count: L).cast();
-    copyFromUint8ListToTarget(data, dataInC.ref);
+    final Pointer<Data> dataInC = calloc<Uint8>(L).cast();
+    copyFromUint8ListToTarget(data, dataInC);
     hash(dataInC, L, hashAlgorithm);
-    free(dataInC);
+    calloc.free(dataInC);
   }
 
   @override
@@ -126,10 +127,10 @@
 
   @override
   void run() {
-    final Pointer<Data> dataInC = allocate<Uint8>(count: L).cast();
-    copyFromUint8ListToTarget(data, dataInC.ref);
+    final Pointer<Data> dataInC = calloc<Uint8>(L).cast();
+    copyFromUint8ListToTarget(data, dataInC);
     final String result = hash(dataInC, L, hashAlgorithm);
-    free(dataInC);
+    calloc.free(dataInC);
     if (result != expectedHash) {
       throw Exception('$name: Unexpected result: $result');
     }
diff --git a/benchmarks/FfiBoringssl/dart2/calloc.dart b/benchmarks/FfiBoringssl/dart2/calloc.dart
new file mode 100644
index 0000000..c6be280
--- /dev/null
+++ b/benchmarks/FfiBoringssl/dart2/calloc.dart
@@ -0,0 +1,111 @@
+// 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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+// @dart=2.9
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/benchmarks/FfiBoringssl/dart2/types.dart b/benchmarks/FfiBoringssl/dart2/types.dart
index 2c1923b..5ceb6a9 100644
--- a/benchmarks/FfiBoringssl/dart2/types.dart
+++ b/benchmarks/FfiBoringssl/dart2/types.dart
@@ -9,21 +9,25 @@
 import 'dart:ffi';
 
 /// digest algorithm.
-class EVP_MD extends Struct {}
+class EVP_MD extends Opaque {}
 
 /// digest context.
-class EVP_MD_CTX extends Struct {}
+class EVP_MD_CTX extends Opaque {}
 
 /// Type for `void*` used to represent opaque data.
-class Data extends Struct {
-  static Data fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>().ref;
+class Data extends Opaque {
+  static Pointer<Data> fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>();
+}
 
-  Pointer<Uint8> asUint8Pointer() => addressOf.cast();
+extension DataPointerAsUint8Pointer on Pointer<Data> {
+  Pointer<Uint8> asUint8Pointer() => cast();
 }
 
 /// Type for `uint8_t*` used to represent byte data.
-class Bytes extends Struct {
-  static Data fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>().ref;
+class Bytes extends Opaque {
+  static Pointer<Data> fromUint8Pointer(Pointer<Uint8> p) => p.cast<Data>();
+}
 
-  Pointer<Uint8> asUint8Pointer() => addressOf.cast();
+extension BytesPointerAsUint8Pointer on Pointer<Bytes> {
+  Pointer<Uint8> asUint8Pointer() => cast();
 }
diff --git a/benchmarks/FfiCall/dart/FfiCall.dart b/benchmarks/FfiCall/dart/FfiCall.dart
index c2392a1..d33e120 100644
--- a/benchmarks/FfiCall/dart/FfiCall.dart
+++ b/benchmarks/FfiCall/dart/FfiCall.dart
@@ -13,6 +13,7 @@
 import 'package:ffi/ffi.dart';
 import 'package:benchmark_harness/benchmark_harness.dart';
 
+import 'calloc.dart';
 import 'dlopen_helper.dart';
 
 //
@@ -1070,9 +1071,9 @@
 
   Pointer<Uint8> pointer = nullptr;
   @override
-  void setup() => pointer = allocate(count: N + 1);
+  void setup() => pointer = calloc(N + 1);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -1091,13 +1092,13 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N + 1);
+    pointer = calloc(N + 1);
     pointer2 = pointer.elementAt(1);
   }
 
   @override
   void teardown() {
-    free(pointer);
+    calloc.free(pointer);
   }
 
   @override
@@ -1119,7 +1120,7 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N + 1);
+    pointer = calloc(N + 1);
     pointer2 = pointer.elementAt(1);
     pointer3 = pointer.elementAt(2);
     pointer4 = pointer.elementAt(3);
@@ -1127,7 +1128,7 @@
 
   @override
   void teardown() {
-    free(pointer);
+    calloc.free(pointer);
   }
 
   @override
@@ -1156,7 +1157,7 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N + 1);
+    pointer = calloc(N + 1);
     pointer2 = pointer.elementAt(1);
     pointer3 = pointer.elementAt(2);
     pointer4 = pointer.elementAt(3);
@@ -1170,7 +1171,7 @@
 
   @override
   void teardown() {
-    free(pointer);
+    calloc.free(pointer);
   }
 
   @override
@@ -1219,7 +1220,7 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N + 1);
+    pointer = calloc(N + 1);
     pointer2 = pointer.elementAt(1);
     pointer3 = pointer.elementAt(2);
     pointer4 = pointer.elementAt(3);
@@ -1243,7 +1244,7 @@
 
   @override
   void teardown() {
-    free(pointer);
+    calloc.free(pointer);
   }
 
   @override
diff --git a/benchmarks/FfiCall/dart/calloc.dart b/benchmarks/FfiCall/dart/calloc.dart
new file mode 100644
index 0000000..e17238a
--- /dev/null
+++ b/benchmarks/FfiCall/dart/calloc.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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/benchmarks/FfiCall/dart2/FfiCall.dart b/benchmarks/FfiCall/dart2/FfiCall.dart
index fa67dce..3da29b4 100644
--- a/benchmarks/FfiCall/dart2/FfiCall.dart
+++ b/benchmarks/FfiCall/dart2/FfiCall.dart
@@ -15,6 +15,7 @@
 import 'package:ffi/ffi.dart';
 import 'package:benchmark_harness/benchmark_harness.dart';
 
+import 'calloc.dart';
 import 'dlopen_helper.dart';
 
 //
@@ -1072,9 +1073,9 @@
 
   Pointer<Uint8> pointer;
   @override
-  void setup() => pointer = allocate(count: N + 1);
+  void setup() => pointer = calloc(N + 1);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -1092,13 +1093,13 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N + 1);
+    pointer = calloc(N + 1);
     pointer2 = pointer.elementAt(1);
   }
 
   @override
   void teardown() {
-    free(pointer);
+    calloc.free(pointer);
   }
 
   @override
@@ -1117,7 +1118,7 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N + 1);
+    pointer = calloc(N + 1);
     pointer2 = pointer.elementAt(1);
     pointer3 = pointer.elementAt(2);
     pointer4 = pointer.elementAt(3);
@@ -1125,7 +1126,7 @@
 
   @override
   void teardown() {
-    free(pointer);
+    calloc.free(pointer);
   }
 
   @override
@@ -1154,7 +1155,7 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N + 1);
+    pointer = calloc(N + 1);
     pointer2 = pointer.elementAt(1);
     pointer3 = pointer.elementAt(2);
     pointer4 = pointer.elementAt(3);
@@ -1168,7 +1169,7 @@
 
   @override
   void teardown() {
-    free(pointer);
+    calloc.free(pointer);
   }
 
   @override
@@ -1217,7 +1218,7 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N + 1);
+    pointer = calloc(N + 1);
     pointer2 = pointer.elementAt(1);
     pointer3 = pointer.elementAt(2);
     pointer4 = pointer.elementAt(3);
@@ -1241,7 +1242,7 @@
 
   @override
   void teardown() {
-    free(pointer);
+    calloc.free(pointer);
   }
 
   @override
diff --git a/benchmarks/FfiCall/dart2/calloc.dart b/benchmarks/FfiCall/dart2/calloc.dart
new file mode 100644
index 0000000..c6be280
--- /dev/null
+++ b/benchmarks/FfiCall/dart2/calloc.dart
@@ -0,0 +1,111 @@
+// 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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+// @dart=2.9
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/benchmarks/FfiMemory/dart/FfiMemory.dart b/benchmarks/FfiMemory/dart/FfiMemory.dart
index d9ee487..423fa74 100644
--- a/benchmarks/FfiMemory/dart/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart/FfiMemory.dart
@@ -14,6 +14,8 @@
 import 'package:ffi/ffi.dart';
 import 'package:benchmark_harness/benchmark_harness.dart';
 
+import 'calloc.dart';
+
 //
 // Pointer store.
 //
@@ -210,9 +212,9 @@
   PointerInt8() : super('FfiMemory.PointerInt8');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -229,9 +231,9 @@
   PointerUint8() : super('FfiMemory.PointerUint8');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -248,9 +250,9 @@
   PointerInt16() : super('FfiMemory.PointerInt16');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -267,9 +269,9 @@
   PointerUint16() : super('FfiMemory.PointerUint16');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -286,9 +288,9 @@
   PointerInt32() : super('FfiMemory.PointerInt32');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -305,9 +307,9 @@
   PointerUint32() : super('FfiMemory.PointerUint32');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -324,9 +326,9 @@
   PointerInt64() : super('FfiMemory.PointerInt64');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -343,9 +345,9 @@
   PointerUint64() : super('FfiMemory.PointerUint64');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -362,9 +364,9 @@
   PointerFloat() : super('FfiMemory.PointerFloat');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -381,9 +383,9 @@
   PointerDouble() : super('FfiMemory.PointerDouble');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -402,14 +404,14 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N);
-    data = allocate();
+    pointer = calloc(N);
+    data = calloc();
   }
 
   @override
   void teardown() {
-    free(pointer);
-    free(data);
+    calloc.free(pointer);
+    calloc.free(data);
   }
 
   @override
@@ -427,9 +429,9 @@
   PointerInt64Mint() : super('FfiMemory.PointerInt64Mint');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
diff --git a/benchmarks/FfiMemory/dart/calloc.dart b/benchmarks/FfiMemory/dart/calloc.dart
new file mode 100644
index 0000000..e17238a
--- /dev/null
+++ b/benchmarks/FfiMemory/dart/calloc.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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/benchmarks/FfiMemory/dart2/FfiMemory.dart b/benchmarks/FfiMemory/dart2/FfiMemory.dart
index 11fbea2..d8d41e2 100644
--- a/benchmarks/FfiMemory/dart2/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart2/FfiMemory.dart
@@ -16,6 +16,8 @@
 import 'package:ffi/ffi.dart';
 import 'package:benchmark_harness/benchmark_harness.dart';
 
+import 'calloc.dart';
+
 //
 // Pointer store.
 //
@@ -212,9 +214,9 @@
   PointerInt8() : super('FfiMemory.PointerInt8');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -231,9 +233,9 @@
   PointerUint8() : super('FfiMemory.PointerUint8');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -250,9 +252,9 @@
   PointerInt16() : super('FfiMemory.PointerInt16');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -269,9 +271,9 @@
   PointerUint16() : super('FfiMemory.PointerUint16');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -288,9 +290,9 @@
   PointerInt32() : super('FfiMemory.PointerInt32');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -307,9 +309,9 @@
   PointerUint32() : super('FfiMemory.PointerUint32');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -326,9 +328,9 @@
   PointerInt64() : super('FfiMemory.PointerInt64');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -345,9 +347,9 @@
   PointerUint64() : super('FfiMemory.PointerUint64');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -364,9 +366,9 @@
   PointerFloat() : super('FfiMemory.PointerFloat');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -383,9 +385,9 @@
   PointerDouble() : super('FfiMemory.PointerDouble');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
@@ -404,14 +406,14 @@
 
   @override
   void setup() {
-    pointer = allocate(count: N);
-    data = allocate();
+    pointer = calloc(N);
+    data = calloc();
   }
 
   @override
   void teardown() {
-    free(pointer);
-    free(data);
+    calloc.free(pointer);
+    calloc.free(data);
   }
 
   @override
@@ -429,9 +431,9 @@
   PointerInt64Mint() : super('FfiMemory.PointerInt64Mint');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
diff --git a/benchmarks/FfiMemory/dart2/calloc.dart b/benchmarks/FfiMemory/dart2/calloc.dart
new file mode 100644
index 0000000..c6be280
--- /dev/null
+++ b/benchmarks/FfiMemory/dart2/calloc.dart
@@ -0,0 +1,111 @@
+// 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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+// @dart=2.9
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/benchmarks/FfiStruct/dart/FfiStruct.dart b/benchmarks/FfiStruct/dart/FfiStruct.dart
index 26768c5..a4a8f14 100644
--- a/benchmarks/FfiStruct/dart/FfiStruct.dart
+++ b/benchmarks/FfiStruct/dart/FfiStruct.dart
@@ -12,6 +12,8 @@
 import 'package:ffi/ffi.dart';
 import 'package:benchmark_harness/benchmark_harness.dart';
 
+import 'calloc.dart';
+
 //
 // Struct field store (plus Pointer elementAt and load).
 //
@@ -50,9 +52,9 @@
   FieldLoadStore() : super('FfiStruct.FieldLoadStore');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
diff --git a/benchmarks/FfiStruct/dart/calloc.dart b/benchmarks/FfiStruct/dart/calloc.dart
new file mode 100644
index 0000000..e17238a
--- /dev/null
+++ b/benchmarks/FfiStruct/dart/calloc.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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/benchmarks/FfiStruct/dart2/FfiStruct.dart b/benchmarks/FfiStruct/dart2/FfiStruct.dart
index a11e8ab..6f4e17c 100644
--- a/benchmarks/FfiStruct/dart2/FfiStruct.dart
+++ b/benchmarks/FfiStruct/dart2/FfiStruct.dart
@@ -14,6 +14,8 @@
 import 'package:ffi/ffi.dart';
 import 'package:benchmark_harness/benchmark_harness.dart';
 
+import 'calloc.dart';
+
 //
 // Struct field store (plus Pointer elementAt and load).
 //
@@ -52,9 +54,9 @@
   FieldLoadStore() : super('FfiStruct.FieldLoadStore');
 
   @override
-  void setup() => pointer = allocate(count: N);
+  void setup() => pointer = calloc(N);
   @override
-  void teardown() => free(pointer);
+  void teardown() => calloc.free(pointer);
 
   @override
   void run() {
diff --git a/benchmarks/FfiStruct/dart2/calloc.dart b/benchmarks/FfiStruct/dart2/calloc.dart
new file mode 100644
index 0000000..c6be280
--- /dev/null
+++ b/benchmarks/FfiStruct/dart2/calloc.dart
@@ -0,0 +1,111 @@
+// 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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+// @dart=2.9
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/build/toolchain/fuchsia/BUILD.gn b/build/toolchain/fuchsia/BUILD.gn
index 2901377..b067bf4 100644
--- a/build/toolchain/fuchsia/BUILD.gn
+++ b/build/toolchain/fuchsia/BUILD.gn
@@ -17,9 +17,10 @@
 }
 
 toolchain("fuchsia") {
-  assert(target_cpu == "x64", "We currently only support 'x64' for fuchsia.")
+  assert(target_cpu == "x64" || target_cpu == "arm64",
+         "We currently only support 'x64' and 'arm64' for fuchsia.")
   toolchain_bin =
-      rebase_path("//buildtools/$host_os-$target_cpu/clang/bin", root_out_dir)
+      rebase_path("//buildtools/$host_os-x64/clang/bin", root_out_dir)
   fuchsia_sdk = rebase_path("//third_party/fuchsia/sdk/$host_os", root_out_dir)
 
   # We can't do string interpolation ($ in strings) on things with dots in
@@ -34,6 +35,10 @@
   strip = "${toolchain_bin}/llvm-strip"
 
   target_triple_flags = "--target=x86_64-fuchsia"
+  if (target_cpu == "arm64") {
+    target_triple_flags = "--target=aarch64-fuchsia"
+  }
+
   sysroot_flags = "--sysroot ${fuchsia_sdk}/arch/${target_cpu}/sysroot"
   lto_flags = ""
 
@@ -129,6 +134,11 @@
     exename = "{{target_output_name}}{{output_extension}}"
     outfile = "{{root_out_dir}}/$exename"
     rspfile = "$outfile.rsp"
+
+    # Note that the unstripped_outfile is in the exe.stripped folder.
+    # We should probably clean this up, but changing this and dart.cmx
+    # to point ./dart instead of ./exe.stripped/dart makes the build
+    # fail because ./dart does not end up in the manifest file.
     unstripped_outfile = "{{root_out_dir}}/exe.stripped/$exename"
     command = "$compiler_prefix $ld $target_triple_flags $sysroot_flags $lto_flags {{ldflags}} -o $unstripped_outfile -Wl,--build-id -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}} && ${strip} -o $outfile $unstripped_outfile"
     description = "LINK $outfile"
diff --git a/docs/process/breaking-changes.md b/docs/process/breaking-changes.md
index b277e44..cee804e 100644
--- a/docs/process/breaking-changes.md
+++ b/docs/process/breaking-changes.md
@@ -35,7 +35,8 @@
 * Must access libraries via the public API (for example, must not reach into
   the internals of a package located in the `/src/` directory).
 
-* Must not rely on an [experiment flag](flags.md).
+* Must not rely on an [experiment flag](experimental-flags.md), or depend on
+  libraries or APIs that are documented as being experimental.
 
 * Must not circumvent clear restrictions documented in the public API
   documentation (for example, must not mixin a class clearly documented as
@@ -95,8 +96,8 @@
 
 * Resolve the breaking change issue and make a note that the change has landed
 
-* Make a note in the [Dart SDK changelog](`changelog.md`) detailing the change.
-  This must be prefixed `** Breaking change:`.
+* Make a note in the [Dart SDK changelog](../../CHANGELOG.md) detailing the change.
+  This must be prefixed `**Breaking Change**`.
 
 * Reply to the original announcement email, and make a note that the change is
   being implemented.
diff --git a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
index 2e138d8..46bc443 100644
--- a/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/base/errors.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:meta/meta.dart';
-
 import 'customized_codes.dart';
 
 /// An error code associated with an [AnalysisError].
@@ -23,7 +21,7 @@
 
   final String _message;
 
-  final String _correction;
+  final String? _correction;
 
   /**
    * Return `true` if diagnostics with this code have documentation for them
@@ -43,25 +41,27 @@
    * given [correction] template.
    */
   const ErrorCode({
-    String correction,
+    String? correction,
     this.hasPublishedDocs = false,
     this.isUnresolvedIdentifier: false,
-    @required String message,
-    @required this.name,
-    @required this.uniqueName,
+    required String message,
+    required this.name,
+    required this.uniqueName,
   })  : _correction = correction,
         _message = message,
+        // ignore: unnecessary_null_comparison
         assert(hasPublishedDocs != null),
+        // ignore: unnecessary_null_comparison
         assert(isUnresolvedIdentifier != null);
 
   @Deprecated('Use the default constructor')
   const ErrorCode.temporary2({
-    String correction,
+    String? correction,
     bool hasPublishedDocs = false,
     bool isUnresolvedIdentifier = false,
-    @required String message,
-    @required String name,
-    @required String uniqueName,
+    required String message,
+    required String name,
+    required String uniqueName,
   }) : this(
           correction: correction,
           hasPublishedDocs: hasPublishedDocs,
@@ -76,7 +76,7 @@
    * or `null` if there is no correction information for this error. The
    * correction should indicate how the user can fix the error.
    */
-  String get correction => customizedCorrections[uniqueName] ?? _correction;
+  String? get correction => customizedCorrections[uniqueName] ?? _correction;
 
   /**
    * The severity of the error.
@@ -102,7 +102,7 @@
    * Return a URL that can be used to access documentation for diagnostics with
    * this code, or `null` if there is no published documentation.
    */
-  String get url {
+  String? get url {
     if (hasPublishedDocs) {
       return 'https://dart.dev/tools/diagnostic-messages#${name.toLowerCase()}';
     }
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index 9752d91..6809bbc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -4,6 +4,16 @@
 
 import 'package:meta/meta.dart';
 
+/// Set this boolean to `true` to permanently enable the feature of allowing
+/// local boolean variables to influence promotion (see
+/// https://github.com/dart-lang/language/issues/1274).  While this boolean is
+/// `false`, the feature remains experimental and can be activated via an
+/// optional boolean parameter to the [FlowAnalysis] constructor.
+///
+/// Changing this value to `true` will cause some dead code warnings to appear
+/// for code that only exists to support the old behavior.
+const bool allowLocalBooleanVarsToPromoteByDefault = true;
+
 /// [AssignedVariables] is a helper class capable of computing the set of
 /// variables that are potentially written to, and potentially captured by
 /// closures, at various locations inside the code being analyzed.  This class
@@ -24,7 +34,7 @@
 /// We use the term "node" to refer generally to a loop statement, switch
 /// statement, try statement, loop collection element, local function, or
 /// closure.
-class AssignedVariables<Node, Variable> {
+class AssignedVariables<Node extends Object, Variable extends Object> {
   /// Mapping from a node to the info for that node.
   final Map<Node, AssignedVariablesNodeInfo<Variable>> _info =
       new Map<Node, AssignedVariablesNodeInfo<Variable>>.identity();
@@ -84,12 +94,18 @@
   AssignedVariablesNodeInfo<Variable> deferNode(
       {bool isClosureOrLateVariableInitializer: false}) {
     AssignedVariablesNodeInfo<Variable> info = _stack.removeLast();
+    info._read.removeAll(info._declared);
     info._written.removeAll(info._declared);
+    info._readCaptured.removeAll(info._declared);
     info._captured.removeAll(info._declared);
     AssignedVariablesNodeInfo<Variable> last = _stack.last;
+    last._read.addAll(info._read);
     last._written.addAll(info._written);
+    last._readCaptured.addAll(info._readCaptured);
     last._captured.addAll(info._captured);
     if (isClosureOrLateVariableInitializer) {
+      last._readCaptured.addAll(info._read);
+      _anywhere._readCaptured.addAll(info._read);
       last._captured.addAll(info._written);
       _anywhere._captured.addAll(info._written);
     }
@@ -113,7 +129,9 @@
     AssignedVariablesNodeInfo<Variable> discarded = _stack.removeLast();
     AssignedVariablesNodeInfo<Variable> last = _stack.last;
     last._declared.addAll(discarded._declared);
+    last._read.addAll(discarded._read);
     last._written.addAll(discarded._written);
+    last._readCaptured.addAll(discarded._readCaptured);
     last._captured.addAll(discarded._captured);
   }
 
@@ -144,6 +162,9 @@
           _deferredInfos.isEmpty, "Deferred infos not stored: $_deferredInfos");
       assert(_stack.length == 1, "Unexpected stack: $_stack");
       AssignedVariablesNodeInfo<Variable> last = _stack.last;
+      Set<Variable> undeclaredReads = last._read.difference(last._declared);
+      assert(undeclaredReads.isEmpty,
+          'Variables read from but not declared: $undeclaredReads');
       Set<Variable> undeclaredWrites = last._written.difference(last._declared);
       assert(undeclaredWrites.isEmpty,
           'Variables written to but not declared: $undeclaredWrites');
@@ -171,19 +192,24 @@
     _stack.add(node);
   }
 
+  void read(Variable variable) {
+    _stack.last._read.add(variable);
+    _anywhere._read.add(variable);
+  }
+
   /// Call this method to register that the node [from] for which information
   /// has been stored is replaced by the node [to].
   // TODO(johnniwinther): Remove this when unified collections are encoded as
   // general elements in the front-end.
   void reassignInfo(Node from, Node to) {
     assert(!_info.containsKey(to), "Node $to already has info: ${_info[to]}");
-    AssignedVariablesNodeInfo<Variable> info = _info.remove(from);
+    AssignedVariablesNodeInfo<Variable>? info = _info.remove(from);
     assert(
         info != null,
         'No information for $from (${from.hashCode}) in '
         '{${_info.keys.map((k) => '$k (${k.hashCode})').join(',')}}');
 
-    _info[to] = info;
+    _info[to] = info!;
   }
 
   /// This method may be called at any time between a call to [deferNode] and
@@ -226,12 +252,16 @@
 /// Extension of [AssignedVariables] intended for use in tests.  This class
 /// exposes the results of the analysis so that they can be tested directly.
 /// Not intended to be used by clients of flow analysis.
-class AssignedVariablesForTesting<Node, Variable>
+class AssignedVariablesForTesting<Node extends Object, Variable extends Object>
     extends AssignedVariables<Node, Variable> {
   Set<Variable> get capturedAnywhere => _anywhere._captured;
 
   Set<Variable> get declaredAtTopLevel => _stack.first._declared;
 
+  Set<Variable> get readAnywhere => _anywhere._read;
+
+  Set<Variable> get readCapturedAnywhere => _anywhere._readCaptured;
+
   Set<Variable> get writtenAnywhere => _anywhere._written;
 
   Set<Variable> capturedInNode(Node node) => _getInfoForNode(node)._captured;
@@ -240,6 +270,11 @@
 
   bool isTracked(Node node) => _info.containsKey(node);
 
+  Set<Variable> readCapturedInNode(Node node) =>
+      _getInfoForNode(node)._readCaptured;
+
+  Set<Variable> readInNode(Node node) => _getInfoForNode(node)._read;
+
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('AssignedVariablesForTesting(');
@@ -252,10 +287,14 @@
 }
 
 /// Information tracked by [AssignedVariables] for a single node.
-class AssignedVariablesNodeInfo<Variable> {
+class AssignedVariablesNodeInfo<Variable extends Object> {
+  final Set<Variable> _read = new Set<Variable>.identity();
+
   /// The set of local variables that are potentially written in the node.
   final Set<Variable> _written = new Set<Variable>.identity();
 
+  final Set<Variable> _readCaptured = new Set<Variable>.identity();
+
   /// The set of local variables for which a potential write is captured by a
   /// local function or closure inside the node.
   final Set<Variable> _captured = new Set<Variable>.identity();
@@ -270,7 +309,7 @@
 
 /// A collection of flow models representing the possible outcomes of evaluating
 /// an expression that are relevant to flow analysis.
-class ExpressionInfo<Variable, Type> {
+class ExpressionInfo<Variable extends Object, Type extends Object> {
   /// The state after the expression evaluates, if we don't care what it
   /// evaluates to.
   final FlowModel<Variable, Type> after;
@@ -283,15 +322,20 @@
 
   ExpressionInfo(this.after, this.ifTrue, this.ifFalse);
 
+  /// Computes a new [ExpressionInfo] based on this one, but with the roles of
+  /// [ifTrue] and [ifFalse] reversed.
+  ExpressionInfo<Variable, Type> invert() =>
+      new ExpressionInfo<Variable, Type>(after, ifFalse, ifTrue);
+
+  ExpressionInfo<Variable, Type>? rebaseForward(
+          TypeOperations<Variable, Type> typeOperations,
+          FlowModel<Variable, Type> base) =>
+      new ExpressionInfo(base, ifTrue.rebaseForward(typeOperations, base),
+          ifFalse.rebaseForward(typeOperations, base));
+
   @override
   String toString() =>
       'ExpressionInfo(after: $after, _ifTrue: $ifTrue, ifFalse: $ifFalse)';
-
-  /// Compute a new [ExpressionInfo] based on this one, but with the roles of
-  /// [ifTrue] and [ifFalse] reversed.
-  static ExpressionInfo<Variable, Type> invert<Variable, Type>(
-          ExpressionInfo<Variable, Type> info) =>
-      new ExpressionInfo<Variable, Type>(info.after, info.ifFalse, info.ifTrue);
 }
 
 /// Implementation of flow analysis to be shared between the analyzer and the
@@ -300,13 +344,19 @@
 /// The client should create one instance of this class for every method, field,
 /// or top level variable to be analyzed, and call the appropriate methods
 /// while visiting the code for type inference.
-abstract class FlowAnalysis<Node, Statement extends Node, Expression, Variable,
-    Type> {
+abstract class FlowAnalysis<Node extends Object, Statement extends Node,
+    Expression extends Object, Variable extends Object, Type extends Object> {
   factory FlowAnalysis(TypeOperations<Variable, Type> typeOperations,
-      AssignedVariables<Node, Variable> assignedVariables) {
-    return new _FlowAnalysisImpl(typeOperations, assignedVariables);
+      AssignedVariables<Node, Variable> assignedVariables,
+      {bool allowLocalBooleanVarsToPromote = false}) {
+    return new _FlowAnalysisImpl(typeOperations, assignedVariables,
+        allowLocalBooleanVarsToPromote: allowLocalBooleanVarsToPromote);
   }
 
+  factory FlowAnalysis.legacy(TypeOperations<Variable, Type> typeOperations,
+          AssignedVariables<Node, Variable> assignedVariables) =
+      _LegacyTypePromotion;
+
   /// Return `true` if the current state is reachable.
   bool get isReachable;
 
@@ -366,7 +416,8 @@
 
   /// Call this method upon reaching the "?" part of a conditional expression
   /// ("?:").  [condition] should be the expression preceding the "?".
-  void conditional_thenBegin(Expression condition);
+  /// [conditionalExpression] should be the entire conditional expression.
+  void conditional_thenBegin(Expression condition, Node conditionalExpression);
 
   /// Register a declaration of the [variable] in the current state.
   /// Should also be called for function parameters.
@@ -397,6 +448,12 @@
   /// or `!=` expression.
   void equalityOp_rightBegin(Expression leftOperand, Type leftOperandType);
 
+  /// Retrieves the [ExpressionInfo] associated with [target], if known.  Will
+  /// return `null` if (a) no info is associated with [target], or (b) another
+  /// expression with info has been visited more recently than [target].  For
+  /// testing only.
+  ExpressionInfo<Variable, Type>? expressionInfoForTesting(Expression target);
+
   /// This method should be called at the conclusion of flow analysis for a top
   /// level function or method.  Performs assertion checks.
   void finish();
@@ -414,7 +471,7 @@
   /// the loop condition should cause any promotions to occur.  If [condition]
   /// is null, the condition is understood to be empty (equivalent to a
   /// condition of `true`).
-  void for_bodyBegin(Statement node, Expression condition);
+  void for_bodyBegin(Statement? node, Expression? condition);
 
   /// Call this method just before visiting the condition of a conventional
   /// "for" statement or collection element.
@@ -461,7 +518,7 @@
   /// be the variable assigned to by the loop (if it is promotable, otherwise
   /// null).  [writtenType] should be the type written to that variable (i.e.
   /// if the loop iterates over `List<Foo>`, it should be `Foo`).
-  void forEach_bodyBegin(Node node, Variable loopVariable, Type writtenType);
+  void forEach_bodyBegin(Node node, Variable? loopVariable, Type writtenType);
 
   /// Call this method just before visiting the body of a "for-in" statement or
   /// collection element.  See [forEach_bodyBegin] for details.
@@ -552,8 +609,14 @@
   void ifStatement_end(bool hasElse);
 
   /// Call this method after visiting the condition part of an if statement.
-  /// [condition] should be the if statement's condition.
-  void ifStatement_thenBegin(Expression condition);
+  /// [condition] should be the if statement's condition.  [ifNode] should be
+  /// the entire `if` statement (or the collection literal entry).
+  void ifStatement_thenBegin(Expression condition, Node ifNode);
+
+  /// Call this method after visiting the initializer of a variable declaration.
+  void initialize(
+      Variable variable, Type initializerType, Expression initializerExpression,
+      {required bool isFinal, required bool isLate});
 
   /// Return whether the [variable] is definitely assigned in the current state.
   bool isAssigned(Variable variable);
@@ -573,7 +636,7 @@
 
   /// Call this method before visiting a labeled statement.
   /// Call [labeledStatement_end] after visiting the statement.
-  void labeledStatement_begin(Node node);
+  void labeledStatement_begin(Statement node);
 
   /// Call this method after visiting a labeled statement.
   void labeledStatement_end();
@@ -594,14 +657,15 @@
   /// [rightOperand] should be the RHS.  [isAnd] should indicate whether the
   /// logical operator is "&&" or "||".
   void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
-      {@required bool isAnd});
+      {required bool isAnd});
 
   /// Call this method after visiting the LHS of a logical binary operation
   /// ("||" or "&&").
   /// [rightOperand] should be the LHS.  [isAnd] should indicate whether the
-  /// logical operator is "&&" or "||".
-  void logicalBinaryOp_rightBegin(Expression leftOperand,
-      {@required bool isAnd});
+  /// logical operator is "&&" or "||".  [wholeExpression] should be the whole
+  /// logical binary expression.
+  void logicalBinaryOp_rightBegin(Expression leftOperand, Node wholeExpression,
+      {required bool isAnd});
 
   /// Call this method after visiting a logical not ("!") expression.
   /// [notExpression] should be the complete expression.  [operand] should be
@@ -630,7 +694,7 @@
   /// code being analyzed is `x?.y?.z(x)`, [nullAwareAccess_rightBegin] should
   /// be called once upon reaching each `?.`, but [nullAwareAccess_end] should
   /// not be called until after processing the method call to `z(x)`.
-  void nullAwareAccess_rightBegin(Expression target, Type targetType);
+  void nullAwareAccess_rightBegin(Expression? target, Type targetType);
 
   /// Call this method when encountering an expression that is a `null` literal.
   void nullLiteral(Expression expression);
@@ -649,7 +713,13 @@
 
   /// Retrieves the type that the [variable] is promoted to, if the [variable]
   /// is currently promoted.  Otherwise returns `null`.
-  Type promotedType(Variable variable);
+  Type? promotedType(Variable variable);
+
+  /// Retrieves the SSA node associated with [variable], or `null` if [variable]
+  /// is not associated with an SSA node because it is write captured.  For
+  /// testing only.
+  @visibleForTesting
+  SsaNode<Variable, Type>? ssaNodeForTesting(Variable variable);
 
   /// Call this method just before visiting one of the cases in the body of a
   /// switch statement.  See [switchStatement_expressionEnd] for details.
@@ -723,7 +793,7 @@
   /// clause, or `null` if there is no exception variable.  Similar for
   /// [stackTraceVariable].
   void tryCatchStatement_catchBegin(
-      Variable exceptionVariable, Variable stackTraceVariable);
+      Variable? exceptionVariable, Variable? stackTraceVariable);
 
   /// Call this method just after visiting a catch clause of a "try/catch"
   /// statement.  See [tryCatchStatement_bodyBegin] for details.
@@ -768,7 +838,7 @@
   ///
   /// If the variable's type is currently promoted, the promoted type is
   /// returned.  Otherwise `null` is returned.
-  Type variableRead(Expression expression, Variable variable);
+  Type? variableRead(Expression expression, Variable variable);
 
   /// Call this method after visiting the condition part of a "while" statement.
   /// [whileStatement] should be the full while statement.  [condition] should
@@ -787,27 +857,46 @@
 
   /// Register write of the given [variable] in the current state.
   /// [writtenType] should be the type of the value that was written.
+  /// [writtenExpression] should be the expression that was written, or `null`
+  /// if the expression that was written is not directly represented in the
+  /// source code (this happens, for example, with compound assignments and with
+  /// for-each loops).
   ///
   /// This should also be used for the implicit write to a non-final variable in
   /// its initializer, to ensure that the type is promoted to non-nullable if
   /// necessary; in this case, [viaInitializer] should be `true`.
-  void write(Variable variable, Type writtenType,
-      {bool viaInitializer = false});
+  void write(
+      Variable variable, Type writtenType, Expression? writtenExpression);
+
+  /// Prints out a summary of the current state of flow analysis, intended for
+  /// debugging use only.
+  void _dumpState();
 }
 
 /// Alternate implementation of [FlowAnalysis] that prints out inputs and output
 /// at the API boundary, for assistance in debugging.
-class FlowAnalysisDebug<Node, Statement extends Node, Expression, Variable,
-    Type> implements FlowAnalysis<Node, Statement, Expression, Variable, Type> {
-  _FlowAnalysisImpl<Node, Statement, Expression, Variable, Type> _wrapped;
+class FlowAnalysisDebug<Node extends Object, Statement extends Node,
+        Expression extends Object, Variable extends Object, Type extends Object>
+    implements FlowAnalysis<Node, Statement, Expression, Variable, Type> {
+  FlowAnalysis<Node, Statement, Expression, Variable, Type> _wrapped;
 
   bool _exceptionOccurred = false;
 
   factory FlowAnalysisDebug(TypeOperations<Variable, Type> typeOperations,
-      AssignedVariables<Node, Variable> assignedVariables) {
+      AssignedVariables<Node, Variable> assignedVariables,
+      {bool allowLocalBooleanVarsToPromote = false}) {
     print('FlowAnalysisDebug()');
+    return new FlowAnalysisDebug._(new _FlowAnalysisImpl(
+        typeOperations, assignedVariables,
+        allowLocalBooleanVarsToPromote: allowLocalBooleanVarsToPromote));
+  }
+
+  factory FlowAnalysisDebug.legacy(
+      TypeOperations<Variable, Type> typeOperations,
+      AssignedVariables<Node, Variable> assignedVariables) {
+    print('FlowAnalysisDebug.legacy()');
     return new FlowAnalysisDebug._(
-        new _FlowAnalysisImpl(typeOperations, assignedVariables));
+        new _LegacyTypePromotion(typeOperations, assignedVariables));
   }
 
   FlowAnalysisDebug._(this._wrapped);
@@ -864,9 +953,9 @@
   }
 
   @override
-  void conditional_thenBegin(Expression condition) {
-    _wrap('conditional_thenBegin($condition)',
-        () => _wrapped.conditional_thenBegin(condition));
+  void conditional_thenBegin(Expression condition, Node conditionalExpression) {
+    _wrap('conditional_thenBegin($condition, $conditionalExpression)',
+        () => _wrapped.conditional_thenBegin(condition, conditionalExpression));
   }
 
   @override
@@ -912,6 +1001,13 @@
   }
 
   @override
+  ExpressionInfo<Variable, Type>? expressionInfoForTesting(Expression target) {
+    return _wrap('expressionInfoForTesting($target)',
+        () => _wrapped.expressionInfoForTesting(target),
+        isQuery: true);
+  }
+
+  @override
   void finish() {
     if (_exceptionOccurred) {
       _wrap('finish() (skipped)', () {}, isPure: true);
@@ -921,7 +1017,7 @@
   }
 
   @override
-  void for_bodyBegin(Statement node, Expression condition) {
+  void for_bodyBegin(Statement? node, Expression? condition) {
     _wrap('for_bodyBegin($node, $condition)',
         () => _wrapped.for_bodyBegin(node, condition));
   }
@@ -942,7 +1038,7 @@
   }
 
   @override
-  void forEach_bodyBegin(Node node, Variable loopVariable, Type writtenType) {
+  void forEach_bodyBegin(Node node, Variable? loopVariable, Type writtenType) {
     return _wrap('forEach_bodyBegin($node, $loopVariable, $writtenType)',
         () => _wrapped.forEach_bodyBegin(node, loopVariable, writtenType));
   }
@@ -1017,9 +1113,21 @@
   }
 
   @override
-  void ifStatement_thenBegin(Expression condition) {
-    _wrap('ifStatement_thenBegin($condition)',
-        () => _wrapped.ifStatement_thenBegin(condition));
+  void ifStatement_thenBegin(Expression condition, Node ifNode) {
+    _wrap('ifStatement_thenBegin($condition, $ifNode)',
+        () => _wrapped.ifStatement_thenBegin(condition, ifNode));
+  }
+
+  @override
+  void initialize(
+      Variable variable, Type initializerType, Expression initializerExpression,
+      {required bool isFinal, required bool isLate}) {
+    _wrap(
+        'initialize($variable, $initializerType, $initializerExpression, '
+        'isFinal: $isFinal, isLate: $isLate)',
+        () => _wrapped.initialize(
+            variable, initializerType, initializerExpression,
+            isFinal: isFinal, isLate: isLate));
   }
 
   @override
@@ -1045,7 +1153,7 @@
   }
 
   @override
-  void labeledStatement_begin(Node node) {
+  void labeledStatement_begin(Statement node) {
     return _wrap('labeledStatement_begin($node)',
         () => _wrapped.labeledStatement_begin(node));
   }
@@ -1074,7 +1182,7 @@
 
   @override
   void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
-      {@required bool isAnd}) {
+      {required bool isAnd}) {
     _wrap(
         'logicalBinaryOp_end($wholeExpression, $rightOperand, isAnd: $isAnd)',
         () => _wrapped.logicalBinaryOp_end(wholeExpression, rightOperand,
@@ -1082,10 +1190,13 @@
   }
 
   @override
-  void logicalBinaryOp_rightBegin(Expression leftOperand,
-      {@required bool isAnd}) {
-    _wrap('logicalBinaryOp_rightBegin($leftOperand, isAnd: $isAnd)',
-        () => _wrapped.logicalBinaryOp_rightBegin(leftOperand, isAnd: isAnd));
+  void logicalBinaryOp_rightBegin(Expression leftOperand, Node wholeExpression,
+      {required bool isAnd}) {
+    _wrap(
+        'logicalBinaryOp_rightBegin($leftOperand, $wholeExpression, '
+        'isAnd: $isAnd)',
+        () => _wrapped.logicalBinaryOp_rightBegin(leftOperand, wholeExpression,
+            isAnd: isAnd));
   }
 
   @override
@@ -1106,7 +1217,7 @@
   }
 
   @override
-  void nullAwareAccess_rightBegin(Expression target, Type targetType) {
+  void nullAwareAccess_rightBegin(Expression? target, Type targetType) {
     _wrap('nullAwareAccess_rightBegin($target, $targetType)',
         () => _wrapped.nullAwareAccess_rightBegin(target, targetType));
   }
@@ -1131,13 +1242,20 @@
   }
 
   @override
-  Type promotedType(Variable variable) {
+  Type? promotedType(Variable variable) {
     return _wrap(
         'promotedType($variable)', () => _wrapped.promotedType(variable),
         isQuery: true);
   }
 
   @override
+  SsaNode<Variable, Type>? ssaNodeForTesting(Variable variable) {
+    return _wrap('ssaNodeForTesting($variable)',
+        () => _wrapped.ssaNodeForTesting(variable),
+        isQuery: true);
+  }
+
+  @override
   void switchStatement_beginCase(bool hasLabel, Node node) {
     _wrap('switchStatement_beginCase($hasLabel, $node)',
         () => _wrapped.switchStatement_beginCase(hasLabel, node));
@@ -1169,7 +1287,7 @@
 
   @override
   void tryCatchStatement_catchBegin(
-      Variable exceptionVariable, Variable stackTraceVariable) {
+      Variable? exceptionVariable, Variable? stackTraceVariable) {
     return _wrap(
         'tryCatchStatement_catchBegin($exceptionVariable, $stackTraceVariable)',
         () => _wrapped.tryCatchStatement_catchBegin(
@@ -1207,7 +1325,7 @@
   }
 
   @override
-  Type variableRead(Expression expression, Variable variable) {
+  Type? variableRead(Expression expression, Variable variable) {
     return _wrap('variableRead($expression, $variable)',
         () => _wrapped.variableRead(expression, variable),
         isQuery: true, isPure: false);
@@ -1232,16 +1350,17 @@
   }
 
   @override
-  void write(Variable variable, Type writtenType,
-      {bool viaInitializer = false}) {
-    _wrap(
-        'write($variable, $writtenType, viaInitializer: $viaInitializer)',
-        () => _wrapped.write(variable, writtenType,
-            viaInitializer: viaInitializer));
+  void write(
+      Variable variable, Type writtenType, Expression? writtenExpression) {
+    _wrap('write($variable, $writtenType, $writtenExpression)',
+        () => _wrapped.write(variable, writtenType, writtenExpression));
   }
 
+  @override
+  void _dumpState() => _wrapped._dumpState();
+
   T _wrap<T>(String description, T callback(),
-      {bool isQuery: false, bool isPure}) {
+      {bool isQuery: false, bool? isPure}) {
     isPure ??= isQuery;
     print(description);
     T result;
@@ -1270,7 +1389,7 @@
 /// Instances of this class are immutable, so the methods below that "update"
 /// the state actually leave `this` unchanged and return a new state object.
 @visibleForTesting
-class FlowModel<Variable, Type> {
+class FlowModel<Variable extends Object, Type extends Object> {
   final Reachability reachable;
 
   /// For each variable being tracked by flow analysis, the variable's model.
@@ -1300,15 +1419,131 @@
 
   @visibleForTesting
   FlowModel.withInfo(this.reachable, this.variableInfo) {
+    // ignore:unnecessary_null_comparison
     assert(reachable != null);
     assert(() {
       for (VariableModel<Variable, Type> value in variableInfo.values) {
+        // ignore:unnecessary_null_comparison
         assert(value != null);
       }
       return true;
     }());
   }
 
+  /// Computes the effect of executing a try/finally's `try` and `finally`
+  /// blocks in sequence.  `this` is the flow analysis state from the end of the
+  /// `try` block; [beforeFinally] and [afterFinally] are the flow analysis
+  /// states from the top and bottom of the `finally` block, respectively.
+  ///
+  /// Initially the `finally` block is analyzed under the conservative
+  /// assumption that the `try` block might have been interrupted at any point
+  /// by an exception occurring, therefore no variable assignments or promotions
+  /// that occurred in the `try` block can be relied upon.  As a result, when we
+  /// get to the end of processing the `finally` block, the only promotions and
+  /// variable assignments accounted for by flow analysis are the ones performed
+  /// within the `finally` block itself.  However, when we analyze code that
+  /// follows the `finally` block, we know that the `try` block did *not* throw
+  /// an exception, so we want to reinstate the results of any promotions and
+  /// assignments that occurred during the `try` block, to the extent that they
+  /// weren't invalidated by later assignments in the `finally` block.
+  FlowModel<Variable, Type> attachFinally(
+      TypeOperations<Variable, Type> typeOperations,
+      FlowModel<Variable, Type> beforeFinally,
+      FlowModel<Variable, Type> afterFinally) {
+    // Code that follows the `try/finally` is reachable iff the end of the `try`
+    // block is reachable _and_ the end of the `finally` block is reachable.
+    Reachability newReachable = afterFinally.reachable.rebaseForward(reachable);
+
+    // Consider each variable that is common to all three models.
+    Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
+        <Variable, VariableModel<Variable, Type>>{};
+    bool variableInfoMatchesThis = true;
+    bool variableInfoMatchesAfterFinally = true;
+    for (MapEntry<Variable, VariableModel<Variable, Type>> entry
+        in variableInfo.entries) {
+      Variable variable = entry.key;
+      VariableModel<Variable, Type> thisModel = entry.value;
+      VariableModel<Variable, Type>? beforeFinallyModel =
+          beforeFinally.variableInfo[variable];
+      VariableModel<Variable, Type>? afterFinallyModel =
+          afterFinally.variableInfo[variable];
+      if (beforeFinallyModel == null || afterFinallyModel == null) {
+        // The variable is in `this` model but not in one of the `finally`
+        // models.  This happens when the variable is declared inside the `try`
+        // block.  We can just drop the variable because it won't be in scope
+        // after the try/finally statement.
+        variableInfoMatchesThis = false;
+        continue;
+      }
+      // We can just use the "write captured" state from the `finally` block,
+      // because any write captures in the `try` block are conservatively
+      // considered to take effect in the `finally` block too.
+      List<Type>? newPromotedTypes;
+      SsaNode<Variable, Type>? newSsaNode;
+      if (beforeFinallyModel.ssaNode == afterFinallyModel.ssaNode) {
+        // The finally clause doesn't write to the variable, so we want to keep
+        // all promotions that were done to it in both the try and finally
+        // blocks.
+        newPromotedTypes = VariableModel.rebasePromotedTypes(typeOperations,
+            thisModel.promotedTypes, afterFinallyModel.promotedTypes);
+        // And we can safely restore the SSA node from the end of the try block.
+        newSsaNode = thisModel.ssaNode;
+      } else {
+        // A write to the variable occurred in the finally block, so promotions
+        // from the try block aren't necessarily valid.
+        newPromotedTypes = afterFinallyModel.promotedTypes;
+        // And we can't safely restore the SSA node from the end of the try
+        // block; we need to keep the one from the end of the finally block.
+        newSsaNode = afterFinallyModel.ssaNode;
+      }
+      // The `finally` block inherited all tests from the `try` block so we can
+      // just inherit tests from it.
+      List<Type> newTested = afterFinallyModel.tested;
+      // The variable is definitely assigned if it was definitely assigned in
+      // either the `try` or the `finally` block.
+      bool newAssigned = thisModel.assigned || afterFinallyModel.assigned;
+      // The `finally` block inherited the "unassigned" state from the `try`
+      // block so we can just inherit from it.
+      bool newUnassigned = afterFinallyModel.unassigned;
+      VariableModel<Variable, Type> newModel = VariableModel._identicalOrNew(
+          thisModel,
+          afterFinallyModel,
+          newPromotedTypes,
+          newTested,
+          newAssigned,
+          newUnassigned,
+          newSsaNode);
+      newVariableInfo[variable] = newModel;
+      if (!identical(newModel, thisModel)) variableInfoMatchesThis = false;
+      if (!identical(newModel, afterFinallyModel)) {
+        variableInfoMatchesAfterFinally = false;
+      }
+    }
+    // newVariableInfo is now correct.  However, if there are any variables
+    // present in `afterFinally` that aren't present in `this`, we may
+    // erroneously think that `newVariableInfo` matches `afterFinally`.  If so,
+    // correct that.
+    if (variableInfoMatchesAfterFinally) {
+      for (Variable variable in afterFinally.variableInfo.keys) {
+        if (!variableInfo.containsKey(variable)) {
+          variableInfoMatchesAfterFinally = false;
+          break;
+        }
+      }
+    }
+    assert(variableInfoMatchesThis ==
+        _variableInfosEqual(newVariableInfo, variableInfo));
+    assert(variableInfoMatchesAfterFinally ==
+        _variableInfosEqual(newVariableInfo, afterFinally.variableInfo));
+    if (variableInfoMatchesThis) {
+      newVariableInfo = variableInfo;
+    } else if (variableInfoMatchesAfterFinally) {
+      newVariableInfo = afterFinally.variableInfo;
+    }
+
+    return _identicalOrNew(this, afterFinally, newReachable, newVariableInfo);
+  }
+
   /// Updates the state to indicate that the given [writtenVariables] are no
   /// longer promoted and are no longer definitely unassigned, and the given
   /// [capturedVariables] have been captured by closures.
@@ -1332,7 +1567,7 @@
   FlowModel<Variable, Type> conservativeJoin(
       Iterable<Variable> writtenVariables,
       Iterable<Variable> capturedVariables) {
-    Map<Variable, VariableModel<Variable, Type>> newVariableInfo;
+    Map<Variable, VariableModel<Variable, Type>>? newVariableInfo;
 
     for (Variable variable in writtenVariables) {
       VariableModel<Variable, Type> info = infoFor(variable);
@@ -1346,12 +1581,16 @@
     }
 
     for (Variable variable in capturedVariables) {
-      VariableModel<Variable, Type> info = variableInfo[variable];
+      VariableModel<Variable, Type>? info = variableInfo[variable];
       if (info == null) {
         (newVariableInfo ??=
             new Map<Variable, VariableModel<Variable, Type>>.from(
                 variableInfo))[variable] = new VariableModel<Variable, Type>(
-            null, const [], false, false, true);
+            promotedTypes: null,
+            tested: const [],
+            assigned: false,
+            unassigned: false,
+            ssaNode: null);
       } else if (!info.writeCaptured) {
         (newVariableInfo ??=
             new Map<Variable, VariableModel<Variable, Type>>.from(
@@ -1375,7 +1614,7 @@
     VariableModel<Variable, Type> newInfoForVar =
         new VariableModel.fresh(assigned: initialized);
 
-    return _updateVariableInfo(variable, newInfoForVar);
+    return _updateVariableInfo(new VariableReference(variable), newInfoForVar);
   }
 
   /// Gets the info for the given [variable], creating it if it doesn't exist.
@@ -1400,7 +1639,7 @@
         in variableInfo.entries) {
       Variable variable = entry.key;
       VariableModel<Variable, Type> variableModel = entry.value;
-      VariableModel<Variable, Type> otherVariableModel =
+      VariableModel<Variable, Type>? otherVariableModel =
           otherVariableInfo[variable];
       VariableModel<Variable, Type> newVariableModel =
           otherVariableModel == null
@@ -1417,6 +1656,106 @@
     }
   }
 
+  /// Updates `this` flow model to account for any promotions and assignments
+  /// present in [base].
+  ///
+  /// This is called "rebasing" the flow model by analogy to "git rebase"; in
+  /// effect, it rewinds any flow analysis state present in `this` but not in
+  /// the history of [base], and then reapplies that state using [base] as a
+  /// starting point, to the extent possible without creating unsoundness.  For
+  /// example, if a variable is promoted in `this` but not in [base], then it
+  /// will be promoted in the output model, provided that hasn't been reassigned
+  /// since then (which would make the promotion unsound).
+  FlowModel<Variable, Type> rebaseForward(
+      TypeOperations<Variable, Type> typeOperations,
+      FlowModel<Variable, Type> base) {
+    // The rebased model is reachable iff both `this` and the new base are
+    // reachable.
+    Reachability newReachable = reachable.rebaseForward(base.reachable);
+
+    // Consider each variable in the new base model.
+    Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
+        <Variable, VariableModel<Variable, Type>>{};
+    bool variableInfoMatchesThis = true;
+    bool variableInfoMatchesBase = true;
+    for (MapEntry<Variable, VariableModel<Variable, Type>> entry
+        in base.variableInfo.entries) {
+      Variable variable = entry.key;
+      VariableModel<Variable, Type> baseModel = entry.value;
+      VariableModel<Variable, Type>? thisModel = variableInfo[variable];
+      if (thisModel == null) {
+        // The variable has newly came into scope since `thisModel`, so the
+        // information in `baseModel` is up to date.
+        newVariableInfo[variable] = baseModel;
+        variableInfoMatchesThis = false;
+        continue;
+      }
+      // If the variable was write captured in either `this` or the new base,
+      // it's captured now.
+      bool newWriteCaptured =
+          thisModel.writeCaptured || baseModel.writeCaptured;
+      List<Type>? newPromotedTypes;
+      if (newWriteCaptured) {
+        // Write captured variables can't be promoted.
+        newPromotedTypes = null;
+      } else if (baseModel.ssaNode != thisModel.ssaNode) {
+        // The variable may have been written to since `thisModel`, so we can't
+        // use any of the promotions from `thisModel`.
+        newPromotedTypes = baseModel.promotedTypes;
+      } else {
+        // The variable hasn't been written to since `thisModel`, so we can keep
+        // all of the promotions from `thisModel`, provided that we retain the
+        // usual "promotion chain" invariant (each promoted type is a subtype of
+        // the previous).
+        newPromotedTypes = VariableModel.rebasePromotedTypes(
+            typeOperations, thisModel.promotedTypes, baseModel.promotedTypes);
+      }
+      // Tests are kept regardless of whether they are in `this` model or the
+      // new base model.
+      List<Type> newTested = VariableModel.joinTested(
+          thisModel.tested, baseModel.tested, typeOperations);
+      // The variable is definitely assigned if it was definitely assigned
+      // either in `this` model or the new base model.
+      bool newAssigned = thisModel.assigned || baseModel.assigned;
+      // The variable is definitely unassigned if it was definitely unassigned
+      // in both `this` model and the new base model.
+      bool newUnassigned = thisModel.unassigned && baseModel.unassigned;
+      VariableModel<Variable, Type> newModel = VariableModel._identicalOrNew(
+          thisModel,
+          baseModel,
+          newPromotedTypes,
+          newTested,
+          newAssigned,
+          newUnassigned,
+          newWriteCaptured ? null : baseModel.ssaNode);
+      newVariableInfo[variable] = newModel;
+      if (!identical(newModel, thisModel)) variableInfoMatchesThis = false;
+      if (!identical(newModel, baseModel)) variableInfoMatchesBase = false;
+    }
+    // newVariableInfo is now correct.  However, if there are any variables
+    // present in `this` that aren't present in `base`, we may erroneously think
+    // that `newVariableInfo` matches `this`.  If so, correct that.
+    if (variableInfoMatchesThis) {
+      for (Variable variable in variableInfo.keys) {
+        if (!base.variableInfo.containsKey(variable)) {
+          variableInfoMatchesThis = false;
+          break;
+        }
+      }
+    }
+    assert(variableInfoMatchesThis ==
+        _variableInfosEqual(newVariableInfo, variableInfo));
+    assert(variableInfoMatchesBase ==
+        _variableInfosEqual(newVariableInfo, base.variableInfo));
+    if (variableInfoMatchesThis) {
+      newVariableInfo = variableInfo;
+    } else if (variableInfoMatchesBase) {
+      newVariableInfo = base.variableInfo;
+    }
+
+    return _identicalOrNew(this, base, newReachable, newVariableInfo);
+  }
+
   /// Updates the state to reflect a control path that is known to have
   /// previously passed through some [other] state.
   ///
@@ -1441,6 +1780,12 @@
       TypeOperations<Variable, Type> typeOperations,
       FlowModel<Variable, Type> other,
       Set<Variable> unsafe) {
+    if (allowLocalBooleanVarsToPromoteByDefault) {
+      // TODO(paulberry): when we hardcode
+      // allowLocalBooleanVarsToPromoteByDefault to `true`, we should remove
+      // this method entirely.
+      throw new StateError('This method should not be called anymore');
+    }
     Reachability newReachable =
         Reachability.restrict(reachable, other.reachable);
 
@@ -1452,7 +1797,7 @@
         in variableInfo.entries) {
       Variable variable = entry.key;
       VariableModel<Variable, Type> thisModel = entry.value;
-      VariableModel<Variable, Type> otherModel = other.variableInfo[variable];
+      VariableModel<Variable, Type>? otherModel = other.variableInfo[variable];
       if (otherModel == null) {
         variableInfoMatchesThis = false;
         continue;
@@ -1501,28 +1846,29 @@
   String toString() => '($reachable, $variableInfo)';
 
   /// Returns an [ExpressionInfo] indicating the result of checking whether the
-  /// given [variable] is non-null.
+  /// given [reference] is non-null.
   ///
   /// Note that the state is only changed if the previous type of [variable] was
   /// potentially nullable.
   ExpressionInfo<Variable, Type> tryMarkNonNullable(
-      TypeOperations<Variable, Type> typeOperations, Variable variable) {
-    VariableModel<Variable, Type> info = infoFor(variable);
+      TypeOperations<Variable, Type> typeOperations,
+      Reference<Variable, Type> reference) {
+    VariableModel<Variable, Type> info = reference.getInfo(variableInfo);
     if (info.writeCaptured) {
-      return new ExpressionInfo<Variable, Type>(this, this, this);
+      return new _TrivialExpressionInfo<Variable, Type>(this);
     }
 
-    Type previousType = info.promotedTypes?.last;
-    previousType ??= typeOperations.variableType(variable);
+    Type? previousType = info.promotedTypes?.last;
+    previousType ??= reference.getDeclaredType(typeOperations);
 
     Type newType = typeOperations.promoteToNonNull(previousType);
     if (typeOperations.isSameType(newType, previousType)) {
-      return new ExpressionInfo<Variable, Type>(this, this, this);
+      return new _TrivialExpressionInfo<Variable, Type>(this);
     }
     assert(typeOperations.isSubtypeOf(newType, previousType));
 
     FlowModel<Variable, Type> modelIfSuccessful =
-        _finishTypeTest(typeOperations, variable, info, null, newType);
+        _finishTypeTest(typeOperations, reference, info, null, newType);
 
     FlowModel<Variable, Type> modelIfFailed = this;
 
@@ -1531,7 +1877,7 @@
   }
 
   /// Returns an [ExpressionInfo] indicating the result of casting the given
-  /// [variable] to the given [type], as a consequence of an `as` expression.
+  /// [reference] to the given [type], as a consequence of an `as` expression.
   ///
   /// Note that the state is only changed if [type] is a subtype of the
   /// variable's previous (possibly promoted) type.
@@ -1540,28 +1886,28 @@
   /// variable as definitely assigned?  Does it matter?
   FlowModel<Variable, Type> tryPromoteForTypeCast(
       TypeOperations<Variable, Type> typeOperations,
-      Variable variable,
+      Reference<Variable, Type> reference,
       Type type) {
-    VariableModel<Variable, Type> info = infoFor(variable);
+    VariableModel<Variable, Type> info = reference.getInfo(variableInfo);
     if (info.writeCaptured) {
       return this;
     }
 
-    Type previousType = info.promotedTypes?.last;
-    previousType ??= typeOperations.variableType(variable);
+    Type? previousType = info.promotedTypes?.last;
+    previousType ??= reference.getDeclaredType(typeOperations);
 
-    Type newType = typeOperations.tryPromoteToType(type, previousType);
+    Type? newType = typeOperations.tryPromoteToType(type, previousType);
     if (newType == null || typeOperations.isSameType(newType, previousType)) {
       return this;
     }
 
     assert(typeOperations.isSubtypeOf(newType, previousType),
         "Expected $newType to be a subtype of $previousType.");
-    return _finishTypeTest(typeOperations, variable, info, type, newType);
+    return _finishTypeTest(typeOperations, reference, info, type, newType);
   }
 
   /// Returns an [ExpressionInfo] indicating the result of checking whether the
-  /// given [variable] satisfies the given [type], e.g. as a consequence of an
+  /// given [reference] satisfies the given [type], e.g. as a consequence of an
   /// `is` expression as the condition of an `if` statement.
   ///
   /// Note that the "ifTrue" state is only changed if [type] is a subtype of
@@ -1571,28 +1917,28 @@
   /// variable as definitely assigned?  Does it matter?
   ExpressionInfo<Variable, Type> tryPromoteForTypeCheck(
       TypeOperations<Variable, Type> typeOperations,
-      Variable variable,
+      Reference<Variable, Type> reference,
       Type type) {
-    VariableModel<Variable, Type> info = infoFor(variable);
+    VariableModel<Variable, Type> info = reference.getInfo(variableInfo);
     if (info.writeCaptured) {
-      return new ExpressionInfo<Variable, Type>(this, this, this);
+      return new _TrivialExpressionInfo<Variable, Type>(this);
     }
 
-    Type previousType = info.promotedTypes?.last;
-    previousType ??= typeOperations.variableType(variable);
+    Type? previousType = info.promotedTypes?.last;
+    previousType ??= reference.getDeclaredType(typeOperations);
 
     FlowModel<Variable, Type> modelIfSuccessful = this;
-    Type typeIfSuccess = typeOperations.tryPromoteToType(type, previousType);
+    Type? typeIfSuccess = typeOperations.tryPromoteToType(type, previousType);
     if (typeIfSuccess != null &&
         !typeOperations.isSameType(typeIfSuccess, previousType)) {
       assert(typeOperations.isSubtypeOf(typeIfSuccess, previousType),
           "Expected $typeIfSuccess to be a subtype of $previousType.");
       modelIfSuccessful =
-          _finishTypeTest(typeOperations, variable, info, type, typeIfSuccess);
+          _finishTypeTest(typeOperations, reference, info, type, typeIfSuccess);
     }
 
     Type factoredType = typeOperations.factor(previousType, type);
-    Type typeIfFailed;
+    Type? typeIfFailed;
     if (typeOperations.isNever(factoredType)) {
       // Promoting to `Never` would mark the code as unreachable.  But it might
       // be reachable due to mixed mode unsoundness.  So don't promote.
@@ -1604,7 +1950,7 @@
       typeIfFailed = factoredType;
     }
     FlowModel<Variable, Type> modelIfFailed =
-        _finishTypeTest(typeOperations, variable, info, type, typeIfFailed);
+        _finishTypeTest(typeOperations, reference, info, type, typeIfFailed);
 
     return new ExpressionInfo<Variable, Type>(
         this, modelIfSuccessful, modelIfFailed);
@@ -1629,21 +1975,24 @@
   /// Updates the state to indicate that an assignment was made to the given
   /// [variable].  The variable is marked as definitely assigned, and any
   /// previous type promotion is removed.
-  FlowModel<Variable, Type> write(Variable variable, Type writtenType,
+  FlowModel<Variable, Type> write(
+      Variable variable,
+      Type writtenType,
+      SsaNode<Variable, Type> newSsaNode,
       TypeOperations<Variable, Type> typeOperations) {
-    VariableModel<Variable, Type> infoForVar = variableInfo[variable];
+    VariableModel<Variable, Type>? infoForVar = variableInfo[variable];
     if (infoForVar == null) return this;
 
     VariableModel<Variable, Type> newInfoForVar =
-        infoForVar.write(variable, writtenType, typeOperations);
+        infoForVar.write(variable, writtenType, typeOperations, newSsaNode);
     if (identical(newInfoForVar, infoForVar)) return this;
 
-    return _updateVariableInfo(variable, newInfoForVar);
+    return _updateVariableInfo(new VariableReference(variable), newInfoForVar);
   }
 
   /// Common algorithm for [tryMarkNonNullable], [tryPromoteForTypeCast],
   /// and [tryPromoteForTypeCheck].  Builds a [FlowModel] object describing the
-  /// effect of updating the [variable] by adding the [testedType] to the
+  /// effect of updating the [reference] by adding the [testedType] to the
   /// list of tested types (if not `null`, and not there already), adding the
   /// [promotedType] to the chain of promoted types.
   ///
@@ -1654,10 +2003,10 @@
   /// - The variable should not be write-captured.
   FlowModel<Variable, Type> _finishTypeTest(
     TypeOperations<Variable, Type> typeOperations,
-    Variable variable,
+    Reference<Variable, Type> reference,
     VariableModel<Variable, Type> info,
-    Type testedType,
-    Type promotedType,
+    Type? testedType,
+    Type? promotedType,
   ) {
     List<Type> newTested = info.tested;
     if (testedType != null) {
@@ -1665,7 +2014,7 @@
           info.tested, testedType, typeOperations);
     }
 
-    List<Type> newPromotedTypes = info.promotedTypes;
+    List<Type>? newPromotedTypes = info.promotedTypes;
     Reachability newReachable = reachable;
     if (promotedType != null) {
       newPromotedTypes =
@@ -1680,21 +2029,25 @@
             newReachable == reachable
         ? this
         : _updateVariableInfo(
-            variable,
-            new VariableModel<Variable, Type>(newPromotedTypes, newTested,
-                info.assigned, info.unassigned, info.writeCaptured),
+            reference,
+            new VariableModel<Variable, Type>(
+                promotedTypes: newPromotedTypes,
+                tested: newTested,
+                assigned: info.assigned,
+                unassigned: info.unassigned,
+                ssaNode: info.ssaNode),
             reachable: newReachable);
   }
 
-  /// Returns a new [FlowModel] where the information for [variable] is replaced
-  /// with [model].
+  /// Returns a new [FlowModel] where the information for [reference] is
+  /// replaced with [model].
   FlowModel<Variable, Type> _updateVariableInfo(
-      Variable variable, VariableModel<Variable, Type> model,
-      {Reachability reachable}) {
+      Reference<Variable, Type> reference, VariableModel<Variable, Type> model,
+      {Reachability? reachable}) {
     reachable ??= this.reachable;
     Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
         new Map<Variable, VariableModel<Variable, Type>>.from(variableInfo);
-    newVariableInfo[variable] = model;
+    reference.storeInfo(newVariableInfo, model);
     return new FlowModel<Variable, Type>.withInfo(reachable, newVariableInfo);
   }
 
@@ -1707,13 +2060,14 @@
   /// are kept only if they are common to both input states; if a variable is
   /// promoted to one type in one state and a subtype in the other state, the
   /// less specific type promotion is kept.
-  static FlowModel<Variable, Type> join<Variable, Type>(
+  static FlowModel<Variable, Type>
+      join<Variable extends Object, Type extends Object>(
     TypeOperations<Variable, Type> typeOperations,
-    FlowModel<Variable, Type> first,
-    FlowModel<Variable, Type> second,
+    FlowModel<Variable, Type>? first,
+    FlowModel<Variable, Type>? second,
     Map<Variable, VariableModel<Variable, Type>> emptyVariableMap,
   ) {
-    if (first == null) return second;
+    if (first == null) return second!;
     if (second == null) return first;
 
     assert(identical(first.reachable.parent, second.reachable.parent));
@@ -1739,7 +2093,7 @@
   /// Joins two "variable info" maps.  See [join] for details.
   @visibleForTesting
   static Map<Variable, VariableModel<Variable, Type>>
-      joinVariableInfo<Variable, Type>(
+      joinVariableInfo<Variable extends Object, Type extends Object>(
     TypeOperations<Variable, Type> typeOperations,
     Map<Variable, VariableModel<Variable, Type>> first,
     Map<Variable, VariableModel<Variable, Type>> second,
@@ -1757,7 +2111,7 @@
     for (MapEntry<Variable, VariableModel<Variable, Type>> entry
         in first.entries) {
       Variable variable = entry.key;
-      VariableModel<Variable, Type> secondModel = second[variable];
+      VariableModel<Variable, Type>? secondModel = second[variable];
       if (secondModel == null) {
         alwaysFirst = false;
       } else {
@@ -1778,13 +2132,14 @@
 
   /// Models the result of joining the flow models [first] and [second] at the
   /// merge of two control flow paths.
-  static FlowModel<Variable, Type> merge<Variable, Type>(
+  static FlowModel<Variable, Type>
+      merge<Variable extends Object, Type extends Object>(
     TypeOperations<Variable, Type> typeOperations,
-    FlowModel<Variable, Type> first,
-    FlowModel<Variable, Type> second,
+    FlowModel<Variable, Type>? first,
+    FlowModel<Variable, Type>? second,
     Map<Variable, VariableModel<Variable, Type>> emptyVariableMap,
   ) {
-    if (first == null) return second.unsplit();
+    if (first == null) return second!.unsplit();
     if (second == null) return first.unsplit();
 
     assert(identical(first.reachable.parent, second.reachable.parent));
@@ -1809,11 +2164,12 @@
 
   /// Creates a new [FlowModel] object, unless it is equivalent to either
   /// [first] or [second], in which case one of those objects is re-used.
-  static FlowModel<Variable, Type> _identicalOrNew<Variable, Type>(
-      FlowModel<Variable, Type> first,
-      FlowModel<Variable, Type> second,
-      Reachability newReachable,
-      Map<Variable, VariableModel<Variable, Type>> newVariableInfo) {
+  static FlowModel<Variable, Type>
+      _identicalOrNew<Variable extends Object, Type extends Object>(
+          FlowModel<Variable, Type> first,
+          FlowModel<Variable, Type> second,
+          Reachability newReachable,
+          Map<Variable, VariableModel<Variable, Type>> newVariableInfo) {
     if (first.reachable == newReachable &&
         identical(first.variableInfo, newVariableInfo)) {
       return first;
@@ -1831,7 +2187,7 @@
   ///
   /// The equivalence check is shallow; if two variables' models are not
   /// identical, we return `false`.
-  static bool _variableInfosEqual<Variable, Type>(
+  static bool _variableInfosEqual<Variable extends Object, Type extends Object>(
       Map<Variable, VariableModel<Variable, Type>> p1,
       Map<Variable, VariableModel<Variable, Type>> p2) {
     if (p1.length != p2.length) return false;
@@ -1839,7 +2195,7 @@
     for (MapEntry<Variable, VariableModel<Variable, Type>> entry
         in p1.entries) {
       VariableModel<Variable, Type> p1Value = entry.value;
-      VariableModel<Variable, Type> p2Value = p2[entry.key];
+      VariableModel<Variable, Type>? p2Value = p2[entry.key];
       if (!identical(p1Value, p2Value)) {
         return false;
       }
@@ -1863,7 +2219,7 @@
   /// if there is no checkpoint.  Reachabilities form a tree structure that
   /// mimics the control flow of the code being analyzed, so this is called the
   /// "parent".
-  final Reachability parent;
+  final Reachability? parent;
 
   /// Whether this point in the source code is considered reachable from the
   /// most recent checkpoint.
@@ -1873,7 +2229,11 @@
   /// beginning of the function being analyzed.
   final bool overallReachable;
 
-  Reachability._(this.parent, this.locallyReachable, this.overallReachable) {
+  /// The number of `parent` links between this node and [initial].
+  final int depth;
+
+  Reachability._(this.parent, this.locallyReachable, this.overallReachable)
+      : depth = parent == null ? 0 : parent.depth + 1 {
     assert(overallReachable ==
         (locallyReachable && (parent?.overallReachable ?? true)));
   }
@@ -1881,7 +2241,30 @@
   const Reachability._initial()
       : parent = null,
         locallyReachable = true,
-        overallReachable = true;
+        overallReachable = true,
+        depth = 0;
+
+  /// Updates `this` reachability to account for the reachability of [base].
+  ///
+  /// This is the reachability component of the algorithm in
+  /// [FlowModel.rebaseForward].
+  Reachability rebaseForward(Reachability base) {
+    // If [base] is not reachable, then the result is not reachable.
+    if (!base.locallyReachable) return base;
+    // If any of the reachability nodes between `this` and its common ancestor
+    // with [base] are locally unreachable, that means that there was an exit in
+    // the flow control path from the point at which `this` and [base] diverged
+    // up to the current point of `this`; therefore we want to mark [base] as
+    // unreachable.
+    Reachability? ancestor = commonAncestor(this, base);
+    for (Reachability? self = this;
+        self != null && !identical(self, ancestor);
+        self = self.parent) {
+      if (!self.locallyReachable) return base.setUnreachable();
+    }
+    // Otherwise, the result is as reachable as [base] was.
+    return base;
+  }
 
   /// Returns a reachability with the same checkpoint as `this`, but where the
   /// current point in the program is considered locally unreachable.
@@ -1898,7 +2281,7 @@
   @override
   String toString() {
     List<bool> values = [];
-    for (Reachability node = this; node != null; node = node.parent) {
+    for (Reachability? node = this; node != null; node = node.parent) {
       values.add(node.locallyReachable);
     }
     return '[${values.join(', ')}]';
@@ -1908,12 +2291,30 @@
   /// the same notion of reachability relative to the previous two checkpoints.
   Reachability unsplit() {
     if (locallyReachable) {
-      return parent;
+      return parent!;
     } else {
-      return parent.setUnreachable();
+      return parent!.setUnreachable();
     }
   }
 
+  /// Finds the common ancestor node of [r1] and [r2], if any such node exists;
+  /// otherwise `null`.  If [r1] and [r2] are the same node, that node is
+  /// returned.
+  static Reachability? commonAncestor(Reachability? r1, Reachability? r2) {
+    if (r1 == null || r2 == null) return null;
+    while (r1!.depth > r2.depth) {
+      r1 = r1.parent!;
+    }
+    while (r2!.depth > r1.depth) {
+      r2 = r2.parent!;
+    }
+    while (!identical(r1, r2)) {
+      r1 = r1!.parent;
+      r2 = r2!.parent;
+    }
+    return r1;
+  }
+
   /// Combines two reachabilities (both of which must be based on the same
   /// checkpoint), where the code is considered reachable from the checkpoint
   /// iff either argument is reachable from the checkpoint.
@@ -1943,6 +2344,69 @@
   }
 }
 
+/// Abstract base class representing a reference to a storage location that
+/// might be of interest to flow analysis to track.  This could be a variable,
+/// `this`, or the result of a property access on some other reference.
+///
+/// Note that only variables can undergo promotion, but flow analysis may track
+/// other references in order to give useful error messages to the user about
+/// why promotion did not occur.
+@visibleForTesting
+abstract class Reference<Variable extends Object, Type extends Object> {
+  /// Retrieves the declared type of this reference.  This is used as the
+  /// starting point for promotions.
+  Type getDeclaredType(TypeOperations<Variable, Type> typeOperations);
+
+  /// Gets the info for this reference, creating it if it doesn't exist.
+  VariableModel<Variable, Type> getInfo(
+          Map<Variable, VariableModel<Variable, Type>> variableInfo) =>
+      _getInfo(variableInfo) ?? new VariableModel<Variable, Type>.fresh();
+
+  /// Stores info for this reference in [variableInfo].
+  void storeInfo(Map<Variable, VariableModel<Variable, Type>> variableInfo,
+      VariableModel<Variable, Type> variableModel);
+
+  /// Gets the info for this reference, or `null` if it doesn't exist.
+  VariableModel<Variable, Type>? _getInfo(
+      Map<Variable, VariableModel<Variable, Type>> variableInfo);
+}
+
+/// Data structure representing a unique value that a variable might take on
+/// during execution of the code being analyzed.  SSA nodes are immutable (so
+/// they can be safety shared among data structures) and have identity (so that
+/// it is possible to tell whether one SSA node is the same as another).
+///
+/// This is similar to the nodes used in traditional single assignment analysis
+/// (https://en.wikipedia.org/wiki/Static_single_assignment_form) except that it
+/// does not store a complete IR of the code being analyzed.
+@visibleForTesting
+class SsaNode<Variable extends Object, Type extends Object> {
+  /// Expando mapping SSA nodes to debug ids.  Only used by `toString`.
+  static final Expando<int> _debugIds = new Expando<int>();
+
+  static int _nextDebugId = 0;
+
+  /// Flow analysis information was associated with the expression that
+  /// produced the value represented by this SSA node, if it was non-trivial.
+  /// This can be used at a later time to perform promotions if the value is
+  /// used in a control flow construct.
+  ///
+  /// We don't bother storing flow analysis information if it's trivial (see
+  /// [_TrivialExpressionInfo]) because such information does not lead to
+  /// promotions.
+  @visibleForTesting
+  final ExpressionInfo<Variable, Type>? expressionInfo;
+
+  SsaNode(this.expressionInfo);
+
+  @override
+  String toString() {
+    SsaNode self = this; // Work around #44475
+    int id = _debugIds[self] ??= _nextDebugId++;
+    return 'ssa$id';
+  }
+}
+
 /// Enum representing the different classifications of types that can be
 /// returned by [TypeOperations.classifyType].
 enum TypeClassification {
@@ -1958,7 +2422,7 @@
 }
 
 /// Operations on types, abstracted from concrete type interfaces.
-abstract class TypeOperations<Variable, Type> {
+abstract class TypeOperations<Variable extends Object, Type extends Object> {
   /// Classifies the given type into one of the three categories defined by
   /// the [TypeClassification] enum.
   TypeClassification classifyType(Type type);
@@ -1973,8 +2437,8 @@
   ///
   /// It is not expected that any implementation would override this except for
   /// the migration engine.
-  bool forcePromotion(Type to, Type from, List<Type> promotedTypes,
-          List<Type> newPromotedTypes) =>
+  bool forcePromotion(Type to, Type from, List<Type>? promotedTypes,
+          List<Type>? newPromotedTypes) =>
       false;
 
   /// Determines whether the given [type] is equivalent to the `Never` type.
@@ -2002,13 +2466,13 @@
   ///
   /// It is not expected that any implementation would override this except for
   /// the migration engine.
-  List<Type> refinePromotedTypes(
-          List<Type> chain1, List<Type> chain2, List<Type> promotedTypes) =>
+  List<Type>? refinePromotedTypes(
+          List<Type>? chain1, List<Type>? chain2, List<Type>? promotedTypes) =>
       promotedTypes;
 
   /// Tries to promote to the first type from the second type, and returns the
   /// promoted type if it succeeds, otherwise null.
-  Type tryPromoteToType(Type to, Type from);
+  Type? tryPromoteToType(Type to, Type from);
 
   /// Return the static type of the given [variable].
   Type variableType(Variable variable);
@@ -2021,11 +2485,11 @@
 /// Instances of this class are immutable, so the methods below that "update"
 /// the state actually leave `this` unchanged and return a new state object.
 @visibleForTesting
-class VariableModel<Variable, Type> {
+class VariableModel<Variable extends Object, Type extends Object> {
   /// Sequence of types that the variable has been promoted to, where each
   /// element of the sequence is a subtype of the previous.  Null if the
   /// variable hasn't been promoted.
-  final List<Type> promotedTypes;
+  final List<Type>? promotedTypes;
 
   /// List of types that the variable has been tested against in all code paths
   /// leading to the given point in the source code.
@@ -2037,18 +2501,29 @@
   /// Indicates whether the variable is unassigned.
   final bool unassigned;
 
-  /// Indicates whether the variable has been write captured.
-  final bool writeCaptured;
+  /// SSA node associated with this variable.  Every time the variable's value
+  /// potentially changes (either through an explicit write or a join with a
+  /// control flow path that contains a write), this field is updated to point
+  /// to a fresh node.  Thus, it can be used to detect whether a variable's
+  /// value has changed since a time in the past.
+  ///
+  /// `null` if the variable has been write captured.
+  final SsaNode<Variable, Type>? ssaNode;
 
-  VariableModel(this.promotedTypes, this.tested, this.assigned, this.unassigned,
-      this.writeCaptured) {
+  VariableModel(
+      {required this.promotedTypes,
+      required this.tested,
+      required this.assigned,
+      required this.unassigned,
+      required this.ssaNode}) {
     assert(!(assigned && unassigned),
         "Can't be both definitely assigned and unassigned");
-    assert(promotedTypes == null || promotedTypes.isNotEmpty);
+    assert(promotedTypes == null || promotedTypes!.isNotEmpty);
     assert(!writeCaptured || promotedTypes == null,
         "Write-captured variables can't be promoted");
     assert(!(writeCaptured && unassigned),
         "Write-captured variables can't be definitely unassigned");
+    // ignore:unnecessary_null_comparison
     assert(tested != null);
   }
 
@@ -2058,16 +2533,23 @@
       : promotedTypes = null,
         tested = const [],
         unassigned = !assigned,
-        writeCaptured = false;
+        ssaNode = new SsaNode<Variable, Type>(null);
+
+  /// Indicates whether the variable has been write captured.
+  bool get writeCaptured => ssaNode == null;
 
   /// Returns a new [VariableModel] in which any promotions present have been
   /// dropped, and the variable has been marked as "not unassigned".
+  ///
+  /// Used by [conservativeJoin] to update the state of variables at the top of
+  /// loops whose bodies write to them.
   VariableModel<Variable, Type> discardPromotionsAndMarkNotUnassigned() {
-    if (promotedTypes == null && !unassigned) {
-      return this;
-    }
     return new VariableModel<Variable, Type>(
-        null, tested, assigned, false, writeCaptured);
+        promotedTypes: null,
+        tested: tested,
+        assigned: assigned,
+        unassigned: false,
+        ssaNode: writeCaptured ? null : new SsaNode<Variable, Type>(null));
   }
 
   /// Returns an updated model reflect a control path that is known to have
@@ -2077,8 +2559,14 @@
       TypeOperations<Variable, Type> typeOperations,
       VariableModel<Variable, Type> otherModel,
       bool unsafe) {
-    List<Type> thisPromotedTypes = promotedTypes;
-    List<Type> otherPromotedTypes = otherModel.promotedTypes;
+    if (allowLocalBooleanVarsToPromoteByDefault) {
+      // TODO(paulberry): when we hardcode
+      // allowLocalBooleanVarsToPromoteByDefault to `true`, we should remove
+      // this method entirely.
+      throw new StateError('This method should not be called anymore');
+    }
+    List<Type>? thisPromotedTypes = promotedTypes;
+    List<Type>? otherPromotedTypes = otherModel.promotedTypes;
     bool newAssigned = assigned || otherModel.assigned;
     // The variable can only be unassigned in this state if it was also
     // unassigned in the other state or if the other state didn't complete
@@ -2101,7 +2589,7 @@
     //
     bool newUnassigned = unassigned && otherModel.unassigned;
     bool newWriteCaptured = writeCaptured || otherModel.writeCaptured;
-    List<Type> newPromotedTypes;
+    List<Type>? newPromotedTypes;
     if (newWriteCaptured) {
       // Write-captured variables can't be promoted
       newPromotedTypes = null;
@@ -2109,37 +2597,17 @@
       // There was an assignment to the variable in the "this" path, so none of
       // the promotions from the "other" path can be used.
       newPromotedTypes = thisPromotedTypes;
-    } else if (otherPromotedTypes == null) {
-      // The other promotion chain contributes nothing so we just use this
-      // promotion chain directly.
-      newPromotedTypes = thisPromotedTypes;
-    } else if (thisPromotedTypes == null) {
-      // This promotion chain contributes nothing so we just use the other
-      // promotion chain directly.
-      newPromotedTypes = otherPromotedTypes;
     } else {
-      // Start with otherPromotedTypes and apply each of the promotions in
-      // thisPromotedTypes (discarding any that don't follow the ordering
-      // invariant)
-      newPromotedTypes = otherPromotedTypes;
-      Type otherPromotedType = otherPromotedTypes.last;
-      for (int i = 0; i < thisPromotedTypes.length; i++) {
-        Type nextType = thisPromotedTypes[i];
-        if (typeOperations.isSubtypeOf(nextType, otherPromotedType) &&
-            !typeOperations.isSameType(nextType, otherPromotedType)) {
-          newPromotedTypes = otherPromotedTypes.toList()
-            ..addAll(thisPromotedTypes.skip(i));
-          break;
-        }
-      }
+      newPromotedTypes = rebasePromotedTypes(
+          typeOperations, thisPromotedTypes, otherPromotedTypes);
     }
     return _identicalOrNew(this, otherModel, newPromotedTypes, tested,
-        newAssigned, newUnassigned, newWriteCaptured);
+        newAssigned, newUnassigned, newWriteCaptured ? null : ssaNode);
   }
 
   @override
   String toString() {
-    List<String> parts = [];
+    List<String> parts = [ssaNode.toString()];
     if (promotedTypes != null) {
       parts.add('promotedTypes: $promotedTypes');
     }
@@ -2160,14 +2628,21 @@
 
   /// Returns a new [VariableModel] reflecting the fact that the variable was
   /// just written to.
-  VariableModel<Variable, Type> write(Variable variable, Type writtenType,
-      TypeOperations<Variable, Type> typeOperations) {
+  VariableModel<Variable, Type> write(
+      Variable variable,
+      Type writtenType,
+      TypeOperations<Variable, Type> typeOperations,
+      SsaNode<Variable, Type> newSsaNode) {
     if (writeCaptured) {
       return new VariableModel<Variable, Type>(
-          promotedTypes, tested, true, false, writeCaptured);
+          promotedTypes: promotedTypes,
+          tested: tested,
+          assigned: true,
+          unassigned: false,
+          ssaNode: null);
     }
 
-    List<Type> newPromotedTypes = _demoteViaAssignment(
+    List<Type>? newPromotedTypes = _demoteViaAssignment(
       writtenType,
       typeOperations,
     );
@@ -2175,7 +2650,14 @@
     Type declaredType = typeOperations.variableType(variable);
     newPromotedTypes = _tryPromoteToTypeOfInterest(
         typeOperations, declaredType, newPromotedTypes, writtenType);
-    if (identical(promotedTypes, newPromotedTypes) && assigned) return this;
+    if (identical(promotedTypes, newPromotedTypes) && assigned) {
+      return new VariableModel<Variable, Type>(
+          promotedTypes: promotedTypes,
+          tested: tested,
+          assigned: assigned,
+          unassigned: unassigned,
+          ssaNode: newSsaNode);
+    }
 
     List<Type> newTested;
     if (newPromotedTypes == null && promotedTypes != null) {
@@ -2185,20 +2667,29 @@
     }
 
     return new VariableModel<Variable, Type>(
-        newPromotedTypes, newTested, true, false, writeCaptured);
+        promotedTypes: newPromotedTypes,
+        tested: newTested,
+        assigned: true,
+        unassigned: false,
+        ssaNode: newSsaNode);
   }
 
   /// Returns a new [VariableModel] reflecting the fact that the variable has
   /// been write-captured.
   VariableModel<Variable, Type> writeCapture() {
     return new VariableModel<Variable, Type>(
-        null, const [], assigned, false, true);
+        promotedTypes: null,
+        tested: const [],
+        assigned: assigned,
+        unassigned: false,
+        ssaNode: null);
   }
 
-  List<Type> _demoteViaAssignment(
+  List<Type>? _demoteViaAssignment(
     Type writtenType,
     TypeOperations<Variable, Type> typeOperations,
   ) {
+    List<Type>? promotedTypes = this.promotedTypes;
     if (promotedTypes == null) {
       return null;
     }
@@ -2225,10 +2716,10 @@
   ///
   /// Note that since promotion chains are considered immutable, if promotion
   /// is required, a new promotion chain will be created and returned.
-  List<Type> _tryPromoteToTypeOfInterest(
+  List<Type>? _tryPromoteToTypeOfInterest(
       TypeOperations<Variable, Type> typeOperations,
       Type declaredType,
-      List<Type> promotedTypes,
+      List<Type>? promotedTypes,
       Type writtenType) {
     assert(!writeCaptured);
 
@@ -2240,10 +2731,10 @@
     // Figure out if we have any promotion candidates (types that are a
     // supertype of writtenType and a proper subtype of the currently-promoted
     // type).  If at any point we find an exact match, we take it immediately.
-    Type currentlyPromotedType = promotedTypes?.last;
+    Type? currentlyPromotedType = promotedTypes?.last;
 
-    List<Type> result;
-    List<Type> candidates = null;
+    List<Type>? result;
+    List<Type>? candidates = null;
 
     void handleTypeOfInterest(Type type) {
       // The written type must be a subtype of the type.
@@ -2272,8 +2763,8 @@
       }
 
       // Add only unique candidates.
-      if (!_typeListContains(typeOperations, candidates, type)) {
-        candidates.add(type);
+      if (!_typeListContains(typeOperations, candidates!, type)) {
+        candidates!.add(type);
         return;
       }
     }
@@ -2284,7 +2775,7 @@
     if (!typeOperations.isSameType(declaredTypeNonNull, declaredType)) {
       handleTypeOfInterest(declaredTypeNonNull);
       if (result != null) {
-        return result;
+        return result!;
       }
     }
 
@@ -2293,27 +2784,28 @@
 
       handleTypeOfInterest(type);
       if (result != null) {
-        return result;
+        return result!;
       }
 
       Type typeNonNull = typeOperations.promoteToNonNull(type);
       if (!typeOperations.isSameType(typeNonNull, type)) {
         handleTypeOfInterest(typeNonNull);
         if (result != null) {
-          return result;
+          return result!;
         }
       }
     }
 
-    if (candidates != null) {
+    List<Type>? candidates2 = candidates;
+    if (candidates2 != null) {
       // Figure out if we have a unique promotion candidate that's a subtype
       // of all the others.
-      Type promoted;
+      Type? promoted;
       outer:
-      for (int i = 0; i < candidates.length; i++) {
-        for (int j = 0; j < candidates.length; j++) {
+      for (int i = 0; i < candidates2.length; i++) {
+        for (int j = 0; j < candidates2.length; j++) {
           if (j == i) continue;
-          if (!typeOperations.isSubtypeOf(candidates[i], candidates[j])) {
+          if (!typeOperations.isSubtypeOf(candidates2[i], candidates2[j])) {
             // Not a subtype of all the others.
             continue outer;
           }
@@ -2322,7 +2814,7 @@
           // Not unique.  Do not promote.
           return promotedTypes;
         } else {
-          promoted = candidates[i];
+          promoted = candidates2[i];
         }
       }
       if (promoted != null) {
@@ -2339,22 +2831,28 @@
   /// are consistently treated as "of interest" in code that follows the loop,
   /// regardless of the type of loop.
   @visibleForTesting
-  static VariableModel<Variable, Type> inheritTested<Variable, Type>(
-      TypeOperations<Variable, Type> typeOperations,
-      VariableModel<Variable, Type> model,
-      List<Type> tested) {
+  static VariableModel<Variable, Type>
+      inheritTested<Variable extends Object, Type extends Object>(
+          TypeOperations<Variable, Type> typeOperations,
+          VariableModel<Variable, Type> model,
+          List<Type> tested) {
     List<Type> newTested = joinTested(tested, model.tested, typeOperations);
     if (identical(newTested, model.tested)) return model;
-    return new VariableModel<Variable, Type>(model.promotedTypes, newTested,
-        model.assigned, model.unassigned, model.writeCaptured);
+    return new VariableModel<Variable, Type>(
+        promotedTypes: model.promotedTypes,
+        tested: newTested,
+        assigned: model.assigned,
+        unassigned: model.unassigned,
+        ssaNode: model.ssaNode);
   }
 
   /// Joins two variable models.  See [FlowModel.join] for details.
-  static VariableModel<Variable, Type> join<Variable, Type>(
-      TypeOperations<Variable, Type> typeOperations,
-      VariableModel<Variable, Type> first,
-      VariableModel<Variable, Type> second) {
-    List<Type> newPromotedTypes = joinPromotedTypes(
+  static VariableModel<Variable, Type>
+      join<Variable extends Object, Type extends Object>(
+          TypeOperations<Variable, Type> typeOperations,
+          VariableModel<Variable, Type> first,
+          VariableModel<Variable, Type> second) {
+    List<Type>? newPromotedTypes = joinPromotedTypes(
         first.promotedTypes, second.promotedTypes, typeOperations);
     newPromotedTypes = typeOperations.refinePromotedTypes(
         first.promotedTypes, second.promotedTypes, newPromotedTypes);
@@ -2364,16 +2862,24 @@
     List<Type> newTested = newWriteCaptured
         ? const []
         : joinTested(first.tested, second.tested, typeOperations);
+    SsaNode<Variable, Type>? newSsaNode = newWriteCaptured
+        ? null
+        : first.ssaNode == second.ssaNode
+            ? first.ssaNode
+            : new SsaNode<Variable, Type>(null);
     return _identicalOrNew(first, second, newPromotedTypes, newTested,
-        newAssigned, newUnassigned, newWriteCaptured);
+        newAssigned, newUnassigned, newWriteCaptured ? null : newSsaNode);
   }
 
   /// Performs the portion of the "join" algorithm that applies to promotion
   /// chains.  Briefly, we intersect given chains.  The chains are totally
   /// ordered subsets of a global partial order.  Their intersection is a
   /// subset of each, and as such is also totally ordered.
-  static List<Type> joinPromotedTypes<Variable, Type>(List<Type> chain1,
-      List<Type> chain2, TypeOperations<Variable, Type> typeOperations) {
+  static List<Type>?
+      joinPromotedTypes<Variable extends Object, Type extends Object>(
+          List<Type>? chain1,
+          List<Type>? chain2,
+          TypeOperations<Variable, Type> typeOperations) {
     if (chain1 == null) return chain1;
     if (chain2 == null) return chain2;
 
@@ -2381,7 +2887,7 @@
     int index2 = 0;
     bool skipped1 = false;
     bool skipped2 = false;
-    List<Type> result;
+    List<Type>? result;
     while (index1 < chain1.length && index2 < chain2.length) {
       Type type1 = chain1[index1];
       Type type2 = chain2[index2];
@@ -2416,8 +2922,10 @@
   /// - The sense of equality for the union operation is determined by
   ///   [TypeOperations.isSameType].
   /// - The types of interests lists are considered immutable.
-  static List<Type> joinTested<Variable, Type>(List<Type> types1,
-      List<Type> types2, TypeOperations<Variable, Type> typeOperations) {
+  static List<Type> joinTested<Variable extends Object, Type extends Object>(
+      List<Type> types1,
+      List<Type> types2,
+      TypeOperations<Variable, Type> typeOperations) {
     // Ensure that types1 is the shorter list.
     if (types1.length > types2.length) {
       List<Type> tmp = types1;
@@ -2446,47 +2954,94 @@
     return types2;
   }
 
-  static List<Type> _addToPromotedTypes<Type>(
-          List<Type> promotedTypes, Type promoted) =>
+  /// Forms a promotion chain by starting with [basePromotedTypes] and applying
+  /// promotions from [thisPromotedTypes] to it, to the extent possible without
+  /// violating the usual ordering invariant (each promoted type must be a
+  /// subtype of the previous).
+  ///
+  /// In degenerate cases, the returned chain will be identical to
+  /// [thisPromotedTypes] or [basePromotedTypes] (to make it easier for the
+  /// caller to detect when data structures may be re-used).
+  static List<Type>? rebasePromotedTypes<Type extends Object>(
+      TypeOperations<Object, Type> typeOperations,
+      List<Type>? thisPromotedTypes,
+      List<Type>? basePromotedTypes) {
+    if (basePromotedTypes == null) {
+      // The base promotion chain contributes nothing so we just use this
+      // promotion chain directly.
+      return thisPromotedTypes;
+    } else if (thisPromotedTypes == null) {
+      // This promotion chain contributes nothing so we just use the base
+      // promotion chain directly.
+      return basePromotedTypes;
+    } else {
+      // Start with basePromotedTypes and apply each of the promotions in
+      // thisPromotedTypes (discarding any that don't follow the ordering
+      // invariant)
+      List<Type> newPromotedTypes = basePromotedTypes;
+      Type otherPromotedType = basePromotedTypes.last;
+      for (int i = 0; i < thisPromotedTypes.length; i++) {
+        Type nextType = thisPromotedTypes[i];
+        if (typeOperations.isSubtypeOf(nextType, otherPromotedType) &&
+            !typeOperations.isSameType(nextType, otherPromotedType)) {
+          newPromotedTypes = basePromotedTypes.toList()
+            ..addAll(thisPromotedTypes.skip(i));
+          break;
+        }
+      }
+      return newPromotedTypes;
+    }
+  }
+
+  static List<Type> _addToPromotedTypes<Type extends Object>(
+          List<Type>? promotedTypes, Type promoted) =>
       promotedTypes == null
           ? [promoted]
           : (promotedTypes.toList()..add(promoted));
 
-  static List<Type> _addTypeToUniqueList<Variable, Type>(List<Type> types,
-      Type newType, TypeOperations<Variable, Type> typeOperations) {
+  static List<Type>
+      _addTypeToUniqueList<Variable extends Object, Type extends Object>(
+          List<Type> types,
+          Type newType,
+          TypeOperations<Variable, Type> typeOperations) {
     if (_typeListContains(typeOperations, types, newType)) return types;
     return new List<Type>.from(types)..add(newType);
   }
 
   /// Creates a new [VariableModel] object, unless it is equivalent to either
   /// [first] or [second], in which case one of those objects is re-used.
-  static VariableModel<Variable, Type> _identicalOrNew<Variable, Type>(
-      VariableModel<Variable, Type> first,
-      VariableModel<Variable, Type> second,
-      List<Type> newPromotedTypes,
-      List<Type> newTested,
-      bool newAssigned,
-      bool newUnassigned,
-      bool newWriteCaptured) {
+  static VariableModel<Variable, Type>
+      _identicalOrNew<Variable extends Object, Type extends Object>(
+          VariableModel<Variable, Type> first,
+          VariableModel<Variable, Type> second,
+          List<Type>? newPromotedTypes,
+          List<Type> newTested,
+          bool newAssigned,
+          bool newUnassigned,
+          SsaNode<Variable, Type>? newSsaNode) {
     if (identical(first.promotedTypes, newPromotedTypes) &&
         identical(first.tested, newTested) &&
         first.assigned == newAssigned &&
         first.unassigned == newUnassigned &&
-        first.writeCaptured == newWriteCaptured) {
+        first.ssaNode == newSsaNode) {
       return first;
     } else if (identical(second.promotedTypes, newPromotedTypes) &&
         identical(second.tested, newTested) &&
         second.assigned == newAssigned &&
         second.unassigned == newUnassigned &&
-        second.writeCaptured == newWriteCaptured) {
+        second.ssaNode == newSsaNode) {
       return second;
     } else {
-      return new VariableModel<Variable, Type>(newPromotedTypes, newTested,
-          newAssigned, newUnassigned, newWriteCaptured);
+      return new VariableModel<Variable, Type>(
+          promotedTypes: newPromotedTypes,
+          tested: newTested,
+          assigned: newAssigned,
+          unassigned: newUnassigned,
+          ssaNode: newSsaNode);
     }
   }
 
-  static bool _typeListContains<Variable, Type>(
+  static bool _typeListContains<Variable extends Object, Type extends Object>(
       TypeOperations<Variable, Type> typeOperations,
       List<Type> list,
       Type searchType) {
@@ -2497,10 +3052,37 @@
   }
 }
 
+/// Specialization of [Reference] representing a reference to a local variable
+/// (or function parameter).
+@visibleForTesting
+class VariableReference<Variable extends Object, Type extends Object>
+    extends Reference<Variable, Type> {
+  /// The variable being referred to.
+  final Variable variable;
+
+  VariableReference(this.variable);
+
+  @override
+  Type getDeclaredType(TypeOperations<Variable, Type> typeOperations) =>
+      typeOperations.variableType(variable);
+
+  @override
+  void storeInfo(Map<Variable, VariableModel<Variable, Type>> variableInfo,
+      VariableModel<Variable, Type> variableModel) {
+    variableInfo[variable] = variableModel;
+  }
+
+  @override
+  VariableModel<Variable, Type>? _getInfo(
+          Map<Variable, VariableModel<Variable, Type>> variableInfo) =>
+      variableInfo[variable];
+}
+
 /// [_FlowContext] representing an assert statement or assert initializer.
-class _AssertContext<Variable, Type> extends _SimpleContext<Variable, Type> {
+class _AssertContext<Variable extends Object, Type extends Object>
+    extends _SimpleContext<Variable, Type> {
   /// Flow models associated with the condition being asserted.
-  ExpressionInfo<Variable, Type> _conditionInfo;
+  ExpressionInfo<Variable, Type>? _conditionInfo;
 
   _AssertContext(FlowModel<Variable, Type> previous) : super(previous);
 
@@ -2512,9 +3094,10 @@
 /// [_FlowContext] representing a language construct that branches on a boolean
 /// condition, such as an `if` statement, conditional expression, or a logical
 /// binary operator.
-class _BranchContext<Variable, Type> extends _FlowContext {
+class _BranchContext<Variable extends Object, Type extends Object>
+    extends _FlowContext {
   /// Flow models associated with the condition being branched on.
-  final ExpressionInfo<Variable, Type> _conditionInfo;
+  final ExpressionInfo<Variable, Type>? _conditionInfo;
 
   _BranchContext(this._conditionInfo);
 
@@ -2524,14 +3107,15 @@
 
 /// [_FlowContext] representing a language construct that can be targeted by
 /// `break` or `continue` statements, such as a loop or switch statement.
-class _BranchTargetContext<Variable, Type> extends _FlowContext {
+class _BranchTargetContext<Variable extends Object, Type extends Object>
+    extends _FlowContext {
   /// Accumulated flow model for all `break` statements seen so far, or `null`
   /// if no `break` statements have been seen yet.
-  FlowModel<Variable, Type> _breakModel;
+  FlowModel<Variable, Type>? _breakModel;
 
   /// Accumulated flow model for all `continue` statements seen so far, or
   /// `null` if no `continue` statements have been seen yet.
-  FlowModel<Variable, Type> _continueModel;
+  FlowModel<Variable, Type>? _continueModel;
 
   /// The reachability checkpoint associated with this loop or switch statement.
   /// When analyzing deeply nested `break` and `continue` statements, their flow
@@ -2547,11 +3131,11 @@
 }
 
 /// [_FlowContext] representing a conditional expression.
-class _ConditionalContext<Variable, Type>
+class _ConditionalContext<Variable extends Object, Type extends Object>
     extends _BranchContext<Variable, Type> {
   /// Flow models associated with the value of the conditional expression in the
   /// circumstance where the "then" branch is taken.
-  ExpressionInfo<Variable, Type> _thenInfo;
+  ExpressionInfo<Variable, Type>? _thenInfo;
 
   _ConditionalContext(ExpressionInfo<Variable, Type> conditionInfo)
       : super(conditionInfo);
@@ -2562,12 +3146,17 @@
 }
 
 /// [_FlowContext] representing an equality comparison using `==` or `!=`.
-class _EqualityOpContext<Variable, Type> extends _BranchContext {
+class _EqualityOpContext<Variable extends Object, Type extends Object>
+    extends _BranchContext<Variable, Type> {
   /// The type of the expression on the LHS of `==` or `!=`.
   final Type _leftOperandType;
 
-  _EqualityOpContext(
-      ExpressionInfo<Variable, Type> conditionInfo, this._leftOperandType)
+  /// If the LHS of `==` or `!=` is a reference, the thing being referred to.
+  /// Otherwise `null`.
+  final Reference<Variable, Type>? _leftOperandReference;
+
+  _EqualityOpContext(ExpressionInfo<Variable, Type>? conditionInfo,
+      this._leftOperandType, this._leftOperandReference)
       : super(conditionInfo);
 
   @override
@@ -2576,8 +3165,9 @@
       '$_leftOperandType)';
 }
 
-class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
-    Type> implements FlowAnalysis<Node, Statement, Expression, Variable, Type> {
+class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
+        Expression extends Object, Variable extends Object, Type extends Object>
+    implements FlowAnalysis<Node, Statement, Expression, Variable, Type> {
   /// The [TypeOperations], used to access types, and check subtyping.
   final TypeOperations<Variable, Type> typeOperations;
 
@@ -2591,22 +3181,41 @@
   final Map<Statement, _BranchTargetContext<Variable, Type>>
       _statementToContext = {};
 
-  FlowModel<Variable, Type> _current;
+  late FlowModel<Variable, Type> _current;
 
   /// The most recently visited expression for which an [ExpressionInfo] object
   /// exists, or `null` if no expression has been visited that has a
   /// corresponding [ExpressionInfo] object.
-  Expression _expressionWithInfo;
+  Expression? _expressionWithInfo;
 
   /// If [_expressionWithInfo] is not `null`, the [ExpressionInfo] object
   /// corresponding to it.  Otherwise `null`.
-  ExpressionInfo<Variable, Type> _expressionInfo;
+  ExpressionInfo<Variable, Type>? _expressionInfo;
+
+  /// The most recently visited expression which was a reference, or `null` if
+  /// no such expression has been visited.
+  Expression? _expressionWithReference;
+
+  /// If [_expressionVariable] is not `null`, the reference corresponding to it.
+  /// Otherwise `null`.
+  Reference<Variable, Type>? _expressionReference;
 
   int _functionNestingLevel = 0;
 
   final AssignedVariables<Node, Variable> _assignedVariables;
 
-  _FlowAnalysisImpl(this.typeOperations, this._assignedVariables) {
+  /// Set this boolean to `true` to temporarily enable the feature of allowing
+  /// local boolean variables to influence promotion, for this flow analysis
+  /// session (see https://github.com/dart-lang/language/issues/1274).  Once the
+  /// top level const [allowLocalBooleanVarsToPromoteByDefault] is changed to
+  /// `true`, this field will always be `true`, so it can be safely removed.
+  final bool allowLocalBooleanVarsToPromote;
+
+  _FlowAnalysisImpl(this.typeOperations, this._assignedVariables,
+      {bool allowLocalBooleanVarsToPromote = false})
+      : allowLocalBooleanVarsToPromote =
+            allowLocalBooleanVarsToPromoteByDefault ||
+                allowLocalBooleanVarsToPromote {
     _current = new FlowModel<Variable, Type>(Reachability.initial);
   }
 
@@ -2615,15 +3224,10 @@
 
   @override
   void asExpression_end(Expression subExpression, Type type) {
-    ExpressionInfo<Variable, Type> subExpressionInfo =
-        _getExpressionInfo(subExpression);
-    Variable variable;
-    if (subExpressionInfo is _VariableReadInfo<Variable, Type>) {
-      variable = subExpressionInfo._variable;
-    } else {
-      return;
-    }
-    _current = _current.tryPromoteForTypeCast(typeOperations, variable, type);
+    Reference<Variable, Type>? reference =
+        _getExpressionReference(subExpression);
+    if (reference == null) return;
+    _current = _current.tryPromoteForTypeCast(typeOperations, reference, type);
   }
 
   @override
@@ -2645,7 +3249,7 @@
   void assert_end() {
     _AssertContext<Variable, Type> context =
         _stack.removeLast() as _AssertContext<Variable, Type>;
-    _current = _merge(context._previous, context._conditionInfo.ifTrue);
+    _current = _merge(context._previous, context._conditionInfo!.ifTrue);
   }
 
   @override
@@ -2668,7 +3272,7 @@
     _ConditionalContext<Variable, Type> context =
         _stack.last as _ConditionalContext<Variable, Type>;
     context._thenInfo = _expressionEnd(thenExpression);
-    _current = context._conditionInfo.ifFalse;
+    _current = context._conditionInfo!.ifFalse;
   }
 
   @override
@@ -2676,7 +3280,7 @@
       Expression conditionalExpression, Expression elseExpression) {
     _ConditionalContext<Variable, Type> context =
         _stack.removeLast() as _ConditionalContext<Variable, Type>;
-    ExpressionInfo<Variable, Type> thenInfo = context._thenInfo;
+    ExpressionInfo<Variable, Type> thenInfo = context._thenInfo!;
     ExpressionInfo<Variable, Type> elseInfo = _expressionEnd(elseExpression);
     _storeExpressionInfo(
         conditionalExpression,
@@ -2687,7 +3291,7 @@
   }
 
   @override
-  void conditional_thenBegin(Expression condition) {
+  void conditional_thenBegin(Expression condition, Node conditionalExpression) {
     ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
     _stack.add(new _ConditionalContext(conditionInfo));
     _current = conditionInfo.ifTrue;
@@ -2729,9 +3333,12 @@
       {bool notEqual = false}) {
     _EqualityOpContext<Variable, Type> context =
         _stack.removeLast() as _EqualityOpContext<Variable, Type>;
-    ExpressionInfo<Variable, Type> lhsInfo = context._conditionInfo;
+    ExpressionInfo<Variable, Type>? lhsInfo = context._conditionInfo;
+    Reference<Variable, Type>? lhsReference = context._leftOperandReference;
     Type leftOperandType = context._leftOperandType;
-    ExpressionInfo<Variable, Type> rhsInfo = _getExpressionInfo(rightOperand);
+    ExpressionInfo<Variable, Type>? rhsInfo = _getExpressionInfo(rightOperand);
+    Reference<Variable, Type>? rhsReference =
+        _getExpressionReference(rightOperand);
     TypeClassification leftOperandTypeClassification =
         typeOperations.classifyType(leftOperandType);
     TypeClassification rightOperandTypeClassification =
@@ -2749,42 +3356,44 @@
       // but weak mode it might produce an "equal" result.  We don't want flow
       // analysis behavior to depend on mode, so we conservatively assume that
       // either result is possible.
-    } else if (lhsInfo is _NullInfo<Variable, Type> &&
-        rhsInfo is _VariableReadInfo<Variable, Type>) {
-      assert(
-          leftOperandTypeClassification == TypeClassification.nullOrEquivalent);
+    } else if (lhsInfo is _NullInfo<Variable, Type> && rhsReference != null) {
       ExpressionInfo<Variable, Type> equalityInfo =
-          _current.tryMarkNonNullable(typeOperations, rhsInfo._variable);
-      _storeExpressionInfo(wholeExpression,
-          notEqual ? equalityInfo : ExpressionInfo.invert(equalityInfo));
-    } else if (rhsInfo is _NullInfo<Variable, Type> &&
-        lhsInfo is _VariableReadInfo<Variable, Type>) {
+          _current.tryMarkNonNullable(typeOperations, rhsReference);
+      _storeExpressionInfo(
+          wholeExpression, notEqual ? equalityInfo : equalityInfo.invert());
+    } else if (rhsInfo is _NullInfo<Variable, Type> && lhsReference != null) {
       ExpressionInfo<Variable, Type> equalityInfo =
-          _current.tryMarkNonNullable(typeOperations, lhsInfo._variable);
-      _storeExpressionInfo(wholeExpression,
-          notEqual ? equalityInfo : ExpressionInfo.invert(equalityInfo));
+          _current.tryMarkNonNullable(typeOperations, lhsReference);
+      _storeExpressionInfo(
+          wholeExpression, notEqual ? equalityInfo : equalityInfo.invert());
     }
   }
 
   @override
   void equalityOp_rightBegin(Expression leftOperand, Type leftOperandType) {
     _stack.add(new _EqualityOpContext<Variable, Type>(
-        _getExpressionInfo(leftOperand), leftOperandType));
+        _getExpressionInfo(leftOperand),
+        leftOperandType,
+        _getExpressionReference(leftOperand)));
   }
 
   @override
+  ExpressionInfo<Variable, Type>? expressionInfoForTesting(Expression target) =>
+      identical(target, _expressionWithInfo) ? _expressionInfo : null;
+
+  @override
   void finish() {
     assert(_stack.isEmpty);
     assert(_current.reachable.parent == null);
   }
 
   @override
-  void for_bodyBegin(Statement node, Expression condition) {
+  void for_bodyBegin(Statement? node, Expression? condition) {
     ExpressionInfo<Variable, Type> conditionInfo = condition == null
         ? new ExpressionInfo(_current, _current, _current.setUnreachable())
         : _expressionEnd(condition);
     _WhileContext<Variable, Type> context = new _WhileContext<Variable, Type>(
-        _current.reachable.parent, conditionInfo);
+        _current.reachable.parent!, conditionInfo);
     _stack.add(context);
     if (node != null) {
       _statementToContext[node] = context;
@@ -2804,7 +3413,7 @@
     _WhileContext<Variable, Type> context =
         _stack.removeLast() as _WhileContext<Variable, Type>;
     // Tail of the stack: falseCondition, break
-    FlowModel<Variable, Type> breakState = context._breakModel;
+    FlowModel<Variable, Type>? breakState = context._breakModel;
     FlowModel<Variable, Type> falseCondition = context._conditionInfo.ifFalse;
 
     _current = _merge(falseCondition, breakState)
@@ -2819,16 +3428,17 @@
   }
 
   @override
-  void forEach_bodyBegin(Node node, Variable loopVariable, Type writtenType) {
+  void forEach_bodyBegin(Node node, Variable? loopVariable, Type writtenType) {
     AssignedVariablesNodeInfo<Variable> info =
         _assignedVariables._getInfoForNode(node);
     _current = _current.conservativeJoin(info._written, info._captured).split();
     _SimpleStatementContext<Variable, Type> context =
         new _SimpleStatementContext<Variable, Type>(
-            _current.reachable.parent, _current);
+            _current.reachable.parent!, _current);
     _stack.add(context);
     if (loopVariable != null) {
-      _current = _current.write(loopVariable, writtenType, typeOperations);
+      _current = _current.write(loopVariable, writtenType,
+          new SsaNode<Variable, Type>(null), typeOperations);
     }
   }
 
@@ -2844,6 +3454,9 @@
     if (identical(_expressionWithInfo, oldExpression)) {
       _expressionWithInfo = newExpression;
     }
+    if (identical(_expressionWithReference, oldExpression)) {
+      _expressionWithReference = newExpression;
+    }
   }
 
   @override
@@ -2868,7 +3481,7 @@
 
   @override
   void handleBreak(Statement target) {
-    _BranchTargetContext<Variable, Type> context = _statementToContext[target];
+    _BranchTargetContext<Variable, Type>? context = _statementToContext[target];
     if (context != null) {
       context._breakModel =
           _join(context._breakModel, _current.unsplitTo(context._checkpoint));
@@ -2878,7 +3491,7 @@
 
   @override
   void handleContinue(Statement target) {
-    _BranchTargetContext<Variable, Type> context = _statementToContext[target];
+    _BranchTargetContext<Variable, Type>? context = _statementToContext[target];
     if (context != null) {
       context._continueModel = _join(
           context._continueModel, _current.unsplitTo(context._checkpoint));
@@ -2901,12 +3514,13 @@
   @override
   void ifNullExpression_rightBegin(
       Expression leftHandSide, Type leftHandSideType) {
-    ExpressionInfo<Variable, Type> lhsInfo = _getExpressionInfo(leftHandSide);
+    Reference<Variable, Type>? lhsReference =
+        _getExpressionReference(leftHandSide);
     FlowModel<Variable, Type> promoted;
     _current = _current.split();
-    if (lhsInfo is _VariableReadInfo<Variable, Type>) {
+    if (lhsReference != null) {
       ExpressionInfo<Variable, Type> promotionInfo =
-          _current.tryMarkNonNullable(typeOperations, lhsInfo._variable);
+          _current.tryMarkNonNullable(typeOperations, lhsReference);
       _current = promotionInfo.ifFalse;
       promoted = promotionInfo.ifTrue;
     } else {
@@ -2925,7 +3539,7 @@
     _IfContext<Variable, Type> context =
         _stack.last as _IfContext<Variable, Type>;
     context._afterThen = _current;
-    _current = context._conditionInfo.ifFalse;
+    _current = context._conditionInfo!.ifFalse;
   }
 
   @override
@@ -2935,23 +3549,43 @@
     FlowModel<Variable, Type> afterThen;
     FlowModel<Variable, Type> afterElse;
     if (hasElse) {
-      afterThen = context._afterThen;
+      afterThen = context._afterThen!;
       afterElse = _current;
     } else {
       afterThen = _current; // no `else`, so `then` is still current
-      afterElse = context._conditionInfo.ifFalse;
+      afterElse = context._conditionInfo!.ifFalse;
     }
     _current = _merge(afterThen, afterElse);
   }
 
   @override
-  void ifStatement_thenBegin(Expression condition) {
+  void ifStatement_thenBegin(Expression condition, Node ifNode) {
     ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
     _stack.add(new _IfContext(conditionInfo));
     _current = conditionInfo.ifTrue;
   }
 
   @override
+  void initialize(
+      Variable variable, Type initializerType, Expression initializerExpression,
+      {required bool isFinal, required bool isLate}) {
+    ExpressionInfo<Variable, Type>? expressionInfo =
+        _getExpressionInfo(initializerExpression);
+    SsaNode<Variable, Type> newSsaNode = new SsaNode<Variable, Type>(isLate
+        ? null
+        : expressionInfo is _TrivialExpressionInfo
+            ? null
+            : expressionInfo);
+    if (isFinal) {
+      // We don't promote final variables on initialization, so pretend the
+      // written type is the variable's declared type.
+      initializerType = typeOperations.variableType(variable);
+    }
+    _current =
+        _current.write(variable, initializerType, newSsaNode, typeOperations);
+  }
+
+  @override
   bool isAssigned(Variable variable) {
     return _current.infoFor(variable).assigned;
   }
@@ -2959,14 +3593,13 @@
   @override
   void isExpression_end(Expression isExpression, Expression subExpression,
       bool isNot, Type type) {
-    ExpressionInfo<Variable, Type> subExpressionInfo =
-        _getExpressionInfo(subExpression);
-    if (subExpressionInfo is _VariableReadInfo<Variable, Type>) {
-      ExpressionInfo<Variable, Type> expressionInfo =
-          _current.tryPromoteForTypeCheck(
-              typeOperations, subExpressionInfo._variable, type);
-      _storeExpressionInfo(isExpression,
-          isNot ? ExpressionInfo.invert(expressionInfo) : expressionInfo);
+    Reference<Variable, Type>? subExpressionReference =
+        _getExpressionReference(subExpression);
+    if (subExpressionReference != null) {
+      ExpressionInfo<Variable, Type> expressionInfo = _current
+          .tryPromoteForTypeCheck(typeOperations, subExpressionReference, type);
+      _storeExpressionInfo(
+          isExpression, isNot ? expressionInfo.invert() : expressionInfo);
     }
   }
 
@@ -2976,10 +3609,10 @@
   }
 
   @override
-  void labeledStatement_begin(Node node) {
+  void labeledStatement_begin(Statement node) {
     _current = _current.split();
     _BranchTargetContext<Variable, Type> context =
-        new _BranchTargetContext<Variable, Type>(_current.reachable.parent);
+        new _BranchTargetContext<Variable, Type>(_current.reachable.parent!);
     _stack.add(context);
     _statementToContext[node] = context;
   }
@@ -3018,7 +3651,7 @@
 
   @override
   void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
-      {@required bool isAnd}) {
+      {required bool isAnd}) {
     _BranchContext<Variable, Type> context =
         _stack.removeLast() as _BranchContext<Variable, Type>;
     ExpressionInfo<Variable, Type> rhsInfo = _expressionEnd(rightOperand);
@@ -3027,9 +3660,9 @@
     FlowModel<Variable, Type> falseResult;
     if (isAnd) {
       trueResult = rhsInfo.ifTrue;
-      falseResult = _join(context._conditionInfo.ifFalse, rhsInfo.ifFalse);
+      falseResult = _join(context._conditionInfo!.ifFalse, rhsInfo.ifFalse);
     } else {
-      trueResult = _join(context._conditionInfo.ifTrue, rhsInfo.ifTrue);
+      trueResult = _join(context._conditionInfo!.ifTrue, rhsInfo.ifTrue);
       falseResult = rhsInfo.ifFalse;
     }
     _storeExpressionInfo(
@@ -3039,8 +3672,8 @@
   }
 
   @override
-  void logicalBinaryOp_rightBegin(Expression leftOperand,
-      {@required bool isAnd}) {
+  void logicalBinaryOp_rightBegin(Expression leftOperand, Node wholeExpression,
+      {required bool isAnd}) {
     ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(leftOperand);
     _stack.add(new _BranchContext<Variable, Type>(conditionInfo));
     _current = isAnd ? conditionInfo.ifTrue : conditionInfo.ifFalse;
@@ -3049,16 +3682,16 @@
   @override
   void logicalNot_end(Expression notExpression, Expression operand) {
     ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(operand);
-    _storeExpressionInfo(notExpression, ExpressionInfo.invert(conditionInfo));
+    _storeExpressionInfo(notExpression, conditionInfo.invert());
   }
 
   @override
   void nonNullAssert_end(Expression operand) {
-    ExpressionInfo<Variable, Type> operandInfo = _getExpressionInfo(operand);
-    if (operandInfo is _VariableReadInfo<Variable, Type>) {
-      _current = _current
-          .tryMarkNonNullable(typeOperations, operandInfo._variable)
-          .ifTrue;
+    Reference<Variable, Type>? operandReference =
+        _getExpressionReference(operand);
+    if (operandReference != null) {
+      _current =
+          _current.tryMarkNonNullable(typeOperations, operandReference).ifTrue;
     }
   }
 
@@ -3070,17 +3703,16 @@
   }
 
   @override
-  void nullAwareAccess_rightBegin(Expression target, Type targetType) {
+  void nullAwareAccess_rightBegin(Expression? target, Type targetType) {
+    // ignore:unnecessary_null_comparison
     assert(targetType != null);
     _current = _current.split();
     _stack.add(new _NullAwareAccessContext<Variable, Type>(_current));
-    if (target != null) {
-      ExpressionInfo<Variable, Type> targetInfo = _getExpressionInfo(target);
-      if (targetInfo is _VariableReadInfo<Variable, Type>) {
-        _current = _current
-            .tryMarkNonNullable(typeOperations, targetInfo._variable)
-            .ifTrue;
-      }
+    Reference<Variable, Type>? targetReference =
+        _getExpressionReference(target);
+    if (targetReference != null) {
+      _current =
+          _current.tryMarkNonNullable(typeOperations, targetReference).ifTrue;
     }
   }
 
@@ -3097,16 +3729,22 @@
 
   @override
   void promote(Variable variable, Type type) {
-    _current =
-        _current.tryPromoteForTypeCheck(typeOperations, variable, type).ifTrue;
+    _current = _current
+        .tryPromoteForTypeCheck(typeOperations,
+            new VariableReference<Variable, Type>(variable), type)
+        .ifTrue;
   }
 
   @override
-  Type promotedType(Variable variable) {
+  Type? promotedType(Variable variable) {
     return _current.infoFor(variable).promotedTypes?.last;
   }
 
   @override
+  SsaNode<Variable, Type>? ssaNodeForTesting(Variable variable) =>
+      _current.variableInfo[variable]?.ssaNode;
+
+  @override
   void switchStatement_beginCase(bool hasLabel, Node node) {
     AssignedVariablesNodeInfo<Variable> info =
         _assignedVariables._getInfoForNode(node);
@@ -3124,7 +3762,7 @@
   void switchStatement_end(bool isExhaustive) {
     _SimpleStatementContext<Variable, Type> context =
         _stack.removeLast() as _SimpleStatementContext<Variable, Type>;
-    FlowModel<Variable, Type> breakState = context._breakModel;
+    FlowModel<Variable, Type>? breakState = context._breakModel;
 
     // It is allowed to "fall off" the end of a switch statement, so join the
     // current state to any breaks that were found previously.
@@ -3141,7 +3779,7 @@
     _current = _current.split();
     _SimpleStatementContext<Variable, Type> context =
         new _SimpleStatementContext<Variable, Type>(
-            _current.reachable.parent, _current);
+            _current.reachable.parent!, _current);
     _stack.add(context);
     _statementToContext[switchStatement] = context;
   }
@@ -3171,10 +3809,10 @@
 
   @override
   void tryCatchStatement_catchBegin(
-      Variable exceptionVariable, Variable stackTraceVariable) {
+      Variable? exceptionVariable, Variable? stackTraceVariable) {
     _TryContext<Variable, Type> context =
         _stack.last as _TryContext<Variable, Type>;
-    _current = context._beforeCatch;
+    _current = context._beforeCatch!;
     if (exceptionVariable != null) {
       _current = _current.declare(exceptionVariable, true);
     }
@@ -3195,39 +3833,57 @@
   void tryCatchStatement_end() {
     _TryContext<Variable, Type> context =
         _stack.removeLast() as _TryContext<Variable, Type>;
-    _current = context._afterBodyAndCatches.unsplit();
+    _current = context._afterBodyAndCatches!.unsplit();
   }
 
   @override
   void tryFinallyStatement_bodyBegin() {
-    _stack.add(new _TryContext<Variable, Type>(_current));
+    _stack.add(new _TryFinallyContext<Variable, Type>(_current));
   }
 
   @override
   void tryFinallyStatement_end(Node finallyBlock) {
     AssignedVariablesNodeInfo<Variable> info =
         _assignedVariables._getInfoForNode(finallyBlock);
-    _TryContext<Variable, Type> context =
-        _stack.removeLast() as _TryContext<Variable, Type>;
-    _current = _current.restrict(
-        typeOperations, context._afterBodyAndCatches, info._written);
+    _TryFinallyContext<Variable, Type> context =
+        _stack.removeLast() as _TryFinallyContext<Variable, Type>;
+    if (allowLocalBooleanVarsToPromote) {
+      _current = context._afterBodyAndCatches!
+          .attachFinally(typeOperations, context._beforeFinally, _current);
+    } else {
+      _current = _current.restrict(
+          typeOperations, context._afterBodyAndCatches!, info._written);
+    }
   }
 
   @override
   void tryFinallyStatement_finallyBegin(Node body) {
     AssignedVariablesNodeInfo<Variable> info =
         _assignedVariables._getInfoForNode(body);
-    _TryContext<Variable, Type> context =
-        _stack.last as _TryContext<Variable, Type>;
+    _TryFinallyContext<Variable, Type> context =
+        _stack.last as _TryFinallyContext<Variable, Type>;
     context._afterBodyAndCatches = _current;
     _current = _join(_current,
         context._previous.conservativeJoin(info._written, info._captured));
+    context._beforeFinally = _current;
   }
 
   @override
-  Type variableRead(Expression expression, Variable variable) {
-    _storeExpressionInfo(expression, new _VariableReadInfo(_current, variable));
-    return _current.infoFor(variable).promotedTypes?.last;
+  Type? variableRead(Expression expression, Variable variable) {
+    VariableReference<Variable, Type> variableReference =
+        new VariableReference<Variable, Type>(variable);
+    _storeExpressionReference(expression, variableReference);
+    VariableModel<Variable, Type> variableModel =
+        variableReference.getInfo(_current.variableInfo);
+    if (allowLocalBooleanVarsToPromote) {
+      ExpressionInfo<Variable, Type>? expressionInfo = variableModel
+          .ssaNode?.expressionInfo
+          ?.rebaseForward(typeOperations, _current);
+      if (expressionInfo != null) {
+        _storeExpressionInfo(expression, expressionInfo);
+      }
+    }
+    return variableModel.promotedTypes?.last;
   }
 
   @override
@@ -3235,7 +3891,7 @@
       Statement whileStatement, Expression condition) {
     ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
     _WhileContext<Variable, Type> context = new _WhileContext<Variable, Type>(
-        _current.reachable.parent, conditionInfo);
+        _current.reachable.parent!, conditionInfo);
     _stack.add(context);
     _statementToContext[whileStatement] = context;
     _current = conditionInfo.ifTrue;
@@ -3258,21 +3914,24 @@
   }
 
   @override
-  void write(Variable variable, Type writtenType,
-      {bool viaInitializer = false}) {
-    if (!viaInitializer) {
-      assert(
-          _assignedVariables._anywhere._written.contains(variable),
-          "Variable is written to, but was not included in "
-          "_variablesWrittenAnywhere: $variable");
-    }
-    _current = _current.write(variable, writtenType, typeOperations);
+  void write(
+      Variable variable, Type writtenType, Expression? writtenExpression) {
+    ExpressionInfo<Variable, Type>? expressionInfo = writtenExpression == null
+        ? null
+        : _getExpressionInfo(writtenExpression);
+    SsaNode<Variable, Type> newSsaNode = new SsaNode<Variable, Type>(
+        expressionInfo is _TrivialExpressionInfo ? null : expressionInfo);
+    _current =
+        _current.write(variable, writtenType, newSsaNode, typeOperations);
   }
 
+  @override
   void _dumpState() {
     print('  current: $_current');
     print('  expressionWithInfo: $_expressionWithInfo');
     print('  expressionInfo: $_expressionInfo');
+    print('  expressionWithReference: $_expressionWithReference');
+    print('  expressionReference: $_expressionReference');
     print('  stack:');
     for (_FlowContext stackEntry in _stack.reversed) {
       print('    $stackEntry');
@@ -3284,16 +3943,15 @@
   /// [ExpressionInfo] associated with the [expression], then a fresh
   /// [ExpressionInfo] is created recording the current flow analysis state.
   ExpressionInfo<Variable, Type> _expressionEnd(Expression expression) =>
-      _getExpressionInfo(expression) ??
-      new ExpressionInfo(_current, _current, _current);
+      _getExpressionInfo(expression) ?? new _TrivialExpressionInfo(_current);
 
   /// Gets the [ExpressionInfo] associated with the [expression] (which should
   /// be the last expression that was traversed).  If there is no
   /// [ExpressionInfo] associated with the [expression], then `null` is
   /// returned.
-  ExpressionInfo<Variable, Type> _getExpressionInfo(Expression expression) {
+  ExpressionInfo<Variable, Type>? _getExpressionInfo(Expression expression) {
     if (identical(expression, _expressionWithInfo)) {
-      ExpressionInfo<Variable, Type> expressionInfo = _expressionInfo;
+      ExpressionInfo<Variable, Type>? expressionInfo = _expressionInfo;
       _expressionInfo = null;
       return expressionInfo;
     } else {
@@ -3301,12 +3959,25 @@
     }
   }
 
-  FlowModel<Variable, Type> _join(
-          FlowModel<Variable, Type> first, FlowModel<Variable, Type> second) =>
+  /// Gets the [Reference] associated with the [expression] (which should be the
+  /// last expression that was traversed).  If there is no [Reference]
+  /// associated with the [expression], then `null` is returned.
+  Reference<Variable, Type>? _getExpressionReference(Expression? expression) {
+    if (identical(expression, _expressionWithReference)) {
+      Reference<Variable, Type>? expressionReference = _expressionReference;
+      _expressionReference = null;
+      return expressionReference;
+    } else {
+      return null;
+    }
+  }
+
+  FlowModel<Variable, Type> _join(FlowModel<Variable, Type>? first,
+          FlowModel<Variable, Type>? second) =>
       FlowModel.join(typeOperations, first, second, _current._emptyVariableMap);
 
   FlowModel<Variable, Type> _merge(
-          FlowModel<Variable, Type> first, FlowModel<Variable, Type> second) =>
+          FlowModel<Variable, Type> first, FlowModel<Variable, Type>? second) =>
       FlowModel.merge(
           typeOperations, first, second, _current._emptyVariableMap);
 
@@ -3319,6 +3990,14 @@
     _expressionInfo = expressionInfo;
     _current = expressionInfo.after;
   }
+
+  /// Associates [expression], which should be the most recently visited
+  /// expression, with the given [Reference] object.
+  void _storeExpressionReference(
+      Expression expression, Reference<Variable, Type> expressionReference) {
+    _expressionWithReference = expression;
+    _expressionReference = expressionReference;
+  }
 }
 
 /// Base class for objects representing constructs in the Dart programming
@@ -3326,7 +4005,7 @@
 abstract class _FlowContext {}
 
 /// [_FlowContext] representing a function expression.
-class _FunctionExpressionContext<Variable, Type>
+class _FunctionExpressionContext<Variable extends Object, Type extends Object>
     extends _SimpleContext<Variable, Type> {
   _FunctionExpressionContext(FlowModel<Variable, Type> previous)
       : super(previous);
@@ -3336,10 +4015,11 @@
 }
 
 /// [_FlowContext] representing an `if` statement.
-class _IfContext<Variable, Type> extends _BranchContext<Variable, Type> {
+class _IfContext<Variable extends Object, Type extends Object>
+    extends _BranchContext<Variable, Type> {
   /// Flow model associated with the state of program execution after the `if`
   /// statement executes, in the circumstance where the "then" branch is taken.
-  FlowModel<Variable, Type> _afterThen;
+  FlowModel<Variable, Type>? _afterThen;
 
   _IfContext(ExpressionInfo<Variable, Type> conditionInfo)
       : super(conditionInfo);
@@ -3350,7 +4030,7 @@
 }
 
 /// [_FlowContext] representing an "if-null" (`??`) expression.
-class _IfNullExpressionContext<Variable, Type>
+class _IfNullExpressionContext<Variable extends Object, Type extends Object>
     extends _SimpleContext<Variable, Type> {
   _IfNullExpressionContext(FlowModel<Variable, Type> previous)
       : super(previous);
@@ -3359,8 +4039,546 @@
   String toString() => '_IfNullExpressionContext(previous: $_previous)';
 }
 
+/// Contextual information tracked by legacy type promotion about a binary "and"
+/// expression (`&&`).
+class _LegacyBinaryAndContext<Variable extends Object, Type extends Object>
+    extends _LegacyContext<Variable, Type> {
+  /// Types that were shown by the LHS of the "and" expression.
+  final Map<Variable, Type> _lhsShownTypes;
+
+  /// Information about variables that might be assigned by the RHS of the "and"
+  /// expression.
+  final AssignedVariablesNodeInfo<Variable> _assignedVariablesInfoForRhs;
+
+  _LegacyBinaryAndContext(Map<Variable, Type> previousKnownTypes,
+      this._lhsShownTypes, this._assignedVariablesInfoForRhs)
+      : super(previousKnownTypes);
+}
+
+/// Contextual information tracked by legacy type promotion about a statement or
+/// expression.
+class _LegacyContext<Variable, Type> {
+  /// The set of known types in effect before the statement or expression in
+  /// question was encountered.
+  final Map<Variable, Type> _previousKnownTypes;
+
+  _LegacyContext(this._previousKnownTypes);
+}
+
+/// Data tracked by legacy type promotion about an expression.
+class _LegacyExpressionInfo<Variable, Type> {
+  /// Variables whose types are "shown" by the expression in question.
+  ///
+  /// For example, the spec says that the expression `x is T` "shows" `x` to
+  /// have type `T`, so accordingly, the [_LegacyExpressionInfo] for `x is T`
+  /// will have an entry in this map that maps `x` to `T`.
+  final Map<Variable, Type> _shownTypes;
+
+  _LegacyExpressionInfo(this._shownTypes);
+
+  @override
+  String toString() => 'LegacyExpressionInfo($_shownTypes)';
+}
+
+/// Implementation of [FlowAnalysis] that performs legacy (pre-null-safety) type
+/// promotion.
+class _LegacyTypePromotion<Node extends Object, Statement extends Node,
+        Expression extends Object, Variable extends Object, Type extends Object>
+    implements FlowAnalysis<Node, Statement, Expression, Variable, Type> {
+  /// The [TypeOperations], used to access types, and check subtyping.
+  final TypeOperations<Variable, Type> _typeOperations;
+
+  /// Information about variable assignments computed during the previous
+  /// compilation pass.
+  final AssignedVariables<Node, Variable> _assignedVariables;
+
+  /// The most recently visited expression for which a [_LegacyExpressionInfo]
+  /// object exists, or `null` if no expression has been visited that has a
+  /// corresponding [_LegacyExpressionInfo] object.
+  Expression? _expressionWithInfo;
+
+  /// If [_expressionWithInfo] is not `null`, the [_LegacyExpressionInfo] object
+  /// corresponding to it.  Otherwise `null`.
+  _LegacyExpressionInfo<Variable, Type>? _expressionInfo;
+
+  /// The set of type promotions currently in effect.
+  Map<Variable, Type> _knownTypes = {};
+
+  /// Stack of [_LegacyContext] objects representing the statements and
+  /// expressions that are currently being visited.
+  final List<_LegacyContext<Variable, Type>> _contextStack = [];
+
+  /// Stack for tracking writes occurring on the LHS of a binary "and" (`&&`)
+  /// operation.  Whenever we visit a write, we update the top entry in this
+  /// stack; whenever we begin to visit the LHS of a binary "and", we push
+  /// a fresh empty entry onto this stack; accordingly, upon reaching the RHS of
+  /// the binary "and", the top entry of the stack contains the set of variables
+  /// written to during the LHS of the "and".
+  final List<Set<Variable>> _writeStackForAnd = [{}];
+
+  _LegacyTypePromotion(this._typeOperations, this._assignedVariables);
+
+  @override
+  bool get isReachable => true;
+
+  @override
+  void asExpression_end(Expression subExpression, Type type) {}
+
+  @override
+  void assert_afterCondition(Expression condition) {}
+
+  @override
+  void assert_begin() {}
+
+  @override
+  void assert_end() {}
+
+  @override
+  void booleanLiteral(Expression expression, bool value) {}
+
+  @override
+  void conditional_conditionBegin() {}
+
+  @override
+  void conditional_elseBegin(Expression thenExpression) {
+    _knownTypes = _contextStack.removeLast()._previousKnownTypes;
+  }
+
+  @override
+  void conditional_end(
+      Expression conditionalExpression, Expression elseExpression) {}
+
+  @override
+  void conditional_thenBegin(Expression condition, Node conditionalExpression) {
+    _conditionalOrIf_thenBegin(condition, conditionalExpression);
+  }
+
+  @override
+  void declare(Variable variable, bool initialized) {}
+
+  @override
+  void doStatement_bodyBegin(Statement doStatement) {}
+
+  @override
+  void doStatement_conditionBegin() {}
+
+  @override
+  void doStatement_end(Expression condition) {}
+
+  @override
+  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
+      Type rightOperandType,
+      {bool notEqual = false}) {}
+
+  @override
+  void equalityOp_rightBegin(Expression leftOperand, Type leftOperandType) {}
+
+  @override
+  ExpressionInfo<Variable, Type>? expressionInfoForTesting(Expression target) {
+    throw new StateError(
+        'expressionInfoForTesting requires null-aware flow analysis');
+  }
+
+  @override
+  void finish() {
+    assert(_contextStack.isEmpty, 'Unexpected stack: $_contextStack');
+  }
+
+  @override
+  void for_bodyBegin(Statement? node, Expression? condition) {}
+
+  @override
+  void for_conditionBegin(Node node) {}
+
+  @override
+  void for_end() {}
+
+  @override
+  void for_updaterBegin() {}
+
+  @override
+  void forEach_bodyBegin(
+      Node node, Variable? loopVariable, Type? writtenType) {}
+
+  @override
+  void forEach_end() {}
+
+  @override
+  void forwardExpression(Expression newExpression, Expression oldExpression) {
+    if (identical(_expressionWithInfo, oldExpression)) {
+      _expressionWithInfo = newExpression;
+    }
+  }
+
+  @override
+  void functionExpression_begin(Node node) {}
+
+  @override
+  void functionExpression_end() {}
+
+  @override
+  void handleBreak(Statement target) {}
+
+  @override
+  void handleContinue(Statement target) {}
+
+  @override
+  void handleExit() {}
+
+  @override
+  void ifNullExpression_end() {}
+
+  @override
+  void ifNullExpression_rightBegin(
+      Expression leftHandSide, Type leftHandSideType) {}
+
+  @override
+  void ifStatement_conditionBegin() {}
+
+  @override
+  void ifStatement_elseBegin() {
+    _knownTypes = _contextStack.removeLast()._previousKnownTypes;
+  }
+
+  @override
+  void ifStatement_end(bool hasElse) {
+    if (!hasElse) {
+      _knownTypes = _contextStack.removeLast()._previousKnownTypes;
+    }
+  }
+
+  @override
+  void ifStatement_thenBegin(Expression condition, Node ifNode) {
+    _conditionalOrIf_thenBegin(condition, ifNode);
+  }
+
+  @override
+  void initialize(
+      Variable variable, Type initializerType, Expression initializerExpression,
+      {required bool isFinal, required bool isLate}) {}
+
+  @override
+  bool isAssigned(Variable variable) {
+    return true;
+  }
+
+  @override
+  void isExpression_end(Expression isExpression, Expression subExpression,
+      bool isNot, Type type) {
+    _LegacyExpressionInfo<Variable, Type>? expressionInfo =
+        _getExpressionInfo(subExpression);
+    if (!isNot && expressionInfo is _LegacyVariableReadInfo<Variable, Type>) {
+      Variable variable = expressionInfo._variable;
+      Type currentType =
+          _knownTypes[variable] ?? _typeOperations.variableType(variable);
+      Type? promotedType = _typeOperations.tryPromoteToType(type, currentType);
+      if (promotedType != null &&
+          !_typeOperations.isSameType(currentType, promotedType)) {
+        _storeExpressionInfo(
+            isExpression,
+            new _LegacyExpressionInfo<Variable, Type>(
+                {variable: promotedType}));
+      }
+    }
+  }
+
+  @override
+  bool isUnassigned(Variable variable) {
+    return false;
+  }
+
+  @override
+  void labeledStatement_begin(Node node) {}
+
+  @override
+  void labeledStatement_end() {}
+
+  @override
+  void lateInitializer_begin(Node node) {}
+
+  @override
+  void lateInitializer_end() {}
+
+  @override
+  void logicalBinaryOp_begin() {
+    _writeStackForAnd.add({});
+  }
+
+  @override
+  void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
+      {required bool isAnd}) {
+    if (!isAnd) return;
+    _LegacyBinaryAndContext<Variable, Type> context =
+        _contextStack.removeLast() as _LegacyBinaryAndContext<Variable, Type>;
+    _knownTypes = context._previousKnownTypes;
+    AssignedVariablesNodeInfo<Variable> assignedVariablesInfoForRhs =
+        context._assignedVariablesInfoForRhs;
+    Map<Variable, Type> lhsShownTypes = context._lhsShownTypes;
+    Map<Variable, Type> rhsShownTypes =
+        _getExpressionInfo(rightOperand)?._shownTypes ?? {};
+    // A logical boolean expression b of the form `e1 && e2` shows that a local
+    // variable v has type T if both of the following conditions hold:
+    // - Either e1 shows that v has type T or e2 shows that v has type T.
+    // - v is not mutated in e2 or within a function other than the one where v
+    //   is declared.
+    // We don't have to worry about whether v is mutated within a function other
+    // than the one where v is declared, because that is checked every time we
+    // evaluate whether v is known to have type T.  So we just have to combine
+    // together the things shown by e1 and e2, and discard anything mutated in
+    // e2.
+    //
+    // Note, however, that there is an ambiguity that isn't addressed by the
+    // spec: what happens if e1 shows that v has type T1 and e2 shows that v has
+    // type T2?  The de facto behavior we have had for a long time is to combine
+    // the two types in the same way we would combine it if c were first
+    // promoted to T1 and then had a successful `is T2` check.
+    Map<Variable, Type> newShownTypes = {};
+    for (MapEntry<Variable, Type> entry in lhsShownTypes.entries) {
+      if (assignedVariablesInfoForRhs._written.contains(entry.key)) continue;
+      newShownTypes[entry.key] = entry.value;
+    }
+    for (MapEntry<Variable, Type> entry in rhsShownTypes.entries) {
+      if (assignedVariablesInfoForRhs._written.contains(entry.key)) continue;
+      Type? previouslyShownType = newShownTypes[entry.key];
+      if (previouslyShownType == null) {
+        newShownTypes[entry.key] = entry.value;
+      } else {
+        Type? newShownType =
+            _typeOperations.tryPromoteToType(entry.value, previouslyShownType);
+        if (newShownType != null &&
+            !_typeOperations.isSameType(previouslyShownType, newShownType)) {
+          newShownTypes[entry.key] = newShownType;
+        }
+      }
+    }
+    _storeExpressionInfo(wholeExpression,
+        new _LegacyExpressionInfo<Variable, Type>(newShownTypes));
+  }
+
+  @override
+  void logicalBinaryOp_rightBegin(Expression leftOperand, Node wholeExpression,
+      {required bool isAnd}) {
+    Set<Variable> variablesWrittenOnLhs = _writeStackForAnd.removeLast();
+    _writeStackForAnd.last.addAll(variablesWrittenOnLhs);
+    if (!isAnd) return;
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(wholeExpression);
+    Map<Variable, Type> lhsShownTypes =
+        _getExpressionInfo(leftOperand)?._shownTypes ?? {};
+    _contextStack.add(new _LegacyBinaryAndContext<Variable, Type>(
+        _knownTypes, lhsShownTypes, info));
+    Map<Variable, Type>? newKnownTypes;
+    for (MapEntry<Variable, Type> entry in lhsShownTypes.entries) {
+      // Given a statement of the form `e1 && e2`, if e1 shows that a
+      // local variable v has type T, then the type of v is known to be T in
+      // e2, unless any of the following are true:
+      // - v is potentially mutated in e1,
+      if (variablesWrittenOnLhs.contains(entry.key)) continue;
+      // - v is potentially mutated in e2,
+      if (info._written.contains(entry.key)) continue;
+      // - v is potentially mutated within a function other than the one where
+      //   v is declared, or
+      if (_assignedVariables._anywhere._captured.contains(entry.key)) {
+        continue;
+      }
+      // - v is accessed by a function defined in e2 and v is potentially
+      //   mutated anywhere in the scope of v.
+      if (info._readCaptured.contains(entry.key) &&
+          _assignedVariables._anywhere._written.contains(entry.key)) {
+        continue;
+      }
+      (newKnownTypes ??= new Map<Variable, Type>.from(_knownTypes))[entry.key] =
+          entry.value;
+    }
+    if (newKnownTypes != null) _knownTypes = newKnownTypes;
+  }
+
+  @override
+  void logicalNot_end(Expression notExpression, Expression operand) {}
+
+  @override
+  void nonNullAssert_end(Expression operand) {}
+
+  @override
+  void nullAwareAccess_end() {}
+
+  @override
+  void nullAwareAccess_rightBegin(Expression? target, Type targetType) {}
+
+  @override
+  void nullLiteral(Expression expression) {}
+
+  @override
+  void parenthesizedExpression(
+      Expression outerExpression, Expression innerExpression) {
+    forwardExpression(outerExpression, innerExpression);
+  }
+
+  @override
+  void promote(Variable variable, Type type) {
+    throw new UnimplementedError('TODO(paulberry)');
+  }
+
+  @override
+  Type? promotedType(Variable variable) {
+    return _knownTypes[variable];
+  }
+
+  @override
+  SsaNode<Variable, Type>? ssaNodeForTesting(Variable variable) {
+    throw new StateError('ssaNodeForTesting requires null-aware flow analysis');
+  }
+
+  @override
+  void switchStatement_beginCase(bool hasLabel, Node node) {}
+
+  @override
+  void switchStatement_end(bool isExhaustive) {}
+
+  @override
+  void switchStatement_expressionEnd(Statement switchStatement) {}
+
+  @override
+  void tryCatchStatement_bodyBegin() {}
+
+  @override
+  void tryCatchStatement_bodyEnd(Node body) {}
+
+  @override
+  void tryCatchStatement_catchBegin(
+      Variable? exceptionVariable, Variable? stackTraceVariable) {}
+
+  @override
+  void tryCatchStatement_catchEnd() {}
+
+  @override
+  void tryCatchStatement_end() {}
+
+  @override
+  void tryFinallyStatement_bodyBegin() {}
+
+  @override
+  void tryFinallyStatement_end(Node finallyBlock) {}
+
+  @override
+  void tryFinallyStatement_finallyBegin(Node body) {}
+
+  @override
+  Type? variableRead(Expression expression, Variable variable) {
+    _storeExpressionInfo(
+        expression, new _LegacyVariableReadInfo<Variable, Type>(variable));
+    return _knownTypes[variable];
+  }
+
+  @override
+  void whileStatement_bodyBegin(
+      Statement whileStatement, Expression condition) {}
+
+  @override
+  void whileStatement_conditionBegin(Node node) {}
+
+  @override
+  void whileStatement_end() {}
+
+  @override
+  void write(
+      Variable variable, Type writtenType, Expression? writtenExpression) {
+    assert(
+        _assignedVariables._anywhere._written.contains(variable),
+        "Variable is written to, but was not included in "
+        "_variablesWrittenAnywhere: $variable");
+    _writeStackForAnd.last.add(variable);
+  }
+
+  void _conditionalOrIf_thenBegin(Expression condition, Node node) {
+    _contextStack.add(new _LegacyContext<Variable, Type>(_knownTypes));
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(node);
+    Map<Variable, Type>? newKnownTypes;
+    _LegacyExpressionInfo<Variable, Type>? expressionInfo =
+        _getExpressionInfo(condition);
+    if (expressionInfo != null) {
+      for (MapEntry<Variable, Type> entry
+          in expressionInfo._shownTypes.entries) {
+        // Given an expression of the form n1?n2:n3 or a statement of the form
+        // `if (n1) n2 else n3`, if n1 shows that a local variable v has type T,
+        // then the type of v is known to be T in n2, unless any of the
+        // following are true:
+        // - v is potentially mutated in n2,
+        if (info._written.contains(entry.key)) continue;
+        // - v is potentially mutated within a function other than the one where
+        //   v is declared, or
+        if (_assignedVariables._anywhere._captured.contains(entry.key)) {
+          continue;
+        }
+        // - v is accessed by a function defined in n2 and v is potentially
+        //   mutated anywhere in the scope of v.
+        if (info._readCaptured.contains(entry.key) &&
+            _assignedVariables._anywhere._written.contains(entry.key)) {
+          continue;
+        }
+        (newKnownTypes ??=
+            new Map<Variable, Type>.from(_knownTypes))[entry.key] = entry.value;
+      }
+      if (newKnownTypes != null) _knownTypes = newKnownTypes;
+    }
+  }
+
+  @override
+  void _dumpState() {
+    print('  knownTypes: $_knownTypes');
+    print('  expressionWithInfo: $_expressionWithInfo');
+    print('  expressionInfo: $_expressionInfo');
+    print('  contextStack:');
+    for (_LegacyContext<Variable, Type> stackEntry in _contextStack.reversed) {
+      print('    $stackEntry');
+    }
+    print('  writeStackForAnd:');
+    for (Set<Variable> stackEntry in _writeStackForAnd.reversed) {
+      print('    $stackEntry');
+    }
+  }
+
+  /// Gets the [_LegacyExpressionInfo] associated with [expression], if any;
+  /// otherwise returns `null`.
+  _LegacyExpressionInfo<Variable, Type>? _getExpressionInfo(
+      Expression expression) {
+    if (identical(expression, _expressionWithInfo)) {
+      _LegacyExpressionInfo<Variable, Type>? expressionInfo = _expressionInfo;
+      _expressionInfo = null;
+      return expressionInfo;
+    } else {
+      return null;
+    }
+  }
+
+  /// Associates [expressionInfo] with [expression] for use by a future call to
+  /// [_getExpressionInfo].
+  void _storeExpressionInfo(Expression expression,
+      _LegacyExpressionInfo<Variable, Type> expressionInfo) {
+    _expressionWithInfo = expression;
+    _expressionInfo = expressionInfo;
+  }
+}
+
+/// Data tracked by legacy type promotion about an expression that reads the
+/// value of a local variable.
+class _LegacyVariableReadInfo<Variable, Type>
+    implements _LegacyExpressionInfo<Variable, Type> {
+  /// The variable being referred to.
+  final Variable _variable;
+
+  _LegacyVariableReadInfo(this._variable);
+
+  @override
+  Map<Variable, Type> get _shownTypes => {};
+
+  @override
+  String toString() => 'LegacyVariableReadInfo($_variable, $_shownTypes)';
+}
+
 /// [_FlowContext] representing a null aware access (`?.`).
-class _NullAwareAccessContext<Variable, Type>
+class _NullAwareAccessContext<Variable extends Object, Type extends Object>
     extends _SimpleContext<Variable, Type> {
   _NullAwareAccessContext(FlowModel<Variable, Type> previous) : super(previous);
 
@@ -3369,7 +4587,8 @@
 }
 
 /// [ExpressionInfo] representing a `null` literal.
-class _NullInfo<Variable, Type> implements ExpressionInfo<Variable, Type> {
+class _NullInfo<Variable extends Object, Type extends Object>
+    implements ExpressionInfo<Variable, Type> {
   @override
   final FlowModel<Variable, Type> after;
 
@@ -3380,12 +4599,27 @@
 
   @override
   FlowModel<Variable, Type> get ifTrue => after;
+
+  @override
+  ExpressionInfo<Variable, Type> invert() {
+    // This should only happen if `!null` is encountered.  That should never
+    // happen for a properly typed program, but we need to handle it so we can
+    // give reasonable errors for an improperly typed program.
+    return this;
+  }
+
+  @override
+  ExpressionInfo<Variable, Type>? rebaseForward(
+          TypeOperations<Variable, Type> typeOperations,
+          FlowModel<Variable, Type> base) =>
+      null;
 }
 
 /// [_FlowContext] representing a language construct for which flow analysis
 /// must store a flow model state to be retrieved later, such as a `try`
 /// statement, function expression, or "if-null" (`??`) expression.
-abstract class _SimpleContext<Variable, Type> extends _FlowContext {
+abstract class _SimpleContext<Variable extends Object, Type extends Object>
+    extends _FlowContext {
   /// The stored state.  For a `try` statement, this is the state from the
   /// beginning of the `try` block.  For a function expression, this is the
   /// state at the point the function expression was created.  For an "if-null"
@@ -3400,7 +4634,7 @@
 /// `break` or `continue` statements, and for which flow analysis must store a
 /// flow model state to be retrieved later.  Examples include "for each" and
 /// `switch` statements.
-class _SimpleStatementContext<Variable, Type>
+class _SimpleStatementContext<Variable extends Object, Type extends Object>
     extends _BranchTargetContext<Variable, Type> {
   /// The stored state.  For a "for each" statement, this is the state after
   /// evaluation of the iterable.  For a `switch` statement, this is the state
@@ -3416,18 +4650,45 @@
       'checkpoint: $_checkpoint)';
 }
 
+/// Specialization of [ExpressionInfo] for the case where the information we
+/// have about the expression is trivial (meaning we know by construction that
+/// the expression's [after], [ifTrue], and [ifFalse] models are all the same).
+class _TrivialExpressionInfo<Variable extends Object, Type extends Object>
+    implements ExpressionInfo<Variable, Type> {
+  @override
+  final FlowModel<Variable, Type> after;
+
+  _TrivialExpressionInfo(this.after);
+
+  @override
+  FlowModel<Variable, Type> get ifFalse => after;
+
+  @override
+  FlowModel<Variable, Type> get ifTrue => after;
+
+  @override
+  ExpressionInfo<Variable, Type> invert() => this;
+
+  @override
+  ExpressionInfo<Variable, Type> rebaseForward(
+          TypeOperations<Variable, Type> typeOperations,
+          FlowModel<Variable, Type> base) =>
+      new _TrivialExpressionInfo(base);
+}
+
 /// [_FlowContext] representing a try statement.
-class _TryContext<Variable, Type> extends _SimpleContext<Variable, Type> {
+class _TryContext<Variable extends Object, Type extends Object>
+    extends _SimpleContext<Variable, Type> {
   /// If the statement is a "try/catch" statement, the flow model representing
   /// program state at the top of any `catch` block.
-  FlowModel<Variable, Type> _beforeCatch;
+  FlowModel<Variable, Type>? _beforeCatch;
 
   /// If the statement is a "try/catch" statement, the accumulated flow model
   /// representing program state after the `try` block or one of the `catch`
   /// blocks has finished executing.  If the statement is a "try/finally"
   /// statement, the flow model representing program state after the `try` block
   /// has finished executing.
-  FlowModel<Variable, Type> _afterBodyAndCatches;
+  FlowModel<Variable, Type>? _afterBodyAndCatches;
 
   _TryContext(FlowModel<Variable, Type> previous) : super(previous);
 
@@ -3437,31 +4698,18 @@
       'afterBodyAndCatches: $_afterBodyAndCatches)';
 }
 
-/// [ExpressionInfo] representing an expression that reads the value of a
-/// variable.
-class _VariableReadInfo<Variable, Type>
-    implements ExpressionInfo<Variable, Type> {
-  @override
-  final FlowModel<Variable, Type> after;
+class _TryFinallyContext<Variable extends Object, Type extends Object>
+    extends _TryContext<Variable, Type> {
+  /// The flow model representing program state at the top of the `finally`
+  /// block.
+  late FlowModel<Variable, Type> _beforeFinally;
 
-  /// The variable that is being read.
-  final Variable _variable;
-
-  _VariableReadInfo(this.after, this._variable);
-
-  @override
-  FlowModel<Variable, Type> get ifFalse => after;
-
-  @override
-  FlowModel<Variable, Type> get ifTrue => after;
-
-  @override
-  String toString() => '_VariableReadInfo(after: $after, variable: $_variable)';
+  _TryFinallyContext(FlowModel<Variable, Type> previous) : super(previous);
 }
 
 /// [_FlowContext] representing a `while` loop (or a C-style `for` loop, which
 /// is functionally similar).
-class _WhileContext<Variable, Type>
+class _WhileContext<Variable extends Object, Type extends Object>
     extends _BranchTargetContext<Variable, Type> {
   /// Flow models associated with the loop condition.
   final ExpressionInfo<Variable, Type> _conditionInfo;
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
index 5d95d3b..acc5edc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
@@ -26,15 +26,12 @@
   /// this error to its corresponding Analyzer error.
   final int index;
 
-  final Template<T> template;
-
-  final List<String> analyzerCodes;
+  final List<String>? analyzerCodes;
 
   final Severity severity;
 
-  const Code(this.name, this.template,
-      {int index, this.analyzerCodes, this.severity: Severity.error})
-      : this.index = index ?? -1;
+  const Code(this.name,
+      {this.index: -1, this.analyzerCodes, this.severity: Severity.error});
 
   String toString() => name;
 }
@@ -44,11 +41,12 @@
 
   final String message;
 
-  final String tip;
+  final String? tip;
 
   final Map<String, dynamic> arguments;
 
-  const Message(this.code, {this.message, this.tip, this.arguments});
+  const Message(this.code,
+      {required this.message, this.tip, this.arguments = const {}});
 
   LocatedMessage withLocation(Uri uri, int charOffset, int length) {
     return new LocatedMessage(uri, charOffset, length, this);
@@ -66,15 +64,15 @@
 class MessageCode extends Code<Null> implements Message {
   final String message;
 
-  final String tip;
+  final String? tip;
 
   const MessageCode(String name,
-      {int index,
-      List<String> analyzerCodes,
+      {int index: -1,
+      List<String>? analyzerCodes,
       Severity severity: Severity.error,
-      this.message,
+      required this.message,
       this.tip})
-      : super(name, null,
+      : super(name,
             index: index, analyzerCodes: analyzerCodes, severity: severity);
 
   Map<String, dynamic> get arguments => const <String, dynamic>{};
@@ -94,15 +92,18 @@
 class Template<T> {
   final String messageTemplate;
 
-  final String tipTemplate;
+  final String? tipTemplate;
 
   final T withArguments;
 
-  const Template({this.messageTemplate, this.tipTemplate, this.withArguments});
+  const Template(
+      {required this.messageTemplate,
+      this.tipTemplate,
+      required this.withArguments});
 }
 
 class LocatedMessage implements Comparable<LocatedMessage> {
-  final Uri uri;
+  final Uri? uri;
 
   final int charOffset;
 
@@ -117,7 +118,7 @@
 
   String get message => messageObject.message;
 
-  String get tip => messageObject.tip;
+  String? get tip => messageObject.tip;
 
   Map<String, dynamic> get arguments => messageObject.arguments;
 
@@ -132,7 +133,7 @@
 
   FormattedMessage withFormatting(String formatted, int line, int column,
       Severity severity, List<FormattedMessage> relatedInformation,
-      {List<Uri> involvedFiles}) {
+      {List<Uri>? involvedFiles}) {
     return new FormattedMessage(
         this, formatted, line, column, severity, relatedInformation,
         involvedFiles: involvedFiles);
@@ -173,9 +174,9 @@
   @override
   final Severity severity;
 
-  final List<FormattedMessage> relatedInformation;
+  final List<FormattedMessage>? relatedInformation;
 
-  final List<Uri> involvedFiles;
+  final List<Uri>? involvedFiles;
 
   const FormattedMessage(this.locatedMessage, this.formatted, this.line,
       this.column, this.severity, this.relatedInformation,
@@ -187,11 +188,11 @@
 
   String get message => locatedMessage.message;
 
-  String get tip => locatedMessage.tip;
+  String? get tip => locatedMessage.tip;
 
   Map<String, dynamic> get arguments => locatedMessage.arguments;
 
-  Uri get uri => locatedMessage.uri;
+  Uri? get uri => locatedMessage.uri;
 
   int get charOffset => locatedMessage.charOffset;
 
@@ -201,7 +202,7 @@
   Iterable<String> get ansiFormatted sync* {
     yield formatted;
     if (relatedInformation != null) {
-      for (FormattedMessage m in relatedInformation) {
+      for (FormattedMessage m in relatedInformation!) {
         yield m.formatted;
       }
     }
@@ -213,14 +214,14 @@
     return ansiFormatted;
   }
 
-  Map<String, Object> toJson() {
+  Map<String, Object?> toJson() {
     // This should be kept in sync with package:kernel/problems.md
-    return <String, Object>{
+    return <String, Object?>{
       "ansiFormatted": ansiFormatted.toList(),
       "plainTextFormatted": plainTextFormatted.toList(),
       "severity": severity.index,
       "uri": uri?.toString(),
-      "involvedFiles": involvedFiles?.map((u) => u.toString())?.toList(),
+      "involvedFiles": involvedFiles?.map((u) => u.toString()).toList(),
       "codeName": code.name,
     };
   }
@@ -241,9 +242,9 @@
   @override
   final Severity severity;
 
-  final Uri uri;
+  final Uri? uri;
 
-  final List<Uri> involvedFiles;
+  final List<Uri>? involvedFiles;
 
   final String codeName;
 
@@ -253,30 +254,31 @@
   factory DiagnosticMessageFromJson.fromJson(String jsonString) {
     Map<String, Object> decoded = json.decode(jsonString);
     List<String> ansiFormatted =
-        new List<String>.from(decoded["ansiFormatted"]);
+        new List<String>.from(_asListOfString(decoded["ansiFormatted"]));
     List<String> plainTextFormatted =
-        new List<String>.from(decoded["plainTextFormatted"]);
-    Severity severity = Severity.values[decoded["severity"]];
-    Uri uri = decoded["uri"] == null ? null : Uri.parse(decoded["uri"]);
-    List<Uri> involvedFiles = decoded["involvedFiles"] == null
+        _asListOfString(decoded["plainTextFormatted"]);
+    Severity severity = Severity.values[decoded["severity"] as int];
+    Uri? uri =
+        decoded["uri"] == null ? null : Uri.parse(decoded["uri"] as String);
+    List<Uri>? involvedFiles = decoded["involvedFiles"] == null
         ? null
-        : new List<String>.from(decoded["involvedFiles"])
+        : _asListOfString(decoded["involvedFiles"])
             .map((e) => Uri.parse(e))
             .toList();
-    String codeName = decoded["codeName"];
+    String codeName = decoded["codeName"] as String;
 
     return new DiagnosticMessageFromJson(ansiFormatted, plainTextFormatted,
         severity, uri, involvedFiles, codeName);
   }
 
-  Map<String, Object> toJson() {
+  Map<String, Object?> toJson() {
     // This should be kept in sync with package:kernel/problems.md
-    return <String, Object>{
+    return <String, Object?>{
       "ansiFormatted": ansiFormatted.toList(),
       "plainTextFormatted": plainTextFormatted.toList(),
       "severity": severity.index,
       "uri": uri?.toString(),
-      "involvedFiles": involvedFiles?.map((u) => u.toString())?.toList(),
+      "involvedFiles": involvedFiles?.map((u) => u.toString()).toList(),
       "codeName": codeName,
     };
   }
@@ -285,9 +287,13 @@
     JsonEncoder encoder = new JsonEncoder.withIndent("  ");
     return encoder.convert(this);
   }
+
+  static List<String> _asListOfString(Object? value) {
+    return (value as List<dynamic>).cast<String>();
+  }
 }
 
-String relativizeUri(Uri uri) {
+String? relativizeUri(Uri? uri) {
   // We have this method here for two reasons:
   //
   // 1. It allows us to implement #uri message argument without using it
@@ -328,3 +334,24 @@
   }
   return demangledName;
 }
+
+final RegExp templateKey = new RegExp(r'#(\w+)');
+
+/// Replaces occurrences of '#key' in [template], where 'key' is a key in
+/// [arguments], with the corresponding values.
+String applyArgumentsToTemplate(
+    String template, Map<String, dynamic> arguments) {
+  // TODO(johnniwinther): Remove `as dynamic` when unsound null safety is
+  // no longer supported.
+  if (arguments as dynamic == null || arguments.isEmpty) {
+    assert(!template.contains(templateKey),
+        'Message requires arguments, but none were provided.');
+    return template;
+  }
+  return template.replaceAllMapped(templateKey, (Match match) {
+    String? key = match.group(1);
+    Object? value = arguments[key];
+    assert(value != null, "No value for '$key' found in $arguments");
+    return value.toString();
+  });
+}
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 e40a4fc..ba1e3a6 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, 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.
 
@@ -21,8 +21,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeAbstractClassInstantiation =
-    const Code<Message Function(String name)>(
-        "AbstractClassInstantiation", templateAbstractClassInstantiation,
+    const Code<Message Function(String name)>("AbstractClassInstantiation",
         analyzerCodes: <String>["NEW_WITH_ABSTRACT_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -117,7 +116,6 @@
     codeAbstractRedirectedClassInstantiation =
     const Code<Message Function(String name)>(
         "AbstractRedirectedClassInstantiation",
-        templateAbstractRedirectedClassInstantiation,
         analyzerCodes: <String>["FACTORY_REDIRECTS_TO_ABSTRACT_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -150,7 +148,6 @@
 const Code<Message Function(String name)> codeAccessError =
     const Code<Message Function(String name)>(
   "AccessError",
-  templateAccessError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -242,8 +239,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(int codePoint)> codeAsciiControlCharacter =
-    const Code<Message Function(int codePoint)>(
-        "AsciiControlCharacter", templateAsciiControlCharacter,
+    const Code<Message Function(int codePoint)>("AsciiControlCharacter",
         analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -253,7 +249,7 @@
   return new Message(codeAsciiControlCharacter,
       message:
           """The control character ${unicode} can only be used in strings and comments.""",
-      arguments: {'codePoint': codePoint});
+      arguments: {'unicode': codePoint});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -328,7 +324,7 @@
 const Code<Message Function(String string, String string2)>
     codeBinaryOperatorWrittenOut =
     const Code<Message Function(String string, String string2)>(
-        "BinaryOperatorWrittenOut", templateBinaryOperatorWrittenOut,
+        "BinaryOperatorWrittenOut",
         index: 112);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -361,7 +357,6 @@
     codeBoundIssueViaCycleNonSimplicity =
     const Code<Message Function(String name, String name2)>(
         "BoundIssueViaCycleNonSimplicity",
-        templateBoundIssueViaCycleNonSimplicity,
         analyzerCodes: <String>["NOT_INSTANTIATED_BOUND"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -392,7 +387,6 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeBoundIssueViaLoopNonSimplicity =
     const Code<Message Function(String name)>("BoundIssueViaLoopNonSimplicity",
-        templateBoundIssueViaLoopNonSimplicity,
         analyzerCodes: <String>["NOT_INSTANTIATED_BOUND"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -420,7 +414,6 @@
     codeBoundIssueViaRawTypeWithNonSimpleBounds =
     const Code<Message Function(String name)>(
         "BoundIssueViaRawTypeWithNonSimpleBounds",
-        templateBoundIssueViaRawTypeWithNonSimpleBounds,
         analyzerCodes: <String>["NOT_INSTANTIATED_BOUND"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -454,8 +447,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeBreakTargetOutsideFunction =
-    const Code<Message Function(String name)>(
-        "BreakTargetOutsideFunction", templateBreakTargetOutsideFunction,
+    const Code<Message Function(String name)>("BreakTargetOutsideFunction",
         analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -476,8 +468,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeBuiltInIdentifierAsType =
-    const Code<Message Function(Token token)>(
-        "BuiltInIdentifierAsType", templateBuiltInIdentifierAsType,
+    const Code<Message Function(Token token)>("BuiltInIdentifierAsType",
         analyzerCodes: <String>["BUILT_IN_IDENTIFIER_AS_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -486,7 +477,7 @@
   return new Message(codeBuiltInIdentifierAsType,
       message:
           """The built-in identifier '${lexeme}' can't be used as a type.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -499,7 +490,6 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeBuiltInIdentifierInDeclaration =
     const Code<Message Function(Token token)>("BuiltInIdentifierInDeclaration",
-        templateBuiltInIdentifierInDeclaration,
         analyzerCodes: <String>["BUILT_IN_IDENTIFIER_IN_DECLARATION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -507,7 +497,7 @@
   String lexeme = token.lexeme;
   return new Message(codeBuiltInIdentifierInDeclaration,
       message: """Can't use '${lexeme}' as a name here.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -531,7 +521,6 @@
     codeCandidateFoundIsDefaultConstructor =
     const Code<Message Function(String name)>(
         "CandidateFoundIsDefaultConstructor",
-        templateCandidateFoundIsDefaultConstructor,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -555,7 +544,6 @@
 const Code<Message Function(String name)> codeCannotAssignToConstVariable =
     const Code<Message Function(String name)>(
   "CannotAssignToConstVariable",
-  templateCannotAssignToConstVariable,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -587,7 +575,6 @@
 const Code<Message Function(String name)> codeCannotAssignToFinalVariable =
     const Code<Message Function(String name)>(
   "CannotAssignToFinalVariable",
-  templateCannotAssignToFinalVariable,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -640,7 +627,6 @@
 const Code<Message Function(String string)> codeCannotReadSdkSpecification =
     const Code<Message Function(String string)>(
   "CannotReadSdkSpecification",
-  templateCannotReadSdkSpecification,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -695,36 +681,6 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String name)>
-    templateCantInferReturnTypeDueToInconsistentOverrides =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Can't infer a return type for '#name' as some of the overridden members have different types.""",
-        tipTemplate: r"""Try adding an explicit type.""",
-        withArguments:
-            _withArgumentsCantInferReturnTypeDueToInconsistentOverrides);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeCantInferReturnTypeDueToInconsistentOverrides =
-    const Code<Message Function(String name)>(
-        "CantInferReturnTypeDueToInconsistentOverrides",
-        templateCantInferReturnTypeDueToInconsistentOverrides,
-        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCantInferReturnTypeDueToInconsistentOverrides(
-    String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeCantInferReturnTypeDueToInconsistentOverrides,
-      message:
-          """Can't infer a return type for '${name}' as some of the overridden members have different types.""",
-      tip: """Try adding an explicit type.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
     templateCantInferReturnTypeDueToNoCombinedSignature =
     const Template<Message Function(String name)>(
         messageTemplate:
@@ -738,7 +694,6 @@
     codeCantInferReturnTypeDueToNoCombinedSignature =
     const Code<Message Function(String name)>(
         "CantInferReturnTypeDueToNoCombinedSignature",
-        templateCantInferReturnTypeDueToNoCombinedSignature,
         analyzerCodes: <String>[
       "COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE"
     ]);
@@ -767,8 +722,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeCantInferTypeDueToCircularity =
-    const Code<Message Function(String string)>(
-        "CantInferTypeDueToCircularity", templateCantInferTypeDueToCircularity,
+    const Code<Message Function(String string)>("CantInferTypeDueToCircularity",
         analyzerCodes: <String>["RECURSIVE_COMPILE_TIME_CONSTANT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -782,34 +736,6 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateCantInferTypeDueToInconsistentOverrides =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Can't infer a type for '#name' as some of the overridden members have different types.""",
-        tipTemplate: r"""Try adding an explicit type.""",
-        withArguments: _withArgumentsCantInferTypeDueToInconsistentOverrides);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeCantInferTypeDueToInconsistentOverrides =
-    const Code<Message Function(String name)>(
-        "CantInferTypeDueToInconsistentOverrides",
-        templateCantInferTypeDueToInconsistentOverrides,
-        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCantInferTypeDueToInconsistentOverrides(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeCantInferTypeDueToInconsistentOverrides,
-      message:
-          """Can't infer a type for '${name}' as some of the overridden members have different types.""",
-      tip: """Try adding an explicit type.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         String
@@ -825,7 +751,6 @@
     codeCantInferTypeDueToNoCombinedSignature =
     const Code<Message Function(String name)>(
         "CantInferTypeDueToNoCombinedSignature",
-        templateCantInferTypeDueToNoCombinedSignature,
         analyzerCodes: <String>[
       "COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE"
     ]);
@@ -842,6 +767,37 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateCantInferTypesDueToNoCombinedSignature = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Can't infer types for '#name' as the overridden members don't have a combined signature.""",
+    tipTemplate: r"""Try adding explicit types.""",
+    withArguments: _withArgumentsCantInferTypesDueToNoCombinedSignature);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeCantInferTypesDueToNoCombinedSignature =
+    const Code<Message Function(String name)>(
+        "CantInferTypesDueToNoCombinedSignature",
+        analyzerCodes: <String>[
+      "COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE"
+    ]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCantInferTypesDueToNoCombinedSignature(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeCantInferTypesDueToNoCombinedSignature,
+      message:
+          """Can't infer types for '${name}' as the overridden members don't have a combined signature.""",
+      tip: """Try adding explicit types.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(Uri uri_, String string)> templateCantReadFile =
     const Template<Message Function(Uri uri_, String string)>(
         messageTemplate: r"""Error when reading '#uri': #string""",
@@ -849,13 +805,12 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Uri uri_, String string)> codeCantReadFile =
-    const Code<Message Function(Uri uri_, String string)>(
-        "CantReadFile", templateCantReadFile,
+    const Code<Message Function(Uri uri_, String string)>("CantReadFile",
         analyzerCodes: <String>["URI_DOES_NOT_EXIST"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsCantReadFile(Uri uri_, String string) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   if (string.isEmpty) throw 'No string provided';
   return new Message(codeCantReadFile,
       message: """Error when reading '${uri}': ${string}""",
@@ -875,7 +830,6 @@
     codeCantUseControlFlowOrSpreadAsConstant =
     const Code<Message Function(Token token)>(
         "CantUseControlFlowOrSpreadAsConstant",
-        templateCantUseControlFlowOrSpreadAsConstant,
         analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -883,7 +837,7 @@
   String lexeme = token.lexeme;
   return new Message(codeCantUseControlFlowOrSpreadAsConstant,
       message: """'${lexeme}' is not supported in constant expressions.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -902,7 +856,6 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeCantUseDeferredPrefixAsConstant =
     const Code<Message Function(Token token)>("CantUseDeferredPrefixAsConstant",
-        templateCantUseDeferredPrefixAsConstant,
         analyzerCodes: <String>["CONST_DEFERRED_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -913,7 +866,7 @@
           """'${lexeme}' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
       tip: """Try moving the constant from the deferred library, or removing 'deferred' from the import.
 """,
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -979,8 +932,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeClassInNullAwareReceiver =
-    const Code<Message Function(String name)>(
-        "ClassInNullAwareReceiver", templateClassInNullAwareReceiver,
+    const Code<Message Function(String name)>("ClassInNullAwareReceiver",
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1019,7 +971,7 @@
 const Code<Message Function(String name, String name2)>
     codeCombinedMemberSignatureFailed =
     const Code<Message Function(String name, String name2)>(
-        "CombinedMemberSignatureFailed", templateCombinedMemberSignatureFailed,
+        "CombinedMemberSignatureFailed",
         analyzerCodes: <String>["INCONSISTENT_INHERITANCE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1036,6 +988,26 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCompilingWithSoundNullSafety =
+    messageCompilingWithSoundNullSafety;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCompilingWithSoundNullSafety = const MessageCode(
+    "CompilingWithSoundNullSafety",
+    severity: Severity.info,
+    message: r"""Compiling with sound null safety""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCompilingWithoutSoundNullSafety =
+    messageCompilingWithoutSoundNullSafety;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCompilingWithoutSoundNullSafety = const MessageCode(
+    "CompilingWithoutSoundNullSafety",
+    severity: Severity.info,
+    message: r"""Compiling without sound null safety""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         String string,
@@ -1051,7 +1023,7 @@
 const Code<Message Function(String string, String string2)>
     codeConflictingModifiers =
     const Code<Message Function(String string, String string2)>(
-        "ConflictingModifiers", templateConflictingModifiers,
+        "ConflictingModifiers",
         index: 59);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1073,8 +1045,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeConflictsWithConstructor =
-    const Code<Message Function(String name)>(
-        "ConflictsWithConstructor", templateConflictsWithConstructor,
+    const Code<Message Function(String name)>("ConflictsWithConstructor",
         analyzerCodes: <String>["CONFLICTS_WITH_CONSTRUCTOR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1096,7 +1067,6 @@
 const Code<Message Function(String name)> codeConflictsWithFactory =
     const Code<Message Function(String name)>(
   "ConflictsWithFactory",
-  templateConflictsWithFactory,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1116,8 +1086,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeConflictsWithMember =
-    const Code<Message Function(String name)>(
-        "ConflictsWithMember", templateConflictsWithMember,
+    const Code<Message Function(String name)>("ConflictsWithMember",
         analyzerCodes: <String>["CONFLICTS_WITH_MEMBER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1137,8 +1106,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeConflictsWithSetter =
-    const Code<Message Function(String name)>(
-        "ConflictsWithSetter", templateConflictsWithSetter,
+    const Code<Message Function(String name)>("ConflictsWithSetter",
         analyzerCodes: <String>["CONFLICTS_WITH_MEMBER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1159,8 +1127,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeConflictsWithTypeVariable =
-    const Code<Message Function(String name)>(
-        "ConflictsWithTypeVariable", templateConflictsWithTypeVariable,
+    const Code<Message Function(String name)>("ConflictsWithTypeVariable",
         analyzerCodes: <String>["CONFLICTING_TYPE_VARIABLE_AND_MEMBER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1302,14 +1269,14 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String nameOKEmpty)> codeConstEvalDeferredLibrary =
-    const Code<Message Function(String nameOKEmpty)>(
-        "ConstEvalDeferredLibrary", templateConstEvalDeferredLibrary,
+    const Code<Message Function(String nameOKEmpty)>("ConstEvalDeferredLibrary",
         analyzerCodes: <String>[
       "NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY"
     ]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalDeferredLibrary(String nameOKEmpty) {
+  // ignore: unnecessary_null_comparison
   if (nameOKEmpty == null || nameOKEmpty.isEmpty) nameOKEmpty = '(unnamed)';
   return new Message(codeConstEvalDeferredLibrary,
       message:
@@ -1351,12 +1318,12 @@
     codeConstEvalFailedAssertionWithMessage =
     const Code<Message Function(String stringOKEmpty)>(
         "ConstEvalFailedAssertionWithMessage",
-        templateConstEvalFailedAssertionWithMessage,
         analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalFailedAssertionWithMessage(
     String stringOKEmpty) {
+  // ignore: unnecessary_null_comparison
   if (stringOKEmpty == null || stringOKEmpty.isEmpty) stringOKEmpty = '(empty)';
   return new Message(codeConstEvalFailedAssertionWithMessage,
       message: """This assertion failed with message: ${stringOKEmpty}""",
@@ -1376,11 +1343,11 @@
     codeConstEvalInvalidStaticInvocation =
     const Code<Message Function(String nameOKEmpty)>(
         "ConstEvalInvalidStaticInvocation",
-        templateConstEvalInvalidStaticInvocation,
         analyzerCodes: <String>["CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalInvalidStaticInvocation(String nameOKEmpty) {
+  // ignore: unnecessary_null_comparison
   if (nameOKEmpty == null || nameOKEmpty.isEmpty) nameOKEmpty = '(unnamed)';
   return new Message(codeConstEvalInvalidStaticInvocation,
       message:
@@ -1405,7 +1372,6 @@
     codeConstEvalNegativeShift =
     const Code<Message Function(String string, String string2, String string3)>(
   "ConstEvalNegativeShift",
-  templateConstEvalNegativeShift,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1435,11 +1401,11 @@
     codeConstEvalNonConstantVariableGet =
     const Code<Message Function(String nameOKEmpty)>(
         "ConstEvalNonConstantVariableGet",
-        templateConstEvalNonConstantVariableGet,
         analyzerCodes: <String>["NON_CONSTANT_VALUE_IN_INITIALIZER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalNonConstantVariableGet(String nameOKEmpty) {
+  // ignore: unnecessary_null_comparison
   if (nameOKEmpty == null || nameOKEmpty.isEmpty) nameOKEmpty = '(unnamed)';
   return new Message(codeConstEvalNonConstantVariableGet,
       message:
@@ -1508,7 +1474,6 @@
     codeConstEvalTruncateError =
     const Code<Message Function(String string, String string2)>(
   "ConstEvalTruncateError",
-  templateConstEvalTruncateError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1544,7 +1509,7 @@
 const Code<Message Function(String string, String string2)>
     codeConstEvalZeroDivisor =
     const Code<Message Function(String string, String string2)>(
-        "ConstEvalZeroDivisor", templateConstEvalZeroDivisor,
+        "ConstEvalZeroDivisor",
         analyzerCodes: <String>["CONST_EVAL_THROWS_IDBZE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1594,8 +1559,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeConstFieldWithoutInitializer =
-    const Code<Message Function(String name)>(
-        "ConstFieldWithoutInitializer", templateConstFieldWithoutInitializer,
+    const Code<Message Function(String name)>("ConstFieldWithoutInitializer",
         analyzerCodes: <String>["CONST_NOT_INITIALIZED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1654,7 +1618,6 @@
     codeConstructorInitializeSameInstanceVariableSeveralTimes =
     const Code<Message Function(String name)>(
         "ConstructorInitializeSameInstanceVariableSeveralTimes",
-        templateConstructorInitializeSameInstanceVariableSeveralTimes,
         analyzerCodes: <String>["FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1675,8 +1638,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeConstructorNotFound =
-    const Code<Message Function(String name)>(
-        "ConstructorNotFound", templateConstructorNotFound,
+    const Code<Message Function(String name)>("ConstructorNotFound",
         analyzerCodes: <String>["CONSTRUCTOR_NOT_FOUND"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1752,7 +1714,6 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeConstructorWithWrongNameContext =
     const Code<Message Function(String name)>("ConstructorWithWrongNameContext",
-        templateConstructorWithWrongNameContext,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1794,8 +1755,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeContinueTargetOutsideFunction =
-    const Code<Message Function(String name)>(
-        "ContinueTargetOutsideFunction", templateContinueTargetOutsideFunction,
+    const Code<Message Function(String name)>("ContinueTargetOutsideFunction",
         analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1832,7 +1792,6 @@
     codeCouldNotParseUri =
     const Code<Message Function(String string, String string2)>(
   "CouldNotParseUri",
-  templateCouldNotParseUri,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1881,7 +1840,7 @@
 const Code<Message Function(String name, String string)>
     codeCycleInTypeVariables =
     const Code<Message Function(String name, String string)>(
-        "CycleInTypeVariables", templateCycleInTypeVariables,
+        "CycleInTypeVariables",
         analyzerCodes: <String>["TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1904,8 +1863,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeCyclicClassHierarchy =
-    const Code<Message Function(String name)>(
-        "CyclicClassHierarchy", templateCyclicClassHierarchy,
+    const Code<Message Function(String name)>("CyclicClassHierarchy",
         analyzerCodes: <String>["RECURSIVE_INTERFACE_INHERITANCE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1929,7 +1887,6 @@
     codeCyclicRedirectingFactoryConstructors =
     const Code<Message Function(String name)>(
         "CyclicRedirectingFactoryConstructors",
-        templateCyclicRedirectingFactoryConstructors,
         analyzerCodes: <String>["RECURSIVE_FACTORY_REDIRECT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1949,8 +1906,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeCyclicTypedef =
-    const Code<Message Function(String name)>(
-        "CyclicTypedef", templateCyclicTypedef,
+    const Code<Message Function(String name)>("CyclicTypedef",
         analyzerCodes: <String>["TYPE_ALIAS_CANNOT_REFERENCE_ITSELF"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1971,8 +1927,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name, String string)> codeDebugTrace =
-    const Code<Message Function(String name, String string)>(
-        "DebugTrace", templateDebugTrace,
+    const Code<Message Function(String name, String string)>("DebugTrace",
         severity: Severity.ignored);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2040,7 +1995,6 @@
     codeDefaultValueInRedirectingFactoryConstructor =
     const Code<Message Function(String name)>(
         "DefaultValueInRedirectingFactoryConstructor",
-        templateDefaultValueInRedirectingFactoryConstructor,
         analyzerCodes: <String>[
       "DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR"
     ]);
@@ -2082,7 +2036,6 @@
 const Code<Message Function(String name)> codeDeferredExtensionImport =
     const Code<Message Function(String name)>(
   "DeferredExtensionImport",
-  templateDeferredExtensionImport,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2108,8 +2061,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDeferredPrefixDuplicated =
-    const Code<Message Function(String name)>(
-        "DeferredPrefixDuplicated", templateDeferredPrefixDuplicated,
+    const Code<Message Function(String name)>("DeferredPrefixDuplicated",
         analyzerCodes: <String>["SHARED_DEFERRED_PREFIX"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2131,8 +2083,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDeferredPrefixDuplicatedCause =
-    const Code<Message Function(String name)>(
-        "DeferredPrefixDuplicatedCause", templateDeferredPrefixDuplicatedCause,
+    const Code<Message Function(String name)>("DeferredPrefixDuplicatedCause",
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2162,18 +2113,22 @@
         num _num3)> codeDillOutlineSummary = const Code<
     Message Function(int count, int count2, num _num1, num _num2, num _num3)>(
   "DillOutlineSummary",
-  templateDillOutlineSummary,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsDillOutlineSummary(
     int count, int count2, num _num1, num _num2, num _num3) {
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (count2 == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (_num1 == null) throw 'No number provided';
   String num1 = _num1.toStringAsFixed(3);
+  // ignore: unnecessary_null_comparison
   if (_num2 == null) throw 'No number provided';
   String num2 = _num2.toStringAsFixed(3).padLeft(12);
+  // ignore: unnecessary_null_comparison
   if (_num3 == null) throw 'No number provided';
   String num3 = _num3.toStringAsFixed(3).padLeft(12);
   return new Message(codeDillOutlineSummary,
@@ -2203,8 +2158,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDirectCycleInTypeVariables =
-    const Code<Message Function(String name)>(
-        "DirectCycleInTypeVariables", templateDirectCycleInTypeVariables,
+    const Code<Message Function(String name)>("DirectCycleInTypeVariables",
         analyzerCodes: <String>["TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2251,7 +2205,6 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDuplicateLabelInSwitchStatement =
     const Code<Message Function(String name)>("DuplicateLabelInSwitchStatement",
-        templateDuplicateLabelInSwitchStatement,
         index: 72);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2282,8 +2235,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDuplicatedDeclaration =
-    const Code<Message Function(String name)>(
-        "DuplicatedDeclaration", templateDuplicatedDeclaration,
+    const Code<Message Function(String name)>("DuplicatedDeclaration",
         analyzerCodes: <String>["DUPLICATE_DEFINITION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2304,8 +2256,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDuplicatedDeclarationCause =
-    const Code<Message Function(String name)>(
-        "DuplicatedDeclarationCause", templateDuplicatedDeclarationCause,
+    const Code<Message Function(String name)>("DuplicatedDeclarationCause",
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2332,7 +2283,6 @@
     codeDuplicatedDeclarationSyntheticCause =
     const Code<Message Function(String name)>(
         "DuplicatedDeclarationSyntheticCause",
-        templateDuplicatedDeclarationSyntheticCause,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2356,7 +2306,6 @@
 const Code<Message Function(String name)> codeDuplicatedDeclarationUse =
     const Code<Message Function(String name)>(
   "DuplicatedDeclarationUse",
-  templateDuplicatedDeclarationUse,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2380,15 +2329,15 @@
 const Code<Message Function(String name, Uri uri_, Uri uri2_)>
     codeDuplicatedExport =
     const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "DuplicatedExport", templateDuplicatedExport,
+        "DuplicatedExport",
         analyzerCodes: <String>["AMBIGUOUS_EXPORT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsDuplicatedExport(String name, Uri uri_, Uri uri2_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
   return new Message(codeDuplicatedExport,
       message: """'${name}' is exported from both '${uri}' and '${uri2}'.""",
       arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
@@ -2407,15 +2356,14 @@
     codeDuplicatedExportInType =
     const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
   "DuplicatedExportInType",
-  templateDuplicatedExportInType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsDuplicatedExportInType(String name, Uri uri_, Uri uri2_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
   return new Message(codeDuplicatedExportInType,
       message: """'${name}' is exported from both '${uri}' and '${uri2}'.""",
       arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
@@ -2433,15 +2381,15 @@
 const Code<Message Function(String name, Uri uri_, Uri uri2_)>
     codeDuplicatedImport =
     const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "DuplicatedImport", templateDuplicatedImport,
+        "DuplicatedImport",
         severity: Severity.ignored);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsDuplicatedImport(String name, Uri uri_, Uri uri2_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
   return new Message(codeDuplicatedImport,
       message: """'${name}' is imported from both '${uri}' and '${uri2}'.""",
       arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
@@ -2459,15 +2407,15 @@
 const Code<Message Function(String name, Uri uri_, Uri uri2_)>
     codeDuplicatedImportInType =
     const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "DuplicatedImportInType", templateDuplicatedImportInType,
+        "DuplicatedImportInType",
         analyzerCodes: <String>["AMBIGUOUS_IMPORT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsDuplicatedImportInType(String name, Uri uri_, Uri uri2_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
   return new Message(codeDuplicatedImportInType,
       message: """'${name}' is imported from both '${uri}' and '${uri2}'.""",
       arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
@@ -2483,9 +2431,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeDuplicatedModifier =
-    const Code<Message Function(Token token)>(
-        "DuplicatedModifier", templateDuplicatedModifier,
-        index: 70);
+    const Code<Message Function(Token token)>("DuplicatedModifier", index: 70);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsDuplicatedModifier(Token token) {
@@ -2493,7 +2439,7 @@
   return new Message(codeDuplicatedModifier,
       message: """The modifier '${lexeme}' was already specified.""",
       tip: """Try removing all but one occurrence of the modifier.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2508,8 +2454,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDuplicatedNamePreviouslyUsed =
-    const Code<Message Function(String name)>(
-        "DuplicatedNamePreviouslyUsed", templateDuplicatedNamePreviouslyUsed,
+    const Code<Message Function(String name)>("DuplicatedNamePreviouslyUsed",
         analyzerCodes: <String>["REFERENCED_BEFORE_DECLARATION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2534,7 +2479,6 @@
     codeDuplicatedNamePreviouslyUsedCause =
     const Code<Message Function(String name)>(
         "DuplicatedNamePreviouslyUsedCause",
-        templateDuplicatedNamePreviouslyUsedCause,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2553,8 +2497,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDuplicatedNamedArgument =
-    const Code<Message Function(String name)>(
-        "DuplicatedNamedArgument", templateDuplicatedNamedArgument,
+    const Code<Message Function(String name)>("DuplicatedNamedArgument",
         analyzerCodes: <String>["DUPLICATE_NAMED_ARGUMENT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2574,8 +2517,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDuplicatedParameterName =
-    const Code<Message Function(String name)>(
-        "DuplicatedParameterName", templateDuplicatedParameterName,
+    const Code<Message Function(String name)>("DuplicatedParameterName",
         analyzerCodes: <String>["DUPLICATE_DEFINITION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2596,8 +2538,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeDuplicatedParameterNameCause =
-    const Code<Message Function(String name)>(
-        "DuplicatedParameterNameCause", templateDuplicatedParameterNameCause,
+    const Code<Message Function(String name)>("DuplicatedParameterNameCause",
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2650,7 +2591,6 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeEnumConstantSameNameAsEnclosing =
     const Code<Message Function(String name)>("EnumConstantSameNameAsEnclosing",
-        templateEnumConstantSameNameAsEnclosing,
         analyzerCodes: <String>["ENUM_CONSTANT_WITH_ENUM_NAME"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2713,12 +2653,11 @@
 const Code<Message Function(Uri uri_, String string)> codeExceptionReadingFile =
     const Code<Message Function(Uri uri_, String string)>(
   "ExceptionReadingFile",
-  templateExceptionReadingFile,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsExceptionReadingFile(Uri uri_, String string) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   if (string.isEmpty) throw 'No string provided';
   return new Message(codeExceptionReadingFile,
       message: """Exception when reading '${uri}': ${string}""",
@@ -2733,8 +2672,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeExpectedAfterButGot =
-    const Code<Message Function(String string)>(
-        "ExpectedAfterButGot", templateExpectedAfterButGot,
+    const Code<Message Function(String string)>("ExpectedAfterButGot",
         analyzerCodes: <String>["EXPECTED_TOKEN"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2790,8 +2728,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeExpectedButGot =
-    const Code<Message Function(String string)>(
-        "ExpectedButGot", templateExpectedButGot,
+    const Code<Message Function(String string)>("ExpectedButGot",
         analyzerCodes: <String>["EXPECTED_TOKEN"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2810,8 +2747,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExpectedClassMember =
-    const Code<Message Function(Token token)>(
-        "ExpectedClassMember", templateExpectedClassMember,
+    const Code<Message Function(Token token)>("ExpectedClassMember",
         analyzerCodes: <String>["EXPECTED_CLASS_MEMBER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2819,7 +2755,7 @@
   String lexeme = token.lexeme;
   return new Message(codeExpectedClassMember,
       message: """Expected a class member, but got '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2833,8 +2769,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeExpectedClassOrMixinBody =
-    const Code<Message Function(String string)>(
-        "ExpectedClassOrMixinBody", templateExpectedClassOrMixinBody,
+    const Code<Message Function(String string)>("ExpectedClassOrMixinBody",
         index: 8);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2854,8 +2789,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExpectedDeclaration =
-    const Code<Message Function(Token token)>(
-        "ExpectedDeclaration", templateExpectedDeclaration,
+    const Code<Message Function(Token token)>("ExpectedDeclaration",
         analyzerCodes: <String>["EXPECTED_EXECUTABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2863,7 +2797,7 @@
   String lexeme = token.lexeme;
   return new Message(codeExpectedDeclaration,
       message: """Expected a declaration, but got '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2886,8 +2820,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExpectedEnumBody =
-    const Code<Message Function(Token token)>(
-        "ExpectedEnumBody", templateExpectedEnumBody,
+    const Code<Message Function(Token token)>("ExpectedEnumBody",
         analyzerCodes: <String>["MISSING_ENUM_BODY"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2897,7 +2830,7 @@
       message: """Expected a enum body, but got '${lexeme}'.""",
       tip:
           """An enum definition must have a body with at least one constant name.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2908,8 +2841,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExpectedFunctionBody =
-    const Code<Message Function(Token token)>(
-        "ExpectedFunctionBody", templateExpectedFunctionBody,
+    const Code<Message Function(Token token)>("ExpectedFunctionBody",
         analyzerCodes: <String>["MISSING_FUNCTION_BODY"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2917,7 +2849,7 @@
   String lexeme = token.lexeme;
   return new Message(codeExpectedFunctionBody,
       message: """Expected a function body, but got '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2938,8 +2870,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExpectedIdentifier =
-    const Code<Message Function(Token token)>(
-        "ExpectedIdentifier", templateExpectedIdentifier,
+    const Code<Message Function(Token token)>("ExpectedIdentifier",
         analyzerCodes: <String>["MISSING_IDENTIFIER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2948,7 +2879,7 @@
   return new Message(codeExpectedIdentifier,
       message: """Expected an identifier, but got '${lexeme}'.""",
       tip: """Try inserting an identifier before '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2967,7 +2898,6 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExpectedIdentifierButGotKeyword =
     const Code<Message Function(Token token)>("ExpectedIdentifierButGotKeyword",
-        templateExpectedIdentifierButGotKeyword,
         index: 113);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2977,7 +2907,7 @@
       message:
           """'${lexeme}' can't be used as an identifier because it's a keyword.""",
       tip: """Try renaming this to be an identifier that isn't a keyword.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2988,9 +2918,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeExpectedInstead =
-    const Code<Message Function(String string)>(
-        "ExpectedInstead", templateExpectedInstead,
-        index: 41);
+    const Code<Message Function(String string)>("ExpectedInstead", index: 41);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsExpectedInstead(String string) {
@@ -3041,8 +2969,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExpectedString =
-    const Code<Message Function(Token token)>(
-        "ExpectedString", templateExpectedString,
+    const Code<Message Function(Token token)>("ExpectedString",
         analyzerCodes: <String>["EXPECTED_STRING_LITERAL"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3050,7 +2977,7 @@
   String lexeme = token.lexeme;
   return new Message(codeExpectedString,
       message: """Expected a String, but got '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3061,8 +2988,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeExpectedToken =
-    const Code<Message Function(String string)>(
-        "ExpectedToken", templateExpectedToken,
+    const Code<Message Function(String string)>("ExpectedToken",
         analyzerCodes: <String>["EXPECTED_TOKEN"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3081,8 +3007,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExpectedType =
-    const Code<Message Function(Token token)>(
-        "ExpectedType", templateExpectedType,
+    const Code<Message Function(Token token)>("ExpectedType",
         analyzerCodes: <String>["EXPECTED_TYPE_NAME"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3090,7 +3015,7 @@
   String lexeme = token.lexeme;
   return new Message(codeExpectedType,
       message: """Expected a type, but got '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3114,8 +3039,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeExperimentDisabled =
-    const Code<Message Function(String string)>(
-        "ExperimentDisabled", templateExperimentDisabled,
+    const Code<Message Function(String string)>("ExperimentDisabled",
         analyzerCodes: <String>["ParserErrorCode.EXPERIMENT_NOT_ENABLED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3142,7 +3066,6 @@
     codeExperimentDisabledInvalidLanguageVersion =
     const Code<Message Function(String string2)>(
         "ExperimentDisabledInvalidLanguageVersion",
-        templateExperimentDisabledInvalidLanguageVersion,
         analyzerCodes: <String>["ParserErrorCode.EXPERIMENT_NOT_ENABLED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3171,7 +3094,7 @@
 const Code<Message Function(String string, String string2)>
     codeExperimentNotEnabled =
     const Code<Message Function(String string, String string2)>(
-        "ExperimentNotEnabled", templateExperimentNotEnabled,
+        "ExperimentNotEnabled",
         index: 48);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3215,7 +3138,6 @@
     codeExperimentNotEnabledNoFlagInvalidLanguageVersion =
     const Code<Message Function(String string2)>(
         "ExperimentNotEnabledNoFlagInvalidLanguageVersion",
-        templateExperimentNotEnabledNoFlagInvalidLanguageVersion,
         analyzerCodes: <String>["ParserErrorCode.EXPERIMENT_NOT_ENABLED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3275,7 +3197,6 @@
     codeExplicitExtensionTypeArgumentMismatch =
     const Code<Message Function(String name, int count)>(
   "ExplicitExtensionTypeArgumentMismatch",
-  templateExplicitExtensionTypeArgumentMismatch,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3283,6 +3204,7 @@
     String name, int count) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
   return new Message(codeExplicitExtensionTypeArgumentMismatch,
       message:
@@ -3311,15 +3233,15 @@
 const Code<Message Function(String name, Uri uri_, Uri uri2_)>
     codeExportHidesExport =
     const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "ExportHidesExport", templateExportHidesExport,
+        "ExportHidesExport",
         severity: Severity.ignored);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsExportHidesExport(String name, Uri uri_, Uri uri2_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
   return new Message(codeExportHidesExport,
       message:
           """Export of '${name}' (from '${uri}') hides export from '${uri2}'.""",
@@ -3370,8 +3292,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeExtendingEnum =
-    const Code<Message Function(String name)>(
-        "ExtendingEnum", templateExtendingEnum,
+    const Code<Message Function(String name)>("ExtendingEnum",
         analyzerCodes: <String>["EXTENDS_ENUM"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3392,8 +3313,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeExtendingRestricted =
-    const Code<Message Function(String name)>(
-        "ExtendingRestricted", templateExtendingRestricted,
+    const Code<Message Function(String name)>("ExtendingRestricted",
         analyzerCodes: <String>["EXTENDS_DISALLOWED_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3473,7 +3393,6 @@
     codeExtensionMemberConflictsWithObjectMember =
     const Code<Message Function(String name)>(
   "ExtensionMemberConflictsWithObjectMember",
-  templateExtensionMemberConflictsWithObjectMember,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3627,9 +3546,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExtraneousModifier =
-    const Code<Message Function(Token token)>(
-        "ExtraneousModifier", templateExtraneousModifier,
-        index: 77);
+    const Code<Message Function(Token token)>("ExtraneousModifier", index: 77);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsExtraneousModifier(Token token) {
@@ -3637,7 +3554,7 @@
   return new Message(codeExtraneousModifier,
       message: """Can't have modifier '${lexeme}' here.""",
       tip: """Try removing '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3650,8 +3567,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeExtraneousModifierInExtension =
-    const Code<Message Function(Token token)>(
-        "ExtraneousModifierInExtension", templateExtraneousModifierInExtension,
+    const Code<Message Function(Token token)>("ExtraneousModifierInExtension",
         index: 98);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3660,7 +3576,7 @@
   return new Message(codeExtraneousModifierInExtension,
       message: """Can't have modifier '${lexeme}' in an extension.""",
       tip: """Try removing '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3692,7 +3608,6 @@
 const Code<Message Function(String name)> codeFastaCLIArgumentRequired =
     const Code<Message Function(String name)>(
   "FastaCLIArgumentRequired",
-  templateFastaCLIArgumentRequired,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3806,6 +3721,56 @@
   -h        Display this message (add -v for information about all options).""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(String name)> templateFfiEmptyStruct = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Struct '#name' is empty. Empty structs are undefined behavior.""",
+    withArguments: _withArgumentsFfiEmptyStruct);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFfiEmptyStruct =
+    const Code<Message Function(String name)>(
+  "FfiEmptyStruct",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiEmptyStruct(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiEmptyStruct,
+      message:
+          """Struct '${name}' is empty. Empty structs are undefined behavior.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateFfiEmptyStructWarning = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Struct '#name' is empty. Support for empty structs is deprecated and will be removed in the next stable version of Dart. Use Opaque instead.""",
+    withArguments: _withArgumentsFfiEmptyStructWarning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFfiEmptyStructWarning =
+    const Code<Message Function(String name)>("FfiEmptyStructWarning",
+        analyzerCodes: <String>["EMPTY_STRUCT_WARNING"],
+        severity: Severity.info);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiEmptyStructWarning(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiEmptyStructWarning,
+      message:
+          """Struct '${name}' is empty. Support for empty structs is deprecated and will be removed in the next stable version of Dart. Use Opaque instead.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeFfiExceptionalReturnNull = messageFfiExceptionalReturnNull;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3834,7 +3799,6 @@
     codeFfiExtendsOrImplementsSealedClass =
     const Code<Message Function(String name)>(
   "FfiExtendsOrImplementsSealedClass",
-  templateFfiExtendsOrImplementsSealedClass,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3858,7 +3822,6 @@
 const Code<Message Function(String name)> codeFfiFieldAnnotation =
     const Code<Message Function(String name)>(
   "FfiFieldAnnotation",
-  templateFfiFieldAnnotation,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3872,18 +3835,44 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, List<String> _names)>
+    templateFfiFieldCyclic =
+    const Template<Message Function(String name, List<String> _names)>(
+        messageTemplate: r"""Struct '#name' contains itself. Cycle elements:
+#names""", withArguments: _withArgumentsFfiFieldCyclic);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, List<String> _names)>
+    codeFfiFieldCyclic =
+    const Code<Message Function(String name, List<String> _names)>(
+  "FfiFieldCyclic",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiFieldCyclic(String name, List<String> _names) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (_names.isEmpty) throw 'No names provided';
+  String names = itemizeNames(_names);
+  return new Message(codeFfiFieldCyclic,
+      message: """Struct '${name}' contains itself. Cycle elements:
+${names}""", arguments: {'name': name, 'names': _names});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(String name)> templateFfiFieldInitializer = const Template<
         Message Function(String name)>(
     messageTemplate:
         r"""Field '#name' is a dart:ffi Pointer to a struct field and therefore cannot be initialized before constructor execution.""",
+    tipTemplate:
+        r"""Mark the field as external to avoid having to initialize it.""",
     withArguments: _withArgumentsFfiFieldInitializer);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeFfiFieldInitializer =
     const Code<Message Function(String name)>(
   "FfiFieldInitializer",
-  templateFfiFieldInitializer,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3893,6 +3882,7 @@
   return new Message(codeFfiFieldInitializer,
       message:
           """Field '${name}' is a dart:ffi Pointer to a struct field and therefore cannot be initialized before constructor execution.""",
+      tip: """Mark the field as external to avoid having to initialize it.""",
       arguments: {'name': name});
 }
 
@@ -3910,7 +3900,6 @@
 const Code<Message Function(String name)> codeFfiFieldNoAnnotation =
     const Code<Message Function(String name)>(
   "FfiFieldNoAnnotation",
-  templateFfiFieldNoAnnotation,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3935,7 +3924,6 @@
 const Code<Message Function(String name)> codeFfiNotStatic =
     const Code<Message Function(String name)>(
   "FfiNotStatic",
-  templateFfiNotStatic,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3958,7 +3946,6 @@
 const Code<Message Function(String name)> codeFfiStructGeneric =
     const Code<Message Function(String name)>(
   "FfiStructGeneric",
-  templateFfiStructGeneric,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3985,7 +3972,6 @@
     codeFieldAlreadyInitializedAtDeclaration =
     const Code<Message Function(String name)>(
         "FieldAlreadyInitializedAtDeclaration",
-        templateFieldAlreadyInitializedAtDeclaration,
         analyzerCodes: <String>[
       "FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION"
     ]);
@@ -4012,7 +3998,6 @@
     codeFieldAlreadyInitializedAtDeclarationCause =
     const Code<Message Function(String name)>(
         "FieldAlreadyInitializedAtDeclarationCause",
-        templateFieldAlreadyInitializedAtDeclarationCause,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4093,8 +4078,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeFinalFieldNotInitialized =
-    const Code<Message Function(String name)>(
-        "FinalFieldNotInitialized", templateFinalFieldNotInitialized,
+    const Code<Message Function(String name)>("FinalFieldNotInitialized",
         analyzerCodes: <String>["FINAL_NOT_INITIALIZED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4125,7 +4109,6 @@
     codeFinalFieldNotInitializedByConstructor =
     const Code<Message Function(String name)>(
         "FinalFieldNotInitializedByConstructor",
-        templateFinalFieldNotInitializedByConstructor,
         analyzerCodes: <String>["FINAL_NOT_INITIALIZED_CONSTRUCTOR_1"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4153,8 +4136,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeFinalFieldWithoutInitializer =
-    const Code<Message Function(String name)>(
-        "FinalFieldWithoutInitializer", templateFinalFieldWithoutInitializer,
+    const Code<Message Function(String name)>("FinalFieldWithoutInitializer",
         analyzerCodes: <String>["FINAL_NOT_INITIALIZED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4179,8 +4161,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeFinalNotAssignedError =
-    const Code<Message Function(String name)>(
-        "FinalNotAssignedError", templateFinalNotAssignedError,
+    const Code<Message Function(String name)>("FinalNotAssignedError",
         analyzerCodes: <String>["READ_POTENTIALLY_UNASSIGNED_FINAL"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4205,8 +4186,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeFinalPossiblyAssignedError =
-    const Code<Message Function(String name)>(
-        "FinalPossiblyAssignedError", templateFinalPossiblyAssignedError,
+    const Code<Message Function(String name)>("FinalPossiblyAssignedError",
         analyzerCodes: <String>["ASSIGNMENT_TO_FINAL_LOCAL"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4319,8 +4299,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeGetterNotFound =
-    const Code<Message Function(String name)>(
-        "GetterNotFound", templateGetterNotFound,
+    const Code<Message Function(String name)>("GetterNotFound",
         analyzerCodes: <String>["UNDEFINED_GETTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4390,8 +4369,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeIllegalMixin =
-    const Code<Message Function(String name)>(
-        "IllegalMixin", templateIllegalMixin,
+    const Code<Message Function(String name)>("IllegalMixin",
         analyzerCodes: <String>["ILLEGAL_MIXIN"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4413,8 +4391,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeIllegalMixinDueToConstructors =
-    const Code<Message Function(String name)>(
-        "IllegalMixinDueToConstructors", templateIllegalMixinDueToConstructors,
+    const Code<Message Function(String name)>("IllegalMixinDueToConstructors",
         analyzerCodes: <String>["MIXIN_DECLARES_CONSTRUCTOR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4440,7 +4417,6 @@
     codeIllegalMixinDueToConstructorsCause =
     const Code<Message Function(String name)>(
         "IllegalMixinDueToConstructorsCause",
-        templateIllegalMixinDueToConstructorsCause,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4538,14 +4514,14 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name, int count)> codeImplementsRepeated =
-    const Code<Message Function(String name, int count)>(
-        "ImplementsRepeated", templateImplementsRepeated,
+    const Code<Message Function(String name, int count)>("ImplementsRepeated",
         analyzerCodes: <String>["IMPLEMENTS_REPEATED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsImplementsRepeated(String name, int count) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
   return new Message(codeImplementsRepeated,
       message: """'${name}' can only be implemented once.""",
@@ -4566,8 +4542,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeImplementsSuperClass =
-    const Code<Message Function(String name)>(
-        "ImplementsSuperClass", templateImplementsSuperClass,
+    const Code<Message Function(String name)>("ImplementsSuperClass",
         analyzerCodes: <String>["IMPLEMENTS_SUPER_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4605,7 +4580,6 @@
     codeImplicitMixinOverride =
     const Code<Message Function(String name, String name2, String name3)>(
   "ImplicitMixinOverride",
-  templateImplicitMixinOverride,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4644,15 +4618,15 @@
 const Code<Message Function(String name, Uri uri_, Uri uri2_)>
     codeImportHidesImport =
     const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "ImportHidesImport", templateImportHidesImport,
+        "ImportHidesImport",
         severity: Severity.ignored);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsImportHidesImport(String name, Uri uri_, Uri uri2_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
   return new Message(codeImportHidesImport,
       message:
           """Import of '${name}' (from '${uri}') hides import from '${uri2}'.""",
@@ -4684,7 +4658,6 @@
     codeIncrementalCompilerIllegalParameter =
     const Code<Message Function(String string)>(
   "IncrementalCompilerIllegalParameter",
-  templateIncrementalCompilerIllegalParameter,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4709,7 +4682,6 @@
     codeIncrementalCompilerIllegalTypeParameter =
     const Code<Message Function(String string)>(
   "IncrementalCompilerIllegalTypeParameter",
-  templateIncrementalCompilerIllegalTypeParameter,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4729,13 +4701,12 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Uri uri_)> codeInferredPackageUri =
-    const Code<Message Function(Uri uri_)>(
-        "InferredPackageUri", templateInferredPackageUri,
+    const Code<Message Function(Uri uri_)>("InferredPackageUri",
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsInferredPackageUri(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeInferredPackageUri,
       message: """Interpreting this as package URI, '${uri}'.""",
       arguments: {'uri': uri_});
@@ -4790,14 +4761,13 @@
     codeInitializeFromDillNotSelfContained =
     const Code<Message Function(String string, Uri uri_)>(
         "InitializeFromDillNotSelfContained",
-        templateInitializeFromDillNotSelfContained,
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsInitializeFromDillNotSelfContained(
     String string, Uri uri_) {
   if (string.isEmpty) throw 'No string provided';
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeInitializeFromDillNotSelfContained,
       message:
           """Tried to initialize from a previous compilation (${string}), but the file was not self-contained. This might be a bug.
@@ -4823,7 +4793,6 @@
     codeInitializeFromDillNotSelfContainedNoDump =
     const Code<Message Function(String string)>(
         "InitializeFromDillNotSelfContainedNoDump",
-        templateInitializeFromDillNotSelfContainedNoDump,
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4866,7 +4835,6 @@
             Message Function(
                 String string, String string2, String string3, Uri uri_)>(
         "InitializeFromDillUnknownProblem",
-        templateInitializeFromDillUnknownProblem,
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4875,7 +4843,7 @@
   if (string.isEmpty) throw 'No string provided';
   if (string2.isEmpty) throw 'No string provided';
   if (string3.isEmpty) throw 'No string provided';
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeInitializeFromDillUnknownProblem,
       message:
           """Tried to initialize from a previous compilation (${string}), but couldn't.
@@ -4912,7 +4880,6 @@
     codeInitializeFromDillUnknownProblemNoDump =
     const Code<Message Function(String string, String string2, String string3)>(
         "InitializeFromDillUnknownProblemNoDump",
-        templateInitializeFromDillUnknownProblemNoDump,
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4953,8 +4920,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeInitializerForStaticField =
-    const Code<Message Function(String name)>(
-        "InitializerForStaticField", templateInitializerForStaticField,
+    const Code<Message Function(String name)>("InitializerForStaticField",
         analyzerCodes: <String>["INITIALIZER_FOR_STATIC_FIELD"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4986,12 +4952,11 @@
 const Code<Message Function(Uri uri_)> codeInputFileNotFound =
     const Code<Message Function(Uri uri_)>(
   "InputFileNotFound",
-  templateInputFileNotFound,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsInputFileNotFound(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeInputFileNotFound,
       message: """Input file not found: ${uri}.""", arguments: {'uri': uri_});
 }
@@ -5010,8 +4975,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeIntegerLiteralIsOutOfRange =
-    const Code<Message Function(String string)>(
-        "IntegerLiteralIsOutOfRange", templateIntegerLiteralIsOutOfRange,
+    const Code<Message Function(String string)>("IntegerLiteralIsOutOfRange",
         analyzerCodes: <String>["INTEGER_LITERAL_OUT_OF_RANGE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5040,7 +5004,6 @@
 const Code<Message Function(String name, String name2)> codeInterfaceCheck =
     const Code<Message Function(String name, String name2)>(
   "InterfaceCheck",
-  templateInterfaceCheck,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5087,7 +5050,6 @@
     codeInternalProblemConstructorNotFound =
     const Code<Message Function(String name, Uri uri_)>(
         "InternalProblemConstructorNotFound",
-        templateInternalProblemConstructorNotFound,
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5095,7 +5057,7 @@
     String name, Uri uri_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeInternalProblemConstructorNotFound,
       message: """No constructor named '${name}' in '${uri}'.""",
       arguments: {'name': name, 'uri': uri_});
@@ -5113,7 +5075,6 @@
 const Code<Message Function(String string)> codeInternalProblemContextSeverity =
     const Code<Message Function(String string)>(
         "InternalProblemContextSeverity",
-        templateInternalProblemContextSeverity,
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5135,7 +5096,7 @@
 const Code<Message Function(String name, String string)>
     codeInternalProblemDebugAbort =
     const Code<Message Function(String name, String string)>(
-        "InternalProblemDebugAbort", templateInternalProblemDebugAbort,
+        "InternalProblemDebugAbort",
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5189,8 +5150,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeInternalProblemNotFound =
-    const Code<Message Function(String name)>(
-        "InternalProblemNotFound", templateInternalProblemNotFound,
+    const Code<Message Function(String name)>("InternalProblemNotFound",
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5212,7 +5172,7 @@
 const Code<Message Function(String name, String name2)>
     codeInternalProblemNotFoundIn =
     const Code<Message Function(String name, String name2)>(
-        "InternalProblemNotFoundIn", templateInternalProblemNotFoundIn,
+        "InternalProblemNotFoundIn",
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5248,7 +5208,6 @@
     codeInternalProblemPrivateConstructorAccess =
     const Code<Message Function(String name)>(
         "InternalProblemPrivateConstructorAccess",
-        templateInternalProblemPrivateConstructorAccess,
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5282,7 +5241,7 @@
 const Code<Message Function(String name, String string)>
     codeInternalProblemStackNotEmpty =
     const Code<Message Function(String name, String string)>(
-        "InternalProblemStackNotEmpty", templateInternalProblemStackNotEmpty,
+        "InternalProblemStackNotEmpty",
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5306,7 +5265,7 @@
 const Code<Message Function(String string, String string2)>
     codeInternalProblemUnexpected =
     const Code<Message Function(String string, String string2)>(
-        "InternalProblemUnexpected", templateInternalProblemUnexpected,
+        "InternalProblemUnexpected",
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5334,7 +5293,6 @@
     codeInternalProblemUnfinishedTypeVariable =
     const Code<Message Function(String name, Uri uri_)>(
         "InternalProblemUnfinishedTypeVariable",
-        templateInternalProblemUnfinishedTypeVariable,
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5342,7 +5300,7 @@
     String name, Uri uri_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeInternalProblemUnfinishedTypeVariable,
       message:
           """Unfinished type variable '${name}' found in non-source library '${uri}'.""",
@@ -5360,7 +5318,7 @@
 const Code<Message Function(String string, String string2)>
     codeInternalProblemUnhandled =
     const Code<Message Function(String string, String string2)>(
-        "InternalProblemUnhandled", templateInternalProblemUnhandled,
+        "InternalProblemUnhandled",
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5381,8 +5339,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeInternalProblemUnimplemented =
-    const Code<Message Function(String string)>(
-        "InternalProblemUnimplemented", templateInternalProblemUnimplemented,
+    const Code<Message Function(String string)>("InternalProblemUnimplemented",
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5401,8 +5358,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeInternalProblemUnsupported =
-    const Code<Message Function(String name)>(
-        "InternalProblemUnsupported", templateInternalProblemUnsupported,
+    const Code<Message Function(String name)>("InternalProblemUnsupported",
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5424,12 +5380,11 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Uri uri_)> codeInternalProblemUriMissingScheme =
     const Code<Message Function(Uri uri_)>("InternalProblemUriMissingScheme",
-        templateInternalProblemUriMissingScheme,
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsInternalProblemUriMissingScheme(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeInternalProblemUriMissingScheme,
       message: """The URI '${uri}' has no scheme.""", arguments: {'uri': uri_});
 }
@@ -5446,7 +5401,6 @@
     codeInternalProblemVerificationError =
     const Code<Message Function(String string)>(
         "InternalProblemVerificationError",
-        templateInternalProblemVerificationError,
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5486,7 +5440,6 @@
 const Code<Message Function(String name)> codeInvalidBreakTarget =
     const Code<Message Function(String name)>(
   "InvalidBreakTarget",
-  templateInvalidBreakTarget,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5526,7 +5479,6 @@
 const Code<Message Function(String name)> codeInvalidContinueTarget =
     const Code<Message Function(String name)>(
   "InvalidContinueTarget",
-  templateInvalidContinueTarget,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5549,7 +5501,6 @@
     codeInvalidGetterSetterTypeFieldContext =
     const Code<Message Function(String name)>(
         "InvalidGetterSetterTypeFieldContext",
-        templateInvalidGetterSetterTypeFieldContext,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5573,7 +5524,6 @@
     codeInvalidGetterSetterTypeGetterContext =
     const Code<Message Function(String name)>(
         "InvalidGetterSetterTypeGetterContext",
-        templateInvalidGetterSetterTypeGetterContext,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5597,7 +5547,6 @@
     codeInvalidGetterSetterTypeSetterContext =
     const Code<Message Function(String name)>(
         "InvalidGetterSetterTypeSetterContext",
-        templateInvalidGetterSetterTypeSetterContext,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5659,16 +5608,14 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeInvalidOperator =
-    const Code<Message Function(Token token)>(
-        "InvalidOperator", templateInvalidOperator,
-        index: 39);
+    const Code<Message Function(Token token)>("InvalidOperator", index: 39);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsInvalidOperator(Token token) {
   String lexeme = token.lexeme;
   return new Message(codeInvalidOperator,
       message: """The string '${lexeme}' isn't a user-definable operator.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5682,12 +5629,11 @@
 const Code<Message Function(Uri uri_, String string)> codeInvalidPackageUri =
     const Code<Message Function(Uri uri_, String string)>(
   "InvalidPackageUri",
-  templateInvalidPackageUri,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsInvalidPackageUri(Uri uri_, String string) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   if (string.isEmpty) throw 'No string provided';
   return new Message(codeInvalidPackageUri,
       message: """Invalid package URI '${uri}':
@@ -5742,7 +5688,6 @@
     codeInvalidTypeVariableInSupertype =
     const Code<Message Function(String name, String string2, String name2)>(
   "InvalidTypeVariableInSupertype",
-  templateInvalidTypeVariableInSupertype,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5779,7 +5724,6 @@
         Message Function(
             String string, String name, String string2, String name2)>(
   "InvalidTypeVariableInSupertypeWithVariance",
-  templateInvalidTypeVariableInSupertypeWithVariance,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5819,7 +5763,6 @@
     codeInvalidTypeVariableVariancePosition =
     const Code<Message Function(String string, String name, String string2)>(
   "InvalidTypeVariableVariancePosition",
-  templateInvalidTypeVariableVariancePosition,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5849,7 +5792,6 @@
     codeInvalidTypeVariableVariancePositionInReturnType =
     const Code<Message Function(String string, String name, String string2)>(
   "InvalidTypeVariableVariancePositionInReturnType",
-  templateInvalidTypeVariableVariancePositionInReturnType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5905,8 +5847,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeInvokeNonFunction =
-    const Code<Message Function(String name)>(
-        "InvokeNonFunction", templateInvokeNonFunction,
+    const Code<Message Function(String name)>("InvokeNonFunction",
         analyzerCodes: <String>["INVOCATION_OF_NON_FUNCTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5947,7 +5888,6 @@
     codeJsInteropDartClassExtendsJSClass =
     const Code<Message Function(String name, String name2)>(
   "JsInteropDartClassExtendsJSClass",
-  templateJsInteropDartClassExtendsJSClass,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6015,7 +5955,6 @@
     codeJsInteropJSClassExtendsDartClass =
     const Code<Message Function(String name, String name2)>(
   "JsInteropJSClassExtendsDartClass",
-  templateJsInteropJSClassExtendsDartClass,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6044,6 +5983,39 @@
     tip: r"""Try replacing them with normal or optional parameters.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String name2,
+        String
+            string3)> templateJsInteropNativeClassInAnnotation = const Template<
+        Message Function(String name, String name2, String string3)>(
+    messageTemplate:
+        r"""JS interop class '#name' conflicts with natively supported class '#name2' in '#string3'.""",
+    withArguments: _withArgumentsJsInteropNativeClassInAnnotation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2, String string3)>
+    codeJsInteropNativeClassInAnnotation =
+    const Code<Message Function(String name, String name2, String string3)>(
+  "JsInteropNativeClassInAnnotation",
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsJsInteropNativeClassInAnnotation(
+    String name, String name2, String string3) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  if (string3.isEmpty) throw 'No string provided';
+  return new Message(codeJsInteropNativeClassInAnnotation,
+      message:
+          """JS interop class '${name}' conflicts with natively supported class '${name2}' in '${string3}'.""",
+      arguments: {'name': name, 'name2': name2, 'string3': string3});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeJsInteropNonExternalConstructor =
     messageJsInteropNonExternalConstructor;
 
@@ -6076,8 +6048,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeLabelNotFound =
-    const Code<Message Function(String name)>(
-        "LabelNotFound", templateLabelNotFound,
+    const Code<Message Function(String name)>("LabelNotFound",
         analyzerCodes: <String>["LABEL_UNDEFINED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6166,12 +6137,13 @@
 const Code<Message Function(int count, int count2)> codeLanguageVersionTooHigh =
     const Code<Message Function(int count, int count2)>(
   "LanguageVersionTooHigh",
-  templateLanguageVersionTooHigh,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsLanguageVersionTooHigh(int count, int count2) {
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (count2 == null) throw 'No count provided';
   return new Message(codeLanguageVersionTooHigh,
       message:
@@ -6191,7 +6163,6 @@
 const Code<Message Function(String name)> codeLateDefinitelyAssignedError =
     const Code<Message Function(String name)>(
   "LateDefinitelyAssignedError",
-  templateLateDefinitelyAssignedError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6217,7 +6188,6 @@
 const Code<Message Function(String name)> codeLateDefinitelyUnassignedError =
     const Code<Message Function(String name)>(
   "LateDefinitelyUnassignedError",
-  templateLateDefinitelyUnassignedError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6262,13 +6232,12 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Uri uri_)> codeLoadLibraryHidesMember =
-    const Code<Message Function(Uri uri_)>(
-        "LoadLibraryHidesMember", templateLoadLibraryHidesMember,
+    const Code<Message Function(Uri uri_)>("LoadLibraryHidesMember",
         severity: Severity.ignored);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsLoadLibraryHidesMember(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeLoadLibraryHidesMember,
       message:
           """The library '${uri}' defines a top-level member named 'loadLibrary'. This member is hidden by the special member 'loadLibrary' that the language adds to support deferred loading.""",
@@ -6298,14 +6267,14 @@
 const Code<Message Function(String name, Uri uri_)>
     codeLocalDefinitionHidesExport =
     const Code<Message Function(String name, Uri uri_)>(
-        "LocalDefinitionHidesExport", templateLocalDefinitionHidesExport,
+        "LocalDefinitionHidesExport",
         severity: Severity.ignored);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsLocalDefinitionHidesExport(String name, Uri uri_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeLocalDefinitionHidesExport,
       message: """Local definition of '${name}' hides export from '${uri}'.""",
       arguments: {'name': name, 'uri': uri_});
@@ -6323,14 +6292,14 @@
 const Code<Message Function(String name, Uri uri_)>
     codeLocalDefinitionHidesImport =
     const Code<Message Function(String name, Uri uri_)>(
-        "LocalDefinitionHidesImport", templateLocalDefinitionHidesImport,
+        "LocalDefinitionHidesImport",
         severity: Severity.ignored);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsLocalDefinitionHidesImport(String name, Uri uri_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeLocalDefinitionHidesImport,
       message: """Local definition of '${name}' hides import from '${uri}'.""",
       arguments: {'name': name, 'uri': uri_});
@@ -6432,8 +6401,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeMethodNotFound =
-    const Code<Message Function(String name)>(
-        "MethodNotFound", templateMethodNotFound,
+    const Code<Message Function(String name)>("MethodNotFound",
         analyzerCodes: <String>["UNDEFINED_METHOD"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6506,12 +6474,12 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(int count)> codeMissingExplicitTypeArguments =
-    const Code<Message Function(int count)>(
-        "MissingExplicitTypeArguments", templateMissingExplicitTypeArguments,
+    const Code<Message Function(int count)>("MissingExplicitTypeArguments",
         severity: Severity.ignored);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsMissingExplicitTypeArguments(int count) {
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
   return new Message(codeMissingExplicitTypeArguments,
       message: """No type arguments provided, ${count} possible.""",
@@ -6561,8 +6529,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeMissingImplementationCause =
-    const Code<Message Function(String name)>(
-        "MissingImplementationCause", templateMissingImplementationCause,
+    const Code<Message Function(String name)>("MissingImplementationCause",
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6596,7 +6563,6 @@
     codeMissingImplementationNotAbstract =
     const Code<Message Function(String name, List<String> _names)>(
         "MissingImplementationNotAbstract",
-        templateMissingImplementationNotAbstract,
         analyzerCodes: <String>["CONCRETE_CLASS_WITH_ABSTRACT_MEMBER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6665,13 +6631,12 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Uri uri_)> codeMissingPartOf =
-    const Code<Message Function(Uri uri_)>(
-        "MissingPartOf", templateMissingPartOf,
+    const Code<Message Function(Uri uri_)>("MissingPartOf",
         analyzerCodes: <String>["PART_OF_NON_PART"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsMissingPartOf(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeMissingPartOf,
       message:
           """Can't use '${uri}' as a part, because it has no 'part of' declaration.""",
@@ -6733,7 +6698,7 @@
 const Code<Message Function(String string, String string2)>
     codeModifierOutOfOrder =
     const Code<Message Function(String string, String string2)>(
-        "ModifierOutOfOrder", templateModifierOutOfOrder,
+        "ModifierOutOfOrder",
         index: 56);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6844,7 +6809,6 @@
 const Code<Message Function(String name, String name2)> codeNamedMixinOverride =
     const Code<Message Function(String name, String name2)>(
   "NamedMixinOverride",
-  templateNamedMixinOverride,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6921,7 +6885,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeNoFormals =
-    const Code<Message Function(Token token)>("NoFormals", templateNoFormals,
+    const Code<Message Function(Token token)>("NoFormals",
         analyzerCodes: <String>["MISSING_FUNCTION_PARAMETERS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6931,7 +6895,7 @@
       message: """A function should have formal parameters.""",
       tip:
           """Try adding '()' after '${lexeme}', or add 'get' before '${lexeme}' to declare a getter.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6942,8 +6906,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeNoSuchNamedParameter =
-    const Code<Message Function(String name)>(
-        "NoSuchNamedParameter", templateNoSuchNamedParameter,
+    const Code<Message Function(String name)>("NoSuchNamedParameter",
         analyzerCodes: <String>["UNDEFINED_NAMED_PARAMETER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6989,7 +6952,7 @@
 const Code<Message Function(String character, int codePoint)>
     codeNonAsciiIdentifier =
     const Code<Message Function(String character, int codePoint)>(
-        "NonAsciiIdentifier", templateNonAsciiIdentifier,
+        "NonAsciiIdentifier",
         analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7001,7 +6964,7 @@
       message:
           """The non-ASCII character '${character}' (${unicode}) can't be used in identifiers, only in strings and comments.""",
       tip: """Try using an US-ASCII letter, a digit, '_' (an underscore), or '\$' (a dollar sign).""",
-      arguments: {'character': character, 'codePoint': codePoint});
+      arguments: {'character': character, 'unicode': codePoint});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7016,8 +6979,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(int codePoint)> codeNonAsciiWhitespace =
-    const Code<Message Function(int codePoint)>(
-        "NonAsciiWhitespace", templateNonAsciiWhitespace,
+    const Code<Message Function(int codePoint)>("NonAsciiWhitespace",
         analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7027,7 +6989,7 @@
   return new Message(codeNonAsciiWhitespace,
       message:
           """The non-ASCII space character ${unicode} can only be used in strings and comments.""",
-      arguments: {'codePoint': codePoint});
+      arguments: {'unicode': codePoint});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7075,7 +7037,6 @@
 const Code<Message Function(String name)> codeNonNullableNotAssignedError =
     const Code<Message Function(String name)>(
   "NonNullableNotAssignedError",
-  templateNonNullableNotAssignedError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7113,7 +7074,6 @@
 const Code<Message Function(String string)> codeNonNullableOptOutExplicit =
     const Code<Message Function(String string)>(
   "NonNullableOptOutExplicit",
-  templateNonNullableOptOutExplicit,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7141,7 +7101,6 @@
 const Code<Message Function(String string)> codeNonNullableOptOutImplicit =
     const Code<Message Function(String string)>(
   "NonNullableOptOutImplicit",
-  templateNonNullableOptOutImplicit,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7175,8 +7134,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeNonSimpleBoundViaReference =
-    const Code<Message Function(String name)>(
-        "NonSimpleBoundViaReference", templateNonSimpleBoundViaReference,
+    const Code<Message Function(String name)>("NonSimpleBoundViaReference",
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7200,8 +7158,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeNonSimpleBoundViaVariable =
-    const Code<Message Function(String name)>(
-        "NonSimpleBoundViaVariable", templateNonSimpleBoundViaVariable,
+    const Code<Message Function(String name)>("NonSimpleBoundViaVariable",
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7259,7 +7216,7 @@
 const Code<Message Function(String name, String name2)>
     codeNotAPrefixInTypeAnnotation =
     const Code<Message Function(String name, String name2)>(
-        "NotAPrefixInTypeAnnotation", templateNotAPrefixInTypeAnnotation,
+        "NotAPrefixInTypeAnnotation",
         analyzerCodes: <String>["NOT_A_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7282,7 +7239,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeNotAType =
-    const Code<Message Function(String name)>("NotAType", templateNotAType,
+    const Code<Message Function(String name)>("NotAType",
         analyzerCodes: <String>["NOT_A_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7318,7 +7275,6 @@
 const Code<Message Function(Token token)> codeNotBinaryOperator =
     const Code<Message Function(Token token)>(
   "NotBinaryOperator",
-  templateNotBinaryOperator,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7326,7 +7282,7 @@
   String lexeme = token.lexeme;
   return new Message(codeNotBinaryOperator,
       message: """'${lexeme}' isn't a binary operator.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7337,8 +7293,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string)> codeNotConstantExpression =
-    const Code<Message Function(String string)>(
-        "NotConstantExpression", templateNotConstantExpression,
+    const Code<Message Function(String string)>("NotConstantExpression",
         analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7373,7 +7328,6 @@
 const Code<Message Function(String name)> codeNullableInterfaceError =
     const Code<Message Function(String name)>(
   "NullableInterfaceError",
-  templateNullableInterfaceError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7396,7 +7350,6 @@
 const Code<Message Function(String name)> codeNullableMixinError =
     const Code<Message Function(String name)>(
   "NullableMixinError",
-  templateNullableMixinError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7428,7 +7381,6 @@
 const Code<Message Function(String name)> codeNullableSuperclassError =
     const Code<Message Function(String name)>(
   "NullableSuperclassError",
-  templateNullableSuperclassError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7451,7 +7403,6 @@
 const Code<Message Function(String name)> codeNullableTearoffError =
     const Code<Message Function(String name)>(
   "NullableTearoffError",
-  templateNullableTearoffError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7511,9 +7462,9 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeOperatorMinusParameterMismatch =
     const Code<Message Function(String name)>("OperatorMinusParameterMismatch",
-        templateOperatorMinusParameterMismatch, analyzerCodes: <String>[
-  "WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS"
-]);
+        analyzerCodes: <String>[
+      "WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS"
+    ]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsOperatorMinusParameterMismatch(String name) {
@@ -7537,7 +7488,6 @@
 const Code<Message Function(String name)> codeOperatorParameterMismatch0 =
     const Code<Message Function(String name)>(
   "OperatorParameterMismatch0",
-  templateOperatorParameterMismatch0,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7559,8 +7509,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeOperatorParameterMismatch1 =
-    const Code<Message Function(String name)>(
-        "OperatorParameterMismatch1", templateOperatorParameterMismatch1,
+    const Code<Message Function(String name)>("OperatorParameterMismatch1",
         analyzerCodes: <String>["WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7582,8 +7531,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeOperatorParameterMismatch2 =
-    const Code<Message Function(String name)>(
-        "OperatorParameterMismatch2", templateOperatorParameterMismatch2,
+    const Code<Message Function(String name)>("OperatorParameterMismatch2",
         analyzerCodes: <String>["WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7623,8 +7571,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeOverriddenMethodCause =
-    const Code<Message Function(String name)>(
-        "OverriddenMethodCause", templateOverriddenMethodCause,
+    const Code<Message Function(String name)>("OverriddenMethodCause",
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7651,7 +7598,7 @@
 const Code<Message Function(String name, String name2)>
     codeOverrideFewerNamedArguments =
     const Code<Message Function(String name, String name2)>(
-        "OverrideFewerNamedArguments", templateOverrideFewerNamedArguments,
+        "OverrideFewerNamedArguments",
         analyzerCodes: <String>["INVALID_OVERRIDE_NAMED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7682,7 +7629,6 @@
     codeOverrideFewerPositionalArguments =
     const Code<Message Function(String name, String name2)>(
         "OverrideFewerPositionalArguments",
-        templateOverrideFewerPositionalArguments,
         analyzerCodes: <String>["INVALID_OVERRIDE_POSITIONAL"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7715,7 +7661,6 @@
     codeOverrideMismatchNamedParameter =
     const Code<Message Function(String name, String name2, String name3)>(
         "OverrideMismatchNamedParameter",
-        templateOverrideMismatchNamedParameter,
         analyzerCodes: <String>["INVALID_OVERRIDE_NAMED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7746,7 +7691,6 @@
     codeOverrideMismatchRequiredNamedParameter =
     const Code<Message Function(String name, String name2, String name3)>(
   "OverrideMismatchRequiredNamedParameter",
-  templateOverrideMismatchRequiredNamedParameter,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7779,7 +7723,7 @@
 const Code<Message Function(String name, String name2)>
     codeOverrideMoreRequiredArguments =
     const Code<Message Function(String name, String name2)>(
-        "OverrideMoreRequiredArguments", templateOverrideMoreRequiredArguments,
+        "OverrideMoreRequiredArguments",
         analyzerCodes: <String>["INVALID_OVERRIDE_REQUIRED"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7809,7 +7753,7 @@
 const Code<Message Function(String name, String name2)>
     codeOverrideTypeVariablesMismatch =
     const Code<Message Function(String name, String name2)>(
-        "OverrideTypeVariablesMismatch", templateOverrideTypeVariablesMismatch,
+        "OverrideTypeVariablesMismatch",
         analyzerCodes: <String>["INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7836,14 +7780,13 @@
 const Code<Message Function(String name, Uri uri_)> codePackageNotFound =
     const Code<Message Function(String name, Uri uri_)>(
   "PackageNotFound",
-  templatePackageNotFound,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsPackageNotFound(String name, Uri uri_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codePackageNotFound,
       message: """Could not resolve the package '${name}' in '${uri}'.""",
       arguments: {'name': name, 'uri': uri_});
@@ -7859,7 +7802,6 @@
 const Code<Message Function(String string)> codePackagesFileFormat =
     const Code<Message Function(String string)>(
   "PackagesFileFormat",
-  templatePackagesFileFormat,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7918,13 +7860,12 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Uri uri_)> codePartOfInLibrary =
-    const Code<Message Function(Uri uri_)>(
-        "PartOfInLibrary", templatePartOfInLibrary,
+    const Code<Message Function(Uri uri_)>("PartOfInLibrary",
         analyzerCodes: <String>["IMPORT_OF_NON_LIBRARY"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsPartOfInLibrary(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codePartOfInLibrary,
       message:
           """Can't import '${uri}', because it has a 'part of' declaration.""",
@@ -7949,13 +7890,13 @@
 const Code<Message Function(Uri uri_, String name, String name2)>
     codePartOfLibraryNameMismatch =
     const Code<Message Function(Uri uri_, String name, String name2)>(
-        "PartOfLibraryNameMismatch", templatePartOfLibraryNameMismatch,
+        "PartOfLibraryNameMismatch",
         analyzerCodes: <String>["PART_OF_DIFFERENT_LIBRARY"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsPartOfLibraryNameMismatch(
     Uri uri_, String name, String name2) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
   if (name2.isEmpty) throw 'No name provided';
@@ -8020,14 +7961,14 @@
 const Code<Message Function(Uri uri_, Uri uri2_, Uri uri3_)>
     codePartOfUriMismatch =
     const Code<Message Function(Uri uri_, Uri uri2_, Uri uri3_)>(
-        "PartOfUriMismatch", templatePartOfUriMismatch,
+        "PartOfUriMismatch",
         analyzerCodes: <String>["PART_OF_DIFFERENT_LIBRARY"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsPartOfUriMismatch(Uri uri_, Uri uri2_, Uri uri3_) {
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
-  String uri3 = relativizeUri(uri3_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
+  String? uri3 = relativizeUri(uri3_);
   return new Message(codePartOfUriMismatch,
       message:
           """Using '${uri}' as part of '${uri2}' but its 'part of' declaration says '${uri3}'.""",
@@ -8052,13 +7993,13 @@
 const Code<Message Function(Uri uri_, Uri uri2_, String name)>
     codePartOfUseUri =
     const Code<Message Function(Uri uri_, Uri uri2_, String name)>(
-        "PartOfUseUri", templatePartOfUseUri,
+        "PartOfUseUri",
         analyzerCodes: <String>["PART_OF_UNNAMED_LIBRARY"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsPartOfUseUri(Uri uri_, Uri uri2_, String name) {
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
   return new Message(codePartOfUseUri,
@@ -8084,12 +8025,12 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Uri uri_)> codePartTwice =
-    const Code<Message Function(Uri uri_)>("PartTwice", templatePartTwice,
+    const Code<Message Function(Uri uri_)>("PartTwice",
         analyzerCodes: <String>["DUPLICATE_PART"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsPartTwice(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codePartTwice,
       message: """Can't use '${uri}' as a part more than once.""",
       arguments: {'uri': uri_});
@@ -8143,14 +8084,13 @@
 const Code<Message Function(String name, Uri uri_)> codePatchInjectionFailed =
     const Code<Message Function(String name, Uri uri_)>(
   "PatchInjectionFailed",
-  templatePatchInjectionFailed,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsPatchInjectionFailed(String name, Uri uri_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codePatchInjectionFailed,
       message: """Can't inject '${name}' into '${uri}'.""",
       tip: """Try adding '@patch'.""",
@@ -8288,8 +8228,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeRedirectionTargetNotFound =
-    const Code<Message Function(String name)>(
-        "RedirectionTargetNotFound", templateRedirectionTargetNotFound,
+    const Code<Message Function(String name)>("RedirectionTargetNotFound",
         analyzerCodes: <String>["REDIRECT_TO_MISSING_CONSTRUCTOR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8315,7 +8254,6 @@
     codeRequiredNamedParameterHasDefaultValueError =
     const Code<Message Function(String name)>(
   "RequiredNamedParameterHasDefaultValueError",
-  templateRequiredNamedParameterHasDefaultValueError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8406,12 +8344,11 @@
 const Code<Message Function(Uri uri_)> codeSdkRootNotFound =
     const Code<Message Function(Uri uri_)>(
   "SdkRootNotFound",
-  templateSdkRootNotFound,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsSdkRootNotFound(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeSdkRootNotFound,
       message: """SDK root directory not found: ${uri}.""",
       arguments: {'uri': uri_});
@@ -8432,12 +8369,11 @@
 const Code<Message Function(Uri uri_)> codeSdkSpecificationNotFound =
     const Code<Message Function(Uri uri_)>(
   "SdkSpecificationNotFound",
-  templateSdkSpecificationNotFound,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsSdkSpecificationNotFound(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeSdkSpecificationNotFound,
       message: """SDK libraries specification not found: ${uri}.""",
       tip:
@@ -8455,12 +8391,11 @@
 const Code<Message Function(Uri uri_)> codeSdkSummaryNotFound =
     const Code<Message Function(Uri uri_)>(
   "SdkSummaryNotFound",
-  templateSdkSummaryNotFound,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsSdkSummaryNotFound(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeSdkSummaryNotFound,
       message: """SDK summary not found: ${uri}.""", arguments: {'uri': uri_});
 }
@@ -8502,8 +8437,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeSetterNotFound =
-    const Code<Message Function(String name)>(
-        "SetterNotFound", templateSetterNotFound,
+    const Code<Message Function(String name)>("SetterNotFound",
         analyzerCodes: <String>["UNDEFINED_SETTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8555,18 +8489,22 @@
         num _num3)> codeSourceBodySummary = const Code<
     Message Function(int count, int count2, num _num1, num _num2, num _num3)>(
   "SourceBodySummary",
-  templateSourceBodySummary,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsSourceBodySummary(
     int count, int count2, num _num1, num _num2, num _num3) {
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (count2 == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (_num1 == null) throw 'No number provided';
   String num1 = _num1.toStringAsFixed(3);
+  // ignore: unnecessary_null_comparison
   if (_num2 == null) throw 'No number provided';
   String num2 = _num2.toStringAsFixed(3).padLeft(12);
+  // ignore: unnecessary_null_comparison
   if (_num3 == null) throw 'No number provided';
   String num3 = _num3.toStringAsFixed(3).padLeft(12);
   return new Message(codeSourceBodySummary,
@@ -8606,18 +8544,22 @@
         num _num3)> codeSourceOutlineSummary = const Code<
     Message Function(int count, int count2, num _num1, num _num2, num _num3)>(
   "SourceOutlineSummary",
-  templateSourceOutlineSummary,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsSourceOutlineSummary(
     int count, int count2, num _num1, num _num2, num _num3) {
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (count2 == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (_num1 == null) throw 'No number provided';
   String num1 = _num1.toStringAsFixed(3);
+  // ignore: unnecessary_null_comparison
   if (_num2 == null) throw 'No number provided';
   String num2 = _num2.toStringAsFixed(3).padLeft(12);
+  // ignore: unnecessary_null_comparison
   if (_num3 == null) throw 'No number provided';
   String num3 = _num3.toStringAsFixed(3).padLeft(12);
   return new Message(codeSourceOutlineSummary,
@@ -8727,7 +8669,6 @@
     codeStrongModeNNBDPackageOptOut =
     const Code<Message Function(List<String> _names)>(
   "StrongModeNNBDPackageOptOut",
-  templateStrongModeNNBDPackageOptOut,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8803,8 +8744,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeSuperclassHasNoConstructor =
-    const Code<Message Function(String name)>(
-        "SuperclassHasNoConstructor", templateSuperclassHasNoConstructor,
+    const Code<Message Function(String name)>("SuperclassHasNoConstructor",
         analyzerCodes: <String>[
       "UNDEFINED_CONSTRUCTOR_IN_INITIALIZER",
       "UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT"
@@ -8834,7 +8774,6 @@
     codeSuperclassHasNoDefaultConstructor =
     const Code<Message Function(String name)>(
         "SuperclassHasNoDefaultConstructor",
-        templateSuperclassHasNoDefaultConstructor,
         analyzerCodes: <String>["NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8855,8 +8794,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeSuperclassHasNoGetter =
-    const Code<Message Function(String name)>(
-        "SuperclassHasNoGetter", templateSuperclassHasNoGetter,
+    const Code<Message Function(String name)>("SuperclassHasNoGetter",
         analyzerCodes: <String>["UNDEFINED_SUPER_GETTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8876,8 +8814,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeSuperclassHasNoMethod =
-    const Code<Message Function(String name)>(
-        "SuperclassHasNoMethod", templateSuperclassHasNoMethod,
+    const Code<Message Function(String name)>("SuperclassHasNoMethod",
         analyzerCodes: <String>["UNDEFINED_SUPER_METHOD"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8897,8 +8834,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeSuperclassHasNoSetter =
-    const Code<Message Function(String name)>(
-        "SuperclassHasNoSetter", templateSuperclassHasNoSetter,
+    const Code<Message Function(String name)>("SuperclassHasNoSetter",
         analyzerCodes: <String>["UNDEFINED_SUPER_SETTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8924,7 +8860,6 @@
 const Code<Message Function(String name)> codeSuperclassMethodArgumentMismatch =
     const Code<Message Function(String name)>(
   "SuperclassMethodArgumentMismatch",
-  templateSuperclassMethodArgumentMismatch,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8953,8 +8888,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeSupertypeIsIllegal =
-    const Code<Message Function(String name)>(
-        "SupertypeIsIllegal", templateSupertypeIsIllegal,
+    const Code<Message Function(String name)>("SupertypeIsIllegal",
         analyzerCodes: <String>["EXTENDS_NON_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -8975,8 +8909,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeSupertypeIsTypeVariable =
-    const Code<Message Function(String name)>(
-        "SupertypeIsTypeVariable", templateSupertypeIsTypeVariable,
+    const Code<Message Function(String name)>("SupertypeIsTypeVariable",
         analyzerCodes: <String>["EXTENDS_NON_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9047,8 +8980,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeThisAccessInFieldInitializer =
-    const Code<Message Function(String name)>(
-        "ThisAccessInFieldInitializer", templateThisAccessInFieldInitializer,
+    const Code<Message Function(String name)>("ThisAccessInFieldInitializer",
         analyzerCodes: <String>["THIS_ACCESS_FROM_FIELD_INITIALIZER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9092,7 +9024,6 @@
     codeThisOrSuperAccessInFieldInitializer =
     const Code<Message Function(String string)>(
         "ThisOrSuperAccessInFieldInitializer",
-        templateThisOrSuperAccessInFieldInitializer,
         analyzerCodes: <String>["THIS_ACCESS_FROM_INITIALIZER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9116,13 +9047,14 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(int count, int count2)> codeTooFewArguments =
-    const Code<Message Function(int count, int count2)>(
-        "TooFewArguments", templateTooFewArguments,
+    const Code<Message Function(int count, int count2)>("TooFewArguments",
         analyzerCodes: <String>["NOT_ENOUGH_REQUIRED_ARGUMENTS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsTooFewArguments(int count, int count2) {
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (count2 == null) throw 'No count provided';
   return new Message(codeTooFewArguments,
       message:
@@ -9144,13 +9076,14 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(int count, int count2)> codeTooManyArguments =
-    const Code<Message Function(int count, int count2)>(
-        "TooManyArguments", templateTooManyArguments,
+    const Code<Message Function(int count, int count2)>("TooManyArguments",
         analyzerCodes: <String>["EXTRA_POSITIONAL_ARGUMENTS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsTooManyArguments(int count, int count2) {
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
+  // ignore: unnecessary_null_comparison
   if (count2 == null) throw 'No count provided';
   return new Message(codeTooManyArguments,
       message:
@@ -9188,12 +9121,12 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(int count)> codeTypeArgumentMismatch =
-    const Code<Message Function(int count)>(
-        "TypeArgumentMismatch", templateTypeArgumentMismatch,
+    const Code<Message Function(int count)>("TypeArgumentMismatch",
         analyzerCodes: <String>["WRONG_NUMBER_OF_TYPE_ARGUMENTS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsTypeArgumentMismatch(int count) {
+  // ignore: unnecessary_null_comparison
   if (count == null) throw 'No count provided';
   return new Message(codeTypeArgumentMismatch,
       message: """Expected ${count} type arguments.""",
@@ -9211,8 +9144,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeTypeArgumentsOnTypeVariable =
-    const Code<Message Function(String name)>(
-        "TypeArgumentsOnTypeVariable", templateTypeArgumentsOnTypeVariable,
+    const Code<Message Function(String name)>("TypeArgumentsOnTypeVariable",
         index: 13);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9243,8 +9175,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeTypeNotFound =
-    const Code<Message Function(String name)>(
-        "TypeNotFound", templateTypeNotFound,
+    const Code<Message Function(String name)>("TypeNotFound",
         analyzerCodes: <String>["UNDEFINED_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9265,14 +9196,13 @@
 const Code<Message Function(String name, Uri uri_)> codeTypeOrigin =
     const Code<Message Function(String name, Uri uri_)>(
   "TypeOrigin",
-  templateTypeOrigin,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsTypeOrigin(String name, Uri uri_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeTypeOrigin,
       message: """'${name}' is from '${uri}'.""",
       arguments: {'name': name, 'uri': uri_});
@@ -9290,15 +9220,14 @@
     codeTypeOriginWithFileUri =
     const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
   "TypeOriginWithFileUri",
-  templateTypeOriginWithFileUri,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsTypeOriginWithFileUri(String name, Uri uri_, Uri uri2_) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  String uri2 = relativizeUri(uri2_);
+  String? uri = relativizeUri(uri_);
+  String? uri2 = relativizeUri(uri2_);
   return new Message(codeTypeOriginWithFileUri,
       message: """'${name}' is from '${uri}' ('${uri2}').""",
       arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
@@ -9324,7 +9253,6 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String name)> codeTypeVariableDuplicatedNameCause =
     const Code<Message Function(String name)>("TypeVariableDuplicatedNameCause",
-        templateTypeVariableDuplicatedNameCause,
         severity: Severity.context);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9451,6 +9379,30 @@
     tip: r"""Try adding a backslash (\) to escape the '$'.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Token
+            token)> templateUnexpectedModifierInNonNnbd = const Template<
+        Message Function(Token token)>(
+    messageTemplate:
+        r"""The modifier '#lexeme' is only available in null safe libraries.""",
+    withArguments: _withArgumentsUnexpectedModifierInNonNnbd);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Token token)> codeUnexpectedModifierInNonNnbd =
+    const Code<Message Function(Token token)>("UnexpectedModifierInNonNnbd",
+        analyzerCodes: <String>["UNEXPECTED_TOKEN"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUnexpectedModifierInNonNnbd(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeUnexpectedModifierInNonNnbd,
+      message:
+          """The modifier '${lexeme}' is only available in null safe libraries.""",
+      arguments: {'lexeme': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(Token token)> templateUnexpectedToken =
     const Template<Message Function(Token token)>(
         messageTemplate: r"""Unexpected token '#lexeme'.""",
@@ -9458,8 +9410,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeUnexpectedToken =
-    const Code<Message Function(Token token)>(
-        "UnexpectedToken", templateUnexpectedToken,
+    const Code<Message Function(Token token)>("UnexpectedToken",
         analyzerCodes: <String>["UNEXPECTED_TOKEN"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9467,7 +9418,7 @@
   String lexeme = token.lexeme;
   return new Message(codeUnexpectedToken,
       message: """Unexpected token '${lexeme}'.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9479,8 +9430,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(String string, Token token)> codeUnmatchedToken =
-    const Code<Message Function(String string, Token token)>(
-        "UnmatchedToken", templateUnmatchedToken,
+    const Code<Message Function(String string, Token token)>("UnmatchedToken",
         analyzerCodes: <String>["EXPECTED_TOKEN"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9489,7 +9439,7 @@
   String lexeme = token.lexeme;
   return new Message(codeUnmatchedToken,
       message: """Can't find '${string}' to match '${lexeme}'.""",
-      arguments: {'string': string, 'token': token});
+      arguments: {'string': string, 'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9508,7 +9458,6 @@
     codeUnresolvedPrefixInTypeAnnotation =
     const Code<Message Function(String name, String name2)>(
         "UnresolvedPrefixInTypeAnnotation",
-        templateUnresolvedPrefixInTypeAnnotation,
         analyzerCodes: <String>["NOT_A_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9534,7 +9483,6 @@
 const Code<Message Function(String string)> codeUnspecified =
     const Code<Message Function(String string)>(
   "Unspecified",
-  templateUnspecified,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9552,8 +9500,7 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Token token)> codeUnsupportedOperator =
-    const Code<Message Function(Token token)>(
-        "UnsupportedOperator", templateUnsupportedOperator,
+    const Code<Message Function(Token token)>("UnsupportedOperator",
         analyzerCodes: <String>["UNSUPPORTED_OPERATOR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9561,7 +9508,7 @@
   String lexeme = token.lexeme;
   return new Message(codeUnsupportedOperator,
       message: """The '${lexeme}' operator is not supported.""",
-      arguments: {'token': token});
+      arguments: {'lexeme': token});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9595,7 +9542,7 @@
 const Code<Message Function(String string, String string2)>
     codeUnterminatedString =
     const Code<Message Function(String string, String string2)>(
-        "UnterminatedString", templateUnterminatedString,
+        "UnterminatedString",
         analyzerCodes: <String>["UNTERMINATED_STRING_LITERAL"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9622,40 +9569,18 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(Uri uri_)> codeUntranslatableUri =
-    const Code<Message Function(Uri uri_)>(
-        "UntranslatableUri", templateUntranslatableUri,
+    const Code<Message Function(Uri uri_)>("UntranslatableUri",
         analyzerCodes: <String>["URI_DOES_NOT_EXIST"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsUntranslatableUri(Uri uri_) {
-  String uri = relativizeUri(uri_);
+  String? uri = relativizeUri(uri_);
   return new Message(codeUntranslatableUri,
       message: """Not found: '${uri}'""", arguments: {'uri': uri_});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String name)>
-    templateUseOfDeprecatedIdentifier =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' is deprecated.""",
-        withArguments: _withArgumentsUseOfDeprecatedIdentifier);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeUseOfDeprecatedIdentifier =
-    const Code<Message Function(String name)>(
-        "UseOfDeprecatedIdentifier", templateUseOfDeprecatedIdentifier,
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUseOfDeprecatedIdentifier(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeUseOfDeprecatedIdentifier,
-      message: """'${name}' is deprecated.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
     templateValueForRequiredParameterNotProvidedError =
     const Template<Message Function(String name)>(
         messageTemplate:
@@ -9667,7 +9592,6 @@
     codeValueForRequiredParameterNotProvidedError =
     const Code<Message Function(String name)>(
   "ValueForRequiredParameterNotProvidedError",
-  templateValueForRequiredParameterNotProvidedError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -9752,7 +9676,6 @@
     codeWebLiteralCannotBeRepresentedExactly =
     const Code<Message Function(String string, String string2)>(
   "WebLiteralCannotBeRepresentedExactly",
-  templateWebLiteralCannotBeRepresentedExactly,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/diagnostic_message.dart b/pkg/_fe_analyzer_shared/lib/src/messages/diagnostic_message.dart
index 7146258..14540d9 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/diagnostic_message.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/diagnostic_message.dart
@@ -35,13 +35,13 @@
 
   Severity get severity;
 
-  Iterable<Uri> get involvedFiles;
+  Iterable<Uri>? get involvedFiles;
 
-  String get codeName;
+  String? get codeName;
 }
 
 /// This method is subject to change.
-Uri getMessageUri(DiagnosticMessage message) {
+Uri? getMessageUri(DiagnosticMessage message) {
   return message is FormattedMessage
       ? message.uri
       : message is DiagnosticMessageFromJson
@@ -50,22 +50,22 @@
 }
 
 /// This method is subject to change.
-int getMessageCharOffset(DiagnosticMessage message) {
+int? getMessageCharOffset(DiagnosticMessage message) {
   return message is FormattedMessage ? message.charOffset : null;
 }
 
 /// This method is subject to change.
-int getMessageLength(DiagnosticMessage message) {
+int? getMessageLength(DiagnosticMessage message) {
   return message is FormattedMessage ? message.length : null;
 }
 
 /// This method is subject to change.
-Code getMessageCodeObject(DiagnosticMessage message) {
+Code? getMessageCodeObject(DiagnosticMessage message) {
   return message is FormattedMessage ? message.code : null;
 }
 
 /// This method is subject to change.
-String getMessageHeaderText(DiagnosticMessage message) {
+String? getMessageHeaderText(DiagnosticMessage message) {
   return message is FormattedMessage ? message.message : null;
 }
 
@@ -75,12 +75,12 @@
 }
 
 /// This method is subject to change.
-Map<String, dynamic> getMessageArguments(DiagnosticMessage message) {
+Map<String, dynamic>? getMessageArguments(DiagnosticMessage message) {
   return message is FormattedMessage ? message.arguments : null;
 }
 
 /// This method is subject to change.
-Iterable<DiagnosticMessage> getMessageRelatedInformation(
+Iterable<DiagnosticMessage>? getMessageRelatedInformation(
     DiagnosticMessage message) {
   return message is FormattedMessage ? message.relatedInformation : null;
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart b/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart
index 0358608..9818cca 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart
@@ -10,6 +10,7 @@
   ignored,
   internalProblem,
   warning,
+  info,
 }
 
 const Map<String, String> severityEnumNames = const <String, String>{
@@ -18,6 +19,7 @@
   'IGNORED': 'ignored',
   'INTERNAL_PROBLEM': 'internalProblem',
   'WARNING': 'warning',
+  'INFO': 'info',
 };
 
 const Map<String, Severity> severityEnumValues = const <String, Severity>{
@@ -26,6 +28,7 @@
   'IGNORED': Severity.ignored,
   'INTERNAL_PROBLEM': Severity.internalProblem,
   'WARNING': Severity.warning,
+  'INFO': Severity.info,
 };
 
 const Map<Severity, String> severityPrefixes = const <Severity, String>{
@@ -33,6 +36,7 @@
   Severity.internalProblem: "Internal problem",
   Severity.warning: "Warning",
   Severity.context: "Context",
+  Severity.info: "Info",
 };
 
 const Map<Severity, String> severityTexts = const <Severity, String>{
@@ -40,4 +44,5 @@
   Severity.internalProblem: "internal problem",
   Severity.warning: "warning",
   Severity.context: "context",
+  Severity.info: "info",
 };
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/block_kind.dart b/pkg/_fe_analyzer_shared/lib/src/parser/block_kind.dart
index 46c0f8d..539fb14 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/block_kind.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/block_kind.dart
@@ -13,7 +13,7 @@
   /// [templateExpectedClassOrMixinBody].
   ///
   /// If `null` the generic [templateExpectedButGot] is used instead.
-  String get missingBlockName => useNameForMissingBlock ? name : null;
+  String? get missingBlockName => useNameForMissingBlock ? name : null;
 
   String toString() => 'BlockKind($name)';
 
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/class_member_parser.dart b/pkg/_fe_analyzer_shared/lib/src/parser/class_member_parser.dart
index c41be78..d42c6ed 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/class_member_parser.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/class_member_parser.dart
@@ -15,7 +15,7 @@
 /// Parser similar to [TopLevelParser] but also parses class members (excluding
 /// their bodies).
 class ClassMemberParser extends Parser {
-  Parser skipParser;
+  Parser? skipParser;
 
   ClassMemberParser(Listener listener) : super(listener);
 
@@ -26,7 +26,7 @@
 
   @override
   Token parseIdentifierExpression(Token token) {
-    return token.next;
+    return token.next!;
   }
 
   Token skipExpression(Token token) {
@@ -35,7 +35,8 @@
     // not triggered during the second parse.
     // When the parser supports not doing token stream rewriting, use that
     // feature together with a no-op listener instead.
-    skipParser ??= new Parser(new ErrorDelegationListener(listener));
+    this.skipParser ??= new Parser(new ErrorDelegationListener(listener));
+    Parser skipParser = this.skipParser!;
     skipParser.mayParseFunctionExpressions = mayParseFunctionExpressions;
     skipParser.asyncState = asyncState;
     skipParser.loopState = loopState;
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
index bca2267..0274d64 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -7,13 +7,13 @@
 import 'parser.dart';
 
 class ForwardingListener implements Listener {
-  Listener listener;
+  Listener? listener;
   bool forwardErrors = true;
 
   ForwardingListener([this.listener]);
 
   @override
-  Uri get uri => listener?.uri;
+  Uri? get uri => listener?.uri;
 
   @override
   void beginArguments(Token token) {
@@ -61,7 +61,7 @@
   }
 
   @override
-  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+  void beginClassDeclaration(Token begin, Token? abstractToken, Token name) {
     listener?.beginClassDeclaration(begin, abstractToken, name);
   }
 
@@ -151,13 +151,13 @@
   }
 
   @override
-  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+  void beginExtensionDeclaration(Token extensionKeyword, Token? name) {
     listener?.beginExtensionDeclaration(extensionKeyword, name);
   }
 
   @override
   void beginFactoryMethod(
-      Token lastConsumed, Token externalToken, Token constToken) {
+      Token lastConsumed, Token? externalToken, Token? constToken) {
     listener?.beginFactoryMethod(lastConsumed, externalToken, constToken);
   }
 
@@ -167,7 +167,7 @@
   }
 
   @override
-  void beginForControlFlow(Token awaitToken, Token forToken) {
+  void beginForControlFlow(Token? awaitToken, Token forToken) {
     listener?.beginForControlFlow(awaitToken, forToken);
   }
 
@@ -182,8 +182,8 @@
   }
 
   @override
-  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
-      Token covariantToken, Token varFinalOrConst) {
+  void beginFormalParameter(Token token, MemberKind kind, Token? requiredToken,
+      Token? covariantToken, Token? varFinalOrConst) {
     listener?.beginFormalParameter(
         token, kind, requiredToken, covariantToken, varFinalOrConst);
   }
@@ -314,8 +314,13 @@
   }
 
   @override
-  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
-      Token varFinalOrConst, Token getOrSet, Token name) {
+  void beginMethod(
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? varFinalOrConst,
+      Token? getOrSet,
+      Token name) {
     listener?.beginMethod(externalToken, staticToken, covariantToken,
         varFinalOrConst, getOrSet, name);
   }
@@ -332,7 +337,7 @@
 
   @override
   void beginNamedMixinApplication(
-      Token begin, Token abstractToken, Token name) {
+      Token begin, Token? abstractToken, Token name) {
     listener?.beginNamedMixinApplication(begin, abstractToken, name);
   }
 
@@ -407,7 +412,7 @@
   }
 
   @override
-  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {
+  void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {
     listener?.beginTopLevelMethod(lastConsumed, externalToken);
   }
 
@@ -443,7 +448,7 @@
 
   @override
   void beginVariablesDeclaration(
-      Token token, Token lateToken, Token varFinalOrConst) {
+      Token token, Token? lateToken, Token? varFinalOrConst) {
     listener?.beginVariablesDeclaration(token, lateToken, varFinalOrConst);
   }
 
@@ -469,7 +474,7 @@
 
   @override
   void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
-      Token commaToken, Token semicolonToken) {
+      Token? commaToken, Token semicolonToken) {
     listener?.endAssert(
         assertKeyword, kind, leftParenthesis, commaToken, semicolonToken);
   }
@@ -516,8 +521,8 @@
   }
 
   @override
-  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endClassConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     listener?.endClassConstructor(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
   }
@@ -535,12 +540,12 @@
 
   @override
   void endClassFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -557,8 +562,8 @@
   }
 
   @override
-  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     listener?.endClassMethod(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
   }
@@ -585,7 +590,7 @@
   }
 
   @override
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token? equalSign) {
     listener?.endConditionalUri(ifKeyword, leftParen, equalSign);
   }
 
@@ -606,7 +611,7 @@
 
   @override
   void endConstructorReference(
-      Token start, Token periodBeforeName, Token endToken) {
+      Token start, Token? periodBeforeName, Token endToken) {
     listener?.endConstructorReference(start, periodBeforeName, endToken);
   }
 
@@ -637,8 +642,8 @@
   }
 
   @override
-  void endExtensionConstructor(Token getOrSet, Token beginToken,
-      Token beginParam, Token beginInitializers, Token endToken) {
+  void endExtensionConstructor(Token? getOrSet, Token beginToken,
+      Token beginParam, Token? beginInitializers, Token endToken) {
     listener?.endExtensionConstructor(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
   }
@@ -657,12 +662,12 @@
 
   @override
   void endExtensionFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -679,8 +684,8 @@
   }
 
   @override
-  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endExtensionMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     listener?.endExtensionMethod(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
   }
@@ -717,11 +722,11 @@
 
   @override
   void endFormalParameter(
-      Token thisKeyword,
-      Token periodAfterThis,
+      Token? thisKeyword,
+      Token? periodAfterThis,
       Token nameToken,
-      Token initializerStart,
-      Token initializerEnd,
+      Token? initializerStart,
+      Token? initializerEnd,
       FormalParameterKind kind,
       MemberKind memberKind) {
     listener?.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
@@ -760,18 +765,18 @@
   }
 
   @override
-  void endFunctionType(Token functionToken, Token questionMark) {
+  void endFunctionType(Token functionToken, Token? questionMark) {
     listener?.endFunctionType(functionToken, questionMark);
   }
 
   @override
   void endFunctionTypeAlias(
-      Token typedefKeyword, Token equals, Token endToken) {
+      Token typedefKeyword, Token? equals, Token endToken) {
     listener?.endFunctionTypeAlias(typedefKeyword, equals, endToken);
   }
 
   @override
-  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token? question) {
     listener?.endFunctionTypedFormalParameter(nameToken, question);
   }
 
@@ -791,7 +796,7 @@
   }
 
   @override
-  void endIfStatement(Token ifToken, Token elseToken) {
+  void endIfStatement(Token ifToken, Token? elseToken) {
     listener?.endIfStatement(ifToken, elseToken);
   }
 
@@ -801,7 +806,7 @@
   }
 
   @override
-  void endImport(Token importKeyword, Token semicolon) {
+  void endImport(Token importKeyword, Token? semicolon) {
     listener?.endImport(importKeyword, semicolon);
   }
 
@@ -827,7 +832,7 @@
   }
 
   @override
-  void endInvalidYieldStatement(Token beginToken, Token starToken,
+  void endInvalidYieldStatement(Token beginToken, Token? starToken,
       Token endToken, MessageCode errorCode) {
     listener?.endInvalidYieldStatement(
         beginToken, starToken, endToken, errorCode);
@@ -864,7 +869,7 @@
   }
 
   @override
-  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+  void endMetadata(Token beginToken, Token? periodBeforeName, Token endToken) {
     listener?.endMetadata(beginToken, periodBeforeName, endToken);
   }
 
@@ -874,8 +879,8 @@
   }
 
   @override
-  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endMixinConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     listener?.endMixinConstructor(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
   }
@@ -893,12 +898,12 @@
 
   @override
   void endMixinFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -915,8 +920,8 @@
   }
 
   @override
-  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endMixinMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     listener?.endMixinMethod(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
   }
@@ -928,7 +933,7 @@
 
   @override
   void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
-      Token implementsKeyword, Token endToken) {
+      Token? implementsKeyword, Token endToken) {
     listener?.endNamedMixinApplication(
         begin, classKeyword, equals, implementsKeyword, endToken);
   }
@@ -985,8 +990,8 @@
   void endSwitchCase(
       int labelCount,
       int expressionCount,
-      Token defaultKeyword,
-      Token colonAfterDefault,
+      Token? defaultKeyword,
+      Token? colonAfterDefault,
       int statementCount,
       Token firstToken,
       Token endToken) {
@@ -1016,11 +1021,11 @@
 
   @override
   void endTopLevelFields(
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -1029,12 +1034,13 @@
   }
 
   @override
-  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+  void endTopLevelMethod(Token beginToken, Token? getOrSet, Token endToken) {
     listener?.endTopLevelMethod(beginToken, getOrSet, endToken);
   }
 
   @override
-  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+  void endTryStatement(
+      int catchCount, Token tryKeyword, Token? finallyKeyword) {
     listener?.endTryStatement(catchCount, tryKeyword, finallyKeyword);
   }
 
@@ -1050,7 +1056,7 @@
 
   @override
   void endTypeVariable(
-      Token token, int index, Token extendsOrSuper, Token variance) {
+      Token token, int index, Token? extendsOrSuper, Token? variance) {
     listener?.endTypeVariable(token, index, extendsOrSuper, variance);
   }
 
@@ -1065,7 +1071,7 @@
   }
 
   @override
-  void endVariablesDeclaration(int count, Token endToken) {
+  void endVariablesDeclaration(int count, Token? endToken) {
     listener?.endVariablesDeclaration(count, endToken);
   }
 
@@ -1080,7 +1086,7 @@
   }
 
   @override
-  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+  void endYieldStatement(Token yieldToken, Token? starToken, Token endToken) {
     listener?.endYieldStatement(yieldToken, starToken, endToken);
   }
 
@@ -1105,7 +1111,7 @@
   }
 
   @override
-  void handleAsyncModifier(Token asyncToken, Token starToken) {
+  void handleAsyncModifier(Token? asyncToken, Token? starToken) {
     listener?.handleAsyncModifier(asyncToken, starToken);
   }
 
@@ -1121,17 +1127,17 @@
   }
 
   @override
-  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
+  void handleCatchBlock(Token? onKeyword, Token? catchKeyword, Token? comma) {
     listener?.handleCatchBlock(onKeyword, catchKeyword, comma);
   }
 
   @override
-  void handleClassExtends(Token extendsKeyword, int typeCount) {
+  void handleClassExtends(Token? extendsKeyword, int typeCount) {
     listener?.handleClassExtends(extendsKeyword, typeCount);
   }
 
   @override
-  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+  void handleClassHeader(Token begin, Token classKeyword, Token? nativeToken) {
     listener?.handleClassHeader(begin, classKeyword, nativeToken);
   }
 
@@ -1142,7 +1148,7 @@
 
   @override
   void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
+      Token? implementsKeyword, int interfacesCount) {
     listener?.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
   }
 
@@ -1153,7 +1159,7 @@
 
   @override
   void handleCommentReference(
-      Token newKeyword, Token prefix, Token period, Token token) {
+      Token? newKeyword, Token? prefix, Token? period, Token token) {
     listener?.handleCommentReference(newKeyword, prefix, period, token);
   }
 
@@ -1204,7 +1210,7 @@
   }
 
   @override
-  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
+  void handleExpressionFunctionBody(Token arrowToken, Token? endToken) {
     listener?.handleExpressionFunctionBody(arrowToken, endToken);
   }
 
@@ -1239,7 +1245,7 @@
   }
 
   @override
-  void handleForInLoopParts(Token awaitToken, Token forToken,
+  void handleForInLoopParts(Token? awaitToken, Token forToken,
       Token leftParenthesis, Token inKeyword) {
     listener?.handleForInLoopParts(
         awaitToken, forToken, leftParenthesis, inKeyword);
@@ -1273,19 +1279,19 @@
   }
 
   @override
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
     listener?.handleImportPrefix(deferredKeyword, asKeyword);
   }
 
   @override
   void handleIndexedExpression(
-      Token question, Token openSquareBracket, Token closeSquareBracket) {
+      Token? question, Token openSquareBracket, Token closeSquareBracket) {
     listener?.handleIndexedExpression(
         question, openSquareBracket, closeSquareBracket);
   }
 
   @override
-  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {
+  void handleInterpolationExpression(Token leftBracket, Token? rightBracket) {
     listener?.handleInterpolationExpression(leftBracket, rightBracket);
   }
 
@@ -1344,7 +1350,7 @@
   }
 
   @override
-  void handleIsOperator(Token isOperator, Token not) {
+  void handleIsOperator(Token isOperator, Token? not) {
     listener?.handleIsOperator(isOperator, not);
   }
 
@@ -1370,7 +1376,7 @@
 
   @override
   void handleLiteralList(
-      int count, Token beginToken, Token constKeyword, Token endToken) {
+      int count, Token beginToken, Token? constKeyword, Token endToken) {
     listener?.handleLiteralList(count, beginToken, constKeyword, endToken);
   }
 
@@ -1388,7 +1394,7 @@
   void handleLiteralSetOrMap(
     int count,
     Token leftBrace,
-    Token constKeyword,
+    Token? constKeyword,
     Token rightBrace,
     // TODO(danrubel): hasSetEntry parameter exists for replicating existing
     // behavior and will be removed once unified collection has been enabled
@@ -1404,7 +1410,7 @@
   }
 
   @override
-  void handleMixinOn(Token onKeyword, int typeCount) {
+  void handleMixinOn(Token? onKeyword, int typeCount) {
     listener?.handleMixinOn(onKeyword, typeCount);
   }
 
@@ -1542,7 +1548,7 @@
   }
 
   @override
-  void handleRecoverImport(Token semicolon) {
+  void handleRecoverImport(Token? semicolon) {
     listener?.handleRecoverImport(semicolon);
   }
 
@@ -1597,7 +1603,7 @@
   }
 
   @override
-  void handleType(Token beginToken, Token questionMark) {
+  void handleType(Token beginToken, Token? questionMark) {
     listener?.handleType(beginToken, questionMark);
   }
 
@@ -1648,7 +1654,7 @@
   }
 
   @override
-  void reportVarianceModifierNotEnabled(Token variance) {
+  void reportVarianceModifierNotEnabled(Token? variance) {
     listener?.reportVarianceModifierNotEnabled(variance);
   }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart
index 42c8fe2..6b81262 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart
@@ -276,7 +276,7 @@
       this.isContinuation: false,
       this.isScopeReference: false,
       this.isBuiltInIdentifierAllowed: true,
-      bool allowedInConstantExpression,
+      bool? allowedInConstantExpression,
       this.recoveryTemplate: templateExpectedIdentifier})
       : this.allowedInConstantExpression =
             // Generally, declarations are legal in constant expressions.  A
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
index 5c94a3f..b49806d 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
@@ -22,7 +22,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -51,7 +51,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.type.isPseudo) {
       return identifier;
@@ -89,7 +89,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     const List<String> followingValues = const [
       ';',
@@ -102,7 +102,7 @@
 
     if (identifier.isIdentifier) {
       if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-          isOneOfOrEof(identifier.next, followingValues)) {
+          isOneOfOrEof(identifier.next!, followingValues)) {
         return identifier;
       }
       // Although this is a valid identifier name, the import declaration
@@ -148,7 +148,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -177,7 +177,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     const List<String> followingValues = const ['.', '==', ')'];
 
@@ -187,7 +187,7 @@
       // used as identifiers, they are more likely the start of the next
       // directive or declaration.
       if (!identifier.isTopLevelKeyword ||
-          isOneOfOrEof(identifier.next, followingValues)) {
+          isOneOfOrEof(identifier.next!, followingValues)) {
         return identifier;
       }
     }
@@ -222,7 +222,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.type.isPseudo) {
       return identifier;
@@ -260,7 +260,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       return identifier;
@@ -297,10 +297,10 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
-      if (optional('await', identifier) && identifier.next.isIdentifier) {
+      if (optional('await', identifier) && identifier.next!.isIdentifier) {
         // Although the `await` can be used in an expression,
         // it is followed by another identifier which does not form
         // a valid expression. Report an error on the `await` token
@@ -311,7 +311,7 @@
         // TODO(danrubel) Consider a new listener event so that analyzer
         // can represent this as an await expression in a context that does
         // not allow await.
-        return identifier.next;
+        return identifier.next!;
       } else {
         checkAsyncAwaitYieldAsIdentifier(identifier, parser);
       }
@@ -322,7 +322,7 @@
     Token reportErrorAt = identifier;
     if (optional(r'$', token) &&
         identifier.isKeyword &&
-        identifier.next.kind == STRING_TOKEN) {
+        identifier.next!.kind == STRING_TOKEN) {
       // Keyword used as identifier in string interpolation
       parser.reportRecoverableErrorWithToken(
           identifier, codes.templateExpectedIdentifierButGotKeyword);
@@ -340,7 +340,7 @@
               const ['.', ',', '(', ')', '[', ']', '{', '}', '?', ':', ';'])) {
         // When in doubt, consume the token to ensure we make progress
         token = identifier;
-        identifier = token.next;
+        identifier = token.next!;
       }
     }
 
@@ -359,7 +359,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       return identifier;
@@ -387,7 +387,7 @@
   Token ensureIdentifierPotentiallyRecovered(
       Token token, Parser parser, bool isRecovered) {
     // Fast path good case.
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       return identifier;
@@ -412,7 +412,7 @@
   @override
   Token ensureIdentifier(Token token, Parser parser) {
     assert(optional('.', token));
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       return identifier;
@@ -433,7 +433,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -482,7 +482,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.type.isPseudo) {
       return identifier;
@@ -498,7 +498,7 @@
       'as'
     ];
     if (identifier.type.isBuiltIn &&
-        isOneOfOrEof(identifier.next, followingValues)) {
+        isOneOfOrEof(identifier.next!, followingValues)) {
       parser.reportRecoverableErrorWithToken(
           identifier, codes.templateBuiltInIdentifierInDeclaration);
     } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
@@ -532,7 +532,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       return identifier;
@@ -556,7 +556,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -592,7 +592,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -627,7 +627,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -676,12 +676,12 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     const List<String> followingValues = const ['.', ';'];
 
     if (identifier.isIdentifier) {
-      Token next = identifier.next;
+      Token next = identifier.next!;
       if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
           isOneOfOrEof(next, followingValues)) {
         return identifier;
@@ -720,7 +720,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -765,7 +765,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -812,7 +812,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       return identifier;
@@ -843,7 +843,7 @@
   Token ensureIdentifierPotentiallyRecovered(
       Token token, Parser parser, bool isRecovered) {
     // Fast path good case.
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       return identifier;
@@ -867,7 +867,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.isIdentifier) {
       checkAsyncAwaitYieldAsIdentifier(identifier, parser);
@@ -905,11 +905,11 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
 
     if (identifier.isIdentifier) {
-      Token next = identifier.next;
+      Token next = identifier.next!;
       if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
           isOneOfOrEof(next, followingValues)) {
         return identifier;
@@ -946,11 +946,11 @@
   Token ensureIdentifierPotentiallyRecovered(
       Token token, Parser parser, bool isRecovered) {
     // Fast path good case.
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
 
     if (identifier.isIdentifier) {
-      Token next = identifier.next;
+      Token next = identifier.next!;
       if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
           isOneOfOrEof(next, followingValues)) {
         return identifier;
@@ -976,7 +976,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.type.isPseudo) {
       if (optional('Function', identifier)) {
@@ -989,7 +989,7 @@
     // Recovery
     const List<String> followingValues = const ['(', '<', '=', ';'];
     if (identifier.type.isBuiltIn &&
-        isOneOfOrEof(identifier.next, followingValues)) {
+        isOneOfOrEof(identifier.next!, followingValues)) {
       parser.reportRecoverableErrorWithToken(
           identifier, codes.templateBuiltInIdentifierInDeclaration);
     } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
@@ -1015,7 +1015,7 @@
   Token ensureIdentifierPotentiallyRecovered(
       Token token, Parser parser, bool isRecovered) {
     // Fast path good case.
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.type.isPseudo) {
       if (optional('Function', identifier)) {
@@ -1057,7 +1057,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(next.kind != IDENTIFIER_TOKEN);
     if (isValidTypeReference(next)) {
       return next;
@@ -1082,7 +1082,7 @@
         next, const ['<', '>', ')', '[', ']', '[]', '{', '}', ',', ';'])) {
       // When in doubt, consume the token to ensure we make progress
       token = next;
-      next = token.next;
+      next = token.next!;
     }
     // Insert a synthetic identifier to satisfy listeners.
     return parser.rewriter.insertSyntheticIdentifier(token);
@@ -1097,7 +1097,7 @@
 
   @override
   Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
+    Token identifier = token.next!;
     assert(identifier.kind != IDENTIFIER_TOKEN);
     if (identifier.type.isPseudo) {
       return identifier;
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
index c898b58..bb635b6 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -40,7 +40,7 @@
 /// Events starting with `handle` are used when isn't possible to have a begin
 /// event.
 class Listener implements UnescapeErrorListener {
-  Uri get uri => null;
+  Uri? get uri => null;
 
   void logEvent(String name) {}
 
@@ -51,7 +51,7 @@
   }
 
   /// Handle async modifiers `async`, `async*`, `sync`.
-  void handleAsyncModifier(Token asyncToken, Token starToken) {
+  void handleAsyncModifier(Token? asyncToken, Token? starToken) {
     logEvent("AsyncModifier");
   }
 
@@ -123,14 +123,14 @@
   /// (or extraneous modifiers in the case of recovery) preceding [name].
   ///
   /// At this point we have parsed the name and type parameter declarations.
-  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {}
+  void beginClassDeclaration(Token begin, Token? abstractToken, Token name) {}
 
   /// Handle an extends clause in a class declaration. Substructures:
   /// - supertype (may be a mixin application)
   /// The typeCount is for error recovery: Invalid code might have more than one
   /// class specified in the extends clause. A parser error has already been
   /// issued.
-  void handleClassExtends(Token extendsKeyword, int typeCount) {
+  void handleClassExtends(Token? extendsKeyword, int typeCount) {
     logEvent("ClassExtends");
   }
 
@@ -138,7 +138,7 @@
   /// Substructures:
   /// - implemented types
   void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
+      Token? implementsKeyword, int interfacesCount) {
     logEvent("ClassImplements");
   }
 
@@ -151,7 +151,7 @@
   /// - with clause
   /// - implemented types
   /// - native clause
-  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+  void handleClassHeader(Token begin, Token classKeyword, Token? nativeToken) {
     logEvent("ClassHeader");
   }
 
@@ -179,7 +179,7 @@
 
   /// Handle an on clause in a mixin declaration. Substructures:
   /// - implemented types
-  void handleMixinOn(Token onKeyword, int typeCount) {
+  void handleMixinOn(Token? onKeyword, int typeCount) {
     logEvent("MixinOn");
   }
 
@@ -229,7 +229,7 @@
   /// - type variables
   ///
   /// At this point we have parsed the name and type parameter declarations.
-  void beginExtensionDeclaration(Token extensionKeyword, Token name) {}
+  void beginExtensionDeclaration(Token extensionKeyword, Token? name) {}
 
   /// Handle the end of an extension methods declaration.  Substructures:
   /// - substructures from [beginExtensionDeclaration]
@@ -269,7 +269,7 @@
   void beginConstructorReference(Token start) {}
 
   void endConstructorReference(
-      Token start, Token periodBeforeName, Token endToken) {
+      Token start, Token? periodBeforeName, Token endToken) {
     logEvent("ConstructorReference");
   }
 
@@ -328,7 +328,7 @@
   /// Note that this is ended by [endClassFactoryMethod],
   /// [endMixinFactoryMethod] or [endExtensionFactoryMethod].
   void beginFactoryMethod(
-      Token lastConsumed, Token externalToken, Token constToken) {}
+      Token lastConsumed, Token? externalToken, Token? constToken) {}
 
   void endClassFactoryMethod(
       Token beginToken, Token factoryKeyword, Token endToken) {
@@ -347,15 +347,15 @@
     endClassFactoryMethod(beginToken, factoryKeyword, endToken);
   }
 
-  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
-      Token covariantToken, Token varFinalOrConst) {}
+  void beginFormalParameter(Token token, MemberKind kind, Token? requiredToken,
+      Token? covariantToken, Token? varFinalOrConst) {}
 
   void endFormalParameter(
-      Token thisKeyword,
-      Token periodAfterThis,
+      Token? thisKeyword,
+      Token? periodAfterThis,
       Token nameToken,
-      Token initializerStart,
-      Token initializerEnd,
+      Token? initializerStart,
+      Token? initializerEnd,
       FormalParameterKind kind,
       MemberKind memberKind) {
     logEvent("FormalParameter");
@@ -380,12 +380,12 @@
   ///
   /// Started by [beginFields].
   void endClassFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -400,12 +400,12 @@
   ///
   /// Started by [beginFields].
   void endMixinFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -422,12 +422,12 @@
   ///
   /// Started by [beginFields].
   void endExtensionFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -477,7 +477,7 @@
   /// Marks the end of parsing the control structure of a for-in statement
   /// or for control flow entry up to and including the closing parenthesis.
   /// `for` `(` (type)? identifier `in` iterator `)`
-  void handleForInLoopParts(Token awaitToken, Token forToken,
+  void handleForInLoopParts(Token? awaitToken, Token forToken,
       Token leftParenthesis, Token inKeyword) {}
 
   // One of the two possible corresponding end events for [beginForStatement].
@@ -594,7 +594,7 @@
   /// - Alias type variables
   /// - Type (FunctionTypeAnnotation)
   void endFunctionTypeAlias(
-      Token typedefKeyword, Token equals, Token endToken) {
+      Token typedefKeyword, Token? equals, Token endToken) {
     logEvent("FunctionTypeAlias");
   }
 
@@ -616,7 +616,7 @@
   ///
   /// At this point we have parsed the name and type parameter declarations.
   void beginNamedMixinApplication(
-      Token begin, Token abstractToken, Token name) {}
+      Token begin, Token? abstractToken, Token name) {}
 
   /// Handle a named mixin application with clause (e.g. "A with B, C").
   /// Substructures:
@@ -640,7 +640,7 @@
   /// declaration, each implemented type is listed separately on the stack, and
   /// the number of implemented types is passed as a parameter.
   void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
-      Token implementsKeyword, Token endToken) {
+      Token? implementsKeyword, Token endToken) {
     logEvent("NamedMixinApplication");
   }
 
@@ -664,7 +664,7 @@
 
   void beginIfStatement(Token token) {}
 
-  void endIfStatement(Token ifToken, Token elseToken) {
+  void endIfStatement(Token ifToken, Token? elseToken) {
     logEvent("IfStatement");
   }
 
@@ -686,7 +686,7 @@
   /// depending upon whether [deferredKeyword] and [asKeyword]
   /// are not `null` respectively. Substructures:
   /// - prefix identifier (only if asKeyword != null)
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
     logEvent("ImportPrefix");
   }
 
@@ -696,7 +696,7 @@
   /// - conditional uris
   /// - prefix identifier
   /// - combinators
-  void endImport(Token importKeyword, Token semicolon) {
+  void endImport(Token importKeyword, Token? semicolon) {
     logEvent("Import");
   }
 
@@ -707,7 +707,7 @@
   /// - conditional uris
   /// - prefix identifier
   /// - combinators
-  void handleRecoverImport(Token semicolon) {
+  void handleRecoverImport(Token? semicolon) {
     logEvent("ImportRecovery");
   }
 
@@ -723,7 +723,7 @@
   /// - Dotted name
   /// - Condition (literal string; only if [equalSign] != null)
   /// - URI (literal string)
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token? equalSign) {
     logEvent("ConditionalUri");
   }
 
@@ -831,7 +831,7 @@
 
   void beginLiteralString(Token token) {}
 
-  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {}
+  void handleInterpolationExpression(Token leftBracket, Token? rightBracket) {}
 
   void endLiteralString(int interpolationCount, Token endToken) {
     logEvent("LiteralString");
@@ -870,8 +870,13 @@
   /// Note that this is ended with [endClassConstructor], [endClassMethod],
   /// [endExtensionConstructor], [endExtensionMethod], [endMixinConstructor] or
   /// [endMixinMethod].
-  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
-      Token varFinalOrConst, Token getOrSet, Token name) {}
+  void beginMethod(
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? varFinalOrConst,
+      Token? getOrSet,
+      Token name) {}
 
   /// Handle the end of a class method declaration.  Substructures:
   /// - metadata
@@ -882,8 +887,8 @@
   /// - initializers
   /// - async marker
   /// - body
-  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     logEvent("ClassMethod");
   }
 
@@ -896,8 +901,8 @@
   /// - initializers
   /// - async marker
   /// - body
-  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endMixinMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     // TODO(danrubel): push implementation into subclasses
     endClassMethod(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
@@ -912,8 +917,8 @@
   /// - initializers
   /// - async marker
   /// - body
-  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endExtensionMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     // TODO(danrubel): push implementation into subclasses
     endClassMethod(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
@@ -928,8 +933,8 @@
   /// - initializers
   /// - async marker
   /// - body
-  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endClassConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     // TODO(danrubel): push implementation into subclasses
     endClassMethod(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
@@ -944,8 +949,8 @@
   /// - initializers
   /// - async marker
   /// - body
-  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endMixinConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     // TODO(danrubel): push implementation into subclasses
     endClassMethod(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
@@ -960,8 +965,8 @@
   /// - initializers
   /// - async marker
   /// - body
-  void endExtensionConstructor(Token getOrSet, Token beginToken,
-      Token beginParam, Token beginInitializers, Token endToken) {
+  void endExtensionConstructor(Token? getOrSet, Token beginToken,
+      Token beginParam, Token? beginInitializers, Token endToken) {
     // TODO(danrubel): push implementation into subclasses
     endClassMethod(
         getOrSet, beginToken, beginParam, beginInitializers, endToken);
@@ -980,7 +985,7 @@
   /// - Type arguments
   /// - Constructor name (only if [periodBeforeName] is not `null`)
   /// - Arguments
-  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+  void endMetadata(Token beginToken, Token? periodBeforeName, Token endToken) {
     logEvent("Metadata");
   }
 
@@ -1048,7 +1053,7 @@
 
   /// This method is invoked when parser finishes parsing the corresponding
   /// expression of the expression function body.
-  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
+  void handleExpressionFunctionBody(Token arrowToken, Token? endToken) {
     logEvent("ExpressionFunctionBody");
   }
 
@@ -1146,18 +1151,18 @@
   ///
   /// Started by [beginFields].
   void endTopLevelFields(
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
     logEvent("TopLevelFields");
   }
 
-  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {}
+  void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {}
 
   /// Handle the end of a top level method.  Substructures:
   /// - metadata
@@ -1168,7 +1173,7 @@
   /// - formal parameters
   /// - async marker
   /// - body
-  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+  void endTopLevelMethod(Token beginToken, Token? getOrSet, Token endToken) {
     logEvent("TopLevelMethod");
   }
 
@@ -1184,7 +1189,7 @@
     logEvent("CatchClause");
   }
 
-  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
+  void handleCatchBlock(Token? onKeyword, Token? catchKeyword, Token? comma) {
     logEvent("CatchBlock");
   }
 
@@ -1192,11 +1197,12 @@
     logEvent("FinallyBlock");
   }
 
-  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+  void endTryStatement(
+      int catchCount, Token tryKeyword, Token? finallyKeyword) {
     logEvent("TryStatement");
   }
 
-  void handleType(Token beginToken, Token questionMark) {
+  void handleType(Token beginToken, Token? questionMark) {
     logEvent("Type");
   }
 
@@ -1218,7 +1224,7 @@
   /// - Type variables
   /// - Return type
   /// - Formal parameters
-  void endFunctionType(Token functionToken, Token questionMark) {
+  void endFunctionType(Token functionToken, Token? questionMark) {
     logEvent("FunctionType");
   }
 
@@ -1258,7 +1264,7 @@
   ///
   /// See [beginTypeVariable] for additional substructures.
   void endTypeVariable(
-      Token token, int index, Token extendsOrSuper, Token variance) {
+      Token token, int index, Token? extendsOrSuper, Token? variance) {
     logEvent("TypeVariable");
   }
 
@@ -1268,7 +1274,7 @@
     logEvent("TypeVariables");
   }
 
-  void reportVarianceModifierNotEnabled(Token variance) {
+  void reportVarianceModifierNotEnabled(Token? variance) {
     if (variance != null) {
       handleRecoverableError(
           templateExperimentNotEnabled.withArguments('variance', '2.9'),
@@ -1293,9 +1299,9 @@
   /// - Metadata
   /// - Type
   void beginVariablesDeclaration(
-      Token token, Token lateToken, Token varFinalOrConst) {}
+      Token token, Token? lateToken, Token? varFinalOrConst) {}
 
-  void endVariablesDeclaration(int count, Token endToken) {
+  void endVariablesDeclaration(int count, Token? endToken) {
     logEvent("VariablesDeclaration");
   }
 
@@ -1356,7 +1362,7 @@
 
   /// Called before parsing a "for" control flow list, set, or map entry.
   /// Ended by either [endForControlFlow] or [endForInControlFlow].
-  void beginForControlFlow(Token awaitToken, Token forToken) {}
+  void beginForControlFlow(Token? awaitToken, Token forToken) {}
 
   /// Called after parsing a "for" control flow list, set, or map entry.
   /// One of the two possible corresponding end events for
@@ -1422,7 +1428,7 @@
   /// - type variables
   /// - return type
   /// - formal parameters
-  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token? question) {
     logEvent("FunctionTypedFormalParameter");
   }
 
@@ -1434,7 +1440,7 @@
   }
 
   void handleIndexedExpression(
-      Token question, Token openSquareBracket, Token closeSquareBracket) {
+      Token? question, Token openSquareBracket, Token closeSquareBracket) {
     logEvent("IndexedExpression");
   }
 
@@ -1444,7 +1450,7 @@
     logEvent("IsOperatorType");
   }
 
-  void handleIsOperator(Token isOperator, Token not) {
+  void handleIsOperator(Token isOperator, Token? not) {
     logEvent("IsOperator");
   }
 
@@ -1469,7 +1475,7 @@
   void beginAssert(Token assertKeyword, Assert kind) {}
 
   void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
-      Token commaToken, Token semicolonToken) {
+      Token? commaToken, Token semicolonToken) {
     logEvent("Assert");
   }
 
@@ -1488,14 +1494,14 @@
   }
 
   void handleLiteralList(
-      int count, Token leftBracket, Token constKeyword, Token rightBracket) {
+      int count, Token leftBracket, Token? constKeyword, Token rightBracket) {
     logEvent("LiteralList");
   }
 
   void handleLiteralSetOrMap(
     int count,
     Token leftBrace,
-    Token constKeyword,
+    Token? constKeyword,
     Token rightBrace,
     // TODO(danrubel): hasSetEntry parameter exists for replicating existing
     // behavior and will be removed once unified collection has been enabled
@@ -1595,8 +1601,8 @@
   void endSwitchCase(
       int labelCount,
       int expressionCount,
-      Token defaultKeyword,
-      Token colonAfterDefault,
+      Token? defaultKeyword,
+      Token? colonAfterDefault,
       int statementCount,
       Token firstToken,
       Token endToken) {
@@ -1648,13 +1654,13 @@
 
   /// One of the two possible corresponding end events for
   /// [beginYieldStatement].
-  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+  void endYieldStatement(Token yieldToken, Token? starToken, Token endToken) {
     logEvent("YieldStatement");
   }
 
   /// One of the two possible corresponding end events for
   /// [beginYieldStatement].
-  void endInvalidYieldStatement(Token beginToken, Token starToken,
+  void endInvalidYieldStatement(Token beginToken, Token? starToken,
       Token endToken, MessageCode errorCode) {
     logEvent("InvalidYieldStatement");
   }
@@ -1712,7 +1718,7 @@
   /// This event is generated by the parser when the parser's
   /// `parseOneCommentReference` method is called.
   void handleCommentReference(
-      Token newKeyword, Token prefix, Token period, Token token) {}
+      Token? newKeyword, Token? prefix, Token? period, Token token) {}
 
   /// This event is generated by the parser when the parser's
   /// `parseOneCommentReference` method is called.
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info.dart b/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info.dart
index 35221fd..8b5b93a 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info.dart
@@ -50,16 +50,16 @@
   }
 
   /// Returns the next step when parsing an entry or `null` if none.
-  LiteralEntryInfo computeNext(Token token) => null;
+  LiteralEntryInfo? computeNext(Token token) => null;
 }
 
 /// Compute the [LiteralEntryInfo] for the literal list, map, or set entry.
 LiteralEntryInfo computeLiteralEntry(Token token) {
-  Token next = token.next;
+  Token next = token.next!;
   if (optional('if', next)) {
     return ifCondition;
   } else if (optional('for', next) ||
-      (optional('await', next) && optional('for', next.next))) {
+      (optional('await', next) && optional('for', next.next!))) {
     return new ForCondition();
   } else if (optional('...', next) || optional('...?', next)) {
     return spreadOperator;
@@ -75,4 +75,4 @@
     optional('...?', token) ||
     optional('if', token) ||
     optional('for', token) ||
-    (optional('await', token) && optional('for', token.next));
+    (optional('await', token) && optional('for', token.next!));
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info_impl.dart
index 9e559f1..309bf3e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info_impl.dart
@@ -17,27 +17,27 @@
 
 /// The first step when processing a `for` control flow collection entry.
 class ForCondition extends LiteralEntryInfo {
-  bool inStyle;
+  late bool inStyle;
 
   ForCondition() : super(false, 0);
 
   @override
   Token parse(Token token, Parser parser) {
-    Token next = token.next;
-    Token awaitToken;
+    Token next = token.next!;
+    Token? awaitToken;
     if (optional('await', next)) {
       awaitToken = token = next;
-      next = token.next;
+      next = token.next!;
     }
     final Token forToken = next;
     assert(optional('for', forToken));
     parser.listener.beginForControlFlow(awaitToken, forToken);
 
     token = parser.parseForLoopPartsStart(awaitToken, forToken);
-    Token identifier = token.next;
+    Token identifier = token.next!;
     token = parser.parseForLoopPartsMid(token, awaitToken, forToken);
 
-    if (optional('in', token.next) || optional(':', token.next)) {
+    if (optional('in', token.next!) || optional(':', token.next!)) {
       // Process `for ( ... in ... )`
       inStyle = true;
       token = parser.parseForInLoopPartsRest(
@@ -52,9 +52,9 @@
 
   @override
   LiteralEntryInfo computeNext(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('for', next) ||
-        (optional('await', next) && optional('for', next.next))) {
+        (optional('await', next) && optional('for', next.next!))) {
       return new Nested(
         new ForCondition(),
         inStyle ? const ForInComplete() : const ForComplete(),
@@ -141,7 +141,7 @@
 
   @override
   Token parse(Token token, Parser parser) {
-    final Token ifToken = token.next;
+    final Token ifToken = token.next!;
     assert(optional('if', ifToken));
     parser.listener.beginIfControlFlow(ifToken);
     Token result = parser.ensureParenthesizedCondition(ifToken);
@@ -151,9 +151,9 @@
 
   @override
   LiteralEntryInfo computeNext(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('for', next) ||
-        (optional('await', next) && optional('for', next.next))) {
+        (optional('await', next) && optional('for', next.next!))) {
       return new Nested(new ForCondition(), const IfComplete());
     } else if (optional('if', next)) {
       return new Nested(ifCondition, const IfComplete());
@@ -187,15 +187,15 @@
 
   @override
   Token parse(Token token, Parser parser) {
-    if (!optional('else', token.next)) {
+    if (!optional('else', token.next!)) {
       parser.listener.endIfControlFlow(token);
     }
     return token;
   }
 
   @override
-  LiteralEntryInfo computeNext(Token token) {
-    return optional('else', token.next) ? const IfElse() : null;
+  LiteralEntryInfo? computeNext(Token token) {
+    return optional('else', token.next!) ? const IfElse() : null;
   }
 }
 
@@ -205,7 +205,7 @@
 
   @override
   Token parse(Token token, Parser parser) {
-    Token elseToken = token.next;
+    Token elseToken = token.next!;
     assert(optional('else', elseToken));
     parser.listener.handleElseControlFlow(elseToken);
     return elseToken;
@@ -214,9 +214,9 @@
   @override
   LiteralEntryInfo computeNext(Token token) {
     assert(optional('else', token));
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('for', next) ||
-        (optional('await', next) && optional('for', next.next))) {
+        (optional('await', next) && optional('for', next.next!))) {
       return new Nested(new ForCondition(), const IfElseComplete());
     } else if (optional('if', next)) {
       return new Nested(ifCondition, const IfElseComplete());
@@ -261,7 +261,7 @@
 
   @override
   Token parse(Token token, Parser parser) {
-    final Token operator = token.next;
+    final Token operator = token.next!;
     assert(optional('...', operator) || optional('...?', operator));
     token = parser.parseExpression(operator);
     parser.listener.handleSpreadExpression(operator);
@@ -270,20 +270,20 @@
 }
 
 class Nested extends LiteralEntryInfo {
-  LiteralEntryInfo nestedStep;
+  LiteralEntryInfo? nestedStep;
   final LiteralEntryInfo lastStep;
 
   Nested(this.nestedStep, this.lastStep) : super(false, 0);
 
   @override
-  bool get hasEntry => nestedStep.hasEntry;
+  bool get hasEntry => nestedStep!.hasEntry;
 
   @override
-  Token parse(Token token, Parser parser) => nestedStep.parse(token, parser);
+  Token parse(Token token, Parser parser) => nestedStep!.parse(token, parser);
 
   @override
   LiteralEntryInfo computeNext(Token token) {
-    nestedStep = nestedStep.computeNext(token);
+    nestedStep = nestedStep!.computeNext(token);
     return nestedStep != null ? this : lastStep;
   }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart b/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart
index 3ef7898..a062b38 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart
@@ -23,8 +23,8 @@
     //   external() => true;
     // and in
     //   for (final external in list) { }
-    Token next = token.next;
-    Keyword keyword = next.keyword;
+    Token next = token.next!;
+    Keyword? keyword = next.keyword;
     if (keyword == null && !next.isIdentifier || keyword == Keyword.IN) {
       return false;
     }
@@ -36,15 +36,15 @@
 /// can occur, but does not call handleModifier or handleModifiers.
 class ModifierRecoveryContext {
   final Parser parser;
-  Token abstractToken;
-  Token constToken;
-  Token covariantToken;
-  Token externalToken;
-  Token finalToken;
-  Token lateToken;
-  Token requiredToken;
-  Token staticToken;
-  Token varToken;
+  Token? abstractToken;
+  Token? constToken;
+  Token? covariantToken;
+  Token? externalToken;
+  Token? finalToken;
+  Token? lateToken;
+  Token? requiredToken;
+  Token? staticToken;
+  Token? varToken;
 
   // Set `true` when parsing modifiers after the `factory` token.
   bool afterFactory = false;
@@ -54,7 +54,7 @@
 
   ModifierRecoveryContext(this.parser);
 
-  set staticOrCovariant(Token staticOrCovariant) {
+  set staticOrCovariant(Token? staticOrCovariant) {
     if (staticOrCovariant == null) {
       covariantToken = null;
       staticToken = null;
@@ -70,9 +70,9 @@
     }
   }
 
-  Token get varFinalOrConst => varToken ?? finalToken ?? constToken;
+  Token? get varFinalOrConst => varToken ?? finalToken ?? constToken;
 
-  set varFinalOrConst(Token varFinalOrConst) {
+  set varFinalOrConst(Token? varFinalOrConst) {
     if (varFinalOrConst == null) {
       varToken = null;
       finalToken = null;
@@ -121,7 +121,7 @@
     } else if (memberKind == MemberKind.GeneralizedFunctionType) {
       if (varFinalOrConst != null) {
         parser.reportRecoverableError(
-            varFinalOrConst, codes.messageFunctionTypedParameterVar);
+            varFinalOrConst!, codes.messageFunctionTypedParameterVar);
       }
     }
     reportExtraneousModifier(abstractToken);
@@ -137,7 +137,7 @@
     token = parseModifiers(token);
     if (abstractToken != null) {
       parser.reportRecoverableError(
-          abstractToken, codes.messageAbstractClassMember);
+          abstractToken!, codes.messageAbstractClassMember);
     }
     reportExtraneousModifier(lateToken);
     reportExtraneousModifier(requiredToken);
@@ -178,9 +178,9 @@
   /// in that order, and the others ignored.
   Token parseModifiers(Token token) {
     // Process invalid and out-of-order modifiers
-    Token next = token.next;
+    Token next = token.next!;
     while (true) {
-      final String value = next.stringValue;
+      final String? value = next.stringValue;
       if (isModifier(next)) {
         if (identical('abstract', value)) {
           token = parseAbstract(token);
@@ -210,21 +210,21 @@
       } else {
         break;
       }
-      next = token.next;
+      next = token.next!;
     }
     return token;
   }
 
   Token parseAbstract(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('abstract', next));
     if (abstractToken == null) {
       abstractToken = next;
 
       if (varFinalOrConst != null) {
-        reportModifierOutOfOrder(next, varFinalOrConst.lexeme);
+        reportModifierOutOfOrder(next, varFinalOrConst!.lexeme);
       } else if (covariantToken != null) {
-        reportModifierOutOfOrder(next, covariantToken.lexeme);
+        reportModifierOutOfOrder(next, covariantToken!.lexeme);
       }
       return next;
     }
@@ -236,7 +236,7 @@
   }
 
   Token parseConst(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('const', next));
     if (varFinalOrConst == null && covariantToken == null) {
       constToken = next;
@@ -244,7 +244,7 @@
       if (afterFactory) {
         reportModifierOutOfOrder(next, 'factory');
       } else if (lateToken != null) {
-        reportConflictingModifiers(next, lateToken);
+        reportConflictingModifiers(next, lateToken!);
       }
       return next;
     }
@@ -254,11 +254,11 @@
       parser.reportRecoverableErrorWithToken(
           next, codes.templateDuplicatedModifier);
     } else if (covariantToken != null) {
-      reportConflictingModifiers(next, covariantToken);
+      reportConflictingModifiers(next, covariantToken!);
     } else if (finalToken != null) {
       parser.reportRecoverableError(next, codes.messageConstAndFinal);
     } else if (varToken != null) {
-      reportConflictingModifiers(next, varToken);
+      reportConflictingModifiers(next, varToken!);
     } else {
       throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
     }
@@ -266,7 +266,7 @@
   }
 
   Token parseCovariant(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('covariant', next));
     if (constToken == null &&
         covariantToken == null &&
@@ -275,11 +275,11 @@
       covariantToken = next;
 
       if (varToken != null) {
-        reportModifierOutOfOrder(next, varToken.lexeme);
+        reportModifierOutOfOrder(next, varToken!.lexeme);
       } else if (finalToken != null) {
-        reportModifierOutOfOrder(next, finalToken.lexeme);
+        reportModifierOutOfOrder(next, finalToken!.lexeme);
       } else if (lateToken != null) {
-        reportModifierOutOfOrder(next, lateToken.lexeme);
+        reportModifierOutOfOrder(next, lateToken!.lexeme);
       }
       return next;
     }
@@ -291,7 +291,7 @@
     } else if (afterFactory) {
       reportExtraneousModifier(next);
     } else if (constToken != null) {
-      reportConflictingModifiers(next, constToken);
+      reportConflictingModifiers(next, constToken!);
     } else if (staticToken != null) {
       parser.reportRecoverableError(next, codes.messageCovariantAndStatic);
     } else {
@@ -301,7 +301,7 @@
   }
 
   Token parseExternal(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('external', next));
     if (externalToken == null) {
       externalToken = next;
@@ -309,15 +309,15 @@
       if (afterFactory) {
         reportModifierOutOfOrder(next, 'factory');
       } else if (constToken != null) {
-        reportModifierOutOfOrder(next, constToken.lexeme);
+        reportModifierOutOfOrder(next, constToken!.lexeme);
       } else if (staticToken != null) {
-        reportModifierOutOfOrder(next, staticToken.lexeme);
+        reportModifierOutOfOrder(next, staticToken!.lexeme);
       } else if (lateToken != null) {
-        reportModifierOutOfOrder(next, lateToken.lexeme);
+        reportModifierOutOfOrder(next, lateToken!.lexeme);
       } else if (varFinalOrConst != null) {
-        reportModifierOutOfOrder(next, varFinalOrConst.lexeme);
+        reportModifierOutOfOrder(next, varFinalOrConst!.lexeme);
       } else if (covariantToken != null) {
-        reportModifierOutOfOrder(next, covariantToken.lexeme);
+        reportModifierOutOfOrder(next, covariantToken!.lexeme);
       }
       return next;
     }
@@ -329,7 +329,7 @@
   }
 
   Token parseFinal(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('final', next));
     if (varFinalOrConst == null && !afterFactory) {
       finalToken = next;
@@ -347,7 +347,7 @@
     } else if (varToken != null) {
       parser.reportRecoverableError(next, codes.messageFinalAndVar);
     } else if (lateToken != null) {
-      reportModifierOutOfOrder(next, lateToken.lexeme);
+      reportModifierOutOfOrder(next, lateToken!.lexeme);
     } else {
       throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
     }
@@ -355,17 +355,17 @@
   }
 
   Token parseLate(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('late', next));
     if (lateToken == null) {
       lateToken = next;
 
       if (constToken != null) {
-        reportConflictingModifiers(next, constToken);
+        reportConflictingModifiers(next, constToken!);
       } else if (varToken != null) {
-        reportModifierOutOfOrder(next, varToken.lexeme);
+        reportModifierOutOfOrder(next, varToken!.lexeme);
       } else if (finalToken != null) {
-        reportModifierOutOfOrder(next, finalToken.lexeme);
+        reportModifierOutOfOrder(next, finalToken!.lexeme);
       }
       return next;
     }
@@ -377,19 +377,19 @@
   }
 
   Token parseRequired(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('required', next));
     if (requiredToken == null) {
       requiredToken = next;
 
       if (constToken != null) {
-        reportModifierOutOfOrder(requiredToken, constToken.lexeme);
+        reportModifierOutOfOrder(requiredToken!, constToken!.lexeme);
       } else if (covariantToken != null) {
-        reportModifierOutOfOrder(requiredToken, covariantToken.lexeme);
+        reportModifierOutOfOrder(requiredToken!, covariantToken!.lexeme);
       } else if (finalToken != null) {
-        reportModifierOutOfOrder(requiredToken, finalToken.lexeme);
+        reportModifierOutOfOrder(requiredToken!, finalToken!.lexeme);
       } else if (varToken != null) {
-        reportModifierOutOfOrder(requiredToken, varToken.lexeme);
+        reportModifierOutOfOrder(requiredToken!, varToken!.lexeme);
       }
       return next;
     }
@@ -401,19 +401,19 @@
   }
 
   Token parseStatic(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('static', next));
     if (covariantToken == null && staticToken == null && !afterFactory) {
       staticToken = next;
 
       if (constToken != null) {
-        reportModifierOutOfOrder(next, constToken.lexeme);
+        reportModifierOutOfOrder(next, constToken!.lexeme);
       } else if (finalToken != null) {
-        reportModifierOutOfOrder(next, finalToken.lexeme);
+        reportModifierOutOfOrder(next, finalToken!.lexeme);
       } else if (varToken != null) {
-        reportModifierOutOfOrder(next, varToken.lexeme);
+        reportModifierOutOfOrder(next, varToken!.lexeme);
       } else if (lateToken != null) {
-        reportModifierOutOfOrder(next, lateToken.lexeme);
+        reportModifierOutOfOrder(next, lateToken!.lexeme);
       }
       return next;
     }
@@ -433,7 +433,7 @@
   }
 
   Token parseVar(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('var', next));
     if (varFinalOrConst == null && !afterFactory) {
       varToken = next;
@@ -447,7 +447,7 @@
     } else if (afterFactory) {
       reportExtraneousModifier(next);
     } else if (constToken != null) {
-      reportConflictingModifiers(next, constToken);
+      reportConflictingModifiers(next, constToken!);
     } else if (finalToken != null) {
       parser.reportRecoverableError(next, codes.messageFinalAndVar);
     } else {
@@ -463,14 +463,14 @@
             .withArguments(modifier.lexeme, earlierModifier.lexeme));
   }
 
-  void reportExtraneousModifier(Token modifier) {
+  void reportExtraneousModifier(Token? modifier) {
     if (modifier != null) {
       parser.reportRecoverableErrorWithToken(
           modifier, codes.templateExtraneousModifier);
     }
   }
 
-  void reportExtraneousModifierInExtension(Token modifier) {
+  void reportExtraneousModifierInExtension(Token? modifier) {
     if (modifier != null) {
       parser.reportRecoverableErrorWithToken(
           modifier, codes.templateExtraneousModifierInExtension);
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 6b2b389..3135c01 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -20,6 +20,7 @@
         POSTFIX_PRECEDENCE,
         RELATIONAL_PRECEDENCE,
         SELECTOR_PRECEDENCE,
+        StringToken,
         SyntheticBeginToken,
         SyntheticKeywordToken,
         SyntheticStringToken,
@@ -268,7 +269,7 @@
 class Parser {
   Listener listener;
 
-  Uri get uri => listener.uri;
+  Uri? get uri => listener.uri;
 
   bool mayParseFunctionExpressions = true;
 
@@ -290,14 +291,14 @@
 
   /// A rewriter for inserting synthetic tokens.
   /// Access using [rewriter] for lazy initialization.
-  TokenStreamRewriter cachedRewriter;
+  TokenStreamRewriter? cachedRewriter;
 
   TokenStreamRewriter get rewriter {
-    cachedRewriter ??= new TokenStreamRewriterImpl();
-    return cachedRewriter;
+    return cachedRewriter ??= new TokenStreamRewriterImpl();
   }
 
-  Parser(this.listener);
+  Parser(this.listener)
+      : assert(listener != null); // ignore:unnecessary_null_comparison
 
   bool get inGenerator {
     return asyncState == AsyncModifier.AsyncStar ||
@@ -347,30 +348,30 @@
     int count = 0;
     DirectiveContext directiveState = new DirectiveContext();
     token = syntheticPreviousToken(token);
-    if (identical(token.next.type, TokenType.SCRIPT_TAG)) {
-      directiveState?.checkScriptTag(this, token.next);
+    if (identical(token.next!.type, TokenType.SCRIPT_TAG)) {
+      directiveState.checkScriptTag(this, token.next!);
       token = parseScript(token);
     }
-    while (!token.next.isEof) {
-      final Token start = token.next;
+    while (!token.next!.isEof) {
+      final Token start = token.next!;
       token = parseTopLevelDeclarationImpl(token, directiveState);
-      listener.endTopLevelDeclaration(token.next);
+      listener.endTopLevelDeclaration(token.next!);
       count++;
-      if (start == token.next) {
+      if (start == token.next!) {
         // Recovery:
         // If progress has not been made reaching the end of the token stream,
         // then report an error and skip the current token.
-        token = token.next;
+        token = token.next!;
         listener.beginMetadataStar(token);
         listener.endMetadataStar(/* count = */ 0);
         reportRecoverableErrorWithToken(
             token, codes.templateExpectedDeclaration);
         listener.handleInvalidTopLevelDeclaration(token);
-        listener.endTopLevelDeclaration(token.next);
+        listener.endTopLevelDeclaration(token.next!);
         count++;
       }
     }
-    token = token.next;
+    token = token.next!;
     reportAllErrorTokens(errorToken);
     listener.endCompilationUnit(count, token);
     // Clear fields that could lead to memory leak.
@@ -393,9 +394,9 @@
     int count = 0;
     DirectiveContext directiveState = new DirectiveContext();
     token = syntheticPreviousToken(token);
-    while (!token.next.isEof) {
-      final Token start = token.next;
-      final String nextValue = start.next.stringValue;
+    while (!token.next!.isEof) {
+      final Token start = token.next!;
+      final String? nextValue = start.next!.stringValue;
 
       // If a built-in keyword is being used as function name, then stop.
       if (identical(nextValue, '.') ||
@@ -404,21 +405,21 @@
         break;
       }
 
-      if (identical(token.next.type, TokenType.SCRIPT_TAG)) {
-        directiveState?.checkScriptTag(this, token.next);
+      if (identical(token.next!.type, TokenType.SCRIPT_TAG)) {
+        directiveState.checkScriptTag(this, token.next!);
         token = parseScript(token);
       } else {
         token = parseMetadataStar(token);
-        Token keyword = token.next;
-        final String value = keyword.stringValue;
+        Token keyword = token.next!;
+        final String? value = keyword.stringValue;
         if (identical(value, 'import')) {
-          directiveState?.checkImport(this, keyword);
+          directiveState.checkImport(this, keyword);
           token = parseImport(keyword);
         } else if (identical(value, 'export')) {
-          directiveState?.checkExport(this, keyword);
+          directiveState.checkExport(this, keyword);
           token = parseExport(keyword);
         } else if (identical(value, 'library')) {
-          directiveState?.checkLibrary(this, keyword);
+          directiveState.checkLibrary(this, keyword);
           token = parseLibraryName(keyword);
         } else if (identical(value, 'part')) {
           token = parsePartOrPartOf(keyword, directiveState);
@@ -430,9 +431,9 @@
           break;
         }
       }
-      listener.endTopLevelDeclaration(token.next);
+      listener.endTopLevelDeclaration(token.next!);
     }
-    token = token.next;
+    token = token.next!;
     listener.endCompilationUnit(count, token);
     // Clear fields that could lead to memory leak.
     cachedRewriter = null;
@@ -448,7 +449,7 @@
   Token parseTopLevelDeclaration(Token token) {
     token = parseTopLevelDeclarationImpl(
             syntheticPreviousToken(token), /* directiveState = */ null)
-        .next;
+        .next!;
     listener.endTopLevelDeclaration(token);
     return token;
   }
@@ -469,9 +470,9 @@
   /// ;
   /// ```
   Token parseTopLevelDeclarationImpl(
-      Token token, DirectiveContext directiveState) {
+      Token token, DirectiveContext? directiveState) {
     token = parseMetadataStar(token);
-    Token next = token.next;
+    Token next = token.next!;
     if (next.isTopLevelKeyword) {
       return parseTopLevelKeywordDeclaration(token, next, directiveState);
     }
@@ -483,15 +484,15 @@
           ((optional('const', next) || optional('final', next)) &&
               // Ignore `const class` and `final class` so that it is reported
               // below as an invalid modifier on a class.
-              !optional('class', next.next))) {
+              !optional('class', next.next!))) {
         directiveState?.checkDeclaration();
         return parseTopLevelMemberImpl(token);
       }
-      while (token.next.isModifier) {
-        token = token.next;
+      while (token.next!.isModifier) {
+        token = token.next!;
       }
     }
-    next = token.next;
+    next = token.next!;
     if (next.isTopLevelKeyword) {
       return parseTopLevelKeywordDeclaration(start, next, directiveState);
     } else if (next.isKeywordOrIdentifier) {
@@ -505,7 +506,7 @@
       return parseTopLevelMemberImpl(start);
     }
     // Recovery
-    if (next.isOperator && optional('(', next.next)) {
+    if (next.isOperator && optional('(', next.next!)) {
       // This appears to be a top level operator declaration, which is invalid.
       reportRecoverableError(next, codes.messageTopLevelOperator);
       // Insert a synthetic identifier
@@ -521,8 +522,8 @@
 
   /// Parse the modifiers before the `class` keyword.
   /// Return the first `abstract` modifier or `null` if not found.
-  Token parseClassDeclarationModifiers(Token start, Token keyword) {
-    Token modifier = start.next;
+  Token? parseClassDeclarationModifiers(Token start, Token keyword) {
+    Token modifier = start.next!;
     while (modifier != keyword) {
       if (optional('abstract', modifier)) {
         parseTopLevelKeywordModifiers(modifier, keyword);
@@ -531,18 +532,18 @@
         // Recovery
         reportTopLevelModifierError(modifier, keyword);
       }
-      modifier = modifier.next;
+      modifier = modifier.next!;
     }
     return null;
   }
 
   /// Report errors on any modifiers before the specified keyword.
   void parseTopLevelKeywordModifiers(Token start, Token keyword) {
-    Token modifier = start.next;
+    Token modifier = start.next!;
     while (modifier != keyword) {
       // Recovery
       reportTopLevelModifierError(modifier, keyword);
-      modifier = modifier.next;
+      modifier = modifier.next!;
     }
   }
 
@@ -571,12 +572,12 @@
   /// Parse any top-level declaration that begins with a keyword.
   /// [start] is the token before any modifiers preceding [keyword].
   Token parseTopLevelKeywordDeclaration(
-      Token start, Token keyword, DirectiveContext directiveState) {
+      Token start, Token keyword, DirectiveContext? directiveState) {
     assert(keyword.isTopLevelKeyword);
-    final String value = keyword.stringValue;
+    final String? value = keyword.stringValue;
     if (identical(value, 'class')) {
       directiveState?.checkDeclaration();
-      Token abstractToken = parseClassDeclarationModifiers(start, keyword);
+      Token? abstractToken = parseClassDeclarationModifiers(start, keyword);
       return parseClassOrNamedMixinApplication(abstractToken, keyword);
     } else if (identical(value, 'enum')) {
       directiveState?.checkDeclaration();
@@ -587,7 +588,7 @@
       // and can be used in a top level declaration
       // as an identifier such as "abstract<T>() => 0;"
       // or as a prefix such as "abstract.A b() => 0;".
-      String nextValue = keyword.next.stringValue;
+      String? nextValue = keyword.next!.stringValue;
       if (identical(nextValue, '(') || identical(nextValue, '.')) {
         directiveState?.checkDeclaration();
         return parseTopLevelMemberImpl(start);
@@ -595,8 +596,8 @@
         if (identical(value, 'extension')) {
           // The name in an extension declaration is optional:
           // `extension<T> on ...`
-          Token endGroup = keyword.next.endGroup;
-          if (endGroup != null && optional('on', endGroup.next)) {
+          Token? endGroup = keyword.next!.endGroup;
+          if (endGroup != null && optional('on', endGroup.next!)) {
             directiveState?.checkDeclaration();
             return parseExtension(keyword);
           }
@@ -654,10 +655,10 @@
   /// ;
   /// ```
   Token parseImportPrefixOpt(Token token) {
-    Token next = token.next;
-    if (optional('deferred', next) && optional('as', next.next)) {
+    Token next = token.next!;
+    if (optional('deferred', next) && optional('as', next.next!)) {
       Token deferredToken = next;
-      Token asKeyword = next.next;
+      Token asKeyword = next.next!;
       token = ensureIdentifier(
           asKeyword, IdentifierContext.importPrefixDeclaration);
       listener.handleImportPrefix(deferredToken, asKeyword);
@@ -686,7 +687,7 @@
     Token uri = token;
     token = parseConditionalUriStar(token);
     token = parseImportPrefixOpt(token);
-    token = parseCombinatorStar(token).next;
+    token = parseCombinatorStar(token).next!;
     if (optional(';', token)) {
       listener.endImport(importKeyword, token);
       return token;
@@ -711,7 +712,7 @@
     token = parseImportPrefixOpt(token);
     token = parseCombinatorStar(token);
 
-    Token firstDeferredKeyword = recoveryListener.deferredKeyword;
+    Token? firstDeferredKeyword = recoveryListener.deferredKeyword;
     bool hasPrefix = recoveryListener.asKeyword != null;
     bool hasCombinator = recoveryListener.hasCombinator;
 
@@ -720,9 +721,9 @@
     recoveryListener.listener = primaryListener;
 
     // Parse additional out-of-order clauses.
-    Token semicolon;
+    Token? semicolon;
     do {
-      Token start = token.next;
+      Token start = token.next!;
 
       // Check for extraneous token in the middle of an import statement.
       token = skipUnexpectedTokenOpt(
@@ -745,20 +746,20 @@
         }
       }
 
-      if (optional('deferred', token.next) &&
-          !optional('as', token.next.next)) {
-        listener.handleImportPrefix(token.next, /* asKeyword = */ null);
-        token = token.next;
+      if (optional('deferred', token.next!) &&
+          !optional('as', token.next!.next!)) {
+        listener.handleImportPrefix(token.next!, /* asKeyword = */ null);
+        token = token.next!;
       } else {
         token = parseImportPrefixOpt(token);
       }
       if (recoveryListener.deferredKeyword != null) {
         if (firstDeferredKeyword != null) {
-          reportRecoverableError(
-              recoveryListener.deferredKeyword, codes.messageDuplicateDeferred);
+          reportRecoverableError(recoveryListener.deferredKeyword!,
+              codes.messageDuplicateDeferred);
         } else {
           if (hasPrefix) {
-            reportRecoverableError(recoveryListener.deferredKeyword,
+            reportRecoverableError(recoveryListener.deferredKeyword!,
                 codes.messageDeferredAfterPrefix);
           }
           firstDeferredKeyword = recoveryListener.deferredKeyword;
@@ -767,11 +768,11 @@
       if (recoveryListener.asKeyword != null) {
         if (hasPrefix) {
           reportRecoverableError(
-              recoveryListener.asKeyword, codes.messageDuplicatePrefix);
+              recoveryListener.asKeyword!, codes.messageDuplicatePrefix);
         } else {
           if (hasCombinator) {
-            reportRecoverableError(
-                recoveryListener.asKeyword, codes.messagePrefixAfterCombinator);
+            reportRecoverableError(recoveryListener.asKeyword!,
+                codes.messagePrefixAfterCombinator);
           }
           hasPrefix = true;
         }
@@ -780,9 +781,9 @@
       token = parseCombinatorStar(token);
       hasCombinator = hasCombinator || recoveryListener.hasCombinator;
 
-      if (optional(';', token.next)) {
-        semicolon = token.next;
-      } else if (identical(start, token.next)) {
+      if (optional(';', token.next!)) {
+        semicolon = token.next!;
+      } else if (identical(start, token.next!)) {
         // If no forward progress was made, insert ';' so that we exit loop.
         semicolon = ensureSemicolon(token);
       }
@@ -803,9 +804,9 @@
   /// ;
   /// ```
   Token parseConditionalUriStar(Token token) {
-    listener.beginConditionalUris(token.next);
+    listener.beginConditionalUris(token.next!);
     int count = 0;
-    while (optional('if', token.next)) {
+    while (optional('if', token.next!)) {
       count++;
       token = parseConditionalUri(token);
     }
@@ -819,25 +820,25 @@
   /// ;
   /// ```
   Token parseConditionalUri(Token token) {
-    Token ifKeyword = token = token.next;
+    Token ifKeyword = token = token.next!;
     assert(optional('if', token));
     listener.beginConditionalUri(token);
-    Token leftParen = token.next;
+    Token leftParen = token.next!;
     if (!optional('(', leftParen)) {
       reportRecoverableError(
           leftParen, codes.templateExpectedButGot.withArguments('('));
       leftParen = rewriter.insertParens(token, /* includeIdentifier = */ true);
     }
     token = parseDottedName(leftParen);
-    Token next = token.next;
-    Token equalitySign;
+    Token next = token.next!;
+    Token? equalitySign;
     if (optional('==', next)) {
       equalitySign = next;
       token = ensureLiteralString(next);
-      next = token.next;
+      next = token.next!;
     }
     if (next != leftParen.endGroup) {
-      Token endGroup = leftParen.endGroup;
+      Token endGroup = leftParen.endGroup!;
       if (endGroup.isSynthetic) {
         // The scanner did not place the synthetic ')' correctly, so move it.
         next = rewriter.moveSynthetic(token, endGroup);
@@ -863,9 +864,9 @@
     token = ensureIdentifier(token, IdentifierContext.dottedName);
     Token firstIdentifier = token;
     int count = 1;
-    while (optional('.', token.next)) {
+    while (optional('.', token.next!)) {
       token = ensureIdentifier(
-          token.next, IdentifierContext.dottedNameContinuation);
+          token.next!, IdentifierContext.dottedNameContinuation);
       count++;
     }
     listener.handleDottedName(count, firstIdentifier);
@@ -895,11 +896,11 @@
   /// ;
   /// ```
   Token parseCombinatorStar(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     listener.beginCombinators(next);
     int count = 0;
     while (true) {
-      String value = next.stringValue;
+      String? value = next.stringValue;
       if (identical('hide', value)) {
         token = parseHide(token);
       } else if (identical('show', value)) {
@@ -908,7 +909,7 @@
         listener.endCombinators(count);
         break;
       }
-      next = token.next;
+      next = token.next!;
       count++;
     }
     return token;
@@ -920,7 +921,7 @@
   /// ;
   /// ```
   Token parseHide(Token token) {
-    Token hideKeyword = token.next;
+    Token hideKeyword = token.next!;
     assert(optional('hide', hideKeyword));
     listener.beginHide(hideKeyword);
     token = parseIdentifierList(hideKeyword);
@@ -934,7 +935,7 @@
   /// ;
   /// ```
   Token parseShow(Token token) {
-    Token showKeyword = token.next;
+    Token showKeyword = token.next!;
     assert(optional('show', showKeyword));
     listener.beginShow(showKeyword);
     token = parseIdentifierList(showKeyword);
@@ -950,8 +951,8 @@
   Token parseIdentifierList(Token token) {
     token = ensureIdentifier(token, IdentifierContext.combinator);
     int count = 1;
-    while (optional(',', token.next)) {
-      token = ensureIdentifier(token.next, IdentifierContext.combinator);
+    while (optional(',', token.next!)) {
+      token = ensureIdentifier(token.next!, IdentifierContext.combinator);
       count++;
     }
     listener.handleIdentifierList(count);
@@ -964,23 +965,23 @@
   /// ;
   /// ```
   Token parseTypeList(Token token) {
-    listener.beginTypeList(token.next);
+    listener.beginTypeList(token.next!);
     token =
         computeType(token, /* required = */ true).ensureTypeOrVoid(token, this);
     int count = 1;
-    while (optional(',', token.next)) {
-      token = computeType(token.next, /* required = */ true)
-          .ensureTypeOrVoid(token.next, this);
+    while (optional(',', token.next!)) {
+      token = computeType(token.next!, /* required = */ true)
+          .ensureTypeOrVoid(token.next!, this);
       count++;
     }
     listener.endTypeList(count);
     return token;
   }
 
-  Token parsePartOrPartOf(Token partKeyword, DirectiveContext directiveState) {
+  Token parsePartOrPartOf(Token partKeyword, DirectiveContext? directiveState) {
     assert(optional('part', partKeyword));
     listener.beginUncategorizedTopLevelDeclaration(partKeyword);
-    if (optional('of', partKeyword.next)) {
+    if (optional('of', partKeyword.next!)) {
       directiveState?.checkPartOf(this, partKeyword);
       return parsePartOf(partKeyword);
     } else {
@@ -1009,11 +1010,11 @@
   /// ;
   /// ```
   Token parsePartOf(Token partKeyword) {
-    Token ofKeyword = partKeyword.next;
+    Token ofKeyword = partKeyword.next!;
     assert(optional('part', partKeyword));
     assert(optional('of', ofKeyword));
     listener.beginPartOf(partKeyword);
-    bool hasName = ofKeyword.next.isIdentifier;
+    bool hasName = ofKeyword.next!.isIdentifier;
     Token token;
     if (hasName) {
       token = parseQualified(ofKeyword, IdentifierContext.partName,
@@ -1032,9 +1033,9 @@
   /// ;
   /// ```
   Token parseMetadataStar(Token token) {
-    listener.beginMetadataStar(token.next);
+    listener.beginMetadataStar(token.next!);
     int count = 0;
-    while (optional('@', token.next)) {
+    while (optional('@', token.next!)) {
       token = parseMetadata(token);
       count++;
     }
@@ -1048,24 +1049,24 @@
   /// ;
   /// ```
   Token parseMetadata(Token token) {
-    Token atToken = token.next;
+    Token atToken = token.next!;
     assert(optional('@', atToken));
     listener.beginMetadata(atToken);
     token = ensureIdentifier(atToken, IdentifierContext.metadataReference);
     token =
         parseQualifiedRestOpt(token, IdentifierContext.metadataContinuation);
-    if (optional("<", token.next)) {
-      reportRecoverableError(token.next, codes.messageMetadataTypeArguments);
+    if (optional("<", token.next!)) {
+      reportRecoverableError(token.next!, codes.messageMetadataTypeArguments);
     }
     token = computeTypeParamOrArg(token).parseArguments(token, this);
-    Token period = null;
-    if (optional('.', token.next)) {
-      period = token.next;
+    Token? period = null;
+    if (optional('.', token.next!)) {
+      period = token.next!;
       token = ensureIdentifier(
           period, IdentifierContext.metadataContinuationAfterTypeArguments);
     }
     token = parseArgumentsOpt(token);
-    listener.endMetadata(atToken, period, token.next);
+    listener.endMetadata(atToken, period, token.next!);
     return token;
   }
 
@@ -1075,7 +1076,7 @@
   /// ;
   /// ```
   Token parseScript(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(identical(token.type, TokenType.SCRIPT_TAG));
     listener.handleScript(token);
     return token;
@@ -1108,11 +1109,11 @@
     listener.beginFunctionTypeAlias(typedefKeyword);
     TypeInfo typeInfo = computeType(typedefKeyword, /* required = */ false);
     Token token = typeInfo.skipType(typedefKeyword);
-    Token next = token.next;
-    Token equals;
+    Token next = token.next!;
+    Token? equals;
     TypeParamOrArgInfo typeParam =
         computeTypeParamOrArg(next, /* inDeclaration = */ true);
-    if (typeInfo == noType && optional('=', typeParam.skip(next).next)) {
+    if (typeInfo == noType && optional('=', typeParam.skip(next).next!)) {
       // New style typedef, e.g. typedef foo = void Function();".
 
       // Parse as recovered here to 'force' using it as an identifier as we've
@@ -1122,13 +1123,13 @@
           IdentifierContext.typedefDeclaration, /* isRecovered = */ true);
 
       token = typeParam.parseVariables(token, this);
-      next = token.next;
+      next = token.next!;
       // parseVariables rewrites so even though we checked in the if,
       // we might not have an equal here now.
-      if (!optional('=', next) && optional('=', next.next)) {
+      if (!optional('=', next) && optional('=', next.next!)) {
         // Recovery after recovery: A token was inserted, but we'll skip it now
         // to get more in line with what we thought in the if before.
-        next = next.next;
+        next = next.next!;
       }
       if (optional('=', next)) {
         equals = next;
@@ -1137,9 +1138,9 @@
           // Recovery: In certain cases insert missing 'Function' and missing
           // parens.
           Token skippedType = type.skipType(equals);
-          if (optional('(', skippedType.next) &&
-              skippedType.next.endGroup != null &&
-              optional(';', skippedType.next.endGroup.next)) {
+          if (optional('(', skippedType.next!) &&
+              skippedType.next!.endGroup != null &&
+              optional(';', skippedType.next!.endGroup!.next!)) {
             // Turn "<return type>? '(' <whatever> ')';"
             // into "<return type>? Function '(' <whatever> ')';".
             // Assume the type is meant as the return type.
@@ -1149,14 +1150,14 @@
                 codes.templateExpectedButGot.withArguments('Function'));
             type = computeType(equals, /* required = */ true);
           } else if (type is NoType &&
-              optional('<', skippedType.next) &&
-              skippedType.next.endGroup != null) {
+              optional('<', skippedType.next!) &&
+              skippedType.next!.endGroup != null) {
             // Recover these two:
             // "<whatever>;" => "Function<whatever>();"
             // "<whatever>(<whatever>);" => "Function<whatever>(<whatever>);"
-            Token endGroup = skippedType.next.endGroup;
+            Token endGroup = skippedType.next!.endGroup!;
             bool recover = false;
-            if (optional(';', endGroup.next)) {
+            if (optional(';', endGroup.next!)) {
               // Missing parenthesis. Insert them.
               // Turn "<whatever>;" in to "<whatever>();"
               // Insert missing 'Function' below.
@@ -1164,9 +1165,9 @@
                   missingParameterMessage(MemberKind.FunctionTypeAlias));
               rewriter.insertParens(endGroup, /*includeIdentifier =*/ false);
               recover = true;
-            } else if (optional('(', endGroup.next) &&
-                endGroup.next.endGroup != null &&
-                optional(';', endGroup.next.endGroup.next)) {
+            } else if (optional('(', endGroup.next!) &&
+                endGroup.next!.endGroup != null &&
+                optional(';', endGroup.next!.endGroup!.next!)) {
               // "<whatever>(<whatever>);". Insert missing 'Function' below.
               recover = true;
             }
@@ -1193,10 +1194,10 @@
     } else {
       // Old style typedef, e.g. "typedef void foo();".
       token = typeInfo.parseType(typedefKeyword, this);
-      next = token.next;
+      next = token.next!;
       bool isIdentifierRecovered = false;
       if (next.kind != IDENTIFIER_TOKEN &&
-          optional('(', typeParam.skip(next).next)) {
+          optional('(', typeParam.skip(next).next!)) {
         // Recovery: Not a valid identifier, but is used as such.
         isIdentifierRecovered = true;
       }
@@ -1214,13 +1215,13 @@
   /// Parse a mixin application starting from `with`. Assumes that the first
   /// type has already been parsed.
   Token parseMixinApplicationRest(Token token) {
-    Token withKeyword = token.next;
+    Token withKeyword = token.next!;
     if (!optional('with', withKeyword)) {
       // Recovery: Report an error and insert synthetic `with` clause.
       reportRecoverableError(
           withKeyword, codes.templateExpectedButGot.withArguments('with'));
       withKeyword = rewriter.insertSyntheticKeyword(token, Keyword.WITH);
-      if (!isValidTypeReference(withKeyword.next)) {
+      if (!isValidTypeReference(withKeyword.next!)) {
         rewriter.insertSyntheticIdentifier(withKeyword);
       }
     }
@@ -1231,7 +1232,7 @@
 
   Token parseWithClauseOpt(Token token) {
     // <mixins> ::= with <typeNotVoidList>
-    Token withKeyword = token.next;
+    Token withKeyword = token.next!;
     if (optional('with', withKeyword)) {
       token = parseTypeList(withKeyword);
       listener.handleClassWithClause(withKeyword);
@@ -1245,7 +1246,7 @@
   /// or function or method.
   Token parseGetterOrFormalParameters(
       Token token, Token name, bool isGetter, MemberKind kind) {
-    Token next = token.next;
+    Token next = token.next!;
     if (optional("(", next)) {
       if (isGetter) {
         reportRecoverableError(next, codes.messageGetterWithFormals);
@@ -1256,11 +1257,11 @@
     } else {
       // Recovery
       if (optional('operator', name)) {
-        Token next = name.next;
+        Token next = name.next!;
         if (next.isOperator) {
           name = next;
         } else if (isUnaryMinus(next)) {
-          name = next.next;
+          name = next.next!;
         }
       }
       reportRecoverableError(name, missingParameterMessage(kind));
@@ -1271,7 +1272,7 @@
   }
 
   Token parseFormalParametersOpt(Token token, MemberKind kind) {
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('(', next)) {
       token = parseFormalParameters(token, kind);
     } else {
@@ -1281,14 +1282,14 @@
   }
 
   Token skipFormalParameters(Token token, MemberKind kind) {
-    return skipFormalParametersRest(token.next, kind);
+    return skipFormalParametersRest(token.next!, kind);
   }
 
   Token skipFormalParametersRest(Token token, MemberKind kind) {
     assert(optional('(', token));
     // TODO(ahe): Shouldn't this be `beginFormalParameters`?
     listener.beginOptionalFormalParameters(token);
-    Token closeBrace = token.endGroup;
+    Token closeBrace = token.endGroup!;
     assert(optional(')', closeBrace));
     listener.endFormalParameters(/* count = */ 0, token, closeBrace, kind);
     return closeBrace;
@@ -1299,7 +1300,7 @@
   /// If `kind == MemberKind.GeneralizedFunctionType`, then names may be
   /// omitted (except for named arguments). Otherwise, types may be omitted.
   Token parseFormalParametersRequiredOpt(Token token, MemberKind kind) {
-    Token next = token.next;
+    Token next = token.next!;
     if (!optional('(', next)) {
       reportRecoverableError(next, missingParameterMessage(kind));
       next = rewriter.insertParens(token, /* includeIdentifier = */ false);
@@ -1313,7 +1314,7 @@
   /// If `kind == MemberKind.GeneralizedFunctionType`, then names may be
   /// omitted (except for named arguments). Otherwise, types may be omitted.
   Token parseFormalParameters(Token token, MemberKind kind) {
-    return parseFormalParametersRest(token.next, kind);
+    return parseFormalParametersRest(token.next!, kind);
   }
 
   /// Parses the formal parameter list of a function given that the left
@@ -1327,13 +1328,13 @@
     listener.beginFormalParameters(begin, kind);
     int parameterCount = 0;
     while (true) {
-      Token next = token.next;
+      Token next = token.next!;
       if (optional(')', next)) {
         token = next;
         break;
       }
       ++parameterCount;
-      String value = next.stringValue;
+      String? value = next.stringValue;
       if (identical(value, '[')) {
         token = parseOptionalPositionalParameters(token, kind);
         token = ensureCloseParen(token, begin);
@@ -1350,19 +1351,19 @@
         break;
       }
       token = parseFormalParameter(token, FormalParameterKind.mandatory, kind);
-      next = token.next;
+      next = token.next!;
       if (!optional(',', next)) {
-        Token next = token.next;
+        Token next = token.next!;
         if (optional(')', next)) {
           token = next;
         } else {
           // Recovery
-          if (begin.endGroup.isSynthetic) {
+          if (begin.endGroup!.isSynthetic) {
             // Scanner has already reported a missing `)` error,
             // but placed the `)` in the wrong location, so move it.
-            token = rewriter.moveSynthetic(token, begin.endGroup);
+            token = rewriter.moveSynthetic(token, begin.endGroup!);
           } else if (next.kind == IDENTIFIER_TOKEN &&
-              next.next.kind == IDENTIFIER_TOKEN) {
+              next.next!.kind == IDENTIFIER_TOKEN) {
             // Looks like a missing comma
             token = rewriteAndRecover(
                 token,
@@ -1394,6 +1395,42 @@
     return codes.messageMissingFunctionParameters;
   }
 
+  /// Check if [token] is the usage of 'required' in a formal parameter in a
+  /// context where it's not legal (i.e. in non-nnbd-mode).
+  bool _isUseOfRequiredInNonNNBD(Token token) {
+    if (token.next is StringToken && token.next!.value() == "required") {
+      // Possible recovery: Figure out if we're in a situation like
+      // required covariant? <type> name
+      // (in non-nnbd-mode) where the required modifier is not legal and thus
+      // would normally be parsed as the type.
+      token = token.next!;
+      Token next = token.next!;
+      // Skip modifiers.
+      while (next.isModifier) {
+        token = next;
+        next = next.next!;
+      }
+      // Parse the (potential) new type.
+      TypeInfo typeInfoAlternative = computeType(
+          token,
+          /* required = */ false,
+          /* inDeclaration = */ true);
+      token = typeInfoAlternative.skipType(token);
+      next = token.next!;
+
+      // We've essentially ignored the 'required' at this point.
+      // `token` is (in the good state) the last token of the type,
+      // `next` is (in the good state) the name;
+      // Are we in a 'good' state?
+      if (typeInfoAlternative != noType &&
+          next.isIdentifier &&
+          (optional(',', next.next!) || optional('}', next.next!))) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   /// ```
   /// normalFormalParameter:
   ///   functionFormalParameter |
@@ -1415,22 +1452,32 @@
   /// ```
   Token parseFormalParameter(
       Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
+    // ignore: unnecessary_null_comparison
     assert(parameterKind != null);
     token = parseMetadataStar(token);
-    Token next = token.next;
+
+    Token? skippedNonRequiredRequired;
+    if (_isUseOfRequiredInNonNNBD(token)) {
+      skippedNonRequiredRequired = token.next!;
+      reportRecoverableErrorWithToken(skippedNonRequiredRequired,
+          codes.templateUnexpectedModifierInNonNnbd);
+      token = token.next!;
+    }
+
+    Token next = token.next!;
     Token start = next;
 
     final bool inFunctionType =
         memberKind == MemberKind.GeneralizedFunctionType;
 
-    Token requiredToken;
-    Token covariantToken;
-    Token varFinalOrConst;
+    Token? requiredToken;
+    Token? covariantToken;
+    Token? varFinalOrConst;
     if (isModifier(next)) {
       if (optional('required', next)) {
         if (parameterKind == FormalParameterKind.optionalNamed) {
           requiredToken = token = next;
-          next = token.next;
+          next = token.next!;
         }
       }
 
@@ -1441,7 +1488,7 @@
               memberKind != MemberKind.ExtensionNonStaticMethod &&
               memberKind != MemberKind.ExtensionStaticMethod) {
             covariantToken = token = next;
-            next = token.next;
+            next = token.next!;
           }
         }
 
@@ -1449,10 +1496,10 @@
           if (!inFunctionType) {
             if (optional('var', next)) {
               varFinalOrConst = token = next;
-              next = token.next;
+              next = token.next!;
             } else if (optional('final', next)) {
               varFinalOrConst = token = next;
-              next = token.next;
+              next = token.next!;
             }
           }
 
@@ -1465,18 +1512,23 @@
 
             token = context.parseFormalParameterModifiers(
                 token, parameterKind, memberKind);
-            next = token.next;
+            next = token.next!;
 
             covariantToken = context.covariantToken;
             requiredToken = context.requiredToken;
             varFinalOrConst = context.varFinalOrConst;
-
-            context = null;
           }
         }
       }
     }
 
+    if (requiredToken == null) {
+      // `required` was used as a modifier in non-nnbd mode. An error has been
+      // emitted. Still use it as a required token for the remainder in an
+      // attempt to avoid cascading errors (and for passing to the listener).
+      requiredToken = skippedNonRequiredRequired;
+    }
+
     listener.beginFormalParameter(
         start, memberKind, requiredToken, covariantToken, varFinalOrConst);
 
@@ -1484,27 +1536,27 @@
     final Token beforeType = token;
     TypeInfo typeInfo = computeType(token, inFunctionType);
     token = typeInfo.skipType(token);
-    next = token.next;
+    next = token.next!;
     if (typeInfo == noType &&
         (optional('.', next) ||
-            (next.isIdentifier && optional('.', next.next)))) {
+            (next.isIdentifier && optional('.', next.next!)))) {
       // Recovery: Malformed type reference.
       typeInfo = computeType(beforeType, /* required = */ true);
       token = typeInfo.skipType(beforeType);
-      next = token.next;
+      next = token.next!;
     }
 
     final bool isNamedParameter =
         parameterKind == FormalParameterKind.optionalNamed;
 
-    Token thisKeyword;
-    Token periodAfterThis;
+    Token? thisKeyword;
+    Token? periodAfterThis;
     IdentifierContext nameContext =
         IdentifierContext.formalParameterDeclaration;
 
     if (!inFunctionType && optional('this', next)) {
       thisKeyword = token = next;
-      next = token.next;
+      next = token.next!;
       if (!optional('.', next)) {
         // Recover from a missing period by inserting one.
         next = rewriteAndRecover(
@@ -1513,28 +1565,28 @@
             new SyntheticToken(TokenType.PERIOD, next.charOffset));
       }
       periodAfterThis = token = next;
-      next = token.next;
+      next = token.next!;
       nameContext = IdentifierContext.fieldInitializer;
     }
 
     if (next.isIdentifier) {
       token = next;
-      next = token.next;
+      next = token.next!;
     }
-    Token beforeInlineFunctionType;
+    Token? beforeInlineFunctionType;
     TypeParamOrArgInfo typeParam = noTypeParamOrArg;
     if (optional("<", next)) {
       typeParam = computeTypeParamOrArg(token);
       if (typeParam != noTypeParamOrArg) {
         Token closer = typeParam.skip(token);
-        if (optional("(", closer.next)) {
+        if (optional("(", closer.next!)) {
           if (varFinalOrConst != null) {
             reportRecoverableError(
                 varFinalOrConst, codes.messageFunctionTypedParameterVar);
           }
           beforeInlineFunctionType = token;
-          token = closer.next.endGroup;
-          next = token.next;
+          token = closer.next!.endGroup!;
+          next = token.next!;
         }
       }
     } else if (optional("(", next)) {
@@ -1543,8 +1595,8 @@
             varFinalOrConst, codes.messageFunctionTypedParameterVar);
       }
       beforeInlineFunctionType = token;
-      token = next.endGroup;
-      next = token.next;
+      token = next.endGroup!;
+      next = token.next!;
     }
     if (typeInfo != noType &&
         varFinalOrConst != null &&
@@ -1552,17 +1604,18 @@
       reportRecoverableError(varFinalOrConst, codes.messageTypeAfterVar);
     }
 
-    Token endInlineFunctionType;
+    Token? endInlineFunctionType;
     if (beforeInlineFunctionType != null) {
       endInlineFunctionType =
           typeParam.parseVariables(beforeInlineFunctionType, this);
-      listener.beginFunctionTypedFormalParameter(beforeInlineFunctionType.next);
+      listener
+          .beginFunctionTypedFormalParameter(beforeInlineFunctionType.next!);
       token = typeInfo.parseType(beforeType, this);
       endInlineFunctionType = parseFormalParametersRequiredOpt(
           endInlineFunctionType, MemberKind.FunctionTypedParameter);
-      Token question;
-      if (optional('?', endInlineFunctionType.next)) {
-        question = endInlineFunctionType = endInlineFunctionType.next;
+      Token? question;
+      if (optional('?', endInlineFunctionType.next!)) {
+        question = endInlineFunctionType = endInlineFunctionType.next!;
       }
       listener.endFunctionTypedFormalParameter(
           beforeInlineFunctionType, question);
@@ -1571,7 +1624,7 @@
       // The following isn't allowed:
       //    int Function(int bar(String x)).
       if (inFunctionType) {
-        reportRecoverableError(beforeInlineFunctionType.next,
+        reportRecoverableError(beforeInlineFunctionType.next!,
             codes.messageInvalidInlineFunctionType);
       }
     } else if (inFunctionType) {
@@ -1584,12 +1637,12 @@
     if (periodAfterThis != null) {
       token = periodAfterThis;
     }
-    next = token.next;
+    next = token.next!;
     if (inFunctionType &&
         !isNamedParameter &&
         !next.isKeywordOrIdentifier &&
         beforeInlineFunctionType == null) {
-      nameToken = token.next;
+      nameToken = token.next!;
       listener.handleNoName(nameToken);
     } else {
       nameToken = token = ensureIdentifier(token, nameContext);
@@ -1600,16 +1653,16 @@
     if (endInlineFunctionType != null) {
       token = endInlineFunctionType;
     }
-    next = token.next;
+    next = token.next!;
 
-    String value = next.stringValue;
-    Token initializerStart, initializerEnd;
+    String? value = next.stringValue;
+    Token? initializerStart, initializerEnd;
     if ((identical('=', value)) || (identical(':', value))) {
       Token equal = next;
-      initializerStart = equal.next;
+      initializerStart = equal.next!;
       listener.beginFormalParameterDefaultValueExpression();
       token = initializerEnd = parseExpression(equal);
-      next = token.next;
+      next = token.next!;
       listener.endFormalParameterDefaultValueExpression();
       // TODO(danrubel): Consider removing the last parameter from the
       // handleValuedFormalParameter event... it appears to be unused.
@@ -1640,18 +1693,18 @@
   /// ;
   /// ```
   Token parseOptionalPositionalParameters(Token token, MemberKind kind) {
-    Token begin = token = token.next;
+    Token begin = token = token.next!;
     assert(optional('[', token));
     listener.beginOptionalFormalParameters(begin);
     int parameterCount = 0;
     while (true) {
-      Token next = token.next;
+      Token next = token.next!;
       if (optional(']', next)) {
         break;
       }
       token = parseFormalParameter(
           token, FormalParameterKind.optionalPositional, kind);
-      next = token.next;
+      next = token.next!;
       ++parameterCount;
       if (!optional(',', next)) {
         if (!optional(']', next)) {
@@ -1659,9 +1712,9 @@
           reportRecoverableError(
               next, codes.templateExpectedButGot.withArguments(']'));
           // Scanner guarantees a closing bracket.
-          next = begin.endGroup;
+          next = begin.endGroup!;
           while (token.next != next) {
-            token = token.next;
+            token = token.next!;
           }
         }
         break;
@@ -1673,12 +1726,12 @@
           token,
           codes.messageEmptyOptionalParameterList,
           new SyntheticStringToken(TokenType.IDENTIFIER, '',
-              token.next.charOffset, /* _length = */ 0));
+              token.next!.charOffset, /* _length = */ 0));
       token = parseFormalParameter(
           token, FormalParameterKind.optionalPositional, kind);
       ++parameterCount;
     }
-    token = token.next;
+    token = token.next!;
     assert(optional(']', token));
     listener.endOptionalFormalParameters(parameterCount, begin, token);
     return token;
@@ -1691,18 +1744,18 @@
   /// ;
   /// ```
   Token parseOptionalNamedParameters(Token token, MemberKind kind) {
-    Token begin = token = token.next;
+    Token begin = token = token.next!;
     assert(optional('{', token));
     listener.beginOptionalFormalParameters(begin);
     int parameterCount = 0;
     while (true) {
-      Token next = token.next;
+      Token next = token.next!;
       if (optional('}', next)) {
         break;
       }
       token =
           parseFormalParameter(token, FormalParameterKind.optionalNamed, kind);
-      next = token.next;
+      next = token.next!;
       ++parameterCount;
       if (!optional(',', next)) {
         if (!optional('}', next)) {
@@ -1710,9 +1763,9 @@
           reportRecoverableError(
               next, codes.templateExpectedButGot.withArguments('}'));
           // Scanner guarantees a closing bracket.
-          next = begin.endGroup;
+          next = begin.endGroup!;
           while (token.next != next) {
-            token = token.next;
+            token = token.next!;
           }
         }
         break;
@@ -1724,12 +1777,12 @@
           token,
           codes.messageEmptyNamedParameterList,
           new SyntheticStringToken(TokenType.IDENTIFIER, '',
-              token.next.charOffset, /* _length = */ 0));
+              token.next!.charOffset, /* _length = */ 0));
       token =
           parseFormalParameter(token, FormalParameterKind.optionalNamed, kind);
       ++parameterCount;
     }
-    token = token.next;
+    token = token.next!;
     assert(optional('}', token));
     listener.endOptionalFormalParameters(parameterCount, begin, token);
     return token;
@@ -1743,7 +1796,7 @@
   Token parseQualified(Token token, IdentifierContext context,
       IdentifierContext continuationContext) {
     token = ensureIdentifier(token, context);
-    while (optional('.', token.next)) {
+    while (optional('.', token.next!)) {
       token = parseQualifiedRest(token, continuationContext);
     }
     return token;
@@ -1756,7 +1809,7 @@
   /// ```
   Token parseQualifiedRestOpt(
       Token token, IdentifierContext continuationContext) {
-    if (optional('.', token.next)) {
+    if (optional('.', token.next!)) {
       return parseQualifiedRest(token, continuationContext);
     } else {
       return token;
@@ -1769,7 +1822,7 @@
   /// ;
   /// ```
   Token parseQualifiedRest(Token token, IdentifierContext context) {
-    token = token.next;
+    token = token.next!;
     assert(optional('.', token));
     Token period = token;
     token = ensureIdentifier(token, context);
@@ -1781,7 +1834,7 @@
     // The scanner ensures that `{` always has a closing `}`.
     return ensureBlock(
             token, /* template = */ null, /* missingBlockName = */ null)
-        .endGroup;
+        .endGroup!;
   }
 
   /// ```
@@ -1795,12 +1848,12 @@
     listener.beginEnum(enumKeyword);
     Token token =
         ensureIdentifier(enumKeyword, IdentifierContext.enumDeclaration);
-    Token leftBrace = token.next;
+    Token leftBrace = token.next!;
     int count = 0;
     if (optional('{', leftBrace)) {
       token = leftBrace;
       while (true) {
-        Token next = token.next;
+        Token next = token.next!;
         if (optional('}', next)) {
           token = next;
           if (count == 0) {
@@ -1810,7 +1863,7 @@
         }
         token = parseMetadataStar(token);
         token = ensureIdentifier(token, IdentifierContext.enumValueDeclaration);
-        next = token.next;
+        next = token.next!;
         count++;
         if (optional(',', next)) {
           token = next;
@@ -1819,7 +1872,7 @@
           break;
         } else {
           // Recovery
-          Token endGroup = leftBrace.endGroup;
+          Token endGroup = leftBrace.endGroup!;
           if (endGroup.isSynthetic) {
             // The scanner did not place the synthetic '}' correctly.
             token = rewriter.moveSynthetic(token, endGroup);
@@ -1835,7 +1888,7 @@
             // Otherwise assume a missing `}` and exit the loop
             reportRecoverableError(
                 next, codes.templateExpectedButGot.withArguments('}'));
-            token = leftBrace.endGroup;
+            token = leftBrace.endGroup!;
             break;
           }
         }
@@ -1844,7 +1897,7 @@
       // TODO(danrubel): merge this error message with missing class/mixin body
       leftBrace = ensureBlock(
           token, codes.templateExpectedEnumBody, /* missingBlockName = */ null);
-      token = leftBrace.endGroup;
+      token = leftBrace.endGroup!;
     }
     assert(optional('}', token));
     listener.endEnum(enumKeyword, leftBrace, count);
@@ -1852,7 +1905,7 @@
   }
 
   Token parseClassOrNamedMixinApplication(
-      Token abstractToken, Token classKeyword) {
+      Token? abstractToken, Token classKeyword) {
     assert(optional('class', classKeyword));
     Token begin = abstractToken ?? classKeyword;
     listener.beginClassOrNamedMixinApplicationPrelude(begin);
@@ -1861,7 +1914,7 @@
     Token token = computeTypeParamOrArg(
             name, /* inDeclaration = */ true, /* allowsVariance = */ true)
         .parseVariables(name, this);
-    if (optional('=', token.next)) {
+    if (optional('=', token.next!)) {
       listener.beginNamedMixinApplication(begin, abstractToken, name);
       return parseNamedMixinApplication(token, begin, classKeyword);
     } else {
@@ -1872,14 +1925,14 @@
 
   Token parseNamedMixinApplication(
       Token token, Token begin, Token classKeyword) {
-    Token equals = token = token.next;
+    Token equals = token = token.next!;
     assert(optional('=', equals));
     token = computeType(token, /* required = */ true)
         .ensureTypeNotVoid(token, this);
     token = parseMixinApplicationRest(token);
-    Token implementsKeyword = null;
-    if (optional('implements', token.next)) {
-      implementsKeyword = token.next;
+    Token? implementsKeyword = null;
+    if (optional('implements', token.next!)) {
+      implementsKeyword = token.next!;
       token = parseTypeList(implementsKeyword);
     }
     token = ensureSemicolon(token);
@@ -1903,7 +1956,7 @@
       Token token, Token begin, Token classKeyword, String className) {
     Token start = token;
     token = parseClassHeaderOpt(token, begin, classKeyword);
-    if (!optional('{', token.next)) {
+    if (!optional('{', token.next!)) {
       // Recovery
       token = parseClassHeaderRecovery(start, begin, classKeyword);
       ensureBlock(token, /* template = */ null, 'class declaration');
@@ -1918,9 +1971,9 @@
     token = parseClassExtendsOpt(token);
     token = parseWithClauseOpt(token);
     token = parseClassOrMixinImplementsOpt(token);
-    Token nativeToken;
-    if (optional('native', token.next)) {
-      nativeToken = token.next;
+    Token? nativeToken;
+    if (optional('native', token.next!)) {
+      nativeToken = token.next!;
       token = parseNativeClause(token);
     }
     listener.handleClassHeader(begin, classKeyword, nativeToken);
@@ -1958,11 +2011,11 @@
       // and generate the same events as in the parseClassHeader method above.
       recoveryListener.clear();
 
-      if (token.next.isKeywordOrIdentifier &&
-          const ['extend', 'on'].contains(token.next.lexeme)) {
-        reportRecoverableError(
-            token.next, codes.templateExpectedInstead.withArguments('extends'));
-        token = parseClassExtendsSeenExtendsClause(token.next, token);
+      if (token.next!.isKeywordOrIdentifier &&
+          const ['extend', 'on'].contains(token.next!.lexeme)) {
+        reportRecoverableError(token.next!,
+            codes.templateExpectedInstead.withArguments('extends'));
+        token = parseClassExtendsSeenExtendsClause(token.next!, token);
       } else {
         token = parseClassExtendsOpt(token);
       }
@@ -1970,13 +2023,13 @@
       if (recoveryListener.extendsKeyword != null) {
         if (hasExtends) {
           reportRecoverableError(
-              recoveryListener.extendsKeyword, codes.messageMultipleExtends);
+              recoveryListener.extendsKeyword!, codes.messageMultipleExtends);
         } else {
           if (hasWith) {
-            reportRecoverableError(recoveryListener.extendsKeyword,
+            reportRecoverableError(recoveryListener.extendsKeyword!,
                 codes.messageWithBeforeExtends);
           } else if (hasImplements) {
-            reportRecoverableError(recoveryListener.extendsKeyword,
+            reportRecoverableError(recoveryListener.extendsKeyword!,
                 codes.messageImplementsBeforeExtends);
           }
           hasExtends = true;
@@ -1988,10 +2041,10 @@
       if (recoveryListener.withKeyword != null) {
         if (hasWith) {
           reportRecoverableError(
-              recoveryListener.withKeyword, codes.messageMultipleWith);
+              recoveryListener.withKeyword!, codes.messageMultipleWith);
         } else {
           if (hasImplements) {
-            reportRecoverableError(recoveryListener.withKeyword,
+            reportRecoverableError(recoveryListener.withKeyword!,
                 codes.messageImplementsBeforeWith);
           }
           hasWith = true;
@@ -2002,7 +2055,7 @@
 
       if (recoveryListener.implementsKeyword != null) {
         if (hasImplements) {
-          reportRecoverableError(recoveryListener.implementsKeyword,
+          reportRecoverableError(recoveryListener.implementsKeyword!,
               codes.messageMultipleImplements);
         } else {
           hasImplements = true;
@@ -2012,7 +2065,7 @@
       listener.handleRecoverClassHeader();
 
       // Exit if a class body is detected, or if no progress has been made
-    } while (!optional('{', token.next) && start != token);
+    } while (!optional('{', token.next!) && start != token);
 
     listener = primaryListener;
     return token;
@@ -2020,7 +2073,7 @@
 
   Token parseClassExtendsOpt(Token token) {
     // extends <typeNotVoid>
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('extends', next)) {
       token = parseClassExtendsSeenExtendsClause(next, token);
     } else {
@@ -2039,11 +2092,11 @@
     int count = 1;
 
     // Error recovery: extends <typeNotVoid>, <typeNotVoid> [...]
-    if (optional(',', token.next)) {
-      reportRecoverableError(token.next, codes.messageMultipleExtends);
+    if (optional(',', token.next!)) {
+      reportRecoverableError(token.next!, codes.messageMultipleExtends);
 
-      while (optional(',', token.next)) {
-        next = token.next;
+      while (optional(',', token.next!)) {
+        next = token.next!;
         token = computeType(next, /* required = */ true)
             .ensureTypeNotVoid(next, this);
         count++;
@@ -2060,15 +2113,15 @@
   /// ;
   /// ```
   Token parseClassOrMixinImplementsOpt(Token token) {
-    Token implementsKeyword;
+    Token? implementsKeyword;
     int interfacesCount = 0;
-    if (optional('implements', token.next)) {
-      implementsKeyword = token.next;
+    if (optional('implements', token.next!)) {
+      implementsKeyword = token.next!;
       do {
-        token = computeType(token.next, /* required = */ true)
-            .ensureTypeNotVoid(token.next, this);
+        token = computeType(token.next!, /* required = */ true)
+            .ensureTypeNotVoid(token.next!, this);
         ++interfacesCount;
-      } while (optional(',', token.next));
+      } while (optional(',', token.next!));
     }
     listener.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
     return token;
@@ -2092,7 +2145,7 @@
         .parseVariables(name, this);
     listener.beginMixinDeclaration(mixinKeyword, name);
     Token token = parseMixinHeaderOpt(headerStart, mixinKeyword);
-    if (!optional('{', token.next)) {
+    if (!optional('{', token.next!)) {
       // Recovery
       token = parseMixinHeaderRecovery(token, mixinKeyword, headerStart);
       ensureBlock(token, /* template = */ null, 'mixin declaration');
@@ -2140,10 +2193,10 @@
       // generate the same events as in the parseMixinHeaderOpt method above.
       recoveryListener.clear();
 
-      if (token.next.isKeywordOrIdentifier &&
-          const ['extend', 'extends'].contains(token.next.lexeme)) {
+      if (token.next!.isKeywordOrIdentifier &&
+          const ['extend', 'extends'].contains(token.next!.lexeme)) {
         reportRecoverableError(
-            token.next, codes.templateExpectedInstead.withArguments('on'));
+            token.next!, codes.templateExpectedInstead.withArguments('on'));
         token = parseMixinOn(token);
       } else {
         token = parseMixinOnOpt(token);
@@ -2152,11 +2205,11 @@
       if (recoveryListener.onKeyword != null) {
         if (hasOn) {
           reportRecoverableError(
-              recoveryListener.onKeyword, codes.messageMultipleOnClauses);
+              recoveryListener.onKeyword!, codes.messageMultipleOnClauses);
         } else {
           if (hasImplements) {
             reportRecoverableError(
-                recoveryListener.onKeyword, codes.messageImplementsBeforeOn);
+                recoveryListener.onKeyword!, codes.messageImplementsBeforeOn);
           }
           hasOn = true;
         }
@@ -2166,7 +2219,7 @@
 
       if (recoveryListener.implementsKeyword != null) {
         if (hasImplements) {
-          reportRecoverableError(recoveryListener.implementsKeyword,
+          reportRecoverableError(recoveryListener.implementsKeyword!,
               codes.messageMultipleImplements);
         } else {
           hasImplements = true;
@@ -2176,7 +2229,7 @@
       listener.handleRecoverMixinHeader();
 
       // Exit if a mixin body is detected, or if no progress has been made
-    } while (!optional('{', token.next) && start != token);
+    } while (!optional('{', token.next!) && start != token);
 
     listener = primaryListener;
     return token;
@@ -2188,7 +2241,7 @@
   /// ;
   /// ```
   Token parseMixinOnOpt(Token token) {
-    if (!optional('on', token.next)) {
+    if (!optional('on', token.next!)) {
       listener.handleMixinOn(/* onKeyword = */ null, /* typeCount = */ 0);
       return token;
     }
@@ -2196,17 +2249,17 @@
   }
 
   Token parseMixinOn(Token token) {
-    Token onKeyword = token.next;
+    Token onKeyword = token.next!;
     // During recovery, the [onKeyword] can be "extend" or "extends"
     assert(optional('on', onKeyword) ||
         optional('extends', onKeyword) ||
         onKeyword.lexeme == 'extend');
     int typeCount = 0;
     do {
-      token = computeType(token.next, /* required = */ true)
-          .ensureTypeNotVoid(token.next, this);
+      token = computeType(token.next!, /* required = */ true)
+          .ensureTypeNotVoid(token.next!, this);
       ++typeCount;
-    } while (optional(',', token.next));
+    } while (optional(',', token.next!));
     listener.handleMixinOn(onKeyword, typeCount);
     return token;
   }
@@ -2221,7 +2274,7 @@
     assert(optional('extension', extensionKeyword));
     Token token = extensionKeyword;
     listener.beginExtensionDeclarationPrelude(extensionKeyword);
-    Token name = token.next;
+    Token? name = token.next!;
     if (name.isIdentifier && !optional('on', name)) {
       token = name;
       if (name.type.isBuiltIn) {
@@ -2234,7 +2287,7 @@
     token = computeTypeParamOrArg(token, /* inDeclaration = */ true)
         .parseVariables(token, this);
     listener.beginExtensionDeclaration(extensionKeyword, name);
-    Token onKeyword = token.next;
+    Token onKeyword = token.next!;
     if (!optional('on', onKeyword)) {
       // Recovery
       if (optional('extends', onKeyword) ||
@@ -2250,9 +2303,9 @@
     }
     TypeInfo typeInfo = computeType(onKeyword, /* required = */ true);
     token = typeInfo.ensureTypeOrVoid(onKeyword, this);
-    if (!optional('{', token.next)) {
+    if (!optional('{', token.next!)) {
       // Recovery
-      Token next = token.next;
+      Token next = token.next!;
       while (!next.isEof) {
         if (optional(',', next) ||
             optional('extends', next) ||
@@ -2263,10 +2316,10 @@
           // optionally followed by an identifier
           reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
           token = next;
-          next = token.next;
+          next = token.next!;
           if (next.isIdentifier) {
             token = next;
-            next = token.next;
+            next = token.next!;
           }
         } else {
           break;
@@ -2281,7 +2334,7 @@
   }
 
   Token parseStringPart(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (next.kind != STRING_TOKEN) {
       reportRecoverableErrorWithToken(next, codes.templateExpectedString);
       next = rewriter.insertToken(token,
@@ -2295,8 +2348,8 @@
   /// message based on the given [context]. Return the synthetic identifier that
   /// was inserted.
   Token insertSyntheticIdentifier(Token token, IdentifierContext context,
-      {codes.Message message, Token messageOnToken}) {
-    Token next = token.next;
+      {codes.Message? message, Token? messageOnToken}) {
+    Token next = token.next!;
     reportRecoverableError(messageOnToken ?? next,
         message ?? context.recoveryTemplate.withArguments(next));
     return rewriter.insertSyntheticIdentifier(token);
@@ -2309,10 +2362,12 @@
   /// identifier in the given [context], create a synthetic identifier, report
   /// an error, and return the synthetic identifier.
   Token ensureIdentifier(Token token, IdentifierContext context) {
+    // ignore: unnecessary_null_comparison
     assert(context != null);
-    Token identifier = token.next;
+    Token identifier = token.next!;
     if (identifier.kind != IDENTIFIER_TOKEN) {
       identifier = context.ensureIdentifier(token, this);
+      // ignore: unnecessary_null_comparison
       assert(identifier != null);
       assert(identifier.isKeywordOrIdentifier);
     }
@@ -2330,11 +2385,13 @@
   /// to use the token as an identifier, even if it isn't a valid identifier.
   Token ensureIdentifierPotentiallyRecovered(
       Token token, IdentifierContext context, bool isRecovered) {
+    // ignore: unnecessary_null_comparison
     assert(context != null);
-    Token identifier = token.next;
+    Token identifier = token.next!;
     if (identifier.kind != IDENTIFIER_TOKEN) {
       identifier = context.ensureIdentifierPotentiallyRecovered(
           token, this, isRecovered);
+      // ignore: unnecessary_null_comparison
       assert(identifier != null);
       assert(identifier.isKeywordOrIdentifier);
     }
@@ -2360,39 +2417,85 @@
   /// last consumed token.
   Token parseTopLevelMember(Token token) {
     token = parseMetadataStar(syntheticPreviousToken(token));
-    return parseTopLevelMemberImpl(token).next;
+    return parseTopLevelMemberImpl(token).next!;
+  }
+
+  /// Check if [token] is the usage of 'late' before a field declaration in a
+  /// context where it's not legal (i.e. in non-nnbd-mode).
+  bool _isUseOfLateInNonNNBD(Token token) {
+    if (token is StringToken && token.value() == "late") {
+      // Possible recovery: Figure out if we're in a situation like
+      // late final? <type>/var/const name [...]
+      // (in non-nnbd-mode) where the late modifier is not legal and thus would
+      // normally be parsed as the type.
+      Token next = token.next!;
+      // Skip modifiers.
+      while (next.isModifier) {
+        token = next;
+        next = next.next!;
+      }
+      // Parse the (potential) new type.
+      TypeInfo typeInfoAlternative = computeType(
+          token,
+          /* required = */ false,
+          /* inDeclaration = */ true);
+      token = typeInfoAlternative.skipType(token);
+      next = token.next!;
+
+      // We've essentially ignored the 'late' at this point.
+      // `token` is (in the good state) the last token of the type,
+      // `next` is (in the good state) the name;
+      // Are we in a 'good' state?
+      if (typeInfoAlternative != noType &&
+          next.isIdentifier &&
+          indicatesMethodOrField(next.next!)) {
+        return true;
+      }
+    }
+    return false;
   }
 
   Token parseTopLevelMemberImpl(Token token) {
     Token beforeStart = token;
-    Token next = token.next;
+    Token next = token.next!;
     listener.beginTopLevelMember(next);
 
-    Token externalToken;
-    Token lateToken;
-    Token varFinalOrConst;
+    Token? skippedNonLateLate;
+
+    if (_isUseOfLateInNonNNBD(next)) {
+      skippedNonLateLate = next;
+      reportRecoverableErrorWithToken(
+          skippedNonLateLate, codes.templateUnexpectedModifierInNonNnbd);
+      token = token.next!;
+      beforeStart = token;
+      next = token.next!;
+    }
+
+    Token? externalToken;
+    Token? lateToken;
+    Token? varFinalOrConst;
 
     if (isModifier(next)) {
       if (optional('external', next)) {
         externalToken = token = next;
-        next = token.next;
+        next = token.next!;
       }
       if (isModifier(next)) {
         if (optional('final', next)) {
           varFinalOrConst = token = next;
-          next = token.next;
+          next = token.next!;
         } else if (optional('var', next)) {
           varFinalOrConst = token = next;
-          next = token.next;
+          next = token.next!;
         } else if (optional('const', next)) {
           varFinalOrConst = token = next;
-          next = token.next;
+          next = token.next!;
         } else if (optional('late', next)) {
           lateToken = token = next;
-          next = token.next;
+          next = token.next!;
           if (isModifier(next) && optional('final', next)) {
             varFinalOrConst = token = next;
-            next = token.next;
+            next = token.next!;
           }
         }
         if (isModifier(next)) {
@@ -2410,30 +2513,34 @@
               ..varFinalOrConst = varFinalOrConst;
 
             token = context.parseTopLevelModifiers(token);
-            next = token.next;
+            next = token.next!;
 
             externalToken = context.externalToken;
             lateToken = context.lateToken;
             varFinalOrConst = context.varFinalOrConst;
-
-            context = null;
           }
         }
       }
     }
+    if (lateToken == null) {
+      // `late` was used as a modifier in non-nnbd mode. An error has been
+      // emitted. Still use it as a late token for the remainder in an attempt
+      // to avoid cascading errors (and for passing to the listener).
+      lateToken = skippedNonLateLate;
+    }
 
     Token beforeType = token;
     TypeInfo typeInfo =
         computeType(token, /* required = */ false, /* inDeclaration = */ true);
     token = typeInfo.skipType(token);
-    next = token.next;
+    next = token.next!;
 
-    Token getOrSet;
-    String value = next.stringValue;
+    Token? getOrSet;
+    String? value = next.stringValue;
     if (identical(value, 'get') || identical(value, 'set')) {
-      if (next.next.isIdentifier) {
+      if (next.next!.isIdentifier) {
         getOrSet = token = next;
-        next = token.next;
+        next = token.next!;
       }
     }
 
@@ -2444,15 +2551,15 @@
     // take the reserved keyword as the name.
     if (typeInfo == noType &&
         varFinalOrConst == null &&
-        isReservedKeyword(next.next) &&
-        indicatesMethodOrField(next.next.next)) {
+        isReservedKeyword(next.next!) &&
+        indicatesMethodOrField(next.next!.next!)) {
       // Recovery: Use the reserved keyword despite that not being legal.
       typeInfo = computeType(
           token,
           /*required = */ true,
           /* inDeclaration = */ true);
       token = typeInfo.skipType(token);
-      next = token.next;
+      next = token.next!;
       nameIsRecovered = true;
     }
 
@@ -2460,7 +2567,7 @@
       value = next.stringValue;
       if (identical(value, 'factory') || identical(value, 'operator')) {
         // `factory` and `operator` can be used as an identifier.
-        value = next.next.stringValue;
+        value = next.next!.stringValue;
         if (getOrSet == null &&
             !identical(value, '(') &&
             !identical(value, '{') &&
@@ -2476,10 +2583,10 @@
                 next, codes.messageFactoryTopLevelDeclaration);
           } else {
             reportRecoverableError(next, codes.messageTopLevelOperator);
-            if (next.next.isOperator) {
+            if (next.next!.isOperator) {
               token = next;
-              next = token.next;
-              if (optional('(', next.next)) {
+              next = token.next!;
+              if (optional('(', next.next!)) {
                 rewriter.insertSyntheticIdentifier(
                     next, '#synthetic_identifier_${next.charOffset}');
               }
@@ -2501,18 +2608,18 @@
           // Looks like a declaration missing an identifier.
           // Insert synthetic identifier and fall through.
           insertSyntheticIdentifier(token, IdentifierContext.methodDeclaration);
-          next = token.next;
+          next = token.next!;
         }
       }
     }
     // At this point, `token` is beforeName.
 
     // Recovery: Inserted ! after method name.
-    if (optional('!', next.next)) {
-      next = next.next;
+    if (optional('!', next.next!)) {
+      next = next.next!;
     }
 
-    next = next.next;
+    next = next.next!;
     value = next.stringValue;
     if (getOrSet != null ||
         identical(value, '(') ||
@@ -2532,7 +2639,7 @@
             lateToken, codes.templateExtraneousModifier);
       }
       return parseTopLevelMethod(beforeStart, externalToken, beforeType,
-          typeInfo, getOrSet, token.next, nameIsRecovered);
+          typeInfo, getOrSet, token.next!, nameIsRecovered);
     }
 
     if (getOrSet != null) {
@@ -2549,7 +2656,7 @@
         varFinalOrConst,
         beforeType,
         typeInfo,
-        token.next,
+        token.next!,
         DeclarationKind.TopLevel,
         /* enclosingDeclarationName = */ null,
         nameIsRecovered);
@@ -2557,17 +2664,17 @@
 
   Token parseFields(
       Token beforeStart,
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       Token beforeType,
       TypeInfo typeInfo,
       Token name,
       DeclarationKind kind,
-      String enclosingDeclarationName,
+      String? enclosingDeclarationName,
       bool nameIsRecovered) {
     listener.beginFields(beforeStart);
 
@@ -2595,7 +2702,7 @@
     }
 
     Token token = typeInfo.parseType(beforeType, this);
-    assert(token.next == name || token.next.isEof);
+    assert(token.next == name || token.next!.isEof);
 
     IdentifierContext context = kind == DeclarationKind.TopLevel
         ? IdentifierContext.topLevelVariableDeclaration
@@ -2606,7 +2713,7 @@
     // Check for covariant late final with initializer.
     if (covariantToken != null && lateToken != null) {
       if (varFinalOrConst != null && optional('final', varFinalOrConst)) {
-        Token next = name.next;
+        Token next = name.next!;
         if (optional('=', next)) {
           reportRecoverableError(covariantToken,
               codes.messageFinalAndCovariantLateWithInitializer);
@@ -2618,26 +2725,26 @@
     int fieldCount = 1;
     token = parseFieldInitializerOpt(name, name, lateToken, abstractToken,
         externalToken, varFinalOrConst, kind, enclosingDeclarationName);
-    while (optional(',', token.next)) {
-      name = ensureIdentifier(token.next, context);
+    while (optional(',', token.next!)) {
+      name = ensureIdentifier(token.next!, context);
       token = parseFieldInitializerOpt(name, name, lateToken, abstractToken,
           externalToken, varFinalOrConst, kind, enclosingDeclarationName);
       ++fieldCount;
     }
-    Token semicolon = token.next;
+    Token semicolon = token.next!;
     if (optional(';', semicolon)) {
       token = semicolon;
     } else {
       // Recovery
       if (kind == DeclarationKind.TopLevel &&
-          beforeType.next.isIdentifier &&
-          beforeType.next.lexeme == 'extension') {
+          beforeType.next!.isIdentifier &&
+          beforeType.next!.lexeme == 'extension') {
         // Looks like an extension method
         // TODO(danrubel): Remove when extension methods are enabled by default
         // because then 'extension' will be interpreted as a built-in
         // and this code will never be executed
         reportRecoverableError(
-            beforeType.next,
+            beforeType.next!,
             codes.templateExperimentNotEnabled
                 .withArguments('extension-methods', '2.6'));
         token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
@@ -2649,7 +2756,7 @@
       case DeclarationKind.TopLevel:
         assert(abstractToken == null);
         listener.endTopLevelFields(externalToken, staticToken, covariantToken,
-            lateToken, varFinalOrConst, fieldCount, beforeStart.next, token);
+            lateToken, varFinalOrConst, fieldCount, beforeStart.next!, token);
         break;
       case DeclarationKind.Class:
         listener.endClassFields(
@@ -2660,7 +2767,7 @@
             lateToken,
             varFinalOrConst,
             fieldCount,
-            beforeStart.next,
+            beforeStart.next!,
             token);
         break;
       case DeclarationKind.Mixin:
@@ -2672,7 +2779,7 @@
             lateToken,
             varFinalOrConst,
             fieldCount,
-            beforeStart.next,
+            beforeStart.next!,
             token);
         break;
       case DeclarationKind.Extension:
@@ -2692,7 +2799,7 @@
             lateToken,
             varFinalOrConst,
             fieldCount,
-            beforeStart.next,
+            beforeStart.next!,
             token);
         break;
     }
@@ -2701,16 +2808,16 @@
 
   Token parseTopLevelMethod(
       Token beforeStart,
-      Token externalToken,
+      Token? externalToken,
       Token beforeType,
       TypeInfo typeInfo,
-      Token getOrSet,
+      Token? getOrSet,
       Token name,
       bool nameIsRecovered) {
     listener.beginTopLevelMethod(beforeStart, externalToken);
 
     Token token = typeInfo.parseType(beforeType, this);
-    assert(token.next == (getOrSet ?? name) || token.next.isEof);
+    assert(token.next == (getOrSet ?? name) || token.next!.isEof);
     name = ensureIdentifierPotentiallyRecovered(
         getOrSet ?? token,
         IdentifierContext.topLevelFunctionDeclaration,
@@ -2722,43 +2829,58 @@
     } else {
       isGetter = optional("get", getOrSet);
       token = name;
-      listener.handleNoTypeVariables(token.next);
+      listener.handleNoTypeVariables(token.next!);
     }
     token = parseGetterOrFormalParameters(
         token, name, isGetter, MemberKind.TopLevelMethod);
     AsyncModifier savedAsyncModifier = asyncState;
-    Token asyncToken = token.next;
+    Token asyncToken = token.next!;
     token = parseAsyncModifierOpt(token);
     if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
       reportRecoverableError(asyncToken, codes.messageSetterNotSync);
     }
-    bool isExternal = externalToken != null;
-    if (isExternal && !optional(';', token.next)) {
-      reportRecoverableError(
-          externalToken, codes.messageExternalMethodWithBody);
+    // TODO(paulberry): code below is slightly hacky to allow for implementing
+    // the feature "Infer non-nullability from local boolean variables"
+    // (https://github.com/dart-lang/language/issues/1274).  Since the version
+    // of Dart that is used for presubmit checks lags slightly behind master,
+    // we need the code to analyze correctly regardless of whether local boolean
+    // variables cause promotion or not.  Once the version of dart used for
+    // presubmit checks has been updated, this can be cleaned up to:
+    //   bool isExternal = externalToken != null;
+    //   if (externalToken != null && !optional(';', token.next!)) {
+    //     reportRecoverableError(
+    //         externalToken, codes.messageExternalMethodWithBody);
+    //   }
+    bool isExternal = false;
+    if (externalToken != null) {
+      isExternal = true;
+      if (!optional(';', token.next!)) {
+        reportRecoverableError(
+            externalToken, codes.messageExternalMethodWithBody);
+      }
     }
     token = parseFunctionBody(
         token, /* ofFunctionExpression = */ false, isExternal);
     asyncState = savedAsyncModifier;
-    listener.endTopLevelMethod(beforeStart.next, getOrSet, token);
+    listener.endTopLevelMethod(beforeStart.next!, getOrSet, token);
     return token;
   }
 
   Token parseMethodTypeVar(Token name) {
-    if (optional('!', name.next)) {
+    if (optional('!', name.next!)) {
       // Recovery
-      name = name.next;
+      name = name.next!;
       reportRecoverableErrorWithToken(name, codes.templateUnexpectedToken);
     }
-    if (!optional('<', name.next)) {
+    if (!optional('<', name.next!)) {
       return noTypeParamOrArg.parseVariables(name, this);
     }
     TypeParamOrArgInfo typeVar =
         computeTypeParamOrArg(name, /* inDeclaration = */ true);
     Token token = typeVar.parseVariables(name, this);
-    if (optional('=', token.next)) {
+    if (optional('=', token.next!)) {
       // Recovery
-      token = token.next;
+      token = token.next!;
       reportRecoverableErrorWithToken(token, codes.templateUnexpectedToken);
     }
     return token;
@@ -2767,21 +2889,21 @@
   Token parseFieldInitializerOpt(
       Token token,
       Token name,
-      Token lateToken,
-      Token abstractToken,
-      Token externalToken,
-      Token varFinalOrConst,
+      Token? lateToken,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? varFinalOrConst,
       DeclarationKind kind,
-      String enclosingDeclarationName) {
+      String? enclosingDeclarationName) {
     if (name.lexeme == enclosingDeclarationName) {
       reportRecoverableError(name, codes.messageMemberWithSameNameAsClass);
     }
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('=', next)) {
       Token assignment = next;
       listener.beginFieldInitializer(next);
       token = parseExpression(next);
-      listener.endFieldInitializer(assignment, token.next);
+      listener.endFieldInitializer(assignment, token.next!);
     } else {
       if (varFinalOrConst != null && !name.isSynthetic) {
         if (optional("const", varFinalOrConst)) {
@@ -2800,14 +2922,14 @@
                   .withArguments(name.lexeme));
         }
       }
-      listener.handleNoFieldInitializer(token.next);
+      listener.handleNoFieldInitializer(token.next!);
     }
     return token;
   }
 
   Token parseVariableInitializerOpt(Token token) {
-    if (optional('=', token.next)) {
-      Token assignment = token.next;
+    if (optional('=', token.next!)) {
+      Token assignment = token.next!;
       listener.beginVariableInitializer(assignment);
       token = parseExpression(assignment);
       listener.endVariableInitializer(assignment);
@@ -2818,8 +2940,8 @@
   }
 
   Token parseInitializersOpt(Token token) {
-    if (optional(':', token.next)) {
-      return parseInitializers(token.next);
+    if (optional(':', token.next!)) {
+      return parseInitializers(token.next!);
     } else {
       listener.handleNoInitializers();
       return token;
@@ -2842,14 +2964,14 @@
     while (true) {
       token = parseInitializer(next);
       ++count;
-      next = token.next;
+      next = token.next!;
       if (!optional(',', next)) {
         // Recovery: Found an identifier which could be
         // 1) missing preceding `,` thus it's another initializer, or
         // 2) missing preceding `;` thus it's a class member, or
         // 3) missing preceding '{' thus it's a statement
         if (optional('assert', next)) {
-          next = next.next;
+          next = next.next!;
           if (!optional('(', next)) {
             break;
           }
@@ -2859,16 +2981,16 @@
           break;
         } else {
           if (optional('this', next)) {
-            next = next.next;
+            next = next.next!;
             if (!optional('.', next)) {
               break;
             }
-            next = next.next;
+            next = next.next!;
             if (!next.isIdentifier && !optional('assert', next)) {
               break;
             }
           }
-          next = next.next;
+          next = next.next!;
           if (!optional('=', next)) {
             break;
           }
@@ -2882,7 +3004,7 @@
       }
     }
     mayParseFunctionExpressions = old;
-    listener.endInitializers(count, begin, token.next);
+    listener.endInitializers(count, begin, token.next!);
     return token;
   }
 
@@ -2898,21 +3020,21 @@
   /// ;
   /// ```
   Token parseInitializer(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     listener.beginInitializer(next);
     Token beforeExpression = token;
     if (optional('assert', next)) {
       token = parseAssert(token, Assert.Initializer);
-      listener.endInitializer(token.next);
+      listener.endInitializer(token.next!);
       return token;
     } else if (optional('super', next)) {
       return parseSuperInitializerExpression(token);
     } else if (optional('this', next)) {
       token = next;
-      next = token.next;
+      next = token.next!;
       if (optional('.', next)) {
         token = next;
-        next = token.next;
+        next = token.next!;
         if (next.isIdentifier) {
           token = next;
         } else {
@@ -2920,14 +3042,14 @@
           token = insertSyntheticIdentifier(
               token, IdentifierContext.fieldInitializer);
         }
-        next = token.next;
+        next = token.next!;
         if (optional('=', next)) {
           return parseInitializerExpressionRest(beforeExpression);
         }
       }
       if (optional('(', next)) {
         token = parseInitializerExpressionRest(beforeExpression);
-        next = token.next;
+        next = token.next!;
         if (optional('{', next) || optional('=>', next)) {
           reportRecoverableError(
               next, codes.messageRedirectingConstructorWithBody);
@@ -2941,12 +3063,12 @@
         reportRecoverableError(
             next, codes.templateExpectedButGot.withArguments('.'));
         rewriter.insertSyntheticToken(token, TokenType.PERIOD);
-        token = rewriter.insertSyntheticIdentifier(token.next);
-        next = token.next;
+        token = rewriter.insertSyntheticIdentifier(token.next!);
+        next = token.next!;
       }
       // Fall through to recovery
     } else if (next.isIdentifier) {
-      Token next2 = next.next;
+      Token next2 = next.next!;
       if (optional('=', next2)) {
         return parseInitializerExpressionRest(token);
       }
@@ -2987,31 +3109,31 @@
   ///   'super' ('.' identifier)? arguments ;
   /// ```
   Token parseSuperInitializerExpression(final Token start) {
-    Token token = start.next;
+    Token token = start.next!;
     assert(optional('super', token));
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('.', next)) {
       token = next;
-      next = token.next;
+      next = token.next!;
       if (next.kind != IDENTIFIER_TOKEN) {
         next = IdentifierContext.expressionContinuation
             .ensureIdentifier(token, this);
       }
       token = next;
-      next = token.next;
+      next = token.next!;
     }
     if (!optional('(', next)) {
       // Recovery
       if (optional('?.', next)) {
         // An error for `super?.` is reported in parseSuperExpression.
         token = next;
-        next = token.next;
+        next = token.next!;
         if (!next.isIdentifier) {
           // Insert a synthetic identifier but don't report another error.
           next = rewriter.insertSyntheticIdentifier(token);
         }
         token = next;
-        next = token.next;
+        next = token.next!;
       }
       if (optional('=', next)) {
         if (optional('super', token)) {
@@ -3031,7 +3153,7 @@
 
   Token parseInitializerExpressionRest(Token token) {
     token = parseExpression(token);
-    listener.endInitializer(token.next);
+    listener.endInitializer(token.next!);
     return token;
   }
 
@@ -3042,9 +3164,9 @@
   /// a default error message instead.
   Token ensureBlock(
       Token token,
-      codes.Template<codes.Message Function(Token token)> template,
-      String missingBlockName) {
-    Token next = token.next;
+      codes.Template<codes.Message Function(Token token)>? template,
+      String? missingBlockName) {
+    Token next = token.next!;
     if (optional('{', next)) return next;
     if (template == null) {
       if (missingBlockName == null) {
@@ -3066,9 +3188,10 @@
   }
 
   Token insertBlock(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     BeginToken beginGroup = rewriter.insertToken(token,
-        new SyntheticBeginToken(TokenType.OPEN_CURLY_BRACKET, next.offset));
+            new SyntheticBeginToken(TokenType.OPEN_CURLY_BRACKET, next.offset))
+        as BeginToken;
     Token endGroup = rewriter.insertToken(beginGroup,
         new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, next.offset));
     beginGroup.endGroup = endGroup;
@@ -3079,14 +3202,14 @@
   /// Otherwise, report an error and return the closing parenthesis
   /// associated with the specified open parenthesis.
   Token ensureCloseParen(Token token, Token openParen) {
-    Token next = token.next;
+    Token next = token.next!;
     if (optional(')', next)) {
       return next;
     }
-    if (openParen.endGroup.isSynthetic) {
+    if (openParen.endGroup!.isSynthetic) {
       // Scanner has already reported a missing `)` error,
       // but placed the `)` in the wrong location, so move it.
-      return rewriter.moveSynthetic(token, openParen.endGroup);
+      return rewriter.moveSynthetic(token, openParen.endGroup!);
     }
 
     // TODO(danrubel): Pass in context for better error message.
@@ -3096,13 +3219,13 @@
     // Scanner guarantees a closing parenthesis
     // TODO(danrubel): Improve recovery by having callers parse tokens
     // between `token` and `openParen.endGroup`.
-    return openParen.endGroup;
+    return openParen.endGroup!;
   }
 
   /// If the next token is a colon, return it. Otherwise, report an
   /// error, insert a synthetic colon, and return the inserted colon.
   Token ensureColon(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (optional(':', next)) return next;
     codes.Message message = codes.templateExpectedButGot.withArguments(':');
     Token newToken = new SyntheticToken(TokenType.COLON, next.charOffset);
@@ -3113,7 +3236,7 @@
   /// then insert a synthetic literal string.
   /// Call `parseLiteralString` and return the result.
   Token ensureLiteralString(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (!identical(next.kind, STRING_TOKEN)) {
       codes.Message message = codes.templateExpectedString.withArguments(next);
       Token newToken = new SyntheticStringToken(
@@ -3130,7 +3253,7 @@
     // TODO(danrubel): Once all expect(';'...) call sites have been converted
     // to use this method, remove similar semicolon recovery code
     // from the handleError method in element_listener.dart.
-    Token next = token.next;
+    Token next = token.next!;
     if (optional(';', next)) return next;
 
     // Find a token on the same line as where the ';' should be inserted.
@@ -3144,14 +3267,14 @@
   /// Report an error at the token after [token] that has the given [message].
   /// Insert the [newToken] after [token] and return [newToken].
   Token rewriteAndRecover(Token token, codes.Message message, Token newToken) {
-    reportRecoverableError(token.next, message);
+    reportRecoverableError(token.next!, message);
     return rewriter.insertToken(token, newToken);
   }
 
   /// Replace the token after [token] with `[` followed by `]`
   /// and return [token].
   Token rewriteSquareBrackets(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('[]', next));
     Token replacement;
     if (next.isSynthetic) {
@@ -3172,9 +3295,9 @@
   /// Report the given token as unexpected and return the next token if the next
   /// token is one of the [expectedNext], otherwise just return the given token.
   Token skipUnexpectedTokenOpt(Token token, List<String> expectedNext) {
-    Token next = token.next;
+    Token next = token.next!;
     if (next.keyword == null) {
-      final String nextValue = next.next.stringValue;
+      final String? nextValue = next.next!.stringValue;
       for (String expectedValue in expectedNext) {
         if (identical(nextValue, expectedValue)) {
           reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
@@ -3186,10 +3309,10 @@
   }
 
   Token parseNativeClause(Token token) {
-    Token nativeToken = token = token.next;
+    Token nativeToken = token = token.next!;
     assert(optional('native', nativeToken));
     bool hasName = false;
-    if (token.next.kind == STRING_TOKEN) {
+    if (token.next!.kind == STRING_TOKEN) {
       hasName = true;
       token = parseLiteralString(token);
     }
@@ -3211,17 +3334,17 @@
   /// ;
   /// ```
   Token parseClassOrMixinOrExtensionBody(
-      Token token, DeclarationKind kind, String enclosingDeclarationName) {
-    Token begin = token = token.next;
+      Token token, DeclarationKind kind, String? enclosingDeclarationName) {
+    Token begin = token = token.next!;
     assert(optional('{', token));
     listener.beginClassOrMixinBody(kind, token);
     int count = 0;
-    while (notEofOrValue('}', token.next)) {
+    while (notEofOrValue('}', token.next!)) {
       token = parseClassOrMixinOrExtensionMemberImpl(
           token, kind, enclosingDeclarationName);
       ++count;
     }
-    token = token.next;
+    token = token.next!;
     assert(token.isEof || optional('}', token));
     listener.endClassOrMixinBody(kind, count, begin, token);
     return token;
@@ -3230,7 +3353,7 @@
   bool isUnaryMinus(Token token) =>
       token.kind == IDENTIFIER_TOKEN &&
       token.lexeme == 'unary' &&
-      optional('-', token.next);
+      optional('-', token.next!);
 
   /// Parse a class member.
   ///
@@ -3241,7 +3364,7 @@
   Token parseClassMember(Token token, String className) {
     return parseClassOrMixinOrExtensionMemberImpl(
             syntheticPreviousToken(token), DeclarationKind.Class, className)
-        .next;
+        .next!;
   }
 
   /// Parse a mixin member.
@@ -3253,7 +3376,7 @@
   Token parseMixinMember(Token token, String mixinName) {
     return parseClassOrMixinOrExtensionMemberImpl(
             syntheticPreviousToken(token), DeclarationKind.Mixin, mixinName)
-        .next;
+        .next!;
   }
 
   /// Parse an extension member.
@@ -3265,7 +3388,7 @@
   Token parseExtensionMember(Token token, String extensionName) {
     return parseClassOrMixinOrExtensionMemberImpl(syntheticPreviousToken(token),
             DeclarationKind.Extension, extensionName)
-        .next;
+        .next!;
   }
 
   bool isReservedKeyword(Token token) {
@@ -3274,7 +3397,7 @@
   }
 
   bool indicatesMethodOrField(Token token) {
-    String value = token.stringValue;
+    String? value = token.stringValue;
     if (identical(value, ';') ||
         identical(value, '=') ||
         identical(value, '(') ||
@@ -3304,49 +3427,59 @@
   /// ;
   /// ```
   Token parseClassOrMixinOrExtensionMemberImpl(
-      Token token, DeclarationKind kind, String enclosingDeclarationName) {
+      Token token, DeclarationKind kind, String? enclosingDeclarationName) {
     Token beforeStart = token = parseMetadataStar(token);
 
-    Token covariantToken;
-    Token abstractToken;
-    Token externalToken;
-    Token lateToken;
-    Token staticToken;
-    Token varFinalOrConst;
+    Token? skippedNonLateLate;
 
-    Token next = token.next;
+    if (_isUseOfLateInNonNNBD(token.next!)) {
+      skippedNonLateLate = token.next!;
+      reportRecoverableErrorWithToken(
+          skippedNonLateLate, codes.templateUnexpectedModifierInNonNnbd);
+      token = token.next!;
+      beforeStart = token;
+    }
+
+    Token? covariantToken;
+    Token? abstractToken;
+    Token? externalToken;
+    Token? lateToken;
+    Token? staticToken;
+    Token? varFinalOrConst;
+
+    Token next = token.next!;
     if (isModifier(next)) {
       if (optional('external', next)) {
         externalToken = token = next;
-        next = token.next;
+        next = token.next!;
       } else if (optional('abstract', next)) {
         abstractToken = token = next;
-        next = token.next;
+        next = token.next!;
       }
       if (isModifier(next)) {
         if (optional('static', next)) {
           staticToken = token = next;
-          next = token.next;
+          next = token.next!;
         } else if (optional('covariant', next)) {
           covariantToken = token = next;
-          next = token.next;
+          next = token.next!;
         }
         if (isModifier(next)) {
           if (optional('final', next)) {
             varFinalOrConst = token = next;
-            next = token.next;
+            next = token.next!;
           } else if (optional('var', next)) {
             varFinalOrConst = token = next;
-            next = token.next;
+            next = token.next!;
           } else if (optional('const', next) && covariantToken == null) {
             varFinalOrConst = token = next;
-            next = token.next;
+            next = token.next!;
           } else if (optional('late', next)) {
             lateToken = token = next;
-            next = token.next;
+            next = token.next!;
             if (isModifier(next) && optional('final', next)) {
               varFinalOrConst = token = next;
-              next = token.next;
+              next = token.next!;
             }
           }
           if (isModifier(next)) {
@@ -3359,7 +3492,7 @@
               ..abstractToken = abstractToken;
 
             token = context.parseClassMemberModifiers(token);
-            next = token.next;
+            next = token.next!;
 
             covariantToken = context.covariantToken;
             externalToken = context.externalToken;
@@ -3367,13 +3500,18 @@
             staticToken = context.staticToken;
             varFinalOrConst = context.varFinalOrConst;
             abstractToken = context.abstractToken;
-
-            context = null;
           }
         }
       }
     }
 
+    if (lateToken == null) {
+      // `late` was used as a modifier in non-nnbd mode. An error has been
+      // emitted. Still use it as a late token for the remainder in an attempt
+      // to avoid cascading errors (and for passing to the listener).
+      lateToken = skippedNonLateLate;
+    }
+
     listener.beginMember();
 
     Token beforeType = token;
@@ -3382,26 +3520,26 @@
         /*required = */ false,
         /* inDeclaration = */ true);
     token = typeInfo.skipType(token);
-    next = token.next;
+    next = token.next!;
 
-    Token getOrSet;
+    Token? getOrSet;
     bool nameIsRecovered = false;
     if (next.type != TokenType.IDENTIFIER) {
-      String value = next.stringValue;
+      String? value = next.stringValue;
       if (identical(value, 'get') || identical(value, 'set')) {
-        if (next.next.isIdentifier) {
+        if (next.next!.isIdentifier) {
           getOrSet = token = next;
-          next = token.next;
-        } else if (isReservedKeyword(next.next) &&
-            indicatesMethodOrField(next.next.next)) {
+          next = token.next!;
+        } else if (isReservedKeyword(next.next!) &&
+            indicatesMethodOrField(next.next!.next!)) {
           // Recovery: Getter or setter followed by a reserved word (name).
           getOrSet = token = next;
-          next = token.next;
+          next = token.next!;
           nameIsRecovered = true;
         }
         // Fall through to continue parsing `get` or `set` as an identifier.
       } else if (identical(value, 'factory')) {
-        Token next2 = next.next;
+        Token next2 = next.next!;
         if (next2.isIdentifier || next2.isModifier) {
           if (beforeType != token) {
             reportRecoverableError(token, codes.messageTypeBeforeFactory);
@@ -3417,7 +3555,7 @@
         }
         // Fall through to continue parsing `factory` as an identifier.
       } else if (identical(value, 'operator')) {
-        Token next2 = next.next;
+        Token next2 = next.next!;
         TypeParamOrArgInfo typeParam = computeTypeParamOrArg(next);
         // `operator` can be used as an identifier as in
         // `int operator<T>()` or `int operator = 2`
@@ -3433,7 +3571,7 @@
               beforeType,
               typeInfo,
               getOrSet,
-              token.next,
+              token.next!,
               kind,
               enclosingDeclarationName,
               nameIsRecovered);
@@ -3469,7 +3607,7 @@
               beforeType,
               typeInfo,
               getOrSet,
-              token.next,
+              token.next!,
               kind,
               enclosingDeclarationName,
               nameIsRecovered);
@@ -3480,7 +3618,7 @@
       } else if (!next.isIdentifier ||
           (identical(value, 'typedef') &&
               token == beforeStart &&
-              next.next.isIdentifier)) {
+              next.next!.isIdentifier)) {
         if (abstractToken != null) {
           reportRecoverableError(
               abstractToken, codes.messageAbstractClassMember);
@@ -3502,9 +3640,9 @@
             enclosingDeclarationName);
       }
     } else if (typeInfo == noType && varFinalOrConst == null) {
-      Token next2 = next.next;
+      Token next2 = next.next!;
       if (next2.isUserDefinableOperator && next2.endGroup == null) {
-        String value = next2.next.stringValue;
+        String? value = next2.next!.stringValue;
         if (identical(value, '(') ||
             identical(value, '{') ||
             identical(value, '=>')) {
@@ -3522,21 +3660,21 @@
               enclosingDeclarationName);
         }
       } else if (isReservedKeyword(next2) &&
-          indicatesMethodOrField(next2.next)) {
+          indicatesMethodOrField(next2.next!)) {
         // Recovery: Use the reserved keyword despite that not being legal.
         typeInfo = computeType(
             token,
             /*required = */ true,
             /* inDeclaration = */ true);
         token = typeInfo.skipType(token);
-        next = token.next;
+        next = token.next!;
         nameIsRecovered = true;
       }
     }
 
     // At this point, token is before the name, and next is the name
-    next = next.next;
-    String value = next.stringValue;
+    next = next.next!;
+    String? value = next.stringValue;
     if (getOrSet != null ||
         identical(value, '(') ||
         identical(value, '{') ||
@@ -3554,7 +3692,7 @@
           beforeType,
           typeInfo,
           getOrSet,
-          token.next,
+          token.next!,
           kind,
           enclosingDeclarationName,
           nameIsRecovered);
@@ -3573,7 +3711,7 @@
           varFinalOrConst,
           beforeType,
           typeInfo,
-          token.next,
+          token.next!,
           kind,
           enclosingDeclarationName,
           nameIsRecovered);
@@ -3584,18 +3722,18 @@
 
   Token parseMethod(
       Token beforeStart,
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       Token beforeType,
       TypeInfo typeInfo,
-      Token getOrSet,
+      Token? getOrSet,
       Token name,
       DeclarationKind kind,
-      String enclosingDeclarationName,
+      String? enclosingDeclarationName,
       bool nameIsRecovered) {
     if (abstractToken != null) {
       reportRecoverableError(abstractToken, codes.messageAbstractClassMember);
@@ -3606,7 +3744,7 @@
     }
     bool isOperator = false;
     if (getOrSet == null && optional('operator', name)) {
-      Token operator = name.next;
+      Token operator = name.next!;
       if (operator.isOperator ||
           identical(operator.kind, EQ_EQ_EQ_TOKEN) ||
           identical(operator.kind, BANG_EQ_EQ_TOKEN) ||
@@ -3678,13 +3816,13 @@
       token = parseMethodTypeVar(token);
     } else {
       isConsideredGetter = optional("get", getOrSet);
-      listener.handleNoTypeVariables(token.next);
+      listener.handleNoTypeVariables(token.next!);
 
       // If it becomes considered a constructor below, don't consider it a
       // getter now (this also enforces parenthesis (and thus parameters)).
       if (hasQualifiedName) {
         isConsideredGetter = false;
-      } else if (isConsideredGetter && optional(':', token.next)) {
+      } else if (isConsideredGetter && optional(':', token.next!)) {
         isConsideredGetter = false;
       } else if (isConsideredGetter &&
           name.lexeme == enclosingDeclarationName) {
@@ -3694,7 +3832,7 @@
     }
 
     Token beforeParam = token;
-    Token beforeInitializers = parseGetterOrFormalParameters(
+    Token? beforeInitializers = parseGetterOrFormalParameters(
         token,
         name,
         isConsideredGetter,
@@ -3709,12 +3847,12 @@
     if (token == beforeInitializers) beforeInitializers = null;
 
     AsyncModifier savedAsyncModifier = asyncState;
-    Token asyncToken = token.next;
+    Token asyncToken = token.next!;
     token = parseAsyncModifierOpt(token);
     if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
       reportRecoverableError(asyncToken, codes.messageSetterNotSync);
     }
-    final Token bodyStart = token.next;
+    final Token bodyStart = token.next!;
     if (externalToken != null) {
       if (!optional(';', bodyStart)) {
         reportRecoverableError(bodyStart, codes.messageExternalMethodWithBody);
@@ -3730,7 +3868,7 @@
     asyncState = savedAsyncModifier;
 
     bool isConstructor = false;
-    if (optional('.', name.next) || beforeInitializers != null) {
+    if (optional('.', name.next!) || beforeInitializers != null) {
       // This is only legal for constructors.
       isConstructor = true;
     } else if (name.lexeme == enclosingDeclarationName) {
@@ -3763,33 +3901,32 @@
       }
       if (typeInfo != noType) {
         reportRecoverableError(
-            beforeType.next, codes.messageConstructorWithReturnType);
+            beforeType.next!, codes.messageConstructorWithReturnType);
       }
       if (beforeInitializers != null && externalToken != null) {
-        reportRecoverableError(beforeInitializers.next,
+        reportRecoverableError(beforeInitializers.next!,
             codes.messageExternalConstructorWithInitializer);
       }
 
       switch (kind) {
         case DeclarationKind.Class:
           // TODO(danrubel): Remove getOrSet from constructor events
-          listener.endClassConstructor(getOrSet, beforeStart.next,
-              beforeParam.next, beforeInitializers?.next, token);
+          listener.endClassConstructor(getOrSet, beforeStart.next!,
+              beforeParam.next!, beforeInitializers?.next, token);
           break;
         case DeclarationKind.Mixin:
           reportRecoverableError(name, codes.messageMixinDeclaresConstructor);
-          listener.endMixinConstructor(getOrSet, beforeStart.next,
-              beforeParam.next, beforeInitializers?.next, token);
+          listener.endMixinConstructor(getOrSet, beforeStart.next!,
+              beforeParam.next!, beforeInitializers?.next, token);
           break;
         case DeclarationKind.Extension:
           reportRecoverableError(
               name, codes.messageExtensionDeclaresConstructor);
-          listener.endExtensionConstructor(getOrSet, beforeStart.next,
-              beforeParam.next, beforeInitializers?.next, token);
+          listener.endExtensionConstructor(getOrSet, beforeStart.next!,
+              beforeParam.next!, beforeInitializers?.next, token);
           break;
         case DeclarationKind.TopLevel:
           throw "Internal error: TopLevel constructor.";
-          break;
       }
     } else {
       //
@@ -3802,35 +3939,34 @@
       switch (kind) {
         case DeclarationKind.Class:
           // TODO(danrubel): Remove beginInitializers token from method events
-          listener.endClassMethod(getOrSet, beforeStart.next, beforeParam.next,
-              beforeInitializers?.next, token);
+          listener.endClassMethod(getOrSet, beforeStart.next!,
+              beforeParam.next!, beforeInitializers?.next, token);
           break;
         case DeclarationKind.Mixin:
-          listener.endMixinMethod(getOrSet, beforeStart.next, beforeParam.next,
-              beforeInitializers?.next, token);
+          listener.endMixinMethod(getOrSet, beforeStart.next!,
+              beforeParam.next!, beforeInitializers?.next, token);
           break;
         case DeclarationKind.Extension:
           if (optional(';', bodyStart) && externalToken == null) {
-            reportRecoverableError(isOperator ? name.next : name,
+            reportRecoverableError(isOperator ? name.next! : name,
                 codes.messageExtensionDeclaresAbstractMember);
           }
-          listener.endExtensionMethod(getOrSet, beforeStart.next,
-              beforeParam.next, beforeInitializers?.next, token);
+          listener.endExtensionMethod(getOrSet, beforeStart.next!,
+              beforeParam.next!, beforeInitializers?.next, token);
           break;
         case DeclarationKind.TopLevel:
           throw "Internal error: TopLevel method.";
-          break;
       }
     }
     return token;
   }
 
   Token parseFactoryMethod(Token token, DeclarationKind kind, Token beforeStart,
-      Token externalToken, Token staticOrCovariant, Token varFinalOrConst) {
-    Token factoryKeyword = token = token.next;
+      Token? externalToken, Token? staticOrCovariant, Token? varFinalOrConst) {
+    Token factoryKeyword = token = token.next!;
     assert(optional('factory', factoryKeyword));
 
-    if (!isValidTypeReference(token.next)) {
+    if (!isValidTypeReference(token.next!)) {
       // Recovery
       ModifierRecoveryContext context = new ModifierRecoveryContext(this)
         ..externalToken = externalToken
@@ -3842,8 +3978,6 @@
       externalToken = context.externalToken;
       staticOrCovariant = context.staticToken ?? context.covariantToken;
       varFinalOrConst = context.varFinalOrConst;
-
-      context = null;
     }
 
     if (staticOrCovariant != null) {
@@ -3862,9 +3996,9 @@
         token, IdentifierContext.methodDeclarationContinuation);
     token = parseMethodTypeVar(token);
     token = parseFormalParametersRequiredOpt(token, MemberKind.Factory);
-    Token asyncToken = token.next;
+    Token asyncToken = token.next!;
     token = parseAsyncModifierOpt(token);
-    Token next = token.next;
+    Token next = token.next!;
     if (!inPlainSync) {
       reportRecoverableError(asyncToken, codes.messageFactoryNotSync);
     }
@@ -3894,31 +4028,32 @@
     }
     switch (kind) {
       case DeclarationKind.Class:
-        listener.endClassFactoryMethod(beforeStart.next, factoryKeyword, token);
+        listener.endClassFactoryMethod(
+            beforeStart.next!, factoryKeyword, token);
         break;
       case DeclarationKind.Mixin:
         reportRecoverableError(
             factoryKeyword, codes.messageMixinDeclaresConstructor);
-        listener.endMixinFactoryMethod(beforeStart.next, factoryKeyword, token);
+        listener.endMixinFactoryMethod(
+            beforeStart.next!, factoryKeyword, token);
         break;
       case DeclarationKind.Extension:
         reportRecoverableError(
             factoryKeyword, codes.messageExtensionDeclaresConstructor);
         listener.endExtensionFactoryMethod(
-            beforeStart.next, factoryKeyword, token);
+            beforeStart.next!, factoryKeyword, token);
         break;
       case DeclarationKind.TopLevel:
         throw "Internal error: TopLevel factory.";
-        break;
     }
     return token;
   }
 
   Token parseOperatorName(Token token) {
     Token beforeToken = token;
-    token = token.next;
+    token = token.next!;
     assert(optional('operator', token));
-    Token next = token.next;
+    Token next = token.next!;
     if (next.isUserDefinableOperator) {
       if (computeTypeParamOrArg(token) != noTypeParamOrArg) {
         // `operator` is being used as an identifier.
@@ -3934,7 +4069,7 @@
     } else if (isUnaryMinus(next)) {
       // Recovery
       reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
-      next = next.next;
+      next = next.next!;
       listener.handleOperatorName(token, next);
       return next;
     } else {
@@ -3952,12 +4087,12 @@
   }
 
   Token parseFunctionExpression(Token token) {
-    Token beginToken = token.next;
+    Token beginToken = token.next!;
     listener.beginFunctionExpression(beginToken);
     token = parseFormalParametersRequiredOpt(token, MemberKind.Local);
     token = parseAsyncOptBody(
         token, /* ofFunctionExpression = */ true, /* allowAbstract = */ false);
-    listener.endFunctionExpression(beginToken, token.next);
+    listener.endFunctionExpression(beginToken, token.next!);
     return token;
   }
 
@@ -3969,10 +4104,10 @@
       TypeParamOrArgInfo typeParam,
       IdentifierContext context) {
     Token formals = typeParam.parseVariables(name, this);
-    listener.beginNamedFunctionExpression(start.next);
+    listener.beginNamedFunctionExpression(start.next!);
     typeInfo.parseType(start, this);
     return parseNamedFunctionRest(
-        beforeName, start.next, formals, /* isFunctionExpression = */ true);
+        beforeName, start.next!, formals, /* isFunctionExpression = */ true);
   }
 
   /// Parses the rest of a named function declaration starting from its [name]
@@ -3993,14 +4128,14 @@
   /// - Return type.
   Token parseNamedFunctionRest(
       Token beforeName, Token begin, Token formals, bool isFunctionExpression) {
-    Token token = beforeName.next;
+    Token token = beforeName.next!;
     listener.beginFunctionName(token);
     token =
         ensureIdentifier(beforeName, IdentifierContext.localFunctionDeclaration)
-            .next;
+            .next!;
     if (isFunctionExpression) {
       reportRecoverableError(
-          beforeName.next, codes.messageNamedFunctionExpression);
+          beforeName.next!, codes.messageNamedFunctionExpression);
     }
     listener.endFunctionName(begin, token);
     token = parseFormalParametersRequiredOpt(formals, MemberKind.Local);
@@ -4031,7 +4166,7 @@
     return token;
   }
 
-  Token parseConstructorReference(Token token, [TypeParamOrArgInfo typeArg]) {
+  Token parseConstructorReference(Token token, [TypeParamOrArgInfo? typeArg]) {
     Token start =
         ensureIdentifier(token, IdentifierContext.constructorReference);
     listener.beginConstructorReference(start);
@@ -4039,21 +4174,21 @@
         start, IdentifierContext.constructorReferenceContinuation);
     typeArg ??= computeTypeParamOrArg(token);
     token = typeArg.parseArguments(token, this);
-    Token period = null;
-    if (optional('.', token.next)) {
-      period = token.next;
+    Token? period = null;
+    if (optional('.', token.next!)) {
+      period = token.next!;
       token = ensureIdentifier(period,
           IdentifierContext.constructorReferenceContinuationAfterTypeArguments);
     } else {
       listener.handleNoConstructorReferenceContinuationAfterTypeArguments(
-          token.next);
+          token.next!);
     }
-    listener.endConstructorReference(start, period, token.next);
+    listener.endConstructorReference(start, period, token.next!);
     return token;
   }
 
   Token parseRedirectingFactoryBody(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('=', token));
     listener.beginRedirectingFactoryBody(token);
     Token equals = token;
@@ -4066,22 +4201,22 @@
   Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) {
     assert(!isExpression);
     token = skipAsyncModifier(token);
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('native', next)) {
       Token nativeToken = next;
       // TODO(danrubel): skip the native clause rather than parsing it
       // or remove this code completely when we remove support
       // for the `native` clause.
       token = parseNativeClause(token);
-      next = token.next;
+      next = token.next!;
       if (optional(';', next)) {
         listener.handleNativeFunctionBodySkipped(nativeToken, next);
-        return token.next;
+        return token.next!;
       }
       listener.handleNativeFunctionBodyIgnored(nativeToken, next);
       // Fall through to recover and skip function body
     }
-    String value = next.stringValue;
+    String? value = next.stringValue;
     if (identical(value, ';')) {
       token = next;
       if (!allowAbstract) {
@@ -4093,8 +4228,8 @@
       // There ought to be a semicolon following the expression, but we check
       // before advancing in order to be consistent with the way the method
       // [parseFunctionBody] recovers when the semicolon is missing.
-      if (optional(';', token.next)) {
-        token = token.next;
+      if (optional(';', token.next!)) {
+        token = token.next!;
       }
       listener.handleFunctionBodySkipped(token, /* isExpressionBody = */ true);
     } else if (identical(value, '=')) {
@@ -4104,8 +4239,8 @@
       // There ought to be a semicolon following the expression, but we check
       // before advancing in order to be consistent with the way the method
       // [parseFunctionBody] recovers when the semicolon is missing.
-      if (optional(';', token.next)) {
-        token = token.next;
+      if (optional(';', token.next!)) {
+        token = token.next!;
       }
       listener.handleFunctionBodySkipped(token, /* isExpressionBody = */ true);
     } else {
@@ -4123,11 +4258,11 @@
   /// It's an error if there's no function body unless [allowAbstract] is true.
   Token parseFunctionBody(
       Token token, bool ofFunctionExpression, bool allowAbstract) {
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('native', next)) {
       Token nativeToken = next;
       token = parseNativeClause(token);
-      next = token.next;
+      next = token.next!;
       if (optional(';', next)) {
         listener.handleNativeFunctionBody(nativeToken, next);
         return next;
@@ -4148,7 +4283,7 @@
       // Recover from a bad factory method.
       reportRecoverableError(next, codes.messageExpectedBody);
       next = rewriter.insertToken(
-          next, new SyntheticToken(TokenType.FUNCTION, next.next.charOffset));
+          next, new SyntheticToken(TokenType.FUNCTION, next.next!.charOffset));
       Token begin = next;
       token = parseExpression(next);
       if (!ofFunctionExpression) {
@@ -4166,21 +4301,21 @@
       // If `return` used instead of `=>`, then report an error and continue
       if (optional('return', next)) {
         reportRecoverableError(next, codes.messageExpectedBody);
-        next = rewriter.insertToken(
-            next, new SyntheticToken(TokenType.FUNCTION, next.next.charOffset));
+        next = rewriter.insertToken(next,
+            new SyntheticToken(TokenType.FUNCTION, next.next!.charOffset));
         return parseExpressionFunctionBody(next, ofFunctionExpression);
       }
       // If there is a stray simple identifier in the function expression
       // because the user is typing (e.g. `() asy => null;`)
       // then report an error, skip the token, and continue parsing.
-      if (next.isKeywordOrIdentifier && optional('=>', next.next)) {
+      if (next.isKeywordOrIdentifier && optional('=>', next.next!)) {
         reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
-        return parseExpressionFunctionBody(next.next, ofFunctionExpression);
+        return parseExpressionFunctionBody(next.next!, ofFunctionExpression);
       }
-      if (next.isKeywordOrIdentifier && optional('{', next.next)) {
+      if (next.isKeywordOrIdentifier && optional('{', next.next!)) {
         reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
         token = next;
-        begin = next = token.next;
+        begin = next = token.next!;
         // Fall through to parse the block.
       } else {
         token = ensureBlock(
@@ -4188,7 +4323,7 @@
             codes.templateExpectedFunctionBody,
             /* missingBlockName = */ null);
         listener.handleInvalidFunctionBody(token);
-        return token.endGroup;
+        return token.endGroup!;
       }
     }
 
@@ -4196,19 +4331,19 @@
     loopState = LoopState.OutsideLoop;
     listener.beginBlockFunctionBody(begin);
     token = next;
-    while (notEofOrValue('}', token.next)) {
-      Token startToken = token.next;
+    while (notEofOrValue('}', token.next!)) {
+      Token startToken = token.next!;
       token = parseStatement(token);
-      if (identical(token.next, startToken)) {
+      if (identical(token.next!, startToken)) {
         // No progress was made, so we report the current token as being invalid
         // and move forward.
         reportRecoverableError(
             token, codes.templateUnexpectedToken.withArguments(token));
-        token = token.next;
+        token = token.next!;
       }
       ++statementCount;
     }
-    token = token.next;
+    token = token.next!;
     assert(token.isEof || optional('}', token));
     listener.endBlockFunctionBody(statementCount, begin, token);
     loopState = savedLoopState;
@@ -4233,33 +4368,33 @@
   }
 
   Token skipAsyncModifier(Token token) {
-    String value = token.next.stringValue;
+    String? value = token.next!.stringValue;
     if (identical(value, 'async')) {
-      token = token.next;
-      value = token.next.stringValue;
+      token = token.next!;
+      value = token.next!.stringValue;
 
       if (identical(value, '*')) {
-        token = token.next;
+        token = token.next!;
       }
     } else if (identical(value, 'sync')) {
-      token = token.next;
-      value = token.next.stringValue;
+      token = token.next!;
+      value = token.next!.stringValue;
 
       if (identical(value, '*')) {
-        token = token.next;
+        token = token.next!;
       }
     }
     return token;
   }
 
   Token parseAsyncModifierOpt(Token token) {
-    Token async;
-    Token star;
+    Token? async;
+    Token? star;
     asyncState = AsyncModifier.Sync;
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('async', next)) {
       async = token = next;
-      next = token.next;
+      next = token.next!;
       if (optional('*', next)) {
         asyncState = AsyncModifier.AsyncStar;
         star = next;
@@ -4269,7 +4404,7 @@
       }
     } else if (optional('sync', next)) {
       async = token = next;
-      next = token.next;
+      next = token.next!;
       if (optional('*', next)) {
         asyncState = AsyncModifier.SyncStar;
         star = next;
@@ -4279,8 +4414,8 @@
       }
     }
     listener.handleAsyncModifier(async, star);
-    if (!inPlainSync && optional(';', token.next)) {
-      reportRecoverableError(token.next, codes.messageAbstractNotSync);
+    if (!inPlainSync && optional(';', token.next!)) {
+      reportRecoverableError(token.next!, codes.messageAbstractNotSync);
     }
     return token;
   }
@@ -4299,8 +4434,8 @@
   }
 
   Token parseStatementX(Token token) {
-    if (identical(token.next.kind, IDENTIFIER_TOKEN)) {
-      if (optional(':', token.next.next)) {
+    if (identical(token.next!.kind, IDENTIFIER_TOKEN)) {
+      if (optional(':', token.next!.next!)) {
         return parseLabeledStatement(token);
       }
       return parseExpressionStatementOrDeclarationAfterModifiers(
@@ -4311,15 +4446,15 @@
           /* typeInfo = */ null,
           /* onlyParseVariableDeclarationStart = */ false);
     }
-    final String value = token.next.stringValue;
+    final String? value = token.next!.stringValue;
     if (identical(value, '{')) {
       // The scanner ensures that `{` always has a closing `}`.
       return parseBlock(token, BlockKind.statement);
     } else if (identical(value, 'return')) {
       return parseReturnStatement(token);
     } else if (identical(value, 'var') || identical(value, 'final')) {
-      Token varOrFinal = token.next;
-      if (!isModifier(varOrFinal.next)) {
+      Token varOrFinal = token.next!;
+      if (!isModifier(varOrFinal.next!)) {
         return parseExpressionStatementOrDeclarationAfterModifiers(
             varOrFinal,
             token,
@@ -4331,8 +4466,9 @@
       return parseExpressionStatementOrDeclaration(token);
     } else if (identical(value, 'if')) {
       return parseIfStatement(token);
-    } else if (identical(value, 'await') && optional('for', token.next.next)) {
-      return parseForStatement(token.next, token.next);
+    } else if (identical(value, 'await') &&
+        optional('for', token.next!.next!)) {
+      return parseForStatement(token.next!, token.next!);
     } else if (identical(value, 'for')) {
       return parseForStatement(token, /* awaitToken = */ null);
     } else if (identical(value, 'rethrow')) {
@@ -4356,7 +4492,7 @@
     } else if (identical(value, 'yield')) {
       switch (asyncState) {
         case AsyncModifier.Sync:
-          if (optional(':', token.next.next)) {
+          if (optional(':', token.next!.next!)) {
             return parseLabeledStatement(token);
           }
           if (looksLikeYieldStatement(token)) {
@@ -4372,10 +4508,9 @@
           return parseYieldStatement(token);
 
         case AsyncModifier.Async:
-          reportRecoverableError(token.next, codes.messageYieldNotGenerator);
+          reportRecoverableError(token.next!, codes.messageYieldNotGenerator);
           return parseYieldStatement(token);
       }
-      throw "Internal error: Unknown asyncState: '$asyncState'.";
     } else if (identical(value, 'const')) {
       return parseExpressionStatementOrConstDeclaration(token);
     } else if (identical(value, 'await')) {
@@ -4389,13 +4524,13 @@
         // and parseAwaitExpression will report the error.
       }
       return parseExpressionStatement(token);
-    } else if (identical(value, 'set') && token.next.next.isIdentifier) {
+    } else if (identical(value, 'set') && token.next!.next!.isIdentifier) {
       // Recovery: invalid use of `set`
       reportRecoverableErrorWithToken(
-          token.next, codes.templateUnexpectedToken);
-      return parseStatementX(token.next);
-    } else if (token.next.isIdentifier) {
-      if (optional(':', token.next.next)) {
+          token.next!, codes.templateUnexpectedToken);
+      return parseStatementX(token.next!);
+    } else if (token.next!.isIdentifier) {
+      if (optional(':', token.next!.next!)) {
         return parseLabeledStatement(token);
       }
       return parseExpressionStatementOrDeclaration(token);
@@ -4410,12 +4545,12 @@
   /// ;
   /// ```
   Token parseYieldStatement(Token token) {
-    Token begin = token = token.next;
+    Token begin = token = token.next!;
     assert(optional('yield', token));
     listener.beginYieldStatement(begin);
-    Token starToken;
-    if (optional('*', token.next)) {
-      starToken = token = token.next;
+    Token? starToken;
+    if (optional('*', token.next!)) {
+      starToken = token = token.next!;
     }
     token = parseExpression(token);
     token = ensureSemicolon(token);
@@ -4441,10 +4576,10 @@
   /// ;
   /// ```
   Token parseReturnStatement(Token token) {
-    Token begin = token = token.next;
+    Token begin = token = token.next!;
     assert(optional('return', token));
     listener.beginReturnStatement(begin);
-    Token next = token.next;
+    Token next = token.next!;
     if (optional(';', next)) {
       listener.endReturnStatement(/* hasExpression = */ false, begin, next);
       return next;
@@ -4465,8 +4600,8 @@
   /// ;
   /// ```
   Token parseLabel(Token token) {
-    assert(token.next.isIdentifier);
-    token = ensureIdentifier(token, IdentifierContext.labelDeclaration).next;
+    assert(token.next!.isIdentifier);
+    token = ensureIdentifier(token, IdentifierContext.labelDeclaration).next!;
     assert(optional(':', token));
     listener.handleLabel(token);
     return token;
@@ -4478,15 +4613,15 @@
   /// ;
   /// ```
   Token parseLabeledStatement(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(next.isIdentifier);
-    assert(optional(':', next.next));
+    assert(optional(':', next.next!));
     int labelCount = 0;
     do {
       token = parseLabel(token);
-      next = token.next;
+      next = token.next!;
       labelCount++;
-    } while (next.isIdentifier && optional(':', next.next));
+    } while (next.isIdentifier && optional(':', next.next!));
     listener.beginLabeledStatement(next, labelCount);
     token = parseStatement(token);
     listener.endLabeledStatement(labelCount);
@@ -4519,20 +4654,20 @@
       // This happens in degenerate programs, for example, with a lot of nested
       // list literals. This is provoked by, for example, the language test
       // deep_nesting1_negative_test.
-      Token next = token.next;
+      Token next = token.next!;
       reportRecoverableError(next, codes.messageStackOverflow);
 
       // Recovery
-      Token endGroup = next.endGroup;
+      Token? endGroup = next.endGroup;
       if (endGroup != null) {
         while (!next.isEof && !identical(next, endGroup)) {
           token = next;
-          next = token.next;
+          next = token.next!;
         }
       } else {
         while (!isOneOf(next, const [')', ']', '}', ';'])) {
           token = next;
-          next = token.next;
+          next = token.next!;
         }
       }
       if (!token.isEof) {
@@ -4540,7 +4675,7 @@
         listener.handleIdentifier(token, IdentifierContext.expression);
       }
     } else {
-      token = optional('throw', token.next)
+      token = optional('throw', token.next!)
           ? parseThrowExpression(token, /* allowCascades = */ true)
           : parsePrecedenceExpression(
               token, ASSIGNMENT_PRECEDENCE, /* allowCascades = */ true);
@@ -4550,7 +4685,7 @@
   }
 
   Token parseExpressionWithoutCascade(Token token) {
-    return optional('throw', token.next)
+    return optional('throw', token.next!)
         ? parseThrowExpression(token, /* allowCascades = */ false)
         : parsePrecedenceExpression(
             token, ASSIGNMENT_PRECEDENCE, /* allowCascades = */ false);
@@ -4560,7 +4695,7 @@
     // We want to check if we can parse, not send events and permanently change
     // the token stream. Set it up so we can do that.
     Listener originalListener = listener;
-    TokenStreamRewriter originalRewriter = cachedRewriter;
+    TokenStreamRewriter? originalRewriter = cachedRewriter;
     NullListener nullListener = listener = new NullListener();
     UndoableTokenStreamRewriter undoableTokenStreamRewriter =
         new UndoableTokenStreamRewriter();
@@ -4569,8 +4704,8 @@
     bool isConditional = false;
 
     Token afterExpression1 = parseExpressionWithoutCascade(question);
-    if (!nullListener.hasErrors && optional(':', afterExpression1.next)) {
-      parseExpressionWithoutCascade(afterExpression1.next);
+    if (!nullListener.hasErrors && optional(':', afterExpression1.next!)) {
+      parseExpressionWithoutCascade(afterExpression1.next!);
       if (!nullListener.hasErrors) {
         // Now we know it's a conditional expression.
         isConditional = true;
@@ -4586,7 +4721,7 @@
   }
 
   Token parseConditionalExpressionRest(Token token) {
-    Token question = token = token.next;
+    Token question = token = token.next!;
     assert(optional('?', question));
     listener.beginConditionalExpression(token);
     token = parseExpressionWithoutCascade(token);
@@ -4603,8 +4738,8 @@
     assert(precedence <= SELECTOR_PRECEDENCE);
     token = parseUnaryExpression(token, allowCascades);
     Token bangToken = token;
-    if (optional('!', token.next)) {
-      bangToken = token.next;
+    if (optional('!', token.next!)) {
+      bangToken = token.next!;
     }
     TypeParamOrArgInfo typeArg = computeMethodTypeArguments(bangToken);
     if (typeArg != noTypeParamOrArg) {
@@ -4613,7 +4748,7 @@
         listener.handleNonNullAssertExpression(bangToken);
       }
       token = typeArg.parseArguments(bangToken, this);
-      assert(optional('(', token.next));
+      assert(optional('(', token.next!));
     }
 
     return _parsePrecedenceExpressionLoop(
@@ -4622,13 +4757,13 @@
 
   Token _parsePrecedenceExpressionLoop(int precedence, bool allowCascades,
       TypeParamOrArgInfo typeArg, Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     TokenType type = next.type;
     int tokenLevel = _computePrecedence(next);
     bool enteredLoop = false;
     for (int level = tokenLevel; level >= precedence; --level) {
       int lastBinaryExpressionLevel = -1;
-      Token lastCascade;
+      Token? lastCascade;
       while (identical(tokenLevel, level)) {
         enteredLoop = true;
         Token operator = next;
@@ -4644,15 +4779,15 @@
         } else if (identical(tokenLevel, ASSIGNMENT_PRECEDENCE)) {
           // Right associative, so we recurse at the same precedence
           // level.
-          Token next = token.next;
-          token = optional('throw', next.next)
+          Token next = token.next!;
+          token = optional('throw', next.next!)
               ? parseThrowExpression(next, /* allowCascades = */ false)
               : parsePrecedenceExpression(next, level, allowCascades);
           listener.handleAssignmentExpression(operator);
         } else if (identical(tokenLevel, POSTFIX_PRECEDENCE)) {
           if ((identical(type, TokenType.PLUS_PLUS)) ||
               (identical(type, TokenType.MINUS_MINUS))) {
-            listener.handleUnaryPostfixAssignmentExpression(token.next);
+            listener.handleUnaryPostfixAssignmentExpression(token.next!);
             token = next;
           } else if (identical(type, TokenType.BANG)) {
             listener.handleNonNullAssertExpression(next);
@@ -4667,12 +4802,12 @@
             // unary expression isn't legal after a period, so we call
             // [parsePrimary] instead.
             token = parsePrimary(
-                token.next, IdentifierContext.expressionContinuation);
+                token.next!, IdentifierContext.expressionContinuation);
             listener.handleEndingBinaryExpression(operator);
 
             Token bangToken = token;
-            if (optional('!', token.next)) {
-              bangToken = token.next;
+            if (optional('!', token.next!)) {
+              bangToken = token.next!;
             }
             typeArg = computeMethodTypeArguments(bangToken);
             if (typeArg != noTypeParamOrArg) {
@@ -4681,7 +4816,7 @@
                 listener.handleNonNullAssertExpression(bangToken);
               }
               token = typeArg.parseArguments(bangToken, this);
-              assert(optional('(', token.next));
+              assert(optional('(', token.next!));
             }
           } else if (identical(type, TokenType.OPEN_PAREN) ||
               identical(type, TokenType.OPEN_SQUARE_BRACKET)) {
@@ -4697,12 +4832,12 @@
             token = parseArgumentOrIndexStar(
                 token, noTypeParamOrArg, /* checkedNullAware = */ false);
           } else if (identical(type, TokenType.BANG)) {
-            listener.handleNonNullAssertExpression(token.next);
+            listener.handleNonNullAssertExpression(token.next!);
             token = next;
           } else {
             // Recovery
             reportRecoverableErrorWithToken(
-                token.next, codes.templateUnexpectedToken);
+                token.next!, codes.templateUnexpectedToken);
             token = next;
           }
         } else if (identical(type, TokenType.IS)) {
@@ -4727,10 +4862,10 @@
           // Left associative, so we recurse at the next higher
           // precedence level.
           token =
-              parsePrecedenceExpression(token.next, level + 1, allowCascades);
+              parsePrecedenceExpression(token.next!, level + 1, allowCascades);
           listener.endBinaryExpression(operator);
         }
-        next = token.next;
+        next = token.next!;
         type = next.type;
         tokenLevel = _computePrecedence(next);
       }
@@ -4740,7 +4875,7 @@
             token, precedence, level, allowCascades, typeArg)) {
           // Recovered - try again at same level with the replacement token.
           level++;
-          next = token.next;
+          next = token.next!;
           type = next.type;
           tokenLevel = _computePrecedence(next);
         }
@@ -4762,8 +4897,8 @@
   bool _attemptPrecedenceLevelRecovery(Token token, int precedence,
       int currentLevel, bool allowCascades, TypeParamOrArgInfo typeArg) {
     // Attempt recovery.
-    assert(_token_recovery_replacements.containsKey(token.next.lexeme));
-    TokenType replacement = _token_recovery_replacements[token.next.lexeme];
+    assert(_token_recovery_replacements.containsKey(token.next!.lexeme));
+    TokenType replacement = _token_recovery_replacements[token.next!.lexeme]!;
     if (currentLevel >= 0) {
       // Check that the new precedence and currentLevel would have accepted this
       // replacement here.
@@ -4785,7 +4920,7 @@
     _currentlyRecovering = true;
     _recoverAtPrecedenceLevel = false;
     Listener originalListener = listener;
-    TokenStreamRewriter originalRewriter = cachedRewriter;
+    TokenStreamRewriter? originalRewriter = cachedRewriter;
     NullListener nullListener = listener = new NullListener();
     UndoableTokenStreamRewriter undoableTokenStreamRewriter =
         new UndoableTokenStreamRewriter();
@@ -4796,7 +4931,7 @@
         precedence, allowCascades, typeArg, token);
 
     if (!nullListener.hasErrors &&
-        isOneOfOrEof(afterExpression.next, const [';', ',', ')', '{', '}'])) {
+        isOneOfOrEof(afterExpression.next!, const [';', ',', ')', '{', '}'])) {
       // Seems good!
       acceptRecovery = true;
     }
@@ -4810,9 +4945,9 @@
     if (acceptRecovery) {
       // Report and redo recovery.
       reportRecoverableError(
-          token.next,
+          token.next!,
           codes.templateBinaryOperatorWrittenOut
-              .withArguments(token.next.lexeme, replacement.lexeme));
+              .withArguments(token.next!.lexeme, replacement.lexeme));
       rewriter.replaceNextTokenWithSyntheticToken(token, replacement);
       return true;
     }
@@ -4836,7 +4971,7 @@
     if (identical(type, TokenType.BANG)) {
       // The '!' has prefix precedence but here it's being used as a
       // postfix operator to assert the expression has a non-null value.
-      TokenType nextType = token.next.type;
+      TokenType nextType = token.next!.type;
       if (identical(nextType, TokenType.PERIOD) ||
           identical(nextType, TokenType.QUESTION) ||
           identical(nextType, TokenType.OPEN_PAREN) ||
@@ -4846,7 +4981,7 @@
       }
       return POSTFIX_PRECEDENCE;
     } else if (identical(type, TokenType.QUESTION) &&
-        optional('[', token.next)) {
+        optional('[', token.next!)) {
       // "?[" can be a null-aware bracket or a conditional. If it's a
       // null-aware bracket it has selector precedence.
       bool isConditional = canParseAsConditional(token);
@@ -4866,35 +5001,35 @@
   }
 
   Token parseCascadeExpression(Token token) {
-    Token cascadeOperator = token = token.next;
+    Token cascadeOperator = token = token.next!;
     assert(optional('..', cascadeOperator) || optional('?..', cascadeOperator));
     listener.beginCascade(cascadeOperator);
-    if (optional('[', token.next)) {
+    if (optional('[', token.next!)) {
       token = parseArgumentOrIndexStar(
           token, noTypeParamOrArg, /* checkedNullAware = */ false);
     } else {
       token = parseSend(token, IdentifierContext.expressionContinuation);
       listener.handleEndingBinaryExpression(cascadeOperator);
     }
-    Token next = token.next;
+    Token next = token.next!;
     Token mark;
     do {
       mark = token;
       if (optional('.', next) || optional('?.', next)) {
         Token period = next;
         token = parseSend(next, IdentifierContext.expressionContinuation);
-        next = token.next;
+        next = token.next!;
         listener.handleEndingBinaryExpression(period);
       } else if (optional('!', next)) {
         listener.handleNonNullAssertExpression(next);
         token = next;
-        next = token.next;
+        next = token.next!;
       }
       TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
       if (typeArg != noTypeParamOrArg) {
         // For example a(b)..<T>(c), where token is '<'.
         token = typeArg.parseArguments(token, this);
-        next = token.next;
+        next = token.next!;
         assert(optional('(', next));
       }
       TokenType nextType = next.type;
@@ -4907,7 +5042,7 @@
       }
       token = parseArgumentOrIndexStar(
           token, typeArg, /* checkedNullAware = */ false);
-      next = token.next;
+      next = token.next!;
     } while (!identical(mark, token));
 
     if (identical(next.type.precedence, ASSIGNMENT_PRECEDENCE)) {
@@ -4920,7 +5055,7 @@
   }
 
   Token parseUnaryExpression(Token token, bool allowCascades) {
-    String value = token.next.stringValue;
+    String? value = token.next!.stringValue;
     // Prefix:
     if (identical(value, 'await')) {
       if (inPlainSync) {
@@ -4938,39 +5073,39 @@
           // TODO(danrubel): Consider reporting "missing identifier" instead.
           codes.messageUnsupportedPrefixPlus,
           new SyntheticStringToken(
-              TokenType.IDENTIFIER, '', token.next.offset));
+              TokenType.IDENTIFIER, '', token.next!.offset));
       return parsePrimary(token, IdentifierContext.expression);
     } else if ((identical(value, '!')) ||
         (identical(value, '-')) ||
         (identical(value, '~'))) {
-      Token operator = token.next;
+      Token operator = token.next!;
       // Right associative, so we recurse at the same precedence
       // level.
       token = parsePrecedenceExpression(
-          token.next, POSTFIX_PRECEDENCE, allowCascades);
+          token.next!, POSTFIX_PRECEDENCE, allowCascades);
       listener.handleUnaryPrefixExpression(operator);
       return token;
     } else if ((identical(value, '++')) || identical(value, '--')) {
       // TODO(ahe): Validate this is used correctly.
-      Token operator = token.next;
+      Token operator = token.next!;
       // Right associative, so we recurse at the same precedence
       // level.
       token = parsePrecedenceExpression(
-          token.next, POSTFIX_PRECEDENCE, allowCascades);
+          token.next!, POSTFIX_PRECEDENCE, allowCascades);
       listener.handleUnaryPrefixAssignmentExpression(operator);
       return token;
-    } else if (token.next.isIdentifier) {
-      Token identifier = token.next;
-      if (optional(".", identifier.next)) {
-        identifier = identifier.next.next;
+    } else if (token.next!.isIdentifier) {
+      Token identifier = token.next!;
+      if (optional(".", identifier.next!)) {
+        identifier = identifier.next!.next!;
       }
       if (identifier.isIdentifier) {
         // Looking at `identifier ('.' identifier)?`.
-        if (optional("<", identifier.next)) {
+        if (optional("<", identifier.next!)) {
           TypeParamOrArgInfo typeArg = computeTypeParamOrArg(identifier);
           if (typeArg != noTypeParamOrArg) {
             Token endTypeArguments = typeArg.skip(identifier);
-            if (optional(".", endTypeArguments.next)) {
+            if (optional(".", endTypeArguments.next!)) {
               return parseImplicitCreationExpression(token, typeArg);
             }
           }
@@ -4982,11 +5117,11 @@
 
   Token parseArgumentOrIndexStar(
       Token token, TypeParamOrArgInfo typeArg, bool checkedNullAware) {
-    Token next = token.next;
+    Token next = token.next!;
     final Token beginToken = next;
     while (true) {
       bool potentialNullAware =
-          (optional('?', next) && optional('[', next.next));
+          (optional('?', next) && optional('[', next.next!));
       if (potentialNullAware && !checkedNullAware) {
         // While it's a potential null aware index it hasn't been checked.
         // It might be a conditional expression.
@@ -4998,24 +5133,24 @@
       if (optional('[', next) || potentialNullAware) {
         assert(typeArg == noTypeParamOrArg);
         Token openSquareBracket = next;
-        Token question;
+        Token? question;
         if (optional('?', next)) {
           question = next;
-          next = next.next;
+          next = next.next!;
           openSquareBracket = next;
           assert(optional('[', openSquareBracket));
         }
         bool old = mayParseFunctionExpressions;
         mayParseFunctionExpressions = true;
         token = parseExpression(next);
-        next = token.next;
+        next = token.next!;
         mayParseFunctionExpressions = old;
         if (!optional(']', next)) {
           // Recovery
           reportRecoverableError(
               next, codes.templateExpectedButGot.withArguments(']'));
           // Scanner ensures a closing ']'
-          Token endGroup = openSquareBracket.endGroup;
+          Token endGroup = openSquareBracket.endGroup!;
           if (endGroup.isSynthetic) {
             // Scanner inserted closing ']' in the wrong place, so move it.
             next = rewriter.moveSynthetic(token, endGroup);
@@ -5027,8 +5162,8 @@
         listener.handleIndexedExpression(question, openSquareBracket, next);
         token = next;
         Token bangToken = token;
-        if (optional('!', token.next)) {
-          bangToken = token.next;
+        if (optional('!', token.next!)) {
+          bangToken = token.next!;
         }
         typeArg = computeMethodTypeArguments(bangToken);
         if (typeArg != noTypeParamOrArg) {
@@ -5037,9 +5172,9 @@
             listener.handleNonNullAssertExpression(bangToken);
           }
           token = typeArg.parseArguments(bangToken, this);
-          assert(optional('(', token.next));
+          assert(optional('(', token.next!));
         }
-        next = token.next;
+        next = token.next!;
       } else if (optional('(', next)) {
         if (typeArg == noTypeParamOrArg) {
           listener.handleNoTypeArguments(next);
@@ -5047,8 +5182,8 @@
         token = parseArguments(token);
         listener.handleSend(beginToken, token);
         Token bangToken = token;
-        if (optional('!', token.next)) {
-          bangToken = token.next;
+        if (optional('!', token.next!)) {
+          bangToken = token.next!;
         }
         typeArg = computeMethodTypeArguments(bangToken);
         if (typeArg != noTypeParamOrArg) {
@@ -5057,9 +5192,9 @@
             listener.handleNonNullAssertExpression(bangToken);
           }
           token = typeArg.parseArguments(bangToken, this);
-          assert(optional('(', token.next));
+          assert(optional('(', token.next!));
         }
-        next = token.next;
+        next = token.next!;
       } else {
         break;
       }
@@ -5068,7 +5203,7 @@
   }
 
   Token parsePrimary(Token token, IdentifierContext context) {
-    final int kind = token.next.kind;
+    final int kind = token.next!.kind;
     if (kind == IDENTIFIER_TOKEN) {
       return parseSendOrFunctionLiteral(token, context);
     } else if (kind == INT_TOKEN || kind == HEXADECIMAL_TOKEN) {
@@ -5080,7 +5215,7 @@
     } else if (kind == HASH_TOKEN) {
       return parseLiteralSymbol(token);
     } else if (kind == KEYWORD_TOKEN) {
-      final String value = token.next.stringValue;
+      final String? value = token.next!.stringValue;
       if (identical(value, "true") || identical(value, "false")) {
         return parseLiteralBool(token);
       } else if (identical(value, "null")) {
@@ -5100,11 +5235,11 @@
         // Fall through to the recovery code.
       } else if (identical(value, "assert")) {
         return parseAssert(token, Assert.Expression);
-      } else if (token.next.isIdentifier) {
+      } else if (token.next!.isIdentifier) {
         return parseSendOrFunctionLiteral(token, context);
       } else if (identical(value, "return")) {
         // Recovery
-        token = token.next;
+        token = token.next!;
         reportRecoverableErrorWithToken(token, codes.templateUnexpectedToken);
         return parsePrimary(token, context);
       } else {
@@ -5113,11 +5248,11 @@
     } else if (kind == OPEN_PAREN_TOKEN) {
       return parseParenthesizedExpressionOrFunctionLiteral(token);
     } else if (kind == OPEN_SQUARE_BRACKET_TOKEN ||
-        optional('[]', token.next)) {
-      listener.handleNoTypeArguments(token.next);
+        optional('[]', token.next!)) {
+      listener.handleNoTypeArguments(token.next!);
       return parseLiteralListSuffix(token, /* constKeyword = */ null);
     } else if (kind == OPEN_CURLY_BRACKET_TOKEN) {
-      listener.handleNoTypeArguments(token.next);
+      listener.handleNoTypeArguments(token.next!);
       return parseLiteralSetOrMapSuffix(token, /* constKeyword = */ null);
     } else if (kind == LT_TOKEN) {
       return parseLiteralListSetMapOrFunction(token, /* constKeyword = */ null);
@@ -5131,9 +5266,9 @@
   }
 
   Token parseParenthesizedExpressionOrFunctionLiteral(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     assert(optional('(', next));
-    Token nextToken = next.endGroup.next;
+    Token nextToken = next.endGroup!.next!;
     int kind = nextToken.kind;
     if (mayParseFunctionExpressions) {
       if ((identical(kind, FUNCTION_TOKEN) ||
@@ -5150,7 +5285,7 @@
         // If there is a stray simple identifier in the function expression
         // because the user is typing (e.g. `() asy {}`) then continue parsing
         // and allow parseFunctionExpression to report an unexpected token.
-        kind = nextToken.next.kind;
+        kind = nextToken.next!.kind;
         if ((identical(kind, FUNCTION_TOKEN) ||
             identical(kind, OPEN_CURLY_BRACKET_TOKEN))) {
           listener.handleNoTypeVariables(next);
@@ -5166,7 +5301,7 @@
   }
 
   Token ensureParenthesizedCondition(Token token) {
-    Token openParen = token.next;
+    Token openParen = token.next!;
     if (!optional('(', openParen)) {
       // Recover
       reportRecoverableError(
@@ -5179,19 +5314,19 @@
   }
 
   Token parseParenthesizedExpression(Token token) {
-    Token begin = token.next;
+    Token begin = token.next!;
     token = parseExpressionInParenthesis(token);
     listener.handleParenthesizedExpression(begin);
     return token;
   }
 
   Token parseExpressionInParenthesis(Token token) {
-    return parseExpressionInParenthesisRest(token.next);
+    return parseExpressionInParenthesisRest(token.next!);
   }
 
   Token parseExpressionInParenthesisRest(Token token) {
     assert(optional('(', token));
-    BeginToken begin = token;
+    BeginToken begin = token as BeginToken;
     token = parseExpression(token);
     token = ensureCloseParen(token, begin);
     assert(optional(')', token));
@@ -5199,29 +5334,29 @@
   }
 
   Token parseThisExpression(Token token, IdentifierContext context) {
-    Token thisToken = token = token.next;
+    Token thisToken = token = token.next!;
     assert(optional('this', thisToken));
     listener.handleThisExpression(thisToken, context);
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('(', next)) {
       // Constructor forwarding.
       listener.handleNoTypeArguments(next);
       token = parseArguments(token);
-      listener.handleSend(thisToken, token.next);
+      listener.handleSend(thisToken, token.next!);
     }
     return token;
   }
 
   Token parseSuperExpression(Token token, IdentifierContext context) {
-    Token superToken = token = token.next;
+    Token superToken = token = token.next!;
     assert(optional('super', token));
     listener.handleSuperExpression(superToken, context);
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('(', next)) {
       // Super constructor.
       listener.handleNoTypeArguments(next);
       token = parseArguments(token);
-      listener.handleSend(superToken, token.next);
+      listener.handleSend(superToken, token.next!);
     } else if (optional("?.", next)) {
       reportRecoverableError(next, codes.messageSuperNullAware);
     }
@@ -5240,30 +5375,30 @@
   /// Provide a [constKeyword] if the literal is preceded by 'const', or `null`
   /// if not. This is a suffix parser because it is assumed that type arguments
   /// have been parsed, or `listener.handleNoTypeArguments` has been executed.
-  Token parseLiteralListSuffix(Token token, Token constKeyword) {
+  Token parseLiteralListSuffix(Token token, Token? constKeyword) {
     Token beforeToken = token;
-    Token beginToken = token = token.next;
+    Token beginToken = token = token.next!;
     assert(optional('[', token) || optional('[]', token));
     int count = 0;
     if (optional('[]', token)) {
-      token = rewriteSquareBrackets(beforeToken).next;
+      token = rewriteSquareBrackets(beforeToken).next!;
       listener.handleLiteralList(
           /* count = */ 0,
           token,
           constKeyword,
-          token.next);
-      return token.next;
+          token.next!);
+      return token.next!;
     }
     bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = true;
     while (true) {
-      Token next = token.next;
+      Token next = token.next!;
       if (optional(']', next)) {
         token = next;
         break;
       }
       int ifCount = 0;
-      LiteralEntryInfo info = computeLiteralEntry(token);
+      LiteralEntryInfo? info = computeLiteralEntry(token);
       while (info != null) {
         if (info.hasEntry) {
           token = parseExpression(token);
@@ -5273,7 +5408,7 @@
         ifCount += info.ifConditionDelta;
         info = info.computeNext(token);
       }
-      next = token.next;
+      next = token.next!;
       ++count;
       if (!optional(',', next)) {
         if (optional(']', next)) {
@@ -5283,15 +5418,15 @@
 
         // Recovery
         if (!looksLikeLiteralEntry(next)) {
-          if (beginToken.endGroup.isSynthetic) {
+          if (beginToken.endGroup!.isSynthetic) {
             // The scanner has already reported an error,
             // but inserted `]` in the wrong place.
-            token = rewriter.moveSynthetic(token, beginToken.endGroup);
+            token = rewriter.moveSynthetic(token, beginToken.endGroup!);
           } else {
             // Report an error and jump to the end of the list.
             reportRecoverableError(
                 next, codes.templateExpectedButGot.withArguments(']'));
-            token = beginToken.endGroup;
+            token = beginToken.endGroup!;
           }
           break;
         }
@@ -5312,10 +5447,10 @@
 
   /// This method parses the portion of a set or map literal that starts with
   /// the left curly brace when there are no leading type arguments.
-  Token parseLiteralSetOrMapSuffix(Token token, Token constKeyword) {
-    Token leftBrace = token = token.next;
+  Token parseLiteralSetOrMapSuffix(Token token, Token? constKeyword) {
+    Token leftBrace = token = token.next!;
     assert(optional('{', leftBrace));
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('}', next)) {
       listener.handleLiteralSetOrMap(/* count = */ 0, leftBrace, constKeyword,
           next, /* hasSetEntry = */ false);
@@ -5327,30 +5462,30 @@
     int count = 0;
     // TODO(danrubel): hasSetEntry parameter exists for replicating existing
     // behavior and will be removed once unified collection has been enabled
-    bool hasSetEntry;
+    bool? hasSetEntry;
 
     while (true) {
       int ifCount = 0;
-      LiteralEntryInfo info = computeLiteralEntry(token);
+      LiteralEntryInfo? info = computeLiteralEntry(token);
       if (info == simpleEntry) {
         // TODO(danrubel): Remove this section and use the while loop below
         // once hasSetEntry is no longer needed.
         token = parseExpression(token);
-        bool isMapEntry = optional(':', token.next);
+        bool isMapEntry = optional(':', token.next!);
         hasSetEntry ??= !isMapEntry;
         if (isMapEntry) {
-          Token colon = token.next;
+          Token colon = token.next!;
           token = parseExpression(colon);
-          listener.handleLiteralMapEntry(colon, token.next);
+          listener.handleLiteralMapEntry(colon, token.next!);
         }
       } else {
         while (info != null) {
           if (info.hasEntry) {
             token = parseExpression(token);
-            if (optional(':', token.next)) {
-              Token colon = token.next;
+            if (optional(':', token.next!)) {
+              Token colon = token.next!;
               token = parseExpression(colon);
-              listener.handleLiteralMapEntry(colon, token.next);
+              listener.handleLiteralMapEntry(colon, token.next!);
             }
           } else {
             token = info.parse(token, this);
@@ -5360,12 +5495,12 @@
         }
       }
       ++count;
-      next = token.next;
+      next = token.next!;
 
-      Token comma;
+      Token? comma;
       if (optional(',', next)) {
         comma = token = next;
-        next = token.next;
+        next = token.next!;
       }
       if (optional('}', next)) {
         listener.handleLiteralSetOrMap(
@@ -5390,7 +5525,7 @@
           reportRecoverableError(
               next, codes.templateExpectedButGot.withArguments('}'));
           // Scanner guarantees a closing curly bracket
-          next = leftBrace.endGroup;
+          next = leftBrace.endGroup!;
           listener.handleLiteralSetOrMap(
               count, leftBrace, constKeyword, next, hasSetEntry ?? false);
           mayParseFunctionExpressions = old;
@@ -5405,9 +5540,9 @@
   /// This is a suffix parser because it is assumed that type arguments have
   /// been parsed, or `listener.handleNoTypeArguments(..)` has been executed.
   Token parseLiteralFunctionSuffix(Token token) {
-    assert(optional('(', token.next));
+    assert(optional('(', token.next!));
     // Scanner ensures `(` has matching `)`.
-    Token next = token.next.endGroup.next;
+    Token next = token.next!.endGroup!.next!;
     int kind = next.kind;
     if (!identical(kind, FUNCTION_TOKEN) &&
         !identical(kind, OPEN_CURLY_BRACKET_TOKEN) &&
@@ -5428,12 +5563,12 @@
   ///       typeParameters formalParameterList functionBody
   /// Provide token for [constKeyword] if preceded by 'const', null if not.
   Token parseLiteralListSetMapOrFunction(
-      final Token start, Token constKeyword) {
-    assert(optional('<', start.next));
+      final Token start, Token? constKeyword) {
+    assert(optional('<', start.next!));
     TypeParamOrArgInfo typeParamOrArg =
         computeTypeParamOrArg(start, /* inDeclaration = */ true);
     Token token = typeParamOrArg.skip(start);
-    if (optional('(', token.next)) {
+    if (optional('(', token.next!)) {
       if (constKeyword != null) {
         reportRecoverableErrorWithToken(
             constKeyword, codes.templateUnexpectedToken);
@@ -5443,10 +5578,10 @@
     }
     // Note that parseArguments can rewrite the token stream!
     token = typeParamOrArg.parseArguments(start, this);
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('{', next)) {
       if (typeParamOrArg.typeArgumentCount > 2) {
-        reportRecoverableErrorWithEnd(start.next, token,
+        reportRecoverableErrorWithEnd(start.next!, token,
             codes.messageSetOrMapLiteralTooManyTypeArguments);
       }
       return parseLiteralSetOrMapSuffix(token, constKeyword);
@@ -5472,14 +5607,14 @@
     // Assume the listener rejects non-string keys.
     // TODO(brianwilkerson): Change the assumption above by moving error
     // checking into the parser, making it possible to recover.
-    LiteralEntryInfo info = computeLiteralEntry(token);
+    LiteralEntryInfo? info = computeLiteralEntry(token);
     while (info != null) {
       if (info.hasEntry) {
         token = parseExpression(token);
         Token colon = ensureColon(token);
         token = parseExpression(colon);
         // TODO remove unused 2nd parameter
-        listener.handleLiteralMapEntry(colon, token.next);
+        listener.handleLiteralMapEntry(colon, token.next!);
       } else {
         token = info.parse(token, this);
       }
@@ -5494,12 +5629,12 @@
     }
     TypeInfo typeInfo = computeType(token, /* required = */ false);
     Token beforeName = typeInfo.skipType(token);
-    Token name = beforeName.next;
+    Token name = beforeName.next!;
     if (name.isIdentifier) {
       TypeParamOrArgInfo typeParam = computeTypeParamOrArg(name);
-      Token next = typeParam.skip(name).next;
+      Token next = typeParam.skip(name).next!;
       if (optional('(', next)) {
-        if (looksLikeFunctionBody(next.endGroup.next)) {
+        if (looksLikeFunctionBody(next.endGroup!.next!)) {
           return parseFunctionLiteral(
               token, beforeName, name, typeInfo, typeParam, context);
         }
@@ -5509,7 +5644,7 @@
   }
 
   Token ensureArguments(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (!optional('(', next)) {
       reportRecoverableError(
           token, codes.templateExpectedAfterButGot.withArguments('('));
@@ -5519,7 +5654,7 @@
   }
 
   Token parseConstructorInvocationArguments(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (!optional('(', next)) {
       // Recovery: Check for invalid type parameters
       TypeParamOrArgInfo typeArg = computeTypeParamOrArg(token);
@@ -5531,7 +5666,7 @@
             token, codes.messageConstructorWithTypeArguments);
         token = typeArg.parseArguments(token, this);
         listener.handleInvalidTypeArguments(token);
-        next = token.next;
+        next = token.next!;
       }
       if (!optional('(', next)) {
         next = rewriter.insertParens(token, /* includeIdentifier = */ false);
@@ -5546,7 +5681,7 @@
   /// ;
   /// ```
   Token parseNewExpression(Token token) {
-    Token newKeyword = token.next;
+    Token newKeyword = token.next!;
     assert(optional('new', newKeyword));
     listener.beginNewExpression(newKeyword);
     token = parseConstructorReference(newKeyword);
@@ -5583,28 +5718,28 @@
   /// ;
   /// ```
   Token parseConstExpression(Token token) {
-    Token constKeyword = token = token.next;
+    Token constKeyword = token = token.next!;
     assert(optional('const', constKeyword));
-    Token next = token.next;
-    final String value = next.stringValue;
+    Token next = token.next!;
+    final String? value = next.stringValue;
     if ((identical(value, '[')) || (identical(value, '[]'))) {
       listener.beginConstLiteral(next);
       listener.handleNoTypeArguments(next);
       token = parseLiteralListSuffix(token, constKeyword);
-      listener.endConstLiteral(token.next);
+      listener.endConstLiteral(token.next!);
       return token;
     }
     if (identical(value, '{')) {
       listener.beginConstLiteral(next);
       listener.handleNoTypeArguments(next);
       token = parseLiteralSetOrMapSuffix(token, constKeyword);
-      listener.endConstLiteral(token.next);
+      listener.endConstLiteral(token.next!);
       return token;
     }
     if (identical(value, '<')) {
       listener.beginConstLiteral(next);
       token = parseLiteralListSetMapOrFunction(token, constKeyword);
-      listener.endConstLiteral(token.next);
+      listener.endConstLiteral(token.next!);
       return token;
     }
     listener.beginConstExpression(constKeyword);
@@ -5620,7 +5755,7 @@
   /// ;
   /// ```
   Token parseLiteralInt(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(identical(token.kind, INT_TOKEN) ||
         identical(token.kind, HEXADECIMAL_TOKEN));
     listener.handleLiteralInt(token);
@@ -5633,7 +5768,7 @@
   /// ;
   /// ```
   Token parseLiteralDouble(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(identical(token.kind, DOUBLE_TOKEN));
     listener.handleLiteralDouble(token);
     return token;
@@ -5646,12 +5781,12 @@
   /// ```
   Token parseLiteralString(Token token) {
     Token startToken = token;
-    assert(identical(token.next.kind, STRING_TOKEN));
+    assert(identical(token.next!.kind, STRING_TOKEN));
     bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = true;
     token = parseSingleLiteralString(token);
     int count = 1;
-    while (identical(token.next.kind, STRING_TOKEN)) {
+    while (identical(token.next!.kind, STRING_TOKEN)) {
       token = parseSingleLiteralString(token);
       count++;
     }
@@ -5668,10 +5803,10 @@
   /// ;
   /// ```
   Token parseLiteralSymbol(Token token) {
-    Token hashToken = token = token.next;
+    Token hashToken = token = token.next!;
     assert(optional('#', hashToken));
     listener.beginLiteralSymbol(hashToken);
-    Token next = token.next;
+    Token next = token.next!;
     if (next.isUserDefinableOperator) {
       listener.handleOperator(next);
       listener.endLiteralSymbol(hashToken, /* identifierCount = */ 1);
@@ -5683,10 +5818,10 @@
     } else {
       int count = 1;
       token = ensureIdentifier(token, IdentifierContext.literalSymbol);
-      while (optional('.', token.next)) {
+      while (optional('.', token.next!)) {
         count++;
         token = ensureIdentifier(
-            token.next, IdentifierContext.literalSymbolContinuation);
+            token.next!, IdentifierContext.literalSymbolContinuation);
       }
       listener.endLiteralSymbol(hashToken, count);
       return token;
@@ -5694,21 +5829,21 @@
   }
 
   Token parseSingleLiteralString(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(identical(token.kind, STRING_TOKEN));
     listener.beginLiteralString(token);
     // Parsing the prefix, for instance 'x of 'x${id}y${id}z'
     int interpolationCount = 0;
-    Token next = token.next;
+    Token next = token.next!;
     int kind = next.kind;
     while (kind != EOF_TOKEN) {
       if (identical(kind, STRING_INTERPOLATION_TOKEN)) {
         // Parsing ${expression}.
-        token = parseExpression(next).next;
+        token = parseExpression(next).next!;
         if (!optional('}', token)) {
           reportRecoverableError(
               token, codes.templateExpectedButGot.withArguments('}'));
-          token = next.endGroup;
+          token = next.endGroup!;
         }
         listener.handleInterpolationExpression(next, token);
       } else if (identical(kind, STRING_INTERPOLATION_IDENTIFIER_TOKEN)) {
@@ -5721,7 +5856,7 @@
       ++interpolationCount;
       // Parsing the infix/suffix, for instance y and z' of 'x${id}y${id}z'
       token = parseStringPart(token);
-      next = token.next;
+      next = token.next!;
       kind = next.kind;
     }
     listener.endLiteralString(interpolationCount, next);
@@ -5729,7 +5864,7 @@
   }
 
   Token parseIdentifierExpression(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (next.kind == KEYWORD_TOKEN && identical(next.stringValue, "this")) {
       listener.handleThisExpression(next, IdentifierContext.expression);
       return next;
@@ -5745,7 +5880,7 @@
   /// ;
   /// ```
   Token parseLiteralBool(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('false', token) || optional('true', token));
     listener.handleLiteralBool(token);
     return token;
@@ -5757,7 +5892,7 @@
   /// ;
   /// ```
   Token parseLiteralNull(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('null', token));
     listener.handleLiteralNull(token);
     return token;
@@ -5776,25 +5911,25 @@
     if (typeArg != noTypeParamOrArg) {
       token = typeArg.parseArguments(token, this);
     } else {
-      listener.handleNoTypeArguments(token.next);
+      listener.handleNoTypeArguments(token.next!);
     }
     token = parseArgumentsOpt(token);
-    listener.handleSend(beginToken, token.next);
+    listener.handleSend(beginToken, token.next!);
     return token;
   }
 
   Token skipArgumentsOpt(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     listener.handleNoArguments(next);
     if (optional('(', next)) {
-      return next.endGroup;
+      return next.endGroup!;
     } else {
       return token;
     }
   }
 
   Token parseArgumentsOpt(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     if (!optional('(', next)) {
       listener.handleNoArguments(next);
       return token;
@@ -5818,7 +5953,7 @@
   /// ;
   /// ```
   Token parseArguments(Token token) {
-    return parseArgumentsRest(token.next);
+    return parseArgumentsRest(token.next!);
   }
 
   Token parseArgumentsRest(Token token) {
@@ -5830,16 +5965,16 @@
     bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = true;
     while (true) {
-      Token next = token.next;
+      Token next = token.next!;
       if (optional(')', next)) {
         token = next;
         break;
       }
-      Token colon = null;
-      if (optional(':', next.next)) {
+      Token? colon = null;
+      if (optional(':', next.next!)) {
         token =
             ensureIdentifier(token, IdentifierContext.namedArgumentReference)
-                .next;
+                .next!;
         colon = token;
         hasSeenNamedArgument = true;
       } else if (hasSeenNamedArgument) {
@@ -5847,7 +5982,7 @@
         reportRecoverableError(next, codes.messagePositionalAfterNamedArgument);
       }
       token = parseExpression(token);
-      next = token.next;
+      next = token.next!;
       if (colon != null) listener.handleNamedArgument(colon);
       ++argumentCount;
       if (!optional(',', next)) {
@@ -5882,11 +6017,11 @@
   /// ;
   /// ```
   Token parseIsOperatorRest(Token token) {
-    Token operator = token = token.next;
+    Token operator = token = token.next!;
     assert(optional('is', operator));
-    Token not = null;
-    if (optional('!', token.next)) {
-      not = token = token.next;
+    Token? not = null;
+    if (optional('!', token.next!)) {
+      not = token = token.next!;
     }
     listener.beginIsOperatorType(operator);
     TypeInfo typeInfo = computeTypeAfterIsOrAs(token);
@@ -5899,7 +6034,7 @@
   TypeInfo computeTypeAfterIsOrAs(Token token) {
     TypeInfo typeInfo = computeType(token, /* required = */ true);
     if (typeInfo.isNullable) {
-      Token next = typeInfo.skipType(token).next;
+      Token next = typeInfo.skipType(token).next!;
       if (!isOneOfOrEof(
           next, const [')', '?', '??', ',', ';', ':', 'is', 'as', '..'])) {
         // TODO(danrubel): investigate other situations
@@ -5917,7 +6052,7 @@
   /// ;
   /// ```
   Token parseAsOperatorRest(Token token) {
-    Token operator = token = token.next;
+    Token operator = token = token.next!;
     assert(optional('as', operator));
     listener.beginAsOperatorType(operator);
     TypeInfo typeInfo = computeTypeAfterIsOrAs(token);
@@ -5929,20 +6064,20 @@
 
   Token skipChainedAsIsOperators(Token token) {
     while (true) {
-      Token next = token.next;
-      String value = next.stringValue;
+      Token next = token.next!;
+      String? value = next.stringValue;
       if (!identical(value, 'is') && !identical(value, 'as')) {
         return token;
       }
       // The is- and as-operators cannot be chained.
       // TODO(danrubel): Consider a better error message.
       reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
-      if (optional('!', next.next)) {
-        next = next.next;
+      if (optional('!', next.next!)) {
+        next = next.next!;
       }
       TypeInfo typeInfo = computeTypeAfterIsOrAs(next);
       token = typeInfo.skipType(next);
-      next = token.next;
+      next = token.next!;
       value = next.stringValue;
     }
   }
@@ -5951,16 +6086,16 @@
   /// without a return type.
   bool looksLikeLocalFunction(Token token) {
     if (token.isIdentifier) {
-      if (optional('<', token.next)) {
+      if (optional('<', token.next!)) {
         TypeParamOrArgInfo typeParam = computeTypeParamOrArg(token);
         if (typeParam == noTypeParamOrArg) {
           return false;
         }
         token = typeParam.skip(token);
       }
-      token = token.next;
+      token = token.next!;
       if (optional('(', token)) {
-        token = token.endGroup.next;
+        token = token.endGroup!.next!;
         return optional('{', token) ||
             optional('=>', token) ||
             optional('async', token) ||
@@ -5982,16 +6117,16 @@
   }
 
   Token parseExpressionStatementOrConstDeclaration(final Token start) {
-    Token constToken = start.next;
+    Token constToken = start.next!;
     assert(optional('const', constToken));
-    if (!isModifier(constToken.next)) {
+    if (!isModifier(constToken.next!)) {
       TypeInfo typeInfo = computeType(constToken, /* required = */ false);
       if (typeInfo == noType) {
-        Token next = constToken.next;
+        Token next = constToken.next!;
         if (!next.isIdentifier) {
           return parseExpressionStatement(start);
         }
-        next = next.next;
+        next = next.next!;
         if (!(optional('=', next) ||
             // Recovery
             next.isKeywordOrIdentifier ||
@@ -6027,28 +6162,28 @@
   Token parseExpressionStatementOrDeclaration(final Token start,
       [bool onlyParseVariableDeclarationStart = false]) {
     Token token = start;
-    Token next = token.next;
+    Token next = token.next!;
     if (optional('@', next)) {
       token = parseMetadataStar(token);
-      next = token.next;
+      next = token.next!;
     }
 
-    Token lateToken;
-    Token varFinalOrConst;
+    Token? lateToken;
+    Token? varFinalOrConst;
 
     if (isModifier(next)) {
       if (optional('var', next) ||
           optional('final', next) ||
           optional('const', next)) {
-        varFinalOrConst = token = token.next;
-        next = token.next;
+        varFinalOrConst = token = token.next!;
+        next = token.next!;
       } else if (optional('late', next)) {
         lateToken = token = next;
-        next = token.next;
+        next = token.next!;
         if (isModifier(next) &&
             (optional('var', next) || optional('final', next))) {
           varFinalOrConst = token = next;
-          next = token.next;
+          next = token.next!;
         }
       }
 
@@ -6059,12 +6194,10 @@
           ..varFinalOrConst = varFinalOrConst;
 
         token = context.parseVariableDeclarationModifiers(token);
-        next = token.next;
+        next = token.next!;
 
         lateToken = context.lateToken;
         varFinalOrConst = context.varFinalOrConst;
-
-        context = null;
       }
     }
 
@@ -6079,16 +6212,33 @@
 
   /// See [parseExpressionStatementOrDeclaration]
   Token parseExpressionStatementOrDeclarationAfterModifiers(
-      final Token beforeType,
-      final Token start,
-      final Token lateToken,
-      Token varFinalOrConst,
-      TypeInfo typeInfo,
+      Token beforeType,
+      Token start,
+      Token? lateToken,
+      Token? varFinalOrConst,
+      TypeInfo? typeInfo,
       bool onlyParseVariableDeclarationStart) {
+    // In simple cases check for bad 'late' modifier in non-nnbd-mode.
+    if (typeInfo == null &&
+        lateToken == null &&
+        varFinalOrConst == null &&
+        beforeType == start &&
+        _isUseOfLateInNonNNBD(beforeType.next!)) {
+      lateToken = beforeType.next!;
+      reportRecoverableErrorWithToken(
+          lateToken, codes.templateUnexpectedModifierInNonNnbd);
+      beforeType = start = beforeType.next!;
+
+      // The below doesn't parse modifiers, so we need to do it here.
+      ModifierRecoveryContext context = new ModifierRecoveryContext(this);
+      beforeType =
+          start = context.parseVariableDeclarationModifiers(beforeType);
+      varFinalOrConst = context.varFinalOrConst;
+    }
     typeInfo ??= computeType(beforeType, /* required = */ false);
 
     Token token = typeInfo.skipType(beforeType);
-    Token next = token.next;
+    Token next = token.next!;
 
     if (onlyParseVariableDeclarationStart) {
       if (lateToken != null) {
@@ -6105,17 +6255,17 @@
           reportRecoverableErrorWithToken(
               lateToken, codes.templateExtraneousModifier);
         }
-        if (!optional('@', start.next)) {
-          listener.beginMetadataStar(start.next);
+        if (!optional('@', start.next!)) {
+          listener.beginMetadataStar(start.next!);
           listener.endMetadataStar(/* count = */ 0);
         }
         Token beforeFormals =
             computeTypeParamOrArg(next).parseVariables(next, this);
-        listener.beginLocalFunctionDeclaration(start.next);
+        listener.beginLocalFunctionDeclaration(start.next!);
         token = typeInfo.parseType(beforeType, this);
         return parseNamedFunctionRest(
             token,
-            start.next,
+            start.next!,
             beforeFormals,
             /* isFunctionExpression = */ false);
       }
@@ -6131,7 +6281,7 @@
             next, codes.templateExpectedIdentifier.withArguments(next));
         next = rewriter.insertSyntheticIdentifier(next);
       }
-      Token afterIdentifier = next.next;
+      Token afterIdentifier = next.next!;
       //
       // found <typeref> `?` <identifier>
       // with no annotations or modifiers preceeding it
@@ -6145,7 +6295,7 @@
         listener = new ForwardingListener();
         // TODO(danrubel): consider using TokenStreamGhostWriter here
         Token afterExpression =
-            parseExpressionWithoutCascade(afterIdentifier).next;
+            parseExpressionWithoutCascade(afterIdentifier).next!;
         listener = originalListener;
 
         if (optional(':', afterExpression)) {
@@ -6153,7 +6303,7 @@
           // Drop the type information and reset the last consumed token.
           typeInfo = noType;
           token = start;
-          next = token.next;
+          next = token.next!;
         }
       } else if (!afterIdentifier.isKeyword &&
           !isOneOfOrEof(afterIdentifier, const [';', ',', ')'])) {
@@ -6161,7 +6311,7 @@
         // Drop the type information and reset the last consumed token.
         typeInfo = noType;
         token = start;
-        next = token.next;
+        next = token.next!;
       }
     }
 
@@ -6181,12 +6331,12 @@
       // Detect expressions such as identifier `as` identifier
       // and treat those as expressions.
       if (optional('as', next) || optional('is', next)) {
-        int kind = next.next.kind;
+        int kind = next.next!.kind;
         if (EQ_TOKEN != kind &&
             SEMICOLON_TOKEN != kind &&
             COMMA_TOKEN != kind) {
           if (onlyParseVariableDeclarationStart) {
-            if (!optional('in', next.next)) {
+            if (!optional('in', next.next!)) {
               return start;
             }
           } else {
@@ -6211,12 +6361,12 @@
       }
     }
 
-    if (!optional('@', start.next)) {
-      listener.beginMetadataStar(start.next);
+    if (!optional('@', start.next!)) {
+      listener.beginMetadataStar(start.next!);
       listener.endMetadataStar(/* count = */ 0);
     }
     token = typeInfo.parseType(beforeType, this);
-    next = token.next;
+    next = token.next!;
     listener.beginVariablesDeclaration(next, lateToken, varFinalOrConst);
     if (!onlyParseVariableDeclarationStart) {
       token =
@@ -6228,8 +6378,8 @@
   Token parseVariablesDeclarationRest(Token token, bool endWithSemicolon) {
     int count = 1;
     token = parseOptionallyInitializedIdentifier(token);
-    while (optional(',', token.next)) {
-      token = parseOptionallyInitializedIdentifier(token.next);
+    while (optional(',', token.next!)) {
+      token = parseOptionallyInitializedIdentifier(token.next!);
       ++count;
     }
     if (endWithSemicolon) {
@@ -6257,16 +6407,16 @@
   /// ;
   /// ```
   Token parseIfStatement(Token token) {
-    Token ifToken = token.next;
+    Token ifToken = token.next!;
     assert(optional('if', ifToken));
     listener.beginIfStatement(ifToken);
     token = ensureParenthesizedCondition(ifToken);
-    listener.beginThenStatement(token.next);
+    listener.beginThenStatement(token.next!);
     token = parseStatement(token);
     listener.endThenStatement(token);
-    Token elseToken = null;
-    if (optional('else', token.next)) {
-      elseToken = token.next;
+    Token? elseToken = null;
+    if (optional('else', token.next!)) {
+      elseToken = token.next!;
       listener.beginElseStatement(elseToken);
       token = parseStatement(elseToken);
       listener.endElseStatement(elseToken);
@@ -6292,16 +6442,16 @@
   ///   expression? ';'
   /// ;
   /// ```
-  Token parseForStatement(Token token, Token awaitToken) {
-    Token forToken = token = token.next;
+  Token parseForStatement(Token token, Token? awaitToken) {
+    Token forToken = token = token.next!;
     assert(awaitToken == null || optional('await', awaitToken));
     assert(optional('for', token));
     listener.beginForStatement(forToken);
 
     token = parseForLoopPartsStart(awaitToken, forToken);
-    Token identifier = token.next;
+    Token identifier = token.next!;
     token = parseForLoopPartsMid(token, awaitToken, forToken);
-    if (optional('in', token.next) || optional(':', token.next)) {
+    if (optional('in', token.next!) || optional(':', token.next!)) {
       // Process `for ( ... in ... )`
       return parseForInRest(token, awaitToken, forToken, identifier);
     } else {
@@ -6312,8 +6462,8 @@
 
   /// Parse the start of a for loop control structure
   /// from the open parenthesis up to but not including the identifier.
-  Token parseForLoopPartsStart(Token awaitToken, Token forToken) {
-    Token leftParenthesis = forToken.next;
+  Token parseForLoopPartsStart(Token? awaitToken, Token forToken) {
+    Token leftParenthesis = forToken.next!;
     if (!optional('(', leftParenthesis)) {
       // Recovery
       reportRecoverableError(
@@ -6322,7 +6472,7 @@
       BeginToken openParen = rewriter.insertToken(
           forToken,
           new SyntheticBeginToken(
-              TokenType.OPEN_PAREN, leftParenthesis.offset));
+              TokenType.OPEN_PAREN, leftParenthesis.offset)) as BeginToken;
 
       Token token;
       if (awaitToken != null) {
@@ -6353,25 +6503,25 @@
 
   /// Parse the remainder of the local variable declaration
   /// or an expression if no local variable declaration was found.
-  Token parseForLoopPartsMid(Token token, Token awaitToken, Token forToken) {
+  Token parseForLoopPartsMid(Token token, Token? awaitToken, Token forToken) {
     if (token != forToken.next) {
       token =
           parseVariablesDeclarationRest(token, /* endWithSemicolon = */ false);
       listener.handleForInitializerLocalVariableDeclaration(
-          token, optional('in', token.next) || optional(':', token.next));
-    } else if (optional(';', token.next)) {
-      listener.handleForInitializerEmptyStatement(token.next);
+          token, optional('in', token.next!) || optional(':', token.next!));
+    } else if (optional(';', token.next!)) {
+      listener.handleForInitializerEmptyStatement(token.next!);
     } else {
       token = parseExpression(token);
       listener.handleForInitializerExpressionStatement(
           token,
-          optional('in', token.next) ||
-              optional(':', token.next) ||
+          optional('in', token.next!) ||
+              optional(':', token.next!) ||
               // If this is an empty `await for`, we rewrite it into an
               // `await for (_ in _)`.
-              (awaitToken != null && optional(')', token.next)));
+              (awaitToken != null && optional(')', token.next!)));
     }
-    Token next = token.next;
+    Token next = token.next!;
     if (optional(';', next)) {
       if (awaitToken != null) {
         reportRecoverableError(awaitToken, codes.messageInvalidAwaitFor);
@@ -6401,37 +6551,37 @@
   ///    | identifier 'in' expression
   /// ;
   /// ```
-  Token parseForRest(Token awaitToken, Token token, Token forToken) {
+  Token parseForRest(Token? awaitToken, Token token, Token forToken) {
     token = parseForLoopPartsRest(token, forToken, awaitToken);
-    listener.beginForStatementBody(token.next);
+    listener.beginForStatementBody(token.next!);
     LoopState savedLoopState = loopState;
     loopState = LoopState.InsideLoop;
     token = parseStatement(token);
     loopState = savedLoopState;
-    listener.endForStatementBody(token.next);
-    listener.endForStatement(token.next);
+    listener.endForStatementBody(token.next!);
+    listener.endForStatement(token.next!);
     return token;
   }
 
-  Token parseForLoopPartsRest(Token token, Token forToken, Token awaitToken) {
-    Token leftParenthesis = forToken.next;
+  Token parseForLoopPartsRest(Token token, Token forToken, Token? awaitToken) {
+    Token leftParenthesis = forToken.next!;
     assert(optional('for', forToken));
     assert(optional('(', leftParenthesis));
 
     Token leftSeparator = ensureSemicolon(token);
-    if (optional(';', leftSeparator.next)) {
+    if (optional(';', leftSeparator.next!)) {
       token = parseEmptyStatement(leftSeparator);
     } else {
       token = parseExpressionStatement(leftSeparator);
     }
     int expressionCount = 0;
     while (true) {
-      Token next = token.next;
+      Token next = token.next!;
       if (optional(')', next)) {
         token = next;
         break;
       }
-      token = parseExpression(token).next;
+      token = parseExpression(token).next!;
       ++expressionCount;
       if (!optional(',', token)) {
         break;
@@ -6439,7 +6589,7 @@
     }
     if (token != leftParenthesis.endGroup) {
       reportRecoverableErrorWithToken(token, codes.templateUnexpectedToken);
-      token = leftParenthesis.endGroup;
+      token = leftParenthesis.endGroup!;
     }
     listener.handleForLoopParts(
         forToken, leftParenthesis, leftSeparator, expressionCount);
@@ -6459,23 +6609,23 @@
   /// ;
   /// ```
   Token parseForInRest(
-      Token token, Token awaitToken, Token forToken, Token identifier) {
+      Token token, Token? awaitToken, Token forToken, Token identifier) {
     token = parseForInLoopPartsRest(token, awaitToken, forToken, identifier);
-    listener.beginForInBody(token.next);
+    listener.beginForInBody(token.next!);
     LoopState savedLoopState = loopState;
     loopState = LoopState.InsideLoop;
     token = parseStatement(token);
     loopState = savedLoopState;
-    listener.endForInBody(token.next);
-    listener.endForIn(token.next);
+    listener.endForInBody(token.next!);
+    listener.endForIn(token.next!);
     return token;
   }
 
   Token parseForInLoopPartsRest(
-      Token token, Token awaitToken, Token forToken, Token identifier) {
-    Token inKeyword = token.next;
+      Token token, Token? awaitToken, Token forToken, Token identifier) {
+    Token inKeyword = token.next!;
     assert(optional('for', forToken));
-    assert(optional('(', forToken.next));
+    assert(optional('(', forToken.next!));
     assert(optional('in', inKeyword) || optional(':', inKeyword));
 
     if (!identifier.isIdentifier) {
@@ -6484,24 +6634,24 @@
       reportRecoverableErrorWithToken(
           identifier, codes.templateExpectedIdentifier);
     } else if (identifier != token) {
-      if (optional('=', identifier.next)) {
+      if (optional('=', identifier.next!)) {
         reportRecoverableError(
-            identifier.next, codes.messageInitializedVariableInForEach);
+            identifier.next!, codes.messageInitializedVariableInForEach);
       } else {
         reportRecoverableErrorWithToken(
-            identifier.next, codes.templateUnexpectedToken);
+            identifier.next!, codes.templateUnexpectedToken);
       }
     } else if (awaitToken != null && !inAsync) {
       // TODO(danrubel): consider reporting the error on awaitToken
       reportRecoverableError(inKeyword, codes.messageAwaitForNotAsync);
     }
 
-    listener.beginForInExpression(inKeyword.next);
+    listener.beginForInExpression(inKeyword.next!);
     token = parseExpression(inKeyword);
-    token = ensureCloseParen(token, forToken.next);
+    token = ensureCloseParen(token, forToken.next!);
     listener.endForInExpression(token);
     listener.handleForInLoopParts(
-        awaitToken, forToken, forToken.next, inKeyword);
+        awaitToken, forToken, forToken.next!, inKeyword);
     return token;
   }
 
@@ -6511,17 +6661,17 @@
   /// ;
   /// ```
   Token parseWhileStatement(Token token) {
-    Token whileToken = token.next;
+    Token whileToken = token.next!;
     assert(optional('while', whileToken));
     listener.beginWhileStatement(whileToken);
     token = ensureParenthesizedCondition(whileToken);
-    listener.beginWhileStatementBody(token.next);
+    listener.beginWhileStatementBody(token.next!);
     LoopState savedLoopState = loopState;
     loopState = LoopState.InsideLoop;
     token = parseStatement(token);
     loopState = savedLoopState;
-    listener.endWhileStatementBody(token.next);
-    listener.endWhileStatement(whileToken, token.next);
+    listener.endWhileStatementBody(token.next!);
+    listener.endWhileStatement(whileToken, token.next!);
     return token;
   }
 
@@ -6531,16 +6681,16 @@
   /// ;
   /// ```
   Token parseDoWhileStatement(Token token) {
-    Token doToken = token.next;
+    Token doToken = token.next!;
     assert(optional('do', doToken));
     listener.beginDoWhileStatement(doToken);
-    listener.beginDoWhileStatementBody(doToken.next);
+    listener.beginDoWhileStatementBody(doToken.next!);
     LoopState savedLoopState = loopState;
     loopState = LoopState.InsideLoop;
     token = parseStatement(doToken);
     loopState = savedLoopState;
     listener.endDoWhileStatementBody(token);
-    Token whileToken = token.next;
+    Token whileToken = token.next!;
     if (!optional('while', whileToken)) {
       reportRecoverableError(
           whileToken, codes.templateExpectedButGot.withArguments('while'));
@@ -6562,27 +6712,27 @@
         ensureBlock(token, /* template = */ null, blockKind.missingBlockName);
     listener.beginBlock(begin, blockKind);
     int statementCount = 0;
-    Token startToken = token.next;
+    Token startToken = token.next!;
     while (notEofOrValue('}', startToken)) {
       token = parseStatement(token);
-      if (identical(token.next, startToken)) {
+      if (identical(token.next!, startToken)) {
         // No progress was made, so we report the current token as being invalid
         // and move forward.
-        token = token.next;
+        token = token.next!;
         reportRecoverableError(
             token, codes.templateUnexpectedToken.withArguments(token));
       }
       ++statementCount;
-      startToken = token.next;
+      startToken = token.next!;
     }
-    token = token.next;
+    token = token.next!;
     assert(token.isEof || optional('}', token));
     listener.endBlock(statementCount, begin, token, blockKind);
     return token;
   }
 
   Token parseInvalidBlock(Token token) {
-    Token begin = token.next;
+    Token begin = token.next!;
     assert(optional('{', begin));
     // Parse and report the invalid block, but suppress errors
     // because an error has already been reported by the caller.
@@ -6602,11 +6752,11 @@
     //  does not modify the token stream. For now, use simple look ahead and
     //  ensure no false positives.
 
-    token = token.next;
+    token = token.next!;
     if (token.isIdentifier) {
-      token = token.next;
+      token = token.next!;
       if (optional('(', token)) {
-        token = token.endGroup.next;
+        token = token.endGroup!.next!;
         if (isOneOf(token, [';', '.', '..', '?', '?.'])) {
           return true;
         }
@@ -6632,7 +6782,7 @@
   /// Determine if the following tokens look like an 'await' expression
   /// and not a local variable or local function declaration.
   bool looksLikeAwaitExpression(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('await', token));
 
     return looksLikeExpression(token);
@@ -6641,7 +6791,7 @@
   /// Determine if the following tokens look like a 'yield' expression and not a
   /// local variable or local function declaration.
   bool looksLikeYieldStatement(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('yield', token));
 
     return looksLikeExpression(token);
@@ -6653,17 +6803,17 @@
   /// ;
   /// ```
   Token parseAwaitExpression(Token token, bool allowCascades) {
-    Token awaitToken = token.next;
+    Token awaitToken = token.next!;
     assert(optional('await', awaitToken));
     listener.beginAwaitExpression(awaitToken);
     token = parsePrecedenceExpression(
         awaitToken, POSTFIX_PRECEDENCE, allowCascades);
     if (inAsync) {
-      listener.endAwaitExpression(awaitToken, token.next);
+      listener.endAwaitExpression(awaitToken, token.next!);
     } else {
       codes.MessageCode errorCode = codes.messageAwaitNotAsync;
       reportRecoverableError(awaitToken, errorCode);
-      listener.endInvalidAwaitExpression(awaitToken, token.next, errorCode);
+      listener.endInvalidAwaitExpression(awaitToken, token.next!, errorCode);
     }
     return token;
   }
@@ -6678,23 +6828,23 @@
   /// ;
   /// ```
   Token parseThrowExpression(Token token, bool allowCascades) {
-    Token throwToken = token.next;
+    Token throwToken = token.next!;
     assert(optional('throw', throwToken));
-    if (optional(';', throwToken.next)) {
+    if (optional(';', throwToken.next!)) {
       // TODO(danrubel): Find a better way to intercept the parseExpression
       // recovery to generate this error message rather than explicitly
       // checking the next token as we are doing here.
       reportRecoverableError(
-          throwToken.next, codes.messageMissingExpressionInThrow);
+          throwToken.next!, codes.messageMissingExpressionInThrow);
       rewriter.insertToken(
           throwToken,
           new SyntheticStringToken(TokenType.STRING, '""',
-              throwToken.next.charOffset, /* _length = */ 0));
+              throwToken.next!.charOffset, /* _length = */ 0));
     }
     token = allowCascades
         ? parseExpression(throwToken)
         : parseExpressionWithoutCascade(throwToken);
-    listener.handleThrowExpression(throwToken, token.next);
+    listener.handleThrowExpression(throwToken, token.next!);
     return token;
   }
 
@@ -6704,7 +6854,7 @@
   /// ;
   /// ```
   Token parseRethrowStatement(Token token) {
-    Token throwToken = token.next;
+    Token throwToken = token.next!;
     assert(optional('rethrow', throwToken));
     listener.beginRethrowStatement(throwToken);
     token = ensureSemicolon(throwToken);
@@ -6731,47 +6881,47 @@
   /// ;
   /// ```
   Token parseTryStatement(Token token) {
-    Token tryKeyword = token.next;
+    Token tryKeyword = token.next!;
     assert(optional('try', tryKeyword));
     listener.beginTryStatement(tryKeyword);
     Token lastConsumed = parseBlock(tryKeyword, BlockKind.tryStatement);
-    token = lastConsumed.next;
+    token = lastConsumed.next!;
     int catchCount = 0;
 
-    String value = token.stringValue;
+    String? value = token.stringValue;
     while (identical(value, 'catch') || identical(value, 'on')) {
       listener.beginCatchClause(token);
-      Token onKeyword = null;
+      Token? onKeyword = null;
       if (identical(value, 'on')) {
         // 'on' type catchPart?
         onKeyword = token;
         lastConsumed = computeType(token, /* required = */ true)
             .ensureTypeNotVoid(token, this);
-        token = lastConsumed.next;
+        token = lastConsumed.next!;
         value = token.stringValue;
       }
-      Token catchKeyword = null;
-      Token comma = null;
+      Token? catchKeyword = null;
+      Token? comma = null;
       if (identical(value, 'catch')) {
         catchKeyword = token;
 
-        Token openParens = catchKeyword.next;
+        Token openParens = catchKeyword.next!;
         if (!optional("(", openParens)) {
           reportRecoverableError(openParens, codes.messageCatchSyntax);
           openParens = rewriter.insertParens(
               catchKeyword, /* includeIdentifier = */ true);
         }
 
-        Token exceptionName = openParens.next;
+        Token exceptionName = openParens.next!;
         if (exceptionName.kind != IDENTIFIER_TOKEN) {
           exceptionName = IdentifierContext.catchParameter
               .ensureIdentifier(openParens, this);
         }
 
-        if (optional(")", exceptionName.next)) {
+        if (optional(")", exceptionName.next!)) {
           // OK: `catch (identifier)`.
         } else {
-          comma = exceptionName.next;
+          comma = exceptionName.next!;
           if (!optional(",", comma)) {
             // Recovery
             if (!exceptionName.isSynthetic) {
@@ -6799,9 +6949,9 @@
             //   } catch (e) {}
             //   _s_.f();
 
-            if (openParens.endGroup.isSynthetic) {
+            if (openParens.endGroup!.isSynthetic) {
               // The scanner did not place the synthetic ')' correctly.
-              rewriter.moveSynthetic(exceptionName, openParens.endGroup);
+              rewriter.moveSynthetic(exceptionName, openParens.endGroup!);
               comma = null;
             } else {
               comma =
@@ -6809,40 +6959,40 @@
             }
           }
           if (comma != null) {
-            Token traceName = comma.next;
+            Token traceName = comma.next!;
             if (traceName.kind != IDENTIFIER_TOKEN) {
               traceName = IdentifierContext.catchParameter
                   .ensureIdentifier(comma, this);
             }
-            if (!optional(")", traceName.next)) {
+            if (!optional(")", traceName.next!)) {
               // Recovery
               if (!traceName.isSynthetic) {
                 reportRecoverableError(
-                    traceName.next, codes.messageCatchSyntaxExtraParameters);
+                    traceName.next!, codes.messageCatchSyntaxExtraParameters);
               }
-              if (openParens.endGroup.isSynthetic) {
+              if (openParens.endGroup!.isSynthetic) {
                 // The scanner did not place the synthetic ')' correctly.
-                rewriter.moveSynthetic(traceName, openParens.endGroup);
+                rewriter.moveSynthetic(traceName, openParens.endGroup!);
               }
             }
           }
         }
         lastConsumed = parseFormalParameters(catchKeyword, MemberKind.Catch);
-        token = lastConsumed.next;
+        token = lastConsumed.next!;
       }
       listener.endCatchClause(token);
       lastConsumed = parseBlock(lastConsumed, BlockKind.catchClause);
-      token = lastConsumed.next;
+      token = lastConsumed.next!;
       ++catchCount;
       listener.handleCatchBlock(onKeyword, catchKeyword, comma);
       value = token.stringValue; // while condition
     }
 
-    Token finallyKeyword = null;
+    Token? finallyKeyword = null;
     if (optional('finally', token)) {
       finallyKeyword = token;
       lastConsumed = parseBlock(token, BlockKind.finallyClause);
-      token = lastConsumed.next;
+      token = lastConsumed.next!;
       listener.handleFinallyBlock(finallyKeyword);
     } else {
       if (catchCount == 0) {
@@ -6859,7 +7009,7 @@
   /// ;
   /// ```
   Token parseSwitchStatement(Token token) {
-    Token switchKeyword = token.next;
+    Token switchKeyword = token.next!;
     assert(optional('switch', switchKeyword));
     listener.beginSwitchStatement(switchKeyword);
     token = ensureParenthesizedCondition(switchKeyword);
@@ -6883,35 +7033,35 @@
         token = ensureBlock(token, /* template = */ null, 'switch statement');
     listener.beginSwitchBlock(beginSwitch);
     int caseCount = 0;
-    Token defaultKeyword = null;
-    Token colonAfterDefault = null;
-    while (notEofOrValue('}', token.next)) {
-      Token beginCase = token.next;
+    Token? defaultKeyword = null;
+    Token? colonAfterDefault = null;
+    while (notEofOrValue('}', token.next!)) {
+      Token beginCase = token.next!;
       int expressionCount = 0;
       int labelCount = 0;
       Token peek = peekPastLabels(beginCase);
       while (true) {
         // Loop until we find something that can't be part of a switch case.
-        String value = peek.stringValue;
+        String? value = peek.stringValue;
         if (identical(value, 'default')) {
-          while (!identical(token.next, peek)) {
+          while (!identical(token.next!, peek)) {
             token = parseLabel(token);
             labelCount++;
           }
           if (defaultKeyword != null) {
             reportRecoverableError(
-                token.next, codes.messageSwitchHasMultipleDefaults);
+                token.next!, codes.messageSwitchHasMultipleDefaults);
           }
-          defaultKeyword = token.next;
+          defaultKeyword = token.next!;
           colonAfterDefault = token = ensureColon(defaultKeyword);
-          peek = token.next;
+          peek = token.next!;
           break;
         } else if (identical(value, 'case')) {
-          while (!identical(token.next, peek)) {
+          while (!identical(token.next!, peek)) {
             token = parseLabel(token);
             labelCount++;
           }
-          Token caseKeyword = token.next;
+          Token caseKeyword = token.next!;
           if (defaultKeyword != null) {
             reportRecoverableError(
                 caseKeyword, codes.messageSwitchHasCaseAfterDefault);
@@ -6922,18 +7072,18 @@
           listener.endCaseExpression(token);
           listener.handleCaseMatch(caseKeyword, token);
           expressionCount++;
-          peek = peekPastLabels(token.next);
+          peek = peekPastLabels(token.next!);
         } else if (expressionCount > 0) {
           break;
         } else {
           // Recovery
           reportRecoverableError(
               peek, codes.templateExpectedToken.withArguments("case"));
-          Token endGroup = beginSwitch.endGroup;
+          Token endGroup = beginSwitch.endGroup!;
           while (token.next != endGroup) {
-            token = token.next;
+            token = token.next!;
           }
-          peek = peekPastLabels(token.next);
+          peek = peekPastLabels(token.next!);
           break;
         }
       }
@@ -6941,7 +7091,7 @@
           expressionCount, defaultKeyword, colonAfterDefault);
       ++caseCount;
     }
-    token = token.next;
+    token = token.next!;
     listener.endSwitchBlock(caseCount, beginSwitch, token);
     assert(token.isEof || optional('}', token));
     return token;
@@ -6951,8 +7101,8 @@
   /// is used to determine if the labels belong to a statement or a
   /// switch case.
   Token peekPastLabels(Token token) {
-    while (token.isIdentifier && optional(':', token.next)) {
-      token = token.next.next;
+    while (token.isIdentifier && optional(':', token.next!)) {
+      token = token.next!.next!;
     }
     return token;
   }
@@ -6964,22 +7114,22 @@
       Token begin,
       int labelCount,
       int expressionCount,
-      Token defaultKeyword,
-      Token colonAfterDefault) {
+      Token? defaultKeyword,
+      Token? colonAfterDefault) {
     listener.beginSwitchCase(labelCount, expressionCount, begin);
     // Finally zero or more statements.
     int statementCount = 0;
-    while (!identical(token.next.kind, EOF_TOKEN)) {
-      String value = peek.stringValue;
+    while (!identical(token.next!.kind, EOF_TOKEN)) {
+      String? value = peek.stringValue;
       if ((identical(value, 'case')) ||
           (identical(value, 'default')) ||
-          ((identical(value, '}')) && (identical(token.next, peek)))) {
+          ((identical(value, '}')) && (identical(token.next!, peek)))) {
         // A label just before "}" will be handled as a statement error.
         break;
       } else {
-        Token startToken = token.next;
+        Token startToken = token.next!;
         token = parseStatement(token);
-        Token next = token.next;
+        Token next = token.next!;
         if (identical(next, startToken)) {
           // No progress was made, so we report the current token as being
           // invalid and move forward.
@@ -6989,10 +7139,10 @@
         }
         ++statementCount;
       }
-      peek = peekPastLabels(token.next);
+      peek = peekPastLabels(token.next!);
     }
     listener.endSwitchCase(labelCount, expressionCount, defaultKeyword,
-        colonAfterDefault, statementCount, begin, token.next);
+        colonAfterDefault, statementCount, begin, token.next!);
     return token;
   }
 
@@ -7002,10 +7152,10 @@
   /// ;
   /// ```
   Token parseBreakStatement(Token token) {
-    Token breakKeyword = token = token.next;
+    Token breakKeyword = token = token.next!;
     assert(optional('break', breakKeyword));
     bool hasTarget = false;
-    if (token.next.isIdentifier) {
+    if (token.next!.isIdentifier) {
       token = ensureIdentifier(token, IdentifierContext.labelReference);
       hasTarget = true;
     } else if (!isBreakAllowed) {
@@ -7022,11 +7172,11 @@
   /// ;
   /// ```
   Token parseAssert(Token token, Assert kind) {
-    token = token.next;
+    token = token.next!;
     assert(optional('assert', token));
     listener.beginAssert(token, kind);
     Token assertKeyword = token;
-    Token leftParenthesis = token.next;
+    Token leftParenthesis = token.next!;
     if (!optional('(', leftParenthesis)) {
       // Recovery
       reportRecoverableError(
@@ -7035,24 +7185,24 @@
           rewriter.insertParens(token, /* includeIdentifier = */ true);
     }
     token = leftParenthesis;
-    Token commaToken = null;
+    Token? commaToken = null;
     bool old = mayParseFunctionExpressions;
     mayParseFunctionExpressions = true;
 
     token = parseExpression(token);
-    if (optional(',', token.next)) {
-      token = token.next;
-      if (!optional(')', token.next)) {
+    if (optional(',', token.next!)) {
+      token = token.next!;
+      if (!optional(')', token.next!)) {
         commaToken = token;
         token = parseExpression(token);
-        if (optional(',', token.next)) {
+        if (optional(',', token.next!)) {
           // Trailing comma is ignored.
-          token = token.next;
+          token = token.next!;
         }
       }
     }
 
-    Token endGroup = leftParenthesis.endGroup;
+    Token endGroup = leftParenthesis.endGroup!;
     if (token.next == endGroup) {
       token = endGroup;
     } else {
@@ -7062,7 +7212,7 @@
         token = rewriter.moveSynthetic(token, endGroup);
       } else {
         reportRecoverableErrorWithToken(
-            token.next, codes.templateUnexpectedToken);
+            token.next!, codes.templateUnexpectedToken);
         token = endGroup;
       }
     }
@@ -7075,7 +7225,7 @@
       ensureSemicolon(token);
     }
     listener.endAssert(
-        assertKeyword, kind, leftParenthesis, commaToken, token.next);
+        assertKeyword, kind, leftParenthesis, commaToken, token.next!);
     return token;
   }
 
@@ -7085,9 +7235,9 @@
   /// ;
   /// ```
   Token parseAssertStatement(Token token) {
-    assert(optional('assert', token.next));
+    assert(optional('assert', token.next!));
     // parseAssert ensures that there is a trailing semicolon.
-    return parseAssert(token, Assert.Statement).next;
+    return parseAssert(token, Assert.Statement).next!;
   }
 
   /// ```
@@ -7096,10 +7246,10 @@
   /// ;
   /// ```
   Token parseContinueStatement(Token token) {
-    Token continueKeyword = token = token.next;
+    Token continueKeyword = token = token.next!;
     assert(optional('continue', continueKeyword));
     bool hasTarget = false;
-    if (token.next.isIdentifier) {
+    if (token.next!.isIdentifier) {
       token = ensureIdentifier(token, IdentifierContext.labelReference);
       hasTarget = true;
       if (!isContinueWithLabelAllowed) {
@@ -7124,7 +7274,7 @@
   /// ;
   /// ```
   Token parseEmptyStatement(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional(';', token));
     listener.handleEmptyStatement(token);
     return token;
@@ -7133,10 +7283,10 @@
   /// Given a token ([beforeToken]) that is known to be before another [token],
   /// return the token that is immediately before the [token].
   Token previousToken(Token beforeToken, Token token) {
-    Token next = beforeToken.next;
+    Token next = beforeToken.next!;
     while (next != token && next != beforeToken) {
       beforeToken = next;
-      next = beforeToken.next;
+      next = beforeToken.next!;
     }
     return beforeToken;
   }
@@ -7146,29 +7296,29 @@
   /// (and events have already been generated).
   Token parseInvalidOperatorDeclaration(
       Token beforeStart,
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       Token beforeType,
       DeclarationKind kind,
-      String enclosingDeclarationName) {
+      String? enclosingDeclarationName) {
     TypeInfo typeInfo = computeType(
         beforeStart, /* required = */ false, /* inDeclaration = */ true);
     Token beforeName = typeInfo.skipType(beforeType);
-    Token next = beforeName.next;
+    Token next = beforeName.next!;
 
     if (optional('operator', next)) {
-      next = next.next;
+      next = next.next!;
     } else {
       // The 'operator' keyword is missing, but we may or may not have a type
       // before the token that is the actual operator.
       Token operator = next;
-      if (!next.isOperator && next.next.isOperator) {
+      if (!next.isOperator && next.next!.isOperator) {
         beforeName = next;
-        operator = next.next;
+        operator = next.next!;
       }
       reportRecoverableError(operator, codes.messageMissingOperatorKeyword);
       rewriter.insertSyntheticKeyword(beforeName, Keyword.OPERATOR);
@@ -7177,14 +7327,14 @@
       typeInfo = computeType(
           beforeStart, /* required = */ true, /* inDeclaration = */ true);
       beforeName = typeInfo.skipType(beforeType);
-      next = beforeName.next;
+      next = beforeName.next!;
 
       // The 'next' token can be the just-inserted 'operator' keyword.
       // If it is, change it so it points to the actual operator.
       if (!next.isOperator &&
-          next.next.isOperator &&
+          next.next!.isOperator &&
           identical(next.stringValue, 'operator')) {
-        next = next.next;
+        next = next.next!;
       }
     }
 
@@ -7203,7 +7353,7 @@
         beforeType,
         typeInfo,
         /* getOrSet = */ null,
-        beforeName.next,
+        beforeName.next!,
         kind,
         enclosingDeclarationName,
         /* nameIsRecovered = */ false);
@@ -7217,19 +7367,19 @@
   Token recoverFromInvalidMember(
       Token token,
       Token beforeStart,
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       Token beforeType,
       TypeInfo typeInfo,
-      Token getOrSet,
+      Token? getOrSet,
       DeclarationKind kind,
-      String enclosingDeclarationName) {
-    Token next = token.next;
-    String value = next.stringValue;
+      String? enclosingDeclarationName) {
+    Token next = token.next!;
+    String? value = next.stringValue;
 
     if (identical(value, 'class')) {
       return reportAndSkipClassInClass(next);
@@ -7266,7 +7416,7 @@
           beforeType,
           typeInfo,
           getOrSet,
-          token.next,
+          token.next!,
           kind,
           enclosingDeclarationName,
           /* nameIsRecovered = */ false);
@@ -7289,7 +7439,7 @@
           varFinalOrConst,
           beforeType,
           typeInfo,
-          token.next,
+          token.next!,
           kind,
           enclosingDeclarationName,
           /* nameIsRecovered = */ false);
@@ -7302,14 +7452,14 @@
   /// Report that the nesting depth of the code being parsed is too large for
   /// the parser to safely handle. Return the next `}` or EOF.
   Token recoverFromStackOverflow(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     reportRecoverableError(next, codes.messageStackOverflow);
     next = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
     listener.handleEmptyStatement(next);
 
     while (notEofOrValue('}', next)) {
       token = next;
-      next = token.next;
+      next = token.next!;
     }
     return token;
   }
@@ -7336,20 +7486,20 @@
   Token reportAllErrorTokens(Token token) {
     while (token is ErrorToken) {
       listener.handleErrorToken(token);
-      token = token.next;
+      token = token.next!;
     }
     return token;
   }
 
   Token skipErrorTokens(Token token) {
     while (token is ErrorToken) {
-      token = token.next;
+      token = token.next!;
     }
     return token;
   }
 
   Token parseInvalidTopLevelDeclaration(Token token) {
-    Token next = token.next;
+    Token next = token.next!;
     reportRecoverableErrorWithToken(
         next,
         optional(';', next)
@@ -7366,19 +7516,19 @@
     assert(optional('class', token));
     reportRecoverableError(token, codes.messageClassInClass);
     listener.handleInvalidMember(token);
-    Token next = token.next;
+    Token next = token.next!;
     // If the declaration appears to be a valid class declaration
     // then skip the entire declaration so that we only generate the one
     // error (above) rather than a plethora of unhelpful errors.
     if (next.isIdentifier) {
       // skip class name
       token = next;
-      next = token.next;
+      next = token.next!;
       // TODO(danrubel): consider parsing (skipping) the class header
       // with a recovery listener so that no events are generated
       if (optional('{', next) && next.endGroup != null) {
         // skip class body
-        token = next.endGroup;
+        token = next.endGroup!;
       }
     }
     listener.endMember();
@@ -7389,19 +7539,19 @@
     assert(optional('enum', token));
     reportRecoverableError(token, codes.messageEnumInClass);
     listener.handleInvalidMember(token);
-    Token next = token.next;
+    Token next = token.next!;
     // If the declaration appears to be a valid enum declaration
     // then skip the entire declaration so that we only generate the one
     // error (above) rather than a plethora of unhelpful errors.
     if (next.isIdentifier) {
       // skip enum name
       token = next;
-      next = token.next;
+      next = token.next!;
       if (optional('{', next) && next.endGroup != null) {
         // TODO(danrubel): Consider replacing this `skip enum` functionality
         // with something that can parse and resolve the declaration
         // even though it is in a class context
-        token = next.endGroup;
+        token = next.endGroup!;
       }
     }
     listener.endMember();
@@ -7435,7 +7585,7 @@
     // use and return the last token consumed and the `previous` field
     // has been removed.
     if (token.previous != null) {
-      return token.previous;
+      return token.previous!;
     }
     Token before = new Token.eof(/* offset = */ -1);
     before.next = token;
@@ -7444,9 +7594,9 @@
 
   /// Return the first dartdoc comment token preceding the given token
   /// or `null` if no dartdoc token is found.
-  Token findDartDoc(Token token) {
-    Token comments = token.precedingComments;
-    Token dartdoc = null;
+  Token? findDartDoc(Token token) {
+    Token? comments = token.precedingComments;
+    Token? dartdoc = null;
     bool isMultiline = false;
     while (comments != null) {
       String lexeme = comments.lexeme;
@@ -7513,7 +7663,7 @@
   /// Parse the comment references in a sequence of single line comment tokens
   /// where [token] is the first comment token in the sequence.
   /// Return the number of comment references parsed.
-  int parseReferencesInSingleLineComments(Token token) {
+  int parseReferencesInSingleLineComments(Token? token) {
     int count = 0;
     bool inCodeBlock = false;
     while (token != null && !token.isEof) {
@@ -7612,45 +7762,45 @@
   /// Return `true` if a comment reference was successfully parsed.
   bool parseOneCommentReference(Token token, int referenceOffset) {
     Token begin = token;
-    Token newKeyword = null;
+    Token? newKeyword = null;
     if (optional('new', token)) {
       newKeyword = token;
-      token = token.next;
+      token = token.next!;
     }
-    Token prefix, period;
-    if (token.isIdentifier && optional('.', token.next)) {
+    Token? prefix, period;
+    if (token.isIdentifier && optional('.', token.next!)) {
       prefix = token;
-      period = token.next;
-      token = period.next;
+      period = token.next!;
+      token = period.next!;
     }
     if (token.isEof) {
       // Recovery: Insert a synthetic identifier for code completion
       token = rewriter.insertSyntheticIdentifier(
           period ?? newKeyword ?? syntheticPreviousToken(token));
-      if (begin == token.next) {
+      if (begin == token.next!) {
         begin = token;
       }
     }
-    Token operatorKeyword = null;
+    Token? operatorKeyword = null;
     if (optional('operator', token)) {
       operatorKeyword = token;
-      token = token.next;
+      token = token.next!;
     }
     if (token.isUserDefinableOperator) {
-      if (token.next.isEof) {
+      if (token.next!.isEof) {
         parseOneCommentReferenceRest(
             begin, referenceOffset, newKeyword, prefix, period, token);
         return true;
       }
     } else {
       token = operatorKeyword ?? token;
-      if (token.next.isEof) {
+      if (token.next!.isEof) {
         if (token.isIdentifier) {
           parseOneCommentReferenceRest(
               begin, referenceOffset, newKeyword, prefix, period, token);
           return true;
         }
-        Keyword keyword = token.keyword;
+        Keyword? keyword = token.keyword;
         if (newKeyword == null &&
             prefix == null &&
             (keyword == Keyword.THIS ||
@@ -7672,15 +7822,15 @@
   void parseOneCommentReferenceRest(
       Token begin,
       int referenceOffset,
-      Token newKeyword,
-      Token prefix,
-      Token period,
+      Token? newKeyword,
+      Token? prefix,
+      Token? period,
       Token identifierOrOperator) {
     // Adjust the token offsets to match the enclosing comment token.
     Token token = begin;
     do {
       token.offset += referenceOffset;
-      token = token.next;
+      token = token.next!;
     } while (!token.isEof);
 
     listener.handleCommentReference(
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/quote.dart b/pkg/_fe_analyzer_shared/lib/src/parser/quote.dart
index a33410d..0d5b048 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/quote.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/quote.dart
@@ -102,7 +102,6 @@
     case Quote.RawMultiLineDouble:
       return lengthOfOptionalWhitespacePrefix(first, /* start = */ 4);
   }
-  return throw new UnsupportedError("'$quote' in  firstQuoteLength");
 }
 
 int lastQuoteLength(Quote quote) {
@@ -119,7 +118,6 @@
     case Quote.RawMultiLineDouble:
       return 3;
   }
-  return throw new UnsupportedError("'$quote' in lastQuoteLength");
 }
 
 String unescapeFirstStringPart(String first, Quote quote, Object location,
@@ -176,7 +174,6 @@
           : unescapeCodeUnits(
               string.codeUnits, /* isRaw = */ true, location, listener);
   }
-  return throw new UnsupportedError("'$quote' in unescape");
 }
 
 // Note: based on
@@ -184,7 +181,7 @@
 String unescapeCodeUnits(List<int> codeUnits, bool isRaw, Object location,
     UnescapeErrorListener listener) {
   // Can't use Uint8List or Uint16List here, the code units may be larger.
-  List<int> result = new List<int>.filled(codeUnits.length, null);
+  List<int> result = new List<int>.filled(codeUnits.length, 0);
   int resultOffset = 0;
 
   for (int i = 0; i < codeUnits.length; i++) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/recovery_listeners.dart b/pkg/_fe_analyzer_shared/lib/src/parser/recovery_listeners.dart
index 9320871..5c24c53 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/recovery_listeners.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/recovery_listeners.dart
@@ -7,9 +7,9 @@
 import 'forwarding_listener.dart' show ForwardingListener;
 
 class ClassHeaderRecoveryListener extends ForwardingListener {
-  Token extendsKeyword;
-  Token implementsKeyword;
-  Token withKeyword;
+  Token? extendsKeyword;
+  Token? implementsKeyword;
+  Token? withKeyword;
 
   void clear() {
     extendsKeyword = null;
@@ -18,14 +18,14 @@
   }
 
   @override
-  void handleClassExtends(Token extendsKeyword, int typeCount) {
+  void handleClassExtends(Token? extendsKeyword, int typeCount) {
     this.extendsKeyword = extendsKeyword;
     super.handleClassExtends(extendsKeyword, typeCount);
   }
 
   @override
   void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
+      Token? implementsKeyword, int interfacesCount) {
     this.implementsKeyword = implementsKeyword;
     super.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
   }
@@ -38,9 +38,9 @@
 }
 
 class ImportRecoveryListener extends ForwardingListener {
-  Token asKeyword;
-  Token deferredKeyword;
-  Token ifKeyword;
+  Token? asKeyword;
+  Token? deferredKeyword;
+  Token? ifKeyword;
   bool hasCombinator = false;
 
   void clear() {
@@ -50,7 +50,7 @@
     hasCombinator = false;
   }
 
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token? equalSign) {
     this.ifKeyword = ifKeyword;
     super.endConditionalUri(ifKeyword, leftParen, equalSign);
   }
@@ -65,7 +65,7 @@
     super.endShow(showKeyword);
   }
 
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
     this.deferredKeyword = deferredKeyword;
     this.asKeyword = asKeyword;
     super.handleImportPrefix(deferredKeyword, asKeyword);
@@ -73,8 +73,8 @@
 }
 
 class MixinHeaderRecoveryListener extends ForwardingListener {
-  Token onKeyword;
-  Token implementsKeyword;
+  Token? onKeyword;
+  Token? implementsKeyword;
 
   void clear() {
     onKeyword = null;
@@ -83,13 +83,13 @@
 
   @override
   void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
+      Token? implementsKeyword, int interfacesCount) {
     this.implementsKeyword = implementsKeyword;
     super.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
   }
 
   @override
-  void handleMixinOn(Token onKeyword, int typeCount) {
+  void handleMixinOn(Token? onKeyword, int typeCount) {
     this.onKeyword = onKeyword;
     super.handleMixinOn(onKeyword, typeCount);
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
index 6462add..ce64454 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
@@ -75,7 +75,7 @@
   final Stack stack = debugStack ? new DebugStack() : new StackImpl();
 
   /// Used to report an internal error encountered in the stack listener.
-  dynamic internalProblem(Message message, int charOffset, Uri uri);
+  Never internalProblem(Message message, int charOffset, Uri uri);
 
   /// Checks that [value] matches the expected [kind].
   ///
@@ -84,15 +84,17 @@
   ///     assert(checkValue(token, ValueKind.Token, value));
   ///
   /// to document and validate the expected value kind.
-  bool checkValue(Token token, ValueKind kind, Object value) {
+  bool checkValue(Token? token, ValueKind kind, Object value) {
     if (!kind.check(value)) {
       String message = 'Unexpected value `${value}` (${value.runtimeType}). '
           'Expected ${kind}.';
       if (token != null) {
         // If offset is available report and internal problem to show the
         // parsed code in the output.
-        throw internalProblem(new Message(/* code = */ null, message: message),
-            token.charOffset, uri);
+        throw internalProblem(
+            new Message(const Code<String>('Internal error'), message: message),
+            token.charOffset,
+            uri);
       } else {
         throw message;
       }
@@ -110,12 +112,12 @@
   ///
   /// to document the expected stack and get earlier errors on unexpected stack
   /// content.
-  bool checkState(Token token, List<ValueKind> kinds) {
+  bool checkState(Token? token, List<ValueKind> kinds) {
     bool success = true;
     for (int kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
       ValueKind kind = kinds[kindIndex];
       if (kindIndex < stack.length) {
-        Object value = stack[kindIndex];
+        Object? value = stack[kindIndex];
         if (!kind.check(value)) {
           success = false;
         }
@@ -126,7 +128,7 @@
     if (!success) {
       StringBuffer sb = new StringBuffer();
 
-      String safeToString(Object object) {
+      String safeToString(Object? object) {
         try {
           return '$object';
         } catch (e) {
@@ -160,7 +162,7 @@
         }
         sb.write(padLeft(kindIndex, 4));
         sb.write(': ');
-        ValueKind kind;
+        ValueKind? kind;
         if (kindIndex < kinds.length) {
           kind = kinds[kindIndex];
           sb.write(padRight(kind, 60));
@@ -168,7 +170,7 @@
           sb.write(padRight('---', 60));
         }
         if (kindIndex < stack.length) {
-          Object value = stack[kindIndex];
+          Object? value = stack[kindIndex];
           if (kind == null || kind.check(value)) {
             sb.write(' ');
           } else {
@@ -191,8 +193,10 @@
       if (token != null) {
         // If offset is available report and internal problem to show the
         // parsed code in the output.
-        throw internalProblem(new Message(/* code = */ null, message: message),
-            token.charOffset, uri);
+        throw internalProblem(
+            new Message(const Code<String>('Internal error'), message: message),
+            token.charOffset,
+            uri);
       } else {
         throw message;
       }
@@ -209,7 +213,7 @@
     }
   }
 
-  void push(Object node) {
+  void push(Object? node) {
     if (node == null) {
       internalProblem(
           templateInternalProblemUnhandled.withArguments("null", "push"),
@@ -219,17 +223,17 @@
     stack.push(node);
   }
 
-  void pushIfNull(Token tokenOrNull, NullValue nullValue) {
+  void pushIfNull(Token? tokenOrNull, NullValue nullValue) {
     if (tokenOrNull == null) stack.push(nullValue);
   }
 
-  Object peek() => stack.isNotEmpty ? stack.last : null;
+  Object? peek() => stack.isNotEmpty ? stack.last : null;
 
-  Object pop([NullValue nullValue]) {
+  Object? pop([NullValue? nullValue]) {
     return stack.pop(nullValue);
   }
 
-  Object popIfNotNull(Object value) {
+  Object? popIfNotNull(Object? value) {
     return value == null ? null : pop();
   }
 
@@ -239,7 +243,7 @@
 
   void printEvent(String name) {
     print('\n------------------');
-    for (Object o in stack.values) {
+    for (Object? o in stack.values) {
       String s = "  $o";
       int index = s.indexOf("\n");
       if (index != -1) {
@@ -306,17 +310,17 @@
   }
 
   @override
-  void handleClassExtends(Token extendsKeyword, int typeCount) {
+  void handleClassExtends(Token? extendsKeyword, int typeCount) {
     debugEvent("ClassExtends");
   }
 
   @override
-  void handleMixinOn(Token onKeyword, int typeCount) {
+  void handleMixinOn(Token? onKeyword, int typeCount) {
     debugEvent("MixinOn");
   }
 
   @override
-  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+  void handleClassHeader(Token begin, Token classKeyword, Token? nativeToken) {
     debugEvent("ClassHeader");
   }
 
@@ -337,7 +341,7 @@
 
   @override
   void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
+      Token? implementsKeyword, int interfacesCount) {
     debugEvent("ClassImplements");
   }
 
@@ -424,7 +428,7 @@
   void endLiteralString(int interpolationCount, Token endToken) {
     debugEvent("endLiteralString");
     if (interpolationCount == 0) {
-      Token token = pop();
+      Token token = pop() as Token;
       push(unescapeString(token.lexeme, token, this));
     } else {
       internalProblem(
@@ -498,39 +502,39 @@
 abstract class Stack {
   /// Pops [count] elements from the stack and puts it into [list].
   /// Returns [null] if a [ParserRecovery] value is found, or [list] otherwise.
-  List<Object> popList(int count, List<Object> list, NullValue nullValue);
+  List<T?>? popList<T>(int count, List<T?> list, NullValue? nullValue);
 
   void push(Object value);
 
   /// Will return [null] instead of [NullValue].
-  Object get last;
+  Object? get last;
 
   bool get isNotEmpty;
 
-  List<Object> get values;
+  List<Object?> get values;
 
-  Object pop(NullValue nullValue);
+  Object? pop(NullValue? nullValue);
 
   int get length;
 
   /// Raw, i.e. [NullValue]s will be returned instead of [null].
-  Object operator [](int index);
+  Object? operator [](int index);
 }
 
 class StackImpl implements Stack {
-  List<Object> array = new List<Object>.filled(/* length = */ 8, null);
+  List<Object?> array = new List<Object?>.filled(/* length = */ 8, null);
   int arrayLength = 0;
 
   bool get isNotEmpty => arrayLength > 0;
 
   int get length => arrayLength;
 
-  Object get last {
-    final Object value = array[arrayLength - 1];
+  Object? get last {
+    final Object? value = array[arrayLength - 1];
     return value is NullValue ? null : value;
   }
 
-  Object operator [](int index) {
+  Object? operator [](int index) {
     return array[arrayLength - 1 - index];
   }
 
@@ -541,9 +545,9 @@
     }
   }
 
-  Object pop(NullValue nullValue) {
+  Object? pop(NullValue? nullValue) {
     assert(arrayLength > 0);
-    final Object value = array[--arrayLength];
+    final Object? value = array[--arrayLength];
     array[arrayLength] = null;
     if (value is! NullValue) {
       return value;
@@ -554,15 +558,15 @@
     }
   }
 
-  List<Object> popList(int count, List<Object> list, NullValue nullValue) {
+  List<T?>? popList<T>(int count, List<T?> list, NullValue? nullValue) {
     assert(arrayLength >= count);
-    final List<Object> array = this.array;
+    final List<Object?> array = this.array;
     final int length = arrayLength;
     final int startIndex = length - count;
     bool isParserRecovery = false;
     for (int i = 0; i < count; i++) {
       int arrayIndex = startIndex + i;
-      final Object value = array[arrayIndex];
+      final Object? value = array[arrayIndex];
       array[arrayIndex] = null;
       if (value is NullValue && nullValue == null ||
           identical(value, nullValue)) {
@@ -571,7 +575,7 @@
         isParserRecovery = true;
       } else {
         assert(value is! NullValue);
-        list[i] = value;
+        list[i] = value as T;
       }
     }
     arrayLength -= count;
@@ -579,16 +583,16 @@
     return isParserRecovery ? null : list;
   }
 
-  List<Object> get values {
+  List<Object?> get values {
     final int length = arrayLength;
-    final List<Object> list = new List<Object>.filled(length, null);
+    final List<Object?> list = new List<Object?>.filled(length, null);
     list.setRange(/* start = */ 0, length, array);
     return list;
   }
 
   void _grow() {
     final int length = array.length;
-    final List<Object> newArray = new List<Object>.filled(length * 2, null);
+    final List<Object?> newArray = new List<Object?>.filled(length * 2, null);
     newArray.setRange(/* start = */ 0, length, array, /* skipCount = */ 0);
     array = newArray;
   }
@@ -600,10 +604,10 @@
   List<StackTrace> latestStacktraces = <StackTrace>[];
 
   @override
-  Object operator [](int index) {
-    Object result = realStack[index];
+  Object? operator [](int index) {
+    Object? result = realStack[index];
     latestStacktraces.clear();
-    latestStacktraces.add(stackTraceStack[index]);
+    latestStacktraces.add(stackTraceStack[index] as StackTrace);
     return result;
   }
 
@@ -611,8 +615,8 @@
   bool get isNotEmpty => realStack.isNotEmpty;
 
   @override
-  Object get last {
-    Object result = this[0];
+  Object? get last {
+    Object? result = this[0];
     if (result is NullValue) return null;
     return result;
   }
@@ -621,16 +625,17 @@
   int get length => realStack.length;
 
   @override
-  Object pop(NullValue nullValue) {
-    Object result = realStack.pop(nullValue);
+  Object? pop(NullValue? nullValue) {
+    Object? result = realStack.pop(nullValue);
     latestStacktraces.clear();
-    latestStacktraces.add(stackTraceStack.pop(/* nullValue = */ null));
+    latestStacktraces
+        .add(stackTraceStack.pop(/* nullValue = */ null) as StackTrace);
     return result;
   }
 
   @override
-  List<Object> popList(int count, List<Object> list, NullValue nullValue) {
-    List<Object> result = realStack.popList(count, list, nullValue);
+  List<T?>? popList<T>(int count, List<T?> list, NullValue? nullValue) {
+    List<T?>? result = realStack.popList(count, list, nullValue);
     latestStacktraces.length = count;
     stackTraceStack.popList(count, latestStacktraces, /* nullValue = */ null);
     return result;
@@ -643,7 +648,7 @@
   }
 
   @override
-  List<Object> get values => realStack.values;
+  List<Object?> get values => realStack.values;
 }
 
 /// Helper constant for popping a list of the top of a [Stack].  This helper
@@ -652,16 +657,16 @@
 class FixedNullableList<T> {
   const FixedNullableList();
 
-  List<T> pop(Stack stack, int count, [NullValue nullValue]) {
+  List<T?>? pop(Stack stack, int count, [NullValue? nullValue]) {
     if (count == 0) return null;
-    return stack.popList(count, new List<T>.filled(count, null), nullValue);
+    return stack.popList(count, new List<T?>.filled(count, null), nullValue);
   }
 
-  List<T> popPadded(Stack stack, int count, int padding,
-      [NullValue nullValue]) {
+  List<T?>? popPadded(Stack stack, int count, int padding,
+      [NullValue? nullValue]) {
     if (count + padding == 0) return null;
     return stack.popList(
-        count, new List<T>.filled(count + padding, null), nullValue);
+        count, new List<T?>.filled(count + padding, null), nullValue);
   }
 }
 
@@ -670,10 +675,10 @@
 class GrowableList<T> {
   const GrowableList();
 
-  List<T> pop(Stack stack, int count, [NullValue nullValue]) {
+  List<T?>? pop(Stack stack, int count, [NullValue? nullValue]) {
     return stack.popList(
         count,
-        new List<T>.filled(count, /* fill = */ null, growable: true),
+        new List<T?>.filled(count, /* fill = */ null, growable: true),
         nullValue);
   }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
index 7868ae5..7c367b8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
@@ -23,7 +23,12 @@
   /// open parenthesis. If [insertIdentifier] is true, then a synthetic
   /// identifier is included between the open and close parenthesis.
   Token insertParens(Token token, bool includeIdentifier) {
-    Token next = token.next;
+    // Assert that the token is not eof, though allow an eof-token if the offset
+    // is negative. The last part is because [syntheticPreviousToken] sometimes
+    // creates eof tokens that aren't the real eof-token that has a negative
+    // offset (which wouldn't be valid for the real eof).
+    assert(!token.isEof || token.offset < 0);
+    Token next = token.next!;
     int offset = next.charOffset;
     BeginToken leftParen =
         next = new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
@@ -35,7 +40,7 @@
     }
     next = _setNext(next, new SyntheticToken(TokenType.CLOSE_PAREN, offset));
     _setEndGroup(leftParen, next);
-    _setNext(next, token.next);
+    _setNext(next, token.next!);
 
     // A no-op rewriter could skip this step.
     _setNext(token, leftParen);
@@ -45,7 +50,12 @@
 
   /// Insert [newToken] after [token] and return [newToken].
   Token insertToken(Token token, Token newToken) {
-    _setNext(newToken, token.next);
+    // Assert that the token is not eof, though allow an eof-token if the offset
+    // is negative. The last part is because [syntheticPreviousToken] sometimes
+    // creates eof tokens that aren't the real eof-token that has a negative
+    // offset (which wouldn't be valid for the real eof).
+    assert(!token.isEof || token.offset < 0);
+    _setNext(newToken, token.next!);
 
     // A no-op rewriter could skip this step.
     _setNext(token, newToken);
@@ -56,18 +66,24 @@
   /// Move [endGroup] (a synthetic `)`, `]`, or `}` token) and associated
   /// error token after [token] in the token stream and return [endGroup].
   Token moveSynthetic(Token token, Token endGroup) {
+    // Assert that the token is not eof, though allow an eof-token if the offset
+    // is negative. The last part is because [syntheticPreviousToken] sometimes
+    // creates eof tokens that aren't the real eof-token that has a negative
+    // offset (which wouldn't be valid for the real eof).
+    assert(!token.isEof || token.offset < 0);
+    // ignore:unnecessary_null_comparison
     assert(endGroup.beforeSynthetic != null);
     if (token == endGroup) return endGroup;
-    Token errorToken;
+    Token? errorToken;
     if (endGroup.next is UnmatchedToken) {
       errorToken = endGroup.next;
     }
 
     // Remove endGroup from its current location
-    _setNext(endGroup.beforeSynthetic, (errorToken ?? endGroup).next);
+    _setNext(endGroup.beforeSynthetic!, (errorToken ?? endGroup).next!);
 
     // Insert endGroup into its new location
-    Token next = token.next;
+    Token next = token.next!;
     _setNext(token, endGroup);
     _setNext(errorToken ?? endGroup, next);
     _setOffset(endGroup, next.offset);
@@ -82,13 +98,13 @@
   /// the chain of tokens starting at the [replacementToken]. Return the
   /// [replacementToken].
   Token replaceTokenFollowing(Token previousToken, Token replacementToken) {
-    Token replacedToken = previousToken.next;
+    Token replacedToken = previousToken.next!;
     _setNext(previousToken, replacementToken);
 
     _setPrecedingComments(
         replacementToken as SimpleToken, replacedToken.precedingComments);
 
-    _setNext(_lastTokenInChain(replacementToken), replacedToken.next);
+    _setNext(_lastTokenInChain(replacementToken), replacedToken.next!);
 
     return replacementToken;
   }
@@ -99,14 +115,14 @@
   /// As a side-effect, this method also ensures that the tokens in the chain
   /// have their `previous` pointers set correctly.
   Token _lastTokenInChain(Token firstToken) {
-    Token previous;
+    Token? previous;
     Token current = firstToken;
-    while (current.next != null && current.next.type != TokenType.EOF) {
+    while (current.next != null && current.next!.type != TokenType.EOF) {
       if (previous != null) {
         _setPrevious(current, previous);
       }
       previous = current;
-      current = current.next;
+      current = current.next!;
     }
     if (previous != null) {
       _setPrevious(current, previous);
@@ -126,39 +142,39 @@
 
     // [token] <--> [a] <--> [b]
     ReplacementToken replacement =
-        new ReplacementToken(newTokenType, previousToken.next);
+        new ReplacementToken(newTokenType, previousToken.next!);
     insertToken(previousToken, replacement);
     // [token] <--> [replacement] <--> [a] <--> [b]
-    _setNext(replacement, replacement.next.next);
+    _setNext(replacement, replacement.next!.next!);
     // [token] <--> [replacement] <--> [b]
 
     return replacement;
   }
 
   /// Insert a synthetic identifier after [token] and return the new identifier.
-  Token insertSyntheticIdentifier(Token token, [String value]) {
+  Token insertSyntheticIdentifier(Token token, [String value = '']) {
     return insertToken(
         token,
-        new SyntheticStringToken(TokenType.IDENTIFIER, value ?? '',
-            token.next.charOffset, /* _length = */ 0));
+        new SyntheticStringToken(TokenType.IDENTIFIER, value,
+            token.next!.charOffset, /* _length = */ 0));
   }
 
   /// Insert a new synthetic [keyword] after [token] and return the new token.
   Token insertSyntheticKeyword(Token token, Keyword keyword) => insertToken(
-      token, new SyntheticKeywordToken(keyword, token.next.charOffset));
+      token, new SyntheticKeywordToken(keyword, token.next!.charOffset));
 
   /// Insert a new simple synthetic token of [newTokenType] after [token]
   /// and return the new token.
   Token insertSyntheticToken(Token token, TokenType newTokenType) {
     assert(newTokenType is! Keyword, 'use insertSyntheticKeyword instead');
     return insertToken(
-        token, new SyntheticToken(newTokenType, token.next.charOffset));
+        token, new SyntheticToken(newTokenType, token.next!.charOffset));
   }
 
   Token _setNext(Token setOn, Token nextToken);
   void _setEndGroup(BeginToken setOn, Token endGroup);
   void _setOffset(Token setOn, int offset);
-  void _setPrecedingComments(SimpleToken setOn, CommentToken comment);
+  void _setPrecedingComments(SimpleToken setOn, CommentToken? comment);
   void _setPrevious(Token setOn, Token previous);
 }
 
@@ -197,7 +213,7 @@
     setOn.offset = offset;
   }
 
-  void _setPrecedingComments(SimpleToken setOn, CommentToken comment) {
+  void _setPrecedingComments(SimpleToken setOn, CommentToken? comment) {
     setOn.precedingComments = comment;
   }
 
@@ -211,11 +227,11 @@
 }
 
 class NextTokenStreamChange implements TokenStreamChange {
-  Token setOn;
-  Token setOnNext;
-  Token nextToken;
-  Token nextTokenPrevious;
-  Token nextTokenBeforeSynthetic;
+  late Token setOn;
+  Token? setOnNext;
+  late Token nextToken;
+  Token? nextTokenPrevious;
+  Token? nextTokenBeforeSynthetic;
 
   NextTokenStreamChange(UndoableTokenStreamRewriter rewriter) {
     rewriter._changes.add(this);
@@ -244,8 +260,8 @@
 }
 
 class EndGroupTokenStreamChange implements TokenStreamChange {
-  BeginToken setOn;
-  Token endGroup;
+  late BeginToken setOn;
+  Token? endGroup;
 
   EndGroupTokenStreamChange(UndoableTokenStreamRewriter rewriter) {
     rewriter._changes.add(this);
@@ -265,8 +281,8 @@
 }
 
 class OffsetTokenStreamChange implements TokenStreamChange {
-  Token setOn;
-  int offset;
+  late Token setOn;
+  late int offset;
 
   OffsetTokenStreamChange(UndoableTokenStreamRewriter rewriter) {
     rewriter._changes.add(this);
@@ -286,14 +302,14 @@
 }
 
 class PrecedingCommentsTokenStreamChange implements TokenStreamChange {
-  SimpleToken setOn;
-  CommentToken comment;
+  late SimpleToken setOn;
+  CommentToken? comment;
 
   PrecedingCommentsTokenStreamChange(UndoableTokenStreamRewriter rewriter) {
     rewriter._changes.add(this);
   }
 
-  void setPrecedingComments(SimpleToken setOn, CommentToken comment) {
+  void setPrecedingComments(SimpleToken setOn, CommentToken? comment) {
     this.setOn = setOn;
     this.comment = setOn.precedingComments;
 
@@ -307,8 +323,8 @@
 }
 
 class PreviousTokenStreamChange implements TokenStreamChange {
-  Token setOn;
-  Token previous;
+  late Token setOn;
+  late Token previous;
 
   PreviousTokenStreamChange(UndoableTokenStreamRewriter rewriter) {
     rewriter._changes.add(this);
@@ -316,7 +332,7 @@
 
   void setPrevious(Token setOn, Token previous) {
     this.setOn = setOn;
-    this.previous = setOn.previous;
+    this.previous = setOn.previous!;
 
     setOn.previous = previous;
   }
@@ -357,7 +373,7 @@
   }
 
   @override
-  void _setPrecedingComments(SimpleToken setOn, CommentToken comment) {
+  void _setPrecedingComments(SimpleToken setOn, CommentToken? comment) {
     new PrecedingCommentsTokenStreamChange(this)
         .setPrecedingComments(setOn, comment);
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/top_level_parser.dart b/pkg/_fe_analyzer_shared/lib/src/parser/top_level_parser.dart
index b8b39e0..93be64c 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/top_level_parser.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/top_level_parser.dart
@@ -18,7 +18,7 @@
   TopLevelParser(Listener listener) : super(listener);
 
   @override
-  Token parseClassOrMixinOrExtensionBody(
-          Token token, DeclarationKind kind, String enclosingDeclarationName) =>
+  Token parseClassOrMixinOrExtensionBody(Token token, DeclarationKind kind,
+          String? enclosingDeclarationName) =>
       skipClassOrMixinOrExtensionBody(token);
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
index 260047a..6f10b8a 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
@@ -117,7 +117,7 @@
 
 bool isGeneralizedFunctionType(Token token) {
   return optional('Function', token) &&
-      (optional('<', token.next) || optional('(', token.next));
+      (optional('<', token.next!) || optional('(', token.next!));
 }
 
 bool isValidTypeReference(Token token) {
@@ -127,7 +127,7 @@
     TokenType type = token.type;
     String value = type.lexeme;
     return type.isPseudo ||
-        (type.isBuiltIn && optional('.', token.next)) ||
+        (type.isBuiltIn && optional('.', token.next!)) ||
         (identical(value, 'dynamic')) ||
         (identical(value, 'void'));
   }
@@ -141,24 +141,24 @@
 /// given unbalanced `<` `>` and invalid parameters or arguments.
 TypeInfo computeType(final Token token, bool required,
     [bool inDeclaration = false]) {
-  Token next = token.next;
+  Token next = token.next!;
   if (!isValidTypeReference(next)) {
     if (next.type.isBuiltIn) {
       TypeParamOrArgInfo typeParamOrArg =
           computeTypeParamOrArg(next, inDeclaration);
       if (typeParamOrArg != noTypeParamOrArg) {
         // Recovery: built-in `<` ... `>`
-        if (required || looksLikeName(typeParamOrArg.skip(next).next)) {
+        if (required || looksLikeName(typeParamOrArg.skip(next).next!)) {
           return new ComplexTypeInfo(token, typeParamOrArg)
               .computeBuiltinOrVarAsType(required);
         }
-      } else if (required || isGeneralizedFunctionType(next.next)) {
-        String value = next.stringValue;
+      } else if (required || isGeneralizedFunctionType(next.next!)) {
+        String? value = next.stringValue;
         if ((!identical('get', value) &&
             !identical('set', value) &&
             !identical('factory', value) &&
             !identical('operator', value) &&
-            !(identical('typedef', value) && next.next.isIdentifier))) {
+            !(identical('typedef', value) && next.next!.isIdentifier))) {
           return new ComplexTypeInfo(token, typeParamOrArg)
               .computeBuiltinOrVarAsType(required);
         }
@@ -171,7 +171,7 @@
                 token, computeTypeParamOrArg(next, inDeclaration))
             .computePrefixedType(required);
       } else if (optional('var', next) &&
-          isOneOf(next.next, const ['<', ',', '>'])) {
+          isOneOf(next.next!, const ['<', ',', '>'])) {
         return new ComplexTypeInfo(
                 token, computeTypeParamOrArg(next, inDeclaration))
             .computeBuiltinOrVarAsType(required);
@@ -181,7 +181,7 @@
   }
 
   if (optional('void', next)) {
-    next = next.next;
+    next = next.next!;
     if (isGeneralizedFunctionType(next)) {
       // `void` `Function` ...
       return new ComplexTypeInfo(token, noTypeParamOrArg)
@@ -204,9 +204,9 @@
   if (typeParamOrArg != noTypeParamOrArg) {
     if (typeParamOrArg.isSimpleTypeArgument) {
       // We've seen identifier `<` identifier `>`
-      next = typeParamOrArg.skip(next).next;
+      next = typeParamOrArg.skip(next).next!;
       if (optional('?', next)) {
-        next = next.next;
+        next = next.next!;
         if (!isGeneralizedFunctionType(next)) {
           if ((required || looksLikeName(next)) &&
               typeParamOrArg == simpleTypeArgument1) {
@@ -235,16 +235,16 @@
   }
 
   assert(typeParamOrArg == noTypeParamOrArg);
-  next = next.next;
+  next = next.next!;
   if (optional('.', next)) {
-    next = next.next;
+    next = next.next!;
     if (isValidTypeReference(next)) {
       // We've seen identifier `.` identifier
       typeParamOrArg = computeTypeParamOrArg(next, inDeclaration);
-      next = next.next;
+      next = next.next!;
       if (typeParamOrArg == noTypeParamOrArg) {
         if (optional('?', next)) {
-          next = next.next;
+          next = next.next!;
           if (!isGeneralizedFunctionType(next)) {
             if (required || looksLikeName(next)) {
               // identifier `.` identifier `?` identifier
@@ -273,7 +273,7 @@
     }
     // identifier `.` non-identifier
     if (required) {
-      typeParamOrArg = computeTypeParamOrArg(token.next.next, inDeclaration);
+      typeParamOrArg = computeTypeParamOrArg(token.next!.next!, inDeclaration);
       return new ComplexTypeInfo(token, typeParamOrArg)
           .computePrefixedType(required);
     }
@@ -288,16 +288,16 @@
   }
 
   if (optional('?', next)) {
-    next = next.next;
+    next = next.next!;
     if (isGeneralizedFunctionType(next)) {
       // identifier `?` Function `(`
       return new ComplexTypeInfo(token, noTypeParamOrArg)
           .computeIdentifierQuestionGFT(required);
-    } else if (required || looksLikeName(next)) {
+    } else if (required || looksLikeNameSimpleType(next)) {
       // identifier `?`
       return simpleNullableType;
     }
-  } else if (required || looksLikeName(next)) {
+  } else if (required || looksLikeNameSimpleType(next)) {
     // identifier identifier
     return simpleType;
   }
@@ -312,20 +312,20 @@
 /// given unbalanced `<` `>` and invalid parameters or arguments.
 TypeParamOrArgInfo computeTypeParamOrArg(Token token,
     [bool inDeclaration = false, bool allowsVariance = false]) {
-  Token beginGroup = token.next;
+  Token beginGroup = token.next!;
   if (!optional('<', beginGroup)) {
     return noTypeParamOrArg;
   }
 
   // identifier `<` `void` `>` and `<` `dynamic` `>`
   // are handled by ComplexTypeInfo.
-  Token next = beginGroup.next;
+  Token next = beginGroup.next!;
   if ((next.kind == IDENTIFIER_TOKEN || next.type.isPseudo)) {
-    if (optional('>', next.next)) {
+    if (optional('>', next.next!)) {
       return simpleTypeArgument1;
-    } else if (optional('>>', next.next)) {
+    } else if (optional('>>', next.next!)) {
       return simpleTypeArgument1GtGt;
-    } else if (optional('>=', next.next)) {
+    } else if (optional('>=', next.next!)) {
       return simpleTypeArgument1GtEq;
     }
   } else if (optional('(', next)) {
@@ -346,5 +346,5 @@
 /// possible other constructs will pass (e.g., 'a < C, D > 3').
 TypeParamOrArgInfo computeMethodTypeArguments(Token token) {
   TypeParamOrArgInfo typeArg = computeTypeParamOrArg(token);
-  return optional('(', typeArg.skip(token).next) ? typeArg : noTypeParamOrArg;
+  return optional('(', typeArg.skip(token).next!) ? typeArg : noTypeParamOrArg;
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
index 6e81efc..73bcfb1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
@@ -107,7 +107,7 @@
   @override
   Token ensureTypeNotVoid(Token token, Parser parser) {
     parser.reportRecoverableErrorWithToken(
-        token.next, codes.templateExpectedType);
+        token.next!, codes.templateExpectedType);
     parser.rewriter.insertSyntheticIdentifier(token);
     return simpleType.parseType(token, parser);
   }
@@ -162,28 +162,28 @@
 
   @override
   Token parseType(Token token, Parser parser) {
-    Token start = token = token.next;
+    Token start = token = token.next!;
     assert(token.isKeywordOrIdentifier);
     Listener listener = parser.listener;
     listener.handleIdentifier(token, IdentifierContext.prefixedTypeReference);
 
-    Token period = token = token.next;
+    Token period = token = token.next!;
     assert(optional('.', token));
 
-    token = token.next;
+    token = token.next!;
     assert(token.isKeywordOrIdentifier);
     listener.handleIdentifier(
         token, IdentifierContext.typeReferenceContinuation);
     listener.handleQualified(period);
 
-    listener.handleNoTypeArguments(token.next);
+    listener.handleNoTypeArguments(token.next!);
     listener.handleType(start, /* questionMark = */ null);
     return token;
   }
 
   @override
   Token skipType(Token token) {
-    return token.next.next.next;
+    return token.next!.next!.next!;
   }
 }
 
@@ -202,7 +202,7 @@
 
   @override
   Token parseTypeRest(Token start, Token token, Parser parser) {
-    token = token.next;
+    token = token.next!;
     assert(optional('?', token));
     parser.listener.handleType(start, token);
     return token;
@@ -210,7 +210,7 @@
 
   @override
   Token skipType(Token token) {
-    token = super.skipType(token).next;
+    token = super.skipType(token).next!;
     assert(optional('?', token));
     return token;
   }
@@ -248,7 +248,7 @@
 
   @override
   Token parseType(Token token, Parser parser) {
-    Token start = token = token.next;
+    Token start = token = token.next!;
     assert(token.isKeywordOrIdentifier);
     parser.listener.handleIdentifier(token, IdentifierContext.typeReference);
     token = typeArg.parseArguments(token, parser);
@@ -262,7 +262,7 @@
 
   @override
   Token skipType(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(token.isKeywordOrIdentifier);
     return typeArg.skip(token);
   }
@@ -283,7 +283,7 @@
 
   @override
   Token parseTypeRest(Token start, Parser parser) {
-    Token token = start.next;
+    Token token = start.next!;
     assert(optional('?', token));
     parser.listener.handleType(start, token);
     return token;
@@ -291,7 +291,7 @@
 
   @override
   Token skipType(Token token) {
-    return token.next.next;
+    return token.next!.next!;
   }
 }
 
@@ -325,7 +325,7 @@
 
   @override
   Token parseType(Token token, Parser parser) {
-    token = token.next;
+    token = token.next!;
     assert(isValidTypeReference(token));
     parser.listener.handleIdentifier(token, IdentifierContext.typeReference);
     token = noTypeParamOrArg.parseArguments(token, parser);
@@ -339,7 +339,7 @@
 
   @override
   Token skipType(Token token) {
-    return token.next;
+    return token.next!;
   }
 }
 
@@ -362,7 +362,7 @@
   @override
   Token ensureTypeNotVoid(Token token, Parser parser) {
     // Report an error, then parse `void` as if it were a type name.
-    parser.reportRecoverableError(token.next, codes.messageInvalidVoid);
+    parser.reportRecoverableError(token.next!, codes.messageInvalidVoid);
     return simpleType.parseTypeNotVoid(token, parser);
   }
 
@@ -376,16 +376,16 @@
 
   @override
   Token parseType(Token token, Parser parser) {
-    Token voidKeyword = token = token.next;
+    Token voidKeyword = token = token.next!;
     bool hasTypeArguments = false;
 
     // Recovery: Skip past, but issue problem, if followed by type arguments.
-    if (optional('<', token.next)) {
+    if (optional('<', token.next!)) {
       TypeParamOrArgInfo typeParam = computeTypeParamOrArg(token);
       if (typeParam != noTypeParamOrArg) {
         hasTypeArguments = true;
         parser.reportRecoverableError(
-            token.next, codes.messageVoidWithTypeArguments);
+            token.next!, codes.messageVoidWithTypeArguments);
         token = typeParam.parseArguments(token, parser);
       }
     }
@@ -400,9 +400,9 @@
 
   @override
   Token skipType(Token token) {
-    token = token.next;
+    token = token.next!;
     // Recovery: Skip past if followed by type arguments.
-    if (optional('<', token.next)) {
+    if (optional('<', token.next!)) {
       TypeParamOrArgInfo typeParam = computeTypeParamOrArg(token);
       if (typeParam != noTypeParamOrArg) {
         token = typeParam.skip(token);
@@ -412,20 +412,29 @@
   }
 }
 
-bool looksLikeName(Token token) =>
-    token.kind == IDENTIFIER_TOKEN ||
-    optional('this', token) ||
-    (token.isIdentifier &&
-        // Although `typedef` is a legal identifier,
-        // type `typedef` identifier is not legal and in this situation
-        // `typedef` is probably a separate declaration.
-        (!optional('typedef', token) || !token.next.isIdentifier));
+bool looksLikeName(Token token) {
+  // End-of-file isn't a name, but this is called in a situation where
+  // if there had been a name it would have used the type-info it had
+  // collected --- this being eof probably mean the user is currently
+  // typing and will probably write a name in a moment.
+  return looksLikeNameSimpleType(token) || token.isEof;
+}
+
+bool looksLikeNameSimpleType(Token token) {
+  return token.kind == IDENTIFIER_TOKEN ||
+      optional('this', token) ||
+      (token.isIdentifier &&
+          // Although `typedef` is a legal identifier,
+          // type `typedef` identifier is not legal and in this situation
+          // `typedef` is probably a separate declaration.
+          (!optional('typedef', token) || !token.next!.isIdentifier));
+}
 
 /// When missing a comma, determine if the given token looks like it should
 /// be part of a collection of type parameters or arguments.
 bool looksLikeTypeParamOrArg(bool inDeclaration, Token token) {
   if (inDeclaration && token.kind == IDENTIFIER_TOKEN) {
-    Token next = token.next;
+    Token next = token.next!;
     if (next.kind == IDENTIFIER_TOKEN ||
         optional(',', next) ||
         isCloser(next)) {
@@ -447,10 +456,10 @@
   /// The token before the trailing question mark or `null` if either
   /// 1) there is no trailing question mark, or
   /// 2) the trailing question mark is not part of the type reference.
-  Token beforeQuestionMark;
+  Token? beforeQuestionMark;
 
   /// The last token in the type reference.
-  Token end;
+  Token? end;
 
   /// The `Function` tokens before the start of type variables of function types
   /// as seen during analysis.
@@ -458,10 +467,11 @@
 
   /// If the receiver represents a generalized function type then this indicates
   /// whether it has a return type, otherwise this is `null`.
-  bool gftHasReturnType;
+  bool? gftHasReturnType;
 
   ComplexTypeInfo(Token beforeStart, this.typeArguments)
-      : this.start = beforeStart.next {
+      : this.start = beforeStart.next! {
+    // ignore: unnecessary_null_comparison
     assert(typeArguments != null);
   }
 
@@ -500,7 +510,7 @@
 
   @override
   Token parseType(Token token, Parser parser) {
-    assert(identical(token.next, start));
+    assert(identical(token.next!, start));
 
     if (optional('.', start)) {
       // Recovery: Insert missing identifier without sending events
@@ -509,7 +519,7 @@
     }
 
     final List<Token> typeVariableEndGroups = <Token>[];
-    for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail) {
+    for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail!) {
       parser.listener.beginFunctionType(start);
       typeVariableEndGroups.add(
           computeTypeParamOrArg(t.head, /* inDeclaration = */ true)
@@ -522,12 +532,12 @@
       // generate the full type.
       noType.parseType(token, parser);
     } else {
-      Token typeRefOrPrefix = token.next;
+      Token typeRefOrPrefix = token.next!;
       if (optional('void', typeRefOrPrefix)) {
         token = voidType.parseType(token, parser);
       } else {
         if (!optional('.', typeRefOrPrefix) &&
-            !optional('.', typeRefOrPrefix.next)) {
+            !optional('.', typeRefOrPrefix.next!)) {
           token =
               parser.ensureIdentifier(token, IdentifierContext.typeReference);
         } else {
@@ -543,7 +553,7 @@
         token = typeArguments.parseArguments(token, parser);
 
         // Only consume the `?` if it is part of the complex type
-        Token questionMark = token.next;
+        Token? questionMark = token.next!;
         if (optional('?', questionMark) &&
             (typeVariableEndGroups.isNotEmpty || beforeQuestionMark != null)) {
           token = questionMark;
@@ -556,12 +566,12 @@
     }
 
     int endGroupIndex = typeVariableEndGroups.length - 1;
-    for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail) {
-      token = token.next;
+    for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail!) {
+      token = token.next!;
       assert(optional('Function', token));
       Token functionToken = token;
 
-      if (optional("<", token.next)) {
+      if (optional("<", token.next!)) {
         // Skip type parameters, they were parsed above.
         token = typeVariableEndGroups[endGroupIndex];
         assert(optional('>', token));
@@ -570,7 +580,7 @@
           token, MemberKind.GeneralizedFunctionType);
 
       // Only consume the `?` if it is part of the complex type
-      Token questionMark = token.next;
+      Token? questionMark = token.next!;
       if (optional('?', questionMark) &&
           (endGroupIndex > 0 || beforeQuestionMark != null)) {
         token = questionMark;
@@ -597,7 +607,7 @@
 
   @override
   Token skipType(Token token) {
-    return end;
+    return end!;
   }
 
   /// Given `Function` non-identifier, compute the type
@@ -618,7 +628,7 @@
   /// and return the receiver or one of the [TypeInfo] constants.
   TypeInfo computeVoidGFT(bool required) {
     assert(optional('void', start));
-    assert(optional('Function', start.next));
+    assert(optional('Function', start.next!));
 
     computeRest(start, required);
     if (gftHasReturnType == null) {
@@ -632,7 +642,7 @@
   /// and return the receiver or one of the [TypeInfo] constants.
   TypeInfo computeIdentifierGFT(bool required) {
     assert(isValidTypeReference(start));
-    assert(optional('Function', start.next));
+    assert(optional('Function', start.next!));
 
     computeRest(start, required);
     if (gftHasReturnType == null) {
@@ -646,8 +656,8 @@
   /// and return the receiver or one of the [TypeInfo] constants.
   TypeInfo computeIdentifierQuestionGFT(bool required) {
     assert(isValidTypeReference(start));
-    assert(optional('?', start.next));
-    assert(optional('Function', start.next.next));
+    assert(optional('?', start.next!));
+    assert(optional('Function', start.next!.next!));
 
     computeRest(start, required);
     if (gftHasReturnType == null) {
@@ -663,7 +673,7 @@
     assert(start.type.isBuiltIn || optional('var', start));
 
     end = typeArguments.skip(start);
-    computeRest(end, required);
+    computeRest(end!, required);
     assert(end != null);
     return this;
   }
@@ -672,13 +682,13 @@
   /// and return the receiver or one of the [TypeInfo] constants.
   TypeInfo computeSimpleWithTypeArguments(bool required) {
     assert(isValidTypeReference(start));
-    assert(optional('<', start.next));
+    assert(optional('<', start.next!));
     assert(typeArguments != noTypeParamOrArg);
 
     end = typeArguments.skip(start);
-    computeRest(end, required);
+    computeRest(end!, required);
 
-    if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
+    if (!required && !looksLikeName(end!.next!) && gftHasReturnType == null) {
       return noType;
     }
     assert(end != null);
@@ -692,16 +702,16 @@
     Token token = start;
     if (!optional('.', token)) {
       assert(token.isKeywordOrIdentifier);
-      token = token.next;
+      token = token.next!;
     }
     assert(optional('.', token));
-    if (token.next.isKeywordOrIdentifier) {
-      token = token.next;
+    if (token.next!.isKeywordOrIdentifier) {
+      token = token.next!;
     }
 
     end = typeArguments.skip(token);
-    computeRest(end, required);
-    if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
+    computeRest(end!, required);
+    if (!required && !looksLikeName(end!.next!) && gftHasReturnType == null) {
       return noType;
     }
     assert(end != null);
@@ -709,28 +719,28 @@
   }
 
   void computeRest(Token token, bool required) {
-    if (optional('?', token.next)) {
+    if (optional('?', token.next!)) {
       beforeQuestionMark = token;
-      end = token = token.next;
+      end = token = token.next!;
     }
-    token = token.next;
+    token = token.next!;
     while (optional('Function', token)) {
       Token typeVariableStart = token;
       // TODO(danrubel): Consider caching TypeParamOrArgInfo
       token =
           computeTypeParamOrArg(token, /* inDeclaration = */ true).skip(token);
-      token = token.next;
+      token = token.next!;
       if (!optional('(', token)) {
         break; // Not a function type.
       }
-      token = token.endGroup;
-      if (token == null) {
+      if (token.endGroup == null) {
         break; // Not a function type.
       }
+      token = token.endGroup!;
       if (!required) {
-        Token next = token.next;
+        Token next = token.next!;
         if (optional('?', next)) {
-          next = next.next;
+          next = next.next!;
         }
         if (!(next.isIdentifier || optional('this', next))) {
           break; // `Function` used as the name in a function declaration.
@@ -742,12 +752,12 @@
 
       beforeQuestionMark = null;
       end = token;
-      token = token.next;
+      token = token.next!;
 
       if (optional('?', token)) {
         beforeQuestionMark = end;
         end = token;
-        token = token.next;
+        token = token.next!;
       }
     }
   }
@@ -762,13 +772,13 @@
 
   @override
   Token parseArguments(Token token, Parser parser) {
-    parser.listener.handleNoTypeArguments(token.next);
+    parser.listener.handleNoTypeArguments(token.next!);
     return token;
   }
 
   @override
   Token parseVariables(Token token, Parser parser) {
-    parser.listener.handleNoTypeVariables(token.next);
+    parser.listener.handleNoTypeVariables(token.next!);
     return token;
   }
 
@@ -790,9 +800,9 @@
 
   @override
   Token parseArguments(Token token, Parser parser) {
-    Token beginGroup = token.next;
+    Token beginGroup = token.next!;
     assert(optional('<', beginGroup));
-    Token endGroup = parseEndGroup(beginGroup, beginGroup.next);
+    Token endGroup = parseEndGroup(beginGroup, beginGroup.next!);
     Listener listener = parser.listener;
     listener.beginTypeArguments(beginGroup);
     simpleType.parseType(beginGroup, parser);
@@ -802,9 +812,9 @@
 
   @override
   Token parseVariables(Token token, Parser parser) {
-    Token beginGroup = token.next;
+    Token beginGroup = token.next!;
     assert(optional('<', beginGroup));
-    token = beginGroup.next;
+    token = beginGroup.next!;
     Token endGroup = parseEndGroup(beginGroup, token);
     Listener listener = parser.listener;
     listener.beginTypeVariables(beginGroup);
@@ -825,21 +835,21 @@
 
   @override
   Token skip(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('<', token));
-    token = token.next;
+    token = token.next!;
     assert(token.isKeywordOrIdentifier);
     return skipEndGroup(token);
   }
 
   Token skipEndGroup(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('>', token));
     return token;
   }
 
   Token parseEndGroup(Token beginGroup, Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('>', token));
     return token;
   }
@@ -852,16 +862,16 @@
   TypeInfo get typeInfo => simpleTypeWith1ArgumentGtEq;
 
   Token skipEndGroup(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('>=', token));
     return splitGtEq(token);
   }
 
   Token parseEndGroup(Token beginGroup, Token beforeEndGroup) {
-    Token endGroup = beforeEndGroup.next;
+    Token endGroup = beforeEndGroup.next!;
     if (!optional('>', endGroup)) {
       endGroup = splitGtEq(endGroup);
-      endGroup.next.setNext(endGroup.next.next);
+      endGroup.next!.setNext(endGroup.next!.next!);
     }
     beforeEndGroup.setNext(endGroup);
     return endGroup;
@@ -875,16 +885,16 @@
   TypeInfo get typeInfo => simpleTypeWith1ArgumentGtGt;
 
   Token skipEndGroup(Token token) {
-    token = token.next;
+    token = token.next!;
     assert(optional('>>', token));
     return splitGtGt(token);
   }
 
   Token parseEndGroup(Token beginGroup, Token beforeEndGroup) {
-    Token endGroup = beforeEndGroup.next;
+    Token endGroup = beforeEndGroup.next!;
     if (!optional('>', endGroup)) {
       endGroup = splitGtGt(endGroup);
-      endGroup.next.setNext(endGroup.next.next);
+      endGroup.next!.setNext(endGroup.next!.next!);
     }
     beforeEndGroup.setNext(endGroup);
     return endGroup;
@@ -905,20 +915,22 @@
   final bool allowsVariance;
 
   @override
-  int typeArgumentCount;
+  late int typeArgumentCount;
 
   /// The `>` token which ends the type parameter or argument.
   /// This closer may be synthetic, points to the next token in the stream,
   /// is only used when skipping over the type parameters or arguments,
   /// and may not be part of the token stream.
-  Token skipEnd;
+  Token? skipEnd;
 
   ComplexTypeParamOrArgInfo(
       Token token, this.inDeclaration, this.allowsVariance)
-      : assert(optional('<', token.next)),
+      : assert(optional('<', token.next!)),
+        // ignore: unnecessary_null_comparison
         assert(inDeclaration != null),
+        // ignore: unnecessary_null_comparison
         assert(allowsVariance != null),
-        start = token.next;
+        start = token.next!;
 
   /// Parse the tokens and return the receiver or [noTypeParamOrArg] if there
   /// are no type parameters or arguments. This does not modify the token
@@ -931,30 +943,30 @@
       TypeInfo typeInfo =
           computeType(next, /* required = */ true, inDeclaration);
       if (typeInfo == noType) {
-        while (typeInfo == noType && optional('@', next.next)) {
+        while (typeInfo == noType && optional('@', next.next!)) {
           next = skipMetadata(next);
           typeInfo = computeType(next, /* required = */ true, inDeclaration);
         }
         if (typeInfo == noType) {
-          if (next == start && !inDeclaration && !isCloser(next.next)) {
+          if (next == start && !inDeclaration && !isCloser(next.next!)) {
             return noTypeParamOrArg;
           }
-          if (!optional(',', next.next)) {
+          if (!optional(',', next.next!)) {
             token = next;
-            next = token.next;
+            next = token.next!;
             break;
           }
         }
-        assert(typeInfo != noType || optional(',', next.next));
+        assert(typeInfo != noType || optional(',', next.next!));
         // Fall through to process type (if any) and consume `,`
       }
       ++typeArgumentCount;
       token = typeInfo.skipType(next);
-      next = token.next;
+      next = token.next!;
       if (optional('extends', next)) {
         token = computeType(next, /* required = */ true, inDeclaration)
             .skipType(next);
-        next = token.next;
+        next = token.next!;
       }
       if (!optional(',', next)) {
         skipEnd = splitCloser(next);
@@ -978,12 +990,12 @@
     skipEnd = splitCloser(next);
     if (skipEnd == null) {
       if (optional('(', next)) {
-        token = next.endGroup;
-        next = token.next;
+        token = next.endGroup!;
+        next = token.next!;
       }
       skipEnd = splitCloser(next);
       if (skipEnd == null) {
-        skipEnd = splitCloser(next.next);
+        skipEnd = splitCloser(next.next!);
       }
       if (skipEnd == null) {
         skipEnd = syntheticGt(next);
@@ -994,7 +1006,7 @@
 
   @override
   Token parseArguments(Token token, Parser parser) {
-    assert(identical(token.next, start));
+    assert(identical(token.next!, start));
     Token next = start;
     parser.listener.beginTypeArguments(start);
     int count = 0;
@@ -1003,8 +1015,8 @@
           computeType(next, /* required = */ true, inDeclaration);
       if (typeInfo == noType) {
         // Recovery
-        while (typeInfo == noType && optional('@', next.next)) {
-          Token atToken = next.next;
+        while (typeInfo == noType && optional('@', next.next!)) {
+          Token atToken = next.next!;
           next = skipMetadata(next);
           parser.reportRecoverableErrorWithEnd(
               atToken, next, codes.messageAnnotationOnTypeArgument);
@@ -1013,7 +1025,7 @@
         // Fall through to process type (if any) and consume `,`
       }
       token = typeInfo.ensureTypeOrVoid(next, parser);
-      next = token.next;
+      next = token.next!;
       ++count;
       if (!optional(',', next)) {
         if (parseCloser(token)) {
@@ -1029,28 +1041,28 @@
         next = parseMissingComma(token, parser);
       }
     }
-    Token endGroup = token.next;
+    Token endGroup = token.next!;
     parser.listener.endTypeArguments(count, start, endGroup);
     return endGroup;
   }
 
   @override
   Token parseVariables(Token token, Parser parser) {
-    assert(identical(token.next, start));
+    assert(identical(token.next!, start));
     Token next = start;
     Listener listener = parser.listener;
     listener.beginTypeVariables(start);
     int count = 0;
 
     Link<Token> typeStarts = const Link<Token>();
-    Link<TypeInfo> superTypeInfos = const Link<TypeInfo>();
-    Link<Token> variances = const Link<Token>();
+    Link<TypeInfo?> superTypeInfos = const Link<TypeInfo?>();
+    Link<Token?> variances = const Link<Token?>();
 
     while (true) {
       token = parser.parseMetadataStar(next);
 
-      Token variance = next.next;
-      Token identifier = variance.next;
+      Token variance = next.next!;
+      Token? identifier = variance.next;
       if (allowsVariance &&
           isVariance(variance) &&
           identifier != null &&
@@ -1058,14 +1070,15 @@
         variances = variances.prepend(variance);
 
         // Recovery for multiple variance modifiers
-        while (isVariance(identifier) &&
+        while (identifier != null &&
+            isVariance(identifier) &&
             identifier.next != null &&
-            identifier.next.isKeywordOrIdentifier) {
+            identifier.next!.isKeywordOrIdentifier) {
           // Report an error and skip actual identifier
           parser.reportRecoverableError(
               identifier, codes.messageMultipleVarianceModifiers);
-          variance = variance.next;
-          identifier = identifier.next;
+          variance = variance.next!;
+          identifier = identifier.next!;
         }
 
         token = variance;
@@ -1079,12 +1092,12 @@
       listener.beginTypeVariable(token);
       typeStarts = typeStarts.prepend(token);
 
-      next = token.next;
+      next = token.next!;
       if (optional('extends', next)) {
         TypeInfo typeInfo =
             computeType(next, /* required = */ true, inDeclaration);
         token = typeInfo.skipType(next);
-        next = token.next;
+        next = token.next!;
         superTypeInfos = superTypeInfos.prepend(typeInfo);
       } else {
         superTypeInfos = superTypeInfos.prepend(/* element = */ null);
@@ -1111,43 +1124,43 @@
     assert(variances.slowLength() == count);
     listener.handleTypeVariablesDefined(token, count);
 
-    token = null;
+    Token? token3 = null;
     while (typeStarts.isNotEmpty) {
       Token token2 = typeStarts.head;
-      TypeInfo typeInfo = superTypeInfos.head;
-      Token variance = variances.head;
+      TypeInfo? typeInfo = superTypeInfos.head;
+      Token? variance = variances.head;
 
-      Token extendsOrSuper = null;
-      Token next2 = token2.next;
+      Token? extendsOrSuper = null;
+      Token next2 = token2.next!;
       if (typeInfo != null) {
         assert(optional('extends', next2));
         extendsOrSuper = next2;
         token2 = typeInfo.ensureTypeNotVoid(next2, parser);
-        next2 = token2.next;
+        next2 = token2.next!;
       } else {
         assert(!optional('extends', next2));
         listener.handleNoType(token2);
       }
       // Type variables are "completed" in reverse order, so capture the last
       // consumed token from the first "completed" type variable.
-      token ??= token2;
+      token3 ??= token2;
       listener.endTypeVariable(next2, --count, extendsOrSuper, variance);
 
-      typeStarts = typeStarts.tail;
-      superTypeInfos = superTypeInfos.tail;
-      variances = variances.tail;
+      typeStarts = typeStarts.tail!;
+      superTypeInfos = superTypeInfos.tail!;
+      variances = variances.tail!;
     }
 
-    if (!parseCloser(token)) {
-      token = parseUnexpectedEnd(token, /* isArguments = */ false, parser);
+    if (!parseCloser(token3!)) {
+      token3 = parseUnexpectedEnd(token3, /* isArguments = */ false, parser);
     }
-    Token endGroup = token.next;
+    Token endGroup = token3.next!;
     listener.endTypeVariables(start, endGroup);
     return endGroup;
   }
 
   Token parseMissingComma(Token token, Parser parser) {
-    Token next = token.next;
+    Token next = token.next!;
     parser.reportRecoverableError(
         next, codes.templateExpectedButGot.withArguments(','));
     return parser.rewriter.insertToken(
@@ -1155,7 +1168,7 @@
   }
 
   Token parseUnexpectedEnd(Token token, bool isArguments, Parser parser) {
-    Token next = token.next;
+    Token next = token.next!;
     bool errorReported = token.isSynthetic || (next.isSynthetic && !next.isEof);
 
     bool typeFollowsExtends = false;
@@ -1166,7 +1179,7 @@
         errorReported = true;
       }
       token = next;
-      next = token.next;
+      next = token.next!;
       typeFollowsExtends = isValidTypeReference(next);
 
       if (parseCloser(token)) {
@@ -1191,7 +1204,7 @@
         final Listener originalListener = parser.listener;
         parser.listener = new ForwardingListener();
         token = invalidType.parseType(token, parser);
-        next = token.next;
+        next = token.next!;
         parser.listener = originalListener;
 
         if (parseCloser(token)) {
@@ -1216,7 +1229,7 @@
       token = isArguments
           ? invalidTypeVar.parseArguments(token, parser)
           : invalidTypeVar.parseVariables(token, parser);
-      next = token.next;
+      next = token.next!;
       parser.listener = originalListener;
 
       if (parseCloser(token)) {
@@ -1231,8 +1244,8 @@
             token, codes.templateExpectedAfterButGot.withArguments('>'));
         errorReported = true;
       }
-      token = next.endGroup;
-      next = token.next;
+      token = next.endGroup!;
+      next = token.next!;
 
       if (parseCloser(token)) {
         return token;
@@ -1247,10 +1260,10 @@
     if (parseCloser(next)) {
       return next;
     }
-    Token endGroup = start.endGroup;
+    Token? endGroup = start.endGroup;
     if (endGroup != null) {
       while (token.next != endGroup && !token.isEof) {
-        token = token.next;
+        token = token.next!;
       }
     } else {
       endGroup = syntheticGt(next);
@@ -1263,7 +1276,7 @@
   @override
   Token skip(Token token) {
     assert(skipEnd != null);
-    return skipEnd;
+    return skipEnd!;
   }
 }
 
@@ -1276,7 +1289,7 @@
 
 /// Return `true` if [token] is one of `>`, `>>`, `>>>`, `>=`, `>>=`, or `>>>=`.
 bool isCloser(Token token) {
-  final String value = token.stringValue;
+  final String? value = token.stringValue;
   return identical(value, '>') ||
       identical(value, '>>') ||
       identical(value, '>=') ||
@@ -1288,14 +1301,14 @@
 /// If [beforeCloser].next is one of `>`, `>>`, `>>>`, `>=`, `>>=`, or `>>>=`
 /// then update the token stream and return `true`.
 bool parseCloser(Token beforeCloser) {
-  Token unsplit = beforeCloser.next;
-  Token split = splitCloser(unsplit);
+  Token unsplit = beforeCloser.next!;
+  Token? split = splitCloser(unsplit);
   if (split == unsplit) {
     return true;
   } else if (split == null) {
     return false;
   }
-  split.next.setNext(unsplit.next);
+  split.next!.setNext(unsplit.next!);
   beforeCloser.setNext(split);
   return true;
 }
@@ -1304,8 +1317,8 @@
 /// If [closer] is one of `>>`, `>>>`, `>=`, `>>=`,  or `>>>=` then split
 /// the token and return the leading `>` without updating the token stream.
 /// If [closer] is none of the above, then return null;
-Token splitCloser(Token closer) {
-  String value = closer.stringValue;
+Token? splitCloser(Token closer) {
+  String? value = closer.stringValue;
   if (identical(value, '>')) {
     return closer;
   } else if (identical(value, '>>')) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/util.dart b/pkg/_fe_analyzer_shared/lib/src/parser/util.dart
index dfe02c8..f6f1939 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/util.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/util.dart
@@ -18,16 +18,16 @@
 
 /// Returns the token before the close brace, bracket, or parenthesis
 /// associated with [left]. For '<', it may return `null`.
-Token beforeCloseBraceTokenFor(BeginToken left) {
-  Token endToken = left.endToken;
+Token? beforeCloseBraceTokenFor(BeginToken left) {
+  Token? endToken = left.endToken;
   if (endToken == null) {
     return null;
   }
   Token token = left;
-  Token next = token.next;
+  Token next = token.next!;
   while (next != endToken && next != next.next) {
     token = next;
-    next = token.next;
+    next = token.next!;
   }
   return token;
 }
@@ -36,7 +36,7 @@
 /// not synthetic or synthetic with non-zero length.
 Token findPreviousNonZeroLengthToken(Token token) {
   while (token.isSynthetic && token.length == 0) {
-    Token previous = token.beforeSynthetic;
+    Token? previous = token.beforeSynthetic;
     if (previous == token) {
       throw new StateError("token == token.beforeSynthetic");
     }
@@ -53,7 +53,7 @@
 /// This may return EOF if there are no more non-synthetic tokens in the stream.
 Token findNonZeroLengthToken(Token token) {
   while (token.isSynthetic && token.length == 0 && !token.isEof) {
-    token = token.next;
+    token = token.next!;
   }
   return token;
 }
@@ -88,37 +88,37 @@
 
 /// A null-aware alternative to `token.length`.  If [token] is `null`, returns
 /// [noLength].
-int lengthForToken(Token token) {
+int lengthForToken(Token? token) {
   return token == null ? noLength : token.length;
 }
 
 /// Returns the length of the span from [begin] to [end] (inclusive). If both
 /// tokens are null, return [noLength]. If one of the tokens are null, return
 /// the length of the other token.
-int lengthOfSpan(Token begin, Token end) {
+int lengthOfSpan(Token? begin, Token? end) {
   if (begin == null) return lengthForToken(end);
   if (end == null) return lengthForToken(begin);
   return end.offset + end.length - begin.offset;
 }
 
 Token skipMetadata(Token token) {
-  token = token.next;
+  token = token.next!;
   assert(optional('@', token));
-  Token next = token.next;
+  Token next = token.next!;
   if (next.isIdentifier) {
     token = next;
-    next = token.next;
+    next = token.next!;
     while (optional('.', next)) {
       token = next;
-      next = token.next;
+      next = token.next!;
       if (next.isIdentifier) {
         token = next;
-        next = token.next;
+        next = token.next!;
       }
     }
-    if (optional('(', next) && !next.endGroup.isSynthetic) {
-      token = next.endGroup;
-      next = token.next;
+    if (optional('(', next) && !next.endGroup!.isSynthetic) {
+      token = next.endGroup!;
+      next = token.next!;
     }
   }
   return token;
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/value_kind.dart b/pkg/_fe_analyzer_shared/lib/src/parser/value_kind.dart
index 92549f0..ae85d25 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/value_kind.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/value_kind.dart
@@ -13,18 +13,18 @@
   const ValueKind();
 
   /// Checks the [value] an returns `true` if the value is of the expected kind.
-  bool check(Object value);
+  bool check(Object ?value);
 }
 
 /// A [ValueKind] for a particular type [T], optionally with a recognized
 /// [NullValue].
 class SingleValueKind<T> implements ValueKind {
-  final NullValue nullValue;
+  final NullValue? nullValue;
 
   const SingleValueKind([this.nullValue]);
 
   @override
-  bool check(Object value) {
+  bool check(Object? value) {
     if (nullValue != null && value == nullValue) {
       return true;
     }
@@ -46,7 +46,7 @@
   const UnionValueKind(this.kinds);
 
   @override
-  bool check(Object value) {
+  bool check(Object? value) {
     for (ValueKind kind in kinds) {
       if (kind.check(value)) {
         return true;
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
index da4fc35..725cce1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
@@ -59,7 +59,7 @@
   /// Called when the scanner detects a language version comment
   /// so that the listener can update the scanner configuration
   /// based upon the specified language version.
-  final LanguageVersionChanged languageVersionChanged;
+  final LanguageVersionChanged? languageVersionChanged;
 
   /// Experimental flag for enabling scanning of the `extension` token.
   bool _enableExtensionMethods = false;
@@ -94,12 +94,12 @@
   /**
    * A pointer to the last scanned token.
    */
-  Token tail;
+  late Token tail;
 
   /**
    * A pointer to the last prepended error token.
    */
-  Token errorTail;
+  late Token errorTail;
 
   bool hasErrors = false;
 
@@ -108,14 +108,14 @@
    * before they are assigned to the [Token] precedingComments field
    * of a non-comment token. A value of `null` indicates no comment tokens.
    */
-  CommentToken comments;
+  CommentToken? comments;
 
   /**
    * A pointer to the last scanned comment token or `null` if none.
    */
-  Token commentsTail;
+  Token? commentsTail;
 
-  final List<int> lineStarts;
+  late final List<int> lineStarts;
 
   /**
    * The stack of open groups, e.g [: { ... ( .. :]
@@ -127,9 +127,9 @@
   final bool inRecoveryOption;
   int recoveryCount = 0;
 
-  AbstractScanner(ScannerConfiguration config, this.includeComments,
+  AbstractScanner(ScannerConfiguration? config, this.includeComments,
       this.languageVersionChanged,
-      {int numberOfBytesHint})
+      {int? numberOfBytesHint})
       : lineStarts = new LineStarts(numberOfBytesHint),
         inRecoveryOption = false {
     this.tail = this.tokens;
@@ -154,7 +154,7 @@
   }
 
   @override
-  set configuration(ScannerConfiguration config) {
+  set configuration(ScannerConfiguration? config) {
     if (config != null) {
       _enableExtensionMethods = config.enableExtensionMethods;
       _enableNonNullable = config.enableNonNullable;
@@ -228,7 +228,7 @@
   /**
    * Returns the first token scanned by this [Scanner].
    */
-  Token firstToken() => tokens.next;
+  Token firstToken() => tokens.next!;
 
   /**
    * Notifies that a new token starts at current offset.
@@ -331,7 +331,7 @@
     discardOpenLt();
     while (!groupingStack.isEmpty) {
       unmatchedBeginGroup(groupingStack.head);
-      groupingStack = groupingStack.tail;
+      groupingStack = groupingStack.tail!;
     }
     appendToken(new Token.eof(tokenStart, comments));
   }
@@ -364,7 +364,7 @@
    * Group begin tokens are '{', '(', '[', '<' and '${'.
    */
   void appendBeginGroup(TokenType type) {
-    Token token = new BeginToken(type, tokenStart, comments);
+    BeginToken token = new BeginToken(type, tokenStart, comments);
     appendToken(token);
 
     // { [ ${ cannot appear inside a type parameters / arguments.
@@ -406,13 +406,13 @@
           openKind == OPEN_CURLY_BRACKET_TOKEN);
       // We're ending an interpolated expression.
       begin.endGroup = close;
-      groupingStack = groupingStack.tail;
+      groupingStack = groupingStack.tail!;
       // Using "start-of-text" to signal that we're back in string
       // scanning mode.
       return $STX;
     }
     begin.endGroup = close;
-    groupingStack = groupingStack.tail;
+    groupingStack = groupingStack.tail!;
     return advance();
   }
 
@@ -426,7 +426,7 @@
     if (groupingStack.isEmpty) return;
     if (identical(groupingStack.head.kind, LT_TOKEN)) {
       groupingStack.head.endGroup = tail;
-      groupingStack = groupingStack.tail;
+      groupingStack = groupingStack.tail!;
     }
   }
 
@@ -441,12 +441,12 @@
     if (identical(groupingStack.head.kind, LT_TOKEN)) {
       // Don't assign endGroup: in "T<U<V>>", the '>>' token closes the outer
       // '<', the inner '<' is left without endGroup.
-      groupingStack = groupingStack.tail;
+      groupingStack = groupingStack.tail!;
     }
     if (groupingStack.isEmpty) return;
     if (identical(groupingStack.head.kind, LT_TOKEN)) {
       groupingStack.head.endGroup = tail;
-      groupingStack = groupingStack.tail;
+      groupingStack = groupingStack.tail!;
     }
   }
 
@@ -458,10 +458,10 @@
       errorTail = tail;
     } else {
       token.next = errorTail.next;
-      token.next.previous = token;
+      token.next!.previous = token;
       errorTail.next = token;
       token.previous = errorTail;
-      errorTail = errorTail.next;
+      errorTail = errorTail.next!;
     }
   }
 
@@ -523,7 +523,7 @@
         break; // recover
       }
       first = false;
-      groupingStack = groupingStack.tail;
+      groupingStack = groupingStack.tail!;
     } while (!groupingStack.isEmpty);
 
     recoveryCount++;
@@ -591,7 +591,7 @@
       // The option-runs might have set invalid endGroup pointers. Reset them.
       for (Link<BeginToken> link = originalStack;
           link.isNotEmpty;
-          link = link.tail) {
+          link = link.tail!) {
         link.head.endToken = null;
       }
 
@@ -618,7 +618,7 @@
       if (!identical(entryToUse.head.kind, LT_TOKEN)) {
         unmatchedBeginGroup(originalStack.head);
       }
-      originalStack = originalStack.tail;
+      originalStack = originalStack.tail!;
     }
   }
 
@@ -636,7 +636,7 @@
   void discardOpenLt() {
     while (!groupingStack.isEmpty &&
         identical(groupingStack.head.kind, LT_TOKEN)) {
-      groupingStack = groupingStack.tail;
+      groupingStack = groupingStack.tail!;
     }
   }
 
@@ -650,7 +650,7 @@
     while (!groupingStack.isEmpty) {
       BeginToken beginToken = groupingStack.head;
       unmatchedBeginGroup(beginToken);
-      groupingStack = groupingStack.tail;
+      groupingStack = groupingStack.tail!;
       if (identical(beginToken.kind, STRING_INTERPOLATION_TOKEN)) break;
     }
   }
@@ -1432,7 +1432,7 @@
         createLanguageVersionToken(start, major, minor);
     if (languageVersionChanged != null) {
       // TODO(danrubel): make this required and remove the languageVersion field
-      languageVersionChanged(this, languageVersion);
+      languageVersionChanged!(this, languageVersion);
     } else {
       // TODO(danrubel): remove this hack and require listener to update
       // the scanner's configuration.
@@ -1536,7 +1536,7 @@
 
   void appendDartDoc(int start, TokenType type, bool asciiOnly) {
     if (!includeComments) return;
-    Token newComment = createDartDocToken(type, start, asciiOnly);
+    CommentToken newComment = createDartDocToken(type, start, asciiOnly);
     _appendToCommentStream(newComment);
   }
 
@@ -1557,14 +1557,14 @@
     }
   }
 
-  void _appendToCommentStream(Token newComment) {
+  void _appendToCommentStream(CommentToken newComment) {
     if (comments == null) {
       comments = newComment;
       commentsTail = comments;
     } else {
-      commentsTail.next = newComment;
-      commentsTail.next.previous = commentsTail;
-      commentsTail = commentsTail.next;
+      commentsTail!.next = newComment;
+      commentsTail!.next!.previous = commentsTail;
+      commentsTail = commentsTail!.next;
     }
   }
 
@@ -1580,7 +1580,7 @@
   }
 
   int tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
-    KeywordState state = KeywordState.KEYWORD_STATE;
+    KeywordState? state = KeywordState.KEYWORD_STATE;
     int start = scanOffset;
     // We allow a leading capital character.
     if ($A <= next && next <= $Z) {
@@ -1596,14 +1596,18 @@
       state = state.next(next);
       next = advance();
     }
-    if (state == null || state.keyword == null) {
+    if (state == null) {
       return tokenizeIdentifier(next, start, allowDollar);
     }
-    if (!_enableExtensionMethods && state.keyword == Keyword.EXTENSION) {
+    Keyword? keyword = state.keyword;
+    if (keyword == null) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    }
+    if (!_enableExtensionMethods && keyword == Keyword.EXTENSION) {
       return tokenizeIdentifier(next, start, allowDollar);
     }
     if (!_enableNonNullable &&
-        (state.keyword == Keyword.LATE || state.keyword == Keyword.REQUIRED)) {
+        (keyword == Keyword.LATE || keyword == Keyword.REQUIRED)) {
       return tokenizeIdentifier(next, start, allowDollar);
     }
     if (($A <= next && next <= $Z) ||
@@ -1612,7 +1616,7 @@
         identical(next, $$)) {
       return tokenizeIdentifier(next, start, allowDollar);
     } else {
-      appendKeywordToken(state.keyword);
+      appendKeywordToken(keyword);
       return next;
     }
   }
@@ -1883,7 +1887,7 @@
       if (tail.type == TokenType.IDENTIFIER && tail.charEnd == tokenStart) {
         charOffset = tail.charOffset;
         codeUnits.addAll(tail.lexeme.codeUnits);
-        tail = tail.previous;
+        tail = tail.previous!;
       } else {
         charOffset = errorToken.charOffset;
       }
@@ -1910,7 +1914,9 @@
   }
 
   void unterminatedString(int quoteChar, int quoteStart, int start,
-      {bool asciiOnly, bool isMultiLine, bool isRaw}) {
+      {required bool asciiOnly,
+      required bool isMultiLine,
+      required bool isRaw}) {
     String suffix = new String.fromCharCodes(
         isMultiLine ? [quoteChar, quoteChar, quoteChar] : [quoteChar]);
     String prefix = isRaw ? 'r$suffix' : suffix;
@@ -1938,14 +1944,14 @@
     '{': TokenType.CLOSE_CURLY_BRACKET,
     '<': TokenType.GT,
     r'${': TokenType.CLOSE_CURLY_BRACKET,
-  }[begin.lexeme];
+  }[begin.lexeme]!;
 }
 
 class LineStarts extends Object with ListMixin<int> {
-  List<int> array;
+  late List<int> array;
   int arrayLength = 0;
 
-  LineStarts(int numberOfBytesHint) {
+  LineStarts(int? numberOfBytesHint) {
     // Let's assume the average Dart file is 300 bytes.
     if (numberOfBytesHint == null) numberOfBytesHint = 300;
 
@@ -2038,12 +2044,12 @@
   final bool enableTripleShift;
 
   const ScannerConfiguration({
-    bool enableExtensionMethods,
-    bool enableNonNullable,
-    bool enableTripleShift,
-  })  : this.enableExtensionMethods = enableExtensionMethods ?? false,
-        this.enableNonNullable = enableNonNullable ?? false,
-        this.enableTripleShift = enableTripleShift ?? false;
+    bool enableExtensionMethods = false,
+    bool enableNonNullable = false,
+    bool enableTripleShift = false,
+  })  : this.enableExtensionMethods = enableExtensionMethods,
+        this.enableNonNullable = enableNonNullable,
+        this.enableTripleShift = enableTripleShift;
 }
 
 bool _isIdentifierChar(int next, bool allowDollar) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/error_token.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/error_token.dart
index f7d9d66..9b39e96 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/error_token.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/error_token.dart
@@ -94,13 +94,13 @@
 
   Code<dynamic> get errorCode => assertionMessage.code;
 
-  int get character => null;
+  int? get character => null;
 
-  String get start => null;
+  String? get start => null;
 
-  int get endOffset => null;
+  int? get endOffset => null;
 
-  BeginToken get begin => null;
+  BeginToken? get begin => null;
 
   @override
   Token copy() {
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/errors.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/errors.dart
index 5e87329..a5c83a9 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/errors.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/errors.dart
@@ -16,7 +16,7 @@
   int charOffset = token.charOffset;
   // TODO(paulberry,ahe): why is endOffset sometimes null?
   int endOffset = token.endOffset ?? charOffset;
-  void _makeError(ScannerErrorCode errorCode, List<Object> arguments) {
+  void _makeError(ScannerErrorCode errorCode, List<Object?>? arguments) {
     if (_isAtEnd(token, charOffset)) {
       // Analyzer never generates an error message past the end of the input,
       // since such an error would not be visible in an editor.
@@ -64,8 +64,8 @@
 
     default:
       if (errorCode == codeUnmatchedToken) {
-        charOffset = token.begin.endToken.charOffset;
-        TokenType type = token.begin?.type;
+        charOffset = token.begin!.endToken!.charOffset;
+        TokenType type = token.begin!.type;
         if (type == TokenType.OPEN_CURLY_BRACKET ||
             type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
           return _makeError(ScannerErrorCode.EXPECTED_TOKEN, ['}']);
@@ -94,7 +94,7 @@
 bool _isAtEnd(Token token, int charOffset) {
   while (true) {
     // Skip to the next token.
-    token = token.next;
+    token = token.next!;
     // If we've found an EOF token, its charOffset indicates where the end of
     // the input is.
     if (token.isEof) return token.charOffset == charOffset;
@@ -111,7 +111,7 @@
  * The [arguments] are any arguments needed to complete the error message.
  */
 typedef ReportError(
-    ScannerErrorCode errorCode, int offset, List<Object> arguments);
+    ScannerErrorCode errorCode, int offset, List<Object?>? arguments);
 
 /**
  * The error codes used for errors detected by the scanner.
@@ -181,7 +181,7 @@
    * template. The correction associated with the error will be created from the
    * given [correction] template.
    */
-  const ScannerErrorCode(String name, String message, {String correction})
+  const ScannerErrorCode(String name, String message, {String? correction})
       : super(
           correction: correction,
           message: message,
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/keyword_state.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/keyword_state.dart
index 05f07e0..51a9520 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/keyword_state.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/keyword_state.dart
@@ -12,19 +12,17 @@
  * Abstract state in a state machine for scanning keywords.
  */
 abstract class KeywordState {
-  KeywordState next(int c);
-  KeywordState nextCapital(int c);
+  KeywordState? next(int c);
+  KeywordState? nextCapital(int c);
 
-  analyzer.Keyword get keyword;
+  analyzer.Keyword? get keyword;
 
-  static KeywordState _KEYWORD_STATE;
+  static KeywordState? _KEYWORD_STATE;
   static KeywordState get KEYWORD_STATE {
     if (_KEYWORD_STATE == null) {
-      List<String> strings =
-          new List<String>.filled(analyzer.Keyword.values.length, null);
-      for (int i = 0; i < analyzer.Keyword.values.length; i++) {
-        strings[i] = analyzer.Keyword.values[i].lexeme;
-      }
+      List<String> strings = analyzer.Keyword.values
+          .map((keyword) => keyword.lexeme)
+          .toList(growable: false);
       strings.sort((a, b) => a.compareTo(b));
       _KEYWORD_STATE = computeKeywordStateTable(
           /* start = */ 0,
@@ -32,14 +30,15 @@
           /* offset = */ 0,
           strings.length);
     }
-    return _KEYWORD_STATE;
+    return _KEYWORD_STATE!;
   }
 
   static KeywordState computeKeywordStateTable(
       int start, List<String> strings, int offset, int length) {
     bool isLowercase = true;
 
-    List<KeywordState> table = new List<KeywordState>.filled($z - $A + 1, null);
+    List<KeywordState?> table =
+        new List<KeywordState?>.filled($z - $A + 1, null);
     assert(length != 0);
     int chunk = 0;
     int chunkStart = -1;
@@ -72,7 +71,7 @@
       assert(length == 1);
       return new LeafKeywordState(strings[offset]);
     }
-    String syntax = isLeaf ? strings[offset] : null;
+    String? syntax = isLeaf ? strings[offset] : null;
     if (isLowercase) {
       table = table.sublist($a - $A);
       return new LowerCaseArrayKeywordState(table, syntax);
@@ -86,15 +85,15 @@
  * A state with multiple outgoing transitions.
  */
 abstract class ArrayKeywordState implements KeywordState {
-  final List<KeywordState> table;
-  final analyzer.Keyword keyword;
+  final List<KeywordState?> table;
+  final analyzer.Keyword? keyword;
 
-  ArrayKeywordState(this.table, String syntax)
+  ArrayKeywordState(this.table, String? syntax)
       : keyword = ((syntax == null) ? null : analyzer.Keyword.keywords[syntax]);
 
-  KeywordState next(int c);
+  KeywordState? next(int c);
 
-  KeywordState nextCapital(int c);
+  KeywordState? nextCapital(int c);
 
   String toString() {
     StringBuffer sb = new StringBuffer();
@@ -104,7 +103,7 @@
       sb.write(keyword);
       sb.write(" ");
     }
-    List<KeywordState> foo = table;
+    List<KeywordState?> foo = table;
     for (int i = 0; i < foo.length; i++) {
       if (foo[i] != null) {
         sb.write("${new String.fromCharCodes([i + $a])}: "
@@ -117,25 +116,25 @@
 }
 
 class LowerCaseArrayKeywordState extends ArrayKeywordState {
-  LowerCaseArrayKeywordState(List<KeywordState> table, String syntax)
+  LowerCaseArrayKeywordState(List<KeywordState?> table, String? syntax)
       : super(table, syntax) {
     assert(table.length == $z - $a + 1);
   }
 
-  KeywordState next(int c) => table[c - $a];
+  KeywordState? next(int c) => table[c - $a];
 
-  KeywordState nextCapital(int c) => null;
+  KeywordState? nextCapital(int c) => null;
 }
 
 class UpperCaseArrayKeywordState extends ArrayKeywordState {
-  UpperCaseArrayKeywordState(List<KeywordState> table, String syntax)
+  UpperCaseArrayKeywordState(List<KeywordState?> table, String? syntax)
       : super(table, syntax) {
     assert(table.length == $z - $A + 1);
   }
 
-  KeywordState next(int c) => table[c - $A];
+  KeywordState? next(int c) => table[c - $A];
 
-  KeywordState nextCapital(int c) => table[c - $A];
+  KeywordState? nextCapital(int c) => table[c - $A];
 }
 
 /**
@@ -144,10 +143,11 @@
 class LeafKeywordState implements KeywordState {
   final analyzer.Keyword keyword;
 
-  LeafKeywordState(String syntax) : keyword = analyzer.Keyword.keywords[syntax];
+  LeafKeywordState(String syntax)
+      : keyword = analyzer.Keyword.keywords[syntax]!;
 
-  KeywordState next(int c) => null;
-  KeywordState nextCapital(int c) => null;
+  KeywordState? next(int c) => null;
+  KeywordState? nextCapital(int c) => null;
 
   String toString() => keyword.lexeme;
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/reader.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/reader.dart
index 13460a4..4e073b7 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/reader.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/reader.dart
@@ -60,12 +60,12 @@
   /**
    * The number of characters in the string.
    */
-  int _stringLength;
+  late int _stringLength;
 
   /**
    * The index, relative to the string, of the next character to be read.
    */
-  int _charOffset;
+  late int _charOffset;
 
   /**
    * Initialize a newly created reader to read the characters in the given
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/recover.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/recover.dart
index 4a06122..c18e6b1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/recover.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/recover.dart
@@ -22,14 +22,14 @@
   // Skip over prepended error tokens
   Token token = tokens;
   while (token is ErrorToken) {
-    token = token.next;
+    token = token.next!;
   }
 
   // Assert no error tokens in the remaining tokens
   while (!token.isEof) {
     if (token is ErrorToken) {
       for (int count = 0; count < 3; ++count) {
-        Token previous = token.previous;
+        Token previous = token.previous!;
         if (previous.isEof) break;
         token = previous;
       }
@@ -38,11 +38,11 @@
       for (int count = 0; count < 7; ++count) {
         if (token.isEof) break;
         msg.write(' ${token.runtimeType},');
-        token = token.next;
+        token = token.next!;
       }
       throw msg.toString();
     }
-    token = token.next;
+    token = token.next!;
   }
 
   return tokens;
@@ -54,7 +54,7 @@
 
 Token skipToEof(Token token) {
   while (!token.isEof) {
-    token = token.next;
+    token = token.next!;
   }
   return token;
 }
@@ -66,7 +66,7 @@
     '{': '}',
     '<': '>',
     r'${': '}',
-  }[openBrace];
+  }[openBrace]!;
 }
 
 String closeQuoteFor(String openQuote) {
@@ -79,5 +79,5 @@
     "r'": "'",
     'r"""': '"""',
     "r'''": "'''",
-  }[openQuote];
+  }[openQuote]!;
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart
index f8184e1..63fd51c 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart
@@ -68,9 +68,9 @@
 
 /// Scan/tokenize the given UTF8 [bytes].
 ScannerResult scan(List<int> bytes,
-    {ScannerConfiguration configuration,
+    {ScannerConfiguration? configuration,
     bool includeComments: false,
-    LanguageVersionChanged languageVersionChanged}) {
+    LanguageVersionChanged? languageVersionChanged}) {
   if (bytes.last != 0) {
     throw new ArgumentError("[bytes]: the last byte must be null.");
   }
@@ -83,9 +83,10 @@
 
 /// Scan/tokenize the given [source].
 ScannerResult scanString(String source,
-    {ScannerConfiguration configuration,
+    {ScannerConfiguration? configuration,
     bool includeComments: false,
-    LanguageVersionChanged languageVersionChanged}) {
+    LanguageVersionChanged? languageVersionChanged}) {
+  // ignore: unnecessary_null_comparison
   assert(source != null, 'source must not be null');
   StringScanner scanner = new StringScanner(source,
       configuration: configuration,
@@ -95,10 +96,10 @@
 }
 
 ScannerResult _tokenizeAndRecover(Scanner scanner,
-    {List<int> bytes, String source}) {
+    {List<int>? bytes, String? source}) {
   Token tokens = scanner.tokenize();
   if (scanner.hasErrors) {
-    if (bytes == null) bytes = utf8.encode(source);
+    if (bytes == null) bytes = utf8.encode(source!);
     tokens = scannerRecovery(bytes, tokens, scanner.lineStarts);
   }
   return new ScannerResult(tokens, scanner.lineStarts, scanner.hasErrors);
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/scanner_main.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner_main.dart
index b0232dd..18c7c7e 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/scanner_main.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner_main.dart
@@ -25,7 +25,7 @@
 void printTokens(Token token) {
   while (!token.isEof) {
     print("${token.charOffset}: $token");
-    token = token.next;
+    token = token.next!;
   }
 }
 
@@ -35,7 +35,7 @@
 void verifyErrorTokens(Token firstToken, Uri uri) {
   Token token = firstToken;
   while (token is ErrorToken) {
-    token = token.next;
+    token = token.next!;
   }
 
   while (!token.isEof) {
@@ -49,11 +49,11 @@
       int count = 0;
       token = firstToken;
       while (token != errorToken) {
-        token = token.next;
+        token = token.next!;
         if (count < 10) {
           ++count;
         } else {
-          start = start.next;
+          start = start.next!;
         }
       }
 
@@ -62,12 +62,12 @@
       token = start;
       while (count < 20 && !token.isEof) {
         print("${token.charOffset}: $token");
-        token = token.next;
+        token = token.next!;
         ++count;
       }
       throw 'Out of order ErrorToken: $errorToken';
     }
-    token = token.next;
+    token = token.next!;
   }
 }
 
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/string_canonicalizer.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/string_canonicalizer.dart
index 7370bdf..a43887f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/string_canonicalizer.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/string_canonicalizer.dart
@@ -11,7 +11,7 @@
   int start;
   int end;
   String payload;
-  Node next;
+  Node? next;
   Node(this.data, this.start, this.end, this.payload, this.next);
 }
 
@@ -34,7 +34,7 @@
   int _count = 0;
 
   /// The table itself.
-  List<Node> _nodes = new List<Node>.filled(INITIAL_SIZE, null);
+  List<Node?> _nodes = new List<Node?>.filled(INITIAL_SIZE, null);
 
   static String decode(List<int> data, int start, int end, bool asciiOnly) {
     String s;
@@ -64,15 +64,15 @@
 
   rehash() {
     int newSize = _size * 2;
-    List<Node> newNodes = new List<Node>.filled(newSize, null);
+    List<Node?> newNodes = new List<Node?>.filled(newSize, null);
     for (int i = 0; i < _size; i++) {
-      Node t = _nodes[i];
+      Node? t = _nodes[i];
       while (t != null) {
-        Node n = t.next;
+        Node? n = t.next;
         int newIndex = t.data is String
             ? hashString(t.data, t.start, t.end) & (newSize - 1)
             : hashBytes(t.data, t.start, t.end) & (newSize - 1);
-        Node s = newNodes[newIndex];
+        Node? s = newNodes[newIndex];
         t.next = s;
         newNodes[newIndex] = t;
         t = n;
@@ -88,8 +88,8 @@
         ? hashString(data, start, end)
         : hashBytes(data, start, end);
     index = index & (_size - 1);
-    Node s = _nodes[index];
-    Node t = s;
+    Node? s = _nodes[index];
+    Node? t = s;
     int len = end - start;
     while (t != null) {
       if (t.end - t.start == len) {
@@ -117,7 +117,7 @@
 
   clear() {
     _size = INITIAL_SIZE;
-    _nodes = new List<Node>.filled(_size, null);
+    _nodes = new List<Node?>.filled(_size, null);
     _count = 0;
   }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/string_scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/string_scanner.dart
index b09443e..4b15b5f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/string_scanner.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/string_scanner.dart
@@ -22,15 +22,15 @@
  */
 class StringScanner extends AbstractScanner {
   /** The file content. */
-  String string;
+  late String string;
 
   /** The current offset in [string]. */
-  int scanOffset = -1;
+  late int scanOffset = -1;
 
   StringScanner(String string,
-      {ScannerConfiguration configuration,
+      {ScannerConfiguration? configuration,
       bool includeComments: false,
-      LanguageVersionChanged languageVersionChanged})
+      LanguageVersionChanged? languageVersionChanged})
       : string = ensureZeroTermination(string),
         super(configuration, includeComments, languageVersionChanged);
 
@@ -54,7 +54,7 @@
   static bool isLegalIdentifier(String identifier) {
     StringScanner scanner = new StringScanner(identifier);
     Token startToken = scanner.tokenize();
-    return startToken is! ErrorToken && startToken.next.isEof;
+    return startToken is! ErrorToken && startToken.next!.isEof;
   }
 
   int advance() => string.codeUnitAt(++scanOffset);
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
index 38f0335..9ae4026 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
@@ -39,13 +39,13 @@
   /**
    * The token that corresponds to this token.
    */
-  Token endToken;
+  Token? endToken;
 
   /**
    * Initialize a newly created token to have the given [type] at the given
    * [offset].
    */
-  BeginToken(TokenType type, int offset, [CommentToken precedingComment])
+  BeginToken(TokenType type, int offset, [CommentToken? precedingComment])
       : super(type, offset, precedingComment) {
     assert(type == TokenType.LT ||
         type == TokenType.OPEN_CURLY_BRACKET ||
@@ -58,12 +58,12 @@
   Token copy() => new BeginToken(type, offset, copyComments(precedingComments));
 
   @override
-  Token get endGroup => endToken;
+  Token? get endGroup => endToken;
 
   /**
    * Set the token that corresponds to this token.
    */
-  set endGroup(Token token) {
+  set endGroup(Token? token) {
     endToken = token;
   }
 }
@@ -75,7 +75,7 @@
   /**
    * The token that contains this comment.
    */
-  SimpleToken parent;
+  SimpleToken? parent;
 
   /**
    * Initialize a newly created token to represent a token of the given [type]
@@ -93,12 +93,13 @@
    * This is used when we decide to interpret the comment as syntax.
    */
   void remove() {
+    Token? previous = this.previous;
     if (previous != null) {
       previous.setNextWithoutSettingPrevious(next);
       next?.previous = previous;
     } else {
-      assert(parent.precedingComments == this);
-      parent.precedingComments = next;
+      assert(parent!.precedingComments == this);
+      parent!.precedingComments = next as CommentToken?;
     }
   }
 }
@@ -472,7 +473,7 @@
    * Initialize a newly created token to represent the given [keyword] at the
    * given [offset].
    */
-  KeywordToken(this.keyword, int offset, [CommentToken precedingComment])
+  KeywordToken(this.keyword, int offset, [CommentToken? precedingComment])
       : super(keyword, offset, precedingComment);
 
   @override
@@ -537,15 +538,15 @@
    * The previous token in the token stream.
    */
   @override
-  Token previous;
+  Token? previous;
 
   @override
-  Token next;
+  Token? next;
 
   /**
    * The first comment in the list of comments that precede this token.
    */
-  CommentToken _precedingComment;
+  CommentToken? _precedingComment;
 
   /**
    * Initialize a newly created token to have the given [type] and [offset].
@@ -564,10 +565,10 @@
   int get charEnd => end;
 
   @override
-  Token get beforeSynthetic => null;
+  Token? get beforeSynthetic => null;
 
   @override
-  set beforeSynthetic(Token previous) {
+  set beforeSynthetic(Token? previous) {
     // ignored
   }
 
@@ -575,7 +576,7 @@
   int get end => offset + length;
 
   @override
-  Token get endGroup => null;
+  Token? get endGroup => null;
 
   @override
   bool get isEof => type == TokenType.EOF;
@@ -605,7 +606,7 @@
   bool get isUserDefinableOperator => type.isUserDefinableOperator;
 
   @override
-  Keyword get keyword => null;
+  Keyword? get keyword => null;
 
   @override
   int get kind => type.kind;
@@ -617,31 +618,31 @@
   String get lexeme => type.lexeme;
 
   @override
-  CommentToken get precedingComments => _precedingComment;
+  CommentToken? get precedingComments => _precedingComment;
 
-  void set precedingComments(CommentToken comment) {
+  void set precedingComments(CommentToken? comment) {
     _precedingComment = comment;
     _setCommentParent(_precedingComment);
   }
 
   @override
-  String get stringValue => type.stringValue;
+  String? get stringValue => type.stringValue;
 
   @override
   Token copy() =>
       new SimpleToken(type, offset, copyComments(precedingComments));
 
   @override
-  Token copyComments(Token token) {
+  CommentToken? copyComments(CommentToken? token) {
     if (token == null) {
       return null;
     }
-    Token head = token.copy();
+    CommentToken head = token.copy();
     Token tail = head;
-    token = token.next;
+    token = token.next as CommentToken?;
     while (token != null) {
       tail = tail.setNext(token.copy());
-      token = token.next;
+      token = token.next as CommentToken?;
     }
     return head;
   }
@@ -665,7 +666,7 @@
   }
 
   @override
-  Token setNextWithoutSettingPrevious(Token token) {
+  Token? setNextWithoutSettingPrevious(Token? token) {
     next = token;
     return token;
   }
@@ -680,10 +681,10 @@
    * Sets the `parent` property to `this` for the given [comment] and all the
    * next tokens.
    */
-  void _setCommentParent(CommentToken comment) {
+  void _setCommentParent(CommentToken? comment) {
     while (comment != null) {
       comment.parent = this;
-      comment = comment.next;
+      comment = comment.next as CommentToken?;
     }
   }
 }
@@ -695,14 +696,14 @@
   /**
    * The lexeme represented by this token.
    */
-  String _value;
+  late String _value;
 
   /**
    * Initialize a newly created token to represent a token of the given [type]
    * with the given [value] at the given [offset].
    */
   StringToken(TokenType type, String value, int offset,
-      [CommentToken precedingComment])
+      [CommentToken? precedingComment])
       : super(type, offset, precedingComment) {
     this._value = StringUtilities.intern(value);
   }
@@ -730,7 +731,7 @@
    * [offset].
    */
   SyntheticBeginToken(TokenType type, int offset,
-      [CommentToken precedingComment])
+      [CommentToken? precedingComment])
       : super(type, offset, precedingComment);
 
   @override
@@ -765,7 +766,7 @@
  * A token whose value is independent of it's type.
  */
 class SyntheticStringToken extends StringToken {
-  final int _length;
+  final int? _length;
 
   /**
    * Initialize a newly created token to represent a token of the given [type]
@@ -792,7 +793,7 @@
   SyntheticToken(TokenType type, int offset) : super(type, offset);
 
   @override
-  Token beforeSynthetic;
+  Token? beforeSynthetic;
 
   @override
   bool get isSynthetic => true;
@@ -818,7 +819,7 @@
   }
 
   @override
-  Token beforeSynthetic;
+  Token? beforeSynthetic;
 
   @override
   bool get isSynthetic => true;
@@ -840,13 +841,13 @@
   /**
    * Initialize a newly created token to have the given [type] and [offset].
    */
-  factory Token(TokenType type, int offset, [CommentToken preceedingComment]) =
+  factory Token(TokenType type, int offset, [CommentToken? preceedingComment]) =
       SimpleToken;
 
   /**
    * Initialize a newly created end-of-file token to have the given [offset].
    */
-  factory Token.eof(int offset, [CommentToken precedingComments]) {
+  factory Token.eof(int offset, [CommentToken? precedingComments]) {
     Token eof = new SimpleToken(TokenType.EOF, offset, precedingComments);
     // EOF points to itself so there's always infinite look-ahead.
     eof.previous = eof;
@@ -873,13 +874,13 @@
    * The token before this synthetic token,
    * or `null` if this is not a synthetic `)`, `]`, `}`, or `>` token.
    */
-  Token get beforeSynthetic;
+  Token? get beforeSynthetic;
 
   /**
    * Set token before this synthetic `)`, `]`, `}`, or `>` token,
    * and ignored otherwise.
    */
-  set beforeSynthetic(Token previous);
+  set beforeSynthetic(Token? previous);
 
   @override
   int get end;
@@ -888,7 +889,7 @@
    * The token that corresponds to this token, or `null` if this token is not
    * the first of a pair of matching tokens (such as parentheses).
    */
-  Token get endGroup => null;
+  Token? get endGroup => null;
 
   /**
    * Return `true` if this token represents an end of file.
@@ -944,7 +945,7 @@
   /**
    * Return the keyword, if a keyword token, or `null` otherwise.
    */
-  Keyword get keyword;
+  Keyword? get keyword;
 
   /**
    * The kind enum of this token as determined by its [type].
@@ -964,12 +965,12 @@
   /**
    * Return the next token in the token stream.
    */
-  Token get next;
+  Token? get next;
 
   /**
    * Return the next token in the token stream.
    */
-  void set next(Token next);
+  void set next(Token? next);
 
   @override
   int get offset;
@@ -990,17 +991,17 @@
    * the first preceding comment token will have a lexeme of `/* one */` and
    * the next comment token will have a lexeme of `/* two */`.
    */
-  CommentToken get precedingComments;
+  CommentToken? get precedingComments;
 
   /**
    * Return the previous token in the token stream.
    */
-  Token get previous;
+  Token? get previous;
 
   /**
    * Set the previous token in the token stream to the given [token].
    */
-  void set previous(Token token);
+  void set previous(Token? token);
 
   /**
    * For symbol and keyword tokens, returns the string value represented by this
@@ -1020,7 +1021,7 @@
    * declaration using [:identical(next.stringValue, '('):], which (rightfully)
    * returns false because stringValue returns [:null:].
    */
-  String get stringValue;
+  String? get stringValue;
 
   /**
    * Return the type of the token.
@@ -1037,7 +1038,7 @@
   /**
    * Copy a linked list of comment tokens identical to the given comment tokens.
    */
-  Token copyComments(Token token);
+  CommentToken? copyComments(CommentToken? token);
 
   /**
    * Return `true` if this token has any one of the given [types].
@@ -1056,7 +1057,7 @@
    * which token is the previous token for the given token. Return the token
    * that was passed in.
    */
-  Token setNextWithoutSettingPrevious(Token token);
+  Token? setNextWithoutSettingPrevious(Token? token);
 
   /**
    * Returns a textual representation of this token to be used for debugging
@@ -1083,12 +1084,12 @@
    * `null`. Return the token with the smallest offset, or `null` if the list is
    * empty or if all of the elements of the list are `null`.
    */
-  static Token lexicallyFirst(List<Token> tokens) {
-    Token first = null;
+  static Token? lexicallyFirst(List<Token?> tokens) {
+    Token? first = null;
     int offset = -1;
     int length = tokens.length;
     for (int i = 0; i < length; i++) {
-      Token token = tokens[i];
+      Token? token = tokens[i];
       if (token != null && (offset < 0 || token.offset < offset)) {
         first = token;
         offset = token.offset;
@@ -1693,14 +1694,14 @@
   /**
    * See [Token.stringValue] for an explanation.
    */
-  final String stringValue;
+  final String? stringValue;
 
   const TokenType(this.lexeme, this.name, this.precedence, this.kind,
       {this.isModifier: false,
       this.isOperator: false,
       this.isTopLevelKeyword: false,
       this.isUserDefinableOperator: false,
-      String stringValue: 'unspecified'})
+      String? stringValue: 'unspecified'})
       : this.stringValue = stringValue == 'unspecified' ? lexeme : stringValue;
 
   /**
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart
index a42b728..3c84db5 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart
@@ -34,7 +34,7 @@
    * is canonicalized before the token is created.
    */
   StringToken.fromString(TokenType type, String value, int charOffset,
-      {bool canonicalize: false, analyzer.CommentToken precedingComments})
+      {bool canonicalize: false, analyzer.CommentToken? precedingComments})
       : valueOrLazySubstring = canonicalizedString(
             value, /* start = */ 0, value.length, canonicalize),
         super(type, charOffset, precedingComments);
@@ -45,7 +45,7 @@
    */
   StringToken.fromSubstring(
       TokenType type, String data, int start, int end, int charOffset,
-      {bool canonicalize: false, analyzer.CommentToken precedingComments})
+      {bool canonicalize: false, analyzer.CommentToken? precedingComments})
       : super(type, charOffset, precedingComments) {
     int length = end - start;
     if (length <= LAZY_THRESHOLD) {
@@ -63,7 +63,7 @@
    */
   StringToken.fromUtf8Bytes(TokenType type, List<int> data, int start, int end,
       bool asciiOnly, int charOffset,
-      {analyzer.CommentToken precedingComments})
+      {analyzer.CommentToken? precedingComments})
       : super(type, charOffset, precedingComments) {
     int length = end - start;
     if (length <= LAZY_THRESHOLD) {
@@ -74,7 +74,7 @@
   }
 
   StringToken._(TokenType type, this.valueOrLazySubstring, int charOffset,
-      [analyzer.CommentToken precedingComments])
+      [analyzer.CommentToken? precedingComments])
       : super(type, charOffset, precedingComments);
 
   @override
@@ -85,7 +85,7 @@
       assert(valueOrLazySubstring is _LazySubstring);
       dynamic data = valueOrLazySubstring.data;
       int start = valueOrLazySubstring.start;
-      int end = start + valueOrLazySubstring.length;
+      int end = start + (valueOrLazySubstring as _LazySubstring).length;
       if (data is String) {
         valueOrLazySubstring = canonicalizedString(
             data, start, end, valueOrLazySubstring.boolValue);
@@ -129,7 +129,7 @@
 class SyntheticStringToken extends StringToken
     implements analyzer.SyntheticStringToken {
   SyntheticStringToken(TokenType type, String value, int offset,
-      [analyzer.CommentToken precedingComments])
+      [analyzer.CommentToken? precedingComments])
       : super._(type, value, offset, precedingComments);
 
   @override
@@ -142,7 +142,7 @@
 
 class CommentToken extends StringToken implements analyzer.CommentToken {
   @override
-  analyzer.SimpleToken parent;
+  analyzer.SimpleToken? parent;
 
   /**
    * Creates a lazy comment token. If [canonicalize] is true, the string
@@ -178,11 +178,11 @@
   @override
   void remove() {
     if (previous != null) {
-      previous.setNextWithoutSettingPrevious(next);
+      previous!.setNextWithoutSettingPrevious(next);
       next?.previous = previous;
     } else {
-      assert(parent.precedingComments == this);
-      parent.precedingComments = next as CommentToken;
+      assert(parent!.precedingComments == this);
+      parent!.precedingComments = next as CommentToken;
     }
   }
 }
@@ -200,7 +200,7 @@
 
   LanguageVersionToken.fromSubstring(
       String string, int start, int end, int tokenStart, this.major, this.minor,
-      {bool canonicalize})
+      {bool canonicalize: false})
       : super.fromSubstring(
             TokenType.SINGLE_LINE_COMMENT, string, start, end, tokenStart,
             canonicalize: canonicalize);
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner.dart
index f55b9ee..9ef6fd2 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner.dart
@@ -28,7 +28,7 @@
    *
    * The content is zero-terminated.
    */
-  List<int> bytes;
+  late List<int> bytes;
 
   /**
    * Points to the offset of the last byte returned by [advance].
@@ -84,9 +84,9 @@
    * is not the case, the entire array is copied before scanning.
    */
   Utf8BytesScanner(this.bytes,
-      {ScannerConfiguration configuration,
+      {ScannerConfiguration? configuration,
       bool includeComments: false,
-      LanguageVersionChanged languageVersionChanged})
+      LanguageVersionChanged? languageVersionChanged})
       : super(configuration, includeComments, languageVersionChanged,
             numberOfBytesHint: bytes.length) {
     assert(bytes.last == 0);
diff --git a/pkg/_fe_analyzer_shared/lib/src/sdk/allowed_experiments.dart b/pkg/_fe_analyzer_shared/lib/src/sdk/allowed_experiments.dart
index a7faa11..50a1e65 100644
--- a/pkg/_fe_analyzer_shared/lib/src/sdk/allowed_experiments.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/sdk/allowed_experiments.dart
@@ -4,8 +4,6 @@
 
 import 'dart:convert';
 
-import 'package:meta/meta.dart';
-
 /// Parse the given [jsonText] into the [AllowedExperiments].
 ///
 /// Throw [FormatException] is any format issues are found.
@@ -28,14 +26,14 @@
   final Map<String, List<String>> packageExperiments;
 
   AllowedExperiments({
-    @required this.sdkDefaultExperiments,
-    @required this.sdkLibraryExperiments,
-    @required this.packageExperiments,
+    required this.sdkDefaultExperiments,
+    required this.sdkLibraryExperiments,
+    required this.packageExperiments,
   });
 
   /// Return the set of enabled experiments for the package with the [name],
   /// e.g. "path", possibly `null`.
-  List<String> forPackage(String name) {
+  List<String>? forPackage(String name) {
     return packageExperiments[name];
   }
 
@@ -55,14 +53,14 @@
 
   AllowedExperiments parse() {
     Object rootObject = json.decode(_jsonText);
-    Map<String, Object> map = _mustBeMap(rootObject);
+    Map<String, Object?> map = _mustBeMap(rootObject);
 
     _ensureVersion(map);
 
     _withParsePath('experimentSets', () {
-      Map<String, Object> experimentSetMap =
+      Map<String, Object?> experimentSetMap =
           _requiredMap(map, 'experimentSets');
-      for (MapEntry<String, Object> entry in experimentSetMap.entries) {
+      for (MapEntry<String, Object?> entry in experimentSetMap.entries) {
         String setName = entry.key;
         _withParsePath(setName, () {
           _experimentSets[setName] = _mustBeListOfStrings(entry.value);
@@ -73,7 +71,7 @@
     List<String> sdkDefaultExperimentSet = <String>[];
     Map<String, List<String>> sdkLibraryExperiments = <String, List<String>>{};
     _withParsePath('sdk', () {
-      Map<String, Object> sdkMap = _requiredMap(map, 'sdk');
+      Map<String, Object?> sdkMap = _requiredMap(map, 'sdk');
 
       _withParsePath('default', () {
         sdkDefaultExperimentSet = _experimentList(
@@ -82,14 +80,14 @@
       });
 
       _withParsePath('libraries', () {
-        Map<String, Object> sdkLibraryExperimentsMap =
+        Map<String, Object?>? sdkLibraryExperimentsMap =
             _optionalMap(sdkMap, 'libraries');
         if (sdkLibraryExperimentsMap != null) {
-          for (MapEntry<String, Object> entry
+          for (MapEntry<String, Object?> entry
               in sdkLibraryExperimentsMap.entries) {
             String libraryName = entry.key;
             _withParsePath(libraryName, () {
-              Map<String, Object> libraryMap = _mustBeMap(entry.value);
+              Map<String, Object?> libraryMap = _mustBeMap(entry.value);
               List<String> experimentList = _experimentList(libraryMap);
               sdkLibraryExperiments[libraryName] = experimentList;
             });
@@ -100,12 +98,13 @@
 
     Map<String, List<String>> packageExperiments = <String, List<String>>{};
     _withParsePath('packages', () {
-      Map<String, Object> packageExperimentsMap = _optionalMap(map, 'packages');
+      Map<String, Object?>? packageExperimentsMap =
+          _optionalMap(map, 'packages');
       if (packageExperimentsMap != null) {
-        for (MapEntry<String, Object> entry in packageExperimentsMap.entries) {
+        for (MapEntry<String, Object?> entry in packageExperimentsMap.entries) {
           String packageName = entry.key;
           _withParsePath(packageName, () {
-            Map<String, Object> libraryMap = _mustBeMap(entry.value);
+            Map<String, Object?> libraryMap = _mustBeMap(entry.value);
             List<String> experimentList = _experimentList(libraryMap);
             packageExperiments[packageName] = experimentList;
           });
@@ -120,8 +119,8 @@
     );
   }
 
-  void _ensureVersion(Map<String, Object> map) {
-    Object versionObject = map['version'];
+  void _ensureVersion(Map<String, Object?> map) {
+    Object? versionObject = map['version'];
     if (versionObject is! int || versionObject != 1) {
       throw new FormatException(
         "Expected field 'version' with value '1'; "
@@ -131,9 +130,9 @@
     }
   }
 
-  List<String> _experimentList(Map<String, Object> map) {
+  List<String> _experimentList(Map<String, Object?> map) {
     String experimentSetName = _requiredString(map, 'experimentSet');
-    List<String> result = _experimentSets[experimentSetName];
+    List<String>? result = _experimentSets[experimentSetName];
     if (result != null) {
       return result;
     }
@@ -144,8 +143,8 @@
     );
   }
 
-  List<String> _mustBeListOfStrings(Object object) {
-    if (object is List<Object> && object.every((e) => e is String)) {
+  List<String> _mustBeListOfStrings(Object? object) {
+    if (object is List<Object?> && object.every((e) => e is String)) {
       return List.castFrom(object);
     }
 
@@ -157,8 +156,8 @@
     );
   }
 
-  Map<String, Object> _mustBeMap(Object object) {
-    if (object is Map<String, Object>) {
+  Map<String, Object?> _mustBeMap(Object? object) {
+    if (object is Map<String, Object?>) {
       return object;
     }
 
@@ -170,9 +169,9 @@
     );
   }
 
-  Map<String, Object> _optionalMap(Map<String, Object> map, String name) {
-    Object result = map[name];
-    if (result == null || result is Map<String, Object>) {
+  Map<String, Object?>? _optionalMap(Map<String, Object?> map, String name) {
+    Object? result = map[name];
+    if (result is Map<String, Object?>?) {
       return result;
     }
 
@@ -183,9 +182,9 @@
     );
   }
 
-  Map<String, Object> _requiredMap(Map<String, Object> map, String name) {
-    Object result = map[name];
-    if (result is Map<String, Object>) {
+  Map<String, Object?> _requiredMap(Map<String, Object?> map, String name) {
+    Object? result = map[name];
+    if (result is Map<String, Object?>) {
       return result;
     }
 
@@ -196,8 +195,8 @@
     );
   }
 
-  String _requiredString(Map<String, Object> map, String name) {
-    Object result = map[name];
+  String _requiredString(Map<String, Object?> map, String name) {
+    Object? result = map[name];
     if (result is String) {
       return result;
     }
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/annotated_code_helper.dart b/pkg/_fe_analyzer_shared/lib/src/testing/annotated_code_helper.dart
index d4cb830..000d994 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/annotated_code_helper.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/annotated_code_helper.dart
@@ -15,7 +15,7 @@
   /// The index of the (corresponding) annotation in the annotated code test, or
   /// `null` if the annotation doesn't correspond to an annotation in the
   /// annotated code.
-  final int index;
+  final int? index;
 
   /// 1-based line number of the annotation.
   final int lineNo;
@@ -37,6 +37,7 @@
 
   Annotation(this.index, this.lineNo, this.columnNo, this.offset, this.prefix,
       this.text, this.suffix)
+      // ignore: unnecessary_null_comparison
       : assert(offset != null),
         assert(offset >= 0);
 
@@ -71,7 +72,7 @@
   /// The annotations for the source code.
   final List<Annotation> annotations;
 
-  List<int> _lineStarts;
+  List<int>? _lineStarts;
 
   AnnotatedCode(this.annotatedCode, this.sourceCode, this.annotations);
 
@@ -92,7 +93,7 @@
     List<int> lineStarts = <int>[];
     lineStarts.add(offset);
     while (index < annotatedCode.length) {
-      Match startMatch = start.matchAsPrefix(annotatedCode, index);
+      Match? startMatch = start.matchAsPrefix(annotatedCode, index);
       if (startMatch != null) {
         int startIndex = startMatch.end;
         Iterable<Match> endMatches =
@@ -145,16 +146,17 @@
 
   void _ensureLineStarts() {
     if (_lineStarts == null) {
+      List<int> lineStarts = <int>[];
+      _lineStarts = lineStarts;
       int index = 0;
       int offset = 0;
-      _lineStarts = <int>[];
-      _lineStarts.add(offset);
+      lineStarts.add(offset);
       while (index < sourceCode.length) {
         int charCode = sourceCode.codeUnitAt(index);
         switch (charCode) {
           case _LF:
             offset++;
-            _lineStarts.add(offset);
+            lineStarts.add(offset);
             break;
           case _CR:
             if (index + 1 < sourceCode.length &&
@@ -162,35 +164,35 @@
               index++;
             }
             offset++;
-            _lineStarts.add(offset);
+            lineStarts.add(offset);
             break;
           default:
             offset++;
         }
         index++;
       }
-      _lineStarts.add(offset);
+      lineStarts.add(offset);
     }
   }
 
   void addAnnotation(
       int lineNo, int columnNo, String prefix, String text, String suffix) {
     _ensureLineStarts();
-    int offset = _lineStarts[lineNo - 1] + (columnNo - 1);
+    int offset = _lineStarts![lineNo - 1] + (columnNo - 1);
     annotations.add(new Annotation(
         annotations.length, lineNo, columnNo, offset, prefix, text, suffix));
   }
 
   int get lineCount {
     _ensureLineStarts();
-    return _lineStarts.length;
+    return _lineStarts!.length;
   }
 
   int getLineIndex(int offset) {
     _ensureLineStarts();
     int index = 0;
-    while (index + 1 < _lineStarts.length) {
-      if (_lineStarts[index + 1] <= offset) {
+    while (index + 1 < _lineStarts!.length) {
+      if (_lineStarts![index + 1] <= offset) {
         index++;
       } else {
         break;
@@ -203,8 +205,8 @@
     _ensureLineStarts();
     if (lineIndex < 0) {
       return 0;
-    } else if (lineIndex < _lineStarts.length) {
-      return _lineStarts[lineIndex];
+    } else if (lineIndex < _lineStarts!.length) {
+      return _lineStarts![lineIndex];
     } else {
       return sourceCode.length;
     }
@@ -223,7 +225,7 @@
         int result = a.offset.compareTo(b.offset);
         if (result == 0) {
           if (a.index != null && b.index != null) {
-            result = a.index.compareTo(b.index);
+            result = a.index!.compareTo(b.index!);
           } else if (a.index != null) {
             result = -1;
           } else if (b.index != null) {
@@ -286,13 +288,13 @@
               annotation.prefix,
               annotationText,
               annotation.suffix);
-          map[part].add(subAnnotation);
+          map[part]!.add(subAnnotation);
         }
         continue outer;
       }
     }
     for (String prefix in prefixSet) {
-      map[prefix].add(annotation);
+      map[prefix]!.add(annotation);
     }
   }
   Map<String, AnnotatedCode> split = <String, AnnotatedCode>{};
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/features.dart b/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
index 79072a1..113d1d8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
@@ -36,7 +36,8 @@
 
   /// Add [value] as an element of the list values of feature [key].
   void addElement(String key, [var value]) {
-    List<String> list = _features.putIfAbsent(key, () => <String>[]);
+    List<String> list =
+        _features.putIfAbsent(key, () => <String>[]) as List<String>;
     if (value != null) {
       list.add(value.toString());
     }
@@ -59,10 +60,10 @@
   }
 
   /// Returns the value set for feature [key].
-  Object operator [](String key) => _features[key];
+  Object? operator [](String key) => _features[key];
 
   /// Removes the value set for feature [key]. Returns the existing value.
-  Object remove(String key) => _features.remove(key);
+  Object? remove(String key) => _features.remove(key);
 
   /// Returns `true` if this feature set is empty.
   bool get isEmpty => _features.isEmpty;
@@ -78,7 +79,7 @@
 
   /// Returns a string containing all features in a comma-separated list sorted
   /// by feature names.
-  String getText([String indent]) {
+  String getText([String? indent]) {
     if (indent == null) {
       StringBuffer sb = new StringBuffer();
       bool needsComma = false;
@@ -155,7 +156,7 @@
   ///
   /// Single features will be parsed as strings and list features (features
   /// encoded in `[...]` will be parsed as lists of strings.
-  static Features fromText(String text) {
+  static Features fromText(String? text) {
     Features features = new Features();
     if (text == null) return features;
     int index = 0;
@@ -205,7 +206,7 @@
             endDelimiters.removeLast();
             index++;
           } else {
-            String endDelimiter = delimiters[char];
+            String? endDelimiter = delimiters[char];
             if (endDelimiter != null) {
               endDelimiters.add(endDelimiter);
               index++;
@@ -244,12 +245,12 @@
 }
 
 class FeaturesDataInterpreter implements DataInterpreter<Features> {
-  final String wildcard;
+  final String? wildcard;
 
-  const FeaturesDataInterpreter({this.wildcard: null});
+  const FeaturesDataInterpreter({this.wildcard});
 
   @override
-  String isAsExpected(Features actualFeatures, String expectedData) {
+  String? isAsExpected(Features actualFeatures, String? expectedData) {
     if (wildcard != null && expectedData == wildcard) {
       return null;
     } else if (expectedData == '') {
@@ -265,7 +266,7 @@
           expectMatch = false;
         }
         validatedFeatures.add(key);
-        Object actualValue = actualFeatures[key];
+        Object? actualValue = actualFeatures[key];
         if (!expectMatch) {
           if (actualFeatures.containsKey(key)) {
             errorsFound.add('Unexpected data found for $key=$actualValue');
@@ -284,10 +285,10 @@
             for (Object expectedObject in expectedValue) {
               String expectedText = '$expectedObject';
               bool matchFound = false;
-              if (wildcard != null && expectedText.endsWith(wildcard)) {
+              if (wildcard != null && expectedText.endsWith(wildcard!)) {
                 // Wildcard matcher.
                 String prefix =
-                    expectedText.substring(0, expectedText.indexOf(wildcard));
+                    expectedText.substring(0, expectedText.indexOf(wildcard!));
                 List matches = [];
                 for (Object actualObject in actualList) {
                   if ('$actualObject'.startsWith(prefix)) {
@@ -338,12 +339,12 @@
   }
 
   @override
-  String getText(Features actualData, [String indentation]) {
+  String getText(Features actualData, [String? indentation]) {
     return actualData.getText(indentation);
   }
 
   @override
-  bool isEmpty(Features actualData) {
+  bool isEmpty(Features? actualData) {
     return actualData == null || actualData.isEmpty;
   }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
index 77377cd..f2821d2 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
@@ -83,10 +83,10 @@
   static String idToString(Id id, String value) {
     switch (id.kind) {
       case IdKind.member:
-        MemberId elementId = id;
+        MemberId elementId = id as MemberId;
         return '$memberPrefix${elementId.name}:$value';
       case IdKind.cls:
-        ClassId classId = id;
+        ClassId classId = id as ClassId;
         return '$classPrefix${classId.name}:$value';
       case IdKind.library:
         return '$libraryPrefix$value';
@@ -109,7 +109,6 @@
       case IdKind.error:
         return '$errorPrefix$value';
     }
-    throw new UnsupportedError("Unexpected id kind: ${id.kind}");
   }
 
   static const String globalPrefix = "global#";
@@ -199,7 +198,7 @@
 
 /// Id for an member element.
 class MemberId implements Id {
-  final String className;
+  final String? className;
   final String memberName;
   @override
   final bool isGlobal;
@@ -307,7 +306,9 @@
   final IdKind kind;
 
   const NodeId(this.value, this.kind)
-      : assert(value != null),
+      :
+        // ignore: unnecessary_null_comparison
+        assert(value != null),
         assert(value >= 0);
 
   @override
@@ -341,7 +342,7 @@
 
   int get offset {
     if (id is NodeId) {
-      NodeId nodeId = id;
+      NodeId nodeId = id as NodeId;
       return nodeId.value;
     } else {
       return _offset;
@@ -367,8 +368,8 @@
     if (value != null) {
       ActualData<T> newData = new ActualData<T>(id, value, uri, offset, object);
       if (actualMap.containsKey(id)) {
-        ActualData<T> existingData = actualMap[id];
-        ActualData<T> mergedData = mergeData(existingData, newData);
+        ActualData<T> existingData = actualMap[id]!;
+        ActualData<T>? mergedData = mergeData(existingData, newData);
         if (mergedData != null) {
           actualMap[id] = mergedData;
         } else {
@@ -391,7 +392,7 @@
     }
   }
 
-  ActualData<T> mergeData(ActualData<T> value1, ActualData<T> value2) => null;
+  ActualData<T>? mergeData(ActualData<T> value1, ActualData<T> value2) => null;
 
   /// Called to report duplicate errors.
   void report(Uri uri, int offset, String message);
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
index dd3fdb7e..896c670 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_generation.dart
@@ -12,14 +12,14 @@
     Uri mainUri,
     Map<String, Map<Uri, Map<Id, ActualData<T>>>> actualData,
     DataInterpreter<T> dataInterpreter,
-    {Annotation Function(Annotation expected, Annotation actual) createDiff,
+    {Annotation? Function(Annotation? expected, Annotation? actual)? createDiff,
     bool forceUpdate: false}) {
   Set<Uri> uriSet = {};
   Set<String> actualMarkers = actualData.keys.toSet();
   Map<Uri, Map<Id, Map<String, IdValue>>> idValuePerUri = {};
   Map<Uri, Map<Id, Map<String, ActualData<T>>>> actualDataPerUri = {};
 
-  void addData(String marker, Uri uri, Map<Id, IdValue> data) {
+  void addData(String marker, Uri? uri, Map<Id, IdValue> data) {
     if (uri == null) {
       // TODO(johnniwinther): Avoid `null` URIs.
       assert(data.isEmpty, "Non-empty data without uri: $data");
@@ -43,6 +43,7 @@
   actualData
       .forEach((String marker, Map<Uri, Map<Id, ActualData<T>>> dataPerUri) {
     dataPerUri.forEach((Uri uri, Map<Id, ActualData<T>> dataMap) {
+      // ignore: unnecessary_null_comparison
       if (uri == null) {
         // TODO(johnniwinther): Avoid `null` URIs.
         assert(dataMap.isEmpty, "Non-empty data for `null` uri: $dataMap");
@@ -64,8 +65,9 @@
     Map<Id, Map<String, IdValue>> idValuePerId = idValuePerUri[uri] ?? {};
     Map<Id, Map<String, ActualData<T>>> actualDataPerId =
         actualDataPerUri[uri] ?? {};
-    AnnotatedCode code = annotatedCode[uri];
+    AnnotatedCode code = annotatedCode[uri]!;
     assert(
+        // ignore: unnecessary_null_comparison
         code != null, "No annotated code for ${uri} in ${annotatedCode.keys}");
     result[uri] = _computeAnnotations(code, expectedMaps.keys, actualMarkers,
         idValuePerId, actualDataPerId, dataInterpreter,
@@ -84,12 +86,13 @@
     {String defaultPrefix: '/*',
     String defaultSuffix: '*/',
     bool sortMarkers: true,
-    Annotation Function(Annotation expected, Annotation actual) createDiff,
+    Annotation? Function(Annotation? expected, Annotation? actual)? createDiff,
     bool forceUpdate: false}) {
+  // ignore: unnecessary_null_comparison
   assert(annotatedCode != null);
 
   Annotation createAnnotationFromData(
-      ActualData<T> actualData, Annotation annotation) {
+      ActualData<T> actualData, Annotation? annotation) {
     String getIndentationFromOffset(int offset) {
       int lineIndex = annotatedCode.getLineIndex(offset);
       String line = annotatedCode.getLine(lineIndex);
@@ -161,10 +164,10 @@
 
     Map<String, Annotation> newAnnotationsPerMarker = {};
     for (String marker in supportedMarkers) {
-      IdValue idValue = idValuePerMarker[marker];
-      ActualData<T> actualData = actualDataPerMarker[marker];
-      Annotation expectedAnnotation;
-      Annotation actualAnnotation;
+      IdValue? idValue = idValuePerMarker[marker];
+      ActualData<T>? actualData = actualDataPerMarker[marker];
+      Annotation? expectedAnnotation;
+      Annotation? actualAnnotation;
       if (idValue != null && actualData != null) {
         if (dataInterpreter.isAsExpected(actualData.value, idValue.value) ==
                 null &&
@@ -187,7 +190,7 @@
           actualAnnotation = createAnnotationFromData(actualData, null);
         }
       }
-      Annotation annotation = createDiff != null
+      Annotation? annotation = createDiff != null
           ? createDiff(expectedAnnotation, actualAnnotation)
           : actualAnnotation;
       if (annotation != null) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
index 6ef8308..4149cca 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
@@ -112,7 +112,7 @@
 
 /// Creates an annotation that shows the difference between [expected] and
 /// [actual].
-Annotation createAnnotationsDiff(Annotation expected, Annotation actual) {
+Annotation? createAnnotationsDiff(Annotation? expected, Annotation? actual) {
   if (identical(expected, actual)) return null;
   if (expected != null && actual != null) {
     return new Annotation(
@@ -173,7 +173,7 @@
     _computedDataForEachFile.forEach(f);
   }
 
-  Map<Id, DataType> operator [](Uri file) {
+  Map<Id, DataType>? operator [](Uri file) {
     if (!_computedDataForEachFile.containsKey(file)) {
       _computedDataForEachFile[file] = <Id, DataType>{};
     }
@@ -216,16 +216,17 @@
 // TODO(johnniwinther): Support an empty marker set.
 void computeExpectedMap(Uri sourceUri, String filename, AnnotatedCode code,
     Map<String, MemberAnnotations<IdValue>> maps,
-    {void onFailure(String message),
+    {required void onFailure(String message),
     bool preserveWhitespaceInAnnotations: false,
     bool preserveInfixWhitespaceInAnnotations: false}) {
   List<String> mapKeys = maps.keys.toList();
   Map<String, AnnotatedCode> split = splitByPrefixes(code, mapKeys);
 
   split.forEach((String marker, AnnotatedCode code) {
-    MemberAnnotations<IdValue> fileAnnotations = maps[marker];
+    MemberAnnotations<IdValue> fileAnnotations = maps[marker]!;
+    // ignore: unnecessary_null_comparison
     assert(fileAnnotations != null, "No annotations for $marker in $maps");
-    Map<Id, IdValue> expectedValues = fileAnnotations[sourceUri];
+    Map<Id, IdValue> expectedValues = fileAnnotations[sourceUri]!;
     for (Annotation annotation in code.annotations) {
       String text = annotation.text;
       IdValue idValue = IdValue.decode(sourceUri, annotation, text,
@@ -258,17 +259,17 @@
 /// If [testLibDirectory] is not `null`, files in [testLibDirectory] with the
 /// [testFile] name as a prefix are included.
 TestData computeTestData(FileSystemEntity testFile,
-    {Iterable<String> supportedMarkers,
-    Uri createTestUri(Uri uri, String fileName),
-    void onFailure(String message),
+    {required Iterable<String> supportedMarkers,
+    required Uri createTestUri(Uri uri, String fileName),
+    required void onFailure(String message),
     bool preserveWhitespaceInAnnotations: false,
     bool preserveInfixWhitespaceInAnnotations: false}) {
-  Uri entryPoint;
+  Uri? entryPoint;
 
   String testName;
-  File mainTestFile;
+  File? mainTestFile;
   Uri testFileUri = testFile.uri;
-  Map<String, File> additionalFiles;
+  Map<String, File>? additionalFiles;
   if (testFile is File) {
     testName = testFileUri.pathSegments.last;
     mainTestFile = testFile;
@@ -290,11 +291,13 @@
     }
     assert(
         mainTestFile != null, "No 'main.dart' test file found for $testFile.");
+  } else {
+    throw new UnimplementedError();
   }
 
-  String annotatedCode = new File.fromUri(mainTestFile.uri).readAsStringSync();
+  String annotatedCode = new File.fromUri(mainTestFile!.uri).readAsStringSync();
   Map<Uri, AnnotatedCode> code = {
-    entryPoint:
+    entryPoint!:
         new AnnotatedCode.fromText(annotatedCode, commentStart, commentEnd)
   };
   Map<String, MemberAnnotations<IdValue>> expectedMaps = {};
@@ -302,13 +305,13 @@
     expectedMaps[testMarker] = new MemberAnnotations<IdValue>();
   }
   computeExpectedMap(entryPoint, testFile.uri.pathSegments.last,
-      code[entryPoint], expectedMaps,
+      code[entryPoint]!, expectedMaps,
       onFailure: onFailure,
       preserveWhitespaceInAnnotations: preserveWhitespaceInAnnotations,
       preserveInfixWhitespaceInAnnotations:
           preserveInfixWhitespaceInAnnotations);
   Map<String, String> memorySourceFiles = {
-    entryPoint.path: code[entryPoint].sourceCode
+    entryPoint.path: code[entryPoint]!.sourceCode
   };
 
   if (additionalFiles != null) {
@@ -356,10 +359,10 @@
   final bool isErroneous;
 
   /// The data interpreter used to verify the [compiledData].
-  final DataInterpreter<T> interpreter;
+  final DataInterpreter<T>? interpreter;
 
   /// The actual data computed for the test.
-  final CompiledData<T> compiledData;
+  final CompiledData<T>? compiledData;
 
   TestResult(this.interpreter, this.compiledData, this.hasMismatches)
       : isErroneous = false;
@@ -389,7 +392,7 @@
   CompiledData(this.mainUri, this.actualMaps, this.globalData);
 
   Map<int, List<String>> computeAnnotations(Uri uri) {
-    Map<Id, ActualData<T>> actualMap = actualMaps[uri];
+    Map<Id, ActualData<T>> actualMap = actualMaps[uri]!;
     Map<int, List<String>> annotations = <int, List<String>>{};
     actualMap.forEach((Id id, ActualData<T> data) {
       String value1 = '${data.value}';
@@ -405,7 +408,7 @@
       {bool includeMatches: false}) {
     Map<int, List<String>> annotations = <int, List<String>>{};
     thisMap.forEach((Id id, ActualData<T> thisData) {
-      ActualData<T> otherData = otherMap[id];
+      ActualData<T>? otherData = otherMap[id];
       String thisValue = '${thisData.value}';
       if (thisData.value != otherData?.value) {
         String otherValue = '${otherData?.value ?? '---'}';
@@ -440,7 +443,7 @@
   /// Returns `null` if [actualData] satisfies the [expectedData] annotation.
   /// Otherwise, a message is returned contain the information about the
   /// problems found.
-  String isAsExpected(T actualData, String expectedData);
+  String? isAsExpected(T actualData, String? expectedData);
 
   /// Returns `true` if [actualData] corresponds to empty data.
   bool isEmpty(T actualData);
@@ -449,7 +452,7 @@
   ///
   /// If [indentation] is provided a multiline pretty printing can be returned
   /// using [indentation] for additional lines.
-  String getText(T actualData, [String indentation]);
+  String getText(T actualData, [String? indentation]);
 }
 
 /// Default data interpreter for string data.
@@ -457,8 +460,7 @@
   const StringDataInterpreter();
 
   @override
-  String isAsExpected(String actualData, String expectedData) {
-    actualData ??= '';
+  String? isAsExpected(String actualData, String? expectedData) {
     expectedData ??= '';
     if (actualData != expectedData) {
       return "Expected $expectedData, found $actualData";
@@ -472,7 +474,7 @@
   }
 
   @override
-  String getText(String actualData, [String indentation]) {
+  String getText(String actualData, [String? indentation]) {
     return actualData;
   }
 }
@@ -488,7 +490,7 @@
     if (offset > end) {
       sb.write(sourceCode.substring(end, offset));
     }
-    for (String annotation in annotations[offset]) {
+    for (String annotation in annotations[offset]!) {
       sb.write(colorizeAnnotation('/*', annotation, '*/'));
     }
     end = offset;
@@ -508,22 +510,22 @@
     MemberAnnotations<IdValue> expectedMaps,
     CompiledData<T> compiledData,
     DataInterpreter<T> dataInterpreter,
-    {bool filterActualData(IdValue expected, ActualData<T> actualData),
+    {bool filterActualData(IdValue? expected, ActualData<T> actualData)?,
     bool fatalErrors: true,
     bool succinct: false,
-    void onFailure(String message)}) async {
+    required void onFailure(String message)}) async {
   bool hasFailure = false;
   Set<Uri> neededDiffs = new Set<Uri>();
 
-  void checkActualMap(
-      Map<Id, ActualData<T>> actualMap, Map<Id, IdValue> expectedMap, Uri uri) {
+  void checkActualMap(Map<Id, ActualData<T>> actualMap,
+      Map<Id, IdValue>? expectedMap, Uri uri) {
     expectedMap ??= {};
     bool hasLocalFailure = false;
-    actualMap?.forEach((Id id, ActualData<T> actualData) {
+    actualMap.forEach((Id id, ActualData<T> actualData) {
       T actual = actualData.value;
       String actualText = dataInterpreter.getText(actual);
 
-      if (!expectedMap.containsKey(id)) {
+      if (!expectedMap!.containsKey(id)) {
         if (!dataInterpreter.isEmpty(actual)) {
           String actualValueText = IdValue.idToString(id, actualText);
           compiledData.reportError(
@@ -541,8 +543,8 @@
           }
         }
       } else {
-        IdValue expected = expectedMap[id];
-        String unexpectedMessage =
+        IdValue expected = expectedMap[id]!;
+        String? unexpectedMessage =
             dataInterpreter.isAsExpected(actual, expected.value);
         if (unexpectedMessage != null) {
           String actualValueText = IdValue.idToString(id, actualText);
@@ -566,9 +568,7 @@
     });
     if (hasLocalFailure) {
       hasFailure = true;
-      if (uri != null) {
-        neededDiffs.add(uri);
-      }
+      neededDiffs.add(uri);
     }
   }
 
@@ -580,11 +580,11 @@
 
   Set<Id> missingIds = new Set<Id>();
   void checkMissing(
-      Map<Id, IdValue> expectedMap, Map<Id, ActualData<T>> actualMap,
-      [Uri uri]) {
+      Map<Id, IdValue>? expectedMap, Map<Id, ActualData<T>>? actualMap,
+      [Uri? uri]) {
     actualMap ??= {};
     expectedMap?.forEach((Id id, IdValue expected) {
-      if (!actualMap.containsKey(id)) {
+      if (!actualMap!.containsKey(id)) {
         missingIds.add(id);
         String message = 'MISSING $modeName DATA for ${id.descriptor}: '
             'Expected ${colorizeExpected('$expected')}';
@@ -617,9 +617,9 @@
           createDiff: createAnnotationsDiff);
       for (Uri uri in neededDiffs) {
         print('--annotations diff [${uri.pathSegments.last}]-------------');
-        AnnotatedCode annotatedCode = code[uri];
+        AnnotatedCode? annotatedCode = code[uri];
         print(new AnnotatedCode(annotatedCode?.annotatedCode ?? "",
-                annotatedCode?.sourceCode ?? "", annotations[uri])
+                annotatedCode?.sourceCode ?? "", annotations[uri]!)
             .toText());
         print('----------------------------------------------------------');
       }
@@ -640,7 +640,7 @@
     bool verbose,
     bool succinct,
     bool printCode,
-    Map<String, List<String>> skipMap,
+    Map<String, List<String>>? skipMap,
     Uri nullUri});
 
 /// Compute the file: URI of the file located at `path`, where `path` is
@@ -739,12 +739,12 @@
     {List<String> args: const <String>[],
     int shards: 1,
     int shardIndex: 0,
-    void onTest(Uri uri),
-    Uri createUriForFileName(String fileName),
-    void onFailure(String message),
-    RunTestFunction<T> runTest,
-    List<String> skipList,
-    Map<String, List<String>> skipMap,
+    void onTest(Uri uri)?,
+    required Uri createUriForFileName(String fileName),
+    required void onFailure(String message),
+    required RunTestFunction<T> runTest,
+    List<String>? skipList,
+    Map<String, List<String>>? skipMap,
     bool preserveWhitespaceInAnnotations: false,
     bool preserveInfixWhitespaceInAnnotations: false}) async {
   MarkerOptions markerOptions =
@@ -834,7 +834,7 @@
       hasFailures = true;
     } else if (hasMismatches || (forceUpdate && generateAnnotations)) {
       if (generateAnnotations) {
-        DataInterpreter dataInterpreter;
+        DataInterpreter? dataInterpreter;
         Map<String, Map<Uri, Map<Id, ActualData<T>>>> actualData = {};
         results.forEach((String marker, TestResult<T> result) {
           dataInterpreter ??= result.interpreter;
@@ -842,8 +842,10 @@
               actualData[marker] = {};
 
           void addActualData(Uri uri, Map<Id, ActualData<T>> actualData) {
+            // ignore: unnecessary_null_comparison
             assert(uri != null && testData.code.containsKey(uri) ||
                 actualData.isEmpty);
+            // ignore: unnecessary_null_comparison
             if (uri == null || actualData.isEmpty) {
               // TODO(johnniwinther): Avoid collecting data without
               //  invalid uris.
@@ -854,9 +856,9 @@
             actualDataPerId.addAll(actualData);
           }
 
-          result.compiledData.actualMaps.forEach(addActualData);
+          result.compiledData!.actualMaps.forEach(addActualData);
           addActualData(
-              result.compiledData.mainUri, result.compiledData.globalData);
+              result.compiledData!.mainUri, result.compiledData!.globalData);
         });
 
         Map<Uri, List<Annotation>> annotations = computeAnnotationsPerUri(
@@ -864,16 +866,17 @@
             testData.expectedMaps,
             testData.entryPoint,
             actualData,
-            dataInterpreter,
+            dataInterpreter!,
             forceUpdate: forceUpdate);
         annotations.forEach((Uri uri, List<Annotation> annotations) {
+          // ignore: unnecessary_null_comparison
           assert(uri != null, "Annotations without uri: $annotations");
-          AnnotatedCode code = testData.code[uri];
+          AnnotatedCode? code = testData.code[uri];
           assert(code != null,
               "No annotated code for $uri with annotations: $annotations");
           AnnotatedCode generated = new AnnotatedCode(
               code?.annotatedCode ?? "", code?.sourceCode ?? "", annotations);
-          Uri fileUri = testToFileUri[uri];
+          Uri fileUri = testToFileUri[uri]!;
           new File.fromUri(fileUri).writeAsStringSync(generated.toText());
           print('Generated annotations for ${fileUri}');
         });
@@ -893,9 +896,9 @@
 /// Returns `true` if [testName] is marked as skipped in [skipMap] for
 /// the given [configMarker].
 bool skipForConfig(
-    String testName, String configMarker, Map<String, List<String>> skipMap) {
+    String testName, String configMarker, Map<String, List<String>>? skipMap) {
   if (skipMap != null) {
-    List<String> skipList = skipMap[configMarker];
+    List<String>? skipList = skipMap[configMarker];
     if (skipList != null && skipList.contains(testName)) {
       print("Skip: ${testName} for config '${configMarker}'");
       return true;
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/colors.dart b/pkg/_fe_analyzer_shared/lib/src/util/colors.dart
index f4f1b1b..af78689 100644
--- a/pkg/_fe_analyzer_shared/lib/src/util/colors.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/util/colors.dart
@@ -75,7 +75,7 @@
 /// Boolean value caching whether or not we should display ANSI colors.
 ///
 /// If `null`, we haven't decided whether we should display ANSI colors or not.
-bool _enableColors;
+bool? _enableColors;
 
 /// Finds out whether we are displaying ANSI colors.
 ///
@@ -87,6 +87,7 @@
 /// Allows the client to override the decision of whether to disable ANSI
 /// colors.
 void set enableColors(bool value) {
+  // ignore: unnecessary_null_comparison
   assert(value != null);
   _enableColors = value;
 }
@@ -106,7 +107,7 @@
 
 /// Returns whether [sink] supports ANSI escapes or `null` if it could not be
 /// determined.
-bool _supportsAnsiEscapes(sink) {
+bool? _supportsAnsiEscapes(sink) {
   try {
     // ignore: undefined_getter
     return sink.supportsAnsiEscapes;
@@ -132,8 +133,8 @@
 /// Note: do not call this method directly, as it is expensive to
 /// compute. Instead, use [CompilerContext.enableColors].
 bool _computeEnableColors() {
-  bool stderrSupportsColors = _supportsAnsiEscapes(stdout);
-  bool stdoutSupportsColors = _supportsAnsiEscapes(stderr);
+  bool? stderrSupportsColors = _supportsAnsiEscapes(stdout);
+  bool? stdoutSupportsColors = _supportsAnsiEscapes(stderr);
 
   if (stdoutSupportsColors == false) {
     printEnableColorsReason(
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/link.dart b/pkg/_fe_analyzer_shared/lib/src/util/link.dart
index 2474f06..cfbe99f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/util/link.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/util/link.dart
@@ -9,7 +9,7 @@
 
 class Link<T> implements Iterable<T> {
   T get head => throw new StateError("no elements");
-  Link<T> get tail => null;
+  Link<T>? get tail => null;
 
   const Link();
 
@@ -22,16 +22,9 @@
   void printOn(StringBuffer buffer, [separatedBy]) {}
 
   List<T> toList({bool growable: true}) {
-    List<T> result;
-    if (!growable) {
-      result = new List<T>.filled(slowLength(), null);
-    } else {
-      result = <T>[];
-      result.length = slowLength();
-    }
-    int i = 0;
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
-      result[i++] = link.head;
+    List<T> result = <T>[];
+    for (Link<T> link = this; !link.isEmpty; link = link.tail!) {
+      result.add(link.head);
     }
     return result;
   }
@@ -43,16 +36,17 @@
 
   /// Invokes `fn` for every item in the linked list and returns the results
   /// in a [List].
-  List<E> mapToList<E>(E fn(T item), {bool growable: true}) {
-    List<E> result;
+  /// TODO(scheglov) Rewrite to `List<E>`, or remove.
+  List<E?> mapToList<E>(E fn(T item), {bool growable: true}) {
+    List<E?> result;
     if (!growable) {
-      result = new List<E>.filled(slowLength(), null);
+      result = new List<E?>.filled(slowLength(), null);
     } else {
-      result = <E>[];
+      result = <E?>[];
       result.length = slowLength();
     }
     int i = 0;
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
+    for (Link<T> link = this; !link.isEmpty; link = link.tail!) {
       result[i++] = fn(link.head);
     }
     return result;
@@ -65,7 +59,7 @@
 
   Link<T> reversePrependAll(Link<T> from) {
     if (from.isEmpty) return this;
-    return this.prepend(from.head).reversePrependAll(from.tail);
+    return this.prepend(from.head).reversePrependAll(from.tail!);
   }
 
   Link<T> skip(int n) {
@@ -91,8 +85,8 @@
   int slowLength() => 0;
 
   // TODO(ahe): Remove this method?
-  bool contains(Object element) {
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
+  bool contains(Object? element) {
+    for (Link<T> link = this; !link.isEmpty; link = link.tail!) {
       if (link.head == element) return true;
     }
     return false;
@@ -101,7 +95,7 @@
   // TODO(ahe): Remove this method?
   T get single {
     if (isEmpty) throw new StateError('No elements');
-    if (!tail.isEmpty) throw new StateError('More than one element');
+    if (!tail!.isEmpty) throw new StateError('More than one element');
     return head;
   }
 
@@ -115,7 +109,7 @@
   ///
   /// Returns true for the empty list.
   bool every(bool f(T e)) {
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
+    for (Link<T> link = this; !link.isEmpty; link = link.tail!) {
       if (!f(link.head)) return false;
     }
     return true;
@@ -128,18 +122,18 @@
   Iterable<T> cast<T>() => _unsupported('cast');
   T elementAt(int i) => _unsupported('elementAt');
   Iterable<K> expand<K>(Iterable<K> f(T e)) => _unsupported('expand');
-  T firstWhere(bool f(T e), {T orElse()}) => _unsupported('firstWhere');
+  T firstWhere(bool f(T e), {T orElse()?}) => _unsupported('firstWhere');
   K fold<K>(K initialValue, K combine(K value, T element)) {
     return _unsupported('fold');
   }
 
   Iterable<T> followedBy(Iterable<T> other) => _unsupported('followedBy');
   T get last => _unsupported('get:last');
-  T lastWhere(bool f(T e), {T orElse()}) => _unsupported('lastWhere');
+  T lastWhere(bool f(T e), {T orElse()?}) => _unsupported('lastWhere');
   String join([separator = '']) => _unsupported('join');
   T reduce(T combine(T a, T b)) => _unsupported('reduce');
   Iterable<T> retype<T>() => _unsupported('retype');
-  T singleWhere(bool f(T e), {T orElse()}) => _unsupported('singleWhere');
+  T singleWhere(bool f(T e), {T orElse()?}) => _unsupported('singleWhere');
   Iterable<T> skipWhile(bool f(T e)) => _unsupported('skipWhile');
   Iterable<T> take(int n) => _unsupported('take');
   Iterable<T> takeWhile(bool f(T e)) => _unsupported('takeWhile');
@@ -170,10 +164,10 @@
   T get first;
 
   /// Returns the number of elements in the list being built.
-  final int length;
+  int get length;
 
   /// Returns `true` if the list being built is empty.
-  final bool isEmpty;
+  bool get isEmpty;
 
   /// Removes all added elements and resets the builder.
   void clear();
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/link_implementation.dart b/pkg/_fe_analyzer_shared/lib/src/util/link_implementation.dart
index 7fced1a..70f86ec 100644
--- a/pkg/_fe_analyzer_shared/lib/src/util/link_implementation.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/util/link_implementation.dart
@@ -9,12 +9,12 @@
 import 'link.dart' show Link, LinkBuilder;
 
 class LinkIterator<T> implements Iterator<T> {
-  T _current;
+  T? _current;
   Link<T> _link;
 
   LinkIterator(this._link);
 
-  T get current => _current;
+  T get current => _current!;
 
   bool moveNext() {
     if (_link.isEmpty) {
@@ -22,7 +22,7 @@
       return false;
     }
     _current = _link.head;
-    _link = _link.tail;
+    _link = _link.tail!;
     return true;
   }
 }
@@ -32,11 +32,11 @@
 class MappedLinkIterator<S, T> extends Iterator<T> {
   Transformation<S, T> _transformation;
   Link<S> _link;
-  T _current;
+  T? _current;
 
   MappedLinkIterator(this._link, this._transformation);
 
-  T get current => _current;
+  T get current => _current!;
 
   bool moveNext() {
     if (_link.isEmpty) {
@@ -44,7 +44,7 @@
       return false;
     }
     _current = _transformation(_link.head);
-    _link = _link.tail;
+    _link = _link.tail!;
     return true;
   }
 }
@@ -64,7 +64,7 @@
   final T head;
   Link<T> tail;
 
-  LinkEntry(this.head, [Link<T> tail]) : tail = tail ?? const Link<Null>();
+  LinkEntry(this.head, [Link<T>? tail]) : tail = tail ?? const Link<Never>();
 
   Link<T> prepend(T element) {
     // TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
@@ -74,7 +74,7 @@
   void printOn(StringBuffer buffer, [separatedBy]) {
     buffer.write(head);
     if (separatedBy == null) separatedBy = '';
-    for (Link<T> link = tail; link.isNotEmpty; link = link.tail) {
+    for (Link<T> link = tail; link.isNotEmpty; link = link.tail!) {
       buffer.write(separatedBy);
       buffer.write(link.head);
     }
@@ -91,7 +91,7 @@
   @override
   Link<T> reverse(Link<T> tail) {
     Link<T> result = tail;
-    for (Link<T> link = this; link.isNotEmpty; link = link.tail) {
+    for (Link<T> link = this; link.isNotEmpty; link = link.tail!) {
       result = result.prepend(link.head);
     }
     return result;
@@ -99,7 +99,7 @@
 
   Link<T> reversePrependAll(Link<T> from) {
     Link<T> result;
-    for (result = this; from.isNotEmpty; from = from.tail) {
+    for (result = this; from.isNotEmpty; from = from.tail!) {
       result = result.prepend(from.head);
     }
     return result;
@@ -111,7 +111,7 @@
       if (link.isEmpty) {
         throw new RangeError('Index $n out of range');
       }
-      link = link.tail;
+      link = link.tail!;
     }
     return link;
   }
@@ -120,7 +120,7 @@
   bool get isNotEmpty => true;
 
   void forEach(void f(T element)) {
-    for (Link<T> link = this; link.isNotEmpty; link = link.tail) {
+    for (Link<T> link = this; link.isNotEmpty; link = link.tail!) {
       f(link.head);
     }
   }
@@ -128,21 +128,22 @@
   bool operator ==(other) {
     if (other is! Link<T>) return false;
     Link<T> myElements = this;
-    while (myElements.isNotEmpty && other.isNotEmpty) {
-      if (myElements.head != other.head) {
+    Link<T> otherElements = other;
+    while (myElements.isNotEmpty && otherElements.isNotEmpty) {
+      if (myElements.head != otherElements.head) {
         return false;
       }
-      myElements = myElements.tail;
-      other = other.tail;
+      myElements = myElements.tail!;
+      otherElements = otherElements.tail!;
     }
-    return myElements.isEmpty && other.isEmpty;
+    return myElements.isEmpty && otherElements.isEmpty;
   }
 
   int get hashCode => throw new UnsupportedError('LinkEntry.hashCode');
 
   int slowLength() {
     int length = 0;
-    for (Link<T> current = this; current.isNotEmpty; current = current.tail) {
+    for (Link<T> current = this; current.isNotEmpty; current = current.tail!) {
       ++length;
     }
     return length;
@@ -150,8 +151,8 @@
 }
 
 class LinkBuilderImplementation<T> implements LinkBuilder<T> {
-  LinkEntry<T> head = null;
-  LinkEntry<T> lastLink = null;
+  LinkEntry<T>? head = null;
+  LinkEntry<T>? lastLink = null;
   int length = 0;
 
   LinkBuilderImplementation();
@@ -159,8 +160,8 @@
   @override
   Link<T> toLink(Link<T> tail) {
     if (head == null) return tail;
-    lastLink.tail = tail;
-    Link<T> link = head;
+    lastLink!.tail = tail;
+    Link<T> link = head!;
     lastLink = null;
     head = null;
     length = 0;
@@ -168,14 +169,13 @@
   }
 
   List<T> toList() {
-    if (length == 0) return new List<T>.filled(0, null);
-    List<T> list = new List<T>.filled(length, null);
-    int index = 0;
-    Link<T> link = head;
+    if (length == 0) return <T>[];
+
+    List<T> list = <T>[];
+    Link<T> link = head!;
     while (link.isNotEmpty) {
-      list[index] = link.head;
-      link = link.tail;
-      index++;
+      list.add(link.head);
+      link = link.tail!;
     }
     lastLink = null;
     head = null;
@@ -189,7 +189,7 @@
     if (head == null) {
       head = entry;
     } else {
-      lastLink.tail = entry;
+      lastLink!.tail = entry;
     }
     lastLink = entry;
     return entry;
@@ -199,7 +199,7 @@
 
   T get first {
     if (head != null) {
-      return head.head;
+      return head!.head;
     }
     throw new StateError("no elements");
   }
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index 951d2a4..4252300 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -4,7 +4,7 @@
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
 
 environment:
-  sdk: '>=2.9.0 <3.0.0'
+  sdk: '>=2.12.0-0 <3.0.0'
 dependencies:
   meta: ^1.0.2
 dev_dependencies:
diff --git a/pkg/_fe_analyzer_shared/test/annotated_code_helper_test.dart b/pkg/_fe_analyzer_shared/test/annotated_code_helper_test.dart
index e293175..9fb1558 100644
--- a/pkg/_fe_analyzer_shared/test/annotated_code_helper_test.dart
+++ b/pkg/_fe_analyzer_shared/test/annotated_code_helper_test.dart
@@ -53,7 +53,7 @@
         const StringDataInterpreter());
 
     annotationsPerUri.forEach((Uri uri, List<Annotation> annotations) {
-      AnnotatedCode original = testData.code[uri];
+      AnnotatedCode original = testData.code[uri]!;
       AnnotatedCode generated = new AnnotatedCode(
           original.annotatedCode, original.sourceCode, annotations);
       expectStringEquals(generated.annotatedCode, generated.toText());
diff --git a/pkg/_fe_analyzer_shared/test/constants/data/type_literals.dart b/pkg/_fe_analyzer_shared/test/constants/data/type_literals.dart
index f3f9390..3a0c909 100644
--- a/pkg/_fe_analyzer_shared/test/constants/data/type_literals.dart
+++ b/pkg/_fe_analyzer_shared/test/constants/data/type_literals.dart
@@ -18,7 +18,7 @@
     /*cfe.TypeLiteral(void Function<T>(T))*/ GenericFunctionTypedef;
 const typedefWithFutureOr =
     /*cfe.TypeLiteral(void Function<T>(FutureOr<T>))*/ TypedefWithFutureOr;
-const futureOr = /*cfe.TypeLiteral(FutureOr<dynamic>)*/ FutureOr;
+const futureOr = /*cfe.TypeLiteral(dynamic)*/ FutureOr;
 const null_ = /*cfe.TypeLiteral(Null)*/ Null;
 
 main() {
@@ -48,8 +48,7 @@
 
   print(
       /*analyzer.TypeLiteral(FutureOr<dynamic>*)*/
-      /*cfe.TypeLiteral(FutureOr<dynamic>)*/
-      /*dart2js.TypeLiteral(dynamic)*/
+      /*cfe|dart2js.TypeLiteral(dynamic)*/
       futureOr);
 
   print(
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/and.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/and.dart
new file mode 100644
index 0000000..f0fc09b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/and.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// This test checks that binary `&&` expressions are annotated with the
+// variables written on their right hand sides.  This is needed for legacy type
+// promotion, to ensure that an assignment on the RHS defeats promotion.
+
+/*member: rhs:declared={a, b, c}, read={a, c}, assigned={b}*/
+rhs(bool a, bool b, bool c) {
+  a /*read={c}, assigned={b}*/ && (b = c);
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/assignment.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/assignment.dart
index 08d699d..ddd0931 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/assignment.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/assignment.dart
@@ -2,17 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*member: ordinary:declared={x, y}, assigned={x}*/
+/*member: ordinary:declared={x, y}, read={y}, assigned={x}*/
 ordinary(int x, int y) {
   x = y;
 }
 
-/*member: nullAware:declared={x, y}, assigned={x}*/
+/*member: nullAware:declared={x, y}, read={x, y}, assigned={x}*/
 nullAware(int? x, int y) {
   x ??= y;
 }
 
-/*member: compound:declared={x, y}, assigned={x}*/
+/*member: compound:declared={x, y}, read={x, y}, assigned={x}*/
 compound(int x, int y) {
   x += y;
 }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/conditional.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/conditional.dart
new file mode 100644
index 0000000..4671eff
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/conditional.dart
@@ -0,0 +1,13 @@
+// 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.
+
+// This test checks that conditional (`?:`) expressions are annotated with the
+// variables written in their "then" branches.  This is needed for legacy type
+// promotion, to ensure that an assignment in the "then" branch defeats
+// promotion.
+
+/*member: then:declared={a, b, c, d, e}, read={a, c, e}, assigned={b, d}*/
+then(bool a, bool b, bool c, bool d, bool e) {
+  a /*read={c}, assigned={b}*/ ? b = c : d = e;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart
index cb3d20b..11b6beb 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart
@@ -7,9 +7,9 @@
   [/*assigned={b, c, d}*/ for (a = 0; (b = 0) != 0; c = 0) (d = 0)];
 }
 
-/*member: cStyle_unparenthesized:declared={a, b, c, d, e}, assigned={a, b, d, e}*/
+/*member: cStyle_unparenthesized:declared={a, b, c, d, e}, read={c}, assigned={a, b, d, e}*/
 cStyle_unparenthesized(int a, bool b, bool c, int d, int e) {
-  [/*assigned={b, d, e}*/ for (a = 0; b = c; d = 0) e = 0];
+  [/*read={c}, assigned={b, d, e}*/ for (a = 0; b = c; d = 0) e = 0];
 }
 
 /*member: cStyleWithDeclaration:declared={a, b, c, d, e}, assigned={a, b, c, d}*/
@@ -17,9 +17,9 @@
   [/*assigned={b, c, d}*/ for (int e = (a = 0); (b = 0) != 0; c = 0) (d = 0)];
 }
 
-/*member: cStyleWithDeclaration_unparenthesized:declared={a, b, c, d, e, f}, assigned={a, b, d, e}*/
+/*member: cStyleWithDeclaration_unparenthesized:declared={a, b, c, d, e, f}, read={c}, assigned={a, b, d, e}*/
 cStyleWithDeclaration_unparenthesized(int a, bool b, bool c, int d, int e) {
-  [/*assigned={b, d, e}*/ for (int f = a = 0; b = c; d = 0) e = 0];
+  [/*read={c}, assigned={b, d, e}*/ for (int f = a = 0; b = c; d = 0) e = 0];
 }
 
 /*member: forEach:declared={a, b, c}, assigned={a, b, c}*/
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/if.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/if.dart
new file mode 100644
index 0000000..7a426c9
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/if.dart
@@ -0,0 +1,61 @@
+// 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.
+
+// This test checks that `if` statements and collection elements are annotated
+// with the variables written in their "then" branches.  This is needed for
+// legacy type promotion, to ensure that an assignment in the "then" branch
+// defeats promotion.
+
+/*member: ifThenStatement:declared={a, b, c}, read={a, c}, assigned={b}*/
+ifThenStatement(bool a, bool b, bool c) {
+  /*read={c}, assigned={b}*/ if (a) b = c;
+}
+
+/*member: ifThenElseStatement:declared={a, b, c, d, e}, read={a, c, e}, assigned={b, d}*/
+ifThenElseStatement(bool a, bool b, bool c, bool d, bool e) {
+  /*read={c}, assigned={b}*/ if (a)
+    b = c;
+  else
+    d = e;
+}
+
+/*member: ifThenListElement:declared={a, b, c}, read={a, c}, assigned={b}*/
+ifThenListElement(bool a, bool b, bool c) {
+  [/*read={c}, assigned={b}*/ if (a) b = c];
+}
+
+/*member: ifThenElseListElement:declared={a, b, c, d, e}, read={a, c, e}, assigned={b, d}*/
+ifThenElseListElement(bool a, bool b, bool c, bool d, bool e) {
+  [/*read={c}, assigned={b}*/ if (a) b = c else d = e];
+}
+
+/*member: ifThenSetElement:declared={a, b, c}, read={a, c}, assigned={b}*/
+ifThenSetElement(bool a, bool b, bool c) {
+  ({/*read={c}, assigned={b}*/ if (a) b = c});
+}
+
+/*member: ifThenElseSetElement:declared={a, b, c, d, e}, read={a, c, e}, assigned={b, d}*/
+ifThenElseSetElement(bool a, bool b, bool c, bool d, bool e) {
+  ({/*read={c}, assigned={b}*/ if (a) b = c else d = e});
+}
+
+/*member: ifThenMapKey:declared={a, b, c}, read={a, c}, assigned={b}*/
+ifThenMapKey(bool a, bool b, bool c) {
+  ({/*read={c}, assigned={b}*/ if (a) b = c: null});
+}
+
+/*member: ifThenElseMapKey:declared={a, b, c, d, e}, read={a, c, e}, assigned={b, d}*/
+ifThenElseMapKey(bool a, bool b, bool c, bool d, bool e) {
+  ({/*read={c}, assigned={b}*/ if (a) b = c: null else d = e: null});
+}
+
+/*member: ifThenMapValue:declared={a, b, c}, read={a, c}, assigned={b}*/
+ifThenMapValue(bool a, bool b, bool c) {
+  ({/*read={c}, assigned={b}*/ if (a) null: b = c});
+}
+
+/*member: ifThenElseMapValue:declared={a, b, c, d, e}, read={a, c, e}, assigned={b, d}*/
+ifThenElseMapValue(bool a, bool b, bool c, bool d, bool e) {
+  ({/*read={c}, assigned={b}*/ if (a) null: b = c else null: d = e});
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/postfix.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/postfix.dart
index 8f91e74..df8d011 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/postfix.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/postfix.dart
@@ -2,17 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*member: increment:declared={x}, assigned={x}*/
+/*member: increment:declared={x}, read={x}, assigned={x}*/
 increment(int x) {
   x++;
 }
 
-/*member: decrement:declared={x}, assigned={x}*/
+/*member: decrement:declared={x}, read={x}, assigned={x}*/
 decrement(int x) {
   x--;
 }
 
-/*member: nonNullAssert:declared={x}*/
+/*member: nonNullAssert:declared={x}, read={x}*/
 nonNullAssert(int? x) {
   x!;
 }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/prefix.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/prefix.dart
index 445015c..131b478 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/prefix.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/prefix.dart
@@ -2,27 +2,27 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*member: increment:declared={x}, assigned={x}*/
+/*member: increment:declared={x}, read={x}, assigned={x}*/
 increment(int x) {
   ++x;
 }
 
-/*member: decrement:declared={x}, assigned={x}*/
+/*member: decrement:declared={x}, read={x}, assigned={x}*/
 decrement(int x) {
   --x;
 }
 
-/*member: not:declared={b}*/
+/*member: not:declared={b}, read={b}*/
 not(bool b) {
   !b;
 }
 
-/*member: binaryNot:declared={x}*/
+/*member: binaryNot:declared={x}, read={x}*/
 binaryNot(int x) {
   ~x;
 }
 
-/*member: unaryMinus:declared={x}*/
+/*member: unaryMinus:declared={x}, read={x}*/
 unaryMinus(int x) {
   -x;
 }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart
index cae1c1c..8676f23 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart
@@ -6,6 +6,39 @@
 import 'package:test/test.dart';
 
 main() {
+  test('readCapturedAnywhere records reads in closures', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    var v3 = _Variable('v3');
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.declare(v3);
+    assignedVariables.read(v1);
+    assignedVariables.beginNode();
+    assignedVariables.read(v2);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
+    assignedVariables.read(v3);
+    assignedVariables.finish();
+    expect(assignedVariables.readCapturedAnywhere, {v2});
+  });
+
+  test('readCapturedAnywhere does not record variables local to a closure', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.declare(v2);
+    assignedVariables.read(v1);
+    assignedVariables.read(v2);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
+    assignedVariables.finish();
+    expect(assignedVariables.readCapturedAnywhere, {v1});
+  });
+
   test('capturedAnywhere records assignments in closures', () {
     var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
     var v1 = _Variable('v1');
@@ -39,6 +72,24 @@
     expect(assignedVariables.capturedAnywhere, {v1});
   });
 
+  test('readAnywhere records all reads', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    var v3 = _Variable('v3');
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.declare(v3);
+    assignedVariables.read(v1);
+    assignedVariables.beginNode();
+    assignedVariables.read(v2);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
+    assignedVariables.read(v3);
+    assignedVariables.finish();
+    expect(assignedVariables.readAnywhere, {v1, v2, v3});
+  });
+
   test('writtenAnywhere records all assignments', () {
     var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
     var v1 = _Variable('v1');
@@ -57,6 +108,59 @@
     expect(assignedVariables.writtenAnywhere, {v1, v2, v3});
   });
 
+  test('readInNode ignores reads outside the node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.read(v1);
+    assignedVariables.beginNode();
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.read(v2);
+    assignedVariables.finish();
+    expect(assignedVariables.readInNode(node), isEmpty);
+  });
+
+  test('readInNode records reads inside the node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.read(v1);
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.readInNode(node), {v1});
+  });
+
+  test('readInNode records reads in a nested node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.read(v1);
+    assignedVariables.endNode(_Node());
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.readInNode(node), {v1});
+  });
+
+  test('readInNode records reads in a closure', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.read(v1);
+    var node = _Node();
+    assignedVariables.endNode(node, isClosureOrLateVariableInitializer: true);
+    assignedVariables.finish();
+    expect(assignedVariables.readInNode(node), {v1});
+  });
+
   test('writtenInNode ignores assignments outside the node', () {
     var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
     var v1 = _Variable('v1');
@@ -110,6 +214,46 @@
     expect(assignedVariables.writtenInNode(node), {v1});
   });
 
+  test('readCapturedInNode ignores reads in non-nested closures', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.beginNode();
+    assignedVariables.read(v1);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
+    assignedVariables.beginNode();
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.beginNode();
+    assignedVariables.read(v2);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
+    assignedVariables.finish();
+    expect(assignedVariables.readCapturedInNode(node), isEmpty);
+  });
+
+  test('readCapturedInNode records assignments in nested closures', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.read(v1);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
+    var innerNode = _Node();
+    assignedVariables.endNode(innerNode);
+    var outerNode = _Node();
+    assignedVariables.endNode(outerNode);
+    assignedVariables.finish();
+    expect(assignedVariables.readCapturedInNode(innerNode), {v1});
+    expect(assignedVariables.readCapturedInNode(outerNode), {v1});
+  });
+
   test('capturedInNode ignores assignments in non-nested closures', () {
     var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
     var v1 = _Variable('v1');
@@ -160,8 +304,10 @@
       assignedVariables.beginNode();
       assignedVariables.declare(v1);
       assignedVariables.declare(v2);
+      assignedVariables.read(v1);
       assignedVariables.write(v1);
       assignedVariables.beginNode();
+      assignedVariables.read(v2);
       assignedVariables.write(v2);
       assignedVariables.endNode(_Node(),
           isClosureOrLateVariableInitializer: true);
@@ -171,9 +317,13 @@
       var outerNode = _Node();
       assignedVariables.endNode(outerNode);
       assignedVariables.finish();
+      expect(assignedVariables.readInNode(innerNode), isEmpty);
       expect(assignedVariables.writtenInNode(innerNode), isEmpty);
+      expect(assignedVariables.readCapturedInNode(innerNode), isEmpty);
       expect(assignedVariables.capturedInNode(innerNode), isEmpty);
+      expect(assignedVariables.readInNode(outerNode), isEmpty);
       expect(assignedVariables.writtenInNode(outerNode), isEmpty);
+      expect(assignedVariables.readCapturedInNode(outerNode), isEmpty);
       expect(assignedVariables.capturedInNode(outerNode), isEmpty);
     });
 
@@ -185,8 +335,10 @@
       assignedVariables.beginNode();
       assignedVariables.declare(v1);
       assignedVariables.declare(v2);
+      assignedVariables.read(v1);
       assignedVariables.write(v1);
       assignedVariables.beginNode();
+      assignedVariables.read(v2);
       assignedVariables.write(v2);
       assignedVariables.endNode(_Node(),
           isClosureOrLateVariableInitializer: true);
@@ -196,9 +348,13 @@
       var outerNode = _Node();
       assignedVariables.endNode(outerNode);
       assignedVariables.finish();
+      expect(assignedVariables.readInNode(innerNode), isEmpty);
       expect(assignedVariables.writtenInNode(innerNode), isEmpty);
+      expect(assignedVariables.readCapturedInNode(innerNode), isEmpty);
       expect(assignedVariables.capturedInNode(innerNode), isEmpty);
+      expect(assignedVariables.readInNode(outerNode), isEmpty);
       expect(assignedVariables.writtenInNode(outerNode), isEmpty);
+      expect(assignedVariables.readCapturedInNode(outerNode), isEmpty);
       expect(assignedVariables.capturedInNode(outerNode), isEmpty);
     });
   });
@@ -218,6 +374,23 @@
     expect(assignedVariables.declaredInNode(node), unorderedEquals([v1, v2]));
   });
 
+  test('discardNode percolates reads to enclosing node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    var node = _Node();
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.read(v1);
+    assignedVariables.read(v2);
+    assignedVariables.discardNode();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.readInNode(node), unorderedEquals([v1, v2]));
+  });
+
   test('discardNode percolates writes to enclosing node', () {
     var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
     var v1 = _Variable('v1');
@@ -235,7 +408,28 @@
     expect(assignedVariables.writtenInNode(node), unorderedEquals([v1, v2]));
   });
 
-  test('discardNode percolates captures to enclosing node', () {
+  test('discardNode percolates read captures to enclosing node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    var node = _Node();
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.read(v1);
+    assignedVariables.read(v2);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
+    assignedVariables.discardNode();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(
+        assignedVariables.readCapturedInNode(node), unorderedEquals([v1, v2]));
+  });
+
+  test('discardNode percolates write captures to enclosing node', () {
     var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
     var v1 = _Variable('v1');
     var v2 = _Variable('v2');
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
index 6b7be5d..9838684 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
@@ -7,12 +7,11 @@
 /// AST nodes and then feed them to [Harness.run] to run them through flow
 /// analysis testing.
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 
 const Expression nullLiteral = const _NullLiteral();
 
-Statement assert_(Expression condition, [Expression message]) =>
+Statement assert_(Expression condition, [Expression? message]) =>
     new _Assert(condition, message);
 
 Statement block(List<Statement> statements) => new _Block(statements);
@@ -37,7 +36,7 @@
     SwitchCase._(hasLabel, body);
 
 CatchClause catch_(
-        {Var exception, Var stackTrace, @required List<Statement> body}) =>
+        {Var? exception, Var? stackTrace, required List<Statement> body}) =>
     CatchClause._(body, exception, stackTrace);
 
 /// Creates a pseudo-statement whose function is to verify that flow analysis
@@ -51,7 +50,7 @@
 
 /// Creates a pseudo-statement whose function is to verify that flow analysis
 /// considers [variable]'s assigned state to be promoted to [expectedTypeStr].
-Statement checkPromoted(Var variable, String expectedTypeStr) =>
+Statement checkPromoted(Var variable, String? expectedTypeStr) =>
     new _CheckPromoted(variable, expectedTypeStr);
 
 /// Creates a pseudo-statement whose function is to verify that flow analysis
@@ -68,8 +67,16 @@
 Statement continue_(BranchTargetPlaceholder branchTargetPlaceholder) =>
     new _Continue(branchTargetPlaceholder);
 
-Statement declare(Var variable, {@required bool initialized}) =>
-    new _Declare(variable, initialized);
+Statement declare(Var variable,
+        {required bool initialized,
+        bool isFinal = false,
+        bool isLate = false}) =>
+    new _Declare(variable, initialized ? expr(variable.type.type) : null,
+        isFinal, isLate);
+
+Statement declareInitialized(Var variable, Expression initializer,
+        {bool isFinal = false, bool isLate = false}) =>
+    new _Declare(variable, initializer, isFinal, isLate);
 
 Statement do_(List<Statement> body, Expression condition) =>
     _Do(body, condition);
@@ -82,8 +89,8 @@
 /// Creates a conventional `for` statement.  Optional boolean [forCollection]
 /// indicates that this `for` statement is actually a collection element, so
 /// `null` should be passed to [for_bodyBegin].
-Statement for_(Statement initializer, Expression condition, Expression updater,
-        List<Statement> body,
+Statement for_(Statement? initializer, Expression? condition,
+        Expression? updater, List<Statement> body,
         {bool forCollection = false}) =>
     new _For(initializer, condition, updater, body, forCollection);
 
@@ -107,6 +114,7 @@
 ///     }
 Statement forEachWithVariableDecl(
     Var variable, Expression iterable, List<Statement> body) {
+  // ignore: unnecessary_null_comparison
   assert(variable != null);
   return new _ForEach(variable, iterable, body, true);
 }
@@ -121,12 +129,19 @@
 ///     }
 Statement forEachWithVariableSet(
     Var variable, Expression iterable, List<Statement> body) {
+  // ignore: unnecessary_null_comparison
   assert(variable != null);
   return new _ForEach(variable, iterable, body, false);
 }
 
+/// Creates a [Statement] that, when analyzed, will cause [callback] to be
+/// passed an [SsaNodeHarness] allowing the test to examine the values of
+/// variables' SSA nodes.
+Statement getSsaNodes(void Function(SsaNodeHarness) callback) =>
+    new _GetSsaNodes(callback);
+
 Statement if_(Expression condition, List<Statement> ifTrue,
-        [List<Statement> ifFalse]) =>
+        [List<Statement>? ifFalse]) =>
     new _If(condition, ifTrue, ifFalse);
 
 Statement labeled(Statement body) => new _LabeledStatement(body);
@@ -136,9 +151,11 @@
 Statement return_() => new _Return();
 
 Statement switch_(Expression expression, List<SwitchCase> cases,
-        {@required bool isExhaustive}) =>
+        {required bool isExhaustive}) =>
     new _Switch(expression, cases, isExhaustive);
 
+Expression throw_(Expression operand) => new _Throw(operand);
+
 Statement tryCatch(List<Statement> body, List<CatchClause> catches) =>
     new _TryCatch(body, catches);
 
@@ -151,26 +168,26 @@
 /// Placeholder used by [branchTarget] to tie `break` and `continue` statements
 /// to their branch targets.
 class BranchTargetPlaceholder {
-  Statement _target;
+  late Statement _target;
 
-  /*late*/ BranchTargetPlaceholder._();
+  BranchTargetPlaceholder._();
 }
 
 /// Representation of a single catch clause in a try/catch statement.  Use
 /// [catch_] to create instances of this class.
 class CatchClause implements _Visitable<void> {
   final List<Statement> _body;
-  final Var _exception;
-  final Var _stackTrace;
+  final Var? _exception;
+  final Var? _stackTrace;
 
   CatchClause._(this._body, this._exception, this._stackTrace);
 
   String toString() {
     String initialPart;
     if (_stackTrace != null) {
-      initialPart = 'catch (${_exception.name}, ${_stackTrace.name})';
+      initialPart = 'catch (${_exception!.name}, ${_stackTrace!.name})';
     } else if (_exception != null) {
-      initialPart = 'catch (${_exception.name})';
+      initialPart = 'catch (${_exception!.name})';
     } else {
       initialPart = 'on ...';
     }
@@ -192,12 +209,15 @@
 /// Representation of an expression in the pseudo-Dart language used for flow
 /// analysis testing.  Methods in this class may be used to create more complex
 /// expressions based on this one.
-abstract class Expression implements _Visitable<Type> {
-  const Expression();
+abstract class Expression extends Node implements _Visitable<Type> {
+  const Expression() : super._();
 
   /// If `this` is an expression `x`, creates the expression `x!`.
   Expression get nonNullAssert => new _NonNullAssert(this);
 
+  /// If `this` is an expression `x`, creates the expression `!x`.
+  Expression get not => new _Not(this);
+
   /// If `this` is an expression `x`, creates the expression `(x)`.
   Expression get parenthesized => new _ParenthesizedExpression(this);
 
@@ -218,6 +238,15 @@
   /// If `this` is an expression `x`, creates the expression `x == other`.
   Expression eq(Expression other) => new _Equal(this, other, false);
 
+  /// Creates an [Expression] that, when analyzed, will behave the same as
+  /// `this`, but after visiting it, will cause [callback] to be passed the
+  /// [ExpressionInfo] associated with it.  If the expression has no flow
+  /// analysis information associated with it, `null` will be passed to
+  /// [callback].
+  Expression getExpressionInfo(
+          void Function(ExpressionInfo<Var, Type>?) callback) =>
+      new _GetExpressionInfo(this, callback);
+
   /// If `this` is an expression `x`, creates the expression `x ?? other`.
   Expression ifNull(Expression other) => new _IfNull(this, other);
 
@@ -257,6 +286,8 @@
 /// needed for testing.
 class Harness extends TypeOperations<Var, Type> {
   static const Map<String, bool> _coreSubtypes = const {
+    'bool <: int': false,
+    'bool <: Object': true,
     'double <: Object': true,
     'double <: num': true,
     'double <: num?': true,
@@ -319,12 +350,14 @@
     'Object <: num': false,
     'Object <: num?': false,
     'Object <: Object?': true,
+    'Object <: String': false,
     'Object? <: Object': false,
     'Object? <: int': false,
     'Object? <: int?': false,
     'String <: int': false,
     'String <: int?': false,
     'String <: num?': false,
+    'String <: Object': true,
     'String <: Object?': true,
   };
 
@@ -334,7 +367,9 @@
     'Object? - num?': Type('Object'),
     'Object? - Object?': Type('Never?'),
     'Object? - String': Type('Object?'),
+    'Object - bool': Type('Object'),
     'Object - int': Type('Object'),
+    'Object - String': Type('Object'),
     'int - Object': Type('Never'),
     'int - String': Type('int'),
     'int - int': Type('Never'),
@@ -361,22 +396,34 @@
     'num* - Object': Type('Never'),
   };
 
+  final bool allowLocalBooleanVarsToPromote;
+
+  final bool legacy;
+
   final Map<String, bool> _subtypes = Map.of(_coreSubtypes);
 
   final Map<String, Type> _factorResults = Map.of(_coreFactors);
 
-  Node _currentSwitch;
+  Node? _currentSwitch;
+
+  Map<String, Map<String, String>> _promotionExceptions = {};
+
+  Harness({this.allowLocalBooleanVarsToPromote = false, this.legacy = false});
 
   /// Updates the harness so that when a [factor] query is invoked on types
   /// [from] and [what], [result] will be returned.
-  void addFactor(Type from, Type what, Type result) {
+  void addFactor(String from, String what, String result) {
     var query = '$from - $what';
-    _factorResults[query] = result;
+    _factorResults[query] = Type(result);
+  }
+
+  void addPromotionException(String from, String to, String result) {
+    (_promotionExceptions[from] ??= {})[to] = result;
   }
 
   /// Updates the harness so that when an [isSubtypeOf] query is invoked on
   /// types [leftType] and [rightType], [isSubtype] will be returned.
-  void addSubtype(Type leftType, Type rightType, bool isSubtype) {
+  void addSubtype(String leftType, String rightType, bool isSubtype) {
     var query = '$leftType <: $rightType';
     _subtypes[query] = isSubtype;
   }
@@ -431,14 +478,22 @@
   void run(List<Statement> statements) {
     var assignedVariables = AssignedVariables<Node, Var>();
     statements._preVisit(assignedVariables);
-    var flow = FlowAnalysis<Node, Statement, Expression, Var, Type>(
-        this, assignedVariables);
+    var flow = legacy
+        ? FlowAnalysis<Node, Statement, Expression, Var, Type>.legacy(
+            this, assignedVariables)
+        : FlowAnalysis<Node, Statement, Expression, Var, Type>(
+            this, assignedVariables,
+            allowLocalBooleanVarsToPromote: allowLocalBooleanVarsToPromote);
     statements._visit(this, flow);
     flow.finish();
   }
 
   @override
-  Type tryPromoteToType(Type to, Type from) {
+  Type? tryPromoteToType(Type to, Type from) {
+    var exception = (_promotionExceptions[from.type] ?? {})[to.type];
+    if (exception != null) {
+      return Type(exception);
+    }
     if (isSubtypeOf(to, from)) {
       return to;
     } else {
@@ -475,6 +530,10 @@
         !isSameType(promoteToNonNull(type1), type1)) {
       // type1 is already nullable
       return type1;
+    } else if (type1.type == 'Never') {
+      return type2;
+    } else if (type2.type == 'Never') {
+      return type1;
     } else {
       throw UnimplementedError(
           'TODO(paulberry): least upper bound of $type1 and $type2');
@@ -485,7 +544,19 @@
 /// Representation of an expression or statement in the pseudo-Dart language
 /// used for flow analysis testing.
 class Node {
-  Node._();
+  const Node._();
+}
+
+/// Helper class allowing tests to examine the values of variables' SSA nodes.
+class SsaNodeHarness {
+  final FlowAnalysis<Node, Statement, Expression, Var, Type> _flow;
+
+  SsaNodeHarness(this._flow);
+
+  /// Gets the SSA node associated with [variable] at the current point in
+  /// control flow, or `null` if the variable has been write captured.
+  SsaNode<Var, Type>? operator [](Var variable) =>
+      _flow.ssaNodeForTesting(variable);
 }
 
 /// Representation of a statement in the pseudo-Dart language used for flow
@@ -517,7 +588,7 @@
 
   void _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
-    flow.switchStatement_beginCase(_hasLabel, h._currentSwitch);
+    flow.switchStatement_beginCase(_hasLabel, h._currentSwitch!);
     _body._visit(h, flow);
   }
 }
@@ -550,13 +621,18 @@
   Var(this.name, String typeStr) : type = Type(typeStr);
 
   /// Creates an expression representing a read of this variable.
-  Expression get read => new _VariableRead(this);
+  Expression get read => new _VariableRead(this, null);
+
+  /// Creates an expression representing a read of this variable, which as a
+  /// side effect will call the given callback with the returned promoted type.
+  Expression readAndCheckPromotedType(void Function(Type?) callback) =>
+      new _VariableRead(this, callback);
 
   @override
   String toString() => '$type $name';
 
   /// Creates an expression representing a write to this variable.
-  Expression write(Expression value) => new _Write(this, value);
+  Expression write(Expression? value) => new _Write(this, value);
 }
 
 class _As extends Expression {
@@ -584,7 +660,7 @@
 
 class _Assert extends Statement {
   final Expression condition;
-  final Expression message;
+  final Expression? message;
 
   _Assert(this.condition, this.message) : super._();
 
@@ -662,6 +738,7 @@
   @override
   void _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
+    // ignore: unnecessary_null_comparison
     assert(branchTargetPlaceholder._target != null);
     flow.handleBreak(branchTargetPlaceholder._target);
   }
@@ -691,7 +768,7 @@
 
 class _CheckPromoted extends Statement {
   final Var variable;
-  final String expectedTypeStr;
+  final String? expectedTypeStr;
 
   _CheckPromoted(this.variable, this.expectedTypeStr) : super._();
 
@@ -713,7 +790,7 @@
     if (expectedTypeStr == null) {
       expect(promotedType, isNull);
     } else {
-      expect(promotedType.type, expectedTypeStr);
+      expect(promotedType?.type, expectedTypeStr);
     }
   }
 }
@@ -771,7 +848,9 @@
   @override
   void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
     condition._preVisit(assignedVariables);
+    assignedVariables.beginNode();
     ifTrue._preVisit(assignedVariables);
+    assignedVariables.endNode(this);
     ifFalse._preVisit(assignedVariables);
   }
 
@@ -779,7 +858,7 @@
   Type _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
     flow.conditional_conditionBegin();
-    flow.conditional_thenBegin(condition.._visit(h, flow));
+    flow.conditional_thenBegin(condition.._visit(h, flow), this);
     var ifTrueType = ifTrue._visit(h, flow);
     flow.conditional_elseBegin(ifTrue);
     var ifFalseType = ifFalse._visit(h, flow);
@@ -802,6 +881,7 @@
   @override
   void _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
+    // ignore: unnecessary_null_comparison
     assert(branchTargetPlaceholder._target != null);
     flow.handleContinue(branchTargetPlaceholder._target);
   }
@@ -809,20 +889,38 @@
 
 class _Declare extends Statement {
   final Var variable;
-  final bool initialized;
+  final Expression? initializer;
+  final bool isFinal;
+  final bool isLate;
 
-  _Declare(this.variable, this.initialized) : super._();
+  _Declare(this.variable, this.initializer, this.isFinal, this.isLate)
+      : super._();
 
   @override
-  String toString() => '$variable${initialized ? ' = ...' : ''};';
+  String toString() {
+    var latePart = isLate ? 'late ' : '';
+    var finalPart = isFinal ? 'final ' : '';
+    var initializerPart = initializer != null ? ' = $initializer' : '';
+    return '$latePart$finalPart$variable${initializerPart};';
+  }
 
   @override
-  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}
+  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
+    initializer?._preVisit(assignedVariables);
+  }
 
   @override
   void _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
-    flow.declare(variable, initialized);
+    var initializer = this.initializer;
+    if (initializer == null) {
+      flow.declare(variable, false);
+    } else {
+      var initializerType = initializer._visit(h, flow);
+      flow.declare(variable, true);
+      flow.initialize(variable, initializerType, initializer,
+          isFinal: isFinal, isLate: isLate);
+    }
   }
 }
 
@@ -902,9 +1000,9 @@
 }
 
 class _For extends Statement {
-  final Statement initializer;
-  final Expression condition;
-  final Expression updater;
+  final Statement? initializer;
+  final Expression? condition;
+  final Expression? updater;
   final List<Statement> body;
   final bool forCollection;
 
@@ -957,7 +1055,7 @@
 }
 
 class _ForEach extends Statement {
-  final Var variable;
+  final Var? variable;
   final Expression iterable;
   final List<Statement> body;
   final bool declaresVariable;
@@ -973,7 +1071,7 @@
     } else if (declaresVariable) {
       declarationPart = variable.toString();
     } else {
-      declarationPart = variable.name;
+      declarationPart = variable!.name;
     }
     return 'for ($declarationPart in $iterable) ${block(body)}';
   }
@@ -983,9 +1081,9 @@
     iterable._preVisit(assignedVariables);
     if (variable != null) {
       if (declaresVariable) {
-        assignedVariables.declare(variable);
+        assignedVariables.declare(variable!);
       } else {
-        assignedVariables.write(variable);
+        assignedVariables.write(variable!);
       }
     }
     assignedVariables.beginNode();
@@ -1003,22 +1101,61 @@
   }
 }
 
+class _GetExpressionInfo extends Expression {
+  final Expression target;
+
+  final void Function(ExpressionInfo<Var, Type>?) callback;
+
+  _GetExpressionInfo(this.target, this.callback);
+
+  @override
+  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
+    target._preVisit(assignedVariables);
+  }
+
+  @override
+  Type _visit(
+      Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
+    var type = target._visit(h, flow);
+    flow.forwardExpression(this, target);
+    callback(flow.expressionInfoForTesting(this));
+    return type;
+  }
+}
+
+class _GetSsaNodes extends Statement {
+  final void Function(SsaNodeHarness) callback;
+
+  _GetSsaNodes(this.callback) : super._();
+
+  @override
+  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}
+
+  @override
+  void _visit(
+      Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
+    callback(SsaNodeHarness(flow));
+  }
+}
+
 class _If extends Statement {
   final Expression condition;
   final List<Statement> ifTrue;
-  final List<Statement> ifFalse;
+  final List<Statement>? ifFalse;
 
   _If(this.condition, this.ifTrue, this.ifFalse) : super._();
 
   @override
   String toString() =>
       'if ($condition) ${block(ifTrue)}' +
-      (ifFalse == null ? '' : 'else ${block(ifFalse)}');
+      (ifFalse == null ? '' : 'else ${block(ifFalse!)}');
 
   @override
   void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
     condition._preVisit(assignedVariables);
+    assignedVariables.beginNode();
     ifTrue._preVisit(assignedVariables);
+    assignedVariables.endNode(this);
     ifFalse?._preVisit(assignedVariables);
   }
 
@@ -1026,13 +1163,13 @@
   void _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
     flow.ifStatement_conditionBegin();
-    flow.ifStatement_thenBegin(condition.._visit(h, flow));
+    flow.ifStatement_thenBegin(condition.._visit(h, flow), this);
     ifTrue._visit(h, flow);
     if (ifFalse == null) {
       flow.ifStatement_end(false);
     } else {
       flow.ifStatement_elseBegin();
-      ifFalse._visit(h, flow);
+      ifFalse!._visit(h, flow);
       flow.ifStatement_end(true);
     }
   }
@@ -1138,7 +1275,7 @@
   final Expression rhs;
   final bool isAnd;
 
-  _Logical(this.lhs, this.rhs, {@required this.isAnd});
+  _Logical(this.lhs, this.rhs, {required this.isAnd});
 
   @override
   String toString() => '$lhs ${isAnd ? '&&' : '||'} $rhs';
@@ -1146,14 +1283,16 @@
   @override
   void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
     lhs._preVisit(assignedVariables);
+    assignedVariables.beginNode();
     rhs._preVisit(assignedVariables);
+    assignedVariables.endNode(this);
   }
 
   @override
   Type _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
     flow.logicalBinaryOp_begin();
-    flow.logicalBinaryOp_rightBegin(lhs.._visit(h, flow), isAnd: isAnd);
+    flow.logicalBinaryOp_rightBegin(lhs.._visit(h, flow), this, isAnd: isAnd);
     flow.logicalBinaryOp_end(this, rhs.._visit(h, flow), isAnd: isAnd);
     return Type('bool');
   }
@@ -1181,6 +1320,27 @@
   }
 }
 
+class _Not extends Expression {
+  final Expression operand;
+
+  _Not(this.operand);
+
+  @override
+  String toString() => '!$operand';
+
+  @override
+  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
+    operand._preVisit(assignedVariables);
+  }
+
+  @override
+  Type _visit(
+      Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
+    flow.logicalNot_end(this, operand.._visit(h, flow));
+    return Type('bool');
+  }
+}
+
 class _NullAwareAccess extends Expression {
   final Expression lhs;
   final Expression rhs;
@@ -1321,6 +1481,28 @@
   }
 }
 
+class _Throw extends Expression {
+  final Expression operand;
+
+  _Throw(this.operand);
+
+  @override
+  String toString() => 'throw ...';
+
+  @override
+  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
+    operand._preVisit(assignedVariables);
+  }
+
+  @override
+  Type _visit(
+      Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
+    operand._visit(h, flow);
+    flow.handleExit();
+    return Type('Never');
+  }
+}
+
 class _TryCatch extends Statement {
   final List<Statement> body;
   final List<CatchClause> catches;
@@ -1384,18 +1566,24 @@
 class _VariableRead extends Expression {
   final Var variable;
 
-  _VariableRead(this.variable);
+  final void Function(Type?)? callback;
+
+  _VariableRead(this.variable, this.callback);
 
   @override
   String toString() => variable.name;
 
   @override
-  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {}
+  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
+    assignedVariables.read(variable);
+  }
 
   @override
   Type _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
-    return flow.variableRead(this, variable) ?? variable.type;
+    var readResult = flow.variableRead(this, variable);
+    callback?.call(readResult);
+    return readResult ?? variable.type;
   }
 }
 
@@ -1418,7 +1606,7 @@
   @override
   void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
     assignedVariables.beginNode();
-    condition?._preVisit(assignedVariables);
+    condition._preVisit(assignedVariables);
     body._preVisit(assignedVariables);
     assignedVariables.endNode(this);
   }
@@ -1427,7 +1615,7 @@
   void _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
     flow.whileStatement_conditionBegin(this);
-    condition?._visit(h, flow);
+    condition._visit(h, flow);
     flow.whileStatement_bodyBegin(this, condition);
     body._visit(h, flow);
     flow.whileStatement_end();
@@ -1435,9 +1623,9 @@
 }
 
 class _WrappedExpression extends Expression {
-  final Statement before;
+  final Statement? before;
   final Expression expr;
-  final Statement after;
+  final Statement? after;
 
   _WrappedExpression(this.before, this.expr, this.after);
 
@@ -1475,7 +1663,7 @@
 
 class _Write extends Expression {
   final Var variable;
-  final Expression rhs;
+  final Expression? rhs;
 
   _Write(this.variable, this.rhs);
 
@@ -1485,14 +1673,15 @@
   @override
   void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
     assignedVariables.write(variable);
-    rhs._preVisit(assignedVariables);
+    rhs?._preVisit(assignedVariables);
   }
 
   @override
   Type _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
-    var type = rhs._visit(h, flow);
-    flow.write(variable, type);
+    var rhs = this.rhs;
+    var type = rhs == null ? variable.type : rhs._visit(h, flow);
+    flow.write(variable, type, rhs);
     return type;
   }
 }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index 7d3a04f..9621ff7 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -12,10 +12,13 @@
     test('asExpression_end promotes variables', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforePromotion;
       h.run([
         declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforePromotion = nodes[x]!),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
+        getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
       ]);
     });
 
@@ -164,17 +167,32 @@
       ]);
     });
 
+    test('declare() sets Ssa', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      h.run([
+        declare(x, initialized: false),
+        getSsaNodes((nodes) {
+          expect(nodes[x], isNotNull);
+        }),
+      ]);
+    });
+
     test('equalityOp(x != null) promotes true branch', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforePromotion;
       h.run([
         declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforePromotion = nodes[x]!),
         if_(x.read.notEq(nullLiteral), [
           checkReachable(true),
           checkPromoted(x, 'int'),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ], [
           checkReachable(true),
           checkNotPromoted(x),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ]),
       ]);
     });
@@ -232,14 +250,18 @@
     test('equalityOp(x == null) promotes false branch', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforePromotion;
       h.run([
         declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforePromotion = nodes[x]!),
         if_(x.read.eq(nullLiteral), [
           checkReachable(true),
           checkNotPromoted(x),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ], [
           checkReachable(true),
           checkPromoted(x, 'int'),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ]),
       ]);
     });
@@ -262,12 +284,16 @@
     test('equalityOp(null != x) promotes true branch', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforePromotion;
       h.run([
         declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforePromotion = nodes[x]!),
         if_(nullLiteral.notEq(x.read), [
           checkPromoted(x, 'int'),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ], [
           checkNotPromoted(x),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ]),
       ]);
     });
@@ -288,12 +314,16 @@
     test('equalityOp(null == x) promotes false branch', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforePromotion;
       h.run([
         declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforePromotion = nodes[x]!),
         if_(nullLiteral.eq(x.read), [
           checkNotPromoted(x),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ], [
           checkPromoted(x, 'int'),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ]),
       ]);
     });
@@ -381,14 +411,39 @@
       ]);
     });
 
+    test('declare(initialized: false) assigns new SSA ids', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      var y = Var('y', 'int?');
+      h.run([
+        declare(x, initialized: false),
+        declare(y, initialized: false),
+        getSsaNodes((nodes) => expect(nodes[y], isNot(nodes[x]))),
+      ]);
+    });
+
+    test('declare(initialized: true) assigns new SSA ids', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      var y = Var('y', 'int?');
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        getSsaNodes((nodes) => expect(nodes[y], isNot(nodes[x]))),
+      ]);
+    });
+
     test('doStatement_bodyBegin() un-promotes', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforeLoop;
       h.run([
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
+        getSsaNodes((nodes) => ssaBeforeLoop = nodes[x]!),
         branchTarget((t) => do_([
+              getSsaNodes((nodes) => expect(nodes[x], isNot(ssaBeforeLoop))),
               checkNotPromoted(x),
               x.write(expr('Null')).stmt,
             ], expr('bool'))),
@@ -447,23 +502,33 @@
     test('finish checks proper nesting', () {
       var h = Harness();
       var e = expr('Null');
+      var s = if_(e, []);
       var flow = FlowAnalysis<Node, Statement, Expression, Var, Type>(
           h, AssignedVariables<Node, Var>());
       flow.ifStatement_conditionBegin();
-      flow.ifStatement_thenBegin(e);
+      flow.ifStatement_thenBegin(e, s);
       expect(() => flow.finish(), _asserts);
     });
 
     test('for_conditionBegin() un-promotes', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforeLoop;
       h.run([
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
-        for_(null, checkNotPromoted(x).thenExpr(expr('bool')), null, [
-          x.write(expr('int?')).stmt,
-        ]),
+        getSsaNodes((nodes) => ssaBeforeLoop = nodes[x]!),
+        for_(
+            null,
+            block([
+              checkNotPromoted(x),
+              getSsaNodes((nodes) => expect(nodes[x], isNot(ssaBeforeLoop))),
+            ]).thenExpr(expr('bool')),
+            null,
+            [
+              x.write(expr('int?')).stmt,
+            ]),
       ]);
     });
 
@@ -587,15 +652,75 @@
       ]);
     });
 
+    test('for_end() with break updates Ssa of modified vars', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      var y = Var('x', 'int?');
+      late SsaNode<Var, Type> xSsaInsideLoop;
+      late SsaNode<Var, Type> ySsaInsideLoop;
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        branchTarget((t) => for_(null, expr('bool'), null, [
+              x.write(expr('int?')).stmt,
+              if_(expr('bool'), [break_(t)]),
+              getSsaNodes((nodes) {
+                xSsaInsideLoop = nodes[x]!;
+                ySsaInsideLoop = nodes[y]!;
+              }),
+            ])),
+        getSsaNodes((nodes) {
+          // x's Ssa should have been changed because of the join at the end of
+          // of the loop.  y's should not, since it retains the value it had
+          // prior to the loop.
+          expect(nodes[x], isNot(xSsaInsideLoop));
+          expect(nodes[y], same(ySsaInsideLoop));
+        }),
+      ]);
+    });
+
+    test(
+        'for_end() with break updates Ssa of modified vars when types were '
+        'tested', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      var y = Var('x', 'int?');
+      late SsaNode<Var, Type> xSsaInsideLoop;
+      late SsaNode<Var, Type> ySsaInsideLoop;
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        branchTarget((t) => for_(null, expr('bool'), null, [
+              x.write(expr('int?')).stmt,
+              if_(expr('bool'), [break_(t)]),
+              if_(x.read.is_('int'), []),
+              getSsaNodes((nodes) {
+                xSsaInsideLoop = nodes[x]!;
+                ySsaInsideLoop = nodes[y]!;
+              }),
+            ])),
+        getSsaNodes((nodes) {
+          // x's Ssa should have been changed because of the join at the end of
+          // the loop.  y's should not, since it retains the value it had prior
+          // to the loop.
+          expect(nodes[x], isNot(xSsaInsideLoop));
+          expect(nodes[y], same(ySsaInsideLoop));
+        }),
+      ]);
+    });
+
     test('forEach_bodyBegin() un-promotes', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforeLoop;
       h.run([
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
+        getSsaNodes((nodes) => ssaBeforeLoop = nodes[x]!),
         forEachWithNonVariable(expr('List<int?>'), [
           checkNotPromoted(x),
+          getSsaNodes((nodes) => expect(nodes[x], isNot(ssaBeforeLoop))),
           x.write(expr('int?')).stmt,
         ]),
       ]);
@@ -631,6 +756,20 @@
       ]);
     });
 
+    test('forEach_bodyBegin() does not write capture loop variable', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      h.run([
+        declare(x, initialized: false),
+        checkAssigned(x, false),
+        forEachWithVariableSet(x, expr('List<int?>'), [
+          checkAssigned(x, true),
+          if_(x.read.notEq(nullLiteral), [checkPromoted(x, 'int')]),
+        ]),
+        checkAssigned(x, false),
+      ]);
+    });
+
     test('forEach_bodyBegin() pushes conservative join state', () {
       var h = Harness();
       var x = Var('x', 'int');
@@ -675,13 +814,25 @@
         y.read.as_('int').stmt,
         checkPromoted(x, 'int'),
         checkPromoted(y, 'int'),
+        getSsaNodes((nodes) {
+          expect(nodes[x], isNotNull);
+          expect(nodes[y], isNotNull);
+        }),
         localFunction([
           // x is unpromoted within the local function
           checkNotPromoted(x), checkPromoted(y, 'int'),
+          getSsaNodes((nodes) {
+            expect(nodes[x], isNull);
+            expect(nodes[y], isNotNull);
+          }),
           x.write(expr('int?')).stmt, x.read.as_('int').stmt,
         ]),
         // x is unpromoted after the local function too
         checkNotPromoted(x), checkPromoted(y, 'int'),
+        getSsaNodes((nodes) {
+          expect(nodes[x], isNull);
+          expect(nodes[y], isNotNull);
+        }),
       ]);
     });
 
@@ -721,21 +872,28 @@
       var h = Harness();
       var x = Var('x', 'int?');
       var y = Var('y', 'int?');
+      late SsaNode<Var, Type> ssaBeforeFunction;
       h.run([
         declare(x, initialized: true), declare(y, initialized: true),
         x.read.as_('int').stmt, y.read.as_('int').stmt,
-        checkPromoted(x, 'int'), checkPromoted(y, 'int'),
+        checkPromoted(x, 'int'),
+        getSsaNodes((nodes) => ssaBeforeFunction = nodes[x]!),
+        checkPromoted(y, 'int'),
         localFunction([
           // x is unpromoted within the local function, because the write
           // might have happened by the time the local function executes.
-          checkNotPromoted(x), checkPromoted(y, 'int'),
+          checkNotPromoted(x),
+          getSsaNodes((nodes) => expect(nodes[x], isNot(ssaBeforeFunction))),
+          checkPromoted(y, 'int'),
           // But it can be re-promoted because the write isn't captured.
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'), checkPromoted(y, 'int'),
         ]),
         // x is still promoted after the local function, though, because the
         // write hasn't occurred yet.
-        checkPromoted(x, 'int'), checkPromoted(y, 'int'),
+        checkPromoted(x, 'int'),
+        getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforeFunction))),
+        checkPromoted(y, 'int'),
         x.write(expr('int?')).stmt,
         // x is unpromoted now.
         checkNotPromoted(x), checkPromoted(y, 'int'),
@@ -762,7 +920,9 @@
       h.run([
         declare(y, initialized: true),
         y.read.as_('int').stmt,
+        getSsaNodes((nodes) => expect(nodes[x], null)),
         localFunction([
+          getSsaNodes((nodes) => expect(nodes[x], isNot(nodes[y]))),
           x.read.as_('int').stmt,
           // Promotion should not occur, because x might be write-captured by
           // the time this code is reached.
@@ -967,19 +1127,168 @@
       ]);
     });
 
+    test(
+        'ifStatement_end() discards non-matching expression info from joined '
+        'branches', () {
+      var h = Harness();
+      var w = Var('w', 'Object');
+      var x = Var('x', 'bool');
+      var y = Var('y', 'bool');
+      var z = Var('z', 'bool');
+      late SsaNode<Var, Type> xSsaNodeBeforeIf;
+      h.run([
+        declare(w, initialized: true),
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        declare(z, initialized: true),
+        x.write(w.read.is_('int')).stmt,
+        getSsaNodes((nodes) {
+          xSsaNodeBeforeIf = nodes[x]!;
+          expect(xSsaNodeBeforeIf.expressionInfo, isNotNull);
+        }),
+        if_(expr('bool'), [
+          y.write(w.read.is_('String')).stmt,
+        ], [
+          z.write(w.read.is_('bool')).stmt,
+        ]),
+        getSsaNodes((nodes) {
+          expect(nodes[x], same(xSsaNodeBeforeIf));
+          expect(nodes[y]!.expressionInfo, isNull);
+          expect(nodes[z]!.expressionInfo, isNull);
+        }),
+      ]);
+    });
+
+    test(
+        'ifStatement_end() ignores non-matching SSA info from "then" path if '
+        'unreachable', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      late SsaNode<Var, Type> xSsaNodeBeforeIf;
+      h.run([
+        declare(x, initialized: true),
+        getSsaNodes((nodes) {
+          xSsaNodeBeforeIf = nodes[x]!;
+        }),
+        if_(expr('bool'), [
+          x.write(expr('Object')).stmt,
+          return_(),
+        ]),
+        getSsaNodes((nodes) {
+          expect(nodes[x], same(xSsaNodeBeforeIf));
+        }),
+      ]);
+    });
+
+    test(
+        'ifStatement_end() ignores non-matching SSA info from "else" path if '
+        'unreachable', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      late SsaNode<Var, Type> xSsaNodeBeforeIf;
+      h.run([
+        declare(x, initialized: true),
+        getSsaNodes((nodes) {
+          xSsaNodeBeforeIf = nodes[x]!;
+        }),
+        if_(expr('bool'), [], [
+          x.write(expr('Object')).stmt,
+          return_(),
+        ]),
+        getSsaNodes((nodes) {
+          expect(nodes[x], same(xSsaNodeBeforeIf));
+        }),
+      ]);
+    });
+
+    test('initialize() promotes when not final', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      h.run([
+        declareInitialized(x, expr('int')),
+        checkPromoted(x, 'int'),
+      ]);
+    });
+
+    test('initialize() does not promote when final', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      h.run([
+        declareInitialized(x, expr('int'), isFinal: true),
+        checkNotPromoted(x),
+      ]);
+    });
+
+    test('initialize() stores expressionInfo when not late', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      var y = Var('y', 'int?');
+      late ExpressionInfo<Var, Type> writtenValueInfo;
+      h.run([
+        declareInitialized(
+            x,
+            y.read.eq(nullLiteral).getExpressionInfo((info) {
+              expect(info, isNotNull);
+              writtenValueInfo = info!;
+            })),
+        getSsaNodes((nodes) {
+          expect(nodes[x]!.expressionInfo, same(writtenValueInfo));
+        }),
+      ]);
+    });
+
+    test('initialize() does not store expressionInfo when late', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      var y = Var('y', 'int?');
+      h.run([
+        declareInitialized(x, y.read.eq(nullLiteral), isLate: true),
+        getSsaNodes((nodes) {
+          expect(nodes[x]!.expressionInfo, isNull);
+        }),
+      ]);
+    });
+
+    test('initialize() does not store expressionInfo for trivial expressions',
+        () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      var y = Var('y', 'int?');
+      h.run([
+        declare(y, initialized: true),
+        localFunction([
+          y.write(expr('int?')).stmt,
+        ]),
+        declareInitialized(
+            x,
+            // `y == null` is a trivial expression because y has been write
+            // captured.
+            y.read
+                .eq(nullLiteral)
+                .getExpressionInfo((info) => expect(info, isNotNull))),
+        getSsaNodes((nodes) {
+          expect(nodes[x]!.expressionInfo, isNull);
+        }),
+      ]);
+    });
+
     void _checkIs(String declaredType, String tryPromoteType,
-        String expectedPromotedTypeThen, String expectedPromotedTypeElse,
+        String? expectedPromotedTypeThen, String? expectedPromotedTypeElse,
         {bool inverted = false}) {
       var h = Harness();
       var x = Var('x', declaredType);
+      late SsaNode<Var, Type> ssaBeforePromotion;
       h.run([
         declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforePromotion = nodes[x]!),
         if_(x.read.is_(tryPromoteType, isInverted: inverted), [
           checkReachable(true),
           checkPromoted(x, expectedPromotedTypeThen),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ], [
           checkReachable(true),
           checkPromoted(x, expectedPromotedTypeElse),
+          getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
         ])
       ]);
     }
@@ -1173,28 +1482,58 @@
       ]);
     });
 
-    test('nonNullAssert_end(x) promotes', () {
+    test('logicalNot_end() inverts a condition', () {
       var h = Harness();
       var x = Var('x', 'int?');
       h.run([
         declare(x, initialized: true),
+        if_(x.read.eq(nullLiteral).not, [
+          checkPromoted(x, 'int'),
+        ], [
+          checkNotPromoted(x),
+        ]),
+      ]);
+    });
+
+    test('logicalNot_end() handles null literals', () {
+      var h = Harness();
+      h.run([
+        // `!null` would be a compile error, but we need to make sure we don't
+        // crash.
+        if_(nullLiteral.not, [], []),
+      ]);
+    });
+
+    test('nonNullAssert_end(x) promotes', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforePromotion;
+      h.run([
+        declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforePromotion = nodes[x]!),
         x.read.nonNullAssert.stmt,
         checkPromoted(x, 'int'),
+        getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
       ]);
     });
 
     test('nullAwareAccess temporarily promotes', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforePromotion;
       h.run([
         declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforePromotion = nodes[x]!),
         x.read
             .nullAwareAccess(block([
               checkReachable(true),
               checkPromoted(x, 'int'),
+              getSsaNodes(
+                  (nodes) => expect(nodes[x], same(ssaBeforePromotion))),
             ]).thenExpr(expr('Null')))
             .stmt,
         checkNotPromoted(x),
+        getSsaNodes((nodes) => expect(nodes[x], same(ssaBeforePromotion))),
       ]);
     });
 
@@ -1380,14 +1719,20 @@
     test('switchStatement_beginCase(true) un-promotes', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforeSwitch;
       h.run([
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         switch_(
-            expr('Null'),
+            expr('Null').thenStmt(block([
+              checkPromoted(x, 'int'),
+              getSsaNodes((nodes) => ssaBeforeSwitch = nodes[x]!),
+            ])),
             [
               case_([
                 checkNotPromoted(x),
+                getSsaNodes(
+                    (nodes) => expect(nodes[x], isNot(ssaBeforeSwitch))),
                 x.write(expr('int?')).stmt,
                 checkNotPromoted(x),
               ], hasLabel: true),
@@ -1527,6 +1872,7 @@
         () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaAfterTry;
       h.run([
         declare(x, initialized: true),
         x.read.as_('int').stmt,
@@ -1535,9 +1881,11 @@
           x.write(expr('int?')).stmt,
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'),
+          getSsaNodes((nodes) => ssaAfterTry = nodes[x]!),
         ], [
           catch_(body: [
             checkNotPromoted(x),
+            getSsaNodes((nodes) => expect(nodes[x], isNot(ssaAfterTry))),
           ]),
         ]),
       ]);
@@ -1673,16 +2021,27 @@
         'body', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaAtStartOfTry;
+      late SsaNode<Var, Type> ssaAfterTry;
       h.run([
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
         tryFinally([
+          getSsaNodes((nodes) => ssaAtStartOfTry = nodes[x]!),
           x.write(expr('int?')).stmt,
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'),
+          getSsaNodes((nodes) => ssaAfterTry = nodes[x]!),
         ], [
           checkNotPromoted(x),
+          // The SSA node for X should be different from what it was at any time
+          // during the try block, because there is no telling at what point an
+          // exception might have occurred.
+          getSsaNodes((nodes) {
+            expect(nodes[x], isNot(ssaAtStartOfTry));
+            expect(nodes[x], isNot(ssaAfterTry));
+          }),
         ]),
       ]);
     });
@@ -1733,6 +2092,8 @@
       var h = Harness();
       var x = Var('x', 'int?');
       var y = Var('y', 'int?');
+      late SsaNode<Var, Type> xSsaAtEndOfFinally;
+      late SsaNode<Var, Type> ySsaAtEndOfFinally;
       h.run([
         declare(x, initialized: true), declare(y, initialized: true),
         tryFinally([
@@ -1744,24 +2105,531 @@
           y.write(expr('int?')).stmt,
           y.read.as_('int').stmt,
           checkPromoted(y, 'int'),
+          getSsaNodes((nodes) {
+            xSsaAtEndOfFinally = nodes[x]!;
+            ySsaAtEndOfFinally = nodes[y]!;
+          }),
         ]),
         // x should not be re-promoted, because it might have been assigned a
         // non-promoted value in the "finally" block.  But y's promotion still
         // stands, because y was promoted in the finally block.
         checkNotPromoted(x), checkPromoted(y, 'int'),
+        // Both x and y should have the same SSA nodes they had at the end of
+        // the finally block, since the finally block is guaranteed to have
+        // executed.
+        getSsaNodes((nodes) {
+          expect(nodes[x], same(xSsaAtEndOfFinally));
+          expect(nodes[y], same(ySsaAtEndOfFinally));
+        }),
+      ]);
+    });
+
+    group('allowLocalBooleanVarsToPromote', () {
+      test(
+          'tryFinallyStatement_end() restores SSA nodes from try block when it'
+          'is sound to do so', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'int?');
+        var y = Var('y', 'int?');
+        late SsaNode<Var, Type> xSsaAtEndOfTry;
+        late SsaNode<Var, Type> ySsaAtEndOfTry;
+        late SsaNode<Var, Type> xSsaAtEndOfFinally;
+        late SsaNode<Var, Type> ySsaAtEndOfFinally;
+        h.run([
+          declare(x, initialized: true), declare(y, initialized: true),
+          tryFinally([
+            x.write(expr('int?')).stmt,
+            y.write(expr('int?')).stmt,
+            getSsaNodes((nodes) {
+              xSsaAtEndOfTry = nodes[x]!;
+              ySsaAtEndOfTry = nodes[y]!;
+            }),
+          ], [
+            if_(expr('bool'), [
+              x.write(expr('int?')).stmt,
+            ]),
+            if_(expr('bool'), [
+              y.write(expr('int?')).stmt,
+              return_(),
+            ]),
+            getSsaNodes((nodes) {
+              xSsaAtEndOfFinally = nodes[x]!;
+              ySsaAtEndOfFinally = nodes[y]!;
+              expect(xSsaAtEndOfFinally, isNot(same(xSsaAtEndOfTry)));
+              expect(ySsaAtEndOfFinally, isNot(same(ySsaAtEndOfTry)));
+            }),
+          ]),
+          // x's SSA node should still match what it was at the end of the
+          // finally block, because it might have been written to.  But y
+          // can't have been written to, because once we reach here, we know
+          // that the finally block completed normally, and the write to y
+          // always leads to the explicit return.  So y's SSA node should be
+          // restored back to match that from the end of the try block.
+          getSsaNodes((nodes) {
+            expect(nodes[x], same(xSsaAtEndOfFinally));
+            expect(nodes[y], same(ySsaAtEndOfTry));
+          }),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() sets unreachable if end of try block '
+          'unreachable', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        h.run([
+          tryFinally([
+            return_(),
+            checkReachable(false),
+          ], [
+            checkReachable(true),
+          ]),
+          checkReachable(false),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() sets unreachable if end of finally block '
+          'unreachable', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        h.run([
+          tryFinally([
+            checkReachable(true),
+          ], [
+            return_(),
+            checkReachable(false),
+          ]),
+          checkReachable(false),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles a variable declared only in the '
+          'try block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'int?');
+        h.run([
+          tryFinally([
+            declare(x, initialized: true),
+          ], []),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles a variable declared only in the '
+          'finally block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'int?');
+        h.run([
+          tryFinally([], [
+            declare(x, initialized: true),
+          ]),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles a variable that was write '
+          'captured in the try block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'int?');
+        h.run([
+          declare(x, initialized: true),
+          tryFinally([
+            localFunction([
+              x.write(expr('int?')).stmt,
+            ]),
+          ], []),
+          if_(x.read.notEq(nullLiteral), [
+            checkNotPromoted(x),
+          ]),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles a variable that was write '
+          'captured in the finally block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'int?');
+        h.run([
+          declare(x, initialized: true),
+          tryFinally([], [
+            localFunction([
+              x.write(expr('int?')).stmt,
+            ]),
+          ]),
+          if_(x.read.notEq(nullLiteral), [
+            checkNotPromoted(x),
+          ]),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles a variable that was promoted in '
+          'the try block and write captured in the finally block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'int?');
+        h.run([
+          declare(x, initialized: true),
+          tryFinally([
+            if_(x.read.eq(nullLiteral), [
+              return_(),
+            ]),
+            checkPromoted(x, 'int'),
+          ], [
+            localFunction([
+              x.write(expr('int?')).stmt,
+            ]),
+          ]),
+          // The capture in the `finally` cancels old promotions and prevents
+          // future promotions.
+          checkNotPromoted(x),
+          if_(x.read.notEq(nullLiteral), [
+            checkNotPromoted(x),
+          ]),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() keeps promotions from both try and '
+          'finally blocks when there is no write in the finally block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: true),
+          tryFinally([
+            if_(x.read.is_('num', isInverted: true), [
+              return_(),
+            ]),
+            checkPromoted(x, 'num'),
+          ], [
+            if_(x.read.is_('int', isInverted: true), [
+              return_(),
+            ]),
+          ]),
+          // The promotion chain now contains both `num` and `int`.
+          checkPromoted(x, 'int'),
+          x.write(expr('num')).stmt,
+          checkPromoted(x, 'num'),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() keeps promotions from the finally block '
+          'when there is a write in the finally block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: true),
+          tryFinally([
+            if_(x.read.is_('String', isInverted: true), [
+              return_(),
+            ]),
+            checkPromoted(x, 'String'),
+          ], [
+            x.write(expr('Object')).stmt,
+            if_(x.read.is_('int', isInverted: true), [
+              return_(),
+            ]),
+          ]),
+          checkPromoted(x, 'int'),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() keeps tests from both the try and finally '
+          'blocks', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: true),
+          tryFinally([
+            if_(x.read.is_('String', isInverted: true), []),
+            checkNotPromoted(x),
+          ], [
+            if_(x.read.is_('int', isInverted: true), []),
+            checkNotPromoted(x),
+          ]),
+          checkNotPromoted(x),
+          if_(expr('bool'), [
+            x.write(expr('String')).stmt,
+            checkPromoted(x, 'String'),
+          ], [
+            x.write(expr('int')).stmt,
+            checkPromoted(x, 'int'),
+          ]),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles variables not definitely assigned '
+          'in either the try or finally block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: false),
+          checkAssigned(x, false),
+          tryFinally([
+            if_(expr('bool'), [
+              x.write(expr('Object')).stmt,
+            ]),
+            checkAssigned(x, false),
+          ], [
+            if_(expr('bool'), [
+              x.write(expr('Object')).stmt,
+            ]),
+            checkAssigned(x, false),
+          ]),
+          checkAssigned(x, false),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles variables definitely assigned in '
+          'the try block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: false),
+          checkAssigned(x, false),
+          tryFinally([
+            x.write(expr('Object')).stmt,
+            checkAssigned(x, true),
+          ], [
+            if_(expr('bool'), [
+              x.write(expr('Object')).stmt,
+            ]),
+            checkAssigned(x, false),
+          ]),
+          checkAssigned(x, true),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles variables definitely assigned in '
+          'the finally block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: false),
+          checkAssigned(x, false),
+          tryFinally([
+            if_(expr('bool'), [
+              x.write(expr('Object')).stmt,
+            ]),
+            checkAssigned(x, false),
+          ], [
+            x.write(expr('Object')).stmt,
+            checkAssigned(x, true),
+          ]),
+          checkAssigned(x, true),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles variables definitely unassigned '
+          'in both the try and finally blocks', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: false),
+          checkUnassigned(x, true),
+          tryFinally([
+            checkUnassigned(x, true),
+          ], [
+            checkUnassigned(x, true),
+          ]),
+          checkUnassigned(x, true),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles variables definitely unassigned '
+          'in the try but not the finally block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: false),
+          checkUnassigned(x, true),
+          tryFinally([
+            checkUnassigned(x, true),
+          ], [
+            if_(expr('bool'), [
+              x.write(expr('Object')).stmt,
+            ]),
+            checkUnassigned(x, false),
+          ]),
+          checkUnassigned(x, false),
+        ]);
+      });
+
+      test(
+          'tryFinallyStatement_end() handles variables definitely unassigned '
+          'in the finally but not the try block', () {
+        var h = Harness(allowLocalBooleanVarsToPromote: true);
+        var x = Var('x', 'Object');
+        h.run([
+          declare(x, initialized: false),
+          checkUnassigned(x, true),
+          tryFinally([
+            if_(expr('bool'), [
+              x.write(expr('Object')).stmt,
+            ]),
+            checkUnassigned(x, false),
+          ], [
+            checkUnassigned(x, false),
+          ]),
+          checkUnassigned(x, false),
+        ]);
+      });
+    });
+
+    test('variableRead() restores promotions from previous write()', () {
+      var h = Harness(allowLocalBooleanVarsToPromote: true);
+      var x = Var('x', 'int?');
+      var y = Var('y', 'int?');
+      var z = Var('z', 'bool');
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        declare(z, initialized: true),
+        // Create a variable that promotes x if its value is true, and y if its
+        // value is false.
+        z
+            .write(x.read.notEq(nullLiteral).conditional(
+                booleanLiteral(true),
+                y.read.notEq(nullLiteral).conditional(
+                    booleanLiteral(false), throw_(expr('Object')))))
+            .stmt,
+        checkNotPromoted(x),
+        checkNotPromoted(y),
+        // Simply reading the variable shouldn't promote anything.
+        z.read.stmt,
+        checkNotPromoted(x),
+        checkNotPromoted(y),
+        // But reading it in an "if" condition should promote.
+        if_(z.read, [
+          checkPromoted(x, 'int'),
+          checkNotPromoted(y),
+        ], [
+          checkNotPromoted(x),
+          checkPromoted(y, 'int'),
+        ]),
+      ]);
+    });
+
+    test('variableRead() restores promotions from previous initialization', () {
+      var h = Harness(allowLocalBooleanVarsToPromote: true);
+      var x = Var('x', 'int?');
+      var y = Var('y', 'int?');
+      var z = Var('z', 'bool');
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        // Create a variable that promotes x if its value is true, and y if its
+        // value is false.
+        declareInitialized(
+            z,
+            x.read.notEq(nullLiteral).conditional(
+                booleanLiteral(true),
+                y.read.notEq(nullLiteral).conditional(
+                    booleanLiteral(false), throw_(expr('Object'))))),
+        checkNotPromoted(x),
+        checkNotPromoted(y),
+        // Simply reading the variable shouldn't promote anything.
+        z.read.stmt,
+        checkNotPromoted(x),
+        checkNotPromoted(y),
+        // But reading it in an "if" condition should promote.
+        if_(z.read, [
+          checkPromoted(x, 'int'),
+          checkNotPromoted(y),
+        ], [
+          checkNotPromoted(x),
+          checkPromoted(y, 'int'),
+        ]),
+      ]);
+    });
+
+    test('variableRead() rebases old promotions', () {
+      var h = Harness(allowLocalBooleanVarsToPromote: true);
+      var w = Var('w', 'int?');
+      var x = Var('x', 'int?');
+      var y = Var('y', 'int?');
+      var z = Var('z', 'bool');
+      h.run([
+        declare(w, initialized: true),
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        declare(z, initialized: true),
+        // Create a variable that promotes x if its value is true, and y if its
+        // value is false.
+        z
+            .write(x.read.notEq(nullLiteral).conditional(
+                booleanLiteral(true),
+                y.read.notEq(nullLiteral).conditional(
+                    booleanLiteral(false), throw_(expr('Object')))))
+            .stmt,
+        checkNotPromoted(w),
+        checkNotPromoted(x),
+        checkNotPromoted(y),
+        w.read.nonNullAssert.stmt,
+        checkPromoted(w, 'int'),
+        // Reading the value of z in an "if" condition should promote x or y,
+        // and keep the promotion of w.
+        if_(z.read, [
+          checkPromoted(w, 'int'),
+          checkPromoted(x, 'int'),
+          checkNotPromoted(y),
+        ], [
+          checkPromoted(w, 'int'),
+          checkNotPromoted(x),
+          checkPromoted(y, 'int'),
+        ]),
+      ]);
+    });
+
+    test("variableRead() doesn't restore the notion of whether a value is null",
+        () {
+      // Note: we have the available infrastructure to do this if we want, but
+      // we think it will give an inconsistent feel because comparisons like
+      // `if (i == null)` *don't* promote.
+      var h = Harness(allowLocalBooleanVarsToPromote: true);
+      var x = Var('x', 'int?');
+      var y = Var('y', 'int?');
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        y.write(nullLiteral).stmt,
+        checkNotPromoted(x),
+        checkNotPromoted(y),
+        if_(x.read.eq(y.read), [
+          checkNotPromoted(x),
+          checkNotPromoted(y),
+        ], [
+          // Even though x != y and y is known to contain the value `null`, we
+          // don't promote x.
+          checkNotPromoted(x),
+          checkNotPromoted(y),
+        ]),
       ]);
     });
 
     test('whileStatement_conditionBegin() un-promotes', () {
       var h = Harness();
       var x = Var('x', 'int?');
+      late SsaNode<Var, Type> ssaBeforeLoop;
       h.run([
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
-        while_(checkNotPromoted(x).thenExpr(expr('bool')), [
-          x.write(expr('Null')).stmt,
-        ]),
+        getSsaNodes((nodes) => ssaBeforeLoop = nodes[x]!),
+        while_(
+            block([
+              checkNotPromoted(x),
+              getSsaNodes((nodes) => expect(nodes[x], isNot(ssaBeforeLoop))),
+            ]).thenExpr(expr('bool')),
+            [
+              x.write(expr('Null')).stmt,
+            ]),
       ]);
     });
 
@@ -1835,6 +2703,184 @@
       ]);
     });
 
+    test('whileStatement_end() with break updates Ssa of modified vars', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      var y = Var('x', 'int?');
+      late SsaNode<Var, Type> xSsaInsideLoop;
+      late SsaNode<Var, Type> ySsaInsideLoop;
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        branchTarget((t) => while_(expr('bool'), [
+              x.write(expr('int?')).stmt,
+              if_(expr('bool'), [break_(t)]),
+              getSsaNodes((nodes) {
+                xSsaInsideLoop = nodes[x]!;
+                ySsaInsideLoop = nodes[y]!;
+              }),
+            ])),
+        getSsaNodes((nodes) {
+          // x's Ssa should have been changed because of the join at the end of
+          // the loop.  y's should not, since it retains the value it had prior
+          // to the loop.
+          expect(nodes[x], isNot(xSsaInsideLoop));
+          expect(nodes[y], same(ySsaInsideLoop));
+        }),
+      ]);
+    });
+
+    test(
+        'whileStatement_end() with break updates Ssa of modified vars when '
+        'types were tested', () {
+      var h = Harness();
+      var x = Var('x', 'int?');
+      var y = Var('x', 'int?');
+      late SsaNode<Var, Type> xSsaInsideLoop;
+      late SsaNode<Var, Type> ySsaInsideLoop;
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        branchTarget((t) => while_(expr('bool'), [
+              x.write(expr('int?')).stmt,
+              if_(expr('bool'), [break_(t)]),
+              if_(x.read.is_('int'), []),
+              getSsaNodes((nodes) {
+                xSsaInsideLoop = nodes[x]!;
+                ySsaInsideLoop = nodes[y]!;
+              }),
+            ])),
+        getSsaNodes((nodes) {
+          // x's Ssa should have been changed because of the join at the end of
+          // the loop.  y's should not, since it retains the value it had prior
+          // to the loop.
+          expect(nodes[x], isNot(xSsaInsideLoop));
+          expect(nodes[y], same(ySsaInsideLoop));
+        }),
+      ]);
+    });
+
+    test('write() de-promotes and updates Ssa of a promoted variable', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      var y = Var('y', 'int?');
+      late SsaNode<Var, Type> ssaBeforeWrite;
+      late ExpressionInfo<Var, Type> writtenValueInfo;
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        x.read.as_('int').stmt,
+        checkPromoted(x, 'int'),
+        getSsaNodes((nodes) => ssaBeforeWrite = nodes[x]!),
+        x
+            .write(y.read.eq(nullLiteral).getExpressionInfo((info) {
+              expect(info, isNotNull);
+              writtenValueInfo = info!;
+            }))
+            .stmt,
+        checkNotPromoted(x),
+        getSsaNodes((nodes) {
+          expect(nodes[x], isNot(ssaBeforeWrite));
+          expect(nodes[x]!.expressionInfo, same(writtenValueInfo));
+        }),
+      ]);
+    });
+
+    test('write() updates Ssa', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      var y = Var('y', 'int?');
+      late SsaNode<Var, Type> ssaBeforeWrite;
+      late ExpressionInfo<Var, Type> writtenValueInfo;
+      h.run([
+        declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforeWrite = nodes[x]!),
+        x
+            .write(y.read.eq(nullLiteral).getExpressionInfo((info) {
+              expect(info, isNotNull);
+              writtenValueInfo = info!;
+            }))
+            .stmt,
+        getSsaNodes((nodes) {
+          expect(nodes[x], isNot(ssaBeforeWrite));
+          expect(nodes[x]!.expressionInfo, same(writtenValueInfo));
+        }),
+      ]);
+    });
+
+    test('write() does not copy Ssa from one variable to another', () {
+      // We could do so, and it would enable us to promote in slightly more
+      // situations, e.g.:
+      //   bool b = x != null;
+      //   if (b) { /* x promoted here */ }
+      //   var tmp = x;
+      //   x = ...;
+      //   if (b) { /* x not promoted here */ }
+      //   x = tmp;
+      //   if (b) { /* x promoted again */ }
+      // But there are a lot of corner cases to test and it's not clear how much
+      // the benefit will be, so for now we're not doing it.
+      var h = Harness(allowLocalBooleanVarsToPromote: true);
+      var x = Var('x', 'int?');
+      var y = Var('y', 'int?');
+      late SsaNode<Var, Type> xSsaBeforeWrite;
+      late SsaNode<Var, Type> ySsa;
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        getSsaNodes((nodes) {
+          xSsaBeforeWrite = nodes[x]!;
+          ySsa = nodes[y]!;
+        }),
+        x.write(y.read).stmt,
+        getSsaNodes((nodes) {
+          expect(nodes[x], isNot(xSsaBeforeWrite));
+          expect(nodes[x], isNot(ySsa));
+        }),
+      ]);
+    });
+
+    test('write() does not store expressionInfo for trivial expressions', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      var y = Var('y', 'int?');
+      late SsaNode<Var, Type> ssaBeforeWrite;
+      h.run([
+        declare(x, initialized: true),
+        declare(y, initialized: true),
+        localFunction([
+          y.write(expr('int?')).stmt,
+        ]),
+        getSsaNodes((nodes) => ssaBeforeWrite = nodes[x]!),
+        // `y == null` is a trivial expression because y has been write
+        // captured.
+        x
+            .write(y.read
+                .eq(nullLiteral)
+                .getExpressionInfo((info) => expect(info, isNotNull)))
+            .stmt,
+        getSsaNodes((nodes) {
+          expect(nodes[x], isNot(ssaBeforeWrite));
+          expect(nodes[x]!.expressionInfo, isNull);
+        }),
+      ]);
+    });
+
+    test('write() permits expression to be null', () {
+      var h = Harness();
+      var x = Var('x', 'Object');
+      late SsaNode<Var, Type> ssaBeforeWrite;
+      h.run([
+        declare(x, initialized: true),
+        getSsaNodes((nodes) => ssaBeforeWrite = nodes[x]!),
+        x.write(null).stmt,
+        getSsaNodes((nodes) {
+          expect(nodes[x], isNot(ssaBeforeWrite));
+          expect(nodes[x]!.expressionInfo, isNull);
+        }),
+      ]);
+    });
+
     test('Infinite loop does not implicitly assign variables', () {
       var h = Harness();
       var x = Var('x', 'int');
@@ -1868,8 +2914,10 @@
         localFunction([
           x.write(expr('Object')).stmt,
         ]),
+        getSsaNodes((nodes) => expect(nodes[x], isNull)),
         x.read.as_('int').stmt,
         checkNotPromoted(x),
+        getSsaNodes((nodes) => expect(nodes[x], isNull)),
       ]);
     });
 
@@ -1965,6 +3013,30 @@
           Reachability.restrict(unreachable, unreachable), same(unreachable));
     });
 
+    test('rebaseForward', () {
+      var previous = Reachability.initial;
+      var reachable = previous.split();
+      var reachable2 = previous.split();
+      var unreachable = reachable.setUnreachable();
+      var unreachablePrevious = previous.setUnreachable();
+      var reachable3 = unreachablePrevious.split();
+      expect(reachable.rebaseForward(reachable), same(reachable));
+      expect(reachable.rebaseForward(reachable2), same(reachable2));
+      expect(reachable.rebaseForward(unreachable), same(unreachable));
+      expect(unreachable.rebaseForward(reachable).parent, same(previous));
+      expect(unreachable.rebaseForward(reachable).locallyReachable, false);
+      expect(unreachable.rebaseForward(unreachable), same(unreachable));
+      expect(reachable.rebaseForward(unreachablePrevious),
+          same(unreachablePrevious));
+      expect(
+          unreachablePrevious.rebaseForward(reachable).parent, same(previous));
+      expect(
+          unreachablePrevious.rebaseForward(reachable).locallyReachable, false);
+      expect(reachable.rebaseForward(reachable3), same(reachable3));
+      expect(reachable3.rebaseForward(reachable).parent, same(previous));
+      expect(reachable3.rebaseForward(reachable).locallyReachable, false);
+    });
+
     test('join', () {
       var previous = Reachability.initial.split();
       var reachable = previous.split();
@@ -1974,6 +3046,40 @@
       expect(Reachability.join(unreachable, reachable), same(reachable));
       expect(Reachability.join(unreachable, unreachable), same(unreachable));
     });
+
+    test('commonAncestor', () {
+      var parent1 = Reachability.initial;
+      var parent2 = parent1.setUnreachable();
+      var child1 = parent1.split();
+      var child2 = parent1.split();
+      var child3 = child1.split();
+      var child4 = child2.split();
+      expect(Reachability.commonAncestor(null, null), null);
+      expect(Reachability.commonAncestor(null, parent1), null);
+      expect(Reachability.commonAncestor(parent1, null), null);
+      expect(Reachability.commonAncestor(null, child1), null);
+      expect(Reachability.commonAncestor(child1, null), null);
+      expect(Reachability.commonAncestor(null, child3), null);
+      expect(Reachability.commonAncestor(child3, null), null);
+      expect(Reachability.commonAncestor(parent1, parent1), same(parent1));
+      expect(Reachability.commonAncestor(parent1, parent2), null);
+      expect(Reachability.commonAncestor(parent2, child1), null);
+      expect(Reachability.commonAncestor(child1, parent2), null);
+      expect(Reachability.commonAncestor(parent2, child3), null);
+      expect(Reachability.commonAncestor(child3, parent2), null);
+      expect(Reachability.commonAncestor(parent1, child1), same(parent1));
+      expect(Reachability.commonAncestor(child1, parent1), same(parent1));
+      expect(Reachability.commonAncestor(parent1, child3), same(parent1));
+      expect(Reachability.commonAncestor(child3, parent1), same(parent1));
+      expect(Reachability.commonAncestor(child1, child1), same(child1));
+      expect(Reachability.commonAncestor(child1, child2), same(parent1));
+      expect(Reachability.commonAncestor(child1, child3), same(child1));
+      expect(Reachability.commonAncestor(child3, child1), same(child1));
+      expect(Reachability.commonAncestor(child1, child4), same(parent1));
+      expect(Reachability.commonAncestor(child4, child1), same(parent1));
+      expect(Reachability.commonAncestor(child3, child3), same(child3));
+      expect(Reachability.commonAncestor(child3, child4), same(parent1));
+    });
   });
 
   group('State', () {
@@ -2016,21 +3122,21 @@
     group('unsplitTo', () {
       test('no change', () {
         var s1 = FlowModel<Var, Type>(Reachability.initial.split());
-        var result = s1.unsplitTo(s1.reachable.parent);
+        var result = s1.unsplitTo(s1.reachable.parent!);
         expect(result, same(s1));
       });
 
       test('unsplit once, reachable', () {
         var s1 = FlowModel<Var, Type>(Reachability.initial.split());
         var s2 = s1.split();
-        var result = s2.unsplitTo(s1.reachable.parent);
+        var result = s2.unsplitTo(s1.reachable.parent!);
         expect(result.reachable, same(s1.reachable));
       });
 
       test('unsplit once, unreachable', () {
         var s1 = FlowModel<Var, Type>(Reachability.initial.split());
         var s2 = s1.split().setUnreachable();
-        var result = s2.unsplitTo(s1.reachable.parent);
+        var result = s2.unsplitTo(s1.reachable.parent!);
         expect(result.reachable.locallyReachable, false);
         expect(result.reachable.parent, same(s1.reachable.parent));
       });
@@ -2039,7 +3145,7 @@
         var s1 = FlowModel<Var, Type>(Reachability.initial.split());
         var s2 = s1.split();
         var s3 = s2.split();
-        var result = s3.unsplitTo(s1.reachable.parent);
+        var result = s3.unsplitTo(s1.reachable.parent!);
         expect(result.reachable, same(s1.reachable));
       });
 
@@ -2047,7 +3153,7 @@
         var s1 = FlowModel<Var, Type>(Reachability.initial.split());
         var s2 = s1.split();
         var s3 = s2.split().setUnreachable();
-        var result = s3.unsplitTo(s1.reachable.parent);
+        var result = s3.unsplitTo(s1.reachable.parent!);
         expect(result.reachable.locallyReachable, false);
         expect(result.reachable.parent, same(s1.reachable.parent));
       });
@@ -2056,7 +3162,7 @@
         var s1 = FlowModel<Var, Type>(Reachability.initial.split());
         var s2 = s1.split().setUnreachable();
         var s3 = s2.split();
-        var result = s3.unsplitTo(s1.reachable.parent);
+        var result = s3.unsplitTo(s1.reachable.parent!);
         expect(result.reachable.locallyReachable, false);
         expect(result.reachable.parent, same(s1.reachable.parent));
       });
@@ -2066,28 +3172,34 @@
       test('unpromoted -> unchanged (same)', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial);
-        var s2 = s1.tryPromoteForTypeCheck(h, intVar, Type('int')).ifTrue;
+        var s2 =
+            s1.tryPromoteForTypeCheck(h, _varRef(intVar), Type('int')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> unchanged (supertype)', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial);
-        var s2 = s1.tryPromoteForTypeCheck(h, intVar, Type('Object')).ifTrue;
+        var s2 = s1
+            .tryPromoteForTypeCheck(h, _varRef(intVar), Type('Object'))
+            .ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> unchanged (unrelated)', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial);
-        var s2 = s1.tryPromoteForTypeCheck(h, intVar, Type('String')).ifTrue;
+        var s2 = s1
+            .tryPromoteForTypeCheck(h, _varRef(intVar), Type('String'))
+            .ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> subtype', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial);
-        var s2 = s1.tryPromoteForTypeCheck(h, intQVar, Type('int')).ifTrue;
+        var s2 =
+            s1.tryPromoteForTypeCheck(h, _varRef(intQVar), Type('int')).ifTrue;
         expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           intQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int'])
@@ -2097,38 +3209,44 @@
       test('promoted -> unchanged (same)', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue;
-        var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, Type('int')).ifTrue;
+        var s2 = s1
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
+            .ifTrue;
         expect(s2, same(s1));
       });
 
       test('promoted -> unchanged (supertype)', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue;
-        var s2 =
-            s1.tryPromoteForTypeCheck(h, objectQVar, Type('Object')).ifTrue;
+        var s2 = s1
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('Object'))
+            .ifTrue;
         expect(s2, same(s1));
       });
 
       test('promoted -> unchanged (unrelated)', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue;
-        var s2 =
-            s1.tryPromoteForTypeCheck(h, objectQVar, Type('String')).ifTrue;
+        var s2 = s1
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('String'))
+            .ifTrue;
         expect(s2, same(s1));
       });
 
       test('promoted -> subtype', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int?'))
             .ifTrue;
-        var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, Type('int')).ifTrue;
+        var s2 = s1
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
+            .ifTrue;
         expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2143,8 +3261,8 @@
       test('without declaration', () {
         // This should not happen in valid code, but test that we don't crash.
         var h = Harness();
-        var s = FlowModel<Var, Type>(Reachability.initial)
-            .write(objectQVar, Type('Object?'), h);
+        var s = FlowModel<Var, Type>(Reachability.initial).write(
+            objectQVar, Type('Object?'), new SsaNode<Var, Type>(null), h);
         expect(s.variableInfo[objectQVar], isNull);
       });
 
@@ -2152,15 +3270,25 @@
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, true);
-        var s2 = s1.write(objectQVar, Type('Object?'), h);
-        expect(s2, same(s1));
+        var s2 = s1.write(
+            objectQVar, Type('Object?'), new SsaNode<Var, Type>(null), h);
+        expect(s2, isNot(same(s1)));
+        expect(s2.reachable, same(s1.reachable));
+        expect(
+            s2.infoFor(objectQVar),
+            _matchVariableModel(
+                chain: null,
+                ofInterest: isEmpty,
+                assigned: true,
+                unassigned: false));
       });
 
       test('marks as assigned', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, false);
-        var s2 = s1.write(objectQVar, Type('int?'), h);
+        var s2 =
+            s1.write(objectQVar, Type('int?'), new SsaNode<Var, Type>(null), h);
         expect(s2.reachable.overallReachable, true);
         expect(
             s2.infoFor(objectQVar),
@@ -2175,10 +3303,11 @@
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, true)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue;
         expect(s1.variableInfo, contains(objectQVar));
-        var s2 = s1.write(objectQVar, Type('int?'), h);
+        var s2 =
+            s1.write(objectQVar, Type('int?'), new SsaNode<Var, Type>(null), h);
         expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2193,9 +3322,9 @@
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, true)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num?'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2204,7 +3333,8 @@
               assigned: true,
               unassigned: false)
         });
-        var s2 = s1.write(objectQVar, Type('num'), h);
+        var s2 =
+            s1.write(objectQVar, Type('num'), new SsaNode<Var, Type>(null), h);
         expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2219,11 +3349,11 @@
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, true)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num?'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2232,7 +3362,8 @@
               assigned: true,
               unassigned: false)
         });
-        var s2 = s1.write(objectQVar, Type('num'), h);
+        var s2 =
+            s1.write(objectQVar, Type('num'), new SsaNode<Var, Type>(null), h);
         expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2247,9 +3378,9 @@
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, true)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num?'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num'))
             .ifTrue;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2258,18 +3389,26 @@
               assigned: true,
               unassigned: false)
         });
-        var s2 = s1.write(objectQVar, Type('num'), h);
+        var s2 =
+            s1.write(objectQVar, Type('num'), new SsaNode<Var, Type>(null), h);
         expect(s2.reachable.overallReachable, true);
-        expect(s2.variableInfo, same(s1.variableInfo));
+        expect(s2.variableInfo, isNot(same(s1.variableInfo)));
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?', 'num'],
+              ofInterest: ['num?', 'num'],
+              assigned: true,
+              unassigned: false)
+        });
       });
 
       test('leaves promoted, when writing a subtype', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, true)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num?'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num'))
             .ifTrue;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2278,9 +3417,17 @@
               assigned: true,
               unassigned: false)
         });
-        var s2 = s1.write(objectQVar, Type('int'), h);
+        var s2 =
+            s1.write(objectQVar, Type('int'), new SsaNode<Var, Type>(null), h);
         expect(s2.reachable.overallReachable, true);
-        expect(s2.variableInfo, same(s1.variableInfo));
+        expect(s2.variableInfo, isNot(same(s1.variableInfo)));
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?', 'num'],
+              ofInterest: ['num?', 'num'],
+              assigned: true,
+              unassigned: false)
+        });
       });
 
       group('Promotes to NonNull of a type of interest', () {
@@ -2293,7 +3440,7 @@
             x: _matchVariableModel(chain: null),
           });
 
-          var s2 = s1.write(x, Type('int'), h);
+          var s2 = s1.write(x, Type('int'), new SsaNode<Var, Type>(null), h);
           expect(s2.variableInfo, {
             x: _matchVariableModel(chain: ['int']),
           });
@@ -2314,7 +3461,7 @@
           });
 
           // 'x' is write-captured, so not promoted
-          var s3 = s2.write(x, Type('int'), h);
+          var s3 = s2.write(x, Type('int'), new SsaNode<Var, Type>(null), h);
           expect(s3.variableInfo, {
             x: _matchVariableModel(chain: null, writeCaptured: true),
           });
@@ -2324,7 +3471,7 @@
           var h = Harness();
           var s1 = FlowModel<Var, Type>(Reachability.initial)
               .declare(objectQVar, true)
-              .tryPromoteForTypeCheck(h, objectQVar, Type('int?'))
+              .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int?'))
               .ifTrue;
           expect(s1.variableInfo, {
             objectQVar: _matchVariableModel(
@@ -2332,7 +3479,8 @@
               ofInterest: ['int?'],
             ),
           });
-          var s2 = s1.write(objectQVar, Type('int'), h);
+          var s2 = s1.write(
+              objectQVar, Type('int'), new SsaNode<Var, Type>(null), h);
           expect(s2.variableInfo, {
             objectQVar: _matchVariableModel(
               chain: ['int?', 'int'],
@@ -2345,7 +3493,7 @@
           var h = Harness();
           var s1 = FlowModel<Var, Type>(Reachability.initial)
               .declare(objectQVar, true)
-              .tryPromoteForTypeCheck(h, objectQVar, Type('int?'))
+              .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int?'))
               .ifFalse;
           expect(s1.variableInfo, {
             objectQVar: _matchVariableModel(
@@ -2353,7 +3501,8 @@
               ofInterest: ['int?'],
             ),
           });
-          var s2 = s1.write(objectQVar, Type('int'), h);
+          var s2 = s1.write(
+              objectQVar, Type('int'), new SsaNode<Var, Type>(null), h);
           expect(s2.variableInfo, {
             objectQVar: _matchVariableModel(
               chain: ['Object', 'int'],
@@ -2367,7 +3516,7 @@
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, true)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num?'))
             .ifFalse;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2375,7 +3524,8 @@
             ofInterest: ['num?'],
           ),
         });
-        var s2 = s1.write(objectQVar, Type('num?'), h);
+        var s2 =
+            s1.write(objectQVar, Type('num?'), new SsaNode<Var, Type>(null), h);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
             chain: ['num?'],
@@ -2388,9 +3538,9 @@
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(objectQVar, true)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('num?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num?'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int?'))
             .ifFalse;
         expect(s1.variableInfo, {
           objectQVar: _matchVariableModel(
@@ -2398,7 +3548,8 @@
             ofInterest: ['num?', 'int?'],
           ),
         });
-        var s2 = s1.write(objectQVar, Type('int?'), h);
+        var s2 =
+            s1.write(objectQVar, Type('int?'), new SsaNode<Var, Type>(null), h);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
             chain: ['num?', 'int?'],
@@ -2409,7 +3560,7 @@
 
       group('Multiple candidate types of interest', () {
         group('; choose most specific', () {
-          Harness h;
+          late Harness h;
 
           setUp(() {
             h = Harness();
@@ -2417,38 +3568,38 @@
             // class A {}
             // class B extends A {}
             // class C extends B {}
-            h.addSubtype(Type('Object'), Type('A'), false);
-            h.addSubtype(Type('Object'), Type('A?'), false);
-            h.addSubtype(Type('Object'), Type('B?'), false);
-            h.addSubtype(Type('A'), Type('Object'), true);
-            h.addSubtype(Type('A'), Type('Object?'), true);
-            h.addSubtype(Type('A'), Type('A?'), true);
-            h.addSubtype(Type('A'), Type('B'), false);
-            h.addSubtype(Type('A'), Type('B?'), false);
-            h.addSubtype(Type('A?'), Type('Object'), false);
-            h.addSubtype(Type('A?'), Type('Object?'), true);
-            h.addSubtype(Type('A?'), Type('A'), false);
-            h.addSubtype(Type('A?'), Type('B?'), false);
-            h.addSubtype(Type('B'), Type('Object'), true);
-            h.addSubtype(Type('B'), Type('A'), true);
-            h.addSubtype(Type('B'), Type('A?'), true);
-            h.addSubtype(Type('B'), Type('B?'), true);
-            h.addSubtype(Type('B?'), Type('Object'), false);
-            h.addSubtype(Type('B?'), Type('Object?'), true);
-            h.addSubtype(Type('B?'), Type('A'), false);
-            h.addSubtype(Type('B?'), Type('A?'), true);
-            h.addSubtype(Type('B?'), Type('B'), false);
-            h.addSubtype(Type('C'), Type('Object'), true);
-            h.addSubtype(Type('C'), Type('A'), true);
-            h.addSubtype(Type('C'), Type('A?'), true);
-            h.addSubtype(Type('C'), Type('B'), true);
-            h.addSubtype(Type('C'), Type('B?'), true);
+            h.addSubtype('Object', 'A', false);
+            h.addSubtype('Object', 'A?', false);
+            h.addSubtype('Object', 'B?', false);
+            h.addSubtype('A', 'Object', true);
+            h.addSubtype('A', 'Object?', true);
+            h.addSubtype('A', 'A?', true);
+            h.addSubtype('A', 'B', false);
+            h.addSubtype('A', 'B?', false);
+            h.addSubtype('A?', 'Object', false);
+            h.addSubtype('A?', 'Object?', true);
+            h.addSubtype('A?', 'A', false);
+            h.addSubtype('A?', 'B?', false);
+            h.addSubtype('B', 'Object', true);
+            h.addSubtype('B', 'A', true);
+            h.addSubtype('B', 'A?', true);
+            h.addSubtype('B', 'B?', true);
+            h.addSubtype('B?', 'Object', false);
+            h.addSubtype('B?', 'Object?', true);
+            h.addSubtype('B?', 'A', false);
+            h.addSubtype('B?', 'A?', true);
+            h.addSubtype('B?', 'B', false);
+            h.addSubtype('C', 'Object', true);
+            h.addSubtype('C', 'A', true);
+            h.addSubtype('C', 'A?', true);
+            h.addSubtype('C', 'B', true);
+            h.addSubtype('C', 'B?', true);
 
-            h.addFactor(Type('Object'), Type('A?'), Type('Object'));
-            h.addFactor(Type('Object'), Type('B?'), Type('Object'));
-            h.addFactor(Type('Object?'), Type('A'), Type('Object?'));
-            h.addFactor(Type('Object?'), Type('A?'), Type('Object'));
-            h.addFactor(Type('Object?'), Type('B?'), Type('Object'));
+            h.addFactor('Object', 'A?', 'Object');
+            h.addFactor('Object', 'B?', 'Object');
+            h.addFactor('Object?', 'A', 'Object?');
+            h.addFactor('Object?', 'A?', 'Object');
+            h.addFactor('Object?', 'B?', 'Object');
           });
 
           test('; first', () {
@@ -2456,9 +3607,9 @@
 
             var s1 = FlowModel<Var, Type>(Reachability.initial)
                 .declare(x, true)
-                .tryPromoteForTypeCheck(h, x, Type('B?'))
+                .tryPromoteForTypeCheck(h, _varRef(x), Type('B?'))
                 .ifFalse
-                .tryPromoteForTypeCheck(h, x, Type('A?'))
+                .tryPromoteForTypeCheck(h, _varRef(x), Type('A?'))
                 .ifFalse;
             expect(s1.variableInfo, {
               x: _matchVariableModel(
@@ -2467,7 +3618,7 @@
               ),
             });
 
-            var s2 = s1.write(x, Type('C'), h);
+            var s2 = s1.write(x, Type('C'), new SsaNode<Var, Type>(null), h);
             expect(s2.variableInfo, {
               x: _matchVariableModel(
                 chain: ['Object', 'B'],
@@ -2481,9 +3632,9 @@
 
             var s1 = FlowModel<Var, Type>(Reachability.initial)
                 .declare(x, true)
-                .tryPromoteForTypeCheck(h, x, Type('A?'))
+                .tryPromoteForTypeCheck(h, _varRef(x), Type('A?'))
                 .ifFalse
-                .tryPromoteForTypeCheck(h, x, Type('B?'))
+                .tryPromoteForTypeCheck(h, _varRef(x), Type('B?'))
                 .ifFalse;
             expect(s1.variableInfo, {
               x: _matchVariableModel(
@@ -2492,7 +3643,7 @@
               ),
             });
 
-            var s2 = s1.write(x, Type('C'), h);
+            var s2 = s1.write(x, Type('C'), new SsaNode<Var, Type>(null), h);
             expect(s2.variableInfo, {
               x: _matchVariableModel(
                 chain: ['Object', 'B'],
@@ -2506,9 +3657,9 @@
 
             var s1 = FlowModel<Var, Type>(Reachability.initial)
                 .declare(x, true)
-                .tryPromoteForTypeCheck(h, x, Type('A'))
+                .tryPromoteForTypeCheck(h, _varRef(x), Type('A'))
                 .ifFalse
-                .tryPromoteForTypeCheck(h, x, Type('A?'))
+                .tryPromoteForTypeCheck(h, _varRef(x), Type('A?'))
                 .ifFalse;
             expect(s1.variableInfo, {
               x: _matchVariableModel(
@@ -2517,7 +3668,7 @@
               ),
             });
 
-            var s2 = s1.write(x, Type('B'), h);
+            var s2 = s1.write(x, Type('B'), new SsaNode<Var, Type>(null), h);
             expect(s2.variableInfo, {
               x: _matchVariableModel(
                 chain: ['Object', 'A'],
@@ -2532,9 +3683,9 @@
             var h = Harness();
             var s1 = FlowModel<Var, Type>(Reachability.initial)
                 .declare(objectQVar, true)
-                .tryPromoteForTypeCheck(h, objectQVar, Type('num?'))
+                .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num?'))
                 .ifFalse
-                .tryPromoteForTypeCheck(h, objectQVar, Type('num*'))
+                .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num*'))
                 .ifFalse;
             expect(s1.variableInfo, {
               objectQVar: _matchVariableModel(
@@ -2542,10 +3693,17 @@
                 ofInterest: ['num?', 'num*'],
               ),
             });
-            var s2 = s1.write(objectQVar, Type('int'), h);
+            var s2 = s1.write(
+                objectQVar, Type('int'), new SsaNode<Var, Type>(null), h);
             // It's ambiguous whether to promote to num? or num*, so we don't
             // promote.
-            expect(s2, same(s1));
+            expect(s2, isNot(same(s1)));
+            expect(s2.variableInfo, {
+              objectQVar: _matchVariableModel(
+                chain: ['Object'],
+                ofInterest: ['num?', 'num*'],
+              ),
+            });
           });
         });
 
@@ -2553,9 +3711,9 @@
           var h = Harness();
           var s1 = FlowModel<Var, Type>(Reachability.initial)
               .declare(objectQVar, true)
-              .tryPromoteForTypeCheck(h, objectQVar, Type('num?'))
+              .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num?'))
               .ifFalse
-              .tryPromoteForTypeCheck(h, objectQVar, Type('num*'))
+              .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('num*'))
               .ifFalse;
           expect(s1.variableInfo, {
             objectQVar: _matchVariableModel(
@@ -2563,7 +3721,8 @@
               ofInterest: ['num?', 'num*'],
             ),
           });
-          var s2 = s1.write(objectQVar, Type('num?'), h);
+          var s2 = s1.write(
+              objectQVar, Type('num?'), new SsaNode<Var, Type>(null), h);
           // It's ambiguous whether to promote to num? or num*, but since the
           // written type is exactly num?, we use that.
           expect(s2.variableInfo, {
@@ -2584,9 +3743,9 @@
 
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(x, true)
-            .tryPromoteForTypeCheck(h, x, Type('num?'))
+            .tryPromoteForTypeCheck(h, _varRef(x), Type('num?'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, x, Type('int?'))
+            .tryPromoteForTypeCheck(h, _varRef(x), Type('int?'))
             .ifTrue;
         expect(s1.variableInfo, {
           x: _matchVariableModel(
@@ -2595,7 +3754,7 @@
           ),
         });
 
-        var s2 = s1.write(x, Type('double'), h);
+        var s2 = s1.write(x, Type('double'), new SsaNode<Var, Type>(null), h);
         expect(s2.variableInfo, {
           x: _matchVariableModel(
             chain: ['num?', 'num'],
@@ -2629,14 +3788,14 @@
       test('unpromoted -> unchanged', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial);
-        var s2 = s1.tryMarkNonNullable(h, intVar).ifTrue;
+        var s2 = s1.tryMarkNonNullable(h, _varRef(intVar)).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> promoted', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial);
-        var s2 = s1.tryMarkNonNullable(h, intQVar).ifTrue;
+        var s2 = s1.tryMarkNonNullable(h, _varRef(intQVar)).ifTrue;
         expect(s2.reachable.overallReachable, true);
         expect(s2.infoFor(intQVar),
             _matchVariableModel(chain: ['int'], ofInterest: []));
@@ -2645,18 +3804,18 @@
       test('promoted -> unchanged', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue;
-        var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
+        var s2 = s1.tryMarkNonNullable(h, _varRef(objectQVar)).ifTrue;
         expect(s2, same(s1));
       });
 
       test('promoted -> re-promoted', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int?'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int?'))
             .ifTrue;
-        var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
+        var s2 = s1.tryMarkNonNullable(h, _varRef(objectQVar)).ifTrue;
         expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar:
@@ -2667,7 +3826,7 @@
       test('promote to Never', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial);
-        var s2 = s1.tryMarkNonNullable(h, nullVar).ifTrue;
+        var s2 = s1.tryMarkNonNullable(h, _varRef(nullVar)).ifTrue;
         expect(s2.reachable.overallReachable, false);
         expect(s2.infoFor(nullVar),
             _matchVariableModel(chain: ['Never'], ofInterest: []));
@@ -2679,18 +3838,23 @@
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
             .declare(intQVar, true)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue;
         var s2 = s1.conservativeJoin([intQVar], []);
-        expect(s2, same(s1));
+        expect(s2, isNot(same(s1)));
+        expect(s2.reachable, same(s1.reachable));
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
+          intQVar: _matchVariableModel(chain: null, ofInterest: [])
+        });
       });
 
       test('written', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, intQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(intQVar), Type('int'))
             .ifTrue;
         var s2 = s1.conservativeJoin([intQVar], []);
         expect(s2.reachable.overallReachable, true);
@@ -2703,9 +3867,9 @@
       test('write captured', () {
         var h = Harness();
         var s1 = FlowModel<Var, Type>(Reachability.initial)
-            .tryPromoteForTypeCheck(h, objectQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(objectQVar), Type('int'))
             .ifTrue
-            .tryPromoteForTypeCheck(h, intQVar, Type('int'))
+            .tryPromoteForTypeCheck(h, _varRef(intQVar), Type('int'))
             .ifTrue;
         var s2 = s1.conservativeJoin([], [intQVar]);
         expect(s2.reachable.overallReachable, true);
@@ -2717,15 +3881,19 @@
       });
     });
 
-    group('restrict', () {
+    group('rebaseForward', () {
       test('reachability', () {
         var h = Harness();
         var reachable = FlowModel<Var, Type>(Reachability.initial);
         var unreachable = reachable.setUnreachable();
-        expect(reachable.restrict(h, reachable, Set()), same(reachable));
-        expect(reachable.restrict(h, unreachable, Set()), same(unreachable));
-        expect(unreachable.restrict(h, reachable, Set()), same(unreachable));
-        expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
+        expect(reachable.rebaseForward(h, reachable), same(reachable));
+        expect(reachable.rebaseForward(h, unreachable), same(unreachable));
+        expect(
+            unreachable.rebaseForward(h, reachable).reachable.overallReachable,
+            false);
+        expect(unreachable.rebaseForward(h, reachable).variableInfo,
+            same(unreachable.variableInfo));
+        expect(unreachable.rebaseForward(h, unreachable), same(unreachable));
       });
 
       test('assignments', () {
@@ -2739,9 +3907,13 @@
             .declare(b, false)
             .declare(c, false)
             .declare(d, false);
-        var s1 = s0.write(a, Type('int'), h).write(b, Type('int'), h);
-        var s2 = s1.write(a, Type('int'), h).write(c, Type('int'), h);
-        var result = s2.restrict(h, s1, Set());
+        var s1 = s0
+            .write(a, Type('int'), new SsaNode<Var, Type>(null), h)
+            .write(b, Type('int'), new SsaNode<Var, Type>(null), h);
+        var s2 = s0
+            .write(a, Type('int'), new SsaNode<Var, Type>(null), h)
+            .write(c, Type('int'), new SsaNode<Var, Type>(null), h);
+        var result = s1.rebaseForward(h, s2);
         expect(result.infoFor(a).assigned, true);
         expect(result.infoFor(b).assigned, true);
         expect(result.infoFor(c).assigned, true);
@@ -2762,7 +3934,7 @@
         // In s1, a and b are write captured.  In s2, a and c are.
         var s1 = s0.conservativeJoin([a, b], [a, b]);
         var s2 = s1.conservativeJoin([a, c], [a, c]);
-        var result = s2.restrict(h, s1, Set());
+        var result = s1.rebaseForward(h, s2);
         expect(
           result.infoFor(a),
           _matchVariableModel(writeCaptured: true, unassigned: false),
@@ -2781,24 +3953,48 @@
         );
       });
 
+      test('write captured and promoted', () {
+        var h = Harness();
+        var a = Var('a', 'num');
+        var s0 = FlowModel<Var, Type>(Reachability.initial).declare(a, false);
+        // In s1, a is write captured.  In s2 it's promoted.
+        var s1 = s0.conservativeJoin([a], [a]);
+        var s2 = s0.tryPromoteForTypeCheck(h, _varRef(a), Type('int')).ifTrue;
+        expect(
+          s1.rebaseForward(h, s2).infoFor(a),
+          _matchVariableModel(writeCaptured: true, chain: isNull),
+        );
+        expect(
+          s2.rebaseForward(h, s1).infoFor(a),
+          _matchVariableModel(writeCaptured: true, chain: isNull),
+        );
+      });
+
       test('promotion', () {
-        void _check(String thisType, String otherType, bool unsafe,
-            List<String> expectedChain) {
+        void _check(String? thisType, String? otherType, bool unsafe,
+            List<String>? expectedChain) {
           var h = Harness();
           var x = Var('x', 'Object?');
           var s0 = FlowModel<Var, Type>(Reachability.initial).declare(x, true);
-          var s1 = thisType == null
-              ? s0
-              : s0.tryPromoteForTypeCheck(h, x, Type(thisType)).ifTrue;
+          var s1 = s0;
+          if (unsafe) {
+            s1 = s1.write(x, Type('Object?'), new SsaNode<Var, Type>(null), h);
+          }
+          if (thisType != null) {
+            s1 =
+                s1.tryPromoteForTypeCheck(h, _varRef(x), Type(thisType)).ifTrue;
+          }
           var s2 = otherType == null
               ? s0
-              : s0.tryPromoteForTypeCheck(h, x, Type(otherType)).ifTrue;
-          var result = s1.restrict(h, s2, unsafe ? [x].toSet() : Set());
+              : s0
+                  .tryPromoteForTypeCheck(h, _varRef(x), Type(otherType))
+                  .ifTrue;
+          var result = s2.rebaseForward(h, s1);
           if (expectedChain == null) {
             expect(result.variableInfo, contains(x));
             expect(result.infoFor(x).promotedTypes, isNull);
           } else {
-            expect(result.infoFor(x).promotedTypes.map((t) => t.type).toList(),
+            expect(result.infoFor(x).promotedTypes!.map((t) => t.type).toList(),
                 expectedChain);
           }
         }
@@ -2809,9 +4005,9 @@
         _check('int', null, true, ['int']);
         _check(null, 'int', false, ['int']);
         _check(null, 'int', true, null);
-        _check('int?', 'int', false, ['int']);
-        _check('int', 'int?', false, ['int?', 'int']);
-        _check('int', 'String', false, ['String']);
+        _check('int?', 'int', false, ['int?', 'int']);
+        _check('int', 'int?', false, ['int']);
+        _check('int', 'String', false, ['int']);
         _check('int?', 'int', true, ['int?']);
         _check('int', 'int?', true, ['int']);
         _check('int', 'String', true, ['int']);
@@ -2820,7 +4016,7 @@
       test('promotion chains', () {
         // Verify that the given promotion chain matches the expected list of
         // strings.
-        void _checkChain(List<Type> chain, List<String> expected) {
+        void _checkChain(List<Type>? chain, List<String> expected) {
           var strings = (chain ?? <Type>[]).map((t) => t.type).toList();
           expect(strings, expected);
         }
@@ -2841,25 +4037,28 @@
           var initialModel =
               FlowModel<Var, Type>(Reachability.initial).declare(x, true);
           for (var t in before) {
-            initialModel =
-                initialModel.tryPromoteForTypeCheck(h, x, Type(t)).ifTrue;
+            initialModel = initialModel
+                .tryPromoteForTypeCheck(h, _varRef(x), Type(t))
+                .ifTrue;
           }
           _checkChain(initialModel.infoFor(x).promotedTypes, before);
           var tryModel = initialModel;
           for (var t in inTry) {
-            tryModel = tryModel.tryPromoteForTypeCheck(h, x, Type(t)).ifTrue;
+            tryModel =
+                tryModel.tryPromoteForTypeCheck(h, _varRef(x), Type(t)).ifTrue;
           }
           var expectedTryChain = before.toList()..addAll(inTry);
           _checkChain(tryModel.infoFor(x).promotedTypes, expectedTryChain);
           var finallyModel = initialModel;
           for (var t in inFinally) {
-            finallyModel =
-                finallyModel.tryPromoteForTypeCheck(h, x, Type(t)).ifTrue;
+            finallyModel = finallyModel
+                .tryPromoteForTypeCheck(h, _varRef(x), Type(t))
+                .ifTrue;
           }
           var expectedFinallyChain = before.toList()..addAll(inFinally);
           _checkChain(
               finallyModel.infoFor(x).promotedTypes, expectedFinallyChain);
-          var result = finallyModel.restrict(h, tryModel, {});
+          var result = tryModel.rebaseForward(h, finallyModel);
           _checkChain(result.infoFor(x).promotedTypes, expectedResult);
           // And verify that the inputs are unchanged.
           _checkChain(initialModel.infoFor(x).promotedTypes, before);
@@ -2868,25 +4067,42 @@
               finallyModel.infoFor(x).promotedTypes, expectedFinallyChain);
         }
 
-        _check(['Object'], ['Iterable', 'List'], ['num', 'int'],
+        _check(['Object'], ['num', 'int'], ['Iterable', 'List'],
             ['Object', 'Iterable', 'List']);
-        _check([], ['Iterable', 'List'], ['num', 'int'], ['Iterable', 'List']);
-        _check(['Object'], ['Iterable', 'List'], [],
+        _check([], ['num', 'int'], ['Iterable', 'List'], ['Iterable', 'List']);
+        _check(['Object'], [], ['Iterable', 'List'],
             ['Object', 'Iterable', 'List']);
-        _check([], ['Iterable', 'List'], [], ['Iterable', 'List']);
-        _check(['Object'], [], ['num', 'int'], ['Object', 'num', 'int']);
-        _check([], [], ['num', 'int'], ['num', 'int']);
+        _check([], [], ['Iterable', 'List'], ['Iterable', 'List']);
+        _check(['Object'], ['num', 'int'], [], ['Object', 'num', 'int']);
+        _check([], ['num', 'int'], [], ['num', 'int']);
         _check(['Object'], [], [], ['Object']);
         _check([], [], [], []);
         _check(
-            [], ['Object', 'Iterable'], ['num', 'int'], ['Object', 'Iterable']);
-        _check([], ['Object'], ['num', 'int'], ['Object', 'num', 'int']);
-        _check([], ['num', 'int'], ['Object', 'Iterable'], ['num', 'int']);
-        _check([], ['num', 'int'], ['Object'], ['num', 'int']);
-        _check([], ['Object', 'int'], ['num'], ['Object', 'int']);
-        _check([], ['Object', 'num'], ['int'], ['Object', 'num', 'int']);
-        _check([], ['num'], ['Object', 'int'], ['num', 'int']);
-        _check([], ['int'], ['Object', 'num'], ['int']);
+            [], ['num', 'int'], ['Object', 'Iterable'], ['Object', 'Iterable']);
+        _check([], ['num', 'int'], ['Object'], ['Object', 'num', 'int']);
+        _check([], ['Object', 'Iterable'], ['num', 'int'], ['num', 'int']);
+        _check([], ['Object'], ['num', 'int'], ['num', 'int']);
+        _check([], ['num'], ['Object', 'int'], ['Object', 'int']);
+        _check([], ['int'], ['Object', 'num'], ['Object', 'num', 'int']);
+        _check([], ['Object', 'int'], ['num'], ['num', 'int']);
+        _check([], ['Object', 'num'], ['int'], ['int']);
+      });
+
+      test('types of interest', () {
+        var h = Harness();
+        var a = Var('a', 'Object');
+        var s0 = FlowModel<Var, Type>(Reachability.initial).declare(a, false);
+        var s1 = s0.tryPromoteForTypeCheck(h, _varRef(a), Type('int')).ifFalse;
+        var s2 =
+            s0.tryPromoteForTypeCheck(h, _varRef(a), Type('String')).ifFalse;
+        expect(
+          s1.rebaseForward(h, s2).infoFor(a),
+          _matchVariableModel(ofInterest: ['int', 'String']),
+        );
+        expect(
+          s2.rebaseForward(h, s1).infoFor(a),
+          _matchVariableModel(ofInterest: ['int', 'String']),
+        );
       });
 
       test('variable present in one state but not the other', () {
@@ -2894,10 +4110,8 @@
         var x = Var('x', 'Object?');
         var s0 = FlowModel<Var, Type>(Reachability.initial);
         var s1 = s0.declare(x, true);
-        expect(s0.restrict(h, s1, {}), same(s0));
-        expect(s0.restrict(h, s1, {x}), same(s0));
-        expect(s1.restrict(h, s0, {}), same(s0));
-        expect(s1.restrict(h, s0, {x}), same(s0));
+        expect(s1.rebaseForward(h, s0), same(s0));
+        expect(s0.rebaseForward(h, s1), same(s1));
       });
     });
   });
@@ -2953,22 +4167,22 @@
       var D = Type('D');
       var E = Type('E');
       var F = Type('F');
-      h.addSubtype(A, B, false);
-      h.addSubtype(B, A, true);
-      h.addSubtype(B, C, false);
-      h.addSubtype(B, D, false);
-      h.addSubtype(C, B, true);
-      h.addSubtype(C, D, false);
-      h.addSubtype(C, E, false);
-      h.addSubtype(D, B, true);
-      h.addSubtype(D, C, true);
-      h.addSubtype(D, E, false);
-      h.addSubtype(D, F, false);
-      h.addSubtype(E, C, true);
-      h.addSubtype(E, D, true);
-      h.addSubtype(E, F, false);
-      h.addSubtype(F, D, true);
-      h.addSubtype(F, E, true);
+      h.addSubtype('A', 'B', false);
+      h.addSubtype('B', 'A', true);
+      h.addSubtype('B', 'C', false);
+      h.addSubtype('B', 'D', false);
+      h.addSubtype('C', 'B', true);
+      h.addSubtype('C', 'D', false);
+      h.addSubtype('C', 'E', false);
+      h.addSubtype('D', 'B', true);
+      h.addSubtype('D', 'C', true);
+      h.addSubtype('D', 'E', false);
+      h.addSubtype('D', 'F', false);
+      h.addSubtype('E', 'C', true);
+      h.addSubtype('E', 'D', true);
+      h.addSubtype('E', 'F', false);
+      h.addSubtype('F', 'D', true);
+      h.addSubtype('F', 'E', true);
 
       void check(List<Type> chain1, List<Type> chain2, Matcher matcher) {
         expect(
@@ -3072,15 +4286,14 @@
     var stringType = Type('String');
     const emptyMap = const <Var, VariableModel<Var, Type>>{};
 
-    VariableModel<Var, Type> model(List<Type> promotionChain,
-            {List<Type> typesOfInterest, bool assigned = false}) =>
+    VariableModel<Var, Type> model(List<Type>? promotionChain,
+            {List<Type>? typesOfInterest, bool assigned = false}) =>
         VariableModel<Var, Type>(
-          promotionChain,
-          typesOfInterest ?? promotionChain ?? [],
-          assigned,
-          !assigned,
-          false,
-        );
+            promotedTypes: promotionChain,
+            tested: typesOfInterest ?? promotionChain ?? [],
+            assigned: assigned,
+            unassigned: !assigned,
+            ssaNode: new SsaNode<Var, Type>(null));
 
     group('without input reuse', () {
       test('promoted with unpromoted', () {
@@ -3257,19 +4470,18 @@
     var stringType = Type('String');
     const emptyMap = const <Var, VariableModel<Var, Type>>{};
 
-    VariableModel<Var, Type> varModel(List<Type> promotionChain,
+    VariableModel<Var, Type> varModel(List<Type>? promotionChain,
             {bool assigned = false}) =>
         VariableModel<Var, Type>(
-          promotionChain,
-          promotionChain ?? [],
-          assigned,
-          !assigned,
-          false,
-        );
+            promotedTypes: promotionChain,
+            tested: promotionChain ?? [],
+            assigned: assigned,
+            unassigned: !assigned,
+            ssaNode: new SsaNode<Var, Type>(null));
 
     test('first is null', () {
       var h = Harness();
-      var s1 = FlowModel.withInfo(Reachability.initial.split(), {});
+      var s1 = FlowModel.withInfo(Reachability.initial.split(), emptyMap);
       var result = FlowModel.merge(h, null, s1, emptyMap);
       expect(result.reachable, same(Reachability.initial));
     });
@@ -3278,7 +4490,7 @@
       var h = Harness();
       var splitPoint = Reachability.initial.split();
       var afterSplit = splitPoint.split();
-      var s1 = FlowModel.withInfo(afterSplit, {});
+      var s1 = FlowModel.withInfo(afterSplit, emptyMap);
       var result = FlowModel.merge(h, s1, null, emptyMap);
       expect(result.reachable, same(splitPoint));
     });
@@ -3295,7 +4507,7 @@
       });
       var result = FlowModel.merge(h, s1, s2, emptyMap);
       expect(result.reachable, same(splitPoint));
-      expect(result.variableInfo[x].promotedTypes, isNull);
+      expect(result.variableInfo[x]!.promotedTypes, isNull);
     });
 
     test('first is unreachable', () {
@@ -3341,7 +4553,7 @@
       var result = FlowModel.merge(h, s1, s2, emptyMap);
       expect(result.reachable.locallyReachable, false);
       expect(result.reachable.parent, same(splitPoint.parent));
-      expect(result.variableInfo[x].promotedTypes, isNull);
+      expect(result.variableInfo[x]!.promotedTypes, isNull);
     });
   });
 
@@ -3352,7 +4564,12 @@
     const emptyMap = const <Var, VariableModel<Var, Type>>{};
 
     VariableModel<Var, Type> model(List<Type> typesOfInterest) =>
-        VariableModel<Var, Type>(null, typesOfInterest, true, false, false);
+        VariableModel<Var, Type>(
+            promotedTypes: null,
+            tested: typesOfInterest,
+            assigned: true,
+            unassigned: false,
+            ssaNode: new SsaNode<Var, Type>(null));
 
     test('inherits types of interest from other', () {
       var h = Harness();
@@ -3362,7 +4579,7 @@
       var m2 = FlowModel.withInfo(Reachability.initial, {
         x: model([stringType])
       });
-      expect(m1.inheritTested(h, m2).variableInfo[x].tested,
+      expect(m1.inheritTested(h, m2).variableInfo[x]!.tested,
           _matchOfInterestSet(['int', 'String']));
     });
 
@@ -3386,6 +4603,766 @@
       expect(m1.inheritTested(h, m2), same(m1));
     });
   });
+
+  group('Legacy promotion', () {
+    group('if statement', () {
+      group('promotes a variable whose type is shown by its condition', () {
+        test('within then-block', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkPromoted(x, 'int'),
+            ]),
+          ]);
+        });
+
+        test('but not within else-block', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [], [
+              checkNotPromoted(x),
+            ]),
+          ]);
+        });
+
+        test('unless the then-block mutates it', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkNotPromoted(x),
+              x.write(expr('int')).stmt,
+            ]),
+          ]);
+        });
+
+        test('even if the condition mutates it', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(
+                x
+                    .write(expr('int'))
+                    .parenthesized
+                    .eq(expr('int'))
+                    .and(x.read.is_('int')),
+                [
+                  checkPromoted(x, 'int'),
+                ]),
+          ]);
+        });
+
+        test('even if the else-block mutates it', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkPromoted(x, 'int'),
+            ], [
+              x.write(expr('int')).stmt,
+            ]),
+          ]);
+        });
+
+        test('unless a closure mutates it', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkNotPromoted(x),
+            ]),
+            localFunction([
+              x.write(expr('int')).stmt,
+            ]),
+          ]);
+        });
+
+        test(
+            'unless a closure in the then-block accesses it and it is mutated '
+            'anywhere', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkNotPromoted(x),
+              localFunction([
+                x.read.stmt,
+              ]),
+            ]),
+            x.write(expr('int')).stmt,
+          ]);
+        });
+
+        test(
+            'unless a closure in the then-block accesses it and it is mutated '
+            'anywhere, even if the access is deeply nested', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkNotPromoted(x),
+              localFunction([
+                localFunction([
+                  x.read.stmt,
+                ]),
+              ]),
+            ]),
+            x.write(expr('int')).stmt,
+          ]);
+        });
+
+        test(
+            'even if a closure in the condition accesses it and it is mutated '
+            'somewhere', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(
+                localFunction([
+                  x.read.stmt,
+                ]).thenExpr(expr('bool')).and(x.read.is_('int')),
+                [
+                  checkPromoted(x, 'int'),
+                ]),
+            x.write(expr('int')).stmt,
+          ]);
+        });
+
+        test(
+            'even if a closure in the else-block accesses it and it is mutated '
+            'somewhere', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkPromoted(x, 'int'),
+            ], [
+              localFunction([
+                x.read.stmt,
+              ]),
+            ]),
+            x.write(expr('int')).stmt,
+          ]);
+        });
+
+        test(
+            'even if a closure in the then-block accesses it, provided it is '
+            'not mutated anywhere', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkPromoted(x, 'int'),
+              localFunction([
+                x.read.stmt,
+              ]),
+            ]),
+          ]);
+        });
+      });
+
+      test('handles arbitrary conditions', () {
+        var h = Harness(legacy: true);
+        h.run([
+          if_(expr('bool'), []),
+        ]);
+      });
+
+      test('handles a condition that is a variable', () {
+        var h = Harness(legacy: true);
+        var x = Var('x', 'bool');
+        h.run([
+          if_(x.read, []),
+        ]);
+      });
+
+      test('handles multiple promotions', () {
+        var h = Harness(legacy: true);
+        var x = Var('x', 'Object');
+        var y = Var('y', 'Object');
+        h.run([
+          if_(x.read.is_('int').and(y.read.is_('String')), [
+            checkPromoted(x, 'int'),
+            checkPromoted(y, 'String'),
+          ]),
+        ]);
+      });
+    });
+
+    group('conditional expression', () {
+      group('promotes a variable whose type is shown by its condition', () {
+        test('within then-expression', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .conditional(checkPromoted(x, 'int').thenExpr(expr('Object')),
+                    expr('Object'))
+                .stmt,
+          ]);
+        });
+
+        test('but not within else-expression', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .conditional(expr('Object'),
+                    checkNotPromoted(x).thenExpr(expr('Object')))
+                .stmt,
+          ]);
+        });
+
+        test('unless the then-expression mutates it', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .conditional(
+                    block([
+                      checkNotPromoted(x),
+                      x.write(expr('int')).stmt,
+                    ]).thenExpr(expr('Object')),
+                    expr('Object'))
+                .stmt,
+          ]);
+        });
+
+        test('even if the condition mutates it', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x
+                .write(expr('int'))
+                .parenthesized
+                .eq(expr('int'))
+                .and(x.read.is_('int'))
+                .conditional(checkPromoted(x, 'int').thenExpr(expr('Object')),
+                    expr('Object'))
+                .stmt,
+          ]);
+        });
+
+        test('even if the else-expression mutates it', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .conditional(checkPromoted(x, 'int').thenExpr(expr('int')),
+                    x.write(expr('int')))
+                .stmt,
+          ]);
+        });
+
+        test('unless a closure mutates it', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .conditional(checkNotPromoted(x).thenExpr(expr('Object')),
+                    expr('Object'))
+                .stmt,
+            localFunction([
+              x.write(expr('int')).stmt,
+            ]),
+          ]);
+        });
+
+        test(
+            'unless a closure in the then-expression accesses it and it is '
+            'mutated anywhere', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .conditional(
+                    block([
+                      checkNotPromoted(x),
+                      localFunction([
+                        x.read.stmt,
+                      ]),
+                    ]).thenExpr(expr('Object')),
+                    expr('Object'))
+                .stmt,
+            x.write(expr('int')).stmt,
+          ]);
+        });
+
+        test(
+            'even if a closure in the condition accesses it and it is mutated '
+            'somewhere', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            localFunction([
+              x.read.stmt,
+            ])
+                .thenExpr(expr('Object'))
+                .and(x.read.is_('int'))
+                .conditional(checkPromoted(x, 'int').thenExpr(expr('Object')),
+                    expr('Object'))
+                .stmt,
+            x.write(expr('int')).stmt,
+          ]);
+        });
+
+        test(
+            'even if a closure in the else-expression accesses it and it is '
+            'mutated somewhere', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .conditional(
+                    checkPromoted(x, 'int').thenExpr(expr('Object')),
+                    localFunction([
+                      x.read.stmt,
+                    ]).thenExpr(expr('Object')))
+                .stmt,
+            x.write(expr('int')).stmt,
+          ]);
+        });
+
+        test(
+            'even if a closure in the then-expression accesses it, provided it '
+            'is not mutated anywhere', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .conditional(
+                    block([
+                      checkPromoted(x, 'int'),
+                      localFunction([
+                        x.read.stmt,
+                      ]),
+                    ]).thenExpr(expr('Object')),
+                    expr('Object'))
+                .stmt,
+          ]);
+        });
+      });
+
+      test('handles arbitrary conditions', () {
+        var h = Harness(legacy: true);
+        h.run([
+          expr('bool').conditional(expr('Object'), expr('Object')).stmt,
+        ]);
+      });
+
+      test('handles a condition that is a variable', () {
+        var h = Harness(legacy: true);
+        var x = Var('x', 'bool');
+        h.run([
+          x.read.conditional(expr('Object'), expr('Object')).stmt,
+        ]);
+      });
+
+      test('handles multiple promotions', () {
+        var h = Harness(legacy: true);
+        var x = Var('x', 'Object');
+        var y = Var('y', 'Object');
+        h.run([
+          x.read
+              .is_('int')
+              .and(y.read.is_('String'))
+              .conditional(
+                  block([
+                    checkPromoted(x, 'int'),
+                    checkPromoted(y, 'String'),
+                  ]).thenExpr(expr('Object')),
+                  expr('Object'))
+              .stmt
+        ]);
+      });
+    });
+
+    group('logical', () {
+      group('and', () {
+        group("shows a variable's type", () {
+          test('if the lhs shows the type', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              if_(x.read.is_('int').and(expr('bool')), [
+                checkPromoted(x, 'int'),
+              ]),
+            ]);
+          });
+
+          test('if the rhs shows the type', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              if_(expr('bool').and(x.read.is_('int')), [
+                checkPromoted(x, 'int'),
+              ]),
+            ]);
+          });
+
+          test('unless the rhs mutates it', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              if_(x.read.is_('int').and(x.write(expr('bool'))), [
+                checkNotPromoted(x),
+              ]),
+            ]);
+          });
+
+          test('unless the rhs mutates it, even if the rhs also shows the type',
+              () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              if_(
+                  expr('bool').and(x
+                      .write(expr('Object'))
+                      .and(x.read.is_('int'))
+                      .parenthesized),
+                  [
+                    checkNotPromoted(x),
+                  ]),
+            ]);
+          });
+
+          test('unless a closure mutates it', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              if_(x.read.is_('int').and(expr('bool')), [
+                checkNotPromoted(x),
+              ]),
+              localFunction([
+                x.write(expr('int')).stmt,
+              ]),
+            ]);
+          });
+        });
+
+        group('promotes a variable whose type is shown by its lhs', () {
+          test('within its rhs', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              x.read
+                  .is_('int')
+                  .and(checkPromoted(x, 'int').thenExpr(expr('bool')))
+                  .stmt,
+            ]);
+          });
+
+          test('unless the lhs mutates it', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              x
+                  .write(expr('int'))
+                  .parenthesized
+                  .eq(expr('int'))
+                  .and(x.read.is_('int'))
+                  .parenthesized
+                  .and(checkNotPromoted(x).thenExpr(expr('bool')))
+                  .stmt,
+            ]);
+          });
+
+          test('unless the rhs mutates it', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              x.read
+                  .is_('int')
+                  .and(checkNotPromoted(x).thenExpr(x.write(expr('bool'))))
+                  .stmt,
+            ]);
+          });
+
+          test('unless a closure mutates it', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              x.read
+                  .is_('int')
+                  .and(checkNotPromoted(x).thenExpr(expr('bool')))
+                  .stmt,
+              localFunction([
+                x.write(expr('int')).stmt,
+              ]),
+            ]);
+          });
+
+          test(
+              'unless a closure in the rhs accesses it and it is mutated '
+              'anywhere', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              x.read
+                  .is_('int')
+                  .and(block([
+                    checkNotPromoted(x),
+                    localFunction([
+                      x.read.stmt,
+                    ]),
+                  ]).thenExpr(expr('bool')))
+                  .stmt,
+              x.write(expr('int')).stmt,
+            ]);
+          });
+
+          test(
+              'even if a closure in the lhs accesses it and it is mutated '
+              'somewhere', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              localFunction([
+                x.read.stmt,
+              ])
+                  .thenExpr(expr('Object'))
+                  .and(x.read.is_('int'))
+                  .parenthesized
+                  .and(checkPromoted(x, 'int').thenExpr(expr('bool')))
+                  .stmt,
+              x.write(expr('int')).stmt,
+            ]);
+          });
+
+          test(
+              'even if a closure in the rhs accesses it, provided it is not '
+              'mutated anywhere', () {
+            var h = Harness(legacy: true);
+            var x = Var('x', 'Object');
+            h.run([
+              x.read
+                  .is_('int')
+                  .and(block([
+                    checkPromoted(x, 'int'),
+                    localFunction([
+                      x.read.stmt,
+                    ]),
+                  ]).thenExpr(expr('bool')))
+                  .stmt,
+            ]);
+          });
+        });
+
+        test('uses lhs promotion if rhs is not to a subtype', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          // Note: for this to be an effective test, we need to mutate `x` on
+          // the LHS of the outer `&&` so that `x` is not promoted on the RHS
+          // (and thus the lesser promotion on the RHS can take effect).
+          h.run([
+            if_(
+                x
+                    .write(expr('Object'))
+                    .parenthesized
+                    .and(x.read.is_('int'))
+                    .parenthesized
+                    .and(x.read.is_('num')),
+                [
+                  checkPromoted(x, 'int'),
+                ]),
+          ]);
+        });
+
+        test('uses rhs promotion if rhs is to a subtype', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('num').and(x.read.is_('int')), [
+              checkPromoted(x, 'int'),
+            ]),
+          ]);
+        });
+
+        test('can handle multiple promotions on lhs', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          var y = Var('y', 'Object');
+          h.run([
+            x.read
+                .is_('int')
+                .and(y.read.is_('String'))
+                .parenthesized
+                .and(block([
+                  checkPromoted(x, 'int'),
+                  checkPromoted(y, 'String'),
+                ]).thenExpr(expr('bool')))
+                .stmt,
+          ]);
+        });
+
+        test('handles variables', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'bool');
+          var y = Var('y', 'bool');
+          h.run([
+            if_(x.read.and(y.read), []),
+          ]);
+        });
+
+        test('handles arbitrary expressions', () {
+          var h = Harness(legacy: true);
+          h.run([
+            if_(expr('bool').and(expr('bool')), []),
+          ]);
+        });
+      });
+
+      test('or is ignored', () {
+        var h = Harness(legacy: true);
+        var x = Var('x', 'Object');
+        h.run([
+          if_(x.read.is_('int').or(x.read.is_('int')), [
+            checkNotPromoted(x),
+          ], [
+            checkNotPromoted(x),
+          ])
+        ]);
+      });
+    });
+
+    group('is test', () {
+      group("shows a variable's type", () {
+        test('normally', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkPromoted(x, 'int'),
+            ], [
+              checkNotPromoted(x),
+            ])
+          ]);
+        });
+
+        test('unless the test is inverted', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('int', isInverted: true), [
+              checkNotPromoted(x),
+            ], [
+              checkNotPromoted(x),
+            ])
+          ]);
+        });
+
+        test('unless the tested type is not a subtype of the declared type',
+            () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'String');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkNotPromoted(x),
+            ], [
+              checkNotPromoted(x),
+            ])
+          ]);
+        });
+
+        test("even when the variable's type has been previously promoted", () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('num'), [
+              if_(x.read.is_('int'), [
+                checkPromoted(x, 'int'),
+              ], [
+                checkPromoted(x, 'num'),
+              ])
+            ]),
+          ]);
+        });
+
+        test(
+            'unless the tested type is not a subtype of the previously '
+            'promoted type', () {
+          var h = Harness(legacy: true);
+          var x = Var('x', 'Object');
+          h.run([
+            if_(x.read.is_('String'), [
+              if_(x.read.is_('int'), [
+                checkPromoted(x, 'String'),
+              ], [
+                checkPromoted(x, 'String'),
+              ])
+            ]),
+          ]);
+        });
+
+        test('even when the declared type is a type variable', () {
+          var h = Harness(legacy: true);
+          h.addPromotionException('T', 'int', 'T&int');
+          var x = Var('x', 'T');
+          h.run([
+            if_(x.read.is_('int'), [
+              checkPromoted(x, 'T&int'),
+            ]),
+          ]);
+        });
+      });
+
+      test('handles arbitrary expressions', () {
+        var h = Harness(legacy: true);
+        h.run([
+          if_(expr('Object').is_('int'), []),
+        ]);
+      });
+    });
+
+    test('forwardExpression does not re-activate a deeply nested expression',
+        () {
+      var h = Harness(legacy: true);
+      var x = Var('x', 'Object');
+      h.run([
+        if_(x.read.is_('int').eq(expr('Object')).thenStmt(block([])), [
+          checkNotPromoted(x),
+        ]),
+      ]);
+    });
+
+    test(
+        'parenthesizedExpression does not re-activate a deeply nested '
+        'expression', () {
+      var h = Harness(legacy: true);
+      var x = Var('x', 'Object');
+      h.run([
+        if_(x.read.is_('int').eq(expr('Object')).parenthesized, [
+          checkNotPromoted(x),
+        ]),
+      ]);
+    });
+
+    test('variableRead returns the promoted type if promoted', () {
+      var h = Harness(legacy: true);
+      var x = Var('x', 'Object');
+      h.run([
+        if_(
+            x
+                .readAndCheckPromotedType((type) => expect(type, isNull))
+                .is_('int'),
+            [
+              x
+                  .readAndCheckPromotedType((type) => expect(type!.type, 'int'))
+                  .stmt,
+            ]),
+      ]);
+    });
+  });
 }
 
 /// Returns the appropriate matcher for expecting an assertion error to be
@@ -3413,7 +5390,7 @@
       'interest set $expectedTypes');
 }
 
-Matcher _matchPromotionChain(List<String> expectedTypes) {
+Matcher _matchPromotionChain(List<String>? expectedTypes) {
   if (expectedTypes == null) return isNull;
   return predicate(
       (List<Type> x) =>
@@ -3422,11 +5399,16 @@
 }
 
 Matcher _matchVariableModel(
-    {Object chain = anything,
-    Object ofInterest = anything,
-    Object assigned = anything,
-    Object unassigned = anything,
-    Object writeCaptured = anything}) {
+    {Object? chain,
+    Object? ofInterest,
+    Object? assigned,
+    Object? unassigned,
+    Object? writeCaptured}) {
+  chain ??= anything;
+  ofInterest ??= anything;
+  assigned ??= anything;
+  unassigned ??= anything;
+  writeCaptured ??= anything;
   Matcher chainMatcher =
       chain is List<String> ? _matchPromotionChain(chain) : wrapMatcher(chain);
   Matcher ofInterestMatcher = ofInterest is List<String>
@@ -3449,3 +5431,6 @@
       'unassigned: ${_describeMatcher(unassignedMatcher)}, '
       'writeCaptured: ${_describeMatcher(writeCapturedMatcher)})');
 }
+
+Reference<Var, Type> _varRef(Var variable) =>
+    new VariableReference<Var, Type>(variable);
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/local_boolean.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/local_boolean.dart
new file mode 100644
index 0000000..4c7b408
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/local_boolean.dart
@@ -0,0 +1,149 @@
+// 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.
+
+finalLocalBool(int? x) {
+  final bool b = x == null;
+  if (!b) {
+    /*nonNullable*/ x;
+  } else {
+    x;
+  }
+}
+
+localBool(int? x) {
+  bool b = x == null;
+  if (!b) {
+    /*nonNullable*/ x;
+  } else {
+    x;
+  }
+}
+
+localBool_assigned(int? x, bool b1) {
+  bool b2 = b1;
+  b2 = x == null;
+  if (!b2) {
+    /*nonNullable*/ x;
+  } else {
+    x;
+  }
+}
+
+localBool_assignedDynamic(int? x, bool b1) {
+  dynamic b2 = b1;
+  b2 = x == null;
+  if (!b2) {
+    /*nonNullable*/ x;
+  } else {
+    x;
+  }
+}
+
+parameter_assigned(int? x, bool b) {
+  b = x == null;
+  if (!b) {
+    /*nonNullable*/ x;
+  } else {
+    x;
+  }
+}
+
+parameter_assignedDynamic(int? x, dynamic b) {
+  b = x == null;
+  if (!b) {
+    /*nonNullable*/ x;
+  } else {
+    x;
+  }
+}
+
+lateFinalLocalBool(int? x) {
+  late final bool b = x == null;
+  if (!b) {
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    x;
+  } else {
+    x;
+  }
+}
+
+lateLocalBool(int? x) {
+  late bool b = x == null;
+  if (!b) {
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    x;
+  } else {
+    x;
+  }
+}
+
+lateLocalBool_assignedAndInitialized(int? x, bool b1) {
+  late bool b2 = b1;
+  b2 = x == null;
+  if (!b2) {
+    /*nonNullable*/ x;
+  } else {
+    x;
+  }
+}
+
+lateLocalBool_assignedButNotInitialized(int? x) {
+  late bool b;
+  b = x == null;
+  if (!b) {
+    /*nonNullable*/ x;
+  } else {
+    x;
+  }
+}
+
+rebaseWithDemotion(int? x, int? y, int? z, int? a) {
+  x;
+  y;
+  z;
+  if (y == null) return;
+  x;
+  /*nonNullable*/ y;
+  z;
+  bool b = x == null;
+  x;
+  /*nonNullable*/ y;
+  z;
+  if (z == null) return;
+  x;
+  /*nonNullable*/ y;
+  /*nonNullable*/ z;
+  y = a;
+  x;
+  y;
+  /*nonNullable*/ z;
+  if (b) return;
+  /*nonNullable*/ x;
+  y;
+  /*nonNullable*/ z;
+}
+
+compoundAssignment(int? x, dynamic b) {
+  b += x == null;
+  if (!b) {
+    // It's not safe to promote, because there's no guarantee that value of `b`
+    // has anything to do with the result of `x == null`.
+    x;
+  } else {
+    x;
+  }
+}
+
+ifNullAssignment(int? x, dynamic b) {
+  b ??= x == null;
+  if (!b) {
+    // It's not safe to promote, because there's no guarantee that value of `b`
+    // has anything to do with the result of `x == null`.
+    x;
+  } else {
+    x;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/final_initializer.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/final_initializer.dart
new file mode 100644
index 0000000..e2221c4
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/final_initializer.dart
@@ -0,0 +1,36 @@
+// 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.
+
+// This test checks that final variables aren't promoted to a type of interest
+// based on their initializer, but non-final variables are.
+
+nonFinalPromotesWhenInitializerNonNullable(int i) {
+  num? n = i;
+  /*num*/ n;
+}
+
+nonFinalDoesNotPromoteWhenInitializerNullable(int? i) {
+  num? n = i;
+  n;
+}
+
+finalDoesNotPromote(int i) {
+  final num? n = i;
+  n;
+}
+
+lateNonFinalPromotesWhenInitializerNonNullable(int i) {
+  late num? n = i;
+  /*num*/ n;
+}
+
+lateNonFinalDoesNotPromoteWhenInitializerNullable(int? i) {
+  late num? n = i;
+  n;
+}
+
+lateFinalDoesNotPromote(int i) {
+  late final num? n = i;
+  n;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/implicit_downcast.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/implicit_downcast.dart
new file mode 100644
index 0000000..1c406f5
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/implicit_downcast.dart
@@ -0,0 +1,161 @@
+// 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.
+
+// The tests in this file verify that implicit downcasts *don't* cause
+// promotions.
+
+f(int i) {}
+
+assignment(int i, dynamic d) {
+  i = d;
+  d;
+}
+
+nullAwareAssignment(int i, dynamic d) {
+  i ??= d;
+  d;
+}
+
+compoundAssignment(num n, dynamic d) {
+  n += d;
+  d;
+}
+
+initialization(dynamic d) {
+  int i = d;
+  d;
+}
+
+parameter(dynamic d) {
+  f(d);
+  d;
+}
+
+ifCondition(dynamic d) {
+  if (d) {}
+  d;
+}
+
+ifCondition_then(dynamic d) {
+  if (d) {
+    d;
+  }
+}
+
+ifCondition_return(dynamic d) {
+  if (d) return;
+  d;
+}
+
+ifElementCondition(dynamic d) {
+  [if (d) null];
+  d;
+}
+
+ifElementCondition_then(dynamic d) {
+  [if (d) d];
+}
+
+forCondition(dynamic d) {
+  for (; d;) {}
+  d;
+}
+
+forCondition_body(dynamic d) {
+  for (; d;) {
+    d;
+  }
+}
+
+forElementCondition(dynamic d) {
+  [for (; d;) null];
+  d;
+}
+
+forElementCondition_body(dynamic d) {
+  [for (; d;) d];
+}
+
+forEachIterable(dynamic d) {
+  for (var item in d) {}
+  d;
+}
+
+forEachIterable_body(dynamic d) {
+  for (var item in d) {
+    d;
+  }
+}
+
+forEachElementIterable(dynamic d) {
+  [for (var item in d) null];
+  d;
+}
+
+forEachElementIterable_body(dynamic d) {
+  [for (var item in d) d];
+}
+
+whileCondition(dynamic d) {
+  while (d) {}
+  d;
+}
+
+whileCondition_body(dynamic d) {
+  while (d) {
+    d;
+  }
+}
+
+doCondition(dynamic d) {
+  do {} while (d);
+  d;
+}
+
+conditionalCondition(dynamic d) {
+  d ? null : null;
+  d;
+}
+
+conditionalCondition_thenElse(dynamic d) {
+  d ? d : d;
+}
+
+andLhs(dynamic d, bool b) {
+  d && b;
+  d;
+}
+
+andRhs(dynamic d, bool b) {
+  b && d;
+  d;
+}
+
+andBoth(dynamic d, bool b) {
+  d && d;
+}
+
+orLhs(dynamic d, bool b) {
+  d || b;
+  d;
+}
+
+orRhs(dynamic d, bool b) {
+  b || d;
+  d;
+}
+
+orBotn(dynamic d, bool b) {
+  d || d;
+}
+
+logicalNot(dynamic d, bool b) {
+  !d;
+  d;
+}
+
+await_(dynamic d) async {
+  await d;
+  d;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/this.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/this.dart
new file mode 100644
index 0000000..4ea657e
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/this.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.
+
+// This test verifies that `this` cannot be promoted, even if it appears in an
+// extension method.
+
+class C {
+  void insideClass() {
+    if (this is D) {
+      this;
+    }
+  }
+}
+
+class D extends C {}
+
+extension on C {
+  void insideExtension() {
+    if (this is D) {
+      this;
+    }
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/id_generation_test.dart b/pkg/_fe_analyzer_shared/test/id_generation_test.dart
index 0f19b23..56abad3 100644
--- a/pkg/_fe_analyzer_shared/test/id_generation_test.dart
+++ b/pkg/_fe_analyzer_shared/test/id_generation_test.dart
@@ -467,7 +467,7 @@
 void testString(
   String text, {
   Map<String, Map<Id, String>> actualData: const {},
-  String expectedResult,
+  String? expectedResult,
   int classOffset: 0,
   int memberOffset: 0,
 }) {
@@ -487,7 +487,7 @@
 void testFeatures(
   String text, {
   Map<String, Map<Id, String>> actualData: const {},
-  String expectedResult,
+  String? expectedResult,
   int classOffset: 0,
   int memberOffset: 0,
 }) {
@@ -507,7 +507,7 @@
 
 void testGeneral<T>(DataInterpreter<T> dataInterpreter, String text,
     {Map<String, Map<Id, T>> actualData: const {},
-    String expectedResult,
+    String? expectedResult,
     int classOffset: 0,
     int memberOffset: 0}) {
   expectedResult ??= text;
@@ -517,7 +517,10 @@
   for (String marker in markers) {
     expectedMaps[marker] = new MemberAnnotations<IdValue>();
   }
-  computeExpectedMap(mainUri, mainUri.path, code, expectedMaps);
+  computeExpectedMap(mainUri, mainUri.path, code, expectedMaps,
+      onFailure: (String message) {
+    throw message;
+  });
 
   Map<String, Map<Uri, Map<Id, ActualData<T>>>> actualAnnotations = {};
   actualData.forEach((String marker, Map<Id, T> data) {
@@ -531,6 +534,8 @@
         offset = memberOffset;
       } else if (id is ClassId) {
         offset = classOffset;
+      } else {
+        offset = 0;
       }
       actualData[id] = new ActualData<T>(id, value, mainUri, offset, text);
     });
@@ -543,10 +548,11 @@
       actualAnnotations,
       dataInterpreter);
   AnnotatedCode generated = new AnnotatedCode(
-      code.annotatedCode, code.sourceCode, annotations[mainUri]);
+      code.annotatedCode, code.sourceCode, annotations[mainUri]!);
   String actualResult = generated.toText();
   if (expectedResult != actualResult) {
     print("Unexpected result for '$text'"
+        // ignore: unnecessary_null_comparison
         "${actualData != null ? ' with actualData=$actualData' : ''}");
     print('---expected-------------------------------------------------------');
     print(expectedResult);
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_out.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_out.dart
index d8429c0..8930b99 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_out.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_parameter_opt_out.dart
@@ -66,8 +66,7 @@
 /*cfe|cfe:builder.member: C2._simpleInstanceOfTrue:bool* Function(dynamic)**/
 /*cfe|cfe:builder.member: C2.==:bool* Function(dynamic)**/
 class C2 extends B implements A {
-  /*cfe|cfe:builder.member: C2.method:dynamic Function(dynamic, {dynamic named})**/
-  /*analyzer.member: C2.method:Object* Function(Object*, {Object* named})**/
+  /*member: C2.method:Object* Function(Object*, {Object* named})**/
   method(o, {named}) {}
 }
 
@@ -99,8 +98,7 @@
 /*cfe|cfe:builder.member: C4._simpleInstanceOfTrue:bool* Function(dynamic)**/
 /*cfe|cfe:builder.member: C4.==:bool* Function(dynamic)**/
 class C4 implements B, A {
-  /*cfe|cfe:builder.member: C4.method:dynamic Function(dynamic, {dynamic named})**/
-  /*analyzer.member: C4.method:Object* Function(Object*, {Object* named})**/
+  /*member: C4.method:Object* Function(Object*, {Object* named})**/
   method(o, {named}) {}
 }
 
diff --git a/pkg/_fe_analyzer_shared/test/sdk/allowed_experiments_test.dart b/pkg/_fe_analyzer_shared/test/sdk/allowed_experiments_test.dart
index ad70c28..255e072 100644
--- a/pkg/_fe_analyzer_shared/test/sdk/allowed_experiments_test.dart
+++ b/pkg/_fe_analyzer_shared/test/sdk/allowed_experiments_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:_fe_analyzer_shared/src/sdk/allowed_experiments.dart';
-import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 
 main() {
@@ -159,9 +158,9 @@
   group('valid', () {
     void assertExperiments(
       AllowedExperiments experiments, {
-      @required List<String> sdkDefaultExperiments,
-      @required Map<String, List<String>> sdkLibraryExperiments,
-      @required Map<String, List<String>> packageExperiments,
+      required List<String> sdkDefaultExperiments,
+      required Map<String, List<String>> sdkLibraryExperiments,
+      required Map<String, List<String>> packageExperiments,
     }) {
       expect(experiments.sdkDefaultExperiments, sdkDefaultExperiments);
       expect(experiments.sdkLibraryExperiments, sdkLibraryExperiments);
diff --git a/pkg/_fe_analyzer_shared/test/template_replacement_test.dart b/pkg/_fe_analyzer_shared/test/template_replacement_test.dart
new file mode 100644
index 0000000..b5b627c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/template_replacement_test.dart
@@ -0,0 +1,28 @@
+// 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:_fe_analyzer_shared/src/messages/codes.dart';
+
+void main() {
+  test('#a', {'a': 'b'}, 'b');
+  test('#a #a', {'a': 'b'}, 'b b');
+  test('#a #b', {'a': 'b', 'b': 'c'}, 'b c');
+  test('#a #b', {'a': '#b', 'b': 'c'}, '#b c');
+
+  test('#a1 #a2', {'a1': 'b', 'a2': 'c'}, 'b c');
+  test('#a1 #a2', {'a1': '#a2', 'a2': 'a2'}, '#a2 a2');
+  test('#a1 #a1 #a2 #a2', {'a1': '#a2', 'a2': 'b'}, '#a2 #a2 b b');
+}
+
+void test(
+    String template, Map<String, dynamic>? arguments, String expectedResult) {
+  expect(expectedResult, applyArgumentsToTemplate(template, arguments!),
+      'Unexpected result for replacing $arguments in "$template"');
+}
+
+void expect(expected, actual, String message) {
+  if (expected != actual) {
+    throw '$message: Expected "$expected", actual "$actual".';
+  }
+}
diff --git a/pkg/_js_interop_checks/lib/js_interop_checks.dart b/pkg/_js_interop_checks/lib/js_interop_checks.dart
index 8bb8c6d..e3f0978 100644
--- a/pkg/_js_interop_checks/lib/js_interop_checks.dart
+++ b/pkg/_js_interop_checks/lib/js_interop_checks.dart
@@ -17,17 +17,40 @@
         messageJsInteropNonExternalConstructor,
         messageJsInteropNonExternalMember,
         templateJsInteropDartClassExtendsJSClass,
-        templateJsInteropJSClassExtendsDartClass;
+        templateJsInteropJSClassExtendsDartClass,
+        templateJsInteropNativeClassInAnnotation;
 
 import 'src/js_interop.dart';
 
 class JsInteropChecks extends RecursiveVisitor<void> {
   final CoreTypes _coreTypes;
   final DiagnosticReporter<Message, LocatedMessage> _diagnosticsReporter;
+  final Map<String, Class> _nativeClasses;
   bool _classHasJSAnnotation = false;
+  bool _classHasAnonymousAnnotation = false;
   bool _libraryHasJSAnnotation = false;
+  bool _libraryIsGlobalNamespace = false;
 
-  JsInteropChecks(this._coreTypes, this._diagnosticsReporter);
+  JsInteropChecks(
+      this._coreTypes, this._diagnosticsReporter, this._nativeClasses);
+
+  /// Extract all native class names from the [component].
+  ///
+  /// Returns a map from the name to the underlying Class node. This is a
+  /// static method so that the result can be cached in the corresponding
+  /// compiler target.
+  static Map<String, Class> getNativeClasses(Component component) {
+    Map<String, Class> nativeClasses = {};
+    for (var library in component.libraries) {
+      for (var cls in library.classes) {
+        var nativeNames = getNativeNames(cls);
+        for (var nativeName in nativeNames) {
+          nativeClasses[nativeName] = cls;
+        }
+      }
+    }
+    return nativeClasses;
+  }
 
   @override
   void defaultMember(Member member) {
@@ -40,6 +63,7 @@
   @override
   void visitClass(Class cls) {
     _classHasJSAnnotation = hasJSInteropAnnotation(cls);
+    _classHasAnonymousAnnotation = hasAnonymousAnnotation(cls);
     var superclass = cls.superclass;
     if (superclass != null && superclass != _coreTypes.objectClass) {
       var superHasJSAnnotation = hasJSInteropAnnotation(superclass);
@@ -59,14 +83,53 @@
             cls.location.file);
       }
     }
+    if (_classHasJSAnnotation &&
+        !_classHasAnonymousAnnotation &&
+        _libraryIsGlobalNamespace) {
+      var jsClass = getJSName(cls);
+      if (jsClass.isEmpty) {
+        // No rename, take the name of the class directly.
+        jsClass = cls.name;
+      } else {
+        // Remove any global prefixes. Regex here is greedy and will only return
+        // 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');
+      }
+      if (_nativeClasses.containsKey(jsClass)) {
+        var nativeClass = _nativeClasses[jsClass];
+        _diagnosticsReporter.report(
+            templateJsInteropNativeClassInAnnotation.withArguments(
+                cls.name,
+                nativeClass.name,
+                nativeClass.enclosingLibrary.importUri.toString()),
+            cls.fileOffset,
+            cls.name.length,
+            cls.location.file);
+      }
+    }
     super.visitClass(cls);
+    _classHasAnonymousAnnotation = false;
     _classHasJSAnnotation = false;
   }
 
   @override
   void visitLibrary(Library lib) {
     _libraryHasJSAnnotation = hasJSInteropAnnotation(lib);
+    _libraryIsGlobalNamespace = false;
+    if (_libraryHasJSAnnotation) {
+      var libraryAnnotation = getJSName(lib);
+      var globalRegexp = new RegExp(r'^(self|window)(\.(self|window))*$');
+      if (libraryAnnotation.isEmpty ||
+          globalRegexp.hasMatch(libraryAnnotation)) {
+        _libraryIsGlobalNamespace = true;
+      }
+    } else {
+      _libraryIsGlobalNamespace = true;
+    }
     super.visitLibrary(lib);
+    _libraryIsGlobalNamespace = false;
     _libraryHasJSAnnotation = false;
   }
 
@@ -98,7 +161,7 @@
     }
 
     var isAnonymousFactory =
-        isAnonymousClassMember(procedure) && procedure.isFactory;
+        _classHasAnonymousAnnotation && procedure.isFactory;
 
     if (isAnonymousFactory) {
       if (procedure.function != null &&
diff --git a/pkg/_js_interop_checks/lib/src/js_interop.dart b/pkg/_js_interop_checks/lib/src/js_interop.dart
index 33ab00b..7831f2d 100644
--- a/pkg/_js_interop_checks/lib/src/js_interop.dart
+++ b/pkg/_js_interop_checks/lib/src/js_interop.dart
@@ -9,15 +9,48 @@
 bool hasJSInteropAnnotation(Annotatable a) =>
     a.annotations.any(_isPublicJSAnnotation);
 
-/// Returns true if [m] belongs to an anonymous class.
-bool isAnonymousClassMember(Member m) {
-  var enclosingClass = m.enclosingClass;
-  if (enclosingClass == null) return false;
-  return enclosingClass.annotations.any(_isAnonymousAnnotation);
+/// Returns true iff the node has an `@anonymous(...)` annotation from
+/// `package:js` or from the internal `dart:_js_annotations`.
+bool hasAnonymousAnnotation(Annotatable a) =>
+    a.annotations.any(_isAnonymousAnnotation);
+
+/// If [a] has a `@JS('...')` annotation, returns the value inside the
+/// parentheses.
+///
+/// If there is none or the class does not have a `@JS()` annotation, returns
+/// an empty String.
+String getJSName(Annotatable a) {
+  String jsClass = '';
+  for (var annotation in a.annotations) {
+    if (_isPublicJSAnnotation(annotation)) {
+      var jsClasses = _stringAnnotationValues(annotation);
+      if (jsClasses.length > 0) {
+        jsClass = jsClasses[0];
+      }
+    }
+  }
+  return jsClass;
+}
+
+/// If [a] has a `@Native('...')` annotation, returns the values inside the
+/// parentheses.
+///
+/// If there are none or the class does not have a `@Native()` annotation,
+/// returns an empty list. Unlike `@JS()`, the string within `@Native()` is
+/// allowed to contain several classes separated by a `,`.
+List<String> getNativeNames(Annotatable a) {
+  List<String> nativeClasses = [];
+  for (var annotation in a.annotations) {
+    if (_isNativeAnnotation(annotation)) {
+      nativeClasses.addAll(_stringAnnotationValues(annotation));
+    }
+  }
+  return nativeClasses;
 }
 
 final _packageJs = Uri.parse('package:js/js.dart');
 final _internalJs = Uri.parse('dart:_js_annotations');
+final _jsHelper = Uri.parse('dart:_js_helper');
 
 /// Returns true if [value] is the `JS` annotation from `package:js` or from
 /// `dart:_js_annotations`.
@@ -39,12 +72,20 @@
           c.enclosingLibrary.importUri == _internalJs);
 }
 
+bool _isNativeAnnotation(Expression value) {
+  var c = _annotationClass(value);
+  return c != null &&
+      c.name == 'Native' &&
+      c.enclosingLibrary.importUri == _jsHelper;
+}
+
 /// Returns the class of the instance referred to by metadata annotation [node].
 ///
 /// For example:
 ///
 /// - `@JS()` would return the "JS" class in "package:js".
 /// - `@anonymous` would return the "_Anonymous" class in "package:js".
+/// - `@Native` would return the "Native" class in "dart:_js_helper".
 ///
 /// This function works regardless of whether the CFE is evaluating constants,
 /// or whether the constant is a field reference (such as "anonymous" above).
@@ -60,3 +101,40 @@
   }
   return null;
 }
+
+/// Returns the string values inside of a metadata annotation [node].
+///
+/// For example:
+/// - `@JS('Foo')` would return ['Foo'].
+/// - `@Native('Foo,Bar')` would return ['Foo', 'Bar'].
+///
+/// [node] is expected to be an annotation with either StringConstants or
+/// StringLiterals that can be made up of multiple values. If there are none,
+/// this method returns an empty list. This method throws an assertion if there
+/// are multiple arguments or a named arg in the annotation.
+List<String> _stringAnnotationValues(Expression node) {
+  List<String> values = [];
+  if (node is ConstantExpression) {
+    var constant = node.constant;
+    if (constant is InstanceConstant) {
+      var argLength = constant.fieldValues.values.length;
+      if (argLength == 1) {
+        var value = constant.fieldValues.values.elementAt(0);
+        if (value is StringConstant) values.addAll(value.value.split(','));
+      } else if (argLength > 1) {
+        throw new ArgumentError('Method expects annotation with at most one '
+            'positional argument: $node.');
+      }
+    }
+  } else if (node is ConstructorInvocation) {
+    var argLength = node.arguments.positional.length;
+    if (argLength > 1 || node.arguments.named.length > 0) {
+      throw new ArgumentError('Method expects annotation with at most one '
+          'positional argument: $node.');
+    } else if (argLength == 1) {
+      var value = node.arguments.positional[0];
+      if (value is StringLiteral) values.addAll(value.value.split(','));
+    }
+  }
+  return values;
+}
diff --git a/pkg/analysis_server/README.md b/pkg/analysis_server/README.md
index d93666c..c6a1813 100644
--- a/pkg/analysis_server/README.md
+++ b/pkg/analysis_server/README.md
@@ -13,8 +13,8 @@
 Clients (typically tools, such as an editor) are expected to run the analysis
 server in a separate process and communicate with it using a JSON protocol. The
 original protocol is specified in the file [`analysis_server/doc/api.html`][api]
-and (less complete) [Language Server Protocol][lsp_spec] support is documented
-in [`tool/lsp_spec/README.md`](tool/lsp_spec/README.md).
+and [Language Server Protocol][lsp_spec] support is documented in
+[`tool/lsp_spec/README.md`](tool/lsp_spec/README.md).
 
 ## Features and bugs
 
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 0bce9d2..42a0c71 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.32.1
+  1.32.4
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -236,9 +236,25 @@
   ignoring the item or treating it with some default/fallback handling.
 </p>
 <h3>Changelog</h3>
+<h4>1.32.4</h4>
+<ul>
+  <li>Added <tt>ElementKind.TYPE_ALIAS</tt> and <tt>HighlightRegionType.TYPE_ALIAS</tt>
+    for non-function type aliases.</li>
+</ul>
+<h4>1.32.3</h4>
+<ul>
+  <li>Removed the experimental <tt>completion.listTokenDetails</tt> request and
+    the associated data types.</li>
+</ul>
+<h4>1.32.2</h4>
+<ul>
+  <li>Added <tt>FoldingKind.COMMENT</tt> for folding regions for blocks of
+    comments.</li>
+</ul>
 <h4>1.32.1</h4>
 <ul>
-  <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name completions in <tt>pubspec.yaml</tt></li>
+  <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name
+    completions in <tt>pubspec.yaml</tt>.</li>
 </ul>
 <h3>Domains</h3>
 <p>
@@ -1493,7 +1509,6 @@
   
   
   
-  
 <h3>Requests</h3><dl><dt class="request"><a name="request_completion.getSuggestions">completion.getSuggestions</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "completion.getSuggestions"
@@ -3052,7 +3067,6 @@
   
   
   
-  
 <dl><dt class="typeDefinition"><a name="type_AddContentOverlay">AddContentOverlay: object</a></dt><dd>
     <p>
       A directive to begin overlaying the contents of a file. The supplied
@@ -3824,7 +3838,7 @@
       An enumeration of the kinds of elements.
     </p>
     
-  <dl><dt class="value">CLASS</dt><dt class="value">CLASS_TYPE_ALIAS</dt><dt class="value">COMPILATION_UNIT</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_INVOCATION</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dt class="value">FILE</dt><dt class="value">FUNCTION</dt><dt class="value">FUNCTION_INVOCATION</dt><dt class="value">FUNCTION_TYPE_ALIAS</dt><dt class="value">GETTER</dt><dt class="value">LABEL</dt><dt class="value">LIBRARY</dt><dt class="value">LOCAL_VARIABLE</dt><dt class="value">METHOD</dt><dt class="value">MIXIN</dt><dt class="value">PARAMETER</dt><dt class="value">PREFIX</dt><dt class="value">SETTER</dt><dt class="value">TOP_LEVEL_VARIABLE</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNIT_TEST_GROUP</dt><dt class="value">UNIT_TEST_TEST</dt><dt class="value">UNKNOWN</dt></dl></dd><dt class="typeDefinition"><a name="type_ExecutableFile">ExecutableFile: object</a></dt><dd>
+  <dl><dt class="value">CLASS</dt><dt class="value">CLASS_TYPE_ALIAS</dt><dt class="value">COMPILATION_UNIT</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_INVOCATION</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dt class="value">FILE</dt><dt class="value">FUNCTION</dt><dt class="value">FUNCTION_INVOCATION</dt><dt class="value">FUNCTION_TYPE_ALIAS</dt><dt class="value">GETTER</dt><dt class="value">LABEL</dt><dt class="value">LIBRARY</dt><dt class="value">LOCAL_VARIABLE</dt><dt class="value">METHOD</dt><dt class="value">MIXIN</dt><dt class="value">PARAMETER</dt><dt class="value">PREFIX</dt><dt class="value">SETTER</dt><dt class="value">TOP_LEVEL_VARIABLE</dt><dt class="value">TYPE_ALIAS</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNIT_TEST_GROUP</dt><dt class="value">UNIT_TEST_TEST</dt><dt class="value">UNKNOWN</dt></dl></dd><dt class="typeDefinition"><a name="type_ExecutableFile">ExecutableFile: object</a></dt><dd>
     <p>
       A description of an executable file.
     </p>
@@ -4226,7 +4240,7 @@
       An enumeration of the kinds of folding regions.
     </p>
     
-  <dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
+  <dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">COMMENT</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
     <p>
       A description of a region that can be folded.
     </p>
@@ -4320,7 +4334,7 @@
       </dd><dt class="value">TOP_LEVEL_VARIABLE</dt><dd>
         
         <p>Deprecated - no longer sent.</p>
-      </dd><dt class="value">PARAMETER_DECLARATION</dt><dt class="value">PARAMETER_REFERENCE</dt><dt class="value">STATIC_FIELD_DECLARATION</dt><dt class="value">STATIC_GETTER_DECLARATION</dt><dt class="value">STATIC_GETTER_REFERENCE</dt><dt class="value">STATIC_METHOD_DECLARATION</dt><dt class="value">STATIC_METHOD_REFERENCE</dt><dt class="value">STATIC_SETTER_DECLARATION</dt><dt class="value">STATIC_SETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_FUNCTION_DECLARATION</dt><dt class="value">TOP_LEVEL_FUNCTION_REFERENCE</dt><dt class="value">TOP_LEVEL_GETTER_DECLARATION</dt><dt class="value">TOP_LEVEL_GETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_SETTER_DECLARATION</dt><dt class="value">TOP_LEVEL_SETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_VARIABLE_DECLARATION</dt><dt class="value">TYPE_NAME_DYNAMIC</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNRESOLVED_INSTANCE_MEMBER_REFERENCE</dt><dt class="value">VALID_STRING_ESCAPE</dt></dl></dd><dt class="typeDefinition"><a name="type_HoverInformation">HoverInformation: object</a></dt><dd>
+      </dd><dt class="value">PARAMETER_DECLARATION</dt><dt class="value">PARAMETER_REFERENCE</dt><dt class="value">STATIC_FIELD_DECLARATION</dt><dt class="value">STATIC_GETTER_DECLARATION</dt><dt class="value">STATIC_GETTER_REFERENCE</dt><dt class="value">STATIC_METHOD_DECLARATION</dt><dt class="value">STATIC_METHOD_REFERENCE</dt><dt class="value">STATIC_SETTER_DECLARATION</dt><dt class="value">STATIC_SETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_FUNCTION_DECLARATION</dt><dt class="value">TOP_LEVEL_FUNCTION_REFERENCE</dt><dt class="value">TOP_LEVEL_GETTER_DECLARATION</dt><dt class="value">TOP_LEVEL_GETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_SETTER_DECLARATION</dt><dt class="value">TOP_LEVEL_SETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_VARIABLE_DECLARATION</dt><dt class="value">TYPE_ALIAS</dt><dt class="value">TYPE_NAME_DYNAMIC</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNRESOLVED_INSTANCE_MEMBER_REFERENCE</dt><dt class="value">VALID_STRING_ESCAPE</dt></dl></dd><dt class="typeDefinition"><a name="type_HoverInformation">HoverInformation: object</a></dt><dd>
     <p>
       The hover information associated with a specific location.
     </p>
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 7b20e05..251eafe 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -26,6 +26,139 @@
 
 const jsonEncoder = JsonEncoder.withIndent('    ');
 
+/// A special text edit with an additional change annotation.
+///  @since 3.16.0.
+class AnnotatedTextEdit implements TextEdit, ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(AnnotatedTextEdit.canParse, AnnotatedTextEdit.fromJson);
+
+  AnnotatedTextEdit(
+      {@required this.annotationId,
+      @required this.range,
+      @required this.newText}) {
+    if (annotationId == null) {
+      throw 'annotationId is required but was not provided';
+    }
+    if (range == null) {
+      throw 'range is required but was not provided';
+    }
+    if (newText == null) {
+      throw 'newText is required but was not provided';
+    }
+  }
+  static AnnotatedTextEdit fromJson(Map<String, dynamic> json) {
+    final annotationId = json['annotationId'];
+    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
+    final newText = json['newText'];
+    return AnnotatedTextEdit(
+        annotationId: annotationId, range: range, newText: newText);
+  }
+
+  /// The actual annotation identifier.
+  final String annotationId;
+
+  /// The string to be inserted. For delete operations use an empty string.
+  final String newText;
+
+  /// The range of the text document to be manipulated. To insert text into a
+  /// document create a range where start === end.
+  final Range range;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['annotationId'] =
+        annotationId ?? (throw 'annotationId is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
+    __result['newText'] =
+        newText ?? (throw 'newText is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('annotationId');
+      try {
+        if (!obj.containsKey('annotationId')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['annotationId'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['annotationId'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('range');
+      try {
+        if (!obj.containsKey('range')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['range'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Range.canParse(obj['range'], reporter))) {
+          reporter.reportError('must be of type Range');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('newText');
+      try {
+        if (!obj.containsKey('newText')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['newText'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['newText'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type AnnotatedTextEdit');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is AnnotatedTextEdit && other.runtimeType == AnnotatedTextEdit) {
+      return annotationId == other.annotationId &&
+          range == other.range &&
+          newText == other.newText &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, annotationId.hashCode);
+    hash = JenkinsSmiHash.combine(hash, range.hashCode);
+    hash = JenkinsSmiHash.combine(hash, newText.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class ApplyWorkspaceEditParams implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       ApplyWorkspaceEditParams.canParse, ApplyWorkspaceEditParams.fromJson);
@@ -119,7 +252,8 @@
   static const jsonHandler = LspJsonHandler(
       ApplyWorkspaceEditResponse.canParse, ApplyWorkspaceEditResponse.fromJson);
 
-  ApplyWorkspaceEditResponse({@required this.applied, this.failureReason}) {
+  ApplyWorkspaceEditResponse(
+      {@required this.applied, this.failureReason, this.failedChange}) {
     if (applied == null) {
       throw 'applied is required but was not provided';
     }
@@ -127,16 +261,25 @@
   static ApplyWorkspaceEditResponse fromJson(Map<String, dynamic> json) {
     final applied = json['applied'];
     final failureReason = json['failureReason'];
+    final failedChange = json['failedChange'];
     return ApplyWorkspaceEditResponse(
-        applied: applied, failureReason: failureReason);
+        applied: applied,
+        failureReason: failureReason,
+        failedChange: failedChange);
   }
 
   /// Indicates whether the edit was applied or not.
   final bool applied;
 
+  /// Depending on the client's failure handling strategy `failedChange` might
+  /// contain the index of the change that failed. This property is only
+  /// available if the client signals a `failureHandlingStrategy` in its client
+  /// capabilities.
+  final num failedChange;
+
   /// An optional textual description for why the edit was not applied. This may
-  /// be used may be used by the server for diagnostic logging or to provide a
-  /// suitable error for a request that triggered the edit.
+  /// be used by the server for diagnostic logging or to provide a suitable
+  /// error for a request that triggered the edit.
   final String failureReason;
 
   Map<String, dynamic> toJson() {
@@ -146,6 +289,9 @@
     if (failureReason != null) {
       __result['failureReason'] = failureReason;
     }
+    if (failedChange != null) {
+      __result['failedChange'] = failedChange;
+    }
     return __result;
   }
 
@@ -177,6 +323,15 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('failedChange');
+      try {
+        if (obj['failedChange'] != null && !(obj['failedChange'] is num)) {
+          reporter.reportError('must be of type num');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type ApplyWorkspaceEditResponse');
@@ -190,6 +345,7 @@
         other.runtimeType == ApplyWorkspaceEditResponse) {
       return applied == other.applied &&
           failureReason == other.failureReason &&
+          failedChange == other.failedChange &&
           true;
     }
     return false;
@@ -200,6 +356,1121 @@
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, applied.hashCode);
     hash = JenkinsSmiHash.combine(hash, failureReason.hashCode);
+    hash = JenkinsSmiHash.combine(hash, failedChange.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CallHierarchyClientCapabilities.canParse,
+      CallHierarchyClientCapabilities.fromJson);
+
+  CallHierarchyClientCapabilities({this.dynamicRegistration});
+  static CallHierarchyClientCapabilities fromJson(Map<String, dynamic> json) {
+    final dynamicRegistration = json['dynamicRegistration'];
+    return CallHierarchyClientCapabilities(
+        dynamicRegistration: dynamicRegistration);
+  }
+
+  /// Whether implementation supports dynamic registration. If this is set to
+  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
+  /// StaticRegistrationOptions)` return value for the corresponding server
+  /// capability as well.
+  final bool dynamicRegistration;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (dynamicRegistration != null) {
+      __result['dynamicRegistration'] = dynamicRegistration;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('dynamicRegistration');
+      try {
+        if (obj['dynamicRegistration'] != null &&
+            !(obj['dynamicRegistration'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyClientCapabilities &&
+        other.runtimeType == CallHierarchyClientCapabilities) {
+      return dynamicRegistration == other.dynamicRegistration && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyIncomingCall implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CallHierarchyIncomingCall.canParse, CallHierarchyIncomingCall.fromJson);
+
+  CallHierarchyIncomingCall({@required this.from, @required this.fromRanges}) {
+    if (from == null) {
+      throw 'from is required but was not provided';
+    }
+    if (fromRanges == null) {
+      throw 'fromRanges is required but was not provided';
+    }
+  }
+  static CallHierarchyIncomingCall fromJson(Map<String, dynamic> json) {
+    final from =
+        json['from'] != null ? CallHierarchyItem.fromJson(json['from']) : null;
+    final fromRanges = json['fromRanges']
+        ?.map((item) => item != null ? Range.fromJson(item) : null)
+        ?.cast<Range>()
+        ?.toList();
+    return CallHierarchyIncomingCall(from: from, fromRanges: fromRanges);
+  }
+
+  /// The item that makes the call.
+  final CallHierarchyItem from;
+
+  /// The ranges at which the calls appear. This is relative to the caller
+  /// denoted by [`this.from`](#CallHierarchyIncomingCall.from).
+  final List<Range> fromRanges;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['from'] =
+        from?.toJson() ?? (throw 'from is required but was not set');
+    __result['fromRanges'] =
+        fromRanges ?? (throw 'fromRanges is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('from');
+      try {
+        if (!obj.containsKey('from')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['from'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(CallHierarchyItem.canParse(obj['from'], reporter))) {
+          reporter.reportError('must be of type CallHierarchyItem');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('fromRanges');
+      try {
+        if (!obj.containsKey('fromRanges')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['fromRanges'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['fromRanges'] is List &&
+            (obj['fromRanges']
+                .every((item) => Range.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<Range>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyIncomingCall');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyIncomingCall &&
+        other.runtimeType == CallHierarchyIncomingCall) {
+      return from == other.from &&
+          listEqual(
+              fromRanges, other.fromRanges, (Range a, Range b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, from.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(fromRanges));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyIncomingCallsParams
+    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CallHierarchyIncomingCallsParams.canParse,
+      CallHierarchyIncomingCallsParams.fromJson);
+
+  CallHierarchyIncomingCallsParams(
+      {@required this.item, this.workDoneToken, this.partialResultToken}) {
+    if (item == null) {
+      throw 'item is required but was not provided';
+    }
+  }
+  static CallHierarchyIncomingCallsParams fromJson(Map<String, dynamic> json) {
+    final item =
+        json['item'] != null ? CallHierarchyItem.fromJson(json['item']) : null;
+    final workDoneToken = json['workDoneToken'] is num
+        ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is String
+            ? Either2<num, String>.t2(json['workDoneToken'])
+            : (json['workDoneToken'] == null
+                ? null
+                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+    final partialResultToken = json['partialResultToken'] is num
+        ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is String
+            ? Either2<num, String>.t2(json['partialResultToken'])
+            : (json['partialResultToken'] == null
+                ? null
+                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+    return CallHierarchyIncomingCallsParams(
+        item: item,
+        workDoneToken: workDoneToken,
+        partialResultToken: partialResultToken);
+  }
+
+  final CallHierarchyItem item;
+
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
+  final Either2<num, String> partialResultToken;
+
+  /// An optional token that a server can use to report work done progress.
+  final Either2<num, String> workDoneToken;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['item'] =
+        item?.toJson() ?? (throw 'item is required but was not set');
+    if (workDoneToken != null) {
+      __result['workDoneToken'] = workDoneToken;
+    }
+    if (partialResultToken != null) {
+      __result['partialResultToken'] = partialResultToken;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('item');
+      try {
+        if (!obj.containsKey('item')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['item'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(CallHierarchyItem.canParse(obj['item'], reporter))) {
+          reporter.reportError('must be of type CallHierarchyItem');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneToken');
+      try {
+        if (obj['workDoneToken'] != null &&
+            !((obj['workDoneToken'] is num ||
+                obj['workDoneToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('partialResultToken');
+      try {
+        if (obj['partialResultToken'] != null &&
+            !((obj['partialResultToken'] is num ||
+                obj['partialResultToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyIncomingCallsParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyIncomingCallsParams &&
+        other.runtimeType == CallHierarchyIncomingCallsParams) {
+      return item == other.item &&
+          workDoneToken == other.workDoneToken &&
+          partialResultToken == other.partialResultToken &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, item.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
+    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyItem implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(CallHierarchyItem.canParse, CallHierarchyItem.fromJson);
+
+  CallHierarchyItem(
+      {@required this.name,
+      @required this.kind,
+      this.tags,
+      this.detail,
+      @required this.uri,
+      @required this.range,
+      @required this.selectionRange,
+      this.data}) {
+    if (name == null) {
+      throw 'name is required but was not provided';
+    }
+    if (kind == null) {
+      throw 'kind is required but was not provided';
+    }
+    if (uri == null) {
+      throw 'uri is required but was not provided';
+    }
+    if (range == null) {
+      throw 'range is required but was not provided';
+    }
+    if (selectionRange == null) {
+      throw 'selectionRange is required but was not provided';
+    }
+  }
+  static CallHierarchyItem fromJson(Map<String, dynamic> json) {
+    final name = json['name'];
+    final kind =
+        json['kind'] != null ? SymbolKind.fromJson(json['kind']) : null;
+    final tags = json['tags']
+        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
+        ?.cast<SymbolTag>()
+        ?.toList();
+    final detail = json['detail'];
+    final uri = json['uri'];
+    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
+    final selectionRange = json['selectionRange'] != null
+        ? Range.fromJson(json['selectionRange'])
+        : null;
+    final data = json['data'];
+    return CallHierarchyItem(
+        name: name,
+        kind: kind,
+        tags: tags,
+        detail: detail,
+        uri: uri,
+        range: range,
+        selectionRange: selectionRange,
+        data: data);
+  }
+
+  /// A data entry field that is preserved between a call hierarchy prepare and
+  /// incoming calls or outgoing calls requests.
+  final dynamic data;
+
+  /// More detail for this item, e.g. the signature of a function.
+  final String detail;
+
+  /// The kind of this item.
+  final SymbolKind kind;
+
+  /// The name of this item.
+  final String name;
+
+  /// The range enclosing this symbol not including leading/trailing whitespace
+  /// but everything else, e.g. comments and code.
+  final Range range;
+
+  /// The range that should be selected and revealed when this symbol is being
+  /// picked, e.g. the name of a function. Must be contained by the
+  /// [`range`](#CallHierarchyItem.range).
+  final Range selectionRange;
+
+  /// Tags for this item.
+  final List<SymbolTag> tags;
+
+  /// The resource identifier of this item.
+  final String uri;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['name'] = name ?? (throw 'name is required but was not set');
+    __result['kind'] =
+        kind?.toJson() ?? (throw 'kind is required but was not set');
+    if (tags != null) {
+      __result['tags'] = tags;
+    }
+    if (detail != null) {
+      __result['detail'] = detail;
+    }
+    __result['uri'] = uri ?? (throw 'uri is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
+    __result['selectionRange'] = selectionRange?.toJson() ??
+        (throw 'selectionRange is required but was not set');
+    if (data != null) {
+      __result['data'] = data;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('name');
+      try {
+        if (!obj.containsKey('name')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['name'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['name'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('kind');
+      try {
+        if (!obj.containsKey('kind')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['kind'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(SymbolKind.canParse(obj['kind'], reporter))) {
+          reporter.reportError('must be of type SymbolKind');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('tags');
+      try {
+        if (obj['tags'] != null &&
+            !((obj['tags'] is List &&
+                (obj['tags']
+                    .every((item) => SymbolTag.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<SymbolTag>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('detail');
+      try {
+        if (obj['detail'] != null && !(obj['detail'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('uri');
+      try {
+        if (!obj.containsKey('uri')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['uri'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['uri'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('range');
+      try {
+        if (!obj.containsKey('range')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['range'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Range.canParse(obj['range'], reporter))) {
+          reporter.reportError('must be of type Range');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('selectionRange');
+      try {
+        if (!obj.containsKey('selectionRange')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['selectionRange'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Range.canParse(obj['selectionRange'], reporter))) {
+          reporter.reportError('must be of type Range');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('data');
+      try {
+        if (obj['data'] != null && !(true)) {
+          reporter.reportError('must be of type dynamic');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyItem');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyItem && other.runtimeType == CallHierarchyItem) {
+      return name == other.name &&
+          kind == other.kind &&
+          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
+          detail == other.detail &&
+          uri == other.uri &&
+          range == other.range &&
+          selectionRange == other.selectionRange &&
+          data == other.data &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, name.hashCode);
+    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
+    hash = JenkinsSmiHash.combine(hash, detail.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, range.hashCode);
+    hash = JenkinsSmiHash.combine(hash, selectionRange.hashCode);
+    hash = JenkinsSmiHash.combine(hash, data.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyOptions implements WorkDoneProgressOptions, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CallHierarchyOptions.canParse, CallHierarchyOptions.fromJson);
+
+  CallHierarchyOptions({this.workDoneProgress});
+  static CallHierarchyOptions fromJson(Map<String, dynamic> json) {
+    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyRegistrationOptions.fromJson(json);
+    }
+    final workDoneProgress = json['workDoneProgress'];
+    return CallHierarchyOptions(workDoneProgress: workDoneProgress);
+  }
+
+  final bool workDoneProgress;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (workDoneProgress != null) {
+      __result['workDoneProgress'] = workDoneProgress;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('workDoneProgress');
+      try {
+        if (obj['workDoneProgress'] != null &&
+            !(obj['workDoneProgress'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyOptions &&
+        other.runtimeType == CallHierarchyOptions) {
+      return workDoneProgress == other.workDoneProgress && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyOutgoingCall implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CallHierarchyOutgoingCall.canParse, CallHierarchyOutgoingCall.fromJson);
+
+  CallHierarchyOutgoingCall({@required this.to, @required this.fromRanges}) {
+    if (to == null) {
+      throw 'to is required but was not provided';
+    }
+    if (fromRanges == null) {
+      throw 'fromRanges is required but was not provided';
+    }
+  }
+  static CallHierarchyOutgoingCall fromJson(Map<String, dynamic> json) {
+    final to =
+        json['to'] != null ? CallHierarchyItem.fromJson(json['to']) : null;
+    final fromRanges = json['fromRanges']
+        ?.map((item) => item != null ? Range.fromJson(item) : null)
+        ?.cast<Range>()
+        ?.toList();
+    return CallHierarchyOutgoingCall(to: to, fromRanges: fromRanges);
+  }
+
+  /// The range at which this item is called. This is the range relative to the
+  /// caller, e.g the item passed to `callHierarchy/outgoingCalls` request.
+  final List<Range> fromRanges;
+
+  /// The item that is called.
+  final CallHierarchyItem to;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['to'] = to?.toJson() ?? (throw 'to is required but was not set');
+    __result['fromRanges'] =
+        fromRanges ?? (throw 'fromRanges is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('to');
+      try {
+        if (!obj.containsKey('to')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['to'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(CallHierarchyItem.canParse(obj['to'], reporter))) {
+          reporter.reportError('must be of type CallHierarchyItem');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('fromRanges');
+      try {
+        if (!obj.containsKey('fromRanges')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['fromRanges'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['fromRanges'] is List &&
+            (obj['fromRanges']
+                .every((item) => Range.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<Range>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyOutgoingCall');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyOutgoingCall &&
+        other.runtimeType == CallHierarchyOutgoingCall) {
+      return to == other.to &&
+          listEqual(
+              fromRanges, other.fromRanges, (Range a, Range b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, to.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(fromRanges));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyOutgoingCallsParams
+    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CallHierarchyOutgoingCallsParams.canParse,
+      CallHierarchyOutgoingCallsParams.fromJson);
+
+  CallHierarchyOutgoingCallsParams(
+      {@required this.item, this.workDoneToken, this.partialResultToken}) {
+    if (item == null) {
+      throw 'item is required but was not provided';
+    }
+  }
+  static CallHierarchyOutgoingCallsParams fromJson(Map<String, dynamic> json) {
+    final item =
+        json['item'] != null ? CallHierarchyItem.fromJson(json['item']) : null;
+    final workDoneToken = json['workDoneToken'] is num
+        ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is String
+            ? Either2<num, String>.t2(json['workDoneToken'])
+            : (json['workDoneToken'] == null
+                ? null
+                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+    final partialResultToken = json['partialResultToken'] is num
+        ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is String
+            ? Either2<num, String>.t2(json['partialResultToken'])
+            : (json['partialResultToken'] == null
+                ? null
+                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+    return CallHierarchyOutgoingCallsParams(
+        item: item,
+        workDoneToken: workDoneToken,
+        partialResultToken: partialResultToken);
+  }
+
+  final CallHierarchyItem item;
+
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
+  final Either2<num, String> partialResultToken;
+
+  /// An optional token that a server can use to report work done progress.
+  final Either2<num, String> workDoneToken;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['item'] =
+        item?.toJson() ?? (throw 'item is required but was not set');
+    if (workDoneToken != null) {
+      __result['workDoneToken'] = workDoneToken;
+    }
+    if (partialResultToken != null) {
+      __result['partialResultToken'] = partialResultToken;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('item');
+      try {
+        if (!obj.containsKey('item')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['item'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(CallHierarchyItem.canParse(obj['item'], reporter))) {
+          reporter.reportError('must be of type CallHierarchyItem');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneToken');
+      try {
+        if (obj['workDoneToken'] != null &&
+            !((obj['workDoneToken'] is num ||
+                obj['workDoneToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('partialResultToken');
+      try {
+        if (obj['partialResultToken'] != null &&
+            !((obj['partialResultToken'] is num ||
+                obj['partialResultToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyOutgoingCallsParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyOutgoingCallsParams &&
+        other.runtimeType == CallHierarchyOutgoingCallsParams) {
+      return item == other.item &&
+          workDoneToken == other.workDoneToken &&
+          partialResultToken == other.partialResultToken &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, item.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
+    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyPrepareParams
+    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CallHierarchyPrepareParams.canParse, CallHierarchyPrepareParams.fromJson);
+
+  CallHierarchyPrepareParams(
+      {@required this.textDocument,
+      @required this.position,
+      this.workDoneToken}) {
+    if (textDocument == null) {
+      throw 'textDocument is required but was not provided';
+    }
+    if (position == null) {
+      throw 'position is required but was not provided';
+    }
+  }
+  static CallHierarchyPrepareParams fromJson(Map<String, dynamic> json) {
+    final textDocument = json['textDocument'] != null
+        ? TextDocumentIdentifier.fromJson(json['textDocument'])
+        : null;
+    final position =
+        json['position'] != null ? Position.fromJson(json['position']) : null;
+    final workDoneToken = json['workDoneToken'] is num
+        ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is String
+            ? Either2<num, String>.t2(json['workDoneToken'])
+            : (json['workDoneToken'] == null
+                ? null
+                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+    return CallHierarchyPrepareParams(
+        textDocument: textDocument,
+        position: position,
+        workDoneToken: workDoneToken);
+  }
+
+  /// The position inside the text document.
+  final Position position;
+
+  /// The text document.
+  final TextDocumentIdentifier textDocument;
+
+  /// An optional token that a server can use to report work done progress.
+  final Either2<num, String> workDoneToken;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    __result['position'] =
+        position?.toJson() ?? (throw 'position is required but was not set');
+    if (workDoneToken != null) {
+      __result['workDoneToken'] = workDoneToken;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('textDocument');
+      try {
+        if (!obj.containsKey('textDocument')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['textDocument'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
+          reporter.reportError('must be of type TextDocumentIdentifier');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('position');
+      try {
+        if (!obj.containsKey('position')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['position'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Position.canParse(obj['position'], reporter))) {
+          reporter.reportError('must be of type Position');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneToken');
+      try {
+        if (obj['workDoneToken'] != null &&
+            !((obj['workDoneToken'] is num ||
+                obj['workDoneToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyPrepareParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyPrepareParams &&
+        other.runtimeType == CallHierarchyPrepareParams) {
+      return textDocument == other.textDocument &&
+          position == other.position &&
+          workDoneToken == other.workDoneToken &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
+    hash = JenkinsSmiHash.combine(hash, position.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CallHierarchyRegistrationOptions
+    implements
+        TextDocumentRegistrationOptions,
+        CallHierarchyOptions,
+        StaticRegistrationOptions,
+        ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CallHierarchyRegistrationOptions.canParse,
+      CallHierarchyRegistrationOptions.fromJson);
+
+  CallHierarchyRegistrationOptions(
+      {this.documentSelector, this.workDoneProgress, this.id});
+  static CallHierarchyRegistrationOptions fromJson(Map<String, dynamic> json) {
+    final documentSelector = json['documentSelector']
+        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
+        ?.cast<DocumentFilter>()
+        ?.toList();
+    final workDoneProgress = json['workDoneProgress'];
+    final id = json['id'];
+    return CallHierarchyRegistrationOptions(
+        documentSelector: documentSelector,
+        workDoneProgress: workDoneProgress,
+        id: id);
+  }
+
+  /// A document selector to identify the scope of the registration. If set to
+  /// null the document selector provided on the client side will be used.
+  final List<DocumentFilter> documentSelector;
+
+  /// The id used to register the request. The id can be used to deregister the
+  /// request again. See also Registration#id.
+  final String id;
+  final bool workDoneProgress;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['documentSelector'] = documentSelector;
+    if (workDoneProgress != null) {
+      __result['workDoneProgress'] = workDoneProgress;
+    }
+    if (id != null) {
+      __result['id'] = id;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('documentSelector');
+      try {
+        if (!obj.containsKey('documentSelector')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['documentSelector'] != null &&
+            !((obj['documentSelector'] is List &&
+                (obj['documentSelector'].every(
+                    (item) => DocumentFilter.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<DocumentFilter>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneProgress');
+      try {
+        if (obj['workDoneProgress'] != null &&
+            !(obj['workDoneProgress'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('id');
+      try {
+        if (obj['id'] != null && !(obj['id'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CallHierarchyRegistrationOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CallHierarchyRegistrationOptions &&
+        other.runtimeType == CallHierarchyRegistrationOptions) {
+      return listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
+          workDoneProgress == other.workDoneProgress &&
+          id == other.id &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
+    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -279,12 +1550,131 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// Additional information that describes document changes.
+///  @since 3.16.0
+class ChangeAnnotation implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(ChangeAnnotation.canParse, ChangeAnnotation.fromJson);
+
+  ChangeAnnotation(
+      {@required this.label, this.needsConfirmation, this.description}) {
+    if (label == null) {
+      throw 'label is required but was not provided';
+    }
+  }
+  static ChangeAnnotation fromJson(Map<String, dynamic> json) {
+    final label = json['label'];
+    final needsConfirmation = json['needsConfirmation'];
+    final description = json['description'];
+    return ChangeAnnotation(
+        label: label,
+        needsConfirmation: needsConfirmation,
+        description: description);
+  }
+
+  /// A human-readable string which is rendered less prominent in the user
+  /// interface.
+  final String description;
+
+  /// A human-readable string describing the actual change. The string is
+  /// rendered prominent in the user interface.
+  final String label;
+
+  /// A flag which indicates that user confirmation is needed before applying
+  /// the change.
+  final bool needsConfirmation;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['label'] = label ?? (throw 'label is required but was not set');
+    if (needsConfirmation != null) {
+      __result['needsConfirmation'] = needsConfirmation;
+    }
+    if (description != null) {
+      __result['description'] = description;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('label');
+      try {
+        if (!obj.containsKey('label')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['label'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['label'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('needsConfirmation');
+      try {
+        if (obj['needsConfirmation'] != null &&
+            !(obj['needsConfirmation'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('description');
+      try {
+        if (obj['description'] != null && !(obj['description'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type ChangeAnnotation');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ChangeAnnotation && other.runtimeType == ChangeAnnotation) {
+      return label == other.label &&
+          needsConfirmation == other.needsConfirmation &&
+          description == other.description &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, label.hashCode);
+    hash = JenkinsSmiHash.combine(hash, needsConfirmation.hashCode);
+    hash = JenkinsSmiHash.combine(hash, description.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class ClientCapabilities implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(ClientCapabilities.canParse, ClientCapabilities.fromJson);
 
   ClientCapabilities(
-      {this.workspace, this.textDocument, this.window, this.experimental});
+      {this.workspace,
+      this.textDocument,
+      this.window,
+      this.general,
+      this.experimental});
   static ClientCapabilities fromJson(Map<String, dynamic> json) {
     final workspace = json['workspace'] != null
         ? ClientCapabilitiesWorkspace.fromJson(json['workspace'])
@@ -295,17 +1685,25 @@
     final window = json['window'] != null
         ? ClientCapabilitiesWindow.fromJson(json['window'])
         : null;
+    final general = json['general'] != null
+        ? ClientCapabilitiesGeneral.fromJson(json['general'])
+        : null;
     final experimental = json['experimental'];
     return ClientCapabilities(
         workspace: workspace,
         textDocument: textDocument,
         window: window,
+        general: general,
         experimental: experimental);
   }
 
   /// Experimental client capabilities.
   final dynamic experimental;
 
+  /// General client capabilities.
+  ///  @since 3.16.0
+  final ClientCapabilitiesGeneral general;
+
   /// Text document specific client capabilities.
   final TextDocumentClientCapabilities textDocument;
 
@@ -326,6 +1724,9 @@
     if (window != null) {
       __result['window'] = window.toJson();
     }
+    if (general != null) {
+      __result['general'] = general.toJson();
+    }
     if (experimental != null) {
       __result['experimental'] = experimental;
     }
@@ -367,6 +1768,16 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('general');
+      try {
+        if (obj['general'] != null &&
+            !(ClientCapabilitiesGeneral.canParse(obj['general'], reporter))) {
+          reporter.reportError('must be of type ClientCapabilitiesGeneral');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('experimental');
       try {
         if (obj['experimental'] != null && !(true)) {
@@ -390,6 +1801,7 @@
       return workspace == other.workspace &&
           textDocument == other.textDocument &&
           window == other.window &&
+          general == other.general &&
           experimental == other.experimental &&
           true;
     }
@@ -402,6 +1814,7 @@
     hash = JenkinsSmiHash.combine(hash, workspace.hashCode);
     hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
     hash = JenkinsSmiHash.combine(hash, window.hashCode);
+    hash = JenkinsSmiHash.combine(hash, general.hashCode);
     hash = JenkinsSmiHash.combine(hash, experimental.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
@@ -410,21 +1823,313 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class ClientCapabilitiesFileOperations implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      ClientCapabilitiesFileOperations.canParse,
+      ClientCapabilitiesFileOperations.fromJson);
+
+  ClientCapabilitiesFileOperations(
+      {this.dynamicRegistration,
+      this.didCreate,
+      this.willCreate,
+      this.didRename,
+      this.willRename,
+      this.didDelete,
+      this.willDelete});
+  static ClientCapabilitiesFileOperations fromJson(Map<String, dynamic> json) {
+    final dynamicRegistration = json['dynamicRegistration'];
+    final didCreate = json['didCreate'];
+    final willCreate = json['willCreate'];
+    final didRename = json['didRename'];
+    final willRename = json['willRename'];
+    final didDelete = json['didDelete'];
+    final willDelete = json['willDelete'];
+    return ClientCapabilitiesFileOperations(
+        dynamicRegistration: dynamicRegistration,
+        didCreate: didCreate,
+        willCreate: willCreate,
+        didRename: didRename,
+        willRename: willRename,
+        didDelete: didDelete,
+        willDelete: willDelete);
+  }
+
+  /// The client has support for sending didCreateFiles notifications.
+  final bool didCreate;
+
+  /// The client has support for sending didDeleteFiles notifications.
+  final bool didDelete;
+
+  /// The client has support for sending didRenameFiles notifications.
+  final bool didRename;
+
+  /// Whether the client supports dynamic registration for file
+  /// requests/notifications.
+  final bool dynamicRegistration;
+
+  /// The client has support for sending willCreateFiles requests.
+  final bool willCreate;
+
+  /// The client has support for sending willDeleteFiles requests.
+  final bool willDelete;
+
+  /// The client has support for sending willRenameFiles requests.
+  final bool willRename;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (dynamicRegistration != null) {
+      __result['dynamicRegistration'] = dynamicRegistration;
+    }
+    if (didCreate != null) {
+      __result['didCreate'] = didCreate;
+    }
+    if (willCreate != null) {
+      __result['willCreate'] = willCreate;
+    }
+    if (didRename != null) {
+      __result['didRename'] = didRename;
+    }
+    if (willRename != null) {
+      __result['willRename'] = willRename;
+    }
+    if (didDelete != null) {
+      __result['didDelete'] = didDelete;
+    }
+    if (willDelete != null) {
+      __result['willDelete'] = willDelete;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('dynamicRegistration');
+      try {
+        if (obj['dynamicRegistration'] != null &&
+            !(obj['dynamicRegistration'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('didCreate');
+      try {
+        if (obj['didCreate'] != null && !(obj['didCreate'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('willCreate');
+      try {
+        if (obj['willCreate'] != null && !(obj['willCreate'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('didRename');
+      try {
+        if (obj['didRename'] != null && !(obj['didRename'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('willRename');
+      try {
+        if (obj['willRename'] != null && !(obj['willRename'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('didDelete');
+      try {
+        if (obj['didDelete'] != null && !(obj['didDelete'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('willDelete');
+      try {
+        if (obj['willDelete'] != null && !(obj['willDelete'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type ClientCapabilitiesFileOperations');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ClientCapabilitiesFileOperations &&
+        other.runtimeType == ClientCapabilitiesFileOperations) {
+      return dynamicRegistration == other.dynamicRegistration &&
+          didCreate == other.didCreate &&
+          willCreate == other.willCreate &&
+          didRename == other.didRename &&
+          willRename == other.willRename &&
+          didDelete == other.didDelete &&
+          willDelete == other.willDelete &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
+    hash = JenkinsSmiHash.combine(hash, didCreate.hashCode);
+    hash = JenkinsSmiHash.combine(hash, willCreate.hashCode);
+    hash = JenkinsSmiHash.combine(hash, didRename.hashCode);
+    hash = JenkinsSmiHash.combine(hash, willRename.hashCode);
+    hash = JenkinsSmiHash.combine(hash, didDelete.hashCode);
+    hash = JenkinsSmiHash.combine(hash, willDelete.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class ClientCapabilitiesGeneral implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      ClientCapabilitiesGeneral.canParse, ClientCapabilitiesGeneral.fromJson);
+
+  ClientCapabilitiesGeneral({this.regularExpressions, this.markdown});
+  static ClientCapabilitiesGeneral fromJson(Map<String, dynamic> json) {
+    final regularExpressions = json['regularExpressions'] != null
+        ? RegularExpressionsClientCapabilities.fromJson(
+            json['regularExpressions'])
+        : null;
+    final markdown = json['markdown'] != null
+        ? MarkdownClientCapabilities.fromJson(json['markdown'])
+        : null;
+    return ClientCapabilitiesGeneral(
+        regularExpressions: regularExpressions, markdown: markdown);
+  }
+
+  /// Client capabilities specific to the client's markdown parser.
+  ///  @since 3.16.0
+  final MarkdownClientCapabilities markdown;
+
+  /// Client capabilities specific to regular expressions.
+  ///  @since 3.16.0
+  final RegularExpressionsClientCapabilities regularExpressions;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (regularExpressions != null) {
+      __result['regularExpressions'] = regularExpressions.toJson();
+    }
+    if (markdown != null) {
+      __result['markdown'] = markdown.toJson();
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('regularExpressions');
+      try {
+        if (obj['regularExpressions'] != null &&
+            !(RegularExpressionsClientCapabilities.canParse(
+                obj['regularExpressions'], reporter))) {
+          reporter.reportError(
+              'must be of type RegularExpressionsClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('markdown');
+      try {
+        if (obj['markdown'] != null &&
+            !(MarkdownClientCapabilities.canParse(obj['markdown'], reporter))) {
+          reporter.reportError('must be of type MarkdownClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type ClientCapabilitiesGeneral');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ClientCapabilitiesGeneral &&
+        other.runtimeType == ClientCapabilitiesGeneral) {
+      return regularExpressions == other.regularExpressions &&
+          markdown == other.markdown &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, regularExpressions.hashCode);
+    hash = JenkinsSmiHash.combine(hash, markdown.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class ClientCapabilitiesWindow implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       ClientCapabilitiesWindow.canParse, ClientCapabilitiesWindow.fromJson);
 
-  ClientCapabilitiesWindow({this.workDoneProgress});
+  ClientCapabilitiesWindow(
+      {this.workDoneProgress, this.showMessage, this.showDocument});
   static ClientCapabilitiesWindow fromJson(Map<String, dynamic> json) {
     final workDoneProgress = json['workDoneProgress'];
-    return ClientCapabilitiesWindow(workDoneProgress: workDoneProgress);
+    final showMessage = json['showMessage'] != null
+        ? ShowMessageRequestClientCapabilities.fromJson(json['showMessage'])
+        : null;
+    final showDocument = json['showDocument'] != null
+        ? ShowDocumentClientCapabilities.fromJson(json['showDocument'])
+        : null;
+    return ClientCapabilitiesWindow(
+        workDoneProgress: workDoneProgress,
+        showMessage: showMessage,
+        showDocument: showDocument);
   }
 
-  /// Whether client supports handling progress notifications. If set, servers
+  /// Client capabilities for the show document request.
+  ///  @since 3.16.0
+  final ShowDocumentClientCapabilities showDocument;
+
+  /// Capabilities specific to the showMessage request
+  ///  @since 3.16.0
+  final ShowMessageRequestClientCapabilities showMessage;
+
+  /// Whether client supports handling progress notifications. If set servers
   /// are allowed to report in `workDoneProgress` property in the request
   /// specific server capabilities.
-  ///
-  /// Since 3.15.0
+  ///  @since 3.15.0
   final bool workDoneProgress;
 
   Map<String, dynamic> toJson() {
@@ -432,6 +2137,12 @@
     if (workDoneProgress != null) {
       __result['workDoneProgress'] = workDoneProgress;
     }
+    if (showMessage != null) {
+      __result['showMessage'] = showMessage.toJson();
+    }
+    if (showDocument != null) {
+      __result['showDocument'] = showDocument.toJson();
+    }
     return __result;
   }
 
@@ -447,6 +2158,30 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('showMessage');
+      try {
+        if (obj['showMessage'] != null &&
+            !(ShowMessageRequestClientCapabilities.canParse(
+                obj['showMessage'], reporter))) {
+          reporter.reportError(
+              'must be of type ShowMessageRequestClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('showDocument');
+      try {
+        if (obj['showDocument'] != null &&
+            !(ShowDocumentClientCapabilities.canParse(
+                obj['showDocument'], reporter))) {
+          reporter
+              .reportError('must be of type ShowDocumentClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type ClientCapabilitiesWindow');
@@ -458,7 +2193,10 @@
   bool operator ==(Object other) {
     if (other is ClientCapabilitiesWindow &&
         other.runtimeType == ClientCapabilitiesWindow) {
-      return workDoneProgress == other.workDoneProgress && true;
+      return workDoneProgress == other.workDoneProgress &&
+          showMessage == other.showMessage &&
+          showDocument == other.showDocument &&
+          true;
     }
     return false;
   }
@@ -467,6 +2205,8 @@
   int get hashCode {
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    hash = JenkinsSmiHash.combine(hash, showMessage.hashCode);
+    hash = JenkinsSmiHash.combine(hash, showDocument.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -487,7 +2227,10 @@
       this.symbol,
       this.executeCommand,
       this.workspaceFolders,
-      this.configuration});
+      this.configuration,
+      this.semanticTokens,
+      this.codeLens,
+      this.fileOperations});
   static ClientCapabilitiesWorkspace fromJson(Map<String, dynamic> json) {
     final applyEdit = json['applyEdit'];
     final workspaceEdit = json['workspaceEdit'] != null
@@ -509,6 +2252,16 @@
         : null;
     final workspaceFolders = json['workspaceFolders'];
     final configuration = json['configuration'];
+    final semanticTokens = json['semanticTokens'] != null
+        ? SemanticTokensWorkspaceClientCapabilities.fromJson(
+            json['semanticTokens'])
+        : null;
+    final codeLens = json['codeLens'] != null
+        ? CodeLensWorkspaceClientCapabilities.fromJson(json['codeLens'])
+        : null;
+    final fileOperations = json['fileOperations'] != null
+        ? ClientCapabilitiesFileOperations.fromJson(json['fileOperations'])
+        : null;
     return ClientCapabilitiesWorkspace(
         applyEdit: applyEdit,
         workspaceEdit: workspaceEdit,
@@ -517,16 +2270,22 @@
         symbol: symbol,
         executeCommand: executeCommand,
         workspaceFolders: workspaceFolders,
-        configuration: configuration);
+        configuration: configuration,
+        semanticTokens: semanticTokens,
+        codeLens: codeLens,
+        fileOperations: fileOperations);
   }
 
   /// The client supports applying batch edits to the workspace by supporting
   /// the request 'workspace/applyEdit'
   final bool applyEdit;
 
+  /// Capabilities specific to the code lens requests scoped to the workspace.
+  ///  @since 3.16.0
+  final CodeLensWorkspaceClientCapabilities codeLens;
+
   /// The client supports `workspace/configuration` requests.
-  ///
-  /// Since 3.6.0
+  ///  @since 3.6.0
   final bool configuration;
 
   /// Capabilities specific to the `workspace/didChangeConfiguration`
@@ -540,6 +2299,15 @@
   /// Capabilities specific to the `workspace/executeCommand` request.
   final ExecuteCommandClientCapabilities executeCommand;
 
+  /// The client has support for file requests/notifications.
+  ///  @since 3.16.0
+  final ClientCapabilitiesFileOperations fileOperations;
+
+  /// Capabilities specific to the semantic token requests scoped to the
+  /// workspace.
+  ///  @since 3.16.0
+  final SemanticTokensWorkspaceClientCapabilities semanticTokens;
+
   /// Capabilities specific to the `workspace/symbol` request.
   final WorkspaceSymbolClientCapabilities symbol;
 
@@ -547,8 +2315,7 @@
   final WorkspaceEditClientCapabilities workspaceEdit;
 
   /// The client has support for workspace folders.
-  ///
-  /// Since 3.6.0
+  ///  @since 3.6.0
   final bool workspaceFolders;
 
   Map<String, dynamic> toJson() {
@@ -577,6 +2344,15 @@
     if (configuration != null) {
       __result['configuration'] = configuration;
     }
+    if (semanticTokens != null) {
+      __result['semanticTokens'] = semanticTokens.toJson();
+    }
+    if (codeLens != null) {
+      __result['codeLens'] = codeLens.toJson();
+    }
+    if (fileOperations != null) {
+      __result['fileOperations'] = fileOperations.toJson();
+    }
     return __result;
   }
 
@@ -670,6 +2446,42 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('semanticTokens');
+      try {
+        if (obj['semanticTokens'] != null &&
+            !(SemanticTokensWorkspaceClientCapabilities.canParse(
+                obj['semanticTokens'], reporter))) {
+          reporter.reportError(
+              'must be of type SemanticTokensWorkspaceClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('codeLens');
+      try {
+        if (obj['codeLens'] != null &&
+            !(CodeLensWorkspaceClientCapabilities.canParse(
+                obj['codeLens'], reporter))) {
+          reporter.reportError(
+              'must be of type CodeLensWorkspaceClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('fileOperations');
+      try {
+        if (obj['fileOperations'] != null &&
+            !(ClientCapabilitiesFileOperations.canParse(
+                obj['fileOperations'], reporter))) {
+          reporter
+              .reportError('must be of type ClientCapabilitiesFileOperations');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type ClientCapabilitiesWorkspace');
@@ -689,6 +2501,9 @@
           executeCommand == other.executeCommand &&
           workspaceFolders == other.workspaceFolders &&
           configuration == other.configuration &&
+          semanticTokens == other.semanticTokens &&
+          codeLens == other.codeLens &&
+          fileOperations == other.fileOperations &&
           true;
     }
     return false;
@@ -705,6 +2520,9 @@
     hash = JenkinsSmiHash.combine(hash, executeCommand.hashCode);
     hash = JenkinsSmiHash.combine(hash, workspaceFolders.hashCode);
     hash = JenkinsSmiHash.combine(hash, configuration.hashCode);
+    hash = JenkinsSmiHash.combine(hash, semanticTokens.hashCode);
+    hash = JenkinsSmiHash.combine(hash, codeLens.hashCode);
+    hash = JenkinsSmiHash.combine(hash, fileOperations.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -712,8 +2530,8 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
-/// A code action represents a change that can be performed in code. For
-/// example, to fix a problem or to refactor code.
+/// A code action represents a change that can be performed in code, e.g. to fix
+/// a problem or to refactor code.
 ///
 /// A CodeAction must set either `edit` and/or a `command`. If both are
 /// supplied, the `edit` is applied first, then the `command` is executed.
@@ -726,8 +2544,10 @@
       this.kind,
       this.diagnostics,
       this.isPreferred,
+      this.disabled,
       this.edit,
-      this.command}) {
+      this.command,
+      this.data}) {
     if (title == null) {
       throw 'title is required but was not provided';
     }
@@ -741,26 +2561,55 @@
         ?.cast<Diagnostic>()
         ?.toList();
     final isPreferred = json['isPreferred'];
+    final disabled = json['disabled'] != null
+        ? CodeActionDisabled.fromJson(json['disabled'])
+        : null;
     final edit =
         json['edit'] != null ? WorkspaceEdit.fromJson(json['edit']) : null;
     final command =
         json['command'] != null ? Command.fromJson(json['command']) : null;
+    final data = json['data'];
     return CodeAction(
         title: title,
         kind: kind,
         diagnostics: diagnostics,
         isPreferred: isPreferred,
+        disabled: disabled,
         edit: edit,
-        command: command);
+        command: command,
+        data: data);
   }
 
   /// A command this code action executes. If a code action provides an edit and
   /// a command, first the edit is executed and then the command.
   final Command command;
 
+  /// A data entry field that is preserved on a code action between a
+  /// `textDocument/codeAction` and a `codeAction/resolve` request.
+  ///  @since 3.16.0
+  final dynamic data;
+
   /// The diagnostics that this code action resolves.
   final List<Diagnostic> diagnostics;
 
+  /// Marks that the code action cannot currently be applied.
+  ///
+  /// Clients should follow the following guidelines regarding disabled code
+  /// actions:
+  ///
+  /// - Disabled code actions are not shown in automatic lightbulbs code
+  ///   action menus.
+  ///
+  /// - Disabled actions are shown as faded out in the code action menu when
+  ///   the user request a more specific type of code action, such as
+  ///   refactorings.
+  ///
+  /// - If the user has a keybinding that auto applies a code action and only
+  ///   a disabled code actions are returned, the client should show the user
+  ///   an error message with `reason` in the editor.
+  ///  @since 3.16.0
+  final CodeActionDisabled disabled;
+
   /// The workspace edit this code action performs.
   final WorkspaceEdit edit;
 
@@ -793,12 +2642,18 @@
     if (isPreferred != null) {
       __result['isPreferred'] = isPreferred;
     }
+    if (disabled != null) {
+      __result['disabled'] = disabled.toJson();
+    }
     if (edit != null) {
       __result['edit'] = edit.toJson();
     }
     if (command != null) {
       __result['command'] = command.toJson();
     }
+    if (data != null) {
+      __result['data'] = data;
+    }
     return __result;
   }
 
@@ -852,6 +2707,16 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('disabled');
+      try {
+        if (obj['disabled'] != null &&
+            !(CodeActionDisabled.canParse(obj['disabled'], reporter))) {
+          reporter.reportError('must be of type CodeActionDisabled');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('edit');
       try {
         if (obj['edit'] != null &&
@@ -872,6 +2737,15 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('data');
+      try {
+        if (obj['data'] != null && !(true)) {
+          reporter.reportError('must be of type dynamic');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type CodeAction');
@@ -887,8 +2761,10 @@
           listEqual(diagnostics, other.diagnostics,
               (Diagnostic a, Diagnostic b) => a == b) &&
           isPreferred == other.isPreferred &&
+          disabled == other.disabled &&
           edit == other.edit &&
           command == other.command &&
+          data == other.data &&
           true;
     }
     return false;
@@ -901,8 +2777,10 @@
     hash = JenkinsSmiHash.combine(hash, kind.hashCode);
     hash = JenkinsSmiHash.combine(hash, lspHashCode(diagnostics));
     hash = JenkinsSmiHash.combine(hash, isPreferred.hashCode);
+    hash = JenkinsSmiHash.combine(hash, disabled.hashCode);
     hash = JenkinsSmiHash.combine(hash, edit.hashCode);
     hash = JenkinsSmiHash.combine(hash, command.hashCode);
+    hash = JenkinsSmiHash.combine(hash, data.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -918,7 +2796,11 @@
   CodeActionClientCapabilities(
       {this.dynamicRegistration,
       this.codeActionLiteralSupport,
-      this.isPreferredSupport});
+      this.isPreferredSupport,
+      this.disabledSupport,
+      this.dataSupport,
+      this.resolveSupport,
+      this.honorsChangeAnnotations});
   static CodeActionClientCapabilities fromJson(Map<String, dynamic> json) {
     final dynamicRegistration = json['dynamicRegistration'];
     final codeActionLiteralSupport = json['codeActionLiteralSupport'] != null
@@ -926,10 +2808,21 @@
             json['codeActionLiteralSupport'])
         : null;
     final isPreferredSupport = json['isPreferredSupport'];
+    final disabledSupport = json['disabledSupport'];
+    final dataSupport = json['dataSupport'];
+    final resolveSupport = json['resolveSupport'] != null
+        ? CodeActionClientCapabilitiesResolveSupport.fromJson(
+            json['resolveSupport'])
+        : null;
+    final honorsChangeAnnotations = json['honorsChangeAnnotations'];
     return CodeActionClientCapabilities(
         dynamicRegistration: dynamicRegistration,
         codeActionLiteralSupport: codeActionLiteralSupport,
-        isPreferredSupport: isPreferredSupport);
+        isPreferredSupport: isPreferredSupport,
+        disabledSupport: disabledSupport,
+        dataSupport: dataSupport,
+        resolveSupport: resolveSupport,
+        honorsChangeAnnotations: honorsChangeAnnotations);
   }
 
   /// The client supports code action literals as a valid response of the
@@ -938,12 +2831,34 @@
   final CodeActionClientCapabilitiesCodeActionLiteralSupport
       codeActionLiteralSupport;
 
+  /// Whether code action supports the `data` property which is preserved
+  /// between a `textDocument/codeAction` and a `codeAction/resolve` request.
+  ///  @since 3.16.0
+  final bool dataSupport;
+
+  /// Whether code action supports the `disabled` property.
+  ///  @since 3.16.0
+  final bool disabledSupport;
+
   /// Whether code action supports dynamic registration.
   final bool dynamicRegistration;
 
-  /// Whether code action supports the `isPreferred` property. @since 3.15.0
+  /// Whether th client honors the change annotations in text edits and resource
+  /// operations returned via the `CodeAction#edit` property by for example
+  /// presenting the workspace edit in the user interface and asking for
+  /// confirmation.
+  ///  @since 3.16.0
+  final bool honorsChangeAnnotations;
+
+  /// Whether code action supports the `isPreferred` property.
+  ///  @since 3.15.0
   final bool isPreferredSupport;
 
+  /// Whether the client supports resolving additional code action properties
+  /// via a separate `codeAction/resolve` request.
+  ///  @since 3.16.0
+  final CodeActionClientCapabilitiesResolveSupport resolveSupport;
+
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (dynamicRegistration != null) {
@@ -955,6 +2870,18 @@
     if (isPreferredSupport != null) {
       __result['isPreferredSupport'] = isPreferredSupport;
     }
+    if (disabledSupport != null) {
+      __result['disabledSupport'] = disabledSupport;
+    }
+    if (dataSupport != null) {
+      __result['dataSupport'] = dataSupport;
+    }
+    if (resolveSupport != null) {
+      __result['resolveSupport'] = resolveSupport.toJson();
+    }
+    if (honorsChangeAnnotations != null) {
+      __result['honorsChangeAnnotations'] = honorsChangeAnnotations;
+    }
     return __result;
   }
 
@@ -992,6 +2919,47 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('disabledSupport');
+      try {
+        if (obj['disabledSupport'] != null &&
+            !(obj['disabledSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('dataSupport');
+      try {
+        if (obj['dataSupport'] != null && !(obj['dataSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('resolveSupport');
+      try {
+        if (obj['resolveSupport'] != null &&
+            !(CodeActionClientCapabilitiesResolveSupport.canParse(
+                obj['resolveSupport'], reporter))) {
+          reporter.reportError(
+              'must be of type CodeActionClientCapabilitiesResolveSupport');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('honorsChangeAnnotations');
+      try {
+        if (obj['honorsChangeAnnotations'] != null &&
+            !(obj['honorsChangeAnnotations'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type CodeActionClientCapabilities');
@@ -1006,6 +2974,10 @@
       return dynamicRegistration == other.dynamicRegistration &&
           codeActionLiteralSupport == other.codeActionLiteralSupport &&
           isPreferredSupport == other.isPreferredSupport &&
+          disabledSupport == other.disabledSupport &&
+          dataSupport == other.dataSupport &&
+          resolveSupport == other.resolveSupport &&
+          honorsChangeAnnotations == other.honorsChangeAnnotations &&
           true;
     }
     return false;
@@ -1017,6 +2989,10 @@
     hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
     hash = JenkinsSmiHash.combine(hash, codeActionLiteralSupport.hashCode);
     hash = JenkinsSmiHash.combine(hash, isPreferredSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, disabledSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, dataSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, resolveSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, honorsChangeAnnotations.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -1188,6 +3164,83 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class CodeActionClientCapabilitiesResolveSupport implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CodeActionClientCapabilitiesResolveSupport.canParse,
+      CodeActionClientCapabilitiesResolveSupport.fromJson);
+
+  CodeActionClientCapabilitiesResolveSupport({@required this.properties}) {
+    if (properties == null) {
+      throw 'properties is required but was not provided';
+    }
+  }
+  static CodeActionClientCapabilitiesResolveSupport fromJson(
+      Map<String, dynamic> json) {
+    final properties =
+        json['properties']?.map((item) => item)?.cast<String>()?.toList();
+    return CodeActionClientCapabilitiesResolveSupport(properties: properties);
+  }
+
+  /// The properties that a client can resolve lazily.
+  final List<String> properties;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['properties'] =
+        properties ?? (throw 'properties is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('properties');
+      try {
+        if (!obj.containsKey('properties')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['properties'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['properties'] is List &&
+            (obj['properties'].every((item) => item is String))))) {
+          reporter.reportError('must be of type List<String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type CodeActionClientCapabilitiesResolveSupport');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CodeActionClientCapabilitiesResolveSupport &&
+        other.runtimeType == CodeActionClientCapabilitiesResolveSupport) {
+      return listEqual(
+              properties, other.properties, (String a, String b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(properties));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 /// Contains additional diagnostic information about the context in which a code
 /// action is run.
 class CodeActionContext implements ToJsonable {
@@ -1222,7 +3275,7 @@
   /// Requested kind of actions to return.
   ///
   /// Actions not of this kind are filtered out by the client before being
-  /// shown, so servers can omit computing them.
+  /// shown. So servers can omit computing them.
   final List<CodeActionKind> only;
 
   Map<String, dynamic> toJson() {
@@ -1299,6 +3352,77 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class CodeActionDisabled implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(CodeActionDisabled.canParse, CodeActionDisabled.fromJson);
+
+  CodeActionDisabled({@required this.reason}) {
+    if (reason == null) {
+      throw 'reason is required but was not provided';
+    }
+  }
+  static CodeActionDisabled fromJson(Map<String, dynamic> json) {
+    final reason = json['reason'];
+    return CodeActionDisabled(reason: reason);
+  }
+
+  /// Human readable description of why the code action is currently disabled.
+  ///
+  /// This is displayed in the code actions UI.
+  final String reason;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['reason'] = reason ?? (throw 'reason is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('reason');
+      try {
+        if (!obj.containsKey('reason')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['reason'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['reason'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CodeActionDisabled');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CodeActionDisabled &&
+        other.runtimeType == CodeActionDisabled) {
+      return reason == other.reason && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, reason.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 /// A set of predefined code action kinds.
 class CodeActionKind {
   const CodeActionKind(this._value);
@@ -1357,7 +3481,7 @@
   /// Source code actions apply to the entire file.
   static const Source = CodeActionKind('source');
 
-  /// Base kind for an organize imports source action `source.organizeImports`.
+  /// Base kind for an organize imports source action: `source.organizeImports`.
   static const SourceOrganizeImports = CodeActionKind('source.organizeImports');
 
   Object toJson() => _value;
@@ -1375,7 +3499,8 @@
   static const jsonHandler =
       LspJsonHandler(CodeActionOptions.canParse, CodeActionOptions.fromJson);
 
-  CodeActionOptions({this.codeActionKinds, this.workDoneProgress});
+  CodeActionOptions(
+      {this.codeActionKinds, this.resolveProvider, this.workDoneProgress});
   static CodeActionOptions fromJson(Map<String, dynamic> json) {
     if (CodeActionRegistrationOptions.canParse(json, nullLspJsonReporter)) {
       return CodeActionRegistrationOptions.fromJson(json);
@@ -1384,9 +3509,12 @@
         ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null)
         ?.cast<CodeActionKind>()
         ?.toList();
+    final resolveProvider = json['resolveProvider'];
     final workDoneProgress = json['workDoneProgress'];
     return CodeActionOptions(
-        codeActionKinds: codeActionKinds, workDoneProgress: workDoneProgress);
+        codeActionKinds: codeActionKinds,
+        resolveProvider: resolveProvider,
+        workDoneProgress: workDoneProgress);
   }
 
   /// CodeActionKinds that this server may return.
@@ -1394,6 +3522,11 @@
   /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or
   /// the server may list out every specific kind they provide.
   final List<CodeActionKind> codeActionKinds;
+
+  /// The server provides support to resolve additional information for a code
+  /// action.
+  ///  @since 3.16.0
+  final bool resolveProvider;
   final bool workDoneProgress;
 
   Map<String, dynamic> toJson() {
@@ -1401,6 +3534,9 @@
     if (codeActionKinds != null) {
       __result['codeActionKinds'] = codeActionKinds;
     }
+    if (resolveProvider != null) {
+      __result['resolveProvider'] = resolveProvider;
+    }
     if (workDoneProgress != null) {
       __result['workDoneProgress'] = workDoneProgress;
     }
@@ -1421,6 +3557,16 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('resolveProvider');
+      try {
+        if (obj['resolveProvider'] != null &&
+            !(obj['resolveProvider'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('workDoneProgress');
       try {
         if (obj['workDoneProgress'] != null &&
@@ -1443,6 +3589,7 @@
     if (other is CodeActionOptions && other.runtimeType == CodeActionOptions) {
       return listEqual(codeActionKinds, other.codeActionKinds,
               (CodeActionKind a, CodeActionKind b) => a == b) &&
+          resolveProvider == other.resolveProvider &&
           workDoneProgress == other.workDoneProgress &&
           true;
     }
@@ -1453,6 +3600,7 @@
   int get hashCode {
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, lspHashCode(codeActionKinds));
+    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
@@ -1516,8 +3664,8 @@
   /// Context carrying additional information.
   final CodeActionContext context;
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The range for which the command was invoked.
@@ -1663,7 +3811,10 @@
       CodeActionRegistrationOptions.fromJson);
 
   CodeActionRegistrationOptions(
-      {this.documentSelector, this.codeActionKinds, this.workDoneProgress});
+      {this.documentSelector,
+      this.codeActionKinds,
+      this.resolveProvider,
+      this.workDoneProgress});
   static CodeActionRegistrationOptions fromJson(Map<String, dynamic> json) {
     final documentSelector = json['documentSelector']
         ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
@@ -1673,10 +3824,12 @@
         ?.map((item) => item != null ? CodeActionKind.fromJson(item) : null)
         ?.cast<CodeActionKind>()
         ?.toList();
+    final resolveProvider = json['resolveProvider'];
     final workDoneProgress = json['workDoneProgress'];
     return CodeActionRegistrationOptions(
         documentSelector: documentSelector,
         codeActionKinds: codeActionKinds,
+        resolveProvider: resolveProvider,
         workDoneProgress: workDoneProgress);
   }
 
@@ -1687,8 +3840,13 @@
   final List<CodeActionKind> codeActionKinds;
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
+
+  /// The server provides support to resolve additional information for a code
+  /// action.
+  ///  @since 3.16.0
+  final bool resolveProvider;
   final bool workDoneProgress;
 
   Map<String, dynamic> toJson() {
@@ -1697,6 +3855,9 @@
     if (codeActionKinds != null) {
       __result['codeActionKinds'] = codeActionKinds;
     }
+    if (resolveProvider != null) {
+      __result['resolveProvider'] = resolveProvider;
+    }
     if (workDoneProgress != null) {
       __result['workDoneProgress'] = workDoneProgress;
     }
@@ -1733,6 +3894,16 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('resolveProvider');
+      try {
+        if (obj['resolveProvider'] != null &&
+            !(obj['resolveProvider'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('workDoneProgress');
       try {
         if (obj['workDoneProgress'] != null &&
@@ -1758,6 +3929,7 @@
               (DocumentFilter a, DocumentFilter b) => a == b) &&
           listEqual(codeActionKinds, other.codeActionKinds,
               (CodeActionKind a, CodeActionKind b) => a == b) &&
+          resolveProvider == other.resolveProvider &&
           workDoneProgress == other.workDoneProgress &&
           true;
     }
@@ -1769,6 +3941,7 @@
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
     hash = JenkinsSmiHash.combine(hash, lspHashCode(codeActionKinds));
+    hash = JenkinsSmiHash.combine(hash, resolveProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
@@ -1777,11 +3950,81 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
-/// A CodeLense represents a command that should be shown along with source
+/// Structure to capture a description for an error code.
+///  @since 3.16.0
+class CodeDescription implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(CodeDescription.canParse, CodeDescription.fromJson);
+
+  CodeDescription({@required this.href}) {
+    if (href == null) {
+      throw 'href is required but was not provided';
+    }
+  }
+  static CodeDescription fromJson(Map<String, dynamic> json) {
+    final href = json['href'];
+    return CodeDescription(href: href);
+  }
+
+  /// An URI to open with more information about the diagnostic error.
+  final String href;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['href'] = href ?? (throw 'href is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('href');
+      try {
+        if (!obj.containsKey('href')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['href'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['href'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CodeDescription');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CodeDescription && other.runtimeType == CodeDescription) {
+      return href == other.href && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, href.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// A code lens represents a command that should be shown along with source
 /// text, like the number of references, a way to run tests, etc.
 ///
-/// A CodeLens is _unresolved_ when no command is associated to it. For
-/// performance reasons, the creation of a CodeLens and resolving should be done
+/// A code lens is _unresolved_ when no command is associated to it. For
+/// performance reasons the creation of a code lens and resolving should be done
 /// in two stages.
 class CodeLens implements ToJsonable {
   static const jsonHandler =
@@ -1800,14 +4043,15 @@
     return CodeLens(range: range, command: command, data: data);
   }
 
-  /// The command this CodeLens represents.
+  /// The command this code lens represents.
   final Command command;
 
-  /// A data entry field that is preserved on a CodeLens item between a CodeLens
-  /// and a CodeLens resolve request.
+  /// A data entry field that is preserved on a code lens item between a code
+  /// lens and a code lens resolve request.
   final dynamic data;
 
-  /// The range in which the CodeLens is valid. Should only span a single line.
+  /// The range in which this code lens is valid. Should only span a single
+  /// line.
   final Range range;
 
   Map<String, dynamic> toJson() {
@@ -1902,7 +4146,7 @@
     return CodeLensClientCapabilities(dynamicRegistration: dynamicRegistration);
   }
 
-  /// Whether CodeLens supports dynamic registration.
+  /// Whether code lens supports dynamic registration.
   final bool dynamicRegistration;
 
   Map<String, dynamic> toJson() {
@@ -2070,11 +4314,11 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
-  /// The document to request CodeLens for.
+  /// The document to request code lens for.
   final TextDocumentIdentifier textDocument;
 
   /// An optional token that a server can use to report work done progress.
@@ -2187,7 +4431,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// Code lens has a resolve provider as well.
@@ -2277,6 +4521,74 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class CodeLensWorkspaceClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CodeLensWorkspaceClientCapabilities.canParse,
+      CodeLensWorkspaceClientCapabilities.fromJson);
+
+  CodeLensWorkspaceClientCapabilities({this.refreshSupport});
+  static CodeLensWorkspaceClientCapabilities fromJson(
+      Map<String, dynamic> json) {
+    final refreshSupport = json['refreshSupport'];
+    return CodeLensWorkspaceClientCapabilities(refreshSupport: refreshSupport);
+  }
+
+  /// Whether the client implementation supports a refresh request sent from the
+  /// server to the client.
+  ///
+  /// Note that this event is global and will force the client to refresh all
+  /// code lenses currently shown. It should be used with absolute care and is
+  /// useful for situation where a server for example detect a project wide
+  /// change that requires such a calculation.
+  final bool refreshSupport;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (refreshSupport != null) {
+      __result['refreshSupport'] = refreshSupport;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('refreshSupport');
+      try {
+        if (obj['refreshSupport'] != null && !(obj['refreshSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter
+          .reportError('must be of type CodeLensWorkspaceClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CodeLensWorkspaceClientCapabilities &&
+        other.runtimeType == CodeLensWorkspaceClientCapabilities) {
+      return refreshSupport == other.refreshSupport && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, refreshSupport.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 /// Represents a color in RGBA space.
 class Color implements ToJsonable {
   static const jsonHandler = LspJsonHandler(Color.canParse, Color.fromJson);
@@ -2557,12 +4869,12 @@
   final List<TextEdit> additionalTextEdits;
 
   /// The label of this color presentation. It will be shown on the color picker
-  /// header. By default, this is also the text that is inserted when selecting
+  /// header. By default this is also the text that is inserted when selecting
   /// this color presentation.
   final String label;
 
   /// An edit ([TextEdit]) which is applied to a document when selecting this
-  /// presentation for the color. When `falsy`, the
+  /// presentation for the color.  When `falsy` the
   /// [label](#ColorPresentation.label) is used.
   final TextEdit textEdit;
 
@@ -2703,8 +5015,8 @@
   /// The color information to request presentations for.
   final Color color;
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The range where the color would be inserted. Serves as a context.
@@ -3108,7 +5420,10 @@
       this.documentationFormat,
       this.deprecatedSupport,
       this.preselectSupport,
-      this.tagSupport});
+      this.tagSupport,
+      this.insertReplaceSupport,
+      this.resolveSupport,
+      this.insertTextModeSupport});
   static CompletionClientCapabilitiesCompletionItem fromJson(
       Map<String, dynamic> json) {
     final snippetSupport = json['snippetSupport'];
@@ -3122,13 +5437,25 @@
     final tagSupport = json['tagSupport'] != null
         ? CompletionClientCapabilitiesTagSupport.fromJson(json['tagSupport'])
         : null;
+    final insertReplaceSupport = json['insertReplaceSupport'];
+    final resolveSupport = json['resolveSupport'] != null
+        ? CompletionClientCapabilitiesResolveSupport.fromJson(
+            json['resolveSupport'])
+        : null;
+    final insertTextModeSupport = json['insertTextModeSupport'] != null
+        ? CompletionClientCapabilitiesInsertTextModeSupport.fromJson(
+            json['insertTextModeSupport'])
+        : null;
     return CompletionClientCapabilitiesCompletionItem(
         snippetSupport: snippetSupport,
         commitCharactersSupport: commitCharactersSupport,
         documentationFormat: documentationFormat,
         deprecatedSupport: deprecatedSupport,
         preselectSupport: preselectSupport,
-        tagSupport: tagSupport);
+        tagSupport: tagSupport,
+        insertReplaceSupport: insertReplaceSupport,
+        resolveSupport: resolveSupport,
+        insertTextModeSupport: insertTextModeSupport);
   }
 
   /// Client supports commit characters on a completion item.
@@ -3141,15 +5468,32 @@
   /// The order describes the preferred format of the client.
   final List<MarkupKind> documentationFormat;
 
+  /// Client supports insert replace edit to control different behavior if a
+  /// completion item is inserted in the text or should replace text.
+  ///  @since 3.16.0
+  final bool insertReplaceSupport;
+
+  /// The client supports the `insertTextMode` property on a completion item to
+  /// override the whitespace handling mode as defined by the client (see
+  /// `insertTextMode`).
+  ///  @since 3.16.0
+  final CompletionClientCapabilitiesInsertTextModeSupport insertTextModeSupport;
+
   /// Client supports the preselect property on a completion item.
   final bool preselectSupport;
 
+  /// Indicates which properties a client can resolve lazily on a completion
+  /// item. Before version 3.16.0 only the predefined properties `documentation`
+  /// and `details` could be resolved lazily.
+  ///  @since 3.16.0
+  final CompletionClientCapabilitiesResolveSupport resolveSupport;
+
   /// Client supports snippets as insert text.
   ///
   /// A snippet can define tab stops and placeholders with `$1`, `$2` and
   /// `${3:foo}`. `$0` defines the final tab stop, it defaults to the end of the
-  /// snippet. Placeholders with equal identifiers are linked, so that typing in
-  /// one will update others as well.
+  /// snippet. Placeholders with equal identifiers are linked, that is typing in
+  /// one will update others too.
   final bool snippetSupport;
 
   /// Client supports the tag property on a completion item. Clients supporting
@@ -3179,6 +5523,15 @@
     if (tagSupport != null) {
       __result['tagSupport'] = tagSupport.toJson();
     }
+    if (insertReplaceSupport != null) {
+      __result['insertReplaceSupport'] = insertReplaceSupport;
+    }
+    if (resolveSupport != null) {
+      __result['resolveSupport'] = resolveSupport.toJson();
+    }
+    if (insertTextModeSupport != null) {
+      __result['insertTextModeSupport'] = insertTextModeSupport.toJson();
+    }
     return __result;
   }
 
@@ -3247,6 +5600,40 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('insertReplaceSupport');
+      try {
+        if (obj['insertReplaceSupport'] != null &&
+            !(obj['insertReplaceSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('resolveSupport');
+      try {
+        if (obj['resolveSupport'] != null &&
+            !(CompletionClientCapabilitiesResolveSupport.canParse(
+                obj['resolveSupport'], reporter))) {
+          reporter.reportError(
+              'must be of type CompletionClientCapabilitiesResolveSupport');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('insertTextModeSupport');
+      try {
+        if (obj['insertTextModeSupport'] != null &&
+            !(CompletionClientCapabilitiesInsertTextModeSupport.canParse(
+                obj['insertTextModeSupport'], reporter))) {
+          reporter.reportError(
+              'must be of type CompletionClientCapabilitiesInsertTextModeSupport');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError(
@@ -3266,6 +5653,9 @@
           deprecatedSupport == other.deprecatedSupport &&
           preselectSupport == other.preselectSupport &&
           tagSupport == other.tagSupport &&
+          insertReplaceSupport == other.insertReplaceSupport &&
+          resolveSupport == other.resolveSupport &&
+          insertTextModeSupport == other.insertTextModeSupport &&
           true;
     }
     return false;
@@ -3280,6 +5670,9 @@
     hash = JenkinsSmiHash.combine(hash, deprecatedSupport.hashCode);
     hash = JenkinsSmiHash.combine(hash, preselectSupport.hashCode);
     hash = JenkinsSmiHash.combine(hash, tagSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, insertReplaceSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, resolveSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, insertTextModeSupport.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -3363,6 +5756,164 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class CompletionClientCapabilitiesInsertTextModeSupport implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CompletionClientCapabilitiesInsertTextModeSupport.canParse,
+      CompletionClientCapabilitiesInsertTextModeSupport.fromJson);
+
+  CompletionClientCapabilitiesInsertTextModeSupport({@required this.valueSet}) {
+    if (valueSet == null) {
+      throw 'valueSet is required but was not provided';
+    }
+  }
+  static CompletionClientCapabilitiesInsertTextModeSupport fromJson(
+      Map<String, dynamic> json) {
+    final valueSet = json['valueSet']
+        ?.map((item) => item != null ? InsertTextMode.fromJson(item) : null)
+        ?.cast<InsertTextMode>()
+        ?.toList();
+    return CompletionClientCapabilitiesInsertTextModeSupport(
+        valueSet: valueSet);
+  }
+
+  final List<InsertTextMode> valueSet;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['valueSet'] =
+        valueSet ?? (throw 'valueSet is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('valueSet');
+      try {
+        if (!obj.containsKey('valueSet')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['valueSet'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['valueSet'] is List &&
+            (obj['valueSet']
+                .every((item) => InsertTextMode.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<InsertTextMode>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type CompletionClientCapabilitiesInsertTextModeSupport');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CompletionClientCapabilitiesInsertTextModeSupport &&
+        other.runtimeType ==
+            CompletionClientCapabilitiesInsertTextModeSupport) {
+      return listEqual(valueSet, other.valueSet,
+              (InsertTextMode a, InsertTextMode b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class CompletionClientCapabilitiesResolveSupport implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      CompletionClientCapabilitiesResolveSupport.canParse,
+      CompletionClientCapabilitiesResolveSupport.fromJson);
+
+  CompletionClientCapabilitiesResolveSupport({@required this.properties}) {
+    if (properties == null) {
+      throw 'properties is required but was not provided';
+    }
+  }
+  static CompletionClientCapabilitiesResolveSupport fromJson(
+      Map<String, dynamic> json) {
+    final properties =
+        json['properties']?.map((item) => item)?.cast<String>()?.toList();
+    return CompletionClientCapabilitiesResolveSupport(properties: properties);
+  }
+
+  /// The properties that a client can resolve lazily.
+  final List<String> properties;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['properties'] =
+        properties ?? (throw 'properties is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('properties');
+      try {
+        if (!obj.containsKey('properties')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['properties'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['properties'] is List &&
+            (obj['properties'].every((item) => item is String))))) {
+          reporter.reportError('must be of type List<String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type CompletionClientCapabilitiesResolveSupport');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CompletionClientCapabilitiesResolveSupport &&
+        other.runtimeType == CompletionClientCapabilitiesResolveSupport) {
+      return listEqual(
+              properties, other.properties, (String a, String b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(properties));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class CompletionClientCapabilitiesTagSupport implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       CompletionClientCapabilitiesTagSupport.canParse,
@@ -3463,7 +6014,7 @@
         triggerKind: triggerKind, triggerCharacter: triggerCharacter);
   }
 
-  /// The trigger character (single character) that has trigger code complete.
+  /// The trigger character (a single character) that has trigger code complete.
   /// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
   final String triggerCharacter;
 
@@ -3554,6 +6105,7 @@
       this.filterText,
       this.insertText,
       this.insertTextFormat,
+      this.insertTextMode,
       this.textEdit,
       this.additionalTextEdits,
       this.commitCharacters,
@@ -3589,6 +6141,9 @@
     final insertTextFormat = json['insertTextFormat'] != null
         ? InsertTextFormat.fromJson(json['insertTextFormat'])
         : null;
+    final insertTextMode = json['insertTextMode'] != null
+        ? InsertTextMode.fromJson(json['insertTextMode'])
+        : null;
     final textEdit =
         json['textEdit'] != null ? TextEdit.fromJson(json['textEdit']) : null;
     final additionalTextEdits = json['additionalTextEdits']
@@ -3614,6 +6169,7 @@
         filterText: filterText,
         insertText: insertText,
         insertTextFormat: insertTextFormat,
+        insertTextMode: insertTextMode,
         textEdit: textEdit,
         additionalTextEdits: additionalTextEdits,
         commitCharacters: commitCharacters,
@@ -3635,10 +6191,10 @@
   /// described with the additionalTextEdits-property.
   final Command command;
 
-  /// An optional set of characters that when pressed, while this completion is
-  /// active, will accept it first and then type that character.
-  /// *Note* that all commit characters should have `length=1` and that
-  /// superfluous characters will be ignored.
+  /// An optional set of characters that when pressed while this completion is
+  /// active will accept it first and then type that character. *Note* that all
+  /// commit characters should have `length=1` and that superfluous characters
+  /// will be ignored.
   final List<String> commitCharacters;
 
   /// A data entry field that is preserved on a completion item between a
@@ -3664,18 +6220,24 @@
   /// completion. When `falsy` the label is used.
   ///
   /// The `insertText` is subject to interpretation by the client side. Some
-  /// tools might not take the string literally. For example, VS Code when code
+  /// tools might not take the string literally. For example VS Code when code
   /// complete is requested in this example `con<cursor position>` and a
-  /// completion item with an `insertText` of `console` is provided, it will
-  /// only insert `sole`. Therefore, it is recommended to use `textEdit` instead
-  /// since it avoids additional client side interpretation.
+  /// completion item with an `insertText` of `console` is provided it will only
+  /// insert `sole`. Therefore it is recommended to use `textEdit` instead since
+  /// it avoids additional client side interpretation.
   final String insertText;
 
   /// The format of the insert text. The format applies to both the `insertText`
-  /// property and the `newText` property of a provided `textEdit`. If omitted,
+  /// property and the `newText` property of a provided `textEdit`. If omitted
   /// defaults to `InsertTextFormat.PlainText`.
   final InsertTextFormat insertTextFormat;
 
+  /// How whitespace and indentation is handled during completion item
+  /// insertion. If not provided the client's default value depends on the
+  /// `textDocument.completion.insertTextMode` client capability.
+  ///  @since 3.16.0
+  final InsertTextMode insertTextMode;
+
   /// The kind of this completion item. Based of the kind an icon is chosen by
   /// the editor. The standardized set of available values is defined in
   /// `CompletionItemKind`.
@@ -3700,11 +6262,26 @@
   ///  @since 3.15.0
   final List<CompletionItemTag> tags;
 
-  /// An edit that is applied to a document when selecting this completion. When
-  /// an edit is provided, the value of `insertText` is ignored.
+  /// An edit which is applied to a document when selecting this completion.
+  /// When an edit is provided the value of `insertText` is ignored.
   ///
   /// *Note:* The range of the edit must be a single line range and it must
   /// contain the position at which completion has been requested.
+  ///
+  /// Most editors support two different operations when accepting a completion
+  /// item. One is to insert a completion text and the other is to replace an
+  /// existing text with a completion text. Since this can usually not be
+  /// predetermined by a server it can report both ranges. Clients need to
+  /// signal support for `InsertReplaceEdits` via the
+  /// `textDocument.completion.insertReplaceSupport` client capability property.
+  ///
+  /// *Note 1:* The text edit's range as well as both ranges from an insert
+  /// replace edit must be a [single line] and they must contain the position at
+  /// which completion has been requested.
+  /// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range
+  /// must be a prefix of the edit's replace range, that means it must be
+  /// contained and starting at the same position.
+  ///  @since 3.16.0 additional type `InsertReplaceEdit`
   final TextEdit textEdit;
 
   Map<String, dynamic> toJson() {
@@ -3740,6 +6317,9 @@
     if (insertTextFormat != null) {
       __result['insertTextFormat'] = insertTextFormat.toJson();
     }
+    if (insertTextMode != null) {
+      __result['insertTextMode'] = insertTextMode.toJson();
+    }
     if (textEdit != null) {
       __result['textEdit'] = textEdit.toJson();
     }
@@ -3875,6 +6455,16 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('insertTextMode');
+      try {
+        if (obj['insertTextMode'] != null &&
+            !(InsertTextMode.canParse(obj['insertTextMode'], reporter))) {
+          reporter.reportError('must be of type InsertTextMode');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('textEdit');
       try {
         if (obj['textEdit'] != null &&
@@ -3950,6 +6540,7 @@
           filterText == other.filterText &&
           insertText == other.insertText &&
           insertTextFormat == other.insertTextFormat &&
+          insertTextMode == other.insertTextMode &&
           textEdit == other.textEdit &&
           listEqual(additionalTextEdits, other.additionalTextEdits,
               (TextEdit a, TextEdit b) => a == b) &&
@@ -3976,6 +6567,7 @@
     hash = JenkinsSmiHash.combine(hash, filterText.hashCode);
     hash = JenkinsSmiHash.combine(hash, insertText.hashCode);
     hash = JenkinsSmiHash.combine(hash, insertTextFormat.hashCode);
+    hash = JenkinsSmiHash.combine(hash, insertTextMode.hashCode);
     hash = JenkinsSmiHash.combine(hash, textEdit.hashCode);
     hash = JenkinsSmiHash.combine(hash, lspHashCode(additionalTextEdits));
     hash = JenkinsSmiHash.combine(hash, lspHashCode(commitCharacters));
@@ -4202,11 +6794,11 @@
 
   /// The list of all possible characters that commit a completion. This field
   /// can be used if clients don't support individual commit characters per
-  /// completion item. See `ClientCapabilities.`
-  /// `textDocument.completion.completionItem.commitCharactersSupport`.
+  /// completion item. See client capability
+  /// `completion.completionItem.commitCharactersSupport`.
   ///
   /// If a server provides both `allCommitCharacters` and commit characters on
-  /// an individual completion item, the ones on the completion item win.
+  /// an individual completion item the ones on the completion item win.
   ///  @since 3.2.0
   final List<String> allCommitCharacters;
 
@@ -4215,14 +6807,14 @@
   final bool resolveProvider;
 
   /// Most tools trigger completion request automatically without explicitly
-  /// requesting it using a keyboard shortcut (for example Ctrl+Space).
-  /// Typically they do so when the user starts to type an identifier. For
-  /// example, if the user types `c` in a JavaScript file, code complete will
-  /// automatically display `console` along with others as a completion item.
-  /// Characters that make up identifiers don't need to be listed here.
+  /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they
+  /// do so when the user starts to type an identifier. For example if the user
+  /// types `c` in a JavaScript file code complete will automatically pop up
+  /// present `console` besides others as a completion item. Characters that
+  /// make up identifiers don't need to be listed here.
   ///
-  /// If code complete should automatically be triggered on characters not being
-  /// valid inside an identifier (for example `.` in JavaScript), list them in
+  /// If code complete should automatically be trigger on characters not being
+  /// valid inside an identifier (for example `.` in JavaScript) list them in
   /// `triggerCharacters`.
   final List<String> triggerCharacters;
   final bool workDoneProgress;
@@ -4378,12 +6970,11 @@
   }
 
   /// The completion context. This is only available if the client specifies to
-  /// send this using `ClientCapabilities.textDocument.completion.contextSupport
-  /// === true`
+  /// send this using the client capability `completion.contextSupport === true`
   final CompletionContext context;
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The position inside the text document.
@@ -4553,16 +7144,16 @@
 
   /// The list of all possible characters that commit a completion. This field
   /// can be used if clients don't support individual commit characters per
-  /// completion item. See `ClientCapabilities.`
-  /// `textDocument.completion.completionItem.commitCharactersSupport`.
+  /// completion item. See client capability
+  /// `completion.completionItem.commitCharactersSupport`.
   ///
   /// If a server provides both `allCommitCharacters` and commit characters on
-  /// an individual completion item, the ones on the completion item win.
+  /// an individual completion item the ones on the completion item win.
   ///  @since 3.2.0
   final List<String> allCommitCharacters;
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// The server provides support to resolve additional information for a
@@ -4570,14 +7161,14 @@
   final bool resolveProvider;
 
   /// Most tools trigger completion request automatically without explicitly
-  /// requesting it using a keyboard shortcut (for example Ctrl+Space).
-  /// Typically they do so when the user starts to type an identifier. For
-  /// example, if the user types `c` in a JavaScript file, code complete will
-  /// automatically display `console` along with others as a completion item.
-  /// Characters that make up identifiers don't need to be listed here.
+  /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they
+  /// do so when the user starts to type an identifier. For example if the user
+  /// types `c` in a JavaScript file code complete will automatically pop up
+  /// present `console` besides others as a completion item. Characters that
+  /// make up identifiers don't need to be listed here.
   ///
-  /// If code complete should automatically be triggered on characters not being
-  /// valid inside an identifier (for example `.` in JavaScript), list them in
+  /// If code complete should automatically be trigger on characters not being
+  /// valid inside an identifier (for example `.` in JavaScript) list them in
   /// `triggerCharacters`.
   final List<String> triggerCharacters;
   final bool workDoneProgress;
@@ -4722,7 +7313,7 @@
   static const Invoked = CompletionTriggerKind._(1);
 
   /// Completion was triggered by a trigger character specified by the
-  /// `triggerCharacters` properties of `CompletionRegistrationOptions`.
+  /// `triggerCharacters` properties of the `CompletionRegistrationOptions`.
   static const TriggerCharacter = CompletionTriggerKind._(2);
 
   /// Completion was re-triggered as the current completion list is incomplete.
@@ -4895,7 +7486,11 @@
   static const jsonHandler =
       LspJsonHandler(CreateFile.canParse, CreateFile.fromJson);
 
-  CreateFile({this.kind = 'create', @required this.uri, this.options}) {
+  CreateFile(
+      {this.kind = 'create',
+      @required this.uri,
+      this.options,
+      this.annotationId}) {
     if (kind != 'create') {
       throw 'kind may only be the literal \'create\'';
     }
@@ -4909,9 +7504,15 @@
     final options = json['options'] != null
         ? CreateFileOptions.fromJson(json['options'])
         : null;
-    return CreateFile(kind: kind, uri: uri, options: options);
+    final annotationId = json['annotationId'];
+    return CreateFile(
+        kind: kind, uri: uri, options: options, annotationId: annotationId);
   }
 
+  /// An optional annotation identifer describing the operation.
+  ///  @since 3.16.0
+  final String annotationId;
+
   /// A create
   final String kind;
 
@@ -4928,6 +7529,9 @@
     if (options != null) {
       __result['options'] = options.toJson();
     }
+    if (annotationId != null) {
+      __result['annotationId'] = annotationId;
+    }
     return __result;
   }
 
@@ -4977,6 +7581,15 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('annotationId');
+      try {
+        if (obj['annotationId'] != null && !(obj['annotationId'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type CreateFile');
@@ -4990,6 +7603,7 @@
       return kind == other.kind &&
           uri == other.uri &&
           options == other.options &&
+          annotationId == other.annotationId &&
           true;
     }
     return false;
@@ -5001,6 +7615,7 @@
     hash = JenkinsSmiHash.combine(hash, kind.hashCode);
     hash = JenkinsSmiHash.combine(hash, uri.hashCode);
     hash = JenkinsSmiHash.combine(hash, options.hashCode);
+    hash = JenkinsSmiHash.combine(hash, annotationId.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -5087,6 +7702,84 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// The parameters sent in notifications/requests for user-initiated creation of
+/// files.
+///  @since 3.16.0
+class CreateFilesParams implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(CreateFilesParams.canParse, CreateFilesParams.fromJson);
+
+  CreateFilesParams({@required this.files}) {
+    if (files == null) {
+      throw 'files is required but was not provided';
+    }
+  }
+  static CreateFilesParams fromJson(Map<String, dynamic> json) {
+    final files = json['files']
+        ?.map((item) => item != null ? FileCreate.fromJson(item) : null)
+        ?.cast<FileCreate>()
+        ?.toList();
+    return CreateFilesParams(files: files);
+  }
+
+  /// An array of all files/folders created in this operation.
+  final List<FileCreate> files;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['files'] = files ?? (throw 'files is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('files');
+      try {
+        if (!obj.containsKey('files')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['files'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['files'] is List &&
+            (obj['files']
+                .every((item) => FileCreate.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<FileCreate>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type CreateFilesParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is CreateFilesParams && other.runtimeType == CreateFilesParams) {
+      return listEqual(
+              files, other.files, (FileCreate a, FileCreate b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(files));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class DeclarationClientCapabilities implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       DeclarationClientCapabilities.canParse,
@@ -5101,8 +7794,8 @@
   }
 
   /// Whether declaration supports dynamic registration. If this is set to
-  /// `true`, the client supports the new `DeclarationRegistrationOptions`
-  /// return value for the corresponding server capability as well.
+  /// `true` the client supports the new `DeclarationRegistrationOptions` return
+  /// value for the corresponding server capability as well.
   final bool dynamicRegistration;
 
   /// The client supports additional metadata in the form of declaration links.
@@ -5280,8 +7973,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The position inside the text document.
@@ -5425,7 +8118,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// The id used to register the request. The id can be used to deregister the
@@ -5706,8 +8399,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The position inside the text document.
@@ -5843,7 +8536,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
   final bool workDoneProgress;
 
@@ -5920,7 +8613,11 @@
   static const jsonHandler =
       LspJsonHandler(DeleteFile.canParse, DeleteFile.fromJson);
 
-  DeleteFile({this.kind = 'delete', @required this.uri, this.options}) {
+  DeleteFile(
+      {this.kind = 'delete',
+      @required this.uri,
+      this.options,
+      this.annotationId}) {
     if (kind != 'delete') {
       throw 'kind may only be the literal \'delete\'';
     }
@@ -5934,9 +8631,15 @@
     final options = json['options'] != null
         ? DeleteFileOptions.fromJson(json['options'])
         : null;
-    return DeleteFile(kind: kind, uri: uri, options: options);
+    final annotationId = json['annotationId'];
+    return DeleteFile(
+        kind: kind, uri: uri, options: options, annotationId: annotationId);
   }
 
+  /// An optional annotation identifer describing the operation.
+  ///  @since 3.16.0
+  final String annotationId;
+
   /// A delete
   final String kind;
 
@@ -5953,6 +8656,9 @@
     if (options != null) {
       __result['options'] = options.toJson();
     }
+    if (annotationId != null) {
+      __result['annotationId'] = annotationId;
+    }
     return __result;
   }
 
@@ -6002,6 +8708,15 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('annotationId');
+      try {
+        if (obj['annotationId'] != null && !(obj['annotationId'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type DeleteFile');
@@ -6015,6 +8730,7 @@
       return kind == other.kind &&
           uri == other.uri &&
           options == other.options &&
+          annotationId == other.annotationId &&
           true;
     }
     return false;
@@ -6026,6 +8742,7 @@
     hash = JenkinsSmiHash.combine(hash, kind.hashCode);
     hash = JenkinsSmiHash.combine(hash, uri.hashCode);
     hash = JenkinsSmiHash.combine(hash, options.hashCode);
+    hash = JenkinsSmiHash.combine(hash, annotationId.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -6113,6 +8830,84 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// The parameters sent in notifications/requests for user-initiated deletes of
+/// files.
+///  @since 3.16.0
+class DeleteFilesParams implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(DeleteFilesParams.canParse, DeleteFilesParams.fromJson);
+
+  DeleteFilesParams({@required this.files}) {
+    if (files == null) {
+      throw 'files is required but was not provided';
+    }
+  }
+  static DeleteFilesParams fromJson(Map<String, dynamic> json) {
+    final files = json['files']
+        ?.map((item) => item != null ? FileDelete.fromJson(item) : null)
+        ?.cast<FileDelete>()
+        ?.toList();
+    return DeleteFilesParams(files: files);
+  }
+
+  /// An array of all files/folders deleted in this operation.
+  final List<FileDelete> files;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['files'] = files ?? (throw 'files is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('files');
+      try {
+        if (!obj.containsKey('files')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['files'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['files'] is List &&
+            (obj['files']
+                .every((item) => FileDelete.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<FileDelete>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type DeleteFilesParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is DeleteFilesParams && other.runtimeType == DeleteFilesParams) {
+      return listEqual(
+              files, other.files, (FileDelete a, FileDelete b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(files));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class Diagnostic implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(Diagnostic.canParse, Diagnostic.fromJson);
@@ -6121,10 +8916,12 @@
       {@required this.range,
       this.severity,
       this.code,
+      this.codeDescription,
       this.source,
       @required this.message,
       this.tags,
-      this.relatedInformation}) {
+      this.relatedInformation,
+      this.data}) {
     if (range == null) {
       throw 'range is required but was not provided';
     }
@@ -6138,6 +8935,9 @@
         ? DiagnosticSeverity.fromJson(json['severity'])
         : null;
     final code = json['code'];
+    final codeDescription = json['codeDescription'] != null
+        ? CodeDescription.fromJson(json['codeDescription'])
+        : null;
     final source = json['source'];
     final message = json['message'];
     final tags = json['tags']
@@ -6149,19 +8949,32 @@
             item != null ? DiagnosticRelatedInformation.fromJson(item) : null)
         ?.cast<DiagnosticRelatedInformation>()
         ?.toList();
+    final data = json['data'];
     return Diagnostic(
         range: range,
         severity: severity,
         code: code,
+        codeDescription: codeDescription,
         source: source,
         message: message,
         tags: tags,
-        relatedInformation: relatedInformation);
+        relatedInformation: relatedInformation,
+        data: data);
   }
 
   /// The diagnostic's code, which might appear in the user interface.
   final String code;
 
+  /// An optional property to describe the error code.
+  ///  @since 3.16.0
+  final CodeDescription codeDescription;
+
+  /// A data entry field that is preserved between a
+  /// `textDocument/publishDiagnostics` notification and
+  /// `textDocument/codeAction` request.
+  ///  @since 3.16.0
+  final dynamic data;
+
   /// The diagnostic's message.
   final String message;
 
@@ -6194,6 +9007,9 @@
     if (code != null) {
       __result['code'] = code;
     }
+    if (codeDescription != null) {
+      __result['codeDescription'] = codeDescription.toJson();
+    }
     if (source != null) {
       __result['source'] = source;
     }
@@ -6205,6 +9021,9 @@
     if (relatedInformation != null) {
       __result['relatedInformation'] = relatedInformation;
     }
+    if (data != null) {
+      __result['data'] = data;
+    }
     return __result;
   }
 
@@ -6246,6 +9065,16 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('codeDescription');
+      try {
+        if (obj['codeDescription'] != null &&
+            !(CodeDescription.canParse(obj['codeDescription'], reporter))) {
+          reporter.reportError('must be of type CodeDescription');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('source');
       try {
         if (obj['source'] != null && !(obj['source'] is String)) {
@@ -6297,6 +9126,15 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('data');
+      try {
+        if (obj['data'] != null && !(true)) {
+          reporter.reportError('must be of type dynamic');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type Diagnostic');
@@ -6310,6 +9148,7 @@
       return range == other.range &&
           severity == other.severity &&
           code == other.code &&
+          codeDescription == other.codeDescription &&
           source == other.source &&
           message == other.message &&
           listEqual(
@@ -6320,6 +9159,7 @@
               (DiagnosticRelatedInformation a,
                       DiagnosticRelatedInformation b) =>
                   a == b) &&
+          data == other.data &&
           true;
     }
     return false;
@@ -6331,10 +9171,12 @@
     hash = JenkinsSmiHash.combine(hash, range.hashCode);
     hash = JenkinsSmiHash.combine(hash, severity.hashCode);
     hash = JenkinsSmiHash.combine(hash, code.hashCode);
+    hash = JenkinsSmiHash.combine(hash, codeDescription.hashCode);
     hash = JenkinsSmiHash.combine(hash, source.hashCode);
     hash = JenkinsSmiHash.combine(hash, message.hashCode);
     hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
     hash = JenkinsSmiHash.combine(hash, lspHashCode(relatedInformation));
+    hash = JenkinsSmiHash.combine(hash, data.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -6344,7 +9186,7 @@
 
 /// Represents a related message and source code location for a diagnostic. This
 /// should be used to point to code locations that cause or are related to a
-/// diagnostics, for example, when duplicating a symbol in a scope.
+/// diagnostics, e.g when duplicating a symbol in a scope.
 class DiagnosticRelatedInformation implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       DiagnosticRelatedInformation.canParse,
@@ -6677,18 +9519,18 @@
   }
 
   /// The actual content changes. The content changes describe single state
-  /// changes to the document. If there are two content changes c1 (at array
-  /// index 0) and c2 (at array index 1) for a document in state S, then c1
-  /// moves the document from S to S' and c2 from S' to S''. So c1 is computed
-  /// on the state S and c2 is computed on the state S'.
+  /// changes to the document. So if there are two content changes c1 (at array
+  /// index 0) and c2 (at array index 1) for a document in state S then c1 moves
+  /// the document from S to S' and c2 from S' to S''. So c1 is computed on the
+  /// state S and c2 is computed on the state S'.
   ///
-  /// To mirror the content of a document using change events, use the following
+  /// To mirror the content of a document using change events use the following
   /// approach:
   /// - start with the same initial content
-  /// - apply the 'textDocument/didChange' notifications
-  ///     in the order you receive them.
-  /// - apply the `TextDocumentContentChangeEvent`s
-  ///     in a single notification in the order you receive them.
+  /// - apply the 'textDocument/didChange' notifications in the order you
+  ///   receive them.
+  /// - apply the `TextDocumentContentChangeEvent`s in a single notification
+  ///   in the order you receive them.
   final List<
       Either2<TextDocumentContentChangeEvent1,
           TextDocumentContentChangeEvent2>> contentChanges;
@@ -7481,8 +10323,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The text document.
@@ -7603,7 +10445,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// The id used to register the request. The id can be used to deregister the
@@ -7714,13 +10556,13 @@
   /// - `*` to match one or more characters in a path segment
   /// - `?` to match on one character in a path segment
   /// - `**` to match any number of path segments, including none
-  /// - `{}` to group conditions
-  ///   (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
+  /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
+  ///   and JavaScript files)
   /// - `[]` to declare a range of characters to match in a path segment
   ///   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
   /// - `[!...]` to negate a range of characters to match in a path segment
-  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`,
-  ///    but not `example.0`)
+  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
+  ///   not `example.0`)
   final String pattern;
 
   /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
@@ -8085,7 +10927,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
   final bool workDoneProgress;
 
@@ -8457,8 +11299,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The position inside the text document.
@@ -8600,7 +11442,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
   final bool workDoneProgress;
 
@@ -8705,7 +11547,7 @@
 
   /// The tooltip text when you hover over this link.
   ///
-  /// If a tooltip is provided, it will be displayed in a string that includes
+  /// If a tooltip is provided, is will be displayed in a string that includes
   /// instructions on how to trigger the link, such as `{0} (ctrl + click)`. The
   /// specific instructions vary depending on OS, user settings, and
   /// localization.
@@ -9010,8 +11852,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The document to provide document links for.
@@ -9131,7 +11973,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// Document links have a resolve provider as well.
@@ -9593,7 +12435,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// A character on which formatting should be triggered, like `}`.
@@ -10014,7 +12856,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
   final bool workDoneProgress;
 
@@ -10090,7 +12932,7 @@
 /// Represents programming constructs like variables, classes, interfaces etc.
 /// that appear in a document. Document symbols can be hierarchical and they
 /// have two ranges: one that encloses its definition and one that points to its
-/// most interesting range, for example, the range of an identifier.
+/// most interesting range, e.g. the range of an identifier.
 class DocumentSymbol implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(DocumentSymbol.canParse, DocumentSymbol.fromJson);
@@ -10099,6 +12941,7 @@
       {@required this.name,
       this.detail,
       @required this.kind,
+      this.tags,
       this.deprecated,
       @required this.range,
       @required this.selectionRange,
@@ -10121,6 +12964,10 @@
     final detail = json['detail'];
     final kind =
         json['kind'] != null ? SymbolKind.fromJson(json['kind']) : null;
+    final tags = json['tags']
+        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
+        ?.cast<SymbolTag>()
+        ?.toList();
     final deprecated = json['deprecated'];
     final range = json['range'] != null ? Range.fromJson(json['range']) : null;
     final selectionRange = json['selectionRange'] != null
@@ -10134,6 +12981,7 @@
         name: name,
         detail: detail,
         kind: kind,
+        tags: tags,
         deprecated: deprecated,
         range: range,
         selectionRange: selectionRange,
@@ -10144,6 +12992,7 @@
   final List<DocumentSymbol> children;
 
   /// Indicates if this symbol is deprecated.
+  ///  @deprecated Use tags instead
   final bool deprecated;
 
   /// More detail for this symbol, e.g the signature of a function.
@@ -10159,15 +13008,18 @@
 
   /// The range enclosing this symbol not including leading/trailing whitespace
   /// but everything else like comments. This information is typically used to
-  /// determine if the client's cursor is inside the symbol to reveal in the
+  /// determine if the clients cursor is inside the symbol to reveal in the
   /// symbol in the UI.
   final Range range;
 
   /// The range that should be selected and revealed when this symbol is being
-  /// picked, for example, the name of a function. Must be contained by the
-  /// `range`.
+  /// picked, e.g. the name of a function. Must be contained by the `range`.
   final Range selectionRange;
 
+  /// Tags for this document symbol.
+  ///  @since 3.16.0
+  final List<SymbolTag> tags;
+
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['name'] = name ?? (throw 'name is required but was not set');
@@ -10176,6 +13028,9 @@
     }
     __result['kind'] =
         kind?.toJson() ?? (throw 'kind is required but was not set');
+    if (tags != null) {
+      __result['tags'] = tags;
+    }
     if (deprecated != null) {
       __result['deprecated'] = deprecated;
     }
@@ -10234,6 +13089,18 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('tags');
+      try {
+        if (obj['tags'] != null &&
+            !((obj['tags'] is List &&
+                (obj['tags']
+                    .every((item) => SymbolTag.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<SymbolTag>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('deprecated');
       try {
         if (obj['deprecated'] != null && !(obj['deprecated'] is bool)) {
@@ -10302,6 +13169,7 @@
       return name == other.name &&
           detail == other.detail &&
           kind == other.kind &&
+          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
           deprecated == other.deprecated &&
           range == other.range &&
           selectionRange == other.selectionRange &&
@@ -10318,6 +13186,7 @@
     hash = JenkinsSmiHash.combine(hash, name.hashCode);
     hash = JenkinsSmiHash.combine(hash, detail.hashCode);
     hash = JenkinsSmiHash.combine(hash, kind.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
     hash = JenkinsSmiHash.combine(hash, deprecated.hashCode);
     hash = JenkinsSmiHash.combine(hash, range.hashCode);
     hash = JenkinsSmiHash.combine(hash, selectionRange.hashCode);
@@ -10337,7 +13206,9 @@
   DocumentSymbolClientCapabilities(
       {this.dynamicRegistration,
       this.symbolKind,
-      this.hierarchicalDocumentSymbolSupport});
+      this.hierarchicalDocumentSymbolSupport,
+      this.tagSupport,
+      this.labelSupport});
   static DocumentSymbolClientCapabilities fromJson(Map<String, dynamic> json) {
     final dynamicRegistration = json['dynamicRegistration'];
     final symbolKind = json['symbolKind'] != null
@@ -10346,10 +13217,17 @@
         : null;
     final hierarchicalDocumentSymbolSupport =
         json['hierarchicalDocumentSymbolSupport'];
+    final tagSupport = json['tagSupport'] != null
+        ? DocumentSymbolClientCapabilitiesTagSupport.fromJson(
+            json['tagSupport'])
+        : null;
+    final labelSupport = json['labelSupport'];
     return DocumentSymbolClientCapabilities(
         dynamicRegistration: dynamicRegistration,
         symbolKind: symbolKind,
-        hierarchicalDocumentSymbolSupport: hierarchicalDocumentSymbolSupport);
+        hierarchicalDocumentSymbolSupport: hierarchicalDocumentSymbolSupport,
+        tagSupport: tagSupport,
+        labelSupport: labelSupport);
   }
 
   /// Whether document symbol supports dynamic registration.
@@ -10358,10 +13236,21 @@
   /// The client supports hierarchical document symbols.
   final bool hierarchicalDocumentSymbolSupport;
 
+  /// The client supports an additional label presented in the UI when
+  /// registering a document symbol provider.
+  ///  @since 3.16.0
+  final bool labelSupport;
+
   /// Specific capabilities for the `SymbolKind` in the
   /// `textDocument/documentSymbol` request.
   final DocumentSymbolClientCapabilitiesSymbolKind symbolKind;
 
+  /// The client supports tags on `SymbolInformation`. Tags are supported on
+  /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
+  /// Clients supporting tags have to handle unknown tags gracefully.
+  ///  @since 3.16.0
+  final DocumentSymbolClientCapabilitiesTagSupport tagSupport;
+
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (dynamicRegistration != null) {
@@ -10374,6 +13263,12 @@
       __result['hierarchicalDocumentSymbolSupport'] =
           hierarchicalDocumentSymbolSupport;
     }
+    if (tagSupport != null) {
+      __result['tagSupport'] = tagSupport.toJson();
+    }
+    if (labelSupport != null) {
+      __result['labelSupport'] = labelSupport;
+    }
     return __result;
   }
 
@@ -10411,6 +13306,27 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('tagSupport');
+      try {
+        if (obj['tagSupport'] != null &&
+            !(DocumentSymbolClientCapabilitiesTagSupport.canParse(
+                obj['tagSupport'], reporter))) {
+          reporter.reportError(
+              'must be of type DocumentSymbolClientCapabilitiesTagSupport');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('labelSupport');
+      try {
+        if (obj['labelSupport'] != null && !(obj['labelSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type DocumentSymbolClientCapabilities');
@@ -10426,6 +13342,8 @@
           symbolKind == other.symbolKind &&
           hierarchicalDocumentSymbolSupport ==
               other.hierarchicalDocumentSymbolSupport &&
+          tagSupport == other.tagSupport &&
+          labelSupport == other.labelSupport &&
           true;
     }
     return false;
@@ -10438,6 +13356,8 @@
     hash = JenkinsSmiHash.combine(hash, symbolKind.hashCode);
     hash = JenkinsSmiHash.combine(
         hash, hierarchicalDocumentSymbolSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, tagSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, labelSupport.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -10520,23 +13440,112 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class DocumentSymbolClientCapabilitiesTagSupport implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      DocumentSymbolClientCapabilitiesTagSupport.canParse,
+      DocumentSymbolClientCapabilitiesTagSupport.fromJson);
+
+  DocumentSymbolClientCapabilitiesTagSupport({@required this.valueSet}) {
+    if (valueSet == null) {
+      throw 'valueSet is required but was not provided';
+    }
+  }
+  static DocumentSymbolClientCapabilitiesTagSupport fromJson(
+      Map<String, dynamic> json) {
+    final valueSet = json['valueSet']
+        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
+        ?.cast<SymbolTag>()
+        ?.toList();
+    return DocumentSymbolClientCapabilitiesTagSupport(valueSet: valueSet);
+  }
+
+  /// The tags supported by the client.
+  final List<SymbolTag> valueSet;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['valueSet'] =
+        valueSet ?? (throw 'valueSet is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('valueSet');
+      try {
+        if (!obj.containsKey('valueSet')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['valueSet'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['valueSet'] is List &&
+            (obj['valueSet']
+                .every((item) => SymbolTag.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<SymbolTag>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type DocumentSymbolClientCapabilitiesTagSupport');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is DocumentSymbolClientCapabilitiesTagSupport &&
+        other.runtimeType == DocumentSymbolClientCapabilitiesTagSupport) {
+      return listEqual(
+              valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class DocumentSymbolOptions implements WorkDoneProgressOptions, ToJsonable {
   static const jsonHandler = LspJsonHandler(
       DocumentSymbolOptions.canParse, DocumentSymbolOptions.fromJson);
 
-  DocumentSymbolOptions({this.workDoneProgress});
+  DocumentSymbolOptions({this.label, this.workDoneProgress});
   static DocumentSymbolOptions fromJson(Map<String, dynamic> json) {
     if (DocumentSymbolRegistrationOptions.canParse(json, nullLspJsonReporter)) {
       return DocumentSymbolRegistrationOptions.fromJson(json);
     }
+    final label = json['label'];
     final workDoneProgress = json['workDoneProgress'];
-    return DocumentSymbolOptions(workDoneProgress: workDoneProgress);
+    return DocumentSymbolOptions(
+        label: label, workDoneProgress: workDoneProgress);
   }
 
+  /// A human-readable string that is shown when multiple outlines trees are
+  /// shown for the same document.
+  ///  @since 3.16.0
+  final String label;
   final bool workDoneProgress;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
+    if (label != null) {
+      __result['label'] = label;
+    }
     if (workDoneProgress != null) {
       __result['workDoneProgress'] = workDoneProgress;
     }
@@ -10545,6 +13554,15 @@
 
   static bool canParse(Object obj, LspJsonReporter reporter) {
     if (obj is Map<String, dynamic>) {
+      reporter.push('label');
+      try {
+        if (obj['label'] != null && !(obj['label'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('workDoneProgress');
       try {
         if (obj['workDoneProgress'] != null &&
@@ -10566,7 +13584,9 @@
   bool operator ==(Object other) {
     if (other is DocumentSymbolOptions &&
         other.runtimeType == DocumentSymbolOptions) {
-      return workDoneProgress == other.workDoneProgress && true;
+      return label == other.label &&
+          workDoneProgress == other.workDoneProgress &&
+          true;
     }
     return false;
   }
@@ -10574,6 +13594,7 @@
   @override
   int get hashCode {
     var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, label.hashCode);
     hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
@@ -10619,8 +13640,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The text document.
@@ -10725,25 +13746,36 @@
       DocumentSymbolRegistrationOptions.fromJson);
 
   DocumentSymbolRegistrationOptions(
-      {this.documentSelector, this.workDoneProgress});
+      {this.documentSelector, this.label, this.workDoneProgress});
   static DocumentSymbolRegistrationOptions fromJson(Map<String, dynamic> json) {
     final documentSelector = json['documentSelector']
         ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
         ?.cast<DocumentFilter>()
         ?.toList();
+    final label = json['label'];
     final workDoneProgress = json['workDoneProgress'];
     return DocumentSymbolRegistrationOptions(
-        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
+        documentSelector: documentSelector,
+        label: label,
+        workDoneProgress: workDoneProgress);
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
+
+  /// A human-readable string that is shown when multiple outlines trees are
+  /// shown for the same document.
+  ///  @since 3.16.0
+  final String label;
   final bool workDoneProgress;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['documentSelector'] = documentSelector;
+    if (label != null) {
+      __result['label'] = label;
+    }
     if (workDoneProgress != null) {
       __result['workDoneProgress'] = workDoneProgress;
     }
@@ -10768,6 +13800,15 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('label');
+      try {
+        if (obj['label'] != null && !(obj['label'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('workDoneProgress');
       try {
         if (obj['workDoneProgress'] != null &&
@@ -10791,6 +13832,7 @@
         other.runtimeType == DocumentSymbolRegistrationOptions) {
       return listEqual(documentSelector, other.documentSelector,
               (DocumentFilter a, DocumentFilter b) => a == b) &&
+          label == other.label &&
           workDoneProgress == other.workDoneProgress &&
           true;
     }
@@ -10801,6 +13843,7 @@
   int get hashCode {
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
+    hash = JenkinsSmiHash.combine(hash, label.hashCode);
     hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
@@ -10825,14 +13868,31 @@
   static const MethodNotFound = ErrorCodes(-32601);
   static const InvalidParams = ErrorCodes(-32602);
   static const InternalError = ErrorCodes(-32603);
-  static const serverErrorStart = ErrorCodes(-32099);
-  static const serverErrorEnd = ErrorCodes(-32000);
+
+  /// This is the start range of JSON RPC reserved error codes. It doesn't
+  /// denote a real error code. No LSP error codes should be defined between the
+  /// start and end range. For backwards compatibility the
+  /// `ServerNotInitialized` and the `UnknownErrorCode` are left in the range.
+  ///  @since 3.16.0
+  static const jsonrpcReservedErrorRangeStart = ErrorCodes(-32099);
   static const ServerNotInitialized = ErrorCodes(-32002);
   static const UnknownErrorCode = ErrorCodes(-32001);
 
-  /// Defined by the protocol.
-  static const RequestCancelled = ErrorCodes(-32800);
+  /// This is the start range of JSON RPC reserved error codes. It doesn't
+  /// denote a real error code.
+  static const jsonrpcReservedErrorRangeEnd = ErrorCodes(-32000);
+
+  /// This is the start range of LSP reserved error codes. It doesn't denote a
+  /// real error code.
+  ///  @since 3.16.0
+  static const lspReservedErrorRangeStart = ErrorCodes(-32899);
   static const ContentModified = ErrorCodes(-32801);
+  static const RequestCancelled = ErrorCodes(-32800);
+
+  /// This is the end range of LSP reserved error codes. It doesn't denote a
+  /// real error code.
+  ///  @since 3.16.0
+  static const lspReservedErrorRangeEnd = ErrorCodes(-32800);
 
   Object toJson() => _value;
 
@@ -11245,9 +14305,9 @@
   /// succeed or no changes at all are applied to the workspace.
   static const Transactional = FailureHandlingKind._('transactional');
 
-  /// If the workspace edit contains only textual file changes, they are
-  /// executed transactionally. If resource changes (create, rename or delete
-  /// file) are part of the change, the failure handling strategy is abort.
+  /// If the workspace edit contains only textual file changes they are executed
+  /// transactional. If resource changes (create, rename or delete file) are
+  /// part of the change the failure handling strategy is abort.
   static const TextOnlyTransactional =
       FailureHandlingKind._('textOnlyTransactional');
 
@@ -11297,6 +14357,146 @@
   bool operator ==(Object o) => o is FileChangeType && o._value == _value;
 }
 
+/// Represents information on a file/folder create.
+///  @since 3.16.0
+class FileCreate implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(FileCreate.canParse, FileCreate.fromJson);
+
+  FileCreate({@required this.uri}) {
+    if (uri == null) {
+      throw 'uri is required but was not provided';
+    }
+  }
+  static FileCreate fromJson(Map<String, dynamic> json) {
+    final uri = json['uri'];
+    return FileCreate(uri: uri);
+  }
+
+  /// A file:// URI for the location of the file/folder being created.
+  final String uri;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['uri'] = uri ?? (throw 'uri is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('uri');
+      try {
+        if (!obj.containsKey('uri')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['uri'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['uri'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type FileCreate');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is FileCreate && other.runtimeType == FileCreate) {
+      return uri == other.uri && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// Represents information on a file/folder delete.
+///  @since 3.16.0
+class FileDelete implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(FileDelete.canParse, FileDelete.fromJson);
+
+  FileDelete({@required this.uri}) {
+    if (uri == null) {
+      throw 'uri is required but was not provided';
+    }
+  }
+  static FileDelete fromJson(Map<String, dynamic> json) {
+    final uri = json['uri'];
+    return FileDelete(uri: uri);
+  }
+
+  /// A file:// URI for the location of the file/folder being deleted.
+  final String uri;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['uri'] = uri ?? (throw 'uri is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('uri');
+      try {
+        if (!obj.containsKey('uri')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['uri'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['uri'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type FileDelete');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is FileDelete && other.runtimeType == FileDelete) {
+      return uri == other.uri && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 /// An event describing a file change.
 class FileEvent implements ToJsonable {
   static const jsonHandler =
@@ -11392,6 +14592,494 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// A filter to describe in which file operation requests or notifications the
+/// server is interested in.
+///  @since 3.16.0
+class FileOperationFilter implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      FileOperationFilter.canParse, FileOperationFilter.fromJson);
+
+  FileOperationFilter({this.scheme, @required this.pattern}) {
+    if (pattern == null) {
+      throw 'pattern is required but was not provided';
+    }
+  }
+  static FileOperationFilter fromJson(Map<String, dynamic> json) {
+    final scheme = json['scheme'];
+    final pattern = json['pattern'] != null
+        ? FileOperationPattern.fromJson(json['pattern'])
+        : null;
+    return FileOperationFilter(scheme: scheme, pattern: pattern);
+  }
+
+  /// The actual file operation pattern.
+  final FileOperationPattern pattern;
+
+  /// A Uri like `file` or `untitled`.
+  final String scheme;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (scheme != null) {
+      __result['scheme'] = scheme;
+    }
+    __result['pattern'] =
+        pattern?.toJson() ?? (throw 'pattern is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('scheme');
+      try {
+        if (obj['scheme'] != null && !(obj['scheme'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('pattern');
+      try {
+        if (!obj.containsKey('pattern')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['pattern'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(FileOperationPattern.canParse(obj['pattern'], reporter))) {
+          reporter.reportError('must be of type FileOperationPattern');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type FileOperationFilter');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is FileOperationFilter &&
+        other.runtimeType == FileOperationFilter) {
+      return scheme == other.scheme && pattern == other.pattern && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, scheme.hashCode);
+    hash = JenkinsSmiHash.combine(hash, pattern.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// A pattern to describe in which file operation requests or notifications the
+/// server is interested in.
+///  @since 3.16.0
+class FileOperationPattern implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      FileOperationPattern.canParse, FileOperationPattern.fromJson);
+
+  FileOperationPattern({@required this.glob, this.matches, this.options}) {
+    if (glob == null) {
+      throw 'glob is required but was not provided';
+    }
+  }
+  static FileOperationPattern fromJson(Map<String, dynamic> json) {
+    final glob = json['glob'];
+    final matches = json['matches'] != null
+        ? FileOperationPatternKind.fromJson(json['matches'])
+        : null;
+    final options = json['options'] != null
+        ? FileOperationPatternOptions.fromJson(json['options'])
+        : null;
+    return FileOperationPattern(glob: glob, matches: matches, options: options);
+  }
+
+  /// The glob pattern to match. Glob patterns can have the following syntax:
+  /// - `*` to match one or more characters in a path segment
+  /// - `?` to match on one character in a path segment
+  /// - `**` to match any number of path segments, including none
+  /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
+  ///   and JavaScript files)
+  /// - `[]` to declare a range of characters to match in a path segment
+  ///   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
+  /// - `[!...]` to negate a range of characters to match in a path segment
+  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
+  ///   not `example.0`)
+  final String glob;
+
+  /// Whether to match files or folders with this pattern.
+  ///
+  /// Matches both if undefined.
+  final FileOperationPatternKind matches;
+
+  /// Additional options used during matching.
+  final FileOperationPatternOptions options;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['glob'] = glob ?? (throw 'glob is required but was not set');
+    if (matches != null) {
+      __result['matches'] = matches.toJson();
+    }
+    if (options != null) {
+      __result['options'] = options.toJson();
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('glob');
+      try {
+        if (!obj.containsKey('glob')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['glob'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['glob'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('matches');
+      try {
+        if (obj['matches'] != null &&
+            !(FileOperationPatternKind.canParse(obj['matches'], reporter))) {
+          reporter.reportError('must be of type FileOperationPatternKind');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('options');
+      try {
+        if (obj['options'] != null &&
+            !(FileOperationPatternOptions.canParse(obj['options'], reporter))) {
+          reporter.reportError('must be of type FileOperationPatternOptions');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type FileOperationPattern');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is FileOperationPattern &&
+        other.runtimeType == FileOperationPattern) {
+      return glob == other.glob &&
+          matches == other.matches &&
+          options == other.options &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, glob.hashCode);
+    hash = JenkinsSmiHash.combine(hash, matches.hashCode);
+    hash = JenkinsSmiHash.combine(hash, options.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// A pattern kind describing if a glob pattern matches a file a folder or both.
+///  @since 3.16.0
+class FileOperationPatternKind {
+  const FileOperationPatternKind(this._value);
+  const FileOperationPatternKind.fromJson(this._value);
+
+  final String _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is String;
+  }
+
+  /// The pattern matches a file only.
+  static const file = FileOperationPatternKind(r'file');
+
+  /// The pattern matches a folder only.
+  static const folder = FileOperationPatternKind(r'folder');
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) =>
+      o is FileOperationPatternKind && o._value == _value;
+}
+
+/// Matching options for the file operation pattern.
+///  @since 3.16.0
+class FileOperationPatternOptions implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      FileOperationPatternOptions.canParse,
+      FileOperationPatternOptions.fromJson);
+
+  FileOperationPatternOptions({this.ignoreCase});
+  static FileOperationPatternOptions fromJson(Map<String, dynamic> json) {
+    final ignoreCase = json['ignoreCase'];
+    return FileOperationPatternOptions(ignoreCase: ignoreCase);
+  }
+
+  /// The pattern should be matched ignoring casing.
+  final bool ignoreCase;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (ignoreCase != null) {
+      __result['ignoreCase'] = ignoreCase;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('ignoreCase');
+      try {
+        if (obj['ignoreCase'] != null && !(obj['ignoreCase'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type FileOperationPatternOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is FileOperationPatternOptions &&
+        other.runtimeType == FileOperationPatternOptions) {
+      return ignoreCase == other.ignoreCase && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, ignoreCase.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// The options to register for file operations.
+///  @since 3.16.0
+class FileOperationRegistrationOptions implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      FileOperationRegistrationOptions.canParse,
+      FileOperationRegistrationOptions.fromJson);
+
+  FileOperationRegistrationOptions({@required this.filters}) {
+    if (filters == null) {
+      throw 'filters is required but was not provided';
+    }
+  }
+  static FileOperationRegistrationOptions fromJson(Map<String, dynamic> json) {
+    final filters = json['filters']
+        ?.map(
+            (item) => item != null ? FileOperationFilter.fromJson(item) : null)
+        ?.cast<FileOperationFilter>()
+        ?.toList();
+    return FileOperationRegistrationOptions(filters: filters);
+  }
+
+  /// The actual filters.
+  final List<FileOperationFilter> filters;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['filters'] =
+        filters ?? (throw 'filters is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('filters');
+      try {
+        if (!obj.containsKey('filters')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['filters'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['filters'] is List &&
+            (obj['filters'].every(
+                (item) => FileOperationFilter.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<FileOperationFilter>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type FileOperationRegistrationOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is FileOperationRegistrationOptions &&
+        other.runtimeType == FileOperationRegistrationOptions) {
+      return listEqual(filters, other.filters,
+              (FileOperationFilter a, FileOperationFilter b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(filters));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// Represents information on a file/folder rename.
+///  @since 3.16.0
+class FileRename implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(FileRename.canParse, FileRename.fromJson);
+
+  FileRename({@required this.oldUri, @required this.newUri}) {
+    if (oldUri == null) {
+      throw 'oldUri is required but was not provided';
+    }
+    if (newUri == null) {
+      throw 'newUri is required but was not provided';
+    }
+  }
+  static FileRename fromJson(Map<String, dynamic> json) {
+    final oldUri = json['oldUri'];
+    final newUri = json['newUri'];
+    return FileRename(oldUri: oldUri, newUri: newUri);
+  }
+
+  /// A file:// URI for the new location of the file/folder being renamed.
+  final String newUri;
+
+  /// A file:// URI for the original location of the file/folder being renamed.
+  final String oldUri;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['oldUri'] = oldUri ?? (throw 'oldUri is required but was not set');
+    __result['newUri'] = newUri ?? (throw 'newUri is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('oldUri');
+      try {
+        if (!obj.containsKey('oldUri')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['oldUri'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['oldUri'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('newUri');
+      try {
+        if (!obj.containsKey('newUri')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['newUri'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['newUri'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type FileRename');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is FileRename && other.runtimeType == FileRename) {
+      return oldUri == other.oldUri && newUri == other.newUri && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, oldUri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, newUri.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class FileSystemWatcher implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(FileSystemWatcher.canParse, FileSystemWatcher.fromJson);
@@ -11418,8 +15106,8 @@
   /// - `[]` to declare a range of characters to match in a path segment
   ///   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
   /// - `[!...]` to negate a range of characters to match in a path segment
-  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`,
-  ///    but not `example.0`)
+  ///   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not
+  ///   `example.0`)
   final String globPattern;
 
   /// The kind of events of interest. If omitted it defaults to WatchKind.Create
@@ -11492,7 +15180,9 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
-/// Represents a folding range.
+/// Represents a folding range. To be valid, start and end line must be bigger
+/// than zero and smaller than the number of lines in the document. Clients are
+/// free to ignore invalid ranges.
 class FoldingRange implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(FoldingRange.canParse, FoldingRange.fromJson);
@@ -11529,7 +15219,9 @@
   /// defined, defaults to the length of the end line.
   final num endCharacter;
 
-  /// The zero-based line number where the folded range ends.
+  /// The zero-based end line of the range to fold. The folded area ends with
+  /// the line's last character. To be valid, the end must be zero or larger and
+  /// smaller than the number of lines in the document.
   final num endLine;
 
   /// Describes the kind of the folding range such as `comment` or `region`. The
@@ -11542,7 +15234,9 @@
   /// defined, defaults to the length of the start line.
   final num startCharacter;
 
-  /// The zero-based line number from where the folded range starts.
+  /// The zero-based start line of the range to fold. The folded area starts
+  /// after the line's last character. To be valid, the end must be zero or
+  /// larger and smaller than the number of lines in the document.
   final num startLine;
 
   Map<String, dynamic> toJson() {
@@ -11679,15 +15373,15 @@
         lineFoldingOnly: lineFoldingOnly);
   }
 
-  /// Whether the implementation supports dynamic registration for folding range
-  /// providers. If this is set to `true`, the client supports the new
+  /// Whether implementation supports dynamic registration for folding range
+  /// providers. If this is set to `true` the client supports the new
   /// `FoldingRangeRegistrationOptions` return value for the corresponding
   /// server capability as well.
   final bool dynamicRegistration;
 
   /// If set, the client signals that it only supports folding complete lines.
-  /// If set, the client will ignore specified `startCharacter` and
-  /// `endCharacter` properties in a FoldingRange.
+  /// If set, client will ignore specified `startCharacter` and `endCharacter`
+  /// properties in a FoldingRange.
   final bool lineFoldingOnly;
 
   /// The maximum number of folding ranges that the client prefers to receive
@@ -11902,8 +15596,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The text document.
@@ -12024,7 +15718,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// The id used to register the request. The id can be used to deregister the
@@ -12393,8 +16087,9 @@
         dynamicRegistration: dynamicRegistration, contentFormat: contentFormat);
   }
 
-  /// Client supports the follow content formats for the content property. The
-  /// order describes the preferred format of the client.
+  /// Client supports the follow content formats if the content property refers
+  /// to a `literal of type MarkupContent`. The order describes the preferred
+  /// format of the client.
   final List<MarkupKind> contentFormat;
 
   /// Whether hover supports dynamic registration.
@@ -12678,7 +16373,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
   final bool workDoneProgress;
 
@@ -12765,7 +16460,7 @@
   }
 
   /// Whether implementation supports dynamic registration. If this is set to
-  /// `true`, the client supports the new `ImplementationRegistrationOptions`
+  /// `true` the client supports the new `ImplementationRegistrationOptions`
   /// return value for the corresponding server capability as well.
   final bool dynamicRegistration;
 
@@ -12945,8 +16640,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The position inside the text document.
@@ -13091,7 +16786,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// The id used to register the request. The id can be used to deregister the
@@ -13188,6 +16883,7 @@
   InitializeParams(
       {this.processId,
       this.clientInfo,
+      this.locale,
       this.rootPath,
       this.rootUri,
       this.initializationOptions,
@@ -13204,16 +16900,17 @@
     final clientInfo = json['clientInfo'] != null
         ? InitializeParamsClientInfo.fromJson(json['clientInfo'])
         : null;
+    final locale = json['locale'];
     final rootPath = json['rootPath'];
     final rootUri = json['rootUri'];
     final initializationOptions = json['initializationOptions'];
     final capabilities = json['capabilities'] != null
         ? ClientCapabilities.fromJson(json['capabilities'])
         : null;
-    final trace = const {null, 'off', 'messages', 'verbose'}
+    final trace = const {null, 'off', 'message', 'verbose'}
             .contains(json['trace'])
         ? json['trace']
-        : throw '''${json['trace']} was not one of (null, 'off', 'messages', 'verbose')''';
+        : throw '''${json['trace']} was not one of (null, 'off', 'message', 'verbose')''';
     final workspaceFolders = json['workspaceFolders']
         ?.map((item) => item != null ? WorkspaceFolder.fromJson(item) : null)
         ?.cast<WorkspaceFolder>()
@@ -13228,6 +16925,7 @@
     return InitializeParams(
         processId: processId,
         clientInfo: clientInfo,
+        locale: locale,
         rootPath: rootPath,
         rootUri: rootUri,
         initializationOptions: initializationOptions,
@@ -13247,18 +16945,27 @@
   /// User provided initialization options.
   final dynamic initializationOptions;
 
-  /// The process ID of the parent process that started the server. Is null if
+  /// The locale the client is currently showing the user interface in. This
+  /// must not necessarily be the locale of the operating system.
+  ///
+  /// Uses IETF language tags as the value's syntax (See
+  /// https://en.wikipedia.org/wiki/IETF_language_tag)
+  ///  @since 3.16.0
+  final String locale;
+
+  /// The process Id of the parent process that started the server. Is null if
   /// the process has not been started by another process. If the parent process
-  /// is not alive, then the server should exit (see exit notification) its
+  /// is not alive then the server should exit (see exit notification) its
   /// process.
   final num processId;
 
   /// The rootPath of the workspace. Is null if no folder is open.
-  ///  @deprecated in favour of rootUri.
+  ///  @deprecated in favour of `rootUri`.
   final String rootPath;
 
   /// The rootUri of the workspace. Is null if no folder is open. If both
   /// `rootPath` and `rootUri` are set `rootUri` wins.
+  ///  @deprecated in favour of `workspaceFolders`
   final String rootUri;
 
   /// The initial trace setting. If omitted trace is disabled ('off').
@@ -13280,6 +16987,9 @@
     if (clientInfo != null) {
       __result['clientInfo'] = clientInfo.toJson();
     }
+    if (locale != null) {
+      __result['locale'] = locale;
+    }
     if (rootPath != null) {
       __result['rootPath'] = rootPath;
     }
@@ -13327,6 +17037,15 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('locale');
+      try {
+        if (obj['locale'] != null && !(obj['locale'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('rootPath');
       try {
         if (obj['rootPath'] != null && !(obj['rootPath'] is String)) {
@@ -13379,10 +17098,9 @@
       try {
         if (obj['trace'] != null &&
             !((obj['trace'] == 'off' ||
-                obj['trace'] == 'messages' ||
+                obj['trace'] == 'message' ||
                 obj['trace'] == 'verbose'))) {
-          reporter.reportError(
-              'must be one of the literals \'off\', \'messages\', \'verbose\'');
+          reporter.reportError('must be of type String');
           return false;
         }
       } finally {
@@ -13423,6 +17141,7 @@
     if (other is InitializeParams && other.runtimeType == InitializeParams) {
       return processId == other.processId &&
           clientInfo == other.clientInfo &&
+          locale == other.locale &&
           rootPath == other.rootPath &&
           rootUri == other.rootUri &&
           initializationOptions == other.initializationOptions &&
@@ -13441,6 +17160,7 @@
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, processId.hashCode);
     hash = JenkinsSmiHash.combine(hash, clientInfo.hashCode);
+    hash = JenkinsSmiHash.combine(hash, locale.hashCode);
     hash = JenkinsSmiHash.combine(hash, rootPath.hashCode);
     hash = JenkinsSmiHash.combine(hash, rootUri.hashCode);
     hash = JenkinsSmiHash.combine(hash, initializationOptions.hashCode);
@@ -13762,6 +17482,138 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// A special text edit to provide an insert and a replace operation.
+///  @since 3.16.0
+class InsertReplaceEdit implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(InsertReplaceEdit.canParse, InsertReplaceEdit.fromJson);
+
+  InsertReplaceEdit(
+      {@required this.newText, @required this.insert, @required this.replace}) {
+    if (newText == null) {
+      throw 'newText is required but was not provided';
+    }
+    if (insert == null) {
+      throw 'insert is required but was not provided';
+    }
+    if (replace == null) {
+      throw 'replace is required but was not provided';
+    }
+  }
+  static InsertReplaceEdit fromJson(Map<String, dynamic> json) {
+    final newText = json['newText'];
+    final insert =
+        json['insert'] != null ? Range.fromJson(json['insert']) : null;
+    final replace =
+        json['replace'] != null ? Range.fromJson(json['replace']) : null;
+    return InsertReplaceEdit(
+        newText: newText, insert: insert, replace: replace);
+  }
+
+  /// The range if the insert is requested
+  final Range insert;
+
+  /// The string to be inserted.
+  final String newText;
+
+  /// The range if the replace is requested.
+  final Range replace;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['newText'] =
+        newText ?? (throw 'newText is required but was not set');
+    __result['insert'] =
+        insert?.toJson() ?? (throw 'insert is required but was not set');
+    __result['replace'] =
+        replace?.toJson() ?? (throw 'replace is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('newText');
+      try {
+        if (!obj.containsKey('newText')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['newText'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['newText'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('insert');
+      try {
+        if (!obj.containsKey('insert')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['insert'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Range.canParse(obj['insert'], reporter))) {
+          reporter.reportError('must be of type Range');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('replace');
+      try {
+        if (!obj.containsKey('replace')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['replace'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Range.canParse(obj['replace'], reporter))) {
+          reporter.reportError('must be of type Range');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type InsertReplaceEdit');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is InsertReplaceEdit && other.runtimeType == InsertReplaceEdit) {
+      return newText == other.newText &&
+          insert == other.insert &&
+          replace == other.replace &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, newText.hashCode);
+    hash = JenkinsSmiHash.combine(hash, insert.hashCode);
+    hash = JenkinsSmiHash.combine(hash, replace.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 /// Defines whether the insert text in a completion item should be interpreted
 /// as plain text or a snippet.
 class InsertTextFormat {
@@ -13801,6 +17653,522 @@
   bool operator ==(Object o) => o is InsertTextFormat && o._value == _value;
 }
 
+/// How whitespace and indentation is handled during completion item insertion.
+///  @since 3.16.0
+class InsertTextMode {
+  const InsertTextMode(this._value);
+  const InsertTextMode.fromJson(this._value);
+
+  final num _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is num;
+  }
+
+  /// The insertion or replace strings is taken as it is. If the value is multi
+  /// line the lines below the cursor will be inserted using the indentation
+  /// defined in the string value. The client will not apply any kind of
+  /// adjustments to the string.
+  static const asIs = InsertTextMode(1);
+
+  /// The editor adjusts leading whitespace of new lines so that they match the
+  /// indentation up to the cursor of the line for which the item is accepted.
+  ///
+  /// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a multi
+  /// line completion item is indented using 2 tabs and all following lines
+  /// inserted will be indented using 2 tabs as well.
+  static const adjustIndentation = InsertTextMode(2);
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) => o is InsertTextMode && o._value == _value;
+}
+
+class LinkedEditingRangeClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      LinkedEditingRangeClientCapabilities.canParse,
+      LinkedEditingRangeClientCapabilities.fromJson);
+
+  LinkedEditingRangeClientCapabilities({this.dynamicRegistration});
+  static LinkedEditingRangeClientCapabilities fromJson(
+      Map<String, dynamic> json) {
+    final dynamicRegistration = json['dynamicRegistration'];
+    return LinkedEditingRangeClientCapabilities(
+        dynamicRegistration: dynamicRegistration);
+  }
+
+  /// Whether implementation supports dynamic registration. If this is set to
+  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
+  /// StaticRegistrationOptions)` return value for the corresponding server
+  /// capability as well.
+  final bool dynamicRegistration;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (dynamicRegistration != null) {
+      __result['dynamicRegistration'] = dynamicRegistration;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('dynamicRegistration');
+      try {
+        if (obj['dynamicRegistration'] != null &&
+            !(obj['dynamicRegistration'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter
+          .reportError('must be of type LinkedEditingRangeClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is LinkedEditingRangeClientCapabilities &&
+        other.runtimeType == LinkedEditingRangeClientCapabilities) {
+      return dynamicRegistration == other.dynamicRegistration && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class LinkedEditingRangeOptions implements WorkDoneProgressOptions, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      LinkedEditingRangeOptions.canParse, LinkedEditingRangeOptions.fromJson);
+
+  LinkedEditingRangeOptions({this.workDoneProgress});
+  static LinkedEditingRangeOptions fromJson(Map<String, dynamic> json) {
+    if (LinkedEditingRangeRegistrationOptions.canParse(
+        json, nullLspJsonReporter)) {
+      return LinkedEditingRangeRegistrationOptions.fromJson(json);
+    }
+    final workDoneProgress = json['workDoneProgress'];
+    return LinkedEditingRangeOptions(workDoneProgress: workDoneProgress);
+  }
+
+  final bool workDoneProgress;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (workDoneProgress != null) {
+      __result['workDoneProgress'] = workDoneProgress;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('workDoneProgress');
+      try {
+        if (obj['workDoneProgress'] != null &&
+            !(obj['workDoneProgress'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type LinkedEditingRangeOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is LinkedEditingRangeOptions &&
+        other.runtimeType == LinkedEditingRangeOptions) {
+      return workDoneProgress == other.workDoneProgress && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class LinkedEditingRangeParams
+    implements TextDocumentPositionParams, WorkDoneProgressParams, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      LinkedEditingRangeParams.canParse, LinkedEditingRangeParams.fromJson);
+
+  LinkedEditingRangeParams(
+      {@required this.textDocument,
+      @required this.position,
+      this.workDoneToken}) {
+    if (textDocument == null) {
+      throw 'textDocument is required but was not provided';
+    }
+    if (position == null) {
+      throw 'position is required but was not provided';
+    }
+  }
+  static LinkedEditingRangeParams fromJson(Map<String, dynamic> json) {
+    final textDocument = json['textDocument'] != null
+        ? TextDocumentIdentifier.fromJson(json['textDocument'])
+        : null;
+    final position =
+        json['position'] != null ? Position.fromJson(json['position']) : null;
+    final workDoneToken = json['workDoneToken'] is num
+        ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is String
+            ? Either2<num, String>.t2(json['workDoneToken'])
+            : (json['workDoneToken'] == null
+                ? null
+                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+    return LinkedEditingRangeParams(
+        textDocument: textDocument,
+        position: position,
+        workDoneToken: workDoneToken);
+  }
+
+  /// The position inside the text document.
+  final Position position;
+
+  /// The text document.
+  final TextDocumentIdentifier textDocument;
+
+  /// An optional token that a server can use to report work done progress.
+  final Either2<num, String> workDoneToken;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    __result['position'] =
+        position?.toJson() ?? (throw 'position is required but was not set');
+    if (workDoneToken != null) {
+      __result['workDoneToken'] = workDoneToken;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('textDocument');
+      try {
+        if (!obj.containsKey('textDocument')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['textDocument'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
+          reporter.reportError('must be of type TextDocumentIdentifier');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('position');
+      try {
+        if (!obj.containsKey('position')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['position'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Position.canParse(obj['position'], reporter))) {
+          reporter.reportError('must be of type Position');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneToken');
+      try {
+        if (obj['workDoneToken'] != null &&
+            !((obj['workDoneToken'] is num ||
+                obj['workDoneToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type LinkedEditingRangeParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is LinkedEditingRangeParams &&
+        other.runtimeType == LinkedEditingRangeParams) {
+      return textDocument == other.textDocument &&
+          position == other.position &&
+          workDoneToken == other.workDoneToken &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
+    hash = JenkinsSmiHash.combine(hash, position.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class LinkedEditingRangeRegistrationOptions
+    implements
+        TextDocumentRegistrationOptions,
+        LinkedEditingRangeOptions,
+        StaticRegistrationOptions,
+        ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      LinkedEditingRangeRegistrationOptions.canParse,
+      LinkedEditingRangeRegistrationOptions.fromJson);
+
+  LinkedEditingRangeRegistrationOptions(
+      {this.documentSelector, this.workDoneProgress, this.id});
+  static LinkedEditingRangeRegistrationOptions fromJson(
+      Map<String, dynamic> json) {
+    final documentSelector = json['documentSelector']
+        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
+        ?.cast<DocumentFilter>()
+        ?.toList();
+    final workDoneProgress = json['workDoneProgress'];
+    final id = json['id'];
+    return LinkedEditingRangeRegistrationOptions(
+        documentSelector: documentSelector,
+        workDoneProgress: workDoneProgress,
+        id: id);
+  }
+
+  /// A document selector to identify the scope of the registration. If set to
+  /// null the document selector provided on the client side will be used.
+  final List<DocumentFilter> documentSelector;
+
+  /// The id used to register the request. The id can be used to deregister the
+  /// request again. See also Registration#id.
+  final String id;
+  final bool workDoneProgress;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['documentSelector'] = documentSelector;
+    if (workDoneProgress != null) {
+      __result['workDoneProgress'] = workDoneProgress;
+    }
+    if (id != null) {
+      __result['id'] = id;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('documentSelector');
+      try {
+        if (!obj.containsKey('documentSelector')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['documentSelector'] != null &&
+            !((obj['documentSelector'] is List &&
+                (obj['documentSelector'].every(
+                    (item) => DocumentFilter.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<DocumentFilter>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneProgress');
+      try {
+        if (obj['workDoneProgress'] != null &&
+            !(obj['workDoneProgress'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('id');
+      try {
+        if (obj['id'] != null && !(obj['id'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter
+          .reportError('must be of type LinkedEditingRangeRegistrationOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is LinkedEditingRangeRegistrationOptions &&
+        other.runtimeType == LinkedEditingRangeRegistrationOptions) {
+      return listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
+          workDoneProgress == other.workDoneProgress &&
+          id == other.id &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
+    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class LinkedEditingRanges implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      LinkedEditingRanges.canParse, LinkedEditingRanges.fromJson);
+
+  LinkedEditingRanges({@required this.ranges, this.wordPattern}) {
+    if (ranges == null) {
+      throw 'ranges is required but was not provided';
+    }
+  }
+  static LinkedEditingRanges fromJson(Map<String, dynamic> json) {
+    final ranges = json['ranges']
+        ?.map((item) => item != null ? Range.fromJson(item) : null)
+        ?.cast<Range>()
+        ?.toList();
+    final wordPattern = json['wordPattern'];
+    return LinkedEditingRanges(ranges: ranges, wordPattern: wordPattern);
+  }
+
+  /// A list of ranges that can be renamed together. The ranges must have
+  /// identical length and contain identical text content. The ranges cannot
+  /// overlap.
+  final List<Range> ranges;
+
+  /// An optional word pattern (regular expression) that describes valid
+  /// contents for the given ranges. If no pattern is provided, the client
+  /// configuration's word pattern will be used.
+  final String wordPattern;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['ranges'] = ranges ?? (throw 'ranges is required but was not set');
+    if (wordPattern != null) {
+      __result['wordPattern'] = wordPattern;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('ranges');
+      try {
+        if (!obj.containsKey('ranges')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['ranges'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['ranges'] is List &&
+            (obj['ranges'].every((item) => Range.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<Range>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('wordPattern');
+      try {
+        if (obj['wordPattern'] != null && !(obj['wordPattern'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type LinkedEditingRanges');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is LinkedEditingRanges &&
+        other.runtimeType == LinkedEditingRanges) {
+      return listEqual(ranges, other.ranges, (Range a, Range b) => a == b) &&
+          wordPattern == other.wordPattern &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(ranges));
+    hash = JenkinsSmiHash.combine(hash, wordPattern.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class Location implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(Location.canParse, Location.fromJson);
@@ -13936,15 +18304,15 @@
   /// range at the mouse position.
   final Range originSelectionRange;
 
-  /// The full target range of this link. For example, if the target is a
-  /// symbol, then target range is the range enclosing this symbol not including
+  /// The full target range of this link. If the target for example is a symbol
+  /// then target range is the range enclosing this symbol not including
   /// leading/trailing whitespace but everything else like comments. This
   /// information is typically used to highlight the range in the editor.
   final Range targetRange;
 
   /// The range that should be selected and revealed when this link is being
-  /// followed, for example, the name of a function. Must be contained by the
-  /// the `targetRange`. See also `DocumentSymbol#range`
+  /// followed, e.g the name of a function. Must be contained by the the
+  /// `targetRange`. See also `DocumentSymbol#range`
   final Range targetSelectionRange;
 
   /// The target resource identifier of this link.
@@ -14157,15 +18525,190 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
-/// A `MarkupContent` literal represents a string value, which content is
+class LogTraceParams implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(LogTraceParams.canParse, LogTraceParams.fromJson);
+
+  LogTraceParams({@required this.message, this.verbose}) {
+    if (message == null) {
+      throw 'message is required but was not provided';
+    }
+  }
+  static LogTraceParams fromJson(Map<String, dynamic> json) {
+    final message = json['message'];
+    final verbose = json['verbose'];
+    return LogTraceParams(message: message, verbose: verbose);
+  }
+
+  /// The message to be logged.
+  final String message;
+
+  /// Additional information that can be computed if the `trace` configuration
+  /// is set to `'verbose'`
+  final String verbose;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['message'] =
+        message ?? (throw 'message is required but was not set');
+    if (verbose != null) {
+      __result['verbose'] = verbose;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('message');
+      try {
+        if (!obj.containsKey('message')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['message'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['message'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('verbose');
+      try {
+        if (obj['verbose'] != null && !(obj['verbose'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type LogTraceParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is LogTraceParams && other.runtimeType == LogTraceParams) {
+      return message == other.message && verbose == other.verbose && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, message.hashCode);
+    hash = JenkinsSmiHash.combine(hash, verbose.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// Client capabilities specific to the used markdown parser.
+///  @since 3.16.0
+class MarkdownClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      MarkdownClientCapabilities.canParse, MarkdownClientCapabilities.fromJson);
+
+  MarkdownClientCapabilities({@required this.parser, this.version}) {
+    if (parser == null) {
+      throw 'parser is required but was not provided';
+    }
+  }
+  static MarkdownClientCapabilities fromJson(Map<String, dynamic> json) {
+    final parser = json['parser'];
+    final version = json['version'];
+    return MarkdownClientCapabilities(parser: parser, version: version);
+  }
+
+  /// The name of the parser.
+  final String parser;
+
+  /// The version of the parser.
+  final String version;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['parser'] = parser ?? (throw 'parser is required but was not set');
+    if (version != null) {
+      __result['version'] = version;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('parser');
+      try {
+        if (!obj.containsKey('parser')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['parser'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['parser'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('version');
+      try {
+        if (obj['version'] != null && !(obj['version'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type MarkdownClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is MarkdownClientCapabilities &&
+        other.runtimeType == MarkdownClientCapabilities) {
+      return parser == other.parser && version == other.version && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, parser.hashCode);
+    hash = JenkinsSmiHash.combine(hash, version.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// A `MarkupContent` literal represents a string value which content is
 /// interpreted base on its kind flag. Currently the protocol supports
 /// `plaintext` and `markdown` as markup kinds.
 ///
-/// If the kind is `markdown`, then the value can contain fenced code blocks
-/// like in GitHub issues.
+/// If the kind is `markdown` then the value can contain fenced code blocks like
+/// in GitHub issues.
 ///
-/// An example how such a string is constructed using JavaScript / TypeScript:
-/// ```typescript let markdown: MarkdownContent = {
+/// Here is an example how such a string can be constructed using JavaScript /
+/// TypeScript: ```typescript let markdown: MarkdownContent = {
 ///
 /// kind: MarkupKind.Markdown,
 /// 	value: [
@@ -14176,8 +18719,8 @@
 /// 		'```'
 /// 	].join('\n') }; ```
 ///
-/// *Please Note* that clients might sanitize the returned Markdown. A client
-/// could decide to remove HTML from the Markdown to avoid script execution.
+/// *Please Note* that clients might sanitize the return markdown. A client
+/// could decide to remove HTML from the markdown to avoid script execution.
 class MarkupContent implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(MarkupContent.canParse, MarkupContent.fromJson);
@@ -14517,12 +19060,21 @@
   /// Constant for the 'exit' method.
   static const exit = Method(r'exit');
 
+  /// Constant for the '$/logTrace' method.
+  static const logTrace = Method(r'$/logTrace');
+
+  /// Constant for the '$/setTrace' method.
+  static const setTrace = Method(r'$/setTrace');
+
   /// Constant for the 'window/showMessage' method.
   static const window_showMessage = Method(r'window/showMessage');
 
   /// Constant for the 'window/showMessageRequest' method.
   static const window_showMessageRequest = Method(r'window/showMessageRequest');
 
+  /// Constant for the 'window/showDocument' method.
+  static const window_showDocument = Method(r'window/showDocument');
+
   /// Constant for the 'window/logMessage' method.
   static const window_logMessage = Method(r'window/logMessage');
 
@@ -14572,6 +19124,24 @@
   /// Constant for the 'workspace/applyEdit' method.
   static const workspace_applyEdit = Method(r'workspace/applyEdit');
 
+  /// Constant for the 'workspace/willCreateFiles' method.
+  static const workspace_willCreateFiles = Method(r'workspace/willCreateFiles');
+
+  /// Constant for the 'workspace/didCreateFiles' method.
+  static const workspace_didCreateFiles = Method(r'workspace/didCreateFiles');
+
+  /// Constant for the 'workspace/willRenameFiles' method.
+  static const workspace_willRenameFiles = Method(r'workspace/willRenameFiles');
+
+  /// Constant for the 'workspace/didRenameFiles' method.
+  static const workspace_didRenameFiles = Method(r'workspace/didRenameFiles');
+
+  /// Constant for the 'workspace/willDeleteFiles' method.
+  static const workspace_willDeleteFiles = Method(r'workspace/willDeleteFiles');
+
+  /// Constant for the 'workspace/didDeleteFiles' method.
+  static const workspace_didDeleteFiles = Method(r'workspace/didDeleteFiles');
+
   /// Constant for the 'textDocument/didOpen' method.
   static const textDocument_didOpen = Method(r'textDocument/didOpen');
 
@@ -14636,12 +19206,19 @@
   /// Constant for the 'textDocument/codeAction' method.
   static const textDocument_codeAction = Method(r'textDocument/codeAction');
 
+  /// Constant for the 'codeAction/resolve' method.
+  static const codeAction_resolve = Method(r'codeAction/resolve');
+
   /// Constant for the 'textDocument/codeLens' method.
   static const textDocument_codeLens = Method(r'textDocument/codeLens');
 
   /// Constant for the 'codeLens/resolve' method.
   static const codeLens_resolve = Method(r'codeLens/resolve');
 
+  /// Constant for the 'workspace/codeLens/refresh' method.
+  static const workspace_codeLens_refresh =
+      Method(r'workspace/codeLens/refresh');
+
   /// Constant for the 'textDocument/documentLink' method.
   static const textDocument_documentLink = Method(r'textDocument/documentLink');
 
@@ -14681,6 +19258,41 @@
   static const textDocument_selectionRange =
       Method(r'textDocument/selectionRange');
 
+  /// Constant for the 'textDocument/prepareCallHierarchy' method.
+  static const textDocument_prepareCallHierarchy =
+      Method(r'textDocument/prepareCallHierarchy');
+
+  /// Constant for the 'callHierarchy/incomingCalls' method.
+  static const callHierarchy_incomingCalls =
+      Method(r'callHierarchy/incomingCalls');
+
+  /// Constant for the 'callHierarchy/outgoingCalls' method.
+  static const callHierarchy_outgoingCalls =
+      Method(r'callHierarchy/outgoingCalls');
+
+  /// Constant for the 'textDocument/semanticTokens/full' method.
+  static const textDocument_semanticTokens_full =
+      Method(r'textDocument/semanticTokens/full');
+
+  /// Constant for the 'textDocument/semanticTokens/full/delta' method.
+  static const textDocument_semanticTokens_full_delta =
+      Method(r'textDocument/semanticTokens/full/delta');
+
+  /// Constant for the 'textDocument/semanticTokens/range' method.
+  static const textDocument_semanticTokens_range =
+      Method(r'textDocument/semanticTokens/range');
+
+  /// Constant for the 'workspace/semanticTokens/refresh' method.
+  static const workspace_semanticTokens_refresh =
+      Method(r'workspace/semanticTokens/refresh');
+
+  /// Constant for the 'textDocument/linkedEditingRange' method.
+  static const textDocument_linkedEditingRange =
+      Method(r'textDocument/linkedEditingRange');
+
+  /// Constant for the 'textDocument/moniker' method.
+  static const textDocument_moniker = Method(r'textDocument/moniker');
+
   Object toJson() => _value;
 
   @override
@@ -14692,6 +19304,571 @@
   bool operator ==(Object o) => o is Method && o._value == _value;
 }
 
+/// Moniker definition to match LSIF 0.5 moniker definition.
+class Moniker implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(Moniker.canParse, Moniker.fromJson);
+
+  Moniker(
+      {@required this.scheme,
+      @required this.identifier,
+      @required this.unique,
+      this.kind}) {
+    if (scheme == null) {
+      throw 'scheme is required but was not provided';
+    }
+    if (identifier == null) {
+      throw 'identifier is required but was not provided';
+    }
+    if (unique == null) {
+      throw 'unique is required but was not provided';
+    }
+  }
+  static Moniker fromJson(Map<String, dynamic> json) {
+    final scheme = json['scheme'];
+    final identifier = json['identifier'];
+    final unique = json['unique'] != null
+        ? UniquenessLevel.fromJson(json['unique'])
+        : null;
+    final kind =
+        json['kind'] != null ? MonikerKind.fromJson(json['kind']) : null;
+    return Moniker(
+        scheme: scheme, identifier: identifier, unique: unique, kind: kind);
+  }
+
+  /// The identifier of the moniker. The value is opaque in LSIF however schema
+  /// owners are allowed to define the structure if they want.
+  final String identifier;
+
+  /// The moniker kind if known.
+  final MonikerKind kind;
+
+  /// The scheme of the moniker. For example tsc or .Net
+  final String scheme;
+
+  /// The scope in which the moniker is unique
+  final UniquenessLevel unique;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['scheme'] = scheme ?? (throw 'scheme is required but was not set');
+    __result['identifier'] =
+        identifier ?? (throw 'identifier is required but was not set');
+    __result['unique'] =
+        unique?.toJson() ?? (throw 'unique is required but was not set');
+    if (kind != null) {
+      __result['kind'] = kind.toJson();
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('scheme');
+      try {
+        if (!obj.containsKey('scheme')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['scheme'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['scheme'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('identifier');
+      try {
+        if (!obj.containsKey('identifier')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['identifier'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['identifier'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('unique');
+      try {
+        if (!obj.containsKey('unique')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['unique'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(UniquenessLevel.canParse(obj['unique'], reporter))) {
+          reporter.reportError('must be of type UniquenessLevel');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('kind');
+      try {
+        if (obj['kind'] != null &&
+            !(MonikerKind.canParse(obj['kind'], reporter))) {
+          reporter.reportError('must be of type MonikerKind');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type Moniker');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is Moniker && other.runtimeType == Moniker) {
+      return scheme == other.scheme &&
+          identifier == other.identifier &&
+          unique == other.unique &&
+          kind == other.kind &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, scheme.hashCode);
+    hash = JenkinsSmiHash.combine(hash, identifier.hashCode);
+    hash = JenkinsSmiHash.combine(hash, unique.hashCode);
+    hash = JenkinsSmiHash.combine(hash, kind.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class MonikerClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      MonikerClientCapabilities.canParse, MonikerClientCapabilities.fromJson);
+
+  MonikerClientCapabilities({this.dynamicRegistration});
+  static MonikerClientCapabilities fromJson(Map<String, dynamic> json) {
+    final dynamicRegistration = json['dynamicRegistration'];
+    return MonikerClientCapabilities(dynamicRegistration: dynamicRegistration);
+  }
+
+  /// Whether implementation supports dynamic registration. If this is set to
+  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
+  /// StaticRegistrationOptions)` return value for the corresponding server
+  /// capability as well.
+  final bool dynamicRegistration;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (dynamicRegistration != null) {
+      __result['dynamicRegistration'] = dynamicRegistration;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('dynamicRegistration');
+      try {
+        if (obj['dynamicRegistration'] != null &&
+            !(obj['dynamicRegistration'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type MonikerClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is MonikerClientCapabilities &&
+        other.runtimeType == MonikerClientCapabilities) {
+      return dynamicRegistration == other.dynamicRegistration && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// The moniker kind.
+class MonikerKind {
+  const MonikerKind(this._value);
+  const MonikerKind.fromJson(this._value);
+
+  final String _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is String;
+  }
+
+  /// The moniker represent a symbol that is imported into a project
+  static const import = MonikerKind(r'import');
+
+  /// The moniker represents a symbol that is exported from a project
+  static const export = MonikerKind(r'export');
+
+  /// The moniker represents a symbol that is local to a project (e.g. a local
+  /// variable of a function, a class not visible outside the project, ...)
+  static const local = MonikerKind(r'local');
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) => o is MonikerKind && o._value == _value;
+}
+
+class MonikerOptions implements WorkDoneProgressOptions, ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(MonikerOptions.canParse, MonikerOptions.fromJson);
+
+  MonikerOptions({this.workDoneProgress});
+  static MonikerOptions fromJson(Map<String, dynamic> json) {
+    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
+      return MonikerRegistrationOptions.fromJson(json);
+    }
+    final workDoneProgress = json['workDoneProgress'];
+    return MonikerOptions(workDoneProgress: workDoneProgress);
+  }
+
+  final bool workDoneProgress;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (workDoneProgress != null) {
+      __result['workDoneProgress'] = workDoneProgress;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('workDoneProgress');
+      try {
+        if (obj['workDoneProgress'] != null &&
+            !(obj['workDoneProgress'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type MonikerOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is MonikerOptions && other.runtimeType == MonikerOptions) {
+      return workDoneProgress == other.workDoneProgress && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class MonikerParams
+    implements
+        TextDocumentPositionParams,
+        WorkDoneProgressParams,
+        PartialResultParams,
+        ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(MonikerParams.canParse, MonikerParams.fromJson);
+
+  MonikerParams(
+      {@required this.textDocument,
+      @required this.position,
+      this.workDoneToken,
+      this.partialResultToken}) {
+    if (textDocument == null) {
+      throw 'textDocument is required but was not provided';
+    }
+    if (position == null) {
+      throw 'position is required but was not provided';
+    }
+  }
+  static MonikerParams fromJson(Map<String, dynamic> json) {
+    final textDocument = json['textDocument'] != null
+        ? TextDocumentIdentifier.fromJson(json['textDocument'])
+        : null;
+    final position =
+        json['position'] != null ? Position.fromJson(json['position']) : null;
+    final workDoneToken = json['workDoneToken'] is num
+        ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is String
+            ? Either2<num, String>.t2(json['workDoneToken'])
+            : (json['workDoneToken'] == null
+                ? null
+                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+    final partialResultToken = json['partialResultToken'] is num
+        ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is String
+            ? Either2<num, String>.t2(json['partialResultToken'])
+            : (json['partialResultToken'] == null
+                ? null
+                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+    return MonikerParams(
+        textDocument: textDocument,
+        position: position,
+        workDoneToken: workDoneToken,
+        partialResultToken: partialResultToken);
+  }
+
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
+  final Either2<num, String> partialResultToken;
+
+  /// The position inside the text document.
+  final Position position;
+
+  /// The text document.
+  final TextDocumentIdentifier textDocument;
+
+  /// An optional token that a server can use to report work done progress.
+  final Either2<num, String> workDoneToken;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    __result['position'] =
+        position?.toJson() ?? (throw 'position is required but was not set');
+    if (workDoneToken != null) {
+      __result['workDoneToken'] = workDoneToken;
+    }
+    if (partialResultToken != null) {
+      __result['partialResultToken'] = partialResultToken;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('textDocument');
+      try {
+        if (!obj.containsKey('textDocument')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['textDocument'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
+          reporter.reportError('must be of type TextDocumentIdentifier');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('position');
+      try {
+        if (!obj.containsKey('position')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['position'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Position.canParse(obj['position'], reporter))) {
+          reporter.reportError('must be of type Position');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneToken');
+      try {
+        if (obj['workDoneToken'] != null &&
+            !((obj['workDoneToken'] is num ||
+                obj['workDoneToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('partialResultToken');
+      try {
+        if (obj['partialResultToken'] != null &&
+            !((obj['partialResultToken'] is num ||
+                obj['partialResultToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type MonikerParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is MonikerParams && other.runtimeType == MonikerParams) {
+      return textDocument == other.textDocument &&
+          position == other.position &&
+          workDoneToken == other.workDoneToken &&
+          partialResultToken == other.partialResultToken &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
+    hash = JenkinsSmiHash.combine(hash, position.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
+    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class MonikerRegistrationOptions
+    implements TextDocumentRegistrationOptions, MonikerOptions, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      MonikerRegistrationOptions.canParse, MonikerRegistrationOptions.fromJson);
+
+  MonikerRegistrationOptions({this.documentSelector, this.workDoneProgress});
+  static MonikerRegistrationOptions fromJson(Map<String, dynamic> json) {
+    final documentSelector = json['documentSelector']
+        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
+        ?.cast<DocumentFilter>()
+        ?.toList();
+    final workDoneProgress = json['workDoneProgress'];
+    return MonikerRegistrationOptions(
+        documentSelector: documentSelector, workDoneProgress: workDoneProgress);
+  }
+
+  /// A document selector to identify the scope of the registration. If set to
+  /// null the document selector provided on the client side will be used.
+  final List<DocumentFilter> documentSelector;
+  final bool workDoneProgress;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['documentSelector'] = documentSelector;
+    if (workDoneProgress != null) {
+      __result['workDoneProgress'] = workDoneProgress;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('documentSelector');
+      try {
+        if (!obj.containsKey('documentSelector')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['documentSelector'] != null &&
+            !((obj['documentSelector'] is List &&
+                (obj['documentSelector'].every(
+                    (item) => DocumentFilter.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<DocumentFilter>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneProgress');
+      try {
+        if (obj['workDoneProgress'] != null &&
+            !(obj['workDoneProgress'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type MonikerRegistrationOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is MonikerRegistrationOptions &&
+        other.runtimeType == MonikerRegistrationOptions) {
+      return listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
+          workDoneProgress == other.workDoneProgress &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
+    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class NotificationMessage implements Message, IncomingMessage, ToJsonable {
   static const jsonHandler = LspJsonHandler(
       NotificationMessage.canParse, NotificationMessage.fromJson);
@@ -14811,6 +19988,106 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class OptionalVersionedTextDocumentIdentifier
+    implements TextDocumentIdentifier, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      OptionalVersionedTextDocumentIdentifier.canParse,
+      OptionalVersionedTextDocumentIdentifier.fromJson);
+
+  OptionalVersionedTextDocumentIdentifier({this.version, @required this.uri}) {
+    if (uri == null) {
+      throw 'uri is required but was not provided';
+    }
+  }
+  static OptionalVersionedTextDocumentIdentifier fromJson(
+      Map<String, dynamic> json) {
+    final version = json['version'];
+    final uri = json['uri'];
+    return OptionalVersionedTextDocumentIdentifier(version: version, uri: uri);
+  }
+
+  /// The text document's URI.
+  final String uri;
+
+  /// The version number of this document. If an optional versioned text
+  /// document identifier is sent from the server to the client and the file is
+  /// not open in the editor (the server has not received an open notification
+  /// before) the server can send `null` to indicate that the version is known
+  /// and the content on disk is the master (as specified with document content
+  /// ownership).
+  ///
+  /// The version number of a document will increase after each change,
+  /// including undo/redo. The number doesn't need to be consecutive.
+  final num version;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['version'] = version;
+    __result['uri'] = uri ?? (throw 'uri is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('version');
+      try {
+        if (!obj.containsKey('version')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['version'] != null && !(obj['version'] is num)) {
+          reporter.reportError('must be of type num');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('uri');
+      try {
+        if (!obj.containsKey('uri')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['uri'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['uri'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type OptionalVersionedTextDocumentIdentifier');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is OptionalVersionedTextDocumentIdentifier &&
+        other.runtimeType == OptionalVersionedTextDocumentIdentifier) {
+      return version == other.version && uri == other.uri && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, version.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 /// Represents a parameter of a callable-signature. A parameter can have a label
 /// and a doc-comment.
 class ParameterInformation implements ToJsonable {
@@ -14976,6 +20253,24 @@
     if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
       return SelectionRangeParams.fromJson(json);
     }
+    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyIncomingCallsParams.fromJson(json);
+    }
+    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyOutgoingCallsParams.fromJson(json);
+    }
+    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensParams.fromJson(json);
+    }
+    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensDeltaParams.fromJson(json);
+    }
+    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensRangeParams.fromJson(json);
+    }
+    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
+      return MonikerParams.fromJson(json);
+    }
     final partialResultToken = json['partialResultToken'] is num
         ? Either2<num, String>.t1(json['partialResultToken'])
         : (json['partialResultToken'] is String
@@ -14986,8 +20281,8 @@
     return PartialResultParams(partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   Map<String, dynamic> toJson() {
@@ -15240,6 +20535,32 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class PrepareSupportDefaultBehavior {
+  const PrepareSupportDefaultBehavior(this._value);
+  const PrepareSupportDefaultBehavior.fromJson(this._value);
+
+  final num _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is num;
+  }
+
+  /// The client's default behavior is to select the identifier according the to
+  /// language's syntax rule.
+  static const Identifier = PrepareSupportDefaultBehavior(1);
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) =>
+      o is PrepareSupportDefaultBehavior && o._value == _value;
+}
+
 class ProgressParams<T> implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(ProgressParams.canParse, ProgressParams.fromJson);
@@ -15344,7 +20665,11 @@
       PublishDiagnosticsClientCapabilities.fromJson);
 
   PublishDiagnosticsClientCapabilities(
-      {this.relatedInformation, this.tagSupport, this.versionSupport});
+      {this.relatedInformation,
+      this.tagSupport,
+      this.versionSupport,
+      this.codeDescriptionSupport,
+      this.dataSupport});
   static PublishDiagnosticsClientCapabilities fromJson(
       Map<String, dynamic> json) {
     final relatedInformation = json['relatedInformation'];
@@ -15353,12 +20678,26 @@
             json['tagSupport'])
         : null;
     final versionSupport = json['versionSupport'];
+    final codeDescriptionSupport = json['codeDescriptionSupport'];
+    final dataSupport = json['dataSupport'];
     return PublishDiagnosticsClientCapabilities(
         relatedInformation: relatedInformation,
         tagSupport: tagSupport,
-        versionSupport: versionSupport);
+        versionSupport: versionSupport,
+        codeDescriptionSupport: codeDescriptionSupport,
+        dataSupport: dataSupport);
   }
 
+  /// Client supports a codeDescription property
+  ///  @since 3.16.0
+  final bool codeDescriptionSupport;
+
+  /// Whether code action supports the `data` property which is preserved
+  /// between a `textDocument/publishDiagnostics` and `textDocument/codeAction`
+  /// request.
+  ///  @since 3.16.0
+  final bool dataSupport;
+
   /// Whether the clients accepts diagnostics with related information.
   final bool relatedInformation;
 
@@ -15383,6 +20722,12 @@
     if (versionSupport != null) {
       __result['versionSupport'] = versionSupport;
     }
+    if (codeDescriptionSupport != null) {
+      __result['codeDescriptionSupport'] = codeDescriptionSupport;
+    }
+    if (dataSupport != null) {
+      __result['dataSupport'] = dataSupport;
+    }
     return __result;
   }
 
@@ -15419,6 +20764,25 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('codeDescriptionSupport');
+      try {
+        if (obj['codeDescriptionSupport'] != null &&
+            !(obj['codeDescriptionSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('dataSupport');
+      try {
+        if (obj['dataSupport'] != null && !(obj['dataSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter
@@ -15434,6 +20798,8 @@
       return relatedInformation == other.relatedInformation &&
           tagSupport == other.tagSupport &&
           versionSupport == other.versionSupport &&
+          codeDescriptionSupport == other.codeDescriptionSupport &&
+          dataSupport == other.dataSupport &&
           true;
     }
     return false;
@@ -15445,6 +20811,8 @@
     hash = JenkinsSmiHash.combine(hash, relatedInformation.hashCode);
     hash = JenkinsSmiHash.combine(hash, tagSupport.hashCode);
     hash = JenkinsSmiHash.combine(hash, versionSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, codeDescriptionSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, dataSupport.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -15562,8 +20930,9 @@
   /// The URI for which diagnostic information is reported.
   final String uri;
 
-  /// The version number of the document the diagnostics are published for.
-  /// Optional. @since 3.15.0
+  /// Optional the version number of the document the diagnostics are published
+  /// for.
+  ///  @since 3.15.0
   final num version;
 
   Map<String, dynamic> toJson() {
@@ -16097,8 +21466,8 @@
 
   final ReferenceContext context;
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The position inside the text document.
@@ -16255,7 +21624,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
   final bool workDoneProgress;
 
@@ -16521,27 +21890,144 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// Client capabilities specific to regular expressions.
+class RegularExpressionsClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      RegularExpressionsClientCapabilities.canParse,
+      RegularExpressionsClientCapabilities.fromJson);
+
+  RegularExpressionsClientCapabilities({@required this.engine, this.version}) {
+    if (engine == null) {
+      throw 'engine is required but was not provided';
+    }
+  }
+  static RegularExpressionsClientCapabilities fromJson(
+      Map<String, dynamic> json) {
+    final engine = json['engine'];
+    final version = json['version'];
+    return RegularExpressionsClientCapabilities(
+        engine: engine, version: version);
+  }
+
+  /// The engine's name.
+  final String engine;
+
+  /// The engine's version.
+  final String version;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['engine'] = engine ?? (throw 'engine is required but was not set');
+    if (version != null) {
+      __result['version'] = version;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('engine');
+      try {
+        if (!obj.containsKey('engine')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['engine'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['engine'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('version');
+      try {
+        if (obj['version'] != null && !(obj['version'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter
+          .reportError('must be of type RegularExpressionsClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is RegularExpressionsClientCapabilities &&
+        other.runtimeType == RegularExpressionsClientCapabilities) {
+      return engine == other.engine && version == other.version && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, engine.hashCode);
+    hash = JenkinsSmiHash.combine(hash, version.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class RenameClientCapabilities implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       RenameClientCapabilities.canParse, RenameClientCapabilities.fromJson);
 
-  RenameClientCapabilities({this.dynamicRegistration, this.prepareSupport});
+  RenameClientCapabilities(
+      {this.dynamicRegistration,
+      this.prepareSupport,
+      this.prepareSupportDefaultBehavior,
+      this.honorsChangeAnnotations});
   static RenameClientCapabilities fromJson(Map<String, dynamic> json) {
     final dynamicRegistration = json['dynamicRegistration'];
     final prepareSupport = json['prepareSupport'];
+    final prepareSupportDefaultBehavior =
+        json['prepareSupportDefaultBehavior'] != null
+            ? PrepareSupportDefaultBehavior.fromJson(
+                json['prepareSupportDefaultBehavior'])
+            : null;
+    final honorsChangeAnnotations = json['honorsChangeAnnotations'];
     return RenameClientCapabilities(
         dynamicRegistration: dynamicRegistration,
-        prepareSupport: prepareSupport);
+        prepareSupport: prepareSupport,
+        prepareSupportDefaultBehavior: prepareSupportDefaultBehavior,
+        honorsChangeAnnotations: honorsChangeAnnotations);
   }
 
   /// Whether rename supports dynamic registration.
   final bool dynamicRegistration;
 
+  /// Whether th client honors the change annotations in text edits and resource
+  /// operations returned via the rename request's workspace edit by for example
+  /// presenting the workspace edit in the user interface and asking for
+  /// confirmation.
+  ///  @since 3.16.0
+  final bool honorsChangeAnnotations;
+
   /// Client supports testing for validity of rename operations before
   /// execution.
   ///  @since version 3.12.0
   final bool prepareSupport;
 
+  /// Client supports the default behavior result (`{ defaultBehavior: boolean
+  /// }`).
+  ///
+  /// The value indicates the default behavior used by the client.
+  ///  @since version 3.16.0
+  final PrepareSupportDefaultBehavior prepareSupportDefaultBehavior;
+
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (dynamicRegistration != null) {
@@ -16550,6 +22036,13 @@
     if (prepareSupport != null) {
       __result['prepareSupport'] = prepareSupport;
     }
+    if (prepareSupportDefaultBehavior != null) {
+      __result['prepareSupportDefaultBehavior'] =
+          prepareSupportDefaultBehavior.toJson();
+    }
+    if (honorsChangeAnnotations != null) {
+      __result['honorsChangeAnnotations'] = honorsChangeAnnotations;
+    }
     return __result;
   }
 
@@ -16574,6 +22067,27 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('prepareSupportDefaultBehavior');
+      try {
+        if (obj['prepareSupportDefaultBehavior'] != null &&
+            !(PrepareSupportDefaultBehavior.canParse(
+                obj['prepareSupportDefaultBehavior'], reporter))) {
+          reporter.reportError('must be of type PrepareSupportDefaultBehavior');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('honorsChangeAnnotations');
+      try {
+        if (obj['honorsChangeAnnotations'] != null &&
+            !(obj['honorsChangeAnnotations'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type RenameClientCapabilities');
@@ -16587,6 +22101,9 @@
         other.runtimeType == RenameClientCapabilities) {
       return dynamicRegistration == other.dynamicRegistration &&
           prepareSupport == other.prepareSupport &&
+          prepareSupportDefaultBehavior ==
+              other.prepareSupportDefaultBehavior &&
+          honorsChangeAnnotations == other.honorsChangeAnnotations &&
           true;
     }
     return false;
@@ -16597,6 +22114,8 @@
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
     hash = JenkinsSmiHash.combine(hash, prepareSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, prepareSupportDefaultBehavior.hashCode);
+    hash = JenkinsSmiHash.combine(hash, honorsChangeAnnotations.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -16613,7 +22132,8 @@
       {this.kind = 'rename',
       @required this.oldUri,
       @required this.newUri,
-      this.options}) {
+      this.options,
+      this.annotationId}) {
     if (kind != 'rename') {
       throw 'kind may only be the literal \'rename\'';
     }
@@ -16631,10 +22151,19 @@
     final options = json['options'] != null
         ? RenameFileOptions.fromJson(json['options'])
         : null;
+    final annotationId = json['annotationId'];
     return RenameFile(
-        kind: kind, oldUri: oldUri, newUri: newUri, options: options);
+        kind: kind,
+        oldUri: oldUri,
+        newUri: newUri,
+        options: options,
+        annotationId: annotationId);
   }
 
+  /// An optional annotation identifer describing the operation.
+  ///  @since 3.16.0
+  final String annotationId;
+
   /// A rename
   final String kind;
 
@@ -16655,6 +22184,9 @@
     if (options != null) {
       __result['options'] = options.toJson();
     }
+    if (annotationId != null) {
+      __result['annotationId'] = annotationId;
+    }
     return __result;
   }
 
@@ -16721,6 +22253,15 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('annotationId');
+      try {
+        if (obj['annotationId'] != null && !(obj['annotationId'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type RenameFile');
@@ -16735,6 +22276,7 @@
           oldUri == other.oldUri &&
           newUri == other.newUri &&
           options == other.options &&
+          annotationId == other.annotationId &&
           true;
     }
     return false;
@@ -16747,6 +22289,7 @@
     hash = JenkinsSmiHash.combine(hash, oldUri.hashCode);
     hash = JenkinsSmiHash.combine(hash, newUri.hashCode);
     hash = JenkinsSmiHash.combine(hash, options.hashCode);
+    hash = JenkinsSmiHash.combine(hash, annotationId.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -16833,6 +22376,85 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// The parameters sent in notifications/requests for user-initiated renames of
+/// files.
+///  @since 3.16.0
+class RenameFilesParams implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(RenameFilesParams.canParse, RenameFilesParams.fromJson);
+
+  RenameFilesParams({@required this.files}) {
+    if (files == null) {
+      throw 'files is required but was not provided';
+    }
+  }
+  static RenameFilesParams fromJson(Map<String, dynamic> json) {
+    final files = json['files']
+        ?.map((item) => item != null ? FileRename.fromJson(item) : null)
+        ?.cast<FileRename>()
+        ?.toList();
+    return RenameFilesParams(files: files);
+  }
+
+  /// An array of all files/folders renamed in this operation. When a folder is
+  /// renamed, only the folder will be included, and not its children.
+  final List<FileRename> files;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['files'] = files ?? (throw 'files is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('files');
+      try {
+        if (!obj.containsKey('files')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['files'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['files'] is List &&
+            (obj['files']
+                .every((item) => FileRename.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<FileRename>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type RenameFilesParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is RenameFilesParams && other.runtimeType == RenameFilesParams) {
+      return listEqual(
+              files, other.files, (FileRename a, FileRename b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(files));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class RenameOptions implements WorkDoneProgressOptions, ToJsonable {
   static const jsonHandler =
       LspJsonHandler(RenameOptions.canParse, RenameOptions.fromJson);
@@ -17100,7 +22722,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// Renames should be checked and tested before being executed.
@@ -17791,7 +23413,7 @@
   }
 
   /// Whether implementation supports dynamic registration for selection range
-  /// providers. If set to `true`, the client supports the new
+  /// providers. If this is set to `true` the client supports the new
   /// `SelectionRangeRegistrationOptions` return value for the corresponding
   /// server capability as well.
   final bool dynamicRegistration;
@@ -17951,8 +23573,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The positions inside the text document.
@@ -18100,7 +23722,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// The id used to register the request. The id can be used to deregister the
@@ -18190,6 +23812,2115 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class SemanticTokenModifiers {
+  const SemanticTokenModifiers(this._value);
+  const SemanticTokenModifiers.fromJson(this._value);
+
+  final String _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is String;
+  }
+
+  static const declaration = SemanticTokenModifiers(r'declaration');
+  static const definition = SemanticTokenModifiers(r'definition');
+  static const readonly = SemanticTokenModifiers(r'readonly');
+  static const static = SemanticTokenModifiers(r'static');
+  static const deprecated = SemanticTokenModifiers(r'deprecated');
+  static const abstract = SemanticTokenModifiers(r'abstract');
+  static const async = SemanticTokenModifiers(r'async');
+  static const modification = SemanticTokenModifiers(r'modification');
+  static const documentation = SemanticTokenModifiers(r'documentation');
+  static const defaultLibrary = SemanticTokenModifiers(r'defaultLibrary');
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) =>
+      o is SemanticTokenModifiers && o._value == _value;
+}
+
+class SemanticTokenTypes {
+  const SemanticTokenTypes(this._value);
+  const SemanticTokenTypes.fromJson(this._value);
+
+  final String _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is String;
+  }
+
+  static const namespace = SemanticTokenTypes(r'namespace');
+
+  /// Represents a generic type. Acts as a fallback for types which can't be
+  /// mapped to a specific type like class or enum.
+  static const type = SemanticTokenTypes(r'type');
+  static const class_ = SemanticTokenTypes(r'class');
+  static const enum_ = SemanticTokenTypes(r'enum');
+  static const interface = SemanticTokenTypes(r'interface');
+  static const struct = SemanticTokenTypes(r'struct');
+  static const typeParameter = SemanticTokenTypes(r'typeParameter');
+  static const parameter = SemanticTokenTypes(r'parameter');
+  static const variable = SemanticTokenTypes(r'variable');
+  static const property = SemanticTokenTypes(r'property');
+  static const enumMember = SemanticTokenTypes(r'enumMember');
+  static const event = SemanticTokenTypes(r'event');
+  static const function = SemanticTokenTypes(r'function');
+  static const method = SemanticTokenTypes(r'method');
+  static const macro = SemanticTokenTypes(r'macro');
+  static const keyword = SemanticTokenTypes(r'keyword');
+  static const modifier = SemanticTokenTypes(r'modifier');
+  static const comment = SemanticTokenTypes(r'comment');
+  static const string = SemanticTokenTypes(r'string');
+  static const number = SemanticTokenTypes(r'number');
+  static const regexp = SemanticTokenTypes(r'regexp');
+  static const operator = SemanticTokenTypes(r'operator');
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) => o is SemanticTokenTypes && o._value == _value;
+}
+
+class SemanticTokens implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(SemanticTokens.canParse, SemanticTokens.fromJson);
+
+  SemanticTokens({this.resultId, @required this.data}) {
+    if (data == null) {
+      throw 'data is required but was not provided';
+    }
+  }
+  static SemanticTokens fromJson(Map<String, dynamic> json) {
+    final resultId = json['resultId'];
+    final data = json['data']?.map((item) => item)?.cast<num>()?.toList();
+    return SemanticTokens(resultId: resultId, data: data);
+  }
+
+  /// The actual tokens.
+  final List<num> data;
+
+  /// An optional result id. If provided and clients support delta updating the
+  /// client will include the result id in the next semantic token request. A
+  /// server can then instead of computing all semantic tokens again simply send
+  /// a delta.
+  final String resultId;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (resultId != null) {
+      __result['resultId'] = resultId;
+    }
+    __result['data'] = data ?? (throw 'data is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('resultId');
+      try {
+        if (obj['resultId'] != null && !(obj['resultId'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('data');
+      try {
+        if (!obj.containsKey('data')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['data'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['data'] is List &&
+            (obj['data'].every((item) => item is num))))) {
+          reporter.reportError('must be of type List<num>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokens');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokens && other.runtimeType == SemanticTokens) {
+      return resultId == other.resultId &&
+          listEqual(data, other.data, (num a, num b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, resultId.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(data));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensClientCapabilities.canParse,
+      SemanticTokensClientCapabilities.fromJson);
+
+  SemanticTokensClientCapabilities(
+      {this.dynamicRegistration,
+      @required this.requests,
+      @required this.tokenTypes,
+      @required this.tokenModifiers,
+      @required this.formats,
+      this.overlappingTokenSupport,
+      this.multilineTokenSupport}) {
+    if (requests == null) {
+      throw 'requests is required but was not provided';
+    }
+    if (tokenTypes == null) {
+      throw 'tokenTypes is required but was not provided';
+    }
+    if (tokenModifiers == null) {
+      throw 'tokenModifiers is required but was not provided';
+    }
+    if (formats == null) {
+      throw 'formats is required but was not provided';
+    }
+  }
+  static SemanticTokensClientCapabilities fromJson(Map<String, dynamic> json) {
+    final dynamicRegistration = json['dynamicRegistration'];
+    final requests = json['requests'] != null
+        ? SemanticTokensClientCapabilitiesRequests.fromJson(json['requests'])
+        : null;
+    final tokenTypes =
+        json['tokenTypes']?.map((item) => item)?.cast<String>()?.toList();
+    final tokenModifiers =
+        json['tokenModifiers']?.map((item) => item)?.cast<String>()?.toList();
+    final formats = json['formats']
+        ?.map((item) => item != null ? TokenFormat.fromJson(item) : null)
+        ?.cast<TokenFormat>()
+        ?.toList();
+    final overlappingTokenSupport = json['overlappingTokenSupport'];
+    final multilineTokenSupport = json['multilineTokenSupport'];
+    return SemanticTokensClientCapabilities(
+        dynamicRegistration: dynamicRegistration,
+        requests: requests,
+        tokenTypes: tokenTypes,
+        tokenModifiers: tokenModifiers,
+        formats: formats,
+        overlappingTokenSupport: overlappingTokenSupport,
+        multilineTokenSupport: multilineTokenSupport);
+  }
+
+  /// Whether implementation supports dynamic registration. If this is set to
+  /// `true` the client supports the new `(TextDocumentRegistrationOptions &
+  /// StaticRegistrationOptions)` return value for the corresponding server
+  /// capability as well.
+  final bool dynamicRegistration;
+
+  /// The formats the clients supports.
+  final List<TokenFormat> formats;
+
+  /// Whether the client supports tokens that can span multiple lines.
+  final bool multilineTokenSupport;
+
+  /// Whether the client supports tokens that can overlap each other.
+  final bool overlappingTokenSupport;
+
+  /// Which requests the client supports and might send to the server depending
+  /// on the server's capability. Please note that clients might not show
+  /// semantic tokens or degrade some of the user experience if a range or full
+  /// request is advertised by the client but not provided by the server. If for
+  /// example the client capability `requests.full` and `request.range` are both
+  /// set to true but the server only provides a range provider the client might
+  /// not render a minimap correctly or might even decide to not show any
+  /// semantic tokens at all.
+  final SemanticTokensClientCapabilitiesRequests requests;
+
+  /// The token modifiers that the client supports.
+  final List<String> tokenModifiers;
+
+  /// The token types that the client supports.
+  final List<String> tokenTypes;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (dynamicRegistration != null) {
+      __result['dynamicRegistration'] = dynamicRegistration;
+    }
+    __result['requests'] =
+        requests?.toJson() ?? (throw 'requests is required but was not set');
+    __result['tokenTypes'] =
+        tokenTypes ?? (throw 'tokenTypes is required but was not set');
+    __result['tokenModifiers'] =
+        tokenModifiers ?? (throw 'tokenModifiers is required but was not set');
+    __result['formats'] =
+        formats ?? (throw 'formats is required but was not set');
+    if (overlappingTokenSupport != null) {
+      __result['overlappingTokenSupport'] = overlappingTokenSupport;
+    }
+    if (multilineTokenSupport != null) {
+      __result['multilineTokenSupport'] = multilineTokenSupport;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('dynamicRegistration');
+      try {
+        if (obj['dynamicRegistration'] != null &&
+            !(obj['dynamicRegistration'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('requests');
+      try {
+        if (!obj.containsKey('requests')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['requests'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(SemanticTokensClientCapabilitiesRequests.canParse(
+            obj['requests'], reporter))) {
+          reporter.reportError(
+              'must be of type SemanticTokensClientCapabilitiesRequests');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('tokenTypes');
+      try {
+        if (!obj.containsKey('tokenTypes')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['tokenTypes'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['tokenTypes'] is List &&
+            (obj['tokenTypes'].every((item) => item is String))))) {
+          reporter.reportError('must be of type List<String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('tokenModifiers');
+      try {
+        if (!obj.containsKey('tokenModifiers')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['tokenModifiers'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['tokenModifiers'] is List &&
+            (obj['tokenModifiers'].every((item) => item is String))))) {
+          reporter.reportError('must be of type List<String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('formats');
+      try {
+        if (!obj.containsKey('formats')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['formats'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['formats'] is List &&
+            (obj['formats']
+                .every((item) => TokenFormat.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<TokenFormat>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('overlappingTokenSupport');
+      try {
+        if (obj['overlappingTokenSupport'] != null &&
+            !(obj['overlappingTokenSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('multilineTokenSupport');
+      try {
+        if (obj['multilineTokenSupport'] != null &&
+            !(obj['multilineTokenSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensClientCapabilities &&
+        other.runtimeType == SemanticTokensClientCapabilities) {
+      return dynamicRegistration == other.dynamicRegistration &&
+          requests == other.requests &&
+          listEqual(
+              tokenTypes, other.tokenTypes, (String a, String b) => a == b) &&
+          listEqual(tokenModifiers, other.tokenModifiers,
+              (String a, String b) => a == b) &&
+          listEqual(formats, other.formats,
+              (TokenFormat a, TokenFormat b) => a == b) &&
+          overlappingTokenSupport == other.overlappingTokenSupport &&
+          multilineTokenSupport == other.multilineTokenSupport &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
+    hash = JenkinsSmiHash.combine(hash, requests.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(tokenTypes));
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(tokenModifiers));
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(formats));
+    hash = JenkinsSmiHash.combine(hash, overlappingTokenSupport.hashCode);
+    hash = JenkinsSmiHash.combine(hash, multilineTokenSupport.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensClientCapabilitiesFull implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensClientCapabilitiesFull.canParse,
+      SemanticTokensClientCapabilitiesFull.fromJson);
+
+  SemanticTokensClientCapabilitiesFull({this.delta});
+  static SemanticTokensClientCapabilitiesFull fromJson(
+      Map<String, dynamic> json) {
+    final delta = json['delta'];
+    return SemanticTokensClientCapabilitiesFull(delta: delta);
+  }
+
+  /// The client will send the `textDocument/semanticTokens/full/delta` request
+  /// if the server provides a corresponding handler.
+  final bool delta;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (delta != null) {
+      __result['delta'] = delta;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('delta');
+      try {
+        if (obj['delta'] != null && !(obj['delta'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter
+          .reportError('must be of type SemanticTokensClientCapabilitiesFull');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensClientCapabilitiesFull &&
+        other.runtimeType == SemanticTokensClientCapabilitiesFull) {
+      return delta == other.delta && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, delta.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensClientCapabilitiesRange implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensClientCapabilitiesRange.canParse,
+      SemanticTokensClientCapabilitiesRange.fromJson);
+
+  static SemanticTokensClientCapabilitiesRange fromJson(
+      Map<String, dynamic> json) {
+    return SemanticTokensClientCapabilitiesRange();
+  }
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      return true;
+    } else {
+      reporter
+          .reportError('must be of type SemanticTokensClientCapabilitiesRange');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensClientCapabilitiesRange &&
+        other.runtimeType == SemanticTokensClientCapabilitiesRange) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensClientCapabilitiesRequests implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensClientCapabilitiesRequests.canParse,
+      SemanticTokensClientCapabilitiesRequests.fromJson);
+
+  SemanticTokensClientCapabilitiesRequests({this.range, this.full});
+  static SemanticTokensClientCapabilitiesRequests fromJson(
+      Map<String, dynamic> json) {
+    final range = json['range'] is bool
+        ? Either2<bool, SemanticTokensClientCapabilitiesRange>.t1(json['range'])
+        : (SemanticTokensClientCapabilitiesRange.canParse(
+                json['range'], nullLspJsonReporter)
+            ? Either2<bool, SemanticTokensClientCapabilitiesRange>.t2(
+                json['range'] != null
+                    ? SemanticTokensClientCapabilitiesRange.fromJson(
+                        json['range'])
+                    : null)
+            : (json['range'] == null
+                ? null
+                : (throw '''${json['range']} was not one of (bool, SemanticTokensClientCapabilitiesRange)''')));
+    final full = json['full'] is bool
+        ? Either2<bool, SemanticTokensClientCapabilitiesFull>.t1(json['full'])
+        : (SemanticTokensClientCapabilitiesFull.canParse(
+                json['full'], nullLspJsonReporter)
+            ? Either2<bool, SemanticTokensClientCapabilitiesFull>.t2(
+                json['full'] != null
+                    ? SemanticTokensClientCapabilitiesFull.fromJson(
+                        json['full'])
+                    : null)
+            : (json['full'] == null
+                ? null
+                : (throw '''${json['full']} was not one of (bool, SemanticTokensClientCapabilitiesFull)''')));
+    return SemanticTokensClientCapabilitiesRequests(range: range, full: full);
+  }
+
+  /// The client will send the `textDocument/semanticTokens/full` request if the
+  /// server provides a corresponding handler.
+  final Either2<bool, SemanticTokensClientCapabilitiesFull> full;
+
+  /// The client will send the `textDocument/semanticTokens/range` request if
+  /// the server provides a corresponding handler.
+  final Either2<bool, SemanticTokensClientCapabilitiesRange> range;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (range != null) {
+      __result['range'] = range;
+    }
+    if (full != null) {
+      __result['full'] = full;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('range');
+      try {
+        if (obj['range'] != null &&
+            !((obj['range'] is bool ||
+                SemanticTokensClientCapabilitiesRange.canParse(
+                    obj['range'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either2<bool, SemanticTokensClientCapabilitiesRange>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('full');
+      try {
+        if (obj['full'] != null &&
+            !((obj['full'] is bool ||
+                SemanticTokensClientCapabilitiesFull.canParse(
+                    obj['full'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either2<bool, SemanticTokensClientCapabilitiesFull>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type SemanticTokensClientCapabilitiesRequests');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensClientCapabilitiesRequests &&
+        other.runtimeType == SemanticTokensClientCapabilitiesRequests) {
+      return range == other.range && full == other.full && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, range.hashCode);
+    hash = JenkinsSmiHash.combine(hash, full.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensDelta implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensDelta.canParse, SemanticTokensDelta.fromJson);
+
+  SemanticTokensDelta({this.resultId, @required this.edits}) {
+    if (edits == null) {
+      throw 'edits is required but was not provided';
+    }
+  }
+  static SemanticTokensDelta fromJson(Map<String, dynamic> json) {
+    final resultId = json['resultId'];
+    final edits = json['edits']
+        ?.map((item) => item != null ? SemanticTokensEdit.fromJson(item) : null)
+        ?.cast<SemanticTokensEdit>()
+        ?.toList();
+    return SemanticTokensDelta(resultId: resultId, edits: edits);
+  }
+
+  /// The semantic token edits to transform a previous result into a new result.
+  final List<SemanticTokensEdit> edits;
+  final String resultId;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (resultId != null) {
+      __result['resultId'] = resultId;
+    }
+    __result['edits'] = edits ?? (throw 'edits is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('resultId');
+      try {
+        if (obj['resultId'] != null && !(obj['resultId'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('edits');
+      try {
+        if (!obj.containsKey('edits')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['edits'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['edits'] is List &&
+            (obj['edits'].every(
+                (item) => SemanticTokensEdit.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<SemanticTokensEdit>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensDelta');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensDelta &&
+        other.runtimeType == SemanticTokensDelta) {
+      return resultId == other.resultId &&
+          listEqual(edits, other.edits,
+              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, resultId.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(edits));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensDeltaParams
+    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensDeltaParams.canParse, SemanticTokensDeltaParams.fromJson);
+
+  SemanticTokensDeltaParams(
+      {@required this.textDocument,
+      @required this.previousResultId,
+      this.workDoneToken,
+      this.partialResultToken}) {
+    if (textDocument == null) {
+      throw 'textDocument is required but was not provided';
+    }
+    if (previousResultId == null) {
+      throw 'previousResultId is required but was not provided';
+    }
+  }
+  static SemanticTokensDeltaParams fromJson(Map<String, dynamic> json) {
+    final textDocument = json['textDocument'] != null
+        ? TextDocumentIdentifier.fromJson(json['textDocument'])
+        : null;
+    final previousResultId = json['previousResultId'];
+    final workDoneToken = json['workDoneToken'] is num
+        ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is String
+            ? Either2<num, String>.t2(json['workDoneToken'])
+            : (json['workDoneToken'] == null
+                ? null
+                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+    final partialResultToken = json['partialResultToken'] is num
+        ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is String
+            ? Either2<num, String>.t2(json['partialResultToken'])
+            : (json['partialResultToken'] == null
+                ? null
+                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+    return SemanticTokensDeltaParams(
+        textDocument: textDocument,
+        previousResultId: previousResultId,
+        workDoneToken: workDoneToken,
+        partialResultToken: partialResultToken);
+  }
+
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
+  final Either2<num, String> partialResultToken;
+
+  /// The result id of a previous response. The result Id can either point to a
+  /// full response or a delta response depending on what was received last.
+  final String previousResultId;
+
+  /// The text document.
+  final TextDocumentIdentifier textDocument;
+
+  /// An optional token that a server can use to report work done progress.
+  final Either2<num, String> workDoneToken;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    __result['previousResultId'] = previousResultId ??
+        (throw 'previousResultId is required but was not set');
+    if (workDoneToken != null) {
+      __result['workDoneToken'] = workDoneToken;
+    }
+    if (partialResultToken != null) {
+      __result['partialResultToken'] = partialResultToken;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('textDocument');
+      try {
+        if (!obj.containsKey('textDocument')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['textDocument'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
+          reporter.reportError('must be of type TextDocumentIdentifier');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('previousResultId');
+      try {
+        if (!obj.containsKey('previousResultId')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['previousResultId'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['previousResultId'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneToken');
+      try {
+        if (obj['workDoneToken'] != null &&
+            !((obj['workDoneToken'] is num ||
+                obj['workDoneToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('partialResultToken');
+      try {
+        if (obj['partialResultToken'] != null &&
+            !((obj['partialResultToken'] is num ||
+                obj['partialResultToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensDeltaParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensDeltaParams &&
+        other.runtimeType == SemanticTokensDeltaParams) {
+      return textDocument == other.textDocument &&
+          previousResultId == other.previousResultId &&
+          workDoneToken == other.workDoneToken &&
+          partialResultToken == other.partialResultToken &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
+    hash = JenkinsSmiHash.combine(hash, previousResultId.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
+    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensDeltaPartialResult implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensDeltaPartialResult.canParse,
+      SemanticTokensDeltaPartialResult.fromJson);
+
+  SemanticTokensDeltaPartialResult({@required this.edits}) {
+    if (edits == null) {
+      throw 'edits is required but was not provided';
+    }
+  }
+  static SemanticTokensDeltaPartialResult fromJson(Map<String, dynamic> json) {
+    final edits = json['edits']
+        ?.map((item) => item != null ? SemanticTokensEdit.fromJson(item) : null)
+        ?.cast<SemanticTokensEdit>()
+        ?.toList();
+    return SemanticTokensDeltaPartialResult(edits: edits);
+  }
+
+  final List<SemanticTokensEdit> edits;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['edits'] = edits ?? (throw 'edits is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('edits');
+      try {
+        if (!obj.containsKey('edits')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['edits'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['edits'] is List &&
+            (obj['edits'].every(
+                (item) => SemanticTokensEdit.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<SemanticTokensEdit>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensDeltaPartialResult');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensDeltaPartialResult &&
+        other.runtimeType == SemanticTokensDeltaPartialResult) {
+      return listEqual(edits, other.edits,
+              (SemanticTokensEdit a, SemanticTokensEdit b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(edits));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensEdit implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(SemanticTokensEdit.canParse, SemanticTokensEdit.fromJson);
+
+  SemanticTokensEdit(
+      {@required this.start, @required this.deleteCount, this.data}) {
+    if (start == null) {
+      throw 'start is required but was not provided';
+    }
+    if (deleteCount == null) {
+      throw 'deleteCount is required but was not provided';
+    }
+  }
+  static SemanticTokensEdit fromJson(Map<String, dynamic> json) {
+    final start = json['start'];
+    final deleteCount = json['deleteCount'];
+    final data = json['data']?.map((item) => item)?.cast<num>()?.toList();
+    return SemanticTokensEdit(
+        start: start, deleteCount: deleteCount, data: data);
+  }
+
+  /// The elements to insert.
+  final List<num> data;
+
+  /// The count of elements to remove.
+  final num deleteCount;
+
+  /// The start offset of the edit.
+  final num start;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['start'] = start ?? (throw 'start is required but was not set');
+    __result['deleteCount'] =
+        deleteCount ?? (throw 'deleteCount is required but was not set');
+    if (data != null) {
+      __result['data'] = data;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('start');
+      try {
+        if (!obj.containsKey('start')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['start'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['start'] is num)) {
+          reporter.reportError('must be of type num');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('deleteCount');
+      try {
+        if (!obj.containsKey('deleteCount')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['deleteCount'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['deleteCount'] is num)) {
+          reporter.reportError('must be of type num');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('data');
+      try {
+        if (obj['data'] != null &&
+            !((obj['data'] is List &&
+                (obj['data'].every((item) => item is num))))) {
+          reporter.reportError('must be of type List<num>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensEdit');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensEdit &&
+        other.runtimeType == SemanticTokensEdit) {
+      return start == other.start &&
+          deleteCount == other.deleteCount &&
+          listEqual(data, other.data, (num a, num b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, start.hashCode);
+    hash = JenkinsSmiHash.combine(hash, deleteCount.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(data));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensLegend implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensLegend.canParse, SemanticTokensLegend.fromJson);
+
+  SemanticTokensLegend(
+      {@required this.tokenTypes, @required this.tokenModifiers}) {
+    if (tokenTypes == null) {
+      throw 'tokenTypes is required but was not provided';
+    }
+    if (tokenModifiers == null) {
+      throw 'tokenModifiers is required but was not provided';
+    }
+  }
+  static SemanticTokensLegend fromJson(Map<String, dynamic> json) {
+    final tokenTypes =
+        json['tokenTypes']?.map((item) => item)?.cast<String>()?.toList();
+    final tokenModifiers =
+        json['tokenModifiers']?.map((item) => item)?.cast<String>()?.toList();
+    return SemanticTokensLegend(
+        tokenTypes: tokenTypes, tokenModifiers: tokenModifiers);
+  }
+
+  /// The token modifiers a server uses.
+  final List<String> tokenModifiers;
+
+  /// The token types a server uses.
+  final List<String> tokenTypes;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['tokenTypes'] =
+        tokenTypes ?? (throw 'tokenTypes is required but was not set');
+    __result['tokenModifiers'] =
+        tokenModifiers ?? (throw 'tokenModifiers is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('tokenTypes');
+      try {
+        if (!obj.containsKey('tokenTypes')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['tokenTypes'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['tokenTypes'] is List &&
+            (obj['tokenTypes'].every((item) => item is String))))) {
+          reporter.reportError('must be of type List<String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('tokenModifiers');
+      try {
+        if (!obj.containsKey('tokenModifiers')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['tokenModifiers'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['tokenModifiers'] is List &&
+            (obj['tokenModifiers'].every((item) => item is String))))) {
+          reporter.reportError('must be of type List<String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensLegend');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensLegend &&
+        other.runtimeType == SemanticTokensLegend) {
+      return listEqual(
+              tokenTypes, other.tokenTypes, (String a, String b) => a == b) &&
+          listEqual(tokenModifiers, other.tokenModifiers,
+              (String a, String b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(tokenTypes));
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(tokenModifiers));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensOptions implements WorkDoneProgressOptions, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensOptions.canParse, SemanticTokensOptions.fromJson);
+
+  SemanticTokensOptions(
+      {@required this.legend, this.range, this.full, this.workDoneProgress}) {
+    if (legend == null) {
+      throw 'legend is required but was not provided';
+    }
+  }
+  static SemanticTokensOptions fromJson(Map<String, dynamic> json) {
+    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensRegistrationOptions.fromJson(json);
+    }
+    final legend = json['legend'] != null
+        ? SemanticTokensLegend.fromJson(json['legend'])
+        : null;
+    final range = json['range'] is bool
+        ? Either2<bool, SemanticTokensOptionsRange>.t1(json['range'])
+        : (SemanticTokensOptionsRange.canParse(
+                json['range'], nullLspJsonReporter)
+            ? Either2<bool, SemanticTokensOptionsRange>.t2(json['range'] != null
+                ? SemanticTokensOptionsRange.fromJson(json['range'])
+                : null)
+            : (json['range'] == null
+                ? null
+                : (throw '''${json['range']} was not one of (bool, SemanticTokensOptionsRange)''')));
+    final full = json['full'] is bool
+        ? Either2<bool, SemanticTokensOptionsFull>.t1(json['full'])
+        : (SemanticTokensOptionsFull.canParse(json['full'], nullLspJsonReporter)
+            ? Either2<bool, SemanticTokensOptionsFull>.t2(json['full'] != null
+                ? SemanticTokensOptionsFull.fromJson(json['full'])
+                : null)
+            : (json['full'] == null
+                ? null
+                : (throw '''${json['full']} was not one of (bool, SemanticTokensOptionsFull)''')));
+    final workDoneProgress = json['workDoneProgress'];
+    return SemanticTokensOptions(
+        legend: legend,
+        range: range,
+        full: full,
+        workDoneProgress: workDoneProgress);
+  }
+
+  /// Server supports providing semantic tokens for a full document.
+  final Either2<bool, SemanticTokensOptionsFull> full;
+
+  /// The legend used by the server
+  final SemanticTokensLegend legend;
+
+  /// Server supports providing semantic tokens for a specific range of a
+  /// document.
+  final Either2<bool, SemanticTokensOptionsRange> range;
+  final bool workDoneProgress;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['legend'] =
+        legend?.toJson() ?? (throw 'legend is required but was not set');
+    if (range != null) {
+      __result['range'] = range;
+    }
+    if (full != null) {
+      __result['full'] = full;
+    }
+    if (workDoneProgress != null) {
+      __result['workDoneProgress'] = workDoneProgress;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('legend');
+      try {
+        if (!obj.containsKey('legend')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['legend'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(SemanticTokensLegend.canParse(obj['legend'], reporter))) {
+          reporter.reportError('must be of type SemanticTokensLegend');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('range');
+      try {
+        if (obj['range'] != null &&
+            !((obj['range'] is bool ||
+                SemanticTokensOptionsRange.canParse(obj['range'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either2<bool, SemanticTokensOptionsRange>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('full');
+      try {
+        if (obj['full'] != null &&
+            !((obj['full'] is bool ||
+                SemanticTokensOptionsFull.canParse(obj['full'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either2<bool, SemanticTokensOptionsFull>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneProgress');
+      try {
+        if (obj['workDoneProgress'] != null &&
+            !(obj['workDoneProgress'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensOptions &&
+        other.runtimeType == SemanticTokensOptions) {
+      return legend == other.legend &&
+          range == other.range &&
+          full == other.full &&
+          workDoneProgress == other.workDoneProgress &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, legend.hashCode);
+    hash = JenkinsSmiHash.combine(hash, range.hashCode);
+    hash = JenkinsSmiHash.combine(hash, full.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensOptionsFull implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensOptionsFull.canParse, SemanticTokensOptionsFull.fromJson);
+
+  SemanticTokensOptionsFull({this.delta});
+  static SemanticTokensOptionsFull fromJson(Map<String, dynamic> json) {
+    final delta = json['delta'];
+    return SemanticTokensOptionsFull(delta: delta);
+  }
+
+  /// The server supports deltas for full documents.
+  final bool delta;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (delta != null) {
+      __result['delta'] = delta;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('delta');
+      try {
+        if (obj['delta'] != null && !(obj['delta'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensOptionsFull');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensOptionsFull &&
+        other.runtimeType == SemanticTokensOptionsFull) {
+      return delta == other.delta && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, delta.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensOptionsRange implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensOptionsRange.canParse, SemanticTokensOptionsRange.fromJson);
+
+  static SemanticTokensOptionsRange fromJson(Map<String, dynamic> json) {
+    return SemanticTokensOptionsRange();
+  }
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensOptionsRange');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensOptionsRange &&
+        other.runtimeType == SemanticTokensOptionsRange) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensParams
+    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensParams.canParse, SemanticTokensParams.fromJson);
+
+  SemanticTokensParams(
+      {@required this.textDocument,
+      this.workDoneToken,
+      this.partialResultToken}) {
+    if (textDocument == null) {
+      throw 'textDocument is required but was not provided';
+    }
+  }
+  static SemanticTokensParams fromJson(Map<String, dynamic> json) {
+    final textDocument = json['textDocument'] != null
+        ? TextDocumentIdentifier.fromJson(json['textDocument'])
+        : null;
+    final workDoneToken = json['workDoneToken'] is num
+        ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is String
+            ? Either2<num, String>.t2(json['workDoneToken'])
+            : (json['workDoneToken'] == null
+                ? null
+                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+    final partialResultToken = json['partialResultToken'] is num
+        ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is String
+            ? Either2<num, String>.t2(json['partialResultToken'])
+            : (json['partialResultToken'] == null
+                ? null
+                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+    return SemanticTokensParams(
+        textDocument: textDocument,
+        workDoneToken: workDoneToken,
+        partialResultToken: partialResultToken);
+  }
+
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
+  final Either2<num, String> partialResultToken;
+
+  /// The text document.
+  final TextDocumentIdentifier textDocument;
+
+  /// An optional token that a server can use to report work done progress.
+  final Either2<num, String> workDoneToken;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    if (workDoneToken != null) {
+      __result['workDoneToken'] = workDoneToken;
+    }
+    if (partialResultToken != null) {
+      __result['partialResultToken'] = partialResultToken;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('textDocument');
+      try {
+        if (!obj.containsKey('textDocument')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['textDocument'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
+          reporter.reportError('must be of type TextDocumentIdentifier');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneToken');
+      try {
+        if (obj['workDoneToken'] != null &&
+            !((obj['workDoneToken'] is num ||
+                obj['workDoneToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('partialResultToken');
+      try {
+        if (obj['partialResultToken'] != null &&
+            !((obj['partialResultToken'] is num ||
+                obj['partialResultToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensParams &&
+        other.runtimeType == SemanticTokensParams) {
+      return textDocument == other.textDocument &&
+          workDoneToken == other.workDoneToken &&
+          partialResultToken == other.partialResultToken &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
+    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensPartialResult implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensPartialResult.canParse,
+      SemanticTokensPartialResult.fromJson);
+
+  SemanticTokensPartialResult({@required this.data}) {
+    if (data == null) {
+      throw 'data is required but was not provided';
+    }
+  }
+  static SemanticTokensPartialResult fromJson(Map<String, dynamic> json) {
+    final data = json['data']?.map((item) => item)?.cast<num>()?.toList();
+    return SemanticTokensPartialResult(data: data);
+  }
+
+  final List<num> data;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['data'] = data ?? (throw 'data is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('data');
+      try {
+        if (!obj.containsKey('data')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['data'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['data'] is List &&
+            (obj['data'].every((item) => item is num))))) {
+          reporter.reportError('must be of type List<num>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensPartialResult');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensPartialResult &&
+        other.runtimeType == SemanticTokensPartialResult) {
+      return listEqual(data, other.data, (num a, num b) => a == b) && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(data));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensRangeParams
+    implements WorkDoneProgressParams, PartialResultParams, ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensRangeParams.canParse, SemanticTokensRangeParams.fromJson);
+
+  SemanticTokensRangeParams(
+      {@required this.textDocument,
+      @required this.range,
+      this.workDoneToken,
+      this.partialResultToken}) {
+    if (textDocument == null) {
+      throw 'textDocument is required but was not provided';
+    }
+    if (range == null) {
+      throw 'range is required but was not provided';
+    }
+  }
+  static SemanticTokensRangeParams fromJson(Map<String, dynamic> json) {
+    final textDocument = json['textDocument'] != null
+        ? TextDocumentIdentifier.fromJson(json['textDocument'])
+        : null;
+    final range = json['range'] != null ? Range.fromJson(json['range']) : null;
+    final workDoneToken = json['workDoneToken'] is num
+        ? Either2<num, String>.t1(json['workDoneToken'])
+        : (json['workDoneToken'] is String
+            ? Either2<num, String>.t2(json['workDoneToken'])
+            : (json['workDoneToken'] == null
+                ? null
+                : (throw '''${json['workDoneToken']} was not one of (num, String)''')));
+    final partialResultToken = json['partialResultToken'] is num
+        ? Either2<num, String>.t1(json['partialResultToken'])
+        : (json['partialResultToken'] is String
+            ? Either2<num, String>.t2(json['partialResultToken'])
+            : (json['partialResultToken'] == null
+                ? null
+                : (throw '''${json['partialResultToken']} was not one of (num, String)''')));
+    return SemanticTokensRangeParams(
+        textDocument: textDocument,
+        range: range,
+        workDoneToken: workDoneToken,
+        partialResultToken: partialResultToken);
+  }
+
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
+  final Either2<num, String> partialResultToken;
+
+  /// The range the semantic tokens are requested for.
+  final Range range;
+
+  /// The text document.
+  final TextDocumentIdentifier textDocument;
+
+  /// An optional token that a server can use to report work done progress.
+  final Either2<num, String> workDoneToken;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
+    if (workDoneToken != null) {
+      __result['workDoneToken'] = workDoneToken;
+    }
+    if (partialResultToken != null) {
+      __result['partialResultToken'] = partialResultToken;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('textDocument');
+      try {
+        if (!obj.containsKey('textDocument')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['textDocument'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(TextDocumentIdentifier.canParse(obj['textDocument'], reporter))) {
+          reporter.reportError('must be of type TextDocumentIdentifier');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('range');
+      try {
+        if (!obj.containsKey('range')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['range'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(Range.canParse(obj['range'], reporter))) {
+          reporter.reportError('must be of type Range');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneToken');
+      try {
+        if (obj['workDoneToken'] != null &&
+            !((obj['workDoneToken'] is num ||
+                obj['workDoneToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('partialResultToken');
+      try {
+        if (obj['partialResultToken'] != null &&
+            !((obj['partialResultToken'] is num ||
+                obj['partialResultToken'] is String))) {
+          reporter.reportError('must be of type Either2<num, String>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensRangeParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensRangeParams &&
+        other.runtimeType == SemanticTokensRangeParams) {
+      return textDocument == other.textDocument &&
+          range == other.range &&
+          workDoneToken == other.workDoneToken &&
+          partialResultToken == other.partialResultToken &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, textDocument.hashCode);
+    hash = JenkinsSmiHash.combine(hash, range.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneToken.hashCode);
+    hash = JenkinsSmiHash.combine(hash, partialResultToken.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensRegistrationOptions
+    implements
+        TextDocumentRegistrationOptions,
+        SemanticTokensOptions,
+        StaticRegistrationOptions,
+        ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensRegistrationOptions.canParse,
+      SemanticTokensRegistrationOptions.fromJson);
+
+  SemanticTokensRegistrationOptions(
+      {this.documentSelector,
+      @required this.legend,
+      this.range,
+      this.full,
+      this.workDoneProgress,
+      this.id}) {
+    if (legend == null) {
+      throw 'legend is required but was not provided';
+    }
+  }
+  static SemanticTokensRegistrationOptions fromJson(Map<String, dynamic> json) {
+    final documentSelector = json['documentSelector']
+        ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
+        ?.cast<DocumentFilter>()
+        ?.toList();
+    final legend = json['legend'] != null
+        ? SemanticTokensLegend.fromJson(json['legend'])
+        : null;
+    final range = json['range'] is bool
+        ? Either2<bool, SemanticTokensOptionsRange>.t1(json['range'])
+        : (SemanticTokensOptionsRange.canParse(
+                json['range'], nullLspJsonReporter)
+            ? Either2<bool, SemanticTokensOptionsRange>.t2(json['range'] != null
+                ? SemanticTokensOptionsRange.fromJson(json['range'])
+                : null)
+            : (json['range'] == null
+                ? null
+                : (throw '''${json['range']} was not one of (bool, SemanticTokensOptionsRange)''')));
+    final full = json['full'] is bool
+        ? Either2<bool, SemanticTokensOptionsFull>.t1(json['full'])
+        : (SemanticTokensOptionsFull.canParse(json['full'], nullLspJsonReporter)
+            ? Either2<bool, SemanticTokensOptionsFull>.t2(json['full'] != null
+                ? SemanticTokensOptionsFull.fromJson(json['full'])
+                : null)
+            : (json['full'] == null
+                ? null
+                : (throw '''${json['full']} was not one of (bool, SemanticTokensOptionsFull)''')));
+    final workDoneProgress = json['workDoneProgress'];
+    final id = json['id'];
+    return SemanticTokensRegistrationOptions(
+        documentSelector: documentSelector,
+        legend: legend,
+        range: range,
+        full: full,
+        workDoneProgress: workDoneProgress,
+        id: id);
+  }
+
+  /// A document selector to identify the scope of the registration. If set to
+  /// null the document selector provided on the client side will be used.
+  final List<DocumentFilter> documentSelector;
+
+  /// Server supports providing semantic tokens for a full document.
+  final Either2<bool, SemanticTokensOptionsFull> full;
+
+  /// The id used to register the request. The id can be used to deregister the
+  /// request again. See also Registration#id.
+  final String id;
+
+  /// The legend used by the server
+  final SemanticTokensLegend legend;
+
+  /// Server supports providing semantic tokens for a specific range of a
+  /// document.
+  final Either2<bool, SemanticTokensOptionsRange> range;
+  final bool workDoneProgress;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['documentSelector'] = documentSelector;
+    __result['legend'] =
+        legend?.toJson() ?? (throw 'legend is required but was not set');
+    if (range != null) {
+      __result['range'] = range;
+    }
+    if (full != null) {
+      __result['full'] = full;
+    }
+    if (workDoneProgress != null) {
+      __result['workDoneProgress'] = workDoneProgress;
+    }
+    if (id != null) {
+      __result['id'] = id;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('documentSelector');
+      try {
+        if (!obj.containsKey('documentSelector')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['documentSelector'] != null &&
+            !((obj['documentSelector'] is List &&
+                (obj['documentSelector'].every(
+                    (item) => DocumentFilter.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<DocumentFilter>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('legend');
+      try {
+        if (!obj.containsKey('legend')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['legend'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(SemanticTokensLegend.canParse(obj['legend'], reporter))) {
+          reporter.reportError('must be of type SemanticTokensLegend');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('range');
+      try {
+        if (obj['range'] != null &&
+            !((obj['range'] is bool ||
+                SemanticTokensOptionsRange.canParse(obj['range'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either2<bool, SemanticTokensOptionsRange>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('full');
+      try {
+        if (obj['full'] != null &&
+            !((obj['full'] is bool ||
+                SemanticTokensOptionsFull.canParse(obj['full'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either2<bool, SemanticTokensOptionsFull>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('workDoneProgress');
+      try {
+        if (obj['workDoneProgress'] != null &&
+            !(obj['workDoneProgress'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('id');
+      try {
+        if (obj['id'] != null && !(obj['id'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SemanticTokensRegistrationOptions');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensRegistrationOptions &&
+        other.runtimeType == SemanticTokensRegistrationOptions) {
+      return listEqual(documentSelector, other.documentSelector,
+              (DocumentFilter a, DocumentFilter b) => a == b) &&
+          legend == other.legend &&
+          range == other.range &&
+          full == other.full &&
+          workDoneProgress == other.workDoneProgress &&
+          id == other.id &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(documentSelector));
+    hash = JenkinsSmiHash.combine(hash, legend.hashCode);
+    hash = JenkinsSmiHash.combine(hash, range.hashCode);
+    hash = JenkinsSmiHash.combine(hash, full.hashCode);
+    hash = JenkinsSmiHash.combine(hash, workDoneProgress.hashCode);
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SemanticTokensWorkspaceClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      SemanticTokensWorkspaceClientCapabilities.canParse,
+      SemanticTokensWorkspaceClientCapabilities.fromJson);
+
+  SemanticTokensWorkspaceClientCapabilities({this.refreshSupport});
+  static SemanticTokensWorkspaceClientCapabilities fromJson(
+      Map<String, dynamic> json) {
+    final refreshSupport = json['refreshSupport'];
+    return SemanticTokensWorkspaceClientCapabilities(
+        refreshSupport: refreshSupport);
+  }
+
+  /// Whether the client implementation supports a refresh request sent from the
+  /// server to the client.
+  ///
+  /// Note that this event is global and will force the client to refresh all
+  /// semantic tokens currently shown. It should be used with absolute care and
+  /// is useful for situation where a server for example detect a project wide
+  /// change that requires such a calculation.
+  final bool refreshSupport;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (refreshSupport != null) {
+      __result['refreshSupport'] = refreshSupport;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('refreshSupport');
+      try {
+        if (obj['refreshSupport'] != null && !(obj['refreshSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type SemanticTokensWorkspaceClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SemanticTokensWorkspaceClientCapabilities &&
+        other.runtimeType == SemanticTokensWorkspaceClientCapabilities) {
+      return refreshSupport == other.refreshSupport && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, refreshSupport.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class ServerCapabilities implements ToJsonable {
   static const jsonHandler =
       LspJsonHandler(ServerCapabilities.canParse, ServerCapabilities.fromJson);
@@ -18217,21 +25948,29 @@
       this.foldingRangeProvider,
       this.executeCommandProvider,
       this.selectionRangeProvider,
+      this.linkedEditingRangeProvider,
+      this.callHierarchyProvider,
+      this.semanticTokensProvider,
+      this.monikerProvider,
       this.workspaceSymbolProvider,
       this.workspace,
       this.experimental});
   static ServerCapabilities fromJson(Map<String, dynamic> json) {
     final textDocumentSync = TextDocumentSyncOptions.canParse(
             json['textDocumentSync'], nullLspJsonReporter)
-        ? Either2<TextDocumentSyncOptions, num>.t1(
+        ? Either2<TextDocumentSyncOptions, TextDocumentSyncKind>.t1(
             json['textDocumentSync'] != null
                 ? TextDocumentSyncOptions.fromJson(json['textDocumentSync'])
                 : null)
-        : (json['textDocumentSync'] is num
-            ? Either2<TextDocumentSyncOptions, num>.t2(json['textDocumentSync'])
+        : (TextDocumentSyncKind.canParse(
+                json['textDocumentSync'], nullLspJsonReporter)
+            ? Either2<TextDocumentSyncOptions, TextDocumentSyncKind>.t2(
+                json['textDocumentSync'] != null
+                    ? TextDocumentSyncKind.fromJson(json['textDocumentSync'])
+                    : null)
             : (json['textDocumentSync'] == null
                 ? null
-                : (throw '''${json['textDocumentSync']} was not one of (TextDocumentSyncOptions, num)''')));
+                : (throw '''${json['textDocumentSync']} was not one of (TextDocumentSyncOptions, TextDocumentSyncKind)''')));
     final completionProvider = json['completionProvider'] != null
         ? CompletionOptions.fromJson(json['completionProvider'])
         : null;
@@ -18468,6 +26207,77 @@
                 : (json['selectionRangeProvider'] == null
                     ? null
                     : (throw '''${json['selectionRangeProvider']} was not one of (bool, SelectionRangeOptions, SelectionRangeRegistrationOptions)'''))));
+    final linkedEditingRangeProvider = json['linkedEditingRangeProvider']
+            is bool
+        ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t1(
+            json['linkedEditingRangeProvider'])
+        : (LinkedEditingRangeOptions.canParse(json['linkedEditingRangeProvider'], nullLspJsonReporter)
+            ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t2(
+                json['linkedEditingRangeProvider'] != null
+                    ? LinkedEditingRangeOptions.fromJson(
+                        json['linkedEditingRangeProvider'])
+                    : null)
+            : (LinkedEditingRangeRegistrationOptions.canParse(json['linkedEditingRangeProvider'], nullLspJsonReporter)
+                ? Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>.t3(
+                    json['linkedEditingRangeProvider'] != null
+                        ? LinkedEditingRangeRegistrationOptions.fromJson(
+                            json['linkedEditingRangeProvider'])
+                        : null)
+                : (json['linkedEditingRangeProvider'] == null
+                    ? null
+                    : (throw '''${json['linkedEditingRangeProvider']} was not one of (bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions)'''))));
+    final callHierarchyProvider = json['callHierarchyProvider'] is bool
+        ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t1(
+            json['callHierarchyProvider'])
+        : (CallHierarchyOptions.canParse(
+                json['callHierarchyProvider'], nullLspJsonReporter)
+            ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t2(json['callHierarchyProvider'] != null
+                ? CallHierarchyOptions.fromJson(json['callHierarchyProvider'])
+                : null)
+            : (CallHierarchyRegistrationOptions.canParse(
+                    json['callHierarchyProvider'], nullLspJsonReporter)
+                ? Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>.t3(
+                    json['callHierarchyProvider'] != null
+                        ? CallHierarchyRegistrationOptions.fromJson(
+                            json['callHierarchyProvider'])
+                        : null)
+                : (json['callHierarchyProvider'] == null
+                    ? null
+                    : (throw '''${json['callHierarchyProvider']} was not one of (bool, CallHierarchyOptions, CallHierarchyRegistrationOptions)'''))));
+    final semanticTokensProvider = SemanticTokensOptions.canParse(
+            json['semanticTokensProvider'], nullLspJsonReporter)
+        ? Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>.t1(
+            json['semanticTokensProvider'] != null
+                ? SemanticTokensOptions.fromJson(json['semanticTokensProvider'])
+                : null)
+        : (SemanticTokensRegistrationOptions.canParse(
+                json['semanticTokensProvider'], nullLspJsonReporter)
+            ? Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>.t2(
+                json['semanticTokensProvider'] != null
+                    ? SemanticTokensRegistrationOptions.fromJson(
+                        json['semanticTokensProvider'])
+                    : null)
+            : (json['semanticTokensProvider'] == null
+                ? null
+                : (throw '''${json['semanticTokensProvider']} was not one of (SemanticTokensOptions, SemanticTokensRegistrationOptions)''')));
+    final monikerProvider = json['monikerProvider'] is bool
+        ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t1(
+            json['monikerProvider'])
+        : (MonikerOptions.canParse(json['monikerProvider'], nullLspJsonReporter)
+            ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t2(
+                json['monikerProvider'] != null
+                    ? MonikerOptions.fromJson(json['monikerProvider'])
+                    : null)
+            : (MonikerRegistrationOptions.canParse(
+                    json['monikerProvider'], nullLspJsonReporter)
+                ? Either3<bool, MonikerOptions, MonikerRegistrationOptions>.t3(
+                    json['monikerProvider'] != null
+                        ? MonikerRegistrationOptions.fromJson(
+                            json['monikerProvider'])
+                        : null)
+                : (json['monikerProvider'] == null
+                    ? null
+                    : (throw '''${json['monikerProvider']} was not one of (bool, MonikerOptions, MonikerRegistrationOptions)'''))));
     final workspaceSymbolProvider = json['workspaceSymbolProvider'] is bool
         ? Either2<bool, WorkspaceSymbolOptions>.t1(
             json['workspaceSymbolProvider'])
@@ -18508,17 +26318,26 @@
         foldingRangeProvider: foldingRangeProvider,
         executeCommandProvider: executeCommandProvider,
         selectionRangeProvider: selectionRangeProvider,
+        linkedEditingRangeProvider: linkedEditingRangeProvider,
+        callHierarchyProvider: callHierarchyProvider,
+        semanticTokensProvider: semanticTokensProvider,
+        monikerProvider: monikerProvider,
         workspaceSymbolProvider: workspaceSymbolProvider,
         workspace: workspace,
         experimental: experimental);
   }
 
+  /// The server provides call hierarchy support.
+  ///  @since 3.16.0
+  final Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>
+      callHierarchyProvider;
+
   /// The server provides code actions. The `CodeActionOptions` return type is
   /// only valid if the client signals code action literal support via the
   /// property `textDocument.codeAction.codeActionLiteralSupport`.
   final Either2<bool, CodeActionOptions> codeActionProvider;
 
-  /// The server provides CodeLens.
+  /// The server provides code lens.
   final CodeLensOptions codeLensProvider;
 
   /// The server provides color provider support.
@@ -18575,6 +26394,16 @@
   final Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>
       implementationProvider;
 
+  /// The server provides linked editing range support.
+  ///  @since 3.16.0
+  final Either3<bool, LinkedEditingRangeOptions,
+      LinkedEditingRangeRegistrationOptions> linkedEditingRangeProvider;
+
+  /// Whether server provides moniker support.
+  ///  @since 3.16.0
+  final Either3<bool, MonikerOptions, MonikerRegistrationOptions>
+      monikerProvider;
+
   /// The server provides find references support.
   final Either2<bool, ReferenceOptions> referencesProvider;
 
@@ -18588,14 +26417,19 @@
   final Either3<bool, SelectionRangeOptions, SelectionRangeRegistrationOptions>
       selectionRangeProvider;
 
+  /// The server provides semantic tokens support.
+  ///  @since 3.16.0
+  final Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>
+      semanticTokensProvider;
+
   /// The server provides signature help support.
   final SignatureHelpOptions signatureHelpProvider;
 
   /// Defines how text documents are synced. Is either a detailed structure
-  /// defining each notification or for backwards compatibility, the
-  /// TextDocumentSyncKind number. If omitted, it defaults to
+  /// defining each notification or for backwards compatibility the
+  /// TextDocumentSyncKind number. If omitted it defaults to
   /// `TextDocumentSyncKind.None`.
-  final Either2<TextDocumentSyncOptions, num> textDocumentSync;
+  final Either2<TextDocumentSyncOptions, TextDocumentSyncKind> textDocumentSync;
 
   /// The server provides goto type definition support.
   ///  @since 3.6.0
@@ -18678,6 +26512,18 @@
     if (selectionRangeProvider != null) {
       __result['selectionRangeProvider'] = selectionRangeProvider;
     }
+    if (linkedEditingRangeProvider != null) {
+      __result['linkedEditingRangeProvider'] = linkedEditingRangeProvider;
+    }
+    if (callHierarchyProvider != null) {
+      __result['callHierarchyProvider'] = callHierarchyProvider;
+    }
+    if (semanticTokensProvider != null) {
+      __result['semanticTokensProvider'] = semanticTokensProvider;
+    }
+    if (monikerProvider != null) {
+      __result['monikerProvider'] = monikerProvider;
+    }
     if (workspaceSymbolProvider != null) {
       __result['workspaceSymbolProvider'] = workspaceSymbolProvider;
     }
@@ -18697,9 +26543,10 @@
         if (obj['textDocumentSync'] != null &&
             !((TextDocumentSyncOptions.canParse(
                     obj['textDocumentSync'], reporter) ||
-                obj['textDocumentSync'] is num))) {
+                TextDocumentSyncKind.canParse(
+                    obj['textDocumentSync'], reporter)))) {
           reporter.reportError(
-              'must be of type Either2<TextDocumentSyncOptions, num>');
+              'must be of type Either2<TextDocumentSyncOptions, TextDocumentSyncKind>');
           return false;
         }
       } finally {
@@ -18973,6 +26820,64 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('linkedEditingRangeProvider');
+      try {
+        if (obj['linkedEditingRangeProvider'] != null &&
+            !((obj['linkedEditingRangeProvider'] is bool ||
+                LinkedEditingRangeOptions.canParse(
+                    obj['linkedEditingRangeProvider'], reporter) ||
+                LinkedEditingRangeRegistrationOptions.canParse(
+                    obj['linkedEditingRangeProvider'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either3<bool, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('callHierarchyProvider');
+      try {
+        if (obj['callHierarchyProvider'] != null &&
+            !((obj['callHierarchyProvider'] is bool ||
+                CallHierarchyOptions.canParse(
+                    obj['callHierarchyProvider'], reporter) ||
+                CallHierarchyRegistrationOptions.canParse(
+                    obj['callHierarchyProvider'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either3<bool, CallHierarchyOptions, CallHierarchyRegistrationOptions>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('semanticTokensProvider');
+      try {
+        if (obj['semanticTokensProvider'] != null &&
+            !((SemanticTokensOptions.canParse(
+                    obj['semanticTokensProvider'], reporter) ||
+                SemanticTokensRegistrationOptions.canParse(
+                    obj['semanticTokensProvider'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either2<SemanticTokensOptions, SemanticTokensRegistrationOptions>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('monikerProvider');
+      try {
+        if (obj['monikerProvider'] != null &&
+            !((obj['monikerProvider'] is bool ||
+                MonikerOptions.canParse(obj['monikerProvider'], reporter) ||
+                MonikerRegistrationOptions.canParse(
+                    obj['monikerProvider'], reporter)))) {
+          reporter.reportError(
+              'must be of type Either3<bool, MonikerOptions, MonikerRegistrationOptions>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('workspaceSymbolProvider');
       try {
         if (obj['workspaceSymbolProvider'] != null &&
@@ -19041,6 +26946,10 @@
           foldingRangeProvider == other.foldingRangeProvider &&
           executeCommandProvider == other.executeCommandProvider &&
           selectionRangeProvider == other.selectionRangeProvider &&
+          linkedEditingRangeProvider == other.linkedEditingRangeProvider &&
+          callHierarchyProvider == other.callHierarchyProvider &&
+          semanticTokensProvider == other.semanticTokensProvider &&
+          monikerProvider == other.monikerProvider &&
           workspaceSymbolProvider == other.workspaceSymbolProvider &&
           workspace == other.workspace &&
           experimental == other.experimental &&
@@ -19076,6 +26985,10 @@
     hash = JenkinsSmiHash.combine(hash, foldingRangeProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, executeCommandProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, selectionRangeProvider.hashCode);
+    hash = JenkinsSmiHash.combine(hash, linkedEditingRangeProvider.hashCode);
+    hash = JenkinsSmiHash.combine(hash, callHierarchyProvider.hashCode);
+    hash = JenkinsSmiHash.combine(hash, semanticTokensProvider.hashCode);
+    hash = JenkinsSmiHash.combine(hash, monikerProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, workspaceSymbolProvider.hashCode);
     hash = JenkinsSmiHash.combine(hash, workspace.hashCode);
     hash = JenkinsSmiHash.combine(hash, experimental.hashCode);
@@ -19086,19 +26999,220 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class ServerCapabilitiesFileOperations implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      ServerCapabilitiesFileOperations.canParse,
+      ServerCapabilitiesFileOperations.fromJson);
+
+  ServerCapabilitiesFileOperations(
+      {this.didCreate,
+      this.willCreate,
+      this.didRename,
+      this.willRename,
+      this.didDelete,
+      this.willDelete});
+  static ServerCapabilitiesFileOperations fromJson(Map<String, dynamic> json) {
+    final didCreate = json['didCreate'] != null
+        ? FileOperationRegistrationOptions.fromJson(json['didCreate'])
+        : null;
+    final willCreate = json['willCreate'] != null
+        ? FileOperationRegistrationOptions.fromJson(json['willCreate'])
+        : null;
+    final didRename = json['didRename'] != null
+        ? FileOperationRegistrationOptions.fromJson(json['didRename'])
+        : null;
+    final willRename = json['willRename'] != null
+        ? FileOperationRegistrationOptions.fromJson(json['willRename'])
+        : null;
+    final didDelete = json['didDelete'] != null
+        ? FileOperationRegistrationOptions.fromJson(json['didDelete'])
+        : null;
+    final willDelete = json['willDelete'] != null
+        ? FileOperationRegistrationOptions.fromJson(json['willDelete'])
+        : null;
+    return ServerCapabilitiesFileOperations(
+        didCreate: didCreate,
+        willCreate: willCreate,
+        didRename: didRename,
+        willRename: willRename,
+        didDelete: didDelete,
+        willDelete: willDelete);
+  }
+
+  /// The server is interested in receiving didCreateFiles notifications.
+  final FileOperationRegistrationOptions didCreate;
+
+  /// The server is interested in receiving didDeleteFiles file notifications.
+  final FileOperationRegistrationOptions didDelete;
+
+  /// The server is interested in receiving didRenameFiles notifications.
+  final FileOperationRegistrationOptions didRename;
+
+  /// The server is interested in receiving willCreateFiles requests.
+  final FileOperationRegistrationOptions willCreate;
+
+  /// The server is interested in receiving willDeleteFiles file requests.
+  final FileOperationRegistrationOptions willDelete;
+
+  /// The server is interested in receiving willRenameFiles requests.
+  final FileOperationRegistrationOptions willRename;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (didCreate != null) {
+      __result['didCreate'] = didCreate.toJson();
+    }
+    if (willCreate != null) {
+      __result['willCreate'] = willCreate.toJson();
+    }
+    if (didRename != null) {
+      __result['didRename'] = didRename.toJson();
+    }
+    if (willRename != null) {
+      __result['willRename'] = willRename.toJson();
+    }
+    if (didDelete != null) {
+      __result['didDelete'] = didDelete.toJson();
+    }
+    if (willDelete != null) {
+      __result['willDelete'] = willDelete.toJson();
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('didCreate');
+      try {
+        if (obj['didCreate'] != null &&
+            !(FileOperationRegistrationOptions.canParse(
+                obj['didCreate'], reporter))) {
+          reporter
+              .reportError('must be of type FileOperationRegistrationOptions');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('willCreate');
+      try {
+        if (obj['willCreate'] != null &&
+            !(FileOperationRegistrationOptions.canParse(
+                obj['willCreate'], reporter))) {
+          reporter
+              .reportError('must be of type FileOperationRegistrationOptions');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('didRename');
+      try {
+        if (obj['didRename'] != null &&
+            !(FileOperationRegistrationOptions.canParse(
+                obj['didRename'], reporter))) {
+          reporter
+              .reportError('must be of type FileOperationRegistrationOptions');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('willRename');
+      try {
+        if (obj['willRename'] != null &&
+            !(FileOperationRegistrationOptions.canParse(
+                obj['willRename'], reporter))) {
+          reporter
+              .reportError('must be of type FileOperationRegistrationOptions');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('didDelete');
+      try {
+        if (obj['didDelete'] != null &&
+            !(FileOperationRegistrationOptions.canParse(
+                obj['didDelete'], reporter))) {
+          reporter
+              .reportError('must be of type FileOperationRegistrationOptions');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('willDelete');
+      try {
+        if (obj['willDelete'] != null &&
+            !(FileOperationRegistrationOptions.canParse(
+                obj['willDelete'], reporter))) {
+          reporter
+              .reportError('must be of type FileOperationRegistrationOptions');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type ServerCapabilitiesFileOperations');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ServerCapabilitiesFileOperations &&
+        other.runtimeType == ServerCapabilitiesFileOperations) {
+      return didCreate == other.didCreate &&
+          willCreate == other.willCreate &&
+          didRename == other.didRename &&
+          willRename == other.willRename &&
+          didDelete == other.didDelete &&
+          willDelete == other.willDelete &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, didCreate.hashCode);
+    hash = JenkinsSmiHash.combine(hash, willCreate.hashCode);
+    hash = JenkinsSmiHash.combine(hash, didRename.hashCode);
+    hash = JenkinsSmiHash.combine(hash, willRename.hashCode);
+    hash = JenkinsSmiHash.combine(hash, didDelete.hashCode);
+    hash = JenkinsSmiHash.combine(hash, willDelete.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class ServerCapabilitiesWorkspace implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       ServerCapabilitiesWorkspace.canParse,
       ServerCapabilitiesWorkspace.fromJson);
 
-  ServerCapabilitiesWorkspace({this.workspaceFolders});
+  ServerCapabilitiesWorkspace({this.workspaceFolders, this.fileOperations});
   static ServerCapabilitiesWorkspace fromJson(Map<String, dynamic> json) {
     final workspaceFolders = json['workspaceFolders'] != null
         ? WorkspaceFoldersServerCapabilities.fromJson(json['workspaceFolders'])
         : null;
-    return ServerCapabilitiesWorkspace(workspaceFolders: workspaceFolders);
+    final fileOperations = json['fileOperations'] != null
+        ? ServerCapabilitiesFileOperations.fromJson(json['fileOperations'])
+        : null;
+    return ServerCapabilitiesWorkspace(
+        workspaceFolders: workspaceFolders, fileOperations: fileOperations);
   }
 
+  /// The server is interested in file notifications/requests.
+  ///  @since 3.16.0
+  final ServerCapabilitiesFileOperations fileOperations;
+
   /// The server supports workspace folder.
   ///  @since 3.6.0
   final WorkspaceFoldersServerCapabilities workspaceFolders;
@@ -19108,6 +27222,9 @@
     if (workspaceFolders != null) {
       __result['workspaceFolders'] = workspaceFolders.toJson();
     }
+    if (fileOperations != null) {
+      __result['fileOperations'] = fileOperations.toJson();
+    }
     return __result;
   }
 
@@ -19125,6 +27242,18 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('fileOperations');
+      try {
+        if (obj['fileOperations'] != null &&
+            !(ServerCapabilitiesFileOperations.canParse(
+                obj['fileOperations'], reporter))) {
+          reporter
+              .reportError('must be of type ServerCapabilitiesFileOperations');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type ServerCapabilitiesWorkspace');
@@ -19136,7 +27265,9 @@
   bool operator ==(Object other) {
     if (other is ServerCapabilitiesWorkspace &&
         other.runtimeType == ServerCapabilitiesWorkspace) {
-      return workspaceFolders == other.workspaceFolders && true;
+      return workspaceFolders == other.workspaceFolders &&
+          fileOperations == other.fileOperations &&
+          true;
     }
     return false;
   }
@@ -19145,6 +27276,363 @@
   int get hashCode {
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, workspaceFolders.hashCode);
+    hash = JenkinsSmiHash.combine(hash, fileOperations.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class SetTraceParams implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(SetTraceParams.canParse, SetTraceParams.fromJson);
+
+  SetTraceParams({@required this.value}) {
+    if (value == null) {
+      throw 'value is required but was not provided';
+    }
+  }
+  static SetTraceParams fromJson(Map<String, dynamic> json) {
+    final value = const {'off', 'message', 'verbose'}.contains(json['value'])
+        ? json['value']
+        : throw '''${json['value']} was not one of ('off', 'message', 'verbose')''';
+    return SetTraceParams(value: value);
+  }
+
+  /// The new value that should be assigned to the trace setting.
+  final String value;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['value'] = value ?? (throw 'value is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('value');
+      try {
+        if (!obj.containsKey('value')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['value'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['value'] == 'off' ||
+            obj['value'] == 'message' ||
+            obj['value'] == 'verbose'))) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type SetTraceParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is SetTraceParams && other.runtimeType == SetTraceParams) {
+      return value == other.value && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, value.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// Client capabilities for the show document request.
+///  @since 3.16.0
+class ShowDocumentClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      ShowDocumentClientCapabilities.canParse,
+      ShowDocumentClientCapabilities.fromJson);
+
+  ShowDocumentClientCapabilities({@required this.support}) {
+    if (support == null) {
+      throw 'support is required but was not provided';
+    }
+  }
+  static ShowDocumentClientCapabilities fromJson(Map<String, dynamic> json) {
+    final support = json['support'];
+    return ShowDocumentClientCapabilities(support: support);
+  }
+
+  /// The client has support for the show document request.
+  final bool support;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['support'] =
+        support ?? (throw 'support is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('support');
+      try {
+        if (!obj.containsKey('support')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['support'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['support'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type ShowDocumentClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ShowDocumentClientCapabilities &&
+        other.runtimeType == ShowDocumentClientCapabilities) {
+      return support == other.support && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, support.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// Params to show a document.
+///  @since 3.16.0
+class ShowDocumentParams implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(ShowDocumentParams.canParse, ShowDocumentParams.fromJson);
+
+  ShowDocumentParams(
+      {@required this.uri, this.external, this.takeFocus, this.selection}) {
+    if (uri == null) {
+      throw 'uri is required but was not provided';
+    }
+  }
+  static ShowDocumentParams fromJson(Map<String, dynamic> json) {
+    final uri = json['uri'];
+    final external = json['external'];
+    final takeFocus = json['takeFocus'];
+    final selection =
+        json['selection'] != null ? Range.fromJson(json['selection']) : null;
+    return ShowDocumentParams(
+        uri: uri,
+        external: external,
+        takeFocus: takeFocus,
+        selection: selection);
+  }
+
+  /// Indicates to show the resource in an external program. To show for example
+  /// `https://code.visualstudio.com/` in the default WEB browser set `external`
+  /// to `true`.
+  final bool external;
+
+  /// An optional selection range if the document is a text document. Clients
+  /// might ignore the property if an external program is started or the file is
+  /// not a text file.
+  final Range selection;
+
+  /// An optional property to indicate whether the editor showing the document
+  /// should take focus or not. Clients might ignore this property if an
+  /// external program is started.
+  final bool takeFocus;
+
+  /// The document uri to show.
+  final String uri;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['uri'] = uri ?? (throw 'uri is required but was not set');
+    if (external != null) {
+      __result['external'] = external;
+    }
+    if (takeFocus != null) {
+      __result['takeFocus'] = takeFocus;
+    }
+    if (selection != null) {
+      __result['selection'] = selection.toJson();
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('uri');
+      try {
+        if (!obj.containsKey('uri')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['uri'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['uri'] is String)) {
+          reporter.reportError('must be of type String');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('external');
+      try {
+        if (obj['external'] != null && !(obj['external'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('takeFocus');
+      try {
+        if (obj['takeFocus'] != null && !(obj['takeFocus'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('selection');
+      try {
+        if (obj['selection'] != null &&
+            !(Range.canParse(obj['selection'], reporter))) {
+          reporter.reportError('must be of type Range');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type ShowDocumentParams');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ShowDocumentParams &&
+        other.runtimeType == ShowDocumentParams) {
+      return uri == other.uri &&
+          external == other.external &&
+          takeFocus == other.takeFocus &&
+          selection == other.selection &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, external.hashCode);
+    hash = JenkinsSmiHash.combine(hash, takeFocus.hashCode);
+    hash = JenkinsSmiHash.combine(hash, selection.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+/// The result of an show document request.
+///  @since 3.16.0
+class ShowDocumentResult implements ToJsonable {
+  static const jsonHandler =
+      LspJsonHandler(ShowDocumentResult.canParse, ShowDocumentResult.fromJson);
+
+  ShowDocumentResult({@required this.success}) {
+    if (success == null) {
+      throw 'success is required but was not provided';
+    }
+  }
+  static ShowDocumentResult fromJson(Map<String, dynamic> json) {
+    final success = json['success'];
+    return ShowDocumentResult(success: success);
+  }
+
+  /// A boolean indicating if the show was successful.
+  final bool success;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['success'] =
+        success ?? (throw 'success is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('success');
+      try {
+        if (!obj.containsKey('success')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['success'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['success'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError('must be of type ShowDocumentResult');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ShowDocumentResult &&
+        other.runtimeType == ShowDocumentResult) {
+      return success == other.success && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, success.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -19249,6 +27737,145 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// Show message request client capabilities
+class ShowMessageRequestClientCapabilities implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      ShowMessageRequestClientCapabilities.canParse,
+      ShowMessageRequestClientCapabilities.fromJson);
+
+  ShowMessageRequestClientCapabilities({this.messageActionItem});
+  static ShowMessageRequestClientCapabilities fromJson(
+      Map<String, dynamic> json) {
+    final messageActionItem = json['messageActionItem'] != null
+        ? ShowMessageRequestClientCapabilitiesMessageActionItem.fromJson(
+            json['messageActionItem'])
+        : null;
+    return ShowMessageRequestClientCapabilities(
+        messageActionItem: messageActionItem);
+  }
+
+  /// Capabilities specific to the `MessageActionItem` type.
+  final ShowMessageRequestClientCapabilitiesMessageActionItem messageActionItem;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (messageActionItem != null) {
+      __result['messageActionItem'] = messageActionItem.toJson();
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('messageActionItem');
+      try {
+        if (obj['messageActionItem'] != null &&
+            !(ShowMessageRequestClientCapabilitiesMessageActionItem.canParse(
+                obj['messageActionItem'], reporter))) {
+          reporter.reportError(
+              'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter
+          .reportError('must be of type ShowMessageRequestClientCapabilities');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ShowMessageRequestClientCapabilities &&
+        other.runtimeType == ShowMessageRequestClientCapabilities) {
+      return messageActionItem == other.messageActionItem && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, messageActionItem.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class ShowMessageRequestClientCapabilitiesMessageActionItem
+    implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      ShowMessageRequestClientCapabilitiesMessageActionItem.canParse,
+      ShowMessageRequestClientCapabilitiesMessageActionItem.fromJson);
+
+  ShowMessageRequestClientCapabilitiesMessageActionItem(
+      {this.additionalPropertiesSupport});
+  static ShowMessageRequestClientCapabilitiesMessageActionItem fromJson(
+      Map<String, dynamic> json) {
+    final additionalPropertiesSupport = json['additionalPropertiesSupport'];
+    return ShowMessageRequestClientCapabilitiesMessageActionItem(
+        additionalPropertiesSupport: additionalPropertiesSupport);
+  }
+
+  /// Whether the client supports additional attributes which are preserved and
+  /// sent back to the server in the request's response.
+  final bool additionalPropertiesSupport;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (additionalPropertiesSupport != null) {
+      __result['additionalPropertiesSupport'] = additionalPropertiesSupport;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('additionalPropertiesSupport');
+      try {
+        if (obj['additionalPropertiesSupport'] != null &&
+            !(obj['additionalPropertiesSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type ShowMessageRequestClientCapabilitiesMessageActionItem');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is ShowMessageRequestClientCapabilitiesMessageActionItem &&
+        other.runtimeType ==
+            ShowMessageRequestClientCapabilitiesMessageActionItem) {
+      return additionalPropertiesSupport == other.additionalPropertiesSupport &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, additionalPropertiesSupport.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class ShowMessageRequestParams implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       ShowMessageRequestParams.canParse, ShowMessageRequestParams.fromJson);
@@ -19703,7 +28330,9 @@
       SignatureHelpClientCapabilitiesSignatureInformation.fromJson);
 
   SignatureHelpClientCapabilitiesSignatureInformation(
-      {this.documentationFormat, this.parameterInformation});
+      {this.documentationFormat,
+      this.parameterInformation,
+      this.activeParameterSupport});
   static SignatureHelpClientCapabilitiesSignatureInformation fromJson(
       Map<String, dynamic> json) {
     final documentationFormat = json['documentationFormat']
@@ -19714,11 +28343,18 @@
         ? SignatureHelpClientCapabilitiesParameterInformation.fromJson(
             json['parameterInformation'])
         : null;
+    final activeParameterSupport = json['activeParameterSupport'];
     return SignatureHelpClientCapabilitiesSignatureInformation(
         documentationFormat: documentationFormat,
-        parameterInformation: parameterInformation);
+        parameterInformation: parameterInformation,
+        activeParameterSupport: activeParameterSupport);
   }
 
+  /// The client supports the `activeParameter` property on
+  /// `SignatureInformation` literal.
+  ///  @since 3.16.0
+  final bool activeParameterSupport;
+
   /// Client supports the follow content formats for the documentation property.
   /// The order describes the preferred format of the client.
   final List<MarkupKind> documentationFormat;
@@ -19735,6 +28371,9 @@
     if (parameterInformation != null) {
       __result['parameterInformation'] = parameterInformation.toJson();
     }
+    if (activeParameterSupport != null) {
+      __result['activeParameterSupport'] = activeParameterSupport;
+    }
     return __result;
   }
 
@@ -19764,6 +28403,16 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('activeParameterSupport');
+      try {
+        if (obj['activeParameterSupport'] != null &&
+            !(obj['activeParameterSupport'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError(
@@ -19780,6 +28429,7 @@
       return listEqual(documentationFormat, other.documentationFormat,
               (MarkupKind a, MarkupKind b) => a == b) &&
           parameterInformation == other.parameterInformation &&
+          activeParameterSupport == other.activeParameterSupport &&
           true;
     }
     return false;
@@ -19790,6 +28440,7 @@
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, lspHashCode(documentationFormat));
     hash = JenkinsSmiHash.combine(hash, parameterInformation.hashCode);
+    hash = JenkinsSmiHash.combine(hash, activeParameterSupport.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -19847,8 +28498,8 @@
 
   /// Character that caused signature help to be triggered.
   ///
-  /// This is undefined when `triggerKind !==
-  /// SignatureHelpTriggerKind.TriggerCharacter`.
+  /// This is undefined when triggerKind !==
+  /// SignatureHelpTriggerKind.TriggerCharacter
   final String triggerCharacter;
 
   /// Action that caused signature help to be triggered.
@@ -20123,7 +28774,7 @@
 
   /// The signature help context. This is only available if the client specifies
   /// to send this using the client capability
-  /// `textDocument.signatureHelp.contextSupport === true`.
+  /// `textDocument.signatureHelp.contextSupport === true`
   ///  @since 3.15.0
   final SignatureHelpContext context;
 
@@ -20278,7 +28929,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// List of characters that re-trigger signature help.
@@ -20436,7 +29087,10 @@
       SignatureInformation.canParse, SignatureInformation.fromJson);
 
   SignatureInformation(
-      {@required this.label, this.documentation, this.parameters}) {
+      {@required this.label,
+      this.documentation,
+      this.parameters,
+      this.activeParameter}) {
     if (label == null) {
       throw 'label is required but was not provided';
     }
@@ -20457,10 +29111,20 @@
             (item) => item != null ? ParameterInformation.fromJson(item) : null)
         ?.cast<ParameterInformation>()
         ?.toList();
+    final activeParameter = json['activeParameter'];
     return SignatureInformation(
-        label: label, documentation: documentation, parameters: parameters);
+        label: label,
+        documentation: documentation,
+        parameters: parameters,
+        activeParameter: activeParameter);
   }
 
+  /// The index of the active parameter.
+  ///
+  /// If provided, this is used in place of `SignatureHelp.activeParameter`.
+  ///  @since 3.16.0
+  final num activeParameter;
+
   /// The human-readable doc-comment of this signature. Will be shown in the UI
   /// but can be omitted.
   final Either2<String, MarkupContent> documentation;
@@ -20480,6 +29144,9 @@
     if (parameters != null) {
       __result['parameters'] = parameters;
     }
+    if (activeParameter != null) {
+      __result['activeParameter'] = activeParameter;
+    }
     return __result;
   }
 
@@ -20526,6 +29193,16 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('activeParameter');
+      try {
+        if (obj['activeParameter'] != null &&
+            !(obj['activeParameter'] is num)) {
+          reporter.reportError('must be of type num');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type SignatureInformation');
@@ -20541,6 +29218,7 @@
           documentation == other.documentation &&
           listEqual(parameters, other.parameters,
               (ParameterInformation a, ParameterInformation b) => a == b) &&
+          activeParameter == other.activeParameter &&
           true;
     }
     return false;
@@ -20552,6 +29230,7 @@
     hash = JenkinsSmiHash.combine(hash, label.hashCode);
     hash = JenkinsSmiHash.combine(hash, documentation.hashCode);
     hash = JenkinsSmiHash.combine(hash, lspHashCode(parameters));
+    hash = JenkinsSmiHash.combine(hash, activeParameter.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -20584,6 +29263,16 @@
     if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
       return SelectionRangeRegistrationOptions.fromJson(json);
     }
+    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyRegistrationOptions.fromJson(json);
+    }
+    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensRegistrationOptions.fromJson(json);
+    }
+    if (LinkedEditingRangeRegistrationOptions.canParse(
+        json, nullLspJsonReporter)) {
+      return LinkedEditingRangeRegistrationOptions.fromJson(json);
+    }
     final id = json['id'];
     return StaticRegistrationOptions(id: id);
   }
@@ -20647,6 +29336,7 @@
   SymbolInformation(
       {@required this.name,
       @required this.kind,
+      this.tags,
       this.deprecated,
       @required this.location,
       this.containerName}) {
@@ -20664,6 +29354,10 @@
     final name = json['name'];
     final kind =
         json['kind'] != null ? SymbolKind.fromJson(json['kind']) : null;
+    final tags = json['tags']
+        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
+        ?.cast<SymbolTag>()
+        ?.toList();
     final deprecated = json['deprecated'];
     final location =
         json['location'] != null ? Location.fromJson(json['location']) : null;
@@ -20671,6 +29365,7 @@
     return SymbolInformation(
         name: name,
         kind: kind,
+        tags: tags,
         deprecated: deprecated,
         location: location,
         containerName: containerName);
@@ -20683,6 +29378,7 @@
   final String containerName;
 
   /// Indicates if this symbol is deprecated.
+  ///  @deprecated Use tags instead
   final bool deprecated;
 
   /// The kind of this symbol.
@@ -20702,11 +29398,18 @@
   /// The name of this symbol.
   final String name;
 
+  /// Tags for this completion item.
+  ///  @since 3.16.0
+  final List<SymbolTag> tags;
+
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['name'] = name ?? (throw 'name is required but was not set');
     __result['kind'] =
         kind?.toJson() ?? (throw 'kind is required but was not set');
+    if (tags != null) {
+      __result['tags'] = tags;
+    }
     if (deprecated != null) {
       __result['deprecated'] = deprecated;
     }
@@ -20754,6 +29457,18 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('tags');
+      try {
+        if (obj['tags'] != null &&
+            !((obj['tags'] is List &&
+                (obj['tags']
+                    .every((item) => SymbolTag.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<SymbolTag>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       reporter.push('deprecated');
       try {
         if (obj['deprecated'] != null && !(obj['deprecated'] is bool)) {
@@ -20801,6 +29516,7 @@
     if (other is SymbolInformation && other.runtimeType == SymbolInformation) {
       return name == other.name &&
           kind == other.kind &&
+          listEqual(tags, other.tags, (SymbolTag a, SymbolTag b) => a == b) &&
           deprecated == other.deprecated &&
           location == other.location &&
           containerName == other.containerName &&
@@ -20814,6 +29530,7 @@
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, name.hashCode);
     hash = JenkinsSmiHash.combine(hash, kind.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(tags));
     hash = JenkinsSmiHash.combine(hash, deprecated.hashCode);
     hash = JenkinsSmiHash.combine(hash, location.hashCode);
     hash = JenkinsSmiHash.combine(hash, containerName.hashCode);
@@ -20873,6 +29590,32 @@
   bool operator ==(Object o) => o is SymbolKind && o._value == _value;
 }
 
+/// Symbol tags are extra annotations that tweak the rendering of a symbol.
+///  @since 3.16
+class SymbolTag {
+  const SymbolTag(this._value);
+  const SymbolTag.fromJson(this._value);
+
+  final num _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is num;
+  }
+
+  /// Render a symbol as obsolete, usually using a strike-out.
+  static const Deprecated = SymbolTag(1);
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) => o is SymbolTag && o._value == _value;
+}
+
 /// Describe options to be used when registering for text document change
 /// events.
 class TextDocumentChangeRegistrationOptions
@@ -20901,7 +29644,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// How documents are synced to the server. See TextDocumentSyncKind.Full and
@@ -21011,7 +29754,11 @@
       this.rename,
       this.publishDiagnostics,
       this.foldingRange,
-      this.selectionRange});
+      this.selectionRange,
+      this.linkedEditingRange,
+      this.callHierarchy,
+      this.semanticTokens,
+      this.moniker});
   static TextDocumentClientCapabilities fromJson(Map<String, dynamic> json) {
     final synchronization = json['synchronization'] != null
         ? TextDocumentSyncClientCapabilities.fromJson(json['synchronization'])
@@ -21083,6 +29830,19 @@
     final selectionRange = json['selectionRange'] != null
         ? SelectionRangeClientCapabilities.fromJson(json['selectionRange'])
         : null;
+    final linkedEditingRange = json['linkedEditingRange'] != null
+        ? LinkedEditingRangeClientCapabilities.fromJson(
+            json['linkedEditingRange'])
+        : null;
+    final callHierarchy = json['callHierarchy'] != null
+        ? CallHierarchyClientCapabilities.fromJson(json['callHierarchy'])
+        : null;
+    final semanticTokens = json['semanticTokens'] != null
+        ? SemanticTokensClientCapabilities.fromJson(json['semanticTokens'])
+        : null;
+    final moniker = json['moniker'] != null
+        ? MonikerClientCapabilities.fromJson(json['moniker'])
+        : null;
     return TextDocumentClientCapabilities(
         synchronization: synchronization,
         completion: completion,
@@ -21105,9 +29865,17 @@
         rename: rename,
         publishDiagnostics: publishDiagnostics,
         foldingRange: foldingRange,
-        selectionRange: selectionRange);
+        selectionRange: selectionRange,
+        linkedEditingRange: linkedEditingRange,
+        callHierarchy: callHierarchy,
+        semanticTokens: semanticTokens,
+        moniker: moniker);
   }
 
+  /// Capabilities specific to the various call hierarchy requests.
+  ///  @since 3.16.0
+  final CallHierarchyClientCapabilities callHierarchy;
+
   /// Capabilities specific to the `textDocument/codeAction` request.
   final CodeActionClientCapabilities codeAction;
 
@@ -21152,6 +29920,14 @@
   ///  @since 3.6.0
   final ImplementationClientCapabilities implementation;
 
+  /// Capabilities specific to the `textDocument/linkedEditingRange` request.
+  ///  @since 3.16.0
+  final LinkedEditingRangeClientCapabilities linkedEditingRange;
+
+  /// Capabilities specific to the `textDocument/moniker` request.
+  ///  @since 3.16.0
+  final MonikerClientCapabilities moniker;
+
   /// request. Capabilities specific to the `textDocument/onTypeFormatting`
   /// request.
   final DocumentOnTypeFormattingClientCapabilities onTypeFormatting;
@@ -21173,6 +29949,10 @@
   ///  @since 3.15.0
   final SelectionRangeClientCapabilities selectionRange;
 
+  /// Capabilities specific to the various semantic token requests.
+  ///  @since 3.16.0
+  final SemanticTokensClientCapabilities semanticTokens;
+
   /// Capabilities specific to the `textDocument/signatureHelp` request.
   final SignatureHelpClientCapabilities signatureHelp;
   final TextDocumentSyncClientCapabilities synchronization;
@@ -21249,6 +30029,18 @@
     if (selectionRange != null) {
       __result['selectionRange'] = selectionRange.toJson();
     }
+    if (linkedEditingRange != null) {
+      __result['linkedEditingRange'] = linkedEditingRange.toJson();
+    }
+    if (callHierarchy != null) {
+      __result['callHierarchy'] = callHierarchy.toJson();
+    }
+    if (semanticTokens != null) {
+      __result['semanticTokens'] = semanticTokens.toJson();
+    }
+    if (moniker != null) {
+      __result['moniker'] = moniker.toJson();
+    }
     return __result;
   }
 
@@ -21507,6 +30299,52 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('linkedEditingRange');
+      try {
+        if (obj['linkedEditingRange'] != null &&
+            !(LinkedEditingRangeClientCapabilities.canParse(
+                obj['linkedEditingRange'], reporter))) {
+          reporter.reportError(
+              'must be of type LinkedEditingRangeClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('callHierarchy');
+      try {
+        if (obj['callHierarchy'] != null &&
+            !(CallHierarchyClientCapabilities.canParse(
+                obj['callHierarchy'], reporter))) {
+          reporter
+              .reportError('must be of type CallHierarchyClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('semanticTokens');
+      try {
+        if (obj['semanticTokens'] != null &&
+            !(SemanticTokensClientCapabilities.canParse(
+                obj['semanticTokens'], reporter))) {
+          reporter
+              .reportError('must be of type SemanticTokensClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('moniker');
+      try {
+        if (obj['moniker'] != null &&
+            !(MonikerClientCapabilities.canParse(obj['moniker'], reporter))) {
+          reporter.reportError('must be of type MonikerClientCapabilities');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type TextDocumentClientCapabilities');
@@ -21540,6 +30378,10 @@
           publishDiagnostics == other.publishDiagnostics &&
           foldingRange == other.foldingRange &&
           selectionRange == other.selectionRange &&
+          linkedEditingRange == other.linkedEditingRange &&
+          callHierarchy == other.callHierarchy &&
+          semanticTokens == other.semanticTokens &&
+          moniker == other.moniker &&
           true;
     }
     return false;
@@ -21570,6 +30412,10 @@
     hash = JenkinsSmiHash.combine(hash, publishDiagnostics.hashCode);
     hash = JenkinsSmiHash.combine(hash, foldingRange.hashCode);
     hash = JenkinsSmiHash.combine(hash, selectionRange.hashCode);
+    hash = JenkinsSmiHash.combine(hash, linkedEditingRange.hashCode);
+    hash = JenkinsSmiHash.combine(hash, callHierarchy.hashCode);
+    hash = JenkinsSmiHash.combine(hash, semanticTokens.hashCode);
+    hash = JenkinsSmiHash.combine(hash, moniker.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -21781,20 +30627,28 @@
   }
   static TextDocumentEdit fromJson(Map<String, dynamic> json) {
     final textDocument = json['textDocument'] != null
-        ? VersionedTextDocumentIdentifier.fromJson(json['textDocument'])
+        ? OptionalVersionedTextDocumentIdentifier.fromJson(json['textDocument'])
         : null;
     final edits = json['edits']
-        ?.map((item) => item != null ? TextEdit.fromJson(item) : null)
-        ?.cast<TextEdit>()
+        ?.map((item) => TextEdit.canParse(item, nullLspJsonReporter)
+            ? Either2<TextEdit, AnnotatedTextEdit>.t1(
+                item != null ? TextEdit.fromJson(item) : null)
+            : (AnnotatedTextEdit.canParse(item, nullLspJsonReporter)
+                ? Either2<TextEdit, AnnotatedTextEdit>.t2(
+                    item != null ? AnnotatedTextEdit.fromJson(item) : null)
+                : (throw '''${item} was not one of (TextEdit, AnnotatedTextEdit)''')))
+        ?.cast<Either2<TextEdit, AnnotatedTextEdit>>()
         ?.toList();
     return TextDocumentEdit(textDocument: textDocument, edits: edits);
   }
 
   /// The edits to be applied.
-  final List<TextEdit> edits;
+  ///  @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
+  /// client capability `workspace.workspaceEdit.changeAnnotationSupport`
+  final List<Either2<TextEdit, AnnotatedTextEdit>> edits;
 
   /// The text document to change.
-  final VersionedTextDocumentIdentifier textDocument;
+  final OptionalVersionedTextDocumentIdentifier textDocument;
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
@@ -21816,10 +30670,10 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(VersionedTextDocumentIdentifier.canParse(
+        if (!(OptionalVersionedTextDocumentIdentifier.canParse(
             obj['textDocument'], reporter))) {
-          reporter
-              .reportError('must be of type VersionedTextDocumentIdentifier');
+          reporter.reportError(
+              'must be of type OptionalVersionedTextDocumentIdentifier');
           return false;
         }
       } finally {
@@ -21836,9 +30690,10 @@
           return false;
         }
         if (!((obj['edits'] is List &&
-            (obj['edits']
-                .every((item) => TextEdit.canParse(item, reporter)))))) {
-          reporter.reportError('must be of type List<TextEdit>');
+            (obj['edits'].every((item) => (TextEdit.canParse(item, reporter) ||
+                AnnotatedTextEdit.canParse(item, reporter))))))) {
+          reporter.reportError(
+              'must be of type List<Either2<TextEdit, AnnotatedTextEdit>>');
           return false;
         }
       } finally {
@@ -21855,7 +30710,12 @@
   bool operator ==(Object other) {
     if (other is TextDocumentEdit && other.runtimeType == TextDocumentEdit) {
       return textDocument == other.textDocument &&
-          listEqual(edits, other.edits, (TextEdit a, TextEdit b) => a == b) &&
+          listEqual(
+              edits,
+              other.edits,
+              (Either2<TextEdit, AnnotatedTextEdit> a,
+                      Either2<TextEdit, AnnotatedTextEdit> b) =>
+                  a == b) &&
           true;
     }
     return false;
@@ -21886,6 +30746,10 @@
     if (VersionedTextDocumentIdentifier.canParse(json, nullLspJsonReporter)) {
       return VersionedTextDocumentIdentifier.fromJson(json);
     }
+    if (OptionalVersionedTextDocumentIdentifier.canParse(
+        json, nullLspJsonReporter)) {
+      return OptionalVersionedTextDocumentIdentifier.fromJson(json);
+    }
     final uri = json['uri'];
     return TextDocumentIdentifier(uri: uri);
   }
@@ -22153,6 +31017,15 @@
     if (PrepareRenameParams.canParse(json, nullLspJsonReporter)) {
       return PrepareRenameParams.fromJson(json);
     }
+    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyPrepareParams.fromJson(json);
+    }
+    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
+      return LinkedEditingRangeParams.fromJson(json);
+    }
+    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
+      return MonikerParams.fromJson(json);
+    }
     final textDocument = json['textDocument'] != null
         ? TextDocumentIdentifier.fromJson(json['textDocument'])
         : null;
@@ -22323,6 +31196,19 @@
     if (SelectionRangeRegistrationOptions.canParse(json, nullLspJsonReporter)) {
       return SelectionRangeRegistrationOptions.fromJson(json);
     }
+    if (CallHierarchyRegistrationOptions.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyRegistrationOptions.fromJson(json);
+    }
+    if (SemanticTokensRegistrationOptions.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensRegistrationOptions.fromJson(json);
+    }
+    if (LinkedEditingRangeRegistrationOptions.canParse(
+        json, nullLspJsonReporter)) {
+      return LinkedEditingRangeRegistrationOptions.fromJson(json);
+    }
+    if (MonikerRegistrationOptions.canParse(json, nullLspJsonReporter)) {
+      return MonikerRegistrationOptions.fromJson(json);
+    }
     final documentSelector = json['documentSelector']
         ?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
         ?.cast<DocumentFilter>()
@@ -22331,7 +31217,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   Map<String, dynamic> toJson() {
@@ -22398,8 +31284,8 @@
     return obj is num;
   }
 
-  /// Manually triggered, for example, by the user pressing save, by starting
-  /// debugging, or by an API call.
+  /// Manually triggered, e.g. by the user pressing save, by starting debugging,
+  /// or by an API call.
   static const Manual = TextDocumentSaveReason(1);
 
   /// Automatic after a delay.
@@ -22440,7 +31326,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// The client is supposed to include the content on save.
@@ -22711,25 +31597,25 @@
   }
 
   /// Change notifications are sent to the server. See
-  /// TextDocumentSyncKind.None, TextDocumentSyncKind.Full, and
-  /// TextDocumentSyncKind.Incremental. If omitted, it defaults to
+  /// TextDocumentSyncKind.None, TextDocumentSyncKind.Full and
+  /// TextDocumentSyncKind.Incremental. If omitted it defaults to
   /// TextDocumentSyncKind.None.
   final TextDocumentSyncKind change;
 
-  /// Open and close notifications are sent to the server. If omitted, open
-  /// close notification should not be sent.
+  /// Open and close notifications are sent to the server. If omitted open close
+  /// notification should not be sent.
   final bool openClose;
 
-  /// If present save notifications are sent to the server. If omitted, the
+  /// If present save notifications are sent to the server. If omitted the
   /// notification should not be sent.
   final Either2<bool, SaveOptions> save;
 
-  /// If present will save notifications are sent to the server. If omitted, the
+  /// If present will save notifications are sent to the server. If omitted the
   /// notification should not be sent.
   final bool willSave;
 
   /// If present will save wait until requests are sent to the server. If
-  /// omitted, the request should not be sent.
+  /// omitted the request should not be sent.
   final bool willSaveWaitUntil;
 
   Map<String, dynamic> toJson() {
@@ -22852,6 +31738,9 @@
     }
   }
   static TextEdit fromJson(Map<String, dynamic> json) {
+    if (AnnotatedTextEdit.canParse(json, nullLspJsonReporter)) {
+      return AnnotatedTextEdit.fromJson(json);
+    }
     final range = json['range'] != null ? Range.fromJson(json['range']) : null;
     final newText = json['newText'];
     return TextEdit(range: range, newText: newText);
@@ -22936,6 +31825,29 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class TokenFormat {
+  const TokenFormat(this._value);
+  const TokenFormat.fromJson(this._value);
+
+  final String _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is String;
+  }
+
+  static const Relative = TokenFormat(r'relative');
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) => o is TokenFormat && o._value == _value;
+}
+
 class TypeDefinitionClientCapabilities implements ToJsonable {
   static const jsonHandler = LspJsonHandler(
       TypeDefinitionClientCapabilities.canParse,
@@ -22951,7 +31863,7 @@
   }
 
   /// Whether implementation supports dynamic registration. If this is set to
-  /// `true`, the client supports the new ` TypeDefinitionRegistrationOptions`
+  /// `true` the client supports the new `TypeDefinitionRegistrationOptions`
   /// return value for the corresponding server capability as well.
   final bool dynamicRegistration;
 
@@ -23131,8 +32043,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// The position inside the text document.
@@ -23277,7 +32189,7 @@
   }
 
   /// A document selector to identify the scope of the registration. If set to
-  /// null, the document selector provided on the client side will be used.
+  /// null the document selector provided on the client side will be used.
   final List<DocumentFilter> documentSelector;
 
   /// The id used to register the request. The id can be used to deregister the
@@ -23367,6 +32279,43 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+/// Moniker uniqueness level to define scope of the moniker.
+class UniquenessLevel {
+  const UniquenessLevel(this._value);
+  const UniquenessLevel.fromJson(this._value);
+
+  final String _value;
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    return obj is String;
+  }
+
+  /// The moniker is only unique inside a document
+  static const document = UniquenessLevel(r'document');
+
+  /// The moniker is unique inside a project for which a dump got created
+  static const project = UniquenessLevel(r'project');
+
+  /// The moniker is unique inside the group to which a project belongs
+  static const group = UniquenessLevel(r'group');
+
+  /// The moniker is unique inside the moniker scheme.
+  static const scheme = UniquenessLevel(r'scheme');
+
+  /// The moniker is globally unique
+  static const global = UniquenessLevel(r'global');
+
+  Object toJson() => _value;
+
+  @override
+  String toString() => _value.toString();
+
+  @override
+  int get hashCode => _value.hashCode;
+
+  bool operator ==(Object o) => o is UniquenessLevel && o._value == _value;
+}
+
 /// General parameters to unregister a capability.
 class Unregistration implements ToJsonable {
   static const jsonHandler =
@@ -23548,7 +32497,11 @@
       VersionedTextDocumentIdentifier.canParse,
       VersionedTextDocumentIdentifier.fromJson);
 
-  VersionedTextDocumentIdentifier({this.version, @required this.uri}) {
+  VersionedTextDocumentIdentifier(
+      {@required this.version, @required this.uri}) {
+    if (version == null) {
+      throw 'version is required but was not provided';
+    }
     if (uri == null) {
       throw 'uri is required but was not provided';
     }
@@ -23562,12 +32515,7 @@
   /// The text document's URI.
   final String uri;
 
-  /// The version number of this document. If a versioned text document
-  /// identifier is sent from the server to the client and the file is not open
-  /// in the editor (the server has not received an open notification before),
-  /// the server can send `null` to indicate that the version is known and the
-  /// content on disk is the master (as specified with document content
-  /// ownership).
+  /// The version number of this document.
   ///
   /// The version number of a document will increase after each change,
   /// including undo/redo. The number doesn't need to be consecutive.
@@ -23575,7 +32523,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['version'] = version;
+    __result['version'] =
+        version ?? (throw 'version is required but was not set');
     __result['uri'] = uri ?? (throw 'uri is required but was not set');
     return __result;
   }
@@ -23588,7 +32537,11 @@
           reporter.reportError('must not be undefined');
           return false;
         }
-        if (obj['version'] != null && !(obj['version'] is num)) {
+        if (obj['version'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!(obj['version'] is num)) {
           reporter.reportError('must be of type num');
           return false;
         }
@@ -23688,13 +32641,15 @@
     final textDocument = json['textDocument'] != null
         ? TextDocumentIdentifier.fromJson(json['textDocument'])
         : null;
-    final reason = json['reason'];
+    final reason = json['reason'] != null
+        ? TextDocumentSaveReason.fromJson(json['reason'])
+        : null;
     return WillSaveTextDocumentParams(
         textDocument: textDocument, reason: reason);
   }
 
   /// The 'TextDocumentSaveReason'.
-  final num reason;
+  final TextDocumentSaveReason reason;
 
   /// The document that will be saved.
   final TextDocumentIdentifier textDocument;
@@ -23703,7 +32658,8 @@
     var __result = <String, dynamic>{};
     __result['textDocument'] = textDocument?.toJson() ??
         (throw 'textDocument is required but was not set');
-    __result['reason'] = reason ?? (throw 'reason is required but was not set');
+    __result['reason'] =
+        reason?.toJson() ?? (throw 'reason is required but was not set');
     return __result;
   }
 
@@ -23736,8 +32692,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['reason'] is num)) {
-          reporter.reportError('must be of type num');
+        if (!(TextDocumentSaveReason.canParse(obj['reason'], reporter))) {
+          reporter.reportError('must be of type TextDocumentSaveReason');
           return false;
         }
       } finally {
@@ -23805,8 +32761,8 @@
   }
 
   /// Controls if a cancel button should show to allow the user to cancel the
-  /// long running operation. Clients that don't support cancellation can ignore
-  /// the setting.
+  /// long running operation. Clients that don't support cancellation are
+  /// allowed to ignore the setting.
   final bool cancellable;
   final String kind;
 
@@ -23822,7 +32778,7 @@
   /// ignore the `percentage` value in subsequent in report notifications.
   ///
   /// The value should be steadily rising. Clients are free to ignore values
-  /// that are not following this rule.
+  /// that are not following this rule. The value range is [0, 100]
   final num percentage;
 
   /// Mandatory title of the progress operation. Used to briefly inform about
@@ -24249,6 +33205,18 @@
     if (SelectionRangeOptions.canParse(json, nullLspJsonReporter)) {
       return SelectionRangeOptions.fromJson(json);
     }
+    if (CallHierarchyOptions.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyOptions.fromJson(json);
+    }
+    if (SemanticTokensOptions.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensOptions.fromJson(json);
+    }
+    if (LinkedEditingRangeOptions.canParse(json, nullLspJsonReporter)) {
+      return LinkedEditingRangeOptions.fromJson(json);
+    }
+    if (MonikerOptions.canParse(json, nullLspJsonReporter)) {
+      return MonikerOptions.fromJson(json);
+    }
     final workDoneProgress = json['workDoneProgress'];
     return WorkDoneProgressOptions(workDoneProgress: workDoneProgress);
   }
@@ -24377,6 +33345,30 @@
     if (SelectionRangeParams.canParse(json, nullLspJsonReporter)) {
       return SelectionRangeParams.fromJson(json);
     }
+    if (CallHierarchyPrepareParams.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyPrepareParams.fromJson(json);
+    }
+    if (CallHierarchyIncomingCallsParams.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyIncomingCallsParams.fromJson(json);
+    }
+    if (CallHierarchyOutgoingCallsParams.canParse(json, nullLspJsonReporter)) {
+      return CallHierarchyOutgoingCallsParams.fromJson(json);
+    }
+    if (SemanticTokensParams.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensParams.fromJson(json);
+    }
+    if (SemanticTokensDeltaParams.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensDeltaParams.fromJson(json);
+    }
+    if (SemanticTokensRangeParams.canParse(json, nullLspJsonReporter)) {
+      return SemanticTokensRangeParams.fromJson(json);
+    }
+    if (LinkedEditingRangeParams.canParse(json, nullLspJsonReporter)) {
+      return LinkedEditingRangeParams.fromJson(json);
+    }
+    if (MonikerParams.canParse(json, nullLspJsonReporter)) {
+      return MonikerParams.fromJson(json);
+    }
     final workDoneToken = json['workDoneToken'] is num
         ? Either2<num, String>.t1(json['workDoneToken'])
         : (json['workDoneToken'] is String
@@ -24460,11 +33452,11 @@
         percentage: percentage);
   }
 
-  /// Controls enablement state of a cancel button. T This property is only
-  /// valid if a cancel button is requested in the `WorkDoneProgressStart`
-  /// payload.
+  /// Controls enablement state of a cancel button. This property is only valid
   ///
-  /// Clients that don't support cancellation or don't support controlling the
+  /// if a cancel button got requested in the `WorkDoneProgressStart` payload.
+  ///
+  /// Clients that don't support cancellation or don't support control the
   /// button's enablement state are allowed to ignore the setting.
   final bool cancellable;
   final String kind;
@@ -24481,7 +33473,7 @@
   /// ignore the `percentage` value in subsequent in report notifications.
   ///
   /// The value should be steadily rising. Clients are free to ignore values
-  /// that are not following this rule.
+  /// that are not following this rule. The value range is [0, 100]
   final num percentage;
 
   Map<String, dynamic> toJson() {
@@ -24583,7 +33575,7 @@
   static const jsonHandler =
       LspJsonHandler(WorkspaceEdit.canParse, WorkspaceEdit.fromJson);
 
-  WorkspaceEdit({this.changes, this.documentChanges});
+  WorkspaceEdit({this.changes, this.documentChanges, this.changeAnnotations});
   static WorkspaceEdit fromJson(Map<String, dynamic> json) {
     final changes = json['changes']
         ?.map((key, value) => MapEntry(
@@ -24611,24 +33603,39 @@
                 ?.cast<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>()
                 ?.toList())
             : (json['documentChanges'] == null ? null : (throw '''${json['documentChanges']} was not one of (List<TextDocumentEdit>, List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>)''')));
-    return WorkspaceEdit(changes: changes, documentChanges: documentChanges);
+    final changeAnnotations = json['changeAnnotations']
+        ?.map((key, value) => MapEntry(
+            key, value != null ? ChangeAnnotation.fromJson(value) : null))
+        ?.cast<String, ChangeAnnotation>();
+    return WorkspaceEdit(
+        changes: changes,
+        documentChanges: documentChanges,
+        changeAnnotations: changeAnnotations);
   }
 
+  /// A map of change annotations that can be referenced in `AnnotatedTextEdit`s
+  /// or create, rename and delete file / folder operations.
+  ///
+  /// Whether clients honor this property depends on the client capability
+  /// `workspace.changeAnnotationSupport`.
+  ///  @since 3.16.0
+  final Map<String, ChangeAnnotation> changeAnnotations;
+
   /// Holds changes to existing resources.
   final Map<String, List<TextEdit>> changes;
 
-  /// The client capability `workspace.workspaceEdit.resourceOperations`
-  /// determines whether document changes are either an array of
-  /// `TextDocumentEdit`s to express changes to different text documents, where
-  /// each text document edit addresses a specific version of a text document,
-  /// or it can contains the above `TextDocumentEdit`s mixed with create,
-  /// rename, and delete file / folder operations.
+  /// Depending on the client capability
+  /// `workspace.workspaceEdit.resourceOperations` document changes are either
+  /// an array of `TextDocumentEdit`s to express changes to n different text
+  /// documents where each text document edit addresses a specific version of a
+  /// text document. Or it can contain above `TextDocumentEdit`s mixed with
+  /// create, rename and delete file / folder operations.
   ///
   /// Whether a client supports versioned document edits is expressed via
   /// `workspace.workspaceEdit.documentChanges` client capability.
   ///
-  /// If a client doesn't support `documentChanges` or
-  /// `workspace.workspaceEdit.resourceOperations`, then only plain `TextEdit`s
+  /// If a client neither supports `documentChanges` nor
+  /// `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s
   /// using the `changes` property are supported.
   final Either2<List<TextDocumentEdit>,
           List<Either4<TextDocumentEdit, CreateFile, RenameFile, DeleteFile>>>
@@ -24642,6 +33649,9 @@
     if (documentChanges != null) {
       __result['documentChanges'] = documentChanges;
     }
+    if (changeAnnotations != null) {
+      __result['changeAnnotations'] = changeAnnotations;
+    }
     return __result;
   }
 
@@ -24681,6 +33691,20 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('changeAnnotations');
+      try {
+        if (obj['changeAnnotations'] != null &&
+            !((obj['changeAnnotations'] is Map &&
+                (obj['changeAnnotations'].keys.every((item) =>
+                    item is String &&
+                    obj['changeAnnotations'].values.every((item) =>
+                        ChangeAnnotation.canParse(item, reporter))))))) {
+          reporter.reportError('must be of type Map<String, ChangeAnnotation>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type WorkspaceEdit');
@@ -24697,6 +33721,8 @@
               (List<TextEdit> a, List<TextEdit> b) =>
                   listEqual(a, b, (TextEdit a, TextEdit b) => a == b)) &&
           documentChanges == other.documentChanges &&
+          mapEqual(changeAnnotations, other.changeAnnotations,
+              (ChangeAnnotation a, ChangeAnnotation b) => a == b) &&
           true;
     }
     return false;
@@ -24707,6 +33733,7 @@
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, lspHashCode(changes));
     hash = JenkinsSmiHash.combine(hash, documentChanges.hashCode);
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(changeAnnotations));
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -24720,7 +33747,11 @@
       WorkspaceEditClientCapabilities.fromJson);
 
   WorkspaceEditClientCapabilities(
-      {this.documentChanges, this.resourceOperations, this.failureHandling});
+      {this.documentChanges,
+      this.resourceOperations,
+      this.failureHandling,
+      this.normalizesLineEndings,
+      this.changeAnnotationSupport});
   static WorkspaceEditClientCapabilities fromJson(Map<String, dynamic> json) {
     final documentChanges = json['documentChanges'];
     final resourceOperations = json['resourceOperations']
@@ -24731,12 +33762,25 @@
     final failureHandling = json['failureHandling'] != null
         ? FailureHandlingKind.fromJson(json['failureHandling'])
         : null;
+    final normalizesLineEndings = json['normalizesLineEndings'];
+    final changeAnnotationSupport = json['changeAnnotationSupport'] != null
+        ? WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson(
+            json['changeAnnotationSupport'])
+        : null;
     return WorkspaceEditClientCapabilities(
         documentChanges: documentChanges,
         resourceOperations: resourceOperations,
-        failureHandling: failureHandling);
+        failureHandling: failureHandling,
+        normalizesLineEndings: normalizesLineEndings,
+        changeAnnotationSupport: changeAnnotationSupport);
   }
 
+  /// Whether the client in general supports change annotations on text edits,
+  /// create file, rename file and delete file changes.
+  ///  @since 3.16.0
+  final WorkspaceEditClientCapabilitiesChangeAnnotationSupport
+      changeAnnotationSupport;
+
   /// The client supports versioned document changes in `WorkspaceEdit`s
   final bool documentChanges;
 
@@ -24745,6 +33789,12 @@
   ///  @since 3.13.0
   final FailureHandlingKind failureHandling;
 
+  /// Whether the client normalizes line endings to the client specific setting.
+  /// If set to `true` the client will normalize line ending characters in a
+  /// workspace edit to the client specific new line character(s).
+  ///  @since 3.16.0
+  final bool normalizesLineEndings;
+
   /// The resource operations the client supports. Clients should at least
   /// support 'create', 'rename' and 'delete' files and folders.
   ///  @since 3.13.0
@@ -24761,6 +33811,12 @@
     if (failureHandling != null) {
       __result['failureHandling'] = failureHandling.toJson();
     }
+    if (normalizesLineEndings != null) {
+      __result['normalizesLineEndings'] = normalizesLineEndings;
+    }
+    if (changeAnnotationSupport != null) {
+      __result['changeAnnotationSupport'] = changeAnnotationSupport.toJson();
+    }
     return __result;
   }
 
@@ -24798,6 +33854,28 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('normalizesLineEndings');
+      try {
+        if (obj['normalizesLineEndings'] != null &&
+            !(obj['normalizesLineEndings'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      reporter.push('changeAnnotationSupport');
+      try {
+        if (obj['changeAnnotationSupport'] != null &&
+            !(WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse(
+                obj['changeAnnotationSupport'], reporter))) {
+          reporter.reportError(
+              'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type WorkspaceEditClientCapabilities');
@@ -24813,6 +33891,8 @@
           listEqual(resourceOperations, other.resourceOperations,
               (ResourceOperationKind a, ResourceOperationKind b) => a == b) &&
           failureHandling == other.failureHandling &&
+          normalizesLineEndings == other.normalizesLineEndings &&
+          changeAnnotationSupport == other.changeAnnotationSupport &&
           true;
     }
     return false;
@@ -24824,6 +33904,75 @@
     hash = JenkinsSmiHash.combine(hash, documentChanges.hashCode);
     hash = JenkinsSmiHash.combine(hash, lspHashCode(resourceOperations));
     hash = JenkinsSmiHash.combine(hash, failureHandling.hashCode);
+    hash = JenkinsSmiHash.combine(hash, normalizesLineEndings.hashCode);
+    hash = JenkinsSmiHash.combine(hash, changeAnnotationSupport.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
+class WorkspaceEditClientCapabilitiesChangeAnnotationSupport
+    implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      WorkspaceEditClientCapabilitiesChangeAnnotationSupport.canParse,
+      WorkspaceEditClientCapabilitiesChangeAnnotationSupport.fromJson);
+
+  WorkspaceEditClientCapabilitiesChangeAnnotationSupport({this.groupsOnLabel});
+  static WorkspaceEditClientCapabilitiesChangeAnnotationSupport fromJson(
+      Map<String, dynamic> json) {
+    final groupsOnLabel = json['groupsOnLabel'];
+    return WorkspaceEditClientCapabilitiesChangeAnnotationSupport(
+        groupsOnLabel: groupsOnLabel);
+  }
+
+  /// Whether the client groups edits with equal labels into tree nodes, for
+  /// instance all edits labelled with "Changes in Strings" would be a tree
+  /// node.
+  final bool groupsOnLabel;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    if (groupsOnLabel != null) {
+      __result['groupsOnLabel'] = groupsOnLabel;
+    }
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('groupsOnLabel');
+      try {
+        if (obj['groupsOnLabel'] != null && !(obj['groupsOnLabel'] is bool)) {
+          reporter.reportError('must be of type bool');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type WorkspaceEditClientCapabilitiesChangeAnnotationSupport');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is WorkspaceEditClientCapabilitiesChangeAnnotationSupport &&
+        other.runtimeType ==
+            WorkspaceEditClientCapabilitiesChangeAnnotationSupport) {
+      return groupsOnLabel == other.groupsOnLabel && true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, groupsOnLabel.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -25140,15 +34289,21 @@
       WorkspaceSymbolClientCapabilities.fromJson);
 
   WorkspaceSymbolClientCapabilities(
-      {this.dynamicRegistration, this.symbolKind});
+      {this.dynamicRegistration, this.symbolKind, this.tagSupport});
   static WorkspaceSymbolClientCapabilities fromJson(Map<String, dynamic> json) {
     final dynamicRegistration = json['dynamicRegistration'];
     final symbolKind = json['symbolKind'] != null
         ? WorkspaceSymbolClientCapabilitiesSymbolKind.fromJson(
             json['symbolKind'])
         : null;
+    final tagSupport = json['tagSupport'] != null
+        ? WorkspaceSymbolClientCapabilitiesTagSupport.fromJson(
+            json['tagSupport'])
+        : null;
     return WorkspaceSymbolClientCapabilities(
-        dynamicRegistration: dynamicRegistration, symbolKind: symbolKind);
+        dynamicRegistration: dynamicRegistration,
+        symbolKind: symbolKind,
+        tagSupport: tagSupport);
   }
 
   /// Symbol request supports dynamic registration.
@@ -25158,6 +34313,11 @@
   /// request.
   final WorkspaceSymbolClientCapabilitiesSymbolKind symbolKind;
 
+  /// The client supports tags on `SymbolInformation`. Clients supporting tags
+  /// have to handle unknown tags gracefully.
+  ///  @since 3.16.0
+  final WorkspaceSymbolClientCapabilitiesTagSupport tagSupport;
+
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (dynamicRegistration != null) {
@@ -25166,6 +34326,9 @@
     if (symbolKind != null) {
       __result['symbolKind'] = symbolKind.toJson();
     }
+    if (tagSupport != null) {
+      __result['tagSupport'] = tagSupport.toJson();
+    }
     return __result;
   }
 
@@ -25193,6 +34356,18 @@
       } finally {
         reporter.pop();
       }
+      reporter.push('tagSupport');
+      try {
+        if (obj['tagSupport'] != null &&
+            !(WorkspaceSymbolClientCapabilitiesTagSupport.canParse(
+                obj['tagSupport'], reporter))) {
+          reporter.reportError(
+              'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
       return true;
     } else {
       reporter.reportError('must be of type WorkspaceSymbolClientCapabilities');
@@ -25206,6 +34381,7 @@
         other.runtimeType == WorkspaceSymbolClientCapabilities) {
       return dynamicRegistration == other.dynamicRegistration &&
           symbolKind == other.symbolKind &&
+          tagSupport == other.tagSupport &&
           true;
     }
     return false;
@@ -25216,6 +34392,7 @@
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, dynamicRegistration.hashCode);
     hash = JenkinsSmiHash.combine(hash, symbolKind.hashCode);
+    hash = JenkinsSmiHash.combine(hash, tagSupport.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 
@@ -25298,6 +34475,86 @@
   String toString() => jsonEncoder.convert(toJson());
 }
 
+class WorkspaceSymbolClientCapabilitiesTagSupport implements ToJsonable {
+  static const jsonHandler = LspJsonHandler(
+      WorkspaceSymbolClientCapabilitiesTagSupport.canParse,
+      WorkspaceSymbolClientCapabilitiesTagSupport.fromJson);
+
+  WorkspaceSymbolClientCapabilitiesTagSupport({@required this.valueSet}) {
+    if (valueSet == null) {
+      throw 'valueSet is required but was not provided';
+    }
+  }
+  static WorkspaceSymbolClientCapabilitiesTagSupport fromJson(
+      Map<String, dynamic> json) {
+    final valueSet = json['valueSet']
+        ?.map((item) => item != null ? SymbolTag.fromJson(item) : null)
+        ?.cast<SymbolTag>()
+        ?.toList();
+    return WorkspaceSymbolClientCapabilitiesTagSupport(valueSet: valueSet);
+  }
+
+  /// The tags supported by the client.
+  final List<SymbolTag> valueSet;
+
+  Map<String, dynamic> toJson() {
+    var __result = <String, dynamic>{};
+    __result['valueSet'] =
+        valueSet ?? (throw 'valueSet is required but was not set');
+    return __result;
+  }
+
+  static bool canParse(Object obj, LspJsonReporter reporter) {
+    if (obj is Map<String, dynamic>) {
+      reporter.push('valueSet');
+      try {
+        if (!obj.containsKey('valueSet')) {
+          reporter.reportError('must not be undefined');
+          return false;
+        }
+        if (obj['valueSet'] == null) {
+          reporter.reportError('must not be null');
+          return false;
+        }
+        if (!((obj['valueSet'] is List &&
+            (obj['valueSet']
+                .every((item) => SymbolTag.canParse(item, reporter)))))) {
+          reporter.reportError('must be of type List<SymbolTag>');
+          return false;
+        }
+      } finally {
+        reporter.pop();
+      }
+      return true;
+    } else {
+      reporter.reportError(
+          'must be of type WorkspaceSymbolClientCapabilitiesTagSupport');
+      return false;
+    }
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other is WorkspaceSymbolClientCapabilitiesTagSupport &&
+        other.runtimeType == WorkspaceSymbolClientCapabilitiesTagSupport) {
+      return listEqual(
+              valueSet, other.valueSet, (SymbolTag a, SymbolTag b) => a == b) &&
+          true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    var hash = 0;
+    hash = JenkinsSmiHash.combine(hash, lspHashCode(valueSet));
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  String toString() => jsonEncoder.convert(toJson());
+}
+
 class WorkspaceSymbolOptions implements WorkDoneProgressOptions, ToJsonable {
   static const jsonHandler = LspJsonHandler(
       WorkspaceSymbolOptions.canParse, WorkspaceSymbolOptions.fromJson);
@@ -25395,8 +34652,8 @@
         partialResultToken: partialResultToken);
   }
 
-  /// An optional token that a server can use to report partial results (for
-  /// example, streaming) to the client.
+  /// An optional token that a server can use to report partial results (e.g.
+  /// streaming) to the client.
   final Either2<num, String> partialResultToken;
 
   /// A query string to filter symbols by. Clients may send an empty string here
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index f62b233..a0a5fe9 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -6,7 +6,6 @@
 /// entities.
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analyzer/dart/element/element.dart' as engine;
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:path/path.dart' as pathos;
 
 /// Return a protocol [Element] corresponding to the given [engine.Element].
@@ -132,8 +131,13 @@
       return null;
     }
     parameters = element.parameters.toList();
-  } else if (element is engine.FunctionTypeAliasElement) {
-    parameters = element.function.parameters.toList();
+  } else if (element is engine.TypeAliasElement) {
+    var aliasedElement = element.aliasedElement;
+    if (aliasedElement is engine.GenericFunctionTypeElement) {
+      parameters = aliasedElement.parameters.toList();
+    } else {
+      return null;
+    }
   } else {
     return null;
   }
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 7636ffc..9b566ba 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.32.1';
+const String PROTOCOL_VERSION = '1.32.4';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -145,9 +145,6 @@
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_ID = 'id';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_LABEL = 'label';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_OFFSET = 'offset';
-const String COMPLETION_REQUEST_LIST_TOKEN_DETAILS =
-    'completion.listTokenDetails';
-const String COMPLETION_REQUEST_LIST_TOKEN_DETAILS_FILE = 'file';
 const String COMPLETION_REQUEST_REGISTER_LIBRARY_PATHS =
     'completion.registerLibraryPaths';
 const String COMPLETION_REQUEST_REGISTER_LIBRARY_PATHS_PATHS = 'paths';
@@ -159,13 +156,13 @@
 const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_CHANGE = 'change';
 const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_COMPLETION =
     'completion';
-const String COMPLETION_RESPONSE_LIST_TOKEN_DETAILS_TOKENS = 'tokens';
 const String DIAGNOSTIC_REQUEST_GET_DIAGNOSTICS = 'diagnostic.getDiagnostics';
 const String DIAGNOSTIC_REQUEST_GET_SERVER_PORT = 'diagnostic.getServerPort';
 const String DIAGNOSTIC_RESPONSE_GET_DIAGNOSTICS_CONTEXTS = 'contexts';
 const String DIAGNOSTIC_RESPONSE_GET_SERVER_PORT_PORT = 'port';
 const String EDIT_REQUEST_BULK_FIXES = 'edit.bulkFixes';
 const String EDIT_REQUEST_BULK_FIXES_INCLUDED = 'included';
+const String EDIT_REQUEST_BULK_FIXES_IN_TEST_MODE = 'inTestMode';
 const String EDIT_REQUEST_DARTFIX = 'edit.dartfix';
 const String EDIT_REQUEST_DARTFIX_EXCLUDED_FIXES = 'excludedFixes';
 const String EDIT_REQUEST_DARTFIX_INCLUDED = 'included';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 3cf16bf..1ae7337 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -5886,168 +5886,6 @@
   }
 }
 
-/// completion.listTokenDetails params
-///
-/// {
-///   "file": FilePath
-/// }
-///
-/// Clients may not extend, implement or mix-in this class.
-class CompletionListTokenDetailsParams implements RequestParams {
-  String _file;
-
-  /// The path to the file from which tokens should be returned.
-  String get file => _file;
-
-  /// The path to the file from which tokens should be returned.
-  set file(String value) {
-    assert(value != null);
-    _file = value;
-  }
-
-  CompletionListTokenDetailsParams(String file) {
-    this.file = file;
-  }
-
-  factory CompletionListTokenDetailsParams.fromJson(
-      JsonDecoder jsonDecoder, String jsonPath, Object json) {
-    json ??= {};
-    if (json is Map) {
-      String file;
-      if (json.containsKey('file')) {
-        file = jsonDecoder.decodeString(jsonPath + '.file', json['file']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'file');
-      }
-      return CompletionListTokenDetailsParams(file);
-    } else {
-      throw jsonDecoder.mismatch(
-          jsonPath, 'completion.listTokenDetails params', json);
-    }
-  }
-
-  factory CompletionListTokenDetailsParams.fromRequest(Request request) {
-    return CompletionListTokenDetailsParams.fromJson(
-        RequestDecoder(request), 'params', request.params);
-  }
-
-  @override
-  Map<String, dynamic> toJson() {
-    var result = <String, dynamic>{};
-    result['file'] = file;
-    return result;
-  }
-
-  @override
-  Request toRequest(String id) {
-    return Request(id, 'completion.listTokenDetails', toJson());
-  }
-
-  @override
-  String toString() => json.encode(toJson());
-
-  @override
-  bool operator ==(other) {
-    if (other is CompletionListTokenDetailsParams) {
-      return file == other.file;
-    }
-    return false;
-  }
-
-  @override
-  int get hashCode {
-    var hash = 0;
-    hash = JenkinsSmiHash.combine(hash, file.hashCode);
-    return JenkinsSmiHash.finish(hash);
-  }
-}
-
-/// completion.listTokenDetails result
-///
-/// {
-///   "tokens": List<TokenDetails>
-/// }
-///
-/// Clients may not extend, implement or mix-in this class.
-class CompletionListTokenDetailsResult implements ResponseResult {
-  List<TokenDetails> _tokens;
-
-  /// A list of the file's scanned tokens including analysis information about
-  /// them.
-  List<TokenDetails> get tokens => _tokens;
-
-  /// A list of the file's scanned tokens including analysis information about
-  /// them.
-  set tokens(List<TokenDetails> value) {
-    assert(value != null);
-    _tokens = value;
-  }
-
-  CompletionListTokenDetailsResult(List<TokenDetails> tokens) {
-    this.tokens = tokens;
-  }
-
-  factory CompletionListTokenDetailsResult.fromJson(
-      JsonDecoder jsonDecoder, String jsonPath, Object json) {
-    json ??= {};
-    if (json is Map) {
-      List<TokenDetails> tokens;
-      if (json.containsKey('tokens')) {
-        tokens = jsonDecoder.decodeList(
-            jsonPath + '.tokens',
-            json['tokens'],
-            (String jsonPath, Object json) =>
-                TokenDetails.fromJson(jsonDecoder, jsonPath, json));
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'tokens');
-      }
-      return CompletionListTokenDetailsResult(tokens);
-    } else {
-      throw jsonDecoder.mismatch(
-          jsonPath, 'completion.listTokenDetails result', json);
-    }
-  }
-
-  factory CompletionListTokenDetailsResult.fromResponse(Response response) {
-    return CompletionListTokenDetailsResult.fromJson(
-        ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
-        'result',
-        response.result);
-  }
-
-  @override
-  Map<String, dynamic> toJson() {
-    var result = <String, dynamic>{};
-    result['tokens'] =
-        tokens.map((TokenDetails value) => value.toJson()).toList();
-    return result;
-  }
-
-  @override
-  Response toResponse(String id) {
-    return Response(id, result: toJson());
-  }
-
-  @override
-  String toString() => json.encode(toJson());
-
-  @override
-  bool operator ==(other) {
-    if (other is CompletionListTokenDetailsResult) {
-      return listEqual(
-          tokens, other.tokens, (TokenDetails a, TokenDetails b) => a == b);
-    }
-    return false;
-  }
-
-  @override
-  int get hashCode {
-    var hash = 0;
-    hash = JenkinsSmiHash.combine(hash, tokens.hashCode);
-    return JenkinsSmiHash.finish(hash);
-  }
-}
-
 /// completion.registerLibraryPaths params
 ///
 /// {
@@ -7301,12 +7139,15 @@
 ///
 /// {
 ///   "included": List<FilePath>
+///   "inTestMode": optional bool
 /// }
 ///
 /// Clients may not extend, implement or mix-in this class.
 class EditBulkFixesParams implements RequestParams {
   List<String> _included;
 
+  bool _inTestMode;
+
   /// A list of the files and directories for which edits should be suggested.
   ///
   /// If a request is made with a path that is invalid, e.g. is not absolute
@@ -7330,8 +7171,27 @@
     _included = value;
   }
 
-  EditBulkFixesParams(List<String> included) {
+  /// A flag indicating whether the bulk fixes are being run in test mode. The
+  /// only difference is that in test mode the fix processor will look for a
+  /// configuration file that can modify the content of the data file used to
+  /// compute the fixes when data-driven fixes are being considered.
+  ///
+  /// If this field is omitted the flag defaults to false.
+  bool get inTestMode => _inTestMode;
+
+  /// A flag indicating whether the bulk fixes are being run in test mode. The
+  /// only difference is that in test mode the fix processor will look for a
+  /// configuration file that can modify the content of the data file used to
+  /// compute the fixes when data-driven fixes are being considered.
+  ///
+  /// If this field is omitted the flag defaults to false.
+  set inTestMode(bool value) {
+    _inTestMode = value;
+  }
+
+  EditBulkFixesParams(List<String> included, {bool inTestMode}) {
     this.included = included;
+    this.inTestMode = inTestMode;
   }
 
   factory EditBulkFixesParams.fromJson(
@@ -7345,7 +7205,12 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'included');
       }
-      return EditBulkFixesParams(included);
+      bool inTestMode;
+      if (json.containsKey('inTestMode')) {
+        inTestMode = jsonDecoder.decodeBool(
+            jsonPath + '.inTestMode', json['inTestMode']);
+      }
+      return EditBulkFixesParams(included, inTestMode: inTestMode);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'edit.bulkFixes params', json);
     }
@@ -7360,6 +7225,9 @@
   Map<String, dynamic> toJson() {
     var result = <String, dynamic>{};
     result['included'] = included;
+    if (inTestMode != null) {
+      result['inTestMode'] = inTestMode;
+    }
     return result;
   }
 
@@ -7375,7 +7243,8 @@
   bool operator ==(other) {
     if (other is EditBulkFixesParams) {
       return listEqual(
-          included, other.included, (String a, String b) => a == b);
+              included, other.included, (String a, String b) => a == b) &&
+          inTestMode == other.inTestMode;
     }
     return false;
   }
@@ -7384,6 +7253,7 @@
   int get hashCode {
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, included.hashCode);
+    hash = JenkinsSmiHash.combine(hash, inTestMode.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
@@ -21313,151 +21183,6 @@
   }
 }
 
-/// TokenDetails
-///
-/// {
-///   "lexeme": String
-///   "type": optional String
-///   "validElementKinds": optional List<String>
-///   "offset": int
-/// }
-///
-/// Clients may not extend, implement or mix-in this class.
-class TokenDetails implements HasToJson {
-  String _lexeme;
-
-  String _type;
-
-  List<String> _validElementKinds;
-
-  int _offset;
-
-  /// The token's lexeme.
-  String get lexeme => _lexeme;
-
-  /// The token's lexeme.
-  set lexeme(String value) {
-    assert(value != null);
-    _lexeme = value;
-  }
-
-  /// A unique id for the type of the identifier. Omitted if the token is not
-  /// an identifier in a reference position.
-  String get type => _type;
-
-  /// A unique id for the type of the identifier. Omitted if the token is not
-  /// an identifier in a reference position.
-  set type(String value) {
-    _type = value;
-  }
-
-  /// An indication of whether this token is in a declaration or reference
-  /// position. (If no other purpose is found for this field then it should be
-  /// renamed and converted to a boolean value.) Omitted if the token is not an
-  /// identifier.
-  List<String> get validElementKinds => _validElementKinds;
-
-  /// An indication of whether this token is in a declaration or reference
-  /// position. (If no other purpose is found for this field then it should be
-  /// renamed and converted to a boolean value.) Omitted if the token is not an
-  /// identifier.
-  set validElementKinds(List<String> value) {
-    _validElementKinds = value;
-  }
-
-  /// The offset of the first character of the token in the file which it
-  /// originated from.
-  int get offset => _offset;
-
-  /// The offset of the first character of the token in the file which it
-  /// originated from.
-  set offset(int value) {
-    assert(value != null);
-    _offset = value;
-  }
-
-  TokenDetails(String lexeme, int offset,
-      {String type, List<String> validElementKinds}) {
-    this.lexeme = lexeme;
-    this.type = type;
-    this.validElementKinds = validElementKinds;
-    this.offset = offset;
-  }
-
-  factory TokenDetails.fromJson(
-      JsonDecoder jsonDecoder, String jsonPath, Object json) {
-    json ??= {};
-    if (json is Map) {
-      String lexeme;
-      if (json.containsKey('lexeme')) {
-        lexeme = jsonDecoder.decodeString(jsonPath + '.lexeme', json['lexeme']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'lexeme');
-      }
-      String type;
-      if (json.containsKey('type')) {
-        type = jsonDecoder.decodeString(jsonPath + '.type', json['type']);
-      }
-      List<String> validElementKinds;
-      if (json.containsKey('validElementKinds')) {
-        validElementKinds = jsonDecoder.decodeList(
-            jsonPath + '.validElementKinds',
-            json['validElementKinds'],
-            jsonDecoder.decodeString);
-      }
-      int offset;
-      if (json.containsKey('offset')) {
-        offset = jsonDecoder.decodeInt(jsonPath + '.offset', json['offset']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'offset');
-      }
-      return TokenDetails(lexeme, offset,
-          type: type, validElementKinds: validElementKinds);
-    } else {
-      throw jsonDecoder.mismatch(jsonPath, 'TokenDetails', json);
-    }
-  }
-
-  @override
-  Map<String, dynamic> toJson() {
-    var result = <String, dynamic>{};
-    result['lexeme'] = lexeme;
-    if (type != null) {
-      result['type'] = type;
-    }
-    if (validElementKinds != null) {
-      result['validElementKinds'] = validElementKinds;
-    }
-    result['offset'] = offset;
-    return result;
-  }
-
-  @override
-  String toString() => json.encode(toJson());
-
-  @override
-  bool operator ==(other) {
-    if (other is TokenDetails) {
-      return lexeme == other.lexeme &&
-          type == other.type &&
-          listEqual(validElementKinds, other.validElementKinds,
-              (String a, String b) => a == b) &&
-          offset == other.offset;
-    }
-    return false;
-  }
-
-  @override
-  int get hashCode {
-    var hash = 0;
-    hash = JenkinsSmiHash.combine(hash, lexeme.hashCode);
-    hash = JenkinsSmiHash.combine(hash, type.hashCode);
-    hash = JenkinsSmiHash.combine(hash, validElementKinds.hashCode);
-    hash = JenkinsSmiHash.combine(hash, offset.hashCode);
-    return JenkinsSmiHash.finish(hash);
-  }
-}
-
 /// TypeHierarchyItem
 ///
 /// {
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 4599f0a..95b2236 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -757,6 +757,11 @@
   }
 
   @override
+  void afterContextRefresh() {
+    analysisServer.addContextsToDeclarationsTracker();
+  }
+
+  @override
   void afterWatchEvent(WatchEvent event) {
     analysisServer._onAnalysisSetChangedController.add(null);
   }
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 9c33f83..8f1ec94 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -15,7 +15,6 @@
 import 'package:analyzer/src/dart/micro/resolve_file.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/util/performance/operation_performance.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:meta/meta.dart';
 
 /// The cache that can be reuse for across multiple completion request.
diff --git a/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart b/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart
index d83aa7c..dd01e3f 100644
--- a/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_closingLabels.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/generated/source.dart';
 
 /// A computer for [CompilationUnit] closing labels.
 class DartUnitClosingLabelsComputer {
diff --git a/pkg/analysis_server/lib/src/computer/computer_folding.dart b/pkg/analysis_server/lib/src/computer/computer_folding.dart
index 9bf7c03..2a8bc96 100644
--- a/pkg/analysis_server/lib/src/computer/computer_folding.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_folding.dart
@@ -6,7 +6,6 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 
 /// A computer for [CompilationUnit] folding.
@@ -50,7 +49,6 @@
 
   /// Returns a list of folding regions, not `null`.
   List<FoldingRegion> compute() {
-    _addFileHeaderRegion();
     _unit.accept(_DartUnitFoldingComputerVisitor(this));
 
     if (_firstDirective != null &&
@@ -62,39 +60,90 @@
           _lastDirective.end - _firstDirective.keyword.end));
     }
 
+    _addCommentRegions();
+
     return _foldingRegions;
   }
 
-  void _addFileHeaderRegion() {
-    var firstToken = _unit.beginToken;
-    while (firstToken?.type == TokenType.SCRIPT_TAG) {
-      firstToken = firstToken.next;
+  /// Create a folding region for the provided comment, reading forwards if neccesary.
+  ///
+  /// If [mayBeFileHeader] is true, the token will be considered a file header
+  /// if comment is a single-line-comment and there is a blank line or another
+  /// comment type after it.
+  ///
+  /// Returns the next comment to be processed or null if there are no more comments
+  /// to process in the chain.
+  Token _addCommentRegion(Token commentToken, {bool mayBeFileHeader = false}) {
+    int offset, end;
+    var isFileHeader = false;
+    Token nextComment;
+
+    if (commentToken.type == TokenType.MULTI_LINE_COMMENT) {
+      // Multiline comments already span all of their lines but the folding
+      // region should start at the end of the first line.
+      offset = commentToken.offset + (commentToken.eolOffset ?? 0);
+      end = commentToken.end;
+      nextComment = commentToken.next;
+    } else {
+      // Single line comments need grouping together explicitly but should
+      // only group if the prefix is the same and up to any blank line.
+      final isTripleSlash = commentToken.isTripleSlash;
+      // Track the last comment that belongs to this folding region.
+      var lastComment = commentToken;
+      var current = lastComment.next;
+      while (current != null &&
+          current.type == lastComment.type &&
+          current.isTripleSlash == isTripleSlash &&
+          !_hasBlankLineBetween(lastComment.end, current.offset)) {
+        lastComment = current;
+        current = current.next;
+      }
+
+      // For single line comments we prefer to start the range at the end of
+      // first token so the first line is still visible when the range is
+      // collapsed.
+      offset = commentToken.end;
+      end = lastComment.end;
+      nextComment = lastComment.next;
+
+      // Single line comments are file headers if they're followed by a different
+      // comment type of there's a blank line between them and the first token.
+      isFileHeader = mayBeFileHeader &&
+          (nextComment != null ||
+              _hasBlankLineBetween(end, _unit.beginToken.offset));
     }
 
-    final Token firstComment = firstToken?.precedingComments;
-    if (firstComment == null ||
-        firstComment.type != TokenType.SINGLE_LINE_COMMENT) {
-      return;
+    final kind = isFileHeader
+        ? FoldingKind.FILE_HEADER
+        : (commentToken.lexeme.startsWith('///') ||
+                commentToken.lexeme.startsWith('/**'))
+            ? FoldingKind.DOCUMENTATION_COMMENT
+            : FoldingKind.COMMENT;
+
+    _addRegion(offset, end, kind);
+
+    return nextComment;
+  }
+
+  void _addCommentRegions() {
+    var token = _unit.beginToken;
+    if (token.type == TokenType.SCRIPT_TAG) {
+      token = token.next;
     }
-
-    // Walk through the comments looking for a blank line to signal the end of
-    // the file header.
-    var lastComment = firstComment;
-    while (lastComment.next != null) {
-      lastComment = lastComment.next;
-
-      // If we ran out of tokens, use the original token as starting position.
-      final hasBlankLine =
-          _hasBlankLineBetween(lastComment, lastComment.next ?? firstToken);
-
-      // Also considered non-single-line-comments as the end
-      final nextCommentIsDifferentType = lastComment.next != null &&
-          lastComment.next.type != TokenType.SINGLE_LINE_COMMENT;
-
-      if (hasBlankLine || nextCommentIsDifferentType) {
-        _addRegion(firstComment.end, lastComment.end, FoldingKind.FILE_HEADER);
+    var isFirstToken = true;
+    while (token != null) {
+      Token commentToken = token.precedingComments;
+      while (commentToken != null) {
+        commentToken =
+            _addCommentRegion(commentToken, mayBeFileHeader: isFirstToken);
+      }
+      isFirstToken = false;
+      // Only exit the loop when hitting EOF *after* processing the token as
+      // the EOF token may have preceeding comments.
+      if (token.type == TokenType.EOF) {
         break;
       }
+      token = token.next;
     }
   }
 
@@ -115,9 +164,9 @@
     }
   }
 
-  bool _hasBlankLineBetween(Token first, Token second) {
-    final CharacterLocation firstLoc = _lineInfo.getLocation(first.end);
-    final CharacterLocation secondLoc = _lineInfo.getLocation(second.offset);
+  bool _hasBlankLineBetween(int offset, int end) {
+    final CharacterLocation firstLoc = _lineInfo.getLocation(offset);
+    final CharacterLocation secondLoc = _lineInfo.getLocation(end);
     return secondLoc.lineNumber - firstLoc.lineNumber > 1;
   }
 
@@ -163,15 +212,6 @@
   }
 
   @override
-  void visitComment(Comment node) {
-    if (node.isDocumentation) {
-      _computer._addRegion(
-          node.offset, node.end, FoldingKind.DOCUMENTATION_COMMENT);
-    }
-    super.visitComment(node);
-  }
-
-  @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
     _computer._addRegionForAnnotations(node.metadata);
     super.visitConstructorDeclaration(node);
@@ -304,3 +344,17 @@
     super.visitWhileStatement(node);
   }
 }
+
+extension _CommentTokenExtensions on Token {
+  static final _newlinePattern = RegExp(r'[\r\n]');
+
+  /// The offset of the first eol character or null
+  /// if no newlines were found.
+  int get eolOffset {
+    final offset = lexeme.indexOf(_newlinePattern);
+    return offset != -1 ? offset : null;
+  }
+
+  /// Whether this comment is a triple-slash single line comment.
+  bool get isTripleSlash => lexeme.startsWith('///');
+}
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index df56229..717c136 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -2,28 +2,58 @@
 // for 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/lsp_protocol/protocol_generated.dart'
+    show SemanticTokenTypes, SemanticTokenModifiers;
+import 'package:analysis_server/src/lsp/constants.dart'
+    show CustomSemanticTokenModifiers;
+import 'package:analysis_server/src/lsp/semantic_tokens/encoder.dart'
+    show SemanticTokenInfo;
+import 'package:analysis_server/src/lsp/semantic_tokens/mapping.dart'
+    show highlightRegionTokenModifiers, highlightRegionTokenTypes;
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/source/source_range.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
 
-/// A computer for [HighlightRegion]s in a Dart [CompilationUnit].
+/// A computer for [HighlightRegion]s and LSP [SemanticTokenInfo] in a Dart [CompilationUnit].
 class DartUnitHighlightsComputer {
   final CompilationUnit _unit;
+  final SourceRange range;
 
-  final List<HighlightRegion> _regions = <HighlightRegion>[];
+  final _regions = <HighlightRegion>[];
+  final _semanticTokens = <SemanticTokenInfo>[];
+  bool _computeRegions = false;
+  bool _computeSemanticTokens = false;
 
-  DartUnitHighlightsComputer(this._unit);
+  /// Creates a computer for [HighlightRegion]s and LSP [SemanticTokenInfo] in a
+  /// Dart [CompilationUnit].
+  ///
+  /// If [range] is supplied, tokens outside of this range will not be included
+  /// in results.
+  DartUnitHighlightsComputer(this._unit, {this.range});
 
   /// Returns the computed highlight regions, not `null`.
   List<HighlightRegion> compute() {
+    _reset();
+    _computeRegions = true;
     _unit.accept(_DartUnitHighlightsComputerVisitor(this));
     _addCommentRanges();
     return _regions;
   }
 
+  /// Returns the computed semantic tokens, not `null`.
+  List<SemanticTokenInfo> computeSemanticTokens() {
+    _reset();
+    _computeSemanticTokens = true;
+    _unit.accept(_DartUnitHighlightsComputerVisitor(this));
+    _addCommentRanges();
+    return _semanticTokens;
+  }
+
   void _addCommentRanges() {
     var token = _unit.beginToken;
     while (token != null) {
@@ -38,7 +68,11 @@
           }
         }
         if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
-          highlightType = HighlightRegionType.COMMENT_END_OF_LINE;
+          if (commentToken.lexeme.startsWith('///')) {
+            highlightType = HighlightRegionType.COMMENT_DOCUMENTATION;
+          } else {
+            highlightType = HighlightRegionType.COMMENT_END_OF_LINE;
+          }
         }
         if (highlightType != null) {
           _addRegion_token(commentToken, highlightType);
@@ -76,9 +110,6 @@
     if (_addIdentifierRegion_function(node)) {
       return;
     }
-    if (_addIdentifierRegion_functionTypeAlias(node)) {
-      return;
-    }
     if (_addIdentifierRegion_importPrefix(node)) {
       return;
     }
@@ -94,6 +125,9 @@
     if (_addIdentifierRegion_parameter(node)) {
       return;
     }
+    if (_addIdentifierRegion_typeAlias(node)) {
+      return;
+    }
     if (_addIdentifierRegion_typeParameter(node)) {
       return;
     }
@@ -235,14 +269,6 @@
     return _addRegion_node(node, type);
   }
 
-  bool _addIdentifierRegion_functionTypeAlias(SimpleIdentifier node) {
-    var element = node.writeOrReadElement;
-    if (element is! FunctionTypeAliasElement) {
-      return false;
-    }
-    return _addRegion_node(node, HighlightRegionType.FUNCTION_TYPE_ALIAS);
-  }
-
   bool _addIdentifierRegion_getterSetterDeclaration(SimpleIdentifier node) {
     // should be declaration
     var parent = node.parent;
@@ -347,7 +373,20 @@
     var type = node.inDeclarationContext()
         ? HighlightRegionType.PARAMETER_DECLARATION
         : HighlightRegionType.PARAMETER_REFERENCE;
-    return _addRegion_node(node, type);
+    var modifiers =
+        node.parent is Label ? {CustomSemanticTokenModifiers.label} : null;
+    return _addRegion_node(node, type, semanticTokenModifiers: modifiers);
+  }
+
+  bool _addIdentifierRegion_typeAlias(SimpleIdentifier node) {
+    var element = node.writeOrReadElement;
+    if (element is TypeAliasElement) {
+      var type = element.aliasedType is FunctionType
+          ? HighlightRegionType.FUNCTION_TYPE_ALIAS
+          : HighlightRegionType.TYPE_ALIAS;
+      return _addRegion_node(node, type);
+    }
+    return false;
   }
 
   bool _addIdentifierRegion_typeParameter(SimpleIdentifier node) {
@@ -390,14 +429,57 @@
     return false;
   }
 
-  void _addRegion(int offset, int length, HighlightRegionType type) {
-    _regions.add(HighlightRegion(type, offset, length));
+  /// Adds a highlight region/semantic token for the given [offset]/[length].
+  ///
+  /// If [semanticTokenType] or [semanticTokenModifiers] are not provided, the
+  /// values from the default LSP mapping for [type] (also used for plugins)
+  /// will be used instead.
+  ///
+  /// If the computer has a [range] set, tokens that fall outside of that range
+  /// will not be recorded.
+  void _addRegion(
+    int offset,
+    int length,
+    HighlightRegionType type, {
+    SemanticTokenTypes semanticTokenType,
+    Set<SemanticTokenModifiers> semanticTokenModifiers,
+  }) {
+    if (range != null) {
+      final end = offset + length;
+      // Skip token if it ends before the range of starts after the range.
+      if (end < range.offset || offset > range.end) {
+        return;
+      }
+    }
+    if (_computeRegions) {
+      _regions.add(HighlightRegion(type, offset, length));
+    }
+    if (_computeSemanticTokens) {
+      // Use default mappings if an overriden type/modifiers were not supplied.
+      semanticTokenType ??= highlightRegionTokenTypes[type];
+      semanticTokenModifiers ??= highlightRegionTokenModifiers[type];
+      if (semanticTokenType != null) {
+        _semanticTokens.add(SemanticTokenInfo(
+            offset, length, semanticTokenType, semanticTokenModifiers));
+      }
+    }
   }
 
-  bool _addRegion_node(AstNode node, HighlightRegionType type) {
+  bool _addRegion_node(
+    AstNode node,
+    HighlightRegionType type, {
+    SemanticTokenTypes semanticTokenType,
+    Set<SemanticTokenModifiers> semanticTokenModifiers,
+  }) {
     var offset = node.offset;
     var length = node.length;
-    _addRegion(offset, length, type);
+    _addRegion(
+      offset,
+      length,
+      type,
+      semanticTokenType: semanticTokenType,
+      semanticTokenModifiers: semanticTokenModifiers,
+    );
     return true;
   }
 
@@ -408,11 +490,18 @@
     _addRegion(offset, end - offset, type);
   }
 
-  void _addRegion_token(Token token, HighlightRegionType type) {
+  void _addRegion_token(
+    Token token,
+    HighlightRegionType type, {
+    SemanticTokenTypes semanticTokenType,
+    Set<SemanticTokenModifiers> semanticTokenModifiers,
+  }) {
     if (token != null) {
       var offset = token.offset;
       var length = token.length;
-      _addRegion(offset, length, type);
+      _addRegion(offset, length, type,
+          semanticTokenType: semanticTokenType,
+          semanticTokenModifiers: semanticTokenModifiers);
     }
   }
 
@@ -423,6 +512,13 @@
     _addRegion(offset, end - offset, type);
   }
 
+  void _reset() {
+    _computeRegions = false;
+    _computeSemanticTokens = false;
+    _regions.clear();
+    _semanticTokens.clear();
+  }
+
   static bool _isDynamicExpression(Expression e) {
     var type = e.staticType;
     return type != null && type.isDynamic;
@@ -449,13 +545,15 @@
 
   @override
   void visitAssertStatement(AssertStatement node) {
-    computer._addRegion_token(node.assertKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.assertKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitAssertStatement(node);
   }
 
   @override
   void visitAwaitExpression(AwaitExpression node) {
-    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitAwaitExpression(node);
   }
 
@@ -474,14 +572,17 @@
 
   @override
   void visitBreakStatement(BreakStatement node) {
-    computer._addRegion_token(node.breakKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.breakKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitBreakStatement(node);
   }
 
   @override
   void visitCatchClause(CatchClause node) {
-    computer._addRegion_token(node.catchKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.onKeyword, HighlightRegionType.BUILT_IN);
+    computer._addRegion_token(node.catchKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
+    computer._addRegion_token(node.onKeyword, HighlightRegionType.BUILT_IN,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitCatchClause(node);
   }
 
@@ -511,8 +612,8 @@
 
   @override
   void visitContinueStatement(ContinueStatement node) {
-    computer._addRegion_token(
-        node.continueKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.continueKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitContinueStatement(node);
   }
 
@@ -525,8 +626,10 @@
 
   @override
   void visitDoStatement(DoStatement node) {
-    computer._addRegion_token(node.doKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.doKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
+    computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitDoStatement(node);
   }
 
@@ -588,27 +691,33 @@
 
   @override
   void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
-    computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitForEachPartsWithDeclaration(node);
   }
 
   @override
   void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
-    computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.inKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitForEachPartsWithIdentifier(node);
   }
 
   @override
   void visitForElement(ForElement node) {
-    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
-    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
+    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitForElement(node);
   }
 
   @override
   void visitForStatement(ForStatement node) {
-    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
-    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
+    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitForStatement(node);
   }
 
@@ -638,13 +747,14 @@
   @override
   void visitGenericFunctionType(GenericFunctionType node) {
     computer._addRegion_token(
-        node.functionKeyword, HighlightRegionType.KEYWORD);
+        node.functionKeyword, HighlightRegionType.BUILT_IN);
     super.visitGenericFunctionType(node);
   }
 
   @override
   void visitGenericTypeAlias(GenericTypeAlias node) {
-    computer._addRegion_token(node.typedefKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(
+        node.typedefKeyword, HighlightRegionType.BUILT_IN);
     super.visitGenericTypeAlias(node);
   }
 
@@ -656,15 +766,19 @@
 
   @override
   void visitIfElement(IfElement node) {
-    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
+    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitIfElement(node);
   }
 
   @override
   void visitIfStatement(IfStatement node) {
-    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
+    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitIfStatement(node);
   }
 
@@ -700,6 +814,12 @@
   }
 
   @override
+  void visitInterpolationString(InterpolationString node) {
+    computer._addRegion_node(node, HighlightRegionType.LITERAL_STRING);
+    super.visitInterpolationString(node);
+  }
+
+  @override
   void visitIsExpression(IsExpression node) {
     computer._addRegion_token(node.isOperator, HighlightRegionType.KEYWORD);
     super.visitIsExpression(node);
@@ -785,13 +905,15 @@
 
   @override
   void visitRethrowExpression(RethrowExpression node) {
-    computer._addRegion_token(node.rethrowKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.rethrowKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitRethrowExpression(node);
   }
 
   @override
   void visitReturnStatement(ReturnStatement node) {
-    computer._addRegion_token(node.returnKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.returnKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitReturnStatement(node);
   }
 
@@ -842,19 +964,22 @@
 
   @override
   void visitSwitchCase(SwitchCase node) {
-    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitSwitchCase(node);
   }
 
   @override
   void visitSwitchDefault(SwitchDefault node) {
-    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.keyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitSwitchDefault(node);
   }
 
   @override
   void visitSwitchStatement(SwitchStatement node) {
-    computer._addRegion_token(node.switchKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.switchKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitSwitchStatement(node);
   }
 
@@ -866,7 +991,8 @@
 
   @override
   void visitThrowExpression(ThrowExpression node) {
-    computer._addRegion_token(node.throwKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.throwKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitThrowExpression(node);
   }
 
@@ -879,8 +1005,10 @@
 
   @override
   void visitTryStatement(TryStatement node) {
-    computer._addRegion_token(node.tryKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.finallyKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.tryKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
+    computer._addRegion_token(node.finallyKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitTryStatement(node);
   }
 
@@ -905,7 +1033,8 @@
 
   @override
   void visitWhileStatement(WhileStatement node) {
-    computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.whileKeyword, HighlightRegionType.KEYWORD,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitWhileStatement(node);
   }
 
@@ -921,7 +1050,8 @@
     var star = node.star;
     var offset = keyword.offset;
     var end = star != null ? star.end : keyword.end;
-    computer._addRegion(offset, end - offset, HighlightRegionType.BUILT_IN);
+    computer._addRegion(offset, end - offset, HighlightRegionType.BUILT_IN,
+        semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     super.visitYieldStatement(node);
   }
 
@@ -931,7 +1061,8 @@
       var star = node.star;
       var offset = keyword.offset;
       var end = star != null ? star.end : keyword.end;
-      computer._addRegion(offset, end - offset, HighlightRegionType.BUILT_IN);
+      computer._addRegion(offset, end - offset, HighlightRegionType.BUILT_IN,
+          semanticTokenModifiers: {CustomSemanticTokenModifiers.control});
     }
   }
 }
diff --git a/pkg/analysis_server/lib/src/computer/computer_signature.dart b/pkg/analysis_server/lib/src/computer/computer_signature.dart
index 8da528f..c1e5764 100644
--- a/pkg/analysis_server/lib/src/computer/computer_signature.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_signature.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:analysis_server/protocol/protocol_generated.dart'
-    show AnalysisGetSignatureResult;
 import 'package:analysis_server/src/computer/computer_hover.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analyzer/dart/ast/ast.dart';
diff --git a/pkg/analysis_server/lib/src/computer/new_notifications.dart b/pkg/analysis_server/lib/src/computer/new_notifications.dart
index e44abed..a30965d 100644
--- a/pkg/analysis_server/lib/src/computer/new_notifications.dart
+++ b/pkg/analysis_server/lib/src/computer/new_notifications.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:analysis_server/protocol/protocol_generated.dart' as protocol;
 import 'package:analysis_server/src/analysis_server.dart' show AnalysisServer;
 import 'package:analysis_server/src/domains/analysis/occurrences.dart';
 import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index c37c64c..d552d08 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -16,7 +16,6 @@
 import 'package:analyzer/src/context/context_root.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
@@ -31,12 +30,21 @@
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/util/glob.dart';
 import 'package:analyzer/src/util/yaml.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
 import 'package:analyzer_plugin/utilities/analyzer_converter.dart';
 import 'package:path/path.dart' as pathos;
 import 'package:watcher/watcher.dart';
 import 'package:yaml/yaml.dart';
 
+/// Enables watching of files generated by Bazel.
+///
+/// TODO(michalt): This is a temporary flag that we use to disable this
+/// functionality due its performance issues. We plan to benchmark and optimize
+/// it and re-enable it everywhere.
+/// Not private to enable testing.
+var experimentalEnableBazelWatching = false;
+
 /// An indication of which files have been added, changed, removed, or deleted.
 ///
 /// No file should be added to the change set more than once, either with the
@@ -297,6 +305,10 @@
   /// Create and return a new analysis driver rooted at the given [folder].
   AnalysisDriver addAnalysisDriver(Folder folder, ContextRoot contextRoot);
 
+  /// Called after contexts are rebuilt, such as after recovering from a watcher
+  /// failure.
+  void afterContextRefresh();
+
   /// An [event] was processed, so analysis state might be different now.
   void afterWatchEvent(WatchEvent event);
 
@@ -393,6 +405,11 @@
   final Map<Folder, StreamSubscription<WatchEvent>> changeSubscriptions =
       <Folder, StreamSubscription<WatchEvent>>{};
 
+  /// For each root directory stores subscriptions and watchers that we
+  /// established to detect changes to Bazel generated files.
+  final Map<Folder, _BazelWorkspaceSubscription> bazelSubscriptions =
+      <Folder, _BazelWorkspaceSubscription>{};
+
   ContextManagerImpl(
     this.resourceProvider,
     this.sdkManager,
@@ -550,6 +567,8 @@
 
     // Rebuild contexts based on the data last sent to setRoots().
     setRoots(includedPaths, excludedPaths);
+
+    callbacks.afterContextRefresh();
   }
 
   /// Sets the [ignorePatterns] for the context having info [info].
@@ -1016,6 +1035,7 @@
       contextRoot.optionsFilePath = optionsFile.path;
     }
     info.analysisDriver = callbacks.addAnalysisDriver(folder, contextRoot);
+    _watchBazelFilesIfNeeded(folder, info.analysisDriver);
     if (optionsFile != null) {
       _analyzeAnalysisOptionsFile(info.analysisDriver, optionsFile.path);
     }
@@ -1116,6 +1136,7 @@
   /// Clean up and destroy the context associated with the given folder.
   void _destroyContext(ContextInfo info) {
     changeSubscriptions.remove(info.folder)?.cancel();
+    bazelSubscriptions.remove(info.folder)?.cancel();
     callbacks.removeContext(info.folder, _computeFlushedFiles(info));
     var wasRemoved = info.parent.children.remove(info);
     assert(wasRemoved);
@@ -1220,6 +1241,47 @@
     return rootInfo;
   }
 
+  /// Establishes watch(es) for the Bazel generated files provided in
+  /// [notification].
+  ///
+  /// Whenever the files change, we trigger re-analysis. This allows us to react
+  /// to creation/modification of files that were generated by Bazel.
+  void _handleBazelFileNotification(
+      Folder folder, BazelFileNotification notification) {
+    var fileSubscriptions = bazelSubscriptions[folder].fileSubscriptions;
+    if (fileSubscriptions.containsKey(notification.requested)) {
+      // We have already established a Watcher for this particular path.
+      return;
+    }
+    var watcher = notification.watcher(
+        pollingDelayShort: Duration(seconds: 10),
+        pollingDelayLong: Duration(seconds: 30));
+    var subscription = watcher.events.listen(_handleBazelWatchEvent);
+    fileSubscriptions[notification.requested] =
+        _BazelFilesSubscription(watcher, subscription);
+    watcher.start();
+  }
+
+  /// Notifies the drivers that a generated Bazel file has changed.
+  void _handleBazelWatchEvent(WatchEvent event) {
+    if (event.type == ChangeType.ADD) {
+      for (var driver in driverMap.values) {
+        driver.addFile(event.path);
+        // Since the file has been created after we've searched for it, the
+        // URI resolution is likely wrong, so we need to reset it.
+        driver.resetUriResolution();
+      }
+    } else if (event.type == ChangeType.MODIFY) {
+      for (var driver in driverMap.values) {
+        driver.changeFile(event.path);
+      }
+    } else if (event.type == ChangeType.REMOVE) {
+      for (var driver in driverMap.values) {
+        driver.removeFile(event.path);
+      }
+    }
+  }
+
   void _handleWatchEvent(WatchEvent event) {
     callbacks.broadcastWatchEvent(event);
     _handleWatchEventImpl(event);
@@ -1504,6 +1566,23 @@
     driver.configure(sourceFactory: sourceFactory);
   }
 
+  /// Listens to files generated by Bazel that were found or searched for.
+  ///
+  /// This is handled specially because the files are outside the package
+  /// folder, but we still want to watch for changes to them.
+  ///
+  /// Does nothing if the [driver] is not in a Bazel workspace.
+  void _watchBazelFilesIfNeeded(Folder folder, AnalysisDriver analysisDriver) {
+    if (!experimentalEnableBazelWatching) return;
+    var workspace = analysisDriver.analysisContext.workspace;
+    if (workspace is BazelWorkspace &&
+        !bazelSubscriptions.containsKey(folder)) {
+      var subscription = workspace.bazelCandidateFiles.listen(
+          (notification) => _handleBazelFileNotification(folder, notification));
+      bazelSubscriptions[folder] = _BazelWorkspaceSubscription(subscription);
+    }
+  }
+
   /// Create and return a source representing the given [file] within the given
   /// [driver].
   static Source createSourceInContext(AnalysisDriver driver, File file) {
@@ -1622,3 +1701,36 @@
     return _embedderLocator;
   }
 }
+
+/// A watcher with subscription used to detect changes to some file.
+class _BazelFilesSubscription {
+  final BazelFileWatcher watcher;
+  final StreamSubscription<WatchEvent> subscription;
+
+  _BazelFilesSubscription(this.watcher, this.subscription);
+
+  void cancel() {
+    subscription.cancel();
+    watcher.stop();
+  }
+}
+
+/// A subscription to notifications from a Bazel workspace.
+class _BazelWorkspaceSubscription {
+  final StreamSubscription<BazelFileNotification> workspaceSubscription;
+
+  /// For each absolute path that we searched for, provides the subscriptions
+  /// that we established to watch for changes.
+  ///
+  /// Note that the absolute path used when searching for a file is not
+  /// necessarily the actual path of the file (see [BazelWorkspace.findFile] for
+  /// details on how the files are searched).
+  final fileSubscriptions = <String, _BazelFilesSubscription>{};
+
+  _BazelWorkspaceSubscription(this.workspaceSubscription);
+
+  void cancel() {
+    workspaceSubscription.cancel();
+    fileSubscriptions.values.forEach((sub) => sub.cancel());
+  }
+}
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 9d90b64..8f0c867 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -16,7 +16,6 @@
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
 import 'package:analyzer_plugin/utilities/navigation/navigation_dart.dart';
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 0aafdda..d649879 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -16,7 +16,6 @@
 import 'package:analysis_server/src/services/completion/completion_core.dart';
 import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
-import 'package:analysis_server/src/services/completion/token_details/token_detail_builder.dart';
 import 'package:analysis_server/src/services/completion/yaml/analysis_options_generator.dart';
 import 'package:analysis_server/src/services/completion/yaml/fix_data_generator.dart';
 import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.dart';
@@ -251,9 +250,6 @@
       } else if (requestName == COMPLETION_REQUEST_GET_SUGGESTIONS) {
         processRequest(request);
         return Response.DELAYED_RESPONSE;
-      } else if (requestName == COMPLETION_REQUEST_LIST_TOKEN_DETAILS) {
-        listTokenDetails(request);
-        return Response.DELAYED_RESPONSE;
       } else if (requestName == COMPLETION_REQUEST_SET_SUBSCRIPTIONS) {
         return setSubscriptions(request);
       }
@@ -273,40 +269,6 @@
     }
   }
 
-  /// Process a `completion.listTokenDetails` request.
-  Future<void> listTokenDetails(Request request) async {
-    var params = CompletionListTokenDetailsParams.fromRequest(request);
-
-    var file = params.file;
-    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
-      return;
-    }
-
-    var analysisDriver = server.getAnalysisDriver(file);
-    if (analysisDriver == null) {
-      server.sendResponse(Response.invalidParameter(
-        request,
-        'file',
-        'File is not being analyzed: $file',
-      ));
-    }
-    var session = analysisDriver.currentSession;
-    var result = await session.getResolvedUnit(file);
-    if (result.state != ResultState.VALID) {
-      server.sendResponse(Response.invalidParameter(
-        request,
-        'file',
-        'File does not exist or cannot be read: $file',
-      ));
-    }
-
-    var builder = TokenDetailBuilder();
-    builder.visitNode(result.unit);
-    server.sendResponse(
-      CompletionListTokenDetailsResult(builder.details).toResponse(request.id),
-    );
-  }
-
   /// Process a `completion.getSuggestions` request.
   Future<void> processRequest(Request request) async {
     performance = CompletionPerformance();
diff --git a/pkg/analysis_server/lib/src/domain_execution.dart b/pkg/analysis_server/lib/src/domain_execution.dart
index 2e75ddd..db74f5f 100644
--- a/pkg/analysis_server/lib/src/domain_execution.dart
+++ b/pkg/analysis_server/lib/src/domain_execution.dart
@@ -5,9 +5,7 @@
 import 'dart:collection';
 import 'dart:core';
 
-import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_constants.dart';
-import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analyzer/file_system/file_system.dart';
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index 12a49cd..faad3f9 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/overlay_file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 
 class RuntimeCompletionComputer {
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 30a2a3dd..fe63631 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -40,7 +40,6 @@
 import 'package:analyzer/error/error.dart' as engine;
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/src/dart/analysis/results.dart' as engine;
@@ -106,8 +105,8 @@
       }
 
       var workspace = DartChangeWorkspace(server.currentSessions);
-      var processor =
-          BulkFixProcessor(server.instrumentationService, workspace);
+      var processor = BulkFixProcessor(server.instrumentationService, workspace,
+          useConfigFiles: params.inTestMode);
 
       String sdkPath;
       var sdk = server.findSdk();
diff --git a/pkg/analysis_server/lib/src/lsp/client_configuration.dart b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
index 8af5a85..26ad2d0 100644
--- a/pkg/analysis_server/lib/src/lsp/client_configuration.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
@@ -31,6 +31,9 @@
   bool get previewCommitCharacters =>
       _settings['previewCommitCharacters'] ?? false;
 
+  /// Whether diagnostics should be generated for TODO comments.
+  bool get showTodos => _settings['showTodos'] ?? 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) {
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index c58b195..8e751a4 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -78,17 +78,54 @@
 }
 
 abstract class CustomMethods {
-  static const DiagnosticServer = Method('dart/diagnosticServer');
-  static const Reanalyze = Method('dart/reanalyze');
-  static const PublishClosingLabels =
+  static const diagnosticServer = Method('dart/diagnosticServer');
+  static const reanalyze = Method('dart/reanalyze');
+  static const publishClosingLabels =
       Method('dart/textDocument/publishClosingLabels');
-  static const PublishOutline = Method('dart/textDocument/publishOutline');
-  static const PublishFlutterOutline =
+  static const publishOutline = Method('dart/textDocument/publishOutline');
+  static const publishFlutterOutline =
       Method('dart/textDocument/publishFlutterOutline');
-  static const Super = Method('dart/textDocument/super');
+  static const super_ = Method('dart/textDocument/super');
+
   // TODO(dantup): Remove custom AnalyzerStatus status method soon as no clients
-  // should be relying on it and we now support proper $/progress events.
-  static const AnalyzerStatus = Method(r'$/analyzerStatus');
+  // should be relying on it as we now support proper $/progress events.
+  static const analyzerStatus = Method(r'$/analyzerStatus');
+
+  /// Semantic tokens are dynamically registered using a single string
+  /// "textDocument/semanticTokens" instead of for each individual method
+  /// (full, range, full/delta) so the built-in Method class does not contain
+  /// the required constant.
+  static const semanticTokenDynamicRegistration =
+      Method('textDocument/semanticTokens');
+}
+
+abstract class CustomSemanticTokenModifiers {
+  /// A modifier applied to control keywords like if/for/etc. so they can be
+  /// coloured differently to other keywords (void, import, etc), matching the
+  /// original Dart textmate grammar.
+  /// https://github.com/dart-lang/dart-syntax-highlight/blob/84a8e84f79bc917ebd959a4587349c865dc945e0/grammars/dart.json#L244-L261
+  static const control = SemanticTokenModifiers('control');
+
+  /// A modifier applied to parameter references to indicate they are the name/label
+  /// to allow theming them differently to the values. For example in the code
+  /// `foo({String a}) => foo(a: a)` the a's will be differentiated as:
+  /// - parameter.declaration
+  /// - parameter.label
+  /// - parameter
+  static const label = SemanticTokenModifiers('label');
+
+  /// All custom semantic token modifiers, used to populate the LSP Legend which must
+  /// include all used modifiers.
+  static const values = [control, label];
+}
+
+abstract class CustomSemanticTokenTypes {
+  static const annotation = SemanticTokenTypes('annotation');
+  static const boolean = SemanticTokenTypes('boolean');
+
+  /// All custom semantic token types, used to populate the LSP Legend which must
+  /// include all used types.
+  static const values = [annotation, boolean];
 }
 
 /// CodeActionKinds supported by the server that are not declared in the LSP spec.
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 4a302a2..6ac4547 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
@@ -52,9 +52,9 @@
 
     final result = await requireResolvedUnit(path);
     return result.mapResult((result) async {
-      return _getRefactoring(
-              RefactoringKind(kind), result, offset, length, options)
-          .mapResult((refactoring) async {
+      final refactoring = await _getRefactoring(
+          RefactoringKind(kind), result, offset, length, options);
+      return refactoring.mapResult((refactoring) async {
         // If the token we were given is not cancellable, replace it with one that
         // is for the rest of this request, as a future refactor may need to cancel
         // this request.
@@ -99,24 +99,46 @@
     });
   }
 
-  ErrorOr<Refactoring> _getRefactoring(
+  Future<ErrorOr<Refactoring>> _getRefactoring(
     RefactoringKind kind,
     ResolvedUnitResult result,
     int offset,
     int length,
     Map<String, dynamic> options,
-  ) {
+  ) async {
     switch (kind) {
       case RefactoringKind.EXTRACT_METHOD:
         final refactor = ExtractMethodRefactoring(
             server.searchEngine, result, offset, length);
-        // TODO(dantup): For now we don't have a good way to prompt the user
-        // for a method name so we just use a placeholder and expect them to
-        // rename (this is what C#/Omnisharp does), but there's an open request
-        // to handle this better.
-        // https://github.com/microsoft/language-server-protocol/issues/764
-        refactor.name =
-            (options != null ? options['name'] : null) ?? 'newMethod';
+
+        var preferredName = options != null ? options['name'] : null;
+        // checkInitialConditions will populate names with suggestions.
+        if (preferredName == null) {
+          await refactor.checkInitialConditions();
+          if (refactor.names.isNotEmpty) {
+            preferredName = refactor.names.first;
+          }
+        }
+        refactor.name = preferredName ?? 'newMethod';
+
+        // Defaults to true, but may be surprising if users didn't have an option
+        // to opt in.
+        refactor.extractAll = false;
+        return success(refactor);
+
+      case RefactoringKind.EXTRACT_LOCAL_VARIABLE:
+        final refactor = ExtractLocalRefactoring(result, offset, length);
+
+        var preferredName = options != null ? options['name'] : null;
+        // checkInitialConditions will populate names with suggestions.
+        if (preferredName == null) {
+          await refactor.checkInitialConditions();
+          if (refactor.names.isNotEmpty) {
+            preferredName = refactor.names.first;
+          }
+        }
+        refactor.name = preferredName ?? 'newVariable';
+
         // Defaults to true, but may be surprising if users didn't have an option
         // to opt in.
         refactor.extractAll = false;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
index 559c54e..8a5727a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
@@ -28,7 +28,7 @@
   }
 
   Future<ErrorOr<void>> sendSourceEditsToClient(
-      VersionedTextDocumentIdentifier docIdentifier,
+      OptionalVersionedTextDocumentIdentifier docIdentifier,
       CompilationUnit unit,
       List<SourceEdit> edits) async {
     // If there are no edits to apply, just complete the command without going
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
index 9e3373a..66f95f6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
@@ -13,7 +13,7 @@
     extends MessageHandler<void, DartDiagnosticServer> {
   DiagnosticServerHandler(LspAnalysisServer server) : super(server);
   @override
-  Method get handlesMessage => CustomMethods.DiagnosticServer;
+  Method get handlesMessage => CustomMethods.diagnosticServer;
 
   @override
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_reanalyze.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_reanalyze.dart
index 68a04e9..0c2cde4 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_reanalyze.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_reanalyze.dart
@@ -11,7 +11,7 @@
 class ReanalyzeHandler extends MessageHandler<void, void> {
   ReanalyzeHandler(LspAnalysisServer server) : super(server);
   @override
-  Method get handlesMessage => CustomMethods.Reanalyze;
+  Method get handlesMessage => CustomMethods.reanalyze;
 
   @override
   LspJsonHandler<void> get jsonHandler => NullJsonHandler;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart
index b33967f..9ddba98 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart
@@ -14,7 +14,7 @@
     extends MessageHandler<TextDocumentPositionParams, Location> {
   SuperHandler(LspAnalysisServer server) : super(server);
   @override
-  Method get handlesMessage => CustomMethods.Super;
+  Method get handlesMessage => CustomMethods.super_;
 
   @override
   LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
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 355cbde..f2bec91 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
@@ -439,6 +439,12 @@
             'Extract Method', RefactoringKind.EXTRACT_METHOD));
       }
 
+      // Extract Local Variable
+      if (ExtractLocalRefactoring(unit, offset, length).isAvailable()) {
+        refactorActions.add(createRefactor(CodeActionKind.RefactorExtract,
+            'Extract Local Variable', RefactoringKind.EXTRACT_LOCAL_VARIABLE));
+      }
+
       // Extract Widget
       if (ExtractWidgetRefactoring(server.searchEngine, unit, offset, length)
           .isAvailable()) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
index 71205a0..eae5c8c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -87,6 +87,7 @@
     }
 
     final pos = params.position;
+    final textDocument = params.textDocument;
     final path = pathOfDoc(params.textDocument);
     // If the client provided us a version doc identifier, we'll use it to ensure
     // we're not computing a rename for an old document. If not, we'll just assume
@@ -94,9 +95,12 @@
     // and then use it to verify the document hadn't changed again before we
     // send the edits.
     final docIdentifier = await path.mapResult((path) => success(
-        params.textDocument is VersionedTextDocumentIdentifier
-            ? params.textDocument as VersionedTextDocumentIdentifier
-            : server.getVersionedDocumentIdentifier(path)));
+        textDocument is OptionalVersionedTextDocumentIdentifier
+            ? textDocument
+            : textDocument is VersionedTextDocumentIdentifier
+                ? OptionalVersionedTextDocumentIdentifier(
+                    uri: textDocument.uri, version: textDocument.version)
+                : server.getVersionedDocumentIdentifier(path)));
 
     final unit = await path.mapResult(requireResolvedUnit);
     final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_semantic_tokens.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_semantic_tokens.dart
new file mode 100644
index 0000000..ad40077
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_semantic_tokens.dart
@@ -0,0 +1,146 @@
+// 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 'dart:async';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/computer/computer_highlights.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/lsp/semantic_tokens/encoder.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+
+abstract class AbstractSemanticTokensHandler<T>
+    extends MessageHandler<T, SemanticTokens>
+    with LspPluginRequestHandlerMixin {
+  AbstractSemanticTokensHandler(LspAnalysisServer server) : super(server);
+
+  List<List<HighlightRegion>> getPluginResults(String path) {
+    final notificationManager = server.notificationManager;
+    return notificationManager.highlights.getResults(path);
+  }
+
+  Future<List<SemanticTokenInfo>> getServerResult(
+      String path, SourceRange range) async {
+    final result = await server.getResolvedUnit(path);
+    if (result?.state == ResultState.VALID) {
+      final computer = DartUnitHighlightsComputer(result.unit, range: range);
+      return computer.computeSemanticTokens();
+    }
+    return [];
+  }
+
+  Iterable<SemanticTokenInfo> _filter(
+      Iterable<SemanticTokenInfo> tokens, SourceRange range) {
+    if (range == null) {
+      return tokens;
+    }
+
+    return tokens.where((token) =>
+        !(token.offset + token.length < range.offset ||
+            token.offset > range.end));
+  }
+
+  Future<ErrorOr<SemanticTokens>> _handleImpl(
+      TextDocumentIdentifier textDocument, CancellationToken token,
+      {Range range}) async {
+    final path = pathOfDoc(textDocument);
+
+    return path.mapResult((path) async {
+      final lineInfo = server.getLineInfo(path);
+      // If there is no lineInfo, the request cannot be translated from LSP
+      // line/col to server offset/length.
+      if (lineInfo == null) {
+        return success(null);
+      }
+
+      return toSourceRange(lineInfo, range).mapResult((range) async {
+        final serverTokens = await getServerResult(path, range);
+        final pluginHighlightRegions =
+            getPluginResults(path).expand((results) => results).toList();
+
+        if (token.isCancellationRequested) {
+          return cancelled();
+        }
+
+        final encoder = SemanticTokenEncoder();
+        Iterable<SemanticTokenInfo> pluginTokens =
+            encoder.convertHighlightToTokens(pluginHighlightRegions);
+
+        // Plugin tokens are not filtered at source, so need to be filtered here.
+        pluginTokens = _filter(pluginTokens, range);
+
+        Iterable<SemanticTokenInfo> tokens = [...serverTokens, ...pluginTokens];
+
+        // Capabilities exist for supporting multiline/overlapping tokens. These
+        // could be used if any clients take it up (VS Code does not).
+        // - clientCapabilities?.multilineTokenSupport
+        // - clientCapabilities?.overlappingTokenSupport
+        final allowMultilineTokens = false;
+        final allowOverlappingTokens = false;
+
+        // Some of the translation operations and the final encoding require
+        // the tokens to be sorted. Do it once here to avoid each method needing
+        // to do it itself (resulting in multiple sorts).
+        tokens = tokens.toList()
+          ..sort(SemanticTokenInfo.offsetLengthPrioritySort);
+
+        if (!allowOverlappingTokens) {
+          tokens = encoder.splitOverlappingTokens(tokens);
+        }
+
+        if (!allowMultilineTokens) {
+          tokens = tokens
+              .expand((token) => encoder.splitMultilineTokens(token, lineInfo));
+
+          // Tokens may need re-filtering after being split up as there may
+          // now be tokens outside of the range.
+          tokens = _filter(tokens, range);
+        }
+
+        final semanticTokens = encoder.encodeTokens(tokens.toList(), lineInfo);
+
+        return success(semanticTokens);
+      });
+    });
+  }
+}
+
+class SemanticTokensFullHandler
+    extends AbstractSemanticTokensHandler<SemanticTokensParams> {
+  SemanticTokensFullHandler(LspAnalysisServer server) : super(server);
+
+  @override
+  Method get handlesMessage => Method.textDocument_semanticTokens_full;
+
+  @override
+  LspJsonHandler<SemanticTokensParams> get jsonHandler =>
+      SemanticTokensParams.jsonHandler;
+
+  @override
+  Future<ErrorOr<SemanticTokens>> handle(
+          SemanticTokensParams params, CancellationToken token) =>
+      _handleImpl(params.textDocument, token);
+}
+
+class SemanticTokensRangeHandler
+    extends AbstractSemanticTokensHandler<SemanticTokensRangeParams> {
+  SemanticTokensRangeHandler(LspAnalysisServer server) : super(server);
+
+  @override
+  Method get handlesMessage => Method.textDocument_semanticTokens_range;
+
+  @override
+  LspJsonHandler<SemanticTokensRangeParams> get jsonHandler =>
+      SemanticTokensRangeParams.jsonHandler;
+
+  @override
+  Future<ErrorOr<SemanticTokens>> handle(
+          SemanticTokensRangeParams params, CancellationToken token) =>
+      _handleImpl(params.textDocument, token, range: params.range);
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
index be00dc9..c1298e5 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -29,9 +29,11 @@
 import 'package:analysis_server/src/lsp/handlers/handler_initialized.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_references.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_rename.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_semantic_tokens.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_shutdown.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_signature_help.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_text_document_changes.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_will_rename_files.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_workspace_configuration.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_workspace_symbols.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
@@ -100,6 +102,9 @@
     registerHandler(WorkspaceSymbolHandler(server));
     registerHandler(WorkspaceDidChangeConfigurationMessageHandler(server));
     registerHandler(ReanalyzeHandler(server));
+    registerHandler(WillRenameFilesHandler(server));
+    registerHandler(SemanticTokensFullHandler(server));
+    registerHandler(SemanticTokensRangeHandler(server));
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
index 152ba37..fccc0eb 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
@@ -118,7 +118,7 @@
     final doc = params.textDocument;
     final path = pathOfDocItem(doc);
     return path.mapResult((path) {
-      // We don't get a VersionedTextDocumentIdentifier with a didOpen but we
+      // We don't get a OptionalVersionedTextDocumentIdentifier with a didOpen but we
       // do get the necessary info to create one.
       server.documentVersions[path] = VersionedTextDocumentIdentifier(
         version: params.textDocument.version,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
new file mode 100644
index 0000000..2beb369
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
@@ -0,0 +1,60 @@
+// 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.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/services/refactoring/refactoring.dart';
+
+class WillRenameFilesHandler extends MessageHandler<RenameFilesParams, void> {
+  WillRenameFilesHandler(LspAnalysisServer server) : super(server);
+  @override
+  Method get handlesMessage => Method.workspace_willRenameFiles;
+
+  @override
+  LspJsonHandler<RenameFilesParams> get jsonHandler =>
+      RenameFilesParams.jsonHandler;
+
+  @override
+  Future<ErrorOr<WorkspaceEdit>> handle(
+      RenameFilesParams params, CancellationToken token) async {
+    final files = params?.files ?? [];
+    // For performance reasons, only single-file rename/moves are currently supported.
+    if (files.length > 1 || files.any((f) => !f.oldUri.endsWith('.dart'))) {
+      return success(null);
+    }
+
+    final file = files.single;
+    final oldPath = pathOfUri(Uri.tryParse(file.oldUri));
+    final newPath = pathOfUri(Uri.tryParse(file.newUri));
+    return oldPath.mapResult((oldPath) =>
+        newPath.mapResult((newPath) => _renameFile(oldPath, newPath)));
+  }
+
+  Future<ErrorOr<WorkspaceEdit>> _renameFile(
+      String oldPath, String newPath) async {
+    final resolvedUnit = await server.getResolvedUnit(oldPath);
+    if (resolvedUnit == null) {
+      return success(null);
+    }
+
+    final refactoring = MoveFileRefactoring(server.resourceProvider,
+        server.refactoringWorkspace, resolvedUnit, oldPath)
+      ..newFile = newPath;
+
+    // If we're unable to update imports for a rename, we should silently do
+    // nothing rather than interrupt the users file rename with an error.
+    final results = await refactoring.checkAllConditions();
+    if (results.hasFatalError) {
+      return success(null);
+    }
+
+    final change = await refactoring.createChange();
+    final edit = createWorkspaceEdit(server, change.edits);
+
+    return success(edit);
+  }
+}
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 3c67aab..106cd91 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -8,7 +8,6 @@
 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:analysis_server/protocol/protocol_generated.dart' as protocol;
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/analysis_server_abstract.dart';
 import 'package:analysis_server/src/collections.dart';
@@ -248,11 +247,13 @@
   }
 
   /// Gets the version of a document known to the server, returning a
-  /// [VersionedTextDocumentIdentifier] with a version of `null` if the document
+  /// [OptionalVersionedTextDocumentIdentifier] with a version of `null` if the document
   /// version is not known.
-  VersionedTextDocumentIdentifier getVersionedDocumentIdentifier(String path) {
-    return documentVersions[path] ??
-        VersionedTextDocumentIdentifier(uri: Uri.file(path).toString());
+  OptionalVersionedTextDocumentIdentifier getVersionedDocumentIdentifier(
+      String path) {
+    return OptionalVersionedTextDocumentIdentifier(
+        uri: Uri.file(path).toString(),
+        version: documentVersions[path]?.version);
   }
 
   void handleClientConnection(
@@ -424,7 +425,7 @@
     final params = PublishClosingLabelsParams(
         uri: Uri.file(path).toString(), labels: labels);
     final message = NotificationMessage(
-      method: CustomMethods.PublishClosingLabels,
+      method: CustomMethods.publishClosingLabels,
       params: params,
       jsonrpc: jsonRpcVersion,
     );
@@ -446,7 +447,7 @@
     final params = PublishFlutterOutlineParams(
         uri: Uri.file(path).toString(), outline: outline);
     final message = NotificationMessage(
-      method: CustomMethods.PublishFlutterOutline,
+      method: CustomMethods.publishFlutterOutline,
       params: params,
       jsonrpc: jsonRpcVersion,
     );
@@ -457,7 +458,7 @@
     final params =
         PublishOutlineParams(uri: Uri.file(path).toString(), outline: outline);
     final message = NotificationMessage(
-      method: CustomMethods.PublishOutline,
+      method: CustomMethods.publishOutline,
       params: params,
       jsonrpc: jsonRpcVersion,
     );
@@ -552,7 +553,7 @@
     // it's unlikely to be in use by any clients.
     if (clientCapabilities.window?.workDoneProgress != true) {
       channel.sendNotification(NotificationMessage(
-        method: CustomMethods.AnalyzerStatus,
+        method: CustomMethods.analyzerStatus,
         params: AnalyzerStatusParams(isAnalyzing: status.isAnalyzing),
         jsonrpc: jsonRpcVersion,
       ));
@@ -771,9 +772,7 @@
       if (analysisServer.shouldSendErrorsNotificationFor(path)) {
         final serverErrors = protocol.mapEngineErrors(
             result,
-            result.errors
-                .where((e) => e.errorCode.type != ErrorType.TODO)
-                .toList(),
+            result.errors.where(_shouldSendDiagnostic).toList(),
             (result, error, [severity]) => toDiagnostic(
                   result,
                   error,
@@ -815,6 +814,11 @@
   }
 
   @override
+  void afterContextRefresh() {
+    analysisServer.addContextsToDeclarationsTracker();
+  }
+
+  @override
   void afterWatchEvent(WatchEvent event) {
     // TODO: implement afterWatchEvent
   }
@@ -874,4 +878,8 @@
         ?.forEach((path) => analysisServer.publishDiagnostics(path, const []));
     driver.dispose();
   }
+
+  bool _shouldSendDiagnostic(AnalysisError error) =>
+      error.errorCode.type != ErrorType.TODO ||
+      analysisServer.clientConfiguration.showTodos;
 }
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 6f0cd7b..fdde79c 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -8,8 +8,6 @@
 import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart'
     as lsp;
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
-import 'package:analysis_server/lsp_protocol/protocol_generated.dart'
-    show ResponseError;
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
@@ -29,8 +27,8 @@
 import 'package:analyzer/diagnostic/diagnostic.dart' as analyzer;
 import 'package:analyzer/error/error.dart' as server;
 import 'package:analyzer/source/line_info.dart' as server;
+import 'package:analyzer/source/source_range.dart' as server;
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/source.dart' as server;
 import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:analyzer/src/services/available_declarations.dart' as dec;
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
@@ -1057,6 +1055,7 @@
 
 lsp.FoldingRangeKind toFoldingRangeKind(server.FoldingKind kind) {
   switch (kind) {
+    case server.FoldingKind.COMMENT:
     case server.FoldingKind.DOCUMENTATION_COMMENT:
     case server.FoldingKind.FILE_HEADER:
       return lsp.FoldingRangeKind.Comment;
@@ -1208,10 +1207,36 @@
   );
 }
 
+ErrorOr<server.SourceRange> toSourceRange(
+    server.LineInfo lineInfo, Range range) {
+  if (range == null) {
+    return success(null);
+  }
+
+  // If there is a range, convert to offsets because that's what
+  // the tokens are computed using initially.
+  final start = toOffset(lineInfo, range.start);
+  final end = toOffset(lineInfo, range.end);
+  if (start?.isError ?? false) {
+    return failure(start);
+  }
+  if (end?.isError ?? false) {
+    return failure(end);
+  }
+
+  final startOffset = start?.result;
+  final endOffset = end?.result;
+
+  return success(server.SourceRange(startOffset, endOffset - startOffset));
+}
+
 lsp.TextDocumentEdit toTextDocumentEdit(FileEditInformation edit) {
   return lsp.TextDocumentEdit(
     textDocument: edit.doc,
-    edits: edit.edits.map((e) => toTextEdit(edit.lineInfo, e)).toList(),
+    edits: edit.edits
+        .map((e) => Either2<TextEdit, AnnotatedTextEdit>.t1(
+            toTextEdit(edit.lineInfo, e)))
+        .toList(),
   );
 }
 
@@ -1294,6 +1319,14 @@
   var insertText = completion;
   var insertTextFormat = lsp.InsertTextFormat.PlainText;
 
+  // SuggestionBuilder already does the equiv of completeFunctionCalls for
+  // some methods (for example Flutter's setState). If the completion already
+  // includes any `(` then disable our own insertion as the special-cased code
+  // will likely provide better code.
+  if (completion.contains('(')) {
+    completeFunctionCalls = false;
+  }
+
   // If the client supports snippets, we can support completeFunctionCalls or
   // setting a selection.
   if (supportsSnippets) {
diff --git a/pkg/analysis_server/lib/src/lsp/notification_manager.dart b/pkg/analysis_server/lib/src/lsp/notification_manager.dart
index 068b5ef..7752a79 100644
--- a/pkg/analysis_server/lib/src/lsp/notification_manager.dart
+++ b/pkg/analysis_server/lib/src/lsp/notification_manager.dart
@@ -10,7 +10,6 @@
 import 'package:analysis_server/src/plugin/notification_manager.dart';
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analyzer_plugin/protocol/protocol.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
 import 'package:path/path.dart';
 
 class LspNotificationManager extends AbstractNotificationManager {
diff --git a/pkg/analysis_server/lib/src/lsp/semantic_tokens/encoder.dart b/pkg/analysis_server/lib/src/lsp/semantic_tokens/encoder.dart
new file mode 100644
index 0000000..4ee6f99
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/encoder.dart
@@ -0,0 +1,196 @@
+// 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 'dart:collection';
+import 'dart:math' as math;
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/semantic_tokens/legend.dart';
+import 'package:analysis_server/src/lsp/semantic_tokens/mapping.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+
+/// Collects information about Semantic Tokens using absolute line/columns and
+/// token types/modifiers and encodes them into a [List<int>] in a
+/// [SemanticTokens] (a [List<int>]) as described by the LSP spec .
+class SemanticTokenEncoder {
+  // LSP is zero-based but server is 1-based.
+  static const _serverToLspLineOffset = -1;
+
+  /// Converts [regions]s into LSP [SemanticTokenInfo].
+  List<SemanticTokenInfo> convertHighlightToTokens(
+      List<HighlightRegion> regions) {
+    final tokens = <SemanticTokenInfo>[];
+
+    Iterable<HighlightRegion> translatedRegions = regions;
+
+    // Remove any tokens that will not be mapped as there's no point further processing
+    // them (eg. splitting multiline/overlaps) if they will be dropped.
+    translatedRegions = translatedRegions
+        .where((region) => highlightRegionTokenTypes.containsKey(region.type));
+
+    for (final region in translatedRegions) {
+      final tokenType = highlightRegionTokenTypes[region.type];
+
+      tokens.add(SemanticTokenInfo(
+        region.offset,
+        region.length,
+        tokenType,
+        highlightRegionTokenModifiers[region.type],
+      ));
+    }
+
+    return tokens;
+  }
+
+  /// Encodes tokens according to the LSP spec.
+  ///
+  /// Tokens must be pre-sorted by offset so that relative line/columns are accurate.
+  SemanticTokens encodeTokens(
+      List<SemanticTokenInfo> sortedTokens, LineInfo lineInfo) {
+    final encodedTokens = <int>[];
+    var lastLine = 0;
+    var lastColumn = 0;
+
+    for (final token in sortedTokens) {
+      final location = lineInfo.getLocation(token.offset);
+      final tokenLine = location.lineNumber + _serverToLspLineOffset;
+      final tokenColumn = location.columnNumber + _serverToLspLineOffset;
+
+      final relativeLine = tokenLine - lastLine;
+      // Column is relative to last only if on the same line.
+      final relativeColumn =
+          relativeLine == 0 ? tokenColumn - lastColumn : tokenColumn;
+
+      // The resulting array is groups of 5 items as described in the LSP spec:
+      // https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-16.md#textDocument_semanticTokens
+      encodedTokens.addAll([
+        relativeLine,
+        relativeColumn,
+        token.length,
+        semanticTokenLegend.indexForType(token.type),
+        semanticTokenLegend.bitmaskForModifiers(token.modifiers) ?? 0
+      ]);
+
+      lastLine = tokenLine;
+      lastColumn = tokenColumn;
+    }
+
+    return SemanticTokens(data: encodedTokens);
+  }
+
+  /// Splits multiline regions into multiple regions for clients that do not support
+  /// multiline tokens. Multiline tokens will be split at the end of the line and
+  /// line endings and indenting will be included in the tokens.
+  Iterable<SemanticTokenInfo> splitMultilineTokens(
+      SemanticTokenInfo token, LineInfo lineInfo) sync* {
+    final start = lineInfo.getLocation(token.offset);
+    final end = lineInfo.getLocation(token.offset + token.length);
+
+    // Create a region for each line in the original region.
+    for (var lineNumber = start.lineNumber;
+        lineNumber <= end.lineNumber;
+        lineNumber++) {
+      final isFirstLine = lineNumber == start.lineNumber;
+      final isLastLine = lineNumber == end.lineNumber;
+      final lineOffset = lineInfo.getOffsetOfLine(lineNumber - 1);
+
+      final startOffset = isFirstLine ? start.columnNumber - 1 : 0;
+      final endOffset = isLastLine
+          ? end.columnNumber - 1
+          : lineInfo.getOffsetOfLine(lineNumber) - lineOffset;
+      final length = endOffset - startOffset;
+
+      yield SemanticTokenInfo(
+          lineOffset + startOffset, length, token.type, token.modifiers);
+    }
+  }
+
+  /// Splits overlapping/nested tokens into descrete ranges for the "top-most"
+  /// token.
+  ///
+  /// Tokens must be pre-sorted by offset, with tokens having the same offset sorted
+  /// with the longest first.
+  Iterable<SemanticTokenInfo> splitOverlappingTokens(
+      Iterable<SemanticTokenInfo> sortedTokens) sync* {
+    if (sortedTokens.isEmpty) {
+      return;
+    }
+
+    final firstToken = sortedTokens.first;
+    final stack = ListQueue<SemanticTokenInfo>()..add(firstToken);
+    var pos = firstToken.offset;
+
+    for (final current in sortedTokens.skip(1)) {
+      if (stack.last != null) {
+        final last = stack.last;
+        final newPos = current.offset;
+        if (newPos - pos > 0) {
+          // The previous region ends at either its original end or
+          // the position of this next region, whichever is shorter.
+          final end = math.min(last.offset + last.length, newPos);
+          final length = end - pos;
+          yield SemanticTokenInfo(pos, length, last.type, last.modifiers);
+          pos = newPos;
+        }
+      }
+
+      stack.addLast(current);
+    }
+
+    // Process any remaining stack after the last region.
+    while (stack.isNotEmpty) {
+      final last = stack.removeLast();
+      final newPos = last.offset + last.length;
+      final length = newPos - pos;
+      if (length > 0) {
+        yield SemanticTokenInfo(pos, length, last.type, last.modifiers);
+        pos = newPos;
+      }
+    }
+  }
+}
+
+class SemanticTokenInfo {
+  final int offset;
+  final int length;
+  final SemanticTokenTypes type;
+  final Set<SemanticTokenModifiers> modifiers;
+
+  SemanticTokenInfo(this.offset, this.length, this.type, this.modifiers);
+
+  /// Sorter for semantic tokens that ensures tokens are sorted in offset order
+  /// then longest first, then by priority, and finally by name. This ensures
+  /// the order is always stable.
+  static int offsetLengthPrioritySort(
+      SemanticTokenInfo t1, SemanticTokenInfo t2) {
+    final priorities = {
+      // Ensure boolean comes above keyword.
+      CustomSemanticTokenTypes.boolean: 1,
+    };
+
+    // First sort by offset.
+    if (t1.offset != t2.offset) {
+      return t1.offset.compareTo(t2.offset);
+    }
+
+    // Then length (so longest are first).
+    if (t1.length != t1.length) {
+      return -t1.length.compareTo(t2.length);
+    }
+
+    // Next sort by priority (if different).
+    final priority1 = priorities[t1.type] ?? 0;
+    final priority2 = priorities[t2.type] ?? 0;
+    if (priority1 != priority2) {
+      return priority1.compareTo(priority2);
+    }
+
+    // If the tokens had the same offset and length, sort by name. This
+    // is completely arbitrary but it's only important that it is consistent
+    // between tokens and the sort is stable.
+    return t1.type.toString().compareTo(t2.type.toString());
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/semantic_tokens/legend.dart b/pkg/analysis_server/lib/src/lsp/semantic_tokens/legend.dart
new file mode 100644
index 0000000..ef2d8c4
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/legend.dart
@@ -0,0 +1,83 @@
+// 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 'dart:math' as math;
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/semantic_tokens/mapping.dart';
+import 'package:meta/meta.dart';
+
+final semanticTokenLegend = SemanticTokenLegendLookup();
+
+/// A helper for looking up indexes and bitmasks of [SemanticTokenTypes] and
+/// [SemanticTokenModifiers].
+class SemanticTokenLegendLookup {
+  /// An LSP [SemanticTokensLegend] describing all supported tokens and modifiers.
+  SemanticTokensLegend lspLegend;
+
+  /// All [SemanticTokenModifiers] the server may generate. The order of these
+  /// items is important as the indexes will be used in communication between
+  /// server and client.
+  List<SemanticTokenModifiers> _usedTokenModifiers;
+
+  /// All [SemanticTokenTypes] the server may generate. The order of these
+  /// items is important as the indexes will be used in communication betewen
+  /// server and client.
+  List<SemanticTokenTypes> _usedTokenTypes;
+
+  SemanticTokenLegendLookup() {
+    // Build lists of all tokens and modifiers that exist in our mappings or that
+    // we have added as custom types. These will be used to determine the indexes used for communication.
+    _usedTokenTypes = Set.of(highlightRegionTokenTypes.values
+            .followedBy(CustomSemanticTokenTypes.values))
+        .toList();
+    _usedTokenModifiers = Set.of(highlightRegionTokenModifiers.values
+            .expand((v) => v)
+            .followedBy(CustomSemanticTokenModifiers.values))
+        .toList();
+
+    // Build the LSP Legend which tells the client all of the tokens and modifiers
+    // we will use in the order they should be accessed by index/bit.
+    lspLegend = SemanticTokensLegend(
+      tokenTypes:
+          _usedTokenTypes.map((tokenType) => tokenType.toString()).toList(),
+      tokenModifiers: _usedTokenModifiers
+          .map((tokenModifier) => tokenModifier.toString())
+          .toList(),
+    );
+  }
+
+  int bitmaskForModifiers(Set<SemanticTokenModifiers> modifiers) {
+    // Modifiers use a bit mask where each bit represents the index of a modifier.
+    // 001001 would indicate the 1st and 4th modifiers are applied.
+    return modifiers
+            ?.map(_usedTokenModifiers.indexOf)
+            ?.map((index) => math.pow(2, index))
+            ?.reduce((a, b) => a + b) ??
+        0;
+  }
+
+  int indexForType(SemanticTokenTypes type) {
+    return _usedTokenTypes.indexOf(type);
+  }
+
+  /// Gets the [SemanticTokenModifiers] for a given index.
+  @visibleForTesting
+  List<SemanticTokenModifiers> modifiersForBitmask(int mask) {
+    final modifiers = <SemanticTokenModifiers>[];
+    for (var i = 0; i < _usedTokenModifiers.length; i++) {
+      // Check if the i'th bit is set
+      final modifierBit = 1 << i;
+      if (mask & modifierBit != 0) {
+        modifiers.add(_usedTokenModifiers[i]);
+      }
+    }
+    return modifiers;
+  }
+
+  /// Gets the [SemanticTokenTypes] for a given index.
+  @visibleForTesting
+  SemanticTokenTypes typeForIndex(int index) => _usedTokenTypes[index];
+}
diff --git a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
new file mode 100644
index 0000000..7405b0e
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
@@ -0,0 +1,173 @@
+// 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/semantic_tokens/legend.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+
+final highlightRegionMapper = RegionTypeMapper();
+
+/// A mapping from [HighlightRegionType] to a set of [SemanticTokenModifiers].
+final highlightRegionTokenModifiers =
+    <HighlightRegionType, Set<SemanticTokenModifiers>>{
+  HighlightRegionType.COMMENT_DOCUMENTATION: {
+    SemanticTokenModifiers.documentation
+  },
+  HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.DYNAMIC_PARAMETER_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.INSTANCE_FIELD_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.INSTANCE_GETTER_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.INSTANCE_METHOD_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.INSTANCE_SETTER_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.LOCAL_FUNCTION_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.LOCAL_VARIABLE_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.PARAMETER_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.STATIC_FIELD_DECLARATION: {
+    SemanticTokenModifiers.declaration,
+    SemanticTokenModifiers.static,
+  },
+  HighlightRegionType.STATIC_GETTER_DECLARATION: {
+    SemanticTokenModifiers.declaration,
+    SemanticTokenModifiers.static,
+  },
+  HighlightRegionType.STATIC_GETTER_REFERENCE: {SemanticTokenModifiers.static},
+  HighlightRegionType.STATIC_METHOD_DECLARATION: {
+    SemanticTokenModifiers.declaration,
+    SemanticTokenModifiers.static,
+  },
+  HighlightRegionType.STATIC_METHOD_REFERENCE: {SemanticTokenModifiers.static},
+  HighlightRegionType.STATIC_SETTER_DECLARATION: {
+    SemanticTokenModifiers.declaration,
+    SemanticTokenModifiers.static,
+  },
+  HighlightRegionType.STATIC_SETTER_REFERENCE: {SemanticTokenModifiers.static},
+  HighlightRegionType.TOP_LEVEL_FUNCTION_DECLARATION: {
+    SemanticTokenModifiers.declaration,
+    SemanticTokenModifiers.static,
+  },
+  HighlightRegionType.TOP_LEVEL_GETTER_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.TOP_LEVEL_SETTER_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+  HighlightRegionType.TOP_LEVEL_VARIABLE_DECLARATION: {
+    SemanticTokenModifiers.declaration
+  },
+};
+
+/// A mapping from [HighlightRegionType] to [SemanticTokenTypes].
+final highlightRegionTokenTypes = {
+  HighlightRegionType.ANNOTATION: CustomSemanticTokenTypes.annotation,
+  HighlightRegionType.BUILT_IN: SemanticTokenTypes.keyword,
+  HighlightRegionType.CLASS: SemanticTokenTypes.class_,
+  HighlightRegionType.COMMENT_BLOCK: SemanticTokenTypes.comment,
+  HighlightRegionType.COMMENT_DOCUMENTATION: SemanticTokenTypes.comment,
+  HighlightRegionType.COMMENT_END_OF_LINE: SemanticTokenTypes.comment,
+  HighlightRegionType.CONSTRUCTOR: SemanticTokenTypes.class_,
+  HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_DECLARATION:
+      SemanticTokenTypes.variable,
+  HighlightRegionType.DYNAMIC_LOCAL_VARIABLE_REFERENCE:
+      SemanticTokenTypes.variable,
+  HighlightRegionType.DYNAMIC_PARAMETER_DECLARATION:
+      SemanticTokenTypes.parameter,
+  HighlightRegionType.DYNAMIC_PARAMETER_REFERENCE: SemanticTokenTypes.parameter,
+  HighlightRegionType.ENUM: SemanticTokenTypes.enum_,
+  HighlightRegionType.ENUM_CONSTANT: SemanticTokenTypes.enumMember,
+  HighlightRegionType.FUNCTION_TYPE_ALIAS: SemanticTokenTypes.type,
+  HighlightRegionType.INSTANCE_FIELD_DECLARATION: SemanticTokenTypes.variable,
+  HighlightRegionType.INSTANCE_FIELD_REFERENCE: SemanticTokenTypes.variable,
+  HighlightRegionType.INSTANCE_GETTER_DECLARATION: SemanticTokenTypes.property,
+  HighlightRegionType.INSTANCE_GETTER_REFERENCE: SemanticTokenTypes.property,
+  HighlightRegionType.INSTANCE_METHOD_DECLARATION: SemanticTokenTypes.method,
+  HighlightRegionType.INSTANCE_METHOD_REFERENCE: SemanticTokenTypes.method,
+  HighlightRegionType.INSTANCE_SETTER_DECLARATION: SemanticTokenTypes.property,
+  HighlightRegionType.INSTANCE_SETTER_REFERENCE: SemanticTokenTypes.property,
+  HighlightRegionType.KEYWORD: SemanticTokenTypes.keyword,
+  HighlightRegionType.LIBRARY_NAME: SemanticTokenTypes.namespace,
+  HighlightRegionType.LITERAL_BOOLEAN: CustomSemanticTokenTypes.boolean,
+  HighlightRegionType.LITERAL_DOUBLE: SemanticTokenTypes.number,
+  HighlightRegionType.LITERAL_INTEGER: SemanticTokenTypes.number,
+  HighlightRegionType.LITERAL_STRING: SemanticTokenTypes.string,
+  HighlightRegionType.LOCAL_FUNCTION_DECLARATION: SemanticTokenTypes.function,
+  HighlightRegionType.LOCAL_FUNCTION_REFERENCE: SemanticTokenTypes.function,
+  HighlightRegionType.LOCAL_VARIABLE_DECLARATION: SemanticTokenTypes.variable,
+  HighlightRegionType.LOCAL_VARIABLE_REFERENCE: SemanticTokenTypes.variable,
+  HighlightRegionType.PARAMETER_DECLARATION: SemanticTokenTypes.parameter,
+  HighlightRegionType.PARAMETER_REFERENCE: SemanticTokenTypes.parameter,
+  HighlightRegionType.STATIC_FIELD_DECLARATION: SemanticTokenTypes.variable,
+  HighlightRegionType.STATIC_GETTER_DECLARATION: SemanticTokenTypes.property,
+  HighlightRegionType.STATIC_GETTER_REFERENCE: SemanticTokenTypes.property,
+  HighlightRegionType.STATIC_METHOD_DECLARATION: SemanticTokenTypes.method,
+  HighlightRegionType.STATIC_METHOD_REFERENCE: SemanticTokenTypes.method,
+  HighlightRegionType.STATIC_SETTER_DECLARATION: SemanticTokenTypes.property,
+  HighlightRegionType.STATIC_SETTER_REFERENCE: SemanticTokenTypes.property,
+  HighlightRegionType.TOP_LEVEL_FUNCTION_DECLARATION:
+      SemanticTokenTypes.function,
+  HighlightRegionType.TOP_LEVEL_FUNCTION_REFERENCE: SemanticTokenTypes.function,
+  HighlightRegionType.TOP_LEVEL_GETTER_DECLARATION: SemanticTokenTypes.property,
+  HighlightRegionType.TOP_LEVEL_GETTER_REFERENCE: SemanticTokenTypes.property,
+  HighlightRegionType.TOP_LEVEL_SETTER_DECLARATION: SemanticTokenTypes.property,
+  HighlightRegionType.TOP_LEVEL_SETTER_REFERENCE: SemanticTokenTypes.property,
+  HighlightRegionType.TOP_LEVEL_VARIABLE: SemanticTokenTypes.variable,
+  HighlightRegionType.TOP_LEVEL_VARIABLE_DECLARATION:
+      SemanticTokenTypes.variable,
+  HighlightRegionType.TYPE_NAME_DYNAMIC: SemanticTokenTypes.type,
+  HighlightRegionType.TYPE_PARAMETER: SemanticTokenTypes.typeParameter,
+  HighlightRegionType.UNRESOLVED_INSTANCE_MEMBER_REFERENCE:
+      SemanticTokenTypes.variable,
+};
+
+/// A helper for converting from Server highlight regions to LSP semantic tokens.
+class RegionTypeMapper {
+  /// A map to get the [SemanticTokenTypes] index directly from a [HighlightRegionType].
+  final Map<HighlightRegionType, int> _tokenTypeIndexForHighlightRegion = {};
+
+  /// A map to get the [SemanticTokenModifiers] bitmask directly from a [HighlightRegionType].
+  final Map<HighlightRegionType, int> _tokenModifierBitmaskForHighlightRegion =
+      {};
+
+  RegionTypeMapper() {
+    // Build mappings that go directly from [HighlightRegionType] to index/bitmask
+    // for faster lookups.
+    for (final regionType in highlightRegionTokenTypes.keys) {
+      _tokenTypeIndexForHighlightRegion[regionType] = semanticTokenLegend
+          .indexForType(highlightRegionTokenTypes[regionType]);
+    }
+
+    for (final regionType in highlightRegionTokenTypes.keys) {
+      _tokenModifierBitmaskForHighlightRegion[regionType] = semanticTokenLegend
+          .bitmaskForModifiers(highlightRegionTokenModifiers[regionType]);
+    }
+  }
+
+  /// Gets the [SemanticTokenModifiers] bitmask for a [HighlightRegionType]. Returns
+  /// null if the region type has not been mapped.
+  int bitmaskForModifier(HighlightRegionType type) =>
+      _tokenModifierBitmaskForHighlightRegion[type];
+
+  /// Gets the [SemanticTokenTypes] index for a [HighlightRegionType]. Returns
+  /// null if the region type has not been mapped.
+  int indexForToken(HighlightRegionType type) =>
+      _tokenTypeIndexForHighlightRegion[type];
+}
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 b621c69..f67feaa 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -6,6 +6,7 @@
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/semantic_tokens/legend.dart';
 
 /// Helper for reading client dynamic registrations which may be ommitted by the
 /// client.
@@ -13,7 +14,7 @@
   /// All dynamic registrations supported by the Dart LSP server.
   ///
   /// Anything listed here and supported by the client will not send a static
-  /// registration but intead dynamically register (usually only for a subset of
+  /// registration but instead dynamically register (usually only for a subset of
   /// files such as for .dart/pubspec.yaml/etc).
   ///
   /// When adding new capabilities that will be registered dynamically, the
@@ -35,6 +36,12 @@
     Method.textDocument_codeAction,
     Method.textDocument_rename,
     Method.textDocument_foldingRange,
+    // workspace.fileOperations covers all file operation methods but we only
+    // support this one.
+    Method.workspace_willRenameFiles,
+    // Sematic tokens are all registered under a single "method" as the
+    // actual methods are controlled by the server capabilities.
+    CustomMethods.semanticTokenDynamicRegistration,
   ];
   final ClientCapabilities _capabilities;
 
@@ -60,6 +67,9 @@
   bool get documentSymbol =>
       _capabilities.textDocument?.documentSymbol?.dynamicRegistration ?? false;
 
+  bool get fileOperations =>
+      _capabilities.workspace?.fileOperations?.dynamicRegistration ?? false;
+
   bool get folding =>
       _capabilities.textDocument?.foldingRange?.dynamicRegistration ?? false;
 
@@ -81,6 +91,9 @@
   bool get rename =>
       _capabilities.textDocument?.rename?.dynamicRegistration ?? false;
 
+  bool get semanticTokens =>
+      _capabilities.textDocument?.semanticTokens?.dynamicRegistration ?? false;
+
   bool get signatureHelp =>
       _capabilities.textDocument?.signatureHelp?.dynamicRegistration ?? false;
 
@@ -93,6 +106,19 @@
 }
 
 class ServerCapabilitiesComputer {
+  static final fileOperationRegistrationOptions =
+      FileOperationRegistrationOptions(
+    filters: [
+      FileOperationFilter(
+        scheme: 'file',
+        pattern: FileOperationPattern(
+          glob: '**/*.dart',
+          matches: FileOperationPatternKind.file,
+        ),
+      )
+    ],
+  );
+
   final LspAnalysisServer _server;
 
   /// Map from method name to current registration data.
@@ -124,7 +150,8 @@
     return ServerCapabilities(
       textDocumentSync: dynamicRegistrations.textSync
           ? null
-          : Either2<TextDocumentSyncOptions, num>.t1(TextDocumentSyncOptions(
+          : Either2<TextDocumentSyncOptions, TextDocumentSyncKind>.t1(
+              TextDocumentSyncOptions(
               // The open/close and sync kind flags are registered dynamically if the
               // client supports them, so these static registrations are based on whether
               // the client supports dynamic registration.
@@ -206,16 +233,34 @@
               FoldingRangeRegistrationOptions>.t1(
               true,
             ),
+      semanticTokensProvider: dynamicRegistrations.semanticTokens
+          ? null
+          : Either2<SemanticTokensOptions,
+              SemanticTokensRegistrationOptions>.t1(
+              SemanticTokensOptions(
+                legend: semanticTokenLegend.lspLegend,
+                full: Either2<bool, SemanticTokensOptionsFull>.t2(
+                  SemanticTokensOptionsFull(delta: false),
+                ),
+                range: Either2<bool, SemanticTokensOptionsRange>.t1(true),
+              ),
+            ),
       executeCommandProvider: ExecuteCommandOptions(
         commands: Commands.serverSupportedCommands,
         workDoneProgress: true,
       ),
       workspaceSymbolProvider: Either2<bool, WorkspaceSymbolOptions>.t1(true),
       workspace: ServerCapabilitiesWorkspace(
-          workspaceFolders: WorkspaceFoldersServerCapabilities(
-        supported: true,
-        changeNotifications: Either2<String, bool>.t2(true),
-      )),
+        workspaceFolders: WorkspaceFoldersServerCapabilities(
+          supported: true,
+          changeNotifications: Either2<String, bool>.t2(true),
+        ),
+        fileOperations: dynamicRegistrations.fileOperations
+            ? null
+            : ServerCapabilitiesFileOperations(
+                willRename: fileOperationRegistrationOptions,
+              ),
+      ),
     );
   }
 
@@ -393,9 +438,26 @@
       TextDocumentRegistrationOptions(documentSelector: fullySupportedTypes),
     );
     register(
+      dynamicRegistrations.fileOperations,
+      Method.workspace_willRenameFiles,
+      fileOperationRegistrationOptions,
+    );
+    register(
       dynamicRegistrations.didChangeConfiguration,
       Method.workspace_didChangeConfiguration,
     );
+    register(
+      dynamicRegistrations.semanticTokens,
+      CustomMethods.semanticTokenDynamicRegistration,
+      SemanticTokensRegistrationOptions(
+        documentSelector: fullySupportedTypes,
+        legend: semanticTokenLegend.lspLegend,
+        full: Either2<bool, SemanticTokensOptionsFull>.t2(
+          SemanticTokensOptionsFull(delta: false),
+        ),
+        range: Either2<bool, SemanticTokensOptionsRange>.t1(true),
+      ),
+    );
 
     await _applyRegistrations(registrations);
   }
diff --git a/pkg/analysis_server/lib/src/lsp/source_edits.dart b/pkg/analysis_server/lib/src/lsp/source_edits.dart
index b98a101..0307417 100644
--- a/pkg/analysis_server/lib/src/lsp/source_edits.dart
+++ b/pkg/analysis_server/lib/src/lsp/source_edits.dart
@@ -302,7 +302,7 @@
 /// Helper class that bundles up all information required when converting server
 /// SourceEdits into LSP-compatible WorkspaceEdits.
 class FileEditInformation {
-  final VersionedTextDocumentIdentifier doc;
+  final OptionalVersionedTextDocumentIdentifier doc;
   final LineInfo lineInfo;
   final List<server.SourceEdit> edits;
 
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index ba01e37..0ad8a15 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -57,9 +57,14 @@
     return type != null
         ? type.getDisplayString(withNullability: false)
         : 'dynamic';
-  } else if (element is engine.FunctionTypeAliasElement) {
-    var returnType = element.function.returnType;
-    return returnType.getDisplayString(withNullability: false);
+  } else if (element is engine.TypeAliasElement) {
+    var aliasedElement = element.aliasedElement;
+    if (aliasedElement is engine.GenericFunctionTypeElement) {
+      var returnType = aliasedElement.returnType;
+      return returnType.getDisplayString(withNullability: false);
+    } else {
+      return null;
+    }
   } else {
     return null;
   }
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 183c669..d7efddf 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -98,6 +98,11 @@
   /// The path to the data cache.
   static const String CACHE_FOLDER = 'cache';
 
+  /// The name of the flag specifying the server protocol to use.
+  static const String SERVER_PROTOCOL = 'protocol';
+  static const String PROTOCOL_ANALYZER = 'analyzer';
+  static const String PROTOCOL_LSP = 'lsp';
+
   /// The name of the flag to use the Language Server Protocol (LSP).
   static const String USE_LSP = 'lsp';
 
@@ -124,17 +129,26 @@
   /// If [sendPort] is not null, assumes this is launched in an isolate and will
   /// connect to the original isolate via an [IsolateChannel].
   @override
-  void start(List<String> arguments, [SendPort sendPort]) {
-    var parser = _createArgParser();
+  void start(
+    List<String> arguments, {
+    SendPort sendPort,
+    bool defaultToLsp = false,
+  }) {
+    var parser = createArgParser(defaultToLsp: defaultToLsp);
     var results = parser.parse(arguments);
 
     var analysisServerOptions = AnalysisServerOptions();
     analysisServerOptions.newAnalysisDriverLog =
         results[ANALYSIS_DRIVER_LOG] ?? results[ANALYSIS_DRIVER_LOG_ALIAS];
     analysisServerOptions.clientId = results[CLIENT_ID];
-    analysisServerOptions.useLanguageServerProtocol = results[USE_LSP];
-    // For clients that don't supply their own identifier, use a default based on
-    // whether the server will run in LSP mode or not.
+    if (results.wasParsed(USE_LSP)) {
+      analysisServerOptions.useLanguageServerProtocol = results[USE_LSP];
+    } else {
+      analysisServerOptions.useLanguageServerProtocol =
+          results[SERVER_PROTOCOL] == PROTOCOL_LSP;
+    }
+    // For clients that don't supply their own identifier, use a default based
+    // on whether the server will run in LSP mode or not.
     analysisServerOptions.clientId ??=
         analysisServerOptions.useLanguageServerProtocol
             ? 'unknown.client.lsp'
@@ -478,11 +492,95 @@
     return runZoned(callback, zoneSpecification: zoneSpecification);
   }
 
+  DartSdk _createDefaultSdk(String defaultSdkPath) {
+    var resourceProvider = PhysicalResourceProvider.INSTANCE;
+    return FolderBasedDartSdk(
+      resourceProvider,
+      resourceProvider.getFolder(defaultSdkPath),
+    );
+  }
+
+  /// Constructs a uuid combining the current date and a random integer.
+  String _generateUuidString() {
+    var millisecondsSinceEpoch = DateTime.now().millisecondsSinceEpoch;
+    var random = Random().nextInt(0x3fffffff);
+    return '$millisecondsSinceEpoch$random';
+  }
+
+  String _getSdkPath(ArgResults args) {
+    if (args[DART_SDK] != null) {
+      return args[DART_SDK];
+    } else if (args[DART_SDK_ALIAS] != null) {
+      return args[DART_SDK_ALIAS];
+    } else {
+      return getSdkPath();
+    }
+  }
+
+  /// Print information about how to use the server.
+  void _printUsage(
+    ArgParser parser,
+    telemetry.Analytics analytics, {
+    bool fromHelp = false,
+  }) {
+    print('Usage: $BINARY_NAME [flags]');
+    print('');
+    print('Supported flags are:');
+    print(parser.usage);
+
+    if (telemetry.SHOW_ANALYTICS_UI) {
+      // Print analytics status and information.
+      if (fromHelp) {
+        print('');
+        print(telemetry.analyticsNotice);
+      }
+      print('');
+      print(telemetry.createAnalyticsStatusMessage(analytics.enabled,
+          command: ANALYTICS_FLAG));
+    }
+  }
+
+  /// Read the UUID from disk, generating and storing a new one if necessary.
+  String _readUuid(InstrumentationService service) {
+    final instrumentationLocation =
+        PhysicalResourceProvider.INSTANCE.getStateLocation('.instrumentation');
+    if (instrumentationLocation == null) {
+      return _generateUuidString();
+    }
+    var uuidFile = File(instrumentationLocation.getChild('uuid.txt').path);
+    try {
+      if (uuidFile.existsSync()) {
+        var uuid = uuidFile.readAsStringSync();
+        if (uuid != null && uuid.length > 5) {
+          return uuid;
+        }
+      }
+    } catch (exception, stackTrace) {
+      service.logException(exception, stackTrace);
+    }
+    var uuid = _generateUuidString();
+    try {
+      uuidFile.parent.createSync(recursive: true);
+      uuidFile.writeAsStringSync(uuid);
+    } catch (exception, stackTrace) {
+      service.logException(exception, stackTrace);
+      // Slightly alter the uuid to indicate it was not persisted
+      uuid = 'temp-$uuid';
+    }
+    return uuid;
+  }
+
   /// Create and return the parser used to parse the command-line arguments.
-  ArgParser _createArgParser() {
-    var parser = ArgParser();
-    parser.addFlag(HELP_OPTION,
-        abbr: 'h', negatable: false, help: 'Print this usage information.');
+  static ArgParser createArgParser({
+    int usageLineLength,
+    bool includeHelpFlag = true,
+    bool defaultToLsp = false,
+  }) {
+    var parser = ArgParser(usageLineLength: usageLineLength);
+    if (includeHelpFlag) {
+      parser.addFlag(HELP_OPTION,
+          abbr: 'h', negatable: false, help: 'Print this usage information.');
+    }
     parser.addOption(CLIENT_ID,
         valueHelp: 'name',
         help: 'An identifier for the analysis server client.');
@@ -495,10 +593,28 @@
     parser.addOption(CACHE_FOLDER,
         valueHelp: 'path',
         help: 'Override the location of the analysis server\'s cache.');
+
+    parser.addOption(
+      SERVER_PROTOCOL,
+      defaultsTo: defaultToLsp ? PROTOCOL_LSP : PROTOCOL_ANALYZER,
+      valueHelp: 'protocol',
+      allowed: [PROTOCOL_LSP, PROTOCOL_ANALYZER],
+      allowedHelp: {
+        PROTOCOL_LSP: 'The Language Server Protocol '
+            '(https://microsoft.github.io/language-server-protocol)',
+        PROTOCOL_ANALYZER: 'Dart\'s analysis server protocol '
+            '(https://dart.dev/go/analysis-server-protocol)',
+      },
+      help:
+          'Specify the protocol to use to communicate with the analysis server.',
+    );
+    // This option is hidden but still accepted; it's effectively translated to
+    // the 'protocol' option above.
     parser.addFlag(USE_LSP,
         defaultsTo: false,
         negatable: false,
-        help: 'Whether to use the Language Server Protocol (LSP).');
+        help: 'Whether to use the Language Server Protocol (LSP).',
+        hide: true);
 
     parser.addSeparator('Server diagnostics:');
 
@@ -584,84 +700,6 @@
     return parser;
   }
 
-  DartSdk _createDefaultSdk(String defaultSdkPath) {
-    var resourceProvider = PhysicalResourceProvider.INSTANCE;
-    return FolderBasedDartSdk(
-      resourceProvider,
-      resourceProvider.getFolder(defaultSdkPath),
-    );
-  }
-
-  /// Constructs a uuid combining the current date and a random integer.
-  String _generateUuidString() {
-    var millisecondsSinceEpoch = DateTime.now().millisecondsSinceEpoch;
-    var random = Random().nextInt(0x3fffffff);
-    return '$millisecondsSinceEpoch$random';
-  }
-
-  String _getSdkPath(ArgResults args) {
-    if (args[DART_SDK] != null) {
-      return args[DART_SDK];
-    } else if (args[DART_SDK_ALIAS] != null) {
-      return args[DART_SDK_ALIAS];
-    } else {
-      return getSdkPath();
-    }
-  }
-
-  /// Print information about how to use the server.
-  void _printUsage(
-    ArgParser parser,
-    telemetry.Analytics analytics, {
-    bool fromHelp = false,
-  }) {
-    print('Usage: $BINARY_NAME [flags]');
-    print('');
-    print('Supported flags are:');
-    print(parser.usage);
-
-    if (telemetry.SHOW_ANALYTICS_UI) {
-      // Print analytics status and information.
-      if (fromHelp) {
-        print('');
-        print(telemetry.analyticsNotice);
-      }
-      print('');
-      print(telemetry.createAnalyticsStatusMessage(analytics.enabled,
-          command: ANALYTICS_FLAG));
-    }
-  }
-
-  /// Read the UUID from disk, generating and storing a new one if necessary.
-  String _readUuid(InstrumentationService service) {
-    final instrumentationLocation =
-        PhysicalResourceProvider.INSTANCE.getStateLocation('.instrumentation');
-    if (instrumentationLocation == null) {
-      return _generateUuidString();
-    }
-    var uuidFile = File(instrumentationLocation.getChild('uuid.txt').path);
-    try {
-      if (uuidFile.existsSync()) {
-        var uuid = uuidFile.readAsStringSync();
-        if (uuid != null && uuid.length > 5) {
-          return uuid;
-        }
-      }
-    } catch (exception, stackTrace) {
-      service.logException(exception, stackTrace);
-    }
-    var uuid = _generateUuidString();
-    try {
-      uuidFile.parent.createSync(recursive: true);
-      uuidFile.writeAsStringSync(uuid);
-    } catch (exception, stackTrace) {
-      service.logException(exception, stackTrace);
-      // Slightly alter the uuid to indicate it was not persisted
-      uuid = 'temp-$uuid';
-    }
-    return uuid;
-  }
-
   /// Perform log files rolling.
   ///
   /// Rename existing files with names `[path].(x)` to `[path].(x+1)`.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 01b7721..ecaa1a8 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -153,8 +153,11 @@
 
     var containingNode = request.target.containingNode;
     var entity = request.target.entity;
-    var token =
-        entity is AstNode ? entity.endToken : entity is Token ? entity : null;
+    var token = entity is AstNode
+        ? entity.endToken
+        : entity is Token
+            ? entity
+            : null;
     return (token != containingNode?.endToken) &&
         token?.next?.type == TokenType.COMMA &&
         !token.next.isSynthetic;
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 b27b353..373bcee 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
@@ -42,7 +42,6 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/util/performance/operation_performance.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking_internal.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking_internal.dart
index 5fa273e..0c53e90 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking_internal.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking_internal.dart
@@ -8,7 +8,6 @@
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 
 /// Fuzzy matching between static analysis and model-predicted lexemes
 /// that considers pairs like "main" and "main()" to be equal.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index 512f787..5d17ae8 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/generic_inferrer.dart'
     show GenericInferrer;
 import 'package:analyzer/src/dart/element/type_algebra.dart';
@@ -45,8 +44,7 @@
         if (extension != null) {
           var extendedType = extension.extendedType.type;
           if (extendedType is InterfaceType) {
-            var types = <InterfaceType>[];
-            ClassElementImpl.collectAllSupertypes(types, extendedType, null);
+            var types = [extendedType, ...extendedType.allSupertypes];
             for (var type in types) {
               var inheritanceDistance = memberBuilder.request.featureComputer
                   .inheritanceDistanceFeature(
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 127d348..0cb3b8b 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
@@ -9,8 +9,6 @@
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/protocol_server.dart'
     hide Element, ElementKind;
-import 'package:analysis_server/src/protocol_server.dart'
-    show CompletionSuggestion;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
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 e829ce1..3a3c9ae 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -92,16 +92,16 @@
   }
 
   for (var param in namedParams) {
-    if (param.hasRequired) {
+    if (param.hasRequired || param.isRequiredNamed) {
       if (sb.isNotEmpty) {
         sb.write(', ');
       }
       var name = param.name;
       sb.write('$name: ');
       offset = sb.length;
-      var defaultValue = _getDefaultValue(param);
-      sb.write(defaultValue);
-      ranges.addAll([offset, defaultValue.length]);
+      // TODO(pq): fix to use getDefaultStringParameterValue()
+      sb.write(name);
+      ranges.addAll([offset, name.length]);
     }
   }
 
@@ -250,8 +250,13 @@
       return null;
     }
     type = element.returnType;
-  } else if (element is FunctionTypeAliasElement) {
-    type = element.function.returnType;
+  } else if (element is TypeAliasElement) {
+    var aliasedElement = element.aliasedElement;
+    if (aliasedElement is GenericFunctionTypeElement) {
+      type = aliasedElement.returnType;
+    } else {
+      return null;
+    }
   } else if (element is VariableElement) {
     type = element.type;
   } else {
@@ -275,9 +280,6 @@
   return type.getDisplayString(withNullability: false);
 }
 
-/// TODO(pq): fix to use getDefaultStringParameterValue()
-String _getDefaultValue(ParameterElement param) => 'null';
-
 /// A tuple of text to insert and an (optional) location for the cursor.
 class DefaultArgument {
   /// The text to insert.
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 2984122..2ff7dae 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
@@ -14,7 +14,6 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/error.dart' as engine;
 import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/java_core.dart';
diff --git a/pkg/analysis_server/lib/src/services/completion/token_details/token_detail_builder.dart b/pkg/analysis_server/lib/src/services/completion/token_details/token_detail_builder.dart
deleted file mode 100644
index 44c3ad9..0000000
--- a/pkg/analysis_server/lib/src/services/completion/token_details/token_detail_builder.dart
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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:analysis_server/protocol/protocol_generated.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-
-/// An object used to build the details for each token in the code being
-/// analyzed.
-class TokenDetailBuilder {
-  /// The list of details that were built.
-  List<TokenDetails> details = [];
-
-  /// Initialize a newly created builder.
-  TokenDetailBuilder();
-
-  /// Visit a [node] in the AST structure to build details for all of the tokens
-  /// contained by that node.
-  void visitNode(AstNode node) {
-    for (var entity in node.childEntities) {
-      if (entity is Token) {
-        _createDetails(entity, null, null);
-      } else if (entity is SimpleIdentifier) {
-        String type;
-        var typeNameNode = _getTypeName(entity);
-        if (typeNameNode != null) {
-          var typeStr = _typeStr(typeNameNode.type);
-          type = 'dart:core;Type<$typeStr>';
-        } else if (entity.staticElement is ClassElement) {
-          type = 'Type';
-        } else if (entity.inDeclarationContext()) {
-          var element = entity.staticElement;
-          if (element is FunctionElement) {
-            type = _typeStr(element.type);
-          } else if (element is MethodElement) {
-            type = _typeStr(element.type);
-          } else if (element is VariableElement) {
-            type = _typeStr(element.type);
-          }
-        } else {
-          type = _typeStr(entity.staticType);
-        }
-        var kinds = <String>[];
-        if (entity.inDeclarationContext()) {
-          kinds.add('declaration');
-        } else {
-          kinds.add('reference');
-        }
-        _createDetails(entity.token, type, kinds);
-      } else if (entity is BooleanLiteral) {
-        _createDetails(entity.literal, _typeStr(entity.staticType), null);
-      } else if (entity is DoubleLiteral) {
-        _createDetails(entity.literal, _typeStr(entity.staticType), null);
-      } else if (entity is IntegerLiteral) {
-        _createDetails(entity.literal, _typeStr(entity.staticType), null);
-      } else if (entity is SimpleStringLiteral) {
-        _createDetails(entity.literal, _typeStr(entity.staticType), null);
-      } else if (entity is Comment) {
-        // Ignore comments and the references within them.
-      } else if (entity is AstNode) {
-        visitNode(entity);
-      }
-    }
-  }
-
-  /// Create the details for a single [token], using the given list of [kinds].
-  void _createDetails(Token token, String type, List<String> kinds) {
-    details.add(TokenDetails(token.lexeme, token.offset,
-        type: type, validElementKinds: kinds));
-  }
-
-  /// Return the [TypeName] with the [identifier].
-  TypeName _getTypeName(SimpleIdentifier identifier) {
-    var parent = identifier.parent;
-    if (parent is TypeName && identifier == parent.name) {
-      return parent;
-    } else if (parent is PrefixedIdentifier &&
-        parent.identifier == identifier) {
-      var parent2 = parent.parent;
-      if (parent2 is TypeName && parent == parent2.name) {
-        return parent2;
-      }
-    }
-    return null;
-  }
-
-  /// Return a unique identifier for the [type].
-  String _typeStr(DartType type) {
-    var buffer = StringBuffer();
-    _writeType(buffer, type);
-    return buffer.toString();
-  }
-
-  /// Return a unique identifier for the type of the given [expression].
-  void _writeType(StringBuffer buffer, DartType type) {
-    if (type == null) {
-      // This should never happen if the AST has been resolved.
-      buffer.write('dynamic');
-    } else if (type is FunctionType) {
-      _writeType(buffer, type.returnType);
-      buffer.write(' Function(');
-      var first = true;
-      for (var parameter in type.parameters) {
-        if (first) {
-          first = false;
-        } else {
-          buffer.write(', ');
-        }
-        _writeType(buffer, parameter.type);
-      }
-      buffer.write(')');
-    } else if (type is InterfaceType) {
-      Element element = type.element;
-      if (element == null || element.isSynthetic) {
-        assert(false, 'untested branch may print nullable types wrong');
-        // TODO: test this, use the the library's nullability (not tracked yet).
-        buffer.write(type.getDisplayString(withNullability: false));
-      } else {
-//        String uri = element.library.source.uri.toString();
-        var name = element.name;
-        if (element is ClassMemberElement) {
-          var className = element.enclosingElement.name;
-          // TODO(brianwilkerson) Figure out why the uri is a file: URI when it
-          //  ought to be a package: URI and restore the code below to include
-          //  the URI in the string.
-//          buffer.write('$uri;$className;$name');
-          buffer.write('$className;$name');
-        } else {
-//          buffer.write('$uri;$name');
-          buffer.write('$name');
-        }
-      }
-    } else {
-      // Handle `void` and `dynamic`. Nullability doesn't affect this.
-      assert(type.getDisplayString(withNullability: false) ==
-          type.getDisplayString(withNullability: true));
-      buffer.write(type.getDisplayString(withNullability: false));
-    }
-  }
-}
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 cc96113..31c1975 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
@@ -59,11 +59,10 @@
   @override
   Iterable<CompletionSuggestion> suggestions(
       YamlCompletionRequest request) sync* {
-    // This currently assumes that all paths will be posix paths, but we might
-    // want to support platform-specific paths at some point, in which case we
-    // should add a flag to the constructor and use that to choose between the
-    // hard-coded `path.posix` and `provider.pathContext`;
-    var provider = request.resourceProvider;
+    //
+    // This currently assumes that all of the paths in the assets section will
+    // be posix paths.
+    //
     var context = path.posix;
     var separator = context.separator;
     var precedingText = request.precedingText;
@@ -80,6 +79,16 @@
       parentDirectory = parentDirectory.substring(
           0, parentDirectory.length - separator.length);
     }
+    //
+    // Convert from posix to the platform context.
+    //
+    var provider = request.resourceProvider;
+    context = provider.pathContext;
+    parentDirectory = context.joinAll(path.posix.split(parentDirectory));
+    //
+    // Resolve the relative path and access the disk to see what child entities
+    // exist within the [parentDirectory] that can be suggested.
+    //
     if (context.isRelative(parentDirectory)) {
       parentDirectory =
           context.join(context.dirname(request.filePath), parentDirectory);
@@ -90,13 +99,8 @@
       try {
         for (var child in dir.getChildren()) {
           var name = child.shortName;
-          if (child is Folder) {
-            if (!name.startsWith('.')) {
-              yield identifier(name);
-            }
-          } else if (child is File) {
-            yield identifier(name);
-          }
+          var relevance = name.startsWith('.') ? 500 : 1000;
+          yield identifier(name, relevance: relevance);
         }
       } on FileSystemException {
         // Guard against I/O exceptions.
@@ -171,14 +175,9 @@
   const Producer();
 
   /// A utility method used to create a suggestion for the [identifier].
-  CompletionSuggestion identifier(String identifier) => CompletionSuggestion(
-      CompletionSuggestionKind.IDENTIFIER,
-      1000,
-      identifier,
-      identifier.length,
-      0,
-      false,
-      false);
+  CompletionSuggestion identifier(String identifier, {int relevance = 1000}) =>
+      CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, relevance,
+          identifier, identifier.length, 0, false, false);
 
   /// Return the completion suggestions appropriate to this location.
   Iterable<CompletionSuggestion> suggestions(YamlCompletionRequest request);
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 04dc79d..2929cc2 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -72,9 +72,7 @@
   static const CONVERT_INTO_IS_NOT =
       AssistKind('dart.assist.convert.isNot', 30, 'Convert to is!');
   static const CONVERT_INTO_IS_NOT_EMPTY = AssistKind(
-      'dart.assist.convert.isNotEmpty', 30, "Convert to 'isNotEmpty'",
-      // todo (pq): unify w/ fix
-      associatedErrorCodes: <String>['prefer_is_not_empty']);
+      'dart.assist.convert.isNotEmpty', 30, "Convert to 'isNotEmpty'");
   static const CONVERT_PART_OF_TO_URI = AssistKind(
       'dart.assist.convert.partOfToPartUri', 30, 'Convert to use a URI');
   static const CONVERT_TO_DOUBLE_QUOTED_STRING = AssistKind(
@@ -92,11 +90,9 @@
   static const CONVERT_TO_INT_LITERAL = AssistKind(
       'dart.assist.convert.toIntLiteral', 30, 'Convert to an int literal');
   static const CONVERT_TO_LIST_LITERAL = AssistKind(
-      'dart.assist.convert.toListLiteral', 30, 'Convert to list literal',
-      associatedErrorCodes: <String>['prefer_collection_literals']);
+      'dart.assist.convert.toListLiteral', 30, 'Convert to list literal');
   static const CONVERT_TO_MAP_LITERAL = AssistKind(
-      'dart.assist.convert.toMapLiteral', 30, 'Convert to map literal',
-      associatedErrorCodes: <String>['prefer_collection_literals']);
+      'dart.assist.convert.toMapLiteral', 30, 'Convert to map literal');
   static const CONVERT_TO_MULTILINE_STRING = AssistKind(
       'dart.assist.convert.toMultilineString',
       30,
@@ -116,8 +112,7 @@
       30,
       'Convert to a relative import');
   static const CONVERT_TO_SET_LITERAL = AssistKind(
-      'dart.assist.convert.toSetLiteral', 30, 'Convert to set literal',
-      associatedErrorCodes: <String>['prefer_collection_literals']);
+      'dart.assist.convert.toSetLiteral', 30, 'Convert to set literal');
   static const CONVERT_TO_SINGLE_QUOTED_STRING = AssistKind(
       'dart.assist.convert.toSingleQuotedString',
       30,
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 0dae89c..a0dbd4c 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
@@ -12,9 +12,11 @@
 import 'package:analysis_server/src/services/correction/dart/add_const.dart';
 import 'package:analysis_server/src/services/correction/dart/add_diagnostic_property_reference.dart';
 import 'package:analysis_server/src/services/correction/dart/add_override.dart';
+import 'package:analysis_server/src/services/correction/dart/add_required.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_add_all_to_spread.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_conditional_expression_to_if_element.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_documentation_into_line.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_into_is_not.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_map_from_iterable_to_for_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_quotes.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_contains.dart';
@@ -24,12 +26,14 @@
 import 'package:analysis_server/src/services/correction/dart/convert_to_list_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_package_import.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_where_type.dart';
 import 'package:analysis_server/src/services/correction/dart/create_method.dart';
 import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
 import 'package:analysis_server/src/services/correction/dart/inline_invocation.dart';
+import 'package:analysis_server/src/services/correction/dart/inline_typedef.dart';
 import 'package:analysis_server/src/services/correction/dart/make_final.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_argument.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_await.dart';
@@ -39,6 +43,7 @@
 import 'package:analysis_server/src/services/correction/dart/remove_empty_constructor_body.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_empty_else.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_empty_statement.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_if_null_operator.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_initializer.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_interpolation_braces.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_method_declaration.dart';
@@ -47,6 +52,7 @@
 import 'package:analysis_server/src/services/correction/dart/remove_this_expression.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_type_annotation.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_new.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_string_interpolation.dart';
 import 'package:analysis_server/src/services/correction/dart/rename_to_camel_case.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_cascade_with_dot.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_colon_with_equals.dart';
@@ -61,12 +67,16 @@
 import 'package:analysis_server/src/services/correction/dart/use_is_not_empty.dart';
 import 'package:analysis_server/src/services/correction/dart/use_rethrow.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set_parser.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analyzer/dart/analysis/analysis_context.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/service.dart';
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -77,7 +87,15 @@
 import 'package:analyzer_plugin/utilities/change_builder/conflicting_edit_exception.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 
-/// A fix producer that produces changes to fix multiple diagnostics.
+/// A fix producer that produces changes that will fix multiple diagnostics in
+/// one or more files.
+///
+/// Each diagnostic should have a single fix (correction producer) associated
+/// with it except in cases where at most one of the given producers will ever
+/// produce a fix.
+///
+/// The correction producers that are associated with the diagnostics should not
+/// produce changes that alter the semantics of the code.
 class BulkFixProcessor {
   /// A map from the name of a lint rule to a list of generators used to create
   /// the correction producer used to build a fix for that diagnostic. The
@@ -88,6 +106,9 @@
   /// one will produce a change for a given fix. If more than one change is
   /// produced the result will almost certainly be invalid code.
   static const Map<String, List<ProducerGenerator>> lintProducerMap = {
+    LintNames.always_require_non_null_named_parameters: [
+      AddRequired.newInstance,
+    ],
     LintNames.annotate_overrides: [
       AddOverride.newInstance,
     ],
@@ -100,9 +121,15 @@
     LintNames.avoid_init_to_null: [
       RemoveInitializer.newInstance,
     ],
+    LintNames.avoid_private_typedef_functions: [
+      InlineTypedef.newInstance,
+    ],
     LintNames.avoid_redundant_argument_values: [
       RemoveArgument.newInstance,
     ],
+    LintNames.avoid_relative_lib_imports: [
+      ConvertToPackageImport.newInstance,
+    ],
     LintNames.avoid_return_types_on_setters: [
       RemoveTypeAnnotation.newInstance,
     ],
@@ -202,7 +229,10 @@
       ReplaceWithIsEmpty.newInstance,
     ],
     LintNames.prefer_is_not_empty: [
-      UesIsNotEmpty.newInstance,
+      UseIsNotEmpty.newInstance,
+    ],
+    LintNames.prefer_is_not_operator: [
+      ConvertIntoIsNot.newInstance,
     ],
     LintNames.prefer_iterable_whereType: [
       ConvertToWhereType.newInstance,
@@ -243,12 +273,21 @@
     LintNames.unnecessary_new: [
       RemoveUnnecessaryNew.newInstance,
     ],
+    LintNames.unnecessary_null_in_if_null_operators: [
+      RemoveIfNullOperator.newInstance,
+    ],
     LintNames.unnecessary_overrides: [
       RemoveMethodDeclaration.newInstance,
     ],
+    LintNames.unnecessary_string_interpolations: [
+      RemoveUnnecessaryStringInterpolation.newInstance,
+    ],
     LintNames.unnecessary_this: [
       RemoveThisExpression.newInstance,
     ],
+    LintNames.use_function_type_syntax_for_parameters: [
+      ConvertToGenericFunctionSyntax.newInstance,
+    ],
     LintNames.use_rethrow_when_possible: [
       UseRethrow.newInstance,
     ],
@@ -327,9 +366,15 @@
     HintCode.DEPRECATED_MEMBER_USE: [
       DataDriven.newInstance,
     ],
+    HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE: [
+      DataDriven.newInstance,
+    ],
     HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE: [
       DataDriven.newInstance,
     ],
+    HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE: [
+      DataDriven.newInstance,
+    ],
     HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD: [
       DataDriven.newInstance,
     ],
@@ -350,6 +395,10 @@
   /// will be produced.
   final DartChangeWorkspace workspace;
 
+  /// A flag indicating whether configuration files should be used to override
+  /// the transforms.
+  final bool useConfigFiles;
+
   /// The change builder used to build the changes required to fix the
   /// diagnostics.
   ChangeBuilder builder;
@@ -359,8 +408,10 @@
 
   /// Initialize a newly created processor to create fixes for diagnostics in
   /// libraries in the [workspace].
-  BulkFixProcessor(this.instrumentationService, this.workspace)
-      : builder = ChangeBuilder(workspace: workspace);
+  BulkFixProcessor(this.instrumentationService, this.workspace,
+      {bool useConfigFiles})
+      : useConfigFiles = useConfigFiles ?? false,
+        builder = ChangeBuilder(workspace: workspace);
 
   List<BulkFix> get fixDetails {
     var details = <BulkFix>[];
@@ -414,11 +465,12 @@
       (name) => [],
     );
 
+    var overrideSet = _readOverrideSet(unit);
     for (var error in errors) {
       final processor = ErrorProcessor.getProcessor(analysisOptions, error);
       // Only fix errors not filtered out in analysis options.
       if (processor == null || processor.severity != null) {
-        await _fixSingleError(fixContext, unit, error);
+        await _fixSingleError(fixContext, unit, error, overrideSet);
       }
     }
 
@@ -492,11 +544,12 @@
         null,
         (name) => [],
       );
+      var overrideSet = _readOverrideSet(unitResult);
       for (var error in unitResult.errors) {
         var processor = ErrorProcessor.getProcessor(analysisOptions, error);
         // Only fix errors not filtered out in analysis options.
         if (processor == null || processor.severity != null) {
-          await _fixSingleError(fixContext, unitResult, error);
+          await _fixSingleError(fixContext, unitResult, error, overrideSet);
         }
       }
     }
@@ -505,12 +558,16 @@
   /// Use the change [builder] and the [fixContext] to create a fix for the
   /// given [diagnostic] in the compilation unit associated with the analysis
   /// [result].
-  Future<void> _fixSingleError(DartFixContext fixContext,
-      ResolvedUnitResult result, AnalysisError diagnostic) async {
+  Future<void> _fixSingleError(
+      DartFixContext fixContext,
+      ResolvedUnitResult result,
+      AnalysisError diagnostic,
+      TransformOverrideSet overrideSet) async {
     var context = CorrectionProducerContext(
       applyingBulkFixes: true,
       dartFixContext: fixContext,
       diagnostic: diagnostic,
+      overrideSet: overrideSet,
       resolvedResult: result,
       selectionOffset: diagnostic.offset,
       selectionLength: diagnostic.length,
@@ -585,6 +642,28 @@
           s);
     }
   }
+
+  /// Return the override set corresponding to the given [result], or `null` if
+  /// there is no corresponding configuration file or the file content isn't a
+  /// valid override set.
+  TransformOverrideSet _readOverrideSet(ResolvedUnitResult result) {
+    if (useConfigFiles) {
+      var provider = result.session.resourceProvider;
+      var context = provider.pathContext;
+      var dartFileName = result.path;
+      var configFileName = '${context.withoutExtension(dartFileName)}.config';
+      var configFile = provider.getFile(configFileName);
+      try {
+        var content = configFile.readAsStringSync();
+        var parser = TransformOverrideSetParser(ErrorReporter(
+            AnalysisErrorListener.NULL_LISTENER, configFile.createSource()));
+        return parser.parse(content);
+      } on FileSystemException {
+        // Fall through to return null.
+      }
+    }
+    return null;
+  }
 }
 
 /// Maps changes to library paths.
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 66bd219..559d342 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
@@ -7,12 +7,12 @@
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
 import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/utilities/flutter.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/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
@@ -233,6 +233,8 @@
 
   final Diagnostic diagnostic;
 
+  final TransformOverrideSet overrideSet;
+
   AstNode _node;
 
   CorrectionProducerContext({
@@ -241,6 +243,7 @@
     this.applyingBulkFixes = false,
     this.dartFixContext,
     this.diagnostic,
+    this.overrideSet,
     this.selectionOffset = -1,
     this.selectionLength = 0,
   })  : file = resolvedResult.path,
@@ -320,6 +323,7 @@
   /// Initialize a newly created producer.
   _AbstractCorrectionProducer();
 
+  /// Return `true` if the fixes are being built for the bulk-fix request.
   bool get applyingBulkFixes => _context.applyingBulkFixes;
 
   /// The most deeply nested node that completely covers the highlight region of
@@ -358,6 +362,10 @@
 
   AstNode get node => _context.node;
 
+  /// Return the set of overrides to be applied to the transform set when
+  /// running tests, or `null` if there are no overrides to apply.
+  TransformOverrideSet get overrideSet => _context.overrideSet;
+
   ResolvedUnitResult get resolvedResult => _context.resolvedResult;
 
   /// Return the resource provider used to access the file system.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
index 93c14bd..56791c0 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
@@ -6,6 +6,9 @@
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 
@@ -18,34 +21,68 @@
     if (!libraryElement.isNonNullableByDefault) {
       return;
     }
-    if (node is SimpleIdentifier &&
-        node.parent is VariableDeclaration &&
-        node.parent.parent is VariableDeclarationList) {
-      var list = node.parent.parent as VariableDeclarationList;
-      if (!list.isLate) {
-        if (list.type == null) {
-          var keyword = list.keyword;
-          if (keyword == null) {
-            await _insertAt(builder, list.variables[0].offset);
-            // TODO(brianwilkerson) Consider converting this into an assist and
-            //  expand it to support converting `var` to `late` as well as
-            //  working anywhere a non-late local variable or field is selected.
+    var node = this.node;
+    if (node is SimpleIdentifier) {
+      if (node.parent is VariableDeclaration &&
+          node.parent.parent is VariableDeclarationList) {
+        var list = node.parent.parent as VariableDeclarationList;
+        if (!list.isLate) {
+          if (list.type == null) {
+            var keyword = list.keyword;
+            if (keyword == null) {
+              await _insertAt(builder, list.variables[0].offset);
+              // TODO(brianwilkerson) Consider converting this into an assist and
+              //  expand it to support converting `var` to `late` as well as
+              //  working anywhere a non-late local variable or field is selected.
 //          } else if (keyword.type == Keyword.VAR) {
 //            builder.addFileEdit(file, (builder) {
 //              builder.addSimpleReplacement(range.token(keyword), 'late');
 //            });
-          } else if (keyword.type != Keyword.CONST) {
-            await _insertAt(builder, list.variables[0].offset);
+            } else if (keyword.type != Keyword.CONST) {
+              await _insertAt(builder, list.variables[0].offset);
+            }
+          } else {
+            var keyword = list.keyword;
+            if (keyword != null) {
+              await _insertAt(builder, keyword.offset);
+            } else {
+              var type = list.type;
+              if (type != null) {
+                await _insertAt(builder, type.offset);
+              }
+            }
           }
-        } else {
-          await _insertAt(builder, list.type.offset);
+        }
+      } else {
+        var getter = node.writeOrReadElement;
+        if (getter is PropertyAccessorElement &&
+            getter.isGetter &&
+            getter.isSynthetic &&
+            !getter.variable.isSynthetic &&
+            getter.variable.setter == null &&
+            getter.enclosingElement is ClassElement) {
+          var declarationResult =
+              await sessionHelper.getElementDeclaration(getter.variable);
+          var variable = declarationResult.node;
+          if (variable is VariableDeclaration &&
+              variable.parent is VariableDeclarationList &&
+              variable.parent.parent is FieldDeclaration) {
+            VariableDeclarationList declarationList = variable.parent;
+            var keywordToken = declarationList.keyword;
+            if (declarationList.variables.length == 1 &&
+                keywordToken.keyword == Keyword.FINAL) {
+              await _insertAt(builder, keywordToken.offset,
+                  source: declarationResult.element.source);
+            }
+          }
         }
       }
     }
   }
 
-  Future<void> _insertAt(ChangeBuilder builder, int offset) async {
-    await builder.addDartFileEdit(file, (builder) {
+  Future<void> _insertAt(ChangeBuilder builder, int offset,
+      {Source source}) async {
+    await builder.addDartFileEdit(source?.fullName ?? file, (builder) {
       builder.addSimpleInsertion(offset, 'late ');
     });
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_missing_parameter.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_missing_parameter.dart
index 5c29355..9b8f484 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_missing_parameter.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_missing_parameter.dart
@@ -12,10 +12,11 @@
 class AddMissingParameter extends MultiCorrectionProducer {
   @override
   Iterable<CorrectionProducer> get producers sync* {
-    if (node is! ArgumentList) {
+    // node is the unmatched argument.
+    if (node.parent is! ArgumentList) {
       return;
     }
-    var context = ExecutableParameters(sessionHelper, node.parent);
+    var context = ExecutableParameters(sessionHelper, node.parent.parent);
     if (context == null) {
       return;
     }
@@ -65,7 +66,8 @@
 
   Future<void> _addParameter(
       ChangeBuilder builder, int offset, String prefix, String suffix) async {
-    ArgumentList argumentList = node;
+    // node is the unmatched argument.
+    ArgumentList argumentList = node.parent;
     List<Expression> arguments = argumentList.arguments;
     var numRequired = context.required.length;
     if (numRequired >= arguments.length) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_null_check.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_null_check.dart
index 7fcb556..c297b3c 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_null_check.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_null_check.dart
@@ -41,11 +41,44 @@
       toType = parent.declaredElement.type;
     } else if (parent is ArgumentList) {
       toType = target.staticParameterElement.type;
+    } else if (parent is IndexExpression) {
+      toType = parent.realTarget.staticType;
+    } else if (parent is ForEachPartsWithDeclaration) {
+      toType =
+          typeProvider.iterableType2(parent.loopVariable.declaredElement.type);
+    } else if (parent is ForEachPartsWithIdentifier) {
+      toType = typeProvider.iterableType2(parent.identifier.staticType);
+    } else if (parent is SpreadElement) {
+      var literal = parent.thisOrAncestorOfType<TypedLiteral>();
+      if (literal is ListLiteral) {
+        toType = literal.staticType.asInstanceOf(typeProvider.iterableElement);
+      } else if (literal is SetOrMapLiteral) {
+        toType = literal.staticType.isDartCoreSet
+            ? literal.staticType.asInstanceOf(typeProvider.iterableElement)
+            : literal.staticType.asInstanceOf(typeProvider.mapElement);
+      }
+    } else if (parent is YieldStatement) {
+      var enclosingExecutable =
+          parent.thisOrAncestorOfType<FunctionBody>().parent;
+      if (enclosingExecutable is FunctionDeclaration) {
+        toType = enclosingExecutable.returnType?.type;
+      } else if (enclosingExecutable is MethodDeclaration) {
+        toType = enclosingExecutable.returnType?.type;
+      } else if (enclosingExecutable is FunctionExpression) {
+        toType = enclosingExecutable.declaredElement.returnType;
+      }
+    } else if ((parent is PrefixedIdentifier && target == parent.prefix) ||
+        (parent is PropertyAccess && target == parent.target) ||
+        (parent is MethodInvocation && target == parent.target) ||
+        (parent is FunctionExpressionInvocation && target == parent.function)) {
+      // No need to set the `toType` because there isn't any need for a type
+      // check.
     } else {
       return;
     }
-    if (!typeSystem.isAssignableTo(
-        toType, typeSystem.promoteToNonNull(fromType))) {
+    if (toType != null &&
+        !typeSystem.isAssignableTo(
+            typeSystem.promoteToNonNull(fromType), toType)) {
       // The reason that `fromType` can't be assigned to `toType` is more than
       // just because it's nullable, in which case a null check won't fix the
       // problem.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/change_to.dart b/pkg/analysis_server/lib/src/services/correction/dart/change_to.dart
index b4a176f..c62d89e 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/change_to.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/change_to.dart
@@ -188,20 +188,19 @@
       } else if (node.parent is PropertyAccess) {
         target = (node.parent as PropertyAccess).target;
       }
-      // find getter
-      if (node.inGetterContext()) {
-        await _proposeClassOrMixinMember(builder, target, (Element element) {
-          return element is PropertyAccessorElement && element.isGetter ||
-              element is FieldElement && element.getter != null;
-        });
-      }
-      // find setter
-      if (node.inSetterContext()) {
-        await _proposeClassOrMixinMember(builder, target, (Element element) {
-          return element is PropertyAccessorElement && element.isSetter ||
-              element is FieldElement && element.setter != null;
-        });
-      }
+      // find getter or setter
+      var wantGetter = node.inGetterContext();
+      var wantSetter = node.inSetterContext();
+      await _proposeClassOrMixinMember(builder, target, (Element element) {
+        if (element is PropertyAccessorElement) {
+          return wantGetter && element.isGetter ||
+              wantSetter && element.isSetter;
+        } else if (element is FieldElement) {
+          return wantGetter && element.getter != null ||
+              wantSetter && element.setter != null;
+        }
+        return false;
+      });
     }
   }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
index 3ddef42..00bed8c 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
@@ -27,8 +27,8 @@
             ? (_fromDouble ? "'''" : '"""')
             : (_fromDouble ? "'" : '"');
         var quoteLength = literal.isMultiline ? 3 : 1;
-        var lexeme = literal.literal.lexeme;
-        if (!lexeme.contains(newQuote)) {
+        var token = literal.literal;
+        if (!token.isSynthetic && !token.lexeme.contains(newQuote)) {
           await builder.addDartFileEdit(file, (builder) {
             builder.addSimpleReplacement(
                 SourceRange(
@@ -53,8 +53,8 @@
         for (var i = 0; i < elements.length; i++) {
           var element = elements[i];
           if (element is InterpolationString) {
-            var lexeme = element.contents.lexeme;
-            if (lexeme.contains(newQuote)) {
+            var token = element.contents;
+            if (token.isSynthetic || token.lexeme.contains(newQuote)) {
               return null;
             }
           }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart
index 15a289f..e394659 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart
@@ -21,7 +21,7 @@
     }
     if (node is SingleStringLiteral) {
       var literal = node;
-      if (!literal.isMultiline) {
+      if (!literal.isSynthetic && !literal.isMultiline) {
         await builder.addDartFileEdit(file, (builder) {
           var newQuote = literal.isSingleQuoted ? "'''" : '"""';
           builder.addReplacement(
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_named_arguments.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_named_arguments.dart
index ce315d9..5f62701 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_named_arguments.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_named_arguments.dart
@@ -16,7 +16,8 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var argumentList = node;
+    // node is the unmatched argument.
+    var argumentList = node.parent;
     if (argumentList is ArgumentList) {
       // Prepare parameters.
       List<ParameterElement> parameters;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_null_aware_spread.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_null_aware_spread.dart
new file mode 100644
index 0000000..765178a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_null_aware_spread.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.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class ConvertToNullAwareSpread extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.CONVERT_TO_NULL_AWARE_SPREAD;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    var parent = coveredNode.parent;
+    if (parent is SpreadElement && !parent.isNullAware) {
+      await builder.addDartFileEdit(file, (builder) {
+        builder.addSimpleInsertion(parent.spreadOperator.end, '?');
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static ConvertToNullAwareSpread newInstance() => ConvertToNullAwareSpread();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_constructor.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_constructor.dart
index af90fd1..4e397d4 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_constructor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_constructor.dart
@@ -24,8 +24,10 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    if (node is ArgumentList && node.parent is InstanceCreationExpression) {
-      await _proposeFromInstanceCreation(builder);
+    final argumentList = node.parent is ArgumentList ? node.parent : node;
+    if (argumentList is ArgumentList &&
+        argumentList.parent is InstanceCreationExpression) {
+      await _proposeFromInstanceCreation(builder, argumentList.parent);
     } else {
       await _proposeFromConstructorName(builder);
     }
@@ -90,8 +92,8 @@
     });
   }
 
-  Future<void> _proposeFromInstanceCreation(ChangeBuilder builder) async {
-    InstanceCreationExpression instanceCreation = node.parent;
+  Future<void> _proposeFromInstanceCreation(ChangeBuilder builder,
+      InstanceCreationExpression instanceCreation) async {
     _constructorName = instanceCreation.constructorName;
     // should be synthetic default constructor
     var constructorElement = _constructorName.staticElement;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart b/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
index 7ecd51e..e4c9bd3 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
@@ -6,12 +6,10 @@
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
-import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart' show LibraryElement;
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
@@ -24,7 +22,6 @@
 
   @override
   Iterable<CorrectionProducer> get producers sync* {
-    var name = _name;
     var importedUris = <Uri>[];
     var library = resolvedResult.libraryElement;
     for (var importElement in library.imports) {
@@ -36,8 +33,11 @@
         importedUris.add(Uri.parse(uri));
       }
     }
-    var matcher = ElementMatcher(
-        importedUris: importedUris, name: name, kinds: _kindsForNode(node));
+    var matcher = ElementMatcher.forNode(node);
+    if (matcher == null) {
+      // The node doesn't represent an element that can be transformed.
+      return;
+    }
     for (var set in _availableTransformSetsForLibrary(library)) {
       for (var transform
           in set.transformsFor(matcher, applyingBulkFixes: applyingBulkFixes)) {
@@ -46,114 +46,19 @@
     }
   }
 
-  /// Return the name of the element that was changed.
-  String get _name {
-    String nameFromParent(AstNode node) {
-      var parent = node.parent;
-      if (parent is MethodInvocation) {
-        return parent.methodName.name;
-      } else if (parent is InstanceCreationExpression) {
-        var constructorName = parent.constructorName;
-        if (constructorName.name != null) {
-          return constructorName.name.name;
-        }
-        return constructorName.type.name.name;
-      } else if (parent is ExtensionOverride) {
-        return parent.extensionName.name;
-      }
-      return null;
-    }
-
-    var node = this.node;
-    if (node is SimpleIdentifier) {
-      var parent = node.parent;
-      if (parent is Label && parent.parent is NamedExpression) {
-        // The parent of the named expression is an argument list. Because we
-        // don't represent parameters as elements, the element we need to match
-        // against is the invocation containing those arguments.
-        return nameFromParent(parent.parent.parent);
-      }
-      return node.name;
-    } else if (node is ConstructorName) {
-      return node.name.name;
-    } else if (node is NamedType) {
-      return node.name.name;
-    } else if (node is TypeArgumentList) {
-      return nameFromParent(node);
-    } else if (node is ArgumentList) {
-      return nameFromParent(node);
-    }
-    return null;
-  }
-
   /// Return the transform sets that are available for fixing issues in the
   /// given [library].
   List<TransformSet> _availableTransformSetsForLibrary(LibraryElement library) {
     if (transformSetsForTests != null) {
       return transformSetsForTests;
     }
-    return TransformSetManager.instance.forLibrary(library);
-  }
-
-  List<ElementKind> _kindsForNode(AstNode node, {AstNode child}) {
-    if (node is ConstructorName) {
-      return const [ElementKind.constructorKind];
-    } else if (node is ExtensionOverride) {
-      return const [ElementKind.extensionKind];
-    } else if (node is InstanceCreationExpression) {
-      return const [ElementKind.constructorKind];
-    } else if (node is Label) {
-      var argumentList = node.parent.parent;
-      return _kindsForNode(argumentList.parent, child: argumentList);
-    } else if (node is MethodInvocation) {
-      assert(child != null);
-      if (node.target == child) {
-        return const [
-          ElementKind.classKind,
-          ElementKind.enumKind,
-          ElementKind.mixinKind
-        ];
-      } else if (node.realTarget != null) {
-        return const [ElementKind.constructorKind, ElementKind.methodKind];
-      }
-      return const [
-        ElementKind.classKind,
-        ElementKind.extensionKind,
-        ElementKind.functionKind,
-        ElementKind.methodKind
-      ];
-    } else if (node is NamedType) {
-      var parent = node.parent;
-      if (parent is ConstructorName && parent.name == null) {
-        return const [ElementKind.classKind, ElementKind.constructorKind];
-      }
-      return const [
-        ElementKind.classKind,
-        ElementKind.enumKind,
-        ElementKind.mixinKind,
-        ElementKind.typedefKind
-      ];
-    } else if (node is PrefixedIdentifier) {
-      if (node.prefix == child) {
-        return const [
-          ElementKind.classKind,
-          ElementKind.enumKind,
-          ElementKind.extensionKind,
-          ElementKind.mixinKind,
-          ElementKind.typedefKind
-        ];
-      }
-      return const [
-        ElementKind.fieldKind,
-        ElementKind.getterKind,
-        ElementKind.setterKind
-      ];
-    } else if (node is PropertyAccess) {
-      return const [ElementKind.getterKind, ElementKind.setterKind];
-    } else if (node is SimpleIdentifier) {
-      return _kindsForNode(node.parent, child: node);
+    var transformSets = TransformSetManager.instance.forLibrary(library);
+    var overrideSet = this.overrideSet;
+    if (overrideSet != null) {
+      transformSets =
+          transformSets.map((set) => set.applyOverrides(overrideSet)).toList();
     }
-    return null;
+    return transformSets;
   }
 
   /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart b/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart
index acd8708..fcc42fd 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/ast/token.dart';
 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/type.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
@@ -38,6 +39,8 @@
         await _forFieldFormalParameter(builder, node, parent);
       } else if (parent is AssignmentExpression &&
           parent.rightHandSide == node) {
+        await _forAssignment(builder, node as Expression, parent);
+      } else if (parent is VariableDeclaration && parent.initializer == node) {
         await _forVariableDeclaration(builder, node, parent);
       }
     }
@@ -71,6 +74,31 @@
     return null;
   }
 
+  Future<void> _forAssignment(ChangeBuilder builder, Expression node,
+      AssignmentExpression parent) async {
+    var leftHandSide = parent.leftHandSide;
+    if (leftHandSide is SimpleIdentifier) {
+      var element = leftHandSide.staticElement;
+      if (element is LocalVariableElement) {
+        var oldType = element.type;
+        var newType = node.staticType;
+        if (node is NullLiteral) {
+          newType = (oldType as InterfaceTypeImpl)
+              .withNullability(NullabilitySuffix.question);
+        } else if (!typeSystem.isAssignableTo(
+            oldType, typeSystem.promoteToNonNull(newType))) {
+          return;
+        }
+        var declarationList =
+            _findDeclaration(element, parent.thisOrAncestorOfType<Block>());
+        if (declarationList == null || declarationList.variables.length > 1) {
+          return;
+        }
+        await _updateVariableType(builder, declarationList, newType);
+      }
+    }
+  }
+
   /// Makes [parameter] nullable if possible.
   Future<void> _forFieldFormalParameter(ChangeBuilder builder,
       SimpleIdentifier name, FieldFormalParameter parameter) async {
@@ -119,47 +147,26 @@
     });
   }
 
-  Future<void> _forVariableDeclaration(
-      ChangeBuilder builder, AstNode node, AssignmentExpression parent) async {
-    var leftHandSide = parent.leftHandSide;
-    if (leftHandSide is SimpleIdentifier) {
-      var element = leftHandSide.staticElement;
-      if (element is LocalVariableElement) {
-        var oldType = element.type;
-        var newType = (node as Expression).staticType;
-        if (node is NullLiteral) {
-          newType = (oldType as InterfaceTypeImpl)
-              .withNullability(NullabilitySuffix.question);
-        } else if (!typeSystem.isAssignableTo(
-            oldType, typeSystem.promoteToNonNull(newType))) {
-          return;
-        }
-        var declarationList =
-            _findDeclaration(element, parent.thisOrAncestorOfType<Block>());
-        if (declarationList == null || declarationList.variables.length > 1) {
-          return;
-        }
-        var variable = declarationList.variables[0];
-        _variableName = variable.name.name;
-        await builder.addDartFileEdit(file, (builder) {
-          var keyword = declarationList.keyword;
-          if (keyword != null && keyword.type == Keyword.VAR) {
-            builder.addReplacement(range.token(keyword), (builder) {
-              builder.writeType(newType);
-            });
-          } else if (keyword == null) {
-            if (declarationList.type == null) {
-              builder.addInsertion(variable.offset, (builder) {
-                builder.writeType(newType);
-                builder.write(' ');
-              });
-            } else {
-              builder.addSimpleInsertion(declarationList.type.end, '?');
-            }
-          }
-        });
-      }
+  Future<void> _forVariableDeclaration(ChangeBuilder builder, Expression node,
+      VariableDeclaration parent) async {
+    var grandParent = parent.parent;
+    if (grandParent is! VariableDeclarationList) {
+      return;
     }
+    var declarationList = grandParent as VariableDeclarationList;
+    if (declarationList.variables.length > 1) {
+      return;
+    }
+    var oldType = parent.declaredElement.type;
+    var newType = node.staticType;
+    if (node is NullLiteral) {
+      newType = (oldType as InterfaceTypeImpl)
+          .withNullability(NullabilitySuffix.question);
+    } else if (!typeSystem.isAssignableTo(
+        oldType, typeSystem.promoteToNonNull(newType))) {
+      return;
+    }
+    await _updateVariableType(builder, declarationList, newType);
   }
 
   bool _typeCanBeMadeNullable(TypeAnnotation typeAnnotation) {
@@ -173,6 +180,31 @@
     return true;
   }
 
+  /// Add edits to the [builder] to update the type in the [declarationList] to
+  /// match the [newType].
+  Future<void> _updateVariableType(ChangeBuilder builder,
+      VariableDeclarationList declarationList, DartType newType) async {
+    var variable = declarationList.variables[0];
+    _variableName = variable.name.name;
+    await builder.addDartFileEdit(file, (builder) {
+      var keyword = declarationList.keyword;
+      if (keyword != null && keyword.type == Keyword.VAR) {
+        builder.addReplacement(range.token(keyword), (builder) {
+          builder.writeType(newType);
+        });
+      } else if (keyword == null) {
+        if (declarationList.type == null) {
+          builder.addInsertion(variable.offset, (builder) {
+            builder.writeType(newType);
+            builder.write(' ');
+          });
+        } else {
+          builder.addSimpleInsertion(declarationList.type.end, '?');
+        }
+      }
+    });
+  }
+
   /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
   static MakeVariableNullable newInstance() => MakeVariableNullable();
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
index 080bc4f9..8802226 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
@@ -60,27 +60,36 @@
       }
     } else if (parent is IfStatement) {
       if (parent.elseStatement == null && _conditionIsTrue) {
-        var body = _extractBody(parent);
-        body = utils.indentSourceLeftRight(body);
-        await builder.addDartFileEdit(file, (builder) {
-          builder.addSimpleReplacement(
-              range.startOffsetEndOffset(
-                  parent.offset, utils.getLineContentEnd(parent.end)),
-              body);
-        });
+        await _ifStatement(parent, builder);
       }
     }
   }
 
-  String _extractBody(IfStatement statement) {
-    var body = statement.thenStatement;
-    if (body is Block) {
-      var statements = body.statements;
-      return utils.getRangeText(range.startOffsetEndOffset(
-          statements.first.offset,
-          utils.getLineContentEnd(statements.last.end)));
-    }
-    return utils.getNodeText(body);
+  Future<void> _ifStatement(IfStatement node, ChangeBuilder builder) async {
+    await builder.addDartFileEdit(file, (builder) {
+      var nodeRange = utils.getLinesRangeStatements([node]);
+
+      String bodyCode;
+      var body = node.thenStatement;
+      if (body is Block) {
+        var statements = body.statements;
+        if (statements.isEmpty) {
+          builder.addDeletion(nodeRange);
+          return;
+        } else {
+          bodyCode = utils.getRangeText(
+            utils.getLinesRangeStatements(statements),
+          );
+        }
+      } else {
+        bodyCode = utils.getRangeText(
+          utils.getLinesRangeStatements([body]),
+        );
+      }
+
+      bodyCode = utils.indentSourceLeftRight(bodyCode);
+      builder.addSimpleReplacement(nodeRange, bodyCode);
+    });
   }
 
   /// Use the [builder] to add an edit to delete the operator and given
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_parentheses.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_parentheses.dart
new file mode 100644
index 0000000..b3d860c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_parentheses.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.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class RemoveUnnecessaryParentheses extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.REMOVE_UNNECESSARY_PARENTHESES;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    var outer = coveredNode;
+    if (outer is ParenthesizedExpression &&
+        outer.parent is! ParenthesizedExpression) {
+      await builder.addDartFileEdit(file, (builder) {
+        builder.addDeletion(range.token(outer.leftParenthesis));
+        builder.addDeletion(range.token(outer.rightParenthesis));
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static RemoveUnnecessaryParentheses newInstance() =>
+      RemoveUnnecessaryParentheses();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_string_interpolation.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_string_interpolation.dart
new file mode 100644
index 0000000..31692a1
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_string_interpolation.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.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class RemoveUnnecessaryStringInterpolation extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.REMOVE_UNNECESSARY_STRING_INTERPOLATION;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    final interpolation = node;
+    if (interpolation is StringInterpolation) {
+      final open = interpolation.elements[0] as InterpolationString;
+      final contents = interpolation.elements[1] as InterpolationExpression;
+      final close = interpolation.elements[2] as InterpolationString;
+
+      await builder.addDartFileEdit(file, (builder) {
+        final expression = contents.expression;
+        if (getExpressionPrecedence(expression) <
+            getExpressionParentPrecedence(interpolation)) {
+          builder.addReplacement(range.startStart(open, expression), (builder) {
+            builder.write('(');
+          });
+          builder.addReplacement(range.endEnd(expression, close), (builder) {
+            builder.write(')');
+          });
+        } else {
+          builder.addDeletion(range.startStart(open, expression));
+          builder.addDeletion(range.endEnd(expression, close));
+        }
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static RemoveUnnecessaryStringInterpolation newInstance() =>
+      RemoveUnnecessaryStringInterpolation();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_local_variable.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_local_variable.dart
index 5120c45..e3b5cf2 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_local_variable.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_local_variable.dart
@@ -50,6 +50,19 @@
         return;
       }
 
+      var isCovered = false;
+      for (var other in sourceRanges) {
+        if (other.covers(sourceRange)) {
+          isCovered = true;
+        } else if (other.intersects(sourceRange)) {
+          return;
+        }
+      }
+
+      if (isCovered) {
+        continue;
+      }
+
       sourceRanges.add(sourceRange);
     }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_is_not_empty.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_is_not_empty.dart
index 39ee83b..cc06b0d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/use_is_not_empty.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/use_is_not_empty.dart
@@ -10,7 +10,7 @@
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
 
-class UesIsNotEmpty extends CorrectionProducer {
+class UseIsNotEmpty extends CorrectionProducer {
   @override
   FixKind get fixKind => DartFixKind.USE_IS_NOT_EMPTY;
 
@@ -40,5 +40,5 @@
   }
 
   /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
-  static UesIsNotEmpty newInstance() => UesIsNotEmpty();
+  static UseIsNotEmpty newInstance() => UseIsNotEmpty();
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 8bd57b2..bce5281 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -109,6 +109,8 @@
 /// An enumeration of quick fix kinds for the errors found in an analysis
 /// options file.
 class AnalysisOptionsFixKind {
+  static const REMOVE_LINT =
+      FixKind('analysisOptions.fix.removeLint', 50, "Remove '{0}'");
   static const REMOVE_SETTING =
       FixKind('analysisOptions.fix.removeSetting', 50, "Remove '{0}'");
 }
@@ -245,6 +247,8 @@
       'dart.fix.convert.toNamedArguments', 50, 'Convert to named arguments');
   static const CONVERT_TO_NULL_AWARE =
       FixKind('dart.fix.convert.toNullAware', 50, "Convert to use '?.'");
+  static const CONVERT_TO_NULL_AWARE_SPREAD = FixKind(
+      'dart.fix.convert.toNullAwareSpread', 50, "Convert to use '...?'");
   static const CONVERT_TO_ON_TYPE =
       FixKind('dart.fix.convert.toOnType', 50, "Convert to 'on {0}'");
   static const CONVERT_TO_PACKAGE_IMPORT = FixKind(
@@ -259,8 +263,8 @@
       'Convert to single quoted string');
   static const CONVERT_TO_SPREAD =
       FixKind('dart.fix.convert.toSpread', 50, 'Convert to a spread');
-  static const CONVERT_TO_WHERE_TYPE = FixKind(
-      'dart.fix.convert.toWhereType', 50, "Convert to a use 'whereType'");
+  static const CONVERT_TO_WHERE_TYPE =
+      FixKind('dart.fix.convert.toWhereType', 50, "Convert to use 'whereType'");
   static const CREATE_CLASS =
       FixKind('dart.fix.create.class', 50, "Create class '{0}'");
   static const CREATE_CONSTRUCTOR =
@@ -398,6 +402,17 @@
       'Remove unnecessary const keyword');
   static const REMOVE_UNNECESSARY_NEW = FixKind(
       'dart.fix.remove.unnecessaryNew', 50, 'Remove unnecessary new keyword');
+  static const REMOVE_UNNECESSARY_PARENTHESES = FixKind(
+      'dart.fix.remove.unnecessaryParentheses',
+      50,
+      'Remove unnecessary parentheses',
+      appliedTogetherMessage: 'Remove all unnecessary parentheses in file');
+  static const REMOVE_UNNECESSARY_STRING_INTERPOLATION = FixKind(
+      'dart.fix.remove.unnecessaryStringInterpolation',
+      50,
+      'Remove unnecessary string interpolation',
+      appliedTogetherMessage:
+          'Remove all unnecessary string interpolations in file');
   static const REMOVE_UNUSED_CATCH_CLAUSE = FixKind(
       'dart.fix.remove.unusedCatchClause', 50, "Remove unused 'catch' clause");
   static const REMOVE_UNUSED_CATCH_STACK = FixKind(
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
index b176935..c435c38 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
@@ -10,10 +10,10 @@
 import 'package:analysis_server/src/utilities/yaml_node_locator.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/source/source_range.dart';
 import 'package:analyzer/src/analysis_options/error/option_codes.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/lint/options_rule_validator.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:yaml/yaml.dart';
@@ -64,7 +64,11 @@
 //    } else if (errorCode ==
 //        AnalysisOptionsHintCode.STRONG_MODE_SETTING_DEPRECATED) {
 //    } else
-    if (errorCode == AnalysisOptionsHintCode.SUPER_MIXINS_SETTING_DEPRECATED) {
+
+    if (errorCode == DEPRECATED_LINT_HINT) {
+      await _addFix_removeLint();
+    } else if (errorCode ==
+        AnalysisOptionsHintCode.SUPER_MIXINS_SETTING_DEPRECATED) {
       await _addFix_removeSetting();
 //    } else if (errorCode ==
 //        AnalysisOptionsWarningCode.ANALYSIS_OPTION_DEPRECATED) {
@@ -87,57 +91,17 @@
     return fixes;
   }
 
+  Future<void> _addFix_removeLint() async {
+    var builder = await _createScalarDeletionBuilder();
+    if (builder != null) {
+      _addFixFromBuilder(builder, AnalysisOptionsFixKind.REMOVE_LINT,
+          args: [coveringNodePath[0].toString()]);
+    }
+  }
+
   Future<void> _addFix_removeSetting() async {
-    if (coveringNodePath[0] is YamlScalar) {
-      SourceRange deletionRange;
-      var index = 1;
-      while (index < coveringNodePath.length) {
-        var parent = coveringNodePath[index];
-        if (parent is YamlList) {
-          if (parent.nodes.length > 1) {
-            var nodeToDelete = coveringNodePath[index - 1];
-            deletionRange = _lines(
-                nodeToDelete.span.start.offset, nodeToDelete.span.end.offset);
-            break;
-          }
-        } else if (parent is YamlMap) {
-          var nodes = parent.nodes;
-          if (nodes.length > 1) {
-            YamlNode key;
-            YamlNode value;
-            var child = coveringNodePath[index - 1];
-            if (nodes.containsKey(child)) {
-              key = child;
-              value = nodes[child];
-            } else if (nodes.containsValue(child)) {
-              for (var entry in nodes.entries) {
-                if (child == entry.value) {
-                  key = entry.key;
-                  value = child;
-                  break;
-                }
-              }
-            }
-            if (key == null || value == null) {
-              throw StateError(
-                  'Child is neither a key nor a value in the parent');
-            }
-            deletionRange = _lines(key.span.start.offset,
-                _firstNonWhitespaceBefore(value.span.end.offset));
-            break;
-          }
-        } else if (parent is YamlDocument) {
-          break;
-        }
-        index++;
-      }
-      var nodeToDelete = coveringNodePath[index - 1];
-      deletionRange ??=
-          _lines(nodeToDelete.span.start.offset, nodeToDelete.span.end.offset);
-      var builder = ChangeBuilder();
-      await builder.addGenericFileEdit(file, (builder) {
-        builder.addDeletion(deletionRange);
-      });
+    var builder = await _createScalarDeletionBuilder();
+    if (builder != null) {
       _addFixFromBuilder(builder, AnalysisOptionsFixKind.REMOVE_SETTING,
           args: [coveringNodePath[0].toString()]);
     }
@@ -155,6 +119,63 @@
     fixes.add(Fix(kind, change));
   }
 
+  Future<ChangeBuilder> _createScalarDeletionBuilder() async {
+    if (coveringNodePath[0] is! YamlScalar) {
+      return null;
+    }
+
+    SourceRange deletionRange;
+    var index = 1;
+    while (index < coveringNodePath.length) {
+      var parent = coveringNodePath[index];
+      if (parent is YamlList) {
+        if (parent.nodes.length > 1) {
+          var nodeToDelete = coveringNodePath[index - 1];
+          deletionRange = _lines(
+              nodeToDelete.span.start.offset, nodeToDelete.span.end.offset);
+          break;
+        }
+      } else if (parent is YamlMap) {
+        var nodes = parent.nodes;
+        if (nodes.length > 1) {
+          YamlNode key;
+          YamlNode value;
+          var child = coveringNodePath[index - 1];
+          if (nodes.containsKey(child)) {
+            key = child;
+            value = nodes[child];
+          } else if (nodes.containsValue(child)) {
+            for (var entry in nodes.entries) {
+              if (child == entry.value) {
+                key = entry.key;
+                value = child;
+                break;
+              }
+            }
+          }
+          if (key == null || value == null) {
+            throw StateError(
+                'Child is neither a key nor a value in the parent');
+          }
+          deletionRange = _lines(key.span.start.offset,
+              _firstNonWhitespaceBefore(value.span.end.offset));
+          break;
+        }
+      } else if (parent is YamlDocument) {
+        break;
+      }
+      index++;
+    }
+    var nodeToDelete = coveringNodePath[index - 1];
+    deletionRange ??=
+        _lines(nodeToDelete.span.start.offset, nodeToDelete.span.end.offset);
+    var builder = ChangeBuilder();
+    await builder.addGenericFileEdit(file, (builder) {
+      builder.addDeletion(deletionRange);
+    });
+    return builder;
+  }
+
   int _firstNonWhitespaceBefore(int offset) {
     while (offset > 0 && isWhitespace(content.codeUnitAt(offset - 1))) {
       offset--;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/changes_selector.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/changes_selector.dart
index 85f7b7e..c441575 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/changes_selector.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/changes_selector.dart
@@ -26,7 +26,8 @@
   @override
   List<Change> getChanges(TemplateContext context) {
     for (var entry in changeMap.entries) {
-      if (entry.key.evaluateIn(context)) {
+      var value = entry.key.evaluateIn(context);
+      if (value is bool && value) {
         return entry.value;
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart
index 054de2a..c7345c3 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart
@@ -86,6 +86,8 @@
   static AstNode _getInvocation(AstNode node) {
     if (node is ArgumentList) {
       return node.parent;
+    } else if (node.parent is ArgumentList) {
+      return node.parent.parent;
     } else if (node is InstanceCreationExpression ||
         node is InvocationExpression) {
       return node;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
index 2520805..ae3f501 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
@@ -16,7 +16,8 @@
   /// The kind of element that was changed.
   final ElementKind kind;
 
-  /// The components that uniquely identify the element within its library.
+  /// The components that uniquely identify the element within its library. The
+  /// components are ordered from the most local to the most global.
   final List<String> components;
 
   /// Initialize a newly created element descriptor to describe an element
@@ -47,27 +48,27 @@
         if (node is Annotation) {
           var className = _nameFromIdentifier(node.name);
           var constructorName = node.constructorName ?? '';
-          if (components[0] == className && components[1] == constructorName) {
+          if (components[0] == constructorName && components[1] == className) {
             return true;
           }
         } else if (node is InstanceCreationExpression) {
           var name = node.constructorName;
           var className = _nameFromIdentifier(name.type.name);
           var constructorName = name.name?.name ?? '';
-          if (components[0] == className && components[1] == constructorName) {
+          if (components[0] == constructorName && components[1] == className) {
             return true;
           }
         } else if (node is MethodInvocation) {
           var target = node.target;
           if (target == null) {
-            if (components[0] == node.methodName.name && components[1] == '') {
+            if (components[0] == '' && components[1] == node.methodName.name) {
               return true;
             }
           } else if (target is Identifier) {
             var className = _nameFromIdentifier(target);
             var constructorName = node.methodName.name;
-            if (components[0] == className &&
-                components[1] == constructorName) {
+            if (components[0] == constructorName &&
+                components[1] == className) {
               return true;
             }
           }
@@ -95,7 +96,7 @@
         return false;
       case ElementKind.methodKind:
         if (node is MethodInvocation) {
-          if (components[1] == node.methodName.name) {
+          if (components[0] == node.methodName.name) {
             var target = node.realTarget;
             if (target == null) {
               // TODO(brianwilkerson) If `node.target == null` then the invocation
@@ -115,12 +116,12 @@
                 // that the method might have been in the element's class.
                 return true;
               }
-              if (components[0] == type.element.name) {
+              if (components[1] == type.element.name) {
                 return true;
               }
               if (type is InterfaceType) {
                 for (var supertype in type.allSupertypes) {
-                  if (components[0] == supertype.element.name) {
+                  if (components[1] == supertype.element.name) {
                     return true;
                   }
                 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
index aac5dff..d07b075 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
@@ -4,6 +4,10 @@
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart'
+    show ClassElement, ExtensionElement;
+import 'package:analyzer/dart/element/type.dart';
 import 'package:meta/meta.dart';
 
 /// An object that can be used to determine whether an element is appropriate
@@ -13,38 +17,74 @@
   /// reference.
   final List<Uri> importedUris;
 
-  /// The name of the element being referenced.
-  final String name;
+  /// The components of the element being referenced. The components are ordered
+  /// from the most local to the most global.
+  final List<String> components;
 
   /// A list of the kinds of elements that are appropriate for some given
   /// location in the code An empty list represents all kinds rather than no
   /// kinds.
-  List<ElementKind> validKinds;
+  final List<ElementKind> validKinds;
 
   /// Initialize a newly created matcher representing a reference to an element
   /// with the given [name] in a library that imports the [importedUris].
   ElementMatcher(
       {@required this.importedUris,
-      @required this.name,
+      @required this.components,
       List<ElementKind> kinds})
-      : validKinds = kinds ?? const [];
+      : assert(components != null && components.isNotEmpty),
+        validKinds = kinds ?? const [];
 
   /// Return `true` if this matcher matches the given [element].
   bool matches(ElementDescriptor element) {
-    var components = element.components;
-    var lastComponent = components.last;
-    if (lastComponent.isEmpty) {
-      if (components[components.length - 2] != name) {
+    //
+    // Check that the components in the element's name match the node.
+    //
+    // This algorithm is probably too general given that there will currently
+    // always be either one or two components.
+    //
+    var elementComponents = element.components;
+    var elementComponentCount = elementComponents.length;
+    var nodeComponentCount = components.length;
+    if (nodeComponentCount == elementComponentCount) {
+      // The component counts are the same, so we can just compare the two
+      // lists.
+      for (var i = 0; i < nodeComponentCount; i++) {
+        if (elementComponents[i] != components[i]) {
+          return false;
+        }
+      }
+    } else if (nodeComponentCount < elementComponentCount) {
+      // The node has fewer components, which can happen, for example, when we
+      // can't figure out the class that used to define a field. We treat the
+      // missing components as wildcards and match the rest.
+      for (var i = 0; i < nodeComponentCount; i++) {
+        if (elementComponents[i] != components[i]) {
+          return false;
+        }
+      }
+    } else {
+      // The node has more components than the element, which can happen when a
+      // constructor is implicitly renamed because the class was renamed.
+      // TODO(brianwilkerson) Figure out whether we want to support this or
+      //  whether we want to require fix data authors to explicitly include the
+      //  change to the constructor. On the one hand it's more work for the
+      //  author, on the other hand it give us more data so we're less likely to
+      //  make apply a fix in invalid circumstances.
+      if (elementComponents[0] != components[1]) {
         return false;
       }
-    } else if (lastComponent != name) {
-      return false;
     }
-
+    //
+    // Check whether the kind of element matches the possible kinds that the
+    // node might have.
+    //
     if (validKinds.isNotEmpty && !validKinds.contains(element.kind)) {
       return false;
     }
-
+    //
+    // Check whether the element is in an imported library.
+    //
     var libraryUris = element.libraryUris;
     for (var importedUri in importedUris) {
       if (libraryUris.contains(importedUri)) {
@@ -53,4 +93,246 @@
     }
     return false;
   }
+
+  /// Return an element matcher that will match the element that is, or should
+  /// be, associated with the given [node], or `null` if there is no appropriate
+  /// matcher for the node.
+  static ElementMatcher forNode(AstNode node) {
+    if (node == null) {
+      return null;
+    }
+    var importedUris = _importElementsForNode(node);
+    if (importedUris == null) {
+      return null;
+    }
+    var components = _componentsForNode(node);
+    if (components == null) {
+      return null;
+    }
+    return ElementMatcher(
+        importedUris: importedUris,
+        components: components,
+        kinds: _kindsForNode(node));
+  }
+
+  /// Return the components of the path of the element associated with the given
+  /// [node]. The components are ordered from the most local to the most global.
+  /// For example, for a constructor this would be the name of the constructor
+  /// followed by the name of the class in which the constructor is declared
+  /// (with an empty string for the unnamed constructor).
+  static List<String> _componentsForNode(AstNode node) {
+    if (node is SimpleIdentifier) {
+      var parent = node.parent;
+      if (parent is Label && parent.parent is NamedExpression) {
+        // The parent of the named expression is an argument list. Because we
+        // don't represent parameters as elements, the element we need to match
+        // against is the invocation containing those arguments.
+        return _componentsFromParent(parent.parent.parent);
+      } else if (parent is TypeName && parent.parent is ConstructorName) {
+        return ['', node.name];
+      } else if (parent is MethodDeclaration && node == parent.name) {
+        return [node.name];
+      } else if ((parent is MethodInvocation && node == parent.methodName) ||
+          (parent is PrefixedIdentifier && node == parent.identifier) ||
+          (parent is PropertyAccess && node == parent.propertyName)) {
+        return _componentsFromParent(node);
+      }
+      return _componentsFromIdentifier(node);
+    } else if (node is PrefixedIdentifier) {
+      var parent = node.parent;
+      if (parent is TypeName && parent.parent is ConstructorName) {
+        return ['', node.identifier.name];
+      }
+      return [node.identifier.name];
+    } else if (node is ConstructorName) {
+      return [node.name.name];
+    } else if (node is NamedType) {
+      return [node.name.name];
+    } else if (node is TypeArgumentList) {
+      return _componentsFromParent(node);
+    } else if (node is ArgumentList) {
+      return _componentsFromParent(node);
+    } else if (node?.parent is ArgumentList) {
+      return _componentsFromParent(node.parent);
+    }
+    return null;
+  }
+
+  /// Return the components associated with the [identifier] when there is no
+  /// contextual information.
+  static List<String> _componentsFromIdentifier(SimpleIdentifier identifier) {
+    var element = identifier.staticElement;
+    if (element == null) {
+      var parent = identifier.parent;
+      if (parent is AssignmentExpression && identifier == parent.leftHandSide) {
+        element = parent.writeElement;
+      }
+    }
+    if (element != null) {
+      var enclosingElement = element.enclosingElement;
+      if (enclosingElement is ClassElement ||
+          enclosingElement is ExtensionElement) {
+        return [identifier.name, enclosingElement.name];
+      }
+    }
+    return [identifier.name];
+  }
+
+  /// Return the components for the element associated with the given [node] by
+  /// looking at the parent of the [node].
+  static List<String> _componentsFromParent(AstNode node) {
+    var parent = node.parent;
+    if (parent is ArgumentList) {
+      parent = parent.parent;
+    }
+    if (parent is Annotation) {
+      return [parent.constructorName?.name ?? '', parent.name.name];
+    } else if (parent is ExtensionOverride) {
+      return [parent.extensionName.name];
+    } else if (parent is InstanceCreationExpression) {
+      var constructorName = parent.constructorName;
+      return [constructorName.name?.name ?? '', constructorName.type.name.name];
+    } else if (parent is MethodInvocation) {
+      var methodName = parent.methodName;
+      var targetName = _nameOfTarget(parent.realTarget);
+      if (targetName != null) {
+        return [methodName.name, targetName];
+      }
+      return _componentsFromIdentifier(methodName);
+    } else if (parent is PrefixedIdentifier) {
+      var identifier = parent.identifier;
+      var targetName = _nameOfTarget(parent.prefix);
+      if (targetName != null) {
+        return [identifier.name, targetName];
+      }
+      return _componentsFromIdentifier(identifier);
+    } else if (parent is PropertyAccess) {
+      var propertyName = parent.propertyName;
+      var targetName = _nameOfTarget(parent.realTarget);
+      if (targetName != null) {
+        return [propertyName.name, targetName];
+      }
+      return _componentsFromIdentifier(propertyName);
+    } else if (parent is RedirectingConstructorInvocation) {
+      var ancestor = parent.parent;
+      if (ancestor is ConstructorDeclaration) {
+        return [parent.constructorName?.name ?? '', ancestor.returnType.name];
+      }
+    } else if (parent is SuperConstructorInvocation) {
+      var ancestor = parent.parent;
+      if (ancestor is ConstructorDeclaration) {
+        return [parent.constructorName?.name ?? '', ancestor.returnType.name];
+      }
+    }
+    return null;
+  }
+
+  /// Return the URIs of the imports in the library containing the [node], or
+  /// `null` if the imports can't be determined.
+  static List<Uri> _importElementsForNode(AstNode node) {
+    var root = node.root;
+    if (root is! CompilationUnit) {
+      return null;
+    }
+    var importedUris = <Uri>[];
+    var library = (root as CompilationUnit).declaredElement.library;
+    for (var importElement in library.imports) {
+      // TODO(brianwilkerson) Filter based on combinators to help avoid making
+      //  invalid suggestions.
+      var uri = importElement.importedLibrary?.source?.uri;
+      if (uri != null) {
+        // The [uri] is `null` if the literal string is not a valid URI.
+        importedUris.add(uri);
+      }
+    }
+    return importedUris;
+  }
+
+  /// Return the kinds of elements that could reasonably be referenced at the
+  /// location of the [node]. If [child] is no `null` then the [node] is a
+  /// parent of the original node.
+  static List<ElementKind> _kindsForNode(AstNode node, {AstNode child}) {
+    if (node is ConstructorName) {
+      return const [ElementKind.constructorKind];
+    } else if (node is ExtensionOverride) {
+      return const [ElementKind.extensionKind];
+    } else if (node is InstanceCreationExpression) {
+      return const [ElementKind.constructorKind];
+    } else if (node is Label) {
+      var argumentList = node.parent.parent;
+      return _kindsForNode(argumentList.parent, child: argumentList);
+    } else if (node is MethodInvocation) {
+      assert(child != null);
+      if (node.target == child) {
+        return const [
+          ElementKind.classKind,
+          ElementKind.enumKind,
+          ElementKind.mixinKind
+        ];
+      } else if (node.realTarget != null) {
+        return const [ElementKind.constructorKind, ElementKind.methodKind];
+      }
+      return const [
+        ElementKind.classKind,
+        ElementKind.extensionKind,
+        ElementKind.functionKind,
+        ElementKind.methodKind
+      ];
+    } else if (node is NamedType) {
+      var parent = node.parent;
+      if (parent is ConstructorName && parent.name == null) {
+        return const [ElementKind.classKind, ElementKind.constructorKind];
+      }
+      return const [
+        ElementKind.classKind,
+        ElementKind.enumKind,
+        ElementKind.mixinKind,
+        ElementKind.typedefKind
+      ];
+    } else if (node is PrefixedIdentifier) {
+      if (node.prefix == child) {
+        return const [
+          ElementKind.classKind,
+          ElementKind.enumKind,
+          ElementKind.extensionKind,
+          ElementKind.mixinKind,
+          ElementKind.typedefKind
+        ];
+      }
+      return const [
+        ElementKind.fieldKind,
+        ElementKind.getterKind,
+        ElementKind.setterKind
+      ];
+    } else if (node is PropertyAccess) {
+      return const [ElementKind.getterKind, ElementKind.setterKind];
+    } else if (node is SimpleIdentifier) {
+      return _kindsForNode(node.parent, child: node);
+    }
+    return null;
+  }
+
+  /// Return the name of the class associated with the given [target].
+  static String _nameOfTarget(Expression target) {
+    if (target is SimpleIdentifier) {
+      var type = target.staticType;
+      if (type != null) {
+        if (type is InterfaceType) {
+          return type.element.name;
+        } else if (type.isDynamic) {
+          // The name is likely to be undefined.
+          return target.name;
+        }
+        return null;
+      }
+      return target.name;
+    } else if (target != null) {
+      var type = target.staticType;
+      if (type is InterfaceType) {
+        return type.element.name;
+      }
+      return null;
+    }
+    return null;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
index b73a574..32d0b8e 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
@@ -238,6 +238,9 @@
       if (argumentList is ArgumentList) {
         return _Data(argumentList);
       }
+    } else if (parent?.parent is InvocationExpression) {
+      var argumentList = (parent.parent as InvocationExpression).argumentList;
+      return _Data(argumentList);
     }
     return null;
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform.dart
index 20d7ff4..0a60dd7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform.dart
@@ -5,6 +5,7 @@
 import 'package:analysis_server/src/services/correction/fix/data_driven/changes_selector.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override.dart';
 import 'package:meta/meta.dart';
 
 /// A description of a set of changes to a single element of the API.
@@ -44,4 +45,19 @@
     }
     return matcher.matches(element);
   }
+
+  /// Return a new transform with the [override] applied, or this transform if
+  /// there are no overrides.
+  Transform applyOverride(TransformOverride override) {
+    var overriddenBulkApply = override.bulkApply;
+    if (overriddenBulkApply != null && overriddenBulkApply != bulkApply) {
+      return Transform(
+          title: title,
+          date: date,
+          bulkApply: overriddenBulkApply,
+          element: element,
+          changesSelector: changesSelector);
+    }
+    return this;
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override.dart
new file mode 100644
index 0000000..abb7246
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override.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.
+
+import 'package:meta/meta.dart';
+
+/// A description of a set of changes to a single transform.
+class TransformOverride {
+  /// The title of the transform being overridden.
+  final String title;
+
+  /// The overridden value of the `bulkApply` property of the transform, or
+  /// `null` if the property should not be overridden.
+  final bool bulkApply;
+
+  /// Initialize a newly created transform override to override the transform
+  /// with the given [title]. The remaining parameters correspond to properties
+  /// of the transform. They should have non-null values when the property is to
+  /// be overridden, and a value of `null` when the property should be
+  /// unchanged.
+  TransformOverride({@required this.title, this.bulkApply});
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set.dart
new file mode 100644
index 0000000..597efde
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set.dart
@@ -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.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override.dart';
+
+/// A description of a set of transform overrides.
+class TransformOverrideSet {
+  /// A map from transform titles to the override for that transform.
+  final Map<String, TransformOverride> overrideMap = {};
+
+  /// Initialize a newly created transform override set to include all of the
+  /// [overrides].
+  TransformOverrideSet(List<TransformOverride> overrides) {
+    for (var override in overrides) {
+      overrideMap[override.title] = override;
+    }
+  }
+
+  /// Return the overrides in this set.
+  List<TransformOverride> get overrides => overrideMap.values.toList();
+
+  /// Return the override for the transform with the given [title] or `null` if
+  /// there is no such override in this set.
+  TransformOverride overrideForTransform(String title) => overrideMap[title];
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set_parser.dart
new file mode 100644
index 0000000..fea46f7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set_parser.dart
@@ -0,0 +1,217 @@
+// 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/services/correction/fix/data_driven/transform_override.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_parser.dart';
+import 'package:analysis_server/src/utilities/extensions/yaml.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:yaml/src/yaml_exception.dart';
+import 'package:yaml/src/yaml_node.dart';
+import 'package:yaml/yaml.dart';
+
+/// A parser used to parse the content of a configuration file.
+class TransformOverrideSetParser {
+  // TODO(brianwilkerson) Create a class or mixin that would allow this class
+  //  and `TransformSetParser` to share code.
+  static const String _bulkApplyKey = 'bulkApply';
+
+  /// The error reporter to which diagnostics will be reported.
+  final ErrorReporter errorReporter;
+
+  /// Initialize a newly created parser to report errors to the [errorReporter].
+  TransformOverrideSetParser(this.errorReporter);
+
+  /// Return the result of parsing the file [content] into a transform override,
+  /// or `null` if the content does not represent a valid transform override.
+  TransformOverrideSet parse(String content) {
+    assert(content != null);
+    var map = _parseYaml(content);
+    if (map == null) {
+      // The error has already been reported.
+      return null;
+    }
+    return _translateTransformOverrideSet(map);
+  }
+
+  /// Return a textual description of the type of value represented by the
+  /// [node].
+  String _nodeType(YamlNode node) {
+    if (node is YamlScalar) {
+      return node.value.runtimeType.toString();
+    } else if (node is YamlList) {
+      return 'List';
+    } else if (node is YamlMap) {
+      return 'Map';
+    }
+    // We shouldn't get here.
+    return node.runtimeType.toString();
+  }
+
+  /// Return the result of parsing the file [content] into a YAML node.
+  YamlNode _parseYaml(String content) {
+    try {
+      return loadYamlNode(content);
+    } on YamlException catch (e) {
+      var span = e.span;
+      errorReporter.reportErrorForOffset(TransformSetErrorCode.yamlSyntaxError,
+          span.start.offset, span.length, [e.message]);
+    }
+    return null;
+  }
+
+  /// Report a diagnostic with the given [code] associated with the given
+  /// [node]. A list of [arguments] should be provided if the diagnostic message
+  /// has parameters.
+  void _reportError(TransformSetErrorCode code, YamlNode node,
+      [List<String> arguments]) {
+    var span = node.span;
+    errorReporter.reportErrorForOffset(
+        code, span.start.offset, span.length, arguments);
+  }
+
+  /// Report that the value represented by the [node] does not have the
+  /// [expectedType], using the [context] to get the key to use in the message.
+  Null _reportInvalidValue(
+      YamlNode node, ErrorContext context, String expectedType) {
+    _reportError(TransformSetErrorCode.invalidValue, node,
+        [context.key, expectedType, _nodeType(node)]);
+    return null;
+  }
+
+  /// Report that a required key is missing, using the [context] to locate the
+  /// node associated with the diagnostic and the key to use in the message.
+  Null _reportMissingKey(ErrorContext context) {
+    _reportError(
+        TransformSetErrorCode.missingKey, context.parentNode, [context.key]);
+    return null;
+  }
+
+  /// Report any keys in the [map] whose values are not in [validKeys].
+  void _reportUnsupportedKeys(YamlMap map, Set<String> validKeys) {
+    for (var keyNode in map.nodes.keys) {
+      var key = _translateKey(keyNode);
+      if (key != null && !validKeys.contains(key)) {
+        _reportError(TransformSetErrorCode.unsupportedKey, keyNode, [key]);
+      }
+    }
+  }
+
+  /// Translate the [node] into a bool. Return the resulting bool, or `null`
+  /// if the [node] doesn't represent a valid bool. If the [node] isn't valid,
+  /// use the [context] to report the error. If the [node] doesn't exist and
+  /// [required] is `true`, then report an error.
+  bool _translateBool(YamlNode node, ErrorContext context,
+      {bool required = true}) {
+    if (node is YamlScalar) {
+      var value = node.value;
+      if (value is bool) {
+        return value;
+      }
+      return _reportInvalidValue(node, context, 'boolean');
+    } else if (node == null) {
+      if (required) {
+        return _reportMissingKey(context);
+      }
+      return null;
+    } else {
+      return _reportInvalidValue(node, context, 'boolean');
+    }
+  }
+
+  /// Translate the given [node] as a key.
+  String _translateKey(YamlNode node) {
+    String type;
+    if (node is YamlScalar) {
+      if (node.value is String) {
+        return node.value as String;
+      }
+      type = node.value.runtimeType.toString();
+    } else if (node is YamlList) {
+      type = 'List';
+    } else if (node is YamlMap) {
+      type = 'Map';
+    } else {
+      type = node.runtimeType.toString();
+    }
+    _reportError(TransformSetErrorCode.invalidKey, node, [type]);
+    return null;
+  }
+
+  /// Translate the [node] into a string. Return the resulting string, or `null`
+  /// if the [node] doesn't represent a valid string. If the [node] isn't valid,
+  /// use the [context] to report the error. If the [node] doesn't exist and
+  /// [required] is `true`, then report an error.
+  String _translateString(YamlNode node, ErrorContext context,
+      {bool required = true}) {
+    if (node is YamlScalar) {
+      var value = node.value;
+      if (value is String) {
+        return value;
+      }
+      return _reportInvalidValue(node, context, 'String');
+    } else if (node == null) {
+      if (required) {
+        return _reportMissingKey(context);
+      }
+      return null;
+    } else {
+      return _reportInvalidValue(node, context, 'String');
+    }
+  }
+
+  /// Translate the [node] into a transform override. Return the resulting
+  /// transform override, or `null` if the [node] does not represent a valid
+  /// transform override.
+  TransformOverride _translateTransformOverride(
+      YamlNode node, ErrorContext context, String title) {
+    assert(node != null);
+    if (node is YamlMap) {
+      _reportUnsupportedKeys(node, const {_bulkApplyKey});
+      var bulkApplyNode = node.valueAt(_bulkApplyKey);
+      if (bulkApplyNode != null) {
+        var bulkApplyValue = _translateBool(
+            bulkApplyNode, ErrorContext(key: _bulkApplyKey, parentNode: node),
+            required: true);
+        if (bulkApplyValue != null) {
+          return TransformOverride(title: title, bulkApply: bulkApplyValue);
+        }
+      }
+      return null;
+    } else {
+      return _reportInvalidValue(node, context, 'Map');
+    }
+  }
+
+  /// Translate the [node] into a transform override. Return the resulting
+  /// transform override, or `null` if the [node] does not represent a valid
+  /// transform override.
+  TransformOverrideSet _translateTransformOverrideSet(YamlNode node) {
+    assert(node != null);
+    if (node is YamlMap) {
+      var overrides = <TransformOverride>[];
+      for (var entry in node.nodes.entries) {
+        var keyNode = entry.key as YamlNode;
+        var errorContext = ErrorContext(key: 'file', parentNode: node);
+        var key = _translateString(keyNode, errorContext);
+        if (key != null) {
+          var valueNode = entry.value;
+          var override =
+              _translateTransformOverride(valueNode, errorContext, key);
+          if (override != null) {
+            overrides.add(override);
+          }
+        }
+      }
+      return TransformOverrideSet(overrides);
+    } else {
+      // TODO(brianwilkerson) Consider having a different error code for the
+      //  top-level node (instead of using 'file' as the "key").
+      _reportError(TransformSetErrorCode.invalidValue, node,
+          ['file', 'Map', _nodeType(node)]);
+      return null;
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set.dart
index bbf0976..de1b7dd 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set.dart';
 import 'package:meta/meta.dart';
 
 /// A set of transforms used to aid in the construction of fixes for issues
@@ -18,6 +19,21 @@
     _transforms.add(transform);
   }
 
+  /// Return the result of applying the overrides in the [overrideSet] to the
+  /// transforms in this set.
+  TransformSet applyOverrides(TransformOverrideSet overrideSet) {
+    var overriddenSet = TransformSet();
+    for (var transform in _transforms) {
+      var override = overrideSet.overrideForTransform(transform.title);
+      if (override != null) {
+        overriddenSet.addTransform(transform.applyOverride(override));
+      } else {
+        overriddenSet.addTransform(transform);
+      }
+    }
+    return overriddenSet;
+  }
+
   /// Return a list of the transforms that match the [matcher]. The flag
   /// [applyingBulkFixes] indicates whether the transforms are being applied in
   /// the context of a bulk fix.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
index b477af8..9841ec8 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
@@ -22,7 +22,8 @@
   /// Return the transform sets associated with the [library].
   List<TransformSet> forLibrary(LibraryElement library) {
     var transformSets = <TransformSet>[];
-    var workspace = library.session.analysisContext.workspace;
+    var analysisContext = library.session.analysisContext;
+    var workspace = analysisContext.workspace;
     var libraryPath = library.source.fullName;
     var package = workspace.findPackageFor(libraryPath);
     if (package == null) {
@@ -37,7 +38,14 @@
         transformSets.add(transformSet);
       }
     }
-    // TODO(brianwilkerson) Consider looking for a data file in the SDK.
+    var sdkRoot = analysisContext.sdkRoot;
+    if (sdkRoot != null) {
+      var file = sdkRoot.getChildAssumingFile('lib/_internal/$dataFileName');
+      var transformSet = _loadTransformSet(file);
+      if (transformSet != null) {
+        transformSets.add(transformSet);
+      }
+    }
     return transformSets;
   }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index 351608c..b0c122c 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -657,7 +657,7 @@
             return null;
           }
         } else {
-          components.insert(0, containerName);
+          components.add(containerName);
         }
       }
       if (uris == null) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart
index b59bac9..527669f 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart
@@ -21,8 +21,12 @@
   @override
   String evaluateIn(TemplateContext context) {
     Object target = context.node;
-    for (var accessor in accessors) {
-      target = accessor.getValue(target).result;
+    for (var i = 0; i < accessors.length; i++) {
+      var result = accessors[i].getValue(target);
+      if (!result.isValid) {
+        return '';
+      }
+      target = result.result;
     }
     if (target is AstNode) {
       return context.utils.getRangeText(range.node(target));
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/manifest/fix_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/manifest/fix_generator.dart
index d073108..ebc7431 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/manifest/fix_generator.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/manifest/fix_generator.dart
@@ -8,7 +8,6 @@
 import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/source/source_range.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/manifest/manifest_warning_code.dart';
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart
index 7e66f79..d82b128 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/pubspec/fix_generator.dart
@@ -9,7 +9,6 @@
 import 'package:analysis_server/src/utilities/yaml_node_locator.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/source/source_range.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/pubspec/pubspec_warning_code.dart';
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 5995aaf..97be45b 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -49,6 +49,7 @@
 import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_named_arguments.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware_spread.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_on_type.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_package_import.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
@@ -111,6 +112,8 @@
 import 'package:analysis_server/src/services/correction/dart/remove_type_arguments.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_cast.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_new.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_parentheses.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_string_interpolation.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unused.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unused_catch_clause.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unused_catch_stack.dart';
@@ -415,7 +418,7 @@
       ReplaceWithIsEmpty.newInstance,
     ],
     LintNames.prefer_is_not_empty: [
-      UesIsNotEmpty.newInstance,
+      UseIsNotEmpty.newInstance,
     ],
     LintNames.prefer_if_null_operators: [
       ConvertToIfNull.newInstance,
@@ -478,6 +481,12 @@
     LintNames.unnecessary_overrides: [
       RemoveMethodDeclaration.newInstance,
     ],
+    LintNames.unnecessary_parenthesis: [
+      RemoveUnnecessaryParentheses.newInstance,
+    ],
+    LintNames.unnecessary_string_interpolations: [
+      RemoveUnnecessaryStringInterpolation.newInstance,
+    ],
     LintNames.unnecessary_this: [
       RemoveThisExpression.newInstance,
     ],
@@ -632,6 +641,7 @@
   static const Map<ErrorCode, List<ProducerGenerator>> nonLintProducerMap = {
     CompileTimeErrorCode.ASSIGNMENT_TO_FINAL: [
       MakeFieldNotFinal.newInstance,
+      AddLate.newInstance,
     ],
     CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL: [
       MakeVariableNotFinal.newInstance,
@@ -814,6 +824,34 @@
       CreateClass.newInstance,
       CreateMixin.newInstance,
     ],
+    CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE: [
+      AddNullCheck.newInstance,
+    ],
+    CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE: [
+      AddNullCheck.newInstance,
+    ],
+    CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE: [
+      AddNullCheck.newInstance,
+    ],
+    CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE: [
+      AddNullCheck.newInstance,
+    ],
+    CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE: [
+      AddNullCheck.newInstance,
+    ],
+    CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION: [
+      AddNullCheck.newInstance,
+    ],
+    CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR: [
+      AddNullCheck.newInstance,
+    ],
+    CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD: [
+      AddNullCheck.newInstance,
+      ConvertToNullAwareSpread.newInstance,
+    ],
+    CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH: [
+      AddNullCheck.newInstance,
+    ],
     CompileTimeErrorCode.UNDEFINED_ANNOTATION: [
       ChangeTo.annotation,
       CreateClass.newInstance,
@@ -1081,6 +1119,9 @@
     StaticWarningCode.INVALID_NULL_AWARE_OPERATOR: [
       ReplaceWithNotNullAware.newInstance,
     ],
+    StaticWarningCode.INVALID_NULL_AWARE_OPERATOR_AFTER_SHORT_CIRCUIT: [
+      ReplaceWithNotNullAware.newInstance,
+    ],
     StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH: [
       AddMissingEnumCaseClauses.newInstance,
     ],
diff --git a/pkg/analysis_server/lib/src/services/flutter/property.dart b/pkg/analysis_server/lib/src/services/flutter/property.dart
index ba6509a..25f01ab 100644
--- a/pkg/analysis_server/lib/src/services/flutter/property.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/property.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:analysis_server/protocol/protocol_generated.dart' as protocol;
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/services/flutter/class_description.dart';
 import 'package:analysis_server/src/utilities/flutter.dart';
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 7e66c3c..e24d8d5 100644
--- a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.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:analysis_server/protocol/protocol_generated.dart' as protocol;
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/services/flutter/class_description.dart';
 import 'package:analysis_server/src/services/flutter/property.dart';
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index c291cc2..46abeb4 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -76,6 +76,7 @@
       'prefer_interpolation_to_compose_strings';
   static const String prefer_is_empty = 'prefer_is_empty';
   static const String prefer_is_not_empty = 'prefer_is_not_empty';
+  static const String prefer_is_not_operator = 'prefer_is_not_operator';
   static const String prefer_iterable_whereType = 'prefer_iterable_whereType';
   static const String prefer_null_aware_operators =
       'prefer_null_aware_operators';
@@ -95,6 +96,9 @@
   static const String unnecessary_null_in_if_null_operators =
       'unnecessary_null_in_if_null_operators';
   static const String unnecessary_overrides = 'unnecessary_overrides';
+  static const String unnecessary_parenthesis = 'unnecessary_parenthesis';
+  static const String unnecessary_string_interpolations =
+      'unnecessary_string_interpolations';
   static const String unnecessary_this = 'unnecessary_this';
   static const String use_full_hex_values_for_flutter_colors =
       'use_full_hex_values_for_flutter_colors';
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index 49b10c9..ddc1c22 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -71,8 +71,9 @@
   Future<List<SearchMatch>> searchMemberDeclarations(String name) async {
     var allDeclarations = <SearchMatch>[];
     var drivers = _drivers.toList();
+    var searchedFiles = _createSearchedFiles(drivers);
     for (var driver in drivers) {
-      var elements = await driver.search.classMembers(name);
+      var elements = await driver.search.classMembers(name, searchedFiles);
       allDeclarations.addAll(elements.map(SearchMatchImpl.forElement));
     }
     return allDeclarations;
@@ -126,7 +127,7 @@
   SearchedFiles _createSearchedFiles(List<AnalysisDriver> drivers) {
     var searchedFiles = SearchedFiles();
     for (var driver in drivers) {
-      searchedFiles.ownAdded(driver.search);
+      searchedFiles.ownAnalyzed(driver.search);
     }
     return searchedFiles;
   }
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 8f04747..c64abed 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -482,6 +482,8 @@
     buf.writeln(writeOption('Context location', escape(contextPath)));
     buf.writeln(writeOption('Analysis options path',
         escape(driver.contextRoot.optionsFilePath ?? 'none')));
+    buf.writeln(
+        writeOption('SDK root', escape(driver.analysisContext.sdkRoot.path)));
 
     buf.writeln('<div class="columns">');
 
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart
index 5877e34..78fb773 100644
--- a/pkg/analysis_server/lib/starter.dart
+++ b/pkg/analysis_server/lib/starter.dart
@@ -31,5 +31,6 @@
   set instrumentationService(InstrumentationService service);
 
   /// Use the given command-line [arguments] to start this server.
-  void start(List<String> arguments, [SendPort sendPort]);
+  void start(List<String> arguments,
+      {SendPort sendPort, bool defaultToLsp = false});
 }
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 9c2c7e9..25a3347 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -49,6 +49,17 @@
   final Map<String, String> _declaredVariables = {};
   AnalysisContextCollection _analysisContextCollection;
 
+  List<AnalysisContext> get allContexts {
+    _createAnalysisContexts();
+    return _analysisContextCollection.contexts;
+  }
+
+  List<AnalysisDriver> get allDrivers {
+    return allContexts
+        .map((e) => (e as DriverBasedAnalysisContext).driver)
+        .toList();
+  }
+
   /// The file system specific `/home/test/analysis_options.yaml` path.
   String get analysisOptionsPath =>
       convertPath('/home/test/analysis_options.yaml');
@@ -260,13 +271,28 @@
       enableIndex: true,
       includedPaths: collectionIncludedPaths.map(convertPath).toList(),
       resourceProvider: resourceProvider,
-      sdkPath: convertPath('/sdk'),
+      sdkPath: convertPath(sdkRoot),
     );
 
     verifyCreatedCollection();
   }
 }
 
+mixin WithNonFunctionTypeAliasesMixin on AbstractContextTest {
+  @override
+  String get testPackageLanguageVersion => null;
+
+  @nonVirtual
+  @override
+  void setUp() {
+    super.setUp();
+
+    createAnalysisOptionsFile(
+      experiments: [EnableString.nonfunction_type_aliases],
+    );
+  }
+}
+
 mixin WithNullSafetyMixin on AbstractContextTest {
   @override
   String get testPackageLanguageVersion => '2.12';
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index 504662a..1a04502 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -4,14 +4,11 @@
 
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/ast/element_locator.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/test_utilities/find_element.dart';
 import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:test/test.dart';
@@ -31,6 +28,7 @@
   CompilationUnitElement testUnitElement;
   LibraryElement testLibraryElement;
   FindNode findNode;
+  FindElement findElement;
 
   @override
   void addSource(String path, String content) {
@@ -48,78 +46,16 @@
     addSource(testFile, code);
   }
 
-  Element findElement(String name, [ElementKind kind]) {
-    return findChildElement(testUnitElement, name, kind);
-  }
-
   int findEnd(String search) {
     return findOffset(search) + search.length;
   }
 
-  /// Returns the [SimpleIdentifier] at the given search pattern.
-  SimpleIdentifier findIdentifier(String search) {
-    return findNodeAtString(search, (node) => node is SimpleIdentifier);
-  }
-
-  /// Search the [testUnit] for the [LocalVariableElement] with the given
-  /// [name]. Fail if there is not exactly one such variable.
-  LocalVariableElement findLocalVariable(String name) {
-    var finder = _ElementsByNameFinder(name);
-    testUnit.accept(finder);
-    var localVariables = finder.elements.whereType<LocalVariableElement>();
-    expect(localVariables, hasLength(1));
-    return localVariables.single;
-  }
-
-  AstNode findNodeAtOffset(int offset, [Predicate<AstNode> predicate]) {
-    var result = NodeLocator(offset).searchWithin(testUnit);
-    if (result != null && predicate != null) {
-      result = result.thisOrAncestorMatching(predicate);
-    }
-    return result;
-  }
-
-  AstNode findNodeAtString(String search, [Predicate<AstNode> predicate]) {
-    var offset = findOffset(search);
-    return findNodeAtOffset(offset, predicate);
-  }
-
-  Element findNodeElementAtString(String search,
-      [Predicate<AstNode> predicate]) {
-    var node = findNodeAtString(search, predicate);
-    if (node == null) {
-      return null;
-    }
-    return ElementLocator.locate(node);
-  }
-
   int findOffset(String search) {
     var offset = testCode.indexOf(search);
     expect(offset, isNonNegative, reason: "Not found '$search' in\n$testCode");
     return offset;
   }
 
-  int getLeadingIdentifierLength(String search) {
-    var length = 0;
-    while (length < search.length) {
-      var c = search.codeUnitAt(length);
-      if (c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0)) {
-        length++;
-        continue;
-      }
-      if (c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0)) {
-        length++;
-        continue;
-      }
-      if (c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0)) {
-        length++;
-        continue;
-      }
-      break;
-    }
-    return length;
-  }
-
   @override
   File newFile(String path, {String content = ''}) {
     if (useLineEndingsForPlatform) {
@@ -135,6 +71,7 @@
 
   Future<void> resolveTestFile() async {
     testAnalysisResult = await session.getResolvedUnit(testFile);
+    testCode = testAnalysisResult.content;
     testUnit = testAnalysisResult.unit;
     if (verifyNoTestUnitErrors) {
       expect(testAnalysisResult.errors.where((AnalysisError error) {
@@ -150,6 +87,7 @@
     testUnitElement = testUnit.declaredElement;
     testLibraryElement = testUnitElement.library;
     findNode = FindNode(testCode, testUnit);
+    findElement = FindElement(testUnit);
   }
 
   @override
@@ -158,17 +96,3 @@
     testFile = convertPath('/home/test/lib/test.dart');
   }
 }
-
-class _ElementsByNameFinder extends RecursiveAstVisitor<void> {
-  final String name;
-  final List<Element> elements = [];
-
-  _ElementsByNameFinder(this.name);
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    if (node.name == name && node.inDeclarationContext()) {
-      elements.add(node.staticElement);
-    }
-  }
-}
diff --git a/pkg/analysis_server/test/analysis/bazel_changes_test.dart b/pkg/analysis_server/test/analysis/bazel_changes_test.dart
new file mode 100644
index 0000000..896d08c
--- /dev/null
+++ b/pkg/analysis_server/test/analysis/bazel_changes_test.dart
@@ -0,0 +1,88 @@
+// 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 'dart:async';
+
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol_constants.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/context_manager.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../analysis_abstract.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(BazelChangesTest);
+  });
+}
+
+@reflectiveTest
+class BazelChangesTest extends AbstractAnalysisTest {
+  Map<String, List<AnalysisError>> filesErrors = {};
+  Completer<void> processedNotification;
+
+  @override
+  void processNotification(Notification notification) {
+    if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
+      var decoded = AnalysisErrorsParams.fromNotification(notification);
+      filesErrors[decoded.file] = decoded.errors;
+      processedNotification?.complete();
+    }
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+
+    experimentalEnableBazelWatching = true;
+
+    projectPath = convertPath('/workspaceRoot/third_party/dart/project');
+    testFile =
+        convertPath('/workspaceRoot/third_party/dart/project/lib/test.dart');
+    newFile('/workspaceRoot/WORKSPACE');
+    newFolder('/workspaceRoot/bazel-lib/project');
+    newFolder('/workspaceRoot/bazel-genfiles/project');
+  }
+
+  @override
+  void tearDown() {
+    // Make sure to destroy all the contexts and cancel all subscriptions to
+    // file watchers.
+    server.contextManager.setRoots([], []);
+
+    experimentalEnableBazelWatching = false;
+
+    super.tearDown();
+  }
+
+  Future<void> test_findingFileInGenfiles() async {
+    processedNotification = Completer();
+
+    newFile(testFile, content: r'''
+import 'generated.dart';
+void main() { fun(); }
+''');
+    createProject();
+
+    // We should have some errors since the `generated.dart` is not there yet.
+    await processedNotification.future;
+    expect(filesErrors[testFile], isNotEmpty);
+
+    // Clear errors, so that we'll notice new results.
+    filesErrors.clear();
+    processedNotification = Completer();
+
+    // Simulate the creation of a generated file.
+    newFile(
+        '/workspaceRoot/bazel-genfiles/'
+        'third_party/dart/project/lib/generated.dart',
+        content: 'fun() {}');
+
+    // No errors.
+    await processedNotification.future;
+    expect(filesErrors[testFile], isEmpty);
+  }
+}
diff --git a/pkg/analysis_server/test/analysis/get_signature_test.dart b/pkg/analysis_server/test/analysis/get_signature_test.dart
index da09214..3eb51ae 100644
--- a/pkg/analysis_server/test/analysis/get_signature_test.dart
+++ b/pkg/analysis_server/test/analysis/get_signature_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:analysis_server/protocol/protocol.dart';
-import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analysis_server/test/analysis/notification_folding_test.dart b/pkg/analysis_server/test/analysis/notification_folding_test.dart
index 892e2af..09a78a5 100644
--- a/pkg/analysis_server/test/analysis/notification_folding_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_folding_test.dart
@@ -4,9 +4,7 @@
 
 import 'dart:async';
 
-import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_constants.dart';
-import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index 8d9c2bb..3ac8da4 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -16,14 +16,13 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AnalysisNotificationHighlightsTest);
-    defineReflectiveTests(HighlightsWithControlFlowCollectionsTest);
-    defineReflectiveTests(HighlightsWithNullSafetyTest);
     defineReflectiveTests(HighlightTypeTest);
   });
 }
 
 @reflectiveTest
-class AnalysisNotificationHighlightsTest extends HighlightsTestSupport {
+class AnalysisNotificationHighlightsTest extends HighlightsTestSupport
+    with WithNonFunctionTypeAliasesMixin {
   Future<void> test_ANNOTATION_hasArguments() async {
     addTestFile('''
 class AAA {
@@ -99,6 +98,42 @@
     assertHasRegion(HighlightRegionType.BUILT_IN, 'await for');
   }
 
+  Future<void> test_BUILT_IN_awaitForIn_list() async {
+    addTestFile('''
+f(a) async {
+  return [await for(var b in a) b];
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'await');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+  }
+
+  Future<void> test_BUILT_IN_awaitForIn_map() async {
+    addTestFile('''
+f(a) async {
+  return {await for(var b in a) b : 0};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'await');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+  }
+
+  Future<void> test_BUILT_IN_awaitForIn_set() async {
+    addTestFile('''
+f(a) async {
+  return {await for(var b in a) b};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'await');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
+  }
+
   Future<void> test_BUILT_IN_deferred() async {
     addTestFile('''
 import 'dart:math' deferred as math;
@@ -151,6 +186,18 @@
     assertNoRegion(HighlightRegionType.BUILT_IN, 'factory = 42');
   }
 
+  Future<void> test_BUILT_IN_Function() async {
+    addTestFile('''
+typedef F = void Function();
+
+void f(void Function() a, Function b) {}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'Function();');
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'Function() a');
+    assertNoRegion(HighlightRegionType.BUILT_IN, 'Function b');
+  }
+
   Future<void> test_BUILT_IN_get() async {
     addTestFile('''
 get aaa => 1;
@@ -345,11 +392,15 @@
   Future<void> test_BUILT_IN_typedef() async {
     addTestFile('''
 typedef A();
+typedef B = void Function();
+typedef C = List<int>;
 main() {
   var typedef = 42;
 }''');
     await prepareHighlights();
     assertHasRegion(HighlightRegionType.BUILT_IN, 'typedef A();');
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'typedef B =');
+    assertHasRegion(HighlightRegionType.BUILT_IN, 'typedef C =');
     assertNoRegion(HighlightRegionType.BUILT_IN, 'typedef = 42');
   }
 
@@ -548,13 +599,15 @@
 
   Future<void> test_FUNCTION_TYPE_ALIAS() async {
     addTestFile('''
-typedef FFF(p);
-main(FFF fff) {
-}
+typedef A();
+typedef B = void Function();
+void f(A a, B b) {}
 ''');
     await prepareHighlights();
-    assertHasRegion(HighlightRegionType.FUNCTION_TYPE_ALIAS, 'FFF(p)');
-    assertHasRegion(HighlightRegionType.FUNCTION_TYPE_ALIAS, 'FFF fff)');
+    assertHasRegion(HighlightRegionType.FUNCTION_TYPE_ALIAS, 'A();');
+    assertHasRegion(HighlightRegionType.FUNCTION_TYPE_ALIAS, 'A a');
+    assertHasRegion(HighlightRegionType.FUNCTION_TYPE_ALIAS, 'B = ');
+    assertHasRegion(HighlightRegionType.FUNCTION_TYPE_ALIAS, 'B b');
   }
 
   Future<void> test_GETTER() async {
@@ -704,6 +757,93 @@
     assertHasRegion(HighlightRegionType.KEYWORD, 'with A;');
   }
 
+  Future<void> test_KEYWORD_const_list() async {
+    addTestFile('''
+var v = const [];
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+  }
+
+  Future<void> test_KEYWORD_const_map() async {
+    addTestFile('''
+var v = const {0 : 1};
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+  }
+
+  Future<void> test_KEYWORD_const_set() async {
+    addTestFile('''
+var v = const {0};
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
+  }
+
+  Future<void> test_KEYWORD_if_list() async {
+    addTestFile('''
+f(a, b) {
+  return [if (a < b) 'a'];
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+  }
+
+  Future<void> test_KEYWORD_if_map() async {
+    addTestFile('''
+f(a, b) {
+  return {if (a < b) 'a' : 1};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+  }
+
+  Future<void> test_KEYWORD_if_set() async {
+    addTestFile('''
+f(a, b) {
+  return {if (a < b) 'a'};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+  }
+
+  Future<void> test_KEYWORD_ifElse_list() async {
+    addTestFile('''
+f(a, b) {
+  return [if (a < b) 'a' else 'b'];
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+  }
+
+  Future<void> test_KEYWORD_ifElse_map() async {
+    addTestFile('''
+f(a, b) {
+  return {if (a < b) 'a' : 1 else 'b' : 2};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+  }
+
+  Future<void> test_KEYWORD_ifElse_set() async {
+    addTestFile('''
+f(a, b) {
+  return {if (a < b) 'a' else 'b'};
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
+    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
+  }
+
   Future<void> test_KEYWORD_ifElse_statement() async {
     addTestFile('''
 f(a, b) {
@@ -715,6 +855,16 @@
     assertHasRegion(HighlightRegionType.KEYWORD, 'else');
   }
 
+  Future<void> test_KEYWORD_late() async {
+    addTestFile('''
+class C {
+  late int x;
+}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'late');
+  }
+
   Future<void> test_KEYWORD_mixin() async {
     addTestFile('''
 mixin M {}
@@ -723,6 +873,14 @@
     assertHasRegion(HighlightRegionType.BUILT_IN, 'mixin');
   }
 
+  Future<void> test_KEYWORD_required() async {
+    addTestFile('''
+void f({required int x}) {}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.KEYWORD, 'required');
+  }
+
   Future<void> test_KEYWORD_void() async {
     addTestFile('''
 void main() {
@@ -971,6 +1129,26 @@
     assertHasRegion(HighlightRegionType.TOP_LEVEL_SETTER_REFERENCE, 'V2 = 3');
   }
 
+  Future<void> test_TYPE_ALIAS_dynamicType() async {
+    addTestFile('''
+typedef A = dynamic;
+void f(A a) {}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.TYPE_ALIAS, 'A =');
+    assertHasRegion(HighlightRegionType.TYPE_ALIAS, 'A a');
+  }
+
+  Future<void> test_TYPE_ALIAS_interfaceType() async {
+    addTestFile('''
+typedef A = List<int>;
+void f(A a) {}
+''');
+    await prepareHighlights();
+    assertHasRegion(HighlightRegionType.TYPE_ALIAS, 'A =');
+    assertHasRegion(HighlightRegionType.TYPE_ALIAS, 'A a');
+  }
+
   Future<void> test_TYPE_NAME_DYNAMIC() async {
     addTestFile('''
 dynamic main() {
@@ -1154,179 +1332,6 @@
 }
 
 @reflectiveTest
-class HighlightsWithControlFlowCollectionsTest extends HighlightsTestSupport {
-  @failingTest
-  Future<void> test_KEYWORD_awaitForIn_list() async {
-    addTestFile('''
-f(a) async {
-  return [await for(var b in a) b];
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'await');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
-  }
-
-  @failingTest
-  Future<void> test_KEYWORD_awaitForIn_map() async {
-    addTestFile('''
-f(a) async {
-  return {await for(var b in a) b : 0};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'await');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
-  }
-
-  @failingTest
-  Future<void> test_KEYWORD_awaitForIn_set() async {
-    addTestFile('''
-f(a) async {
-  return {await for(var b in a) b};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'await');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'for');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'in');
-  }
-
-  Future<void> test_KEYWORD_const_list() async {
-    addTestFile('''
-var v = const [];
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
-  }
-
-  Future<void> test_KEYWORD_const_map() async {
-    addTestFile('''
-var v = const {0 : 1};
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
-  }
-
-  Future<void> test_KEYWORD_const_set() async {
-    addTestFile('''
-var v = const {0};
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'const');
-  }
-
-  Future<void> test_KEYWORD_if_list() async {
-    addTestFile('''
-f(a, b) {
-  return [if (a < b) 'a'];
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-  }
-
-  Future<void> test_KEYWORD_if_map() async {
-    addTestFile('''
-f(a, b) {
-  return {if (a < b) 'a' : 1};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-  }
-
-  Future<void> test_KEYWORD_if_set() async {
-    addTestFile('''
-f(a, b) {
-  return {if (a < b) 'a'};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-  }
-
-  Future<void> test_KEYWORD_ifElse_list() async {
-    addTestFile('''
-f(a, b) {
-  return [if (a < b) 'a' else 'b'];
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
-  }
-
-  Future<void> test_KEYWORD_ifElse_map() async {
-    addTestFile('''
-f(a, b) {
-  return {if (a < b) 'a' : 1 else 'b' : 2};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
-  }
-
-  Future<void> test_KEYWORD_ifElse_set() async {
-    addTestFile('''
-f(a, b) {
-  return {if (a < b) 'a' else 'b'};
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'if');
-    assertHasRegion(HighlightRegionType.KEYWORD, 'else');
-  }
-
-  Future<void> test_LITERAL_LIST() async {
-    addTestFile('var V = <int>[1, 2, 3];');
-    await prepareHighlights();
-    assertHasStringRegion(HighlightRegionType.LITERAL_LIST, '<int>[1, 2, 3]');
-  }
-
-  Future<void> test_LITERAL_MAP() async {
-    addTestFile("var V = const <int, String>{1: 'a', 2: 'b', 3: 'c'};");
-    await prepareHighlights();
-    assertHasStringRegion(HighlightRegionType.LITERAL_MAP,
-        "const <int, String>{1: 'a', 2: 'b', 3: 'c'}");
-  }
-}
-
-@reflectiveTest
-class HighlightsWithNullSafetyTest extends HighlightsTestSupport {
-  @override
-  void createProject({Map<String, String> packageRoots}) {
-    addAnalysisOptionsFile('''
-analyzer:
-  enable-experiment:
-    - non-nullable
-''');
-    super.createProject(packageRoots: packageRoots);
-  }
-
-  Future<void> test_KEYWORD_late() async {
-    addTestFile('''
-class C {
-  late int x;
-}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'late');
-  }
-
-  Future<void> test_KEYWORD_required() async {
-    addTestFile('''
-void f({required int x}) {}
-''');
-    await prepareHighlights();
-    assertHasRegion(HighlightRegionType.KEYWORD, 'required');
-  }
-}
-
-@reflectiveTest
 class HighlightTypeTest {
   void test_constructor() {
     expect(HighlightRegionType.CLASS,
diff --git a/pkg/analysis_server/test/analysis/test_all.dart b/pkg/analysis_server/test/analysis/test_all.dart
index 1187065..3329d7f 100644
--- a/pkg/analysis_server/test/analysis/test_all.dart
+++ b/pkg/analysis_server/test/analysis/test_all.dart
@@ -4,6 +4,7 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'bazel_changes_test.dart' as bazel_changes;
 import 'get_errors_test.dart' as get_errors;
 import 'get_hover_test.dart' as get_hover;
 import 'get_navigation_test.dart' as get_navigation;
@@ -26,6 +27,7 @@
 
 void main() {
   defineReflectiveSuite(() {
+    bazel_changes.main();
     get_errors.main();
     get_hover.main();
     get_navigation.main();
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index dd5d637..5614cd3 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -227,3 +227,27 @@
     return serverChannel.sendRequest(request, throwOnError: throwOnError);
   }
 }
+
+mixin WithNonFunctionTypeAliasesMixin on AbstractAnalysisTest {
+  @override
+  void createProject({Map<String, String> packageRoots}) {
+    addAnalysisOptionsFile('''
+analyzer:
+  enable-experiment:
+    - nonfunction-type-aliases
+''');
+    super.createProject(packageRoots: packageRoots);
+  }
+}
+
+mixin WithNullSafetyMixin on AbstractAnalysisTest {
+  @override
+  void createProject({Map<String, String> packageRoots}) {
+    addAnalysisOptionsFile('''
+analyzer:
+  enable-experiment:
+    - non-nullable
+''');
+    super.createProject(packageRoots: packageRoots);
+  }
+}
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index bb5fa96..26306df 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -1466,6 +1466,9 @@
 class num{}class Sunflower {static final n!2um MAX_D = 300;nu!3m xc, yc;Sun!4flower() {x!Xc = y!Yc = MA!1 }}''',
         <String>['1+MAX_D', 'X+xc', 'Y+yc', '2+num', '3+num', '4+Sunflower']);
 
+    buildTests('testCompletion_staticField_withoutVarOrFinal', '''
+class num{}class Sunflower {static n!1}''', <String>['1+num']);
+
     buildTests('testCompletion_super_superType', '''
 class A {
   var fa;
diff --git a/pkg/analysis_server/test/completion_test_support.dart b/pkg/analysis_server/test/completion_test_support.dart
index 2221945..4cc0967 100644
--- a/pkg/analysis_server/test/completion_test_support.dart
+++ b/pkg/analysis_server/test/completion_test_support.dart
@@ -7,10 +7,10 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 
-import 'domain_completion_test.dart';
+import 'domain_completion_util.dart';
 
 /// A base class for classes containing completion tests.
-class CompletionTestCase extends CompletionDomainHandlerListTokenDetailsTest {
+class CompletionTestCase extends AbstractCompletionDomainTest {
   static const String CURSOR_MARKER = '!';
 
   List get suggestedCompletions => suggestions
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 8b50d8f..61e3ffa 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2325,6 +2325,9 @@
   }
 
   @override
+  void afterContextRefresh() {}
+
+  @override
   void afterWatchEvent(WatchEvent event) {}
 
   @override
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index e72baca..3d49664 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -19,7 +19,6 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(CompletionDomainHandlerGetSuggestionsTest);
-    defineReflectiveTests(CompletionDomainHandlerListTokenDetailsTest);
   });
 }
 
@@ -778,419 +777,6 @@
   }
 }
 
-@reflectiveTest
-class CompletionDomainHandlerListTokenDetailsTest
-    extends AbstractCompletionDomainTest {
-  String testFileUri;
-
-  Future<void> expectTokens(String content, List<TokenDetails> expected) async {
-    newFile(testFile, content: content);
-    var request = CompletionListTokenDetailsParams(testFile).toRequest('0');
-    var response = await waitResponse(request);
-    List<Map<String, dynamic>> tokens = response.result['tokens'];
-    _compareTokens(tokens, expected);
-  }
-
-  @override
-  void setUp() {
-    super.setUp();
-    testFileUri = toUriStr(testFile);
-  }
-
-  Future<void> test_classDeclaration() async {
-    await expectTokens('''
-class A {}
-class B extends A {}
-class C implements B {}
-class D with C {}
-''', [
-      token('class', 0, null, null),
-      token('A', 6, 'Type',
-          ['declaration']), //token('A', 6, 'dart:core;Type', ['declaration']),
-      token('{', 8, null, null),
-      token('}', 9, null, null),
-      token('class', 11, null, null),
-      token('B', 17, 'Type',
-          ['declaration']), //token('B', 17, 'dart:core;Type', ['declaration']),
-      token('extends', 19, null, null),
-      token('A', 27, 'dart:core;Type<A>', [
-        'reference'
-      ]), //token('A', 27, 'dart:core;Type<$testFileUri;A>', ['reference']),
-      token('{', 29, null, null),
-      token('}', 30, null, null),
-      token('class', 32, null, null),
-      token('C', 38, 'Type',
-          ['declaration']), //token('C', 38, 'dart:core;Type', ['declaration']),
-      token('implements', 40, null, null),
-      token('B', 51, 'dart:core;Type<B>', [
-        'reference'
-      ]), //token('B', 51, 'dart:core;Type<$testFileUri;B>', ['reference']),
-      token('{', 53, null, null),
-      token('}', 54, null, null),
-      token('class', 56, null, null),
-      token('D', 62, 'Type',
-          ['declaration']), //token('D', 62, 'dart:core;Type', ['declaration']),
-      token('with', 64, null, null),
-      token('C', 69, 'dart:core;Type<C>', [
-        'reference'
-      ]), //token('C', 69, 'dart:core;Type<$testFileUri;C>', ['reference']),
-      token('{', 71, null, null),
-      token('}', 72, null, null),
-    ]);
-  }
-
-  Future<void> test_genericType() async {
-    await expectTokens('''
-List<int> x = null;
-''', [
-      token('List', 0, 'dart:core;Type<List>', [
-        'reference'
-      ]), //token('List', 0, 'dart:core;Type<dart:core;List>', ['reference']),
-      token('<', 4, null, null),
-      token('int', 5, 'dart:core;Type<int>', [
-        'reference'
-      ]), //token('int', 5, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('>', 8, null, null),
-      token('x', 10, 'List',
-          ['declaration']), //token('x', 10, 'dart:core;List', ['declaration']),
-      token('=', 12, null, null),
-      token('null', 14, null, null),
-      token(';', 18, null, null),
-    ]);
-  }
-
-  Future<void> test_getterInvocation() async {
-    await expectTokens('''
-var x = 'a'.length;
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'int',
-          ['declaration']), //token('x', 4, 'dart:core;int', ['declaration']),
-      token('=', 6, null, null),
-      token("'a'", 8, 'String',
-          null), //token("'a'", 8, 'dart:core;String', null),
-      token('.', 11, null, null),
-      token('length', 12, 'int',
-          ['reference']), //token('length', 12, 'dart:core;int', ['reference']),
-      token(';', 18, null, null),
-    ]);
-  }
-
-  Future<void> test_literal_bool() async {
-    await expectTokens('''
-var x = true;
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'bool',
-          ['declaration']), //token('x', 4, 'dart:core;bool', ['declaration']),
-      token('=', 6, null, null),
-      token(
-          'true', 8, 'bool', null), //token('true', 8, 'dart:core;bool', null),
-      token(';', 12, null, null),
-    ]);
-  }
-
-  Future<void> test_literal_double() async {
-    await expectTokens('''
-var x = 3.4;
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'double', [
-        'declaration'
-      ]), //token('x', 4, 'dart:core;double', ['declaration']),
-      token('=', 6, null, null),
-      token('3.4', 8, 'double',
-          null), //token('3.4', 8, 'dart:core;double', null),
-      token(';', 11, null, null),
-    ]);
-  }
-
-  Future<void> test_literal_int() async {
-    await expectTokens('''
-var x = 7;
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'int',
-          ['declaration']), //token('x', 4, 'dart:core;int', ['declaration']),
-      token('=', 6, null, null),
-      token('7', 8, 'int', null), //token('7', 8, 'dart:core;int', null),
-      token(';', 9, null, null),
-    ]);
-  }
-
-  Future<void> test_literal_list() async {
-    await expectTokens('''
-var x = <int>[];
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'List',
-          ['declaration']), //token('x', 4, 'dart:core;List', ['declaration']),
-      token('=', 6, null, null),
-      token('<', 8, null, null),
-      token('int', 9, 'dart:core;Type<int>', [
-        'reference'
-      ]), //token("int", 9, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('>', 12, null, null),
-      token('[', 13, null, null),
-      token(']', 14, null, null),
-      token(';', 15, null, null),
-    ]);
-  }
-
-  Future<void> test_literal_map() async {
-    await expectTokens('''
-var x = <int, int>{};
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'Map',
-          ['declaration']), //token('x', 4, 'dart:core;Map', ['declaration']),
-      token('=', 6, null, null),
-      token('<', 8, null, null),
-      token('int', 9, 'dart:core;Type<int>', [
-        'reference'
-      ]), //token("int", 9, 'dart:core;Type<dart:core;int>', ['reference']),
-//      token(',', null, null),
-      token('int', 14, 'dart:core;Type<int>', [
-        'reference'
-      ]), //token("int", 14, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('>', 17, null, null),
-      token('{', 18, null, null),
-      token('}', 19, null, null),
-      token(';', 20, null, null),
-    ]);
-  }
-
-  Future<void> test_literal_null() async {
-    await expectTokens('''
-var x = null;
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'dynamic', ['declaration']),
-      token('=', 6, null, null),
-      token('null', 8, null, null),
-      token(';', 12, null, null),
-    ]);
-  }
-
-  Future<void> test_literal_set() async {
-    await expectTokens('''
-var x = <int>{};
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'Set',
-          ['declaration']), //token('x', 4, 'dart:core;Set', ['declaration']),
-      token('=', 6, null, null),
-      token('<', 8, null, null),
-      token('int', 9, 'dart:core;Type<int>', [
-        'reference'
-      ]), //token("int", 9, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('>', 12, null, null),
-      token('{', 13, null, null),
-      token('}', 14, null, null),
-      token(';', 15, null, null),
-    ]);
-  }
-
-  Future<void> test_literal_string() async {
-    await expectTokens('''
-var x = 'a';
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'String', [
-        'declaration'
-      ]), //token('x', 4, 'dart:core;String', ['declaration']),
-      token('=', 6, null, null),
-      token("'a'", 8, 'String',
-          null), //token("'a'", 8, 'dart:core;String', null),
-      token(';', 11, null, null),
-    ]);
-  }
-
-  Future<void> test_methodDeclaration() async {
-    await expectTokens('''
-class A {
-  String c(int x, int y) {}
-}
-''', [
-      token('class', 0, null, null),
-      token('A', 6, 'Type', ['declaration']),
-      //token('A', 6, 'dart:core;Type', ['declaration']),
-      token('{', 8, null, null),
-      token('String', 12, 'dart:core;Type<String>', ['reference']),
-      //token('String', 12, 'dart:core;Type<dart:core;String>', ['reference']),
-      token('c', 19, 'String Function(int, int)',
-          //'dart:core;String Function(dart:core;int, dart:core;int)',
-          ['declaration']),
-      token('(', 20, null, null),
-      token('int', 21, 'dart:core;Type<int>', ['reference']),
-      //token('int', 21, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('x', 25, 'int', ['declaration']),
-      //token('x', 25, 'dart:core;int', ['declaration']),
-//      token(',', null, null),
-      token('int', 28, 'dart:core;Type<int>', ['reference']),
-      //token('int', 28, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('y', 32, 'int', ['declaration']),
-      //token('y', 32, 'dart:core;int', ['declaration']),
-      token(')', 33, null, null),
-      token('{', 35, null, null),
-      token('}', 36, null, null),
-      token('}', 38, null, null),
-    ]);
-  }
-
-  Future<void> test_methodInvocation() async {
-    await expectTokens('''
-var x = 'radar'.indexOf('r', 1);
-''', [
-      token('var', 0, null, null),
-      token('x', 4, 'int',
-          ['declaration']), //token('x', 4, 'dart:core;int', ['declaration']),
-      token('=', 6, null, null),
-      token("'radar'", 8, 'String',
-          null), //token("'radar'", 8, 'dart:core;String', null),
-      token('.', 15, null, null),
-      token('indexOf', 16, 'int Function(Pattern, int)',
-          //'dart:core;int Function(dart:core;Pattern, dart:core;int)',
-          ['reference']),
-      token('(', 23, null, null),
-      token("'r'", 24, 'String',
-          null), //token("'r'", 24, 'dart:core;String', null),
-//      token(',', null, null),
-      token('1', 29, 'int', null), //token('1', 29, 'dart:core;int', null),
-      token(')', 30, null, null),
-      token(';', 31, null, null),
-    ]);
-  }
-
-  Future<void> test_mixinDeclaration() async {
-    await expectTokens('''
-class A {}
-class B {}
-mixin D on A implements B {}
-''', [
-      token('class', 0, null, null),
-      token('A', 6, 'Type',
-          ['declaration']), //token('A', 6, 'dart:core;Type', ['declaration']),
-      token('{', 8, null, null),
-      token('}', 9, null, null),
-      token('class', 11, null, null),
-      token('B', 17, 'Type',
-          ['declaration']), //token('B', 17, 'dart:core;Type', ['declaration']),
-      token('{', 19, null, null),
-      token('}', 20, null, null),
-      token('mixin', 22, null, null),
-      token('D', 28, 'Type',
-          ['declaration']), //token('D', 28, 'dart:core;Type', ['declaration']),
-      token('on', 30, null, null),
-      token('A', 33, 'dart:core;Type<A>', [
-        'reference'
-      ]), //token('A', 33, 'dart:core;Type<$testFileUri;A>', ['reference']),
-      token('implements', 35, null, null),
-      token('B', 46, 'dart:core;Type<B>', [
-        'reference'
-      ]), //token('B', 'dart:core;Type<$testFileUri;B>', ['reference']),
-      token('{', 48, null, null),
-      token('}', 49, null, null),
-    ]);
-  }
-
-  Future<void> test_parameterReference() async {
-    await expectTokens('''
-int f(int p) {
-  return p;
-}
-''', [
-      token('int', 0, 'dart:core;Type<int>', ['reference']),
-      //token('int', 0, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('f', 4, 'int Function(int)', ['declaration']),
-      //token('f', 4, 'dart:core;int Function(dart:core;int)', ['declaration']),
-      token('(', 5, null, null),
-      token('int', 6, 'dart:core;Type<int>', ['reference']),
-      //token('int', 6, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('p', 10, 'int', ['declaration']),
-      //token('p', 10, 'dart:core;int', ['declaration']),
-      token(')', 11, null, null),
-      token('{', 13, null, null),
-      token('return', 17, null, null),
-      token('p', 24, 'int', ['reference']),
-      //token('p', 24, 'dart:core;int', ['reference']),
-      token(';', 25, null, null),
-      token('}', 27, null, null),
-    ]);
-  }
-
-  Future<void> test_topLevelVariable_withDocComment() async {
-    await expectTokens('''
-/// Doc comment [x] with reference.
-int x;
-''', [
-      token('int', 36, 'dart:core;Type<int>', [
-        'reference'
-      ]), //token('int', 36, 'dart:core;Type<dart:core;int>', ['reference']),
-      token('x', 40, 'int',
-          ['declaration']), //token('x', 40, 'dart:core;int', ['declaration']),
-      token(';', 41, null, null),
-    ]);
-  }
-
-  TokenDetails token(
-      String lexeme, int offset, String type, List<String> kinds) {
-    return TokenDetails(lexeme, offset, type: type, validElementKinds: kinds);
-  }
-
-  void _compareTokens(List<Map<String, dynamic>> actualTokens,
-      List<TokenDetails> expectedTokens) {
-    var length = expectedTokens.length;
-    expect(actualTokens, hasLength(length));
-    var errors = <String>[];
-    for (var i = 0; i < length; i++) {
-      var actual = actualTokens[i];
-      var expected = expectedTokens[i];
-      if (actual['lexeme'] != expected.lexeme) {
-        errors.add('Lexeme at $i: '
-            'expected "${expected.lexeme}", '
-            'actual "${actual['lexeme']}"');
-      }
-      if (actual['offset'] != expected.offset) {
-        errors.add('Offset at $i: ("${expected.lexeme}"): '
-            'expected "${expected.offset}", '
-            'actual "${actual['offset']}"');
-      }
-      if (actual['type'] != expected.type) {
-        errors.add('Type at $i ("${expected.lexeme}"): '
-            'expected "${expected.type}", '
-            'actual "${actual['type']}"');
-      }
-      if (_differentKinds(
-          actual['validElementKinds'], expected.validElementKinds)) {
-        errors.add('Kinds at $i ("${expected.lexeme}"): '
-            'expected "${expected.validElementKinds}", '
-            'actual "${actual['validElementKinds']}"');
-      }
-    }
-    expect(errors, isEmpty);
-  }
-
-  /// Return `true` if the two lists of kinds are different.
-  bool _differentKinds(List<String> actual, List<String> expected) {
-    if (actual == null) {
-      return expected != null;
-    } else if (expected == null) {
-      return true;
-    }
-    var expectedLength = expected.length;
-    if (actual.length != expectedLength) {
-      return true;
-    }
-    for (var i = 0; i < expectedLength; i++) {
-      if (actual[i] != expected[i]) {
-        return true;
-      }
-    }
-    return false;
-  }
-}
-
 class MockRelevancySorter implements DartContributionSorter {
   bool enabled = true;
 
diff --git a/pkg/analysis_server/test/edit/test_all.dart b/pkg/analysis_server/test/edit/test_all.dart
index 7950e43..21cf0bc 100644
--- a/pkg/analysis_server/test/edit/test_all.dart
+++ b/pkg/analysis_server/test/edit/test_all.dart
@@ -13,7 +13,6 @@
 import 'refactoring_test.dart' as refactoring;
 import 'sort_members_test.dart' as sort_members;
 import 'statement_completion_test.dart' as statement_completion;
-import 'token_details_test.dart' as token_details;
 
 void main() {
   defineReflectiveSuite(() {
@@ -26,6 +25,5 @@
     refactoring.main();
     sort_members.main();
     statement_completion.main();
-    token_details.main();
   }, name: 'edit');
 }
diff --git a/pkg/analysis_server/test/edit/token_details_test.dart b/pkg/analysis_server/test/edit/token_details_test.dart
deleted file mode 100644
index 0516889..0000000
--- a/pkg/analysis_server/test/edit/token_details_test.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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:analysis_server/protocol/protocol_generated.dart';
-import 'package:analysis_server/src/domain_completion.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../analysis_abstract.dart';
-
-void main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(CompletionListTokenDetailsTest);
-  });
-}
-
-@reflectiveTest
-class CompletionListTokenDetailsTest extends AbstractAnalysisTest {
-  CompletionDomainHandler completionHandler;
-
-  Future<CompletionListTokenDetailsResult> getTokenDetails() async {
-    var params = CompletionListTokenDetailsParams(testFile);
-    await completionHandler.listTokenDetails(params.toRequest('0'));
-    var response = await serverChannel.responseController.stream.first;
-    return CompletionListTokenDetailsResult.fromResponse(response);
-  }
-
-  @override
-  void setUp() {
-    super.setUp();
-    completionHandler = CompletionDomainHandler(server);
-  }
-
-  Future<void> test_packageUri() async {
-    newFile('/project/.packages', content: '''
-project:lib/
-''');
-    newFile('/project/lib/c.dart', content: '''
-class C {}
-''');
-    addTestFile('''
-import 'package:project/c.dart';
-
-C c;
-''');
-    createProject();
-    var result = await getTokenDetails();
-    var tokens = result.tokens;
-    expect(tokens, hasLength(6));
-  }
-}
diff --git a/pkg/analysis_server/test/integration/completion/list_token_details_test.dart b/pkg/analysis_server/test/integration/completion/list_token_details_test.dart
deleted file mode 100644
index 227fc83..0000000
--- a/pkg/analysis_server/test/integration/completion/list_token_details_test.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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:analysis_server/protocol/protocol_generated.dart';
-import 'package:path/path.dart' as path;
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../support/integration_tests.dart';
-
-void main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ListTokenDetailsTest);
-  });
-}
-
-@reflectiveTest
-class ListTokenDetailsTest extends AbstractAnalysisServerIntegrationTest {
-  String testPackagePath;
-
-  @override
-  Future setUp() async {
-    await super.setUp();
-    testPackagePath = path.join(sourceDirectory.path, 'test_package');
-  }
-
-  @override
-  Future standardAnalysisSetup({bool subscribeStatus = true}) {
-    var futures = <Future>[];
-    if (subscribeStatus) {
-      futures.add(sendServerSetSubscriptions([ServerService.STATUS]));
-    }
-    futures.add(sendAnalysisSetAnalysisRoots([testPackagePath], []));
-    return Future.wait(futures);
-  }
-
-  Future<void> test_getSuggestions() async {
-    var aPath = path.join(sourceDirectory.path, 'a');
-    var aLibPath = path.join(aPath, 'lib');
-    writeFile(path.join(aLibPath, 'a.dart'), '''
-class A {}
-''');
-    writeFile(path.join(testPackagePath, '.packages'), '''
-a:file://${path.toUri(aLibPath)}
-test_package:lib/
-''');
-    var testFilePath = path.join(testPackagePath, 'lib', 'test.dart');
-    writeFile(testFilePath, '''
-import 'package:a/a.dart';
-class B {}
-String f(A a, B b) => a.toString() + b.toString();
-''');
-    await standardAnalysisSetup();
-    await analysisFinished;
-
-    var result = await sendCompletionListTokenDetails(testFilePath);
-    expect(result, isNotNull);
-  }
-}
diff --git a/pkg/analysis_server/test/integration/completion/test_all.dart b/pkg/analysis_server/test/integration/completion/test_all.dart
index 0462e31..857202f 100644
--- a/pkg/analysis_server/test/integration/completion/test_all.dart
+++ b/pkg/analysis_server/test/integration/completion/test_all.dart
@@ -5,11 +5,9 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'get_suggestions_test.dart' as get_suggestions;
-import 'list_token_details_test.dart' as list_token_details;
 
 void main() {
   defineReflectiveSuite(() {
     get_suggestions.main();
-    list_token_details.main();
   }, name: 'completion');
 }
diff --git a/pkg/analysis_server/test/integration/coverage.md b/pkg/analysis_server/test/integration/coverage.md
index 06b628a..38705c6 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -34,7 +34,6 @@
 - [ ] completion.existingImports
 - [ ] completion.getSuggestionDetails
 - [x] completion.getSuggestions
-- [x] completion.listTokenDetails
 - [ ] completion.registerLibraryPaths
 - [ ] completion.results
 - [ ] completion.setSubscriptions
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index 27c7687..b086276c4 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1046,30 +1046,6 @@
         decoder, 'result', result);
   }
 
-  /// Inspect analysis server's knowledge about all of a file's tokens
-  /// including their lexeme, type, and what element kinds would have been
-  /// appropriate for the token's program location.
-  ///
-  /// Parameters
-  ///
-  /// file: FilePath
-  ///
-  ///   The path to the file from which tokens should be returned.
-  ///
-  /// Returns
-  ///
-  /// tokens: List<TokenDetails>
-  ///
-  ///   A list of the file's scanned tokens including analysis information
-  ///   about them.
-  Future<CompletionListTokenDetailsResult> sendCompletionListTokenDetails(
-      String file) async {
-    var params = CompletionListTokenDetailsParams(file).toJson();
-    var result = await server.send('completion.listTokenDetails', params);
-    var decoder = ResponseDecoder(null);
-    return CompletionListTokenDetailsResult.fromJson(decoder, 'result', result);
-  }
-
   /// Reports the completion suggestions that should be presented to the user.
   /// The set of suggestions included in the notification is always a complete
   /// list that supersedes any previously reported suggestions.
@@ -1582,6 +1558,15 @@
   ///   analysis.setAnalysisRoots), an error of type FILE_NOT_ANALYZED will be
   ///   generated.
   ///
+  /// inTestMode: bool (optional)
+  ///
+  ///   A flag indicating whether the bulk fixes are being run in test mode.
+  ///   The only difference is that in test mode the fix processor will look
+  ///   for a configuration file that can modify the content of the data file
+  ///   used to compute the fixes when data-driven fixes are being considered.
+  ///
+  ///   If this field is omitted the flag defaults to false.
+  ///
   /// Returns
   ///
   /// edits: List<SourceFileEdit>
@@ -1592,8 +1577,9 @@
   ///
   ///   Details that summarize the fixes associated with the recommended
   ///   changes.
-  Future<EditBulkFixesResult> sendEditBulkFixes(List<String> included) async {
-    var params = EditBulkFixesParams(included).toJson();
+  Future<EditBulkFixesResult> sendEditBulkFixes(List<String> included,
+      {bool inTestMode}) async {
+    var params = EditBulkFixesParams(included, inTestMode: inTestMode).toJson();
     var result = await server.send('edit.bulkFixes', params);
     var decoder = ResponseDecoder(null);
     return EditBulkFixesResult.fromJson(decoder, 'result', result);
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 464139d..354583b 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -448,6 +448,7 @@
 ///   PREFIX
 ///   SETTER
 ///   TOP_LEVEL_VARIABLE
+///   TYPE_ALIAS
 ///   TYPE_PARAMETER
 ///   UNIT_TEST_GROUP
 ///   UNIT_TEST_TEST
@@ -477,6 +478,7 @@
   'PREFIX',
   'SETTER',
   'TOP_LEVEL_VARIABLE',
+  'TYPE_ALIAS',
   'TYPE_PARAMETER',
   'UNIT_TEST_GROUP',
   'UNIT_TEST_TEST',
@@ -723,6 +725,7 @@
 ///   ANNOTATIONS
 ///   BLOCK
 ///   CLASS_BODY
+///   COMMENT
 ///   DIRECTIVES
 ///   DOCUMENTATION_COMMENT
 ///   FILE_HEADER
@@ -734,6 +737,7 @@
   'ANNOTATIONS',
   'BLOCK',
   'CLASS_BODY',
+  'COMMENT',
   'DIRECTIVES',
   'DOCUMENTATION_COMMENT',
   'FILE_HEADER',
@@ -844,6 +848,7 @@
 ///   TOP_LEVEL_SETTER_DECLARATION
 ///   TOP_LEVEL_SETTER_REFERENCE
 ///   TOP_LEVEL_VARIABLE_DECLARATION
+///   TYPE_ALIAS
 ///   TYPE_NAME_DYNAMIC
 ///   TYPE_PARAMETER
 ///   UNRESOLVED_INSTANCE_MEMBER_REFERENCE
@@ -919,6 +924,7 @@
   'TOP_LEVEL_SETTER_DECLARATION',
   'TOP_LEVEL_SETTER_REFERENCE',
   'TOP_LEVEL_VARIABLE_DECLARATION',
+  'TYPE_ALIAS',
   'TYPE_NAME_DYNAMIC',
   'TYPE_PARAMETER',
   'UNRESOLVED_INSTANCE_MEMBER_REFERENCE',
@@ -1623,23 +1629,6 @@
     'SourceFileEdit',
     {'file': isFilePath, 'fileStamp': isInt, 'edits': isListOf(isSourceEdit)}));
 
-/// TokenDetails
-///
-/// {
-///   "lexeme": String
-///   "type": optional String
-///   "validElementKinds": optional List<String>
-///   "offset": int
-/// }
-final Matcher isTokenDetails = LazyMatcher(() => MatchesJsonObject(
-        'TokenDetails', {
-      'lexeme': isString,
-      'offset': isInt
-    }, optionalFields: {
-      'type': isString,
-      'validElementKinds': isListOf(isString)
-    }));
-
 /// TypeHierarchyItem
 ///
 /// {
@@ -2132,24 +2121,6 @@
     MatchesJsonObject(
         'completion.getSuggestions result', {'id': isCompletionId}));
 
-/// completion.listTokenDetails params
-///
-/// {
-///   "file": FilePath
-/// }
-final Matcher isCompletionListTokenDetailsParams = LazyMatcher(() =>
-    MatchesJsonObject(
-        'completion.listTokenDetails params', {'file': isFilePath}));
-
-/// completion.listTokenDetails result
-///
-/// {
-///   "tokens": List<TokenDetails>
-/// }
-final Matcher isCompletionListTokenDetailsResult = LazyMatcher(() =>
-    MatchesJsonObject('completion.listTokenDetails result',
-        {'tokens': isListOf(isTokenDetails)}));
-
 /// completion.registerLibraryPaths params
 ///
 /// {
@@ -2241,9 +2212,11 @@
 ///
 /// {
 ///   "included": List<FilePath>
+///   "inTestMode": optional bool
 /// }
 final Matcher isEditBulkFixesParams = LazyMatcher(() => MatchesJsonObject(
-    'edit.bulkFixes params', {'included': isListOf(isFilePath)}));
+    'edit.bulkFixes params', {'included': isListOf(isFilePath)},
+    optionalFields: {'inTestMode': isBool}));
 
 /// edit.bulkFixes result
 ///
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 0db9f8d..bd236eb 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -17,6 +17,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(ExtractMethodRefactorCodeActionsTest);
     defineReflectiveTests(ExtractWidgetRefactorCodeActionsTest);
+    defineReflectiveTests(ExtractVariableRefactorCodeActionsTest);
   });
 }
 
@@ -158,6 +159,38 @@
         req1, throwsA(isResponseError(ErrorCodes.ContentModified)));
   }
 
+  Future<void> test_generatesNames() async {
+    const content = '''
+Object main() {
+  return Container([[Text('Test!')]]);
+}
+
+Object Container(Object text) => null;
+Object Text(Object text) => null;
+    ''';
+    const expectedContent = '''
+Object main() {
+  return Container(text());
+}
+
+Object text() => Text('Test!');
+
+Object Container(Object text) => null;
+Object Text(Object text) => null;
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
+    expect(codeAction, isNotNull);
+
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+  }
+
   Future<void> test_invalidLocation() async {
     const content = '''
 import 'dart:convert';
@@ -297,6 +330,71 @@
 }
 
 @reflectiveTest
+class ExtractVariableRefactorCodeActionsTest extends AbstractCodeActionsTest {
+  final extractVariableTitle = 'Extract Local Variable';
+
+  Future<void> test_appliesCorrectEdits() async {
+    const content = '''
+main() {
+  foo([[1 + 2]]);
+}
+
+void foo(int arg) {}
+    ''';
+    const expectedContent = '''
+main() {
+  var arg = 1 + 2;
+  foo(arg);
+}
+
+void foo(int arg) {}
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction = findCommand(
+        codeActions, Commands.performRefactor, extractVariableTitle);
+    expect(codeAction, isNotNull);
+
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+  }
+
+  Future<void> test_doesNotCreateNameConflicts() async {
+    const content = '''
+main() {
+  var arg = "test";
+  foo([[1 + 2]]);
+}
+
+void foo(int arg) {}
+    ''';
+    const expectedContent = '''
+main() {
+  var arg = "test";
+  var arg2 = 1 + 2;
+  foo(arg2);
+}
+
+void foo(int arg) {}
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction = findCommand(
+        codeActions, Commands.performRefactor, extractVariableTitle);
+    expect(codeAction, isNotNull);
+
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+  }
+}
+
+@reflectiveTest
 class ExtractWidgetRefactorCodeActionsTest extends AbstractCodeActionsTest {
   final extractWidgetTitle = 'Extract Widget';
 
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index f71db6c..2214c75 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -31,11 +31,21 @@
     );
   }
 
+  @override
+  void setUp() {
+    super.setUp();
+    writePackageConfig(
+      projectFolderPath,
+      flutter: true,
+    );
+  }
+
   Future<void> test_commitCharacter_completionItem() async {
     await provideConfig(
       () => initialize(
-        textDocumentCapabilities: withAllSupportedDynamicRegistrations(
-            emptyTextDocumentClientCapabilities),
+        textDocumentCapabilities:
+            withAllSupportedTextDocumentDynamicRegistrations(
+                emptyTextDocumentClientCapabilities),
         workspaceCapabilities:
             withConfigurationSupport(emptyWorkspaceClientCapabilities),
       ),
@@ -63,8 +73,9 @@
       () => monitorDynamicRegistrations(
         registrations,
         () => initialize(
-            textDocumentCapabilities: withAllSupportedDynamicRegistrations(
-                emptyTextDocumentClientCapabilities),
+            textDocumentCapabilities:
+                withAllSupportedTextDocumentDynamicRegistrations(
+                    emptyTextDocumentClientCapabilities),
             workspaceCapabilities:
                 withDidChangeConfigurationDynamicRegistration(
                     withConfigurationSupport(
@@ -122,6 +133,55 @@
     );
   }
 
+  Future<void> test_completeFunctionCalls_flutterSetState() async {
+    // Flutter's setState method has special handling inside SuggestionBuilder
+    // that already adds in a selection (which overlaps with completeFunctionCalls).
+    // Ensure we don't end up with two sets of parens/placeholders in this case.
+    final content = '''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatefulWidget {
+  @override
+  _MyWidgetState createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+  @override
+  Widget build(BuildContext context) {
+    [[setSt^]]
+    return Container();
+  }
+}
+    ''';
+
+    await provideConfig(
+      () => initialize(
+        textDocumentCapabilities: withCompletionItemSnippetSupport(
+            emptyTextDocumentClientCapabilities),
+        workspaceCapabilities:
+            withConfigurationSupport(emptyWorkspaceClientCapabilities),
+      ),
+      {'completeFunctionCalls': true},
+    );
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+    final item = res.singleWhere((c) => c.label.startsWith('setState('));
+
+    // Usually the label would be "setState(…)" but here it's slightly different
+    // to indicate a full statement is being inserted.
+    expect(item.label, equals('setState(() {});'));
+
+    // Ensure the snippet comes through in the expected format with the expected
+    // placeholders.
+    expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
+    expect(item.insertText, equals('setState(() {\n      \${0:}\n    \\});'));
+    expect(item.textEdit.newText, equals(item.insertText));
+    expect(
+      item.textEdit.range,
+      equals(rangeFromMarkers(content)),
+    );
+  }
+
   Future<void> test_completeFunctionCalls_noRequiredParameters() async {
     final content = '''
     void myFunction({int a}) {}
@@ -1398,10 +1458,7 @@
   @override
   String get testPackageLanguageVersion => latestLanguageVersion;
 
-  @failingTest
   Future<void> test_completeFunctionCalls_requiredNamed() async {
-    // TODO(dantup): Find out how we can tell this parameter is required
-    // (in the completion mapping).
     final content = '''
     void myFunction(String a, int b, {required String c, String d = ''}) {}
 
@@ -1425,11 +1482,55 @@
     // Ensure the snippet comes through in the expected format with the expected
     // placeholders.
     expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
-    expect(item.insertText, equals(r'myFunction(${1:a}, ${2:b}, ${2:c})'));
+    expect(item.insertText, equals(r'myFunction(${1:a}, ${2:b}, c: ${3:c})'));
     expect(item.textEdit.newText, equals(item.insertText));
     expect(
       item.textEdit.range,
       equals(rangeFromMarkers(content)),
     );
   }
+
+  Future<void> test_completeFunctionCalls_requiredNamed_suggestionSet() async {
+    final otherFile = join(projectFolderPath, 'lib', 'other.dart');
+    newFile(
+      otherFile,
+      content:
+          "void myFunction(String a, int b, {required String c, String d = ''}) {}",
+    );
+    final content = '''
+    main() {
+      [[myFu^]]
+    }
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    await provideConfig(
+      () => initialize(
+        textDocumentCapabilities: withCompletionItemSnippetSupport(
+            emptyTextDocumentClientCapabilities),
+        workspaceCapabilities: withApplyEditSupport(
+            withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+      ),
+      {'completeFunctionCalls': true},
+    );
+    await openFile(mainFileUri, withoutMarkers(content));
+    await initialAnalysis;
+
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+    final item = res.singleWhere((c) => c.label == 'myFunction(…)');
+    // Ensure the snippet comes through in the expected format with the expected
+    // placeholders.
+    expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
+    expect(item.insertText, equals(r'myFunction(${1:a}, ${2:b}, c: ${3:c})'));
+    expect(item.textEdit, isNull);
+
+    // Ensure the item can be resolved and gets a proper TextEdit.
+    final resolved = await resolveCompletion(item);
+    expect(resolved.textEdit, isNotNull);
+    expect(resolved.textEdit.newText, equals(item.insertText));
+    expect(
+      resolved.textEdit.range,
+      equals(rangeFromMarkers(content)),
+    );
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index d2555e9..5adeef9 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -285,16 +285,63 @@
 
   Future<void> test_todos() async {
     // TODOs only show up if there's also some code in the file.
-    const initialContents = '''
+    const contents = '''
     // TODO: This
     String a = "";
     ''';
-    newFile(mainFilePath, content: initialContents);
+    newFile(mainFilePath, content: contents);
 
     final firstDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities:
+              withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+      {'showTodos': true},
+    );
+    final initialDiagnostics = await firstDiagnosticsUpdate;
+    expect(initialDiagnostics, hasLength(1));
+  }
+
+  Future<void> test_todos_disabled() async {
+    const contents = '''
+    // TODO: This
+    String a = "";
+    ''';
+    newFile(mainFilePath, content: contents);
+
+    final firstDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
+    // TODOs are disabled by default so we don't need to send any config.
     await initialize();
     final initialDiagnostics = await firstDiagnosticsUpdate;
-    // TODOs should not be sent by LSP.
     expect(initialDiagnostics, hasLength(0));
   }
+
+  Future<void> test_todos_enabledAfterAnalysis() async {
+    const contents = '''
+    // TODO: This
+    String a = "";
+    ''';
+
+    final initialAnalysis = waitForAnalysisComplete();
+    final firstDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities:
+              withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+      {},
+    );
+    await openFile(mainFileUri, contents);
+    final initialDiagnostics = await firstDiagnosticsUpdate;
+    expect(initialDiagnostics, hasLength(0));
+
+    // Ensure initial analysis completely finished before we continue.
+    await initialAnalysis;
+
+    // Enable showTodos and update the file to ensure TODOs now come through.
+    final secondDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
+    await updateConfig({'showTodos': true});
+    await replaceFile(222, mainFileUri, contents);
+    final updatedDiagnostics = await secondDiagnosticsUpdate;
+    expect(updatedDiagnostics, hasLength(1));
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/folding_test.dart b/pkg/analysis_server/test/lsp/folding_test.dart
index 1caf00a..8b4e389 100644
--- a/pkg/analysis_server/test/lsp/folding_test.dart
+++ b/pkg/analysis_server/test/lsp/folding_test.dart
@@ -44,7 +44,7 @@
 
   Future<void> test_comments() async {
     final content = '''
-    [[/// This is a comment
+    /// This is a comment[[
     /// that spans many lines]]
     class MyClass2 {}
     ''';
@@ -164,13 +164,6 @@
   }
 
   Future<void> test_headersImportsComments() async {
-    // TODO(dantup): Review why the file header and the method comment ranges
-    // are different... one spans only the range to collapse, but the other
-    // just starts at the logical block.
-    // The LSP spec doesn't give any guidance on whether the first part of
-    // the surrounded content should be visible or not after folding
-    // so we'll need to revisit this once there's clarification:
-    // https://github.com/Microsoft/language-server-protocol/issues/659
     final content = '''
     // Copyright some year by some people[[
     // See LICENCE etc.]]
@@ -178,7 +171,7 @@
     import[[ 'dart:io';
     import 'dart:async';]]
 
-    [[/// This is not the file header
+    /// This is not the file header[[
     /// It's just a comment]]
     main() {}
     ''';
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 50bcc58..ce2263f 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -38,13 +38,16 @@
     final initResponse = await monitorDynamicRegistrations(
       registrations,
       () => initialize(
-          // Support dynamic registration for both text sync + hovers.
-          textDocumentCapabilities: withTextSyncDynamicRegistration(
-              withHoverDynamicRegistration(
-                  emptyTextDocumentClientCapabilities))),
+        // Support dynamic registration for both text sync + hovers.
+        textDocumentCapabilities: withTextSyncDynamicRegistration(
+            withHoverDynamicRegistration(emptyTextDocumentClientCapabilities)),
+        // And also file operations.
+        workspaceCapabilities: withFileOperationDynamicRegistration(
+            emptyWorkspaceClientCapabilities),
+      ),
     );
 
-    // Because we support dynamic registration for synchronisation, we won't send
+    // Because we support dynamic registration for synchronization, we won't send
     // static registrations for them.
     // https://github.com/dart-lang/sdk/issues/38490
     final initResult = InitializeResult.fromJson(initResponse.result);
@@ -53,12 +56,15 @@
     expect(initResult.capabilities, isNotNull);
     expect(initResult.capabilities.textDocumentSync, isNull);
 
-    // Should container Hover, DidOpen, DidClose, DidChange.
-    expect(registrations, hasLength(4));
+    // Should contain Hover, DidOpen, DidClose, DidChange, WillRenameFiles.
+    expect(registrations, hasLength(5));
     final hover =
         registrationOptionsFor(registrations, Method.textDocument_hover);
     final change =
         registrationOptionsFor(registrations, Method.textDocument_didChange);
+    final rename = FileOperationRegistrationOptions.fromJson(
+        registrationFor(registrations, Method.workspace_willRenameFiles)
+            ?.registerOptions);
     expect(registrationOptionsFor(registrations, Method.textDocument_didOpen),
         isNotNull);
     expect(registrationOptionsFor(registrations, Method.textDocument_didClose),
@@ -79,6 +85,9 @@
         change.documentSelector
             .any((ds) => ds.pattern == '**/analysis_options.yaml'),
         isTrue);
+
+    expect(rename,
+        equals(ServerCapabilitiesComputer.fileOperationRegistrationOptions));
   }
 
   Future<void> test_dynamicRegistration_notSupportedByClient() async {
@@ -120,6 +129,9 @@
     expect(initResult.capabilities.codeActionProvider, isNotNull);
     expect(initResult.capabilities.renameProvider, isNotNull);
     expect(initResult.capabilities.foldingRangeProvider, isNotNull);
+    expect(initResult.capabilities.workspace.fileOperations.willRename,
+        equals(ServerCapabilitiesComputer.fileOperationRegistrationOptions));
+    expect(initResult.capabilities.semanticTokensProvider, isNotNull);
 
     expect(didGetRegisterCapabilityRequest, isFalse);
   }
@@ -147,9 +159,13 @@
     final initResponse = await monitorDynamicRegistrations(
       registrations,
       () => initialize(
-          // Support dynamic registration for everything we support.
-          textDocumentCapabilities: withAllSupportedDynamicRegistrations(
-              emptyTextDocumentClientCapabilities)),
+        // Support dynamic registration for everything we support.
+        textDocumentCapabilities:
+            withAllSupportedTextDocumentDynamicRegistrations(
+                emptyTextDocumentClientCapabilities),
+        workspaceCapabilities: withAllSupportedWorkspaceDynamicRegistrations(
+            emptyWorkspaceClientCapabilities),
+      ),
     );
 
     final initResult = InitializeResult.fromJson(initResponse.result);
@@ -170,6 +186,8 @@
     expect(initResult.capabilities.codeActionProvider, isNull);
     expect(initResult.capabilities.renameProvider, isNull);
     expect(initResult.capabilities.foldingRangeProvider, isNull);
+    expect(initResult.capabilities.workspace.fileOperations, isNull);
+    expect(initResult.capabilities.semanticTokensProvider, isNull);
 
     // Ensure all expected dynamic registrations.
     for (final expectedRegistration in ClientDynamicRegistrations.supported) {
@@ -186,8 +204,9 @@
     await monitorDynamicRegistrations(
       registrations,
       () => initialize(
-          textDocumentCapabilities: withAllSupportedDynamicRegistrations(
-              emptyTextDocumentClientCapabilities)),
+          textDocumentCapabilities:
+              withAllSupportedTextDocumentDynamicRegistrations(
+                  emptyTextDocumentClientCapabilities)),
     );
 
     final unregisterRequest =
diff --git a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
new file mode 100644
index 0000000..dfd4324
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
@@ -0,0 +1,844 @@
+// 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/semantic_tokens/legend.dart';
+import 'package:analysis_server/src/protocol/protocol_internal.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SemanticTokensTest);
+  });
+}
+
+@reflectiveTest
+class SemanticTokensTest extends AbstractLspAnalysisServerTest {
+  /// Decode tokens according to the LSP spec and pair with relevant file contents.
+  List<_Token> decodeSemanticTokens(String content, SemanticTokens tokens) {
+    final contentLines = content.split('\n').map((line) => '$line\n').toList();
+    final results = <_Token>[];
+
+    var lastLine = 0;
+    var lastColumn = 0;
+    for (var i = 0; i < tokens.data.length; i += 5) {
+      final lineDelta = tokens.data[i];
+      final columnDelta = tokens.data[i + 1];
+      final length = tokens.data[i + 2];
+      final tokenTypeIndex = tokens.data[i + 3];
+      final modifierBitmask = tokens.data[i + 4];
+
+      // Calculate the actual line/col from the deltas.
+      final line = lastLine + lineDelta;
+      final column = lineDelta == 0 ? lastColumn + columnDelta : columnDelta;
+
+      final tokenContent =
+          contentLines[line].substring(column, column + length);
+      results.add(_Token(
+        tokenContent,
+        semanticTokenLegend.typeForIndex(tokenTypeIndex),
+        semanticTokenLegend.modifiersForBitmask(modifierBitmask),
+      ));
+
+      lastLine = line;
+      lastColumn = column;
+    }
+
+    return results;
+  }
+
+  Future<void> test_class() async {
+    final content = '''
+    /// class docs
+    class MyClass<T> {
+      // class comment
+    }
+
+    // Trailing comment
+    ''';
+
+    final expected = [
+      _Token('/// class docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('T', SemanticTokenTypes.typeParameter),
+      _Token('// class comment', SemanticTokenTypes.comment),
+      _Token('// Trailing comment', SemanticTokenTypes.comment),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_class_fields() async {
+    final content = '''
+    class MyClass {
+      /// field docs
+      String myField = 'FieldVal';
+      /// static field docs
+      static String myStaticField = 'StaticFieldVal';
+    }
+
+    main() {
+      final a = MyClass();
+      print(a.myField);
+      MyClass.myStaticField = 'a';
+    }
+    ''';
+
+    final expected = [
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('/// field docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('myField', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token("'FieldVal'", SemanticTokenTypes.string),
+      _Token('/// static field docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('static', SemanticTokenTypes.keyword),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('myStaticField', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token("'StaticFieldVal'", SemanticTokenTypes.string),
+      _Token('main', SemanticTokenTypes.function,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('final', SemanticTokenTypes.keyword),
+      _Token('a', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('print', SemanticTokenTypes.function),
+      _Token('a', SemanticTokenTypes.variable),
+      _Token('myField', SemanticTokenTypes.property),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('myStaticField', SemanticTokenTypes.property,
+          [SemanticTokenModifiers.static]),
+      _Token("'a'", SemanticTokenTypes.string),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_class_getterSetter() async {
+    final content = '''
+    class MyClass {
+      /// getter docs
+      String get myGetter => 'GetterVal';
+      /// setter docs
+      set mySetter(String v) {};
+      /// static getter docs
+      static String get myStaticGetter => 'StaticGetterVal';
+      /// static setter docs
+      static set myStaticSetter(String staticV) {};
+    }
+
+    main() {
+      final a = MyClass();
+      print(a.myGetter);
+      a.mySetter = 'a';
+    }
+    ''';
+
+    final expected = [
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('/// getter docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('get', SemanticTokenTypes.keyword),
+      _Token('myGetter', SemanticTokenTypes.property,
+          [SemanticTokenModifiers.declaration]),
+      _Token("'GetterVal'", SemanticTokenTypes.string),
+      _Token('/// setter docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('set', SemanticTokenTypes.keyword),
+      _Token('mySetter', SemanticTokenTypes.property,
+          [SemanticTokenModifiers.declaration]),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('v', SemanticTokenTypes.parameter,
+          [SemanticTokenModifiers.declaration]),
+      _Token('/// static getter docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('static', SemanticTokenTypes.keyword),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('get', SemanticTokenTypes.keyword),
+      _Token('myStaticGetter', SemanticTokenTypes.property,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token("'StaticGetterVal'", SemanticTokenTypes.string),
+      _Token('/// static setter docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('static', SemanticTokenTypes.keyword),
+      _Token('set', SemanticTokenTypes.keyword),
+      _Token('myStaticSetter', SemanticTokenTypes.property,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('staticV', SemanticTokenTypes.parameter,
+          [SemanticTokenModifiers.declaration]),
+      _Token('main', SemanticTokenTypes.function,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('final', SemanticTokenTypes.keyword),
+      _Token('a', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('print', SemanticTokenTypes.function),
+      _Token('a', SemanticTokenTypes.variable),
+      _Token('myGetter', SemanticTokenTypes.property),
+      _Token('a', SemanticTokenTypes.variable),
+      _Token('mySetter', SemanticTokenTypes.property),
+      _Token("'a'", SemanticTokenTypes.string),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_class_method() async {
+    final content = '''
+    class MyClass {
+      /// method docs
+      @override
+      void myMethod() {}
+      /// static method docs
+      static void myStaticMethod() {
+        // static method comment
+      }
+    }
+
+    main() {
+      final a = MyClass();
+      a.myMethod();
+      MyClass.myStaticMethod();
+    }
+    ''';
+
+    final expected = [
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('/// method docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('@', CustomSemanticTokenTypes.annotation),
+      _Token('override', SemanticTokenTypes.property),
+      _Token('void', SemanticTokenTypes.keyword),
+      _Token('myMethod', SemanticTokenTypes.method,
+          [SemanticTokenModifiers.declaration]),
+      _Token('/// static method docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('static', SemanticTokenTypes.keyword),
+      _Token('void', SemanticTokenTypes.keyword),
+      _Token('myStaticMethod', SemanticTokenTypes.method,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('// static method comment', SemanticTokenTypes.comment),
+      _Token('main', SemanticTokenTypes.function,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('final', SemanticTokenTypes.keyword),
+      _Token('a', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('a', SemanticTokenTypes.variable),
+      _Token('myMethod', SemanticTokenTypes.method),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('myStaticMethod', SemanticTokenTypes.method,
+          [SemanticTokenModifiers.static]),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_directives() async {
+    final content = '''
+    import 'package:flutter/material.dart';
+    export 'package:flutter/widgets.dart';
+    import '../file.dart';
+
+    library foo;
+    ''';
+
+    final expected = [
+      _Token('import', SemanticTokenTypes.keyword),
+      _Token("'package:flutter/material.dart'", SemanticTokenTypes.string),
+      _Token('export', SemanticTokenTypes.keyword),
+      _Token("'package:flutter/widgets.dart'", SemanticTokenTypes.string),
+      _Token('import', SemanticTokenTypes.keyword),
+      _Token("'../file.dart'", SemanticTokenTypes.string),
+      _Token('library', SemanticTokenTypes.keyword),
+      _Token('foo', SemanticTokenTypes.namespace),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_fromPlugin() async {
+    final pluginAnalyzedFilePath = join(projectFolderPath, 'lib', 'foo.foo');
+    final pluginAnalyzedFileUri = Uri.file(pluginAnalyzedFilePath);
+    final content = 'CLASS STRING VARIABLE';
+
+    final expected = [
+      _Token('CLASS', SemanticTokenTypes.class_),
+      _Token('STRING', SemanticTokenTypes.string),
+      _Token('VARIABLE', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+    ];
+
+    await initialize();
+    await openFile(pluginAnalyzedFileUri, withoutMarkers(content));
+
+    final pluginResult = plugin.AnalysisHighlightsParams(
+      pluginAnalyzedFilePath,
+      [
+        plugin.HighlightRegion(plugin.HighlightRegionType.CLASS, 0, 5),
+        plugin.HighlightRegion(plugin.HighlightRegionType.LITERAL_STRING, 6, 6),
+        plugin.HighlightRegion(
+            plugin.HighlightRegionType.TOP_LEVEL_VARIABLE_DECLARATION, 13, 8),
+      ],
+    );
+    configureTestPlugin(notification: pluginResult.toNotification());
+
+    final tokens = await getSemanticTokens(pluginAnalyzedFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_invalidSyntax() async {
+    final content = '''
+    /// class docs
+    class MyClass {
+      // class comment
+    }
+
+    this is not valid code.
+
+    /// class docs 2
+    class MyClass2 {
+      // class comment 2
+    }
+    ''';
+
+    // Expect toe correct tokens for the valid code before/after but don't
+    // check the the tokens for the invalid code as thre are no concrete
+    // expectations for them.
+    final expected1 = [
+      _Token('/// class docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('// class comment', SemanticTokenTypes.comment),
+    ];
+    final expected2 = [
+      _Token('/// class docs 2', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyClass2', SemanticTokenTypes.class_),
+      _Token('// class comment 2', SemanticTokenTypes.comment),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+
+    // Remove the tokens between the two expected sets.
+    decoded.removeRange(expected1.length, decoded.length - expected2.length);
+
+    expect(decoded, equals([...expected1, ...expected2]));
+  }
+
+  Future<void> test_keywords() async {
+    // "control" keywords should be tagged with a modifier so the client
+    // can colour them differently to other keywords.
+    final content = r'''
+    void main() async {
+      var a = new Object();
+      await null;
+      if (false) {
+        print('test');
+      }
+    }
+    ''';
+
+    final expected = [
+      _Token('void', SemanticTokenTypes.keyword),
+      _Token('main', SemanticTokenTypes.function,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('async', SemanticTokenTypes.keyword,
+          [CustomSemanticTokenModifiers.control]),
+      _Token('var', SemanticTokenTypes.keyword),
+      _Token('a', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token('new', SemanticTokenTypes.keyword),
+      _Token('Object', SemanticTokenTypes.class_),
+      _Token('await', SemanticTokenTypes.keyword,
+          [CustomSemanticTokenModifiers.control]),
+      _Token('null', SemanticTokenTypes.keyword),
+      _Token('if', SemanticTokenTypes.keyword,
+          [CustomSemanticTokenModifiers.control]),
+      _Token('false', CustomSemanticTokenTypes.boolean),
+      _Token('print', SemanticTokenTypes.function),
+      _Token("'test'", SemanticTokenTypes.string),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_lastLine_code() async {
+    final content = 'String var;';
+
+    final expected = [
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('var', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_lastLine_comment() async {
+    final content = '// Trailing comment';
+
+    final expected = [
+      _Token('// Trailing comment', SemanticTokenTypes.comment),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_lastLine_multilineComment() async {
+    final content = '''/**
+ * Trailing comment
+ */''';
+
+    final expected = [
+      _Token('/**\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token(' * Trailing comment\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token(' */', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_manyBools_bug() async {
+    // Similar to test_manyImports_sortBug, this code triggered inconsistent tokens
+    // for "false" because tokens were sorted incorrectly (because both boolean and
+    // keyword had the same offset and length, which is all that were sorted by).
+    final content = '''
+class MyTestClass {
+  /// test
+  /// test
+  bool test1 = false;
+
+  /// test
+  /// test
+  bool test2 = false;
+
+  /// test
+  /// test
+  bool test3 = false;
+
+  /// test
+  /// test
+  bool test4 = false;
+
+  /// test
+  /// test
+  bool test5 = false;
+
+  /// test
+  /// test
+  bool test6 = false;
+}
+    ''';
+
+    final expected = [
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyTestClass', SemanticTokenTypes.class_),
+      for (var i = 1; i <= 6; i++) ...[
+        _Token('/// test', SemanticTokenTypes.comment,
+            [SemanticTokenModifiers.documentation]),
+        _Token('/// test', SemanticTokenTypes.comment,
+            [SemanticTokenModifiers.documentation]),
+        _Token('bool', SemanticTokenTypes.class_),
+        _Token('test$i', SemanticTokenTypes.variable,
+            [SemanticTokenModifiers.declaration]),
+        _Token('false', CustomSemanticTokenTypes.boolean),
+      ],
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_manyImports_sortBug() async {
+    // This test is for a bug where some "import" tokens would not be highlighted
+    // correctly. Imports are made up of a DIRECTIVE token that spans a
+    // BUILT_IN ("import") and LITERAL_STRING. The original code sorted by only
+    // offset when handling overlapping tokens, which for certain lists (such as
+    // the one created for the code below) would result in the BUILTIN coming before
+    // the DIRECTIVE, which resulted in the DIRECTIVE overwriting it.
+    final content = '''
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+import 'dart:async';
+    ''';
+
+    final expected = [
+      for (var i = 0; i < 13; i++) ...[
+        _Token('import', SemanticTokenTypes.keyword),
+        _Token("'dart:async'", SemanticTokenTypes.string),
+      ],
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_multilineRegions() async {
+    final content = '''
+/**
+ * This is my class comment
+ *
+ * There are
+ * multiple lines
+ */
+class MyClass {}
+    ''';
+
+    final expected = [
+      _Token('/**\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token(' * This is my class comment\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token(' *\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token(' * There are\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token(' * multiple lines\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token(' */', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyClass', SemanticTokenTypes.class_),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_namedArguments() async {
+    final content = '''
+    f({String a}) {
+      f(a: a);
+    }    
+    ''';
+
+    final expected = [
+      _Token('f', SemanticTokenTypes.function,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('a', SemanticTokenTypes.parameter,
+          [SemanticTokenModifiers.declaration]),
+      _Token('f', SemanticTokenTypes.function),
+      _Token('a', SemanticTokenTypes.parameter,
+          [CustomSemanticTokenModifiers.label]),
+      _Token('a', SemanticTokenTypes.parameter),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_range() async {
+    final content = '''
+    /// class docs
+    class [[MyClass<T> {
+      // class comment
+    }]]
+
+    // Trailing comment
+    ''';
+
+    final expected = [
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('T', SemanticTokenTypes.typeParameter),
+      _Token('// class comment', SemanticTokenTypes.comment),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens =
+        await getSemanticTokensRange(mainFileUri, rangeFromMarkers(content));
+    final decoded = decodeSemanticTokens(withoutMarkers(content), tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_range_entireFile() async {
+    final content = '''[[
+    /// class docs
+    class MyClass<T> {
+      // class comment
+    }
+
+    // Trailing comment
+    ]]''';
+
+    final expected = [
+      _Token('/// class docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('class', SemanticTokenTypes.keyword),
+      _Token('MyClass', SemanticTokenTypes.class_),
+      _Token('T', SemanticTokenTypes.typeParameter),
+      _Token('// class comment', SemanticTokenTypes.comment),
+      _Token('// Trailing comment', SemanticTokenTypes.comment),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens =
+        await getSemanticTokensRange(mainFileUri, rangeFromMarkers(content));
+    final decoded = decodeSemanticTokens(withoutMarkers(content), tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_range_multilineRegions() async {
+    final content = '''
+    /**
+     * This is my class comment
+     *
+     * [[There are
+     * multiple lines
+     */
+    class]] MyClass {}
+    ''';
+
+    final expected = [
+      _Token('     * There are\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('     * multiple lines\n', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('     */', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('class', SemanticTokenTypes.keyword),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens =
+        await getSemanticTokensRange(mainFileUri, rangeFromMarkers(content));
+    final decoded = decodeSemanticTokens(withoutMarkers(content), tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_strings() async {
+    final content = '''
+String foo(String c) => c;
+const string1 = 'test';
+const string2 = 'test1 \$string1 test2 \${foo('test3')}';
+const string3 = r'\$string1 \${string1.length}';
+const string4 = \'\'\'
+multi
+  line
+    string
+\'\'\';
+''';
+
+    final expected = [
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('foo', SemanticTokenTypes.function,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('c', SemanticTokenTypes.parameter,
+          [SemanticTokenModifiers.declaration]),
+      _Token('c', SemanticTokenTypes.parameter),
+      _Token('const', SemanticTokenTypes.keyword),
+      _Token('string1', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token("'test'", SemanticTokenTypes.string),
+      _Token('const', SemanticTokenTypes.keyword),
+      _Token('string2', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token(r"'test1 ", SemanticTokenTypes.string),
+      _Token('string1', SemanticTokenTypes.property),
+      _Token(' test2 ', SemanticTokenTypes.string),
+      _Token('foo', SemanticTokenTypes.function),
+      _Token("'test3'", SemanticTokenTypes.string),
+      _Token("'", SemanticTokenTypes.string),
+      _Token('const', SemanticTokenTypes.keyword),
+      // string3 is raw and should be treated as a single string.
+      _Token('string3', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token(r"r'$string1 ${string1.length}'", SemanticTokenTypes.string),
+      _Token('const', SemanticTokenTypes.keyword),
+      _Token('string4', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token("'''\n", SemanticTokenTypes.string),
+      _Token('multi\n', SemanticTokenTypes.string),
+      _Token('  line\n', SemanticTokenTypes.string),
+      _Token('    string\n', SemanticTokenTypes.string),
+      _Token("'''", SemanticTokenTypes.string),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+
+  Future<void> test_topLevel() async {
+    final content = '''
+    /// strings docs
+    const strings = <String>["test", 'test', r'test', \'''test\'''];
+
+    /// func docs
+    func(String a) => print(a);
+
+    /// abc docs
+    bool get abc => true;
+    ''';
+
+    final expected = [
+      _Token('/// strings docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('const', SemanticTokenTypes.keyword),
+      _Token('strings', SemanticTokenTypes.variable,
+          [SemanticTokenModifiers.declaration]),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('"test"', SemanticTokenTypes.string),
+      _Token("'test'", SemanticTokenTypes.string),
+      _Token("r'test'", SemanticTokenTypes.string),
+      _Token("'''test'''", SemanticTokenTypes.string),
+      _Token('/// func docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('func', SemanticTokenTypes.function,
+          [SemanticTokenModifiers.declaration, SemanticTokenModifiers.static]),
+      _Token('String', SemanticTokenTypes.class_),
+      _Token('a', SemanticTokenTypes.parameter,
+          [SemanticTokenModifiers.declaration]),
+      _Token('print', SemanticTokenTypes.function),
+      _Token('a', SemanticTokenTypes.parameter),
+      _Token('/// abc docs', SemanticTokenTypes.comment,
+          [SemanticTokenModifiers.documentation]),
+      _Token('bool', SemanticTokenTypes.class_),
+      _Token('get', SemanticTokenTypes.keyword),
+      _Token('abc', SemanticTokenTypes.property,
+          [SemanticTokenModifiers.declaration]),
+      _Token('true', CustomSemanticTokenTypes.boolean),
+    ];
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final tokens = await getSemanticTokens(mainFileUri);
+    final decoded = decodeSemanticTokens(content, tokens);
+    expect(decoded, equals(expected));
+  }
+}
+
+class _Token {
+  final String content;
+  final SemanticTokenTypes type;
+  final List<SemanticTokenModifiers> modifiers;
+
+  _Token(this.content, this.type, [this.modifiers = const []]);
+
+  @override
+  int get hashCode => content.hashCode;
+
+  @override
+  bool operator ==(Object o) =>
+      o is _Token &&
+      o.content == content &&
+      o.type == type &&
+      listEqual(
+          // Treat nulls the same as empty lists for convenience when comparing.
+          o.modifiers ?? <SemanticTokenModifiers>[],
+          modifiers ?? <SemanticTokenModifiers>[],
+          (SemanticTokenModifiers a, SemanticTokenModifiers b) => a == b);
+
+  @override
+  String toString() => '$content (${[type, ...?modifiers]})';
+}
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index f99877e..74726a9 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -199,11 +199,12 @@
     return ClientCapabilitiesWorkspace.fromJson(json);
   }
 
-  TextDocumentClientCapabilities withAllSupportedDynamicRegistrations(
+  TextDocumentClientCapabilities
+      withAllSupportedTextDocumentDynamicRegistrations(
     TextDocumentClientCapabilities source,
   ) {
-    // This list should match all of the fields listed in
-    // `ClientDynamicRegistrations.supported`.
+    // This list (when combined with the workspace list) should match all of
+    // the fields listed in `ClientDynamicRegistrations.supported`.
     return extendTextDocumentCapabilities(source, {
       'synchronization': {'dynamicRegistration': true},
       'completion': {'dynamicRegistration': true},
@@ -221,6 +222,22 @@
       'codeAction': {'dynamicRegistration': true},
       'rename': {'dynamicRegistration': true},
       'foldingRange': {'dynamicRegistration': true},
+      'semanticTokens': SemanticTokensClientCapabilities(
+          dynamicRegistration: true,
+          requests: SemanticTokensClientCapabilitiesRequests(),
+          formats: [],
+          tokenModifiers: [],
+          tokenTypes: []).toJson(),
+    });
+  }
+
+  ClientCapabilitiesWorkspace withAllSupportedWorkspaceDynamicRegistrations(
+    ClientCapabilitiesWorkspace source,
+  ) {
+    // This list (when combined with the textDocument list) should match all of
+    // the fields listed in `ClientDynamicRegistrations.supported`.
+    return extendWorkspaceCapabilities(source, {
+      'fileOperations': {'dynamicRegistration': true},
     });
   }
 
@@ -343,6 +360,14 @@
     });
   }
 
+  ClientCapabilitiesWorkspace withFileOperationDynamicRegistration(
+    ClientCapabilitiesWorkspace source,
+  ) {
+    return extendWorkspaceCapabilities(source, {
+      'fileOperations': {'dynamicRegistration': true}
+    });
+  }
+
   TextDocumentClientCapabilities withHierarchicalDocumentSymbolSupport(
     TextDocumentClientCapabilities source,
   ) {
@@ -565,13 +590,16 @@
     });
   }
 
-  String applyTextEdit(String content, TextEdit change) {
-    final startPos = change.range.start;
-    final endPos = change.range.end;
+  String applyTextEdit(
+      String content, Either2<TextEdit, AnnotatedTextEdit> change) {
+    // Both sites of the union can cast to TextEdit.
+    final edit = change.map((e) => e, (e) => e);
+    final startPos = edit.range.start;
+    final endPos = edit.range.end;
     final lineInfo = LineInfo.fromContent(content);
     final start = lineInfo.getOffsetOfLine(startPos.line) + startPos.character;
     final end = lineInfo.getOffsetOfLine(endPos.line) + endPos.character;
-    return content.replaceRange(start, end, change.newText);
+    return content.replaceRange(start, end, edit.newText);
   }
 
   String applyTextEdits(String oldContent, List<TextEdit> changes) {
@@ -626,7 +654,8 @@
       );
 
     for (final change in sortedChanges) {
-      newContent = applyTextEdit(newContent, change);
+      newContent = applyTextEdit(
+          newContent, Either2<TextEdit, AnnotatedTextEdit>.t1(change));
     }
 
     return newContent;
@@ -702,7 +731,7 @@
     final path = Uri.parse(edit.textDocument.uri).toFilePath();
     final expectedVersion = expectedVersions[path];
 
-    if (edit.textDocument is VersionedTextDocumentIdentifier) {
+    if (edit.textDocument is OptionalVersionedTextDocumentIdentifier) {
       expect(edit.textDocument.version, equals(expectedVersion));
     } else {
       throw 'Document identifier for $path was not versioned (expected version $expectedVersion)';
@@ -901,7 +930,7 @@
 
   Future<DartDiagnosticServer> getDiagnosticServer() {
     final request = makeRequest(
-      CustomMethods.DiagnosticServer,
+      CustomMethods.diagnosticServer,
       null,
     );
     return expectSuccessfulResponseTo(request, DartDiagnosticServer.fromJson);
@@ -991,6 +1020,27 @@
         request, _fromJsonList(Location.fromJson));
   }
 
+  Future<SemanticTokens> getSemanticTokens(Uri uri) {
+    final request = makeRequest(
+      Method.textDocument_semanticTokens_full,
+      SemanticTokensParams(
+        textDocument: TextDocumentIdentifier(uri: uri.toString()),
+      ),
+    );
+    return expectSuccessfulResponseTo(request, SemanticTokens.fromJson);
+  }
+
+  Future<SemanticTokens> getSemanticTokensRange(Uri uri, Range range) {
+    final request = makeRequest(
+      Method.textDocument_semanticTokens_range,
+      SemanticTokensRangeParams(
+        textDocument: TextDocumentIdentifier(uri: uri.toString()),
+        range: range,
+      ),
+    );
+    return expectSuccessfulResponseTo(request, SemanticTokens.fromJson);
+  }
+
   Future<SignatureHelp> getSignatureHelp(Uri uri, Position pos,
       [SignatureHelpContext context]) {
     final request = makeRequest(
@@ -1009,7 +1059,7 @@
     Position pos,
   ) {
     final request = makeRequest(
-      CustomMethods.Super,
+      CustomMethods.super_,
       TextDocumentPositionParams(
         textDocument: TextDocumentIdentifier(uri: uri.toString()),
         position: pos,
@@ -1215,6 +1265,14 @@
     );
   }
 
+  Future<WorkspaceEdit> onWillRename(List<FileRename> renames) {
+    final request = makeRequest(
+      Method.workspace_willRenameFiles,
+      RenameFilesParams(files: renames),
+    );
+    return expectSuccessfulResponseTo(request, WorkspaceEdit.fromJson);
+  }
+
   Future openFile(Uri uri, String content, {num version = 1}) async {
     var notification = makeNotification(
       Method.textDocument_didOpen,
@@ -1428,10 +1486,10 @@
   Future<void> waitForAnalysisStatus(bool analyzing) async {
     await serverToClient.firstWhere((message) {
       if (message is NotificationMessage) {
-        if (message.method == CustomMethods.AnalyzerStatus) {
+        if (message.method == CustomMethods.analyzerStatus) {
           if (_clientCapabilities.window?.workDoneProgress == true) {
             throw Exception(
-                'Recieved ${CustomMethods.AnalyzerStatus} notification '
+                'Recieved ${CustomMethods.analyzerStatus} notification '
                 'but client supports workDoneProgress');
           }
 
@@ -1440,7 +1498,7 @@
         } else if (message.method == Method.progress) {
           if (_clientCapabilities.window?.workDoneProgress != true) {
             throw Exception(
-                'Recieved ${CustomMethods.AnalyzerStatus} notification '
+                'Recieved ${CustomMethods.analyzerStatus} notification '
                 'but client supports workDoneProgress');
           }
 
@@ -1473,7 +1531,7 @@
     PublishClosingLabelsParams closingLabelsParams;
     await serverToClient.firstWhere((message) {
       if (message is NotificationMessage &&
-          message.method == CustomMethods.PublishClosingLabels) {
+          message.method == CustomMethods.publishClosingLabels) {
         closingLabelsParams =
             PublishClosingLabelsParams.fromJson(message.params);
 
@@ -1501,7 +1559,7 @@
     PublishFlutterOutlineParams outlineParams;
     await serverToClient.firstWhere((message) {
       if (message is NotificationMessage &&
-          message.method == CustomMethods.PublishFlutterOutline) {
+          message.method == CustomMethods.publishFlutterOutline) {
         outlineParams = PublishFlutterOutlineParams.fromJson(message.params);
 
         return outlineParams.uri == uri.toString();
@@ -1515,7 +1573,7 @@
     PublishOutlineParams outlineParams;
     await serverToClient.firstWhere((message) {
       if (message is NotificationMessage &&
-          message.method == CustomMethods.PublishOutline) {
+          message.method == CustomMethods.publishOutline) {
         outlineParams = PublishOutlineParams.fromJson(message.params);
 
         return outlineParams.uri == uri.toString();
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index ea56793..aa30754 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -34,9 +34,11 @@
 import 'reanalyze_test.dart' as reanalyze;
 import 'references_test.dart' as references;
 import 'rename_test.dart' as rename;
+import 'semantic_tokens_test.dart' as semantic_tokens;
 import 'server_test.dart' as server;
 import 'signature_help_test.dart' as signature_help;
 import 'super_test.dart' as get_super;
+import 'will_rename_files_test.dart' as will_rename_files;
 import 'workspace_symbols_test.dart' as workspace_symbols;
 
 void main() {
@@ -72,8 +74,10 @@
     reanalyze.main();
     references.main();
     rename.main();
+    semantic_tokens.main();
     server.main();
     signature_help.main();
+    will_rename_files.main();
     workspace_symbols.main();
   }, name: 'lsp');
 }
diff --git a/pkg/analysis_server/test/lsp/will_rename_files_test.dart b/pkg/analysis_server/test/lsp/will_rename_files_test.dart
new file mode 100644
index 0000000..e9b6fee
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/will_rename_files_test.dart
@@ -0,0 +1,60 @@
+// 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 'dart:async';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(WillRenameFilesTest);
+  });
+}
+
+@reflectiveTest
+class WillRenameFilesTest extends AbstractLspAnalysisServerTest {
+  Future<void> test_rename_updatesImports() async {
+    final otherFilePath = join(projectFolderPath, 'lib', 'other.dart');
+    final otherFileUri = Uri.file(otherFilePath);
+    final otherFileNewPath = join(projectFolderPath, 'lib', 'other_new.dart');
+    final otherFileNewUri = Uri.file(otherFileNewPath);
+
+    final mainContent = '''
+import 'other.dart';
+
+final a = A();
+''';
+
+    final otherContent = '''
+class A {}
+''';
+
+    final expectedMainContent = '''
+import 'other_new.dart';
+
+final a = A();
+''';
+
+    await initialize();
+    await openFile(mainFileUri, mainContent);
+    await openFile(otherFileUri, otherContent);
+    final edit = await onWillRename([
+      FileRename(
+        oldUri: otherFileUri.toString(),
+        newUri: otherFileNewUri.toString(),
+      ),
+    ]);
+
+    // Ensure applying the edit will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(mainContent),
+    };
+    applyChanges(contents, edit.changes);
+    expect(contents[mainFilePath], equals(expectedMainContent));
+  }
+}
diff --git a/pkg/analysis_server/test/plugin/protocol_dart_test.dart b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
index d693387..aabef45 100644
--- a/pkg/analysis_server/test/plugin/protocol_dart_test.dart
+++ b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
@@ -3,10 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/protocol/protocol_dart.dart';
-import 'package:analyzer/dart/ast/ast.dart' as engine;
 import 'package:analyzer/dart/element/element.dart' as engine;
 import 'package:analyzer/src/dart/element/element.dart' as engine;
-import 'package:analyzer/src/generated/testing/element_search.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -91,20 +89,13 @@
 
 @reflectiveTest
 class ElementTest extends AbstractSingleUnitTest {
-  engine.Element findElementInUnit(engine.CompilationUnit unit, String name,
-      [engine.ElementKind kind]) {
-    return findElementsByName(unit, name)
-        .where((e) => kind == null || e.kind == kind)
-        .single;
-  }
-
   Future<void> test_fromElement_CLASS() async {
     await resolveTestCode('''
 @deprecated
 abstract class _A {}
 class B<K, V> {}''');
     {
-      engine.ClassElement engineElement = findElementInUnit(testUnit, '_A');
+      var engineElement = findElement.class_('_A');
       // create notification Element
       var element = convertElement(engineElement);
       expect(element.kind, ElementKind.CLASS);
@@ -126,7 +117,7 @@
               Element.FLAG_PRIVATE);
     }
     {
-      engine.ClassElement engineElement = findElementInUnit(testUnit, 'B');
+      var engineElement = findElement.class_('B');
       // create notification Element
       var element = convertElement(engineElement);
       expect(element.kind, ElementKind.CLASS);
@@ -141,8 +132,7 @@
 class A {
   const A.myConstructor(int a, [String b]);
 }''');
-    engine.ConstructorElement engineElement =
-        findElementInUnit(testUnit, 'myConstructor');
+    var engineElement = findElement.constructor('myConstructor');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.kind, ElementKind.CONSTRUCTOR);
@@ -169,8 +159,7 @@
   const A.myConstructor(int a, {int b, @required int c});
 }''');
 
-    engine.ConstructorElement engineElement =
-        findElementInUnit(testUnit, 'myConstructor');
+    var engineElement = findElement.constructor('myConstructor');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.parameters, '(int a, {@required int c, int b})');
@@ -185,8 +174,7 @@
   const A.myConstructor(int a, {int b, @required int d, @required int c});
 }''');
 
-    engine.ConstructorElement engineElement =
-        findElementInUnit(testUnit, 'myConstructor');
+    var engineElement = findElement.constructor('myConstructor');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.parameters,
@@ -203,8 +191,7 @@
   const A.myConstructor(int a, {int b, @required int d, @required int c, int a});
 }''');
 
-    engine.ConstructorElement engineElement =
-        findElementInUnit(testUnit, 'myConstructor');
+    var engineElement = findElement.constructor('myConstructor');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.parameters,
@@ -229,7 +216,7 @@
 enum _E1 { one, two }
 enum E2 { three, four }''');
     {
-      engine.ClassElement engineElement = findElementInUnit(testUnit, '_E1');
+      var engineElement = findElement.enum_('_E1');
       expect(engineElement.hasDeprecated, isTrue);
       // create notification Element
       var element = convertElement(engineElement);
@@ -251,7 +238,7 @@
               Element.FLAG_PRIVATE);
     }
     {
-      engine.ClassElement engineElement = findElementInUnit(testUnit, 'E2');
+      var engineElement = findElement.enum_('E2');
       // create notification Element
       var element = convertElement(engineElement);
       expect(element.kind, ElementKind.ENUM);
@@ -267,7 +254,7 @@
 enum _E1 { one, two }
 enum E2 { three, four }''');
     {
-      engine.FieldElement engineElement = findElementInUnit(testUnit, 'one');
+      var engineElement = findElement.field('one');
       // create notification Element
       var element = convertElement(engineElement);
       expect(element.kind, ElementKind.ENUM_CONSTANT);
@@ -291,7 +278,7 @@
           Element.FLAG_CONST | Element.FLAG_STATIC);
     }
     {
-      engine.FieldElement engineElement = findElementInUnit(testUnit, 'three');
+      var engineElement = findElement.field('three');
       // create notification Element
       var element = convertElement(engineElement);
       expect(element.kind, ElementKind.ENUM_CONSTANT);
@@ -309,7 +296,7 @@
       expect(element.flags, Element.FLAG_CONST | Element.FLAG_STATIC);
     }
     {
-      var engineElement = testUnit.declaredElement.enums[1].getField('index');
+      var engineElement = findElement.field('index', of: 'E2');
       // create notification Element
       var element = convertElement(engineElement);
       expect(element.kind, ElementKind.FIELD);
@@ -327,7 +314,7 @@
       expect(element.flags, Element.FLAG_FINAL);
     }
     {
-      var engineElement = testUnit.declaredElement.enums[1].getField('values');
+      var engineElement = findElement.field('values', of: 'E2');
       // create notification Element
       var element = convertElement(engineElement);
       expect(element.kind, ElementKind.FIELD);
@@ -351,7 +338,7 @@
 class A {
   static const myField = 42;
 }''');
-    engine.FieldElement engineElement = findElementInUnit(testUnit, 'myField');
+    var engineElement = findElement.field('myField');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.kind, ElementKind.FIELD);
@@ -373,8 +360,7 @@
     await resolveTestCode('''
 typedef int F<T>(String x);
 ''');
-    engine.FunctionTypeAliasElement engineElement =
-        findElementInUnit(testUnit, 'F');
+    var engineElement = findElement.typeAlias('F');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.kind, ElementKind.FUNCTION_TYPE_ALIAS);
@@ -397,8 +383,7 @@
     await resolveTestCode('''
 typedef F<T> = int Function(String x);
 ''');
-    engine.FunctionTypeAliasElement engineElement =
-        findElementInUnit(testUnit, 'F');
+    var engineElement = findElement.typeAlias('F');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.kind, ElementKind.FUNCTION_TYPE_ALIAS);
@@ -423,8 +408,7 @@
 class A {
   String get myGetter => 42;
 }''');
-    engine.PropertyAccessorElement engineElement =
-        findElementInUnit(testUnit, 'myGetter', engine.ElementKind.GETTER);
+    var engineElement = findElement.getter('myGetter');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.kind, ElementKind.GETTER);
@@ -450,7 +434,7 @@
     break myLabel;
   }
 }''');
-    engine.LabelElement engineElement = findElementInUnit(testUnit, 'myLabel');
+    var engineElement = findElement.label('myLabel');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.kind, ElementKind.LABEL);
@@ -475,8 +459,7 @@
     return null;
   }
 }''');
-    engine.MethodElement engineElement =
-        findElementInUnit(testUnit, 'myMethod');
+    var engineElement = findElement.method('myMethod');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.kind, ElementKind.METHOD);
@@ -499,7 +482,7 @@
 mixin A {}
 ''');
     {
-      engine.ClassElement engineElement = findElementInUnit(testUnit, 'A');
+      var engineElement = findElement.mixin('A');
       // create notification Element
       var element = convertElement(engineElement);
       expect(element.kind, ElementKind.MIXIN);
@@ -523,8 +506,7 @@
 class A {
   set mySetter(String x) {}
 }''');
-    engine.PropertyAccessorElement engineElement =
-        findElementInUnit(testUnit, 'mySetter', engine.ElementKind.SETTER);
+    var engineElement = findElement.setter('mySetter');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.kind, ElementKind.SETTER);
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 63573c1..89353f4 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
@@ -13,7 +13,6 @@
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
-import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:meta/meta.dart';
 import 'package:test/test.dart';
@@ -96,7 +95,7 @@
   /// where there is no `new` or `const` keyword.
   bool get suggestConstructorsWithoutNew => true;
 
-  bool get usingFastaParser => analyzer.Parser.useFasta;
+  bool get usingFastaParser => true;
 
   void addTestSource(String content) {
     expect(completionOffset, isNull, reason: 'Call addTestUnit exactly once');
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index ff603a4..a83e323 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -49,8 +49,7 @@
 void main() {f^}''');
     await computeSuggestions();
 
-    assertSuggestFunction('foo', 'bool',
-        defaultArgListString: 'bar, baz: null');
+    assertSuggestFunction('foo', 'bool', defaultArgListString: 'bar, baz: baz');
   }
 
   Future<void> test_ArgumentList() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index 0c7657a..571d7b2 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -70,8 +70,8 @@
     await computeSuggestions();
 
     assertSuggestFunction('foo', 'bool',
-        defaultArgListString: 'bar, baz: null',
-        defaultArgumentListTextRanges: [0, 3, 10, 4]);
+        defaultArgListString: 'bar, baz: baz',
+        defaultArgumentListTextRanges: [0, 3, 10, 3]);
   }
 
   Future<void> test_ArgDefaults_inherited_method_with_required_named() async {
@@ -92,7 +92,7 @@
     await computeSuggestions();
 
     assertSuggestMethod('foo', 'A', 'bool',
-        defaultArgListString: 'bar, baz: null');
+        defaultArgListString: 'bar, baz: baz');
   }
 
   Future<void> test_ArgDefaults_method_with_required_named() async {
@@ -109,8 +109,8 @@
     await computeSuggestions();
 
     assertSuggestMethod('foo', 'A', 'bool',
-        defaultArgListString: 'bar, baz: null',
-        defaultArgumentListTextRanges: [0, 3, 10, 4]);
+        defaultArgListString: 'bar, baz: baz',
+        defaultArgumentListTextRanges: [0, 3, 10, 3]);
   }
 
   Future<void> test_ArgumentList() async {
@@ -4139,7 +4139,7 @@
   }
 }''');
     await computeSuggestions();
-    assertSuggestConstructor('A', defaultArgListString: 'bar, baz: null');
+    assertSuggestConstructor('A', defaultArgListString: 'bar, baz: baz');
   }
 
   Future<void> test_localConstructor2() async {
@@ -4194,7 +4194,7 @@
   }
 }''');
     await computeSuggestions();
-    assertSuggestConstructor('A', defaultArgListString: 'bar, baz: null');
+    assertSuggestConstructor('A', defaultArgListString: 'bar, baz: baz');
   }
 
   Future<void> test_localConstructor_shadowed() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index aea6d40..894b3d0 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -104,7 +104,7 @@
     await computeSuggestions();
 
     assertSuggestMethod('foo', 'A', 'bool',
-        defaultArgListString: 'bar, baz: null');
+        defaultArgListString: 'bar, baz: baz');
   }
 
   Future<void> test_ArgumentList() async {
diff --git a/pkg/analysis_server/test/services/correction/name_suggestion_test.dart b/pkg/analysis_server/test/services/correction/name_suggestion_test.dart
index 07e8f81..243fd9b 100644
--- a/pkg/analysis_server/test/services/correction/name_suggestion_test.dart
+++ b/pkg/analysis_server/test/services/correction/name_suggestion_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/name_suggestion.dart';
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -25,7 +24,7 @@
 }
 ''');
     var excluded = <String>{};
-    var expr = findNodeAtString('as String', (node) => node is AsExpression);
+    var expr = findNode.as_('as String');
     expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
         unorderedEquals(['sortedNodes', 'nodes']));
   }
@@ -38,9 +37,8 @@
 }
 ''');
     var excluded = <String>{};
-    var expectedType = findLocalVariable('node').type;
-    Expression assignedExpression =
-        findNodeAtString('null;', (node) => node is NullLiteral);
+    var expectedType = findElement.localVar('node').type;
+    var assignedExpression = findNode.nullLiteral('null;');
     var suggestions = getVariableNameSuggestionsForExpression(
         expectedType, assignedExpression, excluded);
     expect(suggestions, unorderedEquals(['treeNode', 'node']));
@@ -52,8 +50,8 @@
   double res = 0.0;
 }
 ''');
-    var expectedType = findLocalVariable('res').type;
-    Expression assignedExpression = findNodeAtString('0.0;');
+    var expectedType = findElement.localVar('res').type;
+    var assignedExpression = findNode.doubleLiteral('0.0;');
     // first choice for "double" is "d"
     expect(
         getVariableNameSuggestionsForExpression(
@@ -72,8 +70,8 @@
   int res = 0;
 }
 ''');
-    var expectedType = findLocalVariable('res').type;
-    Expression assignedExpression = findNodeAtString('0;');
+    var expectedType = findElement.localVar('res').type;
+    var assignedExpression = findNode.integerLiteral('0;');
     // first choice for "int" is "i"
     expect(
         getVariableNameSuggestionsForExpression(
@@ -92,8 +90,8 @@
   String res = 'abc';
 }
 ''');
-    var expectedType = findLocalVariable('res').type;
-    Expression assignedExpression = findNodeAtString("'abc';");
+    var expectedType = findElement.localVar('res').type;
+    var assignedExpression = findNode.stringLiteral("'abc';");
     // first choice for "String" is "s"
     expect(
         getVariableNameSuggestionsForExpression(
@@ -110,7 +108,7 @@
 }
 ''');
     var excluded = <String>{};
-    var expr = findNodeAtString('new List');
+    var expr = findNode.instanceCreation('new List');
     expect(
         getVariableNameSuggestionsForExpression(null, expr, excluded,
             isMethod: false),
@@ -129,7 +127,7 @@
 }
 ''');
     var excluded = <String>{};
-    var expr = findNodeAtString('topNodes[0]').parent;
+    var expr = findNode.index('topNodes[0]');
     var names = getVariableNameSuggestionsForExpression(null, expr, excluded);
     expect(names, unorderedEquals(['topNode', 'node', 'object']));
   }
@@ -147,11 +145,11 @@
     var excluded = <String>{};
     expect(
         getVariableNameSuggestionsForExpression(
-            null, findNodeAtString('new NoSuchClass()'), excluded),
+            null, findNode.instanceCreation('new NoSuchClass()'), excluded),
         unorderedEquals(['noSuchClass', 'suchClass', 'class']));
     expect(
-        getVariableNameSuggestionsForExpression(
-            null, findNodeAtString('new NoSuchClass.named()'), excluded),
+        getVariableNameSuggestionsForExpression(null,
+            findNode.instanceCreation('new NoSuchClass.named()'), excluded),
         unorderedEquals(['noSuchClass', 'suchClass', 'class']));
     // TODO(scheglov) This test does not work.
     // In "p.NoSuchClass" the identifier "p" is not resolved to a PrefixElement.
@@ -172,17 +170,17 @@
 ''');
     var excluded = <String>{};
     {
-      var expr = findNodeAtString('111');
+      var expr = findNode.integerLiteral('111');
       expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
           unorderedEquals(['a']));
     }
     {
-      var expr = findNodeAtString('222');
+      var expr = findNode.integerLiteral('222');
       expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
           unorderedEquals(['b']));
     }
     {
-      var expr = findNodeAtString('333');
+      var expr = findNode.integerLiteral('333');
       expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
           unorderedEquals(['c']));
     }
@@ -197,17 +195,17 @@
 ''');
     var excluded = <String>{};
     {
-      var expr = findNodeAtString('111');
+      var expr = findNode.integerLiteral('111');
       expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
           unorderedEquals(['a']));
     }
     {
-      var expr = findNodeAtString('222');
+      var expr = findNode.integerLiteral('222');
       expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
           unorderedEquals(['b']));
     }
     {
-      var expr = findNodeAtString('333');
+      var expr = findNode.integerLiteral('333');
       expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
           unorderedEquals(['c']));
     }
@@ -222,12 +220,12 @@
 ''');
     var excluded = <String>{};
     {
-      var expr = findNodeAtString('111');
+      var expr = findNode.integerLiteral('111');
       expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
           unorderedEquals(['a']));
     }
     {
-      var expr = findNodeAtString('222');
+      var expr = findNode.integerLiteral('222');
       expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
           unorderedEquals(['b']));
     }
@@ -240,7 +238,7 @@
 }
 ''');
     var excluded = <String>{};
-    var expr = findNodeAtString('p.get', (node) => node is MethodInvocation);
+    var expr = findNode.methodInvocation('p.get');
     expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
         unorderedEquals(['sortedNodes', 'nodes']));
   }
@@ -252,7 +250,7 @@
 }
 ''');
     var excluded = <String>{};
-    var expr = findNodeAtString('p.sorted', (node) => node is MethodInvocation);
+    var expr = findNode.methodInvocation('p.sorted');
     expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
         unorderedEquals(['sortedNodes', 'nodes']));
   }
@@ -264,7 +262,7 @@
 }
 ''');
     var excluded = <String>{};
-    var expr = findNodeAtString('p.get', (node) => node is MethodInvocation);
+    var expr = findNode.methodInvocation('p.get');
     expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
         unorderedEquals([]));
   }
@@ -278,9 +276,7 @@
     var excluded = <String>{};
     expect(
         getVariableNameSuggestionsForExpression(
-            null,
-            findNodeAtString('p.sorted', (node) => node is PrefixedIdentifier),
-            excluded),
+            null, findNode.prefixed('p.sorted'), excluded),
         unorderedEquals(['sortedNodes', 'nodes']));
   }
 
@@ -294,15 +290,11 @@
     var excluded = <String>{};
     expect(
         getVariableNameSuggestionsForExpression(
-            null,
-            findNodeAtString('p._name', (node) => node is PrefixedIdentifier),
-            excluded),
+            null, findNode.prefixed('p._name'), excluded),
         unorderedEquals(['name']));
     expect(
         getVariableNameSuggestionsForExpression(
-            null,
-            findNodeAtString('p._compute', (node) => node is MethodInvocation),
-            excluded),
+            null, findNode.methodInvocation('p._compute'), excluded),
         unorderedEquals(['computeSuffix', 'suffix']));
   }
 
@@ -313,8 +305,7 @@
 }
 ''');
     var excluded = <String>{};
-    PropertyAccess expression =
-        findNodeAtString('p.q.sorted', (node) => node is PropertyAccess);
+    var expression = findNode.propertyAccess('.sorted');
     expect(getVariableNameSuggestionsForExpression(null, expression, excluded),
         unorderedEquals(['sortedNodes', 'nodes']));
   }
@@ -327,7 +318,7 @@
 }
 ''');
     var excluded = <String>{};
-    var expr = findNodeAtString('sortedNodes;');
+    var expr = findNode.simple('sortedNodes;');
     expect(getVariableNameSuggestionsForExpression(null, expr, excluded),
         unorderedEquals(['sortedNodes', 'nodes']));
   }
@@ -342,10 +333,7 @@
     var excluded = <String>{};
     expect(
         getVariableNameSuggestionsForExpression(
-            null,
-            findNodeAtString(
-                'getSortedNodes();', (node) => node is MethodInvocation),
-            excluded),
+            null, findNode.methodInvocation('getSortedNodes();'), excluded),
         unorderedEquals(['sortedNodes', 'nodes']));
   }
 
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart
index 957e9cb..96fb856 100644
--- a/pkg/analysis_server/test/services/correction/status_test.dart
+++ b/pkg/analysis_server/test/services/correction/status_test.dart
@@ -24,7 +24,7 @@
 class RefactoringLocationTest extends AbstractSingleUnitTest {
   Future<void> test_createLocation_forElement() async {
     await resolveTestCode('class MyClass {}');
-    var element = findElement('MyClass');
+    var element = findElement.class_('MyClass');
     // check
     var location = newLocation_fromElement(element);
     expect(location.file, testFile);
@@ -36,7 +36,7 @@
 
   Future<void> test_createLocation_forMatch() async {
     await resolveTestCode('class MyClass {}');
-    var element = findElement('MyClass');
+    var element = findElement.class_('MyClass');
     var sourceRange = range.elementName(element);
     SearchMatch match = SearchMatchImpl(
         element.source.fullName,
@@ -60,7 +60,7 @@
 main() {
 }
 ''');
-    var node = findNodeAtString('main');
+    var node = findNode.simple('main');
     // check
     var location = newLocation_fromNode(node);
     expect(location.file, testFile);
diff --git a/pkg/analysis_server/test/services/correction/util_test.dart b/pkg/analysis_server/test/services/correction/util_test.dart
index ad29a506..cba88ef 100644
--- a/pkg/analysis_server/test/services/correction/util_test.dart
+++ b/pkg/analysis_server/test/services/correction/util_test.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/util.dart';
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
@@ -33,7 +32,7 @@
   }
 }
 ''');
-    IfStatement ifStatement = findNodeAtString('if (');
+    var ifStatement = findNode.ifStatement('if (');
     var condition = ifStatement.condition;
     var result = CorrectionUtils(testAnalysisResult).invertCondition(condition);
     expect(result, expected);
diff --git a/pkg/analysis_server/test/services/linter/linter_test.dart b/pkg/analysis_server/test/services/linter/linter_test.dart
index 1cc5461..ec60e13 100644
--- a/pkg/analysis_server/test/services/linter/linter_test.dart
+++ b/pkg/analysis_server/test/services/linter/linter_test.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/lint/options_rule_validator.dart';
 import 'package:linter/src/rules.dart';
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_rename.dart b/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
index 7de0635..3a3c7aa 100644
--- a/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
+++ b/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
@@ -40,7 +40,7 @@
   /// Creates a new [RenameRefactoring] in [refactoring] for the [Element] of
   /// the [SimpleIdentifier] at the given [search] pattern.
   void createRenameRefactoringAtString(String search) {
-    var identifier = findIdentifier(search);
+    var identifier = findNode.simple(search);
     var element = identifier.writeOrReadElement;
     if (element is PrefixElement) {
       element = getImportElement(identifier);
diff --git a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
index fe8738b..aa6c028 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
@@ -28,7 +28,10 @@
   var b = test;
 }
 ''');
-    _createRefactoring('test');
+    var element = findElement.topGet('test');
+    _createRefactoringForElement(
+      element,
+    );
     // apply refactoring
     return _assertSuccessfulRefactoring('''
 int test() => 42;
@@ -60,7 +63,8 @@
   var vd = d.test;
 }
 ''');
-    _createRefactoringForString('test => 2');
+    var element = findElement.getter('test', of: 'B');
+    _createRefactoringForElement(element);
     // apply refactoring
     return _assertSuccessfulRefactoring('''
 class A {
@@ -100,7 +104,8 @@
   b.test;
 }
 ''');
-    _createRefactoringForString('test => 2');
+    var element = findElement.getter('test', of: 'B');
+    _createRefactoringForElement(element);
     // apply refactoring
     return _assertSuccessfulRefactoring('''
 import 'other.dart';
@@ -120,7 +125,8 @@
 main() {
 }
 ''');
-    _createRefactoring('test');
+    var element = findElement.topGet('test');
+    _createRefactoringForElement(element);
     // check conditions
     await _assertInitialConditions_fatal(
         'Only explicit getters can be converted to methods.');
@@ -141,19 +147,8 @@
     assertTestChangeResult(expectedCode);
   }
 
-  void _createRefactoring(String elementName) {
-    PropertyAccessorElement element =
-        findElement(elementName, ElementKind.GETTER);
-    _createRefactoringForElement(element);
-  }
-
   void _createRefactoringForElement(ExecutableElement element) {
     refactoring = ConvertGetterToMethodRefactoring(
         searchEngine, testAnalysisResult.session, element);
   }
-
-  void _createRefactoringForString(String search) {
-    ExecutableElement element = findNodeElementAtString(search);
-    _createRefactoringForElement(element);
-  }
 }
diff --git a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
index 7195696..95e8ed2 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
@@ -4,7 +4,6 @@
 
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/testing/element_search.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     show RefactoringProblemSeverity;
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -30,7 +29,8 @@
   var b = test();
 }
 ''');
-    _createRefactoring('test');
+    var element = findElement.topFunction('test');
+    _createRefactoringForElement(element);
     // apply refactoring
     return _assertSuccessfulRefactoring('''
 int get test => 42;
@@ -62,7 +62,8 @@
   var vd = d.test();
 }
 ''');
-    _createRefactoringForString('test() => 2');
+    var element = findElement.method('test', of: 'B');
+    _createRefactoringForElement(element);
     // apply refactoring
     return _assertSuccessfulRefactoring('''
 class A {
@@ -102,7 +103,8 @@
   b.test();
 }
 ''');
-    _createRefactoringForString('test() => 2');
+    var element = findElement.method('test', of: 'B');
+    _createRefactoringForElement(element);
     // apply refactoring
     return _assertSuccessfulRefactoring('''
 import 'other.dart';
@@ -124,7 +126,7 @@
   var b = test;
 }
 ''');
-    ExecutableElement element = findElement('test', ElementKind.GETTER);
+    var element = findElement.topGet('test');
     _createRefactoringForElement(element);
     // check conditions
     await _assertInitialConditions_fatal(
@@ -138,7 +140,8 @@
   var v = test(1);
 }
 ''');
-    _createRefactoring('test');
+    var element = findElement.topFunction('test');
+    _createRefactoringForElement(element);
     // check conditions
     await _assertInitialConditions_fatal(
         'Only methods without parameters can be converted to getters.');
@@ -151,7 +154,7 @@
   var v = test();
 }
 ''');
-    ExecutableElement element = findElementsByName(testUnit, 'test').single;
+    var element = findElement.localFunction('test');
     _createRefactoringForElement(element);
     // check conditions
     await _assertInitialConditions_fatal(
@@ -164,7 +167,8 @@
   A.test();
 }
 ''');
-    _createRefactoring('test');
+    var element = findElement.constructor('test');
+    _createRefactoringForElement(element);
     // check conditions
     await _assertInitialConditions_fatal(
         'Only class methods or top-level functions can be converted to getters.');
@@ -174,7 +178,8 @@
     await indexTestUnit('''
 void test() {}
 ''');
-    _createRefactoring('test');
+    var element = findElement.topFunction('test');
+    _createRefactoringForElement(element);
     // check conditions
     await _assertInitialConditions_fatal(
         'Cannot convert function returning void.');
@@ -195,18 +200,8 @@
     assertTestChangeResult(expectedCode);
   }
 
-  void _createRefactoring(String elementName) {
-    ExecutableElement element = findElement(elementName);
-    _createRefactoringForElement(element);
-  }
-
   void _createRefactoringForElement(ExecutableElement element) {
     refactoring = ConvertMethodToGetterRefactoring(
         searchEngine, testAnalysisResult.session, element);
   }
-
-  void _createRefactoringForString(String search) {
-    ExecutableElement element = findNodeElementAtString(search);
-    _createRefactoringForElement(element);
-  }
 }
diff --git a/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart b/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
index 045a97a..52da455 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -236,14 +234,13 @@
   }
 
   void _createConstructorDeclarationRefactoring(String search) {
-    ConstructorElement element = findNodeElementAtString(
-        search, (node) => node is ConstructorDeclaration);
+    var element = findNode.constructor(search).declaredElement;
     createRenameRefactoringForElement(element);
   }
 
   void _createConstructorInvocationRefactoring(String search) {
-    ConstructorElement element = findNodeElementAtString(
-        search, (node) => node is InstanceCreationExpression);
+    var instanceCreation = findNode.instanceCreation(search);
+    var element = instanceCreation.constructorName.staticElement;
     createRenameRefactoringForElement(element);
   }
 }
diff --git a/pkg/analysis_server/test/services/refactoring/rename_import_test.dart b/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
index da9fa1c..b0305ee 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_import_test.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_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -225,8 +224,7 @@
   }
 
   void _createRefactoring(String search) {
-    ImportDirective directive =
-        findNodeAtString(search, (node) => node is ImportDirective);
+    var directive = findNode.import(search);
     createRenameRefactoringForElement(directive.element);
   }
 }
diff --git a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
index 31993ea..e13ea89 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
@@ -465,10 +465,8 @@
 ''');
     await analyzeTestPackageFiles();
 
-    testAnalysisResult = await resolveFile(a);
-    testFile = testAnalysisResult.path;
-    testCode = testAnalysisResult.content;
-    testUnit = testAnalysisResult.unit;
+    testFile = a;
+    await resolveTestFile();
 
     createRenameRefactoringAtString('test});');
     expect(refactoring.refactoringName, 'Rename Parameter');
diff --git a/pkg/analysis_server/test/services/search/hierarchy_test.dart b/pkg/analysis_server/test/services/search/hierarchy_test.dart
index 4dbec50..e576ae2 100644
--- a/pkg/analysis_server/test/services/search/hierarchy_test.dart
+++ b/pkg/analysis_server/test/services/search/hierarchy_test.dart
@@ -41,12 +41,12 @@
 }
 ''');
     {
-      ClassElement classA = findElement('A');
+      var classA = findElement.class_('A');
       var members = getClassMembers(classA);
       expect(members.map((e) => e.name), unorderedEquals(['ma1', 'ma2']));
     }
     {
-      ClassElement classB = findElement('B');
+      var classB = findElement.class_('B');
       var members = getClassMembers(classB);
       expect(members.map((e) => e.name), unorderedEquals(['mb1', 'mb2']));
     }
@@ -61,8 +61,8 @@
   B() {}
 }
 ''');
-    ClassElement classA = findElement('A');
-    ClassElement classB = findElement('B');
+    var classA = findElement.class_('A');
+    var classB = findElement.class_('B');
     ClassMemberElement memberA = classA.constructors[0];
     ClassMemberElement memberB = classB.constructors[0];
     var futureA = getHierarchyMembers(searchEngine, memberA).then((members) {
@@ -89,10 +89,10 @@
   int foo;
 }
 ''');
-    ClassElement classA = findElement('A');
-    ClassElement classB = findElement('B');
-    ClassElement classC = findElement('C');
-    ClassElement classD = findElement('D');
+    var classA = findElement.class_('A');
+    var classB = findElement.class_('B');
+    var classC = findElement.class_('C');
+    var classD = findElement.class_('D');
     ClassMemberElement memberA = classA.fields[0];
     ClassMemberElement memberB = classB.fields[0];
     ClassMemberElement memberC = classC.fields[0];
@@ -124,9 +124,9 @@
   static set foo(x) {}
 }
 ''');
-    ClassElement classA = findElement('A');
-    ClassElement classB = findElement('B');
-    ClassElement classC = findElement('C');
+    var classA = findElement.class_('A');
+    var classB = findElement.class_('B');
+    var classC = findElement.class_('C');
     ClassMemberElement memberA = classA.fields[0];
     ClassMemberElement memberB = classB.fields[0];
     ClassMemberElement memberC = classC.fields[0];
@@ -162,11 +162,11 @@
   foo() {}
 }
 ''');
-    ClassElement classA = findElement('A');
-    ClassElement classB = findElement('B');
-    ClassElement classC = findElement('C');
-    ClassElement classD = findElement('D');
-    ClassElement classE = findElement('E');
+    var classA = findElement.class_('A');
+    var classB = findElement.class_('B');
+    var classC = findElement.class_('C');
+    var classD = findElement.class_('D');
+    var classE = findElement.class_('E');
     ClassMemberElement memberA = classA.methods[0];
     ClassMemberElement memberB = classB.methods[0];
     ClassMemberElement memberC = classC.methods[0];
@@ -199,8 +199,8 @@
   static foo() {}
 }
 ''');
-    ClassElement classA = findElement('A');
-    ClassElement classB = findElement('B');
+    var classA = findElement.class_('A');
+    var classB = findElement.class_('B');
     ClassMemberElement memberA = classA.methods[0];
     ClassMemberElement memberB = classB.methods[0];
     {
@@ -230,9 +230,9 @@
   foo() {}
 }
 ''');
-    ClassElement classA = findElement('A');
-    ClassElement classB = findElement('B');
-    ClassElement classD = findElement('D');
+    var classA = findElement.class_('A');
+    var classB = findElement.class_('B');
+    var classD = findElement.class_('D');
     ClassMemberElement memberA = classA.methods[0];
     ClassMemberElement memberB = classB.methods[0];
     ClassMemberElement memberD = classD.methods[0];
@@ -266,11 +266,11 @@
   foo({p}) {}
 }
 ''');
-    ClassElement classA = findElement('A');
-    ClassElement classB = findElement('B');
-    ClassElement classC = findElement('C');
-    ClassElement classD = findElement('D');
-    ClassElement classE = findElement('E');
+    var classA = findElement.class_('A');
+    var classB = findElement.class_('B');
+    var classC = findElement.class_('C');
+    var classD = findElement.class_('D');
+    var classE = findElement.class_('E');
     var parameterA = classA.methods[0].parameters[0];
     var parameterB = classB.methods[0].parameters[0];
     var parameterC = classC.methods[0].parameters[0];
@@ -313,7 +313,7 @@
   foo() {}
 }
 ''');
-    ClassElement classA = findElement('A');
+    var classA = findElement.class_('A');
     var parameterA = classA.methods[0].parameters[0];
 
     var result = await getHierarchyNamedParameters(searchEngine, parameterA);
@@ -330,7 +330,7 @@
   foo(p) {}
 }
 ''');
-    ClassElement classA = findElement('A');
+    var classA = findElement.class_('A');
     var parameterA = classA.methods[0].parameters[0];
 
     var result = await getHierarchyNamedParameters(searchEngine, parameterA);
@@ -352,7 +352,7 @@
 }
 ''');
     {
-      ClassElement classA = findElement('A');
+      var classA = findElement.class_('A');
       var members = getMembers(classA);
       expect(
           members.map((e) => e.name),
@@ -367,7 +367,7 @@
           ]));
     }
     {
-      ClassElement classB = findElement('B');
+      var classB = findElement.class_('B');
       var members = getMembers(classB);
       expect(
           members.map((e) => e.name),
@@ -395,12 +395,12 @@
 class E extends A with M {}
 class F implements A {}
 ''');
-    ClassElement classA = findElement('A');
-    ClassElement classB = findElement('B');
-    ClassElement classC = findElement('C');
-    ClassElement classD = findElement('D');
-    ClassElement classE = findElement('E');
-    ClassElement classF = findElement('F');
+    var classA = findElement.class_('A');
+    var classB = findElement.class_('B');
+    var classC = findElement.class_('C');
+    var classD = findElement.class_('D');
+    var classE = findElement.class_('E');
+    var classF = findElement.class_('F');
     var objectElement = classA.supertype.element;
     // Object
     {
@@ -451,14 +451,14 @@
 mixin M4 on M2 {}
 mixin M5 on A, C {}
 ''');
-    ClassElement a = findElement('A');
-    ClassElement b = findElement('B');
-    ClassElement c = findElement('C');
-    ClassElement m1 = findElement('M1');
-    ClassElement m2 = findElement('M2');
-    ClassElement m3 = findElement('M3');
-    ClassElement m4 = findElement('M4');
-    ClassElement m5 = findElement('M5');
+    var a = findElement.class_('A');
+    var b = findElement.class_('B');
+    var c = findElement.class_('C');
+    var m1 = findElement.mixin('M1');
+    var m2 = findElement.mixin('M2');
+    var m3 = findElement.mixin('M3');
+    var m4 = findElement.mixin('M4');
+    var m5 = findElement.mixin('M5');
     var object = a.supertype.element;
 
     _assertSuperClasses(object, []);
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 9c46788..9e59c61 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -4,141 +4,140 @@
 
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/element/element.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';
-import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/file_system/file_system.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/test_utilities/find_element.dart';
+import 'package:analyzer/src/test_utilities/find_node.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';
 
+import '../../abstract_context.dart';
+
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SearchEngineImplTest);
+    defineReflectiveTests(SearchEngineImplWithNonFunctionTypeAliasesTest);
   });
 }
 
+/// TODO(scheglov) This class does not really belong here.
+/// Consider merging it into [AbstractContextTest].
+class PubPackageResolutionTest extends AbstractContextTest {
+  ResolvedUnitResult result;
+  FindNode findNode;
+  FindElement findElement;
+
+  String get testFilePath => '$testPackageLibPath/test.dart';
+
+  void addTestFile(String content) {
+    newFile(testFilePath, content: content);
+  }
+
+  /// Resolve the file with the [path] into [result].
+  Future<void> resolveFile2(String path) async {
+    path = convertPath(path);
+
+    result = await resolveFile(path);
+    expect(result.state, ResultState.VALID);
+
+    findNode = FindNode(result.content, result.unit);
+    findElement = FindElement(result.unit);
+  }
+
+  /// Put the [code] into the test file, and resolve it.
+  Future<void> resolveTestCode(String code) {
+    addTestFile(code);
+    return resolveTestFile();
+  }
+
+  Future<void> resolveTestFile() {
+    return resolveFile2(testFilePath);
+  }
+}
+
 @reflectiveTest
-class SearchEngineImplTest with ResourceProviderMixin {
-  DartSdk sdk;
-  final ByteStore byteStore = MemoryByteStore();
-  final FileContentOverlay contentOverlay = FileContentOverlay();
-
-  final StringBuffer logBuffer = StringBuffer();
-  PerformanceLog logger;
-
-  AnalysisDriverScheduler scheduler;
-
-  void setUp() {
-    sdk = MockSdk(resourceProvider: resourceProvider);
-    logger = PerformanceLog(logBuffer);
-    scheduler = AnalysisDriverScheduler(logger);
-    scheduler.start();
+class SearchEngineImplTest extends PubPackageResolutionTest {
+  SearchEngineImpl get searchEngine {
+    return SearchEngineImpl(allDrivers);
   }
 
   Future<void> test_membersOfSubtypes_hasMembers() async {
-    var a = newFile('/test/a.dart', content: '''
+    newFile('$testPackageLibPath/a.dart', content: '''
 class A {
   void a() {}
   void b() {}
   void c() {}
 }
-''').path;
-    var b = newFile('/test/b.dart', content: '''
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
 import 'a.dart';
 class B extends A {
   void a() {}
 }
-''').path;
-    var c = newFile('/test/c.dart', content: '''
+''');
+
+    newFile('$testPackageLibPath/c.dart', content: '''
 import 'a.dart';
 class C extends A {
   void b() {}
 }
-''').path;
+''');
 
-    var driver1 = _newDriver();
-    var driver2 = _newDriver();
+    await resolveFile2('$testPackageLibPath/a.dart');
+    var A = findElement.class_('A');
 
-    driver1.addFile(a);
-    driver2.addFile(b);
-    driver2.addFile(c);
-    await scheduler.waitForIdle();
-
-    var resultA = await driver1.getResult(a);
-    var elementA = resultA.unit.declaredElement.types[0];
-
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
-    var members = await searchEngine.membersOfSubtypes(elementA);
+    var members = await searchEngine.membersOfSubtypes(A);
     expect(members, unorderedEquals(['a', 'b']));
   }
 
   Future<void> test_membersOfSubtypes_noMembers() async {
-    var a = newFile('/test/a.dart', content: '''
+    newFile('$testPackageLibPath/a.dart', content: '''
 class A {
   void a() {}
   void b() {}
   void c() {}
 }
-''').path;
-    var b = newFile('/test/b.dart', content: '''
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
 import 'a.dart';
 class B extends A {}
-''').path;
+''');
 
-    var driver = _newDriver();
+    await resolveFile2('$testPackageLibPath/a.dart');
+    var A = findElement.class_('A');
 
-    driver.addFile(a);
-    driver.addFile(b);
-    await scheduler.waitForIdle();
-
-    var resultA = await driver.getResult(a);
-    var elementA = resultA.unit.declaredElement.types[0];
-
-    var searchEngine = SearchEngineImpl([driver]);
-    var members = await searchEngine.membersOfSubtypes(elementA);
+    var members = await searchEngine.membersOfSubtypes(A);
     expect(members, isEmpty);
   }
 
   Future<void> test_membersOfSubtypes_noSubtypes() async {
-    var a = newFile('/test/a.dart', content: '''
+    newFile('$testPackageLibPath/a.dart', content: '''
 class A {
   void a() {}
   void b() {}
   void c() {}
 }
-''').path;
-    var b = newFile('/test/b.dart', content: '''
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
 import 'a.dart';
 class B {
   void a() {}
 }
-''').path;
+''');
 
-    var driver = _newDriver();
+    await resolveFile2('$testPackageLibPath/a.dart');
+    var A = findElement.class_('A');
 
-    driver.addFile(a);
-    driver.addFile(b);
-    await scheduler.waitForIdle();
-
-    var resultA = await driver.getResult(a);
-    var elementA = resultA.unit.declaredElement.types[0];
-
-    var searchEngine = SearchEngineImpl([driver]);
-    var members = await searchEngine.membersOfSubtypes(elementA);
+    var members = await searchEngine.membersOfSubtypes(A);
     expect(members, isNull);
   }
 
   Future<void> test_membersOfSubtypes_private() async {
-    var a = newFile('/test/a.dart', content: '''
+    newFile('$testPackageLibPath/a.dart', content: '''
 class A {
   void a() {}
   void _b() {}
@@ -147,8 +146,9 @@
 class B extends A {
   void _b() {}
 }
-''').path;
-    var b = newFile('/test/b.dart', content: '''
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
 import 'a.dart';
 class C extends A {
   void a() {}
@@ -157,38 +157,25 @@
 class D extends B {
   void _c() {}
 }
-''').path;
+''');
 
-    var driver1 = _newDriver();
-    var driver2 = _newDriver();
+    await resolveFile2('$testPackageLibPath/a.dart');
+    var A = findElement.class_('A');
 
-    driver1.addFile(a);
-    driver2.addFile(b);
-    await scheduler.waitForIdle();
-
-    var resultA = await driver1.getResult(a);
-    var elementA = resultA.unit.declaredElement.types[0];
-
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
-    var members = await searchEngine.membersOfSubtypes(elementA);
+    var members = await searchEngine.membersOfSubtypes(A);
     expect(members, unorderedEquals(['a', '_b']));
   }
 
   Future<void> test_searchAllSubtypes() async {
-    var p = newFile('/test.dart', content: '''
+    await resolveTestCode('''
 class T {}
 class A extends T {}
 class B extends A {}
 class C implements B {}
-''').path;
+''');
 
-    var driver = _newDriver();
-    driver.addFile(p);
+    var element = findElement.class_('T');
 
-    var resultA = await driver.getResult(p);
-    var element = resultA.unit.declaredElement.types[0];
-
-    var searchEngine = SearchEngineImpl([driver]);
     var subtypes = await searchEngine.searchAllSubtypes(element);
     expect(subtypes, hasLength(3));
     _assertContainsClass(subtypes, 'A');
@@ -197,35 +184,31 @@
   }
 
   Future<void> test_searchAllSubtypes_acrossDrivers() async {
-    var a = newFile('/test/a.dart', content: '''
+    var aaaRootPath = _configureForPackage_aaa();
+
+    newFile('$aaaRootPath/lib/a.dart', content: '''
 class T {}
 class A extends T {}
-''').path;
-    var b = newFile('/test/b.dart', content: '''
-import 'a.dart';
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+import 'package:aaa/a.dart';
 class B extends A {}
 class C extends B {}
-''').path;
+''');
 
-    var driver1 = _newDriver();
-    var driver2 = _newDriver();
+    await resolveFile2('$aaaRootPath/lib/a.dart');
+    var element = findElement.class_('T');
 
-    driver1.addFile(a);
-    driver2.addFile(b);
-
-    var resultA = await driver1.getResult(a);
-    var element = resultA.unit.declaredElement.types[0];
-
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
     var subtypes = await searchEngine.searchAllSubtypes(element);
     expect(subtypes, hasLength(3));
-    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'A')));
-    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'B')));
-    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'C')));
+    _assertContainsClass(subtypes, 'A');
+    _assertContainsClass(subtypes, 'B');
+    _assertContainsClass(subtypes, 'C');
   }
 
   Future<void> test_searchAllSubtypes_mixin() async {
-    var p = newFile('/test.dart', content: '''
+    await resolveTestCode('''
 class T {}
 
 mixin A on T {}
@@ -235,15 +218,10 @@
 
 mixin D on C {}
 mixin E implements C {}
-''').path;
+''');
 
-    var driver = _newDriver();
-    driver.addFile(p);
+    var element = findElement.class_('T');
 
-    var resultA = await driver.getResult(p);
-    var element = resultA.unit.declaredElement.types[0];
-
-    var searchEngine = SearchEngineImpl([driver]);
     var subtypes = await searchEngine.searchAllSubtypes(element);
     expect(subtypes, hasLength(5));
     _assertContainsClass(subtypes, 'A');
@@ -268,20 +246,9 @@
 int test;
 ''';
 
-    var a = newFile('/test/a.dart', content: codeA).path;
-    var b = newFile('/test/b.dart', content: codeB).path;
+    newFile('$testPackageLibPath/a.dart', content: codeA);
+    newFile('$testPackageLibPath/b.dart', content: codeB);
 
-    var driver1 = _newDriver();
-    var driver2 = _newDriver();
-
-    driver1.addFile(a);
-    driver2.addFile(b);
-
-    while (scheduler.isAnalyzing) {
-      await Future.delayed(Duration(milliseconds: 1));
-    }
-
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
     var matches = await searchEngine.searchMemberDeclarations('test');
     expect(matches, hasLength(2));
 
@@ -299,28 +266,22 @@
   }
 
   Future<void> test_searchMemberReferences() async {
-    var a = newFile('/test/a.dart', content: '''
+    newFile('$testPackageLibPath/a.dart', content: '''
 class A {
   int test;
 }
 foo(p) {
   p.test;
 }
-''').path;
-    var b = newFile('/test/b.dart', content: '''
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
 import 'a.dart';
 bar(p) {
   p.test = 1;
 }
-''').path;
+''');
 
-    var driver1 = _newDriver();
-    var driver2 = _newDriver();
-
-    driver1.addFile(a);
-    driver2.addFile(b);
-
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
     var matches = await searchEngine.searchMemberReferences('test');
     expect(matches, hasLength(2));
     expect(
@@ -334,25 +295,19 @@
   }
 
   Future<void> test_searchReferences() async {
-    var a = newFile('/test/a.dart', content: '''
+    var aaaRootPath = _configureForPackage_aaa();
+
+    newFile('$aaaRootPath/lib/a.dart', content: '''
 class T {}
 T a;
-''').path;
-    var b = newFile('/test/b.dart', content: '''
-import 'a.dart';
+''');
+
+    await resolveTestCode('''
+import 'package:aaa/a.dart';
 T b;
-''').path;
+''');
 
-    var driver1 = _newDriver();
-    var driver2 = _newDriver();
-
-    driver1.addFile(a);
-    driver2.addFile(b);
-
-    var resultA = await driver1.getResult(a);
-    var element = resultA.unit.declaredElement.types[0];
-
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
+    var element = findElement.importFind('package:aaa/a.dart').class_('T');
     var matches = await searchEngine.searchReferences(element);
     expect(matches, hasLength(2));
     expect(
@@ -362,24 +317,20 @@
   }
 
   Future<void> test_searchReferences_discover_owned() async {
-    var t = newFile('/test/lib/t.dart', content: '''
-import 'package:aaa/a.dart';
-int t;
-''').path;
-    var a = newFile('/aaa/lib/a.dart', content: '''
+    var aaaRootPath = _configureForPackage_aaa();
+
+    var a = newFile('$aaaRootPath/lib/a.dart', content: '''
 int a;
 ''').path;
 
-    var driver1 = _newDriver(packageUriResolver: _mapUriResolver('aaa', a));
-    var driver2 = _newDriver();
+    var t = newFile('$testPackageLibPath/lib/t.dart', content: '''
+import 'package:aaa/a.dart';
+int t;
+''').path;
 
-    driver1.addFile(t);
-    driver2.addFile(a);
-
-    var coreLib = await driver1.getLibraryByUri('dart:core');
+    var coreLib = await driverFor(testFilePath).getLibraryByUri('dart:core');
     var intElement = coreLib.getType('int');
 
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
     var matches = await searchEngine.searchReferences(intElement);
 
     void assertHasOne(String path, String name) {
@@ -394,26 +345,18 @@
   }
 
   Future<void> test_searchTopLevelDeclarations() async {
-    var a = newFile('/test/a.dart', content: '''
+    newFile('$testPackageLibPath/a.dart', content: '''
 class A {}
 int a;
-''').path;
-    var b = newFile('/test/b.dart', content: '''
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
 class B {}
 get b => 42;
-''').path;
+''');
 
-    var driver1 = _newDriver();
-    var driver2 = _newDriver();
+    await _ensureContainedFilesKnown();
 
-    driver1.addFile(a);
-    driver2.addFile(b);
-
-    while (scheduler.isAnalyzing) {
-      await Future.delayed(Duration(milliseconds: 1));
-    }
-
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
     var matches = await searchEngine.searchTopLevelDeclarations('.*');
     matches.removeWhere((match) => match.libraryElement.isInSdk);
     expect(matches, hasLength(4));
@@ -431,31 +374,27 @@
   }
 
   Future<void> test_searchTopLevelDeclarations_dependentPackage() async {
-    var a = newFile('/a/lib/a.dart', content: '''
-class A {}
-''').path;
-    var driver1 = _newDriver();
-    driver1.addFile(a);
+    var aaaRootPath = _configureForPackage_aaa();
 
-    // The package:b uses the class A from the package:a,
-    // so it sees the declaration the element A.
-    var b = newFile('/b/lib/b.dart', content: '''
-import 'package:a/a.dart';
+    newFile('$aaaRootPath/lib/a.dart', content: '''
+class A {}
+''');
+
+    // The `package:test` uses the class `A` from the `package:aaa`.
+    // So it sees the declaration the element `A`.
+    newFile('$testFilePath', content: '''
+import 'package:aaa/a.dart';
 class B extends A {}
 ''');
-    var driver2 = _newDriver(packageUriResolver: _mapUriResolver('a', a));
-    driver2.addFile(b.path);
 
-    while (scheduler.isAnalyzing) {
-      await Future.delayed(Duration(milliseconds: 1));
-    }
+    await _ensureContainedFilesKnown();
 
-    var searchEngine = SearchEngineImpl([driver1, driver2]);
     var matches = await searchEngine.searchTopLevelDeclarations('.*');
-    // We get exactly two items: A and B.
-    // I.e. we get exactly one A.
-    expect(
-        matches.where((match) => !match.libraryElement.isInSdk), hasLength(2));
+    matches.removeWhere((match) => match.libraryElement.isInSdk);
+
+    // We get exactly two items: `A` and `B`.
+    // Specifically, we get exactly one `A`.
+    expect(matches, hasLength(2));
 
     void assertHasOneElement(String name) {
       var nameMatches = matches.where((SearchMatch m) =>
@@ -467,28 +406,64 @@
     assertHasOneElement('B');
   }
 
-  UriResolver _mapUriResolver(String packageName, String path) {
-    return PackageMapUriResolver(resourceProvider, {
-      packageName: [resourceProvider.getFile(path).parent]
-    });
+  String _configureForPackage_aaa() {
+    var aaaRootPath = '$workspaceRootPath/aaa';
+
+    writePackageConfig(
+      '$aaaRootPath/.dart_tool/package_config.json',
+      PackageConfigFileBuilder()..add(name: 'aaa', rootPath: aaaRootPath),
+    );
+
+    writeTestPackageConfig(
+      config: PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaRootPath),
+    );
+
+    return aaaRootPath;
   }
 
-  AnalysisDriver _newDriver({UriResolver packageUriResolver}) {
-    var resolvers = <UriResolver>[
-      DartUriResolver(sdk),
-      ResourceUriResolver(resourceProvider)
-    ];
-    if (packageUriResolver != null) {
-      resolvers.add(packageUriResolver);
+  Future _ensureContainedFilesKnown() async {
+    for (var driver in allDrivers) {
+      var contextRoot = driver.analysisContext.contextRoot;
+      for (var file in contextRoot.analyzedFiles()) {
+        if (file.endsWith('.dart')) {
+          await driver.getUnitElement(file);
+        }
+      }
     }
-    resolvers.add(ResourceUriResolver(resourceProvider));
-
-    return AnalysisDriver(scheduler, logger, resourceProvider, byteStore,
-        contentOverlay, null, SourceFactory(resolvers), AnalysisOptionsImpl(),
-        packages: Packages.empty, enableIndex: true);
   }
 
   static void _assertContainsClass(Set<ClassElement> subtypes, String name) {
     expect(subtypes, contains(predicate((ClassElement e) => e.name == name)));
   }
 }
+
+@reflectiveTest
+class SearchEngineImplWithNonFunctionTypeAliasesTest
+    extends SearchEngineImplTest with WithNonFunctionTypeAliasesMixin {
+  Future<void> test_searchReferences_typeAlias_interfaceType() async {
+    await resolveTestCode('''
+typedef A<T> = Map<T, String>;
+
+void f(A<int> a, A<double> b) {}
+''');
+
+    var element = findElement.typeAlias('A');
+    var matches = await searchEngine.searchReferences(element);
+
+    Matcher hasOne(Element element, String search) {
+      return predicate((SearchMatch match) {
+        return match.element == element &&
+            match.sourceRange.offset == findNode.offset(search);
+      });
+    }
+
+    expect(
+      matches,
+      unorderedMatches([
+        hasOne(findElement.parameter('a'), 'A<int>'),
+        hasOne(findElement.parameter('b'), 'A<double>'),
+      ]),
+    );
+  }
+}
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 0f3fa04..03534e7 100644
--- a/pkg/analysis_server/test/src/computer/folding_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
@@ -17,6 +17,12 @@
 
 @reflectiveTest
 class FoldingComputerTest extends AbstractContextTest {
+  static const commentKinds = {
+    FoldingKind.FILE_HEADER,
+    FoldingKind.COMMENT,
+    FoldingKind.DOCUMENTATION_COMMENT
+  };
+
   String sourcePath;
 
   @override
@@ -125,15 +131,72 @@
 
   Future<void> test_comment_is_not_considered_file_header() async {
     var content = """
-// This is not the file header
-// It's just a comment
+// This is not the file header/*1:EXC*/
+// It's just a comment/*1:INC:COMMENT*/
 main() {}
 """;
 
     // Since there are no region comment markers above
     // just check the length instead of the contents
     final regions = await _computeRegions(content);
-    expect(regions, hasLength(0));
+    _compareRegions(regions, content);
+  }
+
+  Future<void> test_comment_multiline() async {
+    var content = '''
+main() {
+/*/*1:EXC*/
+ * comment 1
+ *//*1:EXC:COMMENT*/
+
+/* this comment starts on the same line as delimeters/*2:EXC*/
+ * second line
+ *//*2:EXC:COMMENT*/
+}
+''';
+
+    final regions = await _computeRegions(content);
+    _compareRegions(regions, content, commentKinds);
+  }
+
+  Future<void> test_comment_singleFollowedByBlankLine() async {
+    var content = '''
+main() {
+// this is/*1:EXC*/
+// a comment/*1:INC:COMMENT*/
+/// this is not part of it
+}
+''';
+
+    final regions = await _computeRegions(content);
+    _compareRegions(regions, content, commentKinds);
+  }
+
+  Future<void> test_comment_singleFollowedByMulti() async {
+    var content = '''
+main() {
+  // this is/*1:EXC*/
+  // a comment/*1:INC:COMMENT*/
+  /* this is not part of it */
+  String foo;
+}
+''';
+
+    final regions = await _computeRegions(content);
+    _compareRegions(regions, content, commentKinds);
+  }
+
+  Future<void> test_comment_singleFollowedByTripleSlash() async {
+    var content = '''
+main() {
+// this is/*1:EXC*/
+// a comment/*1:INC:COMMENT*/
+/// this is not part of it
+}
+''';
+
+    final regions = await _computeRegions(content);
+    _compareRegions(regions, content, commentKinds);
   }
 
   Future<void> test_constructor_invocations() async {
@@ -164,7 +227,7 @@
 """;
 
     final regions = await _computeRegions(content);
-    _compareRegions(regions, content);
+    _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
   }
 
   Future<void> test_file_header_does_not_include_block_comments() async {
@@ -179,7 +242,7 @@
 """;
 
     final regions = await _computeRegions(content);
-    expect(regions, hasLength(0));
+    _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
   }
 
   Future<void> test_file_header_with_no_function_comment() async {
@@ -191,7 +254,7 @@
 ''';
 
     final regions = await _computeRegions(content);
-    _compareRegions(regions, content);
+    _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
   }
 
   Future<void> test_file_header_with_non_end_of_line_comment() async {
@@ -204,7 +267,7 @@
 """;
 
     final regions = await _computeRegions(content);
-    _compareRegions(regions, content);
+    _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
   }
 
   Future<void> test_file_header_with_script_prefix() async {
@@ -219,6 +282,19 @@
 """;
 
     final regions = await _computeRegions(content);
+    _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
+  }
+
+  Future<void> test_fileHeader_singleFollowedByBlank() async {
+    var content = '''
+// this is/*1:EXC*/
+// a file header/*1:INC:FILE_HEADER*/
+
+// this is not part of it
+main() {}
+''';
+
+    final regions = await _computeRegions(content);
     _compareRegions(regions, content);
   }
 
@@ -263,7 +339,7 @@
     var content = '''
 // Content before
 
-/*1:EXC*//// This is a doc comment
+/// This is a doc comment/*1:EXC*/
 /// that spans lines/*1:INC:DOCUMENTATION_COMMENT*/
 main() {/*2:INC*/
   print("Hello, world!");
@@ -434,11 +510,19 @@
 
   /// Compares provided folding regions with expected
   /// regions extracted from the comments in the provided content.
-  void _compareRegions(List<FoldingRegion> regions, String content) {
+  ///
+  /// If [onlyKinds] is supplied only regions of that type will be compared.
+  void _compareRegions(List<FoldingRegion> regions, String content,
+      [Set<FoldingKind> onlyKinds]) {
     // Find all numeric markers for region starts.
     final regex = RegExp(r'/\*(\d+):(INC|EXC)\*/');
     final expectedRegions = regex.allMatches(content);
 
+    if (onlyKinds != null) {
+      regions =
+          regions.where((region) => onlyKinds.contains(region.kind)).toList();
+    }
+
     // Check we didn't get more than expected, since the loop below only
     // checks for the presence of matches, not absence.
     expect(regions, hasLength(expectedRegions.length));
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 d251985..5880e68 100644
--- a/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
@@ -66,6 +66,23 @@
     _check(HighlightRegionType.KEYWORD, 'null');
   }
 
+  Future<void> test_string_interpolated() async {
+    await _computeHighlights(r'''
+class A {
+  String b(String c) => c;
+}
+var foo = A();
+var bar = A();
+var s = 'test1 $foo test2 ${bar.b('test3')}';
+''');
+    _check(HighlightRegionType.LITERAL_STRING, "'test1 ");
+    _check(HighlightRegionType.TOP_LEVEL_GETTER_REFERENCE, 'foo');
+    _check(HighlightRegionType.LITERAL_STRING, ' test2 ');
+    _check(HighlightRegionType.TOP_LEVEL_GETTER_REFERENCE, 'bar');
+    _check(HighlightRegionType.INSTANCE_METHOD_REFERENCE, 'b');
+    _check(HighlightRegionType.LITERAL_STRING, "'test3'");
+  }
+
   Future<void> test_throwExpression() async {
     await _computeHighlights('''
 void main() {
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
index 3fac860..095ebcb 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
@@ -4,9 +4,7 @@
 
 import 'dart:convert';
 
-import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_constants.dart';
-import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/domain_completion.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
index 156c4b4..7ed929c 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.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:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:meta/meta.dart';
 import 'package:test/test.dart';
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
index 4a2d307..6d9e3fc 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
@@ -67,6 +67,25 @@
     expect(includedIdSet, contains(asyncSet.id));
   }
 
+  Future<void> test_dart_afterRecovery() async {
+    addTestFile('');
+    // Wait for a known set to be available.
+    await waitForSetWithUri('dart:math');
+
+    // Ensure the set is returned in the results.
+    var results = await _getSuggestions(testFile, 0);
+    expect(results.includedSuggestionSets, isNotEmpty);
+
+    // Force the server to rebuild all contexts, as happens when the file watcher
+    // fails on Windows.
+    // https://github.com/dart-lang/sdk/issues/44650
+    server.contextManager.refresh(null);
+
+    // Ensure the set is still returned after the rebuild.
+    results = await _getSuggestions(testFile, 0);
+    expect(results.includedSuggestionSets, isNotEmpty);
+  }
+
   Future<void> test_dart_instanceCreationExpression() async {
     addTestFile(r'''
 main() {
@@ -102,8 +121,8 @@
     expect(fff.defaultArgumentListTextRanges, [0, 3, 5, 3]);
 
     var ggg = aSet.items.singleWhere((e) => e.label == 'ggg');
-    expect(ggg.defaultArgumentListString, 'bbb: null, ccc: null');
-    expect(ggg.defaultArgumentListTextRanges, [5, 4, 16, 4]);
+    expect(ggg.defaultArgumentListString, 'bbb: bbb, ccc: ccc');
+    expect(ggg.defaultArgumentListTextRanges, [5, 3, 15, 3]);
   }
 
   Future<void> test_displayUri_file() async {
diff --git a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
index 2235fe2..1435f6c 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
@@ -6,7 +6,6 @@
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
-import 'package:analyzer/instrumentation/service.dart';
 import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError;
@@ -16,6 +15,7 @@
 import 'package:test/test.dart';
 
 import '../../../../abstract_single_unit.dart';
+import '../../../../utils/test_instrumentation_service.dart';
 
 export 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 
@@ -193,7 +193,7 @@
 
   Future<List<Assist>> _computeAssists() async {
     var context = DartAssistContextImpl(
-      InstrumentationService.NULL_SERVICE,
+      TestInstrumentationService(),
       workspace,
       testAnalysisResult,
       _offset,
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart
index 6f8f3d2..813e4bc 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_double_quoted_string_test.dart
@@ -54,6 +54,16 @@
 ''');
   }
 
+  Future<void> test_one_interpolation_unterminated() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode(r'''
+void f(int a) {
+  '$a
+}
+''');
+    await assertNoAssistAt("'");
+  }
+
   Future<void> test_one_raw() async {
     await resolveTestCode('''
 main() {
@@ -80,6 +90,16 @@
 ''');
   }
 
+  Future<void> test_one_simple_unterminated_empty() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  '
+}
+''');
+    await assertNoAssistAt("'");
+  }
+
   Future<void> test_three_embeddedTarget() async {
     await resolveTestCode("""
 main() {
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_multiline_string_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_multiline_string_test.dart
index 316515d..1e52915 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_to_multiline_string_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_multiline_string_test.dart
@@ -103,6 +103,26 @@
 ''');
   }
 
+  Future<void> test_doubleQuoted_unterminated() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  "abc
+}
+''');
+    await assertNoAssistAt('"');
+  }
+
+  Future<void> test_doubleQuoted_unterminated_empty() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  "
+}
+''');
+    await assertNoAssistAt('"');
+  }
+
   Future<void> test_singleQuoted() async {
     await resolveTestCode('''
 main() {
@@ -177,4 +197,24 @@
 }
 """);
   }
+
+  Future<void> test_singleQuoted_unterminated() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  'abc
+}
+''');
+    await assertNoAssistAt("'");
+  }
+
+  Future<void> test_singleQuoted_unterminated_empty() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  '
+}
+''');
+    await assertNoAssistAt("'");
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart
index 9e925c0..4214de8 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_single_quoted_string_test.dart
@@ -55,6 +55,16 @@
 ''');
   }
 
+  Future<void> test_one_interpolation_unterminated() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode(r'''
+void f(int a) {
+  "$a
+}
+''');
+    await assertNoAssistAt('"');
+  }
+
   Future<void> test_one_raw() async {
     await resolveTestCode('''
 main() {
@@ -92,6 +102,16 @@
     await assertNoAssist();
   }
 
+  Future<void> test_one_simple_unterminated_empty() async {
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+void f() {
+  "
+}
+''');
+    await assertNoAssistAt('"');
+  }
+
   Future<void> test_three_embeddedTarget() async {
     await resolveTestCode('''
 main() {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_late_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_late_test.dart
index 9558f70..b44ebfc 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_late_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_late_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -36,6 +37,51 @@
   @override
   FixKind get kind => DartFixKind.ADD_LATE;
 
+  Future<void> test_changeInImportedLib() async {
+    addSource('/home/test/lib/a.dart', '''
+class C {
+  final String s;
+}
+''');
+    await resolveTestCode('''
+import 'a.dart';
+
+void f(C c) {
+  c.s = '';
+}
+''');
+    await assertHasFix('''
+class C {
+  late final String s;
+}
+''', target: '/home/test/lib/a.dart');
+  }
+
+  @FailingTest(reason: 'The lint does not fire for parts.')
+  Future<void> test_changeInPart() async {
+    addSource('/home/test/lib/a.dart', '''
+part 'test.dart';
+
+class C {
+  final String s;
+}
+''');
+    await resolveTestCode('''
+part of 'a.dart';
+
+void f(C c) {
+  c.s = '';
+}
+''');
+    await assertHasFix('''
+part 'test.dart';
+
+class C {
+  late final String s;
+}
+''', target: '/home/test/lib/a.dart');
+  }
+
   Future<void> test_withFinal() async {
     await resolveTestCode('''
 class C {
@@ -44,11 +90,76 @@
 ''');
     await assertHasFix('''
 class C {
-  final late String s;
+  late final String s;
 }
 ''');
   }
 
+  Future<void> test_withFinalAssignedInConstructor() async {
+    await resolveTestCode('''
+class C {
+  final String s;
+  C() {
+    s = '';
+  }
+}
+''');
+    await assertHasFix('''
+class C {
+  late final String s;
+  C() {
+    s = '';
+  }
+}
+''',
+        errorFilter: (error) =>
+            error.errorCode == CompileTimeErrorCode.ASSIGNMENT_TO_FINAL);
+  }
+
+  Future<void> test_withFinalAssignedInLibrary() async {
+    await resolveTestCode('''
+class C {
+  final String s;
+}
+
+void f(C c) {
+  c.s = '';
+}
+''');
+    await assertHasFix('''
+class C {
+  late final String s;
+}
+
+void f(C c) {
+  c.s = '';
+}
+''',
+        errorFilter: (error) =>
+            error.errorCode == CompileTimeErrorCode.ASSIGNMENT_TO_FINAL);
+  }
+
+  Future<void> test_withFinalStaticAssignedInConstructor() async {
+    await resolveTestCode('''
+class C {
+  static final String s;
+  C() {
+    s = '';
+  }
+}
+''');
+    await assertHasFix('''
+class C {
+  static late final String s;
+  C() {
+    s = '';
+  }
+}
+''',
+        errorFilter: (error) =>
+            error.errorCode == CompileTimeErrorCode.ASSIGNMENT_TO_FINAL);
+  }
+
   Future<void> test_withLate() async {
     await resolveTestCode('''
 class C {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_null_check_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_null_check_test.dart
index dc640e4..09750df 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_null_check_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_null_check_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -97,6 +99,83 @@
 ''');
   }
 
+  Future<void> test_forEachWithDeclarationCondition() async {
+    await resolveTestCode('''
+void f (List<String>? args) {
+  for (var e in args) print(e);
+}
+''');
+    await assertHasFix('''
+void f (List<String>? args) {
+  for (var e in args!) print(e);
+}
+''');
+  }
+
+  Future<void>
+      test_forEachWithDeclarationCondition_differByMoreThanNullability() async {
+    await resolveTestCode('''
+void f (List<int>? args) {
+  for (String e in args) print(e);
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_forEachWithIdentifierCondition() async {
+    await resolveTestCode('''
+void f (List<String>? args) {
+  String s = "";
+  for (s in args) print(s);
+}
+''');
+    await assertHasFix('''
+void f (List<String>? args) {
+  String s = "";
+  for (s in args!) print(s);
+}
+''');
+  }
+
+  Future<void>
+      test_forEachWithIdentifierCondition_differByMoreThanNullability() async {
+    await resolveTestCode('''
+void f (List<int>? args) {
+  String s = "";
+  for (s in args) print(s);
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_functionExpressionInvocation() async {
+    await resolveTestCode('''
+int f(C c) => c.func();
+class C {
+  int Function()? get func => null;
+}
+''');
+    await assertHasFix('''
+int f(C c) => c.func!();
+class C {
+  int Function()? get func => null;
+}
+''');
+  }
+
+  Future<void> test_indexExpression() async {
+    await resolveTestCode('''
+void f (List<String>? args) {
+  print(args[0]);
+}
+''');
+    await assertHasFix('''
+void f (List<String>? args) {
+  print(args![0]);
+}
+''');
+  }
+
   Future<void> test_initializer() async {
     await resolveTestCode('''
 void f(int? x) {
@@ -112,6 +191,21 @@
 ''');
   }
 
+  Future<void> test_initializer_assignable() async {
+    await resolveTestCode('''
+void f(int? x) {
+  num y = x;
+  print(y);
+}
+''');
+    await assertHasFix('''
+void f(int? x) {
+  num y = x!;
+  print(y);
+}
+''');
+  }
+
   Future<void> test_initializer_differByMoreThanNullability() async {
     await resolveTestCode('''
 void f(String x) {
@@ -121,4 +215,157 @@
 ''');
     await assertNoFix();
   }
+
+  Future<void> test_methodInvocation() async {
+    await resolveTestCode('''
+String f(String? s) => s.substring(0);
+''');
+    await assertHasFix('''
+String f(String? s) => s!.substring(0);
+''');
+  }
+
+  Future<void> test_prefixedIdentifier() async {
+    await resolveTestCode('''
+int f(String? s) => s.length;
+''');
+    await assertHasFix('''
+int f(String? s) => s!.length;
+''');
+  }
+
+  Future<void> test_propertyAccess() async {
+    await resolveTestCode('''
+int f(String? s) => (s).length;
+''');
+    await assertHasFix('''
+int f(String? s) => (s)!.length;
+''');
+  }
+
+  Future<void> test_spreadList() async {
+    await resolveTestCode('''
+void f (List<String>? args) {
+  [...args];
+}
+''');
+    await assertHasFix('''
+void f (List<String>? args) {
+  [...args!];
+}
+''');
+  }
+
+  Future<void> test_spreadList_differByMoreThanNullability() async {
+    await resolveTestCode('''
+void f (List<int>? args) {
+  <String>[...args];
+}
+''');
+    await assertNoFix(
+        errorFilter: (AnalysisError error) =>
+            error.errorCode !=
+            CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
+  }
+
+  Future<void> test_spreadMap() async {
+    await resolveTestCode('''
+void f (Map<int, String>? args) {
+  print({...args});
+}
+''');
+    await assertHasFix('''
+void f (Map<int, String>? args) {
+  print({...args!});
+}
+''');
+  }
+
+  Future<void> test_spreadSet() async {
+    await resolveTestCode('''
+void f (List<String>? args) {
+  print({...args});
+}
+''');
+    await assertHasFix('''
+void f (List<String>? args) {
+  print({...args!});
+}
+''');
+  }
+
+  Future<void> test_yieldEach_closure() async {
+    await resolveTestCode('''
+g(Iterable<String> Function() cb) {}
+f(List<String>? args) {
+  g(() sync* {
+    yield* args;
+  });
+}
+''');
+    await assertHasFix('''
+g(Iterable<String> Function() cb) {}
+f(List<String>? args) {
+  g(() sync* {
+    yield* args!;
+  });
+}
+''',
+        errorFilter: (AnalysisError error) =>
+            error.errorCode != CompileTimeErrorCode.YIELD_OF_INVALID_TYPE);
+  }
+
+  Future<void> test_yieldEach_localFunction() async {
+    await resolveTestCode('''
+g() {
+  Iterable<String> f(List<String>? args) sync* {
+    yield* args;
+  }
+}
+''');
+    await assertHasFix('''
+g() {
+  Iterable<String> f(List<String>? args) sync* {
+    yield* args!;
+  }
+}
+''',
+        errorFilter: (AnalysisError error) =>
+            error.errorCode ==
+            CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH);
+  }
+
+  Future<void> test_yieldEach_method() async {
+    await resolveTestCode('''
+class C {
+  Iterable<String> f(List<String>? args) sync* {
+    yield* args;
+  }
+}
+''');
+    await assertHasFix('''
+class C {
+  Iterable<String> f(List<String>? args) sync* {
+    yield* args!;
+  }
+}
+''',
+        errorFilter: (AnalysisError error) =>
+            error.errorCode != CompileTimeErrorCode.YIELD_OF_INVALID_TYPE);
+  }
+
+  Future<void> test_yieldEach_topLevel() async {
+    await resolveTestCode('''
+Iterable<String> f(List<String>? args) sync* {
+  yield* args;
+}
+''');
+    await assertHasFix('''
+Iterable<String> f(List<String>? args) sync* {
+  yield* args!;
+}
+''',
+        errorFilter: (AnalysisError error) =>
+            error.errorCode != CompileTimeErrorCode.YIELD_OF_INVALID_TYPE);
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/remove_lint_test.dart b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/remove_lint_test.dart
new file mode 100644
index 0000000..deb6eb4
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/remove_lint_test.dart
@@ -0,0 +1,81 @@
+// 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:linter/src/rules.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveLintTest);
+  });
+}
+
+@reflectiveTest
+class RemoveLintTest extends AnalysisOptionsFixTest {
+  void setUp() {
+    registerLintRules();
+  }
+
+  Future<void> test_deprecated() async {
+    await assertHasFix('''
+linter:
+  rules:
+    - camel_case_types
+    - super_goes_last
+''', '''
+linter:
+  rules:
+    - camel_case_types
+''');
+  }
+
+  Future<void> test_deprecated_only() async {
+    await assertHasFix('''
+linter:
+  rules:
+    - super_goes_last
+''', '''
+''');
+  }
+
+  Future<void> test_deprecated_withSectionAfter() async {
+    await assertHasFix('''
+linter:
+  rules:
+    - camel_case_types
+    - super_goes_last
+section:
+  - foo
+''', '''
+linter:
+  rules:
+    - camel_case_types
+section:
+  - foo
+''');
+  }
+
+  Future<void> test_deprecated_withSectionBefore() async {
+    await assertHasFix('''
+analyzer:
+  exclude:
+    - test/data/**
+
+linter:
+  rules:
+    - camel_case_types
+    - super_goes_last
+''', '''
+analyzer:
+  exclude:
+    - test/data/**
+
+linter:
+  rules:
+    - camel_case_types
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_all.dart
index e17f40e..6d61c19 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_all.dart
@@ -4,10 +4,12 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'remove_lint_test.dart' as remove_lint;
 import 'remove_setting_test.dart' as remove_setting;
 
 void main() {
   defineReflectiveSuite(() {
+    remove_lint.main();
     remove_setting.main();
   });
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_support.dart
index 4419e5d..4d1d0a8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_support.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/analysis_options/test_support.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
-import 'package:yaml/src/yaml_node.dart';
 import 'package:yaml/yaml.dart';
 
 /// A base class providing utility methods for tests of fixes associated with
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/add_required_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/add_required_test.dart
new file mode 100644
index 0000000..0be6d18
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/add_required_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.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    // Note that this lint does not fire w/ NNBD.
+    defineReflectiveTests(AddRequiredTest);
+  });
+}
+
+@reflectiveTest
+class AddRequiredTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.always_require_non_null_named_parameters;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+void function({String p1, int p2}) {
+  assert(p1 != null);
+  assert(p2 != null);
+}
+''');
+    await assertHasFix('''
+void function({@required String p1, @required int p2}) {
+  assert(p1 != null);
+  assert(p2 != null);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
index 1f45cc4..59ae8b8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
@@ -4,7 +4,6 @@
 
 import 'package:analysis_server/src/services/correction/bulk_fix_processor.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
-import 'package:analyzer/instrumentation/service.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -12,6 +11,7 @@
 import 'package:test/test.dart';
 
 import '../../../../../abstract_single_unit.dart';
+import '../../../../../utils/test_instrumentation_service.dart';
 
 /// A base class defining support for writing bulk fix processor tests.
 abstract class BulkFixProcessorTest extends AbstractSingleUnitTest {
@@ -30,6 +30,9 @@
   /// Return the lint code being tested.
   String get lintCode => null;
 
+  /// Return `true` if this test uses config files.
+  bool get useConfigFiles => false;
+
   /// The workspace in which fixes contributor operates.
   ChangeWorkspace get workspace {
     return DartChangeWorkspace([session]);
@@ -58,8 +61,8 @@
     var tracker = DeclarationsTracker(MemoryByteStore(), resourceProvider);
     var analysisContext = contextFor(testFile);
     tracker.addContext(analysisContext);
-    var processor =
-        BulkFixProcessor(InstrumentationService.NULL_SERVICE, workspace);
+    var processor = BulkFixProcessor(TestInstrumentationService(), workspace,
+        useConfigFiles: useConfigFiles);
     await processor.fixErrors([analysisContext]);
     return processor;
   }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_generic_function_syntax_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_generic_function_syntax_test.dart
index af826e2..e279e12 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_generic_function_syntax_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_generic_function_syntax_test.dart
@@ -10,6 +10,7 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PreferGenericFunctionTypeAliasesTest);
+    defineReflectiveTests(UseFunctionTypeSyntaxForParametersTest);
   });
 }
 
@@ -29,3 +30,29 @@
 ''');
   }
 }
+
+@reflectiveTest
+class UseFunctionTypeSyntaxForParametersTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.use_function_type_syntax_for_parameters;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+g(String f(int x), int h()) {}
+''');
+    await assertHasFix('''
+g(String Function(int x) f, int Function() h) {}
+''');
+  }
+
+  @failingTest
+  Future<void> test_singleFile_nested() async {
+    // Only the outer function gets converted.
+    await resolveTestCode('''
+g(String f(int h())) {}
+''');
+    await assertHasFix('''
+g(String Function(int Function() h) f) {}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_is_not_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_is_not_test.dart
new file mode 100644
index 0000000..42a907d
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_is_not_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.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertIntoIsNotTest);
+  });
+}
+
+@reflectiveTest
+class ConvertIntoIsNotTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_is_not_operator;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+main(p) {
+  !(p is String) && !!(p is String);
+}
+''');
+    await assertHasFix('''
+main(p) {
+  p is! String && !(p is! String);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_package_import_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_package_import_test.dart
new file mode 100644
index 0000000..3c8cf2b
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_package_import_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:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../fix_processor.dart';
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToPackageImportTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToPackageImportTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.avoid_relative_lib_imports;
+
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/44673')
+  Future<void> test_singleFile() async {
+    writeTestPackageConfig(config: PackageConfigFileBuilder());
+    addSource('/home/test/lib/bar.dart', 'class Bar {}');
+
+    testFile = convertPath('/home/test/tool/test.dart');
+
+    await resolveTestCode('''
+import '../lib/bar.dart';
+
+var bar = Bar();
+''');
+    await assertHasFix('''
+import 'package:test/foo/bar.dart';
+
+var bar = Bar();
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart
index 88e911a..2a480a0 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart
@@ -29,6 +29,7 @@
     defineReflectiveTests(UndefinedIdentifierTest);
     defineReflectiveTests(UndefinedMethodTest);
     defineReflectiveTests(UndefinedSetterTest);
+    defineReflectiveTests(WithConfigFileTest);
     defineReflectiveTests(WrongNumberOfTypeArgumentsConstructorTest);
     defineReflectiveTests(WrongNumberOfTypeArgumentsExtensionTest);
     defineReflectiveTests(WrongNumberOfTypeArgumentsMethodTest);
@@ -939,6 +940,44 @@
 }
 ''');
   }
+
+  Future<void> test_rename_removed_onlyFixOne() async {
+    setPackageContent('''
+class A {
+  void n(int x) {}
+}
+class B {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    method: 'o'
+    inClass: 'A'
+  changes:
+    - kind: 'rename'
+      newName: 'n'
+''');
+    await resolveTestCode('''
+import '$importUri';
+
+void f(A a, B b) {
+  a.o(0);
+  b.o(1);
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f(A a, B b) {
+  a.n(0);
+  b.o(1);
+}
+''');
+  }
 }
 
 @reflectiveTest
@@ -1013,6 +1052,67 @@
 }
 
 @reflectiveTest
+class WithConfigFileTest extends _DataDrivenTest {
+  @override
+  bool get useConfigFiles => true;
+
+  Future<void> test_bulkApply_withConfig() async {
+    setPackageContent('''
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2021-21-01
+  bulkApply: false
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    addSource('/home/test/lib/test.config', '''
+'Rename to New':
+  bulkApply: true
+''');
+    await resolveTestCode('''
+import '$importUri';
+void f(Old p) {}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(New p) {}
+''');
+  }
+
+  Future<void> test_bulkApply_withoutConfig() async {
+    setPackageContent('''
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2021-21-01
+  bulkApply: false
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestCode('''
+import '$importUri';
+void f(Old p) {}
+''');
+    await assertNoFix();
+  }
+}
+
+@reflectiveTest
 class WrongNumberOfTypeArgumentsConstructorTest extends _DataDrivenTest {
   Future<void> test_addTypeParameter() async {
     setPackageContent('''
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/inline_typedef_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/inline_typedef_test.dart
new file mode 100644
index 0000000..c2612f9
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/inline_typedef_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.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InlineTypedefTest);
+  });
+}
+
+@reflectiveTest
+class InlineTypedefTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.avoid_private_typedef_functions;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+typedef _F1 = void Function(int);
+typedef _F2<T> = void Function(T);
+void g(_F2<_F1> f) {}
+''');
+    // Eventually both fixes will be applied but for now we're satisfied that
+    // the results are clean.
+    await assertHasFix('''
+typedef _F2<T> = void Function(T);
+void g(_F2<void Function(int)> f) {}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/remove_if_null_operator_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/remove_if_null_operator_test.dart
new file mode 100644
index 0000000..0003079
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/remove_if_null_operator_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.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnnecessaryNullInIfNullOperatorsTest);
+  });
+}
+
+@reflectiveTest
+class UnnecessaryNullInIfNullOperatorsTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.unnecessary_null_in_if_null_operators;
+
+  @failingTest
+  Future<void> test_null_null_left() async {
+    // The fix only addresses one null and results in:
+    //
+    //     var b = null ?? a;
+    //
+    // (not incorrect but not complete).
+    await resolveTestCode('''
+var a = '';
+var b = null ?? null ?? a;
+''');
+    await assertHasFix('''
+var a = '';
+var b = a;
+''');
+  }
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+var a = '';
+var b = null ?? a ?? null;
+var c = a ?? null ?? null;
+''');
+    await assertHasFix('''
+var a = '';
+var b = a;
+var c = a;
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/remove_unnecessary_string_interpolation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/remove_unnecessary_string_interpolation_test.dart
new file mode 100644
index 0000000..1ae3d1d
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/remove_unnecessary_string_interpolation_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.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnnecessaryStringInterpolation);
+  });
+}
+
+@reflectiveTest
+class RemoveUnnecessaryStringInterpolation extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.unnecessary_string_interpolations;
+
+  Future<void> test_embedded_removeBoth() async {
+    await resolveTestCode(r'''
+void f(String s) {
+  print('${'$s'}');
+}
+''');
+    await assertHasFix(r'''
+void f(String s) {
+  print(s);
+}
+''');
+  }
+
+  Future<void> test_embedded_removeOuter() async {
+    await resolveTestCode(r'''
+void f(String s) {
+  print('${'$s '}');
+}
+''');
+    await assertHasFix(r'''
+void f(String s) {
+  print('$s ');
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
index 14012da..6a65f3b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
@@ -9,6 +9,7 @@
 import 'add_diagnostic_property_reference_test.dart'
     as add_diagnostic_property_reference;
 import 'add_override_test.dart' as add_override;
+import 'add_required_test.dart' as add_required;
 import 'bulk_fix_processor_test.dart' as bulk_fix_processor;
 import 'convert_documentation_into_line_test.dart'
     as convert_documentation_into_line;
@@ -20,9 +21,11 @@
 import 'convert_to_if_element_test.dart' as convert_to_if_element;
 import 'convert_to_if_null_test.dart' as convert_to_if_null;
 import 'convert_to_int_literal_test.dart' as convert_to_int_literal;
+import 'convert_to_is_not_test.dart' as convert_to_is_not;
 import 'convert_to_list_literal_test.dart' as convert_to_list_literal;
 import 'convert_to_map_literal_test.dart' as convert_to_map_literal;
 import 'convert_to_null_aware_test.dart' as convert_to_null_aware;
+import 'convert_to_package_import_test.dart' as convert_to_package_import;
 import 'convert_to_relative_import_test.dart' as convert_to_relative_import;
 import 'convert_to_set_literal_test.dart' as convert_to_set_literal;
 import 'convert_to_single_quoted_strings_test.dart'
@@ -32,6 +35,7 @@
 import 'create_method_test.dart' as create_method;
 import 'data_driven_test.dart' as data_driven;
 import 'inline_invocation_test.dart' as inline_invocation;
+import 'inline_typedef_test.dart' as inline_typedef;
 import 'make_final_test.dart' as make_final;
 import 'remove_argument_test.dart' as remove_argument;
 import 'remove_await_test.dart' as remove_await;
@@ -41,6 +45,7 @@
     as remove_empty_constructor_body;
 import 'remove_empty_else_test.dart' as remove_empty_else;
 import 'remove_empty_statement_test.dart' as remove_empty_statement;
+import 'remove_if_null_operator_test.dart' as remove_if_null_operator;
 import 'remove_initializer_test.dart' as remove_initializer;
 import 'remove_interpolation_braces_test.dart' as remove_interpolation_braces;
 import 'remove_method_declaration_test.dart' as remove_method_declaration;
@@ -50,6 +55,8 @@
 import 'remove_type_annotation_test.dart' as remove_type_annotation;
 import 'remove_unnecessary_const_test.dart' as remove_unnecessary_const;
 import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
+import 'remove_unnecessary_string_interpolation_test.dart'
+    as remove_unnecessary_string_interpolation;
 import 'rename_to_camel_case_test.dart' as rename_to_camel_case;
 import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
 import 'replace_final_with_const_test.dart' as replace_final_with_const;
@@ -71,6 +78,7 @@
     add_const.main();
     add_diagnostic_property_reference.main();
     add_override.main();
+    add_required.main();
     bulk_fix_processor.main();
     convert_documentation_into_line.main();
     convert_map_from_iterable_to_for_literal.main();
@@ -79,9 +87,11 @@
     convert_to_if_element.main();
     convert_to_if_null.main();
     convert_to_int_literal.main();
+    convert_to_is_not.main();
     convert_to_list_literal.main();
     convert_to_map_literal.main();
     convert_to_null_aware.main();
+    convert_to_package_import.main();
     convert_to_relative_import.main();
     convert_to_set_literal.main();
     convert_to_single_quoted_strings.main();
@@ -90,6 +100,7 @@
     create_method.main();
     data_driven.main();
     inline_invocation.main();
+    inline_typedef.main();
     make_final.main();
     remove_argument.main();
     remove_await.main();
@@ -99,6 +110,7 @@
     remove_empty_constructor_body.main();
     remove_empty_else.main();
     remove_empty_statement.main();
+    remove_if_null_operator.main();
     remove_interpolation_braces.main();
     remove_method_declaration.main();
     remove_non_null_assertion.main();
@@ -107,6 +119,7 @@
     remove_type_annotation.main();
     remove_unnecessary_const.main();
     remove_unnecessary_new.main();
+    remove_unnecessary_string_interpolation.main();
     rename_to_camel_case.main();
     replace_with_conditional_assignment.main();
     replace_colon_with_equals.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/change_to_test.dart b/pkg/analysis_server/test/src/services/correction/fix/change_to_test.dart
index e3e581b..da9231f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/change_to_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/change_to_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -311,6 +312,75 @@
 ''');
   }
 
+  Future<void> test_getterSetter_qualified() async {
+    await resolveTestCode('''
+class A {
+  int get foo => 0;
+  set foo(int _) {}
+}
+
+void f(A a) {
+  a.foo2 += 2;
+}
+''');
+    await assertHasFix('''
+class A {
+  int get foo => 0;
+  set foo(int _) {}
+}
+
+void f(A a) {
+  a.foo += 2;
+}
+''', errorFilter: (e) => e.errorCode == CompileTimeErrorCode.UNDEFINED_GETTER);
+  }
+
+  Future<void> test_getterSetter_qualified_static() async {
+    await resolveTestCode('''
+class A {
+  static int get foo => 0;
+  static set foo(int _) {}
+}
+
+void f() {
+  A.foo2 += 2;
+}
+''');
+    await assertHasFix('''
+class A {
+  static int get foo => 0;
+  static set foo(int _) {}
+}
+
+void f() {
+  A.foo += 2;
+}
+''', errorFilter: (e) => e.errorCode == CompileTimeErrorCode.UNDEFINED_GETTER);
+  }
+
+  Future<void> test_getterSetter_unqualified() async {
+    await resolveTestCode('''
+class A {
+  int get foo => 0;
+  set foo(int _) {}
+
+  void f() {
+    foo2 += 2;
+  }
+}
+''');
+    await assertHasFix('''
+class A {
+  int get foo => 0;
+  set foo(int _) {}
+
+  void f() {
+    foo += 2;
+  }
+}
+''');
+  }
+
   Future<void> test_method_ignoreOperators() async {
     await resolveTestCode('''
 main(Object object) {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_null_aware_spread_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_null_aware_spread_test.dart
new file mode 100644
index 0000000..8cdcb25
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_null_aware_spread_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/services/correction/fix.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../abstract_context.dart';
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToNullAwareSpreadTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToNullAwareSpreadTest extends FixProcessorTest
+    with WithNullSafetyMixin {
+  @override
+  FixKind get kind => DartFixKind.CONVERT_TO_NULL_AWARE_SPREAD;
+
+  Future<void> test_spreadList() async {
+    await resolveTestCode('''
+void f (List<String>? args) {
+  [...args];
+}
+''');
+    await assertHasFix('''
+void f (List<String>? args) {
+  [...?args];
+}
+''');
+  }
+
+  Future<void> test_spreadMap() async {
+    await resolveTestCode('''
+void f (Map<int, String>? args) {
+  print({...args});
+}
+''');
+    await assertHasFix('''
+void f (Map<int, String>? args) {
+  print({...?args});
+}
+''');
+  }
+
+  Future<void> test_spreadSet() async {
+    await resolveTestCode('''
+void f (List<String>? args) {
+  print({...args});
+}
+''');
+    await assertHasFix('''
+void f (List<String>? args) {
+  print({...?args});
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_on_type_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_on_type_test.dart
index a6daf9b..f14cf3c 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_on_type_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_on_type_test.dart
@@ -23,6 +23,25 @@
   @override
   String get lintCode => LintNames.avoid_types_as_parameter_names;
 
+  Future<void> test_nameReferenced() async {
+    await resolveTestCode('''
+void f() {
+  try {
+  } catch (ArgumentError) {
+    print(ArgumentError);
+  }
+}
+''');
+    await assertHasFix('''
+void f() {
+  try {
+  } on ArgumentError {
+    print(ArgumentError);
+  }
+}
+''');
+  }
+
   Future<void> test_withOnType() async {
     await resolveTestCode('''
 void f() {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
index 35b1de0..e991423 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_package_import_test.dart
@@ -24,7 +24,7 @@
   String get lintCode => LintNames.avoid_relative_lib_imports;
 
   /// More coverage in the `convert_to_package_import_test.dart` assist test.
-  @failingTest
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/44673')
   Future<void> test_relativeImport() async {
     // This test fails because any attempt to specify a relative path that
     // includes 'lib' (which the lint requires) results in a malformed URI when
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
index 5ed784f..dcda4bc 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
@@ -483,7 +483,7 @@
           element: ElementDescriptor(
               libraryUris: [Uri.parse(importUri)],
               kind: ElementKindUtilities.fromName(_kind),
-              components: components ?? ['C', 'm']),
+              components: components ?? ['m', 'C']),
           bulkApply: false,
           changesSelector: UnconditionalChangesSelector([
             AddTypeParameter(
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_fragment_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_fragment_parser_test.dart
index 2212ec0..9a8fdc2 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_fragment_parser_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_fragment_parser_test.dart
@@ -9,7 +9,6 @@
 import 'package:analysis_server/src/services/correction/fix/data_driven/value_generator.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/variable_scope.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:matcher/matcher.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
index 4a70221..e26e0061 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
@@ -10,7 +10,6 @@
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
-import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 
 import '../fix_processor.dart';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart
new file mode 100644
index 0000000..f462b36
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/element_matcher_test.dart
@@ -0,0 +1,404 @@
+// 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/services/correction/fix/data_driven/element_kind.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.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';
+
+import 'data_driven_test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ElementMatcherComponentAndKindTest);
+    defineReflectiveTests(ElementMatcherImportsTest);
+  });
+}
+
+abstract class AbstractElementMatcherTest extends DataDrivenFixProcessorTest {
+  void _assertMatcher(String search,
+      {List<String> expectedComponents,
+      List<ElementKind> expectedKinds,
+      List<String> expectedUris}) {
+    var node = findNode.any(search);
+    var matcher = ElementMatcher.forNode(node);
+    if (expectedUris != null) {
+      expect(matcher.importedUris,
+          unorderedEquals(expectedUris.map((uri) => Uri.parse(uri))));
+    }
+    if (expectedComponents != null) {
+      expect(matcher.components, expectedComponents);
+    }
+    if (expectedKinds != null) {
+      expect(matcher.validKinds, expectedKinds);
+    }
+  }
+}
+
+@reflectiveTest
+class ElementMatcherComponentAndKindTest extends AbstractElementMatcherTest {
+  /// The kinds that are expected where a getter or setter is allowed.
+  static List<ElementKind> accessorKinds = [
+    ElementKind.fieldKind,
+    ElementKind.getterKind,
+    ElementKind.setterKind,
+  ];
+
+  /// The kinds that are expected where an invocation is allowed.
+  static List<ElementKind> invocationKinds = [
+    ElementKind.classKind,
+    ElementKind.extensionKind,
+    ElementKind.functionKind,
+    ElementKind.methodKind,
+  ];
+
+  /// The kinds that are expected where a method or constructor is allowed.
+  static List<ElementKind> methodKinds = [
+    ElementKind.constructorKind,
+    ElementKind.methodKind
+  ];
+
+  /// The kinds that are expected where a type is allowed.
+  static List<ElementKind> typeKinds = [
+    ElementKind.classKind,
+    ElementKind.enumKind,
+    ElementKind.mixinKind,
+    ElementKind.typedefKind,
+  ];
+
+  @failingTest
+  Future<void> test_binaryExpression_resolved() async {
+    // This test fails because we don't yet support operators.
+    await resolveTestCode('''
+void f(int x, int y) {
+  x + y;
+}
+''');
+    _assertMatcher('+',
+        expectedComponents: ['+', 'int'],
+        expectedKinds: [ElementKind.methodKind]);
+  }
+
+  @failingTest
+  Future<void> test_binaryExpression_unresolved() async {
+    // This test fails because we don't yet support operators.
+    await resolveTestCode('''
+void f(C c1, C c2) {
+  c1 + c2;
+}
+class C {}
+''');
+    _assertMatcher('+',
+        expectedComponents: ['+', 'C'],
+        expectedKinds: [ElementKind.methodKind]);
+  }
+
+  Future<void> test_getter_withoutTarget_resolved() async {
+    await resolveTestCode('''
+class C {
+  String get g => '';
+  void m() {
+    g;
+  }
+}
+''');
+    _assertMatcher('g;', expectedComponents: ['g', 'C']);
+  }
+
+  Future<void> test_getter_withoutTarget_unresolved() async {
+    await resolveTestCode('''
+class C {
+  void m() {
+    foo;
+  }
+}
+''');
+    _assertMatcher('foo', expectedComponents: ['foo']);
+  }
+
+  Future<void> test_getter_withTarget_resolved() async {
+    await resolveTestCode('''
+void f(String s) {
+  s.length;
+}
+''');
+    _assertMatcher('length',
+        expectedComponents: ['length', 'String'], expectedKinds: accessorKinds);
+  }
+
+  Future<void> test_getter_withTarget_unresolved() async {
+    await resolveTestCode('''
+void f(String s) {
+  s.foo;
+}
+''');
+    _assertMatcher('foo',
+        expectedComponents: ['foo', 'String'], expectedKinds: accessorKinds);
+  }
+
+  Future<void> test_identifier_propertyAccess() async {
+    await resolveTestCode('''
+void f() {
+  s.length;
+}
+''');
+    // TODO(brianwilkerson) Several of these kinds don't seem to be appropriate,
+    //  so we might want to narrow down the list.
+    _assertMatcher('s', expectedComponents: [
+      's'
+    ], expectedKinds: [
+      ElementKind.classKind,
+      ElementKind.enumKind,
+      ElementKind.extensionKind,
+      ElementKind.mixinKind,
+      ElementKind.typedefKind,
+    ]);
+  }
+
+  Future<void> test_method_withoutTarget_resolved() async {
+    await resolveTestCode('''
+class C {
+  void m(int i) {}
+  void m2() {
+    m(0);
+  }
+}
+''');
+    _assertMatcher('m(0)',
+        expectedComponents: ['m', 'C'], expectedKinds: invocationKinds);
+  }
+
+  Future<void> test_method_withoutTarget_unresolved() async {
+    await resolveTestCode('''
+class C {
+  void m() {
+    foo();
+  }
+}
+''');
+    _assertMatcher('foo',
+        expectedComponents: ['foo'], expectedKinds: invocationKinds);
+  }
+
+  Future<void> test_method_withTarget_resolved() async {
+    await resolveTestCode('''
+void f(String s) {
+  s.substring(2);
+}
+''');
+    _assertMatcher('substring',
+        expectedComponents: ['substring', 'String'],
+        expectedKinds: methodKinds);
+  }
+
+  Future<void> test_method_withTarget_unresolved() async {
+    await resolveTestCode('''
+void f(String s) {
+  s.foo(2);
+}
+''');
+    _assertMatcher('foo',
+        expectedComponents: ['foo', 'String'], expectedKinds: methodKinds);
+  }
+
+  Future<void> test_setter_withoutTarget_resolved() async {
+    await resolveTestCode('''
+class C {
+  set s(String s) {}
+  void m() {
+    s = '';
+  }
+}
+''');
+    _assertMatcher('s =', expectedComponents: ['s', 'C']);
+  }
+
+  Future<void> test_setter_withoutTarget_unresolved() async {
+    await resolveTestCode('''
+class C {
+  void m() {
+    foo = '';
+  }
+}
+''');
+    _assertMatcher('foo', expectedComponents: ['foo']);
+  }
+
+  Future<void> test_setter_withTarget_resolved() async {
+    await resolveTestCode('''
+void f(C c) {
+  c.s = '';
+}
+class C {
+  set s(String s) {}
+}
+''');
+    _assertMatcher('s =',
+        expectedComponents: ['s', 'C'], expectedKinds: accessorKinds);
+  }
+
+  Future<void> test_setter_withTarget_unresolved() async {
+    await resolveTestCode('''
+void f(String s) {
+  s.foo = '';
+}
+''');
+    _assertMatcher('foo',
+        expectedComponents: ['foo', 'String'], expectedKinds: accessorKinds);
+  }
+
+  Future<void> test_type_field_resolved() async {
+    await resolveTestCode('''
+class C {
+  String s = '';
+}
+''');
+    _assertMatcher('String',
+        expectedComponents: ['String'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_field_unresolved() async {
+    await resolveTestCode('''
+class C {
+  Foo s = '';
+}
+''');
+    _assertMatcher('Foo',
+        expectedComponents: ['Foo'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_localVariable_resolved() async {
+    await resolveTestCode('''
+void f() {
+  String s = '';
+}
+''');
+    _assertMatcher('String',
+        expectedComponents: ['String'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_localVariable_unresolved() async {
+    await resolveTestCode('''
+void f() {
+  Foo s = '';
+}
+''');
+    _assertMatcher('Foo',
+        expectedComponents: ['Foo'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_method_resolved() async {
+    await resolveTestCode('''
+class C {
+  String m() => '';
+}
+''');
+    _assertMatcher('String',
+        expectedComponents: ['String'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_method_unresolved() async {
+    await resolveTestCode('''
+class C {
+  Foo m() => '';
+}
+''');
+    _assertMatcher('Foo',
+        expectedComponents: ['Foo'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_parameter_resolved() async {
+    await resolveTestCode('''
+void f(String s) {}
+''');
+    _assertMatcher('String',
+        expectedComponents: ['String'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_parameter_unresolved() async {
+    await resolveTestCode('''
+void f(Foo s) {}
+''');
+    _assertMatcher('Foo',
+        expectedComponents: ['Foo'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_topLevelFunction_resolved() async {
+    await resolveTestCode('''
+String f() => '';
+''');
+    _assertMatcher('String',
+        expectedComponents: ['String'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_topLevelFunction_unresolved() async {
+    await resolveTestCode('''
+Foo f() => '';
+''');
+    _assertMatcher('Foo',
+        expectedComponents: ['Foo'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_topLevelVariable_resolved() async {
+    await resolveTestCode('''
+String s = '';
+''');
+    _assertMatcher('String',
+        expectedComponents: ['String'], expectedKinds: typeKinds);
+  }
+
+  Future<void> test_type_topLevelVariable_unresolved() async {
+    await resolveTestCode('''
+Foo s = '';
+''');
+    _assertMatcher('Foo',
+        expectedComponents: ['Foo'], expectedKinds: typeKinds);
+  }
+}
+
+@reflectiveTest
+class ElementMatcherImportsTest extends AbstractElementMatcherTest {
+  Future<void> test_imports_noImports() async {
+    await resolveTestCode('''
+String s = '';
+''');
+    _assertMatcher('s', expectedUris: ['dart:core']);
+  }
+
+  Future<void> test_imports_package() async {
+    var packageRootPath = '$workspaceRootPath/other';
+    newFile('$packageRootPath/lib/other.dart', content: '');
+    writeTestPackageConfig(
+        config: PackageConfigFileBuilder()
+          ..add(name: 'other', rootPath: packageRootPath));
+
+    await resolveTestCode('''
+import 'package:other/other.dart';
+
+String s = '';
+''');
+    _assertMatcher('s',
+        expectedUris: ['dart:core', 'package:other/other.dart']);
+  }
+
+  Future<void> test_imports_relative() async {
+    addSource('$testPackageLibPath/a.dart', '');
+    await resolveTestCode('''
+import 'a.dart';
+
+String s = '';
+''');
+    _assertMatcher('s', expectedUris: ['dart:core', 'package:test/a.dart']);
+  }
+
+  Future<void> test_imports_sdkLibraries() async {
+    await resolveTestCode('''
+import 'dart:math';
+
+int f(int x, int y) => max(x, y);
+''');
+    _assertMatcher('f', expectedUris: ['dart:core', 'dart:math']);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
index 7932354..f6359cd 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/flutter_use_case_test.dart
@@ -1001,6 +1001,93 @@
 ''');
   }
 
+  Future<void> test_material_Scaffold_of_missingArgument() async {
+    setPackageContent('''
+class Scaffold {
+  static ScaffoldState of(BuildContext context) => ScaffoldState();
+  static ScaffoldState maybeOf(BuildContext context) => ScaffoldState();
+}
+class ScaffoldState {}
+class BuildContext {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+  - title: 'Remove nullOk'
+    date: 2020-11-04
+    element:
+      uris: ['$importUri']
+      method: 'of'
+      inClass: 'Scaffold'
+    oneOf:
+      - if: "nullOk == 'true'"
+        changes:
+          - kind: 'rename'
+            newName: 'maybeOf'
+          - kind: 'removeParameter'
+            name: 'nullOk'
+      - if: "nullOk == 'false'"
+        changes:
+          - kind: 'removeParameter'
+            name: 'nullOk'
+    variables:
+      nullOk:
+        kind: 'fragment'
+        value: 'arguments[nullOk]'
+''');
+    await resolveTestCode('''
+import '$importUri';
+
+void f(BuildContext context) {
+  Scaffold.of(context, undefined: 3);
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_material_Scaffold_of_wrongType() async {
+    setPackageContent('''
+class Theme {
+  static ThemeData of(BuildContext context, {bool shadowThemeOnly: false}) => ThemeData();
+}
+class ThemeData {}
+class BuildContext {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+  - title: 'Remove nullOk'
+    date: 2020-11-04
+    element:
+      uris: ['$importUri']
+      method: 'of'
+      inClass: 'Scaffold'
+    oneOf:
+      - if: "nullOk == 'true'"
+        changes:
+          - kind: 'rename'
+            newName: 'maybeOf'
+          - kind: 'removeParameter'
+            name: 'nullOk'
+      - if: "nullOk == 'false'"
+        changes:
+          - kind: 'removeParameter'
+            name: 'nullOk'
+    variables:
+      nullOk:
+        kind: 'fragment'
+        value: 'arguments[nullOk]'
+''');
+    await resolveTestCode('''
+import '$importUri';
+
+void f(BuildContext context) {
+  Theme.of(context, nullOk: true);
+}
+''');
+    await assertNoFix();
+  }
+
   Future<void>
       test_material_Scaffold_resizeToAvoidBottomPadding_deprecated() async {
     setPackageContent('''
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
index 30f1bce..d67d30e 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
@@ -34,7 +34,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', false, false, null)],
+        ['m', 'C'], [AddParameter(0, 'a', false, false, null)],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -61,7 +61,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', false, true, codeTemplate('0'))],
+        ['m', 'C'], [AddParameter(0, 'a', false, true, codeTemplate('0'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -88,7 +88,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', true, false, codeTemplate('0'))],
+        ['m', 'C'], [AddParameter(0, 'a', true, false, codeTemplate('0'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -115,7 +115,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
+        ['m', 'C'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -142,7 +142,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', false, false, null)],
+        ['m', 'C'], [AddParameter(1, 'b', false, false, null)],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -169,7 +169,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', false, true, codeTemplate('1'))],
+        ['m', 'C'], [AddParameter(1, 'b', false, true, codeTemplate('1'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -196,7 +196,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', true, false, codeTemplate('1'))],
+        ['m', 'C'], [AddParameter(1, 'b', true, false, codeTemplate('1'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -223,7 +223,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', true, true, codeTemplate('1'))],
+        ['m', 'C'], [AddParameter(1, 'b', true, true, codeTemplate('1'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -250,8 +250,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm'
+      'm',
+      'C'
     ], [
       AddParameter(1, 'b', true, true, codeTemplate('1')),
       AddParameter(2, 'c', true, true, codeTemplate('2')),
@@ -280,7 +280,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
+        ['m', 'C'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -305,7 +305,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))]));
+        ['m', 'C'], [AddParameter(0, 'a', true, true, codeTemplate('0'))]));
     await resolveTestCode('''
 import '$importUri';
 
@@ -331,8 +331,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm'
+      'm',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(0)),
       AddParameter(2, 'c', true, true, codeTemplate('2'))
@@ -362,8 +362,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm'
+      'm',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(1)),
       AddParameter(0, 'a', true, true, codeTemplate('0'))
@@ -393,8 +393,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm1'
+      'm1',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(0)),
       RemoveParameter(PositionalParameterReference(1)),
@@ -425,8 +425,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm1'
+      'm1',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(1)),
       RemoveParameter(PositionalParameterReference(2)),
@@ -457,8 +457,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm1'
+      'm1',
+      'C'
     ], [
       AddParameter(0, 'a', true, true, codeTemplate('0')),
       RemoveParameter(PositionalParameterReference(1)),
@@ -490,8 +490,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm1'
+      'm1',
+      'C'
     ], [
       AddParameter(0, 'b', true, false, codeTemplate('0')),
       RemoveParameter(NamedParameterReference('a')),
@@ -521,7 +521,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(NamedParameterReference('a'))],
+        ['m', 'C'], [RemoveParameter(NamedParameterReference('a'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -548,7 +548,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -575,7 +575,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -602,7 +602,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(NamedParameterReference('b'))],
+        ['m', 'C'], [RemoveParameter(NamedParameterReference('b'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -629,7 +629,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(1))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(1))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -656,7 +656,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(1))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(1))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -682,7 +682,7 @@
 }
 ''');
     setPackageData(
-        _modify(['C', 'm'], [RemoveParameter(NamedParameterReference('b'))]));
+        _modify(['m', 'C'], [RemoveParameter(NamedParameterReference('b'))]));
     await resolveTestCode('''
 import '$importUri';
 
@@ -708,8 +708,8 @@
 }
 ''');
     setPackageData(_modify([
-      'C',
-      'm'
+      'm',
+      'C'
     ], [
       RemoveParameter(PositionalParameterReference(0)),
       RemoveParameter(PositionalParameterReference(2)),
@@ -740,7 +740,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(NamedParameterReference('a'))],
+        ['m', 'C'], [RemoveParameter(NamedParameterReference('a'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -767,7 +767,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(NamedParameterReference('a'))],
+        ['m', 'C'], [RemoveParameter(NamedParameterReference('a'))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -794,7 +794,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -822,7 +822,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
@@ -849,7 +849,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [RemoveParameter(PositionalParameterReference(0))],
+        ['m', 'C'], [RemoveParameter(PositionalParameterReference(0))],
         newName: 'm2'));
     await resolveTestCode('''
 import '$importUri';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
index f892cd6..3a189c0 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_parameter_test.dart
@@ -30,7 +30,7 @@
   C.named({int b, @deprecated int a});
 }
 ''');
-    setPackageData(_rename(['C', 'named'], 'a', 'b'));
+    setPackageData(_rename(['named', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -53,7 +53,7 @@
   C.named({int b});
 }
 ''');
-    setPackageData(_rename(['C', 'named'], 'a', 'b'));
+    setPackageData(_rename(['named', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -76,7 +76,7 @@
   C({int b, @deprecated int a});
 }
 ''');
-    setPackageData(_rename(['C', ''], 'a', 'b'));
+    setPackageData(_rename(['', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -99,7 +99,7 @@
   C({int b});
 }
 ''');
-    setPackageData(_rename(['C', ''], 'a', 'b'));
+    setPackageData(_rename(['', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -128,7 +128,7 @@
   int m({int b, @deprecated int a}) => 0;
 }
 ''');
-    setPackageData(_rename(['D', 'm'], 'a', 'nbew'));
+    setPackageData(_rename(['m', 'D'], 'a', 'nbew'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -145,7 +145,7 @@
   int m({int b, @deprecated int a}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -170,7 +170,7 @@
   int m({int b}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -195,7 +195,7 @@
   int m({int b, @deprecated int a}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -218,7 +218,7 @@
   int m({int b}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -241,7 +241,7 @@
   static int m({int b, @deprecated int a}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -264,7 +264,7 @@
   static int m({int b}) => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'm'], 'a', 'b'));
+    setPackageData(_rename(['m', 'C'], 'a', 'b'));
     await resolveTestCode('''
 import '$importUri';
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
index 2edc72d..6e0ce4a 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
@@ -366,7 +366,7 @@
   C.b();
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -389,7 +389,7 @@
   C.b();
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -414,7 +414,7 @@
   C();
 }
 ''');
-    setPackageData(_rename(['C', 'old'], ''));
+    setPackageData(_rename(['old', 'C'], ''));
     await resolveTestCode('''
 import '$importUri';
 
@@ -437,7 +437,7 @@
   C();
 }
 ''');
-    setPackageData(_rename(['C', 'old'], ''));
+    setPackageData(_rename(['old', 'C'], ''));
     await resolveTestCode('''
 import '$importUri';
 
@@ -462,7 +462,7 @@
   C.a();
 }
 ''');
-    setPackageData(_rename(['C', ''], 'a'));
+    setPackageData(_rename(['', 'C'], 'a'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -485,7 +485,7 @@
   C.a();
 }
 ''');
-    setPackageData(_rename(['C', ''], 'a'));
+    setPackageData(_rename(['', 'C'], 'a'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -606,7 +606,7 @@
   int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -629,7 +629,7 @@
   int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -654,7 +654,7 @@
   static int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -677,7 +677,7 @@
   static int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -702,7 +702,7 @@
   static int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -725,7 +725,7 @@
   static int b;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -760,7 +760,7 @@
   void a(int b) {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -782,7 +782,7 @@
   D({@deprecated int a; int c});
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -799,7 +799,7 @@
   int get b => 1;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -822,7 +822,7 @@
   int get b => 1;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -850,7 +850,7 @@
   C c() => C();
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -876,7 +876,7 @@
   C c() => C();
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -952,7 +952,7 @@
   int b() => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -977,7 +977,7 @@
   int b() => 0;
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -1004,7 +1004,7 @@
   int b() {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -1027,7 +1027,7 @@
   int b() {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -1052,7 +1052,7 @@
   static int b() {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
@@ -1075,7 +1075,7 @@
   static int b() {}
 }
 ''');
-    setPackageData(_rename(['C', 'a'], 'b'));
+    setPackageData(_rename(['a', 'C'], 'b'));
     await resolveTestCode('''
 import '$importUri';
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/sdk_fix_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/sdk_fix_test.dart
new file mode 100644
index 0000000..a154782
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/sdk_fix_test.dart
@@ -0,0 +1,99 @@
+// 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/services/correction/fix/data_driven/transform_set_manager.dart';
+import 'package:analyzer/src/test_utilities/mock_sdk.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'data_driven_test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SdkFixCollectionTest);
+    defineReflectiveTests(SdkFixCoreTest);
+    defineReflectiveTests(SdkNoDataFileTest);
+  });
+}
+
+class AbstractSdkFixTest extends DataDrivenFixProcessorTest {
+  void addSdkDataFile(String content) {
+    newFile('$sdkRoot/lib/_internal/${TransformSetManager.dataFileName}',
+        content: content);
+  }
+
+  @override
+  void setUp() {
+    addSdkDataFile('''
+version: 1
+transforms:
+- title: 'Rename to Bar'
+  date: 2021-01-22
+  element:
+    uris:
+      - '$importUri'
+    class: 'Foo'
+  changes:
+    - kind: 'rename'
+      newName: 'Bar'
+''');
+    super.setUp();
+  }
+}
+
+@reflectiveTest
+class SdkFixCollectionTest extends AbstractSdkFixTest {
+  @override
+  String importUri = 'dart:collection';
+
+  Future<void> test_rename() async {
+    await resolveTestCode('''
+import '$importUri';
+
+void f(Foo o) {}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f(Bar o) {}
+''', errorFilter: ignoreUnusedImport);
+  }
+}
+
+@reflectiveTest
+class SdkFixCoreTest extends AbstractSdkFixTest {
+  @override
+  String importUri = 'dart:core';
+
+  Future<void> test_rename() async {
+    await resolveTestCode('''
+import '$importUri';
+
+void f(Foo o) {}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f(Bar o) {}
+''');
+  }
+
+  Future<void> test_rename_noImport() async {
+    await resolveTestCode('''
+void f(Foo o) {}
+''');
+    await assertHasFix('''
+void f(Bar o) {}
+''');
+  }
+}
+
+@reflectiveTest
+class SdkNoDataFileTest extends DataDrivenFixProcessorTest {
+  Future<void> test_noExceptions() async {
+    await resolveTestCode('''
+var x = '';
+''');
+    assertNoExceptions();
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
index 4eb8242..a21ba3c 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
@@ -8,11 +8,15 @@
 import 'code_fragment_parser_test.dart' as code_fragment_parser;
 import 'code_template_test.dart' as code_template;
 import 'diagnostics/test_all.dart' as diagnostics;
+import 'element_matcher_test.dart' as element_matcher;
 import 'end_to_end_test.dart' as end_to_end;
 import 'flutter_use_case_test.dart' as flutter_use_case;
 import 'modify_parameters_test.dart' as modify_parameters;
 import 'rename_parameter_test.dart' as rename_parameter;
 import 'rename_test.dart' as rename;
+import 'sdk_fix_test.dart' as sdk_fix;
+import 'transform_override_set_parser_test.dart'
+    as transform_override_set_parser;
 import 'transform_set_manager_test.dart' as transform_set_manager;
 import 'transform_set_parser_test.dart' as transform_set_parser;
 
@@ -22,11 +26,14 @@
     code_fragment_parser.main();
     code_template.main();
     diagnostics.main();
+    element_matcher.main();
     end_to_end.main();
     flutter_use_case.main();
     modify_parameters.main();
     rename_parameter.main();
     rename.main();
+    sdk_fix.main();
+    transform_override_set_parser.main();
     transform_set_manager.main();
     transform_set_parser.main();
   });
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_override_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_override_set_parser_test.dart
new file mode 100644
index 0000000..5aa8721
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_override_set_parser_test.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.
+
+import 'package:_fe_analyzer_shared/src/base/errors.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override_set_parser.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../../mocks.dart';
+import '../../../../../utils/test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TransformSetParserTest);
+  });
+}
+
+/// Utilities shared between tests of the [TransformOverrideSetParser].
+abstract class AbstractTransformOverrideSetParserTest {
+  /// The listener to which errors will be reported.
+  GatheringErrorListener errorListener;
+
+  /// The result of parsing the test file's content.
+  TransformOverrideSet result;
+
+  void assertErrors(String code, List<ExpectedError> expectedErrors) {
+    parse(code);
+    errorListener.assertErrors(expectedErrors);
+  }
+
+  void assertNoErrors(String content) {
+    parse(content);
+    errorListener.assertNoErrors();
+  }
+
+  void assertOverride(String title, {bool bulkApply}) {
+    var override = result.overrideForTransform(title);
+    expect(override, isNotNull);
+    if (bulkApply != null) {
+      expect(override.bulkApply, bulkApply);
+    }
+  }
+
+  ExpectedError error(ErrorCode code, int offset, int length,
+          {String text,
+          Pattern messageContains,
+          List<ExpectedContextMessage> contextMessages =
+              const <ExpectedContextMessage>[]}) =>
+      ExpectedError(code, offset, length,
+          message: text,
+          messageContains: messageContains,
+          expectedContextMessages: contextMessages);
+
+  void parse(String content) {
+    errorListener = GatheringErrorListener();
+    var errorReporter = ErrorReporter(errorListener, MockSource('data.yaml'));
+    var parser = TransformOverrideSetParser(errorReporter);
+    result = parser.parse(content);
+  }
+}
+
+@reflectiveTest
+class TransformSetParserTest extends AbstractTransformOverrideSetParserTest {
+  void test_emptyFile() {
+    assertErrors('''
+''', [error(TransformSetErrorCode.invalidValue, 0, 0)]);
+    expect(result, isNull);
+  }
+
+  void test_oneTransform() {
+    assertNoErrors('''
+"transform one":
+  bulkApply: true
+''');
+    assertOverride('transform one', bulkApply: true);
+  }
+
+  void test_twoTransforms() {
+    assertNoErrors('''
+"transform one":
+  bulkApply: false
+"transform two":
+  bulkApply: true
+''');
+    assertOverride('transform one', bulkApply: false);
+    assertOverride('transform two', bulkApply: true);
+  }
+}
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 3420914..c0f59db 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
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
-import 'package:matcher/matcher.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
index c36ea63..d2789c8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
@@ -15,7 +15,6 @@
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/value_generator.dart';
-import 'package:matcher/matcher.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -729,7 +728,7 @@
       (transform.changesSelector as UnconditionalChangesSelector).changes;
 
   ElementMatcher _matcher(String name) =>
-      ElementMatcher(importedUris: uris, name: name);
+      ElementMatcher(importedUris: uris, components: [name]);
 
   List<Transform> _transforms(String name) =>
       result.transformsFor(_matcher(name), applyingBulkFixes: false);
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 0900c1b..70b6a66 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
@@ -8,7 +8,6 @@
 import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/instrumentation/service.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/services/available_declarations.dart';
@@ -22,6 +21,7 @@
 
 import '../../../../abstract_context.dart';
 import '../../../../abstract_single_unit.dart';
+import '../../../../utils/test_instrumentation_service.dart';
 
 export 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 
@@ -31,6 +31,19 @@
   /// Return the lint code being tested.
   String get lintCode;
 
+  /// Return the [LintCode] for the [lintCode] (which is actually a name).
+  Future<LintCode> lintCodeByName(String name) async {
+    var errors = await _computeErrors();
+    var lintCodeSet = errors
+        .map((error) => error.errorCode)
+        .where((errorCode) => errorCode.name == name)
+        .toSet();
+    if (lintCodeSet.length != 1) {
+      fail('Expected exactly one LintCode, actually: $lintCodeSet');
+    }
+    return lintCodeSet.single;
+  }
+
   bool Function(AnalysisError) lintNameFilter(String name) {
     return (e) {
       return e.errorCode is LintCode && e.errorCode.name == name;
@@ -274,7 +287,7 @@
     tracker.addContext(analysisContext);
 
     var context = DartFixContextImpl(
-      InstrumentationService.NULL_SERVICE,
+      TestInstrumentationService(),
       workspace,
       testAnalysisResult,
       error,
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
index 38c113a..9e5a66a 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../../services/refactoring/abstract_rename.dart';
 import 'fix_processor.dart';
 
 void main() {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart
index 804f106..f619f67 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart
@@ -29,7 +29,9 @@
 }
 ''');
     // TODO(srawlins): Remove the type if the quick fix as is would use the same
-    // type as the field's type.
+    //  type as the field's type. (brianwilkerson) I would argue that removing
+    //  the type should be a separate fix/assist. There was a reason why the
+    //  user used an explicit type, and we shouldn't remove it when it's valid.
     await assertHasFix('''
 class C {
   String? s;
@@ -95,6 +97,55 @@
     await assertNoFix();
   }
 
+  Future<void> test_localVariable_initializedToNull() async {
+    await resolveTestCode('''
+void f() {
+  String s = null;
+  print(s);
+}
+''');
+    await assertHasFix('''
+void f() {
+  String? s = null;
+  print(s);
+}
+''');
+  }
+
+  Future<void> test_localVariable_type() async {
+    await resolveTestCode('''
+void f() {
+  String s = '';
+  s = null;
+  print(s);
+}
+''');
+    await assertHasFix('''
+void f() {
+  String? s = '';
+  s = null;
+  print(s);
+}
+''');
+  }
+
+  Future<void> test_localVariable_var() async {
+    await resolveTestCode('''
+void f() {
+  var s = '';
+  s = null;
+  print(s);
+}
+''');
+    await assertHasFix('''
+void f() {
+  String? s = '';
+  s = null;
+  print(s);
+}
+''');
+  }
+
   Future<void> test_multipleVariables() async {
     await resolveTestCode('''
 void f() {
@@ -159,38 +210,4 @@
 void f<T>({T? s}) {}
 ''');
   }
-
-  Future<void> test_type() async {
-    await resolveTestCode('''
-void f() {
-  String s = '';
-  s = null;
-  print(s);
-}
-''');
-    await assertHasFix('''
-void f() {
-  String? s = '';
-  s = null;
-  print(s);
-}
-''');
-  }
-
-  Future<void> test_var() async {
-    await resolveTestCode('''
-void f() {
-  var s = '';
-  s = null;
-  print(s);
-}
-''');
-    await assertHasFix('''
-void f() {
-  String? s = '';
-  s = null;
-  print(s);
-}
-''');
-  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/pubspec/test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/pubspec/test_support.dart
index 4eea061..6fc913e 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/pubspec/test_support.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/pubspec/test_support.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
-import 'package:yaml/src/yaml_node.dart';
 import 'package:yaml/yaml.dart';
 
 /// A base class providing utility methods for tests of fixes associated with
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
index 356d591..5494406 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
@@ -146,7 +146,7 @@
 ''');
   }
 
-  Future<void> test_ifStatement() async {
+  Future<void> test_ifStatement_thenBlock() async {
     await resolveTestCode('''
 void f(String s) {
   if (s != null) {
@@ -160,4 +160,31 @@
 }
 ''');
   }
+
+  Future<void> test_ifStatement_thenBlock_empty() async {
+    await resolveTestCode('''
+void f(String s) {
+  if (s != null) {
+  }
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+}
+''');
+  }
+
+  Future<void> test_ifStatement_thenStatement() async {
+    await resolveTestCode('''
+void f(String s) {
+  if (s != null)
+    print(s);
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+  print(s);
+}
+''');
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_parentheses_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_parentheses_test.dart
new file mode 100644
index 0000000..88b7f30
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_parentheses_test.dart
@@ -0,0 +1,80 @@
+// 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/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnnecessaryParenthesesTest);
+  });
+}
+
+@reflectiveTest
+class RemoveUnnecessaryParenthesesTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_PARENTHESES;
+
+  @override
+  String get lintCode => LintNames.unnecessary_parenthesis;
+
+  Future<void> test_all() async {
+    await resolveTestCode('''
+void f() {
+  (1);
+  (22);
+  (333);
+}
+''');
+    var lintCode = await lintCodeByName(this.lintCode);
+    await assertHasFixAllFix(lintCode, '''
+void f() {
+  1;
+  22;
+  333;
+}
+''');
+  }
+
+  Future<void> test_double_atInner() async {
+    await resolveTestCode('''
+void f() {
+  ((42));
+}
+''');
+    await assertNoFix(
+      errorFilter: (e) => e.offset == testCode.indexOf('(42'),
+    );
+  }
+
+  Future<void> test_double_atOuter() async {
+    await resolveTestCode('''
+void f() {
+  ((42));
+}
+''');
+    await assertHasFix('''
+void f() {
+  (42);
+}
+''', errorFilter: (e) => e.offset == testCode.indexOf('((42'));
+  }
+
+  Future<void> test_single() async {
+    await resolveTestCode('''
+void f() {
+  (42);
+}
+''');
+    await assertHasFix('''
+void f() {
+  42;
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_string_interpolation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_string_interpolation_test.dart
new file mode 100644
index 0000000..cd6a3c4
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_string_interpolation_test.dart
@@ -0,0 +1,213 @@
+// 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/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnnecessaryStringInterpolationTest);
+  });
+}
+
+@reflectiveTest
+class RemoveUnnecessaryStringInterpolationTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_STRING_INTERPOLATION;
+
+  @override
+  String get lintCode => LintNames.unnecessary_string_interpolations;
+
+  Future<void> test_doubleQuote_noBrackets() async {
+    await resolveTestCode(r'''
+void f() {
+  const test = 'testing';
+  "$test";
+}
+''');
+    await assertHasFix(r'''
+void f() {
+  const test = 'testing';
+  test;
+}
+''');
+  }
+
+  Future<void> test_doubleQuote_withBrackets() async {
+    await resolveTestCode(r'''
+void f() {
+  const test = 'testing';
+  "${test}";
+}
+''');
+    await assertHasFix(r'''
+void f() {
+  const test = 'testing';
+  test;
+}
+''');
+  }
+
+  Future<void> test_maintainPrecedence_hasParentheses() async {
+    await resolveTestCode(r'''
+void f(String s) {
+  print('${(s * 2)}'.length);
+}
+''');
+    await assertHasFix(r'''
+void f(String s) {
+  print((s * 2).length);
+}
+''');
+  }
+
+  Future<void> test_maintainPrecedence_noParentheses() async {
+    await resolveTestCode(r'''
+void f(String s) {
+  print('${s * 2}'.length);
+}
+''');
+    await assertHasFix(r'''
+void f(String s) {
+  print((s * 2).length);
+}
+''');
+  }
+
+  Future<void> test_maintainPrecedence_unaryPrefix_addParentheses() async {
+    await resolveTestCode(r'''
+extension Minusable on String {
+  String operator -() => '-$this';
+}
+
+void f(String s) {
+  print('${-  s}'.length);
+}
+''');
+    await assertHasFix(r'''
+extension Minusable on String {
+  String operator -() => '-$this';
+}
+
+void f(String s) {
+  print((-  s).length);
+}
+''');
+  }
+
+  Future<void> test_maintainPrecedence_unaryPrefix_doNotAddParentheses() async {
+    await resolveTestCode(r'''
+extension Minusable on String {
+  String operator -() => '-$this';
+}
+
+void f(String s) {
+  print('${-s}');
+}
+''');
+    await assertHasFix(r'''
+extension Minusable on String {
+  String operator -() => '-$this';
+}
+
+void f(String s) {
+  print(-s);
+}
+''');
+  }
+
+  Future<void> test_singleQuote_noBrackets() async {
+    await resolveTestCode(r'''
+void f() {
+  const test = 'testing';
+  '$test';
+}
+''');
+    await assertHasFix(r'''
+void f() {
+  const test = 'testing';
+  test;
+}
+''');
+  }
+
+  Future<void> test_singleQuote_withBrackets() async {
+    await resolveTestCode(r'''
+void f() {
+  const test = 'testing';
+  '${test}';
+}
+''');
+    await assertHasFix(r'''
+void f() {
+  const test = 'testing';
+  test;
+}
+''');
+  }
+
+  Future<void> test_tripleDoubleQuote_noBrackets() async {
+    await resolveTestCode(r'''
+void f() {
+  const test = 'testing';
+  """$test""";
+}
+''');
+    await assertHasFix(r'''
+void f() {
+  const test = 'testing';
+  test;
+}
+''');
+  }
+
+  Future<void> test_tripleDoubleQuote_withBrackets() async {
+    await resolveTestCode(r'''
+void f() {
+  const test = 'testing';
+  """${test}""";
+}
+''');
+    await assertHasFix(r'''
+void f() {
+  const test = 'testing';
+  test;
+}
+''');
+  }
+
+  Future<void> test_tripleSingleQuote_noBrackets() async {
+    await resolveTestCode(r"""
+void f() {
+  const test = 'testing';
+  '''$test''';
+}
+""");
+    await assertHasFix(r'''
+void f() {
+  const test = 'testing';
+  test;
+}
+''');
+  }
+
+  Future<void> test_tripleSingleQuote_withBrackets() async {
+    await resolveTestCode(r"""
+void f() {
+  const test = 'testing';
+  '''${test}''';
+}
+""");
+    await assertHasFix(r'''
+void f() {
+  const test = 'testing';
+  test;
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart
index c73b174..dac33f8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_local_variable_test.dart
@@ -20,6 +20,21 @@
   @override
   FixKind get kind => DartFixKind.REMOVE_UNUSED_LOCAL_VARIABLE;
 
+  Future<void> test_assignmentInAssignment() async {
+    await resolveTestCode(r'''
+main() {
+  var v = 1;
+  v = (v = 2);
+  print(0);
+}
+''');
+    await assertHasFix(r'''
+main() {
+  print(0);
+}
+''');
+  }
+
   Future<void> test_inArgumentList() async {
     await resolveTestCode(r'''
 main() {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_not_null_aware_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_not_null_aware_test.dart
index 1009ac6..ccbc1cf 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_with_not_null_aware_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_not_null_aware_test.dart
@@ -137,6 +137,22 @@
 ''');
   }
 
+  Future<void> test_shortCircuit() async {
+    await resolveTestCode('''
+class C {
+  C a(C? c) => c?.b?.b ?? this;
+  C get b => this;
+}
+''');
+
+    await assertHasFix('''
+class C {
+  C a(C? c) => c?.b.b ?? this;
+  C get b => this;
+}
+''');
+  }
+
   Future<void> test_spread() async {
     await resolveTestCode('''
 void f(List<int> x) {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 6b82811..62832b7 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -54,6 +54,7 @@
 import 'convert_to_list_literal_test.dart' as convert_to_list_literal;
 import 'convert_to_map_literal_test.dart' as convert_to_map_literal;
 import 'convert_to_named_arguments_test.dart' as convert_to_named_arguments;
+import 'convert_to_null_aware_spread_test.dart' as convert_to_null_aware_spread;
 import 'convert_to_null_aware_test.dart' as convert_to_null_aware;
 import 'convert_to_on_type_test.dart' as convert_to_on_type;
 import 'convert_to_package_import_test.dart' as convert_to_package_import;
@@ -128,6 +129,10 @@
 import 'remove_unnecessary_cast_test.dart' as remove_unnecessary_cast;
 import 'remove_unnecessary_const_test.dart' as remove_unnecessary_const;
 import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
+import 'remove_unnecessary_parentheses_test.dart'
+    as remove_unnecessary_parentheses;
+import 'remove_unnecessary_string_interpolation_test.dart'
+    as remove_unnecessary_string_interpolation;
 import 'remove_unused_catch_clause_test.dart' as remove_unused_catch_clause;
 import 'remove_unused_catch_stack_test.dart' as remove_unused_catch_stack;
 import 'remove_unused_element_test.dart' as remove_unused_element;
@@ -215,6 +220,7 @@
     convert_to_map_literal.main();
     convert_to_named_arguments.main();
     convert_to_null_aware.main();
+    convert_to_null_aware_spread.main();
     convert_to_on_type.main();
     convert_to_package_import.main();
     convert_to_relative_import.main();
@@ -283,6 +289,8 @@
     remove_unnecessary_cast.main();
     remove_unnecessary_const.main();
     remove_unnecessary_new.main();
+    remove_unnecessary_parentheses.main();
+    remove_unnecessary_string_interpolation.main();
     remove_unused_catch_clause.main();
     remove_unused_catch_stack.main();
     remove_unused_element.main();
diff --git a/pkg/analysis_server/test/src/utilities/flutter_test.dart b/pkg/analysis_server/test/src/utilities/flutter_test.dart
index 0d8276a..cce042e 100644
--- a/pkg/analysis_server/test/src/utilities/flutter_test.dart
+++ b/pkg/analysis_server/test/src/utilities/flutter_test.dart
@@ -165,16 +165,14 @@
 Text createText(String txt) => new Text(txt);
 ''');
     {
-      MethodInvocation invocation = findNodeAtString(
-          'createEmptyText();', (node) => node is MethodInvocation);
+      var invocation = findNode.methodInvocation('createEmptyText();');
       expect(_flutter.identifyWidgetExpression(invocation), invocation);
       var argumentList = invocation.argumentList;
       expect(_flutter.identifyWidgetExpression(argumentList), isNull);
     }
 
     {
-      MethodInvocation invocation = findNodeAtString(
-          "createText('xyz');", (node) => node is MethodInvocation);
+      var invocation = findNode.methodInvocation("createText('xyz');");
       expect(_flutter.identifyWidgetExpression(invocation), invocation);
       var argumentList = invocation.argumentList;
       expect(_flutter.identifyWidgetExpression(argumentList), isNull);
@@ -195,7 +193,7 @@
 
 Text createEmptyText() => new Text('');
 ''');
-    Expression childExpression = findNodeAtString('child: ');
+    var childExpression = findNode.namedExpression('child: ');
     expect(_flutter.identifyWidgetExpression(childExpression), isNull);
   }
 
@@ -212,7 +210,7 @@
   foo.bar; // ref
 }
 ''');
-    SimpleIdentifier bar = findNodeAtString('bar; // ref');
+    var bar = findNode.simple('bar; // ref');
     expect(_flutter.identifyWidgetExpression(bar), bar.parent);
   }
 
@@ -229,7 +227,7 @@
   foo.bar; // ref
 }
 ''');
-    SimpleIdentifier foo = findNodeAtString('foo.bar');
+    var foo = findNode.simple('foo.bar');
     expect(_flutter.identifyWidgetExpression(foo), foo.parent);
   }
 
@@ -241,7 +239,7 @@
   widget; // ref
 }
 ''');
-    Expression expression = findNodeAtString('widget; // ref');
+    var expression = findNode.simple('widget; // ref');
     expect(_flutter.identifyWidgetExpression(expression), expression);
   }
 
@@ -258,12 +256,12 @@
 ''');
     expect(_flutter.identifyWidgetExpression(null), isNull);
     {
-      Expression expression = findNodeAtString('42;');
+      var expression = findNode.integerLiteral('42;');
       expect(_flutter.identifyWidgetExpression(expression), isNull);
     }
 
     {
-      Expression expression = findNodeAtString('intVariable;');
+      var expression = findNode.simple('intVariable;');
       expect(_flutter.identifyWidgetExpression(expression), isNull);
     }
   }
@@ -279,7 +277,7 @@
 
 void useWidget(Widget w) {}
 ''');
-    Expression expression = findNodeAtString('text); // ref');
+    var expression = findNode.simple('text); // ref');
     expect(_flutter.identifyWidgetExpression(expression), expression);
   }
 
@@ -323,10 +321,10 @@
   condition ? w1 : w2;
 }
 ''');
-    Expression thenWidget = findNodeAtString('w1 :');
+    var thenWidget = findNode.simple('w1 :');
     expect(_flutter.identifyWidgetExpression(thenWidget), thenWidget);
 
-    Expression elseWidget = findNodeAtString('w2;');
+    var elseWidget = findNode.simple('w2;');
     expect(_flutter.identifyWidgetExpression(elseWidget), elseWidget);
   }
 
@@ -337,7 +335,7 @@
 
 main(Widget widget) => widget; // ref
 ''');
-    Expression expression = findNodeAtString('widget; // ref');
+    var expression = findNode.simple('widget; // ref');
     expect(_flutter.identifyWidgetExpression(expression), expression);
   }
 
@@ -350,7 +348,7 @@
   widget; // ref
 }
 ''');
-    Expression expression = findNodeAtString('widget; // ref');
+    var expression = findNode.simple('widget; // ref');
     expect(_flutter.identifyWidgetExpression(expression), expression);
   }
 
@@ -400,7 +398,7 @@
   return [widget]; // ref
 }
 ''');
-    Expression expression = findNodeAtString('widget]; // ref');
+    var expression = findNode.simple('widget]; // ref');
     expect(_flutter.identifyWidgetExpression(expression), expression);
   }
 
@@ -415,7 +413,7 @@
 
 void useWidget({Widget child}) {}
 ''');
-    Expression expression = findNodeAtString('text); // ref');
+    var expression = findNode.simple('text); // ref');
     expect(_flutter.identifyWidgetExpression(expression), expression);
   }
 
@@ -427,7 +425,7 @@
   return widget; // ref
 }
 ''');
-    Expression expression = findNodeAtString('widget; // ref');
+    var expression = findNode.simple('widget; // ref');
     expect(_flutter.identifyWidgetExpression(expression), expression);
   }
 
@@ -494,46 +492,44 @@
 Text createEmptyText() => new Text('');
 ''');
     {
-      Expression expression = findNodeAtString('named(); // use');
+      var expression = findNode.simple('named(); // use');
       expect(_flutter.isWidgetExpression(expression), isFalse);
       var creation = expression.parent.parent as InstanceCreationExpression;
       expect(_flutter.isWidgetExpression(creation), isTrue);
     }
 
     {
-      Expression expression = findNodeAtString("new Text('abc')");
+      var expression = findNode.instanceCreation("new Text('abc')");
       expect(_flutter.isWidgetExpression(expression), isTrue);
     }
 
     {
-      Expression expression = findNodeAtString('text;');
+      var expression = findNode.simple('text;');
       expect(_flutter.isWidgetExpression(expression), isTrue);
     }
 
     {
-      Expression expression = findNodeAtString(
-          'createEmptyText();', (node) => node is MethodInvocation);
+      var expression = findNode.methodInvocation('createEmptyText();');
       expect(_flutter.isWidgetExpression(expression), isTrue);
     }
 
     {
-      SimpleIdentifier expression = findNodeAtString('Container(');
+      var expression = findNode.simple('Container(');
       expect(_flutter.isWidgetExpression(expression), isFalse);
     }
 
     {
-      NamedExpression expression =
-          findNodeAtString('child: ', (n) => n is NamedExpression);
+      var expression = findNode.namedExpression('child: ');
       expect(_flutter.isWidgetExpression(expression), isFalse);
     }
 
     {
-      Expression expression = findNodeAtString('42;');
+      var expression = findNode.integerLiteral('42;');
       expect(_flutter.isWidgetExpression(expression), isFalse);
     }
 
     {
-      Expression expression = findNodeAtString('intVariable;');
+      var expression = findNode.simple('intVariable;');
       expect(_flutter.isWidgetExpression(expression), isFalse);
     }
   }
diff --git a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
index 1334077..915c417 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
@@ -167,7 +167,7 @@
       // Value whether expected to parse
       const testTraceValues = {
         'off': true,
-        'messages': true,
+        'message': true,
         'verbose': true,
         null: true,
         'invalid': false,
diff --git a/pkg/analysis_server/test/utils/test_instrumentation_service.dart b/pkg/analysis_server/test/utils/test_instrumentation_service.dart
new file mode 100644
index 0000000..4fd7157
--- /dev/null
+++ b/pkg/analysis_server/test/utils/test_instrumentation_service.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.
+
+import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/instrumentation/service.dart';
+
+/// Implementation of [InstrumentationService] that throws on [logException].
+class TestInstrumentationService implements InstrumentationService {
+  @override
+  void logException(
+    exception, [
+    StackTrace stackTrace,
+    List<InstrumentationServiceAttachment> attachments,
+  ]) {
+    throw CaughtException(exception, stackTrace);
+  }
+
+  @override
+  dynamic noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
diff --git a/pkg/analysis_server/test/utils/test_support.dart b/pkg/analysis_server/test/utils/test_support.dart
index 959be9b..811d8ce 100644
--- a/pkg/analysis_server/test/utils/test_support.dart
+++ b/pkg/analysis_server/test/utils/test_support.dart
@@ -8,8 +8,6 @@
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
 
@@ -119,7 +117,7 @@
   final Map<Source, LineInfo> _lineInfoMap = <Source, LineInfo>{};
 
   /// Initialize a newly created error listener to collect errors.
-  GatheringErrorListener({this.checkRanges = Parser.useFasta});
+  GatheringErrorListener({this.checkRanges = true});
 
   /// Return the errors that were collected.
   List<AnalysisError> get errors => _errors;
diff --git a/pkg/analysis_server/test/verify_sorted_test.dart b/pkg/analysis_server/test/verify_sorted_test.dart
index 60fda8d..869d702 100644
--- a/pkg/analysis_server/test/verify_sorted_test.dart
+++ b/pkg/analysis_server/test/verify_sorted_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 'dart:io';
-
 import 'package:analysis_server/src/services/correction/sort_members.dart';
 import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/dart/analysis/results.dart';
diff --git a/pkg/analysis_server/tool/code_completion/corpus.dart b/pkg/analysis_server/tool/code_completion/corpus.dart
index 71e09fb..8f711d2 100644
--- a/pkg/analysis_server/tool/code_completion/corpus.dart
+++ b/pkg/analysis_server/tool/code_completion/corpus.dart
@@ -91,8 +91,9 @@
 
 Future<String> _getBody(String url) async => (await _getResponse(url)).body;
 
-Future<http.Response> _getResponse(String url) async => _client
-    .get(url, headers: const {'User-Agent': 'dart.pkg.completion_metrics'});
+Future<http.Response> _getResponse(String url) async =>
+    _client.get(Uri.parse(url),
+        headers: const {'User-Agent': 'dart.pkg.completion_metrics'});
 
 bool _hasPubspec(FileSystemEntity f) =>
     f is Directory && File(path.join(f.path, 'pubspec.yaml')).existsSync();
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index 961b2c5..2f679b1 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -33,6 +33,7 @@
 - `dart.enableSdkFormatter`: When set to `false`, prevents registration (or unregisters) the SDK formatter. When set to `true` or not supplied, will register/reregister the SDK formatter.
 - `dart.lineLength`: The number of characters the formatter should wrap code at. If unspecified, code will be wrapped at `80` characters.
 - `dart.completeFunctionCalls`: Completes functions/methods with their required parameters.
+- `dart.showTodos`: Whether to generate diagnostics for TODO comments. If unspecified, diagnostics will not be generated.
 
 ## Method Status
 
@@ -66,6 +67,7 @@
 | workspace/symbol | ✅ | ✅ | | ✅ | ✅ |
 | workspace/executeCommand | ✅ | ✅ | | ✅ | ✅ |
 | workspace/applyEdit | ✅ | ✅ | | ✅ | ✅ |
+| workspace/onWillRenameFiles | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/didOpen | ✅ | ✅ | ✅ | ✅ | ✅ |
 | textDocument/didChange | ✅ | ✅ | ✅ | ✅ | ✅ |
 | textDocument/willSave | | | | | |
@@ -100,6 +102,8 @@
 | textDocument/rename | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/prepareRename | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/foldingRange | ✅ | ✅ | ✅ | ✅ | ✅ |
+| textDocument/semanticTokens/full | ✅ | ✅ | ✅ | ✅ | ✅ |
+| textDocument/semanticTokens/range | ✅ | ✅ | ✅ | ✅ | ✅ |
 
 ## Custom Methods and Notifications
 
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index a265eb5..ff160b1 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -68,7 +68,7 @@
 /// The URI of the version of the spec to generate from. This should be periodically updated as
 /// there's no longer a stable URI for the latest published version.
 final Uri specUri = Uri.parse(
-    'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/specification-3-15.md');
+    'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/specification-3-16.md');
 
 /// Pattern to extract inline types from the `result: {xx, yy }` notes in the spec.
 /// Doesn't parse past full stops as some of these have english sentences tagged on
diff --git a/pkg/analysis_server/tool/lsp_spec/lsp_specification.md b/pkg/analysis_server/tool/lsp_spec/lsp_specification.md
index 14ab9bc..d7c94f3 100644
--- a/pkg/analysis_server/tool/lsp_spec/lsp_specification.md
+++ b/pkg/analysis_server/tool/lsp_spec/lsp_specification.md
@@ -1,5 +1,5 @@
 This is an unmodified copy of the Language Server Protocol Specification,
-downloaded from https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/specification-3-15.md. It is the version of the specification that was
+downloaded from https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/specification-3-16.md. It is the version of the specification that was
 used to generate a portion of the Dart code used to support the protocol.
 
 To regenerate the generated code, run the script in
@@ -22,24 +22,32 @@
 
 ---
 title: Specification
-shortTitle: 3.15 - Current
+shortTitle: 3.16 - Upcoming
 layout: specifications
-sectionid: specification-3-15
-toc: specification-3-15-toc
+sectionid: specification-3-16
+toc: specification-3-16-toc
 index: 2
 ---
-# Language Server Protocol Specification - 3.15
+# Language Server Protocol Specification - 3.16
 
-This document describes the 3.15.x version of the language server protocol. An implementation for node of the 3.15.x version of the protocol can be found [here](https://github.com/Microsoft/vscode-languageserver-node).
+This document describes the 3.16.x version of the language server protocol. An implementation for node of the 3.16.x version of the protocol can be found [here](https://github.com/Microsoft/vscode-languageserver-node).
 
-**Note:** edits to this specification can be made via a pull request against this Markdown [document](https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-15.md).
+**Note:** edits to this specification can be made via a pull request against this markdown [document](https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-16.md).
 
-## <a href="#whatIsNew" name="whatIsNew" class="anchor"> What's new in 3.15 </a>
+## <a href="#whatIsNew" name="whatIsNew" class="anchor"> What's new in 3.16 </a>
 
-All new 3.15 features are tagged with a corresponding since version 3.15 text or in JSDoc using `@since 3.15.0` annotation. Major new features are:
+All new 3.16 features are tagged with a corresponding since version 3.16 text or in JSDoc using `@since 3.16.0` annotation. Major new feature are:
 
-- [general progress support](#progress), [work done progress](#workDoneProgress) and [partial result progress](#partialResults)
-- support for [selection ranges](#textDocument_selectionRange)
+- Semantic Token support
+- Call Hierarchy support
+- Linked Editing support
+- Moniker support
+- Events for file operations (create, rename, delete)
+- Change annotation support for text edits and file operations (create, rename, delete)
+
+A detailed list of the changes can be found in the [change log](#version_3_16_0)
+
+The version of the specification is used to group features into a new specification release and to refer to their first appearance. Features in the spec are kept compatible using so called capability flags which are exchanged between the client and the server during initialization.
 
 ## <a href="#baseProtocol" name="baseProtocol" class="anchor"> Base Protocol </a>
 
@@ -84,6 +92,35 @@
 
 The following TypeScript definitions describe the base [JSON-RPC protocol](http://www.jsonrpc.org/specification):
 
+#### <a href="#number" name="number" class="anchor"> Numbers </a>
+
+The protocol use the following definitions for integers, unsigned integers and decimal numbers:
+
+```typescript
+/**
+ * Defines an integer number in the range of -2^31 to 2^31 - 1.
+ */
+export type integer = number;
+```
+
+```typescript
+/**
+ * Defines an unsigned integer number in the range of 0 to 2^31 - 1.
+ */
+export type uinteger = number;
+```
+
+```typescript
+/**
+ * Defines a decimal number. Since decimal numbers are very
+ * rare in the language server specification we denote the
+ * exact range with every decimal using the mathematics
+ * interval notation (e.g. [0, 1] denotes all decimals d with
+ * 0 <= d <= 1.
+ */
+export type decimal = number;
+```
+
 #### Abstract Message
 
 A general message as defined by JSON-RPC. The language server protocol always uses "2.0" as the `jsonrpc` version.
@@ -103,7 +140,7 @@
 	/**
 	 * The request id.
 	 */
-	id: number | string;
+	id: integer | string;
 
 	/**
 	 * The method to be invoked.
@@ -126,7 +163,7 @@
 	/**
 	 * The request id.
 	 */
-	id: number | string | null;
+	id: integer | string | null;
 
 	/**
 	 * The result of a request. This member is REQUIRED on success.
@@ -144,7 +181,7 @@
 	/**
 	 * A number indicating the error type that occurred.
 	 */
-	code: number;
+	code: integer;
 
 	/**
 	 * A string providing a short description of the error.
@@ -160,19 +197,54 @@
 
 export namespace ErrorCodes {
 	// Defined by JSON RPC
-	export const ParseError: number = -32700;
-	export const InvalidRequest: number = -32600;
-	export const MethodNotFound: number = -32601;
-	export const InvalidParams: number = -32602;
-	export const InternalError: number = -32603;
-	export const serverErrorStart: number = -32099;
-	export const serverErrorEnd: number = -32000;
-	export const ServerNotInitialized: number = -32002;
-	export const UnknownErrorCode: number = -32001;
+	export const ParseError: integer = -32700;
+	export const InvalidRequest: integer = -32600;
+	export const MethodNotFound: integer = -32601;
+	export const InvalidParams: integer = -32602;
+	export const InternalError: integer = -32603;
 
-	// Defined by the protocol.
-	export const RequestCancelled: number = -32800;
-	export const ContentModified: number = -32801;
+	/**
+	 * This is the start range of JSON RPC reserved error codes.
+	 * It doesn't denote a real error code. No LSP error codes should
+	 * be defined between the start and end range. For backwards
+	 * compatibility the `ServerNotInitialized` and the `UnknownErrorCode`
+	 * are left in the range.
+	 *
+	 * @since 3.16.0
+	*/
+	export const jsonrpcReservedErrorRangeStart: integer = -32099;
+	/** @deprecated use  jsonrpcReservedErrorRangeStart */
+	export const serverErrorStart: integer = jsonrpcReservedErrorRangeStart;
+
+	export const ServerNotInitialized: integer = -32002;
+	export const UnknownErrorCode: integer = -32001;
+
+	/**
+	 * This is the start range of JSON RPC reserved error codes.
+	 * It doesn't denote a real error code.
+	*/
+	export const jsonrpcReservedErrorRangeEnd = -32000;
+	/** @deprecated use  jsonrpcReservedErrorRangeEnd */
+	export const serverErrorEnd: integer = jsonrpcReservedErrorRangeEnd;
+
+	/**
+	 * This is the start range of LSP reserved error codes.
+	 * It doesn't denote a real error code.
+	 *
+	 * @since 3.16.0
+	 */
+	export const lspReservedErrorRangeStart: integer = -32899;
+
+	export const ContentModified: integer = -32801;
+	export const RequestCancelled: integer = -32800;
+
+	/**
+	 * This is the end range of LSP reserved error codes.
+	 * It doesn't denote a real error code.
+	 *
+	 * @since 3.16.0
+	 */
+	export const lspReservedErrorRangeEnd: integer = -32800;
 }
 ```
 #### <a href="#notificationMessage" name="notificationMessage" class="anchor"> Notification Message </a>
@@ -195,7 +267,7 @@
 
 #### <a href="#dollarRequests" name="dollarRequests" class="anchor"> $ Notifications and Requests </a>
 
-Notification and requests whose methods start with '$/' are messages which are protocol implementation dependent and might not be implementable in all clients or servers. For example if the server implementation uses a single threaded synchronous programming language then there is little a server can do to react to a '$/cancelRequest' notification. If a server or client receives notifications starting with '$/' it is free to ignore the notification. If a server or client receives a requests starting with '$/' it must error the request with error code `MethodNotFound` (e.g. `-32601`).
+Notification and requests whose methods start with '\$/' are messages which are protocol implementation dependent and might not be implementable in all clients or servers. For example if the server implementation uses a single threaded synchronous programming language then there is little a server can do to react to a `$/cancelRequest` notification. If a server or client receives notifications starting with '\$/' it is free to ignore the notification. If a server or client receives a requests starting with '\$/' it must error the request with error code `MethodNotFound` (e.g. `-32601`).
 
 #### <a href="#cancelRequest" name="cancelRequest" class="anchor"> Cancellation Support (:arrow_right: :arrow_left:)</a>
 
@@ -210,7 +282,7 @@
 	/**
 	 * The request id to cancel.
 	 */
-	id: number | string;
+	id: integer | string;
 }
 ```
 
@@ -229,7 +301,8 @@
 * params: `ProgressParams` defined as follows:
 
 ```typescript
-type ProgressToken = number | string;
+type ProgressToken = integer | string;
+
 interface ProgressParams<T> {
 	/**
 	 * The progress token provided by the client or server.
@@ -277,6 +350,60 @@
 type DocumentUri = string;
 ```
 
+There is also a tagging interface for normal non document URIs. It maps to a `string` as well.
+
+```typescript
+type URI = string;
+```
+
+#### <a href="#regExp" name="regExp" class="anchor"> Regular Expressions </a>
+
+Regular expression are a powerful tool and there are actual use cases for them in the language server protocol. However the downside with them is that almost every programming language has its own set of regular expression features so the specification can not simply refer to them as a regular expression. So the LSP uses a two step approach to support regular expressions:
+
+* the client will announce which regular expression engine it will use. This will allow server that are written for a very specific client make full use of the regular expression capabilities of the client
+* the specification will define a set of regular expression features that should be supported by a client. Instead of writing a new specification LSP will refer to the [ECMAScript Regular Expression specification](https://tc39.es/ecma262/#sec-regexp-regular-expression-objects) and remove features from it that are not necessary in the context of LSP or hard to implement for other clients.
+
+_Client Capability_:
+
+The following client capability is used to announce a client's regular expression engine
+
+* property path (optional): `general.regularExpressions`
+* property type: `RegularExpressionsClientCapabilities` defined as follows:
+
+```typescript
+/**
+ * Client capabilities specific to regular expressions.
+ */
+export interface RegularExpressionsClientCapabilities {
+	/**
+	 * The engine's name.
+	 */
+	engine: string;
+
+	/**
+	 * The engine's version.
+	 */
+	version?: string;
+}
+```
+
+The following table lists the well known engine values. Please note that the table should be driven by the community which integrates LSP into existing clients. It is not the goal of the spec to list all available regular expression engines.
+
+Engine | Version | Documentation
+------- | ------- | -------------
+ECMAScript | `ES2020` | [ECMAScript 2020](https://tc39.es/ecma262/#sec-regexp-regular-expression-objects) & [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
+
+_Regular Expression Subset_:
+
+The following features from the [ECMAScript 2020](https://tc39.es/ecma262/#sec-regexp-regular-expression-objects) regular expression specification are NOT mandatory for a client:
+
+- *Assertions*: Lookahead assertion, Negative lookahead assertion, lookbehind assertion, negative lookbehind assertion.
+- *Character classes*: matching control characters using caret notation (e.g. `\cX`) and matching UTF-16 code units (e.g. `\uhhhh`).
+- *Group and ranges*: named capturing groups.
+- *Unicode property escapes*: none of the features needs to be supported.
+
+The only regular expression flag that a client needs to support is 'i' to specify a case insensitive search.
+
 #### <a href="#textDocuments" name="textDocuments" class="anchor"> Text Documents </a>
 
 The current protocol is tailored for textual documents whose content can be represented as a string. There is currently no support for binary documents. A position inside a document (see Position definition below) is expressed as a zero-based line and character offset. The offsets are based on a UTF-16 string representation. So a string of the form `a𐐀b` the character offset of the character `a` is 0, the character offset of `𐐀` is 1 and the character offset of b is 3 since `𐐀` is represented using two code units in UTF-16. To ensure that both client and server split the string into the same line representation the protocol specifies the following end-of-line sequences: '\n', '\r\n' and '\r'.
@@ -296,17 +423,17 @@
 	/**
 	 * Line position in a document (zero-based).
 	 */
-	line: number;
+	line: uinteger;
 
 	/**
-	 * Character offset on a line in a document (zero-based). Assuming that the
-	 * line is represented as a string, the `character` value represents the gap
-	 * between the `character` and `character + 1`.
+	 * Character offset on a line in a document (zero-based). Assuming that
+	 * the line is represented as a string, the `character` value represents
+	 * the gap between the `character` and `character + 1`.
 	 *
 	 * If the character value is greater than the line length it defaults back
 	 * to the line length.
 	 */
-	character: number;
+	character: uinteger;
 }
 ```
 #### <a href="#range" name="range" class="anchor"> Range </a>
@@ -353,8 +480,8 @@
 	/**
 	 * Span of the origin of this link.
 	 *
-	 * Used as the underlined span for mouse interaction.
-	 * Defaults to the word range at the mouse position.
+	 * Used as the underlined span for mouse interaction. Defaults to the word
+	 * range at the mouse position.
 	 */
 	originSelectionRange?: Range;
 
@@ -364,19 +491,17 @@
 	targetUri: DocumentUri;
 
 	/**
-	 * The full target range of this link.
-	 * For example, if the target is a symbol, then target range is the range
-	 * enclosing this symbol not including leading/trailing whitespace but
-	 * everything else like comments.
-	 * This information is typically used to highlight the range in the editor.
+	 * The full target range of this link. If the target for example is a symbol
+	 * then target range is the range enclosing this symbol not including
+	 * leading/trailing whitespace but everything else like comments. This
+	 * information is typically used to highlight the range in the editor.
 	 */
 	targetRange: Range;
 
 	/**
 	 * The range that should be selected and revealed when this link is being
-	 * followed, for example, the name of a function.
-	 * Must be contained by the the `targetRange`.
-	 * See also `DocumentSymbol#range`
+	 * followed, e.g the name of a function. Must be contained by the the
+	 * `targetRange`. See also `DocumentSymbol#range`
 	 */
 	targetSelectionRange: Range;
 }
@@ -402,7 +527,14 @@
 	/**
 	 * The diagnostic's code, which might appear in the user interface.
 	 */
-	code?: number | string;
+	code?: integer | string;
+
+	/**
+	 * An optional property to describe the error code.
+	 *
+	 * @since 3.16.0
+	 */
+	codeDescription?: CodeDescription;
 
 	/**
 	 * A human-readable string describing the source of this
@@ -427,6 +559,15 @@
 	 * a scope collide all definitions can be marked via this property.
 	 */
 	relatedInformation?: DiagnosticRelatedInformation[];
+
+	/**
+	 * A data entry field that is preserved between a
+	 * `textDocument/publishDiagnostics` notification and
+	 * `textDocument/codeAction` request.
+	 *
+	 * @since 3.16.0
+	 */
+	data?: unknown;
 }
 ```
 
@@ -483,8 +624,8 @@
 ```typescript
 /**
  * Represents a related message and source code location for a diagnostic.
- * This should be used to point to code locations that cause or are related
- * to a diagnostics, for example, when duplicating a symbol in a scope.
+ * This should be used to point to code locations that cause or are related to
+ * a diagnostics, e.g when duplicating a symbol in a scope.
  */
 export interface DiagnosticRelatedInformation {
 	/**
@@ -499,6 +640,22 @@
 }
 ```
 
+`CodeDescription` is defined as follows:
+
+```typescript
+/**
+ * Structure to capture a description for an error code.
+ *
+ * @since 3.16.0
+ */
+export interface CodeDescription {
+	/**
+	 * An URI to open with more information about the diagnostic error.
+	 */
+	href: URI;
+}
+```
+
 #### <a href="#command" name="command" class="anchor"> Command </a>
 
 Represents a reference to a command. Provides a title which will be used to represent a command in the UI. Commands are identified by a string identifier. The recommended way to handle commands is to implement their execution on the server side if the client and server provides the corresponding capabilities. Alternatively the tool extension code could handle the command. The protocol currently doesn't specify a set of well-known commands.
@@ -521,7 +678,9 @@
 }
 ```
 
-#### <a href="#textEdit" name="textEdit" class="anchor"> TextEdit </a>
+#### <a href="#textEdit" name="textEdit" class="anchor"> TextEdit  & AnnotatedTextEdit </a>
+
+> New in version 3.16: Support for `AnnotatedTextEdit`.
 
 A textual edit applicable to a text document.
 
@@ -541,33 +700,93 @@
 }
 ```
 
+Since 3.16.0 there is also the concept of an annotated text edit which supports to add an annotation to a text edit. The annotation can add information describing the change to the text edit.
+
+```typescript
+/**
+ * Additional information that describes document changes.
+ *
+ * @since 3.16.0
+ */
+export interface ChangeAnnotation {
+	/**
+	 * A human-readable string describing the actual change. The string
+	 * is rendered prominent in the user interface.
+	 */
+	label: string;
+
+	/**
+	 * A flag which indicates that user confirmation is needed
+	 * before applying the change.
+	 */
+	needsConfirmation?: boolean;
+
+	/**
+	 * A human-readable string which is rendered less prominent in
+	 * the user interface.
+	 */
+	description?: string;
+}
+```
+
+Usually clients provide options to group the changes along the annotations they are associated with. To support this in the protocol an edit or resource operation refers to a change annotation using an identifier and not the change annotation literal directly. This allows servers to use the identical annotation across multiple edits or resource operations which then allows clients to group the operations under that change annotation. The actual change annotations together with their identifers are managed by the workspace edit via the new property `changeAnnotations`.
+
+```typescript
+
+/**
+ * An identifier referring to a change annotation managed by a workspace
+ * edit.
+ *
+ * @since 3.16.0.
+ */
+export type ChangeAnnotationIdentifier = string;
+
+
+/**
+ * A special text edit with an additional change annotation.
+ *
+ * @since 3.16.0.
+ */
+export interface AnnotatedTextEdit extends TextEdit {
+	/**
+	 * The actual annotation identifier.
+	 */
+	annotationId: ChangeAnnotationIdentifier;
+}
+```
+
 #### <a href="#textEditArray" name="textEditArray" class="anchor"> TextEdit[] </a>
 
-Complex text manipulations are described with an array of `TextEdit`'s, representing a single change to the document.
+Complex text manipulations are described with an array of `TextEdit`'s or `AnnotatedTextEdit`'s, representing a single change to the document.
 
 All text edits ranges refer to positions in the document the are computed on. They therefore move a document from state S1 to S2 without describing any intermediate state. Text edits ranges must never overlap, that means no part of the original document must be manipulated by more than one edit. However, it is possible that multiple edits have the same start position: multiple inserts, or any number of inserts followed by a single remove or replace edit. If multiple inserts have the same position, the order in the array defines the order in which the inserted strings appear in the resulting text.
 
 #### <a href="#textDocumentEdit" name="textDocumentEdit" class="anchor"> TextDocumentEdit </a>
 
-Describes textual changes on a single text document. The text document is referred to as a `VersionedTextDocumentIdentifier` to allow clients to check the text document version before an edit is applied. A `TextDocumentEdit` describes all changes on a version Si and after they are applied move the document to version Si+1. So the creator of a `TextDocumentEdit` doesn't need to sort the array of edits or do any kind of ordering. However the edits must be non overlapping.
+> New in version 3.16: support for `AnnotatedTextEdit`. The support is guarded by the client capability `workspace.workspaceEdit.changeAnnotationSupport`. If a client doesn't signal the capability, servers shouldn't send `AnnotatedTextEdit` literals back to the client.
+
+Describes textual changes on a single text document. The text document is referred to as a `OptionalVersionedTextDocumentIdentifier` to allow clients to check the text document version before an edit is applied. A `TextDocumentEdit` describes all changes on a version Si and after they are applied move the document to version Si+1. So the creator of a `TextDocumentEdit` doesn't need to sort the array of edits or do any kind of ordering. However the edits must be non overlapping.
 
 ```typescript
 export interface TextDocumentEdit {
 	/**
 	 * The text document to change.
 	 */
-	textDocument: VersionedTextDocumentIdentifier;
+	textDocument: OptionalVersionedTextDocumentIdentifier;
 
 	/**
 	 * The edits to be applied.
+	 *
+	 * @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
+	 * client capability `workspace.workspaceEdit.changeAnnotationSupport`
 	 */
-	edits: TextEdit[];
+	edits: (TextEdit | AnnotatedTextEdit)[];
 }
 ```
 
 ### <a href="#resourceChanges" name="resourceChanges" class="anchor"> File Resource changes </a>
 
-> New in version 3.13:
+> New in version 3.13. Since version 3.16 file resource changes can carry an additional property `changeAnnotation` to describe the actual change in more detail. Whether a client has support for change annotations is guarded by the client capability `workspace.workspaceEdit.changeAnnotationSupport`.
 
 File resource changes allow servers to create, rename and delete files and folders via the client. Note that the names talk about files but the operations are supposed to work on files and folders. This is in line with other naming in the Language Server Protocol (see file watchers which can watch files and folders). The corresponding change literals look as follows:
 
@@ -580,6 +799,7 @@
 	 * Overwrite existing file. Overwrite wins over `ignoreIfExists`
 	 */
 	overwrite?: boolean;
+
 	/**
 	 * Ignore if exists.
 	 */
@@ -594,14 +814,23 @@
 	 * A create
 	 */
 	kind: 'create';
+
 	/**
 	 * The resource to create.
 	 */
 	uri: DocumentUri;
+
 	/**
 	 * Additional options
 	 */
 	options?: CreateFileOptions;
+
+	/**
+	 * An optional annotation identifer describing the operation.
+	 *
+	 * @since 3.16.0
+	 */
+	annotationId?: ChangeAnnotationIdentifier;
 }
 
 /**
@@ -612,6 +841,7 @@
 	 * Overwrite target if existing. Overwrite wins over `ignoreIfExists`
 	 */
 	overwrite?: boolean;
+
 	/**
 	 * Ignores if target exists.
 	 */
@@ -626,18 +856,28 @@
 	 * A rename
 	 */
 	kind: 'rename';
+
 	/**
 	 * The old (existing) location.
 	 */
 	oldUri: DocumentUri;
+
 	/**
 	 * The new location.
 	 */
 	newUri: DocumentUri;
+
 	/**
 	 * Rename options.
 	 */
 	options?: RenameFileOptions;
+
+	/**
+	 * An optional annotation identifer describing the operation.
+	 *
+	 * @since 3.16.0
+	 */
+	annotationId?: ChangeAnnotationIdentifier;
 }
 
 /**
@@ -648,6 +888,7 @@
 	 * Delete the content recursively if a folder is denoted.
 	 */
 	recursive?: boolean;
+
 	/**
 	 * Ignore the operation if the file doesn't exist.
 	 */
@@ -662,14 +903,23 @@
 	 * A delete
 	 */
 	kind: 'delete';
+
 	/**
 	 * The file to delete.
 	 */
 	uri: DocumentUri;
+
 	/**
 	 * Delete options.
 	 */
 	options?: DeleteFileOptions;
+
+	/**
+	 * An optional annotation identifer describing the operation.
+	 *
+	 * @since 3.16.0
+	 */
+	annotationId?: ChangeAnnotationIdentifier;
 }
 ```
 
@@ -685,24 +935,38 @@
 	changes?: { [uri: DocumentUri]: TextEdit[]; };
 
 	/**
-	 * The client capability `workspace.workspaceEdit.resourceOperations`
-	 * determines whether document changes are either an array of
-	 * `TextDocumentEdit`s to express changes to different text documents,
-	 * where each text document edit addresses a specific version
-	 * of a text document, or it can contains the above `TextDocumentEdit`s
-	 * mixed with create, rename, and delete file / folder operations.
+	 * Depending on the client capability
+	 * `workspace.workspaceEdit.resourceOperations` document changes are either
+	 * an array of `TextDocumentEdit`s to express changes to n different text
+	 * documents where each text document edit addresses a specific version of
+	 * a text document. Or it can contain above `TextDocumentEdit`s mixed with
+	 * create, rename and delete file / folder operations.
 	 *
 	 * Whether a client supports versioned document edits is expressed via
 	 * `workspace.workspaceEdit.documentChanges` client capability.
 	 *
-	 * If a client doesn't support `documentChanges` or
-	 * `workspace.workspaceEdit.resourceOperations`, then only plain
-	 * `TextEdit`s using the `changes` property are supported.
+	 * If a client neither supports `documentChanges` nor
+	 * `workspace.workspaceEdit.resourceOperations` then only plain `TextEdit`s
+	 * using the `changes` property are supported.
 	 */
 	documentChanges?: (
 		TextDocumentEdit[] |
 		(TextDocumentEdit | CreateFile | RenameFile | DeleteFile)[]
 	);
+
+	/**
+	 * A map of change annotations that can be referenced in
+	 * `AnnotatedTextEdit`s or create, rename and delete file / folder
+	 * operations.
+	 *
+	 * Whether clients honor this property depends on the client capability
+	 * `workspace.changeAnnotationSupport`.
+	 *
+	 * @since 3.16.0
+	 */
+	changeAnnotations?: {
+		[id: string /* ChangeAnnotationIdentifier */]: ChangeAnnotation;
+	}
 }
 ```
 
@@ -738,6 +1002,31 @@
 	 * @since 3.13.0
 	 */
 	failureHandling?: FailureHandlingKind;
+
+	/**
+	 * Whether the client normalizes line endings to the client specific
+	 * setting.
+	 * If set to `true` the client will normalize line ending characters
+	 * in a workspace edit to the client specific new line character(s).
+	 *
+	 * @since 3.16.0
+	 */
+	normalizesLineEndings?: boolean;
+
+	/**
+	 * Whether the client in general supports change annotations on text edits,
+	 * create file, rename file and delete file changes.
+	 *
+	 * @since 3.16.0
+	 */
+	changeAnnotationSupport?: {
+        /**
+         * Whether the client groups edits with equal labels into tree nodes,
+         * for instance all edits labelled with "Changes in Strings" would
+         * be a tree node.
+         */
+        groupsOnLabel?: boolean;
+	};
 }
 
 /**
@@ -770,8 +1059,8 @@
 
 	/**
 	 * Applying the workspace change is simply aborted if one of the changes
-	 * provided fails.
-	 * All operations executed before the failing operation stay executed.
+	 * provided fails. All operations executed before the failing operation
+	 * stay executed.
 	 */
 	export const Abort: FailureHandlingKind = 'abort';
 
@@ -783,10 +1072,9 @@
 
 
 	/**
-	 * If the workspace edit contains only textual file changes, they are
-	 * executed transactionally.
-	 * If resource changes (create, rename or delete file) are part of the
-	 * change, the failure handling strategy is abort.
+	 * If the workspace edit contains only textual file changes they are
+	 * executed transactional. If resource changes (create, rename or delete
+	 * file) are part of the change the failure handling strategy is abort.
 	 */
 	export const TextOnlyTransactional: FailureHandlingKind
 		= 'textOnlyTransactional';
@@ -831,7 +1119,7 @@
 	 * The version number of this document (it will increase after each
 	 * change, including undo/redo).
 	 */
-	version: number;
+	version: integer;
 
 	/**
 	 * The content of the opened text document.
@@ -903,22 +1191,36 @@
 
 #### <a href="#versionedTextDocumentIdentifier" name="versionedTextDocumentIdentifier" class="anchor"> VersionedTextDocumentIdentifier </a>
 
-An identifier to denote a specific version of a text document.
+An identifier to denote a specific version of a text document. This information usually flows from the client to the server.
 
 ```typescript
 interface VersionedTextDocumentIdentifier extends TextDocumentIdentifier {
 	/**
 	 * The version number of this document.
-	 * If a versioned text document identifier is sent from the server to the
-	 * client and the file is not open in the editor (the server has not
-	 * received an open notification before), the server can send `null` to
-	 * indicate that the version is known and the content on disk is the
-	 * master (as specified with document content ownership).
 	 *
 	 * The version number of a document will increase after each change,
 	 * including undo/redo. The number doesn't need to be consecutive.
 	 */
-	version: number | null;
+	version: integer;
+}
+```
+
+An identifier which optionally denotes a specific version of a text document. This information usually flows from the server to the client.
+
+```typescript
+interface OptionalVersionedTextDocumentIdentifier extends TextDocumentIdentifier {
+	/**
+	 * The version number of this document. If an optional versioned text document
+	 * identifier is sent from the server to the client and the file is not
+	 * open in the editor (the server has not received an open notification
+	 * before) the server can send `null` to indicate that the version is
+	 * known and the content on disk is the master (as specified with document
+	 * content ownership).
+	 *
+	 * The version number of a document will increase after each change,
+	 * including undo/redo. The number doesn't need to be consecutive.
+	 */
+	version: integer | null;
 }
 ```
 
@@ -926,7 +1228,7 @@
 
 Was `TextDocumentPosition` in 1.0 with inlined parameters.
 
-A parameter literal used in requests to pass a text document and a position inside that document.
+A parameter literal used in requests to pass a text document and a position inside that document. It is up to the client to decide how a selection is converted into a position when issuing a request for a text document. The client can for example honor or ignore the selection direction to make LSP request consistent with features implemented internally.
 
 ```typescript
 interface TextDocumentPositionParams {
@@ -969,13 +1271,13 @@
 	 * - `*` to match one or more characters in a path segment
 	 * - `?` to match on one character in a path segment
 	 * - `**` to match any number of path segments, including none
-	 * - `{}` to group conditions
-	 *   (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
+	 * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
+	 *   and JavaScript files)
 	 * - `[]` to declare a range of characters to match in a path segment
 	 *   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
 	 * - `[!...]` to negate a range of characters to match in a path segment
-	 *   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`,
-	 *    but not `example.0`)
+	 *   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
+	 *   not `example.0`)
 	 */
 	pattern?: string;
 }
@@ -1014,9 +1316,8 @@
  */
 export interface TextDocumentRegistrationOptions {
 	/**
-	 * A document selector to identify the scope of the registration.
-	 * If set to null, the document selector provided on the client side
-	 * will be used.
+	 * A document selector to identify the scope of the registration. If set to
+	 * null the document selector provided on the client side will be used.
 	 */
 	documentSelector: DocumentSelector | null;
 }
@@ -1024,7 +1325,7 @@
 
 #### <a href="#markupContent" name="markupContent" class="anchor"> MarkupContent </a>
 
- A `MarkupContent` literal represents a string value which content can be represented in different formats. Currently `plaintext` and `markdown` are supported formats. A `MarkupContent` is usually used in documentation properties of result literals like `CompletionItem` or `SignatureInformation`. If the format is `markdown` the content can contain fenced code blocks like in [GitHub issues](https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting)
+ A `MarkupContent` literal represents a string value which content can be represented in different formats. Currently `plaintext` and `markdown` are supported formats. A `MarkupContent` is usually used in documentation properties of result literals like `CompletionItem` or `SignatureInformation`. If the format is `markdown` the content should follow the [GitHub Flavored Markdown Specification](https://github.github.com/gfm/).
 
 ```typescript
 /**
@@ -1048,14 +1349,15 @@
 export type MarkupKind = 'plaintext' | 'markdown';
 
 /**
- * A `MarkupContent` literal represents a string value, which content is
- * interpreted base on its kind flag.
- * Currently the protocol supports `plaintext` and `markdown` as markup kinds.
+ * A `MarkupContent` literal represents a string value which content is
+ * interpreted base on its kind flag. Currently the protocol supports
+ * `plaintext` and `markdown` as markup kinds.
  *
- * If the kind is `markdown`, then the value can contain fenced code blocks
- * like in GitHub issues.
+ * If the kind is `markdown` then the value can contain fenced code blocks like
+ * in GitHub issues.
  *
- * An example how such a string is constructed using JavaScript / TypeScript:
+ * Here is an example how such a string can be constructed using
+ * JavaScript / TypeScript:
  * ```typescript
  * let markdown: MarkdownContent = {
  *  kind: MarkupKind.Markdown,
@@ -1069,9 +1371,8 @@
  * };
  * ```
  *
- * *Please Note* that clients might sanitize the returned Markdown.
- * A client could decide to remove HTML from the Markdown to avoid
- * script execution.
+ * *Please Note* that clients might sanitize the return markdown. A client could
+ * decide to remove HTML from the markdown to avoid script execution.
  */
 export interface MarkupContent {
 	/**
@@ -1086,6 +1387,34 @@
 }
 ```
 
+In addition clients should signal the markdown parser they are using via the client capability `general.markdown` introduced in version 3.16.0 defined as follows:
+
+ ```typescript
+/**
+ * Client capabilities specific to the used markdown parser.
+ *
+ * @since 3.16.0
+ */
+export interface MarkdownClientCapabilities {
+	/**
+	 * The name of the parser.
+	 */
+	parser: string;
+
+	/**
+	 * The version of the parser.
+	 */
+	version?: string;
+}
+ ```
+
+Known markdown parsers used by clients right now are:
+
+Parser | Version | Documentation
+------ | ------- | -------------
+marked | 1.1.0   | [Marked Documentation](https://marked.js.org/)
+
+
 #### <a href="#workDoneProgress" name="workDoneProgress" class="anchor"> Work Done Progress </a>
 
 > *Since version 3.15.0*
@@ -1111,8 +1440,8 @@
 
 	/**
 	 * Controls if a cancel button should show to allow the user to cancel the
-	 * long running operation.
-	 * Clients that don't support cancellation can ignore the setting.
+	 * long running operation. Clients that don't support cancellation are
+	 * allowed to ignore the setting.
 	 */
 	cancellable?: boolean;
 
@@ -1131,9 +1460,9 @@
 	 * to ignore the `percentage` value in subsequent in report notifications.
 	 *
 	 * The value should be steadily rising. Clients are free to ignore values
-	 * that are not following this rule.
+	 * that are not following this rule. The value range is [0, 100]
 	 */
-	percentage?: number;
+	percentage?: uinteger;
 }
 ```
 
@@ -1147,12 +1476,11 @@
 	kind: 'report';
 
 	/**
-	 * Controls enablement state of a cancel button. T
-	 * This property is only valid if a cancel button is requested in
-	 * the `WorkDoneProgressStart` payload.
+	 * Controls enablement state of a cancel button. This property is only valid
+	 *  if a cancel button got requested in the `WorkDoneProgressStart` payload.
 	 *
-	 * Clients that don't support cancellation or don't support controlling
-	 * the button's enablement state are allowed to ignore the setting.
+	 * Clients that don't support cancellation or don't support control the
+	 * button's enablement state are allowed to ignore the setting.
 	 */
 	cancellable?: boolean;
 
@@ -1171,9 +1499,9 @@
 	 * to ignore the `percentage` value in subsequent in report notifications.
 	 *
 	 * The value should be steadily rising. Clients are free to ignore values
-	 * that are not following this rule.
+	 * that are not following this rule. The value range is [0, 100]
 	 */
-	percentage?: number;
+	percentage?: uinteger;
 }
 ```
 
@@ -1248,6 +1576,8 @@
 }
 ```
 
+The token received via the `workDoneToken` property in a request's param literal is only valid as long as the request has not send a response back.
+
 There is no specific client capability signaling whether a client will send a progress token per request. The reason for this is that this is in many clients not a static aspect and might even change for every request instance for the same request type. So the capability is signal on every request instance by the presence of a `workDoneToken` property.
 
 To avoid that clients set up a progress monitor user interface before sending a request but the server doesn't actually report any progress a server needs to signal general work done progress reporting support in the corresponding server capability. For the above find references example a server would signal such a support by setting the `referencesProvider` property in the server capabilities as follows:
@@ -1269,7 +1599,7 @@
 ```
 ###### <a href="#serverInitiatedProgress" name="serverInitiatedProgress" class="anchor">Server Initiated Progress </a>
 
-Servers can also initiate progress reporting using the `window/workDoneProgress/create` request. This is useful if the server needs to report progress outside of a request (for example the server needs to re-index a database). The returned token can then be used to report progress using the same notifications used as for client initiated progress.
+Servers can also initiate progress reporting using the `window/workDoneProgress/create` request. This is useful if the server needs to report progress outside of a request (for example the server needs to re-index a database). The returned token can then be used to report progress using the same notifications used as for client initiated progress. A token obtained using the create request should only be used once (e.g. only one begin, many report and one end notification should be sent to it).
 
 To keep the protocol backwards compatible servers are only allowed to use `window/workDoneProgress/create` request if the client signals corresponding support using the client capability `window.workDoneProgress` which is defined as follows:
 
@@ -1327,23 +1657,32 @@
 ```typescript
 export interface PartialResultParams {
 	/**
-	 * An optional token that a server can use to report partial results
-	 * (for example, streaming) to the client.
+	 * An optional token that a server can use to report partial results (e.g.
+	 * streaming) to the client.
 	 */
 	partialResultToken?: ProgressToken;
 }
 ```
 
+#### <a href="#traceValue" name="traceValue" class="anchor"> TraceValue </a>
+
+A `TraceValue` represents the level of verbosity with which the server systematically reports its execution trace using [$/logTrace](#logTrace) notifications.
+The initial trace value is set by the client at initialization and can be modified later using the [$/setTrace](#setTrace) notification.
+
+```typescript
+export type TraceValue = 'off' | 'message' | 'verbose'
+```
+
 ### Actual Protocol
 
 This section documents the actual language server protocol. It uses the following format:
 
 * a header describing the request
 * an optional _Client capability_ section describing the client capability of the request. This includes the client capabilities property path and JSON structure.
-* an optional _Server Capability_ section describing the server capability of the request. This includes the server capabilities property path and JSON structure.
+* an optional _Server Capability_ section describing the server capability of the request. This includes the server capabilities property path and JSON structure. Clients should ignore server capabilities they don't understand (e.g. the initialize request shouldn't fail in this case).
+* an optional _Registration Options_ section describing the registration option if the request or notification supports dynamic capability registration. See the [register](#client_registerCapability) and [unregister](#client_unregisterCapability) request for how this works in detail.
 * a _Request_ section describing the format of the request sent. The method is a string identifying the request the params are documented using a TypeScript interface. It is also documented whether the request supports work done progress and partial result progress.
 * a _Response_ section describing the format of the response. The result item describes the returned data in case of a success. The optional partial result item describes the returned data of a partial result notification. The error.data describes the returned data in case of an error. Please remember that in case of a failure the response already contains an error.code and an error.message field. These fields are only specified if the protocol forces the use of certain error codes or messages. In cases where the server can decide on these values freely they aren't listed here.
-* a _Registration Options_ section describing the registration option if the request or notification supports dynamic capability registration.
 
 #### Request, Notification and Response ordering
 
@@ -1373,12 +1712,12 @@
 ```typescript
 interface InitializeParams extends WorkDoneProgressParams {
 	/**
-	 * The process ID of the parent process that started the server.
-	 * Is null if the process has not been started by another process.
-	 * If the parent process is not alive, then the server should exit
-	 * (see exit notification) its process.
+	 * The process Id of the parent process that started the server. Is null if
+	 * the process has not been started by another process. If the parent
+	 * process is not alive then the server should exit (see exit notification)
+	 * its process.
 	 */
-	processId: number | null;
+	processId: integer | null;
 
 	/**
 	 * Information about the client
@@ -1398,10 +1737,22 @@
 	};
 
 	/**
+	 * The locale the client is currently showing the user interface
+	 * in. This must not necessarily be the locale of the operating
+	 * system.
+	 *
+	 * Uses IETF language tags as the value's syntax
+	 * (See https://en.wikipedia.org/wiki/IETF_language_tag)
+	 *
+	 * @since 3.16.0
+	 */
+	locale?: string;
+
+	/**
 	 * The rootPath of the workspace. Is null
 	 * if no folder is open.
 	 *
-	 * @deprecated in favour of rootUri.
+	 * @deprecated in favour of `rootUri`.
 	 */
 	rootPath?: string | null;
 
@@ -1409,6 +1760,8 @@
 	 * The rootUri of the workspace. Is null if no
 	 * folder is open. If both `rootPath` and `rootUri` are set
 	 * `rootUri` wins.
+	 *
+	 * @deprecated in favour of `workspaceFolders`
 	 */
 	rootUri: DocumentUri | null;
 
@@ -1425,7 +1778,7 @@
 	/**
 	 * The initial trace setting. If omitted trace is disabled ('off').
 	 */
-	trace?: 'off' | 'messages' | 'verbose';
+	trace?: TraceValue;
 
 	/**
 	 * The workspace folders configured in the client when the server starts.
@@ -1441,7 +1794,9 @@
 Where `ClientCapabilities` and `TextDocumentClientCapabilities` are defined as follows:
 
 
-##### `TextDocumentClientCapabilities` define capabilities the editor / tool provides on text documents.
+##### TextDocumentClientCapabilities
+
+`TextDocumentClientCapabilities` define capabilities the editor / tool provides on text documents.
 
 ```typescript
 /**
@@ -1569,6 +1924,34 @@
 	 * @since 3.15.0
 	 */
 	selectionRange?: SelectionRangeClientCapabilities;
+
+	/**
+	 * Capabilities specific to the `textDocument/linkedEditingRange` request.
+	 *
+	 * @since 3.16.0
+	 */
+	linkedEditingRange?: LinkedEditingRangeClientCapabilities;
+
+	/**
+	 * Capabilities specific to the various call hierarchy requests.
+	 *
+	 * @since 3.16.0
+	 */
+	callHierarchy?: CallHierarchyClientCapabilities;
+
+	/**
+	 * Capabilities specific to the various semantic token requests.
+	 *
+	 * @since 3.16.0
+	 */
+	semanticTokens?: SemanticTokensClientCapabilities;
+
+	/**
+	 * Capabilities specific to the `textDocument/moniker` request.
+	 *
+	 * @since 3.16.0
+	 */
+	moniker?: MonikerClientCapabilities;
 }
 ```
 
@@ -1583,52 +1966,111 @@
 	 */
 	workspace?: {
 		/**
-		* The client supports applying batch edits
-		* to the workspace by supporting the request
-		* 'workspace/applyEdit'
-		*/
+		 * The client supports applying batch edits
+		 * to the workspace by supporting the request
+		 * 'workspace/applyEdit'
+		 */
 		applyEdit?: boolean;
 
 		/**
-		* Capabilities specific to `WorkspaceEdit`s
-		*/
+		 * Capabilities specific to `WorkspaceEdit`s
+		 */
 		workspaceEdit?: WorkspaceEditClientCapabilities;
 
 		/**
-		* Capabilities specific to the `workspace/didChangeConfiguration`
-		* notification.
-		*/
+		 * Capabilities specific to the `workspace/didChangeConfiguration`
+		 * notification.
+		 */
 		didChangeConfiguration?: DidChangeConfigurationClientCapabilities;
 
 		/**
-		* Capabilities specific to the `workspace/didChangeWatchedFiles`
-		* notification.
-		*/
+		 * Capabilities specific to the `workspace/didChangeWatchedFiles`
+		 * notification.
+		 */
 		didChangeWatchedFiles?: DidChangeWatchedFilesClientCapabilities;
 
 		/**
-		* Capabilities specific to the `workspace/symbol` request.
-		*/
+		 * Capabilities specific to the `workspace/symbol` request.
+		 */
 		symbol?: WorkspaceSymbolClientCapabilities;
 
 		/**
-		* Capabilities specific to the `workspace/executeCommand` request.
-		*/
+		 * Capabilities specific to the `workspace/executeCommand` request.
+		 */
 		executeCommand?: ExecuteCommandClientCapabilities;
 
 		/**
-		* The client has support for workspace folders.
-		*
-		* Since 3.6.0
-		*/
+		 * The client has support for workspace folders.
+		 *
+		 * @since 3.6.0
+		 */
 		workspaceFolders?: boolean;
 
 		/**
-		* The client supports `workspace/configuration` requests.
-		*
-		* Since 3.6.0
-		*/
+		 * The client supports `workspace/configuration` requests.
+		 *
+		 * @since 3.6.0
+		 */
 		configuration?: boolean;
+
+		/**
+		 * Capabilities specific to the semantic token requests scoped to the
+		 * workspace.
+		 *
+		 * @since 3.16.0
+		 */
+		 semanticTokens?: SemanticTokensWorkspaceClientCapabilities;
+
+		/**
+		 * Capabilities specific to the code lens requests scoped to the
+		 * workspace.
+		 *
+		 * @since 3.16.0
+		 */
+		codeLens?: CodeLensWorkspaceClientCapabilities;
+
+		/**
+		 * The client has support for file requests/notifications.
+		 *
+		 * @since 3.16.0
+		 */
+		fileOperations?: {
+			/**
+			 * Whether the client supports dynamic registration for file
+			 * requests/notifications.
+			 */
+			dynamicRegistration?: boolean;
+
+			/**
+			 * The client has support for sending didCreateFiles notifications.
+			 */
+			didCreate?: boolean;
+
+			/**
+			 * The client has support for sending willCreateFiles requests.
+			 */
+			willCreate?: boolean;
+
+			/**
+			 * The client has support for sending didRenameFiles notifications.
+			 */
+			didRename?: boolean;
+
+			/**
+			 * The client has support for sending willRenameFiles requests.
+			 */
+			willRename?: boolean;
+
+			/**
+			 * The client has support for sending didDeleteFiles notifications.
+			 */
+			didDelete?: boolean;
+
+			/**
+			 * The client has support for sending willDeleteFiles requests.
+			 */
+			willDelete?: boolean;
+		}
 	};
 
 	/**
@@ -1641,13 +2083,48 @@
 	 */
 	window?: {
 		/**
-		 * Whether client supports handling progress notifications.
-		 * If set, servers are allowed to report in `workDoneProgress` property
-		 * in the request specific server capabilities.
+		 * Whether client supports handling progress notifications. If set
+		 * servers are allowed to report in `workDoneProgress` property in the
+		 * request specific server capabilities.
 		 *
-		 * Since 3.15.0
+		 * @since 3.15.0
 		 */
 		workDoneProgress?: boolean;
+
+		/**
+		 * Capabilities specific to the showMessage request
+		 *
+		 * @since 3.16.0
+		 */
+		showMessage?: ShowMessageRequestClientCapabilities;
+
+		/**
+		 * Client capabilities for the show document request.
+		 *
+		 * @since 3.16.0
+		 */
+		showDocument?: ShowDocumentClientCapabilities;
+	}
+
+	/**
+	 * General client capabilities.
+	 *
+	 * @since 3.16.0
+	 */
+	general?: {
+		/**
+		 * Client capabilities specific to regular expressions.
+		 *
+		 * @since 3.16.0
+		 */
+		regularExpressions?: RegularExpressionsClientCapabilities;
+
+		/**
+		 * Client capabilities specific to the client's markdown parser.
+		 *
+		 * @since 3.16.0
+		 */
+		markdown?: MarkdownClientCapabilities;
 	}
 
 	/**
@@ -1693,12 +2170,13 @@
  */
 export namespace InitializeError {
 	/**
-	 * If the protocol version provided by the client can't be handled by
-	 * the server.
-	 * @deprecated This initialize error was replaced by client capabilities.
+	 * If the protocol version provided by the client can't be handled by the
+	 * server.
+	 *
+	 * @deprecated This initialize error got replaced by client capabilities.
 	 * There is no version handshake in version 3.0x
 	 */
-	export const unknownProtocolVersion: number = 1;
+	export const unknownProtocolVersion: 1 = 1;
 }
 ```
 
@@ -1721,12 +2199,12 @@
 ```typescript
 interface ServerCapabilities {
 	/**
-	 * Defines how text documents are synced.
-	 * Is either a detailed structure defining each notification
-	 * or for backwards compatibility, the TextDocumentSyncKind number.
-	 * If omitted, it defaults to `TextDocumentSyncKind.None`.
+	 * Defines how text documents are synced. Is either a detailed structure
+	 * defining each notification or for backwards compatibility the
+	 * TextDocumentSyncKind number. If omitted it defaults to
+	 * `TextDocumentSyncKind.None`.
 	 */
-	textDocumentSync?: TextDocumentSyncOptions | number;
+	textDocumentSync?: TextDocumentSyncOptions | TextDocumentSyncKind;
 
 	/**
 	 * The server provides completion support.
@@ -1788,15 +2266,14 @@
 	documentSymbolProvider?: boolean | DocumentSymbolOptions;
 
 	/**
-	 * The server provides code actions.
-	 * The `CodeActionOptions` return type is only valid if the client signals
-	 * code action literal support via the property
-	 * `textDocument.codeAction.codeActionLiteralSupport`.
+	 * The server provides code actions. The `CodeActionOptions` return type is
+	 * only valid if the client signals code action literal support via the
+	 * property `textDocument.codeAction.codeActionLiteralSupport`.
 	 */
 	codeActionProvider?: boolean | CodeActionOptions;
 
 	/**
-	 * The server provides CodeLens.
+	 * The server provides code lens.
 	 */
 	codeLensProvider?: CodeLensOptions;
 
@@ -1857,6 +2334,37 @@
 		| SelectionRangeRegistrationOptions;
 
 	/**
+	 * The server provides linked editing range support.
+	 *
+	 * @since 3.16.0
+	 */
+	linkedEditingRangeProvider?: boolean | LinkedEditingRangeOptions
+		| LinkedEditingRangeRegistrationOptions;
+
+	/**
+	 * The server provides call hierarchy support.
+	 *
+	 * @since 3.16.0
+	 */
+	callHierarchyProvider?: boolean | CallHierarchyOptions
+		| CallHierarchyRegistrationOptions;
+
+	/**
+	 * The server provides semantic tokens support.
+	 *
+	 * @since 3.16.0
+	 */
+	semanticTokensProvider?: SemanticTokensOptions
+		| SemanticTokensRegistrationOptions;
+
+	/**
+	 * Whether server provides moniker support.
+	 *
+	 * @since 3.16.0
+	 */
+    monikerProvider?: boolean | MonikerOptions | MonikerRegistrationOptions;
+
+	/**
 	 * The server provides workspace symbol support.
 	 */
 	workspaceSymbolProvider?: boolean | WorkspaceSymbolOptions;
@@ -1871,6 +2379,47 @@
 		 * @since 3.6.0
 		 */
 		workspaceFolders?: WorkspaceFoldersServerCapabilities;
+
+		/**
+		 * The server is interested in file notifications/requests.
+		 *
+		 * @since 3.16.0
+		 */
+		fileOperations?: {
+			/**
+			 * The server is interested in receiving didCreateFiles
+			 * notifications.
+			 */
+			didCreate?: FileOperationRegistrationOptions;
+
+			/**
+			 * The server is interested in receiving willCreateFiles requests.
+			 */
+			willCreate?: FileOperationRegistrationOptions;
+
+			/**
+			 * The server is interested in receiving didRenameFiles
+			 * notifications.
+			 */
+			didRename?: FileOperationRegistrationOptions;
+
+			/**
+			 * The server is interested in receiving willRenameFiles requests.
+			 */
+			willRename?: FileOperationRegistrationOptions;
+
+			/**
+			 * The server is interested in receiving didDeleteFiles file
+			 * notifications.
+			 */
+			didDelete?: FileOperationRegistrationOptions;
+
+			/**
+			 * The server is interested in receiving willDeleteFiles file
+			 * requests.
+			 */
+			willDelete?: FileOperationRegistrationOptions;
+		}
 	}
 
 	/**
@@ -1914,6 +2463,51 @@
 * method: 'exit'
 * params: void
 
+#### <a href="#logTrace" name="logTrace" class="anchor">LogTrace Notification (:arrow_left:)</a>
+
+A notification to log the trace of the server's execution.
+The amount and content of these notifications depends on the current `trace` configuration.
+If `trace` is `'off'`, the server should not send any `logTrace` notification.
+If `trace` is `'message'`, the server should not add the `'verbose'` field in the `LogTraceParams`.
+
+`$/logTrace` should be used for systematic trace reporting. For single debugging messages, the server should send [`window/logMessage`](#window_logMessage) notifications.
+
+
+_Notification_:
+* method: '$/logTrace'
+* params: `LogTraceParams` defined as follows:
+
+```typescript
+interface LogTraceParams {
+	/**
+	 * The message to be logged.
+	 */
+	message: string;
+	/**
+	 * Additional information that can be computed if the `trace` configuration
+	 * is set to `'verbose'`
+	 */
+	verbose?: string;
+}
+```
+
+#### <a href="#setTrace" name="setTrace" class="anchor">SetTrace Notification (:arrow_right:)</a>
+
+A notification that should be used by the client to modify the trace setting of the server.
+
+_Notification_:
+* method: '$/setTrace'
+* params: `SetTraceParams` defined as follows:
+
+```typescript
+interface SetTraceParams {
+	/**
+	 * The new value that should be assigned to the trace setting.
+	 */
+	value: TraceValue;
+}
+```
+
 #### <a href="#window_showMessage" name="window_showMessage" class="anchor">ShowMessage Notification (:arrow_left:)</a>
 
 The show message notification is sent from a server to a client to ask the client to display a particular message in the user interface.
@@ -1927,7 +2521,7 @@
 	/**
 	 * The message type. See {@link MessageType}.
 	 */
-	type: number;
+	type: MessageType;
 
 	/**
 	 * The actual message.
@@ -1957,12 +2551,37 @@
 	 */
 	export const Log = 4;
 }
+
+export type MessageType = 1 | 2 | 3 | 4;
 ```
 
 #### <a href="#window_showMessageRequest" name="window_showMessageRequest" class="anchor">ShowMessage Request (:arrow_right_hook:)</a>
 
 The show message request is sent from a server to a client to ask the client to display a particular message in the user interface. In addition to the show message notification the request allows to pass actions and to wait for an answer from the client.
 
+_Client Capability_:
+* property path (optional): `window.showMessage`
+* property type: `ShowMessageRequestClientCapabilities` defined as follows:
+
+```typescript
+/**
+ * Show message request client capabilities
+ */
+export interface ShowMessageRequestClientCapabilities {
+	/**
+	 * Capabilities specific to the `MessageActionItem` type.
+	 */
+	messageActionItem?: {
+		/**
+		 * Whether the client supports additional attributes which
+		 * are preserved and sent back to the server in the
+		 * request's response.
+		 */
+		additionalPropertiesSupport?: boolean;
+	}
+}
+```
+
 _Request_:
 * method: 'window/showMessageRequest'
 * params: `ShowMessageRequestParams` defined as follows:
@@ -1976,7 +2595,7 @@
 	/**
 	 * The message type. See {@link MessageType}
 	 */
-	type: number;
+	type: MessageType;
 
 	/**
 	 * The actual message
@@ -2001,6 +2620,91 @@
 }
 ```
 
+#### <a href="#window_showDocument" name="window_showDocument" class="anchor">Show Document Request (:arrow_right_hook:)</a>
+
+> New in version 3.16.0
+
+The show document request is sent from a server to a client to ask the client to display a particular document in the user interface.
+
+_Client Capability_:
+* property path (optional): `window.showDocument`
+* property type: `ShowDocumentClientCapabilities` defined as follows:
+
+```typescript
+/**
+ * Client capabilities for the show document request.
+ *
+ * @since 3.16.0
+ */
+export interface ShowDocumentClientCapabilities {
+	/**
+	 * The client has support for the show document
+	 * request.
+	 */
+	support: boolean;
+}
+```
+
+_Request_:
+* method: 'window/showDocument'
+* params: `ShowDocumentParams` defined as follows:
+
+```typescript
+/**
+ * Params to show a document.
+ *
+ * @since 3.16.0
+ */
+export interface ShowDocumentParams {
+	/**
+	 * The document uri to show.
+	 */
+	uri: URI;
+
+	/**
+	 * Indicates to show the resource in an external program.
+	 * To show for example `https://code.visualstudio.com/`
+	 * in the default WEB browser set `external` to `true`.
+	 */
+	external?: boolean;
+
+	/**
+	 * An optional property to indicate whether the editor
+	 * showing the document should take focus or not.
+	 * Clients might ignore this property if an external
+	 * program is started.
+	 */
+	takeFocus?: boolean;
+
+	/**
+	 * An optional selection range if the document is a text
+	 * document. Clients might ignore the property if an
+	 * external program is started or the file is not a text
+	 * file.
+	 */
+	selection?: Range;
+}
+```
+
+_Response_:
+
+* result: `ShowDocumentResult` defined as follows:
+
+```typescript
+/**
+ * The result of an show document request.
+ *
+ * @since 3.16.0
+ */
+export interface ShowDocumentResult {
+	/**
+	 * A boolean indicating if the show was successful.
+	 */
+	success: boolean;
+}
+```
+* error: code and message set in case an exception happens during showing a document.
+
 #### <a href="#window_logMessage" name="window_logMessage" class="anchor">LogMessage Notification (:arrow_left:)</a>
 
 The log message notification is sent from the server to the client to ask the client to log a particular message.
@@ -2014,7 +2718,7 @@
 	/**
 	 * The message type. See {@link MessageType}
 	 */
-	type: number;
+	type: MessageType;
 
 	/**
 	 * The actual message
@@ -2048,7 +2752,7 @@
 
 #### <a href="#window_workDoneProgress_cancel" name="window_workDoneProgress_cancel" class="anchor"> Canceling a Work Done Progress (:arrow_right:)</a>
 
-The `window/workDoneProgress/cancel` notification is sent from the client to the server to cancel a progress initiated on the server side using the `window/workDoneProgress/create`.
+The `window/workDoneProgress/cancel` notification is sent from the client to the server to cancel a progress initiated on the server side using the `window/workDoneProgress/create`. The progress need not be marked as `cancellable` to be cancelled and a client may cancel a progress for any number of reasons: in case of error, reloading a workspace etc.
 
 _Notification_:
 
@@ -2066,11 +2770,11 @@
 
 #### <a href="#telemetry_event" name="telemetry_event" class="anchor">Telemetry Notification (:arrow_left:)</a>
 
-The telemetry notification is sent from the server to the client to ask the client to log a telemetry event.
+The telemetry notification is sent from the server to the client to ask the client to log a telemetry event. The protocol doesn't specify the payload since no interpretation of the data happens in the protocol. Most clients even don't handle the event directly but forward them to the extensions owing the corresponding server issuing the event.
 
 _Notification_:
 * method: 'telemetry/event'
-* params: 'any'
+* params: 'object' \| 'number' \| 'boolean' \| 'string';
 
 #### <a href="#client_registerCapability" name="client_registerCapability" class="anchor">Register Capability (:arrow_right_hook:)</a>
 
@@ -2363,13 +3067,13 @@
 
 #### <a href="#workspace_didChangeWatchedFiles" name="workspace_didChangeWatchedFiles" class="anchor">DidChangeWatchedFiles Notification (:arrow_right:)</a>
 
-The watched files notification is sent from the client to the server when the client detects changes to files watched by the language client. It is recommended that servers register for these file events using the registration mechanism. In former implementations clients pushed file events without the server actively asking for it.
+The watched files notification is sent from the client to the server when the client detects changes to files and folders watched by the language client (note although the name suggest that only file events are sent it is about file system events which include folders as well). It is recommended that servers register for these file system events using the registration mechanism. In former implementations clients pushed file events without the server actively asking for it.
 
-Servers are allowed to run their own file watching mechanism and not rely on clients to provide file events. However this is not recommended due to the following reasons:
+Servers are allowed to run their own file system watching mechanism and not rely on clients to provide file system events. However this is not recommended due to the following reasons:
 
-- to our experience getting file watching on disk right is challenging, especially if it needs to be supported across multiple OSes.
-- file watching is not for free especially if the implementation uses some sort of polling and keeps a file tree in memory to compare time stamps (as for example some node modules do)
-- a client usually starts more than one server. If every server runs its own file watching it can become a CPU or memory problem.
+- to our experience getting file system watching on disk right is challenging, especially if it needs to be supported across multiple OSes.
+- file system watching is not for free especially if the implementation uses some sort of polling and keeps a file system tree in memory to compare time stamps (as for example some node modules do)
+- a client usually starts more than one server. If every server runs its own file system watching it can become a CPU or memory problem.
 - in general there are more server than client implementations. So this problem is better solved on the client side.
 
 _Client Capability_:
@@ -2412,8 +3116,8 @@
 	 * - `[]` to declare a range of characters to match in a path segment
 	 *   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
 	 * - `[!...]` to negate a range of characters to match in a path segment
-	 *   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`,
-	 *    but not `example.0`)
+	 *   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not
+	 *   `example.0`)
 	 */
 	globPattern: string;
 
@@ -2422,7 +3126,7 @@
 	 * to WatchKind.Create | WatchKind.Change | WatchKind.Delete
 	 * which is 7.
 	 */
-	kind?: number;
+	kind?: uinteger;
 }
 
 export namespace WatchKind {
@@ -2470,7 +3174,7 @@
 	/**
 	 * The change type.
 	 */
-	type: number;
+	type: uinteger;
 }
 
 /**
@@ -2508,8 +3212,8 @@
 	dynamicRegistration?: boolean;
 
 	/**
-	 * Specific capabilities for the `SymbolKind` in the
-	 * `workspace/symbol` request.
+	 * Specific capabilities for the `SymbolKind` in the `workspace/symbol`
+	 * request.
 	 */
 	symbolKind?: {
 		/**
@@ -2524,6 +3228,19 @@
 		 */
 		valueSet?: SymbolKind[];
 	}
+
+	/**
+	 * The client supports tags on `SymbolInformation`.
+	 * Clients supporting tags have to handle unknown tags gracefully.
+	 *
+	 * @since 3.16.0
+	 */
+	tagSupport?: {
+		/**
+		 * The tags supported by the client.
+		 */
+		valueSet: SymbolTag[]
+	}
 }
 ```
 
@@ -2551,8 +3268,8 @@
 /**
  * The parameters of a Workspace Symbol Request.
  */
-interface WorkspaceSymbolParams
-	extends WorkDoneProgressParams, PartialResultParams {
+interface WorkspaceSymbolParams extends WorkDoneProgressParams,
+	PartialResultParams {
 	/**
 	 * A query string to filter symbols by. Clients may send an empty
 	 * string here to request all symbols.
@@ -2568,9 +3285,7 @@
 
 #### <a href="#workspace_executeCommand" name="workspace_executeCommand" class="anchor">Execute a command (:leftwards_arrow_with_hook:)</a>
 
-The `workspace/executeCommand` request is sent from the client to the server to trigger command execution on the server. In most cases
-the server creates a `WorkspaceEdit` structure and applies the changes to the workspace using the request `workspace/applyEdit` which is
-sent from the server to the client.
+The `workspace/executeCommand` request is sent from the client to the server to trigger command execution on the server. In most cases the server creates a `WorkspaceEdit` structure and applies the changes to the workspace using the request `workspace/applyEdit` which is sent from the server to the client.
 
 _Client Capability_:
 * property path (optional): `workspace.executeCommand`
@@ -2674,15 +3389,351 @@
 
 	/**
 	 * An optional textual description for why the edit was not applied.
-	 * This may be used may be used by the server for diagnostic
-	 * logging or to provide a suitable error for a request that
-	 * triggered the edit.
+	 * This may be used by the server for diagnostic logging or to provide
+	 * a suitable error for a request that triggered the edit.
 	 */
 	failureReason?: string;
+
+	/**
+	 * Depending on the client's failure handling strategy `failedChange`
+	 * might contain the index of the change that failed. This property is
+	 * only available if the client signals a `failureHandlingStrategy`
+	 * in its client capabilities.
+	 */
+	failedChange?: uinteger;
 }
 ```
 * error: code and message set in case an exception happens during the request.
 
+#### <a href="#workspace_willCreateFiles" name="workspace_willCreateFiles" class="anchor">WillCreateFiles Request (:leftwards_arrow_with_hook:)</a>
+
+The will create files request is sent from the client to the server before files are actually created as long as the creation is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are created. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep creates fast and reliable.
+
+_Client Capability_:
+* property name (optional): `workspace.fileOperations.willCreate`
+* property type: `boolean`
+
+The capability indicates that the client supports sending `workspace/willCreateFiles` requests.
+
+_Server Capability_:
+* property name (optional): `workspace.fileOperations.willCreate`
+* property type: `FileOperationRegistrationOptions` where `FileOperationRegistrationOptions` is defined as follows:
+
+```typescript
+/**
+ * The options to register for file operations.
+ *
+ * @since 3.16.0
+ */
+interface FileOperationRegistrationOptions {
+	/**
+	 * The actual filters.
+	 */
+	filters: FileOperationFilter[];
+}
+
+/**
+ * A pattern kind describing if a glob pattern matches a file a folder or
+ * both.
+ *
+ * @since 3.16.0
+ */
+export namespace FileOperationPatternKind {
+	/**
+	 * The pattern matches a file only.
+	 */
+	export const file: 'file' = 'file';
+
+	/**
+	 * The pattern matches a folder only.
+	 */
+	export const folder: 'folder' = 'folder';
+}
+
+export type FileOperationPatternKind = 'file' | 'folder';
+
+/**
+ * Matching options for the file operation pattern.
+ *
+ * @since 3.16.0
+ */
+export interface FileOperationPatternOptions {
+
+	/**
+	 * The pattern should be matched ignoring casing.
+	 */
+	ignoreCase?: boolean;
+}
+
+/**
+ * A pattern to describe in which file operation requests or notifications
+ * the server is interested in.
+ *
+ * @since 3.16.0
+ */
+interface FileOperationPattern {
+	/**
+	 * The glob pattern to match. Glob patterns can have the following syntax:
+	 * - `*` to match one or more characters in a path segment
+	 * - `?` to match on one character in a path segment
+	 * - `**` to match any number of path segments, including none
+	 * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
+	 *   and JavaScript files)
+	 * - `[]` to declare a range of characters to match in a path segment
+	 *   (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
+	 * - `[!...]` to negate a range of characters to match in a path segment
+	 *   (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
+	 *   not `example.0`)
+	 */
+	glob: string;
+
+	/**
+	 * Whether to match files or folders with this pattern.
+	 *
+	 * Matches both if undefined.
+	 */
+	matches?: FileOperationPatternKind;
+
+	/**
+	 * Additional options used during matching.
+	 */
+	options?: FileOperationPatternOptions;
+}
+
+/**
+ * A filter to describe in which file operation requests or notifications
+ * the server is interested in.
+ *
+ * @since 3.16.0
+ */
+export interface FileOperationFilter {
+
+	/**
+	 * A Uri like `file` or `untitled`.
+	 */
+	scheme?: string;
+
+	/**
+	 * The actual file operation pattern.
+	 */
+	pattern: FileOperationPattern;
+}
+```
+
+The capability indicates that the server is interested in receiving `workspace/willCreateFiles` requests.
+
+_Registration Options_: none
+
+_Request_:
+* method: 'workspace/willCreateFiles'
+* params: `CreateFilesParams` defined as follows:
+
+```typescript
+/**
+ * The parameters sent in notifications/requests for user-initiated creation
+ * of files.
+ *
+ * @since 3.16.0
+ */
+export interface CreateFilesParams {
+
+	/**
+	 * An array of all files/folders created in this operation.
+	 */
+	files: FileCreate[];
+}
+/**
+ * Represents information on a file/folder create.
+ *
+ * @since 3.16.0
+ */
+export interface FileCreate {
+
+	/**
+	 * A file:// URI for the location of the file/folder being created.
+	 */
+	uri: string;
+}
+```
+
+_Response_:
+* result:`WorkspaceEdit` \| `null`
+* error: code and message set in case an exception happens during the `willCreateFiles` request.
+
+#### <a href="#workspace_didCreateFiles" name="workspace_didCreateFiles" class="anchor">DidCreateFiles Notification (:arrow_right:)</a>
+
+The did create files notification is sent from the client to the server when files were created from within the client.
+
+_Client Capability_:
+* property name (optional): `workspace.fileOperations.didCreate`
+* property type: `boolean`
+
+The capability indicates that the client supports sending `workspace/didCreateFiles` notifications.
+
+_Server Capability_:
+* property name (optional): `workspace.fileOperations.didCreate`
+* property type: `FileOperationRegistrationOptions`
+
+The capability indicates that the server is interested in receiving `workspace/didCreateFiles` notifications.
+
+_Notification_:
+* method: 'workspace/didCreateFiles'
+* params: `CreateFilesParams`
+
+#### <a href="#workspace_willRenameFiles" name="workspace_willRenameFiles" class="anchor">WillRenameFiles Request (:leftwards_arrow_with_hook:)</a>
+
+The will rename files request is sent from the client to the server before files are actually renamed as long as the rename is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are renamed. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep renames fast and reliable.
+
+_Client Capability_:
+* property name (optional): `workspace.fileOperations.willRename`
+* property type: `boolean`
+
+The capability indicates that the client supports sending `workspace/willRenameFiles` requests.
+
+_Server Capability_:
+* property name (optional): `workspace.fileOperations.willRename`
+* property type: `FileOperationRegistrationOptions`
+
+The capability indicates that the server is interested in receiving `workspace/willRenameFiles` requests.
+
+_Registration Options_: none
+
+_Request_:
+* method: 'workspace/willRenameFiles'
+* params: `RenameFilesParams` defined as follows:
+
+```typescript
+/**
+ * The parameters sent in notifications/requests for user-initiated renames
+ * of files.
+ *
+ * @since 3.16.0
+ */
+export interface RenameFilesParams {
+
+	/**
+	 * An array of all files/folders renamed in this operation. When a folder
+	 * is renamed, only the folder will be included, and not its children.
+	 */
+	files: FileRename[];
+}
+/**
+ * Represents information on a file/folder rename.
+ *
+ * @since 3.16.0
+ */
+export interface FileRename {
+
+	/**
+	 * A file:// URI for the original location of the file/folder being renamed.
+	 */
+	oldUri: string;
+
+	/**
+	 * A file:// URI for the new location of the file/folder being renamed.
+	 */
+	newUri: string;
+}
+```
+
+_Response_:
+* result:`WorkspaceEdit` \| `null`
+* error: code and message set in case an exception happens during the `willRenameFiles` request.
+
+#### <a href="#workspace_didRenameFiles" name="workspace_didRenameFiles" class="anchor">DidRenameFiles Notification (:arrow_right:)</a>
+
+The did rename files notification is sent from the client to the server when files were renamed from within the client.
+
+_Client Capability_:
+* property name (optional): `workspace.fileOperations.didRename`
+* property type: `boolean`
+
+The capability indicates that the client supports sending `workspace/didRenameFiles` notifications.
+
+_Server Capability_:
+* property name (optional): `workspace.fileOperations.didRename`
+* property type: `FileOperationRegistrationOptions`
+
+The capability indicates that the server is interested in receiving `workspace/didRenameFiles` notifications.
+
+_Notification_:
+* method: 'workspace/didRenameFiles'
+* params: `RenameFilesParams`
+
+#### <a href="#workspace_willDeleteFiles" name="workspace_willDeleteFiles" class="anchor">WillDeleteFiles Request (:leftwards_arrow_with_hook:)</a>
+
+The will delete files request is sent from the client to the server before files are actually deleted as long as the deletion is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are deleted. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep deletes fast and reliable.
+
+_Client Capability_:
+* property name (optional): `workspace.fileOperations.willDelete`
+* property type: `boolean`
+
+The capability indicates that the client supports sending `workspace/willDeleteFiles` requests.
+
+_Server Capability_:
+* property name (optional): `workspace.fileOperations.willDelete`
+* property type: `FileOperationRegistrationOptions`
+
+The capability indicates that the server is interested in receiving `workspace/willDeleteFiles` requests.
+
+_Registration Options_: none
+
+_Request_:
+* method: 'workspace/willDeleteFiles'
+* params: `DeleteFilesParams` defined as follows:
+
+```typescript
+/**
+ * The parameters sent in notifications/requests for user-initiated deletes
+ * of files.
+ *
+ * @since 3.16.0
+ */
+export interface DeleteFilesParams {
+
+	/**
+	 * An array of all files/folders deleted in this operation.
+	 */
+	files: FileDelete[];
+}
+/**
+ * Represents information on a file/folder delete.
+ *
+ * @since 3.16.0
+ */
+export interface FileDelete {
+
+	/**
+	 * A file:// URI for the location of the file/folder being deleted.
+	 */
+	uri: string;
+}
+```
+
+_Response_:
+* result:`WorkspaceEdit` \| `null`
+* error: code and message set in case an exception happens during the `willDeleteFiles` request.
+
+#### <a href="#workspace_didDeleteFiles" name="workspace_didDeleteFiles" class="anchor">DidDeleteFiles Notification (:arrow_right:)</a>
+
+The did delete files notification is sent from the client to the server when files were deleted from within the client.
+
+_Client Capability_:
+* property name (optional): `workspace.fileOperations.didDelete`
+* property type: `boolean`
+
+The capability indicates that the client supports sending `workspace/didDeleteFiles` notifications.
+
+_Server Capability_:
+* property name (optional): `workspace.fileOperations.didDelete`
+* property type: `FileOperationRegistrationOptions`
+
+The capability indicates that the server is interested in receiving `workspace/didDeleteFiles` notifications.
+
+_Notification_:
+* method: 'workspace/didDeleteFiles'
+* params: `DeleteFilesParams`
+
 #### <a href="#textDocument_synchronization" name="textDocument_synchronization" class="anchor">Text Document Synchronization</a>
 
 Client support for `textDocument/didOpen`, `textDocument/didChange` and `textDocument/didClose` notifications is mandatory in the protocol and clients can not opt out supporting them. This includes both full and incremental synchronization in the `textDocument/didChange` notification. In addition a server must either implement all three of them or none. Their capabilities are therefore controlled via a combined client and server capability.
@@ -2699,8 +3750,8 @@
 
 ```typescript
 /**
- * Defines how the host (editor) should sync document changes
- * to the language server.
+ * Defines how the host (editor) should sync document changes to the language
+ * server.
  */
 export namespace TextDocumentSyncKind {
 	/**
@@ -2724,16 +3775,16 @@
 
 export interface TextDocumentSyncOptions {
 	/**
-	 * Open and close notifications are sent to the server.
-	 * If omitted open close notification should not be sent.
+	 * Open and close notifications are sent to the server. If omitted open
+	 * close notification should not be sent.
 	 */
 	openClose?: boolean;
 
 	/**
-	 * Change notifications are sent to the server.
-	 * See TextDocumentSyncKind.None, TextDocumentSyncKind.Full,
-	 * and TextDocumentSyncKind.Incremental.
-	 * If omitted, it defaults to TextDocumentSyncKind.None.
+	 * Change notifications are sent to the server. See
+	 * TextDocumentSyncKind.None, TextDocumentSyncKind.Full and
+	 * TextDocumentSyncKind.Incremental. If omitted it defaults to
+	 * TextDocumentSyncKind.None.
 	 */
 	change?: TextDocumentSyncKind;
 }
@@ -2805,28 +3856,26 @@
 	textDocument: VersionedTextDocumentIdentifier;
 
 	/**
-	 * The actual content changes.
-	 * The content changes describe single state changes to the document.
-	 * If there are two content changes c1 (at array index 0) and
-	 * c2 (at array index 1) for a document in state S, then c1 moves the
-	 * document from S to S' and c2 from S' to S''.
-	 * So c1 is computed on the state S and c2 is computed on the state S'.
+	 * The actual content changes. The content changes describe single state
+	 * changes to the document. So if there are two content changes c1 (at
+	 * array index 0) and c2 (at array index 1) for a document in state S then
+	 * c1 moves the document from S to S' and c2 from S' to S''. So c1 is
+	 * computed on the state S and c2 is computed on the state S'.
 	 *
-	 * To mirror the content of a document using change events,
-	 * use the following approach:
+	 * To mirror the content of a document using change events use the following
+	 * approach:
 	 * - start with the same initial content
-	 * - apply the 'textDocument/didChange' notifications
-	 *     in the order you receive them.
-	 * - apply the `TextDocumentContentChangeEvent`s
-	 *     in a single notification in the order you receive them.
+	 * - apply the 'textDocument/didChange' notifications in the order you
+	 *   receive them.
+	 * - apply the `TextDocumentContentChangeEvent`s in a single notification
+	 *   in the order you receive them.
 	 */
 	contentChanges: TextDocumentContentChangeEvent[];
 }
 
 /**
- * An event describing a change to a text document.
- * If range and rangeLength are omitted, the new text is considered to be
- * the full content of the document.
+ * An event describing a change to a text document. If range and rangeLength are
+ * omitted the new text is considered to be the full content of the document.
  */
 export type TextDocumentContentChangeEvent = {
 	/**
@@ -2839,7 +3888,7 @@
 	 *
 	 * @deprecated use range instead.
 	 */
-	rangeLength?: number;
+	rangeLength?: uinteger;
 
 	/**
 	 * The new text for the provided range.
@@ -2888,7 +3937,7 @@
 	/**
 	 * The 'TextDocumentSaveReason'.
 	 */
-	reason: number;
+	reason: TextDocumentSaveReason;
 }
 
 /**
@@ -2897,8 +3946,8 @@
 export namespace TextDocumentSaveReason {
 
 	/**
-	 * Manually triggered, for example, by the user pressing save,
-	 * by starting debugging, or by an API call.
+	 * Manually triggered, e.g. by the user pressing save, by starting
+	 * debugging, or by an API call.
 	 */
 	export const Manual = 1;
 
@@ -2912,6 +3961,8 @@
 	 */
 	export const FocusOut = 3;
 }
+
+export type TextDocumentSaveReason = 1 | 2 | 3;
 ```
 
 #### <a href="#textDocument_willSaveWaitUntil" name="textDocument_willSaveWaitUntil" class="anchor">WillSaveWaitUntilTextDocument Request (:leftwards_arrow_with_hook:)</a>
@@ -3048,8 +4099,8 @@
 }
 
 /**
- * Defines how the host (editor) should sync document changes
- * to the language server.
+ * Defines how the host (editor) should sync document changes to the language
+ * server.
  */
 export namespace TextDocumentSyncKind {
 	/**
@@ -3071,32 +4122,34 @@
 	export const Incremental = 2;
 }
 
+export type TextDocumentSyncKind = 0 | 1 | 2;
+
 export interface TextDocumentSyncOptions {
 	/**
-	 * Open and close notifications are sent to the server.
-	 * If omitted, open close notification should not be sent.
+	 * Open and close notifications are sent to the server. If omitted open
+	 * close notification should not be sent.
 	 */
 	openClose?: boolean;
 	/**
-	 * Change notifications are sent to the server.
-	 * See TextDocumentSyncKind.None, TextDocumentSyncKind.Full,
-	 * and TextDocumentSyncKind.Incremental.
-	 * If omitted, it defaults to TextDocumentSyncKind.None.
+	 * Change notifications are sent to the server. See
+	 * TextDocumentSyncKind.None, TextDocumentSyncKind.Full and
+	 * TextDocumentSyncKind.Incremental. If omitted it defaults to
+	 * TextDocumentSyncKind.None.
 	 */
-	change?: number;
+	change?: TextDocumentSyncKind;
 	/**
-	 * If present will save notifications are sent to the server.
-	 * If omitted, the notification should not be sent.
+	 * If present will save notifications are sent to the server. If omitted
+	 * the notification should not be sent.
 	 */
 	willSave?: boolean;
 	/**
-	 * If present will save wait until requests are sent to the server.
-	 * If omitted, the request should not be sent.
+	 * If present will save wait until requests are sent to the server. If
+	 * omitted the request should not be sent.
 	 */
 	willSaveWaitUntil?: boolean;
 	/**
-	 * If present save notifications are sent to the server.
-	 * If omitted, the notification should not be sent.
+	 * If present save notifications are sent to the server. If omitted the
+	 * notification should not be sent.
 	 */
 	save?: boolean | SaveOptions;
 }
@@ -3108,7 +4161,7 @@
 
 Diagnostics are "owned" by the server so it is the server's responsibility to clear them if necessary. The following rule is used for VS Code servers that generate diagnostics:
 
-* if a language is single file only (for example HTML) then diagnostics are cleared by the server when the file is closed.
+* if a language is single file only (for example HTML) then diagnostics are cleared by the server when the file is closed. Please note that open / close events don't necessarily reflect what the user sees in the user interface. These events are ownership events. So with the current version of the specification it is possible that problems are not cleared although the file is not visible in the user interface since the client has not closed the file yet.
 * if a language has a project system (for example C#) diagnostics are not cleared when a file closes. When a project is opened all diagnostics for all files are recomputed (or read from a cache).
 
 When a file changes it is the server's responsibility to re-compute diagnostics and push them to the client. If the computed set is empty it has to push the empty array to clear former diagnostics. Newly pushed diagnostics always replace previously pushed diagnostics. There is no merging that happens on the client side.
@@ -3146,6 +4199,22 @@
 	 * @since 3.15.0
 	 */
 	versionSupport?: boolean;
+
+	/**
+	 * Client supports a codeDescription property
+	 *
+	 * @since 3.16.0
+	 */
+	codeDescriptionSupport?: boolean;
+
+	/**
+	 * Whether code action supports the `data` property which is
+	 * preserved between a `textDocument/publishDiagnostics` and
+	 * `textDocument/codeAction` request.
+	 *
+	 * @since 3.16.0
+	 */
+	dataSupport?: boolean;
 }
 ```
 
@@ -3161,11 +4230,12 @@
 	uri: DocumentUri;
 
 	/**
-	 * The version number of the document the diagnostics are published for.
-	 * Optional.
+	 * Optional the version number of the document the diagnostics are published
+	 * for.
+	 *
 	 * @since 3.15.0
 	 */
-	version?: number;
+	version?: uinteger;
 
 	/**
 	 * An array of diagnostic information items.
@@ -3176,7 +4246,8 @@
 
 #### <a href="#textDocument_completion" name="textDocument_completion" class="anchor">Completion Request (:leftwards_arrow_with_hook:)</a>
 
-The Completion request is sent from the client to the server to compute completion items at a given cursor position. Completion items are presented in the [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense. If computing full completion items is expensive, servers can additionally provide a handler for the completion item resolve request ('completionItem/resolve'). This request is sent when a completion item is selected in the user interface. A typical use case is for example: the 'textDocument/completion' request doesn't fill in the `documentation` property for returned completion items since it is expensive to compute. When the item is selected in the user interface then a 'completionItem/resolve' request is sent with the selected completion item as a parameter. The returned completion item should have the documentation property filled in. The request can only delay the computation of the `detail` and `documentation` properties. Other properties like `sortText`, `filterText`, `insertText`, `textEdit` and `additionalTextEdits` must be provided in the `textDocument/completion` response and must not be changed during resolve.
+The Completion request is sent from the client to the server to compute completion items at a given cursor position. Completion items are presented in the [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense) user interface. If computing full completion items is expensive, servers can additionally provide a handler for the completion item resolve request ('completionItem/resolve'). This request is sent when a completion item is selected in the user interface. A typical use case is for example: the 'textDocument/completion' request doesn't fill in the `documentation` property for returned completion items since it is expensive to compute. When the item is selected in the user interface then a 'completionItem/resolve' request is sent with the selected completion item as a parameter. The returned completion item should have the documentation property filled in. By default the request can only delay the computation of the `detail` and `documentation` properties. Since 3.16.0 the client
+can signal that it can resolve more properties lazily. This is done using the `completionItem#resolveSupport` client capability which lists all properties that can be filled in during a 'completionItem/resolve' request. All other properties (usually `sortText`, `filterText`, `insertText` and `textEdit`) must be provided in the `textDocument/completion` response and must not be changed during resolve.
 
 _Client Capability_:
 * property name (optional): `textDocument.completion`
@@ -3199,9 +4270,8 @@
 		 *
 		 * A snippet can define tab stops and placeholders with `$1`, `$2`
 		 * and `${3:foo}`. `$0` defines the final tab stop, it defaults to
-		 * the end of the snippet.
-		 * Placeholders with equal identifiers are linked, so that typing in
-		 * one will update others as well.
+		 * the end of the snippet. Placeholders with equal identifiers are
+		 * linked, that is typing in one will update others too.
 		 */
 		snippetSupport?: boolean;
 
@@ -3227,10 +4297,10 @@
 		preselectSupport?: boolean;
 
 		/**
-		 * Client supports the tag property on a completion item.
-		 * Clients supporting tags have to handle unknown tags gracefully.
-		 * Clients especially need to preserve unknown tags when sending
-		 * a completion item back to the server in a resolve call.
+		 * Client supports the tag property on a completion item. Clients
+		 * supporting tags have to handle unknown tags gracefully. Clients
+		 * especially need to preserve unknown tags when sending a completion
+		 * item back to the server in a resolve call.
 		 *
 		 * @since 3.15.0
 		 */
@@ -3240,6 +4310,39 @@
 			 */
 			valueSet: CompletionItemTag[]
 		}
+
+		/**
+		 * Client supports insert replace edit to control different behavior if
+		 * a completion item is inserted in the text or should replace text.
+		 *
+		 * @since 3.16.0
+		 */
+		insertReplaceSupport?: boolean;
+
+		/**
+		 * Indicates which properties a client can resolve lazily on a
+		 * completion item. Before version 3.16.0 only the predefined properties
+		 * `documentation` and `details` could be resolved lazily.
+		 *
+		 * @since 3.16.0
+		 */
+		resolveSupport?: {
+			/**
+			 * The properties that a client can resolve lazily.
+			 */
+			properties: string[];
+		};
+
+		/**
+		 * The client supports the `insertTextMode` property on
+		 * a completion item to override the whitespace handling mode
+		 * as defined by the client (see `insertTextMode`).
+		 *
+		 * @since 3.16.0
+		 */
+		insertTextModeSupport?: {
+			valueSet: InsertTextMode[];
+		}
 	};
 
 	completionItemKind?: {
@@ -3275,27 +4378,26 @@
 export interface CompletionOptions extends WorkDoneProgressOptions {
 	/**
 	 * Most tools trigger completion request automatically without explicitly
-	 * requesting it using a keyboard shortcut (for example Ctrl+Space).
-	 * Typically they do so when the user starts to type an identifier.
-	 * For example, if the user types `c` in a JavaScript file, code complete
-	 * will automatically display `console` along with others as a
-	 * completion item.
-	 * Characters that make up identifiers don't need to be listed here.
+	 * requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they
+	 * do so when the user starts to type an identifier. For example if the user
+	 * types `c` in a JavaScript file code complete will automatically pop up
+	 * present `console` besides others as a completion item. Characters that
+	 * make up identifiers don't need to be listed here.
 	 *
-	 * If code complete should automatically be triggered on characters
-	 * not being valid inside an identifier (for example `.` in JavaScript),
-	 * list them in `triggerCharacters`.
+	 * If code complete should automatically be trigger on characters not being
+	 * valid inside an identifier (for example `.` in JavaScript) list them in
+	 * `triggerCharacters`.
 	 */
 	triggerCharacters?: string[];
 
 	/**
-	 * The list of all possible characters that commit a completion.
-	 * This field can be used if clients don't support individual commit
-	 * characters per completion item. See `ClientCapabilities.`
-	 * `textDocument.completion.completionItem.commitCharactersSupport`.
+	 * The list of all possible characters that commit a completion. This field
+	 * can be used if clients don't support individual commit characters per
+	 * completion item. See client capability
+	 * `completion.completionItem.commitCharactersSupport`.
 	 *
-	 * If a server provides both `allCommitCharacters` and commit characters
-	 * on an individual completion item, the ones on the completion item win.
+	 * If a server provides both `allCommitCharacters` and commit characters on
+	 * an individual completion item the ones on the completion item win.
 	 *
 	 * @since 3.2.0
 	 */
@@ -3321,13 +4423,12 @@
 * params: `CompletionParams` defined as follows:
 
 ```typescript
-export interface CompletionParams
-	extends TextDocumentPositionParams, WorkDoneProgressParams,
-	PartialResultParams {
+export interface CompletionParams extends TextDocumentPositionParams,
+	WorkDoneProgressParams, PartialResultParams {
 	/**
-	 * The completion context.
-	 * This is only available if the client specifies to send this using
-	 * `ClientCapabilities.textDocument.completion.contextSupport === true`
+	 * The completion context. This is only available if the client specifies
+	 * to send this using the client capability
+	 * `completion.contextSupport === true`
 	 */
 	context?: CompletionContext;
 }
@@ -3344,7 +4445,8 @@
 
 	/**
 	 * Completion was triggered by a trigger character specified by
-	 * the `triggerCharacters` properties of `CompletionRegistrationOptions`.
+	 * the `triggerCharacters` properties of the
+	 * `CompletionRegistrationOptions`.
 	 */
 	export const TriggerCharacter: 2 = 2;
 
@@ -3367,8 +4469,9 @@
 	triggerKind: CompletionTriggerKind;
 
 	/**
-	 * The trigger character (single character) that has trigger code complete.
-	 * Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
+	 * The trigger character (a single character) that has trigger code
+	 * complete. Is undefined if
+	 * `triggerKind !== CompletionTriggerKind.TriggerCharacter`
 	 */
 	triggerCharacter?: string;
 }
@@ -3419,8 +4522,8 @@
 export type InsertTextFormat = 1 | 2;
 
 /**
- * Completion item tags are extra annotations that tweak the rendering of
- * a completion item.
+ * Completion item tags are extra annotations that tweak the rendering of a
+ * completion item.
  *
  * @since 3.15.0
  */
@@ -3433,6 +4536,58 @@
 
 export type CompletionItemTag = 1;
 
+/**
+ * A special text edit to provide an insert and a replace operation.
+ *
+ * @since 3.16.0
+ */
+export interface InsertReplaceEdit {
+	/**
+	 * The string to be inserted.
+	 */
+	newText: string;
+
+	/**
+	 * The range if the insert is requested
+	 */
+	insert: Range;
+
+	/**
+	 * The range if the replace is requested.
+	 */
+	replace: Range;
+}
+
+/**
+ * How whitespace and indentation is handled during completion
+ * item insertion.
+ *
+ * @since 3.16.0
+ */
+export namespace InsertTextMode {
+	/**
+	 * The insertion or replace strings is taken as it is. If the
+	 * value is multi line the lines below the cursor will be
+	 * inserted using the indentation defined in the string value.
+	 * The client will not apply any kind of adjustments to the
+	 * string.
+	 */
+	export const asIs: 1 = 1;
+
+	/**
+	 * The editor adjusts leading whitespace of new lines so that
+	 * they match the indentation up to the cursor of the line for
+	 * which the item is accepted.
+	 *
+	 * Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a
+	 * multi line completion item is indented using 2 tabs and all
+	 * following lines inserted will be indented using 2 tabs as well.
+	 */
+	export const adjustIndentation: 2 = 2;
+}
+
+export type InsertTextMode = 1 | 2;
+
 export interface CompletionItem {
 	/**
 	 * The label of this completion item. By default
@@ -3446,7 +4601,7 @@
 	 * an icon is chosen by the editor. The standardized set
 	 * of available values is defined in `CompletionItemKind`.
 	 */
-	kind?: number;
+	kind?: CompletionItemKind;
 
 	/**
 	 * Tags for this completion item.
@@ -3499,37 +4654,61 @@
 	 * this completion. When `falsy` the label is used.
 	 *
 	 * The `insertText` is subject to interpretation by the client side.
-	 * Some tools might not take the string literally.
-	 * For example, VS Code when code complete is requested in this example
+	 * Some tools might not take the string literally. For example
+	 * VS Code when code complete is requested in this example
 	 * `con<cursor position>` and a completion item with an `insertText` of
-	 * `console` is provided, it will only insert `sole`.
-	 * Therefore, it is recommended to use `textEdit` instead since it avoids
-	 * additional client side interpretation.
+	 * `console` is provided it will only insert `sole`. Therefore it is
+	 * recommended to use `textEdit` instead since it avoids additional client
+	 * side interpretation.
 	 */
 	insertText?: string;
 
 	/**
-	 * The format of the insert text.
-	 * The format applies to both the `insertText` property and the `newText`
-	 * property of a provided `textEdit`.
-	 * If omitted, defaults to `InsertTextFormat.PlainText`.
+	 * The format of the insert text. The format applies to both the
+	 * `insertText` property and the `newText` property of a provided
+	 * `textEdit`. If omitted defaults to `InsertTextFormat.PlainText`.
 	 */
 	insertTextFormat?: InsertTextFormat;
 
 	/**
-	 * An edit that is applied to a document when selecting this completion.
-	 * When an edit is provided, the value of `insertText` is ignored.
+	 * How whitespace and indentation is handled during completion
+	 * item insertion. If not provided the client's default value depends on
+	 * the `textDocument.completion.insertTextMode` client capability.
+	 *
+	 * @since 3.16.0
+	 */
+	insertTextMode?: InsertTextMode;
+
+	/**
+	 * An edit which is applied to a document when selecting this completion.
+	 * When an edit is provided the value of `insertText` is ignored.
 	 *
 	 * *Note:* The range of the edit must be a single line range and it must
 	 * contain the position at which completion has been requested.
+	 *
+	 * Most editors support two different operations when accepting a completion
+	 * item. One is to insert a completion text and the other is to replace an
+	 * existing text with a completion text. Since this can usually not be
+	 * predetermined by a server it can report both ranges. Clients need to
+	 * signal support for `InsertReplaceEdits` via the
+	 * `textDocument.completion.insertReplaceSupport` client capability
+	 * property.
+	 *
+	 * *Note 1:* The text edit's range as well as both ranges from an insert
+	 * replace edit must be a [single line] and they must contain the position
+	 * at which completion has been requested.
+	 * *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range
+	 * must be a prefix of the edit's replace range, that means it must be
+	 * contained and starting at the same position.
+	 *
+	 * @since 3.16.0 additional type `InsertReplaceEdit`
 	 */
-	textEdit?: TextEdit;
+	textEdit?: TextEdit | InsertReplaceEdit;
 
 	/**
 	 * An optional array of additional text edits that are applied when
-	 * selecting this completion.
-	 * Edits must not overlap (including the same insert position) with the
-	 * main edit nor with themselves.
+	 * selecting this completion. Edits must not overlap (including the same
+	 * insert position) with the main edit nor with themselves.
 	 *
 	 * Additional text edits should be used to change text unrelated to the
 	 * current cursor position (for example adding an import statement at the
@@ -3538,10 +4717,10 @@
 	additionalTextEdits?: TextEdit[];
 
 	/**
-	 * An optional set of characters that when pressed, while this completion
-	 * is active, will accept it first and then type that character.
-	 * *Note* that all commit characters should have `length=1` and that
-	 * superfluous characters will be ignored.
+	 * An optional set of characters that when pressed while this completion is
+	 * active will accept it first and then type that character. *Note* that all
+	 * commit characters should have `length=1` and that superfluous characters
+	 * will be ignored.
 	 */
 	commitCharacters?: string[];
 
@@ -3631,7 +4810,7 @@
 
 Transformations allow you to modify the value of a variable before it is inserted. The definition of a transformation consists of three parts:
 
-1. A regular expression that is matched against the value of a variable, or the empty string when the variable cannot be resolved.
+1. A [regular expression](#regExp) that is matched against the value of a variable, or the empty string when the variable cannot be resolved.
 2. A "format string" that allows to reference matching groups from the regular expression. The format string allows for conditional inserts and simple modifications.
 3. Options that are passed to the regular expression.
 
@@ -3668,8 +4847,8 @@
                 | '${' int ':+' if '}'
                 | '${' int ':?' if ':' else '}'
                 | '${' int ':-' else '}' | '${' int ':' else '}'
-regex       ::= JavaScript Regular Expression value (ctor-string)
-options     ::= JavaScript Regular Expression option (ctor-options)
+regex       ::= Regular Expression value (ctor-string)
+options     ::= Regular Expression option (ctor-options)
 var         ::= [_a-zA-Z] [_a-zA-Z0-9]*
 int         ::= [0-9]+
 text        ::= .*
@@ -3703,8 +4882,9 @@
 	dynamicRegistration?: boolean;
 
 	/**
-	 * Client supports the follow content formats for the content
-	 * property. The order describes the preferred format of the client.
+	 * Client supports the follow content formats if the content
+	 * property refers to a `literal of type MarkupContent`.
+	 * The order describes the preferred format of the client.
 	 */
 	contentFormat?: MarkupKind[];
 }
@@ -3731,8 +4911,8 @@
 * params: `HoverParams` defined as follows:
 
 ```typescript
-export interface HoverParams
-	extends TextDocumentPositionParams, WorkDoneProgressParams {
+export interface HoverParams extends TextDocumentPositionParams,
+	WorkDoneProgressParams {
 }
 ```
 
@@ -3761,19 +4941,21 @@
 
 ```typescript
 /**
- * MarkedString can be used to render human readable text.
- * It is either a Markdown string or a code-block that provides a language
- * and a code snippet. The language identifier is semantically equal to the
- * optional language identifier in fenced code blocks in GitHub issues.
+ * MarkedString can be used to render human readable text. It is either a
+ * markdown string or a code-block that provides a language and a code snippet.
+ * The language identifier is semantically equal to the optional language
+ * identifier in fenced code blocks in GitHub issues.
  *
- * The pair of a language and a value is an equivalent to Markdown:
+ * The pair of a language and a value is an equivalent to markdown:
  * ```${language}
  * ${value}
  * ```
  *
- * Note that Markdown strings will be sanitized, meaning HTML will be escaped.
-* @deprecated use MarkupContent instead.
-*/
+ * Note that markdown strings will be sanitized - that means html will be
+ * escaped.
+ *
+ * @deprecated use MarkupContent instead.
+ */
 type MarkedString = string | { language: string; value: string };
 ```
 
@@ -3817,6 +4999,14 @@
 			 */
 			labelOffsetSupport?: boolean;
 		};
+
+		/**
+		 * The client supports the `activeParameter` property on
+		 * `SignatureInformation` literal.
+		 *
+		 * @since 3.16.0
+		 */
+		activeParameterSupport?: boolean;
 	};
 
 	/**
@@ -3847,8 +5037,8 @@
 	 * List of characters that re-trigger signature help.
 	 *
 	 * These trigger characters are only active when signature help is already
-	 * showing.
-	 * All trigger characters are also counted as re-trigger characters.
+	 * showing. All trigger characters are also counted as re-trigger
+	 * characters.
 	 *
 	 * @since 3.15.0
 	 */
@@ -3871,9 +5061,9 @@
 export interface SignatureHelpParams extends TextDocumentPositionParams,
 	WorkDoneProgressParams {
 	/**
-	 * The signature help context.
-	 * This is only available if the client specifies to send this using the
-	 * client capability `textDocument.signatureHelp.contextSupport === true`.
+	 * The signature help context. This is only available if the client
+	 * specifies to send this using the client capability
+	 * `textDocument.signatureHelp.contextSupport === true`
 	 *
 	 * @since 3.15.0
 	 */
@@ -3895,16 +5085,16 @@
 	 */
 	export const TriggerCharacter: 2 = 2;
 	/**
-	 * Signature help was triggered by the cursor moving or
-	 * by the document content changing.
+	 * Signature help was triggered by the cursor moving or by the document
+	 * content changing.
 	 */
 	export const ContentChange: 3 = 3;
 }
 export type SignatureHelpTriggerKind = 1 | 2 | 3;
 
 /**
- * Additional information about the context in which a
- * signature help request was triggered.
+ * Additional information about the context in which a signature help request
+ * was triggered.
  *
  * @since 3.15.0
  */
@@ -3917,8 +5107,8 @@
 	/**
 	 * Character that caused signature help to be triggered.
 	 *
-	 * This is undefined when
-	 * `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter`.
+	 * This is undefined when triggerKind !==
+	 * SignatureHelpTriggerKind.TriggerCharacter
 	 */
 	triggerCharacter?: string;
 
@@ -3926,8 +5116,8 @@
 	 * `true` if signature help was already showing when it was triggered.
 	 *
 	 * Retriggers occur when the signature help is already active and can be
-	 * caused by actions such as typing a trigger character, a cursor move,
-	 * or document content changes.
+	 * caused by actions such as typing a trigger character, a cursor move, or
+	 * document content changes.
 	 */
 	isRetrigger: boolean;
 
@@ -3968,7 +5158,7 @@
 	 * In future version of the protocol this property might become
 	 * mandatory to better express this.
 	 */
-	activeSignature?: number;
+	activeSignature?: uinteger;
 
 	/**
 	 * The active parameter of the active signature. If omitted or the value
@@ -3979,7 +5169,7 @@
 	 * mandatory to better express the active parameter if the
 	 * active signature does have any.
 	 */
-	activeParameter?: number;
+	activeParameter?: uinteger;
 }
 
 /**
@@ -4004,6 +5194,15 @@
 	 * The parameters of this signature.
 	 */
 	parameters?: ParameterInformation[];
+
+	/**
+	 * The index of the active parameter.
+	 *
+	 * If provided, this is used in place of `SignatureHelp.activeParameter`.
+	 *
+	 * @since 3.16.0
+	 */
+	activeParameter?: uinteger;
 }
 
 /**
@@ -4016,15 +5215,15 @@
 	 * The label of this parameter information.
 	 *
 	 * Either a string or an inclusive start and exclusive end offsets within
-	 * its containing signature label. (see SignatureInformation.label).
-	 * The offsets are based on a UTF-16 string representation
-	 * as `Position` and `Range` does.
+	 * its containing signature label. (see SignatureInformation.label). The
+	 * offsets are based on a UTF-16 string representation as `Position` and
+	 * `Range` does.
 	 *
 	 * *Note*: a label of type string should be a substring of its containing
-	 * signature label. Its intended use case is to highlight the
-	 * parameter label part in the `SignatureInformation.label`.
+	 * signature label. Its intended use case is to highlight the parameter
+	 * label part in the `SignatureInformation.label`.
 	 */
-	label: string | [number, number];
+	label: string | [uinteger, uinteger];
 
 	/**
 	 * The human-readable doc-comment of this parameter. Will be shown
@@ -4051,10 +5250,9 @@
 ```typescript
 export interface DeclarationClientCapabilities {
 	/**
-	 * Whether declaration supports dynamic registration.
-	 * If this is set to `true`, the client supports the new
-	 * `DeclarationRegistrationOptions` return value for the
-	 * corresponding server capability as well.
+	 * Whether declaration supports dynamic registration. If this is set to
+	 * `true` the client supports the new `DeclarationRegistrationOptions`
+	 * return value for the corresponding server capability as well.
 	 */
 	dynamicRegistration?: boolean;
 
@@ -4133,8 +5331,8 @@
 
 _Registration Options_: `DefinitionRegistrationOptions` defined as follows:
 ```typescript
-export interface DefinitionRegistrationOptions
-	extends TextDocumentRegistrationOptions, DefinitionOptions {
+export interface DefinitionRegistrationOptions extends
+	TextDocumentRegistrationOptions, DefinitionOptions {
 }
 ```
 
@@ -4143,9 +5341,8 @@
 * params: `DefinitionParams` defined as follows:
 
 ```typescript
-export interface DefinitionParams
-	extends TextDocumentPositionParams, WorkDoneProgressParams,
-		PartialResultParams {
+export interface DefinitionParams extends TextDocumentPositionParams,
+	WorkDoneProgressParams, PartialResultParams {
 }
 ```
 
@@ -4169,10 +5366,9 @@
 ```typescript
 export interface TypeDefinitionClientCapabilities {
 	/**
-	 * Whether implementation supports dynamic registration.
-	 * If this is set to `true`, the client supports the new `
-	 * TypeDefinitionRegistrationOptions` return value for the
-	 * corresponding server capability as well.
+	 * Whether implementation supports dynamic registration. If this is set to
+	 * `true` the client supports the new `TypeDefinitionRegistrationOptions`
+	 * return value for the corresponding server capability as well.
 	 */
 	dynamicRegistration?: boolean;
 
@@ -4196,9 +5392,9 @@
 
 _Registration Options_: `TypeDefinitionRegistrationOptions` defined as follows:
 ```typescript
-export interface TypeDefinitionRegistrationOptions
-	extends TextDocumentRegistrationOptions, TypeDefinitionOptions,
-		StaticRegistrationOptions {
+export interface TypeDefinitionRegistrationOptions extends
+	TextDocumentRegistrationOptions, TypeDefinitionOptions,
+	StaticRegistrationOptions {
 }
 ```
 
@@ -4207,9 +5403,8 @@
 * params: `TypeDefinitionParams` defined as follows:
 
 ```typescript
-export interface TypeDefinitionParams
-	extends TextDocumentPositionParams, WorkDoneProgressParams,
-		PartialResultParams {
+export interface TypeDefinitionParams extends TextDocumentPositionParams,
+	WorkDoneProgressParams, PartialResultParams {
 }
 ```
 
@@ -4233,10 +5428,9 @@
 ```typescript
 export interface ImplementationClientCapabilities {
 	/**
-	 * Whether implementation supports dynamic registration.
-	 * If this is set to `true`, the client supports the new
-	 * `ImplementationRegistrationOptions` return value for the
-	 * corresponding server capability as well.
+	 * Whether implementation supports dynamic registration. If this is set to
+	 * `true` the client supports the new `ImplementationRegistrationOptions`
+	 * return value for the corresponding server capability as well.
 	 */
 	dynamicRegistration?: boolean;
 
@@ -4260,9 +5454,9 @@
 
 _Registration Options_: `ImplementationRegistrationOptions` defined as follows:
 ```typescript
-export interface ImplementationRegistrationOptions
-	extends TextDocumentRegistrationOptions, ImplementationOptions,
-		StaticRegistrationOptions {
+export interface ImplementationRegistrationOptions extends
+	TextDocumentRegistrationOptions, ImplementationOptions,
+	StaticRegistrationOptions {
 }
 ```
 
@@ -4309,8 +5503,8 @@
 
 _Registration Options_: `ReferenceRegistrationOptions` defined as follows:
 ```typescript
-export interface ReferenceRegistrationOptions
-	extends TextDocumentRegistrationOptions, ReferenceOptions {
+export interface ReferenceRegistrationOptions extends
+	TextDocumentRegistrationOptions, ReferenceOptions {
 }
 ```
 
@@ -4367,8 +5561,8 @@
 
 _Registration Options_: `DocumentHighlightRegistrationOptions` defined as follows:
 ```typescript
-export interface DocumentHighlightRegistrationOptions
-	extends TextDocumentRegistrationOptions, DocumentHighlightOptions {
+export interface DocumentHighlightRegistrationOptions extends
+	TextDocumentRegistrationOptions, DocumentHighlightOptions {
 }
 ```
 
@@ -4401,7 +5595,7 @@
 	/**
 	 * The highlight kind, default is DocumentHighlightKind.Text.
 	 */
-	kind?: number;
+	kind?: DocumentHighlightKind;
 }
 
 /**
@@ -4423,6 +5617,8 @@
 	 */
 	export const Write = 3;
 }
+
+export type DocumentHighlightKind = 1 | 2 | 3;
 ```
 
 * partial result: `DocumentHighlight[]`
@@ -4435,6 +5631,8 @@
 - `SymbolInformation[]` which is a flat list of all symbols found in a given text document. Then neither the symbol's location range nor the symbol's container name should be used to infer a hierarchy.
 - `DocumentSymbol[]` which is a hierarchy of symbols found in a given text document.
 
+Servers should whenever possible return `DocumentSymbol` since it is the richer data structure.
+
 _Client Capability_:
 * property name (optional): `textDocument.documentSymbol`
 * property type: `DocumentSymbolClientCapabilities` defined as follows:
@@ -4468,6 +5666,28 @@
 	 * The client supports hierarchical document symbols.
 	 */
 	hierarchicalDocumentSymbolSupport?: boolean;
+
+	/**
+	 * The client supports tags on `SymbolInformation`. Tags are supported on
+	 * `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
+	 * Clients supporting tags have to handle unknown tags gracefully.
+	 *
+	 * @since 3.16.0
+	 */
+	tagSupport?: {
+		/**
+		 * The tags supported by the client.
+		 */
+		valueSet: SymbolTag[]
+	}
+
+	/**
+	 * The client supports an additional label presented in the UI when
+	 * registering a document symbol provider.
+	 *
+	 * @since 3.16.0
+	 */
+	labelSupport?: boolean;
 }
 ```
 
@@ -4477,13 +5697,20 @@
 
 ```typescript
 export interface DocumentSymbolOptions extends WorkDoneProgressOptions {
+	/**
+	 * A human-readable string that is shown when multiple outlines trees
+	 * are shown for the same document.
+	 *
+	 * @since 3.16.0
+	 */
+	label?: string;
 }
 ```
 
 _Registration Options_: `DocumentSymbolRegistrationOptions` defined as follows:
 ```typescript
-export interface DocumentSymbolRegistrationOptions
-	extends TextDocumentRegistrationOptions, DocumentSymbolOptions {
+export interface DocumentSymbolRegistrationOptions extends
+	TextDocumentRegistrationOptions, DocumentSymbolOptions {
 }
 ```
 
@@ -4492,8 +5719,8 @@
 * params: `DocumentSymbolParams` defined as follows:
 
 ```typescript
-export interface DocumentSymbolParams
-	extends WorkDoneProgressParams, PartialResultParams {
+export interface DocumentSymbolParams extends WorkDoneProgressParams,
+	PartialResultParams {
 	/**
 	 * The text document.
 	 */
@@ -4538,17 +5765,33 @@
 }
 
 /**
+ * Symbol tags are extra annotations that tweak the rendering of a symbol.
+ *
+ * @since 3.16
+ */
+export namespace SymbolTag {
+
+	/**
+	 * Render a symbol as obsolete, usually using a strike-out.
+	 */
+	export const Deprecated: 1 = 1;
+}
+
+export type SymbolTag = 1;
+
+
+/**
  * Represents programming constructs like variables, classes, interfaces etc.
  * that appear in a document. Document symbols can be hierarchical and they
- * have two ranges: one that encloses its definition and one that points to
- * its most interesting range, for example, the range of an identifier.
+ * have two ranges: one that encloses its definition and one that points to its
+ * most interesting range, e.g. the range of an identifier.
  */
 export interface DocumentSymbol {
 
 	/**
-	 * The name of this symbol.
-	 * Will be displayed in the user interface and therefore must not be
-	 * an empty string or a string only consisting of white spaces.
+	 * The name of this symbol. Will be displayed in the user interface and
+	 * therefore must not be an empty string or a string only consisting of
+	 * white spaces.
 	 */
 	name: string;
 
@@ -4563,22 +5806,30 @@
 	kind: SymbolKind;
 
 	/**
+	 * Tags for this document symbol.
+	 *
+	 * @since 3.16.0
+	 */
+	tags?: SymbolTag[];
+
+	/**
 	 * Indicates if this symbol is deprecated.
+	 *
+	 * @deprecated Use tags instead
 	 */
 	deprecated?: boolean;
 
 	/**
-	 * The range enclosing this symbol not including leading/trailing
-	 * whitespace but everything else like comments.
-	 * This information is typically used to determine if the client's cursor
-	 * is inside the symbol to reveal in the symbol in the UI.
+	 * The range enclosing this symbol not including leading/trailing whitespace
+	 * but everything else like comments. This information is typically used to
+	 * determine if the clients cursor is inside the symbol to reveal in the
+	 * symbol in the UI.
 	 */
 	range: Range;
 
 	/**
-	 * The range that should be selected and revealed when this symbol
-	 * is being picked, for example, the name of a function.
-	 * Must be contained by the `range`.
+	 * The range that should be selected and revealed when this symbol is being
+	 * picked, e.g. the name of a function. Must be contained by the `range`.
 	 */
 	selectionRange: Range;
 
@@ -4604,7 +5855,16 @@
 	kind: SymbolKind;
 
 	/**
+	 * Tags for this completion item.
+	 *
+	 * @since 3.16.0
+	 */
+	tags?: SymbolTag[];
+
+	/**
 	 * Indicates if this symbol is deprecated.
+	 *
+	 * @deprecated Use tags instead
 	 */
 	deprecated?: boolean;
 
@@ -4636,9 +5896,11 @@
 
 #### <a href="#textDocument_codeAction" name="textDocument_codeAction" class="anchor">Code Action Request (:leftwards_arrow_with_hook:)</a>
 
-The code action request is sent from the client to the server to compute commands for a given text document and range. These commands are typically code fixes to either fix problems or to beautify/refactor code. The result of a `textDocument/codeAction` request is an array of `Command` literals which are typically presented in the user interface. To ensure that a server is useful in many clients the commands specified in a code actions should be handled by the server and not by the client (see `workspace/executeCommand` and `ServerCapabilities.executeCommandProvider`). If the client supports providing edits with a code action then the mode should be used.
+The code action request is sent from the client to the server to compute commands for a given text document and range. These commands are typically code fixes to either fix problems or to beautify/refactor code. The result of a `textDocument/codeAction` request is an array of `Command` literals which are typically presented in the user interface. To ensure that a server is useful in many clients the commands specified in a code actions should be handled by the server and not by the client (see `workspace/executeCommand` and `ServerCapabilities.executeCommandProvider`). If the client supports providing edits with a code action then that mode should be used.
 
-When the command is selected the server should be contacted again (via the `workspace/executeCommand`) request to execute the command.
+*Since version 3.16.0:* a client can offer a server to delay the computation of code action properties during a 'textDocument/codeAction' request:
+
+This is useful for cases where it is expensive to compute the value of a property (for example the `edit` property). Clients signal this through the `codeAction.resolveSupport` capability which lists all properties a client can resolve lazily. The server capability `codeActionProvider.resolveProvider` signals that a server will offer a `codeAction/resolve` route. To help servers to uniquely identify a code action in the resolve request, a code action literal can optional carry a data property. This is also guarded by an additional client capability `codeAction.dataSupport`. In general, a client should offer data support if it offers resolve support. It should also be noted that servers shouldn't alter existing attributes of a code action in a codeAction/resolve request.
 
 > *Since version 3.8.0:* support for CodeAction literals to enable the following scenarios:
 
@@ -4683,9 +5945,51 @@
 
 	/**
 	 * Whether code action supports the `isPreferred` property.
+	 *
 	 * @since 3.15.0
 	 */
 	isPreferredSupport?: boolean;
+
+	/**
+	 * Whether code action supports the `disabled` property.
+	 *
+	 * @since 3.16.0
+	 */
+	disabledSupport?: boolean;
+
+	/**
+	 * Whether code action supports the `data` property which is
+	 * preserved between a `textDocument/codeAction` and a
+	 * `codeAction/resolve` request.
+	 *
+	 * @since 3.16.0
+	 */
+	dataSupport?: boolean;
+
+
+	/**
+	 * Whether the client supports resolving additional code action
+	 * properties via a separate `codeAction/resolve` request.
+	 *
+	 * @since 3.16.0
+	 */
+	resolveSupport?: {
+		/**
+		 * The properties that a client can resolve lazily.
+		*/
+		properties: string[];
+	};
+
+	/**
+	 * Whether th client honors the change annotations in
+	 * text edits and resource operations returned via the
+	 * `CodeAction#edit` property by for example presenting
+	 * the workspace edit in the user interface and asking
+	 * for confirmation.
+	 *
+	 * @since 3.16.0
+	 */
+	honorsChangeAnnotations?: boolean;
 }
 ```
 
@@ -4702,13 +6006,21 @@
 	 * or the server may list out every specific kind they provide.
 	 */
 	codeActionKinds?: CodeActionKind[];
+
+	/**
+	 * The server provides support to resolve additional
+	 * information for a code action.
+	 *
+	 * @since 3.16.0
+	 */
+	resolveProvider?: boolean;
 }
 ```
 
 _Registration Options_: `CodeActionRegistrationOptions` defined as follows:
 ```typescript
-export interface CodeActionRegistrationOptions
-	extends TextDocumentRegistrationOptions, CodeActionOptions {
+export interface CodeActionRegistrationOptions extends
+	TextDocumentRegistrationOptions, CodeActionOptions {
 }
 ```
 
@@ -4720,8 +6032,8 @@
 /**
  * Params for the CodeActionRequest
  */
-export interface CodeActionParams
-	extends WorkDoneProgressParams, PartialResultParams {
+export interface CodeActionParams extends WorkDoneProgressParams,
+	PartialResultParams {
 	/**
 	 * The document in which the command was invoked.
 	 */
@@ -4744,8 +6056,8 @@
  * Kinds are a hierarchical list of identifiers separated by `.`,
  * e.g. `"refactor.extract.function"`.
  *
- * The set of kinds is open and the client needs to announce the kinds it
- * supports to the server during initialization.
+ * The set of kinds is open and client needs to announce the kinds it supports
+ * to the server during initialization.
  */
 export type CodeActionKind = string;
 
@@ -4816,10 +6128,11 @@
 	export const Source: CodeActionKind = 'source';
 
 	/**
-	 * Base kind for an organize imports source action `source.organizeImports`.
+	 * Base kind for an organize imports source action:
+	 * `source.organizeImports`.
 	 */
-	export const SourceOrganizeImports: CodeActionKind
-		= 'source.organizeImports';
+	export const SourceOrganizeImports: CodeActionKind =
+		'source.organizeImports';
 }
 
 /**
@@ -4829,19 +6142,19 @@
 export interface CodeActionContext {
 	/**
 	 * An array of diagnostics known on the client side overlapping the range
-	 * provided to the `textDocument/codeAction` request.
-	 * They are provided so that the server knows which errors are currently
-	 * presented to the user for the given range. There is no guarantee that
-	 * these accurately reflect the error state of the resource.
-	 * The primary parameter to compute code actions is the provided range.
+	 * provided to the `textDocument/codeAction` request. They are provided so
+	 * that the server knows which errors are currently presented to the user
+	 * for the given range. There is no guarantee that these accurately reflect
+	 * the error state of the resource. The primary parameter
+	 * to compute code actions is the provided range.
 	 */
 	diagnostics: Diagnostic[];
 
 	/**
 	 * Requested kind of actions to return.
 	 *
-	 * Actions not of this kind are filtered out by the client before
-	 * being shown, so servers can omit computing them.
+	 * Actions not of this kind are filtered out by the client before being
+	 * shown. So servers can omit computing them.
 	 */
 	only?: CodeActionKind[];
 }
@@ -4852,12 +6165,11 @@
 
 ```typescript
 /**
- * A code action represents a change that can be performed in code.
- * For example, to fix a problem or to refactor code.
+ * A code action represents a change that can be performed in code, e.g. to fix
+ * a problem or to refactor code.
  *
- * A CodeAction must set either `edit` and/or a `command`.
- * If both are supplied, the `edit` is applied first, then the `command`
- * is executed.
+ * A CodeAction must set either `edit` and/or a `command`. If both are supplied,
+ * the `edit` is applied first, then the `command` is executed.
  */
 export interface CodeAction {
 
@@ -4879,20 +6191,48 @@
 	diagnostics?: Diagnostic[];
 
 	/**
-	 * Marks this as a preferred action.
-	 * Preferred actions are used by the `auto fix` command and can be
-	 * targeted by keybindings.
+	 * Marks this as a preferred action. Preferred actions are used by the
+	 * `auto fix` command and can be targeted by keybindings.
 	 *
 	 * A quick fix should be marked preferred if it properly addresses the
-	 * underlying error.
-	 * A refactoring should be marked preferred if it is the most reasonable
-	 * choice of actions to take.
+	 * underlying error. A refactoring should be marked preferred if it is the
+	 * most reasonable choice of actions to take.
 	 *
 	 * @since 3.15.0
 	 */
 	isPreferred?: boolean;
 
 	/**
+	 * Marks that the code action cannot currently be applied.
+	 *
+	 * Clients should follow the following guidelines regarding disabled code
+	 * actions:
+	 *
+	 * - Disabled code actions are not shown in automatic lightbulbs code
+	 *   action menus.
+	 *
+	 * - Disabled actions are shown as faded out in the code action menu when
+	 *   the user request a more specific type of code action, such as
+	 *   refactorings.
+	 *
+	 * - If the user has a keybinding that auto applies a code action and only
+	 *   a disabled code actions are returned, the client should show the user
+	 *   an error message with `reason` in the editor.
+	 *
+	 * @since 3.16.0
+	 */
+	disabled?: {
+
+		/**
+		 * Human readable description of why the code action is currently
+		 * disabled.
+		 *
+		 * This is displayed in the code actions UI.
+		 */
+		reason: string;
+	};
+
+	/**
 	 * The workspace edit this code action performs.
 	 */
 	edit?: WorkspaceEdit;
@@ -4903,14 +6243,57 @@
 	 * executed and then the command.
 	 */
 	command?: Command;
+
+	/**
+	 * A data entry field that is preserved on a code action between
+	 * a `textDocument/codeAction` and a `codeAction/resolve` request.
+	 *
+	 * @since 3.16.0
+	 */
+	data?: any
 }
 ```
 * partial result: `(Command | CodeAction)[]`
 * error: code and message set in case an exception happens during the code action request.
 
+#### <a href="#codeAction_resolve" name="codeAction_resolve" class="anchor">Code Action Resolve Request (:leftwards_arrow_with_hook:)</a>
+
+> *Since version 3.16.0*
+
+The request is sent from the client to the server to resolve additional information for a given code action. This is usually used to compute
+the `edit` property of a code action to avoid its unnecessary computation during the `textDocument/codeAction` request.
+
+Consider the clients announces the `edit` property as a property that can be resolved lazy using the client capability
+
+```typescript
+textDocument.codeAction.resolveSupport = { properties: ['edit']};
+```
+
+then a code action
+
+```typescript
+{
+    "title": "Do Foo"
+}
+```
+
+needs to be resolved using the `codeAction/resolve` request before it can be applied.
+
+_Client Capability_:
+* property name (optional): `textDocument.codeAction.resolveSupport`
+* property type: `{ properties: string[]; }`
+
+_Request_:
+* method: 'codeAction/resolve'
+* params: `CodeAction`
+
+_Response_:
+* result: `CodeAction`
+* error: code and message set in case an exception happens during the completion resolve request.
+
 #### <a href="#textDocument_codeLens" name="textDocument_codeLens" class="anchor">Code Lens Request (:leftwards_arrow_with_hook:)</a>
 
-The CodeLens request is sent from the client to the server to compute CodeLens for a given text document.
+The code lens request is sent from the client to the server to compute code lenses for a given text document.
 
 _Client Capability_:
 * property name (optional): `textDocument.codeLens`
@@ -4919,7 +6302,7 @@
 ```typescript
 export interface CodeLensClientCapabilities {
 	/**
-	 * Whether CodeLens supports dynamic registration.
+	 * Whether code lens supports dynamic registration.
 	 */
 	dynamicRegistration?: boolean;
 }
@@ -4940,8 +6323,8 @@
 
 _Registration Options_: `CodeLensRegistrationOptions` defined as follows:
 ```typescript
-export interface CodeLensRegistrationOptions
-	extends TextDocumentRegistrationOptions, CodeLensOptions {
+export interface CodeLensRegistrationOptions extends
+	TextDocumentRegistrationOptions, CodeLensOptions {
 }
 ```
 
@@ -4952,7 +6335,7 @@
 ```typescript
 interface CodeLensParams extends WorkDoneProgressParams, PartialResultParams {
 	/**
-	 * The document to request CodeLens for.
+	 * The document to request code lens for.
 	 */
 	textDocument: TextDocumentIdentifier;
 }
@@ -4963,37 +6346,38 @@
 
 ```typescript
 /**
- * A CodeLense represents a command that should be shown along with
+ * A code lens represents a command that should be shown along with
  * source text, like the number of references, a way to run tests, etc.
  *
- * A CodeLens is _unresolved_ when no command is associated to it.
- * For performance reasons, the creation of a CodeLens and resolving should
- * be done in two stages.
+ * A code lens is _unresolved_ when no command is associated to it. For
+ * performance reasons the creation of a code lens and resolving should be done
+ * in two stages.
  */
 interface CodeLens {
 	/**
-	 * The range in which the CodeLens is valid. Should only span a single line.
+	 * The range in which this code lens is valid. Should only span a single
+	 * line.
 	 */
 	range: Range;
 
 	/**
-	 * The command this CodeLens represents.
+	 * The command this code lens represents.
 	 */
 	command?: Command;
 
 	/**
-	 * A data entry field that is preserved on a CodeLens item between
-	 * a CodeLens and a CodeLens resolve request.
+	 * A data entry field that is preserved on a code lens item between
+	 * a code lens and a code lens resolve request.
 	 */
 	data?: any
 }
 ```
 * partial result: `CodeLens[]`
-* error: code and message set in case an exception happens during the CodeLens request.
+* error: code and message set in case an exception happens during the code lens request.
 
 #### <a href="#codeLens_resolve" name="codeLens_resolve" class="anchor">Code Lens Resolve Request (:leftwards_arrow_with_hook:)</a>
 
-The CodeLens resolve request is sent from the client to the server to resolve the command for a given CodeLens item.
+The code lens resolve request is sent from the client to the server to resolve the command for a given code lens item.
 
 _Request_:
 * method: 'codeLens/resolve'
@@ -5001,7 +6385,43 @@
 
 _Response_:
 * result: `CodeLens`
-* error: code and message set in case an exception happens during the CodeLens resolve request.
+* error: code and message set in case an exception happens during the code lens resolve request.
+
+#### <a href="#codeLens_refresh" name="codeLens_refresh" class="anchor">Code Lens Refresh Request (:arrow_right_hook:)</a>
+
+> *Since version 3.16.0*
+
+The `workspace/codeLens/refresh` request is sent from the server to the client. Servers can use it to ask clients to refresh the code lenses currently shown in editors. As a result the client should ask the server to recompute the code lenses for these editors. This is useful if a server detects a configuration change which requires a re-calculation of all code lenses. Note that the client still has the freedom to delay the re-calculation of the code lenses if for example an editor is currently not visible.
+
+_Client Capability_:
+
+* property name (optional): `workspace.codeLens`
+* property type: `CodeLensWorkspaceClientCapabilities` defined as follows:
+
+```typescript
+export interface CodeLensWorkspaceClientCapabilities {
+	/**
+	 * Whether the client implementation supports a refresh request sent from the
+	 * server to the client.
+	 *
+	 * Note that this event is global and will force the client to refresh all
+	 * code lenses currently shown. It should be used with absolute care and is
+	 * useful for situation where a server for example detect a project wide
+	 * change that requires such a calculation.
+	 */
+	refreshSupport?: boolean;
+}
+```
+
+_Request_:
+
+* method: `workspace/codeLens/refresh`
+* params: none
+
+_Response_:
+
+* result: void
+* error: code and message set in case an exception happens during the 'workspace/codeLens/refresh' request
 
 #### <a href="#textDocument_documentLink" name="textDocument_documentLink" class="anchor">Document Link Request (:leftwards_arrow_with_hook:)</a>
 
@@ -5042,8 +6462,8 @@
 
 _Registration Options_: `DocumentLinkRegistrationOptions` defined as follows:
 ```typescript
-export interface DocumentLinkRegistrationOptions
-	extends TextDocumentRegistrationOptions, DocumentLinkOptions {
+export interface DocumentLinkRegistrationOptions extends
+	TextDocumentRegistrationOptions, DocumentLinkOptions {
 }
 ```
 
@@ -5052,8 +6472,8 @@
 * params: `DocumentLinkParams` defined as follows:
 
 ```typescript
-interface DocumentLinkParams
-	extends WorkDoneProgressParams, PartialResultParams {
+interface DocumentLinkParams extends WorkDoneProgressParams,
+	PartialResultParams {
 	/**
 	 * The document to provide document links for.
 	 */
@@ -5066,8 +6486,8 @@
 
 ```typescript
 /**
- * A document link is a range in a text document that links to an internal
- * or external resource, like another text document or a web site.
+ * A document link is a range in a text document that links to an internal or
+ * external resource, like another text document or a web site.
  */
 interface DocumentLink {
 	/**
@@ -5083,11 +6503,10 @@
 	/**
 	 * The tooltip text when you hover over this link.
 	 *
-	 * If a tooltip is provided, it will be displayed in a string that
-	 * includes instructions on how to trigger the link,
-	 * such as `{0} (ctrl + click)`.
-	 * The specific instructions vary depending on OS, user settings,
-	 * and localization.
+	 * If a tooltip is provided, is will be displayed in a string that includes
+	 * instructions on how to trigger the link, such as `{0} (ctrl + click)`.
+	 * The specific instructions vary depending on OS, user settings, and
+	 * localization.
 	 *
 	 * @since 3.15.0
 	 */
@@ -5149,9 +6568,9 @@
 
 _Registration Options_: `DocumentColorRegistrationOptions` defined as follows:
 ```typescript
-export interface DocumentColorRegistrationOptions
-	extends TextDocumentRegistrationOptions, StaticRegistrationOptions,
-		DocumentColorOptions {
+export interface DocumentColorRegistrationOptions extends
+	TextDocumentRegistrationOptions, StaticRegistrationOptions,
+	DocumentColorOptions {
 }
 ```
 
@@ -5161,8 +6580,8 @@
 * params: `DocumentColorParams` defined as follows
 
 ```typescript
-interface DocumentColorParams
-	extends WorkDoneProgressParams, PartialResultParams {
+interface DocumentColorParams extends WorkDoneProgressParams,
+	PartialResultParams {
 	/**
 	 * The text document.
 	 */
@@ -5194,22 +6613,22 @@
 	/**
 	 * The red component of this color in the range [0-1].
 	 */
-	readonly red: number;
+	readonly red: decimal;
 
 	/**
 	 * The green component of this color in the range [0-1].
 	 */
-	readonly green: number;
+	readonly green: decimal;
 
 	/**
 	 * The blue component of this color in the range [0-1].
 	 */
-	readonly blue: number;
+	readonly blue: decimal;
 
 	/**
 	 * The alpha component of this color in the range [0-1].
 	 */
-	readonly alpha: number;
+	readonly alpha: decimal;
 }
 ```
 * partial result: `ColorInformation[]`
@@ -5231,8 +6650,8 @@
 * params: `ColorPresentationParams` defined as follows
 
 ```typescript
-interface ColorPresentationParams
-	extends WorkDoneProgressParams, PartialResultParams {
+interface ColorPresentationParams extends WorkDoneProgressParams,
+	PartialResultParams {
 	/**
 	 * The text document.
 	 */
@@ -5257,22 +6676,20 @@
 interface ColorPresentation {
 	/**
 	 * The label of this color presentation. It will be shown on the color
-	 * picker header.
-	 * By default, this is also the text that is inserted when selecting
-	 * this color presentation.
+	 * picker header. By default this is also the text that is inserted when
+	 * selecting this color presentation.
 	 */
 	label: string;
 	/**
 	 * An [edit](#TextEdit) which is applied to a document when selecting
-	 * this presentation for the color.
-	 * When `falsy`, the [label](#ColorPresentation.label) is used.
+	 * this presentation for the color.  When `falsy` the
+	 * [label](#ColorPresentation.label) is used.
 	 */
 	textEdit?: TextEdit;
 	/**
-	 * An optional array of additional [text edits](#TextEdit) that are
-	 * applied when selecting this color presentation.
-	 * Edits must not overlap with the main [edit](#ColorPresentation.textEdit)
-	 * nor with themselves.
+	 * An optional array of additional [text edits](#TextEdit) that are applied
+	 * when selecting this color presentation. Edits must not overlap with the
+	 * main [edit](#ColorPresentation.textEdit) nor with themselves.
 	 */
 	additionalTextEdits?: TextEdit[];
 }
@@ -5309,8 +6726,8 @@
 
 _Registration Options_: `DocumentFormattingRegistrationOptions` defined as follows:
 ```typescript
-export interface DocumentFormattingRegistrationOptions
-	extends TextDocumentRegistrationOptions, DocumentFormattingOptions {
+export interface DocumentFormattingRegistrationOptions extends
+	TextDocumentRegistrationOptions, DocumentFormattingOptions {
 }
 ```
 
@@ -5338,7 +6755,7 @@
 	/**
 	 * Size of a tab in spaces.
 	 */
-	tabSize: number;
+	tabSize: uinteger;
 
 	/**
 	 * Prefer spaces over tabs.
@@ -5369,7 +6786,7 @@
 	/**
 	 * Signature for further properties.
 	 */
-	[key: string]: boolean | number | string;
+	[key: string]: boolean | integer | string;
 }
 ```
 
@@ -5399,15 +6816,15 @@
 * property type: `boolean | DocumentRangeFormattingOptions` where `DocumentRangeFormattingOptions` is defined as follows:
 
 ```typescript
-export interface DocumentRangeFormattingOptions
-	extends WorkDoneProgressOptions {
+export interface DocumentRangeFormattingOptions extends
+	WorkDoneProgressOptions {
 }
 ```
 
 _Registration Options_: `DocumentFormattingRegistrationOptions` defined as follows:
 ```typescript
-export interface DocumentRangeFormattingRegistrationOptions
-	extends TextDocumentRegistrationOptions, DocumentRangeFormattingOptions {
+export interface DocumentRangeFormattingRegistrationOptions extends
+	TextDocumentRegistrationOptions, DocumentRangeFormattingOptions {
 }
 ```
 
@@ -5475,8 +6892,8 @@
 
 _Registration Options_: `DocumentOnTypeFormattingRegistrationOptions` defined as follows:
 ```typescript
-export interface DocumentOnTypeFormattingRegistrationOptions
-	extends TextDocumentRegistrationOptions, DocumentOnTypeFormattingOptions {
+export interface DocumentOnTypeFormattingRegistrationOptions extends
+	TextDocumentRegistrationOptions, DocumentOnTypeFormattingOptions {
 }
 ```
 
@@ -5511,6 +6928,13 @@
 * property type: `RenameClientCapabilities` defined as follows:
 
 ```typescript
+export namespace PrepareSupportDefaultBehavior {
+	/**
+	 * The client's default behavior is to select the identifier
+	 * according the to language's syntax rule.
+	 */
+	 export const Identifier: 1 = 1;
+}
 export interface RenameClientCapabilities {
 	/**
 	 * Whether rename supports dynamic registration.
@@ -5524,6 +6948,28 @@
 	 * @since version 3.12.0
 	 */
 	prepareSupport?: boolean;
+
+	/**
+	 * Client supports the default behavior result
+	 * (`{ defaultBehavior: boolean }`).
+	 *
+	 * The value indicates the default behavior used by the
+	 * client.
+	 *
+	 * @since version 3.16.0
+	 */
+	prepareSupportDefaultBehavior?: PrepareSupportDefaultBehavior;
+
+	/**
+	 * Whether th client honors the change annotations in
+	 * text edits and resource operations returned via the
+	 * rename request's workspace edit by for example presenting
+	 * the workspace edit in the user interface and asking
+	 * for confirmation.
+	 *
+	 * @since 3.16.0
+	 */
+	honorsChangeAnnotations?: boolean;
 }
 ```
 
@@ -5544,8 +6990,8 @@
 
 _Registration Options_: `RenameRegistrationOptions` defined as follows:
 ```typescript
-export interface RenameRegistrationOptions
-	extends TextDocumentRegistrationOptions, RenameOptions {
+export interface RenameRegistrationOptions extends
+	TextDocumentRegistrationOptions, RenameOptions {
 }
 ```
 
@@ -5554,8 +7000,8 @@
 * params: `RenameParams` defined as follows
 
 ```typescript
-interface RenameParams
-	extends TextDocumentPositionParams, WorkDoneProgressParams {
+interface RenameParams extends TextDocumentPositionParams,
+	WorkDoneProgressParams {
 	/**
 	 * The new name of the symbol. If the given name is not valid the
 	 * request must return a [ResponseError](#ResponseError) with an
@@ -5584,7 +7030,7 @@
 ```
 
 _Response_:
-* result: [`Range`](#range) \| `{ range: Range, placeholder: string }` \| `null` describing the range of the string to rename and optionally a placeholder text of the string content to be renamed. If `null` is returned then it is deemed that a 'textDocument/rename' request is not valid at the given position.
+* result: `Range | { range: Range, placeholder: string } | { defaultBehavior: boolean } | null` describing a [`Range`](#range) of the string to rename and optionally a placeholder text of the string content to be renamed. If `{ defaultBehavior: boolean }` is returned (since 3.16) the rename position is valid and the client should use its default behavior to compute the rename range. If `null` is returned then it is deemed that a 'textDocument/rename' request is not valid at the given position.
 * error: code and message set in case the element can't be renamed. Clients should show the information in their user interface.
 
 #### <a href="#textDocument_foldingRange" name="textDocument_foldingRange" class="anchor">Folding Range Request (:leftwards_arrow_with_hook:)</a>
@@ -5600,23 +7046,22 @@
 ```typescript
 export interface FoldingRangeClientCapabilities {
 	/**
-	 * Whether the implementation supports dynamic registration for
-	 * folding range providers.
-	 * If this is set to `true`, the client supports the new
+	 * Whether implementation supports dynamic registration for folding range
+	 * providers. If this is set to `true` the client supports the new
 	 * `FoldingRangeRegistrationOptions` return value for the corresponding
 	 * server capability as well.
 	 */
 	dynamicRegistration?: boolean;
 	/**
-	 * The maximum number of folding ranges that the client prefers to
-	 * receive per document.
-	 * The value serves as a hint, servers are free to follow the limit.
+	 * The maximum number of folding ranges that the client prefers to receive
+	 * per document. The value serves as a hint, servers are free to follow the
+	 * limit.
 	 */
-	rangeLimit?: number;
+	rangeLimit?: uinteger;
 	/**
 	 * If set, the client signals that it only supports folding complete lines.
-	 * If set, the client will ignore specified `startCharacter` and
-	 * `endCharacter` properties in a FoldingRange.
+	 * If set, client will ignore specified `startCharacter` and `endCharacter`
+	 * properties in a FoldingRange.
 	 */
 	lineFoldingOnly?: boolean;
 }
@@ -5633,9 +7078,9 @@
 
 _Registration Options_: `FoldingRangeRegistrationOptions` defined as follows:
 ```typescript
-export interface FoldingRangeRegistrationOptions
-	extends TextDocumentRegistrationOptions, FoldingRangeOptions,
-		StaticRegistrationOptions {
+export interface FoldingRangeRegistrationOptions extends
+	TextDocumentRegistrationOptions, FoldingRangeOptions,
+	StaticRegistrationOptions {
 }
 ```
 
@@ -5645,8 +7090,8 @@
 * params: `FoldingRangeParams` defined as follows
 
 ```typescript
-export interface FoldingRangeParams
-	extends WorkDoneProgressParams, PartialResultParams {
+export interface FoldingRangeParams extends WorkDoneProgressParams,
+	PartialResultParams {
 	/**
 	 * The text document.
 	 */
@@ -5677,38 +7122,43 @@
 }
 
 /**
- * Represents a folding range.
+ * Represents a folding range. To be valid, start and end line must be bigger
+ * than zero and smaller than the number of lines in the document. Clients
+ * are free to ignore invalid ranges.
  */
 export interface FoldingRange {
 
 	/**
-	 * The zero-based line number from where the folded range starts.
+	 * The zero-based start line of the range to fold. The folded area starts
+	 * after the line's last character. To be valid, the end must be zero or
+	 * larger and smaller than the number of lines in the document.
 	 */
-	startLine: number;
+	startLine: uinteger;
 
 	/**
-	 * The zero-based character offset from where the folded range starts.
-	 * If not defined, defaults to the length of the start line.
+	 * The zero-based character offset from where the folded range starts. If
+	 * not defined, defaults to the length of the start line.
 	 */
-	startCharacter?: number;
+	startCharacter?: uinteger;
 
 	/**
-	 * The zero-based line number where the folded range ends.
+	 * The zero-based end line of the range to fold. The folded area ends with
+	 * the line's last character. To be valid, the end must be zero or larger
+	 * and smaller than the number of lines in the document.
 	 */
-	endLine: number;
+	endLine: uinteger;
 
 	/**
-	 * The zero-based character offset before the folded range ends.
-	 * If not defined, defaults to the length of the end line.
+	 * The zero-based character offset before the folded range ends. If not
+	 * defined, defaults to the length of the end line.
 	 */
-	endCharacter?: number;
+	endCharacter?: uinteger;
 
 	/**
 	 * Describes the kind of the folding range such as `comment` or `region`.
-	 * The kind is used to categorize folding ranges and used by commands
-	 * like 'Fold all comments'.
-	 * See [FoldingRangeKind](#FoldingRangeKind) for an enumeration of
-	 * standardized kinds.
+	 * The kind is used to categorize folding ranges and used by commands like
+	 * 'Fold all comments'. See [FoldingRangeKind](#FoldingRangeKind) for an
+	 * enumeration of standardized kinds.
 	 */
 	kind?: string;
 }
@@ -5734,9 +7184,8 @@
 ```typescript
 export interface SelectionRangeClientCapabilities {
 	/**
-	 * Whether implementation supports dynamic registration for selection
-	 * range providers.
-	 * If set to `true`, the client supports the new
+	 * Whether implementation supports dynamic registration for selection range
+	 * providers. If this is set to `true` the client supports the new
 	 * `SelectionRangeRegistrationOptions` return value for the corresponding
 	 * server capability as well.
 	 */
@@ -5755,20 +7204,20 @@
 
 _Registration Options_: `SelectionRangeRegistrationOptions` defined as follows:
 ```typescript
-export interface SelectionRangeRegistrationOptions
-	extends SelectionRangeOptions, TextDocumentRegistrationOptions,
-		StaticRegistrationOptions {
+export interface SelectionRangeRegistrationOptions extends
+	SelectionRangeOptions, TextDocumentRegistrationOptions,
+	StaticRegistrationOptions {
 }
 ```
 
 _Request_:
 
 * method: 'textDocument/selectionRange'
-* params: `SelectionRangeParams` defined as follows
+* params: `SelectionRangeParams` defined as follows:
 
 ```typescript
-export interface SelectionRangeParams
-	extends WorkDoneProgressParams, PartialResultParams {
+export interface SelectionRangeParams extends WorkDoneProgressParams,
+	PartialResultParams {
 	/**
 	 * The text document.
 	 */
@@ -5782,27 +7231,891 @@
 ```
 
 _Response_:
+
 * result: `SelectionRange[] | null` defined as follows:
 
 ```typescript
 export interface SelectionRange {
-	/**
-	 * The [range](#Range) of this selection range.
-	 */
-	range: Range;
-
-	/**
-	 * The parent selection range containing this range.
-	 * Therefore `parent.range` must
-	 * contain `this.range`.
-	 */
-	parent?: SelectionRange;
+    /**
+     * The [range](#Range) of this selection range.
+     */
+    range: Range;
+    /**
+     * The parent selection range containing this range. Therefore
+	 * `parent.range` must contain `this.range`.
+     */
+    parent?: SelectionRange;
 }
 ```
 
 * partial result: `SelectionRange[]`
 * error: code and message set in case an exception happens during the 'textDocument/selectionRange' request
 
+#### <a href="#textDocument_prepareCallHierarchy" name="textDocument_prepareCallHierarchy" class="anchor">Prepare Call Hierarchy Request (:leftwards_arrow_with_hook:)</a>
+
+> *Since version 3.16.0*
+
+The call hierarchy request is sent from the client to the server to return a call hierarchy for the language element of given text document positions. The call hierarchy requests are executed in two steps:
+
+  1. first a call hierarchy item is resolved for the given text document position
+  1. for a call hierarchy item the incoming or outgoing call hierarchy items are resolved.
+
+_Client Capability_:
+
+* property name (optional): `textDocument.callHierarchy`
+* property type: `CallHierarchyClientCapabilities` defined as follows:
+
+```typescript
+interface CallHierarchyClientCapabilities {
+	/**
+	 * Whether implementation supports dynamic registration. If this is set to
+	 * `true` the client supports the new `(TextDocumentRegistrationOptions &
+	 * StaticRegistrationOptions)` return value for the corresponding server
+	 * capability as well.
+	 */
+	dynamicRegistration?: boolean;
+}
+```
+
+_Server Capability_:
+
+* property name (optional): `callHierarchyProvider`
+* property type: `boolean | CallHierarchyOptions | CallHierarchyRegistrationOptions` where `CallHierarchyOptions` is defined as follows:
+
+```typescript
+export interface CallHierarchyOptions extends WorkDoneProgressOptions {
+}
+```
+
+_Registration Options_: `CallHierarchyRegistrationOptions` defined as follows:
+
+```typescript
+export interface CallHierarchyRegistrationOptions extends
+	TextDocumentRegistrationOptions, CallHierarchyOptions,
+	StaticRegistrationOptions {
+}
+```
+
+_Request_:
+
+* method: 'textDocument/prepareCallHierarchy'
+* params: `CallHierarchyPrepareParams` defined as follows:
+
+```typescript
+export interface CallHierarchyPrepareParams extends TextDocumentPositionParams,
+	WorkDoneProgressParams {
+}
+```
+
+_Response_:
+
+* result: `CallHierarchyItem[] | null` defined as follows:
+
+```typescript
+export interface CallHierarchyItem {
+	/**
+	 * The name of this item.
+	 */
+	name: string;
+
+	/**
+	 * The kind of this item.
+	 */
+	kind: SymbolKind;
+
+	/**
+	 * Tags for this item.
+	 */
+	tags?: SymbolTag[];
+
+	/**
+	 * More detail for this item, e.g. the signature of a function.
+	 */
+	detail?: string;
+
+	/**
+	 * The resource identifier of this item.
+	 */
+	uri: DocumentUri;
+
+	/**
+	 * The range enclosing this symbol not including leading/trailing whitespace
+	 * but everything else, e.g. comments and code.
+	 */
+	range: Range;
+
+	/**
+	 * The range that should be selected and revealed when this symbol is being
+	 * picked, e.g. the name of a function. Must be contained by the
+	 * [`range`](#CallHierarchyItem.range).
+	 */
+	selectionRange: Range;
+
+	/**
+	 * A data entry field that is preserved between a call hierarchy prepare and
+	 * incoming calls or outgoing calls requests.
+	 */
+	data?: unknown;
+}
+```
+
+* error: code and message set in case an exception happens during the 'textDocument/prepareCallHierarchy' request
+
+#### <a href="#callHierarchy_incomingCalls" name="callHierarchy_incomingCalls" class="anchor">Call Hierarchy Incoming Calls (:leftwards_arrow_with_hook:)</a>
+
+> *Since version 3.16.0*
+
+The request is sent from the client to the server to resolve incoming calls for a given call hierarchy item. The request doesn't define its own client and server capabilities. It is only issued if a server registers for the [`textDocument/prepareCallHierarchy` request](#textDocument_prepareCallHierarchy).
+
+_Request_:
+
+* method: 'callHierarchy/incomingCalls'
+* params: `CallHierarchyIncomingCallsParams` defined as follows:
+
+```typescript
+export interface CallHierarchyIncomingCallsParams extends
+	WorkDoneProgressParams, PartialResultParams {
+	item: CallHierarchyItem;
+}
+```
+
+_Response_:
+
+* result: `CallHierarchyIncomingCall[] | null` defined as follows:
+
+```typescript
+export interface CallHierarchyIncomingCall {
+
+	/**
+	 * The item that makes the call.
+	 */
+	from: CallHierarchyItem;
+
+	/**
+	 * The ranges at which the calls appear. This is relative to the caller
+	 * denoted by [`this.from`](#CallHierarchyIncomingCall.from).
+	 */
+	fromRanges: Range[];
+}
+```
+
+* partial result: `CallHierarchyIncomingCall[]`
+* error: code and message set in case an exception happens during the 'callHierarchy/incomingCalls' request
+
+#### <a href="#callHierarchy_outgoingCalls" name="callHierarchy_outgoingCalls" class="anchor">Call Hierarchy Outgoing Calls (:leftwards_arrow_with_hook:)</a>
+
+> *Since version 3.16.0*
+
+The request is sent from the client to the server to resolve outgoing calls for a given call hierarchy item. The request doesn't define its own client and server capabilities. It is only issued if a server registers for the [`textDocument/prepareCallHierarchy` request](#textDocument_prepareCallHierarchy).
+
+_Request_:
+
+* method: 'callHierarchy/outgoingCalls'
+* params: `CallHierarchyOutgoingCallsParams` defined as follows:
+
+```typescript
+export interface CallHierarchyOutgoingCallsParams extends
+	WorkDoneProgressParams, PartialResultParams {
+	item: CallHierarchyItem;
+}
+```
+
+_Response_:
+
+* result: `CallHierarchyOutgoingCall[] | null` defined as follows:
+
+```typescript
+export interface CallHierarchyOutgoingCall {
+
+	/**
+	 * The item that is called.
+	 */
+	to: CallHierarchyItem;
+
+	/**
+	 * The range at which this item is called. This is the range relative to
+	 * the caller, e.g the item passed to `callHierarchy/outgoingCalls` request.
+	 */
+	fromRanges: Range[];
+}
+```
+
+* partial result: `CallHierarchyOutgoingCall[]`
+* error: code and message set in case an exception happens during the 'callHierarchy/outgoingCalls' request
+
+#### <a href="#textDocument_semanticTokens" name="textDocument_semanticTokens" class="anchor">Semantic Tokens (:leftwards_arrow_with_hook:)</a>
+
+> *Since version 3.16.0*
+
+The request is sent from the client to the server to resolve semantic tokens for a given file. Semantic tokens are used to add additional color information to a file that depends on language specific symbol information. A semantic token request usually produces a large result. The protocol therefore supports encoding tokens with numbers. In addition optional support for deltas is available.
+
+_General Concepts_
+
+Tokens are represented using one token type combined with n token modifiers. A token type is something like `class` or `function` and token modifiers are like `static` or `async`. The protocol defines a set of token types and modifiers but clients are allowed to extend these and announce the values they support in the corresponding client capability. The predefined values are:
+
+```typescript
+export enum SemanticTokenTypes {
+	namespace = 'namespace',
+	/**
+	 * Represents a generic type. Acts as a fallback for types which
+	 * can't be mapped to a specific type like class or enum.
+	 */
+	type = 'type',
+	class = 'class',
+	enum = 'enum',
+	interface = 'interface',
+	struct = 'struct',
+	typeParameter = 'typeParameter',
+	parameter = 'parameter',
+	variable = 'variable',
+	property = 'property',
+	enumMember = 'enumMember',
+	event = 'event',
+	function = 'function',
+	method = 'method',
+	macro = 'macro',
+	keyword = 'keyword',
+	modifier = 'modifier',
+	comment = 'comment',
+	string = 'string',
+	number = 'number',
+	regexp = 'regexp',
+	operator = 'operator'
+}
+
+export enum SemanticTokenModifiers {
+	declaration = 'declaration',
+	definition = 'definition',
+	readonly = 'readonly',
+	static = 'static',
+	deprecated = 'deprecated',
+	abstract = 'abstract',
+	async = 'async',
+	modification = 'modification',
+	documentation = 'documentation',
+	defaultLibrary = 'defaultLibrary'
+}
+```
+
+The protocol defines an additional token format capability to allow future extensions of the format. The only format that is currently specified is `relative` expressing that the tokens are described using relative positions (see Integer Encoding for Tokens below).
+
+```typescript
+export namespace TokenFormat {
+	export const Relative: 'relative' = 'relative';
+}
+
+export type TokenFormat = 'relative';
+```
+
+_Integer Encoding for Tokens_
+
+On the capability level types and modifiers are defined using strings. However the real encoding happens using numbers. The server therefore needs to let the client know which numbers it is using for which types and modifiers. They do so using a legend, which is defined as follows:
+
+```typescript
+export interface SemanticTokensLegend {
+	/**
+	 * The token types a server uses.
+	 */
+	tokenTypes: string[];
+
+	/**
+	 * The token modifiers a server uses.
+	 */
+	tokenModifiers: string[];
+}
+```
+
+Token types are looked up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Since a token type can have n modifiers, multiple token modifiers can be set by using bit flags,
+so a `tokenModifier` value of `3` is first viewed as binary `0b00000011`, which means `[tokenModifiers[0], tokenModifiers[1]]` because bits 0 and 1 are set.
+
+There are different ways how the position of a token can be expressed in a file. Absolute positions or relative positions. The protocol for the token format `relative` uses relative positions, because most tokens remain stable relative to each other when edits are made in a file. This simplifies the computation of a delta if a server supports it. So each token is represented using 5 integers. A specific token `i` in the file consists of the following array indices:
+
+- at index `5*i`   - `deltaLine`: token line number, relative to the previous token
+- at index `5*i+1` - `deltaStart`: token start character, relative to the previous token (relative to 0 or the previous token's start if they are on the same line)
+- at index `5*i+2` - `length`: the length of the token.
+- at index `5*i+3` - `tokenType`: will be looked up in `SemanticTokensLegend.tokenTypes`. We currently ask that `tokenType` < 65536.
+- at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticTokensLegend.tokenModifiers`
+
+Whether a token can span multiple lines is defined by the client capability `multilineTokenSupport`. The client capability `overlappingTokenSupport` defines whether tokens can overlap each other.
+
+Lets look at a concrete example which uses single line tokens without overlaps for encoding a file with 3 tokens in a number array. We start with absolute positions to demonstrate how they can easily be transformed into relative positions:
+
+```typescript
+{ line: 2, startChar:  5, length: 3, tokenType: "property",
+	tokenModifiers: ["private", "static"]
+},
+{ line: 2, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] },
+{ line: 5, startChar:  2, length: 7, tokenType: "class", tokenModifiers: [] }
+```
+
+First of all, a legend must be devised. This legend must be provided up-front on registration and capture all possible token types and modifiers. For the example we use this legend:
+
+```typescript
+{
+   tokenTypes: ['property', 'type', 'class'],
+   tokenModifiers: ['private', 'static']
+}
+```
+
+The first transformation step is to encode `tokenType` and `tokenModifiers` as integers using the legend. As said, token types are looked up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Multiple token modifiers can be set by using bit flags, so a `tokenModifier` value of `3` is first viewed as binary `0b00000011`, which means `[tokenModifiers[0], tokenModifiers[1]]` because bits 0 and 1 are set. Using this legend, the tokens now are:
+
+```typescript
+{ line: 2, startChar:  5, length: 3, tokenType: 0, tokenModifiers: 3 },
+{ line: 2, startChar: 10, length: 4, tokenType: 1, tokenModifiers: 0 },
+{ line: 5, startChar:  2, length: 7, tokenType: 2, tokenModifiers: 0 }
+```
+
+The next step is to represent each token relative to the previous token in the file. In this case, the second token is on the same line as the first token, so the `startChar` of the second token is made relative to the `startChar` of the first token, so it will be `10 - 5`. The third token is on a different line than the second token, so the `startChar` of the third token will not be altered:
+
+```typescript
+{ deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 0, tokenModifiers: 3 },
+{ deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 1, tokenModifiers: 0 },
+{ deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 2, tokenModifiers: 0 }
+```
+
+Finally, the last step is to inline each of the 5 fields for a token in a single array, which is a memory friendly representation:
+
+```typescript
+// 1st token,  2nd token,  3rd token
+[  2,5,3,0,3,  0,5,4,1,0,  3,2,7,2,0 ]
+```
+
+Now assume that the user types a new empty line at the beginning of the file which results in the following tokens in the file:
+
+```typescript
+{ line: 3, startChar:  5, length: 3, tokenType: "property",
+	tokenModifiers: ["private", "static"]
+},
+{ line: 3, startChar: 10, length: 4, tokenType: "type", tokenModifiers: [] },
+{ line: 6, startChar:  2, length: 7, tokenType: "class", tokenModifiers: [] }
+```
+
+Running the same transformations as above will result in the following number array:
+
+```typescript
+// 1st token,  2nd token,  3rd token
+[  3,5,3,0,3,  0,5,4,1,0,  3,2,7,2,0]
+```
+
+The delta is now expressed on these number arrays without any form of interpretation what these numbers mean. This is comparable to the text document edits send from the server to the client to modify the content of a file. Those are character based and don't make any assumption about the meaning of the characters. So `[  2,5,3,0,3,  0,5,4,1,0,  3,2,7,2,0 ]` can be transformed into `[  3,5,3,0,3,  0,5,4,1,0,  3,2,7,2,0]` using the following edit description: `{ start:  0, deleteCount: 1, data: [3] }` which tells the client to simply replace the first number (e.g. `2`) in the array with `3`.
+
+
+_Client Capability_:
+
+The following client capabilities are defined for semantic token requests sent from the client to the server:
+
+* property name (optional): `textDocument.semanticTokens`
+* property type: `SemanticTokensClientCapabilities` defined as follows:
+
+```typescript
+interface SemanticTokensClientCapabilities {
+	/**
+	 * Whether implementation supports dynamic registration. If this is set to
+	 * `true` the client supports the new `(TextDocumentRegistrationOptions &
+	 * StaticRegistrationOptions)` return value for the corresponding server
+	 * capability as well.
+	 */
+	dynamicRegistration?: boolean;
+
+	/**
+	 * Which requests the client supports and might send to the server
+	 * depending on the server's capability. Please note that clients might not
+	 * show semantic tokens or degrade some of the user experience if a range
+	 * or full request is advertised by the client but not provided by the
+	 * server. If for example the client capability `requests.full` and
+	 * `request.range` are both set to true but the server only provides a
+	 * range provider the client might not render a minimap correctly or might
+	 * even decide to not show any semantic tokens at all.
+	 */
+	requests: {
+		/**
+		 * The client will send the `textDocument/semanticTokens/range` request
+		 * if the server provides a corresponding handler.
+		 */
+		range?: boolean | {
+		};
+
+		/**
+		 * The client will send the `textDocument/semanticTokens/full` request
+		 * if the server provides a corresponding handler.
+		 */
+		full?: boolean | {
+			/**
+			 * The client will send the `textDocument/semanticTokens/full/delta`
+			 * request if the server provides a corresponding handler.
+			*/
+			delta?: boolean
+		}
+	}
+
+	/**
+	 * The token types that the client supports.
+	 */
+	tokenTypes: string[];
+
+	/**
+	 * The token modifiers that the client supports.
+	 */
+	tokenModifiers: string[];
+
+	/**
+	 * The formats the clients supports.
+	 */
+	formats: TokenFormat[];
+
+	/**
+	 * Whether the client supports tokens that can overlap each other.
+	 */
+	overlappingTokenSupport?: boolean;
+
+	/**
+	 * Whether the client supports tokens that can span multiple lines.
+	 */
+	multilineTokenSupport?: boolean;
+}
+```
+
+_Server Capability_:
+
+The following server capabilities are defined for semantic tokens:
+
+* property name (optional): `semanticTokensProvider`
+* property type: `SemanticTokensOptions | SemanticTokensRegistrationOptions` where `SemanticTokensOptions` is defined as follows:
+
+```typescript
+export interface SemanticTokensOptions extends WorkDoneProgressOptions {
+	/**
+	 * The legend used by the server
+	 */
+	legend: SemanticTokensLegend;
+
+	/**
+	 * Server supports providing semantic tokens for a specific range
+	 * of a document.
+	 */
+	range?: boolean | {
+	};
+
+	/**
+	 * Server supports providing semantic tokens for a full document.
+	 */
+	full?: boolean | {
+		/**
+		 * The server supports deltas for full documents.
+		 */
+		delta?: boolean;
+	}
+}
+```
+
+_Registration Options_: `SemanticTokensRegistrationOptions` defined as follows:
+
+```typescript
+export interface SemanticTokensRegistrationOptions extends
+	TextDocumentRegistrationOptions, SemanticTokensOptions,
+	StaticRegistrationOptions {
+}
+```
+
+Since the registration option handles range, full and delta requests the method used to register for semantic tokens requests is `textDocument/semanticTokens` and not one of the specific methods described below.
+
+**Requesting semantic tokens for a whole file**
+
+_Request_:
+
+* method: `textDocument/semanticTokens/full`
+* params: `SemanticTokensParams` defined as follows:
+
+```typescript
+export interface SemanticTokensParams extends WorkDoneProgressParams,
+	PartialResultParams {
+	/**
+	 * The text document.
+	 */
+	textDocument: TextDocumentIdentifier;
+}
+```
+
+_Response_:
+
+* result: `SemanticTokens | null` where `SemanticTokens` is defined as follows:
+
+```typescript
+export interface SemanticTokens {
+	/**
+	 * An optional result id. If provided and clients support delta updating
+	 * the client will include the result id in the next semantic token request.
+	 * A server can then instead of computing all semantic tokens again simply
+	 * send a delta.
+	 */
+	resultId?: string;
+
+	/**
+	 * The actual tokens.
+	 */
+	data: uinteger[];
+}
+```
+
+* partial result: `SemanticTokensPartialResult` defines as follows:
+
+```typescript
+export interface SemanticTokensPartialResult {
+	data: uinteger[];
+}
+```
+
+* error: code and message set in case an exception happens during the 'textDocument/semanticTokens/full' request
+
+**Requesting semantic token delta for a whole file**
+
+_Request_:
+
+* method: `textDocument/semanticTokens/full/delta`
+* params: `SemanticTokensDeltaParams` defined as follows:
+
+```typescript
+export interface SemanticTokensDeltaParams extends WorkDoneProgressParams,
+	PartialResultParams {
+	/**
+	 * The text document.
+	 */
+	textDocument: TextDocumentIdentifier;
+
+	/**
+	 * The result id of a previous response. The result Id can either point to
+	 * a full response or a delta response depending on what was received last.
+	 */
+	previousResultId: string;
+}
+```
+
+_Response_:
+
+* result: `SemanticTokens | SemanticTokensDelta | null` where `SemanticTokensDelta` is defined as follows:
+
+```typescript
+export interface SemanticTokensDelta {
+	readonly resultId?: string;
+	/**
+	 * The semantic token edits to transform a previous result into a new
+	 * result.
+	 */
+	edits: SemanticTokensEdit[];
+}
+
+export interface SemanticTokensEdit {
+	/**
+	 * The start offset of the edit.
+	 */
+	start: uinteger;
+
+	/**
+	 * The count of elements to remove.
+	 */
+	deleteCount: uinteger;
+
+	/**
+	 * The elements to insert.
+	 */
+	data?: uinteger[];
+}
+```
+
+* partial result: `SemanticTokensDeltaPartialResult` defines as follows:
+
+```typescript
+export interface SemanticTokensDeltaPartialResult {
+	edits: SemanticTokensEdit[]
+}
+```
+
+* error: code and message set in case an exception happens during the 'textDocument/semanticTokens/full/delta' request
+
+**Requesting semantic tokens for a range**
+
+When a user opens a file it can be beneficial to only compute the semantic tokens for the visible range (faster rendering of the tokens in the user interface). If a server can compute these tokens faster than for the whole file it can provide a handler for the `textDocument/semanticTokens/range` request to handle this case special. Please note that if a client also announces that it will send the `textDocument/semanticTokens/range` server should implement this request as well to allow for flicker free scrolling and semantic coloring of a minimap.
+
+_Request_:
+
+* method: `textDocument/semanticTokens/range`
+* params: `SemanticTokensRangeParams` defined as follows:
+
+```typescript
+export interface SemanticTokensRangeParams extends WorkDoneProgressParams,
+	PartialResultParams {
+	/**
+	 * The text document.
+	 */
+	textDocument: TextDocumentIdentifier;
+
+	/**
+	 * The range the semantic tokens are requested for.
+	 */
+	range: Range;
+}
+```
+
+_Response_:
+
+* result: `SemanticTokens | null` where `SemanticTokensDelta`
+* partial result: `SemanticTokensPartialResult`
+* error: code and message set in case an exception happens during the 'textDocument/semanticTokens/range' request
+
+**Requesting a refresh of all semantic tokens**
+
+The `workspace/semanticTokens/refresh` request is sent from the server to the client. Servers can use it to ask clients to refresh the editors for which this server provides semantic tokens. As a result the client should ask the server to recompute the semantic tokens for these editors. This is useful if a server detects a project wide configuration change which requires a re-calculation of all semantic tokens. Note that the client still has the freedom to delay the re-calculation of the semantic tokens if for example an editor is currently not visible.
+
+_Client Capability_:
+
+* property name (optional): `workspace.semanticTokens`
+* property type: `SemanticTokensWorkspaceClientCapabilities` defined as follows:
+
+```typescript
+export interface SemanticTokensWorkspaceClientCapabilities {
+	/**
+	 * Whether the client implementation supports a refresh request sent from
+	 * the server to the client.
+	 *
+	 * Note that this event is global and will force the client to refresh all
+	 * semantic tokens currently shown. It should be used with absolute care
+	 * and is useful for situation where a server for example detect a project
+	 * wide change that requires such a calculation.
+	 */
+	refreshSupport?: boolean;
+}
+```
+
+_Request_:
+
+* method: `workspace/semanticTokens/refresh`
+* params: none
+
+_Response_:
+
+* result: void
+* error: code and message set in case an exception happens during the 'workspace/semanticTokens/refresh' request
+
+#### <a href="#textDocument_linkedEditingRange" name="textDocument_linkedEditingRange" class="anchor">Linked Editing Range(:leftwards_arrow_with_hook:)</a>
+
+> *Since version 3.16.0*
+
+The linked editing request is sent from the client to the server to return for a given position in a document the range of the symbol at the position and all ranges that have the same content. Optionally a word pattern can be returned to describe valid contents. A rename to one of the ranges can be applied to all other ranges if the new content is valid. If no result-specific word pattern is provided, the word pattern from the client's language configuration is used.
+
+_Client Capabilities_:
+
+* property name (optional): `textDocument.linkedEditingRange`
+* property type: `LinkedEditingRangeClientCapabilities` defined as follows:
+
+```typescript
+export interface LinkedEditingRangeClientCapabilities {
+	/**
+	 * Whether implementation supports dynamic registration.
+	 * If this is set to `true` the client supports the new
+	 * `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
+	 * return value for the corresponding server capability as well.
+	 */
+	dynamicRegistration?: boolean;
+}
+```
+
+_Server Capability_:
+
+* property name (optional): `linkedEditingRangeProvider`
+* property type: `boolean` \| `LinkedEditingRangeOptions` \| `LinkedEditingRangeRegistrationOptions` defined as follows:
+
+```typescript
+export interface LinkedEditingRangeOptions extends WorkDoneProgressOptions {
+}
+```
+
+_Registration Options_: `LinkedEditingRangeRegistrationOptions` defined as follows:
+
+```typescript
+export interface LinkedEditingRangeRegistrationOptions extends
+	TextDocumentRegistrationOptions, LinkedEditingRangeOptions,
+	StaticRegistrationOptions {
+}
+```
+
+_Request_:
+
+* method: `textDocument/linkedEditingRange`
+* params: `LinkedEditingRangeParams` defined as follows:
+
+```typescript
+export interface LinkedEditingRangeParams extends TextDocumentPositionParams,
+	WorkDoneProgressParams {
+}
+```
+
+_Response_:
+
+* result: `LinkedEditingRanges` \| `null` defined as follows:
+
+```typescript
+export interface LinkedEditingRanges {
+	/**
+	 * A list of ranges that can be renamed together. The ranges must have
+	 * identical length and contain identical text content. The ranges cannot overlap.
+	 */
+	ranges: Range[];
+
+	/**
+	 * An optional word pattern (regular expression) that describes valid contents for
+	 * the given ranges. If no pattern is provided, the client configuration's word
+	 * pattern will be used.
+	 */
+	wordPattern?: string;
+}
+```
+* error: code and message set in case an exception happens during the 'textDocument/linkedEditingRange' request
+
+#### <a href="#textDocument_moniker" name="textDocument_moniker" class="anchor">Monikers (:leftwards_arrow_with_hook:)</a>
+
+> *Since version 3.16.0*
+
+Language Server Index Format (LSIF) introduced the concept of symbol monikers to help associate symbols across different indexes. This request adds capability for LSP server implementations to provide the same symbol moniker information given a text document position. Clients can utilize this method to get the moniker at the current location in a file user is editing and do further code navigation queries in other services that rely on LSIF indexes and link symbols together.
+
+The `textDocument/moniker` request is sent from the client to the server to get the symbol monikers for a given text document position. An array of Moniker types is returned as response to indicate possible monikers at the given location. If no monikers can be calculated, an empty array or `null` should be returned.
+
+_Client Capabilities_:
+
+* property name (optional): `textDocument.moniker`
+* property type: `MonikerClientCapabilities` defined as follows:
+
+```typescript
+interface MonikerClientCapabilities {
+	/**
+	 * Whether implementation supports dynamic registration. If this is set to
+	 * `true` the client supports the new `(TextDocumentRegistrationOptions &
+	 * StaticRegistrationOptions)` return value for the corresponding server
+	 * capability as well.
+	 */
+	dynamicRegistration?: boolean;
+}
+```
+
+_Server Capability_:
+
+* property name (optional): `monikerProvider`
+* property type: `boolean | MonikerOptions | MonikerRegistrationOptions`  is defined as follows:
+
+```typescript
+export interface MonikerOptions extends WorkDoneProgressOptions {
+}
+```
+
+_Registration Options_: `MonikerRegistrationOptions` defined as follows:
+
+```typescript
+export interface MonikerRegistrationOptions extends
+	TextDocumentRegistrationOptions, MonikerOptions {
+}
+```
+
+_Request_:
+
+* method: `textDocument/moniker`
+* params: `MonikerParams` defined as follows:
+
+```typescript
+export interface MonikerParams extends TextDocumentPositionParams,
+	WorkDoneProgressParams, PartialResultParams {
+}
+```
+
+_Response_:
+
+* result: `Moniker[] | null`
+* partial result: `Moniker[]`
+* error: code and message set in case an exception happens during the 'textDocument/moniker' request
+
+`Moniker` is defined as follows:
+
+```typescript
+/**
+  * Moniker uniqueness level to define scope of the moniker.
+  */
+export enum UniquenessLevel {
+	/**
+	 * The moniker is only unique inside a document
+	 */
+	document = 'document',
+
+	/**
+	 * The moniker is unique inside a project for which a dump got created
+	 */
+	project = 'project',
+
+	/**
+	 * The moniker is unique inside the group to which a project belongs
+	 */
+	group = 'group',
+
+	/**
+	 * The moniker is unique inside the moniker scheme.
+	 */
+	scheme = 'scheme',
+
+	/**
+	 * The moniker is globally unique
+	 */
+	global = 'global'
+}
+
+/**
+ * The moniker kind.
+ */
+export enum MonikerKind {
+	/**
+	 * The moniker represent a symbol that is imported into a project
+	 */
+	import = 'import',
+
+	/**
+	 * The moniker represents a symbol that is exported from a project
+	 */
+	export = 'export',
+
+	/**
+	 * The moniker represents a symbol that is local to a project (e.g. a local
+	 * variable of a function, a class not visible outside the project, ...)
+	 */
+	local = 'local'
+}
+
+/**
+ * Moniker definition to match LSIF 0.5 moniker definition.
+ */
+export interface Moniker {
+	/**
+	 * The scheme of the moniker. For example tsc or .Net
+	 */
+	scheme: string;
+
+	/**
+	 * The identifier of the moniker. The value is opaque in LSIF however
+	 * schema owners are allowed to define the structure if they want.
+	 */
+	identifier: string;
+
+	/**
+	 * The scope in which the moniker is unique
+	 */
+	unique: UniquenessLevel;
+
+	/**
+	 * The moniker kind if known.
+	 */
+	kind?: MonikerKind;
+}
+```
+
+##### Notes
+
+Server implementations of this method should ensure that the moniker calculation matches to those used in the corresponding LSIF implementation to ensure symbols can be associated correctly across IDE sessions and LSIF indexes.
+
 ### Implementation considerations
 
 Language servers usually run in a separate process and client communicate with them in an asynchronous fashion. Additionally clients usually allow users to interact with the source code even if request results are pending. We recommend the following implementation pattern to avoid that clients apply outdated response results:
@@ -5812,8 +8125,42 @@
 - if servers end up in an inconsistent state they should log this to the client using the `window/logMessage` request. If they can't recover from this the best they can do right now is to exit themselves. We are considering an [extension to the protocol](https://github.com/Microsoft/language-server-protocol/issues/646) that allows servers to request a restart on the client side.
 - if a client notices that a server exits unexpectedly, it should try to restart the server. However clients should be careful not to restart a crashing server endlessly. VS Code, for example, doesn't restart a server which has crashed 5 times in the last 180 seconds.
 
+Servers usually support different communication channels (e.g. stdio, pipes, ...). To easy the usage of servers in different clients it is highly recommended that a server implementation supports the following command line arguments to pick the communication channel:
+
+- **stdio**: uses stdio as the communication channel.
+- **pipe**: use pipes (Windows) or socket files (Linux, Mac) as the communication channel. The pipe / socket file name is passed as the next arg or with `--pipe=`.
+- **socket**: uses a socket as the communication channel. The port is passed as next arg or with `--port=`.
+- **node-ipc**: use node IPC communication between the client and the server. This is only support if both client and server run under node.
+
 ### <a href="#changeLog" name="changeLog" class="anchor">Change Log</a>
 
+#### <a href="#version_3_16_0" name="version_3_16_0" class="anchor">3.16.0 (12/14/2020)</a>
+
+* Add support for tracing.
+* Add semantic token support.
+* Add call hierarchy support.
+* Add client capability for resolving text edits on completion items.
+* Add support for client default behavior on renames.
+* Add support for insert and replace ranges on `CompletionItem`.
+* Add support for diagnostic code descriptions.
+* Add support for document symbol provider label.
+* Add support for tags on `SymbolInformation` and `DocumentSymbol`.
+* Add support for moniker request method.
+* Add support for code action `data` property.
+* Add support for code action `disabled` property.
+* Add support for code action resolve request.
+* Add support for diagnostic `data` property.
+* Add support for signature information `activeParameter` property.
+* Add support for `workspace/didCreateFiles` notifications and `workspace/willCreateFiles` requests.
+* Add support for `workspace/didRenameFiles` notifications and `workspace/willRenameFiles` requests.
+* Add support for `workspace/didDeleteFiles` notifications and `workspace/willDeleteFiles` requests.
+* Add client capability to signal whether the client normalizes line endings.
+* Add support to preserve additional attributes on `MessageActionItem`.
+* Add support to provide the clients locale in the initialize call.
+* Add support for opening and showing a document in the client user interface.
+* Add support for linked editing.
+* Add support for change annotations in text edits as well as in create file, rename file and delete file operations.
+
 #### <a href="#version_3_15_0" name="version_3_15_0" class="anchor">3.15.0 (01/14/2020)</a>
 
 * Add generic progress reporting support.
diff --git a/pkg/analysis_server/tool/lsp_spec/markdown.dart b/pkg/analysis_server/tool/lsp_spec/markdown.dart
index 3104598..fa9d47b 100644
--- a/pkg/analysis_server/tool/lsp_spec/markdown.dart
+++ b/pkg/analysis_server/tool/lsp_spec/markdown.dart
@@ -6,7 +6,7 @@
     r'''_(?:Notification|Request):?_:?(?:\r?\n)+\* method: ['`](.*?)[`'],?\r?\n''',
     multiLine: true);
 final _typeScriptBlockPattern =
-    RegExp(r'\B```typescript([\S\s]*?)\n```', multiLine: true);
+    RegExp(r'\B```typescript([\S\s]*?)\n\s*```', multiLine: true);
 
 List<String> extractMethodNames(String spec) {
   return _methodNamesPattern
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index 44f29f8..f0a54e8 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -76,6 +76,7 @@
     'Diagnostic': {
       'severity': 'DiagnosticSeverity',
       'code': 'String',
+      'data': 'object',
     },
     'TextDocumentSyncOptions': {
       'change': 'TextDocumentSyncKind',
@@ -89,6 +90,10 @@
     'CompletionItem': {
       'kind': 'CompletionItemKind',
       'data': 'CompletionItemResolutionInfo',
+      'textEdit': 'TextEdit',
+    },
+    'CallHierarchyItem': {
+      'data': 'object',
     },
     'DocumentHighlight': {
       'kind': 'DocumentHighlightKind',
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index 9e9d814..c657cab 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -287,6 +287,9 @@
   /// Ensures the next token is [type] and moves to the next, throwing [message]
   /// if not.
   Token _consume(TokenType type, String message) {
+    // Skip over any inline comments when looking for a specific token.
+    _match([TokenType.COMMENT]);
+
     if (_check(type)) {
       return _advance();
     }
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index f3f3dd1..5731163 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -412,16 +412,6 @@
   public void completion_getSuggestions(String file, int offset, GetSuggestionsConsumer consumer);
 
   /**
-   * {@code completion.listTokenDetails}
-   *
-   * Inspect analysis server's knowledge about all of a file's tokens including their lexeme, type,
-   * and what element kinds would have been appropriate for the token's program location.
-   *
-   * @param file The path to the file from which tokens should be returned.
-   */
-  public void completion_listTokenDetails(String file, ListTokenDetailsConsumer consumer);
-
-  /**
    * {@code completion.registerLibraryPaths}
    *
    * The client can make this request to express interest in certain libraries to receive completion
@@ -481,8 +471,12 @@
    *         file which does not exist, or which is not currently subject to analysis (e.g. because
    *         it is not associated with any analysis root specified to analysis.setAnalysisRoots), an
    *         error of type FILE_NOT_ANALYZED will be generated.
+   * @param inTestMode A flag indicating whether the bulk fixes are being run in test mode. The only
+   *         difference is that in test mode the fix processor will look for a configuration file
+   *         that can modify the content of the data file used to compute the fixes when data-driven
+   *         fixes are being considered. If this field is omitted the flag defaults to false.
    */
-  public void edit_bulkFixes(List<String> included, BulkFixesConsumer consumer);
+  public void edit_bulkFixes(List<String> included, boolean inTestMode, BulkFixesConsumer consumer);
 
   /**
    * {@code edit.dartfix}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java b/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
index 5fe4e7b..81be704 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
@@ -61,6 +61,8 @@
 
   public static final String TOP_LEVEL_VARIABLE = "TOP_LEVEL_VARIABLE";
 
+  public static final String TYPE_ALIAS = "TYPE_ALIAS";
+
   public static final String TYPE_PARAMETER = "TYPE_PARAMETER";
 
   public static final String UNIT_TEST_GROUP = "UNIT_TEST_GROUP";
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java b/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
index be9f538..3b8b236 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
@@ -21,6 +21,8 @@
 
   public static final String CLASS_BODY = "CLASS_BODY";
 
+  public static final String COMMENT = "COMMENT";
+
   public static final String DIRECTIVES = "DIRECTIVES";
 
   public static final String DOCUMENTATION_COMMENT = "DOCUMENTATION_COMMENT";
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
index 2b1e1d2..65f636a 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HighlightRegionType.java
@@ -195,6 +195,8 @@
 
   public static final String TOP_LEVEL_VARIABLE_DECLARATION = "TOP_LEVEL_VARIABLE_DECLARATION";
 
+  public static final String TYPE_ALIAS = "TYPE_ALIAS";
+
   public static final String TYPE_NAME_DYNAMIC = "TYPE_NAME_DYNAMIC";
 
   public static final String TYPE_PARAMETER = "TYPE_PARAMETER";
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/TokenDetails.java b/pkg/analysis_server/tool/spec/generated/java/types/TokenDetails.java
deleted file mode 100644
index 71b5f70..0000000
--- a/pkg/analysis_server/tool/spec/generated/java/types/TokenDetails.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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.
- *
- * This file has been automatically generated. Please do not edit it manually.
- * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
- */
-package org.dartlang.analysis.server.protocol;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import com.google.common.collect.Lists;
-import com.google.dart.server.utilities.general.JsonUtilities;
-import com.google.dart.server.utilities.general.ObjectUtilities;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-import java.util.ArrayList;
-import java.util.Iterator;
-import org.apache.commons.lang3.StringUtils;
-
-/**
- * A scanned token along with its inferred type information.
- *
- * @coverage dart.server.generated.types
- */
-@SuppressWarnings("unused")
-public class TokenDetails {
-
-  public static final TokenDetails[] EMPTY_ARRAY = new TokenDetails[0];
-
-  public static final List<TokenDetails> EMPTY_LIST = Lists.newArrayList();
-
-  /**
-   * The token's lexeme.
-   */
-  private final String lexeme;
-
-  /**
-   * A unique id for the type of the identifier. Omitted if the token is not an identifier in a
-   * reference position.
-   */
-  private final String type;
-
-  /**
-   * An indication of whether this token is in a declaration or reference position. (If no other
-   * purpose is found for this field then it should be renamed and converted to a boolean value.)
-   * Omitted if the token is not an identifier.
-   */
-  private final List<String> validElementKinds;
-
-  /**
-   * The offset of the first character of the token in the file which it originated from.
-   */
-  private final int offset;
-
-  /**
-   * Constructor for {@link TokenDetails}.
-   */
-  public TokenDetails(String lexeme, String type, List<String> validElementKinds, int offset) {
-    this.lexeme = lexeme;
-    this.type = type;
-    this.validElementKinds = validElementKinds;
-    this.offset = offset;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (obj instanceof TokenDetails) {
-      TokenDetails other = (TokenDetails) obj;
-      return
-        ObjectUtilities.equals(other.lexeme, lexeme) &&
-        ObjectUtilities.equals(other.type, type) &&
-        ObjectUtilities.equals(other.validElementKinds, validElementKinds) &&
-        other.offset == offset;
-    }
-    return false;
-  }
-
-  public static TokenDetails fromJson(JsonObject jsonObject) {
-    String lexeme = jsonObject.get("lexeme").getAsString();
-    String type = jsonObject.get("type") == null ? null : jsonObject.get("type").getAsString();
-    List<String> validElementKinds = jsonObject.get("validElementKinds") == null ? null : JsonUtilities.decodeStringList(jsonObject.get("validElementKinds").getAsJsonArray());
-    int offset = jsonObject.get("offset").getAsInt();
-    return new TokenDetails(lexeme, type, validElementKinds, offset);
-  }
-
-  public static List<TokenDetails> fromJsonArray(JsonArray jsonArray) {
-    if (jsonArray == null) {
-      return EMPTY_LIST;
-    }
-    ArrayList<TokenDetails> list = new ArrayList<TokenDetails>(jsonArray.size());
-    Iterator<JsonElement> iterator = jsonArray.iterator();
-    while (iterator.hasNext()) {
-      list.add(fromJson(iterator.next().getAsJsonObject()));
-    }
-    return list;
-  }
-
-  /**
-   * The token's lexeme.
-   */
-  public String getLexeme() {
-    return lexeme;
-  }
-
-  /**
-   * The offset of the first character of the token in the file which it originated from.
-   */
-  public int getOffset() {
-    return offset;
-  }
-
-  /**
-   * A unique id for the type of the identifier. Omitted if the token is not an identifier in a
-   * reference position.
-   */
-  public String getType() {
-    return type;
-  }
-
-  /**
-   * An indication of whether this token is in a declaration or reference position. (If no other
-   * purpose is found for this field then it should be renamed and converted to a boolean value.)
-   * Omitted if the token is not an identifier.
-   */
-  public List<String> getValidElementKinds() {
-    return validElementKinds;
-  }
-
-  @Override
-  public int hashCode() {
-    HashCodeBuilder builder = new HashCodeBuilder();
-    builder.append(lexeme);
-    builder.append(type);
-    builder.append(validElementKinds);
-    builder.append(offset);
-    return builder.toHashCode();
-  }
-
-  public JsonObject toJson() {
-    JsonObject jsonObject = new JsonObject();
-    jsonObject.addProperty("lexeme", lexeme);
-    if (type != null) {
-      jsonObject.addProperty("type", type);
-    }
-    if (validElementKinds != null) {
-      JsonArray jsonArrayValidElementKinds = new JsonArray();
-      for (String elt : validElementKinds) {
-        jsonArrayValidElementKinds.add(new JsonPrimitive(elt));
-      }
-      jsonObject.add("validElementKinds", jsonArrayValidElementKinds);
-    }
-    jsonObject.addProperty("offset", offset);
-    return jsonObject;
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    builder.append("[");
-    builder.append("lexeme=");
-    builder.append(lexeme + ", ");
-    builder.append("type=");
-    builder.append(type + ", ");
-    builder.append("validElementKinds=");
-    builder.append(StringUtils.join(validElementKinds, ", ") + ", ");
-    builder.append("offset=");
-    builder.append(offset);
-    builder.append("]");
-    return builder.toString();
-  }
-
-}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 57cd829..a2c3b0a 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.32.1</version>
+  <version>1.32.4</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -134,9 +134,25 @@
   ignoring the item or treating it with some default/fallback handling.
 </p>
 <h3>Changelog</h3>
+<h4>1.32.4</h4>
+<ul>
+  <li>Added <tt>ElementKind.TYPE_ALIAS</tt> and <tt>HighlightRegionType.TYPE_ALIAS</tt>
+    for non-function type aliases.</li>
+</ul>
+<h4>1.32.3</h4>
+<ul>
+  <li>Removed the experimental <tt>completion.listTokenDetails</tt> request and
+    the associated data types.</li>
+</ul>
+<h4>1.32.2</h4>
+<ul>
+  <li>Added <tt>FoldingKind.COMMENT</tt> for folding regions for blocks of
+    comments.</li>
+</ul>
 <h4>1.32.1</h4>
 <ul>
-  <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name completions in <tt>pubspec.yaml</tt></li>
+  <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name
+    completions in <tt>pubspec.yaml</tt>.</li>
 </ul>
 <h3>Domains</h3>
 <p>
@@ -1516,32 +1532,6 @@
       </field>
     </result>
   </request>
-  <request method="listTokenDetails" experimental="true">
-    <p>
-      Inspect analysis server's knowledge about all of a file's tokens including
-      their lexeme, type, and what element kinds would have been appropriate for
-      the token's program location.
-    </p>
-    <params>
-      <field name="file">
-        <ref>FilePath</ref>
-        <p>
-          The path to the file from which tokens should be returned.
-        </p>
-      </field>
-    </params>
-    <result>
-      <field name="tokens">
-        <list>
-          <ref>TokenDetails</ref>
-        </list>
-        <p>
-          A list of the file's scanned tokens including analysis information
-          about them.
-        </p>
-      </field>
-    </result>
-  </request>
   <notification event="results">
     <p>
       Reports the completion suggestions that should be presented
@@ -2191,6 +2181,18 @@
           <tt>FILE_NOT_ANALYZED</tt> will be generated.
         </p>
       </field>
+      <field name="inTestMode" optional="true">
+        <ref>bool</ref>
+        <p>
+          A flag indicating whether the bulk fixes are being run in test mode.
+          The only difference is that in test mode the fix processor will look
+          for a configuration file that can modify the content of the data file
+          used to compute the fixes when data-driven fixes are being considered.
+        </p>
+        <p>
+          If this field is omitted the flag defaults to <tt>false</tt>.
+        </p>
+      </field>
     </params>
     <result>
       <field name="edits">
@@ -4206,44 +4208,6 @@
       <value><code>INTERFACE</code></value>
     </enum>
   </type>
-  <type name="TokenDetails" experimental="true">
-    <p>
-      A scanned token along with its inferred type information.
-    </p>
-    <object>
-      <field name="lexeme">
-        <ref>String</ref>
-        <p>
-          The token's lexeme.
-        </p>
-      </field>
-      <field name="type" optional="true">
-        <ref>String</ref>
-        <p>
-          A unique id for the type of the identifier.
-          Omitted if the token is not an identifier in a reference position.
-        </p>
-      </field>
-      <field name="validElementKinds" optional="true">
-        <list>
-          <ref>String</ref>
-        </list>
-        <p>
-          An indication of whether this token is in a declaration or reference
-          position. (If no other purpose is found for this field then it should
-          be renamed and converted to a boolean value.)
-          Omitted if the token is not an identifier.
-        </p>
-      </field>
-      <field name="offset">
-        <ref>int</ref>
-        <p>
-          The offset of the first character of the token in the file which it
-          originated from.
-        </p>
-      </field>
-    </object>
-  </type>
   <type name="ExecutionService">
     <p>
       An enumeration of the services provided by the execution
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 346847c..cb6ab86 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -1718,6 +1718,7 @@
 ///   PREFIX
 ///   SETTER
 ///   TOP_LEVEL_VARIABLE
+///   TYPE_ALIAS
 ///   TYPE_PARAMETER
 ///   UNIT_TEST_GROUP
 ///   UNIT_TEST_TEST
@@ -1776,6 +1777,8 @@
   static const ElementKind TOP_LEVEL_VARIABLE =
       ElementKind._('TOP_LEVEL_VARIABLE');
 
+  static const ElementKind TYPE_ALIAS = ElementKind._('TYPE_ALIAS');
+
   static const ElementKind TYPE_PARAMETER = ElementKind._('TYPE_PARAMETER');
 
   static const ElementKind UNIT_TEST_GROUP = ElementKind._('UNIT_TEST_GROUP');
@@ -1809,6 +1812,7 @@
     PREFIX,
     SETTER,
     TOP_LEVEL_VARIABLE,
+    TYPE_ALIAS,
     TYPE_PARAMETER,
     UNIT_TEST_GROUP,
     UNIT_TEST_TEST,
@@ -1868,6 +1872,8 @@
         return SETTER;
       case 'TOP_LEVEL_VARIABLE':
         return TOP_LEVEL_VARIABLE;
+      case 'TYPE_ALIAS':
+        return TYPE_ALIAS;
       case 'TYPE_PARAMETER':
         return TYPE_PARAMETER;
       case 'UNIT_TEST_GROUP':
@@ -1904,6 +1910,7 @@
 ///   ANNOTATIONS
 ///   BLOCK
 ///   CLASS_BODY
+///   COMMENT
 ///   DIRECTIVES
 ///   DOCUMENTATION_COMMENT
 ///   FILE_HEADER
@@ -1920,6 +1927,8 @@
 
   static const FoldingKind CLASS_BODY = FoldingKind._('CLASS_BODY');
 
+  static const FoldingKind COMMENT = FoldingKind._('COMMENT');
+
   static const FoldingKind DIRECTIVES = FoldingKind._('DIRECTIVES');
 
   static const FoldingKind DOCUMENTATION_COMMENT =
@@ -1938,6 +1947,7 @@
     ANNOTATIONS,
     BLOCK,
     CLASS_BODY,
+    COMMENT,
     DIRECTIVES,
     DOCUMENTATION_COMMENT,
     FILE_HEADER,
@@ -1959,6 +1969,8 @@
         return BLOCK;
       case 'CLASS_BODY':
         return CLASS_BODY;
+      case 'COMMENT':
+        return COMMENT;
       case 'DIRECTIVES':
         return DIRECTIVES;
       case 'DOCUMENTATION_COMMENT':
@@ -2285,6 +2297,7 @@
 ///   TOP_LEVEL_SETTER_DECLARATION
 ///   TOP_LEVEL_SETTER_REFERENCE
 ///   TOP_LEVEL_VARIABLE_DECLARATION
+///   TYPE_ALIAS
 ///   TYPE_NAME_DYNAMIC
 ///   TYPE_PARAMETER
 ///   UNRESOLVED_INSTANCE_MEMBER_REFERENCE
@@ -2506,6 +2519,9 @@
   static const HighlightRegionType TOP_LEVEL_VARIABLE_DECLARATION =
       HighlightRegionType._('TOP_LEVEL_VARIABLE_DECLARATION');
 
+  static const HighlightRegionType TYPE_ALIAS =
+      HighlightRegionType._('TYPE_ALIAS');
+
   static const HighlightRegionType TYPE_NAME_DYNAMIC =
       HighlightRegionType._('TYPE_NAME_DYNAMIC');
 
@@ -2589,6 +2605,7 @@
     TOP_LEVEL_SETTER_DECLARATION,
     TOP_LEVEL_SETTER_REFERENCE,
     TOP_LEVEL_VARIABLE_DECLARATION,
+    TYPE_ALIAS,
     TYPE_NAME_DYNAMIC,
     TYPE_PARAMETER,
     UNRESOLVED_INSTANCE_MEMBER_REFERENCE,
@@ -2740,6 +2757,8 @@
         return TOP_LEVEL_SETTER_REFERENCE;
       case 'TOP_LEVEL_VARIABLE_DECLARATION':
         return TOP_LEVEL_VARIABLE_DECLARATION;
+      case 'TYPE_ALIAS':
+        return TYPE_ALIAS;
       case 'TYPE_NAME_DYNAMIC':
         return TYPE_NAME_DYNAMIC;
       case 'TYPE_PARAMETER':
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 7636ffc..9b566ba 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.32.1';
+const String PROTOCOL_VERSION = '1.32.4';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -145,9 +145,6 @@
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_ID = 'id';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_LABEL = 'label';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_OFFSET = 'offset';
-const String COMPLETION_REQUEST_LIST_TOKEN_DETAILS =
-    'completion.listTokenDetails';
-const String COMPLETION_REQUEST_LIST_TOKEN_DETAILS_FILE = 'file';
 const String COMPLETION_REQUEST_REGISTER_LIBRARY_PATHS =
     'completion.registerLibraryPaths';
 const String COMPLETION_REQUEST_REGISTER_LIBRARY_PATHS_PATHS = 'paths';
@@ -159,13 +156,13 @@
 const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_CHANGE = 'change';
 const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_COMPLETION =
     'completion';
-const String COMPLETION_RESPONSE_LIST_TOKEN_DETAILS_TOKENS = 'tokens';
 const String DIAGNOSTIC_REQUEST_GET_DIAGNOSTICS = 'diagnostic.getDiagnostics';
 const String DIAGNOSTIC_REQUEST_GET_SERVER_PORT = 'diagnostic.getServerPort';
 const String DIAGNOSTIC_RESPONSE_GET_DIAGNOSTICS_CONTEXTS = 'contexts';
 const String DIAGNOSTIC_RESPONSE_GET_SERVER_PORT_PORT = 'port';
 const String EDIT_REQUEST_BULK_FIXES = 'edit.bulkFixes';
 const String EDIT_REQUEST_BULK_FIXES_INCLUDED = 'included';
+const String EDIT_REQUEST_BULK_FIXES_IN_TEST_MODE = 'inTestMode';
 const String EDIT_REQUEST_DARTFIX = 'edit.dartfix';
 const String EDIT_REQUEST_DARTFIX_EXCLUDED_FIXES = 'excludedFixes';
 const String EDIT_REQUEST_DARTFIX_INCLUDED = 'included';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index b9466f0..e5dd041 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -5886,168 +5886,6 @@
   }
 }
 
-/// completion.listTokenDetails params
-///
-/// {
-///   "file": FilePath
-/// }
-///
-/// Clients may not extend, implement or mix-in this class.
-class CompletionListTokenDetailsParams implements RequestParams {
-  String _file;
-
-  /// The path to the file from which tokens should be returned.
-  String get file => _file;
-
-  /// The path to the file from which tokens should be returned.
-  set file(String value) {
-    assert(value != null);
-    _file = value;
-  }
-
-  CompletionListTokenDetailsParams(String file) {
-    this.file = file;
-  }
-
-  factory CompletionListTokenDetailsParams.fromJson(
-      JsonDecoder jsonDecoder, String jsonPath, Object json) {
-    json ??= {};
-    if (json is Map) {
-      String file;
-      if (json.containsKey('file')) {
-        file = jsonDecoder.decodeString(jsonPath + '.file', json['file']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'file');
-      }
-      return CompletionListTokenDetailsParams(file);
-    } else {
-      throw jsonDecoder.mismatch(
-          jsonPath, 'completion.listTokenDetails params', json);
-    }
-  }
-
-  factory CompletionListTokenDetailsParams.fromRequest(Request request) {
-    return CompletionListTokenDetailsParams.fromJson(
-        RequestDecoder(request), 'params', request.params);
-  }
-
-  @override
-  Map<String, dynamic> toJson() {
-    var result = <String, dynamic>{};
-    result['file'] = file;
-    return result;
-  }
-
-  @override
-  Request toRequest(String id) {
-    return Request(id, 'completion.listTokenDetails', toJson());
-  }
-
-  @override
-  String toString() => json.encode(toJson());
-
-  @override
-  bool operator ==(other) {
-    if (other is CompletionListTokenDetailsParams) {
-      return file == other.file;
-    }
-    return false;
-  }
-
-  @override
-  int get hashCode {
-    var hash = 0;
-    hash = JenkinsSmiHash.combine(hash, file.hashCode);
-    return JenkinsSmiHash.finish(hash);
-  }
-}
-
-/// completion.listTokenDetails result
-///
-/// {
-///   "tokens": List<TokenDetails>
-/// }
-///
-/// Clients may not extend, implement or mix-in this class.
-class CompletionListTokenDetailsResult implements ResponseResult {
-  List<TokenDetails> _tokens;
-
-  /// A list of the file's scanned tokens including analysis information about
-  /// them.
-  List<TokenDetails> get tokens => _tokens;
-
-  /// A list of the file's scanned tokens including analysis information about
-  /// them.
-  set tokens(List<TokenDetails> value) {
-    assert(value != null);
-    _tokens = value;
-  }
-
-  CompletionListTokenDetailsResult(List<TokenDetails> tokens) {
-    this.tokens = tokens;
-  }
-
-  factory CompletionListTokenDetailsResult.fromJson(
-      JsonDecoder jsonDecoder, String jsonPath, Object json) {
-    json ??= {};
-    if (json is Map) {
-      List<TokenDetails> tokens;
-      if (json.containsKey('tokens')) {
-        tokens = jsonDecoder.decodeList(
-            jsonPath + '.tokens',
-            json['tokens'],
-            (String jsonPath, Object json) =>
-                TokenDetails.fromJson(jsonDecoder, jsonPath, json));
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'tokens');
-      }
-      return CompletionListTokenDetailsResult(tokens);
-    } else {
-      throw jsonDecoder.mismatch(
-          jsonPath, 'completion.listTokenDetails result', json);
-    }
-  }
-
-  factory CompletionListTokenDetailsResult.fromResponse(Response response) {
-    return CompletionListTokenDetailsResult.fromJson(
-        ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
-        'result',
-        response.result);
-  }
-
-  @override
-  Map<String, dynamic> toJson() {
-    var result = <String, dynamic>{};
-    result['tokens'] =
-        tokens.map((TokenDetails value) => value.toJson()).toList();
-    return result;
-  }
-
-  @override
-  Response toResponse(String id) {
-    return Response(id, result: toJson());
-  }
-
-  @override
-  String toString() => json.encode(toJson());
-
-  @override
-  bool operator ==(other) {
-    if (other is CompletionListTokenDetailsResult) {
-      return listEqual(
-          tokens, other.tokens, (TokenDetails a, TokenDetails b) => a == b);
-    }
-    return false;
-  }
-
-  @override
-  int get hashCode {
-    var hash = 0;
-    hash = JenkinsSmiHash.combine(hash, tokens.hashCode);
-    return JenkinsSmiHash.finish(hash);
-  }
-}
-
 /// completion.registerLibraryPaths params
 ///
 /// {
@@ -7301,12 +7139,15 @@
 ///
 /// {
 ///   "included": List<FilePath>
+///   "inTestMode": optional bool
 /// }
 ///
 /// Clients may not extend, implement or mix-in this class.
 class EditBulkFixesParams implements RequestParams {
   List<String> _included;
 
+  bool _inTestMode;
+
   /// A list of the files and directories for which edits should be suggested.
   ///
   /// If a request is made with a path that is invalid, e.g. is not absolute
@@ -7330,8 +7171,27 @@
     _included = value;
   }
 
-  EditBulkFixesParams(List<String> included) {
+  /// A flag indicating whether the bulk fixes are being run in test mode. The
+  /// only difference is that in test mode the fix processor will look for a
+  /// configuration file that can modify the content of the data file used to
+  /// compute the fixes when data-driven fixes are being considered.
+  ///
+  /// If this field is omitted the flag defaults to false.
+  bool get inTestMode => _inTestMode;
+
+  /// A flag indicating whether the bulk fixes are being run in test mode. The
+  /// only difference is that in test mode the fix processor will look for a
+  /// configuration file that can modify the content of the data file used to
+  /// compute the fixes when data-driven fixes are being considered.
+  ///
+  /// If this field is omitted the flag defaults to false.
+  set inTestMode(bool value) {
+    _inTestMode = value;
+  }
+
+  EditBulkFixesParams(List<String> included, {bool inTestMode}) {
     this.included = included;
+    this.inTestMode = inTestMode;
   }
 
   factory EditBulkFixesParams.fromJson(
@@ -7345,7 +7205,12 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'included');
       }
-      return EditBulkFixesParams(included);
+      bool inTestMode;
+      if (json.containsKey('inTestMode')) {
+        inTestMode = jsonDecoder.decodeBool(
+            jsonPath + '.inTestMode', json['inTestMode']);
+      }
+      return EditBulkFixesParams(included, inTestMode: inTestMode);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'edit.bulkFixes params', json);
     }
@@ -7360,6 +7225,9 @@
   Map<String, dynamic> toJson() {
     var result = <String, dynamic>{};
     result['included'] = included;
+    if (inTestMode != null) {
+      result['inTestMode'] = inTestMode;
+    }
     return result;
   }
 
@@ -7375,7 +7243,8 @@
   bool operator ==(other) {
     if (other is EditBulkFixesParams) {
       return listEqual(
-          included, other.included, (String a, String b) => a == b);
+              included, other.included, (String a, String b) => a == b) &&
+          inTestMode == other.inTestMode;
     }
     return false;
   }
@@ -7384,6 +7253,7 @@
   int get hashCode {
     var hash = 0;
     hash = JenkinsSmiHash.combine(hash, included.hashCode);
+    hash = JenkinsSmiHash.combine(hash, inTestMode.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
@@ -21313,151 +21183,6 @@
   }
 }
 
-/// TokenDetails
-///
-/// {
-///   "lexeme": String
-///   "type": optional String
-///   "validElementKinds": optional List<String>
-///   "offset": int
-/// }
-///
-/// Clients may not extend, implement or mix-in this class.
-class TokenDetails implements HasToJson {
-  String _lexeme;
-
-  String _type;
-
-  List<String> _validElementKinds;
-
-  int _offset;
-
-  /// The token's lexeme.
-  String get lexeme => _lexeme;
-
-  /// The token's lexeme.
-  set lexeme(String value) {
-    assert(value != null);
-    _lexeme = value;
-  }
-
-  /// A unique id for the type of the identifier. Omitted if the token is not
-  /// an identifier in a reference position.
-  String get type => _type;
-
-  /// A unique id for the type of the identifier. Omitted if the token is not
-  /// an identifier in a reference position.
-  set type(String value) {
-    _type = value;
-  }
-
-  /// An indication of whether this token is in a declaration or reference
-  /// position. (If no other purpose is found for this field then it should be
-  /// renamed and converted to a boolean value.) Omitted if the token is not an
-  /// identifier.
-  List<String> get validElementKinds => _validElementKinds;
-
-  /// An indication of whether this token is in a declaration or reference
-  /// position. (If no other purpose is found for this field then it should be
-  /// renamed and converted to a boolean value.) Omitted if the token is not an
-  /// identifier.
-  set validElementKinds(List<String> value) {
-    _validElementKinds = value;
-  }
-
-  /// The offset of the first character of the token in the file which it
-  /// originated from.
-  int get offset => _offset;
-
-  /// The offset of the first character of the token in the file which it
-  /// originated from.
-  set offset(int value) {
-    assert(value != null);
-    _offset = value;
-  }
-
-  TokenDetails(String lexeme, int offset,
-      {String type, List<String> validElementKinds}) {
-    this.lexeme = lexeme;
-    this.type = type;
-    this.validElementKinds = validElementKinds;
-    this.offset = offset;
-  }
-
-  factory TokenDetails.fromJson(
-      JsonDecoder jsonDecoder, String jsonPath, Object json) {
-    json ??= {};
-    if (json is Map) {
-      String lexeme;
-      if (json.containsKey('lexeme')) {
-        lexeme = jsonDecoder.decodeString(jsonPath + '.lexeme', json['lexeme']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'lexeme');
-      }
-      String type;
-      if (json.containsKey('type')) {
-        type = jsonDecoder.decodeString(jsonPath + '.type', json['type']);
-      }
-      List<String> validElementKinds;
-      if (json.containsKey('validElementKinds')) {
-        validElementKinds = jsonDecoder.decodeList(
-            jsonPath + '.validElementKinds',
-            json['validElementKinds'],
-            jsonDecoder.decodeString);
-      }
-      int offset;
-      if (json.containsKey('offset')) {
-        offset = jsonDecoder.decodeInt(jsonPath + '.offset', json['offset']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'offset');
-      }
-      return TokenDetails(lexeme, offset,
-          type: type, validElementKinds: validElementKinds);
-    } else {
-      throw jsonDecoder.mismatch(jsonPath, 'TokenDetails', json);
-    }
-  }
-
-  @override
-  Map<String, dynamic> toJson() {
-    var result = <String, dynamic>{};
-    result['lexeme'] = lexeme;
-    if (type != null) {
-      result['type'] = type;
-    }
-    if (validElementKinds != null) {
-      result['validElementKinds'] = validElementKinds;
-    }
-    result['offset'] = offset;
-    return result;
-  }
-
-  @override
-  String toString() => json.encode(toJson());
-
-  @override
-  bool operator ==(other) {
-    if (other is TokenDetails) {
-      return lexeme == other.lexeme &&
-          type == other.type &&
-          listEqual(validElementKinds, other.validElementKinds,
-              (String a, String b) => a == b) &&
-          offset == other.offset;
-    }
-    return false;
-  }
-
-  @override
-  int get hashCode {
-    var hash = 0;
-    hash = JenkinsSmiHash.combine(hash, lexeme.hashCode);
-    hash = JenkinsSmiHash.combine(hash, type.hashCode);
-    hash = JenkinsSmiHash.combine(hash, validElementKinds.hashCode);
-    hash = JenkinsSmiHash.combine(hash, offset.hashCode);
-    return JenkinsSmiHash.finish(hash);
-  }
-}
-
 /// TypeHierarchyItem
 ///
 /// {
diff --git a/pkg/analysis_server_client/test/verify_sorted_test.dart b/pkg/analysis_server_client/test/verify_sorted_test.dart
index 79d7299..5a19d51 100644
--- a/pkg/analysis_server_client/test/verify_sorted_test.dart
+++ b/pkg/analysis_server_client/test/verify_sorted_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 'dart:io';
-
 import 'package:analysis_server/src/services/correction/sort_members.dart';
 import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/dart/analysis/results.dart';
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 227a18e..a8e8b53 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 0.41.2-dev
+* Deprecated `FunctionTypeAliasElement.function`.
+  Use `TypeAliasElement.aliasedElement` instead.
+* Widened the dependency on package:crypto to include version 3.0.0.
+* Deprecated `CompilationUnitElement.functionTypeAliases`.
+  Use `CompilationUnitElement.typeAliases` instead.
+* Added `AnalysisContext.sdkRoot`.
+
 ## 0.41.1
 * Updated `PackageBuildWorkspace` that supports `package:build` to stop
   at the first directory with `pubspec.yaml`, and don't try to go up
diff --git a/pkg/analyzer/example/analyze.dart b/pkg/analyzer/example/analyze.dart
new file mode 100644
index 0000000..d9d5cb3
--- /dev/null
+++ b/pkg/analyzer/example/analyze.dart
@@ -0,0 +1,46 @@
+// 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 'dart:io';
+
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+
+/// A simple example of using the AnalysisContextCollection API.
+void main(List<String> args) async {
+  var entity = Directory.current;
+  if (args.isNotEmpty) {
+    String arg = args.first;
+    entity = FileSystemEntity.isDirectorySync(arg) ? Directory(arg) : File(arg);
+  }
+
+  var issueCount = 0;
+  final collection = AnalysisContextCollection(
+      includedPaths: [entity.absolute.path],
+      resourceProvider: PhysicalResourceProvider.INSTANCE);
+
+  // Often one context is returned, but depending on the project structure we
+  // can see multiple contexts.
+  for (final context in collection.contexts) {
+    print('Analyzing ${context.contextRoot.root.path} ...');
+
+    for (final filePath in context.contextRoot.analyzedFiles()) {
+      if (!filePath.endsWith('.dart')) {
+        continue;
+      }
+
+      final errorsResult = await context.currentSession.getErrors(filePath);
+      for (final error in errorsResult.errors) {
+        if (error.errorCode.type != ErrorType.TODO) {
+          print(
+              '  \u001b[1m${error.source.shortName}\u001b[0m ${error.message}');
+          issueCount++;
+        }
+      }
+    }
+  }
+
+  print('$issueCount issues found.');
+}
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_context.dart b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
index 37035e4..97ff59c 100644
--- a/pkg/analyzer/lib/dart/analysis/analysis_context.dart
+++ b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/analysis/context_root.dart';
 import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 
@@ -27,6 +28,10 @@
   /// Return the currently active analysis session.
   AnalysisSession get currentSession;
 
+  /// The root directory of the SDK against which files of this context are
+  /// analyzed, or `null` if the SDK is not directory based.
+  Folder get sdkRoot;
+
   /// Return the workspace for containing the context root.
   Workspace get workspace;
 }
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 44d3ec9..5f38ebb 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -391,6 +391,7 @@
 
   /// Return a list containing all of the function type aliases contained in
   /// this compilation unit.
+  @Deprecated('Use typeAliases instead')
   List<FunctionTypeAliasElement> get functionTypeAliases;
 
   /// Return `true` if this compilation unit defines a top-level function named
@@ -993,6 +994,8 @@
 
   R visitTopLevelVariableElement(TopLevelVariableElement element);
 
+  R visitTypeAliasElement(TypeAliasElement element);
+
   R visitTypeParameterElement(TypeParameterElement element);
 }
 
@@ -1167,6 +1170,7 @@
 abstract class FunctionTypeAliasElement implements TypeAliasElement {
   /// Return the generic function type element representing the generic function
   /// type on the right side of the equals.
+  @Deprecated('Use aliasedElement instead')
   GenericFunctionTypeElement get function;
 
   @override
diff --git a/pkg/analyzer/lib/dart/element/visitor.dart b/pkg/analyzer/lib/dart/element/visitor.dart
index 70552ed..f6256b8 100644
--- a/pkg/analyzer/lib/dart/element/visitor.dart
+++ b/pkg/analyzer/lib/dart/element/visitor.dart
@@ -176,6 +176,9 @@
       visitPropertyInducingElement(element);
 
   @override
+  R visitTypeAliasElement(TypeAliasElement element) => visitElement(element);
+
+  @override
   R visitTypeParameterElement(TypeParameterElement element) =>
       visitElement(element);
 
@@ -318,6 +321,12 @@
   }
 
   @override
+  R visitTypeAliasElement(TypeAliasElement element) {
+    element.visitChildren(this);
+    return null;
+  }
+
+  @override
   R visitTypeParameterElement(TypeParameterElement element) {
     element.visitChildren(this);
     return null;
@@ -396,6 +405,9 @@
   R visitTopLevelVariableElement(TopLevelVariableElement element) => null;
 
   @override
+  R visitTypeAliasElement(TypeAliasElement element) => null;
+
+  @override
   R visitTypeParameterElement(TypeParameterElement element) => null;
 }
 
@@ -478,6 +490,9 @@
       _throw(element);
 
   @override
+  R visitTypeAliasElement(TypeAliasElement element) => _throw(element);
+
+  @override
   R visitTypeParameterElement(TypeParameterElement element) => _throw(element);
 
   R _throw(Element element) {
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 2357561..2bee3dc 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -5,6 +5,7 @@
 import 'dart:collection';
 
 import 'package:_fe_analyzer_shared/src/base/errors.dart';
+import 'package:_fe_analyzer_shared/src/messages/codes.dart';
 import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/listener.dart';
@@ -69,7 +70,6 @@
   CompileTimeErrorCode.AMBIGUOUS_IMPORT,
   CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
   CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER,
-  CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
   CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
   CompileTimeErrorCode.ASSERT_IN_REDIRECTING_CONSTRUCTOR,
   CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
@@ -222,11 +222,11 @@
   CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC,
   CompileTimeErrorCode.INSTANTIATE_ABSTRACT_CLASS,
   CompileTimeErrorCode.INSTANTIATE_ENUM,
+  CompileTimeErrorCode.INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
   CompileTimeErrorCode.INTEGER_LITERAL_IMPRECISE_AS_DOUBLE,
   CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE,
   CompileTimeErrorCode.INVALID_ANNOTATION,
   CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY,
-  CompileTimeErrorCode.INVALID_ANNOTATION_GETTER,
   CompileTimeErrorCode.INVALID_ASSIGNMENT,
   CompileTimeErrorCode.INVALID_CAST_FUNCTION,
   CompileTimeErrorCode.INVALID_CAST_FUNCTION_EXPR,
@@ -240,6 +240,7 @@
   CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME,
   CompileTimeErrorCode.INVALID_EXTENSION_ARGUMENT_COUNT,
   CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS,
+  CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE,
   CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE,
   CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR,
   CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
@@ -374,6 +375,7 @@
   CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR,
   CompileTimeErrorCode.REDIRECT_TO_NON_CLASS,
   CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR,
+  CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
   CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
   CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH,
   CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR,
@@ -403,7 +405,15 @@
   CompileTimeErrorCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
   CompileTimeErrorCode.TYPE_TEST_WITH_NON_TYPE,
   CompileTimeErrorCode.TYPE_TEST_WITH_UNDEFINED_NAME,
+  CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE,
+  CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+  CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE,
+  CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
   CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE,
+  CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+  CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR,
+  CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD,
+  CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH,
   CompileTimeErrorCode.UNDEFINED_ANNOTATION,
   CompileTimeErrorCode.UNDEFINED_CLASS,
   CompileTimeErrorCode.UNDEFINED_CLASS_BOOLEAN,
@@ -448,6 +458,8 @@
   CompileTimeErrorCode.YIELD_IN_NON_GENERATOR,
   CompileTimeErrorCode.YIELD_OF_INVALID_TYPE,
   FfiCode.ANNOTATION_ON_POINTER_FIELD,
+  FfiCode.EMPTY_STRUCT,
+  FfiCode.EMPTY_STRUCT_WARNING,
   FfiCode.EXTRA_ANNOTATION_ON_STRUCT_FIELD,
   FfiCode.FIELD_IN_STRUCT_WITH_INITIALIZER,
   FfiCode.FIELD_INITIALIZER_IN_STRUCT,
@@ -461,6 +473,7 @@
   FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
   FfiCode.MUST_BE_A_SUBTYPE,
   FfiCode.NON_CONSTANT_TYPE_ARGUMENT,
+  FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING,
   FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER,
   FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS,
   FfiCode.SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS,
@@ -539,7 +552,6 @@
   HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR,
   HintCode.NULL_CHECK_ALWAYS_FAILS,
   HintCode.NULLABLE_TYPE_IN_CATCH_CLAUSE,
-  HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE,
   HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD,
   HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER,
   HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD,
@@ -547,6 +559,8 @@
   HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT,
   HintCode.RECEIVER_OF_TYPE_NEVER,
   HintCode.RETURN_OF_DO_NOT_STORE,
+  HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR,
+  HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR,
   HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT,
   HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE,
   HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT,
@@ -828,7 +842,7 @@
 
 /// The lazy initialized map from [ErrorCode.uniqueName] to the [ErrorCode]
 /// instance.
-HashMap<String, ErrorCode> _uniqueNameToCodeMap;
+/*late final*/ HashMap<String, ErrorCode> _uniqueNameToCodeMap;
 
 /// Return the [ErrorCode] with the given [uniqueName], or `null` if not
 /// found.
@@ -929,6 +943,27 @@
     _contextMessages = contextMessages;
   }
 
+  /// Initialize a newly created analysis error. The error is associated with
+  /// the given [source] and is located at the given [offset] with the given
+  /// [length]. The error will have the given [errorCode] and the map  of
+  /// [arguments] will be used to complete the message and correction. If any
+  /// [contextMessages] are provided, they will be recorded with the error.
+  AnalysisError.withNamedArguments(this.source, int offset, int length,
+      this.errorCode, Map<String, dynamic> arguments,
+      {List<DiagnosticMessage> contextMessages = const []}) {
+    String messageText = applyArgumentsToTemplate(errorCode.message, arguments);
+    String correctionTemplate = errorCode.correction;
+    if (correctionTemplate != null) {
+      _correction = applyArgumentsToTemplate(correctionTemplate, arguments);
+    }
+    _problemMessage = DiagnosticMessageImpl(
+        filePath: source?.fullName,
+        length: length,
+        message: messageText,
+        offset: offset);
+    _contextMessages = contextMessages;
+  }
+
   @override
   List<DiagnosticMessage> get contextMessages => _contextMessages;
 
diff --git a/pkg/analyzer/lib/error/listener.dart b/pkg/analyzer/lib/error/listener.dart
index ffb3b98..e1ab6be 100644
--- a/pkg/analyzer/lib/error/listener.dart
+++ b/pkg/analyzer/lib/error/listener.dart
@@ -143,8 +143,8 @@
   /// the error is specified by the given [offset] and [length].
   void reportErrorMessage(
       ErrorCode errorCode, int offset, int length, Message message) {
-    _errorListener.onError(AnalysisError.forValues(
-        _source, offset, length, errorCode, message.message, message.tip));
+    _errorListener.onError(AnalysisError.withNamedArguments(
+        _source, offset, length, errorCode, message.arguments));
   }
 
   /// Report an error with the given [errorCode] and [arguments]. The [node] is
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 7a43df7..c91e372 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -114,7 +114,10 @@
     if (builderOptions.librarySummaryPaths != null) {
       summaryData = SummaryDataStore(builderOptions.librarySummaryPaths);
     }
-    final sf = createSourceFactory(path, summaryData: summaryData);
+    Workspace workspace =
+        ContextBuilder.createWorkspace(resourceProvider, path, this);
+    final sf =
+        createSourceFactoryFromWorkspace(workspace, summaryData: summaryData);
 
     AnalysisDriver driver = AnalysisDriver(
       analysisDriverScheduler,
@@ -143,6 +146,7 @@
         resourceProvider,
         apiContextRoots.first,
         driver,
+        workspace: workspace,
       ),
     );
 
@@ -209,6 +213,15 @@
     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) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 995281e..9792278 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -41,6 +41,7 @@
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/summary2/ast_binary_flags.dart';
 import 'package:meta/meta.dart';
 
 /// TODO(scheglov) We could use generalized Function in
@@ -85,7 +86,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 = 116;
+  static const int DATA_VERSION = 122;
 
   /// The length of the list returned by [_computeDeclaredVariablesSignature].
   static const int _declaredVariablesSignatureLength = 4;
@@ -147,7 +148,7 @@
       _declaredVariablesSignatureLength);
 
   /// The salt to mix into all hashes used as keys for linked data.
-  final Uint32List _saltForResolution = Uint32List(2 +
+  final Uint32List _saltForResolution = Uint32List(3 +
       AnalysisOptionsImpl.signatureLength +
       _declaredVariablesSignatureLength);
 
@@ -627,7 +628,7 @@
     var uriObj = Uri.parse(uri);
     var file = _fsState.getFileForUri(uriObj);
 
-    if (file.isUnresolved) {
+    if (file == null) {
       throw ArgumentError('$uri cannot be resolved to a file.');
     }
 
@@ -884,7 +885,8 @@
   /// without a package name. In these cases we cannot prove that the file is
   /// not a part, so it must be a library.
   bool isLibraryByUri(Uri uri) {
-    return !_fsState.getFileForUri(uri).isPart;
+    var file = _fsState.getFileForUri(uri);
+    return file == null || !file.isPart;
   }
 
   /// Return a [Future] that completes with a [ParsedUnitResult] for the file
@@ -1596,6 +1598,9 @@
     _saltForResolution[index] = enableIndex ? 1 : 0;
     index++;
 
+    _saltForResolution[index] = enableDebugResolutionMarkers ? 1 : 0;
+    index++;
+
     _saltForResolution.setAll(index, _analysisOptions.signature);
     index += AnalysisOptionsImpl.signatureLength;
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart b/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart
index d02bc2c..13ebb84 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver_based_analysis_context.dart
@@ -8,13 +8,14 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptions;
 import 'package:analyzer/src/workspace/workspace.dart';
 
 /// An analysis context whose implementation is based on an analysis driver.
 class DriverBasedAnalysisContext implements AnalysisContext {
   /// The resource provider used to access the file system.
-  final ResourceProvider resourceProvider;
+  final ResourceProvider /*!*/ resourceProvider;
 
   @override
   final ContextRoot contextRoot;
@@ -29,7 +30,9 @@
   /// to access the file system and that is based on the given analysis
   /// [driver].
   DriverBasedAnalysisContext(
-      this.resourceProvider, this.contextRoot, this.driver) {
+      this.resourceProvider, this.contextRoot, this.driver,
+      {Workspace workspace})
+      : _workspace = workspace {
     driver.analysisContext = this;
   }
 
@@ -40,6 +43,15 @@
   AnalysisSession get currentSession => driver.currentSession;
 
   @override
+  Folder get sdkRoot {
+    var sdk = driver.sourceFactory.dartSdk;
+    if (sdk is FolderBasedDartSdk) {
+      return sdk.directory;
+    }
+    return null;
+  }
+
+  @override
   Workspace get workspace {
     return _workspace ??= _buildWorkspace();
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index a37f6a7..0e20865 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -17,7 +17,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/defined_names.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
 import 'package:analyzer/src/dart/analysis/library_graph.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
@@ -37,6 +36,7 @@
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/summary2/bundle_writer.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
+import 'package:collection/collection.dart';
 import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
 import 'package:meta/meta.dart';
@@ -197,9 +197,9 @@
   /// parted.
   Set<FileState> get directReferencedFiles {
     return _directReferencedFiles ??= <FileState>{
-      ...importedFiles,
-      ...exportedFiles,
-      ...partedFiles,
+      ...importedFiles.whereNotNull(),
+      ...exportedFiles.whereNotNull(),
+      ...partedFiles.whereNotNull(),
     };
   }
 
@@ -207,8 +207,8 @@
   /// exported.
   Set<FileState> get directReferencedLibraries {
     return _directReferencedLibraries ??= <FileState>{
-      ...importedFiles,
-      ...exportedFiles,
+      ...importedFiles.whereNotNull(),
+      ...exportedFiles.whereNotNull(),
     };
   }
 
@@ -263,10 +263,6 @@
     return !_unlinked2.hasLibraryDirective && _unlinked2.hasPartOfDirective;
   }
 
-  /// Return `true` if the file is the "unresolved" file, which does not have
-  /// neither a valid URI, nor a path.
-  bool get isUnresolved => uri == null;
-
   /// If the file [isPart], return a currently know library the file is a part
   /// of. Return `null` if a library is not known, for example because we have
   /// not processed a library file yet.
@@ -300,7 +296,10 @@
   /// The list of files files that this library consists of, i.e. this library
   /// file itself and its [partedFiles].
   List<FileState> get libraryFiles {
-    return _libraryFiles ??= [this, ...partedFiles];
+    return _libraryFiles ??= [
+      this,
+      ...partedFiles.whereNotNull(),
+    ];
   }
 
   /// Return information about line in the file.
@@ -313,9 +312,11 @@
       for (var uri in _unlinked2.parts) {
         var file = _fileForRelativeUri(uri);
         _partedFiles.add(file);
-        _fsState._partToLibraries
-            .putIfAbsent(file, () => <FileState>[])
-            .add(this);
+        if (file != null) {
+          _fsState._partToLibraries
+              .putIfAbsent(file, () => <FileState>[])
+              .add(this);
+        }
       }
     }
     return _partedFiles;
@@ -558,18 +559,18 @@
     return unit;
   }
 
-  /// Return the [FileState] for the given [relativeUri], maybe "unresolved"
-  /// file if the URI cannot be parsed, cannot correspond any file, etc.
+  /// Return the [FileState] for the given [relativeUri], or `null` if the
+  /// URI cannot be parsed, cannot correspond any file, etc.
   FileState _fileForRelativeUri(String relativeUri) {
     if (relativeUri.isEmpty) {
-      return _fsState.unresolvedFile;
+      return null;
     }
 
     Uri absoluteUri;
     try {
       absoluteUri = resolveRelativeUri(uri, Uri.parse(relativeUri));
     } on FormatException {
-      return _fsState.unresolvedFile;
+      return null;
     }
 
     return _fsState.getFileForUri(absoluteUri);
@@ -592,7 +593,6 @@
   }
 
   CompilationUnit _parse(AnalysisErrorListener errorListener) {
-    AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
     if (source == null) {
       return _createEmptyCompilationUnit();
     }
@@ -608,12 +608,10 @@
     Token token = scanner.tokenize(reportScannerErrors: false);
     LineInfo lineInfo = LineInfo(scanner.lineStarts);
 
-    bool useFasta = analysisOptions.useFastaParser;
     Parser parser = Parser(
       source,
       errorListener,
       featureSet: scanner.featureSet,
-      useFasta: useFasta,
     );
     parser.enableOptionalNewAndConst = true;
 
@@ -755,7 +753,6 @@
   final FileContentOverlay _contentOverlay;
   final SourceFactory _sourceFactory;
   final Workspace _workspace;
-  final AnalysisOptions _analysisOptions;
   final DeclaredVariables _declaredVariables;
   final Uint32List _saltForUnlinked;
   final Uint32List _saltForElements;
@@ -803,9 +800,6 @@
   /// The value of this field is incremented when the set of files is updated.
   int fileStamp = 0;
 
-  /// The [FileState] instance that correspond to an unresolved URI.
-  FileState _unresolvedFile;
-
   /// The cache of content of files, possibly shared with other file system
   /// states with the same resource provider and the content overlay.
   _FileContentCache _fileContentCache;
@@ -820,7 +814,8 @@
     this.contextName,
     this._sourceFactory,
     this._workspace,
-    this._analysisOptions,
+    @Deprecated('No longer used; will be removed')
+        AnalysisOptions analysisOptions,
     this._declaredVariables,
     this._saltForUnlinked,
     this._saltForElements,
@@ -837,18 +832,6 @@
   @visibleForTesting
   FileSystemStateTestView get test => _testView;
 
-  /// Return the [FileState] instance that correspond to an unresolved URI.
-  /// TODO(scheglov) Remove it.
-  FileState get unresolvedFile {
-    if (_unresolvedFile == null) {
-      var featureSet = FeatureSet.latestLanguageVersion();
-      _unresolvedFile = FileState._(this, null, null, null, null, featureSet,
-          ExperimentStatus.currentVersion);
-      _unresolvedFile.refresh();
-    }
-    return _unresolvedFile;
-  }
-
   FeatureSet contextFeatureSet(
     String path,
     Uri uri,
@@ -934,8 +917,7 @@
       // If the URI cannot be resolved, for example because the factory
       // does not understand the scheme, return the unresolved file instance.
       if (uriSource == null) {
-        _uriToFile[uri] = unresolvedFile;
-        return unresolvedFile;
+        return null;
       }
 
       String path = uriSource.fullName;
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index e6ca405..dc113ba 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -248,9 +248,8 @@
 
   void _computeConstantErrors(
       ErrorReporter errorReporter, CompilationUnit unit) {
-    ConstantVerifier constantVerifier = ConstantVerifier(
-        errorReporter, _libraryElement, _declaredVariables,
-        featureSet: unit.featureSet);
+    ConstantVerifier constantVerifier =
+        ConstantVerifier(errorReporter, _libraryElement, _declaredVariables);
     unit.accept(constantVerifier);
   }
 
@@ -548,7 +547,8 @@
     LibraryIdentifier libraryNameNode;
     var seenPartSources = <Source>{};
     var directivesToResolve = <Directive>[];
-    int partIndex = 0;
+    int partDirectiveIndex = 0;
+    int partElementIndex = 0;
     for (Directive directive in definingCompilationUnit.directives) {
       if (directive is LibraryDirective) {
         libraryNameNode = directive.name;
@@ -583,12 +583,15 @@
       } else if (directive is PartDirective) {
         StringLiteral partUri = directive.uri;
 
-        FileState partFile = _library.partedFiles[partIndex];
-        CompilationUnit partUnit = units[partFile];
-        CompilationUnitElement partElement = _libraryElement.parts[partIndex];
+        FileState partFile = _library.partedFiles[partDirectiveIndex++];
+        if (partFile == null) {
+          continue;
+        }
+
+        var partUnit = units[partFile];
+        var partElement = _libraryElement.parts[partElementIndex++];
         partUnit.element = partElement;
         directive.element = partElement;
-        partIndex++;
 
         Source partSource = directive.uriSource;
         if (partSource == null) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 4d2ff12..411150a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -55,8 +55,6 @@
   AnalysisContextImpl analysisContext;
   LinkedElementFactory elementFactory;
 
-  Set<LibraryCycle> loadedBundles = Set<LibraryCycle>.identity();
-
   LibraryContext({
     @required this.testView,
     @required AnalysisSessionImpl session,
@@ -112,16 +110,15 @@
     var thisLoadLogBuffer = StringBuffer();
 
     void loadBundle(LibraryCycle cycle, String debugPrefix) {
-      if (!loadedBundles.add(cycle)) return;
+      if (cycle.libraries.isEmpty ||
+          elementFactory.hasLibrary(cycle.libraries.first.uriStr)) {
+        return;
+      }
 
       thisLoadLogBuffer.writeln('$debugPrefix$cycle');
 
       librariesTotal += cycle.libraries.length;
 
-      if (cycle.isUnresolvedFile) {
-        return;
-      }
-
       cycle.directDependencies.forEach(
         (e) => loadBundle(e, '$debugPrefix  '),
       );
@@ -193,9 +190,6 @@
                   buffer.writeln('[cycle: $cycle]');
                   buffer.writeln();
 
-                  buffer.writeln('[loadedBundles: ${loadedBundles.toList()}]');
-                  buffer.writeln();
-
                   buffer.writeln('Bundles loaded in this load2() invocation:');
                   buffer.writeln(thisLoadLogBuffer);
                   buffer.writeln();
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
index bb04579..08cb6aa 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/src/summary/api_signature.dart';
 import 'package:analyzer/src/summary/link.dart' as graph
     show DependencyWalker, Node;
+import 'package:collection/collection.dart';
 
 /// Ensure that the [FileState.libraryCycle] for the [file] and anything it
 /// depends on is computed.
@@ -51,10 +52,6 @@
 
   LibraryCycle.external() : transitiveSignature = '<external>';
 
-  bool get isUnresolvedFile {
-    return libraries.length == 1 && libraries[0].isUnresolved;
-  }
-
   /// Invalidate this cycle and any cycles that directly or indirectly use it.
   ///
   /// Practically invalidation means that we clear the library cycle in all the
@@ -121,8 +118,10 @@
     // Append direct referenced cycles.
     for (var node in scc) {
       var file = node.file;
-      _appendDirectlyReferenced(cycle, signature, file.importedFiles);
-      _appendDirectlyReferenced(cycle, signature, file.exportedFiles);
+      _appendDirectlyReferenced(
+          cycle, signature, file.importedFiles.whereNotNull().toList());
+      _appendDirectlyReferenced(
+          cycle, signature, file.exportedFiles.whereNotNull().toList());
     }
 
     // Fill the cycle with libraries.
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index d1f7aa3..3074d5b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -32,7 +32,8 @@
   Search(this._driver);
 
   /// Returns class or mixin members with the given [name].
-  Future<List<Element>> classMembers(String name) async {
+  Future<List<Element>> classMembers(
+      String name, SearchedFiles searchedFiles) async {
     List<Element> elements = <Element>[];
 
     void addElement(Element element) {
@@ -49,10 +50,12 @@
 
     List<String> files = await _driver.getFilesDefiningClassMemberName(name);
     for (String file in files) {
-      UnitElementResult unitResult = await _driver.getUnitElement(file);
-      if (unitResult != null) {
-        unitResult.element.types.forEach(addElements);
-        unitResult.element.mixins.forEach(addElements);
+      if (searchedFiles.add(file, this)) {
+        UnitElementResult unitResult = await _driver.getUnitElement(file);
+        if (unitResult != null) {
+          unitResult.element.types.forEach(addElements);
+          unitResult.element.mixins.forEach(addElements);
+        }
       }
     }
     return elements;
@@ -66,12 +69,11 @@
     }
 
     ElementKind kind = element.kind;
-    if (kind == ElementKind.CLASS ||
-        kind == ElementKind.CONSTRUCTOR ||
-        kind == ElementKind.ENUM ||
-        kind == ElementKind.EXTENSION ||
-        kind == ElementKind.FUNCTION_TYPE_ALIAS ||
-        kind == ElementKind.SETTER) {
+    if (element is ClassElement ||
+        element is ConstructorElement ||
+        element is ExtensionElement ||
+        element is PropertyAccessorElement && element.isSetter ||
+        element is TypeAliasElement) {
       return _searchReferences(element, searchedFiles);
     } else if (kind == ElementKind.COMPILATION_UNIT) {
       return _searchReferences_CompilationUnit(element);
@@ -177,9 +179,9 @@
         unitElement.enums.forEach(addElement);
         unitElement.extensions.forEach(addElement);
         unitElement.functions.forEach(addElement);
-        unitElement.functionTypeAliases.forEach(addElement);
         unitElement.mixins.forEach(addElement);
         unitElement.topLevelVariables.forEach(addElement);
+        unitElement.typeAliases.forEach(addElement);
         unitElement.types.forEach(addElement);
       }
     }
@@ -247,7 +249,7 @@
       }
     } else {
       files = await _driver.getFilesReferencingName(name);
-      if (!files.contains(path)) {
+      if (searchedFiles.add(path, this) && !files.contains(path)) {
         files.add(path);
       }
     }
@@ -498,9 +500,12 @@
     return identical(pathOwner, search) && identical(uriOwner, search);
   }
 
-  void ownAdded(Search search) {
-    for (var path in search._driver.addedFiles) {
-      add(path, search);
+  void ownAnalyzed(Search search) {
+    var contextRoot = search._driver.analysisContext.contextRoot;
+    for (var path in contextRoot.analyzedFiles()) {
+      if (path.endsWith('.dart')) {
+        add(path, search);
+      }
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index ad1100b..e517f1d 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
-import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -46,38 +45,30 @@
   /// The current library that is being analyzed.
   final LibraryElement _currentLibrary;
 
-  final bool _constantUpdate2018Enabled;
-
   final ConstantEvaluationEngine _evaluationEngine;
 
   final DiagnosticFactory _diagnosticFactory = DiagnosticFactory();
 
   /// Initialize a newly created constant verifier.
-  ConstantVerifier(ErrorReporter errorReporter, LibraryElement currentLibrary,
-      DeclaredVariables declaredVariables,
-      {
-      // TODO(paulberry): make [featureSet] a required parameter.
-      FeatureSet featureSet})
-      : this._(
-            errorReporter,
-            currentLibrary,
-            currentLibrary.typeSystem,
-            currentLibrary.typeProvider,
-            declaredVariables,
-            featureSet ??
-                (currentLibrary.context.analysisOptions as AnalysisOptionsImpl)
-                    .contextFeatures);
+  ConstantVerifier(
+    ErrorReporter errorReporter,
+    LibraryElement currentLibrary,
+    DeclaredVariables declaredVariables,
+  ) : this._(
+          errorReporter,
+          currentLibrary,
+          currentLibrary.typeSystem,
+          currentLibrary.typeProvider,
+          declaredVariables,
+        );
 
   ConstantVerifier._(
-      this._errorReporter,
-      this._currentLibrary,
-      this._typeSystem,
-      this._typeProvider,
-      this.declaredVariables,
-      FeatureSet featureSet)
-      : _constantUpdate2018Enabled =
-            featureSet.isEnabled(Feature.constant_update_2018),
-        _intType = _typeProvider.intType,
+    this._errorReporter,
+    this._currentLibrary,
+    this._typeSystem,
+    this._typeProvider,
+    this.declaredVariables,
+  )   : _intType = _typeProvider.intType,
         _evaluationEngine = ConstantEvaluationEngine(declaredVariables);
 
   bool get _isNonNullableByDefault => _currentLibrary.isNonNullableByDefault;
@@ -704,10 +695,6 @@
       verifier._errorReporter.reportErrorForNode(errorCode, element);
       return false;
     } else if (element is IfElement) {
-      if (!verifier._constantUpdate2018Enabled) {
-        verifier._errorReporter.reportErrorForNode(errorCode, element);
-        return false;
-      }
       var conditionValue = verifier._validate(element.condition, errorCode);
       var conditionBool = conditionValue?.toBoolValue();
 
@@ -735,10 +722,6 @@
     } else if (element is MapLiteralEntry) {
       return _validateMapLiteralEntry(element);
     } else if (element is SpreadElement) {
-      if (!verifier._constantUpdate2018Enabled) {
-        verifier._errorReporter.reportErrorForNode(errorCode, element);
-        return false;
-      }
       var value = verifier._validate(element.expression, errorCode);
       if (value == null) return false;
 
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 6c1f831..329422d 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -5,7 +5,6 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
-import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -81,7 +80,7 @@
   /// arguments are correct, `false` if there is an error.
   bool checkFromEnvironmentArguments(
       LibraryElementImpl library,
-      NodeList<Expression> arguments,
+      List<Expression> arguments,
       List<DartObjectImpl> argumentValues,
       Map<String, DartObjectImpl> namedArgumentValues,
       InterfaceType expectedDefaultValueType) {
@@ -271,7 +270,7 @@
       constant = (constant as ConstructorElement).declaration;
     }
     if (constant is VariableElement) {
-      VariableElementImpl declaration = constant.declaration;
+      var declaration = constant.declaration as VariableElementImpl;
       Expression initializer = declaration.constantInitializer;
       if (initializer != null) {
         initializer.accept(referenceFinder);
@@ -497,7 +496,7 @@
         definingType,
       );
     }
-    ConstructorElementImpl constructorBase = constructor.declaration;
+    var constructorBase = constructor.declaration as ConstructorElementImpl;
     List<ConstructorInitializer> initializers =
         constructorBase.constantInitializers;
     if (initializers == null) {
@@ -979,10 +978,6 @@
   /// Convenience getter to gain access to the [evaluationEngine]'s type system.
   TypeSystemImpl get typeSystem => _library.typeSystem;
 
-  bool get _isEnabledConstantUpdate2018 {
-    return _library.featureSet.isEnabled(Feature.constant_update_2018);
-  }
-
   bool get _isNonNullableByDefault => typeSystem.isNonNullableByDefault;
 
   /// Convenience getter to gain access to the [evaluationEngine]'s type
@@ -1005,14 +1000,9 @@
 
   @override
   DartObjectImpl visitAsExpression(AsExpression node) {
-    if (_isEnabledConstantUpdate2018) {
-      DartObjectImpl expressionResult = node.expression.accept(this);
-      DartObjectImpl typeResult = node.type.accept(this);
-      return _dartObjectComputer.castToType(node, expressionResult, typeResult);
-    }
-    // TODO(brianwilkerson) Figure out which error to report.
-    _error(node, null);
-    return null;
+    DartObjectImpl expressionResult = node.expression.accept(this);
+    DartObjectImpl typeResult = node.type.accept(this);
+    return _dartObjectComputer.castToType(node, expressionResult, typeResult);
   }
 
   @override
@@ -1027,33 +1017,21 @@
       return _dartObjectComputer.lazyOr(
           node, leftResult, () => node.rightOperand.accept(this));
     } else if (operatorType == TokenType.QUESTION_QUESTION) {
-      if (_isEnabledConstantUpdate2018) {
-        return _dartObjectComputer.lazyQuestionQuestion(
-            node, leftResult, () => node.rightOperand.accept(this));
-      } else {
-        return _dartObjectComputer.eagerQuestionQuestion(
-            node, leftResult, node.rightOperand.accept(this));
-      }
+      return _dartObjectComputer.lazyQuestionQuestion(
+          node, leftResult, () => node.rightOperand.accept(this));
     }
     // evaluate eager operators
     DartObjectImpl rightResult = node.rightOperand.accept(this);
     if (operatorType == TokenType.AMPERSAND) {
-      return _dartObjectComputer.eagerAnd(
-          node, leftResult, rightResult, _isEnabledConstantUpdate2018);
+      return _dartObjectComputer.eagerAnd(node, leftResult, rightResult);
     } else if (operatorType == TokenType.BANG_EQ) {
       return _dartObjectComputer.notEqual(node, leftResult, rightResult);
     } else if (operatorType == TokenType.BAR) {
-      return _dartObjectComputer.eagerOr(
-          node, leftResult, rightResult, _isEnabledConstantUpdate2018);
+      return _dartObjectComputer.eagerOr(node, leftResult, rightResult);
     } else if (operatorType == TokenType.CARET) {
-      return _dartObjectComputer.eagerXor(
-          node, leftResult, rightResult, _isEnabledConstantUpdate2018);
+      return _dartObjectComputer.eagerXor(node, leftResult, rightResult);
     } else if (operatorType == TokenType.EQ_EQ) {
-      if (_isEnabledConstantUpdate2018) {
-        return _dartObjectComputer.lazyEqualEqual(
-            node, leftResult, rightResult);
-      }
-      return _dartObjectComputer.equalEqual(node, leftResult, rightResult);
+      return _dartObjectComputer.lazyEqualEqual(node, leftResult, rightResult);
     } else if (operatorType == TokenType.GT) {
       return _dartObjectComputer.greaterThan(node, leftResult, rightResult);
     } else if (operatorType == TokenType.GT_EQ) {
@@ -1102,44 +1080,13 @@
   DartObjectImpl visitConditionalExpression(ConditionalExpression node) {
     Expression condition = node.condition;
     DartObjectImpl conditionResult = condition.accept(this);
-    if (_isEnabledConstantUpdate2018) {
-      if (conditionResult == null) {
-        return conditionResult;
-      } else if (!conditionResult.isBool) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, condition);
-        return null;
-      }
-      conditionResult = _dartObjectComputer.applyBooleanConversion(
-          condition, conditionResult);
-      if (conditionResult == null) {
-        return conditionResult;
-      }
-      if (conditionResult.toBoolValue() == true) {
-        _reportNotPotentialConstants(node.elseExpression);
-        return node.thenExpression.accept(this);
-      } else if (conditionResult.toBoolValue() == false) {
-        _reportNotPotentialConstants(node.thenExpression);
-        return node.elseExpression.accept(this);
-      }
-      // We used to return an object with a known type and an unknown value, but
-      // we can't do that without evaluating both the 'then' and 'else'
-      // expressions, and we're not suppose to do that under lazy semantics. I'm
-      // not sure which failure mode is worse.
-      return null;
-    }
-    DartObjectImpl thenResult = node.thenExpression.accept(this);
-    DartObjectImpl elseResult = node.elseExpression.accept(this);
+
     if (conditionResult == null) {
       return conditionResult;
     } else if (!conditionResult.isBool) {
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, condition);
       return null;
-    } else if (thenResult == null) {
-      return thenResult;
-    } else if (elseResult == null) {
-      return elseResult;
     }
     conditionResult =
         _dartObjectComputer.applyBooleanConversion(condition, conditionResult);
@@ -1147,16 +1094,18 @@
       return conditionResult;
     }
     if (conditionResult.toBoolValue() == true) {
-      return thenResult;
+      _reportNotPotentialConstants(node.elseExpression);
+      return node.thenExpression.accept(this);
     } else if (conditionResult.toBoolValue() == false) {
-      return elseResult;
+      _reportNotPotentialConstants(node.thenExpression);
+      return node.elseExpression.accept(this);
     }
-    ParameterizedType thenType = thenResult.type;
-    ParameterizedType elseType = elseResult.type;
-    return DartObjectImpl.validWithUnknownValue(
-      typeSystem,
-      typeSystem.getLeastUpperBound(thenType, elseType) as ParameterizedType,
-    );
+
+    // We used to return an object with a known type and an unknown value, but
+    // we can't do that without evaluating both the 'then' and 'else'
+    // expressions, and we're not suppose to do that under lazy semantics. I'm
+    // not sure which failure mode is worse.
+    return null;
   }
 
   @override
@@ -1224,14 +1173,9 @@
 
   @override
   DartObjectImpl visitIsExpression(IsExpression node) {
-    if (_isEnabledConstantUpdate2018) {
-      DartObjectImpl expressionResult = node.expression.accept(this);
-      DartObjectImpl typeResult = node.type.accept(this);
-      return _dartObjectComputer.typeTest(node, expressionResult, typeResult);
-    }
-    // TODO(brianwilkerson) Figure out which error to report.
-    _error(node, null);
-    return null;
+    DartObjectImpl expressionResult = node.expression.accept(this);
+    DartObjectImpl typeResult = node.type.accept(this);
+    return _dartObjectComputer.typeTest(node, expressionResult, typeResult);
   }
 
   @override
@@ -1550,7 +1494,7 @@
       return false;
     } else if (element is SpreadElement) {
       DartObjectImpl elementResult = element.expression.accept(this);
-      Map<DartObject, DartObject> value = elementResult?.toMapValue();
+      Map<DartObjectImpl, DartObjectImpl> value = elementResult?.toMapValue();
       if (value == null) {
         return true;
       }
@@ -1662,9 +1606,9 @@
         return value.value;
       }
     } else if (variableElement is ExecutableElement) {
-      ExecutableElement function = element;
+      var function = element as ExecutableElement;
       if (function.isStatic) {
-        var functionType = node.staticType;
+        var functionType = node.staticType as ParameterizedType;
         return DartObjectImpl(
           typeSystem,
           functionType,
@@ -1689,7 +1633,7 @@
         _typeProvider.typeType,
         TypeState(_typeProvider.dynamicType),
       );
-    } else if (variableElement is FunctionTypeAliasElement) {
+    } else if (variableElement is TypeAliasElement) {
       var type = variableElement.instantiate(
         typeArguments: variableElement.typeParameters
             .map((t) => _typeProvider.dynamicType)
@@ -1839,10 +1783,10 @@
   }
 
   DartObjectImpl eagerAnd(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand, bool allowBool) {
+      DartObjectImpl rightOperand) {
     if (leftOperand != null && rightOperand != null) {
       try {
-        return leftOperand.eagerAnd(_typeSystem, rightOperand, allowBool);
+        return leftOperand.eagerAnd(_typeSystem, rightOperand);
       } on EvaluationException catch (exception) {
         _errorReporter.reportErrorForNode(exception.errorCode, node);
       }
@@ -1851,10 +1795,10 @@
   }
 
   DartObjectImpl eagerOr(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand, bool allowBool) {
+      DartObjectImpl rightOperand) {
     if (leftOperand != null && rightOperand != null) {
       try {
-        return leftOperand.eagerOr(_typeSystem, rightOperand, allowBool);
+        return leftOperand.eagerOr(_typeSystem, rightOperand);
       } on EvaluationException catch (exception) {
         _errorReporter.reportErrorForNode(exception.errorCode, node);
       }
@@ -1874,10 +1818,10 @@
   }
 
   DartObjectImpl eagerXor(BinaryExpression node, DartObjectImpl leftOperand,
-      DartObjectImpl rightOperand, bool allowBool) {
+      DartObjectImpl rightOperand) {
     if (leftOperand != null && rightOperand != null) {
       try {
-        return leftOperand.eagerXor(_typeSystem, rightOperand, allowBool);
+        return leftOperand.eagerXor(_typeSystem, rightOperand);
       } on EvaluationException catch (exception) {
         _errorReporter.reportErrorForNode(exception.errorCode, node);
       }
diff --git a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
index 7b620f3..8149a3b 100644
--- a/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
+++ b/pkg/analyzer/lib/src/dart/constant/potentially_constant.dart
@@ -39,7 +39,7 @@
 
 bool _isConstantTypeName(Identifier name) {
   var element = name.staticElement;
-  if (element is ClassElement || element is FunctionTypeAliasElement) {
+  if (element is ClassElement || element is TypeAliasElement) {
     if (name is PrefixedIdentifier) {
       if (name.isDeferred) {
         return false;
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 72e220c..077ccf5 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -217,7 +217,8 @@
     if (elementAnnotation == null) {
       // Analyzer ignores annotations on "part of" directives and on enum
       // constant declarations.
-      assert(node.parent is PartOfDirective ||
+      assert(node.parent is PartDirective ||
+          node.parent is PartOfDirective ||
           node.parent is EnumConstantDeclaration);
     } else {
       constantsToCompute.add(elementAnnotation);
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index c2ae7ca..af14481 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -63,13 +63,13 @@
   }
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     if (value == null) {
       return UNKNOWN_VALUE;
     }
@@ -94,11 +94,6 @@
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   BoolState lazyOr(InstanceState Function() rightOperandComputer) {
     if (value == true) {
       return TRUE_STATE;
@@ -332,8 +327,8 @@
   /// Throws an [EvaluationException] if the operator is not appropriate for an
   /// object of this kind.
   DartObjectImpl eagerAnd(
-      TypeSystemImpl typeSystem, DartObjectImpl rightOperand, bool allowBool) {
-    if (allowBool && isBool && rightOperand.isBool) {
+      TypeSystemImpl typeSystem, DartObjectImpl rightOperand) {
+    if (isBool && rightOperand.isBool) {
       return DartObjectImpl(
         typeSystem,
         typeSystem.typeProvider.boolType,
@@ -355,8 +350,8 @@
   /// Throws an [EvaluationException] if the operator is not appropriate for an
   /// object of this kind.
   DartObjectImpl eagerOr(
-      TypeSystemImpl typeSystem, DartObjectImpl rightOperand, bool allowBool) {
-    if (allowBool && isBool && rightOperand.isBool) {
+      TypeSystemImpl typeSystem, DartObjectImpl rightOperand) {
+    if (isBool && rightOperand.isBool) {
       return DartObjectImpl(
         typeSystem,
         typeSystem.typeProvider.boolType,
@@ -378,8 +373,8 @@
   /// Throws an [EvaluationException] if the operator is not appropriate for an
   /// object of this kind.
   DartObjectImpl eagerXor(
-      TypeSystemImpl typeSystem, DartObjectImpl rightOperand, bool allowBool) {
-    if (allowBool && isBool && rightOperand.isBool) {
+      TypeSystemImpl typeSystem, DartObjectImpl rightOperand) {
+    if (isBool && rightOperand.isBool) {
       return DartObjectImpl(
         typeSystem,
         typeSystem.typeProvider.boolType,
@@ -415,7 +410,7 @@
       return DartObjectImpl(
         typeSystem,
         typeSystem.typeProvider.boolType,
-        _state.equalEqual(rightOperand._state),
+        _state.equalEqual(typeSystem, rightOperand._state),
       );
     }
     throw EvaluationException(
@@ -544,7 +539,7 @@
     return DartObjectImpl(
       typeSystem,
       typeSystem.typeProvider.boolType,
-      _state.isIdentical(rightOperand._state),
+      _state.isIdentical(typeSystem, rightOperand._state),
     );
   }
 
@@ -582,7 +577,7 @@
       return DartObjectImpl(
         typeSystem,
         typeSystem.typeProvider.boolType,
-        _state.lazyEqualEqual(rightOperand._state),
+        _state.lazyEqualEqual(typeSystem, rightOperand._state),
       );
     }
     throw EvaluationException(
@@ -1065,7 +1060,7 @@
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     if (value == null) {
       return BoolState.UNKNOWN_VALUE;
     }
@@ -1086,11 +1081,6 @@
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   BoolState lessThan(InstanceState rightOperand) {
     assertNumOrNull(rightOperand);
     if (value == null) {
@@ -1249,12 +1239,12 @@
   }
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     if (_element == null) {
       return BoolState.UNKNOWN_VALUE;
     }
@@ -1269,11 +1259,6 @@
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   String toString() => _element == null ? "-unknown-" : _element.name;
 }
 
@@ -1340,22 +1325,17 @@
   StringState convertToString() => StringState.UNKNOWN_VALUE;
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     return BoolState.from(this == rightOperand);
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   String toString() {
     StringBuffer buffer = StringBuffer();
     List<String> fieldNames = _fieldMap.keys.toList();
@@ -1536,7 +1516,7 @@
   ///
   /// Throws an [EvaluationException] if the operator is not appropriate for an
   /// object of this kind.
-  BoolState equalEqual(InstanceState rightOperand);
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand);
 
   /// Return the result of invoking the '&gt;' operator on this object with the
   /// [rightOperand].
@@ -1573,7 +1553,7 @@
 
   /// Return the result of invoking the identical function on this object with
   /// the [rightOperand].
-  BoolState isIdentical(InstanceState rightOperand);
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand);
 
   /// Return the result of invoking the '&&' operator on this object with the
   /// [rightOperand].
@@ -1595,7 +1575,12 @@
   ///
   /// Throws an [EvaluationException] if the operator is not appropriate for an
   /// object of this kind.
-  BoolState lazyEqualEqual(InstanceState rightOperand);
+  BoolState lazyEqualEqual(
+    TypeSystemImpl typeSystem,
+    InstanceState rightOperand,
+  ) {
+    return isIdentical(typeSystem, rightOperand);
+  }
 
   /// Return the result of invoking the '||' operator on this object with the
   /// [rightOperand].
@@ -1988,7 +1973,7 @@
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     if (value == null) {
       return BoolState.UNKNOWN_VALUE;
     }
@@ -2009,11 +1994,6 @@
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   BoolState lessThan(InstanceState rightOperand) {
     assertNumOrNull(rightOperand);
     if (value == null) {
@@ -2262,22 +2242,17 @@
   StringState convertToString() => StringState.UNKNOWN_VALUE;
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     return BoolState.from(this == rightOperand);
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   String toString() {
     StringBuffer buffer = StringBuffer();
     buffer.write('[');
@@ -2342,22 +2317,17 @@
   StringState convertToString() => StringState.UNKNOWN_VALUE;
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     return BoolState.from(this == rightOperand);
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   String toString() {
     StringBuffer buffer = StringBuffer();
     buffer.write('{');
@@ -2406,22 +2376,17 @@
   StringState convertToString() => StringState("null");
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     return BoolState.from(rightOperand is NullState);
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   BoolState logicalNot() {
     throw EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
@@ -2436,9 +2401,9 @@
   bool get isBoolNumStringOrNull => true;
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 }
 
@@ -2488,22 +2453,17 @@
   StringState convertToString() => StringState.UNKNOWN_VALUE;
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     return BoolState.from(this == rightOperand);
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   String toString() {
     StringBuffer buffer = StringBuffer();
     buffer.write('{');
@@ -2567,13 +2527,13 @@
   StringState convertToString() => this;
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     if (value == null) {
       return BoolState.UNKNOWN_VALUE;
     }
@@ -2588,11 +2548,6 @@
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   IntState stringLength() {
     if (value == null) {
       return IntState.UNKNOWN_VALUE;
@@ -2631,13 +2586,13 @@
   }
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     if (value == null) {
       return BoolState.UNKNOWN_VALUE;
     }
@@ -2652,11 +2607,6 @@
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   String toString() => value == null ? "-unknown-" : "#$value";
 }
 
@@ -2687,13 +2637,13 @@
   }
 
   @override
-  BoolState equalEqual(InstanceState rightOperand) {
+  BoolState equalEqual(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     assertBoolNumStringOrNull(rightOperand);
-    return isIdentical(rightOperand);
+    return isIdentical(typeSystem, rightOperand);
   }
 
   @override
-  BoolState isIdentical(InstanceState rightOperand) {
+  BoolState isIdentical(TypeSystemImpl typeSystem, InstanceState rightOperand) {
     if (_type == null) {
       return BoolState.UNKNOWN_VALUE;
     }
@@ -2702,17 +2652,15 @@
       if (rightType == null) {
         return BoolState.UNKNOWN_VALUE;
       }
-      return BoolState.from(_type == rightType);
+
+      return BoolState.from(
+        typeSystem.runtimeTypesEqual(_type, rightType),
+      );
     }
     return BoolState.FALSE_STATE;
   }
 
   @override
-  BoolState lazyEqualEqual(InstanceState rightOperand) {
-    return isIdentical(rightOperand);
-  }
-
-  @override
   String toString() {
     return _type?.getDisplayString(withNullability: true) ?? '-unknown-';
   }
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 1f98644..146592c 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -267,7 +267,8 @@
   /// This method should be used only for error recovery during analysis,
   /// when instance access to a static class member, defined in this class,
   /// or a superclass.
-  ExecutableElement lookupStaticGetter(String name, LibraryElement library) {
+  PropertyAccessorElement lookupStaticGetter(
+      String name, LibraryElement library) {
     return _first(_implementationsOfGetter(name).where((element) {
       return element.isStatic && element.isAccessibleIn(library);
     }));
@@ -278,7 +279,7 @@
   /// This method should be used only for error recovery during analysis,
   /// when instance access to a static class member, defined in this class,
   /// or a superclass.
-  ExecutableElement lookupStaticMethod(String name, LibraryElement library) {
+  MethodElement lookupStaticMethod(String name, LibraryElement library) {
     return _first(_implementationsOfMethod(name).where((element) {
       return element.isStatic && element.isAccessibleIn(library);
     }));
@@ -289,7 +290,8 @@
   /// This method should be used only for error recovery during analysis,
   /// when instance access to a static class member, defined in this class,
   /// or a superclass.
-  ExecutableElement lookupStaticSetter(String name, LibraryElement library) {
+  PropertyAccessorElement lookupStaticSetter(
+      String name, LibraryElement library) {
     return _first(_implementationsOfSetter(name).where((element) {
       return element.isStatic && element.isAccessibleIn(library);
     }));
@@ -631,7 +633,7 @@
   bool get hasNoSuchMethod {
     MethodElement method = lookUpConcreteMethod(
         FunctionElement.NO_SUCH_METHOD_METHOD_NAME, library);
-    ClassElement definingClass = method?.enclosingElement;
+    var definingClass = method?.enclosingElement as ClassElement;
     return definingClass != null && !definingClass.isDartCoreObject;
   }
 
@@ -902,7 +904,7 @@
       return <ConstructorElement>[];
     }
 
-    ClassElementImpl superElement = supertype.element;
+    var superElement = supertype.element as ClassElementImpl;
 
     // First get the list of constructors of the superclass which need to be
     // forwarded to this class.
@@ -954,9 +956,13 @@
     // substituting type parameters as appropriate.
     return constructorsToForward
         .map((ConstructorElement superclassConstructor) {
-      ConstructorElementImpl implicitConstructor =
-          ConstructorElementImpl(superclassConstructor.name, -1);
+      var containerRef = reference.getChild('@constructor');
+      var name = superclassConstructor.name;
+      var implicitConstructor = ConstructorElementImpl.forLinkedNode(
+          this, containerRef.getChild(name), null);
       implicitConstructor.isSynthetic = true;
+      implicitConstructor.name = name;
+      implicitConstructor.nameOffset = -1;
       implicitConstructor.redirectedConstructor = superclassConstructor;
       var hasMixinWithInstanceVariables = mixins.any(typeHasInstanceVariables);
       implicitConstructor.isConst =
@@ -1065,7 +1071,10 @@
       if (element.isEnum || element.isMixin) {
         return false;
       }
-      if (type.isDartCoreFunction) {
+      if (type.isDartCoreFunction || type.isDartCoreNull) {
+        return false;
+      }
+      if (type.nullabilitySuffix == NullabilitySuffix.question) {
         return false;
       }
       return true;
@@ -1076,39 +1085,19 @@
   /// Return `true` if the given [type] is an [InterfaceType] that can be used
   /// as an interface or a mixin.
   bool _isInterfaceTypeInterface(DartType type) {
-    return type is InterfaceType &&
-        !type.element.isEnum &&
-        !type.isDartCoreFunction;
-  }
-
-  static void collectAllSupertypes(List<InterfaceType> supertypes,
-      InterfaceType startingType, InterfaceType excludeType) {
-    List<InterfaceType> typesToVisit = <InterfaceType>[];
-    List<ClassElement> visitedClasses = <ClassElement>[];
-    typesToVisit.add(startingType);
-    while (typesToVisit.isNotEmpty) {
-      InterfaceType currentType = typesToVisit.removeAt(0);
-      ClassElement currentElement = currentType.element;
-      if (!visitedClasses.contains(currentElement)) {
-        visitedClasses.add(currentElement);
-        if (!identical(currentType, excludeType)) {
-          supertypes.add(currentType);
-        }
-        InterfaceType supertype = currentType.superclass;
-        if (supertype != null) {
-          typesToVisit.add(supertype);
-        }
-        for (InterfaceType type in currentType.superclassConstraints) {
-          typesToVisit.add(type);
-        }
-        for (InterfaceType type in currentType.interfaces) {
-          typesToVisit.add(type);
-        }
-        for (InterfaceType type in currentType.mixins) {
-          typesToVisit.add(type);
-        }
+    if (type is InterfaceType) {
+      if (type.element.isEnum) {
+        return false;
       }
+      if (type.isDartCoreFunction || type.isDartCoreNull) {
+        return false;
+      }
+      if (type.nullabilitySuffix == NullabilitySuffix.question) {
+        return false;
+      }
+      return true;
     }
+    return false;
   }
 
   static ConstructorElement getNamedConstructorFromList(
@@ -1164,6 +1153,7 @@
 
   /// A list containing all of the function type aliases contained in this
   /// compilation unit.
+  @Deprecated('Use typeAliases instead')
   List<FunctionTypeAliasElement> _functionTypeAliases;
 
   /// A list containing all of the type aliases contained in this compilation
@@ -1329,6 +1319,7 @@
     _functions = functions;
   }
 
+  @Deprecated('Use typeAliases instead')
   @override
   List<FunctionTypeAliasElement> get functionTypeAliases {
     return _functionTypeAliases ??=
@@ -1441,10 +1432,9 @@
     return _typeAliases ?? const <TypeAliasElement>[];
   }
 
-  /// Set the function type aliases contained in this compilation unit to the
-  /// given [typeAliases].
-  set typeAliases(List<FunctionTypeAliasElement> typeAliases) {
-    for (FunctionTypeAliasElement typeAlias in typeAliases) {
+  /// Set the type aliases contained in this compilation unit to [typeAliases].
+  set typeAliases(List<TypeAliasElement> typeAliases) {
+    for (TypeAliasElement typeAlias in typeAliases) {
       (typeAlias as ElementImpl).enclosingElement = this;
     }
     _typeAliases = typeAliases;
@@ -1535,8 +1525,8 @@
     safelyVisitChildren(enums, visitor);
     safelyVisitChildren(extensions, visitor);
     safelyVisitChildren(functions, visitor);
-    safelyVisitChildren(functionTypeAliases, visitor);
     safelyVisitChildren(mixins, visitor);
+    safelyVisitChildren(typeAliases, visitor);
     safelyVisitChildren(types, visitor);
     safelyVisitChildren(topLevelVariables, visitor);
   }
@@ -4357,10 +4347,15 @@
     List<DartType> typeArguments,
     NullabilitySuffix nullabilitySuffix,
   }) {
-    return super.instantiate(
+    var type = super.instantiate(
       typeArguments: typeArguments,
       nullabilitySuffix: nullabilitySuffix,
-    ) as FunctionType;
+    );
+    if (type is FunctionType) {
+      return type;
+    } else {
+      return _errorFunctionType(nullabilitySuffix);
+    }
   }
 }
 
@@ -5250,10 +5245,10 @@
       yield* unit.accessors;
       yield* unit.enums;
       yield* unit.extensions;
-      yield* unit.functionTypeAliases;
       yield* unit.functions;
       yield* unit.mixins;
       yield* unit.topLevelVariables;
+      yield* unit.typeAliases;
       yield* unit.types;
     }
   }
@@ -6940,7 +6935,7 @@
   /// from anywhere except a class element or type parameter bounds.
   bool hasSelfReference = false;
 
-  bool _isRawElementReady = false;
+  bool _isAliasedElementReady = false;
   ElementImpl _aliasedElement;
   DartType _aliasedType;
 
@@ -7083,8 +7078,7 @@
 
   @override
   T accept<T>(ElementVisitor<T> visitor) {
-    // TODO(scheglov) `visitTypeAliasElement`
-    throw UnimplementedError();
+    return visitor.visitTypeAliasElement(this);
   }
 
   @override
@@ -7118,8 +7112,16 @@
         parameters: type.parameters,
         returnType: type.returnType,
         nullabilitySuffix: resultNullability,
-        element: this,
-        typeArguments: typeArguments,
+        aliasElement: this,
+        aliasArguments: typeArguments,
+      );
+    } else if (type is InterfaceType) {
+      return InterfaceTypeImpl(
+        element: type.element,
+        typeArguments: type.typeArguments,
+        nullabilitySuffix: resultNullability,
+        aliasElement: this,
+        aliasArguments: typeArguments,
       );
     } else {
       return (type as TypeImpl).withNullability(resultNullability);
@@ -7127,8 +7129,8 @@
   }
 
   void _ensureAliasedElement() {
-    if (_isRawElementReady) return;
-    _isRawElementReady = true;
+    if (_isAliasedElementReady) return;
+    _isAliasedElementReady = true;
 
     var linkedNode = this.linkedNode;
     if (linkedNode != null) {
@@ -7257,7 +7259,7 @@
   @override
   String get name {
     if (linkedNode != null) {
-      TypeParameter node = linkedNode;
+      var node = linkedNode as TypeParameter;
       return node.name.name;
     }
     return super.name;
diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
index f778aef..43bd5eb 100644
--- a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
@@ -365,10 +365,10 @@
         return lower;
       }
       if (!identical(UnknownInferredType.instance, upper)) {
-        return toKnownType ? _typeSystem.greatestClosure(upper) : upper;
+        return toKnownType ? _typeSystem.greatestClosureOfSchema(upper) : upper;
       }
       if (!identical(UnknownInferredType.instance, lower)) {
-        return toKnownType ? _typeSystem.leastClosure(lower) : lower;
+        return toKnownType ? _typeSystem.leastClosureOfSchema(lower) : lower;
       }
       return upper;
     } else {
@@ -379,10 +379,10 @@
         return upper;
       }
       if (!identical(UnknownInferredType.instance, lower)) {
-        return toKnownType ? _typeSystem.leastClosure(lower) : lower;
+        return toKnownType ? _typeSystem.leastClosureOfSchema(lower) : lower;
       }
       if (!identical(UnknownInferredType.instance, upper)) {
-        return toKnownType ? _typeSystem.greatestClosure(upper) : upper;
+        return toKnownType ? _typeSystem.greatestClosureOfSchema(upper) : upper;
       }
       return lower;
     }
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index 9189fad..a2b00e9 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -743,7 +743,7 @@
     FunctionType resultType;
     for (var executable in validOverrides) {
       var type = executable.type;
-      var normalizedType = typeSystem.normalize(type);
+      var normalizedType = typeSystem.normalize(type) as FunctionType;
       if (resultType == null) {
         resultType = normalizedType;
       } else {
diff --git a/pkg/analyzer/lib/src/dart/element/least_greatest_closure.dart b/pkg/analyzer/lib/src/dart/element/least_greatest_closure.dart
new file mode 100644
index 0000000..c800909
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/element/least_greatest_closure.dart
@@ -0,0 +1,97 @@
+// 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/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/replacement_visitor.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_system.dart';
+import 'package:meta/meta.dart';
+
+class LeastGreatestClosureHelper extends ReplacementVisitor {
+  final TypeSystemImpl typeSystem;
+  final DartType topType;
+  final DartType topFunctionType;
+  final DartType bottomType;
+  final Set<TypeParameterElement> eliminationTargets;
+
+  bool _isLeastClosure;
+  bool _isCovariant = true;
+
+  LeastGreatestClosureHelper({
+    @required this.typeSystem,
+    @required this.topType,
+    @required this.topFunctionType,
+    @required this.bottomType,
+    @required this.eliminationTargets,
+  });
+
+  DartType get _functionReplacement {
+    return _isLeastClosure && _isCovariant ||
+            (!_isLeastClosure && !_isCovariant)
+        ? bottomType
+        : topFunctionType;
+  }
+
+  DartType get _typeParameterReplacement {
+    return _isLeastClosure && _isCovariant ||
+            (!_isLeastClosure && !_isCovariant)
+        ? bottomType
+        : topType;
+  }
+
+  @override
+  void changeVariance() {
+    _isCovariant = !_isCovariant;
+  }
+
+  /// Returns a supertype of [type] for all values of [eliminationTargets].
+  DartType eliminateToGreatest(DartType type) {
+    _isCovariant = true;
+    _isLeastClosure = false;
+    return type.accept(this) ?? type;
+  }
+
+  /// Returns a subtype of [type] for all values of [eliminationTargets].
+  DartType eliminateToLeast(DartType type) {
+    _isCovariant = true;
+    _isLeastClosure = true;
+    return type.accept(this) ?? type;
+  }
+
+  @override
+  DartType visitFunctionType(FunctionType node) {
+    // - if `S` is
+    //   `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn,
+    //       [Tn+1 xn+1, ..., Tm xm])`
+    //   or `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn,
+    //       {Tn+1 xn+1, ..., Tm xm})`
+    //   and `L` contains any free type variables from any of the `Bi`:
+    //  - The least closure of `S` with respect to `L` is `Never`
+    //  - The greatest closure of `S` with respect to `L` is `Function`
+    for (var typeParameter in node.typeFormals) {
+      var bound = typeParameter.bound as TypeImpl;
+      if (bound.referencesAny(eliminationTargets)) {
+        return _functionReplacement;
+      }
+    }
+
+    return super.visitFunctionType(node);
+  }
+
+  @override
+  DartType visitTypeParameterType(TypeParameterType node) {
+    if (eliminationTargets.contains(node.element)) {
+      var replacement = _typeParameterReplacement as TypeImpl;
+      return replacement.withNullability(
+        uniteNullabilities(
+          replacement.nullabilitySuffix,
+          node.nullabilitySuffix,
+        ),
+      );
+    }
+    return super.visitTypeParameterType(node);
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
index d355eab..7a031c7 100644
--- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -635,7 +635,7 @@
 
     // UP(X1 extends B1, T2)
     // UP(X1 & B1, T2)
-    if (T1 is TypeParameterType) {
+    if (T1 is TypeParameterTypeImpl) {
       // T2 if X1 <: T2
       if (_typeSystem.isSubtypeOf2(T1, T2)) {
         return T2;
@@ -644,14 +644,16 @@
       if (_typeSystem.isSubtypeOf2(T2, T1)) {
         return T1;
       }
-      // otherwise UP(B1[Object/X1], T2)
-      var T1_toObject = _typeParameterResolveToObjectBounds(T1);
-      return getLeastUpperBound(T1_toObject, T2);
+      // otherwise UP(B1a, T2)
+      //   where B1a is the greatest closure of B1 with respect to X1
+      var bound = _typeParameterBound(T1);
+      var closure = _typeSystem.greatestClosure(bound, [T1.element]);
+      return getLeastUpperBound(closure, T2);
     }
 
     // UP(T1, X2 extends B2)
     // UP(T1, X2 & B2)
-    if (T2 is TypeParameterType) {
+    if (T2 is TypeParameterTypeImpl) {
       // X2 if T1 <: X2
       if (_typeSystem.isSubtypeOf2(T1, T2)) {
         // TODO(scheglov) How to get here?
@@ -661,9 +663,11 @@
       if (_typeSystem.isSubtypeOf2(T2, T1)) {
         return T1;
       }
-      // otherwise UP(T1, B2[Object/X2])
-      var T2_toObject = _typeParameterResolveToObjectBounds(T2);
-      return getLeastUpperBound(T1, T2_toObject);
+      // otherwise UP(T1, B2a)
+      //   where B2a is the greatest closure of B2 with respect to X2
+      var bound = _typeParameterBound(T2);
+      var closure = _typeSystem.greatestClosure(bound, [T2.element]);
+      return getLeastUpperBound(T1, closure);
     }
 
     // UP(T Function<...>(...), Function) = Function
@@ -880,16 +884,14 @@
     return _typeSystem.getGreatestLowerBound(a.type, b.type);
   }
 
-  /// TODO(scheglov) Use greatest closure.
-  /// See https://github.com/dart-lang/language/pull/1195
-  DartType _typeParameterResolveToObjectBounds(DartType type) {
-    var element = type.element;
-
-    var objectType = _typeSystem.isNonNullableByDefault
+  /// Return the promoted or declared bound of the type parameter.
+  DartType _typeParameterBound(TypeParameterTypeImpl type) {
+    var bound = type.promotedBound ?? type.element.bound;
+    if (bound != null) {
+      return bound;
+    }
+    return _typeSystem.isNonNullableByDefault
         ? _typeSystem.objectQuestion
         : _typeSystem.objectStar;
-
-    type = type.resolveToBound(objectType);
-    return Substitution.fromMap({element: objectType}).substituteType(type);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index f343aa1..20ebc91 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -7,7 +7,6 @@
 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/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/display_string_builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
@@ -220,7 +219,7 @@
       return null;
     }
 
-    TypeProvider typeProvider;
+    TypeProviderImpl typeProvider;
     var isLegacy = false;
     var combined = substitution;
     if (element is ExecutableMember) {
@@ -237,7 +236,7 @@
       map.addAll(substitution.map);
       combined = Substitution.fromMap(map);
     } else {
-      typeProvider = element.library.typeProvider;
+      typeProvider = element.library.typeProvider as TypeProviderImpl;
     }
 
     if (!isLegacy && combined.map.isEmpty) {
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 5dd6961..1799c09 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
@@ -3,70 +3,131 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/replacement_visitor.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/extensions.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:meta/meta.dart';
 
 /// Replace every "top" type in a covariant position with [_bottomType].
 /// Replace every "bottom" type in a contravariant position with [_topType].
-class ReplaceTopBottomVisitor extends ReplacementVisitor {
+class ReplaceTopBottomVisitor {
+  final TypeSystemImpl _typeSystem;
   final DartType _topType;
   final DartType _bottomType;
-  final TypeSystemImpl _typeSystem;
-
-  bool _isCovariant;
 
   ReplaceTopBottomVisitor._(
     this._typeSystem,
     this._topType,
     this._bottomType,
-    this._isCovariant,
   );
 
-  @override
-  void changeVariance() {
-    _isCovariant = !_isCovariant;
-  }
-
-  @override
-  DartType visitDynamicType(DynamicType type) {
-    return _isCovariant ? _bottomType : null;
-  }
-
-  @override
-  DartType visitInterfaceType(InterfaceType type) {
-    if (_isCovariant) {
-      if (_typeSystem.isTop(type)) {
-        return _bottomType;
+  DartType process(DartType type, Variance variance) {
+    if (_typeSystem.isNonNullableByDefault) {
+      if (variance.isContravariant) {
+        // ...replacing every occurrence in `T` of a type `S` in a contravariant
+        // position where `S <: Never` by `Object?`
+        if (_typeSystem.isSubtypeOf2(type, NeverTypeImpl.instance)) {
+          return _topType;
+        }
+      } else {
+        // ...and every occurrence in `T` of a top type in a position which
+        // is not contravariant by `Never`.
+        if (_typeSystem.isTop(type)) {
+          return _bottomType;
+        }
       }
     } else {
-      if (!_typeSystem.isNonNullableByDefault && type.isDartCoreNull) {
-        return _topType;
+      if (variance.isCovariant) {
+        // ...replacing every occurrence in `T` of a top type in a covariant
+        // position by `Null`
+        if (_typeSystem.isTop(type)) {
+          return _bottomType;
+        }
+      } else if (variance.isContravariant) {
+        // ...and every occurrence in `T` of `Null` in a contravariant
+        // position by `Object`
+        if (type.isDartCoreNull) {
+          return _topType;
+        }
       }
     }
 
-    return super.visitInterfaceType(type);
-  }
-
-  @override
-  DartType visitNeverType(NeverType type) {
-    return _isCovariant ? null : _topType;
-  }
-
-  @override
-  DartType visitTypeParameterType(TypeParameterType type) {
-    if (!_isCovariant && _typeSystem.isNonNullableByDefault) {
-      if (_typeSystem.isSubtypeOf2(type, NeverTypeImpl.instance)) {
-        return _typeSystem.objectQuestion;
-      }
+    if (type.aliasElement != null) {
+      return _typeAliasInstantiation(type, variance);
+    } else if (type is InterfaceType) {
+      return _interfaceType(type, variance);
+    } else if (type is FunctionType) {
+      return _functionType(type, variance);
     }
-    return null;
+    return type;
   }
 
-  @override
-  DartType visitVoidType(VoidType type) {
-    return _isCovariant ? _bottomType : null;
+  DartType _functionType(FunctionType type, Variance variance) {
+    var newReturnType = process(type.returnType, variance);
+
+    var newParameters = type.parameters.map((parameter) {
+      return parameter.copyWith(
+        type: process(
+          parameter.type,
+          variance.combine(Variance.contravariant),
+        ),
+      );
+    }).toList();
+
+    return FunctionTypeImpl(
+      typeFormals: type.typeFormals,
+      parameters: newParameters,
+      returnType: newReturnType,
+      nullabilitySuffix: type.nullabilitySuffix,
+    );
+  }
+
+  DartType _interfaceType(InterfaceType type, Variance variance) {
+    var typeParameters = type.element.typeParameters;
+    if (typeParameters.isEmpty) {
+      return type;
+    }
+
+    var typeArguments = type.typeArguments;
+    assert(typeParameters.length == typeArguments.length);
+
+    var newTypeArguments = <DartType>[];
+    for (var i = 0; i < typeArguments.length; i++) {
+      var newTypeArgument = process(typeArguments[i], variance);
+      newTypeArguments.add(newTypeArgument);
+    }
+
+    return InterfaceTypeImpl(
+      element: type.element,
+      nullabilitySuffix: type.nullabilitySuffix,
+      typeArguments: newTypeArguments,
+    );
+  }
+
+  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
@@ -78,14 +139,7 @@
     @required TypeSystemImpl typeSystem,
     @required DartType type,
   }) {
-    var visitor = ReplaceTopBottomVisitor._(
-      typeSystem,
-      topType,
-      bottomType,
-      true,
-    );
-    var result = type.accept(visitor);
-    assert(visitor._isCovariant == true);
-    return result ?? type;
+    var visitor = ReplaceTopBottomVisitor._(typeSystem, topType, bottomType);
+    return visitor.process(type, Variance.covariant);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
index 87503e9..c2380d8 100644
--- a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
@@ -30,7 +30,7 @@
 
   DartType createFunctionType({
     @required FunctionType type,
-    @required List<DartType> newTypeArguments,
+    @required List<DartType> newAliasArguments,
     @required List<TypeParameterElement> newTypeParameters,
     @required List<ParameterElement> newParameters,
     @required DartType newReturnType,
@@ -47,8 +47,8 @@
       parameters: newParameters ?? type.parameters,
       returnType: newReturnType ?? type.returnType,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
-      element: type.element,
-      typeArguments: newTypeArguments ?? type.typeArguments,
+      aliasElement: type.aliasElement,
+      aliasArguments: newAliasArguments ?? type.aliasArguments,
     );
   }
 
@@ -75,10 +75,13 @@
 
   DartType createInterfaceType({
     @required InterfaceType type,
+    @required List<DartType> newAliasArguments,
     @required List<DartType> newTypeArguments,
     @required NullabilitySuffix newNullability,
   }) {
-    if (newTypeArguments == null && newNullability == null) {
+    if (newAliasArguments == null &&
+        newTypeArguments == null &&
+        newNullability == null) {
       return null;
     }
 
@@ -86,6 +89,8 @@
       element: type.element,
       typeArguments: newTypeArguments ?? type.typeArguments,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
+      aliasElement: type.aliasElement,
+      aliasArguments: newAliasArguments ?? type.aliasArguments,
     );
   }
 
@@ -206,12 +211,15 @@
 
     var newReturnType = visitType(node.returnType);
 
-    List<DartType> newTypeArguments;
-    for (var i = 0; i < node.typeArguments.length; i++) {
-      var substitution = node.typeArguments[i].accept(this);
-      if (substitution != null) {
-        newTypeArguments ??= node.typeArguments.toList(growable: false);
-        newTypeArguments[i] = substitution;
+    List<DartType> newAliasArguments;
+    var aliasArguments = node.aliasArguments;
+    if (aliasArguments != null) {
+      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;
+        }
       }
     }
 
@@ -241,7 +249,7 @@
 
     return createFunctionType(
       type: node,
-      newTypeArguments: newTypeArguments,
+      newAliasArguments: newAliasArguments,
       newTypeParameters: newTypeParameters,
       newParameters: newParameters,
       newReturnType: newReturnType,
@@ -339,6 +347,14 @@
   DartType visitInterfaceType(InterfaceType type) {
     var newNullability = visitNullability(type);
 
+    var aliasElement = type.aliasElement;
+    var newAliasArguments = aliasElement != null
+        ? _typeArguments(
+            aliasElement.typeParameters,
+            type.aliasArguments,
+          )
+        : null;
+
     var newTypeArguments = _typeArguments(
       type.element.typeParameters,
       type.typeArguments,
@@ -346,6 +362,7 @@
 
     return createInterfaceType(
       type: type,
+      newAliasArguments: newAliasArguments,
       newTypeArguments: newTypeArguments,
       newNullability: newNullability,
     );
@@ -359,7 +376,7 @@
     var element = type.element;
     if (element is ClassElement) {
       parameters = element.typeParameters;
-    } else if (element is FunctionTypeAliasElement) {
+    } else if (element is TypeAliasElement) {
       parameters = element.typeParameters;
     }
 
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index 85085f8..2622bd1 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -115,46 +115,27 @@
     @required String prefix,
     @required String name,
   }) {
-    Iterable<NamespaceCombinator> getShowCombinators(
-        ImportElement importElement) {
-      return importElement.combinators.whereType<ShowElementCombinator>();
+    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) {
-      for (var importElement in _element.imports) {
-        if (importElement.prefix?.name == prefix &&
-            importElement.importedLibrary?.isSynthetic != false) {
-          var showCombinators = getShowCombinators(importElement);
-          if (showCombinators.isEmpty) {
-            return true;
-          }
-          for (ShowElementCombinator combinator in showCombinators) {
-            if (combinator.shownNames.contains(name)) {
-              return true;
-            }
-          }
-        }
-      }
-    } else {
-      // TODO(scheglov) merge for(s).
-      for (var importElement in _element.imports) {
-        if (importElement.prefix == null &&
-            importElement.importedLibrary?.isSynthetic != false) {
-          for (ShowElementCombinator combinator
-              in getShowCombinators(importElement)) {
-            if (combinator.shownNames.contains(name)) {
-              return true;
-            }
-          }
-        }
-      }
-
-      if (name.startsWith(r'_$')) {
-        for (var partElement in _element.parts) {
-          if (partElement.isSynthetic &&
-              isGeneratedSource(partElement.source)) {
-            return true;
-          }
+    if (prefix == null && name.startsWith(r'_$')) {
+      for (var partElement in _element.parts) {
+        if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
+          return true;
         }
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 50953f8..88848f7 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -105,9 +105,6 @@
   final List<ParameterElement> parameters;
 
   @override
-  final List<DartType> typeArguments;
-
-  @override
   final NullabilitySuffix nullabilitySuffix;
 
   FunctionTypeImpl({
@@ -116,33 +113,30 @@
     @required DartType returnType,
     @required NullabilitySuffix nullabilitySuffix,
     Element element,
-    List<DartType> typeArguments,
+    TypeAliasElement aliasElement,
+    List<DartType> aliasArguments,
   })  : typeFormals = typeFormals,
         parameters = _sortNamedParameters(parameters),
         returnType = returnType,
         nullabilitySuffix = nullabilitySuffix,
-        typeArguments = typeArguments ?? const <DartType>[],
-        super(element);
-
-  @deprecated
-  FunctionTypeImpl.synthetic(
-      this.returnType, this.typeFormals, List<ParameterElement> parameters,
-      {Element element,
-      List<DartType> typeArguments,
-      @required NullabilitySuffix nullabilitySuffix})
-      : parameters = _sortNamedParameters(parameters),
-        typeArguments = typeArguments ?? const <DartType>[],
-        nullabilitySuffix = nullabilitySuffix,
-        super(element);
+        super(element,
+            aliasElement: aliasElement, aliasArguments: aliasArguments);
 
   @override
   FunctionTypedElement get element {
-    var element = super.element;
+    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
     // TODO(scheglov) Can we just construct it with the right element?
-    if (element is FunctionTypeAliasElement) {
-      return element.function;
+    var aliasedElement = aliasElement?.aliasedElement;
+    if (aliasedElement is GenericFunctionTypeElement) {
+      return aliasedElement;
     }
-    return element;
+
+    var element = super.element;
+    if (element is FunctionTypedElement) {
+      return element;
+    }
+
+    return null;
   }
 
   @override
@@ -218,6 +212,12 @@
   }
 
   @override
+  List<DartType> get typeArguments {
+    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
+    return aliasArguments ?? const <DartType>[];
+  }
+
+  @override
   bool operator ==(Object other) {
     if (identical(other, this)) {
       return true;
@@ -296,6 +296,33 @@
   }
 
   @override
+  bool referencesAny(Set<TypeParameterElement> parameters) {
+    if (typeFormals.any((element) {
+      var elementImpl = element as TypeParameterElementImpl;
+      assert(!parameters.contains(elementImpl));
+
+      var bound = elementImpl.bound as TypeImpl;
+      if (bound != null && bound.referencesAny(parameters)) {
+        return true;
+      }
+
+      var defaultType = elementImpl.defaultType as TypeImpl;
+      return defaultType.referencesAny(parameters);
+    })) {
+      return true;
+    }
+
+    if (this.parameters.any((element) {
+      var type = element.type as TypeImpl;
+      return type.referencesAny(parameters);
+    })) {
+      return true;
+    }
+
+    return (returnType as TypeImpl).referencesAny(parameters);
+  }
+
+  @override
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
     if (this.nullabilitySuffix == nullabilitySuffix) return this;
     return FunctionTypeImpl(
@@ -303,8 +330,8 @@
       parameters: parameters,
       returnType: returnType,
       nullabilitySuffix: nullabilitySuffix,
-      element: element,
-      typeArguments: typeArguments,
+      aliasElement: aliasElement,
+      aliasArguments: aliasArguments,
     );
   }
 
@@ -637,7 +664,13 @@
     @required ClassElement element,
     @required this.typeArguments,
     @required this.nullabilitySuffix,
-  }) : super(element);
+    TypeAliasElement aliasElement,
+    List<DartType> aliasArguments,
+  }) : super(
+          element,
+          aliasElement: aliasElement,
+          aliasArguments: aliasArguments,
+        );
 
   @override
   List<PropertyAccessorElement> get accessors {
@@ -1306,6 +1339,14 @@
   }
 
   @override
+  bool referencesAny(Set<TypeParameterElement> parameters) {
+    return typeArguments.any((argument) {
+      var argumentImpl = argument as TypeImpl;
+      return argumentImpl.referencesAny(parameters);
+    });
+  }
+
+  @override
   InterfaceTypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
     if (this.nullabilitySuffix == nullabilitySuffix) return this;
 
@@ -1468,12 +1509,12 @@
   /// search should include the target type. The [visitedInterfaces] is a set
   /// containing all of the interfaces that have been examined, used to prevent
   /// infinite recursion and to optimize the search.
-  static ExecutableElement _lookUpMemberInInterfaces(
+  static T _lookUpMemberInInterfaces<T extends ExecutableElement>(
       InterfaceType targetType,
       bool includeTargetType,
       LibraryElement library,
       HashSet<ClassElement> visitedInterfaces,
-      ExecutableElement Function(InterfaceType type) getMember) {
+      T Function(InterfaceType type) getMember) {
     // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the
     // specification (titled "Inheritance and Overriding" under "Interfaces")
     // describes a much more complex scheme for finding the inherited member.
@@ -1614,7 +1655,9 @@
   final Element _element;
 
   /// Initialize a newly created type to be declared by the given [element].
-  TypeImpl(this._element, {this.aliasElement, this.aliasArguments});
+  TypeImpl(this._element, {this.aliasElement, this.aliasArguments})
+      : assert(aliasElement == null && aliasArguments == null ||
+            aliasElement != null && aliasArguments != null);
 
   @deprecated
   @override
@@ -1704,6 +1747,11 @@
     return builder.toString();
   }
 
+  /// Returns true if this type references any of the [parameters].
+  bool referencesAny(Set<TypeParameterElement> parameters) {
+    return false;
+  }
+
   @override
   DartType resolveToBound(DartType objectType) => this;
 
@@ -1845,6 +1893,11 @@
   }
 
   @override
+  bool referencesAny(Set<TypeParameterElement> parameters) {
+    return parameters.contains(element);
+  }
+
+  @override
   DartType resolveToBound(DartType objectType) {
     if (promotedBound != null) {
       return promotedBound;
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index a6ca14b..a06c562 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -104,6 +104,25 @@
   return Substitution.fromMap(substitution).substituteType(type);
 }
 
+///  1. Substituting T=X! into T! yields X!
+///  2. Substituting T=X* into T! yields X*
+///  3. Substituting T=X? into T! yields X?
+///  4. Substituting T=X! into T* yields X*
+///  5. Substituting T=X* into T* yields X*
+///  6. Substituting T=X? into T* yields X?
+///  7. Substituting T=X! into T? yields X?
+///  8. Substituting T=X* into T? yields X?
+///  9. Substituting T=X? into T? yields X?
+NullabilitySuffix uniteNullabilities(NullabilitySuffix a, NullabilitySuffix b) {
+  if (a == NullabilitySuffix.question || b == NullabilitySuffix.question) {
+    return NullabilitySuffix.question;
+  }
+  if (a == NullabilitySuffix.star || b == NullabilitySuffix.star) {
+    return NullabilitySuffix.star;
+  }
+  return NullabilitySuffix.none;
+}
+
 class FreshTypeParameters {
   final List<TypeParameterElement> freshTypeParameters;
   final Substitution substitution;
@@ -160,7 +179,7 @@
 
   /// Substitutes the type parameters on the class of [type] with the
   /// type arguments provided in [type].
-  static Substitution fromInterfaceType(InterfaceType type) {
+  static MapSubstitution fromInterfaceType(InterfaceType type) {
     if (type.typeArguments.isEmpty) {
       return _NullSubstitution.instance;
     }
@@ -424,7 +443,7 @@
     inner.invertVariance();
 
     var returnType = type.returnType.accept(inner);
-    var typeArguments = _mapList(type.typeArguments);
+    var aliasArguments = _mapList(type.aliasArguments);
 
     if (useCounter == before) return type;
 
@@ -433,8 +452,8 @@
       parameters: parameters,
       returnType: returnType,
       nullabilitySuffix: type.nullabilitySuffix,
-      element: type.element,
-      typeArguments: typeArguments,
+      aliasElement: type.aliasElement,
+      aliasArguments: aliasArguments,
     );
   }
 
@@ -533,7 +552,7 @@
 
     var parameterSuffix = type.nullabilitySuffix;
     var argumentSuffix = argument.nullabilitySuffix;
-    var nullability = _computeNullability(parameterSuffix, argumentSuffix);
+    var nullability = uniteNullabilities(parameterSuffix, argumentSuffix);
     return (argument as TypeImpl).withNullability(nullability);
   }
 
@@ -544,32 +563,9 @@
   DartType visitVoidType(VoidType type) => type;
 
   List<DartType> _mapList(List<DartType> types) {
+    if (types == null) return null;
     return types.map((e) => e.accept(this)).toList();
   }
-
-  ///  1. Substituting T=X! into T! yields X!
-  ///  2. Substituting T=X* into T! yields X*
-  ///  3. Substituting T=X? into T! yields X?
-  ///  4. Substituting T=X! into T* yields X*
-  ///  5. Substituting T=X* into T* yields X*
-  ///  6. Substituting T=X? into T* yields X?
-  ///  7. Substituting T=X! into T? yields X?
-  ///  8. Substituting T=X* into T? yields X?
-  ///  9. Substituting T=X? into T? yields X?
-  static NullabilitySuffix _computeNullability(
-    NullabilitySuffix parameterSuffix,
-    NullabilitySuffix argumentSuffix,
-  ) {
-    if (parameterSuffix == NullabilitySuffix.question ||
-        argumentSuffix == NullabilitySuffix.question) {
-      return NullabilitySuffix.question;
-    }
-    if (parameterSuffix == NullabilitySuffix.star ||
-        argumentSuffix == NullabilitySuffix.star) {
-      return NullabilitySuffix.star;
-    }
-    return NullabilitySuffix.none;
-  }
 }
 
 class _UpperLowerBoundsSubstitution extends Substitution {
diff --git a/pkg/analyzer/lib/src/dart/element/type_provider.dart b/pkg/analyzer/lib/src/dart/element/type_provider.dart
index 0ab40ba..8806048 100644
--- a/pkg/analyzer/lib/src/dart/element/type_provider.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_provider.dart
@@ -116,12 +116,12 @@
   }
 
   @override
-  ClassElement get boolElement {
+  ClassElement /*!*/ get boolElement {
     return _boolElement ??= _getClassElement(_coreLibrary, 'bool');
   }
 
   @override
-  InterfaceType get boolType {
+  InterfaceType /*!*/ get boolType {
     _boolType ??= _getType(_coreLibrary, "bool");
     return _boolType;
   }
@@ -135,37 +135,37 @@
   }
 
   @override
-  InterfaceType get deprecatedType {
+  InterfaceType /*!*/ get deprecatedType {
     _deprecatedType ??= _getType(_coreLibrary, "Deprecated");
     return _deprecatedType;
   }
 
   @override
-  ClassElement get doubleElement {
+  ClassElement /*!*/ get doubleElement {
     return _doubleElement ??= _getClassElement(_coreLibrary, "double");
   }
 
   @override
-  InterfaceType get doubleType {
+  InterfaceType /*!*/ get doubleType {
     _doubleType ??= _getType(_coreLibrary, "double");
     return _doubleType;
   }
 
-  InterfaceType get doubleTypeQuestion =>
+  InterfaceType /*!*/ get doubleTypeQuestion =>
       _doubleTypeQuestion ??= (doubleType as InterfaceTypeImpl)
           .withNullability(NullabilitySuffix.question);
 
   @override
-  DartType get dynamicType => DynamicTypeImpl.instance;
+  DartType /*!*/ get dynamicType => DynamicTypeImpl.instance;
 
   @override
-  InterfaceType get functionType {
+  InterfaceType /*!*/ get functionType {
     _functionType ??= _getType(_coreLibrary, "Function");
     return _functionType;
   }
 
   @override
-  InterfaceType get futureDynamicType {
+  InterfaceType /*!*/ get futureDynamicType {
     _futureDynamicType ??= InterfaceTypeImpl(
       element: futureElement,
       typeArguments: [dynamicType],
@@ -175,12 +175,12 @@
   }
 
   @override
-  ClassElement get futureElement {
+  ClassElement /*!*/ get futureElement {
     return _futureElement ??= _getClassElement(_asyncLibrary, 'Future');
   }
 
   @override
-  InterfaceType get futureNullType {
+  InterfaceType /*!*/ get futureNullType {
     _futureNullType ??= InterfaceTypeImpl(
       element: futureElement,
       typeArguments: [nullType],
@@ -190,12 +190,12 @@
   }
 
   @override
-  ClassElement get futureOrElement {
+  ClassElement /*!*/ get futureOrElement {
     return _futureOrElement ??= _getClassElement(_asyncLibrary, 'FutureOr');
   }
 
   @override
-  InterfaceType get futureOrNullType {
+  InterfaceType /*!*/ get futureOrNullType {
     _futureOrNullType ??= InterfaceTypeImpl(
       element: futureOrElement,
       typeArguments: [nullType],
@@ -205,22 +205,22 @@
   }
 
   @override
-  ClassElement get intElement {
+  ClassElement /*!*/ get intElement {
     return _intElement ??= _getClassElement(_coreLibrary, "int");
   }
 
   @override
-  InterfaceType get intType {
+  InterfaceType /*!*/ get intType {
     _intType ??= _getType(_coreLibrary, "int");
     return _intType;
   }
 
-  InterfaceType get intTypeQuestion =>
+  InterfaceType /*!*/ get intTypeQuestion =>
       _intTypeQuestion ??= (intType as InterfaceTypeImpl)
           .withNullability(NullabilitySuffix.question);
 
   @override
-  InterfaceType get iterableDynamicType {
+  InterfaceType /*!*/ get iterableDynamicType {
     _iterableDynamicType ??= InterfaceTypeImpl(
       element: iterableElement,
       typeArguments: [dynamicType],
@@ -230,12 +230,12 @@
   }
 
   @override
-  ClassElement get iterableElement {
+  ClassElement /*!*/ get iterableElement {
     return _iterableElement ??= _getClassElement(_coreLibrary, 'Iterable');
   }
 
   @override
-  InterfaceType get iterableObjectType {
+  InterfaceType /*!*/ get iterableObjectType {
     _iterableObjectType ??= InterfaceTypeImpl(
       element: iterableElement,
       typeArguments: [objectType],
@@ -245,17 +245,17 @@
   }
 
   @override
-  ClassElement get listElement {
+  ClassElement /*!*/ get listElement {
     return _listElement ??= _getClassElement(_coreLibrary, 'List');
   }
 
   @override
-  ClassElement get mapElement {
+  ClassElement /*!*/ get mapElement {
     return _mapElement ??= _getClassElement(_coreLibrary, 'Map');
   }
 
   @override
-  InterfaceType get mapObjectObjectType {
+  InterfaceType /*!*/ get mapObjectObjectType {
     _mapObjectObjectType ??= InterfaceTypeImpl(
       element: mapElement,
       typeArguments: [objectType, objectType],
@@ -265,12 +265,13 @@
   }
 
   @override
-  DartType get neverType => isNonNullableByDefault
+  DartType /*!*/ get neverType => isNonNullableByDefault
       ? NeverTypeImpl.instance
       : NeverTypeImpl.instanceLegacy;
 
   @override
-  Set<ClassElement> get nonSubtypableClasses => _nonSubtypableClasses ??= {
+  Set<ClassElement> /*!*/ get nonSubtypableClasses =>
+      _nonSubtypableClasses ??= {
         boolElement,
         doubleElement,
         futureOrElement,
@@ -281,11 +282,11 @@
       };
 
   @override
-  ClassElement get nullElement {
+  ClassElement /*!*/ get nullElement {
     return _nullElement ??= _getClassElement(_coreLibrary, 'Null');
   }
 
-  InterfaceTypeImpl get nullStar {
+  InterfaceTypeImpl /*!*/ get nullStar {
     return _nullStar ??= nullElement.instantiate(
       typeArguments: const [],
       nullabilitySuffix: NullabilitySuffix.star,
@@ -293,49 +294,49 @@
   }
 
   @override
-  InterfaceType get nullType {
+  InterfaceType /*!*/ get nullType {
     _nullType ??= _getType(_coreLibrary, "Null");
     return _nullType;
   }
 
   @override
-  ClassElement get numElement {
+  ClassElement /*!*/ get numElement {
     return _numElement ??= _getClassElement(_coreLibrary, 'num');
   }
 
   @override
-  InterfaceType get numType {
+  InterfaceType /*!*/ get numType {
     _numType ??= _getType(_coreLibrary, "num");
     return _numType;
   }
 
-  InterfaceType get numTypeQuestion =>
+  InterfaceType /*!*/ get numTypeQuestion =>
       _numTypeQuestion ??= (numType as InterfaceTypeImpl)
           .withNullability(NullabilitySuffix.question);
 
-  ClassElement get objectElement {
+  ClassElement /*!*/ get objectElement {
     return _objectElement ??= _getClassElement(_coreLibrary, 'Object');
   }
 
   @override
-  InterfaceType get objectType {
+  InterfaceType /*!*/ get objectType {
     _objectType ??= _getType(_coreLibrary, "Object");
     return _objectType;
   }
 
   @override
-  ClassElement get setElement {
+  ClassElement /*!*/ get setElement {
     return _setElement ??= _getClassElement(_coreLibrary, 'Set');
   }
 
   @override
-  InterfaceType get stackTraceType {
+  InterfaceType /*!*/ get stackTraceType {
     _stackTraceType ??= _getType(_coreLibrary, "StackTrace");
     return _stackTraceType;
   }
 
   @override
-  InterfaceType get streamDynamicType {
+  InterfaceType /*!*/ get streamDynamicType {
     _streamDynamicType ??= InterfaceTypeImpl(
       element: streamElement,
       typeArguments: [dynamicType],
@@ -345,34 +346,34 @@
   }
 
   @override
-  ClassElement get streamElement {
+  ClassElement /*!*/ get streamElement {
     return _streamElement ??= _getClassElement(_asyncLibrary, 'Stream');
   }
 
   @override
-  ClassElement get stringElement {
+  ClassElement /*!*/ get stringElement {
     return _stringElement ??= _getClassElement(_coreLibrary, 'String');
   }
 
   @override
-  InterfaceType get stringType {
+  InterfaceType /*!*/ get stringType {
     _stringType ??= _getType(_coreLibrary, "String");
     return _stringType;
   }
 
   @override
-  ClassElement get symbolElement {
+  ClassElement /*!*/ get symbolElement {
     return _symbolElement ??= _getClassElement(_coreLibrary, 'Symbol');
   }
 
   @override
-  InterfaceType get symbolType {
+  InterfaceType /*!*/ get symbolType {
     _symbolType ??= _getType(_coreLibrary, "Symbol");
     return _symbolType;
   }
 
   @override
-  InterfaceType get typeType {
+  InterfaceType /*!*/ get typeType {
     _typeType ??= _getType(_coreLibrary, "Type");
     return _typeType;
   }
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index 3acda34..9b2ab91 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -16,6 +16,7 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/generic_inferrer.dart';
 import 'package:analyzer/src/dart/element/greatest_lower_bound.dart';
+import 'package:analyzer/src/dart/element/least_greatest_closure.dart';
 import 'package:analyzer/src/dart/element/least_upper_bound.dart';
 import 'package:analyzer/src/dart/element/normalize.dart';
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
@@ -348,6 +349,36 @@
     return _leastUpperBoundHelper.getLeastUpperBound(T1, T2);
   }
 
+  /// Returns the greatest closure of [type] with respect to [typeParameters].
+  ///
+  /// https://github.com/dart-lang/language
+  /// See `resources/type-system/inference.md`
+  DartType greatestClosure(
+    DartType type,
+    List<TypeParameterElement> typeParameters,
+  ) {
+    var typeParameterSet = Set<TypeParameterElement>.identity();
+    typeParameterSet.addAll(typeParameters);
+
+    if (isNonNullableByDefault) {
+      return LeastGreatestClosureHelper(
+        typeSystem: this,
+        topType: objectQuestion,
+        topFunctionType: typeProvider.functionType,
+        bottomType: NeverTypeImpl.instance,
+        eliminationTargets: typeParameterSet,
+      ).eliminateToGreatest(type);
+    } else {
+      return LeastGreatestClosureHelper(
+        typeSystem: this,
+        topType: DynamicTypeImpl.instance,
+        topFunctionType: typeProvider.functionType,
+        bottomType: typeProvider.nullType,
+        eliminationTargets: typeParameterSet,
+      ).eliminateToGreatest(type);
+    }
+  }
+
   /// Returns the greatest closure of the given type [schema] with respect to
   /// `_`.
   ///
@@ -362,7 +393,7 @@
   ///
   /// Note that the greatest closure of a type schema is always a supertype of
   /// any type which matches the schema.
-  DartType greatestClosure(DartType schema) {
+  DartType greatestClosureOfSchema(DartType schema) {
     if (isNonNullableByDefault) {
       return TypeSchemaEliminationVisitor.run(
         topType: objectQuestion,
@@ -1170,6 +1201,36 @@
     return false;
   }
 
+  /// Returns the least closure of [type] with respect to [typeParameters].
+  ///
+  /// https://github.com/dart-lang/language
+  /// See `resources/type-system/inference.md`
+  DartType leastClosure(
+    DartType type,
+    List<TypeParameterElement> typeParameters,
+  ) {
+    var typeParameterSet = Set<TypeParameterElement>.identity();
+    typeParameterSet.addAll(typeParameters);
+
+    if (isNonNullableByDefault) {
+      return LeastGreatestClosureHelper(
+        typeSystem: this,
+        topType: objectQuestion,
+        topFunctionType: typeProvider.functionType,
+        bottomType: NeverTypeImpl.instance,
+        eliminationTargets: typeParameterSet,
+      ).eliminateToLeast(type);
+    } else {
+      return LeastGreatestClosureHelper(
+        typeSystem: this,
+        topType: DynamicTypeImpl.instance,
+        topFunctionType: typeProvider.functionType,
+        bottomType: typeProvider.nullType,
+        eliminationTargets: typeParameterSet,
+      ).eliminateToLeast(type);
+    }
+  }
+
   /// Returns the least closure of the given type [schema] with respect to `_`.
   ///
   /// The least closure of a type schema `P` with respect to `_` is defined as
@@ -1183,7 +1244,7 @@
   ///
   /// Note that the least closure of a type schema is always a subtype of any
   /// type which matches the schema.
-  DartType leastClosure(DartType schema) {
+  DartType leastClosureOfSchema(DartType schema) {
     if (isNonNullableByDefault) {
       return TypeSchemaEliminationVisitor.run(
         topType: objectQuestion,
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
index eda16d1..63e796e 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
@@ -23,6 +23,26 @@
       correction: "Try removing the annotation.");
 
   /**
+   * Parameters:
+   * 0: the name of the struct class
+   */
+  static const FfiCode EMPTY_STRUCT = FfiCode(
+      name: 'EMPTY_STRUCT',
+      message: "Struct '{0}' is empty. Empty structs are undefined behavior.",
+      correction: "Try adding a field to '{0}' or use a different Struct.");
+
+  /**
+   * Parameters:
+   * 0: the name of the struct class
+   */
+  static const FfiCode EMPTY_STRUCT_WARNING = FfiCode(
+      name: 'EMPTY_STRUCT_WARNING',
+      message:
+          "Struct '{0}' is empty. Support for empty structs is deprecated and will be removed in the next stable version of Dart. Use Opaque instead.",
+      correction: "Try adding a field to '{0}' or use a different Struct.",
+      type: ErrorType.HINT);
+
+  /**
    * No parameters.
    */
   static const FfiCode EXTRA_ANNOTATION_ON_STRUCT_FIELD = FfiCode(
@@ -37,7 +57,8 @@
   static const FfiCode FIELD_IN_STRUCT_WITH_INITIALIZER = FfiCode(
       name: 'FIELD_IN_STRUCT_WITH_INITIALIZER',
       message: "Fields in subclasses of 'Struct' can't have initializers.",
-      correction: "Try removing the initializer.");
+      correction:
+          "Try removing the initializer and marking the field as external.");
 
   /**
    * No parameters.
@@ -46,7 +67,8 @@
       name: 'FIELD_INITIALIZER_IN_STRUCT',
       message: "Constructors in subclasses of 'Struct' can't have field "
           "initializers.",
-      correction: "Try removing the field initializer.");
+      correction: "Try removing the field initializer and marking the field as"
+          " external.");
 
   /**
    * Parameters:
@@ -76,8 +98,9 @@
       name: 'INVALID_FIELD_TYPE_IN_STRUCT',
       message:
           "Fields in struct classes can't have the type '{0}'. They can only "
-          "be declared as 'int', 'double' or 'Pointer'.",
-      correction: "Try using 'int', 'double' or 'Pointer'.");
+          "be declared as 'int', 'double', 'Pointer', or subtype of 'Struct'.",
+      correction:
+          "Try using 'int', 'double', 'Pointer', or subtype of 'Struct'.");
 
   /**
    * No parameters.
@@ -156,6 +179,20 @@
 
   /**
    * Parameters:
+   * 0: the name of the function, method, or constructor having type arguments
+   */
+  static const FfiCode NON_CONSTANT_TYPE_ARGUMENT_WARNING = FfiCode(
+      name: 'NON_CONSTANT_TYPE_ARGUMENT_WARNING',
+      message:
+          "Support for using non-constant type arguments '{0}' in this FFI API"
+          " is deprecated and will be removed in the next stable version of "
+          "Dart. Rewrite the code to ensure that type arguments are compile "
+          "time constants referring to a valid native type.",
+      correction: "Try changing the type argument to be a constant type.",
+      type: ErrorType.HINT);
+
+  /**
+   * Parameters:
    * 0: the type that should be a valid dart:ffi native type.
    */
   static const FfiCode NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER = FfiCode(
@@ -240,6 +277,9 @@
     uniqueName: 'SUBTYPE_OF_STRUCT_CLASS_IN_WITH',
   );
 
+  @override
+  final ErrorType type;
+
   /// Initialize a newly created error code to have the given [name]. If
   /// [uniqueName] is provided, then it will be used to construct the unique
   /// name for the code, otherwise the name will be used to construct the unique
@@ -256,7 +296,9 @@
     @required String message,
     @required String name,
     String uniqueName,
-  }) : super(
+    ErrorType type = ErrorType.COMPILE_TIME_ERROR,
+  })  : type = type,
+        super(
           correction: correction,
           hasPublishedDocs: hasPublishedDocs,
           message: message,
@@ -266,7 +308,4 @@
 
   @override
   ErrorSeverity get errorSeverity => type.severity;
-
-  @override
-  ErrorType get type => ErrorType.COMPILE_TIME_ERROR;
 }
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 402b9c7..c427645 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -332,8 +332,43 @@
       correction: "Try re-writing the expression to use the '~/' operator.");
 
   /**
-   * Duplicate hidden names.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a name occurs multiple times in
+  // a `hide` clause. Repeating the name is unnecessary.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the name `min` is
+  // hidden more than once:
+  //
+  // ```dart
+  // import 'dart:math' hide min, [!min!];
+  //
+  // var x = pi;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the name was mistyped in one or more places, then correct the mistyped
+  // names:
+  //
+  // ```dart
+  // import 'dart:math' hide max, min;
+  //
+  // var x = pi;
+  // ```
+  //
+  // If the name wasn't mistyped, then remove the unnecessary name from the
+  // list:
+  //
+  // ```dart
+  // import 'dart:math' hide min;
+  //
+  // var x = pi;
+  // ```
   static const HintCode DUPLICATE_HIDDEN_NAME =
       HintCode('DUPLICATE_HIDDEN_NAME', "Duplicate hidden name.",
           correction: "Try removing the repeated name from the list of hidden "
@@ -430,8 +465,43 @@
       hasPublishedDocs: true);
 
   /**
-   * Duplicate shown names.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a name occurs multiple times in
+  // a `show` clause. Repeating the name is unnecessary.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the name `min` is shown
+  // more than once:
+  //
+  // ```dart
+  // import 'dart:math' show min, [!min!];
+  //
+  // var x = min(2, min(0, 1));
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the name was mistyped in one or more places, then correct the mistyped
+  // names:
+  //
+  // ```dart
+  // import 'dart:math' show max, min;
+  //
+  // var x = max(2, min(0, 1));
+  // ```
+  //
+  // If the name wasn't mistyped, then remove the unnecessary name from the
+  // list:
+  //
+  // ```dart
+  // import 'dart:math' show min;
+  //
+  // var x = min(2, min(0, 1));
+  // ```
   static const HintCode DUPLICATE_SHOWN_NAME =
       HintCode('DUPLICATE_SHOWN_NAME', "Duplicate shown name.",
           correction: "Try removing the repeated name from the list of shown "
@@ -1546,19 +1616,6 @@
       hasPublishedDocs: true);
 
   /**
-   * Hint for classes that override equals, but not hashCode.
-   *
-   * Parameters:
-   * 0: the name of the current class
-   */
-  // TODO(brianwilkerson) Decide whether we want to implement this check
-  //  (possibly as a lint) or remove the hint code.
-  static const HintCode OVERRIDE_EQUALS_BUT_NOT_HASH_CODE = HintCode(
-      'OVERRIDE_EQUALS_BUT_NOT_HASH_CODE',
-      "The class '{0}' overrides 'operator==', but not 'get hashCode'.",
-      correction: "Try implementing 'hashCode'.");
-
-  /**
    * A field with the override annotation does not override a getter or setter.
    *
    * No parameters.
@@ -1689,6 +1746,27 @@
       correction: "Annotate '{1}' with 'doNotStore'.");
 
   /**
+   * Parameters:
+   * 0: the return type as declared in the return statement
+   * 1: the expected return type as defined by the type of the Future
+   */
+  static const HintCode RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR = HintCode(
+    'RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR',
+    "A value of type '{0}' can't be returned by the 'onError' handler because "
+        "it must be assignable to '{1}'.",
+  );
+
+  /**
+   * Parameters:
+   * 0: the return type of the function
+   * 1: the expected return type as defined by the type of the Future
+   */
+  static const HintCode RETURN_TYPE_INVALID_FOR_CATCH_ERROR = HintCode(
+      'RETURN_TYPE_INVALID_FOR_CATCH_ERROR',
+      "The return type '{0}' isn't assignable to '{1}', as required by "
+          "'Future.catchError'.");
+
+  /**
    * No parameters.
    */
   // #### Description
@@ -2568,25 +2646,50 @@
   );
 
   /**
-   * Unnecessary type checks, the result is always false.
-   *
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the value of a type check (using
+  // either `is` or `is!`) is known at compile time.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the test `a is Object?`
+  // is always `true`:
+  //
+  // ```dart
+  // bool f<T>(T a) => [!a is Object?!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the type check doesn't check what you intended to check, then change the
+  // test:
+  //
+  // ```dart
+  // bool f<T>(T a) => a is Object;
+  // ```
+  //
+  // If the type check does check what you intended to check, then replace the
+  // type check with its known value or completely remove it:
+  //
+  // ```dart
+  // bool f<T>(T a) => true;
+  // ```
   static const HintCode UNNECESSARY_TYPE_CHECK_FALSE = HintCode(
     'UNNECESSARY_TYPE_CHECK',
-    "Unnecessary type check, the result is always false.",
+    "Unnecessary type check; the result is always 'false'.",
     correction: "Try correcting the type check, or removing the type check.",
     uniqueName: 'UNNECESSARY_TYPE_CHECK_FALSE',
   );
 
   /**
-   * Unnecessary type checks, the result is always true.
-   *
    * No parameters.
    */
   static const HintCode UNNECESSARY_TYPE_CHECK_TRUE = HintCode(
     'UNNECESSARY_TYPE_CHECK',
-    "Unnecessary type check, the result is always true.",
+    "Unnecessary type check; the result is always 'true'.",
     correction: "Try correcting the type check, or removing the type check.",
     uniqueName: 'UNNECESSARY_TYPE_CHECK_TRUE',
   );
diff --git a/pkg/analyzer/lib/src/dart/error/todo_codes.dart b/pkg/analyzer/lib/src/dart/error/todo_codes.dart
index 15db063..3fbccd3 100644
--- a/pkg/analyzer/lib/src/dart/error/todo_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/todo_codes.dart
@@ -30,9 +30,16 @@
    * But not
    * * todo
    * * TODOS
+   * 
+   * It also supports wrapped TODOs where the next line is indented by a space:
+   * 
+   *   /**
+   *    * TODO(username): This line is
+   *    *  wrapped onto the next line
+   *    */
    */
-  static RegExp TODO_REGEX =
-      RegExp("([\\s/\\*])((TODO[^\\w\\d][^\\r\\n]*)|(TODO:?\$))");
+  static RegExp TODO_REGEX = RegExp(
+      "([\\s/\\*])((TODO[^\\w\\d][^\\r\\n]*(?:\\n\\s*\\*  [^\\r\\n]*)*)|(TODO:?\$))");
 
   /**
    * Initialize a newly created error code to have the given [name].
diff --git a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
index 667a28d..3d8351e 100644
--- a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
@@ -103,8 +103,8 @@
   _MicroAnalysisSessionImpl currentSession;
 
   final DeclaredVariables declaredVariables;
-  final SourceFactory sourceFactory;
 
+  final SourceFactory sourceFactory;
   Workspace _workspace;
 
   _MicroAnalysisContextImpl(
@@ -123,6 +123,9 @@
   }
 
   @override
+  Folder get sdkRoot => null;
+
+  @override
   Workspace get workspace {
     return _workspace ??= _buildWorkspace();
   }
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 44ab5b5..12a7a75 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -193,9 +193,8 @@
 
   void _computeConstantErrors(
       ErrorReporter errorReporter, CompilationUnit unit) {
-    ConstantVerifier constantVerifier = ConstantVerifier(
-        errorReporter, _libraryElement, _declaredVariables,
-        featureSet: unit.featureSet);
+    ConstantVerifier constantVerifier =
+        ConstantVerifier(errorReporter, _libraryElement, _declaredVariables);
     unit.accept(constantVerifier);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index 26887ce..971bc79 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -177,8 +177,6 @@
   }
 
   CompilationUnit parse(AnalysisErrorListener errorListener, String content) {
-    AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
-
     CharSequenceReader reader = CharSequenceReader(content);
     Scanner scanner = Scanner(source, reader, errorListener)
       ..configureFeatures(
@@ -190,7 +188,6 @@
     Token token = scanner.tokenize(reportScannerErrors: false);
     LineInfo lineInfo = LineInfo(scanner.lineStarts);
 
-    bool useFasta = analysisOptions.useFastaParser;
     // Pass the feature set from the scanner to the parser
     // because the scanner may have detected a language version comment
     // and downgraded the feature set it holds.
@@ -198,7 +195,6 @@
       source,
       errorListener,
       featureSet: scanner.featureSet,
-      useFasta: useFasta,
     );
     parser.enableOptionalNewAndConst = true;
     CompilationUnit unit = parser.parseCompilationUnit(token);
@@ -460,7 +456,6 @@
   final CiderByteStore _byteStore;
   final SourceFactory _sourceFactory;
   final Workspace _workspace;
-  final AnalysisOptions _analysisOptions;
   final Uint32List _linkedSalt;
 
   /// A function that returns the digest for a file as a String. The function
@@ -486,7 +481,8 @@
     this._byteStore,
     this._sourceFactory,
     this._workspace,
-    this._analysisOptions,
+    @Deprecated('No longer used; will be removed')
+        AnalysisOptions analysisOptions,
     this._linkedSalt,
     this.featureSetProvider,
     this.getFileDigest,
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 29516e9..84d29d8 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -511,8 +511,9 @@
     YamlMap optionMap;
 
     var separator = resourceProvider.pathContext.separator;
-    var isThirdParty =
-        path.contains('${separator}third_party${separator}dart$separator');
+    var isThirdParty = path
+            .contains('${separator}third_party${separator}dart$separator') ||
+        path.contains('${separator}third_party${separator}dart_lang$separator');
 
     File optionsFile;
     if (!isThirdParty) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index bd112a8..6b31839 100644
--- a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -37,7 +37,7 @@
     ElementAnnotationImpl elementAnnotationImpl = node.elementAnnotation;
     if (elementAnnotationImpl == null) {
       // Analyzer ignores annotations on "part of" directives.
-      assert(parent is PartOfDirective);
+      assert(parent is PartDirective || parent is PartOfDirective);
     } else {
       elementAnnotationImpl.annotationAst = _createCloner().cloneNode(node);
     }
@@ -269,28 +269,15 @@
 
   void _resolveAnnotationElementGetter(
       Annotation annotation, PropertyAccessorElement accessorElement) {
-    // accessor should be synthetic
-    if (!accessorElement.isSynthetic) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_ANNOTATION_GETTER, annotation);
-      return;
-    }
-    // variable should be constant
+    // The accessor should be synthetic, the variable should be constant, and
+    // there should be no arguments.
     VariableElement variableElement = accessorElement.variable;
-    if (!variableElement.isConst) {
+    if (!accessorElement.isSynthetic ||
+        !variableElement.isConst ||
+        annotation.arguments != null) {
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
-      return;
     }
-    // no arguments
-    if (annotation.arguments != null) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
-          annotation.name,
-          [annotation.name]);
-    }
-    // OK
-    return;
   }
 
   /// Given an [argumentList] and the [executableElement] that will be invoked
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index ebe7c47..25c3137 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -91,7 +91,7 @@
 
     if (flow != null) {
       if (writeElement is VariableElement) {
-        flow.write(writeElement, node.staticType);
+        flow.write(writeElement, node.staticType, hasRead ? null : right);
       }
       if (isIfNull) {
         flow.ifNullExpression_end();
diff --git a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
index 9daaea2..377e713 100644
--- a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
@@ -6,9 +6,11 @@
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/scope.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:meta/meta.dart';
 
 /// Helper for [MethodInvocation]s into [InstanceCreationExpression] to support
 /// the optional `new` and `const` feature, or [ExtensionOverride].
@@ -34,14 +36,10 @@
       }
       Element element = nameScope.lookup(methodName.name).getter;
       if (element is ClassElement) {
-        TypeName typeName = astFactory.typeName(methodName, node.typeArguments);
-        ConstructorName constructorName =
-            astFactory.constructorName(typeName, null, null);
-        InstanceCreationExpression instanceCreationExpression =
-            astFactory.instanceCreationExpression(
-                null, constructorName, node.argumentList);
-        NodeReplacer.replace(node, instanceCreationExpression);
-        return instanceCreationExpression;
+        return _toInstanceCreation_type(
+          node: node,
+          typeIdentifier: methodName,
+        );
       } else if (element is ExtensionElement) {
         ExtensionOverride extensionOverride = astFactory.extensionOverride(
             extensionName: methodName,
@@ -49,6 +47,12 @@
             argumentList: node.argumentList);
         NodeReplacer.replace(node, extensionOverride);
         return extensionOverride;
+      } else if (element is TypeAliasElement &&
+          element.aliasedType is InterfaceType) {
+        return _toInstanceCreation_type(
+          node: node,
+          typeIdentifier: methodName,
+        );
       }
     } else if (target is SimpleIdentifier) {
       // Possible cases: C.n(), p.C() or p.C<>()
@@ -58,41 +62,23 @@
       }
       Element element = nameScope.lookup(target.name).getter;
       if (element is ClassElement) {
-        // Possible case: C.n()
-        var constructorElement = element.getNamedConstructor(methodName.name);
-        if (constructorElement != null) {
-          var typeArguments = node.typeArguments;
-          if (typeArguments != null) {
-            _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
-                typeArguments,
-                [element.name, constructorElement.name]);
-          }
-          TypeName typeName = astFactory.typeName(target, null);
-          ConstructorName constructorName =
-              astFactory.constructorName(typeName, node.operator, methodName);
-          // TODO(scheglov) I think we should drop "typeArguments" below.
-          InstanceCreationExpression instanceCreationExpression =
-              astFactory.instanceCreationExpression(
-                  null, constructorName, node.argumentList,
-                  typeArguments: typeArguments);
-          NodeReplacer.replace(node, instanceCreationExpression);
-          return instanceCreationExpression;
-        }
+        // class C { C.named(); }
+        // C.named()
+        return _toInstanceCreation_type_constructor(
+          node: node,
+          typeIdentifier: target,
+          constructorIdentifier: methodName,
+          classElement: element,
+        );
       } else if (element is PrefixElement) {
         // Possible cases: p.C() or p.C<>()
         Element prefixedElement = element.scope.lookup(methodName.name).getter;
         if (prefixedElement is ClassElement) {
-          TypeName typeName = astFactory.typeName(
-              astFactory.prefixedIdentifier(target, node.operator, methodName),
-              node.typeArguments);
-          ConstructorName constructorName =
-              astFactory.constructorName(typeName, null, null);
-          InstanceCreationExpression instanceCreationExpression =
-              astFactory.instanceCreationExpression(
-                  null, constructorName, node.argumentList);
-          NodeReplacer.replace(node, instanceCreationExpression);
-          return instanceCreationExpression;
+          return _toInstanceCreation_prefix_type(
+            node: node,
+            prefixIdentifier: target,
+            typeIdentifier: methodName,
+          );
         } else if (prefixedElement is ExtensionElement) {
           PrefixedIdentifier extensionName =
               astFactory.prefixedIdentifier(target, node.operator, methodName);
@@ -102,38 +88,143 @@
               argumentList: node.argumentList);
           NodeReplacer.replace(node, extensionOverride);
           return extensionOverride;
+        } else if (prefixedElement is TypeAliasElement &&
+            prefixedElement.aliasedType is InterfaceType) {
+          return _toInstanceCreation_prefix_type(
+            node: node,
+            prefixIdentifier: target,
+            typeIdentifier: methodName,
+          );
+        }
+      } else if (element is TypeAliasElement) {
+        var aliasedType = element.aliasedType;
+        if (aliasedType is InterfaceType) {
+          // class C { C.named(); }
+          // typedef X = C;
+          // X.named()
+          return _toInstanceCreation_type_constructor(
+            node: node,
+            typeIdentifier: target,
+            constructorIdentifier: methodName,
+            classElement: aliasedType.element,
+          );
         }
       }
     } else if (target is PrefixedIdentifier) {
       // Possible case: p.C.n()
-      Element prefixElement = nameScope.lookup(target.prefix.name).getter;
+      var prefixElement = nameScope.lookup(target.prefix.name).getter;
       target.prefix.staticElement = prefixElement;
       if (prefixElement is PrefixElement) {
-        Element element =
-            prefixElement.scope.lookup(target.identifier.name).getter;
+        var prefixedName = target.identifier.name;
+        var element = prefixElement.scope.lookup(prefixedName).getter;
         if (element is ClassElement) {
-          var constructorElement = element.getNamedConstructor(methodName.name);
-          if (constructorElement != null) {
-            var typeArguments = node.typeArguments;
-            if (typeArguments != null) {
-              _errorReporter.reportErrorForNode(
-                  CompileTimeErrorCode
-                      .WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
-                  typeArguments,
-                  [element.name, constructorElement.name]);
-            }
-            TypeName typeName = astFactory.typeName(target, typeArguments);
-            ConstructorName constructorName =
-                astFactory.constructorName(typeName, node.operator, methodName);
-            InstanceCreationExpression instanceCreationExpression =
-                astFactory.instanceCreationExpression(
-                    null, constructorName, node.argumentList);
-            NodeReplacer.replace(node, instanceCreationExpression);
-            return instanceCreationExpression;
+          return _instanceCreation_prefix_type_name(
+            node: node,
+            typeNameIdentifier: target,
+            constructorIdentifier: methodName,
+            classElement: element,
+          );
+        } else if (element is TypeAliasElement) {
+          var aliasedType = element.aliasedType;
+          if (aliasedType is InterfaceType) {
+            return _instanceCreation_prefix_type_name(
+              node: node,
+              typeNameIdentifier: target,
+              constructorIdentifier: methodName,
+              classElement: aliasedType.element,
+            );
           }
         }
       }
     }
     return node;
   }
+
+  AstNode _instanceCreation_prefix_type_name({
+    @required MethodInvocation node,
+    @required PrefixedIdentifier typeNameIdentifier,
+    @required SimpleIdentifier constructorIdentifier,
+    @required ClassElement classElement,
+  }) {
+    var constructorElement = classElement.getNamedConstructor(
+      constructorIdentifier.name,
+    );
+    if (constructorElement == null) {
+      return node;
+    }
+
+    var typeArguments = node.typeArguments;
+    if (typeArguments != null) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
+          typeArguments,
+          [classElement.name, constructorElement.name]);
+    }
+
+    var typeName = astFactory.typeName(typeNameIdentifier, typeArguments);
+    var constructorName = astFactory.constructorName(
+        typeName, node.operator, constructorIdentifier);
+    var instanceCreationExpression = astFactory.instanceCreationExpression(
+        null, constructorName, node.argumentList);
+    NodeReplacer.replace(node, instanceCreationExpression);
+    return instanceCreationExpression;
+  }
+
+  InstanceCreationExpression _toInstanceCreation_prefix_type({
+    @required MethodInvocation node,
+    @required SimpleIdentifier prefixIdentifier,
+    @required SimpleIdentifier typeIdentifier,
+  }) {
+    var typeName = astFactory.typeName(
+        astFactory.prefixedIdentifier(
+            prefixIdentifier, node.operator, typeIdentifier),
+        node.typeArguments);
+    var constructorName = astFactory.constructorName(typeName, null, null);
+    var instanceCreationExpression = astFactory.instanceCreationExpression(
+        null, constructorName, node.argumentList);
+    NodeReplacer.replace(node, instanceCreationExpression);
+    return instanceCreationExpression;
+  }
+
+  InstanceCreationExpression _toInstanceCreation_type({
+    @required MethodInvocation node,
+    @required SimpleIdentifier typeIdentifier,
+  }) {
+    var typeName = astFactory.typeName(typeIdentifier, node.typeArguments);
+    var constructorName = astFactory.constructorName(typeName, null, null);
+    var instanceCreationExpression = astFactory.instanceCreationExpression(
+        null, constructorName, node.argumentList);
+    NodeReplacer.replace(node, instanceCreationExpression);
+    return instanceCreationExpression;
+  }
+
+  AstNode _toInstanceCreation_type_constructor({
+    @required MethodInvocation node,
+    @required SimpleIdentifier typeIdentifier,
+    @required SimpleIdentifier constructorIdentifier,
+    @required ClassElement classElement,
+  }) {
+    var name = constructorIdentifier.name;
+    var constructorElement = classElement.getNamedConstructor(name);
+    if (constructorElement == null) {
+      return node;
+    }
+
+    var typeArguments = node.typeArguments;
+    if (typeArguments != null) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
+          typeArguments,
+          [classElement.name, constructorElement.name]);
+    }
+    var typeName = astFactory.typeName(typeIdentifier, null);
+    var constructorName = astFactory.constructorName(
+        typeName, node.operator, constructorIdentifier);
+    // TODO(scheglov) I think we should drop "typeArguments" below.
+    var instanceCreationExpression = astFactory.instanceCreationExpression(
+        null, constructorName, node.argumentList,
+        typeArguments: typeArguments);
+    NodeReplacer.replace(node, instanceCreationExpression);
+    return instanceCreationExpression;
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index 7572eeb..92bb29d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -181,7 +181,7 @@
     left = node.leftOperand;
 
     if (_flowAnalysis != null) {
-      flow?.logicalBinaryOp_rightBegin(left, isAnd: true);
+      flow?.logicalBinaryOp_rightBegin(left, node, isAnd: true);
       _resolver.checkUnreachableNode(right);
 
       right.accept(_resolver);
@@ -218,7 +218,7 @@
     left.accept(_resolver);
     left = node.leftOperand;
 
-    flow?.logicalBinaryOp_rightBegin(left, isAnd: false);
+    flow?.logicalBinaryOp_rightBegin(left, node, isAnd: false);
     _resolver.checkUnreachableNode(right);
 
     right.accept(_resolver);
@@ -293,6 +293,7 @@
         );
       }
       node.staticElement = member;
+      node.staticInvokeType = member?.type;
       return;
     }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index 0fab9d3..1e46e61 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -193,10 +193,14 @@
   }
 
   void labeledStatement_enter(LabeledStatement node) {
+    if (flow == null) return;
+
     flow.labeledStatement_begin(node);
   }
 
   void labeledStatement_exit(LabeledStatement node) {
+    if (flow == null) return;
+
     flow.labeledStatement_end();
   }
 
@@ -393,6 +397,18 @@
   }
 
   @override
+  void visitBinaryExpression(BinaryExpression node) {
+    if (node.operator.type == TokenType.AMPERSAND_AMPERSAND) {
+      node.leftOperand.accept(this);
+      assignedVariables.beginNode();
+      node.rightOperand.accept(this);
+      assignedVariables.endNode(node);
+    } else {
+      super.visitBinaryExpression(node);
+    }
+  }
+
+  @override
   void visitCatchClause(CatchClause node) {
     for (var identifier in [
       node.exceptionParameter,
@@ -407,6 +423,15 @@
   }
 
   @override
+  void visitConditionalExpression(ConditionalExpression node) {
+    node.condition.accept(this);
+    assignedVariables.beginNode();
+    node.thenExpression.accept(this);
+    assignedVariables.endNode(node);
+    node.elseExpression.accept(this);
+  }
+
+  @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
     throw StateError('Should not visit top level declarations');
   }
@@ -454,6 +479,24 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    node.condition.accept(this);
+    assignedVariables.beginNode();
+    node.thenElement.accept(this);
+    assignedVariables.endNode(node);
+    node.elseElement?.accept(this);
+  }
+
+  @override
+  void visitIfStatement(IfStatement node) {
+    node.condition.accept(this);
+    assignedVariables.beginNode();
+    node.thenStatement.accept(this);
+    assignedVariables.endNode(node);
+    node.elseStatement?.accept(this);
+  }
+
+  @override
   void visitMethodDeclaration(MethodDeclaration node) {
     throw StateError('Should not visit top level declarations');
   }
@@ -487,6 +530,17 @@
   }
 
   @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    var element = node.staticElement;
+    if (element is VariableElement &&
+        node.inGetterContext() &&
+        node.parent is! FormalParameter &&
+        node.parent is! CatchClause) {
+      assignedVariables.read(element);
+    }
+  }
+
+  @override
   void visitSwitchStatement(SwitchStatement node) {
     var expression = node.expression;
     var members = node.members;
diff --git a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
index 8946ab4..b4f7848 100644
--- a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:meta/meta.dart';
 
@@ -118,7 +119,9 @@
     iterable?.accept(_resolver);
     iterable = forEachParts.iterable;
 
-    _resolver.nullableDereferenceVerifier.expression(iterable);
+    _resolver.nullableDereferenceVerifier.expression(iterable,
+        errorCode:
+            CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR);
 
     loopVariable?.accept(_resolver);
     var elementType = _computeForEachElementType(iterable, isAsync);
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
index 9c98040..28cd2ec 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
@@ -43,7 +43,8 @@
       return;
     }
 
-    _nullableDereferenceVerifier.expression(function);
+    _nullableDereferenceVerifier.expression(function,
+        errorCode: CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE);
 
     var receiverType = function.staticType;
     if (receiverType is FunctionType) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
index 0f3a2b1..56332a4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
@@ -69,7 +69,7 @@
       if (_flowAnalysis.flow != null && !isFunctionDeclaration) {
         var bodyContext = BodyInferenceContext.of(node.body);
         _resolver.checkForBodyMayCompleteNormally(
-          returnType: bodyContext.contextType,
+          returnType: bodyContext?.contextType,
           body: body,
           errorNode: body,
         );
@@ -98,7 +98,7 @@
         // corresponding parameter in the context type schema with type
         // schema `K`, the parameter is given an inferred type `T` where `T`
         // is derived from `K` as follows.
-        inferredType = _typeSystem.greatestClosure(inferredType);
+        inferredType = _typeSystem.greatestClosureOfSchema(inferredType);
 
         // If the greatest closure of `K` is `S` and `S` is a subtype of
         // `Null`, then `T` is `Object?`. Otherwise, `T` is `S`.
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 32e61ba..a3349c3 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -132,6 +132,13 @@
           name,
           _resolver.typeProvider.typeType.element,
         );
+      } else if (element is TypeAliasElement) {
+        var aliasedType = element.aliasedType;
+        if (aliasedType is InterfaceType) {
+          _resolveReceiverTypeLiteral(
+              node, aliasedType.element, nameNode, name);
+          return;
+        }
       }
     }
 
@@ -459,7 +466,9 @@
         );
       } else {
         _setDynamicResolution(node);
-        _resolver.nullableDereferenceVerifier.report(receiver, receiverType);
+        _resolver.nullableDereferenceVerifier.report(receiver, receiverType,
+            errorCode: CompileTimeErrorCode
+                .UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE);
       }
       return;
     }
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index 2f7d76f..3a8cef1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -180,7 +180,7 @@
       if (operand is SimpleIdentifier) {
         var element = operand.staticElement;
         if (element is PromotableElement) {
-          _flowAnalysis?.flow?.write(element, operatorReturnType);
+          _flowAnalysis?.flow?.write(element, operatorReturnType, null);
         }
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index cfaaf15..a88e693 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -217,7 +217,7 @@
         if (operand is SimpleIdentifier) {
           var element = operand.staticElement;
           if (element is PromotableElement) {
-            _flowAnalysis?.flow?.write(element, staticType);
+            _flowAnalysis?.flow?.write(element, staticType, null);
           }
         }
       }
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
index 6d65356..a6e5194 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
@@ -61,7 +61,7 @@
       node.staticType = type;
       identifier.staticType = type;
       return;
-    } else if (element is FunctionTypeAliasElement) {
+    } else if (element is TypeAliasElement) {
       if (node.parent is TypeName) {
         // no type
       } else {
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 a271757e..a649b31 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -298,15 +298,24 @@
     if (target is Identifier) {
       var targetElement = target.staticElement;
       if (targetElement is ClassElement) {
-        if (isCascaded) {
-          targetElement = _resolver.typeProvider.typeType.element;
-        }
         return _resolveTargetClassElement(
           typeReference: targetElement,
+          isCascaded: isCascaded,
           propertyName: propertyName,
           hasRead: hasRead,
           hasWrite: hasWrite,
         );
+      } else if (targetElement is TypeAliasElement) {
+        var aliasedType = targetElement.aliasedType;
+        if (aliasedType is InterfaceType) {
+          return _resolveTargetClassElement(
+            typeReference: aliasedType.element,
+            isCascaded: isCascaded,
+            propertyName: propertyName,
+            hasRead: hasRead,
+            hasWrite: hasWrite,
+          );
+        }
       }
     }
 
@@ -382,10 +391,15 @@
 
   PropertyElementResolverResult _resolveTargetClassElement({
     @required ClassElement typeReference,
+    @required bool isCascaded,
     @required SimpleIdentifier propertyName,
     @required bool hasRead,
     @required bool hasWrite,
   }) {
+    if (isCascaded) {
+      typeReference = _resolver.typeProvider.typeType.element;
+    }
+
     ExecutableElement readElement;
     if (hasRead) {
       readElement = typeReference.getGetter(propertyName.name);
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 0eebe01..b9c2384 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -248,11 +248,10 @@
     for (FunctionElement element in compilationUnit.functions) {
       _addIfPublic(definedNames, element);
     }
-    for (FunctionTypeAliasElement element
-        in compilationUnit.functionTypeAliases) {
+    for (ClassElement element in compilationUnit.mixins) {
       _addIfPublic(definedNames, element);
     }
-    for (ClassElement element in compilationUnit.mixins) {
+    for (TypeAliasElement element in compilationUnit.typeAliases) {
       _addIfPublic(definedNames, element);
     }
     for (ClassElement element in compilationUnit.types) {
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 d3b354b..785ea9f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -246,9 +246,8 @@
       }
       return;
     } else if (element is TypeAliasElement) {
-      if (node.inDeclarationContext() || node.parent is TypeName) {
-        // no type
-      } else {
+      if (_isExpressionIdentifier(node) ||
+          element.aliasedType is! InterfaceType) {
         node.staticType = _typeProvider.typeType;
       }
       return;
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 c077118..38e717a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
@@ -79,7 +79,7 @@
         return;
       }
 
-      if (prefixElement is ClassElement) {
+      if (prefixElement is ClassElement || prefixElement is TypeAliasElement) {
         _rewriteToConstructorName(node, typeIdentifier);
         return;
       }
@@ -144,12 +144,7 @@
   NullabilitySuffix _getNullability(TypeName node) {
     if (isNonNullableByDefault) {
       if (node.question != null) {
-        if (identical(node, classHierarchy_typeName)) {
-          _reportInvalidNullableType(node);
-          return NullabilitySuffix.none;
-        } else {
-          return NullabilitySuffix.question;
-        }
+        return NullabilitySuffix.question;
       } else {
         return NullabilitySuffix.none;
       }
@@ -196,12 +191,6 @@
           typeArguments: typeArguments,
           nullabilitySuffix: nullability,
         );
-      } else if (_isInstanceCreation(node)) {
-        _ErrorHelper(errorReporter).reportNewWithNonType(node);
-        return dynamicType;
-      } else if (element is DynamicElementImpl) {
-        _buildTypeArguments(node, 0);
-        return DynamicTypeImpl.instance;
       } else if (element is TypeAliasElement) {
         var typeArguments = _buildTypeArguments(
           node,
@@ -212,7 +201,13 @@
           nullabilitySuffix: nullability,
         );
         type = typeSystem.toLegacyType(type);
-        return type;
+        return _verifyTypeAliasForContext(node, element, type);
+      } else if (_isInstanceCreation(node)) {
+        _ErrorHelper(errorReporter).reportNewWithNonType(node);
+        return dynamicType;
+      } else if (element is DynamicElementImpl) {
+        _buildTypeArguments(node, 0);
+        return DynamicTypeImpl.instance;
       } else if (element is NeverElementImpl) {
         _buildTypeArguments(node, 0);
         return _instantiateElementNever(nullability);
@@ -244,16 +239,17 @@
         classElement: element,
         nullabilitySuffix: nullability,
       );
+    } else if (element is TypeAliasElement) {
+      var type = typeSystem.instantiateToBounds2(
+        typeAliasElement: element,
+        nullabilitySuffix: nullability,
+      );
+      return _verifyTypeAliasForContext(node, element, type);
     } else if (_isInstanceCreation(node)) {
       _ErrorHelper(errorReporter).reportNewWithNonType(node);
       return dynamicType;
     } else if (element is DynamicElementImpl) {
       return DynamicTypeImpl.instance;
-    } else if (element is TypeAliasElement) {
-      return typeSystem.instantiateToBounds2(
-        typeAliasElement: element,
-        nullabilitySuffix: nullability,
-      );
     } else if (element is NeverElementImpl) {
       return _instantiateElementNever(nullability);
     } else if (element is TypeParameterElement) {
@@ -274,33 +270,6 @@
     }
   }
 
-  /// Given a [typeName] that has a question mark, report an error and return
-  /// `true` if it appears in a location where a nullable type is not allowed.
-  void _reportInvalidNullableType(TypeName typeName) {
-    AstNode parent = typeName.parent;
-    if (parent is ExtendsClause || parent is ClassTypeAlias) {
-      errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE,
-        typeName,
-      );
-    } else if (parent is ImplementsClause) {
-      errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE,
-        typeName,
-      );
-    } else if (parent is OnClause) {
-      errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE,
-        typeName,
-      );
-    } else if (parent is WithClause) {
-      errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE,
-        typeName,
-      );
-    }
-  }
-
   void _resolveToElement(TypeName node, Element element) {
     if (element == null) {
       node.type = dynamicType;
@@ -315,7 +284,9 @@
       return;
     }
 
-    node.type = _instantiateElement(node, element);
+    var type = _instantiateElement(node, element);
+    type = _verifyNullability(node, type);
+    node.type = type;
   }
 
   /// We parse `foo.bar` as `prefix.Name` with the expectation that `prefix`
@@ -366,6 +337,62 @@
     }
   }
 
+  /// If the [node] appears in a location where a nullable type is not allowed,
+  /// but the [type] is nullable (because the question mark was specified,
+  /// or the type alias is nullable), report an error, and return the
+  /// corresponding non-nullable type.
+  DartType _verifyNullability(TypeName node, DartType type) {
+    if (identical(node, classHierarchy_typeName)) {
+      if (type.nullabilitySuffix == NullabilitySuffix.question) {
+        var parent = node.parent;
+        if (parent is ExtendsClause || parent is ClassTypeAlias) {
+          errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE,
+            node,
+          );
+        } else if (parent is ImplementsClause) {
+          errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE,
+            node,
+          );
+        } else if (parent is OnClause) {
+          errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE,
+            node,
+          );
+        } else if (parent is WithClause) {
+          errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE,
+            node,
+          );
+        }
+        return (type as TypeImpl).withNullability(NullabilitySuffix.none);
+      }
+    }
+
+    return type;
+  }
+
+  DartType _verifyTypeAliasForContext(
+    TypeName node,
+    TypeAliasElement element,
+    DartType type,
+  ) {
+    if (element.aliasedType is TypeParameterType) {
+      var constructorName = node.parent;
+      if (constructorName is ConstructorName) {
+        _ErrorHelper(errorReporter)
+            .reportTypeAliasExpandsToTypeParameter(constructorName, element);
+        return dynamicType;
+      }
+    }
+    if (type is! InterfaceType && _isInstanceCreation(node)) {
+      _ErrorHelper(errorReporter).reportNewWithNonType(node);
+      return dynamicType;
+    }
+    return type;
+  }
+
   static bool _isInstanceCreation(TypeName node) {
     return node.parent is ConstructorName &&
         node.parent.parent is InstanceCreationExpression;
@@ -406,6 +433,7 @@
       errorReporter.reportErrorForNode(
         CompileTimeErrorCode.UNDEFINED_CLASS_BOOLEAN,
         errorNode,
+        [identifier.name],
       );
       return;
     }
@@ -513,6 +541,28 @@
     );
   }
 
+  void reportTypeAliasExpandsToTypeParameter(
+    ConstructorName constructorName,
+    TypeAliasElement element,
+  ) {
+    var errorNode = _getErrorNode(constructorName.type);
+    var constructorUsage = constructorName.parent;
+    if (constructorUsage is InstanceCreationExpression) {
+      errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+        errorNode,
+      );
+    } else if (constructorUsage is ConstructorDeclaration &&
+        constructorUsage.redirectedConstructor == constructorName) {
+      errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+        errorNode,
+      );
+    } else {
+      throw UnimplementedError('${constructorUsage.runtimeType}');
+    }
+  }
+
   /// Returns the simple identifier of the given (maybe prefixed) identifier.
   static Identifier _getErrorNode(TypeName node) {
     Identifier identifier = node.name;
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
index dc990de..b12e424 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
@@ -12,6 +12,7 @@
 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/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:meta/meta.dart';
 
@@ -91,10 +92,34 @@
         return _toResult();
       }
 
+      var parentExpression = (receiver ?? receiverErrorNode).parent;
+      CompileTimeErrorCode errorCode;
+      if (parentExpression == null) {
+        errorCode = CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE;
+      } else {
+        if (parentExpression is CascadeExpression) {
+          parentExpression =
+              (parentExpression as CascadeExpression).cascadeSections.first;
+        }
+        if (parentExpression is BinaryExpression) {
+          errorCode = CompileTimeErrorCode
+              .UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE;
+        } else if (parentExpression is MethodInvocation ||
+            parentExpression is MethodReferenceExpression) {
+          errorCode = CompileTimeErrorCode
+              .UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE;
+        } else if (parentExpression is FunctionExpressionInvocation) {
+          errorCode =
+              CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE;
+        } else {
+          errorCode =
+              CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE;
+        }
+      }
+
       _resolver.nullableDereferenceVerifier.report(
-        receiverErrorNode,
-        receiverType,
-      );
+          receiverErrorNode, receiverType,
+          errorCode: errorCode, arguments: [name]);
       _reportedGetterError = true;
       _reportedSetterError = true;
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
index e79edc9..672ed6f 100644
--- a/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
@@ -135,7 +135,9 @@
     node.expression.accept(_resolver);
 
     if (node.star != null) {
-      _resolver.nullableDereferenceVerifier.expression(node.expression);
+      _resolver.nullableDereferenceVerifier.expression(node.expression,
+          errorCode: CompileTimeErrorCode
+              .UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH);
     }
 
     _resolver.inferenceContext.bodyContext?.addYield(node);
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
index 0a0d0fa..8b55ebf 100644
--- a/pkg/analyzer/lib/src/dart/sdk/sdk.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -29,7 +29,7 @@
 /// library map.
 abstract class AbstractDartSdk implements DartSdk {
   /// The resource provider used to access the file system.
-  ResourceProvider resourceProvider;
+  /*late final*/ ResourceProvider resourceProvider;
 
   /// A mapping from Dart library URI's to the library represented by that URI.
   LibraryMap libraryMap = LibraryMap();
@@ -130,7 +130,7 @@
   }
 
   @override
-  Source mapDartUri(String dartUri) {
+  Source mapDartUri(String /*!*/ dartUri) {
     Source source = _uriToSourceMap[dartUri];
     if (source == null) {
       source = internalMapDartUri(dartUri);
@@ -288,9 +288,9 @@
   ///
   /// If a key doesn't begin with `dart:` it is ignored.
   void _processEmbedderYaml(Folder libDir, YamlMap map) {
-    YamlNode embedded_libs = map[_EMBEDDED_LIB_MAP_KEY];
-    if (embedded_libs is YamlMap) {
-      embedded_libs.forEach((k, v) => _processEmbeddedLibs(k, v, libDir));
+    YamlNode embeddedLibs = map[_EMBEDDED_LIB_MAP_KEY];
+    if (embeddedLibs is YamlMap) {
+      embeddedLibs.forEach((k, v) => _processEmbeddedLibs(k, v, libDir));
     }
   }
 }
@@ -351,17 +351,17 @@
   final Folder _sdkDirectory;
 
   /// The directory within the SDK directory that contains the libraries.
-  Folder _libraryDirectory;
+  /*late final*/ Folder _libraryDirectory;
 
   /// The revision number of this SDK, or `"0"` if the revision number cannot be
   /// discovered.
-  String _sdkVersion;
+  /*late final*/ String _sdkVersion;
 
   /// The cached language version of this SDK.
-  Version _languageVersion;
+  /*late final*/ Version _languageVersion;
 
   /// The file containing the pub executable.
-  File _pubExecutable;
+  /*late final*/ File _pubExecutable;
 
   /// Initialize a newly created SDK to represent the Dart SDK installed in the
   /// [sdkDirectory].
@@ -473,8 +473,8 @@
   /// Return the initialized library map.
   LibraryMap initialLibraryMap() {
     List<String> searchedPaths = <String>[];
-    StackTrace lastStackTrace;
-    Object lastException;
+    /*late*/ StackTrace lastStackTrace;
+    /*late*/ Object lastException;
     for (File librariesFile in _libraryMapLocations) {
       try {
         String contents = librariesFile.readAsStringSync();
diff --git a/pkg/analyzer/lib/src/error/assignment_verifier.dart b/pkg/analyzer/lib/src/error/assignment_verifier.dart
index 54f0b21..b3f762b 100644
--- a/pkg/analyzer/lib/src/error/assignment_verifier.dart
+++ b/pkg/analyzer/lib/src/error/assignment_verifier.dart
@@ -59,7 +59,7 @@
 
     if (recovery is ClassElement ||
         recovery is DynamicElementImpl ||
-        recovery is FunctionTypeAliasElement ||
+        recovery is TypeAliasElement ||
         recovery is TypeParameterElement) {
       _errorReporter.reportErrorForNode(
         CompileTimeErrorCode.ASSIGNMENT_TO_TYPE,
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 45b860a..cbb6ab5 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -23,6 +23,7 @@
 import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
 import 'package:analyzer/src/dart/resolver/exit_detector.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/error/catch_error_verifier.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/error/deprecated_member_use_verifier.dart';
 import 'package:analyzer/src/error/must_call_super_verifier.dart';
@@ -49,7 +50,7 @@
 
   /// A flag indicating whether a surrounding member is annotated as
   /// `@doNotStore`.
-  bool _inDoNotStoreMember;
+  bool _inDoNotStoreMember = false;
 
   /// The error reporter by which errors will be reported.
   final ErrorReporter _errorReporter;
@@ -72,6 +73,8 @@
 
   final MustCallSuperVerifier _mustCallSuperVerifier;
 
+  final CatchErrorVerifier _catchErrorVerifier;
+
   /// The [WorkspacePackage] in which [_currentLibrary] is declared.
   final WorkspacePackage _workspacePackage;
 
@@ -109,6 +112,8 @@
         _deprecatedVerifier =
             DeprecatedMemberUseVerifier(workspacePackage, _errorReporter),
         _mustCallSuperVerifier = MustCallSuperVerifier(_errorReporter),
+        _catchErrorVerifier =
+            CatchErrorVerifier(_errorReporter, typeProvider, typeSystem),
         _workspacePackage = workspacePackage {
     _deprecatedVerifier.pushInDeprecatedValue(_currentLibrary.hasDeprecated);
     _inDoNotStoreMember = _currentLibrary.hasDoNotStore;
@@ -297,7 +302,7 @@
 
   @override
   void visitClassDeclaration(ClassDeclaration node) {
-    ClassElementImpl element = node.declaredElement;
+    var element = node.declaredElement as ClassElementImpl;
     _enclosingClass = element;
     _invalidAccessVerifier._enclosingClass = element;
 
@@ -421,8 +426,7 @@
       _inDoNotStoreMember = true;
     }
     try {
-      _checkForMissingReturn(
-          node.returnType, node.functionExpression.body, element, node);
+      _checkForMissingReturn(node.functionExpression.body, node);
 
       // Return types are inferred only on non-recursive local functions.
       if (node.parent is CompilationUnit && !node.isSetter) {
@@ -447,7 +451,7 @@
   @override
   void visitFunctionExpression(FunctionExpression node) {
     if (node.parent is! FunctionDeclaration) {
-      _checkForMissingReturn(null, node.body, node.declaredElement, node);
+      _checkForMissingReturn(node.body, node);
     }
     DartType functionType = InferenceContext.getContext(node);
     if (functionType is! FunctionType) {
@@ -557,7 +561,7 @@
     try {
       // This was determined to not be a good hint, see: dartbug.com/16029
       //checkForOverridingPrivateMember(node);
-      _checkForMissingReturn(node.returnType, node.body, element, node);
+      _checkForMissingReturn(node.body, node);
       _mustCallSuperVerifier.checkMethodDeclaration(node);
       _checkForUnnecessaryNoSuchMethod(node);
 
@@ -589,6 +593,7 @@
   void visitMethodInvocation(MethodInvocation node) {
     _deprecatedVerifier.methodInvocation(node);
     _checkForNullAwareHints(node, node.operator);
+    _catchErrorVerifier.verifyMethodInvocation(node);
     super.visitMethodInvocation(node);
   }
 
@@ -692,8 +697,8 @@
   bool _checkAllTypeChecks(IsExpression node) {
     Expression expression = node.expression;
     TypeAnnotation typeName = node.type;
-    TypeImpl lhsType = expression.staticType;
-    TypeImpl rhsType = typeName.type;
+    var lhsType = expression.staticType as TypeImpl;
+    var rhsType = typeName.type as TypeImpl;
     if (lhsType == null || rhsType == null) {
       return false;
     }
@@ -911,7 +916,7 @@
       return nonFinalFields;
     }
 
-    ClassElement element = node.declaredElement;
+    var element = node.declaredElement as ClassElement;
     if (isOrInheritsImmutable(element, HashSet<ClassElement>())) {
       Iterable<String> nonFinalFields =
           definedOrInheritedNonFinalInstanceFields(
@@ -973,13 +978,12 @@
           ...element.typeParameters.map((tp) => tp.bound),
         ];
         for (var type in signatureTypes) {
-          var typeElement = type?.element?.enclosingElement;
-          if (typeElement is FunctionTypeAliasElement &&
-              typeElement.hasInternal) {
+          var aliasElement = type?.aliasElement;
+          if (aliasElement != null && aliasElement.hasInternal) {
             _errorReporter.reportErrorForNode(
                 HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY,
                 node,
-                [typeElement.name, element.displayName]);
+                [aliasElement.name, element.displayName]);
           }
         }
       }
@@ -1153,8 +1157,7 @@
   /// function has a return type that Future<Null> is not assignable to.
   ///
   /// See [HintCode.MISSING_RETURN].
-  void _checkForMissingReturn(TypeAnnotation returnNode, FunctionBody body,
-      ExecutableElement element, AstNode functionNode) {
+  void _checkForMissingReturn(FunctionBody body, AstNode functionNode) {
     if (_isNonNullableByDefault) {
       return;
     }
@@ -1295,6 +1298,9 @@
     if (expressionMap.isNotEmpty) {
       Declaration parent = expression.thisOrAncestorMatching(
           (e) => e is FunctionDeclaration || e is MethodDeclaration);
+      if (parent == null) {
+        return;
+      }
       for (var entry in expressionMap.entries) {
         _errorReporter.reportErrorForNode(
           HintCode.RETURN_OF_DO_NOT_STORE,
@@ -1433,8 +1439,7 @@
     }
   }
 
-  /// In "strict-inference" mode, check that [returnNode]'s return type is
-  /// specified.
+  /// In "strict-inference" mode, check that [returnType] is specified.
   void _checkStrictInferenceReturnType(
       AstNode returnType, AstNode reportNode, String displayName) {
     if (!_strictInference) {
@@ -1480,6 +1485,11 @@
           addTo: expressions);
       _getSubExpressionsMarkedDoNotStore(expression.rightOperand,
           addTo: expressions);
+    } else if (expression is FunctionExpression) {
+      var body = expression.body;
+      if (body is ExpressionFunctionBody) {
+        _getSubExpressionsMarkedDoNotStore(body.expression, addTo: expressions);
+      }
     }
     if (element is PropertyAccessorElement && element.isSynthetic) {
       element = (element as PropertyAccessorElement).variable;
@@ -1727,6 +1737,10 @@
       return;
     }
 
+    if (parent is HideCombinator) {
+      return;
+    }
+
     _checkForInvalidInternalAccess(identifier, element);
     _checkForOtherInvalidAccess(identifier, element);
   }
diff --git a/pkg/analyzer/lib/src/error/bool_expression_verifier.dart b/pkg/analyzer/lib/src/error/bool_expression_verifier.dart
index 05eb039..c5a7253 100644
--- a/pkg/analyzer/lib/src/error/bool_expression_verifier.dart
+++ b/pkg/analyzer/lib/src/error/bool_expression_verifier.dart
@@ -51,7 +51,9 @@
     if (!_checkForUseOfVoidResult(expression) &&
         !_typeSystem.isAssignableTo2(type, _boolType)) {
       if (type.element == _boolElement) {
-        _nullableDereferenceVerifier.report(expression, type);
+        _nullableDereferenceVerifier.report(expression, type,
+            errorCode: CompileTimeErrorCode
+                .UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION);
       } else {
         _errorReporter.reportErrorForNode(errorCode, expression, arguments);
       }
diff --git a/pkg/analyzer/lib/src/error/catch_error_verifier.dart b/pkg/analyzer/lib/src/error/catch_error_verifier.dart
new file mode 100644
index 0000000..a9fa26d
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/catch_error_verifier.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.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/dart/element/type_system.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/error/return_type_verifier.dart';
+import 'package:analyzer/src/generated/error_verifier.dart';
+
+/// Reports on invalid functions passed to [Future.catchError].
+class CatchErrorVerifier {
+  final ErrorReporter _errorReporter;
+
+  final TypeProvider _typeProvider;
+
+  final TypeSystem _typeSystem;
+
+  final ReturnTypeVerifier _returnTypeVerifier;
+
+  CatchErrorVerifier(this._errorReporter, this._typeProvider, this._typeSystem)
+      : _returnTypeVerifier = ReturnTypeVerifier(
+          typeProvider: _typeProvider,
+          typeSystem: _typeSystem,
+          errorReporter: _errorReporter,
+        );
+  void verifyMethodInvocation(MethodInvocation node) {
+    // TODO(https://github.com/dart-lang/sdk/issues/35825): Verify the
+    // parameters of a function passed to `Future.catchError` as well.
+    var target = node.realTarget;
+    if (target == null) {
+      return;
+    }
+    var methodName = node.methodName;
+    if (!(methodName.name == 'catchError' &&
+        target.staticType.isDartAsyncFuture)) {
+      return;
+    }
+    if (node.argumentList.arguments.isEmpty) {
+      return;
+    }
+    var callback = node.argumentList.arguments.first;
+    if (callback is NamedExpression) {
+      // This implies that no positional arguments are passed.
+      return;
+    }
+    var targetType = target.staticType as InterfaceType;
+    var targetFutureType = targetType.typeArguments.first;
+    var expectedReturnType = _typeProvider.futureOrType2(targetFutureType);
+    if (callback is FunctionExpression) {
+      var catchErrorOnErrorExecutable = EnclosingExecutableContext(
+          callback.declaredElement,
+          isAsynchronous: true,
+          catchErrorOnErrorReturnType: expectedReturnType);
+      var returnStatementVerifier =
+          _ReturnStatementVerifier(_returnTypeVerifier);
+      _returnTypeVerifier.enclosingExecutable = catchErrorOnErrorExecutable;
+      callback.body.accept(returnStatementVerifier);
+    } else {
+      var callbackType = callback.staticType;
+      if (callbackType is FunctionType) {
+        _checkReturnType(expectedReturnType, callbackType.returnType, callback);
+      }
+    }
+  }
+
+  void _checkReturnType(
+      DartType expectedType, DartType functionReturnType, Expression callback) {
+    if (!_typeSystem.isAssignableTo(functionReturnType, expectedType)) {
+      _errorReporter.reportErrorForNode(
+        HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR,
+        callback,
+        [functionReturnType, expectedType],
+      );
+    }
+  }
+}
+
+/// Visits a function body, looking for return statements.
+class _ReturnStatementVerifier extends RecursiveAstVisitor<void> {
+  final ReturnTypeVerifier _returnTypeVerifier;
+  _ReturnStatementVerifier(this._returnTypeVerifier);
+  @override
+  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    _returnTypeVerifier.verifyExpressionFunctionBody(node);
+    super.visitExpressionFunctionBody(node);
+  }
+
+  @override
+  void visitFunctionExpression(FunctionExpression node) {
+    // Do not visit within [node]. We have no interest in return statements
+    // within.
+  }
+  @override
+  void visitReturnStatement(ReturnStatement node) {
+    _returnTypeVerifier.verifyReturnStatement(node);
+    super.visitReturnStatement(node);
+  }
+}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 22fbfd8..8d51b49 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -473,29 +473,6 @@
           hasPublishedDocs: true);
 
   /**
-   * 15 Metadata: The constant expression given in an annotation is type checked
-   * and evaluated in the scope surrounding the declaration being annotated.
-   *
-   * 16.12.2 Const: It is a compile-time error if <i>T</i> is not a class
-   * accessible in the current scope, optionally followed by type arguments.
-   *
-   * 16.12.2 Const: If <i>e</i> is of the form <i>const T.id(a<sub>1</sub>,
-   * &hellip;, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>, &hellip;
-   * x<sub>n+k</sub>: a<sub>n+k</sub>)</i> it is a compile-time error if
-   * <i>T</i> is not a class accessible in the current scope, optionally
-   * followed by type arguments.
-   *
-   * Parameters:
-   * 0: the name of the non-type element
-   */
-  static const CompileTimeErrorCode ANNOTATION_WITH_NON_CLASS =
-      CompileTimeErrorCode(
-          'ANNOTATION_WITH_NON_CLASS', "The name '{0}' isn't a class.",
-          correction: "Try importing the library that declares the class, "
-              "correcting the name to match a defined class, or "
-              "defining a class with the given name.");
-
-  /**
    * Parameters:
    * 0: the name of the actual argument type
    * 1: the name of the expected type
@@ -807,12 +784,50 @@
           hasPublishedDocs: true);
 
   /**
-   * 12.18 Assignment: It is as static warning if an assignment of the form
-   * <i>v = e</i> occurs inside a top level or static function (be it function,
-   * method, getter, or setter) or variable initializer and there is neither a
-   * local variable declaration with name <i>v</i> nor setter declaration with
-   * name <i>v=</i> in the lexical scope enclosing the assignment.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the name of a function appears
+  // on the left-hand side of an assignment expression.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the assignment to the
+  // function `f` is invalid:
+  //
+  // ```dart
+  // void f() {}
+  //
+  // void g() {
+  //   [!f!] = () {};
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the right-hand side should be assigned to something else, such as a
+  // local variable, then change the left-hand side:
+  //
+  // ```dart
+  // void f() {}
+  //
+  // void g() {
+  //   var x = () {};
+  //   print(x);
+  // }
+  // ```
+  //
+  // If the intent is to change the implementation of the function, then define
+  // a function-valued variable instead of a function:
+  //
+  // ```dart
+  // void Function() f = () {};
+  //
+  // void g() {
+  //   f = () {};
+  // }
+  // ```
   static const CompileTimeErrorCode ASSIGNMENT_TO_FUNCTION =
       CompileTimeErrorCode(
           'ASSIGNMENT_TO_FUNCTION', "Functions can't be assigned a value.");
@@ -848,25 +863,104 @@
       hasPublishedDocs: true);
 
   /**
-   * 12.18 Assignment: It is as static warning if an assignment of the form
-   * <i>v = e</i> occurs inside a top level or static function (be it function,
-   * method, getter, or setter) or variable initializer and there is neither a
-   * local variable declaration with name <i>v</i> nor setter declaration with
-   * name <i>v=</i> in the lexical scope enclosing the assignment.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the name of a type name appears
+  // on the left-hand side of an assignment expression.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the assignment to the
+  // class `C` is invalid:
+  //
+  // ```dart
+  // class C {}
+  //
+  // void f() {
+  //   [!C!] = null;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the right-hand side should be assigned to something else, such as a
+  // local variable, then change the left-hand side:
+  //
+  // ```dart
+  // void f() {}
+  //
+  // void g() {
+  //   var c = null;
+  //   print(c);
+  // }
+  // ```
   static const CompileTimeErrorCode ASSIGNMENT_TO_TYPE = CompileTimeErrorCode(
       'ASSIGNMENT_TO_TYPE', "Types can't be assigned a value.");
 
   /**
-   * 17.6.3 Asynchronous For-in: It is a compile-time error if an asynchronous
-   * for-in statement appears inside a synchronous function.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an async for-in loop is found in
+  // a function or method whose body isn't marked as being either `async` or
+  // `async*`.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the body of `f` isn't
+  // marked as being either `async` or `async*`, but `f` contains an async
+  // for-in loop:
+  //
+  // ```dart
+  // void f(list) {
+  //   await for (var e [!in!] list) {
+  //     print(e);
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the function should return a `Future`, then mark the body with `async`:
+  //
+  // ```dart
+  // Future<void> f(list) async {
+  //   await for (var e in list) {
+  //     print(e);
+  //   }
+  // }
+  // ```
+  //
+  // If the function should return a `Stream` of values, then mark the body with
+  // `async*`:
+  //
+  // ```dart
+  // Stream<void> f(list) async* {
+  //   await for (var e in list) {
+  //     print(e);
+  //   }
+  // }
+  // ```
+  //
+  // If the function should be synchronous, then remove the `await` before the
+  // loop:
+  //
+  // ```dart
+  // void f(list) {
+  //   for (var e in list) {
+  //     print(e);
+  //   }
+  // }
+  // ```
   static const CompileTimeErrorCode ASYNC_FOR_IN_WRONG_CONTEXT =
       CompileTimeErrorCode('ASYNC_FOR_IN_WRONG_CONTEXT',
-          "The async for-in can only be used in an async function.",
+          "The async for-in loop can only be used in an async function.",
           correction:
               "Try marking the function body with either 'async' or 'async*', "
-              "or removing the 'await' before the for loop.");
+              "or removing the 'await' before the for-in loop.");
 
   /**
    * No parameters.
@@ -1009,9 +1103,62 @@
               "Try adding either a return or a throw statement at the end.",
           hasPublishedDocs: true);
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a break in a case clause inside
+  // a switch statement has a label that is associated with another case clause.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the label `l` is
+  // associated with the case clause for `0`:
+  //
+  // ```dart
+  // void f(int i) {
+  //   switch (i) {
+  //     l: case 0:
+  //       break;
+  //     case 1:
+  //       break [!l!];
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the intent is to transfer control to the statement after the switch,
+  // then remove the label from the break statement:
+  //
+  // ```dart
+  // void f(int i) {
+  //   switch (i) {
+  //     case 0:
+  //       break;
+  //     case 1:
+  //       break;
+  //   }
+  // }
+  // ```
+  //
+  // If the intent is to transfer control to a different case block, then use
+  // `continue` rather than `break`:
+  //
+  // ```dart
+  // void f(int i) {
+  //   switch (i) {
+  //     l: case 0:
+  //       break;
+  //     case 1:
+  //       continue l;
+  //   }
+  // }
+  // ```
   static const CompileTimeErrorCode BREAK_LABEL_ON_SWITCH_MEMBER =
       CompileTimeErrorCode('BREAK_LABEL_ON_SWITCH_MEMBER',
-          "Break label resolves to case or default statement");
+          "A break label resolves to the 'case' or 'default' statement.");
 
   /**
    * Parameters:
@@ -1176,16 +1323,107 @@
           hasPublishedDocs: true);
 
   /**
-   * 13.9 Switch: It is a compile-time error if the class <i>C</i> implements
-   * the operator <i>==</i>.
-   *
    * Parameters:
    * 0: the this of the switch case expression
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the type of the expression
+  // following the keyword `case` has an implementation of the `==` operator
+  // other than the one in `Object`.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the expression
+  // following the keyword `case` (`C(0)`) has the type `C`, and the class `C`
+  // overrides the `==` operator:
+  //
+  // ```dart
+  // class C {
+  //   final int value;
+  //
+  //   const C(this.value);
+  //
+  //   bool operator ==(Object other) {
+  //     return false;
+  //   }
+  // }
+  //
+  // void f(C c) {
+  //   switch (c) {
+  //     case [!C(0)!]:
+  //       break;
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If there isn't a strong reason not to do so, then rewrite the code to use
+  // an if-else structure:
+  //
+  // ```dart
+  // class C {
+  //   final int value;
+  //
+  //   const C(this.value);
+  //
+  //   bool operator ==(Object other) {
+  //     return false;
+  //   }
+  // }
+  //
+  // void f(C c) {
+  //   if (c == C(0)) {
+  //     // ...
+  //   }
+  // }
+  // ```
+  //
+  // If you can't rewrite the switch statement and the implementation of `==`
+  // isn't necessary, then remove it:
+  //
+  // ```dart
+  // class C {
+  //   final int value;
+  //
+  //   const C(this.value);
+  // }
+  //
+  // void f(C c) {
+  //   switch (c) {
+  //     case C(0):
+  //       break;
+  //   }
+  // }
+  // ```
+  //
+  // If you can't rewrite the switch statement and you can't remove the
+  // definition of `==`, then find some other value that can be used to control
+  // the switch:
+  //
+  // ```dart
+  // class C {
+  //   final int value;
+  //
+  //   const C(this.value);
+  //
+  //   bool operator ==(Object other) {
+  //     return false;
+  //   }
+  // }
+  //
+  // void f(C c) {
+  //   switch (c.value) {
+  //     case 0:
+  //       break;
+  //   }
+  // }
+  // ```
   static const CompileTimeErrorCode CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS =
       CompileTimeErrorCode(
           'CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS',
-          "The switch case expression type '{0}' can't override the == "
+          "The switch case expression type '{0}' can't override the '==' "
               "operator.");
 
   /**
@@ -2306,9 +2544,56 @@
           hasPublishedDocs: true);
 
   /**
-   * 7.6.2 Factories: It is a compile-time error if <i>k</i> explicitly
-   * specifies a default value for an optional parameter.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a factory constructor that
+  // redirects to another constructor specifies a default value for an optional
+  // parameter.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the factory constructor
+  // in `A` has a default value for the optional parameter `x`:
+  //
+  // ```dart
+  // class A {
+  //   factory A([int [!x!] = 0]) = B;
+  // }
+  //
+  // class B implements A {
+  //   B([int x = 1]) {}
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the default value from the factory constructor:
+  //
+  // ```dart
+  // class A {
+  //   factory A([int x]) = B;
+  // }
+  //
+  // class B implements A {
+  //   B([int x = 1]) {}
+  // }
+  // ```
+  //
+  // Note that this fix might change the value used when the optional parameter
+  // is omitted. If that happens, and if that change is a problem, then consider
+  // making the optional parameter a required parameter in the factory method:
+  //
+  // ```dart
+  // class A {
+  //  factory A(int x) = B;
+  // }
+  //
+  // class B implements A {
+  //   B([int x = 1]) {}
+  // }
+  // ```
   static const CompileTimeErrorCode
       DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR = CompileTimeErrorCode(
           'DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR',
@@ -3445,7 +3730,7 @@
   // ```dart
   // void f(int a, int b) {}
   // void g() {
-  //   f[!(1, 2, 3)!];
+  //   f(1, 2, [!3!]);
   // }
   // ```
   //
@@ -3486,7 +3771,7 @@
   // %language=2.9
   // void f(int a, int b, {int c}) {}
   // void g() {
-  //   f[!(1, 2, 3)!];
+  //   f(1, 2, [!3!]);
   // }
   // ```
   //
@@ -3521,13 +3806,39 @@
           hasPublishedDocs: true);
 
   /**
-   * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It
-   * is a compile time error if more than one initializer corresponding to a
-   * given instance variable appears in <i>k</i>'s list.
-   *
    * Parameters:
    * 0: the name of the field being initialized multiple times
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the initializer list of a
+  // constructor initializes a field more than once. There is no value to allow
+  // both initializers because only the last value is preserved.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `f` is being
+  // initialized twice:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C() : f = 0, [!f!] = 1;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove one of the initializers:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C() : f = 0;
+  // }
+  // ```
   static const CompileTimeErrorCode FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS =
       CompileTimeErrorCode('FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS',
           "The field '{0}' can't be initialized twice in the same constructor.",
@@ -3586,11 +3897,60 @@
           hasPublishedDocs: true);
 
   /**
-   * 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. It
-   * is a compile time error if <i>k</i>'s initializer list contains an
-   * initializer for a variable that is initialized by means of an initializing
-   * formal of <i>k</i>.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a field is initialized in both
+  // the parameter list and in the initializer list of a constructor.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `f` is
+  // initialized both by a field formal parameter and in the initializer list:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(this.f) : [!f!] = 0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the field should be initialized by the parameter, then remove the
+  // initialization in the initializer list:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(this.f);
+  // }
+  // ```
+  //
+  // If the field should be initialized in the initializer list and the
+  // parameter isn't needed, then remove the parameter:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C() : f = 0;
+  // }
+  // ```
+  //
+  // If the field should be initialized in the initializer list and the
+  // parameter is needed, then make it a normal parameter:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(int g) : f = g * 2;
+  // }
+  // ```
   static const CompileTimeErrorCode
       FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER = CompileTimeErrorCode(
           'FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER',
@@ -3599,10 +3959,38 @@
           correction: "Try removing one of the initializations.");
 
   /**
-   * 7.6.1 Generative Constructors: It is a compile-time error if an
-   * initializing formal is used by a function other than a non-redirecting
-   * generative constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a factory constructor has a
+  // field formal parameter. Factory constructors can't assign values to fields
+  // because no instance is created; hence, there is no field to assign.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the factory constructor
+  // uses a field formal parameter:
+  //
+  // ```dart
+  // class C {
+  //   int? f;
+  //
+  //   factory C([!this.f!]) => throw 0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Replace the field formal parameter with a normal parameter:
+  //
+  // ```dart
+  // class C {
+  //   int? f;
+  //
+  //   factory C(int f) => throw 0;
+  // }
+  // ```
   static const CompileTimeErrorCode FIELD_INITIALIZER_FACTORY_CONSTRUCTOR =
       CompileTimeErrorCode(
           'FIELD_INITIALIZER_FACTORY_CONSTRUCTOR',
@@ -3675,27 +4063,139 @@
           correction: "Try using a normal parameter.");
 
   /**
-   * 7.6.1 Generative Constructors: A generative constructor may be redirecting,
-   * in which case its only action is to invoke another generative constructor.
-   *
-   * 7.6.1 Generative Constructors: It is a compile-time error if an
-   * initializing formal is used by a function other than a non-redirecting
-   * generative constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a redirecting constructor
+  // initializes a field in the object. This isn't allowed because the instance
+  // that has the field hasn't been created at the point at which it should be
+  // initialized.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the constructor
+  // `C.zero`, which redirects to the constructor `C`, has a field formal
+  // parameter that initializes the field `f`:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(this.f);
+  //
+  //   C.zero([!this.f!]) : this(f);
+  // }
+  // ```
+  //
+  // The following code produces this diagnostic because the constructor
+  // `C.zero`, which redirects to the constructor `C`, has an initializer that
+  // initializes the field `f`:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(this.f);
+  //
+  //   C.zero() : [!f = 0!], this(1);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the initialization is done by a field formal parameter, then use a
+  // normal parameter:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(this.f);
+  //
+  //   C.zero(int f) : this(f);
+  // }
+  // ```
+  //
+  // If the initialization is done in an initializer, then remove the
+  // initializer:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(this.f);
+  //
+  //   C.zero() : this(0);
+  // }
+  // ```
   static const CompileTimeErrorCode FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR =
       CompileTimeErrorCode('FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR',
           "The redirecting constructor can't have a field initializer.",
-          correction: "Try using a normal parameter.");
+          correction:
+              "Try initializing the field in the constructor being redirected "
+              "to.");
 
   /**
-   * 7.6.1 Generative Constructors: An initializing formal has the form
-   * <i>this.id</i>. It is a static warning if the static type of <i>id</i> is
-   * not assignable to <i>T<sub>id</sub></i>.
-   *
    * Parameters:
    * 0: the name of the type of the field formal parameter
    * 1: the name of the type of the field
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the type of a field formal
+  // parameter isn't assignable to the type of the field being initialized.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field formal
+  // parameter has the type `String`, but the type of the field is `int`. The
+  // parameter must have a type that is a subtype of the field's type.
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C([!String this.f!]);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the type of the field is incorrect, then change the type of the field to
+  // match the type of the parameter, and consider removing the type from the
+  // parameter:
+  //
+  // ```dart
+  // class C {
+  //   String f;
+  //
+  //   C(this.f);
+  // }
+  // ```
+  //
+  // If the type of the parameter is incorrect, then remove the type of the
+  // parameter:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(this.f);
+  // }
+  // ```
+  //
+  // If the types of both the field and the parameter are correct, then use an
+  // initializer rather than a field formal parameter to convert the parameter
+  // value into a value of the correct type:
+  //
+  // ```dart
+  // class C {
+  //   int f;
+  //
+  //   C(String s) : f = int.parse(s);
+  // }
+  // ```
   static const CompileTimeErrorCode FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE =
       CompileTimeErrorCode('FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE',
           "The parameter type '{0}' is incompatible with the field type '{1}'.",
@@ -3703,13 +4203,50 @@
               "changing the field's type.");
 
   /**
-   * 5. Variables: It is a static warning if a final instance variable that has
-   * been initialized at its point of declaration is also initialized in a
-   * constructor.
-   *
    * Parameters:
    * 0: the name of the field in question
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a final field is initialized
+  // twice: once where it's declared and once by a constructor's parameter.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `f` is
+  // initialized twice:
+  //
+  // ```dart
+  // class C {
+  //   final int f = 0;
+  //
+  //   C(this.[!f!]);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the field should have the same value for all instances, then remove the
+  // initialization in the parameter list:
+  //
+  // ```dart
+  // class C {
+  //   final int f = 0;
+  //
+  //   C();
+  // }
+  // ```
+  //
+  // If the field can have different values in different instances, then remove
+  // the initialization in the declaration:
+  //
+  // ```dart
+  // class C {
+  //   final int f;
+  //
+  //   C(this.f);
+  // }
+  // ```
   static const CompileTimeErrorCode
       FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR = CompileTimeErrorCode(
           'FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR',
@@ -4922,6 +5459,18 @@
       correction: "Try using one of the defined constants.");
 
   /**
+   * It is a compile-time error for an instance creation `C<T1, .. Tk>(...)` or
+   * `C<T1, .. Tk>.name()` (where `k` may be zero, which means that the type
+   * argument list is absent) if `C` denotes a type alias that expands to a
+   * type variable.
+   */
+  static const CompileTimeErrorCode
+      INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER = CompileTimeErrorCode(
+          'INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER',
+          "Type aliases that expand to a type parameter can't be instantiated.",
+          correction: "Try replacing it with a class.");
+
+  /**
    * An integer literal with static type `double` and numeric value `i`
    * evaluates to an instance of the `double` class representing the value `i`.
    * It is a compile-time error if the value `i` cannot be represented
@@ -5064,18 +5613,6 @@
               "changing the import to not be deferred.");
 
   /**
-   * No parameters.
-   */
-  static const CompileTimeErrorCode INVALID_ANNOTATION_GETTER =
-      CompileTimeErrorCode(
-    'INVALID_ANNOTATION',
-    "Getters can't be used as annotations.",
-    correction: "Try using a top-level variable or a field.",
-    hasPublishedDocs: true,
-    uniqueName: 'INVALID_ANNOTATION_GETTER',
-  );
-
-  /**
    * Parameters:
    * 0: the name of the right hand side type
    * 1: the name of the left hand side type
@@ -5353,6 +5890,49 @@
               "the immediately enclosing class.",
           hasPublishedDocs: true);
 
+  /**
+   * Parameters:
+   * 0: the name of the declared member that is not a valid override.
+   * 1: the name of the interface that declares the member.
+   * 2: the type of the declared member in the interface.
+   * 3. the name of the interface with the overridden member.
+   * 4. the type of the overridden member.
+   *
+   * These parameters must be kept in sync with those of
+   * [CompileTimeErrorCode.INVALID_OVERRIDE].
+   */
+  static const CompileTimeErrorCode INVALID_IMPLEMENTATION_OVERRIDE =
+      CompileTimeErrorCode(
+          'INVALID_IMPLEMENTATION_OVERRIDE',
+          "'{1}.{0}' ('{2}') isn't a valid concrete implementation of "
+              "'{3}.{0}' ('{4}').");
+
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a generic function type has a
+  // function-valued parameter that is written using the older inline function
+  // type syntax.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the parameter `f`, in
+  // the generic function type used to define `F`, uses the inline function
+  // type syntax:
+  //
+  // ```dart
+  // typedef F = int Function(int f[!(!]String s));
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Use the generic function syntax for the parameter's type:
+  //
+  // ```dart
+  // typedef F = int Function(int Function(String));
+  // ```
   static const CompileTimeErrorCode INVALID_INLINE_FUNCTION_TYPE =
       CompileTimeErrorCode(
           'INVALID_INLINE_FUNCTION_TYPE',
@@ -5883,19 +6463,58 @@
       "Can't reference label '{0}' declared in an outer method.");
 
   /**
-   * 13.13 Break: It is a compile-time error if no such statement
-   * <i>s<sub>E</sub></i> exists within the innermost function in which
-   * <i>s<sub>b</sub></i> occurs.
-   *
-   * 13.14 Continue: It is a compile-time error if no such statement or case
-   * clause <i>s<sub>E</sub></i> exists within the innermost function in which
-   * <i>s<sub>c</sub></i> occurs.
-   *
    * Parameters:
    * 0: the name of the unresolvable label
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when it finds a reference to a label
+  // that isn't defined in the scope of the `break` or `continue` statement that
+  // is referencing it.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the label `loop` isn't
+  // defined anywhere:
+  //
+  // ```dart
+  // void f() {
+  //   for (int i = 0; i < 10; i++) {
+  //     for (int j = 0; j < 10; j++) {
+  //       break [!loop!];
+  //     }
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the label should be on the innermost enclosing `do`, `for`, `switch`, or
+  // `while` statement, then remove the label:
+  //
+  // ```dart
+  // void f() {
+  //   for (int i = 0; i < 10; i++) {
+  //     for (int j = 0; j < 10; j++) {
+  //       break;
+  //     }
+  //   }
+  // }
+  // ```
+  //
+  // If the label should be on some other statement, then add the label:
+  //
+  // ```dart
+  // void f() {
+  //   loop: for (int i = 0; i < 10; i++) {
+  //     for (int j = 0; j < 10; j++) {
+  //       break loop;
+  //     }
+  //   }
+  // }
+  // ```
   static const CompileTimeErrorCode LABEL_UNDEFINED = CompileTimeErrorCode(
-      'LABEL_UNDEFINED', "Can't reference undefined label '{0}'.",
+      'LABEL_UNDEFINED', "Can't reference an undefined label '{0}'.",
       correction: "Try defining the label, or "
           "correcting the name to match an existing label.");
 
@@ -6055,34 +6674,127 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the first positional parameter
+  // of a function named `main` isn't a supertype of `List<String>`.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `List<int>` isn't a
+  // supertype of `List<String>`:
+  //
+  // ```dart
+  // void main([!List<int>!] args) {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the function is an entry point, then change the type of the first
+  // positional parameter to be a supertype of `List<String>`:
+  //
+  // ```dart
+  // void main(List<String> args) {}
+  // ```
+  //
+  // If the function isn't an entry point, then change the name of the function:
+  //
+  // ```dart
+  // void f(List<int> args) {}
+  // ```
   static const CompileTimeErrorCode MAIN_FIRST_POSITIONAL_PARAMETER_TYPE =
       CompileTimeErrorCode(
     'MAIN_FIRST_POSITIONAL_PARAMETER_TYPE',
-    "The type of the first positional parameter of the 'main' function "
-        "must be a supertype of List<String>.",
+    "The type of the first positional parameter of the 'main' function must be "
+        "a supertype of 'List<String>'.",
     correction: "Try changing the type of the parameter.",
   );
 
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a function named `main` has one
+  // or more required named parameters.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the function named
+  // `main` has a required named parameter (`x`):
+  //
+  // ```dart
+  // void [!main!]({required int x}) {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the function is an entry point, then remove the `required` keyword:
+  //
+  // ```dart
+  // void main({int? x}) {}
+  // ```
+  //
+  // If the function isn't an entry point, then change the name of the function:
+  //
+  // ```dart
+  // void f({required int x}) {}
+  // ```
   static const CompileTimeErrorCode MAIN_HAS_REQUIRED_NAMED_PARAMETERS =
       CompileTimeErrorCode(
     'MAIN_HAS_REQUIRED_NAMED_PARAMETERS',
     "The function 'main' can't have any required named parameters.",
-    correction: "Try using a different name for the function, "
-        "or removing the 'required' modifier.",
+    correction: "Try using a different name for the function, or removing the "
+        "'required' modifier.",
   );
 
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a function named `main` has more
+  // than two required positional parameters.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the function `main` has
+  // three required positional parameters:
+  //
+  // ```dart
+  // void [!main!](List<String> args, int x, int y) {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the function is an entry point and the extra parameters aren't used,
+  // then remove them:
+  //
+  // ```dart
+  // void main(List<String> args, int x) {}
+  // ```
+  //
+  // If the function is an entry point, but the extra parameters used are for
+  // when the function isn't being used as an entry point, then make the extra
+  // parameters optional:
+  //
+  // ```dart
+  // void main(List<String> args, int x, [int y = 0]) {}
+  // ```
+  //
+  // If the function isn't an entry point, then change the name of the function:
+  //
+  // ```dart
+  // void f(List<String> args, int x, int y) {}
+  // ```
   static const CompileTimeErrorCode
       MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS = CompileTimeErrorCode(
     'MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS',
-    "The function 'main' can't have more than two required positional parameters.",
-    correction: "Try using a different name for the function, "
-        "or removing extra parameters.",
+    "The function 'main' can't have more than two required positional "
+        "parameters.",
+    correction:
+        "Try using a different name for the function, or removing extra "
+        "parameters.",
   );
 
   /**
@@ -7669,6 +8381,55 @@
               "superinitializer or changing the superclass constructor '{2}' "
               "to not be a factory constructor.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the body of a factory
+  // constructor is marked with `async`, `async*`, or `sync*`. All constructors,
+  // including factory constructors, are required to return an instance of the
+  // class in which they're declared, not a `Future`, `Stream`, or `Iterator`.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the body of the factory
+  // constructor is marked with `async`:
+  //
+  // ```dart
+  // class C {
+  //   factory C() [!async!] {
+  //     return C._();
+  //   }
+  //   C._();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the member must be declared as a factory constructor, then remove the
+  // keyword appearing before the body:
+  //
+  // ```dart
+  // class C {
+  //   factory C() {
+  //     return C._();
+  //   }
+  //   C._();
+  // }
+  // ```
+  //
+  // If the member must return something other than an instance of the enclosing
+  // class, then make the member a static method:
+  //
+  // ```dart
+  // class C {
+  //   static Future<C> m() async {
+  //     return C._();
+  //   }
+  //   C._();
+  // }
+  // ```
   static const CompileTimeErrorCode NON_SYNC_FACTORY = CompileTimeErrorCode(
       'NON_SYNC_FACTORY',
       "Factory bodies can't use 'async', 'async*', or 'sync*'.");
@@ -8369,17 +9130,53 @@
           "The class 'Object' can't extend any other class.");
 
   /**
-   * 10.10 Superinterfaces: It is a compile-time error if two elements in the
-   * type list of the implements clause of a class `C` specifies the same
-   * type `T`.
-   *
    * Parameters:
    * 0: the name of the interface that is implemented more than once
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the same type is listed in the
+  // superclass constraints of a mixin multiple times.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `A` is included twice
+  // in the superclass constraints for `M`:
+  //
+  // ```dart
+  // mixin M on A, [!A!] {
+  // }
+  //
+  // class A {}
+  // class B {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If a different type should be included in the superclass constraints, then
+  // replace one of the occurrences with the other type:
+  //
+  // ```dart
+  // mixin M on A, B {
+  // }
+  //
+  // class A {}
+  // class B {}
+  // ```
+  //
+  // If no other type was intended, then remove the repeated type name:
+  //
+  // ```dart
+  // mixin M on A {
+  // }
+  //
+  // class A {}
+  // class B {}
+  // ```
   static const CompileTimeErrorCode ON_REPEATED = CompileTimeErrorCode(
       'ON_REPEATED',
-      "'{0}' can only be used in super-class constraints only once.",
-      correction: "Try removing all but one occurrence of the class name.");
+      "The type '{0}' can be included in the superclass constraints only once.",
+      correction: "Try removing all except one occurrence of the type name.");
 
   /**
    * 7.1.1 Operators: It is a compile-time error to declare an optional
@@ -8624,9 +9421,33 @@
           correction: "Try removing '{1}' from the 'with' clause.");
 
   /**
-   * 6.2.2 Optional Formals: It is a compile-time error if the name of a named
-   * optional parameter begins with an '_' character.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the name of a named parameter
+  // starts with an underscore.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the named parameter
+  // `_x` starts with an underscore:
+  //
+  // ```dart
+  // class C {
+  //   void m({int [!_x!] = 0}) {}
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Rename the parameter so that it doesn't start with an underscore:
+  //
+  // ```dart
+  // class C {
+  //   void m({int x = 0}) {}
+  // }
+  // ```
   static const CompileTimeErrorCode PRIVATE_OPTIONAL_PARAMETER =
       CompileTimeErrorCode('PRIVATE_OPTIONAL_PARAMETER',
           "Named parameters can't start with an underscore.");
@@ -8646,16 +9467,39 @@
   );
 
   /**
-   * 12.1 Constants: It is a compile-time error if the value of a compile-time
-   * constant expression depends on itself.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the value of a compile-time
+  // constant is defined in terms of itself, either directly or indirectly,
+  // creating an infinite loop.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic twice because both of the
+  // constants are defined in terms of the other:
+  //
+  // ```dart
+  // const [!secondsPerHour!] = minutesPerHour * 60;
+  // const [!minutesPerHour!] = secondsPerHour / 60;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Break the cycle by finding an alternative way of defining at least one of
+  // the constants:
+  //
+  // ```dart
+  // const secondsPerHour = minutesPerHour * 60;
+  // const minutesPerHour = 60;
+  // ```
   static const CompileTimeErrorCode RECURSIVE_COMPILE_TIME_CONSTANT =
       CompileTimeErrorCode('RECURSIVE_COMPILE_TIME_CONSTANT',
-          "Compile-time constant expression depends on itself.");
+          "The compile-time constant expression depends on itself.");
 
   /**
-   * 7.6.1 Generative Constructors: A generative constructor may be redirecting,
-   * in which case its only action is to invoke another generative constructor.
+   * No parameters.
    *
    * TODO(scheglov) review this later, there are no explicit "it is a
    * compile-time error" in specification. But it was added to the co19 and
@@ -8663,18 +9507,108 @@
    *
    * https://code.google.com/p/dart/issues/detail?id=954
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a constructor redirects to
+  // itself, either directly or indirectly, creating an infinite loop.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the generative
+  // constructors `C.a` and `C.b` each redirect to the other:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : [!this.b()!];
+  //   C.b() : [!this.a()!];
+  // }
+  // ```
+  //
+  // The following code produces this diagnostic because the factory
+  // constructors `A` and `B` each redirect to the other:
+  //
+  // ```dart
+  // abstract class A {
+  //   factory A() = [!B!];
+  // }
+  // class B implements A {
+  //   factory B() = [!A!];
+  //   B.named();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // In the case of generative constructors, break the cycle by finding defining
+  // at least one of the constructors to not redirect to another constructor:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : this.b();
+  //   C.b();
+  // }
+  // ```
+  //
+  // In the case of factory constructors, break the cycle by defining at least
+  // one of the factory constructors to do one of the following:
+  //
+  // - Redirect to a generative constructor:
+  //
+  // ```dart
+  // abstract class A {
+  //   factory A() = B;
+  // }
+  // class B implements A {
+  //   factory B() = B.named;
+  //   B.named();
+  // }
+  // ```
+  //
+  // - Not redirect to another constructor:
+  //
+  // ```dart
+  // abstract class A {
+  //   factory A() = B;
+  // }
+  // class B implements A {
+  //   factory B() {
+  //     return B.named();
+  //   }
+  //
+  //   B.named();
+  // }
+  // ```
+  //
+  // - Not be a factory constructor:
+  //
+  // ```dart
+  // abstract class A {
+  //   factory A() = B;
+  // }
+  // class B implements A {
+  //   B();
+  //   B.named();
+  // }
+  // ```
   static const CompileTimeErrorCode RECURSIVE_CONSTRUCTOR_REDIRECT =
-      CompileTimeErrorCode('RECURSIVE_CONSTRUCTOR_REDIRECT',
-          "Cycle in redirecting generative constructors.");
+      CompileTimeErrorCode(
+          'RECURSIVE_CONSTRUCTOR_REDIRECT',
+          "Constructors can't redirect to themselves either directly or "
+              "indirectly.",
+          correction: 'Try changing one of the constructors in the loop to not '
+              'redirect.');
 
   /**
-   * 7.6.2 Factories: It is a compile-time error if a redirecting factory
-   * constructor redirects to itself, either directly or indirectly via a
-   * sequence of redirections.
+   * No parameters.
    */
   static const CompileTimeErrorCode RECURSIVE_FACTORY_REDIRECT =
-      CompileTimeErrorCode('RECURSIVE_FACTORY_REDIRECT',
-          "Cycle in redirecting factory constructors.");
+      CompileTimeErrorCode(
+          'RECURSIVE_CONSTRUCTOR_REDIRECT',
+          "Constructors can't redirect to themselves either directly or "
+              "indirectly.",
+          uniqueName: 'RECURSIVE_FACTORY_REDIRECT',
+          correction: 'Try changing one of the constructors in the loop to not '
+              'redirect.');
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the interface of a
@@ -8754,10 +9688,43 @@
           "'{0}' can't use itself as a mixin.");
 
   /**
-   * 7.6.1 Generative constructors: A generative constructor may be
-   * <i>redirecting</i>, in which case its only action is to invoke another
-   * generative constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a generative constructor
+  // redirects to a constructor that isn't defined.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the constructor `C.a`
+  // redirects to the constructor `C.b`, but `C.b` isn't defined:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : [!this.b()!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the missing constructor must be called, then define it:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : this.b();
+  //   C.b();
+  // }
+  // ```
+  //
+  // If the missing constructor doesn't need to be called, then remove the
+  // redirect:
+  //
+  // ```dart
+  // class C {
+  //   C.a();
+  // }
+  // ```
   static const CompileTimeErrorCode REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR =
       CompileTimeErrorCode('REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR',
           "The constructor '{0}' couldn't be found in '{1}'.",
@@ -8765,14 +9732,50 @@
               "defining the constructor named '{0}'.");
 
   /**
-   * 7.6.1 Generative constructors: A generative constructor may be
-   * <i>redirecting</i>, in which case its only action is to invoke another
-   * generative constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a generative constructor
+  // redirects to a factory constructor.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the generative
+  // constructor `C.a` redirects to the factory constructor `C.b`:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : [!this.b()!];
+  //   factory C.b() => C.a();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the generative constructor doesn't need to redirect to another
+  // constructor, then remove the redirect.
+  //
+  // ```dart
+  // class C {
+  //   C.a();
+  //   factory C.b() => C.a();
+  // }
+  // ```
+  //
+  // If the generative constructor must redirect to another constructor, then
+  // make the other constructor be a generative (non-factory) constructor:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : this.b();
+  //   C.b();
+  // }
+  // ```
   static const CompileTimeErrorCode
       REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR = CompileTimeErrorCode(
           'REDIRECT_GENERATIVE_TO_NON_GENERATIVE_CONSTRUCTOR',
-          "Generative constructor can't redirect to a factory constructor.",
+          "Generative constructors can't redirect to a factory constructor.",
           correction: "Try redirecting to a different constructor.");
 
   /**
@@ -8988,17 +9991,67 @@
           hasPublishedDocs: true);
 
   /**
-   * 7.6.2 Factories: It is a compile-time error if <i>k</i> is prefixed with
-   * the const modifier but <i>k'</i> is not a constant constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a constructor marked as `const`
+  // redirects to a constructor that isn't marked as `const`.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the constructor `C.a`
+  // is marked as `const` but redirects to the constructor `C.b`, which isn't:
+  //
+  // ```dart
+  // class C {
+  //   const C.a() : this.[!b!]();
+  //   C.b();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the non-constant constructor can be marked as `const`, then mark it as
+  // `const`:
+  //
+  // ```dart
+  // class C {
+  //   const C.a() : this.b();
+  //   const C.b();
+  // }
+  // ```
+  //
+  // If the non-constant constructor can't be marked as `const`, then either
+  // remove the redirect or remove `const` from the redirecting constructor:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : this.b();
+  //   C.b();
+  // }
+  // ```
   static const CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR =
       CompileTimeErrorCode(
           'REDIRECT_TO_NON_CONST_CONSTRUCTOR',
-          "Constant redirecting constructor can't redirect to a non-constant "
+          "A constant redirecting constructor can't redirect to a non-constant "
               "constructor.",
           correction: "Try redirecting to a different constructor.");
 
   /**
+   * It is a compile-time error for a redirecting factory constructor to have
+   * a body which is a type alias that expands to a type variable, or a body
+   * which is a parameterized type of the form `F<T1, .. Tk>`, where `F` is
+   * a type alias that expands to a type variable.
+   */
+  static const CompileTimeErrorCode
+      REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER = CompileTimeErrorCode(
+          'REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER',
+          "Redirecting constructor can't redirect to a type alias "
+              "that expands to a type parameter.",
+          correction: "Try replacing it with a class.");
+
+  /**
    * No parameters.
    */
   // #### Description
@@ -9058,12 +10111,52 @@
           hasPublishedDocs: true);
 
   /**
-   * 12.8.1 Rethrow: It is a compile-time error if an expression of the form
-   * <i>rethrow;</i> is not enclosed within a on-catch clause.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a `rethrow` statement is outside
+  // a `catch` clause. The `rethrow` statement is used to throw a caught
+  // exception again, but there's no caught exception outside of a `catch`
+  // clause.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the`rethrow` statement
+  // is outside of a `catch` clause:
+  //
+  // ```dart
+  // void f() {
+  //   [!rethrow!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you're trying to rethrow an exception, then wrap the `rethrow` statement
+  // in a `catch` clause:
+  //
+  // ```dart
+  // void f() {
+  //   try {
+  //     // ...
+  //   } catch (exception) {
+  //     rethrow;
+  //   }
+  // }
+  // ```
+  //
+  // If you're trying to throw a new exception, then replace the `rethrow`
+  // statement with a `throw` expression:
+  //
+  // ```dart
+  // void f() {
+  //   throw UnsupportedError('Not yet implemented');
+  // }
+  // ```
   static const CompileTimeErrorCode RETHROW_OUTSIDE_CATCH =
-      CompileTimeErrorCode(
-          'RETHROW_OUTSIDE_CATCH', "Rethrow must be inside of catch clause.",
+      CompileTimeErrorCode('RETHROW_OUTSIDE_CATCH',
+          "A rethrow must be inside of a catch clause.",
           correction:
               "Try moving the expression into a catch clause, or using a "
               "'throw' expression.");
@@ -9179,7 +10272,7 @@
   static const CompileTimeErrorCode RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR =
       CompileTimeErrorCode(
     'RETURN_OF_INVALID_TYPE',
-    "A value of type '{0}' can't be returned from constructor '{2}' "
+    "A value of type '{0}' can't be returned from the constructor '{2}' "
         "because it has a return type of '{1}'.",
     hasPublishedDocs: true,
     uniqueName: 'RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR',
@@ -9222,7 +10315,7 @@
   static const CompileTimeErrorCode RETURN_OF_INVALID_TYPE_FROM_FUNCTION =
       CompileTimeErrorCode(
     'RETURN_OF_INVALID_TYPE',
-    "A value of type '{0}' can't be returned from function '{2}' because "
+    "A value of type '{0}' can't be returned from the function '{2}' because "
         "it has a return type of '{1}'.",
     hasPublishedDocs: true,
     uniqueName: 'RETURN_OF_INVALID_TYPE_FROM_FUNCTION',
@@ -9237,7 +10330,7 @@
   static const CompileTimeErrorCode RETURN_OF_INVALID_TYPE_FROM_METHOD =
       CompileTimeErrorCode(
     'RETURN_OF_INVALID_TYPE',
-    "A value of type '{0}' can't be returned from method '{2}' because "
+    "A value of type '{0}' can't be returned from the method '{2}' because "
         "it has a return type of '{1}'.",
     hasPublishedDocs: true,
     uniqueName: 'RETURN_OF_INVALID_TYPE_FROM_METHOD',
@@ -9272,7 +10365,7 @@
   // }
   // ```
   static const CompileTimeErrorCode RETURN_WITHOUT_VALUE = CompileTimeErrorCode(
-      'RETURN_WITHOUT_VALUE', "The  return value is missing after 'return'.",
+      'RETURN_WITHOUT_VALUE', "The return value is missing after 'return'.",
       hasPublishedDocs: true);
 
   static const CompileTimeErrorCode SET_ELEMENT_FROM_DEFERRED_LIBRARY =
@@ -9292,9 +10385,46 @@
           "The element type '{0}' can't be assigned to the set type '{1}'.");
 
   /**
-   * 14.1 Imports: It is a compile-time error if a prefix used in a deferred
-   * import is used in another import clause.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a prefix in a deferred import is
+  // also used as a prefix in other imports (whether deferred or not). The
+  // prefix in a deferred import can't be shared with other imports because the
+  // prefix is used to load the imported library.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the prefix `x` is used
+  // as the prefix for a deferred import and is also used for one other import:
+  //
+  // ```dart
+  // import 'dart:math' [!deferred!] as x;
+  // import 'dart:convert' as x;
+  //
+  // var y = x.json.encode(x.min(0, 1));
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you can use a different name for the deferred import, then do so:
+  //
+  // ```dart
+  // import 'dart:math' deferred as math;
+  // import 'dart:convert' as x;
+  //
+  // var y = x.json.encode(math.min(0, 1));
+  // ```
+  //
+  // If you can use a different name for the other imports, then do so:
+  //
+  // ```dart
+  // import 'dart:math' deferred as x;
+  // import 'dart:convert' as convert;
+  //
+  // var y = convert.json.encode(x.min(0, 1));
+  // ```
   static const CompileTimeErrorCode SHARED_DEFERRED_PREFIX =
       CompileTimeErrorCode(
           'SHARED_DEFERRED_PREFIX',
@@ -9432,9 +10562,37 @@
           hasPublishedDocs: true);
 
   /**
-   * 7.6.1 Generative Constructors: A generative constructor may be redirecting,
-   * in which case its only action is to invoke another generative constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a constructor that redirects to
+  // another constructor also attempts to invoke a constructor from the
+  // superclass. The superclass constructor will be invoked when the constructor
+  // that the redirecting constructor is redirected to is invoked.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the constructor `C.a`
+  // both redirects to `C.b` and invokes a constructor from the superclass:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : this.b(), [!super()!];
+  //   C.b();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the invocation of the `super` constructor:
+  //
+  // ```dart
+  // class C {
+  //   C.a() : this.b();
+  //   C.b();
+  // }
+  // ```
   static const CompileTimeErrorCode SUPER_IN_REDIRECTING_CONSTRUCTOR =
       CompileTimeErrorCode('SUPER_IN_REDIRECTING_CONSTRUCTOR',
           "The redirecting constructor can't have a 'super' initializer.");
@@ -9632,13 +10790,45 @@
           hasPublishedDocs: true);
 
   /**
-   * 10 Generics: However, a type parameter is considered to be a malformed type
-   * when referenced by a static member.
-   *
-   * 15.1 Static Types: Any use of a malformed type gives rise to a static
-   * warning. A malformed type is then interpreted as dynamic by the static type
-   * checker and the runtime.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a static member references a
+  // type parameter that is declared for the class. Type parameters only have
+  // meaning for instances of the class.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the static method
+  // `hasType` has a reference to the type parameter `T`:
+  //
+  // ```dart
+  // class C<T> {
+  //   static bool hasType(Object o) => o is [!T!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the member can be an instance member, then remove the keyword `static`:
+  //
+  // ```dart
+  // class C<T> {
+  //   bool hasType(Object o) => o is T;
+  // }
+  // ```
+  //
+  // If the member must be a static member, then make the member be generic:
+  //
+  // ```dart
+  // class C<T> {
+  //   static bool hasType<S>(Object o) => o is S;
+  // }
+  // ```
+  //
+  // Note, however, that there isn’t a relationship between `T` and `S`, so this
+  // second option changes the semantics from what was likely to be intended.
   static const CompileTimeErrorCode TYPE_PARAMETER_REFERENCED_BY_STATIC =
       CompileTimeErrorCode('TYPE_PARAMETER_REFERENCED_BY_STATIC',
           "Static members can't reference type parameters of the class.",
@@ -9713,6 +10903,44 @@
               "creating a type with the name '{0}'.",
           hasPublishedDocs: true);
 
+  static const CompileTimeErrorCode UNCHECKED_INVOCATION_OF_NULLABLE_VALUE =
+      CompileTimeErrorCode('UNCHECKED_USE_OF_NULLABLE_VALUE',
+          "The function can't be unconditionally invoked because it can be 'null'.",
+          correction: "Try adding a null check ('!').",
+          hasPublishedDocs: true,
+          uniqueName: 'UNCHECKED_INVOCATION_OF_NULLABLE_VALUE');
+
+  static const CompileTimeErrorCode
+      UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE = CompileTimeErrorCode(
+          'UNCHECKED_USE_OF_NULLABLE_VALUE',
+          "The method '{0}' can't be unconditionally invoked because the "
+              "receiver can be 'null'.",
+          correction:
+              "Try making the call conditional (using '?.') or adding a null "
+              "check to the target ('!').",
+          hasPublishedDocs: true,
+          uniqueName: 'UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE');
+
+  static const CompileTimeErrorCode
+      UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE = CompileTimeErrorCode(
+          'UNCHECKED_USE_OF_NULLABLE_VALUE',
+          "The operator '{0}' can't be unconditionally invoked because the "
+              "receiver can be 'null'.",
+          correction: "Try adding a null check to the target ('!').",
+          hasPublishedDocs: true,
+          uniqueName: 'UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE');
+
+  static const CompileTimeErrorCode
+      UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE = CompileTimeErrorCode(
+          'UNCHECKED_USE_OF_NULLABLE_VALUE',
+          "The property '{0}' can't be unconditionally accessed because the "
+              "receiver can be 'null'.",
+          correction:
+              "Try making the access conditional (using '?.') or adding a null "
+              "check to the target ('!').",
+          hasPublishedDocs: true,
+          uniqueName: 'UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE');
+
   /**
    * No parameters.
    */
@@ -9781,6 +11009,46 @@
               "it.",
           hasPublishedDocs: true);
 
+  static const CompileTimeErrorCode
+      UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION = CompileTimeErrorCode(
+          'UNCHECKED_USE_OF_NULLABLE_VALUE',
+          "A nullable expression can't be used as a condition.",
+          correction:
+              "Try checking that the value isn't 'null' before using it as a "
+              'condition.',
+          hasPublishedDocs: true,
+          uniqueName: 'UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION');
+
+  static const CompileTimeErrorCode
+      UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR = CompileTimeErrorCode(
+          'UNCHECKED_USE_OF_NULLABLE_VALUE',
+          "A nullable expression can't be used as an iterator in a for-in "
+              'loop.',
+          correction:
+              "Try checking that the value isn't 'null' before using it as an "
+              'iterator.',
+          hasPublishedDocs: true,
+          uniqueName: 'UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR');
+
+  static const CompileTimeErrorCode UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD =
+      CompileTimeErrorCode('UNCHECKED_USE_OF_NULLABLE_VALUE',
+          "A nullable expression can't be used in a spread.",
+          correction:
+              "Try checking that the value isn't 'null' before using it in a "
+              'spread, or use a null-aware spread.',
+          hasPublishedDocs: true,
+          uniqueName: 'UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD');
+
+  static const CompileTimeErrorCode
+      UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH = CompileTimeErrorCode(
+          'UNCHECKED_USE_OF_NULLABLE_VALUE',
+          "A nullable expression can't be used in a yield-each statement.",
+          correction:
+              "Try checking that the value isn't 'null' before using it in a "
+              'yield-each statement.',
+          hasPublishedDocs: true,
+          uniqueName: 'UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH');
+
   /**
    * No parameters.
    */
@@ -9868,12 +11136,17 @@
 
   /**
    * Same as [CompileTimeErrorCode.UNDEFINED_CLASS], but to catch using
-   * "boolean" instead of "bool".
+   * "boolean" instead of "bool" in order to improve the correction message.
+   *
+   * Parameters:
+   * 0: the name of the undefined class
    */
   static const CompileTimeErrorCode UNDEFINED_CLASS_BOOLEAN =
-      CompileTimeErrorCode(
-          'UNDEFINED_CLASS_BOOLEAN', "Undefined class 'boolean'.",
-          correction: "Try using the type 'bool'.");
+      CompileTimeErrorCode('UNDEFINED_CLASS', "Undefined class '{0}'.",
+          correction: "Try using the type 'bool'.",
+          hasPublishedDocs: true,
+          isUnresolvedIdentifier: true,
+          uniqueName: 'UNDEFINED_CLASS_BOOLEAN');
 
   /**
    * Parameters:
@@ -10817,9 +12090,6 @@
   );
 
   /**
-   * 12.15.1 Ordinary Invocation: It is a static type warning if <i>T</i> does
-   * not have an accessible (3.2) instance member named <i>m</i>.
-   *
    * This is a specialization of [INSTANCE_ACCESS_TO_STATIC_MEMBER] that is used
    * when we are able to find the name defined in a supertype. It exists to
    * provide a more informative error message.
@@ -10827,6 +12097,42 @@
    * Parameters:
    * 0: the name of the defining type
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when code in one class references a
+  // static member in a superclass without prefixing the member's name with the
+  // name of the superclass. Static members can only be referenced without a
+  // prefix in the class in which they're declared.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the static field `x` is
+  // referenced in the getter `g` without prefixing it with the name of the
+  // defining class:
+  //
+  // ```dart
+  // class A {
+  //   static int x = 3;
+  // }
+  //
+  // class B extends A {
+  //   int get g => [!x!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Prefix the name of the static member with the name of the declaring class:
+  //
+  // ```dart
+  // class A {
+  //   static int x = 3;
+  // }
+  //
+  // class B extends A {
+  //   int get g => A.x;
+  // }
+  // ```
   static const CompileTimeErrorCode
       UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER = CompileTimeErrorCode(
           'UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER',
@@ -10973,16 +12279,36 @@
           hasPublishedDocs: true);
 
   /**
-   * 14.1 Imports: It is a compile-time error if <i>x</i> is not a compile-time
-   * constant, or if <i>x</i> involves string interpolation.
-   *
-   * 14.3 Parts: It is a compile-time error if <i>s</i> is not a compile-time
-   * constant, or if <i>s</i> involves string interpolation.
-   *
-   * 14.5 URIs: It is a compile-time error if the string literal <i>x</i> that
-   * describes a URI is not a compile-time constant, or if <i>x</i> involves
-   * string interpolation.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the string literal in an
+  // `import`, `export`, or `part` directive contains an interpolation. The
+  // resolution of the URIs in directives must happen before the declarations
+  // are compiled, so expressions can’t be  evaluated  while determining the
+  // values of the URIs.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the string in the
+  // `import` directive contains an interpolation:
+  //
+  // ```dart
+  // import [!'dart:$m'!];
+  //
+  // const m = 'math';
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the interpolation from the URI:
+  //
+  // ```dart
+  // import 'dart:math';
+  //
+  // var zero = min(0, 0);
+  // ```
   static const CompileTimeErrorCode URI_WITH_INTERPOLATION =
       CompileTimeErrorCode(
           'URI_WITH_INTERPOLATION', "URIs can't use string interpolation.");
@@ -11147,8 +12473,10 @@
    */
   static const CompileTimeErrorCode
       WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS = CompileTimeErrorCode(
-          'WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS',
-          "Operator '-' should declare 0 or 1 parameter, but {0} found.");
+          'WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR',
+          "Operator '-' should declare 0 or 1 parameter, but {0} found.",
+          hasPublishedDocs: true,
+          uniqueName: 'WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS');
 
   /**
    * No parameters.
@@ -11402,23 +12730,48 @@
               "Try adding 'async*' or 'sync*' to the enclosing function.");
 
   /**
-   * 17.16.1 Yield: Let T be the static type of e [the expression to the right
-   * of "yield"] and let f be the immediately enclosing function.  It is a
-   * static type warning if either:
-   *
-   * - the body of f is marked async* and the type Stream<T> may not be
-   *   assigned to the declared return type of f.
-   *
-   * - the body of f is marked sync* and the type Iterable<T> may not be
-   *   assigned to the declared return type of f.
-   *
-   * 17.16.2 Yield-Each: Let T be the static type of e [the expression to the
-   * right of "yield*"] and let f be the immediately enclosing function.  It is
-   * a static type warning if T may not be assigned to the declared return type
-   * of f.  If f is synchronous it is a static type warning if T may not be
-   * assigned to Iterable.  If f is asynchronous it is a static type warning if
-   * T may not be assigned to Stream.
+   * Parameters:
+   * 0: the type of the expression after `yield`
+   * 1: the return type of the function containing the `yield`
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the type of object produced by a
+  // `yield` expression doesn't match the type of objects that are to be
+  // returned from the `Iterable` or `Stream` types that are returned from a
+  // generator (a function or method marked with either `sync*` or `async*`).
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the getter `zero` is
+  // declared to return an `Iterable` that returns integers, but the `yield` is
+  // returning a string from the iterable:
+  //
+  // ```dart
+  // Iterable<int> get zero sync* {
+  //   yield [!'0'!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the return type of the function is correct, then fix the expression
+  // following the keyword `yield` to return the correct type:
+  //
+  // ```dart
+  // Iterable<int> get zero sync* {
+  //   yield 0;
+  // }
+  // ```
+  //
+  // If the expression following the `yield` is correct, then change the return
+  // type of the function to allow it:
+  //
+  // ```dart
+  // Iterable<String> get zero sync* {
+  //   yield '0';
+  // }
+  // ```
   static const CompileTimeErrorCode YIELD_OF_INVALID_TYPE =
       CompileTimeErrorCode(
           'YIELD_OF_INVALID_TYPE',
diff --git a/pkg/analyzer/lib/src/error/correct_override.dart b/pkg/analyzer/lib/src/error/correct_override.dart
index 8abb0b4..f456ab8 100644
--- a/pkg/analyzer/lib/src/error/correct_override.dart
+++ b/pkg/analyzer/lib/src/error/correct_override.dart
@@ -6,6 +6,7 @@
 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/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -48,11 +49,12 @@
     @required ExecutableElement superMember,
     @required ErrorReporter errorReporter,
     @required AstNode errorNode,
+    ErrorCode errorCode,
   }) {
     var isCorrect = isCorrectOverrideOf(superMember: superMember);
     if (!isCorrect) {
       errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.INVALID_OVERRIDE,
+        errorCode ?? CompileTimeErrorCode.INVALID_OVERRIDE,
         errorNode,
         [
           _thisMember.name,
@@ -189,7 +191,7 @@
   /// Return the [Substitution] to convert types of [superMember] to types of
   /// [_thisMember].
   Substitution _superSubstitution(_SuperMember superMember) {
-    var result = Substitution.fromInterfaceType(superMember.interface);
+    Substitution result = Substitution.fromInterfaceType(superMember.interface);
 
     // If the executable has type parameters, ensure that super uses the same.
     var thisTypeParameters = _thisMember.typeParameters;
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 0b5e1f1..073ca29 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -202,15 +202,15 @@
       for (FunctionElement function in element.functions) {
         definedGetters[function.name] = function;
       }
-      for (FunctionTypeAliasElement alias in element.functionTypeAliases) {
-        definedGetters[alias.name] = alias;
-      }
       for (TopLevelVariableElement variable in element.topLevelVariables) {
         definedGetters[variable.name] = variable;
         if (!variable.isFinal && !variable.isConst) {
           definedGetters[variable.name + '='] = variable;
         }
       }
+      for (TypeAliasElement alias in element.typeAliases) {
+        definedGetters[alias.name] = alias;
+      }
       for (ClassElement type in element.types) {
         definedGetters[type.name] = type;
       }
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index d3d43e6..72a8b0c 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -237,6 +237,7 @@
           superMember: interfaceElement,
           errorReporter: reporter,
           errorNode: classNameNode,
+          errorCode: CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE,
         );
       }
 
@@ -285,7 +286,8 @@
         errorNode: node,
       );
 
-      if (superMember is MethodElement &&
+      if (!_isNonNullableByDefault &&
+          superMember is MethodElement &&
           member is MethodElement &&
           methodParameterNodes != null) {
         _checkForOptionalParametersDifferentDefaultValues(
diff --git a/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart b/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart
index 26dae7d..1ed2687 100644
--- a/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart
+++ b/pkg/analyzer/lib/src/error/nullable_dereference_verifier.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
@@ -21,33 +22,38 @@
   })  : _typeSystem = typeSystem,
         _errorReporter = errorReporter;
 
-  bool expression(Expression expression, {DartType type}) {
+  bool expression(Expression expression, {DartType type, ErrorCode errorCode}) {
     if (!_typeSystem.isNonNullableByDefault) {
       return false;
     }
 
     type ??= expression.staticType;
-    return _check(expression, type);
+    return _check(expression, type, errorCode: errorCode);
   }
 
-  void report(AstNode errorNode, DartType receiverType) {
-    var errorCode = receiverType == _typeSystem.typeProvider.nullType
-        ? CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE
-        : CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE;
-    _errorReporter.reportErrorForNode(errorCode, errorNode);
+  void report(AstNode errorNode, DartType receiverType,
+      {ErrorCode errorCode, List<String> arguments = const <String>[]}) {
+    if (receiverType == _typeSystem.typeProvider.nullType) {
+      errorCode = CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE;
+    } else {
+      errorCode ??= CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE;
+    }
+    _errorReporter.reportErrorForNode(errorCode, errorNode, arguments);
   }
 
   /// If the [receiverType] is potentially nullable, report it.
   ///
   /// The [errorNode] is usually the receiver of the invocation, but if the
   /// receiver is the implicit `this`, the name of the invocation.
-  bool _check(AstNode errorNode, DartType receiverType) {
+  ///
+  /// Returns whether [receiverType] was reported.
+  bool _check(AstNode errorNode, DartType receiverType, {ErrorCode errorCode}) {
     if (identical(receiverType, DynamicTypeImpl.instance) ||
         !_typeSystem.isPotentiallyNullable(receiverType)) {
       return false;
     }
 
-    report(errorNode, receiverType);
+    report(errorNode, receiverType, errorCode: errorCode);
     return true;
   }
 }
diff --git a/pkg/analyzer/lib/src/error/return_type_verifier.dart b/pkg/analyzer/lib/src/error/return_type_verifier.dart
index af65202..ce9f2eb 100644
--- a/pkg/analyzer/lib/src/error/return_type_verifier.dart
+++ b/pkg/analyzer/lib/src/error/return_type_verifier.dart
@@ -155,7 +155,13 @@
     var S = expression.staticType;
 
     void reportTypeError() {
-      if (enclosingExecutable.isClosure) {
+      if (enclosingExecutable.catchErrorOnErrorReturnType != null) {
+        _errorReporter.reportErrorForNode(
+          HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR,
+          expression,
+          [S, T],
+        );
+      } else if (enclosingExecutable.isClosure) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
           expression,
@@ -256,7 +262,13 @@
     var S = expression.staticType;
 
     void reportTypeError() {
-      if (enclosingExecutable.isClosure) {
+      if (enclosingExecutable.catchErrorOnErrorReturnType != null) {
+        _errorReporter.reportErrorForNode(
+          HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR,
+          expression,
+          [S, T],
+        );
+      } else if (enclosingExecutable.isClosure) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
           expression,
diff --git a/pkg/analyzer/lib/src/error/todo_finder.dart b/pkg/analyzer/lib/src/error/todo_finder.dart
index 3241562..140a09e 100644
--- a/pkg/analyzer/lib/src/error/todo_finder.dart
+++ b/pkg/analyzer/lib/src/error/todo_finder.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/error/codes.dart';
 
 /// Instances of the class `ToDoFinder` find to-do comments in Dart code.
@@ -12,6 +13,15 @@
   /// The error reporter by which to-do comments will be reported.
   final ErrorReporter _errorReporter;
 
+  /// A regex for whitespace and comment markers to be removed from the text
+  /// of multiline TODOs in multiline comments.
+  final RegExp _commentNewlineAndMarker = RegExp('\\s*\\n\\s*\\*\\s*');
+
+  /// A regex for any character that is not a comment marker `/` or whitespace
+  /// used for finding the first "real" character of a comment to compare its
+  /// indentation for wrapped todos.
+  final RegExp _nonWhitespaceOrCommentMarker = RegExp('[^/ ]');
+
   /// Initialize a newly created to-do finder to report to-do comments to the
   /// given reporter.
   ///
@@ -24,46 +34,101 @@
   ///
   /// @param unit the compilation unit containing the to-do comments
   void findIn(CompilationUnit unit) {
-    _gatherTodoComments(unit.beginToken);
+    _gatherTodoComments(unit.beginToken, unit.lineInfo);
   }
 
   /// Search the comment tokens reachable from the given token and create errors
   /// for each to-do comment.
   ///
   /// @param token the head of the list of tokens being searched
-  void _gatherTodoComments(Token token) {
+  void _gatherTodoComments(Token token, LineInfo lineInfo) {
     while (token != null && token.type != TokenType.EOF) {
       Token commentToken = token.precedingComments;
       while (commentToken != null) {
         if (commentToken.type == TokenType.SINGLE_LINE_COMMENT ||
             commentToken.type == TokenType.MULTI_LINE_COMMENT) {
-          _scrapeTodoComment(commentToken);
+          commentToken = _scrapeTodoComment(commentToken, lineInfo);
+        } else {
+          commentToken = commentToken.next;
         }
-        commentToken = commentToken.next;
       }
       token = token.next;
     }
   }
 
-  /// Look for user defined tasks in comments and convert them into info level
-  /// analysis issues.
+  /// Look for user defined tasks in comments starting [commentToken] and convert
+  /// them into info level analysis issues.
   ///
-  /// @param commentToken the comment token to analyze
-  void _scrapeTodoComment(Token commentToken) {
+  /// Subsequent comments that are indented with an additional space are
+  /// considered continuations and will be included in a single analysis issue.
+  ///
+  /// Returns the next comment token to begin searching from (skipping over
+  /// any continuations).
+  Token _scrapeTodoComment(Token commentToken, LineInfo lineInfo) {
     Iterable<Match> matches =
         TodoCode.TODO_REGEX.allMatches(commentToken.lexeme);
+    // Track the comment that will be returned for looking for the next todo.
+    // This will be moved along if additional comments are consumed by multiline
+    // TODOs.
+    var nextComment = commentToken.next;
+    final commentLocation = lineInfo.getLocation(commentToken.offset);
+
     for (Match match in matches) {
       int offset = commentToken.offset + match.start + match.group(1).length;
+      int column =
+          commentLocation.columnNumber + match.start + match.group(1).length;
       String todoText = match.group(2);
+      int end = offset + todoText.length;
 
-      if (commentToken.type == TokenType.MULTI_LINE_COMMENT &&
-          todoText.endsWith('*/')) {
-        // Remove the `*/` and trim any trailing whitespace.
-        todoText = todoText.substring(0, todoText.length - 2).trimRight();
+      if (commentToken.type == TokenType.MULTI_LINE_COMMENT) {
+        // Remove any `*/` and trim any trailing whitespace.
+        if (todoText.endsWith('*/')) {
+          todoText = todoText.substring(0, todoText.length - 2).trimRight();
+          end = offset + todoText.length;
+        }
+
+        // Replace out whitespace/comment markers to unwrap multiple lines.
+        // Do not reset length after this, as length must include all characters.
+        todoText = todoText.replaceAll(_commentNewlineAndMarker, ' ');
+      } else if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
+        // Append any indented lines onto the end.
+        var line = commentLocation.lineNumber;
+        while (nextComment != null) {
+          final nextCommentLocation = lineInfo.getLocation(nextComment.offset);
+          final columnOfFirstNoneMarkerOrWhitespace =
+              nextCommentLocation.columnNumber +
+                  nextComment.lexeme.indexOf(_nonWhitespaceOrCommentMarker);
+
+          final isContinuation =
+              nextComment.type == TokenType.SINGLE_LINE_COMMENT &&
+                  // Only consider TODOs on the very next line.
+                  nextCommentLocation.lineNumber == line++ + 1 &&
+                  // Only consider comment tokens starting at the same column.
+                  nextCommentLocation.columnNumber ==
+                      commentLocation.columnNumber &&
+                  // And indented more than the original 'todo' text.
+                  columnOfFirstNoneMarkerOrWhitespace == column + 1 &&
+                  // And not their own todos.
+                  !TodoCode.TODO_REGEX.hasMatch(nextComment.lexeme);
+          if (!isContinuation) {
+            break;
+          }
+
+          // Track the end of the continuation for the diagnostic range.
+          end = nextComment.end;
+          final lexemeTextOffset = columnOfFirstNoneMarkerOrWhitespace -
+              nextCommentLocation.columnNumber;
+          final continuationText =
+              nextComment.lexeme.substring(lexemeTextOffset).trimRight();
+          todoText = '$todoText $continuationText';
+          nextComment = nextComment.next;
+        }
       }
 
       _errorReporter.reportErrorForOffset(
-          TodoCode.TODO, offset, todoText.length, [todoText]);
+          TodoCode.TODO, offset, end - offset, [todoText]);
     }
+
+    return nextComment;
   }
 }
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index e37d63d..cdcbe34 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -188,61 +188,103 @@
   /// Verify that the type arguments in the given [typeName] are all within
   /// their bounds.
   void _checkForTypeArgumentNotMatchingBounds(TypeName typeName) {
-    var element = typeName.name.staticElement;
     var type = typeName.type;
 
     List<TypeParameterElement> typeParameters;
     List<DartType> typeArguments;
-    if (type is InterfaceType) {
+    var aliasElement = type.aliasElement;
+    if (aliasElement != null) {
+      typeParameters = aliasElement.typeParameters;
+      typeArguments = type.aliasArguments;
+    } else if (type is InterfaceType) {
       typeParameters = type.element.typeParameters;
       typeArguments = type.typeArguments;
-    } else if (element is FunctionTypeAliasElement && type is FunctionType) {
-      typeParameters = element.typeParameters;
-      typeArguments = type.typeArguments;
     } else {
       return;
     }
 
-    // iterate over each bounded type parameter and corresponding argument
-    NodeList<TypeAnnotation> argumentNodes = typeName.typeArguments?.arguments;
-    int loopThroughIndex =
-        math.min(typeArguments.length, typeParameters.length);
-    bool shouldSubstitute = typeArguments.isNotEmpty;
-    for (int i = 0; i < loopThroughIndex; i++) {
-      DartType argType = typeArguments[i];
-      TypeAnnotation argumentNode =
-          argumentNodes != null && i < argumentNodes.length
-              ? argumentNodes[i]
-              : typeName;
-      if (argType is FunctionType && argType.typeFormals.isNotEmpty) {
+    if (typeParameters.isEmpty) {
+      return;
+    }
+
+    // Check for regular-bounded.
+    List<_TypeArgumentIssue> issues;
+    var substitution = Substitution.fromPairs(typeParameters, typeArguments);
+    for (var i = 0; i < typeArguments.length; i++) {
+      var typeParameter = typeParameters[i];
+      var typeArgument = typeArguments[i];
+
+      if (typeArgument is FunctionType && typeArgument.typeFormals.isNotEmpty) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT,
-          argumentNode,
+          _typeArgumentErrorNode(typeName, i),
         );
         continue;
       }
-      DartType boundType = typeParameters[i].bound;
-      if (argType != null && boundType != null) {
-        boundType = _libraryElement.toLegacyTypeIfOptOut(boundType);
-        if (shouldSubstitute) {
-          boundType = Substitution.fromPairs(typeParameters, typeArguments)
-              .substituteType(boundType);
-        }
 
-        if (!_typeSystem.isSubtypeOf2(argType, boundType)) {
-          if (_shouldAllowSuperBoundedTypes(typeName)) {
-            var replacedType = _typeSystem.replaceTopAndBottom(argType);
-            if (!identical(replacedType, argType) &&
-                _typeSystem.isSubtypeOf2(replacedType, boundType)) {
-              // Bound is satisfied under super-bounded rules, so we're ok.
-              continue;
-            }
-          }
-          _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
-              argumentNode,
-              [argType, boundType]);
-        }
+      var bound = typeParameter.bound;
+      if (bound == null) {
+        continue;
+      }
+
+      bound = _libraryElement.toLegacyTypeIfOptOut(bound);
+      bound = substitution.substituteType(bound);
+
+      if (!_typeSystem.isSubtypeOf2(typeArgument, bound)) {
+        issues ??= <_TypeArgumentIssue>[];
+        issues.add(
+          _TypeArgumentIssue(i, typeParameter, typeArgument),
+        );
+      }
+    }
+
+    // If regular-bounded, we are done.
+    if (issues == null) {
+      return;
+    }
+
+    // If not allowed to be super-bounded, report issues.
+    if (!_shouldAllowSuperBoundedTypes(typeName)) {
+      for (var issue in issues) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+          _typeArgumentErrorNode(typeName, issue.index),
+          [issue.argument, issue.parameter],
+        );
+      }
+      return;
+    }
+
+    // Prepare type arguments for checking for super-bounded.
+    type = _typeSystem.replaceTopAndBottom(type);
+    if (type.aliasElement != null) {
+      typeArguments = type.aliasArguments;
+    } else if (type is InterfaceType) {
+      typeArguments = type.typeArguments;
+    } else {
+      return;
+    }
+
+    // Check for super-bounded.
+    substitution = Substitution.fromPairs(typeParameters, typeArguments);
+    for (var i = 0; i < typeArguments.length; i++) {
+      var typeParameter = typeParameters[i];
+      var typeArgument = typeArguments[i];
+
+      var bound = typeParameter.bound;
+      if (bound == null) {
+        continue;
+      }
+
+      bound = _libraryElement.toLegacyTypeIfOptOut(bound);
+      bound = substitution.substituteType(bound);
+
+      if (!_typeSystem.isSubtypeOf2(typeArgument, bound)) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+          _typeArgumentErrorNode(typeName, i),
+          [typeArgument, bound],
+        );
       }
     }
   }
@@ -353,10 +395,19 @@
   /// - the element is marked with `@optionalTypeArgs` from "package:meta".
   bool _isMissingTypeArguments(AstNode node, DartType type, Element element,
       Expression inferenceContextNode) {
+    List<DartType> typeArguments;
+    var aliasElement = type.aliasElement;
+    if (aliasElement != null) {
+      typeArguments = type.aliasArguments;
+    } else if (type is InterfaceType) {
+      typeArguments = type.typeArguments;
+    } else {
+      return false;
+    }
+
     // Check if this type has type arguments and at least one is dynamic.
     // If so, we may need to issue a strict-raw-types error.
-    if (type is ParameterizedType &&
-        type.typeArguments.any((t) => t.isDynamic)) {
+    if (typeArguments.any((t) => t.isDynamic)) {
       // If we have an inference context node, check if the type was inferred
       // from it. Some cases will not have a context type, such as the type
       // annotation `List` in `List list;`
@@ -387,4 +438,32 @@
     if (parent is ImplementsClause) return false;
     return true;
   }
+
+  /// Return the type arguments at [index] from [node], or the [node] itself.
+  static TypeAnnotation _typeArgumentErrorNode(TypeName node, int index) {
+    var typeArguments = node.typeArguments?.arguments;
+    if (typeArguments != null && index < typeArguments.length) {
+      return typeArguments[index];
+    }
+    return node;
+  }
+}
+
+class _TypeArgumentIssue {
+  /// The index for type argument within the passed type arguments.
+  final int index;
+
+  /// The type parameter with the bound that was violated.
+  final TypeParameterElement parameter;
+
+  /// The type argument that violated the bound.
+  final DartType argument;
+
+  _TypeArgumentIssue(this.index, this.parameter, this.argument);
+
+  @override
+  String toString() {
+    return 'TypeArgumentIssue(index=$index, parameter=$parameter, '
+        'argument=$argument)';
+  }
 }
diff --git a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
index 03496ce..57c322d 100644
--- a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
+++ b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
@@ -343,8 +343,6 @@
         _visitFieldElement(element);
       } else if (element is FunctionElement) {
         _visitFunctionElement(element);
-      } else if (element is FunctionTypeAliasElement) {
-        _visitFunctionTypeAliasElement(element);
       } else if (element is LocalVariableElement) {
         _visitLocalVariableElement(element);
       } else if (element is MethodElement) {
@@ -353,6 +351,8 @@
         _visitPropertyAccessorElement(element);
       } else if (element is TopLevelVariableElement) {
         _visitTopLevelVariableElement(element);
+      } else if (element is TypeAliasElement) {
+        _visitTypeAliasElement(element);
       }
     }
   }
@@ -580,13 +580,6 @@
     }
   }
 
-  void _visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
-    if (!_isUsedElement(element)) {
-      _reportErrorForElement(
-          HintCode.UNUSED_ELEMENT, element, [element.displayName]);
-    }
-  }
-
   void _visitLocalVariableElement(LocalVariableElement element) {
     if (!_isUsedElement(element) && !_isNamedUnderscore(element)) {
       HintCode errorCode;
@@ -621,6 +614,13 @@
           HintCode.UNUSED_ELEMENT, element, [element.displayName]);
     }
   }
+
+  void _visitTypeAliasElement(TypeAliasElement element) {
+    if (!_isUsedElement(element)) {
+      _reportErrorForElement(
+          HintCode.UNUSED_ELEMENT, element, [element.displayName]);
+    }
+  }
 }
 
 /// A container with sets of used [Element]s.
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 16eb67e..3c91d82 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -3550,7 +3550,7 @@
   }
 
   @override
-  dynamic internalProblem(Message message, int charOffset, Uri uri) {
+  internalProblem(Message message, int charOffset, Uri uri) {
     throw UnsupportedError(message.message);
   }
 
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 2fd3549..bfc91e0 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -23,7 +23,7 @@
       String analyzerCode, int offset, int length, Message message) {
     Map<String, dynamic> arguments = message.arguments;
 
-    String lexeme() => (arguments['token'] as Token).lexeme;
+    String lexeme() => (arguments['lexeme'] as Token).lexeme;
 
     switch (analyzerCode) {
       case "ASYNC_FOR_IN_WRONG_CONTEXT":
@@ -350,8 +350,12 @@
     if (index != null && index > 0 && index < fastaAnalyzerErrorCodes.length) {
       ErrorCode errorCode = fastaAnalyzerErrorCodes[index];
       if (errorCode != null) {
-        errorReporter.reportError(AnalysisError.forValues(errorReporter.source,
-            offset, length, errorCode, message.message, message.tip));
+        errorReporter.reportError(AnalysisError.withNamedArguments(
+            errorReporter.source,
+            offset,
+            length,
+            errorCode,
+            message.arguments));
         return;
       }
     }
@@ -368,8 +372,8 @@
   void _reportByCode(
       ErrorCode errorCode, Message message, int offset, int length) {
     if (errorReporter != null) {
-      errorReporter.reportError(AnalysisError.forValues(errorReporter.source,
-          offset, length, errorCode, message.message, null));
+      errorReporter.reportError(AnalysisError.withNamedArguments(
+          errorReporter.source, offset, length, errorCode, message.arguments));
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 5864421..eba129d 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -723,9 +723,14 @@
   /// returned.
   static ClassElement getTypeReference(Expression expression) {
     if (expression is Identifier) {
-      Element staticElement = expression.staticElement;
-      if (staticElement is ClassElement) {
-        return staticElement;
+      var element = expression.staticElement;
+      if (element is ClassElement) {
+        return element;
+      } else if (element is TypeAliasElement) {
+        var aliasedType = element.aliasedType;
+        if (aliasedType is InterfaceType) {
+          return aliasedType.element;
+        }
       }
     }
     return null;
@@ -736,7 +741,9 @@
     for (Annotation annotation in annotations) {
       var elementAnnotation =
           annotation.elementAnnotation as ElementAnnotationImpl;
-      elementAnnotation.element = annotation.element;
+      if (elementAnnotation != null) {
+        elementAnnotation.element = annotation.element;
+      }
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index e54f009..b275202 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -53,6 +53,12 @@
   final bool inFactoryConstructor;
   final bool inStaticMethod;
 
+  /// If this [EnclosingExecutableContext] is the first argument in a method
+  /// invocation of [Future.catchError], returns the return type expected for
+  /// `Future<T>.catchError`'s `onError` parameter, which is `FutureOr<T>`,
+  /// otherwise `null`.
+  final InterfaceType catchErrorOnErrorReturnType;
+
   /// The return statements that have a value.
   final List<ReturnStatement> _returnsWith = [];
 
@@ -63,8 +69,10 @@
   /// for the kind of the function body, e.g. not `Future` for `async`.
   bool hasLegalReturnType = true;
 
-  EnclosingExecutableContext(this.element)
-      : isAsynchronous = element != null && element.isAsynchronous,
+  EnclosingExecutableContext(this.element,
+      {bool isAsynchronous, this.catchErrorOnErrorReturnType})
+      : isAsynchronous =
+            isAsynchronous ?? (element != null && element.isAsynchronous),
         isConstConstructor = element is ConstructorElement && element.isConst,
         isGenerativeConstructor =
             element is ConstructorElement && !element.isFactory,
@@ -104,7 +112,7 @@
 
   bool get isSynchronous => !isAsynchronous;
 
-  DartType get returnType => element.returnType;
+  DartType get returnType => catchErrorOnErrorReturnType ?? element.returnType;
 
   static bool _inFactoryConstructor(ExecutableElement element) {
     if (element is ConstructorElement) {
@@ -747,12 +755,12 @@
   void visitFunctionExpression(FunctionExpression node) {
     _isInLateLocalVariable.add(false);
 
-    if (node.parent is! FunctionDeclaration) {
+    if (node.parent is FunctionDeclaration) {
+      super.visitFunctionExpression(node);
+    } else {
       _withEnclosingExecutable(node.declaredElement, () {
         super.visitFunctionExpression(node);
       });
-    } else {
-      super.visitFunctionExpression(node);
     }
 
     _isInLateLocalVariable.removeLast();
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 9cf47f3..8a32c10 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -14,6 +14,12 @@
 /// used. See 'pkg/vm/lib/transformations/ffi_checks.md' for the specification
 /// of the desired hints.
 class FfiVerifier extends RecursiveAstVisitor<void> {
+  static const _allocatorClassName = 'Allocator';
+  static const _allocateExtensionMethodName = 'call';
+  static const _allocatorExtensionName = 'AllocatorAlloc';
+  static const _dartFfiLibraryName = 'dart.ffi';
+  static const _opaqueClassName = 'Opaque';
+
   static const List<String> _primitiveIntegerNativeTypes = [
     'Int8',
     'Int16',
@@ -31,6 +37,8 @@
     'Double',
   ];
 
+  static const _structClassName = 'Struct';
+
   /// The type system used to check types.
   final TypeSystemImpl typeSystem;
 
@@ -47,14 +55,20 @@
   @override
   void visitClassDeclaration(ClassDeclaration node) {
     inStruct = false;
-    // Only the Struct class may be extended.
+    // Only the Allocator, Opaque and Struct class may be extended.
     ExtendsClause extendsClause = node.extendsClause;
     if (extendsClause != null) {
       final TypeName superclass = extendsClause.superclass;
       if (_isDartFfiClass(superclass)) {
-        if (superclass.name.staticElement.name == 'Struct') {
+        final className = superclass.name.staticElement.name;
+        if (className == _structClassName) {
           inStruct = true;
-        } else {
+          if (_isEmptyStruct(node.declaredElement)) {
+            _errorReporter.reportErrorForNode(
+                FfiCode.EMPTY_STRUCT_WARNING, node, [node.name]);
+          }
+        } else if (className != _allocatorClassName &&
+            className != _opaqueClassName) {
           _errorReporter.reportErrorForNode(
               FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS,
               superclass.name,
@@ -71,6 +85,10 @@
     // No classes from the FFI may be explicitly implemented.
     void checkSupertype(TypeName typename, FfiCode subtypeOfFfiCode,
         FfiCode subtypeOfStructCode) {
+      final superName = typename.name?.staticElement?.name;
+      if (superName == _allocatorClassName) {
+        return;
+      }
       if (_isDartFfiClass(typename)) {
         _errorReporter.reportErrorForNode(
             subtypeOfFfiCode, typename, [node.name, typename.name]);
@@ -120,14 +138,44 @@
   }
 
   @override
+  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    Element element = node?.staticElement;
+    if (element is MethodElement) {
+      Element enclosingElement = element?.enclosingElement;
+      if (enclosingElement is ExtensionElement) {
+        if (_isAllocatorExtension(enclosingElement) &&
+            element.name == _allocateExtensionMethodName) {
+          _validateAllocate(node);
+        }
+      }
+    }
+    super.visitFunctionExpressionInvocation(node);
+  }
+
+  @override
+  void visitIndexExpression(IndexExpression node) {
+    Element element = node?.staticElement;
+    Element enclosingElement = element?.enclosingElement;
+    if (enclosingElement is ExtensionElement) {
+      if (_isNativeStructPointerExtension(enclosingElement)) {
+        if (element.name == '[]') {
+          _validateRefIndexed(node);
+        }
+      }
+    }
+  }
+
+  @override
   void visitMethodInvocation(MethodInvocation node) {
-    Element element = node.methodName.staticElement;
+    Element element = node.methodName?.staticElement;
     if (element is MethodElement) {
       Element enclosingElement = element.enclosingElement;
       if (enclosingElement is ClassElement) {
         if (_isPointer(enclosingElement)) {
           if (element.name == 'fromFunction') {
             _validateFromFunction(node, element);
+          } else if (element.name == 'elementAt') {
+            _validateElementAt(node);
           }
         }
       }
@@ -141,10 +189,53 @@
           _validateLookupFunction(node);
         }
       }
+    } else if (element is FunctionElement) {
+      Element enclosingElement = element?.enclosingElement;
+      if (enclosingElement is CompilationUnitElement) {
+        if (element.library.name == 'dart.ffi') {
+          if (element.name == 'sizeOf') {
+            _validateSizeOf(node);
+          }
+        }
+      }
     }
     super.visitMethodInvocation(node);
   }
 
+  @override
+  void visitPrefixedIdentifier(PrefixedIdentifier node) {
+    Element element = node.staticElement;
+    Element enclosingElement = element?.enclosingElement;
+    if (enclosingElement is ExtensionElement) {
+      if (_isNativeStructPointerExtension(enclosingElement)) {
+        if (element.name == 'ref') {
+          _validateRefPrefixedIdentifier(node);
+        }
+      }
+    }
+    super.visitPrefixedIdentifier(node);
+  }
+
+  @override
+  void visitPropertyAccess(PropertyAccess node) {
+    Element element = node.propertyName.staticElement;
+    Element enclosingElement = element?.enclosingElement;
+    if (enclosingElement is ExtensionElement) {
+      if (_isNativeStructPointerExtension(enclosingElement)) {
+        if (element.name == 'ref') {
+          _validateRefPropertyAccess(node);
+        }
+      }
+    }
+    super.visitPropertyAccess(node);
+  }
+
+  /// Return `true` if the given [element] represents the extension
+  /// `AllocatorAlloc`.
+  bool _isAllocatorExtension(Element element) =>
+      element.name == _allocatorExtensionName &&
+      element.library.name == _dartFfiLibraryName;
+
   /// Return `true` if the [typeName] is the name of a type from `dart:ffi`.
   bool _isDartFfiClass(TypeName typeName) =>
       _isDartFfiElement(typeName.name.staticElement);
@@ -154,23 +245,42 @@
     if (element is ConstructorElement) {
       element = element.enclosingElement;
     }
-    return element is ClassElement && element.library.name == 'dart.ffi';
+    return element is ClassElement &&
+        element.library.name == _dartFfiLibraryName;
   }
 
   /// Return `true` if the given [element] represents the extension
   /// `DynamicLibraryExtension`.
   bool _isDynamicLibraryExtension(Element element) =>
       element.name == 'DynamicLibraryExtension' &&
-      element.library.name == 'dart.ffi';
+      element.library.name == _dartFfiLibraryName;
+
+  bool _isEmptyStruct(ClassElement classElement) {
+    final fields = classElement.fields;
+    var structFieldCount = 0;
+    for (final field in fields) {
+      final declaredType = field.type;
+      if (declaredType.isDartCoreInt) {
+        structFieldCount++;
+      } else if (declaredType.isDartCoreDouble) {
+        structFieldCount++;
+      } else if (_isPointer(declaredType.element)) {
+        structFieldCount++;
+      } else if (_isStructClass(declaredType)) {
+        structFieldCount++;
+      }
+    }
+    return structFieldCount == 0;
+  }
 
   bool _isHandle(Element element) =>
-      element.name == 'Handle' && element.library.name == 'dart.ffi';
+      element.name == 'Handle' && element.library.name == _dartFfiLibraryName;
 
   /// Returns `true` iff [nativeType] is a `ffi.NativeFunction<???>` type.
   bool _isNativeFunctionInterfaceType(DartType nativeType) {
     if (nativeType is InterfaceType) {
       final element = nativeType.element;
-      if (element.library.name == 'dart.ffi') {
+      if (element.library.name == _dartFfiLibraryName) {
         return element.name == 'NativeFunction' &&
             nativeType.typeArguments?.length == 1;
       }
@@ -180,28 +290,46 @@
 
   bool _isNativeFunctionPointerExtension(Element element) =>
       element.name == 'NativeFunctionPointer' &&
-      element.library.name == 'dart.ffi';
+      element.library.name == _dartFfiLibraryName;
+
+  bool _isNativeStructPointerExtension(Element element) =>
+      element.name == 'StructPointer' && element.library.name == 'dart.ffi';
 
   /// Returns `true` iff [nativeType] is a `ffi.NativeType` type.
   bool _isNativeTypeInterfaceType(DartType nativeType) {
     if (nativeType is InterfaceType) {
       final element = nativeType.element;
-      if (element.library.name == 'dart.ffi') {
+      if (element.library.name == _dartFfiLibraryName) {
         return element.name == 'NativeType';
       }
     }
     return false;
   }
 
+  /// Returns `true` iff [nativeType] is a opaque type, i.e. a subtype of `Opaque`.
+  bool _isOpaqueClass(DartType nativeType) {
+    if (nativeType is InterfaceType) {
+      final superType = nativeType.element.supertype;
+      if (superType == null) {
+        return false;
+      }
+      final superClassElement = superType.element;
+      if (superClassElement.library.name == _dartFfiLibraryName) {
+        return superClassElement.name == _opaqueClassName;
+      }
+    }
+    return false;
+  }
+
   /// Return `true` if the given [element] represents the class `Pointer`.
   bool _isPointer(Element element) =>
-      element.name == 'Pointer' && element.library.name == 'dart.ffi';
+      element.name == 'Pointer' && element.library.name == _dartFfiLibraryName;
 
   /// Returns `true` iff [nativeType] is a `ffi.Pointer<???>` type.
   bool _isPointerInterfaceType(DartType nativeType) {
     if (nativeType is InterfaceType) {
       final element = nativeType.element;
-      if (element.library.name == 'dart.ffi') {
+      if (element.library.name == _dartFfiLibraryName) {
         return element.name == 'Pointer' &&
             nativeType.typeArguments?.length == 1;
       }
@@ -212,9 +340,13 @@
   /// Returns `true` iff [nativeType] is a struct type.
   bool _isStructClass(DartType nativeType) {
     if (nativeType is InterfaceType) {
-      final superClassElement = nativeType.element.supertype.element;
-      if (superClassElement.library.name == 'dart.ffi') {
-        return superClassElement.name == 'Struct' &&
+      final superType = nativeType.element.supertype;
+      if (superType == null) {
+        return false;
+      }
+      final superClassElement = superType.element;
+      if (superClassElement.library.name == _dartFfiLibraryName) {
+        return superClassElement.name == _structClassName &&
             nativeType.typeArguments?.isEmpty == true;
       }
     }
@@ -227,8 +359,8 @@
     if (superType is ClassElement) {
       bool isStruct(InterfaceType type) {
         return type != null &&
-            type.element.name == 'Struct' &&
-            type.element.library.name == 'dart.ffi';
+            type.element.name == _structClassName &&
+            type.element.library.name == _dartFfiLibraryName;
       }
 
       return isStruct(superType.supertype) ||
@@ -246,12 +378,12 @@
           nativeType.optionalParameterTypes.isNotEmpty) {
         return false;
       }
-      if (!_isValidFfiNativeType(nativeType.returnType, true)) {
+      if (!_isValidFfiNativeType(nativeType.returnType, true, false)) {
         return false;
       }
 
-      for (final DartType typeArg in nativeType.typeArguments) {
-        if (!_isValidFfiNativeType(typeArg, false)) {
+      for (final DartType typeArg in nativeType.normalParameterTypes) {
+        if (!_isValidFfiNativeType(typeArg, false, false)) {
           return false;
         }
       }
@@ -261,7 +393,9 @@
   }
 
   /// Validates that the given [nativeType] is a valid dart:ffi native type.
-  bool _isValidFfiNativeType(DartType nativeType, bool allowVoid) {
+  // TODO(https://dartbug.com/44747): Change to named arguments.
+  bool _isValidFfiNativeType(
+      DartType nativeType, bool allowVoid, bool allowEmptyStruct) {
     if (nativeType is InterfaceType) {
       // Is it a primitive integer/double type (or ffi.Void if we allow it).
       final primitiveType = _primitiveNativeType(nativeType);
@@ -274,10 +408,23 @@
       }
       if (_isPointerInterfaceType(nativeType)) {
         final nativeArgumentType = nativeType.typeArguments.single;
-        return _isValidFfiNativeType(nativeArgumentType, true) ||
+        return _isValidFfiNativeType(nativeArgumentType, true, true) ||
             _isStructClass(nativeArgumentType) ||
             _isNativeTypeInterfaceType(nativeArgumentType);
       }
+      if (_isStructClass(nativeType)) {
+        if (!allowEmptyStruct) {
+          if (_isEmptyStruct(nativeType.element)) {
+            // TODO(dartbug.com/36780): This results in an error message not
+            // mentioning empty structs at all.
+            return false;
+          }
+        }
+        return true;
+      }
+      if (_isOpaqueClass(nativeType)) {
+        return true;
+      }
     } else if (nativeType is FunctionType) {
       return _isValidFfiNativeFunctionType(nativeType);
     }
@@ -287,7 +434,7 @@
   _PrimitiveDartType _primitiveNativeType(DartType nativeType) {
     if (nativeType is InterfaceType) {
       final element = nativeType.element;
-      if (element.library.name == 'dart.ffi') {
+      if (element.library.name == _dartFfiLibraryName) {
         final String name = element.name;
         if (_primitiveIntegerNativeTypes.contains(name)) {
           return _PrimitiveDartType.int;
@@ -320,6 +467,20 @@
     return _PrimitiveDartType.none;
   }
 
+  void _validateAllocate(FunctionExpressionInvocation node) {
+    if (node.typeArgumentTypes.length != 1) {
+      return;
+    }
+    final DartType dartType = node.typeArgumentTypes[0];
+    if (!_isValidFfiNativeType(dartType, true, true)) {
+      final AstNode errorNode = node;
+      _errorReporter.reportErrorForNode(
+          FfiCode.NON_CONSTANT_TYPE_ARGUMENT,
+          errorNode,
+          ['$_allocatorExtensionName.$_allocateExtensionMethodName']);
+    }
+  }
+
   /// Validate that the [annotations] include exactly one annotation that
   /// satisfies the [requiredTypes]. If an error is produced that cannot be
   /// associated with an annotation, associate it with the [errorNode].
@@ -471,6 +632,24 @@
     }
   }
 
+  void _validateElementAt(MethodInvocation node) {
+    Expression target = node.realTarget;
+    DartType targetType = target?.staticType;
+    if (targetType is InterfaceType &&
+        _isPointer(targetType.element) &&
+        targetType.typeArguments.length == 1) {
+      final DartType T = targetType.typeArguments[0];
+
+      if (!_isValidFfiNativeType(T, true, true)) {
+        final AstNode errorNode = node;
+        _errorReporter.reportErrorForNode(
+            FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING,
+            errorNode,
+            ['elementAt']);
+      }
+    }
+  }
+
   /// Validate that the fields declared by the given [node] meet the
   /// requirements for fields within a struct class.
   void _validateFieldsInStruct(FieldDeclaration node) {
@@ -491,6 +670,12 @@
         _validateAnnotations(fieldType, annotations, _PrimitiveDartType.double);
       } else if (_isPointer(declaredType.element)) {
         _validateNoAnnotations(annotations);
+      } else if (_isStructClass(declaredType)) {
+        final clazz = (declaredType as InterfaceType).element;
+        if (_isEmptyStruct(clazz)) {
+          _errorReporter
+              .reportErrorForNode(FfiCode.EMPTY_STRUCT, node, [clazz.name]);
+        }
       } else {
         _errorReporter.reportErrorForNode(FfiCode.INVALID_FIELD_TYPE_IN_STRUCT,
             fieldType, [fieldType.toSource()]);
@@ -533,7 +718,8 @@
     final DartType R = (T as FunctionType).returnType;
     if ((FT as FunctionType).returnType.isVoid ||
         _isPointer(R.element) ||
-        _isHandle(R.element)) {
+        _isHandle(R.element) ||
+        _isStructClass(R)) {
       if (argCount != 1) {
         _errorReporter.reportErrorForNode(
             FfiCode.INVALID_EXCEPTION_VALUE, node.argumentList.arguments[1]);
@@ -588,6 +774,47 @@
     }
   }
 
+  void _validateRefIndexed(IndexExpression node) {
+    DartType targetType = node.target?.staticType;
+    if (!_isValidFfiNativeType(targetType, false, true)) {
+      final AstNode errorNode = node;
+      _errorReporter.reportErrorForNode(
+          FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, errorNode, ['[]']);
+    }
+  }
+
+  /// Validate the invocation of the extension method
+  /// `Pointer<T extends Struct>.ref`.
+  void _validateRefPrefixedIdentifier(PrefixedIdentifier node) {
+    DartType targetType = node.prefix.staticType;
+    if (!_isValidFfiNativeType(targetType, false, true)) {
+      final AstNode errorNode = node;
+      _errorReporter.reportErrorForNode(
+          FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, errorNode, ['ref']);
+    }
+  }
+
+  void _validateRefPropertyAccess(PropertyAccess node) {
+    DartType targetType = node.target?.staticType;
+    if (!_isValidFfiNativeType(targetType, false, true)) {
+      final AstNode errorNode = node;
+      _errorReporter.reportErrorForNode(
+          FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, errorNode, ['ref']);
+    }
+  }
+
+  void _validateSizeOf(MethodInvocation node) {
+    if (node.typeArgumentTypes.length != 1) {
+      return;
+    }
+    final DartType T = node.typeArgumentTypes[0];
+    if (!_isValidFfiNativeType(T, true, true)) {
+      final AstNode errorNode = node;
+      _errorReporter.reportErrorForNode(
+          FfiCode.NON_CONSTANT_TYPE_ARGUMENT_WARNING, errorNode, ['sizeOf']);
+    }
+  }
+
   /// Validate that the given [typeArgument] has a constant value. Return `true`
   /// if a diagnostic was produced because it isn't constant.
   bool _validateTypeArgument(TypeAnnotation typeArgument, String functionName) {
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 89c2ca2..9b05a6f 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -4,40 +4,25 @@
 
 library analyzer.parser;
 
-import 'dart:collection';
-import "dart:math" as math;
-
 import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart'
     as fasta;
 import 'package:_fe_analyzer_shared/src/parser/member_kind.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/parser/type_info.dart' as fasta;
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/fasta/ast_builder.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
-import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:meta/meta.dart';
 
 export 'package:analyzer/src/dart/ast/utilities.dart' show ResolutionCopier;
 export 'package:analyzer/src/dart/error/syntactic_errors.dart';
 
-part 'parser_fasta.dart';
-
 /// A simple data-holder for a method that needs to return multiple values.
 class CommentAndMetadata {
   /// The documentation comment that was parsed, or `null` if none was given.
@@ -129,7873 +114,260 @@
 
 /// A parser used to parse tokens into an AST structure.
 class Parser {
-  static String ASYNC = Keyword.ASYNC.lexeme;
+  Token currentToken;
 
-  static final String _AWAIT = Keyword.AWAIT.lexeme;
+  /// The fasta parser being wrapped.
+  /*late final*/ fasta.Parser fastaParser;
 
-  static final String _HIDE = Keyword.HIDE.lexeme;
+  /// The builder which creates the analyzer AST data structures
+  /// based on the Fasta parser.
+  final AstBuilder astBuilder;
 
-  static final String _SHOW = Keyword.SHOW.lexeme;
-
-  static final String SYNC = Keyword.SYNC.lexeme;
-
-  static final String _YIELD = Keyword.YIELD.lexeme;
-
-  static const int _MAX_TREE_DEPTH = 300;
-
-  /// A flag indicating whether the analyzer [Parser] factory method
-  /// will return a fasta based parser or an analyzer based parser.
-  static const bool useFasta = true;
-
-  /// The source being parsed.
-  final Source _source;
-
-  /// The error listener that will be informed of any errors that are found
-  /// during the parse.
-  final AnalysisErrorListener _errorListener;
-
-  /// An [_errorListener] lock, if more than `0`, then errors are not reported.
-  int _errorListenerLock = 0;
-
-  /// A flag indicating whether the parser should parse instance creation
-  /// expressions that lack either the `new` or `const` keyword.
-  bool _enableOptionalNewAndConst = true;
-
-  /// A flag indicating whether parser is to parse function bodies.
-  bool _parseFunctionBodies = true;
-
-  /// The next token to be parsed.
-  Token _currentToken;
-
-  /// The depth of the current AST. When this depth is too high, so we're at the
-  /// risk of overflowing the stack, we stop parsing and report an error.
-  int _treeDepth = 0;
-
-  /// A flag indicating whether the parser is currently in a function body
-  /// marked as being 'async'.
-  bool _inAsync = false;
-
-  /// A flag indicating whether the parser is currently in a function body
-  ///  marked(by a star) as being a generator.
-  bool _inGenerator = false;
-
-  /// A flag indicating whether the parser is currently in the body of a loop.
-  bool _inLoop = false;
-
-  /// A flag indicating whether the parser is currently in a switch statement.
-  bool _inSwitch = false;
-
-  /// A flag indicating whether the parser is currently in a constructor field
-  /// initializer, with no intervening parentheses, braces, or brackets.
-  bool _inInitializer = false;
-
-  /// A flag indicating whether the parser is to parse generic method syntax.
-  @deprecated
-  bool parseGenericMethods = false;
-
-  bool allowNativeClause;
-
-  FeatureSet _featureSet;
-
-  /// Initialize a newly created parser to parse tokens in the given [_source]
-  /// and to report any errors that are found to the given [_errorListener].
-  factory Parser(Source source, AnalysisErrorListener errorListener,
-      {bool useFasta, @required FeatureSet featureSet}) {
-    featureSet ??= FeatureSet.latestLanguageVersion();
-    if (useFasta ?? Parser.useFasta) {
-      return _Parser2(source, errorListener, featureSet,
-          allowNativeClause: true);
-    } else {
-      return Parser.withoutFasta(source, errorListener, featureSet: featureSet);
-    }
+  Parser(Source source, AnalysisErrorListener errorListener,
+      {@required FeatureSet featureSet, bool allowNativeClause = true})
+      : astBuilder = AstBuilder(
+            ErrorReporter(
+              errorListener,
+              source,
+              isNonNullableByDefault:
+                  featureSet.isEnabled(Feature.non_nullable),
+            ),
+            source.uri,
+            true,
+            featureSet) {
+    fastaParser = fasta.Parser(astBuilder);
+    astBuilder.parser = fastaParser;
+    astBuilder.allowNativeClause = allowNativeClause;
   }
 
-  /// Creates a parser using the old (legacy) analyzer parsing logic.
-  ///
-  /// In a future major version release of the analyzer, the [featureSet]
-  /// argument will be required.
-  Parser.withoutFasta(this._source, this._errorListener,
-      {FeatureSet featureSet}) {
-    if (featureSet != null) {
-      _configureFeatures(featureSet);
-    }
+  set allowNativeClause(bool value) {
+    astBuilder.allowNativeClause = value;
   }
 
-  /// Return the current token.
-  Token get currentToken => _currentToken;
+  bool get enableOptionalNewAndConst => false;
 
-  /// Set the token with which the parse is to begin to the given [token].
-  set currentToken(Token token) {
-    _currentToken = token;
-  }
+  set enableOptionalNewAndConst(bool enable) {}
 
-  /// Return `true` if the parser is to parse asserts in the initializer list of
-  /// a constructor.
-  @deprecated
-  bool get enableAssertInitializer => true;
-
-  /// Set whether the parser is to parse asserts in the initializer list of a
-  /// constructor to match the given [enable] flag.
-  @deprecated
-  set enableAssertInitializer(bool enable) {}
-
-  /// Return `true` if the parser should parse instance creation expressions
-  /// that lack either the `new` or `const` keyword.
-  bool get enableOptionalNewAndConst => _enableOptionalNewAndConst;
-
-  /// Set whether the parser should parse instance creation expressions that
-  /// lack either the `new` or `const` keyword.
-  set enableOptionalNewAndConst(bool enable) {
-    _enableOptionalNewAndConst = enable;
-  }
-
-  /// Enables or disables parsing of set literals.
   set enableSetLiterals(bool value) {
     // TODO(danrubel): Remove this method once the reference to this flag
     // has been removed from dartfmt.
   }
 
-  /// Return `true` if the parser is to allow URI's in part-of directives.
-  @deprecated
-  bool get enableUriInPartOf => true;
-
-  /// Set whether the parser is to allow URI's in part-of directives to the
-  /// given [enable] flag.
-  @deprecated
-  set enableUriInPartOf(bool enable) {}
-
-  /// Return `true` if the current token is the first token of a return type
-  /// that is followed by an identifier, possibly followed by a list of type
-  /// parameters, followed by a left-parenthesis. This is used by
-  /// [parseTypeAlias] to determine whether or not to parse a return type.
-  bool get hasReturnTypeInTypeAlias {
-    // TODO(brianwilkerson) This is too expensive as implemented and needs to be
-    // re-implemented or removed.
-    Token next = skipTypeAnnotation(_currentToken);
-    if (next == null) {
-      return false;
-    }
-    return _tokenMatchesIdentifier(next);
-  }
-
-  /// Set whether the parser is to parse the async support.
-  ///
-  /// Support for removing the 'async' library has been removed.
-  @deprecated
-  set parseAsync(bool parseAsync) {}
-
-  @deprecated
-  bool get parseConditionalDirectives => true;
-
-  @deprecated
-  set parseConditionalDirectives(bool value) {}
-
-  /// Set whether parser is to parse function bodies.
   set parseFunctionBodies(bool parseFunctionBodies) {
-    _parseFunctionBodies = parseFunctionBodies;
+    astBuilder.parseFunctionBodies = parseFunctionBodies;
   }
 
-  /// Return the content of a string with the given literal representation. The
-  /// [lexeme] is the literal representation of the string. The flag [isFirst]
-  /// is `true` if this is the first token in a string literal. The flag
-  /// [isLast] is `true` if this is the last token in a string literal.
-  String computeStringValue(String lexeme, bool isFirst, bool isLast) {
-    StringLexemeHelper helper = StringLexemeHelper(lexeme, isFirst, isLast);
-    int start = helper.start;
-    int end = helper.end;
-    bool stringEndsAfterStart = end >= start;
-    assert(stringEndsAfterStart);
-    if (!stringEndsAfterStart) {
-      AnalysisEngine.instance.instrumentationService.logError(
-          "Internal error: computeStringValue($lexeme, $isFirst, $isLast)");
-      return "";
+  /// Append the given token to the end of the token stream,
+  /// and update the token's offset.
+  void appendToken(Token token, Token newToken) {
+    while (!token.next.isEof) {
+      token = token.next;
     }
-    if (helper.isRaw) {
-      return lexeme.substring(start, end);
-    }
-    StringBuffer buffer = StringBuffer();
-    int index = start;
-    while (index < end) {
-      index = _translateCharacter(buffer, lexeme, index);
-    }
-    return buffer.toString();
+    newToken
+      ..offset = token.end
+      ..setNext(token.next);
+    token.setNext(newToken);
   }
 
-  /// Return a synthetic identifier.
-  SimpleIdentifier createSyntheticIdentifier({bool isDeclaration = false}) {
-    Token syntheticToken;
-    if (_currentToken.type.isKeyword) {
-      // Consider current keyword token as an identifier.
-      // It is not always true, e.g. "^is T" where "^" is place the place for
-      // synthetic identifier. By creating SyntheticStringToken we can
-      // distinguish a real identifier from synthetic. In the code completion
-      // behavior will depend on a cursor position - before or on "is".
-      syntheticToken = _injectToken(SyntheticStringToken(
-          TokenType.IDENTIFIER, _currentToken.lexeme, _currentToken.offset));
-    } else {
-      syntheticToken = _createSyntheticToken(TokenType.IDENTIFIER);
-    }
-    return astFactory.simpleIdentifier(syntheticToken,
-        isDeclaration: isDeclaration);
-  }
+  Expression parseAdditiveExpression() => parseExpression2();
 
-  /// Return a synthetic string literal.
-  SimpleStringLiteral createSyntheticStringLiteral() => astFactory
-      .simpleStringLiteral(_createSyntheticToken(TokenType.STRING), "");
-
-  /// Advance to the next token in the token stream, making it the new current
-  /// token and return the token that was current before this method was
-  /// invoked.
-  Token getAndAdvance() {
-    Token token = _currentToken;
-    _currentToken = _currentToken.next;
-    return token;
-  }
-
-  /// Return `true` if the current token appears to be the beginning of a
-  /// function declaration.
-  bool isFunctionDeclaration() {
-    Keyword keyword = _currentToken.keyword;
-    Token afterReturnType = skipTypeWithoutFunction(_currentToken);
-    if (afterReturnType != null &&
-        _tokenMatchesKeyword(afterReturnType, Keyword.FUNCTION)) {
-      afterReturnType = skipGenericFunctionTypeAfterReturnType(afterReturnType);
-    }
-    // If there was no return type, because it was optional, go back
-    // to where we started.
-    afterReturnType ??= _currentToken;
-    Token afterIdentifier = skipSimpleIdentifier(afterReturnType);
-
-    // It's possible that we parsed the function name as if it were a type
-    // name, so see whether it makes sense if we assume that there is no type.
-    afterIdentifier ??= skipSimpleIdentifier(_currentToken);
-    if (afterIdentifier == null) {
-      return false;
-    }
-    if (isFunctionExpression(afterIdentifier)) {
-      return true;
-    }
-    // It's possible that we have found a getter. While this isn't valid at this
-    // point we test for it in order to recover better.
-    if (keyword == Keyword.GET) {
-      Token afterName = skipSimpleIdentifier(_currentToken.next);
-      if (afterName == null) {
-        return false;
-      }
-      TokenType type = afterName.type;
-      return type == TokenType.FUNCTION || type == TokenType.OPEN_CURLY_BRACKET;
-    } else if (_tokenMatchesKeyword(afterReturnType, Keyword.GET)) {
-      Token afterName = skipSimpleIdentifier(afterReturnType.next);
-      if (afterName == null) {
-        return false;
-      }
-      TokenType type = afterName.type;
-      return type == TokenType.FUNCTION || type == TokenType.OPEN_CURLY_BRACKET;
-    }
-    return false;
-  }
-
-  /// Return `true` if the given [token] appears to be the beginning of a
-  /// function expression.
-  bool isFunctionExpression(Token token) {
-    // Function expressions aren't allowed in initializer lists.
-    if (_inInitializer) {
-      return false;
-    }
-    Token afterTypeParameters = _skipTypeParameterList(token);
-    afterTypeParameters ??= token;
-    Token afterParameters = _skipFormalParameterList(afterTypeParameters);
-    if (afterParameters == null) {
-      return false;
-    }
-    if (afterParameters.matchesAny(
-        const <TokenType>[TokenType.OPEN_CURLY_BRACKET, TokenType.FUNCTION])) {
-      return true;
-    }
-    String lexeme = afterParameters.lexeme;
-    return lexeme == ASYNC || lexeme == SYNC;
-  }
-
-  /// Return `true` if the current token is the first token in an initialized
-  /// variable declaration rather than an expression. This method assumes that
-  /// we have already skipped past any metadata that might be associated with
-  /// the declaration.
-  ///
-  ///     initializedVariableDeclaration ::=
-  ///         declaredIdentifier ('=' expression)? (',' initializedIdentifier)*
-  ///
-  ///     declaredIdentifier ::=
-  ///         metadata finalConstVarOrType identifier
-  ///
-  ///     finalConstVarOrType ::=
-  ///         'final' type?
-  ///       | 'const' type?
-  ///       | 'var'
-  ///       | type
-  ///
-  ///     type ::=
-  ///         qualified typeArguments?
-  ///
-  ///     initializedIdentifier ::=
-  ///         identifier ('=' expression)?
-  bool isInitializedVariableDeclaration() {
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.FINAL ||
-        keyword == Keyword.VAR ||
-        keyword == Keyword.VOID) {
-      // An expression cannot start with a keyword other than 'const',
-      // 'rethrow', or 'throw'.
-      return true;
-    }
-    if (keyword == Keyword.CONST) {
-      // Look to see whether we might be at the start of a list or map literal,
-      // otherwise this should be the start of a variable declaration.
-      return !_peek().matchesAny(const <TokenType>[
-        TokenType.LT,
-        TokenType.OPEN_CURLY_BRACKET,
-        TokenType.OPEN_SQUARE_BRACKET,
-        TokenType.INDEX
-      ]);
-    }
-    bool allowAdditionalTokens = true;
-    // We know that we have an identifier, and need to see whether it might be
-    // a type name.
-    if (_currentToken.type != TokenType.IDENTIFIER) {
-      allowAdditionalTokens = false;
-    }
-    Token token = skipTypeName(_currentToken);
-    if (token == null) {
-      // There was no type name, so this can't be a declaration.
-      return false;
-    }
-    while (_atGenericFunctionTypeAfterReturnType(token)) {
-      token = skipGenericFunctionTypeAfterReturnType(token);
-      if (token == null) {
-        // There was no type name, so this can't be a declaration.
-        return false;
-      }
-    }
-    if (token.type != TokenType.IDENTIFIER) {
-      allowAdditionalTokens = false;
-    }
-    token = skipSimpleIdentifier(token);
-    if (token == null) {
-      return false;
-    }
-    TokenType type = token.type;
-    // Usual cases in valid code:
-    //     String v = '';
-    //     String v, v2;
-    //     String v;
-    //     for (String item in items) {}
-    if (type == TokenType.EQ ||
-        type == TokenType.COMMA ||
-        type == TokenType.SEMICOLON ||
-        token.keyword == Keyword.IN) {
-      return true;
-    }
-    // It is OK to parse as a variable declaration in these cases:
-    //     String v }
-    //     String v if (true) print('OK');
-    //     String v { print(42); }
-    // ...but not in these cases:
-    //     get getterName {
-    //     String get getterName
-    if (allowAdditionalTokens) {
-      if (type == TokenType.CLOSE_CURLY_BRACKET ||
-          type.isKeyword ||
-          type == TokenType.IDENTIFIER ||
-          type == TokenType.OPEN_CURLY_BRACKET) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Return `true` if the current token appears to be the beginning of a switch
-  /// member.
-  bool isSwitchMember() {
-    Token token = _currentToken;
-    while (_tokenMatches(token, TokenType.IDENTIFIER) &&
-        _tokenMatches(token.next, TokenType.COLON)) {
-      token = token.next.next;
-    }
-    Keyword keyword = token.keyword;
-    return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
-  }
-
-  /// Parse an additive expression. Return the additive expression that was
-  /// parsed.
-  ///
-  ///     additiveExpression ::=
-  ///         multiplicativeExpression (additiveOperator multiplicativeExpression)*
-  ///       | 'super' (additiveOperator multiplicativeExpression)+
-  Expression parseAdditiveExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isAdditiveOperator) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseMultiplicativeExpression();
-    }
-    while (_currentToken.type.isAdditiveOperator) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseMultiplicativeExpression());
-    }
-    return expression;
-  }
-
-  /// Parse an annotation. Return the annotation that was parsed.
-  ///
-  /// This method assumes that the current token matches [TokenType.AT].
-  ///
-  ///     annotation ::=
-  ///         '@' qualified ('.' identifier)? arguments?
-  Annotation parseAnnotation() {
-    Token atSign = getAndAdvance();
-    Identifier name = parsePrefixedIdentifier();
-    Token period;
-    SimpleIdentifier constructorName;
-    if (_matches(TokenType.PERIOD)) {
-      period = getAndAdvance();
-      constructorName = parseSimpleIdentifier();
-    }
-    ArgumentList arguments;
-    if (_matches(TokenType.OPEN_PAREN)) {
-      arguments = parseArgumentList();
-    }
-    return astFactory.annotation(
-        atSign, name, period, constructorName, arguments);
-  }
-
-  /// Parse an argument. Return the argument that was parsed.
-  ///
-  ///     argument ::=
-  ///         namedArgument
-  ///       | expression
-  ///
-  ///     namedArgument ::=
-  ///         label expression
   Expression parseArgument() {
-    // TODO(brianwilkerson) Consider returning a wrapper indicating whether the
-    // expression is a named expression in order to remove the 'is' check in
-    // 'parseArgumentList'.
-    //
-    // Both namedArgument and expression can start with an identifier, but only
-    // namedArgument can have an identifier followed by a colon.
-    //
-    if (_matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
-      return astFactory.namedExpression(parseLabel(), parseExpression2());
-    } else {
-      return parseExpression2();
-    }
+    currentToken = SimpleToken(TokenType.OPEN_PAREN, 0)..setNext(currentToken);
+    appendToken(currentToken, SimpleToken(TokenType.CLOSE_PAREN, 0));
+    currentToken = fastaParser
+        .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    var invocation = astBuilder.pop() as MethodInvocation;
+    return invocation.argumentList.arguments[0];
   }
 
-  /// Parse a list of arguments. Return the argument list that was parsed.
-  ///
-  /// This method assumes that the current token matches [TokenType.OPEN_PAREN].
-  ///
-  ///     arguments ::=
-  ///         '(' argumentList? ')'
-  ///
-  ///     argumentList ::=
-  ///         namedArgument (',' namedArgument)*
-  ///       | expressionList (',' namedArgument)*
-  ArgumentList parseArgumentList() {
-    Token leftParenthesis = getAndAdvance();
-    if (_matches(TokenType.CLOSE_PAREN)) {
-      return astFactory.argumentList(leftParenthesis, null, getAndAdvance());
-    }
+  Expression parseAssignableExpression(bool primaryAllowed) =>
+      parseExpression2();
 
-    /// Return `true` if the parser appears to be at the beginning of an
-    /// argument even though there was no comma. This is a special case of the
-    /// more general recovery technique described below.
-    bool isLikelyMissingComma() {
-      if (_matchesIdentifier() &&
-          _tokenMatches(_currentToken.next, TokenType.COLON) &&
-          leftParenthesis is BeginToken &&
-          leftParenthesis.endToken != null) {
-        _reportErrorForToken(
-            ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, [',']);
-        return true;
-      }
-      return false;
-    }
+  Expression parseBitwiseAndExpression() => parseExpression2();
 
-    //
-    // Even though unnamed arguments must all appear before any named arguments,
-    // we allow them to appear in any order so that we can recover faster.
-    //
-    bool wasInInitializer = _inInitializer;
-    _inInitializer = false;
-    try {
-      Token previousStartOfArgument = _currentToken;
-      Expression argument = parseArgument();
-      List<Expression> arguments = <Expression>[argument];
-      bool foundNamedArgument = argument is NamedExpression;
-      bool generatedError = false;
-      while (_optional(TokenType.COMMA) ||
-          (isLikelyMissingComma() &&
-              previousStartOfArgument != _currentToken)) {
-        if (_matches(TokenType.CLOSE_PAREN)) {
-          break;
-        }
-        previousStartOfArgument = _currentToken;
-        argument = parseArgument();
-        arguments.add(argument);
-        if (argument is NamedExpression) {
-          foundNamedArgument = true;
-        } else if (foundNamedArgument) {
-          if (!generatedError) {
-            if (!argument.isSynthetic) {
-              // Report the error, once, but allow the arguments to be in any
-              // order in the AST.
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT);
-              generatedError = true;
-            }
-          }
-        }
-      }
-      // Recovery: If the next token is not a right parenthesis, look at the
-      // left parenthesis to see whether there is a matching right parenthesis.
-      // If there is, then we're more likely missing a comma and should go back
-      // to parsing arguments.
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      return astFactory.argumentList(
-          leftParenthesis, arguments, rightParenthesis);
-    } finally {
-      _inInitializer = wasInInitializer;
-    }
-  }
+  Expression parseBitwiseOrExpression() => parseExpression2();
 
-  /// Parse an assert statement. Return the assert statement.
-  ///
-  /// This method assumes that the current token matches `Keyword.ASSERT`.
-  ///
-  ///     assertStatement ::=
-  ///         'assert' '(' expression [',' expression] ')' ';'
-  AssertStatement parseAssertStatement() {
-    Token keyword = getAndAdvance();
-    Token leftParen = _expect(TokenType.OPEN_PAREN);
-    Expression expression = parseExpression2();
-    Token comma;
-    Expression message;
-    if (_matches(TokenType.COMMA)) {
-      comma = getAndAdvance();
-      if (_matches(TokenType.CLOSE_PAREN)) {
-        comma;
-      } else {
-        message = parseExpression2();
-        if (_matches(TokenType.COMMA)) {
-          getAndAdvance();
-        }
-      }
-    }
-    Token rightParen = _expect(TokenType.CLOSE_PAREN);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    // TODO(brianwilkerson) We should capture the trailing comma in the AST, but
-    // that would be a breaking change, so we drop it for now.
-    return astFactory.assertStatement(
-        keyword, leftParen, expression, comma, message, rightParen, semicolon);
-  }
+  Expression parseBitwiseXorExpression() => parseExpression2();
 
-  /// Parse an assignable expression. The [primaryAllowed] is `true` if the
-  /// expression is allowed to be a primary without any assignable selector.
-  /// Return the assignable expression that was parsed.
-  ///
-  ///     assignableExpression ::=
-  ///         primary (arguments* assignableSelector)+
-  ///       | 'super' unconditionalAssignableSelector
-  ///       | identifier
-  Expression parseAssignableExpression(bool primaryAllowed) {
-    //
-    // A primary expression can start with an identifier. We resolve the
-    // ambiguity by determining whether the primary consists of anything other
-    // than an identifier and/or is followed by an assignableSelector.
-    //
-    Expression expression = parsePrimaryExpression();
-    bool isOptional =
-        primaryAllowed || _isValidAssignableExpression(expression);
-    while (true) {
-      while (_isLikelyArgumentList()) {
-        TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-        ArgumentList argumentList = parseArgumentList();
-        Expression currentExpression = expression;
-        if (currentExpression is SimpleIdentifier) {
-          expression = astFactory.methodInvocation(
-              null, null, currentExpression, typeArguments, argumentList);
-        } else if (currentExpression is PrefixedIdentifier) {
-          expression = astFactory.methodInvocation(
-              currentExpression.prefix,
-              currentExpression.period,
-              currentExpression.identifier,
-              typeArguments,
-              argumentList);
-        } else if (currentExpression is PropertyAccess) {
-          expression = astFactory.methodInvocation(
-              currentExpression.target,
-              currentExpression.operator,
-              currentExpression.propertyName,
-              typeArguments,
-              argumentList);
-        } else {
-          expression = astFactory.functionExpressionInvocation(
-              expression, typeArguments, argumentList);
-        }
-        if (!primaryAllowed) {
-          isOptional = false;
-        }
-      }
-      Expression selectorExpression = parseAssignableSelector(
-          expression, isOptional || (expression is PrefixedIdentifier));
-      if (identical(selectorExpression, expression)) {
-        return expression;
-      }
-      expression = selectorExpression;
-      isOptional = true;
-    }
-  }
-
-  /// Parse an assignable selector. The [prefix] is the expression preceding the
-  /// selector. The [optional] is `true` if the selector is optional. Return the
-  /// assignable selector that was parsed, or the original prefix if there was
-  /// no assignable selector.  If [allowConditional] is false, then the '?.'
-  /// operator will still be parsed, but a parse error will be generated.
-  ///
-  ///     unconditionalAssignableSelector ::=
-  ///         '[' expression ']'
-  ///       | '.' identifier
-  ///
-  ///     assignableSelector ::=
-  ///         unconditionalAssignableSelector
-  ///       | '?.' identifier
-  Expression parseAssignableSelector(Expression prefix, bool optional,
-      {bool allowConditional = true}) {
-    TokenType type = _currentToken.type;
-    if (type == TokenType.OPEN_SQUARE_BRACKET) {
-      Token leftBracket = getAndAdvance();
-      bool wasInInitializer = _inInitializer;
-      _inInitializer = false;
-      try {
-        Expression index = parseExpression2();
-        Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
-        return astFactory.indexExpressionForTarget2(
-            target: prefix,
-            leftBracket: leftBracket,
-            index: index,
-            rightBracket: rightBracket);
-      } finally {
-        _inInitializer = wasInInitializer;
-      }
-    } else {
-      bool isQuestionPeriod = type == TokenType.QUESTION_PERIOD;
-      if (type == TokenType.PERIOD || isQuestionPeriod) {
-        if (isQuestionPeriod && !allowConditional) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
-              [_currentToken.lexeme]);
-        }
-        Token operator = getAndAdvance();
-        return astFactory.propertyAccess(
-            prefix, operator, parseSimpleIdentifier());
-      } else if (type == TokenType.INDEX) {
-        _splitIndex();
-        Token leftBracket = getAndAdvance();
-        Expression index = parseSimpleIdentifier();
-        Token rightBracket = getAndAdvance();
-        return astFactory.indexExpressionForTarget2(
-            target: prefix,
-            leftBracket: leftBracket,
-            index: index,
-            rightBracket: rightBracket);
-      } else {
-        if (!optional) {
-          // Report the missing selector.
-          _reportErrorForCurrentToken(
-              ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR);
-        }
-        return prefix;
-      }
-    }
-  }
-
-  /// Parse a await expression. Return the await expression that was parsed.
-  ///
-  /// This method assumes that the current token matches `_AWAIT`.
-  ///
-  ///     awaitExpression ::=
-  ///         'await' unaryExpression
-  AwaitExpression parseAwaitExpression() {
-    Token awaitToken = getAndAdvance();
-    Expression expression = parseUnaryExpression();
-    return astFactory.awaitExpression(awaitToken, expression);
-  }
-
-  /// Parse a bitwise and expression. Return the bitwise and expression that was
-  /// parsed.
-  ///
-  ///     bitwiseAndExpression ::=
-  ///         shiftExpression ('&' shiftExpression)*
-  ///       | 'super' ('&' shiftExpression)+
-  Expression parseBitwiseAndExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type == TokenType.AMPERSAND) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseShiftExpression();
-    }
-    while (_currentToken.type == TokenType.AMPERSAND) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseShiftExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a bitwise or expression. Return the bitwise or expression that was
-  /// parsed.
-  ///
-  ///     bitwiseOrExpression ::=
-  ///         bitwiseXorExpression ('|' bitwiseXorExpression)*
-  ///       | 'super' ('|' bitwiseXorExpression)+
-  Expression parseBitwiseOrExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type == TokenType.BAR) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseBitwiseXorExpression();
-    }
-    while (_currentToken.type == TokenType.BAR) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseBitwiseXorExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a bitwise exclusive-or expression. Return the bitwise exclusive-or
-  /// expression that was parsed.
-  ///
-  ///     bitwiseXorExpression ::=
-  ///         bitwiseAndExpression ('^' bitwiseAndExpression)*
-  ///       | 'super' ('^' bitwiseAndExpression)+
-  Expression parseBitwiseXorExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type == TokenType.CARET) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseBitwiseAndExpression();
-    }
-    while (_currentToken.type == TokenType.CARET) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseBitwiseAndExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a block. Return the block that was parsed.
-  ///
-  /// This method assumes that the current token matches
-  /// [TokenType.OPEN_CURLY_BRACKET].
-  ///
-  ///     block ::=
-  ///         '{' statements '}'
-  Block parseBlock() {
-    bool isEndOfBlock() {
-      TokenType type = _currentToken.type;
-      return type == TokenType.EOF || type == TokenType.CLOSE_CURLY_BRACKET;
-    }
-
-    Token leftBracket = getAndAdvance();
-    List<Statement> statements = <Statement>[];
-    Token statementStart = _currentToken;
-    while (!isEndOfBlock()) {
-      Statement statement = parseStatement2();
-      if (identical(_currentToken, statementStart)) {
-        // Ensure that we are making progress and report an error if we're not.
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      } else if (statement != null) {
-        statements.add(statement);
-      }
-      statementStart = _currentToken;
-    }
-    // Recovery: If the next token is not a right curly bracket, look at the
-    // left curly bracket to see whether there is a matching right bracket. If
-    // there is, then we're more likely missing a semi-colon and should go back
-    // to parsing statements.
-    Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-    return astFactory.block(leftBracket, statements, rightBracket);
-  }
-
-  /// Parse a break statement. Return the break statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.BREAK`.
-  ///
-  ///     breakStatement ::=
-  ///         'break' identifier? ';'
-  Statement parseBreakStatement() {
-    Token breakKeyword = getAndAdvance();
-    SimpleIdentifier label;
-    if (_matchesIdentifier()) {
-      label = _parseSimpleIdentifierUnchecked();
-    }
-    if (!_inLoop && !_inSwitch && label == null) {
-      _reportErrorForToken(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, breakKeyword);
-    }
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.breakStatement(breakKeyword, label, semicolon);
-  }
-
-  /// Parse a cascade section. Return the expression representing the cascaded
-  /// method invocation.
-  ///
-  /// This method assumes that the current token matches
-  /// `TokenType.PERIOD_PERIOD`.
-  ///
-  ///     cascadeSection ::=
-  ///         '..' (cascadeSelector typeArguments? arguments*)
-  ///         (assignableSelector typeArguments? arguments*)* cascadeAssignment?
-  ///
-  ///     cascadeSelector ::=
-  ///         '[' expression ']'
-  ///       | identifier
-  ///
-  ///     cascadeAssignment ::=
-  ///         assignmentOperator expressionWithoutCascade
-  Expression parseCascadeSection() {
-    Token period = getAndAdvance();
-    Expression expression;
-    SimpleIdentifier functionName;
-    if (_matchesIdentifier()) {
-      functionName = _parseSimpleIdentifierUnchecked();
-    } else if (_currentToken.type == TokenType.OPEN_SQUARE_BRACKET) {
-      Token leftBracket = getAndAdvance();
-      bool wasInInitializer = _inInitializer;
-      _inInitializer = false;
-      try {
-        Expression index = parseExpression2();
-        Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
-        expression = astFactory.indexExpressionForCascade2(
-            period: period,
-            leftBracket: leftBracket,
-            index: index,
-            rightBracket: rightBracket);
-        period;
-      } finally {
-        _inInitializer = wasInInitializer;
-      }
-    } else {
-      _reportErrorForToken(ParserErrorCode.MISSING_IDENTIFIER, _currentToken,
-          [_currentToken.lexeme]);
-      functionName = createSyntheticIdentifier();
-    }
-    assert((expression == null && functionName != null) ||
-        (expression != null && functionName == null));
-    if (_isLikelyArgumentList()) {
-      do {
-        TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-        if (functionName != null) {
-          expression = astFactory.methodInvocation(expression, period,
-              functionName, typeArguments, parseArgumentList());
-          period;
-          functionName;
-        } else if (expression == null) {
-          // It should not be possible to get here.
-          expression = astFactory.methodInvocation(expression, period,
-              createSyntheticIdentifier(), typeArguments, parseArgumentList());
-        } else {
-          expression = astFactory.functionExpressionInvocation(
-              expression, typeArguments, parseArgumentList());
-        }
-      } while (_isLikelyArgumentList());
-    } else if (functionName != null) {
-      expression = astFactory.propertyAccess(expression, period, functionName);
-      period;
-    }
-    assert(expression != null);
-    bool progress = true;
-    while (progress) {
-      progress = false;
-      Expression selector = parseAssignableSelector(expression, true);
-      if (!identical(selector, expression)) {
-        expression = selector;
-        progress = true;
-        while (_isLikelyArgumentList()) {
-          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-          Expression currentExpression = expression;
-          if (currentExpression is PropertyAccess) {
-            expression = astFactory.methodInvocation(
-                currentExpression.target,
-                currentExpression.operator,
-                currentExpression.propertyName,
-                typeArguments,
-                parseArgumentList());
-          } else {
-            expression = astFactory.functionExpressionInvocation(
-                expression, typeArguments, parseArgumentList());
-          }
-        }
-      }
-    }
-    if (_currentToken.type.isAssignmentOperator) {
-      Token operator = getAndAdvance();
-      _ensureAssignable(expression);
-      expression = astFactory.assignmentExpression(
-          expression, operator, parseExpressionWithoutCascade());
-    }
-    return expression;
-  }
-
-  /// Parse a class declaration. The [commentAndMetadata] is the metadata to be
-  /// associated with the member. The [abstractKeyword] is the token for the
-  /// keyword 'abstract', or `null` if the keyword was not given. Return the
-  /// class declaration that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.CLASS`.
-  ///
-  ///     classDeclaration ::=
-  ///         metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}' |
-  ///         metadata 'abstract'? 'class' mixinApplicationClass
-  CompilationUnitMember parseClassDeclaration(
-      CommentAndMetadata commentAndMetadata, Token abstractKeyword) {
-    //
-    // Parse the name and type parameters.
-    //
-    Token keyword = getAndAdvance();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    String className = name.name;
-    TypeParameterList typeParameters;
-    TokenType type = _currentToken.type;
-    if (type == TokenType.LT) {
-      typeParameters = parseTypeParameterList();
-      type = _currentToken.type;
-    }
-    //
-    // Check to see whether this might be a class type alias rather than a class
-    // declaration.
-    //
-    if (type == TokenType.EQ) {
-      return _parseClassTypeAliasAfterName(
-          commentAndMetadata, abstractKeyword, keyword, name, typeParameters);
-    }
-    //
-    // Parse the clauses. The parser accepts clauses in any order, but will
-    // generate errors if they are not in the order required by the
-    // specification.
-    //
-    ExtendsClause extendsClause;
-    WithClause withClause;
-    ImplementsClause implementsClause;
-    bool foundClause = true;
-    while (foundClause) {
-      Keyword keyword = _currentToken.keyword;
-      if (keyword == Keyword.EXTENDS) {
-        if (extendsClause == null) {
-          extendsClause = parseExtendsClause();
-          if (withClause != null) {
-            _reportErrorForToken(
-                ParserErrorCode.WITH_BEFORE_EXTENDS, withClause.withKeyword);
-          } else if (implementsClause != null) {
-            _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS,
-                implementsClause.implementsKeyword);
-          }
-        } else {
-          _reportErrorForToken(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES,
-              extendsClause.extendsKeyword);
-          parseExtendsClause();
-        }
-      } else if (keyword == Keyword.WITH) {
-        if (withClause == null) {
-          withClause = parseWithClause();
-          if (implementsClause != null) {
-            _reportErrorForToken(ParserErrorCode.IMPLEMENTS_BEFORE_WITH,
-                implementsClause.implementsKeyword);
-          }
-        } else {
-          _reportErrorForToken(
-              ParserErrorCode.MULTIPLE_WITH_CLAUSES, withClause.withKeyword);
-          parseWithClause();
-          // TODO(brianwilkerson) Should we merge the list of applied mixins
-          // into a single list?
-        }
-      } else if (keyword == Keyword.IMPLEMENTS) {
-        if (implementsClause == null) {
-          implementsClause = parseImplementsClause();
-        } else {
-          _reportErrorForToken(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES,
-              implementsClause.implementsKeyword);
-          parseImplementsClause();
-          // TODO(brianwilkerson) Should we merge the list of implemented
-          // classes into a single list?
-        }
-      } else {
-        foundClause = false;
-      }
-    }
-    //
-    // Look for and skip over the extra-lingual 'native' specification.
-    //
-    NativeClause nativeClause;
-    if (_matchesKeyword(Keyword.NATIVE) &&
-        _tokenMatches(_peek(), TokenType.STRING)) {
-      nativeClause = _parseNativeClause();
-    }
-    //
-    // Parse the body of the class.
-    //
-    Token leftBracket;
-    List<ClassMember> members;
-    Token rightBracket;
-    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      leftBracket = getAndAdvance();
-      members = _parseClassMembers(className, _getEndToken(leftBracket));
-      rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-    } else {
-      // Recovery: Check for an unmatched closing curly bracket and parse
-      // members until it is reached.
-      leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
-      rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
-      _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_BODY);
-    }
-    ClassDeclaration classDeclaration = astFactory.classDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        abstractKeyword,
-        keyword,
-        name,
-        typeParameters,
-        extendsClause,
-        withClause,
-        implementsClause,
-        leftBracket,
-        members,
-        rightBracket);
-    classDeclaration.nativeClause = nativeClause;
-    return classDeclaration;
-  }
-
-  /// Parse a class member. The [className] is the name of the class containing
-  /// the member being parsed. Return the class member that was parsed, or
-  /// `null` if what was found was not a valid class member.
-  ///
-  ///     classMemberDefinition ::=
-  ///         declaration ';'
-  ///       | methodSignature functionBody
-  ClassMember parseClassMember(String className) {
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    Modifiers modifiers = parseModifiers();
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.VOID ||
-        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      TypeAnnotation returnType;
-      if (keyword == Keyword.VOID) {
-        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
-          returnType = parseTypeAnnotation(false);
-        } else {
-          returnType = astFactory.typeName(
-              astFactory.simpleIdentifier(getAndAdvance()), null);
-        }
-      } else {
-        returnType = parseTypeAnnotation(false);
-      }
-      keyword = _currentToken.keyword;
-      Token next = _peek();
-      bool isFollowedByIdentifier = _tokenMatchesIdentifier(next);
-      if (keyword == Keyword.GET && isFollowedByIdentifier) {
-        _validateModifiersForGetterOrSetterOrMethod(modifiers);
-        return parseGetter(commentAndMetadata, modifiers.externalKeyword,
-            modifiers.staticKeyword, returnType);
-      } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
-        _validateModifiersForGetterOrSetterOrMethod(modifiers);
-        return parseSetter(commentAndMetadata, modifiers.externalKeyword,
-            modifiers.staticKeyword, returnType);
-      } else if (keyword == Keyword.OPERATOR &&
-          (_isOperator(next) || next.type == TokenType.EQ_EQ_EQ)) {
-        _validateModifiersForOperator(modifiers);
-        return _parseOperatorAfterKeyword(commentAndMetadata,
-            modifiers.externalKeyword, returnType, getAndAdvance());
-      } else if (_matchesIdentifier() &&
-          _peek().matchesAny(const <TokenType>[
-            TokenType.OPEN_PAREN,
-            TokenType.OPEN_CURLY_BRACKET,
-            TokenType.FUNCTION,
-            TokenType.LT
-          ])) {
-        _validateModifiersForGetterOrSetterOrMethod(modifiers);
-        return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
-            modifiers.externalKeyword, modifiers.staticKeyword, returnType);
-      } else if (_matchesIdentifier() &&
-          _peek().matchesAny(const <TokenType>[
-            TokenType.EQ,
-            TokenType.COMMA,
-            TokenType.SEMICOLON
-          ])) {
-        return parseInitializedIdentifierList(
-            commentAndMetadata,
-            modifiers.staticKeyword,
-            modifiers.covariantKeyword,
-            _validateModifiersForField(modifiers),
-            returnType);
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        if (_isOperator(_currentToken)) {
-          //
-          // We appear to have found an operator declaration without the
-          // 'operator' keyword.
-          //
-          _validateModifiersForOperator(modifiers);
-          return parseOperator(
-              commentAndMetadata, modifiers.externalKeyword, returnType);
-        }
-        _reportErrorForToken(
-            ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
-        return null;
-      }
-    }
-    Token next = _peek();
-    bool isFollowedByIdentifier = _tokenMatchesIdentifier(next);
-    if (keyword == Keyword.GET && isFollowedByIdentifier) {
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, null);
-    } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      return parseSetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, null);
-    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-      _validateModifiersForOperator(modifiers);
-      return _parseOperatorAfterKeyword(
-          commentAndMetadata, modifiers.externalKeyword, null, getAndAdvance());
-    } else if (!_matchesIdentifier()) {
-      //
-      // Recover from an error.
-      //
-      if (_matchesKeyword(Keyword.CLASS)) {
-        _reportErrorForCurrentToken(ParserErrorCode.CLASS_IN_CLASS);
-        // TODO(brianwilkerson) We don't currently have any way to capture the
-        // class that was parsed.
-        parseClassDeclaration(commentAndMetadata, null);
-        return null;
-      } else if (_matchesKeyword(Keyword.ABSTRACT) &&
-          _tokenMatchesKeyword(_peek(), Keyword.CLASS)) {
-        _reportErrorForToken(ParserErrorCode.CLASS_IN_CLASS, _peek());
-        // TODO(brianwilkerson) We don't currently have any way to capture the
-        // class that was parsed.
-        parseClassDeclaration(commentAndMetadata, getAndAdvance());
-        return null;
-      } else if (_matchesKeyword(Keyword.ENUM)) {
-        _reportErrorForToken(ParserErrorCode.ENUM_IN_CLASS, _peek());
-        // TODO(brianwilkerson) We don't currently have any way to capture the
-        // enum that was parsed.
-        parseEnumDeclaration(commentAndMetadata);
-        return null;
-      } else if (_isOperator(_currentToken)) {
-        //
-        // We appear to have found an operator declaration without the
-        // 'operator' keyword.
-        //
-        _validateModifiersForOperator(modifiers);
-        return parseOperator(
-            commentAndMetadata, modifiers.externalKeyword, null);
-      }
-      Token keyword = modifiers.varKeyword ??
-          modifiers.finalKeyword ??
-          modifiers.constKeyword;
-      if (keyword != null) {
-        //
-        // We appear to have found an incomplete field declaration.
-        //
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-        VariableDeclaration variable = astFactory.variableDeclaration(
-            createSyntheticIdentifier(), null, null);
-        List<VariableDeclaration> variables = <VariableDeclaration>[variable];
-        return astFactory.fieldDeclaration2(
-            comment: commentAndMetadata.comment,
-            metadata: commentAndMetadata.metadata,
-            covariantKeyword: modifiers.covariantKeyword,
-            fieldList: astFactory.variableDeclarationList(
-                null, null, keyword, null, variables),
-            semicolon: _expect(TokenType.SEMICOLON));
-      }
-      _reportErrorForToken(
-          ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
-      if (commentAndMetadata.comment != null ||
-          commentAndMetadata.hasMetadata) {
-        //
-        // We appear to have found an incomplete declaration at the end of the
-        // class. At this point it consists of a metadata, which we don't want
-        // to loose, so we'll treat it as a method declaration with a missing
-        // name, parameters and empty body.
-        //
-        return astFactory.methodDeclaration(
-            commentAndMetadata.comment,
-            commentAndMetadata.metadata,
-            null,
-            null,
-            null,
-            null,
-            null,
-            createSyntheticIdentifier(isDeclaration: true),
-            null,
-            astFactory.formalParameterList(
-                _createSyntheticToken(TokenType.OPEN_PAREN),
-                <FormalParameter>[],
-                null,
-                null,
-                _createSyntheticToken(TokenType.CLOSE_PAREN)),
-            astFactory
-                .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON)));
-      }
-      return null;
-    } else if (_tokenMatches(next, TokenType.PERIOD) &&
-        _tokenMatchesIdentifierOrKeyword(_peekAt(2)) &&
-        _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
-      if (!_tokenMatchesIdentifier(_peekAt(2))) {
-        _reportErrorForToken(ParserErrorCode.INVALID_CONSTRUCTOR_NAME,
-            _peekAt(2), [_peekAt(2).lexeme]);
-      }
-      return _parseConstructor(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          _validateModifiersForConstructor(modifiers),
-          modifiers.factoryKeyword,
-          parseSimpleIdentifier(),
-          getAndAdvance(),
-          parseSimpleIdentifier(allowKeyword: true, isDeclaration: true),
-          parseFormalParameterList());
-    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
-      TypeName returnType;
-      SimpleIdentifier methodName = parseSimpleIdentifier(isDeclaration: true);
-      TypeParameterList typeParameters;
-      FormalParameterList parameters = parseFormalParameterList();
-      if (_matches(TokenType.COLON) ||
-          modifiers.factoryKeyword != null ||
-          methodName.name == className) {
-        return _parseConstructor(
-            commentAndMetadata,
-            modifiers.externalKeyword,
-            _validateModifiersForConstructor(modifiers),
-            modifiers.factoryKeyword,
-            astFactory.simpleIdentifier(methodName.token, isDeclaration: false),
-            null,
-            null,
-            parameters);
-      }
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      _validateFormalParameterList(parameters);
-      return _parseMethodDeclarationAfterParameters(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          modifiers.staticKeyword,
-          returnType,
-          methodName,
-          typeParameters,
-          parameters);
-    } else if (next.matchesAny(const <TokenType>[
-      TokenType.EQ,
-      TokenType.COMMA,
-      TokenType.SEMICOLON
-    ])) {
-      if (modifiers.constKeyword == null &&
-          modifiers.finalKeyword == null &&
-          modifiers.varKeyword == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
-      }
-      return parseInitializedIdentifierList(
-          commentAndMetadata,
-          modifiers.staticKeyword,
-          modifiers.covariantKeyword,
-          _validateModifiersForField(modifiers),
-          null);
-    } else if (keyword == Keyword.TYPEDEF) {
-      _reportErrorForCurrentToken(ParserErrorCode.TYPEDEF_IN_CLASS);
-      // TODO(brianwilkerson) We don't currently have any way to capture the
-      // function type alias that was parsed.
-      _parseFunctionTypeAlias(commentAndMetadata, getAndAdvance());
-      return null;
-    } else {
-      Token token = _skipTypeParameterList(_peek());
-      if (token != null && _tokenMatches(token, TokenType.OPEN_PAREN)) {
-        return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
-            modifiers.externalKeyword, modifiers.staticKeyword, null);
-      }
-    }
-    TypeAnnotation type = _parseTypeAnnotationAfterIdentifier();
-    keyword = _currentToken.keyword;
-    next = _peek();
-    isFollowedByIdentifier = _tokenMatchesIdentifier(next);
-    if (keyword == Keyword.GET && isFollowedByIdentifier) {
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, type);
-    } else if (keyword == Keyword.SET && isFollowedByIdentifier) {
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      return parseSetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, type);
-    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-      _validateModifiersForOperator(modifiers);
-      return _parseOperatorAfterKeyword(
-          commentAndMetadata, modifiers.externalKeyword, type, getAndAdvance());
-    } else if (!_matchesIdentifier()) {
-      if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-        //
-        // We appear to have found an incomplete declaration at the end of the
-        // class. At this point it consists of a type name, so we'll treat it as
-        // a field declaration with a missing field name and semicolon.
-        //
-        return parseInitializedIdentifierList(
-            commentAndMetadata,
-            modifiers.staticKeyword,
-            modifiers.covariantKeyword,
-            _validateModifiersForField(modifiers),
-            type);
-      }
-      if (_isOperator(_currentToken)) {
-        //
-        // We appear to have found an operator declaration without the
-        // 'operator' keyword.
-        //
-        _validateModifiersForOperator(modifiers);
-        return parseOperator(
-            commentAndMetadata, modifiers.externalKeyword, type);
-      }
-      //
-      // We appear to have found an incomplete declaration before another
-      // declaration. At this point it consists of a type name, so we'll treat
-      // it as a field declaration with a missing field name and semicolon.
-      //
-      _reportErrorForToken(
-          ParserErrorCode.EXPECTED_CLASS_MEMBER, _currentToken);
-      try {
-        _lockErrorListener();
-        return parseInitializedIdentifierList(
-            commentAndMetadata,
-            modifiers.staticKeyword,
-            modifiers.covariantKeyword,
-            _validateModifiersForField(modifiers),
-            type);
-      } finally {
-        _unlockErrorListener();
-      }
-    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
-      SimpleIdentifier methodName =
-          _parseSimpleIdentifierUnchecked(isDeclaration: true);
-      TypeParameterList typeParameters;
-      FormalParameterList parameters = parseFormalParameterList();
-      if (methodName.name == className) {
-        _reportErrorForNode(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, type);
-        return _parseConstructor(
-            commentAndMetadata,
-            modifiers.externalKeyword,
-            _validateModifiersForConstructor(modifiers),
-            modifiers.factoryKeyword,
-            astFactory.simpleIdentifier(methodName.token, isDeclaration: true),
-            null,
-            null,
-            parameters);
-      }
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      _validateFormalParameterList(parameters);
-      return _parseMethodDeclarationAfterParameters(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          modifiers.staticKeyword,
-          type,
-          methodName,
-          typeParameters,
-          parameters);
-    } else if (_tokenMatches(next, TokenType.LT)) {
-      return _parseMethodDeclarationAfterReturnType(commentAndMetadata,
-          modifiers.externalKeyword, modifiers.staticKeyword, type);
-    } else if (_tokenMatches(next, TokenType.OPEN_CURLY_BRACKET)) {
-      // We have found "TypeName identifier {", and are guessing that this is a
-      // getter without the keyword 'get'.
-      _validateModifiersForGetterOrSetterOrMethod(modifiers);
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_GET);
-      _currentToken = _injectToken(
-          SyntheticKeywordToken(Keyword.GET, _currentToken.offset));
-      return parseGetter(commentAndMetadata, modifiers.externalKeyword,
-          modifiers.staticKeyword, type);
-    }
-    return parseInitializedIdentifierList(
-        commentAndMetadata,
-        modifiers.staticKeyword,
-        modifiers.covariantKeyword,
-        _validateModifiersForField(modifiers),
-        type);
-  }
-
-  /// Parse a single combinator. Return the combinator that was parsed, or
-  /// `null` if no combinator is found.
-  ///
-  ///     combinator ::=
-  ///         'show' identifier (',' identifier)*
-  ///       | 'hide' identifier (',' identifier)*
-  Combinator parseCombinator() {
-    if (_matchesKeyword(Keyword.SHOW)) {
-      return astFactory.showCombinator(getAndAdvance(), parseIdentifierList());
-    } else if (_matchesKeyword(Keyword.HIDE)) {
-      return astFactory.hideCombinator(getAndAdvance(), parseIdentifierList());
-    }
-    return null;
-  }
-
-  /// Parse a list of combinators in a directive. Return the combinators that
-  /// were parsed, or `null` if there are no combinators.
-  ///
-  ///     combinator ::=
-  ///         'show' identifier (',' identifier)*
-  ///       | 'hide' identifier (',' identifier)*
-  List<Combinator> parseCombinators() {
-    List<Combinator> combinators;
-    while (true) {
-      Combinator combinator = parseCombinator();
-      if (combinator == null) {
-        break;
-      }
-      combinators ??= <Combinator>[];
-      combinators.add(combinator);
-    }
-    return combinators;
-  }
-
-  /// Parse the documentation comment and metadata preceding a declaration. This
-  /// method allows any number of documentation comments to occur before, after
-  /// or between the metadata, but only returns the last (right-most)
-  /// documentation comment that is found. Return the documentation comment and
-  /// metadata that were parsed.
-  ///
-  ///     metadata ::=
-  ///         annotation*
-  CommentAndMetadata parseCommentAndMetadata() {
-    // TODO(brianwilkerson) Consider making the creation of documentation
-    // comments be lazy.
-    List<DocumentationCommentToken> tokens = parseDocumentationCommentTokens();
-    List<Annotation> metadata;
-    while (_matches(TokenType.AT)) {
-      metadata ??= <Annotation>[];
-      metadata.add(parseAnnotation());
-      List<DocumentationCommentToken> optionalTokens =
-          parseDocumentationCommentTokens();
-      if (optionalTokens != null) {
-        tokens = optionalTokens;
-      }
-    }
-    return CommentAndMetadata(parseDocumentationComment(tokens), metadata);
-  }
-
-  /// Parse a comment reference from the source between square brackets. The
-  /// [referenceSource] is the source occurring between the square brackets
-  /// within a documentation comment. The [sourceOffset] is the offset of the
-  /// first character of the reference source. Return the comment reference that
-  /// was parsed, or `null` if no reference could be found.
-  ///
-  ///     commentReference ::=
-  ///         'new'? prefixedIdentifier
-  CommentReference parseCommentReference(
-      String referenceSource, int sourceOffset) {
-    // TODO(brianwilkerson) The errors are not getting the right offset/length
-    // and are being duplicated.
-    try {
-      BooleanErrorListener listener = BooleanErrorListener();
-      Scanner scanner = Scanner(
-          null, SubSequenceReader(referenceSource, sourceOffset), listener)
-        ..configureFeatures(
-          featureSetForOverriding: _featureSet,
-          featureSet: _featureSet,
-        );
-      scanner.setSourceStart(1, 1);
-      Token firstToken = scanner.tokenize();
-      if (listener.errorReported) {
-        return null;
-      }
-      if (firstToken.type == TokenType.EOF) {
-        Token syntheticToken =
-            SyntheticStringToken(TokenType.IDENTIFIER, "", sourceOffset);
-        syntheticToken.setNext(firstToken);
-        return astFactory.commentReference(
-            null, astFactory.simpleIdentifier(syntheticToken));
-      }
-      Token newKeyword;
-      if (_tokenMatchesKeyword(firstToken, Keyword.NEW)) {
-        newKeyword = firstToken;
-        firstToken = firstToken.next;
-      }
-      if (firstToken.isUserDefinableOperator) {
-        if (firstToken.next.type != TokenType.EOF) {
-          return null;
-        }
-        Identifier identifier = astFactory.simpleIdentifier(firstToken);
-        return astFactory.commentReference(null, identifier);
-      } else if (_tokenMatchesKeyword(firstToken, Keyword.OPERATOR)) {
-        Token secondToken = firstToken.next;
-        if (secondToken.isUserDefinableOperator) {
-          if (secondToken.next.type != TokenType.EOF) {
-            return null;
-          }
-          Identifier identifier = astFactory.simpleIdentifier(secondToken);
-          return astFactory.commentReference(null, identifier);
-        }
-        return null;
-      } else if (_tokenMatchesIdentifier(firstToken)) {
-        Token secondToken = firstToken.next;
-        Token thirdToken = secondToken.next;
-        Token nextToken;
-        Identifier identifier;
-        if (_tokenMatches(secondToken, TokenType.PERIOD)) {
-          if (thirdToken.isUserDefinableOperator) {
-            identifier = astFactory.prefixedIdentifier(
-                astFactory.simpleIdentifier(firstToken),
-                secondToken,
-                astFactory.simpleIdentifier(thirdToken));
-            nextToken = thirdToken.next;
-          } else if (_tokenMatchesKeyword(thirdToken, Keyword.OPERATOR)) {
-            Token fourthToken = thirdToken.next;
-            if (fourthToken.isUserDefinableOperator) {
-              identifier = astFactory.prefixedIdentifier(
-                  astFactory.simpleIdentifier(firstToken),
-                  secondToken,
-                  astFactory.simpleIdentifier(fourthToken));
-              nextToken = fourthToken.next;
-            } else {
-              return null;
-            }
-          } else if (_tokenMatchesIdentifier(thirdToken)) {
-            identifier = astFactory.prefixedIdentifier(
-                astFactory.simpleIdentifier(firstToken),
-                secondToken,
-                astFactory.simpleIdentifier(thirdToken));
-            nextToken = thirdToken.next;
-          }
-        } else {
-          identifier = astFactory.simpleIdentifier(firstToken);
-          nextToken = firstToken.next;
-        }
-        if (nextToken.type != TokenType.EOF) {
-          return null;
-        }
-        return astFactory.commentReference(newKeyword, identifier);
-      } else {
-        Keyword keyword = firstToken.keyword;
-        if (keyword == Keyword.THIS ||
-            keyword == Keyword.NULL ||
-            keyword == Keyword.TRUE ||
-            keyword == Keyword.FALSE) {
-          // TODO(brianwilkerson) If we want to support this we will need to
-          // extend the definition of CommentReference to take an expression
-          // rather than an identifier. For now we just ignore it to reduce the
-          // number of errors produced, but that's probably not a valid long term
-          // approach.
-          return null;
-        }
-      }
-    } catch (exception) {
-      // Ignored because we assume that it wasn't a real comment reference.
-    }
-    return null;
-  }
-
-  /// Parse all of the comment references occurring in the given array of
-  /// documentation comments. The [tokens] are the comment tokens representing
-  /// the documentation comments to be parsed. Return the comment references
-  /// that were parsed.
-  ///
-  ///     commentReference ::=
-  ///         '[' 'new'? qualified ']' libraryReference?
-  ///
-  ///     libraryReference ::=
-  ///          '(' stringLiteral ')'
-  List<CommentReference> parseCommentReferences(
-      List<DocumentationCommentToken> tokens) {
-    List<CommentReference> references = <CommentReference>[];
-    bool isInGitHubCodeBlock = false;
-    for (DocumentationCommentToken token in tokens) {
-      String comment = token.lexeme;
-      // Skip GitHub code blocks.
-      // https://help.github.com/articles/creating-and-highlighting-code-blocks/
-      if (tokens.length != 1) {
-        if (comment.contains('```')) {
-          isInGitHubCodeBlock = !isInGitHubCodeBlock;
-        }
-        if (isInGitHubCodeBlock) {
-          continue;
-        }
-      }
-      // Remove GitHub include code.
-      comment = _removeGitHubInlineCode(comment);
-      // Find references.
-      int length = comment.length;
-      List<List<int>> codeBlockRanges = _getCodeBlockRanges(comment);
-      int leftIndex = comment.indexOf('[');
-      while (leftIndex >= 0 && leftIndex + 1 < length) {
-        List<int> range = _findRange(codeBlockRanges, leftIndex);
-        if (range == null) {
-          int nameOffset = token.offset + leftIndex + 1;
-          int rightIndex = comment.indexOf(']', leftIndex);
-          if (rightIndex >= 0) {
-            int firstChar = comment.codeUnitAt(leftIndex + 1);
-            if (firstChar != 0x27 && firstChar != 0x22) {
-              if (_isLinkText(comment, rightIndex)) {
-                // TODO(brianwilkerson) Handle the case where there's a library
-                // URI in the link text.
-              } else {
-                CommentReference reference = parseCommentReference(
-                    comment.substring(leftIndex + 1, rightIndex), nameOffset);
-                if (reference != null) {
-                  references.add(reference);
-                }
-              }
-            }
-          } else {
-            // terminating ']' is not typed yet
-            int charAfterLeft = comment.codeUnitAt(leftIndex + 1);
-            Token nameToken;
-            if (Character.isLetterOrDigit(charAfterLeft)) {
-              int nameEnd = StringUtilities.indexOfFirstNotLetterDigit(
-                  comment, leftIndex + 1);
-              String name = comment.substring(leftIndex + 1, nameEnd);
-              nameToken = StringToken(TokenType.IDENTIFIER, name, nameOffset);
-            } else {
-              nameToken =
-                  SyntheticStringToken(TokenType.IDENTIFIER, '', nameOffset);
-            }
-            nameToken.setNext(Token.eof(nameToken.end));
-            references.add(astFactory.commentReference(
-                null, astFactory.simpleIdentifier(nameToken)));
-            // next character
-            rightIndex = leftIndex + 1;
-          }
-          leftIndex = comment.indexOf('[', rightIndex);
-        } else {
-          leftIndex = comment.indexOf('[', range[1]);
-        }
-      }
-    }
-    return references;
-  }
-
-  /// Parse a compilation unit, starting with the given [token]. Return the
-  /// compilation unit that was parsed.
   CompilationUnit parseCompilationUnit(Token token) {
-    _currentToken = token;
+    currentToken = token;
     return parseCompilationUnit2();
   }
 
-  /// Parse a compilation unit. Return the compilation unit that was parsed.
-  ///
-  /// Specified:
-  ///
-  ///     compilationUnit ::=
-  ///         scriptTag? directive* topLevelDeclaration*
-  ///
-  /// Actual:
-  ///
-  ///     compilationUnit ::=
-  ///         scriptTag? topLevelElement*
-  ///
-  ///     topLevelElement ::=
-  ///         directive
-  ///       | topLevelDeclaration
   CompilationUnit parseCompilationUnit2() {
-    Token firstToken = _currentToken;
-    ScriptTag scriptTag;
-    if (_matches(TokenType.SCRIPT_TAG)) {
-      scriptTag = astFactory.scriptTag(getAndAdvance());
-    }
-    //
-    // Even though all directives must appear before declarations and must occur
-    // in a given order, we allow directives and declarations to occur in any
-    // order so that we can recover better.
-    //
-    bool libraryDirectiveFound = false;
-    bool partOfDirectiveFound = false;
-    bool partDirectiveFound = false;
-    bool directiveFoundAfterDeclaration = false;
-    List<Directive> directives = <Directive>[];
-    List<CompilationUnitMember> declarations = <CompilationUnitMember>[];
-    Token memberStart = _currentToken;
-    TokenType type = _currentToken.type;
-    while (type != TokenType.EOF) {
-      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-      Keyword keyword = _currentToken.keyword;
-      TokenType nextType = _currentToken.next.type;
-      if ((keyword == Keyword.IMPORT ||
-              keyword == Keyword.EXPORT ||
-              keyword == Keyword.LIBRARY ||
-              keyword == Keyword.PART) &&
-          nextType != TokenType.PERIOD &&
-          nextType != TokenType.LT &&
-          nextType != TokenType.OPEN_PAREN) {
-        Directive parseDirective() {
-          if (keyword == Keyword.IMPORT) {
-            if (partDirectiveFound) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE);
-            }
-            return parseImportDirective(commentAndMetadata);
-          } else if (keyword == Keyword.EXPORT) {
-            if (partDirectiveFound) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE);
-            }
-            return parseExportDirective(commentAndMetadata);
-          } else if (keyword == Keyword.LIBRARY) {
-            if (libraryDirectiveFound) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES);
-            } else {
-              if (directives.isNotEmpty) {
-                _reportErrorForCurrentToken(
-                    ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST);
-              }
-              libraryDirectiveFound = true;
-            }
-            return parseLibraryDirective(commentAndMetadata);
-          } else if (keyword == Keyword.PART) {
-            if (_tokenMatchesKeyword(_peek(), Keyword.OF)) {
-              partOfDirectiveFound = true;
-              return _parsePartOfDirective(commentAndMetadata);
-            } else {
-              partDirectiveFound = true;
-              return _parsePartDirective(commentAndMetadata);
-            }
-          } else {
-            // Internal error: this method should not have been invoked if the
-            // current token was something other than one of the above.
-            throw StateError(
-                "parseDirective invoked in an invalid state (currentToken = $_currentToken)");
-          }
-        }
-
-        Directive directive = parseDirective();
-        if (declarations.isNotEmpty && !directiveFoundAfterDeclaration) {
-          _reportErrorForToken(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION,
-              directive.beginToken);
-          directiveFoundAfterDeclaration = true;
-        }
-        directives.add(directive);
-      } else if (type == TokenType.SEMICOLON) {
-        // TODO(brianwilkerson) Consider moving this error detection into
-        // _parseCompilationUnitMember (in the places where EXPECTED_EXECUTABLE
-        // is being generated).
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      } else {
-        CompilationUnitMember member;
-        try {
-          member = parseCompilationUnitMember(commentAndMetadata);
-        } on _TooDeepTreeError {
-          _reportErrorForToken(ParserErrorCode.STACK_OVERFLOW, _currentToken);
-          Token eof = Token.eof(0);
-          return astFactory.compilationUnit(
-            beginToken: eof,
-            endToken: eof,
-            featureSet: _featureSet,
-          );
-        }
-        if (member != null) {
-          declarations.add(member);
-        }
-      }
-      if (identical(_currentToken, memberStart)) {
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-        while (!_matches(TokenType.EOF) &&
-            !_couldBeStartOfCompilationUnitMember()) {
-          _advance();
-        }
-      }
-      memberStart = _currentToken;
-      type = _currentToken.type;
-    }
-    if (partOfDirectiveFound && directives.length > 1) {
-      // TODO(brianwilkerson) Improve error reporting when both a library and
-      // part-of directive are found.
-//      if (libraryDirectiveFound) {
-//        int directiveCount = directives.length;
-//        for (int i = 0; i < directiveCount; i++) {
-//          Directive directive = directives[i];
-//          if (directive is PartOfDirective) {
-//            _reportErrorForToken(
-//                ParserErrorCode.PART_OF_IN_LIBRARY, directive.partKeyword);
-//          }
-//        }
-//      } else {
-      bool firstPartOf = true;
-      int directiveCount = directives.length;
-      for (int i = 0; i < directiveCount; i++) {
-        Directive directive = directives[i];
-        if (directive is PartOfDirective) {
-          if (firstPartOf) {
-            firstPartOf = false;
-          } else {
-            _reportErrorForToken(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES,
-                directive.partKeyword);
-          }
-        } else {
-          _reportErrorForToken(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART,
-              directives[i].keyword);
-        }
-//        }
-      }
-    }
-    return astFactory.compilationUnit(
-      beginToken: firstToken,
-      scriptTag: scriptTag,
-      directives: directives,
-      declarations: declarations,
-      endToken: _currentToken,
-      featureSet: _featureSet,
-    );
+    currentToken = fastaParser.parseUnit(currentToken);
+    return astBuilder.pop() as CompilationUnit;
   }
 
-  /// Parse a compilation unit member. The [commentAndMetadata] is the metadata
-  /// to be associated with the member. Return the compilation unit member that
-  /// was parsed, or `null` if what was parsed could not be represented as a
-  /// compilation unit member.
-  ///
-  ///     compilationUnitMember ::=
-  ///         classDefinition
-  ///       | functionTypeAlias
-  ///       | external functionSignature
-  ///       | external getterSignature
-  ///       | external setterSignature
-  ///       | functionSignature functionBody
-  ///       | returnType? getOrSet identifier formalParameterList functionBody
-  ///       | (final | const) type? staticFinalDeclarationList ';'
-  ///       | variableDeclaration ';'
-  CompilationUnitMember parseCompilationUnitMember(
-      CommentAndMetadata commentAndMetadata) {
-    Modifiers modifiers = parseModifiers();
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.CLASS) {
-      return parseClassDeclaration(
-          commentAndMetadata, _validateModifiersForClass(modifiers));
-    }
-    Token next = _peek();
-    TokenType nextType = next.type;
-    if (keyword == Keyword.TYPEDEF &&
-        nextType != TokenType.PERIOD &&
-        nextType != TokenType.LT &&
-        nextType != TokenType.OPEN_PAREN) {
-      _validateModifiersForTypedef(modifiers);
-      return parseTypeAlias(commentAndMetadata);
-    } else if (keyword == Keyword.ENUM) {
-      _validateModifiersForEnum(modifiers);
-      return parseEnumDeclaration(commentAndMetadata);
-    } else if (keyword == Keyword.VOID ||
-        _atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      TypeAnnotation returnType;
-      if (keyword == Keyword.VOID) {
-        if (_atGenericFunctionTypeAfterReturnType(next)) {
-          returnType = parseTypeAnnotation(false);
-        } else {
-          returnType = astFactory.typeName(
-              astFactory.simpleIdentifier(getAndAdvance()), null);
-        }
-      } else {
-        returnType = parseTypeAnnotation(false);
-      }
-      keyword = _currentToken.keyword;
-      next = _peek();
-      if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
-          _tokenMatchesIdentifier(next)) {
-        _validateModifiersForTopLevelFunction(modifiers);
-        return parseFunctionDeclaration(
-            commentAndMetadata, modifiers.externalKeyword, returnType);
-      } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-        _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
-        return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
-            commentAndMetadata,
-            modifiers.externalKeyword,
-            returnType,
-            getAndAdvance()));
-      } else if (_matchesIdentifier() &&
-          next.matchesAny(const <TokenType>[
-            TokenType.OPEN_PAREN,
-            TokenType.OPEN_CURLY_BRACKET,
-            TokenType.FUNCTION,
-            TokenType.LT
-          ])) {
-        _validateModifiersForTopLevelFunction(modifiers);
-        return parseFunctionDeclaration(
-            commentAndMetadata, modifiers.externalKeyword, returnType);
-      } else if (_matchesIdentifier() &&
-          next.matchesAny(const <TokenType>[
-            TokenType.EQ,
-            TokenType.COMMA,
-            TokenType.SEMICOLON
-          ])) {
-        return astFactory.topLevelVariableDeclaration(
-            commentAndMetadata.comment,
-            commentAndMetadata.metadata,
-            parseVariableDeclarationListAfterType(null,
-                _validateModifiersForTopLevelVariable(modifiers), returnType),
-            _expect(TokenType.SEMICOLON));
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        _reportErrorForToken(
-            ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
-        return null;
-      }
-    } else if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
-        _tokenMatchesIdentifier(next)) {
-      _validateModifiersForTopLevelFunction(modifiers);
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, null);
-    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-      _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
-      return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          null,
-          getAndAdvance()));
-    } else if (!_matchesIdentifier()) {
-      Token keyword = modifiers.varKeyword;
-      keyword ??= modifiers.finalKeyword;
-      keyword ??= modifiers.constKeyword;
-      if (keyword != null) {
-        //
-        // We appear to have found an incomplete top-level variable declaration.
-        //
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-        VariableDeclaration variable = astFactory.variableDeclaration(
-            createSyntheticIdentifier(), null, null);
-        List<VariableDeclaration> variables = <VariableDeclaration>[variable];
-        return astFactory.topLevelVariableDeclaration(
-            commentAndMetadata.comment,
-            commentAndMetadata.metadata,
-            astFactory.variableDeclarationList(
-                null, null, keyword, null, variables),
-            _expect(TokenType.SEMICOLON));
-      }
-      _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
-      return null;
-    } else if (_isPeekGenericTypeParametersAndOpenParen()) {
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, null);
-    } else if (_tokenMatches(next, TokenType.OPEN_PAREN)) {
-      TypeName returnType;
-      _validateModifiersForTopLevelFunction(modifiers);
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, returnType);
-    } else if (next.matchesAny(const <TokenType>[
-      TokenType.EQ,
-      TokenType.COMMA,
-      TokenType.SEMICOLON
-    ])) {
-      if (modifiers.constKeyword == null &&
-          modifiers.finalKeyword == null &&
-          modifiers.varKeyword == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
-      }
-      return astFactory.topLevelVariableDeclaration(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          parseVariableDeclarationListAfterType(
-              null, _validateModifiersForTopLevelVariable(modifiers), null),
-          _expect(TokenType.SEMICOLON));
-    }
-    TypeAnnotation returnType = parseTypeAnnotation(false);
-    keyword = _currentToken.keyword;
-    next = _peek();
-    if ((keyword == Keyword.GET || keyword == Keyword.SET) &&
-        _tokenMatchesIdentifier(next)) {
-      _validateModifiersForTopLevelFunction(modifiers);
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, returnType);
-    } else if (keyword == Keyword.OPERATOR && _isOperator(next)) {
-      _reportErrorForToken(ParserErrorCode.TOP_LEVEL_OPERATOR, _currentToken);
-      return _convertToFunctionDeclaration(_parseOperatorAfterKeyword(
-          commentAndMetadata,
-          modifiers.externalKeyword,
-          returnType,
-          getAndAdvance()));
-    } else if (_matches(TokenType.AT)) {
-      return astFactory.topLevelVariableDeclaration(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          parseVariableDeclarationListAfterType(null,
-              _validateModifiersForTopLevelVariable(modifiers), returnType),
-          _expect(TokenType.SEMICOLON));
-    } else if (!_matchesIdentifier()) {
-      // TODO(brianwilkerson) Generalize this error. We could also be parsing a
-      // top-level variable at this point.
-      _reportErrorForToken(ParserErrorCode.EXPECTED_EXECUTABLE, _currentToken);
-      Token semicolon;
-      if (_matches(TokenType.SEMICOLON)) {
-        semicolon = getAndAdvance();
-      } else {
-        semicolon = _createSyntheticToken(TokenType.SEMICOLON);
-      }
-      VariableDeclaration variable = astFactory.variableDeclaration(
-          createSyntheticIdentifier(), null, null);
-      List<VariableDeclaration> variables = <VariableDeclaration>[variable];
-      return astFactory.topLevelVariableDeclaration(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          astFactory.variableDeclarationList(
-              null, null, null, returnType, variables),
-          semicolon);
-    } else if (next.matchesAny(const <TokenType>[
-      TokenType.OPEN_PAREN,
-      TokenType.FUNCTION,
-      TokenType.OPEN_CURLY_BRACKET,
-      TokenType.LT
-    ])) {
-      _validateModifiersForTopLevelFunction(modifiers);
-      return parseFunctionDeclaration(
-          commentAndMetadata, modifiers.externalKeyword, returnType);
-    }
-    return astFactory.topLevelVariableDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        parseVariableDeclarationListAfterType(
-            null, _validateModifiersForTopLevelVariable(modifiers), returnType),
-        _expect(TokenType.SEMICOLON));
-  }
+  Expression parseConditionalExpression() => parseExpression2();
 
-  /// Parse a conditional expression. Return the conditional expression that was
-  /// parsed.
-  ///
-  ///     conditionalExpression ::=
-  ///         ifNullExpression ('?' expressionWithoutCascade ':' expressionWithoutCascade)?
-  Expression parseConditionalExpression() {
-    Expression condition = parseIfNullExpression();
-    if (_currentToken.type != TokenType.QUESTION) {
-      return condition;
-    }
-    Token question = getAndAdvance();
-    Expression thenExpression = parseExpressionWithoutCascade();
-    Token colon = _expect(TokenType.COLON);
-    Expression elseExpression = parseExpressionWithoutCascade();
-    return astFactory.conditionalExpression(
-        condition, question, thenExpression, colon, elseExpression);
-  }
-
-  /// Parse a configuration in either an import or export directive.
-  ///
-  /// This method assumes that the current token matches `Keyword.IF`.
-  ///
-  ///     configuration ::=
-  ///         'if' '(' test ')' uri
-  ///
-  ///     test ::=
-  ///         dottedName ('==' stringLiteral)?
-  ///
-  ///     dottedName ::=
-  ///         identifier ('.' identifier)*
   Configuration parseConfiguration() {
-    Token ifKeyword = getAndAdvance();
-    Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-    DottedName name = parseDottedName();
-    Token equalToken;
-    StringLiteral value;
-    if (_matches(TokenType.EQ_EQ)) {
-      equalToken = getAndAdvance();
-      value = parseStringLiteral();
-      if (value is StringInterpolation) {
-        _reportErrorForNode(
-            ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, value);
-      }
-    }
-    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-    StringLiteral libraryUri = _parseUri();
-    return astFactory.configuration(ifKeyword, leftParenthesis, name,
-        equalToken, value, rightParenthesis, libraryUri);
+    currentToken = fastaParser
+        .parseConditionalUri(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    return astBuilder.pop() as Configuration;
   }
 
-  /// Parse a const expression. Return the const expression that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.CONST`.
-  ///
-  ///     constExpression ::=
-  ///         instanceCreationExpression
-  ///       | listLiteral
-  ///       | mapLiteral
-  Expression parseConstExpression() {
-    Token keyword = getAndAdvance();
-    TokenType type = _currentToken.type;
-    if (type == TokenType.LT) {
-      return parseListOrMapLiteral(keyword);
-    } else if (type == TokenType.OPEN_SQUARE_BRACKET ||
-        type == TokenType.INDEX) {
-      return parseListLiteral(keyword, null);
-    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-      return parseMapLiteral(keyword, null);
-    }
-    return parseInstanceCreationExpression(keyword);
-  }
+  Expression parseConstExpression() => parseExpression2();
 
-  /// Parse a field initializer within a constructor. The flag [hasThis] should
-  /// be true if the current token is `this`. Return the field initializer that
-  /// was parsed.
-  ///
-  ///     fieldInitializer:
-  ///         ('this' '.')? identifier '=' conditionalExpression cascadeSection*
-  ConstructorFieldInitializer parseConstructorFieldInitializer(bool hasThis) {
-    Token keywordToken;
-    Token period;
-    if (hasThis) {
-      keywordToken = getAndAdvance();
-      period = _expect(TokenType.PERIOD);
-    }
-    SimpleIdentifier fieldName = parseSimpleIdentifier();
-    Token equals;
-    TokenType type = _currentToken.type;
-    if (type == TokenType.EQ) {
-      equals = getAndAdvance();
-    } else {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER);
-      Keyword keyword = _currentToken.keyword;
-      if (keyword != Keyword.THIS &&
-          keyword != Keyword.SUPER &&
-          type != TokenType.OPEN_CURLY_BRACKET &&
-          type != TokenType.FUNCTION) {
-        equals = _createSyntheticToken(TokenType.EQ);
-      } else {
-        return astFactory.constructorFieldInitializer(
-            keywordToken,
-            period,
-            fieldName,
-            _createSyntheticToken(TokenType.EQ),
-            createSyntheticIdentifier());
-      }
-    }
-    bool wasInInitializer = _inInitializer;
-    _inInitializer = true;
-    try {
-      Expression expression = parseConditionalExpression();
-      if (_matches(TokenType.PERIOD_PERIOD)) {
-        List<Expression> cascadeSections = <Expression>[];
-        do {
-          Expression section = parseCascadeSection();
-          if (section != null) {
-            cascadeSections.add(section);
-          }
-        } while (_matches(TokenType.PERIOD_PERIOD));
-        expression = astFactory.cascadeExpression(expression, cascadeSections);
-      }
-      return astFactory.constructorFieldInitializer(
-          keywordToken, period, fieldName, equals, expression);
-    } finally {
-      _inInitializer = wasInInitializer;
-    }
-  }
-
-  /// Parse the name of a constructor. Return the constructor name that was
-  /// parsed.
-  ///
-  ///     constructorName:
-  ///         type ('.' identifier)?
-  ConstructorName parseConstructorName() {
-    TypeName type = parseTypeName(false);
-    Token period;
-    SimpleIdentifier name;
-    if (_matches(TokenType.PERIOD)) {
-      period = getAndAdvance();
-      name = parseSimpleIdentifier();
-    }
-    return astFactory.constructorName(type, period, name);
-  }
-
-  /// Parse a continue statement. Return the continue statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.CONTINUE`.
-  ///
-  ///     continueStatement ::=
-  ///         'continue' identifier? ';'
-  Statement parseContinueStatement() {
-    Token continueKeyword = getAndAdvance();
-    if (!_inLoop && !_inSwitch) {
-      _reportErrorForToken(
-          ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, continueKeyword);
-    }
-    SimpleIdentifier label;
-    if (_matchesIdentifier()) {
-      label = _parseSimpleIdentifierUnchecked();
-    }
-    if (_inSwitch && !_inLoop && label == null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, continueKeyword);
-    }
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.continueStatement(continueKeyword, label, semicolon);
-  }
-
-  /// Parse a directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the directive that was parsed.
-  ///
-  ///     directive ::=
-  ///         exportDirective
-  ///       | libraryDirective
-  ///       | importDirective
-  ///       | partDirective
-  Directive parseDirective(CommentAndMetadata commentAndMetadata) {
-    if (_matchesKeyword(Keyword.IMPORT)) {
-      return parseImportDirective(commentAndMetadata);
-    } else if (_matchesKeyword(Keyword.EXPORT)) {
-      return parseExportDirective(commentAndMetadata);
-    } else if (_matchesKeyword(Keyword.LIBRARY)) {
-      return parseLibraryDirective(commentAndMetadata);
-    } else if (_matchesKeyword(Keyword.PART)) {
-      return parsePartOrPartOfDirective(commentAndMetadata);
-    } else {
-      // Internal error: this method should not have been invoked if the current
-      // token was something other than one of the above.
-      throw StateError(
-          "parseDirective invoked in an invalid state; currentToken = $_currentToken");
-    }
-  }
-
-  /// Parse the script tag and directives in a compilation unit, starting with
-  /// the given [token], until the first non-directive is encountered. The
-  /// remainder of the compilation unit will not be parsed. Specifically, if
-  /// there are directives later in the file, they will not be parsed. Return
-  /// the compilation unit that was parsed.
   CompilationUnit parseDirectives(Token token) {
-    _currentToken = token;
+    currentToken = token;
     return parseDirectives2();
   }
 
-  /// Parse the script tag and directives in a compilation unit until the first
-  /// non-directive is encountered. Return the compilation unit that was parsed.
-  ///
-  ///     compilationUnit ::=
-  ///         scriptTag? directive*
   CompilationUnit parseDirectives2() {
-    Token firstToken = _currentToken;
-    ScriptTag scriptTag;
-    if (_matches(TokenType.SCRIPT_TAG)) {
-      scriptTag = astFactory.scriptTag(getAndAdvance());
-    }
-    List<Directive> directives = <Directive>[];
-    while (!_matches(TokenType.EOF)) {
-      CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-      Keyword keyword = _currentToken.keyword;
-      TokenType type = _peek().type;
-      if ((keyword == Keyword.IMPORT ||
-              keyword == Keyword.EXPORT ||
-              keyword == Keyword.LIBRARY ||
-              keyword == Keyword.PART) &&
-          type != TokenType.PERIOD &&
-          type != TokenType.LT &&
-          type != TokenType.OPEN_PAREN) {
-        directives.add(parseDirective(commentAndMetadata));
-      } else if (_matches(TokenType.SEMICOLON)) {
-        _advance();
-      } else {
-        while (!_matches(TokenType.EOF)) {
-          _advance();
-        }
-        return astFactory.compilationUnit(
-          beginToken: firstToken,
-          scriptTag: scriptTag,
-          directives: directives,
-          endToken: _currentToken,
-          featureSet: _featureSet,
-        );
-      }
-    }
-    return astFactory.compilationUnit(
-      beginToken: firstToken,
-      scriptTag: scriptTag,
-      directives: directives,
-      endToken: _currentToken,
-      featureSet: _featureSet,
-    );
+    currentToken = fastaParser.parseDirectives(currentToken);
+    return astBuilder.pop() as CompilationUnit;
   }
 
-  /// Parse a documentation comment based on the given list of documentation
-  /// comment tokens. Return the documentation comment that was parsed, or
-  /// `null` if there was no comment.
-  ///
-  ///     documentationComment ::=
-  ///         multiLineComment?
-  ///       | singleLineComment*
-  Comment parseDocumentationComment(List<DocumentationCommentToken> tokens) {
-    if (tokens == null) {
-      return null;
-    }
-    List<CommentReference> references = parseCommentReferences(tokens);
-    return astFactory.documentationComment(tokens, references);
-  }
-
-  /// Parse a documentation comment. Return the documentation comment that was
-  /// parsed, or `null` if there was no comment.
-  ///
-  ///     documentationComment ::=
-  ///         multiLineComment?
-  ///       | singleLineComment*
-  List<DocumentationCommentToken> parseDocumentationCommentTokens() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[];
-    CommentToken commentToken = _currentToken.precedingComments;
-    while (commentToken != null) {
-      if (commentToken is DocumentationCommentToken) {
-        if (tokens.isNotEmpty) {
-          if (commentToken.type == TokenType.SINGLE_LINE_COMMENT) {
-            if (tokens[0].type != TokenType.SINGLE_LINE_COMMENT) {
-              tokens.clear();
-            }
-          } else {
-            tokens.clear();
-          }
-        }
-        tokens.add(commentToken);
-      }
-      commentToken = commentToken.next;
-    }
-    return tokens.isEmpty ? null : tokens;
-  }
-
-  /// Parse a do statement. Return the do statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.DO`.
-  ///
-  ///     doStatement ::=
-  ///         'do' statement 'while' '(' expression ')' ';'
-  Statement parseDoStatement() {
-    bool wasInLoop = _inLoop;
-    _inLoop = true;
-    try {
-      Token doKeyword = getAndAdvance();
-      Statement body = parseStatement2();
-      Token whileKeyword = _expectKeyword(Keyword.WHILE);
-      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-      Expression condition = parseExpression2();
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      Token semicolon = _expect(TokenType.SEMICOLON);
-      return astFactory.doStatement(doKeyword, body, whileKeyword,
-          leftParenthesis, condition, rightParenthesis, semicolon);
-    } finally {
-      _inLoop = wasInLoop;
-    }
-  }
-
-  /// Parse a dotted name. Return the dotted name that was parsed.
-  ///
-  ///     dottedName ::=
-  ///         identifier ('.' identifier)*
   DottedName parseDottedName() {
-    List<SimpleIdentifier> components = <SimpleIdentifier>[
-      parseSimpleIdentifier()
-    ];
-    while (_optional(TokenType.PERIOD)) {
-      components.add(parseSimpleIdentifier());
-    }
-    return astFactory.dottedName(components);
+    currentToken = fastaParser
+        .parseDottedName(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    return astBuilder.pop() as DottedName;
   }
 
-  /// Parse an empty statement. Return the empty statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.SEMICOLON`.
-  ///
-  ///     emptyStatement ::=
-  ///         ';'
-  Statement parseEmptyStatement() => astFactory.emptyStatement(getAndAdvance());
+  Expression parseEqualityExpression() => parseExpression2();
 
-  /// Parse an enum declaration. The [commentAndMetadata] is the metadata to be
-  /// associated with the member. Return the enum declaration that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.ENUM`.
-  ///
-  ///     enumType ::=
-  ///         metadata 'enum' id '{' id (',' id)* (',')? '}'
-  EnumDeclaration parseEnumDeclaration(CommentAndMetadata commentAndMetadata) {
-    Token keyword = getAndAdvance();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    Token leftBracket;
-    List<EnumConstantDeclaration> constants = <EnumConstantDeclaration>[];
-    Token rightBracket;
-    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      leftBracket = getAndAdvance();
-      if (_matchesIdentifier() || _matches(TokenType.AT)) {
-        constants.add(_parseEnumConstantDeclaration());
-      } else if (_matches(TokenType.COMMA) &&
-          _tokenMatchesIdentifier(_peek())) {
-        constants.add(_parseEnumConstantDeclaration());
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-      } else {
-        constants.add(_parseEnumConstantDeclaration());
-        _reportErrorForCurrentToken(ParserErrorCode.EMPTY_ENUM_BODY);
-      }
-      while (_optional(TokenType.COMMA)) {
-        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-          break;
-        }
-        constants.add(_parseEnumConstantDeclaration());
-      }
-      rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-    } else {
-      leftBracket = _createSyntheticToken(TokenType.OPEN_CURLY_BRACKET);
-      rightBracket = _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET);
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_ENUM_BODY);
-    }
-    return astFactory.enumDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        keyword,
-        name,
-        leftBracket,
-        constants,
-        rightBracket);
-  }
-
-  /// Parse an equality expression. Return the equality expression that was
-  /// parsed.
-  ///
-  ///     equalityExpression ::=
-  ///         relationalExpression (equalityOperator relationalExpression)?
-  ///       | 'super' equalityOperator relationalExpression
-  Expression parseEqualityExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isEqualityOperator) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseRelationalExpression();
-    }
-    bool leftEqualityExpression = false;
-    while (_currentToken.type.isEqualityOperator) {
-      if (leftEqualityExpression) {
-        _reportErrorForNode(
-            ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, expression);
-      }
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseRelationalExpression());
-      leftEqualityExpression = true;
-    }
-    return expression;
-  }
-
-  /// Parse an export directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the export directive that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.EXPORT`.
-  ///
-  ///     exportDirective ::=
-  ///         metadata 'export' stringLiteral configuration* combinator*';'
-  ExportDirective parseExportDirective(CommentAndMetadata commentAndMetadata) {
-    Token exportKeyword = getAndAdvance();
-    StringLiteral libraryUri = _parseUri();
-    List<Configuration> configurations = _parseConfigurations();
-    List<Combinator> combinators = parseCombinators();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.exportDirective(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        exportKeyword,
-        libraryUri,
-        configurations,
-        combinators,
-        semicolon);
-  }
-
-  /// Parse an expression, starting with the given [token]. Return the
-  /// expression that was parsed, or `null` if the tokens do not represent a
-  /// recognizable expression.
   Expression parseExpression(Token token) {
-    _currentToken = token;
+    currentToken = token;
     return parseExpression2();
   }
 
-  /// Parse an expression that might contain a cascade. Return the expression
-  /// that was parsed.
-  ///
-  ///     expression ::=
-  ///         assignableExpression assignmentOperator expression
-  ///       | conditionalExpression cascadeSection*
-  ///       | throwExpression
   Expression parseExpression2() {
-    if (_treeDepth > _MAX_TREE_DEPTH) {
-      throw _TooDeepTreeError();
-    }
-    _treeDepth++;
-    try {
-      Keyword keyword = _currentToken.keyword;
-      if (keyword == Keyword.THROW) {
-        return parseThrowExpression();
-      } else if (keyword == Keyword.RETHROW) {
-        // TODO(brianwilkerson) Rethrow is a statement again.
-        return parseRethrowExpression();
-      }
-      //
-      // assignableExpression is a subset of conditionalExpression, so we can
-      // parse a conditional expression and then determine whether it is followed
-      // by an assignmentOperator, checking for conformance to the restricted
-      // grammar after making that determination.
-      //
-      Expression expression = parseConditionalExpression();
-      TokenType type = _currentToken.type;
-      if (type == TokenType.PERIOD_PERIOD) {
-        List<Expression> cascadeSections = <Expression>[];
-        do {
-          Expression section = parseCascadeSection();
-          if (section != null) {
-            cascadeSections.add(section);
-          }
-        } while (_currentToken.type == TokenType.PERIOD_PERIOD);
-        return astFactory.cascadeExpression(expression, cascadeSections);
-      } else if (type.isAssignmentOperator) {
-        Token operator = getAndAdvance();
-        _ensureAssignable(expression);
-        return astFactory.assignmentExpression(
-            expression, operator, parseExpression2());
-      }
-      return expression;
-    } finally {
-      _treeDepth--;
-    }
+    currentToken = fastaParser
+        .parseExpression(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    return astBuilder.pop() as Expression;
   }
 
-  /// Parse a list of expressions. Return the expression that was parsed.
-  ///
-  ///     expressionList ::=
-  ///         expression (',' expression)*
-  List<Expression> parseExpressionList() {
-    List<Expression> expressions = <Expression>[parseExpression2()];
-    while (_optional(TokenType.COMMA)) {
-      expressions.add(parseExpression2());
-    }
-    return expressions;
-  }
+  Expression parseExpressionWithoutCascade() => parseExpression2();
 
-  /// Parse an expression that does not contain any cascades. Return the
-  /// expression that was parsed.
-  ///
-  ///     expressionWithoutCascade ::=
-  ///         assignableExpression assignmentOperator expressionWithoutCascade
-  ///       | conditionalExpression
-  ///       | throwExpressionWithoutCascade
-  Expression parseExpressionWithoutCascade() {
-    if (_matchesKeyword(Keyword.THROW)) {
-      return parseThrowExpressionWithoutCascade();
-    } else if (_matchesKeyword(Keyword.RETHROW)) {
-      return parseRethrowExpression();
-    }
-    //
-    // assignableExpression is a subset of conditionalExpression, so we can
-    // parse a conditional expression and then determine whether it is followed
-    // by an assignmentOperator, checking for conformance to the restricted
-    // grammar after making that determination.
-    //
-    Expression expression = parseConditionalExpression();
-    if (_currentToken.type.isAssignmentOperator) {
-      Token operator = getAndAdvance();
-      _ensureAssignable(expression);
-      expression = astFactory.assignmentExpression(
-          expression, operator, parseExpressionWithoutCascade());
-    }
-    return expression;
-  }
-
-  /// Parse a class extends clause. Return the class extends clause that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.EXTENDS`.
-  ///
-  ///     classExtendsClause ::=
-  ///         'extends' type
-  ExtendsClause parseExtendsClause() {
-    Token keyword = getAndAdvance();
-    TypeName superclass = parseTypeName(false);
-    return astFactory.extendsClause(keyword, superclass);
-  }
-
-  /// Parse the 'final', 'const', 'var' or type preceding a variable
-  /// declaration. The [optional] is `true` if the keyword and type are
-  /// optional. Return the 'final', 'const', 'var' or type that was parsed.
-  ///
-  ///     finalConstVarOrType ::=
-  ///         'final' type?
-  ///       | 'const' type?
-  ///       | 'var'
-  ///       | type
-  FinalConstVarOrType parseFinalConstVarOrType(bool optional,
-      {bool inFunctionType = false}) {
-    Token keywordToken;
-    TypeAnnotation type;
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.FINAL || keyword == Keyword.CONST) {
-      keywordToken = getAndAdvance();
-      if (_isTypedIdentifier(_currentToken)) {
-        type = parseTypeAnnotation(false);
-      }
-    } else if (keyword == Keyword.VAR) {
-      keywordToken = getAndAdvance();
-    } else if (_isTypedIdentifier(_currentToken)) {
-      type = parseTypeAnnotation(false);
-    } else if (inFunctionType && _matchesIdentifier()) {
-      type = parseTypeAnnotation(false);
-    } else if (!optional) {
-      // If there is a valid type immediately following an unexpected token,
-      // then report and skip the unexpected token.
-      Token next = _peek();
-      Keyword nextKeyword = next.keyword;
-      if (nextKeyword == Keyword.FINAL ||
-          nextKeyword == Keyword.CONST ||
-          nextKeyword == Keyword.VAR ||
-          _isTypedIdentifier(next) ||
-          inFunctionType && _tokenMatchesIdentifier(next)) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
-        _advance();
-        return parseFinalConstVarOrType(optional,
-            inFunctionType: inFunctionType);
-      }
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE);
-    } else {
-      // Support parameters such as `(/*=K*/ key, /*=V*/ value)`
-      // This is not supported if the type is required.
-      type;
-    }
-    return FinalConstVarOrType(keywordToken, type);
-  }
-
-  /// Parse a formal parameter. At most one of `isOptional` and `isNamed` can be
-  /// `true`. The [kind] is the kind of parameter being expected based on the
-  /// presence or absence of group delimiters. Return the formal parameter that
-  /// was parsed.
-  ///
-  ///     defaultFormalParameter ::=
-  ///         normalFormalParameter ('=' expression)?
-  ///
-  ///     defaultNamedParameter ::=
-  ///         normalFormalParameter ('=' expression)?
-  ///         normalFormalParameter (':' expression)?
-  FormalParameter parseFormalParameter(ParameterKind kind,
-      {bool inFunctionType = false}) {
-    NormalFormalParameter parameter =
-        parseNormalFormalParameter(inFunctionType: inFunctionType);
-    TokenType type = _currentToken.type;
-    if (type == TokenType.EQ) {
-      if (inFunctionType) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE);
-      }
-      Token separator = getAndAdvance();
-      Expression defaultValue = parseExpression2();
-      if (kind == ParameterKind.REQUIRED) {
-        _reportErrorForNode(
-            ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, parameter);
-        kind = ParameterKind.POSITIONAL;
-      } else if (kind == ParameterKind.NAMED &&
-          inFunctionType &&
-          parameter.identifier == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
-        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
-      }
-      return astFactory.defaultFormalParameter(
-          parameter, kind, separator, defaultValue);
-    } else if (type == TokenType.COLON) {
-      if (inFunctionType) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE);
-      }
-      Token separator = getAndAdvance();
-      Expression defaultValue = parseExpression2();
-      if (kind == ParameterKind.REQUIRED) {
-        _reportErrorForNode(
-            ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, parameter);
-        kind = ParameterKind.NAMED;
-      } else if (kind == ParameterKind.POSITIONAL) {
-        _reportErrorForToken(
-            ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
-            separator);
-      } else if (kind == ParameterKind.NAMED &&
-          inFunctionType &&
-          parameter.identifier == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
-        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
-      }
-      return astFactory.defaultFormalParameter(
-          parameter, kind, separator, defaultValue);
-    } else if (kind != ParameterKind.REQUIRED) {
-      if (kind == ParameterKind.NAMED &&
-          inFunctionType &&
-          parameter.identifier == null) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER);
-        parameter.identifier = createSyntheticIdentifier(isDeclaration: true);
-      }
-      return astFactory.defaultFormalParameter(parameter, kind, null, null);
-    }
-    return parameter;
-  }
-
-  /// Parse a list of formal parameters. Return the formal parameters that were
-  /// parsed.
-  ///
-  ///     formalParameterList ::=
-  ///         '(' ')'
-  ///       | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
-  ///       | '(' optionalFormalParameters ')'
-  ///
-  ///     normalFormalParameters ::=
-  ///         normalFormalParameter (',' normalFormalParameter)*
-  ///
-  ///     optionalFormalParameters ::=
-  ///         optionalPositionalFormalParameters
-  ///       | namedFormalParameters
-  ///
-  ///     optionalPositionalFormalParameters ::=
-  ///         '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
-  ///
-  ///     namedFormalParameters ::=
-  ///         '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
   FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
-    if (_matches(TokenType.OPEN_PAREN)) {
-      return _parseFormalParameterListUnchecked(inFunctionType: inFunctionType);
-    }
-    // TODO(brianwilkerson) Improve the error message.
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_PAREN.lexeme]);
-    // Recovery: Check for an unmatched closing paren and parse parameters until
-    // it is reached.
-    return _parseFormalParameterListAfterParen(
-        _createSyntheticToken(TokenType.OPEN_PAREN));
+    currentToken = fastaParser
+        .parseFormalParametersRequiredOpt(
+            fastaParser.syntheticPreviousToken(currentToken),
+            inFunctionType
+                ? fasta.MemberKind.GeneralizedFunctionType
+                : fasta.MemberKind.NonStaticMethod)
+        .next;
+    return astBuilder.pop() as FormalParameterList;
   }
 
-  /// Parse a for statement. Return the for statement that was parsed.
-  ///
-  ///     forStatement ::=
-  ///         'for' '(' forLoopParts ')' statement
-  ///
-  ///     forLoopParts ::=
-  ///         forInitializerStatement expression? ';' expressionList?
-  ///       | declaredIdentifier 'in' expression
-  ///       | identifier 'in' expression
-  ///
-  ///     forInitializerStatement ::=
-  ///         localVariableDeclaration ';'
-  ///       | expression? ';'
-  Statement parseForStatement() {
-    bool wasInLoop = _inLoop;
-    _inLoop = true;
-    try {
-      Token awaitKeyword;
-      if (_matchesKeyword(Keyword.AWAIT)) {
-        awaitKeyword = getAndAdvance();
-      }
-      Token forKeyword = _expectKeyword(Keyword.FOR);
-      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-      VariableDeclarationList variableList;
-      Expression initialization;
-      if (!_matches(TokenType.SEMICOLON)) {
-        CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-        if (_matchesIdentifier() &&
-            (_tokenMatchesKeyword(_peek(), Keyword.IN) ||
-                _tokenMatches(_peek(), TokenType.COLON))) {
-          SimpleIdentifier variableName = _parseSimpleIdentifierUnchecked();
-          variableList = astFactory.variableDeclarationList(
-              commentAndMetadata.comment,
-              commentAndMetadata.metadata,
-              null,
-              null, <VariableDeclaration>[
-            astFactory.variableDeclaration(variableName, null, null)
-          ]);
-        } else if (isInitializedVariableDeclaration()) {
-          variableList =
-              parseVariableDeclarationListAfterMetadata(commentAndMetadata);
-        } else {
-          initialization = parseExpression2();
-        }
-        TokenType type = _currentToken.type;
-        if (_matchesKeyword(Keyword.IN) || type == TokenType.COLON) {
-          if (type == TokenType.COLON) {
-            _reportErrorForCurrentToken(ParserErrorCode.COLON_IN_PLACE_OF_IN);
-          }
-          DeclaredIdentifier loopVariable;
-          SimpleIdentifier identifier;
-          if (variableList == null) {
-            // We found: <expression> 'in'
-            _reportErrorForCurrentToken(
-                ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH);
-          } else {
-            NodeList<VariableDeclaration> variables = variableList.variables;
-            if (variables.length > 1) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH,
-                  [variables.length.toString()]);
-            }
-            VariableDeclaration variable = variables[0];
-            if (variable.initializer != null) {
-              _reportErrorForCurrentToken(
-                  ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH);
-            }
-            Token keyword = variableList.keyword;
-            TypeAnnotation type = variableList.type;
-            if (keyword != null || type != null) {
-              loopVariable = astFactory.declaredIdentifier(
-                  commentAndMetadata.comment,
-                  commentAndMetadata.metadata,
-                  keyword,
-                  type,
-                  astFactory.simpleIdentifier(variable.name.token,
-                      isDeclaration: true));
-            } else {
-              if (commentAndMetadata.hasMetadata) {
-                // TODO(jwren) metadata isn't allowed before the identifier in
-                // "identifier in expression", add warning if commentAndMetadata
-                // has content
-              }
-              identifier = variable.name;
-            }
-          }
-          Token inKeyword = getAndAdvance();
-          Expression iterator = parseExpression2();
-          Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-          Statement body = parseStatement2();
-          ForLoopParts forLoopParts;
-          if (loopVariable == null) {
-            forLoopParts = astFactory.forEachPartsWithIdentifier(
-                identifier: identifier,
-                inKeyword: inKeyword,
-                iterable: iterator);
-          } else {
-            forLoopParts = astFactory.forEachPartsWithDeclaration(
-                loopVariable: loopVariable,
-                inKeyword: inKeyword,
-                iterable: iterator);
-          }
-          return astFactory.forStatement(
-              forKeyword: forKeyword,
-              leftParenthesis: leftParenthesis,
-              forLoopParts: forLoopParts,
-              rightParenthesis: rightParenthesis,
-              body: body);
-        }
-      }
-      if (awaitKeyword != null) {
-        _reportErrorForToken(
-            ParserErrorCode.INVALID_AWAIT_IN_FOR, awaitKeyword);
-      }
-      Token leftSeparator = _expect(TokenType.SEMICOLON);
-      Expression condition;
-      if (!_matches(TokenType.SEMICOLON)) {
-        condition = parseExpression2();
-      }
-      Token rightSeparator = _expect(TokenType.SEMICOLON);
-      List<Expression> updaters;
-      if (!_matches(TokenType.CLOSE_PAREN)) {
-        updaters = parseExpressionList();
-      }
-      ForLoopParts forLoopParts;
-      if (variableList != null) {
-        forLoopParts = astFactory.forPartsWithDeclarations(
-            variables: variableList,
-            leftSeparator: leftSeparator,
-            condition: condition,
-            rightSeparator: rightSeparator,
-            updaters: updaters);
-      } else {
-        forLoopParts = astFactory.forPartsWithExpression(
-            initialization: initialization,
-            leftSeparator: leftSeparator,
-            condition: condition,
-            rightSeparator: rightSeparator,
-            updaters: updaters);
-      }
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      Statement body = parseStatement2();
-      return astFactory.forStatement(
-          forKeyword: forKeyword,
-          leftParenthesis: leftParenthesis,
-          forLoopParts: forLoopParts,
-          rightParenthesis: rightParenthesis,
-          body: body);
-    } finally {
-      _inLoop = wasInLoop;
-    }
-  }
-
-  /// Parse a function body. The [mayBeEmpty] is `true` if the function body is
-  /// allowed to be empty. The [emptyErrorCode] is the error code to report if
-  /// function body expected, but not found. The [inExpression] is `true` if the
-  /// function body is being parsed as part of an expression and therefore does
-  /// not have a terminating semicolon. Return the function body that was
-  /// parsed.
-  ///
-  ///     functionBody ::=
-  ///         '=>' expression ';'
-  ///       | block
-  ///
-  ///     functionExpressionBody ::=
-  ///         '=>' expression
-  ///       | block
   FunctionBody parseFunctionBody(
       bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
-    bool wasInAsync = _inAsync;
-    bool wasInGenerator = _inGenerator;
-    bool wasInLoop = _inLoop;
-    bool wasInSwitch = _inSwitch;
-    _inAsync = false;
-    _inGenerator = false;
-    _inLoop = false;
-    _inSwitch = false;
-    try {
-      TokenType type = _currentToken.type;
-      if (type == TokenType.SEMICOLON) {
-        if (!mayBeEmpty) {
-          _reportErrorForCurrentToken(emptyErrorCode);
-        }
-        return astFactory.emptyFunctionBody(getAndAdvance());
-      }
-      Token keyword;
-      Token star;
-      bool foundAsync = false;
-      bool foundSync = false;
-      if (type.isKeyword) {
-        String lexeme = _currentToken.lexeme;
-        if (lexeme == ASYNC) {
-          foundAsync = true;
-          keyword = getAndAdvance();
-          if (_matches(TokenType.STAR)) {
-            star = getAndAdvance();
-            _inGenerator = true;
-          }
-          type = _currentToken.type;
-          _inAsync = true;
-        } else if (lexeme == SYNC) {
-          foundSync = true;
-          keyword = getAndAdvance();
-          if (_matches(TokenType.STAR)) {
-            star = getAndAdvance();
-            _inGenerator = true;
-          }
-          type = _currentToken.type;
-        }
-      }
-      if (type == TokenType.FUNCTION) {
-        if (keyword != null) {
-          if (!foundAsync) {
-            _reportErrorForToken(ParserErrorCode.INVALID_SYNC, keyword);
-            keyword;
-          } else if (star != null) {
-            _reportErrorForToken(
-                ParserErrorCode.INVALID_STAR_AFTER_ASYNC, star);
-          }
-        }
-        Token functionDefinition = getAndAdvance();
-        if (_matchesKeyword(Keyword.RETURN)) {
-          _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-              [_currentToken.lexeme]);
-          _advance();
-        }
-        Expression expression = parseExpression2();
-        Token semicolon;
-        if (!inExpression) {
-          semicolon = _expect(TokenType.SEMICOLON);
-        }
-        if (!_parseFunctionBodies) {
-          return astFactory
-              .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
-        }
-        return astFactory.expressionFunctionBody(
-            keyword, functionDefinition, expression, semicolon);
-      } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-        if (keyword != null) {
-          if (foundSync && star == null) {
-            _reportErrorForToken(
-                ParserErrorCode.MISSING_STAR_AFTER_SYNC, keyword);
-          }
-        }
-        if (!_parseFunctionBodies) {
-          _skipBlock();
-          return astFactory
-              .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
-        }
-        return astFactory.blockFunctionBody(keyword, star, parseBlock());
-      } else if (_matchesKeyword(Keyword.NATIVE)) {
-        Token nativeToken = getAndAdvance();
-        StringLiteral stringLiteral;
-        if (_matches(TokenType.STRING)) {
-          stringLiteral = _parseStringLiteralUnchecked();
-        }
-        return astFactory.nativeFunctionBody(
-            nativeToken, stringLiteral, _expect(TokenType.SEMICOLON));
-      } else {
-        // Invalid function body
-        _reportErrorForCurrentToken(emptyErrorCode);
-        return astFactory
-            .emptyFunctionBody(_createSyntheticToken(TokenType.SEMICOLON));
-      }
-    } finally {
-      _inAsync = wasInAsync;
-      _inGenerator = wasInGenerator;
-      _inLoop = wasInLoop;
-      _inSwitch = wasInSwitch;
-    }
+    currentToken = fastaParser.parseAsyncModifierOpt(
+        fastaParser.syntheticPreviousToken(currentToken));
+    currentToken =
+        fastaParser.parseFunctionBody(currentToken, inExpression, mayBeEmpty);
+    return astBuilder.pop() as FunctionBody;
   }
 
-  /// Parse a function declaration. The [commentAndMetadata] is the
-  /// documentation comment and metadata to be associated with the declaration.
-  /// The [externalKeyword] is the 'external' keyword, or `null` if the
-  /// function is not external. The [returnType] is the return type, or `null`
-  /// if there is no return type. The [isStatement] is `true` if the function
-  /// declaration is being parsed as a statement. Return the function
-  /// declaration that was parsed.
-  ///
-  ///     functionDeclaration ::=
-  ///         functionSignature functionBody
-  ///       | returnType? getOrSet identifier formalParameterList functionBody
-  FunctionDeclaration parseFunctionDeclaration(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      TypeAnnotation returnType) {
-    Token keywordToken;
-    bool isGetter = false;
-    Keyword keyword = _currentToken.keyword;
-    SimpleIdentifier name;
-    if (keyword == Keyword.GET) {
-      keywordToken = getAndAdvance();
-      isGetter = true;
-    } else if (keyword == Keyword.SET) {
-      keywordToken = getAndAdvance();
-    }
-    if (keywordToken != null && _matches(TokenType.OPEN_PAREN)) {
-      name = astFactory.simpleIdentifier(keywordToken, isDeclaration: true);
-      keywordToken;
-      isGetter = false;
-    } else {
-      name = parseSimpleIdentifier(isDeclaration: true);
-    }
-    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
-    FormalParameterList parameters;
-    if (!isGetter) {
-      if (_matches(TokenType.OPEN_PAREN)) {
-        parameters = _parseFormalParameterListUnchecked();
-        _validateFormalParameterList(parameters);
-      } else {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.MISSING_FUNCTION_PARAMETERS);
-        parameters = astFactory.formalParameterList(
-            _createSyntheticToken(TokenType.OPEN_PAREN),
-            null,
-            null,
-            null,
-            _createSyntheticToken(TokenType.CLOSE_PAREN));
-      }
-    } else if (_matches(TokenType.OPEN_PAREN)) {
-      _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
-      _parseFormalParameterListUnchecked();
-    }
-    FunctionBody body;
-    if (externalKeyword == null) {
-      body = parseFunctionBody(
-          false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
-    } else {
-      body = astFactory.emptyFunctionBody(_expect(TokenType.SEMICOLON));
-    }
-//        if (!isStatement && matches(TokenType.SEMICOLON)) {
-//          // TODO(brianwilkerson) Improve this error message.
-//          reportError(ParserErrorCode.UNEXPECTED_TOKEN, currentToken.getLexeme());
-//          advance();
-//        }
-    return astFactory.functionDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        returnType,
-        keywordToken,
-        name,
-        astFactory.functionExpression(typeParameters, parameters, body));
-  }
+  FunctionExpression parseFunctionExpression() =>
+      parseExpression2() as FunctionExpression;
 
-  /// Parse a function declaration statement. Return the function declaration
-  /// statement that was parsed.
-  ///
-  ///     functionDeclarationStatement ::=
-  ///         functionSignature functionBody
-  Statement parseFunctionDeclarationStatement() {
-    Modifiers modifiers = parseModifiers();
-    _validateModifiersForFunctionDeclarationStatement(modifiers);
-    return _parseFunctionDeclarationStatementAfterReturnType(
-        parseCommentAndMetadata(), _parseOptionalReturnType());
-  }
+  Expression parseLogicalAndExpression() => parseExpression2();
 
-  /// Parse a function expression. Return the function expression that was
-  /// parsed.
-  ///
-  ///     functionExpression ::=
-  ///         typeParameters? formalParameterList functionExpressionBody
-  FunctionExpression parseFunctionExpression() {
-    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
-    FormalParameterList parameters = parseFormalParameterList();
-    _validateFormalParameterList(parameters);
-    FunctionBody body =
-        parseFunctionBody(false, ParserErrorCode.MISSING_FUNCTION_BODY, true);
-    return astFactory.functionExpression(typeParameters, parameters, body);
-  }
+  Expression parseLogicalOrExpression() => parseExpression2();
 
-  /// Parse the portion of a generic function type following the [returnType].
-  ///
-  ///     functionType ::=
-  ///         returnType? 'Function' typeParameters? parameterTypeList
-  ///     parameterTypeList ::=
-  ///         '(' ')' |
-  ///       | '(' normalParameterTypes ','? ')' |
-  ///       | '(' normalParameterTypes ',' optionalParameterTypes ')' |
-  ///       | '(' optionalParameterTypes ')'
-  ///     normalParameterTypes ::=
-  ///         normalParameterType (',' normalParameterType)*
-  ///     normalParameterType ::=
-  ///         type | typedIdentifier
-  ///     optionalParameterTypes ::=
-  ///         optionalPositionalParameterTypes | namedParameterTypes
-  ///     optionalPositionalParameterTypes ::=
-  ///         '[' normalParameterTypes ','? ']'
-  ///     namedParameterTypes ::=
-  ///         '{' typedIdentifier (',' typedIdentifier)* ','? '}'
-  ///     typedIdentifier ::=
-  ///         type identifier
-  GenericFunctionType parseGenericFunctionTypeAfterReturnType(
-      TypeAnnotation returnType) {
-    Token functionKeyword;
-    if (_matchesKeyword(Keyword.FUNCTION)) {
-      functionKeyword = getAndAdvance();
-    } else if (_matchesIdentifier()) {
-      _reportErrorForCurrentToken(ParserErrorCode.NAMED_FUNCTION_TYPE);
-    } else {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_FUNCTION_KEYWORD);
-    }
-    TypeParameterList typeParameters;
-    if (_matches(TokenType.LT)) {
-      typeParameters = parseTypeParameterList();
-    }
-    FormalParameterList parameters =
-        parseFormalParameterList(inFunctionType: true);
-    return astFactory.genericFunctionType(
-        returnType, functionKeyword, typeParameters, parameters);
-  }
+  Expression parseMultiplicativeExpression() => parseExpression2();
 
-  /// Parse a generic function type alias.
-  ///
-  /// This method assumes that the current token is an identifier.
-  ///
-  ///     genericTypeAlias ::=
-  ///         'typedef' identifier typeParameterList? '=' functionType ';'
-  GenericTypeAlias parseGenericTypeAlias(
-      CommentAndMetadata commentAndMetadata, Token keyword) {
-    Identifier name = _parseSimpleIdentifierUnchecked(isDeclaration: true);
-    TypeParameterList typeParameters;
-    if (_matches(TokenType.LT)) {
-      typeParameters = parseTypeParameterList();
-    }
-    Token equals = _expect(TokenType.EQ);
-    TypeAnnotation functionType = parseTypeAnnotation(false);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    if (functionType is! GenericFunctionType) {
-      // TODO(brianwilkerson) Generate a better error.
-      _reportErrorForToken(
-          ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, semicolon);
-      // TODO(brianwilkerson) Recover better than this.
-      return astFactory.genericTypeAlias(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          keyword,
-          name,
-          typeParameters,
-          equals,
-          null,
-          semicolon);
-    }
-    return astFactory.genericTypeAlias(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        keyword,
-        name,
-        typeParameters,
-        equals,
-        functionType,
-        semicolon);
-  }
-
-  /// Parse a getter. The [commentAndMetadata] is the documentation comment and
-  /// metadata to be associated with the declaration. The externalKeyword] is
-  /// the 'external' token. The staticKeyword] is the static keyword, or `null`
-  /// if the getter is not static. The [returnType] the return type that has
-  /// already been parsed, or `null` if there was no return type. Return the
-  /// getter that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.GET`.
-  ///
-  ///     getter ::=
-  ///         getterSignature functionBody?
-  ///
-  ///     getterSignature ::=
-  ///         'external'? 'static'? returnType? 'get' identifier
-  MethodDeclaration parseGetter(CommentAndMetadata commentAndMetadata,
-      Token externalKeyword, Token staticKeyword, TypeAnnotation returnType) {
-    Token propertyKeyword = getAndAdvance();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    if (_matches(TokenType.OPEN_PAREN) &&
-        _tokenMatches(_peek(), TokenType.CLOSE_PAREN)) {
-      _reportErrorForCurrentToken(ParserErrorCode.GETTER_WITH_PARAMETERS);
-      _advance();
-      _advance();
-    }
-    FunctionBody body = parseFunctionBody(
-        externalKeyword != null || staticKeyword == null,
-        ParserErrorCode.STATIC_GETTER_WITHOUT_BODY,
-        false);
-    if (externalKeyword != null && body is! EmptyFunctionBody) {
-      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_GETTER_WITH_BODY);
-    }
-    return astFactory.methodDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        staticKeyword,
-        returnType,
-        propertyKeyword,
-        null,
-        name,
-        null,
-        null,
-        body);
-  }
-
-  /// Parse a list of identifiers. Return the list of identifiers that were
-  /// parsed.
-  ///
-  ///     identifierList ::=
-  ///         identifier (',' identifier)*
-  List<SimpleIdentifier> parseIdentifierList() {
-    List<SimpleIdentifier> identifiers = <SimpleIdentifier>[
-      parseSimpleIdentifier()
-    ];
-    while (_optional(TokenType.COMMA)) {
-      identifiers.add(parseSimpleIdentifier());
-    }
-    return identifiers;
-  }
-
-  /// Parse an if-null expression.  Return the if-null expression that was
-  /// parsed.
-  ///
-  ///     ifNullExpression ::= logicalOrExpression ('??' logicalOrExpression)*
-  Expression parseIfNullExpression() {
-    Expression expression = parseLogicalOrExpression();
-    while (_currentToken.type == TokenType.QUESTION_QUESTION) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseLogicalOrExpression());
-    }
-    return expression;
-  }
-
-  /// Parse an if statement. Return the if statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.IF`.
-  ///
-  ///     ifStatement ::=
-  ///         'if' '(' expression ')' statement ('else' statement)?
-  Statement parseIfStatement() {
-    Token ifKeyword = getAndAdvance();
-    Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-    Expression condition = parseExpression2();
-    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-    Statement thenStatement = parseStatement2();
-    Token elseKeyword;
-    Statement elseStatement;
-    if (_matchesKeyword(Keyword.ELSE)) {
-      elseKeyword = getAndAdvance();
-      elseStatement = parseStatement2();
-    }
-    return astFactory.ifStatement(ifKeyword, leftParenthesis, condition,
-        rightParenthesis, thenStatement, elseKeyword, elseStatement);
-  }
-
-  /// Parse an implements clause. Return the implements clause that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.IMPLEMENTS`.
-  ///
-  ///     implementsClause ::=
-  ///         'implements' type (',' type)*
-  ImplementsClause parseImplementsClause() {
-    Token keyword = getAndAdvance();
-    List<TypeName> interfaces = <TypeName>[];
-    do {
-      TypeName typeName = parseTypeName(false);
-      interfaces.add(typeName);
-    } while (_optional(TokenType.COMMA));
-    return astFactory.implementsClause(keyword, interfaces);
-  }
-
-  /// Parse an import directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the import directive that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.IMPORT`.
-  ///
-  ///     importDirective ::=
-  ///         metadata 'import' stringLiteral configuration* (deferred)? ('as' identifier)? combinator*';'
-  ImportDirective parseImportDirective(CommentAndMetadata commentAndMetadata) {
-    Token importKeyword = getAndAdvance();
-    StringLiteral libraryUri = _parseUri();
-    List<Configuration> configurations = _parseConfigurations();
-    Token deferredToken;
-    Token asToken;
-    SimpleIdentifier prefix;
-    if (_matchesKeyword(Keyword.DEFERRED)) {
-      deferredToken = getAndAdvance();
-    }
-    if (_matchesKeyword(Keyword.AS)) {
-      asToken = getAndAdvance();
-      prefix = parseSimpleIdentifier(isDeclaration: true);
-    } else if (deferredToken != null) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT);
-    } else if (!_matches(TokenType.SEMICOLON) &&
-        !_matchesKeyword(Keyword.SHOW) &&
-        !_matchesKeyword(Keyword.HIDE)) {
-      Token nextToken = _peek();
-      if (_tokenMatchesKeyword(nextToken, Keyword.AS) ||
-          _tokenMatchesKeyword(nextToken, Keyword.SHOW) ||
-          _tokenMatchesKeyword(nextToken, Keyword.HIDE)) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken]);
-        _advance();
-        if (_matchesKeyword(Keyword.AS)) {
-          asToken = getAndAdvance();
-          prefix = parseSimpleIdentifier(isDeclaration: true);
-        }
-      }
-    }
-    List<Combinator> combinators = parseCombinators();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.importDirective(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        importKeyword,
-        libraryUri,
-        configurations,
-        deferredToken,
-        asToken,
-        prefix,
-        combinators,
-        semicolon);
-  }
-
-  /// Parse a list of initialized identifiers. The [commentAndMetadata] is the
-  /// documentation comment and metadata to be associated with the declaration.
-  /// The [staticKeyword] is the static keyword, or `null` if the getter is not
-  /// static. The [keyword] is the token representing the 'final', 'const' or
-  /// 'var' keyword, or `null` if there is no keyword. The [type] is the type
-  /// that has already been parsed, or `null` if 'var' was provided. Return the
-  /// getter that was parsed.
-  ///
-  ///     declaration ::=
-  ///         ('static' | 'covariant')? ('var' | type) initializedIdentifierList ';'
-  ///       | 'final' type? initializedIdentifierList ';'
-  ///
-  ///     initializedIdentifierList ::=
-  ///         initializedIdentifier (',' initializedIdentifier)*
-  ///
-  ///     initializedIdentifier ::=
-  ///         identifier ('=' expression)?
-  FieldDeclaration parseInitializedIdentifierList(
-      CommentAndMetadata commentAndMetadata,
-      Token staticKeyword,
-      Token covariantKeyword,
-      Token keyword,
-      TypeAnnotation type) {
-    VariableDeclarationList fieldList =
-        parseVariableDeclarationListAfterType(null, keyword, type);
-    return astFactory.fieldDeclaration2(
-        comment: commentAndMetadata.comment,
-        metadata: commentAndMetadata.metadata,
-        covariantKeyword: covariantKeyword,
-        staticKeyword: staticKeyword,
-        fieldList: fieldList,
-        semicolon: _expect(TokenType.SEMICOLON));
-  }
-
-  /// Parse an instance creation expression. The [keyword] is the 'new' or
-  /// 'const' keyword that introduces the expression. Return the instance
-  /// creation expression that was parsed.
-  ///
-  ///     instanceCreationExpression ::=
-  ///         ('new' | 'const') type ('.' identifier)? argumentList
-  InstanceCreationExpression parseInstanceCreationExpression(Token keyword) {
-    ConstructorName constructorName = parseConstructorName();
-    ArgumentList argumentList = _parseArgumentListChecked();
-    return astFactory.instanceCreationExpression(
-        keyword, constructorName, argumentList);
-  }
-
-  /// Parse a label. Return the label that was parsed.
-  ///
-  /// This method assumes that the current token matches an identifier and that
-  /// the following token matches `TokenType.COLON`.
-  ///
-  ///     label ::=
-  ///         identifier ':'
-  Label parseLabel({bool isDeclaration = false}) {
-    SimpleIdentifier label =
-        _parseSimpleIdentifierUnchecked(isDeclaration: isDeclaration);
-    Token colon = getAndAdvance();
-    return astFactory.label(label, colon);
-  }
-
-  /// Parse a library directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the library directive that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.LIBRARY`.
-  ///
-  ///     libraryDirective ::=
-  ///         metadata 'library' identifier ';'
-  LibraryDirective parseLibraryDirective(
-      CommentAndMetadata commentAndMetadata) {
-    Token keyword = getAndAdvance();
-    LibraryIdentifier libraryName = _parseLibraryName(
-        ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE, keyword);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.libraryDirective(commentAndMetadata.comment,
-        commentAndMetadata.metadata, keyword, libraryName, semicolon);
-  }
-
-  /// Parse a library identifier. Return the library identifier that was parsed.
-  ///
-  ///     libraryIdentifier ::=
-  ///         identifier ('.' identifier)*
-  LibraryIdentifier parseLibraryIdentifier() {
-    List<SimpleIdentifier> components = <SimpleIdentifier>[];
-    components.add(parseSimpleIdentifier());
-    while (_optional(TokenType.PERIOD)) {
-      components.add(parseSimpleIdentifier());
-    }
-    return astFactory.libraryIdentifier(components);
-  }
-
-  /// Parse a list literal. The [modifier] is the 'const' modifier appearing
-  /// before the literal, or `null` if there is no modifier. The [typeArguments]
-  /// is the type arguments appearing before the literal, or `null` if there are
-  /// no type arguments. Return the list literal that was parsed.
-  ///
-  /// This method assumes that the current token matches either
-  /// `TokenType.OPEN_SQUARE_BRACKET` or `TokenType.INDEX`.
-  ///
-  ///     listLiteral ::=
-  ///         'const'? typeArguments? '[' (expressionList ','?)? ']'
-  ListLiteral parseListLiteral(Token modifier, TypeArgumentList typeArguments) {
-    if (_matches(TokenType.INDEX)) {
-      _splitIndex();
-      return astFactory.listLiteral(
-          modifier, typeArguments, getAndAdvance(), null, getAndAdvance());
-    }
-    Token leftBracket = getAndAdvance();
-    if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
-      return astFactory.listLiteral(
-          modifier, typeArguments, leftBracket, null, getAndAdvance());
-    }
-    bool wasInInitializer = _inInitializer;
-    _inInitializer = false;
-    try {
-      List<Expression> elements = <Expression>[parseExpression2()];
-      while (_optional(TokenType.COMMA)) {
-        if (_matches(TokenType.CLOSE_SQUARE_BRACKET)) {
-          return astFactory.listLiteral(
-              modifier, typeArguments, leftBracket, elements, getAndAdvance());
-        }
-        elements.add(parseExpression2());
-      }
-      Token rightBracket = _expect(TokenType.CLOSE_SQUARE_BRACKET);
-      return astFactory.listLiteral(
-          modifier, typeArguments, leftBracket, elements, rightBracket);
-    } finally {
-      _inInitializer = wasInInitializer;
-    }
-  }
-
-  /// Parse a list or map literal. The [modifier] is the 'const' modifier
-  /// appearing before the literal, or `null` if there is no modifier. Return
-  /// the list or map literal that was parsed.
-  ///
-  ///     listOrMapLiteral ::=
-  ///         listLiteral
-  ///       | mapLiteral
-  TypedLiteral parseListOrMapLiteral(Token modifier) {
-    TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      return parseMapLiteral(modifier, typeArguments);
-    } else if (_matches(TokenType.OPEN_SQUARE_BRACKET) ||
-        _matches(TokenType.INDEX)) {
-      return parseListLiteral(modifier, typeArguments);
-    }
-    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL);
-    return astFactory.listLiteral(
-        modifier,
-        typeArguments,
-        _createSyntheticToken(TokenType.OPEN_SQUARE_BRACKET),
-        null,
-        _createSyntheticToken(TokenType.CLOSE_SQUARE_BRACKET));
-  }
-
-  /// Parse a logical and expression. Return the logical and expression that was
-  /// parsed.
-  ///
-  ///     logicalAndExpression ::=
-  ///         equalityExpression ('&&' equalityExpression)*
-  Expression parseLogicalAndExpression() {
-    Expression expression = parseEqualityExpression();
-    while (_currentToken.type == TokenType.AMPERSAND_AMPERSAND) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseEqualityExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a logical or expression. Return the logical or expression that was
-  /// parsed.
-  ///
-  ///     logicalOrExpression ::=
-  ///         logicalAndExpression ('||' logicalAndExpression)*
-  Expression parseLogicalOrExpression() {
-    Expression expression = parseLogicalAndExpression();
-    while (_currentToken.type == TokenType.BAR_BAR) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseLogicalAndExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a map literal. The [modifier] is the 'const' modifier appearing
-  /// before the literal, or `null` if there is no modifier. The [typeArguments]
-  /// is the type arguments that were declared, or `null` if there are no type
-  /// arguments. Return the map literal that was parsed.
-  ///
-  /// This method assumes that the current token matches
-  /// `TokenType.OPEN_CURLY_BRACKET`.
-  ///
-  ///     mapLiteral ::=
-  ///         'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
-  SetOrMapLiteral parseMapLiteral(
-      Token modifier, TypeArgumentList typeArguments) {
-    Token leftBracket = getAndAdvance();
-    if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-      return astFactory.setOrMapLiteral(
-          constKeyword: modifier,
-          typeArguments: typeArguments,
-          leftBracket: leftBracket,
-          rightBracket: getAndAdvance());
-    }
-    bool wasInInitializer = _inInitializer;
-    _inInitializer = false;
-    try {
-      List<MapLiteralEntry> entries = <MapLiteralEntry>[parseMapLiteralEntry()];
-      while (_optional(TokenType.COMMA)) {
-        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-          return astFactory.setOrMapLiteral(
-              constKeyword: modifier,
-              typeArguments: typeArguments,
-              leftBracket: leftBracket,
-              elements: entries,
-              rightBracket: getAndAdvance());
-        }
-        entries.add(parseMapLiteralEntry());
-      }
-      Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-      return astFactory.setOrMapLiteral(
-          constKeyword: modifier,
-          typeArguments: typeArguments,
-          leftBracket: leftBracket,
-          elements: entries,
-          rightBracket: rightBracket);
-    } finally {
-      _inInitializer = wasInInitializer;
-    }
-  }
-
-  /// Parse a map literal entry. Return the map literal entry that was parsed.
-  ///
-  ///     mapLiteralEntry ::=
-  ///         expression ':' expression
-  MapLiteralEntry parseMapLiteralEntry() {
-    Expression key = parseExpression2();
-    Token separator = _expect(TokenType.COLON);
-    Expression value = parseExpression2();
-    return astFactory.mapLiteralEntry(key, separator, value);
-  }
-
-  /// Parse the modifiers preceding a declaration. This method allows the
-  /// modifiers to appear in any order but does generate errors for duplicated
-  /// modifiers. Checks for other problems, such as having the modifiers appear
-  /// in the wrong order or specifying both 'const' and 'final', are reported in
-  /// one of the methods whose name is prefixed with `validateModifiersFor`.
-  /// Return the modifiers that were parsed.
-  ///
-  ///     modifiers ::=
-  ///         ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')*
-  Modifiers parseModifiers() {
-    Modifiers modifiers = Modifiers();
-    bool progress = true;
-    while (progress) {
-      TokenType nextType = _peek().type;
-      if (nextType == TokenType.PERIOD ||
-          nextType == TokenType.LT ||
-          nextType == TokenType.OPEN_PAREN) {
-        return modifiers;
-      }
-      Keyword keyword = _currentToken.keyword;
-      if (keyword == Keyword.ABSTRACT) {
-        if (modifiers.abstractKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.abstractKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.CONST) {
-        if (modifiers.constKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.constKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.COVARIANT) {
-        if (modifiers.covariantKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.covariantKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.EXTERNAL) {
-        if (modifiers.externalKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.externalKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.FACTORY) {
-        if (modifiers.factoryKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.factoryKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.FINAL) {
-        if (modifiers.finalKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.finalKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.STATIC) {
-        if (modifiers.staticKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.staticKeyword = getAndAdvance();
-        }
-      } else if (keyword == Keyword.VAR) {
-        if (modifiers.varKeyword != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.DUPLICATED_MODIFIER, [_currentToken.lexeme]);
-          _advance();
-        } else {
-          modifiers.varKeyword = getAndAdvance();
-        }
-      } else {
-        progress = false;
-      }
-    }
-    return modifiers;
-  }
-
-  /// Parse a multiplicative expression. Return the multiplicative expression
-  /// that was parsed.
-  ///
-  ///     multiplicativeExpression ::=
-  ///         unaryExpression (multiplicativeOperator unaryExpression)*
-  ///       | 'super' (multiplicativeOperator unaryExpression)+
-  Expression parseMultiplicativeExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isMultiplicativeOperator) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseUnaryExpression();
-    }
-    while (_currentToken.type.isMultiplicativeOperator) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseUnaryExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a new expression. Return the new expression that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.NEW`.
-  ///
-  ///     newExpression ::=
-  ///         instanceCreationExpression
   InstanceCreationExpression parseNewExpression() =>
-      parseInstanceCreationExpression(getAndAdvance());
+      parseExpression2() as InstanceCreationExpression;
 
-  /// Parse a non-labeled statement. Return the non-labeled statement that was
-  /// parsed.
-  ///
-  ///     nonLabeledStatement ::=
-  ///         block
-  ///       | assertStatement
-  ///       | breakStatement
-  ///       | continueStatement
-  ///       | doStatement
-  ///       | forStatement
-  ///       | ifStatement
-  ///       | returnStatement
-  ///       | switchStatement
-  ///       | tryStatement
-  ///       | whileStatement
-  ///       | variableDeclarationList ';'
-  ///       | expressionStatement
-  ///       | functionSignature functionBody
-  Statement parseNonLabeledStatement() {
-    // TODO(brianwilkerson) Pass the comment and metadata on where appropriate.
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    TokenType type = _currentToken.type;
-    if (type == TokenType.OPEN_CURLY_BRACKET) {
-      if (_tokenMatches(_peek(), TokenType.STRING)) {
-        Token afterString = skipStringLiteral(_currentToken.next);
-        if (afterString != null && afterString.type == TokenType.COLON) {
-          return astFactory.expressionStatement(
-              parseExpression2(), _expect(TokenType.SEMICOLON));
-        }
-      }
-      return parseBlock();
-    } else if (type.isKeyword && !_currentToken.keyword.isBuiltInOrPseudo) {
-      Keyword keyword = _currentToken.keyword;
-      // TODO(jwren) compute some metrics to figure out a better order for this
-      // if-then sequence to optimize performance
-      if (keyword == Keyword.ASSERT) {
-        return parseAssertStatement();
-      } else if (keyword == Keyword.BREAK) {
-        return parseBreakStatement();
-      } else if (keyword == Keyword.CONTINUE) {
-        return parseContinueStatement();
-      } else if (keyword == Keyword.DO) {
-        return parseDoStatement();
-      } else if (keyword == Keyword.FOR) {
-        return parseForStatement();
-      } else if (keyword == Keyword.IF) {
-        return parseIfStatement();
-      } else if (keyword == Keyword.RETHROW) {
-        return astFactory.expressionStatement(
-            parseRethrowExpression(), _expect(TokenType.SEMICOLON));
-      } else if (keyword == Keyword.RETURN) {
-        return parseReturnStatement();
-      } else if (keyword == Keyword.SWITCH) {
-        return parseSwitchStatement();
-      } else if (keyword == Keyword.THROW) {
-        return astFactory.expressionStatement(
-            parseThrowExpression(), _expect(TokenType.SEMICOLON));
-      } else if (keyword == Keyword.TRY) {
-        return parseTryStatement();
-      } else if (keyword == Keyword.WHILE) {
-        return parseWhileStatement();
-      } else if (keyword == Keyword.VAR || keyword == Keyword.FINAL) {
-        return parseVariableDeclarationStatementAfterMetadata(
-            commentAndMetadata);
-      } else if (keyword == Keyword.VOID) {
-        TypeAnnotation returnType;
-        if (_atGenericFunctionTypeAfterReturnType(_peek())) {
-          returnType = parseTypeAnnotation(false);
-        } else {
-          returnType = astFactory.typeName(
-              astFactory.simpleIdentifier(getAndAdvance()), null);
-        }
-        Token next = _currentToken.next;
-        if (_matchesIdentifier() &&
-            next.matchesAny(const <TokenType>[
-              TokenType.OPEN_PAREN,
-              TokenType.OPEN_CURLY_BRACKET,
-              TokenType.FUNCTION,
-              TokenType.LT
-            ])) {
-          return _parseFunctionDeclarationStatementAfterReturnType(
-              commentAndMetadata, returnType);
-        } else if (_matchesIdentifier() &&
-            next.matchesAny(const <TokenType>[
-              TokenType.EQ,
-              TokenType.COMMA,
-              TokenType.SEMICOLON
-            ])) {
-          return _parseVariableDeclarationStatementAfterType(
-              commentAndMetadata, null, returnType);
-        } else {
-          //
-          // We have found an error of some kind. Try to recover.
-          //
-          if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-            //
-            // We appear to have found an incomplete statement at the end of a
-            // block. Parse it as a variable declaration.
-            //
-            return _parseVariableDeclarationStatementAfterType(
-                commentAndMetadata, null, returnType);
-          }
-          _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
-          // TODO(brianwilkerson) Recover from this error.
-          return astFactory
-              .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
-        }
-      } else if (keyword == Keyword.CONST) {
-        Token next = _currentToken.next;
-        if (next.matchesAny(const <TokenType>[
-          TokenType.LT,
-          TokenType.OPEN_CURLY_BRACKET,
-          TokenType.OPEN_SQUARE_BRACKET,
-          TokenType.INDEX
-        ])) {
-          return astFactory.expressionStatement(
-              parseExpression2(), _expect(TokenType.SEMICOLON));
-        } else if (_tokenMatches(next, TokenType.IDENTIFIER)) {
-          Token afterType = skipTypeName(next);
-          if (afterType != null) {
-            if (_tokenMatches(afterType, TokenType.OPEN_PAREN) ||
-                (_tokenMatches(afterType, TokenType.PERIOD) &&
-                    _tokenMatches(afterType.next, TokenType.IDENTIFIER) &&
-                    _tokenMatches(afterType.next.next, TokenType.OPEN_PAREN))) {
-              return astFactory.expressionStatement(
-                  parseExpression2(), _expect(TokenType.SEMICOLON));
-            }
-          }
-        }
-        return parseVariableDeclarationStatementAfterMetadata(
-            commentAndMetadata);
-      } else if (keyword == Keyword.NEW ||
-          keyword == Keyword.TRUE ||
-          keyword == Keyword.FALSE ||
-          keyword == Keyword.NULL ||
-          keyword == Keyword.SUPER ||
-          keyword == Keyword.THIS) {
-        return astFactory.expressionStatement(
-            parseExpression2(), _expect(TokenType.SEMICOLON));
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
-        return astFactory
-            .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
-      }
-    } else if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      TypeAnnotation returnType = parseTypeAnnotation(false);
-      Token next = _currentToken.next;
-      if (_matchesIdentifier() &&
-          next.matchesAny(const <TokenType>[
-            TokenType.OPEN_PAREN,
-            TokenType.OPEN_CURLY_BRACKET,
-            TokenType.FUNCTION,
-            TokenType.LT
-          ])) {
-        return _parseFunctionDeclarationStatementAfterReturnType(
-            commentAndMetadata, returnType);
-      } else if (_matchesIdentifier() &&
-          next.matchesAny(const <TokenType>[
-            TokenType.EQ,
-            TokenType.COMMA,
-            TokenType.SEMICOLON
-          ])) {
-        return _parseVariableDeclarationStatementAfterType(
-            commentAndMetadata, null, returnType);
-      } else {
-        //
-        // We have found an error of some kind. Try to recover.
-        //
-        if (_matches(TokenType.CLOSE_CURLY_BRACKET)) {
-          //
-          // We appear to have found an incomplete statement at the end of a
-          // block. Parse it as a variable declaration.
-          //
-          return _parseVariableDeclarationStatementAfterType(
-              commentAndMetadata, null, returnType);
-        }
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
-        // TODO(brianwilkerson) Recover from this error.
-        return astFactory
-            .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
-      }
-    } else if (_inGenerator && _matchesKeyword(Keyword.YIELD)) {
-      return parseYieldStatement();
-    } else if (_inAsync && _matchesKeyword(Keyword.AWAIT)) {
-      if (_tokenMatchesKeyword(_peek(), Keyword.FOR)) {
-        return parseForStatement();
-      }
-      return astFactory.expressionStatement(
-          parseExpression2(), _expect(TokenType.SEMICOLON));
-    } else if (_matchesKeyword(Keyword.AWAIT) &&
-        _tokenMatchesKeyword(_peek(), Keyword.FOR)) {
-      Token awaitToken = _currentToken;
-      Statement statement = parseForStatement();
-      if (!(statement is ForStatement && statement.forLoopParts is ForParts)) {
-        _reportErrorForToken(
-            CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT, awaitToken);
-      }
-      return statement;
-    } else if (type == TokenType.SEMICOLON) {
-      return parseEmptyStatement();
-    } else if (isInitializedVariableDeclaration()) {
-      return parseVariableDeclarationStatementAfterMetadata(commentAndMetadata);
-    } else if (isFunctionDeclaration()) {
-      return parseFunctionDeclarationStatement();
-    } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_STATEMENT);
-      return astFactory
-          .emptyStatement(_createSyntheticToken(TokenType.SEMICOLON));
-    } else {
-      return astFactory.expressionStatement(
-          parseExpression2(), _expect(TokenType.SEMICOLON));
-    }
-  }
+  Expression parsePostfixExpression() => parseExpression2();
 
-  /// Parse a normal formal parameter. Return the normal formal parameter that
-  /// was parsed.
-  ///
-  ///     normalFormalParameter ::=
-  ///         functionSignature
-  ///       | fieldFormalParameter
-  ///       | simpleFormalParameter
-  ///
-  ///     functionSignature:
-  ///         metadata returnType? identifier typeParameters? formalParameterList
-  ///
-  ///     fieldFormalParameter ::=
-  ///         metadata finalConstVarOrType? 'this' '.' identifier
-  ///
-  ///     simpleFormalParameter ::=
-  ///         declaredIdentifier
-  ///       | metadata identifier
-  NormalFormalParameter parseNormalFormalParameter(
-      {bool inFunctionType = false}) {
-    Token covariantKeyword;
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    if (_matchesKeyword(Keyword.COVARIANT)) {
-      // Check to ensure that 'covariant' isn't being used as the parameter name.
-      Token next = _peek();
-      if (_tokenMatchesKeyword(next, Keyword.FINAL) ||
-          _tokenMatchesKeyword(next, Keyword.CONST) ||
-          _tokenMatchesKeyword(next, Keyword.VAR) ||
-          _tokenMatchesKeyword(next, Keyword.THIS) ||
-          _tokenMatchesKeyword(next, Keyword.VOID) ||
-          _tokenMatchesIdentifier(next)) {
-        covariantKeyword = getAndAdvance();
-      }
-    }
-    FinalConstVarOrType holder = parseFinalConstVarOrType(!inFunctionType,
-        inFunctionType: inFunctionType);
-    Token thisKeyword;
-    Token period;
-    if (_matchesKeyword(Keyword.THIS)) {
-      thisKeyword = getAndAdvance();
-      period = _expect(TokenType.PERIOD);
-    }
-    if (!_matchesIdentifier() && inFunctionType) {
-      return astFactory.simpleFormalParameter2(
-          comment: commentAndMetadata.comment,
-          metadata: commentAndMetadata.metadata,
-          covariantKeyword: covariantKeyword,
-          keyword: holder.keyword,
-          type: holder.type,
-          identifier: null);
-    }
-    SimpleIdentifier identifier = parseSimpleIdentifier();
-    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
-    if (_matches(TokenType.OPEN_PAREN)) {
-      FormalParameterList parameters = _parseFormalParameterListUnchecked();
-      if (thisKeyword == null) {
-        if (holder.keyword != null) {
-          _reportErrorForToken(
-              ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, holder.keyword);
-        }
-        return astFactory.functionTypedFormalParameter2(
-            comment: commentAndMetadata.comment,
-            metadata: commentAndMetadata.metadata,
-            covariantKeyword: covariantKeyword,
-            returnType: holder.type,
-            identifier: astFactory.simpleIdentifier(identifier.token,
-                isDeclaration: true),
-            typeParameters: typeParameters,
-            parameters: parameters);
-      } else {
-        return astFactory.fieldFormalParameter2(
-            comment: commentAndMetadata.comment,
-            metadata: commentAndMetadata.metadata,
-            covariantKeyword: covariantKeyword,
-            keyword: holder.keyword,
-            type: holder.type,
-            thisKeyword: thisKeyword,
-            period: period,
-            identifier: identifier,
-            typeParameters: typeParameters,
-            parameters: parameters);
-      }
-    } else if (typeParameters != null) {
-      // TODO(brianwilkerson) Report an error. It looks like a function-typed
-      // parameter with no parameter list.
-      //_reportErrorForToken(ParserErrorCode.MISSING_PARAMETERS, typeParameters.endToken);
-    }
-    TypeAnnotation type = holder.type;
-    if (type != null &&
-        holder.keyword != null &&
-        _tokenMatchesKeyword(holder.keyword, Keyword.VAR)) {
-      _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, holder.keyword);
-    }
-    if (thisKeyword != null) {
-      // TODO(brianwilkerson) If there are type parameters but no parameters,
-      // should we create a synthetic empty parameter list here so we can
-      // capture the type parameters?
-      return astFactory.fieldFormalParameter2(
-          comment: commentAndMetadata.comment,
-          metadata: commentAndMetadata.metadata,
-          covariantKeyword: covariantKeyword,
-          keyword: holder.keyword,
-          type: type,
-          thisKeyword: thisKeyword,
-          period: period,
-          identifier: identifier);
-    }
-    return astFactory.simpleFormalParameter2(
-        comment: commentAndMetadata.comment,
-        metadata: commentAndMetadata.metadata,
-        covariantKeyword: covariantKeyword,
-        keyword: holder.keyword,
-        type: type,
-        identifier:
-            astFactory.simpleIdentifier(identifier.token, isDeclaration: true));
-  }
+  Identifier parsePrefixedIdentifier() => parseExpression2() as Identifier;
 
-  /// Parse an operator declaration. The [commentAndMetadata] is the
-  /// documentation comment and metadata to be associated with the declaration.
-  /// The [externalKeyword] is the 'external' token. The [returnType] is the
-  /// return type that has already been parsed, or `null` if there was no return
-  /// type. Return the operator declaration that was parsed.
-  ///
-  ///     operatorDeclaration ::=
-  ///         operatorSignature (';' | functionBody)
-  ///
-  ///     operatorSignature ::=
-  ///         'external'? returnType? 'operator' operator formalParameterList
-  MethodDeclaration parseOperator(CommentAndMetadata commentAndMetadata,
-      Token externalKeyword, TypeName returnType) {
-    Token operatorKeyword;
-    if (_matchesKeyword(Keyword.OPERATOR)) {
-      operatorKeyword = getAndAdvance();
-    } else {
-      _reportErrorForToken(
-          ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken);
-      operatorKeyword = _createSyntheticKeyword(Keyword.OPERATOR);
-    }
-    return _parseOperatorAfterKeyword(
-        commentAndMetadata, externalKeyword, returnType, operatorKeyword);
-  }
-
-  /// Parse a part or part-of directive. The [commentAndMetadata] is the
-  /// metadata to be associated with the directive. Return the part or part-of
-  /// directive that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.PART`.
-  ///
-  ///     partDirective ::=
-  ///         metadata 'part' stringLiteral ';'
-  ///
-  ///     partOfDirective ::=
-  ///         metadata 'part' 'of' identifier ';'
-  Directive parsePartOrPartOfDirective(CommentAndMetadata commentAndMetadata) {
-    if (_tokenMatchesKeyword(_peek(), Keyword.OF)) {
-      return _parsePartOfDirective(commentAndMetadata);
-    }
-    return _parsePartDirective(commentAndMetadata);
-  }
-
-  /// Parse a postfix expression. Return the postfix expression that was parsed.
-  ///
-  ///     postfixExpression ::=
-  ///         assignableExpression postfixOperator
-  ///       | primary selector*
-  ///
-  ///     selector ::=
-  ///         assignableSelector
-  ///       | argumentPart
-  Expression parsePostfixExpression() {
-    Expression operand = parseAssignableExpression(true);
-    TokenType type = _currentToken.type;
-    if (type == TokenType.OPEN_SQUARE_BRACKET ||
-        type == TokenType.PERIOD ||
-        type == TokenType.QUESTION_PERIOD ||
-        type == TokenType.OPEN_PAREN ||
-        type == TokenType.LT ||
-        type == TokenType.INDEX) {
-      do {
-        if (_isLikelyArgumentList()) {
-          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-          ArgumentList argumentList = parseArgumentList();
-          Expression currentOperand = operand;
-          if (currentOperand is PropertyAccess) {
-            operand = astFactory.methodInvocation(
-                currentOperand.target,
-                currentOperand.operator,
-                currentOperand.propertyName,
-                typeArguments,
-                argumentList);
-          } else {
-            operand = astFactory.functionExpressionInvocation(
-                operand, typeArguments, argumentList);
-          }
-        } else if (enableOptionalNewAndConst &&
-            operand is Identifier &&
-            _isLikelyNamedInstanceCreation()) {
-          TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-          Token period = _expect(TokenType.PERIOD);
-          SimpleIdentifier name = parseSimpleIdentifier();
-          ArgumentList argumentList = parseArgumentList();
-          TypeName typeName = astFactory.typeName(operand, typeArguments);
-          operand = astFactory.instanceCreationExpression(null,
-              astFactory.constructorName(typeName, period, name), argumentList);
-        } else {
-          operand = parseAssignableSelector(operand, true);
-        }
-        type = _currentToken.type;
-      } while (type == TokenType.OPEN_SQUARE_BRACKET ||
-          type == TokenType.PERIOD ||
-          type == TokenType.QUESTION_PERIOD ||
-          type == TokenType.OPEN_PAREN ||
-          type == TokenType.INDEX);
-      return operand;
-    }
-    if (!_currentToken.type.isIncrementOperator) {
-      return operand;
-    }
-    _ensureAssignable(operand);
-    Token operator = getAndAdvance();
-    return astFactory.postfixExpression(operand, operator);
-  }
-
-  /// Parse a prefixed identifier. Return the prefixed identifier that was
-  /// parsed.
-  ///
-  ///     prefixedIdentifier ::=
-  ///         identifier ('.' identifier)?
-  Identifier parsePrefixedIdentifier() {
-    return _parsePrefixedIdentifierAfterIdentifier(parseSimpleIdentifier());
-  }
-
-  /// Parse a primary expression. Return the primary expression that was parsed.
-  ///
-  ///     primary ::=
-  ///         thisExpression
-  ///       | 'super' unconditionalAssignableSelector
-  ///       | functionExpression
-  ///       | literal
-  ///       | identifier
-  ///       | newExpression
-  ///       | constObjectExpression
-  ///       | '(' expression ')'
-  ///       | argumentDefinitionTest
-  ///
-  ///     literal ::=
-  ///         nullLiteral
-  ///       | booleanLiteral
-  ///       | numericLiteral
-  ///       | stringLiteral
-  ///       | symbolLiteral
-  ///       | mapLiteral
-  ///       | listLiteral
   Expression parsePrimaryExpression() {
-    if (_matchesIdentifier()) {
-      // TODO(brianwilkerson) The code below was an attempt to recover from an
-      // error case, but it needs to be applied as a recovery only after we
-      // know that parsing it as an identifier doesn't work. Leaving the code as
-      // a reminder of how to recover.
-//      if (isFunctionExpression(_peek())) {
-//        //
-//        // Function expressions were allowed to have names at one point, but this is now illegal.
-//        //
-//        reportError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, getAndAdvance());
-//        return parseFunctionExpression();
-//      }
-      return _parsePrefixedIdentifierUnchecked();
-    }
-    TokenType type = _currentToken.type;
-    if (type == TokenType.STRING) {
-      return parseStringLiteral();
-    } else if (type == TokenType.INT) {
-      Token token = getAndAdvance();
-      int value;
-      try {
-        value = int.parse(token.lexeme);
-      } on FormatException {
-        // The invalid format should have been reported by the scanner.
-      }
-      return astFactory.integerLiteral(token, value);
-    }
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.NULL) {
-      return astFactory.nullLiteral(getAndAdvance());
-    } else if (keyword == Keyword.NEW) {
-      return parseNewExpression();
-    } else if (keyword == Keyword.THIS) {
-      return astFactory.thisExpression(getAndAdvance());
-    } else if (keyword == Keyword.SUPER) {
-      return parseAssignableSelector(
-          astFactory.superExpression(getAndAdvance()), false,
-          allowConditional: false);
-    } else if (keyword == Keyword.FALSE) {
-      return astFactory.booleanLiteral(getAndAdvance(), false);
-    } else if (keyword == Keyword.TRUE) {
-      return astFactory.booleanLiteral(getAndAdvance(), true);
-    }
-    if (type == TokenType.DOUBLE) {
-      Token token = getAndAdvance();
-      double value = 0.0;
-      try {
-        value = double.parse(token.lexeme);
-      } on FormatException {
-        // The invalid format should have been reported by the scanner.
-      }
-      return astFactory.doubleLiteral(token, value);
-    } else if (type == TokenType.HEXADECIMAL) {
-      Token token = getAndAdvance();
-      int value;
-      try {
-        value = int.parse(token.lexeme);
-      } on FormatException {
-        // The invalid format should have been reported by the scanner.
-      }
-      return astFactory.integerLiteral(token, value);
-    } else if (keyword == Keyword.CONST) {
-      return parseConstExpression();
-    } else if (type == TokenType.OPEN_PAREN) {
-      if (isFunctionExpression(_currentToken)) {
-        return parseFunctionExpression();
-      }
-      Token leftParenthesis = getAndAdvance();
-      bool wasInInitializer = _inInitializer;
-      _inInitializer = false;
-      try {
-        Expression expression = parseExpression2();
-        Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-        return astFactory.parenthesizedExpression(
-            leftParenthesis, expression, rightParenthesis);
-      } finally {
-        _inInitializer = wasInInitializer;
-      }
-    } else if (type == TokenType.LT) {
-      if (isFunctionExpression(currentToken)) {
-        return parseFunctionExpression();
-      }
-      return parseListOrMapLiteral(null);
-    } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-      return parseMapLiteral(null, null);
-    } else if (type == TokenType.OPEN_SQUARE_BRACKET ||
-        type == TokenType.INDEX) {
-      return parseListLiteral(null, null);
-    } else if (type == TokenType.QUESTION &&
-        _tokenMatches(_peek(), TokenType.IDENTIFIER)) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
-      _advance();
-      return parsePrimaryExpression();
-    } else if (keyword == Keyword.VOID) {
-      //
-      // Recover from having a return type of "void" where a return type is not
-      // expected.
-      //
-      // TODO(brianwilkerson) Improve this error message.
-      _reportErrorForCurrentToken(
-          ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
-      _advance();
-      return parsePrimaryExpression();
-    } else if (type == TokenType.HASH) {
-      return parseSymbolLiteral();
-    } else {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-      return createSyntheticIdentifier();
-    }
+    currentToken = fastaParser
+        .parsePrimary(fastaParser.syntheticPreviousToken(currentToken),
+            fasta.IdentifierContext.expression)
+        .next;
+    return astBuilder.pop() as Expression;
   }
 
-  /// Parse a redirecting constructor invocation. The flag [hasPeriod] should be
-  /// `true` if the `this` is followed by a period. Return the redirecting
-  /// constructor invocation that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.THIS`.
-  ///
-  ///     redirectingConstructorInvocation ::=
-  ///         'this' ('.' identifier)? arguments
-  RedirectingConstructorInvocation parseRedirectingConstructorInvocation(
-      bool hasPeriod) {
-    Token keyword = getAndAdvance();
-    Token period;
-    SimpleIdentifier constructorName;
-    if (hasPeriod) {
-      period = getAndAdvance();
-      if (_matchesIdentifier()) {
-        constructorName = _parseSimpleIdentifierUnchecked(isDeclaration: false);
-      } else {
-        _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-        constructorName = createSyntheticIdentifier(isDeclaration: false);
-        _advance();
-      }
-    }
-    ArgumentList argumentList = _parseArgumentListChecked();
-    return astFactory.redirectingConstructorInvocation(
-        keyword, period, constructorName, argumentList);
-  }
+  Expression parseRelationalExpression() => parseExpression2();
 
-  /// Parse a relational expression. Return the relational expression that was
-  /// parsed.
-  ///
-  ///     relationalExpression ::=
-  ///         bitwiseOrExpression ('is' '!'? type | 'as' type | relationalOperator bitwiseOrExpression)?
-  ///       | 'super' relationalOperator bitwiseOrExpression
-  Expression parseRelationalExpression() {
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isRelationalOperator) {
-      Expression expression = astFactory.superExpression(getAndAdvance());
-      Token operator = getAndAdvance();
-      return astFactory.binaryExpression(
-          expression, operator, parseBitwiseOrExpression());
-    }
-    Expression expression = parseBitwiseOrExpression();
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.AS) {
-      Token asOperator = getAndAdvance();
-      return astFactory.asExpression(
-          expression, asOperator, parseTypeNotVoid(true));
-    } else if (keyword == Keyword.IS) {
-      Token isOperator = getAndAdvance();
-      Token notOperator;
-      if (_matches(TokenType.BANG)) {
-        notOperator = getAndAdvance();
-      }
-      TypeAnnotation type = parseTypeNotVoid(true);
-      return astFactory.isExpression(expression, isOperator, notOperator, type);
-    } else if (_currentToken.type.isRelationalOperator) {
-      Token operator = getAndAdvance();
-      return astFactory.binaryExpression(
-          expression, operator, parseBitwiseOrExpression());
-    }
-    return expression;
-  }
+  Expression parseRethrowExpression() => parseExpression2();
 
-  /// Parse a rethrow expression. Return the rethrow expression that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.RETHROW`.
-  ///
-  ///     rethrowExpression ::=
-  ///         'rethrow'
-  Expression parseRethrowExpression() =>
-      astFactory.rethrowExpression(getAndAdvance());
+  Expression parseShiftExpression() => parseExpression2();
 
-  /// Parse a return statement. Return the return statement that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.RETURN`.
-  ///
-  ///     returnStatement ::=
-  ///         'return' expression? ';'
-  Statement parseReturnStatement() {
-    Token returnKeyword = getAndAdvance();
-    if (_matches(TokenType.SEMICOLON)) {
-      return astFactory.returnStatement(returnKeyword, null, getAndAdvance());
-    }
-    Expression expression = parseExpression2();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.returnStatement(returnKeyword, expression, semicolon);
-  }
-
-  /// Parse a setter. The [commentAndMetadata] is the documentation comment and
-  /// metadata to be associated with the declaration. The [externalKeyword] is
-  /// the 'external' token. The [staticKeyword] is the static keyword, or `null`
-  /// if the setter is not static. The [returnType] is the return type that has
-  /// already been parsed, or `null` if there was no return type. Return the
-  /// setter that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.SET`.
-  ///
-  ///     setter ::=
-  ///         setterSignature functionBody?
-  ///
-  ///     setterSignature ::=
-  ///         'external'? 'static'? returnType? 'set' identifier formalParameterList
-  MethodDeclaration parseSetter(CommentAndMetadata commentAndMetadata,
-      Token externalKeyword, Token staticKeyword, TypeAnnotation returnType) {
-    Token propertyKeyword = getAndAdvance();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    FormalParameterList parameters = parseFormalParameterList();
-    _validateFormalParameterList(parameters);
-    FunctionBody body = parseFunctionBody(
-        externalKeyword != null || staticKeyword == null,
-        ParserErrorCode.STATIC_SETTER_WITHOUT_BODY,
-        false);
-    if (externalKeyword != null && body is! EmptyFunctionBody) {
-      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_SETTER_WITH_BODY);
-    }
-    return astFactory.methodDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        staticKeyword,
-        returnType,
-        propertyKeyword,
-        null,
-        name,
-        null,
-        parameters,
-        body);
-  }
-
-  /// Parse a shift expression. Return the shift expression that was parsed.
-  ///
-  ///     shiftExpression ::=
-  ///         additiveExpression (shiftOperator additiveExpression)*
-  ///       | 'super' (shiftOperator additiveExpression)+
-  Expression parseShiftExpression() {
-    Expression expression;
-    if (_currentToken.keyword == Keyword.SUPER &&
-        _currentToken.next.type.isShiftOperator) {
-      expression = astFactory.superExpression(getAndAdvance());
-    } else {
-      expression = parseAdditiveExpression();
-    }
-    while (_currentToken.type.isShiftOperator) {
-      expression = astFactory.binaryExpression(
-          expression, getAndAdvance(), parseAdditiveExpression());
-    }
-    return expression;
-  }
-
-  /// Parse a simple identifier. Return the simple identifier that was parsed.
-  ///
-  ///     identifier ::=
-  ///         IDENTIFIER
   SimpleIdentifier parseSimpleIdentifier(
-      {bool allowKeyword = false, bool isDeclaration = false}) {
-    if (_matchesIdentifier() ||
-        (allowKeyword && _tokenMatchesIdentifierOrKeyword(_currentToken))) {
-      return _parseSimpleIdentifierUnchecked(isDeclaration: isDeclaration);
-    }
-    _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-    return createSyntheticIdentifier(isDeclaration: isDeclaration);
-  }
+          {bool allowKeyword = false, bool isDeclaration = false}) =>
+      parseExpression2() as SimpleIdentifier;
 
-  /// Parse a statement, starting with the given [token]. Return the statement
-  /// that was parsed, or `null` if the tokens do not represent a recognizable
-  /// statement.
   Statement parseStatement(Token token) {
-    _currentToken = token;
+    currentToken = token;
     return parseStatement2();
   }
 
-  /// Parse a statement. Return the statement that was parsed.
-  ///
-  ///     statement ::=
-  ///         label* nonLabeledStatement
   Statement parseStatement2() {
-    if (_treeDepth > _MAX_TREE_DEPTH) {
-      throw _TooDeepTreeError();
-    }
-    _treeDepth++;
-    try {
-      List<Label> labels;
-      while (
-          _matchesIdentifier() && _currentToken.next.type == TokenType.COLON) {
-        Label label = parseLabel(isDeclaration: true);
-        if (labels == null) {
-          labels = <Label>[label];
-        } else {
-          labels.add(label);
-        }
-      }
-      Statement statement = parseNonLabeledStatement();
-      if (labels == null) {
-        return statement;
-      }
-      return astFactory.labeledStatement(labels, statement);
-    } finally {
-      _treeDepth--;
-    }
+    currentToken = fastaParser
+        .parseStatement(fastaParser.syntheticPreviousToken(currentToken))
+        .next;
+    return astBuilder.pop() as Statement;
   }
 
-  /// Parse a sequence of statements, starting with the given [token]. Return
-  /// the statements that were parsed, or `null` if the tokens do not represent
-  /// a recognizable sequence of statements.
-  List<Statement> parseStatements(Token token) {
-    _currentToken = token;
-    return _parseStatementList();
+  StringLiteral parseStringLiteral() => parseExpression2() as StringLiteral;
+
+  SymbolLiteral parseSymbolLiteral() => parseExpression2() as SymbolLiteral;
+
+  Expression parseThrowExpression() => parseExpression2();
+
+  Expression parseThrowExpressionWithoutCascade() => parseExpression2();
+
+  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
+    currentToken = fastaParser.parseTopLevelDeclaration(currentToken);
+    return (isDirective ? astBuilder.directives : astBuilder.declarations)
+        .removeLast();
   }
 
-  /// Parse a string literal. Return the string literal that was parsed.
-  ///
-  ///     stringLiteral ::=
-  ///         MULTI_LINE_STRING+
-  ///       | SINGLE_LINE_STRING+
-  StringLiteral parseStringLiteral() {
-    if (_matches(TokenType.STRING)) {
-      return _parseStringLiteralUnchecked();
-    }
-    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_STRING_LITERAL);
-    return createSyntheticStringLiteral();
-  }
-
-  /// Parse a super constructor invocation. Return the super constructor
-  /// invocation that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.SUPER].
-  ///
-  ///     superConstructorInvocation ::=
-  ///         'super' ('.' identifier)? arguments
-  SuperConstructorInvocation parseSuperConstructorInvocation() {
-    Token keyword = getAndAdvance();
-    Token period;
-    SimpleIdentifier constructorName;
-    if (_matches(TokenType.PERIOD)) {
-      period = getAndAdvance();
-      constructorName = parseSimpleIdentifier();
-    }
-    ArgumentList argumentList = _parseArgumentListChecked();
-    return astFactory.superConstructorInvocation(
-        keyword, period, constructorName, argumentList);
-  }
-
-  /// Parse a switch statement. Return the switch statement that was parsed.
-  ///
-  ///     switchStatement ::=
-  ///         'switch' '(' expression ')' '{' switchCase* defaultCase? '}'
-  ///
-  ///     switchCase ::=
-  ///         label* ('case' expression ':') statements
-  ///
-  ///     defaultCase ::=
-  ///         label* 'default' ':' statements
-  SwitchStatement parseSwitchStatement() {
-    bool wasInSwitch = _inSwitch;
-    _inSwitch = true;
-    try {
-      HashSet<String> definedLabels = HashSet<String>();
-      Token keyword = _expectKeyword(Keyword.SWITCH);
-      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-      Expression expression = parseExpression2();
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      Token leftBracket = _expect(TokenType.OPEN_CURLY_BRACKET);
-      Token defaultKeyword;
-      List<SwitchMember> members = <SwitchMember>[];
-      TokenType type = _currentToken.type;
-      while (type != TokenType.EOF && type != TokenType.CLOSE_CURLY_BRACKET) {
-        List<Label> labels = <Label>[];
-        while (
-            _matchesIdentifier() && _tokenMatches(_peek(), TokenType.COLON)) {
-          SimpleIdentifier identifier =
-              _parseSimpleIdentifierUnchecked(isDeclaration: true);
-          String label = identifier.token.lexeme;
-          if (definedLabels.contains(label)) {
-            _reportErrorForToken(
-                ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT,
-                identifier.token,
-                [label]);
-          } else {
-            definedLabels.add(label);
-          }
-          Token colon = getAndAdvance();
-          labels.add(astFactory.label(identifier, colon));
-        }
-        Keyword keyword = _currentToken.keyword;
-        if (keyword == Keyword.CASE) {
-          Token caseKeyword = getAndAdvance();
-          Expression caseExpression = parseExpression2();
-          Token colon = _expect(TokenType.COLON);
-          members.add(astFactory.switchCase(labels, caseKeyword, caseExpression,
-              colon, _parseStatementList()));
-          if (defaultKeyword != null) {
-            _reportErrorForToken(
-                ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
-                caseKeyword);
-          }
-        } else if (keyword == Keyword.DEFAULT) {
-          if (defaultKeyword != null) {
-            _reportErrorForToken(
-                ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, _peek());
-          }
-          defaultKeyword = getAndAdvance();
-          Token colon = _expect(TokenType.COLON);
-          members.add(astFactory.switchDefault(
-              labels, defaultKeyword, colon, _parseStatementList()));
-        } else {
-          // We need to advance, otherwise we could end up in an infinite loop,
-          // but this could be a lot smarter about recovering from the error.
-          _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT);
-          bool atEndOrNextMember() {
-            TokenType type = _currentToken.type;
-            if (type == TokenType.EOF ||
-                type == TokenType.CLOSE_CURLY_BRACKET) {
-              return true;
-            }
-            Keyword keyword = _currentToken.keyword;
-            return keyword == Keyword.CASE || keyword == Keyword.DEFAULT;
-          }
-
-          while (!atEndOrNextMember()) {
-            _advance();
-          }
-        }
-        type = _currentToken.type;
-      }
-      Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-      return astFactory.switchStatement(keyword, leftParenthesis, expression,
-          rightParenthesis, leftBracket, members, rightBracket);
-    } finally {
-      _inSwitch = wasInSwitch;
-    }
-  }
-
-  /// Parse a symbol literal. Return the symbol literal that was parsed.
-  ///
-  /// This method assumes that the current token matches [TokenType.HASH].
-  ///
-  ///     symbolLiteral ::=
-  ///         '#' identifier ('.' identifier)*
-  SymbolLiteral parseSymbolLiteral() {
-    Token poundSign = getAndAdvance();
-    List<Token> components = <Token>[];
-    if (_matchesIdentifier()) {
-      components.add(getAndAdvance());
-      while (_optional(TokenType.PERIOD)) {
-        if (_matchesIdentifier()) {
-          components.add(getAndAdvance());
-        } else {
-          _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-          components.add(_createSyntheticToken(TokenType.IDENTIFIER));
-          break;
-        }
-      }
-    } else if (_currentToken.isOperator) {
-      components.add(getAndAdvance());
-    } else if (_matchesKeyword(Keyword.VOID)) {
-      components.add(getAndAdvance());
-    } else {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-      components.add(_createSyntheticToken(TokenType.IDENTIFIER));
-    }
-    return astFactory.symbolLiteral(poundSign, components);
-  }
-
-  /// Parse a throw expression. Return the throw expression that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.THROW].
-  ///
-  ///     throwExpression ::=
-  ///         'throw' expression
-  Expression parseThrowExpression() {
-    Token keyword = getAndAdvance();
-    TokenType type = _currentToken.type;
-    if (type == TokenType.SEMICOLON || type == TokenType.CLOSE_PAREN) {
-      _reportErrorForToken(
-          ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
-      return astFactory.throwExpression(keyword, createSyntheticIdentifier());
-    }
-    Expression expression = parseExpression2();
-    return astFactory.throwExpression(keyword, expression);
-  }
-
-  /// Parse a throw expression. Return the throw expression that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.THROW].
-  ///
-  ///     throwExpressionWithoutCascade ::=
-  ///         'throw' expressionWithoutCascade
-  Expression parseThrowExpressionWithoutCascade() {
-    Token keyword = getAndAdvance();
-    TokenType type = _currentToken.type;
-    if (type == TokenType.SEMICOLON || type == TokenType.CLOSE_PAREN) {
-      _reportErrorForToken(
-          ParserErrorCode.MISSING_EXPRESSION_IN_THROW, _currentToken);
-      return astFactory.throwExpression(keyword, createSyntheticIdentifier());
-    }
-    Expression expression = parseExpressionWithoutCascade();
-    return astFactory.throwExpression(keyword, expression);
-  }
-
-  /// Parse a try statement. Return the try statement that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.TRY].
-  ///
-  ///     tryStatement ::=
-  ///         'try' block (onPart+ finallyPart? | finallyPart)
-  ///
-  ///     onPart ::=
-  ///         catchPart block
-  ///       | 'on' type catchPart? block
-  ///
-  ///     catchPart ::=
-  ///         'catch' '(' identifier (',' identifier)? ')'
-  ///
-  ///     finallyPart ::=
-  ///         'finally' block
-  Statement parseTryStatement() {
-    Token tryKeyword = getAndAdvance();
-    Block body = _parseBlockChecked();
-    List<CatchClause> catchClauses = <CatchClause>[];
-    Block finallyClause;
-    while (_matchesKeyword(Keyword.ON) || _matchesKeyword(Keyword.CATCH)) {
-      Token onKeyword;
-      TypeName exceptionType;
-      if (_matchesKeyword(Keyword.ON)) {
-        onKeyword = getAndAdvance();
-        exceptionType = parseTypeNotVoid(false);
-      }
-      Token catchKeyword;
-      Token leftParenthesis;
-      SimpleIdentifier exceptionParameter;
-      Token comma;
-      SimpleIdentifier stackTraceParameter;
-      Token rightParenthesis;
-      if (_matchesKeyword(Keyword.CATCH)) {
-        catchKeyword = getAndAdvance();
-        leftParenthesis = _expect(TokenType.OPEN_PAREN);
-        exceptionParameter = parseSimpleIdentifier(isDeclaration: true);
-        if (_matches(TokenType.COMMA)) {
-          comma = getAndAdvance();
-          stackTraceParameter = parseSimpleIdentifier(isDeclaration: true);
-        }
-        rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      }
-      Block catchBody = _parseBlockChecked();
-      catchClauses.add(astFactory.catchClause(
-          onKeyword,
-          exceptionType,
-          catchKeyword,
-          leftParenthesis,
-          exceptionParameter,
-          comma,
-          stackTraceParameter,
-          rightParenthesis,
-          catchBody));
-    }
-    Token finallyKeyword;
-    if (_matchesKeyword(Keyword.FINALLY)) {
-      finallyKeyword = getAndAdvance();
-      finallyClause = _parseBlockChecked();
-    } else if (catchClauses.isEmpty) {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_CATCH_OR_FINALLY);
-    }
-    return astFactory.tryStatement(
-        tryKeyword, body, catchClauses, finallyKeyword, finallyClause);
-  }
-
-  /// Parse a type alias. The [commentAndMetadata] is the metadata to be
-  /// associated with the member. Return the type alias that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.TYPEDEF].
-  ///
-  ///     typeAlias ::=
-  ///         'typedef' typeAliasBody
-  ///       | genericTypeAlias
-  ///
-  ///     typeAliasBody ::=
-  ///         functionTypeAlias
-  ///
-  ///     functionTypeAlias ::=
-  ///         functionPrefix typeParameterList? formalParameterList ';'
-  ///
-  ///     functionPrefix ::=
-  ///         returnType? name
-  TypeAlias parseTypeAlias(CommentAndMetadata commentAndMetadata) {
-    Token keyword = getAndAdvance();
-    if (_matchesIdentifier()) {
-      Token next = _peek();
-      if (_tokenMatches(next, TokenType.LT)) {
-        next = _skipTypeParameterList(next);
-        if (next != null && _tokenMatches(next, TokenType.EQ)) {
-          TypeAlias typeAlias =
-              parseGenericTypeAlias(commentAndMetadata, keyword);
-          return typeAlias;
-        }
-      } else if (_tokenMatches(next, TokenType.EQ)) {
-        TypeAlias typeAlias =
-            parseGenericTypeAlias(commentAndMetadata, keyword);
-        return typeAlias;
-      }
-    }
-    return _parseFunctionTypeAlias(commentAndMetadata, keyword);
-  }
-
-  /// Parse a type.
-  ///
-  ///     type ::=
-  ///         typeWithoutFunction
-  ///       | functionType
   TypeAnnotation parseTypeAnnotation(bool inExpression) {
-    TypeAnnotation type;
-    if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      // Generic function type with no return type.
-      type = parseGenericFunctionTypeAfterReturnType(null);
-    } else {
-      type = parseTypeWithoutFunction(inExpression);
-    }
-    while (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      type = parseGenericFunctionTypeAfterReturnType(type);
-    }
-    return type;
+    Token previous = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeType(previous, true, !inExpression)
+        .parseType(previous, fastaParser)
+        .next;
+    return astBuilder.pop() as TypeAnnotation;
   }
 
-  /// Parse a list of type arguments. Return the type argument list that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.LT`.
-  ///
-  ///     typeArguments ::=
-  ///         '<' typeList '>'
-  ///
-  ///     typeList ::=
-  ///         type (',' type)*
   TypeArgumentList parseTypeArgumentList() {
-    Token leftBracket = getAndAdvance();
-    List<TypeAnnotation> arguments = <TypeAnnotation>[
-      parseTypeAnnotation(false)
-    ];
-    while (_optional(TokenType.COMMA)) {
-      arguments.add(parseTypeAnnotation(false));
-    }
-    Token rightBracket = _expectGt();
-    return astFactory.typeArgumentList(leftBracket, arguments, rightBracket);
+    Token previous = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeTypeParamOrArg(previous)
+        .parseArguments(previous, fastaParser)
+        .next;
+    return astBuilder.pop() as TypeArgumentList;
   }
 
-  /// Parse a type which is not void and is not a function type. Return the type
-  /// that was parsed.
-  ///
-  ///     typeNotVoidWithoutFunction ::=
-  ///         qualified typeArguments?
-  // TODO(eernst): Rename this to `parseTypeNotVoidWithoutFunction`?
-  // Apparently,  it was named `parseTypeName` before type arguments existed.
   TypeName parseTypeName(bool inExpression) {
-    return _parseTypeName(inExpression);
+    Token previous = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeType(previous, true, !inExpression)
+        .parseType(previous, fastaParser)
+        .next;
+    return astBuilder.pop() as TypeName;
   }
 
-  /// Parse a type which is not `void`.
-  ///
-  ///     typeNotVoid ::=
-  ///         functionType
-  ///       | typeNotVoidWithoutFunction
-  TypeAnnotation parseTypeNotVoid(bool inExpression) {
-    TypeAnnotation type;
-    if (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      // Generic function type with no return type.
-      type = parseGenericFunctionTypeAfterReturnType(null);
-    } else if (_currentToken.keyword == Keyword.VOID &&
-        _atGenericFunctionTypeAfterReturnType(_currentToken.next)) {
-      type = astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
-    } else {
-      type = parseTypeName(inExpression);
-    }
-    while (_atGenericFunctionTypeAfterReturnType(_currentToken)) {
-      type = parseGenericFunctionTypeAfterReturnType(type);
-    }
-    return type;
-  }
-
-  /// Parse a type parameter. Return the type parameter that was parsed.
-  ///
-  ///     typeParameter ::=
-  ///         metadata name ('extends' bound)?
   TypeParameter parseTypeParameter() {
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    if (_matchesKeyword(Keyword.EXTENDS)) {
-      Token keyword = getAndAdvance();
-      TypeAnnotation bound = parseTypeNotVoid(false);
-      return astFactory.typeParameter(commentAndMetadata.comment,
-          commentAndMetadata.metadata, name, keyword, bound);
-    }
-    return astFactory.typeParameter(commentAndMetadata.comment,
-        commentAndMetadata.metadata, name, null, null);
+    currentToken = SyntheticBeginToken(TokenType.LT, 0)
+      ..endGroup = SyntheticToken(TokenType.GT, 0)
+      ..setNext(currentToken);
+    appendToken(currentToken, currentToken.endGroup);
+    TypeParameterList typeParams = parseTypeParameterList();
+    return typeParams.typeParameters[0];
   }
 
-  /// Parse a list of type parameters. Return the list of type parameters that
-  /// were parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.LT`.
-  ///
-  ///     typeParameterList ::=
-  ///         '<' typeParameter (',' typeParameter)* '>'
   TypeParameterList parseTypeParameterList() {
-    Token leftBracket = getAndAdvance();
-    List<TypeParameter> typeParameters = <TypeParameter>[parseTypeParameter()];
-    while (_optional(TokenType.COMMA)) {
-      typeParameters.add(parseTypeParameter());
-    }
-    Token rightBracket = _expectGt();
-    return astFactory.typeParameterList(
-        leftBracket, typeParameters, rightBracket);
+    Token token = fastaParser.syntheticPreviousToken(currentToken);
+    currentToken = fasta
+        .computeTypeParamOrArg(token, true)
+        .parseVariables(token, fastaParser)
+        .next;
+    return astBuilder.pop() as TypeParameterList;
   }
 
-  /// Parse a type which is not a function type.
-  ///
-  ///     typeWithoutFunction ::=
-  ///         `void`
-  ///       | typeNotVoidWithoutFunction
-  TypeAnnotation parseTypeWithoutFunction(bool inExpression) {
-    if (_currentToken.keyword == Keyword.VOID) {
-      return astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
-    } else {
-      return parseTypeName(inExpression);
-    }
-  }
-
-  /// Parse a unary expression. Return the unary expression that was parsed.
-  ///
-  ///     unaryExpression ::=
-  ///         prefixOperator unaryExpression
-  ///       | awaitExpression
-  ///       | postfixExpression
-  ///       | unaryOperator 'super'
-  ///       | '-' 'super'
-  ///       | incrementOperator assignableExpression
-  Expression parseUnaryExpression() {
-    TokenType type = _currentToken.type;
-    if (type == TokenType.MINUS ||
-        type == TokenType.BANG ||
-        type == TokenType.TILDE) {
-      Token operator = getAndAdvance();
-      if (_matchesKeyword(Keyword.SUPER)) {
-        TokenType nextType = _peek().type;
-        if (nextType == TokenType.OPEN_SQUARE_BRACKET ||
-            nextType == TokenType.PERIOD) {
-          //     "prefixOperator unaryExpression"
-          // --> "prefixOperator postfixExpression"
-          // --> "prefixOperator primary                    selector*"
-          // --> "prefixOperator 'super' assignableSelector selector*"
-          return astFactory.prefixExpression(operator, parseUnaryExpression());
-        }
-        return astFactory.prefixExpression(
-            operator, astFactory.superExpression(getAndAdvance()));
-      }
-      return astFactory.prefixExpression(operator, parseUnaryExpression());
-    } else if (_currentToken.type.isIncrementOperator) {
-      Token operator = getAndAdvance();
-      if (_matchesKeyword(Keyword.SUPER)) {
-        TokenType nextType = _peek().type;
-        if (nextType == TokenType.OPEN_SQUARE_BRACKET ||
-            nextType == TokenType.PERIOD) {
-          // --> "prefixOperator 'super' assignableSelector selector*"
-          return astFactory.prefixExpression(operator, parseUnaryExpression());
-        }
-        //
-        // Even though it is not valid to use an incrementing operator
-        // ('++' or '--') before 'super', we can (and therefore must) interpret
-        // "--super" as semantically equivalent to "-(-super)". Unfortunately,
-        // we cannot do the same for "++super" because "+super" is also not
-        // valid.
-        //
-        if (type == TokenType.MINUS_MINUS) {
-          Token firstOperator = _createToken(operator, TokenType.MINUS);
-          Token secondOperator = Token(TokenType.MINUS, operator.offset + 1);
-          secondOperator.setNext(_currentToken);
-          firstOperator.setNext(secondOperator);
-          operator.previous.setNext(firstOperator);
-          return astFactory.prefixExpression(
-              firstOperator,
-              astFactory.prefixExpression(
-                  secondOperator, astFactory.superExpression(getAndAdvance())));
-        }
-        // Invalid operator before 'super'
-        _reportErrorForCurrentToken(
-            ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, [operator.lexeme]);
-        return astFactory.prefixExpression(
-            operator, astFactory.superExpression(getAndAdvance()));
-      }
-      return astFactory.prefixExpression(
-          operator, parseAssignableExpression(false));
-    } else if (type == TokenType.PLUS) {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_IDENTIFIER);
-      return createSyntheticIdentifier();
-    } else if (_inAsync && _matchesKeyword(Keyword.AWAIT)) {
-      return parseAwaitExpression();
-    }
-    return parsePostfixExpression();
-  }
-
-  /// Parse a variable declaration. Return the variable declaration that was
-  /// parsed.
-  ///
-  ///     variableDeclaration ::=
-  ///         identifier ('=' expression)?
-  VariableDeclaration parseVariableDeclaration() {
-    // TODO(paulberry): prior to the fix for bug 23204, we permitted
-    // annotations before variable declarations (e.g. "String @deprecated s;").
-    // Although such constructions are prohibited by the spec, we may want to
-    // consider handling them anyway to allow for better parser recovery in the
-    // event that the user erroneously tries to use them.  However, as a
-    // counterargument, this would likely degrade parser recovery in the event
-    // of a construct like "class C { int @deprecated foo() {} }" (i.e. the
-    // user is in the middle of inserting "int bar;" prior to
-    // "@deprecated foo() {}").
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    Token equals;
-    Expression initializer;
-    if (_matches(TokenType.EQ)) {
-      equals = getAndAdvance();
-      initializer = parseExpression2();
-    }
-    return astFactory.variableDeclaration(name, equals, initializer);
-  }
-
-  /// Parse a variable declaration list. The [commentAndMetadata] is the
-  /// metadata to be associated with the variable declaration list. Return the
-  /// variable declaration list that was parsed.
-  ///
-  ///     variableDeclarationList ::=
-  ///         finalConstVarOrType variableDeclaration (',' variableDeclaration)*
-  VariableDeclarationList parseVariableDeclarationListAfterMetadata(
-      CommentAndMetadata commentAndMetadata) {
-    FinalConstVarOrType holder = parseFinalConstVarOrType(false);
-    return parseVariableDeclarationListAfterType(
-        commentAndMetadata, holder.keyword, holder.type);
-  }
-
-  /// Parse a variable declaration list. The [commentAndMetadata] is the
-  /// metadata to be associated with the variable declaration list, or `null`
-  /// if there is no attempt at parsing the comment and metadata. The [keyword]
-  /// is the token representing the 'final', 'const' or 'var' keyword, or
-  /// `null` if there is no keyword. The [type] is the type of the variables in
-  /// the list. Return the variable declaration list that was parsed.
-  ///
-  ///     variableDeclarationList ::=
-  ///         finalConstVarOrType variableDeclaration (',' variableDeclaration)*
-  VariableDeclarationList parseVariableDeclarationListAfterType(
-      CommentAndMetadata commentAndMetadata,
-      Token keyword,
-      TypeAnnotation type) {
-    if (type != null &&
-        keyword != null &&
-        _tokenMatchesKeyword(keyword, Keyword.VAR)) {
-      _reportErrorForToken(ParserErrorCode.VAR_AND_TYPE, keyword);
-    }
-    List<VariableDeclaration> variables = <VariableDeclaration>[
-      parseVariableDeclaration()
-    ];
-    while (_optional(TokenType.COMMA)) {
-      variables.add(parseVariableDeclaration());
-    }
-    return astFactory.variableDeclarationList(commentAndMetadata?.comment,
-        commentAndMetadata?.metadata, keyword, type, variables);
-  }
-
-  /// Parse a variable declaration statement. The [commentAndMetadata] is the
-  /// metadata to be associated with the variable declaration statement, or
-  /// `null` if there is no attempt at parsing the comment and metadata. Return
-  /// the variable declaration statement that was parsed.
-  ///
-  ///     variableDeclarationStatement ::=
-  ///         variableDeclarationList ';'
-  VariableDeclarationStatement parseVariableDeclarationStatementAfterMetadata(
-      CommentAndMetadata commentAndMetadata) {
-    //    Token startToken = currentToken;
-    VariableDeclarationList variableList =
-        parseVariableDeclarationListAfterMetadata(commentAndMetadata);
-//        if (!matches(TokenType.SEMICOLON)) {
-//          if (matches(startToken, Keyword.VAR) && isTypedIdentifier(startToken.getNext())) {
-//            // TODO(brianwilkerson) This appears to be of the form "var type variable". We should do
-//            // a better job of recovering in this case.
-//          }
-//        }
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.variableDeclarationStatement(variableList, semicolon);
-  }
-
-  /// Parse a while statement. Return the while statement that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.WHILE].
-  ///
-  ///     whileStatement ::=
-  ///         'while' '(' expression ')' statement
-  Statement parseWhileStatement() {
-    bool wasInLoop = _inLoop;
-    _inLoop = true;
-    try {
-      Token keyword = getAndAdvance();
-      Token leftParenthesis = _expect(TokenType.OPEN_PAREN);
-      Expression condition = parseExpression2();
-      Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-      Statement body = parseStatement2();
-      return astFactory.whileStatement(
-          keyword, leftParenthesis, condition, rightParenthesis, body);
-    } finally {
-      _inLoop = wasInLoop;
-    }
-  }
-
-  /// Parse a with clause. Return the with clause that was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.WITH`.
-  ///
-  ///     withClause ::=
-  ///         'with' typeName (',' typeName)*
-  WithClause parseWithClause() {
-    Token withKeyword = getAndAdvance();
-    List<TypeName> types = <TypeName>[];
-    do {
-      TypeName typeName = parseTypeName(false);
-      types.add(typeName);
-    } while (_optional(TokenType.COMMA));
-    return astFactory.withClause(withKeyword, types);
-  }
-
-  /// Parse a yield statement. Return the yield statement that was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.YIELD].
-  ///
-  ///     yieldStatement ::=
-  ///         'yield' '*'? expression ';'
-  YieldStatement parseYieldStatement() {
-    Token yieldToken = getAndAdvance();
-    Token star;
-    if (_matches(TokenType.STAR)) {
-      star = getAndAdvance();
-    }
-    Expression expression = parseExpression2();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.yieldStatement(yieldToken, star, expression, semicolon);
-  }
-
-  /// Parse a formal parameter list, starting at the [startToken], without
-  /// actually creating a formal parameter list or changing the current token.
-  /// Return the token following the parameter list that was parsed, or `null`
-  /// if the given token is not the first token in a valid parameter list.
-  ///
-  /// This method must be kept in sync with [parseFormalParameterList].
-  Token skipFormalParameterList(Token startToken) {
-    if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
-      return null;
-    }
-    return (startToken as BeginToken).endToken?.next;
-  }
-
-  /// Parse the portion of a generic function type after the return type,
-  /// starting at the [startToken], without actually creating a generic function
-  /// type or changing the current token. Return the token following the generic
-  /// function type that was parsed, or `null` if the given token is not the
-  /// first token in a valid generic function type.
-  ///
-  /// This method must be kept in sync with
-  /// [parseGenericFunctionTypeAfterReturnType].
-  Token skipGenericFunctionTypeAfterReturnType(Token startToken) {
-    Token next = startToken.next; // Skip 'Function'
-    if (_tokenMatches(next, TokenType.LT)) {
-      next = skipTypeParameterList(next);
-      if (next == null) {
-        return null;
-      }
-    }
-    return skipFormalParameterList(next);
-  }
-
-  /// Parse a prefixed identifier, starting at the [startToken], without
-  /// actually creating a prefixed identifier or changing the current token.
-  /// Return the token following the prefixed identifier that was parsed, or
-  /// `null` if the given token is not the first token in a valid prefixed
-  /// identifier.
-  ///
-  /// This method must be kept in sync with [parsePrefixedIdentifier].
-  ///
-  ///     prefixedIdentifier ::=
-  ///         identifier ('.' identifier)?
-  Token skipPrefixedIdentifier(Token startToken) {
-    Token token = skipSimpleIdentifier(startToken);
-    if (token == null) {
-      return null;
-    } else if (!_tokenMatches(token, TokenType.PERIOD)) {
-      return token;
-    }
-    token = token.next;
-    Token nextToken = skipSimpleIdentifier(token);
-    if (nextToken != null) {
-      return nextToken;
-    } else if (_tokenMatches(token, TokenType.CLOSE_PAREN) ||
-        _tokenMatches(token, TokenType.COMMA)) {
-      // If the `id.` is followed by something that cannot produce a valid
-      // structure then assume this is a prefixed identifier but missing the
-      // trailing identifier
-      return token;
-    }
-    return null;
-  }
-
-  /// Parse a simple identifier, starting at the [startToken], without actually
-  /// creating a simple identifier or changing the current token. Return the
-  /// token following the simple identifier that was parsed, or `null` if the
-  /// given token is not the first token in a valid simple identifier.
-  ///
-  /// This method must be kept in sync with [parseSimpleIdentifier].
-  ///
-  ///     identifier ::=
-  ///         IDENTIFIER
-  Token skipSimpleIdentifier(Token startToken) {
-    if (_tokenMatches(startToken, TokenType.IDENTIFIER) ||
-        _tokenMatchesPseudoKeyword(startToken)) {
-      return startToken.next;
-    }
-    return null;
-  }
-
-  /// Parse a string literal, starting at the [startToken], without actually
-  /// creating a string literal or changing the current token. Return the token
-  /// following the string literal that was parsed, or `null` if the given token
-  /// is not the first token in a valid string literal.
-  ///
-  /// This method must be kept in sync with [parseStringLiteral].
-  ///
-  ///     stringLiteral ::=
-  ///         MULTI_LINE_STRING+
-  ///       | SINGLE_LINE_STRING+
-  Token skipStringLiteral(Token startToken) {
-    Token token = startToken;
-    while (token != null && _tokenMatches(token, TokenType.STRING)) {
-      token = token.next;
-      TokenType type = token.type;
-      if (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
-          type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
-        token = _skipStringInterpolation(token);
-      }
-    }
-    if (identical(token, startToken)) {
-      return null;
-    }
-    return token;
-  }
-
-  /// Parse a type annotation, starting at the [startToken], without actually
-  /// creating a type annotation or changing the current token. Return the token
-  /// following the type annotation that was parsed, or `null` if the given
-  /// token is not the first token in a valid type annotation.
-  ///
-  /// This method must be kept in sync with [parseTypeAnnotation].
-  Token skipTypeAnnotation(Token startToken) {
-    Token next;
-    if (_atGenericFunctionTypeAfterReturnType(startToken)) {
-      // Generic function type with no return type.
-      next = skipGenericFunctionTypeAfterReturnType(startToken);
-    } else {
-      next = skipTypeWithoutFunction(startToken);
-    }
-    while (next != null && _atGenericFunctionTypeAfterReturnType(next)) {
-      next = skipGenericFunctionTypeAfterReturnType(next);
-    }
-    return next;
-  }
-
-  /// Parse a list of type arguments, starting at the [startToken], without
-  /// actually creating a type argument list or changing the current token.
-  /// Return the token following the type argument list that was parsed, or
-  /// `null` if the given token is not the first token in a valid type argument
-  /// list.
-  ///
-  /// This method must be kept in sync with [parseTypeArgumentList].
-  ///
-  ///     typeArguments ::=
-  ///         '<' typeList '>'
-  ///
-  ///     typeList ::=
-  ///         type (',' type)*
-  Token skipTypeArgumentList(Token startToken) {
-    Token token = startToken;
-    if (!_tokenMatches(token, TokenType.LT)) {
-      return null;
-    }
-    token = skipTypeAnnotation(token.next);
-    if (token == null) {
-      // If the start token '<' is followed by '>'
-      // then assume this should be type argument list but is missing a type
-      token = startToken.next;
-      if (_tokenMatches(token, TokenType.GT)) {
-        return token.next;
-      }
-      return null;
-    }
-    while (_tokenMatches(token, TokenType.COMMA)) {
-      token = skipTypeAnnotation(token.next);
-      if (token == null) {
-        return null;
-      }
-    }
-    if (token.type == TokenType.GT) {
-      return token.next;
-    } else if (token.type == TokenType.GT_GT) {
-      Token second = Token(TokenType.GT, token.offset + 1);
-      second.setNextWithoutSettingPrevious(token.next);
-      return second;
-    }
-    return null;
-  }
-
-  /// Parse a type name, starting at the [startToken], without actually creating
-  /// a type name or changing the current token. Return the token following the
-  /// type name that was parsed, or `null` if the given token is not the first
-  /// token in a valid type name.
-  ///
-  /// This method must be kept in sync with [parseTypeName].
-  ///
-  ///     type ::=
-  ///         qualified typeArguments?
-  Token skipTypeName(Token startToken) {
-    Token token = skipPrefixedIdentifier(startToken);
-    if (token == null) {
-      return null;
-    }
-    if (_tokenMatches(token, TokenType.LT)) {
-      token = skipTypeArgumentList(token);
-    }
-    return token;
-  }
-
-  /// Parse a type parameter list, starting at the [startToken], without
-  /// actually creating a type parameter list or changing the current token.
-  /// Return the token following the type parameter list that was parsed, or
-  /// `null` if the given token is not the first token in a valid type parameter
-  /// list.
-  ///
-  /// This method must be kept in sync with [parseTypeParameterList].
-  Token skipTypeParameterList(Token startToken) {
-    if (!_tokenMatches(startToken, TokenType.LT)) {
-      return null;
-    }
-    int depth = 1;
-    Token previous = startToken;
-    Token next = startToken.next;
-    while (next != previous) {
-      if (_tokenMatches(next, TokenType.LT)) {
-        depth++;
-      } else if (_tokenMatches(next, TokenType.GT)) {
-        depth--;
-        if (depth == 0) {
-          return next.next;
-        }
-      }
-      previous = next;
-      next = next.next;
-    }
-    return null;
-  }
-
-  /// Parse a typeWithoutFunction, starting at the [startToken], without
-  /// actually creating a TypeAnnotation or changing the current token. Return
-  /// the token following the typeWithoutFunction that was parsed, or `null` if
-  /// the given token is not the first token in a valid typeWithoutFunction.
-  ///
-  /// This method must be kept in sync with [parseTypeWithoutFunction].
-  Token skipTypeWithoutFunction(Token startToken) {
-    if (startToken.keyword == Keyword.VOID) {
-      return startToken.next;
-    } else {
-      return skipTypeName(startToken);
-    }
-  }
-
-  /// Advance to the next token in the token stream.
-  void _advance() {
-    _currentToken = _currentToken.next;
-  }
-
-  /// Append the character equivalent of the given [codePoint] to the given
-  /// [builder]. Use the [startIndex] and [endIndex] to report an error, and
-  /// don't append anything to the builder, if the code point is invalid. The
-  /// [escapeSequence] is the escape sequence that was parsed to produce the
-  /// code point (used for error reporting).
-  void _appendCodePoint(StringBuffer buffer, String source, int codePoint,
-      int startIndex, int endIndex) {
-    if (codePoint < 0 || codePoint > Character.MAX_CODE_POINT) {
-      String escapeSequence = source.substring(startIndex, endIndex + 1);
-      _reportErrorForCurrentToken(
-          ParserErrorCode.INVALID_CODE_POINT, [escapeSequence]);
-      return;
-    }
-    if (codePoint < Character.MAX_VALUE) {
-      buffer.writeCharCode(codePoint);
-    } else {
-      buffer.write(Character.toChars(codePoint));
-    }
-  }
-
-  /// Return `true` if we are positioned at the keyword 'Function' in a generic
-  /// function type alias.
-  bool _atGenericFunctionTypeAfterReturnType(Token startToken) {
-    if (_tokenMatchesKeyword(startToken, Keyword.FUNCTION)) {
-      Token next = startToken.next;
-      if (next != null &&
-          (_tokenMatches(next, TokenType.OPEN_PAREN) ||
-              _tokenMatches(next, TokenType.LT))) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  void _configureFeatures(FeatureSet featureSet) {
-    if (featureSet.isEnabled(Feature.control_flow_collections)) {
-      throw UnimplementedError('control_flow_collections experiment'
-          ' not supported by analyzer parser');
-    }
-    if (featureSet.isEnabled(Feature.non_nullable)) {
-      throw UnimplementedError(
-          'non-nullable experiment not supported by analyzer parser');
-    }
-    if (featureSet.isEnabled(Feature.spread_collections)) {
-      throw UnimplementedError(
-          'spread_collections experiment not supported by analyzer parser');
-    }
-    if (featureSet.isEnabled(Feature.triple_shift)) {
-      throw UnimplementedError('triple_shift experiment'
-          ' not supported by analyzer parser');
-    }
-    _featureSet = featureSet;
-  }
-
-  /// Convert the given [method] declaration into the nearest valid top-level
-  /// function declaration (that is, the function declaration that most closely
-  /// captures the components of the given method declaration).
-  FunctionDeclaration _convertToFunctionDeclaration(MethodDeclaration method) =>
-      astFactory.functionDeclaration(
-          method.documentationComment,
-          method.metadata,
-          method.externalKeyword,
-          method.returnType,
-          method.propertyKeyword,
-          method.name,
-          astFactory.functionExpression(
-              method.typeParameters, method.parameters, method.body));
-
-  /// Return `true` if the current token could be the start of a compilation
-  /// unit member. This method is used for recovery purposes to decide when to
-  /// stop skipping tokens after finding an error while parsing a compilation
-  /// unit member.
-  bool _couldBeStartOfCompilationUnitMember() {
-    Keyword keyword = _currentToken.keyword;
-    Token next = _currentToken.next;
-    TokenType nextType = next.type;
-    if ((keyword == Keyword.IMPORT ||
-            keyword == Keyword.EXPORT ||
-            keyword == Keyword.LIBRARY ||
-            keyword == Keyword.PART) &&
-        nextType != TokenType.PERIOD &&
-        nextType != TokenType.LT) {
-      // This looks like the start of a directive
-      return true;
-    } else if (keyword == Keyword.CLASS) {
-      // This looks like the start of a class definition
-      return true;
-    } else if (keyword == Keyword.TYPEDEF &&
-        nextType != TokenType.PERIOD &&
-        nextType != TokenType.LT) {
-      // This looks like the start of a typedef
-      return true;
-    } else if (keyword == Keyword.VOID ||
-        ((keyword == Keyword.GET || keyword == Keyword.SET) &&
-            _tokenMatchesIdentifier(next)) ||
-        (keyword == Keyword.OPERATOR && _isOperator(next))) {
-      // This looks like the start of a function
-      return true;
-    } else if (_matchesIdentifier()) {
-      if (nextType == TokenType.OPEN_PAREN) {
-        // This looks like the start of a function
-        return true;
-      }
-      Token token = skipTypeAnnotation(_currentToken);
-      if (token == null) {
-        return false;
-      }
-      // TODO(brianwilkerson) This looks wrong; should we be checking 'token'?
-      if (keyword == Keyword.GET ||
-          keyword == Keyword.SET ||
-          (keyword == Keyword.OPERATOR && _isOperator(next)) ||
-          _matchesIdentifier()) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Return a synthetic token representing the given [keyword].
-  Token _createSyntheticKeyword(Keyword keyword) =>
-      _injectToken(SyntheticKeywordToken(keyword, _currentToken.offset));
-
-  /// Return a synthetic token with the given [type].
-  Token _createSyntheticToken(TokenType type) =>
-      _injectToken(StringToken(type, "", _currentToken.offset));
-
-  /// Create and return a new token with the given [type]. The token will
-  /// replace the first portion of the given [token], so it will have the same
-  /// offset and will have any comments that might have preceded the token.
-  Token _createToken(Token token, TokenType type, {bool isBegin = false}) {
-    CommentToken comments = token.precedingComments;
-    if (comments == null) {
-      if (isBegin) {
-        return BeginToken(type, token.offset);
-      }
-      return Token(type, token.offset);
-    } else if (isBegin) {
-      return BeginToken(type, token.offset, comments);
-    }
-    return Token(type, token.offset, comments);
-  }
-
-  /// Check that the given [expression] is assignable and report an error if it
-  /// isn't.
-  ///
-  ///     assignableExpression ::=
-  ///         primary (arguments* assignableSelector)+
-  ///       | 'super' unconditionalAssignableSelector
-  ///       | identifier
-  ///
-  ///     unconditionalAssignableSelector ::=
-  ///         '[' expression ']'
-  ///       | '.' identifier
-  ///
-  ///     assignableSelector ::=
-  ///         unconditionalAssignableSelector
-  ///       | '?.' identifier
-  void _ensureAssignable(Expression expression) {
-    if (expression != null && !expression.isAssignable) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE);
-    }
-  }
-
-  /// If the current token has the expected type, return it after advancing to
-  /// the next token. Otherwise report an error and return the current token
-  /// without advancing.
-  ///
-  /// Note that the method [_expectGt] should be used if the argument to this
-  /// method would be [TokenType.GT].
-  ///
-  /// The [type] is the type of token that is expected.
-  Token _expect(TokenType type) {
-    if (_matches(type)) {
-      return getAndAdvance();
-    }
-    // Remove uses of this method in favor of matches?
-    // Pass in the error code to use to report the error?
-    if (type == TokenType.SEMICOLON) {
-      if (_tokenMatches(_currentToken.next, TokenType.SEMICOLON)) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.UNEXPECTED_TOKEN, [_currentToken.lexeme]);
-        _advance();
-        return getAndAdvance();
-      }
-      _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
-          _currentToken.previous, [type.lexeme]);
-      return _createSyntheticToken(TokenType.SEMICOLON);
-    }
-    _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TOKEN, [type.lexeme]);
-    return _createSyntheticToken(type);
-  }
-
-  /// If the current token has the type [TokenType.GT], return it after
-  /// advancing to the next token. Otherwise report an error and create a
-  /// synthetic token.
-  Token _expectGt() {
-    if (_matchesGt()) {
-      return getAndAdvance();
-    }
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [TokenType.GT.lexeme]);
-    return _createSyntheticToken(TokenType.GT);
-  }
-
-  /// If the current token is a keyword matching the given [keyword], return it
-  /// after advancing to the next token. Otherwise report an error and return
-  /// the current token without advancing.
-  Token _expectKeyword(Keyword keyword) {
-    if (_matchesKeyword(keyword)) {
-      return getAndAdvance();
-    }
-    // Remove uses of this method in favor of matches?
-    // Pass in the error code to use to report the error?
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [keyword.lexeme]);
-    return _currentToken;
-  }
-
-  /// Search the given list of [ranges] for a range that contains the given
-  /// [index]. Return the range that was found, or `null` if none of the ranges
-  /// contain the index.
-  List<int> _findRange(List<List<int>> ranges, int index) {
-    int rangeCount = ranges.length;
-    for (int i = 0; i < rangeCount; i++) {
-      List<int> range = ranges[i];
-      if (range[0] <= index && index <= range[1]) {
-        return range;
-      } else if (index < range[0]) {
-        return null;
-      }
-    }
-    return null;
-  }
-
-  /// Return a list of the ranges of characters in the given [comment] that
-  /// should be treated as code blocks.
-  List<List<int>> _getCodeBlockRanges(String comment) {
-    List<List<int>> ranges = <List<int>>[];
-    int length = comment.length;
-    if (length < 3) {
-      return ranges;
-    }
-    int index = 0;
-    int firstChar = comment.codeUnitAt(0);
-    if (firstChar == 0x2F) {
-      int secondChar = comment.codeUnitAt(1);
-      int thirdChar = comment.codeUnitAt(2);
-      if ((secondChar == 0x2A && thirdChar == 0x2A) ||
-          (secondChar == 0x2F && thirdChar == 0x2F)) {
-        index = 3;
-      }
-    }
-    if (StringUtilities.startsWith4(comment, index, 0x20, 0x20, 0x20, 0x20)) {
-      int end = index + 4;
-      while (end < length &&
-          comment.codeUnitAt(end) != 0xD &&
-          comment.codeUnitAt(end) != 0xA) {
-        end = end + 1;
-      }
-      ranges.add(<int>[index, end]);
-      index = end;
-    }
-    while (index < length) {
-      int currentChar = comment.codeUnitAt(index);
-      if (currentChar == 0xD || currentChar == 0xA) {
-        index = index + 1;
-        while (index < length &&
-            Character.isWhitespace(comment.codeUnitAt(index))) {
-          index = index + 1;
-        }
-        if (StringUtilities.startsWith6(
-            comment, index, 0x2A, 0x20, 0x20, 0x20, 0x20, 0x20)) {
-          int end = index + 6;
-          while (end < length &&
-              comment.codeUnitAt(end) != 0xD &&
-              comment.codeUnitAt(end) != 0xA) {
-            end = end + 1;
-          }
-          ranges.add(<int>[index, end]);
-          index = end;
-        }
-      } else if (index + 1 < length &&
-          currentChar == 0x5B &&
-          comment.codeUnitAt(index + 1) == 0x3A) {
-        int end = StringUtilities.indexOf2(comment, index + 2, 0x3A, 0x5D);
-        if (end < 0) {
-          end = length;
-        }
-        ranges.add(<int>[index, end]);
-        index = end + 1;
-      } else {
-        index = index + 1;
-      }
-    }
-    return ranges;
-  }
-
-  /// Return the end token associated with the given [beginToken], or `null` if
-  /// either the given token is not a begin token or it does not have an end
-  /// token associated with it.
-  Token _getEndToken(Token beginToken) {
-    if (beginToken is BeginToken) {
-      return beginToken.endToken;
-    }
-    return null;
-  }
-
-  /// Inject the given [token] into the token stream immediately before the
-  /// current token.
-  Token _injectToken(Token token) {
-    Token previous = _currentToken.previous;
-    token.setNext(_currentToken);
-    previous.setNext(token);
-    return token;
-  }
-
-  /// Return `true` if the given [character] is a valid hexadecimal digit.
-  bool _isHexDigit(int character) =>
-      (0x30 <= character && character <= 0x39) ||
-      (0x41 <= character && character <= 0x46) ||
-      (0x61 <= character && character <= 0x66);
-
-  bool _isLikelyArgumentList() {
-    // Try to reduce the amount of lookahead required here before enabling
-    // generic methods.
-    if (_matches(TokenType.OPEN_PAREN)) {
-      return true;
-    }
-    Token token = skipTypeArgumentList(_currentToken);
-    return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
-  }
-
-  /// Return `true` if it looks like we have found the invocation of a named
-  /// constructor following the name of the type:
-  /// ```
-  /// typeArguments? '.' identifier '('
-  /// ```
-  bool _isLikelyNamedInstanceCreation() {
-    Token token = skipTypeArgumentList(_currentToken);
-    if (token != null && _tokenMatches(token, TokenType.PERIOD)) {
-      token = skipSimpleIdentifier(token.next);
-      if (token != null && _tokenMatches(token, TokenType.OPEN_PAREN)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Given that we have just found bracketed text within the given [comment],
-  /// look to see whether that text is (a) followed by a parenthesized link
-  /// address, (b) followed by a colon, or (c) followed by optional whitespace
-  /// and another square bracket. The [rightIndex] is the index of the right
-  /// bracket. Return `true` if the bracketed text is followed by a link
-  /// address.
-  ///
-  /// This method uses the syntax described by the
-  /// <a href="http://daringfireball.net/projects/markdown/syntax">markdown</a>
-  /// project.
-  bool _isLinkText(String comment, int rightIndex) {
-    int length = comment.length;
-    int index = rightIndex + 1;
-    if (index >= length) {
-      return false;
-    }
-    int nextChar = comment.codeUnitAt(index);
-    if (nextChar == 0x28 || nextChar == 0x3A) {
-      return true;
-    }
-    while (Character.isWhitespace(nextChar)) {
-      index = index + 1;
-      if (index >= length) {
-        return false;
-      }
-      nextChar = comment.codeUnitAt(index);
-    }
-    return nextChar == 0x5B;
-  }
-
-  /// Return `true` if the given [startToken] appears to be the beginning of an
-  /// operator declaration.
-  bool _isOperator(Token startToken) {
-    // Accept any operator here, even if it is not user definable.
-    if (!startToken.isOperator) {
-      return false;
-    }
-    // Token "=" means that it is actually a field initializer.
-    if (startToken.type == TokenType.EQ) {
-      return false;
-    }
-    // Consume all operator tokens.
-    Token token = startToken.next;
-    while (token.isOperator) {
-      token = token.next;
-    }
-    // Formal parameter list is expect now.
-    return _tokenMatches(token, TokenType.OPEN_PAREN);
-  }
-
-  bool _isPeekGenericTypeParametersAndOpenParen() {
-    Token token = _skipTypeParameterList(_peek());
-    return token != null && _tokenMatches(token, TokenType.OPEN_PAREN);
-  }
-
-  /// Return `true` if the [startToken] appears to be the first token of a type
-  /// name that is followed by a variable or field formal parameter.
-  bool _isTypedIdentifier(Token startToken) {
-    Token token = skipTypeAnnotation(startToken);
-    if (token == null) {
-      return false;
-    } else if (_tokenMatchesIdentifier(token)) {
-      return true;
-    } else if (_tokenMatchesKeyword(token, Keyword.THIS) &&
-        _tokenMatches(token.next, TokenType.PERIOD) &&
-        _tokenMatchesIdentifier(token.next.next)) {
-      return true;
-    } else if (startToken.next != token &&
-        !_tokenMatches(token, TokenType.OPEN_PAREN)) {
-      // The type is more than a simple identifier, so it should be assumed to
-      // be a type name.
-      return true;
-    }
-    return false;
-  }
-
-  /// Return `true` if the given [expression] is a primary expression that is
-  /// allowed to be an assignable expression without any assignable selector.
-  bool _isValidAssignableExpression(Expression expression) {
-    if (expression is SimpleIdentifier) {
-      return true;
-    } else if (expression is PropertyAccess) {
-      return expression.target is SuperExpression;
-    } else if (expression is IndexExpression) {
-      return expression.target is SuperExpression;
-    }
-    return false;
-  }
-
-  /// Increments the error reporting lock level. If level is more than `0`, then
-  /// [reportError] wont report any error.
-  void _lockErrorListener() {
-    _errorListenerLock++;
-  }
-
-  /// Return `true` if the current token has the given [type]. Note that the
-  /// method [_matchesGt] should be used if the argument to this method would be
-  /// [TokenType.GT].
-  bool _matches(TokenType type) => _currentToken.type == type;
-
-  /// Return `true` if the current token has a type of [TokenType.GT]. Note that
-  /// this method, unlike other variants, will modify the token stream if
-  /// possible to match desired type. In particular, if the next token is either
-  /// a '>>' or '>>>', the token stream will be re-written and `true` will be
-  /// returned.
-  bool _matchesGt() {
-    TokenType currentType = _currentToken.type;
-    if (currentType == TokenType.GT) {
-      return true;
-    } else if (currentType == TokenType.GT_GT) {
-      Token first = _createToken(_currentToken, TokenType.GT);
-      Token second = Token(TokenType.GT, _currentToken.offset + 1);
-      second.setNext(_currentToken.next);
-      first.setNext(second);
-      _currentToken.previous.setNext(first);
-      _currentToken = first;
-      return true;
-    } else if (currentType == TokenType.GT_EQ) {
-      Token first = _createToken(_currentToken, TokenType.GT);
-      Token second = Token(TokenType.EQ, _currentToken.offset + 1);
-      second.setNext(_currentToken.next);
-      first.setNext(second);
-      _currentToken.previous.setNext(first);
-      _currentToken = first;
-      return true;
-    } else if (currentType == TokenType.GT_GT_EQ) {
-      int offset = _currentToken.offset;
-      Token first = _createToken(_currentToken, TokenType.GT);
-      Token second = Token(TokenType.GT, offset + 1);
-      Token third = Token(TokenType.EQ, offset + 2);
-      third.setNext(_currentToken.next);
-      second.setNext(third);
-      first.setNext(second);
-      _currentToken.previous.setNext(first);
-      _currentToken = first;
-      return true;
-    }
-    return false;
-  }
-
-  /// Return `true` if the current token is a valid identifier. Valid
-  /// identifiers include built-in identifiers (pseudo-keywords).
-  bool _matchesIdentifier() => _tokenMatchesIdentifier(_currentToken);
-
-  /// Return `true` if the current token matches the given [keyword].
-  bool _matchesKeyword(Keyword keyword) =>
-      _tokenMatchesKeyword(_currentToken, keyword);
-
-  /// If the current token has the given [type], then advance to the next token
-  /// and return `true`. Otherwise, return `false` without advancing. This
-  /// method should not be invoked with an argument value of [TokenType.GT].
-  bool _optional(TokenType type) {
-    if (_currentToken.type == type) {
-      _advance();
-      return true;
-    }
-    return false;
-  }
-
-  /// Parse an argument list when we need to check for an open paren and recover
-  /// when there isn't one. Return the argument list that was parsed.
-  ArgumentList _parseArgumentListChecked() {
-    if (_matches(TokenType.OPEN_PAREN)) {
-      return parseArgumentList();
-    }
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_PAREN.lexeme]);
-    // Recovery: Look to see whether there is a close paren that isn't matched
-    // to an open paren and if so parse the list of arguments as normal.
-    return astFactory.argumentList(_createSyntheticToken(TokenType.OPEN_PAREN),
-        null, _createSyntheticToken(TokenType.CLOSE_PAREN));
-  }
-
-  /// Parse an assert within a constructor's initializer list. Return the
-  /// assert.
-  ///
-  /// This method assumes that the current token matches `Keyword.ASSERT`.
-  ///
-  ///     assertInitializer ::=
-  ///         'assert' '(' expression [',' expression] ')'
-  AssertInitializer _parseAssertInitializer() {
-    Token keyword = getAndAdvance();
-    Token leftParen = _expect(TokenType.OPEN_PAREN);
-    Expression expression = parseExpression2();
-    Token comma;
-    Expression message;
-    if (_matches(TokenType.COMMA)) {
-      comma = getAndAdvance();
-      if (_matches(TokenType.CLOSE_PAREN)) {
-        comma;
-      } else {
-        message = parseExpression2();
-        if (_matches(TokenType.COMMA)) {
-          getAndAdvance();
-        }
-      }
-    }
-    Token rightParen = _expect(TokenType.CLOSE_PAREN);
-    return astFactory.assertInitializer(
-        keyword, leftParen, expression, comma, message, rightParen);
-  }
-
-  /// Parse a block when we need to check for an open curly brace and recover
-  /// when there isn't one. Return the block that was parsed.
-  ///
-  ///     block ::=
-  ///         '{' statements '}'
-  Block _parseBlockChecked() {
-    if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-      return parseBlock();
-    }
-    // TODO(brianwilkerson) Improve the error message.
-    _reportErrorForCurrentToken(
-        ParserErrorCode.EXPECTED_TOKEN, [TokenType.OPEN_CURLY_BRACKET.lexeme]);
-    // Recovery: Check for an unmatched closing curly bracket and parse
-    // statements until it is reached.
-    return astFactory.block(_createSyntheticToken(TokenType.OPEN_CURLY_BRACKET),
-        null, _createSyntheticToken(TokenType.CLOSE_CURLY_BRACKET));
-  }
-
-  /// Parse a list of class members. The [className] is the name of the class
-  /// whose members are being parsed. The [closingBracket] is the closing
-  /// bracket for the class, or `null` if the closing bracket is missing.
-  /// Return the list of class members that were parsed.
-  ///
-  ///     classMembers ::=
-  ///         (metadata memberDefinition)*
-  List<ClassMember> _parseClassMembers(String className, Token closingBracket) {
-    List<ClassMember> members = <ClassMember>[];
-    Token memberStart = _currentToken;
-    TokenType type = _currentToken.type;
-    Keyword keyword = _currentToken.keyword;
-    while (type != TokenType.EOF &&
-        type != TokenType.CLOSE_CURLY_BRACKET &&
-        (closingBracket != null ||
-            (keyword != Keyword.CLASS && keyword != Keyword.TYPEDEF))) {
-      if (type == TokenType.SEMICOLON) {
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      } else {
-        ClassMember member = parseClassMember(className);
-        if (member != null) {
-          members.add(member);
-        }
-      }
-      if (identical(_currentToken, memberStart)) {
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      }
-      memberStart = _currentToken;
-      type = _currentToken.type;
-      keyword = _currentToken.keyword;
-    }
-    return members;
-  }
-
-  /// Parse a class type alias. The [commentAndMetadata] is the metadata to be
-  /// associated with the member. The [abstractKeyword] is the token
-  /// representing the 'abstract' keyword. The [classKeyword] is the token
-  /// representing the 'class' keyword. The [className] is the name of the
-  /// alias, and the [typeParameters] are the type parameters following the
-  /// name. Return the class type alias that was parsed.
-  ///
-  ///     classTypeAlias ::=
-  ///         identifier typeParameters? '=' 'abstract'? mixinApplication
-  ///
-  ///     mixinApplication ::=
-  ///         type withClause implementsClause? ';'
-  ClassTypeAlias _parseClassTypeAliasAfterName(
-      CommentAndMetadata commentAndMetadata,
-      Token abstractKeyword,
-      Token classKeyword,
-      SimpleIdentifier className,
-      TypeParameterList typeParameters) {
-    Token equals = _expect(TokenType.EQ);
-    TypeName superclass = parseTypeName(false);
-    WithClause withClause;
-    if (_matchesKeyword(Keyword.WITH)) {
-      withClause = parseWithClause();
-    } else {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.EXPECTED_TOKEN, [Keyword.WITH.lexeme]);
-    }
-    ImplementsClause implementsClause;
-    if (_matchesKeyword(Keyword.IMPLEMENTS)) {
-      implementsClause = parseImplementsClause();
-    }
-    Token semicolon;
-    if (_matches(TokenType.SEMICOLON)) {
-      semicolon = getAndAdvance();
-    } else {
-      if (_matches(TokenType.OPEN_CURLY_BRACKET)) {
-        _reportErrorForCurrentToken(
-            ParserErrorCode.EXPECTED_TOKEN, [TokenType.SEMICOLON.lexeme]);
-        Token leftBracket = getAndAdvance();
-        _parseClassMembers(className.name, _getEndToken(leftBracket));
-        _expect(TokenType.CLOSE_CURLY_BRACKET);
-      } else {
-        _reportErrorForToken(ParserErrorCode.EXPECTED_TOKEN,
-            _currentToken.previous, [TokenType.SEMICOLON.lexeme]);
-      }
-      semicolon = _createSyntheticToken(TokenType.SEMICOLON);
-    }
-    return astFactory.classTypeAlias(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        classKeyword,
-        className,
-        typeParameters,
-        equals,
-        abstractKeyword,
-        superclass,
-        withClause,
-        implementsClause,
-        semicolon);
-  }
-
-  /// Parse a list of configurations. Return the configurations that were
-  /// parsed, or `null` if there are no configurations.
-  List<Configuration> _parseConfigurations() {
-    List<Configuration> configurations;
-    while (_matchesKeyword(Keyword.IF)) {
-      configurations ??= <Configuration>[];
-      configurations.add(parseConfiguration());
-    }
-    return configurations;
-  }
-
-  ConstructorDeclaration _parseConstructor(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      Token constKeyword,
-      Token factoryKeyword,
-      SimpleIdentifier returnType,
-      Token period,
-      SimpleIdentifier name,
-      FormalParameterList parameters) {
-    bool bodyAllowed = externalKeyword == null;
-    Token separator;
-    List<ConstructorInitializer> initializers;
-    if (_matches(TokenType.COLON)) {
-      separator = getAndAdvance();
-      initializers = <ConstructorInitializer>[];
-      do {
-        Keyword keyword = _currentToken.keyword;
-        if (keyword == Keyword.THIS) {
-          TokenType nextType = _peek().type;
-          if (nextType == TokenType.OPEN_PAREN) {
-            bodyAllowed = false;
-            initializers.add(parseRedirectingConstructorInvocation(false));
-          } else if (nextType == TokenType.PERIOD &&
-              _tokenMatches(_peekAt(3), TokenType.OPEN_PAREN)) {
-            bodyAllowed = false;
-            initializers.add(parseRedirectingConstructorInvocation(true));
-          } else {
-            initializers.add(parseConstructorFieldInitializer(true));
-          }
-        } else if (keyword == Keyword.SUPER) {
-          initializers.add(parseSuperConstructorInvocation());
-        } else if (_matches(TokenType.OPEN_CURLY_BRACKET) ||
-            _matches(TokenType.FUNCTION)) {
-          _reportErrorForCurrentToken(ParserErrorCode.MISSING_INITIALIZER);
-        } else if (_matchesKeyword(Keyword.ASSERT)) {
-          initializers.add(_parseAssertInitializer());
-        } else {
-          initializers.add(parseConstructorFieldInitializer(false));
-        }
-      } while (_optional(TokenType.COMMA));
-      if (factoryKeyword != null) {
-        _reportErrorForToken(
-            ParserErrorCode.FACTORY_WITH_INITIALIZERS, factoryKeyword);
-      }
-    }
-    ConstructorName redirectedConstructor;
-    FunctionBody body;
-    if (_matches(TokenType.EQ)) {
-      separator = getAndAdvance();
-      redirectedConstructor = parseConstructorName();
-      body = astFactory.emptyFunctionBody(_expect(TokenType.SEMICOLON));
-      if (factoryKeyword == null) {
-        _reportErrorForNode(
-            ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
-            redirectedConstructor);
-      }
-    } else {
-      body =
-          parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
-      if (constKeyword != null &&
-          factoryKeyword != null &&
-          externalKeyword == null &&
-          body is! NativeFunctionBody) {
-        _reportErrorForToken(ParserErrorCode.CONST_FACTORY, factoryKeyword);
-      } else if (body is EmptyFunctionBody) {
-        if (factoryKeyword != null &&
-            externalKeyword == null &&
-            _parseFunctionBodies) {
-          _reportErrorForToken(
-              ParserErrorCode.FACTORY_WITHOUT_BODY, factoryKeyword);
-        }
-      } else {
-        if (constKeyword != null && body is! NativeFunctionBody) {
-          _reportErrorForNode(
-              ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, body);
-        } else if (externalKeyword != null) {
-          _reportErrorForNode(
-              ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY, body);
-        } else if (!bodyAllowed) {
-          _reportErrorForNode(
-              ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, body);
-        }
-      }
-    }
-    return astFactory.constructorDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        constKeyword,
-        factoryKeyword,
-        returnType,
-        period,
-        name,
-        parameters,
-        separator,
-        initializers,
-        redirectedConstructor,
-        body);
-  }
-
-  /// Parse an enum constant declaration. Return the enum constant declaration
-  /// that was parsed.
-  ///
-  /// Specified:
-  ///
-  ///     enumConstant ::=
-  ///         id
-  ///
-  /// Actual:
-  ///
-  ///     enumConstant ::=
-  ///         metadata id
-  EnumConstantDeclaration _parseEnumConstantDeclaration() {
-    CommentAndMetadata commentAndMetadata = parseCommentAndMetadata();
-    SimpleIdentifier name;
-    if (_matchesIdentifier()) {
-      name = _parseSimpleIdentifierUnchecked(isDeclaration: true);
-    } else {
-      name = createSyntheticIdentifier();
-    }
-    return astFactory.enumConstantDeclaration(
-        commentAndMetadata.comment, commentAndMetadata.metadata, name);
-  }
-
-  /// Parse a list of formal parameters given that the list starts with the
-  /// given [leftParenthesis]. Return the formal parameters that were parsed.
-  FormalParameterList _parseFormalParameterListAfterParen(Token leftParenthesis,
-      {bool inFunctionType = false}) {
-    if (_matches(TokenType.CLOSE_PAREN)) {
-      return astFactory.formalParameterList(
-          leftParenthesis, null, null, null, getAndAdvance());
-    }
-    //
-    // Even though it is invalid to have default parameters outside of brackets,
-    // required parameters inside of brackets, or multiple groups of default and
-    // named parameters, we allow all of these cases so that we can recover
-    // better.
-    //
-    List<FormalParameter> parameters = <FormalParameter>[];
-    Token leftSquareBracket;
-    Token rightSquareBracket;
-    Token leftCurlyBracket;
-    Token rightCurlyBracket;
-    ParameterKind kind = ParameterKind.REQUIRED;
-    bool firstParameter = true;
-    bool reportedMultiplePositionalGroups = false;
-    bool reportedMultipleNamedGroups = false;
-    bool reportedMixedGroups = false;
-    bool wasOptionalParameter = false;
-    Token initialToken;
-    do {
-      if (firstParameter) {
-        firstParameter = false;
-      } else if (!_optional(TokenType.COMMA)) {
-        // TODO(brianwilkerson) The token is wrong, we need to recover from this
-        // case.
-        if (_getEndToken(leftParenthesis) != null) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.EXPECTED_TOKEN, [TokenType.COMMA.lexeme]);
-        } else {
-          _reportErrorForToken(ParserErrorCode.MISSING_CLOSING_PARENTHESIS,
-              _currentToken.previous);
-          break;
-        }
-      }
-      initialToken = _currentToken;
-      //
-      // Handle the beginning of parameter groups.
-      //
-      TokenType type = _currentToken.type;
-      if (type == TokenType.OPEN_SQUARE_BRACKET) {
-        wasOptionalParameter = true;
-        if (leftSquareBracket != null && !reportedMultiplePositionalGroups) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS);
-          reportedMultiplePositionalGroups = true;
-        }
-        if (leftCurlyBracket != null && !reportedMixedGroups) {
-          _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
-          reportedMixedGroups = true;
-        }
-        leftSquareBracket = getAndAdvance();
-        kind = ParameterKind.POSITIONAL;
-      } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-        wasOptionalParameter = true;
-        if (leftCurlyBracket != null && !reportedMultipleNamedGroups) {
-          _reportErrorForCurrentToken(
-              ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS);
-          reportedMultipleNamedGroups = true;
-        }
-        if (leftSquareBracket != null && !reportedMixedGroups) {
-          _reportErrorForCurrentToken(ParserErrorCode.MIXED_PARAMETER_GROUPS);
-          reportedMixedGroups = true;
-        }
-        leftCurlyBracket = getAndAdvance();
-        kind = ParameterKind.NAMED;
-      }
-      //
-      // Parse and record the parameter.
-      //
-      FormalParameter parameter =
-          parseFormalParameter(kind, inFunctionType: inFunctionType);
-      parameters.add(parameter);
-      if (kind == ParameterKind.REQUIRED && wasOptionalParameter) {
-        _reportErrorForNode(
-            ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, parameter);
-      }
-      //
-      // Handle the end of parameter groups.
-      //
-      // TODO(brianwilkerson) Improve the detection and reporting of missing and
-      // mismatched delimiters.
-      type = _currentToken.type;
-
-      // Advance past trailing commas as appropriate.
-      if (type == TokenType.COMMA) {
-        // Only parse commas trailing normal (non-positional/named) params.
-        if (rightSquareBracket == null && rightCurlyBracket == null) {
-          Token next = _peek();
-          if (next.type == TokenType.CLOSE_PAREN ||
-              next.type == TokenType.CLOSE_CURLY_BRACKET ||
-              next.type == TokenType.CLOSE_SQUARE_BRACKET) {
-            _advance();
-            type = _currentToken.type;
-          }
-        }
-      }
-
-      if (type == TokenType.CLOSE_SQUARE_BRACKET) {
-        rightSquareBracket = getAndAdvance();
-        if (leftSquareBracket == null) {
-          if (leftCurlyBracket != null) {
-            _reportErrorForCurrentToken(
-                ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
-                ['}', ']']);
-            rightCurlyBracket = rightSquareBracket;
-            rightSquareBracket;
-            // Skip over synthetic closer inserted by fasta
-            // since we've already reported an error
-            if (_currentToken.type == TokenType.CLOSE_CURLY_BRACKET &&
-                _currentToken.isSynthetic) {
-              _advance();
-            }
-          } else {
-            _reportErrorForCurrentToken(
-                ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
-                ["["]);
-          }
-        }
-        kind = ParameterKind.REQUIRED;
-      } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
-        rightCurlyBracket = getAndAdvance();
-        if (leftCurlyBracket == null) {
-          if (leftSquareBracket != null) {
-            _reportErrorForCurrentToken(
-                ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
-                [']', '}']);
-            rightSquareBracket = rightCurlyBracket;
-            rightCurlyBracket;
-            // Skip over synthetic closer inserted by fasta
-            // since we've already reported an error
-            if (_currentToken.type == TokenType.CLOSE_SQUARE_BRACKET &&
-                _currentToken.isSynthetic) {
-              _advance();
-            }
-          } else {
-            _reportErrorForCurrentToken(
-                ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
-                ["{"]);
-          }
-        }
-        kind = ParameterKind.REQUIRED;
-      }
-    } while (!_matches(TokenType.CLOSE_PAREN) &&
-        !identical(initialToken, _currentToken));
-    Token rightParenthesis = _expect(TokenType.CLOSE_PAREN);
-    //
-    // Check that the groups were closed correctly.
-    //
-    if (leftSquareBracket != null && rightSquareBracket == null) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["]"]);
-    }
-    if (leftCurlyBracket != null && rightCurlyBracket == null) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP, ["}"]);
-    }
-    //
-    // Build the parameter list.
-    //
-    leftSquareBracket ??= leftCurlyBracket;
-    rightSquareBracket ??= rightCurlyBracket;
-    return astFactory.formalParameterList(leftParenthesis, parameters,
-        leftSquareBracket, rightSquareBracket, rightParenthesis);
-  }
-
-  /// Parse a list of formal parameters. Return the formal parameters that were
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.OPEN_PAREN`.
-  FormalParameterList _parseFormalParameterListUnchecked(
-      {bool inFunctionType = false}) {
-    return _parseFormalParameterListAfterParen(getAndAdvance(),
-        inFunctionType: inFunctionType);
-  }
-
-  /// Parse a function declaration statement. The [commentAndMetadata] is the
-  /// documentation comment and metadata to be associated with the declaration.
-  /// The [returnType] is the return type, or `null` if there is no return type.
-  /// Return the function declaration statement that was parsed.
-  ///
-  ///     functionDeclarationStatement ::=
-  ///         functionSignature functionBody
-  Statement _parseFunctionDeclarationStatementAfterReturnType(
-      CommentAndMetadata commentAndMetadata, TypeAnnotation returnType) {
-    FunctionDeclaration declaration =
-        parseFunctionDeclaration(commentAndMetadata, null, returnType);
-    Token propertyKeyword = declaration.propertyKeyword;
-    if (propertyKeyword != null) {
-      if (propertyKeyword.keyword == Keyword.GET) {
-        _reportErrorForToken(
-            ParserErrorCode.GETTER_IN_FUNCTION, propertyKeyword);
-      } else {
-        _reportErrorForToken(
-            ParserErrorCode.SETTER_IN_FUNCTION, propertyKeyword);
-      }
-    }
-    return astFactory.functionDeclarationStatement(declaration);
-  }
-
-  /// Parse a function type alias. The [commentAndMetadata] is the metadata to
-  /// be associated with the member. The [keyword] is the token representing the
-  /// 'typedef' keyword. Return the function type alias that was parsed.
-  ///
-  ///     functionTypeAlias ::=
-  ///         functionPrefix typeParameterList? formalParameterList ';'
-  ///
-  ///     functionPrefix ::=
-  ///         returnType? name
-  FunctionTypeAlias _parseFunctionTypeAlias(
-      CommentAndMetadata commentAndMetadata, Token keyword) {
-    TypeAnnotation returnType;
-    if (hasReturnTypeInTypeAlias) {
-      returnType = parseTypeAnnotation(false);
-    }
-    SimpleIdentifier name = parseSimpleIdentifier(isDeclaration: true);
-    TypeParameterList typeParameters;
-    if (_matches(TokenType.LT)) {
-      typeParameters = parseTypeParameterList();
-    }
-    TokenType type = _currentToken.type;
-    if (type == TokenType.SEMICOLON || type == TokenType.EOF) {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
-      FormalParameterList parameters = astFactory.formalParameterList(
-          _createSyntheticToken(TokenType.OPEN_PAREN),
-          null,
-          null,
-          null,
-          _createSyntheticToken(TokenType.CLOSE_PAREN));
-      Token semicolon = _expect(TokenType.SEMICOLON);
-      return astFactory.functionTypeAlias(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          keyword,
-          returnType,
-          name,
-          typeParameters,
-          parameters,
-          semicolon);
-    } else if (type == TokenType.OPEN_PAREN) {
-      FormalParameterList parameters = _parseFormalParameterListUnchecked();
-      _validateFormalParameterList(parameters);
-      Token semicolon = _expect(TokenType.SEMICOLON);
-      return astFactory.functionTypeAlias(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          keyword,
-          returnType,
-          name,
-          typeParameters,
-          parameters,
-          semicolon);
-    } else {
-      _reportErrorForCurrentToken(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS);
-      // Recovery: At the very least we should skip to the start of the next
-      // valid compilation unit member, allowing for the possibility of finding
-      // the typedef parameters before that point.
-      return astFactory.functionTypeAlias(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          keyword,
-          returnType,
-          name,
-          typeParameters,
-          astFactory.formalParameterList(
-              _createSyntheticToken(TokenType.OPEN_PAREN),
-              null,
-              null,
-              null,
-              _createSyntheticToken(TokenType.CLOSE_PAREN)),
-          _createSyntheticToken(TokenType.SEMICOLON));
-    }
-  }
-
-  /// Parse the generic method or function's type parameters.
-  ///
-  /// For backwards compatibility this can optionally use comments.
-  /// See [parseGenericMethodComments].
-  TypeParameterList _parseGenericMethodTypeParameters() {
-    if (_matches(TokenType.LT)) {
-      return parseTypeParameterList();
-    }
-    return null;
-  }
-
-  /// Parse a library name. The [missingNameError] is the error code to be used
-  /// if the library name is missing. The [missingNameToken] is the token
-  /// associated with the error produced if the library name is missing. Return
-  /// the library name that was parsed.
-  ///
-  ///     libraryName ::=
-  ///         libraryIdentifier
-  LibraryIdentifier _parseLibraryName(
-      ParserErrorCode missingNameError, Token missingNameToken) {
-    if (_matchesIdentifier()) {
-      return parseLibraryIdentifier();
-    } else if (_matches(TokenType.STRING)) {
-      // Recovery: This should be extended to handle arbitrary tokens until we
-      // can find a token that can start a compilation unit member.
-      StringLiteral string = parseStringLiteral();
-      _reportErrorForNode(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, string);
-    } else {
-      _reportErrorForToken(missingNameError, missingNameToken);
-    }
-    return astFactory
-        .libraryIdentifier(<SimpleIdentifier>[createSyntheticIdentifier()]);
-  }
-
-  /// Parse a method declaration. The [commentAndMetadata] is the documentation
-  /// comment and metadata to be associated with the declaration. The
-  /// [externalKeyword] is the 'external' token. The [staticKeyword] is the
-  /// static keyword, or `null` if the getter is not static. The [returnType] is
-  /// the return type of the method. The [name] is the name of the method. The
-  /// [parameters] is the parameters to the method. Return the method
-  /// declaration that was parsed.
-  ///
-  ///     functionDeclaration ::=
-  ///         ('external' 'static'?)? functionSignature functionBody
-  ///       | 'external'? functionSignature ';'
-  MethodDeclaration _parseMethodDeclarationAfterParameters(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      Token staticKeyword,
-      TypeAnnotation returnType,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters) {
-    FunctionBody body = parseFunctionBody(
-        externalKeyword != null || staticKeyword == null,
-        ParserErrorCode.MISSING_FUNCTION_BODY,
-        false);
-    if (externalKeyword != null) {
-      if (body is! EmptyFunctionBody) {
-        _reportErrorForNode(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, body);
-      }
-    } else if (staticKeyword != null) {
-      if (body is EmptyFunctionBody && _parseFunctionBodies) {
-        _reportErrorForNode(ParserErrorCode.ABSTRACT_STATIC_METHOD, body);
-      }
-    }
-    return astFactory.methodDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        staticKeyword,
-        returnType,
-        null,
-        null,
-        name,
-        typeParameters,
-        parameters,
-        body);
-  }
-
-  /// Parse a method declaration. The [commentAndMetadata] is the documentation
-  /// comment and metadata to be associated with the declaration. The
-  /// [externalKeyword] is the 'external' token. The [staticKeyword] is the
-  /// static keyword, or `null` if the getter is not static. The [returnType] is
-  /// the return type of the method. Return the method declaration that was
-  /// parsed.
-  ///
-  ///     functionDeclaration ::=
-  ///         'external'? 'static'? functionSignature functionBody
-  ///       | 'external'? functionSignature ';'
-  MethodDeclaration _parseMethodDeclarationAfterReturnType(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      Token staticKeyword,
-      TypeAnnotation returnType) {
-    SimpleIdentifier methodName = parseSimpleIdentifier(isDeclaration: true);
-    TypeParameterList typeParameters = _parseGenericMethodTypeParameters();
-    FormalParameterList parameters;
-    TokenType type = _currentToken.type;
-    // TODO(brianwilkerson) Figure out why we care what the current token is if
-    // it isn't a paren.
-    if (type != TokenType.OPEN_PAREN &&
-        (type == TokenType.OPEN_CURLY_BRACKET || type == TokenType.FUNCTION)) {
-      _reportErrorForToken(
-          ParserErrorCode.MISSING_METHOD_PARAMETERS, _currentToken.previous);
-      parameters = astFactory.formalParameterList(
-          _createSyntheticToken(TokenType.OPEN_PAREN),
-          null,
-          null,
-          null,
-          _createSyntheticToken(TokenType.CLOSE_PAREN));
-    } else {
-      parameters = parseFormalParameterList();
-    }
-    _validateFormalParameterList(parameters);
-    return _parseMethodDeclarationAfterParameters(
-        commentAndMetadata,
-        externalKeyword,
-        staticKeyword,
-        returnType,
-        methodName,
-        typeParameters,
-        parameters);
-  }
-
-  /// Parse a class native clause. Return the native clause that was parsed.
-  ///
-  /// This method assumes that the current token matches `_NATIVE`.
-  ///
-  ///     classNativeClause ::=
-  ///         'native' name
-  NativeClause _parseNativeClause() {
-    Token keyword = getAndAdvance();
-    StringLiteral name = parseStringLiteral();
-    return astFactory.nativeClause(keyword, name);
-  }
-
-  /// Parse an operator declaration starting after the 'operator' keyword. The
-  /// [commentAndMetadata] is the documentation comment and metadata to be
-  /// associated with the declaration. The [externalKeyword] is the 'external'
-  /// token. The [returnType] is the return type that has already been parsed,
-  /// or `null` if there was no return type. The [operatorKeyword] is the
-  /// 'operator' keyword. Return the operator declaration that was parsed.
-  ///
-  ///     operatorDeclaration ::=
-  ///         operatorSignature (';' | functionBody)
-  ///
-  ///     operatorSignature ::=
-  ///         'external'? returnType? 'operator' operator formalParameterList
-  MethodDeclaration _parseOperatorAfterKeyword(
-      CommentAndMetadata commentAndMetadata,
-      Token externalKeyword,
-      TypeAnnotation returnType,
-      Token operatorKeyword) {
-    if (!_currentToken.isUserDefinableOperator) {
-      _reportErrorForCurrentToken(
-          _currentToken.type == TokenType.EQ_EQ_EQ
-              ? ParserErrorCode.INVALID_OPERATOR
-              : ParserErrorCode.NON_USER_DEFINABLE_OPERATOR,
-          [_currentToken.lexeme]);
-    }
-    SimpleIdentifier name =
-        astFactory.simpleIdentifier(getAndAdvance(), isDeclaration: true);
-    if (_matches(TokenType.EQ)) {
-      Token previous = _currentToken.previous;
-      if ((_tokenMatches(previous, TokenType.EQ_EQ) ||
-              _tokenMatches(previous, TokenType.BANG_EQ)) &&
-          _currentToken.offset == previous.offset + 2) {
-        _reportErrorForCurrentToken(ParserErrorCode.INVALID_OPERATOR,
-            ["${previous.lexeme}${_currentToken.lexeme}"]);
-        _advance();
-      }
-    }
-    FormalParameterList parameters = parseFormalParameterList();
-    _validateFormalParameterList(parameters);
-    FunctionBody body =
-        parseFunctionBody(true, ParserErrorCode.MISSING_FUNCTION_BODY, false);
-    if (externalKeyword != null && body is! EmptyFunctionBody) {
-      _reportErrorForCurrentToken(ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY);
-    }
-    return astFactory.methodDeclaration(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        externalKeyword,
-        null,
-        returnType,
-        null,
-        operatorKeyword,
-        name,
-        null,
-        parameters,
-        body);
-  }
-
-  /// Parse a return type if one is given, otherwise return `null` without
-  /// advancing. Return the return type that was parsed.
-  TypeAnnotation _parseOptionalReturnType() {
-    Keyword keyword = _currentToken.keyword;
-    if (keyword == Keyword.VOID) {
-      if (_atGenericFunctionTypeAfterReturnType(_peek())) {
-        return parseTypeAnnotation(false);
-      }
-      return astFactory.typeName(
-          astFactory.simpleIdentifier(getAndAdvance()), null);
-    } else if (_matchesIdentifier()) {
-      Token next = _peek();
-      if (keyword != Keyword.GET &&
-          keyword != Keyword.SET &&
-          keyword != Keyword.OPERATOR &&
-          (_tokenMatchesIdentifier(next) ||
-              _tokenMatches(next, TokenType.LT))) {
-        Token afterTypeParameters = _skipTypeParameterList(next);
-        if (afterTypeParameters != null &&
-            _tokenMatches(afterTypeParameters, TokenType.OPEN_PAREN)) {
-          // If the identifier is followed by type parameters and a parenthesis,
-          // then the identifier is the name of a generic method, not a return
-          // type.
-          return null;
-        }
-        return parseTypeAnnotation(false);
-      }
-      Token next2 = next.next;
-      Token next3 = next2.next;
-      if (_tokenMatches(next, TokenType.PERIOD) &&
-          _tokenMatchesIdentifier(next2) &&
-          (_tokenMatchesIdentifier(next3) ||
-              _tokenMatches(next3, TokenType.LT))) {
-        return parseTypeAnnotation(false);
-      }
-    }
-    return null;
-  }
-
-  /// Parse a [TypeArgumentList] if present, otherwise return null.
-  /// This also supports the comment form, if enabled: `/*<T>*/`
-  TypeArgumentList _parseOptionalTypeArguments() {
-    if (_matches(TokenType.LT)) {
-      return parseTypeArgumentList();
-    }
-    return null;
-  }
-
-  /// Parse a part directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the part or part-of directive that
-  /// was parsed.
-  ///
-  /// This method assumes that the current token matches `Keyword.PART`.
-  ///
-  ///     partDirective ::=
-  ///         metadata 'part' stringLiteral ';'
-  Directive _parsePartDirective(CommentAndMetadata commentAndMetadata) {
-    Token partKeyword = getAndAdvance();
-    StringLiteral partUri = _parseUri();
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.partDirective(commentAndMetadata.comment,
-        commentAndMetadata.metadata, partKeyword, partUri, semicolon);
-  }
-
-  /// Parse a part-of directive. The [commentAndMetadata] is the metadata to be
-  /// associated with the directive. Return the part or part-of directive that
-  /// was parsed.
-  ///
-  /// This method assumes that the current token matches [Keyword.PART] and that
-  /// the following token matches the identifier 'of'.
-  ///
-  ///     partOfDirective ::=
-  ///         metadata 'part' 'of' identifier ';'
-  Directive _parsePartOfDirective(CommentAndMetadata commentAndMetadata) {
-    Token partKeyword = getAndAdvance();
-    Token ofKeyword = getAndAdvance();
-    if (_matches(TokenType.STRING)) {
-      StringLiteral libraryUri = _parseUri();
-      Token semicolon = _expect(TokenType.SEMICOLON);
-      return astFactory.partOfDirective(
-          commentAndMetadata.comment,
-          commentAndMetadata.metadata,
-          partKeyword,
-          ofKeyword,
-          libraryUri,
-          null,
-          semicolon);
-    }
-    LibraryIdentifier libraryName = _parseLibraryName(
-        ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, ofKeyword);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.partOfDirective(
-        commentAndMetadata.comment,
-        commentAndMetadata.metadata,
-        partKeyword,
-        ofKeyword,
-        null,
-        libraryName,
-        semicolon);
-  }
-
-  /// Parse a prefixed identifier given that the given [qualifier] was already
-  /// parsed. Return the prefixed identifier that was parsed.
-  ///
-  ///     prefixedIdentifier ::=
-  ///         identifier ('.' identifier)?
-  Identifier _parsePrefixedIdentifierAfterIdentifier(
-      SimpleIdentifier qualifier) {
-    if (!_matches(TokenType.PERIOD)) {
-      return qualifier;
-    }
-    Token period = getAndAdvance();
-    SimpleIdentifier qualified = parseSimpleIdentifier();
-    return astFactory.prefixedIdentifier(qualifier, period, qualified);
-  }
-
-  /// Parse a prefixed identifier. Return the prefixed identifier that was
-  /// parsed.
-  ///
-  /// This method assumes that the current token matches an identifier.
-  ///
-  ///     prefixedIdentifier ::=
-  ///         identifier ('.' identifier)?
-  Identifier _parsePrefixedIdentifierUnchecked() {
-    return _parsePrefixedIdentifierAfterIdentifier(
-        _parseSimpleIdentifierUnchecked());
-  }
-
-  /// Parse a simple identifier. Return the simple identifier that was parsed.
-  ///
-  /// This method assumes that the current token matches an identifier.
-  ///
-  ///     identifier ::=
-  ///         IDENTIFIER
-  SimpleIdentifier _parseSimpleIdentifierUnchecked(
-      {bool isDeclaration = false}) {
-    String lexeme = _currentToken.lexeme;
-    if ((_inAsync || _inGenerator) && (lexeme == _AWAIT || lexeme == _YIELD)) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
-    }
-    return astFactory.simpleIdentifier(getAndAdvance(),
-        isDeclaration: isDeclaration);
-  }
-
-  /// Parse a list of statements within a switch statement. Return the
-  /// statements that were parsed.
-  ///
-  ///     statements ::=
-  ///         statement*
-  List<Statement> _parseStatementList() {
-    List<Statement> statements = <Statement>[];
-    Token statementStart = _currentToken;
-    TokenType type = _currentToken.type;
-    while (type != TokenType.EOF &&
-        type != TokenType.CLOSE_CURLY_BRACKET &&
-        !isSwitchMember()) {
-      statements.add(parseStatement2());
-      if (identical(_currentToken, statementStart)) {
-        _reportErrorForToken(ParserErrorCode.UNEXPECTED_TOKEN, _currentToken,
-            [_currentToken.lexeme]);
-        _advance();
-      }
-      statementStart = _currentToken;
-      type = _currentToken.type;
-    }
-    return statements;
-  }
-
-  /// Parse a string literal that contains interpolations. Return the string
-  /// literal that was parsed.
-  ///
-  /// This method assumes that the current token matches either
-  /// [TokenType.STRING_INTERPOLATION_EXPRESSION] or
-  /// [TokenType.STRING_INTERPOLATION_IDENTIFIER].
-  StringInterpolation _parseStringInterpolation(Token string) {
-    List<InterpolationElement> elements = <InterpolationElement>[
-      astFactory.interpolationString(
-          string, computeStringValue(string.lexeme, true, false))
-    ];
-    bool hasMore = true;
-    bool isExpression = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION);
-    while (hasMore) {
-      if (isExpression) {
-        Token openToken = getAndAdvance();
-        bool wasInInitializer = _inInitializer;
-        _inInitializer = false;
-        try {
-          Expression expression = parseExpression2();
-          Token rightBracket = _expect(TokenType.CLOSE_CURLY_BRACKET);
-          elements.add(astFactory.interpolationExpression(
-              openToken, expression, rightBracket));
-        } finally {
-          _inInitializer = wasInInitializer;
-        }
-      } else {
-        Token openToken = getAndAdvance();
-        Expression expression;
-        if (_matchesKeyword(Keyword.THIS)) {
-          expression = astFactory.thisExpression(getAndAdvance());
-        } else {
-          expression = parseSimpleIdentifier();
-        }
-        elements.add(
-            astFactory.interpolationExpression(openToken, expression, null));
-      }
-      if (_matches(TokenType.STRING)) {
-        string = getAndAdvance();
-        isExpression = _matches(TokenType.STRING_INTERPOLATION_EXPRESSION);
-        hasMore =
-            isExpression || _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER);
-        elements.add(astFactory.interpolationString(
-            string, computeStringValue(string.lexeme, false, !hasMore)));
-      } else {
-        hasMore = false;
-      }
-    }
-    return astFactory.stringInterpolation(elements);
-  }
-
-  /// Parse a string literal. Return the string literal that was parsed.
-  ///
-  /// This method assumes that the current token matches `TokenType.STRING`.
-  ///
-  ///     stringLiteral ::=
-  ///         MULTI_LINE_STRING+
-  ///       | SINGLE_LINE_STRING+
-  StringLiteral _parseStringLiteralUnchecked() {
-    List<StringLiteral> strings = <StringLiteral>[];
-    do {
-      Token string = getAndAdvance();
-      if (_matches(TokenType.STRING_INTERPOLATION_EXPRESSION) ||
-          _matches(TokenType.STRING_INTERPOLATION_IDENTIFIER)) {
-        strings.add(_parseStringInterpolation(string));
-      } else {
-        strings.add(astFactory.simpleStringLiteral(
-            string, computeStringValue(string.lexeme, true, true)));
-      }
-    } while (_matches(TokenType.STRING));
-    return strings.length == 1
-        ? strings[0]
-        : astFactory.adjacentStrings(strings);
-  }
-
-  /// Parse a type annotation, possibly superseded by a type name in a comment.
-  /// Return the type name that was parsed.
-  ///
-  /// This method assumes that the current token is an identifier.
-  ///
-  ///     type ::=
-  ///         qualified typeArguments?
-  TypeAnnotation _parseTypeAnnotationAfterIdentifier() {
-    return parseTypeAnnotation(false);
-  }
-
-  TypeName _parseTypeName(bool inExpression) {
-    Identifier typeName;
-    if (_matchesIdentifier()) {
-      typeName = _parsePrefixedIdentifierUnchecked();
-    } else if (_matchesKeyword(Keyword.VAR)) {
-      _reportErrorForCurrentToken(ParserErrorCode.VAR_AS_TYPE_NAME);
-      typeName = astFactory.simpleIdentifier(getAndAdvance());
-    } else {
-      typeName = createSyntheticIdentifier();
-      _reportErrorForCurrentToken(ParserErrorCode.EXPECTED_TYPE_NAME);
-    }
-    TypeArgumentList typeArguments = _parseOptionalTypeArguments();
-    return astFactory.typeName(typeName, typeArguments);
-  }
-
-  /// Parse a string literal representing a URI. Return the string literal that
-  /// was parsed.
-  StringLiteral _parseUri() {
-    // TODO(brianwilkerson) Should this function also return true for valid
-    // top-level keywords?
-    bool isKeywordAfterUri(Token token) =>
-        token.lexeme == Keyword.AS.lexeme ||
-        token.lexeme == _HIDE ||
-        token.lexeme == _SHOW;
-    TokenType type = _currentToken.type;
-    if (type != TokenType.STRING &&
-        type != TokenType.SEMICOLON &&
-        !isKeywordAfterUri(_currentToken)) {
-      // Attempt to recover in the case where the URI was not enclosed in
-      // quotes.
-      Token token = _currentToken;
-      bool isValidInUri(Token token) {
-        TokenType type = token.type;
-        return type == TokenType.COLON ||
-            type == TokenType.SLASH ||
-            type == TokenType.PERIOD ||
-            type == TokenType.PERIOD_PERIOD ||
-            type == TokenType.PERIOD_PERIOD_PERIOD ||
-            type == TokenType.INT ||
-            type == TokenType.DOUBLE;
-      }
-
-      while ((_tokenMatchesIdentifier(token) && !isKeywordAfterUri(token)) ||
-          isValidInUri(token)) {
-        token = token.next;
-      }
-      if (_tokenMatches(token, TokenType.SEMICOLON) ||
-          isKeywordAfterUri(token)) {
-        Token endToken = token.previous;
-        token = _currentToken;
-        int endOffset = token.end;
-        StringBuffer buffer = StringBuffer();
-        buffer.write(token.lexeme);
-        while (token != endToken) {
-          token = token.next;
-          if (token.offset != endOffset || token.precedingComments != null) {
-            return parseStringLiteral();
-          }
-          buffer.write(token.lexeme);
-          endOffset = token.end;
-        }
-        String value = buffer.toString();
-        Token newToken =
-            StringToken(TokenType.STRING, "'$value'", _currentToken.offset);
-        _reportErrorForToken(
-            ParserErrorCode.NON_STRING_LITERAL_AS_URI, newToken);
-        _currentToken = endToken.next;
-        return astFactory.simpleStringLiteral(newToken, value);
-      }
-    }
-    return parseStringLiteral();
-  }
-
-  /// Parse a variable declaration statement. The [commentAndMetadata] is the
-  /// metadata to be associated with the variable declaration statement, or
-  /// `null` if there is no attempt at parsing the comment and metadata. The
-  /// [keyword] is the token representing the 'final', 'const' or 'var' keyword,
-  /// or `null` if there is no keyword. The [type] is the type of the variables
-  /// in the list. Return the variable declaration statement that was parsed.
-  ///
-  ///     variableDeclarationStatement ::=
-  ///         variableDeclarationList ';'
-  VariableDeclarationStatement _parseVariableDeclarationStatementAfterType(
-      CommentAndMetadata commentAndMetadata,
-      Token keyword,
-      TypeAnnotation type) {
-    VariableDeclarationList variableList =
-        parseVariableDeclarationListAfterType(
-            commentAndMetadata, keyword, type);
-    Token semicolon = _expect(TokenType.SEMICOLON);
-    return astFactory.variableDeclarationStatement(variableList, semicolon);
-  }
-
-  /// Return the token that is immediately after the current token. This is
-  /// equivalent to [_peekAt](1).
-  Token _peek() => _currentToken.next;
-
-  /// Return the token that is the given [distance] after the current token,
-  /// where the distance is the number of tokens to look ahead. A distance of
-  /// `0` is the current token, `1` is the next token, etc.
-  Token _peekAt(int distance) {
-    Token token = _currentToken;
-    for (int i = 0; i < distance; i++) {
-      token = token.next;
-    }
-    return token;
-  }
-
-  String _removeGitHubInlineCode(String comment) {
-    int index = 0;
-    while (true) {
-      int beginIndex = comment.indexOf('`', index);
-      if (beginIndex == -1) {
-        break;
-      }
-      int endIndex = comment.indexOf('`', beginIndex + 1);
-      if (endIndex == -1) {
-        break;
-      }
-      comment = comment.substring(0, beginIndex + 1) +
-          ' ' * (endIndex - beginIndex - 1) +
-          comment.substring(endIndex);
-      index = endIndex + 1;
-    }
-    return comment;
-  }
-
-  /// Report the given [error].
-  void _reportError(AnalysisError error) {
-    if (_errorListenerLock != 0) {
-      return;
-    }
-    _errorListener.onError(error);
-  }
-
-  /// Report an error with the given [errorCode] and [arguments] associated with
-  /// the current token.
-  void _reportErrorForCurrentToken(ParserErrorCode errorCode,
-      [List<Object> arguments]) {
-    _reportErrorForToken(errorCode, _currentToken, arguments);
-  }
-
-  /// Report an error with the given [errorCode] and [arguments] associated with
-  /// the given [node].
-  void _reportErrorForNode(ParserErrorCode errorCode, AstNode node,
-      [List<Object> arguments]) {
-    _reportError(
-        AnalysisError(_source, node.offset, node.length, errorCode, arguments));
-  }
-
-  /// Report an error with the given [errorCode] and [arguments] associated with
-  /// the given [token].
-  void _reportErrorForToken(ErrorCode errorCode, Token token,
-      [List<Object> arguments]) {
-    if (token.type == TokenType.EOF) {
-      token = token.previous;
-    }
-    _reportError(AnalysisError(_source, token.offset, math.max(token.length, 1),
-        errorCode, arguments));
-  }
-
-  /// Skips a block with all containing blocks.
-  void _skipBlock() {
-    Token endToken = (_currentToken as BeginToken).endToken;
-    if (endToken == null) {
-      endToken = _currentToken.next;
-      while (!identical(endToken, _currentToken)) {
-        _currentToken = endToken;
-        endToken = _currentToken.next;
-      }
-      _reportErrorForToken(
-          ParserErrorCode.EXPECTED_TOKEN, _currentToken.previous, ["}"]);
-    } else {
-      _currentToken = endToken.next;
-    }
-  }
-
-  /// Parse the 'final', 'const', 'var' or type preceding a variable
-  /// declaration, starting at the given token, without actually creating a
-  /// type or changing the current token. Return the token following the type
-  /// that was parsed, or `null` if the given token is not the first token in a
-  /// valid type. The [startToken] is the token at which parsing is to begin.
-  /// Return the token following the type that was parsed.
-  ///
-  /// finalConstVarOrType ::=
-  ///   | 'final' type?
-  ///   | 'const' type?
-  ///   | 'var'
-  ///   | type
-  Token _skipFinalConstVarOrType(Token startToken) {
-    Keyword keyword = startToken.keyword;
-    if (keyword == Keyword.FINAL || keyword == Keyword.CONST) {
-      Token next = startToken.next;
-      if (_tokenMatchesIdentifier(next)) {
-        Token next2 = next.next;
-        // "Type parameter" or "Type<" or "prefix.Type"
-        if (_tokenMatchesIdentifier(next2) ||
-            _tokenMatches(next2, TokenType.LT) ||
-            _tokenMatches(next2, TokenType.PERIOD)) {
-          return skipTypeName(next);
-        }
-        // "parameter"
-        return next;
-      }
-    } else if (keyword == Keyword.VAR) {
-      return startToken.next;
-    } else if (_tokenMatchesIdentifier(startToken)) {
-      Token next = startToken.next;
-      if (_tokenMatchesIdentifier(next) ||
-          _tokenMatches(next, TokenType.LT) ||
-          _tokenMatchesKeyword(next, Keyword.THIS) ||
-          (_tokenMatches(next, TokenType.PERIOD) &&
-              _tokenMatchesIdentifier(next.next) &&
-              (_tokenMatchesIdentifier(next.next.next) ||
-                  _tokenMatches(next.next.next, TokenType.LT) ||
-                  _tokenMatchesKeyword(next.next.next, Keyword.THIS)))) {
-        return skipTypeAnnotation(startToken);
-      }
-    }
-    return null;
-  }
-
-  /// Parse a list of formal parameters, starting at the [startToken], without
-  /// actually creating a formal parameter list or changing the current token.
-  /// Return the token following the formal parameter list that was parsed, or
-  /// `null` if the given token is not the first token in a valid list of formal
-  /// parameter.
-  ///
-  /// Note that unlike other skip methods, this method uses a heuristic. In the
-  /// worst case, the parameters could be prefixed by metadata, which would
-  /// require us to be able to skip arbitrary expressions. Rather than duplicate
-  /// the logic of most of the parse methods we simply look for something that
-  /// is likely to be a list of parameters and then skip to returning the token
-  /// after the closing parenthesis.
-  ///
-  /// This method must be kept in sync with [parseFormalParameterList].
-  ///
-  ///     formalParameterList ::=
-  ///         '(' ')'
-  ///       | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
-  ///       | '(' optionalFormalParameters ')'
-  ///
-  ///     normalFormalParameters ::=
-  ///         normalFormalParameter (',' normalFormalParameter)*
-  ///
-  ///     optionalFormalParameters ::=
-  ///         optionalPositionalFormalParameters
-  ///       | namedFormalParameters
-  ///
-  ///     optionalPositionalFormalParameters ::=
-  ///         '[' defaultFormalParameter (',' defaultFormalParameter)* ']'
-  ///
-  ///     namedFormalParameters ::=
-  ///         '{' defaultNamedParameter (',' defaultNamedParameter)* '}'
-  Token _skipFormalParameterList(Token startToken) {
-    if (!_tokenMatches(startToken, TokenType.OPEN_PAREN)) {
-      return null;
-    }
-    Token next = startToken.next;
-    if (_tokenMatches(next, TokenType.CLOSE_PAREN)) {
-      return next.next;
-    }
-    //
-    // Look to see whether the token after the open parenthesis is something
-    // that should only occur at the beginning of a parameter list.
-    //
-    if (next.matchesAny(const <TokenType>[
-          TokenType.AT,
-          TokenType.OPEN_SQUARE_BRACKET,
-          TokenType.OPEN_CURLY_BRACKET
-        ]) ||
-        _tokenMatchesKeyword(next, Keyword.VOID) ||
-        (_tokenMatchesIdentifier(next) &&
-            (next.next.matchesAny(
-                const <TokenType>[TokenType.COMMA, TokenType.CLOSE_PAREN])))) {
-      return _skipPastMatchingToken(startToken);
-    }
-    //
-    // Look to see whether the first parameter is a function typed parameter
-    // without a return type.
-    //
-    if (_tokenMatchesIdentifier(next) &&
-        _tokenMatches(next.next, TokenType.OPEN_PAREN)) {
-      Token afterParameters = _skipFormalParameterList(next.next);
-      if (afterParameters != null &&
-          afterParameters.matchesAny(
-              const <TokenType>[TokenType.COMMA, TokenType.CLOSE_PAREN])) {
-        return _skipPastMatchingToken(startToken);
-      }
-    }
-    //
-    // Look to see whether the first parameter has a type or is a function typed
-    // parameter with a return type.
-    //
-    Token afterType = _skipFinalConstVarOrType(next);
-    if (afterType == null) {
-      return null;
-    }
-    if (skipSimpleIdentifier(afterType) == null) {
-      return null;
-    }
-    return _skipPastMatchingToken(startToken);
-  }
-
-  /// If the [startToken] is a begin token with an associated end token, then
-  /// return the token following the end token. Otherwise, return `null`.
-  Token _skipPastMatchingToken(Token startToken) {
-    if (startToken is! BeginToken) {
-      return null;
-    }
-    Token closeParen = (startToken as BeginToken).endToken;
-    if (closeParen == null) {
-      return null;
-    }
-    return closeParen.next;
-  }
-
-  /// Parse a string literal that contains interpolations, starting at the
-  /// [startToken], without actually creating a string literal or changing the
-  /// current token. Return the token following the string literal that was
-  /// parsed, or `null` if the given token is not the first token in a valid
-  /// string literal.
-  ///
-  /// This method must be kept in sync with [parseStringInterpolation].
-  Token _skipStringInterpolation(Token startToken) {
-    Token token = startToken;
-    TokenType type = token.type;
-    while (type == TokenType.STRING_INTERPOLATION_EXPRESSION ||
-        type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
-      if (type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
-        token = token.next;
-        type = token.type;
-        //
-        // Rather than verify that the following tokens represent a valid
-        // expression, we simply skip tokens until we reach the end of the
-        // interpolation, being careful to handle nested string literals.
-        //
-        int bracketNestingLevel = 1;
-        while (bracketNestingLevel > 0) {
-          if (type == TokenType.EOF) {
-            return null;
-          } else if (type == TokenType.OPEN_CURLY_BRACKET) {
-            bracketNestingLevel++;
-            token = token.next;
-          } else if (type == TokenType.CLOSE_CURLY_BRACKET) {
-            bracketNestingLevel--;
-            token = token.next;
-          } else if (type == TokenType.STRING) {
-            token = skipStringLiteral(token);
-            if (token == null) {
-              return null;
-            }
-          } else {
-            token = token.next;
-          }
-          type = token.type;
-        }
-        token = token.next;
-        type = token.type;
-      } else {
-        token = token.next;
-        if (token.type != TokenType.IDENTIFIER) {
-          return null;
-        }
-        token = token.next;
-      }
-      type = token.type;
-      if (type == TokenType.STRING) {
-        token = token.next;
-        type = token.type;
-      }
-    }
-    return token;
-  }
-
-  /// Parse a list of type parameters, starting at the [startToken], without
-  /// actually creating a type parameter list or changing the current token.
-  /// Return the token following the type parameter list that was parsed, or
-  /// `null` if the given token is not the first token in a valid type parameter
-  /// list.
-  ///
-  /// This method must be kept in sync with [parseTypeParameterList].
-  ///
-  ///     typeParameterList ::=
-  ///         '<' typeParameter (',' typeParameter)* '>'
-  Token _skipTypeParameterList(Token startToken) {
-    if (!_tokenMatches(startToken, TokenType.LT)) {
-      return null;
-    }
-    //
-    // We can't skip a type parameter because it can be preceded by metadata,
-    // so we just assume that everything before the matching end token is valid.
-    //
-    int depth = 1;
-    Token next = startToken.next;
-    while (depth > 0) {
-      if (_tokenMatches(next, TokenType.EOF)) {
-        return null;
-      } else if (_tokenMatches(next, TokenType.LT)) {
-        depth++;
-      } else if (_tokenMatches(next, TokenType.GT)) {
-        depth--;
-      } else if (_tokenMatches(next, TokenType.GT_EQ)) {
-        if (depth == 1) {
-          Token fakeEquals = Token(TokenType.EQ, next.offset + 2);
-          fakeEquals.setNextWithoutSettingPrevious(next.next);
-          return fakeEquals;
-        }
-        depth--;
-      } else if (_tokenMatches(next, TokenType.GT_GT)) {
-        depth -= 2;
-      } else if (_tokenMatches(next, TokenType.GT_GT_EQ)) {
-        if (depth < 2) {
-          return null;
-        } else if (depth == 2) {
-          Token fakeEquals = Token(TokenType.EQ, next.offset + 2);
-          fakeEquals.setNextWithoutSettingPrevious(next.next);
-          return fakeEquals;
-        }
-        depth -= 2;
-      }
-      next = next.next;
-    }
-    return next;
-  }
-
-  /// Assuming that the current token is an index token ('[]'), split it into
-  /// two tokens ('[' and ']'), leaving the left bracket as the current token.
-  void _splitIndex() {
-    // Split the token into two separate tokens.
-    BeginToken leftBracket = _createToken(
-        _currentToken, TokenType.OPEN_SQUARE_BRACKET,
-        isBegin: true);
-    Token rightBracket =
-        Token(TokenType.CLOSE_SQUARE_BRACKET, _currentToken.offset + 1);
-    leftBracket.endToken = rightBracket;
-    rightBracket.setNext(_currentToken.next);
-    leftBracket.setNext(rightBracket);
-    _currentToken.previous.setNext(leftBracket);
-    _currentToken = leftBracket;
-  }
-
-  /// Return `true` if the given [token] has the given [type].
-  bool _tokenMatches(Token token, TokenType type) => token.type == type;
-
-  /// Return `true` if the given [token] is a valid identifier. Valid
-  /// identifiers include built-in identifiers (pseudo-keywords).
-  bool _tokenMatchesIdentifier(Token token) =>
-      _tokenMatches(token, TokenType.IDENTIFIER) ||
-      _tokenMatchesPseudoKeyword(token);
-
-  /// Return `true` if the given [token] is either an identifier or a keyword.
-  bool _tokenMatchesIdentifierOrKeyword(Token token) =>
-      _tokenMatches(token, TokenType.IDENTIFIER) || token.type.isKeyword;
-
-  /// Return `true` if the given [token] matches the given [keyword].
-  bool _tokenMatchesKeyword(Token token, Keyword keyword) =>
-      token.keyword == keyword;
-
-  /// Return `true` if the given [token] matches a pseudo keyword.
-  bool _tokenMatchesPseudoKeyword(Token token) =>
-      token.keyword?.isBuiltInOrPseudo ?? false;
-
-  /// Translate the characters at the given [index] in the given [lexeme],
-  /// appending the translated character to the given [buffer]. The index is
-  /// assumed to be valid.
-  int _translateCharacter(StringBuffer buffer, String lexeme, int index) {
-    int currentChar = lexeme.codeUnitAt(index);
-    if (currentChar != 0x5C) {
-      buffer.writeCharCode(currentChar);
-      return index + 1;
-    }
-    //
-    // We have found an escape sequence, so we parse the string to determine
-    // what kind of escape sequence and what character to add to the builder.
-    //
-    int length = lexeme.length;
-    int currentIndex = index + 1;
-    if (currentIndex >= length) {
-      // Illegal escape sequence: no char after escape.
-      // This cannot actually happen because it would require the escape
-      // character to be the last character in the string, but if it were it
-      // would escape the closing quote, leaving the string unclosed.
-      // reportError(ParserErrorCode.MISSING_CHAR_IN_ESCAPE_SEQUENCE);
-      return length;
-    }
-    currentChar = lexeme.codeUnitAt(currentIndex);
-    if (currentChar == 0x6E) {
-      buffer.writeCharCode(0xA);
-      // newline
-    } else if (currentChar == 0x72) {
-      buffer.writeCharCode(0xD);
-      // carriage return
-    } else if (currentChar == 0x66) {
-      buffer.writeCharCode(0xC);
-      // form feed
-    } else if (currentChar == 0x62) {
-      buffer.writeCharCode(0x8);
-      // backspace
-    } else if (currentChar == 0x74) {
-      buffer.writeCharCode(0x9);
-      // tab
-    } else if (currentChar == 0x76) {
-      buffer.writeCharCode(0xB);
-      // vertical tab
-    } else if (currentChar == 0x78) {
-      if (currentIndex + 2 >= length) {
-        // Illegal escape sequence: not enough hex digits
-        _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE);
-        return length;
-      }
-      int firstDigit = lexeme.codeUnitAt(currentIndex + 1);
-      int secondDigit = lexeme.codeUnitAt(currentIndex + 2);
-      if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit)) {
-        // Illegal escape sequence: invalid hex digit
-        _reportErrorForCurrentToken(ParserErrorCode.INVALID_HEX_ESCAPE);
-      } else {
-        int charCode = (Character.digit(firstDigit, 16) << 4) +
-            Character.digit(secondDigit, 16);
-        buffer.writeCharCode(charCode);
-      }
-      return currentIndex + 3;
-    } else if (currentChar == 0x75) {
-      currentIndex++;
-      if (currentIndex >= length) {
-        // Illegal escape sequence: not enough hex digits
-        _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-        return length;
-      }
-      currentChar = lexeme.codeUnitAt(currentIndex);
-      if (currentChar == 0x7B) {
-        currentIndex++;
-        if (currentIndex >= length) {
-          // Illegal escape sequence: incomplete escape
-          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-          return length;
-        }
-        currentChar = lexeme.codeUnitAt(currentIndex);
-        int digitCount = 0;
-        int value = 0;
-        while (currentChar != 0x7D) {
-          if (!_isHexDigit(currentChar)) {
-            // Illegal escape sequence: invalid hex digit
-            _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-            currentIndex++;
-            while (currentIndex < length &&
-                lexeme.codeUnitAt(currentIndex) != 0x7D) {
-              currentIndex++;
-            }
-            return currentIndex + 1;
-          }
-          digitCount++;
-          value = (value << 4) + Character.digit(currentChar, 16);
-          currentIndex++;
-          if (currentIndex >= length) {
-            // Illegal escape sequence: incomplete escape
-            _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-            return length;
-          }
-          currentChar = lexeme.codeUnitAt(currentIndex);
-        }
-        if (digitCount < 1 || digitCount > 6) {
-          // Illegal escape sequence: not enough or too many hex digits
-          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-        }
-        _appendCodePoint(buffer, lexeme, value, index, currentIndex);
-        return currentIndex + 1;
-      } else {
-        if (currentIndex + 3 >= length) {
-          // Illegal escape sequence: not enough hex digits
-          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-          return length;
-        }
-        int firstDigit = currentChar;
-        int secondDigit = lexeme.codeUnitAt(currentIndex + 1);
-        int thirdDigit = lexeme.codeUnitAt(currentIndex + 2);
-        int fourthDigit = lexeme.codeUnitAt(currentIndex + 3);
-        if (!_isHexDigit(firstDigit) ||
-            !_isHexDigit(secondDigit) ||
-            !_isHexDigit(thirdDigit) ||
-            !_isHexDigit(fourthDigit)) {
-          // Illegal escape sequence: invalid hex digits
-          _reportErrorForCurrentToken(ParserErrorCode.INVALID_UNICODE_ESCAPE);
-        } else {
-          _appendCodePoint(
-              buffer,
-              lexeme,
-              (((((Character.digit(firstDigit, 16) << 4) +
-                                  Character.digit(secondDigit, 16)) <<
-                              4) +
-                          Character.digit(thirdDigit, 16)) <<
-                      4) +
-                  Character.digit(fourthDigit, 16),
-              index,
-              currentIndex + 3);
-        }
-        return currentIndex + 4;
-      }
-    } else {
-      buffer.writeCharCode(currentChar);
-    }
-    return currentIndex + 1;
-  }
-
-  /// Decrements the error reporting lock level. If level is more than `0`, then
-  /// [reportError] wont report any error.
-  void _unlockErrorListener() {
-    if (_errorListenerLock == 0) {
-      throw StateError("Attempt to unlock not locked error listener.");
-    }
-    _errorListenerLock--;
-  }
-
-  /// Validate that the given [parameterList] does not contain any field
-  /// initializers.
-  void _validateFormalParameterList(FormalParameterList parameterList) {
-    for (FormalParameter parameter in parameterList.parameters) {
-      if (parameter is FieldFormalParameter) {
-        _reportErrorForNode(
-            ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
-            parameter.identifier);
-      }
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a class and
-  /// return the 'abstract' keyword if there is one.
-  Token _validateModifiersForClass(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_CLASS, modifiers.externalKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.VAR_CLASS, modifiers.varKeyword);
-    }
-    return modifiers.abstractKeyword;
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a
-  /// constructor and return the 'const' keyword if there is one.
-  Token _validateModifiersForConstructor(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.ABSTRACT_CLASS_MEMBER, modifiers.abstractKeyword);
-    }
-    if (modifiers.covariantKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.COVARIANT_CONSTRUCTOR, modifiers.covariantKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.FINAL_CONSTRUCTOR, modifiers.finalKeyword);
-    }
-    if (modifiers.staticKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.STATIC_CONSTRUCTOR, modifiers.staticKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, modifiers.varKeyword);
-    }
-    Token externalKeyword = modifiers.externalKeyword;
-    Token constKeyword = modifiers.constKeyword;
-    Token factoryKeyword = modifiers.factoryKeyword;
-    if (externalKeyword != null &&
-        constKeyword != null &&
-        constKeyword.offset < externalKeyword.offset) {
-      _reportErrorForToken(
-          ParserErrorCode.MODIFIER_OUT_OF_ORDER, externalKeyword);
-    }
-    if (externalKeyword != null &&
-        factoryKeyword != null &&
-        factoryKeyword.offset < externalKeyword.offset) {
-      _reportErrorForToken(
-          ParserErrorCode.MODIFIER_OUT_OF_ORDER, externalKeyword);
-    }
-    return constKeyword;
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for an enum and
-  /// return the 'abstract' keyword if there is one.
-  void _validateModifiersForEnum(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.ABSTRACT_ENUM, modifiers.abstractKeyword);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.CONST_ENUM, modifiers.constKeyword);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_ENUM, modifiers.externalKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.FINAL_ENUM, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.VAR_ENUM, modifiers.varKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a field and
-  /// return the 'final', 'const' or 'var' keyword if there is one.
-  Token _validateModifiersForField(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
-    }
-    if (modifiers.factoryKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
-    }
-    Token staticKeyword = modifiers.staticKeyword;
-    Token covariantKeyword = modifiers.covariantKeyword;
-    Token constKeyword = modifiers.constKeyword;
-    Token finalKeyword = modifiers.finalKeyword;
-    Token varKeyword = modifiers.varKeyword;
-    if (constKeyword != null) {
-      if (covariantKeyword != null) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, covariantKeyword);
-      }
-      if (finalKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
-      }
-      if (varKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.MODIFIER_OUT_OF_ORDER, varKeyword);
-      }
-      if (staticKeyword != null && constKeyword.offset < staticKeyword.offset) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, staticKeyword);
-      }
-    } else if (finalKeyword != null) {
-      if (covariantKeyword != null) {
-        _reportErrorForToken(
-            ParserErrorCode.FINAL_AND_COVARIANT, covariantKeyword);
-      }
-      if (varKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
-      }
-      if (staticKeyword != null && finalKeyword.offset < staticKeyword.offset) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, staticKeyword);
-      }
-    } else if (varKeyword != null) {
-      if (staticKeyword != null && varKeyword.offset < staticKeyword.offset) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, staticKeyword);
-      }
-      if (covariantKeyword != null &&
-          varKeyword.offset < covariantKeyword.offset) {
-        _reportErrorForToken(
-            ParserErrorCode.MODIFIER_OUT_OF_ORDER, covariantKeyword);
-      }
-    }
-    if (covariantKeyword != null && staticKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.COVARIANT_AND_STATIC, staticKeyword);
-    }
-    return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a local
-  /// function.
-  void _validateModifiersForFunctionDeclarationStatement(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null ||
-        modifiers.constKeyword != null ||
-        modifiers.externalKeyword != null ||
-        modifiers.factoryKeyword != null ||
-        modifiers.finalKeyword != null ||
-        modifiers.staticKeyword != null ||
-        modifiers.varKeyword != null) {
-      _reportErrorForCurrentToken(
-          ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a getter,
-  /// setter, or method.
-  void _validateModifiersForGetterOrSetterOrMethod(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
-    }
-    if (modifiers.covariantKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.COVARIANT_MEMBER, modifiers.covariantKeyword);
-    }
-    if (modifiers.factoryKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
-    }
-    Token externalKeyword = modifiers.externalKeyword;
-    Token staticKeyword = modifiers.staticKeyword;
-    if (externalKeyword != null &&
-        staticKeyword != null &&
-        staticKeyword.offset < externalKeyword.offset) {
-      _reportErrorForToken(
-          ParserErrorCode.MODIFIER_OUT_OF_ORDER, externalKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a getter,
-  /// setter, or method.
-  void _validateModifiersForOperator(Modifiers modifiers) {
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_CLASS_MEMBER);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONST_METHOD, modifiers.constKeyword);
-    }
-    if (modifiers.factoryKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.NON_CONSTRUCTOR_FACTORY, modifiers.factoryKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.FINAL_METHOD, modifiers.finalKeyword);
-    }
-    if (modifiers.staticKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.STATIC_OPERATOR, modifiers.staticKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a top-level
-  /// declaration.
-  void _validateModifiersForTopLevelDeclaration(Modifiers modifiers) {
-    if (modifiers.covariantKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION,
-          modifiers.covariantKeyword);
-    }
-    if (modifiers.factoryKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION,
-          modifiers.factoryKeyword);
-    }
-    if (modifiers.staticKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION,
-          modifiers.staticKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a top-level
-  /// function.
-  void _validateModifiersForTopLevelFunction(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.CONST_CLASS, modifiers.constKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.FINAL_CLASS, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.VAR_RETURN_TYPE, modifiers.varKeyword);
-    }
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a field and
-  /// return the 'final', 'const' or 'var' keyword if there is one.
-  Token _validateModifiersForTopLevelVariable(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForCurrentToken(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_FIELD, modifiers.externalKeyword);
-    }
-    Token constKeyword = modifiers.constKeyword;
-    Token finalKeyword = modifiers.finalKeyword;
-    Token varKeyword = modifiers.varKeyword;
-    if (constKeyword != null) {
-      if (finalKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.CONST_AND_FINAL, finalKeyword);
-      }
-      if (varKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.MODIFIER_OUT_OF_ORDER, varKeyword);
-      }
-    } else if (finalKeyword != null) {
-      if (varKeyword != null) {
-        _reportErrorForToken(ParserErrorCode.FINAL_AND_VAR, varKeyword);
-      }
-    }
-    return Token.lexicallyFirst([constKeyword, finalKeyword, varKeyword]);
-  }
-
-  /// Validate that the given set of [modifiers] is appropriate for a class and
-  /// return the 'abstract' keyword if there is one.
-  void _validateModifiersForTypedef(Modifiers modifiers) {
-    _validateModifiersForTopLevelDeclaration(modifiers);
-    if (modifiers.abstractKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.ABSTRACT_TYPEDEF, modifiers.abstractKeyword);
-    }
-    if (modifiers.constKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.CONST_TYPEDEF, modifiers.constKeyword);
-    }
-    if (modifiers.externalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.EXTERNAL_TYPEDEF, modifiers.externalKeyword);
-    }
-    if (modifiers.finalKeyword != null) {
-      _reportErrorForToken(
-          ParserErrorCode.FINAL_TYPEDEF, modifiers.finalKeyword);
-    }
-    if (modifiers.varKeyword != null) {
-      _reportErrorForToken(ParserErrorCode.VAR_TYPEDEF, modifiers.varKeyword);
-    }
-  }
+  Expression parseUnaryExpression() => parseExpression2();
 }
-
-/// Instances of this class are thrown when the parser detects that AST has
-/// too many nested expressions to be parsed safely and avoid possibility of
-/// [StackOverflowError] in the parser or during later analysis.
-class _TooDeepTreeError {}
diff --git a/pkg/analyzer/lib/src/generated/parser_fasta.dart b/pkg/analyzer/lib/src/generated/parser_fasta.dart
deleted file mode 100644
index c43c75f..0000000
--- a/pkg/analyzer/lib/src/generated/parser_fasta.dart
+++ /dev/null
@@ -1,394 +0,0 @@
-// 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.
-
-part of analyzer.parser;
-
-/// Proxy implementation of the analyzer parser, implemented in terms of the
-/// Fasta parser.
-abstract class ParserAdapter implements Parser {
-  @override
-  Token currentToken;
-
-  /// The fasta parser being wrapped.
-  final fasta.Parser fastaParser;
-
-  /// The builder which creates the analyzer AST data structures
-  /// based on the Fasta parser.
-  final AstBuilder astBuilder;
-
-  ParserAdapter(this.currentToken, ErrorReporter errorReporter, Uri fileUri,
-      FeatureSet featureSet,
-      {bool allowNativeClause = false})
-      : fastaParser = fasta.Parser(null),
-        astBuilder = AstBuilder(errorReporter, fileUri, true, featureSet) {
-    fastaParser.listener = astBuilder;
-    astBuilder.parser = fastaParser;
-    astBuilder.allowNativeClause = allowNativeClause;
-  }
-
-  @override
-  set allowNativeClause(bool value) {
-    astBuilder.allowNativeClause = value;
-  }
-
-  @override
-  bool get enableOptionalNewAndConst => false;
-
-  @override
-  set enableOptionalNewAndConst(bool enable) {}
-
-  @override
-  set enableSetLiterals(bool value) {
-    // TODO(danrubel): Remove this method once the reference to this flag
-    // has been removed from dartfmt.
-  }
-
-  @override
-  set parseFunctionBodies(bool parseFunctionBodies) {
-    astBuilder.parseFunctionBodies = parseFunctionBodies;
-  }
-
-  @override
-  set parseGenericMethods(_) {}
-
-  /// Append the given token to the end of the token stream,
-  /// and update the token's offset.
-  void appendToken(Token token, Token newToken) {
-    while (!token.next.isEof) {
-      token = token.next;
-    }
-    newToken
-      ..offset = token.end
-      ..setNext(token.next);
-    token.setNext(newToken);
-  }
-
-  @override
-  Expression parseAdditiveExpression() => parseExpression2();
-
-  @override
-  Annotation parseAnnotation() {
-    currentToken = fastaParser
-        .parseMetadata(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as Annotation;
-  }
-
-  @override
-  Expression parseArgument() {
-    currentToken = SimpleToken(TokenType.OPEN_PAREN, 0)..setNext(currentToken);
-    appendToken(currentToken, SimpleToken(TokenType.CLOSE_PAREN, 0));
-    currentToken = fastaParser
-        .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    var invocation = astBuilder.pop() as MethodInvocation;
-    return invocation.argumentList.arguments[0];
-  }
-
-  @override
-  ArgumentList parseArgumentList() {
-    currentToken = fastaParser
-        .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    var result = astBuilder.pop();
-    return result is MethodInvocation
-        ? result.argumentList
-        : result as ArgumentList;
-  }
-
-  @override
-  Expression parseAssignableExpression(bool primaryAllowed) =>
-      parseExpression2();
-
-  @override
-  Expression parseBitwiseAndExpression() => parseExpression2();
-
-  @override
-  Expression parseBitwiseOrExpression() => parseExpression2();
-
-  @override
-  Expression parseBitwiseXorExpression() => parseExpression2();
-
-  @override
-  ClassMember parseClassMember(String className) {
-    astBuilder.classDeclaration = astFactory.classDeclaration(
-      null,
-      null,
-      null,
-      Token(Keyword.CLASS, 0),
-      astFactory.simpleIdentifier(
-          fasta.StringToken.fromString(TokenType.IDENTIFIER, className, 6)),
-      null,
-      null,
-      null,
-      null,
-      null /* leftBracket */,
-      <ClassMember>[],
-      null /* rightBracket */,
-    ) as ClassDeclarationImpl;
-    // TODO(danrubel): disambiguate between class and mixin
-    currentToken = fastaParser.parseClassMember(currentToken, className);
-    //currentToken = fastaParser.parseMixinMember(currentToken);
-    ClassDeclaration declaration = astBuilder.classDeclaration;
-    astBuilder.classDeclaration = null;
-    return declaration.members.isNotEmpty ? declaration.members[0] : null;
-  }
-
-  @override
-  List<Combinator> parseCombinators() {
-    currentToken = fastaParser
-        .parseCombinatorStar(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as List<Combinator>;
-  }
-
-  @override
-  CompilationUnit parseCompilationUnit(Token token) {
-    currentToken = token;
-    return parseCompilationUnit2();
-  }
-
-  @override
-  CompilationUnit parseCompilationUnit2() {
-    currentToken = fastaParser.parseUnit(currentToken);
-    return astBuilder.pop() as CompilationUnit;
-  }
-
-  @override
-  Expression parseConditionalExpression() => parseExpression2();
-
-  @override
-  Configuration parseConfiguration() {
-    currentToken = fastaParser
-        .parseConditionalUri(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as Configuration;
-  }
-
-  @override
-  Expression parseConstExpression() => parseExpression2();
-
-  @override
-  CompilationUnit parseDirectives(Token token) {
-    currentToken = token;
-    return parseDirectives2();
-  }
-
-  @override
-  CompilationUnit parseDirectives2() {
-    currentToken = fastaParser.parseDirectives(currentToken);
-    return astBuilder.pop() as CompilationUnit;
-  }
-
-  @override
-  DottedName parseDottedName() {
-    currentToken = fastaParser
-        .parseDottedName(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as DottedName;
-  }
-
-  @override
-  Expression parseEqualityExpression() => parseExpression2();
-
-  @override
-  Expression parseExpression(Token token) {
-    currentToken = token;
-    return parseExpression2();
-  }
-
-  @override
-  Expression parseExpression2() {
-    currentToken = fastaParser
-        .parseExpression(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as Expression;
-  }
-
-  @override
-  Expression parseExpressionWithoutCascade() => parseExpression2();
-
-  @override
-  FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
-    currentToken = fastaParser
-        .parseFormalParametersRequiredOpt(
-            fastaParser.syntheticPreviousToken(currentToken),
-            inFunctionType
-                ? fasta.MemberKind.GeneralizedFunctionType
-                : fasta.MemberKind.NonStaticMethod)
-        .next;
-    return astBuilder.pop() as FormalParameterList;
-  }
-
-  @override
-  FunctionBody parseFunctionBody(
-      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
-    currentToken = fastaParser.parseAsyncModifierOpt(
-        fastaParser.syntheticPreviousToken(currentToken));
-    currentToken =
-        fastaParser.parseFunctionBody(currentToken, inExpression, mayBeEmpty);
-    return astBuilder.pop() as FunctionBody;
-  }
-
-  @override
-  FunctionExpression parseFunctionExpression() =>
-      parseExpression2() as FunctionExpression;
-
-  @override
-  Expression parseLogicalAndExpression() => parseExpression2();
-
-  @override
-  Expression parseLogicalOrExpression() => parseExpression2();
-
-  @override
-  Expression parseMultiplicativeExpression() => parseExpression2();
-
-  @override
-  InstanceCreationExpression parseNewExpression() =>
-      parseExpression2() as InstanceCreationExpression;
-
-  @override
-  Expression parsePostfixExpression() => parseExpression2();
-
-  @override
-  Identifier parsePrefixedIdentifier() => parseExpression2() as Identifier;
-
-  @override
-  Expression parsePrimaryExpression() {
-    currentToken = fastaParser
-        .parsePrimary(fastaParser.syntheticPreviousToken(currentToken),
-            fasta.IdentifierContext.expression)
-        .next;
-    return astBuilder.pop() as Expression;
-  }
-
-  @override
-  Expression parseRelationalExpression() => parseExpression2();
-
-  @override
-  Expression parseRethrowExpression() => parseExpression2();
-
-  @override
-  Expression parseShiftExpression() => parseExpression2();
-
-  @override
-  SimpleIdentifier parseSimpleIdentifier(
-          {bool allowKeyword = false, bool isDeclaration = false}) =>
-      parseExpression2() as SimpleIdentifier;
-
-  @override
-  Statement parseStatement(Token token) {
-    currentToken = token;
-    return parseStatement2();
-  }
-
-  @override
-  Statement parseStatement2() {
-    currentToken = fastaParser
-        .parseStatement(fastaParser.syntheticPreviousToken(currentToken))
-        .next;
-    return astBuilder.pop() as Statement;
-  }
-
-  @override
-  StringLiteral parseStringLiteral() => parseExpression2() as StringLiteral;
-
-  @override
-  SymbolLiteral parseSymbolLiteral() => parseExpression2() as SymbolLiteral;
-
-  @override
-  Expression parseThrowExpression() => parseExpression2();
-
-  @override
-  Expression parseThrowExpressionWithoutCascade() => parseExpression2();
-
-  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
-    currentToken = fastaParser.parseTopLevelDeclaration(currentToken);
-    return (isDirective ? astBuilder.directives : astBuilder.declarations)
-        .removeLast();
-  }
-
-  @override
-  TypeAnnotation parseTypeAnnotation(bool inExpression) {
-    Token previous = fastaParser.syntheticPreviousToken(currentToken);
-    currentToken = fasta
-        .computeType(previous, true, !inExpression)
-        .parseType(previous, fastaParser)
-        .next;
-    return astBuilder.pop() as TypeAnnotation;
-  }
-
-  @override
-  TypeArgumentList parseTypeArgumentList() {
-    Token previous = fastaParser.syntheticPreviousToken(currentToken);
-    currentToken = fasta
-        .computeTypeParamOrArg(previous)
-        .parseArguments(previous, fastaParser)
-        .next;
-    return astBuilder.pop() as TypeArgumentList;
-  }
-
-  @override
-  TypeName parseTypeName(bool inExpression) {
-    Token previous = fastaParser.syntheticPreviousToken(currentToken);
-    currentToken = fasta
-        .computeType(previous, true, !inExpression)
-        .parseType(previous, fastaParser)
-        .next;
-    return astBuilder.pop() as TypeName;
-  }
-
-  @override
-  TypeParameter parseTypeParameter() {
-    currentToken = SyntheticBeginToken(TokenType.LT, 0)
-      ..endGroup = SyntheticToken(TokenType.GT, 0)
-      ..setNext(currentToken);
-    appendToken(currentToken, currentToken.endGroup);
-    TypeParameterList typeParams = parseTypeParameterList();
-    return typeParams.typeParameters[0];
-  }
-
-  @override
-  TypeParameterList parseTypeParameterList() {
-    Token token = fastaParser.syntheticPreviousToken(currentToken);
-    currentToken = fasta
-        .computeTypeParamOrArg(token, true)
-        .parseVariables(token, fastaParser)
-        .next;
-    return astBuilder.pop() as TypeParameterList;
-  }
-
-  @override
-  Expression parseUnaryExpression() => parseExpression2();
-}
-
-/// Replacement parser based on Fasta.
-class _Parser2 extends ParserAdapter {
-  /// The source being parsed.
-  @override
-  final Source _source;
-
-  @override
-  bool enableUriInPartOf = true;
-
-  factory _Parser2(
-      Source source, AnalysisErrorListener errorListener, FeatureSet featureSet,
-      {bool allowNativeClause = false}) {
-    var errorReporter = ErrorReporter(
-      errorListener,
-      source,
-      isNonNullableByDefault: featureSet.isEnabled(Feature.non_nullable),
-    );
-    return _Parser2._(source, errorReporter, source.uri, featureSet,
-        allowNativeClause: allowNativeClause);
-  }
-
-  _Parser2._(this._source, ErrorReporter errorReporter, Uri fileUri,
-      FeatureSet featureSet, {bool allowNativeClause = false})
-      : super(null, errorReporter, fileUri, featureSet,
-            allowNativeClause: allowNativeClause);
-
-  @override
-  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d6c7ecd..2579d39 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -771,26 +771,29 @@
   }
 
   void startNullAwareIndexExpression(IndexExpression node) {
-    if (_migratableAstInfoProvider.isIndexExpressionNullAware(node) &&
-        _flowAnalysis != null) {
-      _flowAnalysis.flow.nullAwareAccess_rightBegin(
-          node.target, node.realTarget.staticType ?? typeProvider.dynamicType);
-      _unfinishedNullShorts.add(node.nullShortingTermination);
+    if (_migratableAstInfoProvider.isIndexExpressionNullAware(node)) {
+      var flow = _flowAnalysis?.flow;
+      if (flow != null) {
+        flow.nullAwareAccess_rightBegin(node.target,
+            node.realTarget.staticType ?? typeProvider.dynamicType);
+        _unfinishedNullShorts.add(node.nullShortingTermination);
+      }
     }
   }
 
-  void startNullAwarePropertyAccess(
-    PropertyAccess node,
-  ) {
-    if (_migratableAstInfoProvider.isPropertyAccessNullAware(node) &&
-        _flowAnalysis != null) {
-      var target = node.target;
-      if (target is SimpleIdentifier && target.staticElement is ClassElement) {
-        // `?.` to access static methods is equivalent to `.`, so do nothing.
-      } else {
-        _flowAnalysis.flow.nullAwareAccess_rightBegin(
-            target, node.realTarget.staticType ?? typeProvider.dynamicType);
-        _unfinishedNullShorts.add(node.nullShortingTermination);
+  void startNullAwarePropertyAccess(PropertyAccess node) {
+    if (_migratableAstInfoProvider.isPropertyAccessNullAware(node)) {
+      var flow = _flowAnalysis?.flow;
+      if (flow != null) {
+        var target = node.target;
+        if (target is SimpleIdentifier &&
+            target.staticElement is ClassElement) {
+          // `?.` to access static methods is equivalent to `.`, so do nothing.
+        } else {
+          flow.nullAwareAccess_rightBegin(
+              target, node.realTarget.staticType ?? typeProvider.dynamicType);
+          _unfinishedNullShorts.add(node.nullShortingTermination);
+        }
       }
     }
   }
@@ -1107,7 +1110,7 @@
 
     if (_flowAnalysis != null) {
       if (flow != null) {
-        flow.conditional_thenBegin(condition);
+        flow.conditional_thenBegin(condition, node);
         checkUnreachableNode(thenExpression);
       }
       thenExpression.accept(this);
@@ -1163,8 +1166,8 @@
     super.visitConstructorDeclaration(node);
 
     if (_flowAnalysis != null) {
-      var bodyContext = BodyInferenceContext.of(node.body);
       if (node.factoryKeyword != null) {
+        var bodyContext = BodyInferenceContext.of(node.body);
         checkForBodyMayCompleteNormally(
           returnType: bodyContext?.contextType,
           body: node.body,
@@ -1468,6 +1471,7 @@
     node.function?.accept(this);
     _functionExpressionInvocationResolver
         .resolve(node as FunctionExpressionInvocationImpl);
+    nullShortingTermination(node);
   }
 
   @override
@@ -1513,7 +1517,7 @@
 
     CollectionElement thenElement = node.thenElement;
     if (_flowAnalysis != null) {
-      _flowAnalysis.flow.ifStatement_thenBegin(condition);
+      _flowAnalysis.flow?.ifStatement_thenBegin(condition, node);
       thenElement.accept(this);
     } else {
       _promoteManager.visitIfElement_thenElement(
@@ -1553,7 +1557,7 @@
 
     Statement thenStatement = node.thenStatement;
     if (_flowAnalysis != null) {
-      _flowAnalysis.flow.ifStatement_thenBegin(condition);
+      _flowAnalysis.flow?.ifStatement_thenBegin(condition, node);
       visitStatementInScope(thenStatement);
       nullSafetyDeadCodeVerifier?.flowEnd(thenStatement);
     } else {
@@ -1684,14 +1688,17 @@
     var target = node.target;
     target?.accept(this);
 
-    if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
-        _flowAnalysis != null) {
-      if (target is SimpleIdentifier && target.staticElement is ClassElement) {
-        // `?.` to access static methods is equivalent to `.`, so do nothing.
-      } else {
-        _flowAnalysis.flow.nullAwareAccess_rightBegin(
-            target, node.realTarget.staticType ?? typeProvider.dynamicType);
-        _unfinishedNullShorts.add(node.nullShortingTermination);
+    if (_migratableAstInfoProvider.isMethodInvocationNullAware(node)) {
+      var flow = _flowAnalysis?.flow;
+      if (flow != null) {
+        if (target is SimpleIdentifier &&
+            target.staticElement is ClassElement) {
+          // `?.` to access static methods is equivalent to `.`, so do nothing.
+        } else {
+          flow.nullAwareAccess_rightBegin(
+              target, node.realTarget.staticType ?? typeProvider.dynamicType);
+          _unfinishedNullShorts.add(node.nullShortingTermination);
+        }
       }
     }
 
@@ -1861,7 +1868,9 @@
     super.visitSpreadElement(node);
 
     if (!node.isNullAware) {
-      nullableDereferenceVerifier.expression(node.expression);
+      nullableDereferenceVerifier.expression(node.expression,
+          errorCode:
+              CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD);
     }
   }
 
@@ -2021,10 +2030,10 @@
           _flowAnalysis?.flow?.promote(
               declaredElement as PromotableElement, initializerStaticType);
         }
-      } else if (!parent.isFinal) {
-        _flowAnalysis?.flow?.write(
-            declaredElement as PromotableElement, initializerStaticType,
-            viaInitializer: true);
+      } else {
+        _flowAnalysis?.flow?.initialize(declaredElement as PromotableElement,
+            initializerStaticType, initializer,
+            isFinal: parent.isFinal, isLate: parent.isLate);
       }
     }
   }
@@ -2206,7 +2215,8 @@
   /// correspond to the list of arguments.
   ///
   /// An error will be reported to [onError] if any of the arguments cannot be
-  /// matched to a parameter. onError can be null to ignore the error.
+  /// matched to a parameter. onError will be provided the node of the first
+  /// argument that is not matched. onError can be null to ignore the error.
   ///
   /// Returns the parameters that correspond to the arguments. If no parameter
   /// matched an argument, that position will be `null` in the list.
@@ -2245,6 +2255,7 @@
     int positionalArgumentCount = 0;
     HashSet<String> usedNames;
     bool noBlankArguments = true;
+    Expression firstUnresolvedArgument;
     for (int i = 0; i < argumentCount; i++) {
       Expression argument = arguments[i];
       if (argument is NamedExpression) {
@@ -2275,6 +2286,8 @@
         positionalArgumentCount++;
         if (unnamedIndex < unnamedParameterCount) {
           resolvedParameters[i] = unnamedParameters[unnamedIndex++];
+        } else {
+          firstUnresolvedArgument ??= argument;
         }
       }
     }
@@ -2295,7 +2308,7 @@
         errorCode = CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS;
       }
       if (onError != null) {
-        onError(errorCode, argumentList,
+        onError(errorCode, firstUnresolvedArgument,
             [unnamedParameterCount, positionalArgumentCount]);
       }
     }
@@ -2726,9 +2739,11 @@
         parent.declaredElement.parameters,
       );
     } else if (parent is FunctionTypeAlias) {
+      var aliasedElement = parent.declaredElement.aliasedElement;
+      var functionElement = aliasedElement as GenericFunctionTypeElement;
       nameScope = FormalParameterScope(
         nameScope,
-        parent.declaredElement.function.parameters,
+        functionElement.parameters,
       );
     } else if (parent is MethodDeclaration) {
       nameScope = FormalParameterScope(
diff --git a/pkg/analyzer/lib/src/generated/testing/element_search.dart b/pkg/analyzer/lib/src/generated/testing/element_search.dart
deleted file mode 100644
index e0bfdbb1..0000000
--- a/pkg/analyzer/lib/src/generated/testing/element_search.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-
-/// Search the [unit] for the [Element]s with the given [name].
-List<Element> findElementsByName(CompilationUnit unit, String name) {
-  var finder = _ElementsByNameFinder(name);
-  unit.accept(finder);
-  return finder.elements;
-}
-
-class _ElementsByNameFinder extends RecursiveAstVisitor<void> {
-  final String name;
-  final List<Element> elements = [];
-
-  _ElementsByNameFinder(this.name);
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    if (node.name == name && node.inDeclarationContext()) {
-      elements.add(node.staticElement);
-    }
-  }
-}
diff --git a/pkg/analyzer/lib/src/generated/testing/node_search.dart b/pkg/analyzer/lib/src/generated/testing/node_search.dart
deleted file mode 100644
index 9a2b15d..0000000
--- a/pkg/analyzer/lib/src/generated/testing/node_search.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-
-/// Search the [unit] for declared [SimpleIdentifier]s with the given [name].
-List<SimpleIdentifier> findDeclaredIdentifiersByName(
-    CompilationUnit unit, String name) {
-  var finder = _DeclaredIdentifiersByNameFinder(name);
-  unit.accept(finder);
-  return finder.identifiers;
-}
-
-class _DeclaredIdentifiersByNameFinder extends RecursiveAstVisitor<void> {
-  final String name;
-  final List<SimpleIdentifier> identifiers = [];
-
-  _DeclaredIdentifiersByNameFinder(this.name);
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    if (node.name == name && node.inDeclarationContext()) {
-      identifiers.add(node);
-    }
-  }
-}
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index d28ca62..bf67b7b 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -469,7 +469,6 @@
         errorReporter,
         libraryElement,
         declaredVariables,
-        featureSet: currentUnit.unit.featureSet,
       ),
     );
     return listener.hasConstError;
diff --git a/pkg/analyzer/lib/src/lint/options_rule_validator.dart b/pkg/analyzer/lib/src/lint/options_rule_validator.dart
index 31f27c0..bf67245 100644
--- a/pkg/analyzer/lib/src/lint/options_rule_validator.dart
+++ b/pkg/analyzer/lib/src/lint/options_rule_validator.dart
@@ -11,6 +11,8 @@
 import 'package:analyzer/src/util/yaml.dart';
 import 'package:yaml/yaml.dart';
 
+/// TODO(pq): migrate these codes to `option_codes.dart`?
+
 /// A hint code indicating reference to a deprecated lint.
 ///
 /// Parameters:
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index e0f631d..d47bbd7 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -1826,32 +1826,22 @@
     var buffer = StringBuffer();
     var ranges = <int>[];
     for (var parameter in parameters.parameters) {
-      if (parameter.isRequired) {
+      if (parameter.isRequired ||
+          (parameter.isNamed && _hasRequiredAnnotation(parameter))) {
         if (buffer.isNotEmpty) {
           buffer.write(', ');
         }
+
         if (parameter.isNamed) {
           buffer.write(parameter.identifier.name);
           buffer.write(': ');
         }
+
         var valueOffset = buffer.length;
         buffer.write(parameter.identifier.name);
         var valueLength = buffer.length - valueOffset;
         ranges.add(valueOffset);
         ranges.add(valueLength);
-      } else if (parameter.isNamed && _hasRequiredAnnotation(parameter)) {
-        if (buffer.isNotEmpty) {
-          buffer.write(', ');
-        }
-        buffer.write(parameter.identifier.name);
-        buffer.write(': ');
-
-        var valueOffset = buffer.length;
-        buffer.write('null');
-        var valueLength = buffer.length - valueOffset;
-
-        ranges.add(valueOffset);
-        ranges.add(valueLength);
       }
     }
     if (buffer.isEmpty) return null;
diff --git a/pkg/analyzer/lib/src/summary2/apply_resolution.dart b/pkg/analyzer/lib/src/summary2/apply_resolution.dart
index 7c6d20e..ec7202d 100644
--- a/pkg/analyzer/lib/src/summary2/apply_resolution.dart
+++ b/pkg/analyzer/lib/src/summary2/apply_resolution.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:math';
+
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -11,6 +13,8 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/variance.dart';
+import 'package:analyzer/src/exception/exception.dart';
+import 'package:analyzer/src/summary2/ast_binary_flags.dart';
 import 'package:analyzer/src/summary2/ast_binary_tag.dart';
 import 'package:analyzer/src/summary2/bundle_reader.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
@@ -77,61 +81,101 @@
 
   @override
   void visitAnnotation(Annotation node) {
+    _expectMarker(MarkerTag.Annotation_name);
     node.name.accept(this);
+    _expectMarker(MarkerTag.Annotation_constructorName);
     node.constructorName?.accept(this);
+    _expectMarker(MarkerTag.Annotation_arguments);
     node.arguments?.accept(this);
+    _expectMarker(MarkerTag.Annotation_element);
     node.element = _nextElement();
   }
 
   @override
   void visitArgumentList(ArgumentList node) {
+    _expectMarker(MarkerTag.ArgumentList_arguments);
     node.arguments.accept(this);
+    _expectMarker(MarkerTag.ArgumentList_end);
   }
 
   @override
   void visitAsExpression(AsExpression node) {
+    _expectMarker(MarkerTag.AsExpression_expression);
     node.expression.accept(this);
+    _expectMarker(MarkerTag.AsExpression_type);
     node.type.accept(this);
+    _expectMarker(MarkerTag.AsExpression_expression2);
     _expression(node);
+    _expectMarker(MarkerTag.AsExpression_end);
   }
 
   @override
   void visitAssertInitializer(AssertInitializer node) {
+    _expectMarker(MarkerTag.AssertInitializer_condition);
     node.condition.accept(this);
+    _expectMarker(MarkerTag.AssertInitializer_message);
     node.message?.accept(this);
+    _expectMarker(MarkerTag.AssertInitializer_end);
   }
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
     var nodeImpl = node as AssignmentExpressionImpl;
+    _expectMarker(MarkerTag.AssignmentExpression_leftHandSide);
     node.leftHandSide.accept(this);
+    _expectMarker(MarkerTag.AssignmentExpression_rightHandSide);
     node.rightHandSide.accept(this);
+    _expectMarker(MarkerTag.AssignmentExpression_staticElement);
     node.staticElement = _nextElement();
+    _expectMarker(MarkerTag.AssignmentExpression_readElement);
     nodeImpl.readElement = _nextElement();
+    _expectMarker(MarkerTag.AssignmentExpression_readType);
     nodeImpl.readType = _nextType();
+    _expectMarker(MarkerTag.AssignmentExpression_writeElement);
     nodeImpl.writeElement = _nextElement();
+    _expectMarker(MarkerTag.AssignmentExpression_writeType);
     nodeImpl.writeType = _nextType();
+    _expectMarker(MarkerTag.AssignmentExpression_expression);
     _expression(node);
+    _expectMarker(MarkerTag.AssignmentExpression_end);
+  }
+
+  @override
+  void visitAwaitExpression(AwaitExpression node) {
+    _expectMarker(MarkerTag.AwaitExpression_expression);
+    node.expression.accept(this);
+    _expectMarker(MarkerTag.AwaitExpression_expression2);
+    _expression(node);
+    _expectMarker(MarkerTag.AwaitExpression_end);
   }
 
   @override
   void visitBinaryExpression(BinaryExpression node) {
+    _expectMarker(MarkerTag.BinaryExpression_leftOperand);
     node.leftOperand.accept(this);
+    _expectMarker(MarkerTag.BinaryExpression_rightOperand);
     node.rightOperand.accept(this);
 
+    _expectMarker(MarkerTag.BinaryExpression_staticElement);
     node.staticElement = _nextElement();
-    node.staticType = _nextType();
+
+    _expectMarker(MarkerTag.BinaryExpression_expression);
+    _expression(node);
+    _expectMarker(MarkerTag.BinaryExpression_end);
   }
 
   @override
   void visitBooleanLiteral(BooleanLiteral node) {
-    node.staticType = _nextType();
+    _expression(node);
   }
 
   @override
   void visitCascadeExpression(CascadeExpression node) {
+    _expectMarker(MarkerTag.CascadeExpression_target);
     node.target.accept(this);
+    _expectMarker(MarkerTag.CascadeExpression_cascadeSections);
     node.cascadeSections.accept(this);
+    _expectMarker(MarkerTag.CascadeExpression_end);
     node.staticType = node.target.staticType;
   }
 
@@ -143,12 +187,32 @@
     element.isSimplyBounded = _resolution.readByte() != 0;
     _enclosingElements.add(element);
 
-    node.typeParameters?.accept(this);
-    node.extendsClause?.accept(this);
-    node.nativeClause?.accept(this);
-    node.withClause?.accept(this);
-    node.implementsClause?.accept(this);
-    _namedCompilationUnitMember(node);
+    try {
+      _expectMarker(MarkerTag.ClassDeclaration_typeParameters);
+      node.typeParameters?.accept(this);
+      _expectMarker(MarkerTag.ClassDeclaration_extendsClause);
+      node.extendsClause?.accept(this);
+      _expectMarker(MarkerTag.ClassDeclaration_withClause);
+      node.withClause?.accept(this);
+      _expectMarker(MarkerTag.ClassDeclaration_implementsClause);
+      node.implementsClause?.accept(this);
+      _expectMarker(MarkerTag.ClassDeclaration_nativeClause);
+      node.nativeClause?.accept(this);
+      _expectMarker(MarkerTag.ClassDeclaration_namedCompilationUnitMember);
+      _namedCompilationUnitMember(node);
+      _expectMarker(MarkerTag.ClassDeclaration_end);
+    } catch (e, stackTrace) {
+      // TODO(scheglov) Remove after fixing http://dartbug.com/44449
+      var headerStr = _astCodeBeforeMarkerOrMaxLength(node, '{', 1000);
+      throw CaughtExceptionWithFiles(e, stackTrace, {
+        'state': '''
+element: ${element.reference}
+header: $headerStr
+resolution.bytes.length: ${_resolution.bytes.length}
+resolution.byteOffset: ${_resolution.byteOffset}
+''',
+      });
+    }
 
     _enclosingElements.removeLast();
   }
@@ -160,28 +224,41 @@
     _enclosingElements.add(element);
 
     element.isSimplyBounded = _resolution.readByte() != 0;
+    _expectMarker(MarkerTag.ClassTypeAlias_typeParameters);
     node.typeParameters?.accept(this);
+    _expectMarker(MarkerTag.ClassTypeAlias_superclass);
     node.superclass?.accept(this);
+    _expectMarker(MarkerTag.ClassTypeAlias_withClause);
     node.withClause?.accept(this);
+    _expectMarker(MarkerTag.ClassTypeAlias_implementsClause);
     node.implementsClause?.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.ClassTypeAlias_typeAlias);
+    _typeAlias(node);
+    _expectMarker(MarkerTag.ClassTypeAlias_end);
 
     _enclosingElements.removeLast();
   }
 
   @override
   void visitConditionalExpression(ConditionalExpression node) {
+    _expectMarker(MarkerTag.ConditionalExpression_condition);
     node.condition.accept(this);
+    _expectMarker(MarkerTag.ConditionalExpression_thenExpression);
     node.thenExpression.accept(this);
+    _expectMarker(MarkerTag.ConditionalExpression_elseExpression);
     node.elseExpression.accept(this);
-    node.staticType = _nextType();
+    _expression(node);
   }
 
   @override
   void visitConfiguration(Configuration node) {
+    _expectMarker(MarkerTag.Configuration_name);
     node.name?.accept(this);
+    _expectMarker(MarkerTag.Configuration_value);
     node.value?.accept(this);
+    _expectMarker(MarkerTag.Configuration_uri);
     node.uri?.accept(this);
+    _expectMarker(MarkerTag.Configuration_end);
   }
 
   @override
@@ -193,16 +270,22 @@
     _enclosingElements.add(element.enclosingElement);
     _enclosingElements.add(element);
 
+    _expectMarker(MarkerTag.ConstructorDeclaration_returnType);
     node.returnType?.accept(this);
+    _expectMarker(MarkerTag.ConstructorDeclaration_parameters);
     node.parameters?.accept(this);
 
     for (var parameter in node.parameters.parameters) {
       _localElements.add(parameter.declaredElement);
     }
 
+    _expectMarker(MarkerTag.ConstructorDeclaration_initializers);
     node.initializers?.accept(this);
+    _expectMarker(MarkerTag.ConstructorDeclaration_redirectedConstructor);
     node.redirectedConstructor?.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.ConstructorDeclaration_classMember);
+    _classMember(node);
+    _expectMarker(MarkerTag.ConstructorDeclaration_end);
 
     _enclosingElements.removeLast();
     _enclosingElements.removeLast();
@@ -210,8 +293,11 @@
 
   @override
   void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    _expectMarker(MarkerTag.ConstructorFieldInitializer_fieldName);
     node.fieldName.accept(this);
+    _expectMarker(MarkerTag.ConstructorFieldInitializer_expression);
     node.expression.accept(this);
+    _expectMarker(MarkerTag.ConstructorFieldInitializer_end);
   }
 
   @override
@@ -236,16 +322,24 @@
       node.name = typeName.identifier;
     }
 
+    _expectMarker(MarkerTag.ConstructorName_type);
     node.type.accept(this);
+    _expectMarker(MarkerTag.ConstructorName_name);
     node.name?.accept(this);
+    _expectMarker(MarkerTag.ConstructorName_staticElement);
     node.staticElement = _nextElement();
+    _expectMarker(MarkerTag.ConstructorName_end);
   }
 
   @override
   void visitDeclaredIdentifier(DeclaredIdentifier node) {
+    _expectMarker(MarkerTag.DeclaredIdentifier_type);
     node.type?.accept(this);
+    _expectMarker(MarkerTag.DeclaredIdentifier_identifier);
     // node.identifier.accept(this);
+    _expectMarker(MarkerTag.DeclaredIdentifier_declaration);
     _declaration(node);
+    _expectMarker(MarkerTag.DeclaredIdentifier_end);
   }
 
   @override
@@ -269,8 +363,11 @@
     var summaryData = nodeImpl.summaryData as SummaryDataForFormalParameter;
     element.setCodeRange(summaryData.codeOffset, summaryData.codeLength);
 
+    _expectMarker(MarkerTag.DefaultFormalParameter_parameter);
     node.parameter.accept(this);
+    _expectMarker(MarkerTag.DefaultFormalParameter_defaultValue);
     node.defaultValue?.accept(this);
+    _expectMarker(MarkerTag.DefaultFormalParameter_end);
   }
 
   @override
@@ -285,19 +382,28 @@
 
   @override
   void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.EnumConstantDeclaration_name);
+    _expectMarker(MarkerTag.EnumConstantDeclaration_declaration);
+    _declaration(node);
+    _expectMarker(MarkerTag.EnumConstantDeclaration_end);
   }
 
   @override
   void visitEnumDeclaration(EnumDeclaration node) {
+    _expectMarker(MarkerTag.EnumDeclaration_constants);
     node.constants.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.EnumDeclaration_namedCompilationUnitMember);
+    _namedCompilationUnitMember(node);
+    _expectMarker(MarkerTag.EnumDeclaration_end);
   }
 
   @override
   void visitExportDirective(ExportDirective node) {
+    _expectMarker(MarkerTag.ExportDirective_namespaceDirective);
     _namespaceDirective(node);
+    _expectMarker(MarkerTag.ExportDirective_exportedLibrary);
     (node.element as ExportElementImpl).exportedLibrary = _nextElement();
+    _expectMarker(MarkerTag.ExportDirective_end);
   }
 
   @override
@@ -307,7 +413,9 @@
 
   @override
   visitExtendsClause(ExtendsClause node) {
+    _expectMarker(MarkerTag.ExtendsClause_superclass);
     node.superclass.accept(this);
+    _expectMarker(MarkerTag.ExtendsClause_end);
   }
 
   @override
@@ -317,9 +425,13 @@
     var element = node.declaredElement as ExtensionElementImpl;
     _enclosingElements.add(element);
 
+    _expectMarker(MarkerTag.ExtensionDeclaration_typeParameters);
     node.typeParameters?.accept(this);
+    _expectMarker(MarkerTag.ExtensionDeclaration_extendedType);
     node.extendedType?.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.ExtensionDeclaration_compilationUnitMember);
+    _compilationUnitMember(node);
+    _expectMarker(MarkerTag.ExtensionDeclaration_end);
 
     _enclosingElements.removeLast();
   }
@@ -335,10 +447,15 @@
       _resolution.readByte();
     }
 
+    _expectMarker(MarkerTag.ExtensionOverride_extensionName);
     node.extensionName.accept(this);
+    _expectMarker(MarkerTag.ExtensionOverride_typeArguments);
     node.typeArguments?.accept(this);
+    _expectMarker(MarkerTag.ExtensionOverride_argumentList);
     node.argumentList.accept(this);
+    _expectMarker(MarkerTag.ExtensionOverride_extendedType);
     (node as ExtensionOverrideImpl).extendedType = _nextType();
+    _expectMarker(MarkerTag.ExtensionOverride_end);
     // TODO(scheglov) typeArgumentTypes?
   }
 
@@ -347,8 +464,11 @@
     _assertNoLocalElements();
     _pushEnclosingClassTypeParameters(node);
 
+    _expectMarker(MarkerTag.FieldDeclaration_fields);
     node.fields.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.FieldDeclaration_classMember);
+    _classMember(node);
+    _expectMarker(MarkerTag.FieldDeclaration_end);
   }
 
   @override
@@ -362,29 +482,42 @@
 
     var localElementsLength = _localElements.length;
 
+    _expectMarker(MarkerTag.FieldFormalParameter_typeParameters);
     node.typeParameters?.accept(this);
+    _expectMarker(MarkerTag.FieldFormalParameter_type);
     node.type?.accept(this);
+    _expectMarker(MarkerTag.FieldFormalParameter_parameters);
     node.parameters?.accept(this);
+    _expectMarker(MarkerTag.FieldFormalParameter_normalFormalParameter);
     _normalFormalParameter(node, element);
+    _expectMarker(MarkerTag.FieldFormalParameter_end);
 
     _localElements.length = localElementsLength;
   }
 
   @override
   void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+    _expectMarker(MarkerTag.ForEachPartsWithDeclaration_loopVariable);
     node.loopVariable.accept(this);
+    _expectMarker(MarkerTag.ForEachPartsWithDeclaration_forEachParts);
     _forEachParts(node);
+    _expectMarker(MarkerTag.ForEachPartsWithDeclaration_end);
   }
 
   @override
   void visitForElement(ForElement node) {
+    _expectMarker(MarkerTag.ForElement_body);
     node.body.accept(this);
-    node.forLoopParts.accept(this);
+    _expectMarker(MarkerTag.ForElement_forMixin);
+    _forMixin(node as ForElementImpl);
+    _expectMarker(MarkerTag.ForElement_end);
   }
 
   @override
   visitFormalParameterList(FormalParameterList node) {
+    _expectMarker(MarkerTag.FormalParameterList_parameters);
     node.parameters.accept(this);
+    _expectMarker(MarkerTag.FormalParameterList_end);
   }
 
   @override
@@ -396,8 +529,20 @@
         nameNode.offset,
       );
     }
+    _expectMarker(MarkerTag.ForPartsWithDeclarations_variables);
     node.variables.accept(this);
+    _expectMarker(MarkerTag.ForPartsWithDeclarations_forParts);
     _forParts(node);
+    _expectMarker(MarkerTag.ForPartsWithDeclarations_end);
+  }
+
+  @override
+  void visitForPartsWithExpression(ForPartsWithExpression node) {
+    _expectMarker(MarkerTag.ForPartsWithExpression_initialization);
+    node.initialization?.accept(this);
+    _expectMarker(MarkerTag.ForPartsWithExpression_forParts);
+    _forParts(node);
+    _expectMarker(MarkerTag.ForPartsWithExpression_end);
   }
 
   @override
@@ -409,17 +554,25 @@
 
     _enclosingElements.add(element);
 
+    _expectMarker(MarkerTag.FunctionDeclaration_functionExpression);
     node.functionExpression.accept(this);
+    _expectMarker(MarkerTag.FunctionDeclaration_returnType);
     node.returnType?.accept(this);
 
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.FunctionDeclaration_namedCompilationUnitMember);
+    _namedCompilationUnitMember(node);
+    _expectMarker(MarkerTag.FunctionDeclaration_returnTypeType);
     element.returnType = _nextType();
+    _expectMarker(MarkerTag.FunctionDeclaration_end);
   }
 
   @override
   void visitFunctionExpression(FunctionExpression node) {
+    _expectMarker(MarkerTag.FunctionExpression_typeParameters);
     node.typeParameters?.accept(this);
+    _expectMarker(MarkerTag.FunctionExpression_parameters);
     node.parameters?.accept(this);
+    _expectMarker(MarkerTag.FunctionExpression_end);
   }
 
   @override
@@ -433,8 +586,11 @@
       _resolution.readByte();
     }
 
+    _expectMarker(MarkerTag.FunctionExpressionInvocation_function);
     node.function.accept(this);
+    _expectMarker(MarkerTag.FunctionExpressionInvocation_invocationExpression);
     _invocationExpression(node);
+    _expectMarker(MarkerTag.FunctionExpressionInvocation_end);
   }
 
   @override
@@ -444,18 +600,25 @@
     var element = node.declaredElement as FunctionTypeAliasElementImpl;
     _enclosingElements.add(element);
 
+    _expectMarker(MarkerTag.FunctionTypeAlias_typeParameters);
     node.typeParameters?.accept(this);
 
     _enclosingElements.add(element.function);
+    _expectMarker(MarkerTag.FunctionTypeAlias_returnType);
     node.returnType?.accept(this);
+    _expectMarker(MarkerTag.FunctionTypeAlias_parameters);
     node.parameters?.accept(this);
     _enclosingElements.removeLast();
 
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.FunctionTypeAlias_typeAlias);
+    _typeAlias(node);
 
+    _expectMarker(MarkerTag.FunctionTypeAlias_returnTypeType);
     element.function.returnType = _nextType();
+    _expectMarker(MarkerTag.FunctionTypeAlias_flags);
     element.isSimplyBounded = _resolution.readByte() != 0;
     element.hasSelfReference = _resolution.readByte() != 0;
+    _expectMarker(MarkerTag.FunctionTypeAlias_end);
 
     _enclosingElements.removeLast();
   }
@@ -471,10 +634,15 @@
 
     var localElementsLength = _localElements.length;
 
+    _expectMarker(MarkerTag.FunctionTypedFormalParameter_typeParameters);
     node.typeParameters?.accept(this);
+    _expectMarker(MarkerTag.FunctionTypedFormalParameter_returnType);
     node.returnType?.accept(this);
+    _expectMarker(MarkerTag.FunctionTypedFormalParameter_parameters);
     node.parameters?.accept(this);
+    _expectMarker(MarkerTag.FunctionTypedFormalParameter_normalFormalParameter);
     _normalFormalParameter(node, element);
+    _expectMarker(MarkerTag.FunctionTypedFormalParameter_end);
 
     _localElements.length = localElementsLength;
   }
@@ -489,10 +657,15 @@
         _enclosingElements.last, null, node);
     _enclosingElements.add(element);
 
+    _expectMarker(MarkerTag.GenericFunctionType_typeParameters);
     node.typeParameters?.accept(this);
+    _expectMarker(MarkerTag.GenericFunctionType_returnType);
     node.returnType?.accept(this);
+    _expectMarker(MarkerTag.GenericFunctionType_parameters);
     node.parameters?.accept(this);
+    _expectMarker(MarkerTag.GenericFunctionType_type);
     nodeImpl.type = _nextType();
+    _expectMarker(MarkerTag.GenericFunctionType_end);
 
     _localElements.length = localElementsLength;
     _enclosingElements.removeLast();
@@ -507,11 +680,16 @@
 
     _enclosingElements.add(element);
 
+    _expectMarker(MarkerTag.GenericTypeAlias_typeParameters);
     node.typeParameters?.accept(this);
+    _expectMarker(MarkerTag.GenericTypeAlias_type);
     node.type?.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.GenericTypeAlias_typeAlias);
+    _typeAlias(node);
+    _expectMarker(MarkerTag.GenericTypeAlias_flags);
     element.isSimplyBounded = _resolution.readByte() != 0;
     element.hasSelfReference = _resolution.readByte() != 0;
+    _expectMarker(MarkerTag.GenericTypeAlias_end);
 
     _enclosingElements.removeLast();
   }
@@ -523,30 +701,45 @@
 
   @override
   void visitIfElement(IfElement node) {
+    _expectMarker(MarkerTag.IfElement_condition);
     node.condition.accept(this);
+    _expectMarker(MarkerTag.IfElement_thenElement);
     node.thenElement.accept(this);
+    _expectMarker(MarkerTag.IfElement_elseElement);
     node.elseElement?.accept(this);
+    _expectMarker(MarkerTag.IfElement_end);
   }
 
   @override
   visitImplementsClause(ImplementsClause node) {
+    _expectMarker(MarkerTag.ImplementsClause_interfaces);
     node.interfaces.accept(this);
+    _expectMarker(MarkerTag.ImplementsClause_end);
   }
 
   @override
   void visitImportDirective(ImportDirective node) {
+    _expectMarker(MarkerTag.ImportDirective_namespaceDirective);
     _namespaceDirective(node);
 
     var element = node.element as ImportElementImpl;
+    _expectMarker(MarkerTag.ImportDirective_importedLibrary);
     element.importedLibrary = _nextElement();
+
+    _expectMarker(MarkerTag.ImportDirective_end);
   }
 
   @override
   void visitIndexExpression(IndexExpression node) {
+    _expectMarker(MarkerTag.IndexExpression_target);
     node.target?.accept(this);
+    _expectMarker(MarkerTag.IndexExpression_index);
     node.index.accept(this);
+    _expectMarker(MarkerTag.IndexExpression_staticElement);
     node.staticElement = _nextElement();
+    _expectMarker(MarkerTag.IndexExpression_expression);
     _expression(node);
+    _expectMarker(MarkerTag.IndexExpression_end);
   }
 
   @override
@@ -560,10 +753,13 @@
       _resolution.readByte();
     }
 
+    _expectMarker(MarkerTag.InstanceCreationExpression_constructorName);
     node.constructorName.accept(this);
-    (node as InstanceCreationExpressionImpl).typeArguments?.accept(this);
+    _expectMarker(MarkerTag.InstanceCreationExpression_argumentList);
     node.argumentList.accept(this);
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.InstanceCreationExpression_expression);
+    _expression(node);
+    _expectMarker(MarkerTag.InstanceCreationExpression_end);
     _resolveNamedExpressions(
       node.constructorName.staticElement,
       node.argumentList,
@@ -572,7 +768,7 @@
 
   @override
   void visitIntegerLiteral(IntegerLiteral node) {
-    node.staticType = _nextType();
+    _expression(node);
   }
 
   @override
@@ -587,9 +783,13 @@
 
   @override
   void visitIsExpression(IsExpression node) {
+    _expectMarker(MarkerTag.IsExpression_expression);
     node.expression.accept(this);
+    _expectMarker(MarkerTag.IsExpression_type);
     node.type.accept(this);
+    _expectMarker(MarkerTag.IsExpression_expression2);
     _expression(node);
+    _expectMarker(MarkerTag.IsExpression_end);
   }
 
   @override
@@ -605,14 +805,20 @@
 
   @override
   void visitListLiteral(ListLiteral node) {
+    _expectMarker(MarkerTag.ListLiteral_typeArguments);
     node.typeArguments?.accept(this);
+    _expectMarker(MarkerTag.ListLiteral_elements);
     node.elements.accept(this);
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.ListLiteral_expression);
+    _expression(node);
+    _expectMarker(MarkerTag.ListLiteral_end);
   }
 
   @override
   void visitMapLiteralEntry(MapLiteralEntry node) {
+    _expectMarker(MarkerTag.MapLiteralEntry_key);
     node.key.accept(this);
+    _expectMarker(MarkerTag.MapLiteralEntry_value);
     node.value.accept(this);
   }
 
@@ -625,16 +831,37 @@
     _enclosingElements.add(element.enclosingElement);
     _enclosingElements.add(element);
 
-    node.typeParameters?.accept(this);
-    node.returnType?.accept(this);
-    node.parameters?.accept(this);
-    node.metadata?.accept(this);
+    try {
+      _expectMarker(MarkerTag.MethodDeclaration_typeParameters);
+      node.typeParameters?.accept(this);
+      _expectMarker(MarkerTag.MethodDeclaration_returnType);
+      node.returnType?.accept(this);
+      _expectMarker(MarkerTag.MethodDeclaration_parameters);
+      node.parameters?.accept(this);
+      _expectMarker(MarkerTag.MethodDeclaration_classMember);
+      _classMember(node);
 
-    element.returnType = _nextType();
-    _setTopLevelInferenceError(element);
-    if (element is MethodElementImpl) {
-      element.isOperatorEqualWithParameterTypeFromObject =
-          _resolution.readByte() != 0;
+      _expectMarker(MarkerTag.MethodDeclaration_returnTypeType);
+      element.returnType = _nextType();
+      _expectMarker(MarkerTag.MethodDeclaration_inferenceError);
+      _setTopLevelInferenceError(element);
+      if (element is MethodElementImpl) {
+        _expectMarker(MarkerTag.MethodDeclaration_flags);
+        element.isOperatorEqualWithParameterTypeFromObject =
+            _resolution.readByte() != 0;
+      }
+      _expectMarker(MarkerTag.MethodDeclaration_end);
+    } catch (e, stackTrace) {
+      // TODO(scheglov) Remove after fixing http://dartbug.com/44449
+      var headerStr = _astCodeBeforeMarkerOrMaxLength(node, '{', 1000);
+      throw CaughtExceptionWithFiles(e, stackTrace, {
+        'state': '''
+element: ${element.reference}
+header: $headerStr
+resolution.bytes.length: ${_resolution.bytes.length}
+resolution.byteOffset: ${_resolution.byteOffset}
+''',
+      });
     }
 
     _enclosingElements.removeLast();
@@ -725,9 +952,13 @@
       throw StateError('[rewriteTag: $rewriteTag][node: $node]');
     }
 
+    _expectMarker(MarkerTag.MethodInvocation_target);
     node.target?.accept(this);
+    _expectMarker(MarkerTag.MethodInvocation_methodName);
     node.methodName.accept(this);
+    _expectMarker(MarkerTag.MethodInvocation_invocationExpression);
     _invocationExpression(node);
+    _expectMarker(MarkerTag.MethodInvocation_end);
   }
 
   @override
@@ -738,22 +969,31 @@
     element.superInvokedNames = _resolution.readStringList();
     _enclosingElements.add(element);
 
+    _expectMarker(MarkerTag.MixinDeclaration_typeParameters);
     node.typeParameters?.accept(this);
+    _expectMarker(MarkerTag.MixinDeclaration_onClause);
     node.onClause?.accept(this);
+    _expectMarker(MarkerTag.MixinDeclaration_implementsClause);
     node.implementsClause?.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.MixinDeclaration_namedCompilationUnitMember);
+    _namedCompilationUnitMember(node);
+    _expectMarker(MarkerTag.MixinDeclaration_end);
 
     _enclosingElements.removeLast();
   }
 
   @override
   void visitNamedExpression(NamedExpression node) {
+    _expectMarker(MarkerTag.NamedExpression_expression);
     node.expression.accept(this);
+    _expectMarker(MarkerTag.NamedExpression_end);
   }
 
   @override
   void visitNativeClause(NativeClause node) {
+    _expectMarker(MarkerTag.NativeClause_name);
     node.name.accept(this);
+    _expectMarker(MarkerTag.NativeClause_end);
   }
 
   @override
@@ -763,13 +1003,18 @@
 
   @override
   void visitOnClause(OnClause node) {
+    _expectMarker(MarkerTag.OnClause_superclassConstraints);
     node.superclassConstraints.accept(this);
+    _expectMarker(MarkerTag.OnClause_end);
   }
 
   @override
   void visitParenthesizedExpression(ParenthesizedExpression node) {
+    _expectMarker(MarkerTag.ParenthesizedExpression_expression);
     node.expression.accept(this);
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.ParenthesizedExpression_expression2);
+    _expression(node);
+    _expectMarker(MarkerTag.ParenthesizedExpression_end);
   }
 
   @override
@@ -779,64 +1024,98 @@
 
   @override
   void visitPartOfDirective(PartOfDirective node) {
+    _expectMarker(MarkerTag.PartOfDirective_libraryName);
+    node.libraryName?.accept(this);
+    _expectMarker(MarkerTag.PartOfDirective_uri);
     node.uri?.accept(this);
+    _expectMarker(MarkerTag.PartOfDirective_directive);
     _directive(node);
+    _expectMarker(MarkerTag.PartOfDirective_end);
   }
 
   @override
   void visitPostfixExpression(PostfixExpression node) {
     var nodeImpl = node as PostfixExpressionImpl;
+    _expectMarker(MarkerTag.PostfixExpression_operand);
     node.operand.accept(this);
+    _expectMarker(MarkerTag.PostfixExpression_staticElement);
     node.staticElement = _nextElement();
     if (node.operator.type.isIncrementOperator) {
+      _expectMarker(MarkerTag.PostfixExpression_readElement);
       nodeImpl.readElement = _nextElement();
+      _expectMarker(MarkerTag.PostfixExpression_readType);
       nodeImpl.readType = _nextType();
+      _expectMarker(MarkerTag.PostfixExpression_writeElement);
       nodeImpl.writeElement = _nextElement();
+      _expectMarker(MarkerTag.PostfixExpression_writeType);
       nodeImpl.writeType = _nextType();
     }
+    _expectMarker(MarkerTag.PostfixExpression_expression);
     _expression(node);
+    _expectMarker(MarkerTag.PostfixExpression_end);
   }
 
   @override
   void visitPrefixedIdentifier(PrefixedIdentifier node) {
+    _expectMarker(MarkerTag.PrefixedIdentifier_prefix);
     node.prefix.accept(this);
+    _expectMarker(MarkerTag.PrefixedIdentifier_identifier);
     node.identifier.accept(this);
+    _expectMarker(MarkerTag.PrefixedIdentifier_expression);
     _expression(node);
+    _expectMarker(MarkerTag.PrefixedIdentifier_end);
   }
 
   @override
   void visitPrefixExpression(PrefixExpression node) {
     var nodeImpl = node as PrefixExpressionImpl;
+    _expectMarker(MarkerTag.PrefixExpression_operand);
     node.operand.accept(this);
+    _expectMarker(MarkerTag.PrefixExpression_staticElement);
     node.staticElement = _nextElement();
     if (node.operator.type.isIncrementOperator) {
+      _expectMarker(MarkerTag.PrefixExpression_readElement);
       nodeImpl.readElement = _nextElement();
+      _expectMarker(MarkerTag.PrefixExpression_readType);
       nodeImpl.readType = _nextType();
+      _expectMarker(MarkerTag.PrefixExpression_writeElement);
       nodeImpl.writeElement = _nextElement();
+      _expectMarker(MarkerTag.PrefixExpression_writeType);
       nodeImpl.writeType = _nextType();
     }
+    _expectMarker(MarkerTag.PrefixExpression_expression);
     _expression(node);
+    _expectMarker(MarkerTag.PrefixExpression_end);
   }
 
   @override
   void visitPropertyAccess(PropertyAccess node) {
+    _expectMarker(MarkerTag.PropertyAccess_target);
     node.target?.accept(this);
+    _expectMarker(MarkerTag.PropertyAccess_propertyName);
     node.propertyName.accept(this);
 
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.PropertyAccess_expression);
+    _expression(node);
+    _expectMarker(MarkerTag.PropertyAccess_end);
   }
 
   @override
   void visitRedirectingConstructorInvocation(
       RedirectingConstructorInvocation node) {
+    _expectMarker(MarkerTag.RedirectingConstructorInvocation_constructorName);
     node.constructorName?.accept(this);
+    _expectMarker(MarkerTag.RedirectingConstructorInvocation_argumentList);
     node.argumentList.accept(this);
+    _expectMarker(MarkerTag.RedirectingConstructorInvocation_staticElement);
     node.staticElement = _nextElement();
     _resolveNamedExpressions(node.staticElement, node.argumentList);
+    _expectMarker(MarkerTag.RedirectingConstructorInvocation_end);
   }
 
   @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
+    _expectMarker(MarkerTag.SetOrMapLiteral_flags);
     var mapOrSetBits = _resolution.readByte();
     if ((mapOrSetBits & 0x01) != 0) {
       (node as SetOrMapLiteralImpl).becomeMap();
@@ -844,9 +1123,13 @@
       (node as SetOrMapLiteralImpl).becomeSet();
     }
 
+    _expectMarker(MarkerTag.SetOrMapLiteral_typeArguments);
     node.typeArguments?.accept(this);
+    _expectMarker(MarkerTag.SetOrMapLiteral_elements);
     node.elements.accept(this);
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.SetOrMapLiteral_expression);
+    _expression(node);
+    _expectMarker(MarkerTag.SetOrMapLiteral_end);
   }
 
   @override
@@ -863,16 +1146,23 @@
           ParameterElementImpl.forLinkedNodeFactory(enclosing, null, node);
     }
 
+    _expectMarker(MarkerTag.SimpleFormalParameter_type);
     node.type?.accept(this);
+    _expectMarker(MarkerTag.SimpleFormalParameter_normalFormalParameter);
     _normalFormalParameter(node, element);
 
+    _expectMarker(MarkerTag.SimpleFormalParameter_flags);
     element.inheritsCovariant = _resolution.readByte() != 0;
+    _expectMarker(MarkerTag.SimpleFormalParameter_end);
   }
 
   @override
   visitSimpleIdentifier(SimpleIdentifier node) {
+    _expectMarker(MarkerTag.SimpleIdentifier_staticElement);
     node.staticElement = _nextElement();
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.SimpleIdentifier_expression);
+    _expression(node);
+    _expectMarker(MarkerTag.SimpleIdentifier_end);
   }
 
   @override
@@ -882,61 +1172,86 @@
 
   @override
   void visitSpreadElement(SpreadElement node) {
+    _expectMarker(MarkerTag.SpreadElement_expression);
     node.expression.accept(this);
+    _expectMarker(MarkerTag.SpreadElement_end);
   }
 
   @override
   void visitStringInterpolation(StringInterpolation node) {
+    _expectMarker(MarkerTag.StringInterpolation_elements);
     node.elements.accept(this);
+    _expectMarker(MarkerTag.StringInterpolation_end);
     // TODO(scheglov) type?
   }
 
   @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    _expectMarker(MarkerTag.SuperConstructorInvocation_constructorName);
     node.constructorName?.accept(this);
+    _expectMarker(MarkerTag.SuperConstructorInvocation_argumentList);
     node.argumentList.accept(this);
+    _expectMarker(MarkerTag.SuperConstructorInvocation_staticElement);
     node.staticElement = _nextElement();
     _resolveNamedExpressions(node.staticElement, node.argumentList);
+    _expectMarker(MarkerTag.SuperConstructorInvocation_end);
   }
 
   @override
   void visitSuperExpression(SuperExpression node) {
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.SuperExpression_expression);
+    _expression(node);
+    _expectMarker(MarkerTag.SuperExpression_end);
   }
 
   @override
   void visitSymbolLiteral(SymbolLiteral node) {
-    node.staticType = _nextType();
+    _expression(node);
   }
 
   @override
   void visitThisExpression(ThisExpression node) {
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.ThisExpression_expression);
+    _expression(node);
+    _expectMarker(MarkerTag.ThisExpression_end);
   }
 
   @override
   void visitThrowExpression(ThrowExpression node) {
+    _expectMarker(MarkerTag.ThrowExpression_expression);
     node.expression.accept(this);
-    node.staticType = _nextType();
+    _expectMarker(MarkerTag.ThrowExpression_expression2);
+    _expression(node);
+    _expectMarker(MarkerTag.ThrowExpression_end);
   }
 
   @override
   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    _expectMarker(MarkerTag.TopLevelVariableDeclaration_variables);
     node.variables.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.TopLevelVariableDeclaration_compilationUnitMember);
+    _compilationUnitMember(node);
+    _expectMarker(MarkerTag.TopLevelVariableDeclaration_end);
   }
 
   @override
   visitTypeArgumentList(TypeArgumentList node) {
+    _expectMarker(MarkerTag.TypeArgumentList_arguments);
     node.arguments?.accept(this);
+    _expectMarker(MarkerTag.TypeArgumentList_end);
   }
 
   @override
   visitTypeName(TypeName node) {
+    _expectMarker(MarkerTag.TypeName_name);
     node.name.accept(this);
+    _expectMarker(MarkerTag.TypeName_typeArguments);
     node.typeArguments?.accept(this);
 
+    _expectMarker(MarkerTag.TypeName_type);
     node.type = _nextType();
+
+    _expectMarker(MarkerTag.TypeName_end);
   }
 
   @override
@@ -949,6 +1264,7 @@
       _localElements.add(element);
     }
 
+    _expectMarker(MarkerTag.TypeParameterList_typeParameters);
     for (var node in node.typeParameters) {
       var nodeImpl = node as TypeParameterImpl;
       var element = node.declaredElement as TypeParameterElementImpl;
@@ -956,17 +1272,22 @@
       var summaryData = nodeImpl.summaryData as SummaryDataForTypeParameter;
       element.setCodeRange(summaryData.codeOffset, summaryData.codeLength);
 
+      _expectMarker(MarkerTag.TypeParameter_bound);
       node.bound?.accept(this);
       element.bound = node.bound?.type;
 
-      node.metadata.accept(this);
+      _expectMarker(MarkerTag.TypeParameter_declaration);
+      _declaration(node);
       element.metadata = _buildAnnotations(
         _unitContext.element,
         node.metadata,
       );
 
+      _expectMarker(MarkerTag.TypeParameter_variance);
       element.variance = _decodeVariance(_resolution.readByte());
+      _expectMarker(MarkerTag.TypeParameter_defaultType);
       element.defaultType = _nextType();
+      _expectMarker(MarkerTag.TypeParameter_end);
 
       // TODO(scheglov) We used to do this with the previous elements impl.
       // We probably still do this.
@@ -996,34 +1317,48 @@
         }
       }
     }
+    _expectMarker(MarkerTag.TypeParameterList_end);
   }
 
   @override
   void visitVariableDeclaration(VariableDeclaration node) {
     var element = node.declaredElement as VariableElementImpl;
+    _expectMarker(MarkerTag.VariableDeclaration_type);
     element.type = _nextType();
+    _expectMarker(MarkerTag.VariableDeclaration_inferenceError);
     _setTopLevelInferenceError(element);
     if (element is FieldElementImpl) {
+      _expectMarker(MarkerTag.VariableDeclaration_inheritsCovariant);
       element.inheritsCovariant = _resolution.readByte() != 0;
     }
 
+    _expectMarker(MarkerTag.VariableDeclaration_initializer);
     node.initializer?.accept(this);
+    _expectMarker(MarkerTag.VariableDeclaration_end);
   }
 
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
+    _expectMarker(MarkerTag.VariableDeclarationList_type);
     node.type?.accept(this);
+    _expectMarker(MarkerTag.VariableDeclarationList_variables);
     node.variables.accept(this);
-    node.metadata?.accept(this);
+    _expectMarker(MarkerTag.VariableDeclarationList_annotatedNode);
+    _annotatedNode(node);
+    _expectMarker(MarkerTag.VariableDeclarationList_end);
   }
 
   @override
   void visitWithClause(WithClause node) {
+    _expectMarker(MarkerTag.WithClause_mixinTypes);
     node.mixinTypes.accept(this);
+    _expectMarker(MarkerTag.WithClause_end);
   }
 
   void _annotatedNode(AnnotatedNode node) {
+    _expectMarker(MarkerTag.AnnotatedNode_metadata);
     node.metadata?.accept(this);
+    _expectMarker(MarkerTag.AnnotatedNode_end);
   }
 
   void _assertNoLocalElements() {
@@ -1050,6 +1385,11 @@
     return annotations;
   }
 
+  void _classMember(ClassMember node) {
+    _expectMarker(MarkerTag.ClassMember_declaration);
+    _declaration(node);
+  }
+
   void _compilationUnitMember(CompilationUnitMember node) {
     _declaration(node);
   }
@@ -1059,34 +1399,66 @@
   }
 
   void _directive(Directive node) {
-    node.metadata?.accept(this);
+    _annotatedNode(node);
+  }
+
+  void _expectMarker(MarkerTag tag) {
+    if (enableDebugResolutionMarkers) {
+      var actualIndex = _resolution.readUInt30();
+      if (actualIndex != tag.index) {
+        if (actualIndex < MarkerTag.values.length) {
+          var actualTag = MarkerTag.values[actualIndex];
+          throw StateError('Expected $tag, found $actualIndex = $actualTag');
+        } else {
+          throw StateError('Expected $tag, found $actualIndex');
+        }
+      }
+    }
   }
 
   void _expression(Expression node) {
+    _expectMarker(MarkerTag.Expression_staticType);
     node.staticType = _nextType();
   }
 
   void _forEachParts(ForEachParts node) {
-    _forLoopParts(node);
+    _expectMarker(MarkerTag.ForEachParts_iterable);
     node.iterable.accept(this);
+    _expectMarker(MarkerTag.ForEachParts_forLoopParts);
+    _forLoopParts(node);
+    _expectMarker(MarkerTag.ForEachParts_end);
   }
 
   void _forLoopParts(ForLoopParts node) {}
 
   void _formalParameter(FormalParameter node) {
+    _expectMarker(MarkerTag.FormalParameter_type);
     (node.declaredElement as ParameterElementImpl).type = _nextType();
   }
 
+  void _forMixin(ForMixin node) {
+    _expectMarker(MarkerTag.ForMixin_forLoopParts);
+    node.forLoopParts.accept(this);
+  }
+
   void _forParts(ForParts node) {
+    _expectMarker(MarkerTag.ForParts_condition);
     node.condition?.accept(this);
+    _expectMarker(MarkerTag.ForParts_updaters);
     node.updaters.accept(this);
+    _expectMarker(MarkerTag.ForParts_forLoopParts);
     _forLoopParts(node);
+    _expectMarker(MarkerTag.ForParts_end);
   }
 
   void _invocationExpression(InvocationExpression node) {
+    _expectMarker(MarkerTag.InvocationExpression_typeArguments);
     node.typeArguments?.accept(this);
+    _expectMarker(MarkerTag.InvocationExpression_argumentList);
     node.argumentList.accept(this);
+    _expectMarker(MarkerTag.InvocationExpression_expression);
     _expression(node);
+    _expectMarker(MarkerTag.InvocationExpression_end);
     // TODO(scheglov) typeArgumentTypes and staticInvokeType?
     var nodeImpl = node as InvocationExpressionImpl;
     nodeImpl.typeArgumentTypes = [];
@@ -1097,9 +1469,13 @@
   }
 
   void _namespaceDirective(NamespaceDirective node) {
+    _expectMarker(MarkerTag.NamespaceDirective_combinators);
     node.combinators?.accept(this);
+    _expectMarker(MarkerTag.NamespaceDirective_configurations);
     node.configurations?.accept(this);
+    _expectMarker(MarkerTag.NamespaceDirective_uriBasedDirective);
     _uriBasedDirective(node);
+    _expectMarker(MarkerTag.NamespaceDirective_end);
   }
 
   Element _nextElement() {
@@ -1120,8 +1496,11 @@
       element.setCodeRange(summaryData.codeOffset, summaryData.codeLength);
     }
 
+    _expectMarker(MarkerTag.NormalFormalParameter_metadata);
     node.metadata?.accept(this);
+    _expectMarker(MarkerTag.NormalFormalParameter_formalParameter);
     _formalParameter(node);
+    _expectMarker(MarkerTag.NormalFormalParameter_end);
   }
 
   /// TODO(scheglov) also enclosing elements
@@ -1175,9 +1554,27 @@
     }
   }
 
+  void _typeAlias(TypeAlias node) {
+    _namedCompilationUnitMember(node);
+  }
+
   void _uriBasedDirective(UriBasedDirective node) {
-    _directive(node);
+    _expectMarker(MarkerTag.UriBasedDirective_uri);
     node.uri.accept(this);
+    _expectMarker(MarkerTag.UriBasedDirective_directive);
+    _directive(node);
+    _expectMarker(MarkerTag.UriBasedDirective_end);
+  }
+
+  /// TODO(scheglov) Remove after fixing http://dartbug.com/44449
+  static String _astCodeBeforeMarkerOrMaxLength(
+      AstNode node, String marker, int maxLength) {
+    var nodeStr = '$node';
+    var indexOfBody = nodeStr.indexOf(marker);
+    if (indexOfBody == -1) {
+      indexOfBody = min(maxLength, nodeStr.length);
+    }
+    return nodeStr.substring(0, indexOfBody);
   }
 
   static Variance _decodeVariance(int encoding) {
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart b/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
index 9bdefc7..4c23e9f 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
@@ -4,6 +4,17 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 
+/// When this option enabled, when we write AST and resolution, we write
+/// into markers into the resolution stream, so when we apply resolution
+/// to AST, we can be more confident that we are reading resolution data
+/// that is expected to the AST node to which resolution is applied.
+///
+/// This might help us to track if we have a bug and think that some resolution
+/// data can be applied (because its signature is the same), when actually
+/// AST changed in ways that should make resolution incompatible (and so
+/// the resolution signature should have been different).
+bool enableDebugResolutionMarkers = false;
+
 class AstBinaryFlags {
   static final Map<Type, int> _typeBits = {};
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 3bc726f..8be47e2 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -46,6 +46,8 @@
         return _readAssertInitializer();
       case Tag.AssignmentExpression:
         return _readAssignmentExpression();
+      case Tag.AwaitExpression:
+        return _readAwaitExpression();
       case Tag.BinaryExpression:
         return _readBinaryExpression();
       case Tag.BooleanLiteral:
@@ -94,6 +96,8 @@
         return _readForElement();
       case Tag.ForPartsWithDeclarations:
         return _readForPartsWithDeclarations();
+      case Tag.ForPartsWithExpression:
+        return _readForPartsWithExpression();
       case Tag.FieldFormalParameter:
         return _readFieldFormalParameter();
       case Tag.FormalParameterList:
@@ -307,6 +311,11 @@
     );
   }
 
+  AwaitExpression _readAwaitExpression() {
+    var expression = readNode() as Expression;
+    return astFactory.awaitExpression(Tokens.AWAIT, expression);
+  }
+
   BinaryExpression _readBinaryExpression() {
     var leftOperand = readNode() as Expression;
     var rightOperand = readNode() as Expression;
@@ -857,6 +866,19 @@
     );
   }
 
+  ForPartsWithExpression _readForPartsWithExpression() {
+    var initialization = _readOptionalNode() as Expression;
+    var condition = _readOptionalNode() as Expression;
+    var updaters = _readNodeList<Expression>();
+    return astFactory.forPartsWithExpression(
+      condition: condition,
+      initialization: initialization,
+      leftSeparator: Tokens.SEMICOLON,
+      rightSeparator: Tokens.SEMICOLON,
+      updaters: updaters,
+    );
+  }
+
   FunctionDeclaration _readFunctionDeclaration() {
     var flags = _readByte();
     var codeOffset = _readInformativeUint30();
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
index 0c19a9e..43eee8a 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
@@ -2,6 +2,330 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/// When debugging, these tags are written in resolution information to
+/// mark positions where we expect resolution for specific kinds of nodes.
+/// This might help us to be more confident that we are reading resolution
+/// data that corresponds to AST, and find places where they start
+/// diverging.
+enum MarkerTag {
+  AnnotatedNode_metadata,
+  AnnotatedNode_end,
+  Annotation_name,
+  Annotation_constructorName,
+  Annotation_arguments,
+  Annotation_element,
+  ArgumentList_arguments,
+  ArgumentList_end,
+  AsExpression_expression,
+  AsExpression_type,
+  AsExpression_expression2,
+  AsExpression_end,
+  AwaitExpression_expression,
+  AwaitExpression_expression2,
+  AwaitExpression_end,
+  Expression_staticType,
+  AssertInitializer_condition,
+  AssertInitializer_message,
+  AssertInitializer_end,
+  AssignmentExpression_leftHandSide,
+  AssignmentExpression_rightHandSide,
+  AssignmentExpression_staticElement,
+  AssignmentExpression_readElement,
+  AssignmentExpression_readType,
+  AssignmentExpression_writeElement,
+  AssignmentExpression_writeType,
+  AssignmentExpression_expression,
+  AssignmentExpression_end,
+  BinaryExpression_leftOperand,
+  BinaryExpression_rightOperand,
+  BinaryExpression_staticElement,
+  BinaryExpression_expression,
+  BinaryExpression_end,
+  CascadeExpression_target,
+  CascadeExpression_cascadeSections,
+  CascadeExpression_end,
+  ClassDeclaration_typeParameters,
+  ClassDeclaration_extendsClause,
+  ClassDeclaration_withClause,
+  ClassDeclaration_implementsClause,
+  ClassDeclaration_nativeClause,
+  ClassDeclaration_namedCompilationUnitMember,
+  ClassDeclaration_end,
+  ClassMember_declaration,
+  ClassMember_end,
+  ClassTypeAlias_typeParameters,
+  ClassTypeAlias_superclass,
+  ClassTypeAlias_withClause,
+  ClassTypeAlias_implementsClause,
+  ClassTypeAlias_typeAlias,
+  ClassTypeAlias_end,
+  ConditionalExpression_condition,
+  ConditionalExpression_thenExpression,
+  ConditionalExpression_elseExpression,
+  Configuration_name,
+  Configuration_value,
+  Configuration_uri,
+  Configuration_end,
+  ConstructorDeclaration_returnType,
+  ConstructorDeclaration_parameters,
+  ConstructorDeclaration_initializers,
+  ConstructorDeclaration_redirectedConstructor,
+  ConstructorDeclaration_classMember,
+  ConstructorDeclaration_end,
+  ConstructorFieldInitializer_fieldName,
+  ConstructorFieldInitializer_expression,
+  ConstructorFieldInitializer_end,
+  ConstructorName_type,
+  ConstructorName_name,
+  ConstructorName_staticElement,
+  ConstructorName_end,
+  DeclaredIdentifier_type,
+  DeclaredIdentifier_identifier,
+  DeclaredIdentifier_declaration,
+  DeclaredIdentifier_end,
+  DefaultFormalParameter_parameter,
+  DefaultFormalParameter_defaultValue,
+  DefaultFormalParameter_end,
+  EnumConstantDeclaration_name,
+  EnumConstantDeclaration_declaration,
+  EnumConstantDeclaration_end,
+  EnumDeclaration_constants,
+  EnumDeclaration_namedCompilationUnitMember,
+  EnumDeclaration_end,
+  ExportDirective_namespaceDirective,
+  ExportDirective_exportedLibrary,
+  ExportDirective_end,
+  ExtendsClause_superclass,
+  ExtendsClause_end,
+  ExtensionDeclaration_typeParameters,
+  ExtensionDeclaration_extendedType,
+  ExtensionDeclaration_compilationUnitMember,
+  ExtensionDeclaration_end,
+  ExtensionOverride_extensionName,
+  ExtensionOverride_typeArguments,
+  ExtensionOverride_argumentList,
+  ExtensionOverride_extendedType,
+  ExtensionOverride_end,
+  FieldDeclaration_fields,
+  FieldDeclaration_classMember,
+  FieldDeclaration_end,
+  FieldFormalParameter_typeParameters,
+  FieldFormalParameter_type,
+  FieldFormalParameter_parameters,
+  FieldFormalParameter_normalFormalParameter,
+  FieldFormalParameter_end,
+  ForEachParts_iterable,
+  ForEachParts_forLoopParts,
+  ForEachParts_end,
+  ForEachPartsWithDeclaration_loopVariable,
+  ForEachPartsWithDeclaration_forEachParts,
+  ForEachPartsWithDeclaration_end,
+  ForElement_body,
+  ForElement_forMixin,
+  ForElement_end,
+  FormalParameter_type,
+  ForMixin_forLoopParts,
+  ForParts_condition,
+  ForParts_updaters,
+  ForParts_forLoopParts,
+  ForParts_end,
+  FormalParameterList_parameters,
+  FormalParameterList_end,
+  ForPartsWithDeclarations_variables,
+  ForPartsWithDeclarations_forParts,
+  ForPartsWithDeclarations_end,
+  ForPartsWithExpression_initialization,
+  ForPartsWithExpression_forParts,
+  ForPartsWithExpression_end,
+  FunctionDeclaration_functionExpression,
+  FunctionDeclaration_returnType,
+  FunctionDeclaration_namedCompilationUnitMember,
+  FunctionDeclaration_returnTypeType,
+  FunctionDeclaration_end,
+  FunctionExpression_typeParameters,
+  FunctionExpression_parameters,
+  FunctionExpression_end,
+  FunctionExpressionInvocation_function,
+  FunctionExpressionInvocation_invocationExpression,
+  FunctionExpressionInvocation_end,
+  FunctionTypeAlias_typeParameters,
+  FunctionTypeAlias_returnType,
+  FunctionTypeAlias_parameters,
+  FunctionTypeAlias_typeAlias,
+  FunctionTypeAlias_returnTypeType,
+  FunctionTypeAlias_flags,
+  FunctionTypeAlias_end,
+  FunctionTypedFormalParameter_typeParameters,
+  FunctionTypedFormalParameter_returnType,
+  FunctionTypedFormalParameter_parameters,
+  FunctionTypedFormalParameter_normalFormalParameter,
+  FunctionTypedFormalParameter_end,
+  GenericFunctionType_typeParameters,
+  GenericFunctionType_returnType,
+  GenericFunctionType_parameters,
+  GenericFunctionType_type,
+  GenericFunctionType_end,
+  GenericTypeAlias_typeParameters,
+  GenericTypeAlias_type,
+  GenericTypeAlias_typeAlias,
+  GenericTypeAlias_flags,
+  GenericTypeAlias_end,
+  IfElement_condition,
+  IfElement_thenElement,
+  IfElement_elseElement,
+  IfElement_end,
+  ImplementsClause_interfaces,
+  ImplementsClause_end,
+  ImportDirective_namespaceDirective,
+  ImportDirective_importedLibrary,
+  ImportDirective_end,
+  IndexExpression_target,
+  IndexExpression_index,
+  IndexExpression_staticElement,
+  IndexExpression_expression,
+  IndexExpression_end,
+  InstanceCreationExpression_constructorName,
+  InstanceCreationExpression_argumentList,
+  InstanceCreationExpression_expression,
+  InstanceCreationExpression_end,
+  IsExpression_expression,
+  IsExpression_type,
+  IsExpression_expression2,
+  IsExpression_end,
+  InvocationExpression_typeArguments,
+  InvocationExpression_argumentList,
+  InvocationExpression_expression,
+  InvocationExpression_end,
+  ListLiteral_typeArguments,
+  ListLiteral_elements,
+  ListLiteral_expression,
+  ListLiteral_end,
+  MapLiteralEntry_key,
+  MapLiteralEntry_value,
+  MethodDeclaration_typeParameters,
+  MethodDeclaration_returnType,
+  MethodDeclaration_parameters,
+  MethodDeclaration_classMember,
+  MethodDeclaration_returnTypeType,
+  MethodDeclaration_inferenceError,
+  MethodDeclaration_flags,
+  MethodDeclaration_end,
+  MethodInvocation_target,
+  MethodInvocation_methodName,
+  MethodInvocation_invocationExpression,
+  MethodInvocation_end,
+  MixinDeclaration_typeParameters,
+  MixinDeclaration_onClause,
+  MixinDeclaration_implementsClause,
+  MixinDeclaration_namedCompilationUnitMember,
+  MixinDeclaration_end,
+  NamedExpression_expression,
+  NamedExpression_end,
+  NamespaceDirective_combinators,
+  NamespaceDirective_configurations,
+  NamespaceDirective_uriBasedDirective,
+  NamespaceDirective_end,
+  NativeClause_name,
+  NativeClause_end,
+  NormalFormalParameter_metadata,
+  NormalFormalParameter_formalParameter,
+  NormalFormalParameter_end,
+  OnClause_superclassConstraints,
+  OnClause_end,
+  ParenthesizedExpression_expression,
+  ParenthesizedExpression_expression2,
+  ParenthesizedExpression_end,
+  PartOfDirective_libraryName,
+  PartOfDirective_uri,
+  PartOfDirective_directive,
+  PartOfDirective_end,
+  PostfixExpression_operand,
+  PostfixExpression_staticElement,
+  PostfixExpression_readElement,
+  PostfixExpression_readType,
+  PostfixExpression_writeElement,
+  PostfixExpression_writeType,
+  PostfixExpression_expression,
+  PostfixExpression_end,
+  PrefixedIdentifier_prefix,
+  PrefixedIdentifier_identifier,
+  PrefixedIdentifier_expression,
+  PrefixedIdentifier_end,
+  PrefixExpression_operand,
+  PrefixExpression_staticElement,
+  PrefixExpression_readElement,
+  PrefixExpression_readType,
+  PrefixExpression_writeElement,
+  PrefixExpression_writeType,
+  PrefixExpression_expression,
+  PrefixExpression_end,
+  PropertyAccess_target,
+  PropertyAccess_propertyName,
+  PropertyAccess_expression,
+  PropertyAccess_end,
+  RedirectingConstructorInvocation_constructorName,
+  RedirectingConstructorInvocation_argumentList,
+  RedirectingConstructorInvocation_staticElement,
+  RedirectingConstructorInvocation_end,
+  SetOrMapLiteral_flags,
+  SetOrMapLiteral_typeArguments,
+  SetOrMapLiteral_elements,
+  SetOrMapLiteral_expression,
+  SetOrMapLiteral_end,
+  SimpleFormalParameter_type,
+  SimpleFormalParameter_normalFormalParameter,
+  SimpleFormalParameter_flags,
+  SimpleFormalParameter_end,
+  SimpleIdentifier_staticElement,
+  SimpleIdentifier_expression,
+  SimpleIdentifier_end,
+  SpreadElement_expression,
+  SpreadElement_end,
+  StringInterpolation_elements,
+  StringInterpolation_end,
+  SuperConstructorInvocation_constructorName,
+  SuperConstructorInvocation_argumentList,
+  SuperConstructorInvocation_staticElement,
+  SuperConstructorInvocation_end,
+  SuperExpression_expression,
+  SuperExpression_end,
+  ThisExpression_expression,
+  ThisExpression_end,
+  ThrowExpression_expression,
+  ThrowExpression_expression2,
+  ThrowExpression_end,
+  TopLevelVariableDeclaration_variables,
+  TopLevelVariableDeclaration_compilationUnitMember,
+  TopLevelVariableDeclaration_end,
+  TypeArgumentList_arguments,
+  TypeArgumentList_end,
+  TypeName_name,
+  TypeName_typeArguments,
+  TypeName_type,
+  TypeName_end,
+  TypeParameter_bound,
+  TypeParameter_declaration,
+  TypeParameter_variance,
+  TypeParameter_defaultType,
+  TypeParameter_end,
+  TypeParameterList_typeParameters,
+  TypeParameterList_end,
+  UriBasedDirective_uri,
+  UriBasedDirective_directive,
+  UriBasedDirective_end,
+  VariableDeclaration_type,
+  VariableDeclaration_inferenceError,
+  VariableDeclaration_inheritsCovariant,
+  VariableDeclaration_initializer,
+  VariableDeclaration_end,
+  VariableDeclarationList_type,
+  VariableDeclarationList_variables,
+  VariableDeclarationList_annotatedNode,
+  VariableDeclarationList_end,
+  WithClause_mixinTypes,
+  WithClause_end,
+}
+
 /// A `MethodInvocation` in unresolved AST might be rewritten later as
 /// another kinds of AST node. We store this rewrite with resolution data.
 class MethodInvocationRewriteTag {
@@ -22,6 +346,7 @@
   static const int AsExpression = 84;
   static const int AssertInitializer = 82;
   static const int AssignmentExpression = 96;
+  static const int AwaitExpression = 100;
   static const int BinaryExpression = 52;
   static const int BooleanLiteral = 4;
   static const int CascadeExpression = 95;
@@ -47,6 +372,7 @@
   static const int ForEachPartsWithDeclaration = 89;
   static const int ForElement = 88;
   static const int ForPartsWithDeclarations = 91;
+  static const int ForPartsWithExpression = 99;
   static const int FormalParameterList = 17;
   static const int FunctionDeclaration = 18;
   static const int FunctionDeclaration_getter = 57;
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 06f82b6..16e1177 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -34,9 +34,7 @@
   /// for [_classMemberIndexItems]?
   final List<_UnitMemberIndexItem> unitMemberIndexItems = [];
   final List<_ClassMemberIndexItem> _classMemberIndexItems = [];
-  bool _isConstField = false;
-  bool _isFinalField = false;
-  bool _isConstTopLevelVariable = false;
+  bool _shouldStoreVariableInitializers = false;
   bool _hasConstConstructor = false;
   int _nextUnnamedExtensionId = 0;
 
@@ -63,9 +61,12 @@
   void visitAnnotation(Annotation node) {
     _writeByte(Tag.Annotation);
 
+    _writeMarker(MarkerTag.Annotation_name);
     _writeOptionalNode(node.name);
+    _writeMarker(MarkerTag.Annotation_constructorName);
     _writeOptionalNode(node.constructorName);
 
+    _writeMarker(MarkerTag.Annotation_arguments);
     var arguments = node.arguments;
     if (arguments != null) {
       if (!arguments.arguments.every(_isSerializableExpression)) {
@@ -75,6 +76,7 @@
     _writeOptionalNode(arguments);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.Annotation_element);
       _resolutionSink.writeElement(node.element);
     }
   }
@@ -82,29 +84,44 @@
   @override
   void visitArgumentList(ArgumentList node) {
     _writeByte(Tag.ArgumentList);
+    _writeMarker(MarkerTag.ArgumentList_arguments);
     _writeNodeList(node.arguments);
+    _writeMarker(MarkerTag.ArgumentList_end);
   }
 
   @override
   void visitAsExpression(AsExpression node) {
     _writeByte(Tag.AsExpression);
+
+    _writeMarker(MarkerTag.AsExpression_expression);
     _writeNode(node.expression);
+
+    _writeMarker(MarkerTag.AsExpression_type);
     _writeNode(node.type);
+
+    _writeMarker(MarkerTag.AsExpression_expression2);
     _storeExpression(node);
+
+    _writeMarker(MarkerTag.AsExpression_end);
   }
 
   @override
   void visitAssertInitializer(AssertInitializer node) {
     _writeByte(Tag.AssertInitializer);
+    _writeMarker(MarkerTag.AssertInitializer_condition);
     _writeNode(node.condition);
+    _writeMarker(MarkerTag.AssertInitializer_message);
     _writeOptionalNode(node.message);
+    _writeMarker(MarkerTag.AssertInitializer_end);
   }
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
     _writeByte(Tag.AssignmentExpression);
 
+    _writeMarker(MarkerTag.AssignmentExpression_leftHandSide);
     _writeNode(node.leftHandSide);
+    _writeMarker(MarkerTag.AssignmentExpression_rightHandSide);
     _writeNode(node.rightHandSide);
 
     var operatorToken = node.operator.type;
@@ -112,20 +129,42 @@
     _writeByte(binaryToken.index);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.AssignmentExpression_staticElement);
       _resolutionSink.writeElement(node.staticElement);
+      _writeMarker(MarkerTag.AssignmentExpression_readElement);
       _resolutionSink.writeElement(node.readElement);
+      _writeMarker(MarkerTag.AssignmentExpression_readType);
       _resolutionSink.writeType(node.readType);
+      _writeMarker(MarkerTag.AssignmentExpression_writeElement);
       _resolutionSink.writeElement(node.writeElement);
+      _writeMarker(MarkerTag.AssignmentExpression_writeType);
       _resolutionSink.writeType(node.writeType);
     }
+    _writeMarker(MarkerTag.AssignmentExpression_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.AssignmentExpression_end);
+  }
+
+  @override
+  void visitAwaitExpression(AwaitExpression node) {
+    _writeByte(Tag.AwaitExpression);
+
+    _writeMarker(MarkerTag.AwaitExpression_expression);
+    _writeNode(node.expression);
+
+    _writeMarker(MarkerTag.AsExpression_expression2);
+    _storeExpression(node);
+
+    _writeMarker(MarkerTag.AwaitExpression_end);
   }
 
   @override
   void visitBinaryExpression(BinaryExpression node) {
     _writeByte(Tag.BinaryExpression);
 
+    _writeMarker(MarkerTag.BinaryExpression_leftOperand);
     _writeNode(node.leftOperand);
+    _writeMarker(MarkerTag.BinaryExpression_rightOperand);
     _writeNode(node.rightOperand);
 
     var operatorToken = node.operator.type;
@@ -133,9 +172,12 @@
     _writeByte(binaryToken.index);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.BinaryExpression_staticElement);
       _resolutionSink.writeElement(node.staticElement);
-      _resolutionSink.writeType(node.staticType);
     }
+    _writeMarker(MarkerTag.BinaryExpression_expression);
+    _storeExpression(node);
+    _writeMarker(MarkerTag.BinaryExpression_end);
   }
 
   @override
@@ -143,15 +185,18 @@
     _writeByte(Tag.BooleanLiteral);
     _writeByte(node.value ? 1 : 0);
     if (_shouldWriteResolution) {
-      _resolutionSink.writeType(node.staticType);
+      _storeExpression(node);
     }
   }
 
   @override
   void visitCascadeExpression(CascadeExpression node) {
     _writeByte(Tag.CascadeExpression);
+    _writeMarker(MarkerTag.CascadeExpression_target);
     _writeNode(node.target);
+    _writeMarker(MarkerTag.CascadeExpression_cascadeSections);
     _writeNodeList(node.cascadeSections);
+    _writeMarker(MarkerTag.CascadeExpression_end);
   }
 
   @override
@@ -184,12 +229,19 @@
 
     _pushScopeTypeParameters(node.typeParameters);
 
+    _writeMarker(MarkerTag.ClassDeclaration_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.ClassDeclaration_extendsClause);
     _writeOptionalNode(node.extendsClause);
+    _writeMarker(MarkerTag.ClassDeclaration_withClause);
     _writeOptionalNode(node.withClause);
+    _writeMarker(MarkerTag.ClassDeclaration_implementsClause);
     _writeOptionalNode(node.implementsClause);
+    _writeMarker(MarkerTag.ClassDeclaration_nativeClause);
     _writeOptionalNode(node.nativeClause);
+    _writeMarker(MarkerTag.ClassDeclaration_namedCompilationUnitMember);
     _storeNamedCompilationUnitMember(node);
+    _writeMarker(MarkerTag.ClassDeclaration_end);
     _writeUInt30(resolutionIndex);
 
     _classMemberIndexItems.clear();
@@ -238,11 +290,17 @@
     _writeInformativeUint30(node.offset);
     _writeInformativeUint30(node.length);
     _pushScopeTypeParameters(node.typeParameters);
+    _writeMarker(MarkerTag.ClassTypeAlias_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.ClassTypeAlias_superclass);
     _writeNode(node.superclass);
+    _writeMarker(MarkerTag.ClassTypeAlias_withClause);
     _writeNode(node.withClause);
+    _writeMarker(MarkerTag.ClassTypeAlias_implementsClause);
     _writeOptionalNode(node.implementsClause);
+    _writeMarker(MarkerTag.ClassTypeAlias_typeAlias);
     _storeTypeAlias(node);
+    _writeMarker(MarkerTag.ClassTypeAlias_end);
     _writeDocumentationCommentString(node.documentationComment);
     _writeUInt30(resolutionIndex);
     if (_shouldWriteResolution) {
@@ -266,8 +324,11 @@
   @override
   void visitConditionalExpression(ConditionalExpression node) {
     _writeByte(Tag.ConditionalExpression);
+    _writeMarker(MarkerTag.ConditionalExpression_condition);
     _writeNode(node.condition);
+    _writeMarker(MarkerTag.ConditionalExpression_thenExpression);
     _writeNode(node.thenExpression);
+    _writeMarker(MarkerTag.ConditionalExpression_elseExpression);
     _writeNode(node.elseExpression);
     _storeExpression(node);
   }
@@ -282,9 +343,13 @@
       ),
     );
 
+    _writeMarker(MarkerTag.Configuration_name);
     _writeNode(node.name);
+    _writeMarker(MarkerTag.Configuration_value);
     _writeOptionalNode(node.value);
+    _writeMarker(MarkerTag.Configuration_uri);
     _writeNode(node.uri);
+    _writeMarker(MarkerTag.Configuration_end);
   }
 
   @override
@@ -316,11 +381,13 @@
     _writeDocumentationCommentString(node.documentationComment);
 
     var resolutionIndex = _getNextResolutionIndex();
+    _writeMarker(MarkerTag.ConstructorDeclaration_returnType);
     _writeNode(node.returnType);
     if (node.period != null) {
       _writeInformativeUint30(node.period.offset);
       _writeDeclarationName(node.name);
     }
+    _writeMarker(MarkerTag.ConstructorDeclaration_parameters);
     _writeNode(node.parameters);
 
     if (_shouldWriteResolution) {
@@ -332,6 +399,7 @@
 
     // TODO(scheglov) Not nice, we skip both resolution and AST.
     // But eventually we want to store full AST, and partial resolution.
+    _writeMarker(MarkerTag.ConstructorDeclaration_initializers);
     if (node.constKeyword != null) {
       _writeNodeList(node.initializers);
     } else {
@@ -342,8 +410,11 @@
       _resolutionSink.localElements.popScope();
     }
 
+    _writeMarker(MarkerTag.ConstructorDeclaration_redirectedConstructor);
     _writeOptionalNode(node.redirectedConstructor);
+    _writeMarker(MarkerTag.ConstructorDeclaration_classMember);
     _storeClassMember(node);
+    _writeMarker(MarkerTag.ConstructorDeclaration_end);
     _writeUInt30(resolutionIndex);
   }
 
@@ -357,9 +428,11 @@
       ),
     );
 
+    _writeMarker(MarkerTag.ConstructorFieldInitializer_fieldName);
     _writeNode(node.fieldName);
+    _writeMarker(MarkerTag.ConstructorFieldInitializer_expression);
     _writeNode(node.expression);
-    _storeConstructorInitializer(node);
+    _writeMarker(MarkerTag.ConstructorFieldInitializer_end);
   }
 
   @override
@@ -374,12 +447,17 @@
       _resolutionSink.writeByte(node.name != null ? 1 : 0);
     }
 
+    _writeMarker(MarkerTag.ConstructorName_type);
     _writeNode(node.type);
+    _writeMarker(MarkerTag.ConstructorName_name);
     _writeOptionalNode(node.name);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.ConstructorName_staticElement);
       _resolutionSink.writeElement(node.staticElement);
     }
+
+    _writeMarker(MarkerTag.ConstructorName_end);
   }
 
   @override
@@ -392,9 +470,13 @@
         isVar: node.keyword?.keyword == Keyword.VAR,
       ),
     );
+    _writeMarker(MarkerTag.DeclaredIdentifier_type);
     _writeOptionalNode(node.type);
+    _writeMarker(MarkerTag.DeclaredIdentifier_identifier);
     _writeDeclarationName(node.identifier);
+    _writeMarker(MarkerTag.DeclaredIdentifier_declaration);
     _storeDeclaration(node);
+    _writeMarker(MarkerTag.DeclaredIdentifier_end);
   }
 
   @override
@@ -412,13 +494,16 @@
     _writeInformativeUint30(node.offset);
     _writeInformativeUint30(node.length);
 
+    _writeMarker(MarkerTag.DefaultFormalParameter_parameter);
     _writeNode(node.parameter);
 
     var defaultValue = node.defaultValue;
     if (!_isSerializableExpression(defaultValue)) {
       defaultValue = null;
     }
+    _writeMarker(MarkerTag.DefaultFormalParameter_defaultValue);
     _writeOptionalNode(defaultValue);
+    _writeMarker(MarkerTag.DefaultFormalParameter_end);
   }
 
   @override
@@ -441,8 +526,11 @@
     _writeInformativeUint30(node.length);
     _writeDocumentationCommentString(node.documentationComment);
 
+    _writeMarker(MarkerTag.EnumConstantDeclaration_name);
     _writeDeclarationName(node.name);
+    _writeMarker(MarkerTag.EnumConstantDeclaration_declaration);
     _storeDeclaration(node);
+    _writeMarker(MarkerTag.EnumConstantDeclaration_end);
   }
 
   @override
@@ -462,8 +550,11 @@
     _writeInformativeUint30(node.length);
     _writeDocumentationCommentString(node.documentationComment);
 
+    _writeMarker(MarkerTag.EnumDeclaration_constants);
     _writeNodeList(node.constants);
+    _writeMarker(MarkerTag.EnumDeclaration_namedCompilationUnitMember);
     _storeNamedCompilationUnitMember(node);
+    _writeMarker(MarkerTag.EnumDeclaration_end);
     _writeUInt30(resolutionIndex);
   }
 
@@ -472,20 +563,26 @@
     var resolutionIndex = _getNextResolutionIndex();
 
     _writeByte(Tag.ExportDirective);
+    _writeMarker(MarkerTag.ExportDirective_namespaceDirective);
     _storeNamespaceDirective(node);
     _writeUInt30(resolutionIndex);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.ExportDirective_exportedLibrary);
       _resolutionSink.writeElement(
         (node.element as ExportElementImpl).exportedLibrary,
       );
     }
+
+    _writeMarker(MarkerTag.ExportDirective_end);
   }
 
   @override
   void visitExtendsClause(ExtendsClause node) {
     _writeByte(Tag.ExtendsClause);
+    _writeMarker(MarkerTag.ExtendsClause_superclass);
     _writeNode(node.superclass);
+    _writeMarker(MarkerTag.ExtendsClause_end);
   }
 
   @override
@@ -500,10 +597,14 @@
     _writeDocumentationCommentString(node.documentationComment);
 
     _pushScopeTypeParameters(node.typeParameters);
+    _writeMarker(MarkerTag.ExtensionDeclaration_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.ExtensionDeclaration_extendedType);
     _writeNode(node.extendedType);
     _writeOptionalDeclarationName(node.name);
+    _writeMarker(MarkerTag.ExtensionDeclaration_compilationUnitMember);
     _storeCompilationUnitMember(node);
+    _writeMarker(MarkerTag.ExtensionDeclaration_end);
     _writeUInt30(resolutionIndex);
 
     _classMemberIndexItems.clear();
@@ -539,10 +640,15 @@
       _resolutionSink.writeByte(MethodInvocationRewriteTag.extensionOverride);
     }
 
+    _writeMarker(MarkerTag.ExtensionOverride_extensionName);
     _writeNode(node.extensionName);
+    _writeMarker(MarkerTag.ExtensionOverride_typeArguments);
     _writeOptionalNode(node.typeArguments);
+    _writeMarker(MarkerTag.ExtensionOverride_argumentList);
     _writeNode(node.argumentList);
+    _writeMarker(MarkerTag.ExtensionOverride_extendedType);
     _resolutionSink.writeType(node.extendedType);
+    _writeMarker(MarkerTag.ExtensionOverride_end);
     // TODO(scheglov) typeArgumentTypes?
   }
 
@@ -571,16 +677,18 @@
 
     var resolutionIndex = _getNextResolutionIndex();
 
-    _isConstField = node.fields.isConst;
-    _isFinalField = node.fields.isFinal;
+    _shouldStoreVariableInitializers = node.fields.isConst ||
+        _hasConstConstructor && node.fields.isFinal && !node.isStatic;
     try {
+      _writeMarker(MarkerTag.FieldDeclaration_fields);
       _writeNode(node.fields);
     } finally {
-      _isConstField = false;
-      _isFinalField = false;
+      _shouldStoreVariableInitializers = false;
     }
 
+    _writeMarker(MarkerTag.FieldDeclaration_classMember);
     _storeClassMember(node);
+    _writeMarker(MarkerTag.FieldDeclaration_end);
 
     _writeUInt30(resolutionIndex);
   }
@@ -590,14 +698,19 @@
     _writeByte(Tag.FieldFormalParameter);
 
     _pushScopeTypeParameters(node.typeParameters);
+    _writeMarker(MarkerTag.FieldFormalParameter_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.FieldFormalParameter_type);
     _writeOptionalNode(node.type);
+    _writeMarker(MarkerTag.FieldFormalParameter_parameters);
     _writeOptionalNode(node.parameters);
+    _writeMarker(MarkerTag.FieldFormalParameter_normalFormalParameter);
     _storeNormalFormalParameter(
       node,
       node.keyword,
       hasQuestion: node.question != null,
     );
+    _writeMarker(MarkerTag.FieldFormalParameter_end);
 
     if (_shouldWriteResolution) {
       _resolutionSink.localElements.popScope();
@@ -607,15 +720,21 @@
   @override
   void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
     _writeByte(Tag.ForEachPartsWithDeclaration);
+    _writeMarker(MarkerTag.ForEachPartsWithDeclaration_loopVariable);
     _writeNode(node.loopVariable);
+    _writeMarker(MarkerTag.ForEachPartsWithDeclaration_forEachParts);
     _storeForEachParts(node);
+    _writeMarker(MarkerTag.ForEachPartsWithDeclaration_end);
   }
 
   @override
   void visitForElement(ForElement node) {
     _writeByte(Tag.ForElement);
+    _writeMarker(MarkerTag.ForElement_body);
     _writeNode(node.body);
+    _writeMarker(MarkerTag.ForElement_forMixin);
     _storeForMixin(node as ForElementImpl);
+    _writeMarker(MarkerTag.ForElement_end);
   }
 
   @override
@@ -630,14 +749,29 @@
       ),
     );
 
+    _writeMarker(MarkerTag.FormalParameterList_parameters);
     _writeNodeList(node.parameters);
+    _writeMarker(MarkerTag.FormalParameterList_end);
   }
 
   @override
   void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
     _writeByte(Tag.ForPartsWithDeclarations);
+    _writeMarker(MarkerTag.ForPartsWithDeclarations_variables);
     _writeNode(node.variables);
+    _writeMarker(MarkerTag.ForPartsWithDeclarations_forParts);
     _storeForParts(node);
+    _writeMarker(MarkerTag.ForPartsWithDeclarations_end);
+  }
+
+  @override
+  void visitForPartsWithExpression(ForPartsWithExpression node) {
+    _writeByte(Tag.ForPartsWithExpression);
+    _writeMarker(MarkerTag.ForPartsWithExpression_initialization);
+    _writeOptionalNode(node.initialization);
+    _writeMarker(MarkerTag.ForPartsWithExpression_forParts);
+    _storeForParts(node);
+    _writeMarker(MarkerTag.ForPartsWithExpression_end);
   }
 
   @override
@@ -675,15 +809,21 @@
 
     _pushScopeTypeParameters(node.functionExpression.typeParameters);
 
+    _writeMarker(MarkerTag.FunctionDeclaration_functionExpression);
     _writeNode(node.functionExpression);
+    _writeMarker(MarkerTag.FunctionDeclaration_returnType);
     _writeOptionalNode(node.returnType);
+    _writeMarker(MarkerTag.FunctionDeclaration_namedCompilationUnitMember);
     _storeNamedCompilationUnitMember(node);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.FunctionDeclaration_returnTypeType);
       _writeActualReturnType(node.declaredElement.returnType);
       _resolutionSink.localElements.popScope();
     }
 
+    _writeMarker(MarkerTag.FunctionDeclaration_end);
+
     _writeUInt30(resolutionIndex);
   }
 
@@ -699,8 +839,11 @@
       ),
     );
 
+    _writeMarker(MarkerTag.FunctionExpression_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.FunctionExpression_parameters);
     _writeOptionalNode(node.parameters);
+    _writeMarker(MarkerTag.FunctionExpression_end);
   }
 
   @override
@@ -712,8 +855,11 @@
           .writeByte(MethodInvocationRewriteTag.functionExpressionInvocation);
     }
 
+    _writeMarker(MarkerTag.FunctionExpressionInvocation_function);
     _writeNode(node.function);
+    _writeMarker(MarkerTag.FunctionExpressionInvocation_invocationExpression);
     _storeInvocationExpression(node);
+    _writeMarker(MarkerTag.FunctionExpressionInvocation_end);
   }
 
   @override
@@ -737,22 +883,30 @@
 
     _pushScopeTypeParameters(node.typeParameters);
 
+    _writeMarker(MarkerTag.FunctionTypeAlias_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.FunctionTypeAlias_returnType);
     _writeOptionalNode(node.returnType);
+    _writeMarker(MarkerTag.FunctionTypeAlias_parameters);
     _writeNode(node.parameters);
 
+    _writeMarker(MarkerTag.FunctionTypeAlias_typeAlias);
     _storeTypeAlias(node);
 
     if (_shouldWriteResolution) {
       var element = node.declaredElement as FunctionTypeAliasElementImpl;
+      _writeMarker(MarkerTag.FunctionTypeAlias_returnTypeType);
       _writeActualReturnType(element.function.returnType);
       // TODO(scheglov) pack into one byte
+      _writeMarker(MarkerTag.FunctionTypeAlias_flags);
       _resolutionSink.writeByte(element.isSimplyBounded ? 1 : 0);
       _resolutionSink.writeByte(element.hasSelfReference ? 1 : 0);
 
       _resolutionSink.localElements.popScope();
     }
 
+    _writeMarker(MarkerTag.FunctionTypeAlias_end);
+
     _writeUInt30(resolutionIndex);
   }
 
@@ -761,10 +915,15 @@
     _writeByte(Tag.FunctionTypedFormalParameter);
 
     _pushScopeTypeParameters(node.typeParameters);
+    _writeMarker(MarkerTag.FunctionTypedFormalParameter_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.FunctionTypedFormalParameter_returnType);
     _writeOptionalNode(node.returnType);
+    _writeMarker(MarkerTag.FunctionTypedFormalParameter_parameters);
     _writeNode(node.parameters);
+    _writeMarker(MarkerTag.FunctionTypedFormalParameter_normalFormalParameter);
     _storeNormalFormalParameter(node, null);
+    _writeMarker(MarkerTag.FunctionTypedFormalParameter_end);
 
     if (_shouldWriteResolution) {
       _resolutionSink.localElements.popScope();
@@ -783,14 +942,20 @@
 
     _pushScopeTypeParameters(node.typeParameters);
 
+    _writeMarker(MarkerTag.GenericFunctionType_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.GenericFunctionType_returnType);
     _writeOptionalNode(node.returnType);
+    _writeMarker(MarkerTag.GenericFunctionType_parameters);
     _writeNode(node.parameters);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.GenericFunctionType_type);
       _resolutionSink.writeType(node.type);
       _resolutionSink.localElements.popScope();
     }
+
+    _writeMarker(MarkerTag.GenericFunctionType_end);
   }
 
   @override
@@ -813,18 +978,24 @@
 
     _pushScopeTypeParameters(node.typeParameters);
 
+    _writeMarker(MarkerTag.GenericTypeAlias_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.GenericTypeAlias_type);
     _writeOptionalNode(node.type);
+    _writeMarker(MarkerTag.GenericTypeAlias_typeAlias);
     _storeTypeAlias(node);
 
     if (_shouldWriteResolution) {
       var element = node.declaredElement as TypeAliasElementImpl;
       // TODO(scheglov) pack into one byte
+      _writeMarker(MarkerTag.GenericTypeAlias_flags);
       _resolutionSink.writeByte(element.isSimplyBounded ? 1 : 0);
       _resolutionSink.writeByte(element.hasSelfReference ? 1 : 0);
       _resolutionSink.localElements.popScope();
     }
 
+    _writeMarker(MarkerTag.GenericTypeAlias_end);
+
     _writeUInt30(resolutionIndex);
   }
 
@@ -838,15 +1009,21 @@
   @override
   void visitIfElement(IfElement node) {
     _writeByte(Tag.IfElement);
+    _writeMarker(MarkerTag.IfElement_condition);
     _writeNode(node.condition);
+    _writeMarker(MarkerTag.IfElement_thenElement);
     _writeNode(node.thenElement);
+    _writeMarker(MarkerTag.IfElement_elseElement);
     _writeOptionalNode(node.elseElement);
+    _writeMarker(MarkerTag.IfElement_end);
   }
 
   @override
   void visitImplementsClause(ImplementsClause node) {
     _writeByte(Tag.ImplementsClause);
+    _writeMarker(MarkerTag.ImplementsClause_interfaces);
     _writeNodeList(node.interfaces);
+    _writeMarker(MarkerTag.ImplementsClause_end);
   }
 
   @override
@@ -868,13 +1045,17 @@
       _writeInformativeUint30(prefix.offset);
     }
 
+    _writeMarker(MarkerTag.ImportDirective_namespaceDirective);
     _storeNamespaceDirective(node);
     _writeUInt30(resolutionIndex);
 
     if (_shouldWriteResolution) {
       var element = node.element as ImportElementImpl;
+      _writeMarker(MarkerTag.ImportDirective_importedLibrary);
       _resolutionSink.writeElement(element.importedLibrary);
     }
+
+    _writeMarker(MarkerTag.ImportDirective_end);
   }
 
   @override
@@ -886,12 +1067,17 @@
         hasQuestion: node.question != null,
       ),
     );
+    _writeMarker(MarkerTag.IndexExpression_target);
     _writeOptionalNode(node.target);
+    _writeMarker(MarkerTag.IndexExpression_index);
     _writeNode(node.index);
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.IndexExpression_staticElement);
       _resolutionSink.writeElement(node.staticElement);
     }
+    _writeMarker(MarkerTag.IndexExpression_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.IndexExpression_end);
   }
 
   @override
@@ -917,9 +1103,13 @@
       ),
     );
 
+    _writeMarker(MarkerTag.InstanceCreationExpression_constructorName);
     _writeNode(node.constructorName);
+    _writeMarker(MarkerTag.InstanceCreationExpression_argumentList);
     _writeNode(node.argumentList);
+    _writeMarker(MarkerTag.InstanceCreationExpression_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.InstanceCreationExpression_end);
   }
 
   @override
@@ -951,10 +1141,8 @@
       }
     }
 
-    if (_shouldWriteResolution) {
-      // TODO(scheglov) Dont write type, AKA separate true `int` and `double`?
-      _resolutionSink.writeType(node.staticType);
-    }
+    // TODO(scheglov) Dont write type, AKA separate true `int` and `double`?
+    _storeExpression(node);
   }
 
   @override
@@ -983,9 +1171,13 @@
         hasNot: node.notOperator != null,
       ),
     );
+    _writeMarker(MarkerTag.IsExpression_expression);
     _writeNode(node.expression);
+    _writeMarker(MarkerTag.IsExpression_type);
     _writeNode(node.type);
+    _writeMarker(MarkerTag.IsExpression_expression2);
     _storeExpression(node);
+    _writeMarker(MarkerTag.IsExpression_end);
   }
 
   @override
@@ -1012,16 +1204,22 @@
       ),
     );
 
+    _writeMarker(MarkerTag.ListLiteral_typeArguments);
     _writeOptionalNode(node.typeArguments);
+    _writeMarker(MarkerTag.ListLiteral_elements);
     _writeNodeList(node.elements);
 
+    _writeMarker(MarkerTag.ListLiteral_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.ListLiteral_end);
   }
 
   @override
   void visitMapLiteralEntry(MapLiteralEntry node) {
     _writeByte(Tag.MapLiteralEntry);
+    _writeMarker(MarkerTag.MapLiteralEntry_key);
     _writeNode(node.key);
+    _writeMarker(MarkerTag.MapLiteralEntry_value);
     _writeNode(node.value);
   }
 
@@ -1066,26 +1264,35 @@
     _pushScopeTypeParameters(node.typeParameters);
 
     _writeDeclarationName(node.name);
+    _writeMarker(MarkerTag.MethodDeclaration_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.MethodDeclaration_returnType);
     _writeOptionalNode(node.returnType);
+    _writeMarker(MarkerTag.MethodDeclaration_parameters);
     _writeOptionalNode(node.parameters);
 
+    _writeMarker(MarkerTag.MethodDeclaration_classMember);
     _storeClassMember(node);
 
     _writeUInt30(resolutionIndex);
 
     if (_shouldWriteResolution) {
       var element = node.declaredElement as ExecutableElementImpl;
+      _writeMarker(MarkerTag.MethodDeclaration_returnTypeType);
       _writeActualReturnType(element.returnType);
+      _writeMarker(MarkerTag.MethodDeclaration_inferenceError);
       _writeTopLevelInferenceError(element);
       // TODO(scheglov) move this flag into ClassElementImpl?
       if (element is MethodElementImpl) {
+        _writeMarker(MarkerTag.MethodDeclaration_flags);
         _resolutionSink.writeByte(
           element.isOperatorEqualWithParameterTypeFromObject ? 1 : 0,
         );
       }
       _resolutionSink.localElements.popScope();
     }
+
+    _writeMarker(MarkerTag.MethodDeclaration_end);
   }
 
   @override
@@ -1102,9 +1309,13 @@
         hasPeriod2: node.operator?.type == TokenType.PERIOD_PERIOD,
       ),
     );
+    _writeMarker(MarkerTag.MethodInvocation_target);
     _writeOptionalNode(node.target);
+    _writeMarker(MarkerTag.MethodInvocation_methodName);
     _writeNode(node.methodName);
+    _writeMarker(MarkerTag.MethodInvocation_invocationExpression);
     _storeInvocationExpression(node);
+    _writeMarker(MarkerTag.MethodInvocation_end);
   }
 
   @override
@@ -1126,10 +1337,15 @@
 
     _pushScopeTypeParameters(node.typeParameters);
 
+    _writeMarker(MarkerTag.MixinDeclaration_typeParameters);
     _writeOptionalNode(node.typeParameters);
+    _writeMarker(MarkerTag.MixinDeclaration_onClause);
     _writeOptionalNode(node.onClause);
+    _writeMarker(MarkerTag.MixinDeclaration_implementsClause);
     _writeOptionalNode(node.implementsClause);
+    _writeMarker(MarkerTag.MixinDeclaration_namedCompilationUnitMember);
     _storeNamedCompilationUnitMember(node);
+    _writeMarker(MarkerTag.MixinDeclaration_end);
     _writeUInt30(resolutionIndex);
 
     _classMemberIndexItems.clear();
@@ -1162,13 +1378,17 @@
     _writeStringReference(nameNode.name);
     _writeInformativeUint30(nameNode.offset);
 
+    _writeMarker(MarkerTag.NamedExpression_expression);
     _writeNode(node.expression);
+    _writeMarker(MarkerTag.NamedExpression_end);
   }
 
   @override
   void visitNativeClause(NativeClause node) {
     _writeByte(Tag.NativeClause);
+    _writeMarker(MarkerTag.NativeClause_name);
     _writeNode(node.name);
+    _writeMarker(MarkerTag.NativeClause_end);
   }
 
   @override
@@ -1179,14 +1399,19 @@
   @override
   void visitOnClause(OnClause node) {
     _writeByte(Tag.OnClause);
+    _writeMarker(MarkerTag.OnClause_superclassConstraints);
     _writeNodeList(node.superclassConstraints);
+    _writeMarker(MarkerTag.OnClause_end);
   }
 
   @override
   void visitParenthesizedExpression(ParenthesizedExpression node) {
     _writeByte(Tag.ParenthesizedExpression);
+    _writeMarker(MarkerTag.ParenthesizedExpression_expression);
     _writeNode(node.expression);
+    _writeMarker(MarkerTag.ParenthesizedExpression_expression2);
     _storeExpression(node);
+    _writeMarker(MarkerTag.ParenthesizedExpression_end);
   }
 
   @override
@@ -1198,15 +1423,20 @@
   @override
   void visitPartOfDirective(PartOfDirective node) {
     _writeByte(Tag.PartOfDirective);
+    _writeMarker(MarkerTag.PartOfDirective_libraryName);
     _writeOptionalNode(node.libraryName);
+    _writeMarker(MarkerTag.PartOfDirective_uri);
     _writeOptionalNode(node.uri);
+    _writeMarker(MarkerTag.PartOfDirective_directive);
     _storeDirective(node);
+    _writeMarker(MarkerTag.PartOfDirective_end);
   }
 
   @override
   void visitPostfixExpression(PostfixExpression node) {
     _writeByte(Tag.PostfixExpression);
 
+    _writeMarker(MarkerTag.PostfixExpression_operand);
     _writeNode(node.operand);
 
     var operatorToken = node.operator.type;
@@ -1214,27 +1444,36 @@
     _writeByte(binaryToken.index);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.PostfixExpression_staticElement);
       _resolutionSink.writeElement(node.staticElement);
       if (operatorToken.isIncrementOperator) {
+        _writeMarker(MarkerTag.PostfixExpression_readElement);
         _resolutionSink.writeElement(node.readElement);
+        _writeMarker(MarkerTag.PostfixExpression_readType);
         _resolutionSink.writeType(node.readType);
+        _writeMarker(MarkerTag.PostfixExpression_writeElement);
         _resolutionSink.writeElement(node.writeElement);
+        _writeMarker(MarkerTag.PostfixExpression_writeType);
         _resolutionSink.writeType(node.writeType);
       }
     }
+    _writeMarker(MarkerTag.PostfixExpression_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.PostfixExpression_end);
   }
 
   @override
   void visitPrefixedIdentifier(PrefixedIdentifier node) {
     _writeByte(Tag.PrefixedIdentifier);
+    _writeMarker(MarkerTag.PrefixedIdentifier_prefix);
     _writeNode(node.prefix);
+    _writeMarker(MarkerTag.PrefixedIdentifier_identifier);
     _writeNode(node.identifier);
 
-    if (_shouldWriteResolution) {
-      // TODO(scheglov) In actual prefixed identifier, the type of the identifier.
-      _resolutionSink.writeType(node.staticType);
-    }
+    // TODO(scheglov) In actual prefixed identifier, the type of the identifier.
+    _writeMarker(MarkerTag.PrefixedIdentifier_expression);
+    _storeExpression(node);
+    _writeMarker(MarkerTag.PrefixedIdentifier_end);
   }
 
   @override
@@ -1245,19 +1484,27 @@
     var binaryToken = TokensWriter.astToBinaryTokenType(operatorToken);
     _writeByte(binaryToken.index);
 
+    _writeMarker(MarkerTag.PrefixExpression_operand);
     _writeNode(node.operand);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.PrefixExpression_staticElement);
       _resolutionSink.writeElement(node.staticElement);
       if (operatorToken.isIncrementOperator) {
+        _writeMarker(MarkerTag.PrefixExpression_readElement);
         _resolutionSink.writeElement(node.readElement);
+        _writeMarker(MarkerTag.PrefixExpression_readType);
         _resolutionSink.writeType(node.readType);
+        _writeMarker(MarkerTag.PrefixExpression_writeElement);
         _resolutionSink.writeElement(node.writeElement);
+        _writeMarker(MarkerTag.PrefixExpression_writeType);
         _resolutionSink.writeType(node.writeType);
       }
     }
 
+    _writeMarker(MarkerTag.PrefixExpression_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.PrefixExpression_end);
   }
 
   @override
@@ -1269,10 +1516,14 @@
         hasPeriod2: node.operator?.type == TokenType.PERIOD_PERIOD,
       ),
     );
+    _writeMarker(MarkerTag.PropertyAccess_target);
     _writeOptionalNode(node.target);
+    _writeMarker(MarkerTag.PropertyAccess_propertyName);
     _writeNode(node.propertyName);
     // TODO(scheglov) Get from the property?
+    _writeMarker(MarkerTag.PropertyAccess_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.PropertyAccess_end);
   }
 
   @override
@@ -1286,12 +1537,15 @@
       ),
     );
 
+    _writeMarker(MarkerTag.RedirectingConstructorInvocation_constructorName);
     _writeOptionalNode(node.constructorName);
+    _writeMarker(MarkerTag.RedirectingConstructorInvocation_argumentList);
     _writeNode(node.argumentList);
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.RedirectingConstructorInvocation_staticElement);
       _resolutionSink.writeElement(node.staticElement);
     }
-    _storeConstructorInitializer(node);
+    _writeMarker(MarkerTag.RedirectingConstructorInvocation_end);
   }
 
   @override
@@ -1307,13 +1561,18 @@
     if (_shouldWriteResolution) {
       var isMapBit = node.isMap ? (1 << 0) : 0;
       var isSetBit = node.isSet ? (1 << 1) : 0;
+      _writeMarker(MarkerTag.SetOrMapLiteral_flags);
       _resolutionSink.writeByte(isMapBit | isSetBit);
     }
 
+    _writeMarker(MarkerTag.SetOrMapLiteral_typeArguments);
     _writeOptionalNode(node.typeArguments);
+    _writeMarker(MarkerTag.SetOrMapLiteral_elements);
     _writeNodeList(node.elements);
 
+    _writeMarker(MarkerTag.SetOrMapLiteral_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.SetOrMapLiteral_end);
   }
 
   @override
@@ -1327,13 +1586,17 @@
   void visitSimpleFormalParameter(SimpleFormalParameter node) {
     _writeByte(Tag.SimpleFormalParameter);
 
+    _writeMarker(MarkerTag.SimpleFormalParameter_type);
     _writeOptionalNode(node.type);
+    _writeMarker(MarkerTag.SimpleFormalParameter_normalFormalParameter);
     _storeNormalFormalParameter(node, node.keyword);
 
     if (_shouldWriteResolution) {
       var element = node.declaredElement as ParameterElementImpl;
+      _writeMarker(MarkerTag.SimpleFormalParameter_flags);
       _resolutionSink.writeByte(element.inheritsCovariant ? 1 : 0);
     }
+    _writeMarker(MarkerTag.SimpleFormalParameter_end);
   }
 
   @override
@@ -1342,10 +1605,13 @@
     _writeStringReference(node.name);
     _writeInformativeUint30(node.offset);
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.SimpleIdentifier_staticElement);
       _resolutionSink.writeElement(node.staticElement);
       // TODO(scheglov) It is inefficient to write many null types.
-      _resolutionSink.writeType(node.staticType);
     }
+    _writeMarker(MarkerTag.SimpleIdentifier_expression);
+    _storeExpression(node);
+    _writeMarker(MarkerTag.SimpleIdentifier_end);
   }
 
   @override
@@ -1364,31 +1630,40 @@
             node.spreadOperator.type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION,
       ),
     );
+    _writeMarker(MarkerTag.SpreadElement_expression);
     _writeNode(node.expression);
+    _writeMarker(MarkerTag.SpreadElement_end);
   }
 
   @override
   void visitStringInterpolation(StringInterpolation node) {
     _writeByte(Tag.StringInterpolation);
+    _writeMarker(MarkerTag.StringInterpolation_elements);
     _writeNodeList(node.elements);
+    _writeMarker(MarkerTag.StringInterpolation_end);
   }
 
   @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
     _writeByte(Tag.SuperConstructorInvocation);
 
+    _writeMarker(MarkerTag.SuperConstructorInvocation_constructorName);
     _writeOptionalNode(node.constructorName);
+    _writeMarker(MarkerTag.SuperConstructorInvocation_argumentList);
     _writeNode(node.argumentList);
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.SuperConstructorInvocation_staticElement);
       _resolutionSink.writeElement(node.staticElement);
     }
-    _storeConstructorInitializer(node);
+    _writeMarker(MarkerTag.SuperConstructorInvocation_end);
   }
 
   @override
   void visitSuperExpression(SuperExpression node) {
     _writeByte(Tag.SuperExpression);
+    _writeMarker(MarkerTag.SuperExpression_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.SuperExpression_end);
   }
 
   @override
@@ -1406,14 +1681,19 @@
   @override
   void visitThisExpression(ThisExpression node) {
     _writeByte(Tag.ThisExpression);
+    _writeMarker(MarkerTag.ThisExpression_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.ThisExpression_end);
   }
 
   @override
   void visitThrowExpression(ThrowExpression node) {
     _writeByte(Tag.ThrowExpression);
+    _writeMarker(MarkerTag.ThrowExpression_expression);
     _writeNode(node.expression);
+    _writeMarker(MarkerTag.ThrowExpression_expression2);
     _storeExpression(node);
+    _writeMarker(MarkerTag.ThrowExpression_end);
   }
 
   @override
@@ -1440,14 +1720,17 @@
 
     var resolutionIndex = _getNextResolutionIndex();
 
-    _isConstTopLevelVariable = node.variables.isConst;
+    _shouldStoreVariableInitializers = node.variables.isConst;
     try {
+      _writeMarker(MarkerTag.TopLevelVariableDeclaration_variables);
       _writeNode(node.variables);
     } finally {
-      _isConstTopLevelVariable = false;
+      _shouldStoreVariableInitializers = false;
     }
 
+    _writeMarker(MarkerTag.TopLevelVariableDeclaration_compilationUnitMember);
     _storeCompilationUnitMember(node);
+    _writeMarker(MarkerTag.TopLevelVariableDeclaration_end);
 
     _writeUInt30(resolutionIndex);
   }
@@ -1455,7 +1738,9 @@
   @override
   void visitTypeArgumentList(TypeArgumentList node) {
     _writeByte(Tag.TypeArgumentList);
+    _writeMarker(MarkerTag.TypeArgumentList_arguments);
     _writeNodeList(node.arguments);
+    _writeMarker(MarkerTag.TypeArgumentList_end);
   }
 
   @override
@@ -1469,12 +1754,16 @@
       ),
     );
 
+    _writeMarker(MarkerTag.TypeName_name);
     _writeNode(node.name);
+    _writeMarker(MarkerTag.TypeName_typeArguments);
     _writeOptionalNode(node.typeArguments);
 
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.TypeName_type);
       _resolutionSink.writeType(node.type);
     }
+    _writeMarker(MarkerTag.TypeName_end);
   }
 
   @override
@@ -1483,22 +1772,29 @@
     _writeInformativeUint30(node.offset);
     _writeInformativeUint30(node.length);
     _writeDeclarationName(node.name);
+    _writeMarker(MarkerTag.TypeParameter_bound);
     _writeOptionalNode(node.bound);
+    _writeMarker(MarkerTag.TypeParameter_declaration);
     _storeDeclaration(node);
 
     if (_shouldWriteResolution) {
       var element = node.declaredElement as TypeParameterElementImpl;
+      _writeMarker(MarkerTag.TypeParameter_variance);
       _resolutionSink.writeByte(
         _encodeVariance(element),
       );
+      _writeMarker(MarkerTag.TypeParameter_defaultType);
       _resolutionSink.writeType(element.defaultType);
     }
+    _writeMarker(MarkerTag.TypeParameter_end);
   }
 
   @override
   void visitTypeParameterList(TypeParameterList node) {
     _writeByte(Tag.TypeParameterList);
+    _writeMarker(MarkerTag.TypeParameterList_typeParameters);
     _writeNodeList(node.typeParameters);
+    _writeMarker(MarkerTag.TypeParameterList_end);
   }
 
   @override
@@ -1514,23 +1810,26 @@
     if (_shouldWriteResolution) {
       // TODO(scheglov) Enforce not null, remove `?` in `?.type` below.
       var element = node.declaredElement as VariableElementImpl;
+      _writeMarker(MarkerTag.VariableDeclaration_type);
       _writeActualType(element?.type);
+      _writeMarker(MarkerTag.VariableDeclaration_inferenceError);
       _writeTopLevelInferenceError(element);
       if (element is FieldElementImpl) {
+        _writeMarker(MarkerTag.VariableDeclaration_inheritsCovariant);
         _resolutionSink.writeByte(element.inheritsCovariant ? 1 : 0);
       }
     }
 
     Expression initializerToWrite;
-    if (_isConstField ||
-        _hasConstConstructor && _isFinalField ||
-        _isConstTopLevelVariable) {
+    if (_shouldStoreVariableInitializers) {
       var initializer = node.initializer;
       if (_isSerializableExpression(initializer)) {
         initializerToWrite = initializer;
       }
     }
+    _writeMarker(MarkerTag.VariableDeclaration_initializer);
     _writeOptionalNode(initializerToWrite);
+    _writeMarker(MarkerTag.VariableDeclaration_end);
   }
 
   @override
@@ -1544,15 +1843,21 @@
         isVar: node.keyword?.keyword == Keyword.VAR,
       ),
     );
+    _writeMarker(MarkerTag.VariableDeclarationList_type);
     _writeOptionalNode(node.type);
+    _writeMarker(MarkerTag.VariableDeclarationList_variables);
     _writeNodeList(node.variables);
+    _writeMarker(MarkerTag.VariableDeclarationList_annotatedNode);
     _storeAnnotatedNode(node);
+    _writeMarker(MarkerTag.VariableDeclarationList_end);
   }
 
   @override
   void visitWithClause(WithClause node) {
     _writeByte(Tag.WithClause);
+    _writeMarker(MarkerTag.WithClause_mixinTypes);
     _writeNodeList(node.mixinTypes);
+    _writeMarker(MarkerTag.WithClause_end);
   }
 
   void _pushScopeTypeParameters(TypeParameterList node) {
@@ -1572,10 +1877,13 @@
   }
 
   void _storeAnnotatedNode(AnnotatedNode node) {
+    _writeMarker(MarkerTag.AnnotatedNode_metadata);
     _writeNodeList(node.metadata);
+    _writeMarker(MarkerTag.AnnotatedNode_end);
   }
 
   void _storeClassMember(ClassMember node) {
+    _writeMarker(MarkerTag.ClassMember_declaration);
     _storeDeclaration(node);
   }
 
@@ -1583,8 +1891,6 @@
     _storeDeclaration(node);
   }
 
-  void _storeConstructorInitializer(ConstructorInitializer node) {}
-
   void _storeDeclaration(Declaration node) {
     _storeAnnotatedNode(node);
   }
@@ -1596,19 +1902,24 @@
 
   void _storeExpression(Expression node) {
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.Expression_staticType);
       _resolutionSink.writeType(node.staticType);
     }
   }
 
   void _storeForEachParts(ForEachParts node) {
+    _writeMarker(MarkerTag.ForEachParts_iterable);
     _writeNode(node.iterable);
+    _writeMarker(MarkerTag.ForEachParts_forLoopParts);
     _storeForLoopParts(node);
+    _writeMarker(MarkerTag.ForEachParts_end);
   }
 
   void _storeForLoopParts(ForLoopParts node) {}
 
   void _storeFormalParameter(FormalParameter node) {
     if (_shouldWriteResolution) {
+      _writeMarker(MarkerTag.FormalParameter_type);
       _writeActualType(node.declaredElement.type);
     }
   }
@@ -1619,19 +1930,28 @@
         hasAwait: node.awaitKeyword != null,
       ),
     );
+    _writeMarker(MarkerTag.ForMixin_forLoopParts);
     _writeNode(node.forLoopParts);
   }
 
   void _storeForParts(ForParts node) {
+    _writeMarker(MarkerTag.ForParts_condition);
     _writeOptionalNode(node.condition);
+    _writeMarker(MarkerTag.ForParts_updaters);
     _writeNodeList(node.updaters);
+    _writeMarker(MarkerTag.ForParts_forLoopParts);
     _storeForLoopParts(node);
+    _writeMarker(MarkerTag.ForParts_end);
   }
 
   void _storeInvocationExpression(InvocationExpression node) {
+    _writeMarker(MarkerTag.InvocationExpression_typeArguments);
     _writeOptionalNode(node.typeArguments);
+    _writeMarker(MarkerTag.InvocationExpression_argumentList);
     _writeNode(node.argumentList);
+    _writeMarker(MarkerTag.InvocationExpression_expression);
     _storeExpression(node);
+    _writeMarker(MarkerTag.InvocationExpression_end);
     // TODO(scheglov) typeArgumentTypes and staticInvokeType?
   }
 
@@ -1641,9 +1961,13 @@
   }
 
   void _storeNamespaceDirective(NamespaceDirective node) {
+    _writeMarker(MarkerTag.NamespaceDirective_combinators);
     _writeNodeList(node.combinators);
+    _writeMarker(MarkerTag.NamespaceDirective_configurations);
     _writeNodeList(node.configurations);
+    _writeMarker(MarkerTag.NamespaceDirective_uriBasedDirective);
     _storeUriBasedDirective(node);
+    _writeMarker(MarkerTag.NamespaceDirective_end);
   }
 
   void _storeNormalFormalParameter(
@@ -1667,11 +1991,14 @@
     _writeInformativeUint30(node.offset);
     _writeInformativeUint30(node.length);
 
+    _writeMarker(MarkerTag.NormalFormalParameter_metadata);
     _writeNodeList(node.metadata);
     if (node.identifier != null) {
       _writeDeclarationName(node.identifier);
     }
+    _writeMarker(MarkerTag.NormalFormalParameter_formalParameter);
     _storeFormalParameter(node);
+    _writeMarker(MarkerTag.NormalFormalParameter_end);
   }
 
   void _storeTypeAlias(TypeAlias node) {
@@ -1679,8 +2006,11 @@
   }
 
   void _storeUriBasedDirective(UriBasedDirective node) {
+    _writeMarker(MarkerTag.UriBasedDirective_uri);
     _writeNode(node.uri);
+    _writeMarker(MarkerTag.UriBasedDirective_directive);
     _storeDirective(node);
+    _writeMarker(MarkerTag.UriBasedDirective_end);
   }
 
   void _writeActualReturnType(DartType type) {
@@ -1789,6 +2119,14 @@
     }
   }
 
+  void _writeMarker(MarkerTag tag) {
+    if (enableDebugResolutionMarkers) {
+      if (_shouldWriteResolution) {
+        _resolutionSink.writeUInt30(tag.index);
+      }
+    }
+  }
+
   void _writeNode(AstNode node) {
     node.accept(this);
   }
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 1b6e4b4..ea791b0 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -585,6 +585,12 @@
     this._byteOffset,
   );
 
+  /// TODO(scheglov) Remove after fixing http://dartbug.com/44449
+  int get byteOffset => _byteOffset;
+
+  /// TODO(scheglov) Remove after fixing http://dartbug.com/44449
+  Uint8List get bytes => _unitReader._resolutionReader.bytes;
+
   Element nextElement() {
     var memberFlags = readByte();
     var element = _readRawElement();
@@ -728,8 +734,8 @@
       element.bound = bound;
     }
 
-    var typedefElement = nextElement();
-    var typeArguments = _readTypeList();
+    var aliasElement = nextElement();
+    var aliasArguments = aliasElement != null ? _readTypeList() : null;
 
     var returnType = nextType();
 
@@ -757,8 +763,8 @@
       parameters: formalParameters,
       returnType: returnType,
       nullabilitySuffix: nullability,
-      element: typedefElement,
-      typeArguments: typeArguments,
+      aliasElement: aliasElement,
+      aliasArguments: aliasArguments,
     );
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index a21430d..1aa10ca 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -466,6 +466,10 @@
     }
   }
 
+  void writeUInt30(int value) {
+    _sink.writeUInt30(value);
+  }
+
   int _indexOfElement(Element element) {
     if (element == null) return 0;
     if (element is MultiplyDefinedElement) return 0;
@@ -525,21 +529,11 @@
       writeType(typeParameter.bound);
     }
 
-    Element typedefElement;
-    List<DartType> typedefTypeArguments = const <DartType>[];
-    if (type.element is FunctionTypeAliasElement) {
-      typedefElement = type.element;
-      typedefTypeArguments = type.typeArguments;
+    var aliasElement = type.aliasElement;
+    writeElement(aliasElement);
+    if (aliasElement != null) {
+      _writeTypeList(type.aliasArguments);
     }
-    // TODO(scheglov) Cleanup to always use FunctionTypeAliasElement.
-    if (type.element is GenericFunctionTypeElement &&
-        type.element.enclosingElement is FunctionTypeAliasElement) {
-      typedefElement = type.element.enclosingElement;
-      typedefTypeArguments = type.typeArguments;
-    }
-
-    writeElement(typedefElement);
-    _writeTypeList(typedefTypeArguments);
 
     writeType(type.returnType);
 
diff --git a/pkg/analyzer/lib/src/summary2/default_types_builder.dart b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
index 68cc053..2dcb918 100644
--- a/pkg/analyzer/lib/src/summary2/default_types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
@@ -257,7 +257,7 @@
 
           if (declaration is ClassElement) {
             recurseParameters(declaration.typeParameters);
-          } else if (declaration is FunctionTypeAliasElement) {
+          } else if (declaration is TypeAliasElement) {
             recurseParameters(declaration.typeParameters);
           }
           visited.remove(startType.element);
diff --git a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
index a8398e4..1e49400 100644
--- a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
@@ -98,6 +98,11 @@
   }
 
   void _parameter(ParameterElementImpl parameter) {
+    // If a function typed parameter, process nested parameters.
+    for (var localParameter in parameter.parameters) {
+      _parameter(localParameter);
+    }
+
     var node = _defaultParameter(parameter);
     if (node == null) return;
 
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 0e9ad99..b92ebe9 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -210,8 +210,8 @@
   }
 
   void createTypeProviders(
-    LibraryElementImpl dartCore,
-    LibraryElementImpl dartAsync,
+    LibraryElementImpl /*!*/ dartCore,
+    LibraryElementImpl /*!*/ dartAsync,
   ) {
     if (analysisContext.typeProviderNonNullableByDefault != null) {
       return;
@@ -381,6 +381,10 @@
     return library.exports;
   }
 
+  bool hasLibrary(String uriStr) {
+    return libraryReaders[uriStr] != null;
+  }
+
   bool isLibraryUri(String uriStr) {
     var libraryContext = libraryReaders[uriStr];
     return !libraryContext.hasPartOfDirective;
diff --git a/pkg/analyzer/lib/src/summary2/simply_bounded.dart b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
index 03be657..fb5d0ed 100644
--- a/pkg/analyzer/lib/src/summary2/simply_bounded.dart
+++ b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
@@ -19,7 +19,7 @@
   var nodes = <SimplyBoundedNode>[];
   for (var libraryBuilder in libraryBuilders) {
     for (var unit in libraryBuilder.element.units) {
-      for (var element in unit.functionTypeAliases) {
+      for (var element in unit.typeAliases) {
         var node = walker.getNode(element);
         nodes.add(node);
       }
diff --git a/pkg/analyzer/lib/src/summary2/type_alias.dart b/pkg/analyzer/lib/src/summary2/type_alias.dart
index f69f097..303646c 100644
--- a/pkg/analyzer/lib/src/summary2/type_alias.dart
+++ b/pkg/analyzer/lib/src/summary2/type_alias.dart
@@ -43,12 +43,8 @@
   }
 
   void genericTypeAlias(GenericTypeAlias node) {
-    var functionType = node.functionType;
-    if (functionType != null) {
-      _typeParameterList(functionType.typeParameters);
-      _formalParameterList(functionType.parameters);
-      _visit(functionType.returnType);
-    }
+    _typeParameterList(node.typeParameters);
+    _visit(node.type);
   }
 
   void _argumentList(TypeArgumentList node) {
diff --git a/pkg/analyzer/lib/src/summary2/variance_builder.dart b/pkg/analyzer/lib/src/summary2/variance_builder.dart
index 755f4c9..5eb87ce 100644
--- a/pkg/analyzer/lib/src/summary2/variance_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/variance_builder.dart
@@ -59,15 +59,16 @@
       }
     } else if (type is NamedTypeBuilder) {
       var element = type.element;
+      var arguments = type.arguments;
       if (element is ClassElement) {
         var result = Variance.unrelated;
-        if (type.arguments.isNotEmpty) {
+        if (arguments.isNotEmpty) {
           var parameters = element.typeParameters;
-          for (int i = 0; i < type.arguments.length; ++i) {
+          for (var i = 0; i < arguments.length && i < parameters.length; i++) {
             var parameter = parameters[i] as TypeParameterElementImpl;
             result = result.meet(
               parameter.variance.combine(
-                _compute(variable, type.arguments[i]),
+                _compute(variable, arguments[i]),
               ),
             );
           }
@@ -78,14 +79,14 @@
 
         var result = Variance.unrelated;
 
-        if (type.arguments.isNotEmpty) {
+        if (arguments.isNotEmpty) {
           var parameters = element.typeParameters;
-          for (var i = 0; i < type.arguments.length; ++i) {
+          for (var i = 0; i < arguments.length && i < parameters.length; i++) {
             var parameter = parameters[i] as TypeParameterElementImpl;
             var parameterVariance = parameter.variance;
             result = result.meet(
               parameterVariance.combine(
-                _compute(variable, type.arguments[i]),
+                _compute(variable, arguments[i]),
               ),
             );
           }
@@ -196,7 +197,7 @@
       return;
     }
 
-    var type = node.functionType?.type;
+    var type = node.type?.type;
 
     // Not a function type, recover.
     if (type == null) {
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index 6add61d..2e8694b 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -47,16 +47,17 @@
     throw StateError('Not found: $name');
   }
 
-  ImportElement import(String targetUri) {
+  ImportElement import(String targetUri, {bool mustBeUnique = true}) {
     ImportElement importElement;
 
     for (var import in unitElement.library.imports) {
       var importedUri = import.importedLibrary.source.uri.toString();
       if (importedUri == targetUri) {
-        if (importElement != null) {
+        if (importElement == null) {
+          importElement = import;
+        } else if (mustBeUnique) {
           throw StateError('Not unique: $targetUri');
         }
-        importElement = import;
       }
     }
 
@@ -66,11 +67,35 @@
     throw StateError('Not found: $targetUri');
   }
 
-  ImportFindElement importFind(String targetUri) {
-    var import = this.import(targetUri);
+  ImportFindElement importFind(String targetUri, {bool mustBeUnique = true}) {
+    var import = this.import(targetUri, mustBeUnique: mustBeUnique);
     return ImportFindElement(import);
   }
 
+  LabelElement label(String name) {
+    LabelElement result;
+
+    void updateResult(Element element) {
+      if (element is LabelElement && element.name == name) {
+        if (result != null) {
+          throw StateError('Not unique: $name');
+        }
+        result = element;
+      }
+    }
+
+    unit.accept(FunctionAstVisitor(
+      label: (node) {
+        updateResult(node.label.staticElement);
+      },
+    ));
+
+    if (result == null) {
+      throw StateError('Not found: $name');
+    }
+    return result;
+  }
+
   FunctionElement localFunction(String name) {
     FunctionElement result;
 
@@ -147,8 +172,11 @@
     findInExecutables(unitElement.accessors);
     findInExecutables(unitElement.functions);
 
-    for (var function in unitElement.functionTypeAliases) {
-      findIn(function.function.parameters);
+    for (var alias in unitElement.typeAliases) {
+      var aliasedElement = alias.aliasedElement;
+      if (aliasedElement is GenericFunctionTypeElement) {
+        findIn(aliasedElement.parameters);
+      }
     }
 
     for (var extension_ in unitElement.extensions) {
@@ -183,6 +211,29 @@
     throw StateError('Not found: $name');
   }
 
+  CompilationUnitElement part(String targetUri) {
+    CompilationUnitElement partElement;
+
+    for (var part in unitElement.library.parts) {
+      if (part.uri == targetUri) {
+        if (partElement != null) {
+          throw StateError('Not unique: $targetUri');
+        }
+        partElement = part;
+      }
+    }
+
+    if (partElement != null) {
+      return partElement;
+    }
+    throw StateError('Not found: $targetUri');
+  }
+
+  PartFindElement partFind(String targetUri) {
+    var part = this.part(targetUri);
+    return PartFindElement(part);
+  }
+
   PrefixElement prefix(String name) {
     for (var import_ in unitElement.library.imports) {
       var prefix = import_.prefix;
@@ -218,9 +269,13 @@
       findIn(type.typeParameters);
     }
 
-    for (var type in unitElement.functionTypeAliases) {
-      findIn(type.typeParameters);
-      findIn(type.function.typeParameters);
+    for (var alias in unitElement.typeAliases) {
+      findIn(alias.typeParameters);
+
+      var aliasedElement = alias.aliasedElement;
+      if (aliasedElement is GenericFunctionTypeElement) {
+        findIn(aliasedElement.typeParameters);
+      }
     }
 
     for (var class_ in unitElement.types) {
@@ -254,6 +309,13 @@
   }
 }
 
+class PartFindElement extends _FindElementBase {
+  @override
+  final CompilationUnitElement unitElement;
+
+  PartFindElement(this.unitElement);
+}
+
 abstract class _FindElementBase {
   CompilationUnitElement get unitElement;
 
@@ -367,15 +429,6 @@
     throw StateError('Not found: $name');
   }
 
-  FunctionTypeAliasElement functionTypeAlias(String name) {
-    for (var element in unitElement.functionTypeAliases) {
-      if (element.name == name) {
-        return element;
-      }
-    }
-    throw StateError('Not found: $name');
-  }
-
   PropertyAccessorElement getter(String name, {String of}) {
     PropertyAccessorElement result;
 
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 07b410e..91afc47 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -83,6 +83,10 @@
     return _node(search, (n) => n is ConstructorFieldInitializer);
   }
 
+  ConstructorName constructorName(String search) {
+    return _node(search, (n) => n is ConstructorName);
+  }
+
   ContinueStatement continueStatement(String search) {
     return _node(search, (n) => n is ContinueStatement);
   }
@@ -163,6 +167,10 @@
     return _node(search, (n) => n is IfElement);
   }
 
+  IfStatement ifStatement(String search) {
+    return _node(search, (n) => n is IfStatement);
+  }
+
   ImportDirective import(String search) {
     return _node(search, (n) => n is ImportDirective);
   }
@@ -211,6 +219,19 @@
     return _node(search, (n) => n is NullLiteral);
   }
 
+  /// Return the unique offset where the [search] string occurs in [content].
+  /// Throws if not found, or if not unique.
+  int offset(String search) {
+    var offset = content.indexOf(search);
+    if (content.contains(search, offset + 1)) {
+      throw StateError('The pattern |$search| is not unique in:\n$content');
+    }
+    if (offset < 0) {
+      throw StateError('The pattern |$search| is not found in:\n$content');
+    }
+    return offset;
+  }
+
   ParenthesizedExpression parenthesized(String search) {
     return _node(search, (n) => n is ParenthesizedExpression);
   }
@@ -337,15 +358,9 @@
   }
 
   AstNode _node(String search, bool Function(AstNode) predicate) {
-    var index = content.indexOf(search);
-    if (content.contains(search, index + 1)) {
-      throw StateError('The pattern |$search| is not unique in:\n$content');
-    }
-    if (index < 0) {
-      throw StateError('The pattern |$search| is not found in:\n$content');
-    }
+    int offset = this.offset(search);
 
-    var node = NodeLocator2(index).searchWithin(unit);
+    var node = NodeLocator2(offset).searchWithin(unit);
     if (node == null) {
       throw StateError(
           'The pattern |$search| had no corresponding node in:\n$content');
diff --git a/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart b/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
index 0c7d2ad..4fc84f6 100644
--- a/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
+++ b/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
@@ -11,6 +11,7 @@
   final void Function(FunctionDeclarationStatement)
       functionDeclarationStatement;
   final void Function(FunctionExpression, bool) functionExpression;
+  final void Function(Label) label;
   final void Function(SimpleIdentifier) simpleIdentifier;
   final void Function(VariableDeclaration) variableDeclaration;
 
@@ -18,6 +19,7 @@
     this.declaredIdentifier,
     this.functionDeclarationStatement,
     this.functionExpression,
+    this.label,
     this.simpleIdentifier,
     this.variableDeclaration,
   });
@@ -49,6 +51,14 @@
   }
 
   @override
+  void visitLabel(Label node) {
+    if (label != null) {
+      label(node);
+    }
+    super.visitLabel(node);
+  }
+
+  @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
     if (simpleIdentifier != null) {
       simpleIdentifier(node);
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 5007cde..36be56b 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -43,6 +43,8 @@
     throw 0;
   }
 
+  Future<T> catchError(Function onError, {bool test(Object error)});
+
   Future<R> then<R>(FutureOr<R> onValue(T value));
 
   Future<T> whenComplete(action());
@@ -224,6 +226,13 @@
 abstract class Encoding {}
 
 class JsonDecoder extends Converter<String, Object> {}
+
+const JsonCodec json = JsonCodec();
+
+class JsonCodec {
+  const JsonCodec();
+  String encode(Object? value, {Object? toEncodable(dynamic object)?}) => '';
+}
 ''',
     )
   ],
@@ -572,6 +581,10 @@
 
 class Type {}
 
+class UnsupportedError {
+  UnsupportedError(String message);
+}
+
 class Uri {
   static List<int> parseIPv6Address(String host, [int start = 0, int end]) {
     return null;
diff --git a/pkg/analyzer/lib/src/util/ast_data_extractor.dart b/pkg/analyzer/lib/src/util/ast_data_extractor.dart
index 2147db8..a95a277 100644
--- a/pkg/analyzer/lib/src/util/ast_data_extractor.dart
+++ b/pkg/analyzer/lib/src/util/ast_data_extractor.dart
@@ -26,13 +26,13 @@
   void computeForClass(Declaration node, Id id) {
     if (id == null) return;
     T value = computeNodeValue(id, node);
-    registerValue(uri, node.offset, id, value, node);
+    registerValue(uri, _nodeOffset(node), id, value, node);
   }
 
   void computeForCollectionElement(CollectionElement node, NodeId id) {
     if (id == null) return;
     T value = computeNodeValue(id, node);
-    registerValue(uri, node.offset, id, value, node);
+    registerValue(uri, _nodeOffset(node), id, value, node);
   }
 
   void computeForLibrary(LibraryElement library, Id id) {
@@ -44,13 +44,13 @@
   void computeForMember(Declaration node, Id id) {
     if (id == null) return;
     T value = computeNodeValue(id, node);
-    registerValue(uri, node.offset, id, value, node);
+    registerValue(uri, _nodeOffset(node), id, value, node);
   }
 
   void computeForStatement(Statement node, NodeId id) {
     if (id == null) return;
     T value = computeNodeValue(id, node);
-    registerValue(uri, node.offset, id, value, node);
+    registerValue(uri, _nodeOffset(node), id, value, node);
   }
 
   /// Implement this to compute the data corresponding to [node].
@@ -174,7 +174,14 @@
   }
 
   int _nodeOffset(AstNode node) {
-    var offset = node.offset;
+    int offset;
+    if (node is ConditionalExpression) {
+      offset = node.question.offset;
+    } else if (node is BinaryExpression) {
+      offset = node.operator.offset;
+    } else {
+      offset = node.offset;
+    }
     assert(offset != null && offset >= 0,
         "No fileOffset on $node (${node.runtimeType})");
     return offset;
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index da3cafa..db269c0 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.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:async';
 import 'dart:collection';
 import 'dart:core';
 
@@ -14,8 +15,43 @@
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/util/uri.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
+import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 import 'package:pub_semver/pub_semver.dart';
+import 'package:watcher/watcher.dart';
+
+/// Notification that we issue in [BazelWorkspace.findFile] when searching for
+/// generated files.
+///
+/// This allows clients to watch for changes to the generated files.
+class BazelFileNotification {
+  /// Candidate paths that we searched.
+  ///
+  /// If it's a singleton, then the file was found/resolved.
+  final List<String> candidates;
+
+  /// Absolute path that we tried searching for.
+  ///
+  /// This is not necessarily the path of the actual file that will be used. See
+  /// [BazelWorkspace.findFile] for details.
+  final String requested;
+
+  final ResourceProvider _provider;
+
+  BazelFileNotification(this.requested, this.candidates, this._provider);
+
+  BazelFileWatcher watcher(
+          {@required Duration pollingDelayShort,
+          @required Duration pollingDelayLong,
+          Timer Function(Duration, void Function(Timer)) timerFactory =
+              _defaultTimerFactory}) =>
+      BazelFileWatcher(candidates, _provider, pollingDelayShort,
+          pollingDelayLong, timerFactory);
+
+  static Timer _defaultTimerFactory(
+          Duration duration, void Function(Timer) callback) =>
+      Timer.periodic(duration, callback);
+}
 
 /// Instances of the class `BazelFileUriResolver` resolve `file` URI's by first
 /// resolving file uri's in the expected way, and then by looking in the
@@ -41,6 +77,140 @@
   }
 }
 
+/// Watches a list of files that should be generated by Bazel.
+///
+/// If we didn't find the file initially, we'll have more that one potential
+/// path. We'll poll them with a shorter delay waiting for at least one
+/// of the paths to become valid (we assume that users will generate the rather
+/// sooner than later since they will likely see errors due to unresolved
+/// files). Once a file appears, we switch to a different mode, where we only
+/// watch that particular file and poll it less frequently. If the file is
+/// deleted we go back to the initial mode of eager polling for all paths.
+class BazelFileWatcher {
+  /// The paths of files that we watch for.
+  ///
+  /// If it's a singleton, then the file was found/resolved by the
+  /// [BazelWorkspace].
+  final List<String> _candidates;
+
+  final _eventsController = StreamController<WatchEvent>.broadcast();
+
+  /// The time of last modification of the file under [_validPath].
+  int _lastModified;
+
+  /// How often do we poll a file that we have found.
+  final Duration _pollingDelayLong;
+
+  /// How often do we poll when none of potential files exist.
+  final Duration _pollingDelayShort;
+
+  final ResourceProvider _provider;
+
+  /// One of the [_candidates] that is valid, i.e., we found a file with that
+  /// path.
+  String _validPath;
+
+  Timer _timer;
+
+  /// Used to contruct a [Timer] for polling.
+  final Timer Function(Duration, void Function(Timer)) _timerFactory;
+
+  BazelFileWatcher(this._candidates, this._provider, this._pollingDelayShort,
+      this._pollingDelayLong, this._timerFactory);
+
+  Stream<WatchEvent> get events => _eventsController.stream;
+
+  /// Starts watching the files.
+  ///
+  /// To avoid missing events, the clients should first start listening on
+  /// [events] and then call [start].
+  void start() {
+    assert(_timer == null);
+    var info = _pollAll();
+    if (info != null) {
+      _validPath = info.path;
+      _lastModified = info.modified;
+      _setPollingDelayToLong();
+    } else {
+      _setPollingDelayToShort();
+    }
+  }
+
+  void stop() {
+    _timer.cancel();
+    _eventsController.close();
+  }
+
+  void _poll() {
+    if (_eventsController.isClosed) return;
+
+    int modified;
+    if (_validPath == null) {
+      var info = _pollAll();
+      if (info != null) {
+        _validPath = info.path;
+        modified = info.modified;
+      }
+    } else {
+      modified = _pollOne(_validPath);
+    }
+
+    // If there is no file, then we have nothing to do.
+    if (_validPath == null) return;
+
+    if (modified == null && _lastModified != null) {
+      // The file is no longer there, so let's issue a REMOVE event, unset
+      // `_validPath` and set the timer to poll more frequently.
+      _eventsController.add(WatchEvent(ChangeType.REMOVE, _validPath));
+      _validPath = null;
+      _setPollingDelayToShort();
+    } else if (modified != null && _lastModified == null) {
+      _eventsController.add(WatchEvent(ChangeType.ADD, _validPath));
+      _setPollingDelayToLong();
+    } else if (_lastModified != null && modified != _lastModified) {
+      _eventsController.add(WatchEvent(ChangeType.MODIFY, _validPath));
+    }
+    _lastModified = modified;
+  }
+
+  /// Tries polling all the possible paths.
+  ///
+  /// Will set [_validPath] and return its modified time if a file is found.
+  /// Returns [null] if nothing is found.
+  FileInfo _pollAll() {
+    assert(_validPath == null);
+    for (var path in _candidates) {
+      var modified = _pollOne(path);
+      if (modified != null) {
+        return FileInfo(path, modified);
+      }
+    }
+    return null;
+  }
+
+  /// Returns the modified time of the path or `null` if the file does not
+  /// exist.
+  int _pollOne(String path) {
+    try {
+      var file = _provider.getFile(path);
+      return file.modificationStamp;
+    } on FileSystemException catch (_) {
+      // File doesn't exist, so return null.
+      return null;
+    }
+  }
+
+  void _setPollingDelayToLong() {
+    _timer?.cancel();
+    _timer = _timerFactory(_pollingDelayLong, (_) => _poll());
+  }
+
+  void _setPollingDelayToShort() {
+    _timer?.cancel();
+    _timer = _timerFactory(_pollingDelayShort, (_) => _poll());
+  }
+}
+
 /// The [UriResolver] that can resolve `package` URIs in [BazelWorkspace].
 class BazelPackageUriResolver extends UriResolver {
   final BazelWorkspace _workspace;
@@ -62,7 +232,8 @@
   Source resolveAbsolute(Uri uri, [Uri actualUri]) {
     return _sourceCache.putIfAbsent(uri, () {
       if (uri.scheme == 'file') {
-        var pathRelativeToRoot = _workspace._relativeToRoot(uri.path);
+        var path = fileUriToNormalizedPath(_context, uri);
+        var pathRelativeToRoot = _workspace._relativeToRoot(path);
         if (pathRelativeToRoot == null) return null;
         var fullFilePath = _context.join(_workspace.root, pathRelativeToRoot);
         File file = _workspace.findFile(fullFilePath);
@@ -189,9 +360,21 @@
   /// The absolute path to the `bazel-genfiles` folder.
   final String genfiles;
 
+  /// The cache of packages. The key is the directory path, the value is
+  /// the corresponding package.
+  final Map<String, BazelWorkspacePackage> _directoryToPackage = {};
+
+  final _bazelCandidateFiles =
+      StreamController<BazelFileNotification>.broadcast();
+
   BazelWorkspace._(
       this.provider, this.root, this.readonly, this.binPaths, this.genfiles);
 
+  /// Stream of files that we tried to find along with their potential or actual
+  /// paths.
+  Stream<BazelFileNotification> get bazelCandidateFiles =>
+      _bazelCandidateFiles.stream;
+
   @override
   bool get isBazel => true;
 
@@ -224,17 +407,16 @@
       if (relative == '.') {
         return null;
       }
-      // genfiles
-      if (genfiles != null) {
-        File file = provider.getFile(context.join(genfiles, relative));
+      // First check genfiles and bin directories
+      var generatedCandidates = <String>[
+        if (genfiles != null) genfiles,
+        ...?binPaths
+      ].map((prefix) => context.join(prefix, relative));
+      for (var path in generatedCandidates) {
+        File file = provider.getFile(path);
         if (file.exists) {
-          return file;
-        }
-      }
-      // bin
-      for (String bin in binPaths) {
-        File file = provider.getFile(context.join(bin, relative));
-        if (file.exists) {
+          _bazelCandidateFiles.add(BazelFileNotification(
+              relative, generatedCandidates.toList(), provider));
           return file;
         }
       }
@@ -250,6 +432,10 @@
           return file;
         }
       }
+      // If we couldn't find the file, assume that it has not yet been
+      // generated, so send an event with all the paths that we tried.
+      _bazelCandidateFiles.add(BazelFileNotification(
+          relative, generatedCandidates.toList(), provider));
       // Not generated, return the default one.
       return writableFile;
     } catch (_) {
@@ -260,7 +446,14 @@
   @override
   WorkspacePackage findPackageFor(String filePath) {
     path.Context context = provider.pathContext;
-    Folder folder = provider.getFolder(context.dirname(filePath));
+    var directoryPath = context.dirname(filePath);
+
+    var cachedPackage = _directoryToPackage[directoryPath];
+    if (cachedPackage != null) {
+      return cachedPackage;
+    }
+
+    Folder folder = provider.getFolder(directoryPath);
     if (!context.isWithin(root, folder.path)) {
       return null;
     }
@@ -275,6 +468,21 @@
       }
     }
 
+    // Return a Package rooted at [folder].
+    BazelWorkspacePackage packageRootedHere() {
+      List<String> uriParts = (packageUriResolver as BazelPackageUriResolver)
+          ._restoreUriParts(root, '${folder.path}/lib/__fake__.dart');
+      String packageName;
+      if (uriParts != null && uriParts.isNotEmpty) {
+        packageName = uriParts[0];
+      }
+      // TODO(srawlins): If [packageName] could not be derived from [uriParts],
+      //  I imagine this should throw.
+      var package = BazelWorkspacePackage(packageName, folder.path, this);
+      _directoryToPackage[directoryPath] = package;
+      return package;
+    }
+
     while (true) {
       Folder parent = folder.parent;
       if (parent == null) {
@@ -286,15 +494,9 @@
         return null;
       }
 
-      // Return a Package rooted at [folder].
-      BazelWorkspacePackage packageRootedHere() {
-        List<String> uriParts = (packageUriResolver as BazelPackageUriResolver)
-            ._restoreUriParts(root, '${folder.path}/lib/__fake__.dart');
-        if (uriParts == null || uriParts.isEmpty) {
-          return BazelWorkspacePackage(null, folder.path, this);
-        } else {
-          return BazelWorkspacePackage(uriParts[0], folder.path, this);
-        }
+      if (folder.getChildAssumingFile(_buildFileName).exists) {
+        // Found the BUILD file, denoting a Dart package.
+        return packageRootedHere();
       }
 
       // In some distributed build environments, BUILD files are not preserved.
@@ -323,11 +525,6 @@
         }
       }
 
-      if (folder.getChildAssumingFile(_buildFileName).exists) {
-        // Found the BUILD file, denoting a Dart package.
-        return packageRootedHere();
-      }
-
       // Go up a folder.
       folder = parent;
     }
@@ -613,3 +810,9 @@
     }
   }
 }
+
+class FileInfo {
+  String path;
+  int modified;
+  FileInfo(this.path, this.modified);
+}
diff --git a/pkg/analyzer/lib/src/workspace/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart
index fe78cc0..3ceaea6 100644
--- a/pkg/analyzer/lib/src/workspace/gn.dart
+++ b/pkg/analyzer/lib/src/workspace/gn.dart
@@ -143,10 +143,15 @@
   /// For a source at `$root/foo/bar`, the packages files are generated in
   /// `$root/out/<debug|release>-XYZ/dartlang/gen/foo/bar`.
   ///
-  /// Note that in some cases multiple .packages files can be found at that
-  /// location, for example if the package contains both a library and a binary
-  /// target. For a complete view of the package, all of these files need to be
-  /// taken into account.
+  /// Note that in some cases multiple package_config.json files can be found at
+  /// that location, for example if the package contains both a library and a
+  /// binary target. For a complete view of the package, all of these files need
+  /// to be taken into account.
+  ///
+  /// Additionally, often times the package_config file name is prepended by
+  /// extra words, which results in file names like
+  /// `tiler_component_package_config.json`. Because of this, we cannot simply
+  /// check for `pathContext.basename(file.path) == 'package_config.json'`.
   static List<File> _findPackagesFile(
     ResourceProvider provider,
     String root,
@@ -166,7 +171,7 @@
     return genDir
         .getChildren()
         .whereType<File>()
-        .where((File file) => pathContext.extension(file.path) == '.packages')
+        .where((File file) => file.path.endsWith('package_config.json'))
         .toList();
   }
 
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index c14bbd5..19837d5 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.41.1
+version: 0.41.2-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
 
@@ -10,10 +10,10 @@
   _fe_analyzer_shared: ^14.0.0
   args: ^1.0.0
   cli_util: '>=0.1.4 <0.3.0'
-  collection: ^1.10.1
+  collection: ^1.15.0-nullsafety.5
   convert: ^2.0.0
-  crypto: ^2.0.0
-  glob: ^1.0.3
+  crypto: '>=2.0.0 <4.0.0'
+  glob: '>=1.0.3 <3.0.0'
   meta: ^1.2.3
   package_config: ^1.0.0
   path: ^1.0.0
@@ -24,6 +24,7 @@
 dev_dependencies:
   analyzer_utilities:
     path: ../analyzer_utilities
+  async: ^2.0.0
   linter: any
   matcher: ^0.12.3
   pedantic: ^1.9.0
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index ba3b7ed..913ea87 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -15,7 +15,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../generated/parser_test.dart' show ParserTestCase;
+import '../../generated/parser_test_base.dart' show ParserTestCase;
 import '../../generated/test_support.dart';
 
 main() {
@@ -943,7 +943,6 @@
         source,
         listener,
         featureSet: featureSet,
-        useFasta: true,
       ).parseCompilationUnit(tokens);
     }
     return _unit;
diff --git a/pkg/analyzer/test/dart/ast/visitor_test.dart b/pkg/analyzer/test/dart/ast/visitor_test.dart
index 9a14730..3499a33 100644
--- a/pkg/analyzer/test/dart/ast/visitor_test.dart
+++ b/pkg/analyzer/test/dart/ast/visitor_test.dart
@@ -7,7 +7,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../generated/parser_test.dart' show ParserTestCase;
+import '../../generated/parser_test_base.dart' show ParserTestCase;
 import '../../util/ast_type_matchers.dart';
 
 main() {
diff --git a/pkg/analyzer/test/embedder_tests.dart b/pkg/analyzer/test/embedder_tests.dart
index c59eb00..ac01db8 100644
--- a/pkg/analyzer/test/embedder_tests.dart
+++ b/pkg/analyzer/test/embedder_tests.dart
@@ -14,8 +14,8 @@
   final String foxPath = '/home/.pub-cache/fox';
   final String foxLib = '/home/.pub-cache/fox/lib';
 
-  TestPathTranslator pathTranslator;
-  ResourceProvider resourceProvider;
+  /*late*/ TestPathTranslator pathTranslator;
+  /*late*/ ResourceProvider resourceProvider;
 
   buildResourceProvider() {
     MemoryResourceProvider rawProvider = MemoryResourceProvider();
@@ -34,16 +34,7 @@
 ''');
   }
 
-  clearResourceProvider() {
-    resourceProvider = null;
-    pathTranslator = null;
-  }
-
   void setUp() {
     buildResourceProvider();
   }
-
-  void tearDown() {
-    clearResourceProvider();
-  }
 }
diff --git a/pkg/analyzer/test/error/error_test.dart b/pkg/analyzer/test/error/error_test.dart
index 2e48e60..d2daf51 100644
--- a/pkg/analyzer/test/error/error_test.dart
+++ b/pkg/analyzer/test/error/error_test.dart
@@ -10,7 +10,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../generated/parser_test.dart';
+import '../generated/parser_test_base.dart';
 
 main() {
   _analyzerRootComponents = path.split(path.fromUri(Platform.script));
diff --git a/pkg/analyzer/test/file_system/file_system_test_support.dart b/pkg/analyzer/test/file_system/file_system_test_support.dart
index 96db954..adf8754 100644
--- a/pkg/analyzer/test/file_system/file_system_test_support.dart
+++ b/pkg/analyzer/test/file_system/file_system_test_support.dart
@@ -124,7 +124,7 @@
 
   test_equals_samePath() {
     File file1 = getFile(exists: true);
-    File file2 = provider.getResource(file1.path);
+    var file2 = provider.getResource(file1.path) as File;
 
     expect(file1 == file2, isTrue);
   }
@@ -143,7 +143,7 @@
 
   test_hashCode_samePath() {
     File file1 = getFile(exists: true);
-    File file2 = provider.getResource(file1.path);
+    var file2 = provider.getResource(file1.path) as File;
 
     expect(file1.hashCode, equals(file2.hashCode));
   }
diff --git a/pkg/analyzer/test/generated/class_member_parser_test.dart b/pkg/analyzer/test/generated/class_member_parser_test.dart
new file mode 100644
index 0000000..36f4c5d
--- /dev/null
+++ b/pkg/analyzer/test/generated/class_member_parser_test.dart
@@ -0,0 +1,1929 @@
+// 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:_fe_analyzer_shared/src/scanner/errors.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ClassMemberParserTest);
+  });
+}
+
+/// Tests which exercise the parser using a class member.
+@reflectiveTest
+class ClassMemberParserTest extends FastaParserTestCase
+    implements AbstractParserViaProxyTestCase {
+  final tripleShift = FeatureSet.forTesting(
+      sdkVersion: '2.0.0', additionalFeatures: [Feature.triple_shift]);
+
+  void test_parse_member_called_late() {
+    var unit = parseCompilationUnit(
+        'class C { void late() { new C().late(); } }',
+        featureSet: nonNullable);
+    var declaration = unit.declarations[0] as ClassDeclaration;
+    var method = declaration.members[0] as MethodDeclaration;
+
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name.name, 'late');
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+
+    var body = method.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var invocation = statement.expression as MethodInvocation;
+    expect(invocation.operator.lexeme, '.');
+    expect(invocation.toSource(), 'new C().late()');
+  }
+
+  void test_parseAwaitExpression_asStatement_inAsync() {
+    createParser('m() async { await x; }');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    FunctionBody body = method.body;
+    expect(body, isBlockFunctionBody);
+    Statement statement = (body as BlockFunctionBody).block.statements[0];
+    expect(statement, isExpressionStatement);
+    Expression expression = (statement as ExpressionStatement).expression;
+    expect(expression, isAwaitExpression);
+    expect((expression as AwaitExpression).awaitKeyword, isNotNull);
+    expect((expression as AwaitExpression).expression, isNotNull);
+  }
+
+  void test_parseAwaitExpression_asStatement_inSync() {
+    createParser('m() { await x; }');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    FunctionBody body = method.body;
+    expect(body, isBlockFunctionBody);
+    Statement statement = (body as BlockFunctionBody).block.statements[0];
+    expect(statement, isVariableDeclarationStatement);
+  }
+
+  void test_parseAwaitExpression_inSync() {
+    createParser('m() { return await x + await y; }');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expect(method, isNotNull);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 13, 5),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5)
+    ]);
+    FunctionBody body = method.body;
+    expect(body, isBlockFunctionBody);
+    Statement statement = (body as BlockFunctionBody).block.statements[0];
+    expect(statement, isReturnStatement);
+    Expression expression = (statement as ReturnStatement).expression;
+    expect(expression, isBinaryExpression);
+  }
+
+  void test_parseClassMember_constructor_withDocComment() {
+    createParser('/// Doc\nC();');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    expectCommentText(constructor.documentationComment, '/// Doc');
+  }
+
+  void test_parseClassMember_constructor_withInitializers() {
+    // TODO(brianwilkerson) Test other kinds of class members: fields, getters
+    // and setters.
+    createParser('C(_, _\$, this.__) : _a = _ + _\$ {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isConstructorDeclaration);
+    ConstructorDeclaration constructor = member;
+    expect(constructor.body, isNotNull);
+    expect(constructor.separator, isNotNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword, isNull);
+    expect(constructor.factoryKeyword, isNull);
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.period, isNull);
+    expect(constructor.returnType, isNotNull);
+    expect(constructor.initializers, hasLength(1));
+  }
+
+  void test_parseClassMember_field_covariant() {
+    createParser('covariant T f;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNotNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseClassMember_field_generic() {
+    createParser('List<List<N>> _allComponents = new List<List<N>>();');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
+    TypeName type = list.type;
+    expect(type.name.name, 'List');
+    NodeList typeArguments = type.typeArguments.arguments;
+    expect(typeArguments, hasLength(1));
+    TypeName type2 = typeArguments[0];
+    expect(type2.name.name, 'List');
+    NodeList typeArguments2 = type2.typeArguments.arguments;
+    expect(typeArguments2, hasLength(1));
+    TypeName type3 = typeArguments2[0];
+    expect(type3.name.name, 'N');
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseClassMember_field_gftType_gftReturnType() {
+    createParser('''
+Function(int) Function(String) v;
+''');
+    ClassMember member = parser.parseClassMember('C');
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    VariableDeclarationList fields = (member as FieldDeclaration).fields;
+    expect(fields.type, isGenericFunctionType);
+  }
+
+  void test_parseClassMember_field_gftType_noReturnType() {
+    createParser('''
+Function(int, String) v;
+''');
+    ClassMember member = parser.parseClassMember('C');
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    VariableDeclarationList fields = (member as FieldDeclaration).fields;
+    expect(fields.type, isGenericFunctionType);
+  }
+
+  void test_parseClassMember_field_instance_prefixedType() {
+    createParser('p.A f;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+    _assertIsDeclarationName(variable.name);
+  }
+
+  void test_parseClassMember_field_namedGet() {
+    createParser('var get;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseClassMember_field_namedOperator() {
+    createParser('var operator;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseClassMember_field_namedOperator_withAssignment() {
+    createParser('var operator = (5);');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+    expect(variable.initializer, isNotNull);
+  }
+
+  void test_parseClassMember_field_namedSet() {
+    createParser('var set;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseClassMember_field_nameKeyword() {
+    createParser('var for;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 4, 3)
+    ]);
+  }
+
+  void test_parseClassMember_field_nameMissing() {
+    createParser('var ;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]);
+  }
+
+  void test_parseClassMember_field_nameMissing2() {
+    createParser('var "";');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 2)]);
+  }
+
+  void test_parseClassMember_field_static() {
+    createParser('static A f;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    FieldDeclaration field = member;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNotNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isFalse);
+    expect(list.lateKeyword, isNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseClassMember_finalAndCovariantLateWithInitializer() {
+    createParser(
+      'covariant late final int f = 0;',
+      featureSet: nonNullable,
+    );
+    parser.parseClassMember('C');
+    assertErrors(errors: [
+      expectedError(
+          ParserErrorCode.FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER, 0, 9)
+    ]);
+  }
+
+  void test_parseClassMember_getter_functionType() {
+    createParser('int Function(int) get g {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.body, isNotNull);
+    expect(method.parameters, isNull);
+  }
+
+  void test_parseClassMember_getter_void() {
+    createParser('void get g {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    _assertIsDeclarationName(method.name);
+    expect(method.operatorKeyword, isNull);
+    expect(method.body, isNotNull);
+    expect(method.parameters, isNull);
+  }
+
+  void test_parseClassMember_method_external() {
+    createParser('external m();');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNotNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.name, isNotNull);
+    _assertIsDeclarationName(method.name);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNull);
+
+    var body = method.body as EmptyFunctionBody;
+    expect(body.keyword, isNull);
+    expect(body.star, isNull);
+    expect(body.semicolon.type, TokenType.SEMICOLON);
+  }
+
+  void test_parseClassMember_method_external_withTypeAndArgs() {
+    createParser('external int m(int a);');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.body, isNotNull);
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNotNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+  }
+
+  void test_parseClassMember_method_generic_noReturnType() {
+    createParser('m<T>() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNotNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_generic_parameterType() {
+    createParser('m<T>(T p) => null;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNotNull);
+
+    FormalParameterList parameters = method.parameters;
+    expect(parameters, isNotNull);
+    expect(parameters.parameters, hasLength(1));
+    var parameter = parameters.parameters[0] as SimpleFormalParameter;
+    var parameterType = parameter.type as TypeName;
+    expect(parameterType.name.name, 'T');
+
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_generic_returnType() {
+    createParser('T m<T>() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNotNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_generic_returnType_bound() {
+    createParser('T m<T extends num>() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect((method.returnType as TypeName).name.name, 'T');
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNotNull);
+    TypeParameter tp = method.typeParameters.typeParameters[0];
+    expect(tp.name.name, 'T');
+    expect(tp.extendsKeyword, isNotNull);
+    expect((tp.bound as TypeName).name.name, 'num');
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_generic_returnType_complex() {
+    createParser('Map<int, T> m<T>() => null;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+
+    {
+      var returnType = method.returnType as TypeName;
+      expect(returnType, isNotNull);
+      expect(returnType.name.name, 'Map');
+
+      List<TypeAnnotation> typeArguments = returnType.typeArguments.arguments;
+      expect(typeArguments, hasLength(2));
+      expect((typeArguments[0] as TypeName).name.name, 'int');
+      expect((typeArguments[1] as TypeName).name.name, 'T');
+    }
+
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNotNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_generic_returnType_static() {
+    createParser('static T m<T>() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNotNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect((method.returnType as TypeName).name.name, 'T');
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNotNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_generic_void() {
+    createParser('void m<T>() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNotNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_get_noType() {
+    createParser('get() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_get_static_namedAsClass() {
+    createParser('static int get C => 0;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 15, 1),
+    ]);
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNotNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_get_type() {
+    createParser('int get() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_get_void() {
+    createParser('void get() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_gftReturnType_noReturnType() {
+    createParser('''
+Function<A>(core.List<core.int> x) m() => null;
+''');
+    ClassMember member = parser.parseClassMember('C');
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    expect((member as MethodDeclaration).body, isExpressionFunctionBody);
+  }
+
+  void test_parseClassMember_method_gftReturnType_voidReturnType() {
+    createParser('''
+void Function<A>(core.List<core.int> x) m() => null;
+''');
+    ClassMember member = parser.parseClassMember('C');
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    expect((member as MethodDeclaration).body, isExpressionFunctionBody);
+  }
+
+  void test_parseClassMember_method_native_allowed() {
+    allowNativeClause = true;
+    _parseClassMember_method_native();
+    assertNoErrors();
+  }
+
+  void test_parseClassMember_method_native_missing_literal_allowed() {
+    allowNativeClause = true;
+    _parseClassMember_method_native_missing_literal();
+    assertNoErrors();
+  }
+
+  void test_parseClassMember_method_native_missing_literal_not_allowed() {
+    allowNativeClause = false;
+    _parseClassMember_method_native_missing_literal();
+    listener.assertErrors([
+      expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
+    ]);
+  }
+
+  void test_parseClassMember_method_native_not_allowed() {
+    allowNativeClause = false;
+    _parseClassMember_method_native();
+    listener.assertErrors([
+      expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
+    ]);
+  }
+
+  void test_parseClassMember_method_native_with_body_allowed() {
+    allowNativeClause = true;
+    _parseClassMember_method_native_with_body();
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    assertErrorsWithCodes([
+      ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
+    ]);
+//      listener.assertErrors([
+//        expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 17, 2),
+//      ]);
+  }
+
+  void test_parseClassMember_method_native_with_body_not_allowed() {
+    allowNativeClause = false;
+    _parseClassMember_method_native_with_body();
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    assertErrorsWithCodes([
+      ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
+      ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
+    ]);
+//      listener.assertErrors([
+//        expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
+//        expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 17, 2),
+//      ]);
+  }
+
+  void test_parseClassMember_method_operator_noType() {
+    createParser('operator() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_operator_type() {
+    createParser('int operator() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_operator_void() {
+    createParser('void operator() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_returnType_functionType() {
+    createParser('int Function(String) m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.name.name, 'm');
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_returnType_parameterized() {
+    createParser('p.A m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_set_noType() {
+    createParser('set() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_set_static_namedAsClass() {
+    createParser('static void set C(_) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
+    ]);
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNotNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_set_type() {
+    createParser('int set() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_set_void() {
+    createParser('void set() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_static_class() {
+    var unit = parseCompilationUnit('class C { static void m() {} }');
+
+    ClassDeclaration c = unit.declarations[0];
+    MethodDeclaration method = c.members[0];
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNotNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_static_mixin() {
+    var unit = parseCompilationUnit('mixin C { static void m() {} }');
+    MixinDeclaration c = unit.declarations[0];
+    MethodDeclaration method = c.members[0];
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNotNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_method_trailing_commas() {
+    createParser('void f(int x, int y,) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_operator_functionType() {
+    createParser('int Function() operator +(int Function() f) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isGenericFunctionType);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNotNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    NodeList<FormalParameter> parameters = method.parameters.parameters;
+    expect(parameters, hasLength(1));
+    expect(
+        (parameters[0] as SimpleFormalParameter).type, isGenericFunctionType);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_operator_gtgtgt() {
+    var unit = parseCompilationUnit(
+        'class C { bool operator >>>(other) => false; }',
+        featureSet: tripleShift);
+    var declaration = unit.declarations[0] as ClassDeclaration;
+    var method = declaration.members[0] as MethodDeclaration;
+
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name.name, '>>>');
+    expect(method.operatorKeyword, isNotNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_operator_gtgtgteq() {
+    var unit = parseCompilationUnit(
+        'class C { foo(int value) { x >>>= value; } }',
+        featureSet: tripleShift);
+    var declaration = unit.declarations[0] as ClassDeclaration;
+    var method = declaration.members[0] as MethodDeclaration;
+    var blockFunctionBody = method.body as BlockFunctionBody;
+    NodeList<Statement> statements = blockFunctionBody.block.statements;
+    expect(statements, hasLength(1));
+    var statement = statements[0] as ExpressionStatement;
+    var assignment = statement.expression as AssignmentExpression;
+    var leftHandSide = assignment.leftHandSide as SimpleIdentifier;
+    expect(leftHandSide.name, 'x');
+    expect(assignment.operator.lexeme, '>>>=');
+    var rightHandSide = assignment.rightHandSide as SimpleIdentifier;
+    expect(rightHandSide.name, 'value');
+  }
+
+  void test_parseClassMember_operator_index() {
+    createParser('int operator [](int i) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNotNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_operator_indexAssign() {
+    createParser('int operator []=(int i) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNotNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_operator_lessThan() {
+    createParser('bool operator <(other) => false;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name.name, '<');
+    expect(method.operatorKeyword, isNotNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.body, isNotNull);
+  }
+
+  void test_parseClassMember_redirectingFactory_const() {
+    createParser('const factory C() = prefix.B.foo;');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    assertNoErrors();
+    expect(constructor, isNotNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword.keyword, Keyword.CONST);
+    expect(constructor.factoryKeyword.keyword, Keyword.FACTORY);
+    expect(constructor.returnType.name, 'C');
+    expect(constructor.period, isNull);
+    expect(constructor.name, isNull);
+    _assertIsDeclarationName(constructor.returnType, false);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, isEmpty);
+    expect(constructor.separator.type, TokenType.EQ);
+    expect(constructor.initializers, isEmpty);
+    expect(constructor.redirectedConstructor, isNotNull);
+    expect(constructor.redirectedConstructor.type.name.name, 'prefix.B');
+    expect(constructor.redirectedConstructor.period.type, TokenType.PERIOD);
+    expect(constructor.redirectedConstructor.name.name, 'foo');
+    expect(constructor.body, isEmptyFunctionBody);
+  }
+
+  void test_parseClassMember_redirectingFactory_expressionBody() {
+    createParser('factory C() => throw 0;');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    assertNoErrors();
+    expect(constructor, isNotNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword, isNull);
+    expect(constructor.factoryKeyword.keyword, Keyword.FACTORY);
+    expect(constructor.returnType.name, 'C');
+    expect(constructor.period, isNull);
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, isEmpty);
+    expect(constructor.separator, isNull);
+    expect(constructor.initializers, isEmpty);
+    expect(constructor.redirectedConstructor, isNull);
+
+    var body = constructor.body as ExpressionFunctionBody;
+    expect(body.keyword, isNull);
+    expect(body.star, isNull);
+    expect(body.functionDefinition.type, TokenType.FUNCTION);
+    expect(body.expression, isNotNull);
+    expect(body.semicolon, isNotNull);
+  }
+
+  void test_parseClassMember_redirectingFactory_nonConst() {
+    createParser('factory C() = B;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isConstructorDeclaration);
+    ConstructorDeclaration constructor = member;
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword, isNull);
+    expect(constructor.factoryKeyword.keyword, Keyword.FACTORY);
+    expect(constructor.returnType.name, 'C');
+    _assertIsDeclarationName(constructor.returnType, false);
+    expect(constructor.period, isNull);
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, isEmpty);
+    expect(constructor.separator.type, TokenType.EQ);
+    expect(constructor.initializers, isEmpty);
+    expect(constructor.redirectedConstructor, isNotNull);
+    expect(constructor.redirectedConstructor.type.name.name, 'B');
+    expect(constructor.redirectedConstructor.period, isNull);
+    expect(constructor.redirectedConstructor.name, isNull);
+    expect(constructor.body, isEmptyFunctionBody);
+  }
+
+  void test_parseConstructor_assert() {
+    createParser('C(x, y) : _x = x, assert (x < y), _y = y;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isConstructorDeclaration);
+    ConstructorDeclaration constructor = member as ConstructorDeclaration;
+    NodeList<ConstructorInitializer> initializers = constructor.initializers;
+    expect(initializers, hasLength(3));
+    ConstructorInitializer initializer = initializers[1];
+    expect(initializer, isAssertInitializer);
+    AssertInitializer assertInitializer = initializer;
+    expect(assertInitializer.condition, isNotNull);
+    expect(assertInitializer.message, isNull);
+  }
+
+  void test_parseConstructor_factory_const_external() {
+    // Although the spec does not allow external const factory,
+    // there are several instances of this in the Dart SDK.
+    // For example `external const factory bool.fromEnvironment(...)`.
+    createParser('external const factory C();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_parseConstructor_factory_named() {
+    createParser('factory C.foo() => throw 0;');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    assertNoErrors();
+    expect(constructor, isNotNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword, isNull);
+    expect(constructor.factoryKeyword, isNotNull);
+    expect(constructor.returnType.name, 'C');
+    _assertIsDeclarationName(constructor.returnType, false);
+    expect(constructor.period.type, TokenType.PERIOD);
+    expect(constructor.name.name, 'foo');
+    _assertIsDeclarationName(constructor.name);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, isEmpty);
+    expect(constructor.separator, isNull);
+    expect(constructor.initializers, isEmpty);
+    expect(constructor.redirectedConstructor, isNull);
+    expect(constructor.body, isExpressionFunctionBody);
+  }
+
+  void test_parseConstructor_initializers_field() {
+    createParser('C(x, y) : _x = x, this._y = y;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isConstructorDeclaration);
+    ConstructorDeclaration constructor = member as ConstructorDeclaration;
+    NodeList<ConstructorInitializer> initializers = constructor.initializers;
+    expect(initializers, hasLength(2));
+
+    {
+      var initializer = initializers[0] as ConstructorFieldInitializer;
+      expect(initializer.thisKeyword, isNull);
+      expect(initializer.period, isNull);
+      expect(initializer.fieldName.name, '_x');
+      expect(initializer.expression, isNotNull);
+    }
+
+    {
+      var initializer = initializers[1] as ConstructorFieldInitializer;
+      expect(initializer.thisKeyword, isNotNull);
+      expect(initializer.period, isNotNull);
+      expect(initializer.fieldName.name, '_y');
+      expect(initializer.expression, isNotNull);
+    }
+  }
+
+  void test_parseConstructor_invalidInitializer() {
+    // https://github.com/dart-lang/sdk/issues/37693
+    parseCompilationUnit('class C{ C() : super() * (); }', errors: [
+      expectedError(ParserErrorCode.INVALID_INITIALIZER, 15, 12),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
+    ]);
+  }
+
+  void test_parseConstructor_named() {
+    createParser('C.foo();');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    assertNoErrors();
+    expect(constructor, isNotNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword, isNull);
+    expect(constructor.factoryKeyword, isNull);
+    expect(constructor.returnType.name, 'C');
+    _assertIsDeclarationName(constructor.returnType, false);
+    expect(constructor.period.type, TokenType.PERIOD);
+    expect(constructor.name.name, 'foo');
+    _assertIsDeclarationName(constructor.name);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, isEmpty);
+    expect(constructor.separator, isNull);
+    expect(constructor.initializers, isEmpty);
+    expect(constructor.redirectedConstructor, isNull);
+    expect(constructor.body, isEmptyFunctionBody);
+  }
+
+  void test_parseConstructor_nullSuperArgList_openBrace_37735() {
+    // https://github.com/dart-lang/sdk/issues/37735
+    var unit = parseCompilationUnit('class{const():super.{n', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
+      expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 11, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 1),
+      expectedError(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, 20, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 21, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 22, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 22, 1),
+    ]);
+    var classDeclaration = unit.declarations[0] as ClassDeclaration;
+    var constructor = classDeclaration.members[0] as ConstructorDeclaration;
+    var invocation = constructor.initializers[0] as SuperConstructorInvocation;
+    expect(invocation.argumentList.arguments, hasLength(0));
+  }
+
+  void test_parseConstructor_operator_name() {
+    var unit = parseCompilationUnit('class A { operator/() : super(); }',
+        errors: [
+          expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 10, 8)
+        ]);
+    var classDeclaration = unit.declarations[0] as ClassDeclaration;
+    var constructor = classDeclaration.members[0] as ConstructorDeclaration;
+    var invocation = constructor.initializers[0] as SuperConstructorInvocation;
+    expect(invocation.argumentList.arguments, hasLength(0));
+  }
+
+  void test_parseConstructor_superIndexed() {
+    createParser('C() : super()[];');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    listener.assertErrors([
+      expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 6, 5),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 1),
+    ]);
+    expect(constructor, isNotNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword, isNull);
+    expect(constructor.factoryKeyword, isNull);
+    expect(constructor.returnType.name, 'C');
+    _assertIsDeclarationName(constructor.returnType, false);
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, isEmpty);
+    expect(constructor.separator.lexeme, ':');
+    expect(constructor.initializers, hasLength(1));
+    SuperConstructorInvocation initializer = constructor.initializers[0];
+    expect(initializer.argumentList.arguments, isEmpty);
+    expect(constructor.redirectedConstructor, isNull);
+    expect(constructor.body, isEmptyFunctionBody);
+  }
+
+  void test_parseConstructor_thisIndexed() {
+    createParser('C() : this()[];');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    listener.assertErrors([
+      expectedError(ParserErrorCode.INVALID_THIS_IN_INITIALIZER, 6, 4),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+    ]);
+    expect(constructor, isNotNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword, isNull);
+    expect(constructor.factoryKeyword, isNull);
+    expect(constructor.returnType.name, 'C');
+    _assertIsDeclarationName(constructor.returnType, false);
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, isEmpty);
+    expect(constructor.separator.lexeme, ':');
+    expect(constructor.initializers, hasLength(1));
+    RedirectingConstructorInvocation initializer = constructor.initializers[0];
+    expect(initializer.argumentList.arguments, isEmpty);
+    expect(constructor.redirectedConstructor, isNull);
+    expect(constructor.body, isEmptyFunctionBody);
+  }
+
+  void test_parseConstructor_unnamed() {
+    createParser('C();');
+    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
+    assertNoErrors();
+    expect(constructor, isNotNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.constKeyword, isNull);
+    expect(constructor.factoryKeyword, isNull);
+    expect(constructor.returnType.name, 'C');
+    _assertIsDeclarationName(constructor.returnType, false);
+    expect(constructor.period, isNull);
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, isEmpty);
+    expect(constructor.separator, isNull);
+    expect(constructor.initializers, isEmpty);
+    expect(constructor.redirectedConstructor, isNull);
+    expect(constructor.body, isEmptyFunctionBody);
+  }
+
+  void test_parseConstructor_with_pseudo_function_literal() {
+    // "(b) {}" should not be misinterpreted as a function literal even though
+    // it looks like one.
+    createParser('C() : a = (b) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isConstructorDeclaration);
+    ConstructorDeclaration constructor = member as ConstructorDeclaration;
+    NodeList<ConstructorInitializer> initializers = constructor.initializers;
+    expect(initializers, hasLength(1));
+    ConstructorInitializer initializer = initializers[0];
+    expect(initializer, isConstructorFieldInitializer);
+    expect((initializer as ConstructorFieldInitializer).expression,
+        isParenthesizedExpression);
+    expect(constructor.body, isBlockFunctionBody);
+  }
+
+  void test_parseConstructorFieldInitializer_qualified() {
+    var initializer = parseConstructorInitializer('this.a = b')
+        as ConstructorFieldInitializer;
+    expect(initializer, isNotNull);
+    assertNoErrors();
+    expect(initializer.equals, isNotNull);
+    expect(initializer.expression, isNotNull);
+    expect(initializer.fieldName, isNotNull);
+    expect(initializer.thisKeyword, isNotNull);
+    expect(initializer.period, isNotNull);
+  }
+
+  void test_parseConstructorFieldInitializer_unqualified() {
+    var initializer =
+        parseConstructorInitializer('a = b') as ConstructorFieldInitializer;
+    expect(initializer, isNotNull);
+    assertNoErrors();
+    expect(initializer.equals, isNotNull);
+    expect(initializer.expression, isNotNull);
+    expect(initializer.fieldName, isNotNull);
+    expect(initializer.thisKeyword, isNull);
+    expect(initializer.period, isNull);
+  }
+
+  void test_parseField_abstract() {
+    createParser('abstract int i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.abstractKeyword, isNotNull);
+  }
+
+  void test_parseField_abstract_external() {
+    createParser('abstract external int i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.ABSTRACT_EXTERNAL_FIELD, 0, 8),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.abstractKeyword, isNotNull);
+    expect(field.externalKeyword, isNotNull);
+  }
+
+  void test_parseField_abstract_late() {
+    createParser('abstract late int? i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.ABSTRACT_LATE_FIELD, 0, 8),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.abstractKeyword, isNotNull);
+  }
+
+  void test_parseField_abstract_late_final() {
+    createParser('abstract late final int? i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.ABSTRACT_LATE_FIELD, 0, 8),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.abstractKeyword, isNotNull);
+  }
+
+  void test_parseField_abstract_static() {
+    createParser('abstract static int? i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.ABSTRACT_STATIC_FIELD, 0, 8),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.abstractKeyword, isNotNull);
+  }
+
+  void test_parseField_const_late() {
+    createParser('const late T f = 0;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 6, 4),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isTrue);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_external() {
+    createParser('external int i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.externalKeyword, isNotNull);
+  }
+
+  void test_parseField_external_abstract() {
+    createParser('external abstract int i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.ABSTRACT_EXTERNAL_FIELD, 9, 8),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.abstractKeyword, isNotNull);
+    expect(field.externalKeyword, isNotNull);
+  }
+
+  void test_parseField_external_late() {
+    createParser('external late int? i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.externalKeyword, isNotNull);
+  }
+
+  void test_parseField_external_late_final() {
+    createParser('external late final int? i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.externalKeyword, isNotNull);
+  }
+
+  void test_parseField_external_static() {
+    createParser('external static int? i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.externalKeyword, isNotNull);
+  }
+
+  void test_parseField_final_late() {
+    createParser('final late T f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4),
+    ]);
+    expect(member, isNotNull);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isTrue);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_late() {
+    createParser('late T f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_late_const() {
+    createParser('late const T f = 0;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 5, 5),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isTrue);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_late_final() {
+    createParser('late final T f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isTrue);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_late_var() {
+    createParser('late var f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseField_non_abstract() {
+    createParser('int i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.abstractKeyword, isNull);
+  }
+
+  void test_parseField_non_external() {
+    createParser('int i;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.externalKeyword, isNull);
+  }
+
+  void test_parseField_var_late() {
+    createParser('var late f;', featureSet: nonNullable);
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 4, 4),
+    ]);
+    expect(member, isFieldDeclaration);
+    var field = member as FieldDeclaration;
+    expect(field.covariantKeyword, isNull);
+    expect(field.documentationComment, isNull);
+    expect(field.metadata, hasLength(0));
+    expect(field.staticKeyword, isNull);
+    VariableDeclarationList list = field.fields;
+    expect(list, isNotNull);
+    expect(list.keyword, isNotNull);
+    expect(list.isConst, isFalse);
+    expect(list.isFinal, isFalse);
+    expect(list.isLate, isTrue);
+    expect(list.lateKeyword, isNotNull);
+    NodeList<VariableDeclaration> variables = list.variables;
+    expect(variables, hasLength(1));
+    VariableDeclaration variable = variables[0];
+    expect(variable.name, isNotNull);
+  }
+
+  void test_parseGetter_identifier_colon_issue_36961() {
+    createParser('get a:');
+    ConstructorDeclaration constructor = parser.parseClassMember('C');
+    expect(constructor, isNotNull);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.GETTER_CONSTRUCTOR, 0, 3),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 4, 1),
+      expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 4, 1),
+      expectedError(ParserErrorCode.MISSING_INITIALIZER, 5, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 6, 0),
+    ]);
+    expect(constructor.body, isNotNull);
+    expect(constructor.documentationComment, isNull);
+    expect(constructor.externalKeyword, isNull);
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.returnType, isNotNull);
+  }
+
+  void test_parseGetter_nonStatic() {
+    createParser('/// Doc\nT get a;');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expect(method, isNotNull);
+    assertNoErrors();
+    expect(method.body, isNotNull);
+    expectCommentText(method.documentationComment, '/// Doc');
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.parameters, isNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect((method.returnType as TypeName).name.name, 'T');
+  }
+
+  void test_parseGetter_static() {
+    createParser('/// Doc\nstatic T get a => 42;');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expect(method, isNotNull);
+    assertNoErrors();
+    expect(method.body, isNotNull);
+    expectCommentText(method.documentationComment, '/// Doc');
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword.lexeme, 'static');
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect((method.returnType as TypeName).name.name, 'T');
+  }
+
+  void test_parseInitializedIdentifierList_type() {
+    createParser("/// Doc\nstatic T a = 1, b, c = 3;");
+    FieldDeclaration declaration = parser.parseClassMember('C');
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expectCommentText(declaration.documentationComment, '/// Doc');
+    VariableDeclarationList fields = declaration.fields;
+    expect(fields, isNotNull);
+    expect(fields.keyword, isNull);
+    expect((fields.type as TypeName).name.name, 'T');
+    expect(fields.variables, hasLength(3));
+    expect(declaration.staticKeyword.lexeme, 'static');
+    expect(declaration.semicolon, isNotNull);
+  }
+
+  void test_parseInitializedIdentifierList_var() {
+    createParser('/// Doc\nstatic var a = 1, b, c = 3;');
+    FieldDeclaration declaration = parser.parseClassMember('C');
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expectCommentText(declaration.documentationComment, '/// Doc');
+    VariableDeclarationList fields = declaration.fields;
+    expect(fields, isNotNull);
+    expect(fields.keyword.lexeme, 'var');
+    expect(fields.type, isNull);
+    expect(fields.variables, hasLength(3));
+    expect(declaration.staticKeyword.lexeme, 'static');
+    expect(declaration.semicolon, isNotNull);
+  }
+
+  void test_parseOperator() {
+    createParser('/// Doc\nT operator +(A a);');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expect(method, isNotNull);
+    assertNoErrors();
+    expect(method.body, isNotNull);
+    expectCommentText(method.documentationComment, '/// Doc');
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNotNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.propertyKeyword, isNull);
+    expect((method.returnType as TypeName).name.name, 'T');
+  }
+
+  void test_parseSetter_nonStatic() {
+    createParser('/// Doc\nT set a(var x);');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expect(method, isNotNull);
+    assertNoErrors();
+    expect(method.body, isNotNull);
+    expectCommentText(method.documentationComment, '/// Doc');
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword, isNull);
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect((method.returnType as TypeName).name.name, 'T');
+  }
+
+  void test_parseSetter_static() {
+    createParser('/// Doc\nstatic T set a(var x) {}');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expect(method, isNotNull);
+    assertNoErrors();
+    expect(method.body, isNotNull);
+    expectCommentText(method.documentationComment, '/// Doc');
+    expect(method.externalKeyword, isNull);
+    expect(method.modifierKeyword.lexeme, 'static');
+    expect(method.name, isNotNull);
+    expect(method.operatorKeyword, isNull);
+    expect(method.typeParameters, isNull);
+    expect(method.parameters, isNotNull);
+    expect(method.propertyKeyword, isNotNull);
+    expect((method.returnType as TypeName).name.name, 'T');
+  }
+
+  void test_simpleFormalParameter_withDocComment() {
+    createParser('''
+int f(
+    /// Doc
+    int x) {}
+''');
+    var function = parseFullCompilationUnitMember() as FunctionDeclaration;
+    var parameter = function.functionExpression.parameters.parameters[0]
+        as NormalFormalParameter;
+    expectCommentText(parameter.documentationComment, '/// Doc');
+  }
+
+  /// Assert that the given [name] is in declaration context.
+  void _assertIsDeclarationName(SimpleIdentifier name, [bool expected = true]) {
+    expect(name.inDeclarationContext(), expected);
+  }
+
+  void _parseClassMember_method_native() {
+    createParser('m() native "str";');
+    var method = parser.parseClassMember('C') as MethodDeclaration;
+    var body = method.body as NativeFunctionBody;
+    expect(body.nativeKeyword, isNotNull);
+    expect(body.stringLiteral, isNotNull);
+    expect(body.stringLiteral?.stringValue, "str");
+    expect(body.semicolon, isNotNull);
+  }
+
+  void _parseClassMember_method_native_missing_literal() {
+    createParser('m() native;');
+    var method = parser.parseClassMember('C') as MethodDeclaration;
+    var body = method.body as NativeFunctionBody;
+    expect(body.nativeKeyword, isNotNull);
+    expect(body.stringLiteral, isNull);
+    expect(body.semicolon, isNotNull);
+  }
+
+  void _parseClassMember_method_native_with_body() {
+    createParser('m() native "str" {}');
+    parser.parseClassMember('C') as MethodDeclaration;
+  }
+}
diff --git a/pkg/analyzer/test/generated/collection_literal_parser_test.dart b/pkg/analyzer/test/generated/collection_literal_parser_test.dart
new file mode 100644
index 0000000..76e1dc8
--- /dev/null
+++ b/pkg/analyzer/test/generated/collection_literal_parser_test.dart
@@ -0,0 +1,649 @@
+// 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'parser_test_base.dart';
+import 'test_support.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CollectionLiteralParserTest);
+  });
+}
+
+@reflectiveTest
+class CollectionLiteralParserTest extends FastaParserTestCase {
+  Expression parseCollectionLiteral(String source,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      int expectedEndOffset,
+      bool inAsync = false}) {
+    return parseExpression(source,
+        codes: codes,
+        errors: errors,
+        expectedEndOffset: expectedEndOffset,
+        inAsync: inAsync,
+        featureSet: FeatureSet.forTesting(
+            sdkVersion: '2.0.0',
+            additionalFeatures: [
+              Feature.spread_collections,
+              Feature.control_flow_collections
+            ]));
+  }
+
+  void test_listLiteral_for() {
+    var list = parseCollectionLiteral(
+      '[1, await for (var x in list) 2]',
+      inAsync: true,
+    ) as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as ForElement;
+    expect(second.awaitKeyword, isNotNull);
+    expect(second.forKeyword.isKeyword, isTrue);
+    expect(second.leftParenthesis.lexeme, '(');
+    expect(second.rightParenthesis.lexeme, ')');
+    var forLoopParts = second.forLoopParts as ForEachPartsWithDeclaration;
+    DeclaredIdentifier forLoopVar = forLoopParts.loopVariable;
+    expect(forLoopVar.identifier.name, 'x');
+    expect(forLoopParts.inKeyword, isNotNull);
+    var iterable = forLoopParts.iterable as SimpleIdentifier;
+    expect(iterable.name, 'list');
+  }
+
+  void test_listLiteral_forIf() {
+    var list = parseCollectionLiteral(
+      '[1, await for (var x in list) if (c) 2]',
+      inAsync: true,
+    ) as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as ForElement;
+    expect(second.awaitKeyword, isNotNull);
+    expect(second.forKeyword.isKeyword, isTrue);
+    expect(second.leftParenthesis.lexeme, '(');
+    expect(second.rightParenthesis.lexeme, ')');
+    var forLoopParts = second.forLoopParts as ForEachPartsWithDeclaration;
+    DeclaredIdentifier forLoopVar = forLoopParts.loopVariable;
+    expect(forLoopVar.identifier.name, 'x');
+    expect(forLoopParts.inKeyword, isNotNull);
+    var iterable = forLoopParts.iterable as SimpleIdentifier;
+    expect(iterable.name, 'list');
+
+    var body = second.body as IfElement;
+    var condition = body.condition as SimpleIdentifier;
+    expect(condition.name, 'c');
+    var thenElement = body.thenElement as IntegerLiteral;
+    expect(thenElement.value, 2);
+  }
+
+  void test_listLiteral_forSpread() {
+    var list =
+        parseCollectionLiteral('[1, for (int x = 0; x < 10; ++x) ...[2]]')
+            as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as ForElement;
+    expect(second.awaitKeyword, isNull);
+    expect(second.forKeyword.isKeyword, isTrue);
+    expect(second.leftParenthesis.lexeme, '(');
+    expect(second.rightParenthesis.lexeme, ')');
+    var forLoopParts = second.forLoopParts as ForPartsWithDeclarations;
+    VariableDeclaration forLoopVar = forLoopParts.variables.variables[0];
+    expect(forLoopVar.name.name, 'x');
+    var condition = forLoopParts.condition as BinaryExpression;
+    var rightOperand = condition.rightOperand as IntegerLiteral;
+    expect(rightOperand.value, 10);
+    var updater = forLoopParts.updaters[0] as PrefixExpression;
+    var updaterOperand = updater.operand as SimpleIdentifier;
+    expect(updaterOperand.name, 'x');
+  }
+
+  void test_listLiteral_if() {
+    var list = parseCollectionLiteral('[1, if (true) 2]') as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as IntegerLiteral;
+    expect(thenElement.value, 2);
+    expect(second.elseElement, isNull);
+  }
+
+  void test_listLiteral_ifElse() {
+    var list = parseCollectionLiteral('[1, if (true) 2 else 5]') as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as IntegerLiteral;
+    expect(thenElement.value, 2);
+    var elseElement = second.elseElement as IntegerLiteral;
+    expect(elseElement.value, 5);
+  }
+
+  void test_listLiteral_ifElseFor() {
+    var list = parseCollectionLiteral('[1, if (true) 2 else for (a in b) 5]')
+        as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as IntegerLiteral;
+    expect(thenElement.value, 2);
+
+    var elseElement = second.elseElement as ForElement;
+    var forLoopParts = elseElement.forLoopParts as ForEachPartsWithIdentifier;
+    expect(forLoopParts.identifier.name, 'a');
+
+    var forValue = elseElement.body as IntegerLiteral;
+    expect(forValue.value, 5);
+  }
+
+  void test_listLiteral_ifElseSpread() {
+    var list = parseCollectionLiteral('[1, if (true) ...[2] else ...?[5]]')
+        as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as SpreadElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    var elseElement = second.elseElement as SpreadElement;
+    expect(elseElement.spreadOperator.lexeme, '...?');
+  }
+
+  void test_listLiteral_ifFor() {
+    var list =
+        parseCollectionLiteral('[1, if (true) for (a in b) 2]') as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+
+    var thenElement = second.thenElement as ForElement;
+    var forLoopParts = thenElement.forLoopParts as ForEachPartsWithIdentifier;
+    expect(forLoopParts.identifier.name, 'a');
+
+    var forValue = thenElement.body as IntegerLiteral;
+    expect(forValue.value, 2);
+    expect(second.elseElement, isNull);
+  }
+
+  void test_listLiteral_ifSpread() {
+    var list = parseCollectionLiteral('[1, if (true) ...[2]]') as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = list.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as SpreadElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    expect(second.elseElement, isNull);
+  }
+
+  void test_listLiteral_spread() {
+    var list = parseCollectionLiteral('[1, ...[2]]') as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var element = list.elements[1] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...');
+    var spreadExpression = element.expression as ListLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_listLiteral_spreadQ() {
+    var list = parseCollectionLiteral('[1, ...?[2]]') as ListLiteral;
+    expect(list.elements, hasLength(2));
+    var first = list.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var element = list.elements[1] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...?');
+    var spreadExpression = element.expression as ListLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_mapLiteral_for() {
+    var map = parseCollectionLiteral('{1:7, await for (y in list) 2:3}',
+        inAsync: true) as SetOrMapLiteral;
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 7);
+
+    var second = map.elements[1] as ForElement;
+    expect(second.awaitKeyword, isNotNull);
+    expect(second.forKeyword.isKeyword, isTrue);
+    expect(second.leftParenthesis.lexeme, '(');
+    expect(second.rightParenthesis.lexeme, ')');
+    var forLoopParts = second.forLoopParts as ForEachPartsWithIdentifier;
+    SimpleIdentifier forLoopVar = forLoopParts.identifier;
+    expect(forLoopVar.name, 'y');
+    expect(forLoopParts.inKeyword, isNotNull);
+    var iterable = forLoopParts.iterable as SimpleIdentifier;
+    expect(iterable.name, 'list');
+  }
+
+  void test_mapLiteral_forIf() {
+    var map = parseCollectionLiteral('{1:7, await for (y in list) if (c) 2:3}',
+        inAsync: true) as SetOrMapLiteral;
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 7);
+
+    var second = map.elements[1] as ForElement;
+    expect(second.awaitKeyword, isNotNull);
+    expect(second.forKeyword.isKeyword, isTrue);
+    expect(second.leftParenthesis.lexeme, '(');
+    expect(second.rightParenthesis.lexeme, ')');
+    var forLoopParts = second.forLoopParts as ForEachPartsWithIdentifier;
+    SimpleIdentifier forLoopVar = forLoopParts.identifier;
+    expect(forLoopVar.name, 'y');
+    expect(forLoopParts.inKeyword, isNotNull);
+    var iterable = forLoopParts.iterable as SimpleIdentifier;
+    expect(iterable.name, 'list');
+
+    var body = second.body as IfElement;
+    var condition = body.condition as SimpleIdentifier;
+    expect(condition.name, 'c');
+    var thenElement = body.thenElement as MapLiteralEntry;
+    var thenValue = thenElement.value as IntegerLiteral;
+    expect(thenValue.value, 3);
+  }
+
+  void test_mapLiteral_forSpread() {
+    var map = parseCollectionLiteral('{1:7, for (x = 0; x < 10; ++x) ...{2:3}}')
+        as SetOrMapLiteral;
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 7);
+
+    var second = map.elements[1] as ForElement;
+    expect(second.awaitKeyword, isNull);
+    expect(second.forKeyword.isKeyword, isTrue);
+    expect(second.leftParenthesis.lexeme, '(');
+    expect(second.rightParenthesis.lexeme, ')');
+    var forLoopParts = second.forLoopParts as ForPartsWithExpression;
+    var forLoopInit = forLoopParts.initialization as AssignmentExpression;
+    var forLoopVar = forLoopInit.leftHandSide as SimpleIdentifier;
+    expect(forLoopVar.name, 'x');
+    var condition = forLoopParts.condition as BinaryExpression;
+    var rightOperand = condition.rightOperand as IntegerLiteral;
+    expect(rightOperand.value, 10);
+    var updater = forLoopParts.updaters[0] as PrefixExpression;
+    var updaterOperand = updater.operand as SimpleIdentifier;
+    expect(updaterOperand.name, 'x');
+  }
+
+  void test_mapLiteral_if() {
+    var map = parseCollectionLiteral('{1:1, if (true) 2:4}') as SetOrMapLiteral;
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 1);
+
+    var second = map.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as MapLiteralEntry;
+    var thenElementValue = thenElement.value as IntegerLiteral;
+    expect(thenElementValue.value, 4);
+    expect(second.elseElement, isNull);
+  }
+
+  void test_mapLiteral_ifElse() {
+    var map = parseCollectionLiteral('{1:1, if (true) 2:4 else 5:6}')
+        as SetOrMapLiteral;
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 1);
+
+    var second = map.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as MapLiteralEntry;
+    var thenElementValue = thenElement.value as IntegerLiteral;
+    expect(thenElementValue.value, 4);
+    var elseElement = second.elseElement as MapLiteralEntry;
+    var elseElementValue = elseElement.value as IntegerLiteral;
+    expect(elseElementValue.value, 6);
+  }
+
+  void test_mapLiteral_ifElseFor() {
+    var map =
+        parseCollectionLiteral('{1:1, if (true) 2:4 else for (c in d) 5:6}')
+            as SetOrMapLiteral;
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 1);
+
+    var second = map.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as MapLiteralEntry;
+    var thenElementValue = thenElement.value as IntegerLiteral;
+    expect(thenElementValue.value, 4);
+
+    var elseElement = second.elseElement as ForElement;
+    var forLoopParts = elseElement.forLoopParts as ForEachPartsWithIdentifier;
+    expect(forLoopParts.identifier.name, 'c');
+
+    var body = elseElement.body as MapLiteralEntry;
+    var bodyValue = body.value as IntegerLiteral;
+    expect(bodyValue.value, 6);
+  }
+
+  void test_mapLiteral_ifElseSpread() {
+    var map = parseCollectionLiteral('{1:7, if (true) ...{2:4} else ...?{5:6}}')
+        as SetOrMapLiteral;
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 7);
+
+    var second = map.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as SpreadElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    var elseElement = second.elseElement as SpreadElement;
+    expect(elseElement.spreadOperator.lexeme, '...?');
+    var elseElementExpression = elseElement.expression as SetOrMapLiteral;
+    expect(elseElementExpression.elements, hasLength(1));
+    var entry = elseElementExpression.elements[0] as MapLiteralEntry;
+    var entryValue = entry.value as IntegerLiteral;
+    expect(entryValue.value, 6);
+  }
+
+  void test_mapLiteral_ifFor() {
+    var map = parseCollectionLiteral('{1:1, if (true) for (a in b) 2:4}')
+        as SetOrMapLiteral;
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 1);
+
+    var second = map.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+
+    var thenElement = second.thenElement as ForElement;
+    var forLoopParts = thenElement.forLoopParts as ForEachPartsWithIdentifier;
+    expect(forLoopParts.identifier.name, 'a');
+
+    var body = thenElement.body as MapLiteralEntry;
+    var thenElementValue = body.value as IntegerLiteral;
+    expect(thenElementValue.value, 4);
+    expect(second.elseElement, isNull);
+  }
+
+  void test_mapLiteral_ifSpread() {
+    SetOrMapLiteral map = parseCollectionLiteral('{1:1, if (true) ...{2:4}}');
+    expect(map.elements, hasLength(2));
+    var first = map.elements[0] as MapLiteralEntry;
+    var firstValue = first.value as IntegerLiteral;
+    expect(firstValue.value, 1);
+
+    var second = map.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as SpreadElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    expect(second.elseElement, isNull);
+  }
+
+  void test_mapLiteral_spread() {
+    var map = parseCollectionLiteral('{1: 2, ...{3: 4}}') as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments, isNull);
+    expect(map.elements, hasLength(2));
+
+    var element = map.elements[1] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...');
+    var spreadExpression = element.expression as SetOrMapLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_mapLiteral_spread2_typed() {
+    var map = parseCollectionLiteral('<int, int>{1: 2, ...{3: 4}}')
+        as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments.arguments, hasLength(2));
+    expect(map.elements, hasLength(2));
+
+    var element = map.elements[1] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...');
+    var spreadExpression = element.expression as SetOrMapLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_mapLiteral_spread_typed() {
+    var map =
+        parseCollectionLiteral('<int, int>{...{3: 4}}') as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments.arguments, hasLength(2));
+    expect(map.elements, hasLength(1));
+
+    var element = map.elements[0] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...');
+    var spreadExpression = element.expression as SetOrMapLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_mapLiteral_spreadQ() {
+    var map = parseCollectionLiteral('{1: 2, ...?{3: 4}}') as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments, isNull);
+    expect(map.elements, hasLength(2));
+
+    var element = map.elements[1] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...?');
+    var spreadExpression = element.expression as SetOrMapLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_mapLiteral_spreadQ2_typed() {
+    var map = parseCollectionLiteral('<int, int>{1: 2, ...?{3: 4}}')
+        as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments.arguments, hasLength(2));
+    expect(map.elements, hasLength(2));
+
+    var element = map.elements[1] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...?');
+    var spreadExpression = element.expression as SetOrMapLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_mapLiteral_spreadQ_typed() {
+    var map =
+        parseCollectionLiteral('<int, int>{...?{3: 4}}') as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments.arguments, hasLength(2));
+    expect(map.elements, hasLength(1));
+
+    var element = map.elements[0] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...?');
+    var spreadExpression = element.expression as SetOrMapLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_setLiteral_if() {
+    var setLiteral =
+        parseCollectionLiteral('{1, if (true) 2}') as SetOrMapLiteral;
+    expect(setLiteral.elements, hasLength(2));
+    var first = setLiteral.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = setLiteral.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as IntegerLiteral;
+    expect(thenElement.value, 2);
+    expect(second.elseElement, isNull);
+  }
+
+  void test_setLiteral_ifElse() {
+    var setLiteral =
+        parseCollectionLiteral('{1, if (true) 2 else 5}') as SetOrMapLiteral;
+    expect(setLiteral.elements, hasLength(2));
+    var first = setLiteral.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = setLiteral.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as IntegerLiteral;
+    expect(thenElement.value, 2);
+    var elseElement = second.elseElement as IntegerLiteral;
+    expect(elseElement.value, 5);
+  }
+
+  void test_setLiteral_ifElseSpread() {
+    var setLiteral =
+        parseCollectionLiteral('{1, if (true) ...{2} else ...?[5]}')
+            as SetOrMapLiteral;
+    expect(setLiteral.elements, hasLength(2));
+    var first = setLiteral.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = setLiteral.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as SpreadElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    var theExpression = thenElement.expression as SetOrMapLiteral;
+    expect(theExpression.elements, hasLength(1));
+    var elseElement = second.elseElement as SpreadElement;
+    expect(elseElement.spreadOperator.lexeme, '...?');
+    var elseExpression = elseElement.expression as ListLiteral;
+    expect(elseExpression.elements, hasLength(1));
+  }
+
+  void test_setLiteral_ifSpread() {
+    var setLiteral =
+        parseCollectionLiteral('{1, if (true) ...[2]}') as SetOrMapLiteral;
+    expect(setLiteral.elements, hasLength(2));
+    var first = setLiteral.elements[0] as IntegerLiteral;
+    expect(first.value, 1);
+
+    var second = setLiteral.elements[1] as IfElement;
+    var condition = second.condition as BooleanLiteral;
+    expect(condition.value, isTrue);
+    var thenElement = second.thenElement as SpreadElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    expect(second.elseElement, isNull);
+  }
+
+  void test_setLiteral_spread2() {
+    var set = parseCollectionLiteral('{3, ...[4]}') as SetOrMapLiteral;
+    expect(set.constKeyword, isNull);
+    expect(set.typeArguments, isNull);
+    expect(set.elements, hasLength(2));
+    var value = set.elements[0] as IntegerLiteral;
+    expect(value.value, 3);
+
+    var element = set.elements[1] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...');
+    var spreadExpression = element.expression as ListLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_setLiteral_spread2Q() {
+    var set = parseCollectionLiteral('{3, ...?[4]}') as SetOrMapLiteral;
+    expect(set.constKeyword, isNull);
+    expect(set.typeArguments, isNull);
+    expect(set.elements, hasLength(2));
+    var value = set.elements[0] as IntegerLiteral;
+    expect(value.value, 3);
+
+    var element = set.elements[1] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...?');
+    var spreadExpression = element.expression as ListLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_setLiteral_spread_typed() {
+    var set = parseCollectionLiteral('<int>{...[3]}') as SetOrMapLiteral;
+    expect(set.constKeyword, isNull);
+    expect(set.typeArguments, isNotNull);
+    expect(set.elements, hasLength(1));
+
+    var element = set.elements[0] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...');
+    var spreadExpression = element.expression as ListLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_setLiteral_spreadQ_typed() {
+    var set = parseCollectionLiteral('<int>{...?[3]}') as SetOrMapLiteral;
+    expect(set.constKeyword, isNull);
+    expect(set.typeArguments, isNotNull);
+    expect(set.elements, hasLength(1));
+
+    var element = set.elements[0] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...?');
+    var spreadExpression = element.expression as ListLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_setOrMapLiteral_spread() {
+    var map = parseCollectionLiteral('{...{3: 4}}') as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments, isNull);
+    expect(map.elements, hasLength(1));
+
+    var element = map.elements[0] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...');
+    var spreadExpression = element.expression as SetOrMapLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+
+  void test_setOrMapLiteral_spreadQ() {
+    var map = parseCollectionLiteral('{...?{3: 4}}') as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments, isNull);
+    expect(map.elements, hasLength(1));
+
+    var element = map.elements[0] as SpreadElement;
+    expect(element.spreadOperator.lexeme, '...?');
+    var spreadExpression = element.expression as SetOrMapLiteral;
+    expect(spreadExpression.elements, hasLength(1));
+  }
+}
diff --git a/pkg/analyzer/test/generated/complex_parser_test.dart b/pkg/analyzer/test/generated/complex_parser_test.dart
new file mode 100644
index 0000000..67ae21b
--- /dev/null
+++ b/pkg/analyzer/test/generated/complex_parser_test.dart
@@ -0,0 +1,573 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ComplexParserTest);
+  });
+}
+
+/// The class `ComplexParserTest` defines parser tests that test the parsing of
+/// more complex code fragments or the interactions between multiple parsing
+/// methods. For example, tests to ensure that the precedence of operations is
+/// being handled correctly should be defined in this class.
+///
+/// Simpler tests should be defined in the class [SimpleParserTest].
+@reflectiveTest
+class ComplexParserTest extends FastaParserTestCase {
+  void test_additiveExpression_normal() {
+    BinaryExpression expression = parseExpression("x + y - z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_additiveExpression_noSpaces() {
+    BinaryExpression expression = parseExpression("i+1");
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.rightOperand, isIntegerLiteral);
+  }
+
+  void test_additiveExpression_precedence_multiplicative_left() {
+    BinaryExpression expression = parseExpression("x * y + z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_additiveExpression_precedence_multiplicative_left_withSuper() {
+    BinaryExpression expression = parseExpression("super * y - z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_additiveExpression_precedence_multiplicative_right() {
+    BinaryExpression expression = parseExpression("x + y * z");
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_additiveExpression_super() {
+    BinaryExpression expression = parseExpression("super + y - z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_assignableExpression_arguments_normal_chain() {
+    PropertyAccess propertyAccess1 = parseExpression("a(b)(c).d(e).f");
+    expect(propertyAccess1.propertyName.name, "f");
+    //
+    // a(b)(c).d(e)
+    //
+    MethodInvocation invocation2 = propertyAccess1.target;
+    expect(invocation2.methodName.name, "d");
+    expect(invocation2.typeArguments, isNull);
+    ArgumentList argumentList2 = invocation2.argumentList;
+    expect(argumentList2, isNotNull);
+    expect(argumentList2.arguments, hasLength(1));
+    //
+    // a(b)(c)
+    //
+    FunctionExpressionInvocation invocation3 = invocation2.target;
+    expect(invocation3.typeArguments, isNull);
+    ArgumentList argumentList3 = invocation3.argumentList;
+    expect(argumentList3, isNotNull);
+    expect(argumentList3.arguments, hasLength(1));
+    //
+    // a(b)
+    //
+    MethodInvocation invocation4 = invocation3.function;
+    expect(invocation4.methodName.name, "a");
+    expect(invocation4.typeArguments, isNull);
+    ArgumentList argumentList4 = invocation4.argumentList;
+    expect(argumentList4, isNotNull);
+    expect(argumentList4.arguments, hasLength(1));
+  }
+
+  void test_assignableExpression_arguments_normal_chain_typeArguments() {
+    _validate_assignableExpression_arguments_normal_chain_typeArguments(
+        "a<E>(b)<F>(c).d<G>(e).f");
+  }
+
+  void test_assignmentExpression_compound() {
+    AssignmentExpression expression = parseExpression("x = y = 0");
+    expect(expression.leftHandSide, isSimpleIdentifier);
+    expect(expression.rightHandSide, isAssignmentExpression);
+  }
+
+  void test_assignmentExpression_indexExpression() {
+    AssignmentExpression expression = parseExpression("x[1] = 0");
+    expect(expression.leftHandSide, isIndexExpression);
+    expect(expression.rightHandSide, isIntegerLiteral);
+  }
+
+  void test_assignmentExpression_prefixedIdentifier() {
+    AssignmentExpression expression = parseExpression("x.y = 0");
+    expect(expression.leftHandSide, isPrefixedIdentifier);
+    expect(expression.rightHandSide, isIntegerLiteral);
+  }
+
+  void test_assignmentExpression_propertyAccess() {
+    AssignmentExpression expression = parseExpression("super.y = 0");
+    expect(expression.leftHandSide, isPropertyAccess);
+    expect(expression.rightHandSide, isIntegerLiteral);
+  }
+
+  void test_binary_operator_written_out_expression() {
+    var expression = parseExpression('x xor y', errors: [
+      expectedError(ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT, 2, 3),
+    ]) as BinaryExpression;
+    var lhs = expression.leftOperand as SimpleIdentifier;
+    expect(lhs.name, 'x');
+    expect(expression.operator.lexeme, '^');
+    var rhs = expression.rightOperand as SimpleIdentifier;
+    expect(rhs.name, 'y');
+  }
+
+  void test_bitwiseAndExpression_normal() {
+    BinaryExpression expression = parseExpression("x & y & z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseAndExpression_precedence_equality_left() {
+    BinaryExpression expression = parseExpression("x == y && z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseAndExpression_precedence_equality_right() {
+    BinaryExpression expression = parseExpression("x && y == z");
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseAndExpression_super() {
+    BinaryExpression expression = parseExpression("super & y & z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseOrExpression_normal() {
+    BinaryExpression expression = parseExpression("x | y | z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseOrExpression_precedence_xor_left() {
+    BinaryExpression expression = parseExpression("x ^ y | z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseOrExpression_precedence_xor_right() {
+    BinaryExpression expression = parseExpression("x | y ^ z");
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseOrExpression_super() {
+    BinaryExpression expression = parseExpression("super | y | z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseXorExpression_normal() {
+    BinaryExpression expression = parseExpression("x ^ y ^ z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseXorExpression_precedence_and_left() {
+    BinaryExpression expression = parseExpression("x & y ^ z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseXorExpression_precedence_and_right() {
+    BinaryExpression expression = parseExpression("x ^ y & z");
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseXorExpression_super() {
+    BinaryExpression expression = parseExpression("super ^ y ^ z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_cascade_withAssignment() {
+    CascadeExpression cascade =
+        parseExpression("new Map()..[3] = 4 ..[0] = 11");
+    Expression target = cascade.target;
+    for (Expression section in cascade.cascadeSections) {
+      expect(section, isAssignmentExpression);
+      Expression lhs = (section as AssignmentExpression).leftHandSide;
+      expect(lhs, isIndexExpression);
+      IndexExpression index = lhs as IndexExpression;
+      expect(index.isCascaded, isTrue);
+      expect(index.realTarget, same(target));
+    }
+  }
+
+  void test_conditionalExpression_precedence_ifNullExpression() {
+    ConditionalExpression expression = parseExpression('a ?? b ? y : z');
+    expect(expression.condition, isBinaryExpression);
+  }
+
+  void test_conditionalExpression_precedence_logicalOrExpression() {
+    ConditionalExpression expression = parseExpression("a | b ? y : z");
+    expect(expression.condition, isBinaryExpression);
+  }
+
+  void test_conditionalExpression_precedence_nullableType_as() {
+    ExpressionStatement statement = parseStatement('x as bool ? (x + y) : z;');
+    ConditionalExpression expression = statement.expression;
+    Expression condition = expression.condition;
+    expect(condition, isAsExpression);
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+  }
+
+  void test_conditionalExpression_precedence_nullableType_as2() {
+    var statement =
+        parseStatement('x as bool? ? (x + y) : z;') as ExpressionStatement;
+    var expression = statement.expression as ConditionalExpression;
+    var asExpression = expression.condition as AsExpression;
+    var type = asExpression.type as TypeName;
+    expect(type.question.lexeme, '?');
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+    assertNoErrors();
+  }
+
+  void test_conditionalExpression_precedence_nullableType_as3() {
+    var statement =
+        parseStatement('(x as bool?) ? (x + y) : z;') as ExpressionStatement;
+    var expression = statement.expression as ConditionalExpression;
+    var condition = expression.condition as ParenthesizedExpression;
+    var asExpression = condition.expression as AsExpression;
+    var type = asExpression.type as TypeName;
+    expect(type.question.lexeme, '?');
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+    assertNoErrors();
+  }
+
+  void test_conditionalExpression_precedence_nullableType_is() {
+    ExpressionStatement statement =
+        parseStatement('x is String ? (x + y) : z;');
+    ConditionalExpression expression = statement.expression;
+    Expression condition = expression.condition;
+    expect(condition, isIsExpression);
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+  }
+
+  void test_conditionalExpression_precedence_nullableType_is2() {
+    var statement =
+        parseStatement('x is String? ? (x + y) : z;') as ExpressionStatement;
+    var expression = statement.expression as ConditionalExpression;
+    var isExpression = expression.condition as IsExpression;
+    var type = isExpression.type as TypeName;
+    expect(type.question.lexeme, '?');
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+    assertNoErrors();
+  }
+
+  void test_conditionalExpression_precedence_nullableType_is3() {
+    var statement =
+        parseStatement('(x is String?) ? (x + y) : z;') as ExpressionStatement;
+    var expression = statement.expression as ConditionalExpression;
+    var condition = expression.condition as ParenthesizedExpression;
+    var isExpression = condition.expression as IsExpression;
+    var type = isExpression.type as TypeName;
+    expect(type.question.lexeme, '?');
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+    assertNoErrors();
+  }
+
+  void test_conditionalExpression_precedence_nullableTypeWithTypeArg1_is() {
+    ExpressionStatement statement =
+        parseStatement('x is String<S> ? (x + y) : z;');
+    ConditionalExpression expression = statement.expression;
+    Expression condition = expression.condition;
+    expect(condition, TypeMatcher<IsExpression>());
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, TypeMatcher<ParenthesizedExpression>());
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, TypeMatcher<SimpleIdentifier>());
+  }
+
+  void test_conditionalExpression_precedence_nullableTypeWithTypeArg1GFT_is() {
+    ExpressionStatement statement =
+        parseStatement('x is String<S> Function() ? (x + y) : z;');
+    ConditionalExpression expression = statement.expression;
+    Expression condition = expression.condition;
+    expect(condition, TypeMatcher<IsExpression>());
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, TypeMatcher<ParenthesizedExpression>());
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, TypeMatcher<SimpleIdentifier>());
+  }
+
+  void test_conditionalExpression_precedence_nullableTypeWithTypeArg2_is() {
+    ExpressionStatement statement =
+        parseStatement('x is String<S,T> ? (x + y) : z;');
+    ConditionalExpression expression = statement.expression;
+    Expression condition = expression.condition;
+    expect(condition, TypeMatcher<IsExpression>());
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, TypeMatcher<ParenthesizedExpression>());
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, TypeMatcher<SimpleIdentifier>());
+  }
+
+  void test_conditionalExpression_precedence_prefixedNullableType_is() {
+    ExpressionStatement statement = parseStatement('x is p.A ? (x + y) : z;');
+    ConditionalExpression expression = statement.expression;
+
+    Expression condition = expression.condition;
+    expect(condition, TypeMatcher<IsExpression>());
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, TypeMatcher<ParenthesizedExpression>());
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, TypeMatcher<SimpleIdentifier>());
+  }
+
+  void test_conditionalExpression_precedence_withAssignment() {
+    ExpressionStatement statement = parseStatement('b ? c = true : g();');
+    ConditionalExpression expression = statement.expression;
+    expect(expression.condition, TypeMatcher<SimpleIdentifier>());
+    expect(expression.thenExpression, TypeMatcher<AssignmentExpression>());
+  }
+
+  void test_conditionalExpression_precedence_withAssignment2() {
+    ExpressionStatement statement = parseStatement('b.x ? c = true : g();');
+    ConditionalExpression expression = statement.expression;
+    expect(expression.condition, TypeMatcher<PrefixedIdentifier>());
+    expect(expression.thenExpression, TypeMatcher<AssignmentExpression>());
+  }
+
+  void test_conditionalExpression_prefixedValue() {
+    ExpressionStatement statement = parseStatement('a.b ? y : z;');
+    ConditionalExpression expression = statement.expression;
+    expect(expression.condition, TypeMatcher<PrefixedIdentifier>());
+    expect(expression.thenExpression, TypeMatcher<SimpleIdentifier>());
+  }
+
+  void test_conditionalExpression_prefixedValue2() {
+    ExpressionStatement statement = parseStatement('a.b ? x.y : z;');
+    ConditionalExpression expression = statement.expression;
+    expect(expression.condition, TypeMatcher<PrefixedIdentifier>());
+    expect(expression.thenExpression, TypeMatcher<PrefixedIdentifier>());
+  }
+
+  void test_constructor_initializer_withParenthesizedExpression() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  C() :
+    this.a = (b == null ? c : d) {
+  }
+}''');
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+  }
+
+  void test_equalityExpression_normal() {
+    BinaryExpression expression = parseExpression("x == y != z",
+        codes: [ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_equalityExpression_precedence_relational_left() {
+    BinaryExpression expression = parseExpression("x is y == z");
+    expect(expression.leftOperand, isIsExpression);
+  }
+
+  void test_equalityExpression_precedence_relational_right() {
+    BinaryExpression expression = parseExpression("x == y is z");
+    expect(expression.rightOperand, isIsExpression);
+  }
+
+  void test_equalityExpression_super() {
+    BinaryExpression expression = parseExpression("super == y != z",
+        codes: [ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_ifNullExpression() {
+    BinaryExpression expression = parseExpression('x ?? y ?? z');
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_ifNullExpression_precedence_logicalOr_left() {
+    BinaryExpression expression = parseExpression('x || y ?? z');
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_ifNullExpression_precedence_logicalOr_right() {
+    BinaryExpression expression = parseExpression('x ?? y || z');
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_logicalAndExpression() {
+    BinaryExpression expression = parseExpression("x && y && z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_logicalAndExpression_precedence_bitwiseOr_left() {
+    BinaryExpression expression = parseExpression("x | y < z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_logicalAndExpression_precedence_bitwiseOr_right() {
+    BinaryExpression expression = parseExpression("x < y | z");
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_logicalAndExpressionStatement() {
+    // Assert that `<` and `>` are not interpreted as type arguments.
+    ExpressionStatement statement = parseStatement("C<T && T>U;");
+    BinaryExpression expression = statement.expression;
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_logicalOrExpression() {
+    BinaryExpression expression = parseExpression("x || y || z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_logicalOrExpression_precedence_logicalAnd_left() {
+    BinaryExpression expression = parseExpression("x && y || z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_logicalOrExpression_precedence_logicalAnd_right() {
+    BinaryExpression expression = parseExpression("x || y && z");
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_methodInvocation1() {
+    // Assert that `<` and `>` are not interpreted as type arguments.
+    ExpressionStatement statement = parseStatement("f(a < b, c > 3);");
+    assertNoErrors();
+    MethodInvocation method = statement.expression;
+    expect(method.argumentList.arguments, hasLength(2));
+  }
+
+  void test_methodInvocation2() {
+    // Assert that `<` and `>` are not interpreted as type arguments.
+    ExpressionStatement statement = parseStatement("f(a < b, c >> 3);");
+    assertNoErrors();
+    MethodInvocation method = statement.expression;
+    expect(method.argumentList.arguments, hasLength(2));
+  }
+
+  void test_methodInvocation3() {
+    // Assert that `<` and `>` are not interpreted as type arguments.
+    ExpressionStatement statement = parseStatement("f(a < b, c < d >> 3);");
+    assertNoErrors();
+    MethodInvocation method = statement.expression;
+    expect(method.argumentList.arguments, hasLength(2));
+  }
+
+  void test_multipleLabels_statement() {
+    LabeledStatement statement = parseStatement("a: b: c: return x;");
+    expect(statement.labels, hasLength(3));
+    expect(statement.statement, isReturnStatement);
+  }
+
+  void test_multiplicativeExpression_normal() {
+    BinaryExpression expression = parseExpression("x * y / z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_multiplicativeExpression_precedence_unary_left() {
+    BinaryExpression expression = parseExpression("-x * y");
+    expect(expression.leftOperand, isPrefixExpression);
+  }
+
+  void test_multiplicativeExpression_precedence_unary_right() {
+    BinaryExpression expression = parseExpression("x * -y");
+    expect(expression.rightOperand, isPrefixExpression);
+  }
+
+  void test_multiplicativeExpression_super() {
+    BinaryExpression expression = parseExpression("super * y / z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_relationalExpression_precedence_shift_right() {
+    IsExpression expression = parseExpression("x << y is z");
+    expect(expression.expression, isBinaryExpression);
+  }
+
+  void test_shiftExpression_normal() {
+    BinaryExpression expression = parseExpression("x >> 4 << 3");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_shiftExpression_precedence_additive_left() {
+    BinaryExpression expression = parseExpression("x + y << z");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_shiftExpression_precedence_additive_right() {
+    BinaryExpression expression = parseExpression("x << y + z");
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_shiftExpression_super() {
+    BinaryExpression expression = parseExpression("super >> 4 << 3");
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_topLevelFunction_nestedGenericFunction() {
+    parseCompilationUnit('''
+void f() {
+  void g<T>() {
+  }
+}
+''');
+  }
+
+  void _validate_assignableExpression_arguments_normal_chain_typeArguments(
+      String code,
+      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
+    PropertyAccess propertyAccess1 = parseExpression(code, codes: errorCodes);
+    expect(propertyAccess1.propertyName.name, "f");
+    //
+    // a<E>(b)<F>(c).d<G>(e)
+    //
+    MethodInvocation invocation2 = propertyAccess1.target;
+    expect(invocation2.methodName.name, "d");
+    expect(invocation2.typeArguments, isNotNull);
+    ArgumentList argumentList2 = invocation2.argumentList;
+    expect(argumentList2, isNotNull);
+    expect(argumentList2.arguments, hasLength(1));
+    //
+    // a<E>(b)<F>(c)
+    //
+    FunctionExpressionInvocation invocation3 = invocation2.target;
+    expect(invocation3.typeArguments, isNotNull);
+    ArgumentList argumentList3 = invocation3.argumentList;
+    expect(argumentList3, isNotNull);
+    expect(argumentList3.arguments, hasLength(1));
+    //
+    // a(b)
+    //
+    MethodInvocation invocation4 = invocation3.function;
+    expect(invocation4.methodName.name, "a");
+    expect(invocation4.typeArguments, isNotNull);
+    ArgumentList argumentList4 = invocation4.argumentList;
+    expect(argumentList4, isNotNull);
+    expect(argumentList4.arguments, hasLength(1));
+  }
+}
diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart
index c139b6e..becf671 100644
--- a/pkg/analyzer/test/generated/elements_types_mixin.dart
+++ b/pkg/analyzer/test/generated/elements_types_mixin.dart
@@ -296,7 +296,7 @@
     ) as InterfaceTypeImpl;
   }
 
-  DartType futureType(DartType T) {
+  InterfaceType futureType(DartType T) {
     var futureElement = typeProvider.futureElement;
     return interfaceTypeStar(futureElement, typeArguments: [T]);
   }
@@ -378,8 +378,8 @@
   LibraryElementImpl library_({
     @required String uriStr,
     @required TypeSystemImpl typeSystem,
-    AnalysisContext analysisContext,
-    AnalysisSessionImpl analysisSession,
+    @required AnalysisContext analysisContext,
+    @required AnalysisSessionImpl analysisSession,
   }) {
     var library = LibraryElementImpl(
       analysisContext,
@@ -574,6 +574,17 @@
     return parameter;
   }
 
+  TypeAliasElementImpl typeAlias({
+    @required String name,
+    @required List<TypeParameterElement> typeParameters,
+    @required DartType aliasedType,
+  }) {
+    var element = TypeAliasElementImpl(name, 0);
+    element.typeParameters = typeParameters;
+    element.aliasedType = aliasedType;
+    return element;
+  }
+
   TypeParameterElementImpl typeParameter(String name,
       {DartType bound, Variance variance}) {
     var element = TypeParameterElementImpl.synthetic(name);
diff --git a/pkg/analyzer/test/generated/error_parser_test.dart b/pkg/analyzer/test/generated/error_parser_test.dart
new file mode 100644
index 0000000..73f8f5f
--- /dev/null
+++ b/pkg/analyzer/test/generated/error_parser_test.dart
@@ -0,0 +1,3068 @@
+// 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:_fe_analyzer_shared/src/scanner/errors.dart';
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ErrorParserTest);
+  });
+}
+
+/// This defines parser tests that test the parsing of code to ensure that
+/// errors are correctly reported, and in some cases, not reported.
+@reflectiveTest
+class ErrorParserTest extends FastaParserTestCase {
+  void test_abstractClassMember_constructor() {
+    createParser('abstract C.c();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 0, 8)]);
+  }
+
+  void test_abstractClassMember_field() {
+    createParser('abstract C f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_abstractClassMember_getter() {
+    createParser('abstract get m;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 0, 8)]);
+  }
+
+  void test_abstractClassMember_method() {
+    createParser('abstract m();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 0, 8)]);
+  }
+
+  void test_abstractClassMember_setter() {
+    createParser('abstract set m(v);');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 0, 8)]);
+  }
+
+  void test_abstractEnum() {
+    parseCompilationUnit("abstract enum E {ONE}",
+        errors: [expectedError(ParserErrorCode.ABSTRACT_ENUM, 0, 8)]);
+  }
+
+  void test_abstractTopLevelFunction_function() {
+    parseCompilationUnit("abstract f(v) {}", errors: [
+      expectedError(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, 0, 8)
+    ]);
+  }
+
+  void test_abstractTopLevelFunction_getter() {
+    parseCompilationUnit("abstract get m {}", errors: [
+      expectedError(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, 0, 8)
+    ]);
+  }
+
+  void test_abstractTopLevelFunction_setter() {
+    parseCompilationUnit("abstract set m(v) {}", errors: [
+      expectedError(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, 0, 8)
+    ]);
+  }
+
+  void test_abstractTopLevelVariable() {
+    parseCompilationUnit("abstract C f;", errors: [
+      expectedError(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE, 0, 8)
+    ]);
+  }
+
+  void test_abstractTypeDef() {
+    parseCompilationUnit("abstract typedef F();",
+        errors: [expectedError(ParserErrorCode.ABSTRACT_TYPEDEF, 0, 8)]);
+  }
+
+  void test_await_missing_async2_issue36048() {
+    parseCompilationUnit('''
+main() { // missing async
+  await foo.bar();
+}
+''', errors: [
+      expectedError(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 28, 5)
+    ]);
+  }
+
+  void test_await_missing_async3_issue36048() {
+    parseCompilationUnit('''
+main() { // missing async
+  (await foo);
+}
+''', errors: [
+      expectedError(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 29, 5)
+    ]);
+  }
+
+  void test_await_missing_async4_issue36048() {
+    parseCompilationUnit('''
+main() { // missing async
+  [await foo];
+}
+''', errors: [
+      expectedError(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 29, 5)
+    ]);
+  }
+
+  void test_await_missing_async_issue36048() {
+    parseCompilationUnit('''
+main() { // missing async
+  await foo();
+}
+''', errors: [
+      expectedError(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 28, 5)
+    ]);
+  }
+
+  void test_breakOutsideOfLoop_breakInDoStatement() {
+    DoStatement statement = parseStatement('do {break;} while (x);');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_breakOutsideOfLoop_breakInForStatement() {
+    Statement statement = parseStatement('for (; x;) {break;}');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_breakOutsideOfLoop_breakInIfStatement() {
+    IfStatement statement = parseStatement('if (x) {break;}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, 8, 5)]);
+  }
+
+  void test_breakOutsideOfLoop_breakInSwitchStatement() {
+    SwitchStatement statement = parseStatement('switch (x) {case 1: break;}');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_breakOutsideOfLoop_breakInWhileStatement() {
+    WhileStatement statement = parseStatement('while (x) {break;}');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_breakOutsideOfLoop_functionExpression_inALoop() {
+    parseStatement("for(; x;) {() {break;};}");
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, 15, 5)]);
+  }
+
+  void test_breakOutsideOfLoop_functionExpression_withALoop() {
+    parseStatement("() {for (; x;) {break;}};");
+  }
+
+  void test_classInClass_abstract() {
+    parseCompilationUnit("class C { abstract class B {} }", errors: [
+      expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 10, 8),
+      expectedError(ParserErrorCode.CLASS_IN_CLASS, 19, 5)
+    ]);
+  }
+
+  void test_classInClass_nonAbstract() {
+    parseCompilationUnit("class C { class B {} }",
+        errors: [expectedError(ParserErrorCode.CLASS_IN_CLASS, 10, 5)]);
+  }
+
+  void test_classTypeAlias_abstractAfterEq() {
+    // This syntax has been removed from the language in favor of
+    // "abstract class A = B with C;" (issue 18098).
+    createParser('class A = abstract B with C;', expectedEndOffset: 21);
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 8),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1)
+    ]);
+  }
+
+  void test_colonInPlaceOfIn() {
+    parseStatement("for (var x : list) {}");
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.COLON_IN_PLACE_OF_IN, 11, 1)]);
+  }
+
+  void test_constAndCovariant() {
+    createParser('covariant const C f = null;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 10, 5)]);
+  }
+
+  void test_constAndFinal() {
+    createParser('const final int x = null;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.CONST_AND_FINAL, 6, 5)]);
+  }
+
+  void test_constAndVar() {
+    createParser('const var x = null;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 6, 3)]);
+  }
+
+  void test_constClass() {
+    parseCompilationUnit("const class C {}",
+        errors: [expectedError(ParserErrorCode.CONST_CLASS, 0, 5)]);
+  }
+
+  void test_constConstructorWithBody() {
+    createParser('const C() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, 10, 1)]);
+  }
+
+  void test_constEnum() {
+    parseCompilationUnit("const enum E {ONE}", errors: [
+      // Fasta interprets the `const` as a malformed top level const
+      // and `enum` as the start of an enum declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
+    ]);
+  }
+
+  void test_constFactory() {
+    createParser('const factory C() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([expectedError(ParserErrorCode.CONST_FACTORY, 0, 5)]);
+  }
+
+  void test_constMethod() {
+    createParser('const int m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
+  }
+
+  void test_constMethod_noReturnType() {
+    createParser('const m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
+  }
+
+  void test_constMethod_noReturnType2() {
+    createParser('const m();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
+  }
+
+  void test_constructor_super_cascade_synthetic() {
+    // https://github.com/dart-lang/sdk/issues/37110
+    parseCompilationUnit('class B extends A { B(): super.. {} }', errors: [
+      expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 2),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 33, 1),
+    ]);
+  }
+
+  void test_constructor_super_field() {
+    // https://github.com/dart-lang/sdk/issues/36262
+    // https://github.com/dart-lang/sdk/issues/31198
+    parseCompilationUnit('class B extends A { B(): super().foo {} }', errors: [
+      expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
+    ]);
+  }
+
+  void test_constructor_super_method() {
+    // https://github.com/dart-lang/sdk/issues/36262
+    // https://github.com/dart-lang/sdk/issues/31198
+    parseCompilationUnit('class B extends A { B(): super().foo() {} }',
+        errors: [
+          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
+        ]);
+  }
+
+  void test_constructor_super_named_method() {
+    // https://github.com/dart-lang/sdk/issues/37600
+    parseCompilationUnit('class B extends A { B(): super.c().create() {} }',
+        errors: [
+          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
+        ]);
+  }
+
+  void test_constructor_super_named_method_method() {
+    // https://github.com/dart-lang/sdk/issues/37600
+    parseCompilationUnit('class B extends A { B(): super.c().create().x() {} }',
+        errors: [
+          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
+        ]);
+  }
+
+  void test_constructor_this_cascade_synthetic() {
+    // https://github.com/dart-lang/sdk/issues/37110
+    parseCompilationUnit('class B extends A { B(): this.. {} }', errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 25, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 29, 2),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 32, 1),
+    ]);
+  }
+
+  void test_constructor_this_field() {
+    // https://github.com/dart-lang/sdk/issues/36262
+    // https://github.com/dart-lang/sdk/issues/31198
+    parseCompilationUnit('class B extends A { B(): this().foo; }', errors: [
+      expectedError(ParserErrorCode.INVALID_THIS_IN_INITIALIZER, 25, 4),
+    ]);
+  }
+
+  void test_constructor_this_method() {
+    // https://github.com/dart-lang/sdk/issues/36262
+    // https://github.com/dart-lang/sdk/issues/31198
+    parseCompilationUnit('class B extends A { B(): this().foo(); }', errors: [
+      expectedError(ParserErrorCode.INVALID_THIS_IN_INITIALIZER, 25, 4),
+    ]);
+  }
+
+  void test_constructor_this_named_method() {
+    // https://github.com/dart-lang/sdk/issues/37600
+    parseCompilationUnit('class B extends A { B(): super.c().create() {} }',
+        errors: [
+          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
+        ]);
+  }
+
+  void test_constructor_this_named_method_field() {
+    // https://github.com/dart-lang/sdk/issues/37600
+    parseCompilationUnit('class B extends A { B(): super.c().create().x {} }',
+        errors: [
+          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
+        ]);
+  }
+
+  void test_constructorPartial() {
+    createParser('class C { C< }');
+    parser.parseCompilationUnit2();
+    listener.assertErrors([
+      expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 2),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 13, 1),
+    ]);
+  }
+
+  void test_constructorPartial2() {
+    createParser('class C { C<@Foo }');
+    parser.parseCompilationUnit2();
+    listener.assertErrors([
+      expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 6),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 17, 1),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1)
+    ]);
+  }
+
+  void test_constructorPartial3() {
+    createParser('class C { C<@Foo @Bar() }');
+    parser.parseCompilationUnit2();
+    listener.assertErrors([
+      expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 13),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 1),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 24, 1)
+    ]);
+  }
+
+  void test_constructorWithReturnType() {
+    createParser('C C() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, 0, 1),
+    ]);
+  }
+
+  void test_constructorWithReturnType_var() {
+    createParser('var C() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3)]);
+  }
+
+  void test_constTypedef() {
+    parseCompilationUnit("const typedef F();", errors: [
+      // Fasta interprets the `const` as a malformed top level const
+      // and `typedef` as the start of an typedef declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 7),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 7),
+    ]);
+  }
+
+  void test_continueOutsideOfLoop_continueInDoStatement() {
+    DoStatement statement = parseStatement('do {continue;} while (x);');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_continueOutsideOfLoop_continueInForStatement() {
+    Statement statement = parseStatement('for (; x;) {continue;}');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_continueOutsideOfLoop_continueInIfStatement() {
+    IfStatement statement = parseStatement('if (x) {continue;}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, 8, 8)]);
+  }
+
+  void test_continueOutsideOfLoop_continueInSwitchStatement() {
+    SwitchStatement statement =
+        parseStatement('switch (x) {case 1: continue a;}');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_continueOutsideOfLoop_continueInWhileStatement() {
+    WhileStatement statement = parseStatement('while (x) {continue;}');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_continueOutsideOfLoop_functionExpression_inALoop() {
+    parseStatement("for(; x;) {() {continue;};}");
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, 15, 8)]);
+  }
+
+  void test_continueOutsideOfLoop_functionExpression_withALoop() {
+    parseStatement("() {for (; x;) {continue;}};");
+  }
+
+  void test_continueWithoutLabelInCase_error() {
+    SwitchStatement statement =
+        parseStatement('switch (x) {case 1: continue;}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, 20, 8)]);
+  }
+
+  void test_continueWithoutLabelInCase_noError() {
+    SwitchStatement statement =
+        parseStatement('switch (x) {case 1: continue a;}');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_continueWithoutLabelInCase_noError_switchInLoop() {
+    WhileStatement statement =
+        parseStatement('while (a) { switch (b) {default: continue;}}');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+  }
+
+  void test_covariantAfterVar() {
+    createParser('var covariant f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 4, 9)]);
+  }
+
+  void test_covariantAndFinal() {
+    createParser('covariant final f = null;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrorsWithCodes([ParserErrorCode.FINAL_AND_COVARIANT]);
+  }
+
+  void test_covariantAndStatic() {
+    createParser('covariant static A f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 10, 6)]);
+  }
+
+  void test_covariantAndType_local() {
+    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
+    // this would be a better error message.
+    parseStatement("covariant int x;");
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 9)]);
+  }
+
+  void test_covariantConstructor() {
+    createParser('class C { covariant C(); }');
+    ClassDeclaration member = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.COVARIANT_MEMBER, 10, 9)]);
+  }
+
+  void test_covariantMember_getter_noReturnType() {
+    createParser('static covariant get x => 0;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 7, 9)]);
+  }
+
+  void test_covariantMember_getter_returnType() {
+    createParser('static covariant int get x => 0;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 7, 9)]);
+  }
+
+  void test_covariantMember_method() {
+    createParser('covariant int m() => 0;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.COVARIANT_MEMBER, 0, 9)]);
+  }
+
+  void test_covariantTopLevelDeclaration_class() {
+    createParser('covariant class C {}');
+    ClassDeclaration member = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION, 0, 9)]);
+  }
+
+  void test_covariantTopLevelDeclaration_enum() {
+    createParser('covariant enum E { v }');
+    EnumDeclaration member = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION, 0, 9)]);
+  }
+
+  void test_covariantTopLevelDeclaration_typedef() {
+    parseCompilationUnit("covariant typedef F();", errors: [
+      expectedError(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION, 0, 9)
+    ]);
+  }
+
+  void test_defaultValueInFunctionType_named_colon() {
+    createParser('({int x : 0})');
+    FormalParameter parameter =
+        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
+    expectNotNullIfNoErrors(parameter);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1)]);
+  }
+
+  void test_defaultValueInFunctionType_named_equal() {
+    createParser('({int x = 0})');
+    FormalParameter parameter =
+        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
+    expectNotNullIfNoErrors(parameter);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1)]);
+  }
+
+  void test_defaultValueInFunctionType_positional() {
+    createParser('([int x = 0])');
+    FormalParameter parameter =
+        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
+    expectNotNullIfNoErrors(parameter);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1)]);
+  }
+
+  void test_directiveAfterDeclaration_classBeforeDirective() {
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    CompilationUnit unit = parseCompilationUnit("class Foo{} library l;",
+        codes: [
+          ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST
+        ],
+        errors: [
+          expectedError(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 12, 10)
+        ]);
+    expect(unit, isNotNull);
+  }
+
+  void test_directiveAfterDeclaration_classBetweenDirectives() {
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    CompilationUnit unit =
+        parseCompilationUnit("library l;\nclass Foo{}\npart 'a.dart';", codes: [
+      ParserErrorCode.DIRECTIVE_AFTER_DECLARATION
+    ], errors: [
+      expectedError(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION, 23, 14)
+    ]);
+    expect(unit, isNotNull);
+  }
+
+  void test_duplicatedModifier_const() {
+    createParser('const const m = null;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 6, 5)]);
+  }
+
+  void test_duplicatedModifier_external() {
+    createParser('external external f();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 9, 8)]);
+  }
+
+  void test_duplicatedModifier_factory() {
+    createParser('factory factory C() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 8, 7)]);
+  }
+
+  void test_duplicatedModifier_final() {
+    createParser('final final m = null;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 6, 5)]);
+  }
+
+  void test_duplicatedModifier_static() {
+    createParser('static static var m;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 7, 6)]);
+  }
+
+  void test_duplicatedModifier_var() {
+    createParser('var var m;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 4, 3)]);
+  }
+
+  void test_duplicateLabelInSwitchStatement() {
+    SwitchStatement statement =
+        parseStatement('switch (e) {l1: case 0: break; l1: case 1: break;}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT, 31, 2)
+    ]);
+  }
+
+  void test_emptyEnumBody() {
+    createParser('enum E {}');
+    EnumDeclaration declaration = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(declaration);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EMPTY_ENUM_BODY]);
+//    listener
+//        .assertErrors([expectedError(ParserErrorCode.EMPTY_ENUM_BODY, 7, 2),]);
+  }
+
+  void test_enumInClass() {
+    parseCompilationUnit(r'''
+class Foo {
+  enum Bar {
+    Bar1, Bar2, Bar3
+  }
+}
+''', errors: [expectedError(ParserErrorCode.ENUM_IN_CLASS, 14, 4)]);
+  }
+
+  void test_equalityCannotBeEqualityOperand_eq_eq() {
+    parseExpression("1 == 2 == 3", errors: [
+      expectedError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 7, 2)
+    ]);
+  }
+
+  void test_equalityCannotBeEqualityOperand_eq_neq() {
+    parseExpression("1 == 2 != 3", errors: [
+      expectedError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 7, 2)
+    ]);
+  }
+
+  void test_equalityCannotBeEqualityOperand_neq_eq() {
+    parseExpression("1 != 2 == 3", errors: [
+      expectedError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 7, 2)
+    ]);
+  }
+
+  void test_expectedBody_class() {
+    parseCompilationUnit("class A class B {}",
+        errors: [expectedError(ParserErrorCode.EXPECTED_BODY, 6, 1)]);
+  }
+
+  void test_expectedCaseOrDefault() {
+    SwitchStatement statement = parseStatement('switch (e) {break;}');
+    expectNotNullIfNoErrors(statement);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)]);
+  }
+
+  void test_expectedClassMember_inClass_afterType() {
+    parseCompilationUnit('class C{ heart 2 heart }', errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 9, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 5),
+      expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 17, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 5)
+    ]);
+  }
+
+  void test_expectedClassMember_inClass_beforeType() {
+    parseCompilationUnit('class C { 4 score }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)
+    ]);
+  }
+
+  void test_expectedExecutable_afterAnnotation_atEOF() {
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    parseCompilationUnit('@A',
+        codes: [ParserErrorCode.EXPECTED_EXECUTABLE],
+        errors: [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 1, 1)]);
+  }
+
+  void test_expectedExecutable_inClass_afterVoid() {
+    parseCompilationUnit('class C { void 2 void }', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 15, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 4),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1)
+    ]);
+  }
+
+  void test_expectedExecutable_topLevel_afterType() {
+    CompilationUnit unit = parseCompilationUnit('heart 2 heart', errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 5),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 8, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 5),
+    ]);
+    expect(unit, isNotNull);
+  }
+
+  void test_expectedExecutable_topLevel_afterVoid() {
+    CompilationUnit unit = parseCompilationUnit('void 2 void', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 5, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 0),
+    ]);
+    expect(unit, isNotNull);
+  }
+
+  void test_expectedExecutable_topLevel_beforeType() {
+    parseCompilationUnit('4 score', errors: [
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 2, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 5),
+    ]);
+  }
+
+  void test_expectedExecutable_topLevel_eof() {
+    parseCompilationUnit('x', errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 1)
+    ]);
+  }
+
+  void test_expectedInterpolationIdentifier() {
+    StringLiteral literal = parseExpression("'\$x\$'",
+        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 4, 1)]);
+    expectNotNullIfNoErrors(literal);
+  }
+
+  void test_expectedInterpolationIdentifier_emptyString() {
+    // The scanner inserts an empty string token between the two $'s; we need to
+    // make sure that the MISSING_IDENTIFIER error that is generated has a
+    // nonzero width so that it will show up in the editor UI.
+    StringLiteral literal = parseExpression("'\$\$foo'",
+        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 2, 1)]);
+    expectNotNullIfNoErrors(literal);
+  }
+
+  void test_expectedToken_commaMissingInArgumentList() {
+    createParser('(x, y z)');
+    ArgumentList list = parser.parseArgumentList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
+  }
+
+  void test_expectedToken_parseStatement_afterVoid() {
+    parseStatement("void}", expectedEndOffset: 4);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
+    ]);
+  }
+
+  void test_expectedToken_semicolonMissingAfterExport() {
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    CompilationUnit unit = parseCompilationUnit("export '' class A {}",
+        codes: [ParserErrorCode.EXPECTED_TOKEN],
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 2)]);
+    ExportDirective directive = unit.directives[0] as ExportDirective;
+    expect(directive.uri, isNotNull);
+    expect(directive.uri.stringValue, '');
+    expect(directive.uri.beginToken.isSynthetic, false);
+    expect(directive.uri.isSynthetic, false);
+    Token semicolon = directive.semicolon;
+    expect(semicolon, isNotNull);
+    expect(semicolon.isSynthetic, isTrue);
+    ClassDeclaration clazz = unit.declarations[0] as ClassDeclaration;
+    expect(clazz.name.name, 'A');
+  }
+
+  void test_expectedToken_semicolonMissingAfterExpression() {
+    parseStatement("x");
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXPECTED_TOKEN]);
+//    listener
+//        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 1)]);
+  }
+
+  void test_expectedToken_semicolonMissingAfterImport() {
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    CompilationUnit unit = parseCompilationUnit("import '' class A {}",
+        codes: [ParserErrorCode.EXPECTED_TOKEN],
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 2)]);
+    ImportDirective directive = unit.directives[0] as ImportDirective;
+    Token semicolon = directive.semicolon;
+    expect(semicolon, isNotNull);
+    expect(semicolon.isSynthetic, isTrue);
+  }
+
+  void test_expectedToken_uriAndSemicolonMissingAfterExport() {
+    CompilationUnit unit = parseCompilationUnit("export class A {}", errors: [
+      expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 7, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 5),
+    ]);
+    ExportDirective directive = unit.directives[0] as ExportDirective;
+    expect(directive.uri, isNotNull);
+    expect(directive.uri.stringValue, '');
+    expect(directive.uri.beginToken.isSynthetic, true);
+    expect(directive.uri.isSynthetic, true);
+    Token semicolon = directive.semicolon;
+    expect(semicolon, isNotNull);
+    expect(semicolon.isSynthetic, isTrue);
+    ClassDeclaration clazz = unit.declarations[0] as ClassDeclaration;
+    expect(clazz.name.name, 'A');
+  }
+
+  void test_expectedToken_whileMissingInDoStatement() {
+    parseStatement("do {} (x);");
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
+  }
+
+  void test_expectedTypeName_as() {
+    parseExpression("x as",
+        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 0)]);
+  }
+
+  void test_expectedTypeName_as_void() {
+    parseExpression("x as void)",
+        expectedEndOffset: 9,
+        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 4)]);
+  }
+
+  void test_expectedTypeName_is() {
+    parseExpression("x is",
+        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 0)]);
+  }
+
+  void test_expectedTypeName_is_void() {
+    parseExpression("x is void)",
+        expectedEndOffset: 9,
+        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 4)]);
+  }
+
+  void test_exportAsType() {
+    parseCompilationUnit('export<dynamic> foo;', errors: [
+      expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 0, 6)
+    ]);
+  }
+
+  void test_exportAsType_inClass() {
+    parseCompilationUnit('class C { export<dynamic> foo; }', errors: [
+      expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 6)
+    ]);
+  }
+
+  void test_exportDirectiveAfterPartDirective() {
+    parseCompilationUnit("part 'a.dart'; export 'b.dart';", errors: [
+      expectedError(
+          ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, 15, 6)
+    ]);
+  }
+
+  void test_externalAfterConst() {
+    createParser('const external C();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 8)]);
+  }
+
+  void test_externalAfterFactory() {
+    createParser('factory external C();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 8, 8)]);
+  }
+
+  void test_externalAfterStatic() {
+    createParser('static external int m();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 7, 8)]);
+  }
+
+  void test_externalClass() {
+    parseCompilationUnit("external class C {}",
+        errors: [expectedError(ParserErrorCode.EXTERNAL_CLASS, 0, 8)]);
+  }
+
+  void test_externalConstructorWithBody_factory() {
+    createParser('external factory C() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXTERNAL_FACTORY_WITH_BODY, 21, 1)]);
+  }
+
+  void test_externalConstructorWithBody_named() {
+    createParser('external C.c() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+//      listener.assertErrors(
+//          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 15, 2)]);
+  }
+
+  void test_externalEnum() {
+    parseCompilationUnit("external enum E {ONE}",
+        errors: [expectedError(ParserErrorCode.EXTERNAL_ENUM, 0, 8)]);
+  }
+
+  void test_externalField_const() {
+    createParser('external const A f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 17, 1)]);
+  }
+
+  void test_externalField_final() {
+    createParser('external final A f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_externalField_static() {
+    createParser('external static A f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_externalField_typed() {
+    createParser('external A f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_externalField_untyped() {
+    createParser('external var f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_externalGetterWithBody() {
+    createParser('external int get x {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+//      listener.assertErrors(
+//          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 19, 2)]);
+  }
+
+  void test_externalMethodWithBody() {
+    createParser('external m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+//    listener.assertErrors(
+//        [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 13, 2)]);
+  }
+
+  void test_externalOperatorWithBody() {
+    createParser('external operator +(int value) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+//      listener.assertErrors(
+//          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 31, 2)]);
+  }
+
+  void test_externalSetterWithBody() {
+    createParser('external set x(int value) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
+//      listener.assertErrors(
+//          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 26, 2)]);
+  }
+
+  void test_externalTypedef() {
+    parseCompilationUnit("external typedef F();",
+        errors: [expectedError(ParserErrorCode.EXTERNAL_TYPEDEF, 0, 8)]);
+  }
+
+  void test_extraCommaInParameterList() {
+    createParser('(int a, , int b)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]);
+  }
+
+  void test_extraCommaTrailingNamedParameterGroup() {
+    createParser('({int b},)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]);
+  }
+
+  void test_extraCommaTrailingPositionalParameterGroup() {
+    createParser('([int b],)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]);
+  }
+
+  void test_extraTrailingCommaInParameterList() {
+    createParser('(a,,)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1)]);
+  }
+
+  void test_factory_issue_36400() {
+    parseCompilationUnit('class T { T factory T() { return null; } }',
+        errors: [expectedError(ParserErrorCode.TYPE_BEFORE_FACTORY, 10, 1)]);
+  }
+
+  void test_factoryTopLevelDeclaration_class() {
+    parseCompilationUnit("factory class C {}", errors: [
+      expectedError(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 0, 7)
+    ]);
+  }
+
+  void test_factoryTopLevelDeclaration_enum() {
+    parseCompilationUnit("factory enum E { v }", errors: [
+      expectedError(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 0, 7)
+    ]);
+  }
+
+  void test_factoryTopLevelDeclaration_typedef() {
+    parseCompilationUnit("factory typedef F();", errors: [
+      expectedError(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 0, 7)
+    ]);
+  }
+
+  void test_factoryWithInitializers() {
+    createParser('factory C() : x = 3 {}', expectedEndOffset: 12);
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)]);
+  }
+
+  void test_factoryWithoutBody() {
+    createParser('factory C();');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 11, 1)]);
+  }
+
+  void test_fieldInitializerOutsideConstructor() {
+    createParser('void m(this.x);');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, 7, 4)
+    ]);
+  }
+
+  void test_finalAndCovariant() {
+    createParser('final covariant f = null;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 9),
+      expectedError(ParserErrorCode.FINAL_AND_COVARIANT, 6, 9)
+    ]);
+  }
+
+  void test_finalAndVar() {
+    createParser('final var x = null;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([expectedError(ParserErrorCode.FINAL_AND_VAR, 6, 3)]);
+  }
+
+  void test_finalClass() {
+    parseCompilationUnit("final class C {}",
+        errors: [expectedError(ParserErrorCode.FINAL_CLASS, 0, 5)]);
+  }
+
+  void test_finalClassMember_modifierOnly() {
+    createParser('final');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 0)
+    ]);
+  }
+
+  void test_finalConstructor() {
+    createParser('final C() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 5)]);
+  }
+
+  void test_finalEnum() {
+    parseCompilationUnit("final enum E {ONE}", errors: [
+      // Fasta interprets the `final` as a malformed top level final
+      // and `enum` as the start of a enum declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
+    ]);
+  }
+
+  void test_finalMethod() {
+    createParser('final int m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 5)]);
+  }
+
+  void test_finalTypedef() {
+    parseCompilationUnit("final typedef F();", errors: [
+      // Fasta interprets the `final` as a malformed top level final
+      // and `typedef` as the start of an typedef declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 7),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 7),
+    ]);
+  }
+
+  void test_functionTypedField_invalidType_abstract() {
+    parseCompilationUnit("Function(abstract) x = null;", errors: [
+      expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 9, 8)
+    ]);
+  }
+
+  void test_functionTypedField_invalidType_class() {
+    parseCompilationUnit("Function(class) x = null;", errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5),
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 9, 5)
+    ]);
+  }
+
+  void test_functionTypedParameter_const() {
+    parseCompilationUnit("void f(const x()) {}", errors: [
+      expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 5),
+      expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
+    ]);
+  }
+
+  void test_functionTypedParameter_final() {
+    parseCompilationUnit("void f(final x()) {}", errors: [
+      expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
+    ]);
+  }
+
+  void test_functionTypedParameter_incomplete1() {
+    parseCompilationUnit("void f(int Function(", errors: [
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
+    ]);
+  }
+
+  void test_functionTypedParameter_var() {
+    parseCompilationUnit("void f(var x()) {}", errors: [
+      expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 3)
+    ]);
+  }
+
+  void test_genericFunctionType_asIdentifier() {
+    createParser('final int Function = 0;');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors([]);
+  }
+
+  void test_genericFunctionType_asIdentifier2() {
+    createParser('int Function() {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors([]);
+  }
+
+  void test_genericFunctionType_asIdentifier3() {
+    createParser('int Function() => 0;');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors([]);
+  }
+
+  void test_genericFunctionType_extraLessThan() {
+    createParser('''
+class Wrong<T> {
+  T Function(<List<int> foo) bar;
+}''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 30, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 1)
+    ]);
+  }
+
+  void test_getterInFunction_block_noReturnType() {
+    Statement result =
+        parseStatement("get x { return _x; }", expectedEndOffset: 4);
+    // Fasta considers `get` to be an identifier in this situation.
+    // TODO(danrubel): Investigate better recovery.
+    ExpressionStatement statement = result;
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
+    expect(statement.expression.toSource(), 'get');
+  }
+
+  void test_getterInFunction_block_returnType() {
+    // Fasta considers `get` to be an identifier in this situation.
+    parseStatement("int get x { return _x; }", expectedEndOffset: 8);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]);
+  }
+
+  void test_getterInFunction_expression_noReturnType() {
+    // Fasta considers `get` to be an identifier in this situation.
+    parseStatement("get x => _x;", expectedEndOffset: 4);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
+  }
+
+  void test_getterInFunction_expression_returnType() {
+    // Fasta considers `get` to be an identifier in this situation.
+    parseStatement("int get x => _x;", expectedEndOffset: 8);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]);
+  }
+
+  void test_getterNativeWithBody() {
+    createParser('String get m native "str" => 0;');
+    parser.parseClassMember('C') as MethodDeclaration;
+    if (!allowNativeClause) {
+      assertErrorsWithCodes([
+        ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
+        ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
+      ]);
+    } else {
+      assertErrorsWithCodes([
+        ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
+      ]);
+    }
+  }
+
+  void test_getterWithParameters() {
+    createParser('int get x() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.GETTER_WITH_PARAMETERS]);
+//    listener.assertErrors(
+//        [expectedError(ParserErrorCode.GETTER_WITH_PARAMETERS, 9, 2)]);
+  }
+
+  void test_illegalAssignmentToNonAssignable_assign_int() {
+    parseStatement("0 = 1;");
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 1),
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 1),
+    ]);
+  }
+
+  void test_illegalAssignmentToNonAssignable_assign_this() {
+    parseStatement("this = 1;");
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 4),
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 4)
+    ]);
+  }
+
+  void test_illegalAssignmentToNonAssignable_postfix_minusMinus_literal() {
+    parseExpression("0--", errors: [
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 1, 2)
+    ]);
+  }
+
+  void test_illegalAssignmentToNonAssignable_postfix_plusPlus_literal() {
+    parseExpression("0++", errors: [
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 1, 2)
+    ]);
+  }
+
+  void test_illegalAssignmentToNonAssignable_postfix_plusPlus_parenthesized() {
+    parseExpression("(x)++", errors: [
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 3, 2)
+    ]);
+  }
+
+  void test_illegalAssignmentToNonAssignable_primarySelectorPostfix() {
+    parseExpression("x(y)(z)++", errors: [
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 7, 2)
+    ]);
+  }
+
+  void test_illegalAssignmentToNonAssignable_superAssigned() {
+    parseStatement("super = x;");
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 5),
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 5)
+    ]);
+  }
+
+  void test_implementsBeforeExtends() {
+    parseCompilationUnit("class A implements B extends C {}", errors: [
+      expectedError(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS, 21, 7)
+    ]);
+  }
+
+  void test_implementsBeforeWith() {
+    parseCompilationUnit("class A extends B implements C with D {}",
+        errors: [expectedError(ParserErrorCode.IMPLEMENTS_BEFORE_WITH, 31, 4)]);
+  }
+
+  void test_importDirectiveAfterPartDirective() {
+    parseCompilationUnit("part 'a.dart'; import 'b.dart';", errors: [
+      expectedError(
+          ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, 15, 6)
+    ]);
+  }
+
+  void test_initializedVariableInForEach() {
+    Statement statement = parseStatement('for (int a = 0 in foo) {}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 11, 1)
+    ]);
+  }
+
+  void test_initializedVariableInForEach_annotation() {
+    Statement statement = parseStatement('for (@Foo var a = 0 in foo) {}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 16, 1)
+    ]);
+  }
+
+  void test_initializedVariableInForEach_localFunction() {
+    Statement statement = parseStatement('for (f()) {}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
+    ]);
+  }
+
+  void test_initializedVariableInForEach_localFunction2() {
+    Statement statement = parseStatement('for (T f()) {}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)
+    ]);
+  }
+
+  void test_initializedVariableInForEach_var() {
+    Statement statement = parseStatement('for (var a = 0 in foo) {}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 11, 1)
+    ]);
+  }
+
+  void test_invalidAwaitInFor() {
+    Statement statement = parseStatement('await for (; ;) {}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_AWAIT_IN_FOR, 0, 5)]);
+  }
+
+  void test_invalidCodePoint() {
+    StringLiteral literal = parseExpression("'begin \\u{110000}'",
+        errors: [expectedError(ParserErrorCode.INVALID_CODE_POINT, 7, 9)]);
+    expectNotNullIfNoErrors(literal);
+  }
+
+  @failingTest
+  void test_invalidCommentReference__new_nonIdentifier() {
+    // This test fails because the method parseCommentReference returns null.
+    createParser('');
+    CommentReference reference = parseCommentReference('new 42', 0);
+    expectNotNullIfNoErrors(reference);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 6)]);
+  }
+
+  @failingTest
+  void test_invalidCommentReference__new_tooMuch() {
+    createParser('');
+    CommentReference reference = parseCommentReference('new a.b.c.d', 0);
+    expectNotNullIfNoErrors(reference);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 11)]);
+  }
+
+  @failingTest
+  void test_invalidCommentReference__nonNew_nonIdentifier() {
+    // This test fails because the method parseCommentReference returns null.
+    createParser('');
+    CommentReference reference = parseCommentReference('42', 0);
+    expectNotNullIfNoErrors(reference);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 2)]);
+  }
+
+  @failingTest
+  void test_invalidCommentReference__nonNew_tooMuch() {
+    createParser('');
+    CommentReference reference = parseCommentReference('a.b.c.d', 0);
+    expectNotNullIfNoErrors(reference);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 7)]);
+  }
+
+  void test_invalidConstructorName_star() {
+    createParser("C.*();");
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]);
+  }
+
+  void test_invalidConstructorName_with() {
+    createParser("C.with();");
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 2, 4)
+    ]);
+  }
+
+  void test_invalidConstructorSuperAssignment() {
+    createParser("C() : super = 42;");
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 6, 5)]);
+  }
+
+  void test_invalidConstructorSuperFieldAssignment() {
+    createParser("C() : super.a = 42;");
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(
+          ParserErrorCode.FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS, 12, 1)
+    ]);
+  }
+
+  void test_invalidHexEscape_invalidDigit() {
+    StringLiteral literal = parseExpression("'not \\x0 a'",
+        errors: [expectedError(ParserErrorCode.INVALID_HEX_ESCAPE, 5, 3)]);
+    expectNotNullIfNoErrors(literal);
+  }
+
+  void test_invalidHexEscape_tooFewDigits() {
+    StringLiteral literal = parseExpression("'\\x0'",
+        errors: [expectedError(ParserErrorCode.INVALID_HEX_ESCAPE, 1, 3)]);
+    expectNotNullIfNoErrors(literal);
+  }
+
+  void test_invalidInlineFunctionType() {
+    parseCompilationUnit(
+      'typedef F = int Function(int a());',
+      errors: [
+        expectedError(CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 30, 1)
+      ],
+    );
+  }
+
+  void test_invalidInterpolation_missingClosingBrace_issue35900() {
+    parseCompilationUnit(r"main () { print('${x' '); }", errors: [
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 26, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 3),
+      expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 23, 1),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 27, 0),
+    ]);
+  }
+
+  void test_invalidInterpolationIdentifier_startWithDigit() {
+    StringLiteral literal = parseExpression("'\$1'",
+        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 2, 1)]);
+    expectNotNullIfNoErrors(literal);
+  }
+
+  void test_invalidLiteralInConfiguration() {
+    createParser("if (a == 'x \$y z') 'a.dart'");
+    Configuration configuration = parser.parseConfiguration();
+    expectNotNullIfNoErrors(configuration);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, 12, 2)
+    ]);
+  }
+
+  void test_invalidOperator() {
+    CompilationUnit unit = parseCompilationUnit(
+        'class C { void operator ===(x) { } }',
+        errors: [expectedError(ScannerErrorCode.UNSUPPORTED_OPERATOR, 24, 1)]);
+    expect(unit, isNotNull);
+  }
+
+  void test_invalidOperator_unary() {
+    createParser('class C { int operator unary- => 0; }');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 28, 1)
+    ]);
+  }
+
+  void test_invalidOperatorAfterSuper_assignableExpression() {
+    Expression expression = parseAssignableExpression('super?.v', false);
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors([
+      expectedError(
+          ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER, 5, 2)
+    ]);
+  }
+
+  void test_invalidOperatorAfterSuper_constructorInitializer2() {
+    parseCompilationUnit('class C { C() : super?.namedConstructor(); }',
+        errors: [
+          expectedError(
+              ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER,
+              21,
+              2)
+        ]);
+  }
+
+  void test_invalidOperatorAfterSuper_primaryExpression() {
+    Expression expression = parseExpression('super?.v', errors: [
+      expectedError(
+          ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER, 5, 2)
+    ]);
+    expectNotNullIfNoErrors(expression);
+  }
+
+  void test_invalidOperatorForSuper() {
+    createParser('++super');
+    Expression expression = parser.parseUnaryExpression();
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 2, 5)]);
+  }
+
+  void test_invalidPropertyAccess_this() {
+    parseExpression('x.this',
+        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 4)]);
+  }
+
+  void test_invalidStarAfterAsync() {
+    createParser('foo() async* => 0;');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors(
+        [expectedError(CompileTimeErrorCode.RETURN_IN_GENERATOR, 13, 2)]);
+  }
+
+  void test_invalidSync() {
+    createParser('foo() sync* => 0;');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    listener.assertErrors(
+        [expectedError(CompileTimeErrorCode.RETURN_IN_GENERATOR, 12, 2)]);
+  }
+
+  void test_invalidTopLevelSetter() {
+    parseCompilationUnit("var set foo; main(){}", errors: [
+      expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 8, 3),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 11, 1)
+    ]);
+  }
+
+  void test_invalidTopLevelVar() {
+    parseCompilationUnit("var Function(var arg);", errors: [
+      expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 21, 1),
+    ]);
+  }
+
+  void test_invalidTypedef() {
+    parseCompilationUnit("typedef var Function(var arg);", errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
+      expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 8, 3),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 3),
+      expectedError(ParserErrorCode.VAR_RETURN_TYPE, 8, 3),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 29, 1),
+    ]);
+  }
+
+  void test_invalidTypedef2() {
+    // https://github.com/dart-lang/sdk/issues/31171
+    parseCompilationUnit(
+        "typedef T = typedef F = Map<String, dynamic> Function();",
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 7),
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 7),
+          expectedError(ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 10, 1),
+        ]);
+  }
+
+  void test_invalidUnicodeEscape_incomplete_noDigits() {
+    Expression expression = parseStringLiteral("'\\u{'");
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 3)]);
+  }
+
+  void test_invalidUnicodeEscape_incomplete_someDigits() {
+    Expression expression = parseStringLiteral("'\\u{0A'");
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 5)]);
+  }
+
+  void test_invalidUnicodeEscape_invalidDigit() {
+    Expression expression = parseStringLiteral("'\\u0 and some more'");
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 3)]);
+  }
+
+  void test_invalidUnicodeEscape_tooFewDigits_fixed() {
+    Expression expression = parseStringLiteral("'\\u04'");
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 4)]);
+  }
+
+  void test_invalidUnicodeEscape_tooFewDigits_variable() {
+    Expression expression = parseStringLiteral("'\\u{}'");
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 4)]);
+  }
+
+  void test_invalidUnicodeEscape_tooManyDigits_variable() {
+    Expression expression = parseStringLiteral("'\\u{12345678}'");
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.INVALID_CODE_POINT, 1, 9)]);
+  }
+
+  void test_libraryDirectiveNotFirst() {
+    parseCompilationUnit("import 'x.dart'; library l;", errors: [
+      expectedError(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 17, 7)
+    ]);
+  }
+
+  void test_libraryDirectiveNotFirst_afterPart() {
+    CompilationUnit unit = parseCompilationUnit("part 'a.dart';\nlibrary l;",
+        errors: [
+          expectedError(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 15, 7)
+        ]);
+    expect(unit, isNotNull);
+  }
+
+  void test_localFunction_annotation() {
+    CompilationUnit unit =
+        parseCompilationUnit("class C { m() { @Foo f() {} } }");
+    expect(unit.declarations, hasLength(1));
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.members, hasLength(1));
+    MethodDeclaration member = declaration.members[0];
+    BlockFunctionBody body = member.body;
+    expect(body.block.statements, hasLength(1));
+    FunctionDeclarationStatement statement = body.block.statements[0];
+    expect(statement.functionDeclaration.metadata, hasLength(1));
+    Annotation metadata = statement.functionDeclaration.metadata[0];
+    expect(metadata.name.name, 'Foo');
+  }
+
+  void test_localFunctionDeclarationModifier_abstract() {
+    parseCompilationUnit("class C { m() { abstract f() {} } }",
+        errors: [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]);
+  }
+
+  void test_localFunctionDeclarationModifier_external() {
+    parseCompilationUnit("class C { m() { external f() {} } }",
+        errors: [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]);
+  }
+
+  void test_localFunctionDeclarationModifier_factory() {
+    parseCompilationUnit("class C { m() { factory f() {} } }",
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 7)]);
+  }
+
+  void test_localFunctionDeclarationModifier_static() {
+    parseCompilationUnit("class C { m() { static f() {} } }",
+        errors: [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 6)]);
+  }
+
+  void test_method_invalidTypeParameterExtends() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/25739.
+
+    // TODO(jmesserly): ideally we'd be better at parser recovery here.
+    createParser('f<E>(E extends num p);');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 7)]);
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.parameters.toString(), '(E)',
+        reason: 'parser recovers what it can');
+  }
+
+  void test_method_invalidTypeParameters() {
+    createParser('void m<E, hello!>() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 5)]);
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.typeParameters.toString(), '<E, hello>',
+        reason: 'parser recovers what it can');
+  }
+
+  void test_missing_closing_bracket_issue37528() {
+    final code = '\${foo';
+    createParser(code);
+    final result = fasta.scanString(code);
+    expect(result.hasErrors, isTrue);
+    var token = parserProxy.fastaParser.syntheticPreviousToken(result.tokens);
+    try {
+      parserProxy.fastaParser.parseExpression(token);
+      // TODO(danrubel): Replace this test once root cause is found
+      fail('exception expected');
+    } catch (e) {
+      var msg = e.toString();
+      expect(msg.contains('test_missing_closing_bracket_issue37528'), isTrue);
+    }
+  }
+
+  void test_missingAssignableSelector_identifiersAssigned() {
+    parseExpression("x.y = y;", expectedEndOffset: 7);
+  }
+
+  void test_missingAssignableSelector_prefix_minusMinus_literal() {
+    parseExpression("--0", errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 2, 1)
+    ]);
+  }
+
+  void test_missingAssignableSelector_prefix_plusPlus_literal() {
+    parseExpression("++0", errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 2, 1)
+    ]);
+  }
+
+  void test_missingAssignableSelector_selector() {
+    parseExpression("x(y)(z).a++");
+  }
+
+  void test_missingAssignableSelector_superPrimaryExpression() {
+    CompilationUnit unit = parseCompilationUnit('main() {super;}', errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 8, 5)
+    ]);
+    FunctionDeclaration declaration = unit.declarations.first;
+    BlockFunctionBody blockBody = declaration.functionExpression.body;
+    ExpressionStatement statement = blockBody.block.statements.first;
+    Expression expression = statement.expression;
+    expect(expression, isSuperExpression);
+    SuperExpression superExpression = expression;
+    expect(superExpression.superKeyword, isNotNull);
+  }
+
+  void test_missingAssignableSelector_superPropertyAccessAssigned() {
+    parseExpression("super.x = x;", expectedEndOffset: 11);
+  }
+
+  void test_missingCatchOrFinally() {
+    TryStatement statement = parseStatement('try {}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_CATCH_OR_FINALLY, 0, 3)]);
+    expect(statement, isNotNull);
+  }
+
+  void test_missingClosingParenthesis() {
+    createParser('(int a, int b ;',
+        expectedEndOffset: 14 /* parsing ends at synthetic ')' */);
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.errors
+        .contains(expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 1));
+  }
+
+  void test_missingConstFinalVarOrType_static() {
+    parseCompilationUnit("class A { static f; }", errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 17, 1)
+    ]);
+  }
+
+  void test_missingConstFinalVarOrType_topLevel() {
+    parseCompilationUnit('a;', errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 1)
+    ]);
+  }
+
+  void test_missingEnumBody() {
+    createParser('enum E;', expectedEndOffset: 6);
+    EnumDeclaration declaration = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(declaration);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.MISSING_ENUM_BODY, 6, 1)]);
+  }
+
+  void test_missingEnumComma() {
+    createParser('enum E {one two}');
+    EnumDeclaration declaration = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(declaration);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 3)]);
+  }
+
+  void test_missingExpressionInThrow() {
+    ThrowExpression expression =
+        (parseStatement('throw;') as ExpressionStatement).expression;
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, 5, 1)]);
+  }
+
+  void test_missingFunctionBody_emptyNotAllowed() {
+    createParser(';');
+    FunctionBody functionBody = parser.parseFunctionBody(
+        false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
+    expectNotNullIfNoErrors(functionBody);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 1)]);
+  }
+
+  void test_missingFunctionBody_invalid() {
+    createParser('return 0;');
+    FunctionBody functionBody = parser.parseFunctionBody(
+        false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
+    expectNotNullIfNoErrors(functionBody);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 6)]);
+  }
+
+  void test_missingFunctionParameters_local_nonVoid_block() {
+    // The parser does not recognize this as a function declaration, so it tries
+    // to parse it as an expression statement. It isn't clear what the best
+    // error message is in this case.
+    parseStatement("int f { return x;}", expectedEndOffset: 6);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]);
+  }
+
+  void test_missingFunctionParameters_local_nonVoid_expression() {
+    // The parser does not recognize this as a function declaration, so it tries
+    // to parse it as an expression statement. It isn't clear what the best
+    // error message is in this case.
+    parseStatement("int f => x;");
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 6, 2)]);
+  }
+
+  void test_missingFunctionParameters_local_void_block() {
+    parseStatement("void f { return x;}", expectedEndOffset: 7);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
+  }
+
+  void test_missingFunctionParameters_local_void_expression() {
+    parseStatement("void f => x;");
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 7, 2)]);
+  }
+
+  void test_missingFunctionParameters_topLevel_nonVoid_block() {
+    parseCompilationUnit("int f { return x;}", errors: [
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)
+    ]);
+  }
+
+  void test_missingFunctionParameters_topLevel_nonVoid_expression() {
+    parseCompilationUnit("int f => x;", errors: [
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)
+    ]);
+  }
+
+  void test_missingFunctionParameters_topLevel_void_block() {
+    CompilationUnit unit = parseCompilationUnit("void f { return x;}", errors: [
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)
+    ]);
+    FunctionDeclaration funct = unit.declarations[0];
+    expect(funct.functionExpression.parameters, hasLength(0));
+  }
+
+  void test_missingFunctionParameters_topLevel_void_expression() {
+    CompilationUnit unit = parseCompilationUnit("void f => x;", errors: [
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)
+    ]);
+    FunctionDeclaration funct = unit.declarations[0];
+    expect(funct.functionExpression.parameters, hasLength(0));
+  }
+
+  void test_missingIdentifier_afterOperator() {
+    createParser('1 *');
+    BinaryExpression expression = parser.parseMultiplicativeExpression();
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 0)]);
+  }
+
+  void test_missingIdentifier_beforeClosingCurly() {
+    createParser('int}', expectedEndOffset: 3);
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 3),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)
+    ]);
+  }
+
+  void test_missingIdentifier_inEnum() {
+    createParser('enum E {, TWO}');
+    EnumDeclaration declaration = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(declaration);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]);
+  }
+
+  void test_missingIdentifier_inParameterGroupNamed() {
+    createParser('(a, {})');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]);
+  }
+
+  void test_missingIdentifier_inParameterGroupOptional() {
+    createParser('(a, [])');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]);
+  }
+
+  void test_missingIdentifier_inSymbol_afterPeriod() {
+    SymbolLiteral literal = parseSymbolLiteral('#a.');
+    expectNotNullIfNoErrors(literal);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1)]);
+  }
+
+  void test_missingIdentifier_inSymbol_first() {
+    SymbolLiteral literal = parseSymbolLiteral('#');
+    expectNotNullIfNoErrors(literal);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 1, 1)]);
+  }
+
+  void test_missingIdentifierForParameterGroup() {
+    createParser('(,)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 1, 1)]);
+  }
+
+  void test_missingKeywordOperator() {
+    createParser('+(x) {}');
+    MethodDeclaration method = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(method);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 0, 1)]);
+  }
+
+  void test_missingKeywordOperator_parseClassMember() {
+    createParser('+() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 0, 1)]);
+  }
+
+  void test_missingKeywordOperator_parseClassMember_afterTypeName() {
+    createParser('int +() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 4, 1)]);
+  }
+
+  void test_missingKeywordOperator_parseClassMember_afterVoid() {
+    createParser('void +() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 5, 1)]);
+  }
+
+  void test_missingMethodParameters_void_block() {
+    createParser('void m {} }', expectedEndOffset: 10);
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 5, 1)]);
+    expect(member, isMethodDeclaration);
+    MethodDeclaration method = member;
+    expect(method.parameters, hasLength(0));
+  }
+
+  void test_missingMethodParameters_void_expression() {
+    createParser('void m => null; }', expectedEndOffset: 16);
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 5, 1)]);
+  }
+
+  void test_missingNameForNamedParameter_colon() {
+    createParser('({int : 0})');
+    FormalParameter parameter =
+        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
+    expectNotNullIfNoErrors(parameter);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
+      expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1)
+    ]);
+    expect(parameter.identifier, isNotNull);
+  }
+
+  void test_missingNameForNamedParameter_equals() {
+    createParser('({int = 0})');
+    FormalParameter parameter =
+        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
+    expectNotNullIfNoErrors(parameter);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
+      expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1)
+    ]);
+    expect(parameter.identifier, isNotNull);
+  }
+
+  void test_missingNameForNamedParameter_noDefault() {
+    createParser('({int})');
+    FormalParameter parameter =
+        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
+    expectNotNullIfNoErrors(parameter);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]);
+    expect(parameter.identifier, isNotNull);
+  }
+
+  void test_missingNameInLibraryDirective() {
+    CompilationUnit unit = parseCompilationUnit("library;",
+        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 7, 1)]);
+    expect(unit, isNotNull);
+  }
+
+  void test_missingNameInPartOfDirective() {
+    CompilationUnit unit = parseCompilationUnit("part of;",
+        errors: [expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 7, 1)]);
+    expect(unit, isNotNull);
+  }
+
+  void test_missingPrefixInDeferredImport() {
+    parseCompilationUnit("import 'foo.dart' deferred;", errors: [
+      expectedError(ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT, 18, 8)
+    ]);
+  }
+
+  void test_missingStartAfterSync() {
+    createParser('sync {}');
+    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
+    expectNotNullIfNoErrors(functionBody);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_STAR_AFTER_SYNC, 0, 4)]);
+  }
+
+  void test_missingStatement() {
+    parseStatement("is");
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 2),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 0)
+    ]);
+  }
+
+  void test_missingStatement_afterVoid() {
+    parseStatement("void;");
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]);
+  }
+
+  void test_missingTerminatorForParameterGroup_named() {
+    createParser('(a, {b: 0)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1)]);
+  }
+
+  void test_missingTerminatorForParameterGroup_optional() {
+    createParser('(a, [b = 0)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)]);
+  }
+
+  void test_missingTypedefParameters_nonVoid() {
+    parseCompilationUnit("typedef int F;", errors: [
+      expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 13, 1)
+    ]);
+  }
+
+  void test_missingTypedefParameters_typeParameters() {
+    parseCompilationUnit("typedef F<E>;", errors: [
+      expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 12, 1)
+    ]);
+  }
+
+  void test_missingTypedefParameters_void() {
+    parseCompilationUnit("typedef void F;", errors: [
+      expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 14, 1)
+    ]);
+  }
+
+  void test_missingVariableInForEach() {
+    Statement statement = parseStatement('for (a < b in foo) {}');
+    expectNotNullIfNoErrors(statement);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 1)]);
+  }
+
+  void test_mixedParameterGroups_namedPositional() {
+    createParser('(a, {b}, [c])');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+  }
+
+  void test_mixedParameterGroups_positionalNamed() {
+    createParser('(a, [b], {c})');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+  }
+
+  void test_mixin_application_lacks_with_clause() {
+    parseCompilationUnit("class Foo = Bar;",
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1)]);
+  }
+
+  void test_multipleExtendsClauses() {
+    parseCompilationUnit("class A extends B extends C {}", errors: [
+      expectedError(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES, 18, 7)
+    ]);
+  }
+
+  void test_multipleImplementsClauses() {
+    parseCompilationUnit("class A implements B implements C {}", errors: [
+      expectedError(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, 21, 10)
+    ]);
+  }
+
+  void test_multipleLibraryDirectives() {
+    parseCompilationUnit("library l; library m;", errors: [
+      expectedError(ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES, 11, 7)
+    ]);
+  }
+
+  void test_multipleNamedParameterGroups() {
+    createParser('(a, {b}, {c})');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+  }
+
+  void test_multiplePartOfDirectives() {
+    parseCompilationUnit("part of l; part of m;", errors: [
+      expectedError(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES, 11, 4)
+    ]);
+  }
+
+  void test_multiplePositionalParameterGroups() {
+    createParser('(a, [b], [c])');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+  }
+
+  void test_multipleVariablesInForEach() {
+    Statement statement = parseStatement('for (int a, b in foo) {}');
+    expectNotNullIfNoErrors(statement);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 10, 1)]);
+  }
+
+  void test_multipleWithClauses() {
+    parseCompilationUnit("class A extends B with C with D {}",
+        errors: [expectedError(ParserErrorCode.MULTIPLE_WITH_CLAUSES, 25, 4)]);
+  }
+
+  void test_namedFunctionExpression() {
+    Expression expression;
+    createParser('f() {}');
+    expression = parser.parsePrimaryExpression();
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, 0, 1)]);
+    expect(expression, isFunctionExpression);
+  }
+
+  void test_namedParameterOutsideGroup() {
+    createParser('(a, b : 0)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 6, 1)]);
+    expect(list.parameters[0].isRequired, isTrue);
+    expect(list.parameters[1].isNamed, isTrue);
+  }
+
+  void test_nonConstructorFactory_field() {
+    createParser('factory int x;', expectedEndOffset: 12);
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 12, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)
+    ]);
+  }
+
+  void test_nonConstructorFactory_method() {
+    createParser('factory int m() {}', expectedEndOffset: 12);
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 12, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)
+    ]);
+  }
+
+  void test_nonIdentifierLibraryName_library() {
+    CompilationUnit unit = parseCompilationUnit("library 'lib';",
+        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 5)]);
+    expect(unit, isNotNull);
+  }
+
+  void test_nonIdentifierLibraryName_partOf() {
+    CompilationUnit unit = parseCompilationUnit("part of 3;", errors: [
+      expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 8, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 1),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 1)
+    ]);
+    expect(unit, isNotNull);
+  }
+
+  void test_nonPartOfDirectiveInPart_after() {
+    parseCompilationUnit("part of l; part 'f.dart';", errors: [
+      expectedError(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, 11, 4)
+    ]);
+  }
+
+  void test_nonPartOfDirectiveInPart_before() {
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    parseCompilationUnit("part 'f.dart'; part of m;", codes: [
+      ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART
+    ], errors: [
+      expectedError(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, 0, 4)
+    ]);
+  }
+
+  void test_nonUserDefinableOperator() {
+    createParser('operator +=(int x) => x + 1;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.INVALID_OPERATOR, 9, 2)]);
+  }
+
+  void test_optionalAfterNormalParameters_named() {
+    parseCompilationUnit("f({a}, b) {}",
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
+  }
+
+  void test_optionalAfterNormalParameters_positional() {
+    parseCompilationUnit("f([a], b) {}",
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
+  }
+
+  void test_parseCascadeSection_missingIdentifier() {
+    MethodInvocation methodInvocation = parseCascadeSection('..()');
+    expectNotNullIfNoErrors(methodInvocation);
+    listener.assertErrors([
+      // Cascade section is preceded by `null` in this test
+      // and error is reported on '('.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1)
+    ]);
+    expect(methodInvocation.target, isNull);
+    expect(methodInvocation.methodName.name, "");
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList.arguments, hasLength(0));
+  }
+
+  void test_parseCascadeSection_missingIdentifier_typeArguments() {
+    MethodInvocation methodInvocation = parseCascadeSection('..<E>()');
+    expectNotNullIfNoErrors(methodInvocation);
+    listener.assertErrors([
+      // Cascade section is preceded by `null` in this test
+      // and error is reported on '<'.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1)
+    ]);
+    expect(methodInvocation.target, isNull);
+    expect(methodInvocation.methodName.name, "");
+    expect(methodInvocation.typeArguments, isNotNull);
+    expect(methodInvocation.argumentList.arguments, hasLength(0));
+  }
+
+  void test_partialNamedConstructor() {
+    parseCompilationUnit('class C { C. }', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 13, 1),
+    ]);
+  }
+
+  void test_positionalAfterNamedArgument() {
+    createParser('(x: 1, 2)');
+    ArgumentList list = parser.parseArgumentList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT, 7, 1)]);
+  }
+
+  void test_positionalParameterOutsideGroup() {
+    createParser('(a, b = 0)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 6, 1)]);
+    expect(list.parameters[0].isRequired, isTrue);
+    expect(list.parameters[1].isNamed, isTrue);
+  }
+
+  void test_redirectingConstructorWithBody_named() {
+    createParser('C.x() : this() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, 15, 1)
+    ]);
+  }
+
+  void test_redirectingConstructorWithBody_unnamed() {
+    createParser('C() : this.x() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, 15, 1)
+    ]);
+  }
+
+  void test_redirectionInNonFactoryConstructor() {
+    createParser('C() = D;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(
+          ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, 4, 1)
+    ]);
+  }
+
+  void test_setterInFunction_block() {
+    parseStatement("set x(v) {_x = v;}");
+    listener
+        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 3)]);
+  }
+
+  void test_setterInFunction_expression() {
+    parseStatement("set x(v) => _x = v;");
+    listener
+        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 3)]);
+  }
+
+  void test_staticAfterConst() {
+    createParser('final static int f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 6)]);
+  }
+
+  void test_staticAfterFinal() {
+    createParser('const static int f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 6),
+      expectedError(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 17, 1)
+    ]);
+  }
+
+  void test_staticAfterVar() {
+    createParser('var static f;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 4, 6)]);
+  }
+
+  void test_staticConstructor() {
+    createParser('static C.m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.STATIC_CONSTRUCTOR, 0, 6)]);
+  }
+
+  void test_staticGetterWithoutBody() {
+    createParser('static get m;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)]);
+  }
+
+  void test_staticOperator_noReturnType() {
+    createParser('static operator +(int x) => x + 1;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.STATIC_OPERATOR, 0, 6)]);
+  }
+
+  void test_staticOperator_returnType() {
+    createParser('static int operator +(int x) => x + 1;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.STATIC_OPERATOR, 0, 6)]);
+  }
+
+  void test_staticOperatorNamedMethod() {
+    // operator can be used as a method name
+    parseCompilationUnit('class C { static operator(x) => x; }');
+  }
+
+  void test_staticSetterWithoutBody() {
+    createParser('static set m(x);');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 15, 1)]);
+  }
+
+  void test_staticTopLevelDeclaration_class() {
+    parseCompilationUnit("static class C {}", errors: [
+      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
+    ]);
+  }
+
+  void test_staticTopLevelDeclaration_enum() {
+    parseCompilationUnit("static enum E { v }", errors: [
+      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
+    ]);
+  }
+
+  void test_staticTopLevelDeclaration_function() {
+    parseCompilationUnit("static f() {}", errors: [
+      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
+    ]);
+  }
+
+  void test_staticTopLevelDeclaration_typedef() {
+    parseCompilationUnit("static typedef F();", errors: [
+      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
+    ]);
+  }
+
+  void test_staticTopLevelDeclaration_variable() {
+    parseCompilationUnit("static var x;", errors: [
+      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
+    ]);
+  }
+
+  void test_string_unterminated_interpolation_block() {
+    parseCompilationUnit(r'''
+m() {
+ {
+ '${${
+''', codes: [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+  }
+
+  void test_switchCase_missingColon() {
+    SwitchStatement statement = parseStatement('switch (a) {case 1 return 0;}');
+    expect(statement, isNotNull);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 6)]);
+  }
+
+  void test_switchDefault_missingColon() {
+    SwitchStatement statement =
+        parseStatement('switch (a) {default return 0;}');
+    expect(statement, isNotNull);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 6)]);
+  }
+
+  void test_switchHasCaseAfterDefaultCase() {
+    SwitchStatement statement =
+        parseStatement('switch (a) {default: return 0; case 1: return 1;}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, 31, 4)
+    ]);
+  }
+
+  void test_switchHasCaseAfterDefaultCase_repeated() {
+    SwitchStatement statement = parseStatement(
+        'switch (a) {default: return 0; case 1: return 1; case 2: return 2;}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, 31, 4),
+      expectedError(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, 49, 4)
+    ]);
+  }
+
+  void test_switchHasMultipleDefaultCases() {
+    SwitchStatement statement =
+        parseStatement('switch (a) {default: return 0; default: return 1;}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, 31, 7)
+    ]);
+  }
+
+  void test_switchHasMultipleDefaultCases_repeated() {
+    SwitchStatement statement = parseStatement(
+        'switch (a) {default: return 0; default: return 1; default: return 2;}');
+    expectNotNullIfNoErrors(statement);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, 31, 7),
+      expectedError(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, 50, 7)
+    ]);
+  }
+
+  void test_switchMissingBlock() {
+    SwitchStatement statement =
+        parseStatement('switch (a) return;', expectedEndOffset: 11);
+    expect(statement, isNotNull);
+    listener.assertErrors([expectedError(ParserErrorCode.EXPECTED_BODY, 9, 1)]);
+  }
+
+  void test_topLevel_getter() {
+    createParser('get x => 7;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration function = member;
+    expect(function.functionExpression.parameters, isNull);
+  }
+
+  void test_topLevelFactory_withFunction() {
+    parseCompilationUnit('factory Function() x = null;', errors: [
+      expectedError(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 0, 7)
+    ]);
+  }
+
+  void test_topLevelOperator_withFunction() {
+    parseCompilationUnit('operator Function() x = null;',
+        errors: [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 8)]);
+  }
+
+  void test_topLevelOperator_withoutOperator() {
+    createParser('+(bool x, bool y) => x | y;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 1)]);
+  }
+
+  void test_topLevelOperator_withoutType() {
+    parseCompilationUnit('operator +(bool x, bool y) => x | y;',
+        errors: [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 8)]);
+  }
+
+  void test_topLevelOperator_withType() {
+    parseCompilationUnit('bool operator +(bool x, bool y) => x | y;',
+        errors: [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 5, 8)]);
+  }
+
+  void test_topLevelOperator_withVoid() {
+    parseCompilationUnit('void operator +(bool x, bool y) => x | y;',
+        errors: [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 5, 8)]);
+  }
+
+  void test_topLevelVariable_withMetadata() {
+    parseCompilationUnit("String @A string;", codes: [
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
+    ]);
+  }
+
+  void test_typedef_incomplete() {
+    // TODO(brianwilkerson) Improve recovery for this case.
+    parseCompilationUnit('''
+class A {}
+class B extends A {}
+
+typedef T
+
+main() {
+  Function<
+}
+''', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 49, 1),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 51, 1),
+    ]);
+  }
+
+  void test_typedef_namedFunction() {
+    parseCompilationUnit('typedef void Function();',
+        codes: [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]);
+  }
+
+  void test_typedefInClass_withoutReturnType() {
+    parseCompilationUnit("class C { typedef F(x); }",
+        errors: [expectedError(ParserErrorCode.TYPEDEF_IN_CLASS, 10, 7)]);
+  }
+
+  void test_typedefInClass_withReturnType() {
+    parseCompilationUnit("class C { typedef int F(int x); }",
+        errors: [expectedError(ParserErrorCode.TYPEDEF_IN_CLASS, 10, 7)]);
+  }
+
+  void test_unexpectedCommaThenInterpolation() {
+    // https://github.com/Dart-Code/Dart-Code/issues/1548
+    parseCompilationUnit(r"main() { String s = 'a' 'b', 'c$foo'; return s; }",
+        errors: [
+          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 29, 2),
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 29, 2),
+        ]);
+  }
+
+  void test_unexpectedTerminatorForParameterGroup_named() {
+    createParser('(a, b})');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
+  }
+
+  void test_unexpectedTerminatorForParameterGroup_optional() {
+    createParser('(a, b])');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]);
+  }
+
+  void test_unexpectedToken_endOfFieldDeclarationStatement() {
+    parseStatement("String s = (null));", expectedEndOffset: 17);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1)]);
+  }
+
+  void test_unexpectedToken_invalidPostfixExpression() {
+    parseExpression("f()++", errors: [
+      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 3, 2)
+    ]);
+  }
+
+  void test_unexpectedToken_invalidPrefixExpression() {
+    parseExpression("++f()", errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 4, 1)
+    ]);
+  }
+
+  void test_unexpectedToken_returnInExpressionFunctionBody() {
+    parseCompilationUnit("f() => return null;",
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 6)]);
+  }
+
+  void test_unexpectedToken_semicolonBetweenClassMembers() {
+    createParser('class C { int x; ; int y;}');
+    ClassDeclaration declaration = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(declaration);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 17, 1)]);
+  }
+
+  void test_unexpectedToken_semicolonBetweenCompilationUnitMembers() {
+    parseCompilationUnit("int x; ; int y;",
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 1)]);
+  }
+
+  void test_unterminatedString_at_eof() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    parseCompilationUnit(r'''
+void main() {
+  var x = "''', errors: [
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 25, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 24, 1)
+    ]);
+  }
+
+  void test_unterminatedString_at_eol() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    parseCompilationUnit(r'''
+void main() {
+  var x = "
+;
+}
+''', errors: [
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1)
+    ]);
+  }
+
+  void test_unterminatedString_multiline_at_eof_3_quotes() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    parseCompilationUnit(r'''
+void main() {
+  var x = """''', codes: [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ], errors: [
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 30, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 0)
+    ]);
+  }
+
+  void test_unterminatedString_multiline_at_eof_4_quotes() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    parseCompilationUnit(r'''
+void main() {
+  var x = """"''', codes: [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ], errors: [
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 31, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 31, 0)
+    ]);
+  }
+
+  void test_unterminatedString_multiline_at_eof_5_quotes() {
+    // Although the "unterminated string" error message is produced by the
+    // scanner, we need to verify that the parser can handle the tokens
+    // produced by the scanner when an unterminated string is encountered.
+    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
+    parseCompilationUnit(r'''
+void main() {
+  var x = """""''', codes: [
+      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
+      ScannerErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN
+    ], errors: [
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 28, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 32, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 32, 0)
+    ]);
+  }
+
+  void test_useOfUnaryPlusOperator() {
+    createParser('+x');
+    Expression expression = parser.parseUnaryExpression();
+    expectNotNullIfNoErrors(expression);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
+    BinaryExpression binaryExpression = expression;
+    expect(binaryExpression.leftOperand.isSynthetic, isTrue);
+    expect(binaryExpression.rightOperand.isSynthetic, isFalse);
+    SimpleIdentifier identifier = binaryExpression.rightOperand;
+    expect(identifier.name, 'x');
+  }
+
+  void test_varAndType_field() {
+    parseCompilationUnit("class C { var int x; }",
+        errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 10, 3)]);
+  }
+
+  void test_varAndType_local() {
+    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
+    // this would be a better error message.
+    parseStatement("var int x;");
+    listener.assertErrors([expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]);
+  }
+
+  void test_varAndType_parameter() {
+    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
+    // this would be a better error message.
+    createParser('(var int x)');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors([expectedError(ParserErrorCode.VAR_AND_TYPE, 1, 3)]);
+  }
+
+  void test_varAndType_topLevelVariable() {
+    parseCompilationUnit("var int x;",
+        errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]);
+  }
+
+  void test_varAsTypeName_as() {
+    parseExpression("x as var",
+        expectedEndOffset: 5,
+        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 3)]);
+  }
+
+  void test_varClass() {
+    parseCompilationUnit("var class C {}", errors: [
+      // Fasta interprets the `var` as a malformed top level var
+      // and `class` as the start of a class declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 5),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 5),
+    ]);
+  }
+
+  void test_varEnum() {
+    parseCompilationUnit("var enum E {ONE}", errors: [
+      // Fasta interprets the `var` as a malformed top level var
+      // and `enum` as the start of an enum declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 4),
+    ]);
+  }
+
+  void test_varReturnType() {
+    createParser('var m() {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3)]);
+  }
+
+  void test_varTypedef() {
+    parseCompilationUnit("var typedef F();", errors: [
+      // Fasta interprets the `var` as a malformed top level var
+      // and `typedef` as the start of an typedef declaration.
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 7),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 7),
+    ]);
+  }
+
+  void test_voidParameter() {
+    NormalFormalParameter parameter =
+        parseFormalParameterList('(void a)').parameters[0];
+    expectNotNullIfNoErrors(parameter);
+    assertNoErrors();
+  }
+
+  void test_voidVariable_parseClassMember_initializer() {
+    createParser('void x = 0;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_voidVariable_parseClassMember_noInitializer() {
+    createParser('void x;');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_voidVariable_parseCompilationUnit_initializer() {
+    parseCompilationUnit("void x = 0;");
+  }
+
+  void test_voidVariable_parseCompilationUnit_noInitializer() {
+    parseCompilationUnit("void x;");
+  }
+
+  void test_voidVariable_parseCompilationUnitMember_initializer() {
+    createParser('void a = 0;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_voidVariable_parseCompilationUnitMember_noInitializer() {
+    createParser('void a;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(member);
+    assertNoErrors();
+  }
+
+  void test_voidVariable_statement_initializer() {
+    parseStatement("void x = 0;");
+    assertNoErrors();
+  }
+
+  void test_voidVariable_statement_noInitializer() {
+    parseStatement("void x;");
+    assertNoErrors();
+  }
+
+  void test_withBeforeExtends() {
+    parseCompilationUnit("class A with B extends C {}",
+        errors: [expectedError(ParserErrorCode.WITH_BEFORE_EXTENDS, 15, 7)]);
+  }
+
+  void test_withWithoutExtends() {
+    createParser('class A with B, C {}');
+    ClassDeclaration declaration = parseFullCompilationUnitMember();
+    expectNotNullIfNoErrors(declaration);
+    listener.assertNoErrors();
+  }
+
+  void test_wrongSeparatorForPositionalParameter() {
+    createParser('(a, [b : 0])');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    listener.assertErrors([
+      expectedError(
+          ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, 7, 1)
+    ]);
+  }
+
+  void test_wrongTerminatorForParameterGroup_named() {
+    createParser('(a, {b, c])');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    // fasta scanner generates '(a, {b, c]})' where '}' is synthetic
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
+    ]);
+  }
+
+  void test_wrongTerminatorForParameterGroup_optional() {
+    createParser('(a, [b, c})');
+    FormalParameterList list = parser.parseFormalParameterList();
+    expectNotNullIfNoErrors(list);
+    // fasta scanner generates '(a, [b, c}])' where ']' is synthetic
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
+    ]);
+  }
+
+  void test_yieldAsLabel() {
+    // yield can be used as a label
+    parseCompilationUnit('main() { yield: break yield; }');
+  }
+}
diff --git a/pkg/analyzer/test/generated/expression_parser_test.dart b/pkg/analyzer/test/generated/expression_parser_test.dart
new file mode 100644
index 0000000..567af1a
--- /dev/null
+++ b/pkg/analyzer/test/generated/expression_parser_test.dart
@@ -0,0 +1,2558 @@
+// 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:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
+    show AbstractScanner;
+import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/ast.dart'
+    show InstanceCreationExpressionImpl;
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:analyzer/src/generated/testing/token_factory.dart';
+import 'package:pub_semver/src/version.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExpressionParserTest);
+  });
+}
+
+/// Tests of the fasta parser based on [ExpressionParserTestMixin].
+@reflectiveTest
+class ExpressionParserTest extends FastaParserTestCase {
+  final beforeUiAsCode = FeatureSet.fromEnableFlags2(
+    sdkLanguageVersion: Version.parse('2.2.0'),
+    flags: [],
+  );
+
+  void test_binaryExpression_allOperators() {
+    // https://github.com/dart-lang/sdk/issues/36255
+    for (TokenType type in TokenType.all) {
+      if (type.precedence > 0) {
+        var source = 'a ${type.lexeme} b';
+        try {
+          parseExpression(source);
+        } on TestFailure {
+          // Ensure that there are no infinite loops or exceptions thrown
+          // by the parser. Test failures are fine.
+        }
+      }
+    }
+  }
+
+  void test_invalidExpression_37706() {
+    // https://github.com/dart-lang/sdk/issues/37706
+    parseExpression('<b?c>()', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 1, 1),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 0),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 7, 0),
+    ]);
+  }
+
+  void test_listLiteral_invalid_assert() {
+    // https://github.com/dart-lang/sdk/issues/37674
+    parseExpression('n=<.["\$assert', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 3, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 6),
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 12, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 13, 1),
+    ]);
+  }
+
+  void test_listLiteral_invalidElement_37697() {
+    // https://github.com/dart-lang/sdk/issues/37674
+    parseExpression('[<y.<z>(){}]', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1),
+    ]);
+  }
+
+  void test_lt_dot_bracket_quote() {
+    // https://github.com/dart-lang/sdk/issues/37674
+    var list = parseExpression('<.["', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 1, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 1),
+      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 3, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 4, 1),
+    ]) as ListLiteral;
+    expect(list.elements, hasLength(1));
+    var first = list.elements[0] as StringLiteral;
+    expect(first.length, 1);
+  }
+
+  void test_lt_dot_listLiteral() {
+    // https://github.com/dart-lang/sdk/issues/37674
+    var list = parseExpression('<.[]', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 1, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 2),
+    ]) as ListLiteral;
+    expect(list.elements, hasLength(0));
+  }
+
+  void test_mapLiteral() {
+    var map = parseExpression('{3: 6}') as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments, isNull);
+    expect(map.elements, hasLength(1));
+    var entry = map.elements[0] as MapLiteralEntry;
+    var key = entry.key as IntegerLiteral;
+    expect(key.value, 3);
+    var value = entry.value as IntegerLiteral;
+    expect(value.value, 6);
+  }
+
+  void test_mapLiteral_const() {
+    var map = parseExpression('const {3: 6}') as SetOrMapLiteral;
+    expect(map.constKeyword, isNotNull);
+    expect(map.typeArguments, isNull);
+    expect(map.elements, hasLength(1));
+    var entry = map.elements[0] as MapLiteralEntry;
+    var key = entry.key as IntegerLiteral;
+    expect(key.value, 3);
+    var value = entry.value as IntegerLiteral;
+    expect(value.value, 6);
+  }
+
+  @failingTest
+  void test_mapLiteral_invalid_too_many_type_arguments1() {
+    var map = parseExpression('<int, int, int>{}', errors: [
+      // TODO(danrubel): Currently the resolver reports invalid number of
+      // type arguments, but the parser could report this.
+      expectedError(
+          /* ParserErrorCode.EXPECTED_ONE_OR_TWO_TYPE_VARIABLES */
+          ParserErrorCode.EXPECTED_TOKEN,
+          11,
+          3),
+    ]) as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.elements, hasLength(0));
+  }
+
+  @failingTest
+  void test_mapLiteral_invalid_too_many_type_arguments2() {
+    var map = parseExpression('<int, int, int>{1}', errors: [
+      // TODO(danrubel): Currently the resolver reports invalid number of
+      // type arguments, but the parser could report this.
+      expectedError(
+          /* ParserErrorCode.EXPECTED_ONE_OR_TWO_TYPE_VARIABLES */
+          ParserErrorCode.EXPECTED_TOKEN,
+          11,
+          3),
+    ]) as SetOrMapLiteral;
+    expect(map.constKeyword, isNull);
+    expect(map.elements, hasLength(0));
+  }
+
+  void test_namedArgument() {
+    var invocation = parseExpression('m(a: 1, b: 2)') as MethodInvocation;
+    List<Expression> arguments = invocation.argumentList.arguments;
+
+    var a = arguments[0] as NamedExpression;
+    expect(a.name.label.name, 'a');
+    expect(a.expression, isNotNull);
+
+    var b = arguments[1] as NamedExpression;
+    expect(b.name.label.name, 'b');
+    expect(b.expression, isNotNull);
+  }
+
+  void test_parseAdditiveExpression_normal() {
+    Expression expression = parseAdditiveExpression('x + y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.PLUS);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseAdditiveExpression_super() {
+    Expression expression = parseAdditiveExpression('super + y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isSuperExpression);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.PLUS);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseAssignableExpression_expression_args_dot() {
+    Expression expression = parseAssignableExpression('(x)(y).z', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    FunctionExpressionInvocation invocation =
+        propertyAccess.target as FunctionExpressionInvocation;
+    expect(invocation.function, isNotNull);
+    expect(invocation.typeArguments, isNull);
+    ArgumentList argumentList = invocation.argumentList;
+    expect(argumentList, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+    expect(propertyAccess.operator, isNotNull);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableExpression_expression_args_dot_typeArguments() {
+    Expression expression = parseAssignableExpression('(x)<F>(y).z', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    FunctionExpressionInvocation invocation =
+        propertyAccess.target as FunctionExpressionInvocation;
+    expect(invocation.function, isNotNull);
+    expect(invocation.typeArguments, isNotNull);
+    ArgumentList argumentList = invocation.argumentList;
+    expect(argumentList, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+    expect(propertyAccess.operator, isNotNull);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableExpression_expression_dot() {
+    Expression expression = parseAssignableExpression('(x).y', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    expect(propertyAccess.target, isNotNull);
+    expect(propertyAccess.operator.type, TokenType.PERIOD);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableExpression_expression_index() {
+    Expression expression = parseAssignableExpression('(x)[y]', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var indexExpression = expression as IndexExpression;
+    expect(indexExpression.target, isNotNull);
+    expect(indexExpression.leftBracket, isNotNull);
+    expect(indexExpression.index, isNotNull);
+    expect(indexExpression.rightBracket, isNotNull);
+  }
+
+  void test_parseAssignableExpression_expression_question_dot() {
+    Expression expression = parseAssignableExpression('(x)?.y', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    expect(propertyAccess.target, isNotNull);
+    expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableExpression_identifier() {
+    Expression expression = parseAssignableExpression('x', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var identifier = expression as SimpleIdentifier;
+    expect(identifier, isNotNull);
+  }
+
+  void test_parseAssignableExpression_identifier_args_dot() {
+    Expression expression = parseAssignableExpression('x(y).z', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    MethodInvocation invocation = propertyAccess.target as MethodInvocation;
+    expect(invocation.methodName.name, "x");
+    expect(invocation.typeArguments, isNull);
+    ArgumentList argumentList = invocation.argumentList;
+    expect(argumentList, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+    expect(propertyAccess.operator, isNotNull);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableExpression_identifier_args_dot_typeArguments() {
+    Expression expression = parseAssignableExpression('x<E>(y).z', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    MethodInvocation invocation = propertyAccess.target as MethodInvocation;
+    expect(invocation.methodName.name, "x");
+    expect(invocation.typeArguments, isNotNull);
+    ArgumentList argumentList = invocation.argumentList;
+    expect(argumentList, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+    expect(propertyAccess.operator, isNotNull);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableExpression_identifier_dot() {
+    Expression expression = parseAssignableExpression('x.y', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var identifier = expression as PrefixedIdentifier;
+    expect(identifier.prefix.name, 'x');
+    expect(identifier.period, isNotNull);
+    expect(identifier.period.type, TokenType.PERIOD);
+    expect(identifier.identifier.name, 'y');
+  }
+
+  void test_parseAssignableExpression_identifier_index() {
+    Expression expression = parseAssignableExpression('x[y]', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var indexExpression = expression as IndexExpression;
+    expect(indexExpression.target, isNotNull);
+    expect(indexExpression.leftBracket, isNotNull);
+    expect(indexExpression.index, isNotNull);
+    expect(indexExpression.rightBracket, isNotNull);
+  }
+
+  void test_parseAssignableExpression_identifier_question_dot() {
+    Expression expression = parseAssignableExpression('x?.y', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    expect(propertyAccess.target, isNotNull);
+    expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableExpression_super_dot() {
+    Expression expression = parseAssignableExpression('super.y', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    expect(propertyAccess.target, isSuperExpression);
+    expect(propertyAccess.operator, isNotNull);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableExpression_super_index() {
+    Expression expression = parseAssignableExpression('super[y]', false);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var indexExpression = expression as IndexExpression;
+    expect(indexExpression.target, isSuperExpression);
+    expect(indexExpression.leftBracket, isNotNull);
+    expect(indexExpression.index, isNotNull);
+    expect(indexExpression.rightBracket, isNotNull);
+  }
+
+  void test_parseAssignableSelector_dot() {
+    Expression expression = parseAssignableSelector('.x', true);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    expect(propertyAccess.operator.type, TokenType.PERIOD);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAssignableSelector_index() {
+    Expression expression = parseAssignableSelector('[x]', true);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var indexExpression = expression as IndexExpression;
+    expect(indexExpression.leftBracket, isNotNull);
+    expect(indexExpression.index, isNotNull);
+    expect(indexExpression.rightBracket, isNotNull);
+  }
+
+  void test_parseAssignableSelector_none() {
+    Expression expression = parseAssignableSelector('', true);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var identifier = expression as SimpleIdentifier;
+    expect(identifier, isNotNull);
+  }
+
+  void test_parseAssignableSelector_question_dot() {
+    Expression expression = parseAssignableSelector('?.x', true);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parseAwaitExpression() {
+    AwaitExpression expression = parseAwaitExpression('await x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.awaitKeyword, isNotNull);
+    expect(expression.expression, isNotNull);
+  }
+
+  void test_parseBitwiseAndExpression_normal() {
+    Expression expression = parseBitwiseAndExpression('x & y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.AMPERSAND);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseBitwiseAndExpression_super() {
+    Expression expression = parseBitwiseAndExpression('super & y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isSuperExpression);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.AMPERSAND);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseBitwiseOrExpression_normal() {
+    Expression expression = parseBitwiseOrExpression('x | y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.BAR);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseBitwiseOrExpression_super() {
+    Expression expression = parseBitwiseOrExpression('super | y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isSuperExpression);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.BAR);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseBitwiseXorExpression_normal() {
+    Expression expression = parseBitwiseXorExpression('x ^ y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.CARET);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseBitwiseXorExpression_super() {
+    Expression expression = parseBitwiseXorExpression('super ^ y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isSuperExpression);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.CARET);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseCascadeSection_i() {
+    Expression expression = parseCascadeSection('..[i]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as IndexExpression;
+    expect(section.target, isNull);
+    expect(section.leftBracket, isNotNull);
+    expect(section.index, isNotNull);
+    expect(section.rightBracket, isNotNull);
+  }
+
+  void test_parseCascadeSection_ia() {
+    Expression expression = parseCascadeSection('..[i](b)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as FunctionExpressionInvocation;
+    expect(section.function, isIndexExpression);
+    expect(section.typeArguments, isNull);
+    expect(section.argumentList, isNotNull);
+  }
+
+  void test_parseCascadeSection_ia_typeArguments() {
+    Expression expression = parseCascadeSection('..[i]<E>(b)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as FunctionExpressionInvocation;
+    expect(section.function, isIndexExpression);
+    expect(section.typeArguments, isNotNull);
+    expect(section.argumentList, isNotNull);
+  }
+
+  void test_parseCascadeSection_ii() {
+    Expression expression = parseCascadeSection('..a(b).c(d)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as MethodInvocation;
+    expect(section.target, isMethodInvocation);
+    expect(section.operator, isNotNull);
+    expect(section.methodName, isNotNull);
+    expect(section.typeArguments, isNull);
+    expect(section.argumentList, isNotNull);
+    expect(section.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseCascadeSection_ii_typeArguments() {
+    Expression expression = parseCascadeSection('..a<E>(b).c<F>(d)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as MethodInvocation;
+    expect(section.target, isMethodInvocation);
+    expect(section.operator, isNotNull);
+    expect(section.methodName, isNotNull);
+    expect(section.typeArguments, isNotNull);
+    expect(section.argumentList, isNotNull);
+    expect(section.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseCascadeSection_p() {
+    Expression expression = parseCascadeSection('..a');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as PropertyAccess;
+    expect(section.target, isNull);
+    expect(section.operator, isNotNull);
+    expect(section.propertyName, isNotNull);
+  }
+
+  void test_parseCascadeSection_p_assign() {
+    Expression expression = parseCascadeSection('..a = 3');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as AssignmentExpression;
+    expect(section.leftHandSide, isNotNull);
+    expect(section.operator, isNotNull);
+    Expression rhs = section.rightHandSide;
+    expect(rhs, isNotNull);
+  }
+
+  void test_parseCascadeSection_p_assign_withCascade() {
+    Expression expression = parseCascadeSection('..a = 3..m()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as AssignmentExpression;
+    expect(section.leftHandSide, isNotNull);
+    expect(section.operator, isNotNull);
+    Expression rhs = section.rightHandSide;
+    expect(rhs, isIntegerLiteral);
+  }
+
+  void test_parseCascadeSection_p_assign_withCascade_typeArguments() {
+    Expression expression = parseCascadeSection('..a = 3..m<E>()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as AssignmentExpression;
+    expect(section.leftHandSide, isNotNull);
+    expect(section.operator, isNotNull);
+    Expression rhs = section.rightHandSide;
+    expect(rhs, isIntegerLiteral);
+  }
+
+  void test_parseCascadeSection_p_builtIn() {
+    Expression expression = parseCascadeSection('..as');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as PropertyAccess;
+    expect(section.target, isNull);
+    expect(section.operator, isNotNull);
+    expect(section.propertyName, isNotNull);
+  }
+
+  void test_parseCascadeSection_pa() {
+    Expression expression = parseCascadeSection('..a(b)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as MethodInvocation;
+    expect(section.target, isNull);
+    expect(section.operator, isNotNull);
+    expect(section.methodName, isNotNull);
+    expect(section.typeArguments, isNull);
+    expect(section.argumentList, isNotNull);
+    expect(section.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseCascadeSection_pa_typeArguments() {
+    Expression expression = parseCascadeSection('..a<E>(b)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as MethodInvocation;
+    expect(section.target, isNull);
+    expect(section.operator, isNotNull);
+    expect(section.methodName, isNotNull);
+    expect(section.typeArguments, isNotNull);
+    expect(section.argumentList, isNotNull);
+    expect(section.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseCascadeSection_paa() {
+    Expression expression = parseCascadeSection('..a(b)(c)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as FunctionExpressionInvocation;
+    expect(section.function, isMethodInvocation);
+    expect(section.typeArguments, isNull);
+    expect(section.argumentList, isNotNull);
+    expect(section.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseCascadeSection_paa_typeArguments() {
+    Expression expression = parseCascadeSection('..a<E>(b)<F>(c)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as FunctionExpressionInvocation;
+    expect(section.function, isMethodInvocation);
+    expect(section.typeArguments, isNotNull);
+    expect(section.argumentList, isNotNull);
+    expect(section.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseCascadeSection_paapaa() {
+    Expression expression = parseCascadeSection('..a(b)(c).d(e)(f)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as FunctionExpressionInvocation;
+    expect(section.function, isMethodInvocation);
+    expect(section.typeArguments, isNull);
+    expect(section.argumentList, isNotNull);
+    expect(section.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseCascadeSection_paapaa_typeArguments() {
+    Expression expression =
+        parseCascadeSection('..a<E>(b)<F>(c).d<G>(e)<H>(f)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as FunctionExpressionInvocation;
+    expect(section.function, isMethodInvocation);
+    expect(section.typeArguments, isNotNull);
+    expect(section.argumentList, isNotNull);
+    expect(section.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseCascadeSection_pap() {
+    Expression expression = parseCascadeSection('..a(b).c');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as PropertyAccess;
+    expect(section.target, isNotNull);
+    expect(section.operator, isNotNull);
+    expect(section.propertyName, isNotNull);
+  }
+
+  void test_parseCascadeSection_pap_typeArguments() {
+    Expression expression = parseCascadeSection('..a<E>(b).c');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var section = expression as PropertyAccess;
+    expect(section.target, isNotNull);
+    expect(section.operator, isNotNull);
+    expect(section.propertyName, isNotNull);
+  }
+
+  void test_parseConditionalExpression() {
+    ConditionalExpression expression = parseConditionalExpression('x ? y : z');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.condition, isNotNull);
+    expect(expression.question, isNotNull);
+    expect(expression.thenExpression, isNotNull);
+    expect(expression.colon, isNotNull);
+    expect(expression.elseExpression, isNotNull);
+  }
+
+  void test_parseConstExpression_instanceCreation() {
+    Expression expression = parseConstExpression('const A()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression, isInstanceCreationExpression);
+    InstanceCreationExpression instanceCreation = expression;
+    expect(instanceCreation.keyword, isNotNull);
+    ConstructorName name = instanceCreation.constructorName;
+    expect(name, isNotNull);
+    expect(name.type, isNotNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+    expect(instanceCreation.argumentList, isNotNull);
+  }
+
+  void test_parseConstExpression_listLiteral_typed() {
+    Expression expression = parseConstExpression('const <A> []');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as ListLiteral;
+    expect(literal.constKeyword, isNotNull);
+    expect(literal.typeArguments, isNotNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseConstExpression_listLiteral_untyped() {
+    Expression expression = parseConstExpression('const []');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as ListLiteral;
+    expect(literal.constKeyword, isNotNull);
+    expect(literal.typeArguments, isNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseConstExpression_mapLiteral_typed() {
+    Expression expression = parseConstExpression('const <A, B> {}');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SetOrMapLiteral;
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+    expect(literal.typeArguments, isNotNull);
+  }
+
+  void test_parseConstExpression_mapLiteral_typed_missingGt() {
+    Expression expression = parseExpression('const <A, B {}',
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1)]);
+    expect(expression, isNotNull);
+    var literal = expression as SetOrMapLiteral;
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+    expect(literal.typeArguments, isNotNull);
+  }
+
+  void test_parseConstExpression_mapLiteral_untyped() {
+    Expression expression = parseConstExpression('const {}');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SetOrMapLiteral;
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+    expect(literal.typeArguments, isNull);
+  }
+
+  void test_parseConstructorInitializer_functionExpression() {
+    // https://github.com/dart-lang/sdk/issues/37414
+    parseCompilationUnit('class C { C.n() : this()(); }', errors: [
+      expectedError(ParserErrorCode.INVALID_INITIALIZER, 18, 8),
+    ]);
+  }
+
+  void test_parseEqualityExpression_normal() {
+    BinaryExpression expression = parseEqualityExpression('x == y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.leftOperand, isNotNull);
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.EQ_EQ);
+    expect(expression.rightOperand, isNotNull);
+  }
+
+  void test_parseEqualityExpression_super() {
+    BinaryExpression expression = parseEqualityExpression('super == y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.leftOperand, isSuperExpression);
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.EQ_EQ);
+    expect(expression.rightOperand, isNotNull);
+  }
+
+  void test_parseExpression_assign() {
+    // TODO(brianwilkerson) Implement more tests for this method.
+    Expression expression = parseExpression('x = y');
+    var assignmentExpression = expression as AssignmentExpression;
+    expect(assignmentExpression.leftHandSide, isNotNull);
+    expect(assignmentExpression.operator, isNotNull);
+    expect(assignmentExpression.operator.type, TokenType.EQ);
+    expect(assignmentExpression.rightHandSide, isNotNull);
+  }
+
+  void test_parseExpression_assign_compound() {
+    if (AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
+      Expression expression = parseExpression('x ||= y');
+      var assignmentExpression = expression as AssignmentExpression;
+      expect(assignmentExpression.leftHandSide, isNotNull);
+      expect(assignmentExpression.operator, isNotNull);
+      expect(assignmentExpression.operator.type, TokenType.BAR_BAR_EQ);
+      expect(assignmentExpression.rightHandSide, isNotNull);
+    }
+  }
+
+  void test_parseExpression_comparison() {
+    Expression expression = parseExpression('--a.b == c');
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.EQ_EQ);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseExpression_constAndTypeParameters() {
+    Expression expression = parseExpression('const <E>', codes: [
+      // TODO(danrubel): Improve this error message.
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    expect(expression, isNotNull);
+  }
+
+  void test_parseExpression_function_async() {
+    Expression expression = parseExpression('() async {}');
+    var functionExpression = expression as FunctionExpression;
+    expect(functionExpression.body, isNotNull);
+    expect(functionExpression.body.isAsynchronous, isTrue);
+    expect(functionExpression.body.isGenerator, isFalse);
+    expect(functionExpression.parameters, isNotNull);
+  }
+
+  void test_parseExpression_function_asyncStar() {
+    Expression expression = parseExpression('() async* {}');
+    var functionExpression = expression as FunctionExpression;
+    expect(functionExpression.body, isNotNull);
+    expect(functionExpression.body.isAsynchronous, isTrue);
+    expect(functionExpression.body.isGenerator, isTrue);
+    expect(functionExpression.parameters, isNotNull);
+  }
+
+  void test_parseExpression_function_sync() {
+    Expression expression = parseExpression('() {}');
+    var functionExpression = expression as FunctionExpression;
+    expect(functionExpression.body, isNotNull);
+    expect(functionExpression.body.isAsynchronous, isFalse);
+    expect(functionExpression.body.isGenerator, isFalse);
+    expect(functionExpression.parameters, isNotNull);
+  }
+
+  void test_parseExpression_function_syncStar() {
+    Expression expression = parseExpression('() sync* {}');
+    var functionExpression = expression as FunctionExpression;
+    expect(functionExpression.body, isNotNull);
+    expect(functionExpression.body.isAsynchronous, isFalse);
+    expect(functionExpression.body.isGenerator, isTrue);
+    expect(functionExpression.parameters, isNotNull);
+  }
+
+  void test_parseExpression_invokeFunctionExpression() {
+    Expression expression = parseExpression('(a) {return a + a;} (3)');
+    var invocation = expression as FunctionExpressionInvocation;
+    expect(invocation.function, isFunctionExpression);
+    FunctionExpression functionExpression =
+        invocation.function as FunctionExpression;
+    expect(functionExpression.parameters, isNotNull);
+    expect(functionExpression.body, isNotNull);
+    expect(invocation.typeArguments, isNull);
+    ArgumentList list = invocation.argumentList;
+    expect(list, isNotNull);
+    expect(list.arguments, hasLength(1));
+  }
+
+  void test_parseExpression_nonAwait() {
+    Expression expression = parseExpression('await()');
+    var invocation = expression as MethodInvocation;
+    expect(invocation.methodName.name, 'await');
+    expect(invocation.typeArguments, isNull);
+    expect(invocation.argumentList, isNotNull);
+  }
+
+  void test_parseExpression_sendWithTypeParam_afterIndex() {
+    final unit = parseCompilationUnit('main() { factories[C]<num, int>(); }');
+    expect(unit.declarations, hasLength(1));
+    FunctionDeclaration mainMethod = unit.declarations[0];
+    BlockFunctionBody body = mainMethod.functionExpression.body;
+    NodeList<Statement> statements = body.block.statements;
+    expect(statements, hasLength(1));
+    ExpressionStatement statement = statements[0];
+    FunctionExpressionInvocation expression = statement.expression;
+
+    IndexExpression function = expression.function;
+    SimpleIdentifier target = function.target;
+    expect(target.name, 'factories');
+    SimpleIdentifier index = function.index;
+    expect(index.name, 'C');
+
+    NodeList<TypeAnnotation> typeArguments = expression.typeArguments.arguments;
+    expect(typeArguments, hasLength(2));
+    expect((typeArguments[0] as NamedType).name.name, 'num');
+    expect((typeArguments[1] as NamedType).name.name, 'int');
+
+    expect(expression.argumentList.arguments, hasLength(0));
+  }
+
+  void test_parseExpression_sendWithTypeParam_afterSend() {
+    final unit = parseCompilationUnit('main() { factories(C)<num, int>(); }');
+    expect(unit.declarations, hasLength(1));
+    FunctionDeclaration mainMethod = unit.declarations[0];
+    BlockFunctionBody body = mainMethod.functionExpression.body;
+    NodeList<Statement> statements = body.block.statements;
+    expect(statements, hasLength(1));
+    ExpressionStatement statement = statements[0];
+    FunctionExpressionInvocation expression = statement.expression;
+
+    MethodInvocation invocation = expression.function;
+    expect(invocation.methodName.name, 'factories');
+    NodeList<Expression> invocationArguments =
+        invocation.argumentList.arguments;
+    expect(invocationArguments, hasLength(1));
+    SimpleIdentifier index = invocationArguments[0];
+    expect(index.name, 'C');
+
+    NodeList<TypeAnnotation> typeArguments = expression.typeArguments.arguments;
+    expect(typeArguments, hasLength(2));
+    expect((typeArguments[0] as NamedType).name.name, 'num');
+    expect((typeArguments[1] as NamedType).name.name, 'int');
+
+    expect(expression.argumentList.arguments, hasLength(0));
+  }
+
+  void test_parseExpression_superMethodInvocation() {
+    Expression expression = parseExpression('super.m()');
+    var invocation = expression as MethodInvocation;
+    expect(invocation.target, isNotNull);
+    expect(invocation.methodName, isNotNull);
+    expect(invocation.typeArguments, isNull);
+    expect(invocation.argumentList, isNotNull);
+  }
+
+  void test_parseExpression_superMethodInvocation_typeArguments() {
+    Expression expression = parseExpression('super.m<E>()');
+    var invocation = expression as MethodInvocation;
+    expect(invocation.target, isNotNull);
+    expect(invocation.methodName, isNotNull);
+    expect(invocation.typeArguments, isNotNull);
+    expect(invocation.argumentList, isNotNull);
+  }
+
+  void test_parseExpression_superMethodInvocation_typeArguments_chained() {
+    Expression expression = parseExpression('super.b.c<D>()');
+    MethodInvocation invocation = expression as MethodInvocation;
+    Expression target = invocation.target;
+    expect(target, isPropertyAccess);
+    expect(invocation.methodName, isNotNull);
+    expect(invocation.methodName.name, 'c');
+    expect(invocation.typeArguments, isNotNull);
+    expect(invocation.argumentList, isNotNull);
+  }
+
+  void test_parseExpressionList_multiple() {
+    List<Expression> result = parseExpressionList('1, 2, 3');
+    expect(result, isNotNull);
+    assertNoErrors();
+    expect(result, hasLength(3));
+  }
+
+  void test_parseExpressionList_single() {
+    List<Expression> result = parseExpressionList('1');
+    expect(result, isNotNull);
+    assertNoErrors();
+    expect(result, hasLength(1));
+  }
+
+  void test_parseExpressionWithoutCascade_assign() {
+    // TODO(brianwilkerson) Implement more tests for this method.
+    Expression expression = parseExpressionWithoutCascade('x = y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var assignmentExpression = expression as AssignmentExpression;
+    expect(assignmentExpression.leftHandSide, isNotNull);
+    expect(assignmentExpression.operator, isNotNull);
+    expect(assignmentExpression.operator.type, TokenType.EQ);
+    expect(assignmentExpression.rightHandSide, isNotNull);
+  }
+
+  void test_parseExpressionWithoutCascade_comparison() {
+    Expression expression = parseExpressionWithoutCascade('--a.b == c');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.EQ_EQ);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseExpressionWithoutCascade_superMethodInvocation() {
+    Expression expression = parseExpressionWithoutCascade('super.m()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var invocation = expression as MethodInvocation;
+    expect(invocation.target, isNotNull);
+    expect(invocation.methodName, isNotNull);
+    expect(invocation.typeArguments, isNull);
+    expect(invocation.argumentList, isNotNull);
+  }
+
+  void
+      test_parseExpressionWithoutCascade_superMethodInvocation_typeArguments() {
+    Expression expression = parseExpressionWithoutCascade('super.m<E>()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var invocation = expression as MethodInvocation;
+    expect(invocation.target, isNotNull);
+    expect(invocation.methodName, isNotNull);
+    expect(invocation.typeArguments, isNotNull);
+    expect(invocation.argumentList, isNotNull);
+  }
+
+  void test_parseFunctionExpression_body_inExpression() {
+    FunctionExpression expression = parseFunctionExpression('(int i) => i++');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.body, isNotNull);
+    expect(expression.typeParameters, isNull);
+    expect(expression.parameters, isNotNull);
+    expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
+  }
+
+  void test_parseFunctionExpression_constAndTypeParameters2() {
+    FunctionExpression expression =
+        parseFunctionExpression('const <E>(E i) => i++');
+    expect(expression, isNotNull);
+    assertErrorsWithCodes([ParserErrorCode.UNEXPECTED_TOKEN]);
+    expect(expression.body, isNotNull);
+    expect(expression.typeParameters, isNotNull);
+    expect(expression.parameters, isNotNull);
+    expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
+  }
+
+  void test_parseFunctionExpression_functionInPlaceOfTypeName() {
+    Expression expression = parseExpression('<test(' ', (){});>[0, 1, 2]',
+        codes: [ParserErrorCode.EXPECTED_TOKEN]);
+    expect(expression, isNotNull);
+    ListLiteral literal = expression;
+    expect(literal.typeArguments.arguments, hasLength(1));
+  }
+
+  void test_parseFunctionExpression_typeParameters() {
+    FunctionExpression expression = parseFunctionExpression('<E>(E i) => i++');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.body, isNotNull);
+    expect(expression.typeParameters, isNotNull);
+    expect(expression.parameters, isNotNull);
+    expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
+  }
+
+  void test_parseInstanceCreationExpression_qualifiedType() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    InstanceCreationExpression expression =
+        parseInstanceCreationExpression('A.B()', token);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type.name.name, 'A.B');
+    expect(type.typeArguments, isNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void test_parseInstanceCreationExpression_qualifiedType_named() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    InstanceCreationExpression expression =
+        parseInstanceCreationExpression('A.B.c()', token);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(type.typeArguments, isNull);
+    expect(name.period, isNotNull);
+    expect(name.name, isNotNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void
+      test_parseInstanceCreationExpression_qualifiedType_named_typeArguments() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    InstanceCreationExpression expression =
+        parseInstanceCreationExpression('A.B<E>.c()', token);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(type.typeArguments.arguments, hasLength(1));
+    expect(name.period, isNotNull);
+    expect(name.name, isNotNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void test_parseInstanceCreationExpression_qualifiedType_typeArguments() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    InstanceCreationExpression expression =
+        parseInstanceCreationExpression('A.B<E>()', token);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(type.typeArguments.arguments, hasLength(1));
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void test_parseInstanceCreationExpression_type() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    InstanceCreationExpression expression =
+        parseInstanceCreationExpression('A()', token);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(type.typeArguments, isNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void test_parseInstanceCreationExpression_type_named() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    InstanceCreationExpression expression =
+        parseInstanceCreationExpression('A.c()', token);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(type.typeArguments, isNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void test_parseInstanceCreationExpression_type_named_typeArguments() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    InstanceCreationExpressionImpl expression =
+        parseInstanceCreationExpression('A<B>.c()', token);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(type.typeArguments.arguments, hasLength(1));
+    expect(name.period, isNotNull);
+    expect(name.name, isNotNull);
+    expect(expression.argumentList, isNotNull);
+    expect(expression.typeArguments, isNull);
+  }
+
+  void test_parseInstanceCreationExpression_type_named_typeArguments_34403() {
+    InstanceCreationExpressionImpl expression =
+        parseExpression('new a.b.c<C>()', errors: [
+      expectedError(
+          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR, 8, 1)
+    ]);
+    expect(expression, isNotNull);
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(type.typeArguments, isNull);
+    expect(name.period, isNotNull);
+    expect(name.name, isNotNull);
+    expect(expression.argumentList, isNotNull);
+    expect(expression.typeArguments.arguments, hasLength(1));
+  }
+
+  void test_parseInstanceCreationExpression_type_typeArguments() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
+    InstanceCreationExpression expression =
+        parseInstanceCreationExpression('A<B>()', token);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword.keyword, Keyword.NEW);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    TypeName type = name.type;
+    expect(type, isNotNull);
+    expect(type.typeArguments.arguments, hasLength(1));
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void test_parseListLiteral_empty_oneToken() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.CONST);
+    ListLiteral literal = parseListLiteral(token, null, '[]');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.constKeyword.keyword, Keyword.CONST);
+    expect(literal.typeArguments, isNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseListLiteral_empty_oneToken_withComment() {
+    ListLiteral literal = parseListLiteral(null, null, '/* 0 */ []');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.constKeyword, isNull);
+    expect(literal.typeArguments, isNull);
+    Token leftBracket = literal.leftBracket;
+    expect(leftBracket, isNotNull);
+    expect(leftBracket.precedingComments, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseListLiteral_empty_twoTokens() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.CONST);
+    ListLiteral literal = parseListLiteral(token, null, '[ ]');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.constKeyword.keyword, Keyword.CONST);
+    expect(literal.typeArguments, isNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseListLiteral_multiple() {
+    ListLiteral literal = parseListLiteral(null, null, '[1, 2, 3]');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.constKeyword, isNull);
+    expect(literal.typeArguments, isNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(3));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseListLiteral_single() {
+    ListLiteral literal = parseListLiteral(null, null, '[1]');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.constKeyword, isNull);
+    expect(literal.typeArguments, isNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(1));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseListLiteral_single_withTypeArgument() {
+    ListLiteral literal = parseListLiteral(null, '<int>', '[1]');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.constKeyword, isNull);
+    expect(literal.typeArguments, isNotNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(1));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseListOrMapLiteral_list_noType() {
+    TypedLiteral literal = parseListOrMapLiteral(null, '[1]');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    var listLiteral = literal as ListLiteral;
+    expect(listLiteral.constKeyword, isNull);
+    expect(listLiteral.typeArguments, isNull);
+    expect(listLiteral.leftBracket, isNotNull);
+    expect(listLiteral.elements, hasLength(1));
+    expect(listLiteral.rightBracket, isNotNull);
+  }
+
+  void test_parseListOrMapLiteral_list_type() {
+    TypedLiteral literal = parseListOrMapLiteral(null, '<int> [1]');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    var listLiteral = literal as ListLiteral;
+    expect(listLiteral.constKeyword, isNull);
+    expect(listLiteral.typeArguments, isNotNull);
+    expect(listLiteral.leftBracket, isNotNull);
+    expect(listLiteral.elements, hasLength(1));
+    expect(listLiteral.rightBracket, isNotNull);
+  }
+
+  void test_parseListOrMapLiteral_map_noType() {
+    TypedLiteral literal = parseListOrMapLiteral(null, "{'1' : 1}");
+    expect(literal, isNotNull);
+    assertNoErrors();
+    var mapLiteral = literal as SetOrMapLiteral;
+    expect(mapLiteral.constKeyword, isNull);
+    expect(mapLiteral.typeArguments, isNull);
+    expect(mapLiteral.leftBracket, isNotNull);
+    expect(mapLiteral.elements, hasLength(1));
+    expect(mapLiteral.rightBracket, isNotNull);
+  }
+
+  void test_parseListOrMapLiteral_map_type() {
+    TypedLiteral literal =
+        parseListOrMapLiteral(null, "<String, int> {'1' : 1}");
+    expect(literal, isNotNull);
+    assertNoErrors();
+    var mapLiteral = literal as SetOrMapLiteral;
+    expect(mapLiteral.constKeyword, isNull);
+    expect(mapLiteral.typeArguments, isNotNull);
+    expect(mapLiteral.leftBracket, isNotNull);
+    expect(mapLiteral.elements, hasLength(1));
+    expect(mapLiteral.rightBracket, isNotNull);
+  }
+
+  void test_parseLogicalAndExpression() {
+    Expression expression = parseLogicalAndExpression('x && y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.AMPERSAND_AMPERSAND);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseLogicalOrExpression() {
+    Expression expression = parseLogicalOrExpression('x || y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.BAR_BAR);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseMapLiteral_empty() {
+    Token token = TokenFactory.tokenFromKeyword(Keyword.CONST);
+    SetOrMapLiteral literal = parseMapLiteral(token, '<String, int>', '{}');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.constKeyword.keyword, Keyword.CONST);
+    expect(literal.typeArguments, isNotNull);
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(0));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseMapLiteral_multiple() {
+    SetOrMapLiteral literal = parseMapLiteral(null, null, "{'a' : b, 'x' : y}");
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(2));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseMapLiteral_multiple_trailing_comma() {
+    SetOrMapLiteral literal =
+        parseMapLiteral(null, null, "{'a' : b, 'x' : y,}");
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(2));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseMapLiteral_single() {
+    SetOrMapLiteral literal = parseMapLiteral(null, null, "{'x' : y}");
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.leftBracket, isNotNull);
+    expect(literal.elements, hasLength(1));
+    expect(literal.rightBracket, isNotNull);
+  }
+
+  void test_parseMapLiteralEntry_complex() {
+    MapLiteralEntry entry = parseMapLiteralEntry('2 + 2 : y');
+    expect(entry, isNotNull);
+    assertNoErrors();
+    expect(entry.key, isNotNull);
+    expect(entry.separator, isNotNull);
+    expect(entry.value, isNotNull);
+  }
+
+  void test_parseMapLiteralEntry_int() {
+    MapLiteralEntry entry = parseMapLiteralEntry('0 : y');
+    expect(entry, isNotNull);
+    assertNoErrors();
+    expect(entry.key, isNotNull);
+    expect(entry.separator, isNotNull);
+    expect(entry.value, isNotNull);
+  }
+
+  void test_parseMapLiteralEntry_string() {
+    MapLiteralEntry entry = parseMapLiteralEntry("'x' : y");
+    expect(entry, isNotNull);
+    assertNoErrors();
+    expect(entry.key, isNotNull);
+    expect(entry.separator, isNotNull);
+    expect(entry.value, isNotNull);
+  }
+
+  void test_parseMultiplicativeExpression_normal() {
+    Expression expression = parseMultiplicativeExpression('x * y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.STAR);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseMultiplicativeExpression_super() {
+    Expression expression = parseMultiplicativeExpression('super * y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isSuperExpression);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.STAR);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseNewExpression() {
+    InstanceCreationExpression expression = parseNewExpression('new A()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.keyword, isNotNull);
+    ConstructorName name = expression.constructorName;
+    expect(name, isNotNull);
+    expect(name.type, isNotNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+    expect(expression.argumentList, isNotNull);
+  }
+
+  void test_parsePostfixExpression_decrement() {
+    Expression expression = parsePostfixExpression('i--');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var postfixExpression = expression as PostfixExpression;
+    expect(postfixExpression.operand, isNotNull);
+    expect(postfixExpression.operator, isNotNull);
+    expect(postfixExpression.operator.type, TokenType.MINUS_MINUS);
+  }
+
+  void test_parsePostfixExpression_increment() {
+    Expression expression = parsePostfixExpression('i++');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var postfixExpression = expression as PostfixExpression;
+    expect(postfixExpression.operand, isNotNull);
+    expect(postfixExpression.operator, isNotNull);
+    expect(postfixExpression.operator.type, TokenType.PLUS_PLUS);
+  }
+
+  void test_parsePostfixExpression_none_indexExpression() {
+    Expression expression = parsePostfixExpression('a[0]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var indexExpression = expression as IndexExpression;
+    expect(indexExpression.target, isNotNull);
+    expect(indexExpression.index, isNotNull);
+  }
+
+  void test_parsePostfixExpression_none_methodInvocation() {
+    Expression expression = parsePostfixExpression('a.m()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var methodInvocation = expression as MethodInvocation;
+    expect(methodInvocation.target, isNotNull);
+    expect(methodInvocation.operator.type, TokenType.PERIOD);
+    expect(methodInvocation.methodName, isNotNull);
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_parsePostfixExpression_none_methodInvocation_question_dot() {
+    Expression expression = parsePostfixExpression('a?.m()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var methodInvocation = expression as MethodInvocation;
+    expect(methodInvocation.target, isNotNull);
+    expect(methodInvocation.operator.type, TokenType.QUESTION_PERIOD);
+    expect(methodInvocation.methodName, isNotNull);
+    expect(methodInvocation.typeArguments, isNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void
+      test_parsePostfixExpression_none_methodInvocation_question_dot_typeArguments() {
+    Expression expression = parsePostfixExpression('a?.m<E>()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var methodInvocation = expression as MethodInvocation;
+    expect(methodInvocation.target, isNotNull);
+    expect(methodInvocation.operator.type, TokenType.QUESTION_PERIOD);
+    expect(methodInvocation.methodName, isNotNull);
+    expect(methodInvocation.typeArguments, isNotNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_parsePostfixExpression_none_methodInvocation_typeArguments() {
+    Expression expression = parsePostfixExpression('a.m<E>()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var methodInvocation = expression as MethodInvocation;
+    expect(methodInvocation.target, isNotNull);
+    expect(methodInvocation.operator.type, TokenType.PERIOD);
+    expect(methodInvocation.methodName, isNotNull);
+    expect(methodInvocation.typeArguments, isNotNull);
+    expect(methodInvocation.argumentList, isNotNull);
+  }
+
+  void test_parsePostfixExpression_none_propertyAccess() {
+    Expression expression = parsePostfixExpression('a.b');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var identifier = expression as PrefixedIdentifier;
+    expect(identifier.prefix, isNotNull);
+    expect(identifier.identifier, isNotNull);
+  }
+
+  void test_parsePrefixedIdentifier_noPrefix() {
+    String lexeme = "bar";
+    Identifier identifier = parsePrefixedIdentifier(lexeme);
+    expect(identifier, isNotNull);
+    assertNoErrors();
+    var simpleIdentifier = identifier as SimpleIdentifier;
+    expect(simpleIdentifier.token, isNotNull);
+    expect(simpleIdentifier.name, lexeme);
+  }
+
+  void test_parsePrefixedIdentifier_prefix() {
+    String lexeme = "foo.bar";
+    Identifier identifier = parsePrefixedIdentifier(lexeme);
+    expect(identifier, isNotNull);
+    assertNoErrors();
+    var prefixedIdentifier = identifier as PrefixedIdentifier;
+    expect(prefixedIdentifier.prefix.name, "foo");
+    expect(prefixedIdentifier.period, isNotNull);
+    expect(prefixedIdentifier.identifier.name, "bar");
+  }
+
+  void test_parsePrimaryExpression_const() {
+    Expression expression = parsePrimaryExpression('const A()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_double() {
+    String doubleLiteral = "3.2e4";
+    Expression expression = parsePrimaryExpression(doubleLiteral);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as DoubleLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, double.parse(doubleLiteral));
+  }
+
+  void test_parsePrimaryExpression_false() {
+    Expression expression = parsePrimaryExpression('false');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as BooleanLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, isFalse);
+  }
+
+  void test_parsePrimaryExpression_function_arguments() {
+    Expression expression = parsePrimaryExpression('(int i) => i + 1');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var functionExpression = expression as FunctionExpression;
+    expect(functionExpression.parameters, isNotNull);
+    expect(functionExpression.body, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_function_noArguments() {
+    Expression expression = parsePrimaryExpression('() => 42');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var functionExpression = expression as FunctionExpression;
+    expect(functionExpression.parameters, isNotNull);
+    expect(functionExpression.body, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_genericFunctionExpression() {
+    Expression expression =
+        parsePrimaryExpression('<X, Y>(Map<X, Y> m, X x) => m[x]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var functionExpression = expression as FunctionExpression;
+    expect(functionExpression.typeParameters, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_hex() {
+    String hexLiteral = "3F";
+    Expression expression = parsePrimaryExpression('0x$hexLiteral');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as IntegerLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, int.parse(hexLiteral, radix: 16));
+  }
+
+  void test_parsePrimaryExpression_identifier() {
+    Expression expression = parsePrimaryExpression('a');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var identifier = expression as SimpleIdentifier;
+    expect(identifier, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_int() {
+    String intLiteral = "472";
+    Expression expression = parsePrimaryExpression(intLiteral);
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as IntegerLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, int.parse(intLiteral));
+  }
+
+  void test_parsePrimaryExpression_listLiteral() {
+    Expression expression = parsePrimaryExpression('[ ]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as ListLiteral;
+    expect(literal, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_listLiteral_index() {
+    Expression expression = parsePrimaryExpression('[]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as ListLiteral;
+    expect(literal, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_listLiteral_typed() {
+    Expression expression = parsePrimaryExpression('<A>[ ]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as ListLiteral;
+    expect(literal.typeArguments, isNotNull);
+    expect(literal.typeArguments.arguments, hasLength(1));
+  }
+
+  void test_parsePrimaryExpression_mapLiteral() {
+    Expression expression = parsePrimaryExpression('{}');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SetOrMapLiteral;
+    expect(literal.typeArguments, isNull);
+    expect(literal, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_mapLiteral_typed() {
+    Expression expression = parsePrimaryExpression('<A, B>{}');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SetOrMapLiteral;
+    expect(literal.typeArguments, isNotNull);
+    expect(literal.typeArguments.arguments, hasLength(2));
+  }
+
+  void test_parsePrimaryExpression_new() {
+    Expression expression = parsePrimaryExpression('new A()');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var creation = expression as InstanceCreationExpression;
+    expect(creation, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_null() {
+    Expression expression = parsePrimaryExpression('null');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression, isNullLiteral);
+    NullLiteral literal = expression;
+    expect(literal.literal, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_parenthesized() {
+    Expression expression = parsePrimaryExpression('(x)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var parens = expression as ParenthesizedExpression;
+    expect(parens, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_string() {
+    Expression expression = parsePrimaryExpression('"string"');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.isMultiline, isFalse);
+    expect(literal.isRaw, isFalse);
+    expect(literal.value, "string");
+  }
+
+  void test_parsePrimaryExpression_string_multiline() {
+    Expression expression = parsePrimaryExpression("'''string'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.isMultiline, isTrue);
+    expect(literal.isRaw, isFalse);
+    expect(literal.value, "string");
+  }
+
+  void test_parsePrimaryExpression_string_raw() {
+    Expression expression = parsePrimaryExpression("r'string'");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.isMultiline, isFalse);
+    expect(literal.isRaw, isTrue);
+    expect(literal.value, "string");
+  }
+
+  void test_parsePrimaryExpression_super() {
+    Expression expression = parseExpression('super.x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var propertyAccess = expression as PropertyAccess;
+    expect(propertyAccess.target is SuperExpression, isTrue);
+    expect(propertyAccess.operator, isNotNull);
+    expect(propertyAccess.operator.type, TokenType.PERIOD);
+    expect(propertyAccess.propertyName, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_this() {
+    Expression expression = parsePrimaryExpression('this');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var thisExpression = expression as ThisExpression;
+    expect(thisExpression.thisKeyword, isNotNull);
+  }
+
+  void test_parsePrimaryExpression_true() {
+    Expression expression = parsePrimaryExpression('true');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as BooleanLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, isTrue);
+  }
+
+  void test_parseRedirectingConstructorInvocation_named() {
+    var invocation = parseConstructorInitializer('this.a()')
+        as RedirectingConstructorInvocation;
+    assertNoErrors();
+    expect(invocation.argumentList, isNotNull);
+    expect(invocation.constructorName, isNotNull);
+    expect(invocation.thisKeyword, isNotNull);
+    expect(invocation.period, isNotNull);
+  }
+
+  void test_parseRedirectingConstructorInvocation_unnamed() {
+    var invocation = parseConstructorInitializer('this()')
+        as RedirectingConstructorInvocation;
+    assertNoErrors();
+    expect(invocation.argumentList, isNotNull);
+    expect(invocation.constructorName, isNull);
+    expect(invocation.thisKeyword, isNotNull);
+    expect(invocation.period, isNull);
+  }
+
+  void test_parseRelationalExpression_as_chained() {
+    AsExpression asExpression = parseExpression('x as Y as Z',
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)]);
+    expect(asExpression, isNotNull);
+    SimpleIdentifier identifier = asExpression.expression;
+    expect(identifier.name, 'x');
+    expect(asExpression.asOperator, isNotNull);
+    TypeName typeName = asExpression.type;
+    expect(typeName.name.name, 'Y');
+  }
+
+  void test_parseRelationalExpression_as_functionType_noReturnType() {
+    Expression expression = parseRelationalExpression('x as Function(int)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var asExpression = expression as AsExpression;
+    expect(asExpression.expression, isNotNull);
+    expect(asExpression.asOperator, isNotNull);
+    expect(asExpression.type, isGenericFunctionType);
+  }
+
+  void test_parseRelationalExpression_as_functionType_returnType() {
+    Expression expression =
+        parseRelationalExpression('x as String Function(int)');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var asExpression = expression as AsExpression;
+    expect(asExpression.expression, isNotNull);
+    expect(asExpression.asOperator, isNotNull);
+    expect(asExpression.type, isGenericFunctionType);
+  }
+
+  void test_parseRelationalExpression_as_generic() {
+    Expression expression = parseRelationalExpression('x as C<D>');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var asExpression = expression as AsExpression;
+    expect(asExpression.expression, isNotNull);
+    expect(asExpression.asOperator, isNotNull);
+    expect(asExpression.type, isTypeName);
+  }
+
+  void test_parseRelationalExpression_as_simple() {
+    Expression expression = parseRelationalExpression('x as Y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var asExpression = expression as AsExpression;
+    expect(asExpression.expression, isNotNull);
+    expect(asExpression.asOperator, isNotNull);
+    expect(asExpression.type, isTypeName);
+  }
+
+  void test_parseRelationalExpression_as_simple_function() {
+    Expression expression = parseRelationalExpression('x as Function');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var asExpression = expression as AsExpression;
+    expect(asExpression.expression, isNotNull);
+    expect(asExpression.asOperator, isNotNull);
+    expect(asExpression.type, isTypeName);
+  }
+
+  void test_parseRelationalExpression_is() {
+    Expression expression = parseRelationalExpression('x is y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var isExpression = expression as IsExpression;
+    expect(isExpression.expression, isNotNull);
+    expect(isExpression.isOperator, isNotNull);
+    expect(isExpression.notOperator, isNull);
+    expect(isExpression.type, isNotNull);
+  }
+
+  void test_parseRelationalExpression_is_chained() {
+    IsExpression isExpression = parseExpression('x is Y is! Z',
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)]);
+    expect(isExpression, isNotNull);
+    SimpleIdentifier identifier = isExpression.expression;
+    expect(identifier.name, 'x');
+    expect(isExpression.isOperator, isNotNull);
+    TypeName typeName = isExpression.type;
+    expect(typeName.name.name, 'Y');
+  }
+
+  void test_parseRelationalExpression_isNot() {
+    Expression expression = parseRelationalExpression('x is! y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var isExpression = expression as IsExpression;
+    expect(isExpression.expression, isNotNull);
+    expect(isExpression.isOperator, isNotNull);
+    expect(isExpression.notOperator, isNotNull);
+    expect(isExpression.type, isNotNull);
+  }
+
+  void test_parseRelationalExpression_normal() {
+    Expression expression = parseRelationalExpression('x < y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.LT);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseRelationalExpression_super() {
+    Expression expression = parseRelationalExpression('super < y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var binaryExpression = expression as BinaryExpression;
+    expect(binaryExpression.leftOperand, isNotNull);
+    expect(binaryExpression.operator, isNotNull);
+    expect(binaryExpression.operator.type, TokenType.LT);
+    expect(binaryExpression.rightOperand, isNotNull);
+  }
+
+  void test_parseRethrowExpression() {
+    RethrowExpression expression = parseRethrowExpression('rethrow');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.rethrowKeyword, isNotNull);
+  }
+
+  void test_parseShiftExpression_normal() {
+    BinaryExpression expression = parseShiftExpression('x << y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.leftOperand, isNotNull);
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.LT_LT);
+    expect(expression.rightOperand, isNotNull);
+  }
+
+  void test_parseShiftExpression_super() {
+    BinaryExpression expression = parseShiftExpression('super << y');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.leftOperand, isNotNull);
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.LT_LT);
+    expect(expression.rightOperand, isNotNull);
+  }
+
+  void test_parseSimpleIdentifier1_normalIdentifier() {
+    // TODO(brianwilkerson) Implement tests for this method.
+  }
+
+  void test_parseSimpleIdentifier_builtInIdentifier() {
+    String lexeme = "as";
+    SimpleIdentifier identifier = parseSimpleIdentifier(lexeme);
+    expect(identifier, isNotNull);
+    assertNoErrors();
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, lexeme);
+  }
+
+  void test_parseSimpleIdentifier_normalIdentifier() {
+    String lexeme = "foo";
+    SimpleIdentifier identifier = parseSimpleIdentifier(lexeme);
+    expect(identifier, isNotNull);
+    assertNoErrors();
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, lexeme);
+  }
+
+  void test_parseStringLiteral_adjacent() {
+    Expression expression = parseStringLiteral("'a' 'b'");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as AdjacentStrings;
+    NodeList<StringLiteral> strings = literal.strings;
+    expect(strings, hasLength(2));
+    StringLiteral firstString = strings[0];
+    StringLiteral secondString = strings[1];
+    expect((firstString as SimpleStringLiteral).value, "a");
+    expect((secondString as SimpleStringLiteral).value, "b");
+  }
+
+  void test_parseStringLiteral_endsWithInterpolation() {
+    Expression expression = parseStringLiteral(r"'x$y'");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var interpolation = expression as StringInterpolation;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], isInterpolationString);
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, 'x');
+    expect(interpolation.elements[1], isInterpolationExpression);
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.leftBracket.lexeme, '\$');
+    expect(element1.expression, isSimpleIdentifier);
+    expect(element1.rightBracket, isNull);
+    expect(interpolation.elements[2], isInterpolationString);
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, '');
+  }
+
+  void test_parseStringLiteral_interpolated() {
+    Expression expression = parseStringLiteral("'a \${b} c \$this d'");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression, isStringInterpolation);
+    StringInterpolation literal = expression;
+    NodeList<InterpolationElement> elements = literal.elements;
+    expect(elements, hasLength(5));
+    expect(elements[0] is InterpolationString, isTrue);
+    expect(elements[1] is InterpolationExpression, isTrue);
+    expect(elements[2] is InterpolationString, isTrue);
+    expect(elements[3] is InterpolationExpression, isTrue);
+    expect(elements[4] is InterpolationString, isTrue);
+    expect((elements[1] as InterpolationExpression).leftBracket.lexeme, '\${');
+    expect((elements[1] as InterpolationExpression).rightBracket.lexeme, '}');
+    expect((elements[3] as InterpolationExpression).leftBracket.lexeme, '\$');
+    expect((elements[3] as InterpolationExpression).rightBracket, isNull);
+  }
+
+  void test_parseStringLiteral_interpolated_void() {
+    Expression expression = parseStringLiteral(r"'<html>$void</html>'");
+    expect(expression, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 8, 4)
+    ]);
+    expect(expression, isStringInterpolation);
+    var literal = expression as StringInterpolation;
+    NodeList<InterpolationElement> elements = literal.elements;
+    expect(elements, hasLength(3));
+    expect(elements[0] is InterpolationString, isTrue);
+    expect(elements[1] is InterpolationExpression, isTrue);
+    expect(elements[2] is InterpolationString, isTrue);
+    expect((elements[1] as InterpolationExpression).leftBracket.lexeme, '\$');
+    expect((elements[1] as InterpolationExpression).rightBracket, isNull);
+  }
+
+  void test_parseStringLiteral_multiline_encodedSpace() {
+    Expression expression = parseStringLiteral("'''\\x20\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, " \na");
+  }
+
+  void test_parseStringLiteral_multiline_endsWithInterpolation() {
+    Expression expression = parseStringLiteral(r"'''x$y'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var interpolation = expression as StringInterpolation;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], isInterpolationString);
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, 'x');
+    expect(interpolation.elements[1], isInterpolationExpression);
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, isSimpleIdentifier);
+    expect(interpolation.elements[2], isInterpolationString);
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, '');
+  }
+
+  void test_parseStringLiteral_multiline_escapedBackslash() {
+    Expression expression = parseStringLiteral("'''\\\\\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "\\\na");
+  }
+
+  void test_parseStringLiteral_multiline_escapedBackslash_raw() {
+    Expression expression = parseStringLiteral("r'''\\\\\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "\\\\\na");
+  }
+
+  void test_parseStringLiteral_multiline_escapedEolMarker() {
+    Expression expression = parseStringLiteral("'''\\\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_escapedEolMarker_raw() {
+    Expression expression = parseStringLiteral("r'''\\\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_escapedSpaceAndEolMarker() {
+    Expression expression = parseStringLiteral("'''\\ \\\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_escapedSpaceAndEolMarker_raw() {
+    Expression expression = parseStringLiteral("r'''\\ \\\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_escapedTab() {
+    Expression expression = parseStringLiteral("'''\\t\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "\t\na");
+  }
+
+  void test_parseStringLiteral_multiline_escapedTab_raw() {
+    Expression expression = parseStringLiteral("r'''\\t\na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "\\t\na");
+  }
+
+  void test_parseStringLiteral_multiline_quoteAfterInterpolation() {
+    Expression expression = parseStringLiteral(r"""'''$x'y'''""");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var interpolation = expression as StringInterpolation;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], isInterpolationString);
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, '');
+    expect(interpolation.elements[1], isInterpolationExpression);
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, isSimpleIdentifier);
+    expect(interpolation.elements[2], isInterpolationString);
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, "'y");
+  }
+
+  void test_parseStringLiteral_multiline_startsWithInterpolation() {
+    Expression expression = parseStringLiteral(r"'''${x}y'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var interpolation = expression as StringInterpolation;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], isInterpolationString);
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, '');
+    expect(interpolation.elements[1], isInterpolationExpression);
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, isSimpleIdentifier);
+    expect(interpolation.elements[2], isInterpolationString);
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, 'y');
+  }
+
+  void test_parseStringLiteral_multiline_twoSpaces() {
+    Expression expression = parseStringLiteral("'''  \na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_twoSpaces_raw() {
+    Expression expression = parseStringLiteral("r'''  \na'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_multiline_untrimmed() {
+    Expression expression = parseStringLiteral("''' a\nb'''");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, " a\nb");
+  }
+
+  void test_parseStringLiteral_quoteAfterInterpolation() {
+    Expression expression = parseStringLiteral(r"""'$x"'""");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var interpolation = expression as StringInterpolation;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], isInterpolationString);
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, '');
+    expect(interpolation.elements[1], isInterpolationExpression);
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, isSimpleIdentifier);
+    expect(interpolation.elements[2], isInterpolationString);
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, '"');
+  }
+
+  void test_parseStringLiteral_single() {
+    Expression expression = parseStringLiteral("'a'");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var literal = expression as SimpleStringLiteral;
+    expect(literal.literal, isNotNull);
+    expect(literal.value, "a");
+  }
+
+  void test_parseStringLiteral_startsWithInterpolation() {
+    Expression expression = parseStringLiteral(r"'${x}y'");
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var interpolation = expression as StringInterpolation;
+    expect(interpolation.elements, hasLength(3));
+    expect(interpolation.elements[0], isInterpolationString);
+    InterpolationString element0 = interpolation.elements[0];
+    expect(element0.value, '');
+    expect(interpolation.elements[1], isInterpolationExpression);
+    InterpolationExpression element1 = interpolation.elements[1];
+    expect(element1.expression, isSimpleIdentifier);
+    expect(interpolation.elements[2], isInterpolationString);
+    InterpolationString element2 = interpolation.elements[2];
+    expect(element2.value, 'y');
+  }
+
+  void test_parseSuperConstructorInvocation_named() {
+    var invocation =
+        parseConstructorInitializer('super.a()') as SuperConstructorInvocation;
+    expect(invocation, isNotNull);
+    assertNoErrors();
+    expect(invocation.argumentList, isNotNull);
+    expect(invocation.constructorName, isNotNull);
+    expect(invocation.superKeyword, isNotNull);
+    expect(invocation.period, isNotNull);
+  }
+
+  void test_parseSuperConstructorInvocation_unnamed() {
+    var invocation =
+        parseConstructorInitializer('super()') as SuperConstructorInvocation;
+    assertNoErrors();
+    expect(invocation.argumentList, isNotNull);
+    expect(invocation.constructorName, isNull);
+    expect(invocation.superKeyword, isNotNull);
+    expect(invocation.period, isNull);
+  }
+
+  void test_parseSymbolLiteral_builtInIdentifier() {
+    SymbolLiteral literal = parseSymbolLiteral('#dynamic.static.abstract');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.poundSign, isNotNull);
+    List<Token> components = literal.components;
+    expect(components, hasLength(3));
+    expect(components[0].lexeme, "dynamic");
+    expect(components[1].lexeme, "static");
+    expect(components[2].lexeme, "abstract");
+  }
+
+  void test_parseSymbolLiteral_multiple() {
+    SymbolLiteral literal = parseSymbolLiteral('#a.b.c');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.poundSign, isNotNull);
+    List<Token> components = literal.components;
+    expect(components, hasLength(3));
+    expect(components[0].lexeme, "a");
+    expect(components[1].lexeme, "b");
+    expect(components[2].lexeme, "c");
+  }
+
+  void test_parseSymbolLiteral_operator() {
+    SymbolLiteral literal = parseSymbolLiteral('#==');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.poundSign, isNotNull);
+    List<Token> components = literal.components;
+    expect(components, hasLength(1));
+    expect(components[0].lexeme, "==");
+  }
+
+  void test_parseSymbolLiteral_single() {
+    SymbolLiteral literal = parseSymbolLiteral('#a');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.poundSign, isNotNull);
+    List<Token> components = literal.components;
+    expect(components, hasLength(1));
+    expect(components[0].lexeme, "a");
+  }
+
+  void test_parseSymbolLiteral_void() {
+    SymbolLiteral literal = parseSymbolLiteral('#void');
+    expect(literal, isNotNull);
+    assertNoErrors();
+    expect(literal.poundSign, isNotNull);
+    List<Token> components = literal.components;
+    expect(components, hasLength(1));
+    expect(components[0].lexeme, "void");
+  }
+
+  void test_parseThrowExpression() {
+    Expression expression = parseThrowExpression('throw x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var throwExpression = expression as ThrowExpression;
+    expect(throwExpression.throwKeyword, isNotNull);
+    expect(throwExpression.expression, isNotNull);
+  }
+
+  void test_parseThrowExpressionWithoutCascade() {
+    Expression expression = parseThrowExpressionWithoutCascade('throw x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    var throwExpression = expression as ThrowExpression;
+    expect(throwExpression.throwKeyword, isNotNull);
+    expect(throwExpression.expression, isNotNull);
+  }
+
+  void test_parseUnaryExpression_decrement_identifier_index() {
+    PrefixExpression expression = parseExpression('--a[0]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.MINUS_MINUS);
+    expect(expression.operand, isNotNull);
+    IndexExpression operand = expression.operand as IndexExpression;
+    expect(operand.realTarget, const TypeMatcher<SimpleIdentifier>());
+    expect(operand.index is IntegerLiteral, isTrue);
+  }
+
+  void test_parseUnaryExpression_decrement_normal() {
+    PrefixExpression expression = parseUnaryExpression('--x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.MINUS_MINUS);
+    expect(expression.operand, isNotNull);
+  }
+
+  @failingTest
+  void test_parseUnaryExpression_decrement_super() {
+    // TODO(danrubel) Reports a different error and different token stream.
+    // Expected: TokenType:<MINUS>
+    //   Actual: TokenType:<MINUS_MINUS>
+    PrefixExpression expression = parseUnaryExpression('--super');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.MINUS);
+    Expression innerExpression = expression.operand;
+    expect(innerExpression, isNotNull);
+    expect(innerExpression is PrefixExpression, isTrue);
+    PrefixExpression operand = innerExpression as PrefixExpression;
+    expect(operand.operator, isNotNull);
+    expect(operand.operator.type, TokenType.MINUS);
+    expect(operand.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_decrement_super_propertyAccess() {
+    PrefixExpression expression = parseUnaryExpression('--super.x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.MINUS_MINUS);
+    expect(expression.operand, isNotNull);
+    PropertyAccess operand = expression.operand as PropertyAccess;
+    expect(operand.target is SuperExpression, isTrue);
+    expect(operand.propertyName.name, "x");
+  }
+
+  @failingTest
+  void test_parseUnaryExpression_decrement_super_withComment() {
+    // TODO(danrubel) Reports a different error and different token stream.
+    // Expected: TokenType:<MINUS>
+    //   Actual: TokenType:<MINUS_MINUS>
+
+    PrefixExpression expression = parseUnaryExpression('/* 0 */ --super');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.MINUS);
+    expect(expression.operator.precedingComments, isNotNull);
+    Expression innerExpression = expression.operand;
+    expect(innerExpression, isNotNull);
+    expect(innerExpression is PrefixExpression, isTrue);
+    PrefixExpression operand = innerExpression as PrefixExpression;
+    expect(operand.operator, isNotNull);
+    expect(operand.operator.type, TokenType.MINUS);
+    expect(operand.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_increment_identifier_index() {
+    PrefixExpression expression = parseExpression('++a[0]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.PLUS_PLUS);
+    expect(expression.operand, isNotNull);
+    IndexExpression operand = expression.operand as IndexExpression;
+    expect(operand.realTarget, const TypeMatcher<SimpleIdentifier>());
+    expect(operand.index is IntegerLiteral, isTrue);
+  }
+
+  void test_parseUnaryExpression_increment_normal() {
+    PrefixExpression expression = parseUnaryExpression('++x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.PLUS_PLUS);
+    expect(expression.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_increment_super_index() {
+    PrefixExpression expression = parseUnaryExpression('++super[0]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.PLUS_PLUS);
+    expect(expression.operand, isNotNull);
+    IndexExpression operand = expression.operand as IndexExpression;
+    expect(operand.realTarget is SuperExpression, isTrue);
+    expect(operand.index is IntegerLiteral, isTrue);
+  }
+
+  void test_parseUnaryExpression_increment_super_propertyAccess() {
+    PrefixExpression expression = parseUnaryExpression('++super.x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.PLUS_PLUS);
+    expect(expression.operand, isNotNull);
+    PropertyAccess operand = expression.operand as PropertyAccess;
+    expect(operand.target is SuperExpression, isTrue);
+    expect(operand.propertyName.name, "x");
+  }
+
+  void test_parseUnaryExpression_minus_identifier_index() {
+    PrefixExpression expression = parseExpression('-a[0]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.MINUS);
+    expect(expression.operand, isNotNull);
+    IndexExpression operand = expression.operand as IndexExpression;
+    expect(operand.realTarget, const TypeMatcher<SimpleIdentifier>());
+    expect(operand.index is IntegerLiteral, isTrue);
+  }
+
+  void test_parseUnaryExpression_minus_normal() {
+    PrefixExpression expression = parseUnaryExpression('-x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.MINUS);
+    expect(expression.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_minus_super() {
+    PrefixExpression expression = parseUnaryExpression('-super');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.MINUS);
+    expect(expression.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_not_normal() {
+    PrefixExpression expression = parseUnaryExpression('!x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.BANG);
+    expect(expression.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_not_super() {
+    PrefixExpression expression = parseUnaryExpression('!super');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.BANG);
+    expect(expression.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_tilda_normal() {
+    PrefixExpression expression = parseUnaryExpression('~x');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.TILDE);
+    expect(expression.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_tilda_super() {
+    PrefixExpression expression = parseUnaryExpression('~super');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.TILDE);
+    expect(expression.operand, isNotNull);
+  }
+
+  void test_parseUnaryExpression_tilde_identifier_index() {
+    PrefixExpression expression = parseExpression('~a[0]');
+    expect(expression, isNotNull);
+    assertNoErrors();
+    expect(expression.operator, isNotNull);
+    expect(expression.operator.type, TokenType.TILDE);
+    expect(expression.operand, isNotNull);
+    IndexExpression operand = expression.operand as IndexExpression;
+    expect(operand.realTarget, const TypeMatcher<SimpleIdentifier>());
+    expect(operand.index is IntegerLiteral, isTrue);
+  }
+
+  void test_setLiteral() {
+    SetOrMapLiteral set = parseExpression('{3}');
+    expect(set.constKeyword, isNull);
+    expect(set.typeArguments, isNull);
+    expect(set.elements, hasLength(1));
+    IntegerLiteral value = set.elements[0];
+    expect(value.value, 3);
+  }
+
+  void test_setLiteral_const() {
+    SetOrMapLiteral set = parseExpression('const {3, 6}');
+    expect(set.constKeyword, isNotNull);
+    expect(set.typeArguments, isNull);
+    expect(set.elements, hasLength(2));
+    IntegerLiteral value1 = set.elements[0];
+    expect(value1.value, 3);
+    IntegerLiteral value2 = set.elements[1];
+    expect(value2.value, 6);
+  }
+
+  void test_setLiteral_const_typed() {
+    SetOrMapLiteral set = parseExpression('const <int>{3}');
+    expect(set.constKeyword, isNotNull);
+    expect(set.typeArguments.arguments, hasLength(1));
+    NamedType typeArg = set.typeArguments.arguments[0];
+    expect(typeArg.name.name, 'int');
+    expect(set.elements.length, 1);
+    IntegerLiteral value = set.elements[0];
+    expect(value.value, 3);
+  }
+
+  void test_setLiteral_nested_typeArgument() {
+    SetOrMapLiteral set = parseExpression('<Set<int>>{{3}}');
+    expect(set.constKeyword, isNull);
+    expect(set.typeArguments.arguments, hasLength(1));
+    NamedType typeArg1 = set.typeArguments.arguments[0];
+    expect(typeArg1.name.name, 'Set');
+    expect(typeArg1.typeArguments.arguments, hasLength(1));
+    NamedType typeArg2 = typeArg1.typeArguments.arguments[0];
+    expect(typeArg2.name.name, 'int');
+    expect(set.elements.length, 1);
+    SetOrMapLiteral intSet = set.elements[0];
+    expect(intSet.elements, hasLength(1));
+    IntegerLiteral value = intSet.elements[0];
+    expect(value.value, 3);
+  }
+
+  void test_setLiteral_typed() {
+    SetOrMapLiteral set = parseExpression('<int>{3}');
+    expect(set.constKeyword, isNull);
+    expect(set.typeArguments.arguments, hasLength(1));
+    NamedType typeArg = set.typeArguments.arguments[0];
+    expect(typeArg.name.name, 'int');
+    expect(set.elements.length, 1);
+    IntegerLiteral value = set.elements[0];
+    expect(value.value, 3);
+  }
+}
diff --git a/pkg/analyzer/test/generated/extension_methods_parser_test.dart b/pkg/analyzer/test/generated/extension_methods_parser_test.dart
new file mode 100644
index 0000000..e5b42d3
--- /dev/null
+++ b/pkg/analyzer/test/generated/extension_methods_parser_test.dart
@@ -0,0 +1,261 @@
+// 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/ast.dart' show CompilationUnitImpl;
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:pub_semver/src/version.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtensionMethodsParserTest);
+  });
+}
+
+@reflectiveTest
+class ExtensionMethodsParserTest extends FastaParserTestCase {
+  void test_complex_extends() {
+    var unit = parseCompilationUnit(
+        'extension E extends A with B, C implements D { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 4),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
+          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 32, 10),
+        ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'extends');
+    expect((extension.extendedType as NamedType).name.name, 'A');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_complex_implements() {
+    var unit = parseCompilationUnit('extension E implements C, D { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 24, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'implements');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_complex_type() {
+    var unit = parseCompilationUnit('extension E on C<T> { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    var namedType = extension.extendedType as NamedType;
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments.arguments, hasLength(1));
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_complex_type2() {
+    var unit = parseCompilationUnit('extension E<T> on C<T> { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    var namedType = extension.extendedType as NamedType;
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments.arguments, hasLength(1));
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_complex_type2_no_name() {
+    var unit = parseCompilationUnit('extension<T> on C<T> { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name, isNull);
+    expect(extension.onKeyword.lexeme, 'on');
+    var namedType = extension.extendedType as NamedType;
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments.arguments, hasLength(1));
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_constructor_named() {
+    var unit = parseCompilationUnit('''
+extension E on C {
+  E.named();
+}
+class C {}
+''', errors: [
+      expectedError(ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR, 21, 1),
+    ]);
+    expect(unit.declarations, hasLength(2));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_constructor_unnamed() {
+    var unit = parseCompilationUnit('''
+extension E on C {
+  E();
+}
+class C {}
+''', errors: [
+      expectedError(ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR, 21, 1),
+    ]);
+    expect(unit.declarations, hasLength(2));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on() {
+    var unit = parseCompilationUnit('extension E', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 11, 0),
+      expectedError(ParserErrorCode.EXPECTED_BODY, 11, 0),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, '');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on_withBlock() {
+    var unit = parseCompilationUnit('extension E {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, '');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_missing_on_withClassAndBlock() {
+    var unit = parseCompilationUnit('extension E C {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_parse_toplevel_member_called_late_calling_self() {
+    CompilationUnitImpl unit = parseCompilationUnit('void late() { late(); }',
+        featureSet: nonNullable);
+    FunctionDeclaration method = unit.declarations[0];
+
+    expect(method.documentationComment, isNull);
+    expect(method.externalKeyword, isNull);
+    expect(method.propertyKeyword, isNull);
+    expect(method.returnType, isNotNull);
+    expect(method.name.name, 'late');
+    expect(method.functionExpression, isNotNull);
+
+    BlockFunctionBody body = method.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    MethodInvocation invocation = statement.expression;
+    expect(invocation.operator, isNull);
+    expect(invocation.toSource(), 'late()');
+  }
+
+  void test_simple() {
+    var unit = parseCompilationUnit('extension E on C { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    var namedType = extension.extendedType as NamedType;
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments, isNull);
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_extends() {
+    var unit = parseCompilationUnit('extension E extends C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'extends');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_implements() {
+    var unit = parseCompilationUnit('extension E implements C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'implements');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_no_name() {
+    var unit = parseCompilationUnit('extension on C { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name, isNull);
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    var namedType = extension.extendedType as NamedType;
+    expect(namedType.name.name, 'C');
+    expect(namedType.typeArguments, isNull);
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_simple_not_enabled() {
+    parseCompilationUnit(
+      'extension E on C { }',
+      errors: [
+        expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 0, 9),
+        expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 15, 1)
+      ],
+      featureSet: FeatureSet.fromEnableFlags2(
+        sdkLanguageVersion: Version.parse('2.3.0'),
+        flags: [],
+      ),
+    );
+  }
+
+  void test_simple_with() {
+    var unit = parseCompilationUnit('extension E with C { }', errors: [
+      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 4),
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'with');
+    expect((extension.extendedType as NamedType).name.name, 'C');
+    expect(extension.members, hasLength(0));
+  }
+
+  void test_void_type() {
+    var unit = parseCompilationUnit('extension E on void { }');
+    expect(unit.declarations, hasLength(1));
+    var extension = unit.declarations[0] as ExtensionDeclaration;
+    expect(extension.name.name, 'E');
+    expect(extension.onKeyword.lexeme, 'on');
+    expect((extension.extendedType as NamedType).name.name, 'void');
+    expect(extension.members, hasLength(0));
+  }
+}
diff --git a/pkg/analyzer/test/generated/formal_parameter_parser_test.dart b/pkg/analyzer/test/generated/formal_parameter_parser_test.dart
new file mode 100644
index 0000000..da72d4b
--- /dev/null
+++ b/pkg/analyzer/test/generated/formal_parameter_parser_test.dart
@@ -0,0 +1,1425 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+import 'test_support.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FormalParameterParserTest);
+  });
+}
+
+/// The class [FormalParameterParserTest] defines parser tests that test
+/// the parsing of formal parameters.
+@reflectiveTest
+class FormalParameterParserTest extends FastaParserTestCase {
+  FormalParameter parseNNBDFormalParameter(String code, ParameterKind kind,
+      {List<ExpectedError> errors}) {
+    String parametersCode;
+    if (kind == ParameterKind.REQUIRED) {
+      parametersCode = '($code)';
+    } else if (kind == ParameterKind.POSITIONAL) {
+      parametersCode = '([$code])';
+    } else if (kind == ParameterKind.NAMED) {
+      parametersCode = '({$code})';
+    } else {
+      fail('$kind');
+    }
+    createParser(parametersCode, featureSet: nonNullable);
+    FormalParameterList list =
+        parserProxy.parseFormalParameterList(inFunctionType: false);
+    assertErrors(errors: errors);
+    return list.parameters.single;
+  }
+
+  void test_fieldFormalParameter_function_nullable() {
+    var parameter =
+        parseNNBDFormalParameter('void this.a()?', ParameterKind.REQUIRED);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter functionParameter = parameter;
+    expect(functionParameter.type, isNotNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNotNull);
+    expect(functionParameter.endToken, functionParameter.question);
+  }
+
+  void test_functionTyped_named_nullable() {
+    ParameterKind kind = ParameterKind.NAMED;
+    var defaultParameter =
+        parseNNBDFormalParameter('a()? : null', kind) as DefaultFormalParameter;
+    var functionParameter =
+        defaultParameter.parameter as FunctionTypedFormalParameter;
+    assertNoErrors();
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.isNamed, isTrue);
+    expect(functionParameter.question, isNotNull);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_functionTyped_named_nullable_disabled() {
+    ParameterKind kind = ParameterKind.NAMED;
+    var defaultParameter = parseFormalParameter('a()? : null', kind,
+            featureSet: preNonNullable,
+            errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
+        as DefaultFormalParameter;
+    var functionParameter =
+        defaultParameter.parameter as FunctionTypedFormalParameter;
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.isNamed, isTrue);
+    expect(functionParameter.question, isNotNull);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_functionTyped_positional_nullable_disabled() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    var defaultParameter = parseFormalParameter('a()? = null', kind,
+            featureSet: preNonNullable,
+            errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
+        as DefaultFormalParameter;
+    var functionParameter =
+        defaultParameter.parameter as FunctionTypedFormalParameter;
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.isOptionalPositional, isTrue);
+    expect(functionParameter.question, isNotNull);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_functionTyped_required_nullable_disabled() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    var functionParameter = parseFormalParameter('a()?', kind,
+            featureSet: preNonNullable,
+            errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
+        as FunctionTypedFormalParameter;
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.isRequiredPositional, isTrue);
+    expect(functionParameter.question, isNotNull);
+  }
+
+  void test_parseConstructorParameter_this() {
+    parseCompilationUnit('''
+class C {
+  final int field;
+  C(this.field);
+}''');
+  }
+
+  void test_parseConstructorParameter_this_Function() {
+    parseCompilationUnit('''
+class C {
+  final Object Function(int, double) field;
+  C(String Function(num, Object) this.field);
+}''');
+  }
+
+  void test_parseConstructorParameter_this_int() {
+    parseCompilationUnit('''
+class C {
+  final int field;
+  C(int this.field);
+}''');
+  }
+
+  void test_parseFormalParameter_covariant_final_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseFormalParameter('covariant final a : null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_final_normal() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter = parseFormalParameter('covariant final a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_final_positional() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter =
+        parseFormalParameter('covariant final a = null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_final_type_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseFormalParameter('covariant final A a : null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_final_type_normal() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter =
+        parseFormalParameter('covariant final A a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_final_type_positional() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter =
+        parseFormalParameter('covariant final A a = null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_required_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseNNBDFormalParameter(
+        'covariant required A a : null', kind,
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 12, 8)]);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_type_function() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter =
+        parseFormalParameter('covariant String Function(int) a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isGenericFunctionType);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_type_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseFormalParameter('covariant A a : null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_type_normal() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter =
+        parseFormalParameter('covariant A<B<C>> a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_type_positional() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter =
+        parseFormalParameter('covariant A a = null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_var_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseFormalParameter('covariant var a : null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_var_normal() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter = parseFormalParameter('covariant var a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_covariant_var_positional() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter =
+        parseFormalParameter('covariant var a = null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_external() {
+    parseNNBDFormalParameter('external int i', ParameterKind.REQUIRED, errors: [
+      expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 1, 8),
+    ]);
+  }
+
+  void test_parseFormalParameter_final_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseFormalParameter('final a : null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_final_normal() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter = parseFormalParameter('final a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_final_positional() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter = parseFormalParameter('final a = null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_final_required_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseNNBDFormalParameter(
+        'final required a : null', kind,
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 8, 8)]);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_final_type_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseFormalParameter('final A a : null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_final_type_normal() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter = parseFormalParameter('final A a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_final_type_positional() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter = parseFormalParameter('final A a = null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_required_covariant_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseNNBDFormalParameter('required covariant A a : null', kind);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNotNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_required_final_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseNNBDFormalParameter('required final a : null', kind);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_required_type_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseNNBDFormalParameter('required A a : null', kind);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_required_var_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter =
+        parseNNBDFormalParameter('required var a : null', kind);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_type_function() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter =
+        parseFormalParameter('String Function(int) a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isGenericFunctionType);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_type_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseFormalParameter('A a : null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_type_named_noDefault() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseFormalParameter('A a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNull);
+    expect(defaultParameter.defaultValue, isNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_type_normal() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter = parseFormalParameter('A a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_type_positional() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter = parseFormalParameter('A a = null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_type_positional_noDefault() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter = parseFormalParameter('A a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNull);
+    expect(defaultParameter.defaultValue, isNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_var_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseFormalParameter('var a : null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameter_var_normal() {
+    ParameterKind kind = ParameterKind.REQUIRED;
+    FormalParameter parameter = parseFormalParameter('var a', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isRequired, isTrue);
+  }
+
+  void test_parseFormalParameter_var_positional() {
+    ParameterKind kind = ParameterKind.POSITIONAL;
+    FormalParameter parameter = parseFormalParameter('var a = null', kind);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isOptionalPositional, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isOptionalPositional, isTrue);
+  }
+
+  void test_parseFormalParameter_var_required_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    FormalParameter parameter = parseNNBDFormalParameter(
+        'var required a : null', kind,
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 8)]);
+    expect(parameter, isNotNull);
+    expect(parameter, isDefaultFormalParameter);
+    DefaultFormalParameter defaultParameter = parameter;
+    SimpleFormalParameter simpleParameter =
+        defaultParameter.parameter as SimpleFormalParameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.requiredKeyword, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.isNamed, isTrue);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseFormalParameterList_empty() {
+    FormalParameterList list = parseFormalParameterList('()');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(0));
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_named_multiple() {
+    FormalParameterList list =
+        parseFormalParameterList('({A a : 1, B b, C c : 3})');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.parameters, hasLength(3));
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_named_single() {
+    FormalParameterList list = parseFormalParameterList('({A a})');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.parameters, hasLength(1));
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_named_trailing_comma() {
+    FormalParameterList list = parseFormalParameterList('(A a, {B b,})');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.parameters, hasLength(2));
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_normal_multiple() {
+    FormalParameterList list = parseFormalParameterList('(A a, B b, C c)');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(3));
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_normal_named() {
+    FormalParameterList list = parseFormalParameterList('(A a, {B b})');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.parameters, hasLength(2));
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_normal_named_inFunctionType() {
+    FormalParameterList list =
+        parseFormalParameterList('(A, {B b})', inFunctionType: true);
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+    NodeList<FormalParameter> parameters = list.parameters;
+    expect(parameters, hasLength(2));
+
+    expect(parameters[0], isSimpleFormalParameter);
+    SimpleFormalParameter required = parameters[0];
+    expect(required.identifier, isNull);
+    expect(required.type, isTypeName);
+    expect((required.type as TypeName).name.name, 'A');
+
+    expect(parameters[1], isDefaultFormalParameter);
+    DefaultFormalParameter named = parameters[1];
+    expect(named.identifier, isNotNull);
+    expect(named.parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simple = named.parameter;
+    expect(simple.type, isTypeName);
+    expect((simple.type as TypeName).name.name, 'B');
+  }
+
+  void test_parseFormalParameterList_normal_positional() {
+    FormalParameterList list = parseFormalParameterList('(A a, [B b])');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.parameters, hasLength(2));
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_normal_single() {
+    FormalParameterList list = parseFormalParameterList('(A a)');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(1));
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_normal_single_Function() {
+    FormalParameterList list = parseFormalParameterList('(Function f)');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(1));
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_normal_single_trailing_comma() {
+    FormalParameterList list = parseFormalParameterList('(A a,)');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(1));
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_positional_multiple() {
+    FormalParameterList list =
+        parseFormalParameterList('([A a = null, B b, C c = null])');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.parameters, hasLength(3));
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_positional_single() {
+    FormalParameterList list = parseFormalParameterList('([A a = null])');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.parameters, hasLength(1));
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_positional_trailing_comma() {
+    FormalParameterList list = parseFormalParameterList('(A a, [B b,])');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNotNull);
+    expect(list.parameters, hasLength(2));
+    expect(list.rightDelimiter, isNotNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_prefixedType() {
+    FormalParameterList list = parseFormalParameterList('(io.File f)');
+    expect(list, isNotNull);
+    assertNoErrors();
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(1));
+    expect(list.parameters[0].toSource(), 'io.File f');
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_prefixedType_missingName() {
+    FormalParameterList list = parseFormalParameterList('(io.File)',
+        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]);
+    expect(list, isNotNull);
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(1));
+    // TODO(danrubel): Investigate and improve recovery of parameter type/name.
+    SimpleFormalParameter parameter = list.parameters[0];
+    expect(parameter.toSource(), 'io.File ');
+    expect(parameter.identifier.token.isSynthetic, isTrue);
+    TypeName type = parameter.type;
+    PrefixedIdentifier typeName = type.name;
+    expect(typeName.prefix.token.isSynthetic, isFalse);
+    expect(typeName.identifier.token.isSynthetic, isFalse);
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_prefixedType_partial() {
+    FormalParameterList list = parseFormalParameterList('(io.)', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
+    ]);
+    expect(list, isNotNull);
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(1));
+    // TODO(danrubel): Investigate and improve recovery of parameter type/name.
+    SimpleFormalParameter parameter = list.parameters[0];
+    expect(parameter.toSource(), 'io. ');
+    expect(parameter.identifier.token.isSynthetic, isTrue);
+    TypeName type = parameter.type;
+    PrefixedIdentifier typeName = type.name;
+    expect(typeName.prefix.token.isSynthetic, isFalse);
+    expect(typeName.identifier.token.isSynthetic, isTrue);
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseFormalParameterList_prefixedType_partial2() {
+    FormalParameterList list = parseFormalParameterList('(io.,a)', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
+    ]);
+    expect(list, isNotNull);
+    expect(list.leftParenthesis, isNotNull);
+    expect(list.leftDelimiter, isNull);
+    expect(list.parameters, hasLength(2));
+    expect(list.parameters[0].toSource(), 'io. ');
+    expect(list.parameters[1].toSource(), 'a');
+    expect(list.rightDelimiter, isNull);
+    expect(list.rightParenthesis, isNotNull);
+  }
+
+  void test_parseNormalFormalParameter_field_const_noType() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('const this.a',
+        errorCodes: [ParserErrorCode.EXTRANEOUS_MODIFIER]);
+    expect(parameter, isNotNull);
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNotNull);
+    expect(fieldParameter.type, isNull);
+    expect(fieldParameter.identifier, isNotNull);
+    expect(fieldParameter.parameters, isNull);
+  }
+
+  void test_parseNormalFormalParameter_field_const_type() {
+    NormalFormalParameter parameter = parseNormalFormalParameter(
+        'const A this.a',
+        errorCodes: [ParserErrorCode.EXTRANEOUS_MODIFIER]);
+    expect(parameter, isNotNull);
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNotNull);
+    expect(fieldParameter.type, isNotNull);
+    expect(fieldParameter.identifier, isNotNull);
+    expect(fieldParameter.parameters, isNull);
+  }
+
+  void test_parseNormalFormalParameter_field_final_noType() {
+    NormalFormalParameter parameter =
+        parseNormalFormalParameter('final this.a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNotNull);
+    expect(fieldParameter.type, isNull);
+    expect(fieldParameter.identifier, isNotNull);
+    expect(fieldParameter.parameters, isNull);
+  }
+
+  void test_parseNormalFormalParameter_field_final_type() {
+    NormalFormalParameter parameter =
+        parseNormalFormalParameter('final A this.a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNotNull);
+    expect(fieldParameter.type, isNotNull);
+    expect(fieldParameter.identifier, isNotNull);
+    expect(fieldParameter.parameters, isNull);
+  }
+
+  void test_parseNormalFormalParameter_field_function_nested() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('this.a(B b)');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNull);
+    expect(fieldParameter.type, isNull);
+    expect(fieldParameter.identifier, isNotNull);
+    FormalParameterList parameterList = fieldParameter.parameters;
+    expect(parameterList, isNotNull);
+    expect(parameterList.parameters, hasLength(1));
+  }
+
+  void test_parseNormalFormalParameter_field_function_noNested() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('this.a()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNull);
+    expect(fieldParameter.type, isNull);
+    expect(fieldParameter.identifier, isNotNull);
+    FormalParameterList parameterList = fieldParameter.parameters;
+    expect(parameterList, isNotNull);
+    expect(parameterList.parameters, hasLength(0));
+  }
+
+  void test_parseNormalFormalParameter_field_function_withDocComment() {
+    var parameter = parseNormalFormalParameter('/// Doc\nthis.f()');
+    expectCommentText(parameter.documentationComment, '/// Doc');
+  }
+
+  void test_parseNormalFormalParameter_field_noType() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('this.a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNull);
+    expect(fieldParameter.type, isNull);
+    expect(fieldParameter.identifier, isNotNull);
+    expect(fieldParameter.parameters, isNull);
+  }
+
+  void test_parseNormalFormalParameter_field_type() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('A this.a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNull);
+    expect(fieldParameter.type, isNotNull);
+    expect(fieldParameter.identifier, isNotNull);
+    expect(fieldParameter.parameters, isNull);
+  }
+
+  void test_parseNormalFormalParameter_field_var() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('var this.a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFieldFormalParameter);
+    FieldFormalParameter fieldParameter = parameter;
+    expect(fieldParameter.keyword, isNotNull);
+    expect(fieldParameter.type, isNull);
+    expect(fieldParameter.identifier, isNotNull);
+    expect(fieldParameter.parameters, isNull);
+  }
+
+  void test_parseNormalFormalParameter_field_withDocComment() {
+    var parameter = parseNormalFormalParameter('/// Doc\nthis.a');
+    expectCommentText(parameter.documentationComment, '/// Doc');
+  }
+
+  void test_parseNormalFormalParameter_function_named() {
+    ParameterKind kind = ParameterKind.NAMED;
+    var defaultParameter =
+        parseFormalParameter('a() : null', kind) as DefaultFormalParameter;
+    var functionParameter =
+        defaultParameter.parameter as FunctionTypedFormalParameter;
+    assertNoErrors();
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.isNamed, isTrue);
+    expect(functionParameter.question, isNull);
+    expect(defaultParameter.separator, isNotNull);
+    expect(defaultParameter.defaultValue, isNotNull);
+    expect(defaultParameter.isNamed, isTrue);
+  }
+
+  void test_parseNormalFormalParameter_function_noType() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('a()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
+  }
+
+  void test_parseNormalFormalParameter_function_noType_covariant() {
+    NormalFormalParameter parameter =
+        parseNormalFormalParameter('covariant a()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.covariantKeyword, isNotNull);
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
+  }
+
+  void test_parseNormalFormalParameter_function_noType_nullable() {
+    NormalFormalParameter parameter =
+        parseNNBDFormalParameter('a()?', ParameterKind.REQUIRED);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNotNull);
+    expect(functionParameter.endToken, functionParameter.question);
+  }
+
+  void test_parseNormalFormalParameter_function_noType_typeParameters() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('a<E>()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.returnType, isNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNotNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
+  }
+
+  void test_parseNormalFormalParameter_function_type() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('A a()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.returnType, isNotNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
+  }
+
+  void test_parseNormalFormalParameter_function_type_typeParameters() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('A a<E>()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.returnType, isNotNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNotNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
+  }
+
+  void test_parseNormalFormalParameter_function_typeVoid_covariant() {
+    NormalFormalParameter parameter =
+        parseNormalFormalParameter('covariant void a()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.covariantKeyword, isNotNull);
+    expect(functionParameter.returnType, isNotNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
+  }
+
+  void test_parseNormalFormalParameter_function_void() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('void a()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.returnType, isNotNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
+  }
+
+  void test_parseNormalFormalParameter_function_void_typeParameters() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('void a<E>()');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isFunctionTypedFormalParameter);
+    FunctionTypedFormalParameter functionParameter = parameter;
+    expect(functionParameter.returnType, isNotNull);
+    expect(functionParameter.identifier, isNotNull);
+    expect(functionParameter.typeParameters, isNotNull);
+    expect(functionParameter.parameters, isNotNull);
+    expect(functionParameter.question, isNull);
+  }
+
+  void test_parseNormalFormalParameter_function_withDocComment() {
+    var parameter = parseFormalParameter('/// Doc\nf()', ParameterKind.REQUIRED)
+        as FunctionTypedFormalParameter;
+    expectCommentText(parameter.documentationComment, '/// Doc');
+  }
+
+  void test_parseNormalFormalParameter_simple_const_noType() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('const a',
+        errorCodes: [ParserErrorCode.EXTRANEOUS_MODIFIER]);
+    expect(parameter, isNotNull);
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+  }
+
+  void test_parseNormalFormalParameter_simple_const_type() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('const A a',
+        errorCodes: [ParserErrorCode.EXTRANEOUS_MODIFIER]);
+    expect(parameter, isNotNull);
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+  }
+
+  void test_parseNormalFormalParameter_simple_final_noType() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('final a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+  }
+
+  void test_parseNormalFormalParameter_simple_final_type() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('final A a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.keyword, isNotNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+  }
+
+  void test_parseNormalFormalParameter_simple_noName() {
+    NormalFormalParameter parameter =
+        parseNormalFormalParameter('a', inFunctionType: true);
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.identifier, isNull);
+  }
+
+  void test_parseNormalFormalParameter_simple_noType() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+  }
+
+  void test_parseNormalFormalParameter_simple_noType_namedCovariant() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('covariant');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.covariantKeyword, isNull);
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNull);
+    expect(simpleParameter.identifier, isNotNull);
+  }
+
+  void test_parseNormalFormalParameter_simple_type() {
+    NormalFormalParameter parameter = parseNormalFormalParameter('A a');
+    expect(parameter, isNotNull);
+    assertNoErrors();
+    expect(parameter, isSimpleFormalParameter);
+    SimpleFormalParameter simpleParameter = parameter;
+    expect(simpleParameter.keyword, isNull);
+    expect(simpleParameter.type, isNotNull);
+    expect(simpleParameter.identifier, isNotNull);
+  }
+}
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index 6fd7955..0d4c949 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -20,6 +20,19 @@
 /// and analysis finishes without exceptions.
 @reflectiveTest
 class InvalidCodeTest extends PubPackageResolutionTest {
+  test_const_AwaitExpression() async {
+    await _assertCanBeAnalyzed(r'''
+const a = await b();
+''');
+  }
+
+  test_const_ForPartsWithExpression() async {
+    await _assertCanBeAnalyzed(r'''
+@A([for (;;) 0])
+void f() {}
+''');
+  }
+
   /// This code results in a method with the empty name, and the default
   /// constructor, which also has the empty name. The `Map` in `f` initializer
   /// references the empty name.
@@ -120,7 +133,7 @@
     await _assertCanBeAnalyzed(r'''
 typedef F = void Function(bool, int a(double b));
 ''');
-    var alias = findElement.functionTypeAlias('F');
+    var alias = findElement.typeAlias('F');
     assertType(
         alias.instantiate(
           typeArguments: const [],
@@ -189,7 +202,7 @@
     await _assertCanBeAnalyzed(r'''
 typedef void F(int a, this.b);
 ''');
-    var alias = findElement.functionTypeAlias('F');
+    var alias = findElement.typeAlias('F');
     assertType(
         alias.instantiate(
           typeArguments: const [],
@@ -389,6 +402,39 @@
 @reflectiveTest
 class InvalidCodeWithNullSafetyTest extends PubPackageResolutionTest
     with WithNullSafetyMixin {
+  test_functionExpression_emptyBody() async {
+    await _assertCanBeAnalyzed(r'''
+var v = <T>();
+''');
+  }
+
+  test_functionExpressionInvocation_mustBeNullShortingTerminated() async {
+    // It looks like MethodInvocation, but because `8` is not SimpleIdentifier,
+    // we parse it as FunctionExpressionInvocation.
+    await _assertCanBeAnalyzed(r'''
+var v = a?.8(b);
+''');
+  }
+
+  test_inAnnotation_noFlow_labeledStatement() async {
+    await _assertCanBeAnalyzed('''
+@A(() { label: })
+typedef F = void Function();
+''');
+  }
+
+  test_inDefaultValue_noFlow_ifExpression() async {
+    await _assertCanBeAnalyzed('''
+typedef void F({a = [if (true) 0]});
+''');
+  }
+
+  test_inDefaultValue_noFlow_ifStatement() async {
+    await _assertCanBeAnalyzed('''
+typedef void F([a = () { if (true) 0; }]);
+''');
+  }
+
   test_issue_40837() async {
     await _assertCanBeAnalyzed('''
 class A {
diff --git a/pkg/analyzer/test/generated/nnbd_parser_test.dart b/pkg/analyzer/test/generated/nnbd_parser_test.dart
new file mode 100644
index 0000000..6fd7547
--- /dev/null
+++ b/pkg/analyzer/test/generated/nnbd_parser_test.dart
@@ -0,0 +1,862 @@
+// 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+import 'test_support.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NNBDParserTest);
+  });
+}
+
+@reflectiveTest
+class NNBDParserTest extends FastaParserTestCase {
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+          {List<ErrorCode> codes,
+          List<ExpectedError> errors,
+          FeatureSet featureSet}) =>
+      super.parseCompilationUnit(content,
+          codes: codes,
+          errors: errors,
+          featureSet: featureSet ?? FeatureSet.latestLanguageVersion());
+
+  void test_assignment_complex() {
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }');
+  }
+
+  void test_assignment_complex2() {
+    parseCompilationUnit(r'''
+main() {
+  A? a;
+  String? s = '';
+  a?..foo().length..x27 = s!..toString().length;
+}
+''');
+  }
+
+  void test_assignment_simple() {
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
+  }
+
+  void test_bangBeforeFuctionCall1() {
+    // https://github.com/dart-lang/sdk/issues/39776
+    var unit = parseCompilationUnit('f() { Function? f1; f1!(42); }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement1 = body.block.statements[0] as VariableDeclarationStatement;
+    expect(statement1.toSource(), "Function? f1;");
+    var statement2 = body.block.statements[1] as ExpressionStatement;
+
+    // expression is "f1!(42)"
+    var expression = statement2.expression as FunctionExpressionInvocation;
+    expect(expression.toSource(), "f1!(42)");
+
+    var functionExpression = expression.function as PostfixExpression;
+    SimpleIdentifier identifier = functionExpression.operand;
+    expect(identifier.name, 'f1');
+    expect(functionExpression.operator.lexeme, '!');
+
+    expect(expression.typeArguments, null);
+
+    expect(expression.argumentList.arguments.length, 1);
+    IntegerLiteral argument = expression.argumentList.arguments.single;
+    expect(argument.value, 42);
+  }
+
+  void test_bangBeforeFuctionCall2() {
+    // https://github.com/dart-lang/sdk/issues/39776
+    var unit = parseCompilationUnit('f() { Function f2; f2!<int>(42); }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement1 = body.block.statements[0] as VariableDeclarationStatement;
+    expect(statement1.toSource(), "Function f2;");
+    var statement2 = body.block.statements[1] as ExpressionStatement;
+
+    // expression is "f2!<int>(42)"
+    var expression = statement2.expression as FunctionExpressionInvocation;
+    expect(expression.toSource(), "f2!<int>(42)");
+
+    var functionExpression = expression.function as PostfixExpression;
+    SimpleIdentifier identifier = functionExpression.operand;
+    expect(identifier.name, 'f2');
+    expect(functionExpression.operator.lexeme, '!');
+
+    expect(expression.typeArguments.arguments.length, 1);
+    TypeName typeArgument = expression.typeArguments.arguments.single;
+    expect(typeArgument.name.name, "int");
+
+    expect(expression.argumentList.arguments.length, 1);
+    IntegerLiteral argument = expression.argumentList.arguments.single;
+    expect(argument.value, 42);
+  }
+
+  void test_bangQuestionIndex() {
+    // http://dartbug.com/41177
+    CompilationUnit unit = parseCompilationUnit('f(dynamic a) { a!?[0]; }');
+    FunctionDeclaration funct = unit.declarations[0];
+    BlockFunctionBody body = funct.functionExpression.body;
+
+    ExpressionStatement statement = body.block.statements[0];
+    IndexExpression expression = statement.expression;
+
+    IntegerLiteral index = expression.index;
+    expect(index.value, 0);
+
+    Token question = expression.question;
+    expect(question, isNotNull);
+    expect(question.lexeme, "?");
+
+    PostfixExpression target = expression.target;
+    SimpleIdentifier identifier = target.operand;
+    expect(identifier.name, 'a');
+    expect(target.operator.lexeme, '!');
+  }
+
+  void test_binary_expression_statement() {
+    final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }');
+    FunctionDeclaration funct = unit.declarations[0];
+    BlockFunctionBody body = funct.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    BinaryExpression expression = statement.expression;
+    SimpleIdentifier lhs = expression.leftOperand;
+    expect(lhs.name, 'X');
+    expect(expression.operator.lexeme, '??');
+    SimpleIdentifier rhs = expression.rightOperand;
+    expect(rhs.name, 'x2');
+  }
+
+  void test_cascade_withNullCheck_indexExpression() {
+    var unit = parseCompilationUnit('main() { a?..[27]; }');
+    FunctionDeclaration funct = unit.declarations[0];
+    BlockFunctionBody body = funct.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    CascadeExpression cascade = statement.expression;
+    IndexExpression indexExpression = cascade.cascadeSections[0];
+    expect(indexExpression.period.lexeme, '?..');
+    expect(indexExpression.toSource(), '?..[27]');
+  }
+
+  void test_cascade_withNullCheck_invalid() {
+    parseCompilationUnit('main() { a..[27]?..x; }', errors: [
+      expectedError(ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER, 16, 3),
+    ]);
+  }
+
+  void test_cascade_withNullCheck_methodInvocation() {
+    var unit = parseCompilationUnit('main() { a?..foo(); }');
+    FunctionDeclaration funct = unit.declarations[0];
+    BlockFunctionBody body = funct.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    CascadeExpression cascade = statement.expression;
+    MethodInvocation invocation = cascade.cascadeSections[0];
+    expect(invocation.operator.lexeme, '?..');
+    expect(invocation.toSource(), '?..foo()');
+  }
+
+  void test_cascade_withNullCheck_propertyAccess() {
+    var unit = parseCompilationUnit('main() { a?..x27; }');
+    FunctionDeclaration funct = unit.declarations[0];
+    BlockFunctionBody body = funct.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    CascadeExpression cascade = statement.expression;
+    PropertyAccess propertyAccess = cascade.cascadeSections[0];
+    expect(propertyAccess.operator.lexeme, '?..');
+    expect(propertyAccess.toSource(), '?..x27');
+  }
+
+  void test_conditional() {
+    parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
+  }
+
+  void test_conditional_complex() {
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
+  }
+
+  void test_conditional_error() {
+    parseCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
+        errors: [
+          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 40, 1),
+          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 40, 1),
+        ]);
+  }
+
+  void test_conditional_simple() {
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
+  }
+
+  void test_enableNonNullable_false() {
+    parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)],
+        featureSet: preNonNullable);
+  }
+
+  void test_for() {
+    parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
+  }
+
+  void test_for_conditional() {
+    parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
+  }
+
+  void test_for_nullable() {
+    parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
+  }
+
+  void test_foreach() {
+    parseCompilationUnit('main() { for(int x in [7]) { } }');
+  }
+
+  void test_foreach_nullable() {
+    parseCompilationUnit('main() { for(int? x in [7, null]) { } }');
+  }
+
+  void test_functionTypedFormalParameter_nullable_disabled() {
+    parseCompilationUnit('void f(void p()?) {}',
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
+        featureSet: preNonNullable);
+  }
+
+  test_fuzz_38113() async {
+    // https://github.com/dart-lang/sdk/issues/38113
+    parseCompilationUnit(r'+t{{r?this}}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+    ]);
+  }
+
+  void test_gft_nullable() {
+    parseCompilationUnit('main() { C? Function() x = 7; }');
+  }
+
+  void test_gft_nullable_1() {
+    parseCompilationUnit('main() { C Function()? x = 7; }');
+  }
+
+  void test_gft_nullable_2() {
+    parseCompilationUnit('main() { C? Function()? x = 7; }');
+  }
+
+  void test_gft_nullable_3() {
+    parseCompilationUnit('main() { C? Function()? Function()? x = 7; }');
+  }
+
+  void test_gft_nullable_prefixed() {
+    parseCompilationUnit('main() { C.a? Function()? x = 7; }');
+  }
+
+  void test_indexed() {
+    CompilationUnit unit = parseCompilationUnit('main() { a[7]; }');
+    FunctionDeclaration method = unit.declarations[0];
+    BlockFunctionBody body = method.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    IndexExpression expression = statement.expression;
+    expect(expression.leftBracket.lexeme, '[');
+  }
+
+  void test_indexed_nullAware() {
+    CompilationUnit unit = parseCompilationUnit('main() { a?[7]; }');
+    FunctionDeclaration method = unit.declarations[0];
+    BlockFunctionBody body = method.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    IndexExpression expression = statement.expression;
+    expect(expression.question, isNotNull);
+    expect(expression.leftBracket.lexeme, '[');
+    expect(expression.rightBracket.lexeme, ']');
+    expect(expression.leftBracket.endGroup, expression.rightBracket);
+  }
+
+  void test_indexed_nullAware_optOut() {
+    CompilationUnit unit = parseCompilationUnit('''
+// @dart = 2.2
+main() { a?[7]; }''',
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 25, 1)]);
+    FunctionDeclaration method = unit.declarations[0];
+    BlockFunctionBody body = method.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    IndexExpressionImpl expression = statement.expression;
+    expect(expression.target.toSource(), 'a');
+    expect(expression.question, isNotNull);
+    expect(expression.leftBracket.lexeme, '[');
+    expect(expression.rightBracket.lexeme, ']');
+    expect(expression.leftBracket.endGroup, expression.rightBracket);
+  }
+
+  void test_indexExpression_nullable_disabled() {
+    parseCompilationUnit('main(a) { a?[0]; }',
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 1)],
+        featureSet: preNonNullable);
+  }
+
+  void test_is_nullable() {
+    CompilationUnit unit =
+        parseCompilationUnit('main() { x is String? ? (x + y) : z; }');
+    FunctionDeclaration function = unit.declarations[0];
+    BlockFunctionBody body = function.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    ConditionalExpression expression = statement.expression;
+
+    IsExpression condition = expression.condition;
+    expect((condition.type as NamedType).question, isNotNull);
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+  }
+
+  void test_is_nullable_parenthesis() {
+    CompilationUnit unit =
+        parseCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
+    FunctionDeclaration function = unit.declarations[0];
+    BlockFunctionBody body = function.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    ConditionalExpression expression = statement.expression;
+
+    ParenthesizedExpression condition = expression.condition;
+    IsExpression isExpression = condition.expression;
+    expect((isExpression.type as NamedType).question, isNotNull);
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+  }
+
+  void test_is_nullable_parenthesis_optOut() {
+    parseCompilationUnit('''
+// @dart = 2.2
+main() { (x is String?) ? (x + y) : z; }
+''', errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)]);
+  }
+
+  void test_late_as_identifier() {
+    parseCompilationUnit('''
+class C {
+  int late;
+}
+
+void f(C c) {
+  print(c.late);
+}
+
+main() {
+  f(new C());
+}
+''', featureSet: preNonNullable);
+  }
+
+  void test_late_as_identifier_optOut() {
+    parseCompilationUnit('''
+// @dart = 2.2
+class C {
+  int late;
+}
+
+void f(C c) {
+  print(c.late);
+}
+
+main() {
+  f(new C());
+}
+''');
+  }
+
+  void test_nullableTypeInInitializerList_01() {
+    // http://dartbug.com/40834
+    var unit = parseCompilationUnit(r'''
+class Foo {
+  String? x;
+  int y;
+
+  Foo(Object? o) : x = o as String?, y = 0;
+}
+''');
+    ClassDeclaration classDeclaration = unit.declarations.first;
+    ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
+
+    // Object? o
+    SimpleFormalParameter parameter = constructor.parameters.parameters.single;
+    expect(parameter.identifier.name, 'o');
+    TypeName type = parameter.type;
+    expect(type.question.lexeme, '?');
+    expect(type.name.name, 'Object');
+
+    expect(constructor.initializers.length, 2);
+
+    // o as String?
+    {
+      ConstructorFieldInitializer initializer = constructor.initializers[0];
+      expect(initializer.fieldName.name, 'x');
+      AsExpression expression = initializer.expression;
+      SimpleIdentifier identifier = expression.expression;
+      expect(identifier.name, 'o');
+      TypeName expressionType = expression.type;
+      expect(expressionType.question.lexeme, '?');
+      expect(expressionType.name.name, 'String');
+    }
+
+    // y = 0
+    {
+      ConstructorFieldInitializer initializer = constructor.initializers[1];
+      expect(initializer.fieldName.name, 'y');
+      IntegerLiteral expression = initializer.expression;
+      expect(expression.value, 0);
+    }
+  }
+
+  void test_nullableTypeInInitializerList_02() {
+    var unit = parseCompilationUnit(r'''
+class Foo {
+  String? x;
+  int y;
+
+  Foo(Object? o) : y = o is String? ? o.length : null, x = null;
+}
+''');
+    ClassDeclaration classDeclaration = unit.declarations.first;
+    ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
+
+    // Object? o
+    SimpleFormalParameter parameter = constructor.parameters.parameters.single;
+    expect(parameter.identifier.name, 'o');
+    TypeName type = parameter.type;
+    expect(type.question.lexeme, '?');
+    expect(type.name.name, 'Object');
+
+    expect(constructor.initializers.length, 2);
+
+    // y = o is String? ? o.length : null
+    {
+      ConstructorFieldInitializer initializer = constructor.initializers[0];
+      expect(initializer.fieldName.name, 'y');
+      ConditionalExpression expression = initializer.expression;
+      IsExpression condition = expression.condition;
+      SimpleIdentifier identifier = condition.expression;
+      expect(identifier.name, 'o');
+      TypeName expressionType = condition.type;
+      expect(expressionType.question.lexeme, '?');
+      expect(expressionType.name.name, 'String');
+      PrefixedIdentifier thenExpression = expression.thenExpression;
+      expect(thenExpression.identifier.name, 'length');
+      expect(thenExpression.prefix.name, 'o');
+      NullLiteral elseExpression = expression.elseExpression;
+      expect(elseExpression, isNotNull);
+    }
+
+    // x = null
+    {
+      ConstructorFieldInitializer initializer = constructor.initializers[1];
+      expect(initializer.fieldName.name, 'x');
+      NullLiteral expression = initializer.expression;
+      expect(expression, isNotNull);
+    }
+  }
+
+  void test_nullableTypeInInitializerList_03() {
+    // As test_nullableTypeInInitializerList_02 but without ? on String in is.
+    var unit = parseCompilationUnit(r'''
+class Foo {
+  String? x;
+  int y;
+
+  Foo(Object? o) : y = o is String ? o.length : null, x = null;
+}
+''');
+    ClassDeclaration classDeclaration = unit.declarations.first;
+    ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
+
+    // Object? o
+    SimpleFormalParameter parameter = constructor.parameters.parameters.single;
+    expect(parameter.identifier.name, 'o');
+    TypeName type = parameter.type;
+    expect(type.question.lexeme, '?');
+    expect(type.name.name, 'Object');
+
+    expect(constructor.initializers.length, 2);
+
+    // y = o is String ? o.length : null
+    {
+      ConstructorFieldInitializer initializer = constructor.initializers[0];
+      expect(initializer.fieldName.name, 'y');
+      ConditionalExpression expression = initializer.expression;
+      IsExpression condition = expression.condition;
+      SimpleIdentifier identifier = condition.expression;
+      expect(identifier.name, 'o');
+      TypeName expressionType = condition.type;
+      expect(expressionType.question, isNull);
+      expect(expressionType.name.name, 'String');
+      PrefixedIdentifier thenExpression = expression.thenExpression;
+      expect(thenExpression.identifier.name, 'length');
+      expect(thenExpression.prefix.name, 'o');
+      NullLiteral elseExpression = expression.elseExpression;
+      expect(elseExpression, isNotNull);
+    }
+
+    // x = null
+    {
+      ConstructorFieldInitializer initializer = constructor.initializers[1];
+      expect(initializer.fieldName.name, 'x');
+      NullLiteral expression = initializer.expression;
+      expect(expression, isNotNull);
+    }
+  }
+
+  void test_nullCheck() {
+    var unit = parseCompilationUnit('f(int? y) { var x = y!; }');
+    FunctionDeclaration function = unit.declarations[0];
+    BlockFunctionBody body = function.functionExpression.body;
+    VariableDeclarationStatement statement = body.block.statements[0];
+    PostfixExpression expression = statement.variables.variables[0].initializer;
+    SimpleIdentifier identifier = expression.operand;
+    expect(identifier.name, 'y');
+    expect(expression.operator.lexeme, '!');
+  }
+
+  void test_nullCheck_disabled() {
+    var unit = parseCompilationUnit('f(int? y) { var x = y!; }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
+        ],
+        featureSet: preNonNullable);
+    FunctionDeclaration function = unit.declarations[0];
+    BlockFunctionBody body = function.functionExpression.body;
+    VariableDeclarationStatement statement = body.block.statements[0];
+    SimpleIdentifier identifier = statement.variables.variables[0].initializer;
+    expect(identifier.name, 'y');
+  }
+
+  void test_nullCheckAfterGetterAccess() {
+    parseCompilationUnit('f() { var x = g.x!.y + 7; }');
+  }
+
+  void test_nullCheckAfterMethodCall() {
+    parseCompilationUnit('f() { var x = g.m()!.y + 7; }');
+  }
+
+  void test_nullCheckBeforeGetterAccess() {
+    parseCompilationUnit('f() { var x = g!.x + 7; }');
+  }
+
+  void test_nullCheckBeforeIndex() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { foo.bar!.baz[arg]; }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as IndexExpression;
+    expect(expression.index.toSource(), 'arg');
+    var propertyAccess = expression.target as PropertyAccess;
+    expect(propertyAccess.propertyName.toSource(), 'baz');
+    var target = propertyAccess.target as PostfixExpression;
+    expect(target.operand.toSource(), 'foo.bar');
+    expect(target.operator.lexeme, '!');
+  }
+
+  void test_nullCheckBeforeMethodCall() {
+    parseCompilationUnit('f() { var x = g!.m() + 7; }');
+  }
+
+  void test_nullCheckFunctionResult() {
+    parseCompilationUnit('f() { var x = g()! + 7; }');
+  }
+
+  void test_nullCheckIndexedValue() {
+    parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
+  }
+
+  void test_nullCheckIndexedValue2() {
+    parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
+  }
+
+  void test_nullCheckInExpression() {
+    parseCompilationUnit('f(int? y) { var x = y! + 7; }');
+  }
+
+  void test_nullCheckInExpression_disabled() {
+    parseCompilationUnit('f(int? y) { var x = y! + 7; }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
+        ],
+        featureSet: preNonNullable);
+  }
+
+  void test_nullCheckMethodResult() {
+    parseCompilationUnit('f() { var x = g.m()! + 7; }');
+  }
+
+  void test_nullCheckMethodResult2() {
+    parseCompilationUnit('f() { var x = g?.m()! + 7; }');
+  }
+
+  void test_nullCheckMethodResult3() {
+    parseCompilationUnit('f() { var x = super.m()! + 7; }');
+  }
+
+  void test_nullCheckOnConstConstructor() {
+    parseCompilationUnit('f() { var x = const Foo()!; }');
+  }
+
+  void test_nullCheckOnConstructor() {
+    parseCompilationUnit('f() { var x = new Foo()!; }');
+  }
+
+  void test_nullCheckOnIndex() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { obj![arg]; }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as IndexExpression;
+    var target = expression.target as PostfixExpression;
+    expect(target.operand.toSource(), 'obj');
+    expect(target.operator.lexeme, '!');
+  }
+
+  void test_nullCheckOnIndex2() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { obj![arg]![arg2]; }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as IndexExpression;
+    expect(expression.index.toSource(), 'arg2');
+    var target = expression.target as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+    expression = target.operand as IndexExpression;
+    expect(expression.index.toSource(), 'arg');
+    target = expression.target as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+    expect(target.operand.toSource(), 'obj');
+  }
+
+  void test_nullCheckOnIndex3() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { foo.bar![arg]; }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as IndexExpression;
+    expect(expression.index.toSource(), 'arg');
+    var target = expression.target as PostfixExpression;
+    expect(target.operand.toSource(), 'foo.bar');
+    expect(target.operator.lexeme, '!');
+  }
+
+  void test_nullCheckOnIndex4() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { foo!.bar![arg]; }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as IndexExpression;
+    var fooBarTarget = expression.target as PostfixExpression;
+    expect(fooBarTarget.toSource(), "foo!.bar!");
+    var propertyAccess = fooBarTarget.operand as PropertyAccess;
+    var targetFoo = propertyAccess.target as PostfixExpression;
+    expect(targetFoo.operand.toSource(), "foo");
+    expect(targetFoo.operator.lexeme, "!");
+    expect(propertyAccess.propertyName.toSource(), "bar");
+    expect(fooBarTarget.operator.lexeme, '!');
+    expect(expression.index.toSource(), 'arg');
+  }
+
+  void test_nullCheckOnIndex5() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { foo.bar![arg]![arg2]; }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as IndexExpression;
+    expect(expression.index.toSource(), 'arg2');
+    var target = expression.target as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+    expression = target.operand as IndexExpression;
+    expect(expression.index.toSource(), 'arg');
+    target = expression.target as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+    expect(target.operand.toSource(), 'foo.bar');
+  }
+
+  void test_nullCheckOnIndex6() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { foo!.bar![arg]![arg2]; }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+
+    // expression is "foo!.bar![arg]![arg2]"
+    var expression = statement.expression as IndexExpression;
+    expect(expression.index.toSource(), 'arg2');
+
+    // target is "foo!.bar![arg]!"
+    var target = expression.target as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+
+    // expression is "foo!.bar![arg]"
+    expression = target.operand as IndexExpression;
+    expect(expression.index.toSource(), 'arg');
+
+    // target is "foo!.bar!"
+    target = expression.target as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+
+    // propertyAccess is "foo!.bar"
+    PropertyAccess propertyAccess = target.operand as PropertyAccess;
+    expect(propertyAccess.propertyName.toSource(), "bar");
+
+    // target is "foo!"
+    target = propertyAccess.target as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+
+    expect(target.operand.toSource(), "foo");
+  }
+
+  void test_nullCheckOnLiteral_disabled() {
+    parseCompilationUnit('f() { var x = 0!; }',
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
+        featureSet: preNonNullable);
+  }
+
+  void test_nullCheckOnLiteralDouble() {
+    // Issues like this should be caught during later analysis
+    parseCompilationUnit('f() { var x = 1.2!; }');
+  }
+
+  void test_nullCheckOnLiteralInt() {
+    // Issues like this should be caught during later analysis
+    parseCompilationUnit('f() { var x = 0!; }');
+  }
+
+  void test_nullCheckOnLiteralList() {
+    // Issues like this should be caught during later analysis
+    parseCompilationUnit('f() { var x = [1,2]!; }');
+  }
+
+  void test_nullCheckOnLiteralMap() {
+    // Issues like this should be caught during later analysis
+    parseCompilationUnit('f() { var x = {1:2}!; }');
+  }
+
+  void test_nullCheckOnLiteralSet() {
+    // Issues like this should be caught during later analysis
+    parseCompilationUnit('f() { var x = {1,2}!; }');
+  }
+
+  void test_nullCheckOnLiteralString() {
+    // Issues like this should be caught during later analysis
+    parseCompilationUnit('f() { var x = "seven"!; }');
+  }
+
+  void test_nullCheckOnNull() {
+    // Issues like this should be caught during later analysis
+    parseCompilationUnit('f() { var x = null!; }');
+  }
+
+  void test_nullCheckOnSend() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { obj!(arg); }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as FunctionExpressionInvocation;
+    var target = expression.function as PostfixExpression;
+    expect(target.operand.toSource(), 'obj');
+    expect(target.operator.lexeme, '!');
+  }
+
+  void test_nullCheckOnSend2() {
+    // https://github.com/dart-lang/sdk/issues/37708
+    var unit = parseCompilationUnit('f() { obj!(arg)!(arg2); }');
+    var funct = unit.declarations[0] as FunctionDeclaration;
+    var body = funct.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var expression = statement.expression as FunctionExpressionInvocation;
+    expect(expression.argumentList.toSource(), '(arg2)');
+    var target = expression.function as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+    expression = target.operand as FunctionExpressionInvocation;
+    expect(expression.argumentList.toSource(), '(arg)');
+    target = expression.function as PostfixExpression;
+    expect(target.operator.lexeme, '!');
+    expect(target.operand.toSource(), 'obj');
+  }
+
+  void test_nullCheckOnSymbol() {
+    // Issues like this should be caught during later analysis
+    parseCompilationUnit('f() { var x = #seven!; }');
+  }
+
+  void test_nullCheckOnValue() {
+    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }');
+  }
+
+  void test_nullCheckOnValue_disabled() {
+    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 24, 1)],
+        featureSet: preNonNullable);
+  }
+
+  void test_nullCheckParenthesizedExpression() {
+    parseCompilationUnit('f(int? y) { var x = (y)! + 7; }');
+  }
+
+  void test_nullCheckPropertyAccess() {
+    parseCompilationUnit('f() { var x = g.p! + 7; }');
+  }
+
+  void test_nullCheckPropertyAccess2() {
+    parseCompilationUnit('f() { var x = g?.p! + 7; }');
+  }
+
+  void test_nullCheckPropertyAccess3() {
+    parseCompilationUnit('f() { var x = super.p! + 7; }');
+  }
+
+  void test_postfix_null_assertion_and_unary_prefix_operator_precedence() {
+    // -x! is parsed as -(x!).
+    var unit = parseCompilationUnit('void main() { -x!; }');
+    var function = unit.declarations[0] as FunctionDeclaration;
+    var body = function.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var outerExpression = statement.expression as PrefixExpression;
+    expect(outerExpression.operator.type, TokenType.MINUS);
+    var innerExpression = outerExpression.operand as PostfixExpression;
+    expect(innerExpression.operator.type, TokenType.BANG);
+  }
+
+  void test_postfix_null_assertion_of_postfix_expression() {
+    // x++! is parsed as (x++)!.
+    var unit = parseCompilationUnit('void main() { x++!; }');
+    var function = unit.declarations[0] as FunctionDeclaration;
+    var body = function.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var outerExpression = statement.expression as PostfixExpression;
+    expect(outerExpression.operator.type, TokenType.BANG);
+    var innerExpression = outerExpression.operand as PostfixExpression;
+    expect(innerExpression.operator.type, TokenType.PLUS_PLUS);
+  }
+
+  void test_typeName_nullable_disabled() {
+    parseCompilationUnit('int? x;',
+        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 3, 1)],
+        featureSet: preNonNullable);
+  }
+}
diff --git a/pkg/analyzer/test/generated/non_error_parser_test.dart b/pkg/analyzer/test/generated/non_error_parser_test.dart
new file mode 100644
index 0000000..e802f3d
--- /dev/null
+++ b/pkg/analyzer/test/generated/non_error_parser_test.dart
@@ -0,0 +1,43 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NonErrorParserTest);
+  });
+}
+
+@reflectiveTest
+class NonErrorParserTest extends ParserTestCase {
+  void test_annotationOnEnumConstant_first() {
+    createParser("enum E { @override C }");
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+  }
+
+  void test_annotationOnEnumConstant_middle() {
+    createParser("enum E { C, @override D, E }");
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+  }
+
+  void test_staticMethod_notParsingFunctionBodies() {
+    ParserTestCase.parseFunctionBodies = false;
+    try {
+      createParser('class C { static void m() {} }');
+      CompilationUnit unit = parser.parseCompilationUnit2();
+      expectNotNullIfNoErrors(unit);
+      assertNoErrors();
+    } finally {
+      ParserTestCase.parseFunctionBodies = true;
+    }
+  }
+}
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
deleted file mode 100644
index 34b6b84..0000000
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ /dev/null
@@ -1,4826 +0,0 @@
-// 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 'package:_fe_analyzer_shared/src/parser/async_modifier.dart';
-import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
-import 'package:_fe_analyzer_shared/src/scanner/error_token.dart'
-    show ErrorToken;
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
-    show ScannerConfiguration, ScannerResult, scanString;
-import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart' as analyzer;
-import 'package:analyzer/dart/ast/token.dart'
-    show Token, TokenType, LanguageVersionToken;
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart' show ErrorReporter;
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/fasta/ast_builder.dart';
-import 'package:analyzer/src/generated/parser.dart' as analyzer;
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/string_source.dart';
-import 'package:pub_semver/src/version.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../util/ast_type_matchers.dart';
-import 'parser_fasta_listener.dart';
-import 'parser_test.dart';
-import 'test_support.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ClassMemberParserTest_Fasta);
-    defineReflectiveTests(ExtensionMethodsParserTest_Fasta);
-    defineReflectiveTests(CollectionLiteralParserTest);
-    defineReflectiveTests(ComplexParserTest_Fasta);
-    defineReflectiveTests(ErrorParserTest_Fasta);
-    defineReflectiveTests(ExpressionParserTest_Fasta);
-    defineReflectiveTests(FormalParameterParserTest_Fasta);
-    defineReflectiveTests(NNBDParserTest_Fasta);
-    defineReflectiveTests(RecoveryParserTest_Fasta);
-    defineReflectiveTests(SimpleParserTest_Fasta);
-    defineReflectiveTests(StatementParserTest_Fasta);
-    defineReflectiveTests(TopLevelParserTest_Fasta);
-    defineReflectiveTests(VarianceParserTest_Fasta);
-  });
-}
-
-/// Type of the "parse..." methods defined in the Fasta parser.
-typedef ParseFunction = analyzer.Token Function(analyzer.Token token);
-
-@reflectiveTest
-class ClassMemberParserTest_Fasta extends FastaParserTestCase
-    with ClassMemberParserTestMixin {
-  final tripleShift = FeatureSet.forTesting(
-      sdkVersion: '2.0.0', additionalFeatures: [Feature.triple_shift]);
-
-  void test_parse_member_called_late() {
-    var unit = parseCompilationUnit(
-        'class C { void late() { new C().late(); } }',
-        featureSet: nonNullable);
-    var declaration = unit.declarations[0] as ClassDeclaration;
-    var method = declaration.members[0] as MethodDeclaration;
-
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name.name, 'late');
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-
-    var body = method.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var invocation = statement.expression as MethodInvocation;
-    expect(invocation.operator.lexeme, '.');
-    expect(invocation.toSource(), 'new C().late()');
-  }
-
-  void test_parseClassMember_finalAndCovariantLateWithInitializer() {
-    createParser(
-      'covariant late final int f = 0;',
-      featureSet: nonNullable,
-    );
-    parser.parseClassMember('C');
-    assertErrors(errors: [
-      expectedError(
-          ParserErrorCode.FINAL_AND_COVARIANT_LATE_WITH_INITIALIZER, 0, 9)
-    ]);
-  }
-
-  void test_parseClassMember_operator_gtgtgt() {
-    var unit = parseCompilationUnit(
-        'class C { bool operator >>>(other) => false; }',
-        featureSet: tripleShift);
-    var declaration = unit.declarations[0] as ClassDeclaration;
-    var method = declaration.members[0] as MethodDeclaration;
-
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name.name, '>>>');
-    expect(method.operatorKeyword, isNotNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_operator_gtgtgteq() {
-    var unit = parseCompilationUnit(
-        'class C { foo(int value) { x >>>= value; } }',
-        featureSet: tripleShift);
-    var declaration = unit.declarations[0] as ClassDeclaration;
-    var method = declaration.members[0] as MethodDeclaration;
-    var blockFunctionBody = method.body as BlockFunctionBody;
-    NodeList<Statement> statements = blockFunctionBody.block.statements;
-    expect(statements, hasLength(1));
-    var statement = statements[0] as ExpressionStatement;
-    var assignment = statement.expression as AssignmentExpression;
-    var leftHandSide = assignment.leftHandSide as SimpleIdentifier;
-    expect(leftHandSide.name, 'x');
-    expect(assignment.operator.lexeme, '>>>=');
-    var rightHandSide = assignment.rightHandSide as SimpleIdentifier;
-    expect(rightHandSide.name, 'value');
-  }
-
-  void test_parseConstructor_invalidInitializer() {
-    // https://github.com/dart-lang/sdk/issues/37693
-    parseCompilationUnit('class C{ C() : super() * (); }', errors: [
-      expectedError(ParserErrorCode.INVALID_INITIALIZER, 15, 12),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
-    ]);
-  }
-
-  void test_parseConstructor_nullSuperArgList_openBrace_37735() {
-    // https://github.com/dart-lang/sdk/issues/37735
-    var unit = parseCompilationUnit('class{const():super.{n', errors: [
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
-      expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 11, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 1),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 1),
-      expectedError(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, 20, 1),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 21, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 22, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 22, 1),
-    ]);
-    var classDeclaration = unit.declarations[0] as ClassDeclaration;
-    var constructor = classDeclaration.members[0] as ConstructorDeclaration;
-    var invocation = constructor.initializers[0] as SuperConstructorInvocation;
-    expect(invocation.argumentList.arguments, hasLength(0));
-  }
-
-  void test_parseConstructor_operator_name() {
-    var unit = parseCompilationUnit('class A { operator/() : super(); }',
-        errors: [
-          expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 10, 8)
-        ]);
-    var classDeclaration = unit.declarations[0] as ClassDeclaration;
-    var constructor = classDeclaration.members[0] as ConstructorDeclaration;
-    var invocation = constructor.initializers[0] as SuperConstructorInvocation;
-    expect(invocation.argumentList.arguments, hasLength(0));
-  }
-
-  void test_parseField_abstract() {
-    createParser('abstract int i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.abstractKeyword, isNotNull);
-  }
-
-  void test_parseField_abstract_external() {
-    createParser('abstract external int i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.ABSTRACT_EXTERNAL_FIELD, 0, 8),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.abstractKeyword, isNotNull);
-    expect(field.externalKeyword, isNotNull);
-  }
-
-  void test_parseField_abstract_late() {
-    createParser('abstract late int? i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.ABSTRACT_LATE_FIELD, 0, 8),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.abstractKeyword, isNotNull);
-  }
-
-  void test_parseField_abstract_late_final() {
-    createParser('abstract late final int? i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.ABSTRACT_LATE_FIELD, 0, 8),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.abstractKeyword, isNotNull);
-  }
-
-  void test_parseField_abstract_static() {
-    createParser('abstract static int? i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.ABSTRACT_STATIC_FIELD, 0, 8),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.abstractKeyword, isNotNull);
-  }
-
-  void test_parseField_const_late() {
-    createParser('const late T f = 0;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 6, 4),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isTrue);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isTrue);
-    expect(list.lateKeyword, isNotNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseField_external() {
-    createParser('external int i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.externalKeyword, isNotNull);
-  }
-
-  void test_parseField_external_abstract() {
-    createParser('external abstract int i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.ABSTRACT_EXTERNAL_FIELD, 9, 8),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.abstractKeyword, isNotNull);
-    expect(field.externalKeyword, isNotNull);
-  }
-
-  void test_parseField_external_late() {
-    createParser('external late int? i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.externalKeyword, isNotNull);
-  }
-
-  void test_parseField_external_late_final() {
-    createParser('external late final int? i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.externalKeyword, isNotNull);
-  }
-
-  void test_parseField_external_static() {
-    createParser('external static int? i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.externalKeyword, isNotNull);
-  }
-
-  void test_parseField_final_late() {
-    createParser('final late T f;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4),
-    ]);
-    expect(member, isNotNull);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isTrue);
-    expect(list.isLate, isTrue);
-    expect(list.lateKeyword, isNotNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseField_late() {
-    createParser('late T f;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list.keyword, isNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isTrue);
-    expect(list.lateKeyword, isNotNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseField_late_const() {
-    createParser('late const T f = 0;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 5, 5),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isTrue);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isTrue);
-    expect(list.lateKeyword, isNotNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseField_late_final() {
-    createParser('late final T f;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isTrue);
-    expect(list.isLate, isTrue);
-    expect(list.lateKeyword, isNotNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseField_late_var() {
-    createParser('late var f;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isTrue);
-    expect(list.lateKeyword, isNotNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseField_non_abstract() {
-    createParser('int i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.abstractKeyword, isNull);
-  }
-
-  void test_parseField_non_external() {
-    createParser('int i;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.externalKeyword, isNull);
-  }
-
-  void test_parseField_var_late() {
-    createParser('var late f;', featureSet: nonNullable);
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 4, 4),
-    ]);
-    expect(member, isFieldDeclaration);
-    var field = member as FieldDeclaration;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isTrue);
-    expect(list.lateKeyword, isNotNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-}
-
-/// Tests of the fasta parser based on [ExpressionParserTestMixin].
-@reflectiveTest
-class CollectionLiteralParserTest extends FastaParserTestCase {
-  Expression parseCollectionLiteral(String source,
-      {List<ErrorCode> codes,
-      List<ExpectedError> errors,
-      int expectedEndOffset,
-      bool inAsync = false}) {
-    return parseExpression(source,
-        codes: codes,
-        errors: errors,
-        expectedEndOffset: expectedEndOffset,
-        inAsync: inAsync,
-        featureSet: FeatureSet.forTesting(
-            sdkVersion: '2.0.0',
-            additionalFeatures: [
-              Feature.spread_collections,
-              Feature.control_flow_collections
-            ]));
-  }
-
-  void test_listLiteral_for() {
-    var list = parseCollectionLiteral(
-      '[1, await for (var x in list) 2]',
-      inAsync: true,
-    ) as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as ForElement;
-    expect(second.awaitKeyword, isNotNull);
-    expect(second.forKeyword.isKeyword, isTrue);
-    expect(second.leftParenthesis.lexeme, '(');
-    expect(second.rightParenthesis.lexeme, ')');
-    var forLoopParts = second.forLoopParts as ForEachPartsWithDeclaration;
-    DeclaredIdentifier forLoopVar = forLoopParts.loopVariable;
-    expect(forLoopVar.identifier.name, 'x');
-    expect(forLoopParts.inKeyword, isNotNull);
-    var iterable = forLoopParts.iterable as SimpleIdentifier;
-    expect(iterable.name, 'list');
-  }
-
-  void test_listLiteral_forIf() {
-    var list = parseCollectionLiteral(
-      '[1, await for (var x in list) if (c) 2]',
-      inAsync: true,
-    ) as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as ForElement;
-    expect(second.awaitKeyword, isNotNull);
-    expect(second.forKeyword.isKeyword, isTrue);
-    expect(second.leftParenthesis.lexeme, '(');
-    expect(second.rightParenthesis.lexeme, ')');
-    var forLoopParts = second.forLoopParts as ForEachPartsWithDeclaration;
-    DeclaredIdentifier forLoopVar = forLoopParts.loopVariable;
-    expect(forLoopVar.identifier.name, 'x');
-    expect(forLoopParts.inKeyword, isNotNull);
-    var iterable = forLoopParts.iterable as SimpleIdentifier;
-    expect(iterable.name, 'list');
-
-    var body = second.body as IfElement;
-    var condition = body.condition as SimpleIdentifier;
-    expect(condition.name, 'c');
-    var thenElement = body.thenElement as IntegerLiteral;
-    expect(thenElement.value, 2);
-  }
-
-  void test_listLiteral_forSpread() {
-    var list =
-        parseCollectionLiteral('[1, for (int x = 0; x < 10; ++x) ...[2]]')
-            as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as ForElement;
-    expect(second.awaitKeyword, isNull);
-    expect(second.forKeyword.isKeyword, isTrue);
-    expect(second.leftParenthesis.lexeme, '(');
-    expect(second.rightParenthesis.lexeme, ')');
-    var forLoopParts = second.forLoopParts as ForPartsWithDeclarations;
-    VariableDeclaration forLoopVar = forLoopParts.variables.variables[0];
-    expect(forLoopVar.name.name, 'x');
-    var condition = forLoopParts.condition as BinaryExpression;
-    var rightOperand = condition.rightOperand as IntegerLiteral;
-    expect(rightOperand.value, 10);
-    var updater = forLoopParts.updaters[0] as PrefixExpression;
-    var updaterOperand = updater.operand as SimpleIdentifier;
-    expect(updaterOperand.name, 'x');
-  }
-
-  void test_listLiteral_if() {
-    var list = parseCollectionLiteral('[1, if (true) 2]') as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as IntegerLiteral;
-    expect(thenElement.value, 2);
-    expect(second.elseElement, isNull);
-  }
-
-  void test_listLiteral_ifElse() {
-    var list = parseCollectionLiteral('[1, if (true) 2 else 5]') as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as IntegerLiteral;
-    expect(thenElement.value, 2);
-    var elseElement = second.elseElement as IntegerLiteral;
-    expect(elseElement.value, 5);
-  }
-
-  void test_listLiteral_ifElseFor() {
-    var list = parseCollectionLiteral('[1, if (true) 2 else for (a in b) 5]')
-        as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as IntegerLiteral;
-    expect(thenElement.value, 2);
-
-    var elseElement = second.elseElement as ForElement;
-    var forLoopParts = elseElement.forLoopParts as ForEachPartsWithIdentifier;
-    expect(forLoopParts.identifier.name, 'a');
-
-    var forValue = elseElement.body as IntegerLiteral;
-    expect(forValue.value, 5);
-  }
-
-  void test_listLiteral_ifElseSpread() {
-    var list = parseCollectionLiteral('[1, if (true) ...[2] else ...?[5]]')
-        as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as SpreadElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    var elseElement = second.elseElement as SpreadElement;
-    expect(elseElement.spreadOperator.lexeme, '...?');
-  }
-
-  void test_listLiteral_ifFor() {
-    var list =
-        parseCollectionLiteral('[1, if (true) for (a in b) 2]') as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-
-    var thenElement = second.thenElement as ForElement;
-    var forLoopParts = thenElement.forLoopParts as ForEachPartsWithIdentifier;
-    expect(forLoopParts.identifier.name, 'a');
-
-    var forValue = thenElement.body as IntegerLiteral;
-    expect(forValue.value, 2);
-    expect(second.elseElement, isNull);
-  }
-
-  void test_listLiteral_ifSpread() {
-    var list = parseCollectionLiteral('[1, if (true) ...[2]]') as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = list.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as SpreadElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    expect(second.elseElement, isNull);
-  }
-
-  void test_listLiteral_spread() {
-    var list = parseCollectionLiteral('[1, ...[2]]') as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var element = list.elements[1] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...');
-    var spreadExpression = element.expression as ListLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_listLiteral_spreadQ() {
-    var list = parseCollectionLiteral('[1, ...?[2]]') as ListLiteral;
-    expect(list.elements, hasLength(2));
-    var first = list.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var element = list.elements[1] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...?');
-    var spreadExpression = element.expression as ListLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_for() {
-    var map = parseCollectionLiteral('{1:7, await for (y in list) 2:3}',
-        inAsync: true) as SetOrMapLiteral;
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 7);
-
-    var second = map.elements[1] as ForElement;
-    expect(second.awaitKeyword, isNotNull);
-    expect(second.forKeyword.isKeyword, isTrue);
-    expect(second.leftParenthesis.lexeme, '(');
-    expect(second.rightParenthesis.lexeme, ')');
-    var forLoopParts = second.forLoopParts as ForEachPartsWithIdentifier;
-    SimpleIdentifier forLoopVar = forLoopParts.identifier;
-    expect(forLoopVar.name, 'y');
-    expect(forLoopParts.inKeyword, isNotNull);
-    var iterable = forLoopParts.iterable as SimpleIdentifier;
-    expect(iterable.name, 'list');
-  }
-
-  void test_mapLiteral_forIf() {
-    var map = parseCollectionLiteral('{1:7, await for (y in list) if (c) 2:3}',
-        inAsync: true) as SetOrMapLiteral;
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 7);
-
-    var second = map.elements[1] as ForElement;
-    expect(second.awaitKeyword, isNotNull);
-    expect(second.forKeyword.isKeyword, isTrue);
-    expect(second.leftParenthesis.lexeme, '(');
-    expect(second.rightParenthesis.lexeme, ')');
-    var forLoopParts = second.forLoopParts as ForEachPartsWithIdentifier;
-    SimpleIdentifier forLoopVar = forLoopParts.identifier;
-    expect(forLoopVar.name, 'y');
-    expect(forLoopParts.inKeyword, isNotNull);
-    var iterable = forLoopParts.iterable as SimpleIdentifier;
-    expect(iterable.name, 'list');
-
-    var body = second.body as IfElement;
-    var condition = body.condition as SimpleIdentifier;
-    expect(condition.name, 'c');
-    var thenElement = body.thenElement as MapLiteralEntry;
-    var thenValue = thenElement.value as IntegerLiteral;
-    expect(thenValue.value, 3);
-  }
-
-  void test_mapLiteral_forSpread() {
-    var map = parseCollectionLiteral('{1:7, for (x = 0; x < 10; ++x) ...{2:3}}')
-        as SetOrMapLiteral;
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 7);
-
-    var second = map.elements[1] as ForElement;
-    expect(second.awaitKeyword, isNull);
-    expect(second.forKeyword.isKeyword, isTrue);
-    expect(second.leftParenthesis.lexeme, '(');
-    expect(second.rightParenthesis.lexeme, ')');
-    var forLoopParts = second.forLoopParts as ForPartsWithExpression;
-    var forLoopInit = forLoopParts.initialization as AssignmentExpression;
-    var forLoopVar = forLoopInit.leftHandSide as SimpleIdentifier;
-    expect(forLoopVar.name, 'x');
-    var condition = forLoopParts.condition as BinaryExpression;
-    var rightOperand = condition.rightOperand as IntegerLiteral;
-    expect(rightOperand.value, 10);
-    var updater = forLoopParts.updaters[0] as PrefixExpression;
-    var updaterOperand = updater.operand as SimpleIdentifier;
-    expect(updaterOperand.name, 'x');
-  }
-
-  void test_mapLiteral_if() {
-    var map = parseCollectionLiteral('{1:1, if (true) 2:4}') as SetOrMapLiteral;
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 1);
-
-    var second = map.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as MapLiteralEntry;
-    var thenElementValue = thenElement.value as IntegerLiteral;
-    expect(thenElementValue.value, 4);
-    expect(second.elseElement, isNull);
-  }
-
-  void test_mapLiteral_ifElse() {
-    var map = parseCollectionLiteral('{1:1, if (true) 2:4 else 5:6}')
-        as SetOrMapLiteral;
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 1);
-
-    var second = map.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as MapLiteralEntry;
-    var thenElementValue = thenElement.value as IntegerLiteral;
-    expect(thenElementValue.value, 4);
-    var elseElement = second.elseElement as MapLiteralEntry;
-    var elseElementValue = elseElement.value as IntegerLiteral;
-    expect(elseElementValue.value, 6);
-  }
-
-  void test_mapLiteral_ifElseFor() {
-    var map =
-        parseCollectionLiteral('{1:1, if (true) 2:4 else for (c in d) 5:6}')
-            as SetOrMapLiteral;
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 1);
-
-    var second = map.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as MapLiteralEntry;
-    var thenElementValue = thenElement.value as IntegerLiteral;
-    expect(thenElementValue.value, 4);
-
-    var elseElement = second.elseElement as ForElement;
-    var forLoopParts = elseElement.forLoopParts as ForEachPartsWithIdentifier;
-    expect(forLoopParts.identifier.name, 'c');
-
-    var body = elseElement.body as MapLiteralEntry;
-    var bodyValue = body.value as IntegerLiteral;
-    expect(bodyValue.value, 6);
-  }
-
-  void test_mapLiteral_ifElseSpread() {
-    var map = parseCollectionLiteral('{1:7, if (true) ...{2:4} else ...?{5:6}}')
-        as SetOrMapLiteral;
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 7);
-
-    var second = map.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as SpreadElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    var elseElement = second.elseElement as SpreadElement;
-    expect(elseElement.spreadOperator.lexeme, '...?');
-    var elseElementExpression = elseElement.expression as SetOrMapLiteral;
-    expect(elseElementExpression.elements, hasLength(1));
-    var entry = elseElementExpression.elements[0] as MapLiteralEntry;
-    var entryValue = entry.value as IntegerLiteral;
-    expect(entryValue.value, 6);
-  }
-
-  void test_mapLiteral_ifFor() {
-    var map = parseCollectionLiteral('{1:1, if (true) for (a in b) 2:4}')
-        as SetOrMapLiteral;
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 1);
-
-    var second = map.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-
-    var thenElement = second.thenElement as ForElement;
-    var forLoopParts = thenElement.forLoopParts as ForEachPartsWithIdentifier;
-    expect(forLoopParts.identifier.name, 'a');
-
-    var body = thenElement.body as MapLiteralEntry;
-    var thenElementValue = body.value as IntegerLiteral;
-    expect(thenElementValue.value, 4);
-    expect(second.elseElement, isNull);
-  }
-
-  void test_mapLiteral_ifSpread() {
-    SetOrMapLiteral map = parseCollectionLiteral('{1:1, if (true) ...{2:4}}');
-    expect(map.elements, hasLength(2));
-    var first = map.elements[0] as MapLiteralEntry;
-    var firstValue = first.value as IntegerLiteral;
-    expect(firstValue.value, 1);
-
-    var second = map.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as SpreadElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    expect(second.elseElement, isNull);
-  }
-
-  void test_mapLiteral_spread() {
-    var map = parseCollectionLiteral('{1: 2, ...{3: 4}}') as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(2));
-
-    var element = map.elements[1] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...');
-    var spreadExpression = element.expression as SetOrMapLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spread2_typed() {
-    var map = parseCollectionLiteral('<int, int>{1: 2, ...{3: 4}}')
-        as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(2));
-
-    var element = map.elements[1] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...');
-    var spreadExpression = element.expression as SetOrMapLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spread_typed() {
-    var map =
-        parseCollectionLiteral('<int, int>{...{3: 4}}') as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(1));
-
-    var element = map.elements[0] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...');
-    var spreadExpression = element.expression as SetOrMapLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spreadQ() {
-    var map = parseCollectionLiteral('{1: 2, ...?{3: 4}}') as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(2));
-
-    var element = map.elements[1] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...?');
-    var spreadExpression = element.expression as SetOrMapLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spreadQ2_typed() {
-    var map = parseCollectionLiteral('<int, int>{1: 2, ...?{3: 4}}')
-        as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(2));
-
-    var element = map.elements[1] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...?');
-    var spreadExpression = element.expression as SetOrMapLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spreadQ_typed() {
-    var map =
-        parseCollectionLiteral('<int, int>{...?{3: 4}}') as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(1));
-
-    var element = map.elements[0] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...?');
-    var spreadExpression = element.expression as SetOrMapLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_setLiteral_if() {
-    var setLiteral =
-        parseCollectionLiteral('{1, if (true) 2}') as SetOrMapLiteral;
-    expect(setLiteral.elements, hasLength(2));
-    var first = setLiteral.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = setLiteral.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as IntegerLiteral;
-    expect(thenElement.value, 2);
-    expect(second.elseElement, isNull);
-  }
-
-  void test_setLiteral_ifElse() {
-    var setLiteral =
-        parseCollectionLiteral('{1, if (true) 2 else 5}') as SetOrMapLiteral;
-    expect(setLiteral.elements, hasLength(2));
-    var first = setLiteral.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = setLiteral.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as IntegerLiteral;
-    expect(thenElement.value, 2);
-    var elseElement = second.elseElement as IntegerLiteral;
-    expect(elseElement.value, 5);
-  }
-
-  void test_setLiteral_ifElseSpread() {
-    var setLiteral =
-        parseCollectionLiteral('{1, if (true) ...{2} else ...?[5]}')
-            as SetOrMapLiteral;
-    expect(setLiteral.elements, hasLength(2));
-    var first = setLiteral.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = setLiteral.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as SpreadElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    var theExpression = thenElement.expression as SetOrMapLiteral;
-    expect(theExpression.elements, hasLength(1));
-    var elseElement = second.elseElement as SpreadElement;
-    expect(elseElement.spreadOperator.lexeme, '...?');
-    var elseExpression = elseElement.expression as ListLiteral;
-    expect(elseExpression.elements, hasLength(1));
-  }
-
-  void test_setLiteral_ifSpread() {
-    var setLiteral =
-        parseCollectionLiteral('{1, if (true) ...[2]}') as SetOrMapLiteral;
-    expect(setLiteral.elements, hasLength(2));
-    var first = setLiteral.elements[0] as IntegerLiteral;
-    expect(first.value, 1);
-
-    var second = setLiteral.elements[1] as IfElement;
-    var condition = second.condition as BooleanLiteral;
-    expect(condition.value, isTrue);
-    var thenElement = second.thenElement as SpreadElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    expect(second.elseElement, isNull);
-  }
-
-  void test_setLiteral_spread2() {
-    var set = parseCollectionLiteral('{3, ...[4]}') as SetOrMapLiteral;
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNull);
-    expect(set.elements, hasLength(2));
-    var value = set.elements[0] as IntegerLiteral;
-    expect(value.value, 3);
-
-    var element = set.elements[1] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...');
-    var spreadExpression = element.expression as ListLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_setLiteral_spread2Q() {
-    var set = parseCollectionLiteral('{3, ...?[4]}') as SetOrMapLiteral;
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNull);
-    expect(set.elements, hasLength(2));
-    var value = set.elements[0] as IntegerLiteral;
-    expect(value.value, 3);
-
-    var element = set.elements[1] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...?');
-    var spreadExpression = element.expression as ListLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_setLiteral_spread_typed() {
-    var set = parseCollectionLiteral('<int>{...[3]}') as SetOrMapLiteral;
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNotNull);
-    expect(set.elements, hasLength(1));
-
-    var element = set.elements[0] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...');
-    var spreadExpression = element.expression as ListLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_setLiteral_spreadQ_typed() {
-    var set = parseCollectionLiteral('<int>{...?[3]}') as SetOrMapLiteral;
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNotNull);
-    expect(set.elements, hasLength(1));
-
-    var element = set.elements[0] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...?');
-    var spreadExpression = element.expression as ListLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_setOrMapLiteral_spread() {
-    var map = parseCollectionLiteral('{...{3: 4}}') as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(1));
-
-    var element = map.elements[0] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...');
-    var spreadExpression = element.expression as SetOrMapLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-
-  void test_setOrMapLiteral_spreadQ() {
-    var map = parseCollectionLiteral('{...?{3: 4}}') as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(1));
-
-    var element = map.elements[0] as SpreadElement;
-    expect(element.spreadOperator.lexeme, '...?');
-    var spreadExpression = element.expression as SetOrMapLiteral;
-    expect(spreadExpression.elements, hasLength(1));
-  }
-}
-
-/// Tests of the fasta parser based on [ComplexParserTestMixin].
-@reflectiveTest
-class ComplexParserTest_Fasta extends FastaParserTestCase
-    with ComplexParserTestMixin {
-  void test_binary_operator_written_out_expression() {
-    var expression = parseExpression('x xor y', errors: [
-      expectedError(ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT, 2, 3),
-    ]) as BinaryExpression;
-    var lhs = expression.leftOperand as SimpleIdentifier;
-    expect(lhs.name, 'x');
-    expect(expression.operator.lexeme, '^');
-    var rhs = expression.rightOperand as SimpleIdentifier;
-    expect(rhs.name, 'y');
-  }
-
-  void test_conditionalExpression_precedence_nullableType_as2() {
-    var statement =
-        parseStatement('x as bool? ? (x + y) : z;') as ExpressionStatement;
-    var expression = statement.expression as ConditionalExpression;
-    var asExpression = expression.condition as AsExpression;
-    var type = asExpression.type as TypeName;
-    expect(type.question.lexeme, '?');
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-    assertNoErrors();
-  }
-
-  void test_conditionalExpression_precedence_nullableType_as3() {
-    var statement =
-        parseStatement('(x as bool?) ? (x + y) : z;') as ExpressionStatement;
-    var expression = statement.expression as ConditionalExpression;
-    var condition = expression.condition as ParenthesizedExpression;
-    var asExpression = condition.expression as AsExpression;
-    var type = asExpression.type as TypeName;
-    expect(type.question.lexeme, '?');
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-    assertNoErrors();
-  }
-
-  void test_conditionalExpression_precedence_nullableType_is2() {
-    var statement =
-        parseStatement('x is String? ? (x + y) : z;') as ExpressionStatement;
-    var expression = statement.expression as ConditionalExpression;
-    var isExpression = expression.condition as IsExpression;
-    var type = isExpression.type as TypeName;
-    expect(type.question.lexeme, '?');
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-    assertNoErrors();
-  }
-
-  void test_conditionalExpression_precedence_nullableType_is3() {
-    var statement =
-        parseStatement('(x is String?) ? (x + y) : z;') as ExpressionStatement;
-    var expression = statement.expression as ConditionalExpression;
-    var condition = expression.condition as ParenthesizedExpression;
-    var isExpression = condition.expression as IsExpression;
-    var type = isExpression.type as TypeName;
-    expect(type.question.lexeme, '?');
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-    assertNoErrors();
-  }
-}
-
-/// Tests of the fasta parser based on [ErrorParserTest].
-@reflectiveTest
-class ErrorParserTest_Fasta extends FastaParserTestCase
-    with ErrorParserTestMixin {
-  void test_await_missing_async2_issue36048() {
-    parseCompilationUnit('''
-main() { // missing async
-  await foo.bar();
-}
-''', errors: [
-      expectedError(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 28, 5)
-    ]);
-  }
-
-  void test_await_missing_async3_issue36048() {
-    parseCompilationUnit('''
-main() { // missing async
-  (await foo);
-}
-''', errors: [
-      expectedError(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 29, 5)
-    ]);
-  }
-
-  void test_await_missing_async4_issue36048() {
-    parseCompilationUnit('''
-main() { // missing async
-  [await foo];
-}
-''', errors: [
-      expectedError(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 29, 5)
-    ]);
-  }
-
-  void test_await_missing_async_issue36048() {
-    parseCompilationUnit('''
-main() { // missing async
-  await foo();
-}
-''', errors: [
-      expectedError(CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT, 28, 5)
-    ]);
-  }
-
-  void test_constructor_super_cascade_synthetic() {
-    // https://github.com/dart-lang/sdk/issues/37110
-    parseCompilationUnit('class B extends A { B(): super.. {} }', errors: [
-      expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 2),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 33, 1),
-    ]);
-  }
-
-  void test_constructor_super_field() {
-    // https://github.com/dart-lang/sdk/issues/36262
-    // https://github.com/dart-lang/sdk/issues/31198
-    parseCompilationUnit('class B extends A { B(): super().foo {} }', errors: [
-      expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
-    ]);
-  }
-
-  void test_constructor_super_method() {
-    // https://github.com/dart-lang/sdk/issues/36262
-    // https://github.com/dart-lang/sdk/issues/31198
-    parseCompilationUnit('class B extends A { B(): super().foo() {} }',
-        errors: [
-          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
-        ]);
-  }
-
-  void test_constructor_super_named_method() {
-    // https://github.com/dart-lang/sdk/issues/37600
-    parseCompilationUnit('class B extends A { B(): super.c().create() {} }',
-        errors: [
-          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
-        ]);
-  }
-
-  void test_constructor_super_named_method_method() {
-    // https://github.com/dart-lang/sdk/issues/37600
-    parseCompilationUnit('class B extends A { B(): super.c().create().x() {} }',
-        errors: [
-          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
-        ]);
-  }
-
-  void test_constructor_this_cascade_synthetic() {
-    // https://github.com/dart-lang/sdk/issues/37110
-    parseCompilationUnit('class B extends A { B(): this.. {} }', errors: [
-      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 25, 4),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 29, 2),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 32, 1),
-    ]);
-  }
-
-  void test_constructor_this_field() {
-    // https://github.com/dart-lang/sdk/issues/36262
-    // https://github.com/dart-lang/sdk/issues/31198
-    parseCompilationUnit('class B extends A { B(): this().foo; }', errors: [
-      expectedError(ParserErrorCode.INVALID_THIS_IN_INITIALIZER, 25, 4),
-    ]);
-  }
-
-  void test_constructor_this_method() {
-    // https://github.com/dart-lang/sdk/issues/36262
-    // https://github.com/dart-lang/sdk/issues/31198
-    parseCompilationUnit('class B extends A { B(): this().foo(); }', errors: [
-      expectedError(ParserErrorCode.INVALID_THIS_IN_INITIALIZER, 25, 4),
-    ]);
-  }
-
-  void test_constructor_this_named_method() {
-    // https://github.com/dart-lang/sdk/issues/37600
-    parseCompilationUnit('class B extends A { B(): super.c().create() {} }',
-        errors: [
-          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
-        ]);
-  }
-
-  void test_constructor_this_named_method_field() {
-    // https://github.com/dart-lang/sdk/issues/37600
-    parseCompilationUnit('class B extends A { B(): super.c().create().x {} }',
-        errors: [
-          expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 25, 5),
-        ]);
-  }
-
-  @override
-  void test_expectedListOrMapLiteral() {
-    // The fasta parser returns an 'IntegerLiteralImpl' when parsing '1'.
-    // This test is not expected to ever pass.
-    //super.test_expectedListOrMapLiteral();
-  }
-
-  @override
-  void test_expectedStringLiteral() {
-    // The fasta parser returns an 'IntegerLiteralImpl' when parsing '1'.
-    // This test is not expected to ever pass.
-    //super.test_expectedStringLiteral();
-  }
-
-  void test_factory_issue_36400() {
-    parseCompilationUnit('class T { T factory T() { return null; } }',
-        errors: [expectedError(ParserErrorCode.TYPE_BEFORE_FACTORY, 10, 1)]);
-  }
-
-  void test_getterNativeWithBody() {
-    createParser('String get m native "str" => 0;');
-    parser.parseClassMember('C') as MethodDeclaration;
-    if (!allowNativeClause) {
-      assertErrorsWithCodes([
-        ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
-        ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
-      ]);
-    } else {
-      assertErrorsWithCodes([
-        ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
-      ]);
-    }
-  }
-
-  void test_invalidOperatorAfterSuper_constructorInitializer2() {
-    parseCompilationUnit('class C { C() : super?.namedConstructor(); }',
-        errors: [
-          expectedError(
-              ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER,
-              21,
-              2)
-        ]);
-  }
-
-  void test_missing_closing_bracket_issue37528() {
-    final code = '\${foo';
-    createParser(code);
-    final result = fasta.scanString(code);
-    expect(result.hasErrors, isTrue);
-    var token = _parserProxy.fastaParser.syntheticPreviousToken(result.tokens);
-    try {
-      _parserProxy.fastaParser.parseExpression(token);
-      // TODO(danrubel): Replace this test once root cause is found
-      fail('exception expected');
-    } catch (e) {
-      var msg = e.toString();
-      expect(msg.contains('test_missing_closing_bracket_issue37528'), isTrue);
-    }
-  }
-
-  void test_partialNamedConstructor() {
-    parseCompilationUnit('class C { C. }', errors: [
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
-      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 13, 1),
-    ]);
-  }
-
-  void test_staticOperatorNamedMethod() {
-    // operator can be used as a method name
-    parseCompilationUnit('class C { static operator(x) => x; }');
-  }
-
-  void test_yieldAsLabel() {
-    // yield can be used as a label
-    parseCompilationUnit('main() { yield: break yield; }');
-  }
-}
-
-/// Tests of the fasta parser based on [ExpressionParserTestMixin].
-@reflectiveTest
-class ExpressionParserTest_Fasta extends FastaParserTestCase
-    with ExpressionParserTestMixin {
-  final beforeUiAsCode = FeatureSet.fromEnableFlags2(
-    sdkLanguageVersion: Version.parse('2.2.0'),
-    flags: [],
-  );
-
-  void test_binaryExpression_allOperators() {
-    // https://github.com/dart-lang/sdk/issues/36255
-    for (TokenType type in TokenType.all) {
-      if (type.precedence > 0) {
-        var source = 'a ${type.lexeme} b';
-        try {
-          parseExpression(source);
-        } on TestFailure {
-          // Ensure that there are no infinite loops or exceptions thrown
-          // by the parser. Test failures are fine.
-        }
-      }
-    }
-  }
-
-  void test_invalidExpression_37706() {
-    // https://github.com/dart-lang/sdk/issues/37706
-    parseExpression('<b?c>()', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 1, 1),
-      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 0),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 7, 0),
-    ]);
-  }
-
-  void test_listLiteral_invalid_assert() {
-    // https://github.com/dart-lang/sdk/issues/37674
-    parseExpression('n=<.["\$assert', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 3, 1),
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
-      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 6),
-      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 12, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 13, 1),
-    ]);
-  }
-
-  void test_listLiteral_invalidElement_37697() {
-    // https://github.com/dart-lang/sdk/issues/37674
-    parseExpression('[<y.<z>(){}]', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1),
-    ]);
-  }
-
-  void test_lt_dot_bracket_quote() {
-    // https://github.com/dart-lang/sdk/issues/37674
-    var list = parseExpression('<.["', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 1, 1),
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 1),
-      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 3, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 4, 1),
-    ]) as ListLiteral;
-    expect(list.elements, hasLength(1));
-    var first = list.elements[0] as StringLiteral;
-    expect(first.length, 1);
-  }
-
-  void test_lt_dot_listLiteral() {
-    // https://github.com/dart-lang/sdk/issues/37674
-    var list = parseExpression('<.[]', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 1, 1),
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 2),
-    ]) as ListLiteral;
-    expect(list.elements, hasLength(0));
-  }
-
-  void test_mapLiteral() {
-    var map = parseExpression('{3: 6}') as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(1));
-    var entry = map.elements[0] as MapLiteralEntry;
-    var key = entry.key as IntegerLiteral;
-    expect(key.value, 3);
-    var value = entry.value as IntegerLiteral;
-    expect(value.value, 6);
-  }
-
-  void test_mapLiteral_const() {
-    var map = parseExpression('const {3: 6}') as SetOrMapLiteral;
-    expect(map.constKeyword, isNotNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(1));
-    var entry = map.elements[0] as MapLiteralEntry;
-    var key = entry.key as IntegerLiteral;
-    expect(key.value, 3);
-    var value = entry.value as IntegerLiteral;
-    expect(value.value, 6);
-  }
-
-  @failingTest
-  void test_mapLiteral_invalid_too_many_type_arguments1() {
-    var map = parseExpression('<int, int, int>{}', errors: [
-      // TODO(danrubel): Currently the resolver reports invalid number of
-      // type arguments, but the parser could report this.
-      expectedError(
-          /* ParserErrorCode.EXPECTED_ONE_OR_TWO_TYPE_VARIABLES */
-          ParserErrorCode.EXPECTED_TOKEN,
-          11,
-          3),
-    ]) as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.elements, hasLength(0));
-  }
-
-  @failingTest
-  void test_mapLiteral_invalid_too_many_type_arguments2() {
-    var map = parseExpression('<int, int, int>{1}', errors: [
-      // TODO(danrubel): Currently the resolver reports invalid number of
-      // type arguments, but the parser could report this.
-      expectedError(
-          /* ParserErrorCode.EXPECTED_ONE_OR_TWO_TYPE_VARIABLES */
-          ParserErrorCode.EXPECTED_TOKEN,
-          11,
-          3),
-    ]) as SetOrMapLiteral;
-    expect(map.constKeyword, isNull);
-    expect(map.elements, hasLength(0));
-  }
-
-  void test_parseConstructorInitializer_functionExpression() {
-    // https://github.com/dart-lang/sdk/issues/37414
-    parseCompilationUnit('class C { C.n() : this()(); }', errors: [
-      expectedError(ParserErrorCode.INVALID_INITIALIZER, 18, 8),
-    ]);
-  }
-
-  void test_parseStringLiteral_interpolated_void() {
-    Expression expression = parseStringLiteral(r"'<html>$void</html>'");
-    expect(expression, isNotNull);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 8, 4)
-    ]);
-    expect(expression, isStringInterpolation);
-    var literal = expression as StringInterpolation;
-    NodeList<InterpolationElement> elements = literal.elements;
-    expect(elements, hasLength(3));
-    expect(elements[0] is InterpolationString, isTrue);
-    expect(elements[1] is InterpolationExpression, isTrue);
-    expect(elements[2] is InterpolationString, isTrue);
-    expect((elements[1] as InterpolationExpression).leftBracket.lexeme, '\$');
-    expect((elements[1] as InterpolationExpression).rightBracket, isNull);
-  }
-
-  @override
-  @failingTest
-  void test_parseUnaryExpression_decrement_super() {
-    // TODO(danrubel) Reports a different error and different token stream.
-    // Expected: TokenType:<MINUS>
-    //   Actual: TokenType:<MINUS_MINUS>
-    super.test_parseUnaryExpression_decrement_super();
-  }
-
-  @override
-  @failingTest
-  void test_parseUnaryExpression_decrement_super_withComment() {
-    // TODO(danrubel) Reports a different error and different token stream.
-    // Expected: TokenType:<MINUS>
-    //   Actual: TokenType:<MINUS_MINUS>
-    super.test_parseUnaryExpression_decrement_super_withComment();
-  }
-
-  void test_setLiteral() {
-    SetOrMapLiteral set = parseExpression('{3}');
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNull);
-    expect(set.elements, hasLength(1));
-    IntegerLiteral value = set.elements[0];
-    expect(value.value, 3);
-  }
-
-  void test_setLiteral_const() {
-    SetOrMapLiteral set = parseExpression('const {3, 6}');
-    expect(set.constKeyword, isNotNull);
-    expect(set.typeArguments, isNull);
-    expect(set.elements, hasLength(2));
-    IntegerLiteral value1 = set.elements[0];
-    expect(value1.value, 3);
-    IntegerLiteral value2 = set.elements[1];
-    expect(value2.value, 6);
-  }
-
-  void test_setLiteral_const_typed() {
-    SetOrMapLiteral set = parseExpression('const <int>{3}');
-    expect(set.constKeyword, isNotNull);
-    expect(set.typeArguments.arguments, hasLength(1));
-    NamedType typeArg = set.typeArguments.arguments[0];
-    expect(typeArg.name.name, 'int');
-    expect(set.elements.length, 1);
-    IntegerLiteral value = set.elements[0];
-    expect(value.value, 3);
-  }
-
-  void test_setLiteral_nested_typeArgument() {
-    SetOrMapLiteral set = parseExpression('<Set<int>>{{3}}');
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments.arguments, hasLength(1));
-    NamedType typeArg1 = set.typeArguments.arguments[0];
-    expect(typeArg1.name.name, 'Set');
-    expect(typeArg1.typeArguments.arguments, hasLength(1));
-    NamedType typeArg2 = typeArg1.typeArguments.arguments[0];
-    expect(typeArg2.name.name, 'int');
-    expect(set.elements.length, 1);
-    SetOrMapLiteral intSet = set.elements[0];
-    expect(intSet.elements, hasLength(1));
-    IntegerLiteral value = intSet.elements[0];
-    expect(value.value, 3);
-  }
-
-  void test_setLiteral_typed() {
-    SetOrMapLiteral set = parseExpression('<int>{3}');
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments.arguments, hasLength(1));
-    NamedType typeArg = set.typeArguments.arguments[0];
-    expect(typeArg.name.name, 'int');
-    expect(set.elements.length, 1);
-    IntegerLiteral value = set.elements[0];
-    expect(value.value, 3);
-  }
-}
-
-@reflectiveTest
-class ExtensionMethodsParserTest_Fasta extends FastaParserTestCase {
-  void test_complex_extends() {
-    var unit = parseCompilationUnit(
-        'extension E extends A with B, C implements D { }',
-        errors: [
-          expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
-          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 4),
-          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
-          expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 32, 10),
-        ]);
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'extends');
-    expect((extension.extendedType as NamedType).name.name, 'A');
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_complex_implements() {
-    var unit = parseCompilationUnit('extension E implements C, D { }', errors: [
-      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
-      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 24, 1),
-    ]);
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'implements');
-    expect((extension.extendedType as NamedType).name.name, 'C');
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_complex_type() {
-    var unit = parseCompilationUnit('extension E on C<T> { }');
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'on');
-    var namedType = extension.extendedType as NamedType;
-    expect(namedType.name.name, 'C');
-    expect(namedType.typeArguments.arguments, hasLength(1));
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_complex_type2() {
-    var unit = parseCompilationUnit('extension E<T> on C<T> { }');
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'on');
-    var namedType = extension.extendedType as NamedType;
-    expect(namedType.name.name, 'C');
-    expect(namedType.typeArguments.arguments, hasLength(1));
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_complex_type2_no_name() {
-    var unit = parseCompilationUnit('extension<T> on C<T> { }');
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name, isNull);
-    expect(extension.onKeyword.lexeme, 'on');
-    var namedType = extension.extendedType as NamedType;
-    expect(namedType.name.name, 'C');
-    expect(namedType.typeArguments.arguments, hasLength(1));
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_constructor_named() {
-    var unit = parseCompilationUnit('''
-extension E on C {
-  E.named();
-}
-class C {}
-''', errors: [
-      expectedError(ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR, 21, 1),
-    ]);
-    expect(unit.declarations, hasLength(2));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_constructor_unnamed() {
-    var unit = parseCompilationUnit('''
-extension E on C {
-  E();
-}
-class C {}
-''', errors: [
-      expectedError(ParserErrorCode.EXTENSION_DECLARES_CONSTRUCTOR, 21, 1),
-    ]);
-    expect(unit.declarations, hasLength(2));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_missing_on() {
-    var unit = parseCompilationUnit('extension E', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 11, 0),
-      expectedError(ParserErrorCode.EXPECTED_BODY, 11, 0),
-    ]);
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'on');
-    expect((extension.extendedType as NamedType).name.name, '');
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_missing_on_withBlock() {
-    var unit = parseCompilationUnit('extension E {}', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
-      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
-    ]);
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'on');
-    expect((extension.extendedType as NamedType).name.name, '');
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_missing_on_withClassAndBlock() {
-    var unit = parseCompilationUnit('extension E C {}', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
-    ]);
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'on');
-    expect((extension.extendedType as NamedType).name.name, 'C');
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_parse_toplevel_member_called_late_calling_self() {
-    CompilationUnitImpl unit = parseCompilationUnit('void late() { late(); }',
-        featureSet: nonNullable);
-    FunctionDeclaration method = unit.declarations[0];
-
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name.name, 'late');
-    expect(method.functionExpression, isNotNull);
-
-    BlockFunctionBody body = method.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    MethodInvocation invocation = statement.expression;
-    expect(invocation.operator, isNull);
-    expect(invocation.toSource(), 'late()');
-  }
-
-  void test_simple() {
-    var unit = parseCompilationUnit('extension E on C { }');
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'on');
-    expect((extension.extendedType as NamedType).name.name, 'C');
-    var namedType = extension.extendedType as NamedType;
-    expect(namedType.name.name, 'C');
-    expect(namedType.typeArguments, isNull);
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_simple_extends() {
-    var unit = parseCompilationUnit('extension E extends C { }', errors: [
-      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
-    ]);
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'extends');
-    expect((extension.extendedType as NamedType).name.name, 'C');
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_simple_implements() {
-    var unit = parseCompilationUnit('extension E implements C { }', errors: [
-      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
-    ]);
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'implements');
-    expect((extension.extendedType as NamedType).name.name, 'C');
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_simple_no_name() {
-    var unit = parseCompilationUnit('extension on C { }');
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name, isNull);
-    expect(extension.onKeyword.lexeme, 'on');
-    expect((extension.extendedType as NamedType).name.name, 'C');
-    var namedType = extension.extendedType as NamedType;
-    expect(namedType.name.name, 'C');
-    expect(namedType.typeArguments, isNull);
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_simple_not_enabled() {
-    parseCompilationUnit(
-      'extension E on C { }',
-      errors: [
-        expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 0, 9),
-        expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 15, 1)
-      ],
-      featureSet: FeatureSet.fromEnableFlags2(
-        sdkLanguageVersion: Version.parse('2.3.0'),
-        flags: [],
-      ),
-    );
-  }
-
-  void test_simple_with() {
-    var unit = parseCompilationUnit('extension E with C { }', errors: [
-      expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 4),
-    ]);
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'with');
-    expect((extension.extendedType as NamedType).name.name, 'C');
-    expect(extension.members, hasLength(0));
-  }
-
-  void test_void_type() {
-    var unit = parseCompilationUnit('extension E on void { }');
-    expect(unit.declarations, hasLength(1));
-    var extension = unit.declarations[0] as ExtensionDeclaration;
-    expect(extension.name.name, 'E');
-    expect(extension.onKeyword.lexeme, 'on');
-    expect((extension.extendedType as NamedType).name.name, 'void');
-    expect(extension.members, hasLength(0));
-  }
-}
-
-/// Implementation of [AbstractParserTestCase] specialized for testing the
-/// Fasta parser.
-class FastaParserTestCase
-    with ParserTestHelpers
-    implements AbstractParserTestCase {
-  static final List<ErrorCode> NO_ERROR_COMPARISON = <ErrorCode>[];
-
-  final controlFlow = FeatureSet.latestLanguageVersion();
-
-  final spread = FeatureSet.latestLanguageVersion();
-
-  final nonNullable = FeatureSet.latestLanguageVersion();
-
-  final preNonNullable = FeatureSet.fromEnableFlags2(
-    sdkLanguageVersion: Version.parse('2.9.0'),
-    flags: [],
-  );
-
-  ParserProxy _parserProxy;
-
-  analyzer.Token _fastaTokens;
-
-  @override
-  bool allowNativeClause = false;
-
-  @override
-  set enableOptionalNewAndConst(bool enable) {
-    // ignored
-  }
-
-  @override
-  set enableUriInPartOf(bool value) {
-    if (value == false) {
-      throw UnimplementedError(
-          'URIs in "part of" declarations cannot be disabled in Fasta.');
-    }
-  }
-
-  @override
-  GatheringErrorListener get listener => _parserProxy._errorListener;
-
-  @override
-  analyzer.Parser get parser => _parserProxy;
-
-  @override
-  bool get usingFastaParser => true;
-
-  void assertErrors({List<ErrorCode> codes, List<ExpectedError> errors}) {
-    if (codes != null) {
-      if (!identical(codes, NO_ERROR_COMPARISON)) {
-        assertErrorsWithCodes(codes);
-      }
-    } else if (errors != null) {
-      listener.assertErrors(errors);
-    } else {
-      assertNoErrors();
-    }
-  }
-
-  @override
-  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
-    _parserProxy._errorListener.assertErrorsWithCodes(
-        _toFastaGeneratedAnalyzerErrorCodes(expectedErrorCodes));
-  }
-
-  @override
-  void assertNoErrors() {
-    _parserProxy._errorListener.assertNoErrors();
-  }
-
-  @override
-  void createParser(String content,
-      {int expectedEndOffset, FeatureSet featureSet}) {
-    featureSet ??= FeatureSet.forTesting();
-    var result = scanString(content,
-        configuration: featureSet.isEnabled(Feature.non_nullable)
-            ? ScannerConfiguration.nonNullable
-            : ScannerConfiguration.classic,
-        includeComments: true);
-    _fastaTokens = result.tokens;
-    _parserProxy = ParserProxy(_fastaTokens, featureSet,
-        allowNativeClause: allowNativeClause,
-        expectedEndOffset: expectedEndOffset);
-  }
-
-  @override
-  ExpectedError expectedError(ErrorCode code, int offset, int length) =>
-      ExpectedError(_toFastaGeneratedAnalyzerErrorCode(code), offset, length);
-
-  @override
-  void expectNotNullIfNoErrors(Object result) {
-    if (!listener.hasErrors) {
-      expect(result, isNotNull);
-    }
-  }
-
-  @override
-  Expression parseAdditiveExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  Expression parseArgument(String source) {
-    createParser(source);
-    return _parserProxy.parseArgument();
-  }
-
-  @override
-  Expression parseAssignableExpression(String code, bool primaryAllowed) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseAssignableSelector(String code, bool optional,
-      {bool allowConditional = true}) {
-    if (optional) {
-      if (code.isEmpty) {
-        return _parseExpression('foo');
-      }
-      return _parseExpression('(foo)$code');
-    }
-    return _parseExpression('foo$code');
-  }
-
-  @override
-  AwaitExpression parseAwaitExpression(String code) {
-    var function = _parseExpression('() async => $code') as FunctionExpression;
-    return (function.body as ExpressionFunctionBody).expression;
-  }
-
-  @override
-  Expression parseBitwiseAndExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseBitwiseOrExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseBitwiseXorExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseCascadeSection(String code) {
-    var cascadeExpression = _parseExpression('null$code') as CascadeExpression;
-    return cascadeExpression.cascadeSections.first;
-  }
-
-  @override
-  CommentReference parseCommentReference(
-      String referenceSource, int sourceOffset) {
-    String padding = ' '.padLeft(sourceOffset - 4, 'a');
-    String source = '/**$padding[$referenceSource] */ class C { }';
-    CompilationUnit unit = parseCompilationUnit(source);
-    ClassDeclaration clazz = unit.declarations[0];
-    Comment comment = clazz.documentationComment;
-    List<CommentReference> references = comment.references;
-    if (references.isEmpty) {
-      return null;
-    } else {
-      expect(references, hasLength(1));
-      return references[0];
-    }
-  }
-
-  @override
-  CompilationUnit parseCompilationUnit(String content,
-      {List<ErrorCode> codes,
-      List<ExpectedError> errors,
-      FeatureSet featureSet}) {
-    GatheringErrorListener listener = GatheringErrorListener(checkRanges: true);
-
-    CompilationUnit unit =
-        parseCompilationUnit2(content, listener, featureSet: featureSet);
-
-    // Assert and return result
-    if (codes != null) {
-      listener
-          .assertErrorsWithCodes(_toFastaGeneratedAnalyzerErrorCodes(codes));
-    } else if (errors != null) {
-      listener.assertErrors(errors);
-    } else {
-      listener.assertNoErrors();
-    }
-    return unit;
-  }
-
-  CompilationUnit parseCompilationUnit2(
-      String content, GatheringErrorListener listener,
-      {LanguageVersionToken languageVersion, FeatureSet featureSet}) {
-    featureSet ??= FeatureSet.forTesting();
-    var source = StringSource(content, 'parser_test_StringSource.dart');
-
-    // Adjust the feature set based on language version comment.
-    void languageVersionChanged(
-        fasta.Scanner scanner, LanguageVersionToken languageVersion) {
-      featureSet = featureSet.restrictToVersion(
-          Version(languageVersion.major, languageVersion.minor, 0));
-      scanner.configuration = Scanner.buildConfig(featureSet);
-    }
-
-    // Scan tokens
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        configuration: Scanner.buildConfig(featureSet),
-        languageVersionChanged: languageVersionChanged);
-    _fastaTokens = result.tokens;
-
-    // Run parser
-    ErrorReporter errorReporter = ErrorReporter(
-      listener,
-      source,
-      isNonNullableByDefault: false,
-    );
-    fasta.Parser parser = fasta.Parser(null);
-    AstBuilder astBuilder =
-        AstBuilder(errorReporter, source.uri, true, featureSet);
-    parser.listener = astBuilder;
-    astBuilder.parser = parser;
-    astBuilder.allowNativeClause = allowNativeClause;
-    parser.parseUnit(_fastaTokens);
-    CompilationUnitImpl unit = astBuilder.pop();
-
-    expect(unit, isNotNull);
-    return unit;
-  }
-
-  @override
-  ConditionalExpression parseConditionalExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseConstExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  ConstructorInitializer parseConstructorInitializer(String code) {
-    createParser('class __Test { __Test() : $code; }');
-    CompilationUnit unit = _parserProxy.parseCompilationUnit2();
-    assertNoErrors();
-    var clazz = unit.declarations[0] as ClassDeclaration;
-    var constructor = clazz.members[0] as ConstructorDeclaration;
-    return constructor.initializers.single;
-  }
-
-  @override
-  CompilationUnit parseDirectives(String source,
-      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
-    createParser(source);
-    CompilationUnit unit =
-        _parserProxy.parseDirectives(_parserProxy.currentToken);
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(0));
-    listener.assertErrorsWithCodes(errorCodes);
-    return unit;
-  }
-
-  @override
-  BinaryExpression parseEqualityExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseExpression(String source,
-      {List<ErrorCode> codes,
-      List<ExpectedError> errors,
-      int expectedEndOffset,
-      bool inAsync = false,
-      FeatureSet featureSet}) {
-    createParser(source,
-        expectedEndOffset: expectedEndOffset, featureSet: featureSet);
-    if (inAsync) {
-      _parserProxy.fastaParser.asyncState = AsyncModifier.Async;
-    }
-    Expression result = _parserProxy.parseExpression2();
-    assertErrors(codes: codes, errors: errors);
-    return result;
-  }
-
-  @override
-  List<Expression> parseExpressionList(String code) {
-    return (_parseExpression('[$code]') as ListLiteral)
-        .elements
-        .toList()
-        .cast<Expression>();
-  }
-
-  @override
-  Expression parseExpressionWithoutCascade(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  FormalParameter parseFormalParameter(String code, ParameterKind kind,
-      {List<ErrorCode> errorCodes = const <ErrorCode>[],
-      FeatureSet featureSet}) {
-    String parametersCode;
-    if (kind == ParameterKind.REQUIRED) {
-      parametersCode = '($code)';
-    } else if (kind == ParameterKind.POSITIONAL) {
-      parametersCode = '([$code])';
-    } else if (kind == ParameterKind.NAMED) {
-      parametersCode = '({$code})';
-    } else {
-      fail('$kind');
-    }
-    FormalParameterList list = parseFormalParameterList(parametersCode,
-        inFunctionType: false, errorCodes: errorCodes, featureSet: featureSet);
-    return list.parameters.single;
-  }
-
-  @override
-  FormalParameterList parseFormalParameterList(String code,
-      {bool inFunctionType = false,
-      List<ErrorCode> errorCodes = const <ErrorCode>[],
-      List<ExpectedError> errors,
-      FeatureSet featureSet}) {
-    createParser(code, featureSet: featureSet);
-    FormalParameterList result =
-        _parserProxy.parseFormalParameterList(inFunctionType: inFunctionType);
-    assertErrors(codes: errors != null ? null : errorCodes, errors: errors);
-    return result;
-  }
-
-  @override
-  CompilationUnitMember parseFullCompilationUnitMember() {
-    return _parserProxy.parseTopLevelDeclaration(false);
-  }
-
-  @override
-  Directive parseFullDirective() {
-    return _parserProxy.parseTopLevelDeclaration(true);
-  }
-
-  @override
-  FunctionExpression parseFunctionExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  InstanceCreationExpression parseInstanceCreationExpression(
-      String code, analyzer.Token newToken) {
-    return _parseExpression('$newToken $code');
-  }
-
-  @override
-  ListLiteral parseListLiteral(
-      analyzer.Token token, String typeArgumentsCode, String code) {
-    String sc = '';
-    if (token != null) {
-      sc += token.lexeme + ' ';
-    }
-    if (typeArgumentsCode != null) {
-      sc += typeArgumentsCode;
-    }
-    sc += code;
-    return _parseExpression(sc);
-  }
-
-  @override
-  TypedLiteral parseListOrMapLiteral(analyzer.Token modifier, String code) {
-    String literalCode = modifier != null ? '$modifier $code' : code;
-    return parsePrimaryExpression(literalCode) as TypedLiteral;
-  }
-
-  @override
-  Expression parseLogicalAndExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseLogicalOrExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  SetOrMapLiteral parseMapLiteral(
-      analyzer.Token token, String typeArgumentsCode, String code) {
-    String sc = '';
-    if (token != null) {
-      sc += token.lexeme + ' ';
-    }
-    if (typeArgumentsCode != null) {
-      sc += typeArgumentsCode;
-    }
-    sc += code;
-    return parsePrimaryExpression(sc) as SetOrMapLiteral;
-  }
-
-  @override
-  MapLiteralEntry parseMapLiteralEntry(String code) {
-    var mapLiteral = parseMapLiteral(null, null, '{ $code }');
-    return mapLiteral.elements.single;
-  }
-
-  @override
-  Expression parseMultiplicativeExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  InstanceCreationExpression parseNewExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  NormalFormalParameter parseNormalFormalParameter(String code,
-      {bool inFunctionType = false,
-      List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
-    FormalParameterList list = parseFormalParameterList('($code)',
-        inFunctionType: inFunctionType, errorCodes: errorCodes);
-    return list.parameters.single;
-  }
-
-  @override
-  Expression parsePostfixExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Identifier parsePrefixedIdentifier(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parsePrimaryExpression(String code,
-      {int expectedEndOffset, List<ExpectedError> errors}) {
-    createParser(code, expectedEndOffset: expectedEndOffset);
-    Expression result = _parserProxy.parsePrimaryExpression();
-    assertErrors(codes: null, errors: errors);
-    return result;
-  }
-
-  @override
-  Expression parseRelationalExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  RethrowExpression parseRethrowExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  BinaryExpression parseShiftExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  SimpleIdentifier parseSimpleIdentifier(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Statement parseStatement(String source,
-      {int expectedEndOffset, FeatureSet featureSet, bool inAsync = false}) {
-    createParser(source,
-        expectedEndOffset: expectedEndOffset, featureSet: featureSet);
-    if (inAsync) {
-      _parserProxy.fastaParser.asyncState = AsyncModifier.Async;
-    }
-    Statement statement = _parserProxy.parseStatement2();
-    assertErrors(codes: NO_ERROR_COMPARISON);
-    return statement;
-  }
-
-  @override
-  Expression parseStringLiteral(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  SymbolLiteral parseSymbolLiteral(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseThrowExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  Expression parseThrowExpressionWithoutCascade(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  PrefixExpression parseUnaryExpression(String code) {
-    return _parseExpression(code);
-  }
-
-  @override
-  VariableDeclarationList parseVariableDeclarationList(String code) {
-    var statement = parseStatement('$code;') as VariableDeclarationStatement;
-    return statement.variables;
-  }
-
-  Expression _parseExpression(String code) {
-    var statement = parseStatement('$code;') as ExpressionStatement;
-    return statement.expression;
-  }
-
-  ErrorCode _toFastaGeneratedAnalyzerErrorCode(ErrorCode code) {
-    if (code == ParserErrorCode.ABSTRACT_ENUM ||
-        code == ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION ||
-        code == ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE ||
-        code == ParserErrorCode.ABSTRACT_TYPEDEF ||
-        code == ParserErrorCode.CONST_ENUM ||
-        code == ParserErrorCode.CONST_TYPEDEF ||
-        code == ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION ||
-        code == ParserErrorCode.FINAL_CLASS ||
-        code == ParserErrorCode.FINAL_ENUM ||
-        code == ParserErrorCode.FINAL_TYPEDEF ||
-        code == ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION) {
-      return ParserErrorCode.EXTRANEOUS_MODIFIER;
-    }
-    return code;
-  }
-
-  List<ErrorCode> _toFastaGeneratedAnalyzerErrorCodes(
-          List<ErrorCode> expectedErrorCodes) =>
-      expectedErrorCodes.map(_toFastaGeneratedAnalyzerErrorCode).toList();
-}
-
-/// Tests of the fasta parser based on [FormalParameterParserTestMixin].
-@reflectiveTest
-class FormalParameterParserTest_Fasta extends FastaParserTestCase
-    with FormalParameterParserTestMixin {
-  FormalParameter parseNNBDFormalParameter(String code, ParameterKind kind,
-      {List<ExpectedError> errors}) {
-    String parametersCode;
-    if (kind == ParameterKind.REQUIRED) {
-      parametersCode = '($code)';
-    } else if (kind == ParameterKind.POSITIONAL) {
-      parametersCode = '([$code])';
-    } else if (kind == ParameterKind.NAMED) {
-      parametersCode = '({$code})';
-    } else {
-      fail('$kind');
-    }
-    createParser(parametersCode, featureSet: nonNullable);
-    FormalParameterList list =
-        _parserProxy.parseFormalParameterList(inFunctionType: false);
-    assertErrors(errors: errors);
-    return list.parameters.single;
-  }
-
-  void test_fieldFormalParameter_function_nullable() {
-    var parameter =
-        parseNNBDFormalParameter('void this.a()?', ParameterKind.REQUIRED);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter functionParameter = parameter;
-    expect(functionParameter.type, isNotNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNotNull);
-    expect(functionParameter.endToken, functionParameter.question);
-  }
-
-  void test_functionTyped_named_nullable() {
-    ParameterKind kind = ParameterKind.NAMED;
-    var defaultParameter =
-        parseNNBDFormalParameter('a()? : null', kind) as DefaultFormalParameter;
-    var functionParameter =
-        defaultParameter.parameter as FunctionTypedFormalParameter;
-    assertNoErrors();
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.isNamed, isTrue);
-    expect(functionParameter.question, isNotNull);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_functionTyped_named_nullable_disabled() {
-    ParameterKind kind = ParameterKind.NAMED;
-    var defaultParameter = parseFormalParameter('a()? : null', kind,
-            featureSet: preNonNullable,
-            errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
-        as DefaultFormalParameter;
-    var functionParameter =
-        defaultParameter.parameter as FunctionTypedFormalParameter;
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.isNamed, isTrue);
-    expect(functionParameter.question, isNotNull);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_functionTyped_positional_nullable_disabled() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    var defaultParameter = parseFormalParameter('a()? = null', kind,
-            featureSet: preNonNullable,
-            errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
-        as DefaultFormalParameter;
-    var functionParameter =
-        defaultParameter.parameter as FunctionTypedFormalParameter;
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.isOptionalPositional, isTrue);
-    expect(functionParameter.question, isNotNull);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_functionTyped_required_nullable_disabled() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    var functionParameter = parseFormalParameter('a()?', kind,
-            featureSet: preNonNullable,
-            errorCodes: [ParserErrorCode.EXPERIMENT_NOT_ENABLED])
-        as FunctionTypedFormalParameter;
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.isRequiredPositional, isTrue);
-    expect(functionParameter.question, isNotNull);
-  }
-
-  void test_parseFormalParameter_covariant_required_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter = parseNNBDFormalParameter(
-        'covariant required A a : null', kind,
-        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 12, 8)]);
-    expect(parameter, isNotNull);
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_external() {
-    parseNNBDFormalParameter('external int i', ParameterKind.REQUIRED, errors: [
-      expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 1, 8),
-    ]);
-  }
-
-  void test_parseFormalParameter_final_required_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter = parseNNBDFormalParameter(
-        'final required a : null', kind,
-        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 8, 8)]);
-    expect(parameter, isNotNull);
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_required_covariant_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter =
-        parseNNBDFormalParameter('required covariant A a : null', kind);
-    expect(parameter, isNotNull);
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_required_final_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter =
-        parseNNBDFormalParameter('required final a : null', kind);
-    expect(parameter, isNotNull);
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_required_type_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter =
-        parseNNBDFormalParameter('required A a : null', kind);
-    expect(parameter, isNotNull);
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_required_var_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter =
-        parseNNBDFormalParameter('required var a : null', kind);
-    expect(parameter, isNotNull);
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_var_required_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter = parseNNBDFormalParameter(
-        'var required a : null', kind,
-        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 8)]);
-    expect(parameter, isNotNull);
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseNormalFormalParameter_function_noType_nullable() {
-    NormalFormalParameter parameter =
-        parseNNBDFormalParameter('a()?', ParameterKind.REQUIRED);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNotNull);
-    expect(functionParameter.endToken, functionParameter.question);
-  }
-}
-
-/// Tests of the fasta parser based on [ComplexParserTestMixin].
-@reflectiveTest
-class NNBDParserTest_Fasta extends FastaParserTestCase {
-  @override
-  CompilationUnit parseCompilationUnit(String content,
-          {List<ErrorCode> codes,
-          List<ExpectedError> errors,
-          FeatureSet featureSet}) =>
-      super.parseCompilationUnit(content,
-          codes: codes,
-          errors: errors,
-          featureSet: featureSet ?? FeatureSet.latestLanguageVersion());
-
-  void test_assignment_complex() {
-    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }');
-  }
-
-  void test_assignment_complex2() {
-    parseCompilationUnit(r'''
-main() {
-  A? a;
-  String? s = '';
-  a?..foo().length..x27 = s!..toString().length;
-}
-''');
-  }
-
-  void test_assignment_simple() {
-    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
-  }
-
-  void test_bangBeforeFuctionCall1() {
-    // https://github.com/dart-lang/sdk/issues/39776
-    var unit = parseCompilationUnit('f() { Function? f1; f1!(42); }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement1 = body.block.statements[0] as VariableDeclarationStatement;
-    expect(statement1.toSource(), "Function? f1;");
-    var statement2 = body.block.statements[1] as ExpressionStatement;
-
-    // expression is "f1!(42)"
-    var expression = statement2.expression as FunctionExpressionInvocation;
-    expect(expression.toSource(), "f1!(42)");
-
-    var functionExpression = expression.function as PostfixExpression;
-    SimpleIdentifier identifier = functionExpression.operand;
-    expect(identifier.name, 'f1');
-    expect(functionExpression.operator.lexeme, '!');
-
-    expect(expression.typeArguments, null);
-
-    expect(expression.argumentList.arguments.length, 1);
-    IntegerLiteral argument = expression.argumentList.arguments.single;
-    expect(argument.value, 42);
-  }
-
-  void test_bangBeforeFuctionCall2() {
-    // https://github.com/dart-lang/sdk/issues/39776
-    var unit = parseCompilationUnit('f() { Function f2; f2!<int>(42); }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement1 = body.block.statements[0] as VariableDeclarationStatement;
-    expect(statement1.toSource(), "Function f2;");
-    var statement2 = body.block.statements[1] as ExpressionStatement;
-
-    // expression is "f2!<int>(42)"
-    var expression = statement2.expression as FunctionExpressionInvocation;
-    expect(expression.toSource(), "f2!<int>(42)");
-
-    var functionExpression = expression.function as PostfixExpression;
-    SimpleIdentifier identifier = functionExpression.operand;
-    expect(identifier.name, 'f2');
-    expect(functionExpression.operator.lexeme, '!');
-
-    expect(expression.typeArguments.arguments.length, 1);
-    TypeName typeArgument = expression.typeArguments.arguments.single;
-    expect(typeArgument.name.name, "int");
-
-    expect(expression.argumentList.arguments.length, 1);
-    IntegerLiteral argument = expression.argumentList.arguments.single;
-    expect(argument.value, 42);
-  }
-
-  void test_bangQuestionIndex() {
-    // http://dartbug.com/41177
-    CompilationUnit unit = parseCompilationUnit('f(dynamic a) { a!?[0]; }');
-    FunctionDeclaration funct = unit.declarations[0];
-    BlockFunctionBody body = funct.functionExpression.body;
-
-    ExpressionStatement statement = body.block.statements[0];
-    IndexExpression expression = statement.expression;
-
-    IntegerLiteral index = expression.index;
-    expect(index.value, 0);
-
-    Token question = expression.question;
-    expect(question, isNotNull);
-    expect(question.lexeme, "?");
-
-    PostfixExpression target = expression.target;
-    SimpleIdentifier identifier = target.operand;
-    expect(identifier.name, 'a');
-    expect(target.operator.lexeme, '!');
-  }
-
-  void test_binary_expression_statement() {
-    final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }');
-    FunctionDeclaration funct = unit.declarations[0];
-    BlockFunctionBody body = funct.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    BinaryExpression expression = statement.expression;
-    SimpleIdentifier lhs = expression.leftOperand;
-    expect(lhs.name, 'X');
-    expect(expression.operator.lexeme, '??');
-    SimpleIdentifier rhs = expression.rightOperand;
-    expect(rhs.name, 'x2');
-  }
-
-  void test_cascade_withNullCheck_indexExpression() {
-    var unit = parseCompilationUnit('main() { a?..[27]; }');
-    FunctionDeclaration funct = unit.declarations[0];
-    BlockFunctionBody body = funct.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    CascadeExpression cascade = statement.expression;
-    IndexExpression indexExpression = cascade.cascadeSections[0];
-    expect(indexExpression.period.lexeme, '?..');
-    expect(indexExpression.toSource(), '?..[27]');
-  }
-
-  void test_cascade_withNullCheck_invalid() {
-    parseCompilationUnit('main() { a..[27]?..x; }', errors: [
-      expectedError(ParserErrorCode.NULL_AWARE_CASCADE_OUT_OF_ORDER, 16, 3),
-    ]);
-  }
-
-  void test_cascade_withNullCheck_methodInvocation() {
-    var unit = parseCompilationUnit('main() { a?..foo(); }');
-    FunctionDeclaration funct = unit.declarations[0];
-    BlockFunctionBody body = funct.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    CascadeExpression cascade = statement.expression;
-    MethodInvocation invocation = cascade.cascadeSections[0];
-    expect(invocation.operator.lexeme, '?..');
-    expect(invocation.toSource(), '?..foo()');
-  }
-
-  void test_cascade_withNullCheck_propertyAccess() {
-    var unit = parseCompilationUnit('main() { a?..x27; }');
-    FunctionDeclaration funct = unit.declarations[0];
-    BlockFunctionBody body = funct.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    CascadeExpression cascade = statement.expression;
-    PropertyAccess propertyAccess = cascade.cascadeSections[0];
-    expect(propertyAccess.operator.lexeme, '?..');
-    expect(propertyAccess.toSource(), '?..x27');
-  }
-
-  void test_conditional() {
-    parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
-  }
-
-  void test_conditional_complex() {
-    parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
-  }
-
-  void test_conditional_error() {
-    parseCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
-        errors: [
-          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
-          expectedError(ParserErrorCode.EXPECTED_TOKEN, 40, 1),
-          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 40, 1),
-        ]);
-  }
-
-  void test_conditional_simple() {
-    parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
-  }
-
-  void test_enableNonNullable_false() {
-    parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)],
-        featureSet: preNonNullable);
-  }
-
-  void test_for() {
-    parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
-  }
-
-  void test_for_conditional() {
-    parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
-  }
-
-  void test_for_nullable() {
-    parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
-  }
-
-  void test_foreach() {
-    parseCompilationUnit('main() { for(int x in [7]) { } }');
-  }
-
-  void test_foreach_nullable() {
-    parseCompilationUnit('main() { for(int? x in [7, null]) { } }');
-  }
-
-  void test_functionTypedFormalParameter_nullable_disabled() {
-    parseCompilationUnit('void f(void p()?) {}',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
-        featureSet: preNonNullable);
-  }
-
-  test_fuzz_38113() async {
-    // https://github.com/dart-lang/sdk/issues/38113
-    parseCompilationUnit(r'+t{{r?this}}', errors: [
-      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
-    ]);
-  }
-
-  void test_gft_nullable() {
-    parseCompilationUnit('main() { C? Function() x = 7; }');
-  }
-
-  void test_gft_nullable_1() {
-    parseCompilationUnit('main() { C Function()? x = 7; }');
-  }
-
-  void test_gft_nullable_2() {
-    parseCompilationUnit('main() { C? Function()? x = 7; }');
-  }
-
-  void test_gft_nullable_3() {
-    parseCompilationUnit('main() { C? Function()? Function()? x = 7; }');
-  }
-
-  void test_gft_nullable_prefixed() {
-    parseCompilationUnit('main() { C.a? Function()? x = 7; }');
-  }
-
-  void test_indexed() {
-    CompilationUnit unit = parseCompilationUnit('main() { a[7]; }');
-    FunctionDeclaration method = unit.declarations[0];
-    BlockFunctionBody body = method.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    IndexExpression expression = statement.expression;
-    expect(expression.leftBracket.lexeme, '[');
-  }
-
-  void test_indexed_nullAware() {
-    CompilationUnit unit = parseCompilationUnit('main() { a?[7]; }');
-    FunctionDeclaration method = unit.declarations[0];
-    BlockFunctionBody body = method.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    IndexExpression expression = statement.expression;
-    expect(expression.question, isNotNull);
-    expect(expression.leftBracket.lexeme, '[');
-    expect(expression.rightBracket.lexeme, ']');
-    expect(expression.leftBracket.endGroup, expression.rightBracket);
-  }
-
-  void test_indexed_nullAware_optOut() {
-    CompilationUnit unit = parseCompilationUnit('''
-// @dart = 2.2
-main() { a?[7]; }''',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 25, 1)]);
-    FunctionDeclaration method = unit.declarations[0];
-    BlockFunctionBody body = method.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    IndexExpressionImpl expression = statement.expression;
-    expect(expression.target.toSource(), 'a');
-    expect(expression.question, isNotNull);
-    expect(expression.leftBracket.lexeme, '[');
-    expect(expression.rightBracket.lexeme, ']');
-    expect(expression.leftBracket.endGroup, expression.rightBracket);
-  }
-
-  void test_indexExpression_nullable_disabled() {
-    parseCompilationUnit('main(a) { a?[0]; }',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 1)],
-        featureSet: preNonNullable);
-  }
-
-  void test_is_nullable() {
-    CompilationUnit unit =
-        parseCompilationUnit('main() { x is String? ? (x + y) : z; }');
-    FunctionDeclaration function = unit.declarations[0];
-    BlockFunctionBody body = function.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    ConditionalExpression expression = statement.expression;
-
-    IsExpression condition = expression.condition;
-    expect((condition.type as NamedType).question, isNotNull);
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-  }
-
-  void test_is_nullable_parenthesis() {
-    CompilationUnit unit =
-        parseCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
-    FunctionDeclaration function = unit.declarations[0];
-    BlockFunctionBody body = function.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    ConditionalExpression expression = statement.expression;
-
-    ParenthesizedExpression condition = expression.condition;
-    IsExpression isExpression = condition.expression;
-    expect((isExpression.type as NamedType).question, isNotNull);
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-  }
-
-  void test_is_nullable_parenthesis_optOut() {
-    parseCompilationUnit('''
-// @dart = 2.2
-main() { (x is String?) ? (x + y) : z; }
-''', errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)]);
-  }
-
-  void test_late_as_identifier() {
-    parseCompilationUnit('''
-class C {
-  int late;
-}
-
-void f(C c) {
-  print(c.late);
-}
-
-main() {
-  f(new C());
-}
-''', featureSet: preNonNullable);
-  }
-
-  void test_late_as_identifier_optOut() {
-    parseCompilationUnit('''
-// @dart = 2.2
-class C {
-  int late;
-}
-
-void f(C c) {
-  print(c.late);
-}
-
-main() {
-  f(new C());
-}
-''');
-  }
-
-  void test_nullableTypeInInitializerList_01() {
-    // http://dartbug.com/40834
-    var unit = parseCompilationUnit(r'''
-class Foo {
-  String? x;
-  int y;
-
-  Foo(Object? o) : x = o as String?, y = 0;
-}
-''');
-    ClassDeclaration classDeclaration = unit.declarations.first;
-    ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
-
-    // Object? o
-    SimpleFormalParameter parameter = constructor.parameters.parameters.single;
-    expect(parameter.identifier.name, 'o');
-    TypeName type = parameter.type;
-    expect(type.question.lexeme, '?');
-    expect(type.name.name, 'Object');
-
-    expect(constructor.initializers.length, 2);
-
-    // o as String?
-    {
-      ConstructorFieldInitializer initializer = constructor.initializers[0];
-      expect(initializer.fieldName.name, 'x');
-      AsExpression expression = initializer.expression;
-      SimpleIdentifier identifier = expression.expression;
-      expect(identifier.name, 'o');
-      TypeName expressionType = expression.type;
-      expect(expressionType.question.lexeme, '?');
-      expect(expressionType.name.name, 'String');
-    }
-
-    // y = 0
-    {
-      ConstructorFieldInitializer initializer = constructor.initializers[1];
-      expect(initializer.fieldName.name, 'y');
-      IntegerLiteral expression = initializer.expression;
-      expect(expression.value, 0);
-    }
-  }
-
-  void test_nullableTypeInInitializerList_02() {
-    var unit = parseCompilationUnit(r'''
-class Foo {
-  String? x;
-  int y;
-
-  Foo(Object? o) : y = o is String? ? o.length : null, x = null;
-}
-''');
-    ClassDeclaration classDeclaration = unit.declarations.first;
-    ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
-
-    // Object? o
-    SimpleFormalParameter parameter = constructor.parameters.parameters.single;
-    expect(parameter.identifier.name, 'o');
-    TypeName type = parameter.type;
-    expect(type.question.lexeme, '?');
-    expect(type.name.name, 'Object');
-
-    expect(constructor.initializers.length, 2);
-
-    // y = o is String? ? o.length : null
-    {
-      ConstructorFieldInitializer initializer = constructor.initializers[0];
-      expect(initializer.fieldName.name, 'y');
-      ConditionalExpression expression = initializer.expression;
-      IsExpression condition = expression.condition;
-      SimpleIdentifier identifier = condition.expression;
-      expect(identifier.name, 'o');
-      TypeName expressionType = condition.type;
-      expect(expressionType.question.lexeme, '?');
-      expect(expressionType.name.name, 'String');
-      PrefixedIdentifier thenExpression = expression.thenExpression;
-      expect(thenExpression.identifier.name, 'length');
-      expect(thenExpression.prefix.name, 'o');
-      NullLiteral elseExpression = expression.elseExpression;
-      expect(elseExpression, isNotNull);
-    }
-
-    // x = null
-    {
-      ConstructorFieldInitializer initializer = constructor.initializers[1];
-      expect(initializer.fieldName.name, 'x');
-      NullLiteral expression = initializer.expression;
-      expect(expression, isNotNull);
-    }
-  }
-
-  void test_nullableTypeInInitializerList_03() {
-    // As test_nullableTypeInInitializerList_02 but without ? on String in is.
-    var unit = parseCompilationUnit(r'''
-class Foo {
-  String? x;
-  int y;
-
-  Foo(Object? o) : y = o is String ? o.length : null, x = null;
-}
-''');
-    ClassDeclaration classDeclaration = unit.declarations.first;
-    ConstructorDeclaration constructor = classDeclaration.getConstructor(null);
-
-    // Object? o
-    SimpleFormalParameter parameter = constructor.parameters.parameters.single;
-    expect(parameter.identifier.name, 'o');
-    TypeName type = parameter.type;
-    expect(type.question.lexeme, '?');
-    expect(type.name.name, 'Object');
-
-    expect(constructor.initializers.length, 2);
-
-    // y = o is String ? o.length : null
-    {
-      ConstructorFieldInitializer initializer = constructor.initializers[0];
-      expect(initializer.fieldName.name, 'y');
-      ConditionalExpression expression = initializer.expression;
-      IsExpression condition = expression.condition;
-      SimpleIdentifier identifier = condition.expression;
-      expect(identifier.name, 'o');
-      TypeName expressionType = condition.type;
-      expect(expressionType.question, isNull);
-      expect(expressionType.name.name, 'String');
-      PrefixedIdentifier thenExpression = expression.thenExpression;
-      expect(thenExpression.identifier.name, 'length');
-      expect(thenExpression.prefix.name, 'o');
-      NullLiteral elseExpression = expression.elseExpression;
-      expect(elseExpression, isNotNull);
-    }
-
-    // x = null
-    {
-      ConstructorFieldInitializer initializer = constructor.initializers[1];
-      expect(initializer.fieldName.name, 'x');
-      NullLiteral expression = initializer.expression;
-      expect(expression, isNotNull);
-    }
-  }
-
-  void test_nullCheck() {
-    var unit = parseCompilationUnit('f(int? y) { var x = y!; }');
-    FunctionDeclaration function = unit.declarations[0];
-    BlockFunctionBody body = function.functionExpression.body;
-    VariableDeclarationStatement statement = body.block.statements[0];
-    PostfixExpression expression = statement.variables.variables[0].initializer;
-    SimpleIdentifier identifier = expression.operand;
-    expect(identifier.name, 'y');
-    expect(expression.operator.lexeme, '!');
-  }
-
-  void test_nullCheck_disabled() {
-    var unit = parseCompilationUnit('f(int? y) { var x = y!; }',
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
-        ],
-        featureSet: preNonNullable);
-    FunctionDeclaration function = unit.declarations[0];
-    BlockFunctionBody body = function.functionExpression.body;
-    VariableDeclarationStatement statement = body.block.statements[0];
-    SimpleIdentifier identifier = statement.variables.variables[0].initializer;
-    expect(identifier.name, 'y');
-  }
-
-  void test_nullCheckAfterGetterAccess() {
-    parseCompilationUnit('f() { var x = g.x!.y + 7; }');
-  }
-
-  void test_nullCheckAfterMethodCall() {
-    parseCompilationUnit('f() { var x = g.m()!.y + 7; }');
-  }
-
-  void test_nullCheckBeforeGetterAccess() {
-    parseCompilationUnit('f() { var x = g!.x + 7; }');
-  }
-
-  void test_nullCheckBeforeIndex() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { foo.bar!.baz[arg]; }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as IndexExpression;
-    expect(expression.index.toSource(), 'arg');
-    var propertyAccess = expression.target as PropertyAccess;
-    expect(propertyAccess.propertyName.toSource(), 'baz');
-    var target = propertyAccess.target as PostfixExpression;
-    expect(target.operand.toSource(), 'foo.bar');
-    expect(target.operator.lexeme, '!');
-  }
-
-  void test_nullCheckBeforeMethodCall() {
-    parseCompilationUnit('f() { var x = g!.m() + 7; }');
-  }
-
-  void test_nullCheckFunctionResult() {
-    parseCompilationUnit('f() { var x = g()! + 7; }');
-  }
-
-  void test_nullCheckIndexedValue() {
-    parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
-  }
-
-  void test_nullCheckIndexedValue2() {
-    parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
-  }
-
-  void test_nullCheckInExpression() {
-    parseCompilationUnit('f(int? y) { var x = y! + 7; }');
-  }
-
-  void test_nullCheckInExpression_disabled() {
-    parseCompilationUnit('f(int? y) { var x = y! + 7; }',
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 5, 1),
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 21, 1),
-        ],
-        featureSet: preNonNullable);
-  }
-
-  void test_nullCheckMethodResult() {
-    parseCompilationUnit('f() { var x = g.m()! + 7; }');
-  }
-
-  void test_nullCheckMethodResult2() {
-    parseCompilationUnit('f() { var x = g?.m()! + 7; }');
-  }
-
-  void test_nullCheckMethodResult3() {
-    parseCompilationUnit('f() { var x = super.m()! + 7; }');
-  }
-
-  void test_nullCheckOnConstConstructor() {
-    parseCompilationUnit('f() { var x = const Foo()!; }');
-  }
-
-  void test_nullCheckOnConstructor() {
-    parseCompilationUnit('f() { var x = new Foo()!; }');
-  }
-
-  void test_nullCheckOnIndex() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { obj![arg]; }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as IndexExpression;
-    var target = expression.target as PostfixExpression;
-    expect(target.operand.toSource(), 'obj');
-    expect(target.operator.lexeme, '!');
-  }
-
-  void test_nullCheckOnIndex2() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { obj![arg]![arg2]; }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as IndexExpression;
-    expect(expression.index.toSource(), 'arg2');
-    var target = expression.target as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-    expression = target.operand as IndexExpression;
-    expect(expression.index.toSource(), 'arg');
-    target = expression.target as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-    expect(target.operand.toSource(), 'obj');
-  }
-
-  void test_nullCheckOnIndex3() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { foo.bar![arg]; }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as IndexExpression;
-    expect(expression.index.toSource(), 'arg');
-    var target = expression.target as PostfixExpression;
-    expect(target.operand.toSource(), 'foo.bar');
-    expect(target.operator.lexeme, '!');
-  }
-
-  void test_nullCheckOnIndex4() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { foo!.bar![arg]; }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as IndexExpression;
-    var fooBarTarget = expression.target as PostfixExpression;
-    expect(fooBarTarget.toSource(), "foo!.bar!");
-    var propertyAccess = fooBarTarget.operand as PropertyAccess;
-    var targetFoo = propertyAccess.target as PostfixExpression;
-    expect(targetFoo.operand.toSource(), "foo");
-    expect(targetFoo.operator.lexeme, "!");
-    expect(propertyAccess.propertyName.toSource(), "bar");
-    expect(fooBarTarget.operator.lexeme, '!');
-    expect(expression.index.toSource(), 'arg');
-  }
-
-  void test_nullCheckOnIndex5() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { foo.bar![arg]![arg2]; }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as IndexExpression;
-    expect(expression.index.toSource(), 'arg2');
-    var target = expression.target as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-    expression = target.operand as IndexExpression;
-    expect(expression.index.toSource(), 'arg');
-    target = expression.target as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-    expect(target.operand.toSource(), 'foo.bar');
-  }
-
-  void test_nullCheckOnIndex6() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { foo!.bar![arg]![arg2]; }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-
-    // expression is "foo!.bar![arg]![arg2]"
-    var expression = statement.expression as IndexExpression;
-    expect(expression.index.toSource(), 'arg2');
-
-    // target is "foo!.bar![arg]!"
-    var target = expression.target as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-
-    // expression is "foo!.bar![arg]"
-    expression = target.operand as IndexExpression;
-    expect(expression.index.toSource(), 'arg');
-
-    // target is "foo!.bar!"
-    target = expression.target as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-
-    // propertyAccess is "foo!.bar"
-    PropertyAccess propertyAccess = target.operand as PropertyAccess;
-    expect(propertyAccess.propertyName.toSource(), "bar");
-
-    // target is "foo!"
-    target = propertyAccess.target as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-
-    expect(target.operand.toSource(), "foo");
-  }
-
-  void test_nullCheckOnLiteral_disabled() {
-    parseCompilationUnit('f() { var x = 0!; }',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 15, 1)],
-        featureSet: preNonNullable);
-  }
-
-  void test_nullCheckOnLiteralDouble() {
-    // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = 1.2!; }');
-  }
-
-  void test_nullCheckOnLiteralInt() {
-    // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = 0!; }');
-  }
-
-  void test_nullCheckOnLiteralList() {
-    // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = [1,2]!; }');
-  }
-
-  void test_nullCheckOnLiteralMap() {
-    // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = {1:2}!; }');
-  }
-
-  void test_nullCheckOnLiteralSet() {
-    // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = {1,2}!; }');
-  }
-
-  void test_nullCheckOnLiteralString() {
-    // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = "seven"!; }');
-  }
-
-  void test_nullCheckOnNull() {
-    // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = null!; }');
-  }
-
-  void test_nullCheckOnSend() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { obj!(arg); }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as FunctionExpressionInvocation;
-    var target = expression.function as PostfixExpression;
-    expect(target.operand.toSource(), 'obj');
-    expect(target.operator.lexeme, '!');
-  }
-
-  void test_nullCheckOnSend2() {
-    // https://github.com/dart-lang/sdk/issues/37708
-    var unit = parseCompilationUnit('f() { obj!(arg)!(arg2); }');
-    var funct = unit.declarations[0] as FunctionDeclaration;
-    var body = funct.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as FunctionExpressionInvocation;
-    expect(expression.argumentList.toSource(), '(arg2)');
-    var target = expression.function as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-    expression = target.operand as FunctionExpressionInvocation;
-    expect(expression.argumentList.toSource(), '(arg)');
-    target = expression.function as PostfixExpression;
-    expect(target.operator.lexeme, '!');
-    expect(target.operand.toSource(), 'obj');
-  }
-
-  void test_nullCheckOnSymbol() {
-    // Issues like this should be caught during later analysis
-    parseCompilationUnit('f() { var x = #seven!; }');
-  }
-
-  void test_nullCheckOnValue() {
-    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }');
-  }
-
-  void test_nullCheckOnValue_disabled() {
-    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 24, 1)],
-        featureSet: preNonNullable);
-  }
-
-  void test_nullCheckParenthesizedExpression() {
-    parseCompilationUnit('f(int? y) { var x = (y)! + 7; }');
-  }
-
-  void test_nullCheckPropertyAccess() {
-    parseCompilationUnit('f() { var x = g.p! + 7; }');
-  }
-
-  void test_nullCheckPropertyAccess2() {
-    parseCompilationUnit('f() { var x = g?.p! + 7; }');
-  }
-
-  void test_nullCheckPropertyAccess3() {
-    parseCompilationUnit('f() { var x = super.p! + 7; }');
-  }
-
-  void test_postfix_null_assertion_and_unary_prefix_operator_precedence() {
-    // -x! is parsed as -(x!).
-    var unit = parseCompilationUnit('void main() { -x!; }');
-    var function = unit.declarations[0] as FunctionDeclaration;
-    var body = function.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var outerExpression = statement.expression as PrefixExpression;
-    expect(outerExpression.operator.type, TokenType.MINUS);
-    var innerExpression = outerExpression.operand as PostfixExpression;
-    expect(innerExpression.operator.type, TokenType.BANG);
-  }
-
-  void test_postfix_null_assertion_of_postfix_expression() {
-    // x++! is parsed as (x++)!.
-    var unit = parseCompilationUnit('void main() { x++!; }');
-    var function = unit.declarations[0] as FunctionDeclaration;
-    var body = function.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var outerExpression = statement.expression as PostfixExpression;
-    expect(outerExpression.operator.type, TokenType.BANG);
-    var innerExpression = outerExpression.operand as PostfixExpression;
-    expect(innerExpression.operator.type, TokenType.PLUS_PLUS);
-  }
-
-  void test_typeName_nullable_disabled() {
-    parseCompilationUnit('int? x;',
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 3, 1)],
-        featureSet: preNonNullable);
-  }
-}
-
-/// Proxy implementation of the analyzer parser, implemented in terms of the
-/// Fasta parser.
-///
-/// This allows many of the analyzer parser tests to be run on Fasta, even if
-/// they call into the analyzer parser class directly.
-class ParserProxy extends analyzer.ParserAdapter {
-  /// The error listener to which scanner and parser errors will be reported.
-  final GatheringErrorListener _errorListener;
-
-  ForwardingTestListener _eventListener;
-
-  final int expectedEndOffset;
-
-  /// Creates a [ParserProxy] which is prepared to begin parsing at the given
-  /// Fasta token.
-  factory ParserProxy(analyzer.Token firstToken, FeatureSet featureSet,
-      {bool allowNativeClause = false, int expectedEndOffset}) {
-    TestSource source = TestSource();
-    var errorListener = GatheringErrorListener(checkRanges: true);
-    var errorReporter = ErrorReporter(
-      errorListener,
-      source,
-      isNonNullableByDefault: false,
-    );
-    return ParserProxy._(
-        firstToken, errorReporter, null, errorListener, featureSet,
-        allowNativeClause: allowNativeClause,
-        expectedEndOffset: expectedEndOffset);
-  }
-
-  ParserProxy._(analyzer.Token firstToken, ErrorReporter errorReporter,
-      Uri fileUri, this._errorListener, FeatureSet featureSet,
-      {bool allowNativeClause = false, this.expectedEndOffset})
-      : super(firstToken, errorReporter, fileUri, featureSet,
-            allowNativeClause: allowNativeClause) {
-    _eventListener = ForwardingTestListener(astBuilder);
-    fastaParser.listener = _eventListener;
-  }
-
-  @override
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-
-  @override
-  Annotation parseAnnotation() {
-    return _run('MetadataStar', () => super.parseAnnotation());
-  }
-
-  @override
-  ArgumentList parseArgumentList() {
-    return _run('unspecified', () => super.parseArgumentList());
-  }
-
-  @override
-  ClassMember parseClassMember(String className) {
-    return _run('ClassOrMixinBody', () => super.parseClassMember(className));
-  }
-
-  @override
-  List<Combinator> parseCombinators() {
-    return _run('Import', () => super.parseCombinators());
-  }
-
-  @override
-  List<CommentReference> parseCommentReferences(
-      List<DocumentationCommentToken> tokens) {
-    for (int index = 0; index < tokens.length - 1; ++index) {
-      analyzer.Token next = tokens[index].next;
-      if (next == null) {
-        tokens[index].setNext(tokens[index + 1]);
-      } else {
-        expect(next, tokens[index + 1]);
-      }
-    }
-    expect(tokens[tokens.length - 1].next, isNull);
-    List<CommentReference> references =
-        astBuilder.parseCommentReferences(tokens.first);
-    if (astBuilder.stack.isNotEmpty) {
-      throw 'Expected empty stack, but found:'
-          '\n  ${astBuilder.stack.values.join('\n  ')}';
-    }
-    return references;
-  }
-
-  @override
-  CompilationUnit parseCompilationUnit2() {
-    CompilationUnit result = super.parseCompilationUnit2();
-    expect(currentToken.isEof, isTrue, reason: currentToken.lexeme);
-    expect(astBuilder.stack, hasLength(0));
-    _eventListener.expectEmpty();
-    return result;
-  }
-
-  @override
-  Configuration parseConfiguration() {
-    return _run('ConditionalUris', () => super.parseConfiguration());
-  }
-
-  @override
-  DottedName parseDottedName() {
-    return _run('unspecified', () => super.parseDottedName());
-  }
-
-  @override
-  Expression parseExpression2() {
-    return _run('unspecified', () => super.parseExpression2());
-  }
-
-  @override
-  FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
-    return _run('unspecified',
-        () => super.parseFormalParameterList(inFunctionType: inFunctionType));
-  }
-
-  @override
-  FunctionBody parseFunctionBody(
-      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
-    Token lastToken;
-    FunctionBody body = _run('unspecified', () {
-      FunctionBody body =
-          super.parseFunctionBody(mayBeEmpty, emptyErrorCode, inExpression);
-      lastToken = currentToken;
-      currentToken = currentToken.next;
-      return body;
-    });
-    if (!inExpression) {
-      if (![';', '}'].contains(lastToken.lexeme)) {
-        fail('Expected ";" or "}", but found: ${lastToken.lexeme}');
-      }
-    }
-    return body;
-  }
-
-  @override
-  Expression parsePrimaryExpression() {
-    return _run('unspecified', () => super.parsePrimaryExpression());
-  }
-
-  @override
-  Statement parseStatement(Token token) {
-    return _run('unspecified', () => super.parseStatement(token));
-  }
-
-  @override
-  Statement parseStatement2() {
-    return _run('unspecified', () => super.parseStatement2());
-  }
-
-  @override
-  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
-    return _run(
-        'CompilationUnit', () => super.parseTopLevelDeclaration(isDirective));
-  }
-
-  @override
-  TypeAnnotation parseTypeAnnotation(bool inExpression) {
-    return _run('unspecified', () => super.parseTypeAnnotation(inExpression));
-  }
-
-  @override
-  TypeArgumentList parseTypeArgumentList() {
-    return _run('unspecified', () => super.parseTypeArgumentList());
-  }
-
-  @override
-  TypeName parseTypeName(bool inExpression) {
-    return _run('unspecified', () => super.parseTypeName(inExpression));
-  }
-
-  @override
-  TypeParameter parseTypeParameter() {
-    return _run('unspecified', () => super.parseTypeParameter());
-  }
-
-  @override
-  TypeParameterList parseTypeParameterList() {
-    return _run('unspecified', () => super.parseTypeParameterList());
-  }
-
-  /// Runs the specified function and returns the result. It checks the
-  /// enclosing listener events, that the parse consumed all of the tokens, and
-  /// that the result stack is empty.
-  _run(String enclosingEvent, Function() f) {
-    _eventListener.begin(enclosingEvent);
-
-    // Simulate error handling of parseUnit by skipping error tokens
-    // before parsing and reporting them after parsing is complete.
-    Token errorToken = currentToken;
-    currentToken = fastaParser.skipErrorTokens(currentToken);
-    var result = f();
-    fastaParser.reportAllErrorTokens(errorToken);
-
-    _eventListener.end(enclosingEvent);
-
-    String lexeme = currentToken is ErrorToken
-        ? currentToken.runtimeType.toString()
-        : currentToken.lexeme;
-    if (expectedEndOffset == null) {
-      expect(currentToken.isEof, isTrue, reason: lexeme);
-    } else {
-      expect(currentToken.offset, expectedEndOffset, reason: lexeme);
-    }
-    expect(astBuilder.stack, hasLength(0));
-    expect(astBuilder.directives, hasLength(0));
-    expect(astBuilder.declarations, hasLength(0));
-    return result;
-  }
-}
-
-@reflectiveTest
-class RecoveryParserTest_Fasta extends FastaParserTestCase
-    with RecoveryParserTestMixin {
-  @override
-  void test_equalityExpression_precedence_relational_right() {
-    parseExpression("== is", codes: [
-      ParserErrorCode.EXPECTED_TYPE_NAME,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-  }
-
-  void test_incompleteForEach2() {
-    ForStatement statement =
-        parseStatement('for (String item i) {}', featureSet: controlFlow);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)
-    ]);
-    expect(statement.toSource(), 'for (String item; i;) {}');
-    ForPartsWithDeclarations forLoopParts = statement.forLoopParts;
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.leftSeparator.type, TokenType.SEMICOLON);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.rightSeparator.type, TokenType.SEMICOLON);
-  }
-
-  void test_invalidTypeParameters_super() {
-    parseCompilationUnit('class C<X super Y> {}', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
-    ]);
-  }
-
-  @override
-  void test_relationalExpression_missing_LHS_RHS() {
-    parseExpression("is", codes: [
-      ParserErrorCode.EXPECTED_TYPE_NAME,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-  }
-
-  @override
-  void test_relationalExpression_precedence_shift_right() {
-    parseExpression("<< is", codes: [
-      ParserErrorCode.EXPECTED_TYPE_NAME,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-  }
-}
-
-@reflectiveTest
-class SimpleParserTest_Fasta extends FastaParserTestCase
-    with SimpleParserTestMixin {
-  void test_method_name_notNull_37733() {
-    // https://github.com/dart-lang/sdk/issues/37733
-    var unit = parseCompilationUnit(r'class C { f(<T>()); }', errors: [
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 12, 1),
-    ]);
-    var classDeclaration = unit.declarations[0] as ClassDeclaration;
-    var method = classDeclaration.members[0] as MethodDeclaration;
-    expect(method.parameters.parameters, hasLength(1));
-    var parameter =
-        method.parameters.parameters[0] as FunctionTypedFormalParameter;
-    expect(parameter.identifier, isNotNull);
-  }
-
-  test_parseArgument() {
-    Expression result = parseArgument('3');
-    expect(result, const TypeMatcher<IntegerLiteral>());
-    IntegerLiteral literal = result;
-    expect(literal.value, 3);
-  }
-
-  test_parseArgument_named() {
-    Expression result = parseArgument('foo: "a"');
-    expect(result, const TypeMatcher<NamedExpression>());
-    NamedExpression expression = result;
-    StringLiteral literal = expression.expression;
-    expect(literal.stringValue, 'a');
-  }
-
-  @failingTest
-  @override
-  void test_parseCommentReferences_skipLink_direct_multiLine() =>
-      super.test_parseCommentReferences_skipLink_direct_multiLine();
-
-  @failingTest
-  @override
-  void test_parseCommentReferences_skipLink_reference_multiLine() =>
-      super.test_parseCommentReferences_skipLink_reference_multiLine();
-
-  void test_parseVariableDeclaration_final_late() {
-    var statement = parseStatement('final late a;', featureSet: nonNullable)
-        as VariableDeclarationStatement;
-    var declarationList = statement.variables;
-    assertErrors(
-        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]);
-    expect(declarationList.keyword.lexeme, 'final');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclaration_late() {
-    var statement = parseStatement('late a;', featureSet: nonNullable)
-        as VariableDeclarationStatement;
-    var declarationList = statement.variables;
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
-    ]);
-    expect(declarationList.keyword, isNull);
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclaration_late_final() {
-    var statement = parseStatement('late final a;', featureSet: nonNullable)
-        as VariableDeclarationStatement;
-    var declarationList = statement.variables;
-    assertNoErrors();
-    expect(declarationList.keyword.lexeme, 'final');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclaration_late_init() {
-    var statement = parseStatement('late a = 0;', featureSet: nonNullable)
-        as VariableDeclarationStatement;
-    var declarationList = statement.variables;
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
-    ]);
-    expect(declarationList.keyword, isNull);
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclaration_late_type() {
-    var statement = parseStatement('late A a;', featureSet: nonNullable)
-        as VariableDeclarationStatement;
-    var declarationList = statement.variables;
-    assertNoErrors();
-    expect(declarationList.lateKeyword, isNotNull);
-    expect(declarationList.keyword, isNull);
-    expect(declarationList.type, isNotNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclaration_late_var() {
-    var statement = parseStatement('late var a;', featureSet: nonNullable)
-        as VariableDeclarationStatement;
-    var declarationList = statement.variables;
-    assertNoErrors();
-    expect(declarationList.lateKeyword, isNotNull);
-    expect(declarationList.keyword?.lexeme, 'var');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclaration_late_var_init() {
-    var statement = parseStatement('late var a = 0;', featureSet: nonNullable)
-        as VariableDeclarationStatement;
-    var declarationList = statement.variables;
-    assertNoErrors();
-    expect(declarationList.lateKeyword, isNotNull);
-    expect(declarationList.keyword?.lexeme, 'var');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_typeAlias_37733() {
-    // https://github.com/dart-lang/sdk/issues/37733
-    var unit = parseCompilationUnit(r'typedef K=Function(<>($', errors: [
-      expectedError(CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 19, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 1),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
-    ]);
-    var typeAlias = unit.declarations[0] as GenericTypeAlias;
-    expect(typeAlias.name.toSource(), 'K');
-    var functionType = typeAlias.functionType;
-    expect(functionType.parameters.parameters, hasLength(1));
-    var parameter = functionType.parameters.parameters[0];
-    expect(parameter.identifier, isNotNull);
-  }
-
-  void test_typeAlias_parameter_missingIdentifier_37733() {
-    // https://github.com/dart-lang/sdk/issues/37733
-    var unit = parseCompilationUnit(r'typedef T=Function(<S>());', errors: [
-      expectedError(CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 19, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
-    ]);
-    var typeAlias = unit.declarations[0] as GenericTypeAlias;
-    expect(typeAlias.name.toSource(), 'T');
-    var functionType = typeAlias.functionType;
-    expect(functionType.parameters.parameters, hasLength(1));
-    var parameter = functionType.parameters.parameters[0];
-    expect(parameter.identifier, isNotNull);
-  }
-}
-
-/// Tests of the fasta parser based on [StatementParserTestMixin].
-@reflectiveTest
-class StatementParserTest_Fasta extends FastaParserTestCase
-    with StatementParserTestMixin {
-  void test_35177() {
-    ExpressionStatement statement = parseStatement('(f)()<int>();');
-
-    FunctionExpressionInvocation funct1 = statement.expression;
-    NodeList<TypeAnnotation> typeArgs = funct1.typeArguments.arguments;
-    expect(typeArgs, hasLength(1));
-    TypeName typeName = typeArgs[0];
-    expect(typeName.name.name, 'int');
-    expect(funct1.argumentList.arguments, hasLength(0));
-
-    FunctionExpressionInvocation funct2 = funct1.function;
-    expect(funct2.typeArguments, isNull);
-    expect(funct2.argumentList.arguments, hasLength(0));
-
-    ParenthesizedExpression expression = funct2.function;
-    SimpleIdentifier identifier = expression.expression;
-    expect(identifier.name, 'f');
-  }
-
-  void test_invalid_typeArg_34850() {
-    var unit = parseCompilationUnit('foo Future<List<int>> bar() {}', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 4),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 6),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 22, 3),
-    ]);
-    // Validate that recovery has properly updated the token stream.
-    analyzer.Token token = unit.beginToken;
-    while (!token.isEof) {
-      expect(token.type, isNot(TokenType.GT_GT));
-      analyzer.Token next = token.next;
-      expect(next.previous, token);
-      token = next;
-    }
-  }
-
-  void test_parseForStatement_each_await2() {
-    ForStatement forStatement = parseStatement(
-      'await for (element in list) {}',
-      inAsync: true,
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNotNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForEachPartsWithIdentifier forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.identifier, isNotNull);
-    expect(forLoopParts.inKeyword, isNotNull);
-    expect(forLoopParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_finalExternal() {
-    ForStatement forStatement = parseStatement(
-      'for (final external in list) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.loopVariable.identifier.name, 'external');
-    expect(forLoopParts.inKeyword, isNotNull);
-    expect(forLoopParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_finalRequired() {
-    ForStatement forStatement = parseStatement(
-      'for (final required in list) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.loopVariable.identifier.name, 'required');
-    expect(forLoopParts.inKeyword, isNotNull);
-    expect(forLoopParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_genericFunctionType2() {
-    ForStatement forStatement = parseStatement(
-      'for (void Function<T>(T) element in list) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.loopVariable, isNotNull);
-    expect(forLoopParts.inKeyword, isNotNull);
-    expect(forLoopParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_identifier2() {
-    ForStatement forStatement = parseStatement(
-      'for (element in list) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForEachPartsWithIdentifier forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.identifier, isNotNull);
-    expect(forLoopParts.inKeyword, isNotNull);
-    expect(forLoopParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_noType_metadata2() {
-    ForStatement forStatement = parseStatement(
-      'for (@A var element in list) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.loopVariable, isNotNull);
-    expect(forLoopParts.loopVariable.metadata, hasLength(1));
-    expect(forLoopParts.inKeyword, isNotNull);
-    expect(forLoopParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_type2() {
-    ForStatement forStatement = parseStatement(
-      'for (A element in list) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.loopVariable, isNotNull);
-    expect(forLoopParts.inKeyword, isNotNull);
-    expect(forLoopParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_var2() {
-    ForStatement forStatement = parseStatement(
-      'for (var element in list) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.loopVariable, isNotNull);
-    expect(forLoopParts.inKeyword, isNotNull);
-    expect(forLoopParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_c2() {
-    ForStatement forStatement = parseStatement(
-      'for (; i < count;) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.initialization, isNull);
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNotNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(0));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_cu2() {
-    ForStatement forStatement = parseStatement(
-      'for (; i < count; i++) {}',
-      featureSet: controlFlow,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.initialization, isNull);
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNotNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_ecu2() {
-    ForStatement forStatement = parseStatement(
-      'for (i--; i < count; i++) {}',
-      featureSet: spread,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.initialization, isNotNull);
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNotNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_i2() {
-    ForStatement forStatement = parseStatement(
-      'for (var i = 0;;) {}',
-      featureSet: spread,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
-    VariableDeclarationList variables = forLoopParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.metadata, hasLength(0));
-    expect(variables.variables, hasLength(1));
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(0));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_i_withMetadata2() {
-    ForStatement forStatement = parseStatement(
-      'for (@A var i = 0;;) {}',
-      featureSet: spread,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
-    VariableDeclarationList variables = forLoopParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.metadata, hasLength(1));
-    expect(variables.variables, hasLength(1));
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(0));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_ic2() {
-    ForStatement forStatement = parseStatement(
-      'for (var i = 0; i < count;) {}',
-      featureSet: spread,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
-    VariableDeclarationList variables = forLoopParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.variables, hasLength(1));
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNotNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(0));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_icu2() {
-    ForStatement forStatement = parseStatement(
-      'for (var i = 0; i < count; i++) {}',
-      featureSet: spread,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
-    VariableDeclarationList variables = forLoopParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.variables, hasLength(1));
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNotNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_iicuu2() {
-    ForStatement forStatement = parseStatement(
-      'for (int i = 0, j = count; i < j; i++, j--) {}',
-      featureSet: spread,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
-    VariableDeclarationList variables = forLoopParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.variables, hasLength(2));
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNotNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(2));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_iu2() {
-    ForStatement forStatement = parseStatement(
-      'for (var i = 0;; i++) {}',
-      featureSet: spread,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
-    VariableDeclarationList variables = forLoopParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.variables, hasLength(1));
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_u2() {
-    ForStatement forStatement = parseStatement(
-      'for (;; i++) {}',
-      featureSet: spread,
-    );
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
-    expect(forLoopParts.initialization, isNull);
-    expect(forLoopParts.leftSeparator, isNotNull);
-    expect(forLoopParts.condition, isNull);
-    expect(forLoopParts.rightSeparator, isNotNull);
-    expect(forLoopParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseLocalVariable_external() {
-    parseStatement('external int i;', featureSet: nonNullable);
-    assertErrors(errors: [
-      expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 8),
-    ]);
-  }
-
-  void test_partial_typeArg1_34850() {
-    var unit = parseCompilationUnit('<bar<', errors: [
-      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 0),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 3),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 5, 0),
-    ]);
-    // Validate that recovery has properly updated the token stream.
-    analyzer.Token token = unit.beginToken;
-    while (!token.isEof) {
-      expect(token.type, isNot(TokenType.GT_GT));
-      analyzer.Token next = token.next;
-      expect(next.previous, token);
-      token = next;
-    }
-  }
-
-  void test_partial_typeArg2_34850() {
-    var unit = parseCompilationUnit('foo <bar<', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 3),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 3),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 9, 0),
-    ]);
-    // Validate that recovery has properly updated the token stream.
-    analyzer.Token token = unit.beginToken;
-    while (!token.isEof) {
-      expect(token.type, isNot(TokenType.GT_GT));
-      analyzer.Token next = token.next;
-      expect(next.previous, token);
-      token = next;
-    }
-  }
-}
-
-/// Tests of the fasta parser based on [TopLevelParserTestMixin].
-@reflectiveTest
-class TopLevelParserTest_Fasta extends FastaParserTestCase
-    with TopLevelParserTestMixin {
-  void test_parseClassDeclaration_native_allowed() {
-    allowNativeClause = true;
-    test_parseClassDeclaration_native();
-  }
-
-  void test_parseClassDeclaration_native_allowedWithFields() {
-    allowNativeClause = true;
-    createParser(r'''
-class A native 'something' {
-  final int x;
-  A() {}
-}
-''');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-  }
-
-  void test_parseClassDeclaration_native_missing_literal() {
-    createParser('class A native {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    if (allowNativeClause) {
-      assertNoErrors();
-    } else {
-      assertErrorsWithCodes([
-        ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
-      ]);
-    }
-    expect(member, TypeMatcher<ClassDeclaration>());
-    ClassDeclaration declaration = member;
-    expect(declaration.nativeClause, isNotNull);
-    expect(declaration.nativeClause.nativeKeyword, isNotNull);
-    expect(declaration.nativeClause.name, isNull);
-    expect(declaration.endToken.type, TokenType.CLOSE_CURLY_BRACKET);
-  }
-
-  void test_parseClassDeclaration_native_missing_literal_allowed() {
-    allowNativeClause = true;
-    test_parseClassDeclaration_native_missing_literal();
-  }
-
-  void test_parseClassDeclaration_native_missing_literal_not_allowed() {
-    allowNativeClause = false;
-    test_parseClassDeclaration_native_missing_literal();
-  }
-
-  void test_parseClassDeclaration_native_not_allowed() {
-    allowNativeClause = false;
-    test_parseClassDeclaration_native();
-  }
-
-  void test_parseMixinDeclaration_empty() {
-    createParser('mixin A {}');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.metadata, isEmpty);
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.onClause, isNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.mixinKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name.name, 'A');
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseMixinDeclaration_implements() {
-    createParser('mixin A implements B {}');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.metadata, isEmpty);
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.onClause, isNull);
-    ImplementsClause implementsClause = declaration.implementsClause;
-    expect(implementsClause.implementsKeyword, isNotNull);
-    NodeList<TypeName> interfaces = implementsClause.interfaces;
-    expect(interfaces, hasLength(1));
-    expect(interfaces[0].name.name, 'B');
-    expect(interfaces[0].typeArguments, isNull);
-    expect(declaration.mixinKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name.name, 'A');
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseMixinDeclaration_implements2() {
-    createParser('mixin A implements B<T>, C {}');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.metadata, isEmpty);
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.onClause, isNull);
-    ImplementsClause implementsClause = declaration.implementsClause;
-    expect(implementsClause.implementsKeyword, isNotNull);
-    NodeList<TypeName> interfaces = implementsClause.interfaces;
-    expect(interfaces, hasLength(2));
-    expect(interfaces[0].name.name, 'B');
-    expect(interfaces[0].typeArguments.arguments, hasLength(1));
-    expect(interfaces[1].name.name, 'C');
-    expect(interfaces[1].typeArguments, isNull);
-    expect(declaration.mixinKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name.name, 'A');
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseMixinDeclaration_metadata() {
-    createParser('@Z mixin A {}');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    NodeList<Annotation> metadata = declaration.metadata;
-    expect(metadata, hasLength(1));
-    expect(metadata[0].name.name, 'Z');
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.onClause, isNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.mixinKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name.name, 'A');
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseMixinDeclaration_on() {
-    createParser('mixin A on B {}');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.metadata, isEmpty);
-    expect(declaration.documentationComment, isNull);
-    OnClause onClause = declaration.onClause;
-    expect(onClause.onKeyword, isNotNull);
-    NodeList<TypeName> constraints = onClause.superclassConstraints;
-    expect(constraints, hasLength(1));
-    expect(constraints[0].name.name, 'B');
-    expect(constraints[0].typeArguments, isNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.mixinKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name.name, 'A');
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseMixinDeclaration_on2() {
-    createParser('mixin A on B, C<T> {}');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.metadata, isEmpty);
-    expect(declaration.documentationComment, isNull);
-    OnClause onClause = declaration.onClause;
-    expect(onClause.onKeyword, isNotNull);
-    NodeList<TypeName> constraints = onClause.superclassConstraints;
-    expect(constraints, hasLength(2));
-    expect(constraints[0].name.name, 'B');
-    expect(constraints[0].typeArguments, isNull);
-    expect(constraints[1].name.name, 'C');
-    expect(constraints[1].typeArguments.arguments, hasLength(1));
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.mixinKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name.name, 'A');
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseMixinDeclaration_onAndImplements() {
-    createParser('mixin A on B implements C {}');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.metadata, isEmpty);
-    expect(declaration.documentationComment, isNull);
-    OnClause onClause = declaration.onClause;
-    expect(onClause.onKeyword, isNotNull);
-    NodeList<TypeName> constraints = onClause.superclassConstraints;
-    expect(constraints, hasLength(1));
-    expect(constraints[0].name.name, 'B');
-    expect(constraints[0].typeArguments, isNull);
-    ImplementsClause implementsClause = declaration.implementsClause;
-    expect(implementsClause.implementsKeyword, isNotNull);
-    NodeList<TypeName> interfaces = implementsClause.interfaces;
-    expect(interfaces, hasLength(1));
-    expect(interfaces[0].name.name, 'C');
-    expect(interfaces[0].typeArguments, isNull);
-    expect(declaration.mixinKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name.name, 'A');
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseMixinDeclaration_simple() {
-    createParser('''
-mixin A {
-  int f;
-  int get g => f;
-  set s(int v) {f = v;}
-  int add(int v) => f = f + v;
-}''');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.metadata, isEmpty);
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.onClause, isNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.mixinKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name.name, 'A');
-    expect(declaration.members, hasLength(4));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseMixinDeclaration_withDocumentationComment() {
-    createParser('/// Doc\nmixin M {}');
-    MixinDeclaration declaration = parseFullCompilationUnitMember();
-    expectCommentText(declaration.documentationComment, '/// Doc');
-  }
-
-  void test_parseTopLevelVariable_external() {
-    var unit = parseCompilationUnit('external int i;', featureSet: nonNullable);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    expect(declaration.externalKeyword, isNotNull);
-  }
-
-  void test_parseTopLevelVariable_external_late() {
-    var unit = parseCompilationUnit('external late int? i;',
-        featureSet: nonNullable,
-        errors: [
-          expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
-        ]);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    expect(declaration.externalKeyword, isNotNull);
-  }
-
-  void test_parseTopLevelVariable_external_late_final() {
-    var unit = parseCompilationUnit('external late final int? i;',
-        featureSet: nonNullable,
-        errors: [
-          expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
-        ]);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    expect(declaration.externalKeyword, isNotNull);
-  }
-
-  void test_parseTopLevelVariable_final_late() {
-    var unit = parseCompilationUnit('final late a;',
-        featureSet: nonNullable,
-        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    var declarationList = declaration.variables;
-    expect(declarationList.keyword.lexeme, 'final');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseTopLevelVariable_late() {
-    var unit = parseCompilationUnit('late a;',
-        featureSet: nonNullable,
-        errors: [
-          expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
-        ]);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    var declarationList = declaration.variables;
-    expect(declarationList.keyword, isNull);
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseTopLevelVariable_late_final() {
-    var unit = parseCompilationUnit('late final a;', featureSet: nonNullable);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    var declarationList = declaration.variables;
-    expect(declarationList.keyword.lexeme, 'final');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseTopLevelVariable_late_init() {
-    var unit = parseCompilationUnit('late a = 0;',
-        featureSet: nonNullable,
-        errors: [
-          expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
-        ]);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    var declarationList = declaration.variables;
-    expect(declarationList.keyword, isNull);
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseTopLevelVariable_late_type() {
-    var unit = parseCompilationUnit('late A a;', featureSet: nonNullable);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    var declarationList = declaration.variables;
-    expect(declarationList.lateKeyword, isNotNull);
-    expect(declarationList.keyword, isNull);
-    expect(declarationList.type, isNotNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseTopLevelVariable_non_external() {
-    var unit = parseCompilationUnit('int i;', featureSet: nonNullable);
-    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
-    expect(declaration.externalKeyword, isNull);
-  }
-}
-
-@reflectiveTest
-class VarianceParserTest_Fasta extends FastaParserTestCase {
-  @override
-  CompilationUnit parseCompilationUnit(String content,
-      {List<ErrorCode> codes,
-      List<ExpectedError> errors,
-      FeatureSet featureSet}) {
-    return super.parseCompilationUnit(content,
-        codes: codes,
-        errors: errors,
-        featureSet: featureSet ??
-            FeatureSet.forTesting(
-              sdkVersion: '2.5.0',
-              additionalFeatures: [Feature.variance],
-            ));
-  }
-
-  void test_class_disabled_multiple() {
-    parseCompilationUnit('class A<in T, inout U, out V> { }',
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 2),
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 14, 5),
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 23, 3)
-        ],
-        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
-  }
-
-  void test_class_disabled_single() {
-    parseCompilationUnit('class A<out T> { }',
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 3),
-        ],
-        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
-  }
-
-  void test_class_enabled_multiple() {
-    var unit = parseCompilationUnit('class A<in T, inout U, out V, W> { }');
-    expect(unit.declarations, hasLength(1));
-    var classDecl = unit.declarations[0] as ClassDeclaration;
-    expect(classDecl.name.name, 'A');
-
-    expect(classDecl.typeParameters.typeParameters, hasLength(4));
-    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
-    expect(classDecl.typeParameters.typeParameters[1].name.name, 'U');
-    expect(classDecl.typeParameters.typeParameters[2].name.name, 'V');
-    expect(classDecl.typeParameters.typeParameters[3].name.name, 'W');
-
-    var typeParameterImplList = classDecl.typeParameters.typeParameters;
-    expect((typeParameterImplList[0] as TypeParameterImpl).varianceKeyword,
-        isNotNull);
-    expect(
-        (typeParameterImplList[0] as TypeParameterImpl).varianceKeyword.lexeme,
-        "in");
-    expect((typeParameterImplList[1] as TypeParameterImpl).varianceKeyword,
-        isNotNull);
-    expect(
-        (typeParameterImplList[1] as TypeParameterImpl).varianceKeyword.lexeme,
-        "inout");
-    expect((typeParameterImplList[2] as TypeParameterImpl).varianceKeyword,
-        isNotNull);
-    expect(
-        (typeParameterImplList[2] as TypeParameterImpl).varianceKeyword.lexeme,
-        "out");
-    expect((typeParameterImplList[3] as TypeParameterImpl).varianceKeyword,
-        isNull);
-  }
-
-  void test_class_enabled_multipleVariances() {
-    var unit = parseCompilationUnit('class A<in out inout T> { }', errors: [
-      expectedError(ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS, 11, 3),
-      expectedError(ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS, 15, 5)
-    ]);
-    expect(unit.declarations, hasLength(1));
-    var classDecl = unit.declarations[0] as ClassDeclaration;
-    expect(classDecl.name.name, 'A');
-    expect(classDecl.typeParameters.typeParameters, hasLength(1));
-    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
-  }
-
-  void test_class_enabled_single() {
-    var unit = parseCompilationUnit('class A<in T> { }');
-    expect(unit.declarations, hasLength(1));
-    var classDecl = unit.declarations[0] as ClassDeclaration;
-    expect(classDecl.name.name, 'A');
-    expect(classDecl.typeParameters.typeParameters, hasLength(1));
-    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
-
-    var typeParameterImpl =
-        classDecl.typeParameters.typeParameters[0] as TypeParameterImpl;
-    expect(typeParameterImpl.varianceKeyword, isNotNull);
-    expect(typeParameterImpl.varianceKeyword.lexeme, "in");
-  }
-
-  void test_function_disabled() {
-    parseCompilationUnit('void A(in int value) {}',
-        errors: [
-          expectedError(
-              ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 2),
-          expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
-        ],
-        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
-  }
-
-  void test_function_enabled() {
-    parseCompilationUnit('void A(in int value) {}', errors: [
-      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 2),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
-    ]);
-  }
-
-  void test_list_disabled() {
-    parseCompilationUnit('List<out String> stringList = [];',
-        errors: [
-          expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 6),
-        ],
-        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
-  }
-
-  void test_list_enabled() {
-    parseCompilationUnit('List<out String> stringList = [];', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 6),
-    ]);
-  }
-
-  void test_mixin_disabled_multiple() {
-    parseCompilationUnit('mixin A<inout T, out U> { }',
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 5),
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 3),
-        ],
-        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
-  }
-
-  void test_mixin_disabled_single() {
-    parseCompilationUnit('mixin A<inout T> { }',
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 5),
-        ],
-        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
-  }
-
-  void test_mixin_enabled_single() {
-    var unit = parseCompilationUnit('mixin A<inout T> { }');
-    expect(unit.declarations, hasLength(1));
-    var mixinDecl = unit.declarations[0] as MixinDeclaration;
-    expect(mixinDecl.name.name, 'A');
-    expect(mixinDecl.typeParameters.typeParameters, hasLength(1));
-    expect(mixinDecl.typeParameters.typeParameters[0].name.name, 'T');
-  }
-
-  void test_typedef_disabled() {
-    parseCompilationUnit('typedef A<inout X> = X Function(X);',
-        errors: [
-          expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
-        ],
-        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
-  }
-
-  void test_typedef_enabled() {
-    parseCompilationUnit('typedef A<inout X> = X Function(X);', errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
-    ]);
-  }
-}
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
deleted file mode 100644
index 340cb84..0000000
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ /dev/null
@@ -1,18037 +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.
-
-import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
-    show AbstractScanner;
-import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
-    show ScannerResult, scanString;
-import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/ast.dart'
-    show InstanceCreationExpressionImpl;
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/testing/token_factory.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../util/ast_type_matchers.dart';
-import 'test_support.dart';
-
-main() {
-  // The fasta parser has a parallel set of tests in parser_fasta_test.dart
-  if (Parser.useFasta) {
-    test('useFasta', () => true);
-    return;
-  }
-
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ClassMemberParserTest);
-    defineReflectiveTests(ComplexParserTest);
-    defineReflectiveTests(ErrorParserTest);
-    defineReflectiveTests(ExpressionParserTest);
-    defineReflectiveTests(FormalParameterParserTest);
-    defineReflectiveTests(NonErrorParserTest);
-    defineReflectiveTests(RecoveryParserTest);
-    defineReflectiveTests(SimpleParserTest);
-    defineReflectiveTests(StatementParserTest);
-    defineReflectiveTests(TopLevelParserTest);
-  });
-}
-
-/// Abstract base class for parser tests, which does not make assumptions about
-/// which parser is used.
-abstract class AbstractParserTestCase implements ParserTestHelpers {
-  bool get allowNativeClause;
-
-  set allowNativeClause(bool value);
-
-  /// Set a flag indicating whether the parser should parse instance creation
-  /// expressions that lack either the `new` or `const` keyword.
-  set enableOptionalNewAndConst(bool value);
-
-  /// Set a flag indicating whether the parser is to parse part-of directives
-  /// that specify a URI rather than a library name.
-  set enableUriInPartOf(bool value);
-
-  /// The error listener to which scanner and parser errors will be reported.
-  ///
-  /// This field is typically initialized by invoking [createParser].
-  GatheringErrorListener get listener;
-
-  /// Get the parser used by the test.
-  ///
-  /// Caller must first invoke [createParser].
-  Parser get parser;
-
-  /// Flag indicating whether the fasta parser is being used.
-  bool get usingFastaParser;
-
-  /// Assert that the number and codes of errors occurred during parsing is the
-  /// same as the [expectedErrorCodes].
-  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes);
-
-  /// Asserts that no errors occurred during parsing.
-  void assertNoErrors();
-
-  /// Prepares to parse using tokens scanned from the given [content] string.
-  ///
-  /// [expectedEndOffset] is the expected offset of the next token to be parsed
-  /// after the parser has finished parsing,
-  /// or `null` (the default) if EOF is expected.
-  /// In general, the analyzer tests do not assert that the last token is EOF,
-  /// but the fasta parser adapter tests do assert this.
-  /// For any analyzer test where the last token is not EOF, set this value.
-  /// It is ignored when not using the fasta parser.
-  void createParser(
-    String content, {
-    int expectedEndOffset,
-    FeatureSet featureSet,
-  });
-
-  ExpectedError expectedError(ErrorCode code, int offset, int length);
-
-  void expectNotNullIfNoErrors(Object result);
-
-  Expression parseAdditiveExpression(String code);
-
-  Expression parseAssignableExpression(String code, bool primaryAllowed);
-
-  Expression parseAssignableSelector(String code, bool optional,
-      {bool allowConditional = true});
-
-  AwaitExpression parseAwaitExpression(String code);
-
-  Expression parseBitwiseAndExpression(String code);
-
-  Expression parseBitwiseOrExpression(String code);
-
-  Expression parseBitwiseXorExpression(String code);
-
-  Expression parseCascadeSection(String code);
-
-  CommentReference parseCommentReference(
-      String referenceSource, int sourceOffset);
-
-  CompilationUnit parseCompilationUnit(String source,
-      {List<ErrorCode> codes, List<ExpectedError> errors});
-
-  ConditionalExpression parseConditionalExpression(String code);
-
-  Expression parseConstExpression(String code);
-
-  ConstructorInitializer parseConstructorInitializer(String code);
-
-  /// Parse the given source as a compilation unit.
-  ///
-  /// @param source the source to be parsed
-  /// @param errorCodes the error codes of the errors that are expected to be
-  ///          found
-  /// @return the compilation unit that was parsed
-  /// @throws Exception if the source could not be parsed, if the compilation
-  ///           errors in the source do not match those that are expected, or if
-  ///           the result would have been `null`
-  CompilationUnit parseDirectives(String source,
-      [List<ErrorCode> errorCodes = const <ErrorCode>[]]);
-
-  BinaryExpression parseEqualityExpression(String code);
-
-  Expression parseExpression(String source,
-      {List<ErrorCode> codes,
-      List<ExpectedError> errors,
-      int expectedEndOffset});
-
-  List<Expression> parseExpressionList(String code);
-
-  Expression parseExpressionWithoutCascade(String code);
-
-  FormalParameter parseFormalParameter(String code, ParameterKind kind,
-      {List<ErrorCode> errorCodes = const <ErrorCode>[]});
-
-  FormalParameterList parseFormalParameterList(String code,
-      {bool inFunctionType = false,
-      List<ErrorCode> errorCodes = const <ErrorCode>[],
-      List<ExpectedError> errors});
-
-  /// Parses a single top level member of a compilation unit (other than a
-  /// directive), including any comment and/or metadata that precedes it.
-  CompilationUnitMember parseFullCompilationUnitMember();
-
-  /// Parses a single top level directive, including any comment and/or metadata
-  /// that precedes it.
-  Directive parseFullDirective();
-
-  FunctionExpression parseFunctionExpression(String code);
-
-  InstanceCreationExpression parseInstanceCreationExpression(
-      String code, Token newToken);
-
-  ListLiteral parseListLiteral(
-      Token token, String typeArgumentsCode, String code);
-
-  TypedLiteral parseListOrMapLiteral(Token modifier, String code);
-
-  Expression parseLogicalAndExpression(String code);
-
-  Expression parseLogicalOrExpression(String code);
-
-  SetOrMapLiteral parseMapLiteral(
-      Token token, String typeArgumentsCode, String code);
-
-  MapLiteralEntry parseMapLiteralEntry(String code);
-
-  Expression parseMultiplicativeExpression(String code);
-
-  InstanceCreationExpression parseNewExpression(String code);
-
-  NormalFormalParameter parseNormalFormalParameter(String code,
-      {bool inFunctionType = false,
-      List<ErrorCode> errorCodes = const <ErrorCode>[]});
-
-  Expression parsePostfixExpression(String code);
-
-  Identifier parsePrefixedIdentifier(String code);
-
-  Expression parsePrimaryExpression(String code,
-      {int expectedEndOffset, List<ExpectedError> errors});
-
-  Expression parseRelationalExpression(String code);
-
-  RethrowExpression parseRethrowExpression(String code);
-
-  BinaryExpression parseShiftExpression(String code);
-
-  SimpleIdentifier parseSimpleIdentifier(String code);
-
-  Statement parseStatement(String source, {int expectedEndOffset});
-
-  Expression parseStringLiteral(String code);
-
-  SymbolLiteral parseSymbolLiteral(String code);
-
-  Expression parseThrowExpression(String code);
-
-  Expression parseThrowExpressionWithoutCascade(String code);
-
-  PrefixExpression parseUnaryExpression(String code);
-
-  VariableDeclarationList parseVariableDeclarationList(String source);
-}
-
-/// Instances of the class `AstValidator` are used to validate the correct
-/// construction of an AST structure.
-class AstValidator extends UnifyingAstVisitor<void> {
-  /// A list containing the errors found while traversing the AST structure.
-  final List<String> _errors = <String>[];
-
-  /// Assert that no errors were found while traversing any of the AST
-  /// structures that have been visited.
-  void assertValid() {
-    if (_errors.isNotEmpty) {
-      StringBuffer buffer = StringBuffer();
-      buffer.write("Invalid AST structure:");
-      for (String message in _errors) {
-        buffer.write("\r\n   ");
-        buffer.write(message);
-      }
-      fail(buffer.toString());
-    }
-  }
-
-  @override
-  void visitNode(AstNode node) {
-    _validate(node);
-    super.visitNode(node);
-  }
-
-  /// Validate that the given AST node is correctly constructed.
-  ///
-  /// @param node the AST node being validated
-  void _validate(AstNode node) {
-    AstNode parent = node.parent;
-    if (node is CompilationUnit) {
-      if (parent != null) {
-        _errors.add("Compilation units should not have a parent");
-      }
-    } else {
-      if (parent == null) {
-        _errors.add("No parent for ${node.runtimeType}");
-      }
-    }
-    if (node.beginToken == null) {
-      _errors.add("No begin token for ${node.runtimeType}");
-    }
-    if (node.endToken == null) {
-      _errors.add("No end token for ${node.runtimeType}");
-    }
-    int nodeStart = node.offset;
-    int nodeLength = node.length;
-    if (nodeStart < 0 || nodeLength < 0) {
-      _errors.add("No source info for ${node.runtimeType}");
-    }
-    if (parent != null) {
-      int nodeEnd = nodeStart + nodeLength;
-      int parentStart = parent.offset;
-      int parentEnd = parentStart + parent.length;
-      if (nodeStart < parentStart) {
-        _errors.add(
-            "Invalid source start ($nodeStart) for ${node.runtimeType} inside ${parent.runtimeType} ($parentStart)");
-      }
-      if (nodeEnd > parentEnd) {
-        _errors.add(
-            "Invalid source end ($nodeEnd) for ${node.runtimeType} inside ${parent.runtimeType} ($parentStart)");
-      }
-    }
-  }
-}
-
-@reflectiveTest
-class ClassMemberParserTest extends ParserTestCase
-    with ClassMemberParserTestMixin {
-  @failingTest
-  @override
-  void test_parseAwaitExpression_inSync() {
-    super.test_parseAwaitExpression_inSync();
-  }
-}
-
-/// Tests which exercise the parser using a class member.
-mixin ClassMemberParserTestMixin implements AbstractParserTestCase {
-  void test_parseAwaitExpression_asStatement_inAsync() {
-    createParser('m() async { await x; }');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    FunctionBody body = method.body;
-    expect(body, isBlockFunctionBody);
-    Statement statement = (body as BlockFunctionBody).block.statements[0];
-    expect(statement, isExpressionStatement);
-    Expression expression = (statement as ExpressionStatement).expression;
-    expect(expression, isAwaitExpression);
-    expect((expression as AwaitExpression).awaitKeyword, isNotNull);
-    expect((expression as AwaitExpression).expression, isNotNull);
-  }
-
-  void test_parseAwaitExpression_asStatement_inSync() {
-    createParser('m() { await x; }');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    FunctionBody body = method.body;
-    expect(body, isBlockFunctionBody);
-    Statement statement = (body as BlockFunctionBody).block.statements[0];
-    expect(statement, isVariableDeclarationStatement);
-  }
-
-  void test_parseAwaitExpression_inSync() {
-    createParser('m() { return await x + await y; }');
-    MethodDeclaration method = parser.parseClassMember('C');
-    expect(method, isNotNull);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 13, 5),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5)
-          ]
-        : [
-            // This test requires better error recovery than we currently have.
-            // In particular, we need to be able to distinguish
-            // between an await expression in the wrong context,
-            // and the use of 'await' as an identifier.
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 5),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 1)
-          ]);
-    FunctionBody body = method.body;
-    expect(body, isBlockFunctionBody);
-    Statement statement = (body as BlockFunctionBody).block.statements[0];
-    expect(statement, isReturnStatement);
-    Expression expression = (statement as ReturnStatement).expression;
-    expect(expression, isBinaryExpression);
-    if (!usingFastaParser) {
-      // TODO(danrubel): capture `await` keywords in fasta generated AST
-      expect((expression as BinaryExpression).leftOperand, isAwaitExpression);
-      expect((expression as BinaryExpression).rightOperand, isAwaitExpression);
-    }
-  }
-
-  void test_parseClassMember_constructor_withDocComment() {
-    createParser('/// Doc\nC();');
-    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
-    expectCommentText(constructor.documentationComment, '/// Doc');
-  }
-
-  void test_parseClassMember_constructor_withInitializers() {
-    // TODO(brianwilkerson) Test other kinds of class members: fields, getters
-    // and setters.
-    createParser('C(_, _\$, this.__) : _a = _ + _\$ {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isConstructorDeclaration);
-    ConstructorDeclaration constructor = member;
-    expect(constructor.body, isNotNull);
-    expect(constructor.separator, isNotNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword, isNull);
-    expect(constructor.factoryKeyword, isNull);
-    expect(constructor.name, isNull);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.period, isNull);
-    expect(constructor.returnType, isNotNull);
-    expect(constructor.initializers, hasLength(1));
-  }
-
-  void test_parseClassMember_field_covariant() {
-    createParser('covariant T f;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    FieldDeclaration field = member;
-    expect(field.covariantKeyword, isNotNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list.keyword, isNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isFalse);
-    expect(list.lateKeyword, isNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseClassMember_field_generic() {
-    createParser('List<List<N>> _allComponents = new List<List<N>>();');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    FieldDeclaration field = member;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list, isNotNull);
-    expect(list.keyword, isNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isFalse);
-    expect(list.lateKeyword, isNull);
-    TypeName type = list.type;
-    expect(type.name.name, 'List');
-    NodeList typeArguments = type.typeArguments.arguments;
-    expect(typeArguments, hasLength(1));
-    TypeName type2 = typeArguments[0];
-    expect(type2.name.name, 'List');
-    NodeList typeArguments2 = type2.typeArguments.arguments;
-    expect(typeArguments2, hasLength(1));
-    TypeName type3 = typeArguments2[0];
-    expect(type3.name.name, 'N');
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseClassMember_field_gftType_gftReturnType() {
-    createParser('''
-Function(int) Function(String) v;
-''');
-    ClassMember member = parser.parseClassMember('C');
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    VariableDeclarationList fields = (member as FieldDeclaration).fields;
-    expect(fields.type, isGenericFunctionType);
-  }
-
-  void test_parseClassMember_field_gftType_noReturnType() {
-    createParser('''
-Function(int, String) v;
-''');
-    ClassMember member = parser.parseClassMember('C');
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    VariableDeclarationList fields = (member as FieldDeclaration).fields;
-    expect(fields.type, isGenericFunctionType);
-  }
-
-  void test_parseClassMember_field_instance_prefixedType() {
-    createParser('p.A f;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    FieldDeclaration field = member;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list, isNotNull);
-    expect(list.keyword, isNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isFalse);
-    expect(list.lateKeyword, isNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-    _assertIsDeclarationName(variable.name);
-  }
-
-  void test_parseClassMember_field_namedGet() {
-    createParser('var get;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    FieldDeclaration field = member;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isFalse);
-    expect(list.lateKeyword, isNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseClassMember_field_namedOperator() {
-    createParser('var operator;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    FieldDeclaration field = member;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isFalse);
-    expect(list.lateKeyword, isNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseClassMember_field_namedOperator_withAssignment() {
-    createParser('var operator = (5);');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    FieldDeclaration field = member;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isFalse);
-    expect(list.lateKeyword, isNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-    expect(variable.initializer, isNotNull);
-  }
-
-  void test_parseClassMember_field_namedSet() {
-    createParser('var set;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    FieldDeclaration field = member;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list, isNotNull);
-    expect(list.keyword, isNotNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isFalse);
-    expect(list.lateKeyword, isNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseClassMember_field_nameKeyword() {
-    createParser('var for;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 4, 3)
-          ]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 3),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 3)
-          ]);
-  }
-
-  void test_parseClassMember_field_nameMissing() {
-    createParser('var ;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]);
-  }
-
-  void test_parseClassMember_field_nameMissing2() {
-    createParser('var "";');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 2)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 2),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 2)
-          ]);
-  }
-
-  void test_parseClassMember_field_static() {
-    createParser('static A f;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFieldDeclaration);
-    FieldDeclaration field = member;
-    expect(field.covariantKeyword, isNull);
-    expect(field.documentationComment, isNull);
-    expect(field.metadata, hasLength(0));
-    expect(field.staticKeyword, isNotNull);
-    VariableDeclarationList list = field.fields;
-    expect(list, isNotNull);
-    expect(list, isNotNull);
-    expect(list.keyword, isNull);
-    expect(list.isConst, isFalse);
-    expect(list.isFinal, isFalse);
-    expect(list.isLate, isFalse);
-    expect(list.lateKeyword, isNull);
-    NodeList<VariableDeclaration> variables = list.variables;
-    expect(variables, hasLength(1));
-    VariableDeclaration variable = variables[0];
-    expect(variable.name, isNotNull);
-  }
-
-  void test_parseClassMember_getter_functionType() {
-    createParser('int Function(int) get g {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNotNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.body, isNotNull);
-    expect(method.parameters, isNull);
-  }
-
-  void test_parseClassMember_getter_void() {
-    createParser('void get g {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNotNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    _assertIsDeclarationName(method.name);
-    expect(method.operatorKeyword, isNull);
-    expect(method.body, isNotNull);
-    expect(method.parameters, isNull);
-  }
-
-  void test_parseClassMember_method_external() {
-    createParser('external m();');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNotNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.name, isNotNull);
-    _assertIsDeclarationName(method.name);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNull);
-
-    var body = method.body as EmptyFunctionBody;
-    expect(body.keyword, isNull);
-    expect(body.star, isNull);
-    expect(body.semicolon.type, TokenType.SEMICOLON);
-  }
-
-  void test_parseClassMember_method_external_withTypeAndArgs() {
-    createParser('external int m(int a);');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.body, isNotNull);
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNotNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-  }
-
-  void test_parseClassMember_method_generic_noReturnType() {
-    createParser('m<T>() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNotNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_generic_parameterType() {
-    createParser('m<T>(T p) => null;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNotNull);
-
-    FormalParameterList parameters = method.parameters;
-    expect(parameters, isNotNull);
-    expect(parameters.parameters, hasLength(1));
-    var parameter = parameters.parameters[0] as SimpleFormalParameter;
-    var parameterType = parameter.type as TypeName;
-    expect(parameterType.name.name, 'T');
-
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_generic_returnType() {
-    createParser('T m<T>() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNotNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_generic_returnType_bound() {
-    createParser('T m<T extends num>() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect((method.returnType as TypeName).name.name, 'T');
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNotNull);
-    TypeParameter tp = method.typeParameters.typeParameters[0];
-    expect(tp.name.name, 'T');
-    expect(tp.extendsKeyword, isNotNull);
-    expect((tp.bound as TypeName).name.name, 'num');
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_generic_returnType_complex() {
-    createParser('Map<int, T> m<T>() => null;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-
-    {
-      var returnType = method.returnType as TypeName;
-      expect(returnType, isNotNull);
-      expect(returnType.name.name, 'Map');
-
-      List<TypeAnnotation> typeArguments = returnType.typeArguments.arguments;
-      expect(typeArguments, hasLength(2));
-      expect((typeArguments[0] as TypeName).name.name, 'int');
-      expect((typeArguments[1] as TypeName).name.name, 'T');
-    }
-
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNotNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_generic_returnType_static() {
-    createParser('static T m<T>() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNotNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect((method.returnType as TypeName).name.name, 'T');
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNotNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_generic_void() {
-    createParser('void m<T>() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNotNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_get_noType() {
-    createParser('get() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_get_static_namedAsClass() {
-    createParser('static int get C => 0;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 15, 1),
-      ]);
-    } else {
-      assertNoErrors();
-    }
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNotNull);
-    expect(method.propertyKeyword, isNotNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_get_type() {
-    createParser('int get() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_get_void() {
-    createParser('void get() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_gftReturnType_noReturnType() {
-    createParser('''
-Function<A>(core.List<core.int> x) m() => null;
-''');
-    ClassMember member = parser.parseClassMember('C');
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    expect((member as MethodDeclaration).body, isExpressionFunctionBody);
-  }
-
-  void test_parseClassMember_method_gftReturnType_voidReturnType() {
-    createParser('''
-void Function<A>(core.List<core.int> x) m() => null;
-''');
-    ClassMember member = parser.parseClassMember('C');
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    expect((member as MethodDeclaration).body, isExpressionFunctionBody);
-  }
-
-  void test_parseClassMember_method_native_allowed() {
-    allowNativeClause = true;
-    _parseClassMember_method_native();
-    assertNoErrors();
-  }
-
-  void test_parseClassMember_method_native_missing_literal_allowed() {
-    allowNativeClause = true;
-    _parseClassMember_method_native_missing_literal();
-    assertNoErrors();
-  }
-
-  void test_parseClassMember_method_native_missing_literal_not_allowed() {
-    allowNativeClause = false;
-    _parseClassMember_method_native_missing_literal();
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
-      ]);
-    } else {
-      assertNoErrors();
-    }
-  }
-
-  void test_parseClassMember_method_native_not_allowed() {
-    allowNativeClause = false;
-    _parseClassMember_method_native();
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
-      ]);
-    } else {
-      assertNoErrors();
-    }
-  }
-
-  void test_parseClassMember_method_native_with_body_allowed() {
-    allowNativeClause = true;
-    _parseClassMember_method_native_with_body();
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      assertErrorsWithCodes([
-        ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
-      ]);
-//      listener.assertErrors([
-//        expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 17, 2),
-//      ]);
-    } else {
-      assertErrorsWithCodes([
-        ParserErrorCode.EXPECTED_TOKEN,
-      ]);
-    }
-  }
-
-  void test_parseClassMember_method_native_with_body_not_allowed() {
-    allowNativeClause = false;
-    _parseClassMember_method_native_with_body();
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      assertErrorsWithCodes([
-        ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
-        ParserErrorCode.EXTERNAL_METHOD_WITH_BODY,
-      ]);
-//      listener.assertErrors([
-//        expectedError(ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION, 4, 6),
-//        expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 17, 2),
-//      ]);
-    } else {
-      assertErrorsWithCodes([
-        ParserErrorCode.EXPECTED_TOKEN,
-      ]);
-    }
-  }
-
-  void test_parseClassMember_method_operator_noType() {
-    createParser('operator() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_operator_type() {
-    createParser('int operator() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_operator_void() {
-    createParser('void operator() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_returnType_functionType() {
-    createParser('int Function(String) m() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.name.name, 'm');
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_returnType_parameterized() {
-    createParser('p.A m() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_set_noType() {
-    createParser('set() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_set_static_namedAsClass() {
-    createParser('static void set C(_) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.MEMBER_WITH_CLASS_NAME, 16, 1),
-      ]);
-    } else {
-      assertNoErrors();
-    }
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNotNull);
-    expect(method.propertyKeyword, isNotNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_set_type() {
-    createParser('int set() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_set_void() {
-    createParser('void set() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_static_class() {
-    var unit = parseCompilationUnit('class C { static void m() {} }');
-
-    ClassDeclaration c = unit.declarations[0];
-    MethodDeclaration method = c.members[0];
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNotNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_static_mixin() {
-    if (!usingFastaParser) return;
-    var unit = parseCompilationUnit('mixin C { static void m() {} }');
-    MixinDeclaration c = unit.declarations[0];
-    MethodDeclaration method = c.members[0];
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNotNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_method_trailing_commas() {
-    createParser('void f(int x, int y,) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_operator_functionType() {
-    createParser('int Function() operator +(int Function() f) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isGenericFunctionType);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNotNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    NodeList<FormalParameter> parameters = method.parameters.parameters;
-    expect(parameters, hasLength(1));
-    expect(
-        (parameters[0] as SimpleFormalParameter).type, isGenericFunctionType);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_operator_index() {
-    createParser('int operator [](int i) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNotNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_operator_indexAssign() {
-    createParser('int operator []=(int i) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNotNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_operator_lessThan() {
-    createParser('bool operator <(other) => false;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.documentationComment, isNull);
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.propertyKeyword, isNull);
-    expect(method.returnType, isNotNull);
-    expect(method.name.name, '<');
-    expect(method.operatorKeyword, isNotNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.body, isNotNull);
-  }
-
-  void test_parseClassMember_redirectingFactory_const() {
-    createParser('const factory C() = prefix.B.foo;');
-    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
-    assertNoErrors();
-    expect(constructor, isNotNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword.keyword, Keyword.CONST);
-    expect(constructor.factoryKeyword.keyword, Keyword.FACTORY);
-    expect(constructor.returnType.name, 'C');
-    expect(constructor.period, isNull);
-    expect(constructor.name, isNull);
-    _assertIsDeclarationName(constructor.returnType, false);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.parameters.parameters, isEmpty);
-    expect(constructor.separator.type, TokenType.EQ);
-    expect(constructor.initializers, isEmpty);
-    expect(constructor.redirectedConstructor, isNotNull);
-    expect(constructor.redirectedConstructor.type.name.name, 'prefix.B');
-    expect(constructor.redirectedConstructor.period.type, TokenType.PERIOD);
-    expect(constructor.redirectedConstructor.name.name, 'foo');
-    expect(constructor.body, isEmptyFunctionBody);
-  }
-
-  void test_parseClassMember_redirectingFactory_expressionBody() {
-    createParser('factory C() => throw 0;');
-    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
-    assertNoErrors();
-    expect(constructor, isNotNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword, isNull);
-    expect(constructor.factoryKeyword.keyword, Keyword.FACTORY);
-    expect(constructor.returnType.name, 'C');
-    expect(constructor.period, isNull);
-    expect(constructor.name, isNull);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.parameters.parameters, isEmpty);
-    expect(constructor.separator, isNull);
-    expect(constructor.initializers, isEmpty);
-    expect(constructor.redirectedConstructor, isNull);
-
-    var body = constructor.body as ExpressionFunctionBody;
-    expect(body.keyword, isNull);
-    expect(body.star, isNull);
-    expect(body.functionDefinition.type, TokenType.FUNCTION);
-    expect(body.expression, isNotNull);
-    expect(body.semicolon, isNotNull);
-  }
-
-  void test_parseClassMember_redirectingFactory_nonConst() {
-    createParser('factory C() = B;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isConstructorDeclaration);
-    ConstructorDeclaration constructor = member;
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword, isNull);
-    expect(constructor.factoryKeyword.keyword, Keyword.FACTORY);
-    expect(constructor.returnType.name, 'C');
-    _assertIsDeclarationName(constructor.returnType, false);
-    expect(constructor.period, isNull);
-    expect(constructor.name, isNull);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.parameters.parameters, isEmpty);
-    expect(constructor.separator.type, TokenType.EQ);
-    expect(constructor.initializers, isEmpty);
-    expect(constructor.redirectedConstructor, isNotNull);
-    expect(constructor.redirectedConstructor.type.name.name, 'B');
-    expect(constructor.redirectedConstructor.period, isNull);
-    expect(constructor.redirectedConstructor.name, isNull);
-    expect(constructor.body, isEmptyFunctionBody);
-  }
-
-  void test_parseConstructor_assert() {
-    createParser('C(x, y) : _x = x, assert (x < y), _y = y;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isConstructorDeclaration);
-    ConstructorDeclaration constructor = member as ConstructorDeclaration;
-    NodeList<ConstructorInitializer> initializers = constructor.initializers;
-    expect(initializers, hasLength(3));
-    ConstructorInitializer initializer = initializers[1];
-    expect(initializer, isAssertInitializer);
-    AssertInitializer assertInitializer = initializer;
-    expect(assertInitializer.condition, isNotNull);
-    expect(assertInitializer.message, isNull);
-  }
-
-  void test_parseConstructor_factory_const_external() {
-    // Although the spec does not allow external const factory,
-    // there are several instances of this in the Dart SDK.
-    // For example `external const factory bool.fromEnvironment(...)`.
-    createParser('external const factory C();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_parseConstructor_factory_named() {
-    createParser('factory C.foo() => throw 0;');
-    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
-    assertNoErrors();
-    expect(constructor, isNotNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword, isNull);
-    expect(constructor.factoryKeyword, isNotNull);
-    expect(constructor.returnType.name, 'C');
-    _assertIsDeclarationName(constructor.returnType, false);
-    expect(constructor.period.type, TokenType.PERIOD);
-    expect(constructor.name.name, 'foo');
-    _assertIsDeclarationName(constructor.name);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.parameters.parameters, isEmpty);
-    expect(constructor.separator, isNull);
-    expect(constructor.initializers, isEmpty);
-    expect(constructor.redirectedConstructor, isNull);
-    expect(constructor.body, isExpressionFunctionBody);
-  }
-
-  void test_parseConstructor_initializers_field() {
-    createParser('C(x, y) : _x = x, this._y = y;');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isConstructorDeclaration);
-    ConstructorDeclaration constructor = member as ConstructorDeclaration;
-    NodeList<ConstructorInitializer> initializers = constructor.initializers;
-    expect(initializers, hasLength(2));
-
-    {
-      var initializer = initializers[0] as ConstructorFieldInitializer;
-      expect(initializer.thisKeyword, isNull);
-      expect(initializer.period, isNull);
-      expect(initializer.fieldName.name, '_x');
-      expect(initializer.expression, isNotNull);
-    }
-
-    {
-      var initializer = initializers[1] as ConstructorFieldInitializer;
-      expect(initializer.thisKeyword, isNotNull);
-      expect(initializer.period, isNotNull);
-      expect(initializer.fieldName.name, '_y');
-      expect(initializer.expression, isNotNull);
-    }
-  }
-
-  void test_parseConstructor_named() {
-    createParser('C.foo();');
-    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
-    assertNoErrors();
-    expect(constructor, isNotNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword, isNull);
-    expect(constructor.factoryKeyword, isNull);
-    expect(constructor.returnType.name, 'C');
-    _assertIsDeclarationName(constructor.returnType, false);
-    expect(constructor.period.type, TokenType.PERIOD);
-    expect(constructor.name.name, 'foo');
-    _assertIsDeclarationName(constructor.name);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.parameters.parameters, isEmpty);
-    expect(constructor.separator, isNull);
-    expect(constructor.initializers, isEmpty);
-    expect(constructor.redirectedConstructor, isNull);
-    expect(constructor.body, isEmptyFunctionBody);
-  }
-
-  void test_parseConstructor_superIndexed() {
-    createParser('C() : super()[];');
-    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
-    listener.assertErrors([
-      expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 6, 5),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 1),
-    ]);
-    expect(constructor, isNotNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword, isNull);
-    expect(constructor.factoryKeyword, isNull);
-    expect(constructor.returnType.name, 'C');
-    _assertIsDeclarationName(constructor.returnType, false);
-    expect(constructor.name, isNull);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.parameters.parameters, isEmpty);
-    expect(constructor.separator.lexeme, ':');
-    expect(constructor.initializers, hasLength(1));
-    SuperConstructorInvocation initializer = constructor.initializers[0];
-    expect(initializer.argumentList.arguments, isEmpty);
-    expect(constructor.redirectedConstructor, isNull);
-    expect(constructor.body, isEmptyFunctionBody);
-  }
-
-  void test_parseConstructor_thisIndexed() {
-    createParser('C() : this()[];');
-    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
-    listener.assertErrors([
-      expectedError(ParserErrorCode.INVALID_THIS_IN_INITIALIZER, 6, 4),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
-    ]);
-    expect(constructor, isNotNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword, isNull);
-    expect(constructor.factoryKeyword, isNull);
-    expect(constructor.returnType.name, 'C');
-    _assertIsDeclarationName(constructor.returnType, false);
-    expect(constructor.name, isNull);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.parameters.parameters, isEmpty);
-    expect(constructor.separator.lexeme, ':');
-    expect(constructor.initializers, hasLength(1));
-    RedirectingConstructorInvocation initializer = constructor.initializers[0];
-    expect(initializer.argumentList.arguments, isEmpty);
-    expect(constructor.redirectedConstructor, isNull);
-    expect(constructor.body, isEmptyFunctionBody);
-  }
-
-  void test_parseConstructor_unnamed() {
-    createParser('C();');
-    var constructor = parser.parseClassMember('C') as ConstructorDeclaration;
-    assertNoErrors();
-    expect(constructor, isNotNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.constKeyword, isNull);
-    expect(constructor.factoryKeyword, isNull);
-    expect(constructor.returnType.name, 'C');
-    _assertIsDeclarationName(constructor.returnType, false);
-    expect(constructor.period, isNull);
-    expect(constructor.name, isNull);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.parameters.parameters, isEmpty);
-    expect(constructor.separator, isNull);
-    expect(constructor.initializers, isEmpty);
-    expect(constructor.redirectedConstructor, isNull);
-    expect(constructor.body, isEmptyFunctionBody);
-  }
-
-  void test_parseConstructor_with_pseudo_function_literal() {
-    // "(b) {}" should not be misinterpreted as a function literal even though
-    // it looks like one.
-    createParser('C() : a = (b) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isConstructorDeclaration);
-    ConstructorDeclaration constructor = member as ConstructorDeclaration;
-    NodeList<ConstructorInitializer> initializers = constructor.initializers;
-    expect(initializers, hasLength(1));
-    ConstructorInitializer initializer = initializers[0];
-    expect(initializer, isConstructorFieldInitializer);
-    expect((initializer as ConstructorFieldInitializer).expression,
-        isParenthesizedExpression);
-    expect(constructor.body, isBlockFunctionBody);
-  }
-
-  void test_parseConstructorFieldInitializer_qualified() {
-    var initializer = parseConstructorInitializer('this.a = b')
-        as ConstructorFieldInitializer;
-    expect(initializer, isNotNull);
-    assertNoErrors();
-    expect(initializer.equals, isNotNull);
-    expect(initializer.expression, isNotNull);
-    expect(initializer.fieldName, isNotNull);
-    expect(initializer.thisKeyword, isNotNull);
-    expect(initializer.period, isNotNull);
-  }
-
-  void test_parseConstructorFieldInitializer_unqualified() {
-    var initializer =
-        parseConstructorInitializer('a = b') as ConstructorFieldInitializer;
-    expect(initializer, isNotNull);
-    assertNoErrors();
-    expect(initializer.equals, isNotNull);
-    expect(initializer.expression, isNotNull);
-    expect(initializer.fieldName, isNotNull);
-    expect(initializer.thisKeyword, isNull);
-    expect(initializer.period, isNull);
-  }
-
-  void test_parseGetter_identifier_colon_issue_36961() {
-    createParser('get a:');
-    ConstructorDeclaration constructor = parser.parseClassMember('C');
-    expect(constructor, isNotNull);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.GETTER_CONSTRUCTOR, 0, 3),
-      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 4, 1),
-      expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 4, 1),
-      expectedError(ParserErrorCode.MISSING_INITIALIZER, 5, 1),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 6, 0),
-    ]);
-    expect(constructor.body, isNotNull);
-    expect(constructor.documentationComment, isNull);
-    expect(constructor.externalKeyword, isNull);
-    expect(constructor.name, isNull);
-    expect(constructor.parameters, isNotNull);
-    expect(constructor.returnType, isNotNull);
-  }
-
-  void test_parseGetter_nonStatic() {
-    createParser('/// Doc\nT get a;');
-    MethodDeclaration method = parser.parseClassMember('C');
-    expect(method, isNotNull);
-    assertNoErrors();
-    expect(method.body, isNotNull);
-    expectCommentText(method.documentationComment, '/// Doc');
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.parameters, isNull);
-    expect(method.propertyKeyword, isNotNull);
-    expect((method.returnType as TypeName).name.name, 'T');
-  }
-
-  void test_parseGetter_static() {
-    createParser('/// Doc\nstatic T get a => 42;');
-    MethodDeclaration method = parser.parseClassMember('C');
-    expect(method, isNotNull);
-    assertNoErrors();
-    expect(method.body, isNotNull);
-    expectCommentText(method.documentationComment, '/// Doc');
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword.lexeme, 'static');
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNull);
-    expect(method.propertyKeyword, isNotNull);
-    expect((method.returnType as TypeName).name.name, 'T');
-  }
-
-  void test_parseInitializedIdentifierList_type() {
-    createParser("/// Doc\nstatic T a = 1, b, c = 3;");
-    FieldDeclaration declaration = parser.parseClassMember('C');
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expectCommentText(declaration.documentationComment, '/// Doc');
-    VariableDeclarationList fields = declaration.fields;
-    expect(fields, isNotNull);
-    expect(fields.keyword, isNull);
-    expect((fields.type as TypeName).name.name, 'T');
-    expect(fields.variables, hasLength(3));
-    expect(declaration.staticKeyword.lexeme, 'static');
-    expect(declaration.semicolon, isNotNull);
-  }
-
-  void test_parseInitializedIdentifierList_var() {
-    createParser('/// Doc\nstatic var a = 1, b, c = 3;');
-    FieldDeclaration declaration = parser.parseClassMember('C');
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expectCommentText(declaration.documentationComment, '/// Doc');
-    VariableDeclarationList fields = declaration.fields;
-    expect(fields, isNotNull);
-    expect(fields.keyword.lexeme, 'var');
-    expect(fields.type, isNull);
-    expect(fields.variables, hasLength(3));
-    expect(declaration.staticKeyword.lexeme, 'static');
-    expect(declaration.semicolon, isNotNull);
-  }
-
-  void test_parseOperator() {
-    createParser('/// Doc\nT operator +(A a);');
-    MethodDeclaration method = parser.parseClassMember('C');
-    expect(method, isNotNull);
-    assertNoErrors();
-    expect(method.body, isNotNull);
-    expectCommentText(method.documentationComment, '/// Doc');
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNotNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.propertyKeyword, isNull);
-    expect((method.returnType as TypeName).name.name, 'T');
-  }
-
-  void test_parseSetter_nonStatic() {
-    createParser('/// Doc\nT set a(var x);');
-    MethodDeclaration method = parser.parseClassMember('C');
-    expect(method, isNotNull);
-    assertNoErrors();
-    expect(method.body, isNotNull);
-    expectCommentText(method.documentationComment, '/// Doc');
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword, isNull);
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.propertyKeyword, isNotNull);
-    expect((method.returnType as TypeName).name.name, 'T');
-  }
-
-  void test_parseSetter_static() {
-    createParser('/// Doc\nstatic T set a(var x) {}');
-    MethodDeclaration method = parser.parseClassMember('C');
-    expect(method, isNotNull);
-    assertNoErrors();
-    expect(method.body, isNotNull);
-    expectCommentText(method.documentationComment, '/// Doc');
-    expect(method.externalKeyword, isNull);
-    expect(method.modifierKeyword.lexeme, 'static');
-    expect(method.name, isNotNull);
-    expect(method.operatorKeyword, isNull);
-    expect(method.typeParameters, isNull);
-    expect(method.parameters, isNotNull);
-    expect(method.propertyKeyword, isNotNull);
-    expect((method.returnType as TypeName).name.name, 'T');
-  }
-
-  void test_simpleFormalParameter_withDocComment() {
-    createParser('''
-int f(
-    /// Doc
-    int x) {}
-''');
-    var function = parseFullCompilationUnitMember() as FunctionDeclaration;
-    var parameter = function.functionExpression.parameters.parameters[0]
-        as NormalFormalParameter;
-    expectCommentText(parameter.documentationComment, '/// Doc');
-  }
-
-  /// Assert that the given [name] is in declaration context.
-  void _assertIsDeclarationName(SimpleIdentifier name, [bool expected = true]) {
-    expect(name.inDeclarationContext(), expected);
-  }
-
-  void _parseClassMember_method_native() {
-    createParser('m() native "str";');
-    var method = parser.parseClassMember('C') as MethodDeclaration;
-    var body = method.body as NativeFunctionBody;
-    expect(body.nativeKeyword, isNotNull);
-    expect(body.stringLiteral, isNotNull);
-    expect(body.stringLiteral?.stringValue, "str");
-    expect(body.semicolon, isNotNull);
-  }
-
-  void _parseClassMember_method_native_missing_literal() {
-    createParser('m() native;');
-    var method = parser.parseClassMember('C') as MethodDeclaration;
-    var body = method.body as NativeFunctionBody;
-    expect(body.nativeKeyword, isNotNull);
-    expect(body.stringLiteral, isNull);
-    expect(body.semicolon, isNotNull);
-  }
-
-  void _parseClassMember_method_native_with_body() {
-    createParser('m() native "str" {}');
-    parser.parseClassMember('C') as MethodDeclaration;
-  }
-}
-
-/// Tests of the analyzer parser based on [ComplexParserTestMixin].
-@reflectiveTest
-class ComplexParserTest extends ParserTestCase with ComplexParserTestMixin {}
-
-/// The class `ComplexParserTest` defines parser tests that test the parsing of
-/// more complex code fragments or the interactions between multiple parsing
-/// methods. For example, tests to ensure that the precedence of operations is
-/// being handled correctly should be defined in this class.
-///
-/// Simpler tests should be defined in the class [SimpleParserTest].
-mixin ComplexParserTestMixin implements AbstractParserTestCase {
-  void test_additiveExpression_normal() {
-    BinaryExpression expression = parseExpression("x + y - z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_additiveExpression_noSpaces() {
-    BinaryExpression expression = parseExpression("i+1");
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.rightOperand, isIntegerLiteral);
-  }
-
-  void test_additiveExpression_precedence_multiplicative_left() {
-    BinaryExpression expression = parseExpression("x * y + z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_additiveExpression_precedence_multiplicative_left_withSuper() {
-    BinaryExpression expression = parseExpression("super * y - z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_additiveExpression_precedence_multiplicative_right() {
-    BinaryExpression expression = parseExpression("x + y * z");
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_additiveExpression_super() {
-    BinaryExpression expression = parseExpression("super + y - z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_assignableExpression_arguments_normal_chain() {
-    PropertyAccess propertyAccess1 = parseExpression("a(b)(c).d(e).f");
-    expect(propertyAccess1.propertyName.name, "f");
-    //
-    // a(b)(c).d(e)
-    //
-    MethodInvocation invocation2 = propertyAccess1.target;
-    expect(invocation2.methodName.name, "d");
-    expect(invocation2.typeArguments, isNull);
-    ArgumentList argumentList2 = invocation2.argumentList;
-    expect(argumentList2, isNotNull);
-    expect(argumentList2.arguments, hasLength(1));
-    //
-    // a(b)(c)
-    //
-    FunctionExpressionInvocation invocation3 = invocation2.target;
-    expect(invocation3.typeArguments, isNull);
-    ArgumentList argumentList3 = invocation3.argumentList;
-    expect(argumentList3, isNotNull);
-    expect(argumentList3.arguments, hasLength(1));
-    //
-    // a(b)
-    //
-    MethodInvocation invocation4 = invocation3.function;
-    expect(invocation4.methodName.name, "a");
-    expect(invocation4.typeArguments, isNull);
-    ArgumentList argumentList4 = invocation4.argumentList;
-    expect(argumentList4, isNotNull);
-    expect(argumentList4.arguments, hasLength(1));
-  }
-
-  void test_assignableExpression_arguments_normal_chain_typeArguments() {
-    _validate_assignableExpression_arguments_normal_chain_typeArguments(
-        "a<E>(b)<F>(c).d<G>(e).f");
-  }
-
-  void test_assignmentExpression_compound() {
-    AssignmentExpression expression = parseExpression("x = y = 0");
-    expect(expression.leftHandSide, isSimpleIdentifier);
-    expect(expression.rightHandSide, isAssignmentExpression);
-  }
-
-  void test_assignmentExpression_indexExpression() {
-    AssignmentExpression expression = parseExpression("x[1] = 0");
-    expect(expression.leftHandSide, isIndexExpression);
-    expect(expression.rightHandSide, isIntegerLiteral);
-  }
-
-  void test_assignmentExpression_prefixedIdentifier() {
-    AssignmentExpression expression = parseExpression("x.y = 0");
-    expect(expression.leftHandSide, isPrefixedIdentifier);
-    expect(expression.rightHandSide, isIntegerLiteral);
-  }
-
-  void test_assignmentExpression_propertyAccess() {
-    AssignmentExpression expression = parseExpression("super.y = 0");
-    expect(expression.leftHandSide, isPropertyAccess);
-    expect(expression.rightHandSide, isIntegerLiteral);
-  }
-
-  void test_bitwiseAndExpression_normal() {
-    BinaryExpression expression = parseExpression("x & y & z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseAndExpression_precedence_equality_left() {
-    BinaryExpression expression = parseExpression("x == y && z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseAndExpression_precedence_equality_right() {
-    BinaryExpression expression = parseExpression("x && y == z");
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseAndExpression_super() {
-    BinaryExpression expression = parseExpression("super & y & z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseOrExpression_normal() {
-    BinaryExpression expression = parseExpression("x | y | z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseOrExpression_precedence_xor_left() {
-    BinaryExpression expression = parseExpression("x ^ y | z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseOrExpression_precedence_xor_right() {
-    BinaryExpression expression = parseExpression("x | y ^ z");
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseOrExpression_super() {
-    BinaryExpression expression = parseExpression("super | y | z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseXorExpression_normal() {
-    BinaryExpression expression = parseExpression("x ^ y ^ z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseXorExpression_precedence_and_left() {
-    BinaryExpression expression = parseExpression("x & y ^ z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseXorExpression_precedence_and_right() {
-    BinaryExpression expression = parseExpression("x ^ y & z");
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseXorExpression_super() {
-    BinaryExpression expression = parseExpression("super ^ y ^ z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_cascade_withAssignment() {
-    CascadeExpression cascade =
-        parseExpression("new Map()..[3] = 4 ..[0] = 11");
-    Expression target = cascade.target;
-    for (Expression section in cascade.cascadeSections) {
-      expect(section, isAssignmentExpression);
-      Expression lhs = (section as AssignmentExpression).leftHandSide;
-      expect(lhs, isIndexExpression);
-      IndexExpression index = lhs as IndexExpression;
-      expect(index.isCascaded, isTrue);
-      expect(index.realTarget, same(target));
-    }
-  }
-
-  void test_conditionalExpression_precedence_ifNullExpression() {
-    ConditionalExpression expression = parseExpression('a ?? b ? y : z');
-    expect(expression.condition, isBinaryExpression);
-  }
-
-  void test_conditionalExpression_precedence_logicalOrExpression() {
-    ConditionalExpression expression = parseExpression("a | b ? y : z");
-    expect(expression.condition, isBinaryExpression);
-  }
-
-  void test_conditionalExpression_precedence_nullableType_as() {
-    ExpressionStatement statement = parseStatement('x as bool ? (x + y) : z;');
-    ConditionalExpression expression = statement.expression;
-    Expression condition = expression.condition;
-    expect(condition, isAsExpression);
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-  }
-
-  void test_conditionalExpression_precedence_nullableType_is() {
-    ExpressionStatement statement =
-        parseStatement('x is String ? (x + y) : z;');
-    ConditionalExpression expression = statement.expression;
-    Expression condition = expression.condition;
-    expect(condition, isIsExpression);
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-  }
-
-  void test_conditionalExpression_precedence_nullableTypeWithTypeArg1_is() {
-    ExpressionStatement statement =
-        parseStatement('x is String<S> ? (x + y) : z;');
-    ConditionalExpression expression = statement.expression;
-    Expression condition = expression.condition;
-    expect(condition, TypeMatcher<IsExpression>());
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, TypeMatcher<ParenthesizedExpression>());
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, TypeMatcher<SimpleIdentifier>());
-  }
-
-  void test_conditionalExpression_precedence_nullableTypeWithTypeArg1GFT_is() {
-    ExpressionStatement statement =
-        parseStatement('x is String<S> Function() ? (x + y) : z;');
-    ConditionalExpression expression = statement.expression;
-    Expression condition = expression.condition;
-    expect(condition, TypeMatcher<IsExpression>());
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, TypeMatcher<ParenthesizedExpression>());
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, TypeMatcher<SimpleIdentifier>());
-  }
-
-  void test_conditionalExpression_precedence_nullableTypeWithTypeArg2_is() {
-    ExpressionStatement statement =
-        parseStatement('x is String<S,T> ? (x + y) : z;');
-    ConditionalExpression expression = statement.expression;
-    Expression condition = expression.condition;
-    expect(condition, TypeMatcher<IsExpression>());
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, TypeMatcher<ParenthesizedExpression>());
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, TypeMatcher<SimpleIdentifier>());
-  }
-
-  void test_conditionalExpression_precedence_prefixedNullableType_is() {
-    ExpressionStatement statement = parseStatement('x is p.A ? (x + y) : z;');
-    ConditionalExpression expression = statement.expression;
-
-    Expression condition = expression.condition;
-    expect(condition, TypeMatcher<IsExpression>());
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, TypeMatcher<ParenthesizedExpression>());
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, TypeMatcher<SimpleIdentifier>());
-  }
-
-  void test_conditionalExpression_precedence_withAssignment() {
-    ExpressionStatement statement = parseStatement('b ? c = true : g();');
-    ConditionalExpression expression = statement.expression;
-    expect(expression.condition, TypeMatcher<SimpleIdentifier>());
-    expect(expression.thenExpression, TypeMatcher<AssignmentExpression>());
-  }
-
-  void test_conditionalExpression_precedence_withAssignment2() {
-    ExpressionStatement statement = parseStatement('b.x ? c = true : g();');
-    ConditionalExpression expression = statement.expression;
-    expect(expression.condition, TypeMatcher<PrefixedIdentifier>());
-    expect(expression.thenExpression, TypeMatcher<AssignmentExpression>());
-  }
-
-  void test_conditionalExpression_prefixedValue() {
-    ExpressionStatement statement = parseStatement('a.b ? y : z;');
-    ConditionalExpression expression = statement.expression;
-    expect(expression.condition, TypeMatcher<PrefixedIdentifier>());
-    expect(expression.thenExpression, TypeMatcher<SimpleIdentifier>());
-  }
-
-  void test_conditionalExpression_prefixedValue2() {
-    ExpressionStatement statement = parseStatement('a.b ? x.y : z;');
-    ConditionalExpression expression = statement.expression;
-    expect(expression.condition, TypeMatcher<PrefixedIdentifier>());
-    expect(expression.thenExpression, TypeMatcher<PrefixedIdentifier>());
-  }
-
-  void test_constructor_initializer_withParenthesizedExpression() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  C() :
-    this.a = (b == null ? c : d) {
-  }
-}''');
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-  }
-
-  void test_equalityExpression_normal() {
-    BinaryExpression expression = parseExpression("x == y != z",
-        codes: [ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_equalityExpression_precedence_relational_left() {
-    BinaryExpression expression = parseExpression("x is y == z");
-    expect(expression.leftOperand, isIsExpression);
-  }
-
-  void test_equalityExpression_precedence_relational_right() {
-    BinaryExpression expression = parseExpression("x == y is z");
-    expect(expression.rightOperand, isIsExpression);
-  }
-
-  void test_equalityExpression_super() {
-    BinaryExpression expression = parseExpression("super == y != z",
-        codes: [ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_ifNullExpression() {
-    BinaryExpression expression = parseExpression('x ?? y ?? z');
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_ifNullExpression_precedence_logicalOr_left() {
-    BinaryExpression expression = parseExpression('x || y ?? z');
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_ifNullExpression_precedence_logicalOr_right() {
-    BinaryExpression expression = parseExpression('x ?? y || z');
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_logicalAndExpression() {
-    BinaryExpression expression = parseExpression("x && y && z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_logicalAndExpression_precedence_bitwiseOr_left() {
-    BinaryExpression expression = parseExpression("x | y < z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_logicalAndExpression_precedence_bitwiseOr_right() {
-    BinaryExpression expression = parseExpression("x < y | z");
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_logicalAndExpressionStatement() {
-    // Assert that `<` and `>` are not interpreted as type arguments.
-    ExpressionStatement statement = parseStatement("C<T && T>U;");
-    BinaryExpression expression = statement.expression;
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_logicalOrExpression() {
-    BinaryExpression expression = parseExpression("x || y || z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_logicalOrExpression_precedence_logicalAnd_left() {
-    BinaryExpression expression = parseExpression("x && y || z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_logicalOrExpression_precedence_logicalAnd_right() {
-    BinaryExpression expression = parseExpression("x || y && z");
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_methodInvocation1() {
-    // Assert that `<` and `>` are not interpreted as type arguments.
-    ExpressionStatement statement = parseStatement("f(a < b, c > 3);");
-    assertNoErrors();
-    MethodInvocation method = statement.expression;
-    expect(method.argumentList.arguments, hasLength(2));
-  }
-
-  void test_methodInvocation2() {
-    // Assert that `<` and `>` are not interpreted as type arguments.
-    ExpressionStatement statement = parseStatement("f(a < b, c >> 3);");
-    assertNoErrors();
-    MethodInvocation method = statement.expression;
-    expect(method.argumentList.arguments, hasLength(2));
-  }
-
-  void test_methodInvocation3() {
-    // Assert that `<` and `>` are not interpreted as type arguments.
-    ExpressionStatement statement = parseStatement("f(a < b, c < d >> 3);");
-    assertNoErrors();
-    MethodInvocation method = statement.expression;
-    expect(method.argumentList.arguments, hasLength(2));
-  }
-
-  void test_multipleLabels_statement() {
-    LabeledStatement statement = parseStatement("a: b: c: return x;");
-    expect(statement.labels, hasLength(3));
-    expect(statement.statement, isReturnStatement);
-  }
-
-  void test_multiplicativeExpression_normal() {
-    BinaryExpression expression = parseExpression("x * y / z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_multiplicativeExpression_precedence_unary_left() {
-    BinaryExpression expression = parseExpression("-x * y");
-    expect(expression.leftOperand, isPrefixExpression);
-  }
-
-  void test_multiplicativeExpression_precedence_unary_right() {
-    BinaryExpression expression = parseExpression("x * -y");
-    expect(expression.rightOperand, isPrefixExpression);
-  }
-
-  void test_multiplicativeExpression_super() {
-    BinaryExpression expression = parseExpression("super * y / z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_relationalExpression_precedence_shift_right() {
-    IsExpression expression = parseExpression("x << y is z");
-    expect(expression.expression, isBinaryExpression);
-  }
-
-  void test_shiftExpression_normal() {
-    BinaryExpression expression = parseExpression("x >> 4 << 3");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_shiftExpression_precedence_additive_left() {
-    BinaryExpression expression = parseExpression("x + y << z");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_shiftExpression_precedence_additive_right() {
-    BinaryExpression expression = parseExpression("x << y + z");
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_shiftExpression_super() {
-    BinaryExpression expression = parseExpression("super >> 4 << 3");
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_topLevelFunction_nestedGenericFunction() {
-    parseCompilationUnit('''
-void f() {
-  void g<T>() {
-  }
-}
-''');
-  }
-
-  void _validate_assignableExpression_arguments_normal_chain_typeArguments(
-      String code,
-      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
-    PropertyAccess propertyAccess1 = parseExpression(code, codes: errorCodes);
-    expect(propertyAccess1.propertyName.name, "f");
-    //
-    // a<E>(b)<F>(c).d<G>(e)
-    //
-    MethodInvocation invocation2 = propertyAccess1.target;
-    expect(invocation2.methodName.name, "d");
-    expect(invocation2.typeArguments, isNotNull);
-    ArgumentList argumentList2 = invocation2.argumentList;
-    expect(argumentList2, isNotNull);
-    expect(argumentList2.arguments, hasLength(1));
-    //
-    // a<E>(b)<F>(c)
-    //
-    FunctionExpressionInvocation invocation3 = invocation2.target;
-    expect(invocation3.typeArguments, isNotNull);
-    ArgumentList argumentList3 = invocation3.argumentList;
-    expect(argumentList3, isNotNull);
-    expect(argumentList3.arguments, hasLength(1));
-    //
-    // a(b)
-    //
-    MethodInvocation invocation4 = invocation3.function;
-    expect(invocation4.methodName.name, "a");
-    expect(invocation4.typeArguments, isNotNull);
-    ArgumentList argumentList4 = invocation4.argumentList;
-    expect(argumentList4, isNotNull);
-    expect(argumentList4.arguments, hasLength(1));
-  }
-}
-
-/// The class `ErrorParserTest` defines parser tests that test the parsing
-/// of code to ensure that errors are correctly reported,
-/// and in some cases, not reported.
-@reflectiveTest
-class ErrorParserTest extends ParserTestCase with ErrorParserTestMixin {
-  void test_missingIdentifier_number() {
-    createParser('1');
-    SimpleIdentifier expression = parser.parseSimpleIdentifier();
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
-    expect(expression.isSynthetic, isTrue);
-  }
-}
-
-mixin ErrorParserTestMixin implements AbstractParserTestCase {
-  void test_abstractClassMember_constructor() {
-    createParser('abstract C.c();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 0, 8)]);
-  }
-
-  void test_abstractClassMember_field() {
-    createParser('abstract C f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_abstractClassMember_getter() {
-    createParser('abstract get m;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 0, 8)]);
-  }
-
-  void test_abstractClassMember_method() {
-    createParser('abstract m();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 0, 8)]);
-  }
-
-  void test_abstractClassMember_setter() {
-    createParser('abstract set m(v);');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 0, 8)]);
-  }
-
-  void test_abstractEnum() {
-    parseCompilationUnit("abstract enum E {ONE}",
-        errors: [expectedError(ParserErrorCode.ABSTRACT_ENUM, 0, 8)]);
-  }
-
-  void test_abstractTopLevelFunction_function() {
-    parseCompilationUnit("abstract f(v) {}", errors: [
-      expectedError(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, 0, 8)
-    ]);
-  }
-
-  void test_abstractTopLevelFunction_getter() {
-    parseCompilationUnit("abstract get m {}", errors: [
-      expectedError(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, 0, 8)
-    ]);
-  }
-
-  void test_abstractTopLevelFunction_setter() {
-    parseCompilationUnit("abstract set m(v) {}", errors: [
-      expectedError(ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION, 0, 8)
-    ]);
-  }
-
-  void test_abstractTopLevelVariable() {
-    parseCompilationUnit("abstract C f;", errors: [
-      expectedError(ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE, 0, 8)
-    ]);
-  }
-
-  void test_abstractTypeDef() {
-    parseCompilationUnit("abstract typedef F();",
-        errors: [expectedError(ParserErrorCode.ABSTRACT_TYPEDEF, 0, 8)]);
-  }
-
-  void test_breakOutsideOfLoop_breakInDoStatement() {
-    DoStatement statement = parseStatement('do {break;} while (x);');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_breakOutsideOfLoop_breakInForStatement() {
-    Statement statement = parseStatement('for (; x;) {break;}');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_breakOutsideOfLoop_breakInIfStatement() {
-    IfStatement statement = parseStatement('if (x) {break;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, 8, 5)]);
-  }
-
-  void test_breakOutsideOfLoop_breakInSwitchStatement() {
-    SwitchStatement statement = parseStatement('switch (x) {case 1: break;}');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_breakOutsideOfLoop_breakInWhileStatement() {
-    WhileStatement statement = parseStatement('while (x) {break;}');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_breakOutsideOfLoop_functionExpression_inALoop() {
-    parseStatement("for(; x;) {() {break;};}");
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP, 15, 5)]);
-  }
-
-  void test_breakOutsideOfLoop_functionExpression_withALoop() {
-    parseStatement("() {for (; x;) {break;}};");
-  }
-
-  void test_classInClass_abstract() {
-    parseCompilationUnit("class C { abstract class B {} }",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.ABSTRACT_CLASS_MEMBER, 10, 8),
-                expectedError(ParserErrorCode.CLASS_IN_CLASS, 19, 5)
-              ]
-            : [expectedError(ParserErrorCode.CLASS_IN_CLASS, 19, 5)]);
-  }
-
-  void test_classInClass_nonAbstract() {
-    parseCompilationUnit("class C { class B {} }",
-        errors: [expectedError(ParserErrorCode.CLASS_IN_CLASS, 10, 5)]);
-  }
-
-  void test_classTypeAlias_abstractAfterEq() {
-    // This syntax has been removed from the language in favor of
-    // "abstract class A = B with C;" (issue 18098).
-    createParser('class A = abstract B with C;', expectedEndOffset: 21);
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 8),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0)
-          ]);
-  }
-
-  void test_colonInPlaceOfIn() {
-    parseStatement("for (var x : list) {}");
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.COLON_IN_PLACE_OF_IN, 11, 1)]);
-  }
-
-  void test_constAndCovariant() {
-    createParser('covariant const C f = null;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 10, 5)]);
-  }
-
-  void test_constAndFinal() {
-    createParser('const final int x = null;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.CONST_AND_FINAL, 6, 5)]);
-  }
-
-  void test_constAndVar() {
-    createParser('const var x = null;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.CONFLICTING_MODIFIERS, 6, 3)]);
-  }
-
-  void test_constClass() {
-    parseCompilationUnit("const class C {}",
-        errors: [expectedError(ParserErrorCode.CONST_CLASS, 0, 5)]);
-  }
-
-  void test_constConstructorWithBody() {
-    createParser('const C() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, 10, 1)]);
-  }
-
-  void test_constEnum() {
-    parseCompilationUnit("const enum E {ONE}",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `const` as a malformed top level const
-                // and `enum` as the start of an enum declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
-              ]
-            : [expectedError(ParserErrorCode.CONST_ENUM, 0, 5)]);
-  }
-
-  void test_constFactory() {
-    createParser('const factory C() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([expectedError(ParserErrorCode.CONST_FACTORY, 0, 5)]);
-  }
-
-  void test_constMethod() {
-    createParser('const int m() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
-  }
-
-  void test_constMethod_noReturnType() {
-    createParser('const m() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
-  }
-
-  void test_constMethod_noReturnType2() {
-    createParser('const m();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([expectedError(ParserErrorCode.CONST_METHOD, 0, 5)]);
-  }
-
-  void test_constructorPartial() {
-    createParser('class C { C< }');
-    parser.parseCompilationUnit2();
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 2),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
-            expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 13, 1),
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 13, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1)
-          ]);
-  }
-
-  void test_constructorPartial2() {
-    createParser('class C { C<@Foo }');
-    parser.parseCompilationUnit2();
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 6),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 17, 1),
-            expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 17, 1)
-          ]);
-  }
-
-  void test_constructorPartial3() {
-    createParser('class C { C<@Foo @Bar() }');
-    parser.parseCompilationUnit2();
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 13),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 1),
-            expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 24, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 12, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 24, 1)
-          ]);
-  }
-
-  void test_constructorWithReturnType() {
-    createParser('C C() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, 0, 1),
-    ]);
-  }
-
-  void test_constructorWithReturnType_var() {
-    createParser('var C() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3)]
-        : [expectedError(ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE, 0, 3)]);
-  }
-
-  void test_constTypedef() {
-    parseCompilationUnit("const typedef F();",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `const` as a malformed top level const
-                // and `typedef` as the start of an typedef declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 7),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 7),
-              ]
-            : [expectedError(ParserErrorCode.CONST_TYPEDEF, 0, 5)]);
-  }
-
-  void test_continueOutsideOfLoop_continueInDoStatement() {
-    DoStatement statement = parseStatement('do {continue;} while (x);');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_continueOutsideOfLoop_continueInForStatement() {
-    Statement statement = parseStatement('for (; x;) {continue;}');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_continueOutsideOfLoop_continueInIfStatement() {
-    IfStatement statement = parseStatement('if (x) {continue;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, 8, 8)]);
-  }
-
-  void test_continueOutsideOfLoop_continueInSwitchStatement() {
-    SwitchStatement statement =
-        parseStatement('switch (x) {case 1: continue a;}');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_continueOutsideOfLoop_continueInWhileStatement() {
-    WhileStatement statement = parseStatement('while (x) {continue;}');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_continueOutsideOfLoop_functionExpression_inALoop() {
-    parseStatement("for(; x;) {() {continue;};}");
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP, 15, 8)]);
-  }
-
-  void test_continueOutsideOfLoop_functionExpression_withALoop() {
-    parseStatement("() {for (; x;) {continue;}};");
-  }
-
-  void test_continueWithoutLabelInCase_error() {
-    SwitchStatement statement =
-        parseStatement('switch (x) {case 1: continue;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.CONTINUE_WITHOUT_LABEL_IN_CASE, 20, 8)]);
-  }
-
-  void test_continueWithoutLabelInCase_noError() {
-    SwitchStatement statement =
-        parseStatement('switch (x) {case 1: continue a;}');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_continueWithoutLabelInCase_noError_switchInLoop() {
-    WhileStatement statement =
-        parseStatement('while (a) { switch (b) {default: continue;}}');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-  }
-
-  void test_covariantAfterVar() {
-    createParser('var covariant f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 4, 9)]);
-  }
-
-  void test_covariantAndFinal() {
-    createParser('covariant final f = null;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrorsWithCodes([ParserErrorCode.FINAL_AND_COVARIANT]);
-  }
-
-  void test_covariantAndStatic() {
-    createParser('covariant static A f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 10, 6)]);
-  }
-
-  void test_covariantAndType_local() {
-    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
-    // this would be a better error message.
-    parseStatement("covariant int x;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 9)]
-        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 9)]);
-  }
-
-  void test_covariantConstructor() {
-    createParser('class C { covariant C(); }');
-    ClassDeclaration member = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.COVARIANT_MEMBER
-              : ParserErrorCode.COVARIANT_CONSTRUCTOR,
-          10,
-          9)
-    ]);
-  }
-
-  void test_covariantMember_getter_noReturnType() {
-    createParser('static covariant get x => 0;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 7, 9)]
-        : [expectedError(ParserErrorCode.COVARIANT_MEMBER, 7, 9)]);
-  }
-
-  void test_covariantMember_getter_returnType() {
-    createParser('static covariant int get x => 0;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.COVARIANT_AND_STATIC, 7, 9)]
-        : [expectedError(ParserErrorCode.COVARIANT_MEMBER, 7, 9)]);
-  }
-
-  void test_covariantMember_method() {
-    createParser('covariant int m() => 0;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.COVARIANT_MEMBER, 0, 9)]);
-  }
-
-  void test_covariantTopLevelDeclaration_class() {
-    createParser('covariant class C {}');
-    ClassDeclaration member = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION, 0, 9)]);
-  }
-
-  void test_covariantTopLevelDeclaration_enum() {
-    createParser('covariant enum E { v }');
-    EnumDeclaration member = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION, 0, 9)]);
-  }
-
-  void test_covariantTopLevelDeclaration_typedef() {
-    parseCompilationUnit("covariant typedef F();", errors: [
-      expectedError(ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION, 0, 9)
-    ]);
-  }
-
-  void test_defaultValueInFunctionType_named_colon() {
-    createParser('({int x : 0})');
-    FormalParameter parameter =
-        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
-    expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1)]);
-  }
-
-  void test_defaultValueInFunctionType_named_equal() {
-    createParser('({int x = 0})');
-    FormalParameter parameter =
-        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
-    expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1)]);
-  }
-
-  void test_defaultValueInFunctionType_positional() {
-    createParser('([int x = 0])');
-    FormalParameter parameter =
-        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
-    expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1)]);
-  }
-
-  void test_directiveAfterDeclaration_classBeforeDirective() {
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    CompilationUnit unit = parseCompilationUnit("class Foo{} library l;",
-        codes: usingFastaParser
-            ? [ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST]
-            : [ParserErrorCode.DIRECTIVE_AFTER_DECLARATION],
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 12, 10)
-              ]
-            : [
-                expectedError(
-                    ParserErrorCode.DIRECTIVE_AFTER_DECLARATION, 12, 10)
-              ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_directiveAfterDeclaration_classBetweenDirectives() {
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    CompilationUnit unit =
-        parseCompilationUnit("library l;\nclass Foo{}\npart 'a.dart';", codes: [
-      ParserErrorCode.DIRECTIVE_AFTER_DECLARATION
-    ], errors: [
-      expectedError(ParserErrorCode.DIRECTIVE_AFTER_DECLARATION, 23, 14)
-    ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_duplicatedModifier_const() {
-    createParser('const const m = null;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 6, 5)]);
-  }
-
-  void test_duplicatedModifier_external() {
-    createParser('external external f();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 9, 8)]);
-  }
-
-  void test_duplicatedModifier_factory() {
-    createParser('factory factory C() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 8, 7)]);
-  }
-
-  void test_duplicatedModifier_final() {
-    createParser('final final m = null;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 6, 5)]);
-  }
-
-  void test_duplicatedModifier_static() {
-    createParser('static static var m;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 7, 6)]);
-  }
-
-  void test_duplicatedModifier_var() {
-    createParser('var var m;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.DUPLICATED_MODIFIER, 4, 3)]);
-  }
-
-  void test_duplicateLabelInSwitchStatement() {
-    SwitchStatement statement =
-        parseStatement('switch (e) {l1: case 0: break; l1: case 1: break;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.DUPLICATE_LABEL_IN_SWITCH_STATEMENT, 31, 2)
-    ]);
-  }
-
-  void test_emptyEnumBody() {
-    createParser('enum E {}');
-    EnumDeclaration declaration = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(declaration);
-    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-    listener.assertErrorsWithCodes([ParserErrorCode.EMPTY_ENUM_BODY]);
-//    listener
-//        .assertErrors([expectedError(ParserErrorCode.EMPTY_ENUM_BODY, 7, 2),]);
-  }
-
-  void test_enumInClass() {
-    parseCompilationUnit(r'''
-class Foo {
-  enum Bar {
-    Bar1, Bar2, Bar3
-  }
-}
-''', errors: [expectedError(ParserErrorCode.ENUM_IN_CLASS, 14, 4)]);
-  }
-
-  void test_equalityCannotBeEqualityOperand_eq_eq() {
-    parseExpression("1 == 2 == 3", errors: [
-      expectedError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 7, 2)
-    ]);
-  }
-
-  void test_equalityCannotBeEqualityOperand_eq_neq() {
-    parseExpression("1 == 2 != 3", errors: [
-      expectedError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 7, 2)
-    ]);
-  }
-
-  void test_equalityCannotBeEqualityOperand_neq_eq() {
-    parseExpression("1 != 2 == 3", errors: [
-      expectedError(ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND, 7, 2)
-    ]);
-  }
-
-  void test_expectedBody_class() {
-    parseCompilationUnit("class A class B {}",
-        errors: [expectedError(ParserErrorCode.EXPECTED_BODY, 6, 1)]);
-  }
-
-  void test_expectedCaseOrDefault() {
-    SwitchStatement statement = parseStatement('switch (e) {break;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)]
-        : [expectedError(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, 12, 5)]);
-  }
-
-  void test_expectedClassMember_inClass_afterType() {
-    parseCompilationUnit('class C{ heart 2 heart }',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 9, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 5),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 17, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 5)
-              ]
-            : [
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 1)
-              ]);
-  }
-
-  void test_expectedClassMember_inClass_beforeType() {
-    parseCompilationUnit('class C { 4 score }',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 10, 1),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 18, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 1)
-              ]);
-  }
-
-  void test_expectedExecutable_afterAnnotation_atEOF() {
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    parseCompilationUnit('@A',
-        codes: [ParserErrorCode.EXPECTED_EXECUTABLE],
-        errors: [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 1, 1)]);
-  }
-
-  void test_expectedExecutable_inClass_afterVoid() {
-    parseCompilationUnit('class C { void 2 void }',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 4),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1)
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 22, 1),
-              ]);
-  }
-
-  void test_expectedExecutable_topLevel_afterType() {
-    CompilationUnit unit = parseCompilationUnit('heart 2 heart',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 5),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 8, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 5),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 6, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 5)
-              ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_expectedExecutable_topLevel_afterVoid() {
-    CompilationUnit unit = parseCompilationUnit('void 2 void',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 5, 1),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 0),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 0),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 6, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 5)
-              ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_expectedExecutable_topLevel_beforeType() {
-    parseCompilationUnit('4 score',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 2, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 5),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 2, 5),
-              ]);
-  }
-
-  void test_expectedExecutable_topLevel_eof() {
-    parseCompilationUnit('x',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 1)
-              ]
-            : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1)]);
-  }
-
-  void test_expectedInterpolationIdentifier() {
-    StringLiteral literal = parseExpression("'\$x\$'",
-        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 4, 1)]);
-    expectNotNullIfNoErrors(literal);
-  }
-
-  void test_expectedInterpolationIdentifier_emptyString() {
-    // The scanner inserts an empty string token between the two $'s; we need to
-    // make sure that the MISSING_IDENTIFIER error that is generated has a
-    // nonzero width so that it will show up in the editor UI.
-    StringLiteral literal = parseExpression("'\$\$foo'",
-        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 2, 1)]);
-    expectNotNullIfNoErrors(literal);
-  }
-
-  @failingTest
-  void test_expectedListOrMapLiteral() {
-    // It isn't clear that this test can ever pass. The parser is currently
-    // create a synthetic list literal in this case, but isSynthetic() isn't
-    // overridden for ListLiteral. The problem is that the synthetic list
-    // literals that are being created are not always zero length (because they
-    // could have type parameters), which violates the contract of
-    // isSynthetic().
-    TypedLiteral literal = parseListOrMapLiteral(null, '1');
-    expectNotNullIfNoErrors(literal);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL, 1, 1)]);
-    expect(literal.isSynthetic, isTrue);
-  }
-
-  void test_expectedStringLiteral() {
-    StringLiteral literal = parseStringLiteral('1');
-    expectNotNullIfNoErrors(literal);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 0, 1)]);
-    expect(literal.isSynthetic, isTrue);
-  }
-
-  void test_expectedToken_commaMissingInArgumentList() {
-    createParser('(x, y z)');
-    ArgumentList list = parser.parseArgumentList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]
-        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]);
-  }
-
-  void test_expectedToken_parseStatement_afterVoid() {
-    parseStatement("void}", expectedEndOffset: 4);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
-    ]);
-  }
-
-  void test_expectedToken_semicolonMissingAfterExport() {
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    CompilationUnit unit = parseCompilationUnit("export '' class A {}",
-        codes: [ParserErrorCode.EXPECTED_TOKEN],
-        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 2)]);
-    ExportDirective directive = unit.directives[0] as ExportDirective;
-    expect(directive.uri, isNotNull);
-    expect(directive.uri.stringValue, '');
-    expect(directive.uri.beginToken.isSynthetic, false);
-    expect(directive.uri.isSynthetic, false);
-    Token semicolon = directive.semicolon;
-    expect(semicolon, isNotNull);
-    expect(semicolon.isSynthetic, isTrue);
-    ClassDeclaration clazz = unit.declarations[0] as ClassDeclaration;
-    expect(clazz.name.name, 'A');
-  }
-
-  void test_expectedToken_semicolonMissingAfterExpression() {
-    parseStatement("x");
-    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-    listener.assertErrorsWithCodes([ParserErrorCode.EXPECTED_TOKEN]);
-//    listener
-//        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 1)]);
-  }
-
-  void test_expectedToken_semicolonMissingAfterImport() {
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    CompilationUnit unit = parseCompilationUnit("import '' class A {}",
-        codes: [ParserErrorCode.EXPECTED_TOKEN],
-        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 2)]);
-    ImportDirective directive = unit.directives[0] as ImportDirective;
-    Token semicolon = directive.semicolon;
-    expect(semicolon, isNotNull);
-    expect(semicolon.isSynthetic, isTrue);
-  }
-
-  void test_expectedToken_uriAndSemicolonMissingAfterExport() {
-    CompilationUnit unit = parseCompilationUnit("export class A {}", errors: [
-      expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 7, 5),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 5),
-    ]);
-    ExportDirective directive = unit.directives[0] as ExportDirective;
-    expect(directive.uri, isNotNull);
-    expect(directive.uri.stringValue, '');
-    expect(directive.uri.beginToken.isSynthetic, true);
-    expect(directive.uri.isSynthetic, true);
-    Token semicolon = directive.semicolon;
-    expect(semicolon, isNotNull);
-    expect(semicolon.isSynthetic, isTrue);
-    ClassDeclaration clazz = unit.declarations[0] as ClassDeclaration;
-    expect(clazz.name.name, 'A');
-  }
-
-  void test_expectedToken_whileMissingInDoStatement() {
-    parseStatement("do {} (x);");
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
-  }
-
-  void test_expectedTypeName_as() {
-    parseExpression("x as",
-        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 0)]);
-  }
-
-  void test_expectedTypeName_as_void() {
-    parseExpression("x as void)",
-        expectedEndOffset: 9,
-        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 4)]);
-  }
-
-  void test_expectedTypeName_is() {
-    parseExpression("x is",
-        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 0)]);
-  }
-
-  void test_expectedTypeName_is_void() {
-    parseExpression("x is void)",
-        expectedEndOffset: 9,
-        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 4)]);
-  }
-
-  void test_exportAsType() {
-    parseCompilationUnit('export<dynamic> foo;',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 0, 6)
-              ]
-            : []);
-  }
-
-  void test_exportAsType_inClass() {
-    parseCompilationUnit('class C { export<dynamic> foo; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 6)
-              ]
-            : []);
-  }
-
-  void test_exportDirectiveAfterPartDirective() {
-    parseCompilationUnit("part 'a.dart'; export 'b.dart';", errors: [
-      expectedError(
-          ParserErrorCode.EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, 15, 6)
-    ]);
-  }
-
-  void test_externalAfterConst() {
-    createParser('const external C();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 8)]);
-  }
-
-  void test_externalAfterFactory() {
-    createParser('factory external C();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 8, 8)]);
-  }
-
-  void test_externalAfterStatic() {
-    createParser('static external int m();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 7, 8)]);
-  }
-
-  void test_externalClass() {
-    parseCompilationUnit("external class C {}",
-        errors: [expectedError(ParserErrorCode.EXTERNAL_CLASS, 0, 8)]);
-  }
-
-  void test_externalConstructorWithBody_factory() {
-    createParser('external factory C() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXTERNAL_FACTORY_WITH_BODY
-              : ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY,
-          21,
-          1)
-    ]);
-  }
-
-  void test_externalConstructorWithBody_named() {
-    createParser('external C.c() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
-//      listener.assertErrors(
-//          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 15, 2)]);
-    } else {
-      listener.assertErrorsWithCodes(
-          [ParserErrorCode.EXTERNAL_CONSTRUCTOR_WITH_BODY]);
-    }
-  }
-
-  void test_externalEnum() {
-    parseCompilationUnit("external enum E {ONE}",
-        errors: [expectedError(ParserErrorCode.EXTERNAL_ENUM, 0, 8)]);
-  }
-
-  void test_externalField_const() {
-    createParser('external const A f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 17, 1)]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_FIELD]);
-    }
-  }
-
-  void test_externalField_final() {
-    createParser('external final A f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_externalField_static() {
-    createParser('external static A f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_externalField_typed() {
-    createParser('external A f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_externalField_untyped() {
-    createParser('external var f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_externalGetterWithBody() {
-    createParser('external int get x {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
-//      listener.assertErrors(
-//          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 19, 2)]);
-    } else {
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_GETTER_WITH_BODY]);
-    }
-  }
-
-  void test_externalMethodWithBody() {
-    createParser('external m() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-    listener.assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
-//    listener.assertErrors(
-//        [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 13, 2)]);
-  }
-
-  void test_externalOperatorWithBody() {
-    createParser('external operator +(int value) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
-//      listener.assertErrors(
-//          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 31, 2)]);
-    } else {
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_OPERATOR_WITH_BODY]);
-    }
-  }
-
-  void test_externalSetterWithBody() {
-    createParser('external set x(int value) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_METHOD_WITH_BODY]);
-//      listener.assertErrors(
-//          [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 26, 2)]);
-    } else {
-      listener
-          .assertErrorsWithCodes([ParserErrorCode.EXTERNAL_SETTER_WITH_BODY]);
-    }
-  }
-
-  void test_externalTypedef() {
-    parseCompilationUnit("external typedef F();",
-        errors: [expectedError(ParserErrorCode.EXTERNAL_TYPEDEF, 0, 8)]);
-  }
-
-  void test_extraCommaInParameterList() {
-    createParser('(int a, , int b)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
-          ]);
-  }
-
-  void test_extraCommaTrailingNamedParameterGroup() {
-    createParser('({int b},)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
-            expectedError(
-                ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, 9, 1)
-          ]);
-  }
-
-  void test_extraCommaTrailingPositionalParameterGroup() {
-    createParser('([int b],)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
-            expectedError(
-                ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, 9, 1)
-          ]);
-  }
-
-  void test_extraTrailingCommaInParameterList() {
-    createParser('(a,,)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1)]);
-  }
-
-  void test_factoryTopLevelDeclaration_class() {
-    parseCompilationUnit("factory class C {}", errors: [
-      expectedError(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 0, 7)
-    ]);
-  }
-
-  void test_factoryTopLevelDeclaration_enum() {
-    parseCompilationUnit("factory enum E { v }", errors: [
-      expectedError(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 0, 7)
-    ]);
-  }
-
-  void test_factoryTopLevelDeclaration_typedef() {
-    parseCompilationUnit("factory typedef F();", errors: [
-      expectedError(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 0, 7)
-    ]);
-  }
-
-  void test_factoryWithInitializers() {
-    createParser('factory C() : x = 3 {}', expectedEndOffset: 12);
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)]
-        : [expectedError(ParserErrorCode.FACTORY_WITH_INITIALIZERS, 12, 1)]);
-  }
-
-  void test_factoryWithoutBody() {
-    createParser('factory C();');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 11, 1)]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.FACTORY_WITHOUT_BODY]);
-    }
-  }
-
-  void test_fieldInitializerOutsideConstructor() {
-    createParser('void m(this.x);');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, 7, 4)
-    ]);
-  }
-
-  void test_finalAndCovariant() {
-    createParser('final covariant f = null;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 9),
-            expectedError(ParserErrorCode.FINAL_AND_COVARIANT, 6, 9)
-          ]
-        : [expectedError(ParserErrorCode.FINAL_AND_COVARIANT, 6, 9)]);
-  }
-
-  void test_finalAndVar() {
-    createParser('final var x = null;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([expectedError(ParserErrorCode.FINAL_AND_VAR, 6, 3)]);
-  }
-
-  void test_finalClass() {
-    parseCompilationUnit("final class C {}",
-        errors: [expectedError(ParserErrorCode.FINAL_CLASS, 0, 5)]);
-  }
-
-  void test_finalClassMember_modifierOnly() {
-    createParser('final');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 0),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 0)
-    ]);
-  }
-
-  void test_finalConstructor() {
-    createParser('final C() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 5)]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.FINAL_CONSTRUCTOR]);
-    }
-  }
-
-  void test_finalEnum() {
-    parseCompilationUnit("final enum E {ONE}",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `final` as a malformed top level final
-                // and `enum` as the start of a enum declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 4),
-              ]
-            : [expectedError(ParserErrorCode.FINAL_ENUM, 0, 5)]);
-  }
-
-  void test_finalMethod() {
-    createParser('final int m() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 5)]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.FINAL_METHOD]);
-    }
-  }
-
-  void test_finalTypedef() {
-    parseCompilationUnit("final typedef F();",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `final` as a malformed top level final
-                // and `typedef` as the start of an typedef declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 7),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 7),
-              ]
-            : [expectedError(ParserErrorCode.FINAL_TYPEDEF, 0, 5)]);
-  }
-
-  void test_functionTypedField_invalidType_abstract() {
-    if (usingFastaParser) {
-      parseCompilationUnit("Function(abstract) x = null;", errors: [
-        expectedError(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 9, 8)
-      ]);
-    }
-  }
-
-  void test_functionTypedField_invalidType_class() {
-    if (usingFastaParser) {
-      parseCompilationUnit("Function(class) x = null;",
-          errors: usingFastaParser
-              ? [
-                  expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5),
-                  expectedError(
-                      ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 9, 5)
-                ]
-              : [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5)]);
-    }
-  }
-
-  void test_functionTypedParameter_const() {
-    parseCompilationUnit("void f(const x()) {}",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 5),
-                expectedError(
-                    ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
-              ]
-            : [
-                expectedError(
-                    ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
-              ]);
-  }
-
-  void test_functionTypedParameter_final() {
-    parseCompilationUnit("void f(final x()) {}", errors: [
-      expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
-    ]);
-  }
-
-  void test_functionTypedParameter_incomplete1() {
-    parseCompilationUnit("void f(int Function(",
-        errors: usingFastaParser
-            ? [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
-              ]
-            : [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 0),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 0),
-              ]);
-  }
-
-  void test_functionTypedParameter_var() {
-    parseCompilationUnit("void f(var x()) {}", errors: [
-      expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 3)
-    ]);
-  }
-
-  void test_genericFunctionType_asIdentifier() {
-    createParser('final int Function = 0;');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    listener.assertErrors([]);
-  }
-
-  void test_genericFunctionType_asIdentifier2() {
-    if (usingFastaParser) {
-      createParser('int Function() {}');
-      CompilationUnit unit = parser.parseCompilationUnit2();
-      expectNotNullIfNoErrors(unit);
-      listener.assertErrors([]);
-    }
-  }
-
-  void test_genericFunctionType_asIdentifier3() {
-    if (usingFastaParser) {
-      createParser('int Function() => 0;');
-      CompilationUnit unit = parser.parseCompilationUnit2();
-      expectNotNullIfNoErrors(unit);
-      listener.assertErrors([]);
-    }
-  }
-
-  void test_genericFunctionType_extraLessThan() {
-    createParser('''
-class Wrong<T> {
-  T Function(<List<int> foo) bar;
-}''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 30, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 1)
-          ]
-        : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 30, 1)]);
-  }
-
-  void test_getterInFunction_block_noReturnType() {
-    Statement result =
-        parseStatement("get x { return _x; }", expectedEndOffset: 4);
-    if (usingFastaParser) {
-      // Fasta considers `get` to be an identifier in this situation.
-      // TODO(danrubel): Investigate better recovery.
-      ExpressionStatement statement = result;
-      listener
-          .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
-      expect(statement.expression.toSource(), 'get');
-    } else {
-      FunctionDeclarationStatement statement = result;
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 0, 3)]);
-      expect(
-          statement.functionDeclaration.functionExpression.parameters, isNull);
-    }
-  }
-
-  void test_getterInFunction_block_returnType() {
-    // Fasta considers `get` to be an identifier in this situation.
-    parseStatement("int get x { return _x; }", expectedEndOffset: 8);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]
-        : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 4, 3)]);
-  }
-
-  void test_getterInFunction_expression_noReturnType() {
-    // Fasta considers `get` to be an identifier in this situation.
-    parseStatement("get x => _x;", expectedEndOffset: 4);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]
-        : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 0, 3)]);
-  }
-
-  void test_getterInFunction_expression_returnType() {
-    // Fasta considers `get` to be an identifier in this situation.
-    parseStatement("int get x => _x;", expectedEndOffset: 8);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]
-        : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 4, 3)]);
-  }
-
-  void test_getterWithParameters() {
-    createParser('int get x() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-    listener.assertErrorsWithCodes([ParserErrorCode.GETTER_WITH_PARAMETERS]);
-//    listener.assertErrors(
-//        [expectedError(ParserErrorCode.GETTER_WITH_PARAMETERS, 9, 2)]);
-  }
-
-  void test_illegalAssignmentToNonAssignable_assign_int() {
-    parseStatement("0 = 1;");
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 1),
-            expectedError(
-                ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 1),
-          ]
-        : [
-            expectedError(
-                ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 4, 1)
-          ]);
-  }
-
-  void test_illegalAssignmentToNonAssignable_assign_this() {
-    parseStatement("this = 1;");
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 4),
-            expectedError(
-                ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 4)
-          ]
-        : [
-            expectedError(
-                ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 7, 1)
-          ]);
-  }
-
-  void test_illegalAssignmentToNonAssignable_postfix_minusMinus_literal() {
-    parseExpression("0--", errors: [
-      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 1, 2)
-    ]);
-  }
-
-  void test_illegalAssignmentToNonAssignable_postfix_plusPlus_literal() {
-    parseExpression("0++", errors: [
-      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 1, 2)
-    ]);
-  }
-
-  void test_illegalAssignmentToNonAssignable_postfix_plusPlus_parenthesized() {
-    parseExpression("(x)++", errors: [
-      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 3, 2)
-    ]);
-  }
-
-  void test_illegalAssignmentToNonAssignable_primarySelectorPostfix() {
-    parseExpression("x(y)(z)++", errors: [
-      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 7, 2)
-    ]);
-  }
-
-  void test_illegalAssignmentToNonAssignable_superAssigned() {
-    parseStatement("super = x;");
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 0, 5),
-      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 0, 5)
-    ]);
-  }
-
-  void test_implementsBeforeExtends() {
-    parseCompilationUnit("class A implements B extends C {}", errors: [
-      expectedError(ParserErrorCode.IMPLEMENTS_BEFORE_EXTENDS, 21, 7)
-    ]);
-  }
-
-  void test_implementsBeforeWith() {
-    parseCompilationUnit("class A extends B implements C with D {}",
-        errors: [expectedError(ParserErrorCode.IMPLEMENTS_BEFORE_WITH, 31, 4)]);
-  }
-
-  void test_importDirectiveAfterPartDirective() {
-    parseCompilationUnit("part 'a.dart'; import 'b.dart';", errors: [
-      expectedError(
-          ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE, 15, 6)
-    ]);
-  }
-
-  void test_initializedVariableInForEach() {
-    Statement statement = parseStatement('for (int a = 0 in foo) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 11, 1)
-    ]);
-  }
-
-  void test_initializedVariableInForEach_annotation() {
-    Statement statement = parseStatement('for (@Foo var a = 0 in foo) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 16, 1)
-    ]);
-  }
-
-  void test_initializedVariableInForEach_localFunction() {
-    Statement statement = parseStatement('for (f()) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
-          ]);
-  }
-
-  void test_initializedVariableInForEach_localFunction2() {
-    Statement statement = parseStatement('for (T f()) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)
-          ]);
-  }
-
-  void test_initializedVariableInForEach_var() {
-    Statement statement = parseStatement('for (var a = 0 in foo) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 11, 1)
-    ]);
-  }
-
-  void test_invalidAwaitInFor() {
-    Statement statement = parseStatement('await for (; ;) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_AWAIT_IN_FOR, 0, 5)]);
-  }
-
-  void test_invalidCodePoint() {
-    StringLiteral literal = parseExpression("'begin \\u{110000}'",
-        errors: [expectedError(ParserErrorCode.INVALID_CODE_POINT, 7, 9)]);
-    expectNotNullIfNoErrors(literal);
-  }
-
-  @failingTest
-  void test_invalidCommentReference__new_nonIdentifier() {
-    // This test fails because the method parseCommentReference returns null.
-    createParser('');
-    CommentReference reference = parseCommentReference('new 42', 0);
-    expectNotNullIfNoErrors(reference);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 6)]);
-  }
-
-  @failingTest
-  void test_invalidCommentReference__new_tooMuch() {
-    createParser('');
-    CommentReference reference = parseCommentReference('new a.b.c.d', 0);
-    expectNotNullIfNoErrors(reference);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 11)]);
-  }
-
-  @failingTest
-  void test_invalidCommentReference__nonNew_nonIdentifier() {
-    // This test fails because the method parseCommentReference returns null.
-    createParser('');
-    CommentReference reference = parseCommentReference('42', 0);
-    expectNotNullIfNoErrors(reference);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 2)]);
-  }
-
-  @failingTest
-  void test_invalidCommentReference__nonNew_tooMuch() {
-    createParser('');
-    CommentReference reference = parseCommentReference('a.b.c.d', 0);
-    expectNotNullIfNoErrors(reference);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_COMMENT_REFERENCE, 0, 7)]);
-  }
-
-  void test_invalidConstructorName_star() {
-    createParser("C.*();");
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1),
-            expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 2, 1)
-          ]);
-  }
-
-  void test_invalidConstructorName_with() {
-    createParser("C.with();");
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      usingFastaParser
-          ? expectedError(
-              ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 2, 4)
-          : expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 0, 1)
-    ]);
-  }
-
-  void test_invalidConstructorSuperAssignment() {
-    createParser("C() : super = 42;");
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 6, 5)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 1),
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 16, 2),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 16, 2),
-            expectedError(
-                ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, 16, 0),
-          ]);
-  }
-
-  void test_invalidConstructorSuperFieldAssignment() {
-    createParser("C() : super.a = 42;");
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                ParserErrorCode.FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS,
-                12,
-                1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 1),
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 16, 2),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 16, 2),
-            expectedError(
-                ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, 16, 0),
-          ]);
-  }
-
-  void test_invalidHexEscape_invalidDigit() {
-    StringLiteral literal = parseExpression("'not \\x0 a'",
-        errors: [expectedError(ParserErrorCode.INVALID_HEX_ESCAPE, 5, 3)]);
-    expectNotNullIfNoErrors(literal);
-  }
-
-  void test_invalidHexEscape_tooFewDigits() {
-    StringLiteral literal = parseExpression("'\\x0'",
-        errors: [expectedError(ParserErrorCode.INVALID_HEX_ESCAPE, 1, 3)]);
-    expectNotNullIfNoErrors(literal);
-  }
-
-  void test_invalidInlineFunctionType() {
-    parseCompilationUnit(
-      'typedef F = int Function(int a());',
-      errors: usingFastaParser
-          ? [
-              expectedError(
-                  CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 30, 1)
-            ]
-          : [],
-    );
-  }
-
-  void test_invalidInterpolation_missingClosingBrace_issue35900() {
-    parseCompilationUnit(r"main () { print('${x' '); }",
-        errors: usingFastaParser
-            ? [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
-                expectedError(
-                    ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 26, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 3),
-                expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 27, 0),
-              ]
-            : [
-                expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
-                expectedError(
-                    ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 26, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 3),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 23, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 1),
-              ]);
-  }
-
-  void test_invalidInterpolationIdentifier_startWithDigit() {
-    StringLiteral literal = parseExpression("'\$1'",
-        errors: [expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 2, 1)]);
-    expectNotNullIfNoErrors(literal);
-  }
-
-  void test_invalidLiteralInConfiguration() {
-    createParser("if (a == 'x \$y z') 'a.dart'");
-    Configuration configuration = parser.parseConfiguration();
-    expectNotNullIfNoErrors(configuration);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, 12, 2)
-    ]);
-  }
-
-  void test_invalidOperator() {
-    CompilationUnit unit =
-        parseCompilationUnit('class C { void operator ===(x) { } }',
-            errors: usingFastaParser
-                ? [expectedError(ScannerErrorCode.UNSUPPORTED_OPERATOR, 24, 1)]
-                : [
-                    expectedError(ScannerErrorCode.UNSUPPORTED_OPERATOR, 24, 1),
-                    expectedError(ParserErrorCode.INVALID_OPERATOR, 24, 3)
-                  ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_invalidOperator_unary() {
-    createParser('class C { int operator unary- => 0; }');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 23, 5),
-            expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 28, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 8),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 28, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 28, 1),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 30, 2),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 30, 2),
-            expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 33, 1),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 33, 1),
-            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 34, 1)
-          ]);
-  }
-
-  void test_invalidOperatorAfterSuper_assignableExpression() {
-    Expression expression = parseAssignableExpression('super?.v', false);
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
-              : ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
-          5,
-          2)
-    ]);
-  }
-
-  void test_invalidOperatorAfterSuper_primaryExpression() {
-    Expression expression = parseExpression('super?.v', errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
-              : ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
-          5,
-          2)
-    ]);
-    expectNotNullIfNoErrors(expression);
-  }
-
-  void test_invalidOperatorForSuper() {
-    createParser('++super');
-    Expression expression = parser.parseUnaryExpression();
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors([
-      usingFastaParser
-          ? expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 2, 5)
-          : expectedError(ParserErrorCode.INVALID_OPERATOR_FOR_SUPER, 0, 2)
-    ]);
-  }
-
-  void test_invalidPropertyAccess_this() {
-    parseExpression('x.this',
-        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 4)]);
-  }
-
-  void test_invalidStarAfterAsync() {
-    createParser('foo() async* => 0;');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(CompileTimeErrorCode.RETURN_IN_GENERATOR, 13, 2)]
-        : [expectedError(ParserErrorCode.INVALID_STAR_AFTER_ASYNC, 11, 1)]);
-  }
-
-  void test_invalidSync() {
-    createParser('foo() sync* => 0;');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(CompileTimeErrorCode.RETURN_IN_GENERATOR, 12, 2)]
-        : [expectedError(ParserErrorCode.INVALID_SYNC, 0, 4)]);
-  }
-
-  void test_invalidTopLevelSetter() {
-    parseCompilationUnit("var set foo; main(){}", errors: [
-      expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3),
-      usingFastaParser
-          ? expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 8, 3)
-          : expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 11, 1),
-      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 11, 1)
-    ]);
-  }
-
-  void test_invalidTopLevelVar() {
-    parseCompilationUnit("var Function(var arg);",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 21, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 21, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 21, 2),
-              ]);
-  }
-
-  void test_invalidTypedef() {
-    parseCompilationUnit("typedef var Function(var arg);",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
-                expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 8, 3),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 3),
-                expectedError(ParserErrorCode.VAR_RETURN_TYPE, 8, 3),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 29, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 3),
-                expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 8, 3),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 29, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 2),
-              ]);
-  }
-
-  void test_invalidTypedef2() {
-    // https://github.com/dart-lang/sdk/issues/31171
-    parseCompilationUnit(
-        "typedef T = typedef F = Map<String, dynamic> Function();",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 7),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 7),
-                expectedError(
-                    ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 10, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 7),
-                expectedError(
-                    ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 20, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 20, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 36, 7),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 43, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 43, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 55, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 55, 1),
-              ]);
-  }
-
-  void test_invalidUnicodeEscape_incomplete_noDigits() {
-    Expression expression = parseStringLiteral("'\\u{'");
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 3)]);
-  }
-
-  void test_invalidUnicodeEscape_incomplete_someDigits() {
-    Expression expression = parseStringLiteral("'\\u{0A'");
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 5)]);
-  }
-
-  void test_invalidUnicodeEscape_invalidDigit() {
-    Expression expression = parseStringLiteral("'\\u0 and some more'");
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 3)]);
-  }
-
-  void test_invalidUnicodeEscape_tooFewDigits_fixed() {
-    Expression expression = parseStringLiteral("'\\u04'");
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 4)]);
-  }
-
-  void test_invalidUnicodeEscape_tooFewDigits_variable() {
-    Expression expression = parseStringLiteral("'\\u{}'");
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 4)]);
-  }
-
-  void test_invalidUnicodeEscape_tooManyDigits_variable() {
-    Expression expression = parseStringLiteral("'\\u{12345678}'");
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.INVALID_CODE_POINT, 1, 9)]
-        : [
-            expectedError(ParserErrorCode.INVALID_UNICODE_ESCAPE, 1, 12),
-            expectedError(ParserErrorCode.INVALID_CODE_POINT, 1, 12)
-          ]);
-  }
-
-  void test_libraryDirectiveNotFirst() {
-    parseCompilationUnit("import 'x.dart'; library l;", errors: [
-      expectedError(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 17, 7)
-    ]);
-  }
-
-  void test_libraryDirectiveNotFirst_afterPart() {
-    CompilationUnit unit = parseCompilationUnit("part 'a.dart';\nlibrary l;",
-        errors: [
-          expectedError(ParserErrorCode.LIBRARY_DIRECTIVE_NOT_FIRST, 15, 7)
-        ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_localFunction_annotation() {
-    CompilationUnit unit =
-        parseCompilationUnit("class C { m() { @Foo f() {} } }");
-    expect(unit.declarations, hasLength(1));
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.members, hasLength(1));
-    MethodDeclaration member = declaration.members[0];
-    BlockFunctionBody body = member.body;
-    expect(body.block.statements, hasLength(1));
-    FunctionDeclarationStatement statement = body.block.statements[0];
-    if (usingFastaParser) {
-      expect(statement.functionDeclaration.metadata, hasLength(1));
-      Annotation metadata = statement.functionDeclaration.metadata[0];
-      expect(metadata.name.name, 'Foo');
-    }
-  }
-
-  void test_localFunctionDeclarationModifier_abstract() {
-    parseCompilationUnit("class C { m() { abstract f() {} } }",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]
-            : [
-                expectedError(
-                    ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 8)
-              ]);
-  }
-
-  void test_localFunctionDeclarationModifier_external() {
-    parseCompilationUnit("class C { m() { external f() {} } }",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]
-            : [
-                expectedError(
-                    ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 8)
-              ]);
-  }
-
-  void test_localFunctionDeclarationModifier_factory() {
-    parseCompilationUnit("class C { m() { factory f() {} } }",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 7)]
-            : [
-                expectedError(
-                    ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 7)
-              ]);
-  }
-
-  void test_localFunctionDeclarationModifier_static() {
-    parseCompilationUnit("class C { m() { static f() {} } }",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 6)]
-            : [
-                expectedError(
-                    ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 6)
-              ]);
-  }
-
-  void test_method_invalidTypeParameterExtends() {
-    // Regression test for https://github.com/dart-lang/sdk/issues/25739.
-
-    // TODO(jmesserly): ideally we'd be better at parser recovery here.
-    createParser('f<E>(E extends num p);');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 7)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0,
-                0), // `extends` is a keyword
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0), // comma
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0), // close paren
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 0)
-          ]);
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(
-        method.parameters.toString(), usingFastaParser ? '(E)' : '(E, extends)',
-        reason: 'parser recovers what it can');
-  }
-
-  void test_method_invalidTypeParameters() {
-    createParser('void m<E, hello!>() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 5)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0) /*>*/,
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 0),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0) /*(*/,
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0) /*)*/,
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 0)
-          ]);
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.typeParameters.toString(), '<E, hello>',
-        reason: 'parser recovers what it can');
-  }
-
-  void test_missingAssignableSelector_identifiersAssigned() {
-    parseExpression("x.y = y;", expectedEndOffset: 7);
-  }
-
-  void test_missingAssignableSelector_prefix_minusMinus_literal() {
-    parseExpression("--0", errors: [
-      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 2, 1)
-    ]);
-  }
-
-  void test_missingAssignableSelector_prefix_plusPlus_literal() {
-    parseExpression("++0", errors: [
-      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 2, 1)
-    ]);
-  }
-
-  void test_missingAssignableSelector_selector() {
-    parseExpression("x(y)(z).a++");
-  }
-
-  void test_missingAssignableSelector_superPrimaryExpression() {
-    CompilationUnit unit = parseCompilationUnit('main() {super;}', errors: [
-      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 8, 5)
-    ]);
-    FunctionDeclaration declaration = unit.declarations.first;
-    BlockFunctionBody blockBody = declaration.functionExpression.body;
-    ExpressionStatement statement = blockBody.block.statements.first;
-    Expression expression = statement.expression;
-    expect(expression, isSuperExpression);
-    SuperExpression superExpression = expression;
-    expect(superExpression.superKeyword, isNotNull);
-  }
-
-  void test_missingAssignableSelector_superPropertyAccessAssigned() {
-    parseExpression("super.x = x;", expectedEndOffset: 11);
-  }
-
-  void test_missingCatchOrFinally() {
-    TryStatement statement = parseStatement('try {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_CATCH_OR_FINALLY, 0, 3)]);
-    expect(statement, isNotNull);
-  }
-
-  void test_missingClosingParenthesis() {
-    createParser('(int a, int b ;',
-        expectedEndOffset: 14 /* parsing ends at synthetic ')' */);
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.errors
-        .contains(expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 1));
-  }
-
-  void test_missingConstFinalVarOrType_static() {
-    parseCompilationUnit("class A { static f; }", errors: [
-      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 17, 1)
-    ]);
-  }
-
-  void test_missingConstFinalVarOrType_topLevel() {
-    parseCompilationUnit('a;', errors: [
-      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 1)
-    ]);
-  }
-
-  void test_missingEnumBody() {
-    createParser('enum E;', expectedEndOffset: 6);
-    EnumDeclaration declaration = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(declaration);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.MISSING_ENUM_BODY, 6, 1)]);
-  }
-
-  void test_missingEnumComma() {
-    createParser('enum E {one two}');
-    EnumDeclaration declaration = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(declaration);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 3)]);
-  }
-
-  void test_missingExpressionInThrow() {
-    ThrowExpression expression =
-        (parseStatement('throw;') as ExpressionStatement).expression;
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_EXPRESSION_IN_THROW, 5, 1)]);
-  }
-
-  void test_missingFunctionBody_emptyNotAllowed() {
-    createParser(';');
-    FunctionBody functionBody = parser.parseFunctionBody(
-        false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
-    expectNotNullIfNoErrors(functionBody);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 1)]);
-  }
-
-  void test_missingFunctionBody_invalid() {
-    createParser('return 0;');
-    FunctionBody functionBody = parser.parseFunctionBody(
-        false, ParserErrorCode.MISSING_FUNCTION_BODY, false);
-    expectNotNullIfNoErrors(functionBody);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 6)]);
-  }
-
-  void test_missingFunctionParameters_local_nonVoid_block() {
-    // The parser does not recognize this as a function declaration, so it tries
-    // to parse it as an expression statement. It isn't clear what the best
-    // error message is in this case.
-    parseStatement("int f { return x;}", expectedEndOffset: 6);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]);
-  }
-
-  void test_missingFunctionParameters_local_nonVoid_expression() {
-    // The parser does not recognize this as a function declaration, so it tries
-    // to parse it as an expression statement. It isn't clear what the best
-    // error message is in this case.
-    parseStatement("int f => x;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 6, 2)]
-        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
-  }
-
-  void test_missingFunctionParameters_local_void_block() {
-    parseStatement("void f { return x;}", expectedEndOffset: 7);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
-        : [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
-  }
-
-  void test_missingFunctionParameters_local_void_expression() {
-    parseStatement("void f => x;");
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 7, 2)]);
-  }
-
-  void test_missingFunctionParameters_topLevel_nonVoid_block() {
-    parseCompilationUnit("int f { return x;}", errors: [
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)
-    ]);
-  }
-
-  void test_missingFunctionParameters_topLevel_nonVoid_expression() {
-    parseCompilationUnit("int f => x;", errors: [
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)
-    ]);
-  }
-
-  void test_missingFunctionParameters_topLevel_void_block() {
-    CompilationUnit unit = parseCompilationUnit("void f { return x;}", errors: [
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)
-    ]);
-    FunctionDeclaration funct = unit.declarations[0];
-    expect(funct.functionExpression.parameters, hasLength(0));
-  }
-
-  void test_missingFunctionParameters_topLevel_void_expression() {
-    CompilationUnit unit = parseCompilationUnit("void f => x;", errors: [
-      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)
-    ]);
-    FunctionDeclaration funct = unit.declarations[0];
-    expect(funct.functionExpression.parameters, hasLength(0));
-  }
-
-  void test_missingIdentifier_afterOperator() {
-    createParser('1 *');
-    BinaryExpression expression = parser.parseMultiplicativeExpression();
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 0)]);
-  }
-
-  void test_missingIdentifier_beforeClosingCurly() {
-    createParser('int}', expectedEndOffset: 3);
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 3),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)
-          ]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)
-          ]);
-  }
-
-  void test_missingIdentifier_inEnum() {
-    createParser('enum E {, TWO}');
-    EnumDeclaration declaration = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(declaration);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]);
-  }
-
-  void test_missingIdentifier_inParameterGroupNamed() {
-    createParser('(a, {})');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]);
-  }
-
-  void test_missingIdentifier_inParameterGroupOptional() {
-    createParser('(a, [])');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    if (usingFastaParser) {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]);
-    } else {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1),
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)
-      ]);
-    }
-  }
-
-  void test_missingIdentifier_inSymbol_afterPeriod() {
-    SymbolLiteral literal = parseSymbolLiteral('#a.');
-    expectNotNullIfNoErrors(literal);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1)]);
-  }
-
-  void test_missingIdentifier_inSymbol_first() {
-    SymbolLiteral literal = parseSymbolLiteral('#');
-    expectNotNullIfNoErrors(literal);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 1, 1)]);
-  }
-
-  void test_missingIdentifierForParameterGroup() {
-    createParser('(,)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 1, 1)]);
-  }
-
-  void test_missingKeywordOperator() {
-    createParser('+(x) {}');
-    MethodDeclaration method = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(method);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 0, 1)]);
-  }
-
-  void test_missingKeywordOperator_parseClassMember() {
-    createParser('+() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 0, 1)]);
-  }
-
-  void test_missingKeywordOperator_parseClassMember_afterTypeName() {
-    createParser('int +() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 4, 1)]);
-  }
-
-  void test_missingKeywordOperator_parseClassMember_afterVoid() {
-    createParser('void +() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 5, 1)]);
-  }
-
-  void test_missingMethodParameters_void_block() {
-    createParser('void m {} }', expectedEndOffset: 10);
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS,
-          usingFastaParser ? 5 : 7, 1)
-    ]);
-    expect(member, isMethodDeclaration);
-    MethodDeclaration method = member;
-    expect(method.parameters, hasLength(0));
-  }
-
-  void test_missingMethodParameters_void_expression() {
-    createParser('void m => null; }', expectedEndOffset: 16);
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS,
-          usingFastaParser ? 5 : 7, 1)
-    ]);
-  }
-
-  void test_missingNameForNamedParameter_colon() {
-    createParser('({int : 0})');
-    FormalParameter parameter =
-        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
-    expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
-            expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1),
-            expectedError(
-                ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER, 7, 1)
-          ]);
-    expect(parameter.identifier, isNotNull);
-  }
-
-  void test_missingNameForNamedParameter_equals() {
-    createParser('({int = 0})');
-    FormalParameter parameter =
-        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
-    expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
-            expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1)
-          ]
-        : [
-            expectedError(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 8, 1),
-            expectedError(
-                ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER, 7, 1)
-          ]);
-    expect(parameter.identifier, isNotNull);
-  }
-
-  void test_missingNameForNamedParameter_noDefault() {
-    createParser('({int})');
-    FormalParameter parameter =
-        parser.parseFormalParameterList(inFunctionType: true).parameters[0];
-    expectNotNullIfNoErrors(parameter);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 1)]
-        : [
-            expectedError(
-                ParserErrorCode.MISSING_NAME_FOR_NAMED_PARAMETER, 5, 1)
-          ]);
-    expect(parameter.identifier, isNotNull);
-  }
-
-  void test_missingNameInLibraryDirective() {
-    CompilationUnit unit = parseCompilationUnit("library;", errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.MISSING_IDENTIFIER
-              : ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE,
-          7,
-          1)
-    ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_missingNameInPartOfDirective() {
-    CompilationUnit unit = parseCompilationUnit("part of;", errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_STRING_LITERAL
-              : ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE,
-          7,
-          1)
-    ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_missingPrefixInDeferredImport() {
-    parseCompilationUnit("import 'foo.dart' deferred;", errors: [
-      expectedError(ParserErrorCode.MISSING_PREFIX_IN_DEFERRED_IMPORT, 18, 8)
-    ]);
-  }
-
-  void test_missingStartAfterSync() {
-    createParser('sync {}');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_STAR_AFTER_SYNC, 0, 4)]);
-  }
-
-  void test_missingStatement() {
-    parseStatement("is");
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 2),
-            expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 2, 0),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 0)
-          ]
-        : [expectedError(ParserErrorCode.MISSING_STATEMENT, 2, 0)]);
-  }
-
-  void test_missingStatement_afterVoid() {
-    parseStatement("void;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]
-        : [expectedError(ParserErrorCode.MISSING_STATEMENT, 4, 1)]);
-  }
-
-  void test_missingTerminatorForParameterGroup_named() {
-    createParser('(a, {b: 0)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener
-        .assertErrors([expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1)]);
-  }
-
-  void test_missingTerminatorForParameterGroup_optional() {
-    createParser('(a, [b = 0)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener
-        .assertErrors([expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)]);
-  }
-
-  void test_missingTypedefParameters_nonVoid() {
-    parseCompilationUnit("typedef int F;", errors: [
-      expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 13, 1)
-    ]);
-  }
-
-  void test_missingTypedefParameters_typeParameters() {
-    parseCompilationUnit("typedef F<E>;", errors: [
-      expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 12, 1)
-    ]);
-  }
-
-  void test_missingTypedefParameters_void() {
-    parseCompilationUnit("typedef void F;", errors: [
-      expectedError(ParserErrorCode.MISSING_TYPEDEF_PARAMETERS, 14, 1)
-    ]);
-  }
-
-  void test_missingVariableInForEach() {
-    Statement statement = parseStatement('for (a < b in foo) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 1)]
-        : [expectedError(ParserErrorCode.MISSING_VARIABLE_IN_FOR_EACH, 5, 5)]);
-  }
-
-  void test_mixedParameterGroups_namedPositional() {
-    createParser('(a, {b}, [c])');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
-        : [expectedError(ParserErrorCode.MIXED_PARAMETER_GROUPS, 9, 3)]);
-  }
-
-  void test_mixedParameterGroups_positionalNamed() {
-    createParser('(a, [b], {c})');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
-        : [expectedError(ParserErrorCode.MIXED_PARAMETER_GROUPS, 9, 3)]);
-  }
-
-  void test_mixin_application_lacks_with_clause() {
-    parseCompilationUnit("class Foo = Bar;",
-        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1)]);
-  }
-
-  void test_multipleExtendsClauses() {
-    parseCompilationUnit("class A extends B extends C {}", errors: [
-      expectedError(ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES, 18, 7)
-    ]);
-  }
-
-  void test_multipleImplementsClauses() {
-    parseCompilationUnit("class A implements B implements C {}", errors: [
-      expectedError(ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES, 21, 10)
-    ]);
-  }
-
-  void test_multipleLibraryDirectives() {
-    parseCompilationUnit("library l; library m;", errors: [
-      expectedError(ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES, 11, 7)
-    ]);
-  }
-
-  void test_multipleNamedParameterGroups() {
-    createParser('(a, {b}, {c})');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
-        : [
-            expectedError(ParserErrorCode.MULTIPLE_NAMED_PARAMETER_GROUPS, 9, 3)
-          ]);
-  }
-
-  void test_multiplePartOfDirectives() {
-    parseCompilationUnit("part of l; part of m;", errors: [
-      expectedError(ParserErrorCode.MULTIPLE_PART_OF_DIRECTIVES, 11, 4)
-    ]);
-  }
-
-  void test_multiplePositionalParameterGroups() {
-    createParser('(a, [b], [c])');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
-        : [
-            expectedError(
-                ParserErrorCode.MULTIPLE_POSITIONAL_PARAMETER_GROUPS, 9, 3)
-          ]);
-  }
-
-  void test_multipleVariablesInForEach() {
-    Statement statement = parseStatement('for (int a, b in foo) {}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 10, 1)]
-        : [
-            expectedError(ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH, 12, 1)
-          ]);
-  }
-
-  void test_multipleWithClauses() {
-    parseCompilationUnit("class A extends B with C with D {}",
-        errors: [expectedError(ParserErrorCode.MULTIPLE_WITH_CLAUSES, 25, 4)]);
-  }
-
-  void test_namedFunctionExpression() {
-    Expression expression;
-    if (usingFastaParser) {
-      createParser('f() {}');
-      expression = parser.parsePrimaryExpression();
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, 0, 1)]);
-      expect(expression, isFunctionExpression);
-    } else {
-      expression = parsePrimaryExpression('f() {}');
-      expectNotNullIfNoErrors(expression);
-      // Should generate an error.
-      //listener.assertErrors(
-      //    [expectedError(ParserErrorCode.NAMED_FUNCTION_EXPRESSION, 0, 1)]);
-      //expect(expression, isFunctionExpression);
-    }
-  }
-
-  void test_namedParameterOutsideGroup() {
-    createParser('(a, b : 0)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 6, 1)]);
-    expect(list.parameters[0].isRequired, isTrue);
-    expect(list.parameters[1].isNamed, isTrue);
-  }
-
-  void test_nonConstructorFactory_field() {
-    createParser('factory int x;', expectedEndOffset: 12);
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 12, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)
-          ]
-        : [expectedError(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, 0, 7)]);
-  }
-
-  void test_nonConstructorFactory_method() {
-    createParser('factory int m() {}', expectedEndOffset: 12);
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 12, 1),
-            expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 12, 1)
-          ]
-        : [expectedError(ParserErrorCode.NON_CONSTRUCTOR_FACTORY, 0, 7)]);
-  }
-
-  void test_nonIdentifierLibraryName_library() {
-    CompilationUnit unit = parseCompilationUnit("library 'lib';", errors: [
-      usingFastaParser
-          ? expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 5)
-          : expectedError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, 8, 5)
-    ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_nonIdentifierLibraryName_partOf() {
-    CompilationUnit unit = parseCompilationUnit("part of 3;",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 8, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 1)
-              ]
-            : [
-                expectedError(
-                    ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE, 8, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 8, 1)
-              ]);
-    expect(unit, isNotNull);
-  }
-
-  void test_nonPartOfDirectiveInPart_after() {
-    parseCompilationUnit("part of l; part 'f.dart';", errors: [
-      expectedError(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, 11, 4)
-    ]);
-  }
-
-  void test_nonPartOfDirectiveInPart_before() {
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    parseCompilationUnit("part 'f.dart'; part of m;", codes: [
-      ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART
-    ], errors: [
-      expectedError(ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART, 0, 4)
-    ]);
-  }
-
-  void test_nonUserDefinableOperator() {
-    createParser('operator +=(int x) => x + 1;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.INVALID_OPERATOR
-              : ParserErrorCode.NON_USER_DEFINABLE_OPERATOR,
-          9,
-          2)
-    ]);
-  }
-
-  void test_optionalAfterNormalParameters_named() {
-    parseCompilationUnit("f({a}, b) {}",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
-            : [
-                expectedError(
-                    ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, 7, 1)
-              ]);
-  }
-
-  void test_optionalAfterNormalParameters_positional() {
-    parseCompilationUnit("f([a], b) {}",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
-            : [
-                expectedError(
-                    ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS, 7, 1)
-              ]);
-  }
-
-  void test_parseCascadeSection_missingIdentifier() {
-    MethodInvocation methodInvocation = parseCascadeSection('..()');
-    expectNotNullIfNoErrors(methodInvocation);
-    listener.assertErrors([
-      // Cascade section is preceded by `null` in this test
-      // and error is reported on '('.
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1)
-    ]);
-    expect(methodInvocation.target, isNull);
-    expect(methodInvocation.methodName.name, "");
-    expect(methodInvocation.typeArguments, isNull);
-    expect(methodInvocation.argumentList.arguments, hasLength(0));
-  }
-
-  void test_parseCascadeSection_missingIdentifier_typeArguments() {
-    MethodInvocation methodInvocation = parseCascadeSection('..<E>()');
-    expectNotNullIfNoErrors(methodInvocation);
-    listener.assertErrors([
-      // Cascade section is preceded by `null` in this test
-      // and error is reported on '<'.
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1)
-    ]);
-    expect(methodInvocation.target, isNull);
-    expect(methodInvocation.methodName.name, "");
-    expect(methodInvocation.typeArguments, isNotNull);
-    expect(methodInvocation.argumentList.arguments, hasLength(0));
-  }
-
-  void test_positionalAfterNamedArgument() {
-    createParser('(x: 1, 2)');
-    ArgumentList list = parser.parseArgumentList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT, 7, 1)]);
-  }
-
-  void test_positionalParameterOutsideGroup() {
-    createParser('(a, b = 0)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 6, 1)]
-        : [
-            expectedError(
-                ParserErrorCode.POSITIONAL_PARAMETER_OUTSIDE_GROUP, 4, 1)
-          ]);
-    expect(list.parameters[0].isRequired, isTrue);
-    if (usingFastaParser) {
-      expect(list.parameters[1].isNamed, isTrue);
-    } else {
-      expect(list.parameters[1].isOptionalPositional, isTrue);
-    }
-  }
-
-  void test_redirectingConstructorWithBody_named() {
-    createParser('C.x() : this() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, 15,
-          usingFastaParser ? 1 : 2)
-    ]);
-  }
-
-  void test_redirectingConstructorWithBody_unnamed() {
-    createParser('C() : this.x() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY, 15,
-          usingFastaParser ? 1 : 2)
-    ]);
-  }
-
-  void test_redirectionInNonFactoryConstructor() {
-    createParser('C() = D;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR, 4, 1)
-    ]);
-  }
-
-  void test_setterInFunction_block() {
-    parseStatement("set x(v) {_x = v;}");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 3)]
-        : [expectedError(ParserErrorCode.SETTER_IN_FUNCTION, 0, 3)]);
-  }
-
-  void test_setterInFunction_expression() {
-    parseStatement("set x(v) => _x = v;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 3)]
-        : [expectedError(ParserErrorCode.SETTER_IN_FUNCTION, 0, 3)]);
-  }
-
-  void test_staticAfterConst() {
-    createParser('final static int f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 6)]);
-  }
-
-  void test_staticAfterFinal() {
-    createParser('const static int f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 6),
-        expectedError(CompileTimeErrorCode.CONST_NOT_INITIALIZED, 17, 1)
-      ]);
-    } else {
-      listener.assertErrorsWithCodes([ParserErrorCode.MODIFIER_OUT_OF_ORDER]);
-    }
-  }
-
-  void test_staticAfterVar() {
-    createParser('var static f;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 4, 6)]);
-  }
-
-  void test_staticConstructor() {
-    createParser('static C.m() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.STATIC_CONSTRUCTOR, 0, 6)]);
-  }
-
-  void test_staticGetterWithoutBody() {
-    createParser('static get m;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.MISSING_FUNCTION_BODY
-              : ParserErrorCode.STATIC_GETTER_WITHOUT_BODY,
-          12,
-          1)
-    ]);
-  }
-
-  void test_staticOperator_noReturnType() {
-    createParser('static operator +(int x) => x + 1;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.STATIC_OPERATOR, 0, 6)]);
-  }
-
-  void test_staticOperator_returnType() {
-    createParser('static int operator +(int x) => x + 1;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.STATIC_OPERATOR, 0, 6)]);
-  }
-
-  void test_staticSetterWithoutBody() {
-    createParser('static set m(x);');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.MISSING_FUNCTION_BODY
-              : ParserErrorCode.STATIC_SETTER_WITHOUT_BODY,
-          15,
-          1)
-    ]);
-  }
-
-  void test_staticTopLevelDeclaration_class() {
-    parseCompilationUnit("static class C {}", errors: [
-      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
-    ]);
-  }
-
-  void test_staticTopLevelDeclaration_enum() {
-    parseCompilationUnit("static enum E { v }", errors: [
-      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
-    ]);
-  }
-
-  void test_staticTopLevelDeclaration_function() {
-    parseCompilationUnit("static f() {}", errors: [
-      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
-    ]);
-  }
-
-  void test_staticTopLevelDeclaration_typedef() {
-    parseCompilationUnit("static typedef F();", errors: [
-      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
-    ]);
-  }
-
-  void test_staticTopLevelDeclaration_variable() {
-    parseCompilationUnit("static var x;", errors: [
-      expectedError(ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION, 0, 6)
-    ]);
-  }
-
-  void test_string_unterminated_interpolation_block() {
-    parseCompilationUnit(r'''
-m() {
- {
- '${${
-''',
-        codes: usingFastaParser
-            ? [
-                ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN
-              ]
-            : [
-                ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ScannerErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-              ]);
-  }
-
-  void test_switchCase_missingColon() {
-    SwitchStatement statement = parseStatement('switch (a) {case 1 return 0;}');
-    expect(statement, isNotNull);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 6)]);
-  }
-
-  void test_switchDefault_missingColon() {
-    SwitchStatement statement =
-        parseStatement('switch (a) {default return 0;}');
-    expect(statement, isNotNull);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 6)]);
-  }
-
-  void test_switchHasCaseAfterDefaultCase() {
-    SwitchStatement statement =
-        parseStatement('switch (a) {default: return 0; case 1: return 1;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, 31, 4)
-    ]);
-  }
-
-  void test_switchHasCaseAfterDefaultCase_repeated() {
-    SwitchStatement statement = parseStatement(
-        'switch (a) {default: return 0; case 1: return 1; case 2: return 2;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, 31, 4),
-      expectedError(ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE, 49, 4)
-    ]);
-  }
-
-  void test_switchHasMultipleDefaultCases() {
-    SwitchStatement statement =
-        parseStatement('switch (a) {default: return 0; default: return 1;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, 31, 7)
-    ]);
-  }
-
-  void test_switchHasMultipleDefaultCases_repeated() {
-    SwitchStatement statement = parseStatement(
-        'switch (a) {default: return 0; default: return 1; default: return 2;}');
-    expectNotNullIfNoErrors(statement);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, 31, 7),
-      expectedError(ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES, 50, 7)
-    ]);
-  }
-
-  void test_switchMissingBlock() {
-    SwitchStatement statement =
-        parseStatement('switch (a) return;', expectedEndOffset: 11);
-    expect(statement, isNotNull);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_BODY, 9, 1)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6),
-            expectedError(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, 11, 6),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6)
-          ]);
-  }
-
-  void test_topLevel_getter() {
-    createParser('get x => 7;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration function = member;
-    expect(function.functionExpression.parameters, isNull);
-  }
-
-  void test_topLevelFactory_withFunction() {
-    parseCompilationUnit('factory Function() x = null;', errors: [
-      expectedError(ParserErrorCode.FACTORY_TOP_LEVEL_DECLARATION, 0, 7)
-    ]);
-  }
-
-  void test_topLevelOperator_withFunction() {
-    parseCompilationUnit('operator Function() x = null;',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 8)]
-            : [
-                // Should be generating an error here.
-              ]);
-  }
-
-  void test_topLevelOperator_withoutOperator() {
-    createParser('+(bool x, bool y) => x | y;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 1)]
-        : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1)]);
-  }
-
-  void test_topLevelOperator_withoutType() {
-    parseCompilationUnit('operator +(bool x, bool y) => x | y;',
-        errors: [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 0, 8)]);
-  }
-
-  void test_topLevelOperator_withType() {
-    parseCompilationUnit('bool operator +(bool x, bool y) => x | y;',
-        errors: [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 5, 8)]);
-  }
-
-  void test_topLevelOperator_withVoid() {
-    parseCompilationUnit('void operator +(bool x, bool y) => x | y;',
-        errors: [expectedError(ParserErrorCode.TOP_LEVEL_OPERATOR, 5, 8)]);
-  }
-
-  void test_topLevelVariable_withMetadata() {
-    parseCompilationUnit("String @A string;",
-        codes: usingFastaParser
-            ? [
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-              ]
-            : [
-                ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-              ]);
-  }
-
-  void test_typedef_incomplete() {
-    // TODO(brianwilkerson) Improve recovery for this case.
-    parseCompilationUnit('''
-class A {}
-class B extends A {}
-
-typedef T
-
-main() {
-  Function<
-}
-''',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 49, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 51, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 51, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 51, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 55, 8)
-              ]);
-  }
-
-  void test_typedef_namedFunction() {
-    parseCompilationUnit('typedef void Function();',
-        codes: usingFastaParser
-            ? [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]
-            : [
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-                ParserErrorCode.MISSING_TYPEDEF_PARAMETERS
-              ]);
-  }
-
-  void test_typedefInClass_withoutReturnType() {
-    parseCompilationUnit("class C { typedef F(x); }",
-        errors: [expectedError(ParserErrorCode.TYPEDEF_IN_CLASS, 10, 7)]);
-  }
-
-  void test_typedefInClass_withReturnType() {
-    parseCompilationUnit("class C { typedef int F(int x); }",
-        errors: [expectedError(ParserErrorCode.TYPEDEF_IN_CLASS, 10, 7)]);
-  }
-
-  void test_unexpectedCommaThenInterpolation() {
-    // https://github.com/Dart-Code/Dart-Code/issues/1548
-    parseCompilationUnit(r"main() { String s = 'a' 'b', 'c$foo'; return s; }",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 29, 2),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 29, 2),
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 29, 2),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 29, 1),
-              ]);
-  }
-
-  void test_unexpectedTerminatorForParameterGroup_named() {
-    createParser('(a, b})');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_TOKEN
-              : ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
-          5,
-          1)
-    ]);
-  }
-
-  void test_unexpectedTerminatorForParameterGroup_optional() {
-    createParser('(a, b])');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
-        : [
-            expectedError(
-                ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP, 5, 1)
-          ]);
-  }
-
-  void test_unexpectedToken_endOfFieldDeclarationStatement() {
-    parseStatement("String s = (null));", expectedEndOffset: 17);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1)]
-        : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 17, 1)]);
-  }
-
-  void test_unexpectedToken_invalidPostfixExpression() {
-    parseExpression("f()++", errors: [
-      expectedError(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 3, 2)
-    ]);
-  }
-
-  void test_unexpectedToken_invalidPrefixExpression() {
-    parseExpression("++f()", errors: [
-      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 4, 1)
-    ]);
-  }
-
-  void test_unexpectedToken_returnInExpressionFunctionBody() {
-    parseCompilationUnit("f() => return null;",
-        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 6)]);
-  }
-
-  void test_unexpectedToken_semicolonBetweenClassMembers() {
-    createParser('class C { int x; ; int y;}');
-    ClassDeclaration declaration = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(declaration);
-    listener.assertErrors([
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_CLASS_MEMBER
-              : ParserErrorCode.UNEXPECTED_TOKEN,
-          17,
-          1)
-    ]);
-  }
-
-  void test_unexpectedToken_semicolonBetweenCompilationUnitMembers() {
-    parseCompilationUnit("int x; ; int y;",
-        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 1)]);
-  }
-
-  void test_unterminatedString_at_eof() {
-    // Although the "unterminated string" error message is produced by the
-    // scanner, we need to verify that the parser can handle the tokens
-    // produced by the scanner when an unterminated string is encountered.
-    parseCompilationUnit(r'''
-void main() {
-  var x = "''', errors: [
-      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 25, 1),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 24, 1)
-    ]);
-  }
-
-  void test_unterminatedString_at_eol() {
-    // Although the "unterminated string" error message is produced by the
-    // scanner, we need to verify that the parser can handle the tokens
-    // produced by the scanner when an unterminated string is encountered.
-    parseCompilationUnit(r'''
-void main() {
-  var x = "
-;
-}
-''', errors: [
-      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1)
-    ]);
-  }
-
-  void test_unterminatedString_multiline_at_eof_3_quotes() {
-    // Although the "unterminated string" error message is produced by the
-    // scanner, we need to verify that the parser can handle the tokens
-    // produced by the scanner when an unterminated string is encountered.
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    parseCompilationUnit(r'''
-void main() {
-  var x = """''', codes: [
-      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-      ScannerErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN
-    ], errors: [
-      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 30, 0),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 0)
-    ]);
-  }
-
-  void test_unterminatedString_multiline_at_eof_4_quotes() {
-    // Although the "unterminated string" error message is produced by the
-    // scanner, we need to verify that the parser can handle the tokens
-    // produced by the scanner when an unterminated string is encountered.
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    parseCompilationUnit(r'''
-void main() {
-  var x = """"''', codes: [
-      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-      ScannerErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN
-    ], errors: [
-      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 31, 0),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 31, 0)
-    ]);
-  }
-
-  void test_unterminatedString_multiline_at_eof_5_quotes() {
-    // Although the "unterminated string" error message is produced by the
-    // scanner, we need to verify that the parser can handle the tokens
-    // produced by the scanner when an unterminated string is encountered.
-    // TODO(brianwilkerson) Remove codes when highlighting is fixed.
-    parseCompilationUnit(r'''
-void main() {
-  var x = """""''', codes: [
-      ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
-      ScannerErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.EXPECTED_TOKEN
-    ], errors: [
-      expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 28, 1),
-      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 32, 0),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 32, 0)
-    ]);
-  }
-
-  void test_useOfUnaryPlusOperator() {
-    createParser('+x');
-    Expression expression = parser.parseUnaryExpression();
-    expectNotNullIfNoErrors(expression);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
-    if (usingFastaParser) {
-      BinaryExpression binaryExpression = expression;
-      expect(binaryExpression.leftOperand.isSynthetic, isTrue);
-      expect(binaryExpression.rightOperand.isSynthetic, isFalse);
-      SimpleIdentifier identifier = binaryExpression.rightOperand;
-      expect(identifier.name, 'x');
-    } else {
-      var identifier = expression as SimpleIdentifier;
-      expect(identifier.isSynthetic, isTrue);
-    }
-  }
-
-  void test_varAndType_field() {
-    parseCompilationUnit("class C { var int x; }",
-        errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 10, 3)]);
-  }
-
-  void test_varAndType_local() {
-    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
-    // this would be a better error message.
-    parseStatement("var int x;");
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]
-        : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 8, 1)]);
-  }
-
-  void test_varAndType_parameter() {
-    // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but
-    // this would be a better error message.
-    createParser('(var int x)');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 1, 3)]
-        : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
-  }
-
-  void test_varAndType_topLevelVariable() {
-    parseCompilationUnit("var int x;",
-        errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]);
-  }
-
-  void test_varAsTypeName_as() {
-    parseExpression("x as var",
-        expectedEndOffset: 5,
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 3)]
-            : [expectedError(ParserErrorCode.VAR_AS_TYPE_NAME, 7, 3)]);
-  }
-
-  void test_varClass() {
-    parseCompilationUnit("var class C {}",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `var` as a malformed top level var
-                // and `class` as the start of a class declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 5),
-              ]
-            : [expectedError(ParserErrorCode.VAR_CLASS, 0, 3)]);
-  }
-
-  void test_varEnum() {
-    parseCompilationUnit("var enum E {ONE}",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `var` as a malformed top level var
-                // and `enum` as the start of an enum declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 4),
-              ]
-            : [expectedError(ParserErrorCode.VAR_ENUM, 0, 3)]);
-  }
-
-  void test_varReturnType() {
-    createParser('var m() {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.VAR_RETURN_TYPE, 0, 3)]);
-  }
-
-  void test_varTypedef() {
-    parseCompilationUnit("var typedef F();",
-        errors: usingFastaParser
-            ? [
-                // Fasta interprets the `var` as a malformed top level var
-                // and `typedef` as the start of an typedef declaration.
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 7),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 7),
-              ]
-            : [expectedError(ParserErrorCode.VAR_TYPEDEF, 0, 3)]);
-  }
-
-  void test_voidParameter() {
-    NormalFormalParameter parameter =
-        parseFormalParameterList('(void a)').parameters[0];
-    expectNotNullIfNoErrors(parameter);
-    assertNoErrors();
-  }
-
-  void test_voidVariable_parseClassMember_initializer() {
-    createParser('void x = 0;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_voidVariable_parseClassMember_noInitializer() {
-    createParser('void x;');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_voidVariable_parseCompilationUnit_initializer() {
-    parseCompilationUnit("void x = 0;");
-  }
-
-  void test_voidVariable_parseCompilationUnit_noInitializer() {
-    parseCompilationUnit("void x;");
-  }
-
-  void test_voidVariable_parseCompilationUnitMember_initializer() {
-    createParser('void a = 0;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_voidVariable_parseCompilationUnitMember_noInitializer() {
-    createParser('void a;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(member);
-    assertNoErrors();
-  }
-
-  void test_voidVariable_statement_initializer() {
-    parseStatement("void x = 0;");
-    assertNoErrors();
-  }
-
-  void test_voidVariable_statement_noInitializer() {
-    parseStatement("void x;");
-    assertNoErrors();
-  }
-
-  void test_withBeforeExtends() {
-    parseCompilationUnit("class A with B extends C {}",
-        errors: [expectedError(ParserErrorCode.WITH_BEFORE_EXTENDS, 15, 7)]);
-  }
-
-  void test_withWithoutExtends() {
-    createParser('class A with B, C {}');
-    ClassDeclaration declaration = parseFullCompilationUnitMember();
-    expectNotNullIfNoErrors(declaration);
-    listener.assertNoErrors();
-  }
-
-  void test_wrongSeparatorForPositionalParameter() {
-    createParser('(a, [b : 0])');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    listener.assertErrors([
-      expectedError(
-          ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER, 7, 1)
-    ]);
-  }
-
-  void test_wrongTerminatorForParameterGroup_named() {
-    createParser('(a, {b, c])');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    // fasta scanner generates '(a, {b, c]})' where '}' is synthetic
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
-        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
-      ]);
-    } else {
-      listener.assertErrors([
-        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1),
-        expectedError(
-            ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, 9, 1)
-      ]);
-    }
-  }
-
-  void test_wrongTerminatorForParameterGroup_optional() {
-    createParser('(a, [b, c})');
-    FormalParameterList list = parser.parseFormalParameterList();
-    expectNotNullIfNoErrors(list);
-    // fasta scanner generates '(a, [b, c}])' where ']' is synthetic
-    if (usingFastaParser) {
-      listener.assertErrors([
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
-        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
-      ]);
-    } else {
-      listener.assertErrors([
-        expectedError(ScannerErrorCode.EXPECTED_TOKEN, 4, 1),
-        expectedError(
-            ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP, 10, 1)
-      ]);
-    }
-  }
-}
-
-@reflectiveTest
-class ExpressionParserTest extends ParserTestCase
-    with ExpressionParserTestMixin {}
-
-mixin ExpressionParserTestMixin implements AbstractParserTestCase {
-  void test_namedArgument() {
-    var invocation = parseExpression('m(a: 1, b: 2)') as MethodInvocation;
-    List<Expression> arguments = invocation.argumentList.arguments;
-
-    var a = arguments[0] as NamedExpression;
-    expect(a.name.label.name, 'a');
-    expect(a.expression, isNotNull);
-
-    var b = arguments[1] as NamedExpression;
-    expect(b.name.label.name, 'b');
-    expect(b.expression, isNotNull);
-  }
-
-  void test_parseAdditiveExpression_normal() {
-    Expression expression = parseAdditiveExpression('x + y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.PLUS);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseAdditiveExpression_super() {
-    Expression expression = parseAdditiveExpression('super + y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isSuperExpression);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.PLUS);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseAssignableExpression_expression_args_dot() {
-    Expression expression = parseAssignableExpression('(x)(y).z', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    FunctionExpressionInvocation invocation =
-        propertyAccess.target as FunctionExpressionInvocation;
-    expect(invocation.function, isNotNull);
-    expect(invocation.typeArguments, isNull);
-    ArgumentList argumentList = invocation.argumentList;
-    expect(argumentList, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-    expect(propertyAccess.operator, isNotNull);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableExpression_expression_args_dot_typeArguments() {
-    Expression expression = parseAssignableExpression('(x)<F>(y).z', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    FunctionExpressionInvocation invocation =
-        propertyAccess.target as FunctionExpressionInvocation;
-    expect(invocation.function, isNotNull);
-    expect(invocation.typeArguments, isNotNull);
-    ArgumentList argumentList = invocation.argumentList;
-    expect(argumentList, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-    expect(propertyAccess.operator, isNotNull);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableExpression_expression_dot() {
-    Expression expression = parseAssignableExpression('(x).y', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    expect(propertyAccess.target, isNotNull);
-    expect(propertyAccess.operator.type, TokenType.PERIOD);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableExpression_expression_index() {
-    Expression expression = parseAssignableExpression('(x)[y]', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var indexExpression = expression as IndexExpression;
-    expect(indexExpression.target, isNotNull);
-    expect(indexExpression.leftBracket, isNotNull);
-    expect(indexExpression.index, isNotNull);
-    expect(indexExpression.rightBracket, isNotNull);
-  }
-
-  void test_parseAssignableExpression_expression_question_dot() {
-    Expression expression = parseAssignableExpression('(x)?.y', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    expect(propertyAccess.target, isNotNull);
-    expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableExpression_identifier() {
-    Expression expression = parseAssignableExpression('x', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var identifier = expression as SimpleIdentifier;
-    expect(identifier, isNotNull);
-  }
-
-  void test_parseAssignableExpression_identifier_args_dot() {
-    Expression expression = parseAssignableExpression('x(y).z', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    MethodInvocation invocation = propertyAccess.target as MethodInvocation;
-    expect(invocation.methodName.name, "x");
-    expect(invocation.typeArguments, isNull);
-    ArgumentList argumentList = invocation.argumentList;
-    expect(argumentList, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-    expect(propertyAccess.operator, isNotNull);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableExpression_identifier_args_dot_typeArguments() {
-    Expression expression = parseAssignableExpression('x<E>(y).z', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    MethodInvocation invocation = propertyAccess.target as MethodInvocation;
-    expect(invocation.methodName.name, "x");
-    expect(invocation.typeArguments, isNotNull);
-    ArgumentList argumentList = invocation.argumentList;
-    expect(argumentList, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-    expect(propertyAccess.operator, isNotNull);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableExpression_identifier_dot() {
-    Expression expression = parseAssignableExpression('x.y', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var identifier = expression as PrefixedIdentifier;
-    expect(identifier.prefix.name, 'x');
-    expect(identifier.period, isNotNull);
-    expect(identifier.period.type, TokenType.PERIOD);
-    expect(identifier.identifier.name, 'y');
-  }
-
-  void test_parseAssignableExpression_identifier_index() {
-    Expression expression = parseAssignableExpression('x[y]', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var indexExpression = expression as IndexExpression;
-    expect(indexExpression.target, isNotNull);
-    expect(indexExpression.leftBracket, isNotNull);
-    expect(indexExpression.index, isNotNull);
-    expect(indexExpression.rightBracket, isNotNull);
-  }
-
-  void test_parseAssignableExpression_identifier_question_dot() {
-    Expression expression = parseAssignableExpression('x?.y', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    expect(propertyAccess.target, isNotNull);
-    expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableExpression_super_dot() {
-    Expression expression = parseAssignableExpression('super.y', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    expect(propertyAccess.target, isSuperExpression);
-    expect(propertyAccess.operator, isNotNull);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableExpression_super_index() {
-    Expression expression = parseAssignableExpression('super[y]', false);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var indexExpression = expression as IndexExpression;
-    expect(indexExpression.target, isSuperExpression);
-    expect(indexExpression.leftBracket, isNotNull);
-    expect(indexExpression.index, isNotNull);
-    expect(indexExpression.rightBracket, isNotNull);
-  }
-
-  void test_parseAssignableSelector_dot() {
-    Expression expression = parseAssignableSelector('.x', true);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    expect(propertyAccess.operator.type, TokenType.PERIOD);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAssignableSelector_index() {
-    Expression expression = parseAssignableSelector('[x]', true);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var indexExpression = expression as IndexExpression;
-    expect(indexExpression.leftBracket, isNotNull);
-    expect(indexExpression.index, isNotNull);
-    expect(indexExpression.rightBracket, isNotNull);
-  }
-
-  void test_parseAssignableSelector_none() {
-    Expression expression = parseAssignableSelector('', true);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var identifier = expression as SimpleIdentifier;
-    expect(identifier, isNotNull);
-  }
-
-  void test_parseAssignableSelector_question_dot() {
-    Expression expression = parseAssignableSelector('?.x', true);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    expect(propertyAccess.operator.type, TokenType.QUESTION_PERIOD);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parseAwaitExpression() {
-    AwaitExpression expression = parseAwaitExpression('await x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.awaitKeyword, isNotNull);
-    expect(expression.expression, isNotNull);
-  }
-
-  void test_parseBitwiseAndExpression_normal() {
-    Expression expression = parseBitwiseAndExpression('x & y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.AMPERSAND);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseBitwiseAndExpression_super() {
-    Expression expression = parseBitwiseAndExpression('super & y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isSuperExpression);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.AMPERSAND);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseBitwiseOrExpression_normal() {
-    Expression expression = parseBitwiseOrExpression('x | y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.BAR);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseBitwiseOrExpression_super() {
-    Expression expression = parseBitwiseOrExpression('super | y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isSuperExpression);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.BAR);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseBitwiseXorExpression_normal() {
-    Expression expression = parseBitwiseXorExpression('x ^ y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.CARET);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseBitwiseXorExpression_super() {
-    Expression expression = parseBitwiseXorExpression('super ^ y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isSuperExpression);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.CARET);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseCascadeSection_i() {
-    Expression expression = parseCascadeSection('..[i]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as IndexExpression;
-    expect(section.target, isNull);
-    expect(section.leftBracket, isNotNull);
-    expect(section.index, isNotNull);
-    expect(section.rightBracket, isNotNull);
-  }
-
-  void test_parseCascadeSection_ia() {
-    Expression expression = parseCascadeSection('..[i](b)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as FunctionExpressionInvocation;
-    expect(section.function, isIndexExpression);
-    expect(section.typeArguments, isNull);
-    expect(section.argumentList, isNotNull);
-  }
-
-  void test_parseCascadeSection_ia_typeArguments() {
-    Expression expression = parseCascadeSection('..[i]<E>(b)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as FunctionExpressionInvocation;
-    expect(section.function, isIndexExpression);
-    expect(section.typeArguments, isNotNull);
-    expect(section.argumentList, isNotNull);
-  }
-
-  void test_parseCascadeSection_ii() {
-    Expression expression = parseCascadeSection('..a(b).c(d)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as MethodInvocation;
-    expect(section.target, isMethodInvocation);
-    expect(section.operator, isNotNull);
-    expect(section.methodName, isNotNull);
-    expect(section.typeArguments, isNull);
-    expect(section.argumentList, isNotNull);
-    expect(section.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseCascadeSection_ii_typeArguments() {
-    Expression expression = parseCascadeSection('..a<E>(b).c<F>(d)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as MethodInvocation;
-    expect(section.target, isMethodInvocation);
-    expect(section.operator, isNotNull);
-    expect(section.methodName, isNotNull);
-    expect(section.typeArguments, isNotNull);
-    expect(section.argumentList, isNotNull);
-    expect(section.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseCascadeSection_p() {
-    Expression expression = parseCascadeSection('..a');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as PropertyAccess;
-    expect(section.target, isNull);
-    expect(section.operator, isNotNull);
-    expect(section.propertyName, isNotNull);
-  }
-
-  void test_parseCascadeSection_p_assign() {
-    Expression expression = parseCascadeSection('..a = 3');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as AssignmentExpression;
-    expect(section.leftHandSide, isNotNull);
-    expect(section.operator, isNotNull);
-    Expression rhs = section.rightHandSide;
-    expect(rhs, isNotNull);
-  }
-
-  void test_parseCascadeSection_p_assign_withCascade() {
-    Expression expression = parseCascadeSection('..a = 3..m()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as AssignmentExpression;
-    expect(section.leftHandSide, isNotNull);
-    expect(section.operator, isNotNull);
-    Expression rhs = section.rightHandSide;
-    expect(rhs, isIntegerLiteral);
-  }
-
-  void test_parseCascadeSection_p_assign_withCascade_typeArguments() {
-    Expression expression = parseCascadeSection('..a = 3..m<E>()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as AssignmentExpression;
-    expect(section.leftHandSide, isNotNull);
-    expect(section.operator, isNotNull);
-    Expression rhs = section.rightHandSide;
-    expect(rhs, isIntegerLiteral);
-  }
-
-  void test_parseCascadeSection_p_builtIn() {
-    Expression expression = parseCascadeSection('..as');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as PropertyAccess;
-    expect(section.target, isNull);
-    expect(section.operator, isNotNull);
-    expect(section.propertyName, isNotNull);
-  }
-
-  void test_parseCascadeSection_pa() {
-    Expression expression = parseCascadeSection('..a(b)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as MethodInvocation;
-    expect(section.target, isNull);
-    expect(section.operator, isNotNull);
-    expect(section.methodName, isNotNull);
-    expect(section.typeArguments, isNull);
-    expect(section.argumentList, isNotNull);
-    expect(section.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseCascadeSection_pa_typeArguments() {
-    Expression expression = parseCascadeSection('..a<E>(b)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as MethodInvocation;
-    expect(section.target, isNull);
-    expect(section.operator, isNotNull);
-    expect(section.methodName, isNotNull);
-    expect(section.typeArguments, isNotNull);
-    expect(section.argumentList, isNotNull);
-    expect(section.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseCascadeSection_paa() {
-    Expression expression = parseCascadeSection('..a(b)(c)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as FunctionExpressionInvocation;
-    expect(section.function, isMethodInvocation);
-    expect(section.typeArguments, isNull);
-    expect(section.argumentList, isNotNull);
-    expect(section.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseCascadeSection_paa_typeArguments() {
-    Expression expression = parseCascadeSection('..a<E>(b)<F>(c)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as FunctionExpressionInvocation;
-    expect(section.function, isMethodInvocation);
-    expect(section.typeArguments, isNotNull);
-    expect(section.argumentList, isNotNull);
-    expect(section.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseCascadeSection_paapaa() {
-    Expression expression = parseCascadeSection('..a(b)(c).d(e)(f)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as FunctionExpressionInvocation;
-    expect(section.function, isMethodInvocation);
-    expect(section.typeArguments, isNull);
-    expect(section.argumentList, isNotNull);
-    expect(section.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseCascadeSection_paapaa_typeArguments() {
-    Expression expression =
-        parseCascadeSection('..a<E>(b)<F>(c).d<G>(e)<H>(f)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as FunctionExpressionInvocation;
-    expect(section.function, isMethodInvocation);
-    expect(section.typeArguments, isNotNull);
-    expect(section.argumentList, isNotNull);
-    expect(section.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseCascadeSection_pap() {
-    Expression expression = parseCascadeSection('..a(b).c');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as PropertyAccess;
-    expect(section.target, isNotNull);
-    expect(section.operator, isNotNull);
-    expect(section.propertyName, isNotNull);
-  }
-
-  void test_parseCascadeSection_pap_typeArguments() {
-    Expression expression = parseCascadeSection('..a<E>(b).c');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var section = expression as PropertyAccess;
-    expect(section.target, isNotNull);
-    expect(section.operator, isNotNull);
-    expect(section.propertyName, isNotNull);
-  }
-
-  void test_parseConditionalExpression() {
-    ConditionalExpression expression = parseConditionalExpression('x ? y : z');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.condition, isNotNull);
-    expect(expression.question, isNotNull);
-    expect(expression.thenExpression, isNotNull);
-    expect(expression.colon, isNotNull);
-    expect(expression.elseExpression, isNotNull);
-  }
-
-  void test_parseConstExpression_instanceCreation() {
-    Expression expression = parseConstExpression('const A()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression, isInstanceCreationExpression);
-    InstanceCreationExpression instanceCreation = expression;
-    expect(instanceCreation.keyword, isNotNull);
-    ConstructorName name = instanceCreation.constructorName;
-    expect(name, isNotNull);
-    expect(name.type, isNotNull);
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-    expect(instanceCreation.argumentList, isNotNull);
-  }
-
-  void test_parseConstExpression_listLiteral_typed() {
-    Expression expression = parseConstExpression('const <A> []');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as ListLiteral;
-    expect(literal.constKeyword, isNotNull);
-    expect(literal.typeArguments, isNotNull);
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseConstExpression_listLiteral_untyped() {
-    Expression expression = parseConstExpression('const []');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as ListLiteral;
-    expect(literal.constKeyword, isNotNull);
-    expect(literal.typeArguments, isNull);
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseConstExpression_mapLiteral_typed() {
-    Expression expression = parseConstExpression('const <A, B> {}');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SetOrMapLiteral;
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-    expect(literal.typeArguments, isNotNull);
-  }
-
-  void test_parseConstExpression_mapLiteral_typed_missingGt() {
-    Expression expression = parseExpression('const <A, B {}',
-        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1)]);
-    expect(expression, isNotNull);
-    var literal = expression as SetOrMapLiteral;
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-    expect(literal.typeArguments, isNotNull);
-  }
-
-  void test_parseConstExpression_mapLiteral_untyped() {
-    Expression expression = parseConstExpression('const {}');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SetOrMapLiteral;
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-    expect(literal.typeArguments, isNull);
-  }
-
-  void test_parseEqualityExpression_normal() {
-    BinaryExpression expression = parseEqualityExpression('x == y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.leftOperand, isNotNull);
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.EQ_EQ);
-    expect(expression.rightOperand, isNotNull);
-  }
-
-  void test_parseEqualityExpression_super() {
-    BinaryExpression expression = parseEqualityExpression('super == y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.leftOperand, isSuperExpression);
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.EQ_EQ);
-    expect(expression.rightOperand, isNotNull);
-  }
-
-  void test_parseExpression_assign() {
-    // TODO(brianwilkerson) Implement more tests for this method.
-    Expression expression = parseExpression('x = y');
-    var assignmentExpression = expression as AssignmentExpression;
-    expect(assignmentExpression.leftHandSide, isNotNull);
-    expect(assignmentExpression.operator, isNotNull);
-    expect(assignmentExpression.operator.type, TokenType.EQ);
-    expect(assignmentExpression.rightHandSide, isNotNull);
-  }
-
-  void test_parseExpression_assign_compound() {
-    if (usingFastaParser && AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
-      Expression expression = parseExpression('x ||= y');
-      var assignmentExpression = expression as AssignmentExpression;
-      expect(assignmentExpression.leftHandSide, isNotNull);
-      expect(assignmentExpression.operator, isNotNull);
-      expect(assignmentExpression.operator.type, TokenType.BAR_BAR_EQ);
-      expect(assignmentExpression.rightHandSide, isNotNull);
-    }
-  }
-
-  void test_parseExpression_comparison() {
-    Expression expression = parseExpression('--a.b == c');
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.EQ_EQ);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseExpression_constAndTypeParameters() {
-    Expression expression = parseExpression('const <E>',
-        codes: usingFastaParser
-            ? [
-                // TODO(danrubel): Improve this error message.
-                ParserErrorCode.EXPECTED_TOKEN
-              ]
-            : [ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL]);
-    expect(expression, isNotNull);
-  }
-
-  void test_parseExpression_function_async() {
-    Expression expression = parseExpression('() async {}');
-    var functionExpression = expression as FunctionExpression;
-    expect(functionExpression.body, isNotNull);
-    expect(functionExpression.body.isAsynchronous, isTrue);
-    expect(functionExpression.body.isGenerator, isFalse);
-    expect(functionExpression.parameters, isNotNull);
-  }
-
-  void test_parseExpression_function_asyncStar() {
-    Expression expression = parseExpression('() async* {}');
-    var functionExpression = expression as FunctionExpression;
-    expect(functionExpression.body, isNotNull);
-    expect(functionExpression.body.isAsynchronous, isTrue);
-    expect(functionExpression.body.isGenerator, isTrue);
-    expect(functionExpression.parameters, isNotNull);
-  }
-
-  void test_parseExpression_function_sync() {
-    Expression expression = parseExpression('() {}');
-    var functionExpression = expression as FunctionExpression;
-    expect(functionExpression.body, isNotNull);
-    expect(functionExpression.body.isAsynchronous, isFalse);
-    expect(functionExpression.body.isGenerator, isFalse);
-    expect(functionExpression.parameters, isNotNull);
-  }
-
-  void test_parseExpression_function_syncStar() {
-    Expression expression = parseExpression('() sync* {}');
-    var functionExpression = expression as FunctionExpression;
-    expect(functionExpression.body, isNotNull);
-    expect(functionExpression.body.isAsynchronous, isFalse);
-    expect(functionExpression.body.isGenerator, isTrue);
-    expect(functionExpression.parameters, isNotNull);
-  }
-
-  void test_parseExpression_invokeFunctionExpression() {
-    Expression expression = parseExpression('(a) {return a + a;} (3)');
-    var invocation = expression as FunctionExpressionInvocation;
-    expect(invocation.function, isFunctionExpression);
-    FunctionExpression functionExpression =
-        invocation.function as FunctionExpression;
-    expect(functionExpression.parameters, isNotNull);
-    expect(functionExpression.body, isNotNull);
-    expect(invocation.typeArguments, isNull);
-    ArgumentList list = invocation.argumentList;
-    expect(list, isNotNull);
-    expect(list.arguments, hasLength(1));
-  }
-
-  void test_parseExpression_nonAwait() {
-    Expression expression = parseExpression('await()');
-    var invocation = expression as MethodInvocation;
-    expect(invocation.methodName.name, 'await');
-    expect(invocation.typeArguments, isNull);
-    expect(invocation.argumentList, isNotNull);
-  }
-
-  void test_parseExpression_sendWithTypeParam_afterIndex() {
-    final unit = parseCompilationUnit('main() { factories[C]<num, int>(); }');
-    expect(unit.declarations, hasLength(1));
-    FunctionDeclaration mainMethod = unit.declarations[0];
-    BlockFunctionBody body = mainMethod.functionExpression.body;
-    NodeList<Statement> statements = body.block.statements;
-    expect(statements, hasLength(1));
-    ExpressionStatement statement = statements[0];
-    FunctionExpressionInvocation expression = statement.expression;
-
-    IndexExpression function = expression.function;
-    SimpleIdentifier target = function.target;
-    expect(target.name, 'factories');
-    SimpleIdentifier index = function.index;
-    expect(index.name, 'C');
-
-    NodeList<TypeAnnotation> typeArguments = expression.typeArguments.arguments;
-    expect(typeArguments, hasLength(2));
-    expect((typeArguments[0] as NamedType).name.name, 'num');
-    expect((typeArguments[1] as NamedType).name.name, 'int');
-
-    expect(expression.argumentList.arguments, hasLength(0));
-  }
-
-  void test_parseExpression_sendWithTypeParam_afterSend() {
-    final unit = parseCompilationUnit('main() { factories(C)<num, int>(); }');
-    expect(unit.declarations, hasLength(1));
-    FunctionDeclaration mainMethod = unit.declarations[0];
-    BlockFunctionBody body = mainMethod.functionExpression.body;
-    NodeList<Statement> statements = body.block.statements;
-    expect(statements, hasLength(1));
-    ExpressionStatement statement = statements[0];
-    FunctionExpressionInvocation expression = statement.expression;
-
-    MethodInvocation invocation = expression.function;
-    expect(invocation.methodName.name, 'factories');
-    NodeList<Expression> invocationArguments =
-        invocation.argumentList.arguments;
-    expect(invocationArguments, hasLength(1));
-    SimpleIdentifier index = invocationArguments[0];
-    expect(index.name, 'C');
-
-    NodeList<TypeAnnotation> typeArguments = expression.typeArguments.arguments;
-    expect(typeArguments, hasLength(2));
-    expect((typeArguments[0] as NamedType).name.name, 'num');
-    expect((typeArguments[1] as NamedType).name.name, 'int');
-
-    expect(expression.argumentList.arguments, hasLength(0));
-  }
-
-  void test_parseExpression_superMethodInvocation() {
-    Expression expression = parseExpression('super.m()');
-    var invocation = expression as MethodInvocation;
-    expect(invocation.target, isNotNull);
-    expect(invocation.methodName, isNotNull);
-    expect(invocation.typeArguments, isNull);
-    expect(invocation.argumentList, isNotNull);
-  }
-
-  void test_parseExpression_superMethodInvocation_typeArguments() {
-    Expression expression = parseExpression('super.m<E>()');
-    var invocation = expression as MethodInvocation;
-    expect(invocation.target, isNotNull);
-    expect(invocation.methodName, isNotNull);
-    expect(invocation.typeArguments, isNotNull);
-    expect(invocation.argumentList, isNotNull);
-  }
-
-  void test_parseExpression_superMethodInvocation_typeArguments_chained() {
-    Expression expression = parseExpression('super.b.c<D>()');
-    MethodInvocation invocation = expression as MethodInvocation;
-    Expression target = invocation.target;
-    expect(target, isPropertyAccess);
-    expect(invocation.methodName, isNotNull);
-    expect(invocation.methodName.name, 'c');
-    expect(invocation.typeArguments, isNotNull);
-    expect(invocation.argumentList, isNotNull);
-  }
-
-  void test_parseExpressionList_multiple() {
-    List<Expression> result = parseExpressionList('1, 2, 3');
-    expect(result, isNotNull);
-    assertNoErrors();
-    expect(result, hasLength(3));
-  }
-
-  void test_parseExpressionList_single() {
-    List<Expression> result = parseExpressionList('1');
-    expect(result, isNotNull);
-    assertNoErrors();
-    expect(result, hasLength(1));
-  }
-
-  void test_parseExpressionWithoutCascade_assign() {
-    // TODO(brianwilkerson) Implement more tests for this method.
-    Expression expression = parseExpressionWithoutCascade('x = y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var assignmentExpression = expression as AssignmentExpression;
-    expect(assignmentExpression.leftHandSide, isNotNull);
-    expect(assignmentExpression.operator, isNotNull);
-    expect(assignmentExpression.operator.type, TokenType.EQ);
-    expect(assignmentExpression.rightHandSide, isNotNull);
-  }
-
-  void test_parseExpressionWithoutCascade_comparison() {
-    Expression expression = parseExpressionWithoutCascade('--a.b == c');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.EQ_EQ);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseExpressionWithoutCascade_superMethodInvocation() {
-    Expression expression = parseExpressionWithoutCascade('super.m()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var invocation = expression as MethodInvocation;
-    expect(invocation.target, isNotNull);
-    expect(invocation.methodName, isNotNull);
-    expect(invocation.typeArguments, isNull);
-    expect(invocation.argumentList, isNotNull);
-  }
-
-  void
-      test_parseExpressionWithoutCascade_superMethodInvocation_typeArguments() {
-    Expression expression = parseExpressionWithoutCascade('super.m<E>()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var invocation = expression as MethodInvocation;
-    expect(invocation.target, isNotNull);
-    expect(invocation.methodName, isNotNull);
-    expect(invocation.typeArguments, isNotNull);
-    expect(invocation.argumentList, isNotNull);
-  }
-
-  void test_parseFunctionExpression_body_inExpression() {
-    FunctionExpression expression = parseFunctionExpression('(int i) => i++');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.body, isNotNull);
-    expect(expression.typeParameters, isNull);
-    expect(expression.parameters, isNotNull);
-    expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
-  }
-
-  void test_parseFunctionExpression_constAndTypeParameters2() {
-    FunctionExpression expression =
-        parseFunctionExpression('const <E>(E i) => i++');
-    expect(expression, isNotNull);
-    assertErrorsWithCodes(usingFastaParser
-        ? [ParserErrorCode.UNEXPECTED_TOKEN]
-        : [
-            ParserErrorCode.EXPECTED_TOKEN,
-            ParserErrorCode.EXPECTED_TOKEN,
-            ParserErrorCode.MISSING_IDENTIFIER,
-            ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR,
-            ParserErrorCode.MISSING_CLOSING_PARENTHESIS,
-          ]);
-    expect(expression.body, isNotNull);
-    if (usingFastaParser) {
-      expect(expression.typeParameters, isNotNull);
-      expect(expression.parameters, isNotNull);
-      expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
-    }
-  }
-
-  void test_parseFunctionExpression_functionInPlaceOfTypeName() {
-    Expression expression = parseExpression('<test(' ', (){});>[0, 1, 2]',
-        codes: usingFastaParser
-            ? [ParserErrorCode.EXPECTED_TOKEN]
-            : [
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
-              ]);
-    expect(expression, isNotNull);
-    if (usingFastaParser) {
-      ListLiteral literal = expression;
-      expect(literal.typeArguments.arguments, hasLength(1));
-    }
-  }
-
-  void test_parseFunctionExpression_typeParameters() {
-    FunctionExpression expression = parseFunctionExpression('<E>(E i) => i++');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.body, isNotNull);
-    expect(expression.typeParameters, isNotNull);
-    expect(expression.parameters, isNotNull);
-    expect((expression.body as ExpressionFunctionBody).semicolon, isNull);
-  }
-
-  void test_parseInstanceCreationExpression_qualifiedType() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
-    InstanceCreationExpression expression =
-        parseInstanceCreationExpression('A.B()', token);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type.name.name, 'A.B');
-    expect(type.typeArguments, isNull);
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-    expect(expression.argumentList, isNotNull);
-  }
-
-  void test_parseInstanceCreationExpression_qualifiedType_named() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
-    InstanceCreationExpression expression =
-        parseInstanceCreationExpression('A.B.c()', token);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type, isNotNull);
-    expect(type.typeArguments, isNull);
-    expect(name.period, isNotNull);
-    expect(name.name, isNotNull);
-    expect(expression.argumentList, isNotNull);
-  }
-
-  void
-      test_parseInstanceCreationExpression_qualifiedType_named_typeArguments() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
-    InstanceCreationExpression expression =
-        parseInstanceCreationExpression('A.B<E>.c()', token);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type, isNotNull);
-    expect(type.typeArguments.arguments, hasLength(1));
-    expect(name.period, isNotNull);
-    expect(name.name, isNotNull);
-    expect(expression.argumentList, isNotNull);
-  }
-
-  void test_parseInstanceCreationExpression_qualifiedType_typeArguments() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
-    InstanceCreationExpression expression =
-        parseInstanceCreationExpression('A.B<E>()', token);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type, isNotNull);
-    expect(type.typeArguments.arguments, hasLength(1));
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-    expect(expression.argumentList, isNotNull);
-  }
-
-  void test_parseInstanceCreationExpression_type() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
-    InstanceCreationExpression expression =
-        parseInstanceCreationExpression('A()', token);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type, isNotNull);
-    expect(type.typeArguments, isNull);
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-    expect(expression.argumentList, isNotNull);
-  }
-
-  void test_parseInstanceCreationExpression_type_named() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
-    InstanceCreationExpression expression =
-        parseInstanceCreationExpression('A.c()', token);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type, isNotNull);
-    expect(type.typeArguments, isNull);
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-    expect(expression.argumentList, isNotNull);
-  }
-
-  void test_parseInstanceCreationExpression_type_named_typeArguments() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
-    InstanceCreationExpressionImpl expression =
-        parseInstanceCreationExpression('A<B>.c()', token);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type, isNotNull);
-    expect(type.typeArguments.arguments, hasLength(1));
-    expect(name.period, isNotNull);
-    expect(name.name, isNotNull);
-    expect(expression.argumentList, isNotNull);
-    expect(expression.typeArguments, isNull);
-  }
-
-  void test_parseInstanceCreationExpression_type_named_typeArguments_34403() {
-    if (!usingFastaParser) {
-      return;
-    }
-    InstanceCreationExpressionImpl expression =
-        parseExpression('new a.b.c<C>()', errors: [
-      expectedError(
-          CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR, 8, 1)
-    ]);
-    expect(expression, isNotNull);
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type, isNotNull);
-    expect(type.typeArguments, isNull);
-    expect(name.period, isNotNull);
-    expect(name.name, isNotNull);
-    expect(expression.argumentList, isNotNull);
-    expect(expression.typeArguments.arguments, hasLength(1));
-  }
-
-  void test_parseInstanceCreationExpression_type_typeArguments() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.NEW);
-    InstanceCreationExpression expression =
-        parseInstanceCreationExpression('A<B>()', token);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword.keyword, Keyword.NEW);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    TypeName type = name.type;
-    expect(type, isNotNull);
-    expect(type.typeArguments.arguments, hasLength(1));
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-    expect(expression.argumentList, isNotNull);
-  }
-
-  void test_parseListLiteral_empty_oneToken() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.CONST);
-    ListLiteral literal = parseListLiteral(token, null, '[]');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.constKeyword.keyword, Keyword.CONST);
-    expect(literal.typeArguments, isNull);
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseListLiteral_empty_oneToken_withComment() {
-    ListLiteral literal = parseListLiteral(null, null, '/* 0 */ []');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.constKeyword, isNull);
-    expect(literal.typeArguments, isNull);
-    Token leftBracket = literal.leftBracket;
-    expect(leftBracket, isNotNull);
-    expect(leftBracket.precedingComments, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseListLiteral_empty_twoTokens() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.CONST);
-    ListLiteral literal = parseListLiteral(token, null, '[ ]');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.constKeyword.keyword, Keyword.CONST);
-    expect(literal.typeArguments, isNull);
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseListLiteral_multiple() {
-    ListLiteral literal = parseListLiteral(null, null, '[1, 2, 3]');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.constKeyword, isNull);
-    expect(literal.typeArguments, isNull);
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(3));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseListLiteral_single() {
-    ListLiteral literal = parseListLiteral(null, null, '[1]');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.constKeyword, isNull);
-    expect(literal.typeArguments, isNull);
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(1));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseListLiteral_single_withTypeArgument() {
-    ListLiteral literal = parseListLiteral(null, '<int>', '[1]');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.constKeyword, isNull);
-    expect(literal.typeArguments, isNotNull);
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(1));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseListOrMapLiteral_list_noType() {
-    TypedLiteral literal = parseListOrMapLiteral(null, '[1]');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    var listLiteral = literal as ListLiteral;
-    expect(listLiteral.constKeyword, isNull);
-    expect(listLiteral.typeArguments, isNull);
-    expect(listLiteral.leftBracket, isNotNull);
-    expect(listLiteral.elements, hasLength(1));
-    expect(listLiteral.rightBracket, isNotNull);
-  }
-
-  void test_parseListOrMapLiteral_list_type() {
-    TypedLiteral literal = parseListOrMapLiteral(null, '<int> [1]');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    var listLiteral = literal as ListLiteral;
-    expect(listLiteral.constKeyword, isNull);
-    expect(listLiteral.typeArguments, isNotNull);
-    expect(listLiteral.leftBracket, isNotNull);
-    expect(listLiteral.elements, hasLength(1));
-    expect(listLiteral.rightBracket, isNotNull);
-  }
-
-  void test_parseListOrMapLiteral_map_noType() {
-    TypedLiteral literal = parseListOrMapLiteral(null, "{'1' : 1}");
-    expect(literal, isNotNull);
-    assertNoErrors();
-    var mapLiteral = literal as SetOrMapLiteral;
-    expect(mapLiteral.constKeyword, isNull);
-    expect(mapLiteral.typeArguments, isNull);
-    expect(mapLiteral.leftBracket, isNotNull);
-    expect(mapLiteral.elements, hasLength(1));
-    expect(mapLiteral.rightBracket, isNotNull);
-  }
-
-  void test_parseListOrMapLiteral_map_type() {
-    TypedLiteral literal =
-        parseListOrMapLiteral(null, "<String, int> {'1' : 1}");
-    expect(literal, isNotNull);
-    assertNoErrors();
-    var mapLiteral = literal as SetOrMapLiteral;
-    expect(mapLiteral.constKeyword, isNull);
-    expect(mapLiteral.typeArguments, isNotNull);
-    expect(mapLiteral.leftBracket, isNotNull);
-    expect(mapLiteral.elements, hasLength(1));
-    expect(mapLiteral.rightBracket, isNotNull);
-  }
-
-  void test_parseLogicalAndExpression() {
-    Expression expression = parseLogicalAndExpression('x && y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.AMPERSAND_AMPERSAND);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseLogicalOrExpression() {
-    Expression expression = parseLogicalOrExpression('x || y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.BAR_BAR);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseMapLiteral_empty() {
-    Token token = TokenFactory.tokenFromKeyword(Keyword.CONST);
-    SetOrMapLiteral literal = parseMapLiteral(token, '<String, int>', '{}');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.constKeyword.keyword, Keyword.CONST);
-    expect(literal.typeArguments, isNotNull);
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(0));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseMapLiteral_multiple() {
-    SetOrMapLiteral literal = parseMapLiteral(null, null, "{'a' : b, 'x' : y}");
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(2));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseMapLiteral_multiple_trailing_comma() {
-    SetOrMapLiteral literal =
-        parseMapLiteral(null, null, "{'a' : b, 'x' : y,}");
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(2));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseMapLiteral_single() {
-    SetOrMapLiteral literal = parseMapLiteral(null, null, "{'x' : y}");
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.leftBracket, isNotNull);
-    expect(literal.elements, hasLength(1));
-    expect(literal.rightBracket, isNotNull);
-  }
-
-  void test_parseMapLiteralEntry_complex() {
-    MapLiteralEntry entry = parseMapLiteralEntry('2 + 2 : y');
-    expect(entry, isNotNull);
-    assertNoErrors();
-    expect(entry.key, isNotNull);
-    expect(entry.separator, isNotNull);
-    expect(entry.value, isNotNull);
-  }
-
-  void test_parseMapLiteralEntry_int() {
-    MapLiteralEntry entry = parseMapLiteralEntry('0 : y');
-    expect(entry, isNotNull);
-    assertNoErrors();
-    expect(entry.key, isNotNull);
-    expect(entry.separator, isNotNull);
-    expect(entry.value, isNotNull);
-  }
-
-  void test_parseMapLiteralEntry_string() {
-    MapLiteralEntry entry = parseMapLiteralEntry("'x' : y");
-    expect(entry, isNotNull);
-    assertNoErrors();
-    expect(entry.key, isNotNull);
-    expect(entry.separator, isNotNull);
-    expect(entry.value, isNotNull);
-  }
-
-  void test_parseMultiplicativeExpression_normal() {
-    Expression expression = parseMultiplicativeExpression('x * y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.STAR);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseMultiplicativeExpression_super() {
-    Expression expression = parseMultiplicativeExpression('super * y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isSuperExpression);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.STAR);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseNewExpression() {
-    InstanceCreationExpression expression = parseNewExpression('new A()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.keyword, isNotNull);
-    ConstructorName name = expression.constructorName;
-    expect(name, isNotNull);
-    expect(name.type, isNotNull);
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-    expect(expression.argumentList, isNotNull);
-  }
-
-  void test_parsePostfixExpression_decrement() {
-    Expression expression = parsePostfixExpression('i--');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var postfixExpression = expression as PostfixExpression;
-    expect(postfixExpression.operand, isNotNull);
-    expect(postfixExpression.operator, isNotNull);
-    expect(postfixExpression.operator.type, TokenType.MINUS_MINUS);
-  }
-
-  void test_parsePostfixExpression_increment() {
-    Expression expression = parsePostfixExpression('i++');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var postfixExpression = expression as PostfixExpression;
-    expect(postfixExpression.operand, isNotNull);
-    expect(postfixExpression.operator, isNotNull);
-    expect(postfixExpression.operator.type, TokenType.PLUS_PLUS);
-  }
-
-  void test_parsePostfixExpression_none_indexExpression() {
-    Expression expression = parsePostfixExpression('a[0]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var indexExpression = expression as IndexExpression;
-    expect(indexExpression.target, isNotNull);
-    expect(indexExpression.index, isNotNull);
-  }
-
-  void test_parsePostfixExpression_none_methodInvocation() {
-    Expression expression = parsePostfixExpression('a.m()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var methodInvocation = expression as MethodInvocation;
-    expect(methodInvocation.target, isNotNull);
-    expect(methodInvocation.operator.type, TokenType.PERIOD);
-    expect(methodInvocation.methodName, isNotNull);
-    expect(methodInvocation.typeArguments, isNull);
-    expect(methodInvocation.argumentList, isNotNull);
-  }
-
-  void test_parsePostfixExpression_none_methodInvocation_question_dot() {
-    Expression expression = parsePostfixExpression('a?.m()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var methodInvocation = expression as MethodInvocation;
-    expect(methodInvocation.target, isNotNull);
-    expect(methodInvocation.operator.type, TokenType.QUESTION_PERIOD);
-    expect(methodInvocation.methodName, isNotNull);
-    expect(methodInvocation.typeArguments, isNull);
-    expect(methodInvocation.argumentList, isNotNull);
-  }
-
-  void
-      test_parsePostfixExpression_none_methodInvocation_question_dot_typeArguments() {
-    Expression expression = parsePostfixExpression('a?.m<E>()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var methodInvocation = expression as MethodInvocation;
-    expect(methodInvocation.target, isNotNull);
-    expect(methodInvocation.operator.type, TokenType.QUESTION_PERIOD);
-    expect(methodInvocation.methodName, isNotNull);
-    expect(methodInvocation.typeArguments, isNotNull);
-    expect(methodInvocation.argumentList, isNotNull);
-  }
-
-  void test_parsePostfixExpression_none_methodInvocation_typeArguments() {
-    Expression expression = parsePostfixExpression('a.m<E>()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var methodInvocation = expression as MethodInvocation;
-    expect(methodInvocation.target, isNotNull);
-    expect(methodInvocation.operator.type, TokenType.PERIOD);
-    expect(methodInvocation.methodName, isNotNull);
-    expect(methodInvocation.typeArguments, isNotNull);
-    expect(methodInvocation.argumentList, isNotNull);
-  }
-
-  void test_parsePostfixExpression_none_propertyAccess() {
-    Expression expression = parsePostfixExpression('a.b');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var identifier = expression as PrefixedIdentifier;
-    expect(identifier.prefix, isNotNull);
-    expect(identifier.identifier, isNotNull);
-  }
-
-  void test_parsePrefixedIdentifier_noPrefix() {
-    String lexeme = "bar";
-    Identifier identifier = parsePrefixedIdentifier(lexeme);
-    expect(identifier, isNotNull);
-    assertNoErrors();
-    var simpleIdentifier = identifier as SimpleIdentifier;
-    expect(simpleIdentifier.token, isNotNull);
-    expect(simpleIdentifier.name, lexeme);
-  }
-
-  void test_parsePrefixedIdentifier_prefix() {
-    String lexeme = "foo.bar";
-    Identifier identifier = parsePrefixedIdentifier(lexeme);
-    expect(identifier, isNotNull);
-    assertNoErrors();
-    var prefixedIdentifier = identifier as PrefixedIdentifier;
-    expect(prefixedIdentifier.prefix.name, "foo");
-    expect(prefixedIdentifier.period, isNotNull);
-    expect(prefixedIdentifier.identifier.name, "bar");
-  }
-
-  void test_parsePrimaryExpression_const() {
-    Expression expression = parsePrimaryExpression('const A()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_double() {
-    String doubleLiteral = "3.2e4";
-    Expression expression = parsePrimaryExpression(doubleLiteral);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as DoubleLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, double.parse(doubleLiteral));
-  }
-
-  void test_parsePrimaryExpression_false() {
-    Expression expression = parsePrimaryExpression('false');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as BooleanLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, isFalse);
-  }
-
-  void test_parsePrimaryExpression_function_arguments() {
-    Expression expression = parsePrimaryExpression('(int i) => i + 1');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var functionExpression = expression as FunctionExpression;
-    expect(functionExpression.parameters, isNotNull);
-    expect(functionExpression.body, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_function_noArguments() {
-    Expression expression = parsePrimaryExpression('() => 42');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var functionExpression = expression as FunctionExpression;
-    expect(functionExpression.parameters, isNotNull);
-    expect(functionExpression.body, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_genericFunctionExpression() {
-    Expression expression =
-        parsePrimaryExpression('<X, Y>(Map<X, Y> m, X x) => m[x]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var functionExpression = expression as FunctionExpression;
-    expect(functionExpression.typeParameters, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_hex() {
-    String hexLiteral = "3F";
-    Expression expression = parsePrimaryExpression('0x$hexLiteral');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as IntegerLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, int.parse(hexLiteral, radix: 16));
-  }
-
-  void test_parsePrimaryExpression_identifier() {
-    Expression expression = parsePrimaryExpression('a');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var identifier = expression as SimpleIdentifier;
-    expect(identifier, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_int() {
-    String intLiteral = "472";
-    Expression expression = parsePrimaryExpression(intLiteral);
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as IntegerLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, int.parse(intLiteral));
-  }
-
-  void test_parsePrimaryExpression_listLiteral() {
-    Expression expression = parsePrimaryExpression('[ ]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as ListLiteral;
-    expect(literal, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_listLiteral_index() {
-    Expression expression = parsePrimaryExpression('[]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as ListLiteral;
-    expect(literal, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_listLiteral_typed() {
-    Expression expression = parsePrimaryExpression('<A>[ ]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as ListLiteral;
-    expect(literal.typeArguments, isNotNull);
-    expect(literal.typeArguments.arguments, hasLength(1));
-  }
-
-  void test_parsePrimaryExpression_mapLiteral() {
-    Expression expression = parsePrimaryExpression('{}');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SetOrMapLiteral;
-    expect(literal.typeArguments, isNull);
-    expect(literal, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_mapLiteral_typed() {
-    Expression expression = parsePrimaryExpression('<A, B>{}');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SetOrMapLiteral;
-    expect(literal.typeArguments, isNotNull);
-    expect(literal.typeArguments.arguments, hasLength(2));
-  }
-
-  void test_parsePrimaryExpression_new() {
-    Expression expression = parsePrimaryExpression('new A()');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var creation = expression as InstanceCreationExpression;
-    expect(creation, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_null() {
-    Expression expression = parsePrimaryExpression('null');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression, isNullLiteral);
-    NullLiteral literal = expression;
-    expect(literal.literal, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_parenthesized() {
-    Expression expression = parsePrimaryExpression('(x)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var parens = expression as ParenthesizedExpression;
-    expect(parens, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_string() {
-    Expression expression = parsePrimaryExpression('"string"');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.isMultiline, isFalse);
-    expect(literal.isRaw, isFalse);
-    expect(literal.value, "string");
-  }
-
-  void test_parsePrimaryExpression_string_multiline() {
-    Expression expression = parsePrimaryExpression("'''string'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.isMultiline, isTrue);
-    expect(literal.isRaw, isFalse);
-    expect(literal.value, "string");
-  }
-
-  void test_parsePrimaryExpression_string_raw() {
-    Expression expression = parsePrimaryExpression("r'string'");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.isMultiline, isFalse);
-    expect(literal.isRaw, isTrue);
-    expect(literal.value, "string");
-  }
-
-  void test_parsePrimaryExpression_super() {
-    Expression expression = parseExpression('super.x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var propertyAccess = expression as PropertyAccess;
-    expect(propertyAccess.target is SuperExpression, isTrue);
-    expect(propertyAccess.operator, isNotNull);
-    expect(propertyAccess.operator.type, TokenType.PERIOD);
-    expect(propertyAccess.propertyName, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_this() {
-    Expression expression = parsePrimaryExpression('this');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var thisExpression = expression as ThisExpression;
-    expect(thisExpression.thisKeyword, isNotNull);
-  }
-
-  void test_parsePrimaryExpression_true() {
-    Expression expression = parsePrimaryExpression('true');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as BooleanLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, isTrue);
-  }
-
-  void test_parseRedirectingConstructorInvocation_named() {
-    var invocation = parseConstructorInitializer('this.a()')
-        as RedirectingConstructorInvocation;
-    assertNoErrors();
-    expect(invocation.argumentList, isNotNull);
-    expect(invocation.constructorName, isNotNull);
-    expect(invocation.thisKeyword, isNotNull);
-    expect(invocation.period, isNotNull);
-  }
-
-  void test_parseRedirectingConstructorInvocation_unnamed() {
-    var invocation = parseConstructorInitializer('this()')
-        as RedirectingConstructorInvocation;
-    assertNoErrors();
-    expect(invocation.argumentList, isNotNull);
-    expect(invocation.constructorName, isNull);
-    expect(invocation.thisKeyword, isNotNull);
-    expect(invocation.period, isNull);
-  }
-
-  void test_parseRelationalExpression_as_chained() {
-    AsExpression asExpression = parseExpression('x as Y as Z',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)]
-            : []);
-    expect(asExpression, isNotNull);
-    SimpleIdentifier identifier = asExpression.expression;
-    expect(identifier.name, 'x');
-    expect(asExpression.asOperator, isNotNull);
-    TypeName typeName = asExpression.type;
-    expect(typeName.name.name, 'Y');
-  }
-
-  void test_parseRelationalExpression_as_functionType_noReturnType() {
-    Expression expression = parseRelationalExpression('x as Function(int)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var asExpression = expression as AsExpression;
-    expect(asExpression.expression, isNotNull);
-    expect(asExpression.asOperator, isNotNull);
-    expect(asExpression.type, isGenericFunctionType);
-  }
-
-  void test_parseRelationalExpression_as_functionType_returnType() {
-    Expression expression =
-        parseRelationalExpression('x as String Function(int)');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var asExpression = expression as AsExpression;
-    expect(asExpression.expression, isNotNull);
-    expect(asExpression.asOperator, isNotNull);
-    expect(asExpression.type, isGenericFunctionType);
-  }
-
-  void test_parseRelationalExpression_as_generic() {
-    Expression expression = parseRelationalExpression('x as C<D>');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var asExpression = expression as AsExpression;
-    expect(asExpression.expression, isNotNull);
-    expect(asExpression.asOperator, isNotNull);
-    expect(asExpression.type, isTypeName);
-  }
-
-  void test_parseRelationalExpression_as_simple() {
-    Expression expression = parseRelationalExpression('x as Y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var asExpression = expression as AsExpression;
-    expect(asExpression.expression, isNotNull);
-    expect(asExpression.asOperator, isNotNull);
-    expect(asExpression.type, isTypeName);
-  }
-
-  void test_parseRelationalExpression_as_simple_function() {
-    Expression expression = parseRelationalExpression('x as Function');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var asExpression = expression as AsExpression;
-    expect(asExpression.expression, isNotNull);
-    expect(asExpression.asOperator, isNotNull);
-    expect(asExpression.type, isTypeName);
-  }
-
-  void test_parseRelationalExpression_is() {
-    Expression expression = parseRelationalExpression('x is y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var isExpression = expression as IsExpression;
-    expect(isExpression.expression, isNotNull);
-    expect(isExpression.isOperator, isNotNull);
-    expect(isExpression.notOperator, isNull);
-    expect(isExpression.type, isNotNull);
-  }
-
-  void test_parseRelationalExpression_is_chained() {
-    IsExpression isExpression = parseExpression('x is Y is! Z',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 2)]
-            : []);
-    expect(isExpression, isNotNull);
-    SimpleIdentifier identifier = isExpression.expression;
-    expect(identifier.name, 'x');
-    expect(isExpression.isOperator, isNotNull);
-    TypeName typeName = isExpression.type;
-    expect(typeName.name.name, 'Y');
-  }
-
-  void test_parseRelationalExpression_isNot() {
-    Expression expression = parseRelationalExpression('x is! y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var isExpression = expression as IsExpression;
-    expect(isExpression.expression, isNotNull);
-    expect(isExpression.isOperator, isNotNull);
-    expect(isExpression.notOperator, isNotNull);
-    expect(isExpression.type, isNotNull);
-  }
-
-  void test_parseRelationalExpression_normal() {
-    Expression expression = parseRelationalExpression('x < y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.LT);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseRelationalExpression_super() {
-    Expression expression = parseRelationalExpression('super < y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var binaryExpression = expression as BinaryExpression;
-    expect(binaryExpression.leftOperand, isNotNull);
-    expect(binaryExpression.operator, isNotNull);
-    expect(binaryExpression.operator.type, TokenType.LT);
-    expect(binaryExpression.rightOperand, isNotNull);
-  }
-
-  void test_parseRethrowExpression() {
-    RethrowExpression expression = parseRethrowExpression('rethrow');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.rethrowKeyword, isNotNull);
-  }
-
-  void test_parseShiftExpression_normal() {
-    BinaryExpression expression = parseShiftExpression('x << y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.leftOperand, isNotNull);
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.LT_LT);
-    expect(expression.rightOperand, isNotNull);
-  }
-
-  void test_parseShiftExpression_super() {
-    BinaryExpression expression = parseShiftExpression('super << y');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.leftOperand, isNotNull);
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.LT_LT);
-    expect(expression.rightOperand, isNotNull);
-  }
-
-  void test_parseSimpleIdentifier1_normalIdentifier() {
-    // TODO(brianwilkerson) Implement tests for this method.
-  }
-
-  void test_parseSimpleIdentifier_builtInIdentifier() {
-    String lexeme = "as";
-    SimpleIdentifier identifier = parseSimpleIdentifier(lexeme);
-    expect(identifier, isNotNull);
-    assertNoErrors();
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, lexeme);
-  }
-
-  void test_parseSimpleIdentifier_normalIdentifier() {
-    String lexeme = "foo";
-    SimpleIdentifier identifier = parseSimpleIdentifier(lexeme);
-    expect(identifier, isNotNull);
-    assertNoErrors();
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, lexeme);
-  }
-
-  void test_parseStringLiteral_adjacent() {
-    Expression expression = parseStringLiteral("'a' 'b'");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as AdjacentStrings;
-    NodeList<StringLiteral> strings = literal.strings;
-    expect(strings, hasLength(2));
-    StringLiteral firstString = strings[0];
-    StringLiteral secondString = strings[1];
-    expect((firstString as SimpleStringLiteral).value, "a");
-    expect((secondString as SimpleStringLiteral).value, "b");
-  }
-
-  void test_parseStringLiteral_endsWithInterpolation() {
-    Expression expression = parseStringLiteral(r"'x$y'");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var interpolation = expression as StringInterpolation;
-    expect(interpolation.elements, hasLength(3));
-    expect(interpolation.elements[0], isInterpolationString);
-    InterpolationString element0 = interpolation.elements[0];
-    expect(element0.value, 'x');
-    expect(interpolation.elements[1], isInterpolationExpression);
-    InterpolationExpression element1 = interpolation.elements[1];
-    expect(element1.leftBracket.lexeme, '\$');
-    expect(element1.expression, isSimpleIdentifier);
-    expect(element1.rightBracket, isNull);
-    expect(interpolation.elements[2], isInterpolationString);
-    InterpolationString element2 = interpolation.elements[2];
-    expect(element2.value, '');
-  }
-
-  void test_parseStringLiteral_interpolated() {
-    Expression expression = parseStringLiteral("'a \${b} c \$this d'");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression, isStringInterpolation);
-    StringInterpolation literal = expression;
-    NodeList<InterpolationElement> elements = literal.elements;
-    expect(elements, hasLength(5));
-    expect(elements[0] is InterpolationString, isTrue);
-    expect(elements[1] is InterpolationExpression, isTrue);
-    expect(elements[2] is InterpolationString, isTrue);
-    expect(elements[3] is InterpolationExpression, isTrue);
-    expect(elements[4] is InterpolationString, isTrue);
-    expect((elements[1] as InterpolationExpression).leftBracket.lexeme, '\${');
-    expect((elements[1] as InterpolationExpression).rightBracket.lexeme, '}');
-    expect((elements[3] as InterpolationExpression).leftBracket.lexeme, '\$');
-    expect((elements[3] as InterpolationExpression).rightBracket, isNull);
-  }
-
-  void test_parseStringLiteral_multiline_encodedSpace() {
-    Expression expression = parseStringLiteral("'''\\x20\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, " \na");
-  }
-
-  void test_parseStringLiteral_multiline_endsWithInterpolation() {
-    Expression expression = parseStringLiteral(r"'''x$y'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var interpolation = expression as StringInterpolation;
-    expect(interpolation.elements, hasLength(3));
-    expect(interpolation.elements[0], isInterpolationString);
-    InterpolationString element0 = interpolation.elements[0];
-    expect(element0.value, 'x');
-    expect(interpolation.elements[1], isInterpolationExpression);
-    InterpolationExpression element1 = interpolation.elements[1];
-    expect(element1.expression, isSimpleIdentifier);
-    expect(interpolation.elements[2], isInterpolationString);
-    InterpolationString element2 = interpolation.elements[2];
-    expect(element2.value, '');
-  }
-
-  void test_parseStringLiteral_multiline_escapedBackslash() {
-    Expression expression = parseStringLiteral("'''\\\\\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "\\\na");
-  }
-
-  void test_parseStringLiteral_multiline_escapedBackslash_raw() {
-    Expression expression = parseStringLiteral("r'''\\\\\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "\\\\\na");
-  }
-
-  void test_parseStringLiteral_multiline_escapedEolMarker() {
-    Expression expression = parseStringLiteral("'''\\\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "a");
-  }
-
-  void test_parseStringLiteral_multiline_escapedEolMarker_raw() {
-    Expression expression = parseStringLiteral("r'''\\\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "a");
-  }
-
-  void test_parseStringLiteral_multiline_escapedSpaceAndEolMarker() {
-    Expression expression = parseStringLiteral("'''\\ \\\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "a");
-  }
-
-  void test_parseStringLiteral_multiline_escapedSpaceAndEolMarker_raw() {
-    Expression expression = parseStringLiteral("r'''\\ \\\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "a");
-  }
-
-  void test_parseStringLiteral_multiline_escapedTab() {
-    Expression expression = parseStringLiteral("'''\\t\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "\t\na");
-  }
-
-  void test_parseStringLiteral_multiline_escapedTab_raw() {
-    Expression expression = parseStringLiteral("r'''\\t\na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "\\t\na");
-  }
-
-  void test_parseStringLiteral_multiline_quoteAfterInterpolation() {
-    Expression expression = parseStringLiteral(r"""'''$x'y'''""");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var interpolation = expression as StringInterpolation;
-    expect(interpolation.elements, hasLength(3));
-    expect(interpolation.elements[0], isInterpolationString);
-    InterpolationString element0 = interpolation.elements[0];
-    expect(element0.value, '');
-    expect(interpolation.elements[1], isInterpolationExpression);
-    InterpolationExpression element1 = interpolation.elements[1];
-    expect(element1.expression, isSimpleIdentifier);
-    expect(interpolation.elements[2], isInterpolationString);
-    InterpolationString element2 = interpolation.elements[2];
-    expect(element2.value, "'y");
-  }
-
-  void test_parseStringLiteral_multiline_startsWithInterpolation() {
-    Expression expression = parseStringLiteral(r"'''${x}y'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var interpolation = expression as StringInterpolation;
-    expect(interpolation.elements, hasLength(3));
-    expect(interpolation.elements[0], isInterpolationString);
-    InterpolationString element0 = interpolation.elements[0];
-    expect(element0.value, '');
-    expect(interpolation.elements[1], isInterpolationExpression);
-    InterpolationExpression element1 = interpolation.elements[1];
-    expect(element1.expression, isSimpleIdentifier);
-    expect(interpolation.elements[2], isInterpolationString);
-    InterpolationString element2 = interpolation.elements[2];
-    expect(element2.value, 'y');
-  }
-
-  void test_parseStringLiteral_multiline_twoSpaces() {
-    Expression expression = parseStringLiteral("'''  \na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "a");
-  }
-
-  void test_parseStringLiteral_multiline_twoSpaces_raw() {
-    Expression expression = parseStringLiteral("r'''  \na'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "a");
-  }
-
-  void test_parseStringLiteral_multiline_untrimmed() {
-    Expression expression = parseStringLiteral("''' a\nb'''");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, " a\nb");
-  }
-
-  void test_parseStringLiteral_quoteAfterInterpolation() {
-    Expression expression = parseStringLiteral(r"""'$x"'""");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var interpolation = expression as StringInterpolation;
-    expect(interpolation.elements, hasLength(3));
-    expect(interpolation.elements[0], isInterpolationString);
-    InterpolationString element0 = interpolation.elements[0];
-    expect(element0.value, '');
-    expect(interpolation.elements[1], isInterpolationExpression);
-    InterpolationExpression element1 = interpolation.elements[1];
-    expect(element1.expression, isSimpleIdentifier);
-    expect(interpolation.elements[2], isInterpolationString);
-    InterpolationString element2 = interpolation.elements[2];
-    expect(element2.value, '"');
-  }
-
-  void test_parseStringLiteral_single() {
-    Expression expression = parseStringLiteral("'a'");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var literal = expression as SimpleStringLiteral;
-    expect(literal.literal, isNotNull);
-    expect(literal.value, "a");
-  }
-
-  void test_parseStringLiteral_startsWithInterpolation() {
-    Expression expression = parseStringLiteral(r"'${x}y'");
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var interpolation = expression as StringInterpolation;
-    expect(interpolation.elements, hasLength(3));
-    expect(interpolation.elements[0], isInterpolationString);
-    InterpolationString element0 = interpolation.elements[0];
-    expect(element0.value, '');
-    expect(interpolation.elements[1], isInterpolationExpression);
-    InterpolationExpression element1 = interpolation.elements[1];
-    expect(element1.expression, isSimpleIdentifier);
-    expect(interpolation.elements[2], isInterpolationString);
-    InterpolationString element2 = interpolation.elements[2];
-    expect(element2.value, 'y');
-  }
-
-  void test_parseSuperConstructorInvocation_named() {
-    var invocation =
-        parseConstructorInitializer('super.a()') as SuperConstructorInvocation;
-    expect(invocation, isNotNull);
-    assertNoErrors();
-    expect(invocation.argumentList, isNotNull);
-    expect(invocation.constructorName, isNotNull);
-    expect(invocation.superKeyword, isNotNull);
-    expect(invocation.period, isNotNull);
-  }
-
-  void test_parseSuperConstructorInvocation_unnamed() {
-    var invocation =
-        parseConstructorInitializer('super()') as SuperConstructorInvocation;
-    assertNoErrors();
-    expect(invocation.argumentList, isNotNull);
-    expect(invocation.constructorName, isNull);
-    expect(invocation.superKeyword, isNotNull);
-    expect(invocation.period, isNull);
-  }
-
-  void test_parseSymbolLiteral_builtInIdentifier() {
-    SymbolLiteral literal = parseSymbolLiteral('#dynamic.static.abstract');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.poundSign, isNotNull);
-    List<Token> components = literal.components;
-    expect(components, hasLength(3));
-    expect(components[0].lexeme, "dynamic");
-    expect(components[1].lexeme, "static");
-    expect(components[2].lexeme, "abstract");
-  }
-
-  void test_parseSymbolLiteral_multiple() {
-    SymbolLiteral literal = parseSymbolLiteral('#a.b.c');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.poundSign, isNotNull);
-    List<Token> components = literal.components;
-    expect(components, hasLength(3));
-    expect(components[0].lexeme, "a");
-    expect(components[1].lexeme, "b");
-    expect(components[2].lexeme, "c");
-  }
-
-  void test_parseSymbolLiteral_operator() {
-    SymbolLiteral literal = parseSymbolLiteral('#==');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.poundSign, isNotNull);
-    List<Token> components = literal.components;
-    expect(components, hasLength(1));
-    expect(components[0].lexeme, "==");
-  }
-
-  void test_parseSymbolLiteral_single() {
-    SymbolLiteral literal = parseSymbolLiteral('#a');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.poundSign, isNotNull);
-    List<Token> components = literal.components;
-    expect(components, hasLength(1));
-    expect(components[0].lexeme, "a");
-  }
-
-  void test_parseSymbolLiteral_void() {
-    SymbolLiteral literal = parseSymbolLiteral('#void');
-    expect(literal, isNotNull);
-    assertNoErrors();
-    expect(literal.poundSign, isNotNull);
-    List<Token> components = literal.components;
-    expect(components, hasLength(1));
-    expect(components[0].lexeme, "void");
-  }
-
-  void test_parseThrowExpression() {
-    Expression expression = parseThrowExpression('throw x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var throwExpression = expression as ThrowExpression;
-    expect(throwExpression.throwKeyword, isNotNull);
-    expect(throwExpression.expression, isNotNull);
-  }
-
-  void test_parseThrowExpressionWithoutCascade() {
-    Expression expression = parseThrowExpressionWithoutCascade('throw x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    var throwExpression = expression as ThrowExpression;
-    expect(throwExpression.throwKeyword, isNotNull);
-    expect(throwExpression.expression, isNotNull);
-  }
-
-  void test_parseUnaryExpression_decrement_identifier_index() {
-    PrefixExpression expression = parseExpression('--a[0]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.MINUS_MINUS);
-    expect(expression.operand, isNotNull);
-    IndexExpression operand = expression.operand as IndexExpression;
-    expect(operand.realTarget, const TypeMatcher<SimpleIdentifier>());
-    expect(operand.index is IntegerLiteral, isTrue);
-  }
-
-  void test_parseUnaryExpression_decrement_normal() {
-    PrefixExpression expression = parseUnaryExpression('--x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.MINUS_MINUS);
-    expect(expression.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_decrement_super() {
-    PrefixExpression expression = parseUnaryExpression('--super');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.MINUS);
-    Expression innerExpression = expression.operand;
-    expect(innerExpression, isNotNull);
-    expect(innerExpression is PrefixExpression, isTrue);
-    PrefixExpression operand = innerExpression as PrefixExpression;
-    expect(operand.operator, isNotNull);
-    expect(operand.operator.type, TokenType.MINUS);
-    expect(operand.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_decrement_super_propertyAccess() {
-    PrefixExpression expression = parseUnaryExpression('--super.x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.MINUS_MINUS);
-    expect(expression.operand, isNotNull);
-    PropertyAccess operand = expression.operand as PropertyAccess;
-    expect(operand.target is SuperExpression, isTrue);
-    expect(operand.propertyName.name, "x");
-  }
-
-  void test_parseUnaryExpression_decrement_super_withComment() {
-    PrefixExpression expression = parseUnaryExpression('/* 0 */ --super');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.MINUS);
-    expect(expression.operator.precedingComments, isNotNull);
-    Expression innerExpression = expression.operand;
-    expect(innerExpression, isNotNull);
-    expect(innerExpression is PrefixExpression, isTrue);
-    PrefixExpression operand = innerExpression as PrefixExpression;
-    expect(operand.operator, isNotNull);
-    expect(operand.operator.type, TokenType.MINUS);
-    expect(operand.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_increment_identifier_index() {
-    PrefixExpression expression = parseExpression('++a[0]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.PLUS_PLUS);
-    expect(expression.operand, isNotNull);
-    IndexExpression operand = expression.operand as IndexExpression;
-    expect(operand.realTarget, const TypeMatcher<SimpleIdentifier>());
-    expect(operand.index is IntegerLiteral, isTrue);
-  }
-
-  void test_parseUnaryExpression_increment_normal() {
-    PrefixExpression expression = parseUnaryExpression('++x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.PLUS_PLUS);
-    expect(expression.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_increment_super_index() {
-    PrefixExpression expression = parseUnaryExpression('++super[0]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.PLUS_PLUS);
-    expect(expression.operand, isNotNull);
-    IndexExpression operand = expression.operand as IndexExpression;
-    expect(operand.realTarget is SuperExpression, isTrue);
-    expect(operand.index is IntegerLiteral, isTrue);
-  }
-
-  void test_parseUnaryExpression_increment_super_propertyAccess() {
-    PrefixExpression expression = parseUnaryExpression('++super.x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.PLUS_PLUS);
-    expect(expression.operand, isNotNull);
-    PropertyAccess operand = expression.operand as PropertyAccess;
-    expect(operand.target is SuperExpression, isTrue);
-    expect(operand.propertyName.name, "x");
-  }
-
-  void test_parseUnaryExpression_minus_identifier_index() {
-    PrefixExpression expression = parseExpression('-a[0]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.MINUS);
-    expect(expression.operand, isNotNull);
-    IndexExpression operand = expression.operand as IndexExpression;
-    expect(operand.realTarget, const TypeMatcher<SimpleIdentifier>());
-    expect(operand.index is IntegerLiteral, isTrue);
-  }
-
-  void test_parseUnaryExpression_minus_normal() {
-    PrefixExpression expression = parseUnaryExpression('-x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.MINUS);
-    expect(expression.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_minus_super() {
-    PrefixExpression expression = parseUnaryExpression('-super');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.MINUS);
-    expect(expression.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_not_normal() {
-    PrefixExpression expression = parseUnaryExpression('!x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.BANG);
-    expect(expression.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_not_super() {
-    PrefixExpression expression = parseUnaryExpression('!super');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.BANG);
-    expect(expression.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_tilda_normal() {
-    PrefixExpression expression = parseUnaryExpression('~x');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.TILDE);
-    expect(expression.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_tilda_super() {
-    PrefixExpression expression = parseUnaryExpression('~super');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.TILDE);
-    expect(expression.operand, isNotNull);
-  }
-
-  void test_parseUnaryExpression_tilde_identifier_index() {
-    PrefixExpression expression = parseExpression('~a[0]');
-    expect(expression, isNotNull);
-    assertNoErrors();
-    expect(expression.operator, isNotNull);
-    expect(expression.operator.type, TokenType.TILDE);
-    expect(expression.operand, isNotNull);
-    IndexExpression operand = expression.operand as IndexExpression;
-    expect(operand.realTarget, const TypeMatcher<SimpleIdentifier>());
-    expect(operand.index is IntegerLiteral, isTrue);
-  }
-}
-
-/// Tests of the analyzer parser based on [FormalParameterParserTestMixin].
-@reflectiveTest
-class FormalParameterParserTest extends ParserTestCase
-    with FormalParameterParserTestMixin {}
-
-/// The class [FormalParameterParserTestMixin] defines parser tests that test
-/// the parsing of formal parameters.
-mixin FormalParameterParserTestMixin implements AbstractParserTestCase {
-  void test_parseConstructorParameter_this() {
-    parseCompilationUnit('''
-class C {
-  final int field;
-  C(this.field);
-}''');
-  }
-
-  void test_parseConstructorParameter_this_Function() {
-    parseCompilationUnit('''
-class C {
-  final Object Function(int, double) field;
-  C(String Function(num, Object) this.field);
-}''');
-  }
-
-  void test_parseConstructorParameter_this_int() {
-    parseCompilationUnit('''
-class C {
-  final int field;
-  C(int this.field);
-}''');
-  }
-
-  void test_parseFormalParameter_covariant_final_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter =
-        parseFormalParameter('covariant final a : null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_final_normal() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter = parseFormalParameter('covariant final a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_final_positional() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter =
-        parseFormalParameter('covariant final a = null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_final_type_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter =
-        parseFormalParameter('covariant final A a : null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_final_type_normal() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter =
-        parseFormalParameter('covariant final A a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_final_type_positional() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter =
-        parseFormalParameter('covariant final A a = null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_type_function() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter =
-        parseFormalParameter('covariant String Function(int) a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isGenericFunctionType);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_type_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter =
-        parseFormalParameter('covariant A a : null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_type_normal() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter =
-        parseFormalParameter('covariant A<B<C>> a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_type_positional() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter =
-        parseFormalParameter('covariant A a = null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_var_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter =
-        parseFormalParameter('covariant var a : null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_var_normal() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter = parseFormalParameter('covariant var a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_covariant_var_positional() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter =
-        parseFormalParameter('covariant var a = null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNotNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameter_final_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter = parseFormalParameter('final a : null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_final_normal() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter = parseFormalParameter('final a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_final_positional() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter = parseFormalParameter('final a = null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameter_final_type_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter = parseFormalParameter('final A a : null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_final_type_normal() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter = parseFormalParameter('final A a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_final_type_positional() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter = parseFormalParameter('final A a = null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameter_type_function() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter =
-        parseFormalParameter('String Function(int) a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isGenericFunctionType);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_type_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter = parseFormalParameter('A a : null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_type_named_noDefault() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter = parseFormalParameter('A a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNull);
-    expect(defaultParameter.defaultValue, isNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_type_normal() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter = parseFormalParameter('A a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_type_positional() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter = parseFormalParameter('A a = null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameter_type_positional_noDefault() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter = parseFormalParameter('A a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNull);
-    expect(defaultParameter.defaultValue, isNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameter_var_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    FormalParameter parameter = parseFormalParameter('var a : null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isNamed, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseFormalParameter_var_normal() {
-    ParameterKind kind = ParameterKind.REQUIRED;
-    FormalParameter parameter = parseFormalParameter('var a', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isRequired, isTrue);
-  }
-
-  void test_parseFormalParameter_var_positional() {
-    ParameterKind kind = ParameterKind.POSITIONAL;
-    FormalParameter parameter = parseFormalParameter('var a = null', kind);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isDefaultFormalParameter);
-    DefaultFormalParameter defaultParameter = parameter;
-    SimpleFormalParameter simpleParameter =
-        defaultParameter.parameter as SimpleFormalParameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.requiredKeyword, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.isOptionalPositional, isTrue);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isOptionalPositional, isTrue);
-  }
-
-  void test_parseFormalParameterList_empty() {
-    FormalParameterList list = parseFormalParameterList('()');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(0));
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_named_multiple() {
-    FormalParameterList list =
-        parseFormalParameterList('({A a : 1, B b, C c : 3})');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.parameters, hasLength(3));
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_named_single() {
-    FormalParameterList list = parseFormalParameterList('({A a})');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.parameters, hasLength(1));
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_named_trailing_comma() {
-    FormalParameterList list = parseFormalParameterList('(A a, {B b,})');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.parameters, hasLength(2));
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_normal_multiple() {
-    FormalParameterList list = parseFormalParameterList('(A a, B b, C c)');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(3));
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_normal_named() {
-    FormalParameterList list = parseFormalParameterList('(A a, {B b})');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.parameters, hasLength(2));
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_normal_named_inFunctionType() {
-    FormalParameterList list =
-        parseFormalParameterList('(A, {B b})', inFunctionType: true);
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-    NodeList<FormalParameter> parameters = list.parameters;
-    expect(parameters, hasLength(2));
-
-    expect(parameters[0], isSimpleFormalParameter);
-    SimpleFormalParameter required = parameters[0];
-    expect(required.identifier, isNull);
-    expect(required.type, isTypeName);
-    expect((required.type as TypeName).name.name, 'A');
-
-    expect(parameters[1], isDefaultFormalParameter);
-    DefaultFormalParameter named = parameters[1];
-    expect(named.identifier, isNotNull);
-    expect(named.parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simple = named.parameter;
-    expect(simple.type, isTypeName);
-    expect((simple.type as TypeName).name.name, 'B');
-  }
-
-  void test_parseFormalParameterList_normal_positional() {
-    FormalParameterList list = parseFormalParameterList('(A a, [B b])');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.parameters, hasLength(2));
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_normal_single() {
-    FormalParameterList list = parseFormalParameterList('(A a)');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(1));
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_normal_single_Function() {
-    FormalParameterList list = parseFormalParameterList('(Function f)');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(1));
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_normal_single_trailing_comma() {
-    FormalParameterList list = parseFormalParameterList('(A a,)');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(1));
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_positional_multiple() {
-    FormalParameterList list =
-        parseFormalParameterList('([A a = null, B b, C c = null])');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.parameters, hasLength(3));
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_positional_single() {
-    FormalParameterList list = parseFormalParameterList('([A a = null])');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.parameters, hasLength(1));
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_positional_trailing_comma() {
-    FormalParameterList list = parseFormalParameterList('(A a, [B b,])');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNotNull);
-    expect(list.parameters, hasLength(2));
-    expect(list.rightDelimiter, isNotNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_prefixedType() {
-    FormalParameterList list = parseFormalParameterList('(io.File f)');
-    expect(list, isNotNull);
-    assertNoErrors();
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(1));
-    expect(list.parameters[0].toSource(), 'io.File f');
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_prefixedType_missingName() {
-    FormalParameterList list = parseFormalParameterList('(io.File)',
-        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1)]);
-    expect(list, isNotNull);
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(1));
-    // TODO(danrubel): Investigate and improve recovery of parameter type/name.
-    SimpleFormalParameter parameter = list.parameters[0];
-    expect(parameter.toSource(), 'io.File ');
-    expect(parameter.identifier.token.isSynthetic, isTrue);
-    TypeName type = parameter.type;
-    PrefixedIdentifier typeName = type.name;
-    expect(typeName.prefix.token.isSynthetic, isFalse);
-    expect(typeName.identifier.token.isSynthetic, isFalse);
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_prefixedType_partial() {
-    FormalParameterList list = parseFormalParameterList('(io.)', errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_TYPE_NAME
-              : ParserErrorCode.MISSING_IDENTIFIER,
-          4,
-          1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
-    ]);
-    expect(list, isNotNull);
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(1));
-    // TODO(danrubel): Investigate and improve recovery of parameter type/name.
-    SimpleFormalParameter parameter = list.parameters[0];
-    expect(parameter.toSource(), 'io. ');
-    expect(parameter.identifier.token.isSynthetic, isTrue);
-    TypeName type = parameter.type;
-    PrefixedIdentifier typeName = type.name;
-    expect(typeName.prefix.token.isSynthetic, isFalse);
-    expect(typeName.identifier.token.isSynthetic, isTrue);
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseFormalParameterList_prefixedType_partial2() {
-    FormalParameterList list = parseFormalParameterList('(io.,a)', errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.EXPECTED_TYPE_NAME
-              : ParserErrorCode.MISSING_IDENTIFIER,
-          4,
-          1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
-    ]);
-    expect(list, isNotNull);
-    expect(list.leftParenthesis, isNotNull);
-    expect(list.leftDelimiter, isNull);
-    expect(list.parameters, hasLength(2));
-    expect(list.parameters[0].toSource(), 'io. ');
-    expect(list.parameters[1].toSource(), 'a');
-    expect(list.rightDelimiter, isNull);
-    expect(list.rightParenthesis, isNotNull);
-  }
-
-  void test_parseNormalFormalParameter_field_const_noType() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('const this.a',
-        errorCodes:
-            usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
-    expect(parameter, isNotNull);
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNotNull);
-    expect(fieldParameter.type, isNull);
-    expect(fieldParameter.identifier, isNotNull);
-    expect(fieldParameter.parameters, isNull);
-  }
-
-  void test_parseNormalFormalParameter_field_const_type() {
-    NormalFormalParameter parameter = parseNormalFormalParameter(
-        'const A this.a',
-        errorCodes:
-            usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
-    expect(parameter, isNotNull);
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNotNull);
-    expect(fieldParameter.type, isNotNull);
-    expect(fieldParameter.identifier, isNotNull);
-    expect(fieldParameter.parameters, isNull);
-  }
-
-  void test_parseNormalFormalParameter_field_final_noType() {
-    NormalFormalParameter parameter =
-        parseNormalFormalParameter('final this.a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNotNull);
-    expect(fieldParameter.type, isNull);
-    expect(fieldParameter.identifier, isNotNull);
-    expect(fieldParameter.parameters, isNull);
-  }
-
-  void test_parseNormalFormalParameter_field_final_type() {
-    NormalFormalParameter parameter =
-        parseNormalFormalParameter('final A this.a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNotNull);
-    expect(fieldParameter.type, isNotNull);
-    expect(fieldParameter.identifier, isNotNull);
-    expect(fieldParameter.parameters, isNull);
-  }
-
-  void test_parseNormalFormalParameter_field_function_nested() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('this.a(B b)');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNull);
-    expect(fieldParameter.type, isNull);
-    expect(fieldParameter.identifier, isNotNull);
-    FormalParameterList parameterList = fieldParameter.parameters;
-    expect(parameterList, isNotNull);
-    expect(parameterList.parameters, hasLength(1));
-  }
-
-  void test_parseNormalFormalParameter_field_function_noNested() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('this.a()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNull);
-    expect(fieldParameter.type, isNull);
-    expect(fieldParameter.identifier, isNotNull);
-    FormalParameterList parameterList = fieldParameter.parameters;
-    expect(parameterList, isNotNull);
-    expect(parameterList.parameters, hasLength(0));
-  }
-
-  void test_parseNormalFormalParameter_field_function_withDocComment() {
-    var parameter = parseNormalFormalParameter('/// Doc\nthis.f()');
-    expectCommentText(parameter.documentationComment, '/// Doc');
-  }
-
-  void test_parseNormalFormalParameter_field_noType() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('this.a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNull);
-    expect(fieldParameter.type, isNull);
-    expect(fieldParameter.identifier, isNotNull);
-    expect(fieldParameter.parameters, isNull);
-  }
-
-  void test_parseNormalFormalParameter_field_type() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('A this.a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNull);
-    expect(fieldParameter.type, isNotNull);
-    expect(fieldParameter.identifier, isNotNull);
-    expect(fieldParameter.parameters, isNull);
-  }
-
-  void test_parseNormalFormalParameter_field_var() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('var this.a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFieldFormalParameter);
-    FieldFormalParameter fieldParameter = parameter;
-    expect(fieldParameter.keyword, isNotNull);
-    expect(fieldParameter.type, isNull);
-    expect(fieldParameter.identifier, isNotNull);
-    expect(fieldParameter.parameters, isNull);
-  }
-
-  void test_parseNormalFormalParameter_field_withDocComment() {
-    var parameter = parseNormalFormalParameter('/// Doc\nthis.a');
-    expectCommentText(parameter.documentationComment, '/// Doc');
-  }
-
-  void test_parseNormalFormalParameter_function_named() {
-    ParameterKind kind = ParameterKind.NAMED;
-    var defaultParameter =
-        parseFormalParameter('a() : null', kind) as DefaultFormalParameter;
-    var functionParameter =
-        defaultParameter.parameter as FunctionTypedFormalParameter;
-    assertNoErrors();
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.isNamed, isTrue);
-    expect(functionParameter.question, isNull);
-    expect(defaultParameter.separator, isNotNull);
-    expect(defaultParameter.defaultValue, isNotNull);
-    expect(defaultParameter.isNamed, isTrue);
-  }
-
-  void test_parseNormalFormalParameter_function_noType() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('a()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNull);
-  }
-
-  void test_parseNormalFormalParameter_function_noType_covariant() {
-    NormalFormalParameter parameter =
-        parseNormalFormalParameter('covariant a()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.covariantKeyword, isNotNull);
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNull);
-  }
-
-  void test_parseNormalFormalParameter_function_noType_typeParameters() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('a<E>()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.returnType, isNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNotNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNull);
-  }
-
-  void test_parseNormalFormalParameter_function_type() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('A a()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.returnType, isNotNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNull);
-  }
-
-  void test_parseNormalFormalParameter_function_type_typeParameters() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('A a<E>()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.returnType, isNotNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNotNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNull);
-  }
-
-  void test_parseNormalFormalParameter_function_typeVoid_covariant() {
-    NormalFormalParameter parameter =
-        parseNormalFormalParameter('covariant void a()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.covariantKeyword, isNotNull);
-    expect(functionParameter.returnType, isNotNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNull);
-  }
-
-  void test_parseNormalFormalParameter_function_void() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('void a()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.returnType, isNotNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNull);
-  }
-
-  void test_parseNormalFormalParameter_function_void_typeParameters() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('void a<E>()');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isFunctionTypedFormalParameter);
-    FunctionTypedFormalParameter functionParameter = parameter;
-    expect(functionParameter.returnType, isNotNull);
-    expect(functionParameter.identifier, isNotNull);
-    expect(functionParameter.typeParameters, isNotNull);
-    expect(functionParameter.parameters, isNotNull);
-    expect(functionParameter.question, isNull);
-  }
-
-  void test_parseNormalFormalParameter_function_withDocComment() {
-    var parameter = parseFormalParameter('/// Doc\nf()', ParameterKind.REQUIRED)
-        as FunctionTypedFormalParameter;
-    expectCommentText(parameter.documentationComment, '/// Doc');
-  }
-
-  void test_parseNormalFormalParameter_simple_const_noType() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('const a',
-        errorCodes:
-            usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
-    expect(parameter, isNotNull);
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-  }
-
-  void test_parseNormalFormalParameter_simple_const_type() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('const A a',
-        errorCodes:
-            usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
-    expect(parameter, isNotNull);
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-  }
-
-  void test_parseNormalFormalParameter_simple_final_noType() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('final a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-  }
-
-  void test_parseNormalFormalParameter_simple_final_type() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('final A a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.keyword, isNotNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-  }
-
-  void test_parseNormalFormalParameter_simple_noName() {
-    NormalFormalParameter parameter =
-        parseNormalFormalParameter('a', inFunctionType: true);
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.identifier, isNull);
-  }
-
-  void test_parseNormalFormalParameter_simple_noType() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-  }
-
-  void test_parseNormalFormalParameter_simple_noType_namedCovariant() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('covariant');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.covariantKeyword, isNull);
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNull);
-    expect(simpleParameter.identifier, isNotNull);
-  }
-
-  void test_parseNormalFormalParameter_simple_type() {
-    NormalFormalParameter parameter = parseNormalFormalParameter('A a');
-    expect(parameter, isNotNull);
-    assertNoErrors();
-    expect(parameter, isSimpleFormalParameter);
-    SimpleFormalParameter simpleParameter = parameter;
-    expect(simpleParameter.keyword, isNull);
-    expect(simpleParameter.type, isNotNull);
-    expect(simpleParameter.identifier, isNotNull);
-  }
-}
-
-@reflectiveTest
-class NonErrorParserTest extends ParserTestCase {
-  void test_annotationOnEnumConstant_first() {
-    createParser("enum E { @override C }");
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-  }
-
-  void test_annotationOnEnumConstant_middle() {
-    createParser("enum E { C, @override D, E }");
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-  }
-
-  void test_staticMethod_notParsingFunctionBodies() {
-    ParserTestCase.parseFunctionBodies = false;
-    try {
-      createParser('class C { static void m() {} }');
-      CompilationUnit unit = parser.parseCompilationUnit2();
-      expectNotNullIfNoErrors(unit);
-      assertNoErrors();
-    } finally {
-      ParserTestCase.parseFunctionBodies = true;
-    }
-  }
-}
-
-/// Implementation of [AbstractParserTestCase] specialized for testing the
-/// analyzer parser.
-class ParserTestCase with ParserTestHelpers implements AbstractParserTestCase {
-  /// A flag indicating whether parser is to parse function bodies.
-  static bool parseFunctionBodies = true;
-
-  @override
-  bool allowNativeClause = true;
-
-  /// A flag indicating whether parser is to parse async.
-  bool parseAsync = true;
-
-  /// A flag indicating whether the parser should parse instance creation
-  /// expressions that lack either the `new` or `const` keyword.
-  bool enableOptionalNewAndConst = false;
-
-  /// A flag indicating whether the parser should parse mixin declarations.
-  /// https://github.com/dart-lang/language/issues/12
-  bool isMixinSupportEnabled = false;
-
-  /// A flag indicating whether the parser is to parse part-of directives that
-  /// specify a URI rather than a library name.
-  bool enableUriInPartOf = false;
-
-  @override
-  GatheringErrorListener listener;
-
-  /// The parser used by the test.
-  ///
-  /// This field is typically initialized by invoking [createParser].
-  @override
-  Parser parser;
-
-  @override
-  bool get usingFastaParser => Parser.useFasta;
-
-  @override
-  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
-    listener.assertErrorsWithCodes(expectedErrorCodes);
-  }
-
-  @override
-  void assertNoErrors() {
-    listener.assertNoErrors();
-  }
-
-  /// Create the [parser] and [listener] used by a test. The [parser] will be
-  /// prepared to parse the tokens scanned from the given [content].
-  @override
-  void createParser(
-    String content, {
-    int expectedEndOffset,
-    LanguageVersionToken languageVersion,
-    FeatureSet featureSet,
-  }) {
-    Source source = TestSource();
-    listener = GatheringErrorListener();
-
-    ScannerResult result = scanString(content, includeComments: true);
-    listener.setLineInfo(source, result.lineStarts);
-
-    parser = Parser(
-      source,
-      listener,
-      featureSet: featureSet,
-    );
-    parser.allowNativeClause = allowNativeClause;
-    parser.parseFunctionBodies = parseFunctionBodies;
-    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    parser.currentToken = result.tokens;
-  }
-
-  @override
-  ExpectedError expectedError(ErrorCode code, int offset, int length) =>
-      ExpectedError(code, offset, length);
-
-  @override
-  void expectNotNullIfNoErrors(Object result) {
-    if (!listener.hasErrors) {
-      expect(result, isNotNull);
-    }
-  }
-
-  @override
-  Expression parseAdditiveExpression(String code) {
-    createParser(code);
-    return parser.parseAdditiveExpression();
-  }
-
-  @override
-  Expression parseAssignableExpression(String code, bool primaryAllowed) {
-    createParser(code);
-    return parser.parseAssignableExpression(primaryAllowed);
-  }
-
-  @override
-  Expression parseAssignableSelector(String code, bool optional,
-      {bool allowConditional = true}) {
-    if (usingFastaParser) {
-      if (optional) {
-        if (code.isEmpty) {
-          createParser('foo');
-        } else {
-          createParser('(foo)$code');
-        }
-      } else {
-        createParser('foo$code');
-      }
-      return parser.parseExpression2();
-    } else {
-      Expression prefix =
-          astFactory.simpleIdentifier(StringToken(TokenType.STRING, 'foo', 0));
-      createParser(code);
-      return parser.parseAssignableSelector(prefix, optional,
-          allowConditional: allowConditional);
-    }
-  }
-
-  @override
-  AwaitExpression parseAwaitExpression(String code) {
-    if (usingFastaParser) {
-      createParser('() async => $code');
-      var function = parser.parseExpression2() as FunctionExpression;
-      return (function.body as ExpressionFunctionBody).expression;
-    } else {
-      createParser(code);
-      return parser.parseAwaitExpression();
-    }
-  }
-
-  @override
-  Expression parseBitwiseAndExpression(String code) {
-    createParser(code);
-    return parser.parseBitwiseAndExpression();
-  }
-
-  @override
-  Expression parseBitwiseOrExpression(String code) {
-    createParser(code);
-    return parser.parseBitwiseOrExpression();
-  }
-
-  @override
-  Expression parseBitwiseXorExpression(String code) {
-    createParser(code);
-    return parser.parseBitwiseXorExpression();
-  }
-
-  @override
-  Expression parseCascadeSection(String code) {
-    if (usingFastaParser) {
-      var statement = parseStatement('null$code;') as ExpressionStatement;
-      var cascadeExpression = statement.expression as CascadeExpression;
-      return cascadeExpression.cascadeSections.first;
-    } else {
-      createParser(code);
-      return parser.parseCascadeSection();
-    }
-  }
-
-  @override
-  CommentReference parseCommentReference(
-      String referenceSource, int sourceOffset) {
-    String padding = ' '.padLeft(sourceOffset - 4, 'a');
-    String source = '/**$padding[$referenceSource] */ class C { }';
-    CompilationUnit unit = parseCompilationUnit(source);
-    ClassDeclaration clazz = unit.declarations[0];
-    Comment comment = clazz.documentationComment;
-    List<CommentReference> references = comment.references;
-    if (references.isEmpty) {
-      return null;
-    } else {
-      expect(references, hasLength(1));
-      return references[0];
-    }
-  }
-
-  /// Parse the given source as a compilation unit.
-  ///
-  /// @param source the source to be parsed
-  /// @param errorCodes the error codes of the errors that are expected to be
-  ///          found
-  /// @return the compilation unit that was parsed
-  /// @throws Exception if the source could not be parsed, if the compilation
-  ///           errors in the source do not match those that are expected, or if
-  ///           the result would have been `null`
-  @override
-  CompilationUnit parseCompilationUnit(String content,
-      {List<ErrorCode> codes, List<ExpectedError> errors}) {
-    Source source = TestSource();
-    GatheringErrorListener listener = GatheringErrorListener();
-
-    ScannerResult result = scanString(content, includeComments: true);
-    listener.setLineInfo(source, result.lineStarts);
-
-    Parser parser = Parser(
-      source,
-      listener,
-      featureSet: FeatureSet.forTesting(),
-    );
-    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
-    expect(unit, isNotNull);
-    if (codes != null) {
-      listener.assertErrorsWithCodes(codes);
-    } else if (errors != null) {
-      listener.assertErrors(errors);
-    } else {
-      listener.assertNoErrors();
-    }
-    return unit;
-  }
-
-  /// Parse the given [content] as a compilation unit.
-  CompilationUnit parseCompilationUnit2(String content,
-      {AnalysisErrorListener listener}) {
-    Source source = NonExistingSource.unknown;
-    listener ??= AnalysisErrorListener.NULL_LISTENER;
-
-    ScannerResult result = scanString(content, includeComments: true);
-
-    Parser parser = Parser(
-      source,
-      listener,
-      featureSet: FeatureSet.forTesting(),
-    );
-    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
-    unit.lineInfo = LineInfo(result.lineStarts);
-    return unit;
-  }
-
-  @override
-  ConditionalExpression parseConditionalExpression(String code) {
-    createParser(code);
-    return parser.parseConditionalExpression();
-  }
-
-  @override
-  Expression parseConstExpression(String code) {
-    createParser(code);
-    return parser.parseConstExpression();
-  }
-
-  @override
-  ConstructorInitializer parseConstructorInitializer(String code) {
-    createParser('class __Test { __Test() : $code; }');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    var clazz = unit.declarations[0] as ClassDeclaration;
-    var constructor = clazz.members[0] as ConstructorDeclaration;
-    return constructor.initializers.single;
-  }
-
-  @override
-  CompilationUnit parseDirectives(String source,
-      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
-    createParser(source);
-    CompilationUnit unit = parser.parseDirectives2();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(0));
-    listener.assertErrorsWithCodes(errorCodes);
-    return unit;
-  }
-
-  @override
-  BinaryExpression parseEqualityExpression(String code) {
-    createParser(code);
-    return parser.parseEqualityExpression();
-  }
-
-  /// Parse the given [source] as an expression. If a list of error [codes] is
-  /// provided, then assert that the produced errors matches the list.
-  /// Otherwise, if a list of [errors] is provided, the assert that the produced
-  /// errors matches the list. Otherwise, assert that there are no errors.
-  @override
-  Expression parseExpression(String source,
-      {List<ErrorCode> codes,
-      List<ExpectedError> errors,
-      int expectedEndOffset}) {
-    createParser(source, expectedEndOffset: expectedEndOffset);
-    Expression expression = parser.parseExpression2();
-    expectNotNullIfNoErrors(expression);
-    if (codes != null) {
-      listener.assertErrorsWithCodes(codes);
-    } else if (errors != null) {
-      listener.assertErrors(errors);
-    } else {
-      assertNoErrors();
-    }
-    return expression;
-  }
-
-  @override
-  List<Expression> parseExpressionList(String code) {
-    if (usingFastaParser) {
-      createParser('[$code]');
-      return (parser.parseExpression2() as ListLiteral)
-          .elements
-          .toList()
-          .cast<Expression>();
-    } else {
-      createParser(code);
-      return parser.parseExpressionList();
-    }
-  }
-
-  @override
-  Expression parseExpressionWithoutCascade(String code) {
-    createParser(code);
-    return parser.parseExpressionWithoutCascade();
-  }
-
-  @override
-  FormalParameter parseFormalParameter(String code, ParameterKind kind,
-      {List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
-    if (usingFastaParser) {
-      String parametersCode;
-      if (kind == ParameterKind.REQUIRED) {
-        parametersCode = '($code)';
-      } else if (kind == ParameterKind.POSITIONAL) {
-        parametersCode = '([$code])';
-      } else if (kind == ParameterKind.NAMED) {
-        parametersCode = '({$code})';
-      } else {
-        fail('$kind');
-      }
-      FormalParameterList list = parseFormalParameterList(parametersCode,
-          inFunctionType: false, errorCodes: errorCodes);
-      return list.parameters.single;
-    } else {
-      createParser(code);
-      FormalParameter parameter = parser.parseFormalParameter(kind);
-      assertErrorsWithCodes(errorCodes);
-      return parameter;
-    }
-  }
-
-  @override
-  FormalParameterList parseFormalParameterList(String code,
-      {bool inFunctionType = false,
-      List<ErrorCode> errorCodes = const <ErrorCode>[],
-      List<ExpectedError> errors}) {
-    createParser(code);
-    FormalParameterList list =
-        parser.parseFormalParameterList(inFunctionType: inFunctionType);
-    if (errors != null) {
-      errorCodes = errors.map((e) => e.code).toList();
-    }
-    assertErrorsWithCodes(errorCodes);
-    return list;
-  }
-
-  /// Parses a single top level member of a compilation unit (other than a
-  /// directive), including any comment and/or metadata that precedes it.
-  @override
-  CompilationUnitMember parseFullCompilationUnitMember() => usingFastaParser
-      ? parser.parseCompilationUnit2().declarations.first
-      : parser.parseCompilationUnitMember(parser.parseCommentAndMetadata());
-
-  @override
-  Directive parseFullDirective() {
-    return usingFastaParser
-        ? (parser as ParserAdapter).parseTopLevelDeclaration(true)
-        : parser.parseDirective(parser.parseCommentAndMetadata());
-  }
-
-  @override
-  FunctionExpression parseFunctionExpression(String code) {
-    createParser(code);
-    return parser.parseFunctionExpression();
-  }
-
-  @override
-  InstanceCreationExpression parseInstanceCreationExpression(
-      String code, Token newToken) {
-    if (usingFastaParser) {
-      createParser('$newToken $code');
-      return parser.parseExpression2();
-    } else {
-      createParser(code);
-      return parser.parseInstanceCreationExpression(newToken);
-    }
-  }
-
-  @override
-  ListLiteral parseListLiteral(
-      Token token, String typeArgumentsCode, String code) {
-    if (usingFastaParser) {
-      String sc = '';
-      if (token != null) {
-        sc += token.lexeme + ' ';
-      }
-      if (typeArgumentsCode != null) {
-        sc += typeArgumentsCode;
-      }
-      sc += code;
-      createParser(sc);
-      return parser.parseExpression2();
-    } else {
-      TypeArgumentList typeArguments;
-      if (typeArgumentsCode != null) {
-        createParser(typeArgumentsCode);
-        typeArguments = parser.parseTypeArgumentList();
-      }
-      createParser(code);
-      return parser.parseListLiteral(token, typeArguments);
-    }
-  }
-
-  @override
-  TypedLiteral parseListOrMapLiteral(Token modifier, String code) {
-    if (usingFastaParser) {
-      String literalCode = modifier != null ? '$modifier $code' : code;
-      createParser(literalCode);
-      return parser.parseExpression2() as TypedLiteral;
-    } else {
-      createParser(code);
-      return parser.parseListOrMapLiteral(modifier);
-    }
-  }
-
-  @override
-  Expression parseLogicalAndExpression(String code) {
-    createParser(code);
-    return parser.parseLogicalAndExpression();
-  }
-
-  @override
-  Expression parseLogicalOrExpression(String code) {
-    createParser(code);
-    return parser.parseLogicalOrExpression();
-  }
-
-  @override
-  SetOrMapLiteral parseMapLiteral(
-      Token token, String typeArgumentsCode, String code) {
-    if (usingFastaParser) {
-      String sc = '';
-      if (token != null) {
-        sc += token.lexeme + ' ';
-      }
-      if (typeArgumentsCode != null) {
-        sc += typeArgumentsCode;
-      }
-      sc += code;
-      createParser(sc);
-      return parser.parseExpression2() as SetOrMapLiteral;
-    } else {
-      TypeArgumentList typeArguments;
-      if (typeArgumentsCode != null) {
-        createParser(typeArgumentsCode);
-        typeArguments = parser.parseTypeArgumentList();
-      }
-      createParser(code);
-      return parser.parseMapLiteral(token, typeArguments);
-    }
-  }
-
-  @override
-  MapLiteralEntry parseMapLiteralEntry(String code) {
-    if (usingFastaParser) {
-      var mapLiteral = parseMapLiteral(null, null, '{ $code }');
-      return mapLiteral.elements.single;
-    } else {
-      createParser(code);
-      return parser.parseMapLiteralEntry();
-    }
-  }
-
-  @override
-  Expression parseMultiplicativeExpression(String code) {
-    createParser(code);
-    return parser.parseMultiplicativeExpression();
-  }
-
-  @override
-  InstanceCreationExpression parseNewExpression(String code) {
-    createParser(code);
-    return parser.parseNewExpression();
-  }
-
-  @override
-  NormalFormalParameter parseNormalFormalParameter(String code,
-      {bool inFunctionType = false,
-      List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
-    if (usingFastaParser) {
-      FormalParameterList list = parseFormalParameterList('($code)',
-          inFunctionType: inFunctionType, errorCodes: errorCodes);
-      return list.parameters.single;
-    } else {
-      createParser(code);
-      FormalParameter parameter =
-          parser.parseNormalFormalParameter(inFunctionType: inFunctionType);
-      assertErrorsWithCodes(errorCodes);
-      return parameter;
-    }
-  }
-
-  @override
-  Expression parsePostfixExpression(String code) {
-    createParser(code);
-    return parser.parsePostfixExpression();
-  }
-
-  @override
-  Identifier parsePrefixedIdentifier(String code) {
-    createParser(code);
-    return parser.parsePrefixedIdentifier();
-  }
-
-  @override
-  Expression parsePrimaryExpression(String code,
-      {int expectedEndOffset, List<ExpectedError> errors}) {
-    createParser(code);
-    var expression = parser.parsePrimaryExpression();
-    if (errors != null) {
-      listener.assertErrors(errors);
-    }
-    return expression;
-  }
-
-  @override
-  Expression parseRelationalExpression(String code) {
-    createParser(code);
-    return parser.parseRelationalExpression();
-  }
-
-  @override
-  RethrowExpression parseRethrowExpression(String code) {
-    createParser(code);
-    return parser.parseRethrowExpression();
-  }
-
-  @override
-  BinaryExpression parseShiftExpression(String code) {
-    createParser(code);
-    return parser.parseShiftExpression();
-  }
-
-  @override
-  SimpleIdentifier parseSimpleIdentifier(String code) {
-    createParser(code);
-    return parser.parseSimpleIdentifier();
-  }
-
-  /// Parse the given [content] as a statement. If
-  /// [enableLazyAssignmentOperators] is `true`, then lazy assignment operators
-  /// should be enabled.
-  @override
-  Statement parseStatement(String content, {int expectedEndOffset}) {
-    Source source = TestSource();
-    listener = GatheringErrorListener();
-
-    ScannerResult result = scanString(content, includeComments: true);
-    listener.setLineInfo(source, result.lineStarts);
-
-    Parser parser = Parser(
-      source,
-      listener,
-      featureSet: FeatureSet.forTesting(),
-    );
-    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    Statement statement = parser.parseStatement(result.tokens);
-    expect(statement, isNotNull);
-    return statement;
-  }
-
-  /// Parse the given source as a sequence of statements.
-  ///
-  /// @param source the source to be parsed
-  /// @param expectedCount the number of statements that are expected
-  /// @param errorCodes the error codes of the errors that are expected to be
-  ///          found
-  /// @return the statements that were parsed
-  /// @throws Exception if the source could not be parsed, if the number of
-  ///           statements does not match the expected count, if the compilation
-  ///           errors in the source do not match those that are expected, or if
-  ///           the result would have been `null`
-  List<Statement> parseStatements(String content, int expectedCount,
-      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
-    Source source = TestSource();
-    GatheringErrorListener listener = GatheringErrorListener();
-
-    ScannerResult result = scanString(content);
-    listener.setLineInfo(source, result.lineStarts);
-
-    Parser parser = Parser(
-      source,
-      listener,
-      featureSet: FeatureSet.forTesting(),
-    );
-    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
-    List<Statement> statements = parser.parseStatements(result.tokens);
-    expect(statements, hasLength(expectedCount));
-    listener.assertErrorsWithCodes(errorCodes);
-    return statements;
-  }
-
-  @override
-  Expression parseStringLiteral(String code) {
-    createParser(code);
-    return parser.parseStringLiteral();
-  }
-
-  @override
-  SymbolLiteral parseSymbolLiteral(String code) {
-    createParser(code);
-    return parser.parseSymbolLiteral();
-  }
-
-  @override
-  Expression parseThrowExpression(String code) {
-    createParser(code);
-    return parser.parseThrowExpression();
-  }
-
-  @override
-  Expression parseThrowExpressionWithoutCascade(String code) {
-    createParser(code);
-    return parser.parseThrowExpressionWithoutCascade();
-  }
-
-  @override
-  PrefixExpression parseUnaryExpression(String code) {
-    createParser(code);
-    return parser.parseUnaryExpression();
-  }
-
-  @override
-  VariableDeclarationList parseVariableDeclarationList(String code) {
-    if (usingFastaParser) {
-      var statement = parseStatement('$code;') as VariableDeclarationStatement;
-      return statement.variables;
-    } else {
-      createParser(code);
-      CommentAndMetadata commentAndMetadata = parser.parseCommentAndMetadata();
-      return parser
-          .parseVariableDeclarationListAfterMetadata(commentAndMetadata);
-    }
-  }
-
-  void setUp() {
-    parseFunctionBodies = true;
-  }
-}
-
-/// Helper methods that aid in parser tests.
-///
-/// Intended to be mixed in to parser test case classes.
-mixin ParserTestHelpers {
-  void expectCommentText(Comment comment, String expectedText) {
-    expect(comment.beginToken, same(comment.endToken));
-    expect(comment.beginToken.lexeme, expectedText);
-  }
-
-  void expectDottedName(DottedName name, List<String> expectedComponents) {
-    int count = expectedComponents.length;
-    NodeList<SimpleIdentifier> components = name.components;
-    expect(components, hasLength(count));
-    for (int i = 0; i < count; i++) {
-      SimpleIdentifier component = components[i];
-      expect(component, isNotNull);
-      expect(component.name, expectedComponents[i]);
-    }
-  }
-}
-
-/// Tests of the analyzer parser based on [RecoveryParserTestMixin].
-@reflectiveTest
-class RecoveryParserTest extends ParserTestCase with RecoveryParserTestMixin {}
-
-/// The class `RecoveryParserTest` defines parser tests that test the parsing of
-/// invalid code sequences to ensure that the correct recovery steps are taken
-/// in the parser.
-mixin RecoveryParserTestMixin implements AbstractParserTestCase {
-  void test_additiveExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("+ y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_additiveExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("+", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_additiveExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x +", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_additiveExpression_missing_RHS_super() {
-    BinaryExpression expression =
-        parseExpression("super +", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_additiveExpression_precedence_multiplicative_left() {
-    BinaryExpression expression = parseExpression("* +", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_additiveExpression_precedence_multiplicative_right() {
-    BinaryExpression expression = parseExpression("+ *", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_additiveExpression_super() {
-    BinaryExpression expression = parseExpression("super + +", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_assignableSelector() {
-    IndexExpression expression =
-        parseExpression("a.b[]", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    Expression index = expression.index;
-    expect(index, isSimpleIdentifier);
-    expect(index.isSynthetic, isTrue);
-  }
-
-  void test_assignmentExpression_missing_compound1() {
-    AssignmentExpression expression =
-        parseExpression("= y = 0", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    Expression syntheticExpression = expression.leftHandSide;
-    expect(syntheticExpression, isSimpleIdentifier);
-    expect(syntheticExpression.isSynthetic, isTrue);
-  }
-
-  void test_assignmentExpression_missing_compound2() {
-    AssignmentExpression expression =
-        parseExpression("x = = 0", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    Expression syntheticExpression =
-        (expression.rightHandSide as AssignmentExpression).leftHandSide;
-    expect(syntheticExpression, isSimpleIdentifier);
-    expect(syntheticExpression.isSynthetic, isTrue);
-  }
-
-  void test_assignmentExpression_missing_compound3() {
-    AssignmentExpression expression =
-        parseExpression("x = y =", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    Expression syntheticExpression =
-        (expression.rightHandSide as AssignmentExpression).rightHandSide;
-    expect(syntheticExpression, isSimpleIdentifier);
-    expect(syntheticExpression.isSynthetic, isTrue);
-  }
-
-  void test_assignmentExpression_missing_LHS() {
-    AssignmentExpression expression =
-        parseExpression("= 0", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftHandSide, isSimpleIdentifier);
-    expect(expression.leftHandSide.isSynthetic, isTrue);
-  }
-
-  void test_assignmentExpression_missing_RHS() {
-    AssignmentExpression expression =
-        parseExpression("x =", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftHandSide, isSimpleIdentifier);
-    expect(expression.rightHandSide.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseAndExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("& y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseAndExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("&", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseAndExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x &", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseAndExpression_missing_RHS_super() {
-    BinaryExpression expression =
-        parseExpression("super &", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseAndExpression_precedence_equality_left() {
-    BinaryExpression expression = parseExpression("== &&", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseAndExpression_precedence_equality_right() {
-    BinaryExpression expression = parseExpression("&& ==", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseAndExpression_super() {
-    BinaryExpression expression = parseExpression("super &  &", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseOrExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("| y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseOrExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("|", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseOrExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x |", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseOrExpression_missing_RHS_super() {
-    BinaryExpression expression =
-        parseExpression("super |", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseOrExpression_precedence_xor_left() {
-    BinaryExpression expression = parseExpression("^ |", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseOrExpression_precedence_xor_right() {
-    BinaryExpression expression = parseExpression("| ^", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseOrExpression_super() {
-    BinaryExpression expression = parseExpression("super |  |", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseXorExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("^ y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseXorExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("^", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseXorExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x ^", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseXorExpression_missing_RHS_super() {
-    BinaryExpression expression =
-        parseExpression("super ^", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_bitwiseXorExpression_precedence_and_left() {
-    BinaryExpression expression = parseExpression("& ^", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseXorExpression_precedence_and_right() {
-    BinaryExpression expression = parseExpression("^ &", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_bitwiseXorExpression_super() {
-    BinaryExpression expression = parseExpression("super ^  ^", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_classTypeAlias_withBody() {
-    parseCompilationUnit(r'''
-class A {}
-class B = Object with A {}''',
-        codes: usingFastaParser
-            // TODO(danrubel): Consolidate and improve error message.
-            ? [
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-                ParserErrorCode.EXPECTED_TOKEN
-              ]
-            : [ParserErrorCode.EXPECTED_TOKEN]);
-  }
-
-  void test_combinator_badIdentifier() {
-    createParser('import "/testB.dart" show @');
-    parser.parseCompilationUnit2();
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 0),
-            expectedError(
-                ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 27, 0),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 0)
-          ]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 26, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
-            expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 27, 1)
-          ]);
-  }
-
-  void test_combinator_missingIdentifier() {
-    createParser('import "/testB.dart" show ;');
-    parser.parseCompilationUnit2();
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1)]);
-  }
-
-  void test_conditionalExpression_missingElse() {
-    Expression expression =
-        parseExpression('x ? y :', codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expectNotNullIfNoErrors(expression);
-    expect(expression, isConditionalExpression);
-    ConditionalExpression conditionalExpression = expression;
-    expect(conditionalExpression.elseExpression, isSimpleIdentifier);
-    expect(conditionalExpression.elseExpression.isSynthetic, isTrue);
-  }
-
-  void test_conditionalExpression_missingThen() {
-    Expression expression =
-        parseExpression('x ? : z', codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expectNotNullIfNoErrors(expression);
-    expect(expression, isConditionalExpression);
-    ConditionalExpression conditionalExpression = expression;
-    expect(conditionalExpression.thenExpression, isSimpleIdentifier);
-    expect(conditionalExpression.thenExpression.isSynthetic, isTrue);
-  }
-
-  void test_conditionalExpression_super() {
-    parseExpression('x ? super : z', errors: [
-      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 4, 5)
-    ]);
-  }
-
-  void test_conditionalExpression_super2() {
-    parseExpression('x ? z : super', errors: [
-      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 8, 5)
-    ]);
-  }
-
-  void test_declarationBeforeDirective() {
-    CompilationUnit unit = parseCompilationUnit(
-        "class foo { } import 'bar.dart';",
-        codes: [ParserErrorCode.DIRECTIVE_AFTER_DECLARATION]);
-    expect(unit.directives, hasLength(1));
-    expect(unit.declarations, hasLength(1));
-    ClassDeclaration classDecl = unit.childEntities.first;
-    expect(classDecl, isNotNull);
-    expect(classDecl.name.name, 'foo');
-  }
-
-  void test_equalityExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("== y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_equalityExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("==", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_equalityExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x ==", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_equalityExpression_missing_RHS_super() {
-    BinaryExpression expression = parseExpression("super ==",
-        codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_equalityExpression_precedence_relational_left() {
-    BinaryExpression expression = parseExpression("is ==", codes: [
-      ParserErrorCode.EXPECTED_TYPE_NAME,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    if (!usingFastaParser) {
-      expect(expression.leftOperand, isIsExpression);
-    }
-  }
-
-  void test_equalityExpression_precedence_relational_right() {
-    BinaryExpression expression = parseExpression("== is", codes: [
-      ParserErrorCode.EXPECTED_TYPE_NAME,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.rightOperand, isIsExpression);
-  }
-
-  void test_equalityExpression_super() {
-    BinaryExpression expression = parseExpression("super ==  ==", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_equalityExpression_superRHS() {
-    parseExpression("1 == super", errors: [
-      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 5, 5)
-    ]);
-  }
-
-  void test_expressionList_multiple_end() {
-    List<Expression> result = parseExpressionList(', 2, 3, 4');
-    expectNotNullIfNoErrors(result);
-    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-    listener.assertErrorsWithCodes([ParserErrorCode.MISSING_IDENTIFIER]);
-//    listener.assertErrors(
-//        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
-    expect(result, hasLength(4));
-    Expression syntheticExpression = result[0];
-    expect(syntheticExpression, isSimpleIdentifier);
-    expect(syntheticExpression.isSynthetic, isTrue);
-  }
-
-  void test_expressionList_multiple_middle() {
-    List<Expression> result = parseExpressionList('1, 2, , 4');
-    expectNotNullIfNoErrors(result);
-    // TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
-    listener.assertErrorsWithCodes([ParserErrorCode.MISSING_IDENTIFIER]);
-//    listener.assertErrors(
-//        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1)]);
-    expect(result, hasLength(4));
-    Expression syntheticExpression = result[2];
-    expect(syntheticExpression, isSimpleIdentifier);
-    expect(syntheticExpression.isSynthetic, isTrue);
-  }
-
-  void test_expressionList_multiple_start() {
-    List<Expression> result = parseExpressionList('1, 2, 3,');
-    expectNotNullIfNoErrors(result);
-    // The fasta parser does not use parseExpressionList when parsing for loops
-    // and instead parseExpressionList is mapped to parseExpression('[$code]')
-    // which allows and ignores an optional trailing comma.
-    if (usingFastaParser) {
-      assertNoErrors();
-      expect(result, hasLength(3));
-    } else {
-      listener.assertErrors(
-          [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 0)]);
-      expect(result, hasLength(4));
-      Expression syntheticExpression = result[3];
-      expect(syntheticExpression, isSimpleIdentifier);
-      expect(syntheticExpression.isSynthetic, isTrue);
-    }
-  }
-
-  void test_functionExpression_in_ConstructorFieldInitializer() {
-    CompilationUnit unit =
-        parseCompilationUnit("class A { A() : a = (){}; var v; }", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      usingFastaParser
-          ? ParserErrorCode.EXPECTED_CLASS_MEMBER
-          : ParserErrorCode.UNEXPECTED_TOKEN
-    ]);
-    // Make sure we recovered and parsed "var v" correctly
-    ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;
-    NodeList<ClassMember> members = declaration.members;
-    ClassMember fieldDecl = members[1];
-    expect(fieldDecl, isFieldDeclaration);
-    NodeList<VariableDeclaration> vars =
-        (fieldDecl as FieldDeclaration).fields.variables;
-    expect(vars, hasLength(1));
-    expect(vars[0].name.name, "v");
-  }
-
-  void test_functionExpression_named() {
-    parseExpression("m(f() => 0);", expectedEndOffset: 11, codes: [
-      usingFastaParser
-          ? ParserErrorCode.NAMED_FUNCTION_EXPRESSION
-          : ParserErrorCode.EXPECTED_TOKEN
-    ]);
-  }
-
-  void test_ifStatement_noElse_statement() {
-    parseStatement('if (x v) f(x);');
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)
-          ]);
-  }
-
-  void test_importDirectivePartial_as() {
-    CompilationUnit unit = parseCompilationUnit("import 'b.dart' d as b;",
-        codes: [ParserErrorCode.UNEXPECTED_TOKEN]);
-    ImportDirective importDirective = unit.childEntities.first;
-    expect(importDirective.asKeyword, isNotNull);
-    expect(unit.directives, hasLength(1));
-    expect(unit.declarations, hasLength(0));
-  }
-
-  void test_importDirectivePartial_hide() {
-    CompilationUnit unit = parseCompilationUnit("import 'b.dart' d hide foo;",
-        codes: [ParserErrorCode.UNEXPECTED_TOKEN]);
-    ImportDirective importDirective = unit.childEntities.first;
-    expect(importDirective.combinators, hasLength(1));
-    expect(unit.directives, hasLength(1));
-    expect(unit.declarations, hasLength(0));
-  }
-
-  void test_importDirectivePartial_show() {
-    CompilationUnit unit = parseCompilationUnit("import 'b.dart' d show foo;",
-        codes: [ParserErrorCode.UNEXPECTED_TOKEN]);
-    ImportDirective importDirective = unit.childEntities.first;
-    expect(importDirective.combinators, hasLength(1));
-    expect(unit.directives, hasLength(1));
-    expect(unit.declarations, hasLength(0));
-  }
-
-  void test_incomplete_conditionalExpression() {
-    parseExpression("x ? 0", codes: [
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-  }
-
-  void test_incomplete_constructorInitializers_empty() {
-    createParser('C() : {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_INITIALIZER, 4, 1)]);
-  }
-
-  void test_incomplete_constructorInitializers_missingEquals() {
-    createParser('C() : x(3) {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 1)
-    ]);
-    expect(member, isConstructorDeclaration);
-    NodeList<ConstructorInitializer> initializers =
-        (member as ConstructorDeclaration).initializers;
-    expect(initializers, hasLength(1));
-    ConstructorInitializer initializer = initializers[0];
-    expect(initializer, isConstructorFieldInitializer);
-    Expression expression =
-        (initializer as ConstructorFieldInitializer).expression;
-    expect(expression, isNotNull);
-    expect(expression,
-        usingFastaParser ? isMethodInvocation : isParenthesizedExpression);
-  }
-
-  void test_incomplete_constructorInitializers_this() {
-    createParser('C() : this {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(usingFastaParser
-        ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
-            expectedError(
-                ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
-          ]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
-            expectedError(
-                ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 11, 1)
-          ]);
-  }
-
-  void test_incomplete_constructorInitializers_thisField() {
-    createParser('C() : this.g {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
-    ]);
-  }
-
-  void test_incomplete_constructorInitializers_thisPeriod() {
-    createParser('C() : this. {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 12, 1),
-      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
-    ]);
-  }
-
-  void test_incomplete_constructorInitializers_variable() {
-    createParser('C() : x {}');
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 1)
-    ]);
-  }
-
-  void test_incomplete_functionExpression() {
-    var expression = parseExpression("() a => null",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 3, 1)]
-            : [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]);
-    if (usingFastaParser) {
-      FunctionExpression functionExpression = expression;
-      expect(functionExpression.parameters.parameters, hasLength(0));
-    }
-  }
-
-  void test_incomplete_functionExpression2() {
-    var expression = parseExpression("() a {}",
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 3, 1)]
-            : [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]);
-    if (usingFastaParser) {
-      FunctionExpression functionExpression = expression;
-      expect(functionExpression.parameters.parameters, hasLength(0));
-    }
-  }
-
-  void test_incomplete_returnType() {
-    if (usingFastaParser) {
-      parseCompilationUnit(r'''
-Map<Symbol, convertStringToSymbolMap(Map<String, dynamic> map) {
-  if (map == null) return null;
-  Map<Symbol, dynamic> result = new Map<Symbol, dynamic>();
-  map.forEach((name, value) {
-    result[new Symbol(name)] = value;
-  });
-  return result;
-}''', errors: [
-        expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 24),
-        expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 3)
-      ]);
-    }
-  }
-
-  void test_incomplete_topLevelFunction() {
-    parseCompilationUnit("foo();",
-        codes: [ParserErrorCode.MISSING_FUNCTION_BODY]);
-  }
-
-  void test_incomplete_topLevelVariable() {
-    CompilationUnit unit = parseCompilationUnit("String",
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 6),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 6)
-              ]
-            : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 6)]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember member = declarations[0];
-    expect(member, isTopLevelVariableDeclaration);
-    NodeList<VariableDeclaration> variables =
-        (member as TopLevelVariableDeclaration).variables.variables;
-    expect(variables, hasLength(1));
-    SimpleIdentifier name = variables[0].name;
-    // Analyzer considers 'String' to be the type
-    // while fasta considers it to be the name.
-    expect(name.isSynthetic, usingFastaParser ? isFalse : isTrue);
-  }
-
-  void test_incomplete_topLevelVariable_const() {
-    CompilationUnit unit = parseCompilationUnit("const ", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember member = declarations[0];
-    expect(member, isTopLevelVariableDeclaration);
-    NodeList<VariableDeclaration> variables =
-        (member as TopLevelVariableDeclaration).variables.variables;
-    expect(variables, hasLength(1));
-    SimpleIdentifier name = variables[0].name;
-    expect(name.isSynthetic, isTrue);
-  }
-
-  void test_incomplete_topLevelVariable_final() {
-    CompilationUnit unit = parseCompilationUnit("final ", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember member = declarations[0];
-    expect(member, isTopLevelVariableDeclaration);
-    NodeList<VariableDeclaration> variables =
-        (member as TopLevelVariableDeclaration).variables.variables;
-    expect(variables, hasLength(1));
-    SimpleIdentifier name = variables[0].name;
-    expect(name.isSynthetic, isTrue);
-  }
-
-  void test_incomplete_topLevelVariable_var() {
-    CompilationUnit unit = parseCompilationUnit("var ", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember member = declarations[0];
-    expect(member, isTopLevelVariableDeclaration);
-    NodeList<VariableDeclaration> variables =
-        (member as TopLevelVariableDeclaration).variables.variables;
-    expect(variables, hasLength(1));
-    SimpleIdentifier name = variables[0].name;
-    expect(name.isSynthetic, isTrue);
-  }
-
-  void test_incompleteField_const() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  const
-}''', codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember unitMember = declarations[0];
-    expect(unitMember, isClassDeclaration);
-    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
-    expect(members, hasLength(1));
-    ClassMember classMember = members[0];
-    expect(classMember, isFieldDeclaration);
-    VariableDeclarationList fieldList =
-        (classMember as FieldDeclaration).fields;
-    expect(fieldList.keyword.keyword, Keyword.CONST);
-    NodeList<VariableDeclaration> fields = fieldList.variables;
-    expect(fields, hasLength(1));
-    VariableDeclaration field = fields[0];
-    expect(field.name.isSynthetic, isTrue);
-  }
-
-  void test_incompleteField_final() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  final
-}''', codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember unitMember = declarations[0];
-    expect(unitMember, isClassDeclaration);
-    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
-    expect(members, hasLength(1));
-    ClassMember classMember = members[0];
-    expect(classMember, isFieldDeclaration);
-    VariableDeclarationList fieldList =
-        (classMember as FieldDeclaration).fields;
-    expect(fieldList.keyword.keyword, Keyword.FINAL);
-    NodeList<VariableDeclaration> fields = fieldList.variables;
-    expect(fields, hasLength(1));
-    VariableDeclaration field = fields[0];
-    expect(field.name.isSynthetic, isTrue);
-  }
-
-  void test_incompleteField_static() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  static c
-}''', codes: [
-      // Fasta considers the `c` to be the type
-      // whereas analyzer considers it to be the identifier.
-      usingFastaParser
-          ? ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-          : ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember unitMember = declarations[0];
-    expect(unitMember, isClassDeclaration);
-    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
-    expect(members, hasLength(1));
-    ClassMember classMember = members[0];
-    expect(classMember, isFieldDeclaration);
-    FieldDeclaration declaration = classMember;
-    expect(declaration.staticKeyword.lexeme, 'static');
-    VariableDeclarationList fieldList = declaration.fields;
-    expect(fieldList.keyword, isNull);
-    NodeList<VariableDeclaration> fields = fieldList.variables;
-    expect(fields, hasLength(1));
-    VariableDeclaration field = fields[0];
-    expect(field.name.isSynthetic, usingFastaParser ? isFalse : isTrue);
-  }
-
-  void test_incompleteField_static2() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  static c x
-}''', codes: [ParserErrorCode.EXPECTED_TOKEN]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember unitMember = declarations[0];
-    expect(unitMember, isClassDeclaration);
-    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
-    expect(members, hasLength(1));
-    ClassMember classMember = members[0];
-    expect(classMember, isFieldDeclaration);
-    FieldDeclaration declaration = classMember;
-    expect(declaration.staticKeyword.lexeme, 'static');
-    VariableDeclarationList fieldList = declaration.fields;
-    expect(fieldList.keyword, isNull);
-    NodeList<VariableDeclaration> fields = fieldList.variables;
-    expect(fields, hasLength(1));
-    VariableDeclaration field = fields[0];
-    expect(field.name.isSynthetic, isFalse);
-  }
-
-  void test_incompleteField_type() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  A
-}''', codes: [
-      // Fasta considers the `c` to be the type
-      // whereas analyzer considers it to be the identifier.
-      usingFastaParser
-          ? ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-          : ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember unitMember = declarations[0];
-    expect(unitMember, isClassDeclaration);
-    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
-    expect(members, hasLength(1));
-    ClassMember classMember = members[0];
-    expect(classMember, isFieldDeclaration);
-    VariableDeclarationList fieldList =
-        (classMember as FieldDeclaration).fields;
-    TypeName type = fieldList.type;
-    NodeList<VariableDeclaration> fields = fieldList.variables;
-    expect(fields, hasLength(1));
-    VariableDeclaration field = fields[0];
-    if (usingFastaParser) {
-      expect(type, isNull);
-      expect(field.name.name, 'A');
-    } else {
-      expect(type.name.name, 'A');
-      expect(field.name.isSynthetic, isTrue);
-    }
-  }
-
-  void test_incompleteField_var() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  var
-}''', codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember unitMember = declarations[0];
-    expect(unitMember, isClassDeclaration);
-    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
-    expect(members, hasLength(1));
-    ClassMember classMember = members[0];
-    expect(classMember, isFieldDeclaration);
-    VariableDeclarationList fieldList =
-        (classMember as FieldDeclaration).fields;
-    expect(fieldList.keyword.keyword, Keyword.VAR);
-    NodeList<VariableDeclaration> fields = fieldList.variables;
-    expect(fields, hasLength(1));
-    VariableDeclaration field = fields[0];
-    expect(field.name.isSynthetic, isTrue);
-  }
-
-  void test_incompleteForEach() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    ForStatement statement = parseStatement('for (String item i) {}');
-    listener.assertErrors([
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)
-    ]);
-    expect(statement, isForStatement);
-    expect(statement.toSource(), 'for (String item; i;) {}');
-    var forParts = statement.forLoopParts as ForParts;
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.leftSeparator.type, TokenType.SEMICOLON);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.rightSeparator.type, TokenType.SEMICOLON);
-  }
-
-  void test_incompleteLocalVariable_atTheEndOfBlock() {
-    Statement statement = parseStatement('String v }', expectedEndOffset: 9);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
-    expect(statement, isVariableDeclarationStatement);
-    expect(statement.toSource(), 'String v;');
-  }
-
-  void test_incompleteLocalVariable_atTheEndOfBlock_modifierOnly() {
-    Statement statement = parseStatement('final }', expectedEndOffset: 6);
-    listener.assertErrors([
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)
-    ]);
-    expect(statement, isVariableDeclarationStatement);
-    expect(statement.toSource(), 'final ;');
-  }
-
-  void test_incompleteLocalVariable_beforeIdentifier() {
-    Statement statement =
-        parseStatement('String v String v2;', expectedEndOffset: 9);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
-    expect(statement, isVariableDeclarationStatement);
-    expect(statement.toSource(), 'String v;');
-  }
-
-  void test_incompleteLocalVariable_beforeKeyword() {
-    Statement statement =
-        parseStatement('String v if (true) {}', expectedEndOffset: 9);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
-    expect(statement, isVariableDeclarationStatement);
-    expect(statement.toSource(), 'String v;');
-  }
-
-  void test_incompleteLocalVariable_beforeNextBlock() {
-    Statement statement = parseStatement('String v {}', expectedEndOffset: 9);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
-    expect(statement, isVariableDeclarationStatement);
-    expect(statement.toSource(), 'String v;');
-  }
-
-  void test_incompleteLocalVariable_parameterizedType() {
-    Statement statement =
-        parseStatement('List<String> v {}', expectedEndOffset: 15);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1)]);
-    expect(statement, isVariableDeclarationStatement);
-    expect(statement.toSource(), 'List<String> v;');
-  }
-
-  void test_incompleteTypeArguments_field() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  final List<int f;
-}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 3)]);
-    // one class
-    List<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
-    // one field declaration
-    List<ClassMember> members = classDecl.members;
-    expect(members, hasLength(1));
-    FieldDeclaration fieldDecl = members[0] as FieldDeclaration;
-    // one field
-    VariableDeclarationList fieldList = fieldDecl.fields;
-    List<VariableDeclaration> fields = fieldList.variables;
-    expect(fields, hasLength(1));
-    VariableDeclaration field = fields[0];
-    expect(field.name.name, 'f');
-    // validate the type
-    TypeArgumentList typeArguments = (fieldList.type as TypeName).typeArguments;
-    expect(typeArguments.arguments, hasLength(1));
-    // synthetic '>'
-    Token token = typeArguments.endToken;
-    expect(token.type, TokenType.GT);
-    expect(token.isSynthetic, isTrue);
-  }
-
-  void test_incompleteTypeParameters() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C<K {
-}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]);
-    // one class
-    List<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
-    // validate the type parameters
-    TypeParameterList typeParameters = classDecl.typeParameters;
-    expect(typeParameters.typeParameters, hasLength(1));
-    // synthetic '>'
-    Token token = typeParameters.endToken;
-    expect(token.type, TokenType.GT);
-    expect(token.isSynthetic, isTrue);
-  }
-
-  void test_incompleteTypeParameters2() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C<K extends L<T> {
-}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 21, 1)]);
-    // one class
-    List<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
-    // validate the type parameters
-    TypeParameterList typeParameters = classDecl.typeParameters;
-    expect(typeParameters.typeParameters, hasLength(1));
-    // synthetic '>'
-    Token token = typeParameters.endToken;
-    expect(token.type, TokenType.GT);
-    expect(token.isSynthetic, isTrue);
-  }
-
-  void test_incompleteTypeParameters3() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C<K extends L<T {
-}''',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 1)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1)
-              ]);
-    // one class
-    List<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
-    // validate the type parameters
-    TypeParameterList typeParameters = classDecl.typeParameters;
-    expect(typeParameters.typeParameters, hasLength(1));
-    // synthetic '>'
-    Token token = typeParameters.endToken;
-    expect(token.type, TokenType.GT);
-    expect(token.isSynthetic, isTrue);
-  }
-
-  void test_invalidFunctionBodyModifier() {
-    parseCompilationUnit("f() sync {}",
-        codes: [ParserErrorCode.MISSING_STAR_AFTER_SYNC]);
-  }
-
-  void test_invalidMapLiteral() {
-    parseCompilationUnit("class C { var f = Map<A, B> {}; }",
-        codes: usingFastaParser
-            ? [
-                // TODO(danrubel): Improve error message to indicate
-                // that "Map" should be removed.
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.MISSING_KEYWORD_OPERATOR,
-                ParserErrorCode.MISSING_METHOD_PARAMETERS,
-                ParserErrorCode.EXPECTED_CLASS_MEMBER,
-              ]
-            : [
-                ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_CLASS_MEMBER,
-                ParserErrorCode.EXPECTED_CLASS_MEMBER,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.UNEXPECTED_TOKEN,
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-              ]);
-  }
-
-  void test_invalidTypeParameters() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  G<int double> g;
-}''',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 24, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 24, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 26, 1)
-              ]);
-    // one class
-    List<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    // validate members
-    if (usingFastaParser) {
-      ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
-      expect(classDecl.members, hasLength(1));
-      FieldDeclaration fields = classDecl.members.first;
-      expect(fields.fields.variables, hasLength(1));
-      VariableDeclaration field = fields.fields.variables.first;
-      expect(field.name.name, 'g');
-    }
-  }
-
-  void test_isExpression_noType() {
-    CompilationUnit unit = parseCompilationUnit(
-        "class Bar<T extends Foo> {m(x){if (x is ) return;if (x is !)}}",
-        codes: usingFastaParser
-            ? [
-                ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.MISSING_IDENTIFIER,
-                ParserErrorCode.EXPECTED_TOKEN,
-              ]
-            : [
-                ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.EXPECTED_TYPE_NAME,
-                ParserErrorCode.MISSING_STATEMENT
-              ]);
-    ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;
-    MethodDeclaration method = declaration.members[0] as MethodDeclaration;
-    BlockFunctionBody body = method.body as BlockFunctionBody;
-    IfStatement ifStatement = body.block.statements[1] as IfStatement;
-    IsExpression expression = ifStatement.condition as IsExpression;
-    expect(expression.expression, isNotNull);
-    expect(expression.isOperator, isNotNull);
-    expect(expression.notOperator, isNotNull);
-    TypeAnnotation type = expression.type;
-    expect(type, isNotNull);
-    expect(type is TypeName && type.name.isSynthetic, isTrue);
-    if (usingFastaParser) {
-      ExpressionStatement thenStatement = ifStatement.thenStatement;
-      expect(thenStatement.semicolon.isSynthetic, isTrue);
-      SimpleIdentifier simpleId = thenStatement.expression;
-      expect(simpleId.isSynthetic, isTrue);
-    } else {
-      expect(ifStatement.thenStatement, isEmptyStatement);
-    }
-  }
-
-  void test_issue_34610_get() {
-    final unit = parseCompilationUnit('class C { get C.named => null; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.GETTER_CONSTRUCTOR, 10, 3),
-                expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 14, 1),
-              ]
-            : [
-                expectedError(
-                    ParserErrorCode.STATIC_GETTER_WITHOUT_BODY, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 25, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 1),
-              ]);
-    ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration method = declaration.members[0];
-      expect(method.name.name, 'named');
-      expect(method.parameters, isNotNull);
-    } else {
-      MethodDeclaration method = declaration.members[0];
-      expect(method.name.name, 'C');
-      expect(method.isGetter, isTrue);
-      expect(method.parameters, isNull);
-    }
-  }
-
-  void test_issue_34610_initializers() {
-    final unit = parseCompilationUnit('class C { C.named : super(); }',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 19),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 19),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 18, 19),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 20, 25),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 20, 25),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 25, 26),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 26),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 26, 27),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 26, 27),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 27, 28),
-              ]);
-    ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration constructor = declaration.members[0];
-      expect(constructor.name.name, 'named');
-      expect(constructor.parameters, isNotNull);
-      expect(constructor.parameters.parameters, hasLength(0));
-    } else {
-      FieldDeclaration field = declaration.members[0];
-      expect(field.fields.type.toSource(), 'C.named');
-    }
-  }
-
-  void test_issue_34610_missing_param() {
-    final unit = parseCompilationUnit('class C { C => null; }',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 18, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 21, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 21, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 1),
-              ]);
-    ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration constructor = declaration.members[0];
-      expect(constructor.name, isNull);
-      expect(constructor.parameters, isNotNull);
-      expect(constructor.parameters.parameters, hasLength(0));
-    } else {
-      FieldDeclaration field = declaration.members[0];
-      expect(field.fields.type.toSource(), 'C');
-    }
-  }
-
-  void test_issue_34610_named_missing_param() {
-    final unit = parseCompilationUnit('class C { C.named => null; }',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 18, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 18, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 21, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 21, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 1),
-              ]);
-    ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration constructor = declaration.members[0];
-      expect(constructor.name.name, 'named');
-      expect(constructor.parameters, isNotNull);
-      expect(constructor.parameters.parameters, hasLength(0));
-    } else {
-      FieldDeclaration field = declaration.members[0];
-      expect(field.fields.type.toSource(), 'C.named');
-    }
-  }
-
-  void test_issue_34610_set() {
-    final unit = parseCompilationUnit('class C { set C.named => null; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.SETTER_CONSTRUCTOR, 10, 3),
-                expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 14, 1),
-              ]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
-                expectedError(
-                    ParserErrorCode.STATIC_SETTER_WITHOUT_BODY, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 22, 2),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 2),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 25, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 25, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 29, 1),
-              ]);
-    ClassDeclaration declaration = unit.declarations[0];
-    if (usingFastaParser) {
-      ConstructorDeclaration method = declaration.members[0];
-      expect(method.name.name, 'named');
-      expect(method.parameters, isNotNull);
-      expect(method.parameters.parameters, hasLength(0));
-    } else {
-      MethodDeclaration method = declaration.members[0];
-      expect(method.name.name, 'C');
-      expect(method.isSetter, isTrue);
-      expect(method.parameters, isNotNull);
-      expect(method.parameters.parameters, hasLength(1));
-    }
-  }
-
-  void test_keywordInPlaceOfIdentifier() {
-    // TODO(brianwilkerson) We could do better with this.
-    parseCompilationUnit("do() {}",
-        codes: usingFastaParser
-            ? [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]
-            : [
-                ParserErrorCode.EXPECTED_EXECUTABLE,
-                ParserErrorCode.UNEXPECTED_TOKEN
-              ]);
-  }
-
-  void test_logicalAndExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("&& y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_logicalAndExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("&&", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_logicalAndExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x &&", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_logicalAndExpression_precedence_bitwiseOr_left() {
-    BinaryExpression expression = parseExpression("| &&", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_logicalAndExpression_precedence_bitwiseOr_right() {
-    BinaryExpression expression = parseExpression("&& |", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_logicalOrExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("|| y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_logicalOrExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("||", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_logicalOrExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x ||", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_logicalOrExpression_precedence_logicalAnd_left() {
-    BinaryExpression expression = parseExpression("&& ||", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_logicalOrExpression_precedence_logicalAnd_right() {
-    BinaryExpression expression = parseExpression("|| &&", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_method_missingBody() {
-    parseCompilationUnit("class C { b() }",
-        errors: [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 14, 1)]);
-  }
-
-  void test_missing_commaInArgumentList() {
-    MethodInvocation expression = parseExpression("f(x: 1 y: 2)",
-        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
-    NodeList<Expression> arguments = expression.argumentList.arguments;
-    expect(arguments, hasLength(2));
-  }
-
-  void test_missingComma_beforeNamedArgument() {
-    createParser('(a b: c)');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 3, 1)]);
-    expect(argumentList.arguments, hasLength(2));
-  }
-
-  void test_missingGet() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C {
-  int length {}
-  void foo() {}
-}''', errors: [
-      expectedError(
-          usingFastaParser
-              ? ParserErrorCode.MISSING_METHOD_PARAMETERS
-              : ParserErrorCode.MISSING_GET,
-          16,
-          6)
-    ]);
-    expect(unit, isNotNull);
-    ClassDeclaration classDeclaration =
-        unit.declarations[0] as ClassDeclaration;
-    NodeList<ClassMember> members = classDeclaration.members;
-    expect(members, hasLength(2));
-    expect(members[0], isMethodDeclaration);
-    ClassMember member = members[1];
-    expect(member, isMethodDeclaration);
-    expect((member as MethodDeclaration).name.name, "foo");
-  }
-
-  void test_missingIdentifier_afterAnnotation() {
-    createParser('@override }', expectedEndOffset: 10);
-    ClassMember member = parser.parseClassMember('C');
-    expectNotNullIfNoErrors(member);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1)]);
-    if (usingFastaParser) {
-      // TODO(danrubel): Consider generating a sub method so that the
-      // existing annotation can be associated with a class member.
-      expect(member, isNull);
-    } else {
-      expect(member, isMethodDeclaration);
-      MethodDeclaration method = member;
-      expect(method.documentationComment, isNull);
-      NodeList<Annotation> metadata = method.metadata;
-      expect(metadata, hasLength(1));
-      expect(metadata[0].name.name, "override");
-    }
-  }
-
-  void test_missingSemicolon_varialeDeclarationList() {
-    void verify(CompilationUnitMember member, String expectedTypeName,
-        String expectedName, String expectedSemicolon) {
-      expect(member, isTopLevelVariableDeclaration);
-      TopLevelVariableDeclaration declaration = member;
-      VariableDeclarationList variableList = declaration.variables;
-      expect(variableList, isNotNull);
-      NodeList<VariableDeclaration> variables = variableList.variables;
-      expect(variables, hasLength(1));
-      VariableDeclaration variable = variables[0];
-      expect(variableList.type.toString(), expectedTypeName);
-      expect(variable.name.name, expectedName);
-      if (expectedSemicolon.isEmpty) {
-        expect(declaration.semicolon.isSynthetic, isTrue);
-      } else {
-        expect(declaration.semicolon.lexeme, expectedSemicolon);
-      }
-    }
-
-    // Fasta considers the `n` an extraneous modifier
-    // and parses this as a single top level declaration.
-    // TODO(danrubel): A better recovery
-    // would be to insert a synthetic comma after the `n`.
-    CompilationUnit unit = parseCompilationUnit('String n x = "";', codes: [
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
-    ]);
-    expect(unit, isNotNull);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(2));
-    verify(declarations[0], 'String', 'n', '');
-    verify(declarations[1], 'null', 'x', ';');
-  }
-
-  void test_multiplicativeExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("* y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_multiplicativeExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("*", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_multiplicativeExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x *", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_multiplicativeExpression_missing_RHS_super() {
-    BinaryExpression expression =
-        parseExpression("super *", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_multiplicativeExpression_precedence_unary_left() {
-    BinaryExpression expression =
-        parseExpression("-x *", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isPrefixExpression);
-  }
-
-  void test_multiplicativeExpression_precedence_unary_right() {
-    BinaryExpression expression =
-        parseExpression("* -y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isPrefixExpression);
-  }
-
-  void test_multiplicativeExpression_super() {
-    BinaryExpression expression = parseExpression("super ==  ==", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_namedParameterOutsideGroup() {
-    CompilationUnit unit =
-        parseCompilationUnit('class A { b(c: 0, Foo d: 0, e){} }', errors: [
-      expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 13, 1),
-      expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 23, 1)
-    ]);
-    expect(unit.declarations, hasLength(1));
-    ClassDeclaration classA = unit.declarations[0];
-    expect(classA.members, hasLength(1));
-    MethodDeclaration method = classA.members[0];
-    NodeList<FormalParameter> parameters = method.parameters.parameters;
-    expect(parameters, hasLength(3));
-    expect(parameters[0].isNamed, isTrue);
-    expect(parameters[1].isNamed, isTrue);
-    expect(parameters[2].isRequired, isTrue);
-  }
-
-  void test_nonStringLiteralUri_import() {
-    parseCompilationUnit("import dart:io; class C {}",
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 7, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 7, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 11, 1),
-                expectedError(
-                    ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 2)
-              ]
-            : [expectedError(ParserErrorCode.NON_STRING_LITERAL_AS_URI, 7, 4)]);
-  }
-
-  void test_prefixExpression_missing_operand_minus() {
-    PrefixExpression expression =
-        parseExpression("-", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.operand, isSimpleIdentifier);
-    expect(expression.operand.isSynthetic, isTrue);
-    expect(expression.operator.type, TokenType.MINUS);
-  }
-
-  void test_primaryExpression_argumentDefinitionTest() {
-    SimpleIdentifier expression = parsePrimaryExpression('?a',
-        expectedEndOffset: 0,
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]
-            : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 1)]);
-    expectNotNullIfNoErrors(expression);
-    expect(expression.isSynthetic, usingFastaParser);
-  }
-
-  void test_propertyAccess_missing_LHS_RHS() {
-    Expression result = parseExpression(".", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    if (usingFastaParser) {
-      PrefixedIdentifier expression = result;
-      expect(expression.prefix.isSynthetic, isTrue);
-      expect(expression.period.lexeme, '.');
-      expect(expression.identifier.isSynthetic, isTrue);
-    } else {
-      PropertyAccess expression = result;
-      SimpleIdentifier target = expression.target;
-      expect(target.isSynthetic, isTrue);
-      expect(expression.operator.lexeme, '.');
-      expect(expression.propertyName.isSynthetic, isTrue);
-    }
-  }
-
-  void test_relationalExpression_missing_LHS() {
-    IsExpression expression =
-        parseExpression("is y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.expression, isSimpleIdentifier);
-    expect(expression.expression.isSynthetic, isTrue);
-  }
-
-  void test_relationalExpression_missing_LHS_RHS() {
-    IsExpression expression = parseExpression("is", codes: [
-      ParserErrorCode.EXPECTED_TYPE_NAME,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.expression, isSimpleIdentifier);
-    expect(expression.expression.isSynthetic, isTrue);
-    expect(expression.type, isTypeName);
-    expect(expression.type.isSynthetic, isTrue);
-  }
-
-  void test_relationalExpression_missing_RHS() {
-    IsExpression expression =
-        parseExpression("x is", codes: [ParserErrorCode.EXPECTED_TYPE_NAME]);
-    expect(expression.type, isTypeName);
-    expect(expression.type.isSynthetic, isTrue);
-  }
-
-  void test_relationalExpression_precedence_shift_right() {
-    IsExpression expression = parseExpression("<< is", codes: [
-      ParserErrorCode.EXPECTED_TYPE_NAME,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.expression, isBinaryExpression);
-  }
-
-  void test_shiftExpression_missing_LHS() {
-    BinaryExpression expression =
-        parseExpression("<< y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-  }
-
-  void test_shiftExpression_missing_LHS_RHS() {
-    BinaryExpression expression = parseExpression("<<", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isSimpleIdentifier);
-    expect(expression.leftOperand.isSynthetic, isTrue);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_shiftExpression_missing_RHS() {
-    BinaryExpression expression =
-        parseExpression("x <<", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_shiftExpression_missing_RHS_super() {
-    BinaryExpression expression = parseExpression("super <<",
-        codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-    expect(expression.rightOperand, isSimpleIdentifier);
-    expect(expression.rightOperand.isSynthetic, isTrue);
-  }
-
-  void test_shiftExpression_precedence_unary_left() {
-    BinaryExpression expression = parseExpression("+ <<", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_shiftExpression_precedence_unary_right() {
-    BinaryExpression expression = parseExpression("<< +", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.rightOperand, isBinaryExpression);
-  }
-
-  void test_shiftExpression_super() {
-    BinaryExpression expression = parseExpression("super << <<", codes: [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ]);
-    expect(expression.leftOperand, isBinaryExpression);
-  }
-
-  void test_typedef_eof() {
-    CompilationUnit unit = parseCompilationUnit("typedef n", codes: [
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_TYPEDEF_PARAMETERS
-    ]);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(1));
-    CompilationUnitMember member = declarations[0];
-    expect(member, isFunctionTypeAlias);
-  }
-
-  void test_unaryPlus() {
-    parseExpression("+2", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
-  }
-}
-
-/// Tests of the analyzer parser based on [SimpleParserTestMixin].
-@reflectiveTest
-class SimpleParserTest extends ParserTestCase with SimpleParserTestMixin {
-  void test_computeStringValue_emptyInterpolationPrefix() {
-    expect(_computeStringValue("'''", true, false), "");
-  }
-
-  void test_computeStringValue_escape_b() {
-    expect(_computeStringValue("'\\b'", true, true), "\b");
-  }
-
-  void test_computeStringValue_escape_f() {
-    expect(_computeStringValue("'\\f'", true, true), "\f");
-  }
-
-  void test_computeStringValue_escape_n() {
-    expect(_computeStringValue("'\\n'", true, true), "\n");
-  }
-
-  void test_computeStringValue_escape_notSpecial() {
-    expect(_computeStringValue("'\\:'", true, true), ":");
-  }
-
-  void test_computeStringValue_escape_r() {
-    expect(_computeStringValue("'\\r'", true, true), "\r");
-  }
-
-  void test_computeStringValue_escape_t() {
-    expect(_computeStringValue("'\\t'", true, true), "\t");
-  }
-
-  void test_computeStringValue_escape_u_fixed() {
-    expect(_computeStringValue("'\\u4321'", true, true), "\u4321");
-  }
-
-  void test_computeStringValue_escape_u_variable() {
-    expect(_computeStringValue("'\\u{123}'", true, true), "\u0123");
-  }
-
-  void test_computeStringValue_escape_v() {
-    expect(_computeStringValue("'\\v'", true, true), "\u000B");
-  }
-
-  void test_computeStringValue_escape_x() {
-    expect(_computeStringValue("'\\xFF'", true, true), "\u00FF");
-  }
-
-  void test_computeStringValue_noEscape_single() {
-    expect(_computeStringValue("'text'", true, true), "text");
-  }
-
-  void test_computeStringValue_noEscape_triple() {
-    expect(_computeStringValue("'''text'''", true, true), "text");
-  }
-
-  void test_computeStringValue_raw_single() {
-    expect(_computeStringValue("r'text'", true, true), "text");
-  }
-
-  void test_computeStringValue_raw_triple() {
-    expect(_computeStringValue("r'''text'''", true, true), "text");
-  }
-
-  void test_computeStringValue_raw_withEscape() {
-    expect(_computeStringValue("r'two\\nlines'", true, true), "two\\nlines");
-  }
-
-  void test_computeStringValue_triple_internalQuote_first_empty() {
-    expect(_computeStringValue("''''", true, false), "'");
-  }
-
-  void test_computeStringValue_triple_internalQuote_first_nonEmpty() {
-    expect(_computeStringValue("''''text", true, false), "'text");
-  }
-
-  void test_computeStringValue_triple_internalQuote_last_empty() {
-    expect(_computeStringValue("'''", false, true), "");
-  }
-
-  void test_computeStringValue_triple_internalQuote_last_nonEmpty() {
-    expect(_computeStringValue("text'''", false, true), "text");
-  }
-
-  void test_createSyntheticIdentifier() {
-    createParser('');
-    SimpleIdentifier identifier = parser.createSyntheticIdentifier();
-    expectNotNullIfNoErrors(identifier);
-    expect(identifier.isSynthetic, isTrue);
-  }
-
-  void test_createSyntheticStringLiteral() {
-    createParser('');
-    SimpleStringLiteral literal = parser.createSyntheticStringLiteral();
-    expectNotNullIfNoErrors(literal);
-    expect(literal.isSynthetic, isTrue);
-  }
-
-  void test_isFunctionDeclaration_nameButNoReturn_block() {
-    expect(_isFunctionDeclaration("f() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_nameButNoReturn_expression() {
-    expect(_isFunctionDeclaration("f() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_nameButNoReturn_typeParameters_block() {
-    expect(_isFunctionDeclaration("f<E>() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_nameButNoReturn_typeParameters_expression() {
-    expect(_isFunctionDeclaration("f<E>() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_normalReturn_block() {
-    expect(_isFunctionDeclaration("C f() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_normalReturn_expression() {
-    expect(_isFunctionDeclaration("C f() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_normalReturn_typeParameters_block() {
-    expect(_isFunctionDeclaration("C f<E>() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_normalReturn_typeParameters_expression() {
-    expect(_isFunctionDeclaration("C f<E>() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_voidReturn_block() {
-    expect(_isFunctionDeclaration("void f() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_voidReturn_expression() {
-    expect(_isFunctionDeclaration("void f() => e"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_voidReturn_typeParameters_block() {
-    expect(_isFunctionDeclaration("void f<E>() {}"), isTrue);
-  }
-
-  void test_isFunctionDeclaration_voidReturn_typeParameters_expression() {
-    expect(_isFunctionDeclaration("void f<E>() => e"), isTrue);
-  }
-
-  void test_isFunctionExpression_false_noBody() {
-    expect(_isFunctionExpression("f();"), isFalse);
-  }
-
-  void test_isFunctionExpression_false_notParameters() {
-    expect(_isFunctionExpression("(a + b) {"), isFalse);
-  }
-
-  void test_isFunctionExpression_noParameters_block() {
-    expect(_isFunctionExpression("() {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_noParameters_expression() {
-    expect(_isFunctionExpression("() => e"), isTrue);
-  }
-
-  void test_isFunctionExpression_noParameters_typeParameters_block() {
-    expect(_isFunctionExpression("<E>() {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_noParameters_typeParameters_expression() {
-    expect(_isFunctionExpression("<E>() => e"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_final() {
-    expect(_isFunctionExpression("(final a) {}"), isTrue);
-    expect(_isFunctionExpression("(final a, b) {}"), isTrue);
-    expect(_isFunctionExpression("(final a, final b) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_final_typed() {
-    expect(_isFunctionExpression("(final int a) {}"), isTrue);
-    expect(_isFunctionExpression("(final prefix.List a) {}"), isTrue);
-    expect(_isFunctionExpression("(final List<int> a) {}"), isTrue);
-    expect(_isFunctionExpression("(final prefix.List<int> a) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_multiple() {
-    expect(_isFunctionExpression("(a, b) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_named() {
-    expect(_isFunctionExpression("({a}) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_optional() {
-    expect(_isFunctionExpression("([a]) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_single() {
-    expect(_isFunctionExpression("(a) {}"), isTrue);
-  }
-
-  void test_isFunctionExpression_parameter_typed() {
-    expect(_isFunctionExpression("(int a, int b) {}"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_assignment() {
-    expect(_isInitializedVariableDeclaration("a = null;"), isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_comparison() {
-    expect(_isInitializedVariableDeclaration("a < 0;"), isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_conditional() {
-    expect(_isInitializedVariableDeclaration("a == null ? init() : update();"),
-        isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_const_noType_initialized() {
-    expect(_isInitializedVariableDeclaration("const a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_const_noType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("const a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_const_simpleType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("const A a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_final_noType_initialized() {
-    expect(_isInitializedVariableDeclaration("final a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_final_noType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("final a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_final_simpleType_initialized() {
-    expect(_isInitializedVariableDeclaration("final A a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_functionDeclaration_typed() {
-    expect(_isInitializedVariableDeclaration("A f() {};"), isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_functionDeclaration_untyped() {
-    expect(_isInitializedVariableDeclaration("f() {};"), isFalse);
-  }
-
-  void test_isInitializedVariableDeclaration_noType_initialized() {
-    expect(_isInitializedVariableDeclaration("var a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_noType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("var a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_parameterizedType_initialized() {
-    expect(_isInitializedVariableDeclaration("List<int> a = null;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_parameterizedType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("List<int> a;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_simpleType_initialized() {
-    expect(_isInitializedVariableDeclaration("A a = 0;"), isTrue);
-  }
-
-  void test_isInitializedVariableDeclaration_simpleType_uninitialized() {
-    expect(_isInitializedVariableDeclaration("A a;"), isTrue);
-  }
-
-  void test_isSwitchMember_case_labeled() {
-    expect(_isSwitchMember("l1: l2: case"), isTrue);
-  }
-
-  void test_isSwitchMember_case_unlabeled() {
-    expect(_isSwitchMember("case"), isTrue);
-  }
-
-  void test_isSwitchMember_default_labeled() {
-    expect(_isSwitchMember("l1: l2: default"), isTrue);
-  }
-
-  void test_isSwitchMember_default_unlabeled() {
-    expect(_isSwitchMember("default"), isTrue);
-  }
-
-  void test_isSwitchMember_false() {
-    expect(_isSwitchMember("break;"), isFalse);
-  }
-
-  void test_parseDottedName_multiple() {
-    createParser('a.b.c');
-    DottedName name = parser.parseDottedName();
-    expectNotNullIfNoErrors(name);
-    assertNoErrors();
-    expectDottedName(name, ["a", "b", "c"]);
-  }
-
-  void test_parseDottedName_single() {
-    createParser('a');
-    DottedName name = parser.parseDottedName();
-    expectNotNullIfNoErrors(name);
-    assertNoErrors();
-    expectDottedName(name, ["a"]);
-  }
-
-  void test_parseFinalConstVarOrType_const_functionType() {
-    createParser('const int Function(int) f');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.CONST);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_const_namedType() {
-    createParser('const A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.CONST);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_const_noType() {
-    createParser('const');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.CONST);
-    expect(result.type, isNull);
-  }
-
-  void test_parseFinalConstVarOrType_final_functionType() {
-    createParser('final int Function(int) f');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.FINAL);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_final_namedType() {
-    createParser('final A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.FINAL);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_final_noType() {
-    createParser('final');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.FINAL);
-    expect(result.type, isNull);
-  }
-
-  void test_parseFinalConstVarOrType_final_prefixedType() {
-    createParser('final p.A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.FINAL);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_function() {
-    createParser('int Function(int) f');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_parameterized() {
-    createParser('A<B> a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_prefixed() {
-    createParser('p.A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_prefixed_noIdentifier() {
-    createParser('p.A,');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_prefixedAndParameterized() {
-    createParser('p.A<B> a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_simple() {
-    createParser('A a');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_type_simple_noIdentifier_inFunctionType() {
-    createParser('A,');
-    FinalConstVarOrType result =
-        parser.parseFinalConstVarOrType(false, inFunctionType: true);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_var() {
-    createParser('var');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    Token keyword = result.keyword;
-    expect(keyword, isNotNull);
-    expect(keyword.type.isKeyword, true);
-    expect(keyword.keyword, Keyword.VAR);
-    expect(result.type, isNull);
-  }
-
-  void test_parseFinalConstVarOrType_void() {
-    createParser('void f()');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_void_identifier() {
-    createParser('void x');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    assertNoErrors();
-    expect(result.keyword, isNull);
-    expect(result.type, isNotNull);
-  }
-
-  void test_parseFinalConstVarOrType_void_noIdentifier() {
-    createParser('void,');
-    FinalConstVarOrType result = parser.parseFinalConstVarOrType(false);
-    expectNotNullIfNoErrors(result);
-    listener.assertErrorsWithCodes(
-        [ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE]);
-  }
-
-  void test_parseFunctionBody_skip_block() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('{}');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isEmptyFunctionBody);
-  }
-
-  void test_parseFunctionBody_skip_block_invalid() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('{');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    listener.assertErrorsWithCodes([ScannerErrorCode.EXPECTED_TOKEN]);
-    expect(functionBody, isEmptyFunctionBody);
-  }
-
-  void test_parseFunctionBody_skip_blocks() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('{ {} }');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isEmptyFunctionBody);
-  }
-
-  void test_parseFunctionBody_skip_expression() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('=> y;');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isEmptyFunctionBody);
-  }
-
-  void test_parseModifiers_abstract() {
-    createParser('abstract A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.abstractKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_const() {
-    createParser('const A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.constKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_covariant() {
-    createParser('covariant A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.covariantKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_external() {
-    createParser('external A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.externalKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_factory() {
-    createParser('factory A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.factoryKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_final() {
-    createParser('final A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.finalKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_static() {
-    createParser('static A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.staticKeyword, isNotNull);
-  }
-
-  void test_parseModifiers_var() {
-    createParser('var A');
-    Modifiers modifiers = parser.parseModifiers();
-    expectNotNullIfNoErrors(modifiers);
-    assertNoErrors();
-    expect(modifiers.varKeyword, isNotNull);
-  }
-
-  void test_Parser() {
-    expect(
-      Parser(
-        NonExistingSource.unknown,
-        null,
-        featureSet: FeatureSet.forTesting(),
-      ),
-      isNotNull,
-    );
-  }
-
-  void test_skipPrefixedIdentifier_invalid() {
-    createParser('+');
-    Token following = parser.skipPrefixedIdentifier(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipPrefixedIdentifier_notPrefixed() {
-    createParser('a +');
-    Token following = parser.skipPrefixedIdentifier(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipPrefixedIdentifier_prefixed() {
-    createParser('a.b +');
-    Token following = parser.skipPrefixedIdentifier(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipReturnType_invalid() {
-    // TODO(eernst): `skipReturnType` eliminated, delete this test?
-    createParser('+');
-    Token following = parser.skipTypeAnnotation(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipReturnType_type() {
-    // TODO(eernst): `skipReturnType` eliminated, delete this test?
-    createParser('C +');
-    Token following = parser.skipTypeAnnotation(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipReturnType_void() {
-    // TODO(eernst): `skipReturnType` eliminated, delete this test?
-    createParser('void +');
-    Token following = parser.skipTypeAnnotation(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipSimpleIdentifier_identifier() {
-    createParser('i +');
-    Token following = parser.skipSimpleIdentifier(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipSimpleIdentifier_invalid() {
-    createParser('9 +');
-    Token following = parser.skipSimpleIdentifier(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipSimpleIdentifier_pseudoKeyword() {
-    createParser('as +');
-    Token following = parser.skipSimpleIdentifier(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipStringLiteral_adjacent() {
-    createParser("'a' 'b' +");
-    Token following = parser.skipStringLiteral(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipStringLiteral_interpolated() {
-    createParser("'a\${b}c' +");
-    Token following = parser.skipStringLiteral(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipStringLiteral_invalid() {
-    createParser('a');
-    Token following = parser.skipStringLiteral(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipStringLiteral_single() {
-    createParser("'a' +");
-    Token following = parser.skipStringLiteral(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipTypeArgumentList_invalid() {
-    createParser('+');
-    Token following = parser.skipTypeArgumentList(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipTypeArgumentList_multiple() {
-    createParser('<E, F, G> +');
-    Token following = parser.skipTypeArgumentList(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipTypeArgumentList_single() {
-    createParser('<E> +');
-    Token following = parser.skipTypeArgumentList(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipTypeName_invalid() {
-    createParser('+');
-    Token following = parser.skipTypeName(parser.currentToken);
-    expect(following, isNull);
-  }
-
-  void test_skipTypeName_parameterized() {
-    createParser('C<E<F<G>>> +');
-    Token following = parser.skipTypeName(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  void test_skipTypeName_simple() {
-    createParser('C +');
-    Token following = parser.skipTypeName(parser.currentToken);
-    expect(following, isNotNull);
-    expect(following.type, TokenType.PLUS);
-  }
-
-  /// Invoke the method [Parser.computeStringValue] with the given argument.
-  ///
-  /// @param lexeme the argument to the method
-  /// @param first `true` if this is the first token in a string literal
-  /// @param last `true` if this is the last token in a string literal
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  String _computeStringValue(String lexeme, bool first, bool last) {
-    createParser('');
-    String value = parser.computeStringValue(lexeme, first, last);
-    assertNoErrors();
-    return value;
-  }
-
-  /// Invoke the method [Parser.isFunctionDeclaration] with the parser set to
-  /// the token stream produced by scanning the given source.
-  ///
-  /// @param source the source to be scanned to produce the token stream being
-  ///          tested
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  bool _isFunctionDeclaration(String source) {
-    createParser(source);
-    bool result = parser.isFunctionDeclaration();
-    expectNotNullIfNoErrors(result);
-    return result;
-  }
-
-  /// Invoke the method [Parser.isFunctionExpression] with the parser set to the
-  /// token stream produced by scanning the given source.
-  ///
-  /// @param source the source to be scanned to produce the token stream being
-  ///          tested
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  bool _isFunctionExpression(String source) {
-    createParser(source);
-    return parser.isFunctionExpression(parser.currentToken);
-  }
-
-  /// Invoke the method [Parser.isInitializedVariableDeclaration] with the
-  /// parser set to the token stream produced by scanning the given source.
-  ///
-  /// @param source the source to be scanned to produce the token stream being
-  ///          tested
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  bool _isInitializedVariableDeclaration(String source) {
-    createParser(source);
-    bool result = parser.isInitializedVariableDeclaration();
-    expectNotNullIfNoErrors(result);
-    return result;
-  }
-
-  /// Invoke the method [Parser.isSwitchMember] with the parser set to the token
-  /// stream produced by scanning the given source.
-  ///
-  /// @param source the source to be scanned to produce the token stream being
-  ///          tested
-  /// @return the result of invoking the method
-  /// @throws Exception if the method could not be invoked or throws an
-  ///           exception
-  bool _isSwitchMember(String source) {
-    createParser(source);
-    bool result = parser.isSwitchMember();
-    expectNotNullIfNoErrors(result);
-    return result;
-  }
-}
-
-/// Parser tests that test individual parsing methods. The code fragments should
-/// be as minimal as possible in order to test the method, but should not test
-/// the interactions between the method under test and other methods.
-///
-/// More complex tests should be defined in the class [ComplexParserTest].
-mixin SimpleParserTestMixin implements AbstractParserTestCase {
-  ConstructorName parseConstructorName(String name) {
-    createParser('new $name();');
-    Statement statement = parser.parseStatement2();
-    expect(statement, isExpressionStatement);
-    Expression expression = (statement as ExpressionStatement).expression;
-    expect(expression, isInstanceCreationExpression);
-    return (expression as InstanceCreationExpression).constructorName;
-  }
-
-  ExtendsClause parseExtendsClause(String clause) {
-    createParser('class TestClass $clause {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(1));
-    ClassDeclaration classDecl = unit.declarations[0];
-    expect(classDecl, isNotNull);
-    return classDecl.extendsClause;
-  }
-
-  List<SimpleIdentifier> parseIdentifierList(String identifiers) {
-    createParser('show $identifiers');
-    List<Combinator> combinators = parser.parseCombinators();
-    expect(combinators, hasLength(1));
-    return (combinators[0] as ShowCombinator).shownNames;
-  }
-
-  ImplementsClause parseImplementsClause(String clause) {
-    createParser('class TestClass $clause {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(1));
-    ClassDeclaration classDecl = unit.declarations[0];
-    expect(classDecl, isNotNull);
-    return classDecl.implementsClause;
-  }
-
-  LibraryIdentifier parseLibraryIdentifier(String name) {
-    createParser('library $name;');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    expect(unit.directives, hasLength(1));
-    LibraryDirective directive = unit.directives[0];
-    return directive.name;
-  }
-
-  /// Parse the given [content] as a sequence of statements by enclosing it in a
-  /// block. The [expectedCount] is the number of statements that are expected
-  /// to be parsed. If [errorCodes] are provided, verify that the error codes of
-  /// the errors that are expected are found.
-  void parseStatementList(String content, int expectedCount) {
-    Statement statement = parseStatement('{$content}');
-    expect(statement, isBlock);
-    Block block = statement;
-    expect(block.statements, hasLength(expectedCount));
-  }
-
-  VariableDeclaration parseVariableDeclaration(String declaration) {
-    createParser(declaration);
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(1));
-    TopLevelVariableDeclaration decl = unit.declarations[0];
-    expect(decl, isNotNull);
-    return decl.variables.variables[0];
-  }
-
-  WithClause parseWithClause(String clause) {
-    createParser('class TestClass extends Object $clause {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(1));
-    ClassDeclaration classDecl = unit.declarations[0];
-    expect(classDecl, isNotNull);
-    return classDecl.withClause;
-  }
-
-  void test_classDeclaration_complexTypeParam() {
-    CompilationUnit unit = parseCompilationUnit('''
-class C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T> {}
-''');
-    ClassDeclaration clazz = unit.declarations[0];
-    expect(clazz.name.name, 'C');
-    expect(clazz.typeParameters.typeParameters, hasLength(1));
-    TypeParameter typeParameter = clazz.typeParameters.typeParameters[0];
-    expect(typeParameter.name.name, 'T');
-    expect(typeParameter.metadata, hasLength(1));
-    Annotation metadata = typeParameter.metadata[0];
-    expect(metadata.name.name, 'Foo.bar');
-  }
-
-  void test_parseAnnotation_n1() {
-    createParser('@A');
-    Annotation annotation = parser.parseAnnotation();
-    expectNotNullIfNoErrors(annotation);
-    assertNoErrors();
-    expect(annotation.atSign, isNotNull);
-    expect(annotation.name, isNotNull);
-    expect(annotation.period, isNull);
-    expect(annotation.constructorName, isNull);
-    expect(annotation.arguments, isNull);
-  }
-
-  void test_parseAnnotation_n1_a() {
-    createParser('@A(x,y)');
-    Annotation annotation = parser.parseAnnotation();
-    expectNotNullIfNoErrors(annotation);
-    assertNoErrors();
-    expect(annotation.atSign, isNotNull);
-    expect(annotation.name, isNotNull);
-    expect(annotation.period, isNull);
-    expect(annotation.constructorName, isNull);
-    expect(annotation.arguments, isNotNull);
-  }
-
-  void test_parseAnnotation_n2() {
-    createParser('@A.B');
-    Annotation annotation = parser.parseAnnotation();
-    expectNotNullIfNoErrors(annotation);
-    assertNoErrors();
-    expect(annotation.atSign, isNotNull);
-    expect(annotation.name, isNotNull);
-    expect(annotation.period, isNull);
-    expect(annotation.constructorName, isNull);
-    expect(annotation.arguments, isNull);
-  }
-
-  void test_parseAnnotation_n2_a() {
-    createParser('@A.B(x,y)');
-    Annotation annotation = parser.parseAnnotation();
-    expectNotNullIfNoErrors(annotation);
-    assertNoErrors();
-    expect(annotation.atSign, isNotNull);
-    expect(annotation.name, isNotNull);
-    expect(annotation.period, isNull);
-    expect(annotation.constructorName, isNull);
-    expect(annotation.arguments, isNotNull);
-  }
-
-  void test_parseAnnotation_n3() {
-    createParser('@A.B.C');
-    Annotation annotation = parser.parseAnnotation();
-    expectNotNullIfNoErrors(annotation);
-    assertNoErrors();
-    expect(annotation.atSign, isNotNull);
-    expect(annotation.name, isNotNull);
-    expect(annotation.period, isNotNull);
-    expect(annotation.constructorName, isNotNull);
-    expect(annotation.arguments, isNull);
-  }
-
-  void test_parseAnnotation_n3_a() {
-    createParser('@A.B.C(x,y)');
-    Annotation annotation = parser.parseAnnotation();
-    expectNotNullIfNoErrors(annotation);
-    assertNoErrors();
-    expect(annotation.atSign, isNotNull);
-    expect(annotation.name, isNotNull);
-    expect(annotation.period, isNotNull);
-    expect(annotation.constructorName, isNotNull);
-    expect(annotation.arguments, isNotNull);
-  }
-
-  void test_parseArgumentList_empty() {
-    createParser('()');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    NodeList<Expression> arguments = argumentList.arguments;
-    expect(arguments, hasLength(0));
-  }
-
-  void test_parseArgumentList_mixed() {
-    createParser('(w, x, y: y, z: z)');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    NodeList<Expression> arguments = argumentList.arguments;
-    expect(arguments, hasLength(4));
-  }
-
-  void test_parseArgumentList_noNamed() {
-    createParser('(x, y, z)');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    NodeList<Expression> arguments = argumentList.arguments;
-    expect(arguments, hasLength(3));
-  }
-
-  void test_parseArgumentList_onlyNamed() {
-    createParser('(x: x, y: y)');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    NodeList<Expression> arguments = argumentList.arguments;
-    expect(arguments, hasLength(2));
-  }
-
-  void test_parseArgumentList_trailing_comma() {
-    createParser('(x, y, z,)');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    NodeList<Expression> arguments = argumentList.arguments;
-    expect(arguments, hasLength(3));
-  }
-
-  void test_parseArgumentList_typeArguments() {
-    createParser('(a<b,c>(d))');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    NodeList<Expression> arguments = argumentList.arguments;
-    expect(arguments, hasLength(1));
-  }
-
-  void test_parseArgumentList_typeArguments_none() {
-    createParser('(a<b,p.q.c>(d))');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    NodeList<Expression> arguments = argumentList.arguments;
-    expect(arguments, hasLength(2));
-  }
-
-  void test_parseArgumentList_typeArguments_prefixed() {
-    createParser('(a<b,p.c>(d))');
-    ArgumentList argumentList = parser.parseArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    NodeList<Expression> arguments = argumentList.arguments;
-    expect(arguments, hasLength(1));
-  }
-
-  void test_parseCombinators_h() {
-    createParser('hide a');
-    List<Combinator> combinators = parser.parseCombinators();
-    expectNotNullIfNoErrors(combinators);
-    assertNoErrors();
-    expect(combinators, hasLength(1));
-    HideCombinator combinator = combinators[0] as HideCombinator;
-    expect(combinator, isNotNull);
-    expect(combinator.keyword, isNotNull);
-    expect(combinator.hiddenNames, hasLength(1));
-  }
-
-  void test_parseCombinators_hs() {
-    createParser('hide a show b');
-    List<Combinator> combinators = parser.parseCombinators();
-    expectNotNullIfNoErrors(combinators);
-    assertNoErrors();
-    expect(combinators, hasLength(2));
-    HideCombinator hideCombinator = combinators[0] as HideCombinator;
-    expect(hideCombinator, isNotNull);
-    expect(hideCombinator.keyword, isNotNull);
-    expect(hideCombinator.hiddenNames, hasLength(1));
-    ShowCombinator showCombinator = combinators[1] as ShowCombinator;
-    expect(showCombinator, isNotNull);
-    expect(showCombinator.keyword, isNotNull);
-    expect(showCombinator.shownNames, hasLength(1));
-  }
-
-  void test_parseCombinators_hshs() {
-    createParser('hide a show b hide c show d');
-    List<Combinator> combinators = parser.parseCombinators();
-    expectNotNullIfNoErrors(combinators);
-    assertNoErrors();
-    expect(combinators, hasLength(4));
-  }
-
-  void test_parseCombinators_s() {
-    createParser('show a');
-    List<Combinator> combinators = parser.parseCombinators();
-    expectNotNullIfNoErrors(combinators);
-    assertNoErrors();
-    expect(combinators, hasLength(1));
-    ShowCombinator combinator = combinators[0] as ShowCombinator;
-    expect(combinator, isNotNull);
-    expect(combinator.keyword, isNotNull);
-    expect(combinator.shownNames, hasLength(1));
-  }
-
-  void test_parseCommentAndMetadata_c() {
-    createParser('/** 1 */ class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNotNull);
-    expect(declaration.metadata, isEmpty);
-  }
-
-  void test_parseCommentAndMetadata_cmc() {
-    createParser('/** 1 */ @A /** 2 */ class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    Comment comment = declaration.documentationComment;
-    expect(comment.isDocumentation, isTrue);
-    expect(comment.tokens, hasLength(1));
-    expect(comment.tokens[0].lexeme, '/** 2 */');
-    expect(declaration.metadata, hasLength(1));
-  }
-
-  void test_parseCommentAndMetadata_cmcm() {
-    createParser('/** 1 */ @A /** 2 */ @B class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNotNull);
-    expect(declaration.metadata, hasLength(2));
-  }
-
-  void test_parseCommentAndMetadata_cmm() {
-    createParser('/** 1 */ @A @B class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNotNull);
-    expect(declaration.metadata, hasLength(2));
-  }
-
-  void test_parseCommentAndMetadata_m() {
-    createParser('@A class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.metadata, hasLength(1));
-  }
-
-  void test_parseCommentAndMetadata_mcm() {
-    createParser('@A /** 1 */ @B class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNotNull);
-    expect(declaration.metadata, hasLength(2));
-  }
-
-  void test_parseCommentAndMetadata_mcmc() {
-    createParser('@A /** 1 */ @B /** 2 */ class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNotNull);
-    expect(declaration.documentationComment.tokens[0].lexeme, contains('2'));
-    expect(declaration.metadata, hasLength(2));
-  }
-
-  void test_parseCommentAndMetadata_mix1() {
-    createParser(r'''
-/**
- * aaa
- */
-/**
- * bbb
- */
-class A {}
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.metadata, hasLength(0));
-    List<Token> tokens = declaration.documentationComment.tokens;
-    expect(tokens, hasLength(1));
-    expect(tokens[0].lexeme, contains('bbb'));
-  }
-
-  void test_parseCommentAndMetadata_mix2() {
-    createParser(r'''
-/**
- * aaa
- */
-/// bbb
-/// ccc
-class B {}
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.metadata, hasLength(0));
-    List<Token> tokens = declaration.documentationComment.tokens;
-    expect(tokens, hasLength(2));
-    expect(tokens[0].lexeme, contains('bbb'));
-    expect(tokens[1].lexeme, contains('ccc'));
-  }
-
-  void test_parseCommentAndMetadata_mix3() {
-    createParser(r'''
-/// aaa
-/// bbb
-/**
- * ccc
- */
-class C {}
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.metadata, hasLength(0));
-    List<Token> tokens = declaration.documentationComment.tokens;
-    expect(tokens, hasLength(1));
-    expect(tokens[0].lexeme, contains('ccc'));
-  }
-
-  test_parseCommentAndMetadata_mix4() {
-    createParser(r'''
-/// aaa
-/// bbb
-/**
- * ccc
- */
-/// ddd
-class D {}
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.metadata, hasLength(0));
-    List<Token> tokens = declaration.documentationComment.tokens;
-    expect(tokens, hasLength(1));
-    expect(tokens[0].lexeme, contains('ddd'));
-  }
-
-  test_parseCommentAndMetadata_mix5() {
-    createParser(r'''
-/**
- * aaa
- */
-// bbb
-class E {}
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.metadata, hasLength(0));
-    List<Token> tokens = declaration.documentationComment.tokens;
-    expect(tokens, hasLength(1));
-    expect(tokens[0].lexeme, contains('aaa'));
-  }
-
-  void test_parseCommentAndMetadata_mm() {
-    createParser('@A @B(x) class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.metadata, hasLength(2));
-  }
-
-  void test_parseCommentAndMetadata_none() {
-    createParser('class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.metadata, isEmpty);
-  }
-
-  void test_parseCommentAndMetadata_singleLine() {
-    createParser(r'''
-/// 1
-/// 2
-class C {}
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expectNotNullIfNoErrors(unit);
-    assertNoErrors();
-    ClassDeclaration declaration = unit.declarations[0];
-    expect(declaration.documentationComment, isNotNull);
-    expect(declaration.metadata, isEmpty);
-  }
-
-  void test_parseCommentReference_new_prefixed() {
-    createParser('');
-    CommentReference reference = parseCommentReference('new a.b', 7);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isPrefixedIdentifier);
-    PrefixedIdentifier prefixedIdentifier = reference.identifier;
-    SimpleIdentifier prefix = prefixedIdentifier.prefix;
-    expect(prefix.token, isNotNull);
-    expect(prefix.name, "a");
-    expect(prefix.offset, 11);
-    expect(prefixedIdentifier.period, isNotNull);
-    SimpleIdentifier identifier = prefixedIdentifier.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "b");
-    expect(identifier.offset, 13);
-  }
-
-  void test_parseCommentReference_new_simple() {
-    createParser('');
-    CommentReference reference = parseCommentReference('new a', 5);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isSimpleIdentifier);
-    SimpleIdentifier identifier = reference.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "a");
-    expect(identifier.offset, 9);
-  }
-
-  void test_parseCommentReference_operator_withKeyword_notPrefixed() {
-    createParser('');
-    CommentReference reference = parseCommentReference('operator ==', 5);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isSimpleIdentifier);
-    SimpleIdentifier identifier = reference.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "==");
-    expect(identifier.offset, 14);
-  }
-
-  void test_parseCommentReference_operator_withKeyword_prefixed() {
-    createParser('');
-    CommentReference reference = parseCommentReference('Object.operator==', 7);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isPrefixedIdentifier);
-    PrefixedIdentifier prefixedIdentifier = reference.identifier;
-    SimpleIdentifier prefix = prefixedIdentifier.prefix;
-    expect(prefix.token, isNotNull);
-    expect(prefix.name, "Object");
-    expect(prefix.offset, 7);
-    expect(prefixedIdentifier.period, isNotNull);
-    SimpleIdentifier identifier = prefixedIdentifier.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "==");
-    expect(identifier.offset, 22);
-  }
-
-  void test_parseCommentReference_operator_withoutKeyword_notPrefixed() {
-    createParser('');
-    CommentReference reference = parseCommentReference('==', 5);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isSimpleIdentifier);
-    SimpleIdentifier identifier = reference.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "==");
-    expect(identifier.offset, 5);
-  }
-
-  void test_parseCommentReference_operator_withoutKeyword_prefixed() {
-    createParser('');
-    CommentReference reference = parseCommentReference('Object.==', 7);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isPrefixedIdentifier);
-    PrefixedIdentifier prefixedIdentifier = reference.identifier;
-    SimpleIdentifier prefix = prefixedIdentifier.prefix;
-    expect(prefix.token, isNotNull);
-    expect(prefix.name, "Object");
-    expect(prefix.offset, 7);
-    expect(prefixedIdentifier.period, isNotNull);
-    SimpleIdentifier identifier = prefixedIdentifier.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "==");
-    expect(identifier.offset, 14);
-  }
-
-  void test_parseCommentReference_prefixed() {
-    createParser('');
-    CommentReference reference = parseCommentReference('a.b', 7);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isPrefixedIdentifier);
-    PrefixedIdentifier prefixedIdentifier = reference.identifier;
-    SimpleIdentifier prefix = prefixedIdentifier.prefix;
-    expect(prefix.token, isNotNull);
-    expect(prefix.name, "a");
-    expect(prefix.offset, 7);
-    expect(prefixedIdentifier.period, isNotNull);
-    SimpleIdentifier identifier = prefixedIdentifier.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "b");
-    expect(identifier.offset, 9);
-  }
-
-  void test_parseCommentReference_simple() {
-    createParser('');
-    CommentReference reference = parseCommentReference('a', 5);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isSimpleIdentifier);
-    SimpleIdentifier identifier = reference.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "a");
-    expect(identifier.offset, 5);
-  }
-
-  void test_parseCommentReference_synthetic() {
-    createParser('');
-    CommentReference reference = parseCommentReference('', 5);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    expect(reference.identifier, isSimpleIdentifier);
-    SimpleIdentifier identifier = reference.identifier;
-    expect(identifier, isNotNull);
-    expect(identifier.isSynthetic, isTrue);
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "");
-    expect(identifier.offset, 5);
-    // Should end with EOF token.
-    Token nextToken = identifier.token.next;
-    expect(nextToken, isNotNull);
-    expect(nextToken.type, TokenType.EOF);
-  }
-
-  @failingTest
-  void test_parseCommentReference_this() {
-    // This fails because we are returning null from the method and asserting
-    // that the return value is not null.
-    createParser('');
-    CommentReference reference = parseCommentReference('this', 5);
-    expectNotNullIfNoErrors(reference);
-    assertNoErrors();
-    SimpleIdentifier identifier = reference.identifier;
-    expect(identifier.token, isNotNull);
-    expect(identifier.name, "a");
-    expect(identifier.offset, 5);
-  }
-
-  void test_parseCommentReferences_33738() {
-    CompilationUnit unit =
-        parseCompilationUnit('/** [String] */ abstract class Foo {}');
-    ClassDeclaration clazz = unit.declarations[0];
-    Comment comment = clazz.documentationComment;
-    expect(clazz.isAbstract, isTrue);
-    List<CommentReference> references = comment.references;
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 5);
-  }
-
-  void test_parseCommentReferences_beforeAnnotation() {
-    CompilationUnit unit = parseCompilationUnit('''
-/// See [int] and [String]
-/// and [Object].
-@Annotation
-abstract class Foo {}
-''');
-    ClassDeclaration clazz = unit.declarations[0];
-    Comment comment = clazz.documentationComment;
-    expect(clazz.isAbstract, isTrue);
-    List<CommentReference> references = comment.references;
-    expect(references, hasLength(3));
-
-    expectReference(int index, String expectedText, int expectedOffset) {
-      CommentReference reference = references[index];
-      expect(reference.identifier.name, expectedText);
-      expect(reference.offset, expectedOffset);
-    }
-
-    expectReference(0, 'int', 9);
-    expectReference(1, 'String', 19);
-    expectReference(2, 'Object', 36);
-  }
-
-  void test_parseCommentReferences_complex() {
-    CompilationUnit unit = parseCompilationUnit('''
-/// This dartdoc comment [should] be ignored
-@Annotation
-/// This dartdoc comment is [included].
-// a non dartdoc comment [inbetween]
-/// See [int] and [String] but `not [a]`
-/// ```
-/// This [code] block should be ignored
-/// ```
-/// and [Object].
-abstract class Foo {}
-''');
-    ClassDeclaration clazz = unit.declarations[0];
-    Comment comment = clazz.documentationComment;
-    expect(clazz.isAbstract, isTrue);
-    List<CommentReference> references = comment.references;
-    expect(references, hasLength(4));
-
-    expectReference(int index, String expectedText, int expectedOffset) {
-      CommentReference reference = references[index];
-      expect(reference.identifier.name, expectedText);
-      expect(reference.offset, expectedOffset);
-    }
-
-    expectReference(0, 'included', 86);
-    expectReference(1, 'int', 143);
-    expectReference(2, 'String', 153);
-    expectReference(3, 'Object', 240);
-  }
-
-  void test_parseCommentReferences_multiLine() {
-    DocumentationCommentToken token = DocumentationCommentToken(
-        TokenType.MULTI_LINE_COMMENT, "/** xxx [a] yyy [bb] zzz */", 3);
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[token];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(2));
-    {
-      CommentReference reference = references[0];
-      expect(reference, isNotNull);
-      expect(reference.identifier, isNotNull);
-      expect(reference.offset, 12);
-      Token referenceToken = reference.identifier.beginToken;
-      expect(referenceToken.offset, 12);
-      expect(referenceToken.lexeme, 'a');
-    }
-    {
-      CommentReference reference = references[1];
-      expect(reference, isNotNull);
-      expect(reference.identifier, isNotNull);
-      expect(reference.offset, 20);
-      Token referenceToken = reference.identifier.beginToken;
-      expect(referenceToken.offset, 20);
-      expect(referenceToken.lexeme, 'bb');
-    }
-  }
-
-  void test_parseCommentReferences_notClosed_noIdentifier() {
-    DocumentationCommentToken docToken = DocumentationCommentToken(
-        TokenType.MULTI_LINE_COMMENT, "/** [ some text", 5);
-    createParser('');
-    List<CommentReference> references =
-        parser.parseCommentReferences(<DocumentationCommentToken>[docToken]);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    Token referenceToken = reference.identifier.beginToken;
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.identifier.isSynthetic, isTrue);
-    expect(reference.identifier.name, "");
-    // Should end with EOF token.
-    Token nextToken = referenceToken.next;
-    expect(nextToken, isNotNull);
-    expect(nextToken.type, TokenType.EOF);
-  }
-
-  void test_parseCommentReferences_notClosed_withIdentifier() {
-    DocumentationCommentToken docToken = DocumentationCommentToken(
-        TokenType.MULTI_LINE_COMMENT, "/** [namePrefix some text", 5);
-    createParser('');
-    List<CommentReference> references =
-        parser.parseCommentReferences(<DocumentationCommentToken>[docToken]);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    Token referenceToken = reference.identifier.beginToken;
-    expect(reference, isNotNull);
-    expect(referenceToken, same(reference.beginToken));
-    expect(reference.identifier, isNotNull);
-    expect(reference.identifier.isSynthetic, isFalse);
-    expect(reference.identifier.name, "namePrefix");
-    // Should end with EOF token.
-    Token nextToken = referenceToken.next;
-    expect(nextToken, isNotNull);
-    expect(nextToken.type, TokenType.EOF);
-  }
-
-  void test_parseCommentReferences_singleLine() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.SINGLE_LINE_COMMENT, "/// xxx [a] yyy [b] zzz", 3),
-      DocumentationCommentToken(TokenType.SINGLE_LINE_COMMENT, "/// x [c]", 28)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(3));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 12);
-    reference = references[1];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 20);
-    reference = references[2];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 35);
-  }
-
-  void test_parseCommentReferences_skipCodeBlock_4spaces_block() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
-          "/**\n *     a[i]\n * non-code line\n */", 3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, isEmpty);
-  }
-
-  void test_parseCommentReferences_skipCodeBlock_4spaces_lines() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.SINGLE_LINE_COMMENT, "/// Code block:", 0),
-      DocumentationCommentToken(
-          TokenType.SINGLE_LINE_COMMENT, "///     a[i] == b[i]", 0)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, isEmpty);
-  }
-
-  void test_parseCommentReferences_skipCodeBlock_bracketed() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.MULTI_LINE_COMMENT, "/** [:xxx [a] yyy:] [b] zzz */", 3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 24);
-  }
-
-  void test_parseCommentReferences_skipCodeBlock_gitHub() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.MULTI_LINE_COMMENT, "/** `a[i]` and [b] */", 0)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 16);
-  }
-
-  void test_parseCommentReferences_skipCodeBlock_gitHub_multiLine() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.MULTI_LINE_COMMENT,
-          r'''
-/**
- * First.
- * ```dart
- * Some [int] reference.
- * ```
- * Last.
- */
-''',
-          3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, isEmpty);
-  }
-
-  void test_parseCommentReferences_skipCodeBlock_gitHub_multiLine_lines() {
-    String commentText = r'''
-/// First.
-/// ```dart
-/// Some [int] reference.
-/// ```
-/// Last.
-''';
-    List<DocumentationCommentToken> tokens = commentText
-        .split('\n')
-        .map((line) =>
-            DocumentationCommentToken(TokenType.SINGLE_LINE_COMMENT, line, 0))
-        .toList();
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, isEmpty);
-  }
-
-  void test_parseCommentReferences_skipCodeBlock_gitHub_notTerminated() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.MULTI_LINE_COMMENT, "/** `a[i] and [b] */", 0)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(2));
-  }
-
-  void test_parseCommentReferences_skipCodeBlock_spaces() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
-          "/**\n *     a[i]\n * xxx [i] zzz\n */", 3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 27);
-  }
-
-  void test_parseCommentReferences_skipLink_direct_multiLine() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.MULTI_LINE_COMMENT,
-          '''
-/**
- * [a link split across multiple
- * lines](http://www.google.com) [b] zzz
- */
-''',
-          3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 74);
-  }
-
-  void test_parseCommentReferences_skipLink_direct_singleLine() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
-          "/** [a](http://www.google.com) [b] zzz */", 3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 35);
-  }
-
-  void test_parseCommentReferences_skipLink_reference_multiLine() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.MULTI_LINE_COMMENT,
-          '''
-/**
- * [a link split across multiple
- * lines][c] [b] zzz
- */
-''',
-          3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 54);
-  }
-
-  void test_parseCommentReferences_skipLink_reference_singleLine() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(
-          TokenType.MULTI_LINE_COMMENT, "/** [a][c] [b] zzz */", 3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 15);
-  }
-
-  void test_parseCommentReferences_skipLinkDefinition() {
-    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
-      DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
-          "/** [a]: http://www.google.com (Google) [b] zzz */", 3)
-    ];
-    createParser('');
-    List<CommentReference> references = parser.parseCommentReferences(tokens);
-    expectNotNullIfNoErrors(references);
-    assertNoErrors();
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.identifier, isNotNull);
-    expect(reference.offset, 44);
-  }
-
-  void test_parseConfiguration_noOperator_dottedIdentifier() {
-    createParser("if (a.b) 'c.dart'");
-    Configuration configuration = parser.parseConfiguration();
-    expectNotNullIfNoErrors(configuration);
-    assertNoErrors();
-    expect(configuration.ifKeyword, isNotNull);
-    expect(configuration.leftParenthesis, isNotNull);
-    expectDottedName(configuration.name, ["a", "b"]);
-    expect(configuration.equalToken, isNull);
-    expect(configuration.value, isNull);
-    expect(configuration.rightParenthesis, isNotNull);
-    expect(configuration.uri, isNotNull);
-  }
-
-  void test_parseConfiguration_noOperator_simpleIdentifier() {
-    createParser("if (a) 'b.dart'");
-    Configuration configuration = parser.parseConfiguration();
-    expectNotNullIfNoErrors(configuration);
-    assertNoErrors();
-    expect(configuration.ifKeyword, isNotNull);
-    expect(configuration.leftParenthesis, isNotNull);
-    expectDottedName(configuration.name, ["a"]);
-    expect(configuration.equalToken, isNull);
-    expect(configuration.value, isNull);
-    expect(configuration.rightParenthesis, isNotNull);
-    expect(configuration.uri, isNotNull);
-  }
-
-  void test_parseConfiguration_operator_dottedIdentifier() {
-    createParser("if (a.b == 'c') 'd.dart'");
-    Configuration configuration = parser.parseConfiguration();
-    expectNotNullIfNoErrors(configuration);
-    assertNoErrors();
-    expect(configuration.ifKeyword, isNotNull);
-    expect(configuration.leftParenthesis, isNotNull);
-    expectDottedName(configuration.name, ["a", "b"]);
-    expect(configuration.equalToken, isNotNull);
-    expect(configuration.value, isNotNull);
-    expect(configuration.rightParenthesis, isNotNull);
-    expect(configuration.uri, isNotNull);
-  }
-
-  void test_parseConfiguration_operator_simpleIdentifier() {
-    createParser("if (a == 'b') 'c.dart'");
-    Configuration configuration = parser.parseConfiguration();
-    expectNotNullIfNoErrors(configuration);
-    assertNoErrors();
-    expect(configuration.ifKeyword, isNotNull);
-    expect(configuration.leftParenthesis, isNotNull);
-    expectDottedName(configuration.name, ["a"]);
-    expect(configuration.equalToken, isNotNull);
-    expect(configuration.value, isNotNull);
-    expect(configuration.rightParenthesis, isNotNull);
-    expect(configuration.uri, isNotNull);
-  }
-
-  void test_parseConstructorName_named_noPrefix() {
-    ConstructorName name = parseConstructorName('A.n');
-    expectNotNullIfNoErrors(name);
-    assertNoErrors();
-    expect(name.type, isNotNull);
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-  }
-
-  void test_parseConstructorName_named_prefixed() {
-    ConstructorName name = parseConstructorName('p.A.n');
-    expectNotNullIfNoErrors(name);
-    assertNoErrors();
-    expect(name.type, isNotNull);
-    expect(name.period, isNotNull);
-    expect(name.name, isNotNull);
-  }
-
-  void test_parseConstructorName_unnamed_noPrefix() {
-    ConstructorName name = parseConstructorName('A');
-    expectNotNullIfNoErrors(name);
-    assertNoErrors();
-    expect(name.type, isNotNull);
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-  }
-
-  void test_parseConstructorName_unnamed_prefixed() {
-    ConstructorName name = parseConstructorName('p.A');
-    expectNotNullIfNoErrors(name);
-    assertNoErrors();
-    expect(name.type, isNotNull);
-    expect(name.period, isNull);
-    expect(name.name, isNull);
-  }
-
-  void test_parseDocumentationComment_block() {
-    createParser('/** */ class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    Comment comment = unit.declarations[0].documentationComment;
-    expectNotNullIfNoErrors(comment);
-    assertNoErrors();
-    expect(comment.isBlock, isFalse);
-    expect(comment.isDocumentation, isTrue);
-    expect(comment.isEndOfLine, isFalse);
-  }
-
-  void test_parseDocumentationComment_block_withReference() {
-    createParser('/** [a] */ class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    Comment comment = unit.declarations[0].documentationComment;
-    expectNotNullIfNoErrors(comment);
-    assertNoErrors();
-    expect(comment.isBlock, isFalse);
-    expect(comment.isDocumentation, isTrue);
-    expect(comment.isEndOfLine, isFalse);
-    NodeList<CommentReference> references = comment.references;
-    expect(references, hasLength(1));
-    CommentReference reference = references[0];
-    expect(reference, isNotNull);
-    expect(reference.offset, 5);
-  }
-
-  void test_parseDocumentationComment_endOfLine() {
-    createParser('/// \n/// \n class C {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    Comment comment = unit.declarations[0].documentationComment;
-    expectNotNullIfNoErrors(comment);
-    assertNoErrors();
-    expect(comment.isBlock, isFalse);
-    expect(comment.isDocumentation, isTrue);
-    expect(comment.isEndOfLine, isFalse);
-  }
-
-  void test_parseExtendsClause() {
-    ExtendsClause clause = parseExtendsClause('extends B');
-    expectNotNullIfNoErrors(clause);
-    assertNoErrors();
-    expect(clause.extendsKeyword, isNotNull);
-    expect(clause.superclass, isNotNull);
-    expect(clause.superclass, isTypeName);
-  }
-
-  void test_parseFunctionBody_block() {
-    createParser('{}');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isBlockFunctionBody);
-    BlockFunctionBody body = functionBody;
-    expect(body.keyword, isNull);
-    expect(body.star, isNull);
-    expect(body.block, isNotNull);
-    expect(body.isAsynchronous, isFalse);
-    expect(body.isGenerator, isFalse);
-    expect(body.isSynchronous, isTrue);
-  }
-
-  void test_parseFunctionBody_block_async() {
-    createParser('async {}');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isBlockFunctionBody);
-    BlockFunctionBody body = functionBody;
-    expect(body.keyword, isNotNull);
-    expect(body.keyword.lexeme, Parser.ASYNC);
-    expect(body.star, isNull);
-    expect(body.block, isNotNull);
-    expect(body.isAsynchronous, isTrue);
-    expect(body.isGenerator, isFalse);
-    expect(body.isSynchronous, isFalse);
-  }
-
-  void test_parseFunctionBody_block_asyncGenerator() {
-    createParser('async* {}');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isBlockFunctionBody);
-    BlockFunctionBody body = functionBody;
-    expect(body.keyword, isNotNull);
-    expect(body.keyword.lexeme, Parser.ASYNC);
-    expect(body.star, isNotNull);
-    expect(body.block, isNotNull);
-    expect(body.isAsynchronous, isTrue);
-    expect(body.isGenerator, isTrue);
-    expect(body.isSynchronous, isFalse);
-  }
-
-  void test_parseFunctionBody_block_syncGenerator() {
-    createParser('sync* {}');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isBlockFunctionBody);
-    BlockFunctionBody body = functionBody;
-    expect(body.keyword, isNotNull);
-    expect(body.keyword.lexeme, Parser.SYNC);
-    expect(body.star, isNotNull);
-    expect(body.block, isNotNull);
-    expect(body.isAsynchronous, isFalse);
-    expect(body.isGenerator, isTrue);
-    expect(body.isSynchronous, isTrue);
-  }
-
-  void test_parseFunctionBody_empty() {
-    createParser(';');
-    FunctionBody functionBody = parser.parseFunctionBody(true, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isEmptyFunctionBody);
-    EmptyFunctionBody body = functionBody;
-    expect(body.semicolon, isNotNull);
-  }
-
-  void test_parseFunctionBody_expression() {
-    createParser('=> y;');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isExpressionFunctionBody);
-    ExpressionFunctionBody body = functionBody;
-    expect(body.keyword, isNull);
-    expect(body.functionDefinition, isNotNull);
-    expect(body.expression, isNotNull);
-    expect(body.semicolon, isNotNull);
-    expect(body.isAsynchronous, isFalse);
-    expect(body.isGenerator, isFalse);
-    expect(body.isSynchronous, isTrue);
-  }
-
-  void test_parseFunctionBody_expression_async() {
-    createParser('async => y;');
-    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
-    expectNotNullIfNoErrors(functionBody);
-    assertNoErrors();
-    expect(functionBody, isExpressionFunctionBody);
-    ExpressionFunctionBody body = functionBody;
-    expect(body.keyword, isNotNull);
-    expect(body.keyword.lexeme, Parser.ASYNC);
-    expect(body.functionDefinition, isNotNull);
-    expect(body.expression, isNotNull);
-    expect(body.semicolon, isNotNull);
-    expect(body.isAsynchronous, isTrue);
-    expect(body.isGenerator, isFalse);
-    expect(body.isSynchronous, isFalse);
-  }
-
-  void test_parseIdentifierList_multiple() {
-    List<SimpleIdentifier> list = parseIdentifierList('a, b, c');
-    expectNotNullIfNoErrors(list);
-    assertNoErrors();
-    expect(list, hasLength(3));
-  }
-
-  void test_parseIdentifierList_single() {
-    List<SimpleIdentifier> list = parseIdentifierList('a');
-    expectNotNullIfNoErrors(list);
-    assertNoErrors();
-    expect(list, hasLength(1));
-  }
-
-  void test_parseImplementsClause_multiple() {
-    ImplementsClause clause = parseImplementsClause('implements A, B, C');
-    expectNotNullIfNoErrors(clause);
-    assertNoErrors();
-    expect(clause.interfaces, hasLength(3));
-    expect(clause.implementsKeyword, isNotNull);
-  }
-
-  void test_parseImplementsClause_single() {
-    ImplementsClause clause = parseImplementsClause('implements A');
-    expectNotNullIfNoErrors(clause);
-    assertNoErrors();
-    expect(clause.interfaces, hasLength(1));
-    expect(clause.implementsKeyword, isNotNull);
-  }
-
-  void test_parseInstanceCreation_keyword_33647() {
-    enableOptionalNewAndConst = true;
-    CompilationUnit unit = parseCompilationUnit('''
-var c = new Future<int>.sync(() => 3).then<int>((e) => e);
-''');
-    expect(unit, isNotNull);
-    TopLevelVariableDeclaration v = unit.declarations[0];
-    MethodInvocation init = v.variables.variables[0].initializer;
-    expect(init.methodName.name, 'then');
-    NodeList<TypeAnnotation> typeArg = init.typeArguments.arguments;
-    expect(typeArg, hasLength(1));
-    expect(typeArg[0].beginToken.lexeme, 'int');
-  }
-
-  void test_parseInstanceCreation_noKeyword_33647() {
-    enableOptionalNewAndConst = true;
-    // Old parser produces errors
-    if (usingFastaParser) {
-      CompilationUnit unit = parseCompilationUnit('''
-var c = Future<int>.sync(() => 3).then<int>((e) => e);
-''');
-      expect(unit, isNotNull);
-      TopLevelVariableDeclaration v = unit.declarations[0];
-      MethodInvocation init = v.variables.variables[0].initializer;
-      expect(init.methodName.name, 'then');
-      NodeList<TypeAnnotation> typeArg = init.typeArguments.arguments;
-      expect(typeArg, hasLength(1));
-      expect(typeArg[0].beginToken.lexeme, 'int');
-    }
-  }
-
-  void test_parseInstanceCreation_noKeyword_noPrefix() {
-    enableOptionalNewAndConst = true;
-    createParser('f() => C<E>.n();');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    FunctionDeclaration f = unit.declarations[0];
-    ExpressionFunctionBody body = f.functionExpression.body;
-    expect(body.expression, isInstanceCreationExpression);
-    InstanceCreationExpressionImpl creation = body.expression;
-    expect(creation.keyword, isNull);
-    ConstructorName constructorName = creation.constructorName;
-    expect(constructorName.type.toSource(), 'C<E>');
-    expect(constructorName.period, isNotNull);
-    expect(constructorName.name, isNotNull);
-    expect(creation.argumentList, isNotNull);
-    expect(creation.typeArguments, isNull);
-  }
-
-  void test_parseInstanceCreation_noKeyword_noPrefix_34403() {
-    if (!usingFastaParser) {
-      return;
-    }
-    enableOptionalNewAndConst = true;
-    createParser('f() => C<E>.n<B>();');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    FunctionDeclaration f = unit.declarations[0];
-    ExpressionFunctionBody body = f.functionExpression.body;
-    expect(body.expression, isInstanceCreationExpression);
-    InstanceCreationExpressionImpl creation = body.expression;
-    expect(creation.keyword, isNull);
-    ConstructorName constructorName = creation.constructorName;
-    expect(constructorName.type.toSource(), 'C<E>');
-    expect(constructorName.period, isNotNull);
-    expect(constructorName.name, isNotNull);
-    expect(creation.argumentList, isNotNull);
-    expect(creation.typeArguments.arguments, hasLength(1));
-  }
-
-  void test_parseInstanceCreation_noKeyword_prefix() {
-    enableOptionalNewAndConst = true;
-    createParser('f() => p.C<E>.n();');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    FunctionDeclaration f = unit.declarations[0];
-    ExpressionFunctionBody body = f.functionExpression.body;
-    expect(body.expression, isInstanceCreationExpression);
-    InstanceCreationExpression creation = body.expression;
-    expect(creation.keyword, isNull);
-    ConstructorName constructorName = creation.constructorName;
-    expect(constructorName.type.toSource(), 'p.C<E>');
-    expect(constructorName.period, isNotNull);
-    expect(constructorName.name, isNotNull);
-    expect(creation.argumentList, isNotNull);
-  }
-
-  void test_parseInstanceCreation_noKeyword_varInit() {
-    enableOptionalNewAndConst = true;
-    createParser('''
-class C<T, S> {}
-void main() {final c = C<int, int Function(String)>();}
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    FunctionDeclaration f = unit.declarations[1];
-    BlockFunctionBody body = f.functionExpression.body;
-    VariableDeclarationStatement statement = body.block.statements[0];
-    VariableDeclaration variable = statement.variables.variables[0];
-    MethodInvocation creation = variable.initializer;
-    expect(creation.methodName.name, 'C');
-    expect(creation.typeArguments.toSource(), '<int, int Function(String)>');
-  }
-
-  void test_parseLibraryIdentifier_builtin() {
-    String name = "deferred";
-    LibraryIdentifier identifier = parseLibraryIdentifier(name);
-    expectNotNullIfNoErrors(identifier);
-    assertNoErrors();
-    expect(identifier.name, name);
-    expect(identifier.beginToken.type.isBuiltIn, isTrue);
-  }
-
-  void test_parseLibraryIdentifier_invalid() {
-    parseCompilationUnit('library <myLibId>;',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 7),
-                expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1),
-              ]
-            : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 8, 1)]);
-  }
-
-  void test_parseLibraryIdentifier_multiple() {
-    String name = "a.b.c";
-    LibraryIdentifier identifier = parseLibraryIdentifier(name);
-    expectNotNullIfNoErrors(identifier);
-    assertNoErrors();
-    expect(identifier.name, name);
-  }
-
-  void test_parseLibraryIdentifier_pseudo() {
-    String name = "await";
-    LibraryIdentifier identifier = parseLibraryIdentifier(name);
-    expectNotNullIfNoErrors(identifier);
-    assertNoErrors();
-    expect(identifier.name, name);
-    expect(identifier.beginToken.type.isPseudo, isTrue);
-  }
-
-  void test_parseLibraryIdentifier_single() {
-    String name = "a";
-    LibraryIdentifier identifier = parseLibraryIdentifier(name);
-    expectNotNullIfNoErrors(identifier);
-    assertNoErrors();
-    expect(identifier.name, name);
-  }
-
-  void test_parseOptionalReturnType() {
-    // TODO(brianwilkerson) Implement tests for this method.
-  }
-
-  void test_parseReturnStatement_noValue() {
-    ReturnStatement statement = parseStatement('return;');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-    expect(statement.returnKeyword, isNotNull);
-    expect(statement.expression, isNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseReturnStatement_value() {
-    ReturnStatement statement = parseStatement('return x;');
-    expectNotNullIfNoErrors(statement);
-    assertNoErrors();
-    expect(statement.returnKeyword, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseStatement_function_noReturnType() {
-    createParser('''
-Function<A>(core.List<core.int> x) m() => null;
-''');
-    Statement statement = parser.parseStatement2();
-    expect(statement, isFunctionDeclarationStatement);
-    expect(
-        (statement as FunctionDeclarationStatement)
-            .functionDeclaration
-            .functionExpression
-            .body,
-        isExpressionFunctionBody);
-  }
-
-  void test_parseStatements_multiple() {
-    parseStatementList("return; return;", 2);
-  }
-
-  void test_parseStatements_single() {
-    parseStatementList("return;", 1);
-  }
-
-  void test_parseTypeAnnotation_function_noReturnType_noParameters() {
-    createParser('Function()');
-    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-    expect(functionType.returnType, isNull);
-    expect(functionType.functionKeyword, isNotNull);
-    expect(functionType.typeParameters, isNull);
-    FormalParameterList parameterList = functionType.parameters;
-    expect(parameterList, isNotNull);
-    expect(parameterList.parameters, hasLength(0));
-  }
-
-  void test_parseTypeAnnotation_function_noReturnType_parameters() {
-    createParser('Function(int, int)');
-    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-    expect(functionType.returnType, isNull);
-    expect(functionType.functionKeyword, isNotNull);
-    expect(functionType.typeParameters, isNull);
-    FormalParameterList parameterList = functionType.parameters;
-    expect(parameterList, isNotNull);
-    NodeList<FormalParameter> parameters = parameterList.parameters;
-    expect(parameters, hasLength(2));
-
-    expect(parameters[0], isSimpleFormalParameter);
-    SimpleFormalParameter parameter = parameters[0];
-    expect(parameter.identifier, isNull);
-    expect(parameter.type, isTypeName);
-    expect((parameter.type as TypeName).name.name, 'int');
-
-    expect(parameters[1], isSimpleFormalParameter);
-    parameter = parameters[1];
-    expect(parameter.identifier, isNull);
-    expect(parameter.type, isTypeName);
-    expect((parameter.type as TypeName).name.name, 'int');
-  }
-
-  void test_parseTypeAnnotation_function_noReturnType_typeParameters() {
-    createParser('Function<S, T>()');
-    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-    expect(functionType.returnType, isNull);
-    expect(functionType.functionKeyword, isNotNull);
-    TypeParameterList typeParameters = functionType.typeParameters;
-    expect(typeParameters, isNotNull);
-    expect(typeParameters.typeParameters, hasLength(2));
-    FormalParameterList parameterList = functionType.parameters;
-    expect(parameterList, isNotNull);
-    expect(parameterList.parameters, hasLength(0));
-  }
-
-  void
-      test_parseTypeAnnotation_function_noReturnType_typeParameters_parameters() {
-    createParser('Function<T>(String, {T t})');
-    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-    expect(functionType.returnType, isNull);
-    expect(functionType.functionKeyword, isNotNull);
-    TypeParameterList typeParameters = functionType.typeParameters;
-    expect(typeParameters, isNotNull);
-    expect(typeParameters.typeParameters, hasLength(1));
-    FormalParameterList parameterList = functionType.parameters;
-    expect(parameterList, isNotNull);
-    expect(parameterList.parameters, hasLength(2));
-  }
-
-  void test_parseTypeAnnotation_function_returnType_classFunction() {
-    createParser('Function');
-    TypeName functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-  }
-
-  void test_parseTypeAnnotation_function_returnType_function() {
-    createParser('A Function(B, C) Function(D)');
-    // TODO(scheglov) improve the test to verify also the node properties
-    var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType;
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-  }
-
-  void test_parseTypeAnnotation_function_returnType_noParameters() {
-    createParser('List<int> Function()');
-    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.functionKeyword, isNotNull);
-    expect(functionType.typeParameters, isNull);
-    FormalParameterList parameterList = functionType.parameters;
-    expect(parameterList, isNotNull);
-    expect(parameterList.parameters, hasLength(0));
-  }
-
-  void test_parseTypeAnnotation_function_returnType_parameters() {
-    createParser('List<int> Function(String s, int i)');
-    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.functionKeyword, isNotNull);
-    expect(functionType.typeParameters, isNull);
-    FormalParameterList parameterList = functionType.parameters;
-    expect(parameterList, isNotNull);
-    NodeList<FormalParameter> parameters = parameterList.parameters;
-    expect(parameters, hasLength(2));
-
-    expect(parameters[0], isSimpleFormalParameter);
-    SimpleFormalParameter parameter = parameters[0];
-    expect(parameter.identifier, isNotNull);
-    expect(parameter.identifier.name, 's');
-    expect(parameter.type, isTypeName);
-    expect((parameter.type as TypeName).name.name, 'String');
-
-    expect(parameters[1], isSimpleFormalParameter);
-    parameter = parameters[1];
-    expect(parameter.identifier, isNotNull);
-    expect(parameter.identifier.name, 'i');
-    expect(parameter.type, isTypeName);
-    expect((parameter.type as TypeName).name.name, 'int');
-  }
-
-  void test_parseTypeAnnotation_function_returnType_simple() {
-    createParser('A Function(B, C)');
-    // TODO(scheglov) improve the test to verify also the node properties
-    var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType;
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-  }
-
-  void test_parseTypeAnnotation_function_returnType_typeParameters() {
-    createParser('List<T> Function<T>()');
-    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.functionKeyword, isNotNull);
-    TypeParameterList typeParameters = functionType.typeParameters;
-    expect(typeParameters, isNotNull);
-    expect(typeParameters.typeParameters, hasLength(1));
-    FormalParameterList parameterList = functionType.parameters;
-    expect(parameterList, isNotNull);
-    expect(parameterList.parameters, hasLength(0));
-  }
-
-  void
-      test_parseTypeAnnotation_function_returnType_typeParameters_parameters() {
-    createParser('List<T> Function<T>(String s, [T])');
-    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.functionKeyword, isNotNull);
-    TypeParameterList typeParameters = functionType.typeParameters;
-    expect(typeParameters, isNotNull);
-    expect(typeParameters.typeParameters, hasLength(1));
-    FormalParameterList parameterList = functionType.parameters;
-    expect(parameterList, isNotNull);
-    expect(parameterList.parameters, hasLength(2));
-  }
-
-  void test_parseTypeAnnotation_function_returnType_withArguments() {
-    createParser('A<B> Function(C)');
-    // TODO(scheglov) improve this test to verify also the node properties
-    var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType;
-    expectNotNullIfNoErrors(functionType);
-    assertNoErrors();
-  }
-
-  void test_parseTypeAnnotation_named() {
-    createParser('A<B>');
-    TypeName typeName = parser.parseTypeAnnotation(false);
-    expectNotNullIfNoErrors(typeName);
-    assertNoErrors();
-  }
-
-  void test_parseTypeArgumentList_empty() {
-    createParser('<>');
-    TypeArgumentList argumentList = parser.parseTypeArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    listener.assertErrorsWithCodes([ParserErrorCode.EXPECTED_TYPE_NAME]);
-    expect(argumentList.leftBracket, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-    expect(argumentList.rightBracket, isNotNull);
-  }
-
-  void test_parseTypeArgumentList_multiple() {
-    createParser('<int, int, int>');
-    TypeArgumentList argumentList = parser.parseTypeArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    expect(argumentList.leftBracket, isNotNull);
-    expect(argumentList.arguments, hasLength(3));
-    expect(argumentList.rightBracket, isNotNull);
-  }
-
-  void test_parseTypeArgumentList_nested() {
-    createParser('<A<B>>');
-    TypeArgumentList argumentList = parser.parseTypeArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    expect(argumentList.leftBracket, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-    TypeName argument = argumentList.arguments[0];
-    expect(argument, isNotNull);
-    TypeArgumentList innerList = argument.typeArguments;
-    expect(innerList, isNotNull);
-    expect(innerList.arguments, hasLength(1));
-    expect(argumentList.rightBracket, isNotNull);
-  }
-
-  void test_parseTypeArgumentList_nested_withComment_double() {
-    createParser('<A<B /* 0 */ >>');
-    TypeArgumentList argumentList = parser.parseTypeArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    expect(argumentList.leftBracket, isNotNull);
-    expect(argumentList.rightBracket, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-
-    TypeName argument = argumentList.arguments[0];
-    expect(argument, isNotNull);
-
-    TypeArgumentList innerList = argument.typeArguments;
-    expect(innerList, isNotNull);
-    expect(innerList.leftBracket, isNotNull);
-    expect(innerList.arguments, hasLength(1));
-    expect(innerList.rightBracket, isNotNull);
-    expect(innerList.rightBracket.precedingComments, isNotNull);
-  }
-
-  void test_parseTypeArgumentList_nested_withComment_tripple() {
-    createParser('<A<B<C /* 0 */ >>>');
-    TypeArgumentList argumentList = parser.parseTypeArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    expect(argumentList.leftBracket, isNotNull);
-    expect(argumentList.rightBracket, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-
-    TypeName argument = argumentList.arguments[0];
-    expect(argument, isNotNull);
-
-    TypeArgumentList innerList = argument.typeArguments;
-    expect(innerList, isNotNull);
-    expect(innerList.leftBracket, isNotNull);
-    expect(innerList.arguments, hasLength(1));
-    expect(innerList.rightBracket, isNotNull);
-
-    TypeName innerArgument = innerList.arguments[0];
-    expect(innerArgument, isNotNull);
-
-    TypeArgumentList innerInnerList = innerArgument.typeArguments;
-    expect(innerInnerList, isNotNull);
-    expect(innerInnerList.leftBracket, isNotNull);
-    expect(innerInnerList.arguments, hasLength(1));
-    expect(innerInnerList.rightBracket, isNotNull);
-    expect(innerInnerList.rightBracket.precedingComments, isNotNull);
-  }
-
-  void test_parseTypeArgumentList_single() {
-    createParser('<int>');
-    TypeArgumentList argumentList = parser.parseTypeArgumentList();
-    expectNotNullIfNoErrors(argumentList);
-    assertNoErrors();
-    expect(argumentList.leftBracket, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-    expect(argumentList.rightBracket, isNotNull);
-  }
-
-  void test_parseTypeName_parameterized() {
-    createParser('List<int>');
-    TypeName typeName = parser.parseTypeName(false);
-    expectNotNullIfNoErrors(typeName);
-    assertNoErrors();
-    expect(typeName.name, isNotNull);
-    expect(typeName.typeArguments, isNotNull);
-  }
-
-  void test_parseTypeName_simple() {
-    createParser('int');
-    TypeName typeName = parser.parseTypeName(false);
-    expectNotNullIfNoErrors(typeName);
-    assertNoErrors();
-    expect(typeName.name, isNotNull);
-    expect(typeName.typeArguments, isNull);
-  }
-
-  void test_parseTypeParameter_bounded_functionType_noReturn() {
-    createParser('A extends Function(int)');
-    TypeParameter parameter = parser.parseTypeParameter();
-    expectNotNullIfNoErrors(parameter);
-    assertNoErrors();
-    expect(parameter.bound, isGenericFunctionType);
-    expect(parameter.extendsKeyword, isNotNull);
-    expect(parameter.name, isNotNull);
-  }
-
-  void test_parseTypeParameter_bounded_functionType_return() {
-    createParser('A extends String Function(int)');
-    TypeParameter parameter = parser.parseTypeParameter();
-    expectNotNullIfNoErrors(parameter);
-    assertNoErrors();
-    expect(parameter.bound, isGenericFunctionType);
-    expect(parameter.extendsKeyword, isNotNull);
-    expect(parameter.name, isNotNull);
-  }
-
-  void test_parseTypeParameter_bounded_generic() {
-    createParser('A extends B<C>');
-    TypeParameter parameter = parser.parseTypeParameter();
-    expectNotNullIfNoErrors(parameter);
-    assertNoErrors();
-    expect(parameter.bound, isTypeName);
-    expect(parameter.extendsKeyword, isNotNull);
-    expect(parameter.name, isNotNull);
-  }
-
-  void test_parseTypeParameter_bounded_simple() {
-    createParser('A extends B');
-    TypeParameter parameter = parser.parseTypeParameter();
-    expectNotNullIfNoErrors(parameter);
-    assertNoErrors();
-    expect(parameter.bound, isTypeName);
-    expect(parameter.extendsKeyword, isNotNull);
-    expect(parameter.name, isNotNull);
-  }
-
-  void test_parseTypeParameter_simple() {
-    createParser('A');
-    TypeParameter parameter = parser.parseTypeParameter();
-    expectNotNullIfNoErrors(parameter);
-    assertNoErrors();
-    expect(parameter.bound, isNull);
-    expect(parameter.extendsKeyword, isNull);
-    expect(parameter.name, isNotNull);
-  }
-
-  void test_parseTypeParameterList_multiple() {
-    createParser('<A, B extends C, D>');
-    TypeParameterList parameterList = parser.parseTypeParameterList();
-    expectNotNullIfNoErrors(parameterList);
-    assertNoErrors();
-    expect(parameterList.leftBracket, isNotNull);
-    expect(parameterList.rightBracket, isNotNull);
-    expect(parameterList.typeParameters, hasLength(3));
-  }
-
-  void test_parseTypeParameterList_parameterizedWithTrailingEquals() {
-    createParser('<A extends B<E>>=', expectedEndOffset: 16);
-    TypeParameterList parameterList = parser.parseTypeParameterList();
-    expectNotNullIfNoErrors(parameterList);
-    assertNoErrors();
-    expect(parameterList.leftBracket, isNotNull);
-    expect(parameterList.rightBracket, isNotNull);
-    expect(parameterList.typeParameters, hasLength(1));
-  }
-
-  void test_parseTypeParameterList_parameterizedWithTrailingEquals2() {
-    createParser('<A extends B<E /* foo */ >>=', expectedEndOffset: 27);
-    TypeParameterList parameterList = parser.parseTypeParameterList();
-    expectNotNullIfNoErrors(parameterList);
-    assertNoErrors();
-    expect(parameterList.leftBracket, isNotNull);
-    expect(parameterList.rightBracket, isNotNull);
-    expect(parameterList.typeParameters, hasLength(1));
-    TypeParameter typeParameter = parameterList.typeParameters[0];
-    expect(typeParameter.name.name, 'A');
-    TypeName bound = typeParameter.bound;
-    expect(bound.name.name, 'B');
-    TypeArgumentList typeArguments = bound.typeArguments;
-    expect(typeArguments.arguments, hasLength(1));
-    expect(typeArguments.rightBracket, isNotNull);
-    expect(typeArguments.rightBracket.precedingComments.lexeme, '/* foo */');
-    TypeName argument = typeArguments.arguments[0];
-    expect(argument.name.name, 'E');
-  }
-
-  void test_parseTypeParameterList_single() {
-    createParser('<<A>', expectedEndOffset: 0);
-    TypeParameterList parameterList = parser.parseTypeParameterList();
-    if (usingFastaParser) {
-      // TODO(danrubel): Consider splitting `<<` and marking the first `<`
-      // as an unexpected token.
-      expect(parameterList, isNull);
-      assertNoErrors();
-    } else {
-      expectNotNullIfNoErrors(parameterList);
-      assertNoErrors();
-      expect(parameterList.leftBracket, isNotNull);
-      expect(parameterList.rightBracket, isNotNull);
-      expect(parameterList.typeParameters, hasLength(1));
-    }
-  }
-
-  void test_parseTypeParameterList_withTrailingEquals() {
-    createParser('<A>=', expectedEndOffset: 3);
-    TypeParameterList parameterList = parser.parseTypeParameterList();
-    expectNotNullIfNoErrors(parameterList);
-    assertNoErrors();
-    expect(parameterList.leftBracket, isNotNull);
-    expect(parameterList.rightBracket, isNotNull);
-    expect(parameterList.typeParameters, hasLength(1));
-  }
-
-  void test_parseVariableDeclaration_equals() {
-    VariableDeclaration declaration = parseVariableDeclaration('var a = b;');
-    expectNotNullIfNoErrors(declaration);
-    assertNoErrors();
-    expect(declaration.name, isNotNull);
-    expect(declaration.equals, isNotNull);
-    expect(declaration.initializer, isNotNull);
-  }
-
-  void test_parseVariableDeclaration_noEquals() {
-    VariableDeclaration declaration = parseVariableDeclaration('var a;');
-    expectNotNullIfNoErrors(declaration);
-    assertNoErrors();
-    expect(declaration.name, isNotNull);
-    expect(declaration.equals, isNull);
-    expect(declaration.initializer, isNull);
-  }
-
-  void test_parseWithClause_multiple() {
-    WithClause clause = parseWithClause('with A, B, C');
-    expectNotNullIfNoErrors(clause);
-    assertNoErrors();
-    expect(clause.withKeyword, isNotNull);
-    expect(clause.mixinTypes, hasLength(3));
-  }
-
-  void test_parseWithClause_single() {
-    WithClause clause = parseWithClause('with M');
-    expectNotNullIfNoErrors(clause);
-    assertNoErrors();
-    expect(clause.withKeyword, isNotNull);
-    expect(clause.mixinTypes, hasLength(1));
-  }
-}
-
-@reflectiveTest
-class StatementParserTest extends ParserTestCase with StatementParserTestMixin {
-}
-
-/// The class [FormalParameterParserTestMixin] defines parser tests that test
-/// the parsing statements.
-mixin StatementParserTestMixin implements AbstractParserTestCase {
-  void test_invalid_typeParamAnnotation() {
-    parseCompilationUnit('main() { C<@Foo T> v; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 4)
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1)
-              ]);
-  }
-
-  void test_invalid_typeParamAnnotation2() {
-    parseCompilationUnit('main() { C<@Foo.bar(1) T> v; }',
-        errors: usingFastaParser
-            ? [
-                expectedError(
-                    ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 11)
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1)
-              ]);
-  }
-
-  void test_invalid_typeParamAnnotation3() {
-    if (usingFastaParser) {
-      parseCompilationUnit('''
-main() {
-  C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T,
-    F Function<G>(int, String, {Bar b}),
-    void Function<H>(int i, [String j, K]),
-    A<B<C>>,
-    W<X<Y<Z>>>
-  > v;
-}''', errors: [
-        expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 13, 63)
-      ]);
-    }
-  }
-
-  void test_parseAssertStatement() {
-    var statement = parseStatement('assert (x);') as AssertStatement;
-    assertNoErrors();
-    expect(statement.assertKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.comma, isNull);
-    expect(statement.message, isNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseAssertStatement_messageLowPrecedence() {
-    // Using a throw expression as an assert message would be silly in
-    // practice, but it's the lowest precedence expression type, so verifying
-    // that it works should give us high confidence that other expression types
-    // will work as well.
-    var statement =
-        parseStatement('assert (x, throw "foo");') as AssertStatement;
-    assertNoErrors();
-    expect(statement.assertKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.comma, isNotNull);
-    expect(statement.message, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseAssertStatement_messageString() {
-    var statement = parseStatement('assert (x, "foo");') as AssertStatement;
-    assertNoErrors();
-    expect(statement.assertKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.comma, isNotNull);
-    expect(statement.message, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseAssertStatement_trailingComma_message() {
-    var statement = parseStatement('assert (x, "m",);') as AssertStatement;
-    assertNoErrors();
-    expect(statement.assertKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.comma, isNotNull);
-    expect(statement.message, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseAssertStatement_trailingComma_noMessage() {
-    var statement = parseStatement('assert (x,);') as AssertStatement;
-    assertNoErrors();
-    expect(statement.assertKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.comma, isNull);
-    expect(statement.message, isNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseBlock_empty() {
-    var block = parseStatement('{}') as Block;
-    assertNoErrors();
-    expect(block.leftBracket, isNotNull);
-    expect(block.statements, hasLength(0));
-    expect(block.rightBracket, isNotNull);
-  }
-
-  void test_parseBlock_nonEmpty() {
-    var block = parseStatement('{;}') as Block;
-    assertNoErrors();
-    expect(block.leftBracket, isNotNull);
-    expect(block.statements, hasLength(1));
-    expect(block.rightBracket, isNotNull);
-  }
-
-  void test_parseBreakStatement_label() {
-    LabeledStatement labeledStatement =
-        parseStatement('foo: while (true) { break foo; }');
-    WhileStatement whileStatement = labeledStatement.statement;
-    BreakStatement statement = (whileStatement.body as Block).statements[0];
-    assertNoErrors();
-    expect(statement.breakKeyword, isNotNull);
-    expect(statement.label, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseBreakStatement_noLabel() {
-    WhileStatement whileStatement = parseStatement('while (true) { break; }');
-    BreakStatement statement = (whileStatement.body as Block).statements[0];
-    assertNoErrors();
-    expect(statement.breakKeyword, isNotNull);
-    expect(statement.label, isNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseContinueStatement_label() {
-    LabeledStatement labeledStatement =
-        parseStatement('foo: while (true) { continue foo; }');
-    WhileStatement whileStatement = labeledStatement.statement;
-    ContinueStatement statement = (whileStatement.body as Block).statements[0];
-    assertNoErrors();
-    expect(statement.continueKeyword, isNotNull);
-    expect(statement.label, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseContinueStatement_noLabel() {
-    WhileStatement whileStatement =
-        parseStatement('while (true) { continue; }');
-    ContinueStatement statement = (whileStatement.body as Block).statements[0];
-    assertNoErrors();
-    expect(statement.continueKeyword, isNotNull);
-    expect(statement.label, isNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseDoStatement() {
-    var statement = parseStatement('do {} while (x);') as DoStatement;
-    assertNoErrors();
-    expect(statement.doKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    expect(statement.whileKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseElseAlone() {
-    parseCompilationUnit('main() { else return 0; } ',
-        errors: usingFastaParser
-            ? [
-                expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 4),
-              ]
-            : [
-                expectedError(ParserErrorCode.MISSING_STATEMENT, 9, 4),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 4),
-              ]);
-  }
-
-  void test_parseEmptyStatement() {
-    var statement = parseStatement(';') as EmptyStatement;
-    assertNoErrors();
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseForStatement_each_await() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    String code = 'await for (element in list) {}';
-    var forStatement = _parseAsyncStatement(code) as ForStatement;
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, usingFastaParser ? isNotNull : isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forEachParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
-    expect(forEachParts.identifier, isNotNull);
-    expect(forEachParts.inKeyword, isNotNull);
-    expect(forEachParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_genericFunctionType() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (void Function<T>(T) element in list) {}')
-            as ForStatement;
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
-    expect(forEachParts.loopVariable, isNotNull);
-    expect(forEachParts.inKeyword, isNotNull);
-    expect(forEachParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_identifier() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (element in list) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forEachParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
-    expect(forEachParts.identifier, isNotNull);
-    expect(forEachParts.inKeyword, isNotNull);
-    expect(forEachParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_noType_metadata() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (@A var element in list) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
-    expect(forEachParts.loopVariable, isNotNull);
-    expect(forEachParts.loopVariable.metadata, hasLength(1));
-    expect(forEachParts.inKeyword, isNotNull);
-    expect(forEachParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_type() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (A element in list) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
-    expect(forEachParts.loopVariable, isNotNull);
-    expect(forEachParts.inKeyword, isNotNull);
-    expect(forEachParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_each_var() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (var element in list) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.awaitKeyword, isNull);
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
-    expect(forEachParts.loopVariable, isNotNull);
-    expect(forEachParts.inKeyword, isNotNull);
-    expect(forEachParts.iterable, isNotNull);
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_c() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement = parseStatement('for (; i < count;) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithExpression;
-    expect(forParts.initialization, isNull);
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNotNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(0));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_cu() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (; i < count; i++) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithExpression;
-    expect(forParts.initialization, isNull);
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNotNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_ecu() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (i--; i < count; i++) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithExpression;
-    expect(forParts.initialization, isNotNull);
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNotNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_i() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement = parseStatement('for (var i = 0;;) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
-    VariableDeclarationList variables = forParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.metadata, hasLength(0));
-    expect(variables.variables, hasLength(1));
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(0));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_i_withMetadata() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (@A var i = 0;;) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
-    VariableDeclarationList variables = forParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.metadata, hasLength(1));
-    expect(variables.variables, hasLength(1));
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(0));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_ic() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (var i = 0; i < count;) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
-    VariableDeclarationList variables = forParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.variables, hasLength(1));
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNotNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(0));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_icu() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (var i = 0; i < count; i++) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
-    VariableDeclarationList variables = forParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.variables, hasLength(1));
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNotNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_iicuu() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (int i = 0, j = count; i < j; i++, j--) {}')
-            as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
-    VariableDeclarationList variables = forParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.variables, hasLength(2));
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNotNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(2));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_iu() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement =
-        parseStatement('for (var i = 0;; i++) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
-    VariableDeclarationList variables = forParts.variables;
-    expect(variables, isNotNull);
-    expect(variables.variables, hasLength(1));
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseForStatement_loop_u() {
-    // TODO(danrubel): remove this once control flow and spread collection
-    // entry parsing is enabled by default
-    var forStatement = parseStatement('for (;; i++) {}') as ForStatement;
-    assertNoErrors();
-    expect(forStatement.forKeyword, isNotNull);
-    expect(forStatement.leftParenthesis, isNotNull);
-    var forParts = forStatement.forLoopParts as ForPartsWithExpression;
-    expect(forParts.initialization, isNull);
-    expect(forParts.leftSeparator, isNotNull);
-    expect(forParts.condition, isNull);
-    expect(forParts.rightSeparator, isNotNull);
-    expect(forParts.updaters, hasLength(1));
-    expect(forStatement.rightParenthesis, isNotNull);
-    expect(forStatement.body, isNotNull);
-  }
-
-  void test_parseFunctionDeclarationStatement() {
-    var statement = parseStatement('void f(int p) => p * 2;')
-        as FunctionDeclarationStatement;
-    assertNoErrors();
-    expect(statement.functionDeclaration, isNotNull);
-  }
-
-  void test_parseFunctionDeclarationStatement_typeParameters() {
-    var statement =
-        parseStatement('E f<E>(E p) => p * 2;') as FunctionDeclarationStatement;
-    assertNoErrors();
-    expect(statement.functionDeclaration, isNotNull);
-    expect(statement.functionDeclaration.functionExpression.typeParameters,
-        isNotNull);
-  }
-
-  void test_parseFunctionDeclarationStatement_typeParameters_noReturnType() {
-    var statement =
-        parseStatement('f<E>(E p) => p * 2;') as FunctionDeclarationStatement;
-    assertNoErrors();
-    expect(statement.functionDeclaration, isNotNull);
-    expect(statement.functionDeclaration.functionExpression.typeParameters,
-        isNotNull);
-  }
-
-  void test_parseIfStatement_else_block() {
-    var statement = parseStatement('if (x) {} else {}') as IfStatement;
-    assertNoErrors();
-    expect(statement.ifKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.thenStatement, isNotNull);
-    expect(statement.elseKeyword, isNotNull);
-    expect(statement.elseStatement, isNotNull);
-  }
-
-  void test_parseIfStatement_else_emptyStatements() {
-    var statement = parseStatement('if (true) ; else ;') as IfStatement;
-    assertNoErrors();
-    expect(statement.ifKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.thenStatement, isNotNull);
-    expect(statement.elseKeyword, isNotNull);
-    expect(statement.elseStatement, isNotNull);
-  }
-
-  void test_parseIfStatement_else_statement() {
-    var statement = parseStatement('if (x) f(x); else f(y);') as IfStatement;
-    assertNoErrors();
-    expect(statement.ifKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.thenStatement, isNotNull);
-    expect(statement.elseKeyword, isNotNull);
-    expect(statement.elseStatement, isNotNull);
-  }
-
-  void test_parseIfStatement_noElse_block() {
-    var statement = parseStatement('if (x) {}') as IfStatement;
-    assertNoErrors();
-    expect(statement.ifKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.thenStatement, isNotNull);
-    expect(statement.elseKeyword, isNull);
-    expect(statement.elseStatement, isNull);
-  }
-
-  void test_parseIfStatement_noElse_statement() {
-    var statement = parseStatement('if (x) f(x);') as IfStatement;
-    assertNoErrors();
-    expect(statement.ifKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.thenStatement, isNotNull);
-    expect(statement.elseKeyword, isNull);
-    expect(statement.elseStatement, isNull);
-  }
-
-  void test_parseNonLabeledStatement_const_list_empty() {
-    var statement = parseStatement('const [];') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_const_list_nonEmpty() {
-    var statement = parseStatement('const [1, 2];') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_const_map_empty() {
-    var statement = parseStatement('const {};') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_const_map_nonEmpty() {
-    // TODO(brianwilkerson) Implement more tests for this method.
-    var statement = parseStatement("const {'a' : 1};") as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_const_object() {
-    var statement = parseStatement('const A();') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_const_object_named_typeParameters() {
-    var statement = parseStatement('const A<B>.c();') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_const_object_named_typeParameters_34403() {
-    if (!usingFastaParser) {
-      return;
-    }
-    var statement = parseStatement('const A<B>.c<C>();') as ExpressionStatement;
-    assertErrorsWithCodes(
-        [CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR]);
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_constructorInvocation() {
-    var statement = parseStatement('new C().m();') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_false() {
-    var statement = parseStatement('false;') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_functionDeclaration() {
-    var statement = parseStatement('f() {}') as FunctionDeclarationStatement;
-    assertNoErrors();
-    var function = statement.functionDeclaration.functionExpression;
-    expect(function.parameters.parameters, isEmpty);
-    expect(function.body, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_functionDeclaration_arguments() {
-    var statement =
-        parseStatement('f(void g()) {}') as FunctionDeclarationStatement;
-    assertNoErrors();
-    var function = statement.functionDeclaration.functionExpression;
-    expect(function.parameters.parameters, hasLength(1));
-    expect(function.body, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_functionExpressionIndex() {
-    var statement = parseStatement('() {}[0] = null;') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_functionInvocation() {
-    var statement = parseStatement('f();') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_invokeFunctionExpression() {
-    var statement =
-        parseStatement('(a) {return a + a;} (3);') as ExpressionStatement;
-    assertNoErrors();
-    var invocation = statement.expression as FunctionExpressionInvocation;
-
-    FunctionExpression expression = invocation.function as FunctionExpression;
-    expect(expression.parameters, isNotNull);
-    expect(expression.body, isNotNull);
-    expect(invocation.typeArguments, isNull);
-    expect(invocation.argumentList.arguments, hasLength(1));
-  }
-
-  void test_parseNonLabeledStatement_localFunction_gftReturnType() {
-    var statement = parseStatement('int Function(int) f(String s) => null;')
-        as FunctionDeclarationStatement;
-    assertNoErrors();
-    FunctionDeclaration function = statement.functionDeclaration;
-    expect(function.returnType, isGenericFunctionType);
-  }
-
-  void test_parseNonLabeledStatement_null() {
-    var statement = parseStatement('null;') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_startingWithBuiltInIdentifier() {
-    var statement = parseStatement('library.getName();') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_true() {
-    var statement = parseStatement('true;') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_typeCast() {
-    var statement = parseStatement('double.NAN as num;') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseNonLabeledStatement_variableDeclaration_final_namedFunction() {
-    var statement = parseStatement('final int Function = 0;')
-        as VariableDeclarationStatement;
-    assertNoErrors();
-    List<VariableDeclaration> variables = statement.variables.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'Function');
-  }
-
-  void test_parseNonLabeledStatement_variableDeclaration_gftType() {
-    var statement =
-        parseStatement('int Function(int) v;') as VariableDeclarationStatement;
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    expect(variableList.type, isGenericFunctionType);
-  }
-
-  void
-      test_parseNonLabeledStatement_variableDeclaration_gftType_functionReturnType() {
-    var statement = parseStatement(
-            'Function Function(int x1, {Function x}) Function<B extends core.int>(int x) v;')
-        as VariableDeclarationStatement;
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    expect(variableList.type, isGenericFunctionType);
-  }
-
-  void
-      test_parseNonLabeledStatement_variableDeclaration_gftType_gftReturnType() {
-    var statement = parseStatement('Function(int) Function(int) v;')
-        as VariableDeclarationStatement;
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    expect(variableList.type, isGenericFunctionType);
-  }
-
-  void
-      test_parseNonLabeledStatement_variableDeclaration_gftType_gftReturnType2() {
-    var statement = parseStatement('int Function(int) Function(int) v;')
-        as VariableDeclarationStatement;
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    expect(variableList.type, isGenericFunctionType);
-  }
-
-  void
-      test_parseNonLabeledStatement_variableDeclaration_gftType_noReturnType() {
-    var statement =
-        parseStatement('Function(int) v;') as VariableDeclarationStatement;
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    expect(variableList.type, isGenericFunctionType);
-  }
-
-  void test_parseNonLabeledStatement_variableDeclaration_gftType_returnType() {
-    var statement =
-        parseStatement('int Function<T>() v;') as VariableDeclarationStatement;
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    expect(variableList.type, isGenericFunctionType);
-  }
-
-  void
-      test_parseNonLabeledStatement_variableDeclaration_gftType_voidReturnType() {
-    var statement =
-        parseStatement('void Function() v;') as VariableDeclarationStatement;
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    expect(variableList.type, isGenericFunctionType);
-  }
-
-  void test_parseNonLabeledStatement_variableDeclaration_typeParam() {
-    VariableDeclarationStatement statement = parseStatement('C<T> v;');
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    TypeName typeName = variableList.type;
-    expect(typeName.name.name, 'C');
-    expect(typeName.typeArguments.arguments, hasLength(1));
-    TypeName typeArgument = typeName.typeArguments.arguments[0];
-    expect(typeArgument.name.name, 'T');
-  }
-
-  void test_parseNonLabeledStatement_variableDeclaration_typeParam2() {
-    VariableDeclarationStatement statement =
-        parseStatement('C<T /* ignored comment */ > v;');
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    TypeName typeName = variableList.type;
-    expect(typeName.name.name, 'C');
-    expect(typeName.typeArguments.arguments, hasLength(1));
-    TypeName typeArgument = typeName.typeArguments.arguments[0];
-    expect(typeArgument.name.name, 'T');
-  }
-
-  void test_parseNonLabeledStatement_variableDeclaration_typeParam3() {
-    VariableDeclarationStatement statement =
-        parseStatement('C<T Function(String s)> v;');
-    assertNoErrors();
-    VariableDeclarationList variableList = statement.variables;
-    List<VariableDeclaration> variables = variableList.variables;
-    expect(variables, hasLength(1));
-    expect(variables[0].name.name, 'v');
-    TypeName typeName = variableList.type;
-    expect(typeName.name.name, 'C');
-    expect(typeName.typeArguments.arguments, hasLength(1));
-    expect(typeName.typeArguments.arguments[0], isGenericFunctionType);
-  }
-
-  void test_parseStatement_emptyTypeArgumentList() {
-    var declaration = parseStatement('C<> c;') as VariableDeclarationStatement;
-    assertErrorsWithCodes([ParserErrorCode.EXPECTED_TYPE_NAME]);
-    VariableDeclarationList variables = declaration.variables;
-    TypeName type = variables.type;
-    TypeArgumentList argumentList = type.typeArguments;
-    expect(argumentList.leftBracket, isNotNull);
-    expect(argumentList.arguments, hasLength(1));
-    expect(argumentList.arguments[0].isSynthetic, isTrue);
-    expect(argumentList.rightBracket, isNotNull);
-  }
-
-  void test_parseStatement_function_gftReturnType() {
-    var statement =
-        parseStatement('void Function<A>(core.List<core.int> x) m() => null;')
-            as FunctionDeclarationStatement;
-    expect(statement.functionDeclaration.functionExpression.body,
-        isExpressionFunctionBody);
-  }
-
-  void test_parseStatement_functionDeclaration_noReturnType() {
-    var statement = parseStatement('true;') as ExpressionStatement;
-    assertNoErrors();
-    expect(statement.expression, isNotNull);
-  }
-
-  void test_parseStatement_functionDeclaration_noReturnType_typeParameters() {
-    var statement =
-        parseStatement('f<E>(a, b) {}') as FunctionDeclarationStatement;
-    assertNoErrors();
-    expect(statement.functionDeclaration, isNotNull);
-  }
-
-  void test_parseStatement_functionDeclaration_returnType() {
-    // TODO(brianwilkerson) Implement more tests for this method.
-    var statement =
-        parseStatement('int f(a, b) {}') as FunctionDeclarationStatement;
-    assertNoErrors();
-    expect(statement.functionDeclaration, isNotNull);
-  }
-
-  void test_parseStatement_functionDeclaration_returnType_typeParameters() {
-    var statement =
-        parseStatement('int f<E>(a, b) {}') as FunctionDeclarationStatement;
-    assertNoErrors();
-    expect(statement.functionDeclaration, isNotNull);
-  }
-
-  void test_parseStatement_multipleLabels() {
-    var statement = parseStatement('l: m: return x;') as LabeledStatement;
-    expect(statement.labels, hasLength(2));
-    expect(statement.statement, isNotNull);
-  }
-
-  void test_parseStatement_noLabels() {
-    var statement = parseStatement('return x;') as ReturnStatement;
-    assertNoErrors();
-    expect(statement, isNotNull);
-  }
-
-  void test_parseStatement_singleLabel() {
-    var statement = parseStatement('l: return x;') as LabeledStatement;
-    assertNoErrors();
-    expect(statement.labels, hasLength(1));
-    expect(statement.labels[0].label.inDeclarationContext(), isTrue);
-    expect(statement.statement, isNotNull);
-  }
-
-  void test_parseSwitchStatement_case() {
-    var statement =
-        parseStatement('switch (a) {case 1: return "I";}') as SwitchStatement;
-    assertNoErrors();
-    expect(statement.switchKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.leftBracket, isNotNull);
-    expect(statement.members, hasLength(1));
-    expect(statement.rightBracket, isNotNull);
-  }
-
-  void test_parseSwitchStatement_empty() {
-    var statement = parseStatement('switch (a) {}') as SwitchStatement;
-    assertNoErrors();
-    expect(statement.switchKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.leftBracket, isNotNull);
-    expect(statement.members, hasLength(0));
-    expect(statement.rightBracket, isNotNull);
-  }
-
-  void test_parseSwitchStatement_labeledCase() {
-    var statement =
-        parseStatement('switch (a) {l1: l2: l3: case(1):}') as SwitchStatement;
-    assertNoErrors();
-    expect(statement.switchKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.leftBracket, isNotNull);
-    expect(statement.members, hasLength(1));
-    {
-      List<Label> labels = statement.members[0].labels;
-      expect(labels, hasLength(3));
-      expect(labels[0].label.inDeclarationContext(), isTrue);
-      expect(labels[1].label.inDeclarationContext(), isTrue);
-      expect(labels[2].label.inDeclarationContext(), isTrue);
-    }
-    expect(statement.rightBracket, isNotNull);
-  }
-
-  void test_parseSwitchStatement_labeledCase2() {
-    SwitchStatement statement =
-        parseStatement('switch (a) {l1: case 0: l2: case 1: return;}');
-    assertNoErrors();
-    expect(statement.switchKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.leftBracket, isNotNull);
-    expect(statement.members, hasLength(2));
-    {
-      List<Label> labels = statement.members[0].labels;
-      expect(labels, hasLength(1));
-      expect(labels[0].label.inDeclarationContext(), isTrue);
-    }
-    {
-      List<Label> labels = statement.members[1].labels;
-      expect(labels, hasLength(1));
-      expect(labels[0].label.inDeclarationContext(), isTrue);
-    }
-    expect(statement.rightBracket, isNotNull);
-  }
-
-  void test_parseSwitchStatement_labeledDefault() {
-    var statement =
-        parseStatement('switch (a) {l1: l2: l3: default:}') as SwitchStatement;
-    assertNoErrors();
-    expect(statement.switchKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.leftBracket, isNotNull);
-    expect(statement.members, hasLength(1));
-    {
-      List<Label> labels = statement.members[0].labels;
-      expect(labels, hasLength(3));
-      expect(labels[0].label.inDeclarationContext(), isTrue);
-      expect(labels[1].label.inDeclarationContext(), isTrue);
-      expect(labels[2].label.inDeclarationContext(), isTrue);
-    }
-    expect(statement.rightBracket, isNotNull);
-  }
-
-  void test_parseSwitchStatement_labeledDefault2() {
-    SwitchStatement statement =
-        parseStatement('switch (a) {l1: case 0: l2: default: return;}');
-    assertNoErrors();
-    expect(statement.switchKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.leftBracket, isNotNull);
-    expect(statement.members, hasLength(2));
-    {
-      List<Label> labels = statement.members[0].labels;
-      expect(labels, hasLength(1));
-      expect(labels[0].label.inDeclarationContext(), isTrue);
-    }
-    {
-      List<Label> labels = statement.members[1].labels;
-      expect(labels, hasLength(1));
-      expect(labels[0].label.inDeclarationContext(), isTrue);
-    }
-    expect(statement.rightBracket, isNotNull);
-  }
-
-  void test_parseSwitchStatement_labeledStatementInCase() {
-    var statement = parseStatement('switch (a) {case 0: f(); l1: g(); break;}')
-        as SwitchStatement;
-    assertNoErrors();
-    expect(statement.switchKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.leftBracket, isNotNull);
-    expect(statement.members, hasLength(1));
-    expect(statement.members[0].statements, hasLength(3));
-    expect(statement.rightBracket, isNotNull);
-  }
-
-  void test_parseTryStatement_catch() {
-    var statement = parseStatement('try {} catch (e) {}') as TryStatement;
-    assertNoErrors();
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNull);
-    expect(clause.exceptionType, isNull);
-    expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
-    expect(clause.comma, isNull);
-    expect(clause.stackTraceParameter, isNull);
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNull);
-    expect(statement.finallyBlock, isNull);
-  }
-
-  void test_parseTryStatement_catch_error_invalidCatchParam() {
-    CompilationUnit unit =
-        parseCompilationUnit('main() { try {} catch (int e) { } }',
-            errors: usingFastaParser
-                ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 27, 1)]
-                : [
-                    expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 1),
-                    expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 1),
-                    expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 1),
-                    expectedError(ParserErrorCode.MISSING_IDENTIFIER, 28, 1),
-                    expectedError(ParserErrorCode.EXPECTED_TOKEN, 28, 1),
-                    expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
-                  ]);
-    FunctionDeclaration method = unit.declarations[0];
-    BlockFunctionBody body = method.functionExpression.body;
-    TryStatement statement = body.block.statements[0];
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNull);
-    expect(clause.exceptionType, isNull);
-    expect(clause.catchKeyword, isNotNull);
-    if (usingFastaParser) {
-      expect(clause.exceptionParameter.name, 'int');
-      expect(clause.comma, isNotNull);
-      expect(clause.stackTraceParameter.name, 'e');
-    } else {
-      expect(clause.exceptionParameter.name, 'int');
-      expect(clause.comma, isNull);
-      expect(clause.stackTraceParameter, isNull);
-    }
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNull);
-    expect(statement.finallyBlock, isNull);
-  }
-
-  void test_parseTryStatement_catch_error_missingCatchParam() {
-    var statement = parseStatement('try {} catch () {}') as TryStatement;
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 14, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 1),
-          ]);
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNull);
-    expect(clause.exceptionType, isNull);
-    expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
-    expect(clause.comma, isNull);
-    expect(clause.stackTraceParameter, isNull);
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNull);
-    expect(statement.finallyBlock, isNull);
-  }
-
-  void test_parseTryStatement_catch_error_missingCatchParen() {
-    var statement = parseStatement('try {} catch {}') as TryStatement;
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 13, 1)]
-        : [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1)
-          ]);
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNull);
-    expect(clause.exceptionType, isNull);
-    expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
-    expect(clause.comma, isNull);
-    expect(clause.stackTraceParameter, isNull);
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNull);
-    expect(statement.finallyBlock, isNull);
-  }
-
-  void test_parseTryStatement_catch_error_missingCatchTrace() {
-    var statement = parseStatement('try {} catch (e,) {}') as TryStatement;
-    listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.CATCH_SYNTAX, 16, 1)]
-        : [
-            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 1),
-          ]);
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNull);
-    expect(clause.exceptionType, isNull);
-    expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
-    expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter, isNotNull);
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNull);
-    expect(statement.finallyBlock, isNull);
-  }
-
-  void test_parseTryStatement_catch_finally() {
-    var statement =
-        parseStatement('try {} catch (e, s) {} finally {}') as TryStatement;
-    assertNoErrors();
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNull);
-    expect(clause.exceptionType, isNull);
-    expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
-    expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter, isNotNull);
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNotNull);
-    expect(statement.finallyBlock, isNotNull);
-  }
-
-  void test_parseTryStatement_finally() {
-    var statement = parseStatement('try {} finally {}') as TryStatement;
-    assertNoErrors();
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    expect(statement.catchClauses, hasLength(0));
-    expect(statement.finallyKeyword, isNotNull);
-    expect(statement.finallyBlock, isNotNull);
-  }
-
-  void test_parseTryStatement_multiple() {
-    var statement =
-        parseStatement('try {} on NPE catch (e) {} on Error {} catch (e) {}')
-            as TryStatement;
-    assertNoErrors();
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    expect(statement.catchClauses, hasLength(3));
-    expect(statement.finallyKeyword, isNull);
-    expect(statement.finallyBlock, isNull);
-  }
-
-  void test_parseTryStatement_on() {
-    var statement = parseStatement('try {} on Error {}') as TryStatement;
-    assertNoErrors();
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNotNull);
-    expect(clause.exceptionType, isNotNull);
-    expect(clause.catchKeyword, isNull);
-    expect(clause.exceptionParameter, isNull);
-    expect(clause.comma, isNull);
-    expect(clause.stackTraceParameter, isNull);
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNull);
-    expect(statement.finallyBlock, isNull);
-  }
-
-  void test_parseTryStatement_on_catch() {
-    var statement =
-        parseStatement('try {} on Error catch (e, s) {}') as TryStatement;
-    assertNoErrors();
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNotNull);
-    expect(clause.exceptionType, isNotNull);
-    expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
-    expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter, isNotNull);
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNull);
-    expect(statement.finallyBlock, isNull);
-  }
-
-  void test_parseTryStatement_on_catch_finally() {
-    var statement = parseStatement('try {} on Error catch (e, s) {} finally {}')
-        as TryStatement;
-    assertNoErrors();
-    expect(statement.tryKeyword, isNotNull);
-    expect(statement.body, isNotNull);
-    NodeList<CatchClause> catchClauses = statement.catchClauses;
-    expect(catchClauses, hasLength(1));
-    CatchClause clause = catchClauses[0];
-    expect(clause.onKeyword, isNotNull);
-    expect(clause.exceptionType, isNotNull);
-    expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
-    expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter, isNotNull);
-    expect(clause.body, isNotNull);
-    expect(statement.finallyKeyword, isNotNull);
-    expect(statement.finallyBlock, isNotNull);
-  }
-
-  void test_parseVariableDeclaration_equals_builtIn() {
-    VariableDeclarationStatement statement = parseStatement('int set = 0;');
-    assertNoErrors();
-    expect(statement.semicolon, isNotNull);
-    VariableDeclarationList variableList = statement.variables;
-    expect(variableList, isNotNull);
-    expect(variableList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclarationListAfterMetadata_const_noType() {
-    var declarationList = parseVariableDeclarationList('const a = 0');
-    assertNoErrors();
-    expect(declarationList.keyword.lexeme, 'const');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclarationListAfterMetadata_const_type() {
-    var declarationList = parseVariableDeclarationList('const A a');
-    assertNoErrors();
-    expect(declarationList.keyword.lexeme, 'const');
-    expect(declarationList.type, isNotNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclarationListAfterMetadata_final_noType() {
-    var declarationList = parseVariableDeclarationList('final a');
-    assertNoErrors();
-    expect(declarationList.keyword, isNotNull);
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclarationListAfterMetadata_final_type() {
-    var declarationList = parseVariableDeclarationList('final A a');
-    assertNoErrors();
-    expect(declarationList.keyword.lexeme, 'final');
-    expect(declarationList.type, isNotNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclarationListAfterMetadata_type_multiple() {
-    var declarationList = parseVariableDeclarationList('A a, b, c');
-    assertNoErrors();
-    expect(declarationList.keyword, isNull);
-    expect(declarationList.type, isNotNull);
-    expect(declarationList.variables, hasLength(3));
-  }
-
-  void test_parseVariableDeclarationListAfterMetadata_type_single() {
-    var declarationList = parseVariableDeclarationList('A a');
-    assertNoErrors();
-    expect(declarationList.keyword, isNull);
-    expect(declarationList.type, isNotNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclarationListAfterMetadata_var_multiple() {
-    var declarationList = parseVariableDeclarationList('var a, b, c');
-    assertNoErrors();
-    expect(declarationList.keyword.lexeme, 'var');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(3));
-  }
-
-  void test_parseVariableDeclarationListAfterMetadata_var_single() {
-    var declarationList = parseVariableDeclarationList('var a');
-    assertNoErrors();
-    expect(declarationList.keyword.lexeme, 'var');
-    expect(declarationList.type, isNull);
-    expect(declarationList.variables, hasLength(1));
-  }
-
-  void test_parseVariableDeclarationStatementAfterMetadata_multiple() {
-    var statement =
-        parseStatement('var x, y, z;') as VariableDeclarationStatement;
-    assertNoErrors();
-    expect(statement.semicolon, isNotNull);
-    VariableDeclarationList variableList = statement.variables;
-    expect(variableList, isNotNull);
-    expect(variableList.variables, hasLength(3));
-  }
-
-  void test_parseVariableDeclarationStatementAfterMetadata_single() {
-    var statement = parseStatement('var x;') as VariableDeclarationStatement;
-    assertNoErrors();
-    expect(statement.semicolon, isNotNull);
-    VariableDeclarationList variableList = statement.variables;
-    expect(variableList, isNotNull);
-    expect(variableList.variables, hasLength(1));
-  }
-
-  void test_parseWhileStatement() {
-    var statement = parseStatement('while (x) {}') as WhileStatement;
-    assertNoErrors();
-    expect(statement.whileKeyword, isNotNull);
-    expect(statement.leftParenthesis, isNotNull);
-    expect(statement.condition, isNotNull);
-    expect(statement.rightParenthesis, isNotNull);
-    expect(statement.body, isNotNull);
-  }
-
-  void test_parseYieldStatement_each() {
-    var statement =
-        _parseAsyncStatement('yield* x;', isGenerator: true) as YieldStatement;
-    assertNoErrors();
-    expect(statement.yieldKeyword, isNotNull);
-    expect(statement.star, isNotNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  void test_parseYieldStatement_normal() {
-    var statement =
-        _parseAsyncStatement('yield x;', isGenerator: true) as YieldStatement;
-    assertNoErrors();
-    expect(statement.yieldKeyword, isNotNull);
-    expect(statement.star, isNull);
-    expect(statement.expression, isNotNull);
-    expect(statement.semicolon, isNotNull);
-  }
-
-  Statement _parseAsyncStatement(String code, {bool isGenerator = false}) {
-    var star = isGenerator ? '*' : '';
-    var localFunction = parseStatement('wrapper() async$star { $code }')
-        as FunctionDeclarationStatement;
-    var localBody = localFunction.functionDeclaration.functionExpression.body
-        as BlockFunctionBody;
-    return localBody.block.statements.single;
-  }
-}
-
-@reflectiveTest
-class TopLevelParserTest extends ParserTestCase with TopLevelParserTestMixin {}
-
-/// Tests which exercise the parser using a complete compilation unit or
-/// compilation unit member.
-mixin TopLevelParserTestMixin implements AbstractParserTestCase {
-  void test_function_literal_allowed_at_toplevel() {
-    parseCompilationUnit("var x = () {};");
-  }
-
-  void
-      test_function_literal_allowed_in_ArgumentList_in_ConstructorFieldInitializer() {
-    parseCompilationUnit("class C { C() : a = f(() {}); }");
-  }
-
-  void
-      test_function_literal_allowed_in_IndexExpression_in_ConstructorFieldInitializer() {
-    parseCompilationUnit("class C { C() : a = x[() {}]; }");
-  }
-
-  void
-      test_function_literal_allowed_in_ListLiteral_in_ConstructorFieldInitializer() {
-    parseCompilationUnit("class C { C() : a = [() {}]; }");
-  }
-
-  void
-      test_function_literal_allowed_in_MapLiteral_in_ConstructorFieldInitializer() {
-    parseCompilationUnit("class C { C() : a = {'key': () {}}; }");
-  }
-
-  void
-      test_function_literal_allowed_in_ParenthesizedExpression_in_ConstructorFieldInitializer() {
-    parseCompilationUnit("class C { C() : a = (() {}); }");
-  }
-
-  void
-      test_function_literal_allowed_in_StringInterpolation_in_ConstructorFieldInitializer() {
-    parseCompilationUnit("class C { C() : a = \"\${(){}}\"; }");
-  }
-
-  void test_import_as_show() {
-    parseCompilationUnit("import 'dart:math' as M show E;");
-  }
-
-  void test_import_show_hide() {
-    parseCompilationUnit(
-        "import 'import1_lib.dart' show hide, show hide ugly;");
-  }
-
-  void test_import_withDocComment() {
-    var compilationUnit = parseCompilationUnit('/// Doc\nimport "foo.dart";');
-    var importDirective = compilationUnit.directives[0];
-    expectCommentText(importDirective.documentationComment, '/// Doc');
-  }
-
-  void test_parseClassDeclaration_abstract() {
-    createParser('abstract class A {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNotNull);
-    expect(declaration.extendsClause, isNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseClassDeclaration_empty() {
-    createParser('class A {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNull);
-    expect(declaration.extendsClause, isNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    _assertIsDeclarationName(declaration.name);
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseClassDeclaration_extends() {
-    createParser('class A extends B {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNull);
-    expect(declaration.extendsClause, isNotNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseClassDeclaration_extendsAndImplements() {
-    createParser('class A extends B implements C {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNull);
-    expect(declaration.extendsClause, isNotNull);
-    expect(declaration.implementsClause, isNotNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseClassDeclaration_extendsAndWith() {
-    createParser('class A extends B with C {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.typeParameters, isNull);
-    expect(declaration.extendsClause, isNotNull);
-    expect(declaration.withClause, isNotNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-  }
-
-  void test_parseClassDeclaration_extendsAndWithAndImplements() {
-    createParser('class A extends B with C implements D {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.typeParameters, isNull);
-    expect(declaration.extendsClause, isNotNull);
-    expect(declaration.withClause, isNotNull);
-    expect(declaration.implementsClause, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-  }
-
-  void test_parseClassDeclaration_implements() {
-    createParser('class A implements C {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNull);
-    expect(declaration.extendsClause, isNull);
-    expect(declaration.implementsClause, isNotNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseClassDeclaration_metadata() {
-    createParser('@A @B(2) @C.foo(3) @d.E.bar(4, 5) class X {}');
-    var declaration = parseFullCompilationUnitMember() as ClassDeclaration;
-    expect(declaration.metadata, hasLength(4));
-
-    {
-      var annotation = declaration.metadata[0];
-      expect(annotation.atSign, isNotNull);
-      expect(annotation.name, isSimpleIdentifier);
-      expect(annotation.name.name, 'A');
-      expect(annotation.period, isNull);
-      expect(annotation.constructorName, isNull);
-      expect(annotation.arguments, isNull);
-    }
-
-    {
-      var annotation = declaration.metadata[1];
-      expect(annotation.atSign, isNotNull);
-      expect(annotation.name, isSimpleIdentifier);
-      expect(annotation.name.name, 'B');
-      expect(annotation.period, isNull);
-      expect(annotation.constructorName, isNull);
-      expect(annotation.arguments, isNotNull);
-      expect(annotation.arguments.arguments, hasLength(1));
-    }
-
-    {
-      var annotation = declaration.metadata[2];
-      expect(annotation.atSign, isNotNull);
-      expect(annotation.name, isPrefixedIdentifier);
-      expect(annotation.name.name, 'C.foo');
-      expect(annotation.period, isNull);
-      expect(annotation.constructorName, isNull);
-      expect(annotation.arguments, isNotNull);
-      expect(annotation.arguments.arguments, hasLength(1));
-    }
-
-    {
-      var annotation = declaration.metadata[3];
-      expect(annotation.atSign, isNotNull);
-      expect(annotation.name, isPrefixedIdentifier);
-      expect(annotation.name.name, 'd.E');
-      expect(annotation.period, isNotNull);
-      expect(annotation.constructorName, isNotNull);
-      expect(annotation.constructorName.name, 'bar');
-      expect(annotation.arguments, isNotNull);
-      expect(annotation.arguments.arguments, hasLength(2));
-    }
-  }
-
-  void test_parseClassDeclaration_native() {
-    createParser('class A native "nativeValue" {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    if (!allowNativeClause) {
-      assertErrorsWithCodes([
-        ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
-      ]);
-    } else {
-      assertNoErrors();
-    }
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    NativeClause nativeClause = declaration.nativeClause;
-    expect(nativeClause, isNotNull);
-    expect(nativeClause.nativeKeyword, isNotNull);
-    expect(nativeClause.name.stringValue, "nativeValue");
-    expect(nativeClause.beginToken, same(nativeClause.nativeKeyword));
-    expect(nativeClause.endToken, same(nativeClause.name.endToken));
-  }
-
-  void test_parseClassDeclaration_nonEmpty() {
-    createParser('class A {var f;}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNull);
-    expect(declaration.extendsClause, isNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.members, hasLength(1));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNull);
-  }
-
-  void test_parseClassDeclaration_typeAlias_implementsC() {
-    createParser('class A = Object with B implements C;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassTypeAlias);
-    ClassTypeAlias typeAlias = member;
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    _assertIsDeclarationName(typeAlias.name);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.withClause, isNotNull);
-    expect(typeAlias.implementsClause, isNotNull);
-    expect(typeAlias.implementsClause.implementsKeyword, isNotNull);
-    expect(typeAlias.implementsClause.interfaces.length, 1);
-    expect(typeAlias.semicolon, isNotNull);
-  }
-
-  void test_parseClassDeclaration_typeAlias_withB() {
-    createParser('class A = Object with B;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassTypeAlias);
-    ClassTypeAlias typeAlias = member;
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.withClause, isNotNull);
-    expect(typeAlias.withClause.withKeyword, isNotNull);
-    expect(typeAlias.withClause.mixinTypes.length, 1);
-    expect(typeAlias.implementsClause, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-  }
-
-  void test_parseClassDeclaration_typeParameters() {
-    createParser('class A<B> {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.abstractKeyword, isNull);
-    expect(declaration.extendsClause, isNull);
-    expect(declaration.implementsClause, isNull);
-    expect(declaration.classKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    _assertIsDeclarationName(declaration.name);
-    expect(declaration.members, hasLength(0));
-    expect(declaration.rightBracket, isNotNull);
-    expect(declaration.typeParameters, isNotNull);
-    expect(declaration.typeParameters.typeParameters, hasLength(1));
-    _assertIsDeclarationName(declaration.typeParameters.typeParameters[0].name);
-  }
-
-  void test_parseClassDeclaration_typeParameters_extends_void() {
-    parseCompilationUnit('class C<T extends void>{}',
-        errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 18, 4)]
-            : [
-                expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 18, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 4),
-                expectedError(ParserErrorCode.EXPECTED_BODY, 18, 4),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 22, 1),
-                expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 22, 1),
-                expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
-              ]);
-  }
-
-  void test_parseClassDeclaration_withDocumentationComment() {
-    createParser('/// Doc\nclass C {}');
-    var classDeclaration = parseFullCompilationUnitMember() as ClassDeclaration;
-    expectCommentText(classDeclaration.documentationComment, '/// Doc');
-  }
-
-  void test_parseClassTypeAlias_withDocumentationComment() {
-    createParser('/// Doc\nclass C = D with E;');
-    var classTypeAlias = parseFullCompilationUnitMember() as ClassTypeAlias;
-    expectCommentText(classTypeAlias.documentationComment, '/// Doc');
-  }
-
-  void test_parseCompilationUnit_abstractAsPrefix_parameterized() {
-    var errorCodes = <ErrorCode>[];
-    if (usingFastaParser) {
-      // This used to be deferred to later in the pipeline, but is now being
-      // reported by the parser.
-      errorCodes.add(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE);
-    }
-    CompilationUnit unit = parseCompilationUnit(
-        'abstract<dynamic> _abstract = new abstract.A();',
-        codes: errorCodes);
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnit_builtIn_asFunctionName() {
-    for (Keyword keyword in Keyword.values) {
-      if (keyword.isBuiltIn || keyword.isPseudo) {
-        String lexeme = keyword.lexeme;
-        if (lexeme == 'Function') continue;
-        parseCompilationUnit('$lexeme(x) => 0;');
-        parseCompilationUnit('class C {$lexeme(x) => 0;}');
-      }
-    }
-  }
-
-  void test_parseCompilationUnit_builtIn_asFunctionName_withTypeParameter() {
-    if (usingFastaParser) {
-      for (Keyword keyword in Keyword.values) {
-        if (keyword.isBuiltIn || keyword.isPseudo) {
-          String lexeme = keyword.lexeme;
-          if (lexeme == 'Function') continue;
-          // The fasta type resolution phase will report an error
-          // on type arguments on `dynamic` (e.g. `dynamic<int>`).
-          parseCompilationUnit('$lexeme<T>(x) => 0;');
-          parseCompilationUnit('class C {$lexeme<T>(x) => 0;}');
-        }
-      }
-    }
-  }
-
-  void test_parseCompilationUnit_builtIn_asGetter() {
-    for (Keyword keyword in Keyword.values) {
-      if (keyword.isBuiltIn || keyword.isPseudo) {
-        String lexeme = keyword.lexeme;
-        parseCompilationUnit('get $lexeme => 0;');
-        parseCompilationUnit('class C {get $lexeme => 0;}');
-      }
-    }
-  }
-
-  void test_parseCompilationUnit_directives_multiple() {
-    createParser("library l;\npart 'a.dart';");
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    assertNoErrors();
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(2));
-    expect(unit.declarations, hasLength(0));
-  }
-
-  void test_parseCompilationUnit_directives_single() {
-    createParser('library l;');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    assertNoErrors();
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(1));
-    expect(unit.declarations, hasLength(0));
-  }
-
-  void test_parseCompilationUnit_empty() {
-    createParser('');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    assertNoErrors();
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-    expect(unit.declarations, hasLength(0));
-    expect(unit.beginToken, isNotNull);
-    expect(unit.endToken, isNotNull);
-    expect(unit.endToken.type, TokenType.EOF);
-  }
-
-  void test_parseCompilationUnit_exportAsPrefix() {
-    createParser('export.A _export = new export.A();');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    assertNoErrors();
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnit_exportAsPrefix_parameterized() {
-    createParser('export<dynamic> _export = new export.A();');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    if (usingFastaParser) {
-      // This used to be deferred to later in the pipeline, but is now being
-      // reported by the parser.
-      assertErrorsWithCodes([CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
-    } else {
-      assertNoErrors();
-    }
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnit_operatorAsPrefix_parameterized() {
-    createParser('operator<dynamic> _operator = new operator.A();');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    if (usingFastaParser) {
-      // This used to be deferred to later in the pipeline, but is now being
-      // reported by the parser.
-      assertErrorsWithCodes([CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
-    } else {
-      assertNoErrors();
-    }
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnit_pseudo_asTypeName() {
-    for (Keyword keyword in Keyword.values) {
-      if (keyword.isPseudo) {
-        String lexeme = keyword.lexeme;
-        parseCompilationUnit('$lexeme f;');
-        parseCompilationUnit('class C {$lexeme f;}');
-        parseCompilationUnit('f($lexeme g) {}');
-        parseCompilationUnit('f() {$lexeme g;}');
-      }
-    }
-  }
-
-  void test_parseCompilationUnit_pseudo_prefixed() {
-    for (Keyword keyword in Keyword.values) {
-      if (keyword.isPseudo) {
-        String lexeme = keyword.lexeme;
-        parseCompilationUnit('M.$lexeme f;');
-        parseCompilationUnit('class C {M.$lexeme f;}');
-      }
-    }
-  }
-
-  void test_parseCompilationUnit_script() {
-    createParser('#! /bin/dart');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    assertNoErrors();
-    expect(unit.scriptTag, isNotNull);
-    expect(unit.directives, hasLength(0));
-    expect(unit.declarations, hasLength(0));
-  }
-
-  void test_parseCompilationUnit_skipFunctionBody_withInterpolation() {
-    ParserTestCase.parseFunctionBodies = false;
-    createParser('f() { "\${n}"; }');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    assertNoErrors();
-    expect(unit.scriptTag, isNull);
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnit_topLevelDeclaration() {
-    createParser('class A {}');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    assertNoErrors();
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-    expect(unit.declarations, hasLength(1));
-    expect(unit.beginToken, isNotNull);
-    expect(unit.beginToken.keyword, Keyword.CLASS);
-    expect(unit.endToken, isNotNull);
-    expect(unit.endToken.type, TokenType.EOF);
-  }
-
-  void test_parseCompilationUnit_typedefAsPrefix() {
-    createParser('typedef.A _typedef = new typedef.A();');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    expect(unit, isNotNull);
-    assertNoErrors();
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnitMember_abstractAsPrefix() {
-    createParser('abstract.A _abstract = new abstract.A();');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isTopLevelVariableDeclaration);
-    TopLevelVariableDeclaration declaration = member;
-    expect(declaration.semicolon, isNotNull);
-    expect(declaration.variables, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_class() {
-    createParser('class A {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassDeclaration);
-    ClassDeclaration declaration = member;
-    expect(declaration.name.name, "A");
-    expect(declaration.members, hasLength(0));
-  }
-
-  void test_parseCompilationUnitMember_classTypeAlias() {
-    createParser('abstract class A = B with C;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassTypeAlias);
-    ClassTypeAlias declaration = member;
-    expect(declaration.name.name, "A");
-    expect(declaration.abstractKeyword, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_constVariable() {
-    createParser('const int x = 0;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isTopLevelVariableDeclaration);
-    TopLevelVariableDeclaration declaration = member;
-    expect(declaration.semicolon, isNotNull);
-    expect(declaration.variables, isNotNull);
-    expect(declaration.variables.keyword.lexeme, 'const');
-    _assertIsDeclarationName(declaration.variables.variables[0].name);
-  }
-
-  void test_parseCompilationUnitMember_expressionFunctionBody_tokens() {
-    createParser('f() => 0;');
-    var f = parseFullCompilationUnitMember() as FunctionDeclaration;
-    var body = f.functionExpression.body as ExpressionFunctionBody;
-    expect(body.functionDefinition.lexeme, '=>');
-    expect(body.semicolon.lexeme, ';');
-    _assertIsDeclarationName(f.name);
-  }
-
-  void test_parseCompilationUnitMember_finalVariable() {
-    createParser('final x = 0;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isTopLevelVariableDeclaration);
-    TopLevelVariableDeclaration declaration = member;
-    expect(declaration.semicolon, isNotNull);
-    expect(declaration.variables, isNotNull);
-    expect(declaration.variables.keyword.lexeme, 'final');
-  }
-
-  void test_parseCompilationUnitMember_function_external_noType() {
-    createParser('external f();');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.externalKeyword, isNotNull);
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNull);
-  }
-
-  void test_parseCompilationUnitMember_function_external_type() {
-    createParser('external int f();');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.externalKeyword, isNotNull);
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNull);
-  }
-
-  void test_parseCompilationUnitMember_function_generic_noReturnType() {
-    createParser('f<E>() {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.returnType, isNull);
-    expect(declaration.functionExpression.typeParameters, isNotNull);
-  }
-
-  void
-      test_parseCompilationUnitMember_function_generic_noReturnType_annotated() {
-    createParser('f<@a E>() {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.returnType, isNull);
-    expect(declaration.functionExpression.typeParameters, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_function_generic_returnType() {
-    createParser('E f<E>() {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.returnType, isNotNull);
-    expect(declaration.functionExpression.typeParameters, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_function_generic_void() {
-    createParser('void f<T>(T t) {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNull);
-  }
-
-  void test_parseCompilationUnitMember_function_gftReturnType() {
-    createParser('''
-void Function<A>(core.List<core.int> x) f() => null;
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    assertNoErrors();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnitMember_function_noReturnType() {
-    createParser('''
-Function<A>(core.List<core.int> x) f() => null;
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    assertNoErrors();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnitMember_function_noType() {
-    createParser('f() {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNull);
-  }
-
-  void test_parseCompilationUnitMember_function_type() {
-    createParser('int f() {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNull);
-  }
-
-  void test_parseCompilationUnitMember_function_void() {
-    createParser('void f() {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.returnType, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_getter_external_noType() {
-    createParser('external get p;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.externalKeyword, isNotNull);
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-    _assertIsDeclarationName(declaration.name);
-  }
-
-  void test_parseCompilationUnitMember_getter_external_type() {
-    createParser('external int get p;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.externalKeyword, isNotNull);
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_getter_noType() {
-    createParser('get p => 0;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_getter_type() {
-    createParser('int get p => 0;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_setter_external_noType() {
-    createParser('external set p(v);');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.externalKeyword, isNotNull);
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_setter_external_type() {
-    createParser('external void set p(int v);');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.externalKeyword, isNotNull);
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_setter_noType() {
-    createParser('set p(v) {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-    _assertIsDeclarationName(declaration.name);
-  }
-
-  void test_parseCompilationUnitMember_setter_type() {
-    createParser('void set p(int v) {}');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isFunctionDeclaration);
-    FunctionDeclaration declaration = member;
-    expect(declaration.functionExpression, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-    expect(declaration.returnType, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_typeAlias_abstract() {
-    createParser('abstract class C = S with M;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassTypeAlias);
-    ClassTypeAlias typeAlias = member;
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name.name, "C");
-    _assertIsDeclarationName(typeAlias.name);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.equals, isNotNull);
-    expect(typeAlias.abstractKeyword, isNotNull);
-    expect(typeAlias.superclass.name.name, "S");
-    expect(typeAlias.withClause, isNotNull);
-    expect(typeAlias.implementsClause, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_typeAlias_generic() {
-    createParser('class C<E> = S<E> with M<E> implements I<E>;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassTypeAlias);
-    ClassTypeAlias typeAlias = member;
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name.name, "C");
-    expect(typeAlias.typeParameters.typeParameters, hasLength(1));
-    expect(typeAlias.equals, isNotNull);
-    expect(typeAlias.abstractKeyword, isNull);
-    expect(typeAlias.superclass.name.name, "S");
-    expect(typeAlias.withClause, isNotNull);
-    expect(typeAlias.implementsClause, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_typeAlias_implements() {
-    createParser('class C = S with M implements I;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassTypeAlias);
-    ClassTypeAlias typeAlias = member;
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name.name, "C");
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.equals, isNotNull);
-    expect(typeAlias.abstractKeyword, isNull);
-    expect(typeAlias.superclass.name.name, "S");
-    expect(typeAlias.withClause, isNotNull);
-    expect(typeAlias.implementsClause, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_typeAlias_noImplements() {
-    createParser('class C = S with M;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isClassTypeAlias);
-    ClassTypeAlias typeAlias = member;
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name.name, "C");
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.equals, isNotNull);
-    expect(typeAlias.abstractKeyword, isNull);
-    expect(typeAlias.superclass.name.name, "S");
-    expect(typeAlias.withClause, isNotNull);
-    expect(typeAlias.implementsClause, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_typedef() {
-    createParser('typedef F();');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, TypeMatcher<FunctionTypeAlias>());
-    FunctionTypeAlias typeAlias = member;
-    expect(typeAlias.name.name, "F");
-    expect(typeAlias.parameters.parameters, hasLength(0));
-    _assertIsDeclarationName(typeAlias.name);
-  }
-
-  void test_parseCompilationUnitMember_typedef_withDocComment() {
-    createParser('/// Doc\ntypedef F();');
-    var typeAlias = parseFullCompilationUnitMember() as FunctionTypeAlias;
-    expectCommentText(typeAlias.documentationComment, '/// Doc');
-  }
-
-  void test_parseCompilationUnitMember_typedVariable() {
-    createParser('int x = 0;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isTopLevelVariableDeclaration);
-    TopLevelVariableDeclaration declaration = member;
-    expect(declaration.semicolon, isNotNull);
-    expect(declaration.variables, isNotNull);
-    expect(declaration.variables.type, isNotNull);
-    expect(declaration.variables.keyword, isNull);
-    _assertIsDeclarationName(declaration.variables.variables[0].name);
-  }
-
-  void test_parseCompilationUnitMember_variable() {
-    createParser('var x = 0;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isTopLevelVariableDeclaration);
-    TopLevelVariableDeclaration declaration = member;
-    expect(declaration.semicolon, isNotNull);
-    expect(declaration.variables, isNotNull);
-    expect(declaration.variables.keyword.lexeme, 'var');
-  }
-
-  void test_parseCompilationUnitMember_variable_gftType_gftReturnType() {
-    createParser('''
-Function(int) Function(String) v;
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    assertNoErrors();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(1));
-    TopLevelVariableDeclaration declaration =
-        unit.declarations[0] as TopLevelVariableDeclaration;
-    expect(declaration.variables.type, isGenericFunctionType);
-  }
-
-  void test_parseCompilationUnitMember_variable_gftType_noReturnType() {
-    createParser('''
-Function(int, String) v;
-''');
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    assertNoErrors();
-    expect(unit, isNotNull);
-    expect(unit.declarations, hasLength(1));
-  }
-
-  void test_parseCompilationUnitMember_variable_withDocumentationComment() {
-    createParser('/// Doc\nvar x = 0;');
-    var declaration =
-        parseFullCompilationUnitMember() as TopLevelVariableDeclaration;
-    expectCommentText(declaration.documentationComment, '/// Doc');
-  }
-
-  void test_parseCompilationUnitMember_variableGet() {
-    createParser('String get = null;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isTopLevelVariableDeclaration);
-    TopLevelVariableDeclaration declaration = member;
-    expect(declaration.semicolon, isNotNull);
-    expect(declaration.variables, isNotNull);
-  }
-
-  void test_parseCompilationUnitMember_variableSet() {
-    createParser('String set = null;');
-    CompilationUnitMember member = parseFullCompilationUnitMember();
-    expect(member, isNotNull);
-    assertNoErrors();
-    expect(member, isTopLevelVariableDeclaration);
-    TopLevelVariableDeclaration declaration = member;
-    expect(declaration.semicolon, isNotNull);
-    expect(declaration.variables, isNotNull);
-  }
-
-  void test_parseDirective_export() {
-    createParser("export 'lib/lib.dart';");
-    Directive directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive, TypeMatcher<ExportDirective>());
-    ExportDirective exportDirective = directive;
-    expect(exportDirective.keyword, isNotNull);
-    expect(exportDirective.uri, isNotNull);
-    expect(exportDirective.combinators, hasLength(0));
-    expect(exportDirective.semicolon, isNotNull);
-  }
-
-  void test_parseDirective_export_withDocComment() {
-    createParser("/// Doc\nexport 'foo.dart';");
-    var directive = parseFullDirective() as ExportDirective;
-    expectCommentText(directive.documentationComment, '/// Doc');
-  }
-
-  void test_parseDirective_import() {
-    createParser("import 'lib/lib.dart';");
-    Directive directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive, TypeMatcher<ImportDirective>());
-    ImportDirective importDirective = directive;
-    expect(importDirective.keyword, isNotNull);
-    expect(importDirective.uri, isNotNull);
-    expect(importDirective.asKeyword, isNull);
-    expect(importDirective.prefix, isNull);
-    expect(importDirective.combinators, hasLength(0));
-    expect(importDirective.semicolon, isNotNull);
-  }
-
-  void test_parseDirective_library() {
-    createParser("library l;");
-    Directive directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive, TypeMatcher<LibraryDirective>());
-    LibraryDirective libraryDirective = directive;
-    expect(libraryDirective.libraryKeyword, isNotNull);
-    expect(libraryDirective.name, isNotNull);
-    expect(libraryDirective.semicolon, isNotNull);
-  }
-
-  void test_parseDirective_library_1_component() {
-    createParser("library a;");
-    var lib = parseFullDirective() as LibraryDirective;
-    expect(lib.name.components, hasLength(1));
-    expect(lib.name.components[0].name, 'a');
-  }
-
-  void test_parseDirective_library_2_components() {
-    createParser("library a.b;");
-    var lib = parseFullDirective() as LibraryDirective;
-    expect(lib.name.components, hasLength(2));
-    expect(lib.name.components[0].name, 'a');
-    expect(lib.name.components[1].name, 'b');
-  }
-
-  void test_parseDirective_library_3_components() {
-    createParser("library a.b.c;");
-    var lib = parseFullDirective() as LibraryDirective;
-    expect(lib.name.components, hasLength(3));
-    expect(lib.name.components[0].name, 'a');
-    expect(lib.name.components[1].name, 'b');
-    expect(lib.name.components[2].name, 'c');
-  }
-
-  void test_parseDirective_library_annotation() {
-    createParser("@A library l;");
-    Directive directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive, TypeMatcher<LibraryDirective>());
-    LibraryDirective libraryDirective = directive;
-    expect(libraryDirective.libraryKeyword, isNotNull);
-    expect(libraryDirective.name, isNotNull);
-    expect(libraryDirective.semicolon, isNotNull);
-    expect(libraryDirective.metadata, hasLength(1));
-    expect(libraryDirective.metadata[0].name.name, 'A');
-  }
-
-  void test_parseDirective_library_annotation2() {
-    createParser("@A library l;");
-    CompilationUnit unit = parser.parseCompilationUnit2();
-    Directive directive = unit.directives[0];
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive, TypeMatcher<LibraryDirective>());
-    LibraryDirective libraryDirective = directive;
-    expect(libraryDirective.libraryKeyword, isNotNull);
-    expect(libraryDirective.name, isNotNull);
-    expect(libraryDirective.semicolon, isNotNull);
-    expect(libraryDirective.metadata, hasLength(1));
-    expect(libraryDirective.metadata[0].name.name, 'A');
-  }
-
-  void test_parseDirective_library_withDocumentationComment() {
-    createParser('/// Doc\nlibrary l;');
-    var directive = parseFullDirective() as LibraryDirective;
-    expectCommentText(directive.documentationComment, '/// Doc');
-  }
-
-  void test_parseDirective_part() {
-    createParser("part 'lib/lib.dart';");
-    Directive directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive, TypeMatcher<PartDirective>());
-    PartDirective partDirective = directive;
-    expect(partDirective.partKeyword, isNotNull);
-    expect(partDirective.uri, isNotNull);
-    expect(partDirective.semicolon, isNotNull);
-  }
-
-  void test_parseDirective_part_of_1_component() {
-    createParser("part of a;");
-    var partOf = parseFullDirective() as PartOfDirective;
-    expect(partOf.libraryName.components, hasLength(1));
-    expect(partOf.libraryName.components[0].name, 'a');
-  }
-
-  void test_parseDirective_part_of_2_components() {
-    createParser("part of a.b;");
-    var partOf = parseFullDirective() as PartOfDirective;
-    expect(partOf.libraryName.components, hasLength(2));
-    expect(partOf.libraryName.components[0].name, 'a');
-    expect(partOf.libraryName.components[1].name, 'b');
-  }
-
-  void test_parseDirective_part_of_3_components() {
-    createParser("part of a.b.c;");
-    var partOf = parseFullDirective() as PartOfDirective;
-    expect(partOf.libraryName.components, hasLength(3));
-    expect(partOf.libraryName.components[0].name, 'a');
-    expect(partOf.libraryName.components[1].name, 'b');
-    expect(partOf.libraryName.components[2].name, 'c');
-  }
-
-  void test_parseDirective_part_of_withDocumentationComment() {
-    createParser('/// Doc\npart of a;');
-    var partOf = parseFullDirective() as PartOfDirective;
-    expectCommentText(partOf.documentationComment, '/// Doc');
-  }
-
-  void test_parseDirective_part_withDocumentationComment() {
-    createParser("/// Doc\npart 'lib.dart';");
-    var directive = parseFullDirective() as PartDirective;
-    expectCommentText(directive.documentationComment, '/// Doc');
-  }
-
-  void test_parseDirective_partOf() {
-    createParser("part of l;");
-    Directive directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive, TypeMatcher<PartOfDirective>());
-    PartOfDirective partOfDirective = directive;
-    expect(partOfDirective.partKeyword, isNotNull);
-    expect(partOfDirective.ofKeyword, isNotNull);
-    expect(partOfDirective.libraryName, isNotNull);
-    expect(partOfDirective.semicolon, isNotNull);
-  }
-
-  void test_parseDirectives_annotations() {
-    CompilationUnit unit =
-        parseDirectives("@A library l; @B import 'foo.dart';");
-    expect(unit.directives, hasLength(2));
-    expect(unit.directives[0].metadata[0].name.name, 'A');
-    expect(unit.directives[1].metadata[0].name.name, 'B');
-  }
-
-  void test_parseDirectives_complete() {
-    CompilationUnit unit =
-        parseDirectives("#! /bin/dart\nlibrary l;\nclass A {}");
-    expect(unit.scriptTag, isNotNull);
-    expect(unit.directives, hasLength(1));
-  }
-
-  void test_parseDirectives_empty() {
-    CompilationUnit unit = parseDirectives("");
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-  }
-
-  void test_parseDirectives_mixed() {
-    CompilationUnit unit =
-        parseDirectives("library l; class A {} part 'foo.dart';");
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(1));
-  }
-
-  void test_parseDirectives_multiple() {
-    CompilationUnit unit = parseDirectives("library l;\npart 'a.dart';");
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(2));
-  }
-
-  void test_parseDirectives_script() {
-    CompilationUnit unit = parseDirectives("#! /bin/dart");
-    expect(unit.scriptTag, isNotNull);
-    expect(unit.directives, hasLength(0));
-  }
-
-  void test_parseDirectives_single() {
-    CompilationUnit unit = parseDirectives("library l;");
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(1));
-  }
-
-  void test_parseDirectives_topLevelDeclaration() {
-    CompilationUnit unit = parseDirectives("class A {}");
-    expect(unit.scriptTag, isNull);
-    expect(unit.directives, hasLength(0));
-  }
-
-  void test_parseEnumDeclaration_one() {
-    createParser("enum E {ONE}");
-    EnumDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.enumKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.constants, hasLength(1));
-    expect(declaration.rightBracket, isNotNull);
-  }
-
-  void test_parseEnumDeclaration_trailingComma() {
-    createParser("enum E {ONE,}");
-    EnumDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.enumKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.constants, hasLength(1));
-    expect(declaration.rightBracket, isNotNull);
-  }
-
-  void test_parseEnumDeclaration_two() {
-    createParser("enum E {ONE, TWO}");
-    EnumDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.documentationComment, isNull);
-    expect(declaration.enumKeyword, isNotNull);
-    expect(declaration.leftBracket, isNotNull);
-    expect(declaration.name, isNotNull);
-    expect(declaration.constants, hasLength(2));
-    expect(declaration.rightBracket, isNotNull);
-  }
-
-  void test_parseEnumDeclaration_withDocComment_onEnum() {
-    createParser('/// Doc\nenum E {ONE}');
-    var declaration = parseFullCompilationUnitMember() as EnumDeclaration;
-    expectCommentText(declaration.documentationComment, '/// Doc');
-  }
-
-  void test_parseEnumDeclaration_withDocComment_onValue() {
-    createParser('''
-enum E {
-  /// Doc
-  ONE
-}''');
-    var declaration = parseFullCompilationUnitMember() as EnumDeclaration;
-    var value = declaration.constants[0];
-    expectCommentText(value.documentationComment, '/// Doc');
-  }
-
-  void test_parseEnumDeclaration_withDocComment_onValue_annotated() {
-    createParser('''
-enum E {
-  /// Doc
-  @annotation
-  ONE
-}
-''');
-    var declaration = parseFullCompilationUnitMember() as EnumDeclaration;
-    var value = declaration.constants[0];
-    expectCommentText(value.documentationComment, '/// Doc');
-    expect(value.metadata, hasLength(1));
-  }
-
-  void test_parseExportDirective_configuration_multiple() {
-    createParser("export 'lib/lib.dart' if (a) 'b.dart' if (c) 'd.dart';");
-    ExportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.configurations, hasLength(2));
-    expectDottedName(directive.configurations[0].name, ['a']);
-    expectDottedName(directive.configurations[1].name, ['c']);
-    expect(directive.combinators, hasLength(0));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseExportDirective_configuration_single() {
-    createParser("export 'lib/lib.dart' if (a.b == 'c.dart') '';");
-    ExportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.configurations, hasLength(1));
-    expectDottedName(directive.configurations[0].name, ['a', 'b']);
-    expect(directive.combinators, hasLength(0));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseExportDirective_hide() {
-    createParser("export 'lib/lib.dart' hide A, B;");
-    ExportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.combinators, hasLength(1));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseExportDirective_hide_show() {
-    createParser("export 'lib/lib.dart' hide A show B;");
-    ExportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.combinators, hasLength(2));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseExportDirective_noCombinator() {
-    createParser("export 'lib/lib.dart';");
-    ExportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.combinators, hasLength(0));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseExportDirective_show() {
-    createParser("export 'lib/lib.dart' show A, B;");
-    ExportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.combinators, hasLength(1));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseExportDirective_show_hide() {
-    createParser("export 'lib/lib.dart' show B hide A;");
-    ExportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.combinators, hasLength(2));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseFunctionDeclaration_function() {
-    createParser('/// Doc\nT f() {}');
-    FunctionDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expectCommentText(declaration.documentationComment, '/// Doc');
-    expect((declaration.returnType as TypeName).name.name, 'T');
-    expect(declaration.name, isNotNull);
-    FunctionExpression expression = declaration.functionExpression;
-    expect(expression, isNotNull);
-    expect(expression.body, isNotNull);
-    expect(expression.typeParameters, isNull);
-    expect(expression.parameters, isNotNull);
-    expect(declaration.propertyKeyword, isNull);
-  }
-
-  void test_parseFunctionDeclaration_functionWithTypeParameters() {
-    createParser('/// Doc\nT f<E>() {}');
-    FunctionDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expectCommentText(declaration.documentationComment, '/// Doc');
-    expect((declaration.returnType as TypeName).name.name, 'T');
-    expect(declaration.name, isNotNull);
-    FunctionExpression expression = declaration.functionExpression;
-    expect(expression, isNotNull);
-    expect(expression.body, isNotNull);
-    expect(expression.typeParameters, isNotNull);
-    expect(expression.parameters, isNotNull);
-    expect(declaration.propertyKeyword, isNull);
-  }
-
-  void test_parseFunctionDeclaration_getter() {
-    createParser('/// Doc\nT get p => 0;');
-    FunctionDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expectCommentText(declaration.documentationComment, '/// Doc');
-    expect((declaration.returnType as TypeName).name.name, 'T');
-    expect(declaration.name, isNotNull);
-    FunctionExpression expression = declaration.functionExpression;
-    expect(expression, isNotNull);
-    expect(expression.body, isNotNull);
-    expect(expression.typeParameters, isNull);
-    expect(expression.parameters, isNull);
-    expect(declaration.propertyKeyword, isNotNull);
-  }
-
-  void test_parseFunctionDeclaration_metadata() {
-    createParser(
-        'T f(@A a, @B(2) Foo b, {@C.foo(3) c : 0, @d.E.bar(4, 5) x:0}) {}');
-    FunctionDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expect(declaration.documentationComment, isNull);
-    expect((declaration.returnType as TypeName).name.name, 'T');
-    expect(declaration.name, isNotNull);
-    FunctionExpression expression = declaration.functionExpression;
-    expect(expression, isNotNull);
-    expect(expression.body, isNotNull);
-    expect(expression.typeParameters, isNull);
-    NodeList<FormalParameter> parameters = expression.parameters.parameters;
-    expect(parameters, hasLength(4));
-    expect(declaration.propertyKeyword, isNull);
-
-    {
-      var annotation = parameters[0].metadata[0];
-      expect(annotation.atSign, isNotNull);
-      expect(annotation.name, isSimpleIdentifier);
-      expect(annotation.name.name, 'A');
-      expect(annotation.period, isNull);
-      expect(annotation.constructorName, isNull);
-      expect(annotation.arguments, isNull);
-    }
-
-    {
-      var annotation = parameters[1].metadata[0];
-      expect(annotation.atSign, isNotNull);
-      expect(annotation.name, isSimpleIdentifier);
-      expect(annotation.name.name, 'B');
-      expect(annotation.period, isNull);
-      expect(annotation.constructorName, isNull);
-      expect(annotation.arguments, isNotNull);
-      expect(annotation.arguments.arguments, hasLength(1));
-    }
-
-    {
-      var annotation = parameters[2].metadata[0];
-      expect(annotation.atSign, isNotNull);
-      expect(annotation.name, isPrefixedIdentifier);
-      expect(annotation.name.name, 'C.foo');
-      expect(annotation.period, isNull);
-      expect(annotation.constructorName, isNull);
-      expect(annotation.arguments, isNotNull);
-      expect(annotation.arguments.arguments, hasLength(1));
-    }
-
-    {
-      var annotation = parameters[3].metadata[0];
-      expect(annotation.atSign, isNotNull);
-      expect(annotation.name, isPrefixedIdentifier);
-      expect(annotation.name.name, 'd.E');
-      expect(annotation.period, isNotNull);
-      expect(annotation.constructorName, isNotNull);
-      expect(annotation.constructorName.name, 'bar');
-      expect(annotation.arguments, isNotNull);
-      expect(annotation.arguments.arguments, hasLength(2));
-    }
-  }
-
-  void test_parseFunctionDeclaration_setter() {
-    createParser('/// Doc\nT set p(v) {}');
-    FunctionDeclaration declaration = parseFullCompilationUnitMember();
-    expect(declaration, isNotNull);
-    assertNoErrors();
-    expectCommentText(declaration.documentationComment, '/// Doc');
-    expect((declaration.returnType as TypeName).name.name, 'T');
-    expect(declaration.name, isNotNull);
-    FunctionExpression expression = declaration.functionExpression;
-    expect(expression, isNotNull);
-    expect(expression.body, isNotNull);
-    expect(expression.typeParameters, isNull);
-    expect(expression.parameters, isNotNull);
-    expect(declaration.propertyKeyword, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_noTypeParameters() {
-    createParser('typedef F = int Function(int);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters, isNull);
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_typeParameters() {
-    createParser('typedef F<T> = T Function(T);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters.typeParameters, hasLength(1));
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_typeParameters2() {
-    // The scanner creates a single token for `>=`
-    // then the parser must split it into two separate tokens.
-    createParser('typedef F<T>= T Function(T);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters.typeParameters, hasLength(1));
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_typeParameters3() {
-    createParser('typedef F<A,B,C> = Function(A a, B b, C c);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters.typeParameters, hasLength(3));
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_typeParameters3_gtEq() {
-    // The scanner creates a single token for `>=`
-    // then the parser must split it into two separate tokens.
-    createParser('typedef F<A,B,C>=Function(A a, B b, C c);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters.typeParameters, hasLength(3));
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_typeParameters_extends() {
-    createParser('typedef F<A,B,C extends D<E>> = Function(A a, B b, C c);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters.typeParameters, hasLength(3));
-    TypeParameter typeParam = alias.typeParameters.typeParameters[2];
-    NamedType type = typeParam.bound;
-    expect(type.typeArguments.arguments, hasLength(1));
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_typeParameters_extends3() {
-    createParser(
-        'typedef F<A,B,C extends D<E,G,H>> = Function(A a, B b, C c);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters.typeParameters, hasLength(3));
-    TypeParameter typeParam = alias.typeParameters.typeParameters[2];
-    NamedType type = typeParam.bound;
-    expect(type.typeArguments.arguments, hasLength(3));
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_typeParameters_extends3_gtGtEq() {
-    // The scanner creates a single token for `>>=`
-    // then the parser must split it into three separate tokens.
-    createParser('typedef F<A,B,C extends D<E,G,H>>=Function(A a, B b, C c);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters.typeParameters, hasLength(3));
-    TypeParameter typeParam = alias.typeParameters.typeParameters[2];
-    NamedType type = typeParam.bound;
-    expect(type.typeArguments.arguments, hasLength(3));
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseGenericTypeAlias_typeParameters_extends_gtGtEq() {
-    // The scanner creates a single token for `>>=`
-    // then the parser must split it into three separate tokens.
-    createParser('typedef F<A,B,C extends D<E>>=Function(A a, B b, C c);');
-    GenericTypeAlias alias = parseFullCompilationUnitMember();
-    expect(alias, isNotNull);
-    assertNoErrors();
-    expect(alias.name, isNotNull);
-    expect(alias.name.name, 'F');
-    expect(alias.typeParameters.typeParameters, hasLength(3));
-    TypeParameter typeParam = alias.typeParameters.typeParameters[2];
-    NamedType type = typeParam.bound;
-    expect(type.typeArguments.arguments, hasLength(1));
-    expect(alias.equals, isNotNull);
-    expect(alias.functionType, isNotNull);
-    expect(alias.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_configuration_multiple() {
-    createParser("import 'lib/lib.dart' if (a) 'b.dart' if (c) 'd.dart';");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.configurations, hasLength(2));
-    expectDottedName(directive.configurations[0].name, ['a']);
-    expectDottedName(directive.configurations[1].name, ['c']);
-    expect(directive.deferredKeyword, isNull);
-    expect(directive.asKeyword, isNull);
-    expect(directive.prefix, isNull);
-    expect(directive.combinators, hasLength(0));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_configuration_single() {
-    createParser("import 'lib/lib.dart' if (a.b == 'c.dart') '';");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.configurations, hasLength(1));
-    expectDottedName(directive.configurations[0].name, ['a', 'b']);
-    expect(directive.deferredKeyword, isNull);
-    expect(directive.asKeyword, isNull);
-    expect(directive.prefix, isNull);
-    expect(directive.combinators, hasLength(0));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_deferred() {
-    createParser("import 'lib/lib.dart' deferred as a;");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.deferredKeyword, isNotNull);
-    expect(directive.asKeyword, isNotNull);
-    expect(directive.prefix, isNotNull);
-    expect(directive.combinators, hasLength(0));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_hide() {
-    createParser("import 'lib/lib.dart' hide A, B;");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.deferredKeyword, isNull);
-    expect(directive.asKeyword, isNull);
-    expect(directive.prefix, isNull);
-    expect(directive.combinators, hasLength(1));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_noCombinator() {
-    createParser("import 'lib/lib.dart';");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.deferredKeyword, isNull);
-    expect(directive.asKeyword, isNull);
-    expect(directive.prefix, isNull);
-    expect(directive.combinators, hasLength(0));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_prefix() {
-    createParser("import 'lib/lib.dart' as a;");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.deferredKeyword, isNull);
-    expect(directive.asKeyword, isNotNull);
-    expect(directive.prefix, isNotNull);
-    expect(directive.combinators, hasLength(0));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_prefix_hide_show() {
-    createParser("import 'lib/lib.dart' as a hide A show B;");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.deferredKeyword, isNull);
-    expect(directive.asKeyword, isNotNull);
-    expect(directive.prefix, isNotNull);
-    expect(directive.combinators, hasLength(2));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_prefix_show_hide() {
-    createParser("import 'lib/lib.dart' as a show B hide A;");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.deferredKeyword, isNull);
-    expect(directive.asKeyword, isNotNull);
-    expect(directive.prefix, isNotNull);
-    expect(directive.combinators, hasLength(2));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseImportDirective_show() {
-    createParser("import 'lib/lib.dart' show A, B;");
-    ImportDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.keyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.deferredKeyword, isNull);
-    expect(directive.asKeyword, isNull);
-    expect(directive.prefix, isNull);
-    expect(directive.combinators, hasLength(1));
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseLibraryDirective() {
-    createParser('library l;');
-    LibraryDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.libraryKeyword, isNotNull);
-    expect(directive.name, isNotNull);
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parsePartDirective() {
-    createParser("part 'lib/lib.dart';");
-    PartDirective directive = parseFullDirective();
-    expect(directive, isNotNull);
-    assertNoErrors();
-    expect(directive.partKeyword, isNotNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parsePartOfDirective_name() {
-    enableUriInPartOf = true;
-    createParser("part of l;");
-    PartOfDirective directive = parseFullDirective();
-    expect(directive.partKeyword, isNotNull);
-    expect(directive.ofKeyword, isNotNull);
-    expect(directive.libraryName, isNotNull);
-    expect(directive.uri, isNull);
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parsePartOfDirective_uri() {
-    enableUriInPartOf = true;
-    createParser("part of 'lib.dart';");
-    PartOfDirective directive = parseFullDirective();
-    expect(directive.partKeyword, isNotNull);
-    expect(directive.ofKeyword, isNotNull);
-    expect(directive.libraryName, isNull);
-    expect(directive.uri, isNotNull);
-    expect(directive.semicolon, isNotNull);
-  }
-
-  void test_parseTypeAlias_function_noParameters() {
-    createParser('typedef bool F();');
-    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.parameters, isNotNull);
-    expect(typeAlias.returnType, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_function_noReturnType() {
-    createParser('typedef F();');
-    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.parameters, isNotNull);
-    expect(typeAlias.returnType, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_function_parameterizedReturnType() {
-    createParser('typedef A<B> F();');
-    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.parameters, isNotNull);
-    expect(typeAlias.returnType, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_function_parameters() {
-    createParser('typedef bool F(Object value);');
-    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.parameters, isNotNull);
-    expect(typeAlias.returnType, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_function_typeParameters() {
-    createParser('typedef bool F<E>();');
-    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.parameters, isNotNull);
-    expect(typeAlias.returnType, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    expect(typeAlias.typeParameters, isNotNull);
-  }
-
-  void test_parseTypeAlias_function_voidReturnType() {
-    createParser('typedef void F();');
-    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.parameters, isNotNull);
-    expect(typeAlias.returnType, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_noParameters() {
-    createParser('typedef F = bool Function();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_noReturnType() {
-    createParser('typedef F = Function();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_parameterizedReturnType() {
-    createParser('typedef F = A<B> Function();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_parameters() {
-    createParser('typedef F = bool Function(Object value);');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_typeParameters() {
-    createParser('typedef F = bool Function<E>();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNotNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_typeParameters_noParameters() {
-    createParser('typedef F<T> = bool Function();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_typeParameters_noReturnType() {
-    createParser('typedef F<T> = Function();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void
-      test_parseTypeAlias_genericFunction_typeParameters_parameterizedReturnType() {
-    createParser('typedef F<T> = A<B> Function();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_typeParameters_parameters() {
-    createParser('typedef F<T> = bool Function(Object value);');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_typeParameters_typeParameters() {
-    createParser('typedef F<T> = bool Function<E>();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNotNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_typeParameters_voidReturnType() {
-    createParser('typedef F<T> = void Function();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNotNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_voidReturnType() {
-    createParser('typedef F = void Function();');
-    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
-    expect(typeAlias, isNotNull);
-    assertNoErrors();
-    expect(typeAlias.typedefKeyword, isNotNull);
-    expect(typeAlias.name, isNotNull);
-    expect(typeAlias.typeParameters, isNull);
-    expect(typeAlias.semicolon, isNotNull);
-    GenericFunctionType functionType = typeAlias.functionType;
-    expect(functionType, isNotNull);
-    expect(functionType.parameters, isNotNull);
-    expect(functionType.returnType, isNotNull);
-    expect(functionType.typeParameters, isNull);
-  }
-
-  void test_parseTypeAlias_genericFunction_withDocComment() {
-    createParser('/// Doc\ntypedef F = bool Function();');
-    var typeAlias = parseFullCompilationUnitMember() as GenericTypeAlias;
-    expectCommentText(typeAlias.documentationComment, '/// Doc');
-  }
-
-  void test_parseTypeVariable_withDocumentationComment() {
-    createParser('''
-class A<
-    /// Doc
-    B> {}
-''');
-    var classDeclaration = parseFullCompilationUnitMember() as ClassDeclaration;
-    var typeVariable = classDeclaration.typeParameters.typeParameters[0];
-    expectCommentText(typeVariable.documentationComment, '/// Doc');
-  }
-
-  /// Assert that the given [name] is in declaration context.
-  void _assertIsDeclarationName(SimpleIdentifier name) {
-    expect(name.inDeclarationContext(), isTrue);
-  }
-}
diff --git a/pkg/analyzer/test/generated/parser_test_base.dart b/pkg/analyzer/test/generated/parser_test_base.dart
new file mode 100644
index 0000000..f6387fe
--- /dev/null
+++ b/pkg/analyzer/test/generated/parser_test_base.dart
@@ -0,0 +1,1532 @@
+// 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.
+
+import 'package:_fe_analyzer_shared/src/parser/async_modifier.dart';
+import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/error_token.dart'
+    show ErrorToken;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show ScannerConfiguration, ScannerResult, scanString;
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/ast.dart'
+    show ClassDeclarationImpl, CompilationUnitImpl;
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/fasta/ast_builder.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:analyzer/src/generated/parser.dart' as analyzer;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/string_source.dart';
+import 'package:pub_semver/src/version.dart';
+import 'package:test/test.dart';
+
+import 'parser_fasta_listener.dart';
+import 'test_support.dart';
+
+/// Abstract base class for parser tests, which does not make assumptions about
+/// which parser is used.
+abstract class AbstractParserTestCase implements ParserTestHelpers {
+  bool get allowNativeClause;
+
+  set allowNativeClause(bool value);
+
+  /// Set a flag indicating whether the parser should parse instance creation
+  /// expressions that lack either the `new` or `const` keyword.
+  set enableOptionalNewAndConst(bool value);
+
+  /// Set a flag indicating whether the parser is to parse part-of directives
+  /// that specify a URI rather than a library name.
+  set enableUriInPartOf(bool value);
+
+  /// The error listener to which scanner and parser errors will be reported.
+  ///
+  /// This field is typically initialized by invoking [createParser].
+  GatheringErrorListener get listener;
+
+  /// Get the parser used by the test.
+  ///
+  /// Caller must first invoke [createParser].
+  analyzer.Parser get parser;
+
+  /// Assert that the number and codes of errors occurred during parsing is the
+  /// same as the [expectedErrorCodes].
+  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes);
+
+  /// Asserts that no errors occurred during parsing.
+  void assertNoErrors();
+
+  /// Prepares to parse using tokens scanned from the given [content] string.
+  ///
+  /// [expectedEndOffset] is the expected offset of the next token to be parsed
+  /// after the parser has finished parsing,
+  /// or `null` (the default) if EOF is expected.
+  /// In general, the analyzer tests do not assert that the last token is EOF,
+  /// but the fasta parser adapter tests do assert this.
+  /// For any analyzer test where the last token is not EOF, set this value.
+  /// It is ignored when not using the fasta parser.
+  void createParser(
+    String content, {
+    int expectedEndOffset,
+    FeatureSet featureSet,
+  });
+
+  ExpectedError expectedError(ErrorCode code, int offset, int length);
+
+  void expectNotNullIfNoErrors(Object result);
+
+  Expression parseAdditiveExpression(String code);
+
+  Expression parseAssignableExpression(String code, bool primaryAllowed);
+
+  Expression parseAssignableSelector(String code, bool optional,
+      {bool allowConditional = true});
+
+  AwaitExpression parseAwaitExpression(String code);
+
+  Expression parseBitwiseAndExpression(String code);
+
+  Expression parseBitwiseOrExpression(String code);
+
+  Expression parseBitwiseXorExpression(String code);
+
+  Expression parseCascadeSection(String code);
+
+  CommentReference parseCommentReference(
+      String referenceSource, int sourceOffset);
+
+  CompilationUnit parseCompilationUnit(String source,
+      {List<ErrorCode> codes, List<ExpectedError> errors});
+
+  ConditionalExpression parseConditionalExpression(String code);
+
+  Expression parseConstExpression(String code);
+
+  ConstructorInitializer parseConstructorInitializer(String code);
+
+  /// Parse the given source as a compilation unit.
+  ///
+  /// @param source the source to be parsed
+  /// @param errorCodes the error codes of the errors that are expected to be
+  ///          found
+  /// @return the compilation unit that was parsed
+  /// @throws Exception if the source could not be parsed, if the compilation
+  ///           errors in the source do not match those that are expected, or if
+  ///           the result would have been `null`
+  CompilationUnit parseDirectives(String source,
+      [List<ErrorCode> errorCodes = const <ErrorCode>[]]);
+
+  BinaryExpression parseEqualityExpression(String code);
+
+  Expression parseExpression(String source,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      int expectedEndOffset});
+
+  List<Expression> parseExpressionList(String code);
+
+  Expression parseExpressionWithoutCascade(String code);
+
+  FormalParameter parseFormalParameter(String code, ParameterKind kind,
+      {List<ErrorCode> errorCodes = const <ErrorCode>[]});
+
+  FormalParameterList parseFormalParameterList(String code,
+      {bool inFunctionType = false,
+      List<ErrorCode> errorCodes = const <ErrorCode>[],
+      List<ExpectedError> errors});
+
+  /// Parses a single top level member of a compilation unit (other than a
+  /// directive), including any comment and/or metadata that precedes it.
+  CompilationUnitMember parseFullCompilationUnitMember();
+
+  /// Parses a single top level directive, including any comment and/or metadata
+  /// that precedes it.
+  Directive parseFullDirective();
+
+  FunctionExpression parseFunctionExpression(String code);
+
+  InstanceCreationExpression parseInstanceCreationExpression(
+      String code, Token newToken);
+
+  ListLiteral parseListLiteral(
+      Token token, String typeArgumentsCode, String code);
+
+  TypedLiteral parseListOrMapLiteral(Token modifier, String code);
+
+  Expression parseLogicalAndExpression(String code);
+
+  Expression parseLogicalOrExpression(String code);
+
+  SetOrMapLiteral parseMapLiteral(
+      Token token, String typeArgumentsCode, String code);
+
+  MapLiteralEntry parseMapLiteralEntry(String code);
+
+  Expression parseMultiplicativeExpression(String code);
+
+  InstanceCreationExpression parseNewExpression(String code);
+
+  NormalFormalParameter parseNormalFormalParameter(String code,
+      {bool inFunctionType = false,
+      List<ErrorCode> errorCodes = const <ErrorCode>[]});
+
+  Expression parsePostfixExpression(String code);
+
+  Identifier parsePrefixedIdentifier(String code);
+
+  Expression parsePrimaryExpression(String code,
+      {int expectedEndOffset, List<ExpectedError> errors});
+
+  Expression parseRelationalExpression(String code);
+
+  RethrowExpression parseRethrowExpression(String code);
+
+  BinaryExpression parseShiftExpression(String code);
+
+  SimpleIdentifier parseSimpleIdentifier(String code);
+
+  Statement parseStatement(String source, {int expectedEndOffset});
+
+  Expression parseStringLiteral(String code);
+
+  SymbolLiteral parseSymbolLiteral(String code);
+
+  Expression parseThrowExpression(String code);
+
+  Expression parseThrowExpressionWithoutCascade(String code);
+
+  PrefixExpression parseUnaryExpression(String code);
+
+  VariableDeclarationList parseVariableDeclarationList(String source);
+}
+
+/// This class just narrows the type of [parser] to [ParserProxy].
+abstract class AbstractParserViaProxyTestCase
+    implements AbstractParserTestCase {
+  @override
+  ParserProxy get parser;
+}
+
+/// Implementation of [AbstractParserTestCase] specialized for testing the
+/// Fasta parser.
+class FastaParserTestCase
+    with ParserTestHelpers
+    implements AbstractParserTestCase {
+  static final List<ErrorCode> NO_ERROR_COMPARISON = <ErrorCode>[];
+
+  final controlFlow = FeatureSet.latestLanguageVersion();
+
+  final spread = FeatureSet.latestLanguageVersion();
+
+  final nonNullable = FeatureSet.latestLanguageVersion();
+
+  final preNonNullable = FeatureSet.fromEnableFlags2(
+    sdkLanguageVersion: Version.parse('2.9.0'),
+    flags: [],
+  );
+
+  ParserProxy parserProxy;
+
+  Token _fastaTokens;
+
+  @override
+  bool allowNativeClause = false;
+
+  @override
+  set enableOptionalNewAndConst(bool enable) {
+    // ignored
+  }
+
+  @override
+  set enableUriInPartOf(bool value) {
+    if (value == false) {
+      throw UnimplementedError(
+          'URIs in "part of" declarations cannot be disabled in Fasta.');
+    }
+  }
+
+  @override
+  GatheringErrorListener get listener => parserProxy.errorListener;
+
+  @override
+  ParserProxy get parser => parserProxy;
+
+  void assertErrors({List<ErrorCode> codes, List<ExpectedError> errors}) {
+    if (codes != null) {
+      if (!identical(codes, NO_ERROR_COMPARISON)) {
+        assertErrorsWithCodes(codes);
+      }
+    } else if (errors != null) {
+      listener.assertErrors(errors);
+    } else {
+      assertNoErrors();
+    }
+  }
+
+  @override
+  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
+    parserProxy.errorListener.assertErrorsWithCodes(
+        _toFastaGeneratedAnalyzerErrorCodes(expectedErrorCodes));
+  }
+
+  @override
+  void assertNoErrors() {
+    parserProxy.errorListener.assertNoErrors();
+  }
+
+  @override
+  void createParser(String content,
+      {int expectedEndOffset, FeatureSet featureSet}) {
+    featureSet ??= FeatureSet.forTesting();
+    var result = scanString(content,
+        configuration: featureSet.isEnabled(Feature.non_nullable)
+            ? ScannerConfiguration.nonNullable
+            : ScannerConfiguration.classic,
+        includeComments: true);
+    _fastaTokens = result.tokens;
+    parserProxy = ParserProxy(_fastaTokens, featureSet,
+        allowNativeClause: allowNativeClause,
+        expectedEndOffset: expectedEndOffset);
+  }
+
+  @override
+  ExpectedError expectedError(ErrorCode code, int offset, int length) =>
+      ExpectedError(_toFastaGeneratedAnalyzerErrorCode(code), offset, length);
+
+  @override
+  void expectNotNullIfNoErrors(Object result) {
+    if (!listener.hasErrors) {
+      expect(result, isNotNull);
+    }
+  }
+
+  @override
+  Expression parseAdditiveExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  Expression parseArgument(String source) {
+    createParser(source);
+    return parserProxy.parseArgument();
+  }
+
+  @override
+  Expression parseAssignableExpression(String code, bool primaryAllowed) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseAssignableSelector(String code, bool optional,
+      {bool allowConditional = true}) {
+    if (optional) {
+      if (code.isEmpty) {
+        return _parseExpression('foo');
+      }
+      return _parseExpression('(foo)$code');
+    }
+    return _parseExpression('foo$code');
+  }
+
+  @override
+  AwaitExpression parseAwaitExpression(String code) {
+    var function = _parseExpression('() async => $code') as FunctionExpression;
+    return (function.body as ExpressionFunctionBody).expression;
+  }
+
+  @override
+  Expression parseBitwiseAndExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseBitwiseOrExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseBitwiseXorExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseCascadeSection(String code) {
+    var cascadeExpression = _parseExpression('null$code') as CascadeExpression;
+    return cascadeExpression.cascadeSections.first;
+  }
+
+  @override
+  CommentReference parseCommentReference(
+      String referenceSource, int sourceOffset) {
+    String padding = ' '.padLeft(sourceOffset - 4, 'a');
+    String source = '/**$padding[$referenceSource] */ class C { }';
+    CompilationUnit unit = parseCompilationUnit(source);
+    ClassDeclaration clazz = unit.declarations[0];
+    Comment comment = clazz.documentationComment;
+    List<CommentReference> references = comment.references;
+    if (references.isEmpty) {
+      return null;
+    } else {
+      expect(references, hasLength(1));
+      return references[0];
+    }
+  }
+
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      FeatureSet featureSet}) {
+    GatheringErrorListener listener = GatheringErrorListener(checkRanges: true);
+
+    CompilationUnit unit =
+        parseCompilationUnit2(content, listener, featureSet: featureSet);
+
+    // Assert and return result
+    if (codes != null) {
+      listener
+          .assertErrorsWithCodes(_toFastaGeneratedAnalyzerErrorCodes(codes));
+    } else if (errors != null) {
+      listener.assertErrors(errors);
+    } else {
+      listener.assertNoErrors();
+    }
+    return unit;
+  }
+
+  CompilationUnit parseCompilationUnit2(
+      String content, GatheringErrorListener listener,
+      {LanguageVersionToken languageVersion, FeatureSet featureSet}) {
+    featureSet ??= FeatureSet.forTesting();
+    var source = StringSource(content, 'parser_test_StringSource.dart');
+
+    // Adjust the feature set based on language version comment.
+    void languageVersionChanged(
+        fasta.Scanner scanner, LanguageVersionToken languageVersion) {
+      featureSet = featureSet.restrictToVersion(
+          Version(languageVersion.major, languageVersion.minor, 0));
+      scanner.configuration = Scanner.buildConfig(featureSet);
+    }
+
+    // Scan tokens
+    ScannerResult result = scanString(content,
+        includeComments: true,
+        configuration: Scanner.buildConfig(featureSet),
+        languageVersionChanged: languageVersionChanged);
+    _fastaTokens = result.tokens;
+
+    // Run parser
+    ErrorReporter errorReporter = ErrorReporter(
+      listener,
+      source,
+      isNonNullableByDefault: false,
+    );
+    AstBuilder astBuilder =
+        AstBuilder(errorReporter, source.uri, true, featureSet);
+    fasta.Parser parser = fasta.Parser(astBuilder);
+    astBuilder.parser = parser;
+    astBuilder.allowNativeClause = allowNativeClause;
+    parser.parseUnit(_fastaTokens);
+    CompilationUnitImpl unit = astBuilder.pop();
+
+    expect(unit, isNotNull);
+    return unit;
+  }
+
+  @override
+  ConditionalExpression parseConditionalExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseConstExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  ConstructorInitializer parseConstructorInitializer(String code) {
+    createParser('class __Test { __Test() : $code; }');
+    CompilationUnit unit = parserProxy.parseCompilationUnit2();
+    assertNoErrors();
+    var clazz = unit.declarations[0] as ClassDeclaration;
+    var constructor = clazz.members[0] as ConstructorDeclaration;
+    return constructor.initializers.single;
+  }
+
+  @override
+  CompilationUnit parseDirectives(String source,
+      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
+    createParser(source);
+    CompilationUnit unit =
+        parserProxy.parseDirectives(parserProxy.currentToken);
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(0));
+    listener.assertErrorsWithCodes(errorCodes);
+    return unit;
+  }
+
+  @override
+  BinaryExpression parseEqualityExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseExpression(String source,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      int expectedEndOffset,
+      bool inAsync = false,
+      FeatureSet featureSet}) {
+    createParser(source,
+        expectedEndOffset: expectedEndOffset, featureSet: featureSet);
+    if (inAsync) {
+      parserProxy.fastaParser.asyncState = AsyncModifier.Async;
+    }
+    Expression result = parserProxy.parseExpression2();
+    assertErrors(codes: codes, errors: errors);
+    return result;
+  }
+
+  @override
+  List<Expression> parseExpressionList(String code) {
+    return (_parseExpression('[$code]') as ListLiteral)
+        .elements
+        .toList()
+        .cast<Expression>();
+  }
+
+  @override
+  Expression parseExpressionWithoutCascade(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  FormalParameter parseFormalParameter(String code, ParameterKind kind,
+      {List<ErrorCode> errorCodes = const <ErrorCode>[],
+      FeatureSet featureSet}) {
+    String parametersCode;
+    if (kind == ParameterKind.REQUIRED) {
+      parametersCode = '($code)';
+    } else if (kind == ParameterKind.POSITIONAL) {
+      parametersCode = '([$code])';
+    } else if (kind == ParameterKind.NAMED) {
+      parametersCode = '({$code})';
+    } else {
+      fail('$kind');
+    }
+    FormalParameterList list = parseFormalParameterList(parametersCode,
+        inFunctionType: false, errorCodes: errorCodes, featureSet: featureSet);
+    return list.parameters.single;
+  }
+
+  @override
+  FormalParameterList parseFormalParameterList(String code,
+      {bool inFunctionType = false,
+      List<ErrorCode> errorCodes = const <ErrorCode>[],
+      List<ExpectedError> errors,
+      FeatureSet featureSet}) {
+    createParser(code, featureSet: featureSet);
+    FormalParameterList result =
+        parserProxy.parseFormalParameterList(inFunctionType: inFunctionType);
+    assertErrors(codes: errors != null ? null : errorCodes, errors: errors);
+    return result;
+  }
+
+  @override
+  CompilationUnitMember parseFullCompilationUnitMember() {
+    return parserProxy.parseTopLevelDeclaration(false);
+  }
+
+  @override
+  Directive parseFullDirective() {
+    return parserProxy.parseTopLevelDeclaration(true);
+  }
+
+  @override
+  FunctionExpression parseFunctionExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  InstanceCreationExpression parseInstanceCreationExpression(
+      String code, Token newToken) {
+    return _parseExpression('$newToken $code');
+  }
+
+  @override
+  ListLiteral parseListLiteral(
+      Token token, String typeArgumentsCode, String code) {
+    String sc = '';
+    if (token != null) {
+      sc += token.lexeme + ' ';
+    }
+    if (typeArgumentsCode != null) {
+      sc += typeArgumentsCode;
+    }
+    sc += code;
+    return _parseExpression(sc);
+  }
+
+  @override
+  TypedLiteral parseListOrMapLiteral(Token modifier, String code) {
+    String literalCode = modifier != null ? '$modifier $code' : code;
+    return parsePrimaryExpression(literalCode) as TypedLiteral;
+  }
+
+  @override
+  Expression parseLogicalAndExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseLogicalOrExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  SetOrMapLiteral parseMapLiteral(
+      Token token, String typeArgumentsCode, String code) {
+    String sc = '';
+    if (token != null) {
+      sc += token.lexeme + ' ';
+    }
+    if (typeArgumentsCode != null) {
+      sc += typeArgumentsCode;
+    }
+    sc += code;
+    return parsePrimaryExpression(sc) as SetOrMapLiteral;
+  }
+
+  @override
+  MapLiteralEntry parseMapLiteralEntry(String code) {
+    var mapLiteral = parseMapLiteral(null, null, '{ $code }');
+    return mapLiteral.elements.single;
+  }
+
+  @override
+  Expression parseMultiplicativeExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  InstanceCreationExpression parseNewExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  NormalFormalParameter parseNormalFormalParameter(String code,
+      {bool inFunctionType = false,
+      List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
+    FormalParameterList list = parseFormalParameterList('($code)',
+        inFunctionType: inFunctionType, errorCodes: errorCodes);
+    return list.parameters.single;
+  }
+
+  @override
+  Expression parsePostfixExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Identifier parsePrefixedIdentifier(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parsePrimaryExpression(String code,
+      {int expectedEndOffset, List<ExpectedError> errors}) {
+    createParser(code, expectedEndOffset: expectedEndOffset);
+    Expression result = parserProxy.parsePrimaryExpression();
+    assertErrors(codes: null, errors: errors);
+    return result;
+  }
+
+  @override
+  Expression parseRelationalExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  RethrowExpression parseRethrowExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  BinaryExpression parseShiftExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  SimpleIdentifier parseSimpleIdentifier(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Statement parseStatement(String source,
+      {int expectedEndOffset, FeatureSet featureSet, bool inAsync = false}) {
+    createParser(source,
+        expectedEndOffset: expectedEndOffset, featureSet: featureSet);
+    if (inAsync) {
+      parserProxy.fastaParser.asyncState = AsyncModifier.Async;
+    }
+    Statement statement = parserProxy.parseStatement2();
+    assertErrors(codes: NO_ERROR_COMPARISON);
+    return statement;
+  }
+
+  @override
+  Expression parseStringLiteral(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  SymbolLiteral parseSymbolLiteral(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseThrowExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  Expression parseThrowExpressionWithoutCascade(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  PrefixExpression parseUnaryExpression(String code) {
+    return _parseExpression(code);
+  }
+
+  @override
+  VariableDeclarationList parseVariableDeclarationList(String code) {
+    var statement = parseStatement('$code;') as VariableDeclarationStatement;
+    return statement.variables;
+  }
+
+  Expression _parseExpression(String code) {
+    var statement = parseStatement('$code;') as ExpressionStatement;
+    return statement.expression;
+  }
+
+  ErrorCode _toFastaGeneratedAnalyzerErrorCode(ErrorCode code) {
+    if (code == ParserErrorCode.ABSTRACT_ENUM ||
+        code == ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION ||
+        code == ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE ||
+        code == ParserErrorCode.ABSTRACT_TYPEDEF ||
+        code == ParserErrorCode.CONST_ENUM ||
+        code == ParserErrorCode.CONST_TYPEDEF ||
+        code == ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION ||
+        code == ParserErrorCode.FINAL_CLASS ||
+        code == ParserErrorCode.FINAL_ENUM ||
+        code == ParserErrorCode.FINAL_TYPEDEF ||
+        code == ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION) {
+      return ParserErrorCode.EXTRANEOUS_MODIFIER;
+    }
+    return code;
+  }
+
+  List<ErrorCode> _toFastaGeneratedAnalyzerErrorCodes(
+          List<ErrorCode> expectedErrorCodes) =>
+      expectedErrorCodes.map(_toFastaGeneratedAnalyzerErrorCode).toList();
+}
+
+/// Proxy implementation of the analyzer parser, implemented in terms of the
+/// Fasta parser.
+///
+/// This allows many of the analyzer parser tests to be run on Fasta, even if
+/// they call into the analyzer parser class directly.
+class ParserProxy extends analyzer.Parser {
+  /// The error listener to which scanner and parser errors will be reported.
+  final GatheringErrorListener errorListener;
+
+  ForwardingTestListener _eventListener;
+
+  final int expectedEndOffset;
+
+  /// Creates a [ParserProxy] which is prepared to begin parsing at the given
+  /// Fasta token.
+  factory ParserProxy(Token firstToken, FeatureSet featureSet,
+      {bool allowNativeClause = false, int expectedEndOffset}) {
+    TestSource source = TestSource();
+    var errorListener = GatheringErrorListener(checkRanges: true);
+    return ParserProxy._(firstToken, source, errorListener, featureSet,
+        allowNativeClause: allowNativeClause,
+        expectedEndOffset: expectedEndOffset);
+  }
+
+  ParserProxy._(Token firstToken, Source source, this.errorListener,
+      FeatureSet featureSet,
+      {bool allowNativeClause = false, this.expectedEndOffset})
+      : super(source, errorListener,
+            featureSet: featureSet, allowNativeClause: allowNativeClause) {
+    _eventListener = ForwardingTestListener(astBuilder);
+    fastaParser.listener = _eventListener;
+    currentToken = firstToken;
+  }
+
+  @override
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+  Annotation parseAnnotation() {
+    return _run('MetadataStar', () {
+      currentToken = fastaParser
+          .parseMetadata(fastaParser.syntheticPreviousToken(currentToken))
+          .next;
+      return astBuilder.pop() as Annotation;
+    });
+  }
+
+  ArgumentList parseArgumentList() {
+    return _run('unspecified', () {
+      currentToken = fastaParser
+          .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
+          .next;
+      var result = astBuilder.pop();
+      return result is MethodInvocation
+          ? result.argumentList
+          : result as ArgumentList;
+    });
+  }
+
+  ClassMember parseClassMember(String className) {
+    return _run('ClassOrMixinBody', () {
+      astBuilder.classDeclaration = astFactory.classDeclaration(
+        null,
+        null,
+        null,
+        Token(Keyword.CLASS, 0),
+        astFactory.simpleIdentifier(
+            fasta.StringToken.fromString(TokenType.IDENTIFIER, className, 6)),
+        null,
+        null,
+        null,
+        null,
+        null /* leftBracket */,
+        <ClassMember>[],
+        null /* rightBracket */,
+      ) as ClassDeclarationImpl;
+      // TODO(danrubel): disambiguate between class and mixin
+      currentToken = fastaParser.parseClassMember(currentToken, className);
+      //currentToken = fastaParser.parseMixinMember(currentToken);
+      ClassDeclaration declaration = astBuilder.classDeclaration;
+      astBuilder.classDeclaration = null;
+      return declaration.members.isNotEmpty ? declaration.members[0] : null;
+    });
+  }
+
+  List<Combinator> parseCombinators() {
+    return _run('Import', () {
+      currentToken = fastaParser
+          .parseCombinatorStar(fastaParser.syntheticPreviousToken(currentToken))
+          .next;
+      return astBuilder.pop() as List<Combinator>;
+    });
+  }
+
+  List<CommentReference> parseCommentReferences(
+      List<DocumentationCommentToken> tokens) {
+    for (int index = 0; index < tokens.length - 1; ++index) {
+      Token next = tokens[index].next;
+      if (next == null) {
+        tokens[index].setNext(tokens[index + 1]);
+      } else {
+        expect(next, tokens[index + 1]);
+      }
+    }
+    expect(tokens[tokens.length - 1].next, isNull);
+    List<CommentReference> references =
+        astBuilder.parseCommentReferences(tokens.first);
+    if (astBuilder.stack.isNotEmpty) {
+      throw 'Expected empty stack, but found:'
+          '\n  ${astBuilder.stack.values.join('\n  ')}';
+    }
+    return references;
+  }
+
+  @override
+  CompilationUnit parseCompilationUnit2() {
+    var result = super.parseCompilationUnit2();
+    expect(currentToken.isEof, isTrue, reason: currentToken.lexeme);
+    expect(astBuilder.stack, hasLength(0));
+    _eventListener.expectEmpty();
+    return result;
+  }
+
+  @override
+  Configuration parseConfiguration() {
+    return _run('ConditionalUris', () => super.parseConfiguration());
+  }
+
+  @override
+  DottedName parseDottedName() {
+    return _run('unspecified', () => super.parseDottedName());
+  }
+
+  @override
+  Expression parseExpression2() {
+    return _run('unspecified', () => super.parseExpression2());
+  }
+
+  @override
+  FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
+    return _run('unspecified',
+        () => super.parseFormalParameterList(inFunctionType: inFunctionType));
+  }
+
+  @override
+  FunctionBody parseFunctionBody(
+      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
+    Token lastToken;
+    FunctionBody body = _run('unspecified', () {
+      FunctionBody body =
+          super.parseFunctionBody(mayBeEmpty, emptyErrorCode, inExpression);
+      lastToken = currentToken;
+      currentToken = currentToken.next;
+      return body;
+    });
+    if (!inExpression) {
+      if (![';', '}'].contains(lastToken.lexeme)) {
+        fail('Expected ";" or "}", but found: ${lastToken.lexeme}');
+      }
+    }
+    return body;
+  }
+
+  @override
+  Expression parsePrimaryExpression() {
+    return _run('unspecified', () => super.parsePrimaryExpression());
+  }
+
+  @override
+  Statement parseStatement(Token token) {
+    return _run('unspecified', () => super.parseStatement(token));
+  }
+
+  @override
+  Statement parseStatement2() {
+    return _run('unspecified', () => super.parseStatement2());
+  }
+
+  @override
+  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
+    return _run(
+        'CompilationUnit', () => super.parseTopLevelDeclaration(isDirective));
+  }
+
+  @override
+  TypeAnnotation parseTypeAnnotation(bool inExpression) {
+    return _run('unspecified', () => super.parseTypeAnnotation(inExpression));
+  }
+
+  @override
+  TypeArgumentList parseTypeArgumentList() {
+    return _run('unspecified', () => super.parseTypeArgumentList());
+  }
+
+  @override
+  TypeName parseTypeName(bool inExpression) {
+    return _run('unspecified', () => super.parseTypeName(inExpression));
+  }
+
+  @override
+  TypeParameter parseTypeParameter() {
+    return _run('unspecified', () => super.parseTypeParameter());
+  }
+
+  @override
+  TypeParameterList parseTypeParameterList() {
+    return _run('unspecified', () => super.parseTypeParameterList());
+  }
+
+  /// Runs the specified function and returns the result. It checks the
+  /// enclosing listener events, that the parse consumed all of the tokens, and
+  /// that the result stack is empty.
+  _run(String enclosingEvent, Function() f) {
+    _eventListener.begin(enclosingEvent);
+
+    // Simulate error handling of parseUnit by skipping error tokens
+    // before parsing and reporting them after parsing is complete.
+    Token errorToken = currentToken;
+    currentToken = fastaParser.skipErrorTokens(currentToken);
+    var result = f();
+    fastaParser.reportAllErrorTokens(errorToken);
+
+    _eventListener.end(enclosingEvent);
+
+    String lexeme = currentToken is ErrorToken
+        ? currentToken.runtimeType.toString()
+        : currentToken.lexeme;
+    if (expectedEndOffset == null) {
+      expect(currentToken.isEof, isTrue, reason: lexeme);
+    } else {
+      expect(currentToken.offset, expectedEndOffset, reason: lexeme);
+    }
+    expect(astBuilder.stack, hasLength(0));
+    expect(astBuilder.directives, hasLength(0));
+    expect(astBuilder.declarations, hasLength(0));
+    return result;
+  }
+}
+
+/// Implementation of [AbstractParserTestCase] specialized for testing the
+/// analyzer parser.
+class ParserTestCase with ParserTestHelpers implements AbstractParserTestCase {
+  /// A flag indicating whether parser is to parse function bodies.
+  static bool parseFunctionBodies = true;
+
+  @override
+  bool allowNativeClause = true;
+
+  /// A flag indicating whether parser is to parse async.
+  bool parseAsync = true;
+
+  /// A flag indicating whether the parser should parse instance creation
+  /// expressions that lack either the `new` or `const` keyword.
+  bool enableOptionalNewAndConst = false;
+
+  /// A flag indicating whether the parser should parse mixin declarations.
+  /// https://github.com/dart-lang/language/issues/12
+  bool isMixinSupportEnabled = false;
+
+  /// A flag indicating whether the parser is to parse part-of directives that
+  /// specify a URI rather than a library name.
+  bool enableUriInPartOf = false;
+
+  @override
+  GatheringErrorListener listener;
+
+  /// The parser used by the test.
+  ///
+  /// This field is typically initialized by invoking [createParser].
+  @override
+  analyzer.Parser parser;
+
+  @override
+  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
+    listener.assertErrorsWithCodes(expectedErrorCodes);
+  }
+
+  @override
+  void assertNoErrors() {
+    listener.assertNoErrors();
+  }
+
+  /// Create the [parser] and [listener] used by a test. The [parser] will be
+  /// prepared to parse the tokens scanned from the given [content].
+  @override
+  void createParser(
+    String content, {
+    int expectedEndOffset,
+    LanguageVersionToken languageVersion,
+    FeatureSet featureSet,
+  }) {
+    featureSet ??= FeatureSet.latestLanguageVersion();
+    Source source = TestSource();
+    listener = GatheringErrorListener();
+
+    fasta.ScannerResult result =
+        fasta.scanString(content, includeComments: true);
+    listener.setLineInfo(source, result.lineStarts);
+
+    parser = analyzer.Parser(
+      source,
+      listener,
+      featureSet: featureSet,
+    );
+    parser.allowNativeClause = allowNativeClause;
+    parser.parseFunctionBodies = parseFunctionBodies;
+    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
+    parser.currentToken = result.tokens;
+  }
+
+  @override
+  ExpectedError expectedError(ErrorCode code, int offset, int length) =>
+      ExpectedError(code, offset, length);
+
+  @override
+  void expectNotNullIfNoErrors(Object result) {
+    if (!listener.hasErrors) {
+      expect(result, isNotNull);
+    }
+  }
+
+  @override
+  Expression parseAdditiveExpression(String code) {
+    createParser(code);
+    return parser.parseAdditiveExpression();
+  }
+
+  @override
+  Expression parseAssignableExpression(String code, bool primaryAllowed) {
+    createParser(code);
+    return parser.parseAssignableExpression(primaryAllowed);
+  }
+
+  @override
+  Expression parseAssignableSelector(String code, bool optional,
+      {bool allowConditional = true}) {
+    if (optional) {
+      if (code.isEmpty) {
+        createParser('foo');
+      } else {
+        createParser('(foo)$code');
+      }
+    } else {
+      createParser('foo$code');
+    }
+    return parser.parseExpression2();
+  }
+
+  @override
+  AwaitExpression parseAwaitExpression(String code) {
+    createParser('() async => $code');
+    var function = parser.parseExpression2() as FunctionExpression;
+    return (function.body as ExpressionFunctionBody).expression;
+  }
+
+  @override
+  Expression parseBitwiseAndExpression(String code) {
+    createParser(code);
+    return parser.parseBitwiseAndExpression();
+  }
+
+  @override
+  Expression parseBitwiseOrExpression(String code) {
+    createParser(code);
+    return parser.parseBitwiseOrExpression();
+  }
+
+  @override
+  Expression parseBitwiseXorExpression(String code) {
+    createParser(code);
+    return parser.parseBitwiseXorExpression();
+  }
+
+  @override
+  Expression parseCascadeSection(String code) {
+    var statement = parseStatement('null$code;') as ExpressionStatement;
+    var cascadeExpression = statement.expression as CascadeExpression;
+    return cascadeExpression.cascadeSections.first;
+  }
+
+  @override
+  CommentReference parseCommentReference(
+      String referenceSource, int sourceOffset) {
+    String padding = ' '.padLeft(sourceOffset - 4, 'a');
+    String source = '/**$padding[$referenceSource] */ class C { }';
+    CompilationUnit unit = parseCompilationUnit(source);
+    ClassDeclaration clazz = unit.declarations[0];
+    Comment comment = clazz.documentationComment;
+    List<CommentReference> references = comment.references;
+    if (references.isEmpty) {
+      return null;
+    } else {
+      expect(references, hasLength(1));
+      return references[0];
+    }
+  }
+
+  /// Parse the given source as a compilation unit.
+  ///
+  /// @param source the source to be parsed
+  /// @param errorCodes the error codes of the errors that are expected to be
+  ///          found
+  /// @return the compilation unit that was parsed
+  /// @throws Exception if the source could not be parsed, if the compilation
+  ///           errors in the source do not match those that are expected, or if
+  ///           the result would have been `null`
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+      {List<ErrorCode> codes, List<ExpectedError> errors}) {
+    Source source = TestSource();
+    GatheringErrorListener listener = GatheringErrorListener();
+
+    fasta.ScannerResult result =
+        fasta.scanString(content, includeComments: true);
+    listener.setLineInfo(source, result.lineStarts);
+
+    analyzer.Parser parser = analyzer.Parser(
+      source,
+      listener,
+      featureSet: FeatureSet.forTesting(),
+    );
+    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
+    CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
+    expect(unit, isNotNull);
+    if (codes != null) {
+      listener.assertErrorsWithCodes(codes);
+    } else if (errors != null) {
+      listener.assertErrors(errors);
+    } else {
+      listener.assertNoErrors();
+    }
+    return unit;
+  }
+
+  /// Parse the given [content] as a compilation unit.
+  CompilationUnit parseCompilationUnit2(String content,
+      {AnalysisErrorListener listener}) {
+    Source source = NonExistingSource.unknown;
+    listener ??= AnalysisErrorListener.NULL_LISTENER;
+
+    fasta.ScannerResult result =
+        fasta.scanString(content, includeComments: true);
+
+    analyzer.Parser parser = analyzer.Parser(
+      source,
+      listener,
+      featureSet: FeatureSet.forTesting(),
+    );
+    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
+    CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
+    unit.lineInfo = LineInfo(result.lineStarts);
+    return unit;
+  }
+
+  @override
+  ConditionalExpression parseConditionalExpression(String code) {
+    createParser(code);
+    return parser.parseConditionalExpression();
+  }
+
+  @override
+  Expression parseConstExpression(String code) {
+    createParser(code);
+    return parser.parseConstExpression();
+  }
+
+  @override
+  ConstructorInitializer parseConstructorInitializer(String code) {
+    createParser('class __Test { __Test() : $code; }');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    var clazz = unit.declarations[0] as ClassDeclaration;
+    var constructor = clazz.members[0] as ConstructorDeclaration;
+    return constructor.initializers.single;
+  }
+
+  @override
+  CompilationUnit parseDirectives(String source,
+      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
+    createParser(source);
+    CompilationUnit unit = parser.parseDirectives2();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(0));
+    listener.assertErrorsWithCodes(errorCodes);
+    return unit;
+  }
+
+  @override
+  BinaryExpression parseEqualityExpression(String code) {
+    createParser(code);
+    return parser.parseEqualityExpression();
+  }
+
+  /// Parse the given [source] as an expression. If a list of error [codes] is
+  /// provided, then assert that the produced errors matches the list.
+  /// Otherwise, if a list of [errors] is provided, the assert that the produced
+  /// errors matches the list. Otherwise, assert that there are no errors.
+  @override
+  Expression parseExpression(String source,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      int expectedEndOffset}) {
+    createParser(source, expectedEndOffset: expectedEndOffset);
+    Expression expression = parser.parseExpression2();
+    expectNotNullIfNoErrors(expression);
+    if (codes != null) {
+      listener.assertErrorsWithCodes(codes);
+    } else if (errors != null) {
+      listener.assertErrors(errors);
+    } else {
+      assertNoErrors();
+    }
+    return expression;
+  }
+
+  @override
+  List<Expression> parseExpressionList(String code) {
+    createParser('[$code]');
+    return (parser.parseExpression2() as ListLiteral)
+        .elements
+        .toList()
+        .cast<Expression>();
+  }
+
+  @override
+  Expression parseExpressionWithoutCascade(String code) {
+    createParser(code);
+    return parser.parseExpressionWithoutCascade();
+  }
+
+  @override
+  FormalParameter parseFormalParameter(String code, ParameterKind kind,
+      {List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
+    String parametersCode;
+    if (kind == ParameterKind.REQUIRED) {
+      parametersCode = '($code)';
+    } else if (kind == ParameterKind.POSITIONAL) {
+      parametersCode = '([$code])';
+    } else if (kind == ParameterKind.NAMED) {
+      parametersCode = '({$code})';
+    } else {
+      fail('$kind');
+    }
+    FormalParameterList list = parseFormalParameterList(parametersCode,
+        inFunctionType: false, errorCodes: errorCodes);
+    return list.parameters.single;
+  }
+
+  @override
+  FormalParameterList parseFormalParameterList(String code,
+      {bool inFunctionType = false,
+      List<ErrorCode> errorCodes = const <ErrorCode>[],
+      List<ExpectedError> errors}) {
+    createParser(code);
+    FormalParameterList list =
+        parser.parseFormalParameterList(inFunctionType: inFunctionType);
+    if (errors != null) {
+      errorCodes = errors.map((e) => e.code).toList();
+    }
+    assertErrorsWithCodes(errorCodes);
+    return list;
+  }
+
+  /// Parses a single top level member of a compilation unit (other than a
+  /// directive), including any comment and/or metadata that precedes it.
+  @override
+  CompilationUnitMember parseFullCompilationUnitMember() =>
+      parser.parseCompilationUnit2().declarations.first;
+
+  @override
+  Directive parseFullDirective() {
+    return parser.parseTopLevelDeclaration(true);
+  }
+
+  @override
+  FunctionExpression parseFunctionExpression(String code) {
+    createParser(code);
+    return parser.parseFunctionExpression();
+  }
+
+  @override
+  InstanceCreationExpression parseInstanceCreationExpression(
+      String code, Token newToken) {
+    createParser('$newToken $code');
+    return parser.parseExpression2();
+  }
+
+  @override
+  ListLiteral parseListLiteral(
+      Token token, String typeArgumentsCode, String code) {
+    String sc = '';
+    if (token != null) {
+      sc += token.lexeme + ' ';
+    }
+    if (typeArgumentsCode != null) {
+      sc += typeArgumentsCode;
+    }
+    sc += code;
+    createParser(sc);
+    return parser.parseExpression2();
+  }
+
+  @override
+  TypedLiteral parseListOrMapLiteral(Token modifier, String code) {
+    String literalCode = modifier != null ? '$modifier $code' : code;
+    createParser(literalCode);
+    return parser.parseExpression2() as TypedLiteral;
+  }
+
+  @override
+  Expression parseLogicalAndExpression(String code) {
+    createParser(code);
+    return parser.parseLogicalAndExpression();
+  }
+
+  @override
+  Expression parseLogicalOrExpression(String code) {
+    createParser(code);
+    return parser.parseLogicalOrExpression();
+  }
+
+  @override
+  SetOrMapLiteral parseMapLiteral(
+      Token token, String typeArgumentsCode, String code) {
+    String sc = '';
+    if (token != null) {
+      sc += token.lexeme + ' ';
+    }
+    if (typeArgumentsCode != null) {
+      sc += typeArgumentsCode;
+    }
+    sc += code;
+    createParser(sc);
+    return parser.parseExpression2() as SetOrMapLiteral;
+  }
+
+  @override
+  MapLiteralEntry parseMapLiteralEntry(String code) {
+    var mapLiteral = parseMapLiteral(null, null, '{ $code }');
+    return mapLiteral.elements.single;
+  }
+
+  @override
+  Expression parseMultiplicativeExpression(String code) {
+    createParser(code);
+    return parser.parseMultiplicativeExpression();
+  }
+
+  @override
+  InstanceCreationExpression parseNewExpression(String code) {
+    createParser(code);
+    return parser.parseNewExpression();
+  }
+
+  @override
+  NormalFormalParameter parseNormalFormalParameter(String code,
+      {bool inFunctionType = false,
+      List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
+    FormalParameterList list = parseFormalParameterList('($code)',
+        inFunctionType: inFunctionType, errorCodes: errorCodes);
+    return list.parameters.single;
+  }
+
+  @override
+  Expression parsePostfixExpression(String code) {
+    createParser(code);
+    return parser.parsePostfixExpression();
+  }
+
+  @override
+  Identifier parsePrefixedIdentifier(String code) {
+    createParser(code);
+    return parser.parsePrefixedIdentifier();
+  }
+
+  @override
+  Expression parsePrimaryExpression(String code,
+      {int expectedEndOffset, List<ExpectedError> errors}) {
+    createParser(code);
+    var expression = parser.parsePrimaryExpression();
+    if (errors != null) {
+      listener.assertErrors(errors);
+    }
+    return expression;
+  }
+
+  @override
+  Expression parseRelationalExpression(String code) {
+    createParser(code);
+    return parser.parseRelationalExpression();
+  }
+
+  @override
+  RethrowExpression parseRethrowExpression(String code) {
+    createParser(code);
+    return parser.parseRethrowExpression();
+  }
+
+  @override
+  BinaryExpression parseShiftExpression(String code) {
+    createParser(code);
+    return parser.parseShiftExpression();
+  }
+
+  @override
+  SimpleIdentifier parseSimpleIdentifier(String code) {
+    createParser(code);
+    return parser.parseSimpleIdentifier();
+  }
+
+  /// Parse the given [content] as a statement. If
+  /// [enableLazyAssignmentOperators] is `true`, then lazy assignment operators
+  /// should be enabled.
+  @override
+  Statement parseStatement(String content, {int expectedEndOffset}) {
+    Source source = TestSource();
+    listener = GatheringErrorListener();
+
+    fasta.ScannerResult result =
+        fasta.scanString(content, includeComments: true);
+    listener.setLineInfo(source, result.lineStarts);
+
+    analyzer.Parser parser = analyzer.Parser(
+      source,
+      listener,
+      featureSet: FeatureSet.forTesting(),
+    );
+    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
+    Statement statement = parser.parseStatement(result.tokens);
+    expect(statement, isNotNull);
+    return statement;
+  }
+
+  @override
+  Expression parseStringLiteral(String code) {
+    createParser(code);
+    return parser.parseStringLiteral();
+  }
+
+  @override
+  SymbolLiteral parseSymbolLiteral(String code) {
+    createParser(code);
+    return parser.parseSymbolLiteral();
+  }
+
+  @override
+  Expression parseThrowExpression(String code) {
+    createParser(code);
+    return parser.parseThrowExpression();
+  }
+
+  @override
+  Expression parseThrowExpressionWithoutCascade(String code) {
+    createParser(code);
+    return parser.parseThrowExpressionWithoutCascade();
+  }
+
+  @override
+  PrefixExpression parseUnaryExpression(String code) {
+    createParser(code);
+    return parser.parseUnaryExpression();
+  }
+
+  @override
+  VariableDeclarationList parseVariableDeclarationList(String code) {
+    var statement = parseStatement('$code;') as VariableDeclarationStatement;
+    return statement.variables;
+  }
+
+  void setUp() {
+    parseFunctionBodies = true;
+  }
+}
+
+/// Helper methods that aid in parser tests.
+///
+/// Intended to be mixed in to parser test case classes.
+mixin ParserTestHelpers {
+  void expectCommentText(Comment comment, String expectedText) {
+    expect(comment.beginToken, same(comment.endToken));
+    expect(comment.beginToken.lexeme, expectedText);
+  }
+
+  void expectDottedName(DottedName name, List<String> expectedComponents) {
+    int count = expectedComponents.length;
+    NodeList<SimpleIdentifier> components = name.components;
+    expect(components, hasLength(count));
+    for (int i = 0; i < count; i++) {
+      SimpleIdentifier component = components[i];
+      expect(component, isNotNull);
+      expect(component.name, expectedComponents[i]);
+    }
+  }
+}
diff --git a/pkg/analyzer/test/generated/recovery_parser_test.dart b/pkg/analyzer/test/generated/recovery_parser_test.dart
new file mode 100644
index 0000000..b578737
--- /dev/null
+++ b/pkg/analyzer/test/generated/recovery_parser_test.dart
@@ -0,0 +1,1518 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RecoveryParserTest);
+  });
+}
+
+/// The class `RecoveryParserTest` defines parser tests that test the parsing of
+/// invalid code sequences to ensure that the correct recovery steps are taken
+/// in the parser.
+@reflectiveTest
+class RecoveryParserTest extends FastaParserTestCase {
+  void test_additiveExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("+ y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_additiveExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("+", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_additiveExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x +", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_additiveExpression_missing_RHS_super() {
+    BinaryExpression expression =
+        parseExpression("super +", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_additiveExpression_precedence_multiplicative_left() {
+    BinaryExpression expression = parseExpression("* +", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_additiveExpression_precedence_multiplicative_right() {
+    BinaryExpression expression = parseExpression("+ *", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_additiveExpression_super() {
+    BinaryExpression expression = parseExpression("super + +", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_assignableSelector() {
+    IndexExpression expression =
+        parseExpression("a.b[]", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    Expression index = expression.index;
+    expect(index, isSimpleIdentifier);
+    expect(index.isSynthetic, isTrue);
+  }
+
+  void test_assignmentExpression_missing_compound1() {
+    AssignmentExpression expression =
+        parseExpression("= y = 0", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    Expression syntheticExpression = expression.leftHandSide;
+    expect(syntheticExpression, isSimpleIdentifier);
+    expect(syntheticExpression.isSynthetic, isTrue);
+  }
+
+  void test_assignmentExpression_missing_compound2() {
+    AssignmentExpression expression =
+        parseExpression("x = = 0", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    Expression syntheticExpression =
+        (expression.rightHandSide as AssignmentExpression).leftHandSide;
+    expect(syntheticExpression, isSimpleIdentifier);
+    expect(syntheticExpression.isSynthetic, isTrue);
+  }
+
+  void test_assignmentExpression_missing_compound3() {
+    AssignmentExpression expression =
+        parseExpression("x = y =", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    Expression syntheticExpression =
+        (expression.rightHandSide as AssignmentExpression).rightHandSide;
+    expect(syntheticExpression, isSimpleIdentifier);
+    expect(syntheticExpression.isSynthetic, isTrue);
+  }
+
+  void test_assignmentExpression_missing_LHS() {
+    AssignmentExpression expression =
+        parseExpression("= 0", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftHandSide, isSimpleIdentifier);
+    expect(expression.leftHandSide.isSynthetic, isTrue);
+  }
+
+  void test_assignmentExpression_missing_RHS() {
+    AssignmentExpression expression =
+        parseExpression("x =", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftHandSide, isSimpleIdentifier);
+    expect(expression.rightHandSide.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseAndExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("& y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseAndExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("&", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseAndExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x &", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseAndExpression_missing_RHS_super() {
+    BinaryExpression expression =
+        parseExpression("super &", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseAndExpression_precedence_equality_left() {
+    BinaryExpression expression = parseExpression("== &&", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseAndExpression_precedence_equality_right() {
+    BinaryExpression expression = parseExpression("&& ==", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseAndExpression_super() {
+    BinaryExpression expression = parseExpression("super &  &", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseOrExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("| y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseOrExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("|", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseOrExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x |", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseOrExpression_missing_RHS_super() {
+    BinaryExpression expression =
+        parseExpression("super |", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseOrExpression_precedence_xor_left() {
+    BinaryExpression expression = parseExpression("^ |", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseOrExpression_precedence_xor_right() {
+    BinaryExpression expression = parseExpression("| ^", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseOrExpression_super() {
+    BinaryExpression expression = parseExpression("super |  |", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseXorExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("^ y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseXorExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("^", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseXorExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x ^", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseXorExpression_missing_RHS_super() {
+    BinaryExpression expression =
+        parseExpression("super ^", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_bitwiseXorExpression_precedence_and_left() {
+    BinaryExpression expression = parseExpression("& ^", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseXorExpression_precedence_and_right() {
+    BinaryExpression expression = parseExpression("^ &", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_bitwiseXorExpression_super() {
+    BinaryExpression expression = parseExpression("super ^  ^", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_classTypeAlias_withBody() {
+    parseCompilationUnit(r'''
+class A {}
+class B = Object with A {}''', codes:
+// TODO(danrubel): Consolidate and improve error message.
+            [
+      ParserErrorCode.EXPECTED_EXECUTABLE,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+  }
+
+  void test_combinator_badIdentifier() {
+    createParser('import "/testB.dart" show @');
+    parser.parseCompilationUnit2();
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 0),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 27, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 27, 0)
+    ]);
+  }
+
+  void test_combinator_missingIdentifier() {
+    createParser('import "/testB.dart" show ;');
+    parser.parseCompilationUnit2();
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 26, 1)]);
+  }
+
+  void test_conditionalExpression_missingElse() {
+    Expression expression =
+        parseExpression('x ? y :', codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expectNotNullIfNoErrors(expression);
+    expect(expression, isConditionalExpression);
+    ConditionalExpression conditionalExpression = expression;
+    expect(conditionalExpression.elseExpression, isSimpleIdentifier);
+    expect(conditionalExpression.elseExpression.isSynthetic, isTrue);
+  }
+
+  void test_conditionalExpression_missingThen() {
+    Expression expression =
+        parseExpression('x ? : z', codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expectNotNullIfNoErrors(expression);
+    expect(expression, isConditionalExpression);
+    ConditionalExpression conditionalExpression = expression;
+    expect(conditionalExpression.thenExpression, isSimpleIdentifier);
+    expect(conditionalExpression.thenExpression.isSynthetic, isTrue);
+  }
+
+  void test_conditionalExpression_super() {
+    parseExpression('x ? super : z', errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 4, 5)
+    ]);
+  }
+
+  void test_conditionalExpression_super2() {
+    parseExpression('x ? z : super', errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 8, 5)
+    ]);
+  }
+
+  void test_declarationBeforeDirective() {
+    CompilationUnit unit = parseCompilationUnit(
+        "class foo { } import 'bar.dart';",
+        codes: [ParserErrorCode.DIRECTIVE_AFTER_DECLARATION]);
+    expect(unit.directives, hasLength(1));
+    expect(unit.declarations, hasLength(1));
+    ClassDeclaration classDecl = unit.childEntities.first;
+    expect(classDecl, isNotNull);
+    expect(classDecl.name.name, 'foo');
+  }
+
+  void test_equalityExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("== y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_equalityExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("==", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_equalityExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x ==", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_equalityExpression_missing_RHS_super() {
+    BinaryExpression expression = parseExpression("super ==",
+        codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_equalityExpression_precedence_relational_right() {
+    parseExpression("== is", codes: [
+      ParserErrorCode.EXPECTED_TYPE_NAME,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+  }
+
+  void test_equalityExpression_super() {
+    BinaryExpression expression = parseExpression("super ==  ==", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_equalityExpression_superRHS() {
+    parseExpression("1 == super", errors: [
+      expectedError(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 5, 5)
+    ]);
+  }
+
+  void test_expressionList_multiple_end() {
+    List<Expression> result = parseExpressionList(', 2, 3, 4');
+    expectNotNullIfNoErrors(result);
+// TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.MISSING_IDENTIFIER]);
+//    listener.assertErrors(
+//        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
+    expect(result, hasLength(4));
+    Expression syntheticExpression = result[0];
+    expect(syntheticExpression, isSimpleIdentifier);
+    expect(syntheticExpression.isSynthetic, isTrue);
+  }
+
+  void test_expressionList_multiple_middle() {
+    List<Expression> result = parseExpressionList('1, 2, , 4');
+    expectNotNullIfNoErrors(result);
+// TODO(brianwilkerson) Convert codes to errors when highlighting is fixed.
+    listener.assertErrorsWithCodes([ParserErrorCode.MISSING_IDENTIFIER]);
+//    listener.assertErrors(
+//        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1)]);
+    expect(result, hasLength(4));
+    Expression syntheticExpression = result[2];
+    expect(syntheticExpression, isSimpleIdentifier);
+    expect(syntheticExpression.isSynthetic, isTrue);
+  }
+
+  void test_expressionList_multiple_start() {
+    List<Expression> result = parseExpressionList('1, 2, 3,');
+    expectNotNullIfNoErrors(result);
+// The fasta parser does not use parseExpressionList when parsing for loops
+// and instead parseExpressionList is mapped to parseExpression('[$code]')
+// which allows and ignores an optional trailing comma.
+    assertNoErrors();
+    expect(result, hasLength(3));
+  }
+
+  void test_functionExpression_in_ConstructorFieldInitializer() {
+    CompilationUnit unit =
+        parseCompilationUnit("class A { A() : a = (){}; var v; }", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPECTED_CLASS_MEMBER
+    ]);
+// Make sure we recovered and parsed "var v" correctly
+    ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;
+    NodeList<ClassMember> members = declaration.members;
+    ClassMember fieldDecl = members[1];
+    expect(fieldDecl, isFieldDeclaration);
+    NodeList<VariableDeclaration> vars =
+        (fieldDecl as FieldDeclaration).fields.variables;
+    expect(vars, hasLength(1));
+    expect(vars[0].name.name, "v");
+  }
+
+  void test_functionExpression_named() {
+    parseExpression("m(f() => 0);",
+        expectedEndOffset: 11,
+        codes: [ParserErrorCode.NAMED_FUNCTION_EXPRESSION]);
+  }
+
+  void test_ifStatement_noElse_statement() {
+    parseStatement('if (x v) f(x);');
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
+  }
+
+  void test_importDirectivePartial_as() {
+    CompilationUnit unit = parseCompilationUnit("import 'b.dart' d as b;",
+        codes: [ParserErrorCode.UNEXPECTED_TOKEN]);
+    ImportDirective importDirective = unit.childEntities.first;
+    expect(importDirective.asKeyword, isNotNull);
+    expect(unit.directives, hasLength(1));
+    expect(unit.declarations, hasLength(0));
+  }
+
+  void test_importDirectivePartial_hide() {
+    CompilationUnit unit = parseCompilationUnit("import 'b.dart' d hide foo;",
+        codes: [ParserErrorCode.UNEXPECTED_TOKEN]);
+    ImportDirective importDirective = unit.childEntities.first;
+    expect(importDirective.combinators, hasLength(1));
+    expect(unit.directives, hasLength(1));
+    expect(unit.declarations, hasLength(0));
+  }
+
+  void test_importDirectivePartial_show() {
+    CompilationUnit unit = parseCompilationUnit("import 'b.dart' d show foo;",
+        codes: [ParserErrorCode.UNEXPECTED_TOKEN]);
+    ImportDirective importDirective = unit.childEntities.first;
+    expect(importDirective.combinators, hasLength(1));
+    expect(unit.directives, hasLength(1));
+    expect(unit.declarations, hasLength(0));
+  }
+
+  void test_incomplete_conditionalExpression() {
+    parseExpression("x ? 0", codes: [
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+  }
+
+  void test_incomplete_constructorInitializers_empty() {
+    createParser('C() : {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_INITIALIZER, 4, 1)]);
+  }
+
+  void test_incomplete_constructorInitializers_missingEquals() {
+    createParser('C() : x(3) {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 1)
+    ]);
+    expect(member, isConstructorDeclaration);
+    NodeList<ConstructorInitializer> initializers =
+        (member as ConstructorDeclaration).initializers;
+    expect(initializers, hasLength(1));
+    ConstructorInitializer initializer = initializers[0];
+    expect(initializer, isConstructorFieldInitializer);
+    Expression expression =
+        (initializer as ConstructorFieldInitializer).expression;
+    expect(expression, isNotNull);
+    expect(expression, isMethodInvocation);
+  }
+
+  void test_incomplete_constructorInitializers_this() {
+    createParser('C() : this {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
+      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
+    ]);
+  }
+
+  void test_incomplete_constructorInitializers_thisField() {
+    createParser('C() : this.g {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
+    ]);
+  }
+
+  void test_incomplete_constructorInitializers_thisPeriod() {
+    createParser('C() : this. {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 12, 1),
+      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
+    ]);
+  }
+
+  void test_incomplete_constructorInitializers_variable() {
+    createParser('C() : x {}');
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 1)
+    ]);
+  }
+
+  void test_incomplete_functionExpression() {
+    var expression = parseExpression("() a => null",
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 3, 1)]);
+    FunctionExpression functionExpression = expression;
+    expect(functionExpression.parameters.parameters, hasLength(0));
+  }
+
+  void test_incomplete_functionExpression2() {
+    var expression = parseExpression("() a {}",
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 3, 1)]);
+    FunctionExpression functionExpression = expression;
+    expect(functionExpression.parameters.parameters, hasLength(0));
+  }
+
+  void test_incomplete_returnType() {
+    parseCompilationUnit(r'''
+Map<Symbol, convertStringToSymbolMap(Map<String, dynamic> map) {
+  if (map == null) return null;
+  Map<Symbol, dynamic> result = new Map<Symbol, dynamic>();
+  map.forEach((name, value) {
+    result[new Symbol(name)] = value;
+  });
+  return result;
+}''', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 24),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 3)
+    ]);
+  }
+
+  void test_incomplete_topLevelFunction() {
+    parseCompilationUnit("foo();",
+        codes: [ParserErrorCode.MISSING_FUNCTION_BODY]);
+  }
+
+  void test_incomplete_topLevelVariable() {
+    CompilationUnit unit = parseCompilationUnit("String", errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 6),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 6)
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember member = declarations[0];
+    expect(member, isTopLevelVariableDeclaration);
+    NodeList<VariableDeclaration> variables =
+        (member as TopLevelVariableDeclaration).variables.variables;
+    expect(variables, hasLength(1));
+    SimpleIdentifier name = variables[0].name;
+    expect(name.isSynthetic, isFalse);
+  }
+
+  void test_incomplete_topLevelVariable_const() {
+    CompilationUnit unit = parseCompilationUnit("const ", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember member = declarations[0];
+    expect(member, isTopLevelVariableDeclaration);
+    NodeList<VariableDeclaration> variables =
+        (member as TopLevelVariableDeclaration).variables.variables;
+    expect(variables, hasLength(1));
+    SimpleIdentifier name = variables[0].name;
+    expect(name.isSynthetic, isTrue);
+  }
+
+  void test_incomplete_topLevelVariable_final() {
+    CompilationUnit unit = parseCompilationUnit("final ", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember member = declarations[0];
+    expect(member, isTopLevelVariableDeclaration);
+    NodeList<VariableDeclaration> variables =
+        (member as TopLevelVariableDeclaration).variables.variables;
+    expect(variables, hasLength(1));
+    SimpleIdentifier name = variables[0].name;
+    expect(name.isSynthetic, isTrue);
+  }
+
+  void test_incomplete_topLevelVariable_var() {
+    CompilationUnit unit = parseCompilationUnit("var ", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember member = declarations[0];
+    expect(member, isTopLevelVariableDeclaration);
+    NodeList<VariableDeclaration> variables =
+        (member as TopLevelVariableDeclaration).variables.variables;
+    expect(variables, hasLength(1));
+    SimpleIdentifier name = variables[0].name;
+    expect(name.isSynthetic, isTrue);
+  }
+
+  void test_incompleteField_const() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  const
+}''', codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember unitMember = declarations[0];
+    expect(unitMember, isClassDeclaration);
+    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
+    expect(members, hasLength(1));
+    ClassMember classMember = members[0];
+    expect(classMember, isFieldDeclaration);
+    VariableDeclarationList fieldList =
+        (classMember as FieldDeclaration).fields;
+    expect(fieldList.keyword.keyword, Keyword.CONST);
+    NodeList<VariableDeclaration> fields = fieldList.variables;
+    expect(fields, hasLength(1));
+    VariableDeclaration field = fields[0];
+    expect(field.name.isSynthetic, isTrue);
+  }
+
+  void test_incompleteField_final() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  final
+}''', codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember unitMember = declarations[0];
+    expect(unitMember, isClassDeclaration);
+    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
+    expect(members, hasLength(1));
+    ClassMember classMember = members[0];
+    expect(classMember, isFieldDeclaration);
+    VariableDeclarationList fieldList =
+        (classMember as FieldDeclaration).fields;
+    expect(fieldList.keyword.keyword, Keyword.FINAL);
+    NodeList<VariableDeclaration> fields = fieldList.variables;
+    expect(fields, hasLength(1));
+    VariableDeclaration field = fields[0];
+    expect(field.name.isSynthetic, isTrue);
+  }
+
+  void test_incompleteField_static() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  static c
+}''', codes: [
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember unitMember = declarations[0];
+    expect(unitMember, isClassDeclaration);
+    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
+    expect(members, hasLength(1));
+    ClassMember classMember = members[0];
+    expect(classMember, isFieldDeclaration);
+    FieldDeclaration declaration = classMember;
+    expect(declaration.staticKeyword.lexeme, 'static');
+    VariableDeclarationList fieldList = declaration.fields;
+    expect(fieldList.keyword, isNull);
+    NodeList<VariableDeclaration> fields = fieldList.variables;
+    expect(fields, hasLength(1));
+    VariableDeclaration field = fields[0];
+    expect(field.name.isSynthetic, isFalse);
+  }
+
+  void test_incompleteField_static2() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  static c x
+}''', codes: [ParserErrorCode.EXPECTED_TOKEN]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember unitMember = declarations[0];
+    expect(unitMember, isClassDeclaration);
+    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
+    expect(members, hasLength(1));
+    ClassMember classMember = members[0];
+    expect(classMember, isFieldDeclaration);
+    FieldDeclaration declaration = classMember;
+    expect(declaration.staticKeyword.lexeme, 'static');
+    VariableDeclarationList fieldList = declaration.fields;
+    expect(fieldList.keyword, isNull);
+    NodeList<VariableDeclaration> fields = fieldList.variables;
+    expect(fields, hasLength(1));
+    VariableDeclaration field = fields[0];
+    expect(field.name.isSynthetic, isFalse);
+  }
+
+  void test_incompleteField_type() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  A
+}''', codes: [
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember unitMember = declarations[0];
+    expect(unitMember, isClassDeclaration);
+    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
+    expect(members, hasLength(1));
+    ClassMember classMember = members[0];
+    expect(classMember, isFieldDeclaration);
+    VariableDeclarationList fieldList =
+        (classMember as FieldDeclaration).fields;
+    TypeName type = fieldList.type;
+    NodeList<VariableDeclaration> fields = fieldList.variables;
+    expect(fields, hasLength(1));
+    VariableDeclaration field = fields[0];
+    expect(type, isNull);
+    expect(field.name.name, 'A');
+  }
+
+  void test_incompleteField_var() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  var
+}''', codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EXPECTED_TOKEN
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember unitMember = declarations[0];
+    expect(unitMember, isClassDeclaration);
+    NodeList<ClassMember> members = (unitMember as ClassDeclaration).members;
+    expect(members, hasLength(1));
+    ClassMember classMember = members[0];
+    expect(classMember, isFieldDeclaration);
+    VariableDeclarationList fieldList =
+        (classMember as FieldDeclaration).fields;
+    expect(fieldList.keyword.keyword, Keyword.VAR);
+    NodeList<VariableDeclaration> fields = fieldList.variables;
+    expect(fields, hasLength(1));
+    VariableDeclaration field = fields[0];
+    expect(field.name.isSynthetic, isTrue);
+  }
+
+  void test_incompleteForEach() {
+// TODO(danrubel): remove this once control flow and spread collection
+// entry parsing is enabled by default
+    ForStatement statement = parseStatement('for (String item i) {}');
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)
+    ]);
+    expect(statement, isForStatement);
+    expect(statement.toSource(), 'for (String item; i;) {}');
+    var forParts = statement.forLoopParts as ForParts;
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.leftSeparator.type, TokenType.SEMICOLON);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.rightSeparator.type, TokenType.SEMICOLON);
+  }
+
+  void test_incompleteForEach2() {
+    ForStatement statement =
+        parseStatement('for (String item i) {}', featureSet: controlFlow);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)
+    ]);
+    expect(statement.toSource(), 'for (String item; i;) {}');
+    ForPartsWithDeclarations forLoopParts = statement.forLoopParts;
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.leftSeparator.type, TokenType.SEMICOLON);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.rightSeparator.type, TokenType.SEMICOLON);
+  }
+
+  void test_incompleteLocalVariable_atTheEndOfBlock() {
+    Statement statement = parseStatement('String v }', expectedEndOffset: 9);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+    expect(statement, isVariableDeclarationStatement);
+    expect(statement.toSource(), 'String v;');
+  }
+
+  void test_incompleteLocalVariable_atTheEndOfBlock_modifierOnly() {
+    Statement statement = parseStatement('final }', expectedEndOffset: 6);
+    listener.assertErrors([
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)
+    ]);
+    expect(statement, isVariableDeclarationStatement);
+    expect(statement.toSource(), 'final ;');
+  }
+
+  void test_incompleteLocalVariable_beforeIdentifier() {
+    Statement statement =
+        parseStatement('String v String v2;', expectedEndOffset: 9);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+    expect(statement, isVariableDeclarationStatement);
+    expect(statement.toSource(), 'String v;');
+  }
+
+  void test_incompleteLocalVariable_beforeKeyword() {
+    Statement statement =
+        parseStatement('String v if (true) {}', expectedEndOffset: 9);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+    expect(statement, isVariableDeclarationStatement);
+    expect(statement.toSource(), 'String v;');
+  }
+
+  void test_incompleteLocalVariable_beforeNextBlock() {
+    Statement statement = parseStatement('String v {}', expectedEndOffset: 9);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+    expect(statement, isVariableDeclarationStatement);
+    expect(statement.toSource(), 'String v;');
+  }
+
+  void test_incompleteLocalVariable_parameterizedType() {
+    Statement statement =
+        parseStatement('List<String> v {}', expectedEndOffset: 15);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1)]);
+    expect(statement, isVariableDeclarationStatement);
+    expect(statement.toSource(), 'List<String> v;');
+  }
+
+  void test_incompleteTypeArguments_field() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  final List<int f;
+}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 3)]);
+// one class
+    List<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+// one field declaration
+    List<ClassMember> members = classDecl.members;
+    expect(members, hasLength(1));
+    FieldDeclaration fieldDecl = members[0] as FieldDeclaration;
+// one field
+    VariableDeclarationList fieldList = fieldDecl.fields;
+    List<VariableDeclaration> fields = fieldList.variables;
+    expect(fields, hasLength(1));
+    VariableDeclaration field = fields[0];
+    expect(field.name.name, 'f');
+// validate the type
+    TypeArgumentList typeArguments = (fieldList.type as TypeName).typeArguments;
+    expect(typeArguments.arguments, hasLength(1));
+// synthetic '>'
+    Token token = typeArguments.endToken;
+    expect(token.type, TokenType.GT);
+    expect(token.isSynthetic, isTrue);
+  }
+
+  void test_incompleteTypeParameters() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C<K {
+}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]);
+// one class
+    List<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+// validate the type parameters
+    TypeParameterList typeParameters = classDecl.typeParameters;
+    expect(typeParameters.typeParameters, hasLength(1));
+// synthetic '>'
+    Token token = typeParameters.endToken;
+    expect(token.type, TokenType.GT);
+    expect(token.isSynthetic, isTrue);
+  }
+
+  void test_incompleteTypeParameters2() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C<K extends L<T> {
+}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 21, 1)]);
+// one class
+    List<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+// validate the type parameters
+    TypeParameterList typeParameters = classDecl.typeParameters;
+    expect(typeParameters.typeParameters, hasLength(1));
+// synthetic '>'
+    Token token = typeParameters.endToken;
+    expect(token.type, TokenType.GT);
+    expect(token.isSynthetic, isTrue);
+  }
+
+  void test_incompleteTypeParameters3() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C<K extends L<T {
+}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 20, 1)]);
+// one class
+    List<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+// validate the type parameters
+    TypeParameterList typeParameters = classDecl.typeParameters;
+    expect(typeParameters.typeParameters, hasLength(1));
+// synthetic '>'
+    Token token = typeParameters.endToken;
+    expect(token.type, TokenType.GT);
+    expect(token.isSynthetic, isTrue);
+  }
+
+  void test_invalidFunctionBodyModifier() {
+    parseCompilationUnit("f() sync {}",
+        codes: [ParserErrorCode.MISSING_STAR_AFTER_SYNC]);
+  }
+
+  void test_invalidMapLiteral() {
+    parseCompilationUnit("class C { var f = Map<A, B> {}; }", codes: [
+// TODO(danrubel): Improve error message to indicate
+// that "Map" should be removed.
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_KEYWORD_OPERATOR,
+      ParserErrorCode.MISSING_METHOD_PARAMETERS,
+      ParserErrorCode.EXPECTED_CLASS_MEMBER,
+    ]);
+  }
+
+  void test_invalidTypeParameters() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  G<int double> g;
+}''', errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 6)]);
+// one class
+    List<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+// validate members
+    ClassDeclaration classDecl = declarations[0] as ClassDeclaration;
+    expect(classDecl.members, hasLength(1));
+    FieldDeclaration fields = classDecl.members.first;
+    expect(fields.fields.variables, hasLength(1));
+    VariableDeclaration field = fields.fields.variables.first;
+    expect(field.name.name, 'g');
+  }
+
+  void test_invalidTypeParameters_super() {
+    parseCompilationUnit('class C<X super Y> {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
+    ]);
+  }
+
+  void test_isExpression_noType() {
+    CompilationUnit unit = parseCompilationUnit(
+        "class Bar<T extends Foo> {m(x){if (x is ) return;if (x is !)}}",
+        codes: [
+          ParserErrorCode.EXPECTED_TYPE_NAME,
+          ParserErrorCode.EXPECTED_TYPE_NAME,
+          ParserErrorCode.MISSING_IDENTIFIER,
+          ParserErrorCode.EXPECTED_TOKEN,
+        ]);
+    ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;
+    MethodDeclaration method = declaration.members[0] as MethodDeclaration;
+    BlockFunctionBody body = method.body as BlockFunctionBody;
+    IfStatement ifStatement = body.block.statements[1] as IfStatement;
+    IsExpression expression = ifStatement.condition as IsExpression;
+    expect(expression.expression, isNotNull);
+    expect(expression.isOperator, isNotNull);
+    expect(expression.notOperator, isNotNull);
+    TypeAnnotation type = expression.type;
+    expect(type, isNotNull);
+    expect(type is TypeName && type.name.isSynthetic, isTrue);
+    ExpressionStatement thenStatement = ifStatement.thenStatement;
+    expect(thenStatement.semicolon.isSynthetic, isTrue);
+    SimpleIdentifier simpleId = thenStatement.expression;
+    expect(simpleId.isSynthetic, isTrue);
+  }
+
+  void test_issue_34610_get() {
+    final unit =
+        parseCompilationUnit('class C { get C.named => null; }', errors: [
+      expectedError(ParserErrorCode.GETTER_CONSTRUCTOR, 10, 3),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 14, 1),
+    ]);
+    ClassDeclaration declaration = unit.declarations[0];
+    ConstructorDeclaration method = declaration.members[0];
+    expect(method.name.name, 'named');
+    expect(method.parameters, isNotNull);
+  }
+
+  void test_issue_34610_initializers() {
+    final unit = parseCompilationUnit('class C { C.named : super(); }',
+        errors: [
+          expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)
+        ]);
+    ClassDeclaration declaration = unit.declarations[0];
+    ConstructorDeclaration constructor = declaration.members[0];
+    expect(constructor.name.name, 'named');
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, hasLength(0));
+  }
+
+  void test_issue_34610_missing_param() {
+    final unit = parseCompilationUnit('class C { C => null; }', errors: [
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)
+    ]);
+    ClassDeclaration declaration = unit.declarations[0];
+    ConstructorDeclaration constructor = declaration.members[0];
+    expect(constructor.name, isNull);
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, hasLength(0));
+  }
+
+  void test_issue_34610_named_missing_param() {
+    final unit = parseCompilationUnit('class C { C.named => null; }', errors: [
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1)
+    ]);
+    ClassDeclaration declaration = unit.declarations[0];
+    ConstructorDeclaration constructor = declaration.members[0];
+    expect(constructor.name.name, 'named');
+    expect(constructor.parameters, isNotNull);
+    expect(constructor.parameters.parameters, hasLength(0));
+  }
+
+  void test_issue_34610_set() {
+    final unit =
+        parseCompilationUnit('class C { set C.named => null; }', errors: [
+      expectedError(ParserErrorCode.SETTER_CONSTRUCTOR, 10, 3),
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 14, 1),
+    ]);
+    ClassDeclaration declaration = unit.declarations[0];
+    ConstructorDeclaration method = declaration.members[0];
+    expect(method.name.name, 'named');
+    expect(method.parameters, isNotNull);
+    expect(method.parameters.parameters, hasLength(0));
+  }
+
+  void test_keywordInPlaceOfIdentifier() {
+// TODO(brianwilkerson) We could do better with this.
+    parseCompilationUnit("do() {}",
+        codes: [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]);
+  }
+
+  void test_logicalAndExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("&& y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_logicalAndExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("&&", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_logicalAndExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x &&", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_logicalAndExpression_precedence_bitwiseOr_left() {
+    BinaryExpression expression = parseExpression("| &&", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_logicalAndExpression_precedence_bitwiseOr_right() {
+    BinaryExpression expression = parseExpression("&& |", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_logicalOrExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("|| y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_logicalOrExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("||", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_logicalOrExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x ||", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_logicalOrExpression_precedence_logicalAnd_left() {
+    BinaryExpression expression = parseExpression("&& ||", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_logicalOrExpression_precedence_logicalAnd_right() {
+    BinaryExpression expression = parseExpression("|| &&", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_method_missingBody() {
+    parseCompilationUnit("class C { b() }",
+        errors: [expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 14, 1)]);
+  }
+
+  void test_missing_commaInArgumentList() {
+    MethodInvocation expression = parseExpression("f(x: 1 y: 2)",
+        errors: [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
+    NodeList<Expression> arguments = expression.argumentList.arguments;
+    expect(arguments, hasLength(2));
+  }
+
+  void test_missingComma_beforeNamedArgument() {
+    createParser('(a b: c)');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    listener
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 3, 1)]);
+    expect(argumentList.arguments, hasLength(2));
+  }
+
+  void test_missingGet() {
+    CompilationUnit unit = parseCompilationUnit(r'''
+class C {
+  int length {}
+  void foo() {}
+}''', errors: [
+      expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 16, 6)
+    ]);
+    expect(unit, isNotNull);
+    ClassDeclaration classDeclaration =
+        unit.declarations[0] as ClassDeclaration;
+    NodeList<ClassMember> members = classDeclaration.members;
+    expect(members, hasLength(2));
+    expect(members[0], isMethodDeclaration);
+    ClassMember member = members[1];
+    expect(member, isMethodDeclaration);
+    expect((member as MethodDeclaration).name.name, "foo");
+  }
+
+  void test_missingIdentifier_afterAnnotation() {
+    createParser('@override }', expectedEndOffset: 10);
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1)]);
+// TODO(danrubel): Consider generating a sub method so that the
+// existing annotation can be associated with a class member.
+    expect(member, isNull);
+  }
+
+  void test_missingSemicolon_varialeDeclarationList() {
+    void verify(CompilationUnitMember member, String expectedTypeName,
+        String expectedName, String expectedSemicolon) {
+      expect(member, isTopLevelVariableDeclaration);
+      TopLevelVariableDeclaration declaration = member;
+      VariableDeclarationList variableList = declaration.variables;
+      expect(variableList, isNotNull);
+      NodeList<VariableDeclaration> variables = variableList.variables;
+      expect(variables, hasLength(1));
+      VariableDeclaration variable = variables[0];
+      expect(variableList.type.toString(), expectedTypeName);
+      expect(variable.name.name, expectedName);
+      if (expectedSemicolon.isEmpty) {
+        expect(declaration.semicolon.isSynthetic, isTrue);
+      } else {
+        expect(declaration.semicolon.lexeme, expectedSemicolon);
+      }
+    }
+
+// Fasta considers the `n` an extraneous modifier
+// and parses this as a single top level declaration.
+// TODO(danrubel): A better recovery
+// would be to insert a synthetic comma after the `n`.
+    CompilationUnit unit = parseCompilationUnit('String n x = "";', codes: [
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE
+    ]);
+    expect(unit, isNotNull);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(2));
+    verify(declarations[0], 'String', 'n', '');
+    verify(declarations[1], 'null', 'x', ';');
+  }
+
+  void test_multiplicativeExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("* y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_multiplicativeExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("*", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_multiplicativeExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x *", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_multiplicativeExpression_missing_RHS_super() {
+    BinaryExpression expression =
+        parseExpression("super *", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_multiplicativeExpression_precedence_unary_left() {
+    BinaryExpression expression =
+        parseExpression("-x *", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isPrefixExpression);
+  }
+
+  void test_multiplicativeExpression_precedence_unary_right() {
+    BinaryExpression expression =
+        parseExpression("* -y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isPrefixExpression);
+  }
+
+  void test_multiplicativeExpression_super() {
+    BinaryExpression expression = parseExpression("super ==  ==", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_namedParameterOutsideGroup() {
+    CompilationUnit unit =
+        parseCompilationUnit('class A { b(c: 0, Foo d: 0, e){} }', errors: [
+      expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 13, 1),
+      expectedError(ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP, 23, 1)
+    ]);
+    expect(unit.declarations, hasLength(1));
+    ClassDeclaration classA = unit.declarations[0];
+    expect(classA.members, hasLength(1));
+    MethodDeclaration method = classA.members[0];
+    NodeList<FormalParameter> parameters = method.parameters.parameters;
+    expect(parameters, hasLength(3));
+    expect(parameters[0].isNamed, isTrue);
+    expect(parameters[1].isNamed, isTrue);
+    expect(parameters[2].isRequired, isTrue);
+  }
+
+  void test_nonStringLiteralUri_import() {
+    parseCompilationUnit("import dart:io; class C {}", errors: [
+      expectedError(ParserErrorCode.EXPECTED_STRING_LITERAL, 7, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 7, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 11, 1),
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 2)
+    ]);
+  }
+
+  void test_prefixExpression_missing_operand_minus() {
+    PrefixExpression expression =
+        parseExpression("-", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.operand, isSimpleIdentifier);
+    expect(expression.operand.isSynthetic, isTrue);
+    expect(expression.operator.type, TokenType.MINUS);
+  }
+
+  void test_primaryExpression_argumentDefinitionTest() {
+    SimpleIdentifier expression = parsePrimaryExpression('?a',
+        expectedEndOffset: 0,
+        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]);
+    expectNotNullIfNoErrors(expression);
+    expect(expression.isSynthetic, isTrue);
+  }
+
+  void test_propertyAccess_missing_LHS_RHS() {
+    Expression result = parseExpression(".", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    PrefixedIdentifier expression = result;
+    expect(expression.prefix.isSynthetic, isTrue);
+    expect(expression.period.lexeme, '.');
+    expect(expression.identifier.isSynthetic, isTrue);
+  }
+
+  void test_relationalExpression_missing_LHS() {
+    IsExpression expression =
+        parseExpression("is y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.expression, isSimpleIdentifier);
+    expect(expression.expression.isSynthetic, isTrue);
+  }
+
+  void test_relationalExpression_missing_LHS_RHS() {
+    parseExpression("is", codes: [
+      ParserErrorCode.EXPECTED_TYPE_NAME,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+  }
+
+  void test_relationalExpression_missing_RHS() {
+    IsExpression expression =
+        parseExpression("x is", codes: [ParserErrorCode.EXPECTED_TYPE_NAME]);
+    expect(expression.type, isTypeName);
+    expect(expression.type.isSynthetic, isTrue);
+  }
+
+  void test_relationalExpression_precedence_shift_right() {
+    parseExpression("<< is", codes: [
+      ParserErrorCode.EXPECTED_TYPE_NAME,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+  }
+
+  void test_shiftExpression_missing_LHS() {
+    BinaryExpression expression =
+        parseExpression("<< y", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+  }
+
+  void test_shiftExpression_missing_LHS_RHS() {
+    BinaryExpression expression = parseExpression("<<", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isSimpleIdentifier);
+    expect(expression.leftOperand.isSynthetic, isTrue);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_shiftExpression_missing_RHS() {
+    BinaryExpression expression =
+        parseExpression("x <<", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_shiftExpression_missing_RHS_super() {
+    BinaryExpression expression = parseExpression("super <<",
+        codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+    expect(expression.rightOperand, isSimpleIdentifier);
+    expect(expression.rightOperand.isSynthetic, isTrue);
+  }
+
+  void test_shiftExpression_precedence_unary_left() {
+    BinaryExpression expression = parseExpression("+ <<", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_shiftExpression_precedence_unary_right() {
+    BinaryExpression expression = parseExpression("<< +", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.rightOperand, isBinaryExpression);
+  }
+
+  void test_shiftExpression_super() {
+    BinaryExpression expression = parseExpression("super << <<", codes: [
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+    expect(expression.leftOperand, isBinaryExpression);
+  }
+
+  void test_typedef_eof() {
+    CompilationUnit unit = parseCompilationUnit("typedef n", codes: [
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_TYPEDEF_PARAMETERS
+    ]);
+    NodeList<CompilationUnitMember> declarations = unit.declarations;
+    expect(declarations, hasLength(1));
+    CompilationUnitMember member = declarations[0];
+    expect(member, isFunctionTypeAlias);
+  }
+
+  void test_unaryPlus() {
+    parseExpression("+2", codes: [ParserErrorCode.MISSING_IDENTIFIER]);
+  }
+}
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 639ce65..c0c874f 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -173,7 +173,8 @@
     int count = expectedLocations.length;
     for (int i = 0; i < count; i++) {
       ScannerTest_ExpectedLocation expectedLocation = expectedLocations[i];
-      CharacterLocation location = info.getLocation(expectedLocation._offset);
+      var location =
+          info.getLocation(expectedLocation._offset) as CharacterLocation;
       expect(location.lineNumber, expectedLocation._lineNumber,
           reason: 'Line number in location $i');
       expect(location.columnNumber, expectedLocation._columnNumber,
diff --git a/pkg/analyzer/test/generated/simple_parser_test.dart b/pkg/analyzer/test/generated/simple_parser_test.dart
new file mode 100644
index 0000000..c3f40da
--- /dev/null
+++ b/pkg/analyzer/test/generated/simple_parser_test.dart
@@ -0,0 +1,2090 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SimpleParserTest);
+  });
+}
+
+/// Parser tests that test individual parsing methods. The code fragments should
+/// be as minimal as possible in order to test the method, but should not test
+/// the interactions between the method under test and other methods.
+///
+/// More complex tests should be defined in the class [ComplexParserTest].
+@reflectiveTest
+class SimpleParserTest extends FastaParserTestCase {
+  ConstructorName parseConstructorName(String name) {
+    createParser('new $name();');
+    Statement statement = parser.parseStatement2();
+    expect(statement, isExpressionStatement);
+    Expression expression = (statement as ExpressionStatement).expression;
+    expect(expression, isInstanceCreationExpression);
+    return (expression as InstanceCreationExpression).constructorName;
+  }
+
+  ExtendsClause parseExtendsClause(String clause) {
+    createParser('class TestClass $clause {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+    ClassDeclaration classDecl = unit.declarations[0];
+    expect(classDecl, isNotNull);
+    return classDecl.extendsClause;
+  }
+
+  List<SimpleIdentifier> parseIdentifierList(String identifiers) {
+    createParser('show $identifiers');
+    List<Combinator> combinators = parser.parseCombinators();
+    expect(combinators, hasLength(1));
+    return (combinators[0] as ShowCombinator).shownNames;
+  }
+
+  ImplementsClause parseImplementsClause(String clause) {
+    createParser('class TestClass $clause {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+    ClassDeclaration classDecl = unit.declarations[0];
+    expect(classDecl, isNotNull);
+    return classDecl.implementsClause;
+  }
+
+  LibraryIdentifier parseLibraryIdentifier(String name) {
+    createParser('library $name;');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    expect(unit.directives, hasLength(1));
+    LibraryDirective directive = unit.directives[0];
+    return directive.name;
+  }
+
+  /// Parse the given [content] as a sequence of statements by enclosing it in a
+  /// block. The [expectedCount] is the number of statements that are expected
+  /// to be parsed. If [errorCodes] are provided, verify that the error codes of
+  /// the errors that are expected are found.
+  void parseStatementList(String content, int expectedCount) {
+    Statement statement = parseStatement('{$content}');
+    expect(statement, isBlock);
+    Block block = statement;
+    expect(block.statements, hasLength(expectedCount));
+  }
+
+  VariableDeclaration parseVariableDeclaration(String declaration) {
+    createParser(declaration);
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+    TopLevelVariableDeclaration decl = unit.declarations[0];
+    expect(decl, isNotNull);
+    return decl.variables.variables[0];
+  }
+
+  WithClause parseWithClause(String clause) {
+    createParser('class TestClass extends Object $clause {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+    ClassDeclaration classDecl = unit.declarations[0];
+    expect(classDecl, isNotNull);
+    return classDecl.withClause;
+  }
+
+  void test_classDeclaration_complexTypeParam() {
+    CompilationUnit unit = parseCompilationUnit('''
+class C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T> {}
+''');
+    ClassDeclaration clazz = unit.declarations[0];
+    expect(clazz.name.name, 'C');
+    expect(clazz.typeParameters.typeParameters, hasLength(1));
+    TypeParameter typeParameter = clazz.typeParameters.typeParameters[0];
+    expect(typeParameter.name.name, 'T');
+    expect(typeParameter.metadata, hasLength(1));
+    Annotation metadata = typeParameter.metadata[0];
+    expect(metadata.name.name, 'Foo.bar');
+  }
+
+  void test_method_name_notNull_37733() {
+    // https://github.com/dart-lang/sdk/issues/37733
+    var unit = parseCompilationUnit(r'class C { f(<T>()); }', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 12, 1),
+    ]);
+    var classDeclaration = unit.declarations[0] as ClassDeclaration;
+    var method = classDeclaration.members[0] as MethodDeclaration;
+    expect(method.parameters.parameters, hasLength(1));
+    var parameter =
+        method.parameters.parameters[0] as FunctionTypedFormalParameter;
+    expect(parameter.identifier, isNotNull);
+  }
+
+  void test_parseAnnotation_n1() {
+    createParser('@A');
+    Annotation annotation = parser.parseAnnotation();
+    expectNotNullIfNoErrors(annotation);
+    assertNoErrors();
+    expect(annotation.atSign, isNotNull);
+    expect(annotation.name, isNotNull);
+    expect(annotation.period, isNull);
+    expect(annotation.constructorName, isNull);
+    expect(annotation.arguments, isNull);
+  }
+
+  void test_parseAnnotation_n1_a() {
+    createParser('@A(x,y)');
+    Annotation annotation = parser.parseAnnotation();
+    expectNotNullIfNoErrors(annotation);
+    assertNoErrors();
+    expect(annotation.atSign, isNotNull);
+    expect(annotation.name, isNotNull);
+    expect(annotation.period, isNull);
+    expect(annotation.constructorName, isNull);
+    expect(annotation.arguments, isNotNull);
+  }
+
+  void test_parseAnnotation_n2() {
+    createParser('@A.B');
+    Annotation annotation = parser.parseAnnotation();
+    expectNotNullIfNoErrors(annotation);
+    assertNoErrors();
+    expect(annotation.atSign, isNotNull);
+    expect(annotation.name, isNotNull);
+    expect(annotation.period, isNull);
+    expect(annotation.constructorName, isNull);
+    expect(annotation.arguments, isNull);
+  }
+
+  void test_parseAnnotation_n2_a() {
+    createParser('@A.B(x,y)');
+    Annotation annotation = parser.parseAnnotation();
+    expectNotNullIfNoErrors(annotation);
+    assertNoErrors();
+    expect(annotation.atSign, isNotNull);
+    expect(annotation.name, isNotNull);
+    expect(annotation.period, isNull);
+    expect(annotation.constructorName, isNull);
+    expect(annotation.arguments, isNotNull);
+  }
+
+  void test_parseAnnotation_n3() {
+    createParser('@A.B.C');
+    Annotation annotation = parser.parseAnnotation();
+    expectNotNullIfNoErrors(annotation);
+    assertNoErrors();
+    expect(annotation.atSign, isNotNull);
+    expect(annotation.name, isNotNull);
+    expect(annotation.period, isNotNull);
+    expect(annotation.constructorName, isNotNull);
+    expect(annotation.arguments, isNull);
+  }
+
+  void test_parseAnnotation_n3_a() {
+    createParser('@A.B.C(x,y)');
+    Annotation annotation = parser.parseAnnotation();
+    expectNotNullIfNoErrors(annotation);
+    assertNoErrors();
+    expect(annotation.atSign, isNotNull);
+    expect(annotation.name, isNotNull);
+    expect(annotation.period, isNotNull);
+    expect(annotation.constructorName, isNotNull);
+    expect(annotation.arguments, isNotNull);
+  }
+
+  test_parseArgument() {
+    Expression result = parseArgument('3');
+    expect(result, const TypeMatcher<IntegerLiteral>());
+    IntegerLiteral literal = result;
+    expect(literal.value, 3);
+  }
+
+  test_parseArgument_named() {
+    Expression result = parseArgument('foo: "a"');
+    expect(result, const TypeMatcher<NamedExpression>());
+    NamedExpression expression = result;
+    StringLiteral literal = expression.expression;
+    expect(literal.stringValue, 'a');
+  }
+
+  void test_parseArgumentList_empty() {
+    createParser('()');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    NodeList<Expression> arguments = argumentList.arguments;
+    expect(arguments, hasLength(0));
+  }
+
+  void test_parseArgumentList_mixed() {
+    createParser('(w, x, y: y, z: z)');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    NodeList<Expression> arguments = argumentList.arguments;
+    expect(arguments, hasLength(4));
+  }
+
+  void test_parseArgumentList_noNamed() {
+    createParser('(x, y, z)');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    NodeList<Expression> arguments = argumentList.arguments;
+    expect(arguments, hasLength(3));
+  }
+
+  void test_parseArgumentList_onlyNamed() {
+    createParser('(x: x, y: y)');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    NodeList<Expression> arguments = argumentList.arguments;
+    expect(arguments, hasLength(2));
+  }
+
+  void test_parseArgumentList_trailing_comma() {
+    createParser('(x, y, z,)');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    NodeList<Expression> arguments = argumentList.arguments;
+    expect(arguments, hasLength(3));
+  }
+
+  void test_parseArgumentList_typeArguments() {
+    createParser('(a<b,c>(d))');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    NodeList<Expression> arguments = argumentList.arguments;
+    expect(arguments, hasLength(1));
+  }
+
+  void test_parseArgumentList_typeArguments_none() {
+    createParser('(a<b,p.q.c>(d))');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    NodeList<Expression> arguments = argumentList.arguments;
+    expect(arguments, hasLength(2));
+  }
+
+  void test_parseArgumentList_typeArguments_prefixed() {
+    createParser('(a<b,p.c>(d))');
+    ArgumentList argumentList = parser.parseArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    NodeList<Expression> arguments = argumentList.arguments;
+    expect(arguments, hasLength(1));
+  }
+
+  void test_parseCombinators_h() {
+    createParser('hide a');
+    List<Combinator> combinators = parser.parseCombinators();
+    expectNotNullIfNoErrors(combinators);
+    assertNoErrors();
+    expect(combinators, hasLength(1));
+    HideCombinator combinator = combinators[0] as HideCombinator;
+    expect(combinator, isNotNull);
+    expect(combinator.keyword, isNotNull);
+    expect(combinator.hiddenNames, hasLength(1));
+  }
+
+  void test_parseCombinators_hs() {
+    createParser('hide a show b');
+    List<Combinator> combinators = parser.parseCombinators();
+    expectNotNullIfNoErrors(combinators);
+    assertNoErrors();
+    expect(combinators, hasLength(2));
+    HideCombinator hideCombinator = combinators[0] as HideCombinator;
+    expect(hideCombinator, isNotNull);
+    expect(hideCombinator.keyword, isNotNull);
+    expect(hideCombinator.hiddenNames, hasLength(1));
+    ShowCombinator showCombinator = combinators[1] as ShowCombinator;
+    expect(showCombinator, isNotNull);
+    expect(showCombinator.keyword, isNotNull);
+    expect(showCombinator.shownNames, hasLength(1));
+  }
+
+  void test_parseCombinators_hshs() {
+    createParser('hide a show b hide c show d');
+    List<Combinator> combinators = parser.parseCombinators();
+    expectNotNullIfNoErrors(combinators);
+    assertNoErrors();
+    expect(combinators, hasLength(4));
+  }
+
+  void test_parseCombinators_s() {
+    createParser('show a');
+    List<Combinator> combinators = parser.parseCombinators();
+    expectNotNullIfNoErrors(combinators);
+    assertNoErrors();
+    expect(combinators, hasLength(1));
+    ShowCombinator combinator = combinators[0] as ShowCombinator;
+    expect(combinator, isNotNull);
+    expect(combinator.keyword, isNotNull);
+    expect(combinator.shownNames, hasLength(1));
+  }
+
+  void test_parseCommentAndMetadata_c() {
+    createParser('/** 1 */ class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNotNull);
+    expect(declaration.metadata, isEmpty);
+  }
+
+  void test_parseCommentAndMetadata_cmc() {
+    createParser('/** 1 */ @A /** 2 */ class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    Comment comment = declaration.documentationComment;
+    expect(comment.isDocumentation, isTrue);
+    expect(comment.tokens, hasLength(1));
+    expect(comment.tokens[0].lexeme, '/** 2 */');
+    expect(declaration.metadata, hasLength(1));
+  }
+
+  void test_parseCommentAndMetadata_cmcm() {
+    createParser('/** 1 */ @A /** 2 */ @B class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNotNull);
+    expect(declaration.metadata, hasLength(2));
+  }
+
+  void test_parseCommentAndMetadata_cmm() {
+    createParser('/** 1 */ @A @B class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNotNull);
+    expect(declaration.metadata, hasLength(2));
+  }
+
+  void test_parseCommentAndMetadata_m() {
+    createParser('@A class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.metadata, hasLength(1));
+  }
+
+  void test_parseCommentAndMetadata_mcm() {
+    createParser('@A /** 1 */ @B class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNotNull);
+    expect(declaration.metadata, hasLength(2));
+  }
+
+  void test_parseCommentAndMetadata_mcmc() {
+    createParser('@A /** 1 */ @B /** 2 */ class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNotNull);
+    expect(declaration.documentationComment.tokens[0].lexeme, contains('2'));
+    expect(declaration.metadata, hasLength(2));
+  }
+
+  void test_parseCommentAndMetadata_mix1() {
+    createParser(r'''
+/**
+ * aaa
+ */
+/**
+ * bbb
+ */
+class A {}
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.metadata, hasLength(0));
+    List<Token> tokens = declaration.documentationComment.tokens;
+    expect(tokens, hasLength(1));
+    expect(tokens[0].lexeme, contains('bbb'));
+  }
+
+  void test_parseCommentAndMetadata_mix2() {
+    createParser(r'''
+/**
+ * aaa
+ */
+/// bbb
+/// ccc
+class B {}
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.metadata, hasLength(0));
+    List<Token> tokens = declaration.documentationComment.tokens;
+    expect(tokens, hasLength(2));
+    expect(tokens[0].lexeme, contains('bbb'));
+    expect(tokens[1].lexeme, contains('ccc'));
+  }
+
+  void test_parseCommentAndMetadata_mix3() {
+    createParser(r'''
+/// aaa
+/// bbb
+/**
+ * ccc
+ */
+class C {}
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.metadata, hasLength(0));
+    List<Token> tokens = declaration.documentationComment.tokens;
+    expect(tokens, hasLength(1));
+    expect(tokens[0].lexeme, contains('ccc'));
+  }
+
+  test_parseCommentAndMetadata_mix4() {
+    createParser(r'''
+/// aaa
+/// bbb
+/**
+ * ccc
+ */
+/// ddd
+class D {}
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.metadata, hasLength(0));
+    List<Token> tokens = declaration.documentationComment.tokens;
+    expect(tokens, hasLength(1));
+    expect(tokens[0].lexeme, contains('ddd'));
+  }
+
+  test_parseCommentAndMetadata_mix5() {
+    createParser(r'''
+/**
+ * aaa
+ */
+// bbb
+class E {}
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.metadata, hasLength(0));
+    List<Token> tokens = declaration.documentationComment.tokens;
+    expect(tokens, hasLength(1));
+    expect(tokens[0].lexeme, contains('aaa'));
+  }
+
+  void test_parseCommentAndMetadata_mm() {
+    createParser('@A @B(x) class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.metadata, hasLength(2));
+  }
+
+  void test_parseCommentAndMetadata_none() {
+    createParser('class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.metadata, isEmpty);
+  }
+
+  void test_parseCommentAndMetadata_singleLine() {
+    createParser(r'''
+/// 1
+/// 2
+class C {}
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expectNotNullIfNoErrors(unit);
+    assertNoErrors();
+    ClassDeclaration declaration = unit.declarations[0];
+    expect(declaration.documentationComment, isNotNull);
+    expect(declaration.metadata, isEmpty);
+  }
+
+  void test_parseCommentReference_new_prefixed() {
+    createParser('');
+    CommentReference reference = parseCommentReference('new a.b', 7);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isPrefixedIdentifier);
+    PrefixedIdentifier prefixedIdentifier = reference.identifier;
+    SimpleIdentifier prefix = prefixedIdentifier.prefix;
+    expect(prefix.token, isNotNull);
+    expect(prefix.name, "a");
+    expect(prefix.offset, 11);
+    expect(prefixedIdentifier.period, isNotNull);
+    SimpleIdentifier identifier = prefixedIdentifier.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "b");
+    expect(identifier.offset, 13);
+  }
+
+  void test_parseCommentReference_new_simple() {
+    createParser('');
+    CommentReference reference = parseCommentReference('new a', 5);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isSimpleIdentifier);
+    SimpleIdentifier identifier = reference.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "a");
+    expect(identifier.offset, 9);
+  }
+
+  void test_parseCommentReference_operator_withKeyword_notPrefixed() {
+    createParser('');
+    CommentReference reference = parseCommentReference('operator ==', 5);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isSimpleIdentifier);
+    SimpleIdentifier identifier = reference.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "==");
+    expect(identifier.offset, 14);
+  }
+
+  void test_parseCommentReference_operator_withKeyword_prefixed() {
+    createParser('');
+    CommentReference reference = parseCommentReference('Object.operator==', 7);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isPrefixedIdentifier);
+    PrefixedIdentifier prefixedIdentifier = reference.identifier;
+    SimpleIdentifier prefix = prefixedIdentifier.prefix;
+    expect(prefix.token, isNotNull);
+    expect(prefix.name, "Object");
+    expect(prefix.offset, 7);
+    expect(prefixedIdentifier.period, isNotNull);
+    SimpleIdentifier identifier = prefixedIdentifier.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "==");
+    expect(identifier.offset, 22);
+  }
+
+  void test_parseCommentReference_operator_withoutKeyword_notPrefixed() {
+    createParser('');
+    CommentReference reference = parseCommentReference('==', 5);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isSimpleIdentifier);
+    SimpleIdentifier identifier = reference.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "==");
+    expect(identifier.offset, 5);
+  }
+
+  void test_parseCommentReference_operator_withoutKeyword_prefixed() {
+    createParser('');
+    CommentReference reference = parseCommentReference('Object.==', 7);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isPrefixedIdentifier);
+    PrefixedIdentifier prefixedIdentifier = reference.identifier;
+    SimpleIdentifier prefix = prefixedIdentifier.prefix;
+    expect(prefix.token, isNotNull);
+    expect(prefix.name, "Object");
+    expect(prefix.offset, 7);
+    expect(prefixedIdentifier.period, isNotNull);
+    SimpleIdentifier identifier = prefixedIdentifier.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "==");
+    expect(identifier.offset, 14);
+  }
+
+  void test_parseCommentReference_prefixed() {
+    createParser('');
+    CommentReference reference = parseCommentReference('a.b', 7);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isPrefixedIdentifier);
+    PrefixedIdentifier prefixedIdentifier = reference.identifier;
+    SimpleIdentifier prefix = prefixedIdentifier.prefix;
+    expect(prefix.token, isNotNull);
+    expect(prefix.name, "a");
+    expect(prefix.offset, 7);
+    expect(prefixedIdentifier.period, isNotNull);
+    SimpleIdentifier identifier = prefixedIdentifier.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "b");
+    expect(identifier.offset, 9);
+  }
+
+  void test_parseCommentReference_simple() {
+    createParser('');
+    CommentReference reference = parseCommentReference('a', 5);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isSimpleIdentifier);
+    SimpleIdentifier identifier = reference.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "a");
+    expect(identifier.offset, 5);
+  }
+
+  void test_parseCommentReference_synthetic() {
+    createParser('');
+    CommentReference reference = parseCommentReference('', 5);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    expect(reference.identifier, isSimpleIdentifier);
+    SimpleIdentifier identifier = reference.identifier;
+    expect(identifier, isNotNull);
+    expect(identifier.isSynthetic, isTrue);
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "");
+    expect(identifier.offset, 5);
+    // Should end with EOF token.
+    Token nextToken = identifier.token.next;
+    expect(nextToken, isNotNull);
+    expect(nextToken.type, TokenType.EOF);
+  }
+
+  @failingTest
+  void test_parseCommentReference_this() {
+    // This fails because we are returning null from the method and asserting
+    // that the return value is not null.
+    createParser('');
+    CommentReference reference = parseCommentReference('this', 5);
+    expectNotNullIfNoErrors(reference);
+    assertNoErrors();
+    SimpleIdentifier identifier = reference.identifier;
+    expect(identifier.token, isNotNull);
+    expect(identifier.name, "a");
+    expect(identifier.offset, 5);
+  }
+
+  void test_parseCommentReferences_33738() {
+    CompilationUnit unit =
+        parseCompilationUnit('/** [String] */ abstract class Foo {}');
+    ClassDeclaration clazz = unit.declarations[0];
+    Comment comment = clazz.documentationComment;
+    expect(clazz.isAbstract, isTrue);
+    List<CommentReference> references = comment.references;
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 5);
+  }
+
+  void test_parseCommentReferences_beforeAnnotation() {
+    CompilationUnit unit = parseCompilationUnit('''
+/// See [int] and [String]
+/// and [Object].
+@Annotation
+abstract class Foo {}
+''');
+    ClassDeclaration clazz = unit.declarations[0];
+    Comment comment = clazz.documentationComment;
+    expect(clazz.isAbstract, isTrue);
+    List<CommentReference> references = comment.references;
+    expect(references, hasLength(3));
+
+    expectReference(int index, String expectedText, int expectedOffset) {
+      CommentReference reference = references[index];
+      expect(reference.identifier.name, expectedText);
+      expect(reference.offset, expectedOffset);
+    }
+
+    expectReference(0, 'int', 9);
+    expectReference(1, 'String', 19);
+    expectReference(2, 'Object', 36);
+  }
+
+  void test_parseCommentReferences_complex() {
+    CompilationUnit unit = parseCompilationUnit('''
+/// This dartdoc comment [should] be ignored
+@Annotation
+/// This dartdoc comment is [included].
+// a non dartdoc comment [inbetween]
+/// See [int] and [String] but `not [a]`
+/// ```
+/// This [code] block should be ignored
+/// ```
+/// and [Object].
+abstract class Foo {}
+''');
+    ClassDeclaration clazz = unit.declarations[0];
+    Comment comment = clazz.documentationComment;
+    expect(clazz.isAbstract, isTrue);
+    List<CommentReference> references = comment.references;
+    expect(references, hasLength(4));
+
+    expectReference(int index, String expectedText, int expectedOffset) {
+      CommentReference reference = references[index];
+      expect(reference.identifier.name, expectedText);
+      expect(reference.offset, expectedOffset);
+    }
+
+    expectReference(0, 'included', 86);
+    expectReference(1, 'int', 143);
+    expectReference(2, 'String', 153);
+    expectReference(3, 'Object', 240);
+  }
+
+  void test_parseCommentReferences_multiLine() {
+    DocumentationCommentToken token = DocumentationCommentToken(
+        TokenType.MULTI_LINE_COMMENT, "/** xxx [a] yyy [bb] zzz */", 3);
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[token];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(2));
+    {
+      CommentReference reference = references[0];
+      expect(reference, isNotNull);
+      expect(reference.identifier, isNotNull);
+      expect(reference.offset, 12);
+      Token referenceToken = reference.identifier.beginToken;
+      expect(referenceToken.offset, 12);
+      expect(referenceToken.lexeme, 'a');
+    }
+    {
+      CommentReference reference = references[1];
+      expect(reference, isNotNull);
+      expect(reference.identifier, isNotNull);
+      expect(reference.offset, 20);
+      Token referenceToken = reference.identifier.beginToken;
+      expect(referenceToken.offset, 20);
+      expect(referenceToken.lexeme, 'bb');
+    }
+  }
+
+  void test_parseCommentReferences_notClosed_noIdentifier() {
+    DocumentationCommentToken docToken = DocumentationCommentToken(
+        TokenType.MULTI_LINE_COMMENT, "/** [ some text", 5);
+    createParser('');
+    List<CommentReference> references =
+        parser.parseCommentReferences(<DocumentationCommentToken>[docToken]);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    Token referenceToken = reference.identifier.beginToken;
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.identifier.isSynthetic, isTrue);
+    expect(reference.identifier.name, "");
+    // Should end with EOF token.
+    Token nextToken = referenceToken.next;
+    expect(nextToken, isNotNull);
+    expect(nextToken.type, TokenType.EOF);
+  }
+
+  void test_parseCommentReferences_notClosed_withIdentifier() {
+    DocumentationCommentToken docToken = DocumentationCommentToken(
+        TokenType.MULTI_LINE_COMMENT, "/** [namePrefix some text", 5);
+    createParser('');
+    List<CommentReference> references =
+        parser.parseCommentReferences(<DocumentationCommentToken>[docToken]);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    Token referenceToken = reference.identifier.beginToken;
+    expect(reference, isNotNull);
+    expect(referenceToken, same(reference.beginToken));
+    expect(reference.identifier, isNotNull);
+    expect(reference.identifier.isSynthetic, isFalse);
+    expect(reference.identifier.name, "namePrefix");
+    // Should end with EOF token.
+    Token nextToken = referenceToken.next;
+    expect(nextToken, isNotNull);
+    expect(nextToken.type, TokenType.EOF);
+  }
+
+  void test_parseCommentReferences_singleLine() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.SINGLE_LINE_COMMENT, "/// xxx [a] yyy [b] zzz", 3),
+      DocumentationCommentToken(TokenType.SINGLE_LINE_COMMENT, "/// x [c]", 28)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(3));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 12);
+    reference = references[1];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 20);
+    reference = references[2];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 35);
+  }
+
+  void test_parseCommentReferences_skipCodeBlock_4spaces_block() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
+          "/**\n *     a[i]\n * non-code line\n */", 3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, isEmpty);
+  }
+
+  void test_parseCommentReferences_skipCodeBlock_4spaces_lines() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.SINGLE_LINE_COMMENT, "/// Code block:", 0),
+      DocumentationCommentToken(
+          TokenType.SINGLE_LINE_COMMENT, "///     a[i] == b[i]", 0)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, isEmpty);
+  }
+
+  void test_parseCommentReferences_skipCodeBlock_bracketed() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.MULTI_LINE_COMMENT, "/** [:xxx [a] yyy:] [b] zzz */", 3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 24);
+  }
+
+  void test_parseCommentReferences_skipCodeBlock_gitHub() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.MULTI_LINE_COMMENT, "/** `a[i]` and [b] */", 0)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 16);
+  }
+
+  void test_parseCommentReferences_skipCodeBlock_gitHub_multiLine() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.MULTI_LINE_COMMENT,
+          r'''
+/**
+ * First.
+ * ```dart
+ * Some [int] reference.
+ * ```
+ * Last.
+ */
+''',
+          3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, isEmpty);
+  }
+
+  void test_parseCommentReferences_skipCodeBlock_gitHub_multiLine_lines() {
+    String commentText = r'''
+/// First.
+/// ```dart
+/// Some [int] reference.
+/// ```
+/// Last.
+''';
+    List<DocumentationCommentToken> tokens = commentText
+        .split('\n')
+        .map((line) =>
+            DocumentationCommentToken(TokenType.SINGLE_LINE_COMMENT, line, 0))
+        .toList();
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, isEmpty);
+  }
+
+  void test_parseCommentReferences_skipCodeBlock_gitHub_notTerminated() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.MULTI_LINE_COMMENT, "/** `a[i] and [b] */", 0)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(2));
+  }
+
+  void test_parseCommentReferences_skipCodeBlock_spaces() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
+          "/**\n *     a[i]\n * xxx [i] zzz\n */", 3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 27);
+  }
+
+  @failingTest
+  void test_parseCommentReferences_skipLink_direct_multiLine() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.MULTI_LINE_COMMENT,
+          '''
+/**
+ * [a link split across multiple
+ * lines](http://www.google.com) [b] zzz
+ */
+''',
+          3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 74);
+  }
+
+  void test_parseCommentReferences_skipLink_direct_singleLine() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
+          "/** [a](http://www.google.com) [b] zzz */", 3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 35);
+  }
+
+  @failingTest
+  void test_parseCommentReferences_skipLink_reference_multiLine() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.MULTI_LINE_COMMENT,
+          '''
+/**
+ * [a link split across multiple
+ * lines][c] [b] zzz
+ */
+''',
+          3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 54);
+  }
+
+  void test_parseCommentReferences_skipLink_reference_singleLine() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(
+          TokenType.MULTI_LINE_COMMENT, "/** [a][c] [b] zzz */", 3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 15);
+  }
+
+  void test_parseCommentReferences_skipLinkDefinition() {
+    List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+      DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
+          "/** [a]: http://www.google.com (Google) [b] zzz */", 3)
+    ];
+    createParser('');
+    List<CommentReference> references = parser.parseCommentReferences(tokens);
+    expectNotNullIfNoErrors(references);
+    assertNoErrors();
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.identifier, isNotNull);
+    expect(reference.offset, 44);
+  }
+
+  void test_parseConfiguration_noOperator_dottedIdentifier() {
+    createParser("if (a.b) 'c.dart'");
+    Configuration configuration = parser.parseConfiguration();
+    expectNotNullIfNoErrors(configuration);
+    assertNoErrors();
+    expect(configuration.ifKeyword, isNotNull);
+    expect(configuration.leftParenthesis, isNotNull);
+    expectDottedName(configuration.name, ["a", "b"]);
+    expect(configuration.equalToken, isNull);
+    expect(configuration.value, isNull);
+    expect(configuration.rightParenthesis, isNotNull);
+    expect(configuration.uri, isNotNull);
+  }
+
+  void test_parseConfiguration_noOperator_simpleIdentifier() {
+    createParser("if (a) 'b.dart'");
+    Configuration configuration = parser.parseConfiguration();
+    expectNotNullIfNoErrors(configuration);
+    assertNoErrors();
+    expect(configuration.ifKeyword, isNotNull);
+    expect(configuration.leftParenthesis, isNotNull);
+    expectDottedName(configuration.name, ["a"]);
+    expect(configuration.equalToken, isNull);
+    expect(configuration.value, isNull);
+    expect(configuration.rightParenthesis, isNotNull);
+    expect(configuration.uri, isNotNull);
+  }
+
+  void test_parseConfiguration_operator_dottedIdentifier() {
+    createParser("if (a.b == 'c') 'd.dart'");
+    Configuration configuration = parser.parseConfiguration();
+    expectNotNullIfNoErrors(configuration);
+    assertNoErrors();
+    expect(configuration.ifKeyword, isNotNull);
+    expect(configuration.leftParenthesis, isNotNull);
+    expectDottedName(configuration.name, ["a", "b"]);
+    expect(configuration.equalToken, isNotNull);
+    expect(configuration.value, isNotNull);
+    expect(configuration.rightParenthesis, isNotNull);
+    expect(configuration.uri, isNotNull);
+  }
+
+  void test_parseConfiguration_operator_simpleIdentifier() {
+    createParser("if (a == 'b') 'c.dart'");
+    Configuration configuration = parser.parseConfiguration();
+    expectNotNullIfNoErrors(configuration);
+    assertNoErrors();
+    expect(configuration.ifKeyword, isNotNull);
+    expect(configuration.leftParenthesis, isNotNull);
+    expectDottedName(configuration.name, ["a"]);
+    expect(configuration.equalToken, isNotNull);
+    expect(configuration.value, isNotNull);
+    expect(configuration.rightParenthesis, isNotNull);
+    expect(configuration.uri, isNotNull);
+  }
+
+  void test_parseConstructorName_named_noPrefix() {
+    ConstructorName name = parseConstructorName('A.n');
+    expectNotNullIfNoErrors(name);
+    assertNoErrors();
+    expect(name.type, isNotNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+  }
+
+  void test_parseConstructorName_named_prefixed() {
+    ConstructorName name = parseConstructorName('p.A.n');
+    expectNotNullIfNoErrors(name);
+    assertNoErrors();
+    expect(name.type, isNotNull);
+    expect(name.period, isNotNull);
+    expect(name.name, isNotNull);
+  }
+
+  void test_parseConstructorName_unnamed_noPrefix() {
+    ConstructorName name = parseConstructorName('A');
+    expectNotNullIfNoErrors(name);
+    assertNoErrors();
+    expect(name.type, isNotNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+  }
+
+  void test_parseConstructorName_unnamed_prefixed() {
+    ConstructorName name = parseConstructorName('p.A');
+    expectNotNullIfNoErrors(name);
+    assertNoErrors();
+    expect(name.type, isNotNull);
+    expect(name.period, isNull);
+    expect(name.name, isNull);
+  }
+
+  void test_parseDocumentationComment_block() {
+    createParser('/** */ class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    Comment comment = unit.declarations[0].documentationComment;
+    expectNotNullIfNoErrors(comment);
+    assertNoErrors();
+    expect(comment.isBlock, isFalse);
+    expect(comment.isDocumentation, isTrue);
+    expect(comment.isEndOfLine, isFalse);
+  }
+
+  void test_parseDocumentationComment_block_withReference() {
+    createParser('/** [a] */ class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    Comment comment = unit.declarations[0].documentationComment;
+    expectNotNullIfNoErrors(comment);
+    assertNoErrors();
+    expect(comment.isBlock, isFalse);
+    expect(comment.isDocumentation, isTrue);
+    expect(comment.isEndOfLine, isFalse);
+    NodeList<CommentReference> references = comment.references;
+    expect(references, hasLength(1));
+    CommentReference reference = references[0];
+    expect(reference, isNotNull);
+    expect(reference.offset, 5);
+  }
+
+  void test_parseDocumentationComment_endOfLine() {
+    createParser('/// \n/// \n class C {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    Comment comment = unit.declarations[0].documentationComment;
+    expectNotNullIfNoErrors(comment);
+    assertNoErrors();
+    expect(comment.isBlock, isFalse);
+    expect(comment.isDocumentation, isTrue);
+    expect(comment.isEndOfLine, isFalse);
+  }
+
+  void test_parseExtendsClause() {
+    ExtendsClause clause = parseExtendsClause('extends B');
+    expectNotNullIfNoErrors(clause);
+    assertNoErrors();
+    expect(clause.extendsKeyword, isNotNull);
+    expect(clause.superclass, isNotNull);
+    expect(clause.superclass, isTypeName);
+  }
+
+  void test_parseFunctionBody_block() {
+    createParser('{}');
+    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
+    expectNotNullIfNoErrors(functionBody);
+    assertNoErrors();
+    expect(functionBody, isBlockFunctionBody);
+    BlockFunctionBody body = functionBody;
+    expect(body.keyword, isNull);
+    expect(body.star, isNull);
+    expect(body.block, isNotNull);
+    expect(body.isAsynchronous, isFalse);
+    expect(body.isGenerator, isFalse);
+    expect(body.isSynchronous, isTrue);
+  }
+
+  void test_parseFunctionBody_block_async() {
+    createParser('async {}');
+    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
+    expectNotNullIfNoErrors(functionBody);
+    assertNoErrors();
+    expect(functionBody, isBlockFunctionBody);
+    BlockFunctionBody body = functionBody;
+    expect(body.keyword, isNotNull);
+    expect(body.keyword.lexeme, Keyword.ASYNC.lexeme);
+    expect(body.star, isNull);
+    expect(body.block, isNotNull);
+    expect(body.isAsynchronous, isTrue);
+    expect(body.isGenerator, isFalse);
+    expect(body.isSynchronous, isFalse);
+  }
+
+  void test_parseFunctionBody_block_asyncGenerator() {
+    createParser('async* {}');
+    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
+    expectNotNullIfNoErrors(functionBody);
+    assertNoErrors();
+    expect(functionBody, isBlockFunctionBody);
+    BlockFunctionBody body = functionBody;
+    expect(body.keyword, isNotNull);
+    expect(body.keyword.lexeme, Keyword.ASYNC.lexeme);
+    expect(body.star, isNotNull);
+    expect(body.block, isNotNull);
+    expect(body.isAsynchronous, isTrue);
+    expect(body.isGenerator, isTrue);
+    expect(body.isSynchronous, isFalse);
+  }
+
+  void test_parseFunctionBody_block_syncGenerator() {
+    createParser('sync* {}');
+    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
+    expectNotNullIfNoErrors(functionBody);
+    assertNoErrors();
+    expect(functionBody, isBlockFunctionBody);
+    BlockFunctionBody body = functionBody;
+    expect(body.keyword, isNotNull);
+    expect(body.keyword.lexeme, Keyword.SYNC.lexeme);
+    expect(body.star, isNotNull);
+    expect(body.block, isNotNull);
+    expect(body.isAsynchronous, isFalse);
+    expect(body.isGenerator, isTrue);
+    expect(body.isSynchronous, isTrue);
+  }
+
+  void test_parseFunctionBody_empty() {
+    createParser(';');
+    FunctionBody functionBody = parser.parseFunctionBody(true, null, false);
+    expectNotNullIfNoErrors(functionBody);
+    assertNoErrors();
+    expect(functionBody, isEmptyFunctionBody);
+    EmptyFunctionBody body = functionBody;
+    expect(body.semicolon, isNotNull);
+  }
+
+  void test_parseFunctionBody_expression() {
+    createParser('=> y;');
+    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
+    expectNotNullIfNoErrors(functionBody);
+    assertNoErrors();
+    expect(functionBody, isExpressionFunctionBody);
+    ExpressionFunctionBody body = functionBody;
+    expect(body.keyword, isNull);
+    expect(body.functionDefinition, isNotNull);
+    expect(body.expression, isNotNull);
+    expect(body.semicolon, isNotNull);
+    expect(body.isAsynchronous, isFalse);
+    expect(body.isGenerator, isFalse);
+    expect(body.isSynchronous, isTrue);
+  }
+
+  void test_parseFunctionBody_expression_async() {
+    createParser('async => y;');
+    FunctionBody functionBody = parser.parseFunctionBody(false, null, false);
+    expectNotNullIfNoErrors(functionBody);
+    assertNoErrors();
+    expect(functionBody, isExpressionFunctionBody);
+    ExpressionFunctionBody body = functionBody;
+    expect(body.keyword, isNotNull);
+    expect(body.keyword.lexeme, Keyword.ASYNC.lexeme);
+    expect(body.functionDefinition, isNotNull);
+    expect(body.expression, isNotNull);
+    expect(body.semicolon, isNotNull);
+    expect(body.isAsynchronous, isTrue);
+    expect(body.isGenerator, isFalse);
+    expect(body.isSynchronous, isFalse);
+  }
+
+  void test_parseIdentifierList_multiple() {
+    List<SimpleIdentifier> list = parseIdentifierList('a, b, c');
+    expectNotNullIfNoErrors(list);
+    assertNoErrors();
+    expect(list, hasLength(3));
+  }
+
+  void test_parseIdentifierList_single() {
+    List<SimpleIdentifier> list = parseIdentifierList('a');
+    expectNotNullIfNoErrors(list);
+    assertNoErrors();
+    expect(list, hasLength(1));
+  }
+
+  void test_parseImplementsClause_multiple() {
+    ImplementsClause clause = parseImplementsClause('implements A, B, C');
+    expectNotNullIfNoErrors(clause);
+    assertNoErrors();
+    expect(clause.interfaces, hasLength(3));
+    expect(clause.implementsKeyword, isNotNull);
+  }
+
+  void test_parseImplementsClause_single() {
+    ImplementsClause clause = parseImplementsClause('implements A');
+    expectNotNullIfNoErrors(clause);
+    assertNoErrors();
+    expect(clause.interfaces, hasLength(1));
+    expect(clause.implementsKeyword, isNotNull);
+  }
+
+  void test_parseInstanceCreation_keyword_33647() {
+    enableOptionalNewAndConst = true;
+    CompilationUnit unit = parseCompilationUnit('''
+var c = new Future<int>.sync(() => 3).then<int>((e) => e);
+''');
+    expect(unit, isNotNull);
+    TopLevelVariableDeclaration v = unit.declarations[0];
+    MethodInvocation init = v.variables.variables[0].initializer;
+    expect(init.methodName.name, 'then');
+    NodeList<TypeAnnotation> typeArg = init.typeArguments.arguments;
+    expect(typeArg, hasLength(1));
+    expect(typeArg[0].beginToken.lexeme, 'int');
+  }
+
+  void test_parseInstanceCreation_noKeyword_33647() {
+    enableOptionalNewAndConst = true;
+    CompilationUnit unit = parseCompilationUnit('''
+var c = Future<int>.sync(() => 3).then<int>((e) => e);
+''');
+    expect(unit, isNotNull);
+    TopLevelVariableDeclaration v = unit.declarations[0];
+    MethodInvocation init = v.variables.variables[0].initializer;
+    expect(init.methodName.name, 'then');
+    NodeList<TypeAnnotation> typeArg = init.typeArguments.arguments;
+    expect(typeArg, hasLength(1));
+    expect(typeArg[0].beginToken.lexeme, 'int');
+  }
+
+  void test_parseInstanceCreation_noKeyword_noPrefix() {
+    enableOptionalNewAndConst = true;
+    createParser('f() => C<E>.n();');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    FunctionDeclaration f = unit.declarations[0];
+    ExpressionFunctionBody body = f.functionExpression.body;
+    expect(body.expression, isInstanceCreationExpression);
+    InstanceCreationExpressionImpl creation = body.expression;
+    expect(creation.keyword, isNull);
+    ConstructorName constructorName = creation.constructorName;
+    expect(constructorName.type.toSource(), 'C<E>');
+    expect(constructorName.period, isNotNull);
+    expect(constructorName.name, isNotNull);
+    expect(creation.argumentList, isNotNull);
+    expect(creation.typeArguments, isNull);
+  }
+
+  void test_parseInstanceCreation_noKeyword_noPrefix_34403() {
+    enableOptionalNewAndConst = true;
+    createParser('f() => C<E>.n<B>();');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    FunctionDeclaration f = unit.declarations[0];
+    ExpressionFunctionBody body = f.functionExpression.body;
+    expect(body.expression, isInstanceCreationExpression);
+    InstanceCreationExpressionImpl creation = body.expression;
+    expect(creation.keyword, isNull);
+    ConstructorName constructorName = creation.constructorName;
+    expect(constructorName.type.toSource(), 'C<E>');
+    expect(constructorName.period, isNotNull);
+    expect(constructorName.name, isNotNull);
+    expect(creation.argumentList, isNotNull);
+    expect(creation.typeArguments.arguments, hasLength(1));
+  }
+
+  void test_parseInstanceCreation_noKeyword_prefix() {
+    enableOptionalNewAndConst = true;
+    createParser('f() => p.C<E>.n();');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    FunctionDeclaration f = unit.declarations[0];
+    ExpressionFunctionBody body = f.functionExpression.body;
+    expect(body.expression, isInstanceCreationExpression);
+    InstanceCreationExpression creation = body.expression;
+    expect(creation.keyword, isNull);
+    ConstructorName constructorName = creation.constructorName;
+    expect(constructorName.type.toSource(), 'p.C<E>');
+    expect(constructorName.period, isNotNull);
+    expect(constructorName.name, isNotNull);
+    expect(creation.argumentList, isNotNull);
+  }
+
+  void test_parseInstanceCreation_noKeyword_varInit() {
+    enableOptionalNewAndConst = true;
+    createParser('''
+class C<T, S> {}
+void main() {final c = C<int, int Function(String)>();}
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    FunctionDeclaration f = unit.declarations[1];
+    BlockFunctionBody body = f.functionExpression.body;
+    VariableDeclarationStatement statement = body.block.statements[0];
+    VariableDeclaration variable = statement.variables.variables[0];
+    MethodInvocation creation = variable.initializer;
+    expect(creation.methodName.name, 'C');
+    expect(creation.typeArguments.toSource(), '<int, int Function(String)>');
+  }
+
+  void test_parseLibraryIdentifier_builtin() {
+    String name = "deferred";
+    LibraryIdentifier identifier = parseLibraryIdentifier(name);
+    expectNotNullIfNoErrors(identifier);
+    assertNoErrors();
+    expect(identifier.name, name);
+    expect(identifier.beginToken.type.isBuiltIn, isTrue);
+  }
+
+  void test_parseLibraryIdentifier_invalid() {
+    parseCompilationUnit('library <myLibId>;', errors: [
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 7),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1),
+    ]);
+  }
+
+  void test_parseLibraryIdentifier_multiple() {
+    String name = "a.b.c";
+    LibraryIdentifier identifier = parseLibraryIdentifier(name);
+    expectNotNullIfNoErrors(identifier);
+    assertNoErrors();
+    expect(identifier.name, name);
+  }
+
+  void test_parseLibraryIdentifier_pseudo() {
+    String name = "await";
+    LibraryIdentifier identifier = parseLibraryIdentifier(name);
+    expectNotNullIfNoErrors(identifier);
+    assertNoErrors();
+    expect(identifier.name, name);
+    expect(identifier.beginToken.type.isPseudo, isTrue);
+  }
+
+  void test_parseLibraryIdentifier_single() {
+    String name = "a";
+    LibraryIdentifier identifier = parseLibraryIdentifier(name);
+    expectNotNullIfNoErrors(identifier);
+    assertNoErrors();
+    expect(identifier.name, name);
+  }
+
+  void test_parseOptionalReturnType() {
+    // TODO(brianwilkerson) Implement tests for this method.
+  }
+
+  void test_parseReturnStatement_noValue() {
+    ReturnStatement statement = parseStatement('return;');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+    expect(statement.returnKeyword, isNotNull);
+    expect(statement.expression, isNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseReturnStatement_value() {
+    ReturnStatement statement = parseStatement('return x;');
+    expectNotNullIfNoErrors(statement);
+    assertNoErrors();
+    expect(statement.returnKeyword, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseStatement_function_noReturnType() {
+    createParser('''
+Function<A>(core.List<core.int> x) m() => null;
+''');
+    Statement statement = parser.parseStatement2();
+    expect(statement, isFunctionDeclarationStatement);
+    expect(
+        (statement as FunctionDeclarationStatement)
+            .functionDeclaration
+            .functionExpression
+            .body,
+        isExpressionFunctionBody);
+  }
+
+  void test_parseStatements_multiple() {
+    parseStatementList("return; return;", 2);
+  }
+
+  void test_parseStatements_single() {
+    parseStatementList("return;", 1);
+  }
+
+  void test_parseTypeAnnotation_function_noReturnType_noParameters() {
+    createParser('Function()');
+    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+    expect(functionType.returnType, isNull);
+    expect(functionType.functionKeyword, isNotNull);
+    expect(functionType.typeParameters, isNull);
+    FormalParameterList parameterList = functionType.parameters;
+    expect(parameterList, isNotNull);
+    expect(parameterList.parameters, hasLength(0));
+  }
+
+  void test_parseTypeAnnotation_function_noReturnType_parameters() {
+    createParser('Function(int, int)');
+    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+    expect(functionType.returnType, isNull);
+    expect(functionType.functionKeyword, isNotNull);
+    expect(functionType.typeParameters, isNull);
+    FormalParameterList parameterList = functionType.parameters;
+    expect(parameterList, isNotNull);
+    NodeList<FormalParameter> parameters = parameterList.parameters;
+    expect(parameters, hasLength(2));
+
+    expect(parameters[0], isSimpleFormalParameter);
+    SimpleFormalParameter parameter = parameters[0];
+    expect(parameter.identifier, isNull);
+    expect(parameter.type, isTypeName);
+    expect((parameter.type as TypeName).name.name, 'int');
+
+    expect(parameters[1], isSimpleFormalParameter);
+    parameter = parameters[1];
+    expect(parameter.identifier, isNull);
+    expect(parameter.type, isTypeName);
+    expect((parameter.type as TypeName).name.name, 'int');
+  }
+
+  void test_parseTypeAnnotation_function_noReturnType_typeParameters() {
+    createParser('Function<S, T>()');
+    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+    expect(functionType.returnType, isNull);
+    expect(functionType.functionKeyword, isNotNull);
+    TypeParameterList typeParameters = functionType.typeParameters;
+    expect(typeParameters, isNotNull);
+    expect(typeParameters.typeParameters, hasLength(2));
+    FormalParameterList parameterList = functionType.parameters;
+    expect(parameterList, isNotNull);
+    expect(parameterList.parameters, hasLength(0));
+  }
+
+  void
+      test_parseTypeAnnotation_function_noReturnType_typeParameters_parameters() {
+    createParser('Function<T>(String, {T t})');
+    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+    expect(functionType.returnType, isNull);
+    expect(functionType.functionKeyword, isNotNull);
+    TypeParameterList typeParameters = functionType.typeParameters;
+    expect(typeParameters, isNotNull);
+    expect(typeParameters.typeParameters, hasLength(1));
+    FormalParameterList parameterList = functionType.parameters;
+    expect(parameterList, isNotNull);
+    expect(parameterList.parameters, hasLength(2));
+  }
+
+  void test_parseTypeAnnotation_function_returnType_classFunction() {
+    createParser('Function');
+    TypeName functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+  }
+
+  void test_parseTypeAnnotation_function_returnType_function() {
+    createParser('A Function(B, C) Function(D)');
+    // TODO(scheglov) improve the test to verify also the node properties
+    var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType;
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+  }
+
+  void test_parseTypeAnnotation_function_returnType_noParameters() {
+    createParser('List<int> Function()');
+    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.functionKeyword, isNotNull);
+    expect(functionType.typeParameters, isNull);
+    FormalParameterList parameterList = functionType.parameters;
+    expect(parameterList, isNotNull);
+    expect(parameterList.parameters, hasLength(0));
+  }
+
+  void test_parseTypeAnnotation_function_returnType_parameters() {
+    createParser('List<int> Function(String s, int i)');
+    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.functionKeyword, isNotNull);
+    expect(functionType.typeParameters, isNull);
+    FormalParameterList parameterList = functionType.parameters;
+    expect(parameterList, isNotNull);
+    NodeList<FormalParameter> parameters = parameterList.parameters;
+    expect(parameters, hasLength(2));
+
+    expect(parameters[0], isSimpleFormalParameter);
+    SimpleFormalParameter parameter = parameters[0];
+    expect(parameter.identifier, isNotNull);
+    expect(parameter.identifier.name, 's');
+    expect(parameter.type, isTypeName);
+    expect((parameter.type as TypeName).name.name, 'String');
+
+    expect(parameters[1], isSimpleFormalParameter);
+    parameter = parameters[1];
+    expect(parameter.identifier, isNotNull);
+    expect(parameter.identifier.name, 'i');
+    expect(parameter.type, isTypeName);
+    expect((parameter.type as TypeName).name.name, 'int');
+  }
+
+  void test_parseTypeAnnotation_function_returnType_simple() {
+    createParser('A Function(B, C)');
+    // TODO(scheglov) improve the test to verify also the node properties
+    var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType;
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+  }
+
+  void test_parseTypeAnnotation_function_returnType_typeParameters() {
+    createParser('List<T> Function<T>()');
+    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.functionKeyword, isNotNull);
+    TypeParameterList typeParameters = functionType.typeParameters;
+    expect(typeParameters, isNotNull);
+    expect(typeParameters.typeParameters, hasLength(1));
+    FormalParameterList parameterList = functionType.parameters;
+    expect(parameterList, isNotNull);
+    expect(parameterList.parameters, hasLength(0));
+  }
+
+  void
+      test_parseTypeAnnotation_function_returnType_typeParameters_parameters() {
+    createParser('List<T> Function<T>(String s, [T])');
+    GenericFunctionType functionType = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.functionKeyword, isNotNull);
+    TypeParameterList typeParameters = functionType.typeParameters;
+    expect(typeParameters, isNotNull);
+    expect(typeParameters.typeParameters, hasLength(1));
+    FormalParameterList parameterList = functionType.parameters;
+    expect(parameterList, isNotNull);
+    expect(parameterList.parameters, hasLength(2));
+  }
+
+  void test_parseTypeAnnotation_function_returnType_withArguments() {
+    createParser('A<B> Function(C)');
+    // TODO(scheglov) improve this test to verify also the node properties
+    var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType;
+    expectNotNullIfNoErrors(functionType);
+    assertNoErrors();
+  }
+
+  void test_parseTypeAnnotation_named() {
+    createParser('A<B>');
+    TypeName typeName = parser.parseTypeAnnotation(false);
+    expectNotNullIfNoErrors(typeName);
+    assertNoErrors();
+  }
+
+  void test_parseTypeArgumentList_empty() {
+    createParser('<>');
+    TypeArgumentList argumentList = parser.parseTypeArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    listener.assertErrorsWithCodes([ParserErrorCode.EXPECTED_TYPE_NAME]);
+    expect(argumentList.leftBracket, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+    expect(argumentList.rightBracket, isNotNull);
+  }
+
+  void test_parseTypeArgumentList_multiple() {
+    createParser('<int, int, int>');
+    TypeArgumentList argumentList = parser.parseTypeArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    expect(argumentList.leftBracket, isNotNull);
+    expect(argumentList.arguments, hasLength(3));
+    expect(argumentList.rightBracket, isNotNull);
+  }
+
+  void test_parseTypeArgumentList_nested() {
+    createParser('<A<B>>');
+    TypeArgumentList argumentList = parser.parseTypeArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    expect(argumentList.leftBracket, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+    TypeName argument = argumentList.arguments[0];
+    expect(argument, isNotNull);
+    TypeArgumentList innerList = argument.typeArguments;
+    expect(innerList, isNotNull);
+    expect(innerList.arguments, hasLength(1));
+    expect(argumentList.rightBracket, isNotNull);
+  }
+
+  void test_parseTypeArgumentList_nested_withComment_double() {
+    createParser('<A<B /* 0 */ >>');
+    TypeArgumentList argumentList = parser.parseTypeArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    expect(argumentList.leftBracket, isNotNull);
+    expect(argumentList.rightBracket, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+
+    TypeName argument = argumentList.arguments[0];
+    expect(argument, isNotNull);
+
+    TypeArgumentList innerList = argument.typeArguments;
+    expect(innerList, isNotNull);
+    expect(innerList.leftBracket, isNotNull);
+    expect(innerList.arguments, hasLength(1));
+    expect(innerList.rightBracket, isNotNull);
+    expect(innerList.rightBracket.precedingComments, isNotNull);
+  }
+
+  void test_parseTypeArgumentList_nested_withComment_tripple() {
+    createParser('<A<B<C /* 0 */ >>>');
+    TypeArgumentList argumentList = parser.parseTypeArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    expect(argumentList.leftBracket, isNotNull);
+    expect(argumentList.rightBracket, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+
+    TypeName argument = argumentList.arguments[0];
+    expect(argument, isNotNull);
+
+    TypeArgumentList innerList = argument.typeArguments;
+    expect(innerList, isNotNull);
+    expect(innerList.leftBracket, isNotNull);
+    expect(innerList.arguments, hasLength(1));
+    expect(innerList.rightBracket, isNotNull);
+
+    TypeName innerArgument = innerList.arguments[0];
+    expect(innerArgument, isNotNull);
+
+    TypeArgumentList innerInnerList = innerArgument.typeArguments;
+    expect(innerInnerList, isNotNull);
+    expect(innerInnerList.leftBracket, isNotNull);
+    expect(innerInnerList.arguments, hasLength(1));
+    expect(innerInnerList.rightBracket, isNotNull);
+    expect(innerInnerList.rightBracket.precedingComments, isNotNull);
+  }
+
+  void test_parseTypeArgumentList_single() {
+    createParser('<int>');
+    TypeArgumentList argumentList = parser.parseTypeArgumentList();
+    expectNotNullIfNoErrors(argumentList);
+    assertNoErrors();
+    expect(argumentList.leftBracket, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+    expect(argumentList.rightBracket, isNotNull);
+  }
+
+  void test_parseTypeName_parameterized() {
+    createParser('List<int>');
+    TypeName typeName = parser.parseTypeName(false);
+    expectNotNullIfNoErrors(typeName);
+    assertNoErrors();
+    expect(typeName.name, isNotNull);
+    expect(typeName.typeArguments, isNotNull);
+  }
+
+  void test_parseTypeName_simple() {
+    createParser('int');
+    TypeName typeName = parser.parseTypeName(false);
+    expectNotNullIfNoErrors(typeName);
+    assertNoErrors();
+    expect(typeName.name, isNotNull);
+    expect(typeName.typeArguments, isNull);
+  }
+
+  void test_parseTypeParameter_bounded_functionType_noReturn() {
+    createParser('A extends Function(int)');
+    TypeParameter parameter = parser.parseTypeParameter();
+    expectNotNullIfNoErrors(parameter);
+    assertNoErrors();
+    expect(parameter.bound, isGenericFunctionType);
+    expect(parameter.extendsKeyword, isNotNull);
+    expect(parameter.name, isNotNull);
+  }
+
+  void test_parseTypeParameter_bounded_functionType_return() {
+    createParser('A extends String Function(int)');
+    TypeParameter parameter = parser.parseTypeParameter();
+    expectNotNullIfNoErrors(parameter);
+    assertNoErrors();
+    expect(parameter.bound, isGenericFunctionType);
+    expect(parameter.extendsKeyword, isNotNull);
+    expect(parameter.name, isNotNull);
+  }
+
+  void test_parseTypeParameter_bounded_generic() {
+    createParser('A extends B<C>');
+    TypeParameter parameter = parser.parseTypeParameter();
+    expectNotNullIfNoErrors(parameter);
+    assertNoErrors();
+    expect(parameter.bound, isTypeName);
+    expect(parameter.extendsKeyword, isNotNull);
+    expect(parameter.name, isNotNull);
+  }
+
+  void test_parseTypeParameter_bounded_simple() {
+    createParser('A extends B');
+    TypeParameter parameter = parser.parseTypeParameter();
+    expectNotNullIfNoErrors(parameter);
+    assertNoErrors();
+    expect(parameter.bound, isTypeName);
+    expect(parameter.extendsKeyword, isNotNull);
+    expect(parameter.name, isNotNull);
+  }
+
+  void test_parseTypeParameter_simple() {
+    createParser('A');
+    TypeParameter parameter = parser.parseTypeParameter();
+    expectNotNullIfNoErrors(parameter);
+    assertNoErrors();
+    expect(parameter.bound, isNull);
+    expect(parameter.extendsKeyword, isNull);
+    expect(parameter.name, isNotNull);
+  }
+
+  void test_parseTypeParameterList_multiple() {
+    createParser('<A, B extends C, D>');
+    TypeParameterList parameterList = parser.parseTypeParameterList();
+    expectNotNullIfNoErrors(parameterList);
+    assertNoErrors();
+    expect(parameterList.leftBracket, isNotNull);
+    expect(parameterList.rightBracket, isNotNull);
+    expect(parameterList.typeParameters, hasLength(3));
+  }
+
+  void test_parseTypeParameterList_parameterizedWithTrailingEquals() {
+    createParser('<A extends B<E>>=', expectedEndOffset: 16);
+    TypeParameterList parameterList = parser.parseTypeParameterList();
+    expectNotNullIfNoErrors(parameterList);
+    assertNoErrors();
+    expect(parameterList.leftBracket, isNotNull);
+    expect(parameterList.rightBracket, isNotNull);
+    expect(parameterList.typeParameters, hasLength(1));
+  }
+
+  void test_parseTypeParameterList_parameterizedWithTrailingEquals2() {
+    createParser('<A extends B<E /* foo */ >>=', expectedEndOffset: 27);
+    TypeParameterList parameterList = parser.parseTypeParameterList();
+    expectNotNullIfNoErrors(parameterList);
+    assertNoErrors();
+    expect(parameterList.leftBracket, isNotNull);
+    expect(parameterList.rightBracket, isNotNull);
+    expect(parameterList.typeParameters, hasLength(1));
+    TypeParameter typeParameter = parameterList.typeParameters[0];
+    expect(typeParameter.name.name, 'A');
+    TypeName bound = typeParameter.bound;
+    expect(bound.name.name, 'B');
+    TypeArgumentList typeArguments = bound.typeArguments;
+    expect(typeArguments.arguments, hasLength(1));
+    expect(typeArguments.rightBracket, isNotNull);
+    expect(typeArguments.rightBracket.precedingComments.lexeme, '/* foo */');
+    TypeName argument = typeArguments.arguments[0];
+    expect(argument.name.name, 'E');
+  }
+
+  void test_parseTypeParameterList_single() {
+    createParser('<<A>', expectedEndOffset: 0);
+    TypeParameterList parameterList = parser.parseTypeParameterList();
+    // TODO(danrubel): Consider splitting `<<` and marking the first `<`
+    // as an unexpected token.
+    expect(parameterList, isNull);
+    assertNoErrors();
+  }
+
+  void test_parseTypeParameterList_withTrailingEquals() {
+    createParser('<A>=', expectedEndOffset: 3);
+    TypeParameterList parameterList = parser.parseTypeParameterList();
+    expectNotNullIfNoErrors(parameterList);
+    assertNoErrors();
+    expect(parameterList.leftBracket, isNotNull);
+    expect(parameterList.rightBracket, isNotNull);
+    expect(parameterList.typeParameters, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_equals() {
+    VariableDeclaration declaration = parseVariableDeclaration('var a = b;');
+    expectNotNullIfNoErrors(declaration);
+    assertNoErrors();
+    expect(declaration.name, isNotNull);
+    expect(declaration.equals, isNotNull);
+    expect(declaration.initializer, isNotNull);
+  }
+
+  void test_parseVariableDeclaration_final_late() {
+    var statement = parseStatement('final late a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertErrors(
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]);
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late() {
+    var statement = parseStatement('late a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
+    ]);
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late_final() {
+    var statement = parseStatement('late final a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertNoErrors();
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late_init() {
+    var statement = parseStatement('late a = 0;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
+    ]);
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late_type() {
+    var statement = parseStatement('late A a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertNoErrors();
+    expect(declarationList.lateKeyword, isNotNull);
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNotNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late_var() {
+    var statement = parseStatement('late var a;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertNoErrors();
+    expect(declarationList.lateKeyword, isNotNull);
+    expect(declarationList.keyword?.lexeme, 'var');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_late_var_init() {
+    var statement = parseStatement('late var a = 0;', featureSet: nonNullable)
+        as VariableDeclarationStatement;
+    var declarationList = statement.variables;
+    assertNoErrors();
+    expect(declarationList.lateKeyword, isNotNull);
+    expect(declarationList.keyword?.lexeme, 'var');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclaration_noEquals() {
+    VariableDeclaration declaration = parseVariableDeclaration('var a;');
+    expectNotNullIfNoErrors(declaration);
+    assertNoErrors();
+    expect(declaration.name, isNotNull);
+    expect(declaration.equals, isNull);
+    expect(declaration.initializer, isNull);
+  }
+
+  void test_parseWithClause_multiple() {
+    WithClause clause = parseWithClause('with A, B, C');
+    expectNotNullIfNoErrors(clause);
+    assertNoErrors();
+    expect(clause.withKeyword, isNotNull);
+    expect(clause.mixinTypes, hasLength(3));
+  }
+
+  void test_parseWithClause_single() {
+    WithClause clause = parseWithClause('with M');
+    expectNotNullIfNoErrors(clause);
+    assertNoErrors();
+    expect(clause.withKeyword, isNotNull);
+    expect(clause.mixinTypes, hasLength(1));
+  }
+
+  void test_typeAlias_37733() {
+    // https://github.com/dart-lang/sdk/issues/37733
+    var unit = parseCompilationUnit(r'typedef K=Function(<>($', errors: [
+      expectedError(CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 19, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 1),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
+      expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1),
+    ]);
+    var typeAlias = unit.declarations[0] as GenericTypeAlias;
+    expect(typeAlias.name.toSource(), 'K');
+    var functionType = typeAlias.functionType;
+    expect(functionType.parameters.parameters, hasLength(1));
+    var parameter = functionType.parameters.parameters[0];
+    expect(parameter.identifier, isNotNull);
+  }
+
+  void test_typeAlias_parameter_missingIdentifier_37733() {
+    // https://github.com/dart-lang/sdk/issues/37733
+    var unit = parseCompilationUnit(r'typedef T=Function(<S>());', errors: [
+      expectedError(CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 19, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
+    ]);
+    var typeAlias = unit.declarations[0] as GenericTypeAlias;
+    expect(typeAlias.name.toSource(), 'T');
+    var functionType = typeAlias.functionType;
+    expect(functionType.parameters.parameters, hasLength(1));
+    var parameter = functionType.parameters.parameters[0];
+    expect(parameter.identifier, isNotNull);
+  }
+}
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index c26ac85..d1a5b58 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -954,7 +954,7 @@
     verifyTestResolved();
 
     expect(
-      findElement.functionTypeAlias('F').metadata,
+      findElement.typeAlias('F').metadata,
       hasLength(1),
     );
 
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart
index 3ec4b21..3282f36 100644
--- a/pkg/analyzer/test/generated/source_factory_test.dart
+++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -21,12 +21,6 @@
   });
 }
 
-Source createSource({String path, String uri}) =>
-    //TODO(pquitslund): find some way to pass an actual URI into source creation
-    MemoryResourceProvider()
-        .getFile(path)
-        .createSource(uri != null ? Uri.parse(uri) : null);
-
 class AbsoluteUriResolver extends UriResolver {
   final MemoryResourceProvider resourceProvider;
 
diff --git a/pkg/analyzer/test/generated/statement_parser_test.dart b/pkg/analyzer/test/generated/statement_parser_test.dart
new file mode 100644
index 0000000..189d673
--- /dev/null
+++ b/pkg/analyzer/test/generated/statement_parser_test.dart
@@ -0,0 +1,1777 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart' as analyzer;
+import 'package:analyzer/dart/ast/token.dart' show TokenType;
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(StatementParserTest);
+  });
+}
+
+/// Tests of the fasta parser based on [StatementParserTestMixin].
+@reflectiveTest
+class StatementParserTest extends FastaParserTestCase {
+  void test_35177() {
+    ExpressionStatement statement = parseStatement('(f)()<int>();');
+
+    FunctionExpressionInvocation funct1 = statement.expression;
+    NodeList<TypeAnnotation> typeArgs = funct1.typeArguments.arguments;
+    expect(typeArgs, hasLength(1));
+    TypeName typeName = typeArgs[0];
+    expect(typeName.name.name, 'int');
+    expect(funct1.argumentList.arguments, hasLength(0));
+
+    FunctionExpressionInvocation funct2 = funct1.function;
+    expect(funct2.typeArguments, isNull);
+    expect(funct2.argumentList.arguments, hasLength(0));
+
+    ParenthesizedExpression expression = funct2.function;
+    SimpleIdentifier identifier = expression.expression;
+    expect(identifier.name, 'f');
+  }
+
+  void test_invalid_typeArg_34850() {
+    var unit = parseCompilationUnit('foo Future<List<int>> bar() {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 4),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 6),
+      expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 22, 3),
+    ]);
+    // Validate that recovery has properly updated the token stream.
+    analyzer.Token token = unit.beginToken;
+    while (!token.isEof) {
+      expect(token.type, isNot(TokenType.GT_GT));
+      analyzer.Token next = token.next;
+      expect(next.previous, token);
+      token = next;
+    }
+  }
+
+  void test_invalid_typeParamAnnotation() {
+    parseCompilationUnit('main() { C<@Foo T> v; }', errors: [
+      expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 4)
+    ]);
+  }
+
+  void test_invalid_typeParamAnnotation2() {
+    parseCompilationUnit('main() { C<@Foo.bar(1) T> v; }', errors: [
+      expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 11, 11)
+    ]);
+  }
+
+  void test_invalid_typeParamAnnotation3() {
+    parseCompilationUnit('''
+main() {
+  C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T,
+    F Function<G>(int, String, {Bar b}),
+    void Function<H>(int i, [String j, K]),
+    A<B<C>>,
+    W<X<Y<Z>>>
+  > v;
+}''', errors: [
+      expectedError(ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT, 13, 63)
+    ]);
+  }
+
+  void test_parseAssertStatement() {
+    var statement = parseStatement('assert (x);') as AssertStatement;
+    assertNoErrors();
+    expect(statement.assertKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.comma, isNull);
+    expect(statement.message, isNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseAssertStatement_messageLowPrecedence() {
+    // Using a throw expression as an assert message would be silly in
+    // practice, but it's the lowest precedence expression type, so verifying
+    // that it works should give us high confidence that other expression types
+    // will work as well.
+    var statement =
+        parseStatement('assert (x, throw "foo");') as AssertStatement;
+    assertNoErrors();
+    expect(statement.assertKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.comma, isNotNull);
+    expect(statement.message, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseAssertStatement_messageString() {
+    var statement = parseStatement('assert (x, "foo");') as AssertStatement;
+    assertNoErrors();
+    expect(statement.assertKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.comma, isNotNull);
+    expect(statement.message, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseAssertStatement_trailingComma_message() {
+    var statement = parseStatement('assert (x, "m",);') as AssertStatement;
+    assertNoErrors();
+    expect(statement.assertKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.comma, isNotNull);
+    expect(statement.message, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseAssertStatement_trailingComma_noMessage() {
+    var statement = parseStatement('assert (x,);') as AssertStatement;
+    assertNoErrors();
+    expect(statement.assertKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.comma, isNull);
+    expect(statement.message, isNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseBlock_empty() {
+    var block = parseStatement('{}') as Block;
+    assertNoErrors();
+    expect(block.leftBracket, isNotNull);
+    expect(block.statements, hasLength(0));
+    expect(block.rightBracket, isNotNull);
+  }
+
+  void test_parseBlock_nonEmpty() {
+    var block = parseStatement('{;}') as Block;
+    assertNoErrors();
+    expect(block.leftBracket, isNotNull);
+    expect(block.statements, hasLength(1));
+    expect(block.rightBracket, isNotNull);
+  }
+
+  void test_parseBreakStatement_label() {
+    LabeledStatement labeledStatement =
+        parseStatement('foo: while (true) { break foo; }');
+    WhileStatement whileStatement = labeledStatement.statement;
+    BreakStatement statement = (whileStatement.body as Block).statements[0];
+    assertNoErrors();
+    expect(statement.breakKeyword, isNotNull);
+    expect(statement.label, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseBreakStatement_noLabel() {
+    WhileStatement whileStatement = parseStatement('while (true) { break; }');
+    BreakStatement statement = (whileStatement.body as Block).statements[0];
+    assertNoErrors();
+    expect(statement.breakKeyword, isNotNull);
+    expect(statement.label, isNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseContinueStatement_label() {
+    LabeledStatement labeledStatement =
+        parseStatement('foo: while (true) { continue foo; }');
+    WhileStatement whileStatement = labeledStatement.statement;
+    ContinueStatement statement = (whileStatement.body as Block).statements[0];
+    assertNoErrors();
+    expect(statement.continueKeyword, isNotNull);
+    expect(statement.label, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseContinueStatement_noLabel() {
+    WhileStatement whileStatement =
+        parseStatement('while (true) { continue; }');
+    ContinueStatement statement = (whileStatement.body as Block).statements[0];
+    assertNoErrors();
+    expect(statement.continueKeyword, isNotNull);
+    expect(statement.label, isNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseDoStatement() {
+    var statement = parseStatement('do {} while (x);') as DoStatement;
+    assertNoErrors();
+    expect(statement.doKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    expect(statement.whileKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseElseAlone() {
+    parseCompilationUnit('main() { else return 0; } ', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 4),
+      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 9, 4),
+    ]);
+  }
+
+  void test_parseEmptyStatement() {
+    var statement = parseStatement(';') as EmptyStatement;
+    assertNoErrors();
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseForStatement_each_await() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    String code = 'await for (element in list) {}';
+    var forStatement = _parseAsyncStatement(code) as ForStatement;
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNotNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forEachParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
+    expect(forEachParts.identifier, isNotNull);
+    expect(forEachParts.inKeyword, isNotNull);
+    expect(forEachParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_await2() {
+    ForStatement forStatement = parseStatement(
+      'await for (element in list) {}',
+      inAsync: true,
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNotNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithIdentifier forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.identifier, isNotNull);
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_finalExternal() {
+    ForStatement forStatement = parseStatement(
+      'for (final external in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable.identifier.name, 'external');
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_finalRequired() {
+    ForStatement forStatement = parseStatement(
+      'for (final required in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable.identifier.name, 'required');
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_genericFunctionType() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (void Function<T>(T) element in list) {}')
+            as ForStatement;
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
+    expect(forEachParts.loopVariable, isNotNull);
+    expect(forEachParts.inKeyword, isNotNull);
+    expect(forEachParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_genericFunctionType2() {
+    ForStatement forStatement = parseStatement(
+      'for (void Function<T>(T) element in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable, isNotNull);
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_identifier() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (element in list) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forEachParts = forStatement.forLoopParts as ForEachPartsWithIdentifier;
+    expect(forEachParts.identifier, isNotNull);
+    expect(forEachParts.inKeyword, isNotNull);
+    expect(forEachParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_identifier2() {
+    ForStatement forStatement = parseStatement(
+      'for (element in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithIdentifier forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.identifier, isNotNull);
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_noType_metadata() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (@A var element in list) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
+    expect(forEachParts.loopVariable, isNotNull);
+    expect(forEachParts.loopVariable.metadata, hasLength(1));
+    expect(forEachParts.inKeyword, isNotNull);
+    expect(forEachParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_noType_metadata2() {
+    ForStatement forStatement = parseStatement(
+      'for (@A var element in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable, isNotNull);
+    expect(forLoopParts.loopVariable.metadata, hasLength(1));
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_type() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (A element in list) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
+    expect(forEachParts.loopVariable, isNotNull);
+    expect(forEachParts.inKeyword, isNotNull);
+    expect(forEachParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_type2() {
+    ForStatement forStatement = parseStatement(
+      'for (A element in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable, isNotNull);
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_var() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (var element in list) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forEachParts = forStatement.forLoopParts as ForEachPartsWithDeclaration;
+    expect(forEachParts.loopVariable, isNotNull);
+    expect(forEachParts.inKeyword, isNotNull);
+    expect(forEachParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_each_var2() {
+    ForStatement forStatement = parseStatement(
+      'for (var element in list) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.awaitKeyword, isNull);
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForEachPartsWithDeclaration forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.loopVariable, isNotNull);
+    expect(forLoopParts.inKeyword, isNotNull);
+    expect(forLoopParts.iterable, isNotNull);
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_c() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement = parseStatement('for (; i < count;) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithExpression;
+    expect(forParts.initialization, isNull);
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNotNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(0));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_c2() {
+    ForStatement forStatement = parseStatement(
+      'for (; i < count;) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.initialization, isNull);
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNotNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(0));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_cu() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (; i < count; i++) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithExpression;
+    expect(forParts.initialization, isNull);
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNotNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_cu2() {
+    ForStatement forStatement = parseStatement(
+      'for (; i < count; i++) {}',
+      featureSet: controlFlow,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.initialization, isNull);
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNotNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_ecu() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (i--; i < count; i++) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithExpression;
+    expect(forParts.initialization, isNotNull);
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNotNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_ecu2() {
+    ForStatement forStatement = parseStatement(
+      'for (i--; i < count; i++) {}',
+      featureSet: spread,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.initialization, isNotNull);
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNotNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_i() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement = parseStatement('for (var i = 0;;) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
+    VariableDeclarationList variables = forParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.metadata, hasLength(0));
+    expect(variables.variables, hasLength(1));
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(0));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_i2() {
+    ForStatement forStatement = parseStatement(
+      'for (var i = 0;;) {}',
+      featureSet: spread,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
+    VariableDeclarationList variables = forLoopParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.metadata, hasLength(0));
+    expect(variables.variables, hasLength(1));
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(0));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_i_withMetadata() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (@A var i = 0;;) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
+    VariableDeclarationList variables = forParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.metadata, hasLength(1));
+    expect(variables.variables, hasLength(1));
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(0));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_i_withMetadata2() {
+    ForStatement forStatement = parseStatement(
+      'for (@A var i = 0;;) {}',
+      featureSet: spread,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
+    VariableDeclarationList variables = forLoopParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.metadata, hasLength(1));
+    expect(variables.variables, hasLength(1));
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(0));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_ic() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (var i = 0; i < count;) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
+    VariableDeclarationList variables = forParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.variables, hasLength(1));
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNotNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(0));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_ic2() {
+    ForStatement forStatement = parseStatement(
+      'for (var i = 0; i < count;) {}',
+      featureSet: spread,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
+    VariableDeclarationList variables = forLoopParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.variables, hasLength(1));
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNotNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(0));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_icu() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (var i = 0; i < count; i++) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
+    VariableDeclarationList variables = forParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.variables, hasLength(1));
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNotNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_icu2() {
+    ForStatement forStatement = parseStatement(
+      'for (var i = 0; i < count; i++) {}',
+      featureSet: spread,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
+    VariableDeclarationList variables = forLoopParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.variables, hasLength(1));
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNotNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_iicuu() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (int i = 0, j = count; i < j; i++, j--) {}')
+            as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
+    VariableDeclarationList variables = forParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.variables, hasLength(2));
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNotNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(2));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_iicuu2() {
+    ForStatement forStatement = parseStatement(
+      'for (int i = 0, j = count; i < j; i++, j--) {}',
+      featureSet: spread,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
+    VariableDeclarationList variables = forLoopParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.variables, hasLength(2));
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNotNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(2));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_iu() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement =
+        parseStatement('for (var i = 0;; i++) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithDeclarations;
+    VariableDeclarationList variables = forParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.variables, hasLength(1));
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_iu2() {
+    ForStatement forStatement = parseStatement(
+      'for (var i = 0;; i++) {}',
+      featureSet: spread,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithDeclarations forLoopParts = forStatement.forLoopParts;
+    VariableDeclarationList variables = forLoopParts.variables;
+    expect(variables, isNotNull);
+    expect(variables.variables, hasLength(1));
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_u() {
+    // TODO(danrubel): remove this once control flow and spread collection
+    // entry parsing is enabled by default
+    var forStatement = parseStatement('for (;; i++) {}') as ForStatement;
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    var forParts = forStatement.forLoopParts as ForPartsWithExpression;
+    expect(forParts.initialization, isNull);
+    expect(forParts.leftSeparator, isNotNull);
+    expect(forParts.condition, isNull);
+    expect(forParts.rightSeparator, isNotNull);
+    expect(forParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseForStatement_loop_u2() {
+    ForStatement forStatement = parseStatement(
+      'for (;; i++) {}',
+      featureSet: spread,
+    );
+    assertNoErrors();
+    expect(forStatement.forKeyword, isNotNull);
+    expect(forStatement.leftParenthesis, isNotNull);
+    ForPartsWithExpression forLoopParts = forStatement.forLoopParts;
+    expect(forLoopParts.initialization, isNull);
+    expect(forLoopParts.leftSeparator, isNotNull);
+    expect(forLoopParts.condition, isNull);
+    expect(forLoopParts.rightSeparator, isNotNull);
+    expect(forLoopParts.updaters, hasLength(1));
+    expect(forStatement.rightParenthesis, isNotNull);
+    expect(forStatement.body, isNotNull);
+  }
+
+  void test_parseFunctionDeclarationStatement() {
+    var statement = parseStatement('void f(int p) => p * 2;')
+        as FunctionDeclarationStatement;
+    assertNoErrors();
+    expect(statement.functionDeclaration, isNotNull);
+  }
+
+  void test_parseFunctionDeclarationStatement_typeParameters() {
+    var statement =
+        parseStatement('E f<E>(E p) => p * 2;') as FunctionDeclarationStatement;
+    assertNoErrors();
+    expect(statement.functionDeclaration, isNotNull);
+    expect(statement.functionDeclaration.functionExpression.typeParameters,
+        isNotNull);
+  }
+
+  void test_parseFunctionDeclarationStatement_typeParameters_noReturnType() {
+    var statement =
+        parseStatement('f<E>(E p) => p * 2;') as FunctionDeclarationStatement;
+    assertNoErrors();
+    expect(statement.functionDeclaration, isNotNull);
+    expect(statement.functionDeclaration.functionExpression.typeParameters,
+        isNotNull);
+  }
+
+  void test_parseIfStatement_else_block() {
+    var statement = parseStatement('if (x) {} else {}') as IfStatement;
+    assertNoErrors();
+    expect(statement.ifKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.thenStatement, isNotNull);
+    expect(statement.elseKeyword, isNotNull);
+    expect(statement.elseStatement, isNotNull);
+  }
+
+  void test_parseIfStatement_else_emptyStatements() {
+    var statement = parseStatement('if (true) ; else ;') as IfStatement;
+    assertNoErrors();
+    expect(statement.ifKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.thenStatement, isNotNull);
+    expect(statement.elseKeyword, isNotNull);
+    expect(statement.elseStatement, isNotNull);
+  }
+
+  void test_parseIfStatement_else_statement() {
+    var statement = parseStatement('if (x) f(x); else f(y);') as IfStatement;
+    assertNoErrors();
+    expect(statement.ifKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.thenStatement, isNotNull);
+    expect(statement.elseKeyword, isNotNull);
+    expect(statement.elseStatement, isNotNull);
+  }
+
+  void test_parseIfStatement_noElse_block() {
+    var statement = parseStatement('if (x) {}') as IfStatement;
+    assertNoErrors();
+    expect(statement.ifKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.thenStatement, isNotNull);
+    expect(statement.elseKeyword, isNull);
+    expect(statement.elseStatement, isNull);
+  }
+
+  void test_parseIfStatement_noElse_statement() {
+    var statement = parseStatement('if (x) f(x);') as IfStatement;
+    assertNoErrors();
+    expect(statement.ifKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.thenStatement, isNotNull);
+    expect(statement.elseKeyword, isNull);
+    expect(statement.elseStatement, isNull);
+  }
+
+  void test_parseLocalVariable_external() {
+    parseStatement('external int i;', featureSet: nonNullable);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 0, 8),
+    ]);
+  }
+
+  void test_parseNonLabeledStatement_const_list_empty() {
+    var statement = parseStatement('const [];') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_const_list_nonEmpty() {
+    var statement = parseStatement('const [1, 2];') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_const_map_empty() {
+    var statement = parseStatement('const {};') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_const_map_nonEmpty() {
+    // TODO(brianwilkerson) Implement more tests for this method.
+    var statement = parseStatement("const {'a' : 1};") as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_const_object() {
+    var statement = parseStatement('const A();') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_const_object_named_typeParameters() {
+    var statement = parseStatement('const A<B>.c();') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_const_object_named_typeParameters_34403() {
+    var statement = parseStatement('const A<B>.c<C>();') as ExpressionStatement;
+    assertErrorsWithCodes(
+        [CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR]);
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_constructorInvocation() {
+    var statement = parseStatement('new C().m();') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_false() {
+    var statement = parseStatement('false;') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_functionDeclaration() {
+    var statement = parseStatement('f() {}') as FunctionDeclarationStatement;
+    assertNoErrors();
+    var function = statement.functionDeclaration.functionExpression;
+    expect(function.parameters.parameters, isEmpty);
+    expect(function.body, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_functionDeclaration_arguments() {
+    var statement =
+        parseStatement('f(void g()) {}') as FunctionDeclarationStatement;
+    assertNoErrors();
+    var function = statement.functionDeclaration.functionExpression;
+    expect(function.parameters.parameters, hasLength(1));
+    expect(function.body, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_functionExpressionIndex() {
+    var statement = parseStatement('() {}[0] = null;') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_functionInvocation() {
+    var statement = parseStatement('f();') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_invokeFunctionExpression() {
+    var statement =
+        parseStatement('(a) {return a + a;} (3);') as ExpressionStatement;
+    assertNoErrors();
+    var invocation = statement.expression as FunctionExpressionInvocation;
+
+    FunctionExpression expression = invocation.function as FunctionExpression;
+    expect(expression.parameters, isNotNull);
+    expect(expression.body, isNotNull);
+    expect(invocation.typeArguments, isNull);
+    expect(invocation.argumentList.arguments, hasLength(1));
+  }
+
+  void test_parseNonLabeledStatement_localFunction_gftReturnType() {
+    var statement = parseStatement('int Function(int) f(String s) => null;')
+        as FunctionDeclarationStatement;
+    assertNoErrors();
+    FunctionDeclaration function = statement.functionDeclaration;
+    expect(function.returnType, isGenericFunctionType);
+  }
+
+  void test_parseNonLabeledStatement_null() {
+    var statement = parseStatement('null;') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_startingWithBuiltInIdentifier() {
+    var statement = parseStatement('library.getName();') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_true() {
+    var statement = parseStatement('true;') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_typeCast() {
+    var statement = parseStatement('double.NAN as num;') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_final_namedFunction() {
+    var statement = parseStatement('final int Function = 0;')
+        as VariableDeclarationStatement;
+    assertNoErrors();
+    List<VariableDeclaration> variables = statement.variables.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'Function');
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_gftType() {
+    var statement =
+        parseStatement('int Function(int) v;') as VariableDeclarationStatement;
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    expect(variableList.type, isGenericFunctionType);
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_functionReturnType() {
+    var statement = parseStatement(
+            'Function Function(int x1, {Function x}) Function<B extends core.int>(int x) v;')
+        as VariableDeclarationStatement;
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    expect(variableList.type, isGenericFunctionType);
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_gftReturnType() {
+    var statement = parseStatement('Function(int) Function(int) v;')
+        as VariableDeclarationStatement;
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    expect(variableList.type, isGenericFunctionType);
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_gftReturnType2() {
+    var statement = parseStatement('int Function(int) Function(int) v;')
+        as VariableDeclarationStatement;
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    expect(variableList.type, isGenericFunctionType);
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_noReturnType() {
+    var statement =
+        parseStatement('Function(int) v;') as VariableDeclarationStatement;
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    expect(variableList.type, isGenericFunctionType);
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_gftType_returnType() {
+    var statement =
+        parseStatement('int Function<T>() v;') as VariableDeclarationStatement;
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    expect(variableList.type, isGenericFunctionType);
+  }
+
+  void
+      test_parseNonLabeledStatement_variableDeclaration_gftType_voidReturnType() {
+    var statement =
+        parseStatement('void Function() v;') as VariableDeclarationStatement;
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    expect(variableList.type, isGenericFunctionType);
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_typeParam() {
+    VariableDeclarationStatement statement = parseStatement('C<T> v;');
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    TypeName typeName = variableList.type;
+    expect(typeName.name.name, 'C');
+    expect(typeName.typeArguments.arguments, hasLength(1));
+    TypeName typeArgument = typeName.typeArguments.arguments[0];
+    expect(typeArgument.name.name, 'T');
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_typeParam2() {
+    VariableDeclarationStatement statement =
+        parseStatement('C<T /* ignored comment */ > v;');
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    TypeName typeName = variableList.type;
+    expect(typeName.name.name, 'C');
+    expect(typeName.typeArguments.arguments, hasLength(1));
+    TypeName typeArgument = typeName.typeArguments.arguments[0];
+    expect(typeArgument.name.name, 'T');
+  }
+
+  void test_parseNonLabeledStatement_variableDeclaration_typeParam3() {
+    VariableDeclarationStatement statement =
+        parseStatement('C<T Function(String s)> v;');
+    assertNoErrors();
+    VariableDeclarationList variableList = statement.variables;
+    List<VariableDeclaration> variables = variableList.variables;
+    expect(variables, hasLength(1));
+    expect(variables[0].name.name, 'v');
+    TypeName typeName = variableList.type;
+    expect(typeName.name.name, 'C');
+    expect(typeName.typeArguments.arguments, hasLength(1));
+    expect(typeName.typeArguments.arguments[0], isGenericFunctionType);
+  }
+
+  void test_parseStatement_emptyTypeArgumentList() {
+    var declaration = parseStatement('C<> c;') as VariableDeclarationStatement;
+    assertErrorsWithCodes([ParserErrorCode.EXPECTED_TYPE_NAME]);
+    VariableDeclarationList variables = declaration.variables;
+    TypeName type = variables.type;
+    TypeArgumentList argumentList = type.typeArguments;
+    expect(argumentList.leftBracket, isNotNull);
+    expect(argumentList.arguments, hasLength(1));
+    expect(argumentList.arguments[0].isSynthetic, isTrue);
+    expect(argumentList.rightBracket, isNotNull);
+  }
+
+  void test_parseStatement_function_gftReturnType() {
+    var statement =
+        parseStatement('void Function<A>(core.List<core.int> x) m() => null;')
+            as FunctionDeclarationStatement;
+    expect(statement.functionDeclaration.functionExpression.body,
+        isExpressionFunctionBody);
+  }
+
+  void test_parseStatement_functionDeclaration_noReturnType() {
+    var statement = parseStatement('true;') as ExpressionStatement;
+    assertNoErrors();
+    expect(statement.expression, isNotNull);
+  }
+
+  void test_parseStatement_functionDeclaration_noReturnType_typeParameters() {
+    var statement =
+        parseStatement('f<E>(a, b) {}') as FunctionDeclarationStatement;
+    assertNoErrors();
+    expect(statement.functionDeclaration, isNotNull);
+  }
+
+  void test_parseStatement_functionDeclaration_returnType() {
+    // TODO(brianwilkerson) Implement more tests for this method.
+    var statement =
+        parseStatement('int f(a, b) {}') as FunctionDeclarationStatement;
+    assertNoErrors();
+    expect(statement.functionDeclaration, isNotNull);
+  }
+
+  void test_parseStatement_functionDeclaration_returnType_typeParameters() {
+    var statement =
+        parseStatement('int f<E>(a, b) {}') as FunctionDeclarationStatement;
+    assertNoErrors();
+    expect(statement.functionDeclaration, isNotNull);
+  }
+
+  void test_parseStatement_multipleLabels() {
+    var statement = parseStatement('l: m: return x;') as LabeledStatement;
+    expect(statement.labels, hasLength(2));
+    expect(statement.statement, isNotNull);
+  }
+
+  void test_parseStatement_noLabels() {
+    var statement = parseStatement('return x;') as ReturnStatement;
+    assertNoErrors();
+    expect(statement, isNotNull);
+  }
+
+  void test_parseStatement_singleLabel() {
+    var statement = parseStatement('l: return x;') as LabeledStatement;
+    assertNoErrors();
+    expect(statement.labels, hasLength(1));
+    expect(statement.labels[0].label.inDeclarationContext(), isTrue);
+    expect(statement.statement, isNotNull);
+  }
+
+  void test_parseSwitchStatement_case() {
+    var statement =
+        parseStatement('switch (a) {case 1: return "I";}') as SwitchStatement;
+    assertNoErrors();
+    expect(statement.switchKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.leftBracket, isNotNull);
+    expect(statement.members, hasLength(1));
+    expect(statement.rightBracket, isNotNull);
+  }
+
+  void test_parseSwitchStatement_empty() {
+    var statement = parseStatement('switch (a) {}') as SwitchStatement;
+    assertNoErrors();
+    expect(statement.switchKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.leftBracket, isNotNull);
+    expect(statement.members, hasLength(0));
+    expect(statement.rightBracket, isNotNull);
+  }
+
+  void test_parseSwitchStatement_labeledCase() {
+    var statement =
+        parseStatement('switch (a) {l1: l2: l3: case(1):}') as SwitchStatement;
+    assertNoErrors();
+    expect(statement.switchKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.leftBracket, isNotNull);
+    expect(statement.members, hasLength(1));
+    {
+      List<Label> labels = statement.members[0].labels;
+      expect(labels, hasLength(3));
+      expect(labels[0].label.inDeclarationContext(), isTrue);
+      expect(labels[1].label.inDeclarationContext(), isTrue);
+      expect(labels[2].label.inDeclarationContext(), isTrue);
+    }
+    expect(statement.rightBracket, isNotNull);
+  }
+
+  void test_parseSwitchStatement_labeledCase2() {
+    SwitchStatement statement =
+        parseStatement('switch (a) {l1: case 0: l2: case 1: return;}');
+    assertNoErrors();
+    expect(statement.switchKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.leftBracket, isNotNull);
+    expect(statement.members, hasLength(2));
+    {
+      List<Label> labels = statement.members[0].labels;
+      expect(labels, hasLength(1));
+      expect(labels[0].label.inDeclarationContext(), isTrue);
+    }
+    {
+      List<Label> labels = statement.members[1].labels;
+      expect(labels, hasLength(1));
+      expect(labels[0].label.inDeclarationContext(), isTrue);
+    }
+    expect(statement.rightBracket, isNotNull);
+  }
+
+  void test_parseSwitchStatement_labeledDefault() {
+    var statement =
+        parseStatement('switch (a) {l1: l2: l3: default:}') as SwitchStatement;
+    assertNoErrors();
+    expect(statement.switchKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.leftBracket, isNotNull);
+    expect(statement.members, hasLength(1));
+    {
+      List<Label> labels = statement.members[0].labels;
+      expect(labels, hasLength(3));
+      expect(labels[0].label.inDeclarationContext(), isTrue);
+      expect(labels[1].label.inDeclarationContext(), isTrue);
+      expect(labels[2].label.inDeclarationContext(), isTrue);
+    }
+    expect(statement.rightBracket, isNotNull);
+  }
+
+  void test_parseSwitchStatement_labeledDefault2() {
+    SwitchStatement statement =
+        parseStatement('switch (a) {l1: case 0: l2: default: return;}');
+    assertNoErrors();
+    expect(statement.switchKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.leftBracket, isNotNull);
+    expect(statement.members, hasLength(2));
+    {
+      List<Label> labels = statement.members[0].labels;
+      expect(labels, hasLength(1));
+      expect(labels[0].label.inDeclarationContext(), isTrue);
+    }
+    {
+      List<Label> labels = statement.members[1].labels;
+      expect(labels, hasLength(1));
+      expect(labels[0].label.inDeclarationContext(), isTrue);
+    }
+    expect(statement.rightBracket, isNotNull);
+  }
+
+  void test_parseSwitchStatement_labeledStatementInCase() {
+    var statement = parseStatement('switch (a) {case 0: f(); l1: g(); break;}')
+        as SwitchStatement;
+    assertNoErrors();
+    expect(statement.switchKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.leftBracket, isNotNull);
+    expect(statement.members, hasLength(1));
+    expect(statement.members[0].statements, hasLength(3));
+    expect(statement.rightBracket, isNotNull);
+  }
+
+  void test_parseTryStatement_catch() {
+    var statement = parseStatement('try {} catch (e) {}') as TryStatement;
+    assertNoErrors();
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNull);
+    expect(clause.exceptionType, isNull);
+    expect(clause.catchKeyword, isNotNull);
+    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.comma, isNull);
+    expect(clause.stackTraceParameter, isNull);
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNull);
+    expect(statement.finallyBlock, isNull);
+  }
+
+  void test_parseTryStatement_catch_error_invalidCatchParam() {
+    CompilationUnit unit = parseCompilationUnit(
+        'main() { try {} catch (int e) { } }',
+        errors: [expectedError(ParserErrorCode.CATCH_SYNTAX, 27, 1)]);
+    FunctionDeclaration method = unit.declarations[0];
+    BlockFunctionBody body = method.functionExpression.body;
+    TryStatement statement = body.block.statements[0];
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNull);
+    expect(clause.exceptionType, isNull);
+    expect(clause.catchKeyword, isNotNull);
+    expect(clause.exceptionParameter.name, 'int');
+    expect(clause.comma, isNotNull);
+    expect(clause.stackTraceParameter.name, 'e');
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNull);
+    expect(statement.finallyBlock, isNull);
+  }
+
+  void test_parseTryStatement_catch_error_missingCatchParam() {
+    var statement = parseStatement('try {} catch () {}') as TryStatement;
+    listener.assertErrors([expectedError(ParserErrorCode.CATCH_SYNTAX, 14, 1)]);
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNull);
+    expect(clause.exceptionType, isNull);
+    expect(clause.catchKeyword, isNotNull);
+    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.comma, isNull);
+    expect(clause.stackTraceParameter, isNull);
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNull);
+    expect(statement.finallyBlock, isNull);
+  }
+
+  void test_parseTryStatement_catch_error_missingCatchParen() {
+    var statement = parseStatement('try {} catch {}') as TryStatement;
+    listener.assertErrors([expectedError(ParserErrorCode.CATCH_SYNTAX, 13, 1)]);
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNull);
+    expect(clause.exceptionType, isNull);
+    expect(clause.catchKeyword, isNotNull);
+    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.comma, isNull);
+    expect(clause.stackTraceParameter, isNull);
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNull);
+    expect(statement.finallyBlock, isNull);
+  }
+
+  void test_parseTryStatement_catch_error_missingCatchTrace() {
+    var statement = parseStatement('try {} catch (e,) {}') as TryStatement;
+    listener.assertErrors([expectedError(ParserErrorCode.CATCH_SYNTAX, 16, 1)]);
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNull);
+    expect(clause.exceptionType, isNull);
+    expect(clause.catchKeyword, isNotNull);
+    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.comma, isNotNull);
+    expect(clause.stackTraceParameter, isNotNull);
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNull);
+    expect(statement.finallyBlock, isNull);
+  }
+
+  void test_parseTryStatement_catch_finally() {
+    var statement =
+        parseStatement('try {} catch (e, s) {} finally {}') as TryStatement;
+    assertNoErrors();
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNull);
+    expect(clause.exceptionType, isNull);
+    expect(clause.catchKeyword, isNotNull);
+    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.comma, isNotNull);
+    expect(clause.stackTraceParameter, isNotNull);
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNotNull);
+    expect(statement.finallyBlock, isNotNull);
+  }
+
+  void test_parseTryStatement_finally() {
+    var statement = parseStatement('try {} finally {}') as TryStatement;
+    assertNoErrors();
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    expect(statement.catchClauses, hasLength(0));
+    expect(statement.finallyKeyword, isNotNull);
+    expect(statement.finallyBlock, isNotNull);
+  }
+
+  void test_parseTryStatement_multiple() {
+    var statement =
+        parseStatement('try {} on NPE catch (e) {} on Error {} catch (e) {}')
+            as TryStatement;
+    assertNoErrors();
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    expect(statement.catchClauses, hasLength(3));
+    expect(statement.finallyKeyword, isNull);
+    expect(statement.finallyBlock, isNull);
+  }
+
+  void test_parseTryStatement_on() {
+    var statement = parseStatement('try {} on Error {}') as TryStatement;
+    assertNoErrors();
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNotNull);
+    expect(clause.exceptionType, isNotNull);
+    expect(clause.catchKeyword, isNull);
+    expect(clause.exceptionParameter, isNull);
+    expect(clause.comma, isNull);
+    expect(clause.stackTraceParameter, isNull);
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNull);
+    expect(statement.finallyBlock, isNull);
+  }
+
+  void test_parseTryStatement_on_catch() {
+    var statement =
+        parseStatement('try {} on Error catch (e, s) {}') as TryStatement;
+    assertNoErrors();
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNotNull);
+    expect(clause.exceptionType, isNotNull);
+    expect(clause.catchKeyword, isNotNull);
+    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.comma, isNotNull);
+    expect(clause.stackTraceParameter, isNotNull);
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNull);
+    expect(statement.finallyBlock, isNull);
+  }
+
+  void test_parseTryStatement_on_catch_finally() {
+    var statement = parseStatement('try {} on Error catch (e, s) {} finally {}')
+        as TryStatement;
+    assertNoErrors();
+    expect(statement.tryKeyword, isNotNull);
+    expect(statement.body, isNotNull);
+    NodeList<CatchClause> catchClauses = statement.catchClauses;
+    expect(catchClauses, hasLength(1));
+    CatchClause clause = catchClauses[0];
+    expect(clause.onKeyword, isNotNull);
+    expect(clause.exceptionType, isNotNull);
+    expect(clause.catchKeyword, isNotNull);
+    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.comma, isNotNull);
+    expect(clause.stackTraceParameter, isNotNull);
+    expect(clause.body, isNotNull);
+    expect(statement.finallyKeyword, isNotNull);
+    expect(statement.finallyBlock, isNotNull);
+  }
+
+  void test_parseVariableDeclaration_equals_builtIn() {
+    VariableDeclarationStatement statement = parseStatement('int set = 0;');
+    assertNoErrors();
+    expect(statement.semicolon, isNotNull);
+    VariableDeclarationList variableList = statement.variables;
+    expect(variableList, isNotNull);
+    expect(variableList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclarationListAfterMetadata_const_noType() {
+    var declarationList = parseVariableDeclarationList('const a = 0');
+    assertNoErrors();
+    expect(declarationList.keyword.lexeme, 'const');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclarationListAfterMetadata_const_type() {
+    var declarationList = parseVariableDeclarationList('const A a');
+    assertNoErrors();
+    expect(declarationList.keyword.lexeme, 'const');
+    expect(declarationList.type, isNotNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclarationListAfterMetadata_final_noType() {
+    var declarationList = parseVariableDeclarationList('final a');
+    assertNoErrors();
+    expect(declarationList.keyword, isNotNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclarationListAfterMetadata_final_type() {
+    var declarationList = parseVariableDeclarationList('final A a');
+    assertNoErrors();
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNotNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclarationListAfterMetadata_type_multiple() {
+    var declarationList = parseVariableDeclarationList('A a, b, c');
+    assertNoErrors();
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNotNull);
+    expect(declarationList.variables, hasLength(3));
+  }
+
+  void test_parseVariableDeclarationListAfterMetadata_type_single() {
+    var declarationList = parseVariableDeclarationList('A a');
+    assertNoErrors();
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNotNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclarationListAfterMetadata_var_multiple() {
+    var declarationList = parseVariableDeclarationList('var a, b, c');
+    assertNoErrors();
+    expect(declarationList.keyword.lexeme, 'var');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(3));
+  }
+
+  void test_parseVariableDeclarationListAfterMetadata_var_single() {
+    var declarationList = parseVariableDeclarationList('var a');
+    assertNoErrors();
+    expect(declarationList.keyword.lexeme, 'var');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseVariableDeclarationStatementAfterMetadata_multiple() {
+    var statement =
+        parseStatement('var x, y, z;') as VariableDeclarationStatement;
+    assertNoErrors();
+    expect(statement.semicolon, isNotNull);
+    VariableDeclarationList variableList = statement.variables;
+    expect(variableList, isNotNull);
+    expect(variableList.variables, hasLength(3));
+  }
+
+  void test_parseVariableDeclarationStatementAfterMetadata_single() {
+    var statement = parseStatement('var x;') as VariableDeclarationStatement;
+    assertNoErrors();
+    expect(statement.semicolon, isNotNull);
+    VariableDeclarationList variableList = statement.variables;
+    expect(variableList, isNotNull);
+    expect(variableList.variables, hasLength(1));
+  }
+
+  void test_parseWhileStatement() {
+    var statement = parseStatement('while (x) {}') as WhileStatement;
+    assertNoErrors();
+    expect(statement.whileKeyword, isNotNull);
+    expect(statement.leftParenthesis, isNotNull);
+    expect(statement.condition, isNotNull);
+    expect(statement.rightParenthesis, isNotNull);
+    expect(statement.body, isNotNull);
+  }
+
+  void test_parseYieldStatement_each() {
+    var statement =
+        _parseAsyncStatement('yield* x;', isGenerator: true) as YieldStatement;
+    assertNoErrors();
+    expect(statement.yieldKeyword, isNotNull);
+    expect(statement.star, isNotNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_parseYieldStatement_normal() {
+    var statement =
+        _parseAsyncStatement('yield x;', isGenerator: true) as YieldStatement;
+    assertNoErrors();
+    expect(statement.yieldKeyword, isNotNull);
+    expect(statement.star, isNull);
+    expect(statement.expression, isNotNull);
+    expect(statement.semicolon, isNotNull);
+  }
+
+  void test_partial_typeArg1_34850() {
+    var unit = parseCompilationUnit('<bar<', errors: [
+      expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 0),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 5, 0),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 5, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 0),
+    ]);
+    // Validate that recovery has properly updated the token stream.
+    analyzer.Token token = unit.beginToken;
+    while (!token.isEof) {
+      expect(token.type, isNot(TokenType.GT_GT));
+      analyzer.Token next = token.next;
+      expect(next.previous, token);
+      token = next;
+    }
+  }
+
+  void test_partial_typeArg2_34850() {
+    var unit = parseCompilationUnit('foo <bar<', errors: [
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 0),
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 0),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 0),
+    ]);
+    // Validate that recovery has properly updated the token stream.
+    analyzer.Token token = unit.beginToken;
+    while (!token.isEof) {
+      expect(token.type, isNot(TokenType.GT_GT));
+      analyzer.Token next = token.next;
+      expect(next.previous, token);
+      token = next;
+    }
+  }
+
+  Statement _parseAsyncStatement(String code, {bool isGenerator = false}) {
+    var star = isGenerator ? '*' : '';
+    var localFunction = parseStatement('wrapper() async$star { $code }')
+        as FunctionDeclarationStatement;
+    var localBody = localFunction.functionDeclaration.functionExpression.body
+        as BlockFunctionBody;
+    return localBody.block.statements.single;
+  }
+}
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index de9b311..25cd672 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -82,7 +82,7 @@
   foo(x, [y]);
 }
 class E extends C implements D {}''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 73, 1),
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 73, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index c291ea0..eb9c936 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -1141,7 +1141,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 225, 1),
     ]);
 
-    DartType cType = findLocalVariable(unit, 'c').type;
+    DartType cType = findElement.localVar('c').type;
     Element elementC = AstFinder.getClass(unit, "C").declaredElement;
 
     _isInstantiationOf(_hasElement(elementC))([_isDynamic])(cType);
@@ -1702,7 +1702,8 @@
 
     {
       List<Statement> statements =
-          AstFinder.getStatementsInTopLevelFunction(unit, "test2").cast<VariableDeclarationStatement>();
+          AstFinder.getStatementsInTopLevelFunction(unit, "test2")
+              .cast<VariableDeclarationStatement>();
       hasType(assertBOf([_isString, _isInt]), rhs(statements[0]));
       hasType(assertBOf([_isString, _isInt]), rhs(statements[1]));
       hasType(assertBOf([_isString, _isInt]), rhs(statements[2]));
@@ -1713,14 +1714,16 @@
 
     {
       List<Statement> statements =
-          AstFinder.getStatementsInTopLevelFunction(unit, "test3").cast<VariableDeclarationStatement>();
+          AstFinder.getStatementsInTopLevelFunction(unit, "test3")
+              .cast<VariableDeclarationStatement>();
       hasType(assertBOf([_isString, _isInt]), rhs(statements[0]));
       hasType(assertBOf([_isString, _isInt]), rhs(statements[1]));
     }
 
     {
       List<Statement> statements =
-          AstFinder.getStatementsInTopLevelFunction(unit, "test4").cast<VariableDeclarationStatement>();
+          AstFinder.getStatementsInTopLevelFunction(unit, "test4")
+              .cast<VariableDeclarationStatement>();
       hasType(assertCOf([_isInt]), rhs(statements[0]));
       hasType(assertCOf([_isInt]), rhs(statements[1]));
       hasType(assertCOf([_isInt]), rhs(statements[2]));
@@ -1731,7 +1734,8 @@
 
     {
       List<Statement> statements =
-          AstFinder.getStatementsInTopLevelFunction(unit, "test5").cast<VariableDeclarationStatement>();
+          AstFinder.getStatementsInTopLevelFunction(unit, "test5")
+              .cast<VariableDeclarationStatement>();
       hasType(assertCOf([_isInt]), rhs(statements[0]));
       hasType(assertCOf([_isInt]), rhs(statements[1]));
     }
@@ -1741,7 +1745,8 @@
       // context.  We could choose a tighter type, but currently
       // we just use dynamic.
       List<Statement> statements =
-          AstFinder.getStatementsInTopLevelFunction(unit, "test6").cast<VariableDeclarationStatement>();
+          AstFinder.getStatementsInTopLevelFunction(unit, "test6")
+              .cast<VariableDeclarationStatement>();
       hasType(assertDOf([_isDynamic, _isString]), rhs(statements[0]));
       hasType(assertDOf([_isDynamic, _isString]), rhs(statements[1]));
       hasType(assertDOf([_isInt, _isString]), rhs(statements[2]));
@@ -1752,20 +1757,23 @@
 
     {
       List<Statement> statements =
-          AstFinder.getStatementsInTopLevelFunction(unit, "test7").cast<VariableDeclarationStatement>();
+          AstFinder.getStatementsInTopLevelFunction(unit, "test7")
+              .cast<VariableDeclarationStatement>();
       hasType(assertDOf([_isDynamic, _isString]), rhs(statements[0]));
       hasType(assertDOf([_isDynamic, _isString]), rhs(statements[1]));
     }
 
     {
       List<Statement> statements =
-          AstFinder.getStatementsInTopLevelFunction(unit, "test8").cast<VariableDeclarationStatement>();
+          AstFinder.getStatementsInTopLevelFunction(unit, "test8")
+              .cast<VariableDeclarationStatement>();
       hasType(assertEOf([_isInt, _isString]), rhs(statements[0]));
     }
 
     {
       List<Statement> statements =
-          AstFinder.getStatementsInTopLevelFunction(unit, "test9").cast<VariableDeclarationStatement>();
+          AstFinder.getStatementsInTopLevelFunction(unit, "test9")
+              .cast<VariableDeclarationStatement>();
       hasType(assertFOf([_isInt, _isString]), rhs(statements[0]));
       hasType(assertFOf([_isInt, _isString]), rhs(statements[1]));
       hasType(assertFOf([_isInt, _isString]), rhs(statements[2]));
@@ -1810,9 +1818,12 @@
     assertListOfListOfInt(literal(2).staticType as InterfaceType);
     assertListOfListOfInt(literal(3).staticType as InterfaceType);
 
-    assertListOfInt((literal(1).elements[0] as Expression).staticType as InterfaceType);
-    assertListOfInt((literal(2).elements[0] as Expression).staticType as InterfaceType);
-    assertListOfInt((literal(3).elements[0] as Expression).staticType as InterfaceType);
+    assertListOfInt(
+        (literal(1).elements[0] as Expression).staticType as InterfaceType);
+    assertListOfInt(
+        (literal(2).elements[0] as Expression).staticType as InterfaceType);
+    assertListOfInt(
+        (literal(3).elements[0] as Expression).staticType as InterfaceType);
   }
 
   test_listLiteral_simple() async {
@@ -3486,6 +3497,7 @@
 class D extends C {}
 ''', [
       error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 69, 1),
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 69, 1),
     ]);
   }
 
@@ -3531,11 +3543,13 @@
   }
 
   test_instantiateToBounds_class_error_typedef() async {
-    await assertNoErrorsInCode(r'''
+    await assertErrorsInCode(r'''
 typedef T F<T>(T x);
 class C<T extends F<T>> {}
 C c;
-''');
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 48, 1),
+    ]);
     _assertTopVarType('c', 'C<dynamic Function(dynamic)>');
   }
 
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 42ff098..7ef4b60 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -5,56 +5,80 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'all_the_rest_test.dart' as all_the_rest;
+import 'class_member_parser_test.dart' as class_member_parser;
+import 'collection_literal_parser_test.dart' as collection_literal_parser;
+import 'complex_parser_test.dart' as complex_parser;
 // ignore: deprecated_member_use_from_same_package
 import 'constant_test.dart' as constant_test;
 import 'element_resolver_test.dart' as element_resolver_test;
+import 'error_parser_test.dart' as error_parser;
 import 'error_suppression_test.dart' as error_suppression;
+import 'expression_parser_test.dart' as expression_parser;
+import 'extension_methods_parser_test.dart' as extension_methods_parser;
+import 'formal_parameter_parser_test.dart' as formal_parameter_parser;
 import 'invalid_code_test.dart' as invalid_code;
 import 'issues_test.dart' as issues;
 import 'java_core_test.dart' as java_core_test;
 import 'java_io_test.dart' as java_io_test;
+import 'nnbd_parser_test.dart' as nnbd_parser;
+import 'non_error_parser_test.dart' as non_error_parser;
 import 'non_error_resolver_test.dart' as non_error_resolver;
 import 'non_hint_code_test.dart' as non_hint_code;
-import 'parser_fasta_test.dart' as parser_fasta_test;
-import 'parser_test.dart' as parser_test;
+import 'recovery_parser_test.dart' as recovery_parser;
 import 'resolver_test.dart' as resolver_test;
 import 'scanner_test.dart' as scanner_test;
 import 'sdk_test.dart' as sdk_test;
+import 'simple_parser_test.dart' as simple_parser;
 import 'simple_resolver_test.dart' as simple_resolver_test;
 import 'source_factory_test.dart' as source_factory_test;
+import 'statement_parser_test.dart' as statement_parser;
 import 'static_type_analyzer_test.dart' as static_type_analyzer_test;
 import 'static_type_warning_code_test.dart' as static_type_warning_code;
 import 'static_warning_code_test.dart' as static_warning_code;
 import 'strong_mode_test.dart' as strong_mode;
+import 'top_level_parser_test.dart' as top_level_parser;
 import 'type_system_test.dart' as type_system_test;
 import 'utilities_dart_test.dart' as utilities_dart_test;
 import 'utilities_test.dart' as utilities_test;
+import 'variance_parser_test.dart' as variance_parser;
 
 main() {
   defineReflectiveSuite(() {
     all_the_rest.main();
+    class_member_parser.main();
+    collection_literal_parser.main();
+    complex_parser.main();
     constant_test.main();
     element_resolver_test.main();
+    error_parser.main();
     error_suppression.main();
+    expression_parser.main();
+    extension_methods_parser.main();
+    formal_parameter_parser.main();
     invalid_code.main();
     issues.main();
     java_core_test.main();
     java_io_test.main();
+    nnbd_parser.main();
+    non_error_parser.main();
     non_error_resolver.main();
     non_hint_code.main();
-    parser_fasta_test.main();
-    parser_test.main();
+    recovery_parser.main();
     resolver_test.main();
     scanner_test.main();
     sdk_test.main();
+    simple_parser.main();
     simple_resolver_test.main();
     source_factory_test.main();
+    statement_parser.main();
     static_type_analyzer_test.main();
     static_type_warning_code.main();
     static_warning_code.main();
     strong_mode.main();
+    top_level_parser.main();
     type_system_test.main();
     utilities_dart_test.main();
     utilities_test.main();
+    variance_parser.main();
   }, name: 'generated');
 }
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index ad8cc0b..43a53ee 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
 
@@ -117,7 +116,7 @@
   final Map<Source, LineInfo> _lineInfoMap = <Source, LineInfo>{};
 
   /// Initialize a newly created error listener to collect errors.
-  GatheringErrorListener({this.checkRanges = Parser.useFasta});
+  GatheringErrorListener({this.checkRanges = true});
 
   /// Return the errors that were collected.
   List<AnalysisError> get errors => _errors;
diff --git a/pkg/analyzer/test/generated/top_level_parser_test.dart b/pkg/analyzer/test/generated/top_level_parser_test.dart
new file mode 100644
index 0000000..140b38a
--- /dev/null
+++ b/pkg/analyzer/test/generated/top_level_parser_test.dart
@@ -0,0 +1,2464 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../util/ast_type_matchers.dart';
+import 'parser_test_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TopLevelParserTest);
+  });
+}
+
+/// Tests which exercise the parser using a complete compilation unit or
+/// compilation unit member.
+@reflectiveTest
+class TopLevelParserTest extends FastaParserTestCase {
+  void test_function_literal_allowed_at_toplevel() {
+    parseCompilationUnit("var x = () {};");
+  }
+
+  void
+      test_function_literal_allowed_in_ArgumentList_in_ConstructorFieldInitializer() {
+    parseCompilationUnit("class C { C() : a = f(() {}); }");
+  }
+
+  void
+      test_function_literal_allowed_in_IndexExpression_in_ConstructorFieldInitializer() {
+    parseCompilationUnit("class C { C() : a = x[() {}]; }");
+  }
+
+  void
+      test_function_literal_allowed_in_ListLiteral_in_ConstructorFieldInitializer() {
+    parseCompilationUnit("class C { C() : a = [() {}]; }");
+  }
+
+  void
+      test_function_literal_allowed_in_MapLiteral_in_ConstructorFieldInitializer() {
+    parseCompilationUnit("class C { C() : a = {'key': () {}}; }");
+  }
+
+  void
+      test_function_literal_allowed_in_ParenthesizedExpression_in_ConstructorFieldInitializer() {
+    parseCompilationUnit("class C { C() : a = (() {}); }");
+  }
+
+  void
+      test_function_literal_allowed_in_StringInterpolation_in_ConstructorFieldInitializer() {
+    parseCompilationUnit("class C { C() : a = \"\${(){}}\"; }");
+  }
+
+  void test_import_as_show() {
+    parseCompilationUnit("import 'dart:math' as M show E;");
+  }
+
+  void test_import_show_hide() {
+    parseCompilationUnit(
+        "import 'import1_lib.dart' show hide, show hide ugly;");
+  }
+
+  void test_import_withDocComment() {
+    var compilationUnit = parseCompilationUnit('/// Doc\nimport "foo.dart";');
+    var importDirective = compilationUnit.directives[0];
+    expectCommentText(importDirective.documentationComment, '/// Doc');
+  }
+
+  void test_parse_missing_type_in_list_at_eof() {
+    createParser('Future<List<>>');
+
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 2),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 0),
+      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 14, 0),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 14, 0),
+    ]);
+
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+
+    // Ensure type parsed as "Future<List<[empty name]>>".
+    expect(declaration.variables.type, isNotNull);
+    expect(declaration.variables.type.question, isNull);
+    expect(declaration.variables.type, TypeMatcher<TypeName>());
+    TypeName type = declaration.variables.type;
+    expect(type.name.name, "Future");
+    expect(type.typeArguments.arguments.length, 1);
+    expect(type.typeArguments.arguments.single, TypeMatcher<TypeName>());
+    TypeName subType = type.typeArguments.arguments.single;
+    expect(subType.name.name, "List");
+    expect(subType.typeArguments.arguments.length, 1);
+    expect(subType.typeArguments.arguments.single, TypeMatcher<TypeName>());
+    TypeName subSubType = subType.typeArguments.arguments.single;
+    expect(subSubType.name.name, "");
+    expect(subSubType.typeArguments, isNull);
+  }
+
+  void test_parseClassDeclaration_abstract() {
+    createParser('abstract class A {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNotNull);
+    expect(declaration.extendsClause, isNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseClassDeclaration_empty() {
+    createParser('class A {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNull);
+    expect(declaration.extendsClause, isNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    _assertIsDeclarationName(declaration.name);
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseClassDeclaration_extends() {
+    createParser('class A extends B {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNull);
+    expect(declaration.extendsClause, isNotNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseClassDeclaration_extendsAndImplements() {
+    createParser('class A extends B implements C {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNull);
+    expect(declaration.extendsClause, isNotNull);
+    expect(declaration.implementsClause, isNotNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseClassDeclaration_extendsAndWith() {
+    createParser('class A extends B with C {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.typeParameters, isNull);
+    expect(declaration.extendsClause, isNotNull);
+    expect(declaration.withClause, isNotNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+  }
+
+  void test_parseClassDeclaration_extendsAndWithAndImplements() {
+    createParser('class A extends B with C implements D {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.typeParameters, isNull);
+    expect(declaration.extendsClause, isNotNull);
+    expect(declaration.withClause, isNotNull);
+    expect(declaration.implementsClause, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+  }
+
+  void test_parseClassDeclaration_implements() {
+    createParser('class A implements C {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNull);
+    expect(declaration.extendsClause, isNull);
+    expect(declaration.implementsClause, isNotNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseClassDeclaration_metadata() {
+    createParser('@A @B(2) @C.foo(3) @d.E.bar(4, 5) class X {}');
+    var declaration = parseFullCompilationUnitMember() as ClassDeclaration;
+    expect(declaration.metadata, hasLength(4));
+
+    {
+      var annotation = declaration.metadata[0];
+      expect(annotation.atSign, isNotNull);
+      expect(annotation.name, isSimpleIdentifier);
+      expect(annotation.name.name, 'A');
+      expect(annotation.period, isNull);
+      expect(annotation.constructorName, isNull);
+      expect(annotation.arguments, isNull);
+    }
+
+    {
+      var annotation = declaration.metadata[1];
+      expect(annotation.atSign, isNotNull);
+      expect(annotation.name, isSimpleIdentifier);
+      expect(annotation.name.name, 'B');
+      expect(annotation.period, isNull);
+      expect(annotation.constructorName, isNull);
+      expect(annotation.arguments, isNotNull);
+      expect(annotation.arguments.arguments, hasLength(1));
+    }
+
+    {
+      var annotation = declaration.metadata[2];
+      expect(annotation.atSign, isNotNull);
+      expect(annotation.name, isPrefixedIdentifier);
+      expect(annotation.name.name, 'C.foo');
+      expect(annotation.period, isNull);
+      expect(annotation.constructorName, isNull);
+      expect(annotation.arguments, isNotNull);
+      expect(annotation.arguments.arguments, hasLength(1));
+    }
+
+    {
+      var annotation = declaration.metadata[3];
+      expect(annotation.atSign, isNotNull);
+      expect(annotation.name, isPrefixedIdentifier);
+      expect(annotation.name.name, 'd.E');
+      expect(annotation.period, isNotNull);
+      expect(annotation.constructorName, isNotNull);
+      expect(annotation.constructorName.name, 'bar');
+      expect(annotation.arguments, isNotNull);
+      expect(annotation.arguments.arguments, hasLength(2));
+    }
+  }
+
+  void test_parseClassDeclaration_native() {
+    createParser('class A native "nativeValue" {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    if (!allowNativeClause) {
+      assertErrorsWithCodes([
+        ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
+      ]);
+    } else {
+      assertNoErrors();
+    }
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    NativeClause nativeClause = declaration.nativeClause;
+    expect(nativeClause, isNotNull);
+    expect(nativeClause.nativeKeyword, isNotNull);
+    expect(nativeClause.name.stringValue, "nativeValue");
+    expect(nativeClause.beginToken, same(nativeClause.nativeKeyword));
+    expect(nativeClause.endToken, same(nativeClause.name.endToken));
+  }
+
+  void test_parseClassDeclaration_native_allowed() {
+    allowNativeClause = true;
+    test_parseClassDeclaration_native();
+  }
+
+  void test_parseClassDeclaration_native_allowedWithFields() {
+    allowNativeClause = true;
+    createParser(r'''
+class A native 'something' {
+  final int x;
+  A() {}
+}
+''');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+  }
+
+  void test_parseClassDeclaration_native_missing_literal() {
+    createParser('class A native {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    if (allowNativeClause) {
+      assertNoErrors();
+    } else {
+      assertErrorsWithCodes([
+        ParserErrorCode.NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
+      ]);
+    }
+    expect(member, TypeMatcher<ClassDeclaration>());
+    ClassDeclaration declaration = member;
+    expect(declaration.nativeClause, isNotNull);
+    expect(declaration.nativeClause.nativeKeyword, isNotNull);
+    expect(declaration.nativeClause.name, isNull);
+    expect(declaration.endToken.type, TokenType.CLOSE_CURLY_BRACKET);
+  }
+
+  void test_parseClassDeclaration_native_missing_literal_allowed() {
+    allowNativeClause = true;
+    test_parseClassDeclaration_native_missing_literal();
+  }
+
+  void test_parseClassDeclaration_native_missing_literal_not_allowed() {
+    allowNativeClause = false;
+    test_parseClassDeclaration_native_missing_literal();
+  }
+
+  void test_parseClassDeclaration_native_not_allowed() {
+    allowNativeClause = false;
+    test_parseClassDeclaration_native();
+  }
+
+  void test_parseClassDeclaration_nonEmpty() {
+    createParser('class A {var f;}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNull);
+    expect(declaration.extendsClause, isNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.members, hasLength(1));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseClassDeclaration_typeAlias_implementsC() {
+    createParser('class A = Object with B implements C;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassTypeAlias);
+    ClassTypeAlias typeAlias = member;
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    _assertIsDeclarationName(typeAlias.name);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.withClause, isNotNull);
+    expect(typeAlias.implementsClause, isNotNull);
+    expect(typeAlias.implementsClause.implementsKeyword, isNotNull);
+    expect(typeAlias.implementsClause.interfaces.length, 1);
+    expect(typeAlias.semicolon, isNotNull);
+  }
+
+  void test_parseClassDeclaration_typeAlias_withB() {
+    createParser('class A = Object with B;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassTypeAlias);
+    ClassTypeAlias typeAlias = member;
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.withClause, isNotNull);
+    expect(typeAlias.withClause.withKeyword, isNotNull);
+    expect(typeAlias.withClause.mixinTypes.length, 1);
+    expect(typeAlias.implementsClause, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+  }
+
+  void test_parseClassDeclaration_typeParameters() {
+    createParser('class A<B> {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.abstractKeyword, isNull);
+    expect(declaration.extendsClause, isNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.classKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    _assertIsDeclarationName(declaration.name);
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNotNull);
+    expect(declaration.typeParameters.typeParameters, hasLength(1));
+    _assertIsDeclarationName(declaration.typeParameters.typeParameters[0].name);
+  }
+
+  void test_parseClassDeclaration_typeParameters_extends_void() {
+    parseCompilationUnit('class C<T extends void>{}',
+        errors: [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 18, 4)]);
+  }
+
+  void test_parseClassDeclaration_withDocumentationComment() {
+    createParser('/// Doc\nclass C {}');
+    var classDeclaration = parseFullCompilationUnitMember() as ClassDeclaration;
+    expectCommentText(classDeclaration.documentationComment, '/// Doc');
+  }
+
+  void test_parseClassTypeAlias_withDocumentationComment() {
+    createParser('/// Doc\nclass C = D with E;');
+    var classTypeAlias = parseFullCompilationUnitMember() as ClassTypeAlias;
+    expectCommentText(classTypeAlias.documentationComment, '/// Doc');
+  }
+
+  void test_parseCompilationUnit_abstractAsPrefix_parameterized() {
+    var errorCodes = <ErrorCode>[];
+    // This used to be deferred to later in the pipeline, but is now being
+    // reported by the parser.
+    errorCodes.add(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE);
+    CompilationUnit unit = parseCompilationUnit(
+        'abstract<dynamic> _abstract = new abstract.A();',
+        codes: errorCodes);
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnit_builtIn_asFunctionName() {
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isBuiltIn || keyword.isPseudo) {
+        String lexeme = keyword.lexeme;
+        if (lexeme == 'Function') continue;
+        parseCompilationUnit('$lexeme(x) => 0;');
+        parseCompilationUnit('class C {$lexeme(x) => 0;}');
+      }
+    }
+  }
+
+  void test_parseCompilationUnit_builtIn_asFunctionName_withTypeParameter() {
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isBuiltIn || keyword.isPseudo) {
+        String lexeme = keyword.lexeme;
+        if (lexeme == 'Function') continue;
+        // The fasta type resolution phase will report an error
+        // on type arguments on `dynamic` (e.g. `dynamic<int>`).
+        parseCompilationUnit('$lexeme<T>(x) => 0;');
+        parseCompilationUnit('class C {$lexeme<T>(x) => 0;}');
+      }
+    }
+  }
+
+  void test_parseCompilationUnit_builtIn_asGetter() {
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isBuiltIn || keyword.isPseudo) {
+        String lexeme = keyword.lexeme;
+        parseCompilationUnit('get $lexeme => 0;');
+        parseCompilationUnit('class C {get $lexeme => 0;}');
+      }
+    }
+  }
+
+  void test_parseCompilationUnit_directives_multiple() {
+    createParser("library l;\npart 'a.dart';");
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    assertNoErrors();
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(2));
+    expect(unit.declarations, hasLength(0));
+  }
+
+  void test_parseCompilationUnit_directives_single() {
+    createParser('library l;');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    assertNoErrors();
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(1));
+    expect(unit.declarations, hasLength(0));
+  }
+
+  void test_parseCompilationUnit_empty() {
+    createParser('');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    assertNoErrors();
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+    expect(unit.declarations, hasLength(0));
+    expect(unit.beginToken, isNotNull);
+    expect(unit.endToken, isNotNull);
+    expect(unit.endToken.type, TokenType.EOF);
+  }
+
+  void test_parseCompilationUnit_exportAsPrefix() {
+    createParser('export.A _export = new export.A();');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    assertNoErrors();
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnit_exportAsPrefix_parameterized() {
+    createParser('export<dynamic> _export = new export.A();');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    // This used to be deferred to later in the pipeline, but is now being
+    // reported by the parser.
+    assertErrorsWithCodes([CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnit_operatorAsPrefix_parameterized() {
+    createParser('operator<dynamic> _operator = new operator.A();');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    // This used to be deferred to later in the pipeline, but is now being
+    // reported by the parser.
+    assertErrorsWithCodes([CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnit_pseudo_asTypeName() {
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isPseudo) {
+        String lexeme = keyword.lexeme;
+        parseCompilationUnit('$lexeme f;');
+        parseCompilationUnit('class C {$lexeme f;}');
+        parseCompilationUnit('f($lexeme g) {}');
+        parseCompilationUnit('f() {$lexeme g;}');
+      }
+    }
+  }
+
+  void test_parseCompilationUnit_pseudo_prefixed() {
+    for (Keyword keyword in Keyword.values) {
+      if (keyword.isPseudo) {
+        String lexeme = keyword.lexeme;
+        parseCompilationUnit('M.$lexeme f;');
+        parseCompilationUnit('class C {M.$lexeme f;}');
+      }
+    }
+  }
+
+  void test_parseCompilationUnit_script() {
+    createParser('#! /bin/dart');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    assertNoErrors();
+    expect(unit.scriptTag, isNotNull);
+    expect(unit.directives, hasLength(0));
+    expect(unit.declarations, hasLength(0));
+  }
+
+  void test_parseCompilationUnit_skipFunctionBody_withInterpolation() {
+    ParserTestCase.parseFunctionBodies = false;
+    createParser('f() { "\${n}"; }');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    assertNoErrors();
+    expect(unit.scriptTag, isNull);
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnit_topLevelDeclaration() {
+    createParser('class A {}');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    assertNoErrors();
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+    expect(unit.declarations, hasLength(1));
+    expect(unit.beginToken, isNotNull);
+    expect(unit.beginToken.keyword, Keyword.CLASS);
+    expect(unit.endToken, isNotNull);
+    expect(unit.endToken.type, TokenType.EOF);
+  }
+
+  void test_parseCompilationUnit_typedefAsPrefix() {
+    createParser('typedef.A _typedef = new typedef.A();');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    assertNoErrors();
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnitMember_abstractAsPrefix() {
+    createParser('abstract.A _abstract = new abstract.A();');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_class() {
+    createParser('class A {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassDeclaration);
+    ClassDeclaration declaration = member;
+    expect(declaration.name.name, "A");
+    expect(declaration.members, hasLength(0));
+  }
+
+  void test_parseCompilationUnitMember_classTypeAlias() {
+    createParser('abstract class A = B with C;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassTypeAlias);
+    ClassTypeAlias declaration = member;
+    expect(declaration.name.name, "A");
+    expect(declaration.abstractKeyword, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_constVariable() {
+    createParser('const int x = 0;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+    expect(declaration.variables.keyword.lexeme, 'const');
+    _assertIsDeclarationName(declaration.variables.variables[0].name);
+  }
+
+  void test_parseCompilationUnitMember_expressionFunctionBody_tokens() {
+    createParser('f() => 0;');
+    var f = parseFullCompilationUnitMember() as FunctionDeclaration;
+    var body = f.functionExpression.body as ExpressionFunctionBody;
+    expect(body.functionDefinition.lexeme, '=>');
+    expect(body.semicolon.lexeme, ';');
+    _assertIsDeclarationName(f.name);
+  }
+
+  void test_parseCompilationUnitMember_finalVariable() {
+    createParser('final x = 0;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+    expect(declaration.variables.keyword.lexeme, 'final');
+  }
+
+  void test_parseCompilationUnitMember_function_external_noType() {
+    createParser('external f();');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.externalKeyword, isNotNull);
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNull);
+  }
+
+  void test_parseCompilationUnitMember_function_external_type() {
+    createParser('external int f();');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.externalKeyword, isNotNull);
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNull);
+  }
+
+  void test_parseCompilationUnitMember_function_generic_noReturnType() {
+    createParser('f<E>() {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.returnType, isNull);
+    expect(declaration.functionExpression.typeParameters, isNotNull);
+  }
+
+  void
+      test_parseCompilationUnitMember_function_generic_noReturnType_annotated() {
+    createParser('f<@a E>() {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.returnType, isNull);
+    expect(declaration.functionExpression.typeParameters, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_function_generic_returnType() {
+    createParser('E f<E>() {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.returnType, isNotNull);
+    expect(declaration.functionExpression.typeParameters, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_function_generic_void() {
+    createParser('void f<T>(T t) {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNull);
+  }
+
+  void test_parseCompilationUnitMember_function_gftReturnType() {
+    createParser('''
+void Function<A>(core.List<core.int> x) f() => null;
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    assertNoErrors();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnitMember_function_noReturnType() {
+    createParser('''
+Function<A>(core.List<core.int> x) f() => null;
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    assertNoErrors();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnitMember_function_noType() {
+    createParser('f() {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNull);
+  }
+
+  void test_parseCompilationUnitMember_function_type() {
+    createParser('int f() {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNull);
+  }
+
+  void test_parseCompilationUnitMember_function_void() {
+    createParser('void f() {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.returnType, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_getter_external_noType() {
+    createParser('external get p;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.externalKeyword, isNotNull);
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+    _assertIsDeclarationName(declaration.name);
+  }
+
+  void test_parseCompilationUnitMember_getter_external_type() {
+    createParser('external int get p;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.externalKeyword, isNotNull);
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_getter_noType() {
+    createParser('get p => 0;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_getter_type() {
+    createParser('int get p => 0;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_setter_external_noType() {
+    createParser('external set p(v);');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.externalKeyword, isNotNull);
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_setter_external_type() {
+    createParser('external void set p(int v);');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.externalKeyword, isNotNull);
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_setter_noType() {
+    createParser('set p(v) {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+    _assertIsDeclarationName(declaration.name);
+  }
+
+  void test_parseCompilationUnitMember_setter_type() {
+    createParser('void set p(int v) {}');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isFunctionDeclaration);
+    FunctionDeclaration declaration = member;
+    expect(declaration.functionExpression, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+    expect(declaration.returnType, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_typeAlias_abstract() {
+    createParser('abstract class C = S with M;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassTypeAlias);
+    ClassTypeAlias typeAlias = member;
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name.name, "C");
+    _assertIsDeclarationName(typeAlias.name);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.equals, isNotNull);
+    expect(typeAlias.abstractKeyword, isNotNull);
+    expect(typeAlias.superclass.name.name, "S");
+    expect(typeAlias.withClause, isNotNull);
+    expect(typeAlias.implementsClause, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_typeAlias_generic() {
+    createParser('class C<E> = S<E> with M<E> implements I<E>;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassTypeAlias);
+    ClassTypeAlias typeAlias = member;
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name.name, "C");
+    expect(typeAlias.typeParameters.typeParameters, hasLength(1));
+    expect(typeAlias.equals, isNotNull);
+    expect(typeAlias.abstractKeyword, isNull);
+    expect(typeAlias.superclass.name.name, "S");
+    expect(typeAlias.withClause, isNotNull);
+    expect(typeAlias.implementsClause, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_typeAlias_implements() {
+    createParser('class C = S with M implements I;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassTypeAlias);
+    ClassTypeAlias typeAlias = member;
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name.name, "C");
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.equals, isNotNull);
+    expect(typeAlias.abstractKeyword, isNull);
+    expect(typeAlias.superclass.name.name, "S");
+    expect(typeAlias.withClause, isNotNull);
+    expect(typeAlias.implementsClause, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_typeAlias_noImplements() {
+    createParser('class C = S with M;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isClassTypeAlias);
+    ClassTypeAlias typeAlias = member;
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name.name, "C");
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.equals, isNotNull);
+    expect(typeAlias.abstractKeyword, isNull);
+    expect(typeAlias.superclass.name.name, "S");
+    expect(typeAlias.withClause, isNotNull);
+    expect(typeAlias.implementsClause, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_typedef() {
+    createParser('typedef F();');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, TypeMatcher<FunctionTypeAlias>());
+    FunctionTypeAlias typeAlias = member;
+    expect(typeAlias.name.name, "F");
+    expect(typeAlias.parameters.parameters, hasLength(0));
+    _assertIsDeclarationName(typeAlias.name);
+  }
+
+  void test_parseCompilationUnitMember_typedef_withDocComment() {
+    createParser('/// Doc\ntypedef F();');
+    var typeAlias = parseFullCompilationUnitMember() as FunctionTypeAlias;
+    expectCommentText(typeAlias.documentationComment, '/// Doc');
+  }
+
+  void test_parseCompilationUnitMember_typedVariable() {
+    createParser('int x = 0;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+    expect(declaration.variables.type, isNotNull);
+    expect(declaration.variables.keyword, isNull);
+    _assertIsDeclarationName(declaration.variables.variables[0].name);
+  }
+
+  void test_parseCompilationUnitMember_variable() {
+    createParser('var x = 0;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+    expect(declaration.variables.keyword.lexeme, 'var');
+  }
+
+  void test_parseCompilationUnitMember_variable_gftType_gftReturnType() {
+    createParser('''
+Function(int) Function(String) v;
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    assertNoErrors();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+    TopLevelVariableDeclaration declaration =
+        unit.declarations[0] as TopLevelVariableDeclaration;
+    expect(declaration.variables.type, isGenericFunctionType);
+  }
+
+  void test_parseCompilationUnitMember_variable_gftType_noReturnType() {
+    createParser('''
+Function(int, String) v;
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    assertNoErrors();
+    expect(unit, isNotNull);
+    expect(unit.declarations, hasLength(1));
+  }
+
+  void test_parseCompilationUnitMember_variable_withDocumentationComment() {
+    createParser('/// Doc\nvar x = 0;');
+    var declaration =
+        parseFullCompilationUnitMember() as TopLevelVariableDeclaration;
+    expectCommentText(declaration.documentationComment, '/// Doc');
+  }
+
+  void test_parseCompilationUnitMember_variableGet() {
+    createParser('String get = null;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+  }
+
+  void test_parseCompilationUnitMember_variableSet() {
+    createParser('String set = null;');
+    CompilationUnitMember member = parseFullCompilationUnitMember();
+    expect(member, isNotNull);
+    assertNoErrors();
+    expect(member, isTopLevelVariableDeclaration);
+    TopLevelVariableDeclaration declaration = member;
+    expect(declaration.semicolon, isNotNull);
+    expect(declaration.variables, isNotNull);
+  }
+
+  void test_parseDirective_export() {
+    createParser("export 'lib/lib.dart';");
+    Directive directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive, TypeMatcher<ExportDirective>());
+    ExportDirective exportDirective = directive;
+    expect(exportDirective.keyword, isNotNull);
+    expect(exportDirective.uri, isNotNull);
+    expect(exportDirective.combinators, hasLength(0));
+    expect(exportDirective.semicolon, isNotNull);
+  }
+
+  void test_parseDirective_export_withDocComment() {
+    createParser("/// Doc\nexport 'foo.dart';");
+    var directive = parseFullDirective() as ExportDirective;
+    expectCommentText(directive.documentationComment, '/// Doc');
+  }
+
+  void test_parseDirective_import() {
+    createParser("import 'lib/lib.dart';");
+    Directive directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive, TypeMatcher<ImportDirective>());
+    ImportDirective importDirective = directive;
+    expect(importDirective.keyword, isNotNull);
+    expect(importDirective.uri, isNotNull);
+    expect(importDirective.asKeyword, isNull);
+    expect(importDirective.prefix, isNull);
+    expect(importDirective.combinators, hasLength(0));
+    expect(importDirective.semicolon, isNotNull);
+  }
+
+  void test_parseDirective_library() {
+    createParser("library l;");
+    Directive directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive, TypeMatcher<LibraryDirective>());
+    LibraryDirective libraryDirective = directive;
+    expect(libraryDirective.libraryKeyword, isNotNull);
+    expect(libraryDirective.name, isNotNull);
+    expect(libraryDirective.semicolon, isNotNull);
+  }
+
+  void test_parseDirective_library_1_component() {
+    createParser("library a;");
+    var lib = parseFullDirective() as LibraryDirective;
+    expect(lib.name.components, hasLength(1));
+    expect(lib.name.components[0].name, 'a');
+  }
+
+  void test_parseDirective_library_2_components() {
+    createParser("library a.b;");
+    var lib = parseFullDirective() as LibraryDirective;
+    expect(lib.name.components, hasLength(2));
+    expect(lib.name.components[0].name, 'a');
+    expect(lib.name.components[1].name, 'b');
+  }
+
+  void test_parseDirective_library_3_components() {
+    createParser("library a.b.c;");
+    var lib = parseFullDirective() as LibraryDirective;
+    expect(lib.name.components, hasLength(3));
+    expect(lib.name.components[0].name, 'a');
+    expect(lib.name.components[1].name, 'b');
+    expect(lib.name.components[2].name, 'c');
+  }
+
+  void test_parseDirective_library_annotation() {
+    createParser("@A library l;");
+    Directive directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive, TypeMatcher<LibraryDirective>());
+    LibraryDirective libraryDirective = directive;
+    expect(libraryDirective.libraryKeyword, isNotNull);
+    expect(libraryDirective.name, isNotNull);
+    expect(libraryDirective.semicolon, isNotNull);
+    expect(libraryDirective.metadata, hasLength(1));
+    expect(libraryDirective.metadata[0].name.name, 'A');
+  }
+
+  void test_parseDirective_library_annotation2() {
+    createParser("@A library l;");
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    Directive directive = unit.directives[0];
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive, TypeMatcher<LibraryDirective>());
+    LibraryDirective libraryDirective = directive;
+    expect(libraryDirective.libraryKeyword, isNotNull);
+    expect(libraryDirective.name, isNotNull);
+    expect(libraryDirective.semicolon, isNotNull);
+    expect(libraryDirective.metadata, hasLength(1));
+    expect(libraryDirective.metadata[0].name.name, 'A');
+  }
+
+  void test_parseDirective_library_withDocumentationComment() {
+    createParser('/// Doc\nlibrary l;');
+    var directive = parseFullDirective() as LibraryDirective;
+    expectCommentText(directive.documentationComment, '/// Doc');
+  }
+
+  void test_parseDirective_part() {
+    createParser("part 'lib/lib.dart';");
+    Directive directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive, TypeMatcher<PartDirective>());
+    PartDirective partDirective = directive;
+    expect(partDirective.partKeyword, isNotNull);
+    expect(partDirective.uri, isNotNull);
+    expect(partDirective.semicolon, isNotNull);
+  }
+
+  void test_parseDirective_part_of_1_component() {
+    createParser("part of a;");
+    var partOf = parseFullDirective() as PartOfDirective;
+    expect(partOf.libraryName.components, hasLength(1));
+    expect(partOf.libraryName.components[0].name, 'a');
+  }
+
+  void test_parseDirective_part_of_2_components() {
+    createParser("part of a.b;");
+    var partOf = parseFullDirective() as PartOfDirective;
+    expect(partOf.libraryName.components, hasLength(2));
+    expect(partOf.libraryName.components[0].name, 'a');
+    expect(partOf.libraryName.components[1].name, 'b');
+  }
+
+  void test_parseDirective_part_of_3_components() {
+    createParser("part of a.b.c;");
+    var partOf = parseFullDirective() as PartOfDirective;
+    expect(partOf.libraryName.components, hasLength(3));
+    expect(partOf.libraryName.components[0].name, 'a');
+    expect(partOf.libraryName.components[1].name, 'b');
+    expect(partOf.libraryName.components[2].name, 'c');
+  }
+
+  void test_parseDirective_part_of_withDocumentationComment() {
+    createParser('/// Doc\npart of a;');
+    var partOf = parseFullDirective() as PartOfDirective;
+    expectCommentText(partOf.documentationComment, '/// Doc');
+  }
+
+  void test_parseDirective_part_withDocumentationComment() {
+    createParser("/// Doc\npart 'lib.dart';");
+    var directive = parseFullDirective() as PartDirective;
+    expectCommentText(directive.documentationComment, '/// Doc');
+  }
+
+  void test_parseDirective_partOf() {
+    createParser("part of l;");
+    Directive directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive, TypeMatcher<PartOfDirective>());
+    PartOfDirective partOfDirective = directive;
+    expect(partOfDirective.partKeyword, isNotNull);
+    expect(partOfDirective.ofKeyword, isNotNull);
+    expect(partOfDirective.libraryName, isNotNull);
+    expect(partOfDirective.semicolon, isNotNull);
+  }
+
+  void test_parseDirectives_annotations() {
+    CompilationUnit unit =
+        parseDirectives("@A library l; @B import 'foo.dart';");
+    expect(unit.directives, hasLength(2));
+    expect(unit.directives[0].metadata[0].name.name, 'A');
+    expect(unit.directives[1].metadata[0].name.name, 'B');
+  }
+
+  void test_parseDirectives_complete() {
+    CompilationUnit unit =
+        parseDirectives("#! /bin/dart\nlibrary l;\nclass A {}");
+    expect(unit.scriptTag, isNotNull);
+    expect(unit.directives, hasLength(1));
+  }
+
+  void test_parseDirectives_empty() {
+    CompilationUnit unit = parseDirectives("");
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+  }
+
+  void test_parseDirectives_mixed() {
+    CompilationUnit unit =
+        parseDirectives("library l; class A {} part 'foo.dart';");
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(1));
+  }
+
+  void test_parseDirectives_multiple() {
+    CompilationUnit unit = parseDirectives("library l;\npart 'a.dart';");
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(2));
+  }
+
+  void test_parseDirectives_script() {
+    CompilationUnit unit = parseDirectives("#! /bin/dart");
+    expect(unit.scriptTag, isNotNull);
+    expect(unit.directives, hasLength(0));
+  }
+
+  void test_parseDirectives_single() {
+    CompilationUnit unit = parseDirectives("library l;");
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(1));
+  }
+
+  void test_parseDirectives_topLevelDeclaration() {
+    CompilationUnit unit = parseDirectives("class A {}");
+    expect(unit.scriptTag, isNull);
+    expect(unit.directives, hasLength(0));
+  }
+
+  void test_parseEnumDeclaration_one() {
+    createParser("enum E {ONE}");
+    EnumDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.enumKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.constants, hasLength(1));
+    expect(declaration.rightBracket, isNotNull);
+  }
+
+  void test_parseEnumDeclaration_trailingComma() {
+    createParser("enum E {ONE,}");
+    EnumDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.enumKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.constants, hasLength(1));
+    expect(declaration.rightBracket, isNotNull);
+  }
+
+  void test_parseEnumDeclaration_two() {
+    createParser("enum E {ONE, TWO}");
+    EnumDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.enumKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name, isNotNull);
+    expect(declaration.constants, hasLength(2));
+    expect(declaration.rightBracket, isNotNull);
+  }
+
+  void test_parseEnumDeclaration_withDocComment_onEnum() {
+    createParser('/// Doc\nenum E {ONE}');
+    var declaration = parseFullCompilationUnitMember() as EnumDeclaration;
+    expectCommentText(declaration.documentationComment, '/// Doc');
+  }
+
+  void test_parseEnumDeclaration_withDocComment_onValue() {
+    createParser('''
+enum E {
+  /// Doc
+  ONE
+}''');
+    var declaration = parseFullCompilationUnitMember() as EnumDeclaration;
+    var value = declaration.constants[0];
+    expectCommentText(value.documentationComment, '/// Doc');
+  }
+
+  void test_parseEnumDeclaration_withDocComment_onValue_annotated() {
+    createParser('''
+enum E {
+  /// Doc
+  @annotation
+  ONE
+}
+''');
+    var declaration = parseFullCompilationUnitMember() as EnumDeclaration;
+    var value = declaration.constants[0];
+    expectCommentText(value.documentationComment, '/// Doc');
+    expect(value.metadata, hasLength(1));
+  }
+
+  void test_parseExportDirective_configuration_multiple() {
+    createParser("export 'lib/lib.dart' if (a) 'b.dart' if (c) 'd.dart';");
+    ExportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.configurations, hasLength(2));
+    expectDottedName(directive.configurations[0].name, ['a']);
+    expectDottedName(directive.configurations[1].name, ['c']);
+    expect(directive.combinators, hasLength(0));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseExportDirective_configuration_single() {
+    createParser("export 'lib/lib.dart' if (a.b == 'c.dart') '';");
+    ExportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.configurations, hasLength(1));
+    expectDottedName(directive.configurations[0].name, ['a', 'b']);
+    expect(directive.combinators, hasLength(0));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseExportDirective_hide() {
+    createParser("export 'lib/lib.dart' hide A, B;");
+    ExportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.combinators, hasLength(1));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseExportDirective_hide_show() {
+    createParser("export 'lib/lib.dart' hide A show B;");
+    ExportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.combinators, hasLength(2));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseExportDirective_noCombinator() {
+    createParser("export 'lib/lib.dart';");
+    ExportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.combinators, hasLength(0));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseExportDirective_show() {
+    createParser("export 'lib/lib.dart' show A, B;");
+    ExportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.combinators, hasLength(1));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseExportDirective_show_hide() {
+    createParser("export 'lib/lib.dart' show B hide A;");
+    ExportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.combinators, hasLength(2));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseFunctionDeclaration_function() {
+    createParser('/// Doc\nT f() {}');
+    FunctionDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expectCommentText(declaration.documentationComment, '/// Doc');
+    expect((declaration.returnType as TypeName).name.name, 'T');
+    expect(declaration.name, isNotNull);
+    FunctionExpression expression = declaration.functionExpression;
+    expect(expression, isNotNull);
+    expect(expression.body, isNotNull);
+    expect(expression.typeParameters, isNull);
+    expect(expression.parameters, isNotNull);
+    expect(declaration.propertyKeyword, isNull);
+  }
+
+  void test_parseFunctionDeclaration_functionWithTypeParameters() {
+    createParser('/// Doc\nT f<E>() {}');
+    FunctionDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expectCommentText(declaration.documentationComment, '/// Doc');
+    expect((declaration.returnType as TypeName).name.name, 'T');
+    expect(declaration.name, isNotNull);
+    FunctionExpression expression = declaration.functionExpression;
+    expect(expression, isNotNull);
+    expect(expression.body, isNotNull);
+    expect(expression.typeParameters, isNotNull);
+    expect(expression.parameters, isNotNull);
+    expect(declaration.propertyKeyword, isNull);
+  }
+
+  void test_parseFunctionDeclaration_getter() {
+    createParser('/// Doc\nT get p => 0;');
+    FunctionDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expectCommentText(declaration.documentationComment, '/// Doc');
+    expect((declaration.returnType as TypeName).name.name, 'T');
+    expect(declaration.name, isNotNull);
+    FunctionExpression expression = declaration.functionExpression;
+    expect(expression, isNotNull);
+    expect(expression.body, isNotNull);
+    expect(expression.typeParameters, isNull);
+    expect(expression.parameters, isNull);
+    expect(declaration.propertyKeyword, isNotNull);
+  }
+
+  void test_parseFunctionDeclaration_metadata() {
+    createParser(
+        'T f(@A a, @B(2) Foo b, {@C.foo(3) c : 0, @d.E.bar(4, 5) x:0}) {}');
+    FunctionDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.documentationComment, isNull);
+    expect((declaration.returnType as TypeName).name.name, 'T');
+    expect(declaration.name, isNotNull);
+    FunctionExpression expression = declaration.functionExpression;
+    expect(expression, isNotNull);
+    expect(expression.body, isNotNull);
+    expect(expression.typeParameters, isNull);
+    NodeList<FormalParameter> parameters = expression.parameters.parameters;
+    expect(parameters, hasLength(4));
+    expect(declaration.propertyKeyword, isNull);
+
+    {
+      var annotation = parameters[0].metadata[0];
+      expect(annotation.atSign, isNotNull);
+      expect(annotation.name, isSimpleIdentifier);
+      expect(annotation.name.name, 'A');
+      expect(annotation.period, isNull);
+      expect(annotation.constructorName, isNull);
+      expect(annotation.arguments, isNull);
+    }
+
+    {
+      var annotation = parameters[1].metadata[0];
+      expect(annotation.atSign, isNotNull);
+      expect(annotation.name, isSimpleIdentifier);
+      expect(annotation.name.name, 'B');
+      expect(annotation.period, isNull);
+      expect(annotation.constructorName, isNull);
+      expect(annotation.arguments, isNotNull);
+      expect(annotation.arguments.arguments, hasLength(1));
+    }
+
+    {
+      var annotation = parameters[2].metadata[0];
+      expect(annotation.atSign, isNotNull);
+      expect(annotation.name, isPrefixedIdentifier);
+      expect(annotation.name.name, 'C.foo');
+      expect(annotation.period, isNull);
+      expect(annotation.constructorName, isNull);
+      expect(annotation.arguments, isNotNull);
+      expect(annotation.arguments.arguments, hasLength(1));
+    }
+
+    {
+      var annotation = parameters[3].metadata[0];
+      expect(annotation.atSign, isNotNull);
+      expect(annotation.name, isPrefixedIdentifier);
+      expect(annotation.name.name, 'd.E');
+      expect(annotation.period, isNotNull);
+      expect(annotation.constructorName, isNotNull);
+      expect(annotation.constructorName.name, 'bar');
+      expect(annotation.arguments, isNotNull);
+      expect(annotation.arguments.arguments, hasLength(2));
+    }
+  }
+
+  void test_parseFunctionDeclaration_setter() {
+    createParser('/// Doc\nT set p(v) {}');
+    FunctionDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expectCommentText(declaration.documentationComment, '/// Doc');
+    expect((declaration.returnType as TypeName).name.name, 'T');
+    expect(declaration.name, isNotNull);
+    FunctionExpression expression = declaration.functionExpression;
+    expect(expression, isNotNull);
+    expect(expression.body, isNotNull);
+    expect(expression.typeParameters, isNull);
+    expect(expression.parameters, isNotNull);
+    expect(declaration.propertyKeyword, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_noTypeParameters() {
+    createParser('typedef F = int Function(int);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters, isNull);
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_typeParameters() {
+    createParser('typedef F<T> = T Function(T);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters.typeParameters, hasLength(1));
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_typeParameters2() {
+    // The scanner creates a single token for `>=`
+    // then the parser must split it into two separate tokens.
+    createParser('typedef F<T>= T Function(T);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters.typeParameters, hasLength(1));
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_typeParameters3() {
+    createParser('typedef F<A,B,C> = Function(A a, B b, C c);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters.typeParameters, hasLength(3));
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_typeParameters3_gtEq() {
+    // The scanner creates a single token for `>=`
+    // then the parser must split it into two separate tokens.
+    createParser('typedef F<A,B,C>=Function(A a, B b, C c);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters.typeParameters, hasLength(3));
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_typeParameters_extends() {
+    createParser('typedef F<A,B,C extends D<E>> = Function(A a, B b, C c);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters.typeParameters, hasLength(3));
+    TypeParameter typeParam = alias.typeParameters.typeParameters[2];
+    NamedType type = typeParam.bound;
+    expect(type.typeArguments.arguments, hasLength(1));
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_typeParameters_extends3() {
+    createParser(
+        'typedef F<A,B,C extends D<E,G,H>> = Function(A a, B b, C c);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters.typeParameters, hasLength(3));
+    TypeParameter typeParam = alias.typeParameters.typeParameters[2];
+    NamedType type = typeParam.bound;
+    expect(type.typeArguments.arguments, hasLength(3));
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_typeParameters_extends3_gtGtEq() {
+    // The scanner creates a single token for `>>=`
+    // then the parser must split it into three separate tokens.
+    createParser('typedef F<A,B,C extends D<E,G,H>>=Function(A a, B b, C c);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters.typeParameters, hasLength(3));
+    TypeParameter typeParam = alias.typeParameters.typeParameters[2];
+    NamedType type = typeParam.bound;
+    expect(type.typeArguments.arguments, hasLength(3));
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseGenericTypeAlias_typeParameters_extends_gtGtEq() {
+    // The scanner creates a single token for `>>=`
+    // then the parser must split it into three separate tokens.
+    createParser('typedef F<A,B,C extends D<E>>=Function(A a, B b, C c);');
+    GenericTypeAlias alias = parseFullCompilationUnitMember();
+    expect(alias, isNotNull);
+    assertNoErrors();
+    expect(alias.name, isNotNull);
+    expect(alias.name.name, 'F');
+    expect(alias.typeParameters.typeParameters, hasLength(3));
+    TypeParameter typeParam = alias.typeParameters.typeParameters[2];
+    NamedType type = typeParam.bound;
+    expect(type.typeArguments.arguments, hasLength(1));
+    expect(alias.equals, isNotNull);
+    expect(alias.functionType, isNotNull);
+    expect(alias.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_configuration_multiple() {
+    createParser("import 'lib/lib.dart' if (a) 'b.dart' if (c) 'd.dart';");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.configurations, hasLength(2));
+    expectDottedName(directive.configurations[0].name, ['a']);
+    expectDottedName(directive.configurations[1].name, ['c']);
+    expect(directive.deferredKeyword, isNull);
+    expect(directive.asKeyword, isNull);
+    expect(directive.prefix, isNull);
+    expect(directive.combinators, hasLength(0));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_configuration_single() {
+    createParser("import 'lib/lib.dart' if (a.b == 'c.dart') '';");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.configurations, hasLength(1));
+    expectDottedName(directive.configurations[0].name, ['a', 'b']);
+    expect(directive.deferredKeyword, isNull);
+    expect(directive.asKeyword, isNull);
+    expect(directive.prefix, isNull);
+    expect(directive.combinators, hasLength(0));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_deferred() {
+    createParser("import 'lib/lib.dart' deferred as a;");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.deferredKeyword, isNotNull);
+    expect(directive.asKeyword, isNotNull);
+    expect(directive.prefix, isNotNull);
+    expect(directive.combinators, hasLength(0));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_hide() {
+    createParser("import 'lib/lib.dart' hide A, B;");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.deferredKeyword, isNull);
+    expect(directive.asKeyword, isNull);
+    expect(directive.prefix, isNull);
+    expect(directive.combinators, hasLength(1));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_noCombinator() {
+    createParser("import 'lib/lib.dart';");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.deferredKeyword, isNull);
+    expect(directive.asKeyword, isNull);
+    expect(directive.prefix, isNull);
+    expect(directive.combinators, hasLength(0));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_prefix() {
+    createParser("import 'lib/lib.dart' as a;");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.deferredKeyword, isNull);
+    expect(directive.asKeyword, isNotNull);
+    expect(directive.prefix, isNotNull);
+    expect(directive.combinators, hasLength(0));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_prefix_hide_show() {
+    createParser("import 'lib/lib.dart' as a hide A show B;");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.deferredKeyword, isNull);
+    expect(directive.asKeyword, isNotNull);
+    expect(directive.prefix, isNotNull);
+    expect(directive.combinators, hasLength(2));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_prefix_show_hide() {
+    createParser("import 'lib/lib.dart' as a show B hide A;");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.deferredKeyword, isNull);
+    expect(directive.asKeyword, isNotNull);
+    expect(directive.prefix, isNotNull);
+    expect(directive.combinators, hasLength(2));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseImportDirective_show() {
+    createParser("import 'lib/lib.dart' show A, B;");
+    ImportDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.keyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.deferredKeyword, isNull);
+    expect(directive.asKeyword, isNull);
+    expect(directive.prefix, isNull);
+    expect(directive.combinators, hasLength(1));
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseLibraryDirective() {
+    createParser('library l;');
+    LibraryDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.libraryKeyword, isNotNull);
+    expect(directive.name, isNotNull);
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseMixinDeclaration_empty() {
+    createParser('mixin A {}');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.metadata, isEmpty);
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.onClause, isNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.mixinKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name.name, 'A');
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseMixinDeclaration_implements() {
+    createParser('mixin A implements B {}');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.metadata, isEmpty);
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.onClause, isNull);
+    ImplementsClause implementsClause = declaration.implementsClause;
+    expect(implementsClause.implementsKeyword, isNotNull);
+    NodeList<TypeName> interfaces = implementsClause.interfaces;
+    expect(interfaces, hasLength(1));
+    expect(interfaces[0].name.name, 'B');
+    expect(interfaces[0].typeArguments, isNull);
+    expect(declaration.mixinKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name.name, 'A');
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseMixinDeclaration_implements2() {
+    createParser('mixin A implements B<T>, C {}');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.metadata, isEmpty);
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.onClause, isNull);
+    ImplementsClause implementsClause = declaration.implementsClause;
+    expect(implementsClause.implementsKeyword, isNotNull);
+    NodeList<TypeName> interfaces = implementsClause.interfaces;
+    expect(interfaces, hasLength(2));
+    expect(interfaces[0].name.name, 'B');
+    expect(interfaces[0].typeArguments.arguments, hasLength(1));
+    expect(interfaces[1].name.name, 'C');
+    expect(interfaces[1].typeArguments, isNull);
+    expect(declaration.mixinKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name.name, 'A');
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseMixinDeclaration_metadata() {
+    createParser('@Z mixin A {}');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    NodeList<Annotation> metadata = declaration.metadata;
+    expect(metadata, hasLength(1));
+    expect(metadata[0].name.name, 'Z');
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.onClause, isNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.mixinKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name.name, 'A');
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseMixinDeclaration_on() {
+    createParser('mixin A on B {}');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.metadata, isEmpty);
+    expect(declaration.documentationComment, isNull);
+    OnClause onClause = declaration.onClause;
+    expect(onClause.onKeyword, isNotNull);
+    NodeList<TypeName> constraints = onClause.superclassConstraints;
+    expect(constraints, hasLength(1));
+    expect(constraints[0].name.name, 'B');
+    expect(constraints[0].typeArguments, isNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.mixinKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name.name, 'A');
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseMixinDeclaration_on2() {
+    createParser('mixin A on B, C<T> {}');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.metadata, isEmpty);
+    expect(declaration.documentationComment, isNull);
+    OnClause onClause = declaration.onClause;
+    expect(onClause.onKeyword, isNotNull);
+    NodeList<TypeName> constraints = onClause.superclassConstraints;
+    expect(constraints, hasLength(2));
+    expect(constraints[0].name.name, 'B');
+    expect(constraints[0].typeArguments, isNull);
+    expect(constraints[1].name.name, 'C');
+    expect(constraints[1].typeArguments.arguments, hasLength(1));
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.mixinKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name.name, 'A');
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseMixinDeclaration_onAndImplements() {
+    createParser('mixin A on B implements C {}');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.metadata, isEmpty);
+    expect(declaration.documentationComment, isNull);
+    OnClause onClause = declaration.onClause;
+    expect(onClause.onKeyword, isNotNull);
+    NodeList<TypeName> constraints = onClause.superclassConstraints;
+    expect(constraints, hasLength(1));
+    expect(constraints[0].name.name, 'B');
+    expect(constraints[0].typeArguments, isNull);
+    ImplementsClause implementsClause = declaration.implementsClause;
+    expect(implementsClause.implementsKeyword, isNotNull);
+    NodeList<TypeName> interfaces = implementsClause.interfaces;
+    expect(interfaces, hasLength(1));
+    expect(interfaces[0].name.name, 'C');
+    expect(interfaces[0].typeArguments, isNull);
+    expect(declaration.mixinKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name.name, 'A');
+    expect(declaration.members, hasLength(0));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseMixinDeclaration_simple() {
+    createParser('''
+mixin A {
+  int f;
+  int get g => f;
+  set s(int v) {f = v;}
+  int add(int v) => f = f + v;
+}''');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expect(declaration, isNotNull);
+    assertNoErrors();
+    expect(declaration.metadata, isEmpty);
+    expect(declaration.documentationComment, isNull);
+    expect(declaration.onClause, isNull);
+    expect(declaration.implementsClause, isNull);
+    expect(declaration.mixinKeyword, isNotNull);
+    expect(declaration.leftBracket, isNotNull);
+    expect(declaration.name.name, 'A');
+    expect(declaration.members, hasLength(4));
+    expect(declaration.rightBracket, isNotNull);
+    expect(declaration.typeParameters, isNull);
+  }
+
+  void test_parseMixinDeclaration_withDocumentationComment() {
+    createParser('/// Doc\nmixin M {}');
+    MixinDeclaration declaration = parseFullCompilationUnitMember();
+    expectCommentText(declaration.documentationComment, '/// Doc');
+  }
+
+  void test_parsePartDirective() {
+    createParser("part 'lib/lib.dart';");
+    PartDirective directive = parseFullDirective();
+    expect(directive, isNotNull);
+    assertNoErrors();
+    expect(directive.partKeyword, isNotNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parsePartOfDirective_name() {
+    enableUriInPartOf = true;
+    createParser("part of l;");
+    PartOfDirective directive = parseFullDirective();
+    expect(directive.partKeyword, isNotNull);
+    expect(directive.ofKeyword, isNotNull);
+    expect(directive.libraryName, isNotNull);
+    expect(directive.uri, isNull);
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parsePartOfDirective_uri() {
+    enableUriInPartOf = true;
+    createParser("part of 'lib.dart';");
+    PartOfDirective directive = parseFullDirective();
+    expect(directive.partKeyword, isNotNull);
+    expect(directive.ofKeyword, isNotNull);
+    expect(directive.libraryName, isNull);
+    expect(directive.uri, isNotNull);
+    expect(directive.semicolon, isNotNull);
+  }
+
+  void test_parseTopLevelVariable_external() {
+    var unit = parseCompilationUnit('external int i;', featureSet: nonNullable);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    expect(declaration.externalKeyword, isNotNull);
+  }
+
+  void test_parseTopLevelVariable_external_late() {
+    var unit = parseCompilationUnit('external late int? i;',
+        featureSet: nonNullable,
+        errors: [
+          expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
+        ]);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    expect(declaration.externalKeyword, isNotNull);
+  }
+
+  void test_parseTopLevelVariable_external_late_final() {
+    var unit = parseCompilationUnit('external late final int? i;',
+        featureSet: nonNullable,
+        errors: [
+          expectedError(ParserErrorCode.EXTERNAL_LATE_FIELD, 0, 8),
+        ]);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    expect(declaration.externalKeyword, isNotNull);
+  }
+
+  void test_parseTopLevelVariable_final_late() {
+    var unit = parseCompilationUnit('final late a;',
+        featureSet: nonNullable,
+        errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_late() {
+    var unit = parseCompilationUnit('late a;',
+        featureSet: nonNullable,
+        errors: [
+          expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
+        ]);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_late_final() {
+    var unit = parseCompilationUnit('late final a;', featureSet: nonNullable);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.keyword.lexeme, 'final');
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_late_init() {
+    var unit = parseCompilationUnit('late a = 0;',
+        featureSet: nonNullable,
+        errors: [
+          expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1)
+        ]);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_late_type() {
+    var unit = parseCompilationUnit('late A a;', featureSet: nonNullable);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    var declarationList = declaration.variables;
+    expect(declarationList.lateKeyword, isNotNull);
+    expect(declarationList.keyword, isNull);
+    expect(declarationList.type, isNotNull);
+    expect(declarationList.variables, hasLength(1));
+  }
+
+  void test_parseTopLevelVariable_non_external() {
+    var unit = parseCompilationUnit('int i;', featureSet: nonNullable);
+    var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
+    expect(declaration.externalKeyword, isNull);
+  }
+
+  void test_parseTypeAlias_function_noParameters() {
+    createParser('typedef bool F();');
+    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.parameters, isNotNull);
+    expect(typeAlias.returnType, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_function_noReturnType() {
+    createParser('typedef F();');
+    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.parameters, isNotNull);
+    expect(typeAlias.returnType, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_function_parameterizedReturnType() {
+    createParser('typedef A<B> F();');
+    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.parameters, isNotNull);
+    expect(typeAlias.returnType, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_function_parameters() {
+    createParser('typedef bool F(Object value);');
+    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.parameters, isNotNull);
+    expect(typeAlias.returnType, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_function_typeParameters() {
+    createParser('typedef bool F<E>();');
+    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.parameters, isNotNull);
+    expect(typeAlias.returnType, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    expect(typeAlias.typeParameters, isNotNull);
+  }
+
+  void test_parseTypeAlias_function_voidReturnType() {
+    createParser('typedef void F();');
+    FunctionTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.parameters, isNotNull);
+    expect(typeAlias.returnType, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_noParameters() {
+    createParser('typedef F = bool Function();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_noReturnType() {
+    createParser('typedef F = Function();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_parameterizedReturnType() {
+    createParser('typedef F = A<B> Function();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_parameters() {
+    createParser('typedef F = bool Function(Object value);');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_typeParameters() {
+    createParser('typedef F = bool Function<E>();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNotNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_typeParameters_noParameters() {
+    createParser('typedef F<T> = bool Function();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_typeParameters_noReturnType() {
+    createParser('typedef F<T> = Function();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void
+      test_parseTypeAlias_genericFunction_typeParameters_parameterizedReturnType() {
+    createParser('typedef F<T> = A<B> Function();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_typeParameters_parameters() {
+    createParser('typedef F<T> = bool Function(Object value);');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_typeParameters_typeParameters() {
+    createParser('typedef F<T> = bool Function<E>();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNotNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_typeParameters_voidReturnType() {
+    createParser('typedef F<T> = void Function();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNotNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_voidReturnType() {
+    createParser('typedef F = void Function();');
+    GenericTypeAlias typeAlias = parseFullCompilationUnitMember();
+    expect(typeAlias, isNotNull);
+    assertNoErrors();
+    expect(typeAlias.typedefKeyword, isNotNull);
+    expect(typeAlias.name, isNotNull);
+    expect(typeAlias.typeParameters, isNull);
+    expect(typeAlias.semicolon, isNotNull);
+    GenericFunctionType functionType = typeAlias.functionType;
+    expect(functionType, isNotNull);
+    expect(functionType.parameters, isNotNull);
+    expect(functionType.returnType, isNotNull);
+    expect(functionType.typeParameters, isNull);
+  }
+
+  void test_parseTypeAlias_genericFunction_withDocComment() {
+    createParser('/// Doc\ntypedef F = bool Function();');
+    var typeAlias = parseFullCompilationUnitMember() as GenericTypeAlias;
+    expectCommentText(typeAlias.documentationComment, '/// Doc');
+  }
+
+  void test_parseTypeVariable_withDocumentationComment() {
+    createParser('''
+class A<
+    /// Doc
+    B> {}
+''');
+    var classDeclaration = parseFullCompilationUnitMember() as ClassDeclaration;
+    var typeVariable = classDeclaration.typeParameters.typeParameters[0];
+    expectCommentText(typeVariable.documentationComment, '/// Doc');
+  }
+
+  /// Assert that the given [name] is in declaration context.
+  void _assertIsDeclarationName(SimpleIdentifier name) {
+    expect(name.inDeclarationContext(), isTrue);
+  }
+}
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 3c0dd2d..0d06335 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -48,6 +48,7 @@
 
     testLibrary = library_(
       uriStr: 'package:test/test.dart',
+      analysisContext: analysisContext,
       analysisSession: analysisContext.analysisSession,
       typeSystem: typeSystem,
     );
@@ -78,6 +79,7 @@
 
     testLibrary = library_(
       uriStr: 'package:test/test.dart',
+      analysisContext: analysisContext,
       analysisSession: analysisContext.analysisSession,
       typeSystem: typeSystem,
     );
diff --git a/pkg/analyzer/test/generated/variance_parser_test.dart b/pkg/analyzer/test/generated/variance_parser_test.dart
new file mode 100644
index 0000000..256eb10
--- /dev/null
+++ b/pkg/analyzer/test/generated/variance_parser_test.dart
@@ -0,0 +1,185 @@
+// 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'parser_test_base.dart';
+import 'test_support.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(VarianceParserTest);
+  });
+}
+
+@reflectiveTest
+class VarianceParserTest extends FastaParserTestCase {
+  @override
+  CompilationUnit parseCompilationUnit(String content,
+      {List<ErrorCode> codes,
+      List<ExpectedError> errors,
+      FeatureSet featureSet}) {
+    return super.parseCompilationUnit(content,
+        codes: codes,
+        errors: errors,
+        featureSet: featureSet ??
+            FeatureSet.forTesting(
+              sdkVersion: '2.5.0',
+              additionalFeatures: [Feature.variance],
+            ));
+  }
+
+  void test_class_disabled_multiple() {
+    parseCompilationUnit('class A<in T, inout U, out V> { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 2),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 14, 5),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 23, 3)
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_class_disabled_single() {
+    parseCompilationUnit('class A<out T> { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 3),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_class_enabled_multiple() {
+    var unit = parseCompilationUnit('class A<in T, inout U, out V, W> { }');
+    expect(unit.declarations, hasLength(1));
+    var classDecl = unit.declarations[0] as ClassDeclaration;
+    expect(classDecl.name.name, 'A');
+
+    expect(classDecl.typeParameters.typeParameters, hasLength(4));
+    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
+    expect(classDecl.typeParameters.typeParameters[1].name.name, 'U');
+    expect(classDecl.typeParameters.typeParameters[2].name.name, 'V');
+    expect(classDecl.typeParameters.typeParameters[3].name.name, 'W');
+
+    var typeParameterImplList = classDecl.typeParameters.typeParameters;
+    expect((typeParameterImplList[0] as TypeParameterImpl).varianceKeyword,
+        isNotNull);
+    expect(
+        (typeParameterImplList[0] as TypeParameterImpl).varianceKeyword.lexeme,
+        "in");
+    expect((typeParameterImplList[1] as TypeParameterImpl).varianceKeyword,
+        isNotNull);
+    expect(
+        (typeParameterImplList[1] as TypeParameterImpl).varianceKeyword.lexeme,
+        "inout");
+    expect((typeParameterImplList[2] as TypeParameterImpl).varianceKeyword,
+        isNotNull);
+    expect(
+        (typeParameterImplList[2] as TypeParameterImpl).varianceKeyword.lexeme,
+        "out");
+    expect((typeParameterImplList[3] as TypeParameterImpl).varianceKeyword,
+        isNull);
+  }
+
+  void test_class_enabled_multipleVariances() {
+    var unit = parseCompilationUnit('class A<in out inout T> { }', errors: [
+      expectedError(ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS, 11, 3),
+      expectedError(ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS, 15, 5)
+    ]);
+    expect(unit.declarations, hasLength(1));
+    var classDecl = unit.declarations[0] as ClassDeclaration;
+    expect(classDecl.name.name, 'A');
+    expect(classDecl.typeParameters.typeParameters, hasLength(1));
+    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
+  }
+
+  void test_class_enabled_single() {
+    var unit = parseCompilationUnit('class A<in T> { }');
+    expect(unit.declarations, hasLength(1));
+    var classDecl = unit.declarations[0] as ClassDeclaration;
+    expect(classDecl.name.name, 'A');
+    expect(classDecl.typeParameters.typeParameters, hasLength(1));
+    expect(classDecl.typeParameters.typeParameters[0].name.name, 'T');
+
+    var typeParameterImpl =
+        classDecl.typeParameters.typeParameters[0] as TypeParameterImpl;
+    expect(typeParameterImpl.varianceKeyword, isNotNull);
+    expect(typeParameterImpl.varianceKeyword.lexeme, "in");
+  }
+
+  void test_function_disabled() {
+    parseCompilationUnit('void A(in int value) {}',
+        errors: [
+          expectedError(
+              ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 2),
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_function_enabled() {
+    parseCompilationUnit('void A(in int value) {}', errors: [
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 2),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
+    ]);
+  }
+
+  void test_list_disabled() {
+    parseCompilationUnit('List<out String> stringList = [];',
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 6),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_list_enabled() {
+    parseCompilationUnit('List<out String> stringList = [];', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 6),
+    ]);
+  }
+
+  void test_mixin_disabled_multiple() {
+    parseCompilationUnit('mixin A<inout T, out U> { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 5),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 3),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_mixin_disabled_single() {
+    parseCompilationUnit('mixin A<inout T> { }',
+        errors: [
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 5),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_mixin_enabled_single() {
+    var unit = parseCompilationUnit('mixin A<inout T> { }');
+    expect(unit.declarations, hasLength(1));
+    var mixinDecl = unit.declarations[0] as MixinDeclaration;
+    expect(mixinDecl.name.name, 'A');
+    expect(mixinDecl.typeParameters.typeParameters, hasLength(1));
+    expect(mixinDecl.typeParameters.typeParameters[0].name.name, 'T');
+  }
+
+  void test_typedef_disabled() {
+    parseCompilationUnit('typedef A<inout X> = X Function(X);',
+        errors: [
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+        ],
+        featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+  }
+
+  void test_typedef_enabled() {
+    parseCompilationUnit('typedef A<inout X> = X Function(X);', errors: [
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/id_tests/assigned_variables_test.dart b/pkg/analyzer/test/id_tests/assigned_variables_test.dart
index f674c7c..00c8a11 100644
--- a/pkg/analyzer/test/id_tests/assigned_variables_test.dart
+++ b/pkg/analyzer/test/id_tests/assigned_variables_test.dart
@@ -69,12 +69,16 @@
     if (node == _currentDeclaration) {
       return _Data(
           _convertVars(_currentAssignedVariables.declaredAtTopLevel),
+          _convertVars(_currentAssignedVariables.readAnywhere),
+          _convertVars(_currentAssignedVariables.readCapturedAnywhere),
           _convertVars(_currentAssignedVariables.writtenAnywhere),
           _convertVars(_currentAssignedVariables.capturedAnywhere));
     }
     if (!_currentAssignedVariables.isTracked(node)) return null;
     return _Data(
         _convertVars(_currentAssignedVariables.declaredInNode(node)),
+        _convertVars(_currentAssignedVariables.readInNode(node)),
+        _convertVars(_currentAssignedVariables.readCapturedInNode(node)),
         _convertVars(_currentAssignedVariables.writtenInNode(node)),
         _convertVars(_currentAssignedVariables.capturedInNode(node)));
   }
@@ -123,6 +127,12 @@
     if (actualData.declared.isNotEmpty) {
       parts.add('declared=${_setToString(actualData.declared)}');
     }
+    if (actualData.read.isNotEmpty) {
+      parts.add('read=${_setToString(actualData.read)}');
+    }
+    if (actualData.readCaptured.isNotEmpty) {
+      parts.add('read=${_setToString(actualData.readCaptured)}');
+    }
     if (actualData.assigned.isNotEmpty) {
       parts.add('assigned=${_setToString(actualData.assigned)}');
     }
@@ -156,9 +166,14 @@
 class _Data {
   final Set<String> declared;
 
+  final Set<String> read;
+
+  final Set<String> readCaptured;
+
   final Set<String> assigned;
 
   final Set<String> captured;
 
-  _Data(this.declared, this.assigned, this.captured);
+  _Data(this.declared, this.read, this.readCaptured, this.assigned,
+      this.captured);
 }
diff --git a/pkg/analyzer/test/id_tests/nullability_test.dart b/pkg/analyzer/test/id_tests/nullability_test.dart
index 1490e2e..19c6869 100644
--- a/pkg/analyzer/test/id_tests/nullability_test.dart
+++ b/pkg/analyzer/test/id_tests/nullability_test.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -78,9 +79,9 @@
         !node.inDeclarationContext()) {
       var element = node.staticElement;
       if (element is LocalVariableElement || element is ParameterElement) {
-        TypeImpl promotedType = node.staticType;
+        TypeImpl promotedType = _readType(node);
         TypeImpl declaredType = (element as VariableElement).type;
-        var isPromoted = promotedType != declaredType;
+        var isPromoted = promotedType != null && promotedType != declaredType;
         if (isPromoted &&
             _typeSystem.isPotentiallyNullable(declaredType) &&
             !_typeSystem.isPotentiallyNullable(promotedType)) {
@@ -90,6 +91,19 @@
     }
     return null;
   }
+
+  static DartType _readType(SimpleIdentifier node) {
+    var parent = node.parent;
+    if (parent is AssignmentExpression && parent.leftHandSide == node) {
+      return parent.readType;
+    } else if (parent is PostfixExpression) {
+      return parent.readType;
+    } else if (parent is PrefixExpression) {
+      return parent.readType;
+    } else {
+      return node.staticType;
+    }
+  }
 }
 
 class _NullabilityDataInterpreter implements DataInterpreter<String> {
diff --git a/pkg/analyzer/test/id_tests/type_promotion_test.dart b/pkg/analyzer/test/id_tests/type_promotion_test.dart
index 54d8d09..177ce59 100644
--- a/pkg/analyzer/test/id_tests/type_promotion_test.dart
+++ b/pkg/analyzer/test/id_tests/type_promotion_test.dart
@@ -54,8 +54,8 @@
     if (node is SimpleIdentifier && node.inGetterContext()) {
       var element = _readElement(node);
       if (element is LocalVariableElement || element is ParameterElement) {
-        TypeImpl promotedType = _readType(node);
-        TypeImpl declaredType = (element as VariableElement).type;
+        var promotedType = _readType(node) as TypeImpl;
+        var declaredType = (element as VariableElement).type as TypeImpl;
         var isPromoted = promotedType != declaredType;
         if (isPromoted) {
           return promotedType;
diff --git a/pkg/analyzer/test/source/analysis_options_provider_test.dart b/pkg/analyzer/test/source/analysis_options_provider_test.dart
index 9e4eb9a..810d8d2 100644
--- a/pkg/analyzer/test/source/analysis_options_provider_test.dart
+++ b/pkg/analyzer/test/source/analysis_options_provider_test.dart
@@ -101,10 +101,10 @@
 
 @reflectiveTest
 class AnalysisOptionsProviderTest {
-  TestPathTranslator pathTranslator;
-  ResourceProvider resourceProvider;
+  /*late*/ TestPathTranslator pathTranslator;
+  /*late*/ ResourceProvider resourceProvider;
 
-  AnalysisOptionsProvider provider;
+  /*late*/ AnalysisOptionsProvider provider;
 
   String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
 
@@ -132,7 +132,7 @@
     YamlMap options = _getOptions('/foo/bar', crawlUp: true);
     expect(options, hasLength(1));
     {
-      YamlMap analyzer = getValue(options, 'analyzer');
+      var analyzer = getValue(options, 'analyzer') as YamlMap;
       expect(analyzer, isNotNull);
       expect(getValue(analyzer, 'ignore'), unorderedEquals(['bar']));
     }
@@ -153,7 +153,7 @@
     YamlMap options = _getOptions('/foo/bar/baz', crawlUp: true);
     expect(options, hasLength(1));
     {
-      YamlMap analyzer = getValue(options, 'analyzer');
+      var analyzer = getValue(options, 'analyzer') as YamlMap;
       expect(analyzer, isNotNull);
       expect(getValue(analyzer, 'ignore'), unorderedEquals(['bar']));
     }
@@ -185,10 +185,10 @@
     YamlMap options = _getOptions('/');
     expect(options, hasLength(2));
     {
-      YamlMap analyzer = getValue(options, 'analyzer');
+      var analyzer = getValue(options, 'analyzer') as YamlMap;
       expect(analyzer, hasLength(1));
       {
-        YamlList ignore = getValue(analyzer, 'ignore');
+        var ignore = getValue(analyzer, 'ignore') as YamlList;
         expect(ignore, hasLength(2));
         expect(ignore[0], 'ignoreme.dart');
         expect(ignore[1], 'sdk_ext/**');
@@ -220,10 +220,10 @@
     YamlMap options = _getOptions('/');
     expect(options, hasLength(1));
     {
-      YamlMap analyzer = getValue(options, 'analyzer');
+      var analyzer = getValue(options, 'analyzer') as YamlMap;
       expect(analyzer, hasLength(1));
       {
-        YamlList ignore = getValue(analyzer, 'ignore');
+        var ignore = getValue(analyzer, 'ignore') as YamlList;
         expect(ignore, hasLength(2));
         expect(ignore[0], 'ignoreme.dart');
         expect(ignore[1], 'sdk_ext/**');
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 7872242..588e22f 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -436,7 +436,11 @@
   void test_createWorkspace_noPackagesFile_hasGnMarkerFiles() {
     newFolder('/workspace/.jiri_root');
     newFile(
-        '/workspace/out/debug-x87_128/dartlang/gen/project/lib/lib.packages');
+        '/workspace/out/debug-x87_128/dartlang/gen/project/lib/lib_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": []
+}''');
     Workspace workspace = ContextBuilder.createWorkspace(resourceProvider,
         convertPath('/workspace/project/lib/lib.dart'), builder);
     expect(workspace, TypeMatcher<GnWorkspace>());
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index f9e47a8..91a5398 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -4,8 +4,6 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
@@ -16,7 +14,6 @@
 import 'package:analyzer/src/dart/analysis/status.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/parser.dart' as analyzer;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
@@ -26,26 +23,6 @@
 import 'package:pub_semver/pub_semver.dart';
 import 'package:test/test.dart';
 
-/// Finds an [Element] with the given [name].
-Element findChildElement(Element root, String name, [ElementKind kind]) {
-  Element result;
-  root.accept(_ElementVisitorFunctionWrapper((Element element) {
-    if (element.name != name) {
-      return;
-    }
-    if (kind != null && element.kind != kind) {
-      return;
-    }
-    result = element;
-  }));
-  return result;
-}
-
-typedef Predicate<E> = bool Function(E argument);
-
-/// A function to be called for every [Element].
-typedef _ElementVisitorFunction = void Function(Element element);
-
 class BaseAnalysisDriverTest with ResourceProviderMixin {
   DartSdk sdk;
   final ByteStore byteStore = MemoryByteStore();
@@ -125,7 +102,7 @@
   }
 
   AnalysisOptionsImpl createAnalysisOptions() => AnalysisOptionsImpl()
-    ..useFastaParser = analyzer.Parser.useFasta
+    ..useFastaParser = true
     ..contextFeatures = FeatureSet.fromEnableFlags2(
       sdkLanguageVersion: ExperimentStatus.testingSdkLanguageVersion,
       flags: enabledExperiments,
@@ -177,19 +154,6 @@
   void tearDown() {}
 }
 
-/// Wraps an [_ElementVisitorFunction] into a [GeneralizingElementVisitor].
-class _ElementVisitorFunctionWrapper extends GeneralizingElementVisitor {
-  final _ElementVisitorFunction function;
-
-  _ElementVisitorFunctionWrapper(this.function);
-
-  @override
-  visitElement(Element element) {
-    function(element);
-    super.visitElement(element);
-  }
-}
-
 class _GeneratedUriResolverMock implements UriResolver {
   Source Function(Uri, Uri) resolveAbsoluteFunction;
 
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 a54fa1a..439d445 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
@@ -88,4 +88,14 @@
     expect(context.driver.sourceFactory.dartSdk.mapDartUri('dart:core'),
         sdk.mapDartUri('dart:core'));
   }
+
+  test_createContext_sdkRoot() {
+    MockSdk(resourceProvider: resourceProvider);
+    var context = contextBuilder.createContext(
+        contextRoot: contextRoot,
+        sdkPath: resourceProvider.convertPath(sdkRoot));
+    expect(context.analysisOptions, isNotNull);
+    expect(context.contextRoot, contextRoot);
+    expect(context.sdkRoot?.path, resourceProvider.convertPath(sdkRoot));
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/analysis/defined_names_test.dart b/pkg/analyzer/test/src/dart/analysis/defined_names_test.dart
index 63f3ad4..0f3fae7 100644
--- a/pkg/analyzer/test/src/dart/analysis/defined_names_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/defined_names_test.dart
@@ -7,7 +7,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/parser_test.dart';
+import '../../../generated/parser_test_base.dart';
 
 main() {
   defineReflectiveSuite(() {
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 30433aa..31db512 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
@@ -22,6 +22,47 @@
     return driver.test.libraryContext.linkedCycles;
   }
 
+  test_change_field_staticFinal_hasConstConstructor_changeInitializer() async {
+    useEmptyByteStore();
+
+    newFile(testFilePath, content: r'''
+class A {
+  static const a = 0;
+  static const b = 1;
+  static final Set<int> f = {a};
+  const A {}
+}
+''');
+
+    await resolveTestFile();
+    assertType(findElement.field('f').type, 'Set<int>');
+
+    // The summary for the library was linked.
+    _assertContainsLinkedCycle({testFilePath}, andClear: true);
+
+    // Dispose the collection, with its driver.
+    // The next analysis will recreate it.
+    // We will reuse the byte store, so can reuse summaries.
+    disposeAnalysisContextCollection();
+
+    newFile(testFilePath, content: r'''
+class A {
+  static const a = 0;
+  static const b = 1;
+  static final Set<int> f = <int>{a, b, 2};
+  const A {}
+}
+''');
+
+    await resolveTestFile();
+    assertType(findElement.field('f').type, 'Set<int>');
+
+    // We changed the initializer of the final field. But it is static, so
+    // even though the class hsa a constant constructor, we don't need its
+    // initializer, so nothing should be linked.
+    _assertNoLinkedCycles();
+  }
+
   test_change_functionBody() async {
     useEmptyByteStore();
 
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 3ba26a1..25d5b03 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -6253,7 +6253,7 @@
     var myLibrary = myImport.importedLibrary;
     var myUnit = myLibrary.definingCompilationUnit;
     var myClass = myUnit.types.single;
-    var myFunctionTypeAlias = myUnit.functionTypeAliases.single;
+    var myTypeAlias = myUnit.typeAliases.single;
     var myTopVariable = myUnit.topLevelVariables[0];
     var myTopFunction = myUnit.functions.single;
     var myGetter = myUnit.topLevelVariables[1].getter;
@@ -6280,7 +6280,7 @@
     }
 
     assertPrefixedIdentifier(0, myClass, typeProvider.typeType);
-    assertPrefixedIdentifier(1, myFunctionTypeAlias, typeProvider.typeType);
+    assertPrefixedIdentifier(1, myTypeAlias, typeProvider.typeType);
     assertPrefixedIdentifier(2, myTopVariable.getter, typeProvider.intType);
 
     {
@@ -7597,25 +7597,24 @@
 
     await resolveTestFile();
     CompilationUnit unit = result.unit;
-    CompilationUnitElement unitElement = unit.declaredElement;
 
     FunctionTypeAlias alias = unit.declarations[0];
-    FunctionTypeAliasElement aliasElement = alias.declaredElement;
-    GenericFunctionTypeElement aliasFunction = aliasElement.function;
-    expect(aliasElement, same(unitElement.functionTypeAliases[0]));
-    expect(aliasFunction.returnType, typeProvider.intType);
+    TypeAliasElement aliasElement = alias.declaredElement;
+    var function = aliasElement.aliasedElement as GenericFunctionTypeElement;
+    expect(aliasElement, same(findElement.typeAlias('F')));
+    expect(function.returnType, typeProvider.intType);
 
     _assertTypeNameSimple(alias.returnType, typeProvider.intType);
 
     _assertSimpleParameter(
-        alias.parameters.parameters[0], aliasFunction.parameters[0],
+        alias.parameters.parameters[0], function.parameters[0],
         name: 'a',
         offset: 22,
         kind: ParameterKind.REQUIRED,
         type: typeProvider.boolType);
 
     _assertSimpleParameter(
-        alias.parameters.parameters[1], aliasFunction.parameters[1],
+        alias.parameters.parameters[1], function.parameters[1],
         name: 'b',
         offset: 27,
         kind: ParameterKind.REQUIRED,
@@ -7824,7 +7823,7 @@
     await resolveTestFile();
 
     FunctionTypeAlias alias = findNode.functionTypeAlias('F<T>');
-    FunctionTypeAliasElement aliasElement = alias.declaredElement;
+    TypeAliasElement aliasElement = alias.declaredElement;
 
     FieldDeclaration fDeclaration = findNode.fieldDeclaration('F<int> f');
 
@@ -7916,7 +7915,7 @@
     CompilationUnit unit = result.unit;
 
     FunctionTypeAlias fNode = unit.declarations[1];
-    FunctionTypeAliasElement fElement = fNode.declaredElement;
+    TypeAliasElement fElement = fNode.declaredElement;
 
     var statements = _getMainStatements(result);
 
@@ -8542,11 +8541,10 @@
       SimpleIdentifier identifier = prefixed.identifier;
       assertSimpleIdentifier(
         identifier,
-        readElement: elementMatcher(
+        element: elementMatcher(
           objectHashCode,
           isLegacy: isNullSafetySdkAndLegacyLibrary,
         ),
-        writeElement: null,
         type: 'int',
       );
     }
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index bcea8e7..56774cd 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -283,11 +283,9 @@
 part 'not_dart.txt';
 ''');
     FileState file = fileSystemState.getFileForPath(a);
-    expect(_excludeSdk(file.importedFiles).map((f) => f.path),
-        unorderedEquals([b, not_dart]));
-    expect(
-        file.exportedFiles.map((f) => f.path), unorderedEquals([c, not_dart]));
-    expect(file.partedFiles.map((f) => f.path), unorderedEquals([d, not_dart]));
+    expect(_excludeSdk(file.importedFiles).map((f) => f.path), [b, not_dart]);
+    expect(file.exportedFiles.map((f) => f.path), [c, not_dart]);
+    expect(file.partedFiles.map((f) => f.path), [d, not_dart]);
     expect(_excludeSdk(fileSystemState.knownFilePaths),
         unorderedEquals([a, b, c, d, not_dart]));
   }
@@ -350,10 +348,7 @@
   test_getFileForUri_invalidUri() {
     var uri = Uri.parse('package:x');
     var file = fileSystemState.getFileForUri(uri);
-    expect(file.isUnresolved, isTrue);
-    expect(file.uri, isNull);
-    expect(file.path, isNull);
-    expect(file.isPart, isFalse);
+    expect(file, isNull);
   }
 
   test_getFileForUri_packageVsFileUri() {
@@ -671,9 +666,7 @@
   }
 
   void _assertIsUnresolvedFile(FileState file) {
-    expect(file.path, isNull);
-    expect(file.uri, isNull);
-    expect(file.source, isNull);
+    expect(file, isNull);
   }
 
   void _assertLibraryCycle(
@@ -694,6 +687,8 @@
         return !file.libraries.any((file) => file.uri.isScheme('dart'));
       } else if (file is FileState) {
         return file.uri?.scheme != 'dart';
+      } else if (file == null) {
+        return true;
       } else {
         return !(file as String).startsWith(convertPath('/sdk'));
       }
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index b73f5bf..21fcfc4 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -4,66 +4,38 @@
 
 import 'dart:convert';
 
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/index.dart';
-import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:analyzer/src/test_utilities/find_element.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'base.dart';
+import '../resolution/context_collection_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(IndexTest);
+    defineReflectiveTests(IndexWithNonFunctionTypeAliasesTest);
   });
 }
 
 class ExpectedLocation {
-  final CompilationUnitElement unitElement;
   final int offset;
   final int length;
   final bool isQualified;
 
-  ExpectedLocation(
-      this.unitElement, this.offset, this.length, this.isQualified);
+  ExpectedLocation(this.offset, this.length, this.isQualified);
 
   @override
   String toString() {
-    return '(unit=$unitElement; offset=$offset; length=$length;'
-        ' isQualified=$isQualified)';
+    return '(offset=$offset; length=$length; isQualified=$isQualified)';
   }
 }
 
 @reflectiveTest
-class IndexTest extends BaseAnalysisDriverTest {
-  CompilationUnit testUnit;
-  CompilationUnitElement testUnitElement;
-  LibraryElement testLibraryElement;
-
-  AnalysisDriverUnitIndex index;
-
-  _ElementIndexAssert assertThat(Element element) {
-    List<_Relation> relations = _getElementRelations(element);
-    return _ElementIndexAssert(this, element, relations);
-  }
-
-  _NameIndexAssert assertThatName(String name) {
-    return _NameIndexAssert(this, name);
-  }
-
-  Element findElement(String name, [ElementKind kind]) {
-    return findChildElement(testUnitElement, name, kind);
-  }
-
-  CompilationUnitElement importedUnit({int index = 0}) {
-    List<ImportElement> imports = testLibraryElement.imports;
-    return imports[index].importedLibrary.definingCompilationUnit;
-  }
-
+class IndexTest extends PubPackageResolutionTest with _IndexMixin {
   test_fieldFormalParameter_noSuchField() async {
     await _indexTestUnit('''
 class B<T> {
@@ -88,7 +60,7 @@
 class C4 implements B2 {}
 class M extends Object with A {}
 ''');
-    ClassElement classElementA = findElement("A");
+    ClassElement classElementA = findElement.class_('A');
     assertThat(classElementA)
       ..isAncestorOf('B1 extends A')
       ..isAncestorOf('B2 implements A')
@@ -106,8 +78,8 @@
 class C1 = Object with A;
 class C2 = Object with B;
 ''');
-    ClassElement classElementA = findElement('A');
-    ClassElement classElementB = findElement('B');
+    ClassElement classElementA = findElement.class_('A');
+    ClassElement classElementB = findElement.class_('B');
     assertThat(classElementA)
       ..isAncestorOf('C1 = Object with A')
       ..isAncestorOf('C2 = Object with B');
@@ -125,7 +97,7 @@
 mixin M4 implements B {}
 mixin M5 on M2 {}
 ''');
-    ClassElement classElementA = findElement('A');
+    ClassElement classElementA = findElement.class_('A');
     assertThat(classElementA)
       ..isAncestorOf('B extends A')
       ..isAncestorOf('M1 on A')
@@ -136,14 +108,14 @@
   }
 
   test_isExtendedBy_ClassDeclaration_isQualified() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 class A {}
 ''');
     await _indexTestUnit('''
 import 'lib.dart' as p;
 class B extends p.A {} // 2
 ''');
-    ClassElement elementA = importedUnit().getType('A');
+    ClassElement elementA = importFindLib().class_('A');
     assertThat(elementA).isExtendedAt('A {} // 2', true);
   }
 
@@ -151,7 +123,7 @@
     await _indexTestUnit('''
 class A {}
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.class_('A');
     ClassElement elementObject = elementA.supertype.element;
     assertThat(elementObject).isExtendedAt('A {}', true, length: 0);
   }
@@ -162,14 +134,14 @@
 class B {}
 class C = A with B;
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.class_('A');
     assertThat(elementA)
       ..isExtendedAt('A with', false)
       ..isReferencedAt('A with', false);
   }
 
   test_isExtendedBy_ClassTypeAlias_isQualified() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 class A {}
 ''');
     await _indexTestUnit('''
@@ -177,7 +149,7 @@
 class B {}
 class C = p.A with B;
 ''');
-    ClassElement elementA = importedUnit().getType('A');
+    ClassElement elementA = importFindLib().class_('A');
     assertThat(elementA)
       ..isExtendedAt('A with', true)
       ..isReferencedAt('A with', true);
@@ -188,21 +160,21 @@
 class A {} // 1
 class B implements A {} // 2
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.class_('A');
     assertThat(elementA)
       ..isImplementedAt('A {} // 2', false)
       ..isReferencedAt('A {} // 2', false);
   }
 
   test_isImplementedBy_ClassDeclaration_isQualified() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 class A {}
 ''');
     await _indexTestUnit('''
 import 'lib.dart' as p;
 class B implements p.A {} // 2
 ''');
-    ClassElement elementA = importedUnit().getType('A');
+    ClassElement elementA = importFindLib().class_('A');
     assertThat(elementA)
       ..isImplementedAt('A {} // 2', true)
       ..isReferencedAt('A {} // 2', true);
@@ -214,7 +186,7 @@
 class B {} // 2
 class C = Object with A implements B; // 3
 ''');
-    ClassElement elementB = findElement('B');
+    ClassElement elementB = findElement.class_('B');
     assertThat(elementB)
       ..isImplementedAt('B; // 3', false)
       ..isReferencedAt('B; // 3', false);
@@ -225,7 +197,7 @@
 class A {} // 1
 mixin M implements A {} // 2
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.class_('A');
     assertThat(elementA)
       ..isImplementedAt('A {} // 2', false)
       ..isReferencedAt('A {} // 2', false);
@@ -236,14 +208,14 @@
 class A {} // 1
 mixin M on A {} // 2
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.class_('A');
     assertThat(elementA)
       ..isImplementedAt('A {} // 2', false)
       ..isReferencedAt('A {} // 2', false);
   }
 
   test_isInvokedBy_FunctionElement() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 library lib;
 foo() {}
 ''');
@@ -254,7 +226,7 @@
   pref.foo(); // q
   foo(); // nq
 }''');
-    FunctionElement element = importedUnit().functions[0];
+    FunctionElement element = importFindLib().topFunction('foo');
     assertThat(element)
       ..isInvokedAt('foo(); // q', true)
       ..isInvokedAt('foo(); // nq', false);
@@ -268,7 +240,7 @@
   math.loadLibrary(); // 2
 }
 ''');
-    LibraryElement mathLib = testLibraryElement.imports[0].importedLibrary;
+    LibraryElement mathLib = findElement.import('dart:math').importedLibrary;
     FunctionElement element = mathLib.loadLibraryFunction;
     assertThat(element).isInvokedAt('loadLibrary(); // 1', true);
     assertThat(element).isInvokedAt('loadLibrary(); // 2', true);
@@ -283,7 +255,7 @@
     foo(); // nq
   }
 }''');
-    Element element = findElement('foo');
+    MethodElement element = findElement.method('foo');
     assertThat(element)
       ..isInvokedAt('foo(); // q', true)
       ..isInvokedAt('foo(); // nq', false);
@@ -299,7 +271,7 @@
   0.foo();
 }
 ''');
-    MethodElement element = findElement('foo');
+    MethodElement element = findElement.method('foo');
     assertThat(element)..isInvokedAt('foo();', true);
   }
 
@@ -313,7 +285,7 @@
   E.foo();
 }
 ''');
-    MethodElement element = findElement('foo');
+    MethodElement element = findElement.method('foo');
     assertThat(element)..isInvokedAt('foo();', true);
   }
 
@@ -332,7 +304,6 @@
   (1.2).foo(); // double ref
 }
 ''');
-    var findNode = FindNode(testCode, testUnit);
 
     var intMethod = findNode.methodDeclaration('foo() {} // int');
     assertThat(intMethod.declaredElement)
@@ -353,7 +324,7 @@
   a.foo();
 }
 ''');
-    Element element = findElement('foo');
+    MethodElement element = findElement.method('foo');
     assertThat(element).isInvokedAt('foo();', true);
   }
 
@@ -369,7 +340,7 @@
   a++;
 }
 ''');
-    MethodElement element = findElement('+');
+    MethodElement element = findElement.method('+');
     assertThat(element)
       ..isInvokedAt('+ 1', true, length: 1)
       ..isInvokedAt('+= 2', true, length: 2)
@@ -388,8 +359,8 @@
   a[1] = 42;
 }
 ''');
-    MethodElement readElement = findElement('[]');
-    MethodElement writeElement = findElement('[]=');
+    MethodElement readElement = findElement.method('[]');
+    MethodElement writeElement = findElement.method('[]=');
     assertThat(readElement).isInvokedAt('[0]', true, length: 1);
     assertThat(writeElement).isInvokedAt('[1]', true, length: 1);
   }
@@ -403,7 +374,7 @@
   print(~a);
 }
 ''');
-    MethodElement element = findElement('~');
+    MethodElement element = findElement.method('~');
     assertThat(element).isInvokedAt('~a', true, length: 1);
   }
 
@@ -412,21 +383,21 @@
 class A {} // 1
 class B extends Object with A {} // 2
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.class_('A');
     assertThat(elementA)
       ..isMixedInAt('A {} // 2', false)
       ..isReferencedAt('A {} // 2', false);
   }
 
   test_isMixedInBy_ClassDeclaration_isQualified() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 class A {}
 ''');
     await _indexTestUnit('''
 import 'lib.dart' as p;
 class B extends Object with p.A {} // 2
 ''');
-    ClassElement elementA = importedUnit().getType('A');
+    ClassElement elementA = importFindLib().class_('A');
     assertThat(elementA).isMixedInAt('A {} // 2', true);
   }
 
@@ -435,7 +406,7 @@
 mixin A {} // 1
 class B extends Object with A {} // 2
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.mixin('A');
     assertThat(elementA)
       ..isMixedInAt('A {} // 2', false)
       ..isReferencedAt('A {} // 2', false);
@@ -446,7 +417,7 @@
 class A {} // 1
 class B = Object with A; // 2
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.class_('A');
     assertThat(elementA).isMixedInAt('A; // 2', false);
   }
 
@@ -455,7 +426,7 @@
 mixin A {} // 1
 class B = Object with A; // 2
 ''');
-    ClassElement elementA = findElement('A');
+    ClassElement elementA = findElement.mixin('A');
     assertThat(elementA).isMixedInAt('A; // 2', false);
   }
 
@@ -468,7 +439,7 @@
     field(); // nq
   }
 }''');
-    FieldElement field = findElement('field');
+    FieldElement field = findElement.field('field');
     assertThat(field.getter)
       ..isReferencedAt('field(); // q', true)
       ..isReferencedAt('field(); // nq', false);
@@ -483,7 +454,7 @@
     ggg(); // nq
   }
 }''');
-    PropertyAccessorElement element = findElement('ggg', ElementKind.GETTER);
+    PropertyAccessorElement element = findElement.getter('ggg');
     assertThat(element)
       ..isReferencedAt('ggg(); // q', true)
       ..isReferencedAt('ggg(); // nq', false);
@@ -501,7 +472,7 @@
   print(A.field); // 3
 }
 ''');
-    ClassElement element = findElement('A');
+    ClassElement element = findElement.class_('A');
     assertThat(element)
       ..isReferencedAt('A p) {', false)
       ..isReferencedAt('A v;', false)
@@ -519,7 +490,7 @@
   MyEnum.a;
 }
 ''');
-    ClassElement element = findElement('MyEnum');
+    ClassElement element = findElement.enum_('MyEnum');
     assertThat(element)
       ..isReferencedAt('MyEnum p) {', false)
       ..isReferencedAt('MyEnum v;', false)
@@ -532,22 +503,22 @@
 
 extension E on A<int> {}
 ''');
-    ClassElement element = findElement('A');
+    ClassElement element = findElement.class_('A');
     assertThat(element)..isReferencedAt('A<int>', false);
   }
 
-  test_isReferencedBy_ClassElement_invocation() async {
+  test_isReferencedBy_ClassElement_implicitNew() async {
     await _indexTestUnit('''
 class A {}
 main() {
   A(); // invalid code, but still a reference
 }''');
-    Element element = findElement('A');
+    ClassElement element = findElement.class_('A');
     assertThat(element).isReferencedAt('A();', false);
   }
 
   test_isReferencedBy_ClassElement_invocation_isQualified() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 class A {}
 ''');
     await _indexTestUnit('''
@@ -555,7 +526,7 @@
 main() {
   p.A(); // invalid code, but still a reference
 }''');
-    Element element = importedUnit().getType('A');
+    Element element = importFindLib().class_('A');
     assertThat(element).isReferencedAt('A();', true);
   }
 
@@ -567,7 +538,7 @@
   f<A>();
 }
 ''');
-    Element element = findElement('A');
+    ClassElement element = findElement.class_('A');
     assertThat(element)..isReferencedAt('A>();', false);
   }
 
@@ -579,47 +550,47 @@
   B v;
 }
 ''');
-    ClassElement element = findElement('B');
+    ClassElement element = findElement.class_('B');
     assertThat(element)
       ..isReferencedAt('B p) {', false)
       ..isReferencedAt('B v;', false);
   }
 
   test_isReferencedBy_CompilationUnitElement_export() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 library lib;
 ''');
     await _indexTestUnit('''
 export 'lib.dart';
 ''');
-    LibraryElement element = testLibraryElement.exports[0].exportedLibrary;
+    var element = findElement.export('package:test/lib.dart').exportedLibrary;
     assertThat(element)..isReferencedAt("'lib.dart'", true, length: 10);
   }
 
   test_isReferencedBy_CompilationUnitElement_import() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 library lib;
 ''');
     await _indexTestUnit('''
 import 'lib.dart';
 ''');
-    LibraryElement element = testLibraryElement.imports[0].importedLibrary;
+    var element = findElement.import('package:test/lib.dart').importedLibrary;
     assertThat(element)..isReferencedAt("'lib.dart'", true, length: 10);
   }
 
   test_isReferencedBy_CompilationUnitElement_part() async {
-    newFile('$testProject2/my_unit.dart', content: 'part of my_lib;');
+    newFile('$testPackageLibPath/my_unit.dart', content: 'part of my_lib;');
     await _indexTestUnit('''
 library my_lib;
 part 'my_unit.dart';
 ''');
-    CompilationUnitElement element = testLibraryElement.parts[0];
+    var element = findElement.part('my_unit.dart');
     assertThat(element)..isReferencedAt("'my_unit.dart';", true, length: 14);
   }
 
   test_isReferencedBy_CompilationUnitElement_part_inPart() async {
-    newFile('$testProject2/a.dart', content: 'part of lib;');
-    newFile('$testProject2/b.dart', content: '''
+    newFile('$testPackageLibPath/a.dart', content: 'part of lib;');
+    newFile('$testPackageLibPath/b.dart', content: '''
 library lib;
 part 'a.dart';
 ''');
@@ -645,9 +616,8 @@
   new A.foo(); // 5
 }
 ''');
-    ClassElement classA = findElement('A');
-    ConstructorElement constA = classA.constructors[0];
-    ConstructorElement constA_foo = classA.constructors[1];
+    var constA = findElement.unnamedConstructor('A');
+    var constA_foo = findElement.constructor('foo', of: 'A');
     // A()
     assertThat(constA)
       ..hasRelationCount(2)
@@ -677,9 +647,8 @@
   new C.named(); // C2
 }
 ''');
-    ClassElement classA = findElement('A');
-    ConstructorElement constA = classA.constructors[0];
-    ConstructorElement constA_named = classA.constructors[1];
+    var constA = findElement.unnamedConstructor('A');
+    var constA_named = findElement.constructor('named', of: 'A');
     assertThat(constA)
       ..isReferencedAt('(); // B1', true, length: 0)
       ..isReferencedAt('(); // C1', true, length: 0);
@@ -711,8 +680,9 @@
 }
 ''');
     // has ".named()", but does not have "named()"
-    int offsetWithoutDot = findOffset('named();');
-    int offsetWithDot = findOffset('.named();');
+    var constructorName = findNode.constructorName('.named();');
+    var offsetWithoutDot = constructorName.name.offset;
+    var offsetWithDot = constructorName.period.offset;
     expect(index.usedElementOffsets, isNot(contains(offsetWithoutDot)));
     expect(index.usedElementOffsets, contains(offsetWithDot));
   }
@@ -725,9 +695,8 @@
   A.bar();
 }
 ''');
-    ClassElement classA = findElement('A');
-    ConstructorElement constA = classA.constructors[0];
-    ConstructorElement constA_bar = classA.constructors[2];
+    var constA = findElement.unnamedConstructor('A');
+    var constA_bar = findElement.constructor('bar');
     assertThat(constA).isReferencedAt('(); // 2', true, length: 0);
     assertThat(constA_bar).isReferencedAt('.bar(); // 1', true, length: 4);
   }
@@ -739,8 +708,7 @@
   new A(); // 1
 }
 ''');
-    ClassElement classA = findElement('A');
-    ConstructorElement constA = classA.constructors[0];
+    var constA = findElement.unnamedConstructor('A');
     // A()
     assertThat(constA)..isReferencedAt('(); // 1', true, length: 0);
   }
@@ -762,7 +730,7 @@
   E(0).foo();
 }
 ''');
-    ExtensionElement element = findElement('E');
+    ExtensionElement element = findElement.extension_('E');
     assertThat(element)..isReferencedAt('E(0).foo()', false);
   }
 
@@ -782,7 +750,7 @@
   new A(field: 4);
 }
 ''');
-    FieldElement field = findElement('field', ElementKind.FIELD);
+    FieldElement field = findElement.field('field');
     PropertyAccessorElement getter = field.getter;
     PropertyAccessorElement setter = field.setter;
     // A()
@@ -812,7 +780,7 @@
 ''');
     // aaa
     {
-      FieldElement field = findElement('aaa', ElementKind.FIELD);
+      FieldElement field = findElement.field('aaa');
       PropertyAccessorElement getter = field.getter;
       PropertyAccessorElement setter = field.setter;
       assertThat(field)..isWrittenAt('aaa, ', true);
@@ -821,7 +789,7 @@
     }
     // bbb
     {
-      FieldElement field = findElement('bbb', ElementKind.FIELD);
+      FieldElement field = findElement.field('bbb');
       PropertyAccessorElement getter = field.getter;
       PropertyAccessorElement setter = field.setter;
       assertThat(field)..isWrittenAt('bbb) {}', true);
@@ -842,7 +810,7 @@
   print(MyEnum.B);
 }
 ''');
-    ClassElement enumElement = findElement('MyEnum');
+    ClassElement enumElement = findElement.enum_('MyEnum');
     assertThat(enumElement.getGetter('values'))
       ..isReferencedAt('values);', true);
     assertThat(enumElement.getGetter('index'))..isReferencedAt('index);', true);
@@ -857,7 +825,7 @@
   int get f => 0;
 }
 ''');
-    ClassElement element2 = findElement('A');
+    ClassElement element2 = findElement.class_('A');
     assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
   }
 
@@ -869,7 +837,7 @@
   set f(_) {}
 }
 ''');
-    ClassElement element2 = findElement('A');
+    ClassElement element2 = findElement.class_('A');
     assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
   }
 
@@ -880,7 +848,7 @@
   set f(_) {}
 }
 ''');
-    ClassElement element2 = findElement('A');
+    ClassElement element2 = findElement.class_('A');
     assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
   }
 
@@ -892,14 +860,14 @@
   print(foo());
 }
 ''');
-    FunctionElement element = findElement('foo');
+    FunctionElement element = findElement.topFunction('foo');
     assertThat(element)
       ..isReferencedAt('foo);', false)
       ..isInvokedAt('foo());', false);
   }
 
   test_isReferencedBy_FunctionElement_with_LibraryElement() async {
-    newFile('$testProject2/foo.dart', content: r'''
+    newFile('$testPackageLibPath/foo.dart', content: r'''
 bar() {}
 ''');
     await _indexTestUnit('''
@@ -908,12 +876,13 @@
   bar();
 }
 ''');
-    LibraryElement fooLibrary = testLibraryElement.imports[0].importedLibrary;
-    assertThat(fooLibrary)..isReferencedAt('"foo.dart";', true, length: 10);
-    {
-      FunctionElement bar = fooLibrary.definingCompilationUnit.functions[0];
-      assertThat(bar)..isInvokedAt('bar();', false);
-    }
+
+    var importFind = findElement.importFind('package:test/foo.dart');
+    assertThat(importFind.importedLibrary)
+      ..isReferencedAt('"foo.dart";', true, length: 10);
+
+    FunctionElement bar = importFind.topFunction('bar');
+    assertThat(bar)..isInvokedAt('bar();', false);
   }
 
   test_isReferencedBy_FunctionTypeAliasElement() async {
@@ -922,7 +891,7 @@
 main(A p) {
 }
 ''');
-    Element element = findElement('A');
+    Element element = findElement.typeAlias('A');
     assertThat(element)..isReferencedAt('A p) {', false);
   }
 
@@ -937,7 +906,7 @@
 /// [A] text
 var myVariable = null;
 ''');
-    Element element = findElement('A');
+    Element element = findElement.class_('A');
     assertThat(element)..isReferencedAt('A] text', false);
   }
 
@@ -950,15 +919,15 @@
     print(method); // nq
   }
 }''');
-    MethodElement element = findElement('method');
+    MethodElement element = findElement.method('method');
     assertThat(element)
       ..isReferencedAt('method); // q', true)
       ..isReferencedAt('method); // nq', false);
   }
 
   test_isReferencedBy_MultiplyDefinedElement() async {
-    newFile('$testProject2/a1.dart', content: 'class A {}');
-    newFile('$testProject2/a2.dart', content: 'class A {}');
+    newFile('$testPackageLibPath/a1.dart', content: 'class A {}');
+    newFile('$testPackageLibPath/a2.dart', content: 'class A {}');
     await _indexTestUnit('''
 import 'a1.dart';
 import 'a2.dart';
@@ -980,7 +949,7 @@
   foo(p: 1);
 }
 ''');
-    Element element = findElement('p');
+    Element element = findElement.parameter('p');
     assertThat(element)..isReferencedAt('p: 1', true);
   }
 
@@ -1035,7 +1004,7 @@
   A(test: 0);
 }
 ''');
-    Element element = findElement('test');
+    Element element = findElement.parameter('test');
     assertThat(element)..isReferencedAt('test: 0', true);
   }
 
@@ -1049,7 +1018,7 @@
   a.foo(test: 0);
 }
 ''');
-    Element element = findElement('test');
+    Element element = findElement.parameter('test');
     assertThat(element)..isReferencedAt('test: 0', true);
   }
 
@@ -1062,7 +1031,7 @@
   foo(1); // 2
 }
 ''');
-    Element element = findElement('p');
+    Element element = findElement.parameter('p');
     assertThat(element)
       ..hasRelationCount(1)
       ..isReferencedAt('1); // 2', true, length: 0);
@@ -1080,8 +1049,8 @@
   0.foo = 0;
 }
 ''');
-    PropertyAccessorElement getter = findElement('foo', ElementKind.GETTER);
-    PropertyAccessorElement setter = findElement('foo=');
+    PropertyAccessorElement getter = findElement.getter('foo');
+    PropertyAccessorElement setter = findElement.setter('foo');
     assertThat(getter)..isReferencedAt('foo;', true);
     assertThat(setter)..isReferencedAt('foo = 0;', true);
   }
@@ -1098,8 +1067,8 @@
   0.foo = 0;
 }
 ''');
-    PropertyAccessorElement getter = findElement('foo', ElementKind.GETTER);
-    PropertyAccessorElement setter = findElement('foo=');
+    PropertyAccessorElement getter = findElement.getter('foo');
+    PropertyAccessorElement setter = findElement.setter('foo');
     assertThat(getter)..isReferencedAt('foo;', true);
     assertThat(setter)..isReferencedAt('foo = 0;', true);
   }
@@ -1123,7 +1092,6 @@
   (1.2).foo = 0; // double setter ref
 }
 ''');
-    var findNode = FindNode(testCode, testUnit);
 
     var intGetter = findNode.methodDeclaration('0; // int getter');
     var intSetter = findNode.methodDeclaration('{} // int setter');
@@ -1153,7 +1121,7 @@
   }
 
   test_isReferencedBy_TopLevelVariableElement() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 library lib;
 var V;
 ''');
@@ -1166,7 +1134,7 @@
   V = 5; // nq
   print(V); // nq
 }''');
-    TopLevelVariableElement variable = importedUnit().topLevelVariables[0];
+    TopLevelVariableElement variable = importFindLib().topVar('V');
     assertThat(variable)..isReferencedAt('V; // imp', true);
     assertThat(variable.getter)
       ..isReferencedAt('V); // q', true)
@@ -1177,25 +1145,25 @@
   }
 
   test_isReferencedBy_TopLevelVariableElement_synthetic_hasGetterSetter() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 int get V => 0;
 void set V(_) {}
 ''');
     await _indexTestUnit('''
 import 'lib.dart' show V;
 ''');
-    TopLevelVariableElement element = importedUnit().topLevelVariables[0];
+    TopLevelVariableElement element = importFindLib().topVar('V');
     assertThat(element).isReferencedAt('V;', true);
   }
 
   test_isReferencedBy_TopLevelVariableElement_synthetic_hasSetter() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 void set V(_) {}
 ''');
     await _indexTestUnit('''
 import 'lib.dart' show V;
 ''');
-    TopLevelVariableElement element = importedUnit().topLevelVariables[0];
+    TopLevelVariableElement element = importFindLib().topVar('V');
     assertThat(element).isReferencedAt('V;', true);
   }
 
@@ -1204,7 +1172,7 @@
 class A {}
 A myVariable = null;
 ''');
-    Element element = findElement('A');
+    Element element = findElement.class_('A');
     assertThat(element).isReferencedAt('A myVariable', false);
   }
 
@@ -1216,7 +1184,7 @@
   A.bar() : field = 5;
 }
 ''');
-    FieldElement element = findElement('field', ElementKind.FIELD);
+    FieldElement element = findElement.field('field');
     assertThat(element)
       ..isWrittenAt('field})', true)
       ..isWrittenAt('field = 5', true);
@@ -1224,7 +1192,7 @@
 
   test_subtypes_classDeclaration() async {
     String libP = 'package:test/lib.dart;package:test/lib.dart';
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 class A {}
 class B {}
 class C {}
@@ -1274,7 +1242,7 @@
 
   test_subtypes_classTypeAlias() async {
     String libP = 'package:test/lib.dart;package:test/lib.dart';
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 class A {}
 class B {}
 class C {}
@@ -1312,7 +1280,7 @@
 
   test_subtypes_mixinDeclaration() async {
     String libP = 'package:test/lib.dart;package:test/lib.dart';
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 class A {}
 class B {}
 class C {}
@@ -1358,14 +1326,14 @@
   var x;
 }
 main(C c) {
-  c.x;
+  c.x; // 1
   c.x = 1;
   c.x += 2;
   c.x();
 }
 ''');
     assertThatName('x')
-      ..isNotUsedQ('x;', IndexRelationKind.IS_READ_BY)
+      ..isNotUsedQ('x; // 1', IndexRelationKind.IS_READ_BY)
       ..isNotUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
       ..isNotUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
       ..isNotUsedQ('x();', IndexRelationKind.IS_INVOKED_BY);
@@ -1392,7 +1360,7 @@
 class C {
   var x;
   m() {
-    x;
+    x; // 1
     x = 1;
     x += 2;
     x();
@@ -1400,7 +1368,7 @@
 }
 ''');
     assertThatName('x')
-      ..isNotUsedQ('x;', IndexRelationKind.IS_READ_BY)
+      ..isNotUsedQ('x; // 1', IndexRelationKind.IS_READ_BY)
       ..isNotUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
       ..isNotUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
       ..isNotUsedQ('x();', IndexRelationKind.IS_INVOKED_BY);
@@ -1421,6 +1389,166 @@
       ..isUsed('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
       ..isUsed('x();', IndexRelationKind.IS_INVOKED_BY);
   }
+}
+
+@reflectiveTest
+class IndexWithNonFunctionTypeAliasesTest extends PubPackageResolutionTest
+    with WithNonFunctionTypeAliasesMixin, _IndexMixin {
+  test_isExtendedBy_ClassDeclaration_TypeAliasElement() async {
+    await _indexTestUnit('''
+class A<T> {}
+typedef B = A<int>;
+class C extends B {}
+''');
+    var B = findElement.typeAlias('B');
+    assertThat(B)
+      ..isExtendedAt('B {}', false)
+      ..isReferencedAt('B {}', false);
+  }
+
+  test_isImplementedBy_ClassDeclaration_TypeAliasElement() async {
+    await _indexTestUnit('''
+class A<T> {}
+typedef B = A<int>;
+class C implements B {}
+''');
+    var B = findElement.typeAlias('B');
+    assertThat(B)
+      ..isImplementedAt('B {}', false)
+      ..isReferencedAt('B {}', false);
+  }
+
+  test_isMixedBy_ClassDeclaration_TypeAliasElement() async {
+    await _indexTestUnit('''
+class A<T> {}
+typedef B = A<int>;
+class C extends Object with B {}
+''');
+    var B = findElement.typeAlias('B');
+    assertThat(B)
+      ..isMixedInAt('B {}', false)
+      ..isReferencedAt('B {}', false);
+  }
+
+  test_isReferencedBy_ClassElement_inTypeAlias() async {
+    await _indexTestUnit('''
+class A<T> {}
+
+typedef B = A<int>;
+''');
+    assertThat(findElement.class_('A')).isReferencedAt('A<int', false);
+    assertThat(intElement).isReferencedAt('int>;', false);
+  }
+
+  test_isReferencedBy_TypeAliasElement() async {
+    await _indexTestUnit('''
+class A<T> {
+  static int field = 0;
+  static void method() {}
+}
+
+typedef B = A<int>;
+
+void f(B p) {
+  B v;
+  B(); // 2
+  B.field = 1;
+  B.field; // 3
+  B.method(); // 4
+}
+''');
+    var element = findElement.typeAlias('B');
+    assertThat(element)
+      ..isReferencedAt('B p) {', false)
+      ..isReferencedAt('B v;', false)
+      ..isReferencedAt('B(); // 2', false)
+      ..isReferencedAt('B.field = 1;', false)
+      ..isReferencedAt('B.field; // 3', false)
+      ..isReferencedAt('B.method(); // 4', false);
+  }
+}
+
+class _ElementIndexAssert {
+  final _IndexMixin test;
+  final Element element;
+  final List<_Relation> relations;
+
+  _ElementIndexAssert(this.test, this.element, this.relations);
+
+  void hasRelationCount(int expectedCount) {
+    expect(relations, hasLength(expectedCount));
+  }
+
+  void isAncestorOf(String search, {int length}) {
+    test._assertHasRelation(
+        element,
+        relations,
+        IndexRelationKind.IS_ANCESTOR_OF,
+        test._expectedLocation(search, false, length: length));
+  }
+
+  void isExtendedAt(String search, bool isQualified, {int length}) {
+    test._assertHasRelation(
+        element,
+        relations,
+        IndexRelationKind.IS_EXTENDED_BY,
+        test._expectedLocation(search, isQualified, length: length));
+  }
+
+  void isImplementedAt(String search, bool isQualified, {int length}) {
+    test._assertHasRelation(
+        element,
+        relations,
+        IndexRelationKind.IS_IMPLEMENTED_BY,
+        test._expectedLocation(search, isQualified, length: length));
+  }
+
+  void isInvokedAt(String search, bool isQualified, {int length}) {
+    test._assertHasRelation(element, relations, IndexRelationKind.IS_INVOKED_BY,
+        test._expectedLocation(search, isQualified, length: length));
+  }
+
+  void isMixedInAt(String search, bool isQualified, {int length}) {
+    test._assertHasRelation(
+        element,
+        relations,
+        IndexRelationKind.IS_MIXED_IN_BY,
+        test._expectedLocation(search, isQualified, length: length));
+  }
+
+  void isReferencedAt(String search, bool isQualified, {int length}) {
+    test._assertHasRelation(
+        element,
+        relations,
+        IndexRelationKind.IS_REFERENCED_BY,
+        test._expectedLocation(search, isQualified, length: length));
+  }
+
+  void isWrittenAt(String search, bool isQualified, {int length}) {
+    test._assertHasRelation(element, relations, IndexRelationKind.IS_WRITTEN_BY,
+        test._expectedLocation(search, isQualified, length: length));
+  }
+}
+
+mixin _IndexMixin on PubPackageResolutionTest {
+  AnalysisDriverUnitIndex index;
+
+  _ElementIndexAssert assertThat(Element element) {
+    List<_Relation> relations = _getElementRelations(element);
+    return _ElementIndexAssert(this, element, relations);
+  }
+
+  _NameIndexAssert assertThatName(String name) {
+    return _NameIndexAssert(this, name);
+  }
+
+  /// Return [ImportFindElement] for 'package:test/lib.dart' import.
+  ImportFindElement importFindLib() {
+    return findElement.importFind(
+      'package:test/lib.dart',
+      mustBeUnique: false,
+    );
+  }
 
   /// Asserts that [index] has an item with the expected properties.
   void _assertHasRelation(
@@ -1474,9 +1602,9 @@
 
   ExpectedLocation _expectedLocation(String search, bool isQualified,
       {int length}) {
-    int offset = findOffset(search);
-    length ??= getLeadingIdentifierLength(search);
-    return ExpectedLocation(testUnitElement, offset, length, isQualified);
+    int offset = findNode.offset(search);
+    length ??= findNode.simple(search).length;
+    return ExpectedLocation(offset, length, isQualified);
   }
 
   void _failWithIndexDump(String msg) {
@@ -1564,81 +1692,14 @@
   }
 
   Future<void> _indexTestUnit(String code) async {
-    addTestFile(code);
+    await resolveTestCode(code);
 
-    ResolvedUnitResult result = await driver.getResult(testFile);
-    testUnit = result.unit;
-    testUnitElement = testUnit.declaredElement;
-    testLibraryElement = testUnitElement.library;
-
-    AnalysisDriverUnitIndexBuilder indexBuilder = indexUnit(testUnit);
-    List<int> indexBytes = indexBuilder.toBuffer();
+    var indexBuilder = indexUnit(result.unit);
+    var indexBytes = indexBuilder.toBuffer();
     index = AnalysisDriverUnitIndex.fromBuffer(indexBytes);
   }
 }
 
-class _ElementIndexAssert {
-  final IndexTest test;
-  final Element element;
-  final List<_Relation> relations;
-
-  _ElementIndexAssert(this.test, this.element, this.relations);
-
-  void hasRelationCount(int expectedCount) {
-    expect(relations, hasLength(expectedCount));
-  }
-
-  void isAncestorOf(String search, {int length}) {
-    test._assertHasRelation(
-        element,
-        relations,
-        IndexRelationKind.IS_ANCESTOR_OF,
-        test._expectedLocation(search, false, length: length));
-  }
-
-  void isExtendedAt(String search, bool isQualified, {int length}) {
-    test._assertHasRelation(
-        element,
-        relations,
-        IndexRelationKind.IS_EXTENDED_BY,
-        test._expectedLocation(search, isQualified, length: length));
-  }
-
-  void isImplementedAt(String search, bool isQualified, {int length}) {
-    test._assertHasRelation(
-        element,
-        relations,
-        IndexRelationKind.IS_IMPLEMENTED_BY,
-        test._expectedLocation(search, isQualified, length: length));
-  }
-
-  void isInvokedAt(String search, bool isQualified, {int length}) {
-    test._assertHasRelation(element, relations, IndexRelationKind.IS_INVOKED_BY,
-        test._expectedLocation(search, isQualified, length: length));
-  }
-
-  void isMixedInAt(String search, bool isQualified, {int length}) {
-    test._assertHasRelation(
-        element,
-        relations,
-        IndexRelationKind.IS_MIXED_IN_BY,
-        test._expectedLocation(search, isQualified, length: length));
-  }
-
-  void isReferencedAt(String search, bool isQualified, {int length}) {
-    test._assertHasRelation(
-        element,
-        relations,
-        IndexRelationKind.IS_REFERENCED_BY,
-        test._expectedLocation(search, isQualified, length: length));
-  }
-
-  void isWrittenAt(String search, bool isQualified, {int length}) {
-    test._assertHasRelation(element, relations, IndexRelationKind.IS_WRITTEN_BY,
-        test._expectedLocation(search, isQualified, length: length));
-  }
-}
-
 class _NameIndexAssert {
   final IndexTest test;
   final String name;
diff --git a/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart b/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart
index d223d82..31f4507 100644
--- a/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart
@@ -7,7 +7,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/parser_test.dart';
+import '../../../generated/parser_test_base.dart';
 
 main() {
   defineReflectiveSuite(() {
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 3858d02..646bada 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -2,24 +2,20 @@
 // for 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/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart' hide Declaration;
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/search.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/testing/element_search.dart';
-import 'package:analyzer/src/test_utilities/find_element.dart';
-import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'base.dart';
+import '../resolution/context_collection_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SearchTest);
     defineReflectiveTests(SearchWithNullSafetyTest);
+    defineReflectiveTests(SearchWithNonFunctionTypeAliasesTest);
   });
 }
 
@@ -66,18 +62,15 @@
 }
 
 @reflectiveTest
-class SearchTest extends BaseAnalysisDriverTest {
-  static const testUri = 'package:test/test.dart';
+class SearchTest extends PubPackageResolutionTest {
+  AnalysisDriver get driver => driverFor(testFilePath);
 
-  CompilationUnit testUnit;
-  CompilationUnitElement testUnitElement;
-  LibraryElement testLibraryElement;
+  CompilationUnitElement get resultUnitElement => result.unit.declaredElement;
 
-  FindNode findNode;
-  FindElement findElement;
+  String get testUriStr => 'package:test/test.dart';
 
   test_classMembers_class() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   test() {}
 }
@@ -91,19 +84,20 @@
 ''');
     var a = findElement.class_('A');
     var b = findElement.class_('B');
-    expect(await driver.search.classMembers('test'),
+
+    expect(await _findClassMembers('test'),
         unorderedEquals([a.methods[0], b.fields[0]]));
   }
 
   test_classMembers_importNotDart() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 import 'not-dart.txt';
 ''');
-    expect(await driver.search.classMembers('test'), isEmpty);
+    expect(await _findClassMembers('test'), isEmpty);
   }
 
   test_classMembers_mixin() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 mixin A {
   test() {}
 }
@@ -117,12 +111,12 @@
 ''');
     var a = findElement.mixin('A');
     var b = findElement.mixin('B');
-    expect(await driver.search.classMembers('test'),
+    expect(await _findClassMembers('test'),
         unorderedEquals([a.methods[0], b.fields[0]]));
   }
 
   test_searchMemberReferences_qualified_resolved() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class C {
   var test;
 }
@@ -137,7 +131,7 @@
   }
 
   test_searchMemberReferences_qualified_unresolved() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 main(p) {
   print(p.test);
   p.test = 1;
@@ -155,7 +149,7 @@
   }
 
   test_searchMemberReferences_unqualified_resolved() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class C {
   var test;
   main() {
@@ -170,7 +164,7 @@
   }
 
   test_searchMemberReferences_unqualified_unresolved() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class C {
   main() {
     print(test);
@@ -190,7 +184,7 @@
   }
 
   test_searchReferences_ClassElement_definedInSdk_declarationSite() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 import 'dart:math';
 Random v1;
 Random v2;
@@ -198,12 +192,7 @@
 
     // Find the Random class element in the SDK source.
     // IDEA performs search always at declaration, never at reference.
-    ClassElement randomElement;
-    {
-      String randomPath = sdk.mapDartUri('dart:math').fullName;
-      ResolvedUnitResult result = await driver.getResult(randomPath);
-      randomElement = result.unit.declaredElement.getType('Random');
-    }
+    var randomElement = findElement.importFind('dart:math').class_('Random');
 
     var v1 = findElement.topVar('v1');
     var v2 = findElement.topVar('v2');
@@ -215,7 +204,7 @@
   }
 
   test_searchReferences_ClassElement_definedInSdk_useSite() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 import 'dart:math';
 Random v1;
 Random v2;
@@ -232,7 +221,7 @@
   }
 
   test_searchReferences_ClassElement_definedInside() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {};
 main(A p) {
   A v;
@@ -261,10 +250,10 @@
   }
 
   test_searchReferences_ClassElement_definedOutside() async {
-    newFile('$testProject2/lib.dart', content: r'''
+    newFile('$testPackageLibPath/lib.dart', content: r'''
 class A {};
 ''');
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 import 'lib.dart';
 main(A p) {
   A v;
@@ -281,7 +270,7 @@
   }
 
   test_searchReferences_ClassElement_enum() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 enum MyEnum {a}
 
 main(MyEnum p) {
@@ -304,7 +293,7 @@
   }
 
   test_searchReferences_ClassElement_mixin() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 mixin A {}
 class B extends Object with A {} // with
 ''');
@@ -317,27 +306,26 @@
   }
 
   test_searchReferences_CompilationUnitElement() async {
-    newFile('$testProject2/foo.dart');
-    await _resolveTestUnit('''
+    newFile('$testPackageLibPath/foo.dart');
+    await resolveTestCode('''
 import 'foo.dart'; // import
 export 'foo.dart'; // export
 ''');
-    CompilationUnitElement element =
-        testLibraryElement.imports[0].importedLibrary.definingCompilationUnit;
+    var element = findElement.importFind('package:test/foo.dart').unitElement;
     int uriLength = "'foo.dart'".length;
     var expected = [
-      _expectIdQ(
-          testUnitElement, SearchResultKind.REFERENCE, "'foo.dart'; // import",
+      _expectIdQ(resultUnitElement, SearchResultKind.REFERENCE,
+          "'foo.dart'; // import",
           length: uriLength),
-      _expectIdQ(
-          testUnitElement, SearchResultKind.REFERENCE, "'foo.dart'; // export",
+      _expectIdQ(resultUnitElement, SearchResultKind.REFERENCE,
+          "'foo.dart'; // export",
           length: uriLength),
     ];
     await _verifyReferences(element, expected);
   }
 
   test_searchReferences_ConstructorElement_default() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   A() {}
 }
@@ -354,7 +342,7 @@
   }
 
   test_searchReferences_ConstructorElement_default_otherFile() async {
-    String other = convertPath('$testProject2/other.dart');
+    String other = convertPath('$testPackageLibPath/other.dart');
     String otherCode = '''
 import 'test.dart';
 main() {
@@ -364,7 +352,7 @@
     newFile(other, content: otherCode);
     driver.addFile(other);
 
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   A() {}
 }
@@ -382,7 +370,7 @@
   }
 
   test_searchReferences_ConstructorElement_named() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   A.named() {}
 }
@@ -400,7 +388,7 @@
   }
 
   test_searchReferences_ConstructorElement_synthetic() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
 }
 main() {
@@ -416,7 +404,7 @@
   }
 
   test_searchReferences_ExtensionElement() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 extension E on int {
   void foo() {}
   static void bar() {}
@@ -437,7 +425,7 @@
   }
 
   test_searchReferences_FieldElement() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   var field;
   A({this.field});
@@ -471,7 +459,7 @@
   }
 
   test_searchReferences_FieldElement_ofEnum() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 enum MyEnum {
   A, B, C
 }
@@ -497,7 +485,7 @@
   }
 
   test_searchReferences_FieldElement_synthetic() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   get field => null;
   set field(x) {}
@@ -527,7 +515,7 @@
   }
 
   test_searchReferences_FunctionElement() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 test() {}
 main() {
   test();
@@ -544,14 +532,14 @@
   }
 
   test_searchReferences_FunctionElement_local() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 main() {
   test() {}
   test();
   print(test);
 }
 ''');
-    FunctionElement element = findElementsByName(testUnit, 'test').single;
+    var element = findElement.localFunction('test');
     var main = findElement.function('main');
     var expected = [
       _expectId(main, SearchResultKind.INVOCATION, 'test();'),
@@ -561,7 +549,7 @@
   }
 
   test_searchReferences_ImportElement_noPrefix() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 import 'dart:math' show max, pi, Random hide min;
 export 'dart:math' show max, pi, Random hide min;
 main() {
@@ -571,7 +559,7 @@
 }
 Random bar() => null;
 ''');
-    ImportElement element = testLibraryElement.imports[0];
+    var element = findElement.import('dart:math', mustBeUnique: false);
     var main = findElement.function('main');
     var bar = findElement.function('bar');
     var kind = SearchResultKind.REFERENCE;
@@ -585,8 +573,17 @@
   }
 
   test_searchReferences_ImportElement_noPrefix_inPackage() async {
-    testFile = convertPath('/aaa/lib/a.dart');
-    await _resolveTestUnit('''
+    var aaaPackageRootPath = '$packagesRootPath/aaa';
+    var aaaFilePath = convertPath('$aaaPackageRootPath/lib/a.dart');
+
+    writeTestPackageConfig(
+      PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaPackageRootPath),
+    );
+
+    pathForContextSelection = testFilePath;
+
+    await resolveFileCode(aaaFilePath, '''
 import 'dart:math' show max, pi, Random hide min;
 export 'dart:math' show max, pi, Random hide min;
 main() {
@@ -595,8 +592,9 @@
   max(1, 2);
 }
 Random bar() => null;
-''', addToDriver: false);
-    ImportElement element = testLibraryElement.imports[0];
+''');
+
+    ImportElement element = findElement.import('dart:math');
     var main = findElement.function('main');
     var bar = findElement.function('bar');
     var kind = SearchResultKind.REFERENCE;
@@ -610,7 +608,7 @@
   }
 
   test_searchReferences_ImportElement_withPrefix() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 import 'dart:math' as math show max, pi, Random hide min;
 export 'dart:math' show max, pi, Random hide min;
 main() {
@@ -620,7 +618,7 @@
 }
 math.Random bar() => null;
 ''');
-    ImportElement element = testLibraryElement.imports[0];
+    var element = findElement.import('dart:math', mustBeUnique: false);
     var main = findElement.function('main');
     var bar = findElement.function('bar');
     var kind = SearchResultKind.REFERENCE;
@@ -635,7 +633,7 @@
   }
 
   test_searchReferences_ImportElement_withPrefix_forMultipleImports() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 import 'dart:async' as p;
 import 'dart:math' as p;
 main() {
@@ -647,14 +645,14 @@
     var kind = SearchResultKind.REFERENCE;
     var length = 'p.'.length;
     {
-      ImportElement element = testLibraryElement.imports[0];
+      ImportElement element = findElement.import('dart:async');
       var expected = [
         _expectId(main, kind, 'p.Future;', length: length),
       ];
       await _verifyReferences(element, expected);
     }
     {
-      ImportElement element = testLibraryElement.imports[1];
+      ImportElement element = findElement.import('dart:math');
       var expected = [
         _expectId(main, kind, 'p.Random', length: length),
       ];
@@ -663,7 +661,7 @@
   }
 
   test_searchReferences_LabelElement() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 main() {
 label:
   while (true) {
@@ -674,7 +672,7 @@
   }
 }
 ''');
-    Element element = findElementsByName(testUnit, 'label').single;
+    var element = findElement.label('label');
     var main = findElement.function('main');
     var expected = [
       _expectId(main, SearchResultKind.REFERENCE, 'label; // 1'),
@@ -686,14 +684,14 @@
   test_searchReferences_LibraryElement() async {
     var codeA = 'part of lib; // A';
     var codeB = 'part of lib; // B';
-    newFile('$testProject2/unitA.dart', content: codeA);
-    newFile('$testProject2/unitB.dart', content: codeB);
-    await _resolveTestUnit('''
+    newFile('$testPackageLibPath/unitA.dart', content: codeA);
+    newFile('$testPackageLibPath/unitB.dart', content: codeB);
+    await resolveTestCode('''
 library lib;
 part 'unitA.dart';
 part 'unitB.dart';
 ''');
-    LibraryElement element = testLibraryElement;
+    LibraryElement element = result.libraryElement;
     CompilationUnitElement unitElementA = element.parts[0];
     CompilationUnitElement unitElementB = element.parts[1];
     var expected = [
@@ -706,20 +704,30 @@
   }
 
   test_searchReferences_LibraryElement_inPackage() async {
-    testFile = convertPath('/aaa/lib/a.dart');
-    var partPathA = convertPath('/aaa/lib/unitA.dart');
-    var partPathB = convertPath('/aaa/lib/unitB.dart');
+    var aaaPackageRootPath = '$packagesRootPath/aaa';
+
+    writeTestPackageConfig(
+      PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaPackageRootPath),
+    );
+
+    var libPath = convertPath('$aaaPackageRootPath/lib/a.dart');
+    var partPathA = convertPath('$aaaPackageRootPath/lib/unitA.dart');
+    var partPathB = convertPath('$aaaPackageRootPath/lib/unitB.dart');
 
     var codeA = 'part of lib; // A';
     var codeB = 'part of lib; // B';
     newFile(partPathA, content: codeA);
     newFile(partPathB, content: codeB);
-    await _resolveTestUnit('''
+
+    pathForContextSelection = testFilePath;
+
+    await resolveFileCode(libPath, '''
 library lib;
 part 'unitA.dart';
 part 'unitB.dart';
-''', addToDriver: false);
-    LibraryElement element = testLibraryElement;
+''');
+    LibraryElement element = result.libraryElement;
     CompilationUnitElement unitElementA = element.parts[0];
     CompilationUnitElement unitElementB = element.parts[1];
     var expected = [
@@ -732,7 +740,7 @@
   }
 
   test_searchReferences_LocalVariableElement() async {
-    await _resolveTestUnit(r'''
+    await resolveTestCode(r'''
 main() {
   var v;
   v = 1;
@@ -741,7 +749,7 @@
   v();
 }
 ''');
-    Element element = findElementsByName(testUnit, 'v').single;
+    Element element = findElement.localVar('v');
     var main = findElement.function('main');
     var expected = [
       _expectId(main, SearchResultKind.WRITE, 'v = 1;'),
@@ -753,7 +761,7 @@
   }
 
   test_searchReferences_LocalVariableElement_inForEachLoop() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 main() {
   for (var v in []) {
     v = 1;
@@ -763,7 +771,7 @@
   }
 }
 ''');
-    Element element = findElementsByName(testUnit, 'v').single;
+    Element element = findElement.localVar('v');
     var main = findElement.function('main');
     var expected = [
       _expectId(main, SearchResultKind.WRITE, 'v = 1;'),
@@ -775,9 +783,17 @@
   }
 
   test_searchReferences_LocalVariableElement_inPackage() async {
-    testFile = convertPath('/aaa/lib/a.dart');
+    var aaaPackageRootPath = '$packagesRootPath/aaa';
+    var testPath = convertPath('$aaaPackageRootPath/lib/a.dart');
 
-    await _resolveTestUnit('''
+    writeTestPackageConfig(
+      PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaPackageRootPath),
+    );
+
+    pathForContextSelection = testFilePath;
+
+    await resolveFileCode(testPath, '''
 main() {
   var v;
   v = 1;
@@ -785,8 +801,8 @@
   print(v);
   v();
 }
-''', addToDriver: false);
-    Element element = findElementsByName(testUnit, 'v').single;
+''');
+    var element = findElement.localVar('v');
     var main = findElement.function('main');
 
     var expected = [
@@ -799,7 +815,7 @@
   }
 
   test_searchReferences_MethodElement_class() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   m() {}
   main() {
@@ -822,7 +838,7 @@
   }
 
   test_searchReferences_MethodElement_extension_named() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 extension E on int {
   void foo() {}
 
@@ -846,7 +862,7 @@
   }
 
   test_searchReferences_MethodElement_extension_unnamed() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 extension on int {
   void foo() {}
 
@@ -870,7 +886,7 @@
   }
 
   test_searchReferences_MethodElement_ofExtension_instance() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 extension E on int {
   void foo() {}
 
@@ -906,7 +922,7 @@
   }
 
   test_searchReferences_MethodElement_ofExtension_static() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 extension E on int {
   static void foo() {}
 
@@ -934,7 +950,7 @@
   }
 
   test_searchReferences_MethodMember_class() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A<T> {
   T m() => null;
 }
@@ -951,7 +967,7 @@
   }
 
   test_searchReferences_ParameterElement_named() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 foo({p}) {
   p = 1;
   p += 2;
@@ -976,7 +992,7 @@
   }
 
   test_searchReferences_ParameterElement_ofConstructor() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class C {
   var f;
   C(p) : f = p + 1 {
@@ -1003,7 +1019,7 @@
   }
 
   test_searchReferences_ParameterElement_ofLocalFunction() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 main() {
   foo(p) {
     p = 1;
@@ -1026,7 +1042,7 @@
   }
 
   test_searchReferences_ParameterElement_ofMethod() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class C {
   foo(p) {
     p = 1;
@@ -1051,7 +1067,7 @@
   }
 
   test_searchReferences_ParameterElement_ofTopLevelFunction() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 foo(p) {
   p = 1;
   p += 2;
@@ -1074,7 +1090,7 @@
   }
 
   test_searchReferences_ParameterElement_optionalPositional() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 foo([p]) {
   p = 1;
   p += 2;
@@ -1103,8 +1119,8 @@
 part of my_lib;
 ppp.Future c;
 ''';
-    newFile('$testProject2/my_part.dart', content: partCode);
-    await _resolveTestUnit('''
+    newFile('$testPackageLibPath/my_part.dart', content: partCode);
+    await resolveTestCode('''
 library my_lib;
 import 'dart:async' as ppp;
 part 'my_part.dart';
@@ -1115,7 +1131,7 @@
 ''');
     var element = findElement.prefix('ppp');
     var main = findElement.function('main');
-    Element c = findChildElement(testLibraryElement, 'c');
+    var c = findElement.partFind('my_part.dart').topVar('c');
     var expected = [
       _expectId(main, SearchResultKind.REFERENCE, 'ppp.Future'),
       _expectId(main, SearchResultKind.REFERENCE, 'ppp.Stream'),
@@ -1126,15 +1142,24 @@
   }
 
   test_searchReferences_PrefixElement_inPackage() async {
-    testFile = convertPath('/aaa/lib/a.dart');
-    var partPath = convertPath('/aaa/lib/my_part.dart');
+    var aaaPackageRootPath = '$packagesRootPath/aaa';
+
+    writeTestPackageConfig(
+      PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaPackageRootPath),
+    );
+
+    pathForContextSelection = testFilePath;
+
+    var libPath = convertPath('$aaaPackageRootPath/lib/a.dart');
+    var partPath = convertPath('$aaaPackageRootPath/lib/my_part.dart');
 
     String partCode = r'''
 part of my_lib;
 ppp.Future c;
 ''';
     newFile(partPath, content: partCode);
-    await _resolveTestUnit('''
+    await resolveFileCode(libPath, '''
 library my_lib;
 import 'dart:async' as ppp;
 part 'my_part.dart';
@@ -1142,10 +1167,10 @@
   ppp.Future a;
   ppp.Stream b;
 }
-''', addToDriver: false);
+''');
     var element = findElement.prefix('ppp');
     var main = findElement.function('main');
-    Element c = findChildElement(testLibraryElement, 'c');
+    var c = findElement.partFind('my_part.dart').topVar('c');
     var expected = [
       _expectId(main, SearchResultKind.REFERENCE, 'ppp.Future'),
       _expectId(main, SearchResultKind.REFERENCE, 'ppp.Stream'),
@@ -1156,20 +1181,16 @@
   }
 
   test_searchReferences_private_declaredInDefiningUnit() async {
-    String p1 = convertPath('$testProject2/part1.dart');
-    String p2 = convertPath('$testProject2/part2.dart');
-    String p3 = convertPath('$testProject2/part3.dart');
+    String p1 = convertPath('$testPackageLibPath/part1.dart');
+    String p2 = convertPath('$testPackageLibPath/part2.dart');
+    String p3 = convertPath('$testPackageLibPath/part3.dart');
     String code1 = 'part of lib; _C v1;';
     String code2 = 'part of lib; _C v2;';
     newFile(p1, content: code1);
     newFile(p2, content: code2);
     newFile(p3, content: 'part of lib; int v3;');
 
-    driver.addFile(p1);
-    driver.addFile(p2);
-    driver.addFile(p3);
-
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 library lib;
 part 'part1.dart';
 part 'part2.dart';
@@ -1178,9 +1199,9 @@
 _C v;
 ''');
     var element = findElement.class_('_C');
-    Element v = testUnitElement.topLevelVariables[0];
-    Element v1 = testLibraryElement.parts[0].topLevelVariables[0];
-    Element v2 = testLibraryElement.parts[1].topLevelVariables[0];
+    Element v = findElement.topVar('v');
+    Element v1 = findElement.partFind('part1.dart').topVar('v1');
+    Element v2 = findElement.partFind('part2.dart').topVar('v2');
     var expected = [
       _expectId(v, SearchResultKind.REFERENCE, '_C v;', length: 2),
       ExpectedResult(
@@ -1192,9 +1213,9 @@
   }
 
   test_searchReferences_private_declaredInPart() async {
-    String p = convertPath('$testProject2/lib.dart');
-    String p1 = convertPath('$testProject2/part1.dart');
-    String p2 = convertPath('$testProject2/part2.dart');
+    String p = convertPath('$testPackageLibPath/lib.dart');
+    String p1 = convertPath('$testPackageLibPath/part1.dart');
+    String p2 = convertPath('$testPackageLibPath/part2.dart');
 
     var code = '''
 library lib;
@@ -1213,19 +1234,12 @@
     newFile(p1, content: code1);
     newFile(p2, content: code2);
 
-    driver.addFile(p);
-    driver.addFile(p1);
-    driver.addFile(p2);
+    await resolveTestCode(code);
 
-    ResolvedUnitResult result = await driver.getResult(p);
-    testUnit = result.unit;
-    testUnitElement = testUnit.declaredElement;
-    testLibraryElement = testUnitElement.library;
-
-    ClassElement element = testLibraryElement.parts[0].types[0];
-    Element v = testUnitElement.topLevelVariables[0];
-    Element v1 = testLibraryElement.parts[0].topLevelVariables[0];
-    Element v2 = testLibraryElement.parts[1].topLevelVariables[0];
+    ClassElement element = findElement.partFind('part1.dart').class_('_C');
+    Element v = findElement.topVar('v');
+    Element v1 = findElement.partFind('part1.dart').topVar('v1');
+    Element v2 = findElement.partFind('part2.dart').topVar('v2');
     var expected = [
       ExpectedResult(v, SearchResultKind.REFERENCE, code.indexOf('_C v;'), 2),
       ExpectedResult(
@@ -1237,28 +1251,37 @@
   }
 
   test_searchReferences_private_inPackage() async {
-    testFile = convertPath('/aaa/lib/a.dart');
-    var p1 = convertPath('/aaa/lib/part1.dart');
-    var p2 = convertPath('/aaa/lib/part2.dart');
+    var aaaPackageRootPath = '$packagesRootPath/aaa';
+    var testFile = convertPath('$aaaPackageRootPath/lib/a.dart');
+    var p1 = convertPath('$aaaPackageRootPath/lib/part1.dart');
+    var p2 = convertPath('$aaaPackageRootPath/lib/part2.dart');
 
+    writeTestPackageConfig(
+      PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaPackageRootPath),
+    );
+
+    pathForContextSelection = testFilePath;
+
+    String testCode = '''
+library lib;
+part 'part1.dart';
+part 'part2.dart';
+class _C {}
+_C v;
+''';
     String code1 = 'part of lib; _C v1;';
     String code2 = 'part of lib; _C v2;';
 
     newFile(p1, content: code1);
     newFile(p2, content: code2);
 
-    await _resolveTestUnit('''
-library lib;
-part 'part1.dart';
-part 'part2.dart';
-class _C {}
-_C v;
-''', addToDriver: false);
+    await resolveFileCode(testFile, testCode);
 
-    Element element = testUnitElement.types.single;
-    Element v = testUnitElement.topLevelVariables[0];
-    Element v1 = testLibraryElement.parts[0].topLevelVariables[0];
-    Element v2 = testLibraryElement.parts[1].topLevelVariables[0];
+    ClassElement element = findElement.class_('_C');
+    Element v = findElement.topVar('v');
+    Element v1 = findElement.partFind('part1.dart').topVar('v1');
+    Element v2 = findElement.partFind('part2.dart').topVar('v2');
     var expected = [
       ExpectedResult(
           v, SearchResultKind.REFERENCE, testCode.indexOf('_C v;'), 2),
@@ -1271,7 +1294,7 @@
   }
 
   test_searchReferences_PropertyAccessor_getter_ofExtension_instance() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 extension E on int {
   int get foo => 0;
 
@@ -1299,7 +1322,7 @@
   }
 
   test_searchReferences_PropertyAccessor_setter_ofExtension_instance() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 extension E on int {
   set foo(int _) {}
 
@@ -1327,7 +1350,7 @@
   }
 
   test_searchReferences_PropertyAccessorElement_getter() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   get ggg => null;
   main() {
@@ -1350,7 +1373,7 @@
   }
 
   test_searchReferences_PropertyAccessorElement_setter() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   set s(x) {}
   main() {
@@ -1369,11 +1392,11 @@
   }
 
   test_searchReferences_TopLevelVariableElement() async {
-    newFile('$testProject2/lib.dart', content: '''
+    newFile('$testPackageLibPath/lib.dart', content: '''
 library lib;
 var V;
 ''');
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 import 'lib.dart' show V; // imp
 import 'lib.dart' as pref;
 main() {
@@ -1385,13 +1408,13 @@
   V(); // nq
 }
 ''');
-    ImportElement importElement = testLibraryElement.imports[0];
+    ImportElement importElement = findNode.import('show V').element;
     CompilationUnitElement impUnit =
         importElement.importedLibrary.definingCompilationUnit;
     TopLevelVariableElement variable = impUnit.topLevelVariables[0];
     var main = findElement.function('main');
     var expected = [
-      _expectIdQ(testUnitElement, SearchResultKind.REFERENCE, 'V; // imp'),
+      _expectIdQ(resultUnitElement, SearchResultKind.REFERENCE, 'V; // imp'),
       _expectIdQ(main, SearchResultKind.WRITE, 'V = 1; // q'),
       _expectIdQ(main, SearchResultKind.READ, 'V); // q'),
       _expectIdQ(main, SearchResultKind.READ, 'V(); // q'),
@@ -1403,7 +1426,7 @@
   }
 
   test_searchReferences_TypeParameterElement_ofClass() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A<T> {
   foo(T a) {}
   bar(T b) {}
@@ -1420,7 +1443,7 @@
   }
 
   test_searchReferences_TypeParameterElement_ofLocalFunction() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 main() {
   void foo<T>(T a) {
     void bar(T b) {}
@@ -1438,7 +1461,7 @@
   }
 
   test_searchReferences_TypeParameterElement_ofMethod() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   foo<T>(T p) {}
 }
@@ -1452,7 +1475,7 @@
   }
 
   test_searchReferences_TypeParameterElement_ofTopLevelFunction() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 foo<T>(T a) {
   bar(T b) {}
 }
@@ -1468,7 +1491,7 @@
   }
 
   test_searchSubtypes() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class T {}
 class A extends T {} // A
 class B = Object with T; // B
@@ -1487,7 +1510,7 @@
   }
 
   test_searchSubtypes_mixinDeclaration() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class T {}
 mixin A on T {} // A
 mixin B implements T {} // B
@@ -1503,7 +1526,7 @@
   }
 
   test_subtypes() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {}
 
 class B extends A {
@@ -1535,16 +1558,16 @@
     SubtypeResult c = subtypes.singleWhere((r) => r.name == 'C');
     SubtypeResult d = subtypes.singleWhere((r) => r.name == 'D');
 
-    expect(b.libraryUri, testUri);
-    expect(b.id, '$testUri;$testUri;B');
+    expect(b.libraryUri, testUriStr);
+    expect(b.id, '$testUriStr;$testUriStr;B');
     expect(b.members, ['methodB']);
 
-    expect(c.libraryUri, testUri);
-    expect(c.id, '$testUri;$testUri;C');
+    expect(c.libraryUri, testUriStr);
+    expect(c.id, '$testUriStr;$testUriStr;C');
     expect(c.members, ['methodC']);
 
-    expect(d.libraryUri, testUri);
-    expect(d.id, '$testUri;$testUri;D');
+    expect(d.libraryUri, testUriStr);
+    expect(d.id, '$testUriStr;$testUriStr;D');
     expect(d.members, ['methodD']);
 
     // Search by 'id'.
@@ -1558,15 +1581,23 @@
   }
 
   test_subtypes_discover() async {
-    var pathT = convertPath('/test/lib/t.dart');
-    var pathA = convertPath('/aaa/lib/a.dart');
-    var pathB = convertPath('/bbb/lib/b.dart');
+    var aaaPackageRootPath = '$packagesRootPath/aaa';
+    var bbbPackageRootPath = '$packagesRootPath/bbb';
 
-    var tUri = 'package:test/t.dart';
+    var aaaFilePath = convertPath('$aaaPackageRootPath/lib/a.dart');
+    var bbbFilePath = convertPath('$bbbPackageRootPath/lib/b.dart');
+
+    writeTestPackageConfig(
+      PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaPackageRootPath)
+        ..add(name: 'bbb', rootPath: bbbPackageRootPath),
+    );
+
+    var tUri = 'package:test/test.dart';
     var aUri = 'package:aaa/a.dart';
     var bUri = 'package:bbb/b.dart';
 
-    newFile(pathT, content: r'''
+    newFile(testFilePath, content: r'''
 import 'package:aaa/a.dart';
 
 class T1 extends A {
@@ -1578,7 +1609,7 @@
 }
 ''');
 
-    newFile(pathB, content: r'''
+    newFile(bbbFilePath, content: r'''
 import 'package:aaa/a.dart';
 
 class B extends A {
@@ -1586,15 +1617,13 @@
 }
 ''');
 
-    newFile(pathA, content: r'''
+    newFile(aaaFilePath, content: r'''
 class A {
   void method1() {}
   void method2() {}
 }
 ''');
 
-    driver.addFile(pathT);
-
     var aLibrary = await driver.getLibraryByUri(aUri);
     ClassElement aClass = aLibrary.getType('A');
 
@@ -1621,17 +1650,24 @@
   }
 
   test_subTypes_discover() async {
-    var t = convertPath('/test/lib/t.dart');
-    var a = convertPath('/aaa/lib/a.dart');
-    var b = convertPath('/bbb/lib/b.dart');
-    var c = convertPath('/ccc/lib/c.dart');
+    var aaaPackageRootPath = '$packagesRootPath/aaa';
+    var bbbPackageRootPath = '$packagesRootPath/bbb';
+    var cccPackageRootPath = '$packagesRootPath/ccc';
 
-    newFile(t, content: 'class T implements List {}');
-    newFile(a, content: 'class A implements List {}');
-    newFile(b, content: 'class B implements List {}');
-    newFile(c, content: 'class C implements List {}');
+    var aaaFilePath = convertPath('$aaaPackageRootPath/lib/a.dart');
+    var bbbFilePath = convertPath('$bbbPackageRootPath/lib/b.dart');
+    var cccFilePath = convertPath('$cccPackageRootPath/lib/c.dart');
 
-    driver.addFile(t);
+    writeTestPackageConfig(
+      PackageConfigFileBuilder()
+        ..add(name: 'aaa', rootPath: aaaPackageRootPath)
+        ..add(name: 'bbb', rootPath: bbbPackageRootPath),
+    );
+
+    newFile(testFilePath, content: 'class T implements List {}');
+    newFile(aaaFilePath, content: 'class A implements List {}');
+    newFile(bbbFilePath, content: 'class B implements List {}');
+    newFile(cccFilePath, content: 'class C implements List {}');
 
     LibraryElement coreLib = await driver.getLibraryByUri('dart:core');
     ClassElement listElement = coreLib.getType('List');
@@ -1647,15 +1683,15 @@
       expect(results, not ? isNot(matcher) : matcher);
     }
 
-    assertHasResult(t, 'T');
-    assertHasResult(a, 'A');
-    assertHasResult(b, 'B');
-    assertHasResult(c, 'C', not: true);
+    assertHasResult(convertPath(testFilePath), 'T');
+    assertHasResult(aaaFilePath, 'A');
+    assertHasResult(bbbFilePath, 'B');
+    assertHasResult(cccFilePath, 'C', not: true);
   }
 
   test_subtypes_files() async {
-    String pathB = convertPath('$testProject2/b.dart');
-    String pathC = convertPath('$testProject2/c.dart');
+    String pathB = convertPath('$testPackageLibPath/b.dart');
+    String pathC = convertPath('$testPackageLibPath/c.dart');
     newFile(pathB, content: r'''
 import 'test.dart';
 class B extends A {}
@@ -1666,15 +1702,11 @@
 class D {}
 ''');
 
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {}
 ''');
     var a = findElement.class_('A');
 
-    driver.addFile(pathB);
-    driver.addFile(pathC);
-    await scheduler.waitForIdle();
-
     List<SubtypeResult> subtypes =
         await driver.search.subtypes(SearchedFiles(), type: a);
     expect(subtypes, hasLength(2));
@@ -1687,7 +1719,7 @@
   }
 
   test_subtypes_mixin_superclassConstraints() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {
   void methodA() {}
 }
@@ -1709,8 +1741,8 @@
       expect(subtypes, hasLength(1));
 
       var m = subtypes.singleWhere((r) => r.name == 'M');
-      expect(m.libraryUri, testUri);
-      expect(m.id, '$testUri;$testUri;M');
+      expect(m.libraryUri, testUriStr);
+      expect(m.id, '$testUriStr;$testUriStr;M');
       expect(m.members, ['methodA', 'methodM']);
     }
 
@@ -1719,14 +1751,14 @@
       expect(subtypes, hasLength(1));
 
       var m = subtypes.singleWhere((r) => r.name == 'M');
-      expect(m.libraryUri, testUri);
-      expect(m.id, '$testUri;$testUri;M');
+      expect(m.libraryUri, testUriStr);
+      expect(m.id, '$testUriStr;$testUriStr;M');
       expect(m.members, ['methodA', 'methodM']);
     }
   }
 
   test_subtypes_partWithoutLibrary() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 part of lib;
 
 class A {}
@@ -1739,12 +1771,12 @@
     expect(subtypes, hasLength(1));
 
     SubtypeResult b = subtypes.singleWhere((r) => r.name == 'B');
-    expect(b.libraryUri, testUri);
-    expect(b.id, '$testUri;$testUri;B');
+    expect(b.libraryUri, testUriStr);
+    expect(b.id, '$testUriStr;$testUriStr;B');
   }
 
   test_topLevelElements() async {
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 class A {} // A
 class B = Object with A;
 mixin C {}
@@ -1756,7 +1788,7 @@
     var a = findElement.class_('A');
     var b = findElement.class_('B');
     var c = findElement.mixin('C');
-    var d = findElement.functionTypeAlias('D');
+    var d = findElement.typeAlias('D');
     var f = findElement.function('f');
     var g = findElement.topVar('g');
     RegExp regExp = RegExp(r'^[ABCDfg]$');
@@ -1767,8 +1799,8 @@
   ExpectedResult _expectId(
       Element enclosingElement, SearchResultKind kind, String search,
       {int length, bool isResolved = true, bool isQualified = false}) {
-    int offset = findOffset(search);
-    length ??= getLeadingIdentifierLength(search);
+    int offset = findNode.offset(search);
+    length ??= findNode.simple(search).length;
     return ExpectedResult(enclosingElement, kind, offset, length,
         isResolved: isResolved, isQualified: isQualified);
   }
@@ -1796,22 +1828,9 @@
         isQualified: false, isResolved: false, length: length);
   }
 
-  Future<void> _resolveTestUnit(String code, {bool addToDriver = true}) async {
-    if (addToDriver) {
-      addTestFile(code);
-    } else {
-      testCode = code;
-      newFile(testFile, content: testCode);
-    }
-    if (testUnit == null) {
-      ResolvedUnitResult result = await driver.getResult(testFile);
-      testUnit = result.unit;
-      testUnitElement = testUnit.declaredElement;
-      testLibraryElement = testUnitElement.library;
-
-      findNode = FindNode(result.content, result.unit);
-      findElement = FindElement(result.unit);
-    }
+  Future<List<Element>> _findClassMembers(String name) {
+    var searchedFiles = SearchedFiles();
+    return driver.search.classMembers(name, searchedFiles);
   }
 
   Future<void> _verifyNameReferences(
@@ -1838,21 +1857,112 @@
 }
 
 @reflectiveTest
-class SearchWithNullSafetyTest extends SearchTest {
-  @override
-  AnalysisOptionsImpl createAnalysisOptions() => AnalysisOptionsImpl()
-    ..contextFeatures = FeatureSet.forTesting(
-        sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
+class SearchWithNonFunctionTypeAliasesTest extends SearchTest
+    with WithNonFunctionTypeAliasesMixin {
+  test_searchReferences_ConstructorElement_named_viaTypeAlias() async {
+    await resolveTestCode('''
+class A<T> {
+  A.named();
+}
 
+typedef B = A<int>;
+
+void f() {
+  B.named(); // ref
+}
+''');
+
+    var element = findElement.constructor('named');
+    var f = findElement.topFunction('f');
+    await _verifyReferences(element, [
+      _expectIdQ(f, SearchResultKind.REFERENCE, '.named(); // ref',
+          length: '.named'.length),
+    ]);
+  }
+
+  test_searchReferences_TypeAliasElement() async {
+    await resolveTestCode('''
+class A<T> {
+  static int field = 0;
+  static void method() {}
+}
+
+typedef B = A<int>;
+
+class C extends B {} // extends
+
+void f(B p) {
+  B v;
+  B.field = 1;
+  B.field;
+  B.method();
+}
+''');
+
+    var element = findElement.typeAlias('B');
+    var f = findElement.topFunction('f');
+    await _verifyReferences(element, [
+      _expectId(findElement.class_('C'), SearchResultKind.REFERENCE,
+          'B {} // extends'),
+      _expectId(findElement.parameter('p'), SearchResultKind.REFERENCE, 'B p'),
+      _expectId(f, SearchResultKind.REFERENCE, 'B v'),
+      _expectId(f, SearchResultKind.REFERENCE, 'B.field ='),
+      _expectId(f, SearchResultKind.REFERENCE, 'B.field;'),
+      _expectId(f, SearchResultKind.REFERENCE, 'B.method();'),
+    ]);
+  }
+
+  test_searchReferences_TypeAliasElement_fromLegacy() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef A<T> = Map<int, T>;
+''');
+    await resolveTestCode('''
+// @dart = 2.9
+import 'a.dart';
+
+void f(A<String> a) {}
+''');
+
+    var A = findElement.importFind('package:test/a.dart').typeAlias('A');
+    await _verifyReferences(A, [
+      _expectId(
+        findElement.parameter('a'),
+        SearchResultKind.REFERENCE,
+        'A<String>',
+      ),
+    ]);
+  }
+
+  test_searchReferences_TypeAliasElement_inConstructorName() async {
+    await resolveTestCode('''
+class A<T> {}
+
+typedef B = A<int>;
+
+void f() {
+  B();
+}
+''');
+
+    var element = findElement.typeAlias('B');
+    var f = findElement.topFunction('f');
+    await _verifyReferences(element, [
+      _expectId(f, SearchResultKind.REFERENCE, 'B();'),
+    ]);
+  }
+}
+
+@reflectiveTest
+class SearchWithNullSafetyTest extends SearchTest with WithNullSafetyMixin {
   test_searchReferences_ImportElement_noPrefix_optIn_fromOptOut() async {
-    newFile('/test/lib/a.dart', content: r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class N1 {}
 void N2() {}
 int get N3 => 0;
 set N4(int _) {}
 ''');
 
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 // @dart = 2.7
 import 'a.dart';
 
@@ -1863,7 +1973,7 @@
   N4 = 0;
 }
 ''');
-    ImportElement element = testLibraryElement.imports[0];
+    ImportElement element = findElement.import('package:test/a.dart');
     var main = findElement.function('main');
     var kind = SearchResultKind.REFERENCE;
     var expected = [
@@ -1876,14 +1986,14 @@
   }
 
   test_searchReferences_ImportElement_withPrefix_optIn_fromOptOut() async {
-    newFile('/test/lib/a.dart', content: r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class N1 {}
 void N2() {}
 int get N3 => 0;
 set N4(int _) {}
 ''');
 
-    await _resolveTestUnit('''
+    await resolveTestCode('''
 // @dart = 2.7
 import 'a.dart' as a;
 
@@ -1894,7 +2004,7 @@
   a.N4 = 0;
 }
 ''');
-    ImportElement element = testLibraryElement.imports[0];
+    ImportElement element = findElement.import('package:test/a.dart');
     var main = findElement.function('main');
     var kind = SearchResultKind.REFERENCE;
     var length = 'a.'.length;
diff --git a/pkg/analyzer/test/src/dart/ast/ast_test.dart b/pkg/analyzer/test/src/dart/ast/ast_test.dart
index bb96a03..d054121 100644
--- a/pkg/analyzer/test/src/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/ast_test.dart
@@ -7,7 +7,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/parser_test.dart';
+import '../../../generated/parser_test_base.dart';
 import '../resolution/context_collection_resolution.dart';
 
 main() {
diff --git a/pkg/analyzer/test/src/dart/ast/parse_base.dart b/pkg/analyzer/test/src/dart/ast/parse_base.dart
index d280721..eb662b2 100644
--- a/pkg/analyzer/test/src/dart/ast/parse_base.dart
+++ b/pkg/analyzer/test/src/dart/ast/parse_base.dart
@@ -36,12 +36,10 @@
     var token = scanner.tokenize();
     featureSet = scanner.featureSet;
 
-    var useFasta = analysisOptions.useFastaParser;
     var parser = Parser(
       source,
       errorListener,
       featureSet: featureSet,
-      useFasta: useFasta,
     );
     parser.enableOptionalNewAndConst = true;
 
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index f0b6733..b274c98 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -20,7 +20,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../../generated/elements_types_mixin.dart';
-import '../../../generated/parser_test.dart' show ParserTestCase;
+import '../../../generated/parser_test_base.dart' show ParserTestCase;
 import '../../../util/ast_type_matchers.dart';
 
 main() {
diff --git a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
index 4ba18ab..97a88b3 100644
--- a/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/potentially_constant_test.dart
@@ -14,7 +14,7 @@
     defineReflectiveTests(IsConstantTypeExpressionTest);
     defineReflectiveTests(IsPotentiallyConstantTypeExpressionTest);
     defineReflectiveTests(PotentiallyConstantTest);
-    defineReflectiveTests(PotentiallyConstantWithNullSafetyTest);
+    defineReflectiveTests(PotentiallyConstantWithNonFunctionTypeAliasesTest);
   });
 }
 
@@ -749,6 +749,12 @@
 ''', () => _xInitializer(), () => [findNode.typeName('T>{0')]);
   }
 
+  test_simpleIdentifier_class() async {
+    await _assertConst(r'''
+var x = int;
+''', () => _xInitializer());
+  }
+
   test_simpleIdentifier_function() async {
     await _assertConst(r'''
 var x = f;
@@ -845,9 +851,10 @@
     );
   }
 
-  test_simpleIdentifier_type_class() async {
+  test_simpleIdentifier_typedef_functionType() async {
     await _assertConst(r'''
-var x = int;
+typedef A = void Function();
+var x = A;
 ''', () => _xInitializer());
   }
 
@@ -918,8 +925,8 @@
 }
 
 @reflectiveTest
-class PotentiallyConstantWithNullSafetyTest extends PotentiallyConstantTest
-    with WithNullSafetyMixin {
+class PotentiallyConstantWithNonFunctionTypeAliasesTest
+    extends PotentiallyConstantTest with WithNonFunctionTypeAliasesMixin {
   @override
   test_asExpression_typeParameter() async {
     await _assertConst(r'''
@@ -965,4 +972,21 @@
 }
 ''', () => _xInitializer());
   }
+
+  test_prefixedIdentifier_typedef_interfaceType() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef A = List<int>;
+''');
+    await _assertConst(r'''
+import 'a.dart' as p;
+var x = p.A;
+''', () => _xInitializer());
+  }
+
+  test_simpleIdentifier_typedef_interfaceType() async {
+    await _assertConst(r'''
+typedef A = List<int>;
+var x = A;
+''', () => _xInitializer());
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart
index f9aa5a8..df77b25 100644
--- a/pkg/analyzer/test/src/dart/constant/value_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -261,6 +261,87 @@
     _assertDivide(_doubleValue(null), _intValue(null), _intValue(2));
   }
 
+  void test_eagerAnd_knownBool_knownBool() {
+    void check(bool left, bool right, bool expected) {
+      _assertEagerAnd(
+        _boolValue(expected),
+        _boolValue(left),
+        _boolValue(right),
+      );
+    }
+
+    check(false, false, false);
+    check(true, false, false);
+    check(false, true, false);
+    check(true, true, true);
+  }
+
+  void test_eagerAnd_knownBool_knownInt() {
+    _assertEagerAnd(null, _boolValue(true), _intValue(0));
+  }
+
+  void test_eagerAnd_knownBool_unknownBool() {
+    _assertEagerAnd(_boolValue(null), _boolValue(true), _boolValue(null));
+  }
+
+  void test_eagerAnd_unknownBool_knownBool() {
+    _assertEagerAnd(_boolValue(null), _boolValue(null), _boolValue(true));
+  }
+
+  void test_eagerOr_knownBool_knownBool() {
+    void check(bool left, bool right, bool expected) {
+      _assertEagerOr(
+        _boolValue(expected),
+        _boolValue(left),
+        _boolValue(right),
+      );
+    }
+
+    check(false, false, false);
+    check(true, false, true);
+    check(false, true, true);
+    check(true, true, true);
+  }
+
+  void test_eagerOr_knownBool_knownInt() {
+    _assertEagerOr(null, _boolValue(true), _intValue(0));
+  }
+
+  void test_eagerOr_knownBool_unknownBool() {
+    _assertEagerOr(_boolValue(null), _boolValue(true), _boolValue(null));
+  }
+
+  void test_eagerOr_unknownBool_knownBool() {
+    _assertEagerOr(_boolValue(null), _boolValue(null), _boolValue(true));
+  }
+
+  void test_eagerXor_knownBool_knownBool() {
+    void check(bool left, bool right, bool expected) {
+      _assertEagerXor(
+        _boolValue(expected),
+        _boolValue(left),
+        _boolValue(right),
+      );
+    }
+
+    check(false, false, false);
+    check(true, false, true);
+    check(false, true, true);
+    check(true, true, false);
+  }
+
+  void test_eagerXor_knownBool_knownInt() {
+    _assertEagerXor(null, _boolValue(true), _intValue(0));
+  }
+
+  void test_eagerXor_knownBool_unknownBool() {
+    _assertEagerXor(_boolValue(null), _boolValue(true), _boolValue(null));
+  }
+
+  void test_eagerXor_unknownBool_knownBool() {
+    _assertEagerXor(_boolValue(null), _boolValue(null), _boolValue(true));
+  }
+
   void test_equalEqual_bool_false() {
     _assertEqualEqual(_boolValue(false), _boolValue(false), _boolValue(true));
   }
@@ -834,6 +915,34 @@
     _assertIdentical(_boolValue(null), _stringValue(null), _stringValue("def"));
   }
 
+  void test_identical_Type_interfaceType() {
+    _assertIdentical(
+      _boolValue(true),
+      _typeValue(_typeProvider.intType),
+      _typeValue(_typeProvider.intType),
+    );
+
+    _assertIdentical(
+      _boolValue(false),
+      _typeValue(_typeProvider.intType),
+      _typeValue(_typeProvider.numType),
+    );
+
+    _assertIdentical(
+      _boolValue(true),
+      _typeValue(_typeProvider.futureOrType2(_typeProvider.objectType)),
+      _typeValue(_typeProvider.objectType),
+    );
+  }
+
+  void test_identical_Type_notType() {
+    _assertIdentical(
+      _boolValue(false),
+      _typeValue(_typeProvider.intType),
+      _intValue(0),
+    );
+  }
+
   void test_integerDivide_infinity_knownDouble() {
     _assertIntegerDivide(
       null,
@@ -1688,10 +1797,10 @@
       DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
     if (expected == null) {
       expect(() {
-        left.eagerAnd(_typeSystem, right, false);
+        left.eagerAnd(_typeSystem, right);
       }, throwsEvaluationException);
     } else {
-      DartObjectImpl result = left.eagerAnd(_typeSystem, right, false);
+      DartObjectImpl result = left.eagerAnd(_typeSystem, right);
       expect(result, isNotNull);
       expect(result, expected);
     }
@@ -1704,10 +1813,10 @@
       DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
     if (expected == null) {
       expect(() {
-        left.eagerOr(_typeSystem, right, false);
+        left.eagerOr(_typeSystem, right);
       }, throwsEvaluationException);
     } else {
-      DartObjectImpl result = left.eagerOr(_typeSystem, right, false);
+      DartObjectImpl result = left.eagerOr(_typeSystem, right);
       expect(result, isNotNull);
       expect(result, expected);
     }
@@ -1720,10 +1829,10 @@
       DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
     if (expected == null) {
       expect(() {
-        left.eagerXor(_typeSystem, right, false);
+        left.eagerXor(_typeSystem, right);
       }, throwsEvaluationException);
     } else {
-      DartObjectImpl result = left.eagerXor(_typeSystem, right, false);
+      DartObjectImpl result = left.eagerXor(_typeSystem, right);
       expect(result, isNotNull);
       expect(result, expected);
     }
@@ -2142,4 +2251,12 @@
       SymbolState(value),
     );
   }
+
+  DartObjectImpl _typeValue(DartType value) {
+    return DartObjectImpl(
+      _typeSystem,
+      _typeProvider.typeType,
+      TypeState(value),
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index b4e5635..167c6d5 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -58,6 +58,7 @@
 
     testLibrary = library_(
       uriStr: 'package:test/test.dart',
+      analysisContext: _analysisContext,
       analysisSession: _analysisContext.analysisSession,
       typeSystem: typeSystem,
     );
diff --git a/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart b/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart
new file mode 100644
index 0000000..2d92505
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart
@@ -0,0 +1,275 @@
+// 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/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:meta/meta.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/type_system_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(GreatestClosureLegacyTest);
+    defineReflectiveTests(GreatestClosureNullSafetyTest);
+  });
+}
+
+@reflectiveTest
+class GreatestClosureLegacyTest extends AbstractTypeSystemTest {
+  TypeParameterElement T;
+  TypeParameterType T_none;
+  TypeParameterType T_question;
+  TypeParameterType T_star;
+
+  @override
+  void setUp() {
+    super.setUp();
+
+    T = typeParameter('T');
+    T_none = typeParameterTypeNone(T);
+    T_question = typeParameterTypeQuestion(T);
+    T_star = typeParameterTypeStar(T);
+  }
+
+  test_contravariant() {
+    _check(
+      functionTypeStar(returnType: voidNone, parameters: [
+        requiredParameter(type: T_star),
+      ]),
+      greatest: 'void Function(Null*)*',
+      least: 'void Function(dynamic)*',
+    );
+
+    _check(
+      functionTypeStar(
+        returnType: functionTypeStar(
+          returnType: voidNone,
+          parameters: [
+            requiredParameter(type: T_star),
+          ],
+        ),
+      ),
+      greatest: 'void Function(Null*)* Function()*',
+      least: 'void Function(dynamic)* Function()*',
+    );
+  }
+
+  test_covariant() {
+    _check(T_star, greatest: 'dynamic', least: 'Null*');
+
+    _check(
+      listStar(T_star),
+      greatest: 'List<dynamic>*',
+      least: 'List<Null*>*',
+    );
+
+    _check(
+      functionTypeStar(returnType: voidNone, parameters: [
+        requiredParameter(
+          type: functionTypeStar(returnType: intStar, parameters: [
+            requiredParameter(type: T_star),
+          ]),
+        ),
+      ]),
+      greatest: 'void Function(int* Function(dynamic)*)*',
+      least: 'void Function(int* Function(Null*)*)*',
+    );
+  }
+
+  test_function() {
+    // void Function<U extends T>()
+    _check(
+      functionTypeStar(
+        typeFormals: [
+          typeParameter('U', bound: T_star),
+        ],
+        returnType: voidNone,
+      ),
+      greatest: 'Function*',
+      least: 'Null*',
+    );
+  }
+
+  test_unrelated() {
+    _check1(intStar, 'int*');
+    _check1(listStar(intStar), 'List<int*>*');
+
+    _check1(objectStar, 'Object*');
+    _check1(neverStar, 'Never*');
+    _check1(nullStar, 'Null*');
+
+    _check1(dynamicNone, 'dynamic');
+
+    _check1(
+      functionTypeStar(returnType: stringStar, parameters: [
+        requiredParameter(type: intStar),
+      ]),
+      'String* Function(int*)*',
+    );
+
+    _check1(
+      typeParameterTypeStar(
+        typeParameter('U'),
+      ),
+      'U*',
+    );
+  }
+
+  void _check(
+    DartType type, {
+    @required String greatest,
+    @required String least,
+  }) {
+    var greatestResult = typeSystem.greatestClosure(type, [T]);
+    expect(
+      greatestResult.getDisplayString(withNullability: true),
+      greatest,
+    );
+
+    var leastResult = typeSystem.leastClosure(type, [T]);
+    expect(
+      leastResult.getDisplayString(withNullability: true),
+      least,
+    );
+  }
+
+  void _check1(DartType type, String expected) {
+    _check(type, greatest: expected, least: expected);
+  }
+}
+
+@reflectiveTest
+class GreatestClosureNullSafetyTest extends AbstractTypeSystemNullSafetyTest {
+  TypeParameterElement T;
+  TypeParameterType T_none;
+  TypeParameterType T_question;
+  TypeParameterType T_star;
+
+  @override
+  void setUp() {
+    super.setUp();
+
+    T = typeParameter('T');
+    T_none = typeParameterTypeNone(T);
+    T_question = typeParameterTypeQuestion(T);
+    T_star = typeParameterTypeStar(T);
+  }
+
+  test_contravariant() {
+    _check(
+      functionTypeNone(returnType: voidNone, parameters: [
+        requiredParameter(type: T_none),
+      ]),
+      greatest: 'void Function(Never)',
+      least: 'void Function(Object?)',
+    );
+
+    _check(
+      functionTypeNone(
+        returnType: functionTypeNone(
+          returnType: voidNone,
+          parameters: [
+            requiredParameter(type: T_none),
+          ],
+        ),
+      ),
+      greatest: 'void Function(Never) Function()',
+      least: 'void Function(Object?) Function()',
+    );
+  }
+
+  test_covariant() {
+    _check(T_none, greatest: 'Object?', least: 'Never');
+    _check(T_question, greatest: 'Object?', least: 'Never?');
+    _check(T_star, greatest: 'Object?', least: 'Never*');
+
+    _check(
+      listNone(T_none),
+      greatest: 'List<Object?>',
+      least: 'List<Never>',
+    );
+
+    _check(
+        functionTypeNone(returnType: voidNone, parameters: [
+          requiredParameter(
+            type: functionTypeNone(returnType: intNone, parameters: [
+              requiredParameter(type: T_none),
+            ]),
+          ),
+        ]),
+        greatest: 'void Function(int Function(Object?))',
+        least: 'void Function(int Function(Never))');
+  }
+
+  test_function() {
+    // void Function<U extends T>()
+    _check(
+      functionTypeNone(
+        typeFormals: [
+          typeParameter('U', bound: T_none),
+        ],
+        returnType: voidNone,
+      ),
+      greatest: 'Function',
+      least: 'Never',
+    );
+  }
+
+  test_unrelated() {
+    _check1(intNone, 'int');
+    _check1(intQuestion, 'int?');
+    _check1(intStar, 'int*');
+
+    _check1(listNone(intNone), 'List<int>');
+    _check1(listQuestion(intNone), 'List<int>?');
+
+    _check1(objectNone, 'Object');
+    _check1(objectQuestion, 'Object?');
+    _check1(objectStar, 'Object*');
+
+    _check1(neverNone, 'Never');
+    _check1(neverQuestion, 'Never?');
+    _check1(neverStar, 'Never*');
+
+    _check1(dynamicNone, 'dynamic');
+
+    _check1(
+      functionTypeNone(returnType: stringNone, parameters: [
+        requiredParameter(type: intNone),
+      ]),
+      'String Function(int)',
+    );
+
+    _check1(
+      typeParameterTypeNone(
+        typeParameter('U'),
+      ),
+      'U',
+    );
+  }
+
+  void _check(
+    DartType type, {
+    @required String greatest,
+    @required String least,
+  }) {
+    var greatestResult = typeSystem.greatestClosure(type, [T]);
+    expect(
+      greatestResult.getDisplayString(withNullability: true),
+      greatest,
+    );
+
+    var leastResult = typeSystem.leastClosure(type, [T]);
+    expect(
+      leastResult.getDisplayString(withNullability: true),
+      least,
+    );
+  }
+
+  void _check1(DartType type, String expected) {
+    _check(type, greatest: expected, least: expected);
+  }
+}
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 b266e1d..227d2cf 100644
--- a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
+++ b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -158,6 +158,28 @@
     );
   }
 
+  test_functionType_returnType_fromAlias() {
+    var T = typeParameter('T');
+    var A = typeAlias(
+      name: 'A',
+      typeParameters: [T],
+      aliasedType: functionTypeNone(returnType: intNone),
+    );
+
+    var input = A.instantiate(
+      typeArguments: [intNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    expect(_typeToString(input), 'int Function()');
+    expect(input.aliasElement, same(A));
+    expect(input.aliasArguments.map(_typeToString).join(', '), 'int');
+
+    var result = NullabilityEliminator.perform(typeProvider, input);
+    expect(_typeToString(result), 'int* Function()*');
+    expect(result.aliasElement, same(A));
+    expect(result.aliasArguments.map(_typeToString).join(', '), 'int*');
+  }
+
   test_functionType_typeParameters() {
     var T = typeParameter('T');
 
@@ -254,6 +276,28 @@
     );
   }
 
+  test_interfaceType_fromAlias() {
+    var T = typeParameter('T');
+    var A = typeAlias(
+      name: 'A',
+      typeParameters: [T],
+      aliasedType: listNone(
+        typeParameterTypeNone(T),
+      ),
+    );
+
+    var input = A.instantiate(
+      typeArguments: [intNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    expect(_typeToString(input), 'List<int>');
+
+    var result = NullabilityEliminator.perform(typeProvider, input);
+    expect(_typeToString(result), 'List<int*>*');
+    expect(result.aliasElement, same(A));
+    expect(result.aliasArguments.map(_typeToString).join(', '), 'int*');
+  }
+
   test_interfaceType_int() {
     _verify(intNone, intStar);
     _verify(intQuestion, intStar);
@@ -305,7 +349,7 @@
     _verifySame(typeProvider.voidType);
   }
 
-  String _typeToString(TypeImpl type) {
+  String _typeToString(DartType type) {
     return type.getDisplayString(withNullability: true);
   }
 
diff --git a/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart b/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
index 4851abd..ea0ffef 100644
--- a/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
+++ b/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
@@ -3,8 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -36,6 +38,10 @@
     _check(dynamicNone, 'Null*');
     _check(voidNone, 'Null*');
 
+    _check(listStar(objectStar), 'List<Null*>*');
+    _check(listStar(dynamicNone), 'List<Null*>*');
+    _check(listStar(voidNone), 'List<Null*>*');
+
     _check(futureOrStar(objectStar), 'Null*');
     _check(futureOrStar(dynamicNone), 'Null*');
     _check(futureOrStar(voidNone), 'Null*');
@@ -53,6 +59,7 @@
       typeStr: 'int* Function(int* Function(Object*)*)*',
     );
 
+    _check(intStar, 'int*');
     _check(listStar(intStar), 'List<int*>*');
   }
 
@@ -98,12 +105,17 @@
     );
   }
 
-  test_covariant_top() {
+  test_notContravariant_covariant_top() {
     _check(objectQuestion, 'Never');
     _check(objectStar, 'Never');
     _check(dynamicNone, 'Never');
     _check(voidNone, 'Never');
 
+    _check(listNone(objectQuestion), 'List<Never>');
+    _check(listNone(objectStar), 'List<Never>');
+    _check(listNone(dynamicNone), 'List<Never>');
+    _check(listNone(voidNone), 'List<Never>');
+
     _check(futureOrNone(objectQuestion), 'Never');
     _check(futureOrNone(objectStar), 'Never');
     _check(futureOrNone(dynamicNone), 'Never');
@@ -122,12 +134,35 @@
       typeStr: 'int Function(int Function(Object?))',
     );
 
+    _check(intNone, 'int');
+    _check(intQuestion, 'int?');
+
     _check(listNone(intNone), 'List<int>');
     _check(listNone(intQuestion), 'List<int?>');
     _check(listQuestion(intNone), 'List<int>?');
     _check(listQuestion(intQuestion), 'List<int?>?');
   }
 
+  test_notContravariant_invariant() {
+    // typedef F<T> = T Function(T);
+    var T = typeParameter('T', variance: Variance.invariant);
+    var T_none = typeParameterTypeNone(T);
+    var F = typeAlias(
+      name: 'F',
+      typeParameters: [T],
+      aliasedType: functionTypeNone(
+        returnType: T_none,
+        parameters: [requiredParameter(type: T_none)],
+      ),
+    );
+
+    var F_dynamic = F.instantiate(
+      typeArguments: [dynamicNone],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    _check(F_dynamic, 'Never Function(Never)');
+  }
+
   void _check(DartType type, String expectedStr, {String typeStr}) {
     NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
       if (typeStr != null) {
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 4cb55f1..18b28e1 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -5410,6 +5410,21 @@
     );
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/language/issues/433')
+  test_typeParameter_44() {
+    var T = typeParameter('T');
+    var T_none = typeParameterTypeNone(T);
+    var FutureOr_T_none = futureOrNone(T_none);
+    T.bound = FutureOr_T_none;
+
+    isSubtype(
+      T_none,
+      FutureOr_T_none,
+      strT0: 'T, T extends FutureOr<T>',
+      strT1: 'FutureOr<T>, T extends FutureOr<T>',
+    );
+  }
+
   void _defineType(String str, DartType type) {
     for (var key in _types.keys) {
       if (key == 'Never' || _typeStr(type) == 'Never') {
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index 6efd3dd..f86065c 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -13,6 +13,7 @@
 import 'future_value_type_test.dart' as future_value_type;
 import 'generic_inferrer_test.dart' as generic_inferrer;
 import 'inheritance_manager3_test.dart' as inheritance_manager3;
+import 'least_greatest_closure_test.dart' as least_greatest_closure_test;
 import 'least_upper_bound_helper_test.dart' as least_upper_bound_helper;
 import 'normalize_type_test.dart' as normalize_type;
 import 'nullability_eliminator_test.dart' as nullability_eliminator;
@@ -25,6 +26,7 @@
 import 'type_bounded_test.dart' as type_bounded;
 import 'type_constraint_gatherer_test.dart' as type_constraint_gatherer;
 import 'type_parameter_element_test.dart' as type_parameter_element;
+import 'type_references_any_test.dart' as type_references_any;
 import 'type_visitor_test.dart' as type_visitor;
 import 'upper_lower_bound_test.dart' as upper_bound;
 
@@ -40,6 +42,7 @@
     future_value_type.main();
     generic_inferrer.main();
     inheritance_manager3.main();
+    least_greatest_closure_test.main();
     least_upper_bound_helper.main();
     normalize_type.main();
     nullability_eliminator.main();
@@ -52,6 +55,7 @@
     type_bounded.main();
     type_constraint_gatherer.main();
     type_parameter_element.main();
+    type_references_any.main();
     type_visitor.main();
     upper_bound.main();
   }, name: 'element');
diff --git a/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart b/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
index 63715f5..94d6e21 100644
--- a/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
@@ -20,10 +20,10 @@
 
 @reflectiveTest
 class TypeConstraintGathererTest extends AbstractTypeSystemNullSafetyTest {
-  TypeParameterElement T;
-  TypeParameterType T_none;
-  TypeParameterType T_question;
-  TypeParameterType T_star;
+  /*late*/ TypeParameterElement T;
+  /*late*/ TypeParameterType T_none;
+  /*late*/ TypeParameterType T_question;
+  /*late*/ TypeParameterType T_star;
 
   UnknownInferredType get unknownType => UnknownInferredType.instance;
 
@@ -681,6 +681,7 @@
     ) {
       var library = library_(
         uriStr: 'package:test/test.dart',
+        analysisContext: analysisContext,
         analysisSession: analysisContext.analysisSession,
         typeSystem: typeSystem,
       );
diff --git a/pkg/analyzer/test/src/dart/element/type_references_any_test.dart b/pkg/analyzer/test/src/dart/element/type_references_any_test.dart
new file mode 100644
index 0000000..60b8192
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/type_references_any_test.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.
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/type_system_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TypeReferencesAnyTest);
+  });
+}
+
+@reflectiveTest
+class TypeReferencesAnyTest extends AbstractTypeSystemNullSafetyTest {
+  TypeParameterElement T;
+  TypeParameterType T_none;
+
+  @override
+  void setUp() {
+    super.setUp();
+
+    T = typeParameter('T');
+    T_none = typeParameterTypeNone(T);
+  }
+
+  test_false() {
+    _checkFalse(dynamicNone);
+    _checkFalse(intNone);
+    _checkFalse(neverNone);
+    _checkFalse(voidNone);
+    _checkFalse(listNone(intNone));
+  }
+
+  test_true() {
+    _checkTrue(T_none);
+    _checkTrue(listNone(T_none));
+    _checkTrue(mapNone(T_none, intNone));
+    _checkTrue(mapNone(intNone, T_none));
+
+    _checkTrue(functionTypeNone(returnType: T_none));
+
+    _checkTrue(
+      functionTypeNone(returnType: voidNone, parameters: [
+        requiredParameter(type: T_none),
+      ]),
+    );
+
+    _checkTrue(
+      functionTypeNone(
+        typeFormals: [
+          typeParameter('U', bound: T_none),
+        ],
+        returnType: voidNone,
+      ),
+    );
+  }
+
+  void _checkFalse(DartType type) {
+    var actual = (type as TypeImpl).referencesAny({T});
+    expect(actual, isFalse);
+  }
+
+  void _checkTrue(DartType type) {
+    var actual = (type as TypeImpl).referencesAny({T});
+    expect(actual, isTrue);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
index 77f2918..6e4b9fe 100644
--- a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
+++ b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
@@ -3092,6 +3092,63 @@
     );
   }
 
+  void test_typeParameter_greatestClosure_functionBounded() {
+    var T = typeParameter('T');
+    var T_none = typeParameterTypeNone(T);
+    T.bound = functionTypeNone(
+      returnType: voidNone,
+      parameters: [
+        requiredParameter(type: T_none),
+      ],
+    );
+
+    _checkLeastUpperBound(
+      T_none,
+      functionTypeNone(
+        returnType: voidNone,
+        parameters: [
+          requiredParameter(type: nullNone),
+        ],
+      ),
+      functionTypeNone(
+        returnType: voidNone,
+        parameters: [
+          requiredParameter(type: neverNone),
+        ],
+      ),
+    );
+  }
+
+  void test_typeParameter_greatestClosure_functionPromoted() {
+    var T = typeParameter('T');
+    var T_none = typeParameterTypeNone(T);
+    var T_none_promoted = typeParameterTypeNone(
+      T,
+      promotedBound: functionTypeNone(
+        returnType: voidNone,
+        parameters: [
+          requiredParameter(type: T_none),
+        ],
+      ),
+    );
+
+    _checkLeastUpperBound(
+      T_none_promoted,
+      functionTypeNone(
+        returnType: voidNone,
+        parameters: [
+          requiredParameter(type: nullNone),
+        ],
+      ),
+      functionTypeNone(
+        returnType: voidNone,
+        parameters: [
+          requiredParameter(type: neverNone),
+        ],
+      ),
+    );
+  }
+
   void test_typeParameter_interface_bounded() {
     var A = class_(name: 'A');
     var A_none = interfaceTypeNone(A);
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 b462f39..2f77d87 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
@@ -273,6 +273,30 @@
     ]);
   }
 
+  test_analysisOptions_file_inThirdPartyDartLang() async {
+    newFile('/workspace/dart/analysis_options/lib/third_party.yaml',
+        content: r'''
+analyzer:
+  strong-mode:
+    implicit-casts: false
+''');
+
+    newFile('/workspace/thid_party/dart_lang/aaa/analysis_options.yaml',
+        content: r'''
+analyzer:
+  strong-mode:
+    implicit-casts: true
+''');
+
+    var aPath = convertPath('/workspace/third_party/dart_lang/aaa/lib/a.dart');
+    await assertErrorsInFile(aPath, r'''
+num a = 0;
+int b = a;
+''', [
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 19, 1),
+    ]);
+  }
+
   test_analysisOptions_lints() async {
     newFile('/workspace/dart/analysis_options/lib/default.yaml', content: r'''
 linter:
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index d07c1ac..f5bd0cd 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -13,6 +13,9 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(AssignmentDriverResolutionTest);
     defineReflectiveTests(AssignmentDriverResolutionWithNullSafetyTest);
+    defineReflectiveTests(
+      AssignmentDriverResolutionWithNonFunctionTypeAliasesTest,
+    );
   });
 }
 
@@ -235,22 +238,19 @@
 
     assertSimpleIdentifier(
       findNode.simple('a['),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       findNode.simple('b]'),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       assignment.rightHandSide,
-      readElement: findElement.parameter('c'),
-      writeElement: null,
+      element: findElement.parameter('c'),
       type: 'int',
     );
   }
@@ -278,22 +278,19 @@
 
     assertSimpleIdentifier(
       findNode.simple('a['),
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'int',
     );
 
     assertSimpleIdentifier(
       findNode.simple('b]'),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       assignment.rightHandSide,
-      readElement: findElement.parameter('c'),
-      writeElement: null,
+      element: findElement.parameter('c'),
       type: 'int',
     );
   }
@@ -324,22 +321,19 @@
 
     assertSimpleIdentifier(
       findNode.simple('a['),
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'A',
     );
 
     assertSimpleIdentifier(
       findNode.simple('b]'),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       assignment.rightHandSide,
-      readElement: findElement.parameter('c'),
-      writeElement: null,
+      element: findElement.parameter('c'),
       type: 'int',
     );
   }
@@ -417,22 +411,19 @@
 
     assertSimpleIdentifier(
       findNode.simple('a + b'),
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'int',
     );
 
     assertSimpleIdentifier(
       findNode.simple('b)'),
-      readElement: findElement.parameter('b'),
-      writeElement: null,
+      element: findElement.parameter('b'),
       type: 'int',
     );
 
     assertSimpleIdentifier(
       findNode.simple('c;'),
-      readElement: findElement.parameter('c'),
-      writeElement: null,
+      element: findElement.parameter('c'),
       type: 'double',
     );
   }
@@ -459,8 +450,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('y;'),
-      readElement: findElement.parameter('y'),
-      writeElement: null,
+      element: findElement.parameter('y'),
       type: 'int',
     );
   }
@@ -487,8 +477,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('y;'),
-      readElement: findElement.parameter('y'),
-      writeElement: null,
+      element: findElement.parameter('y'),
       type: 'int',
     );
   }
@@ -515,8 +504,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('y;'),
-      readElement: findElement.parameter('y'),
-      writeElement: null,
+      element: findElement.parameter('y'),
       type: 'int',
     );
   }
@@ -543,8 +531,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('y;'),
-      readElement: findElement.parameter('y'),
-      writeElement: null,
+      element: findElement.parameter('y'),
       type: 'int',
     );
   }
@@ -571,8 +558,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('y;'),
-      readElement: findElement.parameter('y'),
-      writeElement: null,
+      element: findElement.parameter('y'),
       type: 'int',
     );
   }
@@ -599,8 +585,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('y;'),
-      readElement: findElement.parameter('y'),
-      writeElement: null,
+      element: findElement.parameter('y'),
       type: 'int',
     );
   }
@@ -636,9 +621,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: matcherC,
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -668,9 +650,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.class_('C'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -717,9 +696,6 @@
     var prefixed = assignment.leftHandSide as PrefixedIdentifier;
     assertSimpleIdentifierAssignmentTarget(
       prefixed.identifier,
-      readElement: findElement.getter('x'),
-      writeElement: findElement.setter('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -750,9 +726,6 @@
     var prefixed = assignment.leftHandSide as PrefixedIdentifier;
     assertSimpleIdentifierAssignmentTarget(
       prefixed.identifier,
-      readElement: null,
-      writeElement: findElement.setter('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -785,9 +758,6 @@
     var prefixed = assignment.leftHandSide as PrefixedIdentifier;
     assertSimpleIdentifierAssignmentTarget(
       prefixed.identifier,
-      readElement: null,
-      writeElement: findElement.getter('x'),
-      type: 'dynamic',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -818,9 +788,6 @@
     var prefixed = assignment.leftHandSide as PrefixedIdentifier;
     assertSimpleIdentifierAssignmentTarget(
       prefixed.identifier,
-      readElement: null,
-      writeElement: findElement.setter('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -853,9 +820,6 @@
     var prefixed = assignment.leftHandSide as PrefixedIdentifier;
     assertSimpleIdentifierAssignmentTarget(
       prefixed.identifier,
-      readElement: null,
-      writeElement: findElement.getter('x'),
-      type: 'dynamic',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -895,9 +859,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       prefixed.identifier,
-      readElement: importFind.topGet('x'),
-      writeElement: importFind.topSet('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -925,22 +886,17 @@
 
     assertSimpleIdentifier(
       findNode.simple('a.'),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       findNode.simple('b ='),
-      readElement: null,
-      writeElement: null,
-      type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       assignment.rightHandSide,
-      readElement: findElement.parameter('c'),
-      writeElement: null,
+      element: findElement.parameter('c'),
       type: 'int',
     );
   }
@@ -968,22 +924,17 @@
 
     assertSimpleIdentifier(
       findNode.simple('a.'),
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'int',
     );
 
     assertSimpleIdentifierAssignmentTarget(
       findNode.simple('b +='),
-      readElement: null,
-      writeElement: null,
-      type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       assignment.rightHandSide,
-      readElement: findElement.parameter('c'),
-      writeElement: null,
+      element: findElement.parameter('c'),
       type: 'int',
     );
   }
@@ -1017,9 +968,6 @@
     var propertyAccess = assignment.leftHandSide as PropertyAccess;
     assertSimpleIdentifierAssignmentTarget(
       propertyAccess.propertyName,
-      readElement: findElement.getter('x'),
-      writeElement: findElement.setter('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1082,9 +1030,6 @@
     var propertyAccess = assignment.leftHandSide as PropertyAccess;
     assertSimpleIdentifierAssignmentTarget(
       propertyAccess.propertyName,
-      readElement: findElement.getter('x'),
-      writeElement: findElement.setter('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1152,9 +1097,6 @@
     var propertyAccess = assignment.leftHandSide as PropertyAccess;
     assertSimpleIdentifierAssignmentTarget(
       propertyAccess.propertyName,
-      readElement: null,
-      writeElement: findElement.setter('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1195,9 +1137,6 @@
     assertSuperExpression(propertyAccess.target);
     assertSimpleIdentifierAssignmentTarget(
       propertyAccess.propertyName,
-      readElement: findElement.getter('x', of: 'A'),
-      writeElement: findElement.setter('x', of: 'A'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1232,9 +1171,6 @@
     var propertyAccess = assignment.leftHandSide as PropertyAccess;
     assertSimpleIdentifierAssignmentTarget(
       propertyAccess.propertyName,
-      readElement: findElement.getter('x'),
-      writeElement: findElement.setter('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1262,22 +1198,17 @@
 
     assertSimpleIdentifier(
       findNode.simple('a)'),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       findNode.simple('b ='),
-      readElement: null,
-      writeElement: null,
-      type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       findNode.simple('c;'),
-      readElement: findElement.parameter('c'),
-      writeElement: null,
+      element: findElement.parameter('c'),
       type: 'int',
     );
   }
@@ -1304,22 +1235,17 @@
 
     assertSimpleIdentifier(
       findNode.simple('a)'),
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'int',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       findNode.simple('b ='),
-      readElement: null,
-      writeElement: null,
-      type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       findNode.simple('c;'),
-      readElement: findElement.parameter('c'),
-      writeElement: null,
+      element: findElement.parameter('c'),
       type: 'int',
     );
   }
@@ -1348,9 +1274,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.setter('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1380,9 +1303,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.setter('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1414,9 +1334,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.getter('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1448,9 +1365,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.getter('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1480,9 +1394,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.topGet('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1519,9 +1430,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.prefix('x'),
-      type: null,
     );
   }
 
@@ -1549,9 +1457,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.prefix('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1582,9 +1487,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.localVar('x'),
-      writeElement: findElement.localVar('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1610,11 +1512,8 @@
       type: 'int',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.localVar('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1642,11 +1541,8 @@
       type: 'int',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.localVar('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1674,11 +1570,8 @@
       type: 'int',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.localVar('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1705,9 +1598,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.parameter('x'),
-      writeElement: findElement.parameter('x'),
-      type: 'num$question',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1741,9 +1631,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.parameter('x'),
-      writeElement: findElement.parameter('x'),
-      type: 'B$question',
     );
 
     assertType(assignment.rightHandSide, 'C');
@@ -1773,15 +1660,11 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.parameter('a'),
-      writeElement: findElement.parameter('a'),
-      type: 'double$question',
     );
 
     assertSimpleIdentifier(
       assignment.rightHandSide,
-      readElement: findElement.parameter('b'),
-      writeElement: null,
+      element: findElement.parameter('b'),
       type: 'int',
     );
   }
@@ -1841,11 +1724,8 @@
       type: 'int',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.parameter('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1876,11 +1756,8 @@
       type: expectedType,
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.parameter('x'),
-      type: 'Object',
     );
 
     assertType(assignment.rightHandSide, expectedType);
@@ -1906,11 +1783,8 @@
       type: 'bool',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.parameter('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'bool');
@@ -1936,11 +1810,8 @@
       type: 'int',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.parameter('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -1977,9 +1848,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.getter('x', of: 'B'),
-      type: null,
     );
   }
 
@@ -2014,9 +1882,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.method('x', of: 'B'),
-      type: null,
     );
   }
 
@@ -2046,9 +1911,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.setter('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2074,17 +1936,13 @@
       type: 'int',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: null,
-      type: 'dynamic',
     );
 
     assertSimpleIdentifier(
       assignment.rightHandSide,
-      readElement: findElement.parameter('y'),
-      writeElement: null,
+      element: findElement.parameter('y'),
       type: 'int',
     );
   }
@@ -2117,9 +1975,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.setter('x', of: 'A'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2153,9 +2008,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.getter('x'),
-      writeElement: findElement.setter('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2196,9 +2048,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.getter('x', of: 'M2'),
-      writeElement: findElement.setter('x', of: 'M2'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2235,9 +2084,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.topGet('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2269,9 +2115,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.topGet('x'),
-      writeElement: findElement.topSet('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2307,9 +2150,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.topGet('x'),
-      writeElement: findElement.topSet('x'),
-      type: 'B$question',
     );
 
     assertType(assignment.rightHandSide, 'C');
@@ -2343,9 +2183,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: findElement.topGet('x'),
-      writeElement: findElement.topSet('x'),
-      type: 'num',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2373,9 +2210,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.topSet('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2405,9 +2239,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.topSet('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'bool');
@@ -2437,9 +2268,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: findElement.topGet('x'),
-      type: null,
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2467,9 +2295,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: intElement,
-      type: 'dynamic',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2497,9 +2322,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: intElement,
-      type: 'Type',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2527,9 +2349,6 @@
 
     assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: null,
-      type: 'dynamic',
     );
 
     assertType(assignment.rightHandSide, 'int');
@@ -2555,23 +2374,59 @@
       type: 'int',
     );
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       assignment.leftHandSide,
-      readElement: null,
-      writeElement: null,
-      type: null,
     );
 
     assertSimpleIdentifier(
       assignment.rightHandSide,
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'int',
     );
   }
 }
 
 @reflectiveTest
+class AssignmentDriverResolutionWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  test_prefixedIdentifier_typeAlias_static_compound() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static int get x => 0;
+  static set x(int _) {}
+}
+
+typedef B = A;
+
+void f() {
+  B.x += 2;
+}
+''');
+
+    var assignment = findNode.assignment('x += 2');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('x'),
+      readType: 'int',
+      writeElement: findElement.setter('x'),
+      writeType: 'int',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    var prefixed = assignment.leftHandSide as PrefixedIdentifier;
+    assertSimpleIdentifierAssignmentTarget(
+      prefixed.identifier,
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+}
+
+@reflectiveTest
 class AssignmentDriverResolutionWithNullSafetyTest
     extends PubPackageResolutionTest
     with WithNullSafetyMixin, AssignmentDriverResolutionTestCases {}
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 a51644b..4225019 100644
--- a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
@@ -15,11 +15,17 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AstRewriteMethodInvocationTest);
+    defineReflectiveTests(
+      AstRewriteMethodInvocationWithNonFunctionTypeAliasesTest,
+    );
   });
 }
 
 @reflectiveTest
-class AstRewriteMethodInvocationTest extends PubPackageResolutionTest {
+class AstRewriteMethodInvocationTest extends PubPackageResolutionTest
+    with AstRewriteMethodInvocationTestCases {}
+
+mixin AstRewriteMethodInvocationTestCases on PubPackageResolutionTest {
   test_targetNull_cascade() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -379,3 +385,107 @@
     expect(argumentStrings, expectedArguments);
   }
 }
+
+@reflectiveTest
+class AstRewriteMethodInvocationWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest
+    with WithNonFunctionTypeAliasesMixin, AstRewriteMethodInvocationTestCases {
+  test_targetNull_typeAlias_interfaceType() async {
+    await assertNoErrorsInCode(r'''
+class A<T, U> {
+  A(int _);
+}
+
+typedef X<T, U> = A<T, U>;
+
+void f() {
+  X<int, String>(0);
+}
+''');
+
+    var creation = findNode.instanceCreation('X<int, String>(0);');
+    assertInstanceCreation(
+      creation,
+      findElement.class_('A'),
+      'A<int, String>',
+      expectedConstructorMember: true,
+      expectedSubstitution: {'T': 'int', 'U': 'String'},
+      expectedTypeNameElement: findElement.typeAlias('X'),
+    );
+    _assertArgumentList(creation.argumentList, ['0']);
+  }
+
+  test_targetNull_typeAlias_Never() async {
+    await assertErrorsInCode(r'''
+typedef X = Never;
+
+void f() {
+  X(0);
+}
+''', [
+      error(CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION, 33, 1),
+    ]);
+
+    // Not rewritten.
+    findNode.methodInvocation('X(0)');
+  }
+
+  test_targetPrefixedIdentifier_typeAlias_interfaceType_constructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A<T> {
+  A.named(T a);
+}
+
+typedef X<T> = A<T>;
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'a.dart' as prefix;
+
+void f() {
+  prefix.X.named(0);
+}
+''');
+
+    var importFind = findElement.importFind('package:test/a.dart');
+
+    var creation = findNode.instanceCreation('X.named(0);');
+    assertInstanceCreation(
+      creation,
+      importFind.class_('A'),
+      'A<int>',
+      constructorName: 'named',
+      expectedConstructorMember: true,
+      expectedSubstitution: {'T': 'int'},
+      expectedPrefix: findElement.prefix('prefix'),
+      expectedTypeNameElement: importFind.typeAlias('X'),
+    );
+    _assertArgumentList(creation.argumentList, ['0']);
+  }
+
+  test_targetSimpleIdentifier_typeAlias_interfaceType_constructor() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  A.named(T a);
+}
+
+typedef X<T> = A<T>;
+
+void f() {
+  X.named(0);
+}
+''');
+
+    var creation = findNode.instanceCreation('X.named(0);');
+    assertInstanceCreation(
+      creation,
+      findElement.class_('A'),
+      'A<int>',
+      constructorName: 'named',
+      expectedConstructorMember: true,
+      expectedSubstitution: {'T': 'int'},
+      expectedTypeNameElement: findElement.typeAlias('X'),
+    );
+    _assertArgumentList(creation.argumentList, ['0']);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
index b484064..a5be3c1 100644
--- a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
@@ -341,7 +341,6 @@
         [typeToStringWithNullability ? 'int' : 'num']);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/43114')
   test_plus_int_context_int_via_extension_explicit() async {
     await assertErrorsInCode('''
 extension E on int {
@@ -438,7 +437,6 @@
     );
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/43114')
   test_plus_int_int_via_extension_explicit() async {
     await assertNoErrorsInCode('''
 extension E on int {
@@ -511,7 +509,6 @@
     assertTypeArgumentTypes(findNode.methodInvocation('f()'), ['String']);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/43114')
   test_plus_other_context_int_via_extension_explicit() async {
     await assertErrorsInCode('''
 class A {}
@@ -568,7 +565,6 @@
     );
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/43114')
   test_plus_other_int_via_extension_explicit() async {
     await assertNoErrorsInCode('''
 class A {}
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
index 4090683..87260dc 100644
--- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -131,9 +131,13 @@
 
     // The element and type arguments are available for the function type.
     var importFind = findElement.importFind('package:test/a.dart');
-    var elementF = importFind.functionTypeAlias('F');
-    expect(typeArgument.element, elementF.function);
-    expect(typeArgument.element.enclosingElement, elementF);
+    var alias = importFind.typeAlias('F');
+    expect(typeArgument.aliasElement, alias);
+    assertElementTypeStrings(typeArgument.aliasArguments, ['double']);
+
+    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
+    expect(typeArgument.element, alias.aliasedElement);
+    expect(typeArgument.element.enclosingElement, alias);
     assertElementTypeStrings(typeArgument.typeArguments, ['double']);
   }
 
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 d7f4445..8f9f2df 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -39,12 +39,12 @@
   final bool strictRawTypes;
 
   AnalysisOptionsFileConfig({
-    this.experiments,
-    this.implicitCasts,
-    this.implicitDynamic,
-    this.lints,
-    this.strictInference,
-    this.strictRawTypes,
+    this.experiments = const [],
+    this.implicitCasts = true,
+    this.implicitDynamic = true,
+    this.lints = const [],
+    this.strictInference = false,
+    this.strictRawTypes = false,
   });
 
   String toContent() {
@@ -136,6 +136,10 @@
   Map<String, String> _declaredVariables = {};
   AnalysisContextCollection _analysisContextCollection;
 
+  /// If not `null`, [resolveFile] will use the context that corresponds
+  /// to this path, instead of the given path.
+  String pathForContextSelection;
+
   List<MockSdkLibrary> get additionalMockSdkLibraries => [];
 
   List<String> get collectionIncludedPaths;
@@ -204,7 +208,7 @@
 
   @override
   Future<ResolvedUnitResult> resolveFile(String path) {
-    var analysisContext = contextFor(path);
+    var analysisContext = contextFor(pathForContextSelection ?? path);
     var session = analysisContext.currentSession;
     return session.getResolvedUnit(path);
   }
@@ -259,6 +263,9 @@
   @override
   List<String> get collectionIncludedPaths => [workspaceRootPath];
 
+  /// The path that is not in [workspaceRootPath], contains external packages.
+  String get packagesRootPath => '/packages';
+
   @override
   String get testFilePath => '$testPackageLibPath/test.dart';
 
diff --git a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
index a1bfdde..8e76124 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
@@ -164,7 +164,7 @@
   x<int>(1 + 2);
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
+      error(CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 21, 1),
     ]);
 
     assertFunctionExpressionInvocation(
diff --git a/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart
index b612327..08c8f37 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_type_alias_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/type.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -25,12 +26,15 @@
     FunctionType type = findElement.topVar('g').type;
     assertType(type, 'int Function()');
 
-    var typedefG = findElement.functionTypeAlias('G');
-    var functionG = typedefG.function;
+    var typedefG = findElement.typeAlias('G');
+    var functionG = typedefG.aliasedElement as GenericFunctionTypeElement;
 
+    expect(type.aliasElement, typedefG);
+    assertElementTypeStrings(type.aliasArguments, ['int']);
+
+    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
     expect(type.element, functionG);
     expect(type.element?.enclosingElement, typedefG);
-
     assertElementTypeStrings(type.typeArguments, ['int']);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
index 71c3ecb..1c625c7 100644
--- a/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/generic_type_alias_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/type.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -148,15 +149,18 @@
 
 typedef G<T> = T Function(double);
 ''');
-    FunctionType type = findElement.topVar('g').type;
+    var type = findElement.topVar('g').type as FunctionType;
     assertType(type, 'int Function(double)');
 
-    var typedefG = findElement.functionTypeAlias('G');
-    var functionG = typedefG.function;
+    var typedefG = findElement.typeAlias('G');
+    var functionG = typedefG.aliasedElement as GenericFunctionTypeElement;
 
+    expect(type.aliasElement, typedefG);
+    assertElementTypeStrings(type.aliasArguments, ['int']);
+
+    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
     expect(type.element, functionG);
     expect(type.element?.enclosingElement, typedefG);
-
     assertElementTypeStrings(type.typeArguments, ['int']);
   }
 
@@ -168,14 +172,14 @@
 
 typedef F<T extends A> = B Function<U extends B>(T a, U b);
 ''');
-    var f = findElement.functionTypeAlias('F');
+    var f = findElement.typeAlias('F');
     expect(f.typeParameters, hasLength(1));
 
     var t = f.typeParameters[0];
     expect(t.name, 'T');
     assertType(t.bound, 'A');
 
-    var ff = f.function;
+    var ff = f.aliasedElement as GenericFunctionTypeElement;
     expect(ff.typeParameters, hasLength(1));
 
     var u = ff.typeParameters[0];
diff --git a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
index fc67be62..7558067 100644
--- a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
@@ -29,6 +29,19 @@
     );
   }
 
+  test_invalid_inDefaultValue_nullAware2() async {
+    await assertInvalidTestCode(r'''
+typedef void F({a = b?[0]});
+''');
+
+    assertIndexExpression(
+      findNode.index('[0]'),
+      readElement: null,
+      writeElement: null,
+      type: 'dynamic',
+    );
+  }
+
   test_read() async {
     await assertNoErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index bdd82f2..bf3ee80 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -15,6 +15,9 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(MethodInvocationResolutionTest);
     defineReflectiveTests(MethodInvocationResolutionWithNullSafetyTest);
+    defineReflectiveTests(
+      MethodInvocationResolutionWithNonFunctionTypeAliasesTest,
+    );
   });
 }
 
@@ -1036,7 +1039,7 @@
           CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
           71,
           3),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 74, 3),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 75, 1),
     ]);
 
     assertMethodInvocation2(
@@ -1096,7 +1099,8 @@
 }
 ''', [
       if (typeToStringWithNullability)
-        error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 61, 5),
+        error(
+            CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 61, 5),
       error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 61, 5),
     ]);
 
@@ -1119,7 +1123,8 @@
 }
 ''', [
       if (typeToStringWithNullability)
-        error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 3),
+        error(
+            CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 23, 3),
       error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 23, 3),
     ]);
 
@@ -1142,7 +1147,8 @@
 }
 ''', [
       if (typeToStringWithNullability)
-        error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 26, 5),
+        error(
+            CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 26, 5),
       error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 26, 3),
     ]);
     assertMethodInvocation(
@@ -1161,7 +1167,8 @@
 }
 ''', [
       if (typeToStringWithNullability)
-        error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 22, 3),
+        error(
+            CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 22, 3),
       error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 22, 3),
     ]);
 
@@ -1341,7 +1348,7 @@
 }
 ''', [
       error(HintCode.UNUSED_IMPORT, 7, 11),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 65, 7),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 66, 5),
     ]);
 
     var import = findElement.importFind('dart:math');
@@ -1619,7 +1626,7 @@
     assertElement(foo.propertyName, import.class_('C').getGetter('foo'));
     assertType(foo.propertyName, 'double Function(int)');
 
-    PrefixedIdentifier target = foo.target;
+    var target = foo.target as PrefixedIdentifier;
     assertImportPrefix(target.prefix, import.prefix);
     assertClassRef(target.identifier, import.class_('C'));
   }
@@ -1648,7 +1655,7 @@
       'void Function(int)',
     );
 
-    PrefixedIdentifier target = invocation.target;
+    var target = invocation.target as PrefixedIdentifier;
     assertImportPrefix(target.prefix, import.prefix);
     assertClassRef(target.identifier, import.class_('C'));
   }
@@ -1715,6 +1722,20 @@
     );
   }
 
+  test_invalid_inDefaultValue_nullAware2() async {
+    await assertInvalidTestCode('''
+typedef void F({a = b?.foo()});
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('?.foo()'),
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+  }
+
   test_namedArgument() async {
     var question = typeToStringWithNullability ? '?' : '';
     await assertNoErrorsInCode('''
@@ -2342,6 +2363,60 @@
 }
 
 @reflectiveTest
+class MethodInvocationResolutionWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  test_hasReceiver_typeAlias_staticMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static void foo(int _) {}
+}
+
+typedef B = A;
+
+void f() {
+  B.foo(0);
+}
+''');
+
+    assertMethodInvocation(
+      findNode.methodInvocation('foo(0)'),
+      findElement.method('foo'),
+      'void Function(int)',
+    );
+
+    assertTypeAliasRef(
+      findNode.simple('B.foo'),
+      findElement.typeAlias('B'),
+    );
+  }
+
+  test_hasReceiver_typeAlias_staticMethod_generic() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  static void foo(int _) {}
+}
+
+typedef B<T> = A<T>;
+
+void f() {
+  B.foo(0);
+}
+''');
+
+    assertMethodInvocation(
+      findNode.methodInvocation('foo(0)'),
+      findElement.method('foo'),
+      'void Function(int)',
+    );
+
+    assertTypeAliasRef(
+      findNode.simple('B.foo'),
+      findElement.typeAlias('B'),
+    );
+  }
+}
+
+@reflectiveTest
 class MethodInvocationResolutionWithNullSafetyTest
     extends PubPackageResolutionTest
     with WithNullSafetyMixin, MethodInvocationResolutionTestCases {
@@ -2395,7 +2470,8 @@
   foo.call();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 26, 3),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          26, 3),
     ]);
 
     assertMethodInvocation2(
@@ -2446,7 +2522,8 @@
   a.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 46, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          46, 1),
     ]);
 
     assertMethodInvocation2(
@@ -2472,7 +2549,8 @@
   a.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 84, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          84, 1),
     ]);
 
     assertMethodInvocation2(
@@ -2539,7 +2617,8 @@
   a.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 29, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          29, 1),
     ]);
 
     assertMethodInvocation2(
@@ -2563,7 +2642,8 @@
   a.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 67, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          67, 1),
     ]);
 
     assertMethodInvocation2(
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 cb554a1b..cd08b22 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -196,10 +196,10 @@
 ''');
     _fillLibraries();
 
-    PropertyAccessorElement vg = findNode.simple('a;').staticElement;
+    var vg = findNode.simple('a;').staticElement as PropertyAccessorElement;
     var v = vg.variable as ConstVariableElement;
 
-    InstanceCreationExpression creation = v.constantInitializer;
+    InstanceCreationExpression /*!*/ creation = v.constantInitializer;
     return creation;
   }
 }
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 400c242..ba93f9f 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -179,14 +179,9 @@
       type: 'dynamic',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        postfix.operand,
-        readElement: findElement.typeParameter('T'),
-        writeElement: findElement.typeParameter('T'),
-        type: 'dynamic',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      postfix.operand,
+    );
   }
 
   test_inc_prefixedIdentifier_instance() async {
@@ -419,14 +414,9 @@
       type: 'int',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        postfix.operand,
-        readElement: findElement.getter('x'),
-        writeElement: findElement.setter('x'),
-        type: 'num',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      postfix.operand,
+    );
   }
 
   test_inc_simpleIdentifier_topGetter_topSetter() async {
@@ -454,14 +444,9 @@
       type: 'int',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        postfix.operand,
-        readElement: findElement.topGet('x'),
-        writeElement: findElement.topSet('x'),
-        type: 'num',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      postfix.operand,
+    );
   }
 
   test_inc_simpleIdentifier_topGetter_topSetter_fromClass() async {
@@ -491,14 +476,9 @@
       type: 'int',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        postfix.operand,
-        readElement: findElement.topGet('x'),
-        writeElement: findElement.topSet('x'),
-        type: 'num',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      postfix.operand,
+    );
   }
 }
 
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 671e345..b263cdf 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
@@ -491,14 +491,9 @@
       type: 'int',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        prefix.operand,
-        readElement: findElement.getter('x'),
-        writeElement: findElement.setter('x'),
-        type: 'num',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      prefix.operand,
+    );
   }
 
   test_plusPlus_simpleIdentifier_thisGetter_thisSetter() async {
@@ -526,14 +521,9 @@
       type: 'int',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        prefix.operand,
-        readElement: findElement.getter('x'),
-        writeElement: findElement.setter('x'),
-        type: 'num',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      prefix.operand,
+    );
   }
 
   test_plusPlus_simpleIdentifier_topGetter_topSetter() async {
@@ -561,14 +551,9 @@
       type: 'int',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        prefix.operand,
-        readElement: findElement.topGet('x'),
-        writeElement: findElement.topSet('x'),
-        type: 'num',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      prefix.operand,
+    );
   }
 
   test_plusPlus_simpleIdentifier_topGetter_topSetter_fromClass() async {
@@ -598,14 +583,9 @@
       type: 'int',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        prefix.operand,
-        readElement: findElement.topGet('x'),
-        writeElement: findElement.topSet('x'),
-        type: 'num',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      prefix.operand,
+    );
   }
 
   /// Verify that we get all necessary types when building the dependencies
@@ -668,7 +648,8 @@
   !a?.foo;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 55, 6),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          55, 6),
     ]);
 
     assertPrefixExpression(
@@ -692,7 +673,8 @@
   -a?.foo;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 51, 6),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          51, 6),
     ]);
 
     assertPrefixExpression(
@@ -766,7 +748,8 @@
   ~a?.foo;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 51, 6),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          51, 6),
     ]);
 
     assertPrefixExpression(
diff --git a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
index 50f5527..c3d86dd 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefixed_identifier_test.dart
@@ -12,6 +12,9 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(PrefixedIdentifierResolutionTest);
     defineReflectiveTests(PrefixedIdentifierResolutionWithNullSafetyTest);
+    defineReflectiveTests(
+      PrefixedIdentifierResolutionWithNonFunctionTypeAliasesTest,
+    );
   });
 }
 
@@ -91,15 +94,13 @@
 
     assertSimpleIdentifier(
       prefixed.prefix,
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'A',
     );
 
     assertSimpleIdentifier(
       prefixed.identifier,
-      readElement: findElement.getter('foo'),
-      writeElement: null,
+      element: findElement.getter('foo'),
       type: 'int',
     );
   }
@@ -124,15 +125,13 @@
 
     assertSimpleIdentifier(
       prefixed.prefix,
-      readElement: findElement.class_('A'),
-      writeElement: null,
+      element: findElement.class_('A'),
       type: null,
     );
 
     assertSimpleIdentifier(
       prefixed.identifier,
-      readElement: findElement.method('foo'),
-      writeElement: null,
+      element: findElement.method('foo'),
       type: 'void Function<U>(int, U)',
     );
   }
@@ -157,19 +156,49 @@
 
     assertSimpleIdentifier(
       prefixed.prefix,
-      readElement: findElement.class_('A'),
-      writeElement: null,
+      element: findElement.class_('A'),
       type: null,
     );
 
     assertSimpleIdentifier(
       prefixed.identifier,
-      readElement: findElement.method('foo'),
-      writeElement: null,
+      element: findElement.method('foo'),
       type: 'void Function(int)',
     );
   }
 
+  test_read_typedef_functionType() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef A = void Function();
+''');
+
+    await assertNoErrorsInCode('''
+import 'a.dart' as p;
+
+void f() {
+  p.A;
+}
+''');
+
+    var importFind = findElement.importFind('package:test/a.dart');
+    var A = importFind.typeAlias('A');
+
+    var prefixed = findNode.prefixed('p.A');
+    assertPrefixedIdentifier(
+      prefixed,
+      element: A,
+      type: 'Type',
+    );
+
+    assertImportPrefix(prefixed.prefix, importFind.prefix);
+
+    assertSimpleIdentifier(
+      prefixed.identifier,
+      element: A,
+      type: 'Type',
+    );
+  }
+
   test_readWrite_assignment() async {
     await assertNoErrorsInCode('''
 class A {
@@ -206,19 +235,13 @@
 
     assertSimpleIdentifier(
       prefixed.prefix,
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'A',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        prefixed.identifier,
-        readElement: null,
-        writeElement: findElement.setter('foo'),
-        type: 'int',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      prefixed.identifier,
+    );
   }
 
   test_write() async {
@@ -254,19 +277,80 @@
 
     assertSimpleIdentifier(
       prefixed.prefix,
-      readElement: findElement.parameter('a'),
-      writeElement: null,
+      element: findElement.parameter('a'),
       type: 'A',
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        prefixed.identifier,
-        readElement: null,
-        writeElement: findElement.setter('foo'),
-        type: 'int',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      prefixed.identifier,
+    );
+  }
+}
+
+@reflectiveTest
+class PrefixedIdentifierResolutionWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  test_hasReceiver_typeAlias_staticGetter() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static int get foo => 0;
+}
+
+typedef B = A;
+
+void f() {
+  B.foo;
+}
+''');
+
+    assertPrefixedIdentifier(
+      findNode.prefixed('B.foo'),
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertTypeAliasRef(
+      findNode.simple('B.foo'),
+      findElement.typeAlias('B'),
+    );
+
+    assertSimpleIdentifier(
+      findNode.simple('foo;'),
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+  }
+
+  test_read_typedef_interfaceType() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef A = List<int>;
+''');
+
+    await assertNoErrorsInCode('''
+import 'a.dart' as p;
+
+void f() {
+  p.A;
+}
+''');
+
+    var importFind = findElement.importFind('package:test/a.dart');
+    var A = importFind.typeAlias('A');
+
+    var prefixed = findNode.prefixed('p.A');
+    assertPrefixedIdentifier(
+      prefixed,
+      element: A,
+      type: 'Type',
+    );
+
+    assertImportPrefix(prefixed.prefix, importFind.prefix);
+
+    assertSimpleIdentifier(
+      prefixed.identifier,
+      element: A,
+      type: 'Type',
+    );
   }
 }
 
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 645d77a..63ab662 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -39,8 +39,7 @@
 
     assertSimpleIdentifier(
       propertyAccess.propertyName,
-      readElement: findElement.getter('foo'),
-      writeElement: null,
+      element: findElement.getter('foo'),
       type: 'int',
     );
   }
@@ -114,14 +113,11 @@
         element: findElement.setter('foo'),
         type: 'int',
       );
-
-      assertSimpleIdentifier(
-        propertyAccess.propertyName,
-        readElement: null,
-        writeElement: findElement.setter('foo'),
-        type: 'int',
-      );
     }
+
+    assertSimpleIdentifierAssignmentTarget(
+      propertyAccess.propertyName,
+    );
   }
 
   test_functionType_call_read() async {
@@ -158,8 +154,7 @@
 
     assertSimpleIdentifier(
       propertyAccess.propertyName,
-      readElement: findElement.getter('foo'),
-      writeElement: null,
+      element: findElement.getter('foo'),
       type: 'int',
     );
   }
@@ -228,14 +223,11 @@
         element: findElement.setter('foo'),
         type: 'int',
       );
-
-      assertSimpleIdentifier(
-        propertyAccess.propertyName,
-        readElement: null,
-        writeElement: findElement.setter('foo'),
-        type: 'int',
-      );
     }
+
+    assertSimpleIdentifierAssignmentTarget(
+      propertyAccess.propertyName,
+    );
   }
 
   test_invalid_inDefaultValue_nullAware() async {
@@ -250,6 +242,18 @@
     );
   }
 
+  test_invalid_inDefaultValue_nullAware2() async {
+    await assertInvalidTestCode('''
+typedef void F({a = b?.foo});
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('?.foo'),
+      element: null,
+      type: 'dynamic',
+    );
+  }
+
   test_invalid_inDefaultValue_nullAware_cascade() async {
     await assertInvalidTestCode('''
 void f({a = b?..foo}) {}
@@ -284,8 +288,7 @@
 
     assertSimpleIdentifier(
       propertyAccess.propertyName,
-      readElement: findElement.getter('foo'),
-      writeElement: null,
+      element: findElement.getter('foo'),
       type: 'int',
     );
   }
@@ -359,14 +362,11 @@
         element: findElement.setter('foo'),
         type: 'int',
       );
-
-      assertSimpleIdentifier(
-        propertyAccess.propertyName,
-        readElement: null,
-        writeElement: findElement.setter('foo'),
-        type: 'int',
-      );
     }
+
+    assertSimpleIdentifierAssignmentTarget(
+      propertyAccess.propertyName,
+    );
   }
 
   test_super_read() async {
@@ -395,8 +395,7 @@
 
     assertSimpleIdentifier(
       propertyAccess.propertyName,
-      readElement: findElement.getter('foo'),
-      writeElement: null,
+      element: findElement.getter('foo'),
       type: 'int',
     );
   }
@@ -441,14 +440,9 @@
       propertyAccess.target,
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        propertyAccess.propertyName,
-        readElement: findElement.getter('foo'),
-        writeElement: findElement.setter('foo'),
-        type: 'int',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      propertyAccess.propertyName,
+    );
   }
 
   test_super_write() async {
@@ -488,14 +482,9 @@
       propertyAccess.target,
     );
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        propertyAccess.propertyName,
-        readElement: null,
-        writeElement: findElement.setter('foo'),
-        type: 'int',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      propertyAccess.propertyName,
+    );
   }
 
   test_targetTypeParameter_dynamicBounded() async {
@@ -516,8 +505,7 @@
 
     assertSimpleIdentifier(
       propertyAccess.propertyName,
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
   }
@@ -532,7 +520,8 @@
 ''');
     assertErrorsInResult(expectedErrorsByNullability(
       nullable: [
-        error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 33, 3),
+        error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+            33, 3),
       ],
       legacy: [
         error(CompileTimeErrorCode.UNDEFINED_GETTER, 37, 3),
@@ -548,8 +537,7 @@
 
     assertSimpleIdentifier(
       propertyAccess.propertyName,
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
   }
@@ -702,8 +690,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('foo?'),
-      readElement: findElement.topGet('foo'),
-      writeElement: null,
+      element: findElement.topGet('foo'),
       type: 'A?',
     );
 
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 5e7e81c..458981d 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -343,7 +343,14 @@
     @required FunctionTypeAliasElement element,
     @required List<String> typeArguments,
   }) {
-    assertElement2(type.element, declaration: element.function);
+    assertElement2(type.aliasElement, declaration: element);
+    assertElementTypeStrings(type.aliasArguments, typeArguments);
+
+    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
+    assertElement2(
+      type.element,
+      declaration: element.aliasedElement as GenericFunctionTypeElement,
+    );
     assertElementTypeStrings(type.typeArguments, typeArguments);
   }
 
@@ -400,12 +407,16 @@
     }
   }
 
-  void assertInstanceCreation(InstanceCreationExpression creation,
-      ClassElement expectedClassElement, String expectedType,
-      {String constructorName,
-      bool expectedConstructorMember = false,
-      Map<String, String> expectedSubstitution,
-      PrefixElement expectedPrefix}) {
+  void assertInstanceCreation(
+    InstanceCreationExpression creation,
+    ClassElement expectedClassElement,
+    String expectedType, {
+    String constructorName,
+    bool expectedConstructorMember = false,
+    Map<String, String> expectedSubstitution,
+    PrefixElement expectedPrefix,
+    Element expectedTypeNameElement,
+  }) {
     String expectedClassName = expectedClassElement.name;
 
     ConstructorElement expectedConstructorElement;
@@ -444,7 +455,8 @@
     assertType(creation, expectedType);
 
     var typeName = creation.constructorName.type;
-    assertTypeName(typeName, expectedClassElement, expectedType,
+    expectedTypeNameElement ??= expectedClassElement;
+    assertTypeName(typeName, expectedTypeNameElement, expectedType,
         expectedPrefix: expectedPrefix);
   }
 
@@ -654,53 +666,22 @@
 
   void assertSimpleIdentifier(
     SimpleIdentifier node, {
-    @required Object readElement,
-    @required Object writeElement,
+    @required Object element,
     @required String type,
   }) {
     var isRead = node.inGetterContext();
-    var isWrite = node.inSetterContext();
-    if (isRead && isWrite) {
-      // TODO(scheglov) enable this
-//      assertElement(node.auxiliaryElements?.staticElement, readElement);
-      assertElement(node.staticElement, writeElement);
-    } else if (isRead) {
-      assertElement(node.staticElement, readElement);
-    } else {
-      expect(isWrite, isTrue);
-      assertElement(node.staticElement, writeElement);
-    }
+    expect(isRead, isTrue);
 
-    if (isRead) {
-      assertType(node, type);
-    } else {
-      // TODO(scheglov) enforce this
-//      expect(type, isNull);
-//      assertTypeNull(node);
-    }
+    assertElement(node.staticElement, element);
+    assertType(node, type);
   }
 
   /// TODO(scheglov) https://github.com/dart-lang/sdk/issues/43608
-  /// TODO(scheglov) rename this method
-  void assertSimpleIdentifierAssignmentTarget(
-    SimpleIdentifier node, {
-    @required Object readElement,
-    @required Object writeElement,
-    @required String type,
-  }) {
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        node,
-        readElement: readElement,
-        writeElement: writeElement,
-        type: type,
-      );
-    } else {
-      // TODO(scheglov) Enforce maybe?
-      // Currently VariableResolverVisitor sets it.
-      // expect(node.staticElement, isNull);
-      expect(node.staticType, isNull);
-    }
+  void assertSimpleIdentifierAssignmentTarget(SimpleIdentifier node) {
+    // TODO(scheglov) Enforce maybe?
+    // Currently VariableResolverVisitor sets it.
+    // expect(node.staticElement, isNull);
+    expect(node.staticType, isNull);
   }
 
   void assertSubstitution(
@@ -755,6 +736,15 @@
     }
   }
 
+  /// Assert that the given [identifier] is a reference to a type alias, in the
+  /// form that is not a separate expression, e.g. in a static method
+  /// invocation like `C.staticMethod()`, or a type annotation `C c = null`.
+  void assertTypeAliasRef(
+      SimpleIdentifier identifier, TypeAliasElement expected) {
+    assertElement(identifier, expected);
+    assertTypeNull(identifier);
+  }
+
   void assertTypeArgumentTypes(
     InvocationExpression node,
     List<String> expected,
diff --git a/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart b/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
index 88deb9e..9d01ef1 100644
--- a/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/simple_identifier_test.dart
@@ -27,8 +27,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('dynamic;'),
-      readElement: dynamicElement,
-      writeElement: null,
+      element: dynamicElement,
       type: 'Type',
     );
   }
@@ -46,8 +45,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('dynamic;'),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
   }
@@ -61,8 +59,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('dynamic;'),
-      readElement: dynamicElement,
-      writeElement: null,
+      element: dynamicElement,
       type: 'Type',
     );
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_name_test.dart b/pkg/analyzer/test/src/dart/resolution/type_name_test.dart
index a58eac5..91aa242 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_name_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_name_test.dart
@@ -143,7 +143,7 @@
 
     assertTypeName(
       findNode.typeName('F a'),
-      findElement.functionTypeAlias('F'),
+      findElement.typeAlias('F'),
       typeStr('int Function()', 'int* Function()*'),
     );
   }
@@ -157,7 +157,7 @@
 
     assertTypeName(
       findNode.typeName('F a'),
-      findElement.functionTypeAlias('F'),
+      findElement.typeAlias('F'),
       typeStr('num Function()', 'num* Function()*'),
     );
   }
@@ -171,7 +171,7 @@
 
     assertTypeName(
       findNode.typeName('F a'),
-      findElement.functionTypeAlias('F'),
+      findElement.typeAlias('F'),
       typeStr('dynamic Function()', 'dynamic Function()*'),
     );
   }
@@ -185,7 +185,7 @@
 
     assertTypeName(
       findNode.typeName('F<int> a'),
-      findElement.functionTypeAlias('F'),
+      findElement.typeAlias('F'),
       typeStr('int Function()', 'int* Function()*'),
     );
   }
@@ -291,41 +291,58 @@
 @reflectiveTest
 class TypeNameResolutionWithNonFunctionTypeAliasesTest
     extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
-  test_typeAlias_asParameter_Never_none() async {
+  test_typeAlias_asInstanceCreation_explicitNew_typeArguments_interfaceType_none() async {
     await assertNoErrorsInCode(r'''
-typedef X = Never;
-void f(X a, X? b) {}
+class A<T> {}
+
+typedef X<T> = A<T>;
+
+void f() {
+  new X<int>();
+}
 ''');
 
     assertTypeName(
-      findNode.typeName('X a'),
+      findNode.typeName('X<int>()'),
       findElement.typeAlias('X'),
-      'Never',
-    );
-
-    assertTypeName(
-      findNode.typeName('X? b'),
-      findElement.typeAlias('X'),
-      'Never?',
+      'A<int>',
     );
   }
 
-  test_typeAlias_asParameter_Never_question() async {
+  @FailingTest(reason: 'We attempt to do type inference on A')
+  test_typeAlias_asInstanceCreation_implicitNew_toBounds_noTypeParameters_interfaceType_none() async {
     await assertNoErrorsInCode(r'''
-typedef X = Never?;
-void f(X a, X? b) {}
+class A<T> {}
+
+typedef X = A<int>;
+
+void f() {
+  X();
+}
 ''');
 
     assertTypeName(
-      findNode.typeName('X a'),
+      findNode.typeName('X()'),
       findElement.typeAlias('X'),
-      'Never?',
+      'A<int>',
     );
+  }
+
+  test_typeAlias_asInstanceCreation_implicitNew_typeArguments_interfaceType_none() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {}
+
+typedef X<T> = A<T>;
+
+void f() {
+  X<int>();
+}
+''');
 
     assertTypeName(
-      findNode.typeName('X? b'),
+      findNode.typeName('X<int>()'),
       findElement.typeAlias('X'),
-      'Never?',
+      'A<int>',
     );
   }
 
@@ -348,6 +365,23 @@
     );
   }
 
+  test_typeAlias_asParameterType_interfaceType_none_inLegacy() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef X<T> = Map<int, T>;
+''');
+    await assertNoErrorsInCode(r'''
+// @dart = 2.9
+import 'a.dart';
+void f(X<String> a) {}
+''');
+
+    assertTypeName(
+      findNode.typeName('X<String>'),
+      findElement.importFind('package:test/a.dart').typeAlias('X'),
+      'Map<int*, String*>*',
+    );
+  }
+
   test_typeAlias_asParameterType_interfaceType_question() async {
     await assertNoErrorsInCode(r'''
 typedef X<T> = List<T?>;
@@ -367,6 +401,91 @@
     );
   }
 
+  test_typeAlias_asParameterType_interfaceType_question_inLegacy() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef X<T> = List<T?>;
+''');
+    await assertNoErrorsInCode(r'''
+// @dart = 2.9
+import 'a.dart';
+void f(X<int> a) {}
+''');
+
+    assertTypeName(
+      findNode.typeName('X<int>'),
+      findElement.importFind('package:test/a.dart').typeAlias('X'),
+      'List<int*>*',
+    );
+  }
+
+  test_typeAlias_asParameterType_Never_none() async {
+    await assertNoErrorsInCode(r'''
+typedef X = Never;
+void f(X a, X? b) {}
+''');
+
+    assertTypeName(
+      findNode.typeName('X a'),
+      findElement.typeAlias('X'),
+      'Never',
+    );
+
+    assertTypeName(
+      findNode.typeName('X? b'),
+      findElement.typeAlias('X'),
+      'Never?',
+    );
+  }
+
+  test_typeAlias_asParameterType_Never_none_inLegacy() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+typedef X = Never;
+''');
+    await assertNoErrorsInCode(r'''
+// @dart = 2.9
+import 'a.dart';
+void f(X a) {}
+''');
+
+    assertTypeName(
+      findNode.typeName('X a'),
+      findElement.importFind('package:test/a.dart').typeAlias('X'),
+      'Null*',
+    );
+  }
+
+  test_typeAlias_asParameterType_Never_question() async {
+    await assertNoErrorsInCode(r'''
+typedef X = Never?;
+void f(X a, X? b) {}
+''');
+
+    assertTypeName(
+      findNode.typeName('X a'),
+      findElement.typeAlias('X'),
+      'Never?',
+    );
+
+    assertTypeName(
+      findNode.typeName('X? b'),
+      findElement.typeAlias('X'),
+      'Never?',
+    );
+  }
+
+  test_typeAlias_asParameterType_question() async {
+    await assertNoErrorsInCode(r'''
+typedef X<T> = T?;
+void f(X<int> a) {}
+''');
+
+    assertTypeName(
+      findNode.typeName('X<int>'),
+      findElement.typeAlias('X'),
+      'int?',
+    );
+  }
+
   test_typeAlias_asReturnType_interfaceType() async {
     await assertNoErrorsInCode(r'''
 typedef X<T> = Map<int, T>;
@@ -489,7 +608,7 @@
 f(F a) {}
 ''');
 
-    var element = import_a.functionTypeAlias('F');
+    var element = import_a.typeAlias('F');
 
     var typeName = findNode.typeName('F a');
     assertTypeName(typeName, element, 'int* Function(bool*)*');
@@ -513,7 +632,7 @@
 f(F a) {}
 ''');
 
-    var element = import_a.functionTypeAlias('F');
+    var element = import_a.typeAlias('F');
 
     var typeName = findNode.typeName('F a');
     assertTypeName(typeName, element, 'dynamic Function(bool*)*');
@@ -537,7 +656,7 @@
 f(F a) {}
 ''');
 
-    var element = import_a.functionTypeAlias('F');
+    var element = import_a.typeAlias('F');
 
     var typeName = findNode.typeName('F a');
     assertTypeName(typeName, element, 'num* Function(bool*)*');
@@ -561,7 +680,7 @@
 f(F<int> a) {}
 ''');
 
-    var element = import_a.functionTypeAlias('F');
+    var element = import_a.typeAlias('F');
 
     var typeName = findNode.typeName('F<int> a');
     assertTypeName(typeName, element, 'int* Function(bool*)*');
@@ -673,7 +792,7 @@
 
     assertTypeName(
       findNode.typeName('F a'),
-      import_a.functionTypeAlias('F'),
+      import_a.typeAlias('F'),
       'int* Function()',
     );
   }
@@ -694,7 +813,7 @@
 
     assertTypeName(
       findNode.typeName('F a'),
-      import_a.functionTypeAlias('F'),
+      import_a.typeAlias('F'),
       'num* Function()',
     );
   }
@@ -715,7 +834,7 @@
 
     assertTypeName(
       findNode.typeName('F a'),
-      import_a.functionTypeAlias('F'),
+      import_a.typeAlias('F'),
       'dynamic Function()',
     );
   }
@@ -736,7 +855,7 @@
 
     assertTypeName(
       findNode.typeName('F<int> a'),
-      import_a.functionTypeAlias('F'),
+      import_a.typeAlias('F'),
       'int* Function()',
     );
   }
diff --git a/pkg/analyzer/test/src/diagnostics/annotation_with_non_class_test.dart b/pkg/analyzer/test/src/diagnostics/annotation_with_non_class_test.dart
deleted file mode 100644
index c98e73c..0000000
--- a/pkg/analyzer/test/src/diagnostics/annotation_with_non_class_test.dart
+++ /dev/null
@@ -1,53 +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.
-
-import 'package:analyzer/src/error/codes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/context_collection_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(AnnotationWithNonClassTest);
-  });
-}
-
-@reflectiveTest
-class AnnotationWithNonClassTest extends PubPackageResolutionTest {
-  test_instance() async {
-    await assertErrorsInCode('''
-class Property {
-  final int value;
-  const Property(this.value);
-}
-
-const Property property = const Property(42);
-
-@property(123)
-main() {
-}
-''', [
-      error(CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS, 117, 8),
-    ]);
-  }
-
-  test_prefixed() async {
-    newFile('$testPackageLibPath/annotations.dart', content: r'''
-class Property {
-  final int value;
-  const Property(this.value);
-}
-
-const Property property = const Property(42);
-''');
-    await assertErrorsInCode('''
-import 'annotations.dart' as pref;
-@pref.property(123)
-main() {
-}
-''', [
-      error(CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS, 36, 13),
-    ]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart
index e72359b..3266124 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart
@@ -193,6 +193,21 @@
     ]);
   }
 
+  test_topLevelVariable_assignment_functionExpression() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+@doNotStore
+String _v = '';
+
+var c = ()=> _v;
+
+String v = c();
+''', [
+      error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 76, 2),
+    ]);
+  }
+
   test_topLevelVariable_assignment_getter() async {
     await assertErrorsInCode('''
 import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
index cdba72f..a8133c3 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
@@ -14,7 +14,8 @@
 }
 
 @reflectiveTest
-class AssignmentToTypeTest extends PubPackageResolutionTest {
+class AssignmentToTypeTest extends PubPackageResolutionTest
+    with WithNonFunctionTypeAliasesMixin {
   test_class() async {
     await assertErrorsInCode('''
 class C {}
@@ -47,7 +48,7 @@
     ]);
   }
 
-  test_typedef() async {
+  test_typedef_functionType() async {
     await assertErrorsInCode('''
 typedef void F();
 main() {
@@ -58,6 +59,18 @@
     ]);
   }
 
+  test_typedef_interfaceType() async {
+    await assertErrorsInCode('''
+typedef F = List<int>;
+
+void f() {
+  F = null;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 37, 1),
+    ]);
+  }
+
   test_typeParameter() async {
     await assertErrorsInCode('''
 class C<T> {
diff --git a/pkg/analyzer/test/src/diagnostics/const_initialized_with_non_constant_value_test.dart b/pkg/analyzer/test/src/diagnostics/const_initialized_with_non_constant_value_test.dart
index 8e28cd4..79c1c58 100644
--- a/pkg/analyzer/test/src/diagnostics/const_initialized_with_non_constant_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_initialized_with_non_constant_value_test.dart
@@ -10,6 +10,9 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConstInitializedWithNonConstantValueTest);
+    defineReflectiveTests(
+      ConstInitializedWithNonConstantValueWithNonFunctionTypeAliasesTest,
+    );
   });
 }
 
@@ -103,3 +106,20 @@
     ]);
   }
 }
+
+@reflectiveTest
+class ConstInitializedWithNonConstantValueWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  test_typeLiteral_interfaceType() async {
+    await assertNoErrorsInCode(r'''
+const a = int;
+''');
+  }
+
+  test_typeLiteral_typeAlias_interfaceType() async {
+    await assertNoErrorsInCode(r'''
+typedef A = int;
+const a = A;
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/could_not_infer_test.dart b/pkg/analyzer/test/src/diagnostics/could_not_infer_test.dart
index 951fcbd..2f7f2c3 100644
--- a/pkg/analyzer/test/src/diagnostics/could_not_infer_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/could_not_infer_test.dart
@@ -33,8 +33,9 @@
 }
 ''', [
       error(CompileTimeErrorCode.COULD_NOT_INFER, 154, 3),
-      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 154, 1),
       error(CompileTimeErrorCode.COULD_NOT_INFER, 154, 3),
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 154, 1),
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 154, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
index a2d3d19..186c7a6 100644
--- a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
@@ -398,14 +398,19 @@
   }
 
   void _writeWorkspacePackagesFile(Map<String, String> nameToLibPath) {
-    var builder = StringBuffer();
-    for (var entry in nameToLibPath.entries) {
-      builder.writeln('${entry.key}:${toUriStr(entry.value)}');
-    }
+    var packages = nameToLibPath.entries.map((entry) => '''{
+    "languageVersion": "2.2",
+    "name": "${entry.key}",
+    "packageUri": ".",
+    "rootUri": "${toUriStr(entry.value)}"
+  }''');
 
     var buildDir = 'out/debug-x87_128';
     var genPath = '$workspaceRootPath/$buildDir/dartlang/gen';
-    newFile('$genPath/foo.packages', content: builder.toString());
+    newFile('$genPath/foo_package_config.json', content: '''{
+  "configVersion": 2,
+  "packages": [ ${packages.join(', ')} ]
+}''');
   }
 }
 
diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
index 1891285..a69ca06 100644
--- a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart
@@ -936,7 +936,8 @@
 }
 
 @reflectiveTest
-class DuplicateDefinitionTest extends PubPackageResolutionTest {
+class DuplicateDefinitionTest extends PubPackageResolutionTest
+    with WithNonFunctionTypeAliasesMixin {
   test_catch() async {
     await assertErrorsInCode(r'''
 main() {
@@ -979,16 +980,16 @@
 
   test_locals_block_if() async {
     await assertErrorsInCode(r'''
-main(int p) {
+void f(int p) {
   if (p != 0) {
     var a;
     var a;
   }
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 38, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 49, 1),
-      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 49, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 40, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 51, 1),
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 51, 1),
     ]);
   }
 
@@ -1214,4 +1215,13 @@
         error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 27, 1),
       ]);
   }
+
+  test_unitMembers_typedef_interfaceType() async {
+    await assertErrorsInCode('''
+typedef A = List<int>;
+typedef A = List<int>;
+''', [
+      error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 31, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/extra_positional_arguments_test.dart b/pkg/analyzer/test/src/diagnostics/extra_positional_arguments_test.dart
index 8bb30fb..6e73263 100644
--- a/pkg/analyzer/test/src/diagnostics/extra_positional_arguments_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/extra_positional_arguments_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/context_collection_resolution.dart';
@@ -26,8 +27,8 @@
   const A(0);
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 50,
-          3),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 51,
+          1),
     ]);
   }
 
@@ -40,8 +41,8 @@
   const B() : super(0);
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 71,
-          3),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 72,
+          1),
     ]);
   }
 
@@ -51,8 +52,8 @@
   (int x, {int y}) {} (0, 1);
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 31,
-          6),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 35,
+          1),
     ]);
   }
 
@@ -63,8 +64,23 @@
   f(0, 1, '2');
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 25,
-          11),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 26,
+          1),
+    ]);
+  }
+
+  test_partiallyTypedName() async {
+    await assertErrorsInCode(r'''
+f({int xx, int yy, int zz}) {}
+
+main() {
+  f(xx: 1, yy: 2, z);
+}
+''', [
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED, 59,
+          1),
+      error(ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT, 59, 1),
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 59, 1),
     ]);
   }
 }
@@ -80,7 +96,7 @@
   const A(0);
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 43, 3),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 44, 1),
     ]);
   }
 
@@ -93,7 +109,7 @@
   const B() : super(0);
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 64, 3),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 65, 1),
     ]);
   }
 
@@ -103,7 +119,7 @@
   (int x) {} (0, 1);
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 22, 6),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 26, 1),
     ]);
   }
 
@@ -114,7 +130,7 @@
   f(0, 1, '2');
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 19, 11),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 20, 1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/field_in_struct_with_initializer_test.dart b/pkg/analyzer/test/src/diagnostics/field_in_struct_with_initializer_test.dart
index da75f22..9c908b5 100644
--- a/pkg/analyzer/test/src/diagnostics/field_in_struct_with_initializer_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_in_struct_with_initializer_test.dart
@@ -39,6 +39,7 @@
     await assertNoErrorsInCode(r'''
 import 'dart:ffi';
 class C extends Struct {
+  Pointer p;
   static String str = '';
 }
 ''');
diff --git a/pkg/analyzer/test/src/diagnostics/generic_struct_subclass_test.dart b/pkg/analyzer/test/src/diagnostics/generic_struct_subclass_test.dart
index 8b4aef4..710a812 100644
--- a/pkg/analyzer/test/src/diagnostics/generic_struct_subclass_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/generic_struct_subclass_test.dart
@@ -18,7 +18,9 @@
   test_genericStruct() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
-class S<T> extends Struct {}
+class S<T> extends Struct {
+  Pointer notEmpty;
+}
 ''', [
       error(FfiCode.GENERIC_STRUCT_SUBCLASS, 25, 1),
     ]);
@@ -27,7 +29,9 @@
   test_validStruct() async {
     await assertNoErrorsInCode(r'''
 import 'dart:ffi';
-class S extends Struct {}
+class S extends Struct {
+  Pointer notEmpty;
+}
 ''');
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/instantiate_type_alias_expands_to_type_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/instantiate_type_alias_expands_to_type_parameter_test.dart
new file mode 100644
index 0000000..0cb16f19
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/instantiate_type_alias_expands_to_type_parameter_test.dart
@@ -0,0 +1,114 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InstantiateTypeAliasExpandsToTypeParameterTest);
+  });
+}
+
+@reflectiveTest
+class InstantiateTypeAliasExpandsToTypeParameterTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  CompileTimeErrorCode get _errorCode =>
+      CompileTimeErrorCode.INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER;
+
+  test_const_generic_noArguments_unnamed_typeParameter() async {
+    await assertErrorsInCode(r'''
+typedef A<T> = T;
+
+void f() {
+  const A();
+}
+''', [
+      error(_errorCode, 38, 1),
+    ]);
+  }
+
+  test_const_notGeneric_unnamed_class() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  const A();
+}
+
+typedef X = A;
+
+void f() {
+  const X();
+}
+''');
+  }
+
+  test_new_generic_noArguments_unnamed_typeParameter() async {
+    await assertErrorsInCode(r'''
+typedef A<T> = T;
+
+void f() {
+  new A();
+}
+''', [
+      error(_errorCode, 36, 1),
+    ]);
+  }
+
+  test_new_generic_withArgument_named_typeParameter() async {
+    await assertErrorsInCode(r'''
+class A {
+  A.named();
+}
+
+typedef B<T> = T;
+
+void f() {
+  new B<A>.named();
+}
+''', [
+      error(_errorCode, 62, 1),
+    ]);
+  }
+
+  test_new_generic_withArgument_unnamed_typeParameter() async {
+    await assertErrorsInCode(r'''
+class A {}
+
+typedef B<T> = T;
+
+void f() {
+  new B<A>();
+}
+''', [
+      error(_errorCode, 48, 1),
+    ]);
+  }
+
+  test_new_notGeneric_unnamed_class() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+
+typedef X = A;
+
+void f() {
+  new X();
+}
+''');
+  }
+
+  test_new_notGeneric_unnamed_typeParameter2() async {
+    await assertErrorsInCode(r'''
+typedef A<T> = T;
+typedef B<T> = A<T>;
+
+void f() {
+  new B();
+}
+''', [
+      error(_errorCode, 57, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_annotation_getter_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_annotation_getter_test.dart
deleted file mode 100644
index 9963bea..0000000
--- a/pkg/analyzer/test/src/diagnostics/invalid_annotation_getter_test.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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:analyzer/src/error/codes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/context_collection_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(InvalidAnnotationGetterTest);
-  });
-}
-
-@reflectiveTest
-class InvalidAnnotationGetterTest extends PubPackageResolutionTest {
-  test_getter() async {
-    await assertErrorsInCode(r'''
-get V => 0;
-@V
-main() {
-}
-''', [
-      error(CompileTimeErrorCode.INVALID_ANNOTATION_GETTER, 12, 2),
-    ]);
-  }
-
-  test_importWithPrefix_getter() async {
-    newFile('$testPackageLibPath/lib.dart', content: r'''
-library lib;
-get V => 0;
-''');
-    await assertErrorsInCode(r'''
-import 'lib.dart' as p;
-@p.V
-main() {
-}
-''', [
-      error(CompileTimeErrorCode.INVALID_ANNOTATION_GETTER, 24, 4),
-    ]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_annotation_test.dart
index 1ad964c..1795ae3 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_annotation_test.dart
@@ -15,6 +15,32 @@
 
 @reflectiveTest
 class InvalidAnnotationTest extends PubPackageResolutionTest {
+  test_getter() async {
+    await assertErrorsInCode(r'''
+get V => 0;
+@V
+main() {
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 12, 2),
+    ]);
+  }
+
+  test_getter_importWithPrefix() async {
+    newFile('$testPackageLibPath/lib.dart', content: r'''
+library lib;
+get V => 0;
+''');
+    await assertErrorsInCode(r'''
+import 'lib.dart' as p;
+@p.V
+main() {
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 24, 4),
+    ]);
+  }
+
   test_importWithPrefix_notConstantVariable() async {
     newFile('$testPackageLibPath/lib.dart', content: r'''
 library lib;
@@ -45,6 +71,42 @@
     ]);
   }
 
+  test_notClass_importWithPrefix() async {
+    newFile('$testPackageLibPath/annotations.dart', content: r'''
+class Property {
+  final int value;
+  const Property(this.value);
+}
+
+const Property property = const Property(42);
+''');
+    await assertErrorsInCode('''
+import 'annotations.dart' as pref;
+@pref.property(123)
+main() {
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 35, 19),
+    ]);
+  }
+
+  test_notClass_instance() async {
+    await assertErrorsInCode('''
+class Property {
+  final int value;
+  const Property(this.value);
+}
+
+const Property property = const Property(42);
+
+@property(123)
+main() {
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_ANNOTATION, 116, 14),
+    ]);
+  }
+
   test_notConstantVariable() async {
     await assertErrorsInCode(r'''
 final V = 0;
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_field_type_in_struct_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_field_type_in_struct_test.dart
index 06cd7f3..6fec555 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_field_type_in_struct_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_field_type_in_struct_test.dart
@@ -15,11 +15,14 @@
 
 @reflectiveTest
 class InvalidFieldTypeInStructTest extends PubPackageResolutionTest {
+  // TODO(https://dartbug.com/44677): Remove Pointer notEmpty field.
   test_instance_invalid() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
 class C extends Struct {
   String str;
+
+  Pointer notEmpty;
 }
 ''', [
       error(FfiCode.INVALID_FIELD_TYPE_IN_STRUCT, 46, 6),
@@ -35,11 +38,14 @@
 ''');
   }
 
+  // TODO(https://dartbug.com/44677): Remove Pointer notEmpty field.
   test_static() async {
     await assertNoErrorsInCode(r'''
 import 'dart:ffi';
 class C extends Struct {
   static String str;
+
+  Pointer notEmpty;
 }
 ''');
   }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart
new file mode 100644
index 0000000..dba5d65
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_implementation_override_test.dart
@@ -0,0 +1,115 @@
+// 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 '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidImplementationOverrideTest);
+    defineReflectiveTests(InvalidImplementationOverrideWithNullSafetyTest);
+  });
+}
+
+@reflectiveTest
+class InvalidImplementationOverrideTest extends PubPackageResolutionTest {
+  test_getter_abstractOverridesConcrete() async {
+    await assertErrorsInCode('''
+class A {
+  num get g => 7;
+}
+class B	extends A {
+  int get g;
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 36, 1),
+    ]);
+  }
+
+  test_method_abstractOverridesConcrete() async {
+    await assertErrorsInCode('''
+class A	{
+  int add(int a, int b) => a + b;
+}
+class B	extends A {
+  int add();
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 52, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 3),
+    ]);
+  }
+
+  test_method_abstractOverridesConcrete_expandedParameterType() async {
+    await assertErrorsInCode('''
+class A {
+  int add(int a) => a;
+}
+class B	extends A {
+  int add(num a);
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 41, 1),
+    ]);
+  }
+
+  test_method_abstractOverridesConcrete_expandedParameterType_covariant() async {
+    await assertNoErrorsInCode('''
+class A {
+  int add(covariant int a) => a;
+}
+class B	extends A {
+  int add(num a);
+}
+''');
+  }
+
+  test_method_abstractOverridesConcrete_withOptional() async {
+    await assertErrorsInCode('''
+class A {
+  int add() => 7;
+}
+class B	extends A {
+  int add([int a = 0, int b = 0]);
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 36, 1),
+    ]);
+  }
+
+  test_method_abstractOverridesConcreteInMixin() async {
+    await assertErrorsInCode('''
+mixin M {
+  int add(int a, int b) => a + b;
+}
+class A with M {
+  int add();
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 52, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 69, 3),
+    ]);
+  }
+
+  test_method_abstractOverridesConcreteViaMixin() async {
+    await assertErrorsInCode('''
+class A {
+  int add(int a, int b) => a + b;
+}
+mixin M {
+  int add();
+}
+class B	extends A with M {}
+''', [
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 77, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1),
+    ]);
+  }
+}
+
+@reflectiveTest
+class InvalidImplementationOverrideWithNullSafetyTest
+    extends PubPackageResolutionTest with WithNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
index 110480c..2c6d4f1 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
@@ -20,7 +20,8 @@
 class InvalidOverrideDifferentDefaultValuesNamedTest
     extends PubPackageResolutionTest {
   test_abstract_different_base_value() async {
-    await assertErrorsInCode(r'''
+    await assertErrorsInCode(
+      r'''
 abstract class A {
   void foo({x = 0}) {}
 }
@@ -28,10 +29,12 @@
 abstract class B extends A {
   void foo({x = 1});
 }
-''', [
-      error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
-          86, 5),
-    ]);
+''',
+      expectedErrorsByNullability(nullable: [], legacy: [
+        error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+            86, 5),
+      ]),
+    );
   }
 
   test_abstract_noDefault_base_noDefault() async {
@@ -132,16 +135,19 @@
   }
 
   test_concrete_different() async {
-    await assertErrorsInCode(r'''
+    await assertErrorsInCode(
+      r'''
 class A {
   void foo({x = 0}) {}
 }
 class B extends A {
   void foo({x = 1}) {}
-}''', [
-      error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
-          67, 5),
-    ]);
+}''',
+      expectedErrorsByNullability(nullable: [], legacy: [
+        error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+            67, 5),
+      ]),
+    );
   }
 
   test_concrete_equal() async {
@@ -282,17 +288,20 @@
     // If the base class provided an explicit value for a default parameter,
     // then it is a static warning for the derived class to provide a different
     // value, even if implicitly.
-    await assertErrorsInCode(r'''
+    await assertErrorsInCode(
+      r'''
 class A {
   void foo({x: 1}) {}
 }
 class B extends A {
   void foo({x}) {}
 }
-''', [
-      error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
-          66, 1),
-    ]);
+''',
+      expectedErrorsByNullability(nullable: [], legacy: [
+        error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+            66, 1),
+      ]),
+    );
   }
 }
 
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
index 50128c9..c25b8e0 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
@@ -20,7 +20,8 @@
 class InvalidOverrideDifferentDefaultValuesPositionalTest
     extends PubPackageResolutionTest {
   test_abstract_different_base_value() async {
-    await assertErrorsInCode(r'''
+    await assertErrorsInCode(
+      r'''
 abstract class A {
   void foo([x = 0]) {}
 }
@@ -28,13 +29,15 @@
 abstract class B extends A {
   void foo([x = 1]);
 }
-''', [
-      error(
-          StaticWarningCode
-              .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
-          86,
-          5),
-    ]);
+''',
+      expectedErrorsByNullability(nullable: [], legacy: [
+        error(
+            StaticWarningCode
+                .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+            86,
+            5),
+      ]),
+    );
   }
 
   test_abstract_noDefault_base_noDefault() async {
@@ -140,20 +143,23 @@
   }
 
   test_concrete_different() async {
-    await assertErrorsInCode(r'''
+    await assertErrorsInCode(
+      r'''
 class A {
   void foo([x = 0]) {}
 }
 class B extends A {
   void foo([x = 1]) {}
 }
-''', [
-      error(
-          StaticWarningCode
-              .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
-          67,
-          5),
-    ]);
+''',
+      expectedErrorsByNullability(nullable: [], legacy: [
+        error(
+            StaticWarningCode
+                .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+            67,
+            5),
+      ]),
+    );
   }
 
   test_concrete_equal() async {
@@ -294,20 +300,23 @@
     // If the base class provided an explicit value for a default parameter,
     // then it is a static warning for the derived class to provide a different
     // value, even if implicitly.
-    await assertErrorsInCode(r'''
+    await assertErrorsInCode(
+      r'''
 class A {
   void foo([x = 1]) {}
 }
 class B extends A {
   void foo([x]) {}
 }
-''', [
-      error(
-          StaticWarningCode
-              .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
-          67,
-          1),
-    ]);
+''',
+      expectedErrorsByNullability(nullable: [], legacy: [
+        error(
+            StaticWarningCode
+                .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+            67,
+            1),
+      ]),
+    );
   }
 }
 
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
index 5d52603..42afb2e 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
@@ -87,11 +87,40 @@
   int add();
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 52, 1),
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 52, 1),
       error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 3),
     ]);
   }
 
+  test_method_abstractOverridesConcreteInMixin() async {
+    await assertErrorsInCode('''
+mixin M {
+  int add(int a, int b) => a + b;
+}
+class A with M {
+  int add();
+}
+''', [
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 52, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 69, 3),
+    ]);
+  }
+
+  test_method_abstractOverridesConcreteViaMixin() async {
+    await assertErrorsInCode('''
+class A {
+  int add(int a, int b) => a + b;
+}
+mixin M {
+  int add();
+}
+class B	extends A with M {}
+''', [
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 77, 1),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 94, 1),
+    ]);
+  }
+
   test_method_covariant_1() async {
     await assertNoErrorsInCode(r'''
 abstract class A<T> {
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_testing_member_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_testing_member_test.dart
index 998e775..2ef124c 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_testing_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_use_of_visible_for_testing_member_test.dart
@@ -25,18 +25,40 @@
     writeTestPackageConfigWithMeta();
   }
 
-  test_export() async {
-    newFile('$testPackageRootPath/lib1.dart', content: r'''
+  test_export_hide() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
 import 'package:meta/meta.dart';
+
 @visibleForTesting
-int fn0() => 1;
-''');
-    newFile('$testPackageRootPath/lib2.dart', content: r'''
-export 'lib1.dart' show fn0;
+class A {}
+
+class B {}
 ''');
 
-    await _resolveFile('$testPackageRootPath/lib1.dart');
-    await _resolveFile('$testPackageRootPath/lib2.dart');
+    newFile('$testPackageLibPath/b.dart', content: r'''
+export 'a.dart' hide A;
+''');
+
+    await _resolveFile('$testPackageLibPath/a.dart');
+    await _resolveFile('$testPackageLibPath/b.dart');
+  }
+
+  test_export_show() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+import 'package:meta/meta.dart';
+
+@visibleForTesting
+class A {}
+
+class B {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: r'''
+export 'a.dart' show A;
+''');
+
+    await _resolveFile('$testPackageLibPath/a.dart');
+    await _resolveFile('$testPackageLibPath/b.dart');
   }
 
   test_fromIntegrationTestDirectory() async {
@@ -176,6 +198,49 @@
     ]);
   }
 
+  test_import_hide() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+import 'package:meta/meta.dart';
+
+@visibleForTesting
+class A {}
+
+class B {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: r'''
+import 'a.dart' hide A;
+
+void f(B _) {}
+''');
+
+    await _resolveFile('$testPackageLibPath/a.dart');
+    await _resolveFile('$testPackageLibPath/b.dart');
+  }
+
+  test_import_show() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+import 'package:meta/meta.dart';
+
+@visibleForTesting
+class A {}
+
+class B {}
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: r'''
+import 'a.dart' show A;
+
+void f(A _) {}
+''');
+
+    await _resolveFile('$testPackageLibPath/a.dart');
+    await _resolveFile('$testPackageLibPath/b.dart', [
+      error(HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER, 21, 1),
+      error(HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER, 32, 1),
+    ]);
+  }
+
   test_method() async {
     newFile('$testPackageRootPath/lib1.dart', content: r'''
 import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/missing_field_type_in_struct_test.dart b/pkg/analyzer/test/src/diagnostics/missing_field_type_in_struct_test.dart
index cfae21f..c5ae82c 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_field_type_in_struct_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_field_type_in_struct_test.dart
@@ -20,6 +20,8 @@
 import 'dart:ffi';
 class C extends Struct {
   var str;
+
+  Pointer notEmpty;
 }
 ''', [
       error(FfiCode.MISSING_FIELD_TYPE_IN_STRUCT, 50, 3),
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 8c6ecc1..c46e611 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
@@ -42,6 +42,51 @@
     ]);
   }
 
+  test_lookupFunction_Pointer() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:ffi';
+typedef S = Void Function(Pointer);
+typedef F = void Function(Pointer);
+void f(DynamicLibrary lib) {
+  lib.lookupFunction<S, F>('g');
+}
+''');
+  }
+
+  // TODO(https://dartbug.com/44594): Should this be an error or not?
+  test_lookupFunction_PointerNativeFunction() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+typedef S = Void Function(Pointer<NativeFunction>);
+typedef F = void Function(Pointer<NativeFunction>);
+void f(DynamicLibrary lib) {
+  lib.lookupFunction<S, F>('g');
+}
+''', [error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 173, 1)]);
+  }
+
+  test_lookupFunction_PointerNativeFunction2() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:ffi';
+typedef S = Void Function(Pointer<NativeFunction<Int8 Function()>>);
+typedef F = void Function(Pointer<NativeFunction<Int8 Function()>>);
+void f(DynamicLibrary lib) {
+  lib.lookupFunction<S, F>('g');
+}
+''');
+  }
+
+  test_lookupFunction_PointerVoid() async {
+    await assertNoErrorsInCode(r'''
+import 'dart:ffi';
+typedef S = Pointer<Void> Function(Pointer<Void>);
+typedef F = Pointer<Void> Function(Pointer<Void>);
+void f(DynamicLibrary lib) {
+  lib.lookupFunction<S, F>('g');
+}
+''');
+  }
+
   test_lookupFunction_T() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
diff --git a/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart b/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart
index 699a2a5..25b5b05 100644
--- a/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart
@@ -375,7 +375,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*, int*)*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.topGet('foo'));
   }
 
@@ -400,7 +400,7 @@
     var identifier = invocation.function;
     assertType(identifier, 'A*');
 
-    MethodElement element = invocation.staticElement;
+    var element = invocation.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('call'));
   }
 
@@ -425,7 +425,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*)*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -512,7 +512,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -537,7 +537,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -565,7 +565,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -590,7 +590,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -615,7 +615,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -638,7 +638,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*, int*)*');
 
-    FunctionElement element = identifier.staticElement;
+    var element = identifier.staticElement as FunctionElement;
     _assertLegacyMember(element, _import_a.topFunction('foo'));
   }
 
@@ -661,7 +661,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*, int*)*');
 
-    FunctionElement element = identifier.staticElement;
+    var element = identifier.staticElement as FunctionElement;
     _assertLegacyMember(element, _import_a.topFunction('foo'));
   }
 
@@ -686,7 +686,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*, int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     assertType(element.type, 'int* Function(int*, int*)*');
   }
 
@@ -711,7 +711,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*, int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     assertType(element.type, 'int* Function(int*, int*)*');
   }
 
@@ -738,7 +738,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*, int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     assertType(element.type, 'int* Function(int*, int*)*');
   }
 
@@ -763,7 +763,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*, int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     assertType(element.type, 'int* Function(int*, int*)*');
   }
 
@@ -790,7 +790,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*, int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     assertType(element.type, 'int* Function(int*, int*)*');
   }
 
@@ -904,7 +904,7 @@
     var identifier = prefixedIdentifier.identifier;
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -929,7 +929,7 @@
     var identifier = prefixedIdentifier.identifier;
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -953,7 +953,7 @@
     var identifier = prefixedIdentifier.identifier;
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -977,7 +977,7 @@
     var identifier = prefixedIdentifier.identifier;
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -1001,7 +1001,7 @@
     var identifier = prefixedIdentifier.identifier;
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -1025,7 +1025,7 @@
     var identifier = prefixedIdentifier.identifier;
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -1047,7 +1047,7 @@
     var identifier = prefixedIdentifier.identifier;
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.topGet('foo'));
   }
 
@@ -1071,7 +1071,7 @@
     var identifier = propertyAccess.propertyName;
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -1095,7 +1095,7 @@
     var identifier = propertyAccess.propertyName;
     assertType(identifier, 'int* Function()*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -1120,7 +1120,7 @@
     var identifier = propertyAccess.propertyName;
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -1146,7 +1146,7 @@
     var identifier = propertyAccess.propertyName;
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -1169,7 +1169,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -1192,7 +1192,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -1216,7 +1216,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.getter('foo'));
   }
 
@@ -1240,7 +1240,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int* Function(int*)*');
 
-    MethodElement element = identifier.staticElement;
+    var element = identifier.staticElement as MethodElement;
     _assertLegacyMember(element, _import_a.method('foo'));
   }
 
@@ -1259,7 +1259,7 @@
     var identifier = findNode.simple('foo');
     assertType(identifier, 'int*');
 
-    PropertyAccessorElement element = identifier.staticElement;
+    var element = identifier.staticElement as PropertyAccessorElement;
     _assertLegacyMember(element, _import_a.topGet('foo'));
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/null_safety_read_write_test.dart b/pkg/analyzer/test/src/diagnostics/null_safety_read_write_test.dart
index 8729624..2920519 100644
--- a/pkg/analyzer/test/src/diagnostics/null_safety_read_write_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/null_safety_read_write_test.dart
@@ -515,7 +515,8 @@
 ''', [
       error(CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE, 68,
           1),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 68, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          68, 1),
     ]);
     _assertAssigned('x +=', assigned: false, unassigned: true);
   }
@@ -530,7 +531,8 @@
 ''', [
       error(CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE, 68,
           1),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 68, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          68, 1),
     ]);
     _assertAssigned('x++', assigned: false, unassigned: true);
   }
@@ -545,7 +547,8 @@
 ''', [
       error(CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE, 70,
           1),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 70, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          70, 1),
     ]);
     _assertAssigned('x; // 0', assigned: false, unassigned: true);
   }
@@ -581,7 +584,8 @@
   x += 1;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 90, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          90, 1),
     ]);
     _assertAssigned('x +=', assigned: false, unassigned: false);
   }
@@ -595,7 +599,8 @@
   x++;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 90, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          90, 1),
     ]);
     _assertAssigned('x++', assigned: false, unassigned: false);
   }
@@ -609,7 +614,8 @@
   ++x; // 0
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 92, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          92, 1),
     ]);
     _assertAssigned('x; // 0', assigned: false, unassigned: false);
   }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_extends_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_extends_clause_test.dart
index ccdffe5..aab024e 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_extends_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_extends_clause_test.dart
@@ -15,7 +15,7 @@
 
 @reflectiveTest
 class NullableTypeInExtendsClauseTest extends PubPackageResolutionTest
-    with WithNullSafetyMixin {
+    with WithNonFunctionTypeAliasesMixin {
   test_class_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -32,6 +32,26 @@
     ]);
   }
 
+  test_class_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A;
+class C extends B? {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 42, 2),
+    ]);
+  }
+
+  test_class_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A?;
+class C extends B {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 43, 1),
+    ]);
+  }
+
   test_classAlias_withClass_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -50,6 +70,28 @@
     ]);
   }
 
+  test_classAlias_withClass_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+class B {}
+typedef C = A;
+class D = C? with B;
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 47, 2),
+    ]);
+  }
+
+  test_classAlias_withClass_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+class B {}
+typedef C = A?;
+class D = C with B;
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 48, 1),
+    ]);
+  }
+
   test_classAlias_withMixin_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -67,4 +109,26 @@
       error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 32, 2),
     ]);
   }
+
+  test_classAlias_withMixin_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+mixin B {}
+typedef C = A;
+class D = C? with B;
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 47, 2),
+    ]);
+  }
+
+  test_classAlias_withMixin_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+mixin B {}
+typedef C = A?;
+class D = C with B;
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE, 48, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_implements_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_implements_clause_test.dart
index 9e9d5a8..2238940 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_implements_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_implements_clause_test.dart
@@ -15,7 +15,7 @@
 
 @reflectiveTest
 class NullableTypeInImplementsClauseTest extends PubPackageResolutionTest
-    with WithNullSafetyMixin {
+    with WithNonFunctionTypeAliasesMixin {
   test_class_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -32,6 +32,26 @@
     ]);
   }
 
+  test_class_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A;
+class C implements B? {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE, 45, 2),
+    ]);
+  }
+
+  test_class_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A?;
+class C implements B {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE, 46, 1),
+    ]);
+  }
+
   test_mixin_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -47,4 +67,24 @@
       error(CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE, 30, 2),
     ]);
   }
+
+  test_mixin_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A;
+mixin C implements B? {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE, 45, 2),
+    ]);
+  }
+
+  test_mixin_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A?;
+mixin C implements B {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_IMPLEMENTS_CLAUSE, 46, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_on_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_on_clause_test.dart
index 98a243c..d987fba 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_on_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_on_clause_test.dart
@@ -15,7 +15,7 @@
 
 @reflectiveTest
 class NullableTypeInOnClauseTest extends PubPackageResolutionTest
-    with WithNullSafetyMixin {
+    with WithNonFunctionTypeAliasesMixin {
   test_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -31,4 +31,24 @@
       error(CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE, 22, 2),
     ]);
   }
+
+  test_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A;
+mixin C on B? {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE, 37, 2),
+    ]);
+  }
+
+  test_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A?;
+mixin C on B {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_ON_CLAUSE, 38, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/nullable_type_in_with_clause_test.dart b/pkg/analyzer/test/src/diagnostics/nullable_type_in_with_clause_test.dart
index ba235ef..ea7d118 100644
--- a/pkg/analyzer/test/src/diagnostics/nullable_type_in_with_clause_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/nullable_type_in_with_clause_test.dart
@@ -15,7 +15,7 @@
 
 @reflectiveTest
 class NullableTypeInWithClauseTest extends PubPackageResolutionTest
-    with WithNullSafetyMixin {
+    with WithNonFunctionTypeAliasesMixin {
   test_class_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -32,6 +32,26 @@
     ]);
   }
 
+  test_class_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A;
+class C with B? {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 39, 2),
+    ]);
+  }
+
+  test_class_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+typedef B = A?;
+class C with B {}
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 40, 1),
+    ]);
+  }
+
   test_classAlias_withClass_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -50,6 +70,28 @@
     ]);
   }
 
+  test_classAlias_withClass_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+class B {}
+typedef C = B;
+class D = A with C?;
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 54, 2),
+    ]);
+  }
+
+  test_classAlias_withClass_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+class B {}
+typedef C = B?;
+class D = A with C;
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 55, 1),
+    ]);
+  }
+
   test_classAlias_withMixin_nonNullable() async {
     await assertNoErrorsInCode('''
 class A {}
@@ -67,4 +109,26 @@
       error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 39, 2),
     ]);
   }
+
+  test_classAlias_withMixin_nullable_alias() async {
+    await assertErrorsInCode('''
+class A {}
+mixin B {}
+typedef C = B;
+class D = A with C?;
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 54, 2),
+    ]);
+  }
+
+  test_classAlias_withMixin_nullable_alias2() async {
+    await assertErrorsInCode('''
+class A {}
+mixin B {}
+typedef C = B?;
+class D = A with C;
+''', [
+      error(CompileTimeErrorCode.NULLABLE_TYPE_IN_WITH_CLAUSE, 55, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/override_equals_but_not_hashcode_test.dart b/pkg/analyzer/test/src/diagnostics/override_equals_but_not_hashcode_test.dart
deleted file mode 100644
index 6479ead..0000000
--- a/pkg/analyzer/test/src/diagnostics/override_equals_but_not_hashcode_test.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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:analyzer/src/error/codes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/context_collection_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(OverrideEqualsButNotHashCodeTest);
-  });
-}
-
-@reflectiveTest
-class OverrideEqualsButNotHashCodeTest extends PubPackageResolutionTest {
-  test_overrideBoth() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  bool operator ==(x) { return x; }
-  get hashCode => 0;
-}''');
-  }
-
-  @failingTest
-  test_overrideEquals_andNotHashCode() async {
-    await assertErrorsInCode(r'''
-class A {
-  bool operator ==(x) {}
-}''', [
-      error(HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE, 6, 1),
-    ]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
index 757d377..a5c4ffc 100644
--- a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
@@ -77,7 +77,10 @@
   x + (1 + 2);
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
+      error(
+          CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE,
+          21,
+          1),
     ]);
 
     assertBinaryExpression(
@@ -121,7 +124,7 @@
   x();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
+      error(CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 21, 1),
     ]);
   }
 
@@ -201,7 +204,8 @@
   x[0];
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          21, 1),
     ]);
 
     assertIndexExpression(
@@ -218,7 +222,8 @@
   x[0] += 1 + 2;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          21, 1),
     ]);
 
     assertAssignment(
@@ -249,7 +254,8 @@
   x[0] = 1 + 2;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          21, 1),
     ]);
 
     assertIndexExpression(
@@ -318,7 +324,7 @@
   x.toString(1 + 2);
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 31, 7),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 32, 5),
     ]);
 
     assertMethodInvocation(
@@ -358,7 +364,8 @@
   x++;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          21, 1),
     ]);
 
     assertPostfixExpression(
@@ -399,7 +406,8 @@
   ++x;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          23, 1),
     ]);
 
     assertPrefixExpression(
@@ -422,8 +430,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('foo'),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'Never',
     );
   }
@@ -437,8 +444,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('hashCode'),
-      readElement: objectElement.getGetter('hashCode'),
-      writeElement: null,
+      element: objectElement.getGetter('hashCode'),
       type: 'Never',
     );
   }
@@ -452,14 +458,9 @@
       error(HintCode.DEAD_CODE, 29, 2),
     ]);
 
-    if (hasAssignmentLeftResolution) {
-      assertSimpleIdentifier(
-        findNode.simple('foo'),
-        readElement: null,
-        writeElement: null,
-        type: 'dynamic',
-      );
-    }
+    assertSimpleIdentifierAssignmentTarget(
+      findNode.simple('foo'),
+    );
 
     assertAssignment(
       findNode.assignment('foo += 0'),
@@ -481,8 +482,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('toString'),
-      readElement: objectElement.getMethod('toString'),
-      writeElement: null,
+      element: objectElement.getMethod('toString'),
       type: 'Never',
     );
   }
@@ -496,11 +496,8 @@
       error(HintCode.DEAD_CODE, 28, 2),
     ]);
 
-    assertSimpleIdentifier(
+    assertSimpleIdentifierAssignmentTarget(
       findNode.simple('foo'),
-      readElement: null,
-      writeElement: null,
-      type: 'Never',
     );
 
     assertAssignment(
@@ -520,13 +517,13 @@
   x.foo;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          21, 1),
     ]);
 
     assertSimpleIdentifier(
       findNode.simple('foo'),
-      readElement: null,
-      writeElement: null,
+      element: null,
       type: 'dynamic',
     );
   }
@@ -540,8 +537,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('hashCode'),
-      readElement: objectElement.getGetter('hashCode'),
-      writeElement: null,
+      element: objectElement.getGetter('hashCode'),
       type: 'int',
     );
   }
@@ -555,8 +551,7 @@
 
     assertSimpleIdentifier(
       findNode.simple('toString'),
-      readElement: objectElement.getMethod('toString'),
-      writeElement: null,
+      element: objectElement.getMethod('toString'),
       type: 'String Function()',
     );
   }
@@ -623,11 +618,10 @@
 
     assertSimpleIdentifier(
       findNode.simple('toString'),
-      readElement: elementMatcher(
+      element: elementMatcher(
         objectElement.getMethod('toString'),
         isLegacy: isNullSafetySdkAndLegacyLibrary,
       ),
-      writeElement: null,
       type: 'String Function()',
     );
   }
@@ -641,11 +635,10 @@
 
     assertSimpleIdentifier(
       findNode.simple('hashCode'),
-      readElement: elementMatcher(
+      element: elementMatcher(
         objectElement.getGetter('hashCode'),
         isLegacy: isNullSafetySdkAndLegacyLibrary,
       ),
-      writeElement: null,
       type: 'int',
     );
   }
diff --git a/pkg/analyzer/test/src/diagnostics/redirect_to_type_alias_expands_to_type_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/redirect_to_type_alias_expands_to_type_parameter_test.dart
new file mode 100644
index 0000000..dbe1342
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/redirect_to_type_alias_expands_to_type_parameter_test.dart
@@ -0,0 +1,97 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RedirectTypeAliasExpandsToTypeParameterTest);
+  });
+}
+
+@reflectiveTest
+class RedirectTypeAliasExpandsToTypeParameterTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  test_generic_typeParameter_withArgument_named() async {
+    await assertErrorsInCode(r'''
+class A implements C {
+  A.named();
+}
+
+typedef B<T> = T;
+
+class C {
+  factory C() = B<A>.named;
+}
+''', [
+      error(
+          CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          84,
+          1),
+    ]);
+  }
+
+  test_generic_typeParameter_withArgument_unnamed() async {
+    await assertErrorsInCode(r'''
+class A implements C {}
+
+typedef B<T> = T;
+
+class C {
+  factory C() = B<A>;
+}
+''', [
+      error(
+          CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          70,
+          1),
+    ]);
+  }
+
+  test_generic_typeParameter_withoutArgument_unnamed() async {
+    await assertErrorsInCode(r'''
+class A implements C {}
+
+typedef B<T> = T;
+
+class C {
+  factory C() = B;
+}
+''', [
+      error(
+          CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          70,
+          1),
+    ]);
+  }
+
+  test_notGeneric_class_named() async {
+    await assertNoErrorsInCode(r'''
+class A implements C {
+  A.named();
+}
+
+typedef B = A;
+
+class C {
+  factory C() = B.named;
+}
+''');
+  }
+
+  test_notGeneric_class_unnamed() async {
+    await assertNoErrorsInCode(r'''
+class A implements C {}
+
+typedef B = A;
+
+class C {
+  factory C() = B;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/return_of_do_not_store_test.dart b/pkg/analyzer/test/src/diagnostics/return_of_do_not_store_test.dart
index c747e6a..c8f61f5 100644
--- a/pkg/analyzer/test/src/diagnostics/return_of_do_not_store_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/return_of_do_not_store_test.dart
@@ -21,6 +21,22 @@
     writeTestPackageConfigWithMeta();
   }
 
+  test_returnFromClosureInFunction() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+@doNotStore
+String _v = '';
+
+String f() {
+  var v = () => _v;
+  return v();
+}
+''', [
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 92, 2),
+    ]);
+  }
+
   test_returnFromFunction() async {
     await assertErrorsInCode('''
 import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_from_catch_error_test.dart b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_from_catch_error_test.dart
new file mode 100644
index 0000000..51b7617
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_from_catch_error_test.dart
@@ -0,0 +1,200 @@
+// 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 '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReturnOfInvalidTypeForCatchErrorTest);
+    defineReflectiveTests(ReturnOfInvalidTypeForCatchErrorWithNullSafetyTest);
+  });
+}
+
+@reflectiveTest
+class ReturnOfInvalidTypeForCatchErrorTest extends PubPackageResolutionTest {
+  test_async_okReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<int> future) {
+  future.catchError((e, st) async => 0);
+}
+''');
+  }
+
+  test_blockFunctionBody_async_emptyReturn_nonVoid() async {
+    await assertErrorsInCode('''
+void f(Future<int> future) {
+  future.catchError((e, st) async {
+    return;
+  });
+}
+''', [
+      error(CompileTimeErrorCode.RETURN_WITHOUT_VALUE, 69, 6),
+    ]);
+  }
+
+  test_blockFunctionBody_async_emptyReturn_void() async {
+    await assertNoErrorsInCode('''
+void f(Future<void> future) {
+  future.catchError((e, st) async {
+    return;
+  });
+}
+''');
+  }
+
+  test_blockFunctionBody_emptyReturn_dynamic() async {
+    await assertNoErrorsInCode('''
+void f(Future<dynamic> future) {
+  future.catchError((e, st) {
+    return;
+  });
+}
+''');
+  }
+
+  test_blockFunctionBody_emptyReturn_nonVoid() async {
+    await assertErrorsInCode('''
+void f(Future<int> future) {
+  future.catchError((e, st) {
+    return;
+  });
+}
+''', [
+      error(CompileTimeErrorCode.RETURN_WITHOUT_VALUE, 63, 6),
+    ]);
+  }
+
+  test_blockFunctionBody_emptyReturn_void() async {
+    await assertNoErrorsInCode('''
+void f(Future<void> future) {
+  future.catchError((e, st) {
+    return;
+  });
+}
+''');
+  }
+
+  test_blockFunctionBody_invalidReturnType() async {
+    await assertErrorsInCode('''
+void f(Future<int> future) {
+  future.catchError((e, st) {
+    if (1 == 2) {
+      return 7;
+    } else {
+      return 0.5;
+    }
+  });
+}
+''', [
+      error(HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR, 119, 3),
+    ]);
+  }
+
+  test_blockFunctionBody_withLocalFunction_expression_okReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<int> future) {
+  future.catchError((e, st) {
+    double g() => 0.5;
+    if (g() == 0.5) return 0;
+    return 1;
+  });
+}
+''');
+  }
+
+  test_blockFunctionBody_withLocalFunction_okReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<int> future) {
+  future.catchError((e, st) {
+    double g() {
+      return 0.5;
+    }
+    if (g() == 0.5) return 0;
+    return 1;
+  });
+}
+''');
+  }
+
+  test_expressionFunctionBody_invalidReturnType() async {
+    await assertErrorsInCode('''
+void f(Future<int> future) {
+  future.catchError((e, st) => 'c');
+}
+''', [
+      error(HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR, 60, 3),
+    ]);
+  }
+
+  test_Null_okReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<Null> future) {
+  future.catchError((e, st) => null);
+}
+''');
+  }
+
+  test_okReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<int> future) {
+  future.catchError((e, st) => 0);
+}
+''');
+  }
+
+  test_void_okReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<void> future) {
+  future.catchError((e, st) => 0);
+}
+''');
+  }
+
+  test_voidReturnType() async {
+    await assertErrorsInCode('''
+void f(Future<int> future, void Function() g) {
+  future.catchError((e, st) => g());
+}
+''', [
+      error(HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR, 79, 3),
+    ]);
+  }
+}
+
+@reflectiveTest
+class ReturnOfInvalidTypeForCatchErrorWithNullSafetyTest
+    extends ReturnOfInvalidTypeForCatchErrorTest with WithNullSafetyMixin {
+  test_nullableType_emptyBody() async {
+    await assertNoErrorsInCode('''
+void f(Future<int?> future) {
+  future.catchError((e, st) {});
+}
+''');
+  }
+
+  test_nullableType_emptyReturn() async {
+    await assertErrorsInCode('''
+void f(Future<int?> future) {
+  future.catchError((e, st) {
+    return;
+  });
+}
+''', [
+      error(CompileTimeErrorCode.RETURN_WITHOUT_VALUE, 64, 6),
+    ]);
+  }
+
+  test_nullableType_invalidReturnType() async {
+    await assertErrorsInCode('''
+void f(Future<int?> future) {
+  future.catchError((e, st) => '');
+}
+''', [
+      error(HintCode.RETURN_OF_INVALID_TYPE_FROM_CATCH_ERROR, 61, 2),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/return_type_invalid_for_catch_error_test.dart b/pkg/analyzer/test/src/diagnostics/return_type_invalid_for_catch_error_test.dart
new file mode 100644
index 0000000..ddd5ed2
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/return_type_invalid_for_catch_error_test.dart
@@ -0,0 +1,100 @@
+// 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 '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReturnTypeInvalidForCatchErrorTest);
+    defineReflectiveTests(ReturnTypeInvalidForCatchErrorWithNullSafetyTest);
+  });
+}
+
+@reflectiveTest
+class ReturnTypeInvalidForCatchErrorTest extends PubPackageResolutionTest {
+  test_dynamic_returnTypeIsUnrelatedFuture() async {
+    await assertNoErrorsInCode('''
+void f(
+    Future<dynamic> future, Future<String> Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''');
+  }
+
+  test_dynamic_unrelatedReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<dynamic> future, String Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''');
+  }
+
+  test_invalidReturnType() async {
+    await assertErrorsInCode('''
+void f(Future<int> future, String Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''', [
+      error(HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR, 90, 2),
+    ]);
+  }
+
+  test_returnTypeIsFuture() async {
+    await assertNoErrorsInCode('''
+void f(Future<int> future, Future<int> Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''');
+  }
+
+  test_returnTypeIsFutureOr() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f(Future<int> future, FutureOr<int> Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''');
+  }
+
+  test_sameReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<int> future, int Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''');
+  }
+
+  test_void_returnTypeIsUnrelatedFuture() async {
+    await assertNoErrorsInCode('''
+void f(Future<void> future, Future<String> Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''');
+  }
+
+  test_void_unrelatedReturnType() async {
+    await assertNoErrorsInCode('''
+void f(Future<void> future, String Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''');
+  }
+}
+
+@reflectiveTest
+class ReturnTypeInvalidForCatchErrorWithNullSafetyTest
+    extends ReturnTypeInvalidForCatchErrorTest with WithNullSafetyMixin {
+  test_nullableReturnType() async {
+    await assertErrorsInCode('''
+void f(Future<int> future, String? Function(dynamic, StackTrace) cb) {
+  future.catchError(cb);
+}
+''', [
+      error(HintCode.RETURN_TYPE_INVALID_FOR_CATCH_ERROR, 91, 2),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/return_without_value_test.dart b/pkg/analyzer/test/src/diagnostics/return_without_value_test.dart
index 6d33a0d..9a31d66 100644
--- a/pkg/analyzer/test/src/diagnostics/return_without_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/return_without_value_test.dart
@@ -36,6 +36,16 @@
     ]);
   }
 
+  test_catchError_futureOfVoid() async {
+    await assertNoErrorsInCode('''
+void f(Future<void> future) {
+  future.catchError((e) {
+    return;
+  });
+}
+''');
+  }
+
   test_factoryConstructor() async {
     await assertErrorsInCode('''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/subtype_of_ffi_class_test.dart b/pkg/analyzer/test/src/diagnostics/subtype_of_ffi_class_test.dart
index a5aed99..7073a39 100644
--- a/pkg/analyzer/test/src/diagnostics/subtype_of_ffi_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/subtype_of_ffi_class_test.dart
@@ -84,7 +84,9 @@
   test_Struct() async {
     await assertNoErrorsInCode(r'''
 import 'dart:ffi';
-class C extends Struct {}
+class C extends Struct {
+  Pointer notEmpty;
+}
 ''');
   }
 
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 66f4192..e52db81 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
@@ -21,10 +21,12 @@
   test_extends() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
-class S extends Struct {}
+class S extends Struct {
+  Pointer notEmpty;
+}
 class C extends S {}
 ''', [
-      error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS, 61, 1),
+      error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS, 82, 1),
     ]);
   }
 }
@@ -37,6 +39,7 @@
 class S extends Struct {}
 class C implements S {}
 ''', [
+      error(FfiCode.EMPTY_STRUCT_WARNING, 19, 25),
       error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS, 64, 1),
     ]);
   }
@@ -50,6 +53,7 @@
 class S extends Struct {}
 class C with S {}
 ''', [
+      error(FfiCode.EMPTY_STRUCT_WARNING, 19, 25),
       error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 58, 1),
       error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH, 58, 1),
     ]);
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 05d7fb0..6d808e0 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -17,7 +17,6 @@
 import 'ambiguous_set_or_map_literal_test.dart' as ambiguous_set_or_map_literal;
 import 'annotation_on_pointer_field_test.dart' as annotation_on_pointer_field;
 import 'annotation_syntax_test.dart' as annotation_syntax;
-import 'annotation_with_non_class_test.dart' as annotation_with_non_class;
 import 'argument_type_not_assignable_test.dart' as argument_type_not_assignable;
 import 'assert_in_redirecting_constructor_test.dart'
     as assert_in_redirecting_constructor;
@@ -267,12 +266,13 @@
     as instance_member_access_from_static;
 import 'instantiate_abstract_class_test.dart' as instantiate_abstract_class;
 import 'instantiate_enum_test.dart' as instantiate_enum;
+import 'instantiate_type_alias_expands_to_type_parameter_test.dart'
+    as instantiate_type_alias_expands_to_type_parameter;
 import 'integer_literal_imprecise_as_double_test.dart'
     as integer_literal_imprecise_as_double;
 import 'integer_literal_out_of_range_test.dart' as integer_literal_out_of_range;
 import 'invalid_annotation_from_deferred_library_test.dart'
     as invalid_annotation_from_deferred_library;
-import 'invalid_annotation_getter_test.dart' as invalid_annotation_getter;
 import 'invalid_annotation_target_test.dart' as invalid_annotation_target;
 import 'invalid_annotation_test.dart' as invalid_annotation;
 import 'invalid_assignment_test.dart' as invalid_assignment;
@@ -290,6 +290,8 @@
     as invalid_factory_name_not_a_class;
 import 'invalid_field_type_in_struct_test.dart' as invalid_field_type_in_struct;
 import 'invalid_immutable_annotation_test.dart' as invalid_immutable_annotation;
+import 'invalid_implementation_override_test.dart'
+    as invalid_implementation_override;
 import 'invalid_internal_annotation_test.dart' as invalid_internal_annotation;
 import 'invalid_language_override_greater_test.dart'
     as invalid_language_override_greater;
@@ -482,8 +484,6 @@
     as object_cannot_extend_another_class;
 import 'optional_parameter_in_operator_test.dart'
     as optional_parameter_in_operator;
-import 'override_equals_but_not_hashcode_test.dart'
-    as override_equals_but_not_hashcode;
 import 'override_on_non_overriding_field_test.dart'
     as override_on_non_overriding_field;
 import 'override_on_non_overriding_getter_test.dart'
@@ -527,6 +527,8 @@
 import 'redirect_to_non_class_test.dart' as redirect_to_non_class;
 import 'redirect_to_non_const_constructor_test.dart'
     as redirect_to_non_const_constructor;
+import 'redirect_to_type_alias_expands_to_type_parameter_test.dart'
+    as redirect_to_type_alias_expands_to_type_parameter;
 import 'referenced_before_declaration_test.dart'
     as referenced_before_declaration;
 import 'rethrow_outside_catch_test.dart' as rethrow_outside_catch;
@@ -534,7 +536,11 @@
     as return_in_generative_constructor;
 import 'return_in_generator_test.dart' as return_in_generator;
 import 'return_of_do_not_store_test.dart' as return_of_do_not_store;
+import 'return_of_invalid_type_from_catch_error_test.dart'
+    as return_of_invalid_type_from_catch_error;
 import 'return_of_invalid_type_test.dart' as return_of_invalid_type;
+import 'return_type_invalid_for_catch_error_test.dart'
+    as return_type_invalid_for_catch_error;
 import 'return_without_value_test.dart' as return_without_value;
 import 'sdk_version_as_expression_in_const_context_test.dart'
     as sdk_version_as_expression_in_const_context;
@@ -670,7 +676,6 @@
     ambiguous_set_or_map_literal.main();
     annotation_on_pointer_field.main();
     annotation_syntax.main();
-    annotation_with_non_class.main();
     argument_type_not_assignable.main();
     assert_in_redirecting_constructor.main();
     assignment_of_do_not_store.main();
@@ -833,11 +838,11 @@
     instance_member_access_from_static.main();
     instantiate_abstract_class.main();
     instantiate_enum.main();
+    instantiate_type_alias_expands_to_type_parameter.main();
     integer_literal_imprecise_as_double.main();
     integer_literal_out_of_range.main();
     invalid_annotation.main();
     invalid_annotation_from_deferred_library.main();
-    invalid_annotation_getter.main();
     invalid_annotation_target.main();
     invalid_assignment.main();
     invalid_cast_new_expr.main();
@@ -851,6 +856,7 @@
     invalid_factory_name_not_a_class.main();
     invalid_field_type_in_struct.main();
     invalid_immutable_annotation.main();
+    invalid_implementation_override.main();
     invalid_internal_annotation.main();
     invalid_language_override_greater.main();
     invalid_language_override.main();
@@ -979,7 +985,6 @@
     nullable_type_in_with_clause.main();
     object_cannot_extend_another_class.main();
     optional_parameter_in_operator.main();
-    override_equals_but_not_hashcode.main();
     override_on_non_overriding_field.main();
     override_on_non_overriding_getter.main();
     override_on_non_overriding_method.main();
@@ -1005,12 +1010,15 @@
     redirect_to_missing_constructor.main();
     redirect_to_non_class.main();
     redirect_to_non_const_constructor.main();
+    redirect_to_type_alias_expands_to_type_parameter.main();
     referenced_before_declaration.main();
     rethrow_outside_catch.main();
     return_in_generative_constructor.main();
     return_in_generator.main();
     return_of_do_not_store.main();
+    return_of_invalid_type_from_catch_error.main();
     return_of_invalid_type.main();
+    return_type_invalid_for_catch_error.main();
     return_without_value.main();
     set_element_from_deferred_library.main();
     sdk_version_as_expression_in_const_context.main();
diff --git a/pkg/analyzer/test/src/diagnostics/todo_test.dart b/pkg/analyzer/test/src/diagnostics/todo_test.dart
index 1a540df..c2cb064 100644
--- a/pkg/analyzer/test/src/diagnostics/todo_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/todo_test.dart
@@ -27,6 +27,40 @@
     ]);
   }
 
+  test_todo_multiLineCommentWrapped() async {
+    await assertErrorsInCode(r'''
+main() {
+  /* TODO(a): Implement something
+   *  that is too long for one line
+   * This line is not part of the todo
+   */
+  /* TODO: Implement something
+   *  that is too long for one line
+   * This line is not part of the todo
+   */
+  /* TODO(a): Implement something
+   *  that is too long for one line
+   * 
+   *  This line is not part of the todo
+   */
+  /* TODO: Implement something
+   *  that is too long for one line
+   * 
+   *  This line is not part of the todo
+   */
+}
+''', [
+      error(TodoCode.TODO, 14, 64,
+          text: 'TODO(a): Implement something that is too long for one line'),
+      error(TodoCode.TODO, 129, 61,
+          text: 'TODO: Implement something that is too long for one line'),
+      error(TodoCode.TODO, 241, 64,
+          text: 'TODO(a): Implement something that is too long for one line'),
+      error(TodoCode.TODO, 363, 61,
+          text: 'TODO: Implement something that is too long for one line'),
+    ]);
+  }
+
   test_todo_singleLineComment() async {
     await assertErrorsInCode(r'''
 main() {
@@ -36,4 +70,96 @@
       error(TodoCode.TODO, 14, 15, text: 'TODO: Implement'),
     ]);
   }
+
+  test_todo_singleLineCommentDoubleCommented() async {
+    // Continuations are ignored for code that looks like commented comments
+    // although the original TODOs are still picked up.
+    await assertErrorsInCode(r'''
+main() {
+//      // TODO: Implement something
+//      //  that is too long for one line
+//      main() {
+
+//      // TODO: Implement something
+//      // this is not a todo
+//      main() {
+
+//      // TODO: Implement something
+//      main() {
+}
+''', [
+      error(TodoCode.TODO, 20, 67,
+          text: 'TODO: Implement something that is too long for one line'),
+      error(TodoCode.TODO, 117, 25, text: 'TODO: Implement something'),
+      error(TodoCode.TODO, 202, 25, text: 'TODO: Implement something'),
+    ]);
+  }
+
+  test_todo_singleLineCommentLessIndentedContinuation() async {
+    await assertErrorsInCode(r'''
+main() {
+  // TODO: Implement something
+  //  that is too long for one line
+//    this is not part of the todo
+}
+''', [
+      error(TodoCode.TODO, 14, 61,
+          text: 'TODO: Implement something that is too long for one line'),
+    ]);
+  }
+
+  test_todo_singleLineCommentMoreIndentedContinuation() async {
+    await assertErrorsInCode(r'''
+main() {
+  // TODO: Implement something
+  //  that is too long for one line
+  //      this is not part of the todo
+}
+''', [
+      error(TodoCode.TODO, 14, 61,
+          text: 'TODO: Implement something that is too long for one line'),
+    ]);
+  }
+
+  test_todo_singleLineCommentNested() async {
+    await assertErrorsInCode(r'''
+main() {
+  // TODO: Implement something
+  //  that is too long for one line
+  //  TODO: This is a seperate todo that is accidentally indented
+}
+''', [
+      error(TodoCode.TODO, 14, 61,
+          text: 'TODO: Implement something that is too long for one line'),
+      error(TodoCode.TODO, 82, 59,
+          text: 'TODO: This is a seperate todo that is accidentally indented'),
+    ]);
+  }
+
+  test_todo_singleLineCommentWrapped() async {
+    await assertErrorsInCode(r'''
+main() {
+  // TODO: Implement something
+  //  that is too long for one line
+  // this is not part of the todo
+
+  // TODO: Implement something
+  //  that is too long for one line
+  
+  //  this is not part of the todo
+
+  // TODO: Implement something
+  //  that is too long for one line
+  // 
+  //  this is not part of the todo
+}
+''', [
+      error(TodoCode.TODO, 14, 61,
+          text: 'TODO: Implement something that is too long for one line'),
+      error(TodoCode.TODO, 116, 61,
+          text: 'TODO: Implement something that is too long for one line'),
+      error(TodoCode.TODO, 222, 61,
+          text: 'TODO: Implement something that is too long for one line'),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/type_alias_cannot_reference_itself_test.dart b/pkg/analyzer/test/src/diagnostics/type_alias_cannot_reference_itself_test.dart
index af8a61a..4c9ceb3 100644
--- a/pkg/analyzer/test/src/diagnostics/type_alias_cannot_reference_itself_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_alias_cannot_reference_itself_test.dart
@@ -10,11 +10,22 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(TypeAliasCannotReferenceItselfTest);
+    defineReflectiveTests(
+      TypeAliasCannotReferenceItselfWithNonFunctionTypeAliasesTest,
+    );
   });
 }
 
 @reflectiveTest
 class TypeAliasCannotReferenceItselfTest extends PubPackageResolutionTest {
+  test_functionTypeAlias_typeParameterBounds() async {
+    await assertErrorsInCode('''
+typedef A<T extends A<int>>();
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 30),
+    ]);
+  }
+
   test_functionTypedParameter_returnType() async {
     await assertErrorsInCode('''
 typedef A(A b());
@@ -37,6 +48,14 @@
     ]);
   }
 
+  test_genericTypeAlias_typeParameterBounds() async {
+    await assertErrorsInCode('''
+typedef A<T extends A<int>> = void Function();
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 46),
+    ]);
+  }
+
   test_infiniteParameterBoundCycle() async {
     await assertErrorsInCode(r'''
 typedef F<X extends F<X>> = F Function();
@@ -141,12 +160,58 @@
       error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 15, 14),
     ]);
   }
+}
 
-  test_typeVariableBounds() async {
+@reflectiveTest
+class TypeAliasCannotReferenceItselfWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  test_nonFunction_aliasedType_cycleOf2() async {
     await assertErrorsInCode('''
-typedef A<T extends A<int>>();
+typedef T1 = T2;
+typedef T2 = T1;
 ''', [
-      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 30),
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 16),
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 17, 16),
+    ]);
+  }
+
+  test_nonFunction_aliasedType_directly_functionWithIt() async {
+    await assertErrorsInCode('''
+typedef T = void Function(T);
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 29),
+    ]);
+  }
+
+  test_nonFunction_aliasedType_directly_it_none() async {
+    await assertErrorsInCode('''
+typedef T = T;
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 14),
+    ]);
+  }
+
+  test_nonFunction_aliasedType_directly_it_question() async {
+    await assertErrorsInCode('''
+typedef T = T?;
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 15),
+    ]);
+  }
+
+  test_nonFunction_aliasedType_directly_ListOfIt() async {
+    await assertErrorsInCode('''
+typedef T = List<T>;
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 20),
+    ]);
+  }
+
+  test_nonFunction_typeParameterBounds() async {
+    await assertErrorsInCode('''
+typedef T<X extends T<Never>> = List<X>;
+''', [
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 40),
     ]);
   }
 }
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 da813a8..c515d56 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
@@ -13,11 +13,30 @@
     defineReflectiveTests(
       TypeArgumentNotMatchingBoundsWithNullSafetyTest,
     );
+    defineReflectiveTests(
+      TypeArgumentNotMatchingBoundsWithNonFunctionTypeAliasesTest,
+    );
   });
 }
 
 @reflectiveTest
-class TypeArgumentNotMatchingBoundsTest extends PubPackageResolutionTest {
+class TypeArgumentNotMatchingBoundsTest extends PubPackageResolutionTest
+    with TypeArgumentNotMatchingBoundsTestCases {
+  test_regression_42196_Null() async {
+    await assertNoErrorsInCode(r'''
+typedef G<X> = Function(X);
+class A<X extends G<A<X,Y>>, Y extends X> {}
+
+test<X>() { print("OK"); }
+
+main() {
+  test<A<G<A<Null, Null>>, dynamic>>();
+}
+''');
+  }
+}
+
+mixin TypeArgumentNotMatchingBoundsTestCases on PubPackageResolutionTest {
   test_classTypeAlias() async {
     await assertErrorsInCode(r'''
 class A {}
@@ -352,19 +371,6 @@
     ]);
   }
 
-  test_regression_42196_Null() async {
-    await assertNoErrorsInCode(r'''
-typedef G<X> = Function(X);
-class A<X extends G<A<X,Y>>, Y extends X> {}
-
-test<X>() { print("OK"); }
-
-main() {
-  test<A<G<A<Null, Null>>, dynamic>>();
-}
-''');
-  }
-
   test_typeArgumentList() async {
     await assertErrorsInCode(r'''
 class A {}
@@ -413,8 +419,43 @@
 }
 
 @reflectiveTest
+class TypeArgumentNotMatchingBoundsWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest
+    with
+        WithNonFunctionTypeAliasesMixin,
+        TypeArgumentNotMatchingBoundsTestCases {
+  test_nonFunctionTypeAlias_interfaceType_parameter() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef X<T extends A> = Map<int, T>;
+void f(X<String> a) {}
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 58, 6),
+    ]);
+  }
+
+  test_nonFunctionTypeAlias_interfaceType_parameter_regularBounded() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+class B extends A {}
+typedef X<T extends A> = Map<int, T>;
+void f(X<B> a) {}
+''');
+  }
+
+  test_nonFunctionTypeAlias_interfaceType_parameter_superBounded() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+typedef X<T extends A> = Map<int, T>;
+void f(X<Never> a) {}
+''');
+  }
+}
+
+@reflectiveTest
 class TypeArgumentNotMatchingBoundsWithNullSafetyTest
-    extends TypeArgumentNotMatchingBoundsTest with WithNullSafetyMixin {
+    extends PubPackageResolutionTest
+    with TypeArgumentNotMatchingBoundsTestCases, WithNullSafetyMixin {
   test_extends_optIn_fromOptOut_Null() async {
     newFile('$testPackageLibPath/a.dart', content: r'''
 class A<X extends int> {}
@@ -447,6 +488,16 @@
 ''');
   }
 
+  test_notRegularBounded_notSuperBounded_invariant() async {
+    await assertErrorsInCode(r'''
+typedef A<X> = X Function(X);
+typedef G<X extends A<X>> = void Function<Y extends X>();
+foo(G g) {}
+''', [
+      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 92, 1),
+    ]);
+  }
+
   test_regression_42196() async {
     await assertNoErrorsInCode(r'''
 typedef G<X> = Function(X);
@@ -460,23 +511,6 @@
 ''');
   }
 
-  @override
-  test_regression_42196_Null() async {
-    await assertErrorsInCode(r'''
-typedef G<X> = Function(X);
-class A<X extends G<A<X,Y>>, Y extends X> {}
-
-test<X>() { print("OK"); }
-
-main() {
-  test<A<G<A<Null, Null>>, dynamic>>();
-}
-''', [
-      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 120, 16),
-      error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 124, 4),
-    ]);
-  }
-
   test_regression_42196_object() async {
     await assertNoErrorsInCode(r'''
 typedef G<X> = Function(X);
diff --git a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
index 95cf0b8..08e380a 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
@@ -11,6 +11,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(UnusedElementTest);
     defineReflectiveTests(UnusedElementWithNullSafetyTest);
+    defineReflectiveTests(UnusedElementWithNonFunctionTypeAliasesTest);
   });
 }
 
@@ -1526,6 +1527,94 @@
       error(HintCode.UNUSED_ELEMENT, 34, 2),
     ]);
   }
+
+  test_typeAlias_functionType_isUsed_isExpression() async {
+    await assertNoErrorsInCode(r'''
+typedef _F = void Function();
+main(f) {
+  if (f is _F) {
+    print('F');
+  }
+}
+''');
+  }
+
+  test_typeAlias_functionType_isUsed_reference() async {
+    await assertNoErrorsInCode(r'''
+typedef _F = void Function();
+main(_F f) {
+}
+''');
+  }
+
+  test_typeAlias_functionType_isUsed_typeArgument() async {
+    await assertNoErrorsInCode(r'''
+typedef _F = void Function();
+main() {
+  var v = new List<_F>();
+  print(v);
+}
+''');
+  }
+
+  test_typeAlias_functionType_isUsed_variableDeclaration() async {
+    await assertNoErrorsInCode(r'''
+typedef _F = void Function();
+class A {
+  _F f;
+}
+''');
+  }
+
+  test_typeAlias_functionType_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+typedef _F = void Function();
+main() {
+}
+''', [
+      error(HintCode.UNUSED_ELEMENT, 8, 2),
+    ]);
+  }
+}
+
+@reflectiveTest
+class UnusedElementWithNonFunctionTypeAliasesTest
+    extends PubPackageResolutionTest with WithNonFunctionTypeAliasesMixin {
+  test_typeAlias_interfaceType_isUsed_typeName_isExpression() async {
+    await assertNoErrorsInCode(r'''
+typedef _A = List<int>;
+
+void f(a) {
+  a is _A;
+}
+''');
+  }
+
+  test_typeAlias_interfaceType_isUsed_typeName_parameter() async {
+    await assertNoErrorsInCode(r'''
+typedef _A = List<int>;
+
+void f(_A a) {}
+''');
+  }
+
+  test_typeAlias_interfaceType_isUsed_typeName_typeArgument() async {
+    await assertNoErrorsInCode(r'''
+typedef _A = List<int>;
+
+void f() {
+  Map<_A, int>();
+}
+''');
+  }
+
+  test_typeAlias_interfaceType_notUsed() async {
+    await assertErrorsInCode(r'''
+typedef _A = List<int>;
+''', [
+      error(HintCode.UNUSED_ELEMENT, 8, 2),
+    ]);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
index aaa54e9..5e0338c 100644
--- a/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
@@ -161,8 +161,10 @@
   }
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 126, 4),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 154, 4),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          126, 4),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          154, 4),
     ]);
   }
 
@@ -202,8 +204,10 @@
   }
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 68, 3),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 79, 4),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          68, 3),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          79, 4),
     ]);
   }
 
@@ -233,7 +237,8 @@
   }
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 78, 4),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          78, 4),
     ]);
   }
 
@@ -277,8 +282,10 @@
   }
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 93, 3),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 102, 4),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          93, 3),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          102, 4),
     ]);
   }
 
@@ -322,8 +329,10 @@
   }
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 93, 3),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 106, 4),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          93, 3),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          106, 4),
     ]);
   }
 }
@@ -347,7 +356,8 @@
   if(x && true) {}
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 22, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          22, 1),
     ]);
   }
 
@@ -376,7 +386,8 @@
   assert(x);
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 26, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          26, 1),
     ]);
   }
 
@@ -397,7 +408,8 @@
   b.a.x = 2;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 100, 3),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          100, 3),
     ]);
 
     assertAssignment(
@@ -482,7 +494,8 @@
   b.a.y += 0;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 109, 5),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          109, 5),
     ]);
 
     assertAssignment(
@@ -536,7 +549,8 @@
   b.a.x += 2;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 101, 3),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          101, 3),
     ]);
 
     assertAssignment(
@@ -580,7 +594,8 @@
   y += 0;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 31, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          31, 1),
     ]);
     var assignment1 = findNode.assignment('x +=');
     var assignment2 = findNode.assignment('y +=');
@@ -651,7 +666,8 @@
   x..[0] = 1;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          24, 1),
     ]);
   }
 
@@ -671,7 +687,8 @@
   x..abs();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          18, 1),
     ]);
   }
 
@@ -691,7 +708,8 @@
   x..isEven;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          18, 1),
     ]);
   }
 
@@ -732,7 +750,8 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 28, 1),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 33, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_ITERATOR,
+          33, 1),
     ]);
   }
 
@@ -746,7 +765,8 @@
   x.foo;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 58, 1),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          58, 1),
     ]);
   }
 
@@ -766,7 +786,8 @@
   if (x) {}
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          23, 1),
     ]);
   }
 
@@ -786,7 +807,8 @@
   x[0];
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          19, 1),
     ]);
   }
 
@@ -806,7 +828,7 @@
   x();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 1),
+      error(CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 23, 1),
     ]);
   }
 
@@ -826,7 +848,7 @@
   x();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 25, 1),
+      error(CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 25, 1),
     ]);
   }
 
@@ -882,12 +904,12 @@
   x.isEven;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          18, 1),
     ]);
     assertSimpleIdentifier(
       findNode.simple('isEven'),
-      readElement: intElement.getGetter('isEven'),
-      writeElement: null,
+      element: intElement.getGetter('isEven'),
       type: 'bool',
     );
   }
@@ -908,7 +930,8 @@
   (x).isEven;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 3),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          18, 3),
     ]);
   }
 
@@ -927,7 +950,8 @@
   x.isEven;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 27, 1),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          27, 1),
     ]);
   }
 
@@ -937,7 +961,7 @@
   x.first();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 38, 7),
+      error(CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE, 38, 7),
     ]);
   }
 
@@ -983,7 +1007,8 @@
   x.round();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          18, 1),
     ]);
   }
 
@@ -997,7 +1022,8 @@
   x.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 54, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          54, 1),
     ]);
   }
 
@@ -1032,7 +1058,8 @@
   x.call();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          19, 1),
     ]);
   }
 
@@ -1055,17 +1082,20 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          18, 1),
     ]);
   }
 
   test_not_nonNullable() async {
-    await assertNoErrorsInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   bool x = true;
   if(!x) {}
 }
-''');
+''', [
+      error(HintCode.DEAD_CODE, 32, 2),
+    ]);
   }
 
   test_not_nullable() async {
@@ -1075,7 +1105,8 @@
   if(!x) {}
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          23, 1),
     ]);
   }
 
@@ -1132,7 +1163,10 @@
   x - 3;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(
+          CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE,
+          18,
+          1),
     ]);
   }
 
@@ -1152,7 +1186,10 @@
   x + 3;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(
+          CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE,
+          18,
+          1),
     ]);
   }
 
@@ -1175,7 +1212,8 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          18, 1),
     ]);
   }
 
@@ -1193,7 +1231,8 @@
   x++;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 14, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          14, 1),
     ]);
   }
 
@@ -1209,7 +1248,8 @@
   x++;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 77, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          77, 1),
     ]);
   }
 
@@ -1232,7 +1272,8 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 20, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          20, 1),
     ]);
   }
 
@@ -1250,7 +1291,8 @@
   ++x;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 16, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          16, 1),
     ]);
   }
 
@@ -1273,7 +1315,8 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          19, 1),
     ]);
   }
 
@@ -1289,17 +1332,20 @@
   -x;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 73, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          73, 1),
     ]);
   }
 
   test_or_nonNullable() async {
-    await assertNoErrorsInCode(r'''
+    await assertErrorsInCode(r'''
 m() {
   bool x = true;
   if(x || false) {}
 }
-''');
+''', [
+      error(HintCode.DEAD_CODE, 33, 5),
+    ]);
   }
 
   test_or_nullable() async {
@@ -1309,7 +1355,8 @@
   if(x || false) {}
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 22, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          22, 1),
     ]);
   }
 
@@ -1327,7 +1374,8 @@
   x += 1;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 14, 1),
+      error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+          14, 1),
     ]);
   }
 
@@ -1343,7 +1391,8 @@
   a.x; // 2
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 66, 1),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          66, 1),
     ]);
     var propertyAccess1 = findNode.propertyAccess('a?.x; // 1');
     var propertyAccess2 = findNode.prefixed('a.x; // 2');
@@ -1374,7 +1423,8 @@
   b.a.x; // 2
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 101, 3),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          101, 3),
     ]);
     var propertyAccess1 = findNode.propertyAccess('b.a?.x; // 1');
     var propertyAccess2 = findNode.propertyAccess('b.a.x; // 2');
@@ -1405,7 +1455,8 @@
   b.a.x; // 2
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 101, 1),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          101, 1),
     ]);
     var propertyAccess1 = findNode.propertyAccess('x; // 1');
     var propertyAccess2 = findNode.propertyAccess('x; // 2');
@@ -1441,7 +1492,8 @@
   c.b.a.x; // 2
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 142, 5),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          142, 5),
     ]);
     var propertyAccess1 = findNode.propertyAccess('x; // 1');
     var propertyAccess2 = findNode.propertyAccess('x; // 2');
@@ -1477,7 +1529,8 @@
   c.b.a.x; // 2
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 148, 3),
+      error(CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE,
+          148, 3),
     ]);
     var propertyAccess1 = findNode.propertyAccess('x; // 1');
     var propertyAccess2 = findNode.propertyAccess('x; // 2');
@@ -1511,7 +1564,8 @@
   [...list];
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 26, 4),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD, 26,
+          4),
     ]);
   }
 
@@ -1531,7 +1585,8 @@
   x ? 0 : 1;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+          19, 1),
     ]);
   }
 
@@ -1552,4 +1607,26 @@
 }
 ''');
   }
+
+  test_yieldEach_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() sync* {
+  List<int> x = [];
+  yield* x;
+}
+''');
+  }
+
+  test_yieldEach_nullable() async {
+    await assertErrorsInCode(r'''
+m() sync* {
+  List<int>? x;
+  yield* x;
+}
+''', [
+      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 37, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_YIELD_EACH,
+          37, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/fasta/ast_builder_test.dart b/pkg/analyzer/test/src/fasta/ast_builder_test.dart
index 7d2d005..356122e 100644
--- a/pkg/analyzer/test/src/fasta/ast_builder_test.dart
+++ b/pkg/analyzer/test/src/fasta/ast_builder_test.dart
@@ -7,7 +7,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../generated/parser_fasta_test.dart';
+import '../../generated/parser_test_base.dart';
 
 main() {
   defineReflectiveSuite(() {
diff --git a/pkg/analyzer/test/src/fasta/message_coverage_test.dart b/pkg/analyzer/test/src/fasta/message_coverage_test.dart
index 73a7fac..11f9a85 100644
--- a/pkg/analyzer/test/src/fasta/message_coverage_test.dart
+++ b/pkg/analyzer/test/src/fasta/message_coverage_test.dart
@@ -12,7 +12,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 import 'package:yaml/yaml.dart';
 
-import '../../generated/parser_fasta_test.dart';
+import '../../generated/parser_test_base.dart';
 
 main() {
   defineReflectiveSuite(() {
diff --git a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
index b00f377..a335ee4 100644
--- a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
@@ -9,7 +9,7 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:test/test.dart';
 
-import '../../../generated/parser_fasta_test.dart';
+import '../../../generated/parser_test_base.dart';
 import '../../../generated/test_support.dart';
 
 /// The base class for tests that test how well the parser recovers from various
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index b155619..0b22124 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -1988,8 +1988,8 @@
       _getDeclaration(library.declarations, 'd'),
       'd',
       DeclarationKind.FUNCTION,
-      defaultArgumentListString: 'a, c: null, d: null',
-      defaultArgumentListTextRanges: [0, 1, 6, 4, 15, 4],
+      defaultArgumentListString: 'a, c: c, d: d',
+      defaultArgumentListTextRanges: [0, 1, 6, 1, 12, 1],
       parameters: '(int a, {int b, @required int c, @required int d, int e})',
       parameterNames: ['a', 'b', 'c', 'd', 'e'],
       parameterTypes: ['int', 'int', 'int', 'int', 'int'],
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index d225f1a..b4af040 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -57,7 +57,6 @@
   bool withSyntheticFields = false,
   bool withTypes = false,
   bool withTypeParameterVariance = false,
-  bool annotateNullability = false,
 }) {
   var writer = _ElementWriter(
     selfUriStr: '${library.source.uri}',
@@ -70,7 +69,6 @@
     withSyntheticFields: withSyntheticFields,
     withTypes: withTypes,
     withTypeParameterVariance: withTypeParameterVariance,
-    annotateNullability: annotateNullability,
   );
   writer.writeLibraryElement(library);
 
@@ -140,7 +138,6 @@
   final bool withSyntheticFields;
   final bool withTypes;
   final bool withTypeParameterVariance;
-  final bool annotateNullability;
   final StringBuffer buffer = StringBuffer();
 
   String indent = '';
@@ -156,7 +153,6 @@
     this.withSyntheticFields = false,
     this.withTypes = false,
     this.withTypeParameterVariance,
-    this.annotateNullability = false,
   });
 
   bool isDynamicType(DartType type) => type is DynamicTypeImpl;
@@ -305,16 +301,17 @@
     var initializers = (e as ConstructorElementImpl).constantInitializers;
     if (withFullyResolvedAst) {
       buffer.writeln(';');
-      if (initializers != null && initializers.isNotEmpty) {
-        _withIndent(() {
+      _withIndent(() {
+        if (initializers != null && initializers.isNotEmpty) {
           _writelnWithIndent('constantInitializers');
           _withIndent(() {
             for (var initializer in initializers) {
               _writeResolvedNode(initializer);
             }
           });
-        });
-      }
+        }
+        _writeParameterElementDefaultValues(e.parameters);
+      });
     } else {
       if (initializers != null) {
         writeList(' : ', '', initializers, ', ', writeNode);
@@ -411,6 +408,12 @@
     writeBodyModifiers(e);
 
     buffer.writeln(' {}');
+
+    if (withFullyResolvedAst) {
+      _withIndent(() {
+        _writeParameterElementDefaultValues(e.parameters);
+      });
+    }
   }
 
   void writeIf(bool flag, String str) {
@@ -534,6 +537,7 @@
       _withIndent(() {
         _writeResolvedTypeParameters(e.typeParameters);
         _writeResolvedMetadata(e.metadata);
+        _writeParameterElementDefaultValues(e.parameters);
       });
     }
   }
@@ -832,15 +836,17 @@
     writeName(e);
     writeCodeRange(e);
 
-    if (e.parameters.isNotEmpty) {
-      buffer.write('/*');
-      writeList('(', ')', e.parameters, ', ', writeParameterElement);
-      buffer.write('*/');
-    }
+    if (!withFullyResolvedAst) {
+      if (e.parameters.isNotEmpty) {
+        buffer.write('/*');
+        writeList('(', ')', e.parameters, ', ', writeParameterElement);
+        buffer.write('*/');
+      }
 
-    if (defaultValue != null) {
-      buffer.write(defaultValueSeparator);
-      writeNode(defaultValue);
+      if (defaultValue != null) {
+        buffer.write(defaultValueSeparator);
+        writeNode(defaultValue);
+      }
     }
 
     buffer.write(closeString);
@@ -1176,7 +1182,7 @@
 
   String _typeStr(DartType type) {
     return type?.getDisplayString(
-      withNullability: annotateNullability,
+      withNullability: true,
     );
   }
 
@@ -1198,6 +1204,30 @@
     buffer.writeln(line);
   }
 
+  void _writeParameterElementDefaultValues(
+    List<ParameterElement> parameters, {
+    String enclosingNames = '',
+  }) {
+    for (var parameter in parameters) {
+      if (parameter is DefaultParameterElementImpl) {
+        var defaultValue = parameter.constantInitializer;
+        if (defaultValue != null) {
+          _writelnWithIndent(enclosingNames + parameter.name);
+          _withIndent(() {
+            _writeResolvedNode(defaultValue);
+          });
+        }
+      }
+      var subParameters = parameter.parameters;
+      _withIndent(() {
+        _writeParameterElementDefaultValues(
+          subParameters,
+          enclosingNames: enclosingNames + parameter.name + '::',
+        );
+      });
+    }
+  }
+
   void _writeResolvedMetadata(List<ElementAnnotation> metadata) {
     if (metadata.isNotEmpty) {
       _writelnWithIndent('metadata');
@@ -1216,7 +1246,7 @@
         selfUriStr: selfUriStr,
         sink: buffer,
         indent: indent,
-        withNullability: annotateNullability,
+        withNullability: true,
       ),
     );
   }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index aab0156..1627018 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -122,7 +122,7 @@
   }
 
   void setUp() {
-    featureSet = FeatureSets.beforeNullSafe;
+    featureSet = FeatureSets.nullSafe;
   }
 
   void _addLibraryUnits(
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 7ff0b3a..d690b6c 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -927,7 +927,6 @@
   }
 
   test_class_field_const_late() async {
-    featureSet = FeatureSets.nullSafe;
     var library =
         await checkLibrary('class C { static late const int i = 0; }');
     checkElementText(library, r'''
@@ -947,7 +946,6 @@
   }
 
   test_class_field_implicit_type_late() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('class C { late var x; }');
     checkElementText(library, r'''
 class C {
@@ -966,7 +964,6 @@
   }
 
   test_class_field_static_late() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('class C { static late int i; }');
     checkElementText(library, r'''
 class C {
@@ -986,7 +983,6 @@
   }
 
   test_class_fields_late() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class C {
   late int foo;
@@ -1005,7 +1001,6 @@
   }
 
   test_class_fields_late_final() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class C {
   late final int foo;
@@ -1024,7 +1019,6 @@
   }
 
   test_class_fields_late_final_initialized() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class C {
   late final int foo = 0;
@@ -1320,7 +1314,7 @@
 ''');
   }
 
-  test_class_notSimplyBounded_complex_by_cycle() async {
+  test_class_notSimplyBounded_complex_by_cycle_class() async {
     var library = await checkLibrary('''
 class C<T extends D> {}
 class D<T extends C> {}
@@ -1333,6 +1327,29 @@
 ''');
   }
 
+  test_class_notSimplyBounded_complex_by_cycle_typedef_functionType() async {
+    var library = await checkLibrary('''
+typedef C<T extends D> = void Function();
+typedef D<T extends C> = void Function();
+''');
+    checkElementText(library, r'''
+notSimplyBounded typedef C<T extends dynamic Function()> = void Function();
+notSimplyBounded typedef D<T extends dynamic Function()> = void Function();
+''');
+  }
+
+  test_class_notSimplyBounded_complex_by_cycle_typedef_interfaceType() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary('''
+typedef C<T extends D> = List<T>;
+typedef D<T extends C> = List<T>;
+''');
+    checkElementText(library, r'''
+notSimplyBounded typedef C<T extends dynamic> = List<T>;
+notSimplyBounded typedef D<T extends dynamic> = List<T>;
+''');
+  }
+
   test_class_notSimplyBounded_complex_by_reference_to_cycle() async {
     var library = await checkLibrary('''
 class C<T extends D> {}
@@ -1379,7 +1396,18 @@
 class C<T extends void Function(T)> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends void Function(T) = void Function(Null)> {
+notSimplyBounded class C<T extends void Function(T) = void Function(Never)> {
+}
+''');
+  }
+
+  test_class_notSimplyBounded_function_typed_bound_complex_via_parameter_type_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
+    var library = await checkLibrary('''
+class C<T extends void Function(T)> {}
+''');
+    checkElementText(library, r'''
+notSimplyBounded class C<T extends void Function(T*)* = void Function(Null*)*> {
 }
 ''');
   }
@@ -1469,35 +1497,27 @@
   }
 
   test_class_ref_nullability_none() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class C {}
 C c;
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 class C {
 }
 C c;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_class_ref_nullability_question() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class C {}
 C? c;
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 class C {
 }
 C? c;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_class_ref_nullability_star() async {
@@ -1506,14 +1526,11 @@
 class C {}
 C c;
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 class C {
 }
 C* c;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_class_setter_abstract() async {
@@ -1736,51 +1753,8 @@
 ''');
   }
 
-  test_class_type_parameters_variance_contravariant() async {
-    var library = await checkLibrary('class C<in T> {}');
-    checkElementText(
-        library,
-        r'''
-class C<contravariant T> {
-}
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_class_type_parameters_variance_covariant() async {
-    var library = await checkLibrary('class C<out T> {}');
-    checkElementText(
-        library,
-        r'''
-class C<covariant T> {
-}
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_class_type_parameters_variance_invariant() async {
-    var library = await checkLibrary('class C<inout T> {}');
-    checkElementText(
-        library,
-        r'''
-class C<invariant T> {
-}
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_class_type_parameters_variance_multiple() async {
-    var library = await checkLibrary('class C<inout T, in U, out V> {}');
-    checkElementText(
-        library,
-        r'''
-class C<invariant T, contravariant U, covariant V> {
-}
-''',
-        withTypeParameterVariance: true);
-  }
-
   test_class_typeParameters_defaultType_functionTypeAlias_contravariant_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
     var library = await checkLibrary(r'''
 typedef F<X> = void Function(X);
 
@@ -1789,15 +1763,14 @@
     checkElementText(
         library,
         r'''
-typedef F<contravariant X> = void Function(X );
-notSimplyBounded class A<covariant X extends void Function(X) = void Function(Null)> {
+typedef F<contravariant X> = void Function(X* );
+notSimplyBounded class A<covariant X extends void Function(X*)* = void Function(Null*)*> {
 }
 ''',
         withTypeParameterVariance: true);
   }
 
   test_class_typeParameters_defaultType_functionTypeAlias_contravariant_nullSafe() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 typedef F<X> = void Function(X);
 
@@ -1813,6 +1786,22 @@
         withTypeParameterVariance: true);
   }
 
+  test_class_typeParameters_defaultType_functionTypeAlias_covariant_nullSafe() async {
+    var library = await checkLibrary(r'''
+typedef F<X> = X Function();
+
+class A<X extends F<X>> {}
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<covariant X> = X Function();
+notSimplyBounded class A<covariant X extends X Function() = dynamic Function()> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
   test_class_typeParameters_defaultType_functionTypeAlias_invariant_legacy() async {
     var library = await checkLibrary(r'''
 typedef F<X> = X Function(X);
@@ -1830,7 +1819,6 @@
   }
 
   test_class_typeParameters_defaultType_functionTypeAlias_invariant_nullSafe() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 typedef F<X> = X Function(X);
 
@@ -1847,17 +1835,17 @@
   }
 
   test_class_typeParameters_defaultType_genericFunctionType_both_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
     var library = await checkLibrary(r'''
 class A<X extends X Function(X)> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class A<X extends X Function(X) = dynamic Function(Null)> {
+notSimplyBounded class A<X extends X* Function(X*)* = dynamic Function(Null*)*> {
 }
 ''');
   }
 
   test_class_typeParameters_defaultType_genericFunctionType_both_nullSafe() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 class A<X extends X Function(X)> {}
 ''');
@@ -1868,17 +1856,17 @@
   }
 
   test_class_typeParameters_defaultType_genericFunctionType_contravariant_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
     var library = await checkLibrary(r'''
 class A<X extends void Function(X)> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class A<X extends void Function(X) = void Function(Null)> {
+notSimplyBounded class A<X extends void Function(X*)* = void Function(Null*)*> {
 }
 ''');
   }
 
   test_class_typeParameters_defaultType_genericFunctionType_contravariant_nullSafe() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 class A<X extends void Function(X)> {}
 ''');
@@ -1899,7 +1887,6 @@
   }
 
   test_class_typeParameters_defaultType_genericFunctionType_covariant_nullSafe() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 class A<X extends X Function()> {}
 ''');
@@ -1909,6 +1896,84 @@
 ''');
   }
 
+  test_class_typeParameters_defaultType_typeAlias_interface_contravariant() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A<X> = List<void Function(X)>;
+
+class B<X extends A<X>> {}
+''');
+    checkElementText(
+        library,
+        r'''
+typedef A<contravariant X> = List<void Function(X)>;
+notSimplyBounded class B<covariant X extends List<void Function(X)> = List<void Function(Never)>> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_defaultType_typeAlias_interface_covariant() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A<X> = Map<X, int>;
+
+class B<X extends A<X>> {}
+''');
+    checkElementText(
+        library,
+        r'''
+typedef A<covariant X> = Map<X, int>;
+notSimplyBounded class B<covariant X extends Map<X, int> = Map<dynamic, int>> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_variance_contravariant() async {
+    var library = await checkLibrary('class C<in T> {}');
+    checkElementText(
+        library,
+        r'''
+class C<contravariant T> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_variance_covariant() async {
+    var library = await checkLibrary('class C<out T> {}');
+    checkElementText(
+        library,
+        r'''
+class C<covariant T> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_variance_invariant() async {
+    var library = await checkLibrary('class C<inout T> {}');
+    checkElementText(
+        library,
+        r'''
+class C<invariant T> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_variance_multiple() async {
+    var library = await checkLibrary('class C<inout T, in U, out V> {}');
+    checkElementText(
+        library,
+        r'''
+class C<invariant T, contravariant U, covariant V> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
   test_classes() async {
     var library = await checkLibrary('class C {} class D {}');
     checkElementText(library, r'''
@@ -2714,7 +2779,6 @@
   }
 
   test_compilationUnit_nnbd_disabled_via_dart_directive() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 // @dart=2.2
 ''');
@@ -2728,13 +2792,11 @@
   }
 
   test_compilationUnit_nnbd_enabled() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('');
     expect(library.isNonNullableByDefault, isTrue);
   }
 
   test_const_asExpression() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 const num a = 0;
 const b = a as int;
@@ -2748,7 +2810,6 @@
   }
 
   test_const_assignmentExpression() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 const a = 0;
 const b = (a += 1);
@@ -2781,13 +2842,11 @@
         writeType: dynamic
       staticType: int
 ''',
-      annotateNullability: true,
       withFullyResolvedAst: true,
     );
   }
 
   test_const_cascadeExpression() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 const a = 0..isEven..abs();
 ''');
@@ -2819,7 +2878,6 @@
         literal: 0
         staticType: int
 ''',
-      annotateNullability: true,
       withFullyResolvedAst: true,
     );
   }
@@ -2897,7 +2955,6 @@
   }
 
   test_const_indexExpression() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 const a = [0];
 const b = 0;
@@ -2935,7 +2992,6 @@
         staticType: List<int>
         token: a
 ''',
-      annotateNullability: true,
       withFullyResolvedAst: true,
     );
   }
@@ -3403,7 +3459,6 @@
   }
 
   test_const_isExpression() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 const a = 0;
 const b = a is int;
@@ -3691,7 +3746,6 @@
   }
 
   test_const_methodInvocation() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 T f<T>(T a) => a;
 const b = f<int>(0);
@@ -3723,7 +3777,6 @@
             type: int
 T f(T a) {}
 ''',
-      annotateNullability: true,
       withFullyResolvedAst: true,
     );
   }
@@ -3800,7 +3853,6 @@
   }
 
   test_const_postfixExpression_increment() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 const a = 0;
 const b = a++;
@@ -3828,13 +3880,11 @@
       writeElement: self::@getter::a
       writeType: dynamic
 ''',
-      annotateNullability: true,
       withFullyResolvedAst: true,
     );
   }
 
   test_const_postfixExpression_nullCheck() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 const int? a = 0;
 const b = a!;
@@ -3858,13 +3908,11 @@
       staticElement: <null>
       staticType: int
 ''',
-      annotateNullability: true,
       withFullyResolvedAst: true,
     );
   }
 
   test_const_prefixExpression_increment() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 const a = 0;
 const b = ++a;
@@ -3892,7 +3940,6 @@
       writeElement: self::@getter::a
       writeType: dynamic
 ''',
-      annotateNullability: true,
       withFullyResolvedAst: true,
     );
   }
@@ -4459,7 +4506,6 @@
   }
 
   test_const_topLevel_nullSafe_nullAware_propertyAccess() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 const String? a = '';
 
@@ -4467,13 +4513,30 @@
   a?.length,
 ];
 ''');
-    // TODO(scheglov) include fully resolved AST, when types with suffixes
-    checkElementText(library, r'''
-const String a = '';
-const List<int> b = [
-        a/*location: test.dart;a?*/.
-        length/*location: dart:core;String;length?*/];
-''');
+    checkElementText(
+        library,
+        r'''
+const String? a;
+  constantInitializer
+    SimpleStringLiteral
+      literal: ''
+const List<int?> b;
+  constantInitializer
+    ListLiteral
+      elements
+        PropertyAccess
+          propertyName: SimpleIdentifier
+            staticElement: dart:core::@class::String::@getter::length
+            staticType: int
+            token: length
+          staticType: int?
+          target: SimpleIdentifier
+            staticElement: self::@getter::a
+            staticType: String?
+            token: a
+      staticType: List<int?>
+''',
+        withFullyResolvedAst: true);
   }
 
   test_const_topLevel_parenthesis() async {
@@ -4528,6 +4591,16 @@
 const c = throw 42;
 ''');
     checkElementText(library, r'''
+const Never c = throw 42;
+''');
+  }
+
+  test_const_topLevel_throw_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
+    var library = await checkLibrary(r'''
+const c = throw 42;
+''');
+    checkElementText(library, r'''
 const dynamic c = throw 42;
 ''');
   }
@@ -4832,7 +4905,7 @@
         r'''
 class A {
   final int _f;
-  const A([int f = 0]);
+  const A([int f]);
     constantInitializers
       ConstructorFieldInitializer
         equals: =
@@ -4844,6 +4917,10 @@
           staticElement: self::@class::A::@field::_f
           staticType: null
           token: _f
+    f
+      IntegerLiteral
+        literal: 0
+        staticType: int
 }
 ''',
         withFullyResolvedAst: true);
@@ -5115,6 +5192,30 @@
 ''');
   }
 
+  test_constructor_redirected_factory_named_generic_viaTypeAlias() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary('''
+typedef A<T, U> = C<T, U>;
+class B<T, U> {
+  factory B() = A<U, T>.named;
+  B._();
+}
+class C<T, U> extends A<U, T> {
+  C.named() : super._();
+}
+''');
+    checkElementText(library, r'''
+typedef A<T, U> = C<T, U>;
+class B<T, U> {
+  factory B() = C<U, T>.named;
+  B._();
+}
+class C<T, U> extends C<U, T> {
+  C.named();
+}
+''');
+  }
+
   test_constructor_redirected_factory_named_imported() async {
     addLibrarySource('/foo.dart', '''
 import 'test.dart';
@@ -5278,6 +5379,30 @@
 ''');
   }
 
+  test_constructor_redirected_factory_unnamed_generic_viaTypeAlias() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary('''
+typedef A<T, U> = C<T, U>;
+class B<T, U> {
+  factory B() = A<U, T>;
+  B_();
+}
+class C<T, U> extends B<U, T> {
+  C() : super._();
+}
+''');
+    checkElementText(library, r'''
+typedef A<T, U> = C<T, U>;
+class B<T, U> {
+  factory B() = C<U, T>;
+  dynamic B_();
+}
+class C<T, U> extends B<U, T> {
+  C();
+}
+''');
+  }
+
   test_constructor_redirected_factory_unnamed_imported() async {
     addLibrarySource('/foo.dart', '''
 import 'test.dart';
@@ -5324,6 +5449,31 @@
 ''');
   }
 
+  test_constructor_redirected_factory_unnamed_imported_viaTypeAlias() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    addLibrarySource('/foo.dart', '''
+import 'test.dart';
+typedef A = B;
+class B extends C {
+  B() : super._();
+}
+''');
+    var library = await checkLibrary('''
+import 'foo.dart';
+class C {
+  factory C() = A;
+  C._();
+}
+''');
+    checkElementText(library, r'''
+import 'foo.dart';
+class C {
+  factory C() = B;
+  C._();
+}
+''');
+  }
+
   test_constructor_redirected_factory_unnamed_prefixed() async {
     addLibrarySource('/foo.dart', '''
 import 'test.dart';
@@ -5370,6 +5520,31 @@
 ''');
   }
 
+  test_constructor_redirected_factory_unnamed_prefixed_viaTypeAlias() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    addLibrarySource('/foo.dart', '''
+import 'test.dart';
+typedef A = B;
+class B extends C {
+  B() : super._();
+}
+''');
+    var library = await checkLibrary('''
+import 'foo.dart' as foo;
+class C {
+  factory C() = foo.A;
+  C._();
+}
+''');
+    checkElementText(library, r'''
+import 'foo.dart' as foo;
+class C {
+  factory C() = B;
+  C._();
+}
+''');
+  }
+
   test_constructor_redirected_factory_unnamed_unresolved() async {
     var library = await checkLibrary('''
 class C<E> {
@@ -5383,6 +5558,30 @@
 ''');
   }
 
+  test_constructor_redirected_factory_unnamed_viaTypeAlias() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary('''
+typedef A = C;
+class B {
+  factory B() = A;
+  B._();
+}
+class C extends B {
+  C() : super._();
+}
+''');
+    checkElementText(library, r'''
+typedef A = C;
+class B {
+  factory B() = C;
+  B._();
+}
+class C extends B {
+  C();
+}
+''');
+  }
+
   test_constructor_redirected_thisInvocation_named() async {
     var library = await checkLibrary('''
 class C {
@@ -5526,7 +5725,6 @@
   }
 
   test_defaultValue_eliminateTypeParameters() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class A<T> {
   const X({List<T> a = const []});
@@ -5543,6 +5741,7 @@
   }
 
   test_defaultValue_eliminateTypeParameters_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
     var library = await checkLibrary('''
 class A<T> {
   const X({List<T> a = const []});
@@ -5552,7 +5751,7 @@
         library,
         r'''
 class A<T> {
-  dynamic X({List<T> a: const /*typeArgs=Null*/[]});
+  dynamic X({List<T*>* a: const /*typeArgs=Null**/[]});
 }
 ''',
         withTypes: true);
@@ -5600,6 +5799,30 @@
 ''');
   }
 
+  test_defaultValue_inFunctionTypedFormalParameter() async {
+    var library = await checkLibrary('''
+void f( g({a: 0 is int}) ) {}
+''');
+    checkElementText(
+        library,
+        r'''
+void f(dynamic Function({dynamic a}) g) {}
+    g::a
+      IsExpression
+        expression: IntegerLiteral
+          literal: 0
+          staticType: int
+        staticType: bool
+        type: TypeName
+          name: SimpleIdentifier
+            staticElement: dart:core::@class::int
+            staticType: null
+            token: int
+          type: int
+''',
+        withFullyResolvedAst: true);
+  }
+
   test_defaultValue_refersToExtension_method_inside() async {
     var library = await checkLibrary('''
 class A {}
@@ -5658,7 +5881,7 @@
   const B();
 }
 class C<T> {
-  const C([B<T> b = const /*typeArgs=Null*/
+  const C([B<T> b = const /*typeArgs=Never*/
         B/*location: test.dart;B*/()]);
 }
 ''',
@@ -5684,7 +5907,58 @@
   const B();
 }
 class C<T> implements A<Iterable<T>> {
-  const C([A<T> a = const /*typeArgs=Null*/
+  const C([A<T> a = const /*typeArgs=Never*/
+        B/*location: test.dart;B*/()]);
+}
+''',
+        withTypes: true);
+  }
+
+  test_defaultValue_refersToGenericClass_constructor2_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
+    var library = await checkLibrary('''
+abstract class A<T> {}
+class B<T> implements A<T> {
+  const B();
+}
+class C<T> implements A<Iterable<T>> {
+  const C([A<T> a = const B()]);
+}
+''');
+    checkElementText(
+        library,
+        r'''
+abstract class A<T> {
+}
+class B<T> implements A<T*>* {
+  const B();
+}
+class C<T> implements A<Iterable<T*>*>* {
+  const C([A<T*>* a = const /*typeArgs=Null**/
+        B/*location: test.dart;B*/()]);
+}
+''',
+        withTypes: true);
+  }
+
+  test_defaultValue_refersToGenericClass_constructor_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
+    var library = await checkLibrary('''
+class B<T> {
+  const B();
+}
+class C<T> {
+  const C([B<T> b = const B()]);
+}
+''');
+    checkElementText(
+        library,
+        r'''
+class B<T> {
+  const B();
+}
+class C<T> {
+  const C([B<T*>* b = const /*typeArgs=Null**/
         B/*location: test.dart;B*/()]);
 }
 ''',
@@ -5704,7 +5978,7 @@
 class B<T> {
   const B();
 }
-void foo<T>([B<T> b = const /*typeArgs=Null*/
+void foo<T>([B<T> b = const /*typeArgs=Never*/
         B/*location: test.dart;B*/()]) {}
 ''',
         withTypes: true);
@@ -5726,7 +6000,7 @@
   const B();
 }
 class C {
-  void foo<T>([B<T> b = const /*typeArgs=Null*/
+  void foo<T>([B<T> b = const /*typeArgs=Never*/
         B/*location: test.dart;B*/()]) {}
 }
 ''',
@@ -5749,7 +6023,7 @@
   const B();
 }
 class C<E1> {
-  void foo<E2>([B<E1, E2> b = const /*typeArgs=Null,Null*/
+  void foo<E2>([B<E1, E2> b = const /*typeArgs=Never,Never*/
         B/*location: test.dart;B*/()]) {}
 }
 ''',
@@ -5772,7 +6046,7 @@
   const B();
 }
 class C<T> {
-  void foo([B<T> b = const /*typeArgs=Null*/
+  void foo([B<T> b = const /*typeArgs=Never*/
         B/*location: test.dart;B*/()]) {}
 }
 ''',
@@ -6532,7 +6806,6 @@
   }
 
   test_field_abstract() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 abstract class C {
   abstract int i;
@@ -6576,7 +6849,6 @@
   }
 
   test_field_external() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 abstract class C {
   external int i;
@@ -6817,26 +7089,20 @@
   }
 
   test_field_type_inferred_Never() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 class C {
   var a = throw 42;
 }
 ''');
 
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 class C {
   Never a;
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_field_type_inferred_nonNullify() async {
-    featureSet = FeatureSets.nullSafe;
-
     addSource('/a.dart', '''
 // @dart = 2.7
 var a = 0;
@@ -6849,15 +7115,12 @@
 }
 ''');
 
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 class C {
   int b;
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_field_typed() async {
@@ -7124,14 +7387,14 @@
 ''');
     var unit = library.definingCompilationUnit;
 
-    var F = unit.functionTypeAliases[0];
+    var F = unit.typeAliases[0];
     expect(F.name, 'F');
 
     var T = F.typeParameters[0];
     expect(T.name, 'T');
     expect(T.enclosingElement, same(F));
 
-    var function = F.function;
+    var function = F.aliasedElement as GenericFunctionTypeElement;
     expect(function.enclosingElement, same(F));
 
     var a = function.parameters[0];
@@ -7146,8 +7409,13 @@
 ''');
     var unit = library.definingCompilationUnit;
     var type = unit.topLevelVariables[0].type as FunctionType;
-    expect(type.element.enclosingElement, same(unit.functionTypeAliases[0]));
-    _assertTypeStrings(type.typeArguments, ['int*']);
+
+    expect(type.aliasElement, same(unit.typeAliases[0]));
+    _assertTypeStrings(type.aliasArguments, ['int']);
+
+    // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
+    expect(type.element.enclosingElement, same(unit.typeAliases[0]));
+    _assertTypeStrings(type.typeArguments, ['int']);
   }
 
   test_functionTypeAlias_typeParameters_variance_contravariant() async {
@@ -7330,29 +7598,21 @@
   }
 
   test_generic_function_type_nullability_none() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 void Function() f;
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 void Function() f;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_generic_function_type_nullability_question() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 void Function()? f;
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 void Function()? f;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_generic_function_type_nullability_star() async {
@@ -7360,12 +7620,9 @@
     var library = await checkLibrary('''
 void Function() f;
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 void Function()* f;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_generic_gClass_gMethodStatic() async {
@@ -7459,14 +7716,14 @@
 ''');
     var unit = library.definingCompilationUnit;
 
-    var F = unit.functionTypeAliases[0];
+    var F = unit.typeAliases[0];
     expect(F.name, 'F');
 
     var T = F.typeParameters[0];
     expect(T.name, 'T');
     expect(T.enclosingElement, same(F));
 
-    var function = F.function;
+    var function = F.aliasedElement as GenericFunctionTypeElement;
     expect(function.enclosingElement, same(F));
 
     var U = function.typeParameters[0];
@@ -7487,122 +7744,6 @@
 ''');
   }
 
-  test_genericTypeAlias_typeParameters_variance_contravariant() async {
-    var library = await checkLibrary(r'''
-typedef F<T> = void Function(T);
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F<contravariant T> = void Function(T );
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_genericTypeAlias_typeParameters_variance_contravariant2() async {
-    var library = await checkLibrary(r'''
-typedef F1<T> = void Function(T);
-typedef F2<T> = F1<T> Function();
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F1<contravariant T> = void Function(T );
-typedef F2<contravariant T> = void Function(T) Function();
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_genericTypeAlias_typeParameters_variance_covariant() async {
-    var library = await checkLibrary(r'''
-typedef F<T> = T Function();
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F<covariant T> = T Function();
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_genericTypeAlias_typeParameters_variance_covariant2() async {
-    var library = await checkLibrary(r'''
-typedef F<T> = List<T> Function();
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F<covariant T> = List<T> Function();
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_genericTypeAlias_typeParameters_variance_covariant3() async {
-    var library = await checkLibrary(r'''
-typedef F1<T> = T Function();
-typedef F2<T> = F1<T> Function();
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F1<covariant T> = T Function();
-typedef F2<covariant T> = T Function() Function();
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_genericTypeAlias_typeParameters_variance_covariant4() async {
-    var library = await checkLibrary(r'''
-typedef F1<T> = void Function(T);
-typedef F2<T> = void Function(F1<T>);
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F1<contravariant T> = void Function(T );
-typedef F2<covariant T> = void Function(void Function(T) );
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_genericTypeAlias_typeParameters_variance_invariant() async {
-    var library = await checkLibrary(r'''
-typedef F<T> = T Function(T);
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F<invariant T> = T Function(T );
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_genericTypeAlias_typeParameters_variance_invariant2() async {
-    var library = await checkLibrary(r'''
-typedef F1<T> = T Function();
-typedef F2<T> = F1<T> Function(T);
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F1<covariant T> = T Function();
-typedef F2<invariant T> = T Function() Function(T );
-''',
-        withTypeParameterVariance: true);
-  }
-
-  test_genericTypeAlias_typeParameters_variance_unrelated() async {
-    var library = await checkLibrary(r'''
-typedef F<T> = void Function(int);
-''');
-    checkElementText(
-        library,
-        r'''
-typedef F<unrelated T> = void Function(int );
-''',
-        withTypeParameterVariance: true);
-  }
-
   test_getter_documented() async {
     var library = await checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -8209,7 +8350,6 @@
   }
 
   test_inferred_type_functionExpressionInvocation_oppositeOrder() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class A {
   static final foo = bar(1.2);
@@ -8258,67 +8398,51 @@
   }
 
   test_inferred_type_nullability_class_ref_none() async {
-    featureSet = FeatureSets.nullSafe;
     addSource('/a.dart', 'int f() => 0;');
     var library = await checkLibrary('''
 import 'a.dart';
 var x = f();
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 int x;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_inferred_type_nullability_class_ref_question() async {
-    featureSet = FeatureSets.nullSafe;
     addSource('/a.dart', 'int? f() => 0;');
     var library = await checkLibrary('''
 import 'a.dart';
 var x = f();
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 int? x;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_inferred_type_nullability_function_type_none() async {
-    featureSet = FeatureSets.nullSafe;
     addSource('/a.dart', 'void Function() f() => () {};');
     var library = await checkLibrary('''
 import 'a.dart';
 var x = f();
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 void Function() x;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_inferred_type_nullability_function_type_question() async {
-    featureSet = FeatureSets.nullSafe;
     addSource('/a.dart', 'void Function()? f() => () {};');
     var library = await checkLibrary('''
 import 'a.dart';
 var x = f();
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 void Function()? x;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_inferred_type_refers_to_bound_type_param() async {
@@ -8631,6 +8755,7 @@
   }
 
   test_instanceInference_operator_equal_legacy_from_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
     addLibrarySource('/legacy.dart', r'''
 // @dart = 2.7
 class LegacyDefault {
@@ -8655,9 +8780,7 @@
   bool operator==(other) => false;
 }
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'legacy.dart';
 class X1 extends LegacyDefault* {
   bool* ==(dynamic other) {}
@@ -8668,12 +8791,10 @@
 class X3 extends LegacyInt* {
   bool* ==(int* other) {}
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_instanceInference_operator_equal_legacy_from_legacy_nullSafe() async {
-    featureSet = FeatureSets.nullSafe;
     addLibrarySource('/legacy.dart', r'''
 // @dart = 2.7
 class LegacyDefault {
@@ -8711,9 +8832,7 @@
   bool operator==(other) => false;
 }
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'legacy.dart';
 import 'nullSafe.dart';
 class X1 extends LegacyDefault* implements NullSafeDefault* {
@@ -8725,12 +8844,10 @@
 class X3 extends LegacyInt* implements NullSafeInt* {
   bool* ==(int* other) {}
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_instanceInference_operator_equal_nullSafe_from_nullSafe() async {
-    featureSet = FeatureSets.nullSafe;
     addLibrarySource('/nullSafe.dart', r'''
 class NullSafeDefault {
   bool operator==(other) => false;
@@ -8754,9 +8871,7 @@
   bool operator==(other) => false;
 }
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'nullSafe.dart';
 class X1 extends NullSafeDefault {
   bool ==(Object other) {}
@@ -8767,8 +8882,7 @@
 class X3 extends NullSafeInt {
   bool ==(int other) {}
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_instantiateToBounds_boundRefersToEarlierTypeArgument() async {
@@ -8796,10 +8910,31 @@
 notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 class B {
-  C<C<dynamic>> c3;
+  C<C<Object?>> c3;
 }
 C<C<dynamic>> c;
-C<C<dynamic>> c2;
+C<C<Object?>> c2;
+''');
+  }
+
+  test_instantiateToBounds_boundRefersToItself_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
+    var library = await checkLibrary('''
+class C<T extends C<T>> {}
+C c;
+var c2 = new C();
+class B {
+  var c3 = new C();
+}
+''');
+    checkElementText(library, r'''
+notSimplyBounded class C<T extends C<T*>* = C<dynamic>*> {
+}
+class B {
+  C<C<dynamic>*>* c3;
+}
+C<C<dynamic>*>* c;
+C<C<dynamic>*>* c2;
 ''');
   }
 
@@ -9495,6 +9630,62 @@
 ''');
   }
 
+  test_metadata_constructor_call_named_synthetic_ofClassAlias_generic() async {
+    var library = await checkLibrary('''
+class A {
+  const A.named();
+}
+
+mixin B {}
+
+class C<T> = A with B; 
+
+@C.named()
+class D {}
+''');
+    checkElementText(
+        library,
+        r'''
+class A {
+  const A.named();
+}
+class alias C extends A with B {
+  synthetic const C.named() = A.named;
+}
+  typeParameters
+    T
+      bound: null
+      defaultType: dynamic
+class D {
+}
+  metadata
+    Annotation
+      arguments: ArgumentList
+      element: ConstructorMember
+        base: self::@class::C::@constructor::named
+        substitution: {T: dynamic}
+      name: PrefixedIdentifier
+        identifier: SimpleIdentifier
+          staticElement: ConstructorMember
+            base: self::@class::C::@constructor::named
+            substitution: {T: dynamic}
+          staticType: null
+          token: named
+        period: .
+        prefix: SimpleIdentifier
+          staticElement: self::@class::C
+          staticType: null
+          token: C
+        staticElement: ConstructorMember
+          base: self::@class::C::@constructor::named
+          substitution: {T: dynamic}
+        staticType: null
+mixin B on Object {
+}
+''',
+        withFullyResolvedAst: true);
+  }
+
   test_metadata_constructor_call_unnamed() async {
     var library = await checkLibrary('class A { const A(); } @A() class C {}');
     checkElementText(library, r'''
@@ -9522,6 +9713,50 @@
 ''');
   }
 
+  test_metadata_constructor_call_unnamed_synthetic_ofClassAlias_generic() async {
+    var library = await checkLibrary('''
+class A {
+  const A();
+}
+
+mixin B {}
+
+class C<T> = A with B; 
+
+@C()
+class D {}
+''');
+    checkElementText(
+        library,
+        r'''
+class A {
+  const A();
+}
+class alias C extends A with B {
+  synthetic const C() = A;
+}
+  typeParameters
+    T
+      bound: null
+      defaultType: dynamic
+class D {
+}
+  metadata
+    Annotation
+      arguments: ArgumentList
+      element: ConstructorMember
+        base: self::@class::C::@constructor::•
+        substitution: {T: dynamic}
+      name: SimpleIdentifier
+        staticElement: self::@class::C
+        staticType: null
+        token: C
+mixin B on Object {
+}
+''',
+        withFullyResolvedAst: true);
+  }
+
   test_metadata_constructor_call_with_args() async {
     var library =
         await checkLibrary('class A { const A(x); } @A(null) class C {}');
@@ -10349,14 +10584,13 @@
   }
 
   test_mixin_inference_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
     var library = await checkLibrary(r'''
 class A<T> {}
 mixin M<U> on A<U> {}
 class B extends A<int> with M {}
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 class A<T> {
 }
 class B extends A<int*>* with M<int*>* {
@@ -10364,20 +10598,16 @@
 }
 mixin M<U> on A<U*>* {
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_mixin_inference_nullSafety() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 class A<T> {}
 mixin M<U> on A<U> {}
 class B extends A<int> with M {}
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 class A<T> {
 }
 class B extends A<int> with M<int> {
@@ -10385,12 +10615,10 @@
 }
 mixin M<U> on A<U> {
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_mixin_inference_nullSafety2() async {
-    featureSet = FeatureSets.nullSafe;
     addLibrarySource('/a.dart', r'''
 class A<T> {}
 
@@ -10403,19 +10631,15 @@
 
 class D extends A<int> with B<int>, C {}
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 class D extends A<int*>* with B<int*>*, C<int*>* {
   synthetic D();
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_mixin_inference_nullSafety_mixed_inOrder() async {
-    featureSet = FeatureSets.nullSafe;
     addLibrarySource('/a.dart', r'''
 class A<T> {}
 mixin M<U> on A<U> {}
@@ -10425,20 +10649,16 @@
 import 'a.dart';
 class B extends A<int> with M {}
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 class B extends A<int*>* with M<int*>* {
   synthetic B();
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   @FailingTest(reason: 'Out-of-order inference is not specified yet')
   test_mixin_inference_nullSafety_mixed_outOfOrder() async {
-    featureSet = FeatureSets.nullSafe;
     addLibrarySource('/a.dart', r'''
 // @dart = 2.8
 class A<T> {}
@@ -10449,15 +10669,12 @@
 
 class B extends A<int> with M {}
 ''');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 class B extends A<int> with M<int> {
   synthetic B();
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_mixin_method_namedAsConstraint() async {
@@ -10476,7 +10693,7 @@
 ''');
   }
 
-  test_mixin_type_parameters_variance_contravariant() async {
+  test_mixin_typeParameters_variance_contravariant() async {
     var library = await checkLibrary('mixin M<in T> {}');
     checkElementText(
         library,
@@ -10487,7 +10704,7 @@
         withTypeParameterVariance: true);
   }
 
-  test_mixin_type_parameters_variance_covariant() async {
+  test_mixin_typeParameters_variance_covariant() async {
     var library = await checkLibrary('mixin M<out T> {}');
     checkElementText(
         library,
@@ -10498,7 +10715,7 @@
         withTypeParameterVariance: true);
   }
 
-  test_mixin_type_parameters_variance_invariant() async {
+  test_mixin_typeParameters_variance_invariant() async {
     var library = await checkLibrary('mixin M<inout T> {}');
     checkElementText(
         library,
@@ -10509,7 +10726,7 @@
         withTypeParameterVariance: true);
   }
 
-  test_mixin_type_parameters_variance_multiple() async {
+  test_mixin_typeParameters_variance_multiple() async {
     var library = await checkLibrary('mixin M<inout T, in U, out V> {}');
     checkElementText(
         library,
@@ -10665,7 +10882,7 @@
 ''');
   }
 
-  test_new_typedef_notSimplyBounded_functionType_returnType() async {
+  test_new_typedef_function_notSimplyBounded_functionType_returnType() async {
     var library = await checkLibrary('''
 typedef F = G Function();
 typedef G = F Function();
@@ -10676,7 +10893,7 @@
 ''');
   }
 
-  test_new_typedef_notSimplyBounded_functionType_returnType_viaInterfaceType() async {
+  test_new_typedef_function_notSimplyBounded_functionType_returnType_viaInterfaceType() async {
     var library = await checkLibrary('''
 typedef F = List<F> Function();
 ''');
@@ -10685,16 +10902,16 @@
 ''');
   }
 
-  test_new_typedef_notSimplyBounded_self() async {
+  test_new_typedef_function_notSimplyBounded_self() async {
     var library = await checkLibrary('''
 typedef F<T extends F> = void Function();
 ''');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends void Function()> = void Function();
+notSimplyBounded typedef F<T extends dynamic Function()> = void Function();
 ''');
   }
 
-  test_new_typedef_notSimplyBounded_simple_no_bounds() async {
+  test_new_typedef_function_notSimplyBounded_simple_no_bounds() async {
     var library = await checkLibrary('''
 typedef F<T> = void Function();
 ''');
@@ -10703,7 +10920,7 @@
 ''');
   }
 
-  test_new_typedef_notSimplyBounded_simple_non_generic() async {
+  test_new_typedef_function_notSimplyBounded_simple_non_generic() async {
     var library = await checkLibrary('''
 typedef F = void Function();
 ''');
@@ -10712,6 +10929,26 @@
 ''');
   }
 
+  test_new_typedef_nonFunction_notSimplyBounded_self() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary('''
+typedef F<T extends F> = List<int>;
+''');
+    checkElementText(library, r'''
+notSimplyBounded typedef F<T extends dynamic> = List<int>;
+''');
+  }
+
+  test_new_typedef_nonFunction_notSimplyBounded_viaInterfaceType() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary('''
+typedef F = List<F>;
+''');
+    checkElementText(library, r'''
+notSimplyBounded typedef F = List<dynamic>;
+''');
+  }
+
   test_old_typedef_notSimplyBounded_self() async {
     var library = await checkLibrary('''
 typedef void F<T extends F>();
@@ -11262,7 +11499,6 @@
   }
 
   test_top_level_variable_external() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 external int i;
 ''');
@@ -11551,57 +11787,42 @@
   test_type_never_disableNnbd() async {
     featureSet = FeatureSets.beforeNullSafe;
     var library = await checkLibrary('Never d;');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 Null* d;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_type_never_enableNnbd() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('Never d;');
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 Never d;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_type_param_ref_nullability_none() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class C<T> {
   T t;
 }
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 class C<T> {
   T t;
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_type_param_ref_nullability_question() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('''
 class C<T> {
   T? t;
 }
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 class C<T> {
   T? t;
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_type_param_ref_nullability_star() async {
@@ -11611,14 +11832,11 @@
   T t;
 }
 ''');
-    checkElementText(
-        library,
-        '''
+    checkElementText(library, '''
 class C<T> {
   T* t;
 }
-''',
-        annotateNullability: true);
+''');
   }
 
   test_type_reference_lib_to_lib() async {
@@ -11939,6 +12157,207 @@
 ''');
   }
 
+  test_typeAlias_typeParameters_variance_function_contravariant() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = void Function(T);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<contravariant T> = void Function(T );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_contravariant2() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> = void Function(T);
+typedef F2<T> = F1<T> Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<contravariant T> = void Function(T );
+typedef F2<contravariant T> = void Function(T) Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_covariant() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = T Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<covariant T> = T Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_covariant2() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = List<T> Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<covariant T> = List<T> Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_covariant3() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> = T Function();
+typedef F2<T> = F1<T> Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<covariant T> = T Function();
+typedef F2<covariant T> = T Function() Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_covariant4() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> = void Function(T);
+typedef F2<T> = void Function(F1<T>);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<contravariant T> = void Function(T );
+typedef F2<covariant T> = void Function(void Function(T) );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_invalid() async {
+    var library = await checkLibrary(r'''
+class A {}
+typedef F<T> = void Function(A<int>);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<unrelated T> = void Function(A );
+class A {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_invalid2() async {
+    var library = await checkLibrary(r'''
+typedef F = void Function();
+typedef G<T> = void Function(F<int>);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F = void Function();
+typedef G<unrelated T> = void Function(void Function() );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_invariant() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = T Function(T);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<invariant T> = T Function(T );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_invariant2() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> = T Function();
+typedef F2<T> = F1<T> Function(T);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<covariant T> = T Function();
+typedef F2<invariant T> = T Function() Function(T );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_function_unrelated() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = void Function(int);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<unrelated T> = void Function(int );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_interface_contravariant() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A<T> = List<void Function(T)>;
+''');
+    checkElementText(
+        library,
+        r'''
+typedef A<contravariant T> = List<void Function(T)>;
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_interface_contravariant2() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A<T> = void Function(T);
+typedef B<T> = List<A<T>>;
+''');
+    checkElementText(
+        library,
+        r'''
+typedef A<contravariant T> = void Function(T );
+typedef B<contravariant T> = List<void Function(T)>;
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_interface_covariant() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A<T> = List<T>;
+''');
+    checkElementText(
+        library,
+        r'''
+typedef A<covariant T> = List<T>;
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_typeAlias_typeParameters_variance_interface_covariant2() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A<T> = Map<int, T>;
+typedef B<T> = List<A<T>>;
+''');
+    checkElementText(
+        library,
+        r'''
+typedef A<covariant T> = Map<int, T>;
+typedef B<covariant T> = List<Map<int, T>>;
+''',
+        withTypeParameterVariance: true);
+  }
+
   test_typedef_documented() async {
     var library = await checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -11988,7 +12407,6 @@
 ''');
   }
 
-  /// TODO(scheglov) add `?` cases.
   test_typedef_nonFunction_asInterfaceType_interfaceType_none() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
@@ -12005,24 +12423,95 @@
 ''');
   }
 
-  @failingTest
   test_typedef_nonFunction_asInterfaceType_interfaceType_question() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
 typedef X<T> = A<T>?;
 class A<T> {}
-class B implements X<int> {}
+class B {}
+class C {}
+class D implements B, X<int>, C {}
 ''');
     checkElementText(library, r'''
-typedef X<T> = A<int, T>;
-class A<T, U> {
+typedef X<T> = A<T>?;
+class A<T> {
 }
-class B implements A<int, String> {
+class B {
+}
+class C {
+}
+class D implements B, C {
 }
 ''');
   }
 
-  /// TODO(scheglov) add `?` cases.
+  test_typedef_nonFunction_asInterfaceType_interfaceType_question2() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X<T> = A<T?>;
+class A<T> {}
+class B {}
+class C {}
+class D implements B, X<int>, C {}
+''');
+    checkElementText(library, r'''
+typedef X<T> = A<T?>;
+class A<T> {
+}
+class B {
+}
+class C {
+}
+class D implements B, A<int?>, C {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asInterfaceType_Never_none() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = Never;
+class A implements X {}
+''');
+    checkElementText(library, r'''
+typedef X = Never;
+class A {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asInterfaceType_Null_none() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = Null;
+class A implements X {}
+''');
+    checkElementText(library, r'''
+typedef X = Null;
+class A {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asInterfaceType_typeParameterType() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X<T> = T;
+class A {}
+class B {}
+class C<U> implements A, X<U>, B {}
+''');
+    checkElementText(library, r'''
+typedef X<T> = T;
+class A {
+}
+class B {
+}
+class C<U> implements A, B {
+}
+''');
+  }
+
   test_typedef_nonFunction_asInterfaceType_void() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
@@ -12042,8 +12531,7 @@
 ''');
   }
 
-  /// TODO(scheglov) add `?` cases.
-  test_typedef_nonFunction_asMixinType() async {
+  test_typedef_nonFunction_asMixinType_none() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
 typedef X = A<int>;
@@ -12060,8 +12548,66 @@
 ''');
   }
 
-  /// TODO(scheglov) add `?` cases.
-  test_typedef_nonFunction_asSuperType_interfaceType() async {
+  test_typedef_nonFunction_asMixinType_question() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = A<int>?;
+class A<T> {}
+mixin M1 {}
+mixin M2 {}
+class B with M1, X, M2 {}
+''');
+    checkElementText(library, r'''
+typedef X = A<int>?;
+class A<T> {
+}
+class B extends Object with M1, M2 {
+  synthetic B();
+}
+mixin M1 on Object {
+}
+mixin M2 on Object {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asMixinType_question2() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = A<int?>;
+class A<T> {}
+mixin M1 {}
+mixin M2 {}
+class B with M1, X, M2 {}
+''');
+    checkElementText(library, r'''
+typedef X = A<int?>;
+class A<T> {
+}
+class B extends Object with M1, A<int?>, M2 {
+  synthetic B();
+}
+mixin M1 on Object {
+}
+mixin M2 on Object {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asSuperType_interfaceType_Never_none() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = Never;
+class A extends X {}
+''');
+    checkElementText(library, r'''
+typedef X = Never;
+class A {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asSuperType_interfaceType_none() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
 typedef X = A<int>;
@@ -12077,7 +12623,93 @@
 ''');
   }
 
-  /// TODO(scheglov) add `?` cases.
+  test_typedef_nonFunction_asSuperType_interfaceType_none_viaTypeParameter() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X<T> = T;
+class A<T> {}
+class B extends X<A<int>> {}
+''');
+    checkElementText(library, r'''
+typedef X<T> = T;
+class A<T> {
+}
+class B extends A<int> {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asSuperType_interfaceType_Null_none() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = Null;
+class A extends X {}
+''');
+    checkElementText(library, r'''
+typedef X = Null;
+class A {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asSuperType_interfaceType_question() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = A<int>?;
+class A<T> {}
+class D extends X {}
+''');
+    checkElementText(library, r'''
+typedef X = A<int>?;
+class A<T> {
+}
+class D {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asSuperType_interfaceType_question2() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = A<int?>;
+class A<T> {}
+class D extends X {}
+''');
+    checkElementText(library, r'''
+typedef X = A<int?>;
+class A<T> {
+}
+class D extends A<int?> {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asSuperType_Never_none() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = Never;
+class A extends X {}
+''');
+    checkElementText(library, r'''
+typedef X = Never;
+class A {
+}
+''');
+  }
+
+  test_typedef_nonFunction_asSuperType_Null_none() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef X = Null;
+class A extends X {}
+''');
+    checkElementText(library, r'''
+typedef X = Null;
+class A {
+}
+''');
+  }
+
   test_typedef_nonFunction_using_dynamic() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
@@ -12091,7 +12723,6 @@
   }
 
   test_typedef_nonFunction_using_interface_disabled() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 typedef A = int;
 void f(A a) {}
@@ -12118,6 +12749,34 @@
 ''');
   }
 
+  test_typedef_nonFunction_using_interface_noTypeParameters_legacy() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    newFile('/a.dart', content: r'''
+typedef A = List<int>;
+''');
+    var library = await checkLibrary(r'''
+// @dart = 2.9
+import 'a.dart';
+void f(A a) {}
+''');
+    checkElementText(library, r'''
+import 'a.dart';
+void f(List<int*>* a) {}
+''');
+  }
+
+  test_typedef_nonFunction_using_interface_noTypeParameters_question() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A = int?;
+void f(A a) {}
+''');
+    checkElementText(library, r'''
+typedef A = int?;
+void f(int? a) {}
+''');
+  }
+
   test_typedef_nonFunction_using_interface_withTypeParameters() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
@@ -12130,8 +12789,7 @@
 ''');
   }
 
-  /// TODO(scheglov) add `?` cases.
-  test_typedef_nonFunction_using_Never() async {
+  test_typedef_nonFunction_using_Never_none() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
 typedef A = Never;
@@ -12143,8 +12801,19 @@
 ''');
   }
 
-  /// TODO(scheglov) add `?` cases.
-  test_typedef_nonFunction_using_typeParameter() async {
+  test_typedef_nonFunction_using_Never_question() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A = Never?;
+void f(A a) {}
+''');
+    checkElementText(library, r'''
+typedef A = Never?;
+void f(Never? a) {}
+''');
+  }
+
+  test_typedef_nonFunction_using_typeParameter_none() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
 typedef A<T> = T;
@@ -12158,7 +12827,20 @@
 ''');
   }
 
-  /// TODO(scheglov) add `?` cases.
+  test_typedef_nonFunction_using_typeParameter_question() async {
+    featureSet = FeatureSets.nonFunctionTypeAliases;
+    var library = await checkLibrary(r'''
+typedef A<T> = T?;
+void f1(A a) {}
+void f2(A<int> a) {}
+''');
+    checkElementText(library, r'''
+typedef A<T> = T?;
+void f1(dynamic a) {}
+void f2(int? a) {}
+''');
+  }
+
   test_typedef_nonFunction_using_void() async {
     featureSet = FeatureSets.nonFunctionTypeAliases;
     var library = await checkLibrary(r'''
@@ -12354,14 +13036,30 @@
   test_typedef_type_parameters_f_bound_complex() async {
     var library = await checkLibrary('typedef U F<T extends List<U>, U>(T t);');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends List<U> = List<Null>, U> = U Function(T t);
+notSimplyBounded typedef F<T extends List<U> = List<Never>, U> = U Function(T t);
+''');
+  }
+
+  test_typedef_type_parameters_f_bound_complex_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
+    var library = await checkLibrary('typedef U F<T extends List<U>, U>(T t);');
+    checkElementText(library, r'''
+notSimplyBounded typedef F<T extends List<U*>* = List<Null*>*, U> = U* Function(T* t);
 ''');
   }
 
   test_typedef_type_parameters_f_bound_simple() async {
     var library = await checkLibrary('typedef U F<T extends U, U>(T t);');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends U = Null, U> = U Function(T t);
+notSimplyBounded typedef F<T extends U = Never, U> = U Function(T t);
+''');
+  }
+
+  test_typedef_type_parameters_f_bound_simple_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
+    var library = await checkLibrary('typedef U F<T extends U, U>(T t);');
+    checkElementText(library, r'''
+notSimplyBounded typedef F<T extends U* = Null*, U> = U* Function(T* t);
 ''');
   }
 
@@ -12369,7 +13067,16 @@
     var library =
         await checkLibrary('typedef F<T extends U, U> = U Function(T t);');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends U = Null, U> = U Function(T t);
+notSimplyBounded typedef F<T extends U = Never, U> = U Function(T t);
+''');
+  }
+
+  test_typedef_type_parameters_f_bound_simple_new_syntax_legacy() async {
+    featureSet = FeatureSets.beforeNullSafe;
+    var library =
+        await checkLibrary('typedef F<T extends U, U> = U Function(T t);');
+    checkElementText(library, r'''
+notSimplyBounded typedef F<T extends U* = Null*, U> = U* Function(T* t);
 ''');
   }
 
@@ -12661,7 +13368,6 @@
   }
 
   test_variable_const_late() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('late const int i = 0;');
     checkElementText(library, r'''
 late const int i = 0;
@@ -12762,7 +13468,7 @@
     expect(variable, isNotNull);
     expect(variable.isFinal, isTrue);
     expect(variable.getter, same(getter));
-    expect('${variable.type}', 'int*');
+    expect('${variable.type}', 'int');
     expect(variable, same(_elementOfDefiningUnit(library, '@field', 'x')));
   }
 
@@ -12827,7 +13533,6 @@
   }
 
   test_variable_late() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('late int x = 0;');
     checkElementText(
         library,
@@ -12840,7 +13545,6 @@
   }
 
   test_variable_late_final() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('late final int x;');
     checkElementText(
         library,
@@ -12853,7 +13557,6 @@
   }
 
   test_variable_late_final_initialized() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary('late final int x = 0;');
     checkElementText(
         library,
@@ -12934,17 +13637,13 @@
   }
 
   test_variable_type_inferred_Never() async {
-    featureSet = FeatureSets.nullSafe;
     var library = await checkLibrary(r'''
 var a = throw 42;
 ''');
 
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 Never a;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_variable_type_inferred_noInitializer() async {
@@ -12958,8 +13657,6 @@
   }
 
   test_variable_type_inferred_nonNullify() async {
-    featureSet = FeatureSets.nullSafe;
-
     addSource('/a.dart', '''
 // @dart = 2.7
 var a = 0;
@@ -12970,13 +13667,10 @@
 var b = a;
 ''');
 
-    checkElementText(
-        library,
-        r'''
+    checkElementText(library, r'''
 import 'a.dart';
 int b;
-''',
-        annotateNullability: true);
+''');
   }
 
   test_variableInitializer_contextType_after_astRewrite() async {
@@ -13024,7 +13718,7 @@
   }
 
   void _assertTypeStr(DartType type, String expected) {
-    var typeStr = type.getDisplayString(withNullability: false);
+    var typeStr = type.getDisplayString(withNullability: true);
     expect(typeStr, expected);
   }
 
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 b9bf27d..9fbb5f4 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -2,14 +2,10 @@
 // for 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/results.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../dart/analysis/base.dart';
 import '../dart/resolution/context_collection_resolution.dart';
 import 'element_text.dart';
 
@@ -17,7 +13,6 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(TopLevelInferenceTest);
     defineReflectiveTests(TopLevelInferenceErrorsTest);
-    defineReflectiveTests(TopLevelInferenceTestWithSpread);
 //    defineReflectiveTests(ApplyCheckElementTextReplacements);
   });
 }
@@ -30,7 +25,8 @@
 }
 
 @reflectiveTest
-class TopLevelInferenceErrorsTest extends PubPackageResolutionTest {
+class TopLevelInferenceErrorsTest extends PubPackageResolutionTest
+    with WithNullSafetyMixin {
   test_initializer_additive() async {
     await _assertErrorOnlyLeft(['+', '-']);
   }
@@ -185,7 +181,7 @@
 
   test_initializer_ifNull() async {
     await assertNoErrorsInCode('''
-var a = 1;
+int? a = 1;
 var t = a ?? 2;
 ''');
   }
@@ -216,8 +212,8 @@
 
   test_initializer_methodInvocation_function() async {
     await assertNoErrorsInCode('''
-int f1() => null;
-T f2<T>() => null;
+int f1() => 0;
+T f2<T>() => throw 0;
 var t1 = f1();
 var t2 = f2();
 var t3 = f2<int>();
@@ -227,8 +223,8 @@
   test_initializer_methodInvocation_method() async {
     await assertNoErrorsInCode('''
 class A {
-  int m1() => null;
-  T m2<T>() => null;
+  int m1() => 0;
+  T m2<T>() => throw 0;
 }
 var a = new A();
 var t1 = a.m1();
@@ -303,17 +299,17 @@
   test_override_conflictFieldType() async {
     await assertErrorsInCode('''
 abstract class A {
-  int aaa;
+  int aaa = 0;
 }
 abstract class B {
-  String aaa;
+  String aaa = '0';
 }
 class C implements A, B {
   var aaa;
 }
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 99, 3),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 99, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 109, 3),
+      error(CompileTimeErrorCode.INVALID_OVERRIDE, 109, 3),
     ]);
   }
 
@@ -344,7 +340,8 @@
 }
 
 @reflectiveTest
-class TopLevelInferenceTest extends BaseAnalysisDriverTest {
+class TopLevelInferenceTest extends PubPackageResolutionTest
+    with WithNullSafetyMixin {
   test_initializer_additive() async {
     var library = await _encodeDecodeLibrary(r'''
 var vPlusIntInt = 1 + 2;
@@ -638,7 +635,7 @@
   }
 
   test_initializer_extractProperty_explicitlyTyped_differentLibraryCycle() async {
-    newFile('/test/lib/a.dart', content: r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class C {
   int f = 0;
 }
@@ -669,7 +666,7 @@
   }
 
   test_initializer_extractProperty_explicitlyTyped_sameLibraryCycle() async {
-    newFile('/test/lib/a.dart', content: r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 import 'test.dart'; // just do make it part of the library cycle
 class C {
   int f = 0;
@@ -686,7 +683,7 @@
   }
 
   test_initializer_extractProperty_implicitlyTyped_differentLibraryCycle() async {
-    newFile('/test/lib/a.dart', content: r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class C {
   var f = 0;
 }
@@ -717,7 +714,7 @@
   }
 
   test_initializer_extractProperty_implicitlyTyped_sameLibraryCycle() async {
-    newFile('/test/lib/a.dart', content: r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 import 'test.dart'; // just do make it part of the library cycle
 class C {
   var f = 0;
@@ -2157,7 +2154,35 @@
   double foo(int x);
 }
 abstract class C implements A, B {
-  Null foo/*error: overrideNoCombinedSuperSignature*/(dynamic x);
+  Never foo/*error: overrideNoCombinedSuperSignature*/(dynamic x);
+}
+''');
+  }
+
+  test_method_error_noCombinedSuperSignature2_legacy() async {
+    var library = await _encodeDecodeLibrary(r'''
+// @dart = 2.9
+abstract class A {
+  int foo(int x);
+}
+
+abstract class B {
+  double foo(int x);
+}
+
+abstract class C implements A, B {
+  Never foo(x);
+}
+''');
+    checkElementText(library, r'''
+abstract class A {
+  int* foo(int* x);
+}
+abstract class B {
+  double* foo(int* x);
+}
+abstract class C implements A*, B* {
+  Null* foo/*error: overrideNoCombinedSuperSignature*/(dynamic x);
 }
 ''');
   }
@@ -2590,7 +2615,7 @@
   }
 
   test_method_OK_single_private_linkThroughOtherLibraryOfCycle() async {
-    newFile('/test/lib/other.dart', content: r'''
+    newFile('$testPackageLibPath/other.dart', content: r'''
 import 'test.dart';
 class B extends A2 {}
 ''');
@@ -2685,21 +2710,11 @@
   }
 
   Future<LibraryElement> _encodeDecodeLibrary(String text) async {
-    String path = convertPath('/test/lib/test.dart');
-    newFile(path, content: text);
-    UnitElementResult result = await driver.getUnitElement(path);
+    newFile(testFilePath, content: text);
+
+    var path = convertPath(testFilePath);
+    var analysisSession = contextFor(path).currentSession;
+    var result = await analysisSession.getUnitElement(path);
     return result.element.library /*!*/;
   }
 }
-
-@reflectiveTest
-class TopLevelInferenceTestWithSpread extends TopLevelInferenceTest {
-  @override
-  List<String> get enabledExperiments => [EnableString.spread_collections];
-
-  @override
-  @failingTest
-  test_initializer_literal_map_untyped_empty() async {
-    fail('times out.');
-  }
-}
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index c8fda9d..777a8a1 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2278,11 +2278,11 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 71, 1),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 117, 9),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 137, 15),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 124, 1),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 148, 3),
       error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 159, 3),
       error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 173, 5),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 189, 9),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 196, 1),
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 190, 1),
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 193, 1),
       error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 209, 3),
@@ -3809,7 +3809,7 @@
 
 class D extends Object with C implements A {}
 ''', [
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 100, 1),
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 100, 1),
     ]);
   }
 
@@ -4180,8 +4180,8 @@
 class E extends B implements A { }
 ''', [
       error(CompileTimeErrorCode.INVALID_OVERRIDE, 78, 4),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 159, 1),
-      error(CompileTimeErrorCode.INVALID_OVERRIDE, 189, 1),
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 159, 1),
+      error(CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE, 189, 1),
     ]);
   }
 
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 b7e1600..7e41586 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.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 file.
 
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../utils.dart';
 import '../../dart/resolution/context_collection_resolution.dart';
 
 void main() {
@@ -20,8 +18,6 @@
 
 @reflectiveTest
 class InferredTypeTest extends PubPackageResolutionTest {
-  CompilationUnit get _resultUnit => result.unit;
-
   CompilationUnitElement get _resultUnitElement {
     return result.unit.declaredElement;
   }
@@ -89,7 +85,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 241, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Future<num> Function()');
   }
 
@@ -112,7 +108,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 192, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Future<num> Function()');
   }
 
@@ -135,7 +131,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 215, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Future<num> Function()');
   }
 
@@ -155,7 +151,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 122, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Stream<num> Function()');
   }
 
@@ -183,7 +179,7 @@
       error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE, 62, 1),
     ]);
 
-    var g = findLocalVariable(_resultUnit, 'g');
+    var g = findElement.localVar('g');
     _assertTypeStr(g.type, 'String Function()');
   }
 
@@ -210,7 +206,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 105, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Future<Null> Function()');
   }
 
@@ -228,7 +224,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 105, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Stream<Null> Function()');
   }
 
@@ -251,7 +247,7 @@
       error(CompileTimeErrorCode.INVALID_CAST_LITERAL, 126, 7),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Null Function(Object)');
   }
 
@@ -269,7 +265,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 102, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Iterable<Null> Function()');
   }
 
@@ -306,7 +302,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'double Function(int) Function()');
   }
 
@@ -321,7 +317,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 67, 1),
     ]);
 
-    var y = findLocalVariable(_resultUnit, 'y');
+    var y = findElement.localVar('y');
     _assertTypeStr(y.type, 'Iterable<Null>');
   }
 
@@ -340,7 +336,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 110, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Iterable<num> Function()');
   }
 
@@ -473,11 +469,10 @@
       error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 349, 7),
     ]);
 
-    _assertTypeStr(findLocalVariable(_resultUnit, 'x').type, 'C<int>');
-    _assertTypeStr(findLocalVariable(_resultUnit, 'c_int').type, 'C<int>');
-    _assertTypeStr(findLocalVariable(_resultUnit, 'c_num').type, 'C<num>');
-    _assertTypeStr(
-        findLocalVariable(_resultUnit, 'c_dynamic').type, 'C<dynamic>');
+    _assertTypeStr(findElement.localVar('x').type, 'C<int>');
+    _assertTypeStr(findElement.localVar('c_int').type, 'C<int>');
+    _assertTypeStr(findElement.localVar('c_num').type, 'C<num>');
+    _assertTypeStr(findElement.localVar('c_dynamic').type, 'C<dynamic>');
   }
 
   test_constructors_inferFromArguments_const() async {
@@ -494,7 +489,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 63, 1),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     _assertTypeStr(x.type, 'C<int>');
   }
 
@@ -561,7 +556,7 @@
       error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 149, 7),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     _assertTypeStr(x.type, 'C<int>');
   }
 
@@ -592,7 +587,7 @@
       error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 95, 7),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     _assertTypeStr(x.type, 'C<int>');
   }
 
@@ -618,7 +613,7 @@
       error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 156, 7),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     _assertTypeStr(x.type, 'C<int>');
   }
 
@@ -639,7 +634,7 @@
       error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 123, 7),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     _assertTypeStr(x.type, 'C<int>');
   }
 
@@ -665,7 +660,7 @@
       error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 183, 7),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     _assertTypeStr(x.type, 'C<int>');
   }
 
@@ -689,10 +684,10 @@
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 29, 1),
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 38, 4),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 39, 2),
     ]);
 
-    var a = findLocalVariable(_resultUnit, 'a');
+    var a = findElement.localVar('a');
     _assertTypeStr(a.type, 'A<dynamic>');
   }
 
@@ -2326,7 +2321,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 118, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<int> Function(num)');
   }
 
@@ -2813,7 +2808,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 68, 1),
     ]);
 
-    var y = findLocalVariable(_resultUnit, 'y');
+    var y = findElement.localVar('y');
     _assertTypeStr(y.type, 'double');
   }
 
@@ -2829,7 +2824,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 59, 1),
     ]);
 
-    var y = findLocalVariable(_resultUnit, 'y');
+    var y = findElement.localVar('y');
     _assertTypeStr(y.type, 'double');
   }
 
@@ -2845,7 +2840,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 69, 1),
     ]);
 
-    var y = findLocalVariable(_resultUnit, 'y');
+    var y = findElement.localVar('y');
     _assertTypeStr(y.type, 'double');
   }
 
@@ -2861,7 +2856,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
     ]);
 
-    var y = findLocalVariable(_resultUnit, 'y');
+    var y = findElement.localVar('y');
     _assertTypeStr(y.type, 'int');
   }
 
@@ -2930,27 +2925,25 @@
           contextMessages: [message(testFilePath, 211, 2)]),
     ]);
 
-    _assertTypeStr(findLocalFunction(_resultUnit, 'f0').type, 'int Function()');
-    _assertTypeStr(
-        findLocalFunction(_resultUnit, 'f1').type, 'Future<int> Function()');
+    void assertLocalFunctionType(String name, String expected) {
+      var type = findElement.localFunction(name).type;
+      _assertTypeStr(type, expected);
+    }
 
-    _assertTypeStr(findLocalFunction(_resultUnit, 'f2').type, 'int Function()');
-    _assertTypeStr(
-        findLocalFunction(_resultUnit, 'f3').type, 'Future<int> Function()');
-    _assertTypeStr(
-        findLocalFunction(_resultUnit, 'f4').type, 'Iterable<int> Function()');
-    _assertTypeStr(
-        findLocalFunction(_resultUnit, 'f5').type, 'Stream<int> Function()');
+    assertLocalFunctionType('f0', 'int Function()');
+    assertLocalFunctionType('f1', 'Future<int> Function()');
 
-    _assertTypeStr(findLocalFunction(_resultUnit, 'f6').type, 'num Function()');
+    assertLocalFunctionType('f2', 'int Function()');
+    assertLocalFunctionType('f3', 'Future<int> Function()');
+    assertLocalFunctionType('f4', 'Iterable<int> Function()');
+    assertLocalFunctionType('f5', 'Stream<int> Function()');
+
+    assertLocalFunctionType('f6', 'num Function()');
 
     // Recursive cases: these infer in declaration order.
-    _assertTypeStr(
-        findLocalFunction(_resultUnit, 'f7').type, 'dynamic Function()');
-    _assertTypeStr(
-        findLocalFunction(_resultUnit, 'f8').type, 'dynamic Function()');
-    _assertTypeStr(
-        findLocalFunction(_resultUnit, 'f9').type, 'Stream<int> Function()');
+    assertLocalFunctionType('f7', 'dynamic Function()');
+    assertLocalFunctionType('f8', 'dynamic Function()');
+    assertLocalFunctionType('f9', 'Stream<int> Function()');
   }
 
   test_inferParameterType_setter_fromField() async {
@@ -3032,7 +3025,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var f = findLocalVariable(_resultUnit, 'f');
+    var f = findElement.localVar('f');
     _assertTypeStr(f.type, 'Null Function()');
   }
 
@@ -3089,7 +3082,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 72, 1),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     expect(x.name, 'x');
     _assertTypeStr(x.type, 'bool');
   }
@@ -3108,7 +3101,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 105, 1),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     expect(x.name, 'x');
     _assertTypeStr(x.type, 'bool');
   }
@@ -3912,7 +3905,7 @@
       error(CompileTimeErrorCode.INVALID_CAST_LITERAL, 36, 2),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     _assertTypeStr(x.type, 'List<Null>');
   }
 
@@ -3991,7 +3984,7 @@
       error(CompileTimeErrorCode.INVALID_CAST_LITERAL, 45, 3),
     ]);
 
-    var x = findLocalVariable(_resultUnit, 'x');
+    var x = findElement.localVar('x');
     _assertTypeStr(x.type, 'Map<Null, Null>');
   }
 
@@ -4086,7 +4079,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 36, 1),
     ]);
 
-    var y = findLocalVariable(_resultUnit, 'y');
+    var y = findElement.localVar('y');
     _assertTypeStr(y.type, 'List<num>');
   }
 
@@ -4297,7 +4290,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     expect(v.name, 'v');
     _assertTypeStr(v.type, 'double');
   }
@@ -4341,7 +4334,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 42, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     expect(v.name, 'v');
     _assertTypeStr(v.type, 'C<int>');
   }
@@ -4435,7 +4428,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<int>');
   }
 
@@ -4452,7 +4445,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<int>');
   }
 
@@ -4466,7 +4459,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'double');
   }
 
@@ -4480,7 +4473,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'double');
   }
 
@@ -4493,7 +4486,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<dynamic>');
   }
 
@@ -4507,7 +4500,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<int Function()>');
   }
 
@@ -4523,7 +4516,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<int Function()>');
   }
 
@@ -4536,7 +4529,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'Map<int, dynamic>');
   }
 
@@ -4550,7 +4543,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'Map<int, int Function()>');
   }
 
@@ -4566,7 +4559,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 15, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'Map<int, int Function()>');
   }
 
@@ -4582,7 +4575,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 62, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<dynamic>');
   }
 
@@ -4598,7 +4591,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 62, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<int>');
   }
 
@@ -4617,7 +4610,7 @@
       error(HintCode.UNUSED_LOCAL_VARIABLE, 62, 1),
     ]);
 
-    var v = findLocalVariable(_resultUnit, 'v');
+    var v = findElement.localVar('v');
     _assertTypeStr(v.type, 'List<int>');
   }
 
diff --git a/pkg/analyzer/test/src/workspace/bazel_test.dart b/pkg/analyzer/test/src/workspace/bazel_test.dart
index 2129789..9d7cd6e 100644
--- a/pkg/analyzer/test/src/workspace/bazel_test.dart
+++ b/pkg/analyzer/test/src/workspace/bazel_test.dart
@@ -2,13 +2,17 @@
 // for 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:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:async/async.dart';
 import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'package:watcher/watcher.dart';
 
 import '../../generated/test_support.dart';
 
@@ -130,6 +134,16 @@
         exists: true);
   }
 
+  void test_resolveAbsolute_file_bin_pathHasSpace() {
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/my/foo/test',
+    ]);
+    _assertResolve('file:///workspace/bazel-bin/my/test/a .dart',
+        '/workspace/my/test/a .dart',
+        exists: false, restore: false);
+  }
+
   void test_resolveAbsolute_file_bin_to_genfiles() {
     _addResources([
       '/workspace/WORKSPACE',
@@ -766,6 +780,152 @@
 class BazelWorkspaceTest with ResourceProviderMixin {
   BazelWorkspace workspace;
 
+  void test_bazelFileWatcher() async {
+    _addResources([
+      '/workspace/WORKSPACE',
+    ]);
+    _MockTimer timer;
+    var timerFactory = (Duration _, void Function(Timer) callback) {
+      timer = _MockTimer(callback);
+      return timer;
+    };
+    var candidates = [
+      convertPath('/workspace/bazel-bin/my/module/test1.dart'),
+      convertPath('/workspace/bazel-genfiles/my/module/test1.dart'),
+    ];
+    var watcher = BazelFileWatcher(candidates, resourceProvider, Duration.zero,
+        Duration.zero, timerFactory);
+    var events = StreamQueue(watcher.events);
+    watcher.start();
+
+    // First do some tests with the first candidate path.
+    _addResources([candidates[0]]);
+    timer.triggerCallback();
+
+    var event = await events.next;
+    expect(event.type, ChangeType.ADD);
+    expect(event.path, candidates[0]);
+
+    modifyFile(candidates[0], 'const foo = 42;');
+    timer.triggerCallback();
+
+    event = await events.next;
+    expect(event.type, ChangeType.MODIFY);
+    expect(event.path, candidates[0]);
+
+    _deleteResources([candidates[0]]);
+    timer.triggerCallback();
+
+    event = await events.next;
+    expect(event.type, ChangeType.REMOVE);
+    expect(event.path, candidates[0]);
+
+    // Now check that if we add the *second* candidate, we'll get the
+    // notification for it.
+    _addResources([candidates[1]]);
+    timer.triggerCallback();
+
+    event = await events.next;
+    expect(event.type, ChangeType.ADD);
+    expect(event.path, candidates[1]);
+
+    watcher.stop();
+    expect(await events.rest.isEmpty, true);
+  }
+
+  void test_bazelFileWatcher_existingFile() async {
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/bazel-bin/my/module/test1.dart',
+    ]);
+    BazelWorkspace workspace = BazelWorkspace.find(
+        resourceProvider, convertPath('/workspace/my/module'));
+    _MockTimer timer;
+    var timerFactory = (Duration _, void Function(Timer) callback) {
+      timer = _MockTimer(callback);
+      return timer;
+    };
+    var watcherCompleter = Completer<BazelFileWatcher>();
+    workspace.bazelCandidateFiles.listen((notification) =>
+        watcherCompleter.complete(notification.watcher(
+            pollingDelayLong: Duration.zero,
+            pollingDelayShort: Duration.zero,
+            timerFactory: timerFactory)));
+
+    var file1 =
+        workspace.findFile(convertPath('/workspace/my/module/test1.dart'));
+    expect(file1.exists, true);
+    var watcher = await watcherCompleter.future;
+    var events = StreamQueue(watcher.events);
+    watcher.start();
+
+    // Make sure that triggering the callback, will not generate extra events.
+    timer.triggerCallback();
+
+    var convertedPath =
+        convertPath('/workspace/bazel-bin/my/module/test1.dart');
+
+    // Change the file -- we should get a single MODIFY event and not an ADD
+    // event, since the file already existed.
+    modifyFile(convertedPath, 'const foo = 42;');
+    timer.triggerCallback();
+    var event = await events.next;
+
+    expect(event.type, ChangeType.MODIFY);
+    expect(event.path, convertedPath);
+
+    // But if we delete the file and then re-create it, we should get an ADD
+    // event (after the REMOVE one).
+    deleteFile(convertedPath);
+    timer.triggerCallback();
+    event = await events.next;
+
+    expect(event.type, ChangeType.REMOVE);
+    expect(event.path, convertedPath);
+
+    newFile(convertedPath);
+    timer.triggerCallback();
+    event = await events.next;
+
+    expect(event.type, ChangeType.ADD);
+    expect(event.path, convertedPath);
+
+    watcher.stop();
+    expect(await events.rest.isEmpty, true);
+  }
+
+  void test_bazelNotifications() async {
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/bazel-bin/my/module/test1.dart',
+    ]);
+    BazelWorkspace workspace = BazelWorkspace.find(
+        resourceProvider, convertPath('/workspace/my/module'));
+    var notifications = StreamQueue(workspace.bazelCandidateFiles);
+
+    var file1 =
+        workspace.findFile(convertPath('/workspace/my/module/test1.dart'));
+    expect(file1.exists, true);
+    var notification = await notifications.next;
+    expect(notification.requested, convertPath('my/module/test1.dart'));
+    expect(
+        notification.candidates,
+        containsAll(
+            [convertPath('/workspace/bazel-bin/my/module/test1.dart')]));
+
+    var file2 =
+        workspace.findFile(convertPath('/workspace/my/module/test2.dart'));
+    expect(file2.exists, false);
+    notification = await notifications.next;
+    expect(notification.requested, convertPath('my/module/test2.dart'));
+    expect(
+        notification.candidates,
+        containsAll([
+          convertPath('/workspace/bazel-bin/my/module/test2.dart'),
+          convertPath('/workspace/bazel-genfiles/my/module/test2.dart'),
+        ]));
+  }
+
   void test_find_fail_notAbsolute() {
     expect(
         () =>
@@ -1015,6 +1175,17 @@
     }
   }
 
+  /// Create new files and directories from [paths].
+  void _deleteResources(List<String> paths) {
+    for (String path in paths) {
+      if (path.endsWith('/')) {
+        deleteFolder(path.substring(0, path.length - 1));
+      } else {
+        deleteFile(path);
+      }
+    }
+  }
+
   /// Expect that [BazelWorkspace.findFile], given [path], returns [equals].
   void _expectFindFile(String path, {@required String equals}) =>
       expect(workspace.findFile(convertPath(path)).path, convertPath(equals));
@@ -1031,3 +1202,20 @@
     throw StateError('Unexpected invocation of ${invocation.memberName}');
   }
 }
+
+class _MockTimer implements Timer {
+  final void Function(Timer) callback;
+
+  @override
+  bool isActive = true;
+
+  _MockTimer(this.callback);
+
+  @override
+  int get tick => throw UnimplementedError();
+
+  @override
+  void cancel() => isActive = false;
+
+  void triggerCallback() => callback(this);
+}
diff --git a/pkg/analyzer/test/src/workspace/gn_test.dart b/pkg/analyzer/test/src/workspace/gn_test.dart
index 92244fb..122391c 100644
--- a/pkg/analyzer/test/src/workspace/gn_test.dart
+++ b/pkg/analyzer/test/src/workspace/gn_test.dart
@@ -106,10 +106,25 @@
     newFolder('/ws/.jiri_root');
     String buildDir = convertPath('out/debug-x87_128');
     newFile('/ws/.fx-build-dir', content: '$buildDir\n');
-    newFile('/ws/out/debug-x87_128/dartlang/gen/some/code/foo.packages',
-        content: '''
-p1:file:///some/path/lib/
-workspace:lib/''');
+    newFile(
+        '/ws/out/debug-x87_128/dartlang/gen/some/code/foo_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "p1",
+      "packageUri": "lib",
+      "rootUri": "some/path/"
+    },
+    {
+      "languageVersion": "2.2",
+      "name": "workspace",
+      "packageUri": "lib",
+      "rootUri": ""
+    }
+  ]
+}''');
     newFolder('/ws/some/code');
     var gnWorkspace =
         GnWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
@@ -147,7 +162,8 @@
     newFile('/workspace/some/code/pubspec.yaml');
     String buildDir = convertPath('out/debug-x87_128');
     newFile('/workspace/.fx-build-dir', content: '$buildDir\n');
-    newFile('/workspace/out/debug-x87_128/dartlang/gen/some/code/foo.packages');
+    newFile(
+        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_package_config.json');
     GnWorkspace workspace =
         GnWorkspace.find(resourceProvider, convertPath('/workspace/some/code'));
     expect(workspace, isNotNull);
@@ -162,14 +178,26 @@
     newFile('/workspace/.fx-build-dir', content: '$buildDir\n');
     String packageLocation = convertPath('/workspace/this/is/the/package');
     Uri packageUri = resourceProvider.pathContext.toUri(packageLocation);
-    newFile('/workspace/out/debug-x87_128/dartlang/gen/some/code/foo.packages',
-        content: 'flutter:$packageUri');
+    newFile(
+        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "flutter",
+      "packageUri": "lib",
+      "rootUri": "$packageUri"
+    }
+  ]
+}''');
     GnWorkspace workspace =
         GnWorkspace.find(resourceProvider, convertPath('/workspace/some/code'));
     expect(workspace, isNotNull);
     expect(workspace.root, convertPath('/workspace'));
     expect(workspace.packageMap.length, 1);
-    expect(workspace.packageMap['flutter'][0].path, packageLocation);
+    expect(workspace.packageMap['flutter'][0].path,
+        convertPath("$packageLocation/lib"));
   }
 
   void test_packages_absoluteBuildDir() {
@@ -180,14 +208,26 @@
     newFile('/workspace/.fx-build-dir', content: '$buildDir\n');
     String packageLocation = convertPath('/workspace/this/is/the/package');
     Uri packageUri = resourceProvider.pathContext.toUri(packageLocation);
-    newFile('/workspace/out/debug-x87_128/dartlang/gen/some/code/foo.packages',
-        content: 'flutter:$packageUri');
+    newFile(
+        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "flutter",
+      "packageUri": "lib",
+      "rootUri": "$packageUri"
+    }
+  ]
+}''');
     GnWorkspace workspace =
         GnWorkspace.find(resourceProvider, convertPath('/workspace/some/code'));
     expect(workspace, isNotNull);
     expect(workspace.root, convertPath('/workspace'));
     expect(workspace.packageMap.length, 1);
-    expect(workspace.packageMap['flutter'][0].path, packageLocation);
+    expect(workspace.packageMap['flutter'][0].path,
+        convertPath("$packageLocation/lib"));
   }
 
   void test_packages_fallbackBuildDir() {
@@ -196,14 +236,26 @@
     newFile('/workspace/some/code/pubspec.yaml');
     String packageLocation = convertPath('/workspace/this/is/the/package');
     Uri packageUri = resourceProvider.pathContext.toUri(packageLocation);
-    newFile('/workspace/out/debug-x87_128/dartlang/gen/some/code/foo.packages',
-        content: 'flutter:$packageUri');
+    newFile(
+        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "flutter",
+      "packageUri": "lib",
+      "rootUri": "$packageUri"
+    }
+  ]
+}''');
     GnWorkspace workspace =
         GnWorkspace.find(resourceProvider, convertPath('/workspace/some/code'));
     expect(workspace, isNotNull);
     expect(workspace.root, convertPath('/workspace'));
     expect(workspace.packageMap.length, 1);
-    expect(workspace.packageMap['flutter'][0].path, packageLocation);
+    expect(workspace.packageMap['flutter'][0].path,
+        convertPath("$packageLocation/lib"));
   }
 
   void test_packages_fallbackBuildDirWithUselessConfig() {
@@ -213,14 +265,26 @@
     newFile('/workspace/.fx-build-dir', content: '');
     String packageLocation = convertPath('/workspace/this/is/the/package');
     Uri packageUri = resourceProvider.pathContext.toUri(packageLocation);
-    newFile('/workspace/out/debug-x87_128/dartlang/gen/some/code/foo.packages',
-        content: 'flutter:$packageUri');
+    newFile(
+        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "flutter",
+      "packageUri": "lib",
+      "rootUri": "$packageUri"
+    }
+  ]
+}''');
     GnWorkspace workspace =
         GnWorkspace.find(resourceProvider, convertPath('/workspace/some/code'));
     expect(workspace, isNotNull);
     expect(workspace.root, convertPath('/workspace'));
     expect(workspace.packageMap.length, 1);
-    expect(workspace.packageMap['flutter'][0].path, packageLocation);
+    expect(workspace.packageMap['flutter'][0].path,
+        convertPath("$packageLocation/lib"));
   }
 
   void test_packages_multipleCandidates() {
@@ -231,20 +295,42 @@
     newFile('/workspace/.fx-build-dir', content: '$buildDir\n');
     String packageLocation = convertPath('/workspace/this/is/the/package');
     Uri packageUri = resourceProvider.pathContext.toUri(packageLocation);
-    newFile('/workspace/out/debug-x87_128/dartlang/gen/some/code/foo.packages',
-        content: 'flutter:$packageUri');
+    newFile(
+        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "flutter",
+      "packageUri": "lib1",
+      "rootUri": "$packageUri"
+    }
+  ]
+}''');
     String otherPackageLocation = convertPath('/workspace/here/too');
     Uri otherPackageUri =
         resourceProvider.pathContext.toUri(otherPackageLocation);
     newFile(
-        '/workspace/out/release-y22_256/dartlang/gen/some/code/foo.packages',
-        content: 'rettulf:$otherPackageUri');
+        '/workspace/out/release-y22_256/dartlang/gen/some/code/foo_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "rettulf",
+      "packageUri": "lib2",
+      "rootUri": "$otherPackageUri"
+    }
+  ]
+}''');
     GnWorkspace workspace =
         GnWorkspace.find(resourceProvider, convertPath('/workspace/some/code'));
     expect(workspace, isNotNull);
     expect(workspace.root, convertPath('/workspace'));
     expect(workspace.packageMap.length, 1);
-    expect(workspace.packageMap['rettulf'][0].path, otherPackageLocation);
+    expect(workspace.packageMap['rettulf'][0].path,
+        convertPath("$otherPackageLocation/lib2"));
   }
 
   void test_packages_multipleFiles() {
@@ -255,20 +341,43 @@
     newFile('/workspace/.fx-build-dir', content: '$buildDir\n');
     String packageOneLocation = convertPath('/workspace/this/is/the/package');
     Uri packageOneUri = resourceProvider.pathContext.toUri(packageOneLocation);
-    newFile('/workspace/out/debug-x87_128/dartlang/gen/some/code/foo.packages',
-        content: 'flutter:$packageOneUri');
+    newFile(
+        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "flutter",
+      "packageUri": "one/lib",
+      "rootUri": "$packageOneUri"
+    }
+  ]
+}''');
     String packageTwoLocation =
         convertPath('/workspace/this/is/the/other/package');
     Uri packageTwoUri = resourceProvider.pathContext.toUri(packageTwoLocation);
     newFile(
-        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_test.packages',
-        content: 'rettulf:$packageTwoUri');
+        '/workspace/out/debug-x87_128/dartlang/gen/some/code/foo_test_package_config.json',
+        content: '''{
+  "configVersion": 2,
+  "packages": [
+    {
+      "languageVersion": "2.2",
+      "name": "rettulf",
+      "packageUri": "two/lib",
+      "rootUri": "$packageTwoUri"
+    }
+  ]
+}''');
     GnWorkspace workspace =
         GnWorkspace.find(resourceProvider, convertPath('/workspace/some/code'));
     expect(workspace, isNotNull);
     expect(workspace.root, convertPath('/workspace'));
     expect(workspace.packageMap.length, 2);
-    expect(workspace.packageMap['flutter'][0].path, packageOneLocation);
-    expect(workspace.packageMap['rettulf'][0].path, packageTwoLocation);
+    expect(workspace.packageMap['flutter'][0].path,
+        convertPath("$packageOneLocation/one/lib"));
+    expect(workspace.packageMap['rettulf'][0].path,
+        convertPath("$packageTwoLocation/two/lib"));
   }
 }
diff --git a/pkg/analyzer/test/util/element_type_matchers.dart b/pkg/analyzer/test/util/element_type_matchers.dart
index 1ace6dd..f286b3f 100644
--- a/pkg/analyzer/test/util/element_type_matchers.dart
+++ b/pkg/analyzer/test/util/element_type_matchers.dart
@@ -24,8 +24,6 @@
 
 const isFunctionElement = TypeMatcher<FunctionElement>();
 
-const isFunctionTypeAliasElement = TypeMatcher<FunctionTypeAliasElement>();
-
 const isFunctionTypedElement = TypeMatcher<FunctionTypedElement>();
 
 const isGenericFunctionTypeElement = TypeMatcher<GenericFunctionTypeElement>();
diff --git a/pkg/analyzer/test/utils.dart b/pkg/analyzer/test/utils.dart
index 2e00258..64b63f6 100644
--- a/pkg/analyzer/test/utils.dart
+++ b/pkg/analyzer/test/utils.dart
@@ -7,28 +7,8 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/testing/element_search.dart';
 import 'package:test/test.dart';
 
-/// Search the [unit] for the [LocalVariableElement] with the given [name].
-/// Fail if there is not exactly one such variable.
-FunctionElement findLocalFunction(CompilationUnit unit, String name) {
-  List<Element> elements = findElementsByName(unit, name);
-  List<Element> functions = elements.whereType<FunctionElement>().toList();
-  expect(functions, hasLength(1));
-  return functions[0];
-}
-
-/// Search the [unit] for the [LocalVariableElement] with the given [name].
-/// Fail if there is not exactly one such variable.
-LocalVariableElement findLocalVariable(CompilationUnit unit, String name) {
-  List<Element> elements = findElementsByName(unit, name);
-  List<Element> localVariables =
-      elements.whereType<LocalVariableElement>().toList();
-  expect(localVariables, hasLength(1));
-  return localVariables[0];
-}
-
 /// The type of an assertion which asserts properties of [T]s.
 typedef Asserter<T> = void Function(T type);
 
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index af40e72..96d7c2b 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -46,9 +46,15 @@
     'CompileTimeErrorCode.INVALID_URI',
     // Produces two diagnostics when it should only produce one.
     'CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE',
+    // Produces two diagnostics when it should only produce one.
+    'CompileTimeErrorCode.NON_SYNC_FACTORY',
     // Need a way to make auxiliary files that (a) are not included in the
     // generated docs or (b) can be made persistent for fixes.
     'CompileTimeErrorCode.PART_OF_NON_PART',
+    // Produces two diagnostic out of necessity.
+    'CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT',
+    // Produces two diagnostic out of necessity.
+    'CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT',
     // Produces the diagnostic HintCode.UNUSED_LOCAL_VARIABLE when it shouldn't.
     'CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT',
     // The code has been replaced but is not yet removed.
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index eb96917..340a5a4 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -894,6 +894,53 @@
 }
 {% endprettify %}
 
+### assignment_to_function
+
+_Functions can't be assigned a value._
+
+#### Description
+
+The analyzer produces this diagnostic when the name of a function appears
+on the left-hand side of an assignment expression.
+
+#### Example
+
+The following code produces this diagnostic because the assignment to the
+function `f` is invalid:
+
+{% prettify dart tag=pre+code %}
+void f() {}
+
+void g() {
+  [!f!] = () {};
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the right-hand side should be assigned to something else, such as a
+local variable, then change the left-hand side:
+
+{% prettify dart tag=pre+code %}
+void f() {}
+
+void g() {
+  var x = () {};
+  print(x);
+}
+{% endprettify %}
+
+If the intent is to change the implementation of the function, then define
+a function-valued variable instead of a function:
+
+{% prettify dart tag=pre+code %}
+void Function() f = () {};
+
+void g() {
+  f = () {};
+}
+{% endprettify %}
+
 ### assignment_to_method
 
 _Methods can't be assigned a value._
@@ -922,6 +969,100 @@
 
 Rewrite the code so that there isn't an assignment to a method.
 
+### assignment_to_type
+
+_Types can't be assigned a value._
+
+#### Description
+
+The analyzer produces this diagnostic when the name of a type name appears
+on the left-hand side of an assignment expression.
+
+#### Example
+
+The following code produces this diagnostic because the assignment to the
+class `C` is invalid:
+
+{% prettify dart tag=pre+code %}
+class C {}
+
+void f() {
+  [!C!] = null;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the right-hand side should be assigned to something else, such as a
+local variable, then change the left-hand side:
+
+{% prettify dart tag=pre+code %}
+void f() {}
+
+void g() {
+  var c = null;
+  print(c);
+}
+{% endprettify %}
+
+### async_for_in_wrong_context
+
+_The async for-in loop can only be used in an async function._
+
+#### Description
+
+The analyzer produces this diagnostic when an async for-in loop is found in
+a function or method whose body isn't marked as being either `async` or
+`async*`.
+
+#### Example
+
+The following code produces this diagnostic because the body of `f` isn't
+marked as being either `async` or `async*`, but `f` contains an async
+for-in loop:
+
+{% prettify dart tag=pre+code %}
+void f(list) {
+  await for (var e [!in!] list) {
+    print(e);
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the function should return a `Future`, then mark the body with `async`:
+
+{% prettify dart tag=pre+code %}
+Future<void> f(list) async {
+  await for (var e in list) {
+    print(e);
+  }
+}
+{% endprettify %}
+
+If the function should return a `Stream` of values, then mark the body with
+`async*`:
+
+{% prettify dart tag=pre+code %}
+Stream<void> f(list) async* {
+  await for (var e in list) {
+    print(e);
+  }
+}
+{% endprettify %}
+
+If the function should be synchronous, then remove the `await` before the
+loop:
+
+{% prettify dart tag=pre+code %}
+void f(list) {
+  for (var e in list) {
+    print(e);
+  }
+}
+{% endprettify %}
+
 ### await_in_late_local_variable_initializer
 
 _The 'await' expression can't be used in a 'late' local variable's initializer._
@@ -1038,6 +1179,61 @@
 }
 {% endprettify %}
 
+### break_label_on_switch_member
+
+_A break label resolves to the 'case' or 'default' statement._
+
+#### Description
+
+The analyzer produces this diagnostic when a break in a case clause inside
+a switch statement has a label that is associated with another case clause.
+
+#### Example
+
+The following code produces this diagnostic because the label `l` is
+associated with the case clause for `0`:
+
+{% prettify dart tag=pre+code %}
+void f(int i) {
+  switch (i) {
+    l: case 0:
+      break;
+    case 1:
+      break [!l!];
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the intent is to transfer control to the statement after the switch,
+then remove the label from the break statement:
+
+{% prettify dart tag=pre+code %}
+void f(int i) {
+  switch (i) {
+    case 0:
+      break;
+    case 1:
+      break;
+  }
+}
+{% endprettify %}
+
+If the intent is to transfer control to a different case block, then use
+`continue` rather than `break`:
+
+{% prettify dart tag=pre+code %}
+void f(int i) {
+  switch (i) {
+    l: case 0:
+      break;
+    case 1:
+      continue l;
+  }
+}
+{% endprettify %}
+
 ### built_in_identifier_as_extension_name
 
 _The built-in identifier '{0}' can't be used as an extension name._
@@ -1129,6 +1325,105 @@
 }
 {% endprettify %}
 
+### case_expression_type_implements_equals
+
+_The switch case expression type '{0}' can't override the '==' operator._
+
+#### Description
+
+The analyzer produces this diagnostic when the type of the expression
+following the keyword `case` has an implementation of the `==` operator
+other than the one in `Object`.
+
+#### Example
+
+The following code produces this diagnostic because the expression
+following the keyword `case` (`C(0)`) has the type `C`, and the class `C`
+overrides the `==` operator:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final int value;
+
+  const C(this.value);
+
+  bool operator ==(Object other) {
+    return false;
+  }
+}
+
+void f(C c) {
+  switch (c) {
+    case [!C(0)!]:
+      break;
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If there isn't a strong reason not to do so, then rewrite the code to use
+an if-else structure:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final int value;
+
+  const C(this.value);
+
+  bool operator ==(Object other) {
+    return false;
+  }
+}
+
+void f(C c) {
+  if (c == C(0)) {
+    // ...
+  }
+}
+{% endprettify %}
+
+If you can't rewrite the switch statement and the implementation of `==`
+isn't necessary, then remove it:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final int value;
+
+  const C(this.value);
+}
+
+void f(C c) {
+  switch (c) {
+    case C(0):
+      break;
+  }
+}
+{% endprettify %}
+
+If you can't rewrite the switch statement and you can't remove the
+definition of `==`, then find some other value that can be used to control
+the switch:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final int value;
+
+  const C(this.value);
+
+  bool operator ==(Object other) {
+    return false;
+  }
+}
+
+void f(C c) {
+  switch (c.value) {
+    case 0:
+      break;
+  }
+}
+{% endprettify %}
+
 ### case_expression_type_is_not_switch_expression_subtype
 
 _The switch case expression type '{0}' must be a subtype of the switch
@@ -2023,6 +2318,60 @@
 }
 {% endprettify %}
 
+### default_value_in_redirecting_factory_constructor
+
+_Default values aren't allowed in factory constructors that redirect to another
+constructor._
+
+#### Description
+
+The analyzer produces this diagnostic when a factory constructor that
+redirects to another constructor specifies a default value for an optional
+parameter.
+
+#### Example
+
+The following code produces this diagnostic because the factory constructor
+in `A` has a default value for the optional parameter `x`:
+
+{% prettify dart tag=pre+code %}
+class A {
+  factory A([int [!x!] = 0]) = B;
+}
+
+class B implements A {
+  B([int x = 1]) {}
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the default value from the factory constructor:
+
+{% prettify dart tag=pre+code %}
+class A {
+  factory A([int x]) = B;
+}
+
+class B implements A {
+  B([int x = 1]) {}
+}
+{% endprettify %}
+
+Note that this fix might change the value used when the optional parameter
+is omitted. If that happens, and if that change is a problem, then consider
+making the optional parameter a required parameter in the factory method:
+
+{% prettify dart tag=pre+code %}
+class A {
+ factory A(int x) = B;
+}
+
+class B implements A {
+  B([int x = 1]) {}
+}
+{% endprettify %}
+
 ### definitely_unassigned_late_local_variable
 
 _The late local variable '{0}' is definitely unassigned at this point._
@@ -2217,6 +2566,46 @@
 int y = 1;
 {% endprettify %}
 
+### duplicate_hidden_name
+
+_Duplicate hidden name._
+
+#### Description
+
+The analyzer produces this diagnostic when a name occurs multiple times in
+a `hide` clause. Repeating the name is unnecessary.
+
+#### Example
+
+The following code produces this diagnostic because the name `min` is
+hidden more than once:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' hide min, [!min!];
+
+var x = pi;
+{% endprettify %}
+
+#### Common fixes
+
+If the name was mistyped in one or more places, then correct the mistyped
+names:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' hide max, min;
+
+var x = pi;
+{% endprettify %}
+
+If the name wasn't mistyped, then remove the unnecessary name from the
+list:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' hide min;
+
+var x = pi;
+{% endprettify %}
+
 ### duplicate_ignore
 
 _The diagnostic '{0}' doesn't need to be ignored here because it's already being
@@ -2383,6 +2772,46 @@
 part 'part.dart';
 {% endprettify %}
 
+### duplicate_shown_name
+
+_Duplicate shown name._
+
+#### Description
+
+The analyzer produces this diagnostic when a name occurs multiple times in
+a `show` clause. Repeating the name is unnecessary.
+
+#### Example
+
+The following code produces this diagnostic because the name `min` is shown
+more than once:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' show min, [!min!];
+
+var x = min(2, min(0, 1));
+{% endprettify %}
+
+#### Common fixes
+
+If the name was mistyped in one or more places, then correct the mistyped
+names:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' show max, min;
+
+var x = max(2, min(0, 1));
+{% endprettify %}
+
+If the name wasn't mistyped, then remove the unnecessary name from the
+list:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' show min;
+
+var x = min(2, min(0, 1));
+{% endprettify %}
+
 ### equal_elements_in_const_set
 
 _Two elements in a constant set literal can't be equal._
@@ -3149,7 +3578,7 @@
 {% prettify dart tag=pre+code %}
 void f(int a, int b) {}
 void g() {
-  f[!(1, 2, 3)!];
+  f(1, 2, [!3!]);
 }
 {% endprettify %}
 
@@ -3183,7 +3612,7 @@
 {% prettify dart tag=pre+code %}
 void f(int a, int b, {int c}) {}
 void g() {
-  f[!(1, 2, 3)!];
+  f(1, 2, [!3!]);
 }
 {% endprettify %}
 
@@ -3209,6 +3638,41 @@
 }
 {% endprettify %}
 
+### field_initialized_by_multiple_initializers
+
+_The field '{0}' can't be initialized twice in the same constructor._
+
+#### Description
+
+The analyzer produces this diagnostic when the initializer list of a
+constructor initializes a field more than once. There is no value to allow
+both initializers because only the last value is preserved.
+
+#### Example
+
+The following code produces this diagnostic because the field `f` is being
+initialized twice:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C() : f = 0, [!f!] = 1;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove one of the initializers:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C() : f = 0;
+}
+{% endprettify %}
+
 ### field_initialized_in_initializer_and_declaration
 
 _Fields can't be initialized in the constructor if they are final and were
@@ -3256,6 +3720,98 @@
 }
 {% endprettify %}
 
+### field_initialized_in_parameter_and_initializer
+
+_Fields can't be initialized in both the parameter list and the initializers._
+
+#### Description
+
+The analyzer produces this diagnostic when a field is initialized in both
+the parameter list and in the initializer list of a constructor.
+
+#### Example
+
+The following code produces this diagnostic because the field `f` is
+initialized both by a field formal parameter and in the initializer list:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(this.f) : [!f!] = 0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the field should be initialized by the parameter, then remove the
+initialization in the initializer list:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(this.f);
+}
+{% endprettify %}
+
+If the field should be initialized in the initializer list and the
+parameter isn't needed, then remove the parameter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C() : f = 0;
+}
+{% endprettify %}
+
+If the field should be initialized in the initializer list and the
+parameter is needed, then make it a normal parameter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(int g) : f = g * 2;
+}
+{% endprettify %}
+
+### field_initializer_factory_constructor
+
+_Initializing formal parameters can't be used in factory constructors._
+
+#### Description
+
+The analyzer produces this diagnostic when a factory constructor has a
+field formal parameter. Factory constructors can't assign values to fields
+because no instance is created; hence, there is no field to assign.
+
+#### Example
+
+The following code produces this diagnostic because the factory constructor
+uses a field formal parameter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int? f;
+
+  factory C([!this.f!]) => throw 0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Replace the field formal parameter with a normal parameter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int? f;
+
+  factory C(int f) => throw 0;
+}
+{% endprettify %}
+
 ### field_initializer_not_assignable
 
 _The initializer type '{0}' can't be assigned to the field type '{1}' in a const
@@ -3306,6 +3862,182 @@
 }
 {% endprettify %}
 
+### field_initializer_redirecting_constructor
+
+_The redirecting constructor can't have a field initializer._
+
+#### Description
+
+The analyzer produces this diagnostic when a redirecting constructor
+initializes a field in the object. This isn't allowed because the instance
+that has the field hasn't been created at the point at which it should be
+initialized.
+
+#### Example
+
+The following code produces this diagnostic because the constructor
+`C.zero`, which redirects to the constructor `C`, has a field formal
+parameter that initializes the field `f`:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(this.f);
+
+  C.zero([!this.f!]) : this(f);
+}
+{% endprettify %}
+
+The following code produces this diagnostic because the constructor
+`C.zero`, which redirects to the constructor `C`, has an initializer that
+initializes the field `f`:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(this.f);
+
+  C.zero() : [!f = 0!], this(1);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the initialization is done by a field formal parameter, then use a
+normal parameter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(this.f);
+
+  C.zero(int f) : this(f);
+}
+{% endprettify %}
+
+If the initialization is done in an initializer, then remove the
+initializer:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(this.f);
+
+  C.zero() : this(0);
+}
+{% endprettify %}
+
+### field_initializing_formal_not_assignable
+
+_The parameter type '{0}' is incompatible with the field type '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the type of a field formal
+parameter isn't assignable to the type of the field being initialized.
+
+#### Example
+
+The following code produces this diagnostic because the field formal
+parameter has the type `String`, but the type of the field is `int`. The
+parameter must have a type that is a subtype of the field's type.
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C([!String this.f!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the type of the field is incorrect, then change the type of the field to
+match the type of the parameter, and consider removing the type from the
+parameter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  String f;
+
+  C(this.f);
+}
+{% endprettify %}
+
+If the type of the parameter is incorrect, then remove the type of the
+parameter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(this.f);
+}
+{% endprettify %}
+
+If the types of both the field and the parameter are correct, then use an
+initializer rather than a field formal parameter to convert the parameter
+value into a value of the correct type:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int f;
+
+  C(String s) : f = int.parse(s);
+}
+{% endprettify %}
+
+### final_initialized_in_declaration_and_constructor
+
+_'{0}' is final and was given a value when it was declared, so it can't be set
+to a new value._
+
+#### Description
+
+The analyzer produces this diagnostic when a final field is initialized
+twice: once where it's declared and once by a constructor's parameter.
+
+#### Example
+
+The following code produces this diagnostic because the field `f` is
+initialized twice:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final int f = 0;
+
+  C(this.[!f!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the field should have the same value for all instances, then remove the
+initialization in the parameter list:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final int f = 0;
+
+  C();
+}
+{% endprettify %}
+
+If the field can have different values in different instances, then remove
+the initialization in the declaration:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final int f;
+
+  C(this.f);
+}
+{% endprettify %}
+
 ### final_not_initialized
 
 _The final variable '{0}' must be initialized._
@@ -4174,8 +4906,6 @@
 _Annotation must be either a const variable reference or const constructor
 invocation._
 
-_Getters can't be used as annotations._
-
 #### Description
 
 The analyzer produces this diagnostic when an annotation is found that is
@@ -4397,6 +5127,34 @@
 }
 {% endprettify %}
 
+### invalid_inline_function_type
+
+_Inline function types can't be used for parameters in a generic function type._
+
+#### Description
+
+The analyzer produces this diagnostic when a generic function type has a
+function-valued parameter that is written using the older inline function
+type syntax.
+
+#### Example
+
+The following code produces this diagnostic because the parameter `f`, in
+the generic function type used to define `F`, uses the inline function
+type syntax:
+
+{% prettify dart tag=pre+code %}
+typedef F = int Function(int f[!(!]String s));
+{% endprettify %}
+
+#### Common fixes
+
+Use the generic function syntax for the parameter's type:
+
+{% prettify dart tag=pre+code %}
+typedef F = int Function(int Function(String));
+{% endprettify %}
+
 ### invalid_literal_annotation
 
 _Only const constructors can have the `@literal` annotation._
@@ -5017,6 +5775,58 @@
 }
 {% endprettify %}
 
+### label_undefined
+
+_Can't reference an undefined label '{0}'._
+
+#### Description
+
+The analyzer produces this diagnostic when it finds a reference to a label
+that isn't defined in the scope of the `break` or `continue` statement that
+is referencing it.
+
+#### Example
+
+The following code produces this diagnostic because the label `loop` isn't
+defined anywhere:
+
+{% prettify dart tag=pre+code %}
+void f() {
+  for (int i = 0; i < 10; i++) {
+    for (int j = 0; j < 10; j++) {
+      break [!loop!];
+    }
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the label should be on the innermost enclosing `do`, `for`, `switch`, or
+`while` statement, then remove the label:
+
+{% prettify dart tag=pre+code %}
+void f() {
+  for (int i = 0; i < 10; i++) {
+    for (int j = 0; j < 10; j++) {
+      break;
+    }
+  }
+}
+{% endprettify %}
+
+If the label should be on some other statement, then add the label:
+
+{% prettify dart tag=pre+code %}
+void f() {
+  loop: for (int i = 0; i < 10; i++) {
+    for (int j = 0; j < 10; j++) {
+      break loop;
+    }
+  }
+}
+{% endprettify %}
+
 ### late_final_field_with_const_constructor
 
 _Can't have a late final field in a class with a const constructor._
@@ -5155,6 +5965,113 @@
 List<num> x = [1, 2.5, 3];
 {% endprettify %}
 
+### main_first_positional_parameter_type
+
+_The type of the first positional parameter of the 'main' function must be a
+supertype of 'List<String>'._
+
+#### Description
+
+The analyzer produces this diagnostic when the first positional parameter
+of a function named `main` isn't a supertype of `List<String>`.
+
+#### Example
+
+The following code produces this diagnostic because `List<int>` isn't a
+supertype of `List<String>`:
+
+{% prettify dart tag=pre+code %}
+void main([!List<int>!] args) {}
+{% endprettify %}
+
+#### Common fixes
+
+If the function is an entry point, then change the type of the first
+positional parameter to be a supertype of `List<String>`:
+
+{% prettify dart tag=pre+code %}
+void main(List<String> args) {}
+{% endprettify %}
+
+If the function isn't an entry point, then change the name of the function:
+
+{% prettify dart tag=pre+code %}
+void f(List<int> args) {}
+{% endprettify %}
+
+### main_has_required_named_parameters
+
+_The function 'main' can't have any required named parameters._
+
+#### Description
+
+The analyzer produces this diagnostic when a function named `main` has one
+or more required named parameters.
+
+#### Example
+
+The following code produces this diagnostic because the function named
+`main` has a required named parameter (`x`):
+
+{% prettify dart tag=pre+code %}
+void [!main!]({required int x}) {}
+{% endprettify %}
+
+#### Common fixes
+
+If the function is an entry point, then remove the `required` keyword:
+
+{% prettify dart tag=pre+code %}
+void main({int? x}) {}
+{% endprettify %}
+
+If the function isn't an entry point, then change the name of the function:
+
+{% prettify dart tag=pre+code %}
+void f({required int x}) {}
+{% endprettify %}
+
+### main_has_too_many_required_positional_parameters
+
+_The function 'main' can't have more than two required positional parameters._
+
+#### Description
+
+The analyzer produces this diagnostic when a function named `main` has more
+than two required positional parameters.
+
+#### Example
+
+The following code produces this diagnostic because the function `main` has
+three required positional parameters:
+
+{% prettify dart tag=pre+code %}
+void [!main!](List<String> args, int x, int y) {}
+{% endprettify %}
+
+#### Common fixes
+
+If the function is an entry point and the extra parameters aren't used,
+then remove them:
+
+{% prettify dart tag=pre+code %}
+void main(List<String> args, int x) {}
+{% endprettify %}
+
+If the function is an entry point, but the extra parameters used are for
+when the function isn't being used as an entry point, then make the extra
+parameters optional:
+
+{% prettify dart tag=pre+code %}
+void main(List<String> args, int x, [int y = 0]) {}
+{% endprettify %}
+
+If the function isn't an entry point, then change the name of the function:
+
+{% prettify dart tag=pre+code %}
+void f(List<String> args, int x, int y) {}
+{% endprettify %}
+
 ### main_is_not_function
 
 _The declaration named 'main' must be a function._
@@ -6303,6 +7220,57 @@
 void f() => const C();
 {% endprettify %}
 
+### non_sync_factory
+
+_Factory bodies can't use 'async', 'async*', or 'sync*'._
+
+#### Description
+
+The analyzer produces this diagnostic when the body of a factory
+constructor is marked with `async`, `async*`, or `sync*`. All constructors,
+including factory constructors, are required to return an instance of the
+class in which they're declared, not a `Future`, `Stream`, or `Iterator`.
+
+#### Example
+
+The following code produces this diagnostic because the body of the factory
+constructor is marked with `async`:
+
+{% prettify dart tag=pre+code %}
+class C {
+  factory C() [!async!] {
+    return C._();
+  }
+  C._();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the member must be declared as a factory constructor, then remove the
+keyword appearing before the body:
+
+{% prettify dart tag=pre+code %}
+class C {
+  factory C() {
+    return C._();
+  }
+  C._();
+}
+{% endprettify %}
+
+If the member must return something other than an instance of the enclosing
+class, then make the member a static method:
+
+{% prettify dart tag=pre+code %}
+class C {
+  static Future<C> m() async {
+    return C._();
+  }
+  C._();
+}
+{% endprettify %}
+
 ### non_type_as_type_argument
 
 _The name '{0}' isn't a type so it can't be used as a type argument._
@@ -7003,6 +7971,51 @@
 class C with M {}
 {% endprettify %}
 
+### on_repeated
+
+_The type '{0}' can be included in the superclass constraints only once._
+
+#### Description
+
+The analyzer produces this diagnostic when the same type is listed in the
+superclass constraints of a mixin multiple times.
+
+#### Example
+
+The following code produces this diagnostic because `A` is included twice
+in the superclass constraints for `M`:
+
+{% prettify dart tag=pre+code %}
+mixin M on A, [!A!] {
+}
+
+class A {}
+class B {}
+{% endprettify %}
+
+#### Common fixes
+
+If a different type should be included in the superclass constraints, then
+replace one of the occurrences with the other type:
+
+{% prettify dart tag=pre+code %}
+mixin M on A, B {
+}
+
+class A {}
+class B {}
+{% endprettify %}
+
+If no other type was intended, then remove the repeated type name:
+
+{% prettify dart tag=pre+code %}
+mixin M on A {
+}
+
+class A {}
+class B {}
+{% endprettify %}
+
 ### override_on_non_overriding_member
 
 _The field doesn't override an inherited getter or setter._
@@ -7205,6 +8218,237 @@
 
 If the name is wrong, then correct the name.
 
+### private_optional_parameter
+
+_Named parameters can't start with an underscore._
+
+#### Description
+
+The analyzer produces this diagnostic when the name of a named parameter
+starts with an underscore.
+
+#### Example
+
+The following code produces this diagnostic because the named parameter
+`_x` starts with an underscore:
+
+{% prettify dart tag=pre+code %}
+class C {
+  void m({int [!_x!] = 0}) {}
+}
+{% endprettify %}
+
+#### Common fixes
+
+Rename the parameter so that it doesn't start with an underscore:
+
+{% prettify dart tag=pre+code %}
+class C {
+  void m({int x = 0}) {}
+}
+{% endprettify %}
+
+### recursive_compile_time_constant
+
+_The compile-time constant expression depends on itself._
+
+#### Description
+
+The analyzer produces this diagnostic when the value of a compile-time
+constant is defined in terms of itself, either directly or indirectly,
+creating an infinite loop.
+
+#### Example
+
+The following code produces this diagnostic twice because both of the
+constants are defined in terms of the other:
+
+{% prettify dart tag=pre+code %}
+const [!secondsPerHour!] = minutesPerHour * 60;
+const [!minutesPerHour!] = secondsPerHour / 60;
+{% endprettify %}
+
+#### Common fixes
+
+Break the cycle by finding an alternative way of defining at least one of
+the constants:
+
+{% prettify dart tag=pre+code %}
+const secondsPerHour = minutesPerHour * 60;
+const minutesPerHour = 60;
+{% endprettify %}
+
+### recursive_constructor_redirect
+
+_Constructors can't redirect to themselves either directly or indirectly._
+
+#### Description
+
+The analyzer produces this diagnostic when a constructor redirects to
+itself, either directly or indirectly, creating an infinite loop.
+
+#### Example
+
+The following code produces this diagnostic because the generative
+constructors `C.a` and `C.b` each redirect to the other:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : [!this.b()!];
+  C.b() : [!this.a()!];
+}
+{% endprettify %}
+
+The following code produces this diagnostic because the factory
+constructors `A` and `B` each redirect to the other:
+
+{% prettify dart tag=pre+code %}
+abstract class A {
+  factory A() = [!B!];
+}
+class B implements A {
+  factory B() = [!A!];
+  B.named();
+}
+{% endprettify %}
+
+#### Common fixes
+
+In the case of generative constructors, break the cycle by finding defining
+at least one of the constructors to not redirect to another constructor:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : this.b();
+  C.b();
+}
+{% endprettify %}
+
+In the case of factory constructors, break the cycle by defining at least
+one of the factory constructors to do one of the following:
+
+- Redirect to a generative constructor:
+
+{% prettify dart tag=pre+code %}
+abstract class A {
+  factory A() = B;
+}
+class B implements A {
+  factory B() = B.named;
+  B.named();
+}
+{% endprettify %}
+
+- Not redirect to another constructor:
+
+{% prettify dart tag=pre+code %}
+abstract class A {
+  factory A() = B;
+}
+class B implements A {
+  factory B() {
+    return B.named();
+  }
+
+  B.named();
+}
+{% endprettify %}
+
+- Not be a factory constructor:
+
+{% prettify dart tag=pre+code %}
+abstract class A {
+  factory A() = B;
+}
+class B implements A {
+  B();
+  B.named();
+}
+{% endprettify %}
+
+### redirect_generative_to_missing_constructor
+
+_The constructor '{0}' couldn't be found in '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a generative constructor
+redirects to a constructor that isn't defined.
+
+#### Example
+
+The following code produces this diagnostic because the constructor `C.a`
+redirects to the constructor `C.b`, but `C.b` isn't defined:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : [!this.b()!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the missing constructor must be called, then define it:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : this.b();
+  C.b();
+}
+{% endprettify %}
+
+If the missing constructor doesn't need to be called, then remove the
+redirect:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a();
+}
+{% endprettify %}
+
+### redirect_generative_to_non_generative_constructor
+
+_Generative constructors can't redirect to a factory constructor._
+
+#### Description
+
+The analyzer produces this diagnostic when a generative constructor
+redirects to a factory constructor.
+
+#### Example
+
+The following code produces this diagnostic because the generative
+constructor `C.a` redirects to the factory constructor `C.b`:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : [!this.b()!];
+  factory C.b() => C.a();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the generative constructor doesn't need to redirect to another
+constructor, then remove the redirect.
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a();
+  factory C.b() => C.a();
+}
+{% endprettify %}
+
+If the generative constructor must redirect to another constructor, then
+make the other constructor be a generative (non-factory) constructor:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : this.b();
+  C.b();
+}
+{% endprettify %}
+
 ### redirect_to_invalid_function_type
 
 _The redirected constructor '{0}' has incompatible parameters with '{1}'._
@@ -7373,6 +8617,50 @@
 }
 {% endprettify %}
 
+### redirect_to_non_const_constructor
+
+_A constant redirecting constructor can't redirect to a non-constant
+constructor._
+
+#### Description
+
+The analyzer produces this diagnostic when a constructor marked as `const`
+redirects to a constructor that isn't marked as `const`.
+
+#### Example
+
+The following code produces this diagnostic because the constructor `C.a`
+is marked as `const` but redirects to the constructor `C.b`, which isn't:
+
+{% prettify dart tag=pre+code %}
+class C {
+  const C.a() : this.[!b!]();
+  C.b();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the non-constant constructor can be marked as `const`, then mark it as
+`const`:
+
+{% prettify dart tag=pre+code %}
+class C {
+  const C.a() : this.b();
+  const C.b();
+}
+{% endprettify %}
+
+If the non-constant constructor can't be marked as `const`, then either
+remove the redirect or remove `const` from the redirecting constructor:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : this.b();
+  C.b();
+}
+{% endprettify %}
+
 ### referenced_before_declaration
 
 _Local variable '{0}' can't be referenced before it is declared._
@@ -7423,6 +8711,52 @@
 }
 {% endprettify %}
 
+### rethrow_outside_catch
+
+_A rethrow must be inside of a catch clause._
+
+#### Description
+
+The analyzer produces this diagnostic when a `rethrow` statement is outside
+a `catch` clause. The `rethrow` statement is used to throw a caught
+exception again, but there's no caught exception outside of a `catch`
+clause.
+
+#### Example
+
+The following code produces this diagnostic because the`rethrow` statement
+is outside of a `catch` clause:
+
+{% prettify dart tag=pre+code %}
+void f() {
+  [!rethrow!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you're trying to rethrow an exception, then wrap the `rethrow` statement
+in a `catch` clause:
+
+{% prettify dart tag=pre+code %}
+void f() {
+  try {
+    // ...
+  } catch (exception) {
+    rethrow;
+  }
+}
+{% endprettify %}
+
+If you're trying to throw a new exception, then replace the `rethrow`
+statement with a `throw` expression:
+
+{% prettify dart tag=pre+code %}
+void f() {
+  throw UnsupportedError('Not yet implemented');
+}
+{% endprettify %}
+
 ### return_in_generative_constructor
 
 _Constructors can't return values._
@@ -7475,13 +8809,13 @@
 
 ### return_of_invalid_type
 
-_A value of type '{0}' can't be returned from constructor '{2}' because it has a
-return type of '{1}'._
+_A value of type '{0}' can't be returned from the constructor '{2}' because it
+has a return type of '{1}'._
 
-_A value of type '{0}' can't be returned from function '{2}' because it has a
-return type of '{1}'._
+_A value of type '{0}' can't be returned from the function '{2}' because it has
+a return type of '{1}'._
 
-_A value of type '{0}' can't be returned from method '{2}' because it has a
+_A value of type '{0}' can't be returned from the method '{2}' because it has a
 return type of '{1}'._
 
 #### Description
@@ -7544,7 +8878,7 @@
 
 ### return_without_value
 
-_The  return value is missing after 'return'._
+_The return value is missing after 'return'._
 
 #### Description
 
@@ -8088,6 +9422,49 @@
 var b = [...a];
 {% endprettify %}
 
+### shared_deferred_prefix
+
+_The prefix of a deferred import can't be used in other import directives._
+
+#### Description
+
+The analyzer produces this diagnostic when a prefix in a deferred import is
+also used as a prefix in other imports (whether deferred or not). The
+prefix in a deferred import can't be shared with other imports because the
+prefix is used to load the imported library.
+
+#### Example
+
+The following code produces this diagnostic because the prefix `x` is used
+as the prefix for a deferred import and is also used for one other import:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' [!deferred!] as x;
+import 'dart:convert' as x;
+
+var y = x.json.encode(x.min(0, 1));
+{% endprettify %}
+
+#### Common fixes
+
+If you can use a different name for the deferred import, then do so:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' deferred as math;
+import 'dart:convert' as x;
+
+var y = x.json.encode(math.min(0, 1));
+{% endprettify %}
+
+If you can use a different name for the other imports, then do so:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' deferred as x;
+import 'dart:convert' as convert;
+
+var y = convert.json.encode(x.min(0, 1));
+{% endprettify %}
+
 ### static_access_to_instance_member
 
 _Instance member '{0}' can't be accessed using static access._
@@ -8260,6 +9637,40 @@
 
 Rewrite the code to not use `super`.
 
+### super_in_redirecting_constructor
+
+_The redirecting constructor can't have a 'super' initializer._
+
+#### Description
+
+The analyzer produces this diagnostic when a constructor that redirects to
+another constructor also attempts to invoke a constructor from the
+superclass. The superclass constructor will be invoked when the constructor
+that the redirecting constructor is redirected to is invoked.
+
+#### Example
+
+The following code produces this diagnostic because the constructor `C.a`
+both redirects to `C.b` and invokes a constructor from the superclass:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : this.b(), [!super()!];
+  C.b();
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the invocation of the `super` constructor:
+
+{% prettify dart tag=pre+code %}
+class C {
+  C.a() : this.b();
+  C.b();
+}
+{% endprettify %}
+
 ### switch_expression_not_assignable
 
 _Type '{0}' of the switch expression isn't assignable to the type '{1}' of case
@@ -8372,6 +9783,48 @@
 var a = A<int>();
 {% endprettify %}
 
+### type_parameter_referenced_by_static
+
+_Static members can't reference type parameters of the class._
+
+#### Description
+
+The analyzer produces this diagnostic when a static member references a
+type parameter that is declared for the class. Type parameters only have
+meaning for instances of the class.
+
+#### Example
+
+The following code produces this diagnostic because the static method
+`hasType` has a reference to the type parameter `T`:
+
+{% prettify dart tag=pre+code %}
+class C<T> {
+  static bool hasType(Object o) => o is [!T!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the member can be an instance member, then remove the keyword `static`:
+
+{% prettify dart tag=pre+code %}
+class C<T> {
+  bool hasType(Object o) => o is T;
+}
+{% endprettify %}
+
+If the member must be a static member, then make the member be generic:
+
+{% prettify dart tag=pre+code %}
+class C<T> {
+  static bool hasType<S>(Object o) => o is S;
+}
+{% endprettify %}
+
+Note, however, that there isn’t a relationship between `T` and `S`, so this
+second option changes the semantics from what was likely to be intended.
+
 ### type_test_with_undefined_name
 
 _The name '{0}' isn't defined, so it can't be used in an 'is' expression._
@@ -8408,9 +9861,28 @@
 
 ### unchecked_use_of_nullable_value
 
+_A nullable expression can't be used as a condition._
+
+_A nullable expression can't be used as an iterator in a for-in loop._
+
+_A nullable expression can't be used in a spread._
+
+_A nullable expression can't be used in a yield-each statement._
+
 _An expression whose value can be 'null' must be null-checked before it can be
 dereferenced._
 
+_The function can't be unconditionally invoked because it can be 'null'._
+
+_The method '{0}' can't be unconditionally invoked because the receiver can be
+'null'._
+
+_The operator '{0}' can't be unconditionally invoked because the receiver can be
+'null'._
+
+_The property '{0}' can't be unconditionally accessed because the receiver can
+be 'null'._
+
 #### Description
 
 The analyzer produces this diagnostic when an expression whose type is
@@ -9494,6 +10966,84 @@
 }
 {% endprettify %}
 
+### unnecessary_type_check
+
+_Unnecessary type check; the result is always 'false'._
+
+_Unnecessary type check; the result is always 'true'._
+
+#### Description
+
+The analyzer produces this diagnostic when the value of a type check (using
+either `is` or `is!`) is known at compile time.
+
+#### Example
+
+The following code produces this diagnostic because the test `a is Object?`
+is always `true`:
+
+{% prettify dart tag=pre+code %}
+bool f<T>(T a) => [!a is Object?!];
+{% endprettify %}
+
+#### Common fixes
+
+If the type check doesn't check what you intended to check, then change the
+test:
+
+{% prettify dart tag=pre+code %}
+bool f<T>(T a) => a is Object;
+{% endprettify %}
+
+If the type check does check what you intended to check, then replace the
+type check with its known value or completely remove it:
+
+{% prettify dart tag=pre+code %}
+bool f<T>(T a) => true;
+{% endprettify %}
+
+### unqualified_reference_to_non_local_static_member
+
+_Static members from supertypes must be qualified by the name of the defining
+type._
+
+#### Description
+
+The analyzer produces this diagnostic when code in one class references a
+static member in a superclass without prefixing the member's name with the
+name of the superclass. Static members can only be referenced without a
+prefix in the class in which they're declared.
+
+#### Example
+
+The following code produces this diagnostic because the static field `x` is
+referenced in the getter `g` without prefixing it with the name of the
+defining class:
+
+{% prettify dart tag=pre+code %}
+class A {
+  static int x = 3;
+}
+
+class B extends A {
+  int get g => [!x!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+Prefix the name of the static member with the name of the declaring class:
+
+{% prettify dart tag=pre+code %}
+class A {
+  static int x = 3;
+}
+
+class B extends A {
+  int get g => A.x;
+}
+{% endprettify %}
+
 ### unqualified_reference_to_static_member_of_extended_type
 
 _Static members from the extended type or one of its superclasses must be
@@ -9898,6 +11448,39 @@
 If the file isn't a generated file, then check the spelling of the URI or
 create the file.
 
+### uri_with_interpolation
+
+_URIs can't use string interpolation._
+
+#### Description
+
+The analyzer produces this diagnostic when the string literal in an
+`import`, `export`, or `part` directive contains an interpolation. The
+resolution of the URIs in directives must happen before the declarations
+are compiled, so expressions can’t be  evaluated  while determining the
+values of the URIs.
+
+#### Example
+
+The following code produces this diagnostic because the string in the
+`import` directive contains an interpolation:
+
+{% prettify dart tag=pre+code %}
+import [!'dart:$m'!];
+
+const m = 'math';
+{% endprettify %}
+
+#### Common fixes
+
+Remove the interpolation from the URI:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math';
+
+var zero = min(0, 0);
+{% endprettify %}
+
 ### use_of_void_result
 
 _This expression has a type of 'void' so its value can't be used._
@@ -9966,6 +11549,8 @@
 
 ### wrong_number_of_parameters_for_operator
 
+_Operator '-' should declare 0 or 1 parameter, but {0} found._
+
 _Operator '{0}' should declare exactly {1} parameters, but {2} found._
 
 #### Description
@@ -10130,6 +11715,49 @@
 int f(C c) => c.m(2);
 {% endprettify %}
 
+### yield_of_invalid_type
+
+_The type '{0}' implied by the 'yield' expression must be assignable to '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the type of object produced by a
+`yield` expression doesn't match the type of objects that are to be
+returned from the `Iterable` or `Stream` types that are returned from a
+generator (a function or method marked with either `sync*` or `async*`).
+
+#### Example
+
+The following code produces this diagnostic because the getter `zero` is
+declared to return an `Iterable` that returns integers, but the `yield` is
+returning a string from the iterable:
+
+{% prettify dart tag=pre+code %}
+Iterable<int> get zero sync* {
+  yield [!'0'!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the return type of the function is correct, then fix the expression
+following the keyword `yield` to return the correct type:
+
+{% prettify dart tag=pre+code %}
+Iterable<int> get zero sync* {
+  yield 0;
+}
+{% endprettify %}
+
+If the expression following the `yield` is correct, then change the return
+type of the function to allow it:
+
+{% prettify dart tag=pre+code %}
+Iterable<String> get zero sync* {
+  yield '0';
+}
+{% endprettify %}
+
 ### undefined_super_method
 
 See [undefined_super_member](#undefined_super_member).
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index 1993ae8..356e81f 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -576,7 +576,7 @@
   }
 
   @override
-  dynamic internalProblem(Message message, int charOffset, Uri uri) {
+  internalProblem(Message message, int charOffset, Uri uri) {
     throw UnsupportedError(message.message);
   }
 
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index ec2ad2b..c015730 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -313,10 +313,6 @@
 
             // Add empty synthetic units for unresolved `part` URIs.
             if (partSource == null) {
-              var unit = analysisDriver.fsState.unresolvedFile.parse();
-              inputUnits.add(
-                LinkInputUnit(partUri, null, true, unit),
-              );
               continue;
             }
 
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 1115b86..cd9a1cc 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -22,7 +22,6 @@
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/results.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/interner.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 0ec7a94..61ea617 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -459,7 +459,7 @@
       var bytes = File(aSum).readAsBytesSync();
       var bundle = PackageBundleReader(bytes);
       expect(_linkedLibraryUriList(bundle), [aUri]);
-      expect(_linkedLibraryUnitUriList(bundle, aUri), [aUri, '']);
+      expect(_linkedLibraryUnitUriList(bundle, aUri), [aUri]);
     });
   }
 
diff --git a/pkg/analyzer_cli/tool/perf.dart b/pkg/analyzer_cli/tool/perf.dart
index bd94085..e4e3dcb 100644
--- a/pkg/analyzer_cli/tool/perf.dart
+++ b/pkg/analyzer_cli/tool/perf.dart
@@ -17,7 +17,6 @@
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
-import 'package:analyzer/src/file_system/file_system.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index 6aaac51..664cdce 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1294,7 +1294,7 @@
       An enumeration of the kinds of elements.
     </p>
     
-  <dl><dt class="value">CLASS</dt><dt class="value">CLASS_TYPE_ALIAS</dt><dt class="value">COMPILATION_UNIT</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_INVOCATION</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dt class="value">FILE</dt><dt class="value">FUNCTION</dt><dt class="value">FUNCTION_INVOCATION</dt><dt class="value">FUNCTION_TYPE_ALIAS</dt><dt class="value">GETTER</dt><dt class="value">LABEL</dt><dt class="value">LIBRARY</dt><dt class="value">LOCAL_VARIABLE</dt><dt class="value">METHOD</dt><dt class="value">MIXIN</dt><dt class="value">PARAMETER</dt><dt class="value">PREFIX</dt><dt class="value">SETTER</dt><dt class="value">TOP_LEVEL_VARIABLE</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNIT_TEST_GROUP</dt><dt class="value">UNIT_TEST_TEST</dt><dt class="value">UNKNOWN</dt></dl></dd><dt class="typeDefinition"><a name="type_FilePath">FilePath: String</a></dt><dd>
+  <dl><dt class="value">CLASS</dt><dt class="value">CLASS_TYPE_ALIAS</dt><dt class="value">COMPILATION_UNIT</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_INVOCATION</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dt class="value">FILE</dt><dt class="value">FUNCTION</dt><dt class="value">FUNCTION_INVOCATION</dt><dt class="value">FUNCTION_TYPE_ALIAS</dt><dt class="value">GETTER</dt><dt class="value">LABEL</dt><dt class="value">LIBRARY</dt><dt class="value">LOCAL_VARIABLE</dt><dt class="value">METHOD</dt><dt class="value">MIXIN</dt><dt class="value">PARAMETER</dt><dt class="value">PREFIX</dt><dt class="value">SETTER</dt><dt class="value">TOP_LEVEL_VARIABLE</dt><dt class="value">TYPE_ALIAS</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNIT_TEST_GROUP</dt><dt class="value">UNIT_TEST_TEST</dt><dt class="value">UNKNOWN</dt></dl></dd><dt class="typeDefinition"><a name="type_FilePath">FilePath: String</a></dt><dd>
     
     <p>
       The absolute, normalized path of a file.
@@ -1309,7 +1309,7 @@
       An enumeration of the kinds of folding regions.
     </p>
     
-  <dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
+  <dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">COMMENT</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
     <p>
       A description of a region that can be folded.
     </p>
@@ -1397,7 +1397,7 @@
       </dd><dt class="value">TOP_LEVEL_VARIABLE</dt><dd>
         
         <p>Deprecated - no longer sent.</p>
-      </dd><dt class="value">PARAMETER_DECLARATION</dt><dt class="value">PARAMETER_REFERENCE</dt><dt class="value">STATIC_FIELD_DECLARATION</dt><dt class="value">STATIC_GETTER_DECLARATION</dt><dt class="value">STATIC_GETTER_REFERENCE</dt><dt class="value">STATIC_METHOD_DECLARATION</dt><dt class="value">STATIC_METHOD_REFERENCE</dt><dt class="value">STATIC_SETTER_DECLARATION</dt><dt class="value">STATIC_SETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_FUNCTION_DECLARATION</dt><dt class="value">TOP_LEVEL_FUNCTION_REFERENCE</dt><dt class="value">TOP_LEVEL_GETTER_DECLARATION</dt><dt class="value">TOP_LEVEL_GETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_SETTER_DECLARATION</dt><dt class="value">TOP_LEVEL_SETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_VARIABLE_DECLARATION</dt><dt class="value">TYPE_NAME_DYNAMIC</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNRESOLVED_INSTANCE_MEMBER_REFERENCE</dt><dt class="value">VALID_STRING_ESCAPE</dt></dl></dd><dt class="typeDefinition"><a name="type_KytheEntry">KytheEntry: object</a></dt><dd>
+      </dd><dt class="value">PARAMETER_DECLARATION</dt><dt class="value">PARAMETER_REFERENCE</dt><dt class="value">STATIC_FIELD_DECLARATION</dt><dt class="value">STATIC_GETTER_DECLARATION</dt><dt class="value">STATIC_GETTER_REFERENCE</dt><dt class="value">STATIC_METHOD_DECLARATION</dt><dt class="value">STATIC_METHOD_REFERENCE</dt><dt class="value">STATIC_SETTER_DECLARATION</dt><dt class="value">STATIC_SETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_FUNCTION_DECLARATION</dt><dt class="value">TOP_LEVEL_FUNCTION_REFERENCE</dt><dt class="value">TOP_LEVEL_GETTER_DECLARATION</dt><dt class="value">TOP_LEVEL_GETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_SETTER_DECLARATION</dt><dt class="value">TOP_LEVEL_SETTER_REFERENCE</dt><dt class="value">TOP_LEVEL_VARIABLE_DECLARATION</dt><dt class="value">TYPE_ALIAS</dt><dt class="value">TYPE_NAME_DYNAMIC</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNRESOLVED_INSTANCE_MEMBER_REFERENCE</dt><dt class="value">VALID_STRING_ESCAPE</dt></dl></dd><dt class="typeDefinition"><a name="type_KytheEntry">KytheEntry: object</a></dt><dd>
     <p>
       This object matches the format and documentation of the Entry object
       documented in the
diff --git a/pkg/analyzer_plugin/doc/tutorial/assists.md b/pkg/analyzer_plugin/doc/tutorial/assists.md
index b71e33d..2be0e4d 100644
--- a/pkg/analyzer_plugin/doc/tutorial/assists.md
+++ b/pkg/analyzer_plugin/doc/tutorial/assists.md
@@ -62,7 +62,7 @@
     with AssistContributorMixin
     implements AssistContributor {
   static AssistKind wrapInIf =
-      new AssistKind('wrapInIf', 100, "Wrap in an 'if' statement");
+      AssistKind('wrapInIf', 100, "Wrap in an 'if' statement");
 
   DartAssistRequest request;
 
@@ -71,21 +71,24 @@
   AnalysisSession get session => request.result.session;
 
   @override
-  void computeAssists(DartAssistRequest request, AssistCollector collector) {
+  Future<void> computeAssists(DartAssistRequest request, AssistCollector collector) async {
     this.request = request;
     this.collector = collector;
-    _wrapInIf();
-    _wrapInWhile();
+    await _wrapInIf();
+    await _wrapInWhile();
     // ...
   }
 
-  void _wrapInIf() {
-    ChangeBuilder builder = new ChangeBuilder(session: session);
-    // TODO Build the edit to wrap the selection in a 'if' statement.
+  Future<void> _wrapInIf() async {
+    ChangeBuilder builder = ChangeBuilder(session: session);
+    await changeBuilder.addDartFileEdit(path,
+        (DartFileEditBuilder fileEditBuilder) {
+      // TODO Build the edit to wrap the selection in a 'if' statement.
+    });
     addAssist(wrapInIf, builder);
   }
 
-  void _wrapInWhile() {
+  Future<void> _wrapInWhile() async {
     // ...
   }
 }
@@ -99,8 +102,8 @@
   // ...
 
   @override
-  List<AssistContributor> getAssistContributors(AnalysisDriver driver) {
-    return <AssistContributor>[new MyAssistContributor()];
+  List<AssistContributor> getAssistContributors(String path) {
+    return <AssistContributor>[MyAssistContributor()];
   }
 }
 ```
diff --git a/pkg/analyzer_plugin/doc/tutorial/fixes.md b/pkg/analyzer_plugin/doc/tutorial/fixes.md
index 920ed30..b77e517 100644
--- a/pkg/analyzer_plugin/doc/tutorial/fixes.md
+++ b/pkg/analyzer_plugin/doc/tutorial/fixes.md
@@ -79,28 +79,31 @@
     with FixContributorMixin
     implements FixContributor {
   static FixKind defineComponent =
-      new FixKind('defineComponent', 100, "Define a component named {0}");
+      FixKind('defineComponent', 100, "Define a component named {0}");
 
   AnalysisSession get session => request.result.session;
 
   @override
-  void computeFixesForError(AnalysisError error) {
+  Future<void> computeFixesForError(AnalysisError error) async {
     ErrorCode code = error.errorCode;
     if (code == MyErrorCode.undefinedComponent) {
-      _defineComponent(error);
-      _useExistingComponent(error);
+      await _defineComponent(error);
+      await _useExistingComponent(error);
     }
   }
 
-  void _defineComponent(AnalysisError error) {
+  Future<void> _defineComponent(AnalysisError error) async {
     // TODO Get the name from the source code.
     String componentName = null;
-    ChangeBuilder builder = new ChangeBuilder(session: session);
-    // TODO Build the edit to insert the definition of the component.
+    ChangeBuilder builder = ChangeBuilder(session: session);
+    await changeBuilder.addDartFileEdit(path,
+        (DartFileEditBuilder fileEditBuilder) {
+      // TODO Build the edit to insert the definition of the component.
+    });
     addFix(error, defineComponent, builder, args: [componentName]);
   }
 
-  void _useExistingComponent(AnalysisError error) {
+  Future<void> _useExistingComponent(AnalysisError error) async {
     // ...
   }
 }
@@ -114,9 +117,8 @@
   // ...
 
   @override
-  List<FixContributor> getFixContributors(
-      AnalysisDriverGeneric driver) {
-    return <FixContributor>[new MyFixContributor()];
+  List<FixContributor> getFixContributors(String path) {
+    return <FixContributor>[MyFixContributor()];
   }
 }
 ```
diff --git a/pkg/analyzer_plugin/doc/tutorial/package_structure.md b/pkg/analyzer_plugin/doc/tutorial/package_structure.md
index 9572ece..c2443ec 100644
--- a/pkg/analyzer_plugin/doc/tutorial/package_structure.md
+++ b/pkg/analyzer_plugin/doc/tutorial/package_structure.md
@@ -56,7 +56,7 @@
 
 If a listed host package can be found (via the `.packages` file associated with
 the target package), then the tool looks in the host package for the folder
-`<host_package>/tools/analysis_plugin`. If that directory exists and contains a
+`<host_package>/tools/analyzer_plugin`. If that directory exists and contains a
 valid bootstrap package, then the bootstrap package is run as a plugin.
 
 ## Bootstrap Package Structure
@@ -87,7 +87,7 @@
 When a bootstrap package is to be run, the contents of the directory containing
 the bootstrap package are copied to a temporary directory, the [`pub`][pub]
 command is run in that directory to produce a `.packages` file for the bootstrap
-package, and the file `tools/analysis_plugin/bin/plugin.dart` is run in its own
+package, and the file `tools/analyzer_plugin/bin/plugin.dart` is run in its own
 isolate.
 
 [pub]:https://www.dartlang.org/tools/pub/get-started
diff --git a/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart b/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart
index 051d9d0..1def750 100644
--- a/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart
@@ -28,12 +28,10 @@
   @override
   Future<EditGetAssistsResult> handleEditGetAssists(
       EditGetAssistsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var request = await getAssistRequest(parameters);
     var generator = AssistGenerator(getAssistContributors(path));
-    var result = generator.generateAssistsResponse(request);
+    var result = await generator.generateAssistsResponse(request);
     result.sendNotifications(channel);
     return result.result;
   }
@@ -50,8 +48,6 @@
   @override
   Future<AssistRequest> getAssistRequest(
       EditGetAssistsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var result = await getResolvedUnitResult(path);
     return DartAssistRequestImpl(
diff --git a/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart b/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart
index ed39aba..4bbf59a 100644
--- a/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart
@@ -29,8 +29,6 @@
   @override
   Future<CompletionGetSuggestionsResult> handleCompletionGetSuggestions(
       CompletionGetSuggestionsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var request = await getCompletionRequest(parameters);
     var generator = CompletionGenerator(getCompletionContributors(path));
@@ -52,8 +50,6 @@
   @override
   Future<CompletionRequest> getCompletionRequest(
       CompletionGetSuggestionsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var result = await getResolvedUnitResult(parameters.file);
     return DartCompletionRequestImpl(
         resourceProvider, parameters.offset, result);
diff --git a/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart b/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart
index 1b8d651..f20d776 100644
--- a/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart
@@ -21,8 +21,6 @@
 mixin DartFixesMixin implements FixesMixin {
   @override
   Future<FixesRequest> getFixesRequest(EditGetFixesParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var offset = parameters.offset;
     var result = await getResolvedUnitResult(path);
@@ -59,12 +57,10 @@
   @override
   Future<EditGetFixesResult> handleEditGetFixes(
       EditGetFixesParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var request = await getFixesRequest(parameters);
     var generator = FixGenerator(getFixContributors(path));
-    var result = generator.generateFixesResponse(request);
+    var result = await generator.generateFixesResponse(request);
     result.sendNotifications(channel);
     return result.result;
   }
diff --git a/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart b/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart
index ecae950..6bc5e1b 100644
--- a/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart
@@ -19,8 +19,6 @@
 mixin DartFoldingMixin implements FoldingMixin {
   @override
   Future<FoldingRequest> getFoldingRequest(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var result = await getResolvedUnitResult(path);
     return DartFoldingRequestImpl(resourceProvider, result);
   }
@@ -44,8 +42,6 @@
 
   @override
   Future<void> sendFoldingNotification(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     try {
       var request = await getFoldingRequest(path);
       var generator = FoldingGenerator(getFoldingContributors(path));
diff --git a/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart b/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart
index a74deba..1a119bb 100644
--- a/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart
@@ -19,8 +19,6 @@
 mixin DartHighlightsMixin implements HighlightsMixin {
   @override
   Future<HighlightsRequest> getHighlightsRequest(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var result = await getResolvedUnitResult(path);
     return DartHighlightsRequestImpl(resourceProvider, result);
   }
@@ -44,8 +42,6 @@
 
   @override
   Future<void> sendHighlightsNotification(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     try {
       var request = await getHighlightsRequest(path);
       var generator = HighlightsGenerator(getHighlightsContributors(path));
diff --git a/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart b/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart
index 353ec8d..d452e0d 100644
--- a/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart
@@ -21,8 +21,6 @@
   @override
   Future<EntryRequest> getEntryRequest(
       KytheGetKytheEntriesParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var result = await getResolvedUnitResult(path);
     return DartEntryRequestImpl(resourceProvider, result);
@@ -48,8 +46,6 @@
   @override
   Future<KytheGetKytheEntriesResult> handleKytheGetKytheEntries(
       KytheGetKytheEntriesParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var request = await getEntryRequest(parameters);
     var generator = EntryGenerator(getEntryContributors(path));
diff --git a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
index fb215d7..07dbddb 100644
--- a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
@@ -21,8 +21,6 @@
   @override
   Future<NavigationRequest> getNavigationRequest(
       AnalysisGetNavigationParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var result = await getResolvedUnitResult(path);
     var offset = parameters.offset;
@@ -55,8 +53,6 @@
   @override
   Future<AnalysisGetNavigationResult> handleAnalysisGetNavigation(
       AnalysisGetNavigationParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var path = parameters.file;
     var request = await getNavigationRequest(parameters);
     var generator = NavigationGenerator(getNavigationContributors(path));
@@ -69,8 +65,6 @@
   /// server.
   @override
   Future<void> sendNavigationNotification(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     try {
       var request =
           await getNavigationRequest(AnalysisGetNavigationParams(path, -1, -1));
diff --git a/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart b/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart
index 7c2fd1e..72a2c6c 100644
--- a/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart
@@ -19,8 +19,6 @@
 mixin DartOccurrencesMixin implements OccurrencesMixin {
   @override
   Future<OccurrencesRequest> getOccurrencesRequest(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var result = await getResolvedUnitResult(path);
     return DartOccurrencesRequestImpl(resourceProvider, result);
   }
@@ -44,8 +42,6 @@
 
   @override
   Future<void> sendOccurrencesNotification(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     try {
       var request = await getOccurrencesRequest(path);
       var generator = OccurrencesGenerator(getOccurrencesContributors(path));
diff --git a/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart b/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart
index b249718..760103f 100644
--- a/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart
@@ -19,8 +19,6 @@
 mixin DartOutlineMixin implements OutlineMixin {
   @override
   Future<OutlineRequest> getOutlineRequest(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var result = await getResolvedUnitResult(path);
     return DartOutlineRequestImpl(resourceProvider, result);
   }
@@ -44,8 +42,6 @@
 
   @override
   Future<void> sendOutlineNotification(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     try {
       var request = await getOutlineRequest(path);
       var generator = OutlineGenerator(getOutlineContributors(path));
diff --git a/pkg/analyzer_plugin/lib/plugin/plugin.dart b/pkg/analyzer_plugin/lib/plugin/plugin.dart
index 970d5d9..cdf8829 100644
--- a/pkg/analyzer_plugin/lib/plugin/plugin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/plugin.dart
@@ -95,7 +95,8 @@
   /// Return the SDK manager used to manage SDKs.
   DartSdkManager get sdkManager => _sdkManager;
 
-  /// Return the version number of this plugin, encoded as a string.
+  /// Return the version number of the plugin spec required by this plugin,
+  /// encoded as a string.
   String get version;
 
   /// Handle the fact that the file with the given [path] has been modified.
@@ -153,8 +154,6 @@
   /// Throw a [RequestFailure] is the file cannot be analyzed or if the driver
   /// associated with the file is not an [AnalysisDriver].
   Future<ResolvedUnitResult> getResolvedUnitResult(String path) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var driver = driverForPath(path);
     if (driver is! AnalysisDriver) {
       // Return an error from the request.
@@ -176,8 +175,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<AnalysisGetNavigationResult> handleAnalysisGetNavigation(
       AnalysisGetNavigationParams params) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     return AnalysisGetNavigationResult(
         <String>[], <NavigationTarget>[], <NavigationRegion>[]);
   }
@@ -187,8 +184,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<AnalysisHandleWatchEventsResult> handleAnalysisHandleWatchEvents(
       AnalysisHandleWatchEventsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     for (var event in parameters.events) {
       switch (event.type) {
         case WatchEventType.ADD:
@@ -213,8 +208,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<AnalysisSetContextRootsResult> handleAnalysisSetContextRoots(
       AnalysisSetContextRootsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var contextRoots = parameters.roots;
     var oldRoots = driverMap.keys.toList();
     for (var contextRoot in contextRoots) {
@@ -244,8 +237,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<AnalysisSetPriorityFilesResult> handleAnalysisSetPriorityFiles(
       AnalysisSetPriorityFilesParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var files = parameters.files;
     var filesByDriver = <AnalysisDriverGeneric, List<String>>{};
     for (var file in files) {
@@ -269,8 +260,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<AnalysisSetSubscriptionsResult> handleAnalysisSetSubscriptions(
       AnalysisSetSubscriptionsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var subscriptions = parameters.subscriptions;
     var newSubscriptions = subscriptionManager.setSubscriptions(subscriptions);
     sendNotificationsForSubscriptions(newSubscriptions);
@@ -284,8 +273,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<AnalysisUpdateContentResult> handleAnalysisUpdateContent(
       AnalysisUpdateContentParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     Map<String, Object> files = parameters.files;
     files.forEach((String filePath, Object overlay) {
       if (overlay is AddContentOverlay) {
@@ -319,8 +306,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<CompletionGetSuggestionsResult> handleCompletionGetSuggestions(
       CompletionGetSuggestionsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     return CompletionGetSuggestionsResult(
         -1, -1, const <CompletionSuggestion>[]);
   }
@@ -330,8 +315,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<EditGetAssistsResult> handleEditGetAssists(
       EditGetAssistsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     return EditGetAssistsResult(const <PrioritizedSourceChange>[]);
   }
 
@@ -342,8 +325,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<EditGetAvailableRefactoringsResult> handleEditGetAvailableRefactorings(
       EditGetAvailableRefactoringsParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     return EditGetAvailableRefactoringsResult(const <RefactoringKind>[]);
   }
 
@@ -352,8 +333,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<EditGetFixesResult> handleEditGetFixes(
       EditGetFixesParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     return EditGetFixesResult(const <AnalysisErrorFixes>[]);
   }
 
@@ -362,8 +341,7 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<EditGetRefactoringResult> handleEditGetRefactoring(
       EditGetRefactoringParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    return await null;
+    return null;
   }
 
   /// Handle a 'kythe.getKytheEntries' request.
@@ -371,8 +349,7 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<KytheGetKytheEntriesResult> handleKytheGetKytheEntries(
       KytheGetKytheEntriesParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    return await null;
+    return null;
   }
 
   /// Handle a 'plugin.shutdown' request. Subclasses can override this method to
@@ -382,8 +359,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<PluginShutdownResult> handlePluginShutdown(
       PluginShutdownParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     return PluginShutdownResult();
   }
 
@@ -392,8 +367,6 @@
   /// Throw a [RequestFailure] if the request could not be handled.
   Future<PluginVersionCheckResult> handlePluginVersionCheck(
       PluginVersionCheckParams parameters) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var byteStorePath = parameters.byteStorePath;
     var sdkPath = parameters.sdkPath;
     var versionString = parameters.version;
@@ -511,8 +484,6 @@
   /// Compute the response that should be returned for the given [request], or
   /// `null` if the response has already been sent.
   Future<Response> _getResponse(Request request, int requestTime) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     ResponseResult result;
     switch (request.method) {
       case ANALYSIS_REQUEST_GET_NAVIGATION:
@@ -584,8 +555,6 @@
   /// The method that is called when a [request] is received from the analysis
   /// server.
   Future<void> _onRequest(Request request) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var requestTime = DateTime.now().millisecondsSinceEpoch;
     var id = request.id;
     Response response;
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 56bcadd..5bdb9aa 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -1718,6 +1718,7 @@
 ///   PREFIX
 ///   SETTER
 ///   TOP_LEVEL_VARIABLE
+///   TYPE_ALIAS
 ///   TYPE_PARAMETER
 ///   UNIT_TEST_GROUP
 ///   UNIT_TEST_TEST
@@ -1776,6 +1777,8 @@
   static const ElementKind TOP_LEVEL_VARIABLE =
       ElementKind._('TOP_LEVEL_VARIABLE');
 
+  static const ElementKind TYPE_ALIAS = ElementKind._('TYPE_ALIAS');
+
   static const ElementKind TYPE_PARAMETER = ElementKind._('TYPE_PARAMETER');
 
   static const ElementKind UNIT_TEST_GROUP = ElementKind._('UNIT_TEST_GROUP');
@@ -1809,6 +1812,7 @@
     PREFIX,
     SETTER,
     TOP_LEVEL_VARIABLE,
+    TYPE_ALIAS,
     TYPE_PARAMETER,
     UNIT_TEST_GROUP,
     UNIT_TEST_TEST,
@@ -1868,6 +1872,8 @@
         return SETTER;
       case 'TOP_LEVEL_VARIABLE':
         return TOP_LEVEL_VARIABLE;
+      case 'TYPE_ALIAS':
+        return TYPE_ALIAS;
       case 'TYPE_PARAMETER':
         return TYPE_PARAMETER;
       case 'UNIT_TEST_GROUP':
@@ -1904,6 +1910,7 @@
 ///   ANNOTATIONS
 ///   BLOCK
 ///   CLASS_BODY
+///   COMMENT
 ///   DIRECTIVES
 ///   DOCUMENTATION_COMMENT
 ///   FILE_HEADER
@@ -1920,6 +1927,8 @@
 
   static const FoldingKind CLASS_BODY = FoldingKind._('CLASS_BODY');
 
+  static const FoldingKind COMMENT = FoldingKind._('COMMENT');
+
   static const FoldingKind DIRECTIVES = FoldingKind._('DIRECTIVES');
 
   static const FoldingKind DOCUMENTATION_COMMENT =
@@ -1938,6 +1947,7 @@
     ANNOTATIONS,
     BLOCK,
     CLASS_BODY,
+    COMMENT,
     DIRECTIVES,
     DOCUMENTATION_COMMENT,
     FILE_HEADER,
@@ -1959,6 +1969,8 @@
         return BLOCK;
       case 'CLASS_BODY':
         return CLASS_BODY;
+      case 'COMMENT':
+        return COMMENT;
       case 'DIRECTIVES':
         return DIRECTIVES;
       case 'DOCUMENTATION_COMMENT':
@@ -2285,6 +2297,7 @@
 ///   TOP_LEVEL_SETTER_DECLARATION
 ///   TOP_LEVEL_SETTER_REFERENCE
 ///   TOP_LEVEL_VARIABLE_DECLARATION
+///   TYPE_ALIAS
 ///   TYPE_NAME_DYNAMIC
 ///   TYPE_PARAMETER
 ///   UNRESOLVED_INSTANCE_MEMBER_REFERENCE
@@ -2506,6 +2519,9 @@
   static const HighlightRegionType TOP_LEVEL_VARIABLE_DECLARATION =
       HighlightRegionType._('TOP_LEVEL_VARIABLE_DECLARATION');
 
+  static const HighlightRegionType TYPE_ALIAS =
+      HighlightRegionType._('TYPE_ALIAS');
+
   static const HighlightRegionType TYPE_NAME_DYNAMIC =
       HighlightRegionType._('TYPE_NAME_DYNAMIC');
 
@@ -2589,6 +2605,7 @@
     TOP_LEVEL_SETTER_DECLARATION,
     TOP_LEVEL_SETTER_REFERENCE,
     TOP_LEVEL_VARIABLE_DECLARATION,
+    TYPE_ALIAS,
     TYPE_NAME_DYNAMIC,
     TYPE_PARAMETER,
     UNRESOLVED_INSTANCE_MEMBER_REFERENCE,
@@ -2740,6 +2757,8 @@
         return TOP_LEVEL_SETTER_REFERENCE;
       case 'TOP_LEVEL_VARIABLE_DECLARATION':
         return TOP_LEVEL_VARIABLE_DECLARATION;
+      case 'TYPE_ALIAS':
+        return TYPE_ALIAS;
       case 'TYPE_NAME_DYNAMIC':
         return TYPE_NAME_DYNAMIC;
       case 'TYPE_PARAMETER':
diff --git a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart
index 664e448..2b35cc7 100644
--- a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart
+++ b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart
@@ -181,8 +181,6 @@
   Future<void> listen(void Function(Response response) onResponse,
       void Function(Notification notification) onNotification,
       {void Function(dynamic error) onError, void Function() onDone}) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     if (_isolate != null) {
       throw StateError('Cannot listen to the same channel more than once.');
     }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index e122c98..0ec115b 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -635,6 +635,15 @@
     if (offset <= node.fields.offset) {
       optype.includeTypeNameSuggestions = true;
     }
+
+    // If there is no type then the first "field" could be intended as a type
+    // so also include type name suggestions. eg:
+    //     class MyClass2 { static MyCl^ }
+    if (node.fields.type == null &&
+        (node.fields.variables.isEmpty ||
+            offset <= node.fields.variables.first.end)) {
+      optype.includeTypeNameSuggestions = true;
+    }
   }
 
   @override
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart
index 71b5b58..946ad5b 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart
@@ -46,16 +46,15 @@
     }
 
     for (var param in namedParams) {
-      if (param.hasRequired) {
+      if (param.hasRequired || param.isRequiredNamed) {
         if (buffer.isNotEmpty) {
           buffer.write(', ');
         }
         var name = param.name;
         buffer.write('$name: ');
         offset = buffer.length;
-        var defaultValue = 'null'; // originally _getDefaultValue(param)
-        buffer.write(defaultValue);
-        ranges.addAll([offset, defaultValue.length]);
+        buffer.write(name);
+        ranges.addAll([offset, name.length]);
       }
     }
 
@@ -140,9 +139,14 @@
       return type != null
           ? type.getDisplayString(withNullability: false)
           : 'dynamic';
-    } else if (element is FunctionTypeAliasElement) {
-      var returnType = element.function.returnType;
-      return returnType.getDisplayString(withNullability: false);
+    } else if (element is TypeAliasElement) {
+      var aliasedElement = element.aliasedElement;
+      if (aliasedElement is GenericFunctionTypeElement) {
+        var returnType = aliasedElement.returnType;
+        return returnType.getDisplayString(withNullability: false);
+      } else {
+        return null;
+      }
     } else {
       return null;
     }
diff --git a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
index a46f3bd..bd4f5a5 100644
--- a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
+++ b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
@@ -233,8 +233,13 @@
         return null;
       }
       parameters = element.parameters;
-    } else if (element is analyzer.FunctionTypeAliasElement) {
-      parameters = element.function.parameters;
+    } else if (element is analyzer.TypeAliasElement) {
+      var aliasedElement = element.aliasedElement;
+      if (aliasedElement is analyzer.GenericFunctionTypeElement) {
+        parameters = aliasedElement.parameters;
+      } else {
+        return null;
+      }
     } else {
       return null;
     }
@@ -275,9 +280,14 @@
       return type != null
           ? type.getDisplayString(withNullability: false)
           : 'dynamic';
-    } else if (element is analyzer.FunctionTypeAliasElement) {
-      var returnType = element.function.returnType;
-      return returnType.getDisplayString(withNullability: false);
+    } else if (element is analyzer.TypeAliasElement) {
+      var aliasedElement = element.aliasedElement;
+      if (aliasedElement is analyzer.GenericFunctionTypeElement) {
+        var returnType = aliasedElement.returnType;
+        return returnType.getDisplayString(withNullability: false);
+      } else {
+        return null;
+      }
     }
     return null;
   }
diff --git a/pkg/analyzer_plugin/lib/utilities/assist/assist.dart b/pkg/analyzer_plugin/lib/utilities/assist/assist.dart
index d6fa2a4..3e6290b 100644
--- a/pkg/analyzer_plugin/lib/utilities/assist/assist.dart
+++ b/pkg/analyzer_plugin/lib/utilities/assist/assist.dart
@@ -23,7 +23,7 @@
 abstract class AssistContributor {
   /// Contribute assists for the location in the file specified by the given
   /// [request] into the given [collector].
-  void computeAssists(
+  Future<void> computeAssists(
       covariant AssistRequest request, AssistCollector collector);
 }
 
@@ -41,13 +41,13 @@
   /// Create an 'edit.getAssists' response for the location in the file specified
   /// by the given [request]. If any of the contributors throws an exception,
   /// also create a non-fatal 'plugin.error' notification.
-  GeneratorResult<EditGetAssistsResult> generateAssistsResponse(
-      AssistRequest request) {
+  Future<GeneratorResult<EditGetAssistsResult>> generateAssistsResponse(
+      AssistRequest request) async {
     var notifications = <Notification>[];
     var collector = AssistCollectorImpl();
     for (var contributor in contributors) {
       try {
-        contributor.computeAssists(request, collector);
+        await contributor.computeAssists(request, collector);
       } catch (exception, stackTrace) {
         notifications.add(PluginErrorParams(
                 false, exception.toString(), stackTrace.toString())
@@ -78,14 +78,9 @@
   /// message `"Create a component named '{0}' in '{1}'"` contains two parameters.
   final String message;
 
-  /// A list of any associated error codes. Assists with associated error codes
-  /// can be presented as "fixes" for the associated errors by clients.
-  final List<String> associatedErrorCodes;
-
   /// Initialize a newly created kind of assist to have the given [id],
-  /// [priority], [message] and optionally any [associatedErrorCodes].
-  const AssistKind(this.id, this.priority, this.message,
-      {this.associatedErrorCodes});
+  /// [priority] and [message].
+  const AssistKind(this.id, this.priority, this.message);
 
   @override
   String toString() => id;
diff --git a/pkg/analyzer_plugin/lib/utilities/assist/assist_contributor_mixin.dart b/pkg/analyzer_plugin/lib/utilities/assist/assist_contributor_mixin.dart
index cbd2fcc..1546f14 100644
--- a/pkg/analyzer_plugin/lib/utilities/assist/assist_contributor_mixin.dart
+++ b/pkg/analyzer_plugin/lib/utilities/assist/assist_contributor_mixin.dart
@@ -25,8 +25,9 @@
     if (change.edits.isEmpty) {
       return;
     }
+    change.id = kind.id;
     change.message = formatList(kind.message, args);
     collector.addAssist(
-        PrioritizedSourceChange(kind.priority, builder.sourceChange));
+        PrioritizedSourceChange(kind.priority, change));
   }
 }
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart b/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart
index 0b192c3..4c225fe 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart
@@ -72,8 +72,6 @@
   /// non-fatal 'plugin.error' notification.
   Future<GeneratorResult<CompletionGetSuggestionsResult>>
       generateCompletionResponse(CompletionRequest request) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var notifications = <Notification>[];
     var collector = CompletionCollectorImpl();
     try {
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 d18758d..bac46ee 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
@@ -34,8 +34,6 @@
   @override
   Future<void> computeSuggestions(
       DartCompletionRequest request, CompletionCollector collector) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var target =
         CompletionTarget.forOffset(request.result.unit, request.offset);
     var optype = OpType.forCompletion(target, request.offset);
@@ -61,8 +59,6 @@
     CompletionTarget target,
     OpType optype,
   }) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     target ??= CompletionTarget.forOffset(request.result.unit, request.offset,
         entryPoint: entryPoint);
     optype ??= OpType.forCompletion(target, request.offset);
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 f5630f1..19b3cb0 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
@@ -26,8 +26,6 @@
   @override
   Future<void> computeSuggestions(
       DartCompletionRequest request, CompletionCollector collector) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var containingLibrary = request.result.libraryElement;
     // Gracefully degrade if the library element is not resolved
     // e.g. detached part file or source change
@@ -46,8 +44,6 @@
   /// Clients should not overload this function.
   Future<void> computeSuggestionsWithEntryPoint(DartCompletionRequest request,
       CompletionCollector collector, AstNode entryPoint) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     var containingLibrary = request.result.libraryElement;
     // Gracefully degrade if the library element is not resolved
     // e.g. detached part file or source change
diff --git a/pkg/analyzer_plugin/lib/utilities/fixes/fix_contributor_mixin.dart b/pkg/analyzer_plugin/lib/utilities/fixes/fix_contributor_mixin.dart
index 7f01aca..b4be5b0 100644
--- a/pkg/analyzer_plugin/lib/utilities/fixes/fix_contributor_mixin.dart
+++ b/pkg/analyzer_plugin/lib/utilities/fixes/fix_contributor_mixin.dart
@@ -30,18 +30,19 @@
     if (change.edits.isEmpty) {
       return;
     }
+    change.id = kind.id;
     change.message = formatList(kind.message, args);
     collector.addFix(
-        error, PrioritizedSourceChange(kind.priority, builder.sourceChange));
+        error, PrioritizedSourceChange(kind.priority, change));
   }
 
   @override
-  void computeFixes(DartFixesRequest request, FixCollector collector) {
+  Future<void> computeFixes(DartFixesRequest request, FixCollector collector) async {
     this.request = request;
     this.collector = collector;
     try {
       for (var error in request.errorsToFix) {
-        computeFixesForError(error);
+        await computeFixesForError(error);
       }
     } finally {
       this.request = null;
@@ -51,5 +52,5 @@
 
   /// Compute the fixes that are appropriate for the given [error] and add them
   /// to the fix [collector].
-  void computeFixesForError(AnalysisError error);
+  Future<void> computeFixesForError(AnalysisError error);
 }
diff --git a/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart b/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart
index 46c3a7d..8455680 100644
--- a/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart
+++ b/pkg/analyzer_plugin/lib/utilities/fixes/fixes.dart
@@ -33,7 +33,7 @@
 abstract class FixContributor {
   /// Contribute fixes for the location in the file specified by the given
   /// [request] into the given [collector].
-  void computeFixes(covariant FixesRequest request, FixCollector collector);
+  Future<void> computeFixes(covariant FixesRequest request, FixCollector collector);
 }
 
 /// The information about a requested set of fixes.
@@ -64,13 +64,13 @@
   /// Create an 'edit.getFixes' response for the location in the file specified
   /// by the given [request]. If any of the contributors throws an exception,
   /// also create a non-fatal 'plugin.error' notification.
-  GeneratorResult<EditGetFixesResult> generateFixesResponse(
-      FixesRequest request) {
+  Future<GeneratorResult<EditGetFixesResult>> generateFixesResponse(
+      FixesRequest request) async {
     var notifications = <Notification>[];
     var collector = FixCollectorImpl();
     for (var contributor in contributors) {
       try {
-        contributor.computeFixes(request, collector);
+        await contributor.computeFixes(request, collector);
       } catch (exception, stackTrace) {
         notifications.add(PluginErrorParams(
                 false, exception.toString(), stackTrace.toString())
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index d495c4f..e93caa5 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -259,6 +259,7 @@
 ///   PREFIX
 ///   SETTER
 ///   TOP_LEVEL_VARIABLE
+///   TYPE_ALIAS
 ///   TYPE_PARAMETER
 ///   UNIT_TEST_GROUP
 ///   UNIT_TEST_TEST
@@ -288,6 +289,7 @@
   'PREFIX',
   'SETTER',
   'TOP_LEVEL_VARIABLE',
+  'TYPE_ALIAS',
   'TYPE_PARAMETER',
   'UNIT_TEST_GROUP',
   'UNIT_TEST_TEST',
@@ -305,6 +307,7 @@
 ///   ANNOTATIONS
 ///   BLOCK
 ///   CLASS_BODY
+///   COMMENT
 ///   DIRECTIVES
 ///   DOCUMENTATION_COMMENT
 ///   FILE_HEADER
@@ -316,6 +319,7 @@
   'ANNOTATIONS',
   'BLOCK',
   'CLASS_BODY',
+  'COMMENT',
   'DIRECTIVES',
   'DOCUMENTATION_COMMENT',
   'FILE_HEADER',
@@ -418,6 +422,7 @@
 ///   TOP_LEVEL_SETTER_DECLARATION
 ///   TOP_LEVEL_SETTER_REFERENCE
 ///   TOP_LEVEL_VARIABLE_DECLARATION
+///   TYPE_ALIAS
 ///   TYPE_NAME_DYNAMIC
 ///   TYPE_PARAMETER
 ///   UNRESOLVED_INSTANCE_MEMBER_REFERENCE
@@ -493,6 +498,7 @@
   'TOP_LEVEL_SETTER_DECLARATION',
   'TOP_LEVEL_SETTER_REFERENCE',
   'TOP_LEVEL_VARIABLE_DECLARATION',
+  'TYPE_ALIAS',
   'TYPE_NAME_DYNAMIC',
   'TYPE_PARAMETER',
   'UNRESOLVED_INSTANCE_MEMBER_REFERENCE',
diff --git a/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart
index 67f2c28..955290a 100644
--- a/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart
@@ -55,7 +55,7 @@
   _TestAssistContributor(this.changes);
 
   @override
-  void computeAssists(AssistRequest request, AssistCollector collector) {
+  Future<void> computeAssists(AssistRequest request, AssistCollector collector) async {
     for (var change in changes) {
       collector.addAssist(change);
     }
diff --git a/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart
index 578c0ae..06a1c7f 100644
--- a/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart
@@ -61,7 +61,7 @@
   _TestFixContributor(this.changes);
 
   @override
-  void computeFixes(FixesRequest request, FixCollector collector) {
+  Future<void> computeFixes(FixesRequest request, FixCollector collector) async {
     for (var change in changes) {
       collector.addFix(request.errorsToFix[0], change);
     }
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index a634551..b7c0d5a 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -6,7 +6,6 @@
 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/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -15,7 +14,6 @@
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
-import 'package:analyzer/src/generated/testing/element_search.dart';
 import 'package:analyzer/src/test_utilities/mock_packages.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
@@ -95,13 +93,6 @@
     return context.driver;
   }
 
-  Element findElementInUnit(CompilationUnit unit, String name,
-      [ElementKind kind]) {
-    return findElementsByName(unit, name)
-        .where((e) => kind == null || e.kind == kind)
-        .single;
-  }
-
   @override
   File newFile(String path, {String content = ''}) {
     if (_analysisContextCollection != null && !path.endsWith('.dart')) {
diff --git a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
index 03082d7..ca144aa 100644
--- a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
@@ -9,6 +9,8 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
+import 'package:analyzer/src/test_utilities/find_element.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:test/test.dart';
 
 import 'abstract_context.dart';
@@ -19,18 +21,14 @@
   String testCode;
   String testFile;
   CompilationUnit testUnit;
-  CompilationUnitElement testUnitElement;
-  LibraryElement testLibraryElement;
+  FindNode findNode;
+  FindElement findElement;
 
   void addTestSource(String code) {
     testCode = code;
     addSource(testFile, code);
   }
 
-  Element findElement(String name, [ElementKind kind]) {
-    return findChildElement(testUnitElement, name, kind);
-  }
-
   int findEnd(String search) {
     return findOffset(search) + search.length;
   }
@@ -90,10 +88,15 @@
     return length;
   }
 
-  Future<void> resolveTestUnit(String code) async {
+  Future<void> resolveTestCode(String code) async {
     addTestSource(code);
+    await resolveTestFile();
+  }
+
+  Future resolveTestFile() async {
     var result = await resolveFile(testFile);
-    testUnit = (result).unit;
+    testCode = result.content;
+    testUnit = result.unit;
     if (verifyNoTestUnitErrors) {
       expect(result.errors.where((AnalysisError error) {
         return error.errorCode != HintCode.DEAD_CODE &&
@@ -105,8 +108,8 @@
             error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
       }), isEmpty);
     }
-    testUnitElement = testUnit.declaredElement;
-    testLibraryElement = testUnitElement.library;
+    findNode = FindNode(testCode, testUnit);
+    findElement = FindElement(testUnit);
   }
 
   @override
diff --git a/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart b/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart
index 5d75ed1..db1a6fc 100644
--- a/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart
@@ -15,17 +15,16 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../support/abstract_context.dart';
+import '../support/abstract_single_unit.dart';
 
 void main() {
   defineReflectiveTests(AnalyzerConverterTest);
 }
 
 @reflectiveTest
-class AnalyzerConverterTest extends AbstractContextTest {
+class AnalyzerConverterTest extends AbstractSingleUnitTest {
   AnalyzerConverter converter = AnalyzerConverter();
   analyzer.Source source;
-  String testFile;
 
   /// Assert that the given [pluginError] matches the given [analyzerError].
   void assertError(
@@ -200,14 +199,12 @@
   }
 
   Future<void> test_convertElement_class() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 @deprecated
 abstract class _A {}
 class B<K, V> {}''');
-    var unit = (await resolveFile(testFile))?.unit;
     {
-      var engineElement =
-          findElementInUnit(unit, '_A') as analyzer.ClassElement;
+      var engineElement = findElement.class_('_A');
       // create notification Element
       var element = converter.convertElement(engineElement);
       expect(element.kind, plugin.ElementKind.CLASS);
@@ -229,7 +226,7 @@
               plugin.Element.FLAG_PRIVATE);
     }
     {
-      var engineElement = findElementInUnit(unit, 'B') as analyzer.ClassElement;
+      var engineElement = findElement.class_('B');
       // create notification Element
       var element = converter.convertElement(engineElement);
       expect(element.kind, plugin.ElementKind.CLASS);
@@ -240,13 +237,11 @@
   }
 
   Future<void> test_convertElement_constructor() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 class A {
   const A.myConstructor(int a, [String b]);
 }''');
-    var unit = (await resolveFile(testFile))?.unit;
-    var engineElement =
-        findElementInUnit(unit, 'myConstructor') as analyzer.ConstructorElement;
+    var engineElement = findElement.constructor('myConstructor');
     // create notification Element
     var element = converter.convertElement(engineElement);
     expect(element.kind, plugin.ElementKind.CONSTRUCTOR);
@@ -278,14 +273,12 @@
   }
 
   Future<void> test_convertElement_enum() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 @deprecated
 enum _E1 { one, two }
 enum E2 { three, four }''');
-    var unit = (await resolveFile(testFile))?.unit;
     {
-      var engineElement =
-          findElementInUnit(unit, '_E1') as analyzer.ClassElement;
+      var engineElement = findElement.enum_('_E1');
       expect(engineElement.hasDeprecated, isTrue);
       // create notification Element
       var element = converter.convertElement(engineElement);
@@ -307,8 +300,7 @@
               plugin.Element.FLAG_PRIVATE);
     }
     {
-      var engineElement =
-          findElementInUnit(unit, 'E2') as analyzer.ClassElement;
+      var engineElement = findElement.enum_('E2');
       // create notification Element
       var element = converter.convertElement(engineElement);
       expect(element.kind, plugin.ElementKind.ENUM);
@@ -319,14 +311,12 @@
   }
 
   Future<void> test_convertElement_enumConstant() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 @deprecated
 enum _E1 { one, two }
 enum E2 { three, four }''');
-    var unit = (await resolveFile(testFile))?.unit;
     {
-      var engineElement =
-          findElementInUnit(unit, 'one') as analyzer.FieldElement;
+      var engineElement = findElement.field('one');
       // create notification Element
       var element = converter.convertElement(engineElement);
       expect(element.kind, plugin.ElementKind.ENUM_CONSTANT);
@@ -350,8 +340,7 @@
           plugin.Element.FLAG_CONST | plugin.Element.FLAG_STATIC);
     }
     {
-      var engineElement =
-          findElementInUnit(unit, 'three') as analyzer.FieldElement;
+      var engineElement = findElement.field('three');
       // create notification Element
       var element = converter.convertElement(engineElement);
       expect(element.kind, plugin.ElementKind.ENUM_CONSTANT);
@@ -370,7 +359,7 @@
           plugin.Element.FLAG_CONST | plugin.Element.FLAG_STATIC);
     }
     {
-      var engineElement = unit.declaredElement.enums[1].getField('index');
+      var engineElement = findElement.field('index', of: 'E2');
       // create notification Element
       var element = converter.convertElement(engineElement);
       expect(element.kind, plugin.ElementKind.FIELD);
@@ -388,7 +377,7 @@
       expect(element.flags, plugin.Element.FLAG_FINAL);
     }
     {
-      var engineElement = unit.declaredElement.enums[1].getField('values');
+      var engineElement = findElement.field('values', of: 'E2');
 
       // create notification Element
       var element = converter.convertElement(engineElement);
@@ -410,13 +399,11 @@
   }
 
   Future<void> test_convertElement_field() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 class A {
   static const myField = 42;
 }''');
-    var unit = (await resolveFile(testFile))?.unit;
-    var engineElement =
-        findElementInUnit(unit, 'myField') as analyzer.FieldElement;
+    var engineElement = findElement.field('myField');
     // create notification Element
     var element = converter.convertElement(engineElement);
     expect(element.kind, plugin.ElementKind.FIELD);
@@ -436,12 +423,10 @@
   }
 
   Future<void> test_convertElement_functionTypeAlias() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 typedef int F<T>(String x);
 ''');
-    var unit = (await resolveFile(testFile))?.unit;
-    var engineElement =
-        findElementInUnit(unit, 'F') as analyzer.FunctionTypeAliasElement;
+    var engineElement = findElement.typeAlias('F');
     // create notification Element
     var element = converter.convertElement(engineElement);
     expect(element.kind, plugin.ElementKind.FUNCTION_TYPE_ALIAS);
@@ -461,12 +446,10 @@
   }
 
   Future<void> test_convertElement_genericTypeAlias_function() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 typedef F<T> = int Function(String x);
 ''');
-    var unit = (await resolveFile(testFile))?.unit;
-    var engineElement =
-        findElementInUnit(unit, 'F') as analyzer.FunctionTypeAliasElement;
+    var engineElement = findElement.typeAlias('F');
     // create notification Element
     var element = converter.convertElement(engineElement);
     expect(element.kind, plugin.ElementKind.FUNCTION_TYPE_ALIAS);
@@ -486,14 +469,11 @@
   }
 
   Future<void> test_convertElement_getter() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 class A {
-  String get myGetter => 42;
+  int get myGetter => 42;
 }''');
-    var unit = (await resolveFile(testFile))?.unit;
-    var engineElement =
-        findElementInUnit(unit, 'myGetter', analyzer.ElementKind.GETTER)
-            as analyzer.PropertyAccessorElement;
+    var engineElement = findElement.getter('myGetter');
     // create notification Element
     var element = converter.convertElement(engineElement);
     expect(element.kind, plugin.ElementKind.GETTER);
@@ -501,26 +481,24 @@
     {
       var location = element.location;
       expect(location.file, testFile);
-      expect(location.offset, 23);
+      expect(location.offset, 20);
       expect(location.length, 'myGetter'.length);
       expect(location.startLine, 2);
-      expect(location.startColumn, 14);
+      expect(location.startColumn, 11);
     }
     expect(element.parameters, isNull);
-    expect(element.returnType, 'String');
+    expect(element.returnType, 'int');
     expect(element.flags, 0);
   }
 
   Future<void> test_convertElement_method() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 class A {
   static List<String> myMethod(int a, {String b, int c}) {
     return null;
   }
 }''');
-    var unit = (await resolveFile(testFile))?.unit;
-    var engineElement =
-        findElementInUnit(unit, 'myMethod') as analyzer.MethodElement;
+    var engineElement = findElement.method('myMethod');
     // create notification Element
     var element = converter.convertElement(engineElement);
     expect(element.kind, plugin.ElementKind.METHOD);
@@ -539,14 +517,11 @@
   }
 
   Future<void> test_convertElement_setter() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 class A {
   set mySetter(String x) {}
 }''');
-    var unit = (await resolveFile(testFile))?.unit;
-    var engineElement =
-        findElementInUnit(unit, 'mySetter', analyzer.ElementKind.SETTER)
-            as analyzer.PropertyAccessorElement;
+    var engineElement = findElement.setter('mySetter');
     // create notification Element
     var element = converter.convertElement(engineElement);
     expect(element.kind, plugin.ElementKind.SETTER);
@@ -615,16 +590,14 @@
   }
 
   Future<void> test_fromElement_LABEL() async {
-    addSource(testFile, '''
+    await resolveTestCode('''
 main() {
 myLabel:
   while (true) {
     break myLabel;
   }
 }''');
-    var unit = (await resolveFile(testFile))?.unit;
-    var engineElement =
-        findElementInUnit(unit, 'myLabel') as analyzer.LabelElement;
+    var engineElement = findElement.label('myLabel');
     // create notification Element
     var element = converter.convertElement(engineElement);
     expect(element.kind, plugin.ElementKind.LABEL);
diff --git a/pkg/analyzer_plugin/test/utilities/completion/inherited_reference_contributor_test.dart b/pkg/analyzer_plugin/test/utilities/completion/inherited_reference_contributor_test.dart
index 49d103d..2b63605 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/inherited_reference_contributor_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/inherited_reference_contributor_test.dart
@@ -53,7 +53,7 @@
     await computeSuggestions();
 
     assertSuggestMethod('foo', 'A', 'bool',
-        defaultArgListString: 'bar, baz: null');
+        defaultArgListString: 'bar, baz: baz');
   }
 
   Future<void> test_AwaitExpression_inherited() async {
diff --git a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
index c268c4e..59a19c1 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
@@ -114,7 +114,7 @@
     await computeSuggestions();
 
     assertSuggestMethod('foo', 'A', 'bool',
-        defaultArgListString: 'bar, baz: null');
+        defaultArgListString: 'bar, baz: baz');
   }
 
   Future<void> test_ArgumentList() async {
diff --git a/pkg/analyzer_plugin/test/utilities/range_factory_test.dart b/pkg/analyzer_plugin/test/utilities/range_factory_test.dart
index a2ac201..0250c35 100644
--- a/pkg/analyzer_plugin/test/utilities/range_factory_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/range_factory_test.dart
@@ -32,7 +32,7 @@
   }
 
   Future<void> test_argumentRange_all_mixed_noTrailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1, c: 2);
 }
@@ -42,7 +42,7 @@
   }
 
   Future<void> test_argumentRange_all_mixed_trailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1, c: 2, );
 }
@@ -52,7 +52,7 @@
   }
 
   Future<void> test_argumentRange_all_named_noTrailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(a: 0, b: 1, c: 2);
 }
@@ -62,7 +62,7 @@
   }
 
   Future<void> test_argumentRange_all_named_trailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(a: 0, b: 1, c: 2, );
 }
@@ -72,7 +72,7 @@
   }
 
   Future<void> test_argumentRange_all_positional_noTrailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1, 2);
 }
@@ -82,7 +82,7 @@
   }
 
   Future<void> test_argumentRange_all_positional_trailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1, 2, );
 }
@@ -92,7 +92,7 @@
   }
 
   Future<void> test_argumentRange_first_noTrailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1);
 }
@@ -102,7 +102,7 @@
   }
 
   Future<void> test_argumentRange_first_trailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1, );
 }
@@ -112,7 +112,7 @@
   }
 
   Future<void> test_argumentRange_last_noTrailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1);
 }
@@ -122,7 +122,7 @@
   }
 
   Future<void> test_argumentRange_last_trailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1, );
 }
@@ -132,7 +132,7 @@
   }
 
   Future<void> test_argumentRange_middle_noTrailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1, 2, 3);
 }
@@ -142,7 +142,7 @@
   }
 
   Future<void> test_argumentRange_middle_trailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0, 1, 2, 3, );
 }
@@ -152,7 +152,7 @@
   }
 
   Future<void> test_argumentRange_only_named() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(a: 0);
 }
@@ -162,7 +162,7 @@
   }
 
   Future<void> test_argumentRange_only_positional() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(0);
 }
@@ -172,13 +172,13 @@
   }
 
   Future<void> test_elementName() async {
-    await resolveTestUnit('class ABC {}');
-    var element = findElement('ABC');
+    await resolveTestCode('class ABC {}');
+    var element = findElement.class_('ABC');
     expect(range.elementName(element), SourceRange(6, 3));
   }
 
   Future<void> test_endEnd() async {
-    await resolveTestUnit('main() {}');
+    await resolveTestCode('main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     var mainBody = mainFunction.functionExpression.body;
@@ -186,14 +186,14 @@
   }
 
   Future<void> test_endLength() async {
-    await resolveTestUnit('main() {}');
+    await resolveTestCode('main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     expect(range.endLength(mainName, 3), SourceRange(4, 3));
   }
 
   Future<void> test_endStart() async {
-    await resolveTestUnit('main() {}');
+    await resolveTestCode('main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     var mainBody = mainFunction.functionExpression.body;
@@ -206,14 +206,14 @@
   }
 
   Future<void> test_node() async {
-    await resolveTestUnit('main() {}');
+    await resolveTestCode('main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     expect(range.node(mainName), SourceRange(0, 4));
   }
 
   Future<void> test_nodeInList_argumentList_first_named() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(a: 1, b: 2);
 }
@@ -224,7 +224,7 @@
   }
 
   Future<void> test_nodeInList_argumentList_first_positional() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(1, 2);
 }
@@ -235,7 +235,7 @@
   }
 
   Future<void> test_nodeInList_argumentList_last_named() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(a: 1, b: 2);
 }
@@ -246,7 +246,7 @@
   }
 
   Future<void> test_nodeInList_argumentList_last_positional() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(1, 2);
 }
@@ -257,7 +257,7 @@
   }
 
   Future<void> test_nodeInList_argumentList_middle_named() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(a: 1, b: 2, c: 3);
 }
@@ -268,7 +268,7 @@
   }
 
   Future<void> test_nodeInList_argumentList_middle_positional() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(1, 2, 3);
 }
@@ -279,7 +279,7 @@
   }
 
   Future<void> test_nodeInList_argumentList_only_named() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(a: 1);
 }
@@ -290,7 +290,7 @@
   }
 
   Future<void> test_nodeInList_argumentList_only_named_trailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(a: 1,);
 }
@@ -301,7 +301,7 @@
   }
 
   Future<void> test_nodeInList_argumentList_only_positional() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(1);
 }
@@ -313,7 +313,7 @@
 
   Future<void>
       test_nodeInList_argumentList_only_positional_trailingComma() async {
-    await resolveTestUnit('''
+    await resolveTestCode('''
 void f() {
   g(1,);
 }
@@ -324,7 +324,7 @@
   }
 
   Future<void> test_nodes() async {
-    await resolveTestUnit(' main() {}');
+    await resolveTestCode(' main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     var mainBody = mainFunction.functionExpression.body;
@@ -332,7 +332,7 @@
   }
 
   Future<void> test_nodes_empty() async {
-    await resolveTestUnit('main() {}');
+    await resolveTestCode('main() {}');
     expect(range.nodes([]), SourceRange(0, 0));
   }
 
@@ -341,7 +341,7 @@
   }
 
   Future<void> test_startEnd_nodeNode() async {
-    await resolveTestUnit(' main() {}');
+    await resolveTestCode(' main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     var mainBody = mainFunction.functionExpression.body;
@@ -349,7 +349,7 @@
   }
 
   Future<void> test_startLength_node() async {
-    await resolveTestUnit(' main() {}');
+    await resolveTestCode(' main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     expect(range.startLength(mainName, 10), SourceRange(1, 10));
@@ -360,7 +360,7 @@
   }
 
   Future<void> test_startStart_nodeNode() async {
-    await resolveTestUnit('main() {}');
+    await resolveTestCode('main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     var mainBody = mainFunction.functionExpression.body;
@@ -368,7 +368,7 @@
   }
 
   Future<void> test_token() async {
-    await resolveTestUnit(' main() {}');
+    await resolveTestCode(' main() {}');
     var mainFunction = testUnit.declarations[0] as FunctionDeclaration;
     var mainName = mainFunction.name;
     expect(range.token(mainName.beginToken), SourceRange(1, 4));
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index b1c7056..c2562cf 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -6,7 +6,7 @@
 </head>
 <body>
 <h1>Common Types</h1>
-<version>1.4.0</version>
+<version>1.4.2</version>
 <p>
   This document contains a specification of the types that are common between
   the analysis server wire protocol and the analysis server plugin wire
@@ -550,6 +550,7 @@
       <value><code>PREFIX</code></value>
       <value><code>SETTER</code></value>
       <value><code>TOP_LEVEL_VARIABLE</code></value>
+      <value><code>TYPE_ALIAS</code></value>
       <value><code>TYPE_PARAMETER</code></value>
       <value><code>UNIT_TEST_GROUP</code></value>
       <value><code>UNIT_TEST_TEST</code></value>
@@ -575,6 +576,7 @@
       <value><code>ANNOTATIONS</code></value>
       <value><code>BLOCK</code></value>
       <value><code>CLASS_BODY</code></value>
+      <value><code>COMMENT</code></value>
       <value><code>DIRECTIVES</code></value>
       <value><code>DOCUMENTATION_COMMENT</code></value>
       <value><code>FILE_HEADER</code></value>
@@ -816,6 +818,9 @@
       <value>
         <code>TOP_LEVEL_VARIABLE_DECLARATION</code>
       </value>
+      <value>
+        <code>TYPE_ALIAS</code>
+      </value>
       <value><code>TYPE_NAME_DYNAMIC</code></value>
       <value><code>TYPE_PARAMETER</code></value>
       <value>
diff --git a/pkg/analyzer_utilities/analysis_options.yaml b/pkg/analyzer_utilities/analysis_options.yaml
index 7b2fbe6..f848bc6 100644
--- a/pkg/analyzer_utilities/analysis_options.yaml
+++ b/pkg/analyzer_utilities/analysis_options.yaml
@@ -1,3 +1,5 @@
+include: package:pedantic/analysis_options.1.9.0.yaml
+
 analyzer:
   strong-mode:
     implicit-casts: false
diff --git a/pkg/analyzer_utilities/lib/html.dart b/pkg/analyzer_utilities/lib/html.dart
index 1cbce5f..859740f 100644
--- a/pkg/analyzer_utilities/lib/html.dart
+++ b/pkg/analyzer_utilities/lib/html.dart
@@ -2,23 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * Tools for manipulating HTML during code generation of analyzer and analysis
- * server.
- */
+/// Tools for manipulating HTML during code generation of analyzer and analysis
+/// server.
 import 'package:html/dom.dart' as dom;
 
-/**
- * Make a deep copy of the given HTML nodes.
- */
+/// Make a deep copy of the given HTML nodes.
 List<dom.Node> cloneHtmlNodes(List<dom.Node> nodes) =>
     nodes.map((dom.Node node) => node.clone(true)).toList();
 
-/**
- * Return true if the given iterable contains only whitespace text nodes.
- */
+/// Return true if the given iterable contains only whitespace text nodes.
 bool containsOnlyWhitespace(Iterable<dom.Node> nodes) {
-  for (dom.Node node in nodes) {
+  for (var node in nodes) {
     if (!isWhitespaceNode(node)) {
       return false;
     }
@@ -26,11 +20,9 @@
   return true;
 }
 
-/**
- * Get the text contents of the element, ignoring all markup.
- */
+/// Get the text contents of the element, ignoring all markup.
 String innerText(dom.Element parent) {
-  StringBuffer buffer = new StringBuffer();
+  var buffer = StringBuffer();
   void recurse(dom.Element parent) {
     for (dom.Node child in parent.nodes) {
       if (child is dom.Text) {
@@ -45,10 +37,8 @@
   return buffer.toString();
 }
 
-/**
- * Return true if the given node is a text node containing only whitespace, or
- * a comment.
- */
+/// Return true if the given node is a text node containing only whitespace, or
+/// a comment.
 bool isWhitespaceNode(dom.Node node) {
   if (node is dom.Element) {
     return false;
@@ -59,48 +49,38 @@
   return true;
 }
 
-/**
- * Create an HTML element with the given name, attributes, and child nodes.
- */
+/// Create an HTML element with the given name, attributes, and child nodes.
 dom.Element makeElement(
     String name, Map<dynamic, String> attributes, List<dom.Node> children) {
-  dom.Element result = new dom.Element.tag(name);
+  var result = dom.Element.tag(name);
   result.attributes.addAll(attributes);
-  for (dom.Node child in children) {
+  for (var child in children) {
     result.append(child);
   }
   return result;
 }
 
-/**
- * Mixin class for generating HTML.
- */
+/// Mixin class for generating HTML.
 mixin HtmlGenerator {
-  List<dom.Node> _html;
+  List<dom.Node> _html = [];
 
-  /**
-   * Add the given [node] to the HTML output.
-   */
+  /// Add the given [node] to the HTML output.
   void add(dom.Node node) {
     _html.add(node);
   }
 
-  /**
-   * Add the given [nodes] to the HTML output.
-   */
+  /// Add the given [nodes] to the HTML output.
   void addAll(Iterable<dom.Node> nodes) {
-    for (dom.Node node in nodes) {
+    for (var node in nodes) {
       add(node);
     }
   }
 
-  /**
-   * Execute [callback], collecting any code that is output using [write],
-   * [writeln], [add], [addAll] or [element], and return the result as a list
-   * of HTML nodes.
-   */
-  List<dom.Node> collectHtml(void callback()) {
-    List<dom.Node> oldHtml = _html;
+  /// Execute [callback], collecting any code that is output using [write],
+  /// [writeln], [add], [addAll] or [element], and return the result as a list
+  /// of HTML nodes.
+  List<dom.Node> collectHtml(void Function()? callback) {
+    var oldHtml = _html;
     try {
       _html = <dom.Node>[];
       if (callback != null) {
@@ -112,25 +92,19 @@
     }
   }
 
-  /**
-   * Execute [callback], wrapping its output in an element with the given
-   * [name] and [attributes].
-   */
+  /// Execute [callback], wrapping its output in an element with the given
+  /// [name] and [attributes].
   void element(String name, Map<dynamic, String> attributes,
-      [void callback()]) {
+      [void Function()? callback]) {
     add(makeElement(name, attributes, collectHtml(callback)));
   }
 
-  /**
-   * Output text without ending the current line.
-   */
+  /// Output text without ending the current line.
   void write(String text) {
-    _html.add(new dom.Text(text));
+    _html.add(dom.Text(text));
   }
 
-  /**
-   * Output text, ending the current line.
-   */
+  /// Output text, ending the current line.
   void writeln([Object obj = '']) {
     write('$obj\n');
   }
diff --git a/pkg/analyzer_utilities/lib/text_formatter.dart b/pkg/analyzer_utilities/lib/text_formatter.dart
index a35920b..79c92d2 100644
--- a/pkg/analyzer_utilities/lib/text_formatter.dart
+++ b/pkg/analyzer_utilities/lib/text_formatter.dart
@@ -2,80 +2,57 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * Code for converting HTML into text, for use during code generation of
- * analyzer and analysis server.
- */
-
+/// Code for converting HTML into text, for use during code generation of
+/// analyzer and analysis server.
 import 'package:analyzer_utilities/tools.dart';
 import 'package:html/dom.dart' as dom;
 
-final RegExp whitespace = new RegExp(r'\s');
+final RegExp whitespace = RegExp(r'\s');
 
-/**
- * Convert the HTML in [desc] into text, word wrapping at width [width].
- *
- * If [javadocStyle] is true, then the output is compatible with Javadoc,
- * which understands certain HTML constructs.
- */
+/// Convert the HTML in [desc] into text, word wrapping at width [width].
+///
+/// If [javadocStyle] is true, then the output is compatible with Javadoc,
+/// which understands certain HTML constructs.
 String nodesToText(List<dom.Node> desc, int width, bool javadocStyle,
-    {bool removeTrailingNewLine: false}) {
-  _TextFormatter formatter = new _TextFormatter(width, javadocStyle);
+    {bool removeTrailingNewLine = false}) {
+  var formatter = _TextFormatter(width, javadocStyle);
   return formatter.collectCode(() {
     formatter.addAll(desc);
     formatter.lineBreak(false);
   }, removeTrailingNewLine: removeTrailingNewLine);
 }
 
-/**
- * Engine that transforms HTML to text.  The input HTML is processed one
- * character at a time, gathering characters into words and words into lines.
- */
+/// Engine that transforms HTML to text.  The input HTML is processed one
+/// character at a time, gathering characters into words and words into lines.
 class _TextFormatter extends CodeGenerator {
-  /**
-   * Word-wrapping width.
-   */
+  /// Word-wrapping width.
   final int width;
 
-  /**
-   * The word currently being gathered.
-   */
+  /// The word currently being gathered.
   String word = '';
 
-  /**
-   * The line currently being gathered.
-   */
+  /// The line currently being gathered.
   String line = '';
 
-  /**
-   * True if a blank line should be inserted before the next word.
-   */
+  /// True if a blank line should be inserted before the next word.
   bool verticalSpaceNeeded = false;
 
-  /**
-   * True if no text has been output yet.  This suppresses blank lines.
-   */
+  /// True if no text has been output yet.  This suppresses blank lines.
   bool atStart = true;
 
-  /**
-   * True if we are processing a <pre> element, thus whitespace should be
-   * preserved.
-   */
+  /// True if we are processing a <pre> element, thus whitespace should be
+  /// preserved.
   bool preserveSpaces = false;
 
-  /**
-   * True if the output should be Javadoc compatible.
-   */
+  /// True if the output should be Javadoc compatible.
   final bool javadocStyle;
 
   _TextFormatter(this.width, this.javadocStyle);
 
-  /**
-   * Process an HTML node.
-   */
+  /// Process an HTML node.
   void add(dom.Node node) {
     if (node is dom.Text) {
-      for (String char in node.text.split('')) {
+      for (var char in node.text.split('')) {
         if (preserveSpaces) {
           wordBreak();
           write(escape(char));
@@ -141,7 +118,7 @@
           if (javadocStyle) {
             writeln('<pre>');
           }
-          bool oldPreserveSpaces = preserveSpaces;
+          var oldPreserveSpaces = preserveSpaces;
           try {
             preserveSpaces = true;
             addAll(node.nodes);
@@ -166,25 +143,21 @@
         case 'head':
           break;
         default:
-          throw new Exception('Unexpected HTML element: ${node.localName}');
+          throw Exception('Unexpected HTML element: ${node.localName}');
       }
     } else {
-      throw new Exception('Unexpected HTML: $node');
+      throw Exception('Unexpected HTML: $node');
     }
   }
 
-  /**
-   * Process a list of HTML nodes.
-   */
+  /// Process a list of HTML nodes.
   void addAll(List<dom.Node> nodes) {
-    for (dom.Node node in nodes) {
+    for (var node in nodes) {
       add(node);
     }
   }
 
-  /**
-   * Escape the given character for HTML.
-   */
+  /// Escape the given character for HTML.
   String escape(String char) {
     if (javadocStyle) {
       switch (char) {
@@ -199,9 +172,7 @@
     return char;
   }
 
-  /**
-   * Terminate the current word and/or line, if either is in progress.
-   */
+  /// Terminate the current word and/or line, if either is in progress.
   void lineBreak(bool gap) {
     wordBreak();
     if (line.isNotEmpty) {
@@ -213,9 +184,7 @@
     }
   }
 
-  /**
-   * Insert vertical space if necessary.
-   */
+  /// Insert vertical space if necessary.
   void resolveVerticalSpace() {
     if (verticalSpaceNeeded) {
       writeln();
@@ -223,9 +192,7 @@
     }
   }
 
-  /**
-   * Terminate the current word, if a word is in progress.
-   */
+  /// Terminate the current word, if a word is in progress.
   void wordBreak() {
     if (word.isNotEmpty) {
       atStart = false;
diff --git a/pkg/analyzer_utilities/lib/tools.dart b/pkg/analyzer_utilities/lib/tools.dart
index c26e5a5..3ea8a6b 100644
--- a/pkg/analyzer_utilities/lib/tools.dart
+++ b/pkg/analyzer_utilities/lib/tools.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.
 
-/**
- * Tools for generating code in analyzer and analysis server.
- */
+/// Tools for generating code in analyzer and analysis server.
 import 'dart:async';
 import 'dart:io';
 
@@ -13,16 +11,14 @@
 import 'package:html/dom.dart' as dom;
 import 'package:path/path.dart';
 
-final RegExp trailingSpacesInLineRegExp = new RegExp(r' +$', multiLine: true);
-final RegExp trailingWhitespaceRegExp = new RegExp(r'[\n ]+$');
+final RegExp trailingSpacesInLineRegExp = RegExp(r' +$', multiLine: true);
+final RegExp trailingWhitespaceRegExp = RegExp(r'[\n ]+$');
 
-/**
- * Join the given strings using camelCase.  If [doCapitalize] is true, the first
- * part will be capitalized as well.
- */
-String camelJoin(List<String> parts, {bool doCapitalize: false}) {
-  List<String> upcasedParts = <String>[];
-  for (int i = 0; i < parts.length; i++) {
+/// Join the given strings using camelCase.  If [doCapitalize] is true, the first
+/// part will be capitalized as well.
+String camelJoin(List<String> parts, {bool doCapitalize = false}) {
+  var upcasedParts = <String>[];
+  for (var i = 0; i < parts.length; i++) {
     if (i == 0 && !doCapitalize) {
       upcasedParts.add(parts[i]);
     } else {
@@ -32,51 +28,38 @@
   return upcasedParts.join();
 }
 
-/**
- * Capitalize and return the passed String.
- */
+/// Capitalize and return the passed String.
 String capitalize(String string) {
   return string[0].toUpperCase() + string.substring(1);
 }
 
-/**
- * Type of functions used to compute the contents of a set of generated files.
- * [pkgPath] is the path to the current package.
- */
-typedef Map<String, FileContentsComputer> DirectoryContentsComputer(
+/// Type of functions used to compute the contents of a set of generated files.
+/// [pkgPath] is the path to the current package.
+typedef DirectoryContentsComputer = Map<String, FileContentsComputer> Function(
     String pkgPath);
 
-/**
- * Type of functions used to compute the contents of a generated file.
- * [pkgPath] is the path to the current package.
- */
-typedef Future<String> FileContentsComputer(String pkgPath);
+/// Type of functions used to compute the contents of a generated file.
+/// [pkgPath] is the path to the current package.
+typedef FileContentsComputer = Future<String> Function(String pkgPath);
 
-/**
- * Mixin class for generating code.
- */
+/// Mixin class for generating code.
 class CodeGenerator {
-  _CodeGeneratorState _state;
+  _CodeGeneratorState _state = _CodeGeneratorState();
 
-  /**
-   * Settings that specialize code generation behavior for a given
-   * programming language.
-   */
-  CodeGeneratorSettings codeGeneratorSettings = new CodeGeneratorSettings();
+  /// Settings that specialize code generation behavior for a given
+  /// programming language.
+  CodeGeneratorSettings codeGeneratorSettings = CodeGeneratorSettings();
 
-  /**
-   * Measure the width of the current indentation level.
-   */
+  /// Measure the width of the current indentation level.
   int get indentWidth => _state.nextIndent.length;
 
-  /**
-   * Execute [callback], collecting any code that is output using [write]
-   * or [writeln], and return the result as a string.
-   */
-  String collectCode(void callback(), {bool removeTrailingNewLine: false}) {
-    _CodeGeneratorState oldState = _state;
+  /// Execute [callback], collecting any code that is output using [write]
+  /// or [writeln], and return the result as a string.
+  String collectCode(void Function() callback,
+      {bool removeTrailingNewLine = false}) {
+    var oldState = _state;
     try {
-      _state = new _CodeGeneratorState();
+      _state = _CodeGeneratorState();
       callback();
       var text =
           _state.buffer.toString().replaceAll(trailingSpacesInLineRegExp, '');
@@ -90,49 +73,48 @@
     }
   }
 
-  /**
-   * Generate a doc comment based on the HTML in [docs].
-   *
-   * When generating java code, the output is compatible with Javadoc, which
-   * understands certain HTML constructs.
-   */
-  void docComment(List<dom.Node> docs, {bool removeTrailingNewLine: false}) {
+  /// Generate a doc comment based on the HTML in [docs].
+  ///
+  /// When generating java code, the output is compatible with Javadoc, which
+  /// understands certain HTML constructs.
+  void docComment(List<dom.Node> docs, {bool removeTrailingNewLine = false}) {
     if (containsOnlyWhitespace(docs)) return;
-    if (codeGeneratorSettings.docCommentStartMarker != null)
-      writeln(codeGeneratorSettings.docCommentStartMarker);
-    int width = codeGeneratorSettings.commentLineLength;
-    bool javadocStyle = codeGeneratorSettings.languageName == 'java';
+
+    var startMarker = codeGeneratorSettings.docCommentStartMarker;
+    if (startMarker != null) {
+      writeln(startMarker);
+    }
+
+    var width = codeGeneratorSettings.commentLineLength;
+    var javadocStyle = codeGeneratorSettings.languageName == 'java';
     indentBy(codeGeneratorSettings.docCommentLineLeader, () {
       write(nodesToText(docs, width - _state.indent.length, javadocStyle,
           removeTrailingNewLine: removeTrailingNewLine));
     });
-    if (codeGeneratorSettings.docCommentEndMarker != null)
-      writeln(codeGeneratorSettings.docCommentEndMarker);
+
+    var endMarker = codeGeneratorSettings.docCommentEndMarker;
+    if (endMarker != null) {
+      writeln(endMarker);
+    }
   }
 
-  /**
-   * Execute [callback], indenting any code it outputs.
-   */
-  void indent(void callback()) {
+  /// Execute [callback], indenting any code it outputs.
+  void indent(void Function() callback) {
     indentSpecial(
         codeGeneratorSettings.indent, codeGeneratorSettings.indent, callback);
   }
 
-  /**
-   * Execute [callback], using [additionalIndent] to indent any code it outputs.
-   */
-  void indentBy(String additionalIndent, void callback()) =>
+  /// Execute [callback], using [additionalIndent] to indent any code it outputs.
+  void indentBy(String additionalIndent, void Function() callback) =>
       indentSpecial(additionalIndent, additionalIndent, callback);
 
-  /**
-   * Execute [callback], using [additionalIndent] to indent any code it outputs.
-   * The first line of output is indented by [firstAdditionalIndent] instead of
-   * [additionalIndent].
-   */
-  void indentSpecial(
-      String firstAdditionalIndent, String additionalIndent, void callback()) {
-    String oldNextIndent = _state.nextIndent;
-    String oldIndent = _state.indent;
+  /// Execute [callback], using [additionalIndent] to indent any code it outputs.
+  /// The first line of output is indented by [firstAdditionalIndent] instead of
+  /// [additionalIndent].
+  void indentSpecial(String firstAdditionalIndent, String additionalIndent,
+      void Function() callback) {
+    var oldNextIndent = _state.nextIndent;
+    var oldIndent = _state.indent;
     try {
       _state.nextIndent += firstAdditionalIndent;
       _state.indent += additionalIndent;
@@ -148,13 +130,13 @@
       return;
     }
     write(codeGeneratorSettings.lineCommentLineLeader);
-    int width = codeGeneratorSettings.commentLineLength;
+    var width = codeGeneratorSettings.commentLineLength;
     indentBy(codeGeneratorSettings.lineCommentLineLeader, () {
       write(nodesToText(docs, width - _state.indent.length, false));
     });
   }
 
-  void outputHeader({bool javaStyle: false, String year = null}) {
+  void outputHeader({bool javaStyle = false, String? year}) {
     String header;
     if (codeGeneratorSettings.languageName == 'java') {
       header = '''
@@ -190,157 +172,129 @@
     writeln(header.trim());
   }
 
-  /**
-   * Output text without ending the current line.
-   */
+  /// Output text without ending the current line.
   void write(Object obj) {
     _state.write(obj.toString());
   }
 
-  /**
-   * Output text, ending the current line.
-   */
+  /// Output text, ending the current line.
   void writeln([Object obj = '']) {
     _state.write('$obj\n');
   }
 }
 
-/**
- * Controls several settings of [CodeGenerator].
- *
- * The default settings are valid for generating Java and Dart code.
- */
+/// Controls several settings of [CodeGenerator].
+///
+/// The default settings are valid for generating Java and Dart code.
 class CodeGeneratorSettings {
-  /**
-   * Name of the language being generated. Lowercase.
-   */
+  /// Name of the language being generated. Lowercase.
   String languageName;
 
-  /**
-   * Marker used in line comments.
-   */
+  /// Marker used in line comments.
   String lineCommentLineLeader;
 
-  /**
-   * Start marker for doc comments.
-   */
-  String docCommentStartMarker;
+  /// Start marker for doc comments.
+  String? docCommentStartMarker;
 
-  /**
-   * Line leader for body lines in doc comments.
-   */
+  /// Line leader for body lines in doc comments.
   String docCommentLineLeader;
 
-  /**
-   * End marker for doc comments.
-   */
-  String docCommentEndMarker;
+  /// End marker for doc comments.
+  String? docCommentEndMarker;
 
-  /**
-   * Line length for doc comment lines.
-   */
+  /// Line length for doc comment lines.
   int commentLineLength;
 
-  /**
-   * String used for indenting code.
-   */
+  /// String used for indenting code.
   String indent;
 
   CodeGeneratorSettings(
-      {this.languageName: 'java',
-      this.lineCommentLineLeader: '// ',
-      this.docCommentStartMarker: '/**',
-      this.docCommentLineLeader: ' * ',
-      this.docCommentEndMarker: ' */',
-      this.commentLineLength: 99,
-      this.indent: '  '});
+      {this.languageName = 'java',
+      this.lineCommentLineLeader = '// ',
+      this.docCommentStartMarker = '/**',
+      this.docCommentLineLeader = ' * ',
+      this.docCommentEndMarker = ' */',
+      this.commentLineLength = 99,
+      this.indent = '  '});
 }
 
-/**
- * A utility class for invoking dartfmt.
- */
+/// A utility class for invoking dartfmt.
 class DartFormat {
   static String get _dartfmtPath {
-    String binName = Platform.isWindows ? 'dartfmt.bat' : 'dartfmt';
+    var binName = Platform.isWindows ? 'dartfmt.bat' : 'dartfmt';
     for (var loc in [binName, join('dart-sdk', 'bin', binName)]) {
       var candidatePath = join(dirname(Platform.resolvedExecutable), loc);
-      if (new File(candidatePath).existsSync()) {
+      if (File(candidatePath).existsSync()) {
         return candidatePath;
       }
     }
-    throw new StateError('Could not find dartfmt executable');
+    throw StateError('Could not find dartfmt executable');
   }
 
   static void formatFile(File file) {
-    ProcessResult result = Process.runSync(_dartfmtPath, ['-w', file.path]);
-    if (result.exitCode != 0) throw result.stderr;
+    var result = Process.runSync(_dartfmtPath, ['-w', file.path]);
+    _throwIfExitCode(result);
   }
 
   static String formatText(String text) {
-    File file = new File(join(Directory.systemTemp.path, 'gen.dart'));
+    var file = File(join(Directory.systemTemp.path, 'gen.dart'));
     file.writeAsStringSync(text);
-    ProcessResult result = Process.runSync(_dartfmtPath, ['-w', file.path]);
-    if (result.exitCode != 0) throw result.stderr;
+    var result = Process.runSync(_dartfmtPath, ['-w', file.path]);
+    _throwIfExitCode(result);
     return file.readAsStringSync();
   }
+
+  static void _throwIfExitCode(ProcessResult result) {
+    if (result.exitCode != 0) throw result.stderr as Object;
+  }
 }
 
-/**
- * Abstract base class representing behaviors common to generated files and
- * generated directories.
- */
+/// Abstract base class representing behaviors common to generated files and
+/// generated directories.
 abstract class GeneratedContent {
-  /**
-   * Check whether the [output] has the correct contents, and return true if it
-   * does.  [pkgPath] is the path to the current package.
-   */
+  /// Check whether the [output] has the correct contents, and return true if it
+  /// does.  [pkgPath] is the path to the current package.
   Future<bool> check(String pkgPath);
 
-  /**
-   * Replace the [output] with the correct contents.  [pkgPath] is the path to
-   * the current package.
-   */
+  /// Replace the [output] with the correct contents.  [pkgPath] is the path to
+  /// the current package.
   Future<void> generate(String pkgPath);
 
-  /**
-   * Get a [FileSystemEntity] representing the output file or directory.
-   * [pkgPath] is the path to the current package.
-   */
+  /// Get a [FileSystemEntity] representing the output file or directory.
+  /// [pkgPath] is the path to the current package.
   FileSystemEntity output(String pkgPath);
 
-  /**
-   * Check that all of the [targets] are up to date.  If they are not, print
-   * out a message instructing the user to regenerate them, and exit with a
-   * nonzero error code.
-   *
-   * [pkgPath] is the path to the current package.  [generatorPath] is the path
-   * to a .dart script the user may use to regenerate the targets.
-   *
-   * To avoid mistakes when run on Windows, [generatorPath] always uses
-   * POSIX directory separators.
-   */
+  /// Check that all of the [targets] are up to date.  If they are not, print
+  /// out a message instructing the user to regenerate them, and exit with a
+  /// nonzero error code.
+  ///
+  /// [pkgPath] is the path to the current package.  [generatorPath] is the path
+  /// to a .dart script the user may use to regenerate the targets.
+  ///
+  /// To avoid mistakes when run on Windows, [generatorPath] always uses
+  /// POSIX directory separators.
   static Future<void> checkAll(
       String pkgPath, String generatorPath, Iterable<GeneratedContent> targets,
       {List<String> args = const []}) async {
-    bool generateNeeded = false;
-    for (GeneratedContent target in targets) {
-      bool ok = await target.check(pkgPath);
+    var generateNeeded = false;
+    for (var target in targets) {
+      var ok = await target.check(pkgPath);
       if (!ok) {
-        print("${target.output(pkgPath).absolute}"
+        print('${target.output(pkgPath).absolute}'
             " doesn't have expected contents.");
         generateNeeded = true;
       }
     }
     if (generateNeeded) {
       print('Please regenerate using:');
-      String executable = Platform.executable;
-      String packageRoot = '';
+      var executable = Platform.executable;
+      var packageRoot = '';
       // ignore: deprecated_member_use
       if (Platform.packageRoot != null) {
         // ignore: deprecated_member_use
         packageRoot = ' --package-root=${Platform.packageRoot}';
       }
-      String generateScript = normalize(joinAll(posix.split(generatorPath)));
+      var generateScript = normalize(joinAll(posix.split(generatorPath)));
       print('  $executable$packageRoot $generateScript ${args.join(" ")}');
       exit(1);
     } else {
@@ -348,46 +302,39 @@
     }
   }
 
-  /**
-   * Regenerate all of the [targets].  [pkgPath] is the path to the current
-   * package.
-   */
+  /// Regenerate all of the [targets].  [pkgPath] is the path to the current
+  /// package.
   static Future<void> generateAll(
       String pkgPath, Iterable<GeneratedContent> targets) async {
-    print("Generating...");
-    for (GeneratedContent target in targets) {
+    print('Generating...');
+    for (var target in targets) {
       await target.generate(pkgPath);
     }
   }
 }
 
-/**
- * Class representing a single output directory (either generated code or
- * generated HTML). No other content should exist in the directory.
- */
+/// Class representing a single output directory (either generated code or
+/// generated HTML). No other content should exist in the directory.
 class GeneratedDirectory extends GeneratedContent {
-  /**
-   * The path to the directory that will have the generated content.
-   */
+  /// The path to the directory that will have the generated content.
   final String outputDirPath;
 
-  /**
-   * Callback function that computes the directory contents.
-   */
+  /// Callback function that computes the directory contents.
   final DirectoryContentsComputer directoryContentsComputer;
 
   GeneratedDirectory(this.outputDirPath, this.directoryContentsComputer);
 
   @override
   Future<bool> check(String pkgPath) async {
-    Directory outputDirectory = output(pkgPath);
-    Map<String, FileContentsComputer> map = directoryContentsComputer(pkgPath);
+    var outputDirectory = output(pkgPath);
+    var map = directoryContentsComputer(pkgPath);
     try {
-      for (String file in map.keys) {
-        FileContentsComputer fileContentsComputer = map[file];
-        String expectedContents = await fileContentsComputer(pkgPath);
-        File outputFile = new File(posix.join(outputDirectory.path, file));
-        String actualContents = outputFile.readAsStringSync();
+      for (var entry in map.entries) {
+        var file = entry.key;
+        var fileContentsComputer = entry.value;
+        var expectedContents = await fileContentsComputer(pkgPath);
+        var outputFile = File(posix.join(outputDirectory.path, file));
+        var actualContents = outputFile.readAsStringSync();
         // Normalize Windows line endings to Unix line endings so that the
         // comparison doesn't fail on Windows.
         actualContents = actualContents.replaceAll('\r\n', '\n');
@@ -395,7 +342,7 @@
           return false;
         }
       }
-      int nonHiddenFileCount = 0;
+      var nonHiddenFileCount = 0;
       outputDirectory
           .listSync(recursive: false, followLinks: false)
           .forEach((FileSystemEntity fileSystemEntity) {
@@ -420,7 +367,7 @@
 
   @override
   Future<void> generate(String pkgPath) async {
-    Directory outputDirectory = output(pkgPath);
+    var outputDirectory = output(pkgPath);
     try {
       // delete the contents of the directory (and the directory itself)
       outputDirectory.deleteSync(recursive: true);
@@ -432,36 +379,31 @@
     outputDirectory.createSync(recursive: true);
 
     // generate all of the files in the directory
-    Map<String, FileContentsComputer> map = directoryContentsComputer(pkgPath);
-    for (String file in map.keys) {
-      FileContentsComputer fileContentsComputer = map[file];
-      File outputFile = new File(posix.join(outputDirectory.path, file));
+    var map = directoryContentsComputer(pkgPath);
+    for (var entry in map.entries) {
+      var file = entry.key;
+      var fileContentsComputer = entry.value;
+      var outputFile = File(posix.join(outputDirectory.path, file));
       print('  ${outputFile.path}');
-      String contents = await fileContentsComputer(pkgPath);
+      var contents = await fileContentsComputer(pkgPath);
       outputFile.writeAsStringSync(contents);
     }
   }
 
   @override
   Directory output(String pkgPath) =>
-      new Directory(join(pkgPath, joinAll(posix.split(outputDirPath))));
+      Directory(join(pkgPath, joinAll(posix.split(outputDirPath))));
 }
 
-/**
- * Class representing a single output file (either generated code or generated
- * HTML).
- */
+/// Class representing a single output file (either generated code or generated
+/// HTML).
 class GeneratedFile extends GeneratedContent {
-  /**
-   * The output file to which generated output should be written, relative to
-   * the "tool/spec" directory.  This filename uses the posix path separator
-   * ('/') regardless of the OS.
-   */
+  /// The output file to which generated output should be written, relative to
+  /// the "tool/spec" directory.  This filename uses the posix path separator
+  /// ('/') regardless of the OS.
   final String outputPath;
 
-  /**
-   * Callback function which computes the file.
-   */
+  /// Callback function which computes the file.
   final FileContentsComputer computeContents;
 
   GeneratedFile(this.outputPath, this.computeContents);
@@ -470,13 +412,13 @@
 
   @override
   Future<bool> check(String pkgPath) async {
-    File outputFile = output(pkgPath);
-    String expectedContents = await computeContents(pkgPath);
+    var outputFile = output(pkgPath);
+    var expectedContents = await computeContents(pkgPath);
     if (isDartFile) {
       expectedContents = DartFormat.formatText(expectedContents);
     }
     try {
-      String actualContents = outputFile.readAsStringSync();
+      var actualContents = outputFile.readAsStringSync();
       // Normalize Windows line endings to Unix line endings so that the
       // comparison doesn't fail on Windows.
       actualContents = actualContents.replaceAll('\r\n', '\n');
@@ -491,9 +433,9 @@
 
   @override
   Future<void> generate(String pkgPath) async {
-    File outputFile = output(pkgPath);
+    var outputFile = output(pkgPath);
     print('  ${outputFile.path}');
-    String contents = await computeContents(pkgPath);
+    var contents = await computeContents(pkgPath);
     outputFile.writeAsStringSync(contents);
     if (isDartFile) {
       DartFormat.formatFile(outputFile);
@@ -502,41 +444,33 @@
 
   @override
   File output(String pkgPath) =>
-      new File(join(pkgPath, joinAll(posix.split(outputPath))));
+      File(join(pkgPath, joinAll(posix.split(outputPath))));
 }
 
-/**
- * Mixin class for generating HTML representations of code that are suitable
- * for enclosing inside a <pre> element.
- */
+/// Mixin class for generating HTML representations of code that are suitable
+/// for enclosing inside a <pre> element.
 abstract class HtmlCodeGenerator {
-  _HtmlCodeGeneratorState _state;
+  _HtmlCodeGeneratorState _state = _HtmlCodeGeneratorState();
 
-  /**
-   * Add the given [node] to the HTML output.
-   */
+  /// Add the given [node] to the HTML output.
   void add(dom.Node node) {
     _state.add(node);
   }
 
-  /**
-   * Add the given [nodes] to the HTML output.
-   */
+  /// Add the given [nodes] to the HTML output.
   void addAll(Iterable<dom.Node> nodes) {
-    for (dom.Node node in nodes) {
+    for (var node in nodes) {
       _state.add(node);
     }
   }
 
-  /**
-   * Execute [callback], collecting any code that is output using [write],
-   * [writeln], [add], or [addAll], and return the result as a list of DOM
-   * nodes.
-   */
-  List<dom.Node> collectHtml(void callback()) {
-    _HtmlCodeGeneratorState oldState = _state;
+  /// Execute [callback], collecting any code that is output using [write],
+  /// [writeln], [add], or [addAll], and return the result as a list of DOM
+  /// nodes.
+  List<dom.Node> collectHtml(void Function()? callback) {
+    var oldState = _state;
     try {
-      _state = new _HtmlCodeGeneratorState();
+      _state = _HtmlCodeGeneratorState();
       if (callback != null) {
         callback();
       }
@@ -546,20 +480,16 @@
     }
   }
 
-  /**
-   * Execute [callback], wrapping its output in an element with the given
-   * [name] and [attributes].
-   */
+  /// Execute [callback], wrapping its output in an element with the given
+  /// [name] and [attributes].
   void element(String name, Map<dynamic, String> attributes,
-      [void callback()]) {
+      [void Function()? callback]) {
     add(makeElement(name, attributes, collectHtml(callback)));
   }
 
-  /**
-   * Execute [callback], indenting any code it outputs by two spaces.
-   */
-  void indent(void callback()) {
-    String oldIndent = _state.indent;
+  /// Execute [callback], indenting any code it outputs by two spaces.
+  void indent(void Function() callback) {
+    var oldIndent = _state.indent;
     try {
       _state.indent += '  ';
       callback();
@@ -568,33 +498,27 @@
     }
   }
 
-  /**
-   * Output text without ending the current line.
-   */
+  /// Output text without ending the current line.
   void write(Object obj) {
     _state.write(obj.toString());
   }
 
-  /**
-   * Output text, ending the current line.
-   */
+  /// Output text, ending the current line.
   void writeln([Object obj = '']) {
     _state.write('$obj\n');
   }
 }
 
-/**
- * State used by [CodeGenerator].
- */
+/// State used by [CodeGenerator].
 class _CodeGeneratorState {
-  StringBuffer buffer = new StringBuffer();
+  StringBuffer buffer = StringBuffer();
   String nextIndent = '';
   String indent = '';
   bool indentNeeded = true;
 
   void write(String text) {
-    List<String> lines = text.split('\n');
-    for (int i = 0; i < lines.length; i++) {
+    var lines = text.split('\n');
+    for (var i = 0; i < lines.length; i++) {
       if (i == lines.length - 1 && lines[i].isEmpty) {
         break;
       }
@@ -612,9 +536,7 @@
   }
 }
 
-/**
- * State used by [HtmlCodeGenerator].
- */
+/// State used by [HtmlCodeGenerator].
 class _HtmlCodeGeneratorState {
   List<dom.Node> buffer = <dom.Node>[];
   String indent = '';
@@ -633,15 +555,15 @@
       return;
     }
     if (indentNeeded) {
-      buffer.add(new dom.Text(indent));
+      buffer.add(dom.Text(indent));
     }
-    List<String> lines = text.split('\n');
+    var lines = text.split('\n');
     if (lines.last.isEmpty) {
       lines.removeLast();
-      buffer.add(new dom.Text(lines.join('\n$indent') + '\n'));
+      buffer.add(dom.Text(lines.join('\n$indent') + '\n'));
       indentNeeded = true;
     } else {
-      buffer.add(new dom.Text(lines.join('\n$indent')));
+      buffer.add(dom.Text(lines.join('\n$indent')));
       indentNeeded = false;
     }
   }
diff --git a/pkg/analyzer_utilities/lib/verify_tests.dart b/pkg/analyzer_utilities/lib/verify_tests.dart
index ca6fe74..bfe5f35 100644
--- a/pkg/analyzer_utilities/lib/verify_tests.dart
+++ b/pkg/analyzer_utilities/lib/verify_tests.dart
@@ -18,7 +18,7 @@
   final String testDirPath;
 
   /// Paths to exclude from analysis completely.
-  final List<String> excludedPaths;
+  final List<String>? excludedPaths;
 
   VerifyTests(this.testDirPath, {this.excludedPaths});
 
@@ -66,7 +66,7 @@
   void _buildTestsIn(
       AnalysisSession session, String testDirPath, Folder directory) {
     var testFileNames = <String>[];
-    File testAllFile;
+    File? testAllFile;
     var children = directory.getChildren();
     children
         .sort((first, second) => first.shortName.compareTo(second.shortName));
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index 918c627..77e4a0c 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -40,6 +40,10 @@
 
   /// The raw data read from [uri].
   T get data;
+
+  /// Release any resources held by the input. After releasing, a call to `get
+  /// data` will fail, and previously returned data may be invalid.
+  void release();
 }
 
 /// Interface for providing the compiler with input. That is, Dart source files,
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 1c7d0ed..c01275b 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -96,6 +96,7 @@
   static const String useNewSourceInfo = '--use-new-source-info';
   static const String useOldRti = '--use-old-rti';
   static const String verbose = '--verbose';
+  static const String verbosity = '--verbosity';
   static const String progress = '--show-internal-progress';
   static const String version = '--version';
   static const String reportMetrics = '--report-metrics';
@@ -117,6 +118,7 @@
 
   static const String soundNullSafety = '--sound-null-safety';
   static const String noSoundNullSafety = '--no-sound-null-safety';
+  static const String mergeFragmentsThreshold = '--merge-fragments-threshold';
 
   /// Flag for a combination of flags for 'production' mode.
   static const String benchmarkingProduction = '--benchmarking-production';
@@ -126,6 +128,8 @@
 
   static const String conditionalDirectives = '--conditional-directives';
 
+  static const String cfeInvocationModes = '--cfe-invocation-modes';
+
   // The syntax-only level of support for generic methods is included in the
   // 1.50 milestone for Dart. It is not experimental, but also not permanent:
   // a full implementation is expected in the future. Hence, the
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 33de3f1..fcc224f 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -489,8 +489,13 @@
   final Iterable<ModularName> modularNames;
   final Iterable<ModularExpression> modularExpressions;
 
-  CodegenResult(
-      this.code, this.impact, this.modularNames, this.modularExpressions);
+  CodegenResult(this.code, this.impact, List<ModularName> modularNames,
+      List<ModularExpression> modularExpressions)
+      : this.modularNames =
+            modularNames.isEmpty ? const [] : List.unmodifiable(modularNames),
+        this.modularExpressions = modularExpressions.isEmpty
+            ? const []
+            : List.unmodifiable(modularExpressions);
 
   /// Reads a [CodegenResult] object from [source].
   ///
@@ -505,7 +510,7 @@
     js.Fun code = source.readJsNodeOrNull();
     CodegenImpact impact = CodegenImpact.readFromDataSource(source);
     source.end(tag);
-    return new CodegenResult(code, impact, modularNames, modularExpressions);
+    return CodegenResult(code, impact, modularNames, modularExpressions);
   }
 
   /// Writes the [CodegenResult] object to [sink].
@@ -1487,7 +1492,6 @@
     sink.writeEnum(JsNodeKind.literalExpression);
     sink.begin(JsNodeTags.literalExpression);
     sink.writeString(node.template);
-    visitList(node.inputs);
     sink.end(JsNodeTags.literalExpression);
     _writeInfo(node);
   }
@@ -1956,9 +1960,7 @@
         break;
       case JsNodeKind.literalExpression:
         source.begin(JsNodeTags.literalExpression);
-        String template = source.readString();
-        List<js.Expression> inputs = readList();
-        node = new js.LiteralExpression.withData(template, inputs);
+        node = new js.LiteralExpression(source.readString());
         source.end(JsNodeTags.literalExpression);
         break;
       case JsNodeKind.dartYield:
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 8d84fe7..ae898a3 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -449,6 +449,8 @@
 
   FunctionEntity getInstantiateFunction(int typeArgumentCount);
 
+  FunctionEntity get convertMainArgumentList;
+
   // From dart:_rti
 
   FunctionEntity get setRuntimeTypeInfo;
@@ -1834,6 +1836,10 @@
         cls.name.startsWith('Instantiation');
   }
 
+  @override
+  FunctionEntity get convertMainArgumentList =>
+      _findHelperFunction('convertMainArgumentList');
+
   // From dart:_rti
 
   ClassEntity _findRtiClass(String name) => _findClass(rtiLibrary, name);
@@ -2399,9 +2405,11 @@
   void forEachNestedClosure(
       MemberEntity member, void f(FunctionEntity closure));
 
-  /// Returns `true` if [cls] is a mixin application that mixes in methods with
-  /// super calls.
-  bool isSuperMixinApplication(ClassEntity cls);
+  /// Returns `true` if [cls] is a mixin application with its own members.
+  ///
+  /// This occurs when a mixin contains methods with super calls or when
+  /// the mixin application contains concrete forwarding stubs.
+  bool isMixinApplicationWithMembers(ClassEntity cls);
 
   /// The default type of the [typeVariable].
   ///
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 05bf1ff..6faa855 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -726,9 +726,15 @@
     reportDiagnosticInternal(message, infos, api.Diagnostic.HINT);
   }
 
+  @override
+  void reportInfo(DiagnosticMessage message,
+      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
+    reportDiagnosticInternal(message, infos, api.Diagnostic.INFO);
+  }
+
   @deprecated
   @override
-  void reportInfo(Spannable node, MessageKind messageKind,
+  void reportInfoMessage(Spannable node, MessageKind messageKind,
       [Map<String, String> arguments = const {}]) {
     reportDiagnosticInternal(createMessage(node, messageKind, arguments),
         const <DiagnosticMessage>[], api.Diagnostic.INFO);
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 14b1867..f33c13b 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -27,6 +27,7 @@
   INTERCEPTOR,
   JS_NAME,
   DUMMY_INTERCEPTOR,
+  LATE_SENTINEL,
   UNREACHABLE,
   INSTANTIATION,
   DEFERRED_GLOBAL,
@@ -52,6 +53,8 @@
       covariant InterceptorConstantValue constant, covariant A arg);
   R visitDummyInterceptor(
       covariant DummyInterceptorConstantValue constant, covariant A arg);
+  R visitLateSentinel(
+      covariant LateSentinelConstantValue constant, covariant A arg);
   R visitUnreachable(
       covariant UnreachableConstantValue constant, covariant A arg);
   R visitJsName(covariant JsNameConstantValue constant, covariant A arg);
@@ -894,6 +897,34 @@
   String toStructuredText(DartTypes dartTypes) => 'DummyInterceptorConstant()';
 }
 
+/// A constant used to represent the sentinel for uninitialized late fields and
+/// variables.
+class LateSentinelConstantValue extends ConstantValue {
+  factory LateSentinelConstantValue() => const LateSentinelConstantValue._();
+
+  const LateSentinelConstantValue._();
+
+  @override
+  List<ConstantValue> getDependencies() => const <ConstantValue>[];
+
+  @override
+  accept(ConstantValueVisitor visitor, arg) {
+    return visitor.visitLateSentinel(this, arg);
+  }
+
+  @override
+  DartType getType(CommonElements types) => types.dynamicType;
+
+  @override
+  ConstantValueKind get kind => ConstantValueKind.LATE_SENTINEL;
+
+  @override
+  String toDartText(DartTypes dartTypes) => 'late_sentinel()';
+
+  @override
+  String toStructuredText(DartTypes dartTypes) => 'LateSentinelConstant()';
+}
+
 // A constant with an empty type used in [HInstruction]s of an expression
 // in an unreachable context.
 class UnreachableConstantValue extends ConstantValue {
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 11b8c5d..b1d2000 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -544,6 +544,8 @@
     new OptionHandler(Flags.useOldRti, passThrough),
     new OptionHandler(Flags.testMode, passThrough),
     new OptionHandler('${Flags.dumpSsa}=.+', passThrough),
+    new OptionHandler('${Flags.cfeInvocationModes}=.+', passThrough),
+    new OptionHandler('${Flags.verbosity}=.+', passThrough),
 
     // Experimental features.
     // We don't provide documentation for these yet.
@@ -559,6 +561,7 @@
     new OptionHandler(Flags.experimentUnreachableMethodsThrow, passThrough),
     new OptionHandler(Flags.experimentCallInstrumentation, passThrough),
     new OptionHandler(Flags.experimentNewRti, ignoreOption),
+    new OptionHandler('${Flags.mergeFragmentsThreshold}=.+', passThrough),
 
     // The following three options must come last.
     new OptionHandler('-D.+=.*', addInEnvironment),
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 364fe9a..829e2c5 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -84,6 +84,13 @@
 
   Set<ImportEntity> get importsForTesting => _imports;
 
+  void merge(OutputUnit that) {
+    assert(this != that);
+    // We don't currently support merging code into the main output unit.
+    assert(!isMainOutput);
+    this._imports.addAll(that._imports);
+  }
+
   @override
   String toString() => "OutputUnit($name, $_imports)";
 }
diff --git a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
index 554e809..b009473 100644
--- a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
+++ b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
@@ -49,8 +49,11 @@
   void reportHint(DiagnosticMessage message,
       [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]);
 
+  void reportInfo(DiagnosticMessage message,
+      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]);
+
   @deprecated
-  void reportInfo(Spannable node, MessageKind errorCode,
+  void reportInfoMessage(Spannable node, MessageKind errorCode,
       [Map<String, String> arguments = const {}]);
 
   /// Set current element of this reporter to [element]. This is used for
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 3e82de2..691151c 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -581,7 +581,8 @@
         OutputType.dumpInfo)
       ..add(jsonBuffer.toString())
       ..close();
-    compiler.reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
+    compiler.reporter
+        .reportInfoMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
       'text': "View the dumped .info.json file at "
           "https://dart-lang.github.io/dump-info-visualizer"
     });
@@ -592,7 +593,8 @@
     Sink<List<int>> sink = new BinaryOutputSinkAdapter(compiler.outputProvider
         .createBinarySink(compiler.options.outputUri.resolve(name)));
     dump_info.encode(data, sink);
-    compiler.reporter.reportInfo(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
+    compiler.reporter
+        .reportInfoMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, {
       'text': "Use `package:dart2js_info` to parse and process the dumped "
           ".info.data file."
     });
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index ccd058d..f136327 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -282,21 +282,62 @@
   /// The number of type parameters.
   final int typeParameters;
 
-  const ParameterStructure(
+  static const ParameterStructure getter =
+      ParameterStructure._(0, 0, [], {}, 0);
+
+  static const ParameterStructure setter =
+      ParameterStructure._(1, 1, [], {}, 0);
+
+  static const ParameterStructure zeroArguments =
+      ParameterStructure._(0, 0, [], {}, 0);
+
+  static const List<ParameterStructure> _simple = [
+    ParameterStructure._(0, 0, [], {}, 0),
+    ParameterStructure._(1, 1, [], {}, 0),
+    ParameterStructure._(2, 2, [], {}, 0),
+    ParameterStructure._(3, 3, [], {}, 0),
+    ParameterStructure._(4, 4, [], {}, 0),
+    ParameterStructure._(5, 5, [], {}, 0),
+  ];
+
+  const ParameterStructure._(
       this.requiredPositionalParameters,
       this.positionalParameters,
       this.namedParameters,
       this.requiredNamedParameters,
       this.typeParameters);
 
-  const ParameterStructure.getter()
-      : this(0, 0, const <String>[], const <String>{}, 0);
+  factory ParameterStructure(
+      int requiredPositionalParameters,
+      int positionalParameters,
+      List<String> namedParameters,
+      Set<String> requiredNamedParameters,
+      int typeParameters) {
+    // This simple canonicalization reduces the number of ParameterStructure
+    // objects by over 90%.
+    if (requiredPositionalParameters == positionalParameters &&
+        namedParameters.isEmpty &&
+        requiredNamedParameters.isEmpty &&
+        typeParameters == 0 &&
+        positionalParameters < _simple.length) {
+      return _simple[positionalParameters];
+    }
 
-  const ParameterStructure.setter()
-      : this(1, 1, const <String>[], const <String>{}, 0);
+    // Force sharing of empty collections.
+    if (namedParameters.isEmpty) namedParameters = const [];
+    if (requiredNamedParameters.isEmpty) requiredNamedParameters = const {};
+
+    return ParameterStructure._(
+      requiredPositionalParameters,
+      positionalParameters,
+      namedParameters,
+      requiredNamedParameters,
+      typeParameters,
+    );
+  }
 
   factory ParameterStructure.fromType(FunctionType type) {
-    return new ParameterStructure(
+    return ParameterStructure(
         type.parameterTypes.length,
         type.parameterTypes.length + type.optionalParameterTypes.length,
         type.namedParameters,
@@ -314,7 +355,7 @@
         source.readStrings(emptyAsNull: true)?.toSet() ?? const <String>{};
     int typeParameters = source.readInt();
     source.end(tag);
-    return new ParameterStructure(
+    return ParameterStructure(
         requiredPositionalParameters,
         positionalParameters,
         namedParameters,
@@ -344,7 +385,7 @@
   /// Returns the [CallStructure] corresponding to a call site passing all
   /// parameters both required and optional.
   CallStructure get callStructure {
-    return new CallStructure(totalParameters, namedParameters, typeParameters);
+    return CallStructure(totalParameters, namedParameters, typeParameters);
   }
 
   @override
@@ -382,7 +423,7 @@
 
   /// Short textual representation use for testing.
   String get shortText {
-    StringBuffer sb = new StringBuffer();
+    StringBuffer sb = StringBuffer();
     if (typeParameters != 0) {
       sb.write('<');
       sb.write(typeParameters);
@@ -401,7 +442,7 @@
 
   @override
   String toString() {
-    StringBuffer sb = new StringBuffer();
+    StringBuffer sb = StringBuffer();
     sb.write('ParameterStructure(');
     sb.write('requiredPositionalParameters=$requiredPositionalParameters,');
     sb.write('positionalParameters=$positionalParameters,');
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 8a660e2..4c261da 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -313,8 +313,13 @@
   final ClassEntity element;
   final List<DartType> typeArguments;
 
-  InterfaceType._(this.element, this.typeArguments)
-      : assert(typeArguments.every((e) => e != null));
+  InterfaceType._allocate(this.element, this.typeArguments);
+
+  factory InterfaceType._(ClassEntity element, List<DartType> typeArguments) {
+    assert(typeArguments.every((e) => e != null));
+    if (typeArguments.isEmpty) typeArguments = const [];
+    return InterfaceType._allocate(element, typeArguments);
+  }
 
   factory InterfaceType._readFromDataSource(
       DataSource source, List<FunctionTypeVariable> functionTypeVariables) {
@@ -683,6 +688,7 @@
     // Canonicalize empty collections to constants to save storage.
     if (parameterTypes.isEmpty) parameterTypes = const [];
     if (optionalParameterTypes.isEmpty) optionalParameterTypes = const [];
+    if (namedParameters.isEmpty) namedParameters = const [];
     if (namedParameterTypes.isEmpty) namedParameterTypes = const [];
     if (requiredNamedParameters.isEmpty) requiredNamedParameters = const {};
     if (typeVariables.isEmpty) typeVariables = const [];
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index bf34252..910485e9 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -90,8 +90,8 @@
 
 /// Implementation of [reportHere]
 _reportHere(DiagnosticReporter reporter, Spannable node, String debugMessage) {
-  reporter
-      .reportInfo(node, MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
+  reporter.reportInfoMessage(
+      node, MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
 }
 
 /// Set of tracked objects used by [track] and [ifTracked].
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 55d7ab6..9793cc5 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1906,10 +1906,15 @@
     // are calling does not expose this.
     _state.markThisAsExposed();
 
-    MemberEntity member =
-        _elementMap.getSuperMember(_analyzedMember, node.name);
-    assert(member != null, "No member found for super property get: $node");
+    ir.Member target = getEffectiveSuperTarget(node.interfaceTarget);
     Selector selector = new Selector.getter(_elementMap.getName(node.name));
+    if (target == null) {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
+      return handleSuperNoSuchMethod(node, selector, null);
+    }
+    MemberEntity member = _elementMap.getMember(target);
+    assert(member != null, "No member found for super property get: $node");
     TypeInformation type = handleStaticInvoke(node, selector, member, null);
     if (member.isGetter) {
       FunctionType functionType =
@@ -1937,11 +1942,16 @@
     _state.markThisAsExposed();
 
     TypeInformation rhsType = visit(node.value);
-    MemberEntity member =
-        _elementMap.getSuperMember(_analyzedMember, node.name, setter: true);
-    assert(member != null, "No member found for super property set: $node");
+    ir.Member target = getEffectiveSuperTarget(node.interfaceTarget);
     Selector selector = new Selector.setter(_elementMap.getName(node.name));
     ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null);
+    if (target == null) {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
+      return handleSuperNoSuchMethod(node, selector, arguments);
+    }
+    MemberEntity member = _elementMap.getMember(target);
+    assert(member != null, "No member found for super property set: $node");
     handleStaticInvoke(node, selector, member, arguments);
     return rhsType;
   }
@@ -1952,29 +1962,29 @@
     // are calling does not expose this.
     _state.markThisAsExposed();
 
-    MemberEntity member =
-        _elementMap.getSuperMember(_analyzedMember, node.name);
+    ir.Member target = getEffectiveSuperTarget(node.interfaceTarget);
     ArgumentsTypes arguments = analyzeArguments(node.arguments);
     Selector selector = _elementMap.getSelector(node);
-    if (member == null) {
-      // TODO(johnniwinther): This shouldn't be necessary.
+    if (target == null) {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
+      return handleSuperNoSuchMethod(node, selector, arguments);
+    }
+    MemberEntity member = _elementMap.getMember(target);
+    assert(member.isFunction, "Unexpected super invocation target: $member");
+    if (isIncompatibleInvoke(member, arguments)) {
       return handleSuperNoSuchMethod(node, selector, arguments);
     } else {
-      assert(member.isFunction, "Unexpected super invocation target: $member");
-      if (isIncompatibleInvoke(member, arguments)) {
-        return handleSuperNoSuchMethod(node, selector, arguments);
-      } else {
-        TypeInformation type =
-            handleStaticInvoke(node, selector, member, arguments);
-        FunctionType functionType =
-            _elementMap.elementEnvironment.getFunctionType(member);
-        if (functionType.returnType.containsFreeTypeVariables) {
-          // The return type varies with the call site so we narrow the static
-          // return type.
-          type = _types.narrowType(type, _getStaticType(node));
-        }
-        return type;
+      TypeInformation type =
+          handleStaticInvoke(node, selector, member, arguments);
+      FunctionType functionType =
+          _elementMap.elementEnvironment.getFunctionType(member);
+      if (functionType.returnType.containsFreeTypeVariables) {
+        // The return type varies with the call site so we narrow the static
+        // return type.
+        type = _types.narrowType(type, _getStaticType(node));
       }
+      return type;
     }
   }
 
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
index 935095e..7495c23 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
@@ -56,6 +56,11 @@
   }
 
   @override
+  TypeMask visitLateSentinel(
+          LateSentinelConstantValue constant, JClosedWorld closedWorld) =>
+      _abstractValueDomain.dynamicType;
+
+  @override
   TypeMask visitUnreachable(
       UnreachableConstantValue constant, JClosedWorld closedWorld) {
     return _abstractValueDomain.emptyType;
diff --git a/pkg/compiler/lib/src/io/source_file.dart b/pkg/compiler/lib/src/io/source_file.dart
index 1b358bc..f091dee 100644
--- a/pkg/compiler/lib/src/io/source_file.dart
+++ b/pkg/compiler/lib/src/io/source_file.dart
@@ -225,6 +225,9 @@
   @override
   set length(int v) => lengthCache = v;
   int lengthCache = -1;
+
+  @override
+  void release() {}
 }
 
 class CachingUtf8BytesSourceFile extends Utf8BytesSourceFile {
@@ -242,6 +245,12 @@
     }
     return cachedText;
   }
+
+  @override
+  void release() {
+    cachedText = null;
+    super.release();
+  }
 }
 
 class StringSourceFile extends SourceFile<List<int>> {
@@ -277,17 +286,30 @@
 
   @override
   String slowSubstring(int start, int end) => text.substring(start, end);
+
+  @override
+  void release() {}
 }
 
 /// Binary input data.
 class Binary implements Input<List<int>> {
   @override
   final Uri uri;
-  @override
-  final List<int> data;
+  List<int> /*?*/ _data;
 
-  Binary(this.uri, this.data);
+  Binary(this.uri, List<int> data) : _data = data;
+
+  @override
+  List<int> get data {
+    if (_data != null) return _data;
+    throw StateError("'get data' after 'release()'");
+  }
 
   @override
   InputKind get inputKind => InputKind.binary;
+
+  @override
+  void release() {
+    _data = null;
+  }
 }
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index cedc8b2..0a7118a 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -167,12 +167,12 @@
   void registerInstanceSet(
       ir.DartType receiverType, ClassRelation relation, ir.Member target);
 
-  void registerSuperInvocation(ir.Name name, int positionalArguments,
+  void registerSuperInvocation(ir.Member target, int positionalArguments,
       List<String> namedArguments, List<ir.DartType> typeArguments);
 
-  void registerSuperGet(ir.Name name);
+  void registerSuperGet(ir.Member target);
 
-  void registerSuperSet(ir.Name name);
+  void registerSuperSet(ir.Member target);
 
   void registerSuperInitializer(
       ir.Constructor source,
@@ -590,19 +590,22 @@
   @override
   void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
       ArgumentTypes argumentTypes, ir.DartType returnType) {
-    registerSuperInvocation(node.name, node.arguments.positional.length,
-        _getNamedArguments(node.arguments), node.arguments.types);
+    registerSuperInvocation(
+        getEffectiveSuperTarget(node.interfaceTarget),
+        node.arguments.positional.length,
+        _getNamedArguments(node.arguments),
+        node.arguments.types);
   }
 
   @override
   void handleSuperPropertyGet(
       ir.SuperPropertyGet node, ir.DartType resultType) {
-    registerSuperGet(node.name);
+    registerSuperGet(getEffectiveSuperTarget(node.interfaceTarget));
   }
 
   @override
   void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) {
-    registerSuperSet(node.name);
+    registerSuperSet(getEffectiveSuperTarget(node.interfaceTarget));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index 2dd1fcb..eecf083 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -43,23 +43,23 @@
   }
 
   @override
-  void registerSuperSet(ir.Name name) {
+  void registerSuperSet(ir.Member target) {
     _data._superSets ??= [];
-    _data._superSets.add(name);
+    _data._superSets.add(target);
   }
 
   @override
-  void registerSuperGet(ir.Name name) {
+  void registerSuperGet(ir.Member target) {
     _data._superGets ??= [];
-    _data._superGets.add(name);
+    _data._superGets.add(target);
   }
 
   @override
-  void registerSuperInvocation(ir.Name name, int positionalArguments,
+  void registerSuperInvocation(ir.Member target, int positionalArguments,
       List<String> namedArguments, List<ir.DartType> typeArguments) {
     _data._superInvocations ??= [];
     _data._superInvocations.add(new _SuperInvocation(
-        name,
+        target,
         new _CallStructure(
             positionalArguments, namedArguments, typeArguments)));
   }
@@ -478,8 +478,8 @@
   static const String tag = 'ImpactData';
 
   List<_SuperInitializer> _superInitializers;
-  List<ir.Name> _superSets;
-  List<ir.Name> _superGets;
+  List<ir.Member> _superSets;
+  List<ir.Member> _superGets;
   List<_SuperInvocation> _superInvocations;
   List<_InstanceAccess> _instanceSets;
   List<_DynamicAccess> _dynamicSets;
@@ -529,8 +529,10 @@
     _superInitializers = source.readList(
         () => new _SuperInitializer.fromDataSource(source),
         emptyAsNull: true);
-    _superSets = source.readList(() => source.readName(), emptyAsNull: true);
-    _superGets = source.readList(() => source.readName(), emptyAsNull: true);
+    _superSets =
+        source.readList(() => source.readMemberNode(), emptyAsNull: true);
+    _superGets =
+        source.readList(() => source.readMemberNode(), emptyAsNull: true);
     _superInvocations = source.readList(
         () => new _SuperInvocation.fromDataSource(source),
         emptyAsNull: true);
@@ -632,8 +634,8 @@
     sink.writeList(
         _superInitializers, (_SuperInitializer o) => o.toDataSink(sink),
         allowNull: true);
-    sink.writeList(_superSets, sink.writeName, allowNull: true);
-    sink.writeList(_superGets, sink.writeName, allowNull: true);
+    sink.writeList(_superSets, sink.writeMemberNode, allowNull: true);
+    sink.writeList(_superGets, sink.writeMemberNode, allowNull: true);
     sink.writeList(
         _superInvocations, (_SuperInvocation o) => o.toDataSink(sink),
         allowNull: true);
@@ -722,19 +724,19 @@
       }
     }
     if (_superSets != null) {
-      for (ir.Name data in _superSets) {
+      for (ir.Member data in _superSets) {
         registry.registerSuperSet(data);
       }
     }
     if (_superGets != null) {
-      for (ir.Name data in _superGets) {
+      for (ir.Member data in _superGets) {
         registry.registerSuperGet(data);
       }
     }
     if (_superInvocations != null) {
       for (_SuperInvocation data in _superInvocations) {
         registry.registerSuperInvocation(
-            data.name,
+            data.target,
             data.callStructure.positionalArguments,
             data.callStructure.namedArguments,
             data.callStructure.typeArguments);
@@ -1113,22 +1115,22 @@
 class _SuperInvocation {
   static const String tag = '_SuperInvocation';
 
-  final ir.Name name;
+  final ir.Member target;
   final _CallStructure callStructure;
 
-  _SuperInvocation(this.name, this.callStructure);
+  _SuperInvocation(this.target, this.callStructure);
 
   factory _SuperInvocation.fromDataSource(DataSource source) {
     source.begin(tag);
-    ir.Name name = source.readName();
+    ir.Member member = source.readMemberNode();
     _CallStructure callStructure = new _CallStructure.fromDataSource(source);
     source.end(tag);
-    return new _SuperInvocation(name, callStructure);
+    return new _SuperInvocation(member, callStructure);
   }
 
   void toDataSink(DataSink sink) {
     sink.begin(tag);
-    sink.writeName(name);
+    sink.writeMemberNode(target);
     callStructure.toDataSink(sink);
     sink.end(tag);
   }
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index 1db528a..455c612 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -268,3 +268,20 @@
   if (importUri == null) return false;
   return _isWebLibrary(importUri);
 }
+
+/// Returns the effective target of a super access of [target].
+///
+/// If [target] is a concrete mixin stub then the stub target is returned
+/// instead of the concrete mixin stub. This is done to avoid unnecessary
+/// indirections in super accesses.
+///
+/// See [ir.ProcedureStubKind.ConcreteMixinStub] for why concrete mixin stubs
+/// are inserted in the first place.
+ir.Member getEffectiveSuperTarget(ir.Member target) {
+  if (target is ir.Procedure) {
+    if (target.stubKind == ir.ProcedureStubKind.ConcreteMixinStub) {
+      return getEffectiveSuperTarget(target.stubTarget);
+    }
+  }
+  return target;
+}
diff --git a/pkg/compiler/lib/src/js/size_estimator.dart b/pkg/compiler/lib/src/js/size_estimator.dart
index 60d0354..257fa70 100644
--- a/pkg/compiler/lib/src/js/size_estimator.dart
+++ b/pkg/compiler/lib/src/js/size_estimator.dart
@@ -12,6 +12,13 @@
 import '../js_backend/type_reference.dart';
 import '../js_emitter/metadata_collector.dart';
 
+/// Estimates the size of the Javascript AST represented by the provided [Node].
+int estimateSize(Node node) {
+  var estimator = SizeEstimator();
+  estimator.visit(node);
+  return estimator.charCount;
+}
+
 /// [SizeEstimator] is a [NodeVisitor] designed to produce a consistent size
 /// estimate for a given JavaScript AST. [SizeEstimator] trades accuracy for
 /// stability and performance. In addition, [SizeEstimator] assumes we will emit
@@ -55,12 +62,20 @@
     } else if (node is StringReference) {
       // Worst case we have to inline the string so size of string + 2 bytes for
       // quotes.
-      return "'${node.constant}'";
+      return "'${node.constant.toDartString()}'";
     } else {
       throw UnsupportedError('$node type is not supported');
     }
   }
 
+  String literalStringToString(LiteralString node) {
+    if (node.isFinalized) {
+      return node.value;
+    } else {
+      return sizeEstimate(node);
+    }
+  }
+
   /// Always emit a newline, even under `enableMinification`.
   void forceLine() {
     out('\n'); // '\n'
@@ -757,7 +772,7 @@
         newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
     Node selector = access.selector;
     if (selector is LiteralString) {
-      String fieldWithQuotes = selector.value;
+      String fieldWithQuotes = literalStringToString(selector);
       if (isValidJavaScriptId(fieldWithQuotes)) {
         if (access.receiver is LiteralNumber) {
           // We can eliminate the space in some cases, but for simplicity we
@@ -846,11 +861,7 @@
 
   @override
   void visitLiteralString(LiteralString node) {
-    if (node.isFinalized) {
-      out(node.value); // '${node.value}'
-    } else {
-      out(sizeEstimate(node));
-    }
+    out(literalStringToString(node));
   }
 
   @override
@@ -943,7 +954,7 @@
   void visitProperty(Property node) {
     Node name = node.name;
     if (name is LiteralString) {
-      String text = name.value;
+      String text = literalStringToString(name);
       if (isValidJavaScriptId(text)) {
         // '${text.substring(1, text.length - 1)}
         out('${text.substring(1, text.length - 1)}');
@@ -971,21 +982,7 @@
 
   @override
   void visitLiteralExpression(LiteralExpression node) {
-    String template = node.template;
-    List<Expression> inputs = node.inputs;
-
-    List<String> parts = template.split('#');
-    int inputsLength = inputs == null ? 0 : inputs.length;
-    if (parts.length != inputsLength + 1) {
-      throw UnsupportedError('Wrong number of arguments for JS: $template');
-    }
-    // Code that uses JS must take care of operator precedences, and
-    // put parenthesis if needed.
-    out(parts[0]); // '${parts[0]}'
-    for (int i = 0; i < inputsLength; i++) {
-      visit(inputs[i]);
-      out(parts[i + 1]); // '${parts[i + 1]}'
-    }
+    out(node.template); // '${node.template}'
   }
 
   @override
@@ -1034,9 +1031,3 @@
     visit(node.expression);
   }
 }
-
-int EstimateSize(Node node) {
-  var estimator = SizeEstimator();
-  estimator.visit(node);
-  return estimator.charCount;
-}
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 5f63cfb..39c5e4f 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -117,10 +117,13 @@
   BackendImpact _mainWithArguments;
 
   BackendImpact get mainWithArguments {
-    return _mainWithArguments ??= new BackendImpact(instantiatedClasses: [
-      _commonElements.jsArrayClass,
-      _commonElements.jsStringClass
-    ]);
+    return _mainWithArguments ??= new BackendImpact(
+      globalUses: [_commonElements.convertMainArgumentList],
+      instantiatedClasses: [
+        _commonElements.jsArrayClass,
+        _commonElements.jsStringClass
+      ],
+    );
   }
 
   BackendImpact _asyncBody;
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 95166e4..4d0546c 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -19,6 +19,7 @@
 import '../js_model/type_recipe.dart' show TypeExpressionRecipe;
 import '../options.dart';
 import 'field_analysis.dart' show JFieldAnalysis;
+import 'namer.dart';
 import 'runtime_types_new.dart' show RecipeEncoder;
 import 'runtime_types_resolution.dart';
 
@@ -31,8 +32,9 @@
 class ModularConstantEmitter
     implements ConstantValueVisitor<jsAst.Expression, Null> {
   final CompilerOptions _options;
+  final ModularNamer _namer;
 
-  ModularConstantEmitter(this._options);
+  ModularConstantEmitter(this._options, this._namer);
 
   /// Constructs a literal expression that evaluates to the constant. Uses a
   /// canonical name unless the constant can be emitted multiple times (as for
@@ -159,6 +161,10 @@
   }
 
   @override
+  jsAst.Expression visitLateSentinel(LateSentinelConstantValue constant, [_]) =>
+      js('#', _namer.staticStateHolder);
+
+  @override
   jsAst.Expression visitUnreachable(UnreachableConstantValue constant, [_]) {
     // Unreachable constants should be rare in generated code, so we use
     // `undefined` encoded as `void 1' to make them distinctive.
@@ -226,6 +232,7 @@
   /// can be inlined.
   ConstantEmitter(
       CompilerOptions options,
+      ModularNamer _namer,
       this._commonElements,
       this._elementEnvironment,
       this._rtiNeed,
@@ -234,7 +241,7 @@
       this._emitter,
       this._constantReferenceGenerator,
       this._makeConstantList)
-      : super(options);
+      : super(options, _namer);
 
   @override
   jsAst.Expression visitList(ListConstantValue constant, [_]) {
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index ac07284..8b56213 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -58,9 +58,16 @@
 
       FieldEntity fieldElement = _elementMap.getField(field);
       ir.Expression expression = field.initializer;
-      ConstantValue value = _elementMap.getConstantValue(
-          _elementMap.getStaticTypeContext(fieldElement), expression,
-          requireConstant: false, implicitNull: true);
+      ConstantValue value;
+      if (expression is ir.StaticInvocation &&
+          identical(
+              expression.target, _elementMap.coreTypes.createSentinelMethod)) {
+        value = LateSentinelConstantValue();
+      } else {
+        value = _elementMap.getConstantValue(
+            _elementMap.getStaticTypeContext(fieldElement), expression,
+            requireConstant: false, implicitNull: true);
+      }
       if (value != null && value.isConstant) {
         fieldData[fieldElement] = new AllocatorData(value);
       }
@@ -127,9 +134,16 @@
   void registerStaticField(KField field, EvaluationComplexity complexity) {
     ir.Field node = _elementMap.getMemberNode(field);
     ir.Expression expression = node.initializer;
-    ConstantValue value = _elementMap.getConstantValue(
-        _elementMap.getStaticTypeContext(field), expression,
-        requireConstant: node.isConst, implicitNull: true);
+    ConstantValue value;
+    if (expression is ir.StaticInvocation &&
+        identical(
+            expression.target, _elementMap.coreTypes.createSentinelMethod)) {
+      value = LateSentinelConstantValue();
+    } else {
+      value = _elementMap.getConstantValue(
+          _elementMap.getStaticTypeContext(field), expression,
+          requireConstant: node.isConst, implicitNull: true);
+    }
     if (value != null && !value.isConstant) {
       value = null;
     }
@@ -358,7 +372,8 @@
               } else if (value.isNull ||
                   value.isInt ||
                   value.isBool ||
-                  value.isString) {
+                  value.isString ||
+                  value is LateSentinelConstantValue) {
                 // TODO(johnniwinther,sra): Support non-primitive constants in
                 // allocators when it does cause allocators to deoptimized
                 // because of deferred loading.
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 5ebc469..132100f 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -4,8 +4,6 @@
 
 library js_backend.namer;
 
-import 'dart:collection' show HashMap;
-
 import 'package:front_end/src/api_unstable/dart2js.dart'
     show $0, $9, $A, $Z, $_, $a, $g, $s, $z;
 
@@ -505,12 +503,12 @@
   /// [_disambiguateMember], [_disambiguateInternalMember],
   /// [_disambiguateOperator], and [reservePublicMemberName].
   final NamingScope instanceScope = NamingScope();
-  final Map<String, jsAst.Name> userInstanceMembers = HashMap();
-  final Map<String, String> userInstanceMembersOriginalName = HashMap();
-  final Map<MemberEntity, jsAst.Name> internalInstanceMembers = HashMap();
-  final Map<String, jsAst.Name> userInstanceOperators = HashMap();
-  final Map<jsAst.Name, jsAst.Name> userGetters = HashMap();
-  final Map<jsAst.Name, jsAst.Name> userSetters = HashMap();
+  final Map<String, jsAst.Name> userInstanceMembers = {};
+  final Map<String, String> userInstanceMembersOriginalName = {};
+  final Map<MemberEntity, jsAst.Name> internalInstanceMembers = {};
+  final Map<String, jsAst.Name> userInstanceOperators = {};
+  final Map<jsAst.Name, jsAst.Name> userGetters = {};
+  final Map<jsAst.Name, jsAst.Name> userSetters = {};
   final Map<TypeVariableEntity, jsAst.Name> _typeVariableNames = {};
 
   Map<String, String> createMinifiedInstanceNameMap() {
@@ -538,9 +536,9 @@
 
   final Map<String, int> popularNameCounters = {};
 
-  final Map<LibraryEntity, String> libraryLongNames = HashMap();
+  final Map<LibraryEntity, String> libraryLongNames = {};
 
-  final Map<ConstantValue, jsAst.Name> _constantNames = HashMap();
+  final Map<ConstantValue, jsAst.Name> _constantNames = {};
   final Map<ConstantValue, String> _constantLongNames = {};
   ConstantCanonicalHasher _constantHasher;
 
@@ -551,7 +549,7 @@
   /// Used to store unique keys for library names. Keys are not used as names,
   /// nor are they visible in the output. The only serve as an internal
   /// key into maps.
-  final Map<LibraryEntity, String> _libraryKeys = HashMap();
+  final Map<LibraryEntity, String> _libraryKeys = {};
 
   Namer(this._closedWorld, this.fixedNames) {
     _literalGetterPrefix = new StringBackedName(fixedNames.getterPrefix);
@@ -1495,7 +1493,7 @@
   // parts with the fast-startup emitter.
   String get typesOffsetName => r'typesOffset';
 
-  Map<FunctionType, jsAst.Name> functionTypeNameMap = HashMap();
+  Map<FunctionType, jsAst.Name> functionTypeNameMap = {};
 
   FunctionTypeNamer _functionTypeNamer;
 
@@ -1912,6 +1910,11 @@
   }
 
   @override
+  void visitLateSentinel(LateSentinelConstantValue constant, [_]) {
+    add('late_sentinel');
+  }
+
+  @override
   void visitUnreachable(UnreachableConstantValue constant, [_]) {
     add('unreachable');
   }
@@ -2048,6 +2051,13 @@
   }
 
   @override
+  int visitLateSentinel(LateSentinelConstantValue constant, [_]) =>
+      throw failedAt(
+          NO_LOCATION_SPANNABLE,
+          'LateSentinelConstantValue should never be named and '
+          'never be subconstant');
+
+  @override
   int visitUnreachable(UnreachableConstantValue constant, [_]) {
     throw failedAt(
         NO_LOCATION_SPANNABLE,
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 b412bd7..fb72825 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -20,6 +20,7 @@
 import '../world.dart' show JClosedWorld;
 import 'program_builder/program_builder.dart';
 import 'startup_emitter/emitter.dart' as startup_js_emitter;
+import 'startup_emitter/fragment_merger.dart' as fragment_merger;
 
 import 'metadata_collector.dart' show MetadataCollector;
 import 'model.dart';
@@ -206,6 +207,8 @@
 abstract class Emitter implements ModularEmitter {
   Program get programForTesting;
 
+  List<fragment_merger.PreFragment> get preDeferredFragmentsForTesting;
+
   /// Uses the [programBuilder] to generate a model of the program, emits
   /// the program, and returns the size of the generated output.
   int emitProgram(ProgramBuilder programBuilder, CodegenWorld codegenWorld);
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index 48281f3..9d4c41a 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -161,6 +161,11 @@
   }
 
   @override
+  int visitLateSentinel(
+          LateSentinelConstantValue a, LateSentinelConstantValue b) =>
+      0;
+
+  @override
   int visitUnreachable(UnreachableConstantValue a, UnreachableConstantValue b) {
     // Never emitted.
     return 0;
diff --git a/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
index e20f889..c969c26 100644
--- a/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
@@ -9,16 +9,58 @@
 import '../elements/entities.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
+import '../common_elements.dart';
 
 import 'code_emitter_task.dart' show Emitter;
 
 class MainCallStubGenerator {
   static jsAst.Statement generateInvokeMain(
-      Emitter emitter, FunctionEntity main) {
-    jsAst.Expression mainCallClosure = emitter.staticFunctionAccess(main);
+      CommonElements commonElements, Emitter emitter, FunctionEntity main) {
+    jsAst.Expression mainAccess = emitter.staticFunctionAccess(main);
     jsAst.Expression currentScriptAccess =
         emitter.generateEmbeddedGlobalAccess(embeddedNames.CURRENT_SCRIPT);
 
+    // TODO(https://github.com/dart-lang/language/issues/1120#issuecomment-670802088):
+    // Validate constraints on `main()` in resolution for dart2js, and in DDC.
+
+    final parameterStructure = main.parameterStructure;
+
+    // The forwarding stub passes all arguments, i.e. both required and optional
+    // positional arguments. We ignore named arguments, assuming the `main()`
+    // has been validated earlier.
+    int positionalParameters = parameterStructure.positionalParameters;
+
+    jsAst.Expression mainCallClosure;
+    if (positionalParameters == 0) {
+      if (parameterStructure.namedParameters.isEmpty) {
+        // e.g. `void main()`.
+        // No parameters. The compiled Dart `main` has no parameters and will
+        // ignore any extra parameters passed in, so it can be used directly.
+        mainCallClosure = mainAccess;
+      } else {
+        // e.g. `void main({arg})`.  We should not get here. Drop the named
+        // arguments as we don't know how to convert them.
+        mainCallClosure = js(r'''function() { return #(); }''', mainAccess);
+      }
+    } else {
+      jsAst.Expression convertArgumentList =
+          emitter.staticFunctionAccess(commonElements.convertMainArgumentList);
+      if (positionalParameters == 1) {
+        // e.g. `void main(List<String> args)`,  `main([args])`.
+        mainCallClosure = js(
+          r'''function(args) { return #(#(args)); }''',
+          [mainAccess, convertArgumentList],
+        );
+      } else {
+        // positionalParameters == 2.
+        // e.g. `void main(List<String> args, Object? extra)`
+        mainCallClosure = js(
+          r'''function(args, extra) { return #(#(args), extra); }''',
+          [mainAccess, convertArgumentList],
+        );
+      }
+    }
+
     // This code finds the currently executing script by listening to the
     // onload event of all script tags and getting the first script which
     // finishes. Since onload is called immediately after execution this should
@@ -31,7 +73,7 @@
         }
         // When running as a content-script of a chrome-extension the
         // 'currentScript' is `null` (but not undefined).
-        if (typeof document.currentScript != 'undefined') {
+        if (typeof document.currentScript != "undefined") {
           callback(document.currentScript);
           return;
         }
@@ -48,11 +90,11 @@
         }
       })(function(currentScript) {
         #currentScript = currentScript;
-
+        var callMain = #mainCallClosure;
         if (typeof dartMainRunner === "function") {
-          dartMainRunner(#mainCallClosure, []);
+          dartMainRunner(callMain, []);
         } else {
-          #mainCallClosure([]);
+          callMain([]);
         }
       })''', {
       'currentScript': currentScriptAccess,
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 6fac2f9..db10350 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -115,8 +115,7 @@
   }
 
   /// A map used to canonicalize the entries of metadata.
-  Map<OutputUnit, Map<String, BoundMetadataEntry>> _metadataMap =
-      <OutputUnit, Map<String, BoundMetadataEntry>>{};
+  Map<OutputUnit, Map<String, List<BoundMetadataEntry>>> _metadataMap = {};
 
   /// A map with a token for a lists of JS expressions, one token for each
   /// output unit. Once finalized, the entries represent types including
@@ -129,8 +128,35 @@
   }
 
   /// A map used to canonicalize the entries of types.
-  Map<OutputUnit, Map<DartType, BoundMetadataEntry>> _typesMap =
-      <OutputUnit, Map<DartType, BoundMetadataEntry>>{};
+  Map<OutputUnit, Map<DartType, List<BoundMetadataEntry>>> _typesMap = {};
+
+  void mergeOutputUnitMetadata(OutputUnit target, OutputUnit source) {
+    assert(target != source);
+
+    // Merge _metadataMap
+    var sourceMetadataMap = _metadataMap[source];
+    if (sourceMetadataMap != null) {
+      var targetMetadataMap =
+          _metadataMap[target] ??= Map<String, List<BoundMetadataEntry>>();
+      _metadataMap.remove(source);
+      sourceMetadataMap.forEach((str, entries) {
+        var targetMetadataMapList = targetMetadataMap[str] ??= [];
+        targetMetadataMapList.addAll(entries);
+      });
+    }
+
+    // Merge _typesMap
+    var sourceTypesMap = _typesMap[source];
+    if (sourceTypesMap != null) {
+      var targetTypesMap =
+          _typesMap[target] ??= Map<DartType, List<BoundMetadataEntry>>();
+      _typesMap.remove(source);
+      sourceTypesMap.forEach((type, entries) {
+        var targetTypesMapList = targetTypesMap[type] ??= [];
+        targetTypesMapList.addAll(entries);
+      });
+    }
+  }
 
   MetadataCollector(this._options, this.reporter, this._emitter,
       this._rtiRecipeEncoder, this._elementEnvironment);
@@ -166,10 +192,9 @@
     String printed = jsAst.prettyPrint(node,
         enableMinification: _options.enableMinification,
         renamerForNames: nameToKey);
-    _metadataMap[outputUnit] ??= new Map<String, BoundMetadataEntry>();
-    return _metadataMap[outputUnit].putIfAbsent(printed, () {
-      return new BoundMetadataEntry(node);
-    });
+    final submap = _metadataMap[outputUnit] ??= {};
+    final entries = submap[printed] ??= [BoundMetadataEntry(node)];
+    return entries.single;
   }
 
   jsAst.Expression _computeTypeRepresentationNewRti(DartType type) {
@@ -178,10 +203,20 @@
   }
 
   jsAst.Expression addTypeInOutputUnit(DartType type, OutputUnit outputUnit) {
-    _typesMap[outputUnit] ??= new Map<DartType, BoundMetadataEntry>();
-    return _typesMap[outputUnit].putIfAbsent(type, () {
-      return new BoundMetadataEntry(_computeTypeRepresentationNewRti(type));
-    });
+    _typesMap[outputUnit] ??= Map<DartType, List<BoundMetadataEntry>>();
+    BoundMetadataEntry metadataEntry;
+
+    // See comment for _addGlobalMetadata.
+    if (_typesMap[outputUnit].containsKey(type)) {
+      metadataEntry = _typesMap[outputUnit][type].single;
+    } else {
+      _typesMap[outputUnit].putIfAbsent(type, () {
+        metadataEntry =
+            BoundMetadataEntry(_computeTypeRepresentationNewRti(type));
+        return [metadataEntry];
+      });
+    }
+    return metadataEntry;
   }
 
   @override
@@ -194,9 +229,13 @@
           .forEach(counter.countTokens);
     }
 
-    jsAst.ArrayInitializer finalizeMap(Map<dynamic, BoundMetadataEntry> map) {
-      bool isUsed(BoundMetadataEntry entry) => entry.isUsed;
-      List<BoundMetadataEntry> entries = map.values.where(isUsed).toList();
+    jsAst.ArrayInitializer finalizeMap(
+        Map<dynamic, List<BoundMetadataEntry>> map) {
+      List<BoundMetadataEntry> entries = [
+        for (var entriesList in map.values)
+          for (var entry in entriesList)
+            if (entry.isUsed) entry
+      ];
       entries.sort();
 
       // TODO(herhut): Bucket entries by index length and use a stable
@@ -222,9 +261,9 @@
     });
 
     _typesTokens.forEach((OutputUnit outputUnit, _MetadataList token) {
-      Map typesMap = _typesMap[outputUnit];
+      Map<DartType, List<BoundMetadataEntry>> typesMap = _typesMap[outputUnit];
       if (typesMap != null) {
-        countTokensInTypes(typesMap.values);
+        typesMap.values.forEach(countTokensInTypes);
         token.setExpression(finalizeMap(typesMap));
       } else {
         token.setExpression(new jsAst.ArrayInitializer([]));
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 7479339..2cdfb73 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -42,6 +42,10 @@
     assert(outputContainsConstantList != null);
   }
 
+  void mergeOutputUnitMetadata(OutputUnit target, OutputUnit source) {
+    _metadataCollector.mergeOutputUnitMetadata(target, source);
+  }
+
   /// Accessor for the list of metadata entries for a given [OutputUnit].
   ///
   /// There is one list for each output unit. The list belonging to the main
@@ -290,7 +294,7 @@
   /// A soft-deferred class is only fully initialized at first instantiation.
   final bool isSoftDeferred;
 
-  final bool isSuperMixinApplication;
+  final bool isMixinApplicationWithMembers;
 
   // If the class implements a function type, and the type is encoded in the
   // metatada table, then this field contains the index into that field.
@@ -328,7 +332,7 @@
       this.isNative,
       this.isClosureBaseClass,
       this.isSoftDeferred = false,
-      this.isSuperMixinApplication}) {
+      this.isMixinApplicationWithMembers}) {
     assert(onlyForRti != null);
     assert(onlyForConstructor != null);
     assert(isDirectlyInstantiated != null);
@@ -394,7 +398,7 @@
             isDirectlyInstantiated: isDirectlyInstantiated,
             isNative: false,
             isClosureBaseClass: false,
-            isSuperMixinApplication: false);
+            isMixinApplicationWithMembers: false);
 
   @override
   bool get isSimpleMixinApplication => true;
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 351d6bc..0cd7059 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
@@ -221,7 +221,7 @@
                 "No Class for has been created for superclass "
                 "${superclass} of $c."));
       }
-      if (c.isSimpleMixinApplication || c.isSuperMixinApplication) {
+      if (c.isSimpleMixinApplication || c.isMixinApplicationWithMembers) {
         ClassEntity effectiveMixinClass =
             _elementEnvironment.getEffectiveMixinClass(cls);
         c.setMixinClass(_classes[effectiveMixinClass]);
@@ -388,7 +388,7 @@
 
   js.Statement _buildInvokeMain() {
     return MainCallStubGenerator.generateInvokeMain(
-        _task.emitter, _mainFunction);
+        _commonElements, _task.emitter, _mainFunction);
   }
 
   DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) {
@@ -725,14 +725,14 @@
 
     // MixinApplications run through the members of their mixin. Here, we are
     // only interested in direct members.
-    bool isSuperMixinApplication = false;
+    bool isMixinApplicationWithMembers = false;
     if (!onlyForConstructorOrRti) {
-      if (_elementEnvironment.isSuperMixinApplication(cls)) {
+      if (_elementEnvironment.isMixinApplicationWithMembers(cls)) {
         List<MemberEntity> members = <MemberEntity>[];
         void add(MemberEntity member) {
           if (member.enclosingClass == cls) {
             members.add(member);
-            isSuperMixinApplication = true;
+            isMixinApplicationWithMembers = true;
           }
         }
 
@@ -813,7 +813,7 @@
     Class result;
     if (_elementEnvironment.isMixinApplication(cls) &&
         !onlyForConstructorOrRti &&
-        !isSuperMixinApplication) {
+        !isMixinApplicationWithMembers) {
       assert(!_nativeData.isNativeClass(cls));
       assert(methods.isEmpty);
       assert(!isClosureBaseClass);
@@ -854,7 +854,7 @@
           isNative: _nativeData.isNativeClass(cls),
           isClosureBaseClass: isClosureBaseClass,
           isSoftDeferred: _isSoftDeferred(cls),
-          isSuperMixinApplication: isSuperMixinApplication);
+          isMixinApplicationWithMembers: isMixinApplicationWithMembers);
     }
     _classes[cls] = result;
     return result;
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 b2b924b..ca28cdb 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -24,6 +24,7 @@
 import '../model.dart';
 import '../native_emitter.dart';
 import '../program_builder/program_builder.dart' show ProgramBuilder;
+import 'fragment_merger.dart';
 import 'model_emitter.dart';
 
 abstract class ModularEmitterBase implements ModularEmitter {
@@ -117,7 +118,7 @@
 
   ModularEmitterImpl(
       ModularNamer namer, this._registry, CompilerOptions options)
-      : _constantEmitter = new ModularConstantEmitter(options),
+      : _constantEmitter = new ModularConstantEmitter(options, namer),
         super(namer);
 
   @override
@@ -156,6 +157,9 @@
   @override
   Program programForTesting;
 
+  @override
+  List<PreFragment> preDeferredFragmentsForTesting;
+
   EmitterImpl(
       CompilerOptions options,
       this._reporter,
@@ -196,7 +200,12 @@
       programForTesting = program;
     }
     return _task.measureSubtask('emit program', () {
-      return _emitter.emitProgram(program, codegenWorld);
+      var size = _emitter.emitProgram(program, codegenWorld);
+      if (retainDataForTesting) {
+        preDeferredFragmentsForTesting =
+            _emitter.preDeferredFragmentsForTesting;
+      }
+      return size;
     });
   }
 
@@ -238,11 +247,9 @@
 
   @override
   int generatedSize(OutputUnit unit) {
-    if (_emitter.omittedFragments.any((f) => f.outputUnit == unit)) {
+    if (_emitter.omittedOutputUnits.contains(unit)) {
       return 0;
     }
-    Fragment key = _emitter.outputBuffers.keys
-        .firstWhere((Fragment fragment) => fragment.outputUnit == unit);
-    return _emitter.outputBuffers[key].length;
+    return _emitter.emittedOutputBuffers[unit].length;
   }
 }
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 597f756..939a39f 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -54,6 +54,16 @@
     to[key] = from[key];
   }
 }
+// Copies the own properties from [from] to [to] if not already present in [to].
+function mixinProperties(from, to) {
+  var keys = Object.keys(from);
+  for (var i = 0; i < keys.length; i++) {
+    var key = keys[i];
+    if (!to.hasOwnProperty(key)) {
+      to[key] = from[key];
+    }
+  }
+}
 
 // Only use direct proto access to construct the prototype chain (instead of
 // copying properties) on platforms where we know it works well (Chrome / d8).
@@ -72,7 +82,7 @@
     for (var j = 0; j < keys.length; j++) {
       var key = keys[j];
       var f = holder[key];
-      if (typeof f == 'function') f.name = key;
+      if (typeof f == "function") f.name = key;
     }
   }
 }
@@ -111,7 +121,7 @@
 
 // Mixes in the properties of [mixin] into [cls].
 function mixin(cls, mixin) {
-  copyProperties(mixin.prototype, cls.prototype);
+  mixinProperties(mixin.prototype, cls.prototype);
   cls.prototype.constructor = cls;
 }
 
@@ -250,7 +260,7 @@
   var funs = [];
   for (var i = 0; i < funsOrNames.length; i++) {
     var fun = funsOrNames[i];
-    if ((typeof fun) == 'string') fun = container[fun];
+    if ((typeof fun) == "string") fun = container[fun];
     fun.#callName = callNames[i];
     funs.push(fun);
   }
@@ -690,6 +700,35 @@
     if (library != null) _dumpInfoTask.registerEntityAst(library, code);
   }
 
+  PreFragment emitPreFragment(DeferredFragment fragment, bool estimateSize) {
+    var classPrototypes = emitPrototypes(fragment, includeClosures: false);
+    var closurePrototypes = emitPrototypes(fragment, includeClosures: true);
+    var inheritance = emitInheritance(fragment);
+    var methodAliases = emitInstanceMethodAliases(fragment);
+    var tearOffs = emitInstallTearOffs(fragment);
+    var constants = emitConstants(fragment);
+    var typeRules = emitTypeRules(fragment);
+    var variances = emitVariances(fragment);
+    var staticNonFinalFields = emitStaticNonFinalFields(fragment);
+    var lazyInitializers = emitLazilyInitializedStatics(fragment);
+    // TODO(floitsch): only call emitNativeSupport if we need native.
+    var nativeSupport = emitNativeSupport(fragment);
+    return PreFragment(
+        fragment,
+        classPrototypes,
+        closurePrototypes,
+        inheritance,
+        methodAliases,
+        tearOffs,
+        constants,
+        typeRules,
+        variances,
+        staticNonFinalFields,
+        lazyInitializers,
+        nativeSupport,
+        estimateSize);
+  }
+
   js.Statement emitMainFragment(
       Program program, DeferredLoadingState deferredLoadingState) {
     MainFragment fragment = program.fragments.first;
@@ -699,8 +738,8 @@
 
     String softDeferredId = "softDeferred${new Random().nextInt(0x7FFFFFFF)}";
 
-    HolderCode holderCode =
-        emitHolders(program.holders, fragment, initializeEmptyHolders: true);
+    HolderCode holderCode = emitHolders(program.holders, fragment.libraries,
+        initializeEmptyHolders: true);
 
     js.Statement mainCode = js.js.statement(_mainBoilerplate, {
       // TODO(29455): 'hunkHelpers' displaces other names, so don't minify it.
@@ -791,10 +830,10 @@
     return new js.Block(holderInits);
   }
 
-  js.Expression emitDeferredFragment(DeferredFragment fragment,
-      js.Expression deferredTypes, List<Holder> holders) {
+  js.Expression emitDeferredFragment(
+      FinalizedFragment fragment, List<Holder> holders) {
     HolderCode holderCode =
-        emitHolders(holders, fragment, initializeEmptyHolders: false);
+        emitHolders(holders, fragment.libraries, initializeEmptyHolders: false);
 
     List<Holder> nonStaticStateHolders = holders
         .where((Holder holder) => !holder.isStaticStateHolder)
@@ -821,19 +860,6 @@
       }
     }
 
-    var classPrototypes = emitPrototypes(fragment, includeClosures: false);
-    var closurePrototypes = emitPrototypes(fragment, includeClosures: true);
-    var inheritance = emitInheritance(fragment);
-    var methodAliases = emitInstanceMethodAliases(fragment);
-    var tearOffs = emitInstallTearOffs(fragment);
-    var constants = emitConstants(fragment);
-    var typeRules = emitTypeRules(fragment);
-    var variances = emitVariances(fragment);
-    var staticNonFinalFields = emitStaticNonFinalFields(fragment);
-    var lazyInitializers = emitLazilyInitializedStatics(fragment);
-    // TODO(floitsch): only call emitNativeSupport if we need native.
-    var nativeSupport = emitNativeSupport(fragment);
-
     // TODO(sra): How do we tell if [deferredTypes] is empty? It is filled-in
     // later via the program finalizers. So we should defer the decision on the
     // emptiness of the fragment until the finalizers have run.  For now we seem
@@ -843,16 +869,7 @@
     // not emit any functions, then we probably did not use the signature types
     // in the OutputUnit's types, leaving them unused and tree-shaken.
 
-    if (holderCode.activeHolders.isEmpty &&
-        isEmptyStatement(classPrototypes) &&
-        isEmptyStatement(closurePrototypes) &&
-        isEmptyStatement(inheritance) &&
-        isEmptyStatement(methodAliases) &&
-        isEmptyStatement(tearOffs) &&
-        isEmptyStatement(constants) &&
-        isEmptyStatement(staticNonFinalFields) &&
-        isEmptyStatement(lazyInitializers) &&
-        isEmptyStatement(nativeSupport)) {
+    if (holderCode.activeHolders.isEmpty && fragment.isEmpty) {
       return null;
     }
 
@@ -865,18 +882,18 @@
           .map((holder) => js.js("#", holder.name))
           .toList(growable: false)),
       'updateHolders': new js.Block(updateHolderAssignments),
-      'prototypes': classPrototypes,
-      'closures': closurePrototypes,
-      'inheritance': inheritance,
-      'aliases': methodAliases,
-      'tearOffs': tearOffs,
-      'typeRules': typeRules,
-      'variances': variances,
-      'constants': constants,
-      'staticNonFinalFields': staticNonFinalFields,
-      'lazyStatics': lazyInitializers,
-      'types': deferredTypes,
-      'nativeSupport': nativeSupport,
+      'prototypes': fragment.classPrototypes,
+      'closures': fragment.closurePrototypes,
+      'inheritance': fragment.inheritance,
+      'aliases': fragment.methodAliases,
+      'tearOffs': fragment.tearOffs,
+      'typeRules': fragment.typeRules,
+      'variances': fragment.variances,
+      'constants': fragment.constants,
+      'staticNonFinalFields': fragment.staticNonFinalFields,
+      'lazyStatics': fragment.lazyInitializers,
+      'types': fragment.deferredTypes,
+      'nativeSupport': fragment.nativeSupport,
       'typesOffset': _namer.typesOffsetName,
       'sharedStrings': StringReferenceResource(),
       'sharedTypeRtis': TypeReferenceResource(),
@@ -904,7 +921,7 @@
   ///
   /// The emitted holders contain classes (only the constructors) and all
   /// static functions.
-  HolderCode emitHolders(List<Holder> holders, Fragment fragment,
+  HolderCode emitHolders(List<Holder> holders, List<Library> libraries,
       {bool initializeEmptyHolders}) {
     assert(initializeEmptyHolders != null);
     // Skip the static-state holder in this function.
@@ -918,7 +935,7 @@
       holderCode[holder] = <js.Property>[];
     }
 
-    for (Library library in fragment.libraries) {
+    for (Library library in libraries) {
       for (StaticMethod method in library.statics) {
         assert(!method.holder.isStaticStateHolder);
         Map<js.Name, js.Expression> propertyMap = emitStaticMethod(method);
@@ -1488,13 +1505,6 @@
     return js.js.statement('(function #(){#})();', [name, block]);
   }
 
-  bool isEmptyStatement(js.Statement statement) {
-    if (statement is js.Block) {
-      return statement.statements.isEmpty;
-    }
-    return statement is js.EmptyStatement;
-  }
-
   /// Emits the section that installs tear-off getters.
   js.Statement emitInstallTearOffs(Fragment fragment,
       {bool softDeferred = false}) {
@@ -1864,20 +1874,20 @@
   // array of hashes indexed by part.
   // [deferredLoadHashes] may have missing entries to indicate empty parts.
   void finalizeDeferredLoadingData(
-      Map<String, List<Fragment>> loadMap,
-      Map<DeferredFragment, String> deferredLoadHashes,
+      Map<String, List<FinalizedFragment>> loadMap,
+      Map<FinalizedFragment, String> deferredLoadHashes,
       DeferredLoadingState deferredLoadingState) {
     if (loadMap.isEmpty) return;
 
-    Map<Fragment, int> fragmentIndexes = {};
+    Map<FinalizedFragment, int> fragmentIndexes = {};
     List<String> fragmentUris = [];
     List<String> fragmentHashes = [];
 
     List<js.Property> libraryPartsMapEntries = [];
 
-    loadMap.forEach((String loadId, List<Fragment> fragmentList) {
+    loadMap.forEach((String loadId, List<FinalizedFragment> fragmentList) {
       List<js.Expression> indexes = [];
-      for (Fragment fragment in fragmentList) {
+      for (FinalizedFragment fragment in fragmentList) {
         String fragmentHash = deferredLoadHashes[fragment];
         if (fragmentHash == null) continue;
         int index = fragmentIndexes[fragment];
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
new file mode 100644
index 0000000..576f4ee
--- /dev/null
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
@@ -0,0 +1,372 @@
+// 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 '../../deferred_load.dart' show OutputUnit;
+import '../../js/js.dart' as js;
+import '../../js/size_estimator.dart';
+import '../../options.dart';
+import '../model.dart';
+
+class PreFragment {
+  final List<DeferredFragment> fragments = [];
+  final List<js.Statement> classPrototypes = [];
+  final List<js.Statement> closurePrototypes = [];
+  final List<js.Statement> inheritance = [];
+  final List<js.Statement> methodAliases = [];
+  final List<js.Statement> tearOffs = [];
+  final List<js.Statement> constants = [];
+  final List<js.Statement> typeRules = [];
+  final List<js.Statement> variances = [];
+  final List<js.Statement> staticNonFinalFields = [];
+  final List<js.Statement> lazyInitializers = [];
+  final List<js.Statement> nativeSupport = [];
+  final Set<PreFragment> successors = {};
+  final Set<PreFragment> predecessors = {};
+  int size = 0;
+
+  PreFragment(
+      Fragment fragment,
+      js.Statement classPrototypes,
+      js.Statement closurePrototypes,
+      js.Statement inheritance,
+      js.Statement methodAliases,
+      js.Statement tearOffs,
+      js.Statement constants,
+      js.Statement typeRules,
+      js.Statement variances,
+      js.Statement staticNonFinalFields,
+      js.Statement lazyInitializers,
+      js.Statement nativeSupport,
+      bool estimateSize) {
+    this.fragments.add(fragment);
+    this.classPrototypes.add(classPrototypes);
+    this.closurePrototypes.add(closurePrototypes);
+    this.inheritance.add(inheritance);
+    this.methodAliases.add(methodAliases);
+    this.tearOffs.add(tearOffs);
+    this.constants.add(constants);
+    this.typeRules.add(typeRules);
+    this.variances.add(variances);
+    this.staticNonFinalFields.add(staticNonFinalFields);
+    this.lazyInitializers.add(lazyInitializers);
+    this.nativeSupport.add(nativeSupport);
+    if (estimateSize) {
+      var estimator = SizeEstimator();
+      estimator.visit(classPrototypes);
+      estimator.visit(closurePrototypes);
+      estimator.visit(inheritance);
+      estimator.visit(methodAliases);
+      estimator.visit(tearOffs);
+      estimator.visit(constants);
+      estimator.visit(typeRules);
+      estimator.visit(variances);
+      estimator.visit(staticNonFinalFields);
+      estimator.visit(lazyInitializers);
+      estimator.visit(nativeSupport);
+      size = estimator.charCount;
+    }
+  }
+
+  void mergeAfter(PreFragment that) {
+    assert(this != that);
+    assert(
+        (that.predecessors.length == 1 && that.predecessors.single == this) ||
+            (this.successors.length == 1 && this.successors.single == that));
+    this.fragments.addAll(that.fragments);
+    this.classPrototypes.addAll(that.classPrototypes);
+    this.closurePrototypes.addAll(that.closurePrototypes);
+    this.inheritance.addAll(that.inheritance);
+    this.methodAliases.addAll(that.methodAliases);
+    this.tearOffs.addAll(that.tearOffs);
+    this.constants.addAll(that.constants);
+    this.typeRules.addAll(that.typeRules);
+    this.variances.addAll(that.variances);
+    this.staticNonFinalFields.addAll(that.staticNonFinalFields);
+    this.lazyInitializers.addAll(that.lazyInitializers);
+    this.nativeSupport.addAll(that.nativeSupport);
+    this.successors.remove(that);
+    that.successors.forEach((fragment) {
+      fragment.predecessors.remove(that);
+      fragment.predecessors.add(this);
+    });
+    this.successors.addAll(that.successors);
+    that.predecessors.remove(this);
+    that.predecessors.forEach((fragment) {
+      fragment.successors.remove(that);
+      fragment.successors.add(this);
+    });
+    this.predecessors.addAll(that.predecessors);
+    this.size += that.size;
+  }
+
+  FinalizedFragment finalize(
+      Program program, Map<Fragment, FinalizedFragment> fragmentMap) {
+    FinalizedFragment finalizedFragment;
+    var seedFragment = fragments.first;
+
+    // If we only have a single fragment, then wen just finalize it by itself.
+    // Otherwise, we finalize an entire group of fragments into a single
+    // merged and finalized fragment.
+    if (fragments.length == 1) {
+      finalizedFragment = FinalizedFragment(
+          seedFragment.outputFileName,
+          seedFragment.outputUnit,
+          seedFragment.libraries,
+          classPrototypes.first,
+          closurePrototypes.first,
+          inheritance.first,
+          methodAliases.first,
+          tearOffs.first,
+          constants.first,
+          typeRules.first,
+          variances.first,
+          staticNonFinalFields.first,
+          lazyInitializers.first,
+          nativeSupport.first,
+          program.metadataTypesForOutputUnit(seedFragment.outputUnit));
+      fragmentMap[seedFragment] = finalizedFragment;
+    } else {
+      List<Library> libraries = [];
+      for (var fragment in fragments) {
+        if (seedFragment.outputUnit != fragment.outputUnit) {
+          program.mergeOutputUnitMetadata(
+              seedFragment.outputUnit, fragment.outputUnit);
+          seedFragment.outputUnit.merge(fragment.outputUnit);
+        }
+        libraries.addAll(fragment.libraries);
+      }
+      finalizedFragment = FinalizedFragment(
+          seedFragment.outputFileName,
+          seedFragment.outputUnit,
+          libraries,
+          js.Block(classPrototypes),
+          js.Block(closurePrototypes),
+          js.Block(inheritance),
+          js.Block(methodAliases),
+          js.Block(tearOffs),
+          js.Block(constants),
+          js.Block(typeRules),
+          js.Block(variances),
+          js.Block(staticNonFinalFields),
+          js.Block(lazyInitializers),
+          js.Block(nativeSupport),
+          program.metadataTypesForOutputUnit(seedFragment.outputUnit));
+      for (var fragment in fragments) {
+        fragmentMap[fragment] = finalizedFragment;
+      }
+    }
+    return finalizedFragment;
+  }
+
+  @override
+  String toString() {
+    // This is not an efficient operation and should only be used for debugging.
+    var successors =
+        this.successors.map((fragment) => fragment.debugName()).join(',');
+    var predecessors =
+        this.predecessors.map((fragment) => fragment.debugName()).join(',');
+    var name = debugName();
+    return 'PreFragment(fragments=[$name], successors=[$successors], '
+        'predecessors=[$predecessors])';
+  }
+
+  String debugName() {
+    List<String> names = [];
+    this.fragments.forEach((fragment) => names.add(fragment.name));
+    return names.join(',');
+  }
+
+  static int compare(PreFragment l, PreFragment r) {
+    return l.size.compareTo(r.size);
+  }
+}
+
+class FinalizedFragment {
+  final String outputFileName;
+  final OutputUnit outputUnit;
+  final List<Library> libraries;
+  final js.Statement classPrototypes;
+  final js.Statement closurePrototypes;
+  final js.Statement inheritance;
+  final js.Statement methodAliases;
+  final js.Statement tearOffs;
+  final js.Statement constants;
+  final js.Statement typeRules;
+  final js.Statement variances;
+  final js.Statement staticNonFinalFields;
+  final js.Statement lazyInitializers;
+  final js.Statement nativeSupport;
+  final js.Expression deferredTypes;
+
+  FinalizedFragment(
+      this.outputFileName,
+      this.outputUnit,
+      this.libraries,
+      this.classPrototypes,
+      this.closurePrototypes,
+      this.inheritance,
+      this.methodAliases,
+      this.tearOffs,
+      this.constants,
+      this.typeRules,
+      this.variances,
+      this.staticNonFinalFields,
+      this.lazyInitializers,
+      this.nativeSupport,
+      this.deferredTypes);
+
+  bool isEmptyStatement(js.Statement statement) {
+    if (statement is js.Block) {
+      return statement.statements.isEmpty;
+    }
+    return statement is js.EmptyStatement;
+  }
+
+  bool get isEmpty {
+    // TODO(sra): How do we tell if [deferredTypes] is empty? It is filled-in
+    // later via the program finalizers. So we should defer the decision on the
+    // emptiness of the fragment until the finalizers have run.  For now we seem
+    // to get away with the fact that type indexes are either (1) main unit or
+    // (2) local to the emitted unit, so there is no such thing as a type in a
+    // deferred unit that is referenced from another deferred unit.  If we did
+    // not emit any functions, then we probably did not use the signature types
+    // in the OutputUnit's types, leaving them unused and tree-shaken.
+    // TODO(joshualitt): Currently, we ignore [typeRules] when determining
+    // emptiness because the type rules never seem to be empty.
+    return isEmptyStatement(classPrototypes) &&
+        isEmptyStatement(closurePrototypes) &&
+        isEmptyStatement(inheritance) &&
+        isEmptyStatement(methodAliases) &&
+        isEmptyStatement(tearOffs) &&
+        isEmptyStatement(constants) &&
+        isEmptyStatement(staticNonFinalFields) &&
+        isEmptyStatement(lazyInitializers) &&
+        isEmptyStatement(nativeSupport);
+  }
+}
+
+class FragmentMerger {
+  final CompilerOptions _options;
+
+  FragmentMerger(this._options);
+
+  // Converts a map of (loadId, List<fragments>) to a map of
+  // (loadId, List<FinalizedFragment>).
+  static Map<String, List<FinalizedFragment>> processLoadMap(
+      Map<String, List<Fragment>> programLoadMap,
+      Map<Fragment, FinalizedFragment> fragmentMap) {
+    Map<String, List<FinalizedFragment>> loadMap = {};
+    programLoadMap.forEach((loadId, fragments) {
+      Set<FinalizedFragment> unique = {};
+      List<FinalizedFragment> finalizedFragments = [];
+      loadMap[loadId] = finalizedFragments;
+      for (var fragment in fragments) {
+        var finalizedFragment = fragmentMap[fragment];
+        if (unique.add(finalizedFragment)) {
+          finalizedFragments.add(finalizedFragment);
+        }
+      }
+    });
+    return loadMap;
+  }
+
+  // Attaches predecessors to each PreFragment. We only care about
+  // direct predecessors.
+  static void attachDependencies(Map<String, List<Fragment>> programLoadMap,
+      Map<Fragment, PreFragment> fragmentMap) {
+    programLoadMap.forEach((loadId, fragments) {
+      for (int i = 0; i < fragments.length - 1; i++) {
+        var fragment = fragmentMap[fragments[i]];
+        var nextFragment = fragmentMap[fragments[i + 1]];
+        fragment.successors.add(nextFragment);
+        nextFragment.predecessors.add(fragment);
+      }
+    });
+  }
+
+  // Iterates through preDeferredFragments making as many merges as possible
+  // until either there are no more valid merges to make, or until there are
+  // only mergeFragmentsThreshold remaining.
+  List<PreFragment> mergeFragments(List<PreFragment> preDeferredFragments) {
+    Set<PreFragment> fragmentsBySize = {};
+
+    // We greedily look for a valid merge which results in the smallest
+    // possible increase in size. Currently, we only merge fragments in two
+    // cases:
+    // 1) We will merge two fragments A and B if B is A's single dependent.
+    // 2) We will merge two fragments C and D if C is D's single dependency.
+    bool mergeTwo() {
+      PreFragment aFragment = null;
+      PreFragment bFragment = null;
+      PreFragment cFragment = null;
+      PreFragment dFragment = null;
+      for (var fragment in fragmentsBySize) {
+        if (fragment.successors.length == 1 &&
+            (aFragment == null && bFragment == null ||
+                (fragment.size + fragment.successors.single.size <
+                    aFragment.size + bFragment.size))) {
+          aFragment = fragment;
+          bFragment = fragment.successors.single;
+        }
+        if (fragment.predecessors.length == 1 &&
+            (cFragment == null && dFragment == null ||
+                (fragment.size + fragment.predecessors.single.size <
+                    cFragment.size + dFragment.size))) {
+          cFragment = fragment.predecessors.single;
+          dFragment = fragment;
+        }
+      }
+      assert((aFragment != null &&
+              bFragment != null &&
+              aFragment != bFragment &&
+              aFragment.successors.single == bFragment) ||
+          (cFragment != null &&
+              dFragment != null &&
+              cFragment != dFragment &&
+              dFragment.predecessors.single == cFragment) ||
+          (aFragment == null &&
+              bFragment == null &&
+              cFragment == null &&
+              dFragment == null));
+      int mergeSentinel = 0x10000000000;
+      bool abCanMerge = aFragment != null && bFragment != null;
+      bool cdCanMerge = cFragment != null && dFragment != null;
+      int abMergeSize =
+          abCanMerge ? aFragment.size + bFragment.size : mergeSentinel;
+      int cdMergeSize =
+          cdCanMerge ? cFragment.size + dFragment.size : mergeSentinel;
+      bool abShouldMerge() => abCanMerge && abMergeSize <= cdMergeSize;
+      bool cdShouldMerge() => cdCanMerge && cdMergeSize <= abMergeSize;
+      void innerMerge(PreFragment a, PreFragment b) {
+        fragmentsBySize.remove(a);
+        fragmentsBySize.remove(b);
+        a.mergeAfter(b);
+        fragmentsBySize.add(a);
+      }
+
+      bool merged = abShouldMerge() || cdShouldMerge();
+      if (abShouldMerge()) {
+        innerMerge(aFragment, bFragment);
+      } else if (cdShouldMerge()) {
+        innerMerge(cFragment, dFragment);
+      } else {
+        assert(aFragment == null &&
+            bFragment == null &&
+            cFragment == null &&
+            dFragment == null);
+      }
+      return merged;
+    }
+
+    fragmentsBySize.addAll(preDeferredFragments);
+    var numFragments = preDeferredFragments.length;
+    while (numFragments-- > _options.mergeFragmentsThreshold) {
+      if (!mergeTwo()) {
+        // No further valid merges can be made.
+        break;
+      }
+    }
+    return fragmentsBySize.toList();
+  }
+}
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 f549f60..e12027b 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
@@ -36,8 +36,13 @@
 import '../../common.dart';
 import '../../common/tasks.dart';
 import '../../constants/values.dart'
-    show ConstantValue, FunctionConstantValue, NullConstantValue;
+    show
+        ConstantValue,
+        FunctionConstantValue,
+        LateSentinelConstantValue,
+        NullConstantValue;
 import '../../common_elements.dart' show CommonElements, JElementEnvironment;
+import '../../deferred_load.dart' show OutputUnit;
 import '../../dump_info.dart';
 import '../../elements/entities.dart';
 import '../../elements/types.dart';
@@ -75,6 +80,7 @@
 import '../js_emitter.dart' show buildTearOffCode, NativeGenerator;
 import '../model.dart';
 import '../native_emitter.dart';
+import 'fragment_merger.dart';
 
 part 'fragment_emitter.dart';
 
@@ -86,7 +92,7 @@
   final Namer _namer;
   final CompilerTask _task;
   final Emitter _emitter;
-  ConstantEmitter _constantEmitter;
+  ConstantEmitter constantEmitter;
   final NativeEmitter _nativeEmitter;
   final bool _shouldGenerateSourceMap;
   final JClosedWorld _closedWorld;
@@ -94,9 +100,11 @@
   final SourceInformationStrategy _sourceInformationStrategy;
 
   // The full code that is written to each hunk part-file.
-  final Map<Fragment, CodeOutput> outputBuffers = {};
+  final Map<OutputUnit, CodeOutput> emittedOutputBuffers = {};
 
-  Set<Fragment> omittedFragments = Set();
+  final Set<OutputUnit> omittedOutputUnits = {};
+
+  List<PreFragment> preDeferredFragmentsForTesting;
 
   /// For deferred loading we communicate the initializers via this global var.
   static const String deferredInitializersGlobal =
@@ -121,8 +129,9 @@
       RecipeEncoder rtiRecipeEncoder,
       this._shouldGenerateSourceMap)
       : _constantOrdering = new ConstantOrdering(_closedWorld.sorter) {
-    this._constantEmitter = new ConstantEmitter(
+    this.constantEmitter = new ConstantEmitter(
         _options,
+        _namer,
         _closedWorld.commonElements,
         _closedWorld.elementEnvironment,
         _closedWorld.rtiNeed,
@@ -142,6 +151,7 @@
     if (constant.isFunction) return true; // Already emitted.
     if (constant.isPrimitive) return true; // Inlined.
     if (constant.isDummy) return true; // Inlined.
+    if (constant is LateSentinelConstantValue) return true; // Inlined.
     return false;
   }
 
@@ -177,12 +187,14 @@
     // We are only interested in the "isInlined" part, but it does not hurt to
     // test for the other predicates.
     if (isConstantInlinedOrAlreadyEmitted(value)) {
-      return _constantEmitter.generate(value);
+      return constantEmitter.generate(value);
     }
     return js.js('#.#',
         [_namer.globalObjectForConstant(value), _namer.constantName(value)]);
   }
 
+  bool get shouldMergeFragments => _options.mergeFragmentsThreshold != null;
+
   int emitProgram(Program program, CodegenWorld codegenWorld) {
     MainFragment mainFragment = program.fragments.first;
     List<DeferredFragment> deferredFragments =
@@ -193,7 +205,7 @@
         _dumpInfoTask,
         _namer,
         _emitter,
-        _constantEmitter,
+        constantEmitter,
         this,
         _nativeEmitter,
         _closedWorld,
@@ -203,17 +215,44 @@
     js.Statement mainCode =
         fragmentEmitter.emitMainFragment(program, deferredLoadingState);
 
-    Map<DeferredFragment, js.Expression> deferredFragmentsCode = {};
+    // In order to get size estimates, we partially emit deferred fragments.
+    List<PreFragment> preDeferredFragments = [];
+    Map<DeferredFragment, PreFragment> preFragmentMap = {};
+    _task.measureSubtask('emit prefragments', () {
+      for (var fragment in deferredFragments) {
+        var preFragment =
+            fragmentEmitter.emitPreFragment(fragment, shouldMergeFragments);
+        preFragmentMap[fragment] = preFragment;
+        preDeferredFragments.add(preFragment);
+      }
+    });
 
-    for (DeferredFragment fragment in deferredFragments) {
-      js.Expression types =
-          program.metadataTypesForOutputUnit(fragment.outputUnit);
+    // Attach dependencies to each PreFragment.
+    FragmentMerger.attachDependencies(program.loadMap, preFragmentMap);
+
+    if (shouldMergeFragments) {
+      preDeferredFragments = _task.measureSubtask('merge fragments', () {
+        FragmentMerger fragmentMerger = FragmentMerger(_options);
+        return fragmentMerger.mergeFragments(preDeferredFragments);
+      });
+    }
+
+    // If necessary, we retain the merged PreFragments for testing.
+    if (retainDataForTesting) {
+      preDeferredFragmentsForTesting = preDeferredFragments;
+    }
+
+    Map<DeferredFragment, FinalizedFragment> fragmentMap = {};
+    Map<FinalizedFragment, js.Expression> deferredFragmentsCode = {};
+    for (var preDeferredFragment in preDeferredFragments) {
+      var finalizedFragment =
+          preDeferredFragment.finalize(program, fragmentMap);
       js.Expression fragmentCode = fragmentEmitter.emitDeferredFragment(
-          fragment, types, program.holders);
+          finalizedFragment, program.holders);
       if (fragmentCode != null) {
-        deferredFragmentsCode[fragment] = fragmentCode;
+        deferredFragmentsCode[finalizedFragment] = fragmentCode;
       } else {
-        omittedFragments.add(fragment);
+        omittedOutputUnits.add(finalizedFragment.outputUnit);
       }
     }
 
@@ -227,15 +266,17 @@
     // deferred ASTs inside the parts) have any contents. We should wait until
     // this point to decide if a part is empty.
 
-    Map<DeferredFragment, String> hunkHashes =
+    Map<FinalizedFragment, String> hunkHashes =
         _task.measureSubtask('write fragments', () {
       return writeDeferredFragments(deferredFragmentsCode);
     });
 
     // Now that we have written the deferred hunks, we can create the deferred
     // loading data.
+    Map<String, List<FinalizedFragment>> loadMap =
+        FragmentMerger.processLoadMap(program.loadMap, fragmentMap);
     fragmentEmitter.finalizeDeferredLoadingData(
-        program.loadMap, hunkHashes, deferredLoadingState);
+        loadMap, hunkHashes, deferredLoadingState);
 
     _task.measureSubtask('write fragments', () {
       writeMainFragment(mainFragment, mainCode,
@@ -254,7 +295,7 @@
     }
 
     // Return the total program size.
-    return outputBuffers.values.fold(0, (a, b) => a + b.length);
+    return emittedOutputBuffers.values.fold(0, (a, b) => a + b.length);
   }
 
   /// Generates a simple header that provides the compiler's build id.
@@ -278,11 +319,11 @@
   /// library code).
   ///
   /// Updates the shared [outputBuffers] field with the output.
-  Map<DeferredFragment, String> writeDeferredFragments(
-      Map<DeferredFragment, js.Expression> fragmentsCode) {
-    Map<DeferredFragment, String> hunkHashes = {};
+  Map<FinalizedFragment, String> writeDeferredFragments(
+      Map<FinalizedFragment, js.Expression> fragmentsCode) {
+    Map<FinalizedFragment, String> hunkHashes = {};
 
-    fragmentsCode.forEach((DeferredFragment fragment, js.Expression code) {
+    fragmentsCode.forEach((FinalizedFragment fragment, js.Expression code) {
       hunkHashes[fragment] = writeDeferredFragment(fragment, code);
     });
 
@@ -313,7 +354,7 @@
     CodeOutput mainOutput = StreamCodeOutput(
         _outputProvider.createOutputSink('', 'js', OutputType.js),
         codeOutputListeners);
-    outputBuffers[fragment] = mainOutput;
+    emittedOutputBuffers[fragment.outputUnit] = mainOutput;
 
     js.Program program = js.Program([
       buildGeneratedBy(),
@@ -358,7 +399,7 @@
   // Returns the deferred fragment's hash.
   //
   // Updates the shared [outputBuffers] field with the output.
-  String writeDeferredFragment(DeferredFragment fragment, js.Expression code) {
+  String writeDeferredFragment(FinalizedFragment fragment, js.Expression code) {
     List<CodeOutputListener> outputListeners = [];
     Hasher hasher = new Hasher();
     outputListeners.add(hasher);
@@ -378,7 +419,7 @@
             hunkPrefix, deferredExtension, OutputType.jsPart),
         outputListeners);
 
-    outputBuffers[fragment] = output;
+    emittedOutputBuffers[fragment.outputUnit] = output;
 
     // The [code] contains the function that must be invoked when the deferred
     // hunk is loaded.
@@ -456,8 +497,7 @@
         "needed for a given deferred library import.";
     mapping.addAll(_closedWorld.outputUnitData.computeDeferredMap(
         _options, _closedWorld.elementEnvironment,
-        omittedUnits:
-            omittedFragments.map((fragment) => fragment.outputUnit).toSet()));
+        omittedUnits: omittedOutputUnits));
     _outputProvider.createOutputSink(
         _options.deferredMapUri.path, '', OutputType.deferredMap)
       ..add(const JsonEncoder.withIndent("  ").convert(mapping))
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index e0dd7a2..570da8a 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -481,7 +481,9 @@
         source.readLocalMap<Local, JRecordField>(() => source.readMember());
     Set<Local> freeVariables = source.readLocals().toSet();
     source.end(tag);
-    return new JsScopeInfo.internal(
+    if (boxedVariables.isEmpty) boxedVariables = const {};
+    if (freeVariables.isEmpty) freeVariables = const {};
+    return JsScopeInfo.internal(
         localsUsedInTryOrSync, thisLocal, boxedVariables, freeVariables);
   }
 
@@ -671,7 +673,10 @@
     Map<Local, JField> localToFieldMap =
         source.readLocalMap(() => source.readMember());
     source.end(tag);
-    return new KernelClosureClassInfo.internal(
+    if (boxedVariables.isEmpty) boxedVariables = const {};
+    if (freeVariables.isEmpty) freeVariables = const {};
+    if (localToFieldMap.isEmpty) localToFieldMap = const {};
+    return KernelClosureClassInfo.internal(
         localsUsedInTryOrSync,
         thisLocal,
         boxedVariables,
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index b26e902..622ee68 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -74,11 +74,6 @@
   /// Returns the [ClassEntity] corresponding to the class [node].
   ClassEntity getClass(ir.Class node);
 
-  /// Returns the super [MemberEntity] for a super invocation, get or set of
-  /// [name] from the member [context].
-  MemberEntity getSuperMember(MemberEntity context, ir.Name name,
-      {bool setter: false});
-
   /// Returns the `noSuchMethod` [FunctionEntity] call from a
   /// `super.noSuchMethod` invocation within [cls].
   FunctionEntity getSuperNoSuchMethod(ClassEntity cls);
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 b5a67dd..ec6d67f 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -37,6 +37,7 @@
 import '../ir/util.dart';
 import '../js_backend/annotations.dart';
 import '../js_backend/native_data.dart';
+import '../kernel/dart2js_target.dart' show allowedNativeTest;
 import '../kernel/element_map_impl.dart';
 import '../kernel/env.dart';
 import '../kernel/kelements.dart';
@@ -806,32 +807,6 @@
   }
 
   @override
-  MemberEntity getSuperMember(MemberEntity context, ir.Name name,
-      {bool setter: false}) {
-    // We can no longer trust the interface target of the super access since it
-    // might be a member that we have cloned.
-    ClassEntity cls = getMemberThisType(context).element;
-    assert(
-        cls != null,
-        failedAt(context,
-            "No enclosing class for super member access in $context."));
-    IndexedClass superclass = getSuperType(cls)?.element;
-    while (superclass != null) {
-      JClassEnv env = classes.getEnv(superclass);
-      MemberEntity superMember =
-          env.lookupMember(this, name.text, setter: setter);
-      if (superMember != null) {
-        if (!superMember.isInstanceMember) return null;
-        if (!superMember.isAbstract) {
-          return superMember;
-        }
-      }
-      superclass = getSuperType(superclass)?.element;
-    }
-    return null;
-  }
-
-  @override
   ConstructorEntity getConstructor(ir.Member node) =>
       getConstructorInternal(node);
 
@@ -1066,10 +1041,10 @@
     return env.isUnnamedMixinApplication;
   }
 
-  bool _isSuperMixinApplication(IndexedClass cls) {
+  bool _isMixinApplicationWithMembers(IndexedClass cls) {
     assert(checkFamily(cls));
     JClassEnv env = classes.getEnv(cls);
-    return env.isSuperMixinApplication;
+    return env.isMixinApplicationWithMembers;
   }
 
   void _forEachSupertype(IndexedClass cls, void f(InterfaceType supertype)) {
@@ -1321,18 +1296,6 @@
 
   TypeLookup _typeLookup({bool resolveAsRaw: true}) {
     bool cachedMayLookupInMain;
-    bool mayLookupInMain() {
-      var mainUri = elementEnvironment.mainLibrary.canonicalUri;
-      // Tests permit lookup outside of dart: libraries.
-      return mainUri.path
-              .contains(RegExp(r'(?<!generated_)tests/dart2js/internal')) ||
-          mainUri.path
-              .contains(RegExp(r'(?<!generated_)tests/dart2js/native')) ||
-          mainUri.path
-              .contains(RegExp(r'(?<!generated_)tests/dart2js_2/internal')) ||
-          mainUri.path
-              .contains(RegExp(r'(?<!generated_)tests/dart2js_2/native'));
-    }
 
     DartType lookup(String typeName, {bool required}) {
       DartType findInLibrary(LibraryEntity library) {
@@ -1355,8 +1318,11 @@
       // TODO(johnniwinther): Narrow the set of lookups based on the depending
       // library.
       // TODO(johnniwinther): Cache more results to avoid redundant lookups?
+      cachedMayLookupInMain ??=
+          // Tests permit lookup outside of dart: libraries.
+          allowedNativeTest(elementEnvironment.mainLibrary.canonicalUri);
       DartType type;
-      if (cachedMayLookupInMain ??= mayLookupInMain()) {
+      if (cachedMayLookupInMain) {
         type ??= findInLibrary(elementEnvironment.mainLibrary);
       }
       type ??= findIn(Uris.dart_core);
@@ -2140,6 +2106,10 @@
       } else if (node is ir.Constructor) {
         parts.add(utils.reconstructConstructorName(getMember(node)));
         break;
+      } else if (node is ir.Field) {
+        // Add the field name for closures in field initializers.
+        String name = node.name?.name;
+        if (name != null) parts.add(name);
       }
       current = current.parent;
     }
@@ -2246,8 +2216,8 @@
   }
 
   @override
-  bool isSuperMixinApplication(ClassEntity cls) {
-    return elementMap._isSuperMixinApplication(cls);
+  bool isMixinApplicationWithMembers(ClassEntity cls) {
+    return elementMap._isMixinApplicationWithMembers(cls);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index 05a965f..38337b4 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -506,7 +506,7 @@
   JGetter(JLibrary library, JClass enclosingClass, Name name,
       AsyncMarker asyncMarker,
       {bool isStatic, bool isExternal, this.isAbstract})
-      : super(library, enclosingClass, name, const ParameterStructure.getter(),
+      : super(library, enclosingClass, name, ParameterStructure.getter,
             asyncMarker,
             isStatic: isStatic, isExternal: isExternal);
 
@@ -571,7 +571,7 @@
 
   JSetter(JLibrary library, JClass enclosingClass, Name name,
       {bool isStatic, bool isExternal, this.isAbstract})
-      : super(library, enclosingClass, name, const ParameterStructure.setter(),
+      : super(library, enclosingClass, name, ParameterStructure.setter,
             AsyncMarker.SYNC,
             isStatic: isStatic, isExternal: isExternal);
 
@@ -733,15 +733,9 @@
   static const String tag = 'signature-method';
 
   JSignatureMethod(ClassEntity enclosingClass)
-      : super(
-            enclosingClass.library,
-            enclosingClass,
-            Names.signature,
-            const ParameterStructure(0, 0, const [], const {}, 0),
-            AsyncMarker.SYNC,
-            isStatic: false,
-            isExternal: false,
-            isAbstract: false);
+      : super(enclosingClass.library, enclosingClass, Names.signature,
+            ParameterStructure.zeroArguments, AsyncMarker.SYNC,
+            isStatic: false, isExternal: false, isAbstract: false);
 
   factory JSignatureMethod.readFromDataSource(DataSource source) {
     source.begin(tag);
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index aedff40..2e408ee 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -197,9 +197,11 @@
   /// Whether the class is an unnamed mixin application.
   bool get isUnnamedMixinApplication;
 
-  /// Whether the class is a mixin application that mixes in methods with super
-  /// calls.
-  bool get isSuperMixinApplication;
+  /// Whether the class is a mixin application with its own members.
+  ///
+  /// This occurs when a mixin contains methods with super calls or when
+  /// the mixin application contains concrete forwarding stubs.
+  bool get isMixinApplicationWithMembers;
 
   /// Return the [MemberEntity] for the member [name] in the class. If [setter]
   /// is `true`, the setter or assignable field corresponding to [name] is
@@ -235,13 +237,13 @@
   final Map<String, ir.Member> _setterMap;
   final List<ir.Member> _members; // in declaration order.
   @override
-  final bool isSuperMixinApplication;
+  final bool isMixinApplicationWithMembers;
 
   /// Constructor bodies created for this class.
   List<ConstructorBodyEntity> _constructorBodyList;
 
   JClassEnvImpl(this.cls, this._constructorMap, this._memberMap,
-      this._setterMap, this._members, this.isSuperMixinApplication);
+      this._setterMap, this._members, this.isMixinApplicationWithMembers);
 
   factory JClassEnvImpl.readFromDataSource(DataSource source) {
     source.begin(tag);
@@ -268,7 +270,7 @@
     sink.writeStringMap(_memberMap, sink.writeMemberNode);
     sink.writeStringMap(_setterMap, sink.writeMemberNode);
     sink.writeMemberNodes(_members);
-    sink.writeBool(isSuperMixinApplication);
+    sink.writeBool(isMixinApplicationWithMembers);
     sink.end(tag);
   }
 
@@ -372,7 +374,7 @@
   bool get isUnnamedMixinApplication => false;
 
   @override
-  bool get isSuperMixinApplication => false;
+  bool get isMixinApplicationWithMembers => false;
 
   @override
   ir.Class get cls => null;
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 db779c3..07086db 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -891,6 +891,9 @@
           DummyInterceptorConstantValue constant, _) =>
       constant;
   @override
+  ConstantValue visitLateSentinel(LateSentinelConstantValue constant, _) =>
+      constant;
+  @override
   ConstantValue visitUnreachable(UnreachableConstantValue constant, _) =>
       constant;
   @override
diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
index e9bcb42..c783b25 100644
--- a/pkg/compiler/lib/src/js_model/locals.dart
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -97,10 +97,8 @@
   static const String tag = 'locals-map';
 
   MemberEntity _currentMember;
-  final EntityDataMap<JLocal, LocalData> _locals =
-      new EntityDataMap<JLocal, LocalData>();
-  Map<ir.VariableDeclaration, JLocal> _variableMap =
-      <ir.VariableDeclaration, JLocal>{};
+  final EntityDataMap<JLocal, LocalData> _locals = EntityDataMap();
+  Map<ir.VariableDeclaration, JLocal> _variableMap;
   Map<ir.TreeNode, JJumpTarget> _jumpTargetMap;
   Iterable<ir.BreakStatement> _breaksAsContinue;
 
@@ -111,22 +109,25 @@
     source.begin(tag);
     _currentMember = source.readMember();
     int localsCount = source.readInt();
-    for (int i = 0; i < localsCount; i++) {
-      int index = source.readInt();
-      String name = source.readStringOrNull();
-      bool isRegularParameter = source.readBool();
-      ir.VariableDeclaration node = source.readTreeNode();
-      JLocal local = new JLocal(name, currentMember,
-          isRegularParameter: isRegularParameter);
-      LocalData data = new LocalData(node);
-      _locals.registerByIndex(index, local, data);
-      _variableMap[node] = local;
+    if (localsCount > 0) {
+      _variableMap = {};
+      for (int i = 0; i < localsCount; i++) {
+        int index = source.readInt();
+        String name = source.readStringOrNull();
+        bool isRegularParameter = source.readBool();
+        ir.VariableDeclaration node = source.readTreeNode();
+        JLocal local =
+            JLocal(name, currentMember, isRegularParameter: isRegularParameter);
+        LocalData data = LocalData(node);
+        _locals.registerByIndex(index, local, data);
+        _variableMap[node] = local;
+      }
     }
     int jumpCount = source.readInt();
     if (jumpCount > 0) {
       _jumpTargetMap = {};
       for (int i = 0; i < jumpCount; i++) {
-        JJumpTarget target = new JJumpTarget.readFromDataSource(source);
+        JJumpTarget target = JJumpTarget.readFromDataSource(source);
         List<ir.TreeNode> nodes = source.readTreeNodes();
         for (ir.TreeNode node in nodes) {
           _jumpTargetMap[node] = target;
@@ -134,6 +135,7 @@
       }
     }
     _breaksAsContinue = source.readTreeNodes();
+    if (_breaksAsContinue.isEmpty) _breaksAsContinue = const [];
     source.end(tag);
   }
 
@@ -175,7 +177,7 @@
   // TODO(johnniwinther): Compute this eagerly from the root of the member.
   void _ensureJumpMap(ir.TreeNode node) {
     if (_jumpTargetMap == null) {
-      JumpVisitor visitor = new JumpVisitor(currentMember);
+      JumpVisitor visitor = JumpVisitor(currentMember);
 
       // Find the root node for the current member.
       while (node is! ir.Member) {
@@ -260,10 +262,11 @@
 
   @override
   Local getLocalVariable(ir.VariableDeclaration node) {
-    return _variableMap.putIfAbsent(node, () {
-      JLocal local = new JLocal(node.name, currentMember,
+    final variableMap = _variableMap ??= {};
+    return variableMap.putIfAbsent(node, () {
+      JLocal local = JLocal(node.name, currentMember,
           isRegularParameter: node.parent is ir.FunctionNode);
-      _locals.register<JLocal, LocalData>(local, new LocalData(node));
+      _locals.register<JLocal, LocalData>(local, LocalData(node));
       return local;
     });
   }
@@ -274,7 +277,7 @@
     // TODO(efortuna, johnniwinther): We're not registering the type variables
     // like we are for the variable declarations. Is that okay or do we need to
     // make TypeVariableLocal a JLocal?
-    return new TypeVariableLocal(elementMap.getTypeVariableType(node).element);
+    return TypeVariableLocal(elementMap.getTypeVariableType(node).element);
   }
 
   @override
@@ -292,9 +295,8 @@
   int jumpIndex = 0;
   int labelIndex = 0;
   final MemberEntity member;
-  final Map<ir.TreeNode, JJumpTarget> jumpTargetMap =
-      <ir.TreeNode, JJumpTarget>{};
-  final Set<ir.BreakStatement> breaksAsContinue = new Set<ir.BreakStatement>();
+  final Map<ir.TreeNode, JJumpTarget> jumpTargetMap = {};
+  final Set<ir.BreakStatement> breaksAsContinue = {};
 
   JumpVisitor(this.member);
 
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index ce387d5..1bf5b01 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -33,25 +33,27 @@
   'web_sql'
 ];
 
-bool maybeEnableNative(Uri uri) {
-  bool allowedTestLibrary() {
-    String scriptName = uri.path;
-    return scriptName
-            .contains(RegExp(r'(?<!generated_)tests/dart2js/native')) ||
-        scriptName.contains(RegExp(r'(?<!generated_)tests/dart2js/internal')) ||
-        scriptName.contains('generated_tests/dart2js/native/native_test') ||
-        scriptName.contains(RegExp(r'(?<!generated_)tests/dart2js_2/native')) ||
-        scriptName
-            .contains(RegExp(r'(?<!generated_)tests/dart2js_2/internal')) ||
-        scriptName.contains('generated_tests/dart2js_2/native/native_test');
-  }
+List<Pattern> _allowedNativeTestPatterns = [
+  RegExp(r'(?<!generated_)tests/dart2js/native'),
+  RegExp(r'(?<!generated_)tests/dart2js/internal'),
+  'generated_tests/dart2js/native/native_test',
+  RegExp(r'(?<!generated_)tests/dart2js_2/native'),
+  RegExp(r'(?<!generated_)tests/dart2js_2/internal'),
+  'generated_tests/dart2js_2/native/native_test',
+];
 
+bool allowedNativeTest(Uri uri) {
+  String path = uri.path;
+  return _allowedNativeTestPatterns.any((pattern) => path.contains(pattern));
+}
+
+bool maybeEnableNative(Uri uri) {
   bool allowedDartLibrary() {
     if (uri.scheme != 'dart') return false;
     return _allowedDartSchemePaths.contains(uri.path);
   }
 
-  return allowedTestLibrary() || allowedDartLibrary();
+  return allowedNativeTest(uri) || allowedDartLibrary();
 }
 
 /// A kernel [Target] to configure the Dart Front End for dart2js.
@@ -61,6 +63,8 @@
   @override
   final String name;
 
+  Map<String, ir.Class> _nativeClasses;
+
   Dart2jsTarget(this.name, this.flags);
 
   @override
@@ -70,7 +74,7 @@
   int get enabledLateLowerings => LateLowering.all;
 
   @override
-  bool get supportsLateLoweringSentinel => false;
+  bool get supportsLateLoweringSentinel => true;
 
   @override
   bool get useStaticFieldLowering => false;
@@ -81,6 +85,9 @@
   bool get supportsExplicitGetterCalls => false;
 
   @override
+  bool get supportsNewMethodInvocationEncoding => false;
+
+  @override
   List<String> get extraRequiredLibraries => _requiredLibraries[name];
 
   @override
@@ -119,10 +126,12 @@
       ReferenceFromIndex referenceFromIndex,
       {void logger(String msg),
       ChangedStructureNotifier changedStructureNotifier}) {
+    _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
     for (var library in libraries) {
       JsInteropChecks(
               coreTypes,
-              diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>)
+              diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
+              _nativeClasses)
           .visitLibrary(library);
     }
     lowering.transformLibraries(
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 4b3917c8..dd59226 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -81,11 +81,6 @@
   /// Returns the [ClassEntity] corresponding to the class [node].
   ClassEntity getClass(ir.Class node);
 
-  /// Returns the super [MemberEntity] for a super invocation, get or set of
-  /// [name] from the member [context].
-  MemberEntity getSuperMember(MemberEntity context, ir.Name name,
-      {bool setter: false});
-
   /// Returns the `noSuchMethod` [FunctionEntity] call from a
   /// `super.noSuchMethod` invocation within [cls].
   FunctionEntity getSuperNoSuchMethod(ClassEntity cls);
@@ -190,26 +185,16 @@
 bool memberIsIgnorable(ir.Member node, {ir.Class cls}) {
   if (node is! ir.Procedure) return false;
   ir.Procedure member = node;
-  if ((member.isMemberSignature || member.isForwardingStub) &&
-      member.isAbstract) {
-    // Skip abstract forwarding stubs. These are never emitted but they
-    // might shadow the inclusion of a mixed in method in code like:
-    //
-    //     class Super {}
-    //     class Mixin<T> {
-    //       void method(T t) {}
-    //     }
-    //     class Class extends Super with Mixin<int> {}
-    //     main() => new Class().method();
-    //
-    // Here a stub is created for `Super&Mixin.method` hiding that
-    // `Mixin.method` is inherited by `Class`.
-    return true;
-  }
-  if (cls != null &&
-      (member.isMemberSignature || member.isForwardingStub) &&
-      cls.isAnonymousMixin) {
-    return true;
+  switch (member.stubKind) {
+    case ir.ProcedureStubKind.Regular:
+    case ir.ProcedureStubKind.ConcreteForwardingStub:
+    case ir.ProcedureStubKind.NoSuchMethodForwarder:
+      return false;
+    case ir.ProcedureStubKind.AbstractForwardingStub:
+    case ir.ProcedureStubKind.MemberSignature:
+    case ir.ProcedureStubKind.AbstractMixinStub:
+    case ir.ProcedureStubKind.ConcreteMixinStub:
+      return true;
   }
   return false;
 }
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index e1afb79..fe5ce5f 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -425,32 +425,6 @@
   }
 
   @override
-  MemberEntity getSuperMember(MemberEntity context, ir.Name name,
-      {bool setter: false}) {
-    // We can no longer trust the interface target of the super access since it
-    // might be a member that we have cloned.
-    ClassEntity cls = context.enclosingClass;
-    assert(
-        cls != null,
-        failedAt(context,
-            "No enclosing class for super member access in $context."));
-    IndexedClass superclass = getSuperType(cls)?.element;
-    while (superclass != null) {
-      KClassEnv env = classes.getEnv(superclass);
-      MemberEntity superMember =
-          env.lookupMember(this, name.text, setter: setter);
-      if (superMember != null) {
-        if (!superMember.isInstanceMember) return null;
-        if (!superMember.isAbstract) {
-          return superMember;
-        }
-      }
-      superclass = getSuperType(superclass)?.element;
-    }
-    return null;
-  }
-
-  @override
   ConstructorEntity getConstructor(ir.Member node) =>
       getConstructorInternal(node);
 
@@ -853,7 +827,7 @@
         requiredNamedParameters.add(variable.name);
       }
     }
-    return new ParameterStructure(
+    return ParameterStructure(
         requiredPositionalParameters,
         positionalParameters,
         namedParameters,
@@ -909,18 +883,6 @@
 
   TypeLookup _typeLookup({bool resolveAsRaw: true}) {
     bool cachedMayLookupInMain;
-    bool mayLookupInMain() {
-      var mainUri = elementEnvironment.mainLibrary.canonicalUri;
-      // Tests permit lookup outside of dart: libraries.
-      return mainUri.path
-              .contains(RegExp(r'(?<!generated_)tests/dart2js/internal')) ||
-          mainUri.path
-              .contains(RegExp(r'(?<!generated_)tests/dart2js/native')) ||
-          mainUri.path
-              .contains(RegExp(r'(?<!generated_)tests/dart2js_2/internal')) ||
-          mainUri.path
-              .contains(RegExp(r'(?<!generated_)tests/dart2js_2/native'));
-    }
 
     DartType lookup(String typeName, {bool required}) {
       DartType findInLibrary(LibraryEntity library) {
@@ -943,8 +905,11 @@
       // TODO(johnniwinther): Narrow the set of lookups based on the depending
       // library.
       // TODO(johnniwinther): Cache more results to avoid redundant lookups?
+      cachedMayLookupInMain ??=
+          // Tests permit lookup outside of dart: libraries.
+          allowedNativeTest(elementEnvironment.mainLibrary.canonicalUri);
       DartType type;
-      if (cachedMayLookupInMain ??= mayLookupInMain()) {
+      if (cachedMayLookupInMain) {
         type ??= findInLibrary(elementEnvironment.mainLibrary);
       }
       type ??= findIn(Uris.dart_core);
@@ -1377,7 +1342,7 @@
     bool isStatic = node.isStatic;
     IndexedField field = createField(library, enclosingClass, name,
         isStatic: isStatic,
-        isAssignable: node.isMutable,
+        isAssignable: node.hasSetter,
         isConst: node.isConst);
     return members.register<IndexedField, KFieldData>(
         field, new KFieldDataImpl(node));
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 082be52..49c87e2 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -131,7 +131,7 @@
           }
         } else if (member is ir.Field) {
           _memberMap[member.name.text] = member;
-          if (member.isMutable) {
+          if (member.hasSetter) {
             _setterMap[member.name.text] = member;
           }
         } else {
@@ -242,9 +242,11 @@
   /// Whether the class is an unnamed mixin application.
   bool get isUnnamedMixinApplication;
 
-  /// Whether the class is a mixin application that mixes in methods with super
-  /// calls.
-  bool get isSuperMixinApplication;
+  /// Whether the class is a mixin application with its own members.
+  ///
+  /// This occurs when a mixin contains methods with super calls or when
+  /// the mixin application contains concrete forwarding stubs.
+  bool get isMixinApplicationWithMembers;
 
   /// Ensures that all members have been computed for [cls].
   void ensureMembers(KernelToElementMapImpl elementMap);
@@ -294,7 +296,7 @@
   Map<String, ir.Member> _memberMap;
   Map<String, ir.Member> _setterMap;
   List<ir.Member> _members; // in declaration order.
-  bool _isSuperMixinApplication;
+  bool _isMixinApplicationWithMembers;
 
   /// Constructor bodies created for this class.
   List<ConstructorBodyEntity> _constructorBodyList;
@@ -302,64 +304,15 @@
   KClassEnvImpl(this.cls);
 
   KClassEnvImpl.internal(this.cls, this._constructorMap, this._memberMap,
-      this._setterMap, this._members, this._isSuperMixinApplication);
+      this._setterMap, this._members, this._isMixinApplicationWithMembers);
 
   @override
   bool get isUnnamedMixinApplication => cls.isAnonymousMixin;
 
   @override
-  bool get isSuperMixinApplication {
-    assert(_isSuperMixinApplication != null);
-    return _isSuperMixinApplication;
-  }
-
-  /// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'.
-  ir.Constructor _buildForwardingConstructor(
-      CloneVisitorNotMembers cloner, ir.Constructor superclassConstructor) {
-    var superFunction = superclassConstructor.function;
-
-    // We keep types and default values for the parameters but always mark the
-    // parameters as final (since we just forward them to the super
-    // constructor).
-    ir.VariableDeclaration cloneVariable(ir.VariableDeclaration variable) {
-      ir.VariableDeclaration clone = cloner.clone(variable);
-      clone.isFinal = true;
-      return clone;
-    }
-
-    // Build a [FunctionNode] which has the same parameters as the one in the
-    // superclass constructor.
-    var positionalParameters =
-        superFunction.positionalParameters.map(cloneVariable).toList();
-    var namedParameters =
-        superFunction.namedParameters.map(cloneVariable).toList();
-    var function = new ir.FunctionNode(new ir.EmptyStatement(),
-        positionalParameters: positionalParameters,
-        namedParameters: namedParameters,
-        requiredParameterCount: superFunction.requiredParameterCount,
-        returnType: const ir.VoidType());
-
-    // Build a [SuperInitializer] which takes all positional/named parameters
-    // and forward them to the super class constructor.
-    var positionalArguments = <ir.Expression>[];
-    for (var variable in positionalParameters) {
-      positionalArguments.add(new ir.VariableGet(variable));
-    }
-    var namedArguments = <ir.NamedExpression>[];
-    for (var variable in namedParameters) {
-      namedArguments.add(
-          new ir.NamedExpression(variable.name, new ir.VariableGet(variable)));
-    }
-    var superInitializer = new ir.SuperInitializer(superclassConstructor,
-        new ir.Arguments(positionalArguments, named: namedArguments));
-
-    // Assemble the constructor
-    // TODO(jensj): Provide a "reference" if we need to support
-    // the incremental compiler.
-    return new ir.Constructor(function,
-        name: superclassConstructor.name,
-        initializers: <ir.Initializer>[superInitializer],
-        reference: null);
+  bool get isMixinApplicationWithMembers {
+    assert(_isMixinApplicationWithMembers != null);
+    return _isMixinApplicationWithMembers;
   }
 
   @override
@@ -374,21 +327,23 @@
     _setterMap = <String, ir.Member>{};
     _constructorMap = <String, ir.Member>{};
     var members = <ir.Member>[];
-    _isSuperMixinApplication = false;
+    _isMixinApplicationWithMembers = false;
 
     void addField(ir.Field member, {bool includeStatic}) {
       if (!includeStatic && member.isStatic) return;
       if (isRedirectingFactoryField(member)) return;
       var name = member.name.text;
       _memberMap[name] = member;
-      if (member.isMutable) {
+      if (member.hasSetter) {
         _setterMap[name] = member;
       }
       members.add(member);
     }
 
     void addProcedure(ir.Procedure member,
-        {bool includeStatic, bool includeNoSuchMethodForwarders}) {
+        {bool includeStatic,
+        bool includeNoSuchMethodForwarders,
+        bool isFromMixinApplication: false}) {
       if (memberIsIgnorable(member, cls: cls)) return;
       if (!includeStatic && member.isStatic) return;
       if (member.isNoSuchMethodForwarder) {
@@ -409,12 +364,18 @@
       } else if (member.kind == ir.ProcedureKind.Setter) {
         _setterMap[name] = member;
         members.add(member);
+        if (isFromMixinApplication) {
+          _isMixinApplicationWithMembers = true;
+        }
       } else {
         assert(member.kind == ir.ProcedureKind.Method ||
             member.kind == ir.ProcedureKind.Getter ||
             member.kind == ir.ProcedureKind.Operator);
         _memberMap[name] = member;
         members.add(member);
+        if (isFromMixinApplication) {
+          _isMixinApplicationWithMembers = true;
+        }
       }
     }
 
@@ -428,27 +389,68 @@
     int mixinMemberCount = 0;
 
     if (cls.mixedInClass != null) {
+      Map<ir.Name, ir.Procedure> existingNonSetters;
+      Map<ir.Name, ir.Procedure> existingSetters;
+
+      void ensureExistingProcedureMaps() {
+        if (existingNonSetters == null) {
+          existingNonSetters = {};
+          existingSetters = {};
+          for (ir.Procedure procedure in cls.procedures) {
+            if (procedure.kind == ir.ProcedureKind.Setter) {
+              existingSetters[procedure.name] = procedure;
+            } else {
+              existingNonSetters[procedure.name] = procedure;
+            }
+          }
+        }
+      }
+
       CloneVisitorWithMembers cloneVisitor;
       for (ir.Field field in cls.mixedInClass.mixin.fields) {
         if (field.containsSuperCalls) {
-          _isSuperMixinApplication = true;
-          cloneVisitor ??= new CloneVisitorWithMembers(
+          _isMixinApplicationWithMembers = true;
+          cloneVisitor ??= new MixinApplicationCloner(cls,
               typeSubstitution: getSubstitutionMap(cls.mixedInType));
           // TODO(jensj): Provide a "referenceFrom" if we need to support
           // the incremental compiler.
-          cls.addField(cloneVisitor.cloneField(field, null));
+          ensureExistingProcedureMaps();
+          ir.Procedure existingGetter = existingNonSetters[field.name];
+          ir.Procedure existingSetter = existingSetters[field.name];
+          cls.addField(cloneVisitor.cloneField(
+              field, existingGetter?.reference, existingSetter?.reference));
+          // TODO(johnniwinther): We need to unbind the canonical names before
+          // serializing these references since the canonical names refer to
+          // @getters and @setters instead of @fields and @fields=. This will
+          // not be needed if stop using @fields/@fields= in favor of
+          // @getters/@setters in general.
+          if (existingGetter != null) {
+            cls.procedures.remove(existingGetter);
+          }
+          if (existingSetter != null) {
+            cls.procedures.remove(existingSetter);
+          }
           continue;
         }
         addField(field, includeStatic: false);
       }
       for (ir.Procedure procedure in cls.mixedInClass.mixin.procedures) {
         if (procedure.containsSuperCalls) {
-          _isSuperMixinApplication = true;
-          cloneVisitor ??= new CloneVisitorWithMembers(
+          _isMixinApplicationWithMembers = true;
+          cloneVisitor ??= new MixinApplicationCloner(cls,
               typeSubstitution: getSubstitutionMap(cls.mixedInType));
           // TODO(jensj): Provide a "referenceFrom" if we need to support
           // the incremental compiler.
-          cls.addProcedure(cloneVisitor.cloneProcedure(procedure, null));
+          ensureExistingProcedureMaps();
+          ir.Procedure existingProcedure =
+              procedure.kind == ir.ProcedureKind.Setter
+                  ? existingSetters[procedure.name]
+                  : existingNonSetters[procedure.name];
+          if (existingProcedure != null) {
+            cls.procedures.remove(existingProcedure);
+          }
+          cls.addProcedure(cloneVisitor.cloneProcedure(
+              procedure, existingProcedure?.reference));
           continue;
         }
         addProcedure(procedure,
@@ -464,32 +466,9 @@
     addConstructors(cls);
     for (ir.Procedure member in cls.procedures) {
       addProcedure(member,
-          includeStatic: true, includeNoSuchMethodForwarders: true);
-    }
-
-    if (isUnnamedMixinApplication && _constructorMap.isEmpty) {
-      // Ensure that constructors are created for the superclass in case it
-      // is also an unnamed mixin application.
-      ClassEntity superclass = elementMap.getClass(cls.superclass);
-      elementMap.elementEnvironment.lookupConstructor(superclass, '');
-
-      // Unnamed mixin applications have no constructors when read from .dill.
-      // For each generative constructor in the superclass we make a
-      // corresponding forwarding constructor in the subclass.
-      //
-      // This code is copied from
-      // 'package:kernel/transformations/mixin_full_resolution.dart'
-      var superclassSubstitution = getSubstitutionMap(cls.supertype);
-      var superclassCloner =
-          new CloneVisitorNotMembers(typeSubstitution: superclassSubstitution);
-
-      for (var superclassConstructor in cls.superclass.constructors) {
-        var forwardingConstructor = _buildForwardingConstructor(
-            superclassCloner, superclassConstructor);
-        cls.addConstructor(forwardingConstructor);
-        _constructorMap[forwardingConstructor.name.text] =
-            forwardingConstructor;
-      }
+          includeStatic: true,
+          includeNoSuchMethodForwarders: true,
+          isFromMixinApplication: cls.mixedInClass != null);
     }
 
     mergeSort(members, start: mixinMemberCount, compare: orderByFileOffset);
@@ -590,7 +569,7 @@
       });
     }
     return new JClassEnvImpl(cls, constructorMap, memberMap, setterMap, members,
-        _isSuperMixinApplication ?? false);
+        _isMixinApplicationWithMembers ?? false);
   }
 }
 
diff --git a/pkg/compiler/lib/src/kernel/front_end_adapter.dart b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
index 571f11f..25796fa 100644
--- a/pkg/compiler/lib/src/kernel/front_end_adapter.dart
+++ b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
@@ -116,6 +116,9 @@
     case fe.Severity.warning:
       reporter.reportWarning(mainMessage, infos);
       break;
+    case fe.Severity.info:
+      reporter.reportInfo(mainMessage, infos);
+      break;
     default:
       throw new UnimplementedError('unhandled severity ${message.severity}');
   }
diff --git a/pkg/compiler/lib/src/kernel/kelements.dart b/pkg/compiler/lib/src/kernel/kelements.dart
index 8356cb5..886ccbf 100644
--- a/pkg/compiler/lib/src/kernel/kelements.dart
+++ b/pkg/compiler/lib/src/kernel/kelements.dart
@@ -202,7 +202,7 @@
   KGetter(KLibrary library, KClass enclosingClass, Name name,
       AsyncMarker asyncMarker,
       {bool isStatic, bool isExternal, this.isAbstract})
-      : super(library, enclosingClass, name, const ParameterStructure.getter(),
+      : super(library, enclosingClass, name, ParameterStructure.getter,
             asyncMarker,
             isStatic: isStatic, isExternal: isExternal);
 
@@ -219,7 +219,7 @@
 
   KSetter(KLibrary library, KClass enclosingClass, Name name,
       {bool isStatic, bool isExternal, this.isAbstract})
-      : super(library, enclosingClass, name, const ParameterStructure.setter(),
+      : super(library, enclosingClass, name, ParameterStructure.setter,
             AsyncMarker.SYNC,
             isStatic: isStatic, isExternal: isExternal);
 
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index d167042..f3df3a2 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -499,18 +499,19 @@
   }
 
   @override
-  void registerSuperInvocation(ir.Name name, int positionalArguments,
+  void registerSuperInvocation(ir.Member target, int positionalArguments,
       List<String> namedArguments, List<ir.DartType> typeArguments) {
-    FunctionEntity method =
-        elementMap.getSuperMember(currentMember, name, setter: false);
-    List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
-    if (method != null) {
+    if (target != null) {
+      FunctionEntity method = elementMap.getMember(target);
+      List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
       impactBuilder.registerStaticUse(new StaticUse.superInvoke(
           method,
           new CallStructure(positionalArguments + namedArguments.length,
               namedArguments, typeArguments.length),
           dartTypeArguments));
     } else {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
       impactBuilder.registerStaticUse(new StaticUse.superInvoke(
           elementMap.getSuperNoSuchMethod(currentMember.enclosingClass),
           CallStructure.ONE_ARG));
@@ -519,16 +520,17 @@
   }
 
   @override
-  void registerSuperGet(ir.Name name) {
-    MemberEntity member =
-        elementMap.getSuperMember(currentMember, name, setter: false);
-    if (member != null) {
+  void registerSuperGet(ir.Member target) {
+    if (target != null) {
+      MemberEntity member = elementMap.getMember(target);
       if (member.isFunction) {
         impactBuilder.registerStaticUse(new StaticUse.superTearOff(member));
       } else {
         impactBuilder.registerStaticUse(new StaticUse.superGet(member));
       }
     } else {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
       impactBuilder.registerStaticUse(new StaticUse.superInvoke(
           elementMap.getSuperNoSuchMethod(currentMember.enclosingClass),
           CallStructure.ONE_ARG));
@@ -537,16 +539,17 @@
   }
 
   @override
-  void registerSuperSet(ir.Name name) {
-    MemberEntity member =
-        elementMap.getSuperMember(currentMember, name, setter: true);
-    if (member != null) {
+  void registerSuperSet(ir.Member target) {
+    if (target != null) {
+      MemberEntity member = elementMap.getMember(target);
       if (member.isField) {
         impactBuilder.registerStaticUse(new StaticUse.superFieldSet(member));
       } else {
         impactBuilder.registerStaticUse(new StaticUse.superSetterSet(member));
       }
     } else {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
       impactBuilder.registerStaticUse(new StaticUse.superInvoke(
           elementMap.getSuperNoSuchMethod(currentMember.enclosingClass),
           CallStructure.ONE_ARG));
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index d40a061..99a37c5 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -138,8 +138,13 @@
         bool verbose = false;
         Target target = Dart2jsTarget(targetName, TargetFlags());
         fe.FileSystem fileSystem = CompilerFileSystem(_compilerInput);
+        fe.Verbosity verbosity = _options.verbosity;
         fe.DiagnosticMessageHandler onDiagnostic =
-            (e) => reportFrontEndMessage(_reporter, e);
+            (fe.DiagnosticMessage message) {
+          if (fe.Verbosity.shouldPrint(verbosity, message)) {
+            reportFrontEndMessage(_reporter, message);
+          }
+        };
         fe.CompilerOptions options = fe.CompilerOptions()
           ..target = target
           ..librariesSpecificationUri = _options.librariesSpecificationUri
@@ -147,7 +152,8 @@
           ..explicitExperimentalFlags = _options.explicitExperimentalFlags
           ..verbose = verbose
           ..fileSystem = fileSystem
-          ..onDiagnostic = onDiagnostic;
+          ..onDiagnostic = onDiagnostic
+          ..verbosity = verbosity;
         bool isLegacy =
             await fe.uriUsesLegacyLanguageVersion(resolvedUri, options);
         inferNullSafetyMode(_options.enableNonNullable && !isLegacy);
@@ -170,7 +176,9 @@
             explicitExperimentalFlags: _options.explicitExperimentalFlags,
             nnbdMode: _options.useLegacySubtyping
                 ? fe.NnbdMode.Weak
-                : fe.NnbdMode.Strong);
+                : fe.NnbdMode.Strong,
+            invocationModes: _options.cfeInvocationModes,
+            verbosity: verbosity);
         component = await fe.compile(initializedCompilerState, verbose,
             fileSystem, onDiagnostic, resolvedUri);
         if (component == null) return null;
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 47b0985..ddb6dd0 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -161,6 +161,15 @@
   /// libraries are subdivided.
   Uri deferredMapUri;
 
+  /// The maximum number of deferred fragments to generate. If the number of
+  /// fragments exceeds this amount, then they may be merged.
+  /// Note: Currently, we only merge fragments in a single dependency chain. We
+  /// 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;
+
   /// Whether to disable inlining during the backend optimizations.
   // TODO(sigmund): negate, so all flags are positive
   bool disableInlining = false;
@@ -415,6 +424,20 @@
   /// deserialize when using [readCodegenUri].
   int codegenShards;
 
+  /// Arguments passed to the front end about how it is invoked.
+  ///
+  /// This is used to selectively emit certain messages depending on how the
+  /// CFE is invoked. For instance to emit a message about the null safety
+  /// compilation mode when compiling an executable.
+  ///
+  /// See `InvocationMode` in
+  /// `pkg/front_end/lib/src/api_prototype/compiler_options.dart` for all
+  /// possible options.
+  Set<fe.InvocationMode> cfeInvocationModes = {};
+
+  /// Verbosity level used for filtering messages during compilation.
+  fe.Verbosity verbosity = fe.Verbosity.all;
+
   // -------------------------------------------------
   // Options for deprecated features
   // -------------------------------------------------
@@ -524,7 +547,16 @@
       ..cfeOnly = _hasOption(options, Flags.cfeOnly)
       ..debugGlobalInference = _hasOption(options, Flags.debugGlobalInference)
       .._soundNullSafety = _hasOption(options, Flags.soundNullSafety)
-      .._noSoundNullSafety = _hasOption(options, Flags.noSoundNullSafety);
+      .._noSoundNullSafety = _hasOption(options, Flags.noSoundNullSafety)
+      .._mergeFragmentsThreshold =
+          _extractIntOption(options, '${Flags.mergeFragmentsThreshold}=')
+      ..cfeInvocationModes = fe.InvocationMode.parseArguments(
+          _extractStringOption(options, '${Flags.cfeInvocationModes}=', ''),
+          onError: onError)
+      ..verbosity = fe.Verbosity.parseArgument(
+          _extractStringOption(
+              options, '${Flags.verbosity}=', fe.Verbosity.defaultValue),
+          onError: onError);
   }
 
   void validate() {
@@ -628,6 +660,10 @@
     if (_noNativeNullAssertions || nullSafetyMode != NullSafetyMode.sound) {
       nativeNullAssertions = false;
     }
+
+    if (_mergeFragmentsThreshold != null) {
+      mergeFragmentsThreshold = _mergeFragmentsThreshold;
+    }
   }
 
   /// Returns `true` if warnings and hints are shown for all packages.
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index c127c695b..1bd824c 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -538,6 +538,8 @@
         break;
       case ConstantValueKind.DUMMY_INTERCEPTOR:
         break;
+      case ConstantValueKind.LATE_SENTINEL:
+        break;
       case ConstantValueKind.UNREACHABLE:
         break;
       case ConstantValueKind.JS_NAME:
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index c1e8ea1..f053835 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -546,6 +546,8 @@
         return new DeferredGlobalConstantValue(constant, unit);
       case ConstantValueKind.DUMMY_INTERCEPTOR:
         return DummyInterceptorConstantValue();
+      case ConstantValueKind.LATE_SENTINEL:
+        return LateSentinelConstantValue();
       case ConstantValueKind.UNREACHABLE:
         return UnreachableConstantValue();
       case ConstantValueKind.JS_NAME:
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 28d3224..707def0 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -259,25 +259,38 @@
         _reporter.log('Reading data from ${uri}');
         api.Input<List<int>> dataInput =
             await _provider.readFromUri(uri, inputKind: api.InputKind.binary);
-        DataSource source = new BinarySourceImpl(dataInput.data);
-        backendStrategy.prepareCodegenReader(source);
-        Map<MemberEntity, CodegenResult> codegenResults =
-            source.readMemberMap((MemberEntity member) {
-          List<ModularName> modularNames = [];
-          List<ModularExpression> modularExpressions = [];
-          CodegenReader reader = new CodegenReaderImpl(
-              closedWorld, modularNames, modularExpressions);
-          source.registerCodegenReader(reader);
-          CodegenResult result = CodegenResult.readFromDataSource(
-              source, modularNames, modularExpressions);
-          source.deregisterCodegenReader(reader);
-          return result;
-        });
-        _reporter.log('Read ${codegenResults.length} members from ${uri}');
-        results.addAll(codegenResults);
+        // TODO(36983): This code is extracted because there appeared to be a
+        // memory leak for large buffer held by `source`.
+        _deserializeCodegenInput(
+            backendStrategy, closedWorld, uri, dataInput, results);
+        dataInput.release();
       });
     }
     return new DeserializedCodegenResults(
         globalTypeInferenceResults, codegenInputs, results);
   }
+
+  void _deserializeCodegenInput(
+      BackendStrategy backendStrategy,
+      JClosedWorld closedWorld,
+      Uri uri,
+      api.Input<List<int>> dataInput,
+      Map<MemberEntity, CodegenResult> results) {
+    DataSource source = new BinarySourceImpl(dataInput.data);
+    backendStrategy.prepareCodegenReader(source);
+    Map<MemberEntity, CodegenResult> codegenResults =
+        source.readMemberMap((MemberEntity member) {
+      List<ModularName> modularNames = [];
+      List<ModularExpression> modularExpressions = [];
+      CodegenReader reader =
+          new CodegenReaderImpl(closedWorld, modularNames, modularExpressions);
+      source.registerCodegenReader(reader);
+      CodegenResult result = CodegenResult.readFromDataSource(
+          source, modularNames, modularExpressions);
+      source.deregisterCodegenReader(reader);
+      return result;
+    });
+    _reporter.log('Read ${codegenResults.length} members from ${uri}');
+    results.addAll(codegenResults);
+  }
 }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 7c66c12..20e835b 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -3469,12 +3469,14 @@
     node.value.accept(this);
     HInstruction value = pop();
 
-    MemberEntity member = _elementMap
-        .getSuperMember(_currentFrame.member, node.name, setter: true);
-    if (member == null) {
+    ir.Member target = getEffectiveSuperTarget(node.interfaceTarget);
+    if (target == null) {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
       _generateSuperNoSuchMethod(node, _elementMap.getSelector(node).name + "=",
           <HInstruction>[value], const <DartType>[], sourceInformation);
     } else {
+      MemberEntity member = _elementMap.getMember(target);
       _buildInvokeSuper(
           _elementMap.getSelector(node),
           _elementMap.getClass(_containingClass(node)),
@@ -4145,6 +4147,10 @@
       _handleForeignTypeRef(invocation);
     } else if (name == 'LEGACY_TYPE_REF') {
       _handleForeignLegacyTypeRef(invocation);
+    } else if (name == 'createJsSentinel') {
+      _handleForeignCreateJsSentinel(invocation);
+    } else if (name == 'isJsSentinel') {
+      _handleForeignIsJsSentinel(invocation);
     } else {
       reporter.internalError(
           _elementMap.getSpannable(targetElement, invocation),
@@ -4861,6 +4867,22 @@
       ..sourceInformation = sourceInformation);
   }
 
+  void _handleForeignCreateJsSentinel(ir.StaticInvocation invocation) {
+    SourceInformation sourceInformation =
+        _sourceInformationBuilder.buildCall(invocation, invocation);
+    stack.add(graph.addConstantLateSentinel(closedWorld,
+        sourceInformation: sourceInformation));
+  }
+
+  void _handleForeignIsJsSentinel(ir.StaticInvocation invocation) {
+    SourceInformation sourceInformation =
+        _sourceInformationBuilder.buildCall(invocation, invocation);
+    HInstruction checkedExpression =
+        _visitPositionalArguments(invocation.arguments).single;
+    push(HIsLateSentinel(checkedExpression, _abstractValueDomain.boolType)
+      ..sourceInformation = sourceInformation);
+  }
+
   void _pushStaticInvocation(MemberEntity target, List<HInstruction> arguments,
       AbstractValue typeMask, List<DartType> typeArguments,
       {SourceInformation sourceInformation, InterfaceType instanceType}) {
@@ -5291,13 +5313,15 @@
   void visitSuperPropertyGet(ir.SuperPropertyGet node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildGet(node);
-    MemberEntity member =
-        _elementMap.getSuperMember(_currentFrame.member, node.name);
-    if (member == null) {
+    ir.Member target = getEffectiveSuperTarget(node.interfaceTarget);
+    if (target == null) {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
       _generateSuperNoSuchMethod(node, _elementMap.getSelector(node).name,
           const <HInstruction>[], const <DartType>[], sourceInformation);
       return;
     }
+    MemberEntity member = _elementMap.getMember(target);
     if (member.isField) {
       FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(member);
       if (fieldData.isEffectivelyConstant) {
@@ -5320,9 +5344,10 @@
   void visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildCall(node, node);
-    MemberEntity member =
-        _elementMap.getSuperMember(_currentFrame.member, node.name);
-    if (member == null) {
+    ir.Member superTarget = getEffectiveSuperTarget(node.interfaceTarget);
+    if (superTarget == null) {
+      // TODO(johnniwinther): Remove this when the CFE checks for missing
+      //  concrete super targets.
       Selector selector = _elementMap.getSelector(node);
       List<DartType> typeArguments = <DartType>[];
       selector =
@@ -5333,6 +5358,7 @@
           node, selector.name, arguments, typeArguments, sourceInformation);
       return;
     }
+    MemberEntity member = _elementMap.getMember(superTarget);
     List<DartType> typeArguments =
         _getStaticTypeArguments(member, node.arguments);
 
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 098531f..81f1761 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -642,7 +642,8 @@
   List<js.Expression> visitArguments(List<HInstruction> inputs,
       {int start: HInvoke.ARGUMENTS_OFFSET}) {
     assert(inputs.length >= start);
-    List<js.Expression> result = new List<js.Expression>.filled(inputs.length - start, null);
+    List<js.Expression> result =
+        new List<js.Expression>.filled(inputs.length - start, null);
     for (int i = start; i < inputs.length; i++) {
       use(inputs[i]);
       result[i - start] = pop();
@@ -2564,6 +2565,8 @@
         use(input.inputs[0]);
       } else if (input is HIdentity) {
         emitIdentityComparison(input, sourceInformation, inverse: true);
+      } else if (input is HIsLateSentinel) {
+        _emitIsLateSentinel(input, sourceInformation, inverse: true);
       } else if (canGenerateOptimizedComparison(input)) {
         HRelational relational = input;
         constant_system.BinaryOperation operation = relational.operation();
@@ -2710,7 +2713,9 @@
       assert(over != null || under != null);
       js.Expression underOver = under == null
           ? over
-          : over == null ? under : new js.Binary("||", under, over);
+          : over == null
+              ? under
+              : new js.Binary("||", under, over);
       js.Statement thenBody = new js.Block.empty();
       js.Block oldContainer = currentContainer;
       currentContainer = thenBody;
@@ -3272,4 +3277,18 @@
     _registry.registerStaticUse(
         new StaticUse.directInvoke(method, selector.callStructure, null));
   }
+
+  _emitIsLateSentinel(HIsLateSentinel node, SourceInformation sourceInformation,
+      {inverse: false}) {
+    use(node.inputs[0]);
+    js.Expression value = pop();
+    js.Expression sentinel =
+        _emitter.constantReference(LateSentinelConstantValue());
+    push(js.Binary(mapRelationalOperator('===', inverse), value, sentinel)
+        .withSourceInformation(sourceInformation));
+  }
+
+  @override
+  visitIsLateSentinel(HIsLateSentinel node) =>
+      _emitIsLateSentinel(node, node.sourceInformation);
 }
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 25b48a8..cf71f75 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -66,6 +66,7 @@
   R visitInvokeSuper(HInvokeSuper node);
   R visitInvokeConstructorBody(HInvokeConstructorBody node);
   R visitInvokeGeneratorBody(HInvokeGeneratorBody node);
+  R visitIsLateSentinel(HIsLateSentinel node);
   R visitLateValue(HLateValue node);
   R visitLazyStatic(HLazyStatic node);
   R visitLess(HLess node);
@@ -339,6 +340,11 @@
     return addConstant(UnreachableConstantValue(), closedWorld);
   }
 
+  HConstant addConstantLateSentinel(JClosedWorld closedWorld,
+          {SourceInformation sourceInformation}) =>
+      addConstant(LateSentinelConstantValue(), closedWorld,
+          sourceInformation: sourceInformation);
+
   void finalize(AbstractValueDomain domain) {
     addBlock(exit);
     exit.open();
@@ -577,6 +583,8 @@
   @override
   visitTry(HTry node) => visitControlFlow(node);
   @override
+  visitIsLateSentinel(HIsLateSentinel node) => visitInstruction(node);
+  @override
   visitLateValue(HLateValue node) => visitInstruction(node);
   @override
   visitBoolConversion(HBoolConversion node) => visitCheck(node);
@@ -1093,6 +1101,8 @@
   static const int TYPE_EVAL_TYPECODE = 56;
   static const int TYPE_BIND_TYPECODE = 57;
 
+  static const int IS_LATE_SENTINEL_TYPECODE = 58;
+
   HInstruction(this.inputs, this.instructionType) {
     assert(inputs.every((e) => e != null), "inputs: $inputs");
   }
@@ -4513,3 +4523,25 @@
   @override
   String toString() => 'HTypeBind()';
 }
+
+class HIsLateSentinel extends HInstruction {
+  HIsLateSentinel(HInstruction value, AbstractValue type)
+      : super([value], type) {
+    setUseGvn();
+  }
+
+  @override
+  accept(HVisitor visitor) => visitor.visitIsLateSentinel(this);
+
+  @override
+  int typeCode() => HInstruction.IS_LATE_SENTINEL_TYPECODE;
+
+  @override
+  bool typeEquals(HInstruction other) => other is HIsLateSentinel;
+
+  @override
+  bool dataEquals(HIsLateSentinel other) => true;
+
+  @override
+  String toString() => 'HIsLateSentinel()';
+}
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index b855b90..5f0726f 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -1186,6 +1186,20 @@
     return newInstruction == null ? super.visitIdentity(node) : newInstruction;
   }
 
+  @override
+  HInstruction visitIsLateSentinel(HIsLateSentinel node) {
+    HInstruction value = node.inputs[0];
+    if (value is HConstant) {
+      return _graph.addConstantBool(
+          value.constant is LateSentinelConstantValue, _closedWorld);
+    }
+
+    // TODO(fishythefish): Simplify to `false` when the input cannot evalute to
+    // the sentinel. This can be implemented in the powerset domain.
+
+    return super.visitIsLateSentinel(node);
+  }
+
   void simplifyCondition(
       HBasicBlock block, HInstruction condition, bool value) {
     // `excludePhiOutEdges: true` prevents replacing a partially dominated phi
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index ef1ad6a..3eb079b 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -169,6 +169,10 @@
   }
 
   @override
+  String visitIsLateSentinel(HIsLateSentinel node) =>
+      'IsLateSentinel: ${temporaryId(node.inputs[0])}';
+
+  @override
   String visitLateValue(HLateValue node) {
     return "LateValue: ${temporaryId(node.inputs[0])}";
   }
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index 8a61bf9..0f826c1 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -26,7 +26,7 @@
   js_ast:
     path: ../js_ast
   js_runtime:
-    path: ../../sdk/lib/_internal/js_runtime
+    path: ../js_runtime
 
 dev_dependencies:
   # Published packages - repo version ensured via dependency_overrides
diff --git a/pkg/compiler/test/deferred_loading/data/basic_deferred/main.dart b/pkg/compiler/test/deferred_loading/data/basic_deferred/main.dart
index ca84a9f..ab1d73d 100644
--- a/pkg/compiler/test/deferred_loading/data/basic_deferred/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/basic_deferred/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib.dart' deferred as lib;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_class/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_class/main.dart
index bb45d8c..af43fe3 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_class/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_class/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib.dart' deferred as lib;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant1/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant1/main.dart
index 5a1c77d..fa722a4 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant1/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant1/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib2}], usedBy: [], needs: []}],
+ steps=[lib2=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib1.dart';
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant2/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant2/main.dart
index 71a715b..b4cc534 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant2/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant2/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'package:expect/expect.dart';
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant3/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant3/main.dart
index 5bc723e..0810049 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant3/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant3/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[
+  f1: {units: [1{l1}], usedBy: [], needs: []},
+  f2: {units: [2{l2}], usedBy: [], needs: []}],
+ steps=[
+  l1=(f1),
+  l2=(f2)]
+*/
+
 // @dart = 2.7
 
 import 'shared.dart';
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/main.dart
index 167b145..ba1eed1 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 // Test that when a deferred import fails to load, it is possible to retry.
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_function/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_function/main.dart
index 3c99316..48dd14a 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_function/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_function/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 // Test that loading of a library (with top-level functions only) can
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/main.dart
index 782e177..1da36d1 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/main.dart
@@ -2,6 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec|three-frag.library: 
+ output_units=[
+  f1: {units: [1{lib1, lib2}], usedBy: [2, 3], needs: []},
+  f2: {units: [2{lib1}], usedBy: [], needs: [1]},
+  f3: {units: [3{lib2}], usedBy: [], needs: [1]}],
+ steps=[
+  lib1=(f1, f2),
+  lib2=(f1, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [1{lib1, lib2}, 2{lib1}], usedBy: [2], needs: []},
+  f2: {units: [3{lib2}], usedBy: [], needs: [1]}],
+ steps=[
+  lib1=(f1),
+  lib2=(f1, f2)]
+*/
+
 // @dart = 2.7
 
 import 'lib1.dart' deferred as lib1;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_typed_map/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_typed_map/main.dart
index 20bb44c..45bddff 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_typed_map/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_typed_map/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib1.dart' deferred as lib;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_typedef/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_typedef/main.dart
index 9c56b84..c838c8f 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_typedef/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_typedef/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib1}], usedBy: [], needs: []}],
+ steps=[lib1=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib1.dart' deferred as lib1;
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/main.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/main.dart
index e55be81..d65299a 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/main.dart
@@ -2,6 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec|three-frag.library: 
+ output_units=[
+  f1: {units: [2{lib1, lib2}], usedBy: [2, 3], needs: []},
+  f2: {units: [1{lib1}], usedBy: [], needs: [1]},
+  f3: {units: [3{lib2}], usedBy: [], needs: [1]}],
+ steps=[
+  lib1=(f1, f2),
+  lib2=(f1, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [2{lib1, lib2}, 3{lib2}], usedBy: [2], needs: []},
+  f2: {units: [1{lib1}], usedBy: [], needs: [1]}],
+ steps=[
+  lib1=(f1, f2),
+  lib2=(f1)]
+*/
+
 // @dart = 2.7
 
 // TODO(sigmund): remove this indirection and move the main code here. This is
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/main.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/main.dart
index 3a45b3e..59d567e 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib.dart' deferred as lib;
diff --git a/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/main.dart b/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/main.dart
index 74cd88d..0465c9f 100644
--- a/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 import "lib.dart" deferred as lib;
diff --git a/pkg/compiler/test/deferred_loading/data/future_or/main.dart b/pkg/compiler/test/deferred_loading/data/future_or/main.dart
index de44d54..77ca4a0 100644
--- a/pkg/compiler/test/deferred_loading/data/future_or/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/future_or/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib1}], usedBy: [], needs: []}],
+ steps=[lib1=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'dart:async';
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
index 5da17d9..9b83f62 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{b}], usedBy: [], needs: []}],
+ steps=[b=(f1)]
+*/
+
 // @dart = 2.7
 
 // Test instantiation used only in a deferred library.
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
index ae2c5a7..963d421 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
@@ -2,6 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec|three-frag.library: 
+ output_units=[
+  f1: {units: [2{b, c}], usedBy: [2, 3], needs: []},
+  f2: {units: [1{b}], usedBy: [], needs: [1]},
+  f3: {units: [3{c}], usedBy: [], needs: [1]}],
+ steps=[
+  b=(f1, f2),
+  c=(f1, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [2{b, c}, 1{b}], usedBy: [2], needs: []},
+  f2: {units: [3{c}], usedBy: [], needs: [1]}],
+ steps=[
+  b=(f1),
+  c=(f1, f2)]
+*/
+
 // @dart = 2.7
 
 // Test instantiations with different type argument count used only in two
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
index 3ff8f46..53cbbdb 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
@@ -2,6 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec|three-frag.library: 
+ output_units=[
+  f1: {units: [1{b, c}], usedBy: [2, 3], needs: []},
+  f2: {units: [2{b}], usedBy: [], needs: [1]},
+  f3: {units: [3{c}], usedBy: [], needs: [1]}],
+ steps=[
+  b=(f1, f2),
+  c=(f1, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [1{b, c}, 2{b}], usedBy: [2], needs: []},
+  f2: {units: [3{c}], usedBy: [], needs: [1]}],
+ steps=[
+  b=(f1),
+  c=(f1, f2)]
+*/
+
 // @dart = 2.7
 
 // Test instantiations with the same type argument count used only in two
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
index b0d3a8f..10e0815 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{b}], usedBy: [], needs: []}],
+ steps=[b=(f1)]
+*/
+
 // @dart = 2.7
 
 // Test instantiation used only in a deferred library.
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
index 34bf22a..c6b601b 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
@@ -2,6 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec|three-frag.library: 
+ output_units=[
+  f1: {units: [2{b, c}], usedBy: [2, 3], needs: []},
+  f2: {units: [1{b}], usedBy: [], needs: [1]},
+  f3: {units: [3{c}], usedBy: [], needs: [1]}],
+ steps=[
+  b=(f1, f2),
+  c=(f1, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [2{b, c}, 1{b}], usedBy: [2], needs: []},
+  f2: {units: [3{c}], usedBy: [], needs: [1]}],
+ steps=[
+  b=(f1),
+  c=(f1, f2)]
+*/
+
 // @dart = 2.7
 
 // Test instantiations with different type argument count used only in two
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
index 5612525..8dbfaf1 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
@@ -2,6 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec|three-frag.library: 
+ output_units=[
+  f1: {units: [1{b, c}], usedBy: [2, 3], needs: []},
+  f2: {units: [2{b}], usedBy: [], needs: [1]},
+  f3: {units: [3{c}], usedBy: [], needs: [1]}],
+ steps=[
+  b=(f1, f2),
+  c=(f1, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [1{b, c}, 2{b}], usedBy: [2], needs: []},
+  f2: {units: [3{c}], usedBy: [], needs: [1]}],
+ steps=[
+  b=(f1),
+  c=(f1, f2)]
+*/
+
 // @dart = 2.7
 
 // Test instantiations with the same type argument count used only in two
diff --git a/pkg/compiler/test/deferred_loading/data/inteface_type_variable/main.dart b/pkg/compiler/test/deferred_loading/data/inteface_type_variable/main.dart
index d4b10fb..491bcf6 100644
--- a/pkg/compiler/test/deferred_loading/data/inteface_type_variable/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/inteface_type_variable/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib.dart' deferred as lib;
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
index ca9bb68..441c28d 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
@@ -2,6 +2,41 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec.library: 
+ output_units=[
+  f1: {units: [3{libA, libB, libC}], usedBy: [2, 4], needs: []},
+  f2: {units: [4{libA, libC}], usedBy: [3, 6], needs: [1, 4]},
+  f3: {units: [6{libA}], usedBy: [], needs: [2]},
+  f4: {units: [5{libB, libC}], usedBy: [5, 2], needs: [1]},
+  f5: {units: [1{libB}], usedBy: [], needs: [4]},
+  f6: {units: [2{libC}], usedBy: [], needs: [2]}],
+ steps=[
+  libA=(f1, f2, f3),
+  libB=(f1, f4, f5),
+  libC=(f1, f4, f2, f6)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [3{libA, libB, libC}, 5{libB, libC}, 4{libA, libC}, 6{libA}, 1{libB}], usedBy: [2], needs: []},
+  f2: {units: [2{libC}], usedBy: [], needs: [1]}],
+ steps=[
+  libA=(f1),
+  libB=(f1),
+  libC=(f1, f2)]
+*/
+
+/*three-frag.library: 
+ output_units=[
+  f1: {units: [3{libA, libB, libC}, 5{libB, libC}, 4{libA, libC}, 6{libA}], usedBy: [2, 3], needs: []},
+  f2: {units: [1{libB}], usedBy: [], needs: [1]},
+  f3: {units: [2{libC}], usedBy: [], needs: [1]}],
+ steps=[
+  libA=(f1),
+  libB=(f1, f2),
+  libC=(f1, f3)]
+*/
+
 // @dart = 2.7
 
 import 'liba.dart' deferred as libA;
diff --git a/pkg/compiler/test/deferred_loading/data/many_parts/libB.dart b/pkg/compiler/test/deferred_loading/data/many_parts/libB.dart
index 7f86fc1..85002e0 100644
--- a/pkg/compiler/test/deferred_loading/data/many_parts/libB.dart
+++ b/pkg/compiler/test/deferred_loading/data/many_parts/libB.dart
@@ -35,7 +35,8 @@
 f_010_11(Set<String> u, int b) => v(u, '01011', b);
 
 @pragma('dart2js:noInline')
-/*member: f_011_01:member_unit=8{b1, b3, b4}*/
+/*spec|two-frag.member: f_011_01:member_unit=8{b1, b3, b4}*/
+/*three-frag.member: f_011_01:member_unit=8{b1, b3, b4, b2, b5}*/
 f_011_01(Set<String> u, int b) => v(u, '01101', b);
 
 @pragma('dart2js:noInline')
@@ -51,7 +52,8 @@
 f_100_11(Set<String> u, int b) => v(u, '10011', b);
 
 @pragma('dart2js:noInline')
-/*member: f_101_01:member_unit=12{b1, b3, b5}*/
+/*spec|three-frag.member: f_101_01:member_unit=12{b1, b3, b5}*/
+/*two-frag.member: f_101_01:member_unit=12{b1, b3, b5, b4, b2}*/
 f_101_01(Set<String> u, int b) => v(u, '10101', b);
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/deferred_loading/data/many_parts/main.dart b/pkg/compiler/test/deferred_loading/data/many_parts/main.dart
index 7c057b4..0fc9253 100644
--- a/pkg/compiler/test/deferred_loading/data/many_parts/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/many_parts/main.dart
@@ -2,6 +2,72 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec.library: 
+ output_units=[
+  f10: {units: [7{b1, b2, b4}], usedBy: [11, 29], needs: [9, 8]},
+  f11: {units: [5{b1, b2, b3}], usedBy: [12, 21, 26], needs: [10, 8]},
+  f12: {units: [10{b1, b5}], usedBy: [13, 31], needs: [11, 21]},
+  f13: {units: [6{b1, b4}], usedBy: [14, 30], needs: [12, 22]},
+  f14: {units: [4{b1, b3}], usedBy: [15, 28], needs: [13, 23]},
+  f15: {units: [3{b1, b2}], usedBy: [16, 24], needs: [14, 23]},
+  f16: {units: [2{b1}], usedBy: [], needs: [15]},
+  f17: {units: [24{b2, b3, b4, b5}], usedBy: [3, 2], needs: [1]},
+  f18: {units: [23{b2, b4, b5}], usedBy: [19, 20], needs: [5, 25]},
+  f19: {units: [22{b2, b3, b5}], usedBy: [20, 6], needs: [18, 25]},
+  f1: {units: [1{b1, b2, b3, b4, b5}], usedBy: [2, 17], needs: []},
+  f20: {units: [20{b2, b3, b4}], usedBy: [9, 7, 6], needs: [19, 18]},
+  f21: {units: [21{b2, b5}], usedBy: [22, 12], needs: [11, 26]},
+  f22: {units: [19{b2, b4}], usedBy: [23, 13], needs: [21, 27]},
+  f23: {units: [18{b2, b3}], usedBy: [15, 14], needs: [22, 27]},
+  f24: {units: [17{b2}], usedBy: [], needs: [15]},
+  f25: {units: [28{b3, b4, b5}], usedBy: [19, 18], needs: [5, 4]},
+  f26: {units: [27{b3, b5}], usedBy: [27, 21], needs: [11, 29]},
+  f27: {units: [26{b3, b4}], usedBy: [23, 22], needs: [26, 29]},
+  f28: {units: [25{b3}], usedBy: [], needs: [14]},
+  f29: {units: [30{b4, b5}], usedBy: [27, 26], needs: [10, 9]},
+  f2: {units: [16{b1, b3, b4, b5}], usedBy: [3, 4], needs: [1, 17]},
+  f30: {units: [29{b4}], usedBy: [], needs: [13]},
+  f31: {units: [31{b5}], usedBy: [], needs: [12]},
+  f3: {units: [15{b1, b2, b4, b5}], usedBy: [4, 5], needs: [2, 17]},
+  f4: {units: [13{b1, b2, b3, b5}], usedBy: [5, 25], needs: [3, 2]},
+  f5: {units: [9{b1, b2, b3, b4}], usedBy: [6, 18, 25], needs: [4, 3]},
+  f6: {units: [14{b1, b4, b5}], usedBy: [7, 8], needs: [5, 20, 19]},
+  f7: {units: [12{b1, b3, b5}], usedBy: [8, 9], needs: [6, 20]},
+  f8: {units: [8{b1, b3, b4}], usedBy: [9, 11, 10], needs: [7, 6]},
+  f9: {units: [11{b1, b2, b5}], usedBy: [10, 29], needs: [8, 20, 7]}],
+ steps=[
+  b1=(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16),
+  b2=(f1, f17, f3, f4, f5, f18, f19, f20, f9, f10, f11, f21, f22, f23, f15, f24),
+  b3=(f1, f17, f2, f4, f5, f25, f19, f20, f7, f8, f11, f26, f27, f23, f14, f28),
+  b4=(f1, f17, f2, f3, f5, f25, f18, f20, f6, f8, f10, f29, f27, f22, f13, f30),
+  b5=(f1, f17, f2, f3, f4, f25, f18, f19, f6, f7, f9, f29, f26, f21, f12, f31)]
+*/
+
+/*three-frag.library: 
+ output_units=[
+  f1: {units: [1{b1, b2, b3, b4, b5}, 24{b2, b3, b4, b5}, 16{b1, b3, b4, b5}, 15{b1, b2, b4, b5}, 13{b1, b2, b3, b5}, 9{b1, b2, b3, b4}, 28{b3, b4, b5}, 23{b2, b4, b5}, 22{b2, b3, b5}, 20{b2, b3, b4}, 14{b1, b4, b5}], usedBy: [2, 3], needs: []},
+  f2: {units: [12{b1, b3, b5}], usedBy: [3], needs: [1]},
+  f3: {units: [8{b1, b3, b4, b2, b5}, 11{b1, b2, b5}, 7{b1, b2, b4}, 5{b1, b2, b3}, 30{b4, b5}, 27{b3, b5}, 26{b3, b4}, 21{b2, b5}, 19{b2, b4}, 18{b2, b3}, 10{b1, b5}, 31{b5}, 6{b1, b4}, 29{b4}, 4{b1, b3}, 25{b3}, 3{b1, b2}, 2{b1}, 17{b2}], usedBy: [], needs: [2, 1]}],
+ steps=[
+  b1=(f1, f2, f3),
+  b2=(f1, f3),
+  b3=(f1, f2, f3),
+  b4=(f1, f3),
+  b5=(f1, f2, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [1{b1, b2, b3, b4, b5}, 24{b2, b3, b4, b5}, 16{b1, b3, b4, b5}, 15{b1, b2, b4, b5}, 13{b1, b2, b3, b5}, 9{b1, b2, b3, b4}, 28{b3, b4, b5}, 23{b2, b4, b5}, 22{b2, b3, b5}, 20{b2, b3, b4}, 14{b1, b4, b5}], usedBy: [2], needs: []},
+  f2: {units: [12{b1, b3, b5, b4, b2}, 8{b1, b3, b4}, 11{b1, b2, b5}, 7{b1, b2, b4}, 5{b1, b2, b3}, 30{b4, b5}, 27{b3, b5}, 26{b3, b4}, 21{b2, b5}, 19{b2, b4}, 18{b2, b3}, 10{b1, b5}, 31{b5}, 6{b1, b4}, 29{b4}, 4{b1, b3}, 25{b3}, 3{b1, b2}, 2{b1}, 17{b2}], usedBy: [], needs: [1]}],
+ steps=[
+  b1=(f1, f2),
+  b2=(f1, f2),
+  b3=(f1, f2),
+  b4=(f1, f2),
+  b5=(f1, f2)]
+*/
+
 import 'lib1.dart';
 import 'lib2.dart';
 import 'lib3.dart';
diff --git a/pkg/compiler/test/deferred_loading/data/marker.options b/pkg/compiler/test/deferred_loading/data/marker.options
index 1415216..95010cc 100644
--- a/pkg/compiler/test/deferred_loading/data/marker.options
+++ b/pkg/compiler/test/deferred_loading/data/marker.options
@@ -1 +1,3 @@
 spec=pkg/compiler/test/deferred_loading/deferred_loading_test.dart
+two-frag=pkg/compiler/test/deferred_loading/deferred_loading_test.dart
+three-frag=pkg/compiler/test/deferred_loading/deferred_loading_test.dart
diff --git a/pkg/compiler/test/deferred_loading/data/regress_35311/main.dart b/pkg/compiler/test/deferred_loading/data/regress_35311/main.dart
index d10d45f..7c1acac 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_35311/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_35311/main.dart
@@ -4,6 +4,10 @@
 
 // @dart = 2.7
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
 import 'lib.dart' deferred as lib;
 
 /*member: main:member_unit=main{}*/
diff --git a/pkg/compiler/test/deferred_loading/data/regress_43055/main.dart b/pkg/compiler/test/deferred_loading/data/regress_43055/main.dart
index dfbc3c4..486907a 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_43055/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_43055/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{libb}], usedBy: [], needs: []}],
+ steps=[libb=(f1)]
+*/
+
 // @dart = 2.7
 import 'libb.dart' deferred as libb;
 import 'libc.dart';
diff --git a/pkg/compiler/test/deferred_loading/data/shared_constant/main.dart b/pkg/compiler/test/deferred_loading/data/shared_constant/main.dart
index 8337bc0..dea65bc 100644
--- a/pkg/compiler/test/deferred_loading/data/shared_constant/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/shared_constant/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{s1, s2}], usedBy: [], needs: []}],
+ steps=[
+  s1=(f1),
+  s2=(f1)]
+*/
+
 // @dart = 2.7
 
 /// Regression test for issue https://github.com/dart-lang/sdk/issues/31306.
diff --git a/pkg/compiler/test/deferred_loading/data/static_separate/main.dart b/pkg/compiler/test/deferred_loading/data/static_separate/main.dart
index 78918bf..78990e9 100644
--- a/pkg/compiler/test/deferred_loading/data/static_separate/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/static_separate/main.dart
@@ -2,6 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec|three-frag.library: 
+ output_units=[
+  f1: {units: [2{lib1, lib2}], usedBy: [2, 3], needs: []},
+  f2: {units: [1{lib1}], usedBy: [], needs: [1]},
+  f3: {units: [3{lib2}], usedBy: [], needs: [1]}],
+ steps=[
+  lib1=(f1, f2),
+  lib2=(f1, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [2{lib1, lib2}, 1{lib1}], usedBy: [2], needs: []},
+  f2: {units: [3{lib2}], usedBy: [], needs: [1]}],
+ steps=[
+  lib1=(f1),
+  lib2=(f1, f2)]
+*/
+
 // @dart = 2.7
 
 // The class lib1.C is referenced via lib1
diff --git a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/main.dart b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/main.dart
index c279b65..6049f85 100644
--- a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{c}], usedBy: [], needs: []}],
+ steps=[c=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib1.dart';
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
index dd5873b..4cad65c 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
@@ -2,6 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+/*spec|three-frag.library: 
+ output_units=[
+  f1: {units: [3{lib1, lib3}], usedBy: [2, 3], needs: []},
+  f2: {units: [1{lib1}], usedBy: [], needs: [1]},
+  f3: {units: [2{lib3}], usedBy: [], needs: [1]}],
+ steps=[
+  lib1=(f1, f2),
+  lib3=(f1, f3)]
+*/
+
+/*two-frag.library: 
+ output_units=[
+  f1: {units: [3{lib1, lib3}, 2{lib3}], usedBy: [2], needs: []},
+  f2: {units: [1{lib1}], usedBy: [], needs: [1]}],
+ steps=[
+  lib1=(f1, f2),
+  lib3=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib1.dart' deferred as lib1;
diff --git a/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/main.dart b/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/main.dart
index 8b8ad89..3ee33186 100644
--- a/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/main.dart
@@ -2,6 +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.
 
+/*library: 
+ output_units=[f1: {units: [1{lib}], usedBy: [], needs: []}],
+ steps=[lib=(f1)]
+*/
+
 // @dart = 2.7
 
 import 'lib.dart' deferred as lib;
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
index 43f6ffa..e261408 100644
--- a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
@@ -15,6 +15,9 @@
 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/model.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';
@@ -37,7 +40,9 @@
     await checkTests(dataDir, const OutputUnitDataComputer(),
         options: compilerOptions, args: args, setUpFunction: () {
       importPrefixes.clear();
-    }, testedConfigs: allSpecConfigs);
+    },
+        testedConfigs: allSpecConfigs +
+            [twoDeferredFragmentConfig, threeDeferredFragmentConfig]);
   });
 }
 
@@ -47,10 +52,7 @@
 // prefix name responds to two different libraries.
 Map<String, Uri> importPrefixes = {};
 
-/// Create a consistent string representation of [OutputUnit]s for both
-/// KImportEntities and ImportElements.
-String outputUnitString(OutputUnit unit) {
-  if (unit == null) return 'none';
+String importPrefixString(OutputUnit unit) {
   StringBuffer sb = StringBuffer();
   bool first = true;
   for (ImportEntity import in unit.importsForTesting) {
@@ -73,15 +75,48 @@
     }
     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<Fragment>> loadMap,
+    List<PreFragment> preDeferredFragments) {
+  Map<DeferredFragment, PreFragment> fragmentMap = {};
+  for (var preFragment in preDeferredFragments) {
+    for (var fragment in preFragment.fragments) {
+      assert(!fragmentMap.containsKey(fragment));
+      fragmentMap[fragment] = preFragment;
+    }
+  }
+
+  Map<String, List<PreFragment>> preFragmentMap = {};
+  loadMap.forEach((loadId, fragments) {
+    Set<PreFragment> preFragments = {};
+    for (var fragment in fragments) {
+      preFragments.add(fragmentMap[fragment]);
+    }
+    assert(!preFragmentMap.containsKey(loadId));
+    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';
+  static const String steps = 'steps';
+  static const String outputUnits = 'output_units';
 }
 
 class OutputUnitDataComputer extends DataComputer<Features> {
@@ -118,10 +153,82 @@
   }
 
   @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;
+    Program program =
+        compiler.backendStrategy.emitterTask.emitter.programForTesting;
+    Map<String, List<PreFragment>> preFragmentMap =
+        buildPreFragmentMap(program.loadMap, preDeferredFragments);
+    PreFragmentsIrComputer(compiler.reporter, actualMap, preFragmentMap)
+        .computeForLibrary(node);
+  }
+
+  @override
   DataInterpreter<Features> get dataValidator =>
       const FeaturesDataInterpreter();
 }
 
+class PreFragmentsIrComputer extends IrDataExtractor<Features> {
+  final Map<String, List<PreFragment>> _preFragmentMap;
+
+  PreFragmentsIrComputer(DiagnosticReporter reporter,
+      Map<Id, ActualData<Features>> actualMap, this._preFragmentMap)
+      : 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;
+
+    int index = 1;
+    Map<PreFragment, int> preFragmentIndices = {};
+    Map<int, PreFragment> reversePreFragmentIndices = {};
+    _preFragmentMap.forEach((loadId, preFragments) {
+      List<String> preFragmentNeeds = [];
+      for (var preFragment in preFragments) {
+        if (!preFragmentIndices.containsKey(preFragment)) {
+          preFragmentIndices[preFragment] = index;
+          reversePreFragmentIndices[index++] = preFragment;
+        }
+        preFragmentNeeds.add('f${preFragmentIndices[preFragment]}');
+      }
+      features.addElement(
+          Tags.steps, '$loadId=(${preFragmentNeeds.join(', ')})');
+    });
+
+    for (int i = 1; i < index; i++) {
+      var preFragment = reversePreFragmentIndices[i];
+      List<int> needs = [];
+      List<OutputUnit> supplied = [];
+      List<int> usedBy = [];
+      for (var dependent in preFragment.successors) {
+        assert(preFragmentIndices.containsKey(dependent));
+        usedBy.add(preFragmentIndices[dependent]);
+      }
+
+      for (var dependency in preFragment.predecessors) {
+        assert(preFragmentIndices.containsKey(dependency));
+        needs.add(preFragmentIndices[dependency]);
+      }
+
+      for (var fragment in preFragment.fragments) {
+        supplied.add(fragment.outputUnit);
+      }
+      var suppliedString = '[${supplied.map(outputUnitString).join(', ')}]';
+      features.addElement(Tags.outputUnits,
+          'f$i: {units: $suppliedString, usedBy: $usedBy, needs: $needs}');
+    }
+
+    return features;
+  }
+}
+
 class OutputUnitIrComputer extends IrDataExtractor<Features> {
   final JsToElementMap _elementMap;
   final OutputUnitData _data;
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 63d8596..0058660 100644
--- a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
+++ b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
@@ -48,9 +48,15 @@
   }
 
   @override
-  void reportInfo(Spannable node, MessageKind errorCode,
+  void reportInfo(DiagnosticMessage message,
+      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
+    reporter.reportInfo(message, infos);
+  }
+
+  @override
+  void reportInfoMessage(Spannable node, MessageKind errorCode,
       [Map<String, String> arguments = const {}]) {
-    reporter.reportInfo(node, errorCode, arguments);
+    reporter.reportInfoMessage(node, errorCode, arguments);
   }
 
   @override
diff --git a/pkg/compiler/test/equivalence/id_equivalence_helper.dart b/pkg/compiler/test/equivalence/id_equivalence_helper.dart
index 0a9c8d6..1e22b7c 100644
--- a/pkg/compiler/test/equivalence/id_equivalence_helper.dart
+++ b/pkg/compiler/test/equivalence/id_equivalence_helper.dart
@@ -29,12 +29,24 @@
 
 const String specMarker = 'spec';
 const String prodMarker = 'prod';
+const String twoDeferredFragmentMarker = 'two-frag';
+const String threeDeferredFragmentMarker = 'three-frag';
 
 const TestConfig specConfig = TestConfig(specMarker, 'compliance mode', []);
 
 const TestConfig prodConfig = TestConfig(prodMarker, 'production mode',
     [Flags.omitImplicitChecks, Flags.laxRuntimeTypeToString]);
 
+const TestConfig twoDeferredFragmentConfig = TestConfig(
+    twoDeferredFragmentMarker,
+    'two deferred fragment mode',
+    ['${Flags.mergeFragmentsThreshold}=2']);
+
+const TestConfig threeDeferredFragmentConfig = TestConfig(
+    threeDeferredFragmentMarker,
+    'three deferred fragment mode',
+    ['${Flags.mergeFragmentsThreshold}=3']);
+
 /// Default internal configurations not including experimental features.
 const List<TestConfig> defaultInternalConfigs = [specConfig, prodConfig];
 
diff --git a/pkg/compiler/test/helpers/shared_helper.dart b/pkg/compiler/test/helpers/shared_helper.dart
index 65ca216..4557ea7 100644
--- a/pkg/compiler/test/helpers/shared_helper.dart
+++ b/pkg/compiler/test/helpers/shared_helper.dart
@@ -232,37 +232,34 @@
     sb.write(')');
   }
 
+  void _unsupported(ConstantValue constant) => throw UnsupportedError(
+      'Unsupported constant value: ${constant.toStructuredText(_dartTypes)}');
+
   @override
-  void visitInterceptor(InterceptorConstantValue constant, StringBuffer sb) {
-    throw new UnsupportedError(
-        'Unsupported constant value: ${constant.toStructuredText(_dartTypes)}');
-  }
+  void visitInterceptor(InterceptorConstantValue constant, StringBuffer sb) =>
+      _unsupported(constant);
 
   @override
   void visitDummyInterceptor(
-      DummyInterceptorConstantValue constant, StringBuffer sb) {
-    throw new UnsupportedError(
-        'Unsupported constant value: ${constant.toStructuredText(_dartTypes)}');
-  }
+          DummyInterceptorConstantValue constant, StringBuffer sb) =>
+      _unsupported(constant);
 
   @override
-  void visitUnreachable(UnreachableConstantValue constant, StringBuffer sb) {
-    throw new UnsupportedError(
-        'Unsupported constant value: ${constant.toStructuredText(_dartTypes)}');
-  }
+  void visitLateSentinel(LateSentinelConstantValue constant, StringBuffer sb) =>
+      _unsupported(constant);
 
   @override
-  void visitJsName(JsNameConstantValue constant, StringBuffer sb) {
-    throw new UnsupportedError(
-        'Unsupported constant value: ${constant.toStructuredText(_dartTypes)}');
-  }
+  void visitUnreachable(UnreachableConstantValue constant, StringBuffer sb) =>
+      _unsupported(constant);
+
+  @override
+  void visitJsName(JsNameConstantValue constant, StringBuffer sb) =>
+      _unsupported(constant);
 
   @override
   void visitDeferredGlobal(
-      DeferredGlobalConstantValue constant, StringBuffer sb) {
-    throw new UnsupportedError(
-        'Unsupported constant value: ${constant.toStructuredText(_dartTypes)}');
-  }
+          DeferredGlobalConstantValue constant, StringBuffer sb) =>
+      _unsupported(constant);
 
   @override
   void visitNonConstant(NonConstantValue constant, StringBuffer sb) {
diff --git a/pkg/compiler/test/inference/data/general.dart b/pkg/compiler/test/inference/data/general.dart
index 209f884..275cd19 100644
--- a/pkg/compiler/test/inference/data/general.dart
+++ b/pkg/compiler/test/inference/data/general.dart
@@ -809,8 +809,9 @@
   return new CascadeHelper()
     .. /*update: [exact=CascadeHelper]*/ a = "hello"
     .. /*update: [exact=CascadeHelper]*/ b = 42
-    .. /*[exact=CascadeHelper]*/ /*update: [exact=CascadeHelper]*/ i
-        /*invoke: [subclass=JSPositiveInt]*/ += 1;
+    .. /*[exact=CascadeHelper]*/ i
+        /*invoke: [subclass=JSPositiveInt]*/ /*update: [exact=CascadeHelper]*/ +=
+        1;
 }
 
 /*member: CascadeHelper.:[exact=CascadeHelper]*/
diff --git a/pkg/compiler/test/js/js_size_estimator_test.dart b/pkg/compiler/test/js/js_size_estimator_test.dart
index cb5ce76..e9fbfcf 100644
--- a/pkg/compiler/test/js/js_size_estimator_test.dart
+++ b/pkg/compiler/test/js/js_size_estimator_test.dart
@@ -24,7 +24,7 @@
 
   // Always verify the actual results from the [SizeEstimator].
   // This is the actual test, though DebugSizeEstimator is pretty trivial.
-  int actualEstimate = EstimateSize(node);
+  int actualEstimate = estimateSize(node);
   Expect.equals(actualEstimate, debugSizeEstimator.charCount);
   return debugSizeEstimator;
 }
diff --git a/pkg/compiler/test/model/supermixin_test.dart b/pkg/compiler/test/model/supermixin_test.dart
index f1fed6e..e347d70 100644
--- a/pkg/compiler/test/model/supermixin_test.dart
+++ b/pkg/compiler/test/model/supermixin_test.dart
@@ -53,7 +53,7 @@
     ClassEntity superB = lookupClass(elementEnvironment, 'SuperB');
     ClassEntity superClass = elementEnvironment.getSuperClass(cls);
 
-    Expect.isTrue(elementEnvironment.isSuperMixinApplication(superClass));
+    Expect.isTrue(elementEnvironment.isMixinApplicationWithMembers(superClass));
     Expect.equals(mixin, elementEnvironment.getEffectiveMixinClass(superClass));
     Expect.equals(superA, elementEnvironment.getSuperClass(mixin));
     Expect.equals(superB, elementEnvironment.getSuperClass(superClass));
diff --git a/pkg/compiler/test/serialization/serialization_test_helper.dart b/pkg/compiler/test/serialization/serialization_test_helper.dart
index a3d44ea..b429960 100644
--- a/pkg/compiler/test/serialization/serialization_test_helper.dart
+++ b/pkg/compiler/test/serialization/serialization_test_helper.dart
@@ -6,6 +6,7 @@
 
 import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/inferrer/types.dart';
 import 'package:compiler/src/serialization/strategies.dart';
 import 'package:expect/expect.dart';
@@ -20,55 +21,33 @@
   '"toJsonDuration":'
 ];
 
-runTest(
-    {Uri entryPoint,
-    Map<String, String> memorySourceFiles: const <String, String>{},
-    Uri packageConfig,
-    Uri librariesSpecificationUri,
-    List<String> options,
-    SerializationStrategy strategy: const BytesInMemorySerializationStrategy(),
-    bool useDataKinds: false}) async {
-  OutputCollector collector1 = new OutputCollector();
-  CompilationResult result1 = await runCompiler(
-      entryPoint: entryPoint,
-      memorySourceFiles: memorySourceFiles,
-      packageConfig: packageConfig,
-      librariesSpecificationUri: librariesSpecificationUri,
-      options: options,
-      outputProvider: collector1,
-      beforeRun: (Compiler compiler) {
-        compiler.kernelLoader.forceSerialization = true;
-      });
-  Expect.isTrue(result1.isSuccess);
+void finishCompileAndCompare(
+    Map<OutputType, Map<String, String>> expectedOutput,
+    OutputCollector actualOutputCollector,
+    Compiler compiler,
+    SerializationStrategy strategy,
+    {bool stoppedAfterClosedWorld = false,
+    bool stoppedAfterTypeInference = false}) {
+  if (stoppedAfterClosedWorld) {
+    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+    JsClosedWorld newClosedWorld =
+        cloneClosedWorld(compiler, closedWorld, strategy);
+    compiler.performGlobalTypeInference(newClosedWorld);
+  }
 
-  OutputCollector collector2 = new OutputCollector();
-  CompilationResult result = await runCompiler(
-      entryPoint: entryPoint,
-      memorySourceFiles: memorySourceFiles,
-      packageConfig: packageConfig,
-      librariesSpecificationUri: librariesSpecificationUri,
-      options: options,
-      outputProvider: collector2,
-      beforeRun: (Compiler compiler) {
-        compiler.kernelLoader.forceSerialization = true;
-        compiler.stopAfterTypeInference = true;
-      });
-  Expect.isTrue(result.isSuccess);
-  Compiler compiler = result.compiler;
-  GlobalTypeInferenceResults globalInferenceResults =
-      compiler.globalInference.resultsForTesting;
-  GlobalTypeInferenceResults newGlobalInferenceResults =
-      cloneInferenceResults(compiler, globalInferenceResults, strategy);
+  if (stoppedAfterClosedWorld || stoppedAfterTypeInference) {
+    GlobalTypeInferenceResults globalInferenceResults =
+        compiler.globalInference.resultsForTesting;
+    GlobalTypeInferenceResults newGlobalInferenceResults =
+        cloneInferenceResults(compiler, globalInferenceResults, strategy);
+    compiler.generateJavaScriptCode(newGlobalInferenceResults);
+  }
+  var actualOutput = actualOutputCollector.clear();
+  Expect.setEquals(
+      expectedOutput.keys, actualOutput.keys, "Output type mismatch.");
 
-  Map<OutputType, Map<String, String>> output = collector1.clear();
-
-  compiler.generateJavaScriptCode(newGlobalInferenceResults);
-  Map<OutputType, Map<String, String>> newOutput = collector2.clear();
-
-  Expect.setEquals(output.keys, newOutput.keys, "Output type mismatch.");
-
-  output.forEach((OutputType outputType, Map<String, String> fileMap) {
-    Map<String, String> newFileMap = newOutput[outputType];
+  void check(OutputType outputType, Map<String, String> fileMap) {
+    Map<String, String> newFileMap = actualOutput[outputType];
     Expect.setEquals(fileMap.keys, newFileMap.keys,
         "File mismatch for output type $outputType.");
     fileMap.forEach((String fileName, String code) {
@@ -96,14 +75,117 @@
           "Output mismatch at line $failureLine in "
           "file '${fileName}' of type ${outputType}.");
     });
-  });
+  }
+
+  expectedOutput.forEach(check);
+}
+
+runTest(
+    {Uri entryPoint,
+    Map<String, String> memorySourceFiles: const <String, String>{},
+    Uri packageConfig,
+    Uri librariesSpecificationUri,
+    List<String> options,
+    SerializationStrategy strategy: const BytesInMemorySerializationStrategy(),
+    bool useDataKinds: false}) async {
+  OutputCollector collector = new OutputCollector();
+  CompilationResult result = await runCompiler(
+      entryPoint: entryPoint,
+      memorySourceFiles: memorySourceFiles,
+      packageConfig: packageConfig,
+      librariesSpecificationUri: librariesSpecificationUri,
+      options: options,
+      outputProvider: collector,
+      beforeRun: (Compiler compiler) {
+        compiler.kernelLoader.forceSerialization = true;
+      });
+  Expect.isTrue(result.isSuccess);
+  Map<OutputType, Map<String, String>> expectedOutput = collector.clear();
+
+  OutputCollector collector2 = new OutputCollector();
+  CompilationResult result2 = await runCompiler(
+      entryPoint: entryPoint,
+      memorySourceFiles: memorySourceFiles,
+      packageConfig: packageConfig,
+      librariesSpecificationUri: librariesSpecificationUri,
+      options: options,
+      outputProvider: collector2,
+      beforeRun: (Compiler compiler) {
+        compiler.kernelLoader.forceSerialization = true;
+        compiler.stopAfterClosedWorld = true;
+      });
+  Expect.isTrue(result2.isSuccess);
+
+  OutputCollector collector3 = new OutputCollector();
+  CompilationResult result3 = await runCompiler(
+      entryPoint: entryPoint,
+      memorySourceFiles: memorySourceFiles,
+      packageConfig: packageConfig,
+      librariesSpecificationUri: librariesSpecificationUri,
+      options: options,
+      outputProvider: collector3,
+      beforeRun: (Compiler compiler) {
+        compiler.kernelLoader.forceSerialization = true;
+        compiler.stopAfterTypeInference = true;
+      });
+  Expect.isTrue(result3.isSuccess);
+
+  finishCompileAndCompare(
+      expectedOutput, collector2, result2.compiler, strategy,
+      stoppedAfterClosedWorld: true);
+  finishCompileAndCompare(
+      expectedOutput, collector3, result3.compiler, strategy,
+      stoppedAfterTypeInference: true);
+}
+
+void checkData(List<int> data, List<int> newData) {
+  Expect.equals(
+      data.length, newData.length, "Reserialization data length mismatch.");
+  for (int i = 0; i < data.length; i++) {
+    if (data[i] != newData[i]) {
+      print('Reserialization data mismatch at offset $i:');
+      for (int j = i - 50; j < i + 50; j++) {
+        if (0 <= j && j <= data.length) {
+          String text;
+          if (data[j] == newData[j]) {
+            text = '${data[j]}';
+          } else {
+            text = '${data[j]} <> ${newData[j]}';
+          }
+          print('${j == i ? '> ' : '  '}$j: $text');
+        }
+      }
+      break;
+    }
+  }
+  Expect.listEquals(data, newData);
+}
+
+JsClosedWorld cloneClosedWorld(Compiler compiler, JsClosedWorld closedWorld,
+    SerializationStrategy strategy) {
+  ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
+  List<int> irData = strategy.serializeComponent(component);
+  List<int> closedWorldData = strategy.serializeClosedWorld(closedWorld);
+  print('data size: ${closedWorldData.length}');
+
+  ir.Component newComponent = strategy.deserializeComponent(irData);
+  JsClosedWorld newClosedWorld = strategy.deserializeClosedWorld(
+      compiler.options,
+      compiler.reporter,
+      compiler.environment,
+      compiler.abstractValueStrategy,
+      newComponent,
+      closedWorldData);
+  List<int> newClosedWorldData = strategy.serializeClosedWorld(newClosedWorld);
+  checkData(closedWorldData, newClosedWorldData);
+  return newClosedWorld;
 }
 
 GlobalTypeInferenceResults cloneInferenceResults(Compiler compiler,
     GlobalTypeInferenceResults results, SerializationStrategy strategy) {
   List<int> irData = strategy.unpackAndSerializeComponent(results);
 
-  List worldData = strategy.serializeGlobalTypeInferenceResults(results);
+  List<int> worldData = strategy.serializeGlobalTypeInferenceResults(results);
   print('data size: ${worldData.length}');
 
   ir.Component newComponent = strategy.deserializeComponent(irData);
@@ -115,27 +197,8 @@
           compiler.abstractValueStrategy,
           newComponent,
           worldData);
-  List newWorldData = strategy.serializeGlobalTypeInferenceResults(newResults);
-  Expect.equals(worldData.length, newWorldData.length,
-      "Reserialization data length mismatch.");
-  for (int i = 0; i < worldData.length; i++) {
-    if (worldData[i] != newWorldData[i]) {
-      print('Reserialization data mismatch at offset $i:');
-      for (int j = i - 50; j < i + 50; j++) {
-        if (0 <= j && j <= worldData.length) {
-          String text;
-          if (worldData[j] == newWorldData[j]) {
-            text = '${worldData[j]}';
-          } else {
-            text = '${worldData[j]} <> ${newWorldData[j]}';
-          }
-          print('${j == i ? '> ' : '  '}$j: $text');
-        }
-      }
-      break;
-    }
-  }
-  Expect.listEquals(worldData, newWorldData);
-
+  List<int> newWorldData =
+      strategy.serializeGlobalTypeInferenceResults(newResults);
+  checkData(worldData, newWorldData);
   return newResults;
 }
diff --git a/pkg/compiler/test/sourcemaps/tools/translate_dart2js_stacktrace.dart b/pkg/compiler/test/sourcemaps/tools/translate_dart2js_stacktrace.dart
index c54f9a3..0451c24 100644
--- a/pkg/compiler/test/sourcemaps/tools/translate_dart2js_stacktrace.dart
+++ b/pkg/compiler/test/sourcemaps/tools/translate_dart2js_stacktrace.dart
@@ -29,7 +29,7 @@
   String url = options.rest[0];
   String data;
   if (url.startsWith("http://") || url.startsWith("https://")) {
-    data = (await http.get(url)).body;
+    data = (await http.get(Uri.parse(url))).body;
   } else {
     data = new File(url).readAsStringSync();
   }
diff --git a/pkg/dart2native/bin/dart2native.dart b/pkg/dart2native/bin/dart2native.dart
index 6df0953..7f407416 100644
--- a/pkg/dart2native/bin/dart2native.dart
+++ b/pkg/dart2native/bin/dart2native.dart
@@ -7,6 +7,8 @@
 
 import 'package:args/args.dart';
 import 'package:dart2native/generate.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show Verbosity;
 
 void printUsage(final ArgParser parser) {
   print('''
@@ -65,7 +67,16 @@
 Comma separated list of experimental features.
 ''')
     ..addFlag('verbose',
-        abbr: 'v', negatable: false, help: 'Show verbose output.');
+        abbr: 'v', negatable: false, help: 'Show verbose output.')
+    ..addOption(
+      'verbosity',
+      defaultsTo: Verbosity.defaultValue,
+      help: '''
+Sets the verbosity level used for filtering messages during compilation.
+''',
+      allowed: Verbosity.allowedValues,
+      allowedHelp: Verbosity.allowedValuesHelp,
+    );
 
   ArgResults parsedArgs;
   try {
@@ -106,6 +117,7 @@
         enableExperiment: parsedArgs['enable-experiment'],
         enableAsserts: parsedArgs['enable-asserts'],
         verbose: parsedArgs['verbose'],
+        verbosity: parsedArgs['verbosity'],
         extraOptions: parsedArgs['extra-gen-snapshot-options']);
   } catch (e) {
     stderr.writeln('Failed to generate native files:');
diff --git a/pkg/dart2native/lib/dart2native.dart b/pkg/dart2native/lib/dart2native.dart
index 0139b24..a6d1deb 100644
--- a/pkg/dart2native/lib/dart2native.dart
+++ b/pkg/dart2native/lib/dart2native.dart
@@ -37,8 +37,14 @@
   return Process.run('chmod', ['+x', outputFile]);
 }
 
-Future generateAotKernel(String dart, String genKernel, String platformDill,
-    String sourceFile, String kernelFile, String packages, List<String> defines,
+Future<ProcessResult> generateAotKernel(
+    String dart,
+    String genKernel,
+    String platformDill,
+    String sourceFile,
+    String kernelFile,
+    String packages,
+    List<String> defines,
     {String enableExperiment = '',
     List<String> extraGenKernelOptions = const []}) {
   return Process.run(dart, [
diff --git a/pkg/dart2native/lib/generate.dart b/pkg/dart2native/lib/generate.dart
index eb70dcf..6bc3abd 100644
--- a/pkg/dart2native/lib/generate.dart
+++ b/pkg/dart2native/lib/generate.dart
@@ -27,6 +27,7 @@
   String enableExperiment = '',
   bool enableAsserts = false,
   bool verbose = false,
+  String verbosity = 'all',
   List<String> extraOptions = const [],
 }) async {
   final Directory tempDir = Directory.systemTemp.createTempSync();
@@ -57,13 +58,27 @@
     final String kernelFile = path.join(tempDir.path, 'kernel.dill');
     final kernelResult = await generateAotKernel(Platform.executable, genKernel,
         productPlatformDill, sourcePath, kernelFile, packages, defines,
-        enableExperiment: enableExperiment);
+        enableExperiment: enableExperiment,
+        extraGenKernelOptions: [
+          '--invocation-modes=compile',
+          '--verbosity=$verbosity'
+        ]);
     if (kernelResult.exitCode != 0) {
-      stderr.writeln(kernelResult.stdout);
-      stderr.writeln(kernelResult.stderr);
+      // We pipe both stdout and stderr to stderr because the CFE doesn't print
+      // errors to stderr. This unfortunately does emit info-only output in
+      // stderr, though.
+      stderr.write(kernelResult.stdout);
+      stderr.write(kernelResult.stderr);
       await stderr.flush();
       throw 'Generating AOT kernel dill failed!';
     }
+    // Pipe info and warnings from the CFE to stdout since the compilation
+    // succeeded. Stderr should be empty but we pipe it to stderr for
+    // completeness.
+    stdout.write(kernelResult.stdout);
+    await stdout.flush();
+    stderr.write(kernelResult.stderr);
+    await stderr.flush();
 
     if (verbose) {
       print('Generating AOT snapshot.');
diff --git a/pkg/dart2native/pubspec.yaml b/pkg/dart2native/pubspec.yaml
index 85a9eac..4c274e7 100644
--- a/pkg/dart2native/pubspec.yaml
+++ b/pkg/dart2native/pubspec.yaml
@@ -12,5 +12,7 @@
 dependencies:
    args: ^1.4.0
    path: any
+   front_end:
+     path: ../front_end
 
 dev_dependencies:
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 5e8f2a9..b194847 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -20,6 +20,7 @@
 import 'src/commands/compile.dart';
 import 'src/commands/create.dart';
 import 'src/commands/fix.dart';
+import 'src/commands/language_server.dart';
 import 'src/commands/run.dart';
 import 'src/commands/test.dart';
 import 'src/core.dart';
@@ -96,6 +97,7 @@
     addCommand(CompileCommand(verbose: verbose));
     addCommand(FixCommand(verbose: verbose));
     addCommand(FormatCommand(verbose: verbose));
+    addCommand(LanguageServerCommand(verbose: verbose));
     addCommand(MigrateCommand(verbose: verbose));
     addCommand(pubCommand());
     addCommand(RunCommand(verbose: verbose));
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index e5cfacd..9b8340f 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -125,9 +125,11 @@
         .then((response) => response['version']);
   }
 
-  Future<EditBulkFixesResult> requestBulkFixes(String filePath) {
+  Future<EditBulkFixesResult> requestBulkFixes(
+      String filePath, bool inTestMode) {
     return _sendCommand('edit.bulkFixes', params: <String, dynamic>{
       'included': [path.canonicalize(filePath)],
+      'inTestMode': inTestMode
     }).then((result) {
       return EditBulkFixesResult.fromJson(
           ResponseDecoder(null), 'result', result);
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 6edd82b..021db07 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -7,6 +7,8 @@
 
 import 'package:dart2native/generate.dart';
 import 'package:path/path.dart' as path;
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show Verbosity;
 
 import '../core.dart';
 import '../experiments.dart';
@@ -19,8 +21,17 @@
   final String flag;
   final String help;
   final String abbr;
+  final String defaultsTo;
+  final List<String> allowed;
+  final Map<String, String> allowedHelp;
 
-  Option({this.flag, this.help, this.abbr});
+  Option(
+      {this.flag,
+      this.help,
+      this.abbr,
+      this.defaultsTo,
+      this.allowed,
+      this.allowedHelp});
 }
 
 final Map<String, Option> commonOptions = {
@@ -32,6 +43,15 @@
 This can be an absolute or relative path.
 ''',
   ),
+  'verbosity': Option(
+    flag: 'verbosity',
+    help: '''
+Sets the verbosity level of the compilation.
+''',
+    defaultsTo: Verbosity.defaultValue,
+    allowed: Verbosity.allowedValues,
+    allowedHelp: Verbosity.allowedValuesHelp,
+  ),
 };
 
 bool checkFile(String sourcePath) {
@@ -53,6 +73,15 @@
         commonOptions['outputFile'].flag,
         help: commonOptions['outputFile'].help,
         abbr: commonOptions['outputFile'].abbr,
+        defaultsTo: commonOptions['outputFile'].defaultsTo,
+      )
+      ..addOption(
+        commonOptions['verbosity'].flag,
+        help: commonOptions['verbosity'].help,
+        abbr: commonOptions['verbosity'].abbr,
+        defaultsTo: commonOptions['verbosity'].defaultsTo,
+        allowed: commonOptions['verbosity'].allowed,
+        allowedHelp: commonOptions['verbosity'].allowedHelp,
       )
       ..addFlag(
         'minified',
@@ -98,6 +127,7 @@
           '--libraries-spec=$librariesPath',
           if (argResults.enabledExperiments.isNotEmpty)
             "--enable-experiment=${argResults.enabledExperiments.join(',')}",
+          '--cfe-invocation-modes=compile',
           ...argResults.arguments,
         ],
         packageConfigOverride: null);
@@ -127,7 +157,16 @@
         commonOptions['outputFile'].flag,
         help: commonOptions['outputFile'].help,
         abbr: commonOptions['outputFile'].abbr,
+      )
+      ..addOption(
+        commonOptions['verbosity'].flag,
+        help: commonOptions['verbosity'].help,
+        abbr: commonOptions['verbosity'].abbr,
+        defaultsTo: commonOptions['verbosity'].defaultsTo,
+        allowed: commonOptions['verbosity'].allowed,
+        allowedHelp: commonOptions['verbosity'].allowedHelp,
       );
+
     addExperimentalFlags(argParser, verbose);
   }
 
@@ -159,6 +198,10 @@
     List<String> args = [];
     args.add('--snapshot-kind=$formatName');
     args.add('--snapshot=${path.canonicalize(outputFile)}');
+
+    String verbosity = argResults[commonOptions['verbosity'].flag];
+    args.add('--verbosity=$verbosity');
+
     if (enabledExperiments.isNotEmpty) {
       args.add("--enable-experiment=${enabledExperiments.join(',')}");
     }
@@ -195,6 +238,14 @@
         help: commonOptions['outputFile'].help,
         abbr: commonOptions['outputFile'].abbr,
       )
+      ..addOption(
+        commonOptions['verbosity'].flag,
+        help: commonOptions['verbosity'].help,
+        abbr: commonOptions['verbosity'].abbr,
+        defaultsTo: commonOptions['verbosity'].defaultsTo,
+        allowed: commonOptions['verbosity'].allowed,
+        allowedHelp: commonOptions['verbosity'].allowedHelp,
+      )
       ..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
 Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
 For example: dart compile $commandName -Da=1,b=2 main.dart''')
@@ -245,6 +296,7 @@
         enableExperiment: argResults.enabledExperiments.join(','),
         debugFile: argResults['save-debugging-info'],
         verbose: verbose,
+        verbosity: argResults['verbosity'],
       );
       return 0;
     } catch (e) {
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index f6fa451..a9feca7 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -19,26 +19,14 @@
 
   static final NumberFormat _numberFormat = NumberFormat.decimalPattern();
 
-  static const String cmdDescription = '''Fix Dart source code.
+  static const String cmdDescription =
+      '''Apply automated fixes to Dart source code.
 
-This tool looks for and fixes analysis issues that have associated automated fixes or issues that have associated package API migration information. See dart.dev/go/dart-fix for more information about how automated package API changes work.
+This tool looks for and fixes analysis issues that have associated automated fixes.
 
 To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed changes for a project, or ['dart fix --apply'] to apply the changes.''';
 
-  @override
-  String get description {
-    if (log != null && log.ansi.useAnsi) {
-      return cmdDescription
-          .replaceAll('[', log.ansi.bold)
-          .replaceAll(']', log.ansi.none);
-    } else {
-      return cmdDescription.replaceAll('[', '').replaceAll(']', '');
-    }
-  }
-
-  // This command is hidden as it's currently experimental.
-  FixCommand({bool verbose = false})
-      : super(cmdName, cmdDescription, hidden: true) {
+  FixCommand({bool verbose = false}) : super(cmdName, cmdDescription) {
     argParser.addFlag('dry-run',
         abbr: 'n',
         defaultsTo: false,
@@ -61,33 +49,43 @@
   }
 
   @override
-  FutureOr<int> run() async {
-    log.stdout('\n${log.ansi.emphasized('Note:')} The `fix` command is '
-        'provisional and subject to change or removal in future releases.\n');
+  String get description {
+    if (log != null && log.ansi.useAnsi) {
+      return cmdDescription
+          .replaceAll('[', log.ansi.bold)
+          .replaceAll(']', log.ansi.none);
+    } else {
+      return cmdDescription.replaceAll('[', '').replaceAll(']', '');
+    }
+  }
 
+  @override
+  FutureOr<int> run() async {
     var dryRun = argResults['dry-run'];
-    var testMode = argResults['compare-to-golden'];
+    var inTestMode = argResults['compare-to-golden'];
     var apply = argResults['apply'];
+    if (!apply && !dryRun && !inTestMode) {
+      printUsage();
+      return 0;
+    }
+
     var arguments = argResults.rest;
     var argumentCount = arguments.length;
     if (argumentCount > 1) {
       usageException('Only one file or directory is expected.');
     }
 
-    if (!apply && !dryRun && !testMode) {
-      printUsage();
-      return 0;
-    }
-
     var dir =
         argumentCount == 0 ? io.Directory.current : io.Directory(arguments[0]);
     if (!dir.existsSync()) {
       usageException("Directory doesn't exist: ${dir.path}");
     }
+    dir = io.Directory(path.canonicalize(path.normalize(dir.absolute.path)));
+    var dirPath = dir.path;
 
     var modeText = dryRun ? ' (dry run)' : '';
 
-    final projectName = path.basename(path.canonicalize(dir.path));
+    final projectName = path.basename(dirPath);
     var progress = log.progress(
         'Computing fixes in ${log.ansi.emphasized(projectName)}$modeText');
 
@@ -107,24 +105,24 @@
       }
     });
 
-    fixes = await server.requestBulkFixes(dir.absolute.path);
+    fixes = await server.requestBulkFixes(dirPath, inTestMode);
     final List<SourceFileEdit> edits = fixes.edits;
 
     await server.shutdown();
 
     progress.finish(showTiming: true);
 
-    if (testMode) {
-      if (_compareFixes(edits)) {
-        return 1;
-      }
+    if (inTestMode) {
+      var result = _compareFixesInDirectory(dir, edits);
+      log.stdout('Passed: ${result.passCount}, Failed: ${result.failCount}');
+      return result.failCount > 0 ? 1 : 0;
     } else if (edits.isEmpty) {
       log.stdout('Nothing to fix!');
     } else {
       var details = fixes.details;
       details.sort((f1, f2) => path
-          .relative(f1.path, from: dir.path)
-          .compareTo(path.relative(f2.path, from: dir.path)));
+          .relative(f1.path, from: dirPath)
+          .compareTo(path.relative(f2.path, from: dirPath)));
 
       var fileCount = 0;
       var fixCount = 0;
@@ -166,32 +164,83 @@
 
   /// Return `true` if any of the fixes fail to create the same content as is
   /// found in the golden file.
-  bool _compareFixes(List<SourceFileEdit> edits) {
-    var passCount = 0;
-    var failCount = 0;
+  _TestResult _compareFixesInDirectory(
+      io.Directory directory, List<SourceFileEdit> edits) {
+    var result = _TestResult();
+    //
+    // Gather the files of interest in this directory and process
+    // subdirectories.
+    //
+    var dartFiles = <io.File>[];
+    var expectFileMap = <String, io.File>{};
+    for (var child in directory.listSync()) {
+      if (child is io.Directory) {
+        var childResult = _compareFixesInDirectory(child, edits);
+        result.passCount += childResult.passCount;
+        result.failCount += childResult.failCount;
+      } else if (child is io.File) {
+        var name = child.name;
+        if (name.endsWith('.dart')) {
+          dartFiles.add(child);
+        } else if (name.endsWith('.expect')) {
+          expectFileMap[child.path] = child;
+        }
+      }
+    }
+    var editMap = <String, SourceFileEdit>{};
     for (var edit in edits) {
-      var filePath = edit.file;
+      editMap[edit.file] = edit;
+    }
+    for (var originalFile in dartFiles) {
+      var filePath = originalFile.path;
       var baseName = path.basename(filePath);
       var expectFileName = baseName + '.expect';
       var expectFilePath = path.join(path.dirname(filePath), expectFileName);
+      var expectFile = expectFileMap.remove(expectFilePath);
+      if (expectFile == null) {
+        result.failCount++;
+        log.stdout(
+            'No corresponding expect file for the Dart file at "$filePath".');
+        continue;
+      }
+      var edit = editMap[filePath];
       try {
-        var originalCode = io.File(filePath).readAsStringSync();
-        var expectedCode = io.File(expectFilePath).readAsStringSync();
-        var actualCode = SourceEdit.applySequence(originalCode, edit.edits);
-        if (actualCode != expectedCode) {
-          failCount++;
+        var originalCode = originalFile.readAsStringSync();
+        var expectedCode = expectFile.readAsStringSync();
+        var actualCode = edit == null
+            ? originalCode
+            : SourceEdit.applySequence(originalCode, edit.edits);
+        // Use a whitespace insensitive comparison.
+        if (_compressWhitespace(actualCode) !=
+            _compressWhitespace(expectedCode)) {
+          result.failCount++;
           _reportFailure(filePath, actualCode, expectedCode);
+          _printEdits(edits);
         } else {
-          passCount++;
+          result.passCount++;
         }
       } on io.FileSystemException {
-        // Ignored for now.
+        result.failCount++;
+        log.stdout('Failed to process "$filePath".');
+        log.stdout(
+            '  Ensure that the file and its expect file are both readable.');
       }
     }
-    log.stdout('Passed: $passCount, Failed: $failCount');
-    return failCount > 0;
+    //
+    // Report any `.expect` files that have no corresponding `.dart` file.
+    //
+    for (var unmatchedExpectPath in expectFileMap.keys) {
+      result.failCount++;
+      log.stdout(
+          'No corresponding Dart file for the expect file at "$unmatchedExpectPath".');
+    }
+    return result;
   }
 
+  /// Compress sequences of whitespace characters into a single space.
+  String _compressWhitespace(String code) =>
+      code.replaceAll(RegExp(r'\s*'), ' ');
+
   String _pluralFix(int count) => count == 1 ? 'fix' : 'fixes';
 
   void _printDetails(List<BulkFix> details, io.Directory workingDir) {
@@ -211,6 +260,16 @@
     }
   }
 
+  void _printEdits(List<SourceFileEdit> edits) {
+    log.stdout('Edits returned from server:');
+    for (var fileEdit in edits) {
+      log.stdout('  ${fileEdit.file}');
+      for (var edit in fileEdit.edits) {
+        log.stdout("    ${edit.offset} - ${edit.end}, '${edit.replacement}'");
+      }
+    }
+  }
+
   /// Report that the [actualCode] produced by applying fixes to the content of
   /// [filePath] did not match the [expectedCode].
   void _reportFailure(String filePath, String actualCode, String expectedCode) {
@@ -224,3 +283,15 @@
 
   static String _format(int value) => _numberFormat.format(value);
 }
+
+/// The result of running tests in a given directory.
+class _TestResult {
+  /// The number of tests that passed.
+  int passCount = 0;
+
+  /// The number of tests that failed.
+  int failCount = 0;
+
+  /// Initialize a newly created result object.
+  _TestResult();
+}
diff --git a/pkg/dartdev/lib/src/commands/language_server.dart b/pkg/dartdev/lib/src/commands/language_server.dart
new file mode 100644
index 0000000..924ae19
--- /dev/null
+++ b/pkg/dartdev/lib/src/commands/language_server.dart
@@ -0,0 +1,53 @@
+// 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' as io;
+
+import 'package:analysis_server/src/server/driver.dart' as server_driver;
+import 'package:args/args.dart';
+
+import '../core.dart';
+import '../utils.dart';
+
+class LanguageServerCommand extends DartdevCommand {
+  static const String commandName = 'language-server';
+
+  static const String commandDescription = '''
+Start Dart's analysis server.
+
+This is a long-running process used to provide language services to IDEs and other tooling clients.
+
+It communicates over stdin and stdout and provides services like code completion, errors and warnings, and refactorings. This command is generally not user-facing but consumed by higher level tools.
+
+For more information about the server's capabilities and configuration, see:
+
+  https://github.com/dart-lang/sdk/tree/master/pkg/analysis_server''';
+
+  LanguageServerCommand({bool verbose = false})
+      : super(commandName, commandDescription, hidden: !verbose);
+
+  @override
+  ArgParser createArgParser() {
+    return server_driver.Driver.createArgParser(
+      usageLineLength: dartdevUsageLineLength,
+      includeHelpFlag: false,
+      defaultToLsp: true,
+    );
+  }
+
+  @override
+  Future<int> run() async {
+    final driver = server_driver.Driver();
+    driver.start(
+      argResults.arguments,
+      defaultToLsp: true,
+    );
+
+    // The server will continue to run past the return from this method.
+    //
+    // On an error on startup, the server will set the dart:io exitCode value
+    // (or, call exit() directly).
+    return io.exitCode;
+  }
+}
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 80ca891..2825b49 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -8,6 +8,8 @@
 import 'dart:io';
 
 import 'package:args/args.dart';
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show Verbosity;
 import 'package:path/path.dart';
 import 'package:pub/pub.dart';
 
@@ -91,6 +93,13 @@
       ..addFlag(
         'enable-asserts',
         help: 'Enable assert statements.',
+      )
+      ..addOption(
+        'verbosity',
+        help: 'Sets the verbosity level of the compilation.',
+        defaultsTo: Verbosity.defaultValue,
+        allowed: Verbosity.allowedValues,
+        allowedHelp: Verbosity.allowedValuesHelp,
       );
 
     if (verbose) {
diff --git a/pkg/dartdev/lib/src/commands/test.dart b/pkg/dartdev/lib/src/commands/test.dart
index b5b7c6a..b010f54 100644
--- a/pkg/dartdev/lib/src/commands/test.dart
+++ b/pkg/dartdev/lib/src/commands/test.dart
@@ -29,18 +29,6 @@
 
   @override
   FutureOr<int> run() async {
-    if (argResults.rest.contains('-h') || argResults.rest.contains('--help')) {
-      printUsage();
-      return 0;
-    }
-    if (!project.hasPubspecFile) {
-      log.stdout('''
-No pubspec.yaml file found; please run this command from the root of your project.
-''');
-
-      printUsage();
-      return 65;
-    }
     try {
       final testExecutable = await getExecutableForCommand('test:test');
       log.trace('dart $testExecutable ${argResults.rest.join(' ')}');
@@ -49,9 +37,19 @@
               join(current, '.dart_tool', 'package_config.json'));
       return 0;
     } on CommandResolutionFailedException catch (e) {
-      print(e.message);
-      print('You need to add a dependency on package:test.');
-      print('Try running `dart pub add test`.');
+      if (project.hasPubspecFile) {
+        print(e.message);
+        print('You need to add a dev_dependency on package:test.');
+        print('Try running `dart pub add --dev test`.');
+      } else {
+        print(
+            'No pubspec.yaml file found - run this command in your project folder.');
+      }
+      if (argResults.rest.contains('-h') ||
+          argResults.rest.contains('--help')) {
+        print('');
+        printUsage();
+      }
       return 65;
     }
   }
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index d6347db..9beb550 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -6,6 +6,8 @@
 environment:
   sdk: '>=2.6.0 <3.0.0'
 dependencies:
+  analysis_server:
+    path: ../analysis_server
   analysis_server_client:
     path: ../analysis_server_client
   analyzer:
@@ -15,6 +17,8 @@
   dart2native:
     path: ../dart2native
   dart_style: any
+  front_end:
+    path: ../front_end
   intl: any
   meta:
     path: ../meta
@@ -22,8 +26,7 @@
     path: ../nnbd_migration
   path: ^1.0.0
   pedantic: ^1.9.0
-  pub:
-    path: ../../third_party/pkg/pub
+  pub: any
   stagehand: any
   telemetry:
     path: ../telemetry
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
index f2f5f31..61ebc76 100644
--- a/pkg/dartdev/test/commands/compile_test.dart
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -15,6 +15,10 @@
   group('compile', defineCompileTests, timeout: longTimeout);
 }
 
+const String soundNullSafetyMessage = 'Info: Compiling with sound null safety';
+const String unsoundNullSafetyMessage =
+    'Info: Compiling without sound null safety';
+
 void defineCompileTests() {
   // *** NOTE ***: These tests *must* be run with the `--use-sdk` option
   // as they depend on a fully built SDK to resolve various snapshot files
@@ -201,4 +205,629 @@
     expect(File(outFile).existsSync(), true,
         reason: 'File not found: $outFile');
   });
+
+  test('Compile exe with error', () {
+    final p = project(mainSrc: '''
+void main() {
+  int? i;
+  i.isEven;
+}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'exe',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, isEmpty);
+    expect(result.stderr, contains('Error: '));
+    // The CFE doesn't print to stderr, so all output is piped to stderr, even
+    // including info-only output:
+    expect(result.stderr, contains(soundNullSafetyMessage));
+    expect(result.exitCode, compileErrorExitCode);
+    expect(File(outFile).existsSync(), false,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile exe with warnings', () {
+    final p = project(mainSrc: '''
+void main() {
+  int i = 0;
+  i?.isEven;
+}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'exe',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains('Warning: '));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile exe with sound null safety', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'exe',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(soundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile exe with unsound null safety', () {
+    final p = project(mainSrc: '''
+// @dart=2.9
+void main() {}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'exe',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(unsoundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile exe without info', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'exe',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile exe without warnings', () {
+    final p = project(mainSrc: '''
+void main() {
+  int i = 0;
+  i?.isEven;
+}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'exe',
+        '--verbosity=error',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile JS with sound null safety', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'js',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(soundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile JS with unsound null safety', () {
+    final p = project(mainSrc: '''
+// @dart=2.9
+void main() {}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'js',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(unsoundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile JS without info', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'js',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile JS without warnings', () {
+    final p = project(mainSrc: '''
+void main() {
+  int i = 0;
+  i?.isEven;
+}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjs'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'js',
+        '--verbosity=error',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile AOT snapshot with sound null safety', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'aot-snapshot',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(soundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile AOT snapshot with unsound null safety', () {
+    final p = project(mainSrc: '''
+// @dart=2.9
+void main() {}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'aot-snapshot',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(unsoundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile AOT snapshot without info', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'aot-snapshot',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile AOT snapshot without warnings', () {
+    final p = project(mainSrc: '''
+void main() {
+  int i = 0;
+  i?.isEven;
+}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'aot-snapshot',
+        '--verbosity=error',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile AOT snapshot with warnings', () {
+    final p = project(mainSrc: '''
+void main() {
+  int i = 0;
+  i?.isEven;
+}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myaot'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'aot-snapshot',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stdout, contains('Warning: '));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile kernel with sound null safety', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'kernel',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(soundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile kernel with unsound null safety', () {
+    final p = project(mainSrc: '''
+// @dart=2.9
+void main() {}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'kernel',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(unsoundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile kernel without info', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'kernel',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile kernel without warning', () {
+    final p = project(mainSrc: '''
+void main() {
+    int i;
+    i?.isEven;
+}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'kernel',
+        '--verbosity=error',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, contains('must be assigned before it can be used'));
+    expect(result.exitCode, 254);
+  });
+
+  test('Compile kernel with warnings', () {
+    final p = project(mainSrc: '''
+void main() {
+    int i = 0;
+    i?.isEven;
+}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'mydill'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'kernel',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, contains('Warning:'));
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile JIT snapshot with sound null safety', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'jit-snapshot',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(soundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile JIT snapshot with unsound null safety', () {
+    final p = project(mainSrc: '''
+// @dart=2.9
+void main() {}
+''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'jit-snapshot',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout, contains(unsoundNullSafetyMessage));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile JIT snapshot without info', () {
+    final p = project(mainSrc: '''void main() {}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'jit-snapshot',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+  });
+
+  test('Compile JIT snapshot without warnings', () {
+    final p = project(mainSrc: '''
+void main() {
+    int i;
+    i?.isEven;
+}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'jit-snapshot',
+        '--verbosity=error',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, contains('must be assigned before it can be used'));
+    expect(result.exitCode, 254);
+  });
+
+  test('Compile JIT snapshot with warnings', () {
+    final p = project(mainSrc: '''
+void main() {
+    int i = 0;
+    i?.isEven;
+}''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myjit'));
+
+    var result = p.runSync(
+      [
+        'compile',
+        'jit-snapshot',
+        '--verbosity=warning',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, contains('Warning:'));
+    expect(result.exitCode, 0);
+  });
 }
diff --git a/pkg/dartdev/test/commands/fix_test.dart b/pkg/dartdev/test/commands/fix_test.dart
index 8a92d7b..69b11c9 100644
--- a/pkg/dartdev/test/commands/fix_test.dart
+++ b/pkg/dartdev/test/commands/fix_test.dart
@@ -20,12 +20,38 @@
 void defineFix() {
   TestProject p;
 
+  ProcessResult result;
+
   final bullet = Logger.standard().ansi.bullet;
 
   setUp(() => p = null);
 
   tearDown(() => p?.dispose());
 
+  void assertResult({int exitCode = 0}) {
+    String message;
+    if (result.exitCode != exitCode) {
+      if (result.stderr.isNotEmpty) {
+        message = 'Error code was ${result.exitCode} and stderr was not empty';
+      } else {
+        message = 'Error code was ${result.exitCode}';
+      }
+    } else if (result.stderr.isNotEmpty) {
+      message = 'stderr was not empty';
+    } else {
+      return;
+    }
+    fail('''
+$message
+
+stdout:
+${result.stdout}
+
+stderr:
+${result.stderr}
+''');
+  }
+
   ProcessResult runFix(List<String> args, {String workingDir}) {
     if (runFromSource) {
       var binary = path.join(Directory.current.path, 'bin', 'dartdev.dart');
@@ -34,6 +60,17 @@
     return p.runSync(['fix', ...args], workingDir: workingDir);
   }
 
+  test('help', () {
+    p = project(mainSrc: 'int get foo => 1;\n');
+
+    var result = runFix([p.dirPath, '--help']);
+
+    expect(result.exitCode, 0);
+    expect(result.stderr, isEmpty);
+    expect(
+        result.stdout, contains('Apply automated fixes to Dart source code.'));
+  });
+
   test('none', () {
     p = project(mainSrc: 'int get foo => 1;\n');
 
@@ -41,7 +78,8 @@
 
     expect(result.exitCode, 0);
     expect(result.stderr, isEmpty);
-    expect(result.stdout, contains('Fix Dart source code.'));
+    expect(
+        result.stdout, contains('Apply automated fixes to Dart source code.'));
   });
 
   test('--apply (none)', () {
@@ -172,7 +210,7 @@
   });
 
   group('compare-to-golden', () {
-    test('different', () {
+    test('applied fixes do not match expected', () {
       p = project(
         mainSrc: '''
 class A {
@@ -199,12 +237,11 @@
   String a() => '';
 }
 ''');
-      var result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
-      expect(result.exitCode, 1);
-      expect(result.stderr, isEmpty);
+      result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+      assertResult(exitCode: 1);
     });
 
-    test('same', () {
+    test('applied fixes match expected', () {
       p = project(
         mainSrc: '''
 class A {
@@ -232,9 +269,66 @@
   String a() => '';
 }
 ''');
-      var result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
-      expect(result.exitCode, 0);
-      expect(result.stderr, isEmpty);
+      result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+      assertResult();
+    });
+
+    test('missing expect', () {
+      p = project(
+        mainSrc: '''
+class A {
+  String a() => "";
+}
+
+class B extends A {
+  String a() => "";
+}
+''',
+        analysisOptions: '''
+linter:
+  rules:
+    - annotate_overrides
+    - prefer_single_quotes
+''',
+      );
+      result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+      assertResult(exitCode: 1);
+    });
+
+    test('missing original', () {
+      p = project(mainSrc: '''
+class C {}
+''');
+      p.file('lib/main.dart.expect', '''
+class C {}
+''');
+      p.file('lib/secondary.dart.expect', '''
+class A {}
+''');
+      result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+      assertResult(exitCode: 1);
+    });
+
+    test('no fixes to apply does not match expected', () {
+      p = project(
+        mainSrc: '''
+class A {
+  String a() => "";
+}
+''',
+        analysisOptions: '''
+linter:
+  rules:
+    - annotate_overrides
+''',
+      );
+      p.file('lib/main.dart.expect', '''
+class A {
+  String a() => '';
+}
+''');
+      result = runFix(['--compare-to-golden', '.'], workingDir: p.dirPath);
+      assertResult(exitCode: 1);
     });
   });
 }
diff --git a/pkg/dartdev/test/commands/help_test.dart b/pkg/dartdev/test/commands/help_test.dart
index afbaf09..09c3c41 100644
--- a/pkg/dartdev/test/commands/help_test.dart
+++ b/pkg/dartdev/test/commands/help_test.dart
@@ -20,6 +20,7 @@
   /// Commands not tested by the following loop.
   List<String> _commandsNotTested = <String>[
     'help', // `dart help help` is redundant
+    'test', // `dart help test` does not call `test:test --help`.
   ];
   DartdevRunner(['--no-analytics'])
       .commands
@@ -36,6 +37,16 @@
     }
   });
 
+  test('(help test ~= test --help) outside project', () {
+    p = project();
+    p.deleteFile('pubspec.yaml');
+    var result = p.runSync(['help', 'test']);
+    var testHelpResult = p.runSync(['test', '--help']);
+
+    expect(testHelpResult.stdout, contains(result.stdout));
+    expect(testHelpResult.stderr, contains(result.stderr));
+  });
+
   test('(help pub == pub --help)', () {
     p = project();
     var result = p.runSync(['help', 'pub']);
diff --git a/pkg/dartdev/test/commands/language_server_test.dart b/pkg/dartdev/test/commands/language_server_test.dart
new file mode 100644
index 0000000..1e7a46d
--- /dev/null
+++ b/pkg/dartdev/test/commands/language_server_test.dart
@@ -0,0 +1,104 @@
+// 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:convert';
+import 'dart:io';
+
+import 'package:test/test.dart';
+
+import '../utils.dart' as utils;
+
+void main() {
+  group(
+    'language-server',
+    defineLanguageServerTests,
+    timeout: utils.longTimeout,
+    onPlatform: {
+      'windows': Skip('https://github.com/dart-lang/sdk/issues/44679'),
+    },
+  );
+}
+
+void defineLanguageServerTests() {
+  utils.TestProject project;
+  Process process;
+
+  tearDown(() {
+    project?.dispose();
+    process?.kill();
+  });
+
+  Future runWithLsp(List<String> args) async {
+    project = utils.project();
+
+    process = await project.start(args);
+
+    final Stream<String> inStream =
+        process.stdout.transform<String>(utf8.decoder);
+
+    // Send an LSP init.
+    final String message = jsonEncode({
+      'jsonrpc': '2.0',
+      'id': 1,
+      'method': 'initialize',
+      'params': {
+        'processId': pid,
+        'clientInfo': {'name': 'dart-cli-tester'},
+        'capabilities': {},
+        'rootUri': project.dir.uri.toString(),
+      },
+    });
+
+    process.stdin.write('Content-Length: ${message.length}\r\n');
+    process.stdin.write('\r\n');
+    process.stdin.write(message);
+
+    List<String> responses = await inStream.take(2).toList();
+    expect(responses, hasLength(2));
+
+    expect(responses[0], startsWith('Content-Length: '));
+
+    final json = jsonDecode(responses[1]);
+    expect(json['id'], 1);
+    expect(json['result'], isNotNull);
+    final result = json['result'];
+    expect(result['capabilities'], isNotNull);
+    expect(result['serverInfo'], isNotNull);
+    final serverInfo = result['serverInfo'];
+    expect(serverInfo['name'], isNotEmpty);
+
+    process.kill();
+    process = null;
+  }
+
+  test('protocol default', () async {
+    return runWithLsp(['language-server']);
+  });
+
+  test('protocol lsp', () async {
+    return runWithLsp(['language-server', '--protocol=lsp']);
+  });
+
+  test('protocol analyzer', () async {
+    project = utils.project();
+
+    process = await project.start(['language-server', '--protocol=analyzer']);
+
+    final Stream<String> inStream = process.stdout
+        .transform<String>(utf8.decoder)
+        .transform<String>(const LineSplitter());
+
+    final line = await inStream.first;
+    final json = jsonDecode(line);
+
+    expect(json['event'], 'server.connected');
+    expect(json['params'], isNotNull);
+    final params = json['params'];
+    expect(params['version'], isNotEmpty);
+    expect(params['pid'], isNot(0));
+
+    process.kill();
+    process = null;
+  });
+}
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index 59bffba..12c07d3 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -9,6 +9,8 @@
 
 import '../utils.dart';
 
+const String soundNullSafetyMessage = 'Info: Compiling with sound null safety';
+
 void main() {
   group('run', run, timeout: longTimeout);
 }
@@ -279,4 +281,21 @@
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
   });
+
+  test('without verbose CFE info', () {
+    final p = project(mainSrc: '''void main() {}''');
+
+    var result = p.runSync(
+      [
+        'run',
+        '--verbosity=warning',
+        p.relativeFilePath,
+      ],
+    );
+
+    expect(result.stdout,
+        predicate((o) => !'$o'.contains(soundNullSafetyMessage)));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
 }
diff --git a/pkg/dartdev/test/commands/test_test.dart b/pkg/dartdev/test/commands/test_test.dart
index 00be2bc..cc8b5d0 100644
--- a/pkg/dartdev/test/commands/test_test.dart
+++ b/pkg/dartdev/test/commands/test_test.dart
@@ -24,7 +24,11 @@
     final result = p.runSync(['test', '--help']);
 
     expect(result.exitCode, 0);
-    expect(result.stdout, contains(' tests in this package'));
+    expect(result.stdout, startsWith('''
+Runs tests in this package.
+
+Usage: pub run test [files or directories...]
+'''));
     expect(result.stderr, isEmpty);
   });
 
@@ -46,8 +50,25 @@
     var result = p.runSync(['test']);
 
     expect(result.stderr, isEmpty);
-    expect(result.stdout, contains('No pubspec.yaml file found'));
+    expect(result.stdout, '''
+No pubspec.yaml file found - run this command in your project folder.
+''');
     expect(result.exitCode, 65);
+
+    var resultHelp = p.runSync(['test', '--help']);
+
+    expect(resultHelp.stderr, isEmpty);
+    expect(resultHelp.stdout, '''
+No pubspec.yaml file found - run this command in your project folder.
+
+Run tests in this package.
+
+Usage: dart test [arguments]
+
+
+Run "dart help" to see global options.
+''');
+    expect(resultHelp.exitCode, 65);
   });
 
   test('runs test', () {
@@ -90,7 +111,7 @@
     expect(result.exitCode, 65);
     expect(
       result.stdout,
-      contains('You need to add a dependency on package:test'),
+      contains('You need to add a dev_dependency on package:test'),
     );
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 65);
diff --git a/pkg/dartdev/test/load_from_dill_test.dart b/pkg/dartdev/test/load_from_dill_test.dart
new file mode 100644
index 0000000..6de6c6c
--- /dev/null
+++ b/pkg/dartdev/test/load_from_dill_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.
+
+import 'dart:io';
+
+import 'package:test/test.dart';
+
+import 'utils.dart';
+
+void main() {
+  TestProject p;
+
+  tearDown(() => p?.dispose());
+
+  test("Fallback to dartdev.dill from dartdev.dart.snapshot for 'Hello World'",
+      () {
+    p = project(mainSrc: "void main() { print('Hello World'); }");
+    // The DartDev snapshot includes the --use-bare-instructions flag. If
+    // --no-use-bare-instructions is passed, the VM will fail to load the
+    // snapshot and should fall back to using the DartDev dill file.
+    ProcessResult result =
+        p.runSync(['--no-use-bare-instructions', 'run', p.relativeFilePath]);
+
+    expect(result.stdout, contains('Hello World'));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+}
diff --git a/pkg/dartdev/test/test_all.dart b/pkg/dartdev/test/test_all.dart
index edd644b..f232948 100644
--- a/pkg/dartdev/test/test_all.dart
+++ b/pkg/dartdev/test/test_all.dart
@@ -12,6 +12,7 @@
 import 'commands/flag_test.dart' as flag;
 import 'commands/format_test.dart' as format;
 import 'commands/help_test.dart' as help;
+import 'commands/language_server_test.dart' as language_server;
 import 'commands/migrate_test.dart' as migrate;
 import 'commands/pub_test.dart' as pub;
 import 'commands/run_test.dart' as run;
@@ -39,6 +40,7 @@
     help.main();
     implicit_smoke.main();
     invalid_smoke.main();
+    language_server.main();
     migrate.main();
     no_such_file.main();
     pub.main();
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index 48dcfd7..de507c1 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -68,6 +68,12 @@
     file.writeAsStringSync(contents);
   }
 
+  void deleteFile(String name) {
+    var file = File(path.join(dir.path, name));
+    assert(file.existsSync());
+    file.deleteSync();
+  }
+
   void dispose() {
     if (dir.existsSync()) {
       dir.deleteSync(recursive: true);
@@ -88,6 +94,20 @@
         environment: {if (logAnalytics) '_DARTDEV_LOG_ANALYTICS': 'true'});
   }
 
+  Future<Process> start(
+    List<String> arguments, {
+    String workingDir,
+  }) {
+    return Process.start(
+        Platform.resolvedExecutable,
+        [
+          '--no-analytics',
+          ...arguments,
+        ],
+        workingDirectory: workingDir ?? dir.path,
+        environment: {if (logAnalytics) '_DARTDEV_LOG_ANALYTICS': 'true'});
+  }
+
   String _sdkRootPath;
 
   /// Return the root of the SDK.
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index c88de17..261fdd0 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,25 @@
+# 1.7.4
+- Update `package:vm_service` to 6.0.1-nullsafety.0.
+
+# 1.7.3
+- Return an RpcException error with code `kServiceDisappeared` if the VM
+  service connection disappears with an outstanding forwarded request.
+
+# 1.7.2
+- Fixed issue where a null JSON RPC result could be sent if the VM service
+  disconnected with a request in flight (see https://github.com/flutter/flutter/issues/74051).
+
+# 1.7.1
+- Fixed issue where DartDevelopmentServiceException could have a null message.
+
+# 1.7.0
+- Added `package:dds/vm_service_extensions.dart`, which adds DDS functionality to
+  `package:vm_service` when imported.
+  - Added `onEventWithHistory` method and `onLoggingEventWithHistory`, 
+    `onStdoutEventWithHistory`, `onStderrEventWithHistory`, and 
+    `onExtensionEventWithHistory` getters.
+- Added `getStreamHistory` RPC.
+
 # 1.6.1
 - Fixed unhandled `StateError` that could be thrown if the VM service disconnected
   while a request was outstanding.
diff --git a/pkg/dds/analysis_options.yaml b/pkg/dds/analysis_options.yaml
index b5e3320..413f412 100644
--- a/pkg/dds/analysis_options.yaml
+++ b/pkg/dds/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.1.7.0.yaml
+include: package:pedantic/analysis_options.1.8.0.yaml
 
 linter:
   rules:
diff --git a/pkg/dds/dds_protocol.md b/pkg/dds/dds_protocol.md
index 253ef99..b690c1a 100644
--- a/pkg/dds/dds_protocol.md
+++ b/pkg/dds/dds_protocol.md
@@ -1,6 +1,6 @@
-# Dart Development Service Protocol 1.1
+# Dart Development Service Protocol 1.2
 
-This document describes _version 1.1_ of the Dart Development Service Protocol.
+This document describes _version 1.2_ of the Dart Development Service Protocol.
 This protocol is an extension of the Dart VM Service Protocol and implements it
 in it's entirety. For details on the VM Service Protocol, see the [Dart VM Service Protocol Specification][service-protocol].
 
@@ -103,6 +103,19 @@
 
 See [Size](#size).
 
+
+### getStreamHistory
+
+```
+StreamHistory getStreamHistory(string streamId)
+```
+
+The _getStreamHistory_ RPC is used to retrieve historical events for streams
+which support event history (see [Streams](#streams) for a list of supported
+streams).
+
+See [StreamHistory](#streamhistory).
+
 ### requirePermissionToResume
 
 ```
@@ -189,12 +202,24 @@
 
 A simple object representing a size response.
 
+### StreamHistory
+
+```
+class StreamHistory extends Response {
+  // A list of historical Events for a stream.
+  List<Event> history;
+}
+```
+
+See [getStreamHistory](#getStreamHistory).
+
 ## Revision History
 
 version | comments
 ------- | --------
 1.0 | Initial revision
 1.1 | Added `getDartDevelopmentServiceVersion` RPC.
+1.2 | Added `getStreamHistory` RPC.
 
 [resume]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#resume
 [success]: https://github.com/dart-lang/sdk/blob/master/runtime/vm/service/service.md#success
diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart
index 29cc288..a9024dd 100644
--- a/pkg/dds/lib/dds.dart
+++ b/pkg/dds/lib/dds.dart
@@ -7,35 +7,9 @@
 library dds;
 
 import 'dart:async';
-import 'dart:collection';
-import 'dart:convert';
 import 'dart:io';
-import 'dart:math';
-import 'dart:typed_data';
 
-import 'package:async/async.dart';
-import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-import 'package:meta/meta.dart';
-import 'package:pedantic/pedantic.dart';
-import 'package:shelf/shelf.dart';
-import 'package:shelf/shelf_io.dart' as io;
-import 'package:shelf_proxy/shelf_proxy.dart';
-import 'package:shelf_web_socket/shelf_web_socket.dart';
-import 'package:sse/server/sse_handler.dart';
-import 'package:stream_channel/stream_channel.dart';
-import 'package:web_socket_channel/web_socket_channel.dart';
-
-part 'src/binary_compatible_peer.dart';
-part 'src/client.dart';
-part 'src/client_manager.dart';
-part 'src/constants.dart';
-part 'src/dds_impl.dart';
-part 'src/expression_evaluator.dart';
-part 'src/logging_repository.dart';
-part 'src/isolate_manager.dart';
-part 'src/named_lookup.dart';
-part 'src/rpc_error_codes.dart';
-part 'src/stream_manager.dart';
+import 'src/dds_impl.dart';
 
 /// An intermediary between a Dart VM service and its clients that offers
 /// additional functionality on top of the standard VM service protocol.
@@ -99,7 +73,7 @@
       }
     }
 
-    final service = _DartDevelopmentService(
+    final service = DartDevelopmentServiceImpl(
       remoteVmServiceUri,
       serviceUri,
       enableAuthCodes,
@@ -155,7 +129,7 @@
 
   /// The version of the DDS protocol supported by this [DartDevelopmentService]
   /// instance.
-  static const String protocolVersion = '1.1';
+  static const String protocolVersion = '1.2';
 }
 
 class DartDevelopmentServiceException implements Exception {
@@ -171,22 +145,22 @@
   /// Set when a connection error has occurred after startup.
   static const int connectionError = 3;
 
-  factory DartDevelopmentServiceException._existingDdsInstanceError(
-      String message) {
+  factory DartDevelopmentServiceException.existingDdsInstance(String message) {
     return DartDevelopmentServiceException._(existingDdsInstanceError, message);
   }
 
-  factory DartDevelopmentServiceException._failedToStartError() {
+  factory DartDevelopmentServiceException.failedToStart() {
     return DartDevelopmentServiceException._(
         failedToStartError, 'Failed to start Dart Development Service');
   }
 
-  factory DartDevelopmentServiceException._connectionError(String message) {
+  factory DartDevelopmentServiceException.connectionIssue(String message) {
     return DartDevelopmentServiceException._(connectionError, message);
   }
 
   DartDevelopmentServiceException._(this.errorCode, this.message);
 
+  @override
   String toString() => 'DartDevelopmentServiceException: $message';
 
   final int errorCode;
diff --git a/pkg/dds/lib/src/binary_compatible_peer.dart b/pkg/dds/lib/src/binary_compatible_peer.dart
index de0a182..b701f5e 100644
--- a/pkg/dds/lib/src/binary_compatible_peer.dart
+++ b/pkg/dds/lib/src/binary_compatible_peer.dart
@@ -2,7 +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.
 
-part of dds;
+import 'dart:async';
+import 'dart:convert';
+import 'dart:typed_data';
+
+import 'package:async/async.dart';
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:stream_channel/stream_channel.dart';
+import 'package:web_socket_channel/web_socket_channel.dart';
+
+import 'stream_manager.dart';
 
 /// Adds support for binary events send from the VM service, which are not part
 /// of the official JSON RPC 2.0 specification.
@@ -17,10 +26,10 @@
 /// ```
 /// where `metadata` is the JSON body of the event.
 ///
-/// [_BinaryCompatiblePeer] assumes that only stream events can contain a
+/// [BinaryCompatiblePeer] assumes that only stream events can contain a
 /// binary payload (e.g., clients cannot send a `BinaryEvent` to the VM service).
-class _BinaryCompatiblePeer extends json_rpc.Peer {
-  _BinaryCompatiblePeer(WebSocketChannel ws, _StreamManager streamManager)
+class BinaryCompatiblePeer extends json_rpc.Peer {
+  BinaryCompatiblePeer(WebSocketChannel ws, StreamManager streamManager)
       : super(
           ws.transform<String>(
             StreamChannelTransformer(
@@ -39,7 +48,7 @@
         );
 
   static void _transformStream(
-      _StreamManager streamManager, dynamic data, EventSink<String> sink) {
+      StreamManager streamManager, dynamic data, EventSink<String> sink) {
     if (data is String) {
       // Non-binary messages come in as Strings. Simply forward to the sink.
       sink.add(data);
diff --git a/pkg/dds/lib/src/client.dart b/pkg/dds/lib/src/client.dart
index 9637058..0c854c3 100644
--- a/pkg/dds/lib/src/client.dart
+++ b/pkg/dds/lib/src/client.dart
@@ -2,34 +2,46 @@
 // for 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 dds;
+import 'dart:async';
+
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:meta/meta.dart';
+import 'package:sse/server/sse_handler.dart';
+import 'package:stream_channel/stream_channel.dart';
+import 'package:web_socket_channel/web_socket_channel.dart';
+
+import '../dds.dart';
+import 'constants.dart';
+import 'dds_impl.dart';
+import 'rpc_error_codes.dart';
+import 'stream_manager.dart';
 
 /// Representation of a single DDS client which manages the connection and
 /// DDS request intercepting / forwarding.
-class _DartDevelopmentServiceClient {
-  factory _DartDevelopmentServiceClient.fromWebSocket(
+class DartDevelopmentServiceClient {
+  factory DartDevelopmentServiceClient.fromWebSocket(
     DartDevelopmentService dds,
     WebSocketChannel ws,
     json_rpc.Peer vmServicePeer,
   ) =>
-      _DartDevelopmentServiceClient._(
+      DartDevelopmentServiceClient._(
         dds,
         ws,
         vmServicePeer,
       );
 
-  factory _DartDevelopmentServiceClient.fromSSEConnection(
+  factory DartDevelopmentServiceClient.fromSSEConnection(
     DartDevelopmentService dds,
     SseConnection sse,
     json_rpc.Peer vmServicePeer,
   ) =>
-      _DartDevelopmentServiceClient._(
+      DartDevelopmentServiceClient._(
         dds,
         sse,
         vmServicePeer,
       );
 
-  _DartDevelopmentServiceClient._(
+  DartDevelopmentServiceClient._(
     this.dds,
     this.connection,
     json_rpc.Peer vmServicePeer,
@@ -39,7 +51,7 @@
       // .cast<String>() as cast() results in addStream() being called,
       // binding the underlying sink. This results in a StateError being thrown
       // if we try and add directly to the sink, which we do for binary events
-      // in _StreamManager's streamNotify().
+      // in StreamManager's streamNotify().
       StreamChannel<String>(
         connection.stream.cast(),
         StreamController(sync: true)
@@ -88,21 +100,21 @@
     _clientPeer.registerMethod('streamListen', (parameters) async {
       final streamId = parameters['streamId'].asString;
       await dds.streamManager.streamListen(this, streamId);
-      return _RPCResponses.success;
+      return RPCResponses.success;
     });
 
     _clientPeer.registerMethod('streamCancel', (parameters) async {
       final streamId = parameters['streamId'].asString;
       await dds.streamManager.streamCancel(this, streamId);
-      return _RPCResponses.success;
+      return RPCResponses.success;
     });
 
     _clientPeer.registerMethod('registerService', (parameters) async {
       final serviceId = parameters['service'].asString;
       final alias = parameters['alias'].asString;
       if (services.containsKey(serviceId)) {
-        throw _RpcErrorCodes.buildRpcException(
-          _RpcErrorCodes.kServiceAlreadyRegistered,
+        throw RpcErrorCodes.buildRpcException(
+          RpcErrorCodes.kServiceAlreadyRegistered,
         );
       }
       services[serviceId] = alias;
@@ -112,7 +124,7 @@
         serviceId,
         alias,
       );
-      return _RPCResponses.success;
+      return RPCResponses.success;
     });
 
     _clientPeer.registerMethod(
@@ -136,13 +148,26 @@
       (parameters) => dds.isolateManager.resumeIsolate(this, parameters),
     );
 
+    _clientPeer.registerMethod('getStreamHistory', (parameters) {
+      final stream = parameters['stream'].asString;
+      final events = dds.streamManager.getStreamHistory(stream);
+      if (events == null) {
+        throw json_rpc.RpcException.invalidParams(
+          "Event history is not collected for stream '$stream'",
+        );
+      }
+      return <String, dynamic>{
+        'type': 'StreamHistory',
+        'history': events,
+      };
+    });
+
     _clientPeer.registerMethod(
         'getLogHistorySize',
         (parameters) => {
               'type': 'Size',
-              'size': _StreamManager
-                  .loggingRepositories[_StreamManager.kLoggingStream]
-                  .bufferSize,
+              'size': StreamManager
+                  .loggingRepositories[StreamManager.kLoggingStream].bufferSize,
             });
 
     _clientPeer.registerMethod('setLogHistorySize', (parameters) {
@@ -152,9 +177,9 @@
           "'size' must be greater or equal to zero",
         );
       }
-      _StreamManager.loggingRepositories[_StreamManager.kLoggingStream]
+      StreamManager.loggingRepositories[StreamManager.kLoggingStream]
           .resize(size);
-      return _RPCResponses.success;
+      return RPCResponses.success;
     });
 
     _clientPeer.registerMethod('getDartDevelopmentServiceVersion',
@@ -219,21 +244,21 @@
           [
             // Forward the request to the service client or...
             serviceClient.sendRequest(method, parameters.asMap).catchError((_) {
-              throw _RpcErrorCodes.buildRpcException(
-                _RpcErrorCodes.kServiceDisappeared,
+              throw RpcErrorCodes.buildRpcException(
+                RpcErrorCodes.kServiceDisappeared,
               );
             }, test: (error) => error is StateError),
             // if the service client closes, return an error response.
             serviceClient._clientPeer.done.then(
-              (_) => throw _RpcErrorCodes.buildRpcException(
-                _RpcErrorCodes.kServiceDisappeared,
+              (_) => throw RpcErrorCodes.buildRpcException(
+                RpcErrorCodes.kServiceDisappeared,
               ),
             ),
           ],
         );
       }
       throw json_rpc.RpcException(
-        _RpcErrorCodes.kMethodNotFound,
+        RpcErrorCodes.kMethodNotFound,
         'Unknown service: ${parameters.method}',
       );
     });
@@ -241,11 +266,18 @@
     // Unless otherwise specified, the request is forwarded to the VM service.
     // NOTE: This must be the last fallback registered.
     _clientPeer.registerFallback((parameters) async {
+      // If _vmServicePeer closes in the middle of a request, this will throw
+      // a StateError. Listeners in dds_impl.dart will handle shutting down the
+      // DDS instance, so we don't try and handle the error here.
       try {
         return await _vmServicePeer.sendRequest(
-            parameters.method, parameters.value);
+          parameters.method,
+          parameters.value,
+        );
       } on StateError {
-        await dds.shutdown();
+        throw RpcErrorCodes.buildRpcException(
+          RpcErrorCodes.kServiceDisappeared,
+        );
       }
     });
   }
@@ -260,12 +292,12 @@
   String get name => _name;
 
   // NOTE: this should not be called directly except from:
-  //   - `_ClientManager._clearClientName`
-  //   - `_ClientManager._setClientNameHelper`
+  //   - `ClientManager._clearClientName`
+  //   - `ClientManager._setClientNameHelper`
   set name(String n) => _name = n ?? defaultClientName;
   String _name;
 
-  final _DartDevelopmentService dds;
+  final DartDevelopmentServiceImpl dds;
   final StreamChannel connection;
   final Map<String, String> services = {};
   final json_rpc.Peer _vmServicePeer;
diff --git a/pkg/dds/lib/src/client_manager.dart b/pkg/dds/lib/src/client_manager.dart
index 4304000..b168978 100644
--- a/pkg/dds/lib/src/client_manager.dart
+++ b/pkg/dds/lib/src/client_manager.dart
@@ -2,28 +2,34 @@
 // for 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 dds;
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+
+import 'client.dart';
+import 'constants.dart';
+import 'dds_impl.dart';
+import 'named_lookup.dart';
+import 'stream_manager.dart';
 
 /// [_ClientResumePermissions] associates a list of
-/// [_DartDevelopmentServiceClient]s, all of the same client name, with a
+/// [DartDevelopmentServiceClient]s, all of the same client name, with a
 /// permissions mask used to determine which pause event types require approval
 /// from one of the listed clients before resuming an isolate.
 class _ClientResumePermissions {
-  final List<_DartDevelopmentServiceClient> clients = [];
+  final List<DartDevelopmentServiceClient> clients = [];
   int permissionsMask = 0;
 }
 
-/// The [_ClientManager] has the responsibility of managing all state and
+/// The [ClientManager] has the responsibility of managing all state and
 /// requests related to client connections, including:
 ///   - A list of all currently connected clients
 ///   - Tracking client names and associated permissions for isolate resume
 ///     synchronization
 ///   - Handling RPC invocations which change client state
-class _ClientManager {
-  _ClientManager(this.dds);
+class ClientManager {
+  ClientManager(this.dds);
 
   /// Initialize state for a newly connected client.
-  void addClient(_DartDevelopmentServiceClient client) {
+  void addClient(DartDevelopmentServiceClient client) {
     _setClientNameHelper(
       client,
       client.defaultClientName,
@@ -34,20 +40,20 @@
       dds.isolateManager.initialize().then((_) {
         dds.streamManager.streamListen(
           null,
-          _StreamManager.kDebugStream,
+          StreamManager.kDebugStream,
         );
       });
     }
   }
 
   /// Cleanup state for a disconnected client.
-  void removeClient(_DartDevelopmentServiceClient client) {
+  void removeClient(DartDevelopmentServiceClient client) {
     _clearClientName(client);
     clients.remove(client);
     if (clients.isEmpty) {
       dds.streamManager.streamCancel(
         null,
-        _StreamManager.kDebugStream,
+        StreamManager.kDebugStream,
       );
     }
   }
@@ -67,37 +73,37 @@
   ///
   /// The provided client name is used to track isolate resume approvals.
   Map<String, dynamic> setClientName(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
     json_rpc.Parameters parameters,
   ) {
     _setClientNameHelper(client, parameters['name'].asString);
-    return _RPCResponses.success;
+    return RPCResponses.success;
   }
 
   /// Require permission from this client before resuming an isolate.
   Map<String, dynamic> requirePermissionToResume(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
     json_rpc.Parameters parameters,
   ) {
     int pauseTypeMask = 0;
     if (parameters['onPauseStart'].asBoolOr(false)) {
-      pauseTypeMask |= _PauseTypeMasks.pauseOnStartMask;
+      pauseTypeMask |= PauseTypeMasks.pauseOnStartMask;
     }
     if (parameters['onPauseReload'].asBoolOr(false)) {
-      pauseTypeMask |= _PauseTypeMasks.pauseOnReloadMask;
+      pauseTypeMask |= PauseTypeMasks.pauseOnReloadMask;
     }
     if (parameters['onPauseExit'].asBoolOr(false)) {
-      pauseTypeMask |= _PauseTypeMasks.pauseOnExitMask;
+      pauseTypeMask |= PauseTypeMasks.pauseOnExitMask;
     }
 
     clientResumePermissions[client.name].permissionsMask = pauseTypeMask;
-    return _RPCResponses.success;
+    return RPCResponses.success;
   }
 
   /// Changes `client`'s name to `name` while also updating resume permissions
   /// and approvals.
   void _setClientNameHelper(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
     String name,
   ) {
     _clearClientName(client);
@@ -112,7 +118,7 @@
   /// Resets the client's name while also cleaning up resume permissions and
   /// approvals.
   void _clearClientName(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
   ) {
     final name = client.name;
     client.name = null;
@@ -147,7 +153,7 @@
     }
   }
 
-  _DartDevelopmentServiceClient findFirstClientThatHandlesService(
+  DartDevelopmentServiceClient findFirstClientThatHandlesService(
       String service) {
     for (final client in clients) {
       if (client.services.containsKey(service)) {
@@ -159,7 +165,7 @@
 
   // Handles namespace generation for service extensions.
   static const _kServicePrologue = 's';
-  final NamedLookup<_DartDevelopmentServiceClient> clients = NamedLookup(
+  final NamedLookup<DartDevelopmentServiceClient> clients = NamedLookup(
     prologue: _kServicePrologue,
   );
 
@@ -167,5 +173,5 @@
   /// permissions.
   final Map<String, _ClientResumePermissions> clientResumePermissions = {};
 
-  final _DartDevelopmentService dds;
+  final DartDevelopmentServiceImpl dds;
 }
diff --git a/pkg/dds/lib/src/constants.dart b/pkg/dds/lib/src/constants.dart
index 6a41e0b..c6450d5 100644
--- a/pkg/dds/lib/src/constants.dart
+++ b/pkg/dds/lib/src/constants.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.
 
-part of dds;
-
-abstract class _RPCResponses {
+abstract class RPCResponses {
   static const success = <String, dynamic>{
     'type': 'Success',
   };
@@ -16,13 +14,13 @@
   };
 }
 
-abstract class _PauseTypeMasks {
+abstract class PauseTypeMasks {
   static const pauseOnStartMask = 1 << 0;
   static const pauseOnReloadMask = 1 << 1;
   static const pauseOnExitMask = 1 << 2;
 }
 
-abstract class _ServiceEvents {
+abstract class ServiceEvents {
   static const isolateExit = 'IsolateExit';
   static const isolateSpawn = 'IsolateSpawn';
   static const isolateStart = 'IsolateStart';
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index ad0e46f..137cd20 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -2,7 +2,29 @@
 // for 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 dds;
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:math';
+import 'dart:typed_data';
+
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:meta/meta.dart';
+import 'package:pedantic/pedantic.dart';
+import 'package:shelf/shelf.dart';
+import 'package:shelf/shelf_io.dart' as io;
+import 'package:shelf_proxy/shelf_proxy.dart';
+import 'package:shelf_web_socket/shelf_web_socket.dart';
+import 'package:sse/server/sse_handler.dart';
+import 'package:web_socket_channel/web_socket_channel.dart';
+
+import '../dds.dart';
+import 'binary_compatible_peer.dart';
+import 'client.dart';
+import 'client_manager.dart';
+import 'expression_evaluator.dart';
+import 'isolate_manager.dart';
+import 'stream_manager.dart';
 
 @visibleForTesting
 typedef PeerBuilder = Future<json_rpc.Peer> Function(WebSocketChannel, dynamic);
@@ -18,20 +40,20 @@
 
 Future<json_rpc.Peer> _defaultPeerBuilder(
     WebSocketChannel ws, dynamic streamManager) async {
-  return _BinaryCompatiblePeer(ws, streamManager);
+  return BinaryCompatiblePeer(ws, streamManager);
 }
 
 WebSocketChannel _defaultWebSocketBuilder(Uri uri) {
   return WebSocketChannel.connect(uri.replace(scheme: 'ws'));
 }
 
-class _DartDevelopmentService implements DartDevelopmentService {
-  _DartDevelopmentService(
+class DartDevelopmentServiceImpl implements DartDevelopmentService {
+  DartDevelopmentServiceImpl(
       this._remoteVmServiceUri, this._uri, this._authCodesEnabled, this._ipv6) {
-    _clientManager = _ClientManager(this);
-    _expressionEvaluator = _ExpressionEvaluator(this);
-    _isolateManager = _IsolateManager(this);
-    _streamManager = _StreamManager(this);
+    _clientManager = ClientManager(this);
+    _expressionEvaluator = ExpressionEvaluator(this);
+    _isolateManager = IsolateManager(this);
+    _streamManager = StreamManager(this);
     _authCode = _authCodesEnabled ? _makeAuthToken() : '';
   }
 
@@ -41,22 +63,22 @@
     // TODO(bkonyi): throw if we've already shutdown.
     // Establish the connection to the VM service.
     _vmServiceSocket = webSocketBuilder(remoteVmServiceWsUri);
-    _vmServiceClient = await peerBuilder(_vmServiceSocket, _streamManager);
+    vmServiceClient = await peerBuilder(_vmServiceSocket, _streamManager);
     // Setup the JSON RPC client with the VM service.
     unawaited(
-      _vmServiceClient.listen().then(
+      vmServiceClient.listen().then(
         (_) {
           shutdown();
           if (!started && !completer.isCompleted) {
-            completer.completeError(
-                DartDevelopmentServiceException._failedToStartError());
+            completer
+                .completeError(DartDevelopmentServiceException.failedToStart());
           }
         },
         onError: (e, st) {
           shutdown();
           if (!completer.isCompleted) {
             completer.completeError(
-              DartDevelopmentServiceException._connectionError(e.toString()),
+              DartDevelopmentServiceException.connectionIssue(e.toString()),
               st,
             );
           }
@@ -109,21 +131,24 @@
     // and refuse connections from other clients. DDS is now acting in place of
     // the VM service.
     try {
-      await _vmServiceClient.sendRequest('_yieldControlToDDS', {
+      await vmServiceClient.sendRequest('_yieldControlToDDS', {
         'uri': tmpUri.toString(),
       });
     } on json_rpc.RpcException catch (e) {
       await _server.close(force: true);
+      String message = e.toString();
+      if (e.data != null) {
+        message += ' data: ${e.data}';
+      }
       // _yieldControlToDDS fails if DDS is not the only VM service client.
-      throw DartDevelopmentServiceException._existingDdsInstanceError(
-        e.data != null ? e.data['details'] : e.toString(),
-      );
+      throw DartDevelopmentServiceException.existingDdsInstance(message);
     }
 
     _uri = tmpUri;
   }
 
   /// Stop accepting requests after gracefully handling existing requests.
+  @override
   Future<void> shutdown() async {
     if (_done.isCompleted || _shuttingDown) {
       // Already shutdown.
@@ -197,10 +222,10 @@
   }
 
   Handler _webSocketHandler() => webSocketHandler((WebSocketChannel ws) {
-        final client = _DartDevelopmentServiceClient.fromWebSocket(
+        final client = DartDevelopmentServiceClient.fromWebSocket(
           this,
           ws,
-          _vmServiceClient,
+          vmServiceClient,
         );
         clientManager.addClient(client);
       });
@@ -211,10 +236,10 @@
         : SseHandler(Uri.parse('/$_kSseHandlerPath'));
 
     handler.connections.rest.listen((sseConnection) {
-      final client = _DartDevelopmentServiceClient.fromSSEConnection(
+      final client = DartDevelopmentServiceClient.fromSSEConnection(
         this,
         sseConnection,
-        _vmServiceClient,
+        vmServiceClient,
       );
       clientManager.addClient(client);
     });
@@ -260,19 +285,27 @@
     return uri.replace(scheme: 'sse', pathSegments: pathSegments);
   }
 
-  String _getNamespace(_DartDevelopmentServiceClient client) =>
+  String getNamespace(DartDevelopmentServiceClient client) =>
       clientManager.clients.keyOf(client);
 
+  @override
   bool get authCodesEnabled => _authCodesEnabled;
   final bool _authCodesEnabled;
   String _authCode;
 
+  @override
   Uri get remoteVmServiceUri => _remoteVmServiceUri;
+
+  @override
   Uri get remoteVmServiceWsUri => _toWebSocket(_remoteVmServiceUri);
   Uri _remoteVmServiceUri;
 
+  @override
   Uri get uri => _uri;
+
+  @override
   Uri get sseUri => _toSse(_uri);
+
   Uri get wsUri => _toWebSocket(_uri);
   Uri _uri;
 
@@ -284,21 +317,21 @@
   Completer _done = Completer<void>();
   bool _shuttingDown = false;
 
-  _ClientManager get clientManager => _clientManager;
-  _ClientManager _clientManager;
+  ClientManager get clientManager => _clientManager;
+  ClientManager _clientManager;
 
-  _ExpressionEvaluator get expressionEvaluator => _expressionEvaluator;
-  _ExpressionEvaluator _expressionEvaluator;
+  ExpressionEvaluator get expressionEvaluator => _expressionEvaluator;
+  ExpressionEvaluator _expressionEvaluator;
 
-  _IsolateManager get isolateManager => _isolateManager;
-  _IsolateManager _isolateManager;
+  IsolateManager get isolateManager => _isolateManager;
+  IsolateManager _isolateManager;
 
-  _StreamManager get streamManager => _streamManager;
-  _StreamManager _streamManager;
+  StreamManager get streamManager => _streamManager;
+  StreamManager _streamManager;
 
   static const _kSseHandlerPath = '\$debugHandler';
 
-  json_rpc.Peer _vmServiceClient;
+  json_rpc.Peer vmServiceClient;
   WebSocketChannel _vmServiceSocket;
   HttpServer _server;
 }
diff --git a/pkg/dds/lib/src/expression_evaluator.dart b/pkg/dds/lib/src/expression_evaluator.dart
index 348d8f4..bb69bb5 100644
--- a/pkg/dds/lib/src/expression_evaluator.dart
+++ b/pkg/dds/lib/src/expression_evaluator.dart
@@ -2,22 +2,26 @@
 // for 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 dds;
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+
+import 'client.dart';
+import 'dds_impl.dart';
+import 'rpc_error_codes.dart';
 
 /// A helper class which handles `evaluate` and `evaluateInFrame` calls by
 /// potentially forwarding compilation requests to an external compilation
 /// service like Flutter Tools.
-class _ExpressionEvaluator {
-  _ExpressionEvaluator(this.dds);
+class ExpressionEvaluator {
+  ExpressionEvaluator(this.dds);
 
   Future<Map<String, dynamic>> execute(json_rpc.Parameters parameters) async {
-    _DartDevelopmentServiceClient externalClient =
+    DartDevelopmentServiceClient externalClient =
         dds.clientManager.findFirstClientThatHandlesService(
       'compileExpression',
     );
     // If no compilation service is registered, just forward to the VM service.
     if (externalClient == null) {
-      return await dds._vmServiceClient.sendRequest(
+      return await dds.vmServiceClient.sendRequest(
         parameters.method,
         parameters.value,
       );
@@ -30,8 +34,8 @@
     try {
       buildScopeResponse = await _buildScope(parameters);
     } on json_rpc.RpcException catch (e) {
-      throw _RpcErrorCodes.buildRpcException(
-        _RpcErrorCodes.kExpressionCompilationError,
+      throw RpcErrorCodes.buildRpcException(
+        RpcErrorCodes.kExpressionCompilationError,
         data: e.data,
       );
     }
@@ -40,8 +44,8 @@
       kernelBase64 =
           await _compileExpression(isolateId, expression, buildScopeResponse);
     } on json_rpc.RpcException catch (e) {
-      throw _RpcErrorCodes.buildRpcException(
-        _RpcErrorCodes.kExpressionCompilationError,
+      throw RpcErrorCodes.buildRpcException(
+        RpcErrorCodes.kExpressionCompilationError,
         data: e.data,
       );
     }
@@ -56,7 +60,7 @@
     if (parameters['scope'].asMapOr(null) != null) {
       params['scope'] = parameters['scope'].asMap;
     }
-    return await dds._vmServiceClient.sendRequest(
+    return await dds.vmServiceClient.sendRequest(
       '_buildExpressionEvaluationScope',
       params,
     );
@@ -64,13 +68,13 @@
 
   Future<String> _compileExpression(String isolateId, String expression,
       Map<String, dynamic> buildScopeResponseResult) async {
-    _DartDevelopmentServiceClient externalClient =
+    DartDevelopmentServiceClient externalClient =
         dds.clientManager.findFirstClientThatHandlesService(
       'compileExpression',
     );
     if (externalClient == null) {
-      throw _RpcErrorCodes.buildRpcException(
-          _RpcErrorCodes.kExpressionCompilationError,
+      throw RpcErrorCodes.buildRpcException(
+          RpcErrorCodes.kExpressionCompilationError,
           data: 'compileExpression service disappeared.');
     }
 
@@ -93,8 +97,8 @@
         compileParams,
       ))['kernelBytes'];
     } on json_rpc.RpcException catch (e) {
-      throw _RpcErrorCodes.buildRpcException(
-        _RpcErrorCodes.kExpressionCompilationError,
+      throw RpcErrorCodes.buildRpcException(
+        RpcErrorCodes.kExpressionCompilationError,
         data: e.data,
       );
     }
@@ -113,7 +117,7 @@
     if (parameters['scope'].asMapOr(null) != null) {
       params['scope'] = parameters['scope'].asMap;
     }
-    return await dds._vmServiceClient.sendRequest(
+    return await dds.vmServiceClient.sendRequest(
       '_evaluateCompiledExpression',
       params,
     );
@@ -132,5 +136,5 @@
     }
   }
 
-  final _DartDevelopmentService dds;
+  final DartDevelopmentServiceImpl dds;
 }
diff --git a/pkg/dds/lib/src/isolate_manager.dart b/pkg/dds/lib/src/isolate_manager.dart
index c94d4cd..2714021 100644
--- a/pkg/dds/lib/src/isolate_manager.dart
+++ b/pkg/dds/lib/src/isolate_manager.dart
@@ -2,7 +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.
 
-part of dds;
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+
+import 'client.dart';
+import 'constants.dart';
+import 'dds_impl.dart';
 
 /// This file contains functionality used to track the running state of
 /// all isolates in a given Dart process.
@@ -12,13 +16,13 @@
 /// clients used to synchronize isolate resuming across multiple clients are
 /// tracked in this class.
 ///
-/// The [_IsolateManager] keeps track of all the isolates in the
+/// The [IsolateManager] keeps track of all the isolates in the
 /// target process and handles isolate lifecycle events including:
 ///   - Startup
 ///   - Shutdown
 ///   - Pauses
 ///
-/// The [_IsolateManager] also handles the `resume` RPC, which checks the
+/// The [IsolateManager] also handles the `resume` RPC, which checks the
 /// resume approvals in the target [_RunningIsolate] to determine if the
 /// isolate should be resumed or wait for additional approvals to be granted.
 
@@ -35,10 +39,15 @@
 
   // State setters.
   void pausedOnExit() => _state = _IsolateState.pauseExit;
+
   void pausedOnStart() => _state = _IsolateState.pauseStart;
+
   void pausedPostRequest() => _state = _IsolateState.pausePostRequest;
+
   void resumed() => running();
+
   void running() => _state = _IsolateState.running;
+
   void started() => _state = _IsolateState.start;
 
   /// Resumes the isolate if all clients which need to approve a resume have
@@ -51,7 +60,7 @@
 
     if (shouldResume()) {
       clearResumeApprovals();
-      await isolateManager.dds._vmServiceClient.sendRequest('resume', {
+      await isolateManager.dds.vmServiceClient.sendRequest('resume', {
         'isolateId': id,
       });
     }
@@ -64,7 +73,7 @@
   /// which have provided approval to resume this isolate. If not provided,
   /// the existing approvals state will be examined to see if the isolate
   /// should resume due to a client disconnect or name change.
-  bool shouldResume({_DartDevelopmentServiceClient resumingClient}) {
+  bool shouldResume({DartDevelopmentServiceClient resumingClient}) {
     if (resumingClient != null) {
       // Mark approval by the client.
       _resumeApprovalsByName.add(resumingClient.name);
@@ -97,20 +106,20 @@
   int get _isolateStateMask => isolateStateToMaskMapping[_state] ?? 0;
 
   static const isolateStateToMaskMapping = {
-    _IsolateState.pauseStart: _PauseTypeMasks.pauseOnStartMask,
-    _IsolateState.pausePostRequest: _PauseTypeMasks.pauseOnReloadMask,
-    _IsolateState.pauseExit: _PauseTypeMasks.pauseOnExitMask,
+    _IsolateState.pauseStart: PauseTypeMasks.pauseOnStartMask,
+    _IsolateState.pausePostRequest: PauseTypeMasks.pauseOnReloadMask,
+    _IsolateState.pauseExit: PauseTypeMasks.pauseOnExitMask,
   };
 
-  final _IsolateManager isolateManager;
+  final IsolateManager isolateManager;
   final String name;
   final String id;
   final Set<String> _resumeApprovalsByName = {};
   _IsolateState _state;
 }
 
-class _IsolateManager {
-  _IsolateManager(this.dds);
+class IsolateManager {
+  IsolateManager(this.dds);
 
   /// Handles state changes for isolates.
   void handleIsolateEvent(json_rpc.Parameters parameters) {
@@ -119,7 +128,7 @@
 
     // There's no interesting information about isolate state associated with
     // and IsolateSpawn event.
-    if (eventKind == _ServiceEvents.isolateSpawn) {
+    if (eventKind == ServiceEvents.isolateSpawn) {
       return;
     }
 
@@ -131,25 +140,25 @@
 
   void _updateIsolateState(String id, String name, String eventKind) {
     switch (eventKind) {
-      case _ServiceEvents.isolateStart:
+      case ServiceEvents.isolateStart:
         isolateStarted(id, name);
         break;
-      case _ServiceEvents.isolateExit:
+      case ServiceEvents.isolateExit:
         isolateExited(id);
         break;
       default:
         final isolate = isolates[id];
         switch (eventKind) {
-          case _ServiceEvents.pauseExit:
+          case ServiceEvents.pauseExit:
             isolate.pausedOnExit();
             break;
-          case _ServiceEvents.pausePostRequest:
+          case ServiceEvents.pausePostRequest:
             isolate.pausedPostRequest();
             break;
-          case _ServiceEvents.pauseStart:
+          case ServiceEvents.pauseStart:
             isolate.pausedOnStart();
             break;
-          case _ServiceEvents.resume:
+          case ServiceEvents.resume:
             isolate.resumed();
             break;
           default:
@@ -163,13 +172,13 @@
     if (_initialized) {
       return;
     }
-    final vm = await dds._vmServiceClient.sendRequest('getVM');
+    final vm = await dds.vmServiceClient.sendRequest('getVM');
     final List<Map> isolateRefs = vm['isolates'].cast<Map<String, dynamic>>();
     // Check the pause event for each isolate to determine whether or not the
     // isolate is already paused.
     for (final isolateRef in isolateRefs) {
       final id = isolateRef['id'];
-      final isolate = await dds._vmServiceClient.sendRequest('getIsolate', {
+      final isolate = await dds.vmServiceClient.sendRequest('getIsolate', {
         'isolateId': id,
       });
       final name = isolate['name'];
@@ -206,19 +215,19 @@
   ///
   /// Returns a collected sentinel if the isolate no longer exists.
   Future<Map<String, dynamic>> resumeIsolate(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
     json_rpc.Parameters parameters,
   ) async {
     final isolateId = parameters['isolateId'].asString;
     final isolate = isolates[isolateId];
     if (isolate == null) {
-      return _RPCResponses.collectedSentinel;
+      return RPCResponses.collectedSentinel;
     }
     if (isolate.shouldResume(resumingClient: client)) {
       isolate.clearResumeApprovals();
       return await _sendResumeRequest(isolateId, parameters);
     }
-    return _RPCResponses.success;
+    return RPCResponses.success;
   }
 
   /// Forwards a `resume` request to the VM service.
@@ -228,7 +237,7 @@
   ) async {
     final step = parameters['step'].asStringOr(null);
     final frameIndex = parameters['frameIndex'].asIntOr(null);
-    final resumeResult = await dds._vmServiceClient.sendRequest('resume', {
+    final resumeResult = await dds.vmServiceClient.sendRequest('resume', {
       'isolateId': isolateId,
       if (step != null) 'step': step,
       if (frameIndex != null) 'frameIndex': frameIndex,
@@ -237,6 +246,6 @@
   }
 
   bool _initialized = false;
-  final _DartDevelopmentService dds;
+  final DartDevelopmentServiceImpl dds;
   final Map<String, _RunningIsolate> isolates = {};
 }
diff --git a/pkg/dds/lib/src/logging_repository.dart b/pkg/dds/lib/src/logging_repository.dart
index 67415be..f87fdaa 100644
--- a/pkg/dds/lib/src/logging_repository.dart
+++ b/pkg/dds/lib/src/logging_repository.dart
@@ -2,19 +2,23 @@
 // for 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 dds;
+import 'dart:math';
 
-/// [_LoggingRepository] is used to store historical log messages from the
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+
+import 'client.dart';
+
+/// [LoggingRepository] is used to store historical log messages from the
 /// target VM service. Clients which connect to DDS and subscribe to the
 /// `Logging` stream will be sent all messages contained within this repository
 /// upon initial subscription.
-class _LoggingRepository extends _RingBuffer<Map<String, dynamic>> {
-  _LoggingRepository([int logHistoryLength = 10000]) : super(logHistoryLength) {
+class LoggingRepository extends _RingBuffer<Map<String, dynamic>> {
+  LoggingRepository([int logHistoryLength = 10000]) : super(logHistoryLength) {
     // TODO(bkonyi): enforce log history limit when DartDevelopmentService
     // allows for this to be set via Dart code.
   }
 
-  void sendHistoricalLogs(_DartDevelopmentServiceClient client) {
+  void sendHistoricalLogs(DartDevelopmentServiceClient client) {
     // Only send historical log messages when the client first subscribes to
     // the logging stream.
     if (_sentHistoricLogsClientSet.contains(client)) {
@@ -38,7 +42,7 @@
 
   // The set of clients which have subscribed to the Logging stream at some
   // point in time.
-  final Set<_DartDevelopmentServiceClient> _sentHistoricLogsClientSet = {};
+  final Set<DartDevelopmentServiceClient> _sentHistoricLogsClientSet = {};
   static const int _kMaxLogBufferSize = 100000;
 }
 
@@ -86,6 +90,7 @@
   }
 
   int get bufferSize => _bufferSize;
+
   int get _size => min(_count, _bufferSize);
 
   int _bufferSize;
diff --git a/pkg/dds/lib/src/named_lookup.dart b/pkg/dds/lib/src/named_lookup.dart
index 4b89633..603bbc0 100644
--- a/pkg/dds/lib/src/named_lookup.dart
+++ b/pkg/dds/lib/src/named_lookup.dart
@@ -4,7 +4,7 @@
 
 // Originally pulled from dart:_vmservice.
 
-part of dds;
+import 'dart:collection';
 
 /// [Set]-like containers which automatically generate [String] IDs for its
 /// items.
@@ -29,6 +29,7 @@
   }
 
   E operator [](String id) => _elements[id];
+
   String keyOf(E e) => _ids[e];
 
   Iterator<E> get iterator => _ids.keys.iterator;
diff --git a/pkg/dds/lib/src/rpc_error_codes.dart b/pkg/dds/lib/src/rpc_error_codes.dart
index 8826a51..93c514e 100644
--- a/pkg/dds/lib/src/rpc_error_codes.dart
+++ b/pkg/dds/lib/src/rpc_error_codes.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.
 
-part of dds;
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 
-abstract class _RpcErrorCodes {
+abstract class RpcErrorCodes {
   static json_rpc.RpcException buildRpcException(int code, {dynamic data}) {
     return json_rpc.RpcException(
       code,
@@ -18,15 +18,18 @@
   // static const kParseError = -32700;
   // static const kInvalidRequest = -32600;
   static const kMethodNotFound = -32601;
+
   // static const kInvalidParams = -32602;
   // static const kInternalError = -32603;
 
   // static const kExtensionError = -32000;
 
   static const kFeatureDisabled = 100;
+
   // static const kCannotAddBreakpoint = 102;
   static const kStreamAlreadySubscribed = 103;
   static const kStreamNotSubscribed = 104;
+
   // static const kIsolateMustBeRunnable = 105;
   // static const kIsolateMustBePaused = 106;
   // static const kCannotResume = 107;
@@ -36,6 +39,7 @@
   static const kServiceAlreadyRegistered = 111;
   static const kServiceDisappeared = 112;
   static const kExpressionCompilationError = 113;
+
   // static const kInvalidTimelineRequest = 114;
 
   // Experimental (used in private rpcs).
diff --git a/pkg/dds/lib/src/stream_manager.dart b/pkg/dds/lib/src/stream_manager.dart
index 20be940..28c7f28 100644
--- a/pkg/dds/lib/src/stream_manager.dart
+++ b/pkg/dds/lib/src/stream_manager.dart
@@ -2,10 +2,17 @@
 // for 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 dds;
+import 'dart:typed_data';
 
-class _StreamManager {
-  _StreamManager(this.dds);
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+
+import 'client.dart';
+import 'dds_impl.dart';
+import 'logging_repository.dart';
+import 'rpc_error_codes.dart';
+
+class StreamManager {
+  StreamManager(this.dds);
 
   /// Send `streamNotify` notifications to clients subscribed to `streamId`.
   ///
@@ -18,7 +25,7 @@
   void streamNotify(
     String streamId,
     data, {
-    _DartDevelopmentServiceClient excludedClient,
+    DartDevelopmentServiceClient excludedClient,
   }) {
     if (streamListeners.containsKey(streamId)) {
       final listeners = streamListeners[streamId];
@@ -51,11 +58,11 @@
       };
 
   void sendServiceRegisteredEvent(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
     String service,
     String alias,
   ) {
-    final namespace = dds._getNamespace(client);
+    final namespace = dds.getNamespace(client);
     streamNotify(
       kServiceStream,
       _buildStreamRegisteredEvent(namespace, service, alias),
@@ -64,9 +71,9 @@
   }
 
   void _sendServiceUnregisteredEvents(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
   ) {
-    final namespace = dds._getNamespace(client);
+    final namespace = dds.getNamespace(client);
     for (final service in client.services.keys) {
       streamNotify(
         kServiceStream,
@@ -88,23 +95,23 @@
   /// Start listening for `streamNotify` events from the VM service and forward
   /// them to the clients which have subscribed to the stream.
   Future<void> listen() async {
-    // The _IsolateManager requires information from both the Debug and
+    // The IsolateManager requires information from both the Debug and
     // Isolate streams, so they must always be subscribed to by DDS.
     for (final stream in ddsCoreStreams) {
       try {
         await streamListen(null, stream);
         if (loggingRepositoryStreams.contains(stream)) {
-          loggingRepositories[stream] = _LoggingRepository();
+          loggingRepositories[stream] = LoggingRepository();
         }
       } on json_rpc.RpcException {
         // Stdout and Stderr streams may not exist.
       }
     }
-    dds._vmServiceClient.registerMethod(
+    dds.vmServiceClient.registerMethod(
       'streamNotify',
       (parameters) {
         final streamId = parameters['streamId'].asString;
-        // Forward events from the streams _IsolateManager subscribes to.
+        // Forward events from the streams IsolateManager subscribes to.
         if (isolateManagerStreams.contains(streamId)) {
           dds.isolateManager.handleIsolateEvent(parameters);
         }
@@ -123,7 +130,7 @@
   /// If `client` is the first client to listen to `stream`, DDS will send a
   /// `streamListen` request for `stream` to the VM service.
   Future<void> streamListen(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
     String stream,
   ) async {
     assert(stream != null && stream.isNotEmpty);
@@ -132,12 +139,12 @@
           stream != kDebugStream) {
         // This will return an RPC exception if the stream doesn't exist. This
         // will throw and the exception will be forwarded to the client.
-        final result = await dds._vmServiceClient.sendRequest('streamListen', {
+        final result = await dds.vmServiceClient.sendRequest('streamListen', {
           'streamId': stream,
         });
         assert(result['type'] == 'Success');
       }
-      streamListeners[stream] = <_DartDevelopmentServiceClient>[];
+      streamListeners[stream] = <DartDevelopmentServiceClient>[];
     }
     if (streamListeners[stream].contains(client)) {
       throw kStreamAlreadySubscribedException;
@@ -153,7 +160,7 @@
           if (c == client) {
             continue;
           }
-          final namespace = dds._getNamespace(c);
+          final namespace = dds.getNamespace(c);
           for (final service in c.services.keys) {
             client.sendNotification(
               'streamNotify',
@@ -169,12 +176,21 @@
     }
   }
 
+  List<Map<String, dynamic>> getStreamHistory(String stream) {
+    if (!loggingRepositories.containsKey(stream)) {
+      return null;
+    }
+    return [
+      for (final event in loggingRepositories[stream]()) event['event'],
+    ];
+  }
+
   /// Unsubscribes `client` from a stream.
   ///
   /// If `client` is the last client to unsubscribe from `stream`, DDS will
   /// send a `streamCancel` request for `stream` to the VM service.
   Future<void> streamCancel(
-    _DartDevelopmentServiceClient client,
+    DartDevelopmentServiceClient client,
     String stream, {
     bool cancelCoreStream = false,
   }) async {
@@ -189,10 +205,10 @@
         (!ddsCoreStreams.contains(stream) || cancelCoreStream)) {
       streamListeners.remove(stream);
       // Ensure the VM service hasn't shutdown.
-      if (dds._vmServiceClient.isClosed) {
+      if (dds.vmServiceClient.isClosed) {
         return;
       }
-      final result = await dds._vmServiceClient.sendRequest('streamCancel', {
+      final result = await dds.vmServiceClient.sendRequest('streamCancel', {
         'streamId': stream,
       });
       assert(result['type'] == 'Success');
@@ -202,7 +218,7 @@
   }
 
   /// Cleanup stream subscriptions for `client` when it has disconnected.
-  void clientDisconnect(_DartDevelopmentServiceClient client) {
+  void clientDisconnect(DartDevelopmentServiceClient client) {
     for (final streamId in streamListeners.keys.toList()) {
       streamCancel(client, streamId).catchError(
         (_) => null,
@@ -219,12 +235,12 @@
   static const kServiceStream = 'Service';
 
   static final kStreamAlreadySubscribedException =
-      _RpcErrorCodes.buildRpcException(
-    _RpcErrorCodes.kStreamAlreadySubscribed,
+      RpcErrorCodes.buildRpcException(
+    RpcErrorCodes.kStreamAlreadySubscribed,
   );
 
-  static final kStreamNotSubscribedException = _RpcErrorCodes.buildRpcException(
-    _RpcErrorCodes.kStreamNotSubscribed,
+  static final kStreamNotSubscribedException = RpcErrorCodes.buildRpcException(
+    RpcErrorCodes.kStreamNotSubscribed,
   );
 
   static const kDebugStream = 'Debug';
@@ -234,16 +250,16 @@
   static const kStderrStream = 'Stderr';
   static const kStdoutStream = 'Stdout';
 
-  static Map<String, _LoggingRepository> loggingRepositories = {};
+  static Map<String, LoggingRepository> loggingRepositories = {};
 
-  // Never cancel the Debug or Isolate stream as `_IsolateManager` requires
+  // Never cancel the Debug or Isolate stream as `IsolateManager` requires
   // them for isolate state notifications.
   static const isolateManagerStreams = <String>{
     kDebugStream,
     kIsolateStream,
   };
 
-  // Never cancel the logging and extension event streams as `_LoggingRepository`
+  // Never cancel the logging and extension event streams as `LoggingRepository`
   // requires them keep history.
   static const loggingRepositoryStreams = <String>{
     kExtensionStream,
@@ -258,6 +274,6 @@
     ...loggingRepositoryStreams,
   };
 
-  final _DartDevelopmentService dds;
-  final streamListeners = <String, List<_DartDevelopmentServiceClient>>{};
+  final DartDevelopmentServiceImpl dds;
+  final streamListeners = <String, List<DartDevelopmentServiceClient>>{};
 }
diff --git a/pkg/dds/lib/vm_service_extensions.dart b/pkg/dds/lib/vm_service_extensions.dart
new file mode 100644
index 0000000..8373b87
--- /dev/null
+++ b/pkg/dds/lib/vm_service_extensions.dart
@@ -0,0 +1,157 @@
+// 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 'dart:async';
+import 'dart:collection';
+
+import 'package:async/async.dart';
+import 'package:meta/meta.dart';
+import 'package:pedantic/pedantic.dart';
+import 'package:vm_service/src/vm_service.dart';
+
+extension DdsExtension on VmService {
+  static bool _factoriesRegistered = false;
+  static Version _ddsVersion;
+
+  /// The _getDartDevelopmentServiceVersion_ RPC is used to determine what version of
+  /// the Dart Development Service Protocol is served by a DDS instance.
+  ///
+  /// The result of this call is cached for subsequent invocations.
+  Future<Version> getDartDevelopmentServiceVersion() async {
+    if (_ddsVersion == null) {
+      _ddsVersion =
+          await _callHelper<Version>('getDartDevelopmentServiceVersion');
+    }
+    return _ddsVersion;
+  }
+
+  /// Retrieve the event history for `stream`.
+  ///
+  /// If `stream` does not have event history collected, a parameter error is
+  /// returned.
+  Future<StreamHistory> getStreamHistory(String stream) async {
+    if (!(await _versionCheck(1, 2))) {
+      throw UnimplementedError('getStreamHistory requires DDS version 1.2');
+    }
+    return _callHelper<StreamHistory>('getStreamHistory', args: {
+      'stream': stream,
+    });
+  }
+
+  /// Returns the stream for a given stream id which includes historical
+  /// events.
+  ///
+  /// If `stream` does not have event history collected, a parameter error is
+  /// sent over the returned [Stream].
+  Stream<Event> onEventWithHistory(String stream) {
+    StreamController<Event> controller;
+    StreamQueue<Event> streamEvents;
+
+    controller = StreamController<Event>(onListen: () async {
+      streamEvents = StreamQueue<Event>(onEvent(stream));
+      final history = (await getStreamHistory(stream)).history;
+      Event firstStreamEvent;
+      unawaited(streamEvents.peek.then((e) {
+        firstStreamEvent = e;
+      }));
+      for (final event in history) {
+        if (firstStreamEvent != null &&
+            event.timestamp > firstStreamEvent.timestamp) {
+          break;
+        }
+        controller.sink.add(event);
+      }
+      unawaited(controller.sink.addStream(streamEvents.rest));
+    }, onCancel: () {
+      streamEvents.cancel();
+    });
+
+    return controller.stream;
+  }
+
+  /// Returns a new [Stream<Event>] of `Logging` events which outputs
+  /// historical events before streaming real-time events.
+  ///
+  /// Note: unlike [onLoggingEvent], the returned stream is a single
+  /// subscription stream and a new stream is created for each invocation of
+  /// this getter.
+  Stream<Event> get onLoggingEventWithHistory => onEventWithHistory('Logging');
+
+  /// Returns a new [Stream<Event>] of `Stdout` events which outputs
+  /// historical events before streaming real-time events.
+  ///
+  /// Note: unlike [onStdoutEvent], the returned stream is a single
+  /// subscription stream and a new stream is created for each invocation of
+  /// this getter.
+  Stream<Event> get onStdoutEventWithHistory => onEventWithHistory('Stdout');
+
+  /// Returns a new [Stream<Event>] of `Stderr` events which outputs
+  /// historical events before streaming real-time events.
+  ///
+  /// Note: unlike [onStderrEvent], the returned stream is a single
+  /// subscription stream and a new stream is created for each invocation of
+  /// this getter.
+  Stream<Event> get onStderrEventWithHistory => onEventWithHistory('Stderr');
+
+  /// Returns a new [Stream<Event>] of `Extension` events which outputs
+  /// historical events before streaming real-time events.
+  ///
+  /// Note: unlike [onExtensionEvent], the returned stream is a single
+  /// subscription stream and a new stream is created for each invocation of
+  /// this getter.
+  Stream<Event> get onExtensionEventWithHistory =>
+      onEventWithHistory('Extension');
+
+  Future<bool> _versionCheck(int major, int minor) async {
+    if (_ddsVersion == null) {
+      _ddsVersion = await getDartDevelopmentServiceVersion();
+    }
+    return ((_ddsVersion.major == major && _ddsVersion.minor >= minor) ||
+        (_ddsVersion.major > major));
+  }
+
+  Future<T> _callHelper<T>(String method,
+      {String isolateId, Map args = const {}}) {
+    if (!_factoriesRegistered) {
+      _registerFactories();
+    }
+    return callMethod(
+      method,
+      args: {
+        if (isolateId != null) 'isolateId': isolateId,
+        ...args,
+      },
+    ).then((e) => e as T);
+  }
+
+  static void _registerFactories() {
+    addTypeFactory('StreamHistory', StreamHistory.parse);
+    _factoriesRegistered = true;
+  }
+}
+
+/// A collection of historical [Event]s from some stream.
+class StreamHistory extends Response {
+  static StreamHistory parse(Map<String, dynamic> json) =>
+      json == null ? null : StreamHistory._fromJson(json);
+
+  StreamHistory({@required List<Event> history}) : _history = history;
+
+  StreamHistory._fromJson(Map<String, dynamic> json)
+      : _history = json['history']
+            .map(
+              (e) => Event.parse(e),
+            )
+            .toList()
+            .cast<Event>() {
+    this.json = json;
+  }
+
+  @override
+  String get type => 'StreamHistory';
+
+  /// Historical [Event]s for a stream.
+  List<Event> get history => UnmodifiableListView(_history);
+  final List<Event> _history;
+}
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index d0e85c6..92dee88 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: 1.6.1
+version: 1.7.4
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
 
@@ -20,10 +20,10 @@
   shelf_web_socket: ^0.2.3
   sse: ^3.5.0
   stream_channel: ^2.0.0
+  vm_service: ^6.0.1-nullsafety.0
   web_socket_channel: ^1.1.0
 
 dev_dependencies:
   shelf_static: ^0.2.8
   test: ^1.0.0
-  vm_service: ^5.0.0
   webdriver: ^2.1.2
diff --git a/pkg/dds/test/common/test_helper.dart b/pkg/dds/test/common/test_helper.dart
index 365ffc4..cda9ce2 100644
--- a/pkg/dds/test/common/test_helper.dart
+++ b/pkg/dds/test/common/test_helper.dart
@@ -7,7 +7,10 @@
 
 Uri remoteVmServiceUri;
 
-Future<Process> spawnDartProcess(String script) async {
+Future<Process> spawnDartProcess(
+  String script, {
+  bool pauseOnStart = true,
+}) async {
   final executable = Platform.executable;
   final tmpDir = await Directory.systemTemp.createTemp('dart_service');
   final serviceInfoUri = tmpDir.uri.resolve('service_info.json');
@@ -16,7 +19,7 @@
   final arguments = [
     '--disable-dart-dev',
     '--observe=0',
-    '--pause-isolates-on-start',
+    if (pauseOnStart) '--pause-isolates-on-start',
     '--write-service-info=$serviceInfoUri',
     ...Platform.executableArguments,
     Platform.script.resolve(script).toString(),
diff --git a/pkg/dds/test/get_stream_history_script.dart b/pkg/dds/test/get_stream_history_script.dart
new file mode 100644
index 0000000..68dafec
--- /dev/null
+++ b/pkg/dds/test/get_stream_history_script.dart
@@ -0,0 +1,8 @@
+import 'dart:developer';
+
+void main() {
+  for (int i = 0; i < 10; ++i) {
+    log(i.toString());
+  }
+  debugger();
+}
diff --git a/pkg/dds/test/get_stream_history_test.dart b/pkg/dds/test/get_stream_history_test.dart
new file mode 100644
index 0000000..c2ae8f9
--- /dev/null
+++ b/pkg/dds/test/get_stream_history_test.dart
@@ -0,0 +1,40 @@
+// 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 'dart:io';
+
+import 'package:dds/dds.dart';
+import 'package:dds/vm_service_extensions.dart';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service_io.dart';
+import 'common/test_helper.dart';
+
+void main() {
+  Process process;
+  DartDevelopmentService dds;
+
+  setUp(() async {
+    process = await spawnDartProcess('get_stream_history_script.dart',
+        pauseOnStart: false);
+  });
+
+  tearDown(() async {
+    await dds?.shutdown();
+    process?.kill();
+    dds = null;
+    process = null;
+  });
+
+  test('getStreamHistory returns log history', () async {
+    dds = await DartDevelopmentService.startDartDevelopmentService(
+      remoteVmServiceUri,
+    );
+    expect(dds.isRunning, true);
+    final service = await vmServiceConnectUri(dds.wsUri.toString());
+    final result = await service.getStreamHistory('Logging');
+    expect(result, isNotNull);
+    expect(result, isA<StreamHistory>());
+    expect(result.history.length, 10);
+  });
+}
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 f500711..87d027c 100644
--- a/pkg/dds/test/handles_client_disconnect_state_error_test.dart
+++ b/pkg/dds/test/handles_client_disconnect_state_error_test.dart
@@ -5,6 +5,8 @@
 import 'dart:async';
 
 import 'package:dds/dds.dart';
+import 'package:dds/src/dds_impl.dart';
+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/test.dart';
@@ -28,6 +30,9 @@
         completer.completeError(
           StateError('The client closed with pending request "foo".'),
         );
+        doneCompleter.completeError(
+          StateError('The client closed with pending request "foo".'),
+        );
         break;
       default:
         completer.complete(await super.sendRequest(method, args));
@@ -77,16 +82,22 @@
     final client = json_rpc.Client(ws.cast<String>());
     unawaited(client.listen());
 
+    bool caught = false;
+
     // Make a request that causes the VM service peer to close in the middle of
     // handling a request. This is meant to mimic a device being disconnected
     // unexpectedly.
     try {
       await client.sendRequest('foo');
-    } on StateError {
-      // This state error is expected. This test is ensuring that DDS exits
+    } on json_rpc.RpcException catch (e) {
+      // This RPC exception is expected. This test is ensuring that DDS exits
       // gracefully even if the VM service disappears.
+      expect(e.code, RpcErrorCodes.kServiceDisappeared);
+      caught = true;
     }
 
+    expect(caught, true);
+
     // DDS should shutdown if the VM service peer disconnects.
     await dds.done;
   });
diff --git a/pkg/dds/test/on_event_with_history_script.dart b/pkg/dds/test/on_event_with_history_script.dart
new file mode 100644
index 0000000..3f27df0
--- /dev/null
+++ b/pkg/dds/test/on_event_with_history_script.dart
@@ -0,0 +1,12 @@
+import 'dart:developer';
+
+void main() {
+  for (int i = 1; i <= 10; ++i) {
+    log(i.toString());
+  }
+  debugger();
+  for (int i = 11; i <= 20; ++i) {
+    log(i.toString());
+  }
+  debugger();
+}
diff --git a/pkg/dds/test/on_event_with_history_test.dart b/pkg/dds/test/on_event_with_history_test.dart
new file mode 100644
index 0000000..55e04b9
--- /dev/null
+++ b/pkg/dds/test/on_event_with_history_test.dart
@@ -0,0 +1,59 @@
+// 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:io';
+
+import 'package:dds/dds.dart';
+import 'package:dds/vm_service_extensions.dart';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service_io.dart';
+import 'common/test_helper.dart';
+
+void main() {
+  Process process;
+  DartDevelopmentService dds;
+
+  setUp(() async {
+    process = await spawnDartProcess('on_event_with_history_script.dart',
+        pauseOnStart: false);
+  });
+
+  tearDown(() async {
+    await dds?.shutdown();
+    process?.kill();
+    dds = null;
+    process = null;
+  });
+
+  test('onEventWithHistory returns stream including log history', () async {
+    dds = await DartDevelopmentService.startDartDevelopmentService(
+      remoteVmServiceUri,
+    );
+    expect(dds.isRunning, true);
+    final service = await vmServiceConnectUri(dds.wsUri.toString());
+
+    await service.streamListen('Logging');
+    final stream = service.onLoggingEventWithHistory;
+
+    var completer = Completer<void>();
+    int count = 0;
+    stream.listen((event) {
+      count++;
+      expect(event.logRecord.message.valueAsString, count.toString());
+      if (count % 10 == 0) {
+        completer.complete();
+      }
+    });
+
+    await completer.future;
+
+    completer = Completer<void>();
+    final isolateId = (await service.getVM()).isolates.first.id;
+    await service.resume(isolateId);
+
+    await completer.future;
+    expect(count, 20);
+  });
+}
diff --git a/pkg/dds/test/smoke_test.dart b/pkg/dds/test/smoke_test.dart
index d317893..983a2da 100644
--- a/pkg/dds/test/smoke_test.dart
+++ b/pkg/dds/test/smoke_test.dart
@@ -82,35 +82,6 @@
     createSmokeTest(true, false);
     createSmokeTest(false, false);
     createSmokeTest(true, true);
-
-    test('startup fails when VM service has existing clients', () async {
-      Uri httpToWebSocketUri(Uri httpUri) {
-        final segments = (httpUri.pathSegments.isNotEmpty)
-            ? (httpUri.pathSegments.toList()..removeLast())
-            : <String>[];
-        segments.add('ws');
-        return httpUri.replace(
-          scheme: 'ws',
-          pathSegments: segments,
-        );
-      }
-
-      final _ = await vmServiceConnectUri(
-        httpToWebSocketUri(remoteVmServiceUri).toString(),
-      );
-      try {
-        dds = await DartDevelopmentService.startDartDevelopmentService(
-          remoteVmServiceUri,
-        );
-        fail(
-            'DDS startup should fail if there are existing VM service clients.');
-      } on DartDevelopmentServiceException catch (e) {
-        expect(e.message,
-            'Existing VM service clients prevent DDS from taking control.');
-        expect(e.errorCode,
-            DartDevelopmentServiceException.existingDdsInstanceError);
-      }
-    });
   });
 
   test('Invalid args test', () async {
diff --git a/pkg/dds/test/sse_smoke_test.dart b/pkg/dds/test/sse_smoke_test.dart
index 823f816..9d4a9a6 100644
--- a/pkg/dds/test/sse_smoke_test.dart
+++ b/pkg/dds/test/sse_smoke_test.dart
@@ -106,7 +106,7 @@
 
     createTest(true);
     createTest(false);
-  });
+  }, timeout: Timeout.none);
 }
 
 FutureOr<shelf.Response> _faviconHandler(shelf.Request request) {
diff --git a/pkg/dds/test/web/sse_smoke_driver.dart.js b/pkg/dds/test/web/sse_smoke_driver.dart.js
index bab6993..ce5b212 100644
--- a/pkg/dds/test/web/sse_smoke_driver.dart.js
+++ b/pkg/dds/test/web/sse_smoke_driver.dart.js
@@ -1,4 +1,4 @@
-// Generated by dart2js (fast startup emitter, strong), the Dart to JavaScript compiler version: 2.9.0-edge.9d8087a399ebe62f6a93f21ec20f56d39dbcf1a2.
+// Generated by dart2js (fast startup emitter, strong), the Dart to JavaScript compiler version: 2.12.0-edge.6acb187d4a433b1a3c117ecbf85d281defdf8a82.
 // The code supports the following hooks:
 // dartPrint(message):
 //    if this function is defined it is called instead of the Dart [print]
@@ -84,7 +84,7 @@
     copyProperties(mixin.prototype, cls.prototype);
     cls.prototype.constructor = cls;
   }
-  function lazy(holder, name, getterName, initializer) {
+  function lazyOld(holder, name, getterName, initializer) {
     var uninitializedSentinel = holder;
     holder[name] = uninitializedSentinel;
     holder[getterName] = function() {
@@ -109,6 +109,34 @@
       return result;
     };
   }
+  function lazy(holder, name, getterName, initializer) {
+    var uninitializedSentinel = holder;
+    holder[name] = uninitializedSentinel;
+    holder[getterName] = function() {
+      if (holder[name] === uninitializedSentinel)
+        holder[name] = initializer();
+      holder[getterName] = function() {
+        return this[name];
+      };
+      return holder[name];
+    };
+  }
+  function lazyFinal(holder, name, getterName, initializer) {
+    var uninitializedSentinel = holder;
+    holder[name] = uninitializedSentinel;
+    holder[getterName] = function() {
+      if (holder[name] === uninitializedSentinel) {
+        var value = initializer();
+        if (holder[name] !== uninitializedSentinel)
+          H.throwLateInitializationError(name);
+        holder[name] = value;
+      }
+      holder[getterName] = function() {
+        return this[name];
+      };
+      return holder[name];
+    };
+  }
   function makeConstList(list) {
     list.immutable$list = Array;
     list.fixed$length = Array;
@@ -203,7 +231,7 @@
           return installStaticTearOff(container, getterName, requiredParameterCount, optionalParameterDefaultValues, callNames, [name], funType, applyIndex);
         };
       };
-    return {inherit: inherit, inheritMany: inheritMany, mixin: mixin, installStaticTearOff: installStaticTearOff, installInstanceTearOff: installInstanceTearOff, _instance_0u: mkInstance(0, 0, null, ["call$0"], 0), _instance_1u: mkInstance(0, 1, null, ["call$1"], 0), _instance_2u: mkInstance(0, 2, null, ["call$2"], 0), _instance_0i: mkInstance(1, 0, null, ["call$0"], 0), _instance_1i: mkInstance(1, 1, null, ["call$1"], 0), _instance_2i: mkInstance(1, 2, null, ["call$2"], 0), _static_0: mkStatic(0, null, ["call$0"], 0), _static_1: mkStatic(1, null, ["call$1"], 0), _static_2: mkStatic(2, null, ["call$2"], 0), makeConstList: makeConstList, lazy: lazy, updateHolder: updateHolder, convertToFastObject: convertToFastObject, setFunctionNamesIfNecessary: setFunctionNamesIfNecessary, updateTypes: updateTypes, setOrUpdateInterceptorsByTag: setOrUpdateInterceptorsByTag, setOrUpdateLeafTags: setOrUpdateLeafTags};
+    return {inherit: inherit, inheritMany: inheritMany, mixin: mixin, installStaticTearOff: installStaticTearOff, installInstanceTearOff: installInstanceTearOff, _instance_0u: mkInstance(0, 0, null, ["call$0"], 0), _instance_1u: mkInstance(0, 1, null, ["call$1"], 0), _instance_2u: mkInstance(0, 2, null, ["call$2"], 0), _instance_0i: mkInstance(1, 0, null, ["call$0"], 0), _instance_1i: mkInstance(1, 1, null, ["call$1"], 0), _instance_2i: mkInstance(1, 2, null, ["call$2"], 0), _static_0: mkStatic(0, null, ["call$0"], 0), _static_1: mkStatic(1, null, ["call$1"], 0), _static_2: mkStatic(2, null, ["call$2"], 0), makeConstList: makeConstList, lazy: lazy, lazyFinal: lazyFinal, lazyOld: lazyOld, updateHolder: updateHolder, convertToFastObject: convertToFastObject, setFunctionNamesIfNecessary: setFunctionNamesIfNecessary, updateTypes: updateTypes, setOrUpdateInterceptorsByTag: setOrUpdateInterceptorsByTag, setOrUpdateLeafTags: setOrUpdateLeafTags};
   }();
   function initializeDeferredHunk(hunk) {
     typesOffset = init.types.length;
@@ -220,6 +248,14 @@
   var C = {},
   H = {JS_CONST: function JS_CONST() {
     },
+    ReachabilityError$: function(_message) {
+      return new H.ReachabilityError(_message);
+    },
+    checkNotNullable: function(value, $name, $T) {
+      if (value == null)
+        throw H.wrapException(new H.NotNullableError($name, $T._eval$1("NotNullableError<0>")));
+      return value;
+    },
     MappedIterable_MappedIterable: function(iterable, $function, $S, $T) {
       if (type$.EfficientLengthIterable_dynamic._is(iterable))
         return new H.EfficientLengthMappedIterable(iterable, $function, $S._eval$1("@<0>")._bind$1($T)._eval$1("EfficientLengthMappedIterable<1,2>"));
@@ -231,6 +267,18 @@
     IterableElementError_tooFew: function() {
       return new P.StateError("Too few elements");
     },
+    LateError: function LateError(t0) {
+      this._message = t0;
+    },
+    ReachabilityError: function ReachabilityError(t0) {
+      this._message = t0;
+    },
+    nullFuture_closure: function nullFuture_closure() {
+    },
+    NotNullableError: function NotNullableError(t0, t1) {
+      this.__internal$_name = t0;
+      this.$ti = t1;
+    },
     EfficientLengthIterable: function EfficientLengthIterable() {
     },
     ListIterable: function ListIterable() {
@@ -331,8 +379,7 @@
       return null;
     },
     Primitives_objectTypeName: function(object) {
-      var t1 = H.Primitives__objectTypeNameNewRti(object);
-      return t1;
+      return H.Primitives__objectTypeNameNewRti(object);
     },
     Primitives__objectTypeNameNewRti: function(object) {
       var dispatchName, $constructor, constructorName;
@@ -355,48 +402,6 @@
       var t1 = $name !== "Object" && $name !== "";
       return t1;
     },
-    Primitives__fromCharCodeApply: function(array) {
-      var result, i, i0, chunkEnd,
-        end = array.length;
-      if (end <= 500)
-        return String.fromCharCode.apply(null, array);
-      for (result = "", i = 0; i < end; i = i0) {
-        i0 = i + 500;
-        chunkEnd = i0 < end ? i0 : end;
-        result += String.fromCharCode.apply(null, array.slice(i, chunkEnd));
-      }
-      return result;
-    },
-    Primitives_stringFromCodePoints: function(codePoints) {
-      var t1, _i, i,
-        a = H.setRuntimeTypeInfo([], type$.JSArray_int);
-      for (t1 = codePoints.length, _i = 0; _i < codePoints.length; codePoints.length === t1 || (0, H.throwConcurrentModificationError)(codePoints), ++_i) {
-        i = codePoints[_i];
-        if (!H._isInt(i))
-          throw H.wrapException(H.argumentErrorValue(i));
-        if (i <= 65535)
-          C.JSArray_methods.add$1(a, i);
-        else if (i <= 1114111) {
-          C.JSArray_methods.add$1(a, 55296 + (C.JSInt_methods._shrOtherPositive$1(i - 65536, 10) & 1023));
-          C.JSArray_methods.add$1(a, 56320 + (i & 1023));
-        } else
-          throw H.wrapException(H.argumentErrorValue(i));
-      }
-      return H.Primitives__fromCharCodeApply(a);
-    },
-    Primitives_stringFromCharCodes: function(charCodes) {
-      var t1, _i, i;
-      for (t1 = charCodes.length, _i = 0; _i < t1; ++_i) {
-        i = charCodes[_i];
-        if (!H._isInt(i))
-          throw H.wrapException(H.argumentErrorValue(i));
-        if (i < 0)
-          throw H.wrapException(H.argumentErrorValue(i));
-        if (i > 65535)
-          return H.Primitives_stringFromCodePoints(charCodes);
-      }
-      return H.Primitives__fromCharCodeApply(charCodes);
-    },
     Primitives_stringFromNativeUint8List: function(charCodes, start, end) {
       var i, result, i0, chunkEnd;
       if (end <= 500 && start === 0 && end === charCodes.length)
@@ -414,7 +419,7 @@
         return String.fromCharCode(charCode);
       if (charCode <= 1114111) {
         bits = charCode - 65536;
-        return String.fromCharCode((55296 | C.JSInt_methods._shrOtherPositive$1(bits, 10)) >>> 0, 56320 | bits & 1023);
+        return String.fromCharCode((C.JSInt_methods._shrOtherPositive$1(bits, 10) | 55296) >>> 0, bits & 1023 | 56320);
       }
       throw H.wrapException(P.RangeError$range(charCode, 0, 1114111, null, null));
     },
@@ -493,7 +498,7 @@
     Primitives__genericApplyFunction2: function($function, positionalArguments, namedArguments) {
       var $arguments, argumentCount, requiredParameterCount, defaultValuesClosure, t1, defaultValues, interceptor, jsFunction, keys, _i, defaultValue, used, key;
       if (positionalArguments != null)
-        $arguments = positionalArguments instanceof Array ? positionalArguments : P.List_List$from(positionalArguments, true, type$.dynamic);
+        $arguments = positionalArguments instanceof Array ? positionalArguments : P.List_List$from(positionalArguments, type$.dynamic);
       else
         $arguments = [];
       argumentCount = $arguments.length;
@@ -803,7 +808,7 @@
       return $function;
     },
     Closure_fromTearOff: function(receiver, functions, applyTrampolineIndex, reflectionInfo, isStatic, isIntercepted, propertyName) {
-      var $constructor, t1, trampoline, signatureFunction, applyTrampoline, i, stub, stubCallName,
+      var $constructor, t1, trampoline, applyTrampoline, i, stub, stubCallName,
         $function = functions[0],
         callName = $function.$callName,
         $prototype = isStatic ? Object.create(new H.StaticClosure().constructor.prototype) : Object.create(new H.BoundClosure(null, null, null, "").constructor.prototype);
@@ -829,8 +834,7 @@
         $prototype.$static_name = propertyName;
         trampoline = $function;
       }
-      signatureFunction = H.Closure__computeSignatureFunctionNewRti(reflectionInfo, isStatic, isIntercepted);
-      $prototype.$signature = signatureFunction;
+      $prototype.$signature = H.Closure__computeSignatureFunctionNewRti(reflectionInfo, isStatic, isIntercepted);
       $prototype[callName] = trampoline;
       for (applyTrampoline = trampoline, i = 1; i < functions.length; ++i) {
         stub = functions[i];
@@ -948,7 +952,7 @@
         getReceiver = H.BoundClosure_receiverOf;
       switch (isSuperCall ? -1 : arity) {
         case 0:
-          throw H.wrapException(H.RuntimeError$("Intercepted function with no arguments."));
+          throw H.wrapException(new H.RuntimeError("Intercepted function with no arguments."));
         case 1:
           return function(n, s, r) {
             return function() {
@@ -1046,7 +1050,7 @@
     BoundClosure_computeFieldNamed: function(fieldName) {
       var t1, i, $name,
         template = new H.BoundClosure("self", "target", "receiver", "name"),
-        names = J.JSArray_markFixedList(Object.getOwnPropertyNames(template), type$.dynamic);
+        names = J.JSArray_markFixedList(Object.getOwnPropertyNames(template), type$.nullable_Object);
       for (t1 = names.length, i = 0; i < t1; ++i) {
         $name = names[i];
         if (template[$name] === fieldName)
@@ -1065,42 +1069,11 @@
     throwCyclicInit: function(staticName) {
       throw H.wrapException(new P.CyclicInitializationError(staticName));
     },
-    RuntimeError$: function(message) {
-      return new H.RuntimeError(message);
-    },
     getIsolateAffinityTag: function($name) {
       return init.getIsolateTag($name);
     },
-    setRuntimeTypeInfo: function(target, rti) {
-      target[init.arrayRti] = rti;
-      return target;
-    },
-    getRuntimeTypeInfo: function(target) {
-      if (target == null)
-        return null;
-      return target.$ti;
-    },
-    getRuntimeTypeArguments: function(interceptor, object, substitutionName) {
-      return H.substitute(interceptor["$as" + H.S(substitutionName)], H.getRuntimeTypeInfo(object));
-    },
-    getRuntimeType: function(object) {
-      var rti = object instanceof H.Closure ? H.closureFunctionType(object) : null;
-      return H.createRuntimeType(rti == null ? H.instanceType(object) : rti);
-    },
-    substitute: function(substitution, $arguments) {
-      if (substitution == null)
-        return $arguments;
-      substitution = substitution.apply(null, $arguments);
-      if (substitution == null)
-        return null;
-      if (Array.isArray(substitution))
-        return substitution;
-      if (typeof substitution == "function")
-        return substitution.apply(null, $arguments);
-      return $arguments;
-    },
-    computeSignature: function(signature, context, contextName) {
-      return signature.apply(context, H.getRuntimeTypeArguments(J.getInterceptor$(context), context, contextName));
+    throwLateInitializationError: function($name) {
+      return H.throwExpression(new H.LateError($name));
     },
     defineProperty: function(obj, property, value) {
       Object.defineProperty(obj, property, {value: value, enumerable: false, writable: true, configurable: true});
@@ -1293,16 +1266,16 @@
       _._receiver = t5;
     },
     NullError: function NullError(t0, t1) {
-      this._message = t0;
+      this.__js_helper$_message = t0;
       this._method = t1;
     },
     JsNoSuchMethodError: function JsNoSuchMethodError(t0, t1, t2) {
-      this._message = t0;
+      this.__js_helper$_message = t0;
       this._method = t1;
       this._receiver = t2;
     },
     UnknownJsTypeError: function UnknownJsTypeError(t0) {
-      this._message = t0;
+      this.__js_helper$_message = t0;
     },
     NullThrownFromJavaScriptException: function NullThrownFromJavaScriptException(t0) {
       this._irritant = t0;
@@ -1567,6 +1540,10 @@
       result._named = substitutedNamed;
       return result;
     },
+    setRuntimeTypeInfo: function(target, rti) {
+      target[init.arrayRti] = rti;
+      return target;
+    },
     closureFunctionType: function(closure) {
       var signature = closure.$signature;
       if (signature != null) {
@@ -1634,6 +1611,10 @@
       }
       return type;
     },
+    getRuntimeType: function(object) {
+      var rti = object instanceof H.Closure ? H.closureFunctionType(object) : null;
+      return H.createRuntimeType(rti == null ? H.instanceType(object) : rti);
+    },
     createRuntimeType: function(rti) {
       var recipe, starErasedRecipe, starErasedRti,
         type = rti._cachedRuntimeType;
@@ -1709,16 +1690,22 @@
       return testRti._as(object);
     },
     _nullIs: function(testRti) {
-      var t2,
-        t1 = testRti._kind;
+      var t1,
+        kind = testRti._kind;
       if (!H.isStrongTopType(testRti))
         if (!(testRti === type$.legacy_Object))
-          t2 = testRti === type$.Object;
+          if (!(testRti === type$.legacy_Never))
+            if (kind !== 7)
+              t1 = kind === 8 && H._nullIs(testRti._primary) || testRti === type$.Null || testRti === type$.JSNull;
+            else
+              t1 = true;
+          else
+            t1 = true;
         else
-          t2 = true;
+          t1 = true;
       else
-        t2 = true;
-      return t2 || testRti === type$.legacy_Never || t1 === 7 || testRti === type$.Null || testRti === type$.JSNull;
+        t1 = true;
+      return t1;
     },
     _generalIsTestImplementation: function(object) {
       var testRti = this;
@@ -1732,8 +1719,10 @@
       return this._primary._is(object);
     },
     _isTestViaProperty: function(object) {
-      var t1 = this,
-        tag = t1._specializedTestResource;
+      var tag, testRti = this;
+      if (object == null)
+        return H._nullIs(testRti);
+      tag = testRti._specializedTestResource;
       if (object instanceof P.Object)
         return !!object[tag];
       return !!J.getInterceptor$(object)[tag];
@@ -1784,20 +1773,26 @@
       return true === object || false === object;
     },
     _asBool: function(object) {
-      if (true === object || false === object)
-        return object;
+      if (true === object)
+        return true;
+      if (false === object)
+        return false;
       throw H.wrapException(H._TypeError__TypeError$forType(object, "bool"));
     },
     _asBoolS: function(object) {
-      if (true === object || false === object)
-        return object;
+      if (true === object)
+        return true;
+      if (false === object)
+        return false;
       if (object == null)
         return object;
       throw H.wrapException(H._TypeError__TypeError$forType(object, "bool"));
     },
     _asBoolQ: function(object) {
-      if (true === object || false === object)
-        return object;
+      if (true === object)
+        return true;
+      if (false === object)
+        return false;
       if (object == null)
         return object;
       throw H.wrapException(H._TypeError__TypeError$forType(object, "bool?"));
@@ -2672,7 +2667,7 @@
       return false;
     },
     _isFunctionSubtype: function(universe, s, sEnv, t, tEnv) {
-      var sParameters, tParameters, sRequiredPositional, tRequiredPositional, sRequiredPositionalLength, tRequiredPositionalLength, requiredPositionalDelta, sOptionalPositional, tOptionalPositional, sOptionalPositionalLength, tOptionalPositionalLength, i, t1, sNamed, tNamed, sNamedLength, tNamedLength, sIndex, tIndex, tName, sName, sIsRequired;
+      var sParameters, tParameters, sRequiredPositional, tRequiredPositional, sRequiredPositionalLength, tRequiredPositionalLength, requiredPositionalDelta, sOptionalPositional, tOptionalPositional, sOptionalPositionalLength, tOptionalPositionalLength, i, t1, sNamed, tNamed, sNamedLength, tNamedLength, sIndex, tIndex, tName, sName;
       if (!H._isSubtype(universe, s._primary, sEnv, t._primary, tEnv))
         return false;
       sParameters = s._rest;
@@ -2718,26 +2713,14 @@
           sIndex += 3;
           if (tName < sName)
             return false;
-          sIsRequired = sNamed[sIndex - 2];
-          if (sName < tName) {
-            if (sIsRequired)
-              return false;
+          if (sName < tName)
             continue;
-          }
-          t1 = tNamed[tIndex + 1];
-          if (sIsRequired && !t1)
-            return false;
           t1 = sNamed[sIndex - 1];
           if (!H._isSubtype(universe, tNamed[tIndex + 2], tEnv, t1, sEnv))
             return false;
           break;
         }
       }
-      for (; sIndex < sNamedLength;) {
-        if (sNamed[sIndex + 1])
-          return false;
-        sIndex += 3;
-      }
       return true;
     },
     _isInterfaceSubtype: function(universe, s, sEnv, t, tEnv) {
@@ -3072,6 +3055,9 @@
     $shl$n: function(receiver, a0) {
       return J.getInterceptor$n(receiver).$shl(receiver, a0);
     },
+    $shr$n: function(receiver, a0) {
+      return J.getInterceptor$n(receiver).$shr(receiver, a0);
+    },
     $sub$n: function(receiver, a0) {
       if (typeof receiver == "number" && typeof a0 == "number")
         return receiver - a0;
@@ -3086,6 +3072,9 @@
     elementAt$1$ax: function(receiver, a0) {
       return J.getInterceptor$ax(receiver).elementAt$1(receiver, a0);
     },
+    forEach$1$ax: function(receiver, a0) {
+      return J.getInterceptor$ax(receiver).forEach$1(receiver, a0);
+    },
     map$1$ax: function(receiver, a0) {
       return J.getInterceptor$ax(receiver).map$1(receiver, a0);
     },
@@ -3107,8 +3096,6 @@
     },
     JSNull: function JSNull() {
     },
-    JSObject: function JSObject() {
-    },
     JavaScriptObject: function JavaScriptObject() {
     },
     PlainJavaScriptObject: function PlainJavaScriptObject() {
@@ -3221,25 +3208,7 @@
             }
         };
       }($function, 1);
-      return $.Zone__current.registerBinaryCallback$3$1(new P._wrapJsFunctionForAsync_closure($protected), type$.Null, type$.int, type$.dynamic);
-    },
-    _Future$zoneValue: function(value, _zone, $T) {
-      var t1 = new P._Future(_zone, $T._eval$1("_Future<0>"));
-      $T._as(value);
-      t1._state = 4;
-      t1._resultOrListeners = value;
-      return t1;
-    },
-    _Future__chainForeignFuture: function(source, target) {
-      var e, s, exception;
-      target._state = 1;
-      try {
-        source.then$1$2$onError(new P._Future__chainForeignFuture_closure(target), new P._Future__chainForeignFuture_closure0(target), type$.Null);
-      } catch (exception) {
-        e = H.unwrapException(exception);
-        s = H.getTraceFromException(exception);
-        P.scheduleMicrotask(new P._Future__chainForeignFuture_closure1(target, e, s));
-      }
+      return $.Zone__current.registerBinaryCallback$3$1(new P._wrapJsFunctionForAsync_closure($protected), type$.void, type$.int, type$.dynamic);
     },
     _Future__chainCoreFuture: function(source, target) {
       var t1, t2, listeners;
@@ -3317,17 +3286,26 @@
             $.Zone__current = oldZone;
           t1 = _box_0.listenerValueOrError;
           if (t4._is(t1)) {
+            t5 = _box_0.listener.$ti;
+            t5 = t5._eval$1("Future<2>")._is(t1) || !t5._rest[1]._is(t1);
+          } else
+            t5 = false;
+          if (t5) {
+            t4._as(t1);
             result = _box_0.listener.result;
-            if (t1._state >= 4) {
-              current = t3._as(result._resultOrListeners);
-              result._resultOrListeners = null;
-              listeners = result._reverseListeners$1(current);
-              result._state = t1._state;
-              result._resultOrListeners = t1._resultOrListeners;
-              _box_1.source = t1;
-              continue;
-            } else
-              P._Future__chainCoreFuture(t1, result);
+            if (t1 instanceof P._Future)
+              if (t1._state >= 4) {
+                current = t3._as(result._resultOrListeners);
+                result._resultOrListeners = null;
+                listeners = result._reverseListeners$1(current);
+                result._state = t1._state;
+                result._resultOrListeners = t1._resultOrListeners;
+                _box_1.source = t1;
+                continue;
+              } else
+                P._Future__chainCoreFuture(t1, result);
+            else
+              result._chainForeignFuture$1(t1);
             return;
           }
         }
@@ -3357,7 +3335,7 @@
       t1 = type$.dynamic_Function_Object;
       if (t1._is(errorHandler))
         return t1._as(errorHandler);
-      throw H.wrapException(P.ArgumentError$value(errorHandler, "onError", "Error handler must accept one Object or one Object and a StackTrace as arguments, and return a a valid result"));
+      throw H.wrapException(P.ArgumentError$value(errorHandler, "onError", "Error handler must accept one Object or one Object and a StackTrace as arguments, and return a valid result"));
     },
     _microtaskLoop: function() {
       var entry, next;
@@ -3422,8 +3400,7 @@
       P._rootScheduleMicrotask(_null, _null, currentZone, type$.void_Function._as(currentZone.bindCallbackGuarded$1(callback)));
     },
     StreamIterator_StreamIterator: function(stream, $T) {
-      P.ArgumentError_checkNotNull(stream, "stream", $T._eval$1("Stream<0>"));
-      return new P._StreamIterator(stream, $T._eval$1("_StreamIterator<0>"));
+      return new P._StreamIterator(H.checkNotNullable(stream, "stream", type$.Object), $T._eval$1("_StreamIterator<0>"));
     },
     StreamController_StreamController: function($T) {
       var _null = null;
@@ -3436,6 +3413,13 @@
     _runGuarded: function(notificationHandler) {
       return;
     },
+    _ControllerSubscription$: function(_controller, onData, onError, onDone, cancelOnError, $T) {
+      var t1 = $.Zone__current,
+        t2 = cancelOnError ? 1 : 0,
+        t3 = P._BufferingStreamSubscription__registerDataHandler(t1, onData, $T),
+        t4 = P._BufferingStreamSubscription__registerErrorHandler(t1, onError);
+      return new P._ControllerSubscription(_controller, t3, t4, type$.void_Function._as(onDone), t1, t2, $T._eval$1("_ControllerSubscription<0>"));
+    },
     _BufferingStreamSubscription__registerDataHandler: function(zone, handleData, $T) {
       var t1 = handleData == null ? P.async___nullDataHandler$closure() : handleData;
       return type$.$env_1_1_void._bind$1($T)._eval$1("1(2)")._as(t1);
@@ -3449,9 +3433,6 @@
         return type$.dynamic_Function_Object._as(handleError);
       throw H.wrapException(P.ArgumentError$("handleError callback must take either an Object (the error), or both an Object (the error) and a StackTrace."));
     },
-    _BufferingStreamSubscription__registerDoneHandler: function(zone, handleDone) {
-      return type$.void_Function._as(handleDone);
-    },
     _nullDataHandler: function(value) {
     },
     _nullErrorHandler: function(error, stackTrace) {
@@ -3471,9 +3452,8 @@
       return P.Timer__createTimer(duration, type$.void_Function._as(t1.bindCallbackGuarded$1(callback)));
     },
     AsyncError$: function(error, stackTrace) {
-      var t1 = stackTrace == null ? P.AsyncError_defaultStackTrace(error) : stackTrace;
-      P.ArgumentError_checkNotNull(error, "error", type$.Object);
-      return new P.AsyncError(error, t1);
+      var t1 = H.checkNotNullable(error, "error", type$.Object);
+      return new P.AsyncError(t1, stackTrace == null ? P.AsyncError_defaultStackTrace(error) : stackTrace);
     },
     AsyncError_defaultStackTrace: function(error) {
       var stackTrace;
@@ -3607,10 +3587,6 @@
       _._doneFuture = _._addStreamState = _._lastSubscription = _._firstSubscription = null;
       _.$ti = t2;
     },
-    Future: function Future() {
-    },
-    Completer: function Completer() {
-    },
     _Completer: function _Completer() {
     },
     _AsyncCompleter: function _AsyncCompleter(t0, t1) {
@@ -3642,13 +3618,13 @@
       this.$this = t1;
     },
     _Future__chainForeignFuture_closure: function _Future__chainForeignFuture_closure(t0) {
-      this.target = t0;
+      this.$this = t0;
     },
     _Future__chainForeignFuture_closure0: function _Future__chainForeignFuture_closure0(t0) {
-      this.target = t0;
+      this.$this = t0;
     },
     _Future__chainForeignFuture_closure1: function _Future__chainForeignFuture_closure1(t0, t1, t2) {
-      this.target = t0;
+      this.$this = t0;
       this.e = t1;
       this.s = t2;
     },
@@ -3707,8 +3683,6 @@
     },
     StreamTransformerBase: function StreamTransformerBase() {
     },
-    StreamController: function StreamController() {
-    },
     _StreamController: function _StreamController() {
     },
     _StreamController__subscribe_closure: function _StreamController__subscribe_closure(t0) {
@@ -3798,7 +3772,7 @@
       var _ = this;
       _._async$_subscription = null;
       _._stateData = t0;
-      _._isPaused = false;
+      _._async$_hasValue = false;
       _.$ti = t1;
     },
     _cancelAndValue_closure: function _cancelAndValue_closure(t0, t1) {
@@ -4069,10 +4043,14 @@
       _._collection$_current = null;
       _.$ti = t4;
     },
+    SetMixin: function SetMixin() {
+    },
     _SetBase: function _SetBase() {
     },
     _UnmodifiableMapView_MapView__UnmodifiableMapMixin: function _UnmodifiableMapView_MapView__UnmodifiableMapMixin() {
     },
+    __SetBase_Object_SetMixin: function __SetBase_Object_SetMixin() {
+    },
     _parseJson: function(source, reviver) {
       var parsed, e, exception, t1;
       if (typeof source != "string")
@@ -4139,10 +4117,13 @@
     _defaultToEncodable: function(object) {
       return object.toJson$0();
     },
+    _JsonStringStringifier$: function(_sink, _toEncodable) {
+      return new P._JsonStringStringifier(_sink, [], P.convert___defaultToEncodable$closure());
+    },
     _JsonStringStringifier_stringify: function(object, toEncodable, indent) {
       var t1,
         output = new P.StringBuffer(""),
-        stringifier = new P._JsonStringStringifier(output, [], P.convert___defaultToEncodable$closure());
+        stringifier = P._JsonStringStringifier$(output, toEncodable);
       stringifier.writeObject$1(object);
       t1 = output._contents;
       return t1.charCodeAt(0) == 0 ? t1 : t1;
@@ -4175,9 +4156,9 @@
     _JsonMapKeyIterable: function _JsonMapKeyIterable(t0) {
       this._parent = t0;
     },
-    Utf8Decoder_closure: function Utf8Decoder_closure() {
+    Utf8Decoder__decoder_closure: function Utf8Decoder__decoder_closure() {
     },
-    Utf8Decoder_closure0: function Utf8Decoder_closure0() {
+    Utf8Decoder__decoderNonfatal_closure: function Utf8Decoder__decoderNonfatal_closure() {
     },
     Codec: function Codec() {
     },
@@ -4245,22 +4226,28 @@
           result[i] = fill;
       return result;
     },
-    List_List$from: function(elements, growable, $E) {
+    List_List$from: function(elements, $E) {
       var t1,
         list = H.setRuntimeTypeInfo([], $E._eval$1("JSArray<0>"));
       for (t1 = J.get$iterator$ax(elements); t1.moveNext$0();)
         C.JSArray_methods.add$1(list, $E._as(t1.get$current()));
       return list;
     },
+    List_List$of: function(elements, growable, $E) {
+      var t1 = P.List_List$_of(elements, $E);
+      return t1;
+    },
+    List_List$_of: function(elements, $E) {
+      var list, t1;
+      if (Array.isArray(elements))
+        return H.setRuntimeTypeInfo(elements.slice(0), $E._eval$1("JSArray<0>"));
+      list = H.setRuntimeTypeInfo([], $E._eval$1("JSArray<0>"));
+      for (t1 = J.get$iterator$ax(elements); t1.moveNext$0();)
+        C.JSArray_methods.add$1(list, t1.get$current());
+      return list;
+    },
     String_String$fromCharCodes: function(charCodes, start, end) {
-      var array, len, t1;
-      if (Array.isArray(charCodes)) {
-        array = charCodes;
-        len = array.length;
-        end = P.RangeError_checkValidRange(start, end, len);
-        return H.Primitives_stringFromCharCodes(start > 0 || end < len ? array.slice(start, end) : array);
-      }
-      t1 = H.Primitives_stringFromNativeUint8List(charCodes, start, P.RangeError_checkValidRange(start, end, charCodes.length));
+      var t1 = H.Primitives_stringFromNativeUint8List(charCodes, start, P.RangeError_checkValidRange(start, end, charCodes.length));
       return t1;
     },
     StringBuffer__writeAll: function(string, objects, separator) {
@@ -4332,11 +4319,6 @@
     ArgumentError$value: function(value, $name, message) {
       return new P.ArgumentError(true, value, $name, message);
     },
-    ArgumentError_checkNotNull: function(argument, $name, $T) {
-      if (argument == null)
-        throw H.wrapException(new P.ArgumentError(false, null, $name, "Must not be null"));
-      return argument;
-    },
     RangeError$: function(message) {
       var _null = null;
       return new P.RangeError(_null, _null, false, _null, _null, message);
@@ -4391,14 +4373,10 @@
       this._box_0 = t0;
       this.sb = t1;
     },
-    bool: function bool() {
-    },
     DateTime: function DateTime(t0, t1) {
       this._value = t0;
       this.isUtc = t1;
     },
-    double: function double() {
-    },
     Duration: function Duration(t0) {
       this._duration = t0;
     },
@@ -4411,6 +4389,8 @@
     AssertionError: function AssertionError(t0) {
       this.message = t0;
     },
+    TypeError: function TypeError() {
+    },
     NullThrownError: function NullThrownError() {
     },
     ArgumentError: function ArgumentError(t0, t1, t2, t3) {
@@ -4471,36 +4451,33 @@
       this.source = t1;
       this.offset = t2;
     },
-    Function: function Function() {
-    },
-    int: function int() {
-    },
     Iterable: function Iterable() {
     },
     Iterator: function Iterator() {
     },
-    List: function [] {
-    },
-    Map: function Map() {
-    },
-    MapEntry: function MapEntry() {
-    },
     Null: function Null() {
     },
-    num: function num() {
-    },
     Object: function Object() {
     },
-    StackTrace: function StackTrace() {
-    },
     _StringStackTrace: function _StringStackTrace() {
     },
-    String: function String() {
-    },
     StringBuffer: function StringBuffer(t0) {
       this._contents = t0;
     },
-    Symbol0: function Symbol0() {
+    _convertDartToNative_Value: function(value) {
+      var array;
+      if (value == null)
+        return value;
+      if (typeof value == "string" || typeof value == "number" || H._isBool(value))
+        return value;
+      if (type$.Map_dynamic_dynamic._is(value))
+        return P.convertDartToNative_Dictionary(value);
+      if (type$.List_dynamic._is(value)) {
+        array = [];
+        J.forEach$1$ax(value, new P._convertDartToNative_Value_closure(array));
+        value = array;
+      }
+      return value;
     },
     convertDartToNative_Dictionary: function(dict) {
       var object = {};
@@ -4513,6 +4490,9 @@
       this._box_0 = t0;
       this.$this = t1;
     },
+    _convertDartToNative_Value_closure: function _convertDartToNative_Value_closure(t0) {
+      this.array = t0;
+    },
     convertDartToNative_Dictionary_closure: function convertDartToNative_Dictionary_closure(t0) {
       this.object = t0;
     },
@@ -4535,28 +4515,6 @@
       this.completer = t0;
     },
     _JSRandom: function _JSRandom() {
-    },
-    ByteBuffer: function ByteBuffer() {
-    },
-    ByteData: function ByteData() {
-    },
-    Int8List: function Int8List() {
-    },
-    Uint8List: function Uint8List() {
-    },
-    Uint8ClampedList: function Uint8ClampedList() {
-    },
-    Int16List: function Int16List() {
-    },
-    Uint16List: function Uint16List() {
-    },
-    Int32List: function Int32List() {
-    },
-    Uint32List: function Uint32List() {
-    },
-    Float32List: function Float32List() {
-    },
-    Float64List: function Float64List() {
     }
   },
   W = {
@@ -4570,7 +4528,7 @@
         completer = new P._AsyncCompleter(t1, type$._AsyncCompleter_HttpRequest),
         xhr = new XMLHttpRequest();
       C.HttpRequest_methods.open$3$async(xhr, method, url, true);
-      xhr.withCredentials = true;
+      C.HttpRequest_methods.set$withCredentials(xhr, true);
       t2 = type$.nullable_void_Function_legacy_ProgressEvent;
       t3 = t2._as(new W.HttpRequest_request_closure(xhr, completer));
       type$.nullable_void_Function._as(null);
@@ -4643,66 +4601,6 @@
       this.error = t0;
       this.stackTrace = t1;
     }},
-  E = {Result: function Result() {
-    },
-    main: function() {
-      var $async$goto = 0,
-        $async$completer = P._makeAsyncAwaitCompleter(type$.void),
-        ddsChannel, vmService, id, message, channel, t1, t2, t3, $async$temp1, $async$temp2, $async$temp3;
-      var $async$main = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) {
-        if ($async$errorCode === 1)
-          return P._asyncRethrow($async$result, $async$completer);
-        while (true)
-          switch ($async$goto) {
-            case 0:
-              // Function start
-              channel = M.SseClient$("/test");
-              t1 = channel._incomingController;
-              t2 = new Q.QueueList(type$.QueueList_legacy_Result_legacy_String);
-              t3 = new Array(8);
-              t3.fixed$length = Array;
-              t2.set$_table(H.setRuntimeTypeInfo(t3, type$.JSArray_legacy_Result_legacy_String));
-              $async$temp1 = M;
-              $async$goto = 2;
-              return P._asyncAwait(new G.StreamQueue(new P._ControllerStream(t1, H._instanceType(t1)._eval$1("_ControllerStream<1>")), t2, new P.ListQueue(P.List_List$filled(P.ListQueue__calculateCapacity(null), null, false, type$.nullable__EventRequest_dynamic), type$.ListQueue_legacy__EventRequest_dynamic), type$.StreamQueue_legacy_String).get$next(), $async$main);
-            case 2:
-              // returning from await.
-              ddsChannel = $async$temp1.SseClient$($async$result);
-              t2 = new W._EventStream(ddsChannel._eventSource, "open", false, type$._EventStream_legacy_Event);
-              $async$goto = 3;
-              return P._asyncAwait(t2.get$first(t2), $async$main);
-            case 3:
-              // returning from await.
-              t2 = ddsChannel._incomingController;
-              vmService = Q.VmService$(new P._ControllerStream(t2, H._instanceType(t2)._eval$1("_ControllerStream<1>")), new E.main_closure(ddsChannel));
-              id = "" + ++vmService._id;
-              t2 = new P._Future($.Zone__current, type$._Future_legacy_Version);
-              vmService._completers.$indexSet(0, id, new P._AsyncCompleter(t2, type$._AsyncCompleter_legacy_Version));
-              vmService._methodCalls.$indexSet(0, id, "getVersion");
-              t1 = type$.dynamic;
-              message = C.C_JsonCodec.encode$2$toEncodable(P.LinkedHashMap_LinkedHashMap$_literal(["jsonrpc", "2.0", "id", id, "method", "getVersion", "params", C.Map_empty], t1, t1), null);
-              vmService._onSend.add$1(0, message);
-              vmService._writeMessage.call$1(message);
-              t1 = channel._outgoingController;
-              $async$temp1 = t1;
-              $async$temp2 = H._instanceType(t1)._precomputed1;
-              $async$temp3 = C.C_JsonCodec;
-              $async$goto = 4;
-              return P._asyncAwait(t2, $async$main);
-            case 4:
-              // returning from await.
-              $async$temp1.add$1(0, $async$temp2._as($async$temp3.encode$1($async$result.json)));
-              ddsChannel.close$0(0);
-              // implicit return
-              return P._asyncReturn(null, $async$completer);
-          }
-      });
-      return P._asyncStartSync($async$main, $async$completer);
-    },
-    main_closure: function main_closure(t0) {
-      this.ddsChannel = t0;
-    }
-  },
   F = {ValueResult: function ValueResult(t0, t1) {
       this.value = t0;
       this.$ti = t1;
@@ -4736,7 +4634,6 @@
       this.$this = t0;
     }, StreamQueue__ensureListening_closure0: function StreamQueue__ensureListening_closure0(t0) {
       this.$this = t0;
-    }, _EventRequest: function _EventRequest() {
     }, _NextRequest: function _NextRequest(t0, t1) {
       this._completer = t0;
       this.$ti = t1;
@@ -4754,7 +4651,7 @@
         return _null;
       if (type$.legacy_List_dynamic._is(json)) {
         t1 = J.map$1$1$ax(json, new Q.createServiceObject_closure(expectedTypes), type$.legacy_Object);
-        return P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E"));
+        return P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E"));
       } else if (type$.legacy_Map_dynamic_dynamic._is(json)) {
         type = H._asStringS(json.$index(0, "type"));
         if (type == null)
@@ -4777,7 +4674,7 @@
         return null;
       if (type$.legacy_List_dynamic._is(json)) {
         t1 = J.map$1$1$ax(json, new Q._createSpecificObject_closure(creator), type$.dynamic);
-        return P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E"));
+        return P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E"));
       } else if (type$.legacy_Map_dynamic_dynamic._is(json)) {
         t1 = P.LinkedHashMap_LinkedHashMap$_empty(type$.legacy_String, type$.dynamic);
         for (t2 = json.get$keys(), t2 = t2.get$iterator(t2); t2.moveNext$0();) {
@@ -4812,7 +4709,7 @@
       t2 = Q.createServiceObject(json.$index(0, "members"), C.List_ClassHeapStats);
       if (t2 == null)
         t2 = [];
-      t1.set$members(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_ClassHeapStats));
+      t1.set$members(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_ClassHeapStats));
       t1.memoryUsage = type$.legacy_MemoryUsage._as(Q.createServiceObject(json.$index(0, "memoryUsage"), C.List_MemoryUsage));
       t1.dateLastAccumulatorReset = H._asIntS(typeof json.$index(0, _s24_) == "string" ? P.int_parse(H._asStringS(json.$index(0, _s24_))) : json.$index(0, _s24_));
       t1.dateLastServiceGC = H._asIntS(typeof json.$index(0, _s17_) == "string" ? P.int_parse(H._asStringS(json.$index(0, _s17_))) : json.$index(0, _s17_));
@@ -4879,14 +4776,14 @@
       if (t4 == null)
         t4 = [];
       t5 = type$.Iterable_dynamic;
-      t1.set$interfaces(P.List_List$from(t5._as(t4), true, t3));
+      t1.set$interfaces(P.List_List$from(t5._as(t4), t3));
       t1.mixin = t3._as(Q.createServiceObject(json.$index(0, "mixin"), C.List_InstanceRef));
       t3 = Q.createServiceObject(json.$index(0, "fields"), C.List_FieldRef);
-      t1.set$fields(P.List_List$from(t5._as(t3 == null ? [] : t3), true, type$.legacy_FieldRef));
+      t1.set$fields(P.List_List$from(t5._as(t3 == null ? [] : t3), type$.legacy_FieldRef));
       t3 = Q.createServiceObject(json.$index(0, "functions"), C.List_FuncRef);
-      t1.set$functions(P.List_List$from(t5._as(t3 == null ? [] : t3), true, type$.legacy_FuncRef));
+      t1.set$functions(P.List_List$from(t5._as(t3 == null ? [] : t3), type$.legacy_FuncRef));
       t3 = Q.createServiceObject(json.$index(0, "subclasses"), C.List_ClassRef);
-      t1.set$subclasses(P.List_List$from(t5._as(t3 == null ? [] : t3), true, t2));
+      t1.set$subclasses(P.List_List$from(t5._as(t3 == null ? [] : t3), t2));
       return t1;
     },
     ClassHeapStats_parse: function(json) {
@@ -4909,7 +4806,7 @@
       t2 = Q.createServiceObject(json.$index(0, "classes"), C.List_ClassRef);
       if (t2 == null)
         t2 = [];
-      t1.set$classes(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_ClassRef));
+      t1.set$classes(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_ClassRef));
       return t1;
     },
     ClientName_parse: function(json) {
@@ -4960,7 +4857,7 @@
       t2 = Q.createServiceObject(json.$index(0, "variables"), C.List_ContextElement);
       if (t2 == null)
         t2 = [];
-      t1.set$variables(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_ContextElement));
+      t1.set$variables(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_ContextElement));
       return t1;
     },
     ContextElement_parse: function(json) {
@@ -4984,9 +4881,9 @@
       if (t2 == null)
         t2 = [];
       t3 = type$.Iterable_dynamic;
-      t1.set$functions(P.List_List$from(t3._as(t2), true, type$.legacy_ProfileFunction));
+      t1.set$functions(P.List_List$from(t3._as(t2), type$.legacy_ProfileFunction));
       t2 = Q.createServiceObject(json.$index(0, "samples"), C.List_CpuSample);
-      t1.set$samples(P.List_List$from(t3._as(t2 == null ? [] : t2), true, type$.legacy_CpuSample));
+      t1.set$samples(P.List_List$from(t3._as(t2 == null ? [] : t2), type$.legacy_CpuSample));
       return t1;
     },
     CpuSample_parse: function(json) {
@@ -4998,7 +4895,7 @@
       t1.vmTag = H._asStringS(json.$index(0, "vmTag"));
       t1.userTag = H._asStringS(json.$index(0, "userTag"));
       t1.truncated = H._asBoolS(json.$index(0, "truncated"));
-      t1.set$stack(P.List_List$from(type$.Iterable_dynamic._as(json.$index(0, "stack")), true, type$.legacy_int));
+      t1.set$stack(P.List_List$from(type$.Iterable_dynamic._as(json.$index(0, "stack")), type$.legacy_int));
       return t1;
     },
     ErrorRef_parse: function(json) {
@@ -5038,7 +4935,7 @@
       t1.timestamp = H._asIntS(json.$index(0, "timestamp"));
       t2 = type$.legacy_Breakpoint;
       t1.breakpoint = t2._as(Q.createServiceObject(json.$index(0, "breakpoint"), C.List_Breakpoint));
-      t1.set$pauseBreakpoints(json.$index(0, _s16_) == null ? _null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, _s16_), C.List_Breakpoint)), true, t2));
+      t1.set$pauseBreakpoints(json.$index(0, _s16_) == null ? _null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, _s16_), C.List_Breakpoint)), t2));
       t1.topFrame = type$.legacy_Frame._as(Q.createServiceObject(json.$index(0, "topFrame"), C.List_Frame));
       t2 = type$.legacy_InstanceRef;
       t1.exception = t2._as(Q.createServiceObject(json.$index(0, "exception"), C.List_InstanceRef));
@@ -5048,8 +4945,8 @@
       t1.extensionKind = H._asStringS(json.$index(0, "extensionKind"));
       t2 = type$.legacy_Map_dynamic_dynamic._as(json.$index(0, "extensionData"));
       t1.extensionData = t2 == null ? _null : new Q.ExtensionData(t2);
-      t1.set$timelineEvents(json.$index(0, _s14_) == null ? _null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, _s14_), C.List_TimelineEvent)), true, type$.legacy_TimelineEvent));
-      t1.set$updatedStreams(json.$index(0, _s14_0) == null ? _null : P.List_List$from(type$.Iterable_dynamic._as(json.$index(0, _s14_0)), true, type$.legacy_String));
+      t1.set$timelineEvents(json.$index(0, _s14_) == null ? _null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, _s14_), C.List_TimelineEvent)), type$.legacy_TimelineEvent));
+      t1.set$updatedStreams(json.$index(0, _s14_0) == null ? _null : P.List_List$from(type$.Iterable_dynamic._as(json.$index(0, _s14_0)), type$.legacy_String));
       t1.atAsyncSuspension = H._asBoolS(json.$index(0, "atAsyncSuspension"));
       t1.status = H._asStringS(json.$index(0, "status"));
       t1.logRecord = type$.legacy_LogRecord._as(Q.createServiceObject(json.$index(0, "logRecord"), C.List_LogRecord));
@@ -5111,7 +5008,7 @@
       t2 = Q.createServiceObject(json.$index(0, "flags"), C.List_Flag);
       if (t2 == null)
         t2 = [];
-      t1.set$flags(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_Flag));
+      t1.set$flags(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_Flag));
       return t1;
     },
     Frame_parse: function(json) {
@@ -5123,7 +5020,7 @@
       t1.$function = type$.legacy_FuncRef._as(Q.createServiceObject(json.$index(0, "function"), C.List_FuncRef));
       t1.code = type$.legacy_CodeRef._as(Q.createServiceObject(json.$index(0, "code"), C.List_CodeRef));
       t1.location = type$.legacy_SourceLocation._as(Q.createServiceObject(json.$index(0, "location"), C.List_SourceLocation));
-      t1.set$vars(json.$index(0, "vars") == null ? null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, "vars"), C.List_BoundVariable)), true, type$.legacy_BoundVariable));
+      t1.set$vars(json.$index(0, "vars") == null ? null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, "vars"), C.List_BoundVariable)), type$.legacy_BoundVariable));
       t1.kind = H._asStringS(json.$index(0, "kind"));
       return t1;
     },
@@ -5205,12 +5102,12 @@
       if (t3 == null)
         t3 = [];
       t4 = type$.Iterable_dynamic;
-      t1.set$libraries(P.List_List$from(t4._as(t3), true, t2));
+      t1.set$libraries(P.List_List$from(t4._as(t3), t2));
       t2 = Q.createServiceObject(json.$index(0, "breakpoints"), C.List_Breakpoint);
-      t1.set$breakpoints(P.List_List$from(t4._as(t2 == null ? [] : t2), true, type$.legacy_Breakpoint));
+      t1.set$breakpoints(P.List_List$from(t4._as(t2 == null ? [] : t2), type$.legacy_Breakpoint));
       t1.error = type$.legacy_Error._as(Q.createServiceObject(json.$index(0, "error"), C.List_Error));
       t1.exceptionPauseMode = H._asStringS(json.$index(0, "exceptionPauseMode"));
-      t1.set$extensionRPCs(json.$index(0, _s13_) == null ? null : P.List_List$from(t4._as(json.$index(0, _s13_)), true, type$.legacy_String));
+      t1.set$extensionRPCs(json.$index(0, _s13_) == null ? null : P.List_List$from(t4._as(json.$index(0, _s13_)), type$.legacy_String));
       return t1;
     },
     IsolateGroupRef_parse: function(json) {
@@ -5234,7 +5131,7 @@
       t2 = Q.createServiceObject(json.$index(0, "isolates"), C.List_IsolateRef);
       if (t2 == null)
         t2 = [];
-      t1.set$isolates(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_IsolateRef));
+      t1.set$isolates(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_IsolateRef));
       return t1;
     },
     InboundReferences_parse: function(json) {
@@ -5245,7 +5142,7 @@
       t2 = Q.createServiceObject(json.$index(0, "references"), C.List_InboundReference);
       if (t2 == null)
         t2 = [];
-      t1.set$references(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_InboundReference));
+      t1.set$references(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_InboundReference));
       return t1;
     },
     InboundReference_parse: function(json) {
@@ -5264,7 +5161,7 @@
       t1.type = H._asStringS(json.$index(0, "type"));
       t1.totalCount = H._asIntS(json.$index(0, "totalCount"));
       t2 = json.$index(0, "instances");
-      t1.set$instances(P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(t2 == null ? json.$index(0, "samples") : t2, C.List_ObjRef)), true, type$.legacy_ObjRef));
+      t1.set$instances(P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(t2 == null ? json.$index(0, "samples") : t2, C.List_ObjRef)), type$.legacy_ObjRef));
       return t1;
     },
     LibraryRef_parse: function(json) {
@@ -5287,15 +5184,15 @@
       t1.uri = H._asStringS(json.$index(0, "uri"));
       t1.debuggable = H._asBoolS(json.$index(0, "debuggable"));
       t2 = type$.Iterable_dynamic;
-      t1.set$dependencies(P.List_List$from(t2._as(Q._createSpecificObject(json.$index(0, "dependencies"), Q.vm_service_LibraryDependency_parse$closure())), true, type$.legacy_LibraryDependency));
+      t1.set$dependencies(P.List_List$from(t2._as(Q._createSpecificObject(json.$index(0, "dependencies"), Q.vm_service_LibraryDependency_parse$closure())), type$.legacy_LibraryDependency));
       t3 = Q.createServiceObject(json.$index(0, "scripts"), C.List_ScriptRef);
-      t1.set$scripts(P.List_List$from(t2._as(t3 == null ? [] : t3), true, type$.legacy_ScriptRef));
+      t1.set$scripts(P.List_List$from(t2._as(t3 == null ? [] : t3), type$.legacy_ScriptRef));
       t3 = Q.createServiceObject(json.$index(0, "variables"), C.List_FieldRef);
-      t1.set$variables(P.List_List$from(t2._as(t3 == null ? [] : t3), true, type$.legacy_FieldRef));
+      t1.set$variables(P.List_List$from(t2._as(t3 == null ? [] : t3), type$.legacy_FieldRef));
       t3 = Q.createServiceObject(json.$index(0, "functions"), C.List_FuncRef);
-      t1.set$functions(P.List_List$from(t2._as(t3 == null ? [] : t3), true, type$.legacy_FuncRef));
+      t1.set$functions(P.List_List$from(t2._as(t3 == null ? [] : t3), type$.legacy_FuncRef));
       t3 = Q.createServiceObject(json.$index(0, "classes"), C.List_ClassRef);
-      t1.set$classes(P.List_List$from(t2._as(t3 == null ? [] : t3), true, type$.legacy_ClassRef));
+      t1.set$classes(P.List_List$from(t2._as(t3 == null ? [] : t3), type$.legacy_ClassRef));
       return t1;
     },
     LibraryDependency_parse: function(json) {
@@ -5419,6 +5316,26 @@
       t1.$function = Q.createServiceObject(json.$index(0, "function"), C.List_dynamic);
       return t1;
     },
+    ProtocolList_parse: function(json) {
+      var t1, t2;
+      type$.legacy_Map_of_legacy_String_and_dynamic._as(json);
+      t1 = new Q.ProtocolList(json);
+      t1.type = H._asStringS(json.$index(0, "type"));
+      t2 = Q.createServiceObject(json.$index(0, "protocols"), C.List_Protocol);
+      if (t2 == null)
+        t2 = [];
+      t1.set$protocols(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_Protocol));
+      return t1;
+    },
+    Protocol_parse: function(json) {
+      var t1;
+      type$.legacy_Map_of_legacy_String_and_dynamic._as(json);
+      t1 = new Q.Protocol();
+      t1.protocolName = H._asStringS(json.$index(0, "protocolName"));
+      t1.major = H._asIntS(json.$index(0, "major"));
+      t1.minor = H._asIntS(json.$index(0, "minor"));
+      return t1;
+    },
     ReloadReport_parse: function(json) {
       var t1;
       type$.legacy_Map_of_legacy_String_and_dynamic._as(json);
@@ -5448,7 +5365,7 @@
       t2 = Q.createServiceObject(json.$index(0, "elements"), C.List_RetainingObject);
       if (t2 == null)
         t2 = [];
-      t1.set$elements(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_RetainingObject));
+      t1.set$elements(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_RetainingObject));
       return t1;
     },
     Response_parse: function(json) {
@@ -5505,7 +5422,7 @@
       t2 = Q.createServiceObject(json.$index(0, "scripts"), C.List_ScriptRef);
       if (t2 == null)
         t2 = [];
-      t1.set$scripts(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_ScriptRef));
+      t1.set$scripts(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_ScriptRef));
       return t1;
     },
     SourceLocation_parse: function(json) {
@@ -5524,9 +5441,9 @@
       t1 = new Q.SourceReport(json);
       t1.type = H._asStringS(json.$index(0, "type"));
       t2 = type$.Iterable_dynamic;
-      t1.set$ranges(P.List_List$from(t2._as(Q._createSpecificObject(json.$index(0, "ranges"), Q.vm_service_SourceReportRange_parse$closure())), true, type$.legacy_SourceReportRange));
+      t1.set$ranges(P.List_List$from(t2._as(Q._createSpecificObject(json.$index(0, "ranges"), Q.vm_service_SourceReportRange_parse$closure())), type$.legacy_SourceReportRange));
       t3 = Q.createServiceObject(json.$index(0, "scripts"), C.List_ScriptRef);
-      t1.set$scripts(P.List_List$from(t2._as(t3 == null ? [] : t3), true, type$.legacy_ScriptRef));
+      t1.set$scripts(P.List_List$from(t2._as(t3 == null ? [] : t3), type$.legacy_ScriptRef));
       return t1;
     },
     SourceReportCoverage_parse: function(json) {
@@ -5538,8 +5455,8 @@
         t1 = new Q.SourceReportCoverage();
         t2 = type$.Iterable_dynamic;
         t3 = type$.legacy_int;
-        t1.set$hits(P.List_List$from(t2._as(json.$index(0, "hits")), true, t3));
-        t1.set$misses(P.List_List$from(t2._as(json.$index(0, "misses")), true, t3));
+        t1.set$hits(P.List_List$from(t2._as(json.$index(0, "hits")), t3));
+        t1.set$misses(P.List_List$from(t2._as(json.$index(0, "misses")), t3));
       }
       return t1;
     },
@@ -5557,7 +5474,7 @@
         t1.compiled = H._asBoolS(json.$index(0, "compiled"));
         t1.error = type$.legacy_ErrorRef._as(Q.createServiceObject(json.$index(0, "error"), C.List_ErrorRef));
         t1.coverage = type$.legacy_SourceReportCoverage._as(Q._createSpecificObject(json.$index(0, "coverage"), Q.vm_service_SourceReportCoverage_parse$closure()));
-        t1.set$possibleBreakpoints(json.$index(0, _s19_) == null ? null : P.List_List$from(type$.Iterable_dynamic._as(json.$index(0, _s19_)), true, type$.legacy_int));
+        t1.set$possibleBreakpoints(json.$index(0, _s19_) == null ? null : P.List_List$from(type$.Iterable_dynamic._as(json.$index(0, _s19_)), type$.legacy_int));
       }
       return t1;
     },
@@ -5573,11 +5490,11 @@
         t2 = [];
       t3 = type$.Iterable_dynamic;
       t4 = type$.legacy_Frame;
-      t1.set$frames(P.List_List$from(t3._as(t2), true, t4));
-      t1.set$asyncCausalFrames(json.$index(0, _s17_) == null ? null : P.List_List$from(t3._as(Q.createServiceObject(json.$index(0, _s17_), C.List_Frame)), true, t4));
-      t1.set$awaiterFrames(json.$index(0, _s13_) == null ? null : P.List_List$from(t3._as(Q.createServiceObject(json.$index(0, _s13_), C.List_Frame)), true, t4));
+      t1.set$frames(P.List_List$from(t3._as(t2), t4));
+      t1.set$asyncCausalFrames(json.$index(0, _s17_) == null ? null : P.List_List$from(t3._as(Q.createServiceObject(json.$index(0, _s17_), C.List_Frame)), t4));
+      t1.set$awaiterFrames(json.$index(0, _s13_) == null ? null : P.List_List$from(t3._as(Q.createServiceObject(json.$index(0, _s13_), C.List_Frame)), t4));
       t2 = Q.createServiceObject(json.$index(0, "messages"), C.List_Message);
-      t1.set$messages(P.List_List$from(t3._as(t2 == null ? [] : t2), true, type$.legacy_Message));
+      t1.set$messages(P.List_List$from(t3._as(t2 == null ? [] : t2), type$.legacy_Message));
       return t1;
     },
     Success_parse: function(json) {
@@ -5595,7 +5512,7 @@
       t2 = Q.createServiceObject(json.$index(0, "traceEvents"), C.List_TimelineEvent);
       if (t2 == null)
         t2 = [];
-      t1.set$traceEvents(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_TimelineEvent));
+      t1.set$traceEvents(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_TimelineEvent));
       t1.timeOriginMicros = H._asIntS(json.$index(0, "timeOriginMicros"));
       t1.timeExtentMicros = H._asIntS(json.$index(0, "timeExtentMicros"));
       return t1;
@@ -5612,8 +5529,8 @@
       t1.recorderName = H._asStringS(json.$index(0, "recorderName"));
       t2 = type$.Iterable_dynamic;
       t3 = type$.legacy_String;
-      t1.set$availableStreams(P.List_List$from(t2._as(json.$index(0, "availableStreams")), true, t3));
-      t1.set$recordedStreams(P.List_List$from(t2._as(json.$index(0, "recordedStreams")), true, t3));
+      t1.set$availableStreams(P.List_List$from(t2._as(json.$index(0, "availableStreams")), t3));
+      t1.set$recordedStreams(P.List_List$from(t2._as(json.$index(0, "recordedStreams")), t3));
       return t1;
     },
     Timestamp_parse: function(json) {
@@ -5643,7 +5560,7 @@
       t2 = Q.createServiceObject(json.$index(0, "types"), C.List_InstanceRef);
       if (t2 == null)
         t2 = [];
-      t1.set$types(P.List_List$from(type$.Iterable_dynamic._as(t2), true, type$.legacy_InstanceRef));
+      t1.set$types(P.List_List$from(type$.Iterable_dynamic._as(t2), type$.legacy_InstanceRef));
       return t1;
     },
     UnresolvedSourceLocation_parse: function(json) {
@@ -5692,9 +5609,9 @@
       if (t2 == null)
         t2 = [];
       t3 = type$.Iterable_dynamic;
-      t1.set$isolates(P.List_List$from(t3._as(t2), true, type$.legacy_IsolateRef));
+      t1.set$isolates(P.List_List$from(t3._as(t2), type$.legacy_IsolateRef));
       t2 = Q.createServiceObject(json.$index(0, "isolateGroups"), C.List_IsolateGroupRef);
-      t1.set$isolateGroups(P.List_List$from(t3._as(t2 == null ? [] : t2), true, type$.legacy_IsolateGroupRef));
+      t1.set$isolateGroups(P.List_List$from(t3._as(t2 == null ? [] : t2), type$.legacy_IsolateGroupRef));
       return t1;
     },
     createServiceObject_closure: function createServiceObject_closure(t0) {
@@ -6055,6 +5972,16 @@
       var _ = this;
       _.$function = _.resolvedUrl = _.exclusiveTicks = _.inclusiveTicks = _.kind = null;
     },
+    ProtocolList: function ProtocolList(t0) {
+      this.protocols = null;
+      this.json = t0;
+      this.type = null;
+    },
+    ProtocolList_toJson_closure: function ProtocolList_toJson_closure() {
+    },
+    Protocol: function Protocol() {
+      this.minor = this.major = this.protocolName = null;
+    },
     ReloadReport: function ReloadReport(t0) {
       this.success = null;
       this.json = t0;
@@ -6226,9 +6153,10 @@
     }},
   R = {
     _convert: function(bytes, start, end) {
-      var t1, t2, i, bufferIndex, byteOr, byte, bufferIndex0, t3,
-        buffer = new Uint8Array((end - start) * 2);
-      for (t1 = buffer.length, t2 = bytes.length, i = start, bufferIndex = 0, byteOr = 0; i < end; ++i) {
+      var t2, i, bufferIndex, byteOr, byte, bufferIndex0, t3,
+        t1 = (end - start) * 2,
+        buffer = new Uint8Array(t1);
+      for (t2 = bytes.length, i = start, bufferIndex = 0, byteOr = 0; i < end; ++i) {
         if (i >= t2)
           return H.ioore(bytes, i);
         byte = bytes[i];
@@ -6236,7 +6164,7 @@
           return H.iae(byte);
         byteOr = (byteOr | byte) >>> 0;
         bufferIndex0 = bufferIndex + 1;
-        t3 = (byte & 240) >>> 4;
+        t3 = byte >>> 4 & 15;
         t3 = t3 < 10 ? t3 + 48 : t3 + 97 - 10;
         if (bufferIndex >= t1)
           return H.ioore(buffer, bufferIndex);
@@ -6318,24 +6246,79 @@
       _._hexToByte = _._byteToHex = null;
     }
   },
+  E = {
+    main: function() {
+      var $async$goto = 0,
+        $async$completer = P._makeAsyncAwaitCompleter(type$.void),
+        ddsChannel, vmService, id, message, channel, t1, t2, t3, $async$temp1, $async$temp2, $async$temp3;
+      var $async$main = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) {
+        if ($async$errorCode === 1)
+          return P._asyncRethrow($async$result, $async$completer);
+        while (true)
+          switch ($async$goto) {
+            case 0:
+              // Function start
+              channel = M.SseClient$("/test");
+              t1 = channel._incomingController;
+              t2 = new Q.QueueList(type$.QueueList_legacy_Result_legacy_String);
+              t3 = new Array(8);
+              t3.fixed$length = Array;
+              t2.set$_table(H.setRuntimeTypeInfo(t3, type$.JSArray_legacy_Result_legacy_String));
+              t3 = P.List_List$filled(P.ListQueue__calculateCapacity(null), null, false, type$.nullable__EventRequest_dynamic);
+              $async$temp1 = M;
+              $async$goto = 2;
+              return P._asyncAwait(new G.StreamQueue(new P._ControllerStream(t1, H._instanceType(t1)._eval$1("_ControllerStream<1>")), t2, new P.ListQueue(t3, type$.ListQueue_legacy__EventRequest_dynamic), type$.StreamQueue_legacy_String).get$next(), $async$main);
+            case 2:
+              // returning from await.
+              ddsChannel = $async$temp1.SseClient$($async$result);
+              t1 = new W._EventStream(ddsChannel._eventSource, "open", false, type$._EventStream_legacy_Event);
+              $async$goto = 3;
+              return P._asyncAwait(t1.get$first(t1), $async$main);
+            case 3:
+              // returning from await.
+              t1 = ddsChannel._incomingController;
+              vmService = Q.VmService$(new P._ControllerStream(t1, H._instanceType(t1)._eval$1("_ControllerStream<1>")), new E.main_closure(ddsChannel));
+              id = "" + ++vmService._id;
+              t1 = new P._Future($.Zone__current, type$._Future_legacy_Version);
+              vmService._completers.$indexSet(0, id, new P._AsyncCompleter(t1, type$._AsyncCompleter_legacy_Version));
+              vmService._methodCalls.$indexSet(0, id, "getVersion");
+              t2 = type$.dynamic;
+              message = C.C_JsonCodec.encode$2$toEncodable(P.LinkedHashMap_LinkedHashMap$_literal(["jsonrpc", "2.0", "id", id, "method", "getVersion", "params", C.Map_empty], t2, t2), null);
+              vmService._onSend.add$1(0, message);
+              vmService._writeMessage.call$1(message);
+              t2 = channel._outgoingController;
+              $async$temp1 = t2;
+              $async$temp2 = H._instanceType(t2)._precomputed1;
+              $async$temp3 = C.C_JsonCodec;
+              $async$goto = 4;
+              return P._asyncAwait(t1, $async$main);
+            case 4:
+              // returning from await.
+              $async$temp1.add$1(0, $async$temp2._as($async$temp3.encode$1($async$result.json)));
+              ddsChannel.close$0(0);
+              // implicit return
+              return P._asyncReturn(null, $async$completer);
+          }
+      });
+      return P._asyncStartSync($async$main, $async$completer);
+    },
+    main_closure: function main_closure(t0) {
+      this.ddsChannel = t0;
+    }
+  },
   T = {
     UuidUtil_mathRNG: function() {
-      var b, rand, i,
+      var b, i,
         t1 = new Array(16);
       t1.fixed$length = Array;
       b = H.setRuntimeTypeInfo(t1, type$.JSArray_legacy_int);
-      for (rand = null, i = 0; i < 16; ++i) {
-        t1 = i & 3;
-        if (t1 === 0)
-          rand = C.JSInt_methods.toInt$0(C.JSNumber_methods.floor$0(C.C__JSRandom.nextDouble$0() * 4294967296));
-        if (typeof rand !== "number")
-          return rand.$shr();
-        C.JSArray_methods.$indexSet(b, i, C.JSInt_methods._shrOtherPositive$1(rand, t1 << 3) & 255);
-      }
+      for (i = 0; i < 16; ++i)
+        C.JSArray_methods.$indexSet(b, i, C.C__JSRandom.nextInt$1(256));
+      C.JSArray_methods.shuffle$0(b);
       return b;
     }
   };
-  var holders = [C, H, J, P, W, V, E, F, G, Q, N, R, Y, L, M, K, T];
+  var holders = [C, H, J, P, W, V, F, G, Q, N, R, Y, L, M, K, E, T];
   hunkHelpers.setFunctionNamesIfNecessary(holders);
   var $ = {};
   H.JS_CONST.prototype = {};
@@ -6393,7 +6376,6 @@
     },
     $isNull: 1
   };
-  J.JSObject.prototype = {};
   J.JavaScriptObject.prototype = {
     get$hashCode: function(receiver) {
       return 0;
@@ -6414,9 +6396,6 @@
         return this.super$JavaScriptObject$toString(receiver);
       return "JavaScript function for " + H.S(J.toString$0$(dartClosure));
     },
-    $signature: function() {
-      return {func: 1, opt: [,,,,,,,,,,,,,,,,]};
-    },
     $isFunction: 1
   };
   J.JSArray.prototype = {
@@ -6427,12 +6406,32 @@
       receiver.push(value);
     },
     addAll$1: function(receiver, collection) {
-      var t1, _i;
       H._arrayInstanceType(receiver)._eval$1("Iterable<1>")._as(collection);
       if (!!receiver.fixed$length)
         H.throwExpression(P.UnsupportedError$("addAll"));
-      for (t1 = collection.length, _i = 0; _i < collection.length; collection.length === t1 || (0, H.throwConcurrentModificationError)(collection), ++_i)
-        receiver.push(collection[_i]);
+      this._addAllFromArray$1(receiver, collection);
+      return;
+    },
+    _addAllFromArray$1: function(receiver, array) {
+      var len, i;
+      type$.JSArray_dynamic._as(array);
+      len = array.length;
+      if (len === 0)
+        return;
+      if (receiver === array)
+        throw H.wrapException(P.ConcurrentModificationError$(receiver));
+      for (i = 0; i < len; ++i)
+        receiver.push(array[i]);
+    },
+    forEach$1: function(receiver, f) {
+      var end, i;
+      H._arrayInstanceType(receiver)._eval$1("~(1)")._as(f);
+      end = receiver.length;
+      for (i = 0; i < end; ++i) {
+        f.call$1(receiver[i]);
+        if (receiver.length !== end)
+          throw H.wrapException(P.ConcurrentModificationError$(receiver));
+      }
     },
     map$1$1: function(receiver, f, $T) {
       var t1 = H._arrayInstanceType(receiver);
@@ -6472,6 +6471,29 @@
         for (i = 0; i < $length; ++i)
           receiver[start + i] = t1.$index(otherList, skipCount + i);
     },
+    shuffle$1: function(receiver, random) {
+      var $length, pos, t1, tmp;
+      if (!!receiver.immutable$list)
+        H.throwExpression(P.UnsupportedError$("shuffle"));
+      if (random == null)
+        random = C.C__JSRandom;
+      $length = receiver.length;
+      for (; $length > 1;) {
+        pos = random.nextInt$1($length);
+        --$length;
+        t1 = receiver.length;
+        if ($length >= t1)
+          return H.ioore(receiver, $length);
+        tmp = receiver[$length];
+        if (pos < 0 || pos >= t1)
+          return H.ioore(receiver, pos);
+        this.$indexSet(receiver, $length, receiver[pos]);
+        this.$indexSet(receiver, pos, tmp);
+      }
+    },
+    shuffle$0: function($receiver) {
+      return this.shuffle$1($receiver, null);
+    },
     contains$1: function(receiver, other) {
       var i;
       for (i = 0; i < receiver.length; ++i)
@@ -6526,14 +6548,10 @@
       receiver[index] = value;
     },
     $add: function(receiver, other) {
-      var t2, _i,
-        t1 = H._arrayInstanceType(receiver);
+      var t1 = H._arrayInstanceType(receiver);
       t1._eval$1("List<1>")._as(other);
-      t1 = H.setRuntimeTypeInfo([], t1);
-      for (t2 = receiver.length, _i = 0; _i < receiver.length; receiver.length === t2 || (0, H.throwConcurrentModificationError)(receiver), ++_i)
-        this.add$1(t1, receiver[_i]);
-      for (t2 = other.get$iterator(other); t2.moveNext$0();)
-        this.add$1(t1, t2.get$current());
+      t1 = P.List_List$of(receiver, true, t1._precomputed1);
+      this.addAll$1(t1, other);
       return t1;
     },
     $isJSIndexable: 1,
@@ -6567,16 +6585,6 @@
     $isIterator: 1
   };
   J.JSNumber.prototype = {
-    toInt$0: function(receiver) {
-      var t1;
-      if (receiver >= -2147483648 && receiver <= 2147483647)
-        return receiver | 0;
-      if (isFinite(receiver)) {
-        t1 = receiver < 0 ? Math.ceil(receiver) : Math.floor(receiver);
-        return t1 + 0;
-      }
-      throw H.wrapException(P.UnsupportedError$("" + receiver + ".toInt()"));
-    },
     floor$0: function(receiver) {
       var truncated, d;
       if (receiver >= 0) {
@@ -6625,12 +6633,12 @@
       var absolute, floorLog2, factor, scaled,
         intValue = receiver | 0;
       if (receiver === intValue)
-        return 536870911 & intValue;
+        return intValue & 536870911;
       absolute = Math.abs(receiver);
       floorLog2 = Math.log(absolute) / 0.6931471805599453 | 0;
       factor = Math.pow(2, floorLog2);
       scaled = absolute < 1 ? absolute / factor : factor / absolute;
-      return 536870911 & ((scaled * 9007199254740992 | 0) + (scaled * 3542243181176521 | 0)) * 599197 + floorLog2 * 1259;
+      return ((scaled * 9007199254740992 | 0) + (scaled * 3542243181176521 | 0)) * 599197 + floorLog2 * 1259 & 536870911;
     },
     $add: function(receiver, other) {
       H._asNumS(other);
@@ -6804,13 +6812,13 @@
     get$hashCode: function(receiver) {
       var t1, hash, i;
       for (t1 = receiver.length, hash = 0, i = 0; i < t1; ++i) {
-        hash = 536870911 & hash + receiver.charCodeAt(i);
-        hash = 536870911 & hash + ((524287 & hash) << 10);
+        hash = hash + receiver.charCodeAt(i) & 536870911;
+        hash = hash + ((hash & 524287) << 10) & 536870911;
         hash ^= hash >> 6;
       }
-      hash = 536870911 & hash + ((67108863 & hash) << 3);
+      hash = hash + ((hash & 67108863) << 3) & 536870911;
       hash ^= hash >> 11;
-      return 536870911 & hash + ((16383 & hash) << 15);
+      return hash + ((hash & 16383) << 15) & 536870911;
     },
     get$runtimeType: function(receiver) {
       return C.Type_String_k8F;
@@ -6828,6 +6836,31 @@
     $isPattern: 1,
     $isString: 1
   };
+  H.LateError.prototype = {
+    toString$0: function(_) {
+      var message = this._message;
+      return message != null ? "LateInitializationError: " + message : "LateInitializationError";
+    }
+  };
+  H.ReachabilityError.prototype = {
+    toString$0: function(_) {
+      var t1 = "ReachabilityError: " + this._message;
+      return t1;
+    }
+  };
+  H.nullFuture_closure.prototype = {
+    call$0: function() {
+      var t1 = new P._Future($.Zone__current, type$._Future_Null);
+      t1._asyncComplete$1(null);
+      return t1;
+    },
+    $signature: 45
+  };
+  H.NotNullableError.prototype = {
+    toString$0: function(_) {
+      return "Null is not a valid value for the parameter '" + this.__internal$_name + "' of type '" + H.createRuntimeType(this.$ti._precomputed1).toString$0(0) + "'";
+    }
+  };
   H.EfficientLengthIterable.prototype = {};
   H.ListIterable.prototype = {
     get$iterator: function(_) {
@@ -6844,8 +6877,7 @@
   };
   H.ListIterator.prototype = {
     get$current: function() {
-      var cur = this._current;
-      return cur;
+      return this._current;
     },
     moveNext$0: function() {
       var t3, _this = this,
@@ -6890,8 +6922,7 @@
       return false;
     },
     get$current: function() {
-      var cur = this._current;
-      return cur;
+      return this._current;
     },
     set$_current: function(_current) {
       this._current = this.$ti._eval$1("2?")._as(_current);
@@ -6911,7 +6942,7 @@
       var hash = this._hashCode;
       if (hash != null)
         return hash;
-      hash = 536870911 & 664597 * J.get$hashCode$(this.__internal$_name);
+      hash = 664597 * J.get$hashCode$(this.__internal$_name) & 536870911;
       this._hashCode = hash;
       return hash;
     },
@@ -6938,6 +6969,7 @@
       t1._precomputed1._as(key);
       t1._rest[1]._as(val);
       H.ConstantMap__throwUnmodifiable();
+      H.ReachabilityError$("`null` encountered as the result from expression with type `Never`.");
     },
     map$2$1: function(_, transform, K2, V2) {
       var result = P.LinkedHashMap_LinkedHashMap$_empty(K2, V2);
@@ -6953,10 +6985,10 @@
     call$2: function(key, value) {
       var t1 = H._instanceType(this.$this),
         entry = this.transform.call$2(t1._precomputed1._as(key), t1._rest[1]._as(value));
-      this.result.$indexSet(0, C.JSNull_methods.get$key(entry), entry.get$value());
+      this.result.$indexSet(0, entry.get$key(entry), entry.get$value());
     },
     $signature: function() {
-      return H._instanceType(this.$this)._eval$1("Null(1,2)");
+      return H._instanceType(this.$this)._eval$1("~(1,2)");
     }
   };
   H.ConstantStringMap.prototype = {
@@ -7058,7 +7090,7 @@
       C.JSArray_methods.add$1(this.$arguments, argument);
       ++t1.argumentCount;
     },
-    $signature: 44
+    $signature: 39
   };
   H.TypeErrorDecoder.prototype = {
     matchTypeError$1: function(message) {
@@ -7089,7 +7121,7 @@
     toString$0: function(_) {
       var t1 = this._method;
       if (t1 == null)
-        return "NoSuchMethodError: " + H.S(this._message);
+        return "NoSuchMethodError: " + H.S(this.__js_helper$_message);
       return "NoSuchMethodError: method not found: '" + t1 + "' on null";
     }
   };
@@ -7099,16 +7131,16 @@
         _s38_ = "NoSuchMethodError: method not found: '",
         t1 = _this._method;
       if (t1 == null)
-        return "NoSuchMethodError: " + H.S(_this._message);
+        return "NoSuchMethodError: " + H.S(_this.__js_helper$_message);
       t2 = _this._receiver;
       if (t2 == null)
-        return _s38_ + t1 + "' (" + H.S(_this._message) + ")";
-      return _s38_ + t1 + "' on '" + t2 + "' (" + H.S(_this._message) + ")";
+        return _s38_ + t1 + "' (" + H.S(_this.__js_helper$_message) + ")";
+      return _s38_ + t1 + "' on '" + t2 + "' (" + H.S(_this.__js_helper$_message) + ")";
     }
   };
   H.UnknownJsTypeError.prototype = {
     toString$0: function(_) {
-      var t1 = this._message;
+      var t1 = this.__js_helper$_message;
       return t1.length === 0 ? "Error" : "Error: " + t1;
     }
   };
@@ -7182,7 +7214,7 @@
   };
   H.RuntimeError.prototype = {
     toString$0: function(_) {
-      return "RuntimeError: " + H.S(this.message);
+      return "RuntimeError: " + this.message;
     }
   };
   H._AssertionError.prototype = {
@@ -7441,7 +7473,7 @@
       t1.$indexSet(0, t2._precomputed1._as(key), t2._rest[1]._as(value));
     },
     $signature: function() {
-      return H._instanceType(this.$this)._eval$1("Null(1,2)");
+      return H._instanceType(this.$this)._eval$1("~(1,2)");
     }
   };
   H.LinkedHashMapCell.prototype = {};
@@ -7490,19 +7522,19 @@
     call$1: function(o) {
       return this.getTag(o);
     },
-    $signature: 3
+    $signature: 2
   };
   H.initHooks_closure0.prototype = {
     call$2: function(o, tag) {
       return this.getUnknownTag(o, tag);
     },
-    $signature: 31
+    $signature: 33
   };
   H.initHooks_closure1.prototype = {
     call$1: function(tag) {
       return this.prototypeForTag(H._asStringS(tag));
     },
-    $signature: 41
+    $signature: 35
   };
   H.NativeByteBuffer.prototype = {
     get$runtimeType: function(receiver) {
@@ -7681,7 +7713,7 @@
       t2 = this.span;
       t1.firstChild ? t1.removeChild(t2) : t1.appendChild(t2);
     },
-    $signature: 33
+    $signature: 28
   };
   P._AsyncRun__scheduleImmediateJsOverride_internalCallback.prototype = {
     call$0: function() {
@@ -7689,7 +7721,7 @@
     },
     "call*": "call$0",
     $requiredArgCount: 0,
-    $signature: 1
+    $signature: 3
   };
   P._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback.prototype = {
     call$0: function() {
@@ -7697,7 +7729,7 @@
     },
     "call*": "call$0",
     $requiredArgCount: 0,
-    $signature: 1
+    $signature: 3
   };
   P._TimerImpl.prototype = {
     _TimerImpl$2: function(milliseconds, callback) {
@@ -7761,7 +7793,7 @@
     call$1: function(result) {
       return this.bodyFunction.call$2(0, result);
     },
-    $signature: 2
+    $signature: 1
   };
   P._awaitOnObject_closure0.prototype = {
     call$2: function(error, stackTrace) {
@@ -7769,13 +7801,13 @@
     },
     "call*": "call$2",
     $requiredArgCount: 2,
-    $signature: 34
+    $signature: 40
   };
   P._wrapJsFunctionForAsync_closure.prototype = {
     call$2: function(errorCode, result) {
       this.$protected(H._asIntS(errorCode), result);
     },
-    $signature: 38
+    $signature: 41
   };
   P._BroadcastSubscription.prototype = {
     _onPause$0: function() {
@@ -7880,7 +7912,7 @@
       H._instanceType(_this)._eval$1("~(_BufferingStreamSubscription<1>)")._as(action);
       t1 = _this._state;
       if ((t1 & 2) !== 0)
-        throw H.wrapException(P.StateError$("Cannot fire new event. Controller is already firing an event"));
+        throw H.wrapException(P.StateError$(string$.Cannot));
       subscription = _this._firstSubscription;
       if (subscription == null)
         return;
@@ -7929,7 +7961,7 @@
     },
     _addEventError$0: function() {
       if ((this._state & 2) !== 0)
-        return new P.StateError("Cannot fire new event. Controller is already firing an event");
+        return new P.StateError(string$.Cannot);
       return this.super$_BroadcastStreamController$_addEventError();
     },
     _sendData$1: function(data) {
@@ -7955,7 +7987,7 @@
       this.$this.$ti._eval$1("_BufferingStreamSubscription<1>")._as(subscription)._add$1(this.data);
     },
     $signature: function() {
-      return this.$this.$ti._eval$1("Null(_BufferingStreamSubscription<1>)");
+      return this.$this.$ti._eval$1("~(_BufferingStreamSubscription<1>)");
     }
   };
   P._AsyncBroadcastStreamController.prototype = {
@@ -7967,12 +7999,10 @@
         subscription._addPending$1(new P._DelayedData(data, t1));
     }
   };
-  P.Future.prototype = {};
-  P.Completer.prototype = {};
   P._Completer.prototype = {
     completeError$2: function(error, stackTrace) {
       var t1;
-      P.ArgumentError_checkNotNull(error, "error", type$.Object);
+      H.checkNotNullable(error, "error", type$.Object);
       t1 = this.future;
       if (t1._state !== 0)
         throw H.wrapException(P.StateError$("Future already completed"));
@@ -8028,7 +8058,7 @@
         if (onError != null)
           onError = P._registerErrorHandler(onError, currentZone);
       }
-      result = new P._Future($.Zone__current, $R._eval$1("_Future<0>"));
+      result = new P._Future(currentZone, $R._eval$1("_Future<0>"));
       t2 = onError == null ? 1 : 3;
       this._addListener$1(new P._FutureListener(result, t2, f, onError, t1._eval$1("@<1>")._bind$1($R)._eval$1("_FutureListener<1,2>")));
       return result;
@@ -8052,6 +8082,11 @@
       this._addListener$1(new P._FutureListener(result, 8, action, null, t1._eval$1("@<1>")._bind$1(t1._precomputed1)._eval$1("_FutureListener<1,2>")));
       return result;
     },
+    _setValue$1: function(value) {
+      this.$ti._precomputed1._as(value);
+      this._state = 4;
+      this._resultOrListeners = value;
+    },
     _addListener$1: function(listener) {
       var source, _this = this,
         t1 = _this._state;
@@ -8115,6 +8150,17 @@
       }
       return prev;
     },
+    _chainForeignFuture$1: function(source) {
+      var e, s, exception, _this = this;
+      _this._state = 1;
+      try {
+        source.then$1$2$onError(new P._Future__chainForeignFuture_closure(_this), new P._Future__chainForeignFuture_closure0(_this), type$.Null);
+      } catch (exception) {
+        e = H.unwrapException(exception);
+        s = H.getTraceFromException(exception);
+        P.scheduleMicrotask(new P._Future__chainForeignFuture_closure1(_this, e, s));
+      }
+    },
     _complete$1: function(value) {
       var listeners, _this = this,
         t1 = _this.$ti;
@@ -8123,7 +8169,7 @@
         if (t1._is(value))
           P._Future__chainCoreFuture(value, _this);
         else
-          P._Future__chainForeignFuture(value, _this);
+          _this._chainForeignFuture$1(value);
       else {
         listeners = _this._removeListeners$0();
         t1._precomputed1._as(value);
@@ -8176,7 +8222,7 @@
           P._Future__chainCoreFuture(value, _this);
         return;
       }
-      P._Future__chainForeignFuture(value, _this);
+      _this._chainForeignFuture$1(value);
     },
     _asyncCompleteError$2: function(error, stackTrace) {
       type$.StackTrace._as(stackTrace);
@@ -8189,54 +8235,60 @@
     call$0: function() {
       P._Future__propagateToListeners(this.$this, this.listener);
     },
-    $signature: 1
+    $signature: 0
   };
   P._Future__prependListeners_closure.prototype = {
     call$0: function() {
       P._Future__propagateToListeners(this.$this, this._box_0.listeners);
     },
-    $signature: 1
+    $signature: 0
   };
   P._Future__chainForeignFuture_closure.prototype = {
     call$1: function(value) {
-      var t1 = this.target;
+      var error, stackTrace, exception,
+        t1 = this.$this;
       t1._state = 0;
-      t1._complete$1(value);
+      try {
+        t1._completeWithValue$1(t1.$ti._precomputed1._as(value));
+      } catch (exception) {
+        error = H.unwrapException(exception);
+        stackTrace = H.getTraceFromException(exception);
+        t1._completeError$2(error, stackTrace);
+      }
     },
     $signature: 11
   };
   P._Future__chainForeignFuture_closure0.prototype = {
     call$2: function(error, stackTrace) {
-      type$.StackTrace._as(stackTrace);
-      this.target._completeError$2(error, stackTrace);
+      this.$this._completeError$2(error, type$.StackTrace._as(stackTrace));
     },
     "call*": "call$2",
     $requiredArgCount: 2,
-    $signature: 27
+    $signature: 29
   };
   P._Future__chainForeignFuture_closure1.prototype = {
     call$0: function() {
-      this.target._completeError$2(this.e, this.s);
+      this.$this._completeError$2(this.e, this.s);
     },
-    $signature: 1
+    $signature: 0
   };
   P._Future__asyncCompleteWithValue_closure.prototype = {
     call$0: function() {
       this.$this._completeWithValue$1(this.value);
     },
-    $signature: 1
+    $signature: 0
   };
   P._Future__chainFuture_closure.prototype = {
     call$0: function() {
       P._Future__chainCoreFuture(this.value, this.$this);
     },
-    $signature: 1
+    $signature: 0
   };
   P._Future__asyncCompleteError_closure.prototype = {
     call$0: function() {
       this.$this._completeError$2(this.error, this.stackTrace);
     },
-    $signature: 1
+    $signature: 0
   };
   P._Future__propagateToListeners_handleWhenCompleteCallback.prototype = {
     call$0: function() {
@@ -8283,7 +8335,7 @@
     call$1: function(_) {
       return this.originalSource;
     },
-    $signature: 28
+    $signature: 32
   };
   P._Future__propagateToListeners_handleValueCallback.prototype = {
     call$0: function() {
@@ -8357,7 +8409,7 @@
       ++this._box_0.count;
     },
     $signature: function() {
-      return H._instanceType(this.$this)._eval$1("Null(Stream.T)");
+      return H._instanceType(this.$this)._eval$1("~(Stream.T)");
     }
   };
   P.Stream_length_closure0.prototype = {
@@ -8366,7 +8418,7 @@
     },
     "call*": "call$0",
     $requiredArgCount: 0,
-    $signature: 1
+    $signature: 0
   };
   P.Stream_first_closure.prototype = {
     call$0: function() {
@@ -8386,19 +8438,18 @@
     },
     "call*": "call$0",
     $requiredArgCount: 0,
-    $signature: 1
+    $signature: 0
   };
   P.Stream_first_closure0.prototype = {
     call$1: function(value) {
       P._cancelAndValue(this.subscription, this.future, H._instanceType(this.$this)._eval$1("Stream.T")._as(value));
     },
     $signature: function() {
-      return H._instanceType(this.$this)._eval$1("Null(Stream.T)");
+      return H._instanceType(this.$this)._eval$1("~(Stream.T)");
     }
   };
   P.StreamSubscription.prototype = {};
   P.StreamTransformerBase.prototype = {};
-  P.StreamController.prototype = {};
   P._StreamController.prototype = {
     get$_pendingEvents: function() {
       var t1, _this = this;
@@ -8463,18 +8514,16 @@
       return _this._ensureDoneFuture$0();
     },
     _subscribe$4: function(onData, onError, onDone, cancelOnError) {
-      var t2, t3, subscription, pendingEvents, addState, _this = this,
+      var subscription, pendingEvents, t2, addState, _this = this,
         t1 = H._instanceType(_this);
       t1._eval$1("~(1)?")._as(onData);
       type$.nullable_void_Function._as(onDone);
       if ((_this._state & 3) !== 0)
         throw H.wrapException(P.StateError$("Stream has already been listened to."));
-      t2 = $.Zone__current;
-      t3 = cancelOnError ? 1 : 0;
-      subscription = new P._ControllerSubscription(_this, P._BufferingStreamSubscription__registerDataHandler(t2, onData, t1._precomputed1), P._BufferingStreamSubscription__registerErrorHandler(t2, onError), P._BufferingStreamSubscription__registerDoneHandler(t2, onDone), t2, t3, t1._eval$1("_ControllerSubscription<1>"));
+      subscription = P._ControllerSubscription$(_this, onData, onError, onDone, cancelOnError, t1._precomputed1);
       pendingEvents = _this.get$_pendingEvents();
-      t3 = _this._state |= 1;
-      if ((t3 & 8) !== 0) {
+      t2 = _this._state |= 1;
+      if ((t2 & 8) !== 0) {
         addState = t1._eval$1("_StreamControllerAddStreamState<1>")._as(_this._varData);
         addState.set$varData(subscription);
         addState.resume$0();
@@ -8541,7 +8590,7 @@
     call$0: function() {
       P._runGuarded(this.$this.onListen);
     },
-    $signature: 1
+    $signature: 0
   };
   P._StreamController__recordCancel_complete.prototype = {
     call$0: function() {
@@ -8918,7 +8967,7 @@
         t1.lastPendingEvent = null;
       $event.perform$1(t2);
     },
-    $signature: 1
+    $signature: 0
   };
   P._StreamImplEvents.prototype = {
     add$1: function(_, $event) {
@@ -8970,7 +9019,7 @@
   P._StreamIterator.prototype = {
     get$current: function() {
       var _this = this;
-      if (_this._async$_subscription != null && _this._isPaused)
+      if (_this._async$_hasValue)
         return _this.$ti._precomputed1._as(_this._stateData);
       return _this.$ti._precomputed1._as(null);
     },
@@ -8978,10 +9027,10 @@
       var future, _this = this,
         subscription = _this._async$_subscription;
       if (subscription != null) {
-        if (_this._isPaused) {
+        if (_this._async$_hasValue) {
           future = new P._Future($.Zone__current, type$._Future_bool);
           _this._stateData = future;
-          _this._isPaused = false;
+          _this._async$_hasValue = false;
           subscription.resume$0();
           return future;
         }
@@ -8990,11 +9039,16 @@
       return _this._initializeOrDone$0();
     },
     _initializeOrDone$0: function() {
-      var _this = this,
+      var future, subscription, _this = this,
         stateData = _this._stateData;
       if (stateData != null) {
-        _this.set$_async$_subscription(_this.$ti._eval$1("Stream<1>")._as(stateData).listen$4$cancelOnError$onDone$onError(_this.get$_async$_onData(), true, _this.get$_onDone(), _this.get$_onError()));
-        return _this._stateData = new P._Future($.Zone__current, type$._Future_bool);
+        _this.$ti._eval$1("Stream<1>")._as(stateData);
+        future = new P._Future($.Zone__current, type$._Future_bool);
+        _this._stateData = future;
+        subscription = stateData.listen$4$cancelOnError$onDone$onError(_this.get$_async$_onData(), true, _this.get$_onDone(), _this.get$_onError());
+        if (_this._stateData != null)
+          _this.set$_async$_subscription(subscription);
+        return future;
       }
       return $.$get$Future__falseFuture();
     },
@@ -9005,8 +9059,10 @@
       _this._stateData = null;
       if (subscription != null) {
         _this.set$_async$_subscription(null);
-        if (!_this._isPaused)
+        if (!_this._async$_hasValue)
           type$._Future_bool._as(stateData)._asyncComplete$1(false);
+        else
+          _this._async$_hasValue = false;
         return subscription.cancel$0();
       }
       return $.$get$Future__nullFuture();
@@ -9014,29 +9070,40 @@
     _async$_onData$1: function(data) {
       var moveNextFuture, t1, _this = this;
       _this.$ti._precomputed1._as(data);
+      if (_this._async$_subscription == null)
+        return;
       moveNextFuture = type$._Future_bool._as(_this._stateData);
       _this._stateData = data;
-      _this._isPaused = true;
+      _this._async$_hasValue = true;
       moveNextFuture._complete$1(true);
-      if (_this._isPaused) {
+      if (_this._async$_hasValue) {
         t1 = _this._async$_subscription;
         if (t1 != null)
           t1.pause$0();
       }
     },
     _onError$2: function(error, stackTrace) {
-      var moveNextFuture;
+      var subscription, moveNextFuture, _this = this;
       type$.StackTrace._as(stackTrace);
-      moveNextFuture = type$._Future_bool._as(this._stateData);
-      this.set$_async$_subscription(null);
-      this._stateData = null;
-      moveNextFuture._completeError$2(error, stackTrace);
+      subscription = _this._async$_subscription;
+      moveNextFuture = type$._Future_bool._as(_this._stateData);
+      _this.set$_async$_subscription(null);
+      _this._stateData = null;
+      if (subscription != null)
+        moveNextFuture._completeError$2(error, stackTrace);
+      else
+        moveNextFuture._asyncCompleteError$2(error, stackTrace);
     },
     _onDone$0: function() {
-      var moveNextFuture = type$._Future_bool._as(this._stateData);
-      this.set$_async$_subscription(null);
-      this._stateData = null;
-      moveNextFuture._complete$1(false);
+      var _this = this,
+        subscription = _this._async$_subscription,
+        moveNextFuture = type$._Future_bool._as(_this._stateData);
+      _this.set$_async$_subscription(null);
+      _this._stateData = null;
+      if (subscription != null)
+        moveNextFuture._completeWithValue$1(false);
+      else
+        moveNextFuture._asyncCompleteWithValue$1(false);
     },
     set$_async$_subscription: function(_subscription) {
       this._async$_subscription = this.$ti._eval$1("StreamSubscription<1>?")._as(_subscription);
@@ -9145,7 +9212,7 @@
       error.stack = J.toString$0$(this.stackTrace);
       throw error;
     },
-    $signature: 1
+    $signature: 0
   };
   P._RootZone.prototype = {
     runGuarded$1: function(f) {
@@ -9310,7 +9377,7 @@
       else
         _this._collection$_last = _this._collection$_last._collection$_next = cell;
       ++_this._collection$_length;
-      _this._collection$_modifications = 1073741823 & _this._collection$_modifications + 1;
+      _this._collection$_modifications = _this._collection$_modifications + 1 & 1073741823;
       return cell;
     },
     _computeHashCode$1: function(element) {
@@ -9359,6 +9426,16 @@
     elementAt$1: function(receiver, index) {
       return this.$index(receiver, index);
     },
+    forEach$1: function(receiver, action) {
+      var $length, i;
+      H.instanceType(receiver)._eval$1("~(ListMixin.E)")._as(action);
+      $length = this.get$length(receiver);
+      for (i = 0; i < $length; ++i) {
+        action.call$1(this.$index(receiver, i));
+        if ($length !== this.get$length(receiver))
+          throw H.wrapException(P.ConcurrentModificationError$(receiver));
+      }
+    },
     get$isNotEmpty: function(receiver) {
       return this.get$length(receiver) !== 0;
     },
@@ -9385,17 +9462,11 @@
       return this.toList$1$growable($receiver, true);
     },
     $add: function(receiver, other) {
-      var t2, cur,
-        t1 = H.instanceType(receiver);
+      var t1 = H.instanceType(receiver);
       t1._eval$1("List<ListMixin.E>")._as(other);
-      t2 = H.setRuntimeTypeInfo([], t1._eval$1("JSArray<ListMixin.E>"));
-      for (t1 = new H.ListIterator(receiver, this.get$length(receiver), t1._eval$1("ListIterator<ListMixin.E>")); t1.moveNext$0();) {
-        cur = t1._current;
-        C.JSArray_methods.add$1(t2, cur);
-      }
-      for (t1 = other.get$iterator(other); t1.moveNext$0();)
-        C.JSArray_methods.add$1(t2, t1.get$current());
-      return t2;
+      t1 = P.List_List$of(receiver, true, t1._eval$1("ListMixin.E"));
+      C.JSArray_methods.addAll$1(t1, other);
+      return t1;
     },
     toString$0: function(receiver) {
       return P.IterableBase_iterableToFullString(receiver, "[", "]");
@@ -9432,7 +9503,7 @@
       for (t1 = this.get$keys(), t1 = t1.get$iterator(t1); t1.moveNext$0();) {
         key = t1.get$current();
         entry = transform.call$2(key, this.$index(0, key));
-        result.$indexSet(0, C.JSNull_methods.get$key(entry), entry.get$value());
+        result.$indexSet(0, entry.get$key(entry), entry.get$value());
       }
       return result;
     },
@@ -9533,8 +9604,7 @@
   };
   P._ListQueueIterator.prototype = {
     get$current: function() {
-      var cur = this._collection$_current;
-      return cur;
+      return this._collection$_current;
     },
     moveNext$0: function() {
       var t2, t3, _this = this,
@@ -9558,18 +9628,18 @@
     },
     $isIterator: 1
   };
-  P._SetBase.prototype = {
+  P.SetMixin.prototype = {
     map$1: function(_, f) {
       var t1 = H._instanceType(this);
       return new H.EfficientLengthMappedIterable(this, t1._eval$1("@(1)")._as(f), t1._eval$1("EfficientLengthMappedIterable<1,@>"));
     },
     toString$0: function(_) {
       return P.IterableBase_iterableToFullString(this, "{", "}");
-    },
-    $isEfficientLengthIterable: 1,
-    $isIterable: 1
+    }
   };
+  P._SetBase.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1};
   P._UnmodifiableMapView_MapView__UnmodifiableMapMixin.prototype = {};
+  P.__SetBase_Object_SetMixin.prototype = {};
   P._JsonMap.prototype = {
     $index: function(_, key) {
       var result,
@@ -9699,7 +9769,7 @@
       return this._parent.containsKey$1(key);
     }
   };
-  P.Utf8Decoder_closure.prototype = {
+  P.Utf8Decoder__decoder_closure.prototype = {
     call$0: function() {
       var t1, exception;
       try {
@@ -9712,7 +9782,7 @@
     },
     $signature: 14
   };
-  P.Utf8Decoder_closure0.prototype = {
+  P.Utf8Decoder__decoderNonfatal_closure.prototype = {
     call$0: function() {
       var t1, exception;
       try {
@@ -9932,29 +10002,30 @@
       t1._contents += "]";
     },
     writeMap$1: function(map) {
-      var keyValueList, i, t1, separator, t2, _this = this, _box_0 = {};
+      var t1, keyValueList, i, t2, separator, t3, _this = this, _box_0 = {};
       if (map.get$isEmpty(map)) {
         _this._sink._contents += "{}";
         return true;
       }
-      keyValueList = P.List_List$filled(map.get$length(map) * 2, null, false, type$.nullable_Object);
+      t1 = map.get$length(map) * 2;
+      keyValueList = P.List_List$filled(t1, null, false, type$.nullable_Object);
       i = _box_0.i = 0;
       _box_0.allStringKeys = true;
       map.forEach$1(0, new P._JsonStringifier_writeMap_closure(_box_0, keyValueList));
       if (!_box_0.allStringKeys)
         return false;
-      t1 = _this._sink;
-      t1._contents += "{";
-      for (separator = '"'; i < keyValueList.length; i += 2, separator = ',"') {
-        t1._contents += separator;
+      t2 = _this._sink;
+      t2._contents += "{";
+      for (separator = '"'; i < t1; i += 2, separator = ',"') {
+        t2._contents += separator;
         _this.writeStringContent$1(H._asStringS(keyValueList[i]));
-        t1._contents += '":';
-        t2 = i + 1;
-        if (t2 >= keyValueList.length)
-          return H.ioore(keyValueList, t2);
-        _this.writeObject$1(keyValueList[t2]);
+        t2._contents += '":';
+        t3 = i + 1;
+        if (t3 >= t1)
+          return H.ioore(keyValueList, t3);
+        _this.writeObject$1(keyValueList[t3]);
       }
-      t1._contents += "}";
+      t2._contents += "}";
       return true;
     }
   };
@@ -10134,7 +10205,6 @@
     },
     $signature: 15
   };
-  P.bool.prototype = {};
   P.DateTime.prototype = {
     $eq: function(_, other) {
       if (other == null)
@@ -10160,7 +10230,6 @@
         return y + "-" + m + "-" + d + " " + h + ":" + min + ":" + sec + "." + ms;
     }
   };
-  P.double.prototype = {};
   P.Duration.prototype = {
     $add: function(_, other) {
       return new P.Duration(C.JSInt_methods.$add(this._duration, type$.Duration._as(other).get$_duration()));
@@ -10234,6 +10303,7 @@
       return "Assertion failed";
     }
   };
+  P.TypeError.prototype = {};
   P.NullThrownError.prototype = {
     toString$0: function(_) {
       return "Throw of null.";
@@ -10379,8 +10449,6 @@
       return offset != null ? report + (" (at offset " + H.S(offset) + ")") : report;
     }
   };
-  P.Function.prototype = {};
-  P.int.prototype = {};
   P.Iterable.prototype = {
     map$1: function(_, f) {
       var t1 = H._instanceType(this);
@@ -10409,9 +10477,6 @@
     }
   };
   P.Iterator.prototype = {};
-  P.List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1};
-  P.Map.prototype = {};
-  P.MapEntry.prototype = {};
   P.Null.prototype = {
     get$hashCode: function(_) {
       return P.Object.prototype.get$hashCode.call(C.JSNull_methods, this);
@@ -10420,7 +10485,6 @@
       return "null";
     }
   };
-  P.num.prototype = {};
   P.Object.prototype = {constructor: P.Object, $isObject: 1,
     $eq: function(_, other) {
       return this === other;
@@ -10442,14 +10506,12 @@
       return this.toString$0(this);
     }
   };
-  P.StackTrace.prototype = {};
   P._StringStackTrace.prototype = {
     toString$0: function(_) {
       return "";
     },
     $isStackTrace: 1
   };
-  P.String.prototype = {$isPattern: 1};
   P.StringBuffer.prototype = {
     get$length: function(_) {
       return this._contents.length;
@@ -10460,7 +10522,6 @@
     },
     $isStringSink: 1
   };
-  P.Symbol0.prototype = {};
   W.DomException.prototype = {
     toString$0: function(receiver) {
       return String(receiver);
@@ -10489,6 +10550,9 @@
     open$3$async: function(receiver, method, url, async) {
       return receiver.open(method, url, true);
     },
+    set$withCredentials: function(receiver, value) {
+      receiver.withCredentials = true;
+    },
     $isHttpRequest: 1
   };
   W.HttpRequest_request_closure.prototype = {
@@ -10497,8 +10561,7 @@
       type$.ProgressEvent._as(e);
       t1 = this.xhr;
       t2 = t1.status;
-      if (typeof t2 !== "number")
-        return t2.$ge();
+      t2.toString;
       accepted = t2 >= 200 && t2 < 300;
       unknownRedirect = t2 > 307 && t2 < 400;
       t2 = accepted || t2 === 0 || t2 === 304 || unknownRedirect;
@@ -10508,7 +10571,7 @@
       else
         t3.completeError$1(e);
     },
-    $signature: 40
+    $signature: 42
   };
   W.HttpRequestEventTarget.prototype = {};
   W.MessageEvent.prototype = {$isMessageEvent: 1};
@@ -10529,11 +10592,11 @@
     cancel$0: function() {
       var _this = this;
       if (_this._target == null)
-        return null;
+        return $.$get$nullFuture();
       _this._unlisten$0();
       _this._target = null;
       _this.set$_onData(null);
-      return null;
+      return $.$get$nullFuture();
     },
     onData$1: function(handleData) {
       var t1, _this = this;
@@ -10625,7 +10688,7 @@
           t1 = true;
         if (t1)
           H.throwExpression(P.ArgumentError$("DateTime is outside valid range: " + millisSinceEpoch));
-        P.ArgumentError_checkNotNull(true, "isUtc", type$.bool);
+        H.checkNotNullable(true, "isUtc", type$.bool);
         return new P.DateTime(millisSinceEpoch, true);
       }
       if (e instanceof RegExp)
@@ -10679,13 +10742,19 @@
       J.$indexSet$ax(t1, key, t2);
       return t2;
     },
-    $signature: 47
+    $signature: 52
+  };
+  P._convertDartToNative_Value_closure.prototype = {
+    call$1: function(element) {
+      this.array.push(P._convertDartToNative_Value(element));
+    },
+    $signature: 1
   };
   P.convertDartToNative_Dictionary_closure.prototype = {
     call$2: function(key, value) {
-      this.object[key] = value;
+      this.object[key] = P._convertDartToNative_Value(value);
     },
-    $signature: 51
+    $signature: 58
   };
   P._AcceptStructuredCloneDart2Js.prototype = {
     forEachJsField$2: function(object, action) {
@@ -10701,30 +10770,22 @@
     call$1: function(r) {
       return this.completer.complete$1(this.T._eval$1("0/?")._as(r));
     },
-    $signature: 2
+    $signature: 1
   };
   P.promiseToFuture_closure0.prototype = {
     call$1: function(e) {
       return this.completer.completeError$1(e);
     },
-    $signature: 2
+    $signature: 1
   };
   P._JSRandom.prototype = {
-    nextDouble$0: function() {
-      return Math.random();
-    }
+    nextInt$1: function(max) {
+      if (max <= 0 || max > 4294967296)
+        throw H.wrapException(P.RangeError$("max must be in range 0 < max \u2264 2^32, was " + max));
+      return Math.random() * max >>> 0;
+    },
+    $isRandom: 1
   };
-  P.ByteBuffer.prototype = {};
-  P.ByteData.prototype = {};
-  P.Int8List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  P.Uint8List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  P.Uint8ClampedList.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  P.Int16List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  P.Uint16List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  P.Int32List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  P.Uint32List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  P.Float32List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
-  P.Float64List.prototype = {$isEfficientLengthIterable: 1, $isIterable: 1, $isList: 1};
   V.ErrorResult.prototype = {
     complete$1: function(completer) {
       completer.completeError$2(this.error, this.stackTrace);
@@ -10739,7 +10800,6 @@
     },
     $isResult: 1
   };
-  E.Result.prototype = {};
   F.ValueResult.prototype = {
     complete$1: function(completer) {
       this.$ti._eval$1("Completer<1*>*")._as(completer).complete$1(this.value);
@@ -10853,7 +10913,7 @@
     },
     "call*": "call$2",
     $requiredArgCount: 2,
-    $signature: 56
+    $signature: 62
   };
   G.StreamQueue__ensureListening_closure0.prototype = {
     call$0: function() {
@@ -10864,9 +10924,8 @@
     },
     "call*": "call$0",
     $requiredArgCount: 0,
-    $signature: 1
+    $signature: 3
   };
-  G._EventRequest.prototype = {};
   G._NextRequest.prototype = {
     update$2: function(events, isDone) {
       var t1, t2, result;
@@ -10986,7 +11045,7 @@
   };
   L.LogRecord0.prototype = {
     toString$0: function(_) {
-      return "[" + this.level.name + "] " + this.loggerName + ": " + H.S(this.message);
+      return "[" + this.level.name + "] " + this.loggerName + ": " + this.message;
     }
   };
   F.Logger.prototype = {
@@ -11047,7 +11106,7 @@
         $parent._children.$indexSet(0, thisName, t1);
       return t1;
     },
-    $signature: 60
+    $signature: 27
   };
   M.SseClient.prototype = {
     SseClient$1: function(serverUrl) {
@@ -11118,16 +11177,14 @@
             case 0:
               // Function start
               t1 = $async$self._messages;
-              t1 = new P._ControllerStream(t1, H._instanceType(t1)._eval$1("_ControllerStream<1>"));
-              t2 = new P._StreamIterator(t1, type$._StreamIterator_dynamic);
-              P.ArgumentError_checkNotNull(t1, "stream", type$.Stream_dynamic);
+              t1 = new P._StreamIterator(H.checkNotNullable(new P._ControllerStream(t1, H._instanceType(t1)._eval$1("_ControllerStream<1>")), "stream", type$.Object), type$._StreamIterator_dynamic);
               $async$handler = 2;
-              t1 = $async$self._logger;
+              t2 = $async$self._logger;
             case 5:
               // for condition
               $async$temp1 = H;
               $async$goto = 7;
-              return P._asyncAwait(t2.moveNext$0(), $async$_startPostingMessages$0);
+              return P._asyncAwait(t1.moveNext$0(), $async$_startPostingMessages$0);
             case 7:
               // returning from await.
               if (!$async$temp1.boolConversionCheck($async$result)) {
@@ -11135,7 +11192,7 @@
                 $async$goto = 6;
                 break;
               }
-              message = t2.get$current();
+              message = t1.get$current();
               $async$handler = 9;
               $async$goto = 12;
               return P._asyncAwait(W.HttpRequest_request($async$self._serverUrl, "POST", C.C_JsonCodec.encode$2$toEncodable(message, null), true), $async$_startPostingMessages$0);
@@ -11152,10 +11209,10 @@
               t3 = H.unwrapException($async$exception);
               if (t3 instanceof P.JsonUnsupportedObjectError) {
                 e = t3;
-                t1.log$4(C.Level_WARNING_900, "Unable to encode outgoing message: " + H.S(e), null, null);
+                t2.log$4(C.Level_WARNING_900, "Unable to encode outgoing message: " + H.S(e), null, null);
               } else if (t3 instanceof P.ArgumentError) {
                 e0 = t3;
-                t1.log$4(C.Level_WARNING_900, "Invalid argument: " + H.S(e0), null, null);
+                t2.log$4(C.Level_WARNING_900, "Invalid argument: " + H.S(e0), null, null);
               } else
                 throw $async$exception;
               // goto after finally
@@ -11184,7 +11241,7 @@
               // finally
               $async$handler = 1;
               $async$goto = 13;
-              return P._asyncAwait(t2.cancel$0(), $async$_startPostingMessages$0);
+              return P._asyncAwait(t1.cancel$0(), $async$_startPostingMessages$0);
             case 13:
               // returning from await.
               // goto the next finally handler
@@ -11226,7 +11283,7 @@
         t1 = this.$this,
         t2 = t1._incomingController,
         error = this.error;
-      P.ArgumentError_checkNotNull(error, "error", type$.Object);
+      H.checkNotNullable(error, "error", type$.Object);
       if (t2._state >= 4)
         H.throwExpression(t2._badEventState$0());
       stackTrace = P.AsyncError_defaultStackTrace(error);
@@ -11237,7 +11294,7 @@
         t2._ensurePendingEvents$0().add$1(0, new P._DelayedError(error, stackTrace));
       t1.close$0(0);
     },
-    $signature: 1
+    $signature: 3
   };
   R.StreamChannelMixin.prototype = {};
   K.Uuid.prototype = {
@@ -11278,11 +11335,10 @@
       _this._clockSeq = (t1 | t2) & 262143;
     },
     v1$0: function() {
-      var t1, buf, options, clockSeq, mSecs, nSecs, dt, t2, tl, tmh, node, n, _this = this,
+      var buf, options, clockSeq, mSecs, nSecs, dt, t2, tl, tmh, node, n, _this = this,
         _s8_ = "clockSeq",
-        _s5_ = "nSecs";
-      type$.legacy_Map_of_legacy_String_and_dynamic._as(null);
-      t1 = new Array(16);
+        _s5_ = "nSecs",
+        t1 = new Array(16);
       t1.fixed$length = Array;
       buf = H.setRuntimeTypeInfo(t1, type$.JSArray_legacy_int);
       options = new H.JsLinkedHashMap(type$.JsLinkedHashMap_of_legacy_String_and_dynamic);
@@ -11314,8 +11370,8 @@
       C.JSArray_methods.$indexSet(buf, 5, tmh & 255);
       C.JSArray_methods.$indexSet(buf, 6, tmh >>> 24 & 15 | 16);
       C.JSArray_methods.$indexSet(buf, 7, tmh >>> 16 & 255);
-      t1 = J.getInterceptor$n(clockSeq);
-      C.JSArray_methods.$indexSet(buf, 8, (t1.$shr(clockSeq, 8) | 128) >>> 0);
+      t1 = J.getInterceptor$bn(clockSeq);
+      C.JSArray_methods.$indexSet(buf, 8, (J.$shr$n(t1.$and(clockSeq, 16128), 8) | 128) >>> 0);
       C.JSArray_methods.$indexSet(buf, 9, H._asIntS(t1.$and(clockSeq, 255)));
       node = options.$index(0, "node") != null ? options.$index(0, "node") : _this._nodeId;
       for (t1 = J.getInterceptor$asx(node), n = 0; n < 6; ++n)
@@ -11365,13 +11421,13 @@
     call$1: function(e) {
       return Q.createServiceObject(e, this.expectedTypes);
     },
-    $signature: 29
+    $signature: 30
   };
   Q._createSpecificObject_closure.prototype = {
     call$1: function(e) {
       return this.creator.call$1(type$.legacy_Map_of_legacy_String_and_dynamic._as(e));
     },
-    $signature: 3
+    $signature: 2
   };
   Q.VmService.prototype = {
     _getEventController$1: function(eventName) {
@@ -11565,8 +11621,7 @@
       return P._asyncStartSync($async$_processNotification$1, $async$completer);
     },
     _routeRequest$2: function(method, params) {
-      type$.legacy_Map_of_legacy_String_and_dynamic._as(params);
-      return this._routeRequest$body$VmService(method, params);
+      return this._routeRequest$body$VmService(method, type$.legacy_Map_of_legacy_String_and_dynamic._as(params));
     },
     _routeRequest$body$VmService: function(method, params) {
       var $async$goto = 0,
@@ -11696,7 +11751,7 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["members", P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.AllocationProfile_toJson_closure()), t5), true, t5._eval$1("ListIterable.E")), "memoryUsage", _this.memoryUsage.toJson$0()], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["members", P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.AllocationProfile_toJson_closure()), t5), true, t5._eval$1("ListIterable.E")), "memoryUsage", _this.memoryUsage.toJson$0()], t1, t2));
       Q._setIfNotNull(json, "dateLastAccumulatorReset", _this.dateLastAccumulatorReset);
       Q._setIfNotNull(json, "dateLastServiceGC", _this.dateLastServiceGC);
       return json;
@@ -11712,7 +11767,7 @@
     call$1: function(f) {
       return type$.legacy_ClassHeapStats._as(f).toJson$0();
     },
-    $signature: 30
+    $signature: 31
   };
   Q.BoundField.prototype = {
     toJson$0: function() {
@@ -11795,22 +11850,22 @@
       t5.toString;
       t6 = H._arrayInstanceType(t5);
       t7 = t6._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t7 = P.List_List$from(new H.MappedListIterable(t5, t6._eval$1("Map<String*,@>*(1)")._as(new Q.Class_toJson_closure()), t7), true, t7._eval$1("ListIterable.E"));
+      t7 = P.List_List$of(new H.MappedListIterable(t5, t6._eval$1("Map<String*,@>*(1)")._as(new Q.Class_toJson_closure()), t7), true, t7._eval$1("ListIterable.E"));
       t6 = _this.fields;
       t6.toString;
       t5 = H._arrayInstanceType(t6);
       t8 = t5._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t8 = P.List_List$from(new H.MappedListIterable(t6, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Class_toJson_closure0()), t8), true, t8._eval$1("ListIterable.E"));
+      t8 = P.List_List$of(new H.MappedListIterable(t6, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Class_toJson_closure0()), t8), true, t8._eval$1("ListIterable.E"));
       t5 = _this.functions;
       t5.toString;
       t6 = H._arrayInstanceType(t5);
       t9 = t6._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t9 = P.List_List$from(new H.MappedListIterable(t5, t6._eval$1("Map<String*,@>*(1)")._as(new Q.Class_toJson_closure1()), t9), true, t9._eval$1("ListIterable.E"));
+      t9 = P.List_List$of(new H.MappedListIterable(t5, t6._eval$1("Map<String*,@>*(1)")._as(new Q.Class_toJson_closure1()), t9), true, t9._eval$1("ListIterable.E"));
       t6 = _this.subclasses;
       t6.toString;
       t5 = H._arrayInstanceType(t6);
       t10 = t5._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["name", t1, "abstract", t2, "const", t3, "library", t4, "interfaces", t7, "fields", t8, "functions", t9, "subclasses", P.List_List$from(new H.MappedListIterable(t6, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Class_toJson_closure2()), t10), true, t10._eval$1("ListIterable.E"))], type$.legacy_String, type$.dynamic));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["name", t1, "abstract", t2, "const", t3, "library", t4, "interfaces", t7, "fields", t8, "functions", t9, "subclasses", P.List_List$of(new H.MappedListIterable(t6, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Class_toJson_closure2()), t10), true, t10._eval$1("ListIterable.E"))], type$.legacy_String, type$.dynamic));
       t10 = _this.error;
       Q._setIfNotNull(json, "error", t10 == null ? _null : t10.toJson$0());
       t1 = _this.location;
@@ -11898,7 +11953,7 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["classes", P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.ClassList_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["classes", P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.ClassList_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -12000,7 +12055,7 @@
       t2.toString;
       t3 = H._arrayInstanceType(t2);
       t4 = t3._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["length", t1, "variables", P.List_List$from(new H.MappedListIterable(t2, t3._eval$1("Map<String*,@>*(1)")._as(new Q.Context_toJson_closure()), t4), true, t4._eval$1("ListIterable.E"))], type$.legacy_String, type$.dynamic));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["length", t1, "variables", P.List_List$of(new H.MappedListIterable(t2, t3._eval$1("Map<String*,@>*(1)")._as(new Q.Context_toJson_closure()), t4), true, t4._eval$1("ListIterable.E"))], type$.legacy_String, type$.dynamic));
       t4 = _this.parent;
       Q._setIfNotNull(json, "parent", t4 == null ? null : t4.toJson$0());
       return json;
@@ -12029,7 +12084,7 @@
     call$1: function(f) {
       return type$.legacy_ContextElement._as(f).toJson$0();
     },
-    $signature: 35
+    $signature: 36
   };
   Q.ContextElement.prototype = {
     toJson$0: function() {
@@ -12061,12 +12116,12 @@
       t10.toString;
       t11 = H._arrayInstanceType(t10);
       t12 = t11._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t12 = P.List_List$from(new H.MappedListIterable(t10, t11._eval$1("Map<String*,@>*(1)")._as(new Q.CpuSamples_toJson_closure()), t12), true, t12._eval$1("ListIterable.E"));
+      t12 = P.List_List$of(new H.MappedListIterable(t10, t11._eval$1("Map<String*,@>*(1)")._as(new Q.CpuSamples_toJson_closure()), t12), true, t12._eval$1("ListIterable.E"));
       t11 = _this.samples;
       t11.toString;
       t10 = H._arrayInstanceType(t11);
       t13 = t10._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["samplePeriod", t3, "maxStackDepth", t4, "sampleCount", t5, "timeSpan", t6, "timeOriginMicros", t7, "timeExtentMicros", t8, "pid", t9, "functions", t12, "samples", P.List_List$from(new H.MappedListIterable(t11, t10._eval$1("Map<String*,@>*(1)")._as(new Q.CpuSamples_toJson_closure0()), t13), true, t13._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["samplePeriod", t3, "maxStackDepth", t4, "sampleCount", t5, "timeSpan", t6, "timeOriginMicros", t7, "timeExtentMicros", t8, "pid", t9, "functions", t12, "samples", P.List_List$of(new H.MappedListIterable(t11, t10._eval$1("Map<String*,@>*(1)")._as(new Q.CpuSamples_toJson_closure0()), t13), true, t13._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -12083,13 +12138,13 @@
     call$1: function(f) {
       return type$.legacy_ProfileFunction._as(f).toJson$0();
     },
-    $signature: 36
+    $signature: 37
   };
   Q.CpuSamples_toJson_closure0.prototype = {
     call$1: function(f) {
       return type$.legacy_CpuSample._as(f).toJson$0();
     },
-    $signature: 37
+    $signature: 38
   };
   Q.CpuSample.prototype = {
     toJson$0: function() {
@@ -12103,7 +12158,7 @@
       t5.toString;
       t6 = H._arrayInstanceType(t5);
       t7 = t6._eval$1("MappedListIterable<1,int*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["tid", t3, "timestamp", t4, "stack", P.List_List$from(new H.MappedListIterable(t5, t6._eval$1("int*(1)")._as(new Q.CpuSample_toJson_closure()), t7), true, t7._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["tid", t3, "timestamp", t4, "stack", P.List_List$of(new H.MappedListIterable(t5, t6._eval$1("int*(1)")._as(new Q.CpuSample_toJson_closure()), t7), true, t7._eval$1("ListIterable.E"))], t1, t2));
       Q._setIfNotNull(json, "vmTag", _this.vmTag);
       Q._setIfNotNull(json, "userTag", _this.userTag);
       Q._setIfNotNull(json, "truncated", _this.truncated);
@@ -12190,7 +12245,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("Map<String*,@>*(1)")._as(new Q.Event_toJson_closure()), t2._eval$1("MappedListIterable<1,Map<String*,@>*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "pauseBreakpoints", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "pauseBreakpoints", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       t1 = _this.topFrame;
       Q._setIfNotNull(json, "topFrame", t1 == null ? _null : t1.toJson$0());
       t1 = _this.exception;
@@ -12210,7 +12265,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("Map<String*,@>*(1)")._as(new Q.Event_toJson_closure0()), t2._eval$1("MappedListIterable<1,Map<String*,@>*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "timelineEvents", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "timelineEvents", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       t1 = _this.updatedStreams;
       if (t1 == null)
         t1 = _null;
@@ -12219,7 +12274,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("String*(1)")._as(new Q.Event_toJson_closure1()), t2._eval$1("MappedListIterable<1,String*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "updatedStreams", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "updatedStreams", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       Q._setIfNotNull(json, "atAsyncSuspension", _this.atAsyncSuspension);
       Q._setIfNotNull(json, "status", _this.status);
       t1 = _this.logRecord;
@@ -12336,7 +12391,7 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["flags", P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.FlagList_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["flags", P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.FlagList_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -12350,7 +12405,7 @@
     call$1: function(f) {
       return type$.legacy_Flag._as(f).toJson$0();
     },
-    $signature: 42
+    $signature: 43
   };
   Q.Frame.prototype = {
     toJson$0: function() {
@@ -12374,7 +12429,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("Map<String*,@>*(1)")._as(new Q.Frame_toJson_closure()), t2._eval$1("MappedListIterable<1,Map<String*,@>*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "vars", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "vars", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       Q._setIfNotNull(json, "kind", _this.kind);
       return json;
     },
@@ -12390,7 +12445,7 @@
       type$.legacy_BoundVariable._as(f);
       return f == null ? null : f.toJson$0();
     },
-    $signature: 43
+    $signature: 44
   };
   Q.FuncRef.prototype = {
     toJson$0: function() {
@@ -12441,13 +12496,12 @@
   };
   Q.InstanceRef.prototype = {
     InstanceRef$_fromJson$1: function(json) {
-      var t1, t2, _this = this;
+      var t1, _this = this;
       _this.kind = H._asStringS(json.$index(0, "kind"));
       t1 = type$.legacy_ClassRef;
       _this.classRef = t1._as(Q.createServiceObject(json.$index(0, "class"), C.List_ClassRef));
       _this.set$valueAsString(H._asStringS(json.$index(0, "valueAsString")));
-      t2 = json.$index(0, "valueAsStringIsTruncated");
-      _this.valueAsStringIsTruncated = H._asBoolS(t2 == null ? false : t2);
+      _this.valueAsStringIsTruncated = H._asBoolS(json.$index(0, "valueAsStringIsTruncated"));
       _this.length = H._asIntS(json.$index(0, "length"));
       _this.name = H._asStringS(json.$index(0, "name"));
       _this.typeClass = t1._as(Q.createServiceObject(json.$index(0, "typeClass"), C.List_ClassRef));
@@ -12462,8 +12516,7 @@
       json.$indexSet(0, "type", "@Instance");
       json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["kind", _this.kind, "class", _this.classRef.toJson$0()], type$.legacy_String, type$.dynamic));
       Q._setIfNotNull(json, "valueAsString", _this.get$valueAsString());
-      t1 = _this.valueAsStringIsTruncated;
-      Q._setIfNotNull(json, "valueAsStringIsTruncated", t1 === true);
+      Q._setIfNotNull(json, "valueAsStringIsTruncated", _this.valueAsStringIsTruncated);
       Q._setIfNotNull(json, "length", _this.length);
       Q._setIfNotNull(json, "name", _this.name);
       t1 = _this.typeClass;
@@ -12502,24 +12555,23 @@
   };
   Q.Instance.prototype = {
     Instance$_fromJson$1: function(json) {
-      var t1, t2, _this = this,
+      var t1, _this = this,
         _s8_ = "elements",
         _s12_ = "associations";
       _this.kind = H._asStringS(json.$index(0, "kind"));
       t1 = type$.legacy_ClassRef;
       _this.Instance_classRef = t1._as(Q.createServiceObject(json.$index(0, "class"), C.List_ClassRef));
       _this.set$valueAsString(H._asStringS(json.$index(0, "valueAsString")));
-      t2 = json.$index(0, "valueAsStringIsTruncated");
-      _this.valueAsStringIsTruncated = H._asBoolS(t2 == null ? false : t2);
+      _this.valueAsStringIsTruncated = H._asBoolS(json.$index(0, "valueAsStringIsTruncated"));
       _this.length = H._asIntS(json.$index(0, "length"));
       _this.offset = H._asIntS(json.$index(0, "offset"));
       _this.count = H._asIntS(json.$index(0, "count"));
       _this.name = H._asStringS(json.$index(0, "name"));
       _this.typeClass = t1._as(Q.createServiceObject(json.$index(0, "typeClass"), C.List_ClassRef));
       _this.parameterizedClass = t1._as(Q.createServiceObject(json.$index(0, "parameterizedClass"), C.List_ClassRef));
-      _this.set$fields(json.$index(0, "fields") == null ? null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, "fields"), C.List_BoundField)), true, type$.legacy_BoundField));
-      _this.elements = json.$index(0, _s8_) == null ? null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, _s8_), C.List_dynamic)), true, type$.dynamic);
-      _this.set$associations(json.$index(0, _s12_) == null ? null : P.List_List$from(type$.Iterable_dynamic._as(Q._createSpecificObject(json.$index(0, _s12_), Q.vm_service_MapAssociation_parse$closure())), true, type$.legacy_MapAssociation));
+      _this.set$fields(json.$index(0, "fields") == null ? null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, "fields"), C.List_BoundField)), type$.legacy_BoundField));
+      _this.elements = json.$index(0, _s8_) == null ? null : P.List_List$from(type$.Iterable_dynamic._as(Q.createServiceObject(json.$index(0, _s8_), C.List_dynamic)), type$.dynamic);
+      _this.set$associations(json.$index(0, _s12_) == null ? null : P.List_List$from(type$.Iterable_dynamic._as(Q._createSpecificObject(json.$index(0, _s12_), Q.vm_service_MapAssociation_parse$closure())), type$.legacy_MapAssociation));
       _this.bytes = H._asStringS(json.$index(0, "bytes"));
       t1 = type$.legacy_InstanceRef;
       _this.mirrorReferent = t1._as(Q.createServiceObject(json.$index(0, "mirrorReferent"), C.List_InstanceRef));
@@ -12541,8 +12593,7 @@
       json.$indexSet(0, "type", "Instance");
       json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["kind", _this.kind, "class", _this.Instance_classRef.toJson$0()], type$.legacy_String, type$.dynamic));
       Q._setIfNotNull(json, "valueAsString", _this.get$valueAsString());
-      t1 = _this.valueAsStringIsTruncated;
-      Q._setIfNotNull(json, "valueAsStringIsTruncated", t1 === true);
+      Q._setIfNotNull(json, "valueAsStringIsTruncated", _this.valueAsStringIsTruncated);
       Q._setIfNotNull(json, "length", _this.length);
       Q._setIfNotNull(json, "offset", _this.offset);
       Q._setIfNotNull(json, "count", _this.count);
@@ -12559,7 +12610,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("Map<String*,@>*(1)")._as(new Q.Instance_toJson_closure()), t2._eval$1("MappedListIterable<1,Map<String*,@>*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "fields", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "fields", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       t1 = _this.elements;
       if (t1 == null)
         t1 = _null;
@@ -12568,7 +12619,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("@(1)")._as(new Q.Instance_toJson_closure0()), t2._eval$1("MappedListIterable<1,@>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "elements", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "elements", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       t1 = _this.associations;
       if (t1 == null)
         t1 = _null;
@@ -12577,7 +12628,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("Map<String*,@>*(1)")._as(new Q.Instance_toJson_closure1()), t2._eval$1("MappedListIterable<1,Map<String*,@>*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "associations", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "associations", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       Q._setIfNotNull(json, "bytes", _this.bytes);
       t1 = _this.mirrorReferent;
       Q._setIfNotNull(json, "mirrorReferent", t1 == null ? _null : t1.toJson$0());
@@ -12648,14 +12699,14 @@
     call$1: function(f) {
       return f == null ? null : f.toJson$0();
     },
-    $signature: 3
+    $signature: 2
   };
   Q.Instance_toJson_closure1.prototype = {
     call$1: function(f) {
       type$.legacy_MapAssociation._as(f);
       return f == null ? null : f.toJson$0();
     },
-    $signature: 45
+    $signature: 46
   };
   Q.IsolateRef.prototype = {
     toJson$0: function() {
@@ -12701,12 +12752,12 @@
       t11.toString;
       t12 = H._arrayInstanceType(t11);
       t13 = t12._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t13 = P.List_List$from(new H.MappedListIterable(t11, t12._eval$1("Map<String*,@>*(1)")._as(new Q.Isolate_toJson_closure()), t13), true, t13._eval$1("ListIterable.E"));
+      t13 = P.List_List$of(new H.MappedListIterable(t11, t12._eval$1("Map<String*,@>*(1)")._as(new Q.Isolate_toJson_closure()), t13), true, t13._eval$1("ListIterable.E"));
       t12 = _this.breakpoints;
       t12.toString;
       t11 = H._arrayInstanceType(t12);
       t14 = t11._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["id", t3, "number", t4, "name", t5, "startTime", t6, "runnable", t7, "livePorts", t8, "pauseOnExit", t9, "pauseEvent", t10, "libraries", t13, "breakpoints", P.List_List$from(new H.MappedListIterable(t12, t11._eval$1("Map<String*,@>*(1)")._as(new Q.Isolate_toJson_closure0()), t14), true, t14._eval$1("ListIterable.E")), "exceptionPauseMode", _this.exceptionPauseMode], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["id", t3, "number", t4, "name", t5, "startTime", t6, "runnable", t7, "livePorts", t8, "pauseOnExit", t9, "pauseEvent", t10, "libraries", t13, "breakpoints", P.List_List$of(new H.MappedListIterable(t12, t11._eval$1("Map<String*,@>*(1)")._as(new Q.Isolate_toJson_closure0()), t14), true, t14._eval$1("ListIterable.E")), "exceptionPauseMode", _this.exceptionPauseMode], t1, t2));
       t2 = _this.rootLib;
       Q._setIfNotNull(json, "rootLib", t2 == null ? _null : t2.toJson$0());
       t1 = _this.error;
@@ -12719,7 +12770,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("String*(1)")._as(new Q.Isolate_toJson_closure1()), t2._eval$1("MappedListIterable<1,String*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "extensionRPCs", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "extensionRPCs", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       return json;
     },
     get$hashCode: function(_) {
@@ -12751,7 +12802,7 @@
     call$1: function(f) {
       return type$.legacy_LibraryRef._as(f).toJson$0();
     },
-    $signature: 46
+    $signature: 47
   };
   Q.Isolate_toJson_closure0.prototype = {
     call$1: function(f) {
@@ -12804,7 +12855,7 @@
       t6.toString;
       t7 = H._arrayInstanceType(t6);
       t8 = t7._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["id", t3, "number", t4, "name", t5, "isolates", P.List_List$from(new H.MappedListIterable(t6, t7._eval$1("Map<String*,@>*(1)")._as(new Q.IsolateGroup_toJson_closure()), t8), true, t8._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["id", t3, "number", t4, "name", t5, "isolates", P.List_List$of(new H.MappedListIterable(t6, t7._eval$1("Map<String*,@>*(1)")._as(new Q.IsolateGroup_toJson_closure()), t8), true, t8._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     get$hashCode: function(_) {
@@ -12844,7 +12895,7 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["references", P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.InboundReferences_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["references", P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.InboundReferences_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -12858,7 +12909,7 @@
     call$1: function(f) {
       return type$.legacy_InboundReference._as(f).toJson$0();
     },
-    $signature: 48
+    $signature: 49
   };
   Q.InboundReference.prototype = {
     toJson$0: function() {
@@ -12887,7 +12938,7 @@
       t4.toString;
       t5 = H._arrayInstanceType(t4);
       t6 = t5._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["totalCount", t3, "instances", P.List_List$from(new H.MappedListIterable(t4, t5._eval$1("Map<String*,@>*(1)")._as(new Q.InstanceSet_toJson_closure()), t6), true, t6._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["totalCount", t3, "instances", P.List_List$of(new H.MappedListIterable(t4, t5._eval$1("Map<String*,@>*(1)")._as(new Q.InstanceSet_toJson_closure()), t6), true, t6._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -12901,7 +12952,7 @@
     call$1: function(f) {
       return type$.legacy_ObjRef._as(f).toJson$0();
     },
-    $signature: 49
+    $signature: 50
   };
   Q.LibraryRef.prototype = {
     toJson$0: function() {
@@ -12935,27 +12986,27 @@
       t4.toString;
       t5 = H._arrayInstanceType(t4);
       t6 = t5._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t6 = P.List_List$from(new H.MappedListIterable(t4, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure()), t6), true, t6._eval$1("ListIterable.E"));
+      t6 = P.List_List$of(new H.MappedListIterable(t4, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure()), t6), true, t6._eval$1("ListIterable.E"));
       t5 = _this.scripts;
       t5.toString;
       t4 = H._arrayInstanceType(t5);
       t7 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t7 = P.List_List$from(new H.MappedListIterable(t5, t4._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure0()), t7), true, t7._eval$1("ListIterable.E"));
+      t7 = P.List_List$of(new H.MappedListIterable(t5, t4._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure0()), t7), true, t7._eval$1("ListIterable.E"));
       t4 = _this.variables;
       t4.toString;
       t5 = H._arrayInstanceType(t4);
       t8 = t5._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t8 = P.List_List$from(new H.MappedListIterable(t4, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure1()), t8), true, t8._eval$1("ListIterable.E"));
+      t8 = P.List_List$of(new H.MappedListIterable(t4, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure1()), t8), true, t8._eval$1("ListIterable.E"));
       t5 = _this.functions;
       t5.toString;
       t4 = H._arrayInstanceType(t5);
       t9 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t9 = P.List_List$from(new H.MappedListIterable(t5, t4._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure2()), t9), true, t9._eval$1("ListIterable.E"));
+      t9 = P.List_List$of(new H.MappedListIterable(t5, t4._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure2()), t9), true, t9._eval$1("ListIterable.E"));
       t4 = _this.classes;
       t4.toString;
       t5 = H._arrayInstanceType(t4);
       t10 = t5._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["name", t1, "uri", t2, "debuggable", t3, "dependencies", t6, "scripts", t7, "variables", t8, "functions", t9, "classes", P.List_List$from(new H.MappedListIterable(t4, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure3()), t10), true, t10._eval$1("ListIterable.E"))], type$.legacy_String, type$.dynamic));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["name", t1, "uri", t2, "debuggable", t3, "dependencies", t6, "scripts", t7, "variables", t8, "functions", t9, "classes", P.List_List$of(new H.MappedListIterable(t4, t5._eval$1("Map<String*,@>*(1)")._as(new Q.Library_toJson_closure3()), t10), true, t10._eval$1("ListIterable.E"))], type$.legacy_String, type$.dynamic));
       return json;
     },
     get$hashCode: function(_) {
@@ -12990,7 +13041,7 @@
     call$1: function(f) {
       return type$.legacy_LibraryDependency._as(f).toJson$0();
     },
-    $signature: 50
+    $signature: 51
   };
   Q.Library_toJson_closure0.prototype = {
     call$1: function(f) {
@@ -13240,6 +13291,45 @@
       return "[ProfileFunction kind: " + H.S(_this.kind) + ", inclusiveTicks: " + H.S(_this.inclusiveTicks) + ", exclusiveTicks: " + H.S(_this.exclusiveTicks) + ", resolvedUrl: " + H.S(_this.resolvedUrl) + ", function: " + H.S(_this.$function) + "]";
     }
   };
+  Q.ProtocolList.prototype = {
+    toJson$0: function() {
+      var t3, t4, t5,
+        t1 = type$.legacy_String,
+        t2 = type$.dynamic,
+        json = P.LinkedHashMap_LinkedHashMap$_empty(t1, t2);
+      json.$indexSet(0, "type", "ProtocolList");
+      t3 = this.protocols;
+      t3.toString;
+      t4 = H._arrayInstanceType(t3);
+      t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["protocols", P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.ProtocolList_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
+      return json;
+    },
+    toString$0: function(_) {
+      return "[ProtocolList type: " + H.S(this.type) + ", protocols: " + H.S(this.protocols) + "]";
+    },
+    set$protocols: function(protocols) {
+      this.protocols = type$.legacy_List_legacy_Protocol._as(protocols);
+    }
+  };
+  Q.ProtocolList_toJson_closure.prototype = {
+    call$1: function(f) {
+      return type$.legacy_Protocol._as(f).toJson$0();
+    },
+    $signature: 53
+  };
+  Q.Protocol.prototype = {
+    toJson$0: function() {
+      var t1 = type$.legacy_String,
+        t2 = type$.dynamic,
+        json = P.LinkedHashMap_LinkedHashMap$_empty(t1, t2);
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["protocolName", this.protocolName, "major", this.major, "minor", this.minor], t1, t2));
+      return json;
+    },
+    toString$0: function(_) {
+      return "[Protocol protocolName: " + H.S(this.protocolName) + ", major: " + H.S(this.major) + ", minor: " + H.S(this.minor) + "]";
+    }
+  };
   Q.ReloadReport.prototype = {
     toJson$0: function() {
       var t1 = type$.legacy_String,
@@ -13283,7 +13373,7 @@
       t5.toString;
       t6 = H._arrayInstanceType(t5);
       t7 = t6._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["length", t3, "gcRootType", t4, "elements", P.List_List$from(new H.MappedListIterable(t5, t6._eval$1("Map<String*,@>*(1)")._as(new Q.RetainingPath_toJson_closure()), t7), true, t7._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["length", t3, "gcRootType", t4, "elements", P.List_List$of(new H.MappedListIterable(t5, t6._eval$1("Map<String*,@>*(1)")._as(new Q.RetainingPath_toJson_closure()), t7), true, t7._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -13301,7 +13391,7 @@
     call$1: function(f) {
       return type$.legacy_RetainingObject._as(f).toJson$0();
     },
-    $signature: 52
+    $signature: 54
   };
   Q.Response.prototype = {
     toJson$0: function() {
@@ -13355,7 +13445,7 @@
       _this.lineOffset = H._asIntS(json.$index(0, "lineOffset"));
       _this.columnOffset = H._asIntS(json.$index(0, "columnOffset"));
       _this.source = H._asStringS(json.$index(0, "source"));
-      _this.set$tokenPosTable(json.$index(0, _s13_) == null ? null : P.List_List$from(type$.Iterable_dynamic._as(J.map$1$ax(json.$index(0, _s13_), new Q.Script$_fromJson_closure())), true, type$.legacy_List_legacy_int));
+      _this.set$tokenPosTable(json.$index(0, _s13_) == null ? null : P.List_List$from(type$.Iterable_dynamic._as(J.map$1$ax(json.$index(0, _s13_), new Q.Script$_fromJson_closure())), type$.legacy_List_legacy_int));
       _this._parseTokenPosTable$0();
     },
     _parseTokenPosTable$0: function() {
@@ -13392,7 +13482,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("List<int*>*(1)")._as(new Q.Script_toJson_closure()), t2._eval$1("MappedListIterable<1,List<int*>*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "tokenPosTable", t1 == null ? null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "tokenPosTable", t1 == null ? null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       return json;
     },
     get$hashCode: function(_) {
@@ -13414,16 +13504,16 @@
   };
   Q.Script$_fromJson_closure.prototype = {
     call$1: function(list) {
-      return P.List_List$from(type$.Iterable_dynamic._as(list), true, type$.legacy_int);
+      return P.List_List$from(type$.Iterable_dynamic._as(list), type$.legacy_int);
     },
-    $signature: 53
+    $signature: 55
   };
   Q.Script_toJson_closure.prototype = {
     call$1: function(f) {
       type$.legacy_List_legacy_int._as(f);
       return f == null ? null : J.toList$0$ax(f);
     },
-    $signature: 54
+    $signature: 56
   };
   Q.ScriptList.prototype = {
     toJson$0: function() {
@@ -13436,7 +13526,7 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["scripts", P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.ScriptList_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["scripts", P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.ScriptList_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -13477,12 +13567,12 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t5 = P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.SourceReport_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"));
+      t5 = P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.SourceReport_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"));
       t4 = this.scripts;
       t4.toString;
       t3 = H._arrayInstanceType(t4);
       t6 = t3._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["ranges", t5, "scripts", P.List_List$from(new H.MappedListIterable(t4, t3._eval$1("Map<String*,@>*(1)")._as(new Q.SourceReport_toJson_closure0()), t6), true, t6._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["ranges", t5, "scripts", P.List_List$of(new H.MappedListIterable(t4, t3._eval$1("Map<String*,@>*(1)")._as(new Q.SourceReport_toJson_closure0()), t6), true, t6._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -13499,7 +13589,7 @@
     call$1: function(f) {
       return type$.legacy_SourceReportRange._as(f).toJson$0();
     },
-    $signature: 55
+    $signature: 57
   };
   Q.SourceReport_toJson_closure0.prototype = {
     call$1: function(f) {
@@ -13517,12 +13607,12 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,int*>");
-      t5 = P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("int*(1)")._as(new Q.SourceReportCoverage_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"));
+      t5 = P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("int*(1)")._as(new Q.SourceReportCoverage_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"));
       t4 = this.misses;
       t4.toString;
       t3 = H._arrayInstanceType(t4);
       t6 = t3._eval$1("MappedListIterable<1,int*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["hits", t5, "misses", P.List_List$from(new H.MappedListIterable(t4, t3._eval$1("int*(1)")._as(new Q.SourceReportCoverage_toJson_closure0()), t6), true, t6._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["hits", t5, "misses", P.List_List$of(new H.MappedListIterable(t4, t3._eval$1("int*(1)")._as(new Q.SourceReportCoverage_toJson_closure0()), t6), true, t6._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -13566,7 +13656,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("int*(1)")._as(new Q.SourceReportRange_toJson_closure()), t2._eval$1("MappedListIterable<1,int*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "possibleBreakpoints", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "possibleBreakpoints", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       return json;
     },
     toString$0: function(_) {
@@ -13594,12 +13684,12 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t5 = P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.Stack_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"));
+      t5 = P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.Stack_toJson_closure()), t5), true, t5._eval$1("ListIterable.E"));
       t4 = _this.messages;
       t4.toString;
       t3 = H._arrayInstanceType(t4);
       t6 = t3._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["frames", t5, "messages", P.List_List$from(new H.MappedListIterable(t4, t3._eval$1("Map<String*,@>*(1)")._as(new Q.Stack_toJson_closure0()), t6), true, t6._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["frames", t5, "messages", P.List_List$of(new H.MappedListIterable(t4, t3._eval$1("Map<String*,@>*(1)")._as(new Q.Stack_toJson_closure0()), t6), true, t6._eval$1("ListIterable.E"))], t1, t2));
       t2 = _this.asyncCausalFrames;
       if (t2 == null)
         t1 = _null;
@@ -13607,7 +13697,7 @@
         t1 = H._arrayInstanceType(t2);
         t1 = new H.MappedListIterable(t2, t1._eval$1("Map<String*,@>*(1)")._as(new Q.Stack_toJson_closure1()), t1._eval$1("MappedListIterable<1,Map<String*,@>*>"));
       }
-      Q._setIfNotNull(json, "asyncCausalFrames", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "asyncCausalFrames", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       t1 = _this.awaiterFrames;
       if (t1 == null)
         t1 = _null;
@@ -13616,7 +13706,7 @@
         t2 = new H.MappedListIterable(t1, t2._eval$1("Map<String*,@>*(1)")._as(new Q.Stack_toJson_closure2()), t2._eval$1("MappedListIterable<1,Map<String*,@>*>"));
         t1 = t2;
       }
-      Q._setIfNotNull(json, "awaiterFrames", t1 == null ? _null : P.List_List$from(t1, true, t1.$ti._eval$1("ListIterable.E")));
+      Q._setIfNotNull(json, "awaiterFrames", t1 == null ? _null : P.List_List$of(t1, true, t1.$ti._eval$1("ListIterable.E")));
       return json;
     },
     toString$0: function(_) {
@@ -13645,7 +13735,7 @@
     call$1: function(f) {
       return type$.legacy_Message._as(f).toJson$0();
     },
-    $signature: 57
+    $signature: 59
   };
   Q.Stack_toJson_closure1.prototype = {
     call$1: function(f) {
@@ -13682,7 +13772,7 @@
       t3.toString;
       t4 = H._arrayInstanceType(t3);
       t5 = t4._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["traceEvents", P.List_List$from(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.Timeline_toJson_closure()), t5), true, t5._eval$1("ListIterable.E")), "timeOriginMicros", this.timeOriginMicros, "timeExtentMicros", this.timeExtentMicros], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["traceEvents", P.List_List$of(new H.MappedListIterable(t3, t4._eval$1("Map<String*,@>*(1)")._as(new Q.Timeline_toJson_closure()), t5), true, t5._eval$1("ListIterable.E")), "timeOriginMicros", this.timeOriginMicros, "timeExtentMicros", this.timeExtentMicros], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -13721,12 +13811,12 @@
       t4.toString;
       t5 = H._arrayInstanceType(t4);
       t6 = t5._eval$1("MappedListIterable<1,String*>");
-      t6 = P.List_List$from(new H.MappedListIterable(t4, t5._eval$1("String*(1)")._as(new Q.TimelineFlags_toJson_closure()), t6), true, t6._eval$1("ListIterable.E"));
+      t6 = P.List_List$of(new H.MappedListIterable(t4, t5._eval$1("String*(1)")._as(new Q.TimelineFlags_toJson_closure()), t6), true, t6._eval$1("ListIterable.E"));
       t5 = this.recordedStreams;
       t5.toString;
       t4 = H._arrayInstanceType(t5);
       t7 = t4._eval$1("MappedListIterable<1,String*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["recorderName", t3, "availableStreams", t6, "recordedStreams", P.List_List$from(new H.MappedListIterable(t5, t4._eval$1("String*(1)")._as(new Q.TimelineFlags_toJson_closure0()), t7), true, t7._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["recorderName", t3, "availableStreams", t6, "recordedStreams", P.List_List$of(new H.MappedListIterable(t5, t4._eval$1("String*(1)")._as(new Q.TimelineFlags_toJson_closure0()), t7), true, t7._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -13794,7 +13884,7 @@
       t2.toString;
       t3 = H._arrayInstanceType(t2);
       t4 = t3._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["name", t1, "types", P.List_List$from(new H.MappedListIterable(t2, t3._eval$1("Map<String*,@>*(1)")._as(new Q.TypeArguments_toJson_closure()), t4), true, t4._eval$1("ListIterable.E"))], type$.legacy_String, type$.dynamic));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["name", t1, "types", P.List_List$of(new H.MappedListIterable(t2, t3._eval$1("Map<String*,@>*(1)")._as(new Q.TypeArguments_toJson_closure()), t4), true, t4._eval$1("ListIterable.E"))], type$.legacy_String, type$.dynamic));
       return json;
     },
     get$hashCode: function(_) {
@@ -13882,12 +13972,12 @@
       t11.toString;
       t12 = H._arrayInstanceType(t11);
       t13 = t12._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      t13 = P.List_List$from(new H.MappedListIterable(t11, t12._eval$1("Map<String*,@>*(1)")._as(new Q.VM_toJson_closure()), t13), true, t13._eval$1("ListIterable.E"));
+      t13 = P.List_List$of(new H.MappedListIterable(t11, t12._eval$1("Map<String*,@>*(1)")._as(new Q.VM_toJson_closure()), t13), true, t13._eval$1("ListIterable.E"));
       t12 = _this.isolateGroups;
       t12.toString;
       t11 = H._arrayInstanceType(t12);
       t14 = t11._eval$1("MappedListIterable<1,Map<String*,@>*>");
-      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["name", t3, "architectureBits", t4, "hostCPU", t5, "operatingSystem", t6, "targetCPU", t7, "version", t8, "pid", t9, "startTime", t10, "isolates", t13, "isolateGroups", P.List_List$from(new H.MappedListIterable(t12, t11._eval$1("Map<String*,@>*(1)")._as(new Q.VM_toJson_closure0()), t14), true, t14._eval$1("ListIterable.E"))], t1, t2));
+      json.addAll$1(0, P.LinkedHashMap_LinkedHashMap$_literal(["name", t3, "architectureBits", t4, "hostCPU", t5, "operatingSystem", t6, "targetCPU", t7, "version", t8, "pid", t9, "startTime", t10, "isolates", t13, "isolateGroups", P.List_List$of(new H.MappedListIterable(t12, t11._eval$1("Map<String*,@>*(1)")._as(new Q.VM_toJson_closure0()), t14), true, t14._eval$1("ListIterable.E"))], t1, t2));
       return json;
     },
     toString$0: function(_) {
@@ -13911,7 +14001,7 @@
     call$1: function(f) {
       return type$.legacy_IsolateGroupRef._as(f).toJson$0();
     },
-    $signature: 58
+    $signature: 60
   };
   E.main_closure.prototype = {
     call$1: function(e) {
@@ -13919,7 +14009,7 @@
       t1.add$1(0, H._instanceType(t1)._precomputed1._as(e));
       return null;
     },
-    $signature: 59
+    $signature: 61
   };
   (function aliases() {
     var _ = J.Interceptor.prototype;
@@ -13952,12 +14042,12 @@
     _static_1(P, "async__AsyncRun__scheduleImmediateWithSetImmediate$closure", "_AsyncRun__scheduleImmediateWithSetImmediate", 6);
     _static_1(P, "async__AsyncRun__scheduleImmediateWithTimer$closure", "_AsyncRun__scheduleImmediateWithTimer", 6);
     _static_0(P, "async___startMicrotaskLoop$closure", "_startMicrotaskLoop", 0);
-    _static_1(P, "async___nullDataHandler$closure", "_nullDataHandler", 2);
+    _static_1(P, "async___nullDataHandler$closure", "_nullDataHandler", 1);
     _static_2(P, "async___nullErrorHandler$closure", "_nullErrorHandler", 7);
     var _;
     _instance_0_u(_ = P._BroadcastSubscription.prototype, "get$_onPause", "_onPause$0", 0);
     _instance_0_u(_, "get$_onResume", "_onResume$0", 0);
-    _instance(P._Completer.prototype, "get$completeError", 0, 1, null, ["call$2", "call$1"], ["completeError$2", "completeError$1"], 39, 0);
+    _instance(P._Completer.prototype, "get$completeError", 0, 1, null, ["call$2", "call$1"], ["completeError$2", "completeError$1"], 48, 0);
     _instance_2_u(P._Future.prototype, "get$_completeError", "_completeError$2", 7);
     _instance_0_u(_ = P._ControllerSubscription.prototype, "get$_onPause", "_onPause$0", 0);
     _instance_0_u(_, "get$_onResume", "_onResume$0", 0);
@@ -13970,98 +14060,102 @@
     _instance_0_u(_ = P._ForwardingStreamSubscription.prototype, "get$_onPause", "_onPause$0", 0);
     _instance_0_u(_, "get$_onResume", "_onResume$0", 0);
     _instance_1_u(_, "get$_handleData", "_handleData$1", 12);
-    _instance_2_u(_, "get$_handleError", "_handleError$2", 32);
+    _instance_2_u(_, "get$_handleError", "_handleError$2", 34);
     _instance_0_u(_, "get$_handleDone", "_handleDone$0", 0);
-    _static_1(P, "convert___defaultToEncodable$closure", "_defaultToEncodable", 3);
+    _static_1(P, "convert___defaultToEncodable$closure", "_defaultToEncodable", 2);
     _instance_1_u(_ = M.SseClient.prototype, "get$_onIncomingControlMessage", "_onIncomingControlMessage$1", 18);
     _instance_1_u(_, "get$_onIncomingMessage", "_onIncomingMessage$1", 18);
     _instance_0_u(_, "get$_onOutgoingDone", "_onOutgoingDone$0", 0);
-    _instance_1_u(_, "get$_onOutgoingMessage", "_onOutgoingMessage$1", 2);
-    _static_1(Q, "vm_service_ExtensionData_parse$closure", "ExtensionData_parse", 61);
-    _static_1(Q, "vm_service_AllocationProfile_parse$closure", "AllocationProfile_parse", 62);
-    _static_1(Q, "vm_service_BoundField_parse$closure", "BoundField_parse", 63);
-    _static_1(Q, "vm_service_BoundVariable_parse$closure", "BoundVariable_parse", 64);
-    _static_1(Q, "vm_service_Breakpoint_parse$closure", "Breakpoint_parse", 65);
-    _static_1(Q, "vm_service_ClassRef_parse$closure", "ClassRef_parse", 66);
-    _static_1(Q, "vm_service_Class_parse$closure", "Class_parse", 67);
-    _static_1(Q, "vm_service_ClassHeapStats_parse$closure", "ClassHeapStats_parse", 68);
-    _static_1(Q, "vm_service_ClassList_parse$closure", "ClassList_parse", 69);
-    _static_1(Q, "vm_service_ClientName_parse$closure", "ClientName_parse", 70);
-    _static_1(Q, "vm_service_CodeRef_parse$closure", "CodeRef_parse", 71);
-    _static_1(Q, "vm_service_Code_parse$closure", "Code_parse", 72);
-    _static_1(Q, "vm_service_ContextRef_parse$closure", "ContextRef_parse", 73);
-    _static_1(Q, "vm_service_Context_parse$closure", "Context_parse", 74);
-    _static_1(Q, "vm_service_ContextElement_parse$closure", "ContextElement_parse", 75);
-    _static_1(Q, "vm_service_CpuSamples_parse$closure", "CpuSamples_parse", 76);
-    _static_1(Q, "vm_service_CpuSample_parse$closure", "CpuSample_parse", 77);
-    _static_1(Q, "vm_service_ErrorRef_parse$closure", "ErrorRef_parse", 78);
-    _static_1(Q, "vm_service_Error_parse$closure", "Error_parse", 79);
-    _static_1(Q, "vm_service_Event_parse$closure", "Event_parse", 80);
-    _static_1(Q, "vm_service_FieldRef_parse$closure", "FieldRef_parse", 81);
-    _static_1(Q, "vm_service_Field_parse$closure", "Field_parse", 82);
-    _static_1(Q, "vm_service_Flag_parse$closure", "Flag_parse", 83);
-    _static_1(Q, "vm_service_FlagList_parse$closure", "FlagList_parse", 84);
-    _static_1(Q, "vm_service_Frame_parse$closure", "Frame_parse", 85);
-    _static_1(Q, "vm_service_FuncRef_parse$closure", "FuncRef_parse", 86);
-    _static_1(Q, "vm_service_Func_parse$closure", "Func_parse", 87);
-    _static_1(Q, "vm_service_InstanceRef_parse$closure", "InstanceRef_parse", 133);
-    _static_1(Q, "vm_service_Instance_parse$closure", "Instance_parse", 89);
-    _static_1(Q, "vm_service_IsolateRef_parse$closure", "IsolateRef_parse", 90);
-    _static_1(Q, "vm_service_Isolate_parse$closure", "Isolate_parse", 91);
-    _static_1(Q, "vm_service_IsolateGroupRef_parse$closure", "IsolateGroupRef_parse", 92);
-    _static_1(Q, "vm_service_IsolateGroup_parse$closure", "IsolateGroup_parse", 93);
-    _static_1(Q, "vm_service_InboundReferences_parse$closure", "InboundReferences_parse", 94);
-    _static_1(Q, "vm_service_InboundReference_parse$closure", "InboundReference_parse", 95);
-    _static_1(Q, "vm_service_InstanceSet_parse$closure", "InstanceSet_parse", 96);
-    _static_1(Q, "vm_service_LibraryRef_parse$closure", "LibraryRef_parse", 97);
-    _static_1(Q, "vm_service_Library_parse$closure", "Library_parse", 98);
-    _static_1(Q, "vm_service_LibraryDependency_parse$closure", "LibraryDependency_parse", 99);
-    _static_1(Q, "vm_service_LogRecord_parse$closure", "LogRecord_parse", 100);
-    _static_1(Q, "vm_service_MapAssociation_parse$closure", "MapAssociation_parse", 101);
-    _static_1(Q, "vm_service_MemoryUsage_parse$closure", "MemoryUsage_parse", 102);
-    _static_1(Q, "vm_service_Message_parse$closure", "Message_parse", 103);
-    _static_1(Q, "vm_service_NativeFunction_parse$closure", "NativeFunction_parse", 104);
-    _static_1(Q, "vm_service_NullValRef_parse$closure", "NullValRef_parse", 105);
-    _static_1(Q, "vm_service_NullVal_parse$closure", "NullVal_parse", 106);
-    _static_1(Q, "vm_service_ObjRef_parse$closure", "ObjRef_parse", 107);
-    _static_1(Q, "vm_service_Obj_parse$closure", "Obj_parse", 108);
-    _static_1(Q, "vm_service_ProfileFunction_parse$closure", "ProfileFunction_parse", 109);
-    _static_1(Q, "vm_service_ReloadReport_parse$closure", "ReloadReport_parse", 110);
-    _static_1(Q, "vm_service_RetainingObject_parse$closure", "RetainingObject_parse", 111);
-    _static_1(Q, "vm_service_RetainingPath_parse$closure", "RetainingPath_parse", 112);
-    _static_1(Q, "vm_service_Response_parse$closure", "Response_parse", 113);
-    _static_1(Q, "vm_service_Sentinel_parse$closure", "Sentinel_parse", 114);
-    _static_1(Q, "vm_service_ScriptRef_parse$closure", "ScriptRef_parse", 115);
-    _static_1(Q, "vm_service_Script_parse$closure", "Script_parse", 116);
-    _static_1(Q, "vm_service_ScriptList_parse$closure", "ScriptList_parse", 117);
-    _static_1(Q, "vm_service_SourceLocation_parse$closure", "SourceLocation_parse", 118);
-    _static_1(Q, "vm_service_SourceReport_parse$closure", "SourceReport_parse", 119);
-    _static_1(Q, "vm_service_SourceReportCoverage_parse$closure", "SourceReportCoverage_parse", 120);
-    _static_1(Q, "vm_service_SourceReportRange_parse$closure", "SourceReportRange_parse", 121);
-    _static_1(Q, "vm_service_Stack_parse$closure", "Stack_parse", 122);
-    _static_1(Q, "vm_service_Success_parse$closure", "Success_parse", 123);
-    _static_1(Q, "vm_service_Timeline_parse$closure", "Timeline_parse", 124);
-    _static_1(Q, "vm_service_TimelineEvent_parse$closure", "TimelineEvent_parse", 125);
-    _static_1(Q, "vm_service_TimelineFlags_parse$closure", "TimelineFlags_parse", 126);
-    _static_1(Q, "vm_service_Timestamp_parse$closure", "Timestamp_parse", 127);
-    _static_1(Q, "vm_service_TypeArgumentsRef_parse$closure", "TypeArgumentsRef_parse", 128);
-    _static_1(Q, "vm_service_TypeArguments_parse$closure", "TypeArguments_parse", 129);
-    _static_1(Q, "vm_service_UnresolvedSourceLocation_parse$closure", "UnresolvedSourceLocation_parse", 130);
-    _static_1(Q, "vm_service_Version_parse$closure", "Version_parse", 131);
-    _static_1(Q, "vm_service_VMRef_parse$closure", "VMRef_parse", 132);
-    _static_1(Q, "vm_service_VM_parse$closure", "VM_parse", 88);
-    _instance_1_u(Q.VmService.prototype, "get$_processMessage", "_processMessage$1", 2);
+    _instance_1_u(_, "get$_onOutgoingMessage", "_onOutgoingMessage$1", 1);
+    _static_1(Q, "vm_service_ExtensionData_parse$closure", "ExtensionData_parse", 63);
+    _static_1(Q, "vm_service_AllocationProfile_parse$closure", "AllocationProfile_parse", 64);
+    _static_1(Q, "vm_service_BoundField_parse$closure", "BoundField_parse", 65);
+    _static_1(Q, "vm_service_BoundVariable_parse$closure", "BoundVariable_parse", 66);
+    _static_1(Q, "vm_service_Breakpoint_parse$closure", "Breakpoint_parse", 67);
+    _static_1(Q, "vm_service_ClassRef_parse$closure", "ClassRef_parse", 68);
+    _static_1(Q, "vm_service_Class_parse$closure", "Class_parse", 69);
+    _static_1(Q, "vm_service_ClassHeapStats_parse$closure", "ClassHeapStats_parse", 70);
+    _static_1(Q, "vm_service_ClassList_parse$closure", "ClassList_parse", 71);
+    _static_1(Q, "vm_service_ClientName_parse$closure", "ClientName_parse", 72);
+    _static_1(Q, "vm_service_CodeRef_parse$closure", "CodeRef_parse", 73);
+    _static_1(Q, "vm_service_Code_parse$closure", "Code_parse", 74);
+    _static_1(Q, "vm_service_ContextRef_parse$closure", "ContextRef_parse", 75);
+    _static_1(Q, "vm_service_Context_parse$closure", "Context_parse", 76);
+    _static_1(Q, "vm_service_ContextElement_parse$closure", "ContextElement_parse", 77);
+    _static_1(Q, "vm_service_CpuSamples_parse$closure", "CpuSamples_parse", 78);
+    _static_1(Q, "vm_service_CpuSample_parse$closure", "CpuSample_parse", 79);
+    _static_1(Q, "vm_service_ErrorRef_parse$closure", "ErrorRef_parse", 80);
+    _static_1(Q, "vm_service_Error_parse$closure", "Error_parse", 81);
+    _static_1(Q, "vm_service_Event_parse$closure", "Event_parse", 82);
+    _static_1(Q, "vm_service_FieldRef_parse$closure", "FieldRef_parse", 83);
+    _static_1(Q, "vm_service_Field_parse$closure", "Field_parse", 84);
+    _static_1(Q, "vm_service_Flag_parse$closure", "Flag_parse", 85);
+    _static_1(Q, "vm_service_FlagList_parse$closure", "FlagList_parse", 86);
+    _static_1(Q, "vm_service_Frame_parse$closure", "Frame_parse", 87);
+    _static_1(Q, "vm_service_FuncRef_parse$closure", "FuncRef_parse", 88);
+    _static_1(Q, "vm_service_Func_parse$closure", "Func_parse", 89);
+    _static_1(Q, "vm_service_InstanceRef_parse$closure", "InstanceRef_parse", 90);
+    _static_1(Q, "vm_service_Instance_parse$closure", "Instance_parse", 137);
+    _static_1(Q, "vm_service_IsolateRef_parse$closure", "IsolateRef_parse", 92);
+    _static_1(Q, "vm_service_Isolate_parse$closure", "Isolate_parse", 93);
+    _static_1(Q, "vm_service_IsolateGroupRef_parse$closure", "IsolateGroupRef_parse", 94);
+    _static_1(Q, "vm_service_IsolateGroup_parse$closure", "IsolateGroup_parse", 95);
+    _static_1(Q, "vm_service_InboundReferences_parse$closure", "InboundReferences_parse", 96);
+    _static_1(Q, "vm_service_InboundReference_parse$closure", "InboundReference_parse", 97);
+    _static_1(Q, "vm_service_InstanceSet_parse$closure", "InstanceSet_parse", 98);
+    _static_1(Q, "vm_service_LibraryRef_parse$closure", "LibraryRef_parse", 99);
+    _static_1(Q, "vm_service_Library_parse$closure", "Library_parse", 100);
+    _static_1(Q, "vm_service_LibraryDependency_parse$closure", "LibraryDependency_parse", 101);
+    _static_1(Q, "vm_service_LogRecord_parse$closure", "LogRecord_parse", 102);
+    _static_1(Q, "vm_service_MapAssociation_parse$closure", "MapAssociation_parse", 103);
+    _static_1(Q, "vm_service_MemoryUsage_parse$closure", "MemoryUsage_parse", 104);
+    _static_1(Q, "vm_service_Message_parse$closure", "Message_parse", 105);
+    _static_1(Q, "vm_service_NativeFunction_parse$closure", "NativeFunction_parse", 106);
+    _static_1(Q, "vm_service_NullValRef_parse$closure", "NullValRef_parse", 107);
+    _static_1(Q, "vm_service_NullVal_parse$closure", "NullVal_parse", 108);
+    _static_1(Q, "vm_service_ObjRef_parse$closure", "ObjRef_parse", 109);
+    _static_1(Q, "vm_service_Obj_parse$closure", "Obj_parse", 110);
+    _static_1(Q, "vm_service_ProfileFunction_parse$closure", "ProfileFunction_parse", 111);
+    _static_1(Q, "vm_service_ProtocolList_parse$closure", "ProtocolList_parse", 112);
+    _static_1(Q, "vm_service_Protocol_parse$closure", "Protocol_parse", 113);
+    _static_1(Q, "vm_service_ReloadReport_parse$closure", "ReloadReport_parse", 114);
+    _static_1(Q, "vm_service_RetainingObject_parse$closure", "RetainingObject_parse", 115);
+    _static_1(Q, "vm_service_RetainingPath_parse$closure", "RetainingPath_parse", 116);
+    _static_1(Q, "vm_service_Response_parse$closure", "Response_parse", 117);
+    _static_1(Q, "vm_service_Sentinel_parse$closure", "Sentinel_parse", 118);
+    _static_1(Q, "vm_service_ScriptRef_parse$closure", "ScriptRef_parse", 119);
+    _static_1(Q, "vm_service_Script_parse$closure", "Script_parse", 120);
+    _static_1(Q, "vm_service_ScriptList_parse$closure", "ScriptList_parse", 121);
+    _static_1(Q, "vm_service_SourceLocation_parse$closure", "SourceLocation_parse", 122);
+    _static_1(Q, "vm_service_SourceReport_parse$closure", "SourceReport_parse", 123);
+    _static_1(Q, "vm_service_SourceReportCoverage_parse$closure", "SourceReportCoverage_parse", 124);
+    _static_1(Q, "vm_service_SourceReportRange_parse$closure", "SourceReportRange_parse", 125);
+    _static_1(Q, "vm_service_Stack_parse$closure", "Stack_parse", 126);
+    _static_1(Q, "vm_service_Success_parse$closure", "Success_parse", 127);
+    _static_1(Q, "vm_service_Timeline_parse$closure", "Timeline_parse", 128);
+    _static_1(Q, "vm_service_TimelineEvent_parse$closure", "TimelineEvent_parse", 129);
+    _static_1(Q, "vm_service_TimelineFlags_parse$closure", "TimelineFlags_parse", 130);
+    _static_1(Q, "vm_service_Timestamp_parse$closure", "Timestamp_parse", 131);
+    _static_1(Q, "vm_service_TypeArgumentsRef_parse$closure", "TypeArgumentsRef_parse", 132);
+    _static_1(Q, "vm_service_TypeArguments_parse$closure", "TypeArguments_parse", 133);
+    _static_1(Q, "vm_service_UnresolvedSourceLocation_parse$closure", "UnresolvedSourceLocation_parse", 134);
+    _static_1(Q, "vm_service_Version_parse$closure", "Version_parse", 135);
+    _static_1(Q, "vm_service_VMRef_parse$closure", "VMRef_parse", 136);
+    _static_1(Q, "vm_service_VM_parse$closure", "VM_parse", 91);
+    _instance_1_u(Q.VmService.prototype, "get$_processMessage", "_processMessage$1", 1);
   })();
   (function inheritance() {
     var _mixin = hunkHelpers.mixin,
       _inherit = hunkHelpers.inherit,
       _inheritMany = hunkHelpers.inheritMany;
     _inherit(P.Object, null);
-    _inheritMany(P.Object, [H.JS_CONST, J.Interceptor, J.JSObject, J.ArrayIterator, P.Iterable, H.ListIterator, P.Iterator, H.FixedLengthListMixin, H.Symbol, P.MapView, H.ConstantMap, H.Closure, H.JSInvocationMirror, H.TypeErrorDecoder, P.Error0, H.NullThrownFromJavaScriptException, H.ExceptionAndStackTrace, H._StackTrace, H._Required, P.MapMixin, H.LinkedHashMapCell, H.LinkedHashMapKeyIterator, H.Rti, H._FunctionParameters, H._Type, P._TimerImpl, P._AsyncAwaitCompleter, P._BufferingStreamSubscription, P._BroadcastStreamController, P.Future, P.Completer, P._Completer, P._FutureListener, P._Future, P._AsyncCallbackEntry, P.Stream, P.StreamSubscription, P.StreamTransformerBase, P.StreamController, P._StreamController, P._AsyncStreamControllerDispatch, P._StreamSinkWrapper, P._DelayedEvent, P._DelayedDone, P._PendingEvents, P._DoneStreamSubscription, P._StreamIterator, P.AsyncError, P._Zone, P._SetBase, P._LinkedHashSetCell, P._LinkedHashSetIterator, P.ListMixin, P._UnmodifiableMapMixin, P._ListQueueIterator, P.Codec, P._JsonStringifier, P._Utf8Decoder, P.bool, P.DateTime, P.num, P.Duration, P.OutOfMemoryError, P.StackOverflowError, P._Exception, P.FormatException, P.Function, P.List, P.Map, P.MapEntry, P.Null, P.StackTrace, P._StringStackTrace, P.String, P.StringBuffer, P.Symbol0, W.EventStreamProvider, P._AcceptStructuredClone, P._JSRandom, P.ByteBuffer, P.ByteData, P.Int8List, P.Uint8List, P.Uint8ClampedList, P.Int16List, P.Uint16List, P.Int32List, P.Uint32List, P.Float32List, P.Float64List, V.ErrorResult, E.Result, F.ValueResult, G.StreamQueue, G._EventRequest, G._NextRequest, Q._QueueList_Object_ListMixin, Y.Level, L.LogRecord0, F.Logger, R.StreamChannelMixin, K.Uuid, Q.VmService, Q.RPCError, Q.SentinelException, Q.ExtensionData, Q._NullLog, Q.Response, Q.BoundField, Q.ContextElement, Q.CpuSample, Q.Flag, Q.InboundReference, Q.LibraryDependency, Q.MapAssociation, Q.NativeFunction, Q.ProfileFunction, Q.RetainingObject, Q.SourceReportCoverage, Q.SourceReportRange, Q.TimelineEvent]);
+    _inheritMany(P.Object, [H.JS_CONST, J.Interceptor, J.ArrayIterator, P.Error0, H.Closure, P.Iterable, H.ListIterator, P.Iterator, H.FixedLengthListMixin, H.Symbol, P.MapView, H.ConstantMap, H.JSInvocationMirror, H.TypeErrorDecoder, H.NullThrownFromJavaScriptException, H.ExceptionAndStackTrace, H._StackTrace, H._Required, P.MapMixin, H.LinkedHashMapCell, H.LinkedHashMapKeyIterator, H.Rti, H._FunctionParameters, H._Type, P._TimerImpl, P._AsyncAwaitCompleter, P._BufferingStreamSubscription, P._BroadcastStreamController, P._Completer, P._FutureListener, P._Future, P._AsyncCallbackEntry, P.Stream, P.StreamSubscription, P.StreamTransformerBase, P._StreamController, P._AsyncStreamControllerDispatch, P._StreamSinkWrapper, P._DelayedEvent, P._DelayedDone, P._PendingEvents, P._DoneStreamSubscription, P._StreamIterator, P.AsyncError, P._Zone, P.__SetBase_Object_SetMixin, P._LinkedHashSetCell, P._LinkedHashSetIterator, P.ListMixin, P._UnmodifiableMapMixin, P._ListQueueIterator, P.SetMixin, P.Codec, P._JsonStringifier, P._Utf8Decoder, P.DateTime, P.Duration, P.OutOfMemoryError, P.StackOverflowError, P._Exception, P.FormatException, P.Null, P._StringStackTrace, P.StringBuffer, W.EventStreamProvider, P._AcceptStructuredClone, P._JSRandom, V.ErrorResult, F.ValueResult, G.StreamQueue, G._NextRequest, Q._QueueList_Object_ListMixin, Y.Level, L.LogRecord0, F.Logger, R.StreamChannelMixin, K.Uuid, Q.VmService, Q.RPCError, Q.SentinelException, Q.ExtensionData, Q._NullLog, Q.Response, Q.BoundField, Q.ContextElement, Q.CpuSample, Q.Flag, Q.InboundReference, Q.LibraryDependency, Q.MapAssociation, Q.NativeFunction, Q.ProfileFunction, Q.Protocol, Q.RetainingObject, Q.SourceReportCoverage, Q.SourceReportRange, Q.TimelineEvent]);
     _inheritMany(J.Interceptor, [J.JSBool, J.JSNull, J.JavaScriptObject, J.JSArray, J.JSNumber, J.JSString, H.NativeByteBuffer, H.NativeTypedData, W.DomException, W.Event0, W.EventTarget]);
     _inheritMany(J.JavaScriptObject, [J.PlainJavaScriptObject, J.UnknownJavaScriptObject, J.JavaScriptFunction]);
     _inherit(J.JSUnmodifiableArray, J.JSArray);
     _inheritMany(J.JSNumber, [J.JSInt, J.JSDouble]);
+    _inheritMany(P.Error0, [H.LateError, H.ReachabilityError, H.NotNullableError, P.TypeError, H.JsNoSuchMethodError, H.UnknownJsTypeError, H.RuntimeError, P.AssertionError, H._Error, P.JsonUnsupportedObjectError, P.NullThrownError, P.ArgumentError, P.NoSuchMethodError, P.UnsupportedError, P.UnimplementedError, P.StateError, P.ConcurrentModificationError, P.CyclicInitializationError]);
+    _inheritMany(H.Closure, [H.nullFuture_closure, H.ConstantMap_map_closure, H.Primitives_functionNoSuchMethod_closure, H.TearOffClosure, H.JsLinkedHashMap_addAll_closure, H.initHooks_closure, H.initHooks_closure0, H.initHooks_closure1, P._AsyncRun__initializeScheduleImmediate_internalCallback, P._AsyncRun__initializeScheduleImmediate_closure, P._AsyncRun__scheduleImmediateJsOverride_internalCallback, P._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback, P._TimerImpl_internalCallback, P._awaitOnObject_closure, P._awaitOnObject_closure0, P._wrapJsFunctionForAsync_closure, P._SyncBroadcastStreamController__sendData_closure, P._Future__addListener_closure, P._Future__prependListeners_closure, P._Future__chainForeignFuture_closure, P._Future__chainForeignFuture_closure0, P._Future__chainForeignFuture_closure1, P._Future__asyncCompleteWithValue_closure, P._Future__chainFuture_closure, P._Future__asyncCompleteError_closure, P._Future__propagateToListeners_handleWhenCompleteCallback, P._Future__propagateToListeners_handleWhenCompleteCallback_closure, P._Future__propagateToListeners_handleValueCallback, P._Future__propagateToListeners_handleError, P.Stream_length_closure, P.Stream_length_closure0, P.Stream_first_closure, P.Stream_first_closure0, P._StreamController__subscribe_closure, P._StreamController__recordCancel_complete, P._BufferingStreamSubscription__sendError_sendError, P._BufferingStreamSubscription__sendDone_sendDone, P._PendingEvents_schedule_closure, P._cancelAndValue_closure, P._rootHandleUncaughtError_closure, P._RootZone_bindCallback_closure, P._RootZone_bindCallbackGuarded_closure, P._RootZone_bindUnaryCallbackGuarded_closure, P.MapBase_mapToString_closure, P.Utf8Decoder__decoder_closure, P.Utf8Decoder__decoderNonfatal_closure, P._JsonStringifier_writeMap_closure, P._symbolMapToStringMap_closure, P.NoSuchMethodError_toString_closure, P.Duration_toString_sixDigits, P.Duration_toString_twoDigits, W.HttpRequest_request_closure, W._EventStreamSubscription_closure, W._EventStreamSubscription_onData_closure, P._AcceptStructuredClone_walk_closure, P._convertDartToNative_Value_closure, P.convertDartToNative_Dictionary_closure, P.promiseToFuture_closure, P.promiseToFuture_closure0, G.StreamQueue__ensureListening_closure, G.StreamQueue__ensureListening_closure1, G.StreamQueue__ensureListening_closure0, F.Logger_Logger_closure, M.SseClient_closure, M.SseClient_closure0, M.SseClient__closure, Q.createServiceObject_closure, Q._createSpecificObject_closure, Q.VmService_closure, Q.AllocationProfile_toJson_closure, Q.Class_toJson_closure, Q.Class_toJson_closure0, Q.Class_toJson_closure1, Q.Class_toJson_closure2, Q.ClassList_toJson_closure, Q.Context_toJson_closure, Q.CpuSamples_toJson_closure, Q.CpuSamples_toJson_closure0, Q.CpuSample_toJson_closure, Q.Event_toJson_closure, Q.Event_toJson_closure0, Q.Event_toJson_closure1, Q.FlagList_toJson_closure, Q.Frame_toJson_closure, Q.Instance_toJson_closure, Q.Instance_toJson_closure0, Q.Instance_toJson_closure1, Q.Isolate_toJson_closure, Q.Isolate_toJson_closure0, Q.Isolate_toJson_closure1, Q.IsolateGroup_toJson_closure, Q.InboundReferences_toJson_closure, Q.InstanceSet_toJson_closure, Q.Library_toJson_closure, Q.Library_toJson_closure0, Q.Library_toJson_closure1, Q.Library_toJson_closure2, Q.Library_toJson_closure3, Q.ProtocolList_toJson_closure, Q.RetainingPath_toJson_closure, Q.Script$_fromJson_closure, Q.Script_toJson_closure, Q.ScriptList_toJson_closure, Q.SourceReport_toJson_closure, Q.SourceReport_toJson_closure0, Q.SourceReportCoverage_toJson_closure, Q.SourceReportCoverage_toJson_closure0, Q.SourceReportRange_toJson_closure, Q.Stack_toJson_closure, Q.Stack_toJson_closure0, Q.Stack_toJson_closure1, Q.Stack_toJson_closure2, Q.Timeline_toJson_closure, Q.TimelineFlags_toJson_closure, Q.TimelineFlags_toJson_closure0, Q.TypeArguments_toJson_closure, Q.VM_toJson_closure, Q.VM_toJson_closure0, E.main_closure]);
     _inheritMany(P.Iterable, [H.EfficientLengthIterable, H.MappedIterable, H._ConstantMapKeyIterable]);
     _inheritMany(H.EfficientLengthIterable, [H.ListIterable, H.LinkedHashMapKeyIterable]);
     _inherit(H.EfficientLengthMappedIterable, H.MappedIterable);
@@ -14070,9 +14164,8 @@
     _inherit(P._UnmodifiableMapView_MapView__UnmodifiableMapMixin, P.MapView);
     _inherit(P.UnmodifiableMapView, P._UnmodifiableMapView_MapView__UnmodifiableMapMixin);
     _inherit(H.ConstantMapView, P.UnmodifiableMapView);
-    _inheritMany(H.Closure, [H.ConstantMap_map_closure, H.Primitives_functionNoSuchMethod_closure, H.TearOffClosure, H.JsLinkedHashMap_addAll_closure, H.initHooks_closure, H.initHooks_closure0, H.initHooks_closure1, P._AsyncRun__initializeScheduleImmediate_internalCallback, P._AsyncRun__initializeScheduleImmediate_closure, P._AsyncRun__scheduleImmediateJsOverride_internalCallback, P._AsyncRun__scheduleImmediateWithSetImmediate_internalCallback, P._TimerImpl_internalCallback, P._awaitOnObject_closure, P._awaitOnObject_closure0, P._wrapJsFunctionForAsync_closure, P._SyncBroadcastStreamController__sendData_closure, P._Future__addListener_closure, P._Future__prependListeners_closure, P._Future__chainForeignFuture_closure, P._Future__chainForeignFuture_closure0, P._Future__chainForeignFuture_closure1, P._Future__asyncCompleteWithValue_closure, P._Future__chainFuture_closure, P._Future__asyncCompleteError_closure, P._Future__propagateToListeners_handleWhenCompleteCallback, P._Future__propagateToListeners_handleWhenCompleteCallback_closure, P._Future__propagateToListeners_handleValueCallback, P._Future__propagateToListeners_handleError, P.Stream_length_closure, P.Stream_length_closure0, P.Stream_first_closure, P.Stream_first_closure0, P._StreamController__subscribe_closure, P._StreamController__recordCancel_complete, P._BufferingStreamSubscription__sendError_sendError, P._BufferingStreamSubscription__sendDone_sendDone, P._PendingEvents_schedule_closure, P._cancelAndValue_closure, P._rootHandleUncaughtError_closure, P._RootZone_bindCallback_closure, P._RootZone_bindCallbackGuarded_closure, P._RootZone_bindUnaryCallbackGuarded_closure, P.MapBase_mapToString_closure, P.Utf8Decoder_closure, P.Utf8Decoder_closure0, P._JsonStringifier_writeMap_closure, P._symbolMapToStringMap_closure, P.NoSuchMethodError_toString_closure, P.Duration_toString_sixDigits, P.Duration_toString_twoDigits, W.HttpRequest_request_closure, W._EventStreamSubscription_closure, W._EventStreamSubscription_onData_closure, P._AcceptStructuredClone_walk_closure, P.convertDartToNative_Dictionary_closure, P.promiseToFuture_closure, P.promiseToFuture_closure0, G.StreamQueue__ensureListening_closure, G.StreamQueue__ensureListening_closure1, G.StreamQueue__ensureListening_closure0, F.Logger_Logger_closure, M.SseClient_closure, M.SseClient_closure0, M.SseClient__closure, Q.createServiceObject_closure, Q._createSpecificObject_closure, Q.VmService_closure, Q.AllocationProfile_toJson_closure, Q.Class_toJson_closure, Q.Class_toJson_closure0, Q.Class_toJson_closure1, Q.Class_toJson_closure2, Q.ClassList_toJson_closure, Q.Context_toJson_closure, Q.CpuSamples_toJson_closure, Q.CpuSamples_toJson_closure0, Q.CpuSample_toJson_closure, Q.Event_toJson_closure, Q.Event_toJson_closure0, Q.Event_toJson_closure1, Q.FlagList_toJson_closure, Q.Frame_toJson_closure, Q.Instance_toJson_closure, Q.Instance_toJson_closure0, Q.Instance_toJson_closure1, Q.Isolate_toJson_closure, Q.Isolate_toJson_closure0, Q.Isolate_toJson_closure1, Q.IsolateGroup_toJson_closure, Q.InboundReferences_toJson_closure, Q.InstanceSet_toJson_closure, Q.Library_toJson_closure, Q.Library_toJson_closure0, Q.Library_toJson_closure1, Q.Library_toJson_closure2, Q.Library_toJson_closure3, Q.RetainingPath_toJson_closure, Q.Script$_fromJson_closure, Q.Script_toJson_closure, Q.ScriptList_toJson_closure, Q.SourceReport_toJson_closure, Q.SourceReport_toJson_closure0, Q.SourceReportCoverage_toJson_closure, Q.SourceReportCoverage_toJson_closure0, Q.SourceReportRange_toJson_closure, Q.Stack_toJson_closure, Q.Stack_toJson_closure0, Q.Stack_toJson_closure1, Q.Stack_toJson_closure2, Q.Timeline_toJson_closure, Q.TimelineFlags_toJson_closure, Q.TimelineFlags_toJson_closure0, Q.TypeArguments_toJson_closure, Q.VM_toJson_closure, Q.VM_toJson_closure0, E.main_closure]);
     _inherit(H.ConstantStringMap, H.ConstantMap);
-    _inheritMany(P.Error0, [H.NullError, H.JsNoSuchMethodError, H.UnknownJsTypeError, H.RuntimeError, P.AssertionError, H._Error, P.JsonUnsupportedObjectError, P.NullThrownError, P.ArgumentError, P.NoSuchMethodError, P.UnsupportedError, P.UnimplementedError, P.StateError, P.ConcurrentModificationError, P.CyclicInitializationError]);
+    _inherit(H.NullError, P.TypeError);
     _inheritMany(H.TearOffClosure, [H.StaticClosure, H.BoundClosure]);
     _inherit(H._AssertionError, P.AssertionError);
     _inherit(P.MapBase, P.MapMixin);
@@ -14097,13 +14190,13 @@
     _inherit(P._StreamImplEvents, P._PendingEvents);
     _inherit(P._MapStream, P._ForwardingStream);
     _inherit(P._RootZone, P._Zone);
+    _inherit(P._SetBase, P.__SetBase_Object_SetMixin);
     _inherit(P._LinkedHashSet, P._SetBase);
     _inherit(P.Converter, P.StreamTransformerBase);
     _inherit(P.JsonCyclicError, P.JsonUnsupportedObjectError);
     _inheritMany(P.Codec, [P.JsonCodec, N.HexCodec]);
     _inheritMany(P.Converter, [P.JsonEncoder, P.JsonDecoder, P.Utf8Decoder, R.HexEncoder]);
     _inherit(P._JsonStringStringifier, P._JsonStringifier);
-    _inheritMany(P.num, [P.double, P.int]);
     _inheritMany(P.ArgumentError, [P.RangeError, P.IndexError]);
     _inheritMany(W.EventTarget, [W.EventSource, W.HttpRequestEventTarget]);
     _inherit(W.HttpRequest, W.HttpRequestEventTarget);
@@ -14112,7 +14205,7 @@
     _inherit(P._AcceptStructuredCloneDart2Js, P._AcceptStructuredClone);
     _inherit(Q.QueueList, Q._QueueList_Object_ListMixin);
     _inherit(M.SseClient, R.StreamChannelMixin);
-    _inheritMany(Q.Response, [Q.AllocationProfile, Q.BoundVariable, Q.Obj, Q.ObjRef, Q.ClassHeapStats, Q.ClassList, Q.ClientName, Q.CpuSamples, Q.Event, Q.FlagList, Q.Frame, Q.IsolateRef, Q.Isolate, Q.IsolateGroupRef, Q.IsolateGroup, Q.InboundReferences, Q.InstanceSet, Q.LogRecord, Q.MemoryUsage, Q.Message, Q.ReloadReport, Q.RetainingPath, Q.Sentinel, Q.ScriptList, Q.SourceLocation, Q.SourceReport, Q.Stack, Q.Success, Q.Timeline, Q.TimelineFlags, Q.Timestamp, Q.UnresolvedSourceLocation, Q.Version, Q.VMRef, Q.VM]);
+    _inheritMany(Q.Response, [Q.AllocationProfile, Q.BoundVariable, Q.Obj, Q.ObjRef, Q.ClassHeapStats, Q.ClassList, Q.ClientName, Q.CpuSamples, Q.Event, Q.FlagList, Q.Frame, Q.IsolateRef, Q.Isolate, Q.IsolateGroupRef, Q.IsolateGroup, Q.InboundReferences, Q.InstanceSet, Q.LogRecord, Q.MemoryUsage, Q.Message, Q.ProtocolList, Q.ReloadReport, Q.RetainingPath, Q.Sentinel, Q.ScriptList, Q.SourceLocation, Q.SourceReport, Q.Stack, Q.Success, Q.Timeline, Q.TimelineFlags, Q.Timestamp, Q.UnresolvedSourceLocation, Q.Version, Q.VMRef, Q.VM]);
     _inheritMany(Q.Obj, [Q.Breakpoint, Q.Class, Q.Context, Q.Error, Q.Field, Q.Func, Q.Instance, Q.Library, Q.Script, Q.TypeArguments]);
     _inheritMany(Q.ObjRef, [Q.ClassRef, Q.CodeRef, Q.Code, Q.ContextRef, Q.ErrorRef, Q.FieldRef, Q.FuncRef, Q.InstanceRef, Q.LibraryRef, Q.ScriptRef, Q.TypeArgumentsRef]);
     _inherit(Q.NullValRef, Q.InstanceRef);
@@ -14123,6 +14216,7 @@
     _mixin(H._NativeTypedArrayOfInt_NativeTypedArray_ListMixin_FixedLengthListMixin, H.FixedLengthListMixin);
     _mixin(P._AsyncStreamController, P._AsyncStreamControllerDispatch);
     _mixin(P._UnmodifiableMapView_MapView__UnmodifiableMapMixin, P._UnmodifiableMapMixin);
+    _mixin(P.__SetBase_Object_SetMixin, P.SetMixin);
     _mixin(Q._QueueList_Object_ListMixin, P.ListMixin);
   })();
   var init = {
@@ -14131,13 +14225,16 @@
     mangledNames: {},
     getTypeFromName: getGlobalFromName,
     metadata: [],
-    types: ["~()", "Null()", "~(@)", "@(@)", "int*(int*)", "String*(String*)", "~(~())", "~(Object,StackTrace)", "Map<String*,@>*(ClassRef*)", "Map<String*,@>*(ScriptRef*)", "Map<String*,@>*(Frame*)", "Null(@)", "~(Object?)", "Null(Object?,Object?)", "@()", "Null(Symbol0,@)", "String(int)", "@(Event0)", "~(Event0*)", "Null(Event0*)", "Map<String*,@>*(InstanceRef*)", "Map<String*,@>*(FieldRef*)", "Map<String*,@>*(FuncRef*)", "Map<String*,@>*(Breakpoint*)", "Map<String*,@>*(TimelineEvent*)", "Map<String*,@>*(IsolateRef*)", "Map<String*,@>*(BoundField*)", "Null(Object,StackTrace)", "_Future<@>(@)", "Object*(@)", "Map<String*,@>*(ClassHeapStats*)", "@(@,String)", "~(@,StackTrace)", "Null(~())", "Null(@,StackTrace)", "Map<String*,@>*(ContextElement*)", "Map<String*,@>*(ProfileFunction*)", "Map<String*,@>*(CpuSample*)", "Null(int,@)", "~(Object[StackTrace?])", "Null(ProgressEvent)", "@(String)", "Map<String*,@>*(Flag*)", "Map<String*,@>*(BoundVariable*)", "Null(String,@)", "Map<String*,@>*(MapAssociation*)", "Map<String*,@>*(LibraryRef*)", "@(@,@)", "Map<String*,@>*(InboundReference*)", "Map<String*,@>*(ObjRef*)", "Map<String*,@>*(LibraryDependency*)", "Null(@,@)", "Map<String*,@>*(RetainingObject*)", "List<int*>*(@)", "List<int*>*(List<int*>*)", "Map<String*,@>*(SourceReportRange*)", "Null(@,StackTrace*)", "Map<String*,@>*(Message*)", "Map<String*,@>*(IsolateGroupRef*)", "~(String*)", "Logger*()", "ExtensionData*(Map<@,@>*)", "AllocationProfile*(Map<String*,@>*)", "BoundField*(Map<String*,@>*)", "BoundVariable*(Map<String*,@>*)", "Breakpoint*(Map<String*,@>*)", "ClassRef*(Map<String*,@>*)", "Class*(Map<String*,@>*)", "ClassHeapStats*(Map<String*,@>*)", "ClassList*(Map<String*,@>*)", "ClientName*(Map<String*,@>*)", "CodeRef*(Map<String*,@>*)", "Code*(Map<String*,@>*)", "ContextRef*(Map<String*,@>*)", "Context*(Map<String*,@>*)", "ContextElement*(Map<String*,@>*)", "CpuSamples*(Map<String*,@>*)", "CpuSample*(Map<String*,@>*)", "ErrorRef*(Map<String*,@>*)", "Error*(Map<String*,@>*)", "Event*(Map<String*,@>*)", "FieldRef*(Map<String*,@>*)", "Field*(Map<String*,@>*)", "Flag*(Map<String*,@>*)", "FlagList*(Map<String*,@>*)", "Frame*(Map<String*,@>*)", "FuncRef*(Map<String*,@>*)", "Func*(Map<String*,@>*)", "VM*(Map<String*,@>*)", "Instance*(Map<String*,@>*)", "IsolateRef*(Map<String*,@>*)", "Isolate*(Map<String*,@>*)", "IsolateGroupRef*(Map<String*,@>*)", "IsolateGroup*(Map<String*,@>*)", "InboundReferences*(Map<String*,@>*)", "InboundReference*(Map<String*,@>*)", "InstanceSet*(Map<String*,@>*)", "LibraryRef*(Map<String*,@>*)", "Library*(Map<String*,@>*)", "LibraryDependency*(Map<String*,@>*)", "LogRecord*(Map<String*,@>*)", "MapAssociation*(Map<String*,@>*)", "MemoryUsage*(Map<String*,@>*)", "Message*(Map<String*,@>*)", "NativeFunction*(Map<String*,@>*)", "NullValRef*(Map<String*,@>*)", "NullVal*(Map<String*,@>*)", "ObjRef*(Map<String*,@>*)", "Obj*(Map<String*,@>*)", "ProfileFunction*(Map<String*,@>*)", "ReloadReport*(Map<String*,@>*)", "RetainingObject*(Map<String*,@>*)", "RetainingPath*(Map<String*,@>*)", "Response*(Map<String*,@>*)", "Sentinel*(Map<String*,@>*)", "ScriptRef*(Map<String*,@>*)", "Script*(Map<String*,@>*)", "ScriptList*(Map<String*,@>*)", "SourceLocation*(Map<String*,@>*)", "SourceReport*(Map<String*,@>*)", "SourceReportCoverage*(Map<String*,@>*)", "SourceReportRange*(Map<String*,@>*)", "Stack*(Map<String*,@>*)", "Success*(Map<String*,@>*)", "Timeline*(Map<String*,@>*)", "TimelineEvent*(Map<String*,@>*)", "TimelineFlags*(Map<String*,@>*)", "Timestamp*(Map<String*,@>*)", "TypeArgumentsRef*(Map<String*,@>*)", "TypeArguments*(Map<String*,@>*)", "UnresolvedSourceLocation*(Map<String*,@>*)", "Version*(Map<String*,@>*)", "VMRef*(Map<String*,@>*)", "InstanceRef*(Map<String*,@>*)"],
+    types: ["~()", "~(@)", "@(@)", "Null()", "int*(int*)", "String*(String*)", "~(~())", "~(Object,StackTrace)", "Map<String*,@>*(ClassRef*)", "Map<String*,@>*(ScriptRef*)", "Map<String*,@>*(Frame*)", "Null(@)", "~(Object?)", "~(Object?,Object?)", "@()", "~(Symbol0,@)", "String(int)", "~(Event0)", "~(Event0*)", "Null(Event0*)", "Map<String*,@>*(InstanceRef*)", "Map<String*,@>*(FieldRef*)", "Map<String*,@>*(FuncRef*)", "Map<String*,@>*(Breakpoint*)", "Map<String*,@>*(TimelineEvent*)", "Map<String*,@>*(IsolateRef*)", "Map<String*,@>*(BoundField*)", "Logger*()", "Null(~())", "Null(Object,StackTrace)", "Object*(@)", "Map<String*,@>*(ClassHeapStats*)", "_Future<@>(@)", "@(@,String)", "~(@,StackTrace)", "@(String)", "Map<String*,@>*(ContextElement*)", "Map<String*,@>*(ProfileFunction*)", "Map<String*,@>*(CpuSample*)", "~(String,@)", "Null(@,StackTrace)", "~(int,@)", "~(ProgressEvent)", "Map<String*,@>*(Flag*)", "Map<String*,@>*(BoundVariable*)", "Future<Null>()", "Map<String*,@>*(MapAssociation*)", "Map<String*,@>*(LibraryRef*)", "~(Object[StackTrace?])", "Map<String*,@>*(InboundReference*)", "Map<String*,@>*(ObjRef*)", "Map<String*,@>*(LibraryDependency*)", "@(@,@)", "Map<String*,@>*(Protocol*)", "Map<String*,@>*(RetainingObject*)", "List<int*>*(@)", "List<int*>*(List<int*>*)", "Map<String*,@>*(SourceReportRange*)", "~(@,@)", "Map<String*,@>*(Message*)", "Map<String*,@>*(IsolateGroupRef*)", "~(String*)", "Null(@,StackTrace*)", "ExtensionData*(Map<@,@>*)", "AllocationProfile*(Map<String*,@>*)", "BoundField*(Map<String*,@>*)", "BoundVariable*(Map<String*,@>*)", "Breakpoint*(Map<String*,@>*)", "ClassRef*(Map<String*,@>*)", "Class*(Map<String*,@>*)", "ClassHeapStats*(Map<String*,@>*)", "ClassList*(Map<String*,@>*)", "ClientName*(Map<String*,@>*)", "CodeRef*(Map<String*,@>*)", "Code*(Map<String*,@>*)", "ContextRef*(Map<String*,@>*)", "Context*(Map<String*,@>*)", "ContextElement*(Map<String*,@>*)", "CpuSamples*(Map<String*,@>*)", "CpuSample*(Map<String*,@>*)", "ErrorRef*(Map<String*,@>*)", "Error*(Map<String*,@>*)", "Event*(Map<String*,@>*)", "FieldRef*(Map<String*,@>*)", "Field*(Map<String*,@>*)", "Flag*(Map<String*,@>*)", "FlagList*(Map<String*,@>*)", "Frame*(Map<String*,@>*)", "FuncRef*(Map<String*,@>*)", "Func*(Map<String*,@>*)", "InstanceRef*(Map<String*,@>*)", "VM*(Map<String*,@>*)", "IsolateRef*(Map<String*,@>*)", "Isolate*(Map<String*,@>*)", "IsolateGroupRef*(Map<String*,@>*)", "IsolateGroup*(Map<String*,@>*)", "InboundReferences*(Map<String*,@>*)", "InboundReference*(Map<String*,@>*)", "InstanceSet*(Map<String*,@>*)", "LibraryRef*(Map<String*,@>*)", "Library*(Map<String*,@>*)", "LibraryDependency*(Map<String*,@>*)", "LogRecord*(Map<String*,@>*)", "MapAssociation*(Map<String*,@>*)", "MemoryUsage*(Map<String*,@>*)", "Message*(Map<String*,@>*)", "NativeFunction*(Map<String*,@>*)", "NullValRef*(Map<String*,@>*)", "NullVal*(Map<String*,@>*)", "ObjRef*(Map<String*,@>*)", "Obj*(Map<String*,@>*)", "ProfileFunction*(Map<String*,@>*)", "ProtocolList*(Map<String*,@>*)", "Protocol*(Map<String*,@>*)", "ReloadReport*(Map<String*,@>*)", "RetainingObject*(Map<String*,@>*)", "RetainingPath*(Map<String*,@>*)", "Response*(Map<String*,@>*)", "Sentinel*(Map<String*,@>*)", "ScriptRef*(Map<String*,@>*)", "Script*(Map<String*,@>*)", "ScriptList*(Map<String*,@>*)", "SourceLocation*(Map<String*,@>*)", "SourceReport*(Map<String*,@>*)", "SourceReportCoverage*(Map<String*,@>*)", "SourceReportRange*(Map<String*,@>*)", "Stack*(Map<String*,@>*)", "Success*(Map<String*,@>*)", "Timeline*(Map<String*,@>*)", "TimelineEvent*(Map<String*,@>*)", "TimelineFlags*(Map<String*,@>*)", "Timestamp*(Map<String*,@>*)", "TypeArgumentsRef*(Map<String*,@>*)", "TypeArguments*(Map<String*,@>*)", "UnresolvedSourceLocation*(Map<String*,@>*)", "Version*(Map<String*,@>*)", "VMRef*(Map<String*,@>*)", "Instance*(Map<String*,@>*)"],
     interceptorsByTag: null,
     leafTags: null,
     arrayRti: typeof Symbol == "function" && typeof Symbol() == "symbol" ? Symbol("$ti") : "$ti"
   };
-  H._Universe_addRules(init.typeUniverse, JSON.parse('{"JavaScriptFunction":"JavaScriptObject","PlainJavaScriptObject":"JavaScriptObject","UnknownJavaScriptObject":"JavaScriptObject","AbortPaymentEvent":"Event0","ExtendableEvent":"Event0","_ResourceProgressEvent":"ProgressEvent","MessagePort":"EventTarget","JSBool":{"bool":[]},"JSNull":{"Null":[]},"JavaScriptObject":{"Function":[]},"JSArray":{"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"JSIndexable":["1"]},"JSUnmodifiableArray":{"JSArray":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"JSIndexable":["1"]},"ArrayIterator":{"Iterator":["1"]},"JSNumber":{"double":[],"num":[]},"JSInt":{"double":[],"int":[],"num":[]},"JSDouble":{"double":[],"num":[]},"JSString":{"String":[],"Pattern":[],"JSIndexable":["@"]},"EfficientLengthIterable":{"Iterable":["1"]},"ListIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"ListIterator":{"Iterator":["1"]},"MappedIterable":{"Iterable":["2"],"Iterable.E":"2"},"EfficientLengthMappedIterable":{"MappedIterable":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"MappedIterator":{"Iterator":["2"]},"MappedListIterable":{"ListIterable":["2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListIterable.E":"2","Iterable.E":"2"},"Symbol":{"Symbol0":[]},"ConstantMapView":{"UnmodifiableMapView":["1","2"],"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ConstantMap":{"Map":["1","2"]},"ConstantStringMap":{"ConstantMap":["1","2"],"Map":["1","2"]},"_ConstantMapKeyIterable":{"Iterable":["1"],"Iterable.E":"1"},"JSInvocationMirror":{"Invocation":[]},"NullError":{"Error0":[]},"JsNoSuchMethodError":{"Error0":[]},"UnknownJsTypeError":{"Error0":[]},"_StackTrace":{"StackTrace":[]},"Closure":{"Function":[]},"TearOffClosure":{"Function":[]},"StaticClosure":{"Function":[]},"BoundClosure":{"Function":[]},"RuntimeError":{"Error0":[]},"_AssertionError":{"Error0":[]},"JsLinkedHashMap":{"MapMixin":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapMixin.K":"1","MapMixin.V":"2"},"LinkedHashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapKeyIterator":{"Iterator":["1"]},"NativeByteData":{"ByteData":[]},"NativeTypedArray":{"JavaScriptIndexingBehavior":["1"],"JSIndexable":["1"]},"NativeTypedArrayOfDouble":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["double"],"List":["double"],"EfficientLengthIterable":["double"],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"]},"NativeTypedArrayOfInt":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"]},"NativeFloat32List":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["double"],"List":["double"],"EfficientLengthIterable":["double"],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"ListMixin.E":"double"},"NativeFloat64List":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["double"],"List":["double"],"EfficientLengthIterable":["double"],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"ListMixin.E":"double"},"NativeInt16List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeInt32List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeInt8List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint16List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint32List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint8ClampedList":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint8List":{"ListMixin":["int"],"Uint8List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"_Error":{"Error0":[]},"_TypeError":{"Error0":[]},"_TimerImpl":{"Timer":[]},"_AsyncAwaitCompleter":{"Completer":["1"]},"_BroadcastSubscription":{"_ControllerSubscription":["1"],"_BufferingStreamSubscription":["1"],"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_BroadcastStreamController":{"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_SyncBroadcastStreamController":{"_BroadcastStreamController":["1"],"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_AsyncBroadcastStreamController":{"_BroadcastStreamController":["1"],"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_Completer":{"Completer":["1"]},"_AsyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_Future":{"Future":["1"]},"_StreamController":{"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_AsyncStreamController":{"_AsyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_ControllerStream":{"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_ControllerSubscription":{"_BufferingStreamSubscription":["1"],"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_BufferingStreamSubscription":{"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamImpl":{"Stream":["1"]},"_DelayedData":{"_DelayedEvent":["1"]},"_DelayedError":{"_DelayedEvent":["@"]},"_DelayedDone":{"_DelayedEvent":["@"]},"_StreamImplEvents":{"_PendingEvents":["1"]},"_DoneStreamSubscription":{"StreamSubscription":["1"]},"_ForwardingStream":{"Stream":["2"]},"_ForwardingStreamSubscription":{"_BufferingStreamSubscription":["2"],"StreamSubscription":["2"],"_EventSink":["2"],"_EventDispatch":["2"],"_BufferingStreamSubscription.T":"2"},"_MapStream":{"_ForwardingStream":["1","2"],"Stream":["2"],"Stream.T":"2"},"AsyncError":{"Error0":[]},"_Zone":{"Zone":[]},"_RootZone":{"_Zone":[],"Zone":[]},"_LinkedHashSet":{"_SetBase":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_LinkedHashSetIterator":{"Iterator":["1"]},"MapBase":{"MapMixin":["1","2"],"Map":["1","2"]},"MapMixin":{"Map":["1","2"]},"MapView":{"Map":["1","2"]},"UnmodifiableMapView":{"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ListQueue":{"ListIterable":["1"],"Queue":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"_ListQueueIterator":{"Iterator":["1"]},"_SetBase":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"_JsonMap":{"MapMixin":["String","@"],"Map":["String","@"],"MapMixin.K":"String","MapMixin.V":"@"},"_JsonMapKeyIterable":{"ListIterable":["String"],"EfficientLengthIterable":["String"],"Iterable":["String"],"ListIterable.E":"String","Iterable.E":"String"},"JsonUnsupportedObjectError":{"Error0":[]},"JsonCyclicError":{"Error0":[]},"JsonCodec":{"Codec":["Object?","String"],"Codec.S":"Object?"},"JsonEncoder":{"Converter":["Object?","String"]},"JsonDecoder":{"Converter":["String","Object?"]},"Utf8Decoder":{"Converter":["List<int>","String"]},"double":{"num":[]},"AssertionError":{"Error0":[]},"NullThrownError":{"Error0":[]},"ArgumentError":{"Error0":[]},"RangeError":{"Error0":[]},"IndexError":{"Error0":[]},"NoSuchMethodError":{"Error0":[]},"UnsupportedError":{"Error0":[]},"UnimplementedError":{"Error0":[]},"StateError":{"Error0":[]},"ConcurrentModificationError":{"Error0":[]},"OutOfMemoryError":{"Error0":[]},"StackOverflowError":{"Error0":[]},"CyclicInitializationError":{"Error0":[]},"int":{"num":[]},"List":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"_StringStackTrace":{"StackTrace":[]},"String":{"Pattern":[]},"StringBuffer":{"StringSink":[]},"EventSource":{"EventTarget":[]},"HttpRequest":{"EventTarget":[]},"HttpRequestEventTarget":{"EventTarget":[]},"MessageEvent":{"Event0":[]},"ProgressEvent":{"Event0":[]},"_EventStream":{"Stream":["1"],"Stream.T":"1"},"_EventStreamSubscription":{"StreamSubscription":["1"]},"Int8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8ClampedList":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Float32List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]},"Float64List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]},"ErrorResult":{"Result":["Null"]},"ValueResult":{"Result":["1*"]},"_NextRequest":{"_EventRequest":["1*"]},"QueueList":{"ListMixin":["1*"],"List":["1*"],"Queue":["1*"],"EfficientLengthIterable":["1*"],"Iterable":["1*"],"ListMixin.E":"1*"},"HexCodec":{"Codec":["List<int*>*","String*"],"Codec.S":"List<int*>*"},"HexEncoder":{"Converter":["List<int*>*","String*"]},"_NullLog":{"Log":[]},"Breakpoint":{"ObjRef":[]},"ClassRef":{"ObjRef":[]},"Class":{"ClassRef":[],"ObjRef":[]},"CodeRef":{"ObjRef":[]},"Code":{"CodeRef":[],"ObjRef":[]},"ContextRef":{"ObjRef":[]},"Context":{"ContextRef":[],"ObjRef":[]},"ErrorRef":{"ObjRef":[]},"Error":{"ErrorRef":[],"ObjRef":[]},"FieldRef":{"ObjRef":[]},"Field":{"FieldRef":[],"ObjRef":[]},"FuncRef":{"ObjRef":[]},"Func":{"FuncRef":[],"ObjRef":[]},"InstanceRef":{"ObjRef":[]},"Instance":{"InstanceRef":[],"ObjRef":[]},"Isolate":{"IsolateRef":[]},"IsolateGroup":{"IsolateGroupRef":[]},"LibraryRef":{"ObjRef":[]},"Library":{"LibraryRef":[],"ObjRef":[]},"NullValRef":{"InstanceRef":[],"ObjRef":[]},"NullVal":{"NullValRef":[],"InstanceRef":[],"ObjRef":[]},"Obj":{"ObjRef":[]},"ScriptRef":{"ObjRef":[]},"Script":{"ScriptRef":[],"ObjRef":[]},"TypeArgumentsRef":{"ObjRef":[]},"TypeArguments":{"TypeArgumentsRef":[],"ObjRef":[]},"VM":{"VMRef":[]}}'));
-  H._Universe_addErasedTypes(init.typeUniverse, JSON.parse('{"EfficientLengthIterable":1,"NativeTypedArray":1,"StreamTransformerBase":2,"MapBase":2,"MapEntry":2,"_QueueList_Object_ListMixin":1,"StreamChannelMixin":1}'));
+  H._Universe_addRules(init.typeUniverse, JSON.parse('{"JavaScriptFunction":"JavaScriptObject","PlainJavaScriptObject":"JavaScriptObject","UnknownJavaScriptObject":"JavaScriptObject","AbortPaymentEvent":"Event0","ExtendableEvent":"Event0","_ResourceProgressEvent":"ProgressEvent","MessagePort":"EventTarget","JSBool":{"bool":[]},"JSNull":{"Null":[]},"JavaScriptObject":{"Function":[]},"JSArray":{"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"JSIndexable":["1"]},"JSUnmodifiableArray":{"JSArray":["1"],"List":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"JSIndexable":["1"]},"ArrayIterator":{"Iterator":["1"]},"JSNumber":{"double":[],"num":[]},"JSInt":{"double":[],"int":[],"num":[]},"JSDouble":{"double":[],"num":[]},"JSString":{"String":[],"Pattern":[],"JSIndexable":["@"]},"LateError":{"Error0":[]},"ReachabilityError":{"Error0":[]},"NotNullableError":{"Error0":[]},"EfficientLengthIterable":{"Iterable":["1"]},"ListIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"ListIterator":{"Iterator":["1"]},"MappedIterable":{"Iterable":["2"],"Iterable.E":"2"},"EfficientLengthMappedIterable":{"MappedIterable":["1","2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"Iterable.E":"2"},"MappedIterator":{"Iterator":["2"]},"MappedListIterable":{"ListIterable":["2"],"EfficientLengthIterable":["2"],"Iterable":["2"],"ListIterable.E":"2","Iterable.E":"2"},"Symbol":{"Symbol0":[]},"ConstantMapView":{"UnmodifiableMapView":["1","2"],"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ConstantMap":{"Map":["1","2"]},"ConstantStringMap":{"ConstantMap":["1","2"],"Map":["1","2"]},"_ConstantMapKeyIterable":{"Iterable":["1"],"Iterable.E":"1"},"JSInvocationMirror":{"Invocation":[]},"NullError":{"Error0":[]},"JsNoSuchMethodError":{"Error0":[]},"UnknownJsTypeError":{"Error0":[]},"_StackTrace":{"StackTrace":[]},"Closure":{"Function":[]},"TearOffClosure":{"Function":[]},"StaticClosure":{"Function":[]},"BoundClosure":{"Function":[]},"RuntimeError":{"Error0":[]},"_AssertionError":{"Error0":[]},"JsLinkedHashMap":{"MapMixin":["1","2"],"LinkedHashMap":["1","2"],"Map":["1","2"],"MapMixin.K":"1","MapMixin.V":"2"},"LinkedHashMapKeyIterable":{"EfficientLengthIterable":["1"],"Iterable":["1"],"Iterable.E":"1"},"LinkedHashMapKeyIterator":{"Iterator":["1"]},"NativeByteData":{"ByteData":[]},"NativeTypedArray":{"JavaScriptIndexingBehavior":["1"],"JSIndexable":["1"]},"NativeTypedArrayOfDouble":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["double"],"List":["double"],"EfficientLengthIterable":["double"],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"]},"NativeTypedArrayOfInt":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"]},"NativeFloat32List":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["double"],"List":["double"],"EfficientLengthIterable":["double"],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"ListMixin.E":"double"},"NativeFloat64List":{"ListMixin":["double"],"JavaScriptIndexingBehavior":["double"],"List":["double"],"EfficientLengthIterable":["double"],"JSIndexable":["double"],"Iterable":["double"],"FixedLengthListMixin":["double"],"ListMixin.E":"double"},"NativeInt16List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeInt32List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeInt8List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint16List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint32List":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint8ClampedList":{"ListMixin":["int"],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"NativeUint8List":{"ListMixin":["int"],"Uint8List":[],"JavaScriptIndexingBehavior":["int"],"List":["int"],"EfficientLengthIterable":["int"],"JSIndexable":["int"],"Iterable":["int"],"FixedLengthListMixin":["int"],"ListMixin.E":"int"},"_Error":{"Error0":[]},"_TypeError":{"Error0":[]},"_TimerImpl":{"Timer":[]},"_AsyncAwaitCompleter":{"Completer":["1"]},"_BroadcastSubscription":{"_ControllerSubscription":["1"],"_BufferingStreamSubscription":["1"],"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_BroadcastStreamController":{"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_SyncBroadcastStreamController":{"_BroadcastStreamController":["1"],"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_AsyncBroadcastStreamController":{"_BroadcastStreamController":["1"],"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_Completer":{"Completer":["1"]},"_AsyncCompleter":{"_Completer":["1"],"Completer":["1"]},"_Future":{"Future":["1"]},"_StreamController":{"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_AsyncStreamController":{"_AsyncStreamControllerDispatch":["1"],"_StreamController":["1"],"StreamController":["1"],"_StreamControllerLifecycle":["1"],"_EventSink":["1"],"_EventDispatch":["1"]},"_ControllerStream":{"_StreamImpl":["1"],"Stream":["1"],"Stream.T":"1"},"_ControllerSubscription":{"_BufferingStreamSubscription":["1"],"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_BufferingStreamSubscription":{"StreamSubscription":["1"],"_EventSink":["1"],"_EventDispatch":["1"],"_BufferingStreamSubscription.T":"1"},"_StreamImpl":{"Stream":["1"]},"_DelayedData":{"_DelayedEvent":["1"]},"_DelayedError":{"_DelayedEvent":["@"]},"_DelayedDone":{"_DelayedEvent":["@"]},"_StreamImplEvents":{"_PendingEvents":["1"]},"_DoneStreamSubscription":{"StreamSubscription":["1"]},"_ForwardingStream":{"Stream":["2"]},"_ForwardingStreamSubscription":{"_BufferingStreamSubscription":["2"],"StreamSubscription":["2"],"_EventSink":["2"],"_EventDispatch":["2"],"_BufferingStreamSubscription.T":"2"},"_MapStream":{"_ForwardingStream":["1","2"],"Stream":["2"],"Stream.T":"2"},"AsyncError":{"Error0":[]},"_Zone":{"Zone":[]},"_RootZone":{"_Zone":[],"Zone":[]},"_LinkedHashSet":{"SetMixin":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_LinkedHashSetIterator":{"Iterator":["1"]},"MapBase":{"MapMixin":["1","2"],"Map":["1","2"]},"MapMixin":{"Map":["1","2"]},"MapView":{"Map":["1","2"]},"UnmodifiableMapView":{"_UnmodifiableMapView_MapView__UnmodifiableMapMixin":["1","2"],"MapView":["1","2"],"_UnmodifiableMapMixin":["1","2"],"Map":["1","2"]},"ListQueue":{"ListIterable":["1"],"Queue":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"],"ListIterable.E":"1","Iterable.E":"1"},"_ListQueueIterator":{"Iterator":["1"]},"_SetBase":{"SetMixin":["1"],"EfficientLengthIterable":["1"],"Iterable":["1"]},"_JsonMap":{"MapMixin":["String","@"],"Map":["String","@"],"MapMixin.K":"String","MapMixin.V":"@"},"_JsonMapKeyIterable":{"ListIterable":["String"],"EfficientLengthIterable":["String"],"Iterable":["String"],"ListIterable.E":"String","Iterable.E":"String"},"JsonUnsupportedObjectError":{"Error0":[]},"JsonCyclicError":{"Error0":[]},"JsonCodec":{"Codec":["Object?","String"],"Codec.S":"Object?"},"JsonEncoder":{"Converter":["Object?","String"]},"JsonDecoder":{"Converter":["String","Object?"]},"Utf8Decoder":{"Converter":["List<int>","String"]},"double":{"num":[]},"int":{"num":[]},"List":{"EfficientLengthIterable":["1"],"Iterable":["1"]},"String":{"Pattern":[]},"AssertionError":{"Error0":[]},"TypeError":{"Error0":[]},"NullThrownError":{"Error0":[]},"ArgumentError":{"Error0":[]},"RangeError":{"Error0":[]},"IndexError":{"Error0":[]},"NoSuchMethodError":{"Error0":[]},"UnsupportedError":{"Error0":[]},"UnimplementedError":{"Error0":[]},"StateError":{"Error0":[]},"ConcurrentModificationError":{"Error0":[]},"OutOfMemoryError":{"Error0":[]},"StackOverflowError":{"Error0":[]},"CyclicInitializationError":{"Error0":[]},"_StringStackTrace":{"StackTrace":[]},"StringBuffer":{"StringSink":[]},"EventSource":{"EventTarget":[]},"HttpRequest":{"EventTarget":[]},"HttpRequestEventTarget":{"EventTarget":[]},"MessageEvent":{"Event0":[]},"ProgressEvent":{"Event0":[]},"_EventStream":{"Stream":["1"],"Stream.T":"1"},"_EventStreamSubscription":{"StreamSubscription":["1"]},"_JSRandom":{"Random":[]},"ErrorResult":{"Result":["Null"]},"ValueResult":{"Result":["1*"]},"_NextRequest":{"_EventRequest":["1*"]},"QueueList":{"ListMixin":["1*"],"List":["1*"],"Queue":["1*"],"EfficientLengthIterable":["1*"],"Iterable":["1*"],"ListMixin.E":"1*"},"HexCodec":{"Codec":["List<int*>*","String*"],"Codec.S":"List<int*>*"},"HexEncoder":{"Converter":["List<int*>*","String*"]},"_NullLog":{"Log":[]},"Breakpoint":{"ObjRef":[]},"ClassRef":{"ObjRef":[]},"Class":{"ClassRef":[],"ObjRef":[]},"CodeRef":{"ObjRef":[]},"Code":{"CodeRef":[],"ObjRef":[]},"ContextRef":{"ObjRef":[]},"Context":{"ContextRef":[],"ObjRef":[]},"ErrorRef":{"ObjRef":[]},"Error":{"ErrorRef":[],"ObjRef":[]},"FieldRef":{"ObjRef":[]},"Field":{"FieldRef":[],"ObjRef":[]},"FuncRef":{"ObjRef":[]},"Func":{"FuncRef":[],"ObjRef":[]},"InstanceRef":{"ObjRef":[]},"Instance":{"InstanceRef":[],"ObjRef":[]},"Isolate":{"IsolateRef":[]},"IsolateGroup":{"IsolateGroupRef":[]},"LibraryRef":{"ObjRef":[]},"Library":{"LibraryRef":[],"ObjRef":[]},"NullValRef":{"InstanceRef":[],"ObjRef":[]},"NullVal":{"NullValRef":[],"InstanceRef":[],"ObjRef":[]},"Obj":{"ObjRef":[]},"ScriptRef":{"ObjRef":[]},"Script":{"ScriptRef":[],"ObjRef":[]},"TypeArgumentsRef":{"ObjRef":[]},"TypeArguments":{"TypeArgumentsRef":[],"ObjRef":[]},"VM":{"VMRef":[]},"Int8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint8ClampedList":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint16List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Int32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Uint32List":{"List":["int"],"EfficientLengthIterable":["int"],"Iterable":["int"]},"Float32List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]},"Float64List":{"List":["double"],"EfficientLengthIterable":["double"],"Iterable":["double"]}}'));
+  H._Universe_addErasedTypes(init.typeUniverse, JSON.parse('{"EfficientLengthIterable":1,"NativeTypedArray":1,"StreamTransformerBase":2,"MapBase":2,"_SetBase":1,"__SetBase_Object_SetMixin":1,"MapEntry":2,"_QueueList_Object_ListMixin":1,"StreamChannelMixin":1}'));
+  var string$ = {
+    Cannot: "Cannot fire new event. Controller is already firing an event"
+  };
   var type$ = (function rtii() {
     var findType = H.findType;
     return {
@@ -14156,7 +14253,6 @@
       Iterable_dynamic: findType("Iterable<@>"),
       JSArray_String: findType("JSArray<String>"),
       JSArray_dynamic: findType("JSArray<@>"),
-      JSArray_int: findType("JSArray<int>"),
       JSArray_legacy_Result_legacy_String: findType("JSArray<Result<String*>*>"),
       JSArray_legacy_String: findType("JSArray<String*>"),
       JSArray_legacy_int: findType("JSArray<int*>"),
@@ -14178,7 +14274,6 @@
       QueueList_legacy_Result_legacy_String: findType("QueueList<Result<String*>*>"),
       StackTrace: findType("StackTrace"),
       StreamQueue_legacy_String: findType("StreamQueue<String*>"),
-      Stream_dynamic: findType("Stream<@>"),
       String: findType("String"),
       Symbol: findType("Symbol0"),
       UnknownJavaScriptObject: findType("UnknownJavaScriptObject"),
@@ -14187,6 +14282,7 @@
       _AsyncCompleter_legacy_Version: findType("_AsyncCompleter<Version*>"),
       _EventStream_legacy_Event: findType("_EventStream<Event0*>"),
       _Future_HttpRequest: findType("_Future<HttpRequest>"),
+      _Future_Null: findType("_Future<Null>"),
       _Future_bool: findType("_Future<bool>"),
       _Future_dynamic: findType("_Future<@>"),
       _Future_int: findType("_Future<int>"),
@@ -14253,6 +14349,7 @@
       legacy_List_legacy_Message: findType("List<Message*>*"),
       legacy_List_legacy_ObjRef: findType("List<ObjRef*>*"),
       legacy_List_legacy_ProfileFunction: findType("List<ProfileFunction*>*"),
+      legacy_List_legacy_Protocol: findType("List<Protocol*>*"),
       legacy_List_legacy_RetainingObject: findType("List<RetainingObject*>*"),
       legacy_List_legacy_ScriptRef: findType("List<ScriptRef*>*"),
       legacy_List_legacy_SourceReportRange: findType("List<SourceReportRange*>*"),
@@ -14275,6 +14372,7 @@
       legacy_Object: findType("Object*"),
       legacy_ProfileFunction: findType("ProfileFunction*"),
       legacy_ProgressEvent: findType("ProgressEvent*"),
+      legacy_Protocol: findType("Protocol*"),
       legacy_RetainingObject: findType("RetainingObject*"),
       legacy_ScriptRef: findType("ScriptRef*"),
       legacy_SourceLocation: findType("SourceLocation*"),
@@ -14501,6 +14599,8 @@
     C.List_ObjRef = H.setRuntimeTypeInfo(makeConstList(["ObjRef"]), type$.JSArray_legacy_String);
     C.List_PAk = H.setRuntimeTypeInfo(makeConstList(["InstanceRef", "TypeArgumentsRef", "Sentinel"]), type$.JSArray_legacy_String);
     C.List_ProfileFunction = H.setRuntimeTypeInfo(makeConstList(["ProfileFunction"]), type$.JSArray_legacy_String);
+    C.List_Protocol = H.setRuntimeTypeInfo(makeConstList(["Protocol"]), type$.JSArray_legacy_String);
+    C.List_ProtocolList = H.setRuntimeTypeInfo(makeConstList(["ProtocolList"]), type$.JSArray_legacy_String);
     C.List_ReloadReport = H.setRuntimeTypeInfo(makeConstList(["ReloadReport"]), type$.JSArray_legacy_String);
     C.List_RetainingObject = H.setRuntimeTypeInfo(makeConstList(["RetainingObject"]), type$.JSArray_legacy_String);
     C.List_RetainingPath = H.setRuntimeTypeInfo(makeConstList(["RetainingPath"]), type$.JSArray_legacy_String);
@@ -14565,32 +14665,37 @@
     $._toStringVisiting = H.setRuntimeTypeInfo([], H.findType("JSArray<Object>"));
     $.LogRecord__nextNumber = 0;
     $.Logger__loggers = P.LinkedHashMap_LinkedHashMap$_empty(type$.legacy_String, type$.legacy_Logger);
-    $._typeFactories = P.LinkedHashMap_LinkedHashMap$_literal(["AllocationProfile", Q.vm_service_AllocationProfile_parse$closure(), "BoundField", Q.vm_service_BoundField_parse$closure(), "BoundVariable", Q.vm_service_BoundVariable_parse$closure(), "Breakpoint", Q.vm_service_Breakpoint_parse$closure(), "@Class", Q.vm_service_ClassRef_parse$closure(), "Class", Q.vm_service_Class_parse$closure(), "ClassHeapStats", Q.vm_service_ClassHeapStats_parse$closure(), "ClassList", Q.vm_service_ClassList_parse$closure(), "ClientName", Q.vm_service_ClientName_parse$closure(), "@Code", Q.vm_service_CodeRef_parse$closure(), "Code", Q.vm_service_Code_parse$closure(), "@Context", Q.vm_service_ContextRef_parse$closure(), "Context", Q.vm_service_Context_parse$closure(), "ContextElement", Q.vm_service_ContextElement_parse$closure(), "CpuSamples", Q.vm_service_CpuSamples_parse$closure(), "CpuSample", Q.vm_service_CpuSample_parse$closure(), "@Error", Q.vm_service_ErrorRef_parse$closure(), "Error", Q.vm_service_Error_parse$closure(), "Event", Q.vm_service_Event_parse$closure(), "ExtensionData", Q.vm_service_ExtensionData_parse$closure(), "@Field", Q.vm_service_FieldRef_parse$closure(), "Field", Q.vm_service_Field_parse$closure(), "Flag", Q.vm_service_Flag_parse$closure(), "FlagList", Q.vm_service_FlagList_parse$closure(), "Frame", Q.vm_service_Frame_parse$closure(), "@Function", Q.vm_service_FuncRef_parse$closure(), "Function", Q.vm_service_Func_parse$closure(), "@Instance", Q.vm_service_InstanceRef_parse$closure(), "Instance", Q.vm_service_Instance_parse$closure(), "@Isolate", Q.vm_service_IsolateRef_parse$closure(), "Isolate", Q.vm_service_Isolate_parse$closure(), "@IsolateGroup", Q.vm_service_IsolateGroupRef_parse$closure(), "IsolateGroup", Q.vm_service_IsolateGroup_parse$closure(), "InboundReferences", Q.vm_service_InboundReferences_parse$closure(), "InboundReference", Q.vm_service_InboundReference_parse$closure(), "InstanceSet", Q.vm_service_InstanceSet_parse$closure(), "@Library", Q.vm_service_LibraryRef_parse$closure(), "Library", Q.vm_service_Library_parse$closure(), "LibraryDependency", Q.vm_service_LibraryDependency_parse$closure(), "LogRecord", Q.vm_service_LogRecord_parse$closure(), "MapAssociation", Q.vm_service_MapAssociation_parse$closure(), "MemoryUsage", Q.vm_service_MemoryUsage_parse$closure(), "Message", Q.vm_service_Message_parse$closure(), "NativeFunction", Q.vm_service_NativeFunction_parse$closure(), "@Null", Q.vm_service_NullValRef_parse$closure(), "Null", Q.vm_service_NullVal_parse$closure(), "@Object", Q.vm_service_ObjRef_parse$closure(), "Object", Q.vm_service_Obj_parse$closure(), "ProfileFunction", Q.vm_service_ProfileFunction_parse$closure(), "ReloadReport", Q.vm_service_ReloadReport_parse$closure(), "RetainingObject", Q.vm_service_RetainingObject_parse$closure(), "RetainingPath", Q.vm_service_RetainingPath_parse$closure(), "Response", Q.vm_service_Response_parse$closure(), "Sentinel", Q.vm_service_Sentinel_parse$closure(), "@Script", Q.vm_service_ScriptRef_parse$closure(), "Script", Q.vm_service_Script_parse$closure(), "ScriptList", Q.vm_service_ScriptList_parse$closure(), "SourceLocation", Q.vm_service_SourceLocation_parse$closure(), "SourceReport", Q.vm_service_SourceReport_parse$closure(), "SourceReportCoverage", Q.vm_service_SourceReportCoverage_parse$closure(), "SourceReportRange", Q.vm_service_SourceReportRange_parse$closure(), "Stack", Q.vm_service_Stack_parse$closure(), "Success", Q.vm_service_Success_parse$closure(), "Timeline", Q.vm_service_Timeline_parse$closure(), "TimelineEvent", Q.vm_service_TimelineEvent_parse$closure(), "TimelineFlags", Q.vm_service_TimelineFlags_parse$closure(), "Timestamp", Q.vm_service_Timestamp_parse$closure(), "@TypeArguments", Q.vm_service_TypeArgumentsRef_parse$closure(), "TypeArguments", Q.vm_service_TypeArguments_parse$closure(), "UnresolvedSourceLocation", Q.vm_service_UnresolvedSourceLocation_parse$closure(), "Version", Q.vm_service_Version_parse$closure(), "@VM", Q.vm_service_VMRef_parse$closure(), "VM", Q.vm_service_VM_parse$closure()], type$.legacy_String, H.findType("Function*"));
-    $._methodReturnTypes = P.LinkedHashMap_LinkedHashMap$_literal(["addBreakpoint", C.List_Breakpoint, "addBreakpointWithScriptUri", C.List_Breakpoint, "addBreakpointAtEntry", C.List_Breakpoint, "clearCpuSamples", C.List_Success, "clearVMTimeline", C.List_Success, "invoke", C.List_InstanceRef_ErrorRef, "evaluate", C.List_InstanceRef_ErrorRef, "evaluateInFrame", C.List_InstanceRef_ErrorRef, "getAllocationProfile", C.List_AllocationProfile, "getClassList", C.List_ClassList, "getClientName", C.List_ClientName, "getCpuSamples", C.List_CpuSamples, "getFlagList", C.List_FlagList, "getInboundReferences", C.List_InboundReferences, "getInstances", C.List_InstanceSet, "getIsolate", C.List_Isolate, "getIsolateGroup", C.List_IsolateGroup, "getMemoryUsage", C.List_MemoryUsage, "getIsolateGroupMemoryUsage", C.List_MemoryUsage, "getScripts", C.List_ScriptList, "getObject", C.List_Obj, "getRetainingPath", C.List_RetainingPath, "getStack", C.List_Stack, "getSourceReport", C.List_SourceReport, "getVersion", C.List_Version, "getVM", C.List_VM, "getVMTimeline", C.List_Timeline, "getVMTimelineFlags", C.List_TimelineFlags, "getVMTimelineMicros", C.List_Timestamp, "pause", C.List_Success, "kill", C.List_Success, "registerService", C.List_Success, "reloadSources", C.List_ReloadReport, "removeBreakpoint", C.List_Success, "requestHeapSnapshot", C.List_Success, "requirePermissionToResume", C.List_Success, "resume", C.List_Success, "setClientName", C.List_Success, "setExceptionPauseMode", C.List_Success, "setFlag", C.List_Success_Error, "setLibraryDebuggable", C.List_Success, "setName", C.List_Success, "setVMName", C.List_Success, "setVMTimelineFlags", C.List_Success, "streamCancel", C.List_Success, "streamListen", C.List_Success], type$.legacy_String, type$.legacy_List_legacy_String);
+    $._typeFactories = P.LinkedHashMap_LinkedHashMap$_literal(["AllocationProfile", Q.vm_service_AllocationProfile_parse$closure(), "BoundField", Q.vm_service_BoundField_parse$closure(), "BoundVariable", Q.vm_service_BoundVariable_parse$closure(), "Breakpoint", Q.vm_service_Breakpoint_parse$closure(), "@Class", Q.vm_service_ClassRef_parse$closure(), "Class", Q.vm_service_Class_parse$closure(), "ClassHeapStats", Q.vm_service_ClassHeapStats_parse$closure(), "ClassList", Q.vm_service_ClassList_parse$closure(), "ClientName", Q.vm_service_ClientName_parse$closure(), "@Code", Q.vm_service_CodeRef_parse$closure(), "Code", Q.vm_service_Code_parse$closure(), "@Context", Q.vm_service_ContextRef_parse$closure(), "Context", Q.vm_service_Context_parse$closure(), "ContextElement", Q.vm_service_ContextElement_parse$closure(), "CpuSamples", Q.vm_service_CpuSamples_parse$closure(), "CpuSample", Q.vm_service_CpuSample_parse$closure(), "@Error", Q.vm_service_ErrorRef_parse$closure(), "Error", Q.vm_service_Error_parse$closure(), "Event", Q.vm_service_Event_parse$closure(), "ExtensionData", Q.vm_service_ExtensionData_parse$closure(), "@Field", Q.vm_service_FieldRef_parse$closure(), "Field", Q.vm_service_Field_parse$closure(), "Flag", Q.vm_service_Flag_parse$closure(), "FlagList", Q.vm_service_FlagList_parse$closure(), "Frame", Q.vm_service_Frame_parse$closure(), "@Function", Q.vm_service_FuncRef_parse$closure(), "Function", Q.vm_service_Func_parse$closure(), "@Instance", Q.vm_service_InstanceRef_parse$closure(), "Instance", Q.vm_service_Instance_parse$closure(), "@Isolate", Q.vm_service_IsolateRef_parse$closure(), "Isolate", Q.vm_service_Isolate_parse$closure(), "@IsolateGroup", Q.vm_service_IsolateGroupRef_parse$closure(), "IsolateGroup", Q.vm_service_IsolateGroup_parse$closure(), "InboundReferences", Q.vm_service_InboundReferences_parse$closure(), "InboundReference", Q.vm_service_InboundReference_parse$closure(), "InstanceSet", Q.vm_service_InstanceSet_parse$closure(), "@Library", Q.vm_service_LibraryRef_parse$closure(), "Library", Q.vm_service_Library_parse$closure(), "LibraryDependency", Q.vm_service_LibraryDependency_parse$closure(), "LogRecord", Q.vm_service_LogRecord_parse$closure(), "MapAssociation", Q.vm_service_MapAssociation_parse$closure(), "MemoryUsage", Q.vm_service_MemoryUsage_parse$closure(), "Message", Q.vm_service_Message_parse$closure(), "NativeFunction", Q.vm_service_NativeFunction_parse$closure(), "@Null", Q.vm_service_NullValRef_parse$closure(), "Null", Q.vm_service_NullVal_parse$closure(), "@Object", Q.vm_service_ObjRef_parse$closure(), "Object", Q.vm_service_Obj_parse$closure(), "ProfileFunction", Q.vm_service_ProfileFunction_parse$closure(), "ProtocolList", Q.vm_service_ProtocolList_parse$closure(), "Protocol", Q.vm_service_Protocol_parse$closure(), "ReloadReport", Q.vm_service_ReloadReport_parse$closure(), "RetainingObject", Q.vm_service_RetainingObject_parse$closure(), "RetainingPath", Q.vm_service_RetainingPath_parse$closure(), "Response", Q.vm_service_Response_parse$closure(), "Sentinel", Q.vm_service_Sentinel_parse$closure(), "@Script", Q.vm_service_ScriptRef_parse$closure(), "Script", Q.vm_service_Script_parse$closure(), "ScriptList", Q.vm_service_ScriptList_parse$closure(), "SourceLocation", Q.vm_service_SourceLocation_parse$closure(), "SourceReport", Q.vm_service_SourceReport_parse$closure(), "SourceReportCoverage", Q.vm_service_SourceReportCoverage_parse$closure(), "SourceReportRange", Q.vm_service_SourceReportRange_parse$closure(), "Stack", Q.vm_service_Stack_parse$closure(), "Success", Q.vm_service_Success_parse$closure(), "Timeline", Q.vm_service_Timeline_parse$closure(), "TimelineEvent", Q.vm_service_TimelineEvent_parse$closure(), "TimelineFlags", Q.vm_service_TimelineFlags_parse$closure(), "Timestamp", Q.vm_service_Timestamp_parse$closure(), "@TypeArguments", Q.vm_service_TypeArgumentsRef_parse$closure(), "TypeArguments", Q.vm_service_TypeArguments_parse$closure(), "UnresolvedSourceLocation", Q.vm_service_UnresolvedSourceLocation_parse$closure(), "Version", Q.vm_service_Version_parse$closure(), "@VM", Q.vm_service_VMRef_parse$closure(), "VM", Q.vm_service_VM_parse$closure()], type$.legacy_String, H.findType("Function*"));
+    $._methodReturnTypes = P.LinkedHashMap_LinkedHashMap$_literal(["addBreakpoint", C.List_Breakpoint, "addBreakpointWithScriptUri", C.List_Breakpoint, "addBreakpointAtEntry", C.List_Breakpoint, "clearCpuSamples", C.List_Success, "clearVMTimeline", C.List_Success, "invoke", C.List_InstanceRef_ErrorRef, "evaluate", C.List_InstanceRef_ErrorRef, "evaluateInFrame", C.List_InstanceRef_ErrorRef, "getAllocationProfile", C.List_AllocationProfile, "getClassList", C.List_ClassList, "getClientName", C.List_ClientName, "getCpuSamples", C.List_CpuSamples, "getFlagList", C.List_FlagList, "getInboundReferences", C.List_InboundReferences, "getInstances", C.List_InstanceSet, "getIsolate", C.List_Isolate, "getIsolateGroup", C.List_IsolateGroup, "getMemoryUsage", C.List_MemoryUsage, "getIsolateGroupMemoryUsage", C.List_MemoryUsage, "getScripts", C.List_ScriptList, "getObject", C.List_Obj, "getRetainingPath", C.List_RetainingPath, "getStack", C.List_Stack, "getSupportedProtocols", C.List_ProtocolList, "getSourceReport", C.List_SourceReport, "getVersion", C.List_Version, "getVM", C.List_VM, "getVMTimeline", C.List_Timeline, "getVMTimelineFlags", C.List_TimelineFlags, "getVMTimelineMicros", C.List_Timestamp, "pause", C.List_Success, "kill", C.List_Success, "registerService", C.List_Success, "reloadSources", C.List_ReloadReport, "removeBreakpoint", C.List_Success, "requestHeapSnapshot", C.List_Success, "requirePermissionToResume", C.List_Success, "resume", C.List_Success, "setClientName", C.List_Success, "setExceptionPauseMode", C.List_Success, "setFlag", C.List_Success_Error, "setLibraryDebuggable", C.List_Success, "setName", C.List_Success, "setVMName", C.List_Success, "setVMTimelineFlags", C.List_Success, "streamCancel", C.List_Success, "streamListen", C.List_Success], type$.legacy_String, type$.legacy_List_legacy_String);
   })();
   (function lazyInitializers() {
-    var _lazy = hunkHelpers.lazy;
-    _lazy($, "DART_CLOSURE_PROPERTY_NAME", "$get$DART_CLOSURE_PROPERTY_NAME", function() {
+    var _lazyFinal = hunkHelpers.lazyFinal,
+      _lazy = hunkHelpers.lazy,
+      _lazyOld = hunkHelpers.lazyOld;
+    _lazyFinal($, "DART_CLOSURE_PROPERTY_NAME", "$get$DART_CLOSURE_PROPERTY_NAME", function() {
       return H.getIsolateAffinityTag("_$dart_dartClosure");
     });
-    _lazy($, "TypeErrorDecoder_noSuchMethodPattern", "$get$TypeErrorDecoder_noSuchMethodPattern", function() {
+    _lazyFinal($, "nullFuture", "$get$nullFuture", function() {
+      return C.C__RootZone.run$1$1(new H.nullFuture_closure(), H.findType("Future<Null>"));
+    });
+    _lazyFinal($, "TypeErrorDecoder_noSuchMethodPattern", "$get$TypeErrorDecoder_noSuchMethodPattern", function() {
       return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn({
         toString: function() {
           return "$receiver$";
         }
       }));
     });
-    _lazy($, "TypeErrorDecoder_notClosurePattern", "$get$TypeErrorDecoder_notClosurePattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_notClosurePattern", "$get$TypeErrorDecoder_notClosurePattern", function() {
       return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn({$method$: null,
         toString: function() {
           return "$receiver$";
         }
       }));
     });
-    _lazy($, "TypeErrorDecoder_nullCallPattern", "$get$TypeErrorDecoder_nullCallPattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_nullCallPattern", "$get$TypeErrorDecoder_nullCallPattern", function() {
       return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn(null));
     });
-    _lazy($, "TypeErrorDecoder_nullLiteralCallPattern", "$get$TypeErrorDecoder_nullLiteralCallPattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_nullLiteralCallPattern", "$get$TypeErrorDecoder_nullLiteralCallPattern", function() {
       return H.TypeErrorDecoder_extractPattern(function() {
         var $argumentsExpr$ = '$arguments$';
         try {
@@ -14600,10 +14705,10 @@
         }
       }());
     });
-    _lazy($, "TypeErrorDecoder_undefinedCallPattern", "$get$TypeErrorDecoder_undefinedCallPattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_undefinedCallPattern", "$get$TypeErrorDecoder_undefinedCallPattern", function() {
       return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn(void 0));
     });
-    _lazy($, "TypeErrorDecoder_undefinedLiteralCallPattern", "$get$TypeErrorDecoder_undefinedLiteralCallPattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_undefinedLiteralCallPattern", "$get$TypeErrorDecoder_undefinedLiteralCallPattern", function() {
       return H.TypeErrorDecoder_extractPattern(function() {
         var $argumentsExpr$ = '$arguments$';
         try {
@@ -14613,10 +14718,10 @@
         }
       }());
     });
-    _lazy($, "TypeErrorDecoder_nullPropertyPattern", "$get$TypeErrorDecoder_nullPropertyPattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_nullPropertyPattern", "$get$TypeErrorDecoder_nullPropertyPattern", function() {
       return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokePropertyErrorOn(null));
     });
-    _lazy($, "TypeErrorDecoder_nullLiteralPropertyPattern", "$get$TypeErrorDecoder_nullLiteralPropertyPattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_nullLiteralPropertyPattern", "$get$TypeErrorDecoder_nullLiteralPropertyPattern", function() {
       return H.TypeErrorDecoder_extractPattern(function() {
         try {
           null.$method$;
@@ -14625,10 +14730,10 @@
         }
       }());
     });
-    _lazy($, "TypeErrorDecoder_undefinedPropertyPattern", "$get$TypeErrorDecoder_undefinedPropertyPattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_undefinedPropertyPattern", "$get$TypeErrorDecoder_undefinedPropertyPattern", function() {
       return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokePropertyErrorOn(void 0));
     });
-    _lazy($, "TypeErrorDecoder_undefinedLiteralPropertyPattern", "$get$TypeErrorDecoder_undefinedLiteralPropertyPattern", function() {
+    _lazyFinal($, "TypeErrorDecoder_undefinedLiteralPropertyPattern", "$get$TypeErrorDecoder_undefinedLiteralPropertyPattern", function() {
       return H.TypeErrorDecoder_extractPattern(function() {
         try {
           (void 0).$method$;
@@ -14637,25 +14742,27 @@
         }
       }());
     });
-    _lazy($, "_AsyncRun__scheduleImmediateClosure", "$get$_AsyncRun__scheduleImmediateClosure", function() {
+    _lazyFinal($, "_AsyncRun__scheduleImmediateClosure", "$get$_AsyncRun__scheduleImmediateClosure", function() {
       return P._AsyncRun__initializeScheduleImmediate();
     });
-    _lazy($, "Future__nullFuture", "$get$Future__nullFuture", function() {
-      return P._Future$zoneValue(null, C.C__RootZone, type$.Null);
+    _lazyFinal($, "Future__nullFuture", "$get$Future__nullFuture", function() {
+      return type$._Future_Null._as($.$get$nullFuture());
     });
-    _lazy($, "Future__falseFuture", "$get$Future__falseFuture", function() {
-      return P._Future$zoneValue(false, C.C__RootZone, type$.bool);
+    _lazyFinal($, "Future__falseFuture", "$get$Future__falseFuture", function() {
+      var t1 = new P._Future(C.C__RootZone, type$._Future_bool);
+      t1._setValue$1(false);
+      return t1;
     });
-    _lazy($, "Utf8Decoder__decoder", "$get$Utf8Decoder__decoder", function() {
-      return new P.Utf8Decoder_closure().call$0();
+    _lazyFinal($, "Utf8Decoder__decoder", "$get$Utf8Decoder__decoder", function() {
+      return new P.Utf8Decoder__decoder_closure().call$0();
     });
-    _lazy($, "Utf8Decoder__decoderNonfatal", "$get$Utf8Decoder__decoderNonfatal", function() {
-      return new P.Utf8Decoder_closure0().call$0();
+    _lazyFinal($, "Utf8Decoder__decoderNonfatal", "$get$Utf8Decoder__decoderNonfatal", function() {
+      return new P.Utf8Decoder__decoderNonfatal_closure().call$0();
     });
     _lazy($, "_hasErrorStackProperty", "$get$_hasErrorStackProperty", function() {
       return new Error().stack != void 0;
     });
-    _lazy($, "Logger_root", "$get$Logger_root", function() {
+    _lazyOld($, "Logger_root", "$get$Logger_root", function() {
       return F.Logger_Logger("");
     });
   })();
@@ -14713,10 +14820,11 @@
       scripts[i].addEventListener("load", onLoad, false);
   })(function(currentScript) {
     init.currentScript = currentScript;
+    var callMain = E.main;
     if (typeof dartMainRunner === "function")
-      dartMainRunner(E.main, []);
+      dartMainRunner(callMain, []);
     else
-      E.main([]);
+      callMain([]);
   });
 })();
 
diff --git a/pkg/dev_compiler/lib/js/legacy/dart_library.js b/pkg/dev_compiler/lib/js/legacy/dart_library.js
index 609945c..ac7b2b2 100644
--- a/pkg/dev_compiler/lib/js/legacy/dart_library.js
+++ b/pkg/dev_compiler/lib/js/legacy/dart_library.js
@@ -7,306 +7,316 @@
 if (!dart_library) {
   dart_library = typeof module != "undefined" && module.exports || {};
 
-(function (dart_library) {
-  'use strict';
+  (function (dart_library) {
+    'use strict';
 
-  // Throws an error related to module loading.
-  //
-  // This does not throw a Dart error because the Dart SDK may not have loaded
-  // yet, and module loading errors cannot be caught by Dart code.
-  function throwLibraryError(message) {
-    // Dispatch event to allow others to react to the load error without
-    // capturing the exception.
-    window.dispatchEvent(
-      new CustomEvent('dartLoadException', { detail: message }));
-    throw Error(message);
-  }
-
-  const libraryImports = Symbol('libraryImports');
-  dart_library.libraryImports = libraryImports;
-
-  // Module support.  This is a simplified module system for Dart.
-  // Longer term, we can easily migrate to an existing JS module system:
-  // ES6, AMD, RequireJS, ....
-
-  // Returns a proxy that delegates to the underlying loader.
-  // This defers loading of a module until a library is actually used.
-  const loadedModule = Symbol('loadedModule');
-  dart_library.defer = function (module, name, patch) {
-    let done = false;
-    function loadDeferred() {
-      done = true;
-      let mod = module[loadedModule];
-      let lib = mod[name];
-      // Install unproxied module and library in caller's context.
-      patch(mod, lib);
-    }
-    // The deferred library object.  Note, the only legal operations on a Dart
-    // library object should be get (to read a top-level variable, method, or
-    // Class) or set (to write a top-level variable).
-    return new Proxy({}, {
-      get: function (o, p) {
-        if (!done) loadDeferred();
-        return module[name][p];
-      },
-      set: function (o, p, value) {
-        if (!done) loadDeferred();
-        module[name][p] = value;
-        return true;
-      },
-    });
-  };
-
-  let _reverseImports = new Map();
-  class LibraryLoader {
-
-    constructor(name, defaultValue, imports, loader) {
-      imports.forEach(function (i) {
-        let deps = _reverseImports.get(i);
-        if (!deps) {
-          deps = new Set();
-          _reverseImports.set(i, deps);
-        }
-        deps.add(name);
-      });
-      this._name = name;
-      this._library = defaultValue ? defaultValue : {};
-      this._imports = imports;
-      this._loader = loader;
-
-      // Cyclic import detection
-      this._state = LibraryLoader.NOT_LOADED;
-    }
-
-    loadImports() {
-      let results = [];
-      for (let name of this._imports) {
-        results.push(import_(name));
+    // Throws an error related to module loading.
+    //
+    // This does not throw a Dart error because the Dart SDK may not have loaded
+    // yet, and module loading errors cannot be caught by Dart code.
+    function throwLibraryError(message) {
+      // Dispatch event to allow others to react to the load error without
+      // capturing the exception.
+      if (!!self.dispatchEvent) {
+        self.dispatchEvent(
+          new CustomEvent('dartLoadException', {detail: message}));
       }
-      return results;
+      throw Error(message);
     }
 
-    load() {
-      // Check for cycles
-      if (this._state == LibraryLoader.LOADING) {
-        throwLibraryError('Circular dependence on library: ' + this._name);
-      } else if (this._state >= LibraryLoader.READY) {
+    const libraryImports = Symbol('libraryImports');
+    dart_library.libraryImports = libraryImports;
+
+    // Module support.  This is a simplified module system for Dart.
+    // Longer term, we can easily migrate to an existing JS module system:
+    // ES6, AMD, RequireJS, ....
+
+    // Returns a proxy that delegates to the underlying loader.
+    // This defers loading of a module until a library is actually used.
+    const loadedModule = Symbol('loadedModule');
+    dart_library.defer = function (module, name, patch) {
+      let done = false;
+      function loadDeferred() {
+        done = true;
+        let mod = module[loadedModule];
+        let lib = mod[name];
+        // Install unproxied module and library in caller's context.
+        patch(mod, lib);
+      }
+      // The deferred library object.  Note, the only legal operations on a Dart
+      // library object should be get (to read a top-level variable, method, or
+      // Class) or set (to write a top-level variable).
+      return new Proxy({}, {
+        get: function (o, p) {
+          if (!done) loadDeferred();
+          return module[name][p];
+        },
+        set: function (o, p, value) {
+          if (!done) loadDeferred();
+          module[name][p] = value;
+          return true;
+        },
+      });
+    };
+
+    let _reverseImports = new Map();
+    class LibraryLoader {
+
+      constructor(name, defaultValue, imports, loader) {
+        imports.forEach(function (i) {
+          let deps = _reverseImports.get(i);
+          if (!deps) {
+            deps = new Set();
+            _reverseImports.set(i, deps);
+          }
+          deps.add(name);
+        });
+        this._name = name;
+        this._library = defaultValue ? defaultValue : {};
+        this._imports = imports;
+        this._loader = loader;
+
+        // Cyclic import detection
+        this._state = LibraryLoader.NOT_LOADED;
+      }
+
+      loadImports() {
+        let results = [];
+        for (let name of this._imports) {
+          results.push(import_(name));
+        }
+        return results;
+      }
+
+      load() {
+        // Check for cycles
+        if (this._state == LibraryLoader.LOADING) {
+          throwLibraryError('Circular dependence on library: ' + this._name);
+        } else if (this._state >= LibraryLoader.READY) {
+          return this._library;
+        }
+        this._state = LibraryLoader.LOADING;
+
+        // Handle imports
+        let args = this.loadImports();
+
+        // Load the library
+        let loader = this;
+        let library = this._library;
+
+        library[libraryImports] = this._imports;
+        library[loadedModule] = library;
+        args.unshift(library);
+
+        if (this._name == 'dart_sdk') {
+          // Eagerly load the SDK.
+          this._loader.apply(null, args);
+        } else {
+          // Load / parse other modules on demand.
+          let done = false;
+          this._library = new Proxy(library, {
+            get: function (o, name) {
+              if (!done) {
+                done = true;
+                loader._loader.apply(null, args);
+              }
+              return o[name];
+            }
+          });
+        }
+
+        this._state = LibraryLoader.READY;
         return this._library;
       }
-      this._state = LibraryLoader.LOADING;
 
-      // Handle imports
-      let args = this.loadImports();
+      stub() {
+        return this._library;
+      }
+    }
+    LibraryLoader.NOT_LOADED = 0;
+    LibraryLoader.LOADING = 1;
+    LibraryLoader.READY = 2;
 
-      // Load the library
-      let loader = this;
-      let library = this._library;
+    // Map from name to LibraryLoader
+    let _libraries = new Map();
+    dart_library.libraries = function () {
+      return _libraries.keys();
+    };
+    dart_library.debuggerLibraries = function () {
+      let debuggerLibraries = [];
+      _libraries.forEach(function (value, key, map) {
+        debuggerLibraries.push(value.load());
+      });
+      debuggerLibraries.__proto__ = null;
+      return debuggerLibraries;
+    };
 
-      library[libraryImports] = this._imports;
-      library[loadedModule] = library;
-      args.unshift(library);
+    // Invalidate a library and all things that depend on it
+    function _invalidateLibrary(name) {
+      let lib = _libraries.get(name);
+      if (lib._state == LibraryLoader.NOT_LOADED) return;
+      lib._state = LibraryLoader.NOT_LOADED;
+      lib._library = {};
+      let deps = _reverseImports.get(name);
+      if (!deps) return;
+      deps.forEach(_invalidateLibrary);
+    }
 
-      if (this._name == 'dart_sdk') {
-        // Eagerly load the SDK.
-        this._loader.apply(null, args);
-      } else {
-        // Load / parse other modules on demand.
-        let done = false;
-        this._library = new Proxy(library, {
-          get: function (o, name) {
-            if (!done) {
-              done = true;
-              loader._loader.apply(null, args);
-            }
-            return o[name];
+    function library(name, defaultValue, imports, loader) {
+      let result = _libraries.get(name);
+      if (result) {
+        console.log('Re-loading ' + name);
+        _invalidateLibrary(name);
+      }
+      result = new LibraryLoader(name, defaultValue, imports, loader);
+      _libraries.set(name, result);
+      return result;
+    }
+    dart_library.library = library;
+
+    // Maintain a stack of active imports.  If a requested library/module is not
+    // available, print the stack to show where/how it was requested.
+    let _stack = [];
+    function import_(name) {
+      let lib = _libraries.get(name);
+      if (!lib) {
+        let message = 'Module ' + name + ' not loaded in the browser.';
+        if (_stack != []) {
+          message += '\nDependency via:';
+          let indent = '';
+          for (let last = _stack.length - 1; last >= 0; last--) {
+            indent += ' ';
+            message += '\n' + indent + '- ' + _stack[last];
           }
+        }
+        throwLibraryError(message);
+      }
+      _stack.push(name);
+      let result = lib.load();
+      _stack.pop();
+      return result;
+    }
+    dart_library.import = import_;
+
+    let _debuggerInitialized = false;
+
+    // Called to initiate a hot restart of the application.
+    //
+    // "Hot restart" means all application state is cleared, the newly compiled
+    // modules are loaded, and `main()` is called.
+    //
+    // Note: `onReloadEnd()` can be provided, and if so will be used instead of
+    // `main()` for hot restart.
+    //
+    // This happens in the following sequence:
+    //
+    // 1. Look for `onReloadStart()` in the same library that has `main()`, and
+    //    call it if present. This function is implemented by the application to
+    //    ensure any global browser/DOM state is cleared, so the application can
+    //    restart.
+    // 2. Wait for `onReloadStart()` to complete (either synchronously, or async
+    //    if it returned a `Future`).
+    // 3. Call dart:_runtime's `hotRestart()` function to clear any state that
+    //    `dartdevc` is tracking, such as initialized static fields and type
+    //    caches.
+    // 4. Call `window.$dartWarmReload()` (provided by the HTML page) to reload
+    //    the relevant JS modules, passing a callback that will invoke `main()`.
+    // 5. `$dartWarmReload` calls the callback to rerun main.
+    //
+    function reload(clearState) {
+      // TODO(jmesserly): once we've rolled out `clearState` make it the default,
+      // and eventually remove the parameter.
+      if (clearState == null) clearState = true;
+
+
+      // TODO(jmesserly): we may want to change these APIs to use the
+      // "hot restart" terminology for consistency with Flutter. In Flutter,
+      // "hot reload" refers to keeping the application state and attempting to
+      // patch the code for the application while it is executing
+      // (https://flutter.io/hot-reload/), whereas "hot restart" refers to what
+      // dartdevc supports: tear down the app, update the code, and rerun the app.
+      if (!self || !self.$dartWarmReload) {
+        console.warn('Hot restart not supported in this environment.');
+        return;
+      }
+
+      // Call the application's `onReloadStart()` function, if provided.
+      let result;
+      if (_lastLibrary && _lastLibrary.onReloadStart) {
+        result = _lastLibrary.onReloadStart();
+      }
+
+      let sdk = _libraries.get("dart_sdk");
+
+      /// Once the `onReloadStart()` completes, this finishes the restart.
+      function finishHotRestart() {
+        self.console.clear();
+        if (clearState) {
+          // This resets all initialized fields and clears type caches and other
+          // temporary data structures used by the compiler/SDK.
+          sdk.dart.hotRestart();
+        }
+        // Call the module loader to reload the necessary modules.
+        self.$dartWarmReload(() => {
+          // Once the modules are loaded, rerun `main()`.
+          start(_lastModuleName, _lastLibraryName, true);
         });
       }
 
-      this._state = LibraryLoader.READY;
-      return this._library;
+      if (result && result.then) {
+        result.then(sdk._library.dart.Dynamic)(finishHotRestart);
+      } else {
+        finishHotRestart();
+      }
     }
+    dart_library.reload = reload;
 
-    stub() {
-      return this._library;
-    }
-  }
-  LibraryLoader.NOT_LOADED = 0;
-  LibraryLoader.LOADING = 1;
-  LibraryLoader.READY = 2;
 
-  // Map from name to LibraryLoader
-  let _libraries = new Map();
-  dart_library.libraries = function () { return _libraries.keys(); };
-  dart_library.debuggerLibraries = function () {
-    let debuggerLibraries = [];
-    _libraries.forEach(function (value, key, map) {
-      debuggerLibraries.push(value.load());
-    });
-    debuggerLibraries.__proto__ = null;
-    return debuggerLibraries;
-  };
+    let _lastModuleName;
+    let _lastLibraryName;
+    let _lastLibrary;
+    let _originalBody;
 
-  // Invalidate a library and all things that depend on it
-  function _invalidateLibrary(name) {
-    let lib = _libraries.get(name);
-    if (lib._state == LibraryLoader.NOT_LOADED) return;
-    lib._state = LibraryLoader.NOT_LOADED;
-    lib._library = {};
-    let deps = _reverseImports.get(name);
-    if (!deps) return;
-    deps.forEach(_invalidateLibrary);
-  }
+    function start(moduleName, libraryName, isReload) {
+      if (libraryName == null) libraryName = moduleName;
+      _lastModuleName = moduleName;
+      _lastLibraryName = libraryName;
+      let library = import_(moduleName)[libraryName];
+      _lastLibrary = library;
+      let dart_sdk = import_('dart_sdk');
 
-  function library(name, defaultValue, imports, loader) {
-    let result = _libraries.get(name);
-    if (result) {
-      console.log('Re-loading ' + name);
-      _invalidateLibrary(name);
-    }
-    result = new LibraryLoader(name, defaultValue, imports, loader);
-    _libraries.set(name, result);
-    return result;
-  }
-  dart_library.library = library;
+      if (!_debuggerInitialized) {
+        // This import is only needed for chrome debugging. We should provide an
+        // option to compile without it.
+        dart_sdk._debugger.registerDevtoolsFormatter();
 
-  // Maintain a stack of active imports.  If a requested library/module is not
-  // available, print the stack to show where/how it was requested.
-  let _stack = [];
-  function import_(name) {
-    let lib = _libraries.get(name);
-    if (!lib) {
-      let message = 'Module ' + name + ' not loaded in the browser.';
-      if (_stack != []) {
-        message += '\nDependency via:';
-        let indent = '';
-        for (let last = _stack.length - 1; last >= 0; last--) {
-          indent += ' ';
-          message += '\n' + indent + '- ' + _stack[last];
+        // Create isolate.
+        _debuggerInitialized = true;
+      }
+      if (isReload) {
+        if (library.onReloadEnd) {
+          library.onReloadEnd();
+          return;
+        } else {
+          if (!!self.document) {
+            // Note: we expect _originalBody to be undefined in non-browser
+            // environments, but in that case so is the body.
+            if (!_originalBody && !!self.document.body) {
+              self.console.warn('No body saved to update on reload');
+            } else {
+              self.document.body = _originalBody;
+            }
+          }
+        }
+      } else {
+        // If not a reload then store the initial html to reset it on reload.
+        if (!!self.document && !!self.document.body) {
+          _originalBody = self.document.body.cloneNode(true);
         }
       }
-      throwLibraryError(message);
+      library.main([]);
     }
-    _stack.push(name);
-    let result = lib.load();
-    _stack.pop();
-    return result;
-  }
-  dart_library.import = import_;
+    dart_library.start = start;
 
-  let _debuggerInitialized = false;
-
-  // Called to initiate a hot restart of the application.
-  //
-  // "Hot restart" means all application state is cleared, the newly compiled
-  // modules are loaded, and `main()` is called.
-  //
-  // Note: `onReloadEnd()` can be provided, and if so will be used instead of
-  // `main()` for hot restart.
-  //
-  // This happens in the following sequence:
-  //
-  // 1. Look for `onReloadStart()` in the same library that has `main()`, and
-  //    call it if present. This function is implemented by the application to
-  //    ensure any global browser/DOM state is cleared, so the application can
-  //    restart.
-  // 2. Wait for `onReloadStart()` to complete (either synchronously, or async
-  //    if it returned a `Future`).
-  // 3. Call dart:_runtime's `hotRestart()` function to clear any state that
-  //    `dartdevc` is tracking, such as initialized static fields and type
-  //    caches.
-  // 4. Call `window.$dartWarmReload()` (provided by the HTML page) to reload
-  //    the relevant JS modules, passing a callback that will invoke `main()`.
-  // 5. `$dartWarmReload` calls the callback to rerun main.
-  //
-  function reload(clearState) {
-    // TODO(jmesserly): once we've rolled out `clearState` make it the default,
-    // and eventually remove the parameter.
-    if (clearState == null) clearState = false;
-
-
-    // TODO(jmesserly): we may want to change these APIs to use the
-    // "hot restart" terminology for consistency with Flutter. In Flutter,
-    // "hot reload" refers to keeping the application state and attempting to
-    // patch the code for the application while it is executing
-    // (https://flutter.io/hot-reload/), whereas "hot restart" refers to what
-    // dartdevc supports: tear down the app, update the code, and rerun the app.
-    if (!window || !window.$dartWarmReload) {
-      console.warn('Hot restart not supported in this environment.');
-      return;
-    }
-
-    // Call the application's `onReloadStart()` function, if provided.
-    let result;
-    if (_lastLibrary && _lastLibrary.onReloadStart) {
-      result = _lastLibrary.onReloadStart();
-    }
-
-    let sdk = _libraries.get("dart_sdk");
-
-    /// Once the `onReloadStart()` completes, this finishes the restart.
-    function finishHotRestart() {
-      window.console.clear();
-      if (clearState) {
-        // This resets all initialized fields and clears type caches and other
-        // temporary data structures used by the compiler/SDK.
-        sdk.dart.hotRestart();
-      }
-      // Call the module loader to reload the necessary modules.
-      window.$dartWarmReload(() => {
-        // Once the modules are loaded, rerun `main()`.
-        start(_lastModuleName, _lastLibraryName, true);
-      });
-    }
-
-    if (result && result.then) {
-      result.then(sdk._library.dart.Dynamic)(finishHotRestart);
-    } else {
-      finishHotRestart();
-    }
-  }
-  dart_library.reload = reload;
-
-
-  let _lastModuleName;
-  let _lastLibraryName;
-  let _lastLibrary;
-  let _originalBody;
-
-  function start(moduleName, libraryName, isReload) {
-    if (libraryName == null) libraryName = moduleName;
-    _lastModuleName = moduleName;
-    _lastLibraryName = libraryName;
-    let library = import_(moduleName)[libraryName];
-    _lastLibrary = library;
-    let dart_sdk = import_('dart_sdk');
-
-    if (!_debuggerInitialized) {
-      // This import is only needed for chrome debugging. We should provide an
-      // option to compile without it.
-      dart_sdk._debugger.registerDevtoolsFormatter();
-
-      // Create isolate.
-      _debuggerInitialized = true;
-    }
-    if (isReload) {
-      if (library.onReloadEnd) {
-        library.onReloadEnd();
-        return;
-      } else { 
-        if (dart_sdk.dart.global.document) {
-          dart_sdk.dart.global.document.body = _originalBody;
-        }
-      }
-    } else {
-      // If not a reload then store the initial html to reset it on reload.
-      if (dart_sdk.dart.global.document) {
-        _originalBody = dart_sdk.dart.global.document.body.cloneNode(true);
-      }
-    }
-    library.main([]);
-  }
-  dart_library.start = start;
-
-})(dart_library);
+  })(dart_library);
 }
diff --git a/pkg/dev_compiler/lib/src/compiler/module_containers.dart b/pkg/dev_compiler/lib/src/compiler/module_containers.dart
new file mode 100644
index 0000000..8bda34d
--- /dev/null
+++ b/pkg/dev_compiler/lib/src/compiler/module_containers.dart
@@ -0,0 +1,296 @@
+// 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 '../compiler/js_names.dart' as js_ast;
+import '../js_ast/js_ast.dart' as js_ast;
+import '../js_ast/js_ast.dart' show js;
+
+/// Represents a top-level property hoisted to a top-level object.
+class ModuleItemData {
+  /// The container that holds this module item in the emitted JS.
+  js_ast.Identifier id;
+
+  /// This module item's key in the emitted JS.
+  ///
+  /// A LiteralString if this object is backed by a JS Object/Map.
+  /// A LiteralNumber if this object is backed by a JS Array.
+  js_ast.Literal jsKey;
+
+  /// This module item's value in the emitted JS.
+  js_ast.Expression jsValue;
+
+  ModuleItemData(this.id, this.jsKey, this.jsValue);
+}
+
+/// Holds variables emitted during code gen.
+///
+/// Associates a [K] with a container-unique JS key and arbitrary JS value.
+/// The container is emitted as a single object:
+/// ```
+/// var C = {
+///   jsKey: jsValue,
+///   ...
+/// };
+/// ```
+abstract class ModuleItemContainer<K> {
+  /// Name of the container in the emitted JS.
+  String name;
+
+  /// Indicates if this table is being used in an incremental context (such as
+  /// during expression evaluation).
+  ///
+  /// Set by `emitFunctionIncremental` in kernel/compiler.dart.
+  bool incrementalMode = false;
+
+  /// Refers to the latest container if this container is sharded.
+  js_ast.Identifier containerId;
+
+  /// Refers to the aggregated entrypoint into this container.
+  ///
+  /// Should only be accessed during expression evaluation since lookups are
+  /// deoptimized in V8..
+  js_ast.Identifier aggregatedContainerId;
+
+  final Map<K, ModuleItemData> moduleItems = {};
+
+  /// Holds keys that will not be emitted when calling [emit].
+  final Set<K> _noEmit = {};
+
+  /// Creates a container with a name, ID, and incremental ID used for
+  /// expression evaluation.
+  ///
+  /// If [aggregatedId] is null, the container is not sharded, so the
+  /// containerId is safe to use during eval.
+  ModuleItemContainer._(
+      this.name, this.containerId, js_ast.Identifier aggregatedId)
+      : this.aggregatedContainerId = aggregatedId ?? containerId;
+
+  /// Creates an automatically sharding container backed by JS Objects.
+  factory ModuleItemContainer.asObject(String name,
+      {String Function(K) keyToString}) {
+    return ModuleItemObjectContainer<K>(name, keyToString);
+  }
+
+  /// Creates a container backed by a JS Array.
+  factory ModuleItemContainer.asArray(String name) {
+    return ModuleItemArrayContainer<K>(name);
+  }
+
+  bool get isNotEmpty => moduleItems.isNotEmpty;
+
+  Iterable<K> get keys => moduleItems.keys;
+
+  int get length => moduleItems.keys.length;
+
+  bool get isEmpty => moduleItems.isEmpty;
+
+  js_ast.Expression operator [](K key) => moduleItems[key]?.jsValue;
+
+  void operator []=(K key, js_ast.Expression value);
+
+  /// Returns the expression that retrieves [key]'s corresponding JS value via
+  /// a property access through its container.
+  js_ast.Expression access(K key);
+
+  bool contains(K key) => moduleItems.containsKey(key);
+
+  bool canEmit(K key) => !_noEmit.contains(key);
+
+  /// Indicates that [K] should be treated as if it weren't hoisted.
+  ///
+  /// Used when we are managing the variable declarations manually (such as
+  /// unhoisting specific symbols for performance reasons).
+  void setNoEmit(K key) {
+    _noEmit.add(key);
+  }
+
+  /// Emit the container declaration/initializer, using multiple statements if
+  /// necessary.
+  List<js_ast.Statement> emit();
+
+  /// Emit the container declaration/initializer incrementally.
+  ///
+  /// Used during expression evaluation. Appends all newly added types to the
+  /// aggregated container.
+  List<js_ast.Statement> emitIncremental();
+}
+
+/// Associates a [K] with a container-unique JS key and arbitrary JS value.
+///
+/// Emitted as a series of JS Objects, splitting them into groups of 500 for
+/// JS optimization purposes:
+/// ```
+/// var C = {
+///   jsKey: jsValue,
+///   ...
+/// };
+/// var C$1 = { ... };
+/// ```
+class ModuleItemObjectContainer<K> extends ModuleItemContainer<K> {
+  /// Tracks how often JS emitted field names appear.
+  ///
+  /// [keyToString] may resolve multiple unique keys to the same JS string.
+  /// When this occurs, the resolved JS string will automatically be renamed.
+  final Map<String, int> _nameFrequencies = {};
+
+  /// Transforms a [K] into a valid name for a JS object property key.
+  ///
+  /// Non-unique generated strings are automatically renamed.
+  String Function(K) keyToString;
+
+  ModuleItemObjectContainer(String name, this.keyToString)
+      : super._(
+            name, js_ast.TemporaryId(name), js_ast.Identifier('${name}\$Eval'));
+
+  @override
+  void operator []=(K key, js_ast.Expression value) {
+    if (this.contains(key)) {
+      moduleItems[key].jsValue = value;
+      return;
+    }
+    // Create a unique name for K when emitted as a JS field.
+    var fieldString = keyToString(key);
+    _nameFrequencies.update(fieldString, (v) {
+      fieldString += '\$${v + 1}';
+      return v + 1;
+    }, ifAbsent: () {
+      // Avoid shadowing common JS properties.
+      if (js_ast.objectProperties.contains(fieldString)) {
+        fieldString += '\$';
+      }
+      return 0;
+    });
+    moduleItems[key] = ModuleItemData(
+        containerId, js_ast.LiteralString("'$fieldString'"), value);
+    if (length % 500 == 0) containerId = js_ast.TemporaryId(name);
+  }
+
+  @override
+  js_ast.Expression access(K key) {
+    var id = incrementalMode ? aggregatedContainerId : moduleItems[key].id;
+    return js.call('#.#', [id, moduleItems[key].jsKey]);
+  }
+
+  @override
+  List<js_ast.Statement> emit() {
+    var containersToProperties = <js_ast.Identifier, List<js_ast.Property>>{};
+    moduleItems.forEach((k, v) {
+      if (_noEmit.contains(k)) return;
+      if (!containersToProperties.containsKey(v.id)) {
+        containersToProperties[v.id] = <js_ast.Property>[];
+      }
+      containersToProperties[v.id].add(js_ast.Property(v.jsKey, v.jsValue));
+    });
+
+    // Emit a self-reference for the next container so V8 does not optimize it
+    // away. Required for expression evaluation.
+    if (containersToProperties[containerId] == null) {
+      containersToProperties[containerId] = [
+        js_ast.Property(
+            js_ast.LiteralString('_'), js.call('() => #', [containerId]))
+      ];
+    }
+    var statements = <js_ast.Statement>[];
+    var aggregatedContainers = <js_ast.Expression>[];
+    containersToProperties.forEach((containerId, properties) {
+      var containerObject = js_ast.ObjectInitializer(properties,
+          multiline: properties.length > 1);
+      statements.add(js.statement('var # = #', [containerId, containerObject]));
+      aggregatedContainers.add(js.call('#', [containerId]));
+    });
+    // Create an aggregated access point over all containers for eval.
+    statements.add(js.statement('var # = Object.assign({_ : () => #}, #)',
+        [aggregatedContainerId, aggregatedContainerId, aggregatedContainers]));
+    return statements;
+  }
+
+  /// Appends all newly added types to the most recent container.
+  @override
+  List<js_ast.Statement> emitIncremental() {
+    assert(incrementalMode);
+    var statements = <js_ast.Statement>[];
+    moduleItems.forEach((k, v) {
+      if (_noEmit.contains(k)) return;
+      statements.add(js
+          .statement('#[#] = #', [aggregatedContainerId, v.jsKey, v.jsValue]));
+    });
+    return statements;
+  }
+}
+
+/// Associates a unique [K] with an arbitrary JS value.
+///
+/// Emitted as a JS Array:
+/// ```
+/// var C = [
+///   jsValue,
+///   ...
+/// ];
+/// ```
+class ModuleItemArrayContainer<K> extends ModuleItemContainer<K> {
+  ModuleItemArrayContainer(String name)
+      : super._(name, js_ast.TemporaryId(name), null);
+
+  @override
+  void operator []=(K key, js_ast.Expression value) {
+    if (moduleItems.containsKey(key)) {
+      moduleItems[key].jsValue = value;
+      return;
+    }
+    moduleItems[key] =
+        ModuleItemData(containerId, js_ast.LiteralNumber('$length'), value);
+  }
+
+  @override
+  js_ast.Expression access(K key) {
+    var id = incrementalMode ? aggregatedContainerId : containerId;
+    return js.call('#[#]', [id, moduleItems[key].jsKey]);
+  }
+
+  @override
+  List<js_ast.Statement> emit() {
+    var properties = List<js_ast.Expression>.filled(length, null);
+
+    // If the entire array holds just one value, generate a short initializer.
+    var valueSet = <js_ast.Expression>{};
+    moduleItems.forEach((k, v) {
+      if (_noEmit.contains(k)) return;
+      valueSet.add(v.jsValue);
+      properties[int.parse((v.jsKey as js_ast.LiteralNumber).value)] =
+          v.jsValue;
+    });
+
+    if (valueSet.length == 1 && moduleItems.length > 1) {
+      return [
+        js.statement('var # = Array(#).fill(#)', [
+          containerId,
+          js_ast.LiteralNumber('${properties.length}'),
+          valueSet.first
+        ])
+      ];
+    }
+    // Array containers are not sharded, as we do not expect to hit V8's
+    // dictionary-mode limit of 99999 elements.
+    return [
+      js.statement('var # = #', [
+        containerId,
+        js_ast.ArrayInitializer(properties, multiline: properties.length > 1)
+      ])
+    ];
+  }
+
+  @override
+  List<js_ast.Statement> emitIncremental() {
+    assert(incrementalMode);
+    var statements = <js_ast.Statement>[];
+    moduleItems.forEach((k, v) {
+      if (_noEmit.contains(k)) return;
+      statements.add(js
+          .statement('#[#] = #', [aggregatedContainerId, v.jsKey, v.jsValue]));
+    });
+    return statements;
+  }
+}
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index e9527d9..363ff0b 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -8,6 +8,7 @@
 import 'package:meta/meta.dart';
 
 import '../compiler/js_names.dart' as js_ast;
+import '../compiler/module_containers.dart' show ModuleItemContainer;
 import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 
@@ -25,6 +26,10 @@
   /// Private member names in this module, organized by their library.
   final _privateNames = HashMap<Library, HashMap<String, js_ast.TemporaryId>>();
 
+  /// Holds all top-level JS symbols (used for caching or indexing fields).
+  final _symbolContainer = ModuleItemContainer<js_ast.Identifier>.asObject('S',
+      keyToString: (js_ast.Identifier i) => '${i.name}');
+
   /// Extension member symbols for adding Dart members to JS types.
   ///
   /// These are added to the [extensionSymbolsModule]; see that field for more
@@ -51,11 +56,18 @@
   /// Whether we're currently building the SDK, which may require special
   /// bootstrapping logic.
   ///
-  /// This is initialized by [startModule], which must be called before
+  /// This is initialized by [emitModule], which must be called before
   /// accessing this field.
   @protected
   bool isBuildingSdk;
 
+  /// Whether or not to move top level symbols into top-level containers.
+  ///
+  /// This is set in both [emitModule] and [emitLibrary].
+  /// Depends on [isBuildingSdk].
+  @protected
+  bool containerizeSymbols;
+
   /// The temporary variable that stores named arguments (these are passed via a
   /// JS object literal, to match JS conventions).
   @protected
@@ -250,10 +262,16 @@
       var idName = name.endsWith('=') ? name.replaceAll('=', '_') : name;
       idName = idName.replaceAll(js_ast.invalidCharInIdentifier, '_');
       id ??= js_ast.TemporaryId(idName);
-      // TODO(vsm): Change back to `const`.
-      // See https://github.com/dart-lang/sdk/issues/40380.
-      moduleItems.add(js.statement('var # = #.privateName(#, #)',
-          [id, runtimeModule, emitLibraryName(library), js.string(name)]));
+      addSymbol(
+          id,
+          js.call('#.privateName(#, #)',
+              [runtimeModule, emitLibraryName(library), js.string(name)]));
+      if (!containerizeSymbols) {
+        // TODO(vsm): Change back to `const`.
+        // See https://github.com/dart-lang/sdk/issues/40380.
+        moduleItems.add(js.statement('var # = #.privateName(#, #)',
+            [id, runtimeModule, emitLibraryName(library), js.string(name)]));
+      }
       return id;
     }
 
@@ -338,9 +356,13 @@
     var name = js.escapedString(symbolName, "'");
     js_ast.Expression result;
     if (last.startsWith('_')) {
-      var nativeSymbol = emitPrivateNameSymbol(currentLibrary, last);
-      result = js.call('new #.new(#, #)',
-          [emitConstructorAccess(privateSymbolType), name, nativeSymbol]);
+      var nativeSymbolAccessor =
+          getSymbol(emitPrivateNameSymbol(currentLibrary, last));
+      result = js.call('new #.new(#, #)', [
+        emitConstructorAccess(privateSymbolType),
+        name,
+        nativeSymbolAccessor
+      ]);
     } else {
       result = js.call(
           'new #.new(#)', [emitConstructorAccess(internalSymbolType), name]);
@@ -366,12 +388,11 @@
   /// symbols into the list returned by this method. Finally, [finishModule]
   /// can be called to complete the module and return the resulting JS AST.
   ///
-  /// This also initializes several fields: [isBuildingSdk], [runtimeModule],
-  /// [extensionSymbolsModule], as well as the [_libraries] map needed by
+  /// This also initializes several fields: [runtimeModule],
+  /// [extensionSymbolsModule], and the [_libraries] map needed by
   /// [emitLibraryName].
   @protected
   List<js_ast.ModuleItem> startModule(Iterable<Library> libraries) {
-    isBuildingSdk = libraries.any(isSdkInternalRuntime);
     if (isBuildingSdk) {
       // Don't allow these to be renamed when we're building the SDK.
       // There is JS code in dart:* that depends on their names.
@@ -460,7 +481,8 @@
 
   /// Emits imports and extension methods into [items].
   @protected
-  void emitImportsAndExtensionSymbols(List<js_ast.ModuleItem> items) {
+  void emitImportsAndExtensionSymbols(List<js_ast.ModuleItem> items,
+      {bool forceExtensionSymbols = false}) {
     var modules = <String, List<Library>>{};
 
     for (var import in _imports.keys) {
@@ -504,10 +526,17 @@
           js_ast.PropertyAccess(extensionSymbolsModule, propertyName(name));
       if (isBuildingSdk) {
         value = js.call('# = Symbol(#)', [value, js.string('dartx.$name')]);
+      } else if (forceExtensionSymbols) {
+        value = js.call(
+            '# || (# = Symbol(#))', [value, value, js.string('dartx.$name')]);
       }
-      // TODO(vsm): Change back to `const`.
-      // See https://github.com/dart-lang/sdk/issues/40380.
-      items.add(js.statement('var # = #;', [id, value]));
+      if (!_symbolContainer.canEmit(id)) {
+        // Extension symbols marked with noEmit are managed manually.
+        // TODO(vsm): Change back to `const`.
+        // See https://github.com/dart-lang/sdk/issues/40380.
+        items.add(js.statement('var # = #;', [id, value]));
+      }
+      _symbolContainer[id] = value;
     });
   }
 
@@ -534,6 +563,32 @@
         [runtimeModule, js.string(name), module, partMap]));
   }
 
+  /// Returns an accessor for [id] via the symbol container.
+  /// E.g., transforms $sym to S$5.$sym.
+  ///
+  /// A symbol lookup on an id marked no emit omits the symbol accessor.
+  js_ast.Expression getSymbol(js_ast.Identifier id) {
+    return _symbolContainer.canEmit(id) ? _symbolContainer.access(id) : id;
+  }
+
+  /// Returns the raw JS value associated with [id].
+  js_ast.Expression getSymbolValue(js_ast.Identifier id) {
+    return _symbolContainer[id];
+  }
+
+  /// Inserts a symbol into the symbol table.
+  js_ast.Expression addSymbol(js_ast.Identifier id, js_ast.Expression symbol) {
+    _symbolContainer[id] = symbol;
+    if (!containerizeSymbols) {
+      _symbolContainer.setNoEmit(id);
+    }
+    return _symbolContainer[id];
+  }
+
+  void setSymbolContainerIncrementalMode(bool setting) {
+    _symbolContainer.incrementalMode = setting;
+  }
+
   /// Finishes the module created by [startModule], by combining the preable
   /// [items] with the [moduleItems] that have been emitted.
   ///
@@ -552,6 +607,9 @@
     // code between `startModule` and `finishModule` is very similar in both.
     _emitDebuggerExtensionInfo(moduleName);
 
+    // Emit all top-level JS symbol containers.
+    items.addAll(_symbolContainer.emit());
+
     // Add the module's code (produced by visiting compilation units, above)
     _copyAndFlattenBlocks(items, moduleItems);
     moduleItems.clear();
@@ -582,10 +640,13 @@
   /// handle the many details involved in naming.
   @protected
   js_ast.TemporaryId getExtensionSymbolInternal(String name) {
-    return _extensionSymbols.putIfAbsent(
-        name,
-        () => js_ast.TemporaryId(
-            '\$${js_ast.friendlyNameForDartOperator[name] ?? name}'));
+    if (!_extensionSymbols.containsKey(name)) {
+      var id = js_ast.TemporaryId(
+          '\$${js_ast.friendlyNameForDartOperator[name] ?? name}');
+      _extensionSymbols[name] = id;
+      addSymbol(id, id);
+    }
+    return _extensionSymbols[name];
   }
 
   /// Shorthand for identifier-like property names.
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index 137bfd4..bdfb6c9 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -906,28 +906,19 @@
 
 class LiteralExpression extends Expression {
   final String template;
-  final List<Expression> inputs;
-
-  LiteralExpression(this.template) : inputs = const [];
-  LiteralExpression.withData(this.template, this.inputs);
+  LiteralExpression(this.template);
 
   @override
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralExpression(this);
 
   @override
-  void visitChildren(NodeVisitor visitor) {
-    if (inputs != null) {
-      for (Expression expr in inputs) {
-        expr.accept(visitor);
-      }
-    }
-  }
+  void visitChildren(NodeVisitor visitor) {}
 
   @override
-  LiteralExpression _clone() => LiteralExpression.withData(template, inputs);
+  LiteralExpression _clone() => LiteralExpression(template);
 
-  // Code that uses JS must take care of operator precedences, and
-  // put parenthesis if needed.
+  // Code that uses LiteralExpression must take care of operator precedences,
+  // and put parenthesis if needed.
   @override
   int get precedenceLevel => PRIMARY;
 }
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index d62126b..9fabc56 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -1355,21 +1355,7 @@
 
   @override
   visitLiteralExpression(LiteralExpression node) {
-    String template = node.template;
-    List<Expression> inputs = node.inputs;
-
-    List<String> parts = template.split('#');
-    int inputsLength = inputs == null ? 0 : inputs.length;
-    if (parts.length != inputsLength + 1) {
-      context.error('Wrong number of arguments for JS: $template');
-    }
-    // Code that uses JS must take care of operator precedences, and
-    // put parenthesis if needed.
-    out(parts[0]);
-    for (int i = 0; i < inputsLength; i++) {
-      visit(inputs[i]);
-      out(parts[i + 1]);
-    }
+    out(node.template);
   }
 
   @override
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index fb3f3c8..8085f69 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -16,6 +16,7 @@
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart' hide MapEntry;
+import 'package:kernel/ast.dart' show NonNullableByDefaultCompiledMode;
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
 import 'package:path/path.dart' as p;
@@ -707,7 +708,11 @@
 ModuleMetadata _emitMetadata(js_ast.Program program, Component component,
     String sourceMapUri, String moduleUri) {
   var metadata = ModuleMetadata(
-      program.name, loadFunctionName(program.name), sourceMapUri, moduleUri);
+      program.name,
+      loadFunctionName(program.name),
+      sourceMapUri,
+      moduleUri,
+      component.mode == NonNullableByDefaultCompiledMode.Strong);
 
   for (var lib in component.libraries) {
     metadata.addLibrary(LibraryMetadata(
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index d3f637a..db638dc 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -22,6 +22,7 @@
 import '../compiler/js_utils.dart' as js_ast;
 import '../compiler/module_builder.dart'
     show isSdkInternalRuntimeUri, libraryUriToJsIdentifier, pathToJSIdentifier;
+import '../compiler/module_containers.dart' show ModuleItemContainer;
 import '../compiler/shared_command.dart' show SharedCompilerOptions;
 import '../compiler/shared_compiler.dart';
 import '../js_ast/js_ast.dart' as js_ast;
@@ -34,6 +35,7 @@
 import 'native_types.dart';
 import 'nullable_inference.dart';
 import 'property_model.dart';
+import 'target.dart' show allowedNativeTest;
 import 'type_table.dart';
 
 class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
@@ -69,11 +71,14 @@
   /// Let variables collected for the given function.
   List<js_ast.TemporaryId> _letVariables;
 
-  final _constTable = _emitTemporaryId('CT');
+  final _constTable = js_ast.Identifier('CT');
 
-  // Constant getters used to populate the constant table.
+  /// Constant getters used to populate the constant table.
   final _constLazyAccessors = <js_ast.Method>[];
 
+  /// Container for holding the results of lazily-evaluated constants.
+  final _constTableCache = ModuleItemContainer<String>.asArray('C');
+
   /// Tracks the index in [moduleItems] where the const table must be inserted.
   /// Required for SDK builds due to internal circular dependencies.
   /// E.g., dart.constList depends on JSArray.
@@ -216,7 +221,7 @@
   final constAliasCache = HashMap<Constant, js_ast.Expression>();
 
   /// Maps uri strings in asserts and elsewhere to hoisted identifiers.
-  final _uriMap = HashMap<String, js_ast.Identifier>();
+  final _uriContainer = ModuleItemContainer<String>.asArray('I');
 
   final Class _jsArrayClass;
   final Class _privateSymbolClass;
@@ -247,7 +252,7 @@
     coreTypes ??= CoreTypes(component);
     var types = TypeEnvironment(coreTypes, hierarchy);
     var constants = DevCompilerConstants();
-    var nativeTypes = NativeTypeSet(coreTypes, constants);
+    var nativeTypes = NativeTypeSet(coreTypes, constants, component);
     var jsTypeRep = JSTypeRep(types, hierarchy);
     var staticTypeContext = StatefulStaticTypeContext.stacked(types);
     return ProgramCompiler._(
@@ -323,7 +328,32 @@
 
     var libraries = component.libraries;
 
-    // Initialize our library variables.
+    // Initialize library variables.
+    isBuildingSdk = libraries.any(isSdkInternalRuntime);
+
+    // For runtime performance reasons, we only containerize SDK symbols in web
+    // libraries. Otherwise, we use a 600-member cutoff before a module is
+    // containerized. This is somewhat arbitrary but works promisingly for the
+    // SDK and Flutter Web.
+    if (!isBuildingSdk) {
+      // The number of DDC top-level symbols scales with the number of
+      // non-static class members across an entire module.
+      var uniqueNames = HashSet<String>();
+      libraries.forEach((Library l) {
+        l.classes.forEach((Class c) {
+          c.members.forEach((m) {
+            var isStatic =
+                m is Field ? m.isStatic : (m is Procedure ? m.isStatic : false);
+            if (isStatic) return;
+            var name = js_ast.toJSIdentifier(
+                m.name.text.replaceAll(js_ast.invalidCharInIdentifier, '_'));
+            uniqueNames.add(name);
+          });
+        });
+      });
+      containerizeSymbols = uniqueNames.length > 600;
+    }
+
     var items = startModule(libraries);
     _nullableInference.allowNotNullDeclarations = isBuildingSdk;
     _typeTable = TypeTable(runtimeModule);
@@ -335,10 +365,23 @@
       _pendingClasses.addAll(l.classes);
     }
 
-    // TODO(markzipan): Don't emit this when compiling the SDK.
-    moduleItems
-        .add(js.statement('const # = Object.create(null);', [_constTable]));
-    _constTableInsertionIndex = moduleItems.length;
+    // Insert a circular reference so neither the constant table or its cache
+    // are optimized away by V8. Required for expression evaluation.
+    var constTableDeclaration =
+        js.statement('const # = Object.create({# : () => (#, #)});', [
+      _constTable,
+      js_ast.LiteralString('_'),
+      _constTableCache.containerId,
+      _constTable
+    ]);
+    moduleItems.add(constTableDeclaration);
+
+    // Record a safe index after the declaration of type generators and
+    // top-level symbols but before the declaration of any functions.
+    // Various preliminary data structures must be inserted here prior before
+    // referenced by the rest of the module.
+    var safeDeclarationIndex = moduleItems.length;
+    _constTableInsertionIndex = safeDeclarationIndex;
 
     // Add implicit dart:core dependency so it is first.
     emitLibraryName(_coreTypes.coreLibrary);
@@ -350,8 +393,11 @@
     // This is done by forward declaring items.
     libraries.forEach(_emitLibrary);
 
-    // This can cause problems if it's ever true during the SDK build, as it's
-    // emitted before dart.defineLazy.
+    // Emit hoisted assert strings
+    moduleItems.insertAll(safeDeclarationIndex, _uriContainer.emit());
+
+    moduleItems.insertAll(safeDeclarationIndex, _constTableCache.emit());
+
     if (_constLazyAccessors.isNotEmpty) {
       var constTableBody = runtimeStatement(
           'defineLazy(#, { # }, false)', [_constTable, _constLazyAccessors]);
@@ -359,13 +405,6 @@
       _constLazyAccessors.clear();
     }
 
-    // Add assert locations
-    _uriMap.forEach((location, id) {
-      var value = location == null ? 'null' : js.escapedString(location);
-      moduleItems.insert(
-          _constTableInsertionIndex, js.statement('var # = #;', [id, value]));
-    });
-
     moduleItems.addAll(afterClassDefItems);
     afterClassDefItems.clear();
 
@@ -373,7 +412,9 @@
     libraries.forEach(_emitExports);
 
     // Declare imports and extension symbols
-    emitImportsAndExtensionSymbols(items);
+    emitImportsAndExtensionSymbols(items,
+        forceExtensionSymbols:
+            libraries.any((l) => allowedNativeTest(l.importUri)));
 
     // Insert a check that runs when loading this module to verify that the null
     // safety mode it was compiled in matches the mode used when compiling the
@@ -399,9 +440,8 @@
           runtimeStatement('_checkModuleNullSafetyMode(#)', [soundNullSafety]));
     }
 
-    // Discharge the type table cache variables and
-    // hoisted definitions.
-    items.addAll(_typeTable.discharge());
+    // Emit the hoisted type table cache variables
+    items.addAll(_typeTable.dischargeBoundTypes());
 
     return finishModule(items, _options.moduleName);
   }
@@ -466,6 +506,10 @@
     _currentLibrary = library;
     _staticTypeContext.enterLibrary(_currentLibrary);
 
+    if (isBuildingSdk) {
+      containerizeSymbols = _isWebLibrary(library.importUri);
+    }
+
     if (isSdkInternalRuntime(library)) {
       // `dart:_runtime` uses a different order for bootstrapping.
       //
@@ -590,10 +634,29 @@
     _classProperties =
         ClassPropertyModel.build(_types, _extensionTypes, _virtualFields, c);
 
+    var body = <js_ast.Statement>[];
+
+    // ClassPropertyModel.build introduces symbols for virtual field accessors.
+    _classProperties.virtualFields.forEach((field, virtualField) {
+      // TODO(vsm): Clean up this logic.
+      //
+      // Typically, [emitClassPrivateNameSymbol] creates a new symbol.  If it
+      // is called multiple times, that symbol is cached.  If the former,
+      // assign directly to [virtualField].  If the latter, copy the old
+      // variable to [virtualField].
+      var symbol = emitClassPrivateNameSymbol(c.enclosingLibrary,
+          getLocalClassName(c), field.name.text, virtualField);
+      if (symbol != virtualField) {
+        addSymbol(virtualField, getSymbolValue(symbol));
+        if (!containerizeSymbols) {
+          body.add(js.statement('const # = #;', [virtualField, symbol]));
+        }
+      }
+    });
+
     var jsCtors = _defineConstructors(c, className);
     var jsMethods = _emitClassMethods(c);
 
-    var body = <js_ast.Statement>[];
     _emitSuperHelperSymbols(body);
     // Deferred supertypes must be evaluated lazily while emitting classes to
     // prevent evaluating a JS expression for a deferred type from influencing
@@ -617,7 +680,6 @@
     // Attach caches on all canonicalized types.
     body.add(runtimeStatement('addTypeCaches(#)', [className]));
 
-    _emitVirtualFieldSymbols(c, body);
     _emitClassSignature(c, className, body);
     _initExtensionSymbols(c);
     if (!c.isMixinDeclaration) {
@@ -668,7 +730,7 @@
 
     var typeConstructor = js.call('(#) => { #; #; return #; }', [
       jsFormals,
-      _typeTable.discharge(formals),
+      _typeTable.dischargeFreeTypes(formals),
       body,
       className ?? _emitIdentifier(name)
     ]);
@@ -1549,7 +1611,13 @@
 
     var body = <js_ast.Statement>[];
     void emitFieldInit(Field f, Expression initializer, TreeNode hoverInfo) {
-      var access = _classProperties.virtualFields[f] ?? _declareMemberName(f);
+      var virtualField = _classProperties.virtualFields[f];
+
+      // Avoid calling getSymbol on _declareMemberName since _declareMemberName
+      // calls _emitMemberName downstream, which already invokes getSymbol.
+      var access = virtualField == null
+          ? _declareMemberName(f)
+          : getSymbol(virtualField);
       var jsInit = _visitInitializer(initializer, f.annotations);
       body.add(jsInit
           .toAssignExpression(js.call('this.#', [access])
@@ -1815,8 +1883,8 @@
     if (member.isGetter) return const [];
 
     var enclosingClass = member.enclosingClass;
-    var superMember = member.forwardingStubSuperTarget ??
-        member.forwardingStubInterfaceTarget;
+    var superMember = member.concreteForwardingStubTarget ??
+        member.abstractForwardingStubTarget;
 
     if (superMember == null) return const [];
 
@@ -1936,14 +2004,16 @@
   /// wrong behavior if a new field was declared.
   List<js_ast.Method> _emitVirtualFieldAccessor(Field field) {
     var virtualField = _classProperties.virtualFields[field];
+    var virtualFieldSymbol = getSymbol(virtualField);
     var name = _declareMemberName(field);
 
-    var getter = js.fun('function() { return this[#]; }', [virtualField]);
+    var getter = js.fun('function() { return this[#]; }', [virtualFieldSymbol]);
     var jsGetter = js_ast.Method(name, getter, isGetter: true)
       ..sourceInformation = _nodeStart(field);
 
-    var args =
-        field.isFinal ? [js_ast.Super(), name] : [js_ast.This(), virtualField];
+    var args = field.isFinal
+        ? [js_ast.Super(), name]
+        : [js_ast.This(), virtualFieldSymbol];
 
     js_ast.Expression value = _emitIdentifier('value');
     if (!field.isFinal && isCovariantField(field)) {
@@ -2259,13 +2329,13 @@
       var memberLibrary = member?.name?.library ??
           memberClass?.enclosingLibrary ??
           _currentLibrary;
-      return emitPrivateNameSymbol(memberLibrary, name);
+      return getSymbol(emitPrivateNameSymbol(memberLibrary, name));
     }
 
     useExtension ??= _isSymbolizedMember(memberClass, name);
     name = js_ast.memberNameForDartMember(name, _isExternal(member));
     if (useExtension) {
-      return getExtensionSymbolInternal(name);
+      return getSymbol(getExtensionSymbolInternal(name));
     }
     return propertyName(name);
   }
@@ -2389,7 +2459,12 @@
 
   js_ast.PropertyAccess _emitTopLevelNameNoInterop(NamedNode n,
       {String suffix = ''}) {
-    return js_ast.PropertyAccess(emitLibraryName(getLibrary(n)),
+    // Some native tests use top-level native methods.
+    var isTopLevelNative = n is Member && isNative(n);
+    return js_ast.PropertyAccess(
+        isTopLevelNative
+            ? runtimeCall('global.self')
+            : emitLibraryName(getLibrary(n)),
         _emitTopLevelMemberName(n, suffix: suffix));
   }
 
@@ -2882,7 +2957,7 @@
 
       js_ast.Expression addTypeFormalsAsParameters(
           List<js_ast.Expression> elements) {
-        var names = _typeTable.discharge(typeFormals);
+        var names = _typeTable.dischargeFreeTypes(typeFormals);
         return names.isEmpty
             ? js.call('(#) => [#]', [tf, elements])
             : js.call('(#) => {#; return [#];}', [tf, names, elements]);
@@ -3021,16 +3096,15 @@
     // original code.
     _checkParameters = false;
 
+    // Set module item containers to incremental mode.
+    setSymbolContainerIncrementalMode(true);
+    _typeTable.typeContainer.incrementalMode = true;
+
     // Emit function with additional information, such as types that are used
-    // in the expression. Note that typeTable can be null if this function is
-    // called from the expression compilation service, since we currently do
-    // not optimize for size of generated javascript in that scenario.
-    // TODO: figure whether or when optimizing for build time vs JavaScript
-    // size on expression evaluation is better.
-    // Issue: https://github.com/dart-lang/sdk/issues/43288
+    // in the expression.
     var fun = _emitFunction(functionNode, name);
 
-    var types = _typeTable.discharge();
+    var types = _typeTable.dischargeBoundTypes();
     var constants = _dischargeConstTable();
 
     var body = js_ast.Block([...?types, ...?constants, ...fun.body.statements]);
@@ -3126,22 +3200,6 @@
     return result;
   }
 
-  void _emitVirtualFieldSymbols(Class c, List<js_ast.Statement> body) {
-    _classProperties.virtualFields.forEach((field, virtualField) {
-      // TODO(vsm): Clean up this logic.  See comments on the following method.
-      //
-      // Typically, [emitClassPrivateNameSymbol] creates a new symbol.  If it
-      // is called multiple times, that symbol is cached.  If the former,
-      // assign directly to [virtualField].  If the latter, copy the old
-      // variable to [virtualField].
-      var symbol = emitClassPrivateNameSymbol(c.enclosingLibrary,
-          getLocalClassName(c), field.name.text, virtualField);
-      if (symbol != virtualField) {
-        body.add(js.statement('const # = #;', [virtualField, symbol]));
-      }
-    });
-  }
-
   List<js_ast.Identifier> _emitTypeFormals(List<TypeParameter> typeFormals) {
     return typeFormals
         .map((t) => _emitIdentifier(getTypeParameterName(t)))
@@ -3668,14 +3726,11 @@
 
   // Replace a string `uri` literal with a cached top-level variable containing
   // the value to reduce overall code size.
-  js_ast.Identifier _cacheUri(String uri) {
-    var id = _uriMap[uri];
-    if (id == null) {
-      var name = 'L${_uriMap.length}';
-      id = js_ast.TemporaryId(name);
-      _uriMap[uri] = id;
+  js_ast.Expression _cacheUri(String uri) {
+    if (!_uriContainer.contains(uri)) {
+      _uriContainer[uri] = js_ast.LiteralString('"$uri"');
     }
-    return id;
+    return _uriContainer.access(uri);
   }
 
   @override
@@ -3934,7 +3989,12 @@
         [_visitExpression(node.iterable)]);
 
     var iter = _emitTemporaryId('iter');
-    return js.statement(
+
+    var savedContinueTargets = _currentContinueTargets;
+    var savedBreakTargets = _currentBreakTargets;
+    _currentContinueTargets = <LabeledStatement>[];
+    _currentBreakTargets = <LabeledStatement>[];
+    var awaitForStmt = js.statement(
         '{'
         '  let # = #;'
         '  try {'
@@ -3952,6 +4012,9 @@
           js_ast.Yield(js.call('#.cancel()', iter))
             ..sourceInformation = _nodeStart(node.variable)
         ]);
+    _currentContinueTargets = savedContinueTargets;
+    _currentBreakTargets = savedBreakTargets;
+    return awaitForStmt;
   }
 
   @override
@@ -4306,12 +4369,40 @@
           .toAssignExpression(_emitVariableRef(node.variable));
 
   @override
+  js_ast.Expression visitDynamicGet(DynamicGet node) {
+    return _emitPropertyGet(node.receiver, null, node.name.name);
+  }
+
+  @override
+  js_ast.Expression visitInstanceGet(InstanceGet node) {
+    return _emitPropertyGet(
+        node.receiver, node.interfaceTarget, node.name.name);
+  }
+
+  @override
+  js_ast.Expression visitInstanceTearOff(InstanceTearOff node) {
+    return _emitPropertyGet(
+        node.receiver, node.interfaceTarget, node.name.name);
+  }
+
+  @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);
+  }
+
+  @override
+  js_ast.Expression visitInstanceSet(InstanceSet node) {
+    return _emitPropertySet(
+        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);
@@ -4421,6 +4512,10 @@
   js_ast.Expression visitStaticGet(StaticGet node) =>
       _emitStaticGet(node.target);
 
+  @override
+  js_ast.Expression visitStaticTearOff(StaticTearOff node) =>
+      _emitStaticGet(node.target);
+
   js_ast.Expression _emitStaticGet(Member target) {
     var result = _emitStaticTarget(target);
     if (_reifyTearoff(target)) {
@@ -4444,6 +4539,43 @@
   }
 
   @override
+  js_ast.Expression visitDynamicInvocation(DynamicInvocation node) {
+    return _emitMethodCall(node.receiver, null, node.arguments, node);
+  }
+
+  @override
+  js_ast.Expression visitFunctionInvocation(FunctionInvocation node) {
+    return _emitMethodCall(node.receiver, null, node.arguments, node);
+  }
+
+  @override
+  js_ast.Expression visitInstanceInvocation(InstanceInvocation node) {
+    return _emitMethodCall(
+        node.receiver, node.interfaceTarget, node.arguments, node);
+  }
+
+  @override
+  js_ast.Expression visitLocalFunctionInvocation(LocalFunctionInvocation node) {
+    return _emitMethodCall(
+        VariableGet(node.variable)..fileOffset = node.fileOffset,
+        null,
+        node.arguments,
+        node);
+  }
+
+  @override
+  js_ast.Expression visitEqualsCall(EqualsCall node) {
+    return _emitEqualityOperator(node.left, node.interfaceTarget, node.right,
+        negated: node.isNot);
+  }
+
+  @override
+  js_ast.Expression visitEqualsNull(EqualsNull node) {
+    return _emitCoreIdenticalCall([node.expression, NullLiteral()],
+        negated: node.isNot);
+  }
+
+  @override
   js_ast.Expression visitMethodInvocation(MethodInvocation node) {
     return _emitMethodCall(
         node.receiver, node.interfaceTarget, node.arguments, node);
@@ -4466,9 +4598,12 @@
         // The call to add is marked as invariant, so the type check on the
         // parameter to add is not needed.
         var receiver = node.receiver;
-        if (receiver is VariableGet && receiver.variable.isFinal) {
+        if (receiver is VariableGet &&
+            receiver.variable.isFinal &&
+            !receiver.variable.isLate) {
           // The receiver is a final variable, so it only contains the
-          // initializer value.
+          // initializer value. Also, avoid late variables in case the CFE
+          // lowering of late variables is changed in the future.
           if (receiver.variable.initializer is ListLiteral) {
             // The initializer is a list literal, so we know the list can be
             // grown, modified, and is represented by a JavaScript Array.
@@ -4629,16 +4764,29 @@
     // If the consumer of the expression is '==' or '!=' with a constant that
     // fits in 31 bits, adding a coercion does not change the result of the
     // comparison, e.g.  `a & ~b == 0`.
+    Expression left;
+    Expression right;
+    String op;
     if (parent is InvocationExpression &&
         parent.arguments.positional.length == 1) {
-      var op = parent.name.text;
-      var left = getInvocationReceiver(parent);
-      var right = parent.arguments.positional[0];
-      if (left != null && op == '==') {
+      op = parent.name.text;
+      left = getInvocationReceiver(parent);
+      right = parent.arguments.positional[0];
+    } else if (parent is EqualsCall) {
+      left = parent.left;
+      right = parent.right;
+      op = '==';
+    } else if (parent is EqualsNull) {
+      left = parent.expression;
+      right = NullLiteral();
+      op = '==';
+    }
+    if (left != null) {
+      if (op == '==') {
         const MAX = 0x7fffffff;
         if (_asIntInRange(right, 0, MAX) != null) return uncoerced;
         if (_asIntInRange(left, 0, MAX) != null) return uncoerced;
-      } else if (left != null && op == '>>') {
+      } else if (op == '>>') {
         if (_isDefinitelyNonNegative(left) &&
             _asIntInRange(right, 0, 31) != null) {
           // Parent will generate `# >>> n`.
@@ -4864,9 +5012,7 @@
       Expression left, Member target, Expression right,
       {bool negated = false}) {
     var targetClass = target?.enclosingClass;
-    var leftType = targetClass != null
-        ? _coreTypes.legacyRawType(targetClass)
-        : left.getStaticType(_staticTypeContext);
+    var leftType = left.getStaticType(_staticTypeContext);
 
     // Conceptually `x == y` in Dart is defined as:
     //
@@ -4996,6 +5142,21 @@
     return js_ast.PropertyAccess(js_ast.This(), jsMethod.name);
   }
 
+  /// If [e] is a [TypeLiteral] or a [TypeLiteralConstant] expression, return
+  /// the underlying [DartType], otherwise returns null.
+  // TODO(sigmund,nshahan): remove all uses of type literals in the runtime
+  // libraries, so that this pattern can be deleted.
+  DartType getTypeLiteralType(Expression e) {
+    if (e is TypeLiteral) return e.type;
+    if (e is ConstantExpression) {
+      var constant = e.constant;
+      if (constant is TypeLiteralConstant) {
+        return constant.type.withDeclaredNullability(Nullability.nonNullable);
+      }
+    }
+    return null;
+  }
+
   @override
   js_ast.Expression visitStaticInvocation(StaticInvocation node) {
     var target = node.target;
@@ -5005,18 +5166,14 @@
     // Optimize some internal SDK calls.
     if (isSdkInternalRuntime(target.enclosingLibrary)) {
       var name = target.name.text;
-      if (node.arguments.positional.isEmpty) {
-        if (name == 'typeRep') {
-          return _emitType(node.arguments.types.single);
-        }
+      if (node.arguments.positional.isEmpty &&
+          node.arguments.types.length == 1) {
+        var type = node.arguments.types.single;
+        if (name == 'typeRep') return _emitType(type);
         if (name == 'legacyTypeRep') {
-          return _emitType(node.arguments.types.single
-              .withDeclaredNullability(Nullability.legacy));
+          return _emitType(type.withDeclaredNullability(Nullability.legacy));
         }
-      } else if (node.arguments.positional.length == 1) {
-        var firstArg = node.arguments.positional[0];
-        if (name == 'getGenericClass' && firstArg is TypeLiteral) {
-          var type = firstArg.type;
+        if (name == 'getGenericClassStatic') {
           if (type is InterfaceType) {
             return _emitTopLevelNameNoInterop(type.classNode, suffix: '\$');
           }
@@ -5024,11 +5181,14 @@
             return _emitFutureOrNameNoInterop(suffix: '\$');
           }
         }
-        if (name == 'unwrapType' && firstArg is TypeLiteral) {
-          return _emitType(firstArg.type);
+      } else if (node.arguments.positional.length == 1) {
+        var firstArg = node.arguments.positional[0];
+        var type = getTypeLiteralType(firstArg);
+        if (name == 'unwrapType' && type != null) {
+          return _emitType(type);
         }
         if (name == 'extensionSymbol' && firstArg is StringLiteral) {
-          return getExtensionSymbolInternal(firstArg.value);
+          return getSymbol(getExtensionSymbolInternal(firstArg.value));
         }
 
         if (name == 'compileTimeFlag' && firstArg is StringLiteral) {
@@ -5041,19 +5201,18 @@
       } else if (node.arguments.positional.length == 2) {
         var firstArg = node.arguments.positional[0];
         var secondArg = node.arguments.positional[1];
-        if (name == '_jsInstanceOf' && secondArg is TypeLiteral) {
+        var type = getTypeLiteralType(secondArg);
+        if (name == '_jsInstanceOf' && type != null) {
           return js.call('# instanceof #', [
             _visitExpression(firstArg),
-            _emitType(
-                secondArg.type.withDeclaredNullability(Nullability.nonNullable))
+            _emitType(type.withDeclaredNullability(Nullability.nonNullable))
           ]);
         }
 
-        if (name == '_equalType' && secondArg is TypeLiteral) {
+        if (name == '_equalType' && type != null) {
           return js.call('# === #', [
             _visitExpression(firstArg),
-            _emitType(
-                secondArg.type.withDeclaredNullability(Nullability.nonNullable))
+            _emitType(type.withDeclaredNullability(Nullability.nonNullable))
           ]);
         }
       }
@@ -5799,7 +5958,10 @@
 
   @override
   js_ast.Expression visitLoadLibrary(LoadLibrary node) =>
-      runtimeCall('loadLibrary()');
+      runtimeCall('loadLibrary(#, #)', [
+        js.string(jsLibraryName(node.import.enclosingLibrary)),
+        js.string(node.import.name)
+      ]);
 
   // TODO(jmesserly): DDC loads all libraries eagerly.
   // See
@@ -5807,7 +5969,10 @@
   // https://github.com/dart-lang/sdk/issues/27777
   @override
   js_ast.Expression visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
-      js.boolean(true);
+      runtimeCall('checkDeferredIsLoaded(#, #)', [
+        js.string(jsLibraryName(node.import.enclosingLibrary)),
+        js.string(node.import.name)
+      ]);
 
   bool _reifyFunctionType(FunctionNode f) {
     if (_currentLibrary.importUri.scheme != 'dart') return true;
@@ -5874,6 +6039,26 @@
             'tearoffInterop(#)', [_emitStaticTarget(node.procedure)]);
       }
     }
+    if (node is TypeLiteralConstant) {
+      // We bypass the use of constants, since types are already canonicalized
+      // in the DDC output. DDC emits type literals in two contexts:
+      //   * Foreign JS functions: we use the non-nullable version of some types
+      //     directly in the runtime libraries (e.g. dart:_runtime). For
+      //     correctness of those libraries, we need to remove the legacy marker
+      //     that was added by the CFE normalization of type literals.
+      //
+      //   * Regular user code: we need to emit a canonicalized type. We do so
+      //     by calling `wrapType` on the type at runtime. By emitting the
+      //     non-nullable version we save some redundant work at runtime.
+      //     Technically, emitting a legacy type in this case would be correct,
+      //     only more verbose and inefficient.
+      var type = node.type;
+      if (type.nullability == Nullability.legacy) {
+        type = type.withDeclaredNullability(Nullability.nonNullable);
+      }
+      assert(!_isInForeignJS || type.nullability == Nullability.nonNullable);
+      return _emitTypeLiteral(type);
+    }
     if (isSdkInternalRuntime(_currentLibrary) || node is PrimitiveConstant) {
       return super.visitConstant(node);
     }
@@ -5883,19 +6068,19 @@
     }
     var constAliasString = 'C${constAliasCache.length}';
     var constAliasProperty = propertyName(constAliasString);
-    var constAliasId = _emitTemporaryId(constAliasString);
-    var constAccessor =
-        js.call('# || #.#', [constAliasId, _constTable, constAliasProperty]);
+
+    _constTableCache[constAliasString] = js.call('void 0');
+    var constAliasAccessor = _constTableCache.access(constAliasString);
+
+    var constAccessor = js.call(
+        '# || #.#', [constAliasAccessor, _constTable, constAliasProperty]);
     constAliasCache[node] = constAccessor;
     var constJs = super.visitConstant(node);
-    // TODO(vsm): Change back to `let`.
-    // See https://github.com/dart-lang/sdk/issues/40380.
-    moduleItems.add(js.statement('var #;', [constAliasId]));
 
     var func = js_ast.Fun(
         [],
         js_ast.Block([
-          js.statement('return # = #;', [constAliasId, constJs])
+          js.statement('return # = #;', [constAliasAccessor, constJs])
         ]));
     var accessor = js_ast.Method(constAliasProperty, func, isGetter: true);
     _constLazyAccessors.add(accessor);
@@ -5981,8 +6166,8 @@
       // was overridden.
       var symbol = cls.isEnum
           ? _emitMemberName(member.name.text, member: member)
-          : emitClassPrivateNameSymbol(
-              cls.enclosingLibrary, getLocalClassName(cls), member.name.text);
+          : getSymbol(emitClassPrivateNameSymbol(
+              cls.enclosingLibrary, getLocalClassName(cls), member.name.text));
       return js_ast.Property(symbol, constant);
     }
 
@@ -6020,6 +6205,11 @@
   @override
   js_ast.Expression visitUnevaluatedConstant(UnevaluatedConstant node) =>
       throw UnsupportedError('Encountered an unevaluated constant: $node');
+
+  @override
+  js_ast.Expression visitFunctionTearOff(FunctionTearOff node) {
+    return _emitPropertyGet(node.receiver, null, 'call');
+  }
 }
 
 bool _isInlineJSFunction(Statement body) {
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
index eb746a7..8c47904 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
@@ -15,7 +15,6 @@
 import 'package:dev_compiler/src/js_ast/js_ast.dart' as js_ast;
 import 'package:dev_compiler/src/kernel/compiler.dart';
 
-import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/api_unstable/ddc.dart';
 
 import 'package:kernel/ast.dart'
@@ -40,7 +39,7 @@
         Visitor;
 
 DiagnosticMessage _createInternalError(Uri uri, int line, int col, String msg) {
-  return Message(Code<String>('Expression Compiler Internal error', null),
+  return Message(Code<String>('Expression Compiler Internal error'),
           message: msg)
       .withLocation(uri, 0, 0)
       .withFormatting(
@@ -164,8 +163,14 @@
 
   @override
   void visitVariableDeclaration(VariableDeclaration decl) {
-    // collect locals and formals
-    _definitions[decl.name] = decl.type;
+    // Collect locals and formals appearing before current breakpoint.
+    // Note that we include variables with no offset because the offset
+    // is not set in many cases in generated code, so omitting them would
+    // make expression evaluation fail in too many cases.
+    // Issue: https://github.com/dart-lang/sdk/issues/43966
+    if (decl.fileOffset < 0 || decl.fileOffset < _offset) {
+      _definitions[decl.name] = decl.type;
+    }
     super.visitVariableDeclaration(decl);
   }
 
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 fbd7ba6..d7aa824 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -8,16 +8,16 @@
 import 'dart:convert';
 import 'dart:io';
 
-import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart';
-import 'package:_fe_analyzer_shared/src/messages/severity.dart';
 import 'package:args/args.dart';
 import 'package:build_integration/file_system/multi_root.dart';
-import 'package:front_end/src/api_prototype/compiler_options.dart';
-import 'package:front_end/src/api_prototype/experimental_flags.dart';
 import 'package:front_end/src/api_prototype/file_system.dart';
 import 'package:front_end/src/api_unstable/ddc.dart';
 import 'package:kernel/ast.dart' show Component, Library;
+import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
+import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/target/targets.dart' show TargetFlags;
+import 'package:kernel/src/tool/find_referenced_libraries.dart'
+    show duplicateLibrariesReachable;
 import 'package:meta/meta.dart';
 import 'package:vm/http_filesystem.dart';
 
@@ -28,29 +28,6 @@
 import 'expression_compiler.dart';
 import 'target.dart';
 
-/// A wrapper around asset server that redirects file read requests
-/// to http get requests to the asset server.
-class AssetFileSystem extends HttpAwareFileSystem {
-  final String server;
-  final String port;
-
-  AssetFileSystem(FileSystem original, this.server, this.port)
-      : super(original);
-
-  Uri resourceUri(Uri uri) =>
-      Uri.parse('http://$server:$port/getResource?uri=${uri.toString()}');
-
-  @override
-  FileSystemEntity entityForUri(Uri uri) {
-    if (uri.scheme == 'file') {
-      return super.entityForUri(uri);
-    }
-
-    // pass the uri to the asset server in the debugger
-    return HttpFileSystemEntity(this, resourceUri(uri));
-  }
-}
-
 /// The service that handles expression compilation requests from
 /// the debugger.
 ///
@@ -100,10 +77,9 @@
   final Stream<Map<String, dynamic>> requestStream;
   final void Function(Map<String, dynamic>) sendResponse;
 
-  final _libraryForUri = <Uri, Library>{};
-  final _componentForLibrary = <Library, Component>{};
-  final _componentForModuleName = <String, Component>{};
-  final _componentModuleNames = <Component, String>{};
+  final Map<String, Uri> _fullModules = {};
+  final ModuleCache _moduleCache = ModuleCache();
+
   final ProcessedOptions _processedOptions;
   final CompilerOptions _compilerOptions;
   final Component _sdkComponent;
@@ -163,6 +139,7 @@
 
   static List<String> errors = <String>[];
   static List<String> warnings = <String>[];
+  static List<String> infos = <String>[];
 
   /// Create the worker and load the sdk outlines.
   static Future<ExpressionCompilerWorker> create({
@@ -192,7 +169,7 @@
       ..omitPlatform = true
       ..environmentDefines = environmentDefines
       ..explicitExperimentalFlags = explicitExperimentalFlags
-      ..onDiagnostic = _onDiagnosticHandler(errors, warnings)
+      ..onDiagnostic = _onDiagnosticHandler(errors, warnings, infos)
       ..nnbdMode = soundNullSafety ? NnbdMode.Strong : NnbdMode.Weak
       ..verbose = verbose;
     requestStream ??= stdin
@@ -209,7 +186,7 @@
 
     return ExpressionCompilerWorker._(processedOptions, compilerOptions,
         sdkComponent, requestStream, sendResponse)
-      .._update(sdkComponent, dartSdkModule);
+      .._updateCache(sdkComponent, dartSdkModule, true);
   }
 
   /// Starts listening and responding to commands.
@@ -223,8 +200,8 @@
         if (command == 'Shutdown') break;
         switch (command) {
           case 'UpdateDeps':
-            sendResponse(
-                await _updateDeps(UpdateDepsRequest.fromJson(request)));
+            sendResponse(await _updateDependencies(
+                UpdateDependenciesRequest.fromJson(request)));
             break;
           case 'CompileExpression':
             sendResponse(await _compileExpression(
@@ -249,6 +226,8 @@
   Future<Map<String, dynamic>> _compileExpression(
       CompileExpressionRequest request) async {
     var libraryUri = Uri.parse(request.libraryUri);
+    var moduleName = request.moduleName;
+
     if (libraryUri.scheme == 'dart') {
       // compiling expressions inside the SDK currently fails because
       // SDK kernel outlines do not contain information that is needed
@@ -257,70 +236,115 @@
       throw Exception('Expression compilation inside SDK is not supported yet');
     }
 
-    var originalComponent = _componentForModuleName[request.moduleName];
-    if (originalComponent == null) {
-      throw ArgumentError(
-          'Unable to find library `$libraryUri`, it must be loaded first.');
-    }
-    _processedOptions.ticker.logMs(
-        'Compiling expression to JavaScript in module ${request.moduleName}');
-    var component = _sdkComponent;
+    _processedOptions.ticker
+        .logMs('Compiling expression to JavaScript in module $moduleName');
 
+    // Reset linking of libraries to the original state,
+    // so any newly loaded components are linked to the
+    // libraries in the cache.
+    _resetCacheLinks();
+
+    if (!_fullModules.containsKey(moduleName)) {
+      throw StateError('No full dill path available for $moduleName');
+    }
+
+    // Note that this doesn't actually re-load it if it's already fully loaded.
+    if (!await _loadAndUpdateComponent(
+        _fullModules[moduleName], moduleName, false)) {
+      throw ArgumentError('Failed to load full dill for module $moduleName');
+    }
+
+    var originalComponent = _moduleCache.componentForModuleName[moduleName];
+
+    var component = _sdkComponent;
     if (libraryUri.scheme != 'dart') {
+      _processedOptions.ticker.logMs('Collecting libraries for $moduleName');
+
       var libraries =
           _collectTransitiveDependencies(originalComponent, _sdkComponent);
+
+      assert(!duplicateLibrariesReachable(libraries));
+
       component = Component(
         libraries: libraries,
         nameRoot: originalComponent.root,
         uriToSource: originalComponent.uriToSource,
-      );
+      )..setMainMethodAndMode(
+          originalComponent.mainMethodName, true, originalComponent.mode);
     }
-    _processedOptions.ticker.logMs('Collected dependencies for expression');
+
+    _processedOptions.ticker.logMs('Collected libraries for $moduleName');
 
     errors.clear();
     warnings.clear();
+    infos.clear();
 
     var incrementalCompiler = IncrementalCompiler.forExpressionCompilationOnly(
         CompilerContext(_processedOptions), component, /*resetTicker*/ false);
 
-    var finalComponent =
-        await incrementalCompiler.computeDelta(entryPoints: [libraryUri]);
-    finalComponent.computeCanonicalNames();
+    var finalComponent = await incrementalCompiler
+        .computeDelta(entryPoints: [libraryUri], fullComponent: true);
+    assert(!duplicateLibrariesReachable(finalComponent.libraries));
+    assert(_canSerialize(finalComponent));
+
     _processedOptions.ticker.logMs('Computed delta for expression');
 
     if (errors.isNotEmpty) {
       return {
         'errors': errors,
         'warnings': warnings,
+        'infos': infos,
         'compiledProcedure': null,
         'succeeded': errors.isEmpty,
       };
     }
 
-    var compiler = ProgramCompiler(
+    var coreTypes = incrementalCompiler.getCoreTypes();
+    var hierarchy = incrementalCompiler.getClassHierarchy();
+
+    var kernel2jsCompiler = ProgramCompiler(
       finalComponent,
-      incrementalCompiler.getClassHierarchy(),
+      hierarchy,
       SharedCompilerOptions(
           sourceMap: true,
           summarizeApi: false,
-          moduleName: request.moduleName,
+          moduleName: moduleName,
           // Disable asserts due to failures to load source and
           // locations on kernel loaded from dill files in DDC.
           // https://github.com/dart-lang/sdk/issues/43986
           enableAsserts: false),
-      _componentForLibrary,
-      _componentModuleNames,
-      coreTypes: incrementalCompiler.getCoreTypes(),
+      _moduleCache.componentForLibrary,
+      _moduleCache.moduleNameForComponent,
+      coreTypes: coreTypes,
     );
 
-    compiler.emitModule(finalComponent);
+    assert(originalComponent.libraries.toSet().length ==
+        originalComponent.libraries.length);
+
+    // Pick the libraries from finalComponent that's also in originalComponent.
+    // This is needed because originalComponent can contain unreachable things
+    // (i.e. unreachable from the entry point used here).
+    var names = originalComponent.libraries.map((e) => e.importUri).toSet();
+    var librariesToEmit = finalComponent.libraries
+        .where((e) => names.contains(e.importUri))
+        .toList();
+    assert(_librariesAreKnown(hierarchy, librariesToEmit));
+
+    var componentToEmit = Component(
+        libraries: librariesToEmit,
+        nameRoot: finalComponent.root,
+        uriToSource: finalComponent.uriToSource)
+      ..setMainMethodAndMode(
+          originalComponent.mainMethodName, true, originalComponent.mode);
+
+    kernel2jsCompiler.emitModule(componentToEmit);
     _processedOptions.ticker.logMs('Emitted module for expression');
 
     var expressionCompiler = ExpressionCompiler(
       _compilerOptions,
       errors,
       incrementalCompiler,
-      compiler,
+      kernel2jsCompiler,
       finalComponent,
     );
 
@@ -336,49 +360,82 @@
     return {
       'errors': errors,
       'warnings': warnings,
+      'infos': infos,
       'compiledProcedure': compiledProcedure,
       'succeeded': errors.isEmpty,
     };
   }
 
+  /// Collect libraries reachable from component.
   List<Library> _collectTransitiveDependencies(
       Component component, Component sdk) {
-    var libraries = <Library>{};
-    libraries.addAll(sdk.libraries);
+    var visited = <Uri>{};
+    var libraries = <Library>[];
+    var toVisit = <Uri>[];
 
-    var toVisit = <Library>[];
-    toVisit.addAll(component.libraries);
+    toVisit.addAll(sdk.libraries.map((e) => e.importUri));
+    toVisit.addAll(component.libraries.map((e) => e.importUri));
 
     while (toVisit.isNotEmpty) {
-      var lib = toVisit.removeLast();
-      if (!libraries.contains(lib)) {
-        libraries.add(lib);
-
-        for (var dep in lib.dependencies) {
-          var uri = dep.importedLibraryReference.asLibrary.importUri;
-          var library = _libraryForUri[uri];
-          assert(library == dep.importedLibraryReference.asLibrary);
-          toVisit.add(library);
+      var uri = toVisit.removeLast();
+      if (!visited.contains(uri)) {
+        visited.add(uri);
+        if (_moduleCache.libraryForUri.containsKey(uri)) {
+          var lib = _moduleCache.libraryForUri[uri];
+          libraries.add(lib);
+          for (var dep in lib.dependencies) {
+            if (dep.importedLibraryReference.node != null) {
+              toVisit.add(dep.importedLibraryReference.asLibrary.importUri);
+            } else {
+              _processedOptions.ticker.logMs(
+                  'Missing link for ${dep.importedLibraryReference.canonicalName}'
+                  ' in ${lib.importUri}');
+            }
+          }
+        } else {
+          _processedOptions.ticker.logMs('No summary found for library: $uri');
         }
       }
     }
 
-    return libraries.toList();
+    return libraries;
   }
 
   /// Loads in the specified dill files and invalidates any existing ones.
-  Future<Map<String, dynamic>> _updateDeps(UpdateDepsRequest request) async {
+  Future<Map<String, dynamic>> _updateDependencies(
+      UpdateDependenciesRequest request) async {
     _processedOptions.ticker
         .logMs('Updating dependencies for expression evaluation');
 
     for (var input in request.inputs) {
-      var file =
-          _processedOptions.fileSystem.entityForUri(Uri.parse(input.path));
-      var bytes = await file.readAsBytes();
-      var component = await _processedOptions.loadComponent(
-          bytes, _sdkComponent.root,
-          alwaysCreateNewNamedNodes: true);
-      _update(component, input.moduleName);
+      _clearCache(input.moduleName);
+    }
+
+    // Reset linking of libraries to the original state,
+    // so any newly loaded components are linked to the
+    // libraries in the cache.
+    _resetCacheLinks();
+
+    // Load summaries and store paths for full kernel files.
+    // Note that we intentionally ignore loading failures here
+    // as not all of them are fatal. We report missing dependencies
+    // instead on expression evaluation.
+    // TODO(annagrin): throw on load failures when blaze build starts
+    // producing all summaries.
+    for (var input in request.inputs) {
+      // Support older debugger versions that do not provide summary
+      // path by loading full dill kernel instead.
+      var hasSummary = input.summaryPath != null;
+      if (!hasSummary) {
+        _processedOptions.ticker
+            .logMs('Summary path is not provided for ${input.moduleName}.'
+                ' Loading full dill instead.');
+      }
+      var summaryPath = input.summaryPath ?? input.path;
+      await _loadAndUpdateComponent(
+          Uri.parse(summaryPath), input.moduleName, hasSummary);
+
+      _fullModules[input.moduleName] = Uri.parse(input.path);
     }
 
     _processedOptions.ticker
@@ -386,34 +443,151 @@
     return {'succeeded': true};
   }
 
-  void _update(Component component, String moduleName) {
-    // do not update dart sdk
+  /// Load component and update cache.
+  Future<bool> _loadAndUpdateComponent(
+      Uri uri, String moduleName, bool isSummary) async {
+    if (isSummary && _moduleCache.isModuleLoaded(moduleName)) return true;
+    if (!isSummary && _moduleCache.isModuleFullyLoaded(moduleName)) return true;
+
+    var component = await _loadComponent(uri);
+    if (component == null) {
+      var componentKind = isSummary ? 'summary' : 'full kernel';
+      _processedOptions.ticker
+          .logMs('Failed to load $componentKind for $moduleName');
+      return false;
+    }
+    _updateCache(component, moduleName, isSummary);
+    return true;
+  }
+
+  Future<Component> _loadComponent(Uri uri) async {
+    var file = _processedOptions.fileSystem.entityForUri(uri);
+    if (await file.exists()) {
+      var bytes = await file.readAsBytes();
+      var component = _processedOptions.loadComponent(bytes, _sdkComponent.root,
+          alwaysCreateNewNamedNodes: true);
+      return component;
+    }
+    return null;
+  }
+
+  void _updateCache(Component component, String moduleName, bool isSummary) {
+    // Do not update dart sdk as we don't expect it to change.
     if (moduleName == dartSdkModule &&
-        _componentForModuleName.containsKey(moduleName)) {
+        _moduleCache.isModuleLoaded(moduleName)) {
       return;
     }
+    _moduleCache.addModule(moduleName, component, isSummary);
+  }
 
-    // cleanup old components and libraries
-    if (_componentForModuleName.containsKey(moduleName)) {
-      var oldComponent = _componentForModuleName[moduleName];
-      for (var lib in oldComponent.libraries) {
-        _componentForLibrary.remove(lib);
-        _libraryForUri.remove(lib.importUri);
-      }
-      _componentModuleNames.remove(oldComponent);
-      _componentForModuleName.remove(moduleName);
+  void _clearCache(String moduleName) {
+    // Do not remove dart sdk as we don't expect it to change.
+    if (moduleName == dartSdkModule) return;
+    _moduleCache.removeModule(moduleName);
+  }
+
+  /// Reset library links and canonical name trees.
+  void _resetCacheLinks() {
+    // Adopting children for the sdk and all already loaded components means
+    // that the root knows about all of it so anything new that is loaded will
+    // link correctly.
+    _sdkComponent.adoptChildren();
+    for (var component in _moduleCache.componentForModuleName.values) {
+      component.adoptChildren();
+    }
+  }
+
+  bool _librariesAreKnown(ClassHierarchy hierarchy, List<Library> libraries) {
+    for (var library in libraries) {
+      if (!hierarchy.knownLibraries.contains(library)) return false;
+    }
+    return true;
+  }
+
+  bool _canSerialize(Component component) {
+    var byteSink = _ByteSink();
+    var printer = BinaryPrinter(byteSink);
+    printer.writeComponentFile(component);
+    return true;
+  }
+}
+
+/// A wrapper around asset server that redirects file read requests
+/// to http get requests to the asset server.
+class AssetFileSystem extends HttpAwareFileSystem {
+  final String server;
+  final String port;
+
+  AssetFileSystem(FileSystem original, this.server, this.port)
+      : super(original);
+
+  Uri resourceUri(Uri uri) =>
+      Uri.parse('http://$server:$port/getResource?uri=${uri.toString()}');
+
+  @override
+  FileSystemEntity entityForUri(Uri uri) {
+    if (uri.scheme == 'file') {
+      return super.entityForUri(uri);
     }
 
-    // add new components and libraries
-    _componentModuleNames[component] = moduleName;
-    _componentForModuleName[moduleName] = component;
+    // Pass the uri to the asset server in the debugger.
+    return HttpFileSystemEntity(this, resourceUri(uri));
+  }
+}
+
+/// Module cache used to load modules and look up loaded libraries.
+///
+/// After each build, the cache is updated with summaries for
+/// new or updated modules. The summaries can be replaced by
+/// full dill kernel during a later expression evaluation in
+/// the corresponding module.
+class ModuleCache {
+  final Map<Uri, Library> libraryForUri = {};
+  final Map<Library, Component> componentForLibrary = {};
+  final Map<String, Component> componentForModuleName = {};
+  final Map<Component, String> moduleNameForComponent = {};
+  final Set<String> fullyLoadedModules = {};
+
+  bool isModuleLoaded(String moduleName) =>
+      componentForModuleName.containsKey(moduleName);
+
+  bool isModuleFullyLoaded(String moduleName) =>
+      fullyLoadedModules.contains(moduleName);
+
+  bool isLibraryLoaded(Library library) =>
+      componentForLibrary.containsKey(library);
+
+  void addModule(String moduleName, Component component, bool isSummary) {
+    moduleNameForComponent[component] = moduleName;
+    componentForModuleName[moduleName] = component;
+    if (!isSummary) fullyLoadedModules.add(moduleName);
+
     for (var lib in component.libraries) {
-      _componentForLibrary[lib] = component;
-      _libraryForUri[lib.importUri] = lib;
+      if (isLibraryLoaded(lib)) {
+        throw Exception('library ${lib.importUri} is already loaded in '
+            '${moduleNameForComponent[componentForLibrary[lib]]}');
+      }
+      componentForLibrary[lib] = component;
+      libraryForUri[lib.importUri] = lib;
+    }
+  }
+
+  void removeModule(String moduleName) {
+    if (isModuleLoaded(moduleName)) {
+      var oldComponent = componentForModuleName[moduleName];
+      for (var lib in oldComponent.libraries) {
+        componentForLibrary.remove(lib);
+        libraryForUri.remove(lib.importUri);
+      }
+
+      moduleNameForComponent.remove(oldComponent);
+      componentForModuleName.remove(moduleName);
+      fullyLoadedModules.remove(moduleName);
     }
   }
 }
 
+/// Expression compilation request to the expression compilation worker.
 class CompileExpressionRequest {
   final int column;
   final String expression;
@@ -445,27 +619,30 @@
       );
 }
 
-class UpdateDepsRequest {
+/// Module update request to the expression compilation worker.
+class UpdateDependenciesRequest {
   final List<InputDill> inputs;
 
-  UpdateDepsRequest(this.inputs);
+  UpdateDependenciesRequest(this.inputs);
 
-  factory UpdateDepsRequest.fromJson(Map<String, dynamic> json) =>
-      UpdateDepsRequest([
+  factory UpdateDependenciesRequest.fromJson(Map<String, dynamic> json) =>
+      UpdateDependenciesRequest([
         for (var input in json['inputs'] as List)
-          InputDill(input['path'] as String, input['moduleName'] as String),
+          InputDill(input['path'] as String, input['summaryPath'] as String,
+              input['moduleName'] as String),
       ]);
 }
 
 class InputDill {
   final String moduleName;
   final String path;
+  final String summaryPath;
 
-  InputDill(this.path, this.moduleName);
+  InputDill(this.path, this.summaryPath, this.moduleName);
 }
 
 void Function(DiagnosticMessage) _onDiagnosticHandler(
-        List<String> errors, List<String> warnings) =>
+        List<String> errors, List<String> warnings, List<String> infos) =>
     (DiagnosticMessage message) {
       switch (message.severity) {
         case Severity.error:
@@ -475,6 +652,9 @@
         case Severity.warning:
           warnings.add(message.plainTextFormatted.join('\n'));
           break;
+        case Severity.info:
+          infos.add(message.plainTextFormatted.join('\n'));
+          break;
         case Severity.context:
         case Severity.ignored:
           throw 'Unexpected severity: ${message.severity}';
@@ -498,3 +678,15 @@
 
 Uri _argToUri(String uriArg) =>
     uriArg == null ? null : Uri.base.resolve(uriArg.replaceAll('\\', '/'));
+
+class _ByteSink implements Sink<List<int>> {
+  final BytesBuilder builder = BytesBuilder();
+
+  @override
+  void add(List<int> data) {
+    builder.add(data);
+  }
+
+  @override
+  void close() {}
+}
diff --git a/pkg/dev_compiler/lib/src/kernel/js_interop.dart b/pkg/dev_compiler/lib/src/kernel/js_interop.dart
index ae20b09..65ab098 100644
--- a/pkg/dev_compiler/lib/src/kernel/js_interop.dart
+++ b/pkg/dev_compiler/lib/src/kernel/js_interop.dart
@@ -45,7 +45,9 @@
 bool isJsMember(Member member) {
   // TODO(vsm): If we ever use external outside the SDK for non-JS interop,
   // we're need to fix this.
-  return !_isLibrary(member.enclosingLibrary, ['dart:*']) && member.isExternal;
+  return !_isLibrary(member.enclosingLibrary, ['dart:*']) &&
+      member.isExternal &&
+      !isNative(member);
 }
 
 bool _annotationIsFromJSLibrary(String expectedName, Expression value) {
@@ -118,14 +120,18 @@
 
 /// Returns true iff this element is a JS interop member.
 ///
-/// The element's library must have `@JS(...)` annotation from `package:js`.
-/// If the element is a class, it must also be marked with `@JS`. Other
-/// elements, such as class members and top-level functions/accessors, should
-/// be marked `external`.
+/// JS annotations are required explicitly on classes. Other elements, such as
+/// class members and top-level functions/accessors, should be marked `external`
+/// and should have directly or indirectly a `JS` annotation. It is sufficient
+/// if the annotation is in the procedure itself or an enclosing element like
+/// the class or library.
 bool usesJSInterop(NamedNode n) {
-  var library = getLibrary(n);
-  return library != null &&
-      library.annotations.any(isPublicJSAnnotation) &&
-      (n is Procedure && n.isExternal ||
-          n is Class && n.annotations.any(isPublicJSAnnotation));
+  if (n is Member && n.isExternal) {
+    return n.enclosingLibrary.annotations.any(isPublicJSAnnotation) ||
+        n.annotations.any(isPublicJSAnnotation) ||
+        (n.enclosingClass?.annotations?.any(isPublicJSAnnotation) ?? false);
+  } else if (n is Class) {
+    return n.annotations.any(isPublicJSAnnotation);
+  }
+  return false;
 }
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 437fcce..64eb246 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -190,8 +190,20 @@
   return result;
 }
 
-Expression getInvocationReceiver(InvocationExpression node) =>
-    node is MethodInvocation ? node.receiver : null;
+Expression getInvocationReceiver(InvocationExpression node) {
+  if (node is MethodInvocation) {
+    return node.receiver;
+  } else if (node is InstanceInvocation) {
+    return node.receiver;
+  } else if (node is DynamicInvocation) {
+    return node.receiver;
+  } else if (node is FunctionInvocation) {
+    return node.receiver;
+  } else if (node is LocalFunctionInvocation) {
+    return VariableGet(node.variable);
+  }
+  return null;
+}
 
 bool isInlineJS(Member e) =>
     e is Procedure &&
@@ -341,3 +353,28 @@
       t is TypedefType ||
       t is VoidType;
 }
+
+/// Whether [member] is declared native, as in:
+///
+///    void foo() native;
+///
+/// This syntax is only allowed in sdk libraries and native tests.
+bool isNative(Member member) =>
+    // The CFE represents `native` members with the `external` bit and with an
+    // internal @ExternalName annotation as a marker.
+    member.isExternal && member.annotations.any(_isNativeMarkerAnnotation);
+
+bool _isNativeMarkerAnnotation(Expression annotation) {
+  if (annotation is ConstantExpression) {
+    var constant = annotation.constant;
+    if (constant is InstanceConstant &&
+        constant.classNode.name == 'ExternalName' &&
+        _isDartInternal(constant.classNode.enclosingLibrary.importUri)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool _isDartInternal(Uri uri) =>
+    uri.scheme == 'dart' && uri.path == '_internal';
diff --git a/pkg/dev_compiler/lib/src/kernel/module_metadata.dart b/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
index 29496ff..deca70b 100644
--- a/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
+++ b/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
@@ -29,7 +29,7 @@
   ///
   /// TODO(annagrin): create metadata package, make version the same as the
   /// metadata package version, automate updating with the package update
-  static const ModuleMetadataVersion current = ModuleMetadataVersion(1, 0, 0);
+  static const ModuleMetadataVersion current = ModuleMetadataVersion(1, 0, 1);
 
   /// Current metadata version created by the reader
   String get version => '$majorVersion.$minorVersion.$patchVersion';
@@ -126,7 +126,12 @@
 
   final Map<String, LibraryMetadata> libraries = {};
 
+  /// True if the module corresponding to this metadata was compiled with sound
+  /// null safety enabled.
+  final bool soundNullSafety;
+
   ModuleMetadata(this.name, this.closureName, this.sourceMapUri, this.moduleUri,
+      this.soundNullSafety,
       {this.version}) {
     version ??= ModuleMetadataVersion.current.version;
   }
@@ -151,7 +156,8 @@
         name = json['name'] as String,
         closureName = json['closureName'] as String,
         sourceMapUri = json['sourceMapUri'] as String,
-        moduleUri = json['moduleUri'] as String {
+        moduleUri = json['moduleUri'] as String,
+        soundNullSafety = json['soundNullSafety'] as bool {
     var fileVersion = json['version'] as String;
     if (!ModuleMetadataVersion.current.isCompatibleWith(version)) {
       throw Exception('Unsupported metadata version $fileVersion');
@@ -169,7 +175,8 @@
       'closureName': closureName,
       'sourceMapUri': sourceMapUri,
       'moduleUri': moduleUri,
-      'libraries': [for (var lib in libraries.values) lib.toJson()]
+      'libraries': [for (var lib in libraries.values) lib.toJson()],
+      'soundNullSafety': soundNullSafety
     };
   }
 }
diff --git a/pkg/dev_compiler/lib/src/kernel/native_types.dart b/pkg/dev_compiler/lib/src/kernel/native_types.dart
index 2aa3164..dd7bdc8 100644
--- a/pkg/dev_compiler/lib/src/kernel/native_types.dart
+++ b/pkg/dev_compiler/lib/src/kernel/native_types.dart
@@ -9,6 +9,7 @@
 import 'package:kernel/kernel.dart';
 import 'constants.dart';
 import 'kernel_helpers.dart';
+import 'target.dart' show allowedNativeTest;
 
 /// Contains information about native JS types (those types provided by the
 /// implementation) that are also provided by the Dart SDK.
@@ -39,7 +40,7 @@
   final _nativeTypes = HashSet<Class>.identity();
   final _pendingLibraries = HashSet<Library>.identity();
 
-  NativeTypeSet(this.coreTypes, this.constants) {
+  NativeTypeSet(this.coreTypes, this.constants, Component component) {
     // First, core types:
     // TODO(vsm): If we're analyzing against the main SDK, those
     // types are not explicitly annotated.
@@ -69,6 +70,14 @@
     _addPendingExtensionTypes(sdk.getLibrary('dart:web_audio'));
     _addPendingExtensionTypes(sdk.getLibrary('dart:web_gl'));
     _addPendingExtensionTypes(sdk.getLibrary('dart:web_sql'));
+
+    // For testing purposes only, we add extension types outside the Dart SDK.
+    // These are only allowed for native tests (see allowedNativeTest).
+    for (var library in component.libraries) {
+      if (allowedNativeTest(library.importUri)) {
+        _addExtensionTypes(library);
+      }
+    }
   }
 
   void _addExtensionType(Class c, [bool mustBeNative = false]) {
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index c8fdf12..bd952b2 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -95,9 +95,30 @@
       _getterIsNullable(node.interfaceTarget, node);
 
   @override
+  bool visitInstanceGet(InstanceGet node) =>
+      _getterIsNullable(node.interfaceTarget, node);
+
+  @override
+  bool visitDynamicGet(DynamicGet node) => _getterIsNullable(null, node);
+
+  @override
+  bool visitInstanceTearOff(InstanceTearOff node) =>
+      _getterIsNullable(node.interfaceTarget, node);
+
+  @override
+  bool visitFunctionTearOff(FunctionTearOff node) =>
+      _getterIsNullable(null, node);
+
+  @override
   bool visitPropertySet(PropertySet node) => isNullable(node.value);
 
   @override
+  bool visitInstanceSet(InstanceSet node) => isNullable(node.value);
+
+  @override
+  bool visitDynamicSet(DynamicSet node) => isNullable(node.value);
+
+  @override
   bool visitSuperPropertyGet(SuperPropertyGet node) =>
       _getterIsNullable(node.interfaceTarget, node);
 
@@ -108,6 +129,10 @@
   bool visitStaticGet(StaticGet node) => _getterIsNullable(node.target, node);
 
   @override
+  bool visitStaticTearOff(StaticTearOff node) =>
+      _getterIsNullable(node.target, node);
+
+  @override
   bool visitStaticSet(StaticSet node) => isNullable(node.value);
 
   @override
@@ -115,6 +140,29 @@
       node.interfaceTarget, node.name.text, node, node.receiver);
 
   @override
+  bool visitInstanceInvocation(InstanceInvocation node) =>
+      _invocationIsNullable(
+          node.interfaceTarget, node.name.text, node, node.receiver);
+
+  @override
+  bool visitDynamicInvocation(DynamicInvocation node) =>
+      _invocationIsNullable(null, node.name.text, node, node.receiver);
+
+  @override
+  bool visitFunctionInvocation(FunctionInvocation node) =>
+      _invocationIsNullable(null, 'call', node, node.receiver);
+
+  @override
+  bool visitLocalFunctionInvocation(LocalFunctionInvocation node) =>
+      _invocationIsNullable(null, 'call', node, VariableGet(node.variable));
+
+  @override
+  bool visitEqualsNull(EqualsNull node) => false;
+
+  @override
+  bool visitEqualsCall(EqualsCall node) => false;
+
+  @override
   bool visitSuperMethodInvocation(SuperMethodInvocation node) =>
       _invocationIsNullable(node.interfaceTarget, node.name.text, node);
 
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index ea0eade..5e403c2 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -260,7 +260,7 @@
           fieldModel.isVirtual(field) ||
           field.isCovariant ||
           field.isGenericCovariantImpl) {
-        virtualFields[field] = js_ast.TemporaryId(name);
+        virtualFields[field] = js_ast.TemporaryId(js_ast.toJSIdentifier(name));
       }
     }
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index d22ded9..ecec776 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -30,6 +30,8 @@
 
   WidgetCreatorTracker _widgetTracker;
 
+  Map<String, Class> _nativeClasses;
+
   @override
   bool get enableSuperMixins => true;
 
@@ -48,6 +50,9 @@
   bool get supportsExplicitGetterCalls => false;
 
   @override
+  bool get supportsNewMethodInvocationEncoding => true;
+
+  @override
   String get name => 'dartdevc';
 
   @override
@@ -113,9 +118,7 @@
   bool _allowedTestLibrary(Uri uri) {
     // Multi-root scheme used by modular test framework.
     if (uri.scheme == 'dev-dart-app') return true;
-
-    var scriptName = uri.path;
-    return scriptName.contains('tests/dartdevc');
+    return allowedNativeTest(uri);
   }
 
   bool _allowedDartLibrary(Uri uri) => uri.scheme == 'dart';
@@ -149,10 +152,13 @@
       ReferenceFromIndex referenceFromIndex,
       {void Function(String msg) logger,
       ChangedStructureNotifier changedStructureNotifier}) {
+    _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
     for (var library in libraries) {
       _CovarianceTransformer(library).transform();
-      JsInteropChecks(coreTypes,
-              diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>)
+      JsInteropChecks(
+              coreTypes,
+              diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
+              _nativeClasses)
           .visitLibrary(library);
     }
   }
@@ -400,14 +406,57 @@
   }
 
   @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);
+  }
+
+  @override
+  void visitInstanceTearOff(InstanceTearOff node) {
+    _checkTearoff(node.interfaceTarget);
+    super.visitInstanceTearOff(node);
+  }
+
+  @override
+  void visitEqualsCall(EqualsCall node) {
+    _checkTarget(node.left, node.interfaceTarget);
+    super.visitEqualsCall(node);
+  }
+}
+
+List<Pattern> _allowedNativeTestPatterns = [
+  'tests/dartdevc',
+  'tests/dart2js/native',
+  'tests/dart2js_2/native',
+  'tests/dart2js/internal',
+  'tests/dart2js_2/internal',
+];
+
+bool allowedNativeTest(Uri uri) {
+  var path = uri.path;
+  return _allowedNativeTestPatterns.any((pattern) => path.contains(pattern));
 }
diff --git a/pkg/dev_compiler/lib/src/kernel/type_table.dart b/pkg/dev_compiler/lib/src/kernel/type_table.dart
index ddaf27f..7154215 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_table.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_table.dart
@@ -4,13 +4,17 @@
 
 // @dart = 2.9
 
+import 'dart:collection';
+
 import 'package:kernel/kernel.dart';
 
 import '../compiler/js_names.dart' as js_ast;
+import '../compiler/module_containers.dart' show ModuleItemContainer;
 import '../js_ast/js_ast.dart' as js_ast;
 import '../js_ast/js_ast.dart' show js;
 import 'kernel_helpers.dart';
 
+/// Returns all non-locally defined type parameters referred to by [t].
 Set<TypeParameter> freeTypeParameters(DartType t) {
   assert(isKnownDartTypeImplementor(t));
   var result = <TypeParameter>{};
@@ -36,160 +40,151 @@
   return result;
 }
 
-/// _CacheTable tracks cache variables for variables that
-/// are emitted in place with a hoisted variable for a cache.
-class _CacheTable {
-  /// Mapping from types to their canonical names.
-  // Use a LinkedHashMap to maintain key insertion order so the generated code
-  // is stable under slight perturbation.  (If this is not good enough we could
-  // sort by name to canonicalize order.)
-  final _names = <DartType, js_ast.TemporaryId>{};
-  Iterable<DartType> get keys => _names.keys.toList();
-
-  js_ast.Statement _dischargeType(DartType type) {
-    var name = _names.remove(type);
-    if (name != null) {
-      return js.statement('let #;', [name]);
-    }
-    return null;
+/// A name for a type made of JS identifier safe characters.
+///
+/// 'L' and 'N' are prepended to a type name to represent a legacy or nullable
+/// flavor of a type.
+String _typeString(DartType type, {bool flat = false}) {
+  var nullability = type.declaredNullability == Nullability.legacy
+      ? 'L'
+      : type.declaredNullability == Nullability.nullable
+          ? 'N'
+          : '';
+  assert(isKnownDartTypeImplementor(type));
+  if (type is InterfaceType) {
+    var name = '${type.classNode.name}$nullability';
+    var typeArgs = type.typeArguments;
+    if (typeArgs == null) return name;
+    if (typeArgs.every((p) => p == const DynamicType())) return name;
+    return "${name}Of${typeArgs.map(_typeString).join("\$")}";
   }
-
-  /// Emit a list of statements declaring the cache variables for
-  /// types tracked by this table.  If [typeFilter] is given,
-  /// only emit the types listed in the filter.
-  List<js_ast.Statement> discharge([Iterable<DartType> typeFilter]) {
-    var decls = <js_ast.Statement>[];
-    var types = typeFilter ?? keys;
-    for (var t in types) {
-      var stmt = _dischargeType(t);
-      if (stmt != null) decls.add(stmt);
-    }
-    return decls;
+  if (type is FutureOrType) {
+    var name = 'FutureOr$nullability';
+    if (type.typeArgument == const DynamicType()) return name;
+    return '${name}Of${_typeString(type.typeArgument)}';
   }
-
-  bool isNamed(DartType type) => _names.containsKey(type);
-
-  /// A name for a type made of JS identifier safe characters.
-  ///
-  /// 'L' and 'N' are prepended to a type name to represent a legacy or nullable
-  /// flavor of a type.
-  String _typeString(DartType type, {bool flat = false}) {
-    var nullability = type.declaredNullability == Nullability.legacy
-        ? 'L'
-        : type.declaredNullability == Nullability.nullable
-            ? 'N'
-            : '';
-    assert(isKnownDartTypeImplementor(type));
-    if (type is InterfaceType) {
-      var name = '${type.classNode.name}$nullability';
-      var typeArgs = type.typeArguments;
-      if (typeArgs == null) return name;
-      if (typeArgs.every((p) => p == const DynamicType())) return name;
-      return "${name}Of${typeArgs.map(_typeString).join("\$")}";
-    }
-    if (type is FutureOrType) {
-      var name = 'FutureOr$nullability';
-      if (type.typeArgument == const DynamicType()) return name;
-      return '${name}Of${_typeString(type.typeArgument)}';
-    }
-    if (type is TypedefType) {
-      var name = '${type.typedefNode.name}$nullability';
-      var typeArgs = type.typeArguments;
-      if (typeArgs == null) return name;
-      if (typeArgs.every((p) => p == const DynamicType())) return name;
-      return "${name}Of${typeArgs.map(_typeString).join("\$")}";
-    }
-    if (type is FunctionType) {
-      if (flat) return 'Fn';
-      var rType = _typeString(type.returnType, flat: true);
-      var params = type.positionalParameters
-          .take(3)
-          .map((p) => _typeString(p, flat: true));
-      var paramList = params.join('And');
-      var count = type.positionalParameters.length;
-      if (count > 3 || type.namedParameters.isNotEmpty) {
-        paramList = '${paramList}__';
-      } else if (count == 0) {
-        paramList = 'Void';
-      }
-      return '${paramList}To$nullability$rType';
-    }
-    if (type is TypeParameterType) return '${type.parameter.name}$nullability';
-    if (type is DynamicType) return 'dynamic';
-    if (type is VoidType) return 'void';
-    if (type is NeverType) return 'Never$nullability';
-    if (type is BottomType) return 'bottom';
-    if (type is NullType) return 'Null';
-    return 'invalid';
+  if (type is TypedefType) {
+    var name = '${type.typedefNode.name}$nullability';
+    var typeArgs = type.typeArguments;
+    if (typeArgs == null) return name;
+    if (typeArgs.every((p) => p == const DynamicType())) return name;
+    return "${name}Of${typeArgs.map(_typeString).join("\$")}";
   }
-
-  /// Heuristically choose a good name for the cache and generator
-  /// variables.
-  js_ast.TemporaryId chooseTypeName(DartType type) {
-    return js_ast.TemporaryId(escapeIdentifier(_typeString(type)));
-  }
-}
-
-/// _GeneratorTable tracks types which have been
-/// named and hoisted.
-class _GeneratorTable extends _CacheTable {
-  final _defs = <DartType, js_ast.Expression>{};
-
-  final js_ast.Identifier _runtimeModule;
-
-  _GeneratorTable(this._runtimeModule);
-
-  @override
-  js_ast.Statement _dischargeType(DartType t) {
-    var name = _names.remove(t);
-    if (name != null) {
-      var init = _defs.remove(t);
-      assert(init != null);
-      // TODO(vsm): Change back to `let`.
-      // See https://github.com/dart-lang/sdk/issues/40380.
-      return js.statement('var # = () => ((# = #.constFn(#))());',
-          [name, name, _runtimeModule, init]);
+  if (type is FunctionType) {
+    if (flat) return 'Fn';
+    var rType = _typeString(type.returnType, flat: true);
+    var params = type.positionalParameters
+        .take(3)
+        .map((p) => _typeString(p, flat: true));
+    var paramList = params.join('And');
+    var count = type.positionalParameters.length;
+    if (count > 3 || type.namedParameters.isNotEmpty) {
+      paramList = '${paramList}__';
+    } else if (count == 0) {
+      paramList = 'Void';
     }
-    return null;
+    return '${paramList}To$nullability$rType';
   }
-
-  /// If [type] does not already have a generator name chosen for it,
-  /// assign it one, using [typeRep] as the initializer for it.
-  /// Emit the generator name.
-  js_ast.TemporaryId _nameType(DartType type, js_ast.Expression typeRep) {
-    var temp = _names[type];
-    if (temp == null) {
-      _names[type] = temp = chooseTypeName(type);
-      _defs[type] = typeRep;
-    }
-    return temp;
-  }
+  if (type is TypeParameterType) return '${type.parameter.name}$nullability';
+  if (type is DynamicType) return 'dynamic';
+  if (type is VoidType) return 'void';
+  if (type is NeverType) return 'Never$nullability';
+  if (type is BottomType) return 'bottom';
+  if (type is NullType) return 'Null';
+  return 'invalid';
 }
 
 class TypeTable {
-  /// Generator variable names for hoisted types.
-  final _GeneratorTable _generators;
-
   /// Mapping from type parameters to the types which must have their
   /// cache/generator variables discharged at the binding site for the
   /// type variable since the type definition depends on the type
   /// parameter.
   final _scopeDependencies = <TypeParameter, List<DartType>>{};
 
-  TypeTable(js_ast.Identifier runtime) : _generators = _GeneratorTable(runtime);
+  /// Contains types with any free type parameters and maps them to a unique
+  /// JS identifier.
+  ///
+  /// Used to reference types hoisted to the top of a generic class or generic
+  /// function (as opposed to the top of the entire module).
+  final _unboundTypeIds = HashMap<DartType, js_ast.Identifier>();
 
-  /// Emit a list of statements declaring the cache variables and generator
-  /// definitions tracked by the table.  If [formals] is present, only
-  /// emit the definitions which depend on the formals.
-  List<js_ast.Statement> discharge([List<TypeParameter> formals]) {
-    var filter = formals?.expand((p) => _scopeDependencies[p] ?? <DartType>[]);
-    var stmts = _generators.discharge(filter);
-    formals?.forEach(_scopeDependencies.remove);
-    return stmts;
+  /// Holds JS type generators keyed by their underlying DartType.
+  final typeContainer = ModuleItemContainer<DartType>.asObject('T',
+      keyToString: (DartType t) => escapeIdentifier(_typeString(t)));
+
+  final js_ast.Identifier _runtimeModule;
+
+  TypeTable(this._runtimeModule);
+
+  /// Returns true if [type] is already recorded in the table.
+  bool _isNamed(DartType type) =>
+      typeContainer.contains(type) || _unboundTypeIds.containsKey(type);
+
+  /// Emit the initializer statements for the type container, which contains
+  /// all named types with fully bound type parameters.
+  List<js_ast.Statement> dischargeBoundTypes() {
+    for (var t in typeContainer.keys) {
+      typeContainer[t] = js.call('() => ((# = #.constFn(#))())',
+          [typeContainer.access(t), _runtimeModule, typeContainer[t]]);
+    }
+    var boundTypes = typeContainer.incrementalMode
+        ? typeContainer.emitIncremental()
+        : typeContainer.emit();
+    // Bound types should only be emitted once (even across multiple evals).
+    for (var t in typeContainer.keys) {
+      typeContainer.setNoEmit(t);
+    }
+    return boundTypes;
   }
 
-  /// Record the dependencies of the type on its free variables
+  js_ast.Statement _dischargeFreeType(DartType type) {
+    typeContainer.setNoEmit(type);
+    var init = typeContainer[type];
+    var id = _unboundTypeIds[type];
+    // TODO(vsm): Change back to `let`.
+    // See https://github.com/dart-lang/sdk/issues/40380.
+    return js.statement('var # = () => ((# = #.constFn(#))());',
+        [id, id, _runtimeModule, init]);
+  }
+
+  /// Emit a list of statements declaring the cache variables and generator
+  /// definitions tracked by the table so far.
+  ///
+  /// If [formals] is present, only emit the definitions which depend on the
+  /// formals.
+  List<js_ast.Statement> dischargeFreeTypes([Iterable<TypeParameter> formals]) {
+    var decls = <js_ast.Statement>[];
+    var types = formals == null
+        ? typeContainer.keys.where((p) => freeTypeParameters(p).isNotEmpty)
+        : formals.expand((p) => _scopeDependencies[p] ?? <DartType>[]).toSet();
+
+    for (var t in types) {
+      var stmt = _dischargeFreeType(t);
+      if (stmt != null) decls.add(stmt);
+    }
+    return decls;
+  }
+
+  /// Emit a JS expression that evaluates to the generator for [type].
+  ///
+  /// If [type] does not already have a generator name chosen for it,
+  /// assign it one, using [typeRep] as its initializer.
+  js_ast.Expression _nameType(DartType type, js_ast.Expression typeRep) {
+    if (!typeContainer.contains(type)) {
+      typeContainer[type] = typeRep;
+    }
+    return _unboundTypeIds[type] ?? typeContainer.access(type);
+  }
+
+  /// Record the dependencies of the type on its free variables.
+  ///
+  /// Returns true if [type] is a free type parameter (but not a bound) and so
+  /// is not locally hoisted.
   bool recordScopeDependencies(DartType type) {
+    if (_isNamed(type)) {
+      return false;
+    }
+
     var freeVariables = freeTypeParameters(type);
     // TODO(leafp): This is a hack to avoid trying to hoist out of
     // generic functions and generic function types.  This often degrades
@@ -200,6 +195,17 @@
       return true;
     }
 
+    // This is only reached when [type] is itself a bound that depends on a
+    // free type parameter.
+    // TODO(markzipan): Bounds are locally hoisted to their own JS identifiers,
+    // but we don't do this this for other types that depend on free variables,
+    // resulting in some duplicated runtime code. We may get some performance
+    // wins if we just locally hoist everything.
+    if (freeVariables.isNotEmpty) {
+      _unboundTypeIds[type] =
+          js_ast.TemporaryId(escapeIdentifier(_typeString(type)));
+    }
+
     for (var free in freeVariables) {
       // If `free` is a promoted type parameter, get the original one so we can
       // find it in our map.
@@ -212,10 +218,10 @@
   /// add the type and its representation to the table, returning an
   /// expression which implements the type (but which caches the value).
   js_ast.Expression nameType(DartType type, js_ast.Expression typeRep) {
-    if (!_generators.isNamed(type) && recordScopeDependencies(type)) {
+    if (recordScopeDependencies(type)) {
       return typeRep;
     }
-    var name = _generators._nameType(type, typeRep);
+    var name = _nameType(type, typeRep);
     return js.call('#()', [name]);
   }
 
@@ -228,10 +234,10 @@
   js_ast.Expression nameFunctionType(
       FunctionType type, js_ast.Expression typeRep,
       {bool lazy = false}) {
-    if (!_generators.isNamed(type) && recordScopeDependencies(type)) {
+    if (recordScopeDependencies(type)) {
       return lazy ? js_ast.ArrowFun([], typeRep) : typeRep;
     }
-    var name = _generators._nameType(type, typeRep);
+    var name = _nameType(type, typeRep);
     return lazy ? name : js.call('#()', [name]);
   }
 }
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
index 1209475..108bc1e 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
@@ -10,8 +10,6 @@
 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/api_prototype/compiler_options.dart'
-    show CompilerOptions;
 import 'package:front_end/src/compute_platform_binaries_location.dart';
 import 'package:front_end/src/fasta/incremental_serializer.dart';
 import 'package:kernel/ast.dart' show Component, Library;
@@ -294,6 +292,129 @@
   group('Unsound null safety:', () {
     var options = SetupCompilerOptions(false);
 
+    group('Expression compiler scope collection tests', () {
+      var source = '''
+        ${options.dartLangComment}
+
+        class C {
+          C(int this.field);
+
+          int methodFieldAccess(int x) {
+            var inScope = 1;
+            {
+              var innerInScope = global + staticField + field;
+              /* evaluation placeholder */
+              print(innerInScope);
+              var innerNotInScope = 2;
+            }
+            var notInScope = 3;
+          }
+
+          static int staticField = 0;
+          int field;
+        }
+
+        int global = 42;
+        main() => 0;
+        ''';
+
+      TestDriver driver;
+
+      setUp(() {
+        driver = TestDriver(options, source);
+      });
+
+      tearDown(() {
+        driver.delete();
+      });
+
+      test('local in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'inScope',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return inScope;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('local in inner scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'innerInScope',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return innerInScope;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('global in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'global',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return foo.global;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('static field in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'staticField',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return foo.C.staticField;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('field in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'field',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return this.field;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('local not in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'notInScope',
+            expectedError:
+                "Error: The getter 'notInScope' isn't defined for the class 'C'.");
+      });
+
+      test('local not in inner scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'innerNotInScope',
+            expectedError:
+                "Error: The getter 'innerNotInScope' isn't defined for the class 'C'.");
+      });
+    });
+
     group('Expression compiler tests in extension method:', () {
       var source = '''
         ${options.dartLangComment}
@@ -452,14 +573,13 @@
             expression: 'main',
             expectedResult: '''
             (function(x, y, z) {
-              var VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
+              T\$Eval.VoidTodynamic = () => (T\$Eval.VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.fn(foo.main, VoidTodynamic());
+                  return C[0] = dart.fn(foo.main, T\$Eval.VoidTodynamic());
                 }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1,
               2,
@@ -1342,8 +1462,8 @@
             expression: 'baz(p as String)',
             expectedResult: '''
             (function(p) {
-              var StringL = () => (StringL = dart.constFn(dart.legacy(core.String)))();
-              return foo.baz(StringL().as(p));
+              T\$Eval.StringL = () => (T\$Eval.StringL = dart.constFn(dart.legacy(core.String)))();
+              return foo.baz(T\$Eval.StringL().as(p));
             }(
             0
             ))
@@ -1358,14 +1478,13 @@
             (function(p) {
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.const({
+                  return C[0] = dart.const({
                     __proto__: foo.MyClass.prototype,
                     [_t]: 1
                   });
                 }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1
             ))
@@ -1407,14 +1526,13 @@
             (function(p) {
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.const({
+                  return C[0] = dart.const({
                     __proto__: foo.ValueKey.prototype,
                     [value]: "t"
                     });
                   }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1
             ))
@@ -1927,11 +2045,231 @@
             expectedError: "Error: Getter not found: 'z'");
       });
     });
+
+    group('Expression compiler tests for interactions with module containers:',
+        () {
+      var source = '''
+        ${options.dartLangComment}
+        class A {
+          const A();
+        }
+        class B {
+          const B();
+        }
+        void foo() {
+          const a = A();
+          var check = a is int;
+          /* evaluation placeholder */
+          return;
+        }
+        
+        void main() => foo();
+        ''';
+
+      TestDriver driver;
+      setUp(() {
+        driver = TestDriver(options, source);
+      });
+
+      tearDown(() {
+        driver.delete();
+      });
+
+      test('evaluation that non-destructively appends to the type container',
+          () async {
+        await driver.check(
+            scope: <String, String>{'a': 'null', 'check': 'null'},
+            expression: 'a is String',
+            expectedResult: '''
+            (function(a, check) {
+              T\$Eval.StringL = () => (T\$Eval.StringL = dart.constFn(dart.legacy(core.String)))();
+              return T\$Eval.StringL().is(a);
+            }(
+              null,
+              null
+            ))
+            ''');
+      });
+
+      test('evaluation that reuses the type container', () async {
+        await driver.check(
+            scope: <String, String>{'a': 'null', 'check': 'null'},
+            expression: 'a is int',
+            expectedResult: '''
+            (function(a, check) {
+              return T\$Eval.intL().is(a);
+            }(
+              null,
+              null
+            ))
+            ''');
+      });
+
+      test(
+          'evaluation that non-destructively appends to the constant container',
+          () async {
+        await driver.check(
+            scope: <String, String>{'a': 'null', 'check': 'null'},
+            expression: 'const B()',
+            expectedResult: '''
+            (function(a, check) {
+            dart.defineLazy(CT, {
+              get C1() {
+                return C[1] = dart.const({
+                  __proto__: foo.B.prototype
+                });
+              }
+            }, false);
+            return C[1] || CT.C1;
+            }(
+              null,
+              null
+            ))
+            ''');
+      });
+
+      test('evaluation that reuses the constant container', () async {
+        await driver.check(
+            scope: <String, String>{'a': 'null', 'check': 'null'},
+            expression: 'const A()',
+            expectedResult: '''
+            (function(a, check) {
+              return C[0] || CT.C0;
+            }(
+              null,
+              null
+            ))
+            ''');
+      });
+    });
   });
 
   group('Sound null safety:', () {
     var options = SetupCompilerOptions(true);
 
+    group('Expression compiler scope collection tests', () {
+      var source = '''
+        ${options.dartLangComment}
+
+        class C {
+          C(int this.field);
+
+          int methodFieldAccess(int x) {
+            var inScope = 1;
+            {
+              var innerInScope = global + staticField + field;
+              /* evaluation placeholder */
+              print(innerInScope);
+              var innerNotInScope = 2;
+            }
+            var notInScope = 3;
+          }
+
+          static int staticField = 0;
+          int field;
+        }
+
+        int global = 42;
+        main() => 0;
+        ''';
+
+      TestDriver driver;
+
+      setUp(() {
+        driver = TestDriver(options, source);
+      });
+
+      tearDown(() {
+        driver.delete();
+      });
+
+      test('local in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'inScope',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return inScope;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('local in inner scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'innerInScope',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return innerInScope;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('global in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'global',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return foo.global;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('static field in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'staticField',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return foo.C.staticField;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('field in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'field',
+            expectedResult: '''
+            (function(inScope, innerInScope) {
+              return this.field;
+            }.bind(this)(
+              1,
+              0
+            ))
+            ''');
+      });
+
+      test('local not in scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'notInScope',
+            expectedError:
+                "Error: The getter 'notInScope' isn't defined for the class 'C'.");
+      });
+
+      test('local not in inner scope', () async {
+        await driver.check(
+            scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
+            expression: 'innerNotInScope',
+            expectedError:
+                "Error: The getter 'innerNotInScope' isn't defined for the class 'C'.");
+      });
+    });
+
     group('Expression compiler tests in extension method:', () {
       var source = '''
         ${options.dartLangComment}
@@ -2090,14 +2428,13 @@
             expression: 'main',
             expectedResult: '''
             (function(x, y, z) {
-              var VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
+              T\$Eval.VoidTodynamic = () => (T\$Eval.VoidTodynamic = dart.constFn(dart.fnType(dart.dynamic, [])))();
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.fn(foo.main, VoidTodynamic());
+                  return C[0] = dart.fn(foo.main, T\$Eval.VoidTodynamic());
                 }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1,
               2,
@@ -2995,14 +3332,13 @@
             (function(p) {
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.const({
+                  return C[0] = dart.const({
                     __proto__: foo.MyClass.prototype,
                     [_t]: 1
                   });
                 }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1
             ))
@@ -3044,14 +3380,13 @@
             (function(p) {
               dart.defineLazy(CT, {
                 get C0() {
-                  return C0 = dart.const({
+                  return C[0] = dart.const({
                     __proto__: foo.ValueKey.prototype,
                     [value]: "t"
                     });
                   }
               }, false);
-              var C0;
-              return C0 || CT.C0;
+              return C[0] || CT.C0;
             }(
               1
             ))
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 68357f8..e964f5f 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
@@ -27,6 +27,7 @@
   final String moduleName;
   final String jsFileName;
   final String fullDillFileName;
+  final String summaryDillFileName;
 
   ModuleConfiguration(
       {this.root,
@@ -34,17 +35,20 @@
       this.moduleName,
       this.libraryUri,
       this.jsFileName,
-      this.fullDillFileName});
+      this.fullDillFileName,
+      this.summaryDillFileName});
 
   Uri get jsPath => root.resolve('$outputDir/$jsFileName');
   Uri get fullDillPath => root.resolve('$outputDir/$fullDillFileName');
+  Uri get summaryDillPath => root.resolve('$outputDir/$summaryDillFileName');
 }
 
 class TestProjectConfiguration {
   final Directory rootDirectory;
   final String outputDir = 'out';
+  final bool soundNullSafety;
 
-  TestProjectConfiguration(this.rootDirectory);
+  TestProjectConfiguration(this.rootDirectory, this.soundNullSafety);
 
   ModuleConfiguration get mainModule => ModuleConfiguration(
       root: root,
@@ -52,7 +56,8 @@
       moduleName: 'packages/_testPackage/main',
       libraryUri: 'org-dartlang-app:/lib/main.dart',
       jsFileName: 'main.js',
-      fullDillFileName: 'main.full.dill');
+      fullDillFileName: 'main.full.dill',
+      summaryDillFileName: 'main.dill');
 
   ModuleConfiguration get testModule => ModuleConfiguration(
       root: root,
@@ -60,23 +65,39 @@
       moduleName: 'packages/_testPackage/test_library',
       libraryUri: 'package:_testPackage/test_library.dart',
       jsFileName: 'test_library.js',
-      fullDillFileName: 'test_library.full.dill');
+      fullDillFileName: 'test_library.full.dill',
+      summaryDillFileName: 'test_library.dill');
 
+  // TODO(annagrin): E.g. this module should have a file included that's not
+  // directly reachable from the libraryUri (i.e. where "too much" has been
+  // bundled).
   ModuleConfiguration get testModule2 => ModuleConfiguration(
       root: root,
       outputDir: outputDir,
       moduleName: 'packages/_testPackage/test_library2',
       libraryUri: 'package:_testPackage/test_library2.dart',
       jsFileName: 'test_library2.js',
-      fullDillFileName: 'test_library2.full.dill');
+      fullDillFileName: 'test_library2.full.dill',
+      summaryDillFileName: 'test_library2.dill');
+
+  ModuleConfiguration get testModule3 => ModuleConfiguration(
+      root: root,
+      outputDir: outputDir,
+      moduleName: 'packages/_testPackage/test_library3',
+      libraryUri: 'package:_testPackage/test_library3.dart',
+      jsFileName: 'test_library3.js',
+      fullDillFileName: 'test_library3.full.dill',
+      summaryDillFileName: 'test_library3.dill');
 
   String get rootPath => rootDirectory.path;
   Uri get root => rootDirectory.uri;
   Uri get outputPath => root.resolve(outputDir);
-  Uri get packagesPath => root.resolve('.packages');
+  Uri get packagesPath => root.resolve('package_config.json');
 
   Uri get sdkRoot => computePlatformBinariesLocation();
-  Uri get sdkSummaryPath => sdkRoot.resolve('ddc_sdk.dill');
+  Uri get sdkSummaryPath => soundNullSafety
+      ? sdkRoot.resolve('ddc_outline_sound.dill')
+      : sdkRoot.resolve('ddc_sdk.dill');
   Uri get librariesPath => sdkRoot.resolve('lib/libraries.json');
 
   void createTestProject() {
@@ -91,25 +112,34 @@
   sdk: '>=2.8.0 <3.0.0'
 ''');
 
-    var packages = root.resolve('.packages');
-    File.fromUri(packages)
+    File.fromUri(packagesPath)
       ..createSync()
       ..writeAsStringSync('''
-_testPackage:lib/
-''');
+      {
+        "configVersion": 2,
+        "packages": [
+          {
+            "name": "_testPackage",
+            "rootUri": "./lib",
+            "packageUri": "./"
+          }
+        ]
+      }
+      ''');
 
     var main = root.resolve('lib/main.dart');
     File.fromUri(main)
       ..createSync(recursive: true)
       ..writeAsStringSync('''
-// @dart = 2.9
+
 import 'package:_testPackage/test_library.dart';
+import 'package:_testPackage/test_library3.dart';
 
 var global = 0;
 
 void main() {
   var count = 0;
-  // line 8
+  // line 9
   print('Global is: \${++global}');
   print('Count is: \${++count}');
 
@@ -119,17 +149,22 @@
 extension NumberParsing on String {
   int parseInt() {
     var ret = int.parse(this);
-    // line 17
+    // line 19
     return ret;
   }
 }
+
+void linkToImports() {
+  testLibraryFunction(42);
+  testLibraryFunction3(42);
+}
 ''');
 
     var testLibrary = root.resolve('lib/test_library.dart');
     File.fromUri(testLibrary)
       ..createSync()
       ..writeAsStringSync('''
-// @dart = 2.9
+
 import 'package:_testPackage/test_library2.dart';
 
 int testLibraryFunction(int formal) {
@@ -137,11 +172,14 @@
 }
 
 int callLibraryFunction2(int formal) {
-  return testLibraryFunction2(formal); // line 8
+  return testLibraryFunction2(formal); // line 9
 }
 
 class B {
   C c() => new C();
+  void printNumber() {
+    print(c().getNumber() + 1);
+  }
 }
 ''');
 
@@ -149,7 +187,7 @@
     File.fromUri(testLibrary2)
       ..createSync()
       ..writeAsStringSync('''
-// @dart = 2.9
+
 int testLibraryFunction2(int formal) {
   return formal; // line 3
 }
@@ -158,241 +196,504 @@
   int getNumber() => 42;
 }
 ''');
+
+    var testLibrary3 = root.resolve('lib/test_library3.dart');
+    File.fromUri(testLibrary3)
+      ..createSync()
+      ..writeAsStringSync('''
+
+int testLibraryFunction3(int formal) {
+  return formal; // line 3
+}
+''');
   }
 }
 
 void main() async {
-  group('Expression compiler worker (webdev simulation) - ', () {
-    ExpressionCompilerWorker worker;
-    Future workerDone;
-    StreamController<Map<String, dynamic>> requestController;
-    StreamController<Map<String, dynamic>> responseController;
-    Directory tempDir;
-    TestProjectConfiguration config;
-    List inputs;
+  for (var soundNullSafety in [true, false]) {
+    group('${soundNullSafety ? "sound" : "unsound"} null safety -', () {
+      for (var summarySupport in [true, false]) {
+        group('${summarySupport ? "" : "no "}debugger summary support -', () {
+          group('expression compiler worker', () {
+            ExpressionCompilerWorker worker;
+            Future workerDone;
+            StreamController<Map<String, dynamic>> requestController;
+            StreamController<Map<String, dynamic>> responseController;
+            Directory tempDir;
+            TestProjectConfiguration config;
+            List inputs;
 
-    setUpAll(() async {
-      tempDir = Directory.systemTemp.createTempSync('foo bar');
-      config = TestProjectConfiguration(tempDir);
+            setUpAll(() async {
+              tempDir = Directory.systemTemp.createTempSync('foo bar');
+              config = TestProjectConfiguration(tempDir, soundNullSafety);
 
-      // simulate webdev
-      config.createTestProject();
-      var kernelGenerator = DDCKernelGenerator(config);
-      await kernelGenerator.generate();
+              // simulate webdev
+              config.createTestProject();
+              var kernelGenerator = DDCKernelGenerator(config);
+              await kernelGenerator.generate();
 
-      inputs = [
-        {
-          'path': config.mainModule.fullDillPath.path,
-          'moduleName': config.mainModule.moduleName
-        },
-        {
-          'path': config.testModule.fullDillPath.path,
-          'moduleName': config.testModule.moduleName
-        },
-        {
-          'path': config.testModule2.fullDillPath.path,
-          'moduleName': config.testModule2.moduleName
-        },
-      ];
+              inputs = [
+                {
+                  'path': config.mainModule.fullDillPath.path,
+                  if (summarySupport)
+                    'summaryPath': config.mainModule.summaryDillPath.path,
+                  'moduleName': config.mainModule.moduleName
+                },
+                {
+                  'path': config.testModule.fullDillPath.path,
+                  if (summarySupport)
+                    'summaryPath': config.testModule.summaryDillPath.path,
+                  'moduleName': config.testModule.moduleName
+                },
+                {
+                  'path': config.testModule2.fullDillPath.path,
+                  if (summarySupport)
+                    'summaryPath': config.testModule2.summaryDillPath.path,
+                  'moduleName': config.testModule2.moduleName
+                },
+                {
+                  'path': config.testModule3.fullDillPath.path,
+                  if (summarySupport)
+                    'summaryPath': config.testModule3.summaryDillPath.path,
+                  'moduleName': config.testModule3.moduleName
+                },
+              ];
+            });
+
+            tearDownAll(() async {
+              tempDir.deleteSync(recursive: true);
+            });
+
+            setUp(() async {
+              var fileSystem = MultiRootFileSystem('org-dartlang-app',
+                  [tempDir.uri], StandardFileSystem.instance);
+
+              requestController = StreamController<Map<String, dynamic>>();
+              responseController = StreamController<Map<String, dynamic>>();
+              worker = await ExpressionCompilerWorker.create(
+                librariesSpecificationUri: config.librariesPath,
+                // We should be able to load everything from dill and not require
+                // source parsing. Webdev and google3 integration currently rely on
+                // that. Make the test fail on source reading by not providing a
+                // packages file.
+                packagesFile: null,
+                sdkSummary: config.sdkSummaryPath,
+                fileSystem: fileSystem,
+                requestStream: requestController.stream,
+                sendResponse: responseController.add,
+                soundNullSafety: soundNullSafety,
+                verbose: verbose,
+              );
+              workerDone = worker.start();
+            });
+
+            tearDown(() async {
+              unawaited(requestController.close());
+              await workerDone;
+              unawaited(responseController.close());
+            });
+
+            test('can load dependencies and compile expressions in sdk',
+                () async {
+              requestController.add({
+                'command': 'UpdateDeps',
+                'inputs': inputs,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'other',
+                'line': 107,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'other': 'other'},
+                'libraryUri': 'dart:collection',
+                'moduleName': 'dart_sdk',
+              });
+
+              expect(
+                  responseController.stream,
+                  emitsInOrder([
+                    equals({
+                      'succeeded': true,
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return other;'),
+                    })
+                  ]));
+            }, skip: 'Evaluating expressions in SDK is not supported yet');
+
+            test('can load dependencies and compile expressions in a library',
+                () async {
+              requestController.add({
+                'command': 'UpdateDeps',
+                'inputs': inputs,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'formal',
+                'line': 5,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'formal': 'formal'},
+                'libraryUri': config.testModule.libraryUri,
+                'moduleName': config.testModule.moduleName,
+              });
+
+              expect(
+                  responseController.stream,
+                  emitsInOrder([
+                    equals({
+                      'succeeded': true,
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return formal;'),
+                    })
+                  ]));
+            });
+
+            test('can load dependencies and compile expressions in main',
+                () async {
+              requestController.add({
+                'command': 'UpdateDeps',
+                'inputs': inputs,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'count',
+                'line': 9,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'count': 'count'},
+                'libraryUri': config.mainModule.libraryUri,
+                'moduleName': config.mainModule.moduleName,
+              });
+
+              expect(
+                  responseController.stream,
+                  emitsInOrder([
+                    equals({
+                      'succeeded': true,
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return count;'),
+                    })
+                  ]));
+            });
+
+            test(
+                'can load dependencies and compile expressions in main (extension method)',
+                () async {
+              requestController.add({
+                'command': 'UpdateDeps',
+                'inputs': inputs,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'ret',
+                'line': 19,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'ret': 'ret'},
+                'libraryUri': config.mainModule.libraryUri,
+                'moduleName': config.mainModule.moduleName,
+              });
+
+              expect(
+                  responseController.stream,
+                  emitsInOrder([
+                    equals({
+                      'succeeded': true,
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return ret;'),
+                    })
+                  ]));
+            });
+
+            test(
+                'can load dependencies and compile transitive expressions in main',
+                () async {
+              requestController.add({
+                'command': 'UpdateDeps',
+                'inputs': inputs,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'B().c().getNumber()',
+                'line': 9,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {},
+                'libraryUri': config.mainModule.libraryUri,
+                'moduleName': config.mainModule.moduleName,
+              });
+
+              expect(
+                  responseController.stream,
+                  emitsInOrder([
+                    equals({
+                      'succeeded': true,
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains(
+                          'return new test_library.B.new().c().getNumber()'),
+                    })
+                  ]));
+            });
+
+            test('can compile series of expressions in various libraries',
+                () async {
+              requestController.add({
+                'command': 'UpdateDeps',
+                'inputs': inputs,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'B().c().getNumber()',
+                'line': 8,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {},
+                'libraryUri': config.mainModule.libraryUri,
+                'moduleName': config.mainModule.moduleName,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'formal',
+                'line': 5,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'formal': 'formal'},
+                'libraryUri': config.testModule.libraryUri,
+                'moduleName': config.testModule.moduleName,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'formal',
+                'line': 3,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'formal': 'formal'},
+                'libraryUri': config.testModule2.libraryUri,
+                'moduleName': config.testModule2.moduleName,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'formal',
+                'line': 3,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'formal': 'formal'},
+                'libraryUri': config.testModule3.libraryUri,
+                'moduleName': config.testModule3.moduleName,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'B().printNumber()',
+                'line': 9,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {},
+                'libraryUri': config.mainModule.libraryUri,
+                'moduleName': config.mainModule.moduleName,
+              });
+
+              expect(
+                  responseController.stream,
+                  emitsInOrder([
+                    equals({
+                      'succeeded': true,
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure':
+                          contains('new test_library.B.new().c().getNumber()'),
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return formal;'),
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return formal;'),
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return formal;'),
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure':
+                          contains('test_library.B.new().printNumber()'),
+                    })
+                  ]));
+            });
+
+            test('can compile after dependency update', () async {
+              requestController.add({
+                'command': 'UpdateDeps',
+                'inputs': inputs,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'B().c().getNumber()',
+                'line': 8,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {},
+                'libraryUri': config.mainModule.libraryUri,
+                'moduleName': config.mainModule.moduleName,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'formal',
+                'line': 5,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'formal': 'formal'},
+                'libraryUri': config.testModule.libraryUri,
+                'moduleName': config.testModule.moduleName,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'B().printNumber()',
+                'line': 9,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {},
+                'libraryUri': config.mainModule.libraryUri,
+                'moduleName': config.mainModule.moduleName,
+              });
+
+              requestController.add({
+                'command': 'UpdateDeps',
+                'inputs': inputs,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'B().c().getNumber()',
+                'line': 8,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {},
+                'libraryUri': config.mainModule.libraryUri,
+                'moduleName': config.mainModule.moduleName,
+              });
+
+              requestController.add({
+                'command': 'CompileExpression',
+                'expression': 'formal',
+                'line': 3,
+                'column': 1,
+                'jsModules': {},
+                'jsScope': {'formal': 'formal'},
+                'libraryUri': config.testModule3.libraryUri,
+                'moduleName': config.testModule3.moduleName,
+              });
+
+              expect(
+                  responseController.stream,
+                  emitsInOrder([
+                    equals({
+                      'succeeded': true,
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure':
+                          contains('new test_library.B.new().c().getNumber()'),
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return formal;'),
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure':
+                          contains('test_library.B.new().printNumber()'),
+                    }),
+                    equals({
+                      'succeeded': true,
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure':
+                          contains('new test_library.B.new().c().getNumber()'),
+                    }),
+                    equals({
+                      'succeeded': true,
+                      'errors': isEmpty,
+                      'warnings': isEmpty,
+                      'infos': isEmpty,
+                      'compiledProcedure': contains('return formal;'),
+                    }),
+                  ]));
+            });
+          });
+        });
+      }
     });
-
-    tearDownAll(() async {
-      tempDir.deleteSync(recursive: true);
-    });
-
-    setUp(() async {
-      var fileSystem = MultiRootFileSystem(
-          'org-dartlang-app', [tempDir.uri], StandardFileSystem.instance);
-
-      requestController = StreamController<Map<String, dynamic>>();
-      responseController = StreamController<Map<String, dynamic>>();
-      worker = await ExpressionCompilerWorker.create(
-        librariesSpecificationUri: config.librariesPath,
-        // We should be able to load everything from dill and not require
-        // source parsing. Webdev and google3 integration currently rely on
-        // that. Make the test fail on source reading by not providing a
-        // packages file.
-        packagesFile: null,
-        sdkSummary: config.sdkSummaryPath,
-        fileSystem: fileSystem,
-        requestStream: requestController.stream,
-        sendResponse: responseController.add,
-        verbose: verbose,
-      );
-      workerDone = worker.start();
-    });
-
-    tearDown(() async {
-      unawaited(requestController.close());
-      await workerDone;
-      unawaited(responseController.close());
-    });
-
-    test('can load dependencies and compile expressions in sdk', () async {
-      requestController.add({
-        'command': 'UpdateDeps',
-        'inputs': inputs,
-      });
-
-      requestController.add({
-        'command': 'CompileExpression',
-        'expression': 'other',
-        'line': 107,
-        'column': 1,
-        'jsModules': {},
-        'jsScope': {'other': 'other'},
-        'libraryUri': 'dart:collection',
-        'moduleName': 'dart_sdk',
-      });
-
-      expect(
-          responseController.stream,
-          emitsInOrder([
-            equals({
-              'succeeded': true,
-            }),
-            equals({
-              'succeeded': true,
-              'errors': isEmpty,
-              'warnings': isEmpty,
-              'compiledProcedure': contains('return other;'),
-            })
-          ]));
-    }, skip: 'Evaluating expressions in SDK is not supported yet');
-
-    test('can load dependencies and compile expressions in a library',
-        () async {
-      requestController.add({
-        'command': 'UpdateDeps',
-        'inputs': inputs,
-      });
-
-      requestController.add({
-        'command': 'CompileExpression',
-        'expression': 'formal',
-        'line': 5,
-        'column': 1,
-        'jsModules': {},
-        'jsScope': {'formal': 'formal'},
-        'libraryUri': config.testModule.libraryUri,
-        'moduleName': config.testModule.moduleName,
-      });
-
-      expect(
-          responseController.stream,
-          emitsInOrder([
-            equals({
-              'succeeded': true,
-            }),
-            equals({
-              'succeeded': true,
-              'errors': isEmpty,
-              'warnings': isEmpty,
-              'compiledProcedure': contains('return formal;'),
-            })
-          ]));
-    });
-
-    test('can load dependencies and compile expressions in main', () async {
-      requestController.add({
-        'command': 'UpdateDeps',
-        'inputs': inputs,
-      });
-
-      requestController.add({
-        'command': 'CompileExpression',
-        'expression': 'count',
-        'line': 8,
-        'column': 1,
-        'jsModules': {},
-        'jsScope': {'count': 'count'},
-        'libraryUri': config.mainModule.libraryUri,
-        'moduleName': config.mainModule.moduleName,
-      });
-
-      expect(
-          responseController.stream,
-          emitsInOrder([
-            equals({
-              'succeeded': true,
-            }),
-            equals({
-              'succeeded': true,
-              'errors': isEmpty,
-              'warnings': isEmpty,
-              'compiledProcedure': contains('return count;'),
-            })
-          ]));
-    });
-
-    test(
-        'can load dependencies and compile expressions in main (extension method)',
-        () async {
-      requestController.add({
-        'command': 'UpdateDeps',
-        'inputs': inputs,
-      });
-
-      requestController.add({
-        'command': 'CompileExpression',
-        'expression': 'ret',
-        'line': 17,
-        'column': 1,
-        'jsModules': {},
-        'jsScope': {'ret': 'ret'},
-        'libraryUri': config.mainModule.libraryUri,
-        'moduleName': config.mainModule.moduleName,
-      });
-
-      expect(
-          responseController.stream,
-          emitsInOrder([
-            equals({
-              'succeeded': true,
-            }),
-            equals({
-              'succeeded': true,
-              'errors': isEmpty,
-              'warnings': isEmpty,
-              'compiledProcedure': contains('return ret;'),
-            })
-          ]));
-    });
-
-    test('can load dependencies and compile transitive expressions in main',
-        () async {
-      requestController.add({
-        'command': 'UpdateDeps',
-        'inputs': inputs,
-      });
-
-      requestController.add({
-        'command': 'CompileExpression',
-        'expression': 'B().c().getNumber()',
-        'line': 8,
-        'column': 1,
-        'jsModules': {},
-        'jsScope': {},
-        'libraryUri': config.mainModule.libraryUri,
-        'moduleName': config.mainModule.moduleName,
-      });
-
-      expect(
-          responseController.stream,
-          emitsInOrder([
-            equals({
-              'succeeded': true,
-            }),
-            equals({
-              'succeeded': true,
-              'errors': isEmpty,
-              'warnings': isEmpty,
-              'compiledProcedure':
-                  contains('return new test_library.B.new().c().getNumber()'),
-            })
-          ]));
-    });
-  });
+  }
 }
 
 /// Uses DDC to generate kernel from the test code
@@ -409,11 +710,35 @@
 
     Directory.fromUri(config.outputPath)..createSync();
 
-    // generate test_library2.full.dill
+    // generate test_library3.full.dill
     var args = [
       dartdevc,
+      config.testModule3.libraryUri,
+      '-o',
+      config.testModule3.jsPath.toFilePath(),
+      '--source-map',
+      '--experimental-emit-debug-metadata',
+      '--experimental-output-compiled-kernel',
+      '--dart-sdk-summary',
+      config.sdkSummaryPath.path,
+      '--multi-root',
+      '${config.root}',
+      '--multi-root-scheme',
+      'org-dartlang-app',
+      '--packages',
+      config.packagesPath.path,
+      config.soundNullSafety ? '--sound-null-safety' : '--no-sound-null-safety'
+    ];
+
+    var exitCode = await runProcess(dart, args, config.rootPath);
+    if (exitCode != 0) {
+      return exitCode;
+    }
+
+    // generate test_library2.full.dill
+    args = [
+      dartdevc,
       config.testModule2.libraryUri,
-      '--no-summarize',
       '-o',
       config.testModule2.jsPath.toFilePath(),
       '--source-map',
@@ -427,9 +752,10 @@
       'org-dartlang-app',
       '--packages',
       config.packagesPath.path,
+      if (config.soundNullSafety) '--sound-null-safety',
     ];
 
-    var exitCode = await runProcess(dart, args, config.rootPath);
+    exitCode = await runProcess(dart, args, config.rootPath);
     if (exitCode != 0) {
       return exitCode;
     }
@@ -438,9 +764,8 @@
     args = [
       dartdevc,
       config.testModule.libraryUri,
-      '--no-summarize',
       '--summary',
-      '${config.testModule2.fullDillPath}=${config.testModule2.moduleName}',
+      '${config.testModule2.summaryDillPath}=${config.testModule2.moduleName}',
       '-o',
       config.testModule.jsPath.toFilePath(),
       '--source-map',
@@ -454,6 +779,7 @@
       'org-dartlang-app',
       '--packages',
       config.packagesPath.path,
+      if (config.soundNullSafety) '--sound-null-safety',
     ];
 
     exitCode = await runProcess(dart, args, config.rootPath);
@@ -465,11 +791,10 @@
     args = [
       dartdevc,
       config.mainModule.libraryUri,
-      '--no-summarize',
       '--summary',
-      '${config.testModule2.fullDillPath}=${config.testModule2.moduleName}',
+      '${config.testModule3.summaryDillPath}=${config.testModule3.moduleName}',
       '--summary',
-      '${config.testModule.fullDillPath}=${config.testModule.moduleName}',
+      '${config.testModule.summaryDillPath}=${config.testModule.moduleName}',
       '-o',
       config.mainModule.jsPath.toFilePath(),
       '--source-map',
@@ -482,7 +807,8 @@
       '--multi-root-scheme',
       'org-dartlang-app',
       '--packages',
-      config.packagesPath.path,
+      config.packagesPath.toFilePath(),
+      if (config.soundNullSafety) '--sound-null-safety',
     ];
 
     return await runProcess(dart, args, config.rootPath);
diff --git a/pkg/dev_compiler/test/expression_compiler/scope_offset_test.dart b/pkg/dev_compiler/test/expression_compiler/scope_offset_test.dart
index 0ee38ea..5fa3f1f 100644
--- a/pkg/dev_compiler/test/expression_compiler/scope_offset_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/scope_offset_test.dart
@@ -5,7 +5,6 @@
 // @dart = 2.9
 
 import 'package:dev_compiler/src/kernel/expression_compiler.dart';
-import 'package:front_end/src/api_prototype/standard_file_system.dart';
 import 'package:front_end/src/api_unstable/ddc.dart';
 import 'package:front_end/src/compute_platform_binaries_location.dart';
 import 'package:kernel/ast.dart';
@@ -79,7 +78,8 @@
         : (member is Procedure)
             ? member.isNoSuchMethodForwarder ||
                 member.isAbstract ||
-                member.isForwardingStub
+                member.isForwardingStub ||
+                member.stubKind == ProcedureStubKind.ConcreteMixinStub
             : (member is Field)
                 ? member.name.name.contains(redirectingName)
                 : false;
diff --git a/pkg/dev_compiler/test/module_metadata_test.dart b/pkg/dev_compiler/test/module_metadata_test.dart
index 2751e94..06054cf 100644
--- a/pkg/dev_compiler/test/module_metadata_test.dart
+++ b/pkg/dev_compiler/test/module_metadata_test.dart
@@ -114,7 +114,7 @@
 }
 
 ModuleMetadata createMetadata(String version) => ModuleMetadata(
-    'module', 'closure', 'module.map', 'module.js', version: version)
+    'module', 'closure', 'module.map', 'module.js', true, version: version)
   ..addLibrary(LibraryMetadata('library', 'package:library/test.dart',
       'file:///source/library/lib/test.dart', ['src/test2.dart']));
 
@@ -125,6 +125,7 @@
   expect(module.closureName, 'closure');
   expect(module.sourceMapUri, 'module.map');
   expect(module.moduleUri, 'module.js');
+  expect(module.soundNullSafety, true);
 
   var libUri = module.libraries.keys.first;
   var lib = module.libraries[libUri];
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index 9753c50..e077906 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -310,7 +310,7 @@
         var y = (x = null) == null;
         print(x);
         print(y);
-      }''', '1, (x = null).{dart.core::Object.==}(null), y');
+      }''', '1, (x = null) == null, y');
     });
     test('declaration from variable transitive', () async {
       await expectNotNull('''main() {
@@ -369,6 +369,7 @@
           var z = 1;
           print(z);
         }
+        f;
         f(42);
       }''', '0, void () => dart.core::print("g"), "g", g, y, 1, z, f, 42');
     });
@@ -378,6 +379,7 @@
         f(x) {
           y = x;
         }
+        f;
         f(42);
         print(y);
       }''', '0, f, 42');
diff --git a/pkg/dev_compiler/test/sourcemap/common.dart b/pkg/dev_compiler/test/sourcemap/common.dart
index 3e9564d..19972c4 100644
--- a/pkg/dev_compiler/test/sourcemap/common.dart
+++ b/pkg/dev_compiler/test/sourcemap/common.dart
@@ -4,8 +4,6 @@
 
 // @dart = 2.9
 
-import 'dart:async' show Future;
-
 import 'dart:io';
 
 import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
index 0a88bc0..ea96e19 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
@@ -4,7 +4,6 @@
 
 // @dart = 2.9
 
-import 'dart:async';
 import 'dart:io';
 
 import 'package:dev_compiler/src/kernel/command.dart';
diff --git a/pkg/dev_compiler/test/worker/worker_test.dart b/pkg/dev_compiler/test/worker/worker_test.dart
index 916f797..b03c32f 100644
--- a/pkg/dev_compiler/test/worker/worker_test.dart
+++ b/pkg/dev_compiler/test/worker/worker_test.dart
@@ -9,8 +9,6 @@
 import 'dart:io';
 
 import 'package:bazel_worker/bazel_worker.dart';
-// TODO(jakemac): Remove once this is a part of the testing library.
-import 'package:bazel_worker/src/async_message_grouper.dart';
 import 'package:bazel_worker/testing.dart';
 import 'package:path/path.dart' show dirname, join, joinAll;
 import 'package:test/test.dart';
diff --git a/pkg/dev_compiler/tool/check_nnbd_sdk.dart b/pkg/dev_compiler/tool/check_nnbd_sdk.dart
index 80ba657..c329e26 100644
--- a/pkg/dev_compiler/tool/check_nnbd_sdk.dart
+++ b/pkg/dev_compiler/tool/check_nnbd_sdk.dart
@@ -134,6 +134,12 @@
 
   // Trim temporary directory paths and sort errors.
   errors = errors.replaceAll(sdkDir, '');
+  if (!(args['keep-lines'] as bool)) {
+    // Golden files change frequenty if line numbers are recorded.
+    // We remove them by default but provide an option to show them if
+    // they can be helpful.
+    errors = errors.replaceAll(RegExp(r'\|[0-9]*\|[0-9]*\|[0-9]*\|'), '|');
+  }
   var errorList = errors.isEmpty ? <String>[] : errors.trim().split('\n');
   var count = errorList.length;
   print('$count analyzer errors.');
@@ -209,4 +215,6 @@
       allowed: ['dartdevc', 'dart2js', 'dart2js_server', 'vm', 'flutter'],
       defaultsTo: 'dartdevc')
   ..addFlag('update-golden', help: 'Update the golden file.', defaultsTo: false)
+  ..addFlag('keep-lines',
+      help: 'Show line numbers on errors.', defaultsTo: false)
   ..addFlag('help', abbr: 'h', help: 'Display this message.');
diff --git a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
index d85029a..960c5e4 100644
--- a/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dart2js_nnbd_sdk_error_golden.txt
@@ -1,12 +1,10 @@
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1706|7|5|Superinterfaces don't have a valid override for '&': JSNumber.& (num Function(num)), int.& (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1706|7|5|Superinterfaces don't have a valid override for '<<': JSNumber.<< (num Function(num)), int.<< (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1706|7|5|Superinterfaces don't have a valid override for '>>': JSNumber.>> (num Function(num)), int.>> (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1706|7|5|Superinterfaces don't have a valid override for '\|': JSNumber.\| (num Function(num)), int.\| (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|1706|7|5|Superinterfaces don't have a valid override for '^': JSNumber.^ (num Function(num)), int.^ (int Function(int)).
-ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_runtime/lib/interceptors.dart|1561|14|45|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
-ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_runtime/lib/interceptors.dart|1563|14|45|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1723|28|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1725|27|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1728|17|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1733|18|1|The operator '&' isn't defined for the type 'JSInt'.
-ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|1733|44|1|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '&': JSNumber.& (num Function(num)), int.& (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '<<': JSNumber.<< (num Function(num)), int.<< (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '>>': JSNumber.>> (num Function(num)), int.>> (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '\|': JSNumber.\| (num Function(num)), int.\| (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|INCONSISTENT_INHERITANCE|lib/_internal/js_runtime/lib/interceptors.dart|Superinterfaces don't have a valid override for '^': JSNumber.^ (num Function(num)), int.^ (int Function(int)).
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
+ERROR|COMPILE_TIME_ERROR|UNDEFINED_OPERATOR|lib/_internal/js_runtime/lib/interceptors.dart|The operator '&' isn't defined for the type 'JSInt'.
diff --git a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
index 0336282..3adfa76 100644
--- a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
+++ b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
@@ -1,11 +1,8 @@
-ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|3679|5|94|Const constructors can't throw exceptions.
-ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|7878|5|97|Const constructors can't throw exceptions.
-ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|893|5|95|Const constructors can't throw exceptions.
-ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|926|5|94|Const constructors can't throw exceptions.
-ERROR|COMPILE_TIME_ERROR|INVALID_ASSIGNMENT|lib/_internal/js_dev_runtime/private/interceptors.dart|1358|18|27|A value of type 'double' can't be assigned to a variable of type 'int'.
-ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_dev_runtime/private/interceptors.dart|1225|14|38|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
-ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_dev_runtime/private/interceptors.dart|1227|14|38|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
-ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|3677|3|5|Only redirecting factory constructors can be declared to be 'const'.
-ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|7876|3|5|Only redirecting factory constructors can be declared to be 'const'.
-ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|891|3|5|Only redirecting factory constructors can be declared to be 'const'.
-ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|924|3|5|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|Const constructors can't throw exceptions.
+ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|Const constructors can't throw exceptions.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|Only redirecting factory constructors can be declared to be 'const'.
+ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|Only redirecting factory constructors can be declared to be 'const'.
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index 023d555..a87d416 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -116,7 +116,7 @@
   var verbose = options['verbose'] as bool;
   var soundNullSafety = options['sound-null-safety'] as bool;
   var nonNullAsserts = options['null-assertions'] as bool;
-  var nativeNonNullAsserts = options['null-assertions'] as bool;
+  var nativeNonNullAsserts = options['native-null-assertions'] as bool;
   var weakNullSafetyErrors = options['weak-null-safety-errors'] as bool;
   var entry = p.canonicalize(options.rest.first);
   var out = (options['out'] as String) ?? p.setExtension(entry, '.js');
@@ -323,15 +323,6 @@
           ['--inspect=localhost:$port', nodeFile], {'NODE_PATH': nodePath});
       if (await process.exitCode != 0) exit(await process.exitCode);
     } else if (d8) {
-      // Fix SDK import.  `d8` doesn't let us set paths, so we need a full path
-      // to the SDK.
-
-      var jsFile = File(out);
-      var jsContents = jsFile.readAsStringSync();
-      jsContents = jsContents.replaceFirst(
-          "from 'dart_sdk.js'", "from '$sdkJsPath/dart_sdk.js'");
-      jsFile.writeAsStringSync(jsContents);
-
       var runjs = '''
 load("$ddcPath/lib/js/legacy/dart_library.js");
 load("$sdkJsPath/dart_sdk.js");
@@ -350,7 +341,7 @@
       var d8File = p.setExtension(out, '.d8.js');
       File(d8File).writeAsStringSync(runjs);
       var d8Binary = binary ?? p.join(dartCheckoutPath, _d8executable);
-      var process = await startProcess('D8', d8Binary, ['--module', d8File]);
+      var process = await startProcess('D8', d8Binary, [d8File]);
       if (await process.exitCode != 0) exit(await process.exitCode);
     }
   }
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index 25f50ec..d699e16 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -6,6 +6,7 @@
   exclude:
     - parser_testcases/**
     - test/analyser_ignored/**
+    - test/class_hierarchy/data/**
     - test/enable_non_nullable/data/**
     - test/extensions/data/**
     - test/id_testing/data/**
diff --git a/pkg/front_end/benchmarks/ikg/dart2js.dart b/pkg/front_end/benchmarks/ikg/dart2js.dart
index ebc4b21..3877ff2 100644
--- a/pkg/front_end/benchmarks/ikg/dart2js.dart
+++ b/pkg/front_end/benchmarks/ikg/dart2js.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.9
+
 import 'package:compiler/src/dart2js.dart' as dart2js;
 
 main(args) => dart2js.main(args);
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 4b517ca..99c4fc7 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -2,10 +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.
 
+// @dart = 2.9
+
 library front_end.compiler_options;
 
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
-    show DiagnosticMessageHandler;
+    show DiagnosticMessage, DiagnosticMessageHandler;
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
 import 'package:kernel/ast.dart' show Version;
 
@@ -189,7 +192,7 @@
   bool verify = false;
 
   /// Whether to - if verifying - skip the platform.
-  bool verifySkipPlatform = false;
+  bool skipPlatformVerification = false;
 
   /// Whether to dump generated components in a text format (also mainly for
   /// debugging).
@@ -256,6 +259,16 @@
   /// compiling the platform dill.
   bool emitDeps = true;
 
+  /// Set of invocation modes the describe how the compilation is performed.
+  ///
+  /// This used to selectively emit certain messages depending on how the
+  /// CFE is invoked. For instance to emit a message about the null safety
+  /// compilation mode when the modes includes [InvocationMode.compile].
+  Set<InvocationMode> invocationModes = {};
+
+  /// Verbosity level used for filtering emitted messages.
+  Verbosity verbosity = Verbosity.all;
+
   bool isExperimentEnabledByDefault(ExperimentalFlag flag) {
     return flags.isExperimentEnabled(flag,
         defaultExperimentFlagsForTesting: defaultExperimentFlagsForTesting);
@@ -325,7 +338,9 @@
     }
     if (!ignoreVerify) {
       if (verify != other.verify) return false;
-      if (verifySkipPlatform != other.verifySkipPlatform) return false;
+      if (skipPlatformVerification != other.skipPlatformVerification) {
+        return false;
+      }
     }
     if (!ignoreDebugDump) {
       if (debugDump != other.debugDump) return false;
@@ -344,6 +359,7 @@
     if (nnbdMode != other.nnbdMode) return false;
     if (currentSdkVersion != other.currentSdkVersion) return false;
     if (emitDeps != other.emitDeps) return false;
+    if (!equalSets(invocationModes, other.invocationModes)) return false;
 
     return true;
   }
@@ -431,3 +447,162 @@
   }
   return flags;
 }
+
+class InvocationMode {
+  /// This mode is used for when the CFE is invoked in order to compile an
+  /// executable.
+  ///
+  /// If used, a message about the null safety compilation mode will be emitted.
+  static const InvocationMode compile = const InvocationMode('compile');
+
+  final String name;
+
+  const InvocationMode(this.name);
+
+  /// Returns the set of information modes from a comma-separated list of
+  /// invocation mode names.
+  ///
+  /// If a name isn't recognized and [onError] is provided, [onError] is called
+  /// with an error messages and an empty set of invocation modes is returned.
+  ///
+  /// If a name isn't recognized and [onError] isn't provided, an error is
+  /// thrown.
+  static Set<InvocationMode> parseArguments(String arg,
+      {void Function(String) onError}) {
+    Set<InvocationMode> result = {};
+    for (String name in arg.split(',')) {
+      if (name.isNotEmpty) {
+        InvocationMode mode = fromName(name);
+        if (mode == null) {
+          String message = "Unknown invocation mode '$name'.";
+          if (onError != null) {
+            onError(message);
+          } else {
+            throw new UnsupportedError(message);
+          }
+        } else {
+          result.add(mode);
+        }
+      }
+    }
+    return result;
+  }
+
+  /// Returns the [InvocationMode] with the given [name].
+  static InvocationMode fromName(String name) {
+    for (InvocationMode invocationMode in values) {
+      if (name == invocationMode.name) {
+        return invocationMode;
+      }
+    }
+    return null;
+  }
+
+  static const List<InvocationMode> values = const [compile];
+}
+
+/// Verbosity level used for filtering messages during compilation.
+class Verbosity {
+  /// Only error messages are emitted.
+  static const Verbosity error =
+      const Verbosity('error', 'Show only error messages');
+
+  /// Error and warning messages are emitted.
+  static const Verbosity warning =
+      const Verbosity('warning', 'Show only error and warning messages');
+
+  /// Error, warning, and info messages are emitted.
+  static const Verbosity info =
+      const Verbosity('info', 'Show error, warning, and info messages');
+
+  /// All messages are emitted.
+  static const Verbosity all = const Verbosity('all', 'Show all messages');
+
+  static const List<Verbosity> values = const [error, warning, info, all];
+
+  /// Returns the names of all options.
+  static List<String> get allowedValues =>
+      [for (Verbosity value in values) value.name];
+
+  /// Returns a map from option name to option help messages.
+  static Map<String, String> get allowedValuesHelp =>
+      {for (Verbosity value in values) value.name: value.help};
+
+  /// Returns the verbosity corresponding to the given [name].
+  ///
+  /// If [name] isn't recognized and [onError] is provided, [onError] is called
+  /// with an error messages and [defaultValue] is returned.
+  ///
+  /// If [name] isn't recognized and [onError] isn't provided, an error is
+  /// thrown.
+  static Verbosity parseArgument(String name,
+      {void Function(String) onError, Verbosity defaultValue: Verbosity.all}) {
+    for (Verbosity verbosity in values) {
+      if (name == verbosity.name) {
+        return verbosity;
+      }
+    }
+    String message = "Unknown verbosity '$name'.";
+    if (onError != null) {
+      onError(message);
+      return defaultValue;
+    }
+    throw new UnsupportedError(message);
+  }
+
+  static bool shouldPrint(Verbosity verbosity, DiagnosticMessage message) {
+    Severity severity = message.severity;
+    switch (verbosity) {
+      case Verbosity.error:
+        switch (severity) {
+          case Severity.internalProblem:
+          case Severity.error:
+            return true;
+          case Severity.warning:
+          case Severity.info:
+          case Severity.context:
+          case Severity.ignored:
+            return false;
+        }
+        break;
+      case Verbosity.warning:
+        switch (severity) {
+          case Severity.internalProblem:
+          case Severity.error:
+          case Severity.warning:
+            return true;
+          case Severity.info:
+          case Severity.context:
+          case Severity.ignored:
+            return false;
+        }
+        break;
+      case Verbosity.info:
+        switch (severity) {
+          case Severity.internalProblem:
+          case Severity.error:
+          case Severity.warning:
+          case Severity.info:
+            return true;
+          case Severity.context:
+          case Severity.ignored:
+            return false;
+        }
+        break;
+      case Verbosity.all:
+        return true;
+    }
+    throw new UnsupportedError(
+        "Unsupported verbosity $verbosity and severity $severity.");
+  }
+
+  static const String defaultValue = 'all';
+
+  final String name;
+  final String help;
+
+  const Verbosity(this.name, this.help);
+
+  @override
+  String toString() => 'Verbosity($name)';
+}
diff --git a/pkg/front_end/lib/src/api_prototype/constant_evaluator.dart b/pkg/front_end/lib/src/api_prototype/constant_evaluator.dart
index 98dd0ab..5427e63 100644
--- a/pkg/front_end/lib/src/api_prototype/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/api_prototype/constant_evaluator.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.9
+
 library front_end.constant_evaluator;
 
 export '../fasta/kernel/constant_evaluator.dart'
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index d0057f7..088b517 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.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.9
+
 import 'package:kernel/kernel.dart' show Version;
 
 part 'experimental_flags_generated.dart';
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index 9be22af..dfdef38 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -1,7 +1,9 @@
-// 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.
 
+// @dart = 2.9
+
 // NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
 //
 // Instead modify 'tools/experimental_features.yaml' and run
diff --git a/pkg/front_end/lib/src/api_prototype/front_end.dart b/pkg/front_end/lib/src/api_prototype/front_end.dart
index 3830dbe..1ef9263 100644
--- a/pkg/front_end/lib/src/api_prototype/front_end.dart
+++ b/pkg/front_end/lib/src/api_prototype/front_end.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.9
+
 /// The Dart Front End contains logic to build summaries and kernel programs
 /// from Dart sources. The APIs exposed here are designed for tools in the Dart
 /// ecosystem that need to load sources and convert them to these formats.
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 e5b1bc2..1e2a446 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
@@ -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.9
+
 import 'package:_fe_analyzer_shared/src/scanner/string_scanner.dart'
     show StringScanner;
 
diff --git a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
index 27857a9..6e80dc5 100644
--- a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/kernel_generator.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.9
+
 /// Defines the front-end API for converting source code to Dart Kernel objects.
 library front_end.kernel_generator;
 
diff --git a/pkg/front_end/lib/src/api_prototype/language_version.dart b/pkg/front_end/lib/src/api_prototype/language_version.dart
index 02db78f..84b27fd 100644
--- a/pkg/front_end/lib/src/api_prototype/language_version.dart
+++ b/pkg/front_end/lib/src/api_prototype/language_version.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.9
+
 import 'dart:typed_data' show Uint8List;
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
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 28122d7..50da5f6 100644
--- a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
+++ b/pkg/front_end/lib/src/api_prototype/lowering_predicates.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.9
+
 import 'package:kernel/ast.dart';
 import '../fasta/kernel/late_lowering.dart';
 import '../fasta/source/source_extension_builder.dart' show extensionThisName;
@@ -31,6 +33,34 @@
       !node.name.text.endsWith(lateIsSetSuffix);
 }
 
+/// Returns the name of the original field for a lowered late field where
+/// [node] is the field holding the value of a lowered late field.
+///
+/// For instance
+///
+///    late int field;
+///
+/// is lowered to (simplified):
+///
+///    int? _#field = null;
+///    int get field => _#field != null ? _#field : throw 'Uninitialized';
+///    void set field(int value) {
+///      _#field = value;
+///    }
+///
+/// where '_#field' is the field holding that value and 'field' is the name of
+/// the original field.
+///
+/// This assumes that `isLateLoweredField(node)` is true.
+Name extractFieldNameFromLateLoweredField(Field node) {
+  assert(isLateLoweredField(node));
+  String prefix = lateFieldPrefix;
+  if (node.isInstanceMember) {
+    prefix = '$prefix${node.enclosingClass.name}#';
+  }
+  return new Name(node.name.text.substring(prefix.length), node.name.library);
+}
+
 /// Returns `true` if [node] is the field holding the marker for whether a
 /// lowered late field has been set or not.
 ///
@@ -58,6 +88,40 @@
       node.name.text.endsWith(lateIsSetSuffix);
 }
 
+/// Returns the name of the original field for a lowered late field where [node]
+/// is the field holding the marker for whether the lowered late field has been
+/// set or not.
+///
+/// For instance
+///
+///    late int? field;
+///
+/// is lowered to (simplified):
+///
+///    bool _#field#isSet = false;
+///    int? _#field = null;
+///    int get field => _#field#isSet ? _#field : throw 'Uninitialized';
+///    void set field(int value) {
+///      _#field = value;
+///      _#field#isSet = true;
+///    }
+///
+/// where '_#field#isSet' is the field holding the marker and 'field' is the
+/// name of the original field.
+///
+/// This assumes that `isLateLoweredIsSetField(node)` is true.
+Name extractFieldNameFromLateLoweredIsSetField(Field node) {
+  assert(isLateLoweredIsSetField(node));
+  String prefix = lateFieldPrefix;
+  if (node.isInstanceMember) {
+    prefix = '$prefix${node.enclosingClass.name}#';
+  }
+  return new Name(
+      node.name.text.substring(
+          prefix.length, node.name.text.length - lateIsSetSuffix.length),
+      node.name.library);
+}
+
 /// Returns `true` if [node] is the getter for reading the value of a lowered
 /// late field.
 ///
@@ -93,6 +157,30 @@
   return false;
 }
 
+/// Returns the name of the original field for a lowered late field where [node]
+/// is the getter for reading the value of a lowered late field.
+///
+/// For instance
+///
+///    late int field;
+///
+/// is lowered to (simplified):
+///
+///    int? _#field = null;
+///    int get field => _#field != null ? _#field : throw 'Uninitialized';
+///    void set field(int value) {
+///      _#field = value;
+///    }
+///
+/// where 'int get field' is the getter for reading the field and 'field' is the
+/// name of the original field.
+///
+/// This assumes that `isLateLoweredFieldGetter(node)` is true.
+Name extractFieldNameFromLateLoweredFieldGetter(Procedure node) {
+  assert(isLateLoweredFieldGetter(node));
+  return node.name;
+}
+
 /// Returns `true` if [node] is the setter for setting the value of a lowered
 /// late field.
 ///
@@ -128,6 +216,265 @@
   return false;
 }
 
+/// Returns the name of the original field for a lowered late field where [node]
+/// is the setter for setting the value of a lowered late field.
+///
+/// For instance
+///
+///    late int field;
+///
+/// is lowered to (simplified):
+///
+///    int? _#field = null;
+///    int get field => _#field != null ? _#field : throw 'Uninitialized';
+///    void set field(int value) {
+///      _#field = value;
+///    }
+///
+/// where 'void set field' is the setter for setting the value of the field and
+/// 'field' is the name of the original field.
+///
+/// This assumes that `isLateLoweredFieldSetter(node)` is true.
+Name extractFieldNameFromLateLoweredFieldSetter(Procedure node) {
+  assert(isLateLoweredFieldSetter(node));
+  return node.name;
+}
+
+/// Returns the original initializer of a lowered late field where [node] is
+/// either the field holding the value, the field holding the marker for whether
+/// it has been set or not, getter for reading the value, or the setter for
+/// setting the value of the field.
+///
+/// For instance
+///
+///    late int field = 42;
+///
+/// is lowered to (simplified):
+///
+///    int? _#field = null;
+///    int get field => _#field == null ? throw 'Uninitialized' : _#field = 42;
+///    void set field(int value) {
+///      _#field = value;
+///    }
+///
+/// where this original initializer is `42`, '_#field' is the field holding that
+/// value,  '_#field#isSet' is the field holding the marker, 'int get field' is
+/// the getter for reading the field, and 'void set field' is the setter for
+/// setting the value of the field.
+///
+/// If the original late field had no initializer, `null` is returned.
+///
+/// If [node] is not part of a late field lowering, `null` is returned.
+Expression getLateFieldInitializer(Member node) {
+  Procedure lateFieldGetter = _getLateFieldTarget(node);
+  if (lateFieldGetter != null) {
+    Statement body = lateFieldGetter.function.body;
+    if (body is Block &&
+        body.statements.length == 2 &&
+        body.statements.first is IfStatement) {
+      IfStatement ifStatement = body.statements.first;
+      if (ifStatement.then is Block) {
+        Block block = ifStatement.then;
+        if (block.statements.isNotEmpty &&
+            block.statements.first is ExpressionStatement) {
+          ExpressionStatement firstStatement = block.statements.first;
+          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;
+            assert(propertySet.interfaceTarget == getLateFieldTarget(node));
+            return propertySet.value;
+          } else if (firstStatement.expression is StaticSet) {
+            // We have
+            //
+            //    get field {
+            //      if (!_#isSet#field) {
+            //        _#field = <init>;
+            //        ...
+            //      }
+            //      return _#field;
+            //    }
+            //
+            // in case `<init>` is the initializer.
+            StaticSet staticSet = firstStatement.expression;
+            assert(staticSet.target == getLateFieldTarget(node));
+            return staticSet.value;
+          }
+        } else if (block.statements.isNotEmpty &&
+            block.statements.first is VariableDeclaration) {
+          // We have
+          //
+          //    get field {
+          //      if (!_#isSet#field) {
+          //        var temp = <init>;
+          //        if (_#isSet#field) throw '...'
+          //        _#field = temp;
+          //        _#isSet#field = true
+          //      }
+          //      return _#field;
+          //    }
+          //
+          // in case `<init>` is the initializer.
+          VariableDeclaration variableDeclaration = block.statements.first;
+          return variableDeclaration.initializer;
+        }
+      }
+      return null;
+    } else if (body is ReturnStatement) {
+      Expression expression = body.expression;
+      if (expression is ConditionalExpression &&
+          expression.otherwise is Throw) {
+        // We have
+        //
+        //    get field => _#field#isSet ? #field : throw ...;
+        //
+        // in which case there is no initializer.
+        return null;
+      } else if (expression is Let) {
+        Expression letBody = expression.body;
+        if (letBody is ConditionalExpression) {
+          Expression then = letBody.then;
+          if (then is Throw) {
+            // We have
+            //
+            //    get field => let # = _#field in <is-unset> ? throw ... : #;
+            //
+            // 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 StaticSet) {
+            // We have
+            //
+            //    get field => let # = this._#field in <is-unset>
+            //        ? this._#field = <init> : #;
+            //
+            // in which case `<init>` is the initializer.
+            assert(then.target == getLateFieldTarget(node));
+            return then.value;
+          } else if (then is Let && then.body is ConditionalExpression) {
+            // We have
+            //
+            //    get field => let #1 = _#field in <is-unset>
+            //        ? let #2 = <init> in ...
+            //        : #1;
+            //
+            // in which case `<init>` is the initializer.
+            return then.variable.initializer;
+          }
+        }
+      }
+    }
+    throw new UnsupportedError(
+        'Unrecognized late getter encoding for $lateFieldGetter: ${body}');
+  }
+
+  return null;
+}
+
+/// Returns getter for reading the value of a lowered late field where [node] is
+/// either the field holding the value, the field holding the marker for whether
+/// it has been set or not, getter for reading the value, or the setter for
+/// setting the value of the field.
+Procedure _getLateFieldTarget(Member node) {
+  Name lateFieldName;
+  if (node is Procedure) {
+    if (isLateLoweredFieldGetter(node)) {
+      return node;
+    } else if (isLateLoweredFieldSetter(node)) {
+      lateFieldName = extractFieldNameFromLateLoweredFieldSetter(node);
+    }
+  } else if (node is Field) {
+    if (isLateLoweredField(node)) {
+      lateFieldName = extractFieldNameFromLateLoweredField(node);
+    } else if (isLateLoweredIsSetField(node)) {
+      lateFieldName = extractFieldNameFromLateLoweredIsSetField(node);
+    }
+  }
+  if (lateFieldName != null) {
+    TreeNode parent = node.parent;
+    List<Procedure> procedures;
+    if (parent is Class) {
+      procedures = parent.procedures;
+    } else if (parent is Library) {
+      procedures = parent.procedures;
+    }
+    return procedures.singleWhere((Procedure procedure) =>
+        isLateLoweredFieldGetter(procedure) &&
+        extractFieldNameFromLateLoweredFieldGetter(procedure) == lateFieldName);
+  }
+  return null;
+}
+
+/// Returns the field holding the value for a lowered late field where [node] is
+/// either the field holding the value, the field holding the marker for whether
+/// it has been set or not, getter for reading the value, or the setter for
+/// setting the value of the field.
+///
+/// For instance
+///
+///    late int field = 42;
+///
+/// is lowered to (simplified):
+///
+///    int? _#field = null;
+///    int get field => _#field == null ? throw 'Uninitialized' : _#field = 42;
+///    void set field(int value) {
+///      _#field = value;
+///    }
+///
+/// where '_#field' is the field holding that value,  '_#field#isSet' is the
+/// field holding the marker, 'int get field' is the getter for reading the
+/// field, and 'void set field' is the setter for setting the value of the
+/// field.
+///
+/// If [node] is not part of a late field lowering, `null` is returned.
+Field getLateFieldTarget(Member node) {
+  Name lateFieldName;
+  if (node is Procedure) {
+    if (isLateLoweredFieldGetter(node)) {
+      lateFieldName = extractFieldNameFromLateLoweredFieldGetter(node);
+    } else if (isLateLoweredFieldSetter(node)) {
+      lateFieldName = extractFieldNameFromLateLoweredFieldSetter(node);
+    }
+  } else if (node is Field) {
+    if (isLateLoweredField(node)) {
+      return node;
+    } else if (isLateLoweredIsSetField(node)) {
+      lateFieldName = extractFieldNameFromLateLoweredIsSetField(node);
+    }
+  }
+  if (lateFieldName != null) {
+    TreeNode parent = node.parent;
+    List<Field> fields;
+    if (parent is Class) {
+      fields = parent.fields;
+    } else if (parent is Library) {
+      fields = parent.fields;
+    }
+    return fields.singleWhere((Field field) =>
+        isLateLoweredField(field) &&
+        extractFieldNameFromLateLoweredField(field) == lateFieldName);
+  }
+  return null;
+}
+
 /// Returns `true` if [node] is the local variable holding the value of a
 /// lowered late variable.
 ///
diff --git a/pkg/front_end/lib/src/api_prototype/memory_file_system.dart b/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
index e077d8d..194393b 100644
--- a/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
+++ b/pkg/front_end/lib/src/api_prototype/memory_file_system.dart
@@ -87,7 +87,7 @@
 
   @override
   Future<List<int>> readAsBytes() async {
-    Uint8List contents = _fileSystem._files[uri];
+    Uint8List? contents = _fileSystem._files[uri];
     if (contents == null) {
       throw new FileSystemException(uri, 'File $uri does not exist.');
     }
diff --git a/pkg/front_end/lib/src/api_prototype/standard_file_system.dart b/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
index a8bbc0b..bc1a4bc 100644
--- a/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
+++ b/pkg/front_end/lib/src/api_prototype/standard_file_system.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.9
+
 library front_end.standard_file_system;
 
 import 'dart:io' as io;
diff --git a/pkg/front_end/lib/src/api_prototype/summary_generator.dart b/pkg/front_end/lib/src/api_prototype/summary_generator.dart
index d579536..0492289 100644
--- a/pkg/front_end/lib/src/api_prototype/summary_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/summary_generator.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.9
+
 /// Defines the front-end API for converting source code to summaries.
 library front_end.summary_generator;
 
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 48df5c9..9cfd890 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.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.9
+
 /// API needed by `utils/front_end/summary_worker.dart`, a tool used to compute
 /// summaries in build systems like bazel, pub-build, and package-build.
 
diff --git a/pkg/front_end/lib/src/api_unstable/compiler_state.dart b/pkg/front_end/lib/src/api_unstable/compiler_state.dart
index 9baa0b7..97779f8 100644
--- a/pkg/front_end/lib/src/api_unstable/compiler_state.dart
+++ b/pkg/front_end/lib/src/api_unstable/compiler_state.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.9
+
 import '../api_prototype/compiler_options.dart' show CompilerOptions;
 
 import '../base/processed_options.dart' show ProcessedOptions;
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index d7fba2e..c9fbb930 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.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.9
+
 import 'package:_fe_analyzer_shared/src/messages/codes.dart'
     show messageMissingMain;
 
@@ -18,7 +20,8 @@
 
 import 'package:kernel/target/targets.dart' show Target;
 
-import '../api_prototype/compiler_options.dart' show CompilerOptions;
+import '../api_prototype/compiler_options.dart'
+    show CompilerOptions, InvocationMode, Verbosity;
 
 import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
 
@@ -40,7 +43,7 @@
 
 import 'compiler_state.dart' show InitializedCompilerState;
 
-import 'util.dart' show equalLists, equalMaps;
+import 'util.dart' show equalLists, equalMaps, equalSets;
 
 export 'package:_fe_analyzer_shared/src/messages/codes.dart'
     show LocatedMessage;
@@ -97,7 +100,12 @@
     show relativizeUri;
 
 export '../api_prototype/compiler_options.dart'
-    show CompilerOptions, parseExperimentalFlags, parseExperimentalArguments;
+    show
+        CompilerOptions,
+        InvocationMode,
+        Verbosity,
+        parseExperimentalFlags,
+        parseExperimentalArguments;
 
 export '../api_prototype/experimental_flags.dart'
     show defaultExperimentalFlags, ExperimentalFlag, isExperimentEnabled;
@@ -138,7 +146,9 @@
     Uri packagesFileUri,
     {Map<ExperimentalFlag, bool> explicitExperimentalFlags,
     bool verify: false,
-    NnbdMode nnbdMode}) {
+    NnbdMode nnbdMode,
+    Set<InvocationMode> invocationModes: const <InvocationMode>{},
+    Verbosity verbosity: Verbosity.all}) {
   additionalDills.sort((a, b) => a.toString().compareTo(b.toString()));
 
   // We don't check `target` because it doesn't support '==' and each
@@ -151,7 +161,9 @@
       equalMaps(oldState.options.explicitExperimentalFlags,
           explicitExperimentalFlags) &&
       oldState.options.verify == verify &&
-      oldState.options.nnbdMode == nnbdMode) {
+      oldState.options.nnbdMode == nnbdMode &&
+      equalSets(oldState.options.invocationModes, invocationModes) &&
+      oldState.options.verbosity == verbosity) {
     return oldState;
   }
 
@@ -161,7 +173,9 @@
     ..librariesSpecificationUri = librariesSpecificationUri
     ..packagesFileUri = packagesFileUri
     ..explicitExperimentalFlags = explicitExperimentalFlags
-    ..verify = verify;
+    ..verify = verify
+    ..invocationModes = invocationModes
+    ..verbosity = verbosity;
   if (nnbdMode != null) options.nnbdMode = nnbdMode;
 
   ProcessedOptions processedOpts = new ProcessedOptions(options: options);
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index b28384f..c3de146 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.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.9
+
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessageHandler;
 
diff --git a/pkg/front_end/lib/src/api_unstable/modular_incremental_compilation.dart b/pkg/front_end/lib/src/api_unstable/modular_incremental_compilation.dart
index eb80f97..7086aad 100644
--- a/pkg/front_end/lib/src/api_unstable/modular_incremental_compilation.dart
+++ b/pkg/front_end/lib/src/api_unstable/modular_incremental_compilation.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.9
+
 import 'package:kernel/kernel.dart' show Component, CanonicalName, Library;
 
 import 'package:kernel/target/targets.dart' show Target;
diff --git a/pkg/front_end/lib/src/api_unstable/util.dart b/pkg/front_end/lib/src/api_unstable/util.dart
index cc5f7fc..2200eff 100644
--- a/pkg/front_end/lib/src/api_unstable/util.dart
+++ b/pkg/front_end/lib/src/api_unstable/util.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.
 
-bool equalLists<T>(List<T> a, List<T> b) {
+bool equalLists<T>(List<T>? a, List<T>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   if (a.length != b.length) return false;
@@ -12,7 +12,7 @@
   return true;
 }
 
-bool equalSets<K>(Set<K> a, Set<K> b) {
+bool equalSets<K>(Set<K>? a, Set<K>? b) {
   if (identical(a, b)) return true;
   if (a == null || b == null) return false;
   if (a.length != b.length) return false;
@@ -22,7 +22,7 @@
   return true;
 }
 
-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;
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index e0970d7..9bfeea8 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -2,13 +2,20 @@
 // for 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
+
 export 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessage, DiagnosticMessageHandler, getMessageUri;
 
 export 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
 export '../api_prototype/compiler_options.dart'
-    show CompilerOptions, parseExperimentalArguments, parseExperimentalFlags;
+    show
+        CompilerOptions,
+        InvocationMode,
+        Verbosity,
+        parseExperimentalArguments,
+        parseExperimentalFlags;
 
 export '../api_prototype/experimental_flags.dart'
     show defaultExperimentalFlags, ExperimentalFlag;
@@ -47,12 +54,16 @@
         messageFfiExpectedConstant,
         noLength,
         templateFfiDartTypeMismatch,
+        templateFfiEmptyStruct,
+        templateFfiEmptyStructWarning,
         templateFfiExpectedExceptionalReturn,
         templateFfiExpectedNoExceptionalReturn,
         templateFfiExtendsOrImplementsSealedClass,
         templateFfiFieldAnnotation,
+        templateFfiFieldCyclic,
         templateFfiFieldInitializer,
         templateFfiFieldNoAnnotation,
+        templateFfiNonConstantTypeArgumentWarning,
         templateFfiNotStatic,
         templateFfiStructGeneric,
         templateFfiTypeInvalid,
diff --git a/pkg/front_end/lib/src/base/command_line_options.dart b/pkg/front_end/lib/src/base/command_line_options.dart
index a87824f..4d8ef80 100644
--- a/pkg/front_end/lib/src/base/command_line_options.dart
+++ b/pkg/front_end/lib/src/base/command_line_options.dart
@@ -38,7 +38,10 @@
   static const String singleRootBase = "--single-root-base";
   static const String singleRootScheme = "--single-root-scheme";
   static const String verbose = "--verbose";
+  static const String verbosity = "--verbosity";
   static const String verify = "--verify";
-  static const String verifySkipPlatform = "--verify-skip-platform";
+  static const String skipPlatformVerification = "--skip-platform-verification";
   static const String warnOnReachabilityCheck = "--warn-on-reachability-check";
+
+  static const String invocationModes = "--invocation-modes";
 }
diff --git a/pkg/front_end/lib/src/base/instrumentation.dart b/pkg/front_end/lib/src/base/instrumentation.dart
index 8cf7170..24876a6 100644
--- a/pkg/front_end/lib/src/base/instrumentation.dart
+++ b/pkg/front_end/lib/src/base/instrumentation.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.9
+
 import 'package:kernel/ast.dart' show DartType, Member;
 import 'package:kernel/src/text_util.dart';
 
diff --git a/pkg/front_end/lib/src/base/libraries_specification.dart b/pkg/front_end/lib/src/base/libraries_specification.dart
index 52a18dc..61f0028 100644
--- a/pkg/front_end/lib/src/base/libraries_specification.dart
+++ b/pkg/front_end/lib/src/base/libraries_specification.dart
@@ -106,7 +106,7 @@
   /// The library specification for a given [target], or throws if none is
   /// available.
   TargetLibrariesSpecification specificationFor(String target) {
-    TargetLibrariesSpecification targetSpec = _targets[target];
+    TargetLibrariesSpecification? targetSpec = _targets[target];
     if (targetSpec == null) {
       throw new LibrariesSpecificationException(
           'No library specification for target "$target"');
@@ -119,15 +119,15 @@
   ///
   /// May throw an exception if [json] is not properly formatted or contains
   /// invalid values.
-  static LibrariesSpecification parse(Uri baseUri, String json) {
+  static LibrariesSpecification parse(Uri baseUri, String? json) {
     if (json == null) return const LibrariesSpecification();
     Map<String, dynamic> jsonData;
     try {
       dynamic data = jsonDecode(json);
-      if (data is! Map) {
+      if (data is! Map<String, dynamic>) {
         return _reportError('top-level specification is not a map');
       }
-      jsonData = data as Map;
+      jsonData = data;
     } on FormatException catch (e) {
       throw new LibrariesSpecificationException(e);
     }
@@ -145,11 +145,11 @@
             "for '$targetName' doesn't have a libraries entry");
       }
       dynamic librariesData = targetData["libraries"];
-      if (librariesData is! Map) {
+      if (librariesData is! Map<String, dynamic>) {
         return _reportError("libraries entry for '$targetName' is not a map");
       }
       librariesData.forEach((String name, data) {
-        if (data is! Map) {
+        if (data is! Map<String, dynamic>) {
           return _reportError(
               "library data for '$name' in target '$targetName' is not a map");
         }
@@ -233,7 +233,7 @@
       [this._libraries = const <String, LibraryInfo>{}]);
 
   /// Details about a library whose import is `dart:$name`.
-  LibraryInfo libraryInfoFor(String name) => _libraries[name];
+  LibraryInfo? libraryInfoFor(String name) => _libraries[name];
 
   Iterable<LibraryInfo> get allLibraries => _libraries.values;
 }
diff --git a/pkg/front_end/lib/src/base/library_info.dart b/pkg/front_end/lib/src/base/library_info.dart
index f7541da..a8186f3 100644
--- a/pkg/front_end/lib/src/base/library_info.dart
+++ b/pkg/front_end/lib/src/base/library_info.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.9
+
 /// A bit flag used by [LibraryInfo] indicating that a library is used by
 /// dart2js.
 ///
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 7414b1c..94a7d0d 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_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.9
+
 import 'dart:io' show exitCode;
 
 import 'dart:typed_data' show Uint8List;
@@ -24,7 +26,7 @@
 import 'package:package_config/package_config.dart';
 
 import '../api_prototype/compiler_options.dart'
-    show CompilerOptions, DiagnosticMessage;
+    show CompilerOptions, InvocationMode, Verbosity, DiagnosticMessage;
 
 import '../api_prototype/experimental_flags.dart' as flags;
 
@@ -45,6 +47,8 @@
         Message,
         messageCantInferPackagesFromManyInputs,
         messageCantInferPackagesFromPackageUri,
+        messageCompilingWithSoundNullSafety,
+        messageCompilingWithoutSoundNullSafety,
         messageInternalProblemProvidedBothCompileSdkAndSdkSummary,
         messageMissingInput,
         noLength,
@@ -163,7 +167,7 @@
 
   bool get verify => _raw.verify;
 
-  bool get verifySkipPlatform => _raw.verifySkipPlatform;
+  bool get skipPlatformVerification => _raw.skipPlatformVerification;
 
   bool get debugDump => _raw.debugDump;
 
@@ -259,7 +263,9 @@
   }
 
   void _defaultDiagnosticMessageHandler(DiagnosticMessage message) {
-    printDiagnosticMessage(message, print);
+    if (Verbosity.shouldPrint(_raw.verbosity, message)) {
+      printDiagnosticMessage(message, print);
+    }
   }
 
   // TODO(askesc): Remove this and direct callers directly to report.
@@ -267,6 +273,25 @@
     report(message.withoutLocation(), severity);
   }
 
+  /// If `CompilerOptions.invocationModes` contains `InvocationMode.compile`, an
+  /// info message about the null safety compilation mode is emitted.
+  void reportNullSafetyCompilationModeInfo() {
+    if (_raw.invocationModes.contains(InvocationMode.compile)) {
+      switch (nnbdMode) {
+        case NnbdMode.Weak:
+          reportWithoutLocation(messageCompilingWithoutSoundNullSafety,
+              messageCompilingWithoutSoundNullSafety.severity);
+          break;
+        case NnbdMode.Strong:
+          reportWithoutLocation(messageCompilingWithSoundNullSafety,
+              messageCompilingWithSoundNullSafety.severity);
+          break;
+        case NnbdMode.Agnostic:
+          break;
+      }
+    }
+  }
+
   /// Runs various validations checks on the input options. For instance,
   /// if an option is a path to a file, it checks that the file exists.
   Future<bool> validateOptions({bool errorOnMissingInput: true}) async {
@@ -400,7 +425,8 @@
       if (sdkSummary == null) return null;
       List<int> bytes = await loadSdkSummaryBytes();
       if (bytes != null && bytes.isNotEmpty) {
-        _sdkSummaryComponent = loadComponent(bytes, nameRoot);
+        _sdkSummaryComponent =
+            loadComponent(bytes, nameRoot, fileUri: sdkSummary);
       }
     }
     return _sdkSummaryComponent;
@@ -424,10 +450,13 @@
       // TODO(sigmund): throttle # of concurrent operations.
       List<List<int>> allBytes = await Future.wait(
           uris.map((uri) => _readAsBytes(fileSystem.entityForUri(uri))));
-      _additionalDillComponents = allBytes
-          .where((bytes) => bytes != null)
-          .map((bytes) => loadComponent(bytes, nameRoot))
-          .toList();
+      List<Component> result = [];
+      for (int i = 0; i < uris.length; i++) {
+        if (allBytes[i] == null) continue;
+        List<int> bytes = allBytes[i];
+        result.add(loadComponent(bytes, nameRoot, fileUri: uris[i]));
+      }
+      _additionalDillComponents = result;
     }
     return _additionalDillComponents;
   }
@@ -442,13 +471,12 @@
 
   /// Helper to load a .dill file from [uri] using the existing [nameRoot].
   Component loadComponent(List<int> bytes, CanonicalName nameRoot,
-      {bool alwaysCreateNewNamedNodes}) {
+      {bool alwaysCreateNewNamedNodes, Uri fileUri}) {
     Component component =
         target.configureComponent(new Component(nameRoot: nameRoot));
-    // TODO(ahe): Pass file name to BinaryBuilder.
     // TODO(ahe): Control lazy loading via an option.
     new BinaryBuilder(bytes,
-            filename: null,
+            filename: fileUri == null ? null : '$fileUri',
             disableLazyReading: false,
             alwaysCreateNewNamedNodes: alwaysCreateNewNamedNodes)
         .readComponent(component);
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 2c36d10..3060afb 100644
--- a/pkg/front_end/lib/src/compute_platform_binaries_location.dart
+++ b/pkg/front_end/lib/src/compute_platform_binaries_location.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.9
+
 import "dart:io" show File, Platform;
 
 import 'package:kernel/ast.dart' show Source;
diff --git a/pkg/front_end/lib/src/fasta/builder/builder.dart b/pkg/front_end/lib/src/fasta/builder/builder.dart
index 709c4cfcc..4f2897d 100644
--- a/pkg/front_end/lib/src/fasta/builder/builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builder.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.9
+
 library fasta.declaration;
 
 import '../problems.dart' show unsupported;
diff --git a/pkg/front_end/lib/src/fasta/builder/builtin_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/builtin_type_declaration_builder.dart
index 24d258e..7f39862 100644
--- a/pkg/front_end/lib/src/fasta/builder/builtin_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builtin_type_declaration_builder.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.9
+
 library fasta.builtin_type_builder;
 
 import 'package:kernel/ast.dart' show DartType, Nullability;
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 6b97dd9..90141d2 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.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.9
+
 library fasta.class_builder;
 
 import 'package:kernel/ast.dart'
@@ -33,6 +35,8 @@
 import 'package:kernel/type_environment.dart'
     show SubtypeCheckMode, TypeEnvironment;
 
+import 'package:kernel/src/legacy_erasure.dart';
+
 import 'package:kernel/src/types.dart' show Types;
 
 import '../dill/dill_member_builder.dart';
@@ -177,12 +181,8 @@
 
   void checkSupertypes(CoreTypes coreTypes);
 
-  void handleSeenCovariant(
-      Types types,
-      Member declaredMember,
-      Member interfaceMember,
-      bool isSetter,
-      callback(Member declaredMember, Member interfaceMember, bool isSetter));
+  void handleSeenCovariant(Types types, Member interfaceMember, bool isSetter,
+      callback(Member interfaceMember, bool isSetter));
 
   bool hasUserDefinedNoSuchMethod(
       Class klass, ClassHierarchy hierarchy, Class objectClass);
@@ -611,7 +611,13 @@
   Supertype buildSupertype(
       LibraryBuilder library, List<TypeBuilder> arguments) {
     Class cls = isPatch ? origin.cls : this.cls;
-    return new Supertype(cls, buildTypeArguments(library, arguments));
+    List<DartType> typeArguments = buildTypeArguments(library, arguments);
+    if (!library.isNonNullableByDefault) {
+      for (int i = 0; i < typeArguments.length; ++i) {
+        typeArguments[i] = legacyErasure(typeArguments[i]);
+      }
+    }
+    return new Supertype(cls, typeArguments);
   }
 
   @override
@@ -738,12 +744,8 @@
   }
 
   @override
-  void handleSeenCovariant(
-      Types types,
-      Member declaredMember,
-      Member interfaceMember,
-      bool isSetter,
-      callback(Member declaredMember, Member interfaceMember, bool isSetter)) {
+  void handleSeenCovariant(Types types, Member interfaceMember, bool isSetter,
+      callback(Member interfaceMember, bool isSetter)) {
     // When a parameter is covariant we have to check that we also
     // override the same member in all parents.
     for (Supertype supertype in interfaceMember.enclosingClass.supers) {
@@ -751,7 +753,7 @@
           supertype.classNode, interfaceMember.name,
           setter: isSetter);
       if (m != null) {
-        callback(declaredMember, m, isSetter);
+        callback(m, isSetter);
       }
     }
   }
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 03f46c7..b98d56b 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
@@ -138,7 +140,7 @@
       int charOffset,
       this.charOpenParenOffset,
       int charEndOffset,
-      Constructor referenceFrom,
+      Member referenceFrom,
       [String nativeMethodName])
       : _constructor = new Constructor(null,
             fileUri: compilationUnit.fileUri,
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_reference_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_reference_builder.dart
index eb66bc8..824d08f 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_reference_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_reference_builder.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.9
+
 library fasta.constructor_reference_builder;
 
 import '../messages.dart' show noLength, templateConstructorNotFound;
diff --git a/pkg/front_end/lib/src/fasta/builder/declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/declaration_builder.dart
index 01d9fb0..0ba64f4 100644
--- a/pkg/front_end/lib/src/fasta/builder/declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/declaration_builder.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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/lib/src/fasta/builder/dynamic_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/dynamic_type_declaration_builder.dart
index b5e9b80..cdc6f30 100644
--- a/pkg/front_end/lib/src/fasta/builder/dynamic_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/dynamic_type_declaration_builder.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.9
+
 library fasta.dynamic_type_builder;
 
 import 'package:kernel/ast.dart' show DartType;
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 deb42c7..7101cf2 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.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.9
+
 library fasta.enum_builder;
 
 import 'package:kernel/ast.dart'
@@ -17,9 +19,10 @@
         IntLiteral,
         InterfaceType,
         ListLiteral,
-        Procedure,
+        Name,
         ProcedureKind,
         PropertyGet,
+        Reference,
         ReturnStatement,
         StaticGet,
         StringLiteral,
@@ -173,17 +176,32 @@
     ///   String toString() => _name;
     /// }
     Constructor constructorReference;
-    Procedure toStringReference;
-    Field indexReference;
-    Field _nameReference;
-    Field valuesReference;
+    Reference toStringReference;
+    Reference indexGetterReference;
+    Reference indexSetterReference;
+    Reference _nameGetterReference;
+    Reference _nameSetterReference;
+    Reference valuesGetterReference;
+    Reference valuesSetterReference;
     if (referencesFrom != null) {
-      constructorReference = referencesFromIndexed.lookupConstructor("");
+      constructorReference =
+          referencesFromIndexed.lookupConstructor(new Name(""));
       toStringReference =
-          referencesFromIndexed.lookupProcedureNotSetter("toString");
-      indexReference = referencesFromIndexed.lookupField("index");
-      _nameReference = referencesFromIndexed.lookupField("_name");
-      valuesReference = referencesFromIndexed.lookupField("values");
+          referencesFromIndexed.lookupGetterReference(new Name("toString"));
+      Name indexName = new Name("index");
+      indexGetterReference =
+          referencesFromIndexed.lookupGetterReference(indexName);
+      indexSetterReference =
+          referencesFromIndexed.lookupSetterReference(indexName);
+      _nameGetterReference = referencesFromIndexed.lookupGetterReference(
+          new Name("_name", referencesFromIndexed.library));
+      _nameSetterReference = referencesFromIndexed.lookupSetterReference(
+          new Name("_name", referencesFromIndexed.library));
+      Name valuesName = new Name("values");
+      valuesGetterReference =
+          referencesFromIndexed.lookupGetterReference(valuesName);
+      valuesSetterReference =
+          referencesFromIndexed.lookupSetterReference(valuesName);
     }
 
     members["index"] = new SourceFieldBuilder(
@@ -195,10 +213,8 @@
         parent,
         charOffset,
         charOffset,
-        indexReference,
-        null,
-        null,
-        null);
+        fieldGetterReference: indexGetterReference,
+        fieldSetterReference: indexSetterReference);
     members["_name"] = new SourceFieldBuilder(
         null,
         stringType,
@@ -208,10 +224,8 @@
         parent,
         charOffset,
         charOffset,
-        _nameReference,
-        null,
-        null,
-        null);
+        fieldGetterReference: _nameGetterReference,
+        fieldSetterReference: _nameSetterReference);
     ConstructorBuilder constructorBuilder = new ConstructorBuilderImpl(
         null,
         constMask,
@@ -240,10 +254,8 @@
         parent,
         charOffset,
         charOffset,
-        valuesReference,
-        null,
-        null,
-        null);
+        fieldGetterReference: valuesGetterReference,
+        fieldSetterReference: valuesSetterReference);
     members["values"] = valuesBuilder;
     constructorBuilder
       ..registerInitializedField(members["_name"])
@@ -303,9 +315,14 @@
               name.length,
               parent.fileUri);
         }
-        Field fieldReference;
-        if (referencesFrom != null) {
-          fieldReference = referencesFromIndexed.lookupField(name);
+        Reference getterReference;
+        Reference setterReference;
+        if (referencesFromIndexed != null) {
+          Name nameName = new Name(name, referencesFromIndexed.library);
+          getterReference =
+              referencesFromIndexed.lookupGetterReference(nameName);
+          setterReference =
+              referencesFromIndexed.lookupSetterReference(nameName);
         }
         FieldBuilder fieldBuilder = new SourceFieldBuilder(
             metadata,
@@ -316,10 +333,8 @@
             parent,
             enumConstantInfo.charOffset,
             enumConstantInfo.charOffset,
-            fieldReference,
-            null,
-            null,
-            null);
+            fieldGetterReference: getterReference,
+            fieldSetterReference: setterReference);
         metadataCollector?.setDocumentationComment(
             fieldBuilder.field, documentationComment);
         members[name] = fieldBuilder..next = existing;
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 b361811..b0bc5db 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
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 833753c..736be55 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.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.9
+
 library fasta.field_builder;
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
@@ -117,10 +119,12 @@
       SourceLibraryBuilder libraryBuilder,
       int charOffset,
       int charEndOffset,
-      Field reference,
-      Field lateIsSetReferenceFrom,
-      Procedure getterReferenceFrom,
-      Procedure setterReferenceFrom)
+      {Reference fieldGetterReference,
+      Reference fieldSetterReference,
+      Reference lateIsSetGetterReference,
+      Reference lateIsSetSetterReference,
+      Reference getterReference,
+      Reference setterReference})
       : super(libraryBuilder, charOffset) {
     Uri fileUri = libraryBuilder?.fileUri;
     // If in mixed mode, late lowerings cannot use `null` as a sentinel on
@@ -128,8 +132,8 @@
     late_lowering.IsSetStrategy isSetStrategy =
         late_lowering.computeIsSetStrategy(libraryBuilder);
     if (isAbstract || isExternal) {
-      _fieldEncoding = new AbstractOrExternalFieldEncoding(fileUri, charOffset,
-          charEndOffset, getterReferenceFrom, setterReferenceFrom,
+      _fieldEncoding = new AbstractOrExternalFieldEncoding(
+          fileUri, charOffset, charEndOffset, getterReference, setterReference,
           isAbstract: isAbstract,
           isExternal: isExternal,
           isFinal: isFinal,
@@ -147,10 +151,12 @@
               fileUri,
               charOffset,
               charEndOffset,
-              reference,
-              lateIsSetReferenceFrom,
-              getterReferenceFrom,
-              setterReferenceFrom,
+              fieldGetterReference,
+              fieldSetterReference,
+              lateIsSetGetterReference,
+              lateIsSetSetterReference,
+              getterReference,
+              setterReference,
               isCovariant,
               isSetStrategy);
         } else {
@@ -159,10 +165,12 @@
               fileUri,
               charOffset,
               charEndOffset,
-              reference,
-              lateIsSetReferenceFrom,
-              getterReferenceFrom,
-              setterReferenceFrom,
+              fieldGetterReference,
+              fieldSetterReference,
+              lateIsSetGetterReference,
+              lateIsSetSetterReference,
+              getterReference,
+              setterReference,
               isCovariant,
               isSetStrategy);
         }
@@ -173,10 +181,12 @@
               fileUri,
               charOffset,
               charEndOffset,
-              reference,
-              lateIsSetReferenceFrom,
-              getterReferenceFrom,
-              setterReferenceFrom,
+              fieldGetterReference,
+              fieldSetterReference,
+              lateIsSetGetterReference,
+              lateIsSetSetterReference,
+              getterReference,
+              setterReference,
               isCovariant,
               isSetStrategy);
         } else {
@@ -185,10 +195,12 @@
               fileUri,
               charOffset,
               charEndOffset,
-              reference,
-              lateIsSetReferenceFrom,
-              getterReferenceFrom,
-              setterReferenceFrom,
+              fieldGetterReference,
+              fieldSetterReference,
+              lateIsSetGetterReference,
+              lateIsSetSetterReference,
+              getterReference,
+              setterReference,
               isCovariant,
               isSetStrategy);
         }
@@ -204,10 +216,12 @@
             fileUri,
             charOffset,
             charEndOffset,
-            reference,
-            lateIsSetReferenceFrom,
-            getterReferenceFrom,
-            setterReferenceFrom,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            getterReference,
+            setterReference,
             isCovariant,
             isSetStrategy);
       } else {
@@ -216,19 +230,29 @@
             fileUri,
             charOffset,
             charEndOffset,
-            reference,
-            lateIsSetReferenceFrom,
-            getterReferenceFrom,
-            setterReferenceFrom,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            getterReference,
+            setterReference,
             isCovariant,
             isSetStrategy);
       }
     } else {
-      assert(lateIsSetReferenceFrom == null);
-      assert(getterReferenceFrom == null);
-      assert(setterReferenceFrom == null);
-      _fieldEncoding = new RegularFieldEncoding(fileUri, charOffset,
-          charEndOffset, reference, library.isNonNullableByDefault);
+      assert(lateIsSetGetterReference == null);
+      assert(lateIsSetSetterReference == null);
+      assert(getterReference == null);
+      assert(setterReference == null);
+      _fieldEncoding = new RegularFieldEncoding(
+          fileUri, charOffset, charEndOffset,
+          isFinal: isFinal,
+          isConst: isConst,
+          isLate: isLate,
+          hasInitializer: hasInitializer,
+          isNonNullableByDefault: library.isNonNullableByDefault,
+          getterReference: fieldGetterReference,
+          setterReference: fieldSetterReference);
     }
   }
 
@@ -286,7 +310,11 @@
       internalProblem(
           messageInternalProblemAlreadyInitialized, charOffset, fileUri);
     }
-    _fieldEncoding.createBodies(coreTypes, initializer);
+    _fieldEncoding.createBodies(
+        coreTypes,
+        initializer,
+        library
+            .loader.target.backendTarget.supportsNewMethodInvocationEncoding);
   }
 
   @override
@@ -526,7 +554,8 @@
   ///
   /// 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);
+  void createBodies(CoreTypes coreTypes, Expression initializer,
+      bool useNewMethodInvocationEncoding);
 
   List<Initializer> createInitializer(int fileOffset, Expression value,
       {bool isSynthetic});
@@ -583,11 +612,33 @@
   Field _field;
 
   RegularFieldEncoding(Uri fileUri, int charOffset, int charEndOffset,
-      Field reference, bool isNonNullableByDefault) {
-    _field = new Field(null,
-        fileUri: fileUri,
-        getterReference: reference?.getterReference,
-        setterReference: reference?.setterReference)
+      {bool isFinal,
+      bool isConst,
+      bool isLate,
+      bool hasInitializer,
+      bool isNonNullableByDefault,
+      Reference getterReference,
+      Reference setterReference}) {
+    assert(isFinal != null);
+    assert(isConst != null);
+    assert(isLate != null);
+    assert(hasInitializer != null);
+    bool isImmutable =
+        isLate ? (isFinal && hasInitializer) : (isFinal || isConst);
+    _field = isImmutable
+        ? new Field.immutable(null,
+            isFinal: isFinal,
+            isConst: isConst,
+            isLate: isLate,
+            fileUri: fileUri,
+            getterReference: getterReference)
+        : new Field.mutable(null,
+            isFinal: isFinal,
+            isLate: isLate,
+            fileUri: fileUri,
+            getterReference: getterReference,
+            setterReference: setterReference);
+    _field
       ..fileOffset = charOffset
       ..fileEndOffset = charEndOffset
       ..isNonNullableByDefault = isNonNullableByDefault;
@@ -605,7 +656,8 @@
   void completeSignature(CoreTypes coreTypes) {}
 
   @override
-  void createBodies(CoreTypes coreTypes, Expression initializer) {
+  void createBodies(CoreTypes coreTypes, Expression initializer,
+      bool useNewMethodInvocationEncoding) {
     if (initializer != null) {
       _field.initializer = initializer..parent = _field;
     }
@@ -624,10 +676,7 @@
   @override
   void build(
       SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
-    _field
-      ..isCovariant = fieldBuilder.isCovariant
-      ..isFinal = fieldBuilder.isFinal
-      ..isConst = fieldBuilder.isConst;
+    _field..isCovariant = fieldBuilder.isCovariant;
     String fieldName;
     if (fieldBuilder.isExtensionMember) {
       ExtensionBuilder extension = fieldBuilder.parent;
@@ -635,8 +684,6 @@
           FieldNameType.Field, fieldBuilder.name,
           isExtensionMethod: true, extensionName: extension.name);
       _field
-        ..hasImplicitGetter = false
-        ..hasImplicitSetter = false
         ..isStatic = true
         ..isExtensionMember = true;
     } else {
@@ -648,11 +695,6 @@
           FieldNameType.Field, fieldBuilder.name,
           isInstanceMember: isInstanceMember, className: className);
       _field
-        ..hasImplicitGetter = isInstanceMember
-        ..hasImplicitSetter = isInstanceMember &&
-            !fieldBuilder.isConst &&
-            (!fieldBuilder.isFinal ||
-                (fieldBuilder.isLate && !fieldBuilder.hasInitializer))
         ..isStatic = !isInstanceMember
         ..isExtensionMember = false;
     }
@@ -749,9 +791,6 @@
   bool get isProperty => true;
 
   @override
-  bool get isFunction => false;
-
-  @override
   bool isSameDeclaration(ClassMember other) {
     return other is SourceFieldMember && memberBuilder == other.memberBuilder;
   }
@@ -789,10 +828,12 @@
       Uri fileUri,
       int charOffset,
       int charEndOffset,
-      Field referenceFrom,
-      Field lateIsSetReferenceFrom,
-      Procedure getterReferenceFrom,
-      Procedure setterReferenceFrom,
+      Reference fieldGetterReference,
+      Reference fieldSetterReference,
+      Reference lateIsSetGetterReference,
+      Reference lateIsSetSetterReference,
+      Reference getterReference,
+      Reference setterReference,
       bool isCovariant,
       late_lowering.IsSetStrategy isSetStrategy)
       : fileOffset = charOffset,
@@ -800,10 +841,10 @@
         _isSetStrategy = isSetStrategy,
         _forceIncludeIsSetField =
             isSetStrategy == late_lowering.IsSetStrategy.forceUseIsSetField {
-    _field = new Field(null,
+    _field = new Field.mutable(null,
         fileUri: fileUri,
-        getterReference: referenceFrom?.getterReference,
-        setterReference: referenceFrom?.setterReference)
+        getterReference: fieldGetterReference,
+        setterReference: fieldSetterReference)
       ..fileOffset = charOffset
       ..fileEndOffset = charEndOffset
       ..isNonNullableByDefault = true
@@ -815,10 +856,10 @@
         break;
       case late_lowering.IsSetStrategy.forceUseIsSetField:
       case late_lowering.IsSetStrategy.useIsSetFieldOrNull:
-        _lateIsSetField = new Field(null,
+        _lateIsSetField = new Field.mutable(null,
             fileUri: fileUri,
-            getterReference: lateIsSetReferenceFrom?.getterReference,
-            setterReference: lateIsSetReferenceFrom?.setterReference)
+            getterReference: lateIsSetGetterReference,
+            setterReference: lateIsSetSetterReference)
           ..fileOffset = charOffset
           ..fileEndOffset = charEndOffset
           ..isNonNullableByDefault = true
@@ -832,11 +873,11 @@
           ..fileOffset = charOffset
           ..fileEndOffset = charEndOffset,
         fileUri: fileUri,
-        reference: getterReferenceFrom?.reference)
+        reference: getterReference)
       ..fileOffset = charOffset
       ..fileEndOffset = charEndOffset
       ..isNonNullableByDefault = true;
-    _lateSetter = _createSetter(name, fileUri, charOffset, setterReferenceFrom,
+    _lateSetter = _createSetter(name, fileUri, charOffset, setterReference,
         isCovariant: isCovariant);
   }
 
@@ -854,11 +895,13 @@
   }
 
   @override
-  void createBodies(CoreTypes coreTypes, Expression initializer) {
+  void createBodies(CoreTypes coreTypes, Expression initializer,
+      bool useNewMethodInvocationEncoding) {
     assert(_type != null, "Type has not been computed for field $name.");
     if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
       _field.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
           new Arguments([], types: [_type])..fileOffset = fileOffset)
+        ..fileOffset = fileOffset
         ..parent = _field;
     } else {
       _field.initializer = new NullLiteral()
@@ -870,11 +913,15 @@
         ..fileOffset = fileOffset
         ..parent = _lateIsSetField;
     }
-    _lateGetter.function.body = _createGetterBody(coreTypes, name, initializer)
+    _lateGetter.function.body = _createGetterBody(
+        coreTypes, name, initializer, useNewMethodInvocationEncoding)
       ..parent = _lateGetter.function;
     if (_lateSetter != null) {
       _lateSetter.function.body = _createSetterBody(
-          coreTypes, name, _lateSetter.function.positionalParameters.first)
+          coreTypes,
+          name,
+          _lateSetter.function.positionalParameters.first,
+          useNewMethodInvocationEncoding)
         ..parent = _lateSetter.function;
     }
   }
@@ -936,11 +983,11 @@
     }
   }
 
-  Statement _createGetterBody(
-      CoreTypes coreTypes, String name, Expression initializer);
+  Statement _createGetterBody(CoreTypes coreTypes, String name,
+      Expression initializer, bool useNewMethodInvocationEncoding);
 
   Procedure _createSetter(
-      String name, Uri fileUri, int charOffset, Procedure referenceFrom,
+      String name, Uri fileUri, int charOffset, Reference reference,
       {bool isCovariant}) {
     assert(isCovariant != null);
     VariableDeclaration parameter = new VariableDeclaration(null)
@@ -954,14 +1001,14 @@
           ..fileOffset = charOffset
           ..fileEndOffset = fileEndOffset,
         fileUri: fileUri,
-        reference: referenceFrom?.reference)
+        reference: reference)
       ..fileOffset = charOffset
       ..fileEndOffset = fileEndOffset
       ..isNonNullableByDefault = true;
   }
 
-  Statement _createSetterBody(
-      CoreTypes coreTypes, String name, VariableDeclaration parameter);
+  Statement _createSetterBody(CoreTypes coreTypes, String name,
+      VariableDeclaration parameter, bool useNewMethodInvocationEncoding);
 
   @override
   DartType get type => _type;
@@ -1031,16 +1078,12 @@
       ExtensionBuilder extension = fieldBuilder.parent;
       extensionName = extension.name;
       _field
-        ..hasImplicitGetter = false
-        ..hasImplicitSetter = false
         ..isStatic = true
         ..isExtensionMember = isExtensionMember;
       isInstanceMember = false;
     } else {
       isInstanceMember = !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
       _field
-        ..hasImplicitGetter = isInstanceMember
-        ..hasImplicitSetter = isInstanceMember
         ..isStatic = !isInstanceMember
         ..isExtensionMember = false;
       if (isInstanceMember) {
@@ -1068,8 +1111,6 @@
                 isSynthesized: true),
             libraryBuilder.library)
         ..isStatic = !isInstanceMember
-        ..hasImplicitGetter = isInstanceMember
-        ..hasImplicitSetter = isInstanceMember
         ..isStatic = _field.isStatic
         ..isExtensionMember = isExtensionMember;
     }
@@ -1165,8 +1206,8 @@
 
 mixin NonFinalLate on AbstractLateFieldEncoding {
   @override
-  Statement _createSetterBody(
-      CoreTypes coreTypes, String name, VariableDeclaration parameter) {
+  Statement _createSetterBody(CoreTypes coreTypes, String name,
+      VariableDeclaration parameter, bool useNewMethodInvocationEncoding) {
     assert(_type != null, "Type has not been computed for field $name.");
     return late_lowering.createSetterBody(
         coreTypes, fileOffset, name, parameter, _type,
@@ -1181,11 +1222,11 @@
 
 mixin LateWithoutInitializer on AbstractLateFieldEncoding {
   @override
-  Statement _createGetterBody(
-      CoreTypes coreTypes, String name, Expression initializer) {
+  Statement _createGetterBody(CoreTypes coreTypes, String name,
+      Expression initializer, bool useNewMethodInvocationEncoding) {
     assert(_type != null, "Type has not been computed for field $name.");
     return late_lowering.createGetterBodyWithoutInitializer(
-        coreTypes, fileOffset, name, type,
+        coreTypes, fileOffset, name, type, useNewMethodInvocationEncoding,
         createVariableRead: _createFieldRead,
         createIsSetRead: () => _createFieldGet(_lateIsSetField),
         isSetEncoding: isSetEncoding,
@@ -1200,10 +1241,12 @@
       Uri fileUri,
       int charOffset,
       int charEndOffset,
-      Field referenceFrom,
-      Field lateIsSetReferenceFrom,
-      Procedure getterReferenceFrom,
-      Procedure setterReferenceFrom,
+      Reference fieldGetterReference,
+      Reference fieldSetterReference,
+      Reference lateIsSetGetterReference,
+      Reference lateIsSetSetterReference,
+      Reference getterReference,
+      Reference setterReference,
       bool isCovariant,
       late_lowering.IsSetStrategy isSetStrategy)
       : super(
@@ -1211,10 +1254,12 @@
             fileUri,
             charOffset,
             charEndOffset,
-            referenceFrom,
-            lateIsSetReferenceFrom,
-            getterReferenceFrom,
-            setterReferenceFrom,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            getterReference,
+            setterReference,
             isCovariant,
             isSetStrategy);
 }
@@ -1226,10 +1271,12 @@
       Uri fileUri,
       int charOffset,
       int charEndOffset,
-      Field referenceFrom,
-      Field lateIsSetReferenceFrom,
-      Procedure getterReferenceFrom,
-      Procedure setterReferenceFrom,
+      Reference fieldGetterReference,
+      Reference fieldSetterReference,
+      Reference lateIsSetGetterReference,
+      Reference lateIsSetSetterReference,
+      Reference getterReference,
+      Reference setterReference,
       bool isCovariant,
       late_lowering.IsSetStrategy isSetStrategy)
       : super(
@@ -1237,19 +1284,21 @@
             fileUri,
             charOffset,
             charEndOffset,
-            referenceFrom,
-            lateIsSetReferenceFrom,
-            getterReferenceFrom,
-            setterReferenceFrom,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            getterReference,
+            setterReference,
             isCovariant,
             isSetStrategy);
 
   @override
-  Statement _createGetterBody(
-      CoreTypes coreTypes, String name, Expression initializer) {
+  Statement _createGetterBody(CoreTypes coreTypes, String name,
+      Expression initializer, bool useNewMethodInvocationEncoding) {
     assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createGetterWithInitializer(
-        coreTypes, fileOffset, name, _type, initializer,
+    return late_lowering.createGetterWithInitializer(coreTypes, fileOffset,
+        name, _type, initializer, useNewMethodInvocationEncoding,
         createVariableRead: _createFieldRead,
         createVariableWrite: (Expression value) =>
             _createFieldSet(_field, value),
@@ -1267,10 +1316,12 @@
       Uri fileUri,
       int charOffset,
       int charEndOffset,
-      Field referenceFrom,
-      Field lateIsSetReferenceFrom,
-      Procedure getterReferenceFrom,
-      Procedure setterReferenceFrom,
+      Reference fieldGetterReference,
+      Reference fieldSetterReference,
+      Reference lateIsSetGetterReference,
+      Reference lateIsSetSetterReference,
+      Reference getterReference,
+      Reference setterReference,
       bool isCovariant,
       late_lowering.IsSetStrategy isSetStrategy)
       : super(
@@ -1278,19 +1329,21 @@
             fileUri,
             charOffset,
             charEndOffset,
-            referenceFrom,
-            lateIsSetReferenceFrom,
-            getterReferenceFrom,
-            setterReferenceFrom,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            getterReference,
+            setterReference,
             isCovariant,
             isSetStrategy);
 
   @override
-  Statement _createSetterBody(
-      CoreTypes coreTypes, String name, VariableDeclaration parameter) {
+  Statement _createSetterBody(CoreTypes coreTypes, String name,
+      VariableDeclaration parameter, bool useNewMethodInvocationEncoding) {
     assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createSetterBodyFinal(
-        coreTypes, fileOffset, name, parameter, type,
+    return late_lowering.createSetterBodyFinal(coreTypes, fileOffset, name,
+        parameter, type, useNewMethodInvocationEncoding,
         shouldReturnValue: false,
         createVariableRead: () => _createFieldGet(_field),
         createVariableWrite: (Expression value) =>
@@ -1309,10 +1362,12 @@
       Uri fileUri,
       int charOffset,
       int charEndOffset,
-      Field referenceFrom,
-      Field lateIsSetReferenceFrom,
-      Procedure getterReferenceFrom,
-      Procedure setterReferenceFrom,
+      Reference fieldGetterReference,
+      Reference fieldSetterReference,
+      Reference lateIsSetGetterReference,
+      Reference lateIsSetSetterReference,
+      Reference getterReference,
+      Reference setterReference,
       bool isCovariant,
       late_lowering.IsSetStrategy isSetStrategy)
       : super(
@@ -1320,18 +1375,20 @@
             fileUri,
             charOffset,
             charEndOffset,
-            referenceFrom,
-            lateIsSetReferenceFrom,
-            getterReferenceFrom,
-            setterReferenceFrom,
+            fieldGetterReference,
+            fieldSetterReference,
+            lateIsSetGetterReference,
+            lateIsSetSetterReference,
+            getterReference,
+            setterReference,
             isCovariant,
             isSetStrategy);
   @override
-  Statement _createGetterBody(
-      CoreTypes coreTypes, String name, Expression initializer) {
+  Statement _createGetterBody(CoreTypes coreTypes, String name,
+      Expression initializer, bool useNewMethodInvocationEncoding) {
     assert(_type != null, "Type has not been computed for field $name.");
-    return late_lowering.createGetterWithInitializerWithRecheck(
-        coreTypes, fileOffset, name, _type, initializer,
+    return late_lowering.createGetterWithInitializerWithRecheck(coreTypes,
+        fileOffset, name, _type, initializer, useNewMethodInvocationEncoding,
         createVariableRead: _createFieldRead,
         createVariableWrite: (Expression value) =>
             _createFieldSet(_field, value),
@@ -1344,13 +1401,13 @@
 
   @override
   Procedure _createSetter(
-          String name, Uri fileUri, int charOffset, Procedure referenceFrom,
+          String name, Uri fileUri, int charOffset, Reference reference,
           {bool isCovariant}) =>
       null;
 
   @override
-  Statement _createSetterBody(
-          CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
+  Statement _createSetterBody(CoreTypes coreTypes, String name,
+          VariableDeclaration parameter, bool useNewMethodInvocationEncoding) =>
       null;
 }
 
@@ -1400,9 +1457,6 @@
   bool get isProperty => isField || isGetter || isSetter;
 
   @override
-  bool get isFunction => !isProperty;
-
-  @override
   ClassBuilder get classBuilder => fieldBuilder.classBuilder;
 
   @override
@@ -1474,19 +1528,9 @@
   bool get isAbstract => _member.isAbstract;
 
   @override
-  bool get needsComputation => false;
-
-  @override
   bool get isSynthesized => false;
 
   @override
-  bool get isInheritableConflict => false;
-
-  @override
-  ClassMember withParent(ClassBuilder classBuilder) =>
-      throw new UnsupportedError("$runtimeType.withParent");
-
-  @override
   bool get hasDeclarations => false;
 
   @override
@@ -1494,10 +1538,7 @@
       throw new UnsupportedError("$runtimeType.declarations");
 
   @override
-  ClassMember get abstract => this;
-
-  @override
-  ClassMember get concrete => this;
+  ClassMember get interfaceMember => this;
 
   @override
   bool isSameDeclaration(ClassMember other) {
@@ -1520,7 +1561,7 @@
   Procedure _setter;
 
   AbstractOrExternalFieldEncoding(Uri fileUri, int charOffset,
-      int charEndOffset, Procedure getterReference, Procedure setterReference,
+      int charEndOffset, Reference getterReference, Reference setterReference,
       {this.isAbstract,
       this.isExternal,
       bool isFinal,
@@ -1532,7 +1573,7 @@
         assert(isCovariant != null),
         assert(isNonNullableByDefault != null) {
     _getter = new Procedure(null, ProcedureKind.Getter, new FunctionNode(null),
-        fileUri: fileUri, reference: getterReference?.reference)
+        fileUri: fileUri, reference: getterReference)
       ..fileOffset = charOffset
       ..fileEndOffset = charEndOffset
       ..isNonNullableByDefault = isNonNullableByDefault;
@@ -1549,7 +1590,7 @@
             ..fileOffset = charOffset
             ..fileEndOffset = charEndOffset,
           fileUri: fileUri,
-          reference: setterReference?.reference)
+          reference: setterReference)
         ..fileOffset = charOffset
         ..fileEndOffset = charEndOffset
         ..isNonNullableByDefault = isNonNullableByDefault;
@@ -1571,7 +1612,8 @@
   void completeSignature(CoreTypes coreTypes) {}
 
   @override
-  void createBodies(CoreTypes coreTypes, Expression initializer) {
+  void createBodies(CoreTypes coreTypes, Expression initializer,
+      bool useNewMethodInvocationEncoding) {
     //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 d6eb954..3f91098 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
@@ -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.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 
 import '../problems.dart';
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 626190e..3b8fe9b 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
@@ -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.9
+
 library fasta.formal_parameter_builder;
 
 import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart'
@@ -17,7 +19,9 @@
 import 'package:front_end/src/fasta/builder/procedure_builder.dart';
 
 import 'package:kernel/ast.dart'
-    show DynamicType, Expression, VariableDeclaration;
+    show DartType, DynamicType, Expression, VariableDeclaration;
+
+import 'package:kernel/src/legacy_erasure.dart';
 
 import '../constant_context.dart' show ConstantContext;
 
@@ -117,8 +121,12 @@
       SourceLibraryBuilder library, int functionNestingLevel,
       [bool notInstanceContext]) {
     if (variable == null) {
+      DartType builtType = type?.build(library, null, notInstanceContext);
+      if (!library.isNonNullableByDefault && builtType != null) {
+        builtType = legacyErasure(builtType);
+      }
       variable = new VariableDeclarationImpl(name, functionNestingLevel,
-          type: type?.build(library, null, notInstanceContext),
+          type: builtType,
           isFinal: isFinal,
           isConst: isConst,
           isFieldFormal: isInitializingFormal,
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 129c01a..4bdfca5 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.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.9
+
 library fasta.procedure_builder;
 
 import 'dart:core' hide MapEntry;
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
index 3143c2d..1f5bbe7 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_type_builder.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.9
+
 library fasta.function_type_builder;
 
 import 'package:kernel/ast.dart'
diff --git a/pkg/front_end/lib/src/fasta/builder/future_or_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/future_or_type_declaration_builder.dart
index bc3c296..3e3e050 100644
--- a/pkg/front_end/lib/src/fasta/builder/future_or_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/future_or_type_declaration_builder.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.9
+
 library fasta.future_or_type_builder;
 
 import 'package:kernel/ast.dart' show DartType, FutureOrType, Nullability;
diff --git a/pkg/front_end/lib/src/fasta/builder/invalid_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/invalid_type_declaration_builder.dart
index d101dfa..bce176c5 100644
--- a/pkg/front_end/lib/src/fasta/builder/invalid_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/invalid_type_declaration_builder.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.9
+
 library fasta.invalid_type_builder;
 
 import 'package:kernel/ast.dart' show DartType, InvalidType, Nullability;
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 7f80ef3e..f318572 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.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.9
+
 library fasta.library_builder;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
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 58d5882..b41a5a4 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.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.9
+
 library fasta.member_builder;
 
 import 'dart:core' hide MapEntry;
@@ -98,10 +100,10 @@
 
   MemberDataForTesting dataForTesting;
 
-  MemberBuilderImpl(this.parent, int charOffset)
+  MemberBuilderImpl(this.parent, int charOffset, [Uri fileUri])
       : dataForTesting =
             retainDataForTesting ? new MemberDataForTesting() : null,
-        super(parent, charOffset);
+        super(parent, charOffset, fileUri);
 
   @override
   bool get isDeclarationInstanceMember => isDeclarationMember && !isStatic;
@@ -259,22 +261,12 @@
   bool get isAbstract => memberBuilder.member.isAbstract;
 
   @override
-  bool get needsComputation => false;
-
-  @override
   bool get isSynthesized => false;
 
   @override
   bool get isInternalImplementation => false;
 
   @override
-  bool get isInheritableConflict => false;
-
-  @override
-  ClassMember withParent(ClassBuilder classBuilder) =>
-      throw new UnsupportedError("$runtimeType.withParent");
-
-  @override
   bool get hasDeclarations => false;
 
   @override
@@ -282,10 +274,7 @@
       throw new UnsupportedError("$runtimeType.declarations");
 
   @override
-  ClassMember get abstract => this;
-
-  @override
-  ClassMember get concrete => this;
+  ClassMember get interfaceMember => this;
 
   @override
   String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
diff --git a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
index 80978bb..910119c 100644
--- a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/metadata_builder.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.9
+
 library fasta.metadata_builder;
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
diff --git a/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart b/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
index e78679d..e1439c5 100644
--- a/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.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.9
+
 library fasta.mixin_application_builder;
 
 import 'package:kernel/ast.dart' show InterfaceType, Supertype, TypedefType;
diff --git a/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart b/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart
index 7820923..8836414 100644
--- a/pkg/front_end/lib/src/fasta/builder/modifier_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/modifier_builder.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.9
+
 library fasta.modifier_builder;
 
 import '../modifier.dart';
diff --git a/pkg/front_end/lib/src/fasta/builder/name_iterator.dart b/pkg/front_end/lib/src/fasta/builder/name_iterator.dart
index 165dfb3..653a49b 100644
--- a/pkg/front_end/lib/src/fasta/builder/name_iterator.dart
+++ b/pkg/front_end/lib/src/fasta/builder/name_iterator.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.9
+
 library fasta.name_iterator;
 
 import 'builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 54cd164..1618af1 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -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.9
+
 library fasta.named_type_builder;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
diff --git a/pkg/front_end/lib/src/fasta/builder/never_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/never_type_declaration_builder.dart
index 509dd32..61bcbc8 100644
--- a/pkg/front_end/lib/src/fasta/builder/never_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/never_type_declaration_builder.dart
@@ -2,9 +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
+
 library fasta.never_type_builder;
 
-import 'package:kernel/ast.dart' show DartType, NullType, Nullability;
+import 'package:kernel/ast.dart' show DartType, Nullability;
 
 import 'builtin_type_declaration_builder.dart';
 import 'library_builder.dart';
@@ -24,17 +26,11 @@
   DartType buildType(LibraryBuilder library,
       NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
       [bool notInstanceContext]) {
-    if (!library.isNonNullableByDefault) {
-      return const NullType();
-    }
     return type.withDeclaredNullability(nullabilityBuilder.build(library));
   }
 
   DartType buildTypesWithBuiltArguments(LibraryBuilder library,
       Nullability nullability, List<DartType> arguments) {
-    if (!library.isNonNullableByDefault) {
-      return const NullType();
-    }
     return type.withDeclaredNullability(nullability);
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/null_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/null_type_declaration_builder.dart
index cbfd853..4e81719 100644
--- a/pkg/front_end/lib/src/fasta/builder/null_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/null_type_declaration_builder.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.9
+
 library fasta.null_type_declaration_builder;
 
 import 'package:kernel/ast.dart' show DartType, Nullability;
diff --git a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
index 4d7b983..d14f2dc 100644
--- a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/nullability_builder.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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart b/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
index 4fe2571..0635ea9 100644
--- a/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/prefix_builder.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.9
+
 library fasta.prefix_builder;
 
 import 'package:kernel/ast.dart' show LibraryDependency;
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 4857e5e..388ba1d 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:front_end/src/fasta/dill/dill_member_builder.dart';
@@ -97,13 +99,12 @@
       int charOffset,
       this.charOpenParenOffset,
       int charEndOffset,
-      Procedure referenceFrom,
+      Reference procedureReference,
       this.isExtensionInstanceMember,
       [String nativeMethodName])
       : _procedure = new Procedure(
             null, isExtensionInstanceMember ? ProcedureKind.Method : kind, null,
-            fileUri: compilationUnit.fileUri,
-            reference: referenceFrom?.reference)
+            fileUri: compilationUnit.fileUri, reference: procedureReference)
           ..startFileOffset = startCharOffset
           ..fileOffset = charOffset
           ..fileEndOffset = charEndOffset
@@ -202,7 +203,7 @@
 }
 
 class SourceProcedureBuilder extends ProcedureBuilderImpl {
-  final Procedure _tearOffReferenceFrom;
+  final Reference _tearOffReference;
 
   /// If this is an extension instance method then [_extensionTearOff] holds
   /// the synthetically created tear off function.
@@ -229,8 +230,8 @@
       int charOffset,
       int charOpenParenOffset,
       int charEndOffset,
-      Procedure referenceFrom,
-      this._tearOffReferenceFrom,
+      Reference procedureReference,
+      this._tearOffReference,
       AsyncMarker asyncModifier,
       bool isExtensionInstanceMember,
       [String nativeMethodName])
@@ -247,7 +248,7 @@
             charOffset,
             charOpenParenOffset,
             charEndOffset,
-            referenceFrom,
+            procedureReference,
             isExtensionInstanceMember,
             nativeMethodName) {
     this.asyncModifier = asyncModifier;
@@ -568,9 +569,7 @@
   Procedure get extensionTearOff {
     if (isExtensionInstanceMember && kind == ProcedureKind.Method) {
       _extensionTearOff ??= new Procedure(null, ProcedureKind.Method, null,
-          isStatic: true,
-          isExtensionMember: true,
-          reference: _tearOffReferenceFrom?.reference)
+          isStatic: true, isExtensionMember: true, reference: _tearOffReference)
         ..isNonNullableByDefault = library.isNonNullableByDefault;
     }
     return _extensionTearOff;
@@ -640,9 +639,6 @@
       memberBuilder.kind == ProcedureKind.Setter;
 
   @override
-  bool get isFunction => !isProperty;
-
-  @override
   bool isSameDeclaration(ClassMember other) {
     return other is SourceProcedureMember &&
         memberBuilder == other.memberBuilder;
@@ -665,7 +661,7 @@
       int charOffset,
       int charOpenParenOffset,
       int charEndOffset,
-      Procedure referenceFrom,
+      Reference reference,
       [String nativeMethodName,
       this.redirectionTarget])
       : super(
@@ -681,7 +677,7 @@
             charOffset,
             charOpenParenOffset,
             charEndOffset,
-            referenceFrom,
+            reference,
             /* isExtensionInstanceMember = */ false,
             nativeMethodName);
 
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 f6a2aeb..c4c5502 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
@@ -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.9
+
 library fasta.function_type_alias_builder;
 
 import 'package:kernel/ast.dart'
@@ -14,6 +16,7 @@
         Typedef;
 
 import 'package:kernel/type_algebra.dart' show substitute, uniteNullabilities;
+import 'package:kernel/src/legacy_erasure.dart';
 
 import '../fasta_codes.dart'
     show
@@ -163,12 +166,18 @@
       nullability = uniteNullabilities(
           thisType.declaredNullability, nullabilityBuilder.build(library));
     }
+    DartType result;
     if (typedef.typeParameters.isEmpty && arguments == null) {
-      return thisType.withDeclaredNullability(nullability);
+      result = thisType.withDeclaredNullability(nullability);
+    } else {
+      // Otherwise, substitute.
+      result = buildTypesWithBuiltArguments(
+          library, nullability, buildTypeArguments(library, arguments));
     }
-    // Otherwise, substitute.
-    return buildTypesWithBuiltArguments(
-        library, nullability, buildTypeArguments(library, arguments));
+    if (!library.isNonNullableByDefault) {
+      result = legacyErasure(result);
+    }
+    return result;
   }
 
   TypeDeclarationBuilder _cachedUnaliasedDeclaration;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
index d1ff518..2aed213 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_builder.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.9
+
 library fasta.type_builder;
 
 import 'package:kernel/ast.dart' show DartType, Supertype, TypedefType;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index a8c16a1..cdfac5c 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.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.9
+
 library fasta.type_declaration_builder;
 
 import 'package:kernel/ast.dart' show DartType, Nullability;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index b73ea20..d8d4a27 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.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.9
+
 library fasta.type_variable_builder;
 
 import 'package:kernel/ast.dart'
diff --git a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart b/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
index f90ac59..8925e6b 100644
--- a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
+++ b/pkg/front_end/lib/src/fasta/builder/unresolved_type.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.9
+
 library fasta.unresolved_type;
 
 import '../scope.dart';
diff --git a/pkg/front_end/lib/src/fasta/builder/variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/variable_builder.dart
index cc006cb..17eb7f2 100644
--- a/pkg/front_end/lib/src/fasta/builder/variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/variable_builder.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.9
+
 library fasta.kernel_variable_builder;
 
 import 'package:kernel/ast.dart' show VariableDeclaration;
diff --git a/pkg/front_end/lib/src/fasta/builder/void_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/void_type_declaration_builder.dart
index 25c6760..b50507a 100644
--- a/pkg/front_end/lib/src/fasta/builder/void_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/void_type_declaration_builder.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.9
+
 library fasta.void_type_builder;
 
 import 'package:kernel/ast.dart' show DartType;
diff --git a/pkg/front_end/lib/src/fasta/builder_graph.dart b/pkg/front_end/lib/src/fasta/builder_graph.dart
index 79539fd..f6f447a 100644
--- a/pkg/front_end/lib/src/fasta/builder_graph.dart
+++ b/pkg/front_end/lib/src/fasta/builder_graph.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.9
+
 library fasta.builder_graph;
 
 import 'package:kernel/kernel.dart' show LibraryDependency, LibraryPart;
diff --git a/pkg/front_end/lib/src/fasta/command_line_reporting.dart b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
index 1247aea..2b05cc6 100644
--- a/pkg/front_end/lib/src/fasta/command_line_reporting.dart
+++ b/pkg/front_end/lib/src/fasta/command_line_reporting.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.9
+
 /// Provides a default implementation of the report and format methods of
 /// [CompilerContext] that are suitable for command-line tools. The methods in
 /// this library aren't intended to be called directly, instead, one should use
@@ -19,7 +21,7 @@
     show $CARET, $SPACE, $TAB;
 
 import 'package:_fe_analyzer_shared/src/util/colors.dart'
-    show enableColors, green, magenta, red;
+    show enableColors, green, magenta, red, yellow;
 
 import 'package:_fe_analyzer_shared/src/util/relativize.dart'
     show isWindows, relativizeUri;
@@ -73,6 +75,11 @@
           messageText = green(messageText);
           break;
 
+        case Severity.info:
+          messageText = yellow(messageText);
+          break;
+
+        case Severity.ignored:
         default:
           return unhandled("$severity", "format", -1, null);
       }
@@ -145,14 +152,15 @@
     case Severity.error:
     case Severity.internalProblem:
     case Severity.context:
+    case Severity.info:
       return false;
 
     case Severity.warning:
       return hideWarnings;
-
-    default:
-      return unhandled("$severity", "isHidden", -1, null);
+    case Severity.ignored:
+      return true;
   }
+  return unhandled("$severity", "isHidden", -1, null);
 }
 
 /// Are problems of [severity] fatal? That is, should the compiler terminate
@@ -168,12 +176,12 @@
     case Severity.warning:
       return CompilerContext.current.options.throwOnWarningsForDebugging;
 
+    case Severity.info:
+    case Severity.ignored:
     case Severity.context:
       return false;
-
-    default:
-      return unhandled("$severity", "shouldThrowOn", -1, null);
   }
+  return unhandled("$severity", "shouldThrowOn", -1, null);
 }
 
 bool isCompileTimeError(Severity severity) {
@@ -184,6 +192,7 @@
 
     case Severity.warning:
     case Severity.context:
+    case Severity.info:
       return false;
 
     case Severity.ignored:
diff --git a/pkg/front_end/lib/src/fasta/compiler_context.dart b/pkg/front_end/lib/src/fasta/compiler_context.dart
index e64cd29..a1d2005 100644
--- a/pkg/front_end/lib/src/fasta/compiler_context.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_context.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.9
+
 library fasta.compiler_context;
 
 import 'dart:async' show Zone, runZoned;
diff --git a/pkg/front_end/lib/src/fasta/configuration.dart b/pkg/front_end/lib/src/fasta/configuration.dart
index d12a43a..f24e5bf 100644
--- a/pkg/front_end/lib/src/fasta/configuration.dart
+++ b/pkg/front_end/lib/src/fasta/configuration.dart
@@ -9,6 +9,7 @@
   final String dottedName;
   final String condition;
   final String importUri;
+
   Configuration(
       this.charOffset, this.dottedName, this.condition, this.importUri);
 }
diff --git a/pkg/front_end/lib/src/fasta/crash.dart b/pkg/front_end/lib/src/fasta/crash.dart
index 1ad20fc..82e44be 100644
--- a/pkg/front_end/lib/src/fasta/crash.dart
+++ b/pkg/front_end/lib/src/fasta/crash.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.9
+
 library fasta.crash;
 
 import 'dart:convert' show jsonEncode;
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 a548f80..93ee939 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
@@ -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.9
+
 library fasta.dill_class_builder;
 
 import 'package:kernel/ast.dart' hide MapEntry;
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 a114dc6..b460387 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
@@ -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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart
index 02aa055..d946f72 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_extension_member_builder.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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
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 08d1655..f4ddeff 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
@@ -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.9
+
 library fasta.dill_library_builder;
 
 import 'dart:convert' show jsonDecode;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
index 2ce2498..8cbf077 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_loader.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.9
+
 library fasta.dill_loader;
 
 import 'package:kernel/ast.dart' show Class, Component, DartType, Library;
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 331b581..de71663d 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
@@ -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.9
+
 library fasta.dill_member_builder;
 
 import 'package:kernel/ast.dart'
@@ -27,7 +29,7 @@
 
   DillMemberBuilder(Member member, Builder parent)
       : modifiers = computeModifiers(member),
-        super(parent, member.fileOffset);
+        super(parent, member.fileOffset, member.fileUri);
 
   Member get member;
 
@@ -252,6 +254,7 @@
   bool get isSynthesized {
     Member member = memberBuilder.member;
     return member is Procedure &&
+        // TODO(johnniwinther): Should this just be `member.isSynthesized`?
         (member.isMemberSignature ||
             (member.isForwardingStub && !member.isForwardingSemiStub));
   }
@@ -266,9 +269,6 @@
   }
 
   @override
-  bool get isFunction => !isProperty;
-
-  @override
   void inferType(ClassHierarchyBuilder hierarchy) {
     // Do nothing; this is only for source members.
   }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_target.dart b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
index 52fa515..9901f81 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_target.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_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.9
+
 library fasta.dill_target;
 
 import 'package:front_end/src/fasta/builder/library_builder.dart'
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 9cf8bad..9020e68 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
@@ -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.9
+
 library fasta.dill_typedef_builder;
 
 import 'package:kernel/ast.dart' show DartType, InvalidType, NullType, Typedef;
diff --git a/pkg/front_end/lib/src/fasta/export.dart b/pkg/front_end/lib/src/fasta/export.dart
index e57cf8d..8ed7105 100644
--- a/pkg/front_end/lib/src/fasta/export.dart
+++ b/pkg/front_end/lib/src/fasta/export.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.9
+
 library fasta.export;
 
 import 'builder/builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes.dart b/pkg/front_end/lib/src/fasta/fasta_codes.dart
index 50f79c1..446cd72 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes.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.9
+
 library fasta.codes;
 
 import 'package:_fe_analyzer_shared/src/messages/codes.dart'
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
index f7adca0..0d94cfb 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -1,7 +1,9 @@
-// Copyright (c) 2018, 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.
 
+// @dart = 2.9
+
 // NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
 //
 // Instead modify 'pkg/front_end/messages.yaml' and run
@@ -32,7 +34,6 @@
         bool isNonNullableByDefault)> codeAmbiguousExtensionMethod = const Code<
     Message Function(String name, DartType _type, bool isNonNullableByDefault)>(
   "AmbiguousExtensionMethod",
-  templateAmbiguousExtensionMethod,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -72,7 +73,6 @@
         Message Function(
             String name, DartType _type, bool isNonNullableByDefault)>(
   "AmbiguousExtensionOperator",
-  templateAmbiguousExtensionOperator,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -112,7 +112,6 @@
         Message Function(
             String name, DartType _type, bool isNonNullableByDefault)>(
   "AmbiguousExtensionProperty",
-  templateAmbiguousExtensionProperty,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -148,8 +147,7 @@
             bool isNonNullableByDefault)> codeAmbiguousSupertypes =
     const Code<
             Message Function(String name, DartType _type, DartType _type2,
-                bool isNonNullableByDefault)>(
-        "AmbiguousSupertypes", templateAmbiguousSupertypes,
+                bool isNonNullableByDefault)>("AmbiguousSupertypes",
         analyzerCodes: <String>["AMBIGUOUS_SUPERTYPES"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -186,7 +184,7 @@
     codeArgumentTypeNotAssignable = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "ArgumentTypeNotAssignable", templateArgumentTypeNotAssignable,
+        "ArgumentTypeNotAssignable",
         analyzerCodes: <String>["ARGUMENT_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -223,7 +221,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "ArgumentTypeNotAssignableNullability",
-        templateArgumentTypeNotAssignableNullability,
         analyzerCodes: <String>["ARGUMENT_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -254,7 +251,6 @@
     codeArgumentTypeNotAssignableNullabilityNull =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
         "ArgumentTypeNotAssignableNullabilityNull",
-        templateArgumentTypeNotAssignableNullabilityNull,
         analyzerCodes: <String>["ARGUMENT_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -290,7 +286,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "ArgumentTypeNotAssignableNullabilityNullType",
-        templateArgumentTypeNotAssignableNullabilityNullType,
         analyzerCodes: <String>["ARGUMENT_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -327,7 +322,6 @@
             Message Function(DartType _type, DartType _type2, DartType _type3,
                 DartType _type4, bool isNonNullableByDefault)>(
         "ArgumentTypeNotAssignablePartNullability",
-        templateArgumentTypeNotAssignablePartNullability,
         analyzerCodes: <String>["ARGUMENT_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -372,7 +366,6 @@
     codeConstEvalCaseImplementsEqual = const Code<
         Message Function(Constant _constant, bool isNonNullableByDefault)>(
   "ConstEvalCaseImplementsEqual",
-  templateConstEvalCaseImplementsEqual,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -401,7 +394,7 @@
 const Code<Message Function(Constant _constant, bool isNonNullableByDefault)>
     codeConstEvalDuplicateElement = const Code<
             Message Function(Constant _constant, bool isNonNullableByDefault)>(
-        "ConstEvalDuplicateElement", templateConstEvalDuplicateElement,
+        "ConstEvalDuplicateElement",
         analyzerCodes: <String>["EQUAL_ELEMENTS_IN_CONST_SET"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -430,7 +423,7 @@
 const Code<Message Function(Constant _constant, bool isNonNullableByDefault)>
     codeConstEvalDuplicateKey = const Code<
             Message Function(Constant _constant, bool isNonNullableByDefault)>(
-        "ConstEvalDuplicateKey", templateConstEvalDuplicateKey,
+        "ConstEvalDuplicateKey",
         analyzerCodes: <String>["EQUAL_KEYS_IN_CONST_MAP"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -460,7 +453,6 @@
     codeConstEvalElementImplementsEqual = const Code<
             Message Function(Constant _constant, bool isNonNullableByDefault)>(
         "ConstEvalElementImplementsEqual",
-        templateConstEvalElementImplementsEqual,
         analyzerCodes: <String>["CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -489,7 +481,6 @@
     codeConstEvalFreeTypeParameter =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "ConstEvalFreeTypeParameter",
-  templateConstEvalFreeTypeParameter,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -524,7 +515,6 @@
         Message Function(String stringOKEmpty, Constant _constant,
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "ConstEvalInvalidBinaryOperandType",
-  templateConstEvalInvalidBinaryOperandType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -534,6 +524,7 @@
     DartType _type,
     DartType _type2,
     bool isNonNullableByDefault) {
+  // ignore: unnecessary_null_comparison
   if (stringOKEmpty == null || stringOKEmpty.isEmpty) stringOKEmpty = '(empty)';
   TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
   List<Object> constantParts = labeler.labelConstant(_constant);
@@ -573,7 +564,6 @@
         Message Function(
             Constant _constant, DartType _type, bool isNonNullableByDefault)>(
   "ConstEvalInvalidEqualsOperandType",
-  templateConstEvalInvalidEqualsOperandType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -610,12 +600,12 @@
             Message Function(String stringOKEmpty, Constant _constant,
                 bool isNonNullableByDefault)>(
         "ConstEvalInvalidMethodInvocation",
-        templateConstEvalInvalidMethodInvocation,
         analyzerCodes: <String>["UNDEFINED_OPERATOR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalInvalidMethodInvocation(
     String stringOKEmpty, Constant _constant, bool isNonNullableByDefault) {
+  // ignore: unnecessary_null_comparison
   if (stringOKEmpty == null || stringOKEmpty.isEmpty) stringOKEmpty = '(empty)';
   TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
   List<Object> constantParts = labeler.labelConstant(_constant);
@@ -644,13 +634,13 @@
             bool isNonNullableByDefault)> codeConstEvalInvalidPropertyGet =
     const Code<
             Message Function(String stringOKEmpty, Constant _constant,
-                bool isNonNullableByDefault)>(
-        "ConstEvalInvalidPropertyGet", templateConstEvalInvalidPropertyGet,
+                bool isNonNullableByDefault)>("ConstEvalInvalidPropertyGet",
         analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalInvalidPropertyGet(
     String stringOKEmpty, Constant _constant, bool isNonNullableByDefault) {
+  // ignore: unnecessary_null_comparison
   if (stringOKEmpty == null || stringOKEmpty.isEmpty) stringOKEmpty = '(empty)';
   TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
   List<Object> constantParts = labeler.labelConstant(_constant);
@@ -678,7 +668,6 @@
     codeConstEvalInvalidStringInterpolationOperand = const Code<
             Message Function(Constant _constant, bool isNonNullableByDefault)>(
         "ConstEvalInvalidStringInterpolationOperand",
-        templateConstEvalInvalidStringInterpolationOperand,
         analyzerCodes: <String>["CONST_EVAL_TYPE_BOOL_NUM_STRING"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -708,7 +697,7 @@
 const Code<Message Function(Constant _constant, bool isNonNullableByDefault)>
     codeConstEvalInvalidSymbolName = const Code<
             Message Function(Constant _constant, bool isNonNullableByDefault)>(
-        "ConstEvalInvalidSymbolName", templateConstEvalInvalidSymbolName,
+        "ConstEvalInvalidSymbolName",
         analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -745,7 +734,6 @@
     Message Function(Constant _constant, DartType _type, DartType _type2,
         bool isNonNullableByDefault)>(
   "ConstEvalInvalidType",
-  templateConstEvalInvalidType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -778,7 +766,7 @@
 const Code<Message Function(Constant _constant, bool isNonNullableByDefault)>
     codeConstEvalKeyImplementsEqual = const Code<
             Message Function(Constant _constant, bool isNonNullableByDefault)>(
-        "ConstEvalKeyImplementsEqual", templateConstEvalKeyImplementsEqual,
+        "ConstEvalKeyImplementsEqual",
         analyzerCodes: <String>[
       "CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS"
     ]);
@@ -818,7 +806,7 @@
     codeDeferredTypeAnnotation = const Code<
             Message Function(
                 DartType _type, String name, bool isNonNullableByDefault)>(
-        "DeferredTypeAnnotation", templateDeferredTypeAnnotation,
+        "DeferredTypeAnnotation",
         analyzerCodes: <String>["TYPE_ANNOTATION_DEFERRED_CLASS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -855,7 +843,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "FfiDartTypeMismatch",
-  templateFfiDartTypeMismatch,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -885,7 +872,6 @@
     codeFfiExpectedExceptionalReturn =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "FfiExpectedExceptionalReturn",
-  templateFfiExpectedExceptionalReturn,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -914,7 +900,6 @@
     codeFfiExpectedNoExceptionalReturn =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "FfiExpectedNoExceptionalReturn",
-  templateFfiExpectedNoExceptionalReturn,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -931,6 +916,35 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
+    templateFfiNonConstantTypeArgumentWarning = const Template<
+            Message Function(DartType _type, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""Support for using non-constant type arguments '#type' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type.""",
+        withArguments: _withArgumentsFfiNonConstantTypeArgumentWarning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, bool isNonNullableByDefault)>
+    codeFfiNonConstantTypeArgumentWarning =
+    const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
+        "FfiNonConstantTypeArgumentWarning",
+        analyzerCodes: <String>["NON_CONSTANT_TYPE_ARGUMENT_WARNING"],
+        severity: Severity.info);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiNonConstantTypeArgumentWarning(
+    DartType _type, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeFfiNonConstantTypeArgumentWarning,
+      message:
+          """Support for using non-constant type arguments '${type}' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type.""" +
+              labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         DartType _type,
@@ -946,7 +960,6 @@
     codeFfiTypeInvalid =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "FfiTypeInvalid",
-  templateFfiTypeInvalid,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -983,7 +996,6 @@
     Message Function(DartType _type, DartType _type2, DartType _type3,
         bool isNonNullableByDefault)>(
   "FfiTypeMismatch",
-  templateFfiTypeMismatch,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1023,7 +1035,6 @@
         Message Function(
             String name, DartType _type, bool isNonNullableByDefault)>(
   "FieldNonNullableNotInitializedByConstructorError",
-  templateFieldNonNullableNotInitializedByConstructorError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1060,7 +1071,6 @@
         Message Function(
             String name, DartType _type, bool isNonNullableByDefault)>(
   "FieldNonNullableWithoutInitializerError",
-  templateFieldNonNullableWithoutInitializerError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1098,7 +1108,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "ForInLoopElementTypeNotAssignable",
-        templateForInLoopElementTypeNotAssignable,
         analyzerCodes: <String>["FOR_IN_OF_INVALID_ELEMENT_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1138,7 +1147,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "ForInLoopElementTypeNotAssignableNullability",
-        templateForInLoopElementTypeNotAssignableNullability,
         analyzerCodes: <String>["FOR_IN_OF_INVALID_ELEMENT_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1178,7 +1186,6 @@
             Message Function(DartType _type, DartType _type2, DartType _type3,
                 DartType _type4, bool isNonNullableByDefault)>(
         "ForInLoopElementTypeNotAssignablePartNullability",
-        templateForInLoopElementTypeNotAssignablePartNullability,
         analyzerCodes: <String>["FOR_IN_OF_INVALID_ELEMENT_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1228,7 +1235,7 @@
     codeForInLoopTypeNotIterable = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "ForInLoopTypeNotIterable", templateForInLoopTypeNotIterable,
+        "ForInLoopTypeNotIterable",
         analyzerCodes: <String>["FOR_IN_OF_INVALID_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1265,7 +1272,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "ForInLoopTypeNotIterableNullability",
-        templateForInLoopTypeNotIterableNullability,
         analyzerCodes: <String>["FOR_IN_OF_INVALID_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1302,7 +1308,6 @@
             Message Function(DartType _type, DartType _type2, DartType _type3,
                 DartType _type4, bool isNonNullableByDefault)>(
         "ForInLoopTypeNotIterablePartNullability",
-        templateForInLoopTypeNotIterablePartNullability,
         analyzerCodes: <String>["FOR_IN_OF_INVALID_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1349,7 +1354,6 @@
     codeGenericFunctionTypeInferredAsActualTypeArgument =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
         "GenericFunctionTypeInferredAsActualTypeArgument",
-        templateGenericFunctionTypeInferredAsActualTypeArgument,
         analyzerCodes: <String>["GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1380,7 +1384,7 @@
 const Code<Message Function(DartType _type, bool isNonNullableByDefault)>
     codeImplicitCallOfNonMethod =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
-        "ImplicitCallOfNonMethod", templateImplicitCallOfNonMethod,
+        "ImplicitCallOfNonMethod",
         analyzerCodes: <String>["IMPLICIT_CALL_OF_NON_METHOD"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1413,7 +1417,6 @@
     codeImplicitReturnNull =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "ImplicitReturnNull",
-  templateImplicitReturnNull,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1448,7 +1451,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "IncompatibleRedirecteeFunctionType",
-        templateIncompatibleRedirecteeFunctionType,
         analyzerCodes: <String>["REDIRECT_TO_INVALID_TYPE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1484,9 +1486,12 @@
         Message Function(DartType _type, DartType _type2, String name,
             String name2, bool isNonNullableByDefault)>
     codeIncorrectTypeArgument = const Code<
-            Message Function(DartType _type, DartType _type2, String name,
-                String name2, bool isNonNullableByDefault)>(
-        "IncorrectTypeArgument", templateIncorrectTypeArgument,
+            Message Function(
+                DartType _type,
+                DartType _type2,
+                String name,
+                String name2,
+                bool isNonNullableByDefault)>("IncorrectTypeArgument",
         analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1535,7 +1540,6 @@
             Message Function(DartType _type, DartType _type2, String name,
                 String name2, bool isNonNullableByDefault)>(
         "IncorrectTypeArgumentInReturnType",
-        templateIncorrectTypeArgumentInReturnType,
         analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1607,7 +1611,7 @@
                 String name3,
                 String name4,
                 bool isNonNullableByDefault)>(
-        "IncorrectTypeArgumentInSupertype", templateIncorrectTypeArgumentInSupertype,
+        "IncorrectTypeArgumentInSupertype",
         analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1692,7 +1696,7 @@
                 String name3,
                 String name4,
                 bool isNonNullableByDefault)>(
-        "IncorrectTypeArgumentInSupertypeInferred", templateIncorrectTypeArgumentInSupertypeInferred,
+        "IncorrectTypeArgumentInSupertypeInferred",
         analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1751,9 +1755,12 @@
         Message Function(DartType _type, DartType _type2, String name,
             String name2, bool isNonNullableByDefault)>
     codeIncorrectTypeArgumentInferred = const Code<
-            Message Function(DartType _type, DartType _type2, String name,
-                String name2, bool isNonNullableByDefault)>(
-        "IncorrectTypeArgumentInferred", templateIncorrectTypeArgumentInferred,
+            Message Function(
+                DartType _type,
+                DartType _type2,
+                String name,
+                String name2,
+                bool isNonNullableByDefault)>("IncorrectTypeArgumentInferred",
         analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1799,10 +1806,13 @@
         Message Function(DartType _type, DartType _type2, String name,
             DartType _type3, String name2, bool isNonNullableByDefault)>
     codeIncorrectTypeArgumentQualified = const Code<
-            Message Function(DartType _type, DartType _type2, String name,
-                DartType _type3, String name2, bool isNonNullableByDefault)>(
-        "IncorrectTypeArgumentQualified",
-        templateIncorrectTypeArgumentQualified,
+            Message Function(
+                DartType _type,
+                DartType _type2,
+                String name,
+                DartType _type3,
+                String name2,
+                bool isNonNullableByDefault)>("IncorrectTypeArgumentQualified",
         analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1858,7 +1868,7 @@
     codeIncorrectTypeArgumentQualifiedInferred = const Code<
             Message Function(DartType _type, DartType _type2, String name,
                 DartType _type3, String name2, bool isNonNullableByDefault)>(
-        "IncorrectTypeArgumentQualifiedInferred", templateIncorrectTypeArgumentQualifiedInferred,
+        "IncorrectTypeArgumentQualifiedInferred",
         analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1914,7 +1924,6 @@
     const Code<
             Message Function(String name, DartType _type, DartType _type2,
                 bool isNonNullableByDefault)>("InitializingFormalTypeMismatch",
-        templateInitializingFormalTypeMismatch,
         analyzerCodes: <String>["INVALID_PARAMETER_DECLARATION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1954,7 +1963,6 @@
             Message Function(
                 String string, DartType _type, bool isNonNullableByDefault)>(
         "InternalProblemUnsupportedNullability",
-        templateInternalProblemUnsupportedNullability,
         severity: Severity.internalProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1989,7 +1997,7 @@
     codeInvalidAssignmentError = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidAssignmentError", templateInvalidAssignmentError,
+        "InvalidAssignmentError",
         analyzerCodes: <String>["INVALID_ASSIGNMENT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2026,7 +2034,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "InvalidAssignmentErrorNullability",
-        templateInvalidAssignmentErrorNullability,
         analyzerCodes: <String>["INVALID_ASSIGNMENT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2057,7 +2064,6 @@
     codeInvalidAssignmentErrorNullabilityNull =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
         "InvalidAssignmentErrorNullabilityNull",
-        templateInvalidAssignmentErrorNullabilityNull,
         analyzerCodes: <String>["INVALID_ASSIGNMENT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2092,7 +2098,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "InvalidAssignmentErrorNullabilityNullType",
-        templateInvalidAssignmentErrorNullabilityNullType,
         analyzerCodes: <String>["INVALID_ASSIGNMENT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2129,7 +2134,6 @@
             Message Function(DartType _type, DartType _type2, DartType _type3,
                 DartType _type4, bool isNonNullableByDefault)>(
         "InvalidAssignmentErrorPartNullability",
-        templateInvalidAssignmentErrorPartNullability,
         analyzerCodes: <String>["INVALID_ASSIGNMENT"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2182,7 +2186,7 @@
     codeInvalidCastFunctionExpr = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidCastFunctionExpr", templateInvalidCastFunctionExpr,
+        "InvalidCastFunctionExpr",
         analyzerCodes: <String>["INVALID_CAST_FUNCTION_EXPR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2226,7 +2230,7 @@
     codeInvalidCastLiteralList = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidCastLiteralList", templateInvalidCastLiteralList,
+        "InvalidCastLiteralList",
         analyzerCodes: <String>["INVALID_CAST_LITERAL_LIST"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2270,7 +2274,7 @@
     codeInvalidCastLiteralMap = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidCastLiteralMap", templateInvalidCastLiteralMap,
+        "InvalidCastLiteralMap",
         analyzerCodes: <String>["INVALID_CAST_LITERAL_MAP"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2314,7 +2318,7 @@
     codeInvalidCastLiteralSet = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidCastLiteralSet", templateInvalidCastLiteralSet,
+        "InvalidCastLiteralSet",
         analyzerCodes: <String>["INVALID_CAST_LITERAL_SET"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2358,7 +2362,7 @@
     codeInvalidCastLocalFunction = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidCastLocalFunction", templateInvalidCastLocalFunction,
+        "InvalidCastLocalFunction",
         analyzerCodes: <String>["INVALID_CAST_FUNCTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2402,7 +2406,7 @@
     codeInvalidCastNewExpr = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidCastNewExpr", templateInvalidCastNewExpr,
+        "InvalidCastNewExpr",
         analyzerCodes: <String>["INVALID_CAST_NEW_EXPR"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2443,7 +2447,7 @@
     codeInvalidCastStaticMethod = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidCastStaticMethod", templateInvalidCastStaticMethod,
+        "InvalidCastStaticMethod",
         analyzerCodes: <String>["INVALID_CAST_METHOD"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2482,7 +2486,7 @@
     codeInvalidCastTopLevelFunction = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "InvalidCastTopLevelFunction", templateInvalidCastTopLevelFunction,
+        "InvalidCastTopLevelFunction",
         analyzerCodes: <String>["INVALID_CAST_FUNCTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2519,7 +2523,6 @@
     Message Function(DartType _type, String name, DartType _type2, String name2,
         bool isNonNullableByDefault)>(
   "InvalidGetterSetterType",
-  templateInvalidGetterSetterType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2565,7 +2568,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeBothInheritedField",
-  templateInvalidGetterSetterTypeBothInheritedField,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2612,7 +2614,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeBothInheritedFieldLegacy",
-  templateInvalidGetterSetterTypeBothInheritedFieldLegacy,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2663,7 +2664,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeBothInheritedGetter",
-  templateInvalidGetterSetterTypeBothInheritedGetter,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2710,7 +2710,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeBothInheritedGetterLegacy",
-  templateInvalidGetterSetterTypeBothInheritedGetterLegacy,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2760,7 +2759,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeFieldInherited",
-  templateInvalidGetterSetterTypeFieldInherited,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2807,7 +2805,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeFieldInheritedLegacy",
-  templateInvalidGetterSetterTypeFieldInheritedLegacy,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2857,7 +2854,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeGetterInherited",
-  templateInvalidGetterSetterTypeGetterInherited,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2904,7 +2900,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeGetterInheritedLegacy",
-  templateInvalidGetterSetterTypeGetterInheritedLegacy,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2954,7 +2949,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeLegacy",
-  templateInvalidGetterSetterTypeLegacy,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3001,7 +2995,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeSetterInheritedField",
-  templateInvalidGetterSetterTypeSetterInheritedField,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3052,7 +3045,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeSetterInheritedFieldLegacy",
-  templateInvalidGetterSetterTypeSetterInheritedFieldLegacy,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3103,7 +3095,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeSetterInheritedGetter",
-  templateInvalidGetterSetterTypeSetterInheritedGetter,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3154,7 +3145,6 @@
         Message Function(DartType _type, String name, DartType _type2,
             String name2, bool isNonNullableByDefault)>(
   "InvalidGetterSetterTypeSetterInheritedGetterLegacy",
-  templateInvalidGetterSetterTypeSetterInheritedGetterLegacy,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3206,7 +3196,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "InvalidReturn",
-  templateInvalidReturn,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3245,7 +3234,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "InvalidReturnAsync",
-  templateInvalidReturnAsync,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3282,7 +3270,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "InvalidReturnAsyncNullability",
-  templateInvalidReturnAsyncNullability,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3313,7 +3300,6 @@
     codeInvalidReturnAsyncNullabilityNull =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "InvalidReturnAsyncNullabilityNull",
-  templateInvalidReturnAsyncNullabilityNull,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3348,7 +3334,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "InvalidReturnAsyncNullabilityNullType",
-  templateInvalidReturnAsyncNullabilityNullType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3385,7 +3370,6 @@
         Message Function(DartType _type, DartType _type2, DartType _type3,
             DartType _type4, bool isNonNullableByDefault)>(
   "InvalidReturnAsyncPartNullability",
-  templateInvalidReturnAsyncPartNullability,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3435,7 +3419,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "InvalidReturnNullability",
-  templateInvalidReturnNullability,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3466,7 +3449,6 @@
     codeInvalidReturnNullabilityNull =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "InvalidReturnNullabilityNull",
-  templateInvalidReturnNullabilityNull,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3501,7 +3483,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "InvalidReturnNullabilityNullType",
-  templateInvalidReturnNullabilityNullType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3538,7 +3519,6 @@
         Message Function(DartType _type, DartType _type2, DartType _type3,
             DartType _type4, bool isNonNullableByDefault)>(
   "InvalidReturnPartNullability",
-  templateInvalidReturnPartNullability,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3588,7 +3568,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "MainWrongParameterType",
-  templateMainWrongParameterType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3625,7 +3604,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "MainWrongParameterTypeExported",
-  templateMainWrongParameterTypeExported,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3662,7 +3640,6 @@
             Message Function(DartType _type, DartType _type2, DartType _type3,
                 bool isNonNullableByDefault)>(
         "MixinApplicationIncompatibleSupertype",
-        templateMixinApplicationIncompatibleSupertype,
         analyzerCodes: <String>["MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3700,8 +3677,7 @@
             bool isNonNullableByDefault)> codeMixinInferenceNoMatchingClass =
     const Code<
             Message Function(String name, String name2, DartType _type,
-                bool isNonNullableByDefault)>(
-        "MixinInferenceNoMatchingClass", templateMixinInferenceNoMatchingClass,
+                bool isNonNullableByDefault)>("MixinInferenceNoMatchingClass",
         analyzerCodes: <String>["MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3733,7 +3709,6 @@
     codeNonNullAwareSpreadIsNull =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "NonNullAwareSpreadIsNull",
-  templateNonNullAwareSpreadIsNull,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3766,7 +3741,7 @@
     codeNonNullableInNullAware = const Code<
             Message Function(
                 String name, DartType _type, bool isNonNullableByDefault)>(
-        "NonNullableInNullAware", templateNonNullableInNullAware,
+        "NonNullableInNullAware",
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3798,7 +3773,6 @@
     codeNullableExpressionCallError =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "NullableExpressionCallError",
-  templateNullableExpressionCallError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3833,7 +3807,6 @@
         bool isNonNullableByDefault)> codeNullableMethodCallError = const Code<
     Message Function(String name, DartType _type, bool isNonNullableByDefault)>(
   "NullableMethodCallError",
-  templateNullableMethodCallError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3871,7 +3844,6 @@
         Message Function(
             String name, DartType _type, bool isNonNullableByDefault)>(
   "NullableOperatorCallError",
-  templateNullableOperatorCallError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3909,7 +3881,6 @@
         Message Function(
             String name, DartType _type, bool isNonNullableByDefault)>(
   "NullablePropertyAccessError",
-  templateNullablePropertyAccessError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3950,7 +3921,6 @@
             Message Function(
                 String name, DartType _type, bool isNonNullableByDefault)>(
         "OptionalNonNullableWithoutInitializerError",
-        templateOptionalNonNullableWithoutInitializerError,
         analyzerCodes: <String>["MISSING_DEFAULT_VALUE_FOR_PARAMETER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3987,9 +3957,13 @@
         Message Function(String name, String name2, DartType _type,
             DartType _type2, String name3, bool isNonNullableByDefault)>
     codeOverrideTypeMismatchParameter = const Code<
-            Message Function(String name, String name2, DartType _type,
-                DartType _type2, String name3, bool isNonNullableByDefault)>(
-        "OverrideTypeMismatchParameter", templateOverrideTypeMismatchParameter,
+            Message Function(
+                String name,
+                String name2,
+                DartType _type,
+                DartType _type2,
+                String name3,
+                bool isNonNullableByDefault)>("OverrideTypeMismatchParameter",
         analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4042,10 +4016,12 @@
         Message Function(String name, DartType _type, DartType _type2,
             String name2, bool isNonNullableByDefault)>
     codeOverrideTypeMismatchReturnType = const Code<
-            Message Function(String name, DartType _type, DartType _type2,
-                String name2, bool isNonNullableByDefault)>(
-        "OverrideTypeMismatchReturnType",
-        templateOverrideTypeMismatchReturnType,
+            Message Function(
+                String name,
+                DartType _type,
+                DartType _type2,
+                String name2,
+                bool isNonNullableByDefault)>("OverrideTypeMismatchReturnType",
         analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4093,9 +4069,12 @@
         Message Function(String name, DartType _type, DartType _type2,
             String name2, bool isNonNullableByDefault)>
     codeOverrideTypeMismatchSetter = const Code<
-            Message Function(String name, DartType _type, DartType _type2,
-                String name2, bool isNonNullableByDefault)>(
-        "OverrideTypeMismatchSetter", templateOverrideTypeMismatchSetter,
+            Message Function(
+                String name,
+                DartType _type,
+                DartType _type2,
+                String name2,
+                bool isNonNullableByDefault)>("OverrideTypeMismatchSetter",
         analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4141,7 +4120,6 @@
         Message Function(DartType _type, String name, String name2,
             DartType _type2, String name3, bool isNonNullableByDefault)>(
   "OverrideTypeVariablesBoundMismatch",
-  templateOverrideTypeVariablesBoundMismatch,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4196,7 +4174,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "RedirectingFactoryIncompatibleTypeArgument",
-        templateRedirectingFactoryIncompatibleTypeArgument,
         analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4232,7 +4209,7 @@
     codeSpreadElementTypeMismatch = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "SpreadElementTypeMismatch", templateSpreadElementTypeMismatch,
+        "SpreadElementTypeMismatch",
         analyzerCodes: <String>["LIST_ELEMENT_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4269,7 +4246,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "SpreadElementTypeMismatchNullability",
-        templateSpreadElementTypeMismatchNullability,
         analyzerCodes: <String>["LIST_ELEMENT_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4306,7 +4282,6 @@
             Message Function(DartType _type, DartType _type2, DartType _type3,
                 DartType _type4, bool isNonNullableByDefault)>(
         "SpreadElementTypeMismatchPartNullability",
-        templateSpreadElementTypeMismatchPartNullability,
         analyzerCodes: <String>["LIST_ELEMENT_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4356,7 +4331,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "SpreadMapEntryElementKeyTypeMismatch",
-        templateSpreadMapEntryElementKeyTypeMismatch,
         analyzerCodes: <String>["MAP_KEY_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4394,7 +4368,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "SpreadMapEntryElementKeyTypeMismatchNullability",
-        templateSpreadMapEntryElementKeyTypeMismatchNullability,
         analyzerCodes: <String>["MAP_KEY_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4433,7 +4406,6 @@
             Message Function(DartType _type, DartType _type2, DartType _type3,
                 DartType _type4, bool isNonNullableByDefault)>(
         "SpreadMapEntryElementKeyTypeMismatchPartNullability",
-        templateSpreadMapEntryElementKeyTypeMismatchPartNullability,
         analyzerCodes: <String>["MAP_KEY_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4483,7 +4455,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "SpreadMapEntryElementValueTypeMismatch",
-        templateSpreadMapEntryElementValueTypeMismatch,
         analyzerCodes: <String>["MAP_VALUE_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4521,7 +4492,6 @@
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         "SpreadMapEntryElementValueTypeMismatchNullability",
-        templateSpreadMapEntryElementValueTypeMismatchNullability,
         analyzerCodes: <String>["MAP_VALUE_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4560,7 +4530,6 @@
             Message Function(DartType _type, DartType _type2, DartType _type3,
                 DartType _type4, bool isNonNullableByDefault)>(
         "SpreadMapEntryElementValueTypeMismatchPartNullability",
-        templateSpreadMapEntryElementValueTypeMismatchPartNullability,
         analyzerCodes: <String>["MAP_VALUE_TYPE_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4604,7 +4573,6 @@
     codeSpreadMapEntryTypeMismatch =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "SpreadMapEntryTypeMismatch",
-  templateSpreadMapEntryTypeMismatch,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4636,7 +4604,6 @@
     codeSpreadTypeMismatch =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "SpreadTypeMismatch",
-  templateSpreadTypeMismatch,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4654,6 +4621,44 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
+    Message Function(
+        DartType _type,
+        DartType _type2,
+        bool
+            isNonNullableByDefault)> templateSuperBoundedHint = const Template<
+        Message Function(
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>(
+    messageTemplate:
+        r"""If you want '#type' to be a super-bounded type, note that the inverted type '#type2' must then satisfy its bounds, which it does not.""",
+    withArguments: _withArgumentsSuperBoundedHint);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>
+    codeSuperBoundedHint = const Code<
+            Message Function(
+                DartType _type, DartType _type2, bool isNonNullableByDefault)>(
+        "SuperBoundedHint",
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSuperBoundedHint(
+    DartType _type, DartType _type2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeSuperBoundedHint,
+      message:
+          """If you want '${type}' to be a super-bounded type, note that the inverted type '${type2}' must then satisfy its bounds, which it does not.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>
     templateSwitchExpressionNotAssignable = const Template<
@@ -4670,7 +4675,7 @@
     codeSwitchExpressionNotAssignable = const Code<
             Message Function(
                 DartType _type, DartType _type2, bool isNonNullableByDefault)>(
-        "SwitchExpressionNotAssignable", templateSwitchExpressionNotAssignable,
+        "SwitchExpressionNotAssignable",
         analyzerCodes: <String>["SWITCH_EXPRESSION_NOT_ASSIGNABLE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4707,7 +4712,6 @@
         Message Function(
             DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "SwitchExpressionNotSubtype",
-  templateSwitchExpressionNotSubtype,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4738,7 +4742,6 @@
     codeThrowingNotAssignableToObjectError =
     const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
   "ThrowingNotAssignableToObjectError",
-  templateThrowingNotAssignableToObjectError,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4776,7 +4779,7 @@
     codeUndefinedGetter = const Code<
             Message Function(
                 String name, DartType _type, bool isNonNullableByDefault)>(
-        "UndefinedGetter", templateUndefinedGetter,
+        "UndefinedGetter",
         analyzerCodes: <String>["UNDEFINED_GETTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4818,7 +4821,7 @@
     codeUndefinedMethod = const Code<
             Message Function(
                 String name, DartType _type, bool isNonNullableByDefault)>(
-        "UndefinedMethod", templateUndefinedMethod,
+        "UndefinedMethod",
         analyzerCodes: <String>["UNDEFINED_METHOD"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4860,7 +4863,7 @@
     codeUndefinedOperator = const Code<
             Message Function(
                 String name, DartType _type, bool isNonNullableByDefault)>(
-        "UndefinedOperator", templateUndefinedOperator,
+        "UndefinedOperator",
         analyzerCodes: <String>["UNDEFINED_METHOD"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -4902,7 +4905,7 @@
     codeUndefinedSetter = const Code<
             Message Function(
                 String name, DartType _type, bool isNonNullableByDefault)>(
-        "UndefinedSetter", templateUndefinedSetter,
+        "UndefinedSetter",
         analyzerCodes: <String>["UNDEFINED_SETTER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/get_dependencies.dart b/pkg/front_end/lib/src/fasta/get_dependencies.dart
index 3a23778..903c1b0 100644
--- a/pkg/front_end/lib/src/fasta/get_dependencies.dart
+++ b/pkg/front_end/lib/src/fasta/get_dependencies.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.9
+
 library fasta.get_dependencies;
 
 import 'package:kernel/kernel.dart' show Component, loadComponentFromBytes;
diff --git a/pkg/front_end/lib/src/fasta/hybrid_file_system.dart b/pkg/front_end/lib/src/fasta/hybrid_file_system.dart
index 3a78a1c..9f1a08b 100644
--- a/pkg/front_end/lib/src/fasta/hybrid_file_system.dart
+++ b/pkg/front_end/lib/src/fasta/hybrid_file_system.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.9
+
 /// A memory + physical file system used to mock input for tests but provide
 /// sdk sources from disk.
 library front_end.src.hybrid_file_system;
diff --git a/pkg/front_end/lib/src/fasta/identifiers.dart b/pkg/front_end/lib/src/fasta/identifiers.dart
index 644cd6a..f7dcd4f 100644
--- a/pkg/front_end/lib/src/fasta/identifiers.dart
+++ b/pkg/front_end/lib/src/fasta/identifiers.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.9
+
 library fasta.qualified_name;
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
@@ -11,62 +13,31 @@
 import 'problems.dart' show unhandled, unsupported;
 
 class Identifier {
-  final String name;
-  final int charOffset;
+  final Token token;
 
-  Identifier(Token token)
-      : name = token.lexeme,
-        charOffset = token.charOffset;
+  Identifier(this.token);
 
-  Identifier._(this.name, this.charOffset);
+  String get name => token.lexeme;
 
-  factory Identifier.preserveToken(Token token) {
-    return new _TokenIdentifier(token);
-  }
+  int get charOffset => token.charOffset;
 
   Expression get initializer => null;
 
   int get endCharOffset => charOffset + name.length;
 
   QualifiedName withQualifier(Object qualifier) {
-    return new QualifiedName._(qualifier, name, charOffset);
+    return new QualifiedName(qualifier, token);
   }
 
   @override
   String toString() => "identifier($name)";
 }
 
-class _TokenIdentifier implements Identifier {
-  final Token token;
-
-  _TokenIdentifier(this.token);
-
-  @override
-  String get name => token.lexeme;
-
-  @override
-  int get charOffset => token.charOffset;
-
-  @override
-  Expression get initializer => null;
-
-  @override
-  int get endCharOffset => charOffset + name.length;
-
-  @override
-  QualifiedName withQualifier(Object qualifier) {
-    return new _TokenQualifiedName(qualifier, token);
-  }
-
-  @override
-  String toString() => "token-identifier($name)";
-}
-
-class InitializedIdentifier extends _TokenIdentifier {
+class InitializedIdentifier extends Identifier {
   @override
   final Expression initializer;
 
-  InitializedIdentifier(_TokenIdentifier identifier, this.initializer)
+  InitializedIdentifier(Identifier identifier, this.initializer)
       : super(identifier.token);
 
   @override
@@ -83,8 +54,7 @@
 
   QualifiedName(this.qualifier, Token suffix) : super(suffix);
 
-  QualifiedName._(this.qualifier, String name, int charOffset)
-      : super._(name, charOffset);
+  Token get suffix => token;
 
   @override
   QualifiedName withQualifier(Object qualifier) {
@@ -95,23 +65,6 @@
   String toString() => "qualified-name($qualifier, $name)";
 }
 
-class _TokenQualifiedName extends _TokenIdentifier implements QualifiedName {
-  @override
-  final Object qualifier;
-
-  _TokenQualifiedName(this.qualifier, Token suffix)
-      : assert(qualifier is! Identifier || qualifier is _TokenIdentifier),
-        super(suffix);
-
-  @override
-  QualifiedName withQualifier(Object qualifier) {
-    return unsupported("withQualifier", charOffset, null);
-  }
-
-  @override
-  String toString() => "token-qualified-name($qualifier, $name)";
-}
-
 void flattenQualifiedNameOn(
     QualifiedName name, StringBuffer buffer, int charOffset, Uri fileUri) {
   final Object qualifier = name.qualifier;
@@ -142,8 +95,3 @@
     return unhandled("${name.runtimeType}", "flattenName", charOffset, fileUri);
   }
 }
-
-Token deprecated_extractToken(Identifier identifier) {
-  _TokenIdentifier tokenIdentifier = identifier;
-  return tokenIdentifier?.token;
-}
diff --git a/pkg/front_end/lib/src/fasta/ignored_parser_errors.dart b/pkg/front_end/lib/src/fasta/ignored_parser_errors.dart
index fbd01f9..04b0e4a 100644
--- a/pkg/front_end/lib/src/fasta/ignored_parser_errors.dart
+++ b/pkg/front_end/lib/src/fasta/ignored_parser_errors.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.9
+
 library fasta.ignored_parser_errors;
 
 import 'package:_fe_analyzer_shared/src/parser/parser.dart' show optional;
diff --git a/pkg/front_end/lib/src/fasta/import.dart b/pkg/front_end/lib/src/fasta/import.dart
index fe41e88..6a51033 100644
--- a/pkg/front_end/lib/src/fasta/import.dart
+++ b/pkg/front_end/lib/src/fasta/import.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.9
+
 library fasta.import;
 
 import 'package:kernel/ast.dart' show LibraryDependency;
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 35c074e..22a3f8b 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.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.9
+
 library fasta.incremental_compiler;
 
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
@@ -230,7 +232,19 @@
       Set<Uri> invalidatedUris = this.invalidatedUris.toSet();
       invalidateNotKeptUserBuilders(invalidatedUris);
       ReusageResult reusedResult =
-          computeReusedLibraries(invalidatedUris, uriTranslator);
+          computeReusedLibraries(invalidatedUris, uriTranslator, entryPoints);
+
+      // Use the reused libraries to re-write entry-points.
+      if (reusedResult.arePartsUsedAsEntryPoints()) {
+        for (int i = 0; i < entryPoints.length; i++) {
+          Uri entryPoint = entryPoints[i];
+          Uri redirect =
+              reusedResult.getLibraryUriForPartUsedAsEntryPoint(entryPoint);
+          if (redirect != null) {
+            entryPoints[i] = redirect;
+          }
+        }
+      }
 
       // Experimental invalidation initialization (e.g. figure out if we can).
       ExperimentalInvalidation experimentalInvalidation =
@@ -949,8 +963,8 @@
       ReusageResult reusedResult, UriTranslator uriTranslator) {
     bool removedDillBuilders = false;
     for (LibraryBuilder builder in reusedResult.notReusedLibraries) {
-      cleanupSourcesForBuilder(
-          builder, uriTranslator, CompilerContext.current.uriToSource);
+      cleanupSourcesForBuilder(reusedResult, builder, uriTranslator,
+          CompilerContext.current.uriToSource);
       incrementalSerializer?.invalidate(builder.fileUri);
 
       LibraryBuilder dillBuilder =
@@ -989,8 +1003,7 @@
 
     // Figure out if the file(s) have changed outline, or we can just
     // rebuild the bodies.
-    for (int i = 0; i < reusedResult.directlyInvalidated.length; i++) {
-      LibraryBuilder builder = reusedResult.directlyInvalidated[i];
+    for (LibraryBuilder builder in reusedResult.directlyInvalidated) {
       if (builder.library.problemsAsJson != null) {
         assert(builder.library.problemsAsJson.isNotEmpty);
         return null;
@@ -1441,18 +1454,26 @@
   /// any saved component problems for such builders.
   List<Library> computeTransitiveClosure(
       List<Library> inputLibraries,
-      List<Uri> entries,
+      List<Uri> entryPoints,
       List<LibraryBuilder> reusedLibraries,
       ClassHierarchy hierarchy,
       UriTranslator uriTranslator,
       Map<Uri, Source> uriToSource,
       [List<Library> inputLibrariesFiltered]) {
     List<Library> result = <Library>[];
+    Map<Uri, Uri> partUriToLibraryImportUri = <Uri, Uri>{};
     Map<Uri, Library> libraryMap = <Uri, Library>{};
     Map<Uri, Library> potentiallyReferencedLibraries = <Uri, Library>{};
     Map<Uri, Library> potentiallyReferencedInputLibraries = <Uri, Library>{};
     for (Library library in inputLibraries) {
       libraryMap[library.importUri] = library;
+      if (library.parts.isNotEmpty) {
+        for (int partIndex = 0; partIndex < library.parts.length; partIndex++) {
+          LibraryPart part = library.parts[partIndex];
+          Uri partUri = getPartUri(library.importUri, part);
+          partUriToLibraryImportUri[partUri] = library.importUri;
+        }
+      }
       if (library.importUri.scheme == "dart") {
         result.add(library);
         inputLibrariesFiltered?.add(library);
@@ -1461,9 +1482,6 @@
         potentiallyReferencedInputLibraries[library.importUri] = library;
       }
     }
-
-    List<Uri> worklist = <Uri>[];
-    worklist.addAll(entries);
     for (LibraryBuilder libraryBuilder in reusedLibraries) {
       if (libraryBuilder.importUri.scheme == "dart" &&
           !libraryBuilder.isSynthetic) {
@@ -1474,6 +1492,19 @@
       libraryMap[libraryBuilder.importUri] = lib;
     }
 
+    List<Uri> worklist = <Uri>[];
+    for (Uri entry in entryPoints) {
+      if (libraryMap.containsKey(entry)) {
+        worklist.add(entry);
+      } else {
+        // If the entry is a part redirect to the "main" entry.
+        Uri partTranslation = partUriToLibraryImportUri[entry];
+        if (partTranslation != null) {
+          worklist.add(partTranslation);
+        }
+      }
+    }
+
     LibraryGraph graph = new LibraryGraph(libraryMap);
     Set<Uri> partsUsed = new Set<Uri>();
     while (worklist.isNotEmpty && potentiallyReferencedLibraries.isNotEmpty) {
@@ -1494,7 +1525,6 @@
                 getPartFileUri(library.fileUri, part, uriTranslator);
             partsUsed.add(partFileUri);
           }
-          partsUsed;
         }
       }
     }
@@ -1510,7 +1540,7 @@
         if (dillLoadedData.loader.builders.remove(uri) != null) {
           removedDillBuilders = true;
         }
-        cleanupSourcesForBuilder(builder, uriTranslator,
+        cleanupSourcesForBuilder(null, builder, uriTranslator,
             CompilerContext.current.uriToSource, uriToSource, partsUsed);
         userBuilders?.remove(uri);
         removeLibraryFromRemainingComponentProblems(
@@ -1545,15 +1575,43 @@
   /// [partsUsed] indicates part uris that are used by (other/alive) libraries.
   /// Those parts will not be cleaned up. This is useful when a part has been
   /// "moved" to be part of another library.
-  void cleanupSourcesForBuilder(LibraryBuilder builder,
-      UriTranslator uriTranslator, Map<Uri, Source> uriToSource,
-      [Map<Uri, Source> uriToSourceExtra, Set<Uri> partsUsed]) {
+  void cleanupSourcesForBuilder(
+      ReusageResult reusedResult,
+      LibraryBuilder builder,
+      UriTranslator uriTranslator,
+      Map<Uri, Source> uriToSource,
+      [Map<Uri, Source> uriToSourceExtra,
+      Set<Uri> partsUsed]) {
     uriToSource.remove(builder.fileUri);
     uriToSourceExtra?.remove(builder.fileUri);
     Library lib = builder.library;
     for (LibraryPart part in lib.parts) {
       Uri partFileUri = getPartFileUri(lib.fileUri, part, uriTranslator);
       if (partsUsed != null && partsUsed.contains(partFileUri)) continue;
+
+      // If the builders map contain the "parts" import uri, it's a real library
+      // (erroneously) used as a part so we don't want to remove that.
+      if (userCode?.loader != null) {
+        Uri partImportUri = uriToSource[partFileUri]?.importUri;
+        if (partImportUri != null &&
+            userCode.loader.builders.containsKey(partImportUri)) {
+          continue;
+        }
+      } else if (reusedResult != null) {
+        // We've just launched and don't have userCode yet. Search reusedResult
+        // for a kept library with this uri.
+        bool found = false;
+        for (int i = 0; i < reusedResult.reusedLibraries.length; i++) {
+          LibraryBuilder reusedLibrary = reusedResult.reusedLibraries[i];
+          if (reusedLibrary.fileUri == partFileUri) {
+            found = true;
+            break;
+          }
+        }
+        if (found) {
+          continue;
+        }
+      }
       uriToSource.remove(partFileUri);
       uriToSourceExtra?.remove(partFileUri);
     }
@@ -1902,8 +1960,8 @@
   }
 
   /// Internal method.
-  ReusageResult computeReusedLibraries(
-      Set<Uri> invalidatedUris, UriTranslator uriTranslator) {
+  ReusageResult computeReusedLibraries(Set<Uri> invalidatedUris,
+      UriTranslator uriTranslator, List<Uri> entryPoints) {
     Set<Uri> seenUris = new Set<Uri>();
     List<LibraryBuilder> reusedLibraries = <LibraryBuilder>[];
     for (int i = 0; i < platformBuilders.length; i++) {
@@ -1912,14 +1970,15 @@
       reusedLibraries.add(builder);
     }
     if (userCode == null && userBuilders == null) {
-      return new ReusageResult({}, [], false, reusedLibraries);
+      return new ReusageResult.reusedLibrariesOnly(reusedLibraries);
     }
     bool invalidatedBecauseOfPackageUpdate = false;
-    List<LibraryBuilder> directlyInvalidated = <LibraryBuilder>[];
+    Set<LibraryBuilder> directlyInvalidated = new Set<LibraryBuilder>();
     Set<LibraryBuilder> notReusedLibraries = new Set<LibraryBuilder>();
 
     // Maps all non-platform LibraryBuilders from their import URI.
     Map<Uri, LibraryBuilder> builders = <Uri, LibraryBuilder>{};
+    Map<Uri, LibraryBuilder> partUriToParent = <Uri, LibraryBuilder>{};
 
     // Invalidated URIs translated back to their import URI (package:, dart:,
     // etc.).
@@ -1963,7 +2022,10 @@
         invalidatedImportUris.add(uri);
       }
       if (libraryBuilder is SourceLibraryBuilder) {
+        // TODO(jensj): This shouldn't be possible anymore.
         for (LibraryBuilder part in libraryBuilder.parts) {
+          partUriToParent[part.importUri] = libraryBuilder;
+          partUriToParent[part.fileUri] = libraryBuilder;
           if (isInvalidated(part.importUri, part.fileUri)) {
             invalidatedImportUris.add(part.importUri);
             builders[part.importUri] = part;
@@ -1974,10 +2036,18 @@
           Uri partUri = getPartUri(libraryBuilder.importUri, part);
           Uri fileUri = getPartFileUri(
               libraryBuilder.library.fileUri, part, uriTranslator);
+          partUriToParent[partUri] = libraryBuilder;
+          partUriToParent[fileUri] = libraryBuilder;
 
           if (isInvalidated(partUri, fileUri)) {
             invalidatedImportUris.add(partUri);
-            builders[partUri] = libraryBuilder;
+            if (builders[partUri] == null) {
+              // Only add if entry doesn't already exist.
+              // For good cases it shouldn't exist, but if one library claims
+              // another library is a part (when it's not) we don't want to
+              // overwrite the real library builder.
+              builders[partUri] = libraryBuilder;
+            }
           }
         }
       }
@@ -2046,8 +2116,21 @@
       reusedLibraries.add(builder);
     }
 
-    return new ReusageResult(notReusedLibraries, directlyInvalidated,
-        invalidatedBecauseOfPackageUpdate, reusedLibraries);
+    ReusageResult result = new ReusageResult(
+        notReusedLibraries,
+        directlyInvalidated,
+        invalidatedBecauseOfPackageUpdate,
+        reusedLibraries);
+
+    for (Uri entryPoint in entryPoints) {
+      LibraryBuilder parent = partUriToParent[entryPoint];
+      if (reusedLibraries.contains(parent)) {
+        result.registerLibraryUriForPartUsedAsEntryPoint(
+            entryPoint, parent.importUri);
+      }
+    }
+
+    return result;
   }
 
   @override
@@ -2118,16 +2201,35 @@
 
 class ReusageResult {
   final Set<LibraryBuilder> notReusedLibraries;
-  final List<LibraryBuilder> directlyInvalidated;
+  final Set<LibraryBuilder> directlyInvalidated;
   final bool invalidatedBecauseOfPackageUpdate;
   final List<LibraryBuilder> reusedLibraries;
+  final Map<Uri, Uri> _reusedLibrariesPartsToParentForEntryPoints;
+
+  ReusageResult.reusedLibrariesOnly(this.reusedLibraries)
+      : notReusedLibraries = const {},
+        directlyInvalidated = const {},
+        invalidatedBecauseOfPackageUpdate = false,
+        _reusedLibrariesPartsToParentForEntryPoints = const {};
 
   ReusageResult(this.notReusedLibraries, this.directlyInvalidated,
       this.invalidatedBecauseOfPackageUpdate, this.reusedLibraries)
-      : assert(notReusedLibraries != null),
+      : _reusedLibrariesPartsToParentForEntryPoints = {},
+        assert(notReusedLibraries != null),
         assert(directlyInvalidated != null),
         assert(invalidatedBecauseOfPackageUpdate != null),
         assert(reusedLibraries != null);
+
+  void registerLibraryUriForPartUsedAsEntryPoint(
+      Uri entryPoint, Uri importUri) {
+    _reusedLibrariesPartsToParentForEntryPoints[entryPoint] = importUri;
+  }
+
+  bool arePartsUsedAsEntryPoints() =>
+      _reusedLibrariesPartsToParentForEntryPoints.isNotEmpty;
+
+  Uri getLibraryUriForPartUsedAsEntryPoint(Uri entryPoint) =>
+      _reusedLibrariesPartsToParentForEntryPoints[entryPoint];
 }
 
 class ExperimentalInvalidation {
diff --git a/pkg/front_end/lib/src/fasta/incremental_serializer.dart b/pkg/front_end/lib/src/fasta/incremental_serializer.dart
index 4581f16..208022e 100644
--- a/pkg/front_end/lib/src/fasta/incremental_serializer.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_serializer.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.9
+
 library fasta.incremental_serializer;
 
 import 'dart:typed_data' show Uint8List;
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 ede2b69..3bf29c0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2,11 +2,14 @@
 // for 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.body_builder;
 
 import 'dart:core' hide MapEntry;
 
-import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart'
+    hide Reference; // Work around https://github.com/dart-lang/sdk/issues/44667
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
@@ -40,7 +43,8 @@
 
 import 'package:_fe_analyzer_shared/src/util/link.dart';
 
-import 'package:kernel/ast.dart';
+import 'package:kernel/ast.dart'
+    hide Reference; // Work around https://github.com/dart-lang/sdk/issues/44667
 import 'package:kernel/type_environment.dart';
 
 import '../builder/builder.dart';
@@ -78,12 +82,7 @@
 import '../fasta_codes.dart' show LocatedMessage, Message, noLength, Template;
 
 import '../identifiers.dart'
-    show
-        Identifier,
-        InitializedIdentifier,
-        QualifiedName,
-        deprecated_extractToken,
-        flattenName;
+    show Identifier, InitializedIdentifier, QualifiedName, flattenName;
 
 import '../messages.dart' as messages show getLocationFromUri;
 
@@ -451,6 +450,11 @@
   }
 
   @override
+  void registerVariableDeclaration(VariableDeclaration variable) {
+    typeInferrer?.assignedVariables?.declare(variable);
+  }
+
+  @override
   void push(Object node) {
     if (node is DartType) {
       unhandled("DartType", "push", -1, uri);
@@ -631,9 +635,7 @@
       Object expression = pop();
       if (expression is Identifier) {
         Identifier identifier = expression;
-        expression = new UnresolvedNameGenerator(
-            this,
-            deprecated_extractToken(identifier),
+        expression = new UnresolvedNameGenerator(this, identifier.token,
             new Name(identifier.name, libraryBuilder.nameOrigin));
       }
       if (name?.isNotEmpty ?? false) {
@@ -1695,6 +1697,7 @@
       }
       VariableDeclaration variable =
           forest.createVariableDeclarationForValue(expression);
+      registerVariableDeclaration(variable);
       push(new Cascade(variable, isNullAware: isNullAware)
         ..fileOffset = expression.fileOffset);
       push(_createReadOnlyVariableAccess(variable, token, expression.fileOffset,
@@ -1728,9 +1731,15 @@
 
   @override
   void beginBinaryExpression(Token token) {
-    if (optional("&&", token) || optional("||", token)) {
+    bool isAnd = optional("&&", token);
+    if (isAnd || optional("||", token)) {
       Expression lhs = popForValue();
       typePromoter?.enterLogicalExpression(lhs, token.stringValue);
+      // This is matched by the call to [endNode] in
+      // [doLogicalExpression].
+      if (isAnd) {
+        typeInferrer?.assignedVariables?.beginNode();
+      }
       push(lhs);
     }
   }
@@ -1815,6 +1824,11 @@
         offsetForToken(token), receiver, token.stringValue, argument);
     typePromoter?.exitLogicalExpression(argument, logicalExpression);
     push(logicalExpression);
+    if (optional("&&", token)) {
+      // This is matched by the call to [beginNode] in
+      // [beginBinaryExpression].
+      typeInferrer?.assignedVariables?.endNode(logicalExpression);
+    }
   }
 
   /// Handle `a ?? b`.
@@ -1995,13 +2009,6 @@
   void handleIdentifier(Token token, IdentifierContext context) {
     debugEvent("handleIdentifier");
     String name = token.lexeme;
-    if (name.startsWith("deprecated") &&
-        // Note that the previous check is redundant, but faster in the common
-        // case (when [name] isn't deprecated).
-        (name == "deprecated" || name.startsWith("deprecated_"))) {
-      addProblem(fasta.templateUseOfDeprecatedIdentifier.withArguments(name),
-          offsetForToken(token), lengthForToken(token));
-    }
     if (context.isScopeReference) {
       assert(!inInitializer ||
           this.scope == enclosingScope ||
@@ -2029,7 +2036,7 @@
     if (token.isSynthetic) {
       push(new ParserRecovery(offsetForToken(token)));
     } else {
-      push(new Identifier.preserveToken(token));
+      push(new Identifier(token));
     }
   }
 
@@ -2038,6 +2045,9 @@
   @override
   VariableGet createVariableGet(VariableDeclaration variable, int charOffset,
       {bool forNullGuardedAccess: false}) {
+    if (!(variable as VariableDeclarationImpl).isLocalFunction) {
+      typeInferrer?.assignedVariables?.read(variable);
+    }
     Object fact =
         typePromoter?.getFactForAccess(variable, functionNestingLevel);
     Object scope = typePromoter?.currentScope;
@@ -2405,6 +2415,9 @@
   void beginThenStatement(Token token) {
     Expression condition = popForValue();
     enterThenForTypePromotion(condition);
+    // This is matched by the call to [deferNode] in
+    // [endThenStatement].
+    typeInferrer?.assignedVariables?.beginNode();
     push(condition);
     super.beginThenStatement(token);
   }
@@ -2413,16 +2426,26 @@
   void endThenStatement(Token token) {
     typePromoter?.enterElse();
     super.endThenStatement(token);
+    // This is matched by the call to [beginNode] in
+    // [beginThenStatement] and by the call to [storeInfo] in
+    // [endIfStatement].
+    push(typeInferrer?.assignedVariables?.deferNode());
   }
 
   @override
   void endIfStatement(Token ifToken, Token elseToken) {
     Statement elsePart = popStatementIfNotNull(elseToken);
+    AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesInfo =
+        pop();
     Statement thenPart = popStatement();
     Expression condition = pop();
     typePromoter?.exitConditional();
-    push(forest.createIfStatement(
-        offsetForToken(ifToken), condition, thenPart, elsePart));
+    Statement node = forest.createIfStatement(
+        offsetForToken(ifToken), condition, thenPart, elsePart);
+    // This is matched by the call to [deferNode] in
+    // [endThenStatement].
+    typeInferrer?.assignedVariables?.storeInfo(node, assignedVariablesInfo);
+    push(node);
   }
 
   @override
@@ -2501,7 +2524,7 @@
     assert(isConst == (constantContext == ConstantContext.inferred));
     VariableDeclaration variable = new VariableDeclarationImpl(
         identifier.name, functionNestingLevel,
-        forSyntheticToken: deprecated_extractToken(identifier).isSynthetic,
+        forSyntheticToken: identifier.token.isSynthetic,
         initializer: initializer,
         type: buildDartType(currentLocalVariableType),
         isFinal: isFinal,
@@ -3280,7 +3303,7 @@
     if (name is QualifiedName) {
       QualifiedName qualified = name;
       Object prefix = qualified.qualifier;
-      Token suffix = deprecated_extractToken(qualified);
+      Token suffix = qualified.suffix;
       if (prefix is Generator) {
         name = prefix.qualifiedLookup(suffix);
       } else {
@@ -3466,6 +3489,9 @@
   void beginConditionalExpression(Token question) {
     Expression condition = popForValue();
     typePromoter?.enterThen(condition);
+    // This is matched by the call to [deferNode] in
+    // [handleConditionalExpressionColon].
+    typeInferrer?.assignedVariables?.beginNode();
     push(condition);
     super.beginConditionalExpression(question);
   }
@@ -3474,6 +3500,10 @@
   void handleConditionalExpressionColon() {
     Expression then = popForValue();
     typePromoter?.enterElse();
+    // This is matched by the call to [beginNode] in
+    // [beginConditionalExpression] and by the call to [storeInfo] in
+    // [endConditionalExpression].
+    push(typeInferrer?.assignedVariables?.deferNode());
     push(then);
     super.handleConditionalExpressionColon();
   }
@@ -3483,10 +3513,16 @@
     debugEvent("ConditionalExpression");
     Expression elseExpression = popForValue();
     Expression thenExpression = pop();
+    AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesInfo =
+        pop();
     Expression condition = pop();
     typePromoter?.exitConditional();
-    push(forest.createConditionalExpression(
-        offsetForToken(question), condition, thenExpression, elseExpression));
+    Expression node = forest.createConditionalExpression(
+        offsetForToken(question), condition, thenExpression, elseExpression);
+    push(node);
+    // This is matched by the call to [deferNode] in
+    // [handleConditionalExpressionColon].
+    typeInferrer?.assignedVariables?.storeInfo(node, assignedVariablesInfo);
   }
 
   @override
@@ -3973,7 +4009,8 @@
   /// name.
   void pushQualifiedReference(Token start, Token periodBeforeName) {
     assert(checkState(start, [
-      /*suffix*/ if (periodBeforeName != null) ValueKinds.Identifier,
+      /*suffix*/ if (periodBeforeName != null)
+        unionOfKinds([ValueKinds.Identifier, ValueKinds.ParserRecovery]),
       /*type arguments*/ ValueKinds.TypeArgumentsOrNull,
       /*type*/ unionOfKinds([
         ValueKinds.Generator,
@@ -3982,7 +4019,18 @@
         ValueKinds.ParserRecovery
       ])
     ]));
-    Identifier suffix = popIfNotNull(periodBeforeName);
+    Object suffixObject = popIfNotNull(periodBeforeName);
+    Identifier suffix;
+    if (suffixObject is Identifier) {
+      suffix = suffixObject;
+    } else {
+      assert(
+          suffixObject == null || suffixObject is ParserRecovery,
+          "Unexpected qualified name suffix $suffixObject "
+          "(${suffixObject.runtimeType})");
+      // There was a `.` without a suffix.
+    }
+
     Identifier identifier;
     List<UnresolvedType> typeArguments = pop();
     Object type = pop();
@@ -4002,7 +4050,7 @@
               identifier.charOffset, identifier.name.length);
         }
       } else if (qualifier is Generator) {
-        type = qualifier.qualifiedLookup(deprecated_extractToken(identifier));
+        type = qualifier.qualifiedLookup(identifier.token);
         identifier = null;
       } else if (qualifier is ProblemBuilder) {
         type = qualifier;
@@ -4320,8 +4368,7 @@
     ]));
     Arguments arguments = pop();
     Identifier nameLastIdentifier = pop(NullValue.Identifier);
-    Token nameLastToken =
-        deprecated_extractToken(nameLastIdentifier) ?? nameToken;
+    Token nameLastToken = nameLastIdentifier?.token ?? nameToken;
     String name = pop();
     List<UnresolvedType> typeArguments = pop();
 
@@ -4617,6 +4664,10 @@
   void handleThenControlFlow(Token token) {
     Expression condition = popForValue();
     enterThenForTypePromotion(condition);
+    // This is matched by the call to [deferNode] in
+    // [handleElseControlFlow] and by the call to [endNode] in
+    // [endIfControlFlow].
+    typeInferrer?.assignedVariables?.beginNode();
     push(condition);
     super.handleThenControlFlow(token);
   }
@@ -4627,6 +4678,10 @@
     // happens before we go into the else block.
     Object node = pop();
     if (node is! MapEntry) node = toValue(node);
+    // This is matched by the call to [beginNode] in
+    // [handleThenControlFlow] and by the call to [storeInfo] in
+    // [endIfElseControlFlow].
+    push(typeInferrer?.assignedVariables?.deferNode());
     push(node);
     typePromoter?.enterElse();
   }
@@ -4639,15 +4694,20 @@
     Token ifToken = pop();
 
     transformCollections = true;
+    TreeNode node;
     if (entry is MapEntry) {
-      push(forest.createIfMapEntry(
-          offsetForToken(ifToken), toValue(condition), entry));
+      node = forest.createIfMapEntry(
+          offsetForToken(ifToken), toValue(condition), entry);
     } else {
-      push(forest.createIfElement(
-          offsetForToken(ifToken), toValue(condition), toValue(entry)));
+      node = forest.createIfElement(
+          offsetForToken(ifToken), toValue(condition), toValue(entry));
     }
+    push(node);
     typePromoter?.enterElse();
     typePromoter?.exitConditional();
+    // This is matched by the call to [beginNode] in
+    // [handleThenControlFlow].
+    typeInferrer?.assignedVariables?.endNode(node);
   }
 
   @override
@@ -4655,72 +4715,79 @@
     debugEvent("endIfElseControlFlow");
     Object elseEntry = pop(); // else entry
     Object thenEntry = pop(); // then entry
+    AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesInfo =
+        pop();
     Object condition = pop(); // parenthesized expression
     Token ifToken = pop();
     typePromoter?.exitConditional();
 
     transformCollections = true;
+    TreeNode node;
     if (thenEntry is MapEntry) {
       if (elseEntry is MapEntry) {
-        push(forest.createIfMapEntry(
-            offsetForToken(ifToken), toValue(condition), thenEntry, elseEntry));
+        node = forest.createIfMapEntry(
+            offsetForToken(ifToken), toValue(condition), thenEntry, elseEntry);
       } else if (elseEntry is ControlFlowElement) {
         MapEntry elseMapEntry =
             elseEntry.toMapEntry(typeInferrer?.assignedVariables?.reassignInfo);
         if (elseMapEntry != null) {
-          push(forest.createIfMapEntry(offsetForToken(ifToken),
-              toValue(condition), thenEntry, elseMapEntry));
+          node = forest.createIfMapEntry(offsetForToken(ifToken),
+              toValue(condition), thenEntry, elseMapEntry);
         } else {
           int offset = elseEntry is Expression
               ? elseEntry.fileOffset
               : offsetForToken(ifToken);
-          push(new MapEntry(
+          node = new MapEntry(
               buildProblem(
                   fasta.messageCantDisambiguateAmbiguousInformation, offset, 1),
               new NullLiteral())
-            ..fileOffset = offsetForToken(ifToken));
+            ..fileOffset = offsetForToken(ifToken);
         }
       } else {
         int offset = elseEntry is Expression
             ? elseEntry.fileOffset
             : offsetForToken(ifToken);
-        push(new MapEntry(
+        node = new MapEntry(
             buildProblem(fasta.templateExpectedAfterButGot.withArguments(':'),
                 offset, 1),
             new NullLiteral())
-          ..fileOffset = offsetForToken(ifToken));
+          ..fileOffset = offsetForToken(ifToken);
       }
     } else if (elseEntry is MapEntry) {
       if (thenEntry is ControlFlowElement) {
         MapEntry thenMapEntry =
             thenEntry.toMapEntry(typeInferrer?.assignedVariables?.reassignInfo);
         if (thenMapEntry != null) {
-          push(forest.createIfMapEntry(offsetForToken(ifToken),
-              toValue(condition), thenMapEntry, elseEntry));
+          node = forest.createIfMapEntry(offsetForToken(ifToken),
+              toValue(condition), thenMapEntry, elseEntry);
         } else {
           int offset = thenEntry is Expression
               ? thenEntry.fileOffset
               : offsetForToken(ifToken);
-          push(new MapEntry(
+          node = new MapEntry(
               buildProblem(
                   fasta.messageCantDisambiguateAmbiguousInformation, offset, 1),
               new NullLiteral())
-            ..fileOffset = offsetForToken(ifToken));
+            ..fileOffset = offsetForToken(ifToken);
         }
       } else {
         int offset = thenEntry is Expression
             ? thenEntry.fileOffset
             : offsetForToken(ifToken);
-        push(new MapEntry(
+        node = new MapEntry(
             buildProblem(fasta.templateExpectedAfterButGot.withArguments(':'),
                 offset, 1),
             new NullLiteral())
-          ..fileOffset = offsetForToken(ifToken));
+          ..fileOffset = offsetForToken(ifToken);
       }
     } else {
-      push(forest.createIfElement(offsetForToken(ifToken), toValue(condition),
-          toValue(thenEntry), toValue(elseEntry)));
+      node = forest.createIfElement(offsetForToken(ifToken), toValue(condition),
+          toValue(thenEntry), toValue(elseEntry));
     }
+    push(node);
+    // This is matched by the call to [deferNode] in
+    // [handleElseControlFlow].
+    typeInferrer?.assignedVariables?.storeInfo(node, assignedVariablesInfo);
   }
 
   @override
@@ -4793,7 +4860,7 @@
   void endFunctionName(Token beginToken, Token token) {
     debugEvent("FunctionName");
     Identifier name = pop();
-    Token nameToken = deprecated_extractToken(name);
+    Token nameToken = name.token;
     VariableDeclaration variable = new VariableDeclarationImpl(
         name.name, functionNestingLevel,
         forSyntheticToken: nameToken.isSynthetic,
@@ -6088,7 +6155,7 @@
   @override
   void handleSymbolVoid(Token token) {
     debugEvent("SymbolVoid");
-    push(new Identifier.preserveToken(token));
+    push(new Identifier(token));
   }
 
   @override
@@ -6252,6 +6319,7 @@
     if (isNullAware) {
       VariableDeclaration variable =
           forest.createVariableDeclarationForValue(receiver);
+      registerVariableDeclaration(variable);
       return new NullAwareMethodInvocation(
           variable,
           forest.createMethodInvocation(
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 387a16c..cbc684d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.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.9
+
 library fasta.class_hierarchy_builder;
 
 import 'package:kernel/ast.dart' hide MapEntry;
@@ -20,6 +22,7 @@
 import 'package:kernel/src/standard_bounds.dart';
 import 'package:kernel/src/types.dart' show Types;
 
+import '../../base/common.dart';
 import '../../testing/id_testing_utils.dart' show typeToText;
 
 import '../builder/builder.dart';
@@ -48,9 +51,8 @@
         messageInheritedMembersConflictCause2,
         messageStaticAndInstanceConflict,
         messageStaticAndInstanceConflictCause,
-        templateCantInferReturnTypeDueToInconsistentOverrides,
+        templateCantInferTypesDueToNoCombinedSignature,
         templateCantInferReturnTypeDueToNoCombinedSignature,
-        templateCantInferTypeDueToInconsistentOverrides,
         templateCantInferTypeDueToNoCombinedSignature,
         templateCombinedMemberSignatureFailed,
         templateDuplicatedDeclaration,
@@ -61,7 +63,6 @@
 
 import '../names.dart' show noSuchMethodName;
 
-import '../problems.dart';
 import '../scope.dart' show Scope;
 
 import '../source/source_class_builder.dart';
@@ -86,8 +87,6 @@
 
 import 'forwarding_node.dart' show ForwardingNode;
 
-import 'kernel_builder.dart' show ImplicitFieldType;
-
 const DebugLogger debug =
     const bool.fromEnvironment("debug.hierarchy") ? const DebugLogger() : null;
 
@@ -228,13 +227,15 @@
   bool get isFinal;
   bool get isConst;
   bool get forSetter;
-  bool get isSourceDeclaration;
 
-  /// Returns `true` if this member is a regular method or operator.
-  bool get isFunction;
+  /// Returns `true` if this member corresponds to a declaration in the source
+  /// code.
+  bool get isSourceDeclaration;
 
   /// Returns `true` if this member is a field, getter or setter.
   bool get isProperty;
+
+  /// Computes the [Member] node resulting from this class member.
   Member getMember(ClassHierarchyBuilder hierarchy);
 
   /// Returns the member [Covariance] for this class member.
@@ -244,12 +245,17 @@
   String get fullName;
   String get fullNameForErrors;
   ClassBuilder get classBuilder;
+
+  /// Returns `true` if this class member is declared in Object from dart:core.
   bool isObjectMember(ClassBuilder objectClass);
   Uri get fileUri;
   int get charOffset;
+
+  /// Returns `true` if this class member is an interface member.
   bool get isAbstract;
 
-  bool get needsComputation;
+  /// Returns `true` if this member doesn't corresponds to a declaration in the
+  /// source code.
   bool get isSynthesized;
 
   // If `true` this member is not part of the interface but only part of the
@@ -259,17 +265,71 @@
   // lowering.
   bool get isInternalImplementation;
 
-  bool get isInheritableConflict;
-  ClassMember withParent(ClassBuilder classBuilder);
+  /// Returns `true` if this member is composed from a list of class members
+  /// accessible through [declarations].
   bool get hasDeclarations;
+
+  /// If [hasDeclaration] is `true`, this returns the list of class members
+  /// from which this class member is composed.
+  ///
+  /// This is used in [unfoldDeclarations] to retrieve all underlying member
+  /// source declarations, and in [toSet] to retrieve all members used for
+  /// this class member wrt. certain level of the hierarchy.
+  /// TODO(johnniwinther): Can the use of [toSet] be replaced with a direct
+  /// use of [declarations]?
   List<ClassMember> get declarations;
-  ClassMember get abstract;
-  ClassMember get concrete;
+
+  /// The interface member corresponding to this member.
+  ///
+  /// If this member is declared on the source, the interface member is
+  /// the member itself. For instance
+  ///
+  ///     abstract class Class {
+  ///        void concreteMethod() {}
+  ///        void abstractMethod();
+  ///     }
+  ///
+  /// the interface members for `concreteMethod` and `abstractMethod` are the
+  /// members themselves.
+  ///
+  /// If this member is a synthesized interface member, the
+  /// interface member is the member itself. For instance
+  ///
+  ///     abstract class Interface1 {
+  ///        void method() {}
+  ///     }
+  ///     abstract class Interface2 {
+  ///        void method() {}
+  ///     }
+  ///     abstract class Class implements Interface1, Interface2 {}
+  ///
+  /// the interface member for `method` in `Class` is the synthesized interface
+  /// member created for the implemented members `Interface1.method` and
+  /// `Interface2.method`.
+  ///
+  /// If this member is a concrete member that implements an interface member,
+  /// the interface member is the implemented interface member. For instance
+  ///
+  ///     class Super {
+  ///        void method() {}
+  ///     }
+  ///     class Interface {
+  ///        void method() {}
+  ///     }
+  ///     class Class extends Super implements Interface {}
+  ///
+  /// the interface member for `Super.method` implementing `method` in `Class`
+  /// is the synthesized interface member created for the implemented members
+  /// `Super.method` and `Interface.method`.
+  ClassMember get interfaceMember;
 
   void inferType(ClassHierarchyBuilder hierarchy);
   void registerOverrideDependency(Set<ClassMember> overriddenMembers);
 
   /// Returns `true` if this has the same underlying declaration as [other].
+  ///
+  /// This is used for avoiding unnecessary checks and can this trivially
+  /// return `false`.
   bool isSameDeclaration(ClassMember other);
 }
 
@@ -382,9 +442,10 @@
     _delayedTypeComputations.add(computation);
   }
 
-  void registerOverrideCheck(
-      SourceClassBuilder classBuilder, ClassMember a, ClassMember b) {
-    _delayedChecks.add(new DelayedOverrideCheck(classBuilder, a, b));
+  void registerOverrideCheck(SourceClassBuilder classBuilder,
+      ClassMember declaredMember, Set<ClassMember> overriddenMembers) {
+    _delayedChecks.add(new DelayedOverrideCheck(
+        classBuilder, declaredMember, overriddenMembers));
   }
 
   void registerGetterSetterCheck(
@@ -647,8 +708,6 @@
 
   bool hasNoSuchMethod = false;
 
-  List<ClassMember> abstractMembers = null;
-
   final Map<Class, Substitution> substitutions;
 
   ClassHierarchyNodeBuilder(
@@ -694,257 +753,85 @@
 
       Set<ClassMember> overriddenMemberSet =
           toSet(declaredMember.classBuilder, overriddenMembers);
-      if (classBuilder.library.isNonNullableByDefault) {
-        CombinedClassMemberSignature combinedMemberSignature =
-            new CombinedClassMemberSignature(
-                hierarchy, classBuilder, overriddenMemberSet.toList(),
-                forSetter: false);
-        FunctionType combinedMemberSignatureType = combinedMemberSignature
-            .getCombinedSignatureTypeInContext(declaredTypeParameters);
-        if (declaredMember.returnType == null) {
-          if (combinedMemberSignatureType == null) {
-            inferredReturnType = const InvalidType();
-            reportCantInferReturnType(
-                classBuilder, declaredMember, hierarchy, overriddenMembers);
-          } else {
-            inferredReturnType = combinedMemberSignatureType.returnType;
-          }
-        }
-        if (declaredMember.formals != null) {
-          for (int i = 0; i < declaredPositional.length; i++) {
-            FormalParameterBuilder declaredParameter =
-                declaredMember.formals[i];
-            if (declaredParameter.type != null) {
-              continue;
-            }
+      CombinedClassMemberSignature combinedMemberSignature =
+          new CombinedClassMemberSignature(
+              hierarchy, classBuilder, overriddenMemberSet.toList(),
+              forSetter: false);
+      FunctionType combinedMemberSignatureType = combinedMemberSignature
+          .getCombinedSignatureTypeInContext(declaredTypeParameters);
 
-            DartType inferredParameterType;
-            if (combinedMemberSignatureType == null) {
-              inferredParameterType = const InvalidType();
-              reportCantInferParameterType(classBuilder, declaredParameter,
-                  hierarchy, overriddenMembers);
-            } else if (i <
-                combinedMemberSignatureType.positionalParameters.length) {
-              inferredParameterType =
-                  combinedMemberSignatureType.positionalParameters[i];
-            }
-            inferredParameterTypes[declaredParameter] = inferredParameterType;
-          }
+      bool cantInferReturnType = false;
+      List<FormalParameterBuilder> cantInferParameterTypes;
 
-          Map<String, DartType> namedParameterTypes;
-          for (int i = declaredPositional.length;
-              i < declaredMember.formals.length;
-              i++) {
-            FormalParameterBuilder declaredParameter =
-                declaredMember.formals[i];
-            if (declaredParameter.type != null) {
-              continue;
-            }
-
-            DartType inferredParameterType;
-            if (combinedMemberSignatureType == null) {
-              inferredParameterType = const InvalidType();
-              reportCantInferParameterType(classBuilder, declaredParameter,
-                  hierarchy, overriddenMembers);
-            } else {
-              if (namedParameterTypes == null) {
-                namedParameterTypes = {};
-                for (NamedType namedType
-                    in combinedMemberSignatureType.namedParameters) {
-                  namedParameterTypes[namedType.name] = namedType.type;
-                }
-              }
-              inferredParameterType =
-                  namedParameterTypes[declaredParameter.name];
-            }
-            inferredParameterTypes[declaredParameter] = inferredParameterType;
-          }
-        }
-      } else {
-        for (ClassMember classMember in overriddenMemberSet) {
-          Member overriddenMember = classMember.getMember(hierarchy);
-          Substitution classSubstitution;
-          if (classBuilder.cls != overriddenMember.enclosingClass) {
-            assert(
-                substitutions.containsKey(overriddenMember.enclosingClass),
-                "No substitution found for '${classBuilder.fullNameForErrors}' "
-                "as instance of '${overriddenMember.enclosingClass.name}'. "
-                "Substitutions available for: ${substitutions.keys}");
-            classSubstitution = substitutions[overriddenMember.enclosingClass];
-            debug?.log("${classBuilder.fullNameForErrors} -> "
-                "${overriddenMember.enclosingClass.name} $classSubstitution");
-          }
-          if (overriddenMember is! Procedure) {
-            debug?.log("Giving up 1");
-            continue;
-          }
-          Procedure overriddenProcedure = overriddenMember;
-          FunctionNode overriddenFunction = overriddenProcedure.function;
-
-          List<TypeParameter> overriddenTypeParameters =
-              overriddenFunction.typeParameters;
-          int typeParameterCount = declaredTypeParameters.length;
-          if (typeParameterCount != overriddenTypeParameters.length) {
-            debug?.log("Giving up 2");
-            continue;
-          }
-          Substitution methodSubstitution;
-          if (typeParameterCount != 0) {
-            List<DartType> types =
-                new List<DartType>.filled(typeParameterCount, null);
-            for (int i = 0; i < typeParameterCount; i++) {
-              types[i] = new TypeParameterType.forAlphaRenaming(
-                  overriddenTypeParameters[i], declaredTypeParameters[i]);
-            }
-            methodSubstitution =
-                Substitution.fromPairs(overriddenTypeParameters, types);
-            for (int i = 0; i < typeParameterCount; i++) {
-              DartType declaredBound = declaredTypeParameters[i].bound;
-              DartType overriddenBound = methodSubstitution
-                  .substituteType(overriddenTypeParameters[i].bound);
-              if (!hierarchy.types
-                  .performNullabilityAwareMutualSubtypesCheck(
-                      declaredBound, overriddenBound)
-                  .isSubtypeWhenUsingNullabilities()) {
-                debug?.log("Giving up 3");
-                continue;
-              }
-            }
-          }
-
-          DartType inheritedReturnType = overriddenFunction.returnType;
-          if (classSubstitution != null) {
-            inheritedReturnType =
-                classSubstitution.substituteType(inheritedReturnType);
-          }
-          if (methodSubstitution != null) {
-            inheritedReturnType =
-                methodSubstitution.substituteType(inheritedReturnType);
-          }
-          if (declaredMember.returnType == null &&
-              inferredReturnType is! InvalidType) {
-            inferredReturnType = mergeTypeInLibrary(hierarchy, classBuilder,
-                inferredReturnType, inheritedReturnType);
-            if (inferredReturnType == null) {
-              // A different type has already been inferred.
-              inferredReturnType = const InvalidType();
-              reportCantInferReturnType(
-                  classBuilder, declaredMember, hierarchy, overriddenMembers);
-            }
-          }
-          if (declaredFunction.requiredParameterCount >
-              overriddenFunction.requiredParameterCount) {
-            debug?.log("Giving up 4");
-            continue;
-          }
-          List<VariableDeclaration> overriddenPositional =
-              overriddenFunction.positionalParameters;
-          if (declaredPositional.length < overriddenPositional.length) {
-            debug?.log("Giving up 5");
-            continue;
-          }
-
-          for (int i = 0; i < overriddenPositional.length; i++) {
-            FormalParameterBuilder declaredParameter =
-                declaredMember.formals[i];
-            if (declaredParameter.type != null) continue;
-
-            VariableDeclaration overriddenParameter = overriddenPositional[i];
-            DartType inheritedParameterType = overriddenParameter.type;
-            if (classSubstitution != null) {
-              inheritedParameterType =
-                  classSubstitution.substituteType(inheritedParameterType);
-            }
-            if (methodSubstitution != null) {
-              inheritedParameterType =
-                  methodSubstitution.substituteType(inheritedParameterType);
-            }
-            if (hierarchy.coreTypes.objectClass.enclosingLibrary
-                    .isNonNullableByDefault &&
-                !declaredMember.classBuilder.library.isNonNullableByDefault &&
-                overriddenProcedure == hierarchy.coreTypes.objectEquals) {
-              // In legacy code we special case `Object.==` to infer `dynamic`
-              // instead `Object!`.
-              inheritedParameterType = const DynamicType();
-            }
-            DartType inferredParameterType =
-                inferredParameterTypes[declaredParameter];
-            inferredParameterType = mergeTypeInLibrary(hierarchy, classBuilder,
-                inferredParameterType, inheritedParameterType);
-            if (inferredParameterType == null) {
-              // A different type has already been inferred.
-              inferredParameterType = const InvalidType();
-              reportCantInferParameterType(classBuilder, declaredParameter,
-                  hierarchy, overriddenMembers);
-            }
-            inferredParameterTypes[declaredParameter] = inferredParameterType;
-          }
-
-          List<VariableDeclaration> overriddenNamed =
-              overriddenFunction.namedParameters;
-          named:
-          if (declaredNamed.isNotEmpty || overriddenNamed.isNotEmpty) {
-            if (declaredPositional.length != overriddenPositional.length) {
-              debug?.log("Giving up 9");
-              break named;
-            }
-            if (declaredFunction.requiredParameterCount !=
-                overriddenFunction.requiredParameterCount) {
-              debug?.log("Giving up 10");
-              break named;
-            }
-
-            overriddenNamed = overriddenNamed.toList()
-              ..sort(compareNamedParameters);
-            int declaredIndex = 0;
-            for (int overriddenIndex = 0;
-                overriddenIndex < overriddenNamed.length;
-                overriddenIndex++) {
-              String name = overriddenNamed[overriddenIndex].name;
-              for (; declaredIndex < declaredNamed.length; declaredIndex++) {
-                if (declaredNamed[declaredIndex].name == name) break;
-              }
-              if (declaredIndex == declaredNamed.length) {
-                debug?.log("Giving up 11");
-                break named;
-              }
-              FormalParameterBuilder declaredParameter;
-              for (int i = declaredPositional.length;
-                  i < declaredMember.formals.length;
-                  ++i) {
-                if (declaredMember.formals[i].name == name) {
-                  declaredParameter = declaredMember.formals[i];
-                  break;
-                }
-              }
-              if (declaredParameter.type != null) continue;
-              VariableDeclaration overriddenParameter =
-                  overriddenNamed[overriddenIndex];
-
-              DartType inheritedParameterType = overriddenParameter.type;
-              if (classSubstitution != null) {
-                inheritedParameterType =
-                    classSubstitution.substituteType(inheritedParameterType);
-              }
-              if (methodSubstitution != null) {
-                inheritedParameterType =
-                    methodSubstitution.substituteType(inheritedParameterType);
-              }
-              DartType inferredParameterType =
-                  inferredParameterTypes[declaredParameter];
-              inferredParameterType = mergeTypeInLibrary(hierarchy,
-                  classBuilder, inferredParameterType, inheritedParameterType);
-              if (inferredParameterType == null) {
-                // A different type has already been inferred.
-                inferredParameterType = const InvalidType();
-                reportCantInferParameterType(classBuilder, declaredParameter,
-                    hierarchy, overriddenMembers);
-              }
-              inferredParameterTypes[declaredParameter] = inferredParameterType;
-            }
-          }
+      if (declaredMember.returnType == null) {
+        if (combinedMemberSignatureType == null) {
+          inferredReturnType = const InvalidType();
+          cantInferReturnType = true;
+        } else {
+          inferredReturnType = combinedMemberSignatureType.returnType;
         }
       }
+      if (declaredMember.formals != null) {
+        for (int i = 0; i < declaredPositional.length; i++) {
+          FormalParameterBuilder declaredParameter = declaredMember.formals[i];
+          if (declaredParameter.type != null) {
+            continue;
+          }
+
+          DartType inferredParameterType;
+          if (combinedMemberSignatureType == null) {
+            inferredParameterType = const InvalidType();
+            cantInferParameterTypes ??= [];
+            cantInferParameterTypes.add(declaredParameter);
+          } else if (i <
+              combinedMemberSignatureType.positionalParameters.length) {
+            inferredParameterType =
+                combinedMemberSignatureType.positionalParameters[i];
+          }
+          inferredParameterTypes[declaredParameter] = inferredParameterType;
+        }
+
+        Map<String, DartType> namedParameterTypes;
+        for (int i = declaredPositional.length;
+            i < declaredMember.formals.length;
+            i++) {
+          FormalParameterBuilder declaredParameter = declaredMember.formals[i];
+          if (declaredParameter.type != null) {
+            continue;
+          }
+
+          DartType inferredParameterType;
+          if (combinedMemberSignatureType == null) {
+            inferredParameterType = const InvalidType();
+            cantInferParameterTypes ??= [];
+            cantInferParameterTypes.add(declaredParameter);
+          } else {
+            if (namedParameterTypes == null) {
+              namedParameterTypes = {};
+              for (NamedType namedType
+                  in combinedMemberSignatureType.namedParameters) {
+                namedParameterTypes[namedType.name] = namedType.type;
+              }
+            }
+            inferredParameterType = namedParameterTypes[declaredParameter.name];
+          }
+          inferredParameterTypes[declaredParameter] = inferredParameterType;
+        }
+      }
+
+      if ((cantInferReturnType && cantInferParameterTypes != null) ||
+          (cantInferParameterTypes != null &&
+              cantInferParameterTypes.length > 1)) {
+        reportCantInferTypes(
+            classBuilder, declaredMember, hierarchy, overriddenMembers);
+      } else if (cantInferReturnType) {
+        reportCantInferReturnType(
+            classBuilder, declaredMember, hierarchy, overriddenMembers);
+      } else if (cantInferParameterTypes != null) {
+        reportCantInferParameterType(classBuilder,
+            cantInferParameterTypes.single, hierarchy, overriddenMembers);
+      }
+
       if (declaredMember.returnType == null) {
         inferredReturnType ??= const DynamicType();
         declaredFunction.returnType = inferredReturnType;
@@ -1006,114 +893,50 @@
         declaredMember.returnType == null) {
       DartType inferredType;
       overriddenMembers = toSet(classBuilder, overriddenMembers);
-      if (classBuilder.library.isNonNullableByDefault) {
-        List<ClassMember> overriddenGetters = [];
-        List<ClassMember> overriddenSetters = [];
-        for (ClassMember overriddenMember in overriddenMembers) {
-          if (overriddenMember.forSetter) {
-            overriddenSetters.add(overriddenMember);
-          } else {
-            overriddenGetters.add(overriddenMember);
-          }
-        }
 
-        void inferFrom(List<ClassMember> members, {bool forSetter}) {
-          assert(forSetter != null);
-          CombinedClassMemberSignature combinedMemberSignature =
-              new CombinedClassMemberSignature(hierarchy, classBuilder, members,
-                  forSetter: forSetter);
-          DartType combinedMemberSignatureType =
-              combinedMemberSignature.combinedMemberSignatureType;
-          if (combinedMemberSignatureType == null) {
-            inferredType = const InvalidType();
-            reportCantInferReturnType(
-                classBuilder, declaredMember, hierarchy, members);
-          } else {
-            inferredType = combinedMemberSignatureType;
-          }
-        }
-
-        if (overriddenGetters.isNotEmpty) {
-          // 1) The return type of a getter, parameter type of a setter or type
-          // of a field which overrides/implements only one or more getters is
-          // inferred to be the return type of the combined member signature of
-          // said getter in the direct superinterfaces.
-
-          // 2) The return type of a getter which overrides/implements both a
-          // setter and a getter is inferred to be the return type of the
-          // combined member signature of said getter in the direct
-          // superinterfaces.
-          inferFrom(overriddenGetters, forSetter: false);
+      List<ClassMember> overriddenGetters = [];
+      List<ClassMember> overriddenSetters = [];
+      for (ClassMember overriddenMember in overriddenMembers) {
+        if (overriddenMember.forSetter) {
+          overriddenSetters.add(overriddenMember);
         } else {
-          // The return type of a getter, parameter type of a setter or type of
-          // a field which overrides/implements only one or more setters is
-          // inferred to be the parameter type of the combined member signature
-          // of said setter in the direct superinterfaces.
-          inferFrom(overriddenSetters, forSetter: true);
+          overriddenGetters.add(overriddenMember);
         }
+      }
+
+      void inferFrom(List<ClassMember> members, {bool forSetter}) {
+        assert(forSetter != null);
+        CombinedClassMemberSignature combinedMemberSignature =
+            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
+                forSetter: forSetter);
+        DartType combinedMemberSignatureType =
+            combinedMemberSignature.combinedMemberSignatureType;
+        if (combinedMemberSignatureType == null) {
+          inferredType = const InvalidType();
+          reportCantInferReturnType(
+              classBuilder, declaredMember, hierarchy, members);
+        } else {
+          inferredType = combinedMemberSignatureType;
+        }
+      }
+
+      if (overriddenGetters.isNotEmpty) {
+        // 1) The return type of a getter, parameter type of a setter or type
+        // of a field which overrides/implements only one or more getters is
+        // inferred to be the return type of the combined member signature of
+        // said getter in the direct superinterfaces.
+
+        // 2) The return type of a getter which overrides/implements both a
+        // setter and a getter is inferred to be the return type of the
+        // combined member signature of said getter in the direct
+        // superinterfaces.
+        inferFrom(overriddenGetters, forSetter: false);
       } else {
-        void inferFrom(ClassMember classMember) {
-          if (inferredType is InvalidType) return;
-
-          Member overriddenMember = classMember.getMember(hierarchy);
-          Substitution substitution;
-          if (classBuilder.cls != overriddenMember.enclosingClass) {
-            assert(
-                substitutions.containsKey(overriddenMember.enclosingClass),
-                "No substitution found for '${classBuilder.fullNameForErrors}' "
-                "as instance of '${overriddenMember.enclosingClass.name}'. "
-                "Substitutions available for: ${substitutions.keys}");
-            substitution = substitutions[overriddenMember.enclosingClass];
-          }
-          DartType inheritedType;
-          if (overriddenMember is Field) {
-            inheritedType = overriddenMember.type;
-            assert(inheritedType is! ImplicitFieldType);
-          } else if (overriddenMember is Procedure) {
-            if (overriddenMember.kind == ProcedureKind.Setter) {
-              VariableDeclaration bParameter =
-                  overriddenMember.function.positionalParameters.single;
-              inheritedType = bParameter.type;
-            } else if (overriddenMember.kind == ProcedureKind.Getter) {
-              inheritedType = overriddenMember.function.returnType;
-            } else {
-              debug?.log("Giving up (not accessor: ${overriddenMember.kind})");
-              return;
-            }
-          } else {
-            debug?.log("Giving up (not field/procedure: "
-                "${overriddenMember.runtimeType})");
-            return;
-          }
-          if (substitution != null) {
-            inheritedType = substitution.substituteType(inheritedType);
-          }
-          inferredType = mergeTypeInLibrary(
-              hierarchy, classBuilder, inferredType, inheritedType);
-
-          if (inferredType == null) {
-            // A different type has already been inferred.
-            inferredType = const InvalidType();
-            reportCantInferReturnType(
-                classBuilder, declaredMember, hierarchy, overriddenMembers);
-          }
-        }
-
-        // The getter type must be inferred from getters first.
-        for (ClassMember overriddenMember in overriddenMembers) {
-          if (!overriddenMember.forSetter) {
-            inferFrom(overriddenMember);
-          }
-        }
-        if (inferredType == null) {
-          // The getter type must be inferred from setters if no type was
-          // inferred from getters.
-          for (ClassMember overriddenMember in overriddenMembers) {
-            if (overriddenMember.forSetter) {
-              inferFrom(overriddenMember);
-            }
-          }
-        }
+        // The return type of a getter, parameter type of a setter or type of
+        // a field which overrides/implements only one or more setters is
+        // inferred to be the parameter type of the combined member signature
+        // of said setter in the direct superinterfaces.
+        inferFrom(overriddenSetters, forSetter: true);
       }
 
       inferredType ??= const DynamicType();
@@ -1133,113 +956,50 @@
       DartType inferredType;
 
       overriddenMembers = toSet(classBuilder, overriddenMembers);
-      if (classBuilder.library.isNonNullableByDefault) {
-        List<ClassMember> overriddenGetters = [];
-        List<ClassMember> overriddenSetters = [];
-        for (ClassMember overriddenMember in overriddenMembers) {
-          if (overriddenMember.forSetter) {
-            overriddenSetters.add(overriddenMember);
-          } else {
-            overriddenGetters.add(overriddenMember);
-          }
-        }
 
-        void inferFrom(List<ClassMember> members, {bool forSetter}) {
-          assert(forSetter != null);
-          CombinedClassMemberSignature combinedMemberSignature =
-              new CombinedClassMemberSignature(hierarchy, classBuilder, members,
-                  forSetter: forSetter);
-          DartType combinedMemberSignatureType =
-              combinedMemberSignature.combinedMemberSignatureType;
-          if (combinedMemberSignatureType == null) {
-            inferredType = const InvalidType();
-            reportCantInferReturnType(
-                classBuilder, declaredMember, hierarchy, members);
-          } else {
-            inferredType = combinedMemberSignatureType;
-          }
-        }
-
-        if (overriddenSetters.isNotEmpty) {
-          // 1) The return type of a getter, parameter type of a setter or type
-          // of a field which overrides/implements only one or more setters is
-          // inferred to be the parameter type of the combined member signature
-          // of said setter in the direct superinterfaces.
-          //
-          // 2) The parameter type of a setter which overrides/implements both a
-          // setter and a getter is inferred to be the parameter type of the
-          // combined member signature of said setter in the direct
-          // superinterfaces.
-          inferFrom(overriddenSetters, forSetter: true);
+      List<ClassMember> overriddenGetters = [];
+      List<ClassMember> overriddenSetters = [];
+      for (ClassMember overriddenMember in overriddenMembers) {
+        if (overriddenMember.forSetter) {
+          overriddenSetters.add(overriddenMember);
         } else {
-          // The return type of a getter, parameter type of a setter or type of
-          // a field which overrides/implements only one or more getters is
-          // inferred to be the return type of the combined member signature of
-          // said getter in the direct superinterfaces.
-          inferFrom(overriddenGetters, forSetter: false);
+          overriddenGetters.add(overriddenMember);
         }
+      }
+
+      void inferFrom(List<ClassMember> members, {bool forSetter}) {
+        assert(forSetter != null);
+        CombinedClassMemberSignature combinedMemberSignature =
+            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
+                forSetter: forSetter);
+        DartType combinedMemberSignatureType =
+            combinedMemberSignature.combinedMemberSignatureType;
+        if (combinedMemberSignatureType == null) {
+          inferredType = const InvalidType();
+          reportCantInferReturnType(
+              classBuilder, declaredMember, hierarchy, members);
+        } else {
+          inferredType = combinedMemberSignatureType;
+        }
+      }
+
+      if (overriddenSetters.isNotEmpty) {
+        // 1) The return type of a getter, parameter type of a setter or type
+        // of a field which overrides/implements only one or more setters is
+        // inferred to be the parameter type of the combined member signature
+        // of said setter in the direct superinterfaces.
+        //
+        // 2) The parameter type of a setter which overrides/implements both a
+        // setter and a getter is inferred to be the parameter type of the
+        // combined member signature of said setter in the direct
+        // superinterfaces.
+        inferFrom(overriddenSetters, forSetter: true);
       } else {
-        void inferFrom(ClassMember classMember) {
-          if (inferredType is InvalidType) return;
-
-          Member overriddenMember = classMember.getMember(hierarchy);
-          Substitution substitution;
-          if (classBuilder.cls != overriddenMember.enclosingClass) {
-            assert(
-                substitutions.containsKey(overriddenMember.enclosingClass),
-                "No substitution found for '${classBuilder.fullNameForErrors}' "
-                "as instance of '${overriddenMember.enclosingClass.name}'. "
-                "Substitutions available for: ${substitutions.keys}");
-            substitution = substitutions[overriddenMember.enclosingClass];
-          }
-          DartType inheritedType;
-          if (overriddenMember is Field) {
-            inheritedType = overriddenMember.type;
-            assert(inheritedType is! ImplicitFieldType);
-          } else if (overriddenMember is Procedure) {
-            if (classMember.isSetter) {
-              VariableDeclaration bParameter =
-                  overriddenMember.function.positionalParameters.single;
-              inheritedType = bParameter.type;
-            } else if (classMember.isGetter) {
-              inheritedType = overriddenMember.function.returnType;
-            } else {
-              debug?.log("Giving up (not accessor: ${overriddenMember.kind})");
-              return;
-            }
-          } else {
-            debug?.log("Giving up (not field/procedure: "
-                "${overriddenMember.runtimeType})");
-            return;
-          }
-          if (substitution != null) {
-            inheritedType = substitution.substituteType(inheritedType);
-          }
-          inferredType = mergeTypeInLibrary(
-              hierarchy, classBuilder, inferredType, inheritedType);
-          if (inferredType == null) {
-            // A different type has already been inferred.
-            inferredType = const InvalidType();
-            reportCantInferParameterType(
-                classBuilder, parameter, hierarchy, overriddenMembers);
-          }
-        }
-
-        // The setter type must be inferred from setters first.
-        for (ClassMember overriddenMember in overriddenMembers) {
-          if (overriddenMember.forSetter) {
-            inferFrom(overriddenMember);
-          }
-        }
-        if (inferredType == null) {
-          // The setter type must be inferred from getters if no type was
-          // inferred from setters.
-          for (ClassMember overriddenMember in overriddenMembers) {
-            if (!overriddenMember.forSetter) {
-              inferFrom(overriddenMember);
-            }
-          }
-        }
+        // The return type of a getter, parameter type of a setter or type of
+        // a field which overrides/implements only one or more getters is
+        // inferred to be the return type of the combined member signature of
+        // said getter in the direct superinterfaces.
+        inferFrom(overriddenGetters, forSetter: false);
       }
 
       inferredType ??= const DynamicType();
@@ -1285,7 +1045,7 @@
     }
   }
 
-  /// Infers the field type of [declaredMember] based on [overriddenMembers].
+  /// Infers the field type of [fieldBuilder] based on [overriddenMembers].
   static void inferFieldType(
       ClassHierarchyBuilder hierarchy,
       ClassBuilder classBuilder,
@@ -1297,137 +1057,66 @@
       DartType inferredType;
 
       overriddenMembers = toSet(classBuilder, overriddenMembers);
-      if (classBuilder.library.isNonNullableByDefault) {
-        List<ClassMember> overriddenGetters = [];
-        List<ClassMember> overriddenSetters = [];
-        for (ClassMember overriddenMember in overriddenMembers) {
-          if (overriddenMember.forSetter) {
-            overriddenSetters.add(overriddenMember);
-          } else {
-            overriddenGetters.add(overriddenMember);
-          }
-        }
-
-        DartType inferFrom(List<ClassMember> members, {bool forSetter}) {
-          assert(forSetter != null);
-          CombinedClassMemberSignature combinedMemberSignature =
-              new CombinedClassMemberSignature(hierarchy, classBuilder, members,
-                  forSetter: forSetter);
-          return combinedMemberSignature.combinedMemberSignatureType;
-        }
-
-        DartType combinedMemberSignatureType;
-        if (fieldBuilder.isAssignable &&
-            overriddenGetters.isNotEmpty &&
-            overriddenSetters.isNotEmpty) {
-          // The type of a non-final field which overrides/implements both a
-          // setter and a getter is inferred to be the parameter type of the
-          // combined member signature of said setter in the direct
-          // superinterfaces, if this type is the same as the return type of the
-          // combined member signature of said getter in the direct
-          // superinterfaces. If the types are not the same then inference fails
-          // with an error.
-          DartType getterType = inferFrom(overriddenGetters, forSetter: false);
-          DartType setterType = inferFrom(overriddenSetters, forSetter: true);
-          if (getterType == setterType) {
-            combinedMemberSignatureType = getterType;
-          }
-        } else if (overriddenGetters.isNotEmpty) {
-          // 1) The return type of a getter, parameter type of a setter or type
-          // of a field which overrides/implements only one or more getters is
-          // inferred to be the return type of the combined member signature of
-          // said getter in the direct superinterfaces.
-          //
-          // 2) The type of a final field which overrides/implements both a
-          // setter and a getter is inferred to be the return type of the
-          // combined member signature of said getter in the direct
-          // superinterfaces.
-          combinedMemberSignatureType =
-              inferFrom(overriddenGetters, forSetter: false);
+      List<ClassMember> overriddenGetters = [];
+      List<ClassMember> overriddenSetters = [];
+      for (ClassMember overriddenMember in overriddenMembers) {
+        if (overriddenMember.forSetter) {
+          overriddenSetters.add(overriddenMember);
         } else {
-          // The return type of a getter, parameter type of a setter or type of
-          // a field which overrides/implements only one or more setters is
-          // inferred to be the parameter type of the combined member signature
-          // of said setter in the direct superinterfaces.
-          combinedMemberSignatureType =
-              inferFrom(overriddenSetters, forSetter: true);
+          overriddenGetters.add(overriddenMember);
         }
+      }
 
-        if (combinedMemberSignatureType == null) {
-          inferredType = const InvalidType();
-          reportCantInferFieldType(
-              classBuilder, fieldBuilder, overriddenMembers);
-        } else {
-          inferredType = combinedMemberSignatureType;
+      DartType inferFrom(List<ClassMember> members, {bool forSetter}) {
+        assert(forSetter != null);
+        CombinedClassMemberSignature combinedMemberSignature =
+            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
+                forSetter: forSetter);
+        return combinedMemberSignature.combinedMemberSignatureType;
+      }
+
+      DartType combinedMemberSignatureType;
+      if (fieldBuilder.isAssignable &&
+          overriddenGetters.isNotEmpty &&
+          overriddenSetters.isNotEmpty) {
+        // The type of a non-final field which overrides/implements both a
+        // setter and a getter is inferred to be the parameter type of the
+        // combined member signature of said setter in the direct
+        // superinterfaces, if this type is the same as the return type of the
+        // combined member signature of said getter in the direct
+        // superinterfaces. If the types are not the same then inference fails
+        // with an error.
+        DartType getterType = inferFrom(overriddenGetters, forSetter: false);
+        DartType setterType = inferFrom(overriddenSetters, forSetter: true);
+        if (getterType == setterType) {
+          combinedMemberSignatureType = getterType;
         }
+      } else if (overriddenGetters.isNotEmpty) {
+        // 1) The return type of a getter, parameter type of a setter or type
+        // of a field which overrides/implements only one or more getters is
+        // inferred to be the return type of the combined member signature of
+        // said getter in the direct superinterfaces.
+        //
+        // 2) The type of a final field which overrides/implements both a
+        // setter and a getter is inferred to be the return type of the
+        // combined member signature of said getter in the direct
+        // superinterfaces.
+        combinedMemberSignatureType =
+            inferFrom(overriddenGetters, forSetter: false);
       } else {
-        void inferFrom(ClassMember classMember) {
-          if (inferredType is InvalidType) return;
+        // The return type of a getter, parameter type of a setter or type of
+        // a field which overrides/implements only one or more setters is
+        // inferred to be the parameter type of the combined member signature
+        // of said setter in the direct superinterfaces.
+        combinedMemberSignatureType =
+            inferFrom(overriddenSetters, forSetter: true);
+      }
 
-          Member overriddenMember = classMember.getMember(hierarchy);
-          DartType inheritedType;
-          if (overriddenMember is Procedure) {
-            if (overriddenMember.isSetter) {
-              VariableDeclaration parameter =
-                  overriddenMember.function.positionalParameters.single;
-              inheritedType = parameter.type;
-            } else if (overriddenMember.isGetter) {
-              inheritedType = overriddenMember.function.returnType;
-            }
-          } else if (overriddenMember is Field) {
-            inheritedType = overriddenMember.type;
-          }
-          if (inheritedType == null) {
-            debug?.log(
-                "Giving up (inheritedType == null)\n${StackTrace.current}");
-            return;
-          }
-          Substitution substitution;
-          if (classBuilder.cls != overriddenMember.enclosingClass) {
-            assert(
-                substitutions.containsKey(overriddenMember.enclosingClass),
-                "${classBuilder.fullNameForErrors} "
-                "${overriddenMember.enclosingClass.name}");
-            substitution = substitutions[overriddenMember.enclosingClass];
-            debug?.log("${classBuilder.fullNameForErrors} -> "
-                "${overriddenMember.enclosingClass.name} $substitution");
-          }
-          assert(inheritedType is! ImplicitFieldType);
-          if (substitution != null) {
-            inheritedType = substitution.substituteType(inheritedType);
-          }
-          inferredType = mergeTypeInLibrary(
-              hierarchy, classBuilder, inferredType, inheritedType);
-          if (inferredType == null) {
-            // A different type has already been inferred.
-            inferredType = const InvalidType();
-            reportCantInferFieldType(
-                classBuilder, fieldBuilder, overriddenMembers);
-          }
-        }
-
-        if (fieldBuilder.isAssignable) {
-          // The field type must be inferred from both getters and setters.
-          for (ClassMember overriddenMember in overriddenMembers) {
-            inferFrom(overriddenMember);
-          }
-        } else {
-          // The field type must be inferred from getters first.
-          for (ClassMember overriddenMember in overriddenMembers) {
-            if (!overriddenMember.forSetter) {
-              inferFrom(overriddenMember);
-            }
-          }
-          if (inferredType == null) {
-            // The field type must be inferred from setters if no type was
-            // inferred from getters.
-            for (ClassMember overriddenMember in overriddenMembers) {
-              if (overriddenMember.forSetter) {
-                inferFrom(overriddenMember);
-              }
-            }
-          }
-        }
+      if (combinedMemberSignatureType == null) {
+        inferredType = const InvalidType();
+        reportCantInferFieldType(classBuilder, fieldBuilder, overriddenMembers);
+      } else {
+        inferredType = combinedMemberSignatureType;
       }
 
       inferredType ??= const DynamicType();
@@ -1459,6 +1148,15 @@
               messageDeclaredMemberConflictsWithInheritedMemberCause
                   .withLocation(b.fileUri, b.charOffset, name.length)
             ]);
+      } else if (b.classBuilder == classBuilder) {
+        classBuilder.addProblem(
+            messageDeclaredMemberConflictsWithInheritedMember,
+            b.charOffset,
+            name.length,
+            context: <LocatedMessage>[
+              messageDeclaredMemberConflictsWithInheritedMemberCause
+                  .withLocation(a.fileUri, a.charOffset, name.length)
+            ]);
       } else {
         classBuilder.addProblem(messageInheritedMembersConflict,
             classBuilder.charOffset, classBuilder.fullNameForErrors.length,
@@ -1508,15 +1206,6 @@
     }
   }
 
-  void recordAbstractMember(ClassMember member) {
-    abstractMembers ??= <ClassMember>[];
-    if (member.hasDeclarations && classBuilder == member.classBuilder) {
-      abstractMembers.addAll(member.declarations);
-    } else {
-      abstractMembers.add(member);
-    }
-  }
-
   ClassHierarchyNode build() {
     assert(!classBuilder.isPatch);
     ClassHierarchyNode supernode;
@@ -1529,12 +1218,23 @@
       assert(supernode != null);
     }
 
+    /// Set to `true` if the class needs interfaces, that is, if it has any
+    /// members where the interface member is different from its corresponding
+    /// class members.
+    ///
+    /// This is an optimization to avoid unnecessary computation of interface
+    /// members.
+    bool hasInterfaces = false;
+
     Map<Name, Tuple> memberMap = {};
 
     Scope scope = classBuilder.scope;
 
     for (MemberBuilder memberBuilder in scope.localMembers) {
       for (ClassMember classMember in memberBuilder.localMembers) {
+        if (classMember.isAbstract) {
+          hasInterfaces = true;
+        }
         Tuple tuple = memberMap[classMember.name];
         if (tuple == null) {
           memberMap[classMember.name] = new Tuple.declareMember(classMember);
@@ -1543,6 +1243,9 @@
         }
       }
       for (ClassMember classMember in memberBuilder.localSetters) {
+        if (classMember.isAbstract) {
+          hasInterfaces = true;
+        }
         Tuple tuple = memberMap[classMember.name];
         if (tuple == null) {
           memberMap[classMember.name] = new Tuple.declareSetter(classMember);
@@ -1554,6 +1257,9 @@
 
     for (MemberBuilder memberBuilder in scope.localSetters) {
       for (ClassMember classMember in memberBuilder.localMembers) {
+        if (classMember.isAbstract) {
+          hasInterfaces = true;
+        }
         Tuple tuple = memberMap[classMember.name];
         if (tuple == null) {
           memberMap[classMember.name] = new Tuple.declareMember(classMember);
@@ -1562,6 +1268,9 @@
         }
       }
       for (ClassMember classMember in memberBuilder.localSetters) {
+        if (classMember.isAbstract) {
+          hasInterfaces = true;
+        }
         Tuple tuple = memberMap[classMember.name];
         if (tuple == null) {
           memberMap[classMember.name] = new Tuple.declareSetter(classMember);
@@ -1590,6 +1299,9 @@
 
         for (MemberBuilder memberBuilder in scope.localMembers) {
           for (ClassMember classMember in memberBuilder.localMembers) {
+            if (classMember.isAbstract) {
+              hasInterfaces = true;
+            }
             Tuple tuple = memberMap[classMember.name];
             if (tuple == null) {
               memberMap[classMember.name] = new Tuple.mixInMember(classMember);
@@ -1598,6 +1310,9 @@
             }
           }
           for (ClassMember classMember in memberBuilder.localSetters) {
+            if (classMember.isAbstract) {
+              hasInterfaces = true;
+            }
             Tuple tuple = memberMap[classMember.name];
             if (tuple == null) {
               memberMap[classMember.name] = new Tuple.mixInSetter(classMember);
@@ -1609,6 +1324,9 @@
 
         for (MemberBuilder memberBuilder in scope.localSetters) {
           for (ClassMember classMember in memberBuilder.localMembers) {
+            if (classMember.isAbstract) {
+              hasInterfaces = true;
+            }
             Tuple tuple = memberMap[classMember.name];
             if (tuple == null) {
               memberMap[classMember.name] = new Tuple.mixInMember(classMember);
@@ -1617,6 +1335,9 @@
             }
           }
           for (ClassMember classMember in memberBuilder.localSetters) {
+            if (classMember.isAbstract) {
+              hasInterfaces = true;
+            }
             Tuple tuple = memberMap[classMember.name];
             if (tuple == null) {
               memberMap[classMember.name] = new Tuple.mixInSetter(classMember);
@@ -1680,7 +1401,6 @@
       }
     }
 
-    bool hasInterfaces = false;
     if (supernode == null) {
       // This should be Object.
       superclasses = new List<Supertype>.filled(0, null);
@@ -1736,8 +1456,10 @@
         hasInterfaces = true;
       }
 
-      implement(supernode.interfaceMemberMap);
-      implement(supernode.interfaceSetterMap);
+      if (hasInterfaces) {
+        implement(supernode.interfaceMemberMap ?? supernode.classMemberMap);
+        implement(supernode.interfaceSetterMap ?? supernode.classSetterMap);
+      }
 
       if (directInterfaceBuilders != null) {
         for (int i = 0; i < directInterfaceBuilders.length; i++) {
@@ -1830,495 +1552,1460 @@
     /// [ClassHierarchyNode].
     Map<Name, ClassMember> interfaceSetterMap = {};
 
-    void registerOverrideCheck(
-        ClassMember member, ClassMember overriddenMember) {
+    /// Map for members declared in this class to the members that they
+    /// override. This is used for checking valid overrides and to ensure that
+    /// override inference correctly propagates inferred types through the
+    /// class hierarchy.
+    Map<ClassMember, Set<ClassMember>> declaredOverridesMap = {};
+
+    /// In case this class is a mixin application, this maps members declared in
+    /// the mixin to the members that they override. This is used for checking
+    /// valid overrides but _not_ as for [declaredOverridesMap] for override
+    /// inference.
+    Map<ClassMember, Set<ClassMember>> mixinApplicationOverridesMap = {};
+
+    /// In case this class is concrete, this maps concrete members that are
+    /// inherited into this class to the members they should override to validly
+    /// implement the interface of this class.
+    Map<ClassMember, Set<ClassMember>> inheritedImplementsMap = {};
+
+    /// In case this class is concrete, this holds the interface members
+    /// without a corresponding class member. These are either reported as
+    /// missing implementations or trigger insertion of noSuchMethod forwarders.
+    List<ClassMember> abstractMembers = [];
+
+    ClassHierarchyNodeDataForTesting dataForTesting;
+    if (retainDataForTesting) {
+      dataForTesting = new ClassHierarchyNodeDataForTesting(
+          abstractMembers,
+          declaredOverridesMap,
+          mixinApplicationOverridesMap,
+          inheritedImplementsMap);
+    }
+
+    /// Registers that the current class has an interface member without a
+    /// corresponding class member.
+    ///
+    /// This is used to report missing implementation or, in the case the class
+    /// has a user defined concrete noSuchMethod, to insert noSuchMethod
+    /// forwarders. (Currently, insertion of forwarders is handled elsewhere.)
+    ///
+    /// For instance:
+    ///
+    ///    abstract class Interface {
+    ///      method();
+    ///    }
+    ///    class Class1 implements Interface {
+    ///      // Missing implementation for `Interface.method`.
+    ///    }
+    ///    class Class2 implements Interface {
+    ///      noSuchMethod(_) {}
+    ///      // A noSuchMethod forwarder is added for `Interface.method`.
+    ///    }
+    ///
+    void registerAbstractMember(ClassMember abstractMember) {
+      if (!abstractMember.isInternalImplementation) {
+        /// If `isInternalImplementation` is `true`, the member is synthesized
+        /// implementation that does not require implementation in other
+        /// classes.
+        ///
+        /// This is for instance used for late lowering where
+        ///
+        ///    class Interface {
+        ///      late int? field;
+        ///    }
+        ///    class Class implements Interface {
+        ///      int? field;
+        ///    }
+        ///
+        /// is encoded as
+        ///
+        ///    class Interface {
+        ///      bool _#field#isSet = false;
+        ///      int? _#field = null;
+        ///      int? get field => _#field#isSet ? _#field : throw ...;
+        ///      void set field(int? value) { ... }
+        ///    }
+        ///    class Class implements Interface {
+        ///      int? field;
+        ///    }
+        ///
+        /// and `Class` should not be required to implement
+        /// `Interface._#field#isSet` and `Interface._#field`.
+        abstractMembers.add(abstractMember);
+      }
+    }
+
+    /// Registers that [inheritedMember] should be checked to validly override
+    /// [overrides].
+    ///
+    /// This is needed in the case where a concrete member is inherited into
+    /// a concrete subclass. For instance:
+    ///
+    ///    class Super {
+    ///      void method() {}
+    ///    }
+    ///    abstract class Interface {
+    ///      void method();
+    ///    }
+    ///    class Class extends Super implements Interface {}
+    ///
+    /// Here `Super.method` must be checked to be a valid implementation for
+    /// `Interface.method` by being a valid override of it.
+    void registerInheritedImplements(
+        ClassMember inheritedMember, Set<ClassMember> overrides,
+        {ClassMember aliasForTesting}) {
       if (classBuilder is SourceClassBuilder) {
-        if (overriddenMember.hasDeclarations &&
-            classBuilder == overriddenMember.classBuilder) {
-          for (int i = 0; i < overriddenMember.declarations.length; i++) {
-            hierarchy.registerOverrideCheck(
-                classBuilder, member, overriddenMember.declarations[i]);
-          }
-        } else {
-          hierarchy.registerOverrideCheck(
-              classBuilder, member, overriddenMember);
+        assert(
+            inheritedMember.classBuilder != classBuilder,
+            "Only inherited members can implement by inheritance: "
+            "${inheritedMember}");
+        inheritedImplementsMap[inheritedMember] = overrides;
+        if (dataForTesting != null && aliasForTesting != null) {
+          dataForTesting.aliasMap[aliasForTesting] = inheritedMember;
         }
       }
     }
 
-    memberMap.forEach((Name name, Tuple tuple) {
-      Set<ClassMember> overriddenMembers = {};
+    /// Returns `true` if the current class is from an opt-out library and
+    /// [classMember] is from an opt-in library.
+    ///
+    /// In this case a member signature needs to be inserted to show the
+    /// legacy erased type of the interface member. For instance:
+    ///
+    ///    // Opt-in library:
+    ///    class Super {
+    ///      int? method(int i) {}
+    ///    }
+    ///    // Opt-out library:
+    ///    class Class extends Super {
+    ///      // A member signature is inserted:
+    ///      // int* method(int* i);
+    ///    }
+    ///
+    bool needsMemberSignatureFor(ClassMember classMember) {
+      return !classBuilder.library.isNonNullableByDefault &&
+          classMember.classBuilder.library.isNonNullableByDefault;
+    }
 
-      void registerOverrideDependency(
-          ClassMember member, ClassMember overriddenMember) {
-        if (classBuilder == member.classBuilder && member.isSourceDeclaration) {
-          if (overriddenMember.hasDeclarations &&
-              classBuilder == overriddenMember.classBuilder) {
-            for (int i = 0; i < overriddenMember.declarations.length; i++) {
-              registerOverrideDependency(
-                  member, overriddenMember.declarations[i]);
-            }
+    memberMap.forEach((Name name, Tuple tuple) {
+      /// The computation starts by sanitizing the members. Conflicts between
+      /// methods and properties (getters/setters) or between static and
+      /// instance members are reported. Conflicting members and members
+      /// overridden by duplicates are removed.
+      ///
+      /// For this [definingGetable] and [definingSetable] hold the first member
+      /// of its kind found among declared, mixed in, extended and implemented
+      /// members.
+      ///
+      /// Conflicts between [definingGetable] and [definingSetable] are reported
+      /// afterwards.
+
+      ClassMember definingGetable;
+      ClassMember definingSetable;
+
+      ClassMember declaredGetable = tuple.declaredMember;
+      if (declaredGetable != null) {
+        /// class Class {
+        ///   method() {}
+        /// }
+        definingGetable = declaredGetable;
+      }
+      ClassMember declaredSetable = tuple.declaredSetter;
+      if (declaredSetable != null) {
+        /// class Class {
+        ///   set setter(value) {}
+        /// }
+        definingSetable = declaredSetable;
+      }
+
+      ClassMember mixedInGetable;
+      if (tuple.mixedInMember != null &&
+          !tuple.mixedInMember.isStatic &&
+          !tuple.mixedInMember.isDuplicate) {
+        /// We treat
+        ///
+        ///   class Mixin {
+        ///     static method1() {}
+        ///     method2() {}
+        ///     method2() {}
+        ///   }
+        ///   class Class with Mixin {}
+        ///
+        /// as
+        ///
+        ///   class Mixin {}
+        ///   class Class with Mixin {}
+        ///
+        if (definingGetable == null) {
+          /// class Mixin {
+          ///   method() {}
+          /// }
+          /// class Class with Mixin {}
+          definingGetable = mixedInGetable = tuple.mixedInMember;
+        } else if (!definingGetable.isDuplicate) {
+          // This case is currently unreachable from source code since classes
+          // cannot both declare and mix in members. From dill, this can occur
+          // but should not conflicting members.
+          //
+          // The case is handled for consistency.
+          if (definingGetable.isStatic ||
+              definingGetable.isProperty != tuple.mixedInMember.isProperty) {
+            reportInheritanceConflict(definingGetable, tuple.mixedInMember);
           } else {
-            overriddenMembers.add(overriddenMember);
+            mixedInGetable = tuple.mixedInMember;
+          }
+        }
+      }
+      ClassMember mixedInSetable;
+      if (tuple.mixedInSetter != null &&
+          !tuple.mixedInSetter.isStatic &&
+          !tuple.mixedInSetter.isDuplicate) {
+        /// We treat
+        ///
+        ///   class Mixin {
+        ///     static set setter1(value) {}
+        ///     set setter2(value) {}
+        ///     set setter2(value) {}
+        ///   }
+        ///   class Class with Mixin {}
+        ///
+        /// as
+        ///
+        ///   class Mixin {}
+        ///   class Class with Mixin {}
+        ///
+        if (definingSetable == null) {
+          /// class Mixin {
+          ///   set setter(value) {}
+          /// }
+          /// class Class with Mixin {}
+          definingSetable = mixedInSetable = tuple.mixedInSetter;
+        } else if (!definingSetable.isDuplicate) {
+          if (definingSetable.isStatic ||
+              definingSetable.isProperty != tuple.mixedInSetter.isProperty) {
+            reportInheritanceConflict(definingGetable, tuple.mixedInSetter);
+          } else {
+            mixedInSetable = tuple.mixedInSetter;
           }
         }
       }
 
-      ClassMember computeClassMember(
+      ClassMember extendedGetable;
+      if (tuple.extendedMember != null &&
+          !tuple.extendedMember.isStatic &&
+          !tuple.extendedMember.isDuplicate) {
+        /// We treat
+        ///
+        ///   class Super {
+        ///     static method1() {}
+        ///     method2() {}
+        ///     method2() {}
+        ///   }
+        ///   class Class extends Super {}
+        ///
+        /// as
+        ///
+        ///   class Super {}
+        ///   class Class extends Super {}
+        ///
+        if (definingGetable == null) {
+          /// class Super {
+          ///   method() {}
+          /// }
+          /// class Class extends Super {}
+          definingGetable = extendedGetable = tuple.extendedMember;
+        } else if (!definingGetable.isDuplicate) {
+          if (definingGetable.isStatic ||
+              definingGetable.isProperty != tuple.extendedMember.isProperty) {
+            ///   class Super {
+            ///     method() {}
+            ///   }
+            ///   class Class extends Super {
+            ///     static method() {}
+            ///   }
+            ///
+            /// or
+            ///
+            ///   class Super {
+            ///     method() {}
+            ///   }
+            ///   class Class extends Super {
+            ///     get getter => 0;
+            ///   }
+            reportInheritanceConflict(definingGetable, tuple.extendedMember);
+          } else {
+            extendedGetable = tuple.extendedMember;
+          }
+        }
+      }
+      ClassMember extendedSetable;
+      if (tuple.extendedSetter != null &&
+          !tuple.extendedSetter.isStatic &&
+          !tuple.extendedSetter.isDuplicate) {
+        /// We treat
+        ///
+        ///   class Super {
+        ///     static set setter1(value) {}
+        ///     set setter2(value) {}
+        ///     set setter2(value) {}
+        ///   }
+        ///   class Class extends Super {}
+        ///
+        /// as
+        ///
+        ///   class Super {}
+        ///   class Class extends Super {}
+        ///
+        if (definingSetable == null) {
+          /// class Super {
+          ///   set setter(value) {}
+          /// }
+          /// class Class extends Super {}
+          definingSetable = extendedSetable = tuple.extendedSetter;
+        } else if (!definingSetable.isDuplicate) {
+          if (definingSetable.isStatic ||
+              definingSetable.isProperty != tuple.extendedSetter.isProperty) {
+            reportInheritanceConflict(definingSetable, tuple.extendedSetter);
+          } else {
+            extendedSetable = tuple.extendedSetter;
+          }
+        }
+      }
+
+      // TODO(johnniwinther): Remove extended and mixed in members/setters
+      // from implemented members/setters. Mixin applications always implement
+      // the mixin class leading to unnecessary interface members.
+      List<ClassMember> implementedGetables;
+      if (tuple.implementedMembers != null &&
+          // Skip implemented members if we already have a duplicate.
+          !(definingGetable != null && definingGetable.isDuplicate)) {
+        for (int i = 0; i < tuple.implementedMembers.length; i++) {
+          ClassMember implementedGetable = tuple.implementedMembers[i];
+          if (implementedGetable.isStatic || implementedGetable.isDuplicate) {
+            /// We treat
+            ///
+            ///   class Interface {
+            ///     static method1() {}
+            ///     method2() {}
+            ///     method2() {}
+            ///   }
+            ///   class Class implements Interface {}
+            ///
+            /// as
+            ///
+            ///   class Interface {}
+            ///   class Class implements Interface {}
+            ///
+            implementedGetable = null;
+          } else {
+            if (definingGetable == null) {
+              /// class Interface {
+              ///   method() {}
+              /// }
+              /// class Class implements Interface {}
+              definingGetable = implementedGetable;
+            } else if (definingGetable.isStatic ||
+                definingGetable.isProperty != implementedGetable.isProperty) {
+              ///   class Interface {
+              ///     method() {}
+              ///   }
+              ///   class Class implements Interface {
+              ///     static method() {}
+              ///   }
+              ///
+              /// or
+              ///
+              ///   class Interface {
+              ///     method() {}
+              ///   }
+              ///   class Class implements Interface {
+              ///     get getter => 0;
+              ///   }
+              reportInheritanceConflict(definingGetable, implementedGetable);
+              implementedGetable = null;
+            }
+          }
+          if (implementedGetable == null) {
+            // On the first skipped member we add all previous.
+            implementedGetables ??= tuple.implementedMembers.take(i).toList();
+          } else if (implementedGetables != null) {
+            // If already skipping members we add [implementedGetable]
+            // explicitly.
+            implementedGetables.add(implementedGetable);
+          }
+        }
+        if (implementedGetables == null) {
+          // No members were skipped so we use the full list.
+          implementedGetables = tuple.implementedMembers;
+        } else if (implementedGetables.isEmpty) {
+          // No members were included.
+          implementedGetables = null;
+        }
+      }
+
+      List<ClassMember> implementedSetables;
+      if (tuple.implementedSetters != null &&
+          // Skip implemented setters if we already have a duplicate.
+          !(definingSetable != null && definingSetable.isDuplicate)) {
+        for (int i = 0; i < tuple.implementedSetters.length; i++) {
+          ClassMember implementedSetable = tuple.implementedSetters[i];
+          if (implementedSetable.isStatic || implementedSetable.isDuplicate) {
+            /// We treat
+            ///
+            ///   class Interface {
+            ///     static set setter1(value) {}
+            ///     set setter2(value) {}
+            ///     set setter2(value) {}
+            ///   }
+            ///   class Class implements Interface {}
+            ///
+            /// as
+            ///
+            ///   class Interface {}
+            ///   class Class implements Interface {}
+            ///
+            implementedSetable = null;
+          } else {
+            if (definingSetable == null) {
+              /// class Interface {
+              ///   set setter(value) {}
+              /// }
+              /// class Class implements Interface {}
+              definingSetable = implementedSetable;
+            } else if (definingSetable.isStatic ||
+                definingSetable.isProperty != implementedSetable.isProperty) {
+              /// class Interface {
+              ///   set setter(value) {}
+              /// }
+              /// class Class implements Interface {
+              ///   static set setter(value) {}
+              /// }
+              reportInheritanceConflict(definingSetable, implementedSetable);
+              implementedSetable = null;
+            }
+          }
+          if (implementedSetable == null) {
+            // On the first skipped setter we add all previous.
+            implementedSetables ??= tuple.implementedSetters.take(i).toList();
+          } else if (implementedSetables != null) {
+            // If already skipping setters we add [implementedSetable]
+            // explicitly.
+            implementedSetables.add(implementedSetable);
+          }
+        }
+        if (implementedSetables == null) {
+          // No setters were skipped so we use the full list.
+          implementedSetables = tuple.implementedSetters;
+        } else if (implementedSetables.isEmpty) {
+          // No setters were included.
+          implementedSetables = null;
+        }
+      }
+
+      if (definingGetable != null && definingSetable != null) {
+        if (definingGetable.isStatic != definingSetable.isStatic ||
+            definingGetable.isProperty != definingSetable.isProperty) {
+          reportInheritanceConflict(definingGetable, definingSetable);
+          // TODO(johnniwinther): Should we remove [definingSetable]? If we
+          // leave it in this conflict will also be reported in subclasses. If
+          // we remove it, any write to the setable will be unresolved.
+        }
+      }
+
+      // TODO(johnniwinther): Handle declared members together with mixed in
+      // members. This should only occur from .dill, though.
+      if (mixedInGetable != null) {
+        declaredGetable = null;
+      }
+      if (mixedInSetable != null) {
+        declaredSetable = null;
+      }
+
+      /// Set to `true` if declared members have been registered in
+      /// [registerDeclaredOverride] or [registerMixedInOverride].
+      bool hasDeclaredMembers = false;
+
+      /// Declared methods, getters and setters registered in
+      /// [registerDeclaredOverride].
+      ClassMember declaredMethod;
+      List<ClassMember> declaredProperties;
+
+      /// Declared methods, getters and setters registered in
+      /// [registerDeclaredOverride].
+      ClassMember mixedInMethod;
+      List<ClassMember> mixedInProperties;
+
+      /// Registers that [declaredMember] overrides extended and implemented
+      /// members.
+      ///
+      /// Getters and setters share overridden members so the registration
+      /// of override relations is performed after the interface members have
+      /// been computed.
+      ///
+      /// Declared members must be checked for valid override of the overridden
+      /// members _and_ must register an override dependency with the overridden
+      /// members so that override inference can propagate inferred types
+      /// correctly. For instance:
+      ///
+      ///    class Super {
+      ///      int get property => 42;
+      ///    }
+      ///    class Class extends Super {
+      ///      void set property(value) {}
+      ///    }
+      ///
+      /// Here the parameter type of the setter `Class.property` must be
+      /// inferred from the type of the getter `Super.property`.
+      void registerDeclaredOverride(ClassMember declaredMember,
+          {ClassMember aliasForTesting}) {
+        if (classBuilder is SourceClassBuilder && !declaredMember.isStatic) {
+          assert(
+              declaredMember.isSourceDeclaration &&
+                  declaredMember.classBuilder == classBuilder,
+              "Only declared members can override: ${declaredMember}");
+          hasDeclaredMembers = true;
+          if (declaredMember.isProperty) {
+            declaredProperties ??= [];
+            declaredProperties.add(declaredMember);
+          } else {
+            assert(
+                declaredMethod == null,
+                "Multiple methods unexpectedly declared: "
+                "${declaredMethod} and ${declaredMember}.");
+            declaredMethod = declaredMember;
+          }
+          if (dataForTesting != null && aliasForTesting != null) {
+            dataForTesting.aliasMap[aliasForTesting] = declaredMember;
+          }
+        }
+      }
+
+      /// Registers that [mixedMember] overrides extended and implemented
+      /// members through application.
+      ///
+      /// Getters and setters share overridden members so the registration
+      /// of override relations in performed after the interface members have
+      /// been computed.
+      ///
+      /// Declared mixed in members must be checked for valid override of the
+      /// overridden members but _not_ register an override dependency with the
+      /// overridden members. This is in contrast to declared members. For
+      /// instance:
+      ///
+      ///    class Super {
+      ///      int get property => 42;
+      ///    }
+      ///    class Mixin {
+      ///      void set property(value) {}
+      ///    }
+      ///    class Class = Super with Mixin;
+      ///
+      /// Here the parameter type of the setter `Mixin.property` must _not_ be
+      /// inferred from the type of the getter `Super.property`, but should
+      /// instead default to `dynamic`.
+      void registerMixedInOverride(ClassMember mixedInMember,
+          {ClassMember aliasForTesting}) {
+        assert(mixedInMember.classBuilder != classBuilder,
+            "Only mixin members can override by application: ${mixedInMember}");
+        if (classBuilder is SourceClassBuilder) {
+          hasDeclaredMembers = true;
+          if (mixedInMember.isProperty) {
+            mixedInProperties ??= [];
+            mixedInProperties.add(mixedInMember);
+          } else {
+            assert(
+                mixedInMethod == null,
+                "Multiple methods unexpectedly declared in mixin: "
+                "${mixedInMethod} and ${mixedInMember}.");
+            mixedInMethod = mixedInMember;
+          }
+          if (dataForTesting != null && aliasForTesting != null) {
+            dataForTesting.aliasMap[aliasForTesting] = mixedInMember;
+          }
+        }
+      }
+
+      /// Computes the class and interface members for a method, getter, or
+      /// setter in the current [tuple].
+      ///
+      /// [definingMember] is the member which defines whether the computation
+      /// is for a method, a getter or a setter.
+      /// [declaredMember] is the member declared in the current class, if any.
+      /// [mixedInMember] is the member declared in a mixin that is mixed into
+      /// the current current class, if any.
+      /// [extendedMember] is the member inherited from the super class.
+      /// [implementedMembers] are the members inherited from the super
+      /// interfaces, if none this is `null`.
+      ///
+      /// The computed class and interface members are added to [classMemberMap]
+      /// and [interfaceMemberMap], respectively.
+      ClassMember computeMembers(
+          {ClassMember definingMember,
           ClassMember declaredMember,
           ClassMember mixedInMember,
           ClassMember extendedMember,
-          bool forSetter) {
+          List<ClassMember> implementedMembers,
+          Map<Name, ClassMember> classMemberMap,
+          Map<Name, ClassMember> interfaceMemberMap}) {
+        ClassMember classMember;
+        ClassMember interfaceMember;
+
         if (mixedInMember != null) {
-          // TODO(johnniwinther): Handle members declared in mixin applications
-          // correctly.
-          declaredMember = null;
-        }
-        if (declaredMember != null) {
-          if (extendedMember != null && !extendedMember.isStatic) {
-            if (declaredMember == extendedMember) return declaredMember;
-            if (declaredMember.isDuplicate || extendedMember.isDuplicate) {
-              // Don't check overrides involving duplicated members.
-              return declaredMember;
-            }
-            ClassMember result =
-                checkInheritanceConflict(declaredMember, extendedMember);
-            if (result != null) return result;
-            assert(
-                declaredMember.isProperty == extendedMember.isProperty,
-                "Unexpected member combination: "
-                "$declaredMember vs $extendedMember");
-            result = declaredMember;
+          if (mixedInMember.isAbstract) {
+            ///    class Mixin {
+            ///      method();
+            ///    }
+            ///    class Class = Object with Mixin;
 
-            // [declaredMember] is a method declared in [cls]. This means it
-            // defines the interface of this class regardless if its abstract.
-            if (!declaredMember.isSynthesized) {
-              registerOverrideDependency(
-                  declaredMember, extendedMember.abstract);
-              registerOverrideCheck(declaredMember, extendedMember.abstract);
+            /// Interface members from the extended, mixed in, and implemented
+            /// members define the combined member signature.
+            Set<ClassMember> interfaceMembers = {};
+
+            if (extendedMember != null) {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Mixin {
+              ///      method();
+              ///    }
+              ///    class Class = Super with Mixin;
+              interfaceMembers.add(extendedMember.interfaceMember);
             }
 
-            if (declaredMember.isAbstract) {
-              if (extendedMember.isAbstract) {
-                recordAbstractMember(declaredMember);
-              } else {
-                if (!classBuilder.isAbstract) {
-                  // The interface of this class is [declaredMember]. But the
-                  // implementation is [extendedMember]. So [extendedMember]
-                  // must implement [declaredMember], unless [cls] is abstract.
-                  registerOverrideCheck(extendedMember, declaredMember);
-                }
-                ClassMember concrete = extendedMember.concrete;
-                result = new AbstractMemberOverridingImplementation(
-                    classBuilder,
-                    declaredMember,
-                    concrete,
-                    declaredMember.isProperty,
-                    forSetter,
-                    shouldModifyKernel,
-                    concrete.isAbstract,
-                    concrete.name);
-                hierarchy.registerMemberComputation(result);
+            interfaceMembers.add(mixedInMember);
+
+            if (implementedMembers != null) {
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Mixin {
+              ///      method();
+              ///    }
+              ///    class Class = Object with Mixin implements Interface;
+              interfaceMembers.addAll(implementedMembers);
+            }
+
+            /// We always create a synthesized interface member, even in the
+            /// case of [interfaceMembers] being a singleton, to insert the
+            /// abstract mixin stub.
+            interfaceMember = new SynthesizedInterfaceMember(
+                classBuilder, name, interfaceMembers.toList(),
+                superClassMember: extendedMember,
+                canonicalMember: mixedInMember,
+                mixedInMember: mixedInMember,
+                isProperty: definingMember.isProperty,
+                forSetter: definingMember.forSetter,
+                shouldModifyKernel: shouldModifyKernel);
+            hierarchy.registerMemberComputation(interfaceMember);
+
+            if (extendedMember != null) {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Mixin {
+              ///      method();
+              ///    }
+              ///    class Class = Super with Mixin;
+              ///
+              /// The concrete extended member is the class member but might
+              /// be overwritten by a concrete forwarding stub:
+              ///
+              ///    class Super {
+              ///      method(int i) {}
+              ///    }
+              ///    class Interface {
+              ///      method(covariant int i) {}
+              ///    }
+              ///    class Mixin {
+              ///      method(int i);
+              ///    }
+              ///    // A concrete forwarding stub
+              ///    //   method(covariant int i) => super.method(i);
+              ///    // will be inserted.
+              ///    class Class = Super with Mixin implements Interface;
+              ///
+              classMember = new InheritedClassMemberImplementsInterface(
+                  classBuilder, name,
+                  inheritedClassMember: extendedMember,
+                  implementedInterfaceMember: interfaceMember,
+                  forSetter: definingMember.forSetter,
+                  isProperty: definingMember.isProperty);
+              hierarchy.registerMemberComputation(classMember);
+              if (!classBuilder.isAbstract) {
+                registerInheritedImplements(extendedMember, {interfaceMember},
+                    aliasForTesting: classMember);
               }
+            } else if (!classBuilder.isAbstract) {
+              ///    class Mixin {
+              ///      method(); // Missing implementation.
+              ///    }
+              ///    class Class = Object with Mixin;
+              registerAbstractMember(interfaceMember);
             }
-            assert(
-                !(classBuilder.isMixinApplication &&
-                    declaredMember.classBuilder != classBuilder),
-                "Unexpected declared member ${declaredMember} in "
-                "${classBuilder} from foreign class.");
 
-            if (result.name == noSuchMethodName &&
-                !result.isObjectMember(objectClass)) {
-              hasNoSuchMethod = true;
-            }
-            return result;
-          } else {
-            if (declaredMember.isAbstract) {
-              recordAbstractMember(declaredMember);
-            }
-            return declaredMember;
-          }
-        } else if (mixedInMember != null) {
-          if (extendedMember != null && !extendedMember.isStatic) {
-            if (mixedInMember == extendedMember) return mixedInMember;
-            if (mixedInMember.isDuplicate || extendedMember.isDuplicate) {
-              // Don't check overrides involving duplicated members.
-              return mixedInMember;
-            }
-            ClassMember result =
-                checkInheritanceConflict(mixedInMember, extendedMember);
-            if (result != null) return result;
-            assert(
-                mixedInMember.isProperty == extendedMember.isProperty,
-                "Unexpected member combination: "
-                "$mixedInMember vs $extendedMember");
-            result = mixedInMember;
-
-            // [declaredMember] is a method declared in [cls]. This means it
-            // defines the interface of this class regardless if its abstract.
             if (!mixedInMember.isSynthesized) {
-              registerOverrideDependency(
-                  mixedInMember, extendedMember.abstract);
-              registerOverrideCheck(mixedInMember, extendedMember.abstract);
+              /// Members declared in the mixin must override extended and
+              /// implemented members.
+              ///
+              /// When loading from .dill the mixed in member might be
+              /// synthesized, for instance a member signature or forwarding
+              /// stub, and this should not be checked to override the extended
+              /// and implemented members:
+              ///
+              ///    // Opt-out library, from source:
+              ///    class Mixin {}
+              ///    // Opt-out library, from .dill:
+              ///    class Mixin {
+              ///      ...
+              ///      String* toString(); // member signature
+              ///    }
+              ///    // Opt-out library, from source:
+              ///    class Class = Object with Mixin;
+              ///    // Mixin.toString should not be checked to override
+              ///    // Object.toString.
+              ///
+              registerMixedInOverride(mixedInMember,
+                  aliasForTesting: interfaceMember);
             }
-
-            if (mixedInMember.isAbstract) {
-              if (extendedMember.isAbstract) {
-                recordAbstractMember(mixedInMember);
-              } else {
-                if (!classBuilder.isAbstract) {
-                  // The interface of this class is [declaredMember]. But the
-                  // implementation is [extendedMember]. So [extendedMember]
-                  // must implement [declaredMember], unless [cls] is abstract.
-                  registerOverrideCheck(extendedMember, mixedInMember);
-                }
-                ClassMember concrete = extendedMember.concrete;
-                result = new AbstractMemberOverridingImplementation(
-                    classBuilder,
-                    mixedInMember,
-                    concrete,
-                    mixedInMember.isProperty,
-                    forSetter,
-                    shouldModifyKernel,
-                    concrete.isAbstract,
-                    concrete.name);
-                hierarchy.registerMemberComputation(result);
-              }
-            } else {
-              assert(
-                  (classBuilder.isMixinApplication &&
-                      mixedInMember.classBuilder != classBuilder),
-                  "Unexpected mixed in member ${mixedInMember} in "
-                  "${classBuilder} from the current class.");
-              result = InheritedImplementationInterfaceConflict.combined(
-                  classBuilder,
-                  mixedInMember,
-                  extendedMember,
-                  forSetter,
-                  shouldModifyKernel,
-                  isInheritableConflict: false);
-              if (result.needsComputation) {
-                hierarchy.registerMemberComputation(result);
-              }
-            }
-
-            if (result.name == noSuchMethodName &&
-                !result.isObjectMember(objectClass)) {
-              hasNoSuchMethod = true;
-            }
-            return result;
           } else {
-            if (mixedInMember.isAbstract) {
-              recordAbstractMember(mixedInMember);
+            assert(!mixedInMember.isAbstract);
+
+            ///    class Mixin {
+            ///      method() {}
+            ///    }
+            ///    class Class = Object with Mixin;
+            ///
+
+            /// Interface members from the extended, mixed in, and implemented
+            /// members define the combined member signature.
+            Set<ClassMember> interfaceMembers = {};
+
+            if (extendedMember != null) {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Mixin {
+              ///      method() {}
+              ///    }
+              ///    class Class = Super with Mixin;
+              interfaceMembers.add(extendedMember.interfaceMember);
             }
-            return mixedInMember;
-          }
-        } else if (extendedMember != null && !extendedMember.isStatic) {
-          if (extendedMember.isAbstract) {
-            if (isNameVisibleIn(extendedMember.name, classBuilder.library)) {
-              recordAbstractMember(extendedMember);
+
+            interfaceMembers.add(mixedInMember);
+
+            if (implementedMembers != null) {
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Mixin {
+              ///      method() {}
+              ///    }
+              ///    class Class = Object with Mixin implements Interface;
+              interfaceMembers.addAll(implementedMembers);
+            }
+
+            /// We always create a synthesized interface member, even in the
+            /// case of [interfaceMembers] being a singleton, to insert the
+            /// concrete mixin stub.
+            interfaceMember = new SynthesizedInterfaceMember(
+                classBuilder, name, interfaceMembers.toList(),
+                superClassMember: mixedInMember,
+                canonicalMember: mixedInMember,
+                mixedInMember: mixedInMember,
+                isProperty: definingMember.isProperty,
+                forSetter: definingMember.forSetter,
+                shouldModifyKernel: shouldModifyKernel);
+            hierarchy.registerMemberComputation(interfaceMember);
+
+            /// The concrete mixed in member is the class member but will
+            /// be overwritten by a concrete mixin stub:
+            ///
+            ///    class Mixin {
+            ///       method() {}
+            ///    }
+            ///    // A concrete mixin stub
+            ///    //   method() => super.method();
+            ///    // will be inserted.
+            ///    class Class = Object with Mixin;
+            ///
+            classMember = new InheritedClassMemberImplementsInterface(
+                classBuilder, name,
+                inheritedClassMember: mixedInMember,
+                implementedInterfaceMember: interfaceMember,
+                forSetter: definingMember.forSetter,
+                isProperty: definingMember.isProperty);
+            hierarchy.registerMemberComputation(classMember);
+
+            if (!classBuilder.isAbstract) {
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Mixin {
+              ///      method() {}
+              ///    }
+              ///    class Class = Object with Mixin;
+              ///
+              /// [mixinMember] must implemented interface member.
+              registerInheritedImplements(mixedInMember, {interfaceMember},
+                  aliasForTesting: classMember);
+            }
+            if (!mixedInMember.isSynthesized) {
+              /// Members declared in the mixin must override extended and
+              /// implemented members.
+              ///
+              /// When loading from .dill the mixed in member might be
+              /// synthesized, for instance a member signature or forwarding
+              /// stub, and this should not be checked to override the extended
+              /// and implemented members.
+              ///
+              /// These synthesized mixed in members should always be abstract
+              /// and therefore not be handled here, but we handled them here
+              /// for consistency.
+              registerMixedInOverride(mixedInMember);
             }
           }
-          if (extendedMember.name == noSuchMethodName &&
-              !extendedMember.isObjectMember(objectClass)) {
+        } else if (declaredMember != null) {
+          if (declaredMember.isAbstract) {
+            ///    class Class {
+            ///      method();
+            ///    }
+            interfaceMember = declaredMember;
+
+            /// Interface members from the declared, extended, and implemented
+            /// members define the combined member signature.
+            Set<ClassMember> interfaceMembers = {};
+
+            if (extendedMember != null) {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Class extends Super {
+              ///      method();
+              ///    }
+              interfaceMembers.add(extendedMember);
+            }
+
+            interfaceMembers.add(declaredMember);
+
+            if (implementedMembers != null) {
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Class implements Interface {
+              ///      method();
+              ///    }
+              interfaceMembers.addAll(implementedMembers);
+            }
+
+            /// If only one member defines the interface member there is no
+            /// need for a synthesized interface member, since its result will
+            /// simply be that one member.
+            if (interfaceMembers.length > 1) {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Class extends Super implements Interface {
+              ///      method();
+              ///    }
+              interfaceMember = new SynthesizedInterfaceMember(
+                  classBuilder, name, interfaceMembers.toList(),
+                  superClassMember: extendedMember,
+                  canonicalMember: declaredMember,
+                  isProperty: definingMember.isProperty,
+                  forSetter: definingMember.forSetter,
+                  shouldModifyKernel: shouldModifyKernel);
+              hierarchy.registerMemberComputation(interfaceMember);
+            }
+
+            if (extendedMember != null) {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Class extends Super {
+              ///      method();
+              ///    }
+              ///
+              /// The concrete extended member is the class member but might
+              /// be overwritten by a concrete forwarding stub:
+              ///
+              ///    class Super {
+              ///      method(int i) {}
+              ///    }
+              ///    class Interface {
+              ///      method(covariant int i) {}
+              ///    }
+              ///    class Class extends Super implements Interface {
+              ///      // This will be turned into the concrete forwarding stub
+              ///      //    method(covariant int i) => super.method(i);
+              ///      method(int i);
+              ///    }
+              ///
+              classMember = new InheritedClassMemberImplementsInterface(
+                  classBuilder, name,
+                  inheritedClassMember: extendedMember,
+                  implementedInterfaceMember: interfaceMember,
+                  forSetter: definingMember.forSetter,
+                  isProperty: definingMember.isProperty);
+              hierarchy.registerMemberComputation(classMember);
+
+              if (!classBuilder.isAbstract) {
+                ///    class Super {
+                ///      method() {}
+                ///    }
+                ///    class Class extends Super {
+                ///      method();
+                ///    }
+                ///
+                /// [extendedMember] must implemented interface member.
+                registerInheritedImplements(extendedMember, {interfaceMember},
+                    aliasForTesting: classMember);
+              }
+            } else if (!classBuilder.isAbstract) {
+              ///    class Class {
+              ///      method(); // Missing implementation.
+              ///    }
+              registerAbstractMember(declaredMember);
+            }
+
+            /// The declared member must override extended and implemented
+            /// members.
+            registerDeclaredOverride(declaredMember,
+                aliasForTesting: interfaceMember);
+          } else {
+            assert(!declaredMember.isAbstract);
+
+            ///    class Class {
+            ///      method() {}
+            ///    }
+            classMember = declaredMember;
+
+            /// The declared member must override extended and implemented
+            /// members.
+            registerDeclaredOverride(declaredMember);
+          }
+        } else if (extendedMember != null) {
+          ///    class Super {
+          ///      method() {}
+          ///    }
+          ///    class Class extends Super {}
+          assert(!extendedMember.isAbstract,
+              "Abstract extended member: ${extendedMember}");
+
+          classMember = extendedMember;
+
+          if (implementedMembers != null) {
+            ///    class Super {
+            ///      method() {}
+            ///    }
+            ///    class Interface {
+            ///      method() {}
+            ///    }
+            ///    class Class extends Super implements Interface {}
+            ClassMember extendedInterfaceMember =
+                extendedMember.interfaceMember;
+
+            /// Interface members from the extended and implemented
+            /// members define the combined member signature.
+            Set<ClassMember> interfaceMembers = {extendedInterfaceMember};
+
+            // TODO(johnniwinther): The extended member might be included in
+            // a synthesized implemented member. For instance:
+            //
+            //    class Super {
+            //      void method() {}
+            //    }
+            //    class Interface {
+            //      void method() {}
+            //    }
+            //    abstract class Class extends Super implements Interface {
+            //      // Synthesized interface member of
+            //      //   {Super.method, Interface.method}
+            //    }
+            //    class Sub extends Class {
+            //      // Super.method implements Class.method =
+            //      //   {Super.method, Interface.method}
+            //      // Synthesized interface member of
+            //      //   {Super.method, Class.method}
+            //    }
+            //
+            // Maybe we should recognized this.
+            interfaceMembers.addAll(implementedMembers);
+
+            /// Normally, if only one member defines the interface member there
+            /// is no need for a synthesized interface member, since its result
+            /// will simply be that one member, but if the extended member is
+            /// from an opt-in library and the current class is from an opt-out
+            /// library we need to create a member signature:
+            ///
+            ///    // Opt-in:
+            ///    class Super {
+            ///      int? method() => null;
+            ///    }
+            ///    class Interface implements Super {}
+            ///    // Opt-out:
+            ///    class Class extends Super implements Interface {
+            ///      // Member signature added:
+            ///      int* method();
+            ///    }
+            ///
+            if (interfaceMembers.length == 1 &&
+                !needsMemberSignatureFor(extendedInterfaceMember)) {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Interface implements Super {}
+              ///    class Class extends Super implements Interface {}
+              interfaceMember = interfaceMembers.first;
+            } else {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Class extends Super implements Interface {}
+              interfaceMember = new SynthesizedInterfaceMember(
+                  classBuilder, name, interfaceMembers.toList(),
+                  superClassMember: extendedMember,
+                  isProperty: definingMember.isProperty,
+                  forSetter: definingMember.forSetter,
+                  shouldModifyKernel: shouldModifyKernel);
+              hierarchy.registerMemberComputation(interfaceMember);
+            }
+            if (interfaceMember == classMember) {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Interface implements Super {}
+              ///    class Class extends Super implements Interface {}
+              ///
+              /// We keep track of whether a class needs interfaces, that is,
+              /// whether is has any members that have an interface member
+              /// different from its corresponding class member, so we set
+              /// [interfaceMember] to `null` so show that the interface member
+              /// is not needed.
+              interfaceMember = null;
+            } else {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Class extends Super implements Interface {}
+              ///
+              /// The concrete extended member is the class member but might
+              /// be overwritten by a concrete forwarding stub:
+              ///
+              ///    class Super {
+              ///      method(int i) {}
+              ///    }
+              ///    class Interface {
+              ///      method(covariant int i) {}
+              ///    }
+              ///    class Class extends Super implements Interface {
+              ///      // A concrete forwarding stub will be created:
+              ///      //    method(covariant int i) => super.method(i);
+              ///    }
+              ///
+              classMember = new InheritedClassMemberImplementsInterface(
+                  classBuilder, name,
+                  inheritedClassMember: extendedMember,
+                  implementedInterfaceMember: interfaceMember,
+                  isProperty: definingMember.isProperty,
+                  forSetter: definingMember.forSetter);
+              hierarchy.registerMemberComputation(classMember);
+              if (!classBuilder.isAbstract) {
+                ///    class Super {
+                ///      method() {}
+                ///    }
+                ///    class Interface {
+                ///      method() {}
+                ///    }
+                ///    class Class extends Super implements Interface {}
+                registerInheritedImplements(extendedMember, {interfaceMember},
+                    aliasForTesting: classMember);
+              }
+            }
+          } else if (needsMemberSignatureFor(extendedMember)) {
+            ///    // Opt-in library:
+            ///    class Super {
+            ///      method() {}
+            ///    }
+            ///    // opt-out library:
+            ///    class Class extends Super {}
+            interfaceMember = new SynthesizedInterfaceMember(
+                classBuilder, name, [extendedMember],
+                superClassMember: extendedMember,
+                isProperty: definingMember.isProperty,
+                forSetter: definingMember.forSetter,
+                shouldModifyKernel: shouldModifyKernel);
+            hierarchy.registerMemberComputation(interfaceMember);
+
+            /// The concrete extended member is the class member and should
+            /// be able to be overwritten by a synthesized concrete member here,
+            /// but we handle the case for consistency.
+            classMember = new InheritedClassMemberImplementsInterface(
+                classBuilder, name,
+                inheritedClassMember: extendedMember,
+                implementedInterfaceMember: interfaceMember,
+                isProperty: definingMember.isProperty,
+                forSetter: definingMember.forSetter);
+            hierarchy.registerMemberComputation(classMember);
+          }
+        } else if (implementedMembers != null) {
+          ///    class Interface {
+          ///      method() {}
+          ///    }
+          ///    class Class implements Interface {}
+          Set<ClassMember> interfaceMembers = implementedMembers.toSet();
+          if (interfaceMembers.isNotEmpty) {
+            /// Normally, if only one member defines the interface member there
+            /// is no need for a synthesized interface member, since its result
+            /// will simply be that one member, but if the implemented member is
+            /// from an opt-in library and the current class is from an opt-out
+            /// library we need to create a member signature:
+            ///
+            ///    // Opt-in:
+            ///    class Interface {
+            ///      int? method() => null;
+            ///    }
+            ///    // Opt-out:
+            ///    class Class implements Interface {
+            ///      // Member signature added:
+            ///      int* method();
+            ///    }
+            ///
+            if (interfaceMembers.length == 1 &&
+                !needsMemberSignatureFor(interfaceMembers.first)) {
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Class implements Interface {}
+              interfaceMember = interfaceMembers.first;
+            } else {
+              ///    class Interface1 {
+              ///      method() {}
+              ///    }
+              ///    class Interface2 {
+              ///      method() {}
+              ///    }
+              ///    class Class implements Interface1, Interface2 {}
+              interfaceMember = new SynthesizedInterfaceMember(
+                  classBuilder, name, interfaceMembers.toList(),
+                  isProperty: definingMember.isProperty,
+                  forSetter: definingMember.forSetter,
+                  shouldModifyKernel: shouldModifyKernel);
+              hierarchy.registerMemberComputation(interfaceMember);
+            }
+            if (!classBuilder.isAbstract) {
+              ///    class Interface {
+              ///      method() {}
+              ///    }
+              ///    class Class implements Interface {}
+              for (ClassMember abstractMember in interfaceMembers) {
+                registerAbstractMember(abstractMember);
+              }
+            }
+          }
+        }
+
+        if (interfaceMember != null) {
+          // We have an explicit interface.
+          hasInterfaces = true;
+        }
+        if (classMember != null) {
+          if (name == noSuchMethodName &&
+              !classMember.isObjectMember(objectClass)) {
             hasNoSuchMethod = true;
           }
-          if (extendedMember.isInheritableConflict) {
-            extendedMember = extendedMember.withParent(classBuilder);
-            hierarchy.registerMemberComputation(extendedMember);
-          }
-          if (extendedMember.classBuilder.library.isNonNullableByDefault &&
-              !classBuilder.library.isNonNullableByDefault) {
-            if (!extendedMember.isSynthesized) {
-              extendedMember = new InterfaceConflict(
-                  classBuilder,
-                  [extendedMember],
-                  extendedMember.isProperty,
-                  forSetter,
-                  shouldModifyKernel,
-                  extendedMember.isAbstract,
-                  extendedMember.name,
-                  isImplicitlyAbstract: extendedMember.isAbstract);
-              hierarchy.registerMemberComputation(extendedMember);
-            }
-          }
-          return extendedMember;
+          classMemberMap[name] = classMember;
+          interfaceMember ??= classMember.interfaceMember;
         }
-        return null;
-      }
-
-      ClassMember computeInterfaceMember(ClassMember classMember,
-          List<ClassMember> implementedMembers, bool forSetter) {
-        ClassMember interfaceMember;
-        if (implementedMembers != null) {
-          for (ClassMember member in implementedMembers) {
-            if (member.isStatic) continue;
-            if (interfaceMember == null) {
-              interfaceMember = member;
-            } else {
-              ClassMember handleMergeConflict(ClassMember a, ClassMember b) {
-                if (a == b) return a;
-                if (a.isDuplicate || b.isDuplicate) {
-                  // Don't check overrides involving duplicated members.
-                  return a;
-                }
-                ClassMember result = checkInheritanceConflict(a, b);
-                if (result != null) return result;
-                assert(a.isProperty == b.isProperty,
-                    "Unexpected member combination: $a vs $b");
-                result = a;
-                result = InterfaceConflict.combined(
-                    classBuilder, a, b, forSetter, shouldModifyKernel);
-                return result;
-              }
-
-              interfaceMember = handleMergeConflict(interfaceMember, member);
-            }
-          }
-        }
-        if (hasInterfaces) {
-          if (interfaceMember != null) {
-            if (classMember != null) {
-              if (classMember == interfaceMember) return classMember;
-              if (classMember.isDuplicate || interfaceMember.isDuplicate) {
-                // Don't check overrides involving duplicated members.
-                return classMember;
-              }
-              ClassMember result =
-                  checkInheritanceConflict(classMember, interfaceMember);
-              if (result != null) return result;
-              assert(
-                  classMember.isProperty == interfaceMember.isProperty,
-                  "Unexpected member combination: "
-                  "$classMember vs $interfaceMember");
-              result = classMember;
-
-              // [interfaceMember] is inherited from an interface so it is
-              // implicitly abstract.
-              classMember = classMember.abstract;
-              interfaceMember = interfaceMember.abstract;
-
-              // If [classMember] is declared in this class, it defines the
-              // interface.
-              if (classMember.classBuilder == classBuilder) {
-                if (!classMember.isSynthesized) {
-                  registerOverrideDependency(classMember, interfaceMember);
-                  registerOverrideCheck(classMember, interfaceMember);
-                }
-                if (classMember.hasDeclarations) {
-                  if (interfaceMember.hasDeclarations &&
-                      interfaceMember.classBuilder == classBuilder) {
-                    addAllDeclarationsTo(
-                        interfaceMember, classMember.declarations);
-                  } else {
-                    addDeclarationIfDifferent(
-                        interfaceMember, classMember.declarations);
-                  }
-                }
-              } else {
-                if (classMember.isAbstract) {
-                  result = InterfaceConflict.combined(classBuilder, classMember,
-                      interfaceMember, forSetter, shouldModifyKernel);
-                } else {
-                  result = InheritedImplementationInterfaceConflict.combined(
-                      classBuilder,
-                      classMember,
-                      interfaceMember,
-                      forSetter,
-                      shouldModifyKernel);
-                }
-                if (result.needsComputation) {
-                  hierarchy.registerMemberComputation(result);
-                }
-              }
-
-              return result;
-            } else {
-              if (isNameVisibleIn(interfaceMember.name, classBuilder.library)) {
-                if (!interfaceMember.isInternalImplementation) {
-                  recordAbstractMember(interfaceMember);
-                }
-              }
-              if (interfaceMember.isInheritableConflict) {
-                interfaceMember = interfaceMember.withParent(classBuilder);
-                hierarchy.registerMemberComputation(interfaceMember);
-              }
-              if (interfaceMember.classBuilder.library.isNonNullableByDefault &&
-                  !classBuilder.library.isNonNullableByDefault) {
-                if (!interfaceMember.isSynthesized) {
-                  interfaceMember = new InterfaceConflict(
-                      classBuilder,
-                      [interfaceMember],
-                      interfaceMember.isProperty,
-                      forSetter,
-                      shouldModifyKernel,
-                      interfaceMember.isAbstract,
-                      interfaceMember.name,
-                      isImplicitlyAbstract: interfaceMember.isAbstract);
-                  hierarchy.registerMemberComputation(interfaceMember);
-                }
-              }
-              return interfaceMember;
-            }
-          } else if (classMember != null) {
-            return classMember;
-          }
+        if (interfaceMember != null) {
+          interfaceMemberMap[name] = interfaceMember;
         }
         return interfaceMember;
       }
 
-      void checkMemberVsSetter(
-          ClassMember member, ClassMember overriddenMember) {
-        if (overriddenMember.classBuilder == classBuilder &&
-            overriddenMember.hasDeclarations) {
-          for (ClassMember declaration in overriddenMember.declarations) {
-            checkMemberVsSetter(member, declaration);
-          }
-          return;
-        }
-
-        if (classBuilder is! SourceClassBuilder) return;
-        if (overriddenMember.isStatic) return;
-        if (member == overriddenMember) return;
-        if (member.isDuplicate || overriddenMember.isDuplicate) {
-          // Don't check overrides involving duplicated members.
-          return;
-        }
-        ClassMember result = checkInheritanceConflict(member, overriddenMember);
-        if (result != null) return;
-        assert(member.isProperty == overriddenMember.isProperty,
-            "Unexpected member combination: $member vs $overriddenMember");
-        if (member.classBuilder == classBuilder &&
-            overriddenMember.classBuilder != classBuilder) {
-          if (member is SourceFieldMember) {
-            registerOverrideDependency(member, overriddenMember);
-            hierarchy.registerOverrideCheck(
-                classBuilder, member, overriddenMember);
-          } else if (member is SourceProcedureMember) {
-            registerOverrideDependency(member, overriddenMember);
-            hierarchy.registerOverrideCheck(
-                classBuilder, member, overriddenMember);
-          }
-        }
+      ClassMember interfaceGetable;
+      if (definingGetable != null) {
+        interfaceGetable = computeMembers(
+            definingMember: definingGetable,
+            declaredMember: declaredGetable,
+            mixedInMember: mixedInGetable,
+            extendedMember: extendedGetable,
+            implementedMembers: implementedGetables,
+            classMemberMap: classMemberMap,
+            interfaceMemberMap: interfaceMemberMap);
       }
-
-      ClassMember classMember = computeClassMember(tuple.declaredMember,
-          tuple.mixedInMember, tuple.extendedMember, false);
-      ClassMember interfaceMember =
-          computeInterfaceMember(classMember, tuple.implementedMembers, false);
-      ClassMember classSetter = computeClassMember(tuple.declaredSetter,
-          tuple.mixedInSetter, tuple.extendedSetter, true);
-      ClassMember interfaceSetter =
-          computeInterfaceMember(classSetter, tuple.implementedSetters, true);
-
-      if ((tuple.mixedInMember != null || tuple.declaredMember != null) &&
-          classSetter != null) {
-        checkMemberVsSetter(
-            tuple.mixedInMember ?? tuple.declaredMember, classSetter);
-      }
-      if ((tuple.mixedInSetter != null || tuple.declaredSetter != null) &&
-          classMember != null) {
-        checkMemberVsSetter(
-            tuple.mixedInSetter ?? tuple.declaredSetter, classMember);
-      }
-      if (classMember != null && interfaceSetter != null) {
-        checkMemberVsSetter(classMember, interfaceSetter);
-      }
-      if (classSetter != null && interfaceMember != null) {
-        checkMemberVsSetter(classSetter, interfaceMember);
-      }
-
-      if (classMember != null &&
-          interfaceMember != null &&
-          classMember != interfaceMember) {
-        if (classMember.isAbstract == interfaceMember.isAbstract) {
-          // TODO(johnniwinther): Ensure that we don't have both class and
-          //  interface members that can give rise to a forwarding stub in
-          //  the current class. We might already have registered a delayed
-          //  member computation for the [classMember] that we're replacing
-          //  and therefore create two stubs for this member.
-          classMember = interfaceMember;
-        }
-      }
-      if (classSetter != null &&
-          interfaceSetter != null &&
-          classSetter != interfaceSetter) {
-        if (classSetter.isAbstract == interfaceSetter.isAbstract) {
-          // TODO(johnniwinther): Ensure that we don't have both class and
-          //  interface members that can give rise to a forwarding stub in
-          //  the current class. We might already have registered a delayed
-          //  member computation for the [classMember] that we're replacing
-          //  and therefore create two stubs for this member.
-          classSetter = interfaceSetter;
-        }
+      ClassMember interfaceSetable;
+      if (definingSetable != null) {
+        interfaceSetable = computeMembers(
+            definingMember: definingSetable,
+            declaredMember: declaredSetable,
+            mixedInMember: mixedInSetable,
+            extendedMember: extendedSetable,
+            implementedMembers: implementedSetables,
+            classMemberMap: classSetterMap,
+            interfaceMemberMap: interfaceSetterMap);
       }
       if (classBuilder is SourceClassBuilder) {
-        ClassMember member = interfaceMember ?? classMember;
-        ClassMember setter = interfaceSetter ?? classSetter;
-        if (member != null &&
-            setter != null &&
-            member.isProperty &&
-            setter.isProperty &&
-            member.isStatic == setter.isStatic &&
-            !member.isSameDeclaration(setter)) {
-          hierarchy.registerGetterSetterCheck(classBuilder, member, setter);
+        if (interfaceGetable != null &&
+            interfaceSetable != null &&
+            interfaceGetable.isProperty &&
+            interfaceSetable.isProperty &&
+            interfaceGetable.isStatic == interfaceSetable.isStatic &&
+            !interfaceGetable.isSameDeclaration(interfaceSetable)) {
+          /// We need to check that the getter type is a subtype of the setter
+          /// type. For instance
+          ///
+          ///    class Super {
+          ///       int get property1 => null;
+          ///       num get property2 => null;
+          ///    }
+          ///    class Mixin {
+          ///       void set property1(num value) {}
+          ///       void set property2(int value) {}
+          ///    }
+          ///    class Class = Super with Mixin;
+          ///
+          /// Here `Super.property1` and `Mixin.property1` form a valid getter/
+          /// setter pair in `Class` because the type of the getter
+          /// `Super.property1` is a subtype of the setter `Mixin.property1`.
+          ///
+          /// In contrast the pair `Super.property2` and `Mixin.property2` is
+          /// not a valid getter/setter in `Class` because the type of the getter
+          /// `Super.property2` is _not_ a subtype of the setter
+          /// `Mixin.property1`.
+          hierarchy.registerGetterSetterCheck(
+              classBuilder, interfaceGetable, interfaceSetable);
         }
       }
-      if (classMember != null) {
-        classMemberMap[name] = classMember;
-      }
-      if (interfaceMember != null) {
-        interfaceMemberMap[name] = interfaceMember;
-      }
-      if (classSetter != null) {
-        classSetterMap[name] = classSetter;
-      }
-      if (interfaceSetter != null) {
-        interfaceSetterMap[name] = interfaceSetter;
-      }
-      if (overriddenMembers.isNotEmpty) {
-        void registerOverrideDependencies(ClassMember member) {
-          if (member != null &&
-              member.classBuilder == classBuilder &&
-              member.isSourceDeclaration) {
-            member.registerOverrideDependency(overriddenMembers);
-            DelayedTypeComputation computation =
-                new DelayedTypeComputation(this, member, overriddenMembers);
-            hierarchy.registerDelayedTypeComputation(computation);
+      if (hasDeclaredMembers) {
+        Set<ClassMember> getableOverrides = {};
+        Set<ClassMember> setableOverrides = {};
+        if (extendedGetable != null) {
+          ///    (abstract) class Super {
+          ///      method() {}
+          ///      int get property => 0;
+          ///    }
+          ///    (abstract) class Class extends Super {
+          ///      method() {}
+          ///      set property(int value) {}
+          ///    }
+          getableOverrides.add(extendedGetable.interfaceMember);
+        }
+        if (extendedSetable != null) {
+          ///    (abstract) class Super {
+          ///      set setter(int value) {}
+          ///      set property(int value) {}
+          ///    }
+          ///    (abstract) class Class extends Super {
+          ///      set setter(int value) {}
+          ///      int get property => 0;
+          ///    }
+          setableOverrides.add(extendedSetable.interfaceMember);
+        }
+        if (implementedGetables != null) {
+          ///    (abstract) class Interface {
+          ///      method() {}
+          ///      int get property => 0;
+          ///    }
+          ///    (abstract) class Class implements Interface {
+          ///      method() {}
+          ///      set property(int value) {}
+          ///    }
+          getableOverrides.addAll(implementedGetables);
+        }
+        if (implementedSetables != null) {
+          ///    (abstract) class Interface {
+          ///      set setter(int value) {}
+          ///      set property(int value) {}
+          ///    }
+          ///    (abstract) class Class implements Interface {
+          ///      set setter(int value) {}
+          ///      int get property => 0;
+          ///    }
+          setableOverrides.addAll(implementedSetables);
+        }
+        if (getableOverrides.isNotEmpty || setableOverrides.isNotEmpty) {
+          if (declaredMethod != null && getableOverrides.isNotEmpty) {
+            ///    class Super {
+            ///      method() {}
+            ///    }
+            ///    class Class extends Super {
+            ///      method() {}
+            ///    }
+            declaredOverridesMap[declaredMethod] = getableOverrides;
+          }
+          if (declaredProperties != null) {
+            Set<ClassMember> overrides;
+            if (declaredMethod != null) {
+              ///    class Super {
+              ///      set setter() {}
+              ///    }
+              ///    class Class extends Super {
+              ///      method() {}
+              ///    }
+              overrides = setableOverrides;
+            } else {
+              ///    class Super {
+              ///      get property => null
+              ///      void set property(value) {}
+              ///    }
+              ///    class Class extends Super {
+              ///      get property => null
+              ///      void set property(value) {}
+              ///    }
+              overrides = {...getableOverrides, ...setableOverrides};
+            }
+            if (overrides.isNotEmpty) {
+              for (ClassMember declaredMember in declaredProperties) {
+                declaredOverridesMap[declaredMember] = overrides;
+              }
+            }
+          }
+          if (mixedInMethod != null && getableOverrides.isNotEmpty) {
+            ///    class Super {
+            ///      method() {}
+            ///    }
+            ///    class Mixin {
+            ///      method() {}
+            ///    }
+            ///    class Class = Super with Mixin;
+            mixinApplicationOverridesMap[mixedInMethod] = getableOverrides;
+          }
+          if (mixedInProperties != null) {
+            Set<ClassMember> overrides;
+            if (mixedInMethod != null) {
+              ///    class Super {
+              ///      set setter() {}
+              ///    }
+              ///    class Mixin {
+              ///      method() {}
+              ///    }
+              ///    class Class = Super with Mixin;
+              overrides = setableOverrides;
+            } else {
+              ///    class Super {
+              ///      method() {}
+              ///    }
+              ///    class Mixin extends Super {
+              ///      method() {}
+              ///    }
+              overrides = {...getableOverrides, ...setableOverrides};
+            }
+            if (overrides.isNotEmpty) {
+              for (ClassMember mixedInMember in mixedInProperties) {
+                mixinApplicationOverridesMap[mixedInMember] = overrides;
+              }
+            }
           }
         }
-
-        registerOverrideDependencies(
-            tuple.mixedInMember ?? tuple.declaredMember);
-        registerOverrideDependencies(
-            tuple.mixedInSetter ?? tuple.declaredSetter);
       }
     });
 
+    if (classBuilder is SourceClassBuilder) {
+      // TODO(johnniwinther): Avoid duplicate override check computations
+      //  between [declaredOverridesMap], [mixinApplicationOverridesMap] and
+      //  [inheritedImplementsMap].
+
+      // TODO(johnniwinther): Ensure that a class member is only checked to
+      // validly override another member once. Currently it can happen multiple
+      // times as an inherited implementation.
+
+      declaredOverridesMap.forEach(
+          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
+        /// A declared member can inherit its type from the overridden members.
+        ///
+        /// We register this with the class member itself so the it can force
+        /// computation of type on the overridden members before determining its
+        /// own type.
+        ///
+        /// Member types can be queried at arbitrary points during top level
+        /// inference so we need to ensure that types are computed in dependency
+        /// order.
+        classMember.registerOverrideDependency(overriddenMembers);
+
+        /// Not all member type are queried during top level inference so we
+        /// register delayed computation to ensure that all types have been
+        /// computed before override checks are performed.
+        DelayedTypeComputation computation =
+            new DelayedTypeComputation(this, classMember, overriddenMembers);
+        hierarchy.registerDelayedTypeComputation(computation);
+
+        /// Declared members must be checked to validly override the the
+        /// overridden members.
+        hierarchy.registerOverrideCheck(
+            classBuilder, classMember, overriddenMembers);
+      });
+
+      mixinApplicationOverridesMap.forEach(
+          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
+        /// Declared mixed in members must be checked to validly override the
+        /// overridden members.
+        hierarchy.registerOverrideCheck(
+            classBuilder, classMember, overriddenMembers);
+      });
+
+      inheritedImplementsMap.forEach(
+          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
+        /// Concrete members must be checked to validly override the overridden
+        /// members in concrete classes.
+        hierarchy.registerOverrideCheck(
+            classBuilder, classMember, overriddenMembers);
+      });
+    }
+
     if (!hasInterfaces) {
+      /// All interface members also class members to we don't need to store
+      /// the interface members separately.
+      assert(
+          classMemberMap.length == interfaceMemberMap.length,
+          "Class/interface member mismatch. Class members: "
+          "$classMemberMap, interface members: $interfaceMemberMap.");
+      assert(
+          classSetterMap.length == interfaceSetterMap.length,
+          "Class/interface setter mismatch. Class setters: "
+          "$classSetterMap, interface setters: $interfaceSetterMap.");
+      assert(
+          classMemberMap.keys.every((Name name) =>
+              identical(classMemberMap[name], interfaceMemberMap[name])),
+          "Class/interface member mismatch. Class members: "
+          "$classMemberMap, interface members: $interfaceMemberMap.");
+      assert(
+          classSetterMap.keys.every((Name name) =>
+              identical(classSetterMap[name], interfaceSetterMap[name])),
+          "Class/interface setter mismatch. Class setters: "
+          "$classSetterMap, interface setters: $interfaceSetterMap.");
       interfaceMemberMap = null;
       interfaceSetterMap = null;
     }
 
     if (abstractMembers != null && !classBuilder.isAbstract) {
       if (!hasNoSuchMethod) {
-        reportMissingMembers();
+        reportMissingMembers(abstractMembers);
       } else {
         installNsmHandlers();
       }
     }
 
     return new ClassHierarchyNode(
-      classBuilder,
-      classMemberMap,
-      classSetterMap,
-      interfaceMemberMap,
-      interfaceSetterMap,
-      superclasses,
-      interfaces,
-      maxInheritancePath,
-      hasNoSuchMethod,
-    );
+        classBuilder,
+        classMemberMap,
+        classSetterMap,
+        interfaceMemberMap,
+        interfaceSetterMap,
+        superclasses,
+        interfaces,
+        maxInheritancePath,
+        hasNoSuchMethod,
+        dataForTesting);
   }
 
   Supertype recordSupertype(Supertype supertype) {
@@ -2431,10 +3118,9 @@
     interfaces.add(type);
   }
 
-  void reportMissingMembers() {
+  void reportMissingMembers(List<ClassMember> abstractMembers) {
     Map<String, LocatedMessage> contextMap = <String, LocatedMessage>{};
-    for (int i = 0; i < abstractMembers.length; i++) {
-      ClassMember declaration = abstractMembers[i];
+    for (ClassMember declaration in unfoldDeclarations(abstractMembers)) {
       if (isNameVisibleIn(declaration.name, classBuilder.library)) {
         String name = declaration.fullNameForErrors;
         String className = declaration.classBuilder?.fullNameForErrors;
@@ -2546,6 +3232,8 @@
 
   final bool hasNoSuchMethod;
 
+  final ClassHierarchyNodeDataForTesting dataForTesting;
+
   ClassHierarchyNode(
       this.classBuilder,
       this.classMemberMap,
@@ -2555,7 +3243,8 @@
       this.superclasses,
       this.interfaces,
       this.maxInheritancePath,
-      this.hasNoSuchMethod);
+      this.hasNoSuchMethod,
+      this.dataForTesting);
 
   /// Returns a list of all supertypes of [classBuilder], including this node.
   List<ClassHierarchyNode> computeAllSuperNodes(
@@ -2677,6 +3366,17 @@
   }
 }
 
+class ClassHierarchyNodeDataForTesting {
+  final List<ClassMember> abstractMembers;
+  final Map<ClassMember, Set<ClassMember>> declaredOverrides;
+  final Map<ClassMember, Set<ClassMember>> mixinApplicationOverrides;
+  final Map<ClassMember, Set<ClassMember>> inheritedImplements;
+  final Map<ClassMember, ClassMember> aliasMap = {};
+
+  ClassHierarchyNodeDataForTesting(this.abstractMembers, this.declaredOverrides,
+      this.mixinApplicationOverrides, this.inheritedImplements);
+}
+
 List<LocatedMessage> _inheritedConflictContext(ClassMember a, ClassMember b) {
   int length = a.fullNameForErrors.length;
   // TODO(ahe): Delete this method when it isn't used by [InterfaceResolver].
@@ -2786,25 +3486,57 @@
 }
 
 class DelayedOverrideCheck implements DelayedCheck {
-  final SourceClassBuilder classBuilder;
-  final ClassMember declaredMember;
-  final ClassMember overriddenMember;
+  final SourceClassBuilder _classBuilder;
+  final ClassMember _declaredMember;
+  final Set<ClassMember> _overriddenMembers;
 
-  const DelayedOverrideCheck(
-      this.classBuilder, this.declaredMember, this.overriddenMember);
+  DelayedOverrideCheck(
+      this._classBuilder, this._declaredMember, this._overriddenMembers);
 
   void check(ClassHierarchyBuilder hierarchy) {
-    void callback(
-        Member declaredMember, Member interfaceMember, bool isSetter) {
-      classBuilder.checkOverride(
+    Member declaredMember = _declaredMember.getMember(hierarchy);
+
+    /// If [_declaredMember] is a class member that is declared in an opt-in
+    /// library but inherited to [_classBuilder] through an opt-out class then
+    /// we need to apply legacy erasure to the declared type to get the
+    /// inherited type.
+    ///
+    /// For interface members this is handled by member signatures but since
+    /// these are abstract they will never be the inherited class member.
+    ///
+    /// For instance:
+    ///
+    ///    // Opt in:
+    ///    class Super {
+    ///      int extendedMethod(int i, {required int j}) => i;
+    ///    }
+    ///    class Mixin {
+    ///      int mixedInMethod(int i, {required int j}) => i;
+    ///    }
+    ///    // Opt out:
+    ///    class Legacy extends Super with Mixin {}
+    ///    // Opt in:
+    ///    class Class extends Legacy {
+    ///      // Valid overrides since the type of `Legacy.extendedMethod` is
+    ///      // `int* Function(int*, {int* j})`.
+    ///      int? extendedMethod(int? i, {int? j}) => i;
+    ///      // Valid overrides since the type of `Legacy.mixedInMethod` is
+    ///      // `int* Function(int*, {int* j})`.
+    ///      int? mixedInMethod(int? i, {int? j}) => i;
+    ///    }
+    ///
+    bool declaredNeedsLegacyErasure =
+        needsLegacyErasure(_classBuilder.cls, declaredMember.enclosingClass);
+    void callback(Member interfaceMember, bool isSetter) {
+      _classBuilder.checkOverride(
           hierarchy.types, declaredMember, interfaceMember, isSetter, callback,
-          isInterfaceCheck: !classBuilder.isMixinApplication);
+          isInterfaceCheck: !_classBuilder.isMixinApplication,
+          declaredNeedsLegacyErasure: declaredNeedsLegacyErasure);
     }
 
-    debug?.log("Delayed override check of ${declaredMember.fullName} "
-        "${overriddenMember.fullName} wrt. ${classBuilder.fullNameForErrors}");
-    callback(declaredMember.getMember(hierarchy),
-        overriddenMember.getMember(hierarchy), declaredMember.isSetter);
+    for (ClassMember overriddenMember in _overriddenMembers) {
+      callback(overriddenMember.getMember(hierarchy), _declaredMember.isSetter);
+    }
   }
 }
 
@@ -2854,527 +3586,6 @@
       '${builder.classBuilder.name},$declaredMember,$overriddenMembers)';
 }
 
-abstract class DelayedMember implements ClassMember {
-  /// The class which has inherited [declarations].
-  @override
-  final ClassBuilder classBuilder;
-
-  bool get hasDeclarations => true;
-
-  /// Conflicting declarations.
-  final List<ClassMember> declarations;
-
-  final bool isProperty;
-
-  final bool isSetter;
-
-  final bool modifyKernel;
-
-  final bool isExplicitlyAbstract;
-
-  @override
-  final Name name;
-
-  DelayedMember(this.classBuilder, this.declarations, this.isProperty,
-      this.isSetter, this.modifyKernel, this.isExplicitlyAbstract, this.name) {
-    assert(declarations.every((element) => element.isProperty == isProperty),
-        "isProperty mismatch for $this");
-  }
-
-  @override
-  bool get isSourceDeclaration => false;
-
-  @override
-  bool get needsComputation => true;
-
-  @override
-  bool get isSynthesized => true;
-
-  @override
-  bool get isInternalImplementation => false;
-
-  @override
-  bool get forSetter => isSetter;
-
-  @override
-  bool get isFunction => !isProperty;
-
-  @override
-  bool get isAbstract => isExplicitlyAbstract;
-
-  bool get isStatic => false;
-  bool get isField => false;
-  bool get isGetter => false;
-  bool get isFinal => false;
-  bool get isConst => false;
-  bool get isAssignable => false;
-  bool get isDuplicate => false;
-
-  DelayedMember withParent(ClassBuilder parent);
-
-  @override
-  ClassMember get abstract => this;
-
-  @override
-  ClassMember get concrete => this;
-
-  @override
-  Uri get fileUri => classBuilder.fileUri;
-
-  @override
-  int get charOffset => classBuilder.charOffset;
-
-  @override
-  String get fullNameForErrors =>
-      declarations.map((ClassMember m) => m.fullName).join("%");
-
-  bool get isInheritableConflict => true;
-
-  String get fullName {
-    String suffix = isSetter ? "=" : "";
-    return "${fullNameForErrors}$suffix";
-  }
-
-  @override
-  void inferType(ClassHierarchyBuilder hierarchy) {
-    // Do nothing; this is only for declared members.
-  }
-
-  @override
-  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
-    // Do nothing; this is only for declared members.
-  }
-}
-
-/// This represents a concrete implementation inherited from a superclass that
-/// has conflicts with methods inherited from an interface. The concrete
-/// implementation is the first element of [declarations].
-class InheritedImplementationInterfaceConflict extends DelayedMember {
-  Member _member;
-  Covariance _covariance;
-  final ClassMember concreteMember;
-
-  @override
-  final bool isInheritableConflict;
-
-  InheritedImplementationInterfaceConflict(
-      ClassBuilder parent,
-      this.concreteMember,
-      List<ClassMember> declarations,
-      bool isProperty,
-      bool isSetter,
-      bool modifyKernel,
-      bool isAbstract,
-      Name name,
-      {this.isInheritableConflict = true})
-      : assert(!concreteMember.isAbstract),
-        super(parent, declarations, isProperty, isSetter, modifyKernel,
-            isAbstract, name);
-
-  @override
-  bool isObjectMember(ClassBuilder objectClass) {
-    return concreteMember.isObjectMember(objectClass);
-  }
-
-  @override
-  String toString() {
-    return "InheritedImplementationInterfaceConflict("
-        "${classBuilder.fullNameForErrors}, $concreteMember, "
-        "[${declarations.join(', ')}])";
-  }
-
-  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
-    if (_member == null) {
-      if (!classBuilder.isAbstract) {
-        if (classBuilder is SourceClassBuilder) {
-          for (int i = 0; i < declarations.length; i++) {
-            if (concreteMember != declarations[i]) {
-              new DelayedOverrideCheck(
-                      classBuilder, concreteMember, declarations[i])
-                  .check(hierarchy);
-            }
-          }
-        }
-      }
-      InterfaceConflict interfaceConflict = new InterfaceConflict(classBuilder,
-          declarations, isProperty, isSetter, modifyKernel, isAbstract, name);
-      _member = interfaceConflict.getMember(hierarchy);
-      _covariance = interfaceConflict.getCovariance(hierarchy);
-    }
-  }
-
-  @override
-  Member getMember(ClassHierarchyBuilder hierarchy) {
-    _ensureMemberAndCovariance(hierarchy);
-    return _member;
-  }
-
-  @override
-  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
-    _ensureMemberAndCovariance(hierarchy);
-    return _covariance;
-  }
-
-  @override
-  DelayedMember withParent(ClassBuilder parent) {
-    return parent == this.classBuilder
-        ? this
-        : new InheritedImplementationInterfaceConflict(parent, concreteMember,
-            [this], isProperty, isSetter, modifyKernel, isAbstract, name);
-  }
-
-  @override
-  bool isSameDeclaration(ClassMember other) {
-    // This could be more precise but it currently has no benefit.
-    return identical(this, other);
-  }
-
-  static ClassMember combined(
-      ClassBuilder parent,
-      ClassMember concreteImplementation,
-      ClassMember other,
-      bool isSetter,
-      bool createForwarders,
-      {bool isInheritableConflict = true}) {
-    assert(concreteImplementation.isProperty == other.isProperty,
-        "Unexpected member combination: $concreteImplementation vs $other");
-    List<ClassMember> declarations = <ClassMember>[];
-    if (concreteImplementation.hasDeclarations &&
-        concreteImplementation.classBuilder == parent) {
-      addAllDeclarationsTo(concreteImplementation, declarations);
-    } else {
-      declarations.add(concreteImplementation);
-    }
-    if (other.hasDeclarations && other.classBuilder == parent) {
-      addAllDeclarationsTo(other, declarations);
-    } else {
-      addDeclarationIfDifferent(other, declarations);
-    }
-    if (declarations.length == 1) {
-      return declarations.single;
-    } else {
-      return new InheritedImplementationInterfaceConflict(
-          parent,
-          concreteImplementation.concrete,
-          declarations,
-          concreteImplementation.isProperty,
-          isSetter,
-          createForwarders,
-          declarations.first.isAbstract,
-          declarations.first.name,
-          isInheritableConflict: isInheritableConflict);
-    }
-  }
-}
-
-class InterfaceConflict extends DelayedMember {
-  final bool isImplicitlyAbstract;
-
-  InterfaceConflict(
-      ClassBuilder parent,
-      List<ClassMember> declarations,
-      bool isProperty,
-      bool isSetter,
-      bool modifyKernel,
-      bool isAbstract,
-      Name name,
-      {this.isImplicitlyAbstract: true})
-      : super(parent, declarations, isProperty, isSetter, modifyKernel,
-            isAbstract, name);
-
-  @override
-  bool isObjectMember(ClassBuilder objectClass) =>
-      declarations.first.isObjectMember(objectClass);
-
-  @override
-  bool get isAbstract => isExplicitlyAbstract || isImplicitlyAbstract;
-
-  Member _member;
-  Covariance _covariance;
-
-  @override
-  String toString() {
-    return "InterfaceConflict(${classBuilder.fullNameForErrors}, "
-        "[${declarations.join(', ')}])";
-  }
-
-  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
-    if (_member != null) {
-      return;
-    }
-    if (classBuilder.library is! SourceLibraryBuilder) {
-      _member = declarations.first.getMember(hierarchy);
-      _covariance = declarations.first.getCovariance(hierarchy);
-      return;
-    }
-
-    CombinedClassMemberSignature combinedMemberSignature =
-        new CombinedClassMemberSignature(hierarchy, classBuilder, declarations,
-            forSetter: isSetter);
-
-    if (combinedMemberSignature.canonicalMember == null) {
-      String name = classBuilder.fullNameForErrors;
-      int length = classBuilder.isAnonymousMixinApplication ? 1 : name.length;
-      List<LocatedMessage> context = declarations.map((ClassMember d) {
-        return messageDeclaredMemberConflictsWithOverriddenMembersCause
-            .withLocation(d.fileUri, d.charOffset, d.fullNameForErrors.length);
-      }).toList();
-
-      classBuilder.addProblem(
-          templateCombinedMemberSignatureFailed.withArguments(
-              classBuilder.fullNameForErrors,
-              declarations.first.fullNameForErrors),
-          classBuilder.charOffset,
-          length,
-          context: context);
-      // TODO(johnniwinther): Maybe we should have an invalid marker to avoid
-      // cascading errors.
-      _member = declarations.first.getMember(hierarchy);
-      _covariance = declarations.first.getCovariance(hierarchy);
-      return;
-    }
-    debug?.log("Combined Member Signature of ${fullNameForErrors}: "
-        "${combinedMemberSignature.canonicalMember.fullName}");
-
-    if (modifyKernel) {
-      ProcedureKind kind = ProcedureKind.Method;
-      Member bestMemberSoFar =
-          combinedMemberSignature.canonicalMember.getMember(hierarchy);
-      if (combinedMemberSignature.canonicalMember.isProperty) {
-        kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
-      } else if (bestMemberSoFar is Procedure &&
-          bestMemberSoFar.kind == ProcedureKind.Operator) {
-        kind = ProcedureKind.Operator;
-      }
-
-      debug?.log("Combined Member Signature of ${fullNameForErrors}: new "
-          "ForwardingNode($classBuilder, "
-          "${combinedMemberSignature.canonicalMember}, "
-          "$declarations, $kind)");
-      Member stub =
-          new ForwardingNode(combinedMemberSignature, kind).finalize();
-      if (stub != null && classBuilder.cls == stub.enclosingClass) {
-        if (stub is Procedure) {
-          classBuilder.cls.addProcedure(stub);
-        } else if (stub is Field) {
-          classBuilder.cls.addField(stub);
-        } else if (stub is Constructor) {
-          classBuilder.cls.addConstructor(stub);
-        } else if (stub is RedirectingFactoryConstructor) {
-          classBuilder.cls.addRedirectingFactoryConstructor(stub);
-        } else {
-          unhandled("${stub.runtimeType}", "getMember", stub.fileOffset,
-              stub.fileUri);
-        }
-        SourceLibraryBuilder library = classBuilder.library;
-        Member bestMemberSoFar =
-            combinedMemberSignature.canonicalMember.getMember(hierarchy);
-        if (bestMemberSoFar is Procedure) {
-          library.forwardersOrigins..add(stub)..add(bestMemberSoFar);
-        }
-        debug?.log("Combined Member Signature of ${fullNameForErrors}: "
-            "added stub $stub");
-        _member = stub;
-        _covariance = combinedMemberSignature.combinedMemberSignatureCovariance;
-        assert(
-            _covariance ==
-                new Covariance.fromMember(_member, forSetter: forSetter),
-            "Unexpected covariance for combined members signature "
-            "$_member. Found $_covariance, expected "
-            "${new Covariance.fromMember(_member, forSetter: forSetter)}.");
-        return;
-      }
-    }
-
-    debug?.log(
-        "Combined Member Signature of ${fullNameForErrors}: picked bestSoFar");
-    _member = combinedMemberSignature.canonicalMember.getMember(hierarchy);
-    _covariance = combinedMemberSignature.combinedMemberSignatureCovariance;
-  }
-
-  @override
-  Member getMember(ClassHierarchyBuilder hierarchy) {
-    _ensureMemberAndCovariance(hierarchy);
-    return _member;
-  }
-
-  @override
-  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
-    _ensureMemberAndCovariance(hierarchy);
-    return _covariance;
-  }
-
-  @override
-  DelayedMember withParent(ClassBuilder parent) {
-    return parent == this.classBuilder
-        ? this
-        : new InterfaceConflict(parent, [this], isProperty, isSetter,
-            modifyKernel, isAbstract, name,
-            isImplicitlyAbstract: isImplicitlyAbstract);
-  }
-
-  @override
-  bool isSameDeclaration(ClassMember other) {
-    // This could be more precise but it currently has no benefit.
-    return identical(this, other);
-  }
-
-  static ClassMember combined(ClassBuilder parent, ClassMember a, ClassMember b,
-      bool isSetter, bool createForwarders) {
-    assert(a.isProperty == b.isProperty,
-        "Unexpected member combination: $a vs $b");
-    List<ClassMember> declarations = <ClassMember>[];
-    if (a.hasDeclarations && a.classBuilder == parent) {
-      addAllDeclarationsTo(a, declarations);
-    } else {
-      declarations.add(a);
-    }
-    if (b.hasDeclarations && b.classBuilder == parent) {
-      addAllDeclarationsTo(b, declarations);
-    } else {
-      addDeclarationIfDifferent(b, declarations);
-    }
-    if (declarations.length == 1) {
-      return declarations.single;
-    } else {
-      return new InterfaceConflict(
-          parent,
-          declarations,
-          a.isProperty,
-          isSetter,
-          createForwarders,
-          declarations.first.isAbstract,
-          declarations.first.name);
-    }
-  }
-
-  @override
-  ClassMember get concrete {
-    if (isAbstract) {
-      return declarations.first.concrete;
-    }
-    return this;
-  }
-}
-
-class AbstractMemberOverridingImplementation extends DelayedMember {
-  AbstractMemberOverridingImplementation(
-      ClassBuilder parent,
-      ClassMember abstractMember,
-      ClassMember concreteImplementation,
-      bool isProperty,
-      bool isSetter,
-      bool modifyKernel,
-      bool isAbstract,
-      Name name)
-      : super(parent, <ClassMember>[concreteImplementation, abstractMember],
-            isProperty, isSetter, modifyKernel, isAbstract, name);
-
-  @override
-  bool isObjectMember(ClassBuilder objectClass) =>
-      concreteImplementation.isObjectMember(objectClass);
-
-  ClassMember get concreteImplementation => declarations[0];
-
-  ClassMember get abstractMember => declarations[1];
-
-  bool _isChecked = false;
-
-  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
-    if (!_isChecked) {
-      _isChecked = true;
-      if (!classBuilder.isAbstract &&
-          !hierarchy.nodes[classBuilder.cls].hasNoSuchMethod) {
-        if (classBuilder is SourceClassBuilder) {
-          new DelayedOverrideCheck(
-                  classBuilder, concreteImplementation, abstractMember)
-              .check(hierarchy);
-        }
-      }
-
-      ProcedureKind kind = ProcedureKind.Method;
-      if (abstractMember.isProperty) {
-        kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
-      }
-      if (modifyKernel) {
-        // This call will add a body to the abstract method if needed for
-        // isGenericCovariantImpl checks.
-        new ForwardingNode(
-                new CombinedClassMemberSignature.internal(
-                    hierarchy, classBuilder, 1, declarations,
-                    forSetter: isSetter),
-                kind)
-            .finalize();
-      }
-    }
-  }
-
-  @override
-  Member getMember(ClassHierarchyBuilder hierarchy) {
-    _ensureMemberAndCovariance(hierarchy);
-    return abstractMember.getMember(hierarchy);
-  }
-
-  @override
-  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
-    _ensureMemberAndCovariance(hierarchy);
-    return abstractMember.getCovariance(hierarchy);
-  }
-
-  @override
-  DelayedMember withParent(ClassBuilder parent) {
-    return parent == this.classBuilder
-        ? this
-        : new AbstractMemberOverridingImplementation(
-            parent,
-            abstractMember,
-            concreteImplementation,
-            isProperty,
-            isSetter,
-            modifyKernel,
-            isAbstract,
-            name);
-  }
-
-  @override
-  String toString() {
-    return "AbstractMemberOverridingImplementation("
-        "${classBuilder.fullNameForErrors}, "
-        "[${declarations.join(', ')}])";
-  }
-
-  @override
-  ClassMember get abstract => abstractMember;
-
-  @override
-  ClassMember get concrete => concreteImplementation;
-
-  @override
-  bool isSameDeclaration(ClassMember other) {
-    if (identical(this, other)) return false;
-    return other is AbstractMemberOverridingImplementation &&
-        classBuilder == other.classBuilder &&
-        abstract.isSameDeclaration(other.abstract) &&
-        concrete.isSameDeclaration(other.concrete);
-  }
-}
-
-void addDeclarationIfDifferent(
-    ClassMember declaration, List<ClassMember> declarations) {
-  for (int i = 0; i < declarations.length; i++) {
-    if (declaration == declarations[i]) return;
-  }
-  declarations.add(declaration);
-}
-
-void addAllDeclarationsTo(ClassMember member, List<ClassMember> declarations) {
-  assert(member.hasDeclarations);
-  for (int i = 0; i < member.declarations.length; i++) {
-    addDeclarationIfDifferent(member.declarations[i], declarations);
-  }
-  assert(declarations.toSet().length == declarations.length);
-}
-
 int compareNamedParameters(VariableDeclaration a, VariableDeclaration b) {
   return a.name.compareTo(b.name);
 }
@@ -3396,15 +3607,34 @@
       .toSet()
       .toList();
   cls.addProblem(
-      cls.library.isNonNullableByDefault
-          ? templateCantInferTypeDueToNoCombinedSignature.withArguments(name)
-          : templateCantInferTypeDueToInconsistentOverrides.withArguments(name),
+      templateCantInferTypeDueToNoCombinedSignature.withArguments(name),
       parameter.charOffset,
       name.length,
       wasHandled: true,
       context: context);
 }
 
+void reportCantInferTypes(ClassBuilder cls, SourceProcedureBuilder member,
+    ClassHierarchyBuilder hierarchy, Iterable<ClassMember> overriddenMembers) {
+  String name = member.fullNameForErrors;
+  List<LocatedMessage> context = overriddenMembers
+      .map((ClassMember overriddenMember) {
+        return messageDeclaredMemberConflictsWithOverriddenMembersCause
+            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
+                overriddenMember.fullNameForErrors.length);
+      })
+      // Call toSet to avoid duplicate context for instance of fields that are
+      // overridden both as getters and setters.
+      .toSet()
+      .toList();
+  cls.addProblem(
+      templateCantInferTypesDueToNoCombinedSignature.withArguments(name),
+      member.charOffset,
+      name.length,
+      wasHandled: true,
+      context: context);
+}
+
 void reportCantInferReturnType(ClassBuilder cls, SourceProcedureBuilder member,
     ClassHierarchyBuilder hierarchy, Iterable<ClassMember> overriddenMembers) {
   String name = member.fullNameForErrors;
@@ -3466,11 +3696,7 @@
   //   }
   // }
   cls.addProblem(
-      cls.library.isNonNullableByDefault
-          ? templateCantInferReturnTypeDueToNoCombinedSignature
-              .withArguments(name)
-          : templateCantInferReturnTypeDueToInconsistentOverrides
-              .withArguments(name),
+      templateCantInferReturnTypeDueToNoCombinedSignature.withArguments(name),
       member.charOffset,
       name.length,
       wasHandled: true,
@@ -3491,9 +3717,7 @@
       .toList();
   String name = member.fullNameForErrors;
   cls.addProblem(
-      cls.library.isNonNullableByDefault
-          ? templateCantInferTypeDueToNoCombinedSignature.withArguments(name)
-          : templateCantInferTypeDueToInconsistentOverrides.withArguments(name),
+      templateCantInferTypeDueToNoCombinedSignature.withArguments(name),
       member.charOffset,
       name.length,
       wasHandled: true,
@@ -3527,3 +3751,482 @@
     }
   }
 }
+
+Set<ClassMember> unfoldDeclarations(Iterable<ClassMember> members) {
+  Set<ClassMember> result = <ClassMember>{};
+  _unfoldDeclarations(members, result);
+  return result;
+}
+
+void _unfoldDeclarations(
+    Iterable<ClassMember> members, Set<ClassMember> result) {
+  for (ClassMember member in members) {
+    if (member.hasDeclarations) {
+      _unfoldDeclarations(member.declarations, result);
+    } else {
+      result.add(member);
+    }
+  }
+}
+
+abstract class SynthesizedMember extends ClassMember {
+  @override
+  final ClassBuilder classBuilder;
+
+  @override
+  final Name name;
+
+  @override
+  final bool forSetter;
+
+  @override
+  final bool isProperty;
+
+  SynthesizedMember(this.classBuilder, this.name,
+      {this.forSetter, this.isProperty})
+      : assert(forSetter != null),
+        assert(isProperty != null);
+
+  @override
+  List<ClassMember> get declarations => throw new UnimplementedError();
+
+  @override
+  void inferType(ClassHierarchyBuilder hierarchy) {}
+
+  @override
+  bool get isAssignable => throw new UnimplementedError();
+
+  @override
+  bool get isConst => throw new UnimplementedError();
+
+  @override
+  bool get isDuplicate => false;
+
+  @override
+  bool get isField => throw new UnimplementedError();
+
+  @override
+  bool get isFinal => throw new UnimplementedError();
+
+  @override
+  bool get isGetter => throw new UnimplementedError();
+
+  @override
+  bool get isInternalImplementation => false;
+
+  @override
+  bool get isSetter => forSetter;
+
+  @override
+  bool get isSourceDeclaration => false;
+
+  @override
+  bool get isStatic => false;
+
+  @override
+  bool get isSynthesized => true;
+
+  @override
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {}
+}
+
+/// Class member for a set of interface members.
+///
+/// This is used to compute combined member signature of a set of interface
+/// members inherited into the same class, and to insert forwarding stubs,
+/// mixin stubs, and member signatures where needed.
+class SynthesizedInterfaceMember extends SynthesizedMember {
+  @override
+  final List<ClassMember> declarations;
+
+  /// The concrete member in the super class overridden by [declarations], if
+  /// any.
+  ///
+  /// This is used to as the target when creating concrete forwarding and mixin
+  /// stub. For instance:
+  ///
+  ///    class Super {
+  ///      method(int i) {}
+  ///    }
+  ///    class Interface {
+  ///      method(covariant int i) {}
+  ///    }
+  ///    class Class extends Super implements Interface {
+  ///      // Concrete forwarding stub calling [_superClassMember]:
+  ///      method(covariant int i) => super.method(i);
+  ///
+  final ClassMember _superClassMember;
+
+  /// The canonical member of the combined member signature if it is known by
+  /// construction. The canonical member defines the type of combined member
+  /// signature.
+  ///
+  /// This is used when a declared member is part of a set of implemented
+  /// members. For instance
+  ///
+  ///     class Super {
+  ///       method(int i) {}
+  ///     }
+  ///     class Interface {
+  ///       method(covariant num i) {}
+  ///     }
+  ///     class Class implements Interface {
+  ///       // This member is updated to be a concrete forwarding stub with an
+  ///       // covariant parameter but with its declared parameter type:
+  ///       //    method(covariant int i) => super.method(i);
+  ///       method(int i);
+  ///     }
+  final ClassMember _canonicalMember;
+
+  /// The member in [declarations] that is mixed in, if any.
+  ///
+  /// This is used to create mixin stubs. If the mixed in member is abstract,
+  /// an abstract mixin stub is created:
+  ///
+  ///    class Super {
+  ///      void method() {}
+  ///    }
+  ///    class Mixin {
+  ///      void method();
+  ///    }
+  ///    // Abstract mixin stub with `Mixin.method` as target inserted:
+  ///    //   void method();
+  ///    class Class = Super with Mixin;
+  ///
+  /// If the mixed in member is concrete, a concrete mixin member is created:
+  ///
+  ///    class Super {
+  ///      void method() {}
+  ///    }
+  ///    class Mixin {
+  ///      void method() {}
+  ///    }
+  ///    // Concrete mixin stub with `Mixin.method` as target inserted:
+  ///    //   void method() => super.method();
+  ///    class Class = Super with Mixin;
+  ///
+  /// If a forwarding stub is needed, the created stub will be a possibly
+  /// concrete forwarding stub:
+  ///
+  ///    class Super {
+  ///      void method(int i) {}
+  ///    }
+  ///    class Interface {
+  ///      void method(covariant num i) {}
+  ///    }
+  ///    class Mixin {
+  ///      void method(int i);
+  ///    }
+  ///    // Concrete forwarding stub with `Super.method` as target inserted:
+  ///    //   void method(covariant int i) => super.method(i);
+  ///    class Class = Super with Mixin implements Interface;
+  ///
+  final ClassMember _mixedInMember;
+
+  /// If `true`, a stub should be inserted, if needed.
+  final bool _shouldModifyKernel;
+
+  Member _member;
+  Covariance _covariance;
+
+  SynthesizedInterfaceMember(
+      ClassBuilder classBuilder, Name name, this.declarations,
+      {ClassMember superClassMember,
+      ClassMember canonicalMember,
+      ClassMember mixedInMember,
+      bool isProperty,
+      bool forSetter,
+      bool shouldModifyKernel})
+      : this._superClassMember = superClassMember,
+        this._canonicalMember = canonicalMember,
+        this._mixedInMember = mixedInMember,
+        this._shouldModifyKernel = shouldModifyKernel,
+        super(classBuilder, name, isProperty: isProperty, forSetter: forSetter);
+
+  @override
+  bool get hasDeclarations => true;
+
+  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
+    if (_member != null) {
+      return;
+    }
+    if (classBuilder.library is! SourceLibraryBuilder) {
+      if (_canonicalMember != null) {
+        _member = _canonicalMember.getMember(hierarchy);
+        _covariance = _canonicalMember.getCovariance(hierarchy);
+      } else {
+        _member = declarations.first.getMember(hierarchy);
+        _covariance = declarations.first.getCovariance(hierarchy);
+      }
+      return;
+    }
+    CombinedClassMemberSignature combinedMemberSignature;
+    if (_canonicalMember != null) {
+      combinedMemberSignature = new CombinedClassMemberSignature.internal(
+          hierarchy,
+          classBuilder,
+          declarations.indexOf(_canonicalMember),
+          declarations,
+          forSetter: isSetter);
+    } else {
+      combinedMemberSignature = new CombinedClassMemberSignature(
+          hierarchy, classBuilder, declarations,
+          forSetter: isSetter);
+
+      if (combinedMemberSignature.canonicalMember == null) {
+        String name = classBuilder.fullNameForErrors;
+        int length = classBuilder.isAnonymousMixinApplication ? 1 : name.length;
+        List<LocatedMessage> context = declarations.map((ClassMember d) {
+          return messageDeclaredMemberConflictsWithOverriddenMembersCause
+              .withLocation(
+                  d.fileUri, d.charOffset, d.fullNameForErrors.length);
+        }).toList();
+
+        classBuilder.addProblem(
+            templateCombinedMemberSignatureFailed.withArguments(
+                classBuilder.fullNameForErrors,
+                declarations.first.fullNameForErrors),
+            classBuilder.charOffset,
+            length,
+            context: context);
+        // TODO(johnniwinther): Maybe we should have an invalid marker to avoid
+        // cascading errors.
+        _member = declarations.first.getMember(hierarchy);
+        _covariance = declarations.first.getCovariance(hierarchy);
+        return;
+      }
+    }
+
+    if (_shouldModifyKernel) {
+      ProcedureKind kind = ProcedureKind.Method;
+      Member canonicalMember =
+          combinedMemberSignature.canonicalMember.getMember(hierarchy);
+      if (combinedMemberSignature.canonicalMember.isProperty) {
+        kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
+      } else if (canonicalMember is Procedure &&
+          canonicalMember.kind == ProcedureKind.Operator) {
+        kind = ProcedureKind.Operator;
+      }
+
+      Procedure stub = new ForwardingNode(
+              combinedMemberSignature, kind, _superClassMember, _mixedInMember)
+          .finalize();
+      if (stub != null) {
+        assert(classBuilder.cls == stub.enclosingClass);
+        assert(stub != canonicalMember);
+        classBuilder.cls.addProcedure(stub);
+        SourceLibraryBuilder library = classBuilder.library;
+        if (canonicalMember is Procedure) {
+          library.forwardersOrigins..add(stub)..add(canonicalMember);
+        }
+        _member = stub;
+        _covariance = combinedMemberSignature.combinedMemberSignatureCovariance;
+        assert(
+            _covariance ==
+                new Covariance.fromMember(_member, forSetter: forSetter),
+            "Unexpected covariance for combined members signature "
+            "$_member. Found $_covariance, expected "
+            "${new Covariance.fromMember(_member, forSetter: forSetter)}.");
+        return;
+      }
+    }
+
+    _member = combinedMemberSignature.canonicalMember.getMember(hierarchy);
+    _covariance = combinedMemberSignature.combinedMemberSignatureCovariance;
+  }
+
+  @override
+  Member getMember(ClassHierarchyBuilder hierarchy) {
+    _ensureMemberAndCovariance(hierarchy);
+    return _member;
+  }
+
+  @override
+  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
+    _ensureMemberAndCovariance(hierarchy);
+    return _covariance;
+  }
+
+  @override
+  ClassMember get interfaceMember => this;
+
+  @override
+  bool isObjectMember(ClassBuilder objectClass) {
+    return false;
+  }
+
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    // TODO(johnniwinther): Optimize this.
+    return false;
+  }
+
+  @override
+  int get charOffset => declarations.first.charOffset;
+
+  @override
+  Uri get fileUri => declarations.first.fileUri;
+
+  @override
+  bool get isAbstract => true;
+
+  @override
+  String get fullNameForErrors =>
+      declarations.map((ClassMember m) => m.fullName).join("%");
+
+  @override
+  String get fullName {
+    String suffix = isSetter ? "=" : "";
+    return "${fullNameForErrors}$suffix";
+  }
+
+  String toString() => 'SynthesizedInterfaceMember($classBuilder,$name,'
+      '$declarations,forSetter=$forSetter)';
+}
+
+/// Class member for an inherited concrete member that implements an interface
+/// member.
+///
+/// This is used to ensure that both the inherited concrete member and the
+/// interface member is taken into account when computing the resulting [Member]
+/// node.
+///
+/// This is needed because an interface member, though initially abstract, can
+/// result in a concrete stub that overrides the concrete member. For instance
+///
+///    class Super {
+///      method(int i) {}
+///    }
+///    class Interface {
+///      method(covariant int i) {}
+///    }
+///    class Class extends Super implements Interface {
+///      // A concrete forwarding stub is inserted:
+///      method(covariant int i) => super.method(i);
+///    }
+///    class Sub extends Class implements Interface {
+///      // No forwarding stub should be inserted since `Class.method` is
+///      // adequate.
+///    }
+///
+///
+///  Here the create stub `Class.method` overrides `Super.method` and should
+///  be used to determine whether to insert a forwarding stub in subclasses.
+class InheritedClassMemberImplementsInterface extends SynthesizedMember {
+  final ClassMember inheritedClassMember;
+  final ClassMember implementedInterfaceMember;
+
+  Member _member;
+  Covariance _covariance;
+
+  InheritedClassMemberImplementsInterface(ClassBuilder classBuilder, Name name,
+      {this.inheritedClassMember,
+      this.implementedInterfaceMember,
+      bool isProperty,
+      bool forSetter})
+      : assert(inheritedClassMember != null),
+        assert(implementedInterfaceMember != null),
+        super(classBuilder, name, isProperty: isProperty, forSetter: forSetter);
+
+  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
+    if (_member == null) {
+      Member classMember = inheritedClassMember.getMember(hierarchy);
+      Member interfaceMember = implementedInterfaceMember.getMember(hierarchy);
+      if (!interfaceMember.isAbstract &&
+          interfaceMember.enclosingClass == classBuilder.cls) {
+        /// The interface member resulted in a concrete stub being inserted.
+        /// For instance for `method1` but _not_ for `method2` here:
+        ///
+        ///    class Super {
+        ///      method1(int i) {}
+        ///      method2(covariant int i) {}
+        ///    }
+        ///    class Interface {
+        ///      method1(covariant int i) {}
+        ///      method2(int i) {}
+        ///    }
+        ///    class Class extends Super implements Interface {
+        ///      // A concrete forwarding stub is inserted for `method1` since
+        ///      // the parameter on `Super.method1` is _not_ marked as
+        ///      // covariant:
+        ///      method1(covariant int i) => super.method(i);
+        ///      // No concrete forwarding stub is inserted for `method2` since
+        ///      // the parameter on `Super.method2` is already marked as
+        ///      // covariant.
+        ///    }
+        ///
+        /// The inserted stub should be used as the resulting member.
+        _member = interfaceMember;
+        _covariance = implementedInterfaceMember.getCovariance(hierarchy);
+      } else {
+        /// The interface member did not result in an inserted stub or the
+        /// inserted stub was abstract. For instance:
+        ///
+        ///    // Opt-in:
+        ///    class Super {
+        ///      method(int? i) {}
+        ///    }
+        ///    // Opt-out:
+        ///    class Class extends Super {
+        ///      // An abstract member signature stub is inserted:
+        ///      method(int* i);
+        ///    }
+        ///
+        /// The inserted stub should _not_ be used as the resulting member
+        /// since it is abstract and therefore not a class member.
+        _member = classMember;
+        _covariance = inheritedClassMember.getCovariance(hierarchy);
+      }
+    }
+  }
+
+  @override
+  Member getMember(ClassHierarchyBuilder hierarchy) {
+    _ensureMemberAndCovariance(hierarchy);
+    return _member;
+  }
+
+  @override
+  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
+    _ensureMemberAndCovariance(hierarchy);
+    return _covariance;
+  }
+
+  @override
+  ClassMember get interfaceMember => implementedInterfaceMember;
+
+  @override
+  bool isObjectMember(ClassBuilder objectClass) {
+    return inheritedClassMember.isObjectMember(objectClass);
+  }
+
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    // TODO(johnniwinther): Optimize this.
+    return false;
+  }
+
+  @override
+  int get charOffset => inheritedClassMember.charOffset;
+
+  @override
+  Uri get fileUri => inheritedClassMember.fileUri;
+
+  @override
+  bool get hasDeclarations => false;
+
+  @override
+  bool get isAbstract => false;
+
+  @override
+  String get fullNameForErrors => inheritedClassMember.fullNameForErrors;
+
+  String get fullName => inheritedClassMember.fullName;
+
+  @override
+  String toString() =>
+      'InheritedClassMemberImplementsInterface($classBuilder,$name,'
+      'inheritedClassMember=$inheritedClassMember,'
+      'implementedInterfaceMember=$implementedInterfaceMember,'
+      'forSetter=$forSetter)';
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/collections.dart b/pkg/front_end/lib/src/fasta/kernel/collections.dart
index 79b99c0..1e2f994 100644
--- a/pkg/front_end/lib/src/fasta/kernel/collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/collections.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library fasta.collections;
 
 import 'dart:core' hide MapEntry;
diff --git a/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart b/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart
index 5924d4a..2f22878 100644
--- a/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.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.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchyBase;
@@ -28,6 +30,8 @@
 abstract class CombinedMemberSignatureBase<T> {
   ClassHierarchyBase get hierarchy;
 
+  Name get name;
+
   /// The target class for the combined member signature.
   ///
   /// The [_memberTypes] are computed in terms of each member is inherited into
@@ -156,11 +160,9 @@
             candidateIndex++) {
           DartType candidateType = getMemberType(candidateIndex);
           if (!_isMoreSpecific(bestTypeSoFar, candidateType, forSetter)) {
-            if (!shouldOverrideProblemBeOverlooked(classBuilder)) {
-              bestSoFarIndex = null;
-              bestTypeSoFar = null;
-              _mutualSubtypes = null;
-            }
+            int favoredIndex = getOverlookedOverrideProblemChoice(classBuilder);
+            bestSoFarIndex = favoredIndex;
+            _mutualSubtypes = null;
             break;
           }
         }
@@ -261,17 +263,6 @@
     return _containsNnbdTypes;
   }
 
-  /// Returns `true` if the covariance of the combined member signature is
-  /// different from the covariance of the overridden member in the superclass.
-  ///
-  /// If `true` a concrete forwarding stub that checks the covariance must
-  /// be generated.
-  // TODO(johnniwinther): This is imprecise. It assumes that the 0th member is
-  // from the superclass which might not be the case.
-  bool get needsSuperImpl {
-    return _getMemberCovariance(0) != combinedMemberSignatureCovariance;
-  }
-
   /// The this type of [classBuilder].
   DartType get thisType {
     return _thisType ??= _coreTypes.thisInterfaceType(
@@ -508,10 +499,10 @@
       {bool copyLocation}) {
     assert(copyLocation != null);
     Class enclosingClass = classBuilder.cls;
-    Procedure referenceFrom;
+    Reference reference;
     if (classBuilder.referencesFromIndexed != null) {
-      referenceFrom = classBuilder.referencesFromIndexed
-          .lookupProcedureNotSetter(member.name.text);
+      reference =
+          classBuilder.referencesFromIndexed.lookupGetterReference(member.name);
     }
     Uri fileUri;
     int startFileOffset;
@@ -531,7 +522,7 @@
       new FunctionNode(null, returnType: type),
       isAbstract: true,
       fileUri: fileUri,
-      reference: referenceFrom?.reference,
+      reference: reference,
       isSynthetic: true,
       stubKind: ProcedureStubKind.MemberSignature,
       stubTarget: member.memberSignatureOrigin ?? member,
@@ -554,10 +545,10 @@
     assert(isGenericCovariantImpl != null);
     assert(copyLocation != null);
     Class enclosingClass = classBuilder.cls;
-    Procedure referenceFrom;
+    Reference reference;
     if (classBuilder.referencesFromIndexed != null) {
-      referenceFrom = classBuilder.referencesFromIndexed
-          .lookupProcedureSetter(member.name.text);
+      reference =
+          classBuilder.referencesFromIndexed.lookupSetterReference(member.name);
     }
     Uri fileUri;
     int startFileOffset;
@@ -583,7 +574,7 @@
           ]),
       isAbstract: true,
       fileUri: fileUri,
-      reference: referenceFrom?.reference,
+      reference: reference,
       isSynthetic: true,
       stubKind: ProcedureStubKind.MemberSignature,
       stubTarget: member.memberSignatureOrigin ?? member,
@@ -598,11 +589,8 @@
       {bool copyLocation}) {
     assert(copyLocation != null);
     Class enclosingClass = classBuilder.cls;
-    Procedure referenceFrom;
-    if (classBuilder.referencesFromIndexed != null) {
-      referenceFrom = classBuilder.referencesFromIndexed
-          .lookupProcedureNotSetter(procedure.name.text);
-    }
+    Reference reference = classBuilder.referencesFromIndexed
+        ?.lookupGetterReference(procedure.name);
     Uri fileUri;
     int startFileOffset;
     int fileOffset;
@@ -659,7 +647,7 @@
           requiredParameterCount: function.requiredParameterCount),
       isAbstract: true,
       fileUri: fileUri,
-      reference: referenceFrom?.reference,
+      reference: reference,
       isSynthetic: true,
       stubKind: ProcedureStubKind.MemberSignature,
       stubTarget: procedure.memberSignatureOrigin ?? procedure,
@@ -713,9 +701,11 @@
 class CombinedClassMemberSignature
     extends CombinedMemberSignatureBase<ClassMember> {
   /// The class hierarchy builder used for building this class.
+  @override
   final ClassHierarchyBuilder hierarchy;
 
   /// The list of the members inherited into or overridden in [classBuilder].
+  @override
   final List<ClassMember> members;
 
   /// Creates a [CombinedClassMemberSignature] whose canonical member is already
@@ -736,8 +726,13 @@
       {bool forSetter})
       : super(classBuilder, forSetter: forSetter);
 
+  @override
+  Name get name => members.first.name;
+
+  @override
   Types get _types => hierarchy.types;
 
+  @override
   Member _getMember(int index) {
     ClassMember candidate = members[index];
     Member target = candidate.getMember(hierarchy);
@@ -776,6 +771,9 @@
         super(classBuilder, forSetter: forSetter);
 
   @override
+  Name get name => members.first.name;
+
+  @override
   Member _getMember(int index) => members[index];
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
index f10419d..6d95ecf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.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.9
+
 part of 'constant_evaluator.dart';
 
 abstract class _ListOrSetConstantBuilder<L extends Expression> {
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 a92f302..02b7300 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.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.9
+
 /// This library implements a kernel2kernel constant evaluation transformation.
 ///
 /// Even though it is expected that the frontend does not emit kernel AST which
@@ -27,7 +29,9 @@
 import 'package:kernel/clone.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
+import 'package:kernel/src/const_canonical_type.dart';
 import 'package:kernel/src/legacy_erasure.dart';
+import 'package:kernel/src/norm.dart';
 import 'package:kernel/src/printer.dart' show AstPrinter, AstTextStrategy;
 import 'package:kernel/type_algebra.dart';
 import 'package:kernel/type_environment.dart';
@@ -198,8 +202,12 @@
 
   @override
   Constant visitMapConstant(MapConstant node) {
-    DartType keyType = rawLegacyErasure(node.keyType);
-    DartType valueType = rawLegacyErasure(node.valueType);
+    DartType keyType = computeConstCanonicalType(
+        node.keyType, _evaluator.coreTypes,
+        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
+    DartType valueType = computeConstCanonicalType(
+        node.valueType, _evaluator.coreTypes,
+        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
     List<ConstantMapEntry> entries;
     for (int index = 0; index < node.entries.length; index++) {
       ConstantMapEntry entry = node.entries[index];
@@ -220,7 +228,9 @@
 
   @override
   Constant visitListConstant(ListConstant node) {
-    DartType typeArgument = rawLegacyErasure(node.typeArgument);
+    DartType typeArgument = computeConstCanonicalType(
+        node.typeArgument, _evaluator.coreTypes,
+        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
     List<Constant> entries;
     for (int index = 0; index < node.entries.length; index++) {
       Constant entry = visitConstant(node.entries[index]);
@@ -238,7 +248,9 @@
 
   @override
   Constant visitSetConstant(SetConstant node) {
-    DartType typeArgument = rawLegacyErasure(node.typeArgument);
+    DartType typeArgument = computeConstCanonicalType(
+        node.typeArgument, _evaluator.coreTypes,
+        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
     List<Constant> entries;
     for (int index = 0; index < node.entries.length; index++) {
       Constant entry = visitConstant(node.entries[index]);
@@ -258,7 +270,9 @@
   Constant visitInstanceConstant(InstanceConstant node) {
     List<DartType> typeArguments;
     for (int index = 0; index < node.typeArguments.length; index++) {
-      DartType typeArgument = rawLegacyErasure(node.typeArguments[index]);
+      DartType typeArgument = computeConstCanonicalType(
+          node.typeArguments[index], _evaluator.coreTypes,
+          isNonNullableByDefault: _evaluator.isNonNullableByDefault);
       if (typeArgument != null) {
         typeArguments ??= node.typeArguments.toList(growable: false);
         typeArguments[index] = typeArgument;
@@ -284,7 +298,9 @@
       PartialInstantiationConstant node) {
     List<DartType> types;
     for (int index = 0; index < node.types.length; index++) {
-      DartType type = rawLegacyErasure(node.types[index]);
+      DartType type = computeConstCanonicalType(
+          node.types[index], _evaluator.coreTypes,
+          isNonNullableByDefault: _evaluator.isNonNullableByDefault);
       if (type != null) {
         types ??= node.types.toList(growable: false);
         types[index] = type;
@@ -301,7 +317,8 @@
 
   @override
   Constant visitTypeLiteralConstant(TypeLiteralConstant node) {
-    DartType type = rawLegacyErasure(node.type);
+    DartType type = computeConstCanonicalType(node.type, _evaluator.coreTypes,
+        isNonNullableByDefault: _evaluator.isNonNullableByDefault);
     if (type != null) {
       return new TypeLiteralConstant(type);
     }
@@ -570,6 +587,27 @@
         constantEvaluator.evaluate(_staticTypeContext, node), node);
   }
 
+  bool _isNull(Expression node) {
+    return node is NullLiteral ||
+        node is ConstantExpression && node.constant is NullConstant;
+  }
+
+  @override
+  Expression visitEqualsCall(EqualsCall node) {
+    Expression left = node.left.accept<TreeNode>(this);
+    Expression right = node.right.accept<TreeNode>(this);
+    if (_isNull(left)) {
+      return new EqualsNull(right, isNot: node.isNot)
+        ..fileOffset = node.fileOffset;
+    } else if (_isNull(right)) {
+      return new EqualsNull(left, isNot: node.isNot)
+        ..fileOffset = node.fileOffset;
+    }
+    node.left = left..parent = node;
+    node.right = right..parent = node;
+    return node;
+  }
+
   @override
   Expression visitStaticGet(StaticGet node) {
     final Member target = node.target;
@@ -591,6 +629,15 @@
   }
 
   @override
+  Expression visitStaticTearOff(StaticTearOff node) {
+    final Member target = node.target;
+    if (target is Procedure && target.kind == ProcedureKind.Method) {
+      return evaluateAndTransformWithContext(node, node);
+    }
+    return super.visitStaticTearOff(node);
+  }
+
+  @override
   SwitchCase visitSwitchCase(SwitchCase node) {
     transformExpressions(node.expressions, node);
     return super.visitSwitchCase(node);
@@ -673,6 +720,14 @@
   }
 
   @override
+  Expression visitTypeLiteral(TypeLiteral node) {
+    if (!containsFreeTypeVariables(node.type)) {
+      return evaluateAndTransformWithContext(node, node);
+    }
+    return super.visitTypeLiteral(node);
+  }
+
+  @override
   Expression visitMapConcatenation(MapConcatenation node) {
     return evaluateAndTransformWithContext(node, node);
   }
@@ -817,9 +872,10 @@
     switch (evaluationMode) {
       case EvaluationMode.strong:
       case EvaluationMode.agnostic:
-        return type;
+        return norm(coreTypes, type);
       case EvaluationMode.weak:
-        return legacyErasure(type);
+        return computeConstCanonicalType(norm(coreTypes, type), coreTypes,
+            isNonNullableByDefault: isNonNullableByDefault);
     }
     throw new UnsupportedError(
         "Unexpected evaluation mode: ${evaluationMode}.");
@@ -829,9 +885,13 @@
     switch (evaluationMode) {
       case EvaluationMode.strong:
       case EvaluationMode.agnostic:
-        return types;
+        return types.map((DartType type) => norm(coreTypes, type)).toList();
       case EvaluationMode.weak:
-        return types.map((DartType type) => legacyErasure(type)).toList();
+        return types
+            .map((DartType type) => computeConstCanonicalType(
+                norm(coreTypes, type), coreTypes,
+                isNonNullableByDefault: isNonNullableByDefault))
+            .toList();
     }
     throw new UnsupportedError(
         "Unexpected evaluation mode: ${evaluationMode}.");
@@ -1115,7 +1175,10 @@
 
   @override
   Constant visitTypeLiteral(TypeLiteral node) {
-    final DartType type = _evaluateDartType(node, node.type);
+    DartType type = _evaluateDartType(node, node.type);
+    if (type != null) {
+      type = convertType(type);
+    }
     if (type == null && _gotError != null) {
       AbortConstant error = _gotError;
       _gotError = null;
@@ -1741,12 +1804,19 @@
   }
 
   @override
-  Constant visitMethodInvocation(MethodInvocation node) {
-    // We have no support for generic method invocation atm.
-    if (node.arguments.named.isNotEmpty) {
+  Constant visitDynamicInvocation(DynamicInvocation node) {
+    // We have no support for generic method invocation at the moment.
+    if (node.arguments.types.isNotEmpty) {
       return createInvalidExpressionConstant(node, "generic method invocation");
     }
 
+    // We have no support for method invocation with named arguments at the
+    // moment.
+    if (node.arguments.named.isNotEmpty) {
+      return createInvalidExpressionConstant(
+          node, "method invocation with named arguments");
+    }
+
     final Constant receiver = _evaluateSubexpression(node.receiver);
     if (receiver is AbortConstant) return receiver;
     final List<Constant> arguments =
@@ -1763,35 +1833,139 @@
     if (shouldBeUnevaluated) {
       return unevaluated(
           node,
-          new MethodInvocation(extract(receiver), node.name,
+          new DynamicInvocation(node.kind, extract(receiver), node.name,
               unevaluatedArguments(arguments, {}, node.arguments.types))
+            ..fileOffset = node.fileOffset);
+    }
+
+    return _handleInvocation(node, node.name, receiver, arguments);
+  }
+
+  @override
+  Constant visitInstanceInvocation(InstanceInvocation node) {
+    // We have no support for generic method invocation at the moment.
+    if (node.arguments.types.isNotEmpty) {
+      return createInvalidExpressionConstant(node, "generic method invocation");
+    }
+
+    // We have no support for method invocation with named arguments at the
+    // moment.
+    if (node.arguments.named.isNotEmpty) {
+      return createInvalidExpressionConstant(
+          node, "method invocation with named arguments");
+    }
+
+    final Constant receiver = _evaluateSubexpression(node.receiver);
+    if (receiver is AbortConstant) return receiver;
+    final List<Constant> arguments =
+        _evaluatePositionalArguments(node.arguments);
+
+    if (arguments == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(arguments != null);
+
+    if (shouldBeUnevaluated) {
+      return unevaluated(
+          node,
+          new InstanceInvocation(node.kind, extract(receiver), node.name,
+              unevaluatedArguments(arguments, {}, node.arguments.types),
+              functionType: node.functionType,
+              interfaceTarget: node.interfaceTarget)
             ..fileOffset = node.fileOffset
             ..flags = node.flags);
     }
 
-    final String op = node.name.text;
+    return _handleInvocation(node, node.name, receiver, arguments);
+  }
+
+  @override
+  Constant visitFunctionInvocation(FunctionInvocation node) {
+    return createInvalidExpressionConstant(node, "function invocation");
+  }
+
+  @override
+  Constant visitLocalFunctionInvocation(LocalFunctionInvocation node) {
+    return createInvalidExpressionConstant(node, "local function invocation");
+  }
+
+  @override
+  Constant visitEqualsCall(EqualsCall node) {
+    final Constant left = _evaluateSubexpression(node.left);
+    if (left is AbortConstant) return left;
+    final Constant right = _evaluateSubexpression(node.right);
+    if (right is AbortConstant) return right;
+
+    if (shouldBeUnevaluated) {
+      return unevaluated(
+          node,
+          new EqualsCall(extract(left), extract(right),
+              isNot: node.isNot,
+              functionType: node.functionType,
+              interfaceTarget: node.interfaceTarget)
+            ..fileOffset = node.fileOffset);
+    }
+
+    return _handleEquals(node, left, right, isNot: node.isNot);
+  }
+
+  @override
+  Constant visitEqualsNull(EqualsNull node) {
+    final Constant expression = _evaluateSubexpression(node.expression);
+    if (expression is AbortConstant) return expression;
+
+    if (shouldBeUnevaluated) {
+      return unevaluated(
+          node,
+          new EqualsNull(extract(expression), isNot: node.isNot)
+            ..fileOffset = node.fileOffset);
+    }
+
+    return _handleEquals(node, expression, nullConstant, isNot: node.isNot);
+  }
+
+  Constant _handleEquals(Expression node, Constant left, Constant right,
+      {bool isNot}) {
+    assert(isNot != null);
+    if (left is NullConstant ||
+        left is BoolConstant ||
+        left is IntConstant ||
+        left is DoubleConstant ||
+        left is StringConstant ||
+        right is NullConstant) {
+      // [DoubleConstant] uses [identical] to determine equality, so we need
+      // to take the special cases into account.
+      Constant result =
+          doubleSpecialCases(left, right) ?? makeBoolConstant(left == right);
+      if (isNot) {
+        if (result == trueConstant) {
+          result = falseConstant;
+        } else {
+          assert(result == falseConstant);
+          result = trueConstant;
+        }
+      }
+      return result;
+    } else {
+      return createErrorConstant(
+          node,
+          templateConstEvalInvalidEqualsOperandType.withArguments(
+              left, left.getType(_staticTypeContext), isNonNullableByDefault));
+    }
+  }
+
+  Constant _handleInvocation(
+      Expression node, Name name, Constant receiver, List<Constant> arguments) {
+    final String op = name.text;
 
     // Handle == and != first (it's common between all types). Since `a != b` is
     // parsed as `!(a == b)` it is handled implicitly through ==.
     if (arguments.length == 1 && op == '==') {
       final Constant right = arguments[0];
-
-      if (receiver is NullConstant ||
-          receiver is BoolConstant ||
-          receiver is IntConstant ||
-          receiver is DoubleConstant ||
-          receiver is StringConstant ||
-          right is NullConstant) {
-        // [DoubleConstant] uses [identical] to determine equality, so we need
-        // to take the special cases into account.
-        return doubleSpecialCases(receiver, right) ??
-            makeBoolConstant(receiver == right);
-      } else {
-        return createErrorConstant(
-            node,
-            templateConstEvalInvalidEqualsOperandType.withArguments(receiver,
-                receiver.getType(_staticTypeContext), isNonNullableByDefault));
-      }
+      return _handleEquals(node, receiver, right, isNot: false);
     }
 
     // This is a white-listed set of methods we need to support on constants.
@@ -1909,6 +2083,48 @@
   }
 
   @override
+  Constant visitMethodInvocation(MethodInvocation node) {
+    // We have no support for generic method invocation at the moment.
+    if (node.arguments.types.isNotEmpty) {
+      return createInvalidExpressionConstant(node, "generic method invocation");
+    }
+
+    // We have no support for method invocation with named arguments at the
+    // moment.
+    if (node.arguments.named.isNotEmpty) {
+      return createInvalidExpressionConstant(
+          node, "method invocation with named arguments");
+    }
+
+    final Constant receiver = _evaluateSubexpression(node.receiver);
+    if (receiver is AbortConstant) return receiver;
+    final List<Constant> arguments =
+        _evaluatePositionalArguments(node.arguments);
+
+    if (arguments == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(arguments != null);
+
+    if (shouldBeUnevaluated) {
+      return unevaluated(
+          node,
+          new MethodInvocation(
+              extract(receiver),
+              node.name,
+              unevaluatedArguments(arguments, {}, node.arguments.types),
+              node.interfaceTarget)
+            ..fileOffset = node.fileOffset
+            ..flags = node.flags);
+    }
+
+    return _handleInvocation(node, node.name, receiver, arguments);
+  }
+
+  @override
   Constant visitLogicalExpression(LogicalExpression node) {
     final Constant left = _evaluateSubexpression(node.left);
     if (left is AbortConstant) return left;
@@ -2015,6 +2231,86 @@
   }
 
   @override
+  Constant visitInstanceGet(InstanceGet 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 Field field in instanceBuilder.fields.keys) {
+        if (field.name == node.name) {
+          return instanceBuilder.fields[field];
+        }
+      }
+
+      // 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 InstanceGet(node.kind, extract(receiver), node.name,
+              resultType: node.resultType,
+              interfaceTarget: node.interfaceTarget));
+    } else if (receiver is NullConstant) {
+      return createErrorConstant(node, messageConstEvalNullValue);
+    }
+    return createErrorConstant(
+        node,
+        templateConstEvalInvalidPropertyGet.withArguments(
+            node.name.text, receiver, isNonNullableByDefault));
+  }
+
+  @override
+  Constant visitDynamicGet(DynamicGet node) {
+    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 DynamicGet(node.kind, extract(receiver), node.name));
+    } else if (receiver is NullConstant) {
+      return createErrorConstant(node, messageConstEvalNullValue);
+    }
+    return createErrorConstant(
+        node,
+        templateConstEvalInvalidPropertyGet.withArguments(
+            node.name.text, receiver, isNonNullableByDefault));
+  }
+
+  @override
+  Constant visitInstanceTearOff(InstanceTearOff node) {
+    final Constant receiver = _evaluateSubexpression(node.receiver);
+    if (receiver is AbortConstant) return receiver;
+    return createErrorConstant(
+        node,
+        templateConstEvalInvalidPropertyGet.withArguments(
+            node.name.text, receiver, isNonNullableByDefault));
+  }
+
+  @override
+  Constant visitFunctionTearOff(FunctionTearOff node) {
+    final Constant receiver = _evaluateSubexpression(node.receiver);
+    if (receiver is AbortConstant) return receiver;
+    return createErrorConstant(
+        node,
+        templateConstEvalInvalidPropertyGet.withArguments(
+            Name.callName.text, receiver, isNonNullableByDefault));
+  }
+
+  @override
   Constant visitPropertyGet(PropertyGet node) {
     if (node.receiver is ThisExpression) {
       // Probably unreachable unless trying to evaluate non-const stuff as
@@ -2132,6 +2428,25 @@
   }
 
   @override
+  Constant visitStaticTearOff(StaticTearOff node) {
+    return withNewEnvironment(() {
+      final Member target = node.target;
+      if (target is Procedure) {
+        if (target.kind == ProcedureKind.Method) {
+          return canonicalize(new TearOffConstant(target));
+        }
+        return createErrorConstant(
+            node,
+            templateConstEvalInvalidStaticInvocation
+                .withArguments(target.name.name));
+      } else {
+        return createInvalidExpressionConstant(
+            node, 'No support for ${target.runtimeType} in a static tear-off.');
+      }
+    });
+  }
+
+  @override
   Constant visitStringConcatenation(StringConcatenation node) {
     final List<Object> concatenated = <Object>[new StringBuffer()];
     for (int i = 0; i < node.expressions.length; i++) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart b/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
index 0d73f92..8d0c5b0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
@@ -34,17 +36,17 @@
   Constant makeIntConstant(int value, {bool unsigned: false});
 
   Constant foldUnaryOperator(
-      MethodInvocation node, String op, covariant Constant operand);
+      Expression node, String op, covariant Constant operand);
 
-  Constant foldBinaryOperator(MethodInvocation node, String op,
+  Constant foldBinaryOperator(Expression node, String op,
       covariant Constant left, covariant Constant right);
 
-  Constant truncatingDivide(MethodInvocation node, num left, num right);
+  Constant truncatingDivide(Expression node, num left, num right);
 
   /// Returns [null] on success and an error-"constant" on failure, as such the
   /// return value should be checked.
   AbortConstant _checkOperands(
-      MethodInvocation node, String op, num left, num right) {
+      Expression node, String op, num left, num right) {
     if ((op == '<<' || op == '>>' || op == '>>>') && right < 0) {
       return evaluator.createErrorConstant(node,
           templateConstEvalNegativeShift.withArguments(op, '$left', '$right'));
@@ -69,8 +71,7 @@
   }
 
   @override
-  Constant foldUnaryOperator(
-      MethodInvocation node, String op, IntConstant operand) {
+  Constant foldUnaryOperator(Expression node, String op, IntConstant operand) {
     switch (op) {
       case 'unary-':
         return new IntConstant(-operand.value);
@@ -85,7 +86,7 @@
 
   @override
   Constant foldBinaryOperator(
-      MethodInvocation node, String op, IntConstant left, IntConstant right) {
+      Expression node, String op, IntConstant left, IntConstant right) {
     int a = left.value;
     int b = right.value;
     AbortConstant error = _checkOperands(node, op, a, b);
@@ -133,7 +134,7 @@
   }
 
   @override
-  Constant truncatingDivide(MethodInvocation node, num left, num right) {
+  Constant truncatingDivide(Expression node, num left, num right) {
     try {
       return new IntConstant(left ~/ right);
     } catch (e) {
@@ -174,7 +175,7 @@
 
   @override
   Constant foldUnaryOperator(
-      MethodInvocation node, String op, DoubleConstant operand) {
+      Expression node, String op, DoubleConstant operand) {
     switch (op) {
       case 'unary-':
         return new DoubleConstant(-operand.value);
@@ -189,8 +190,8 @@
   }
 
   @override
-  Constant foldBinaryOperator(MethodInvocation node, String op,
-      DoubleConstant left, DoubleConstant right) {
+  Constant foldBinaryOperator(
+      Expression node, String op, DoubleConstant left, DoubleConstant right) {
     double a = left.value;
     double b = right.value;
     AbortConstant error = _checkOperands(node, op, a, b);
@@ -244,7 +245,7 @@
   }
 
   @override
-  Constant truncatingDivide(MethodInvocation node, num left, num right) {
+  Constant truncatingDivide(Expression node, num left, num right) {
     double division = (left / right);
     if (division.isNaN || division.isInfinite) {
       return evaluator.createErrorConstant(node,
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 509c236..5fe56fe 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.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.9
+
 /// A library to help generate expression.
 library fasta.expression_generator;
 
@@ -405,6 +407,7 @@
     }
     VariableDeclaration read =
         _helper.forest.createVariableDeclarationForValue(_createRead());
+    _helper.registerVariableDeclaration(read);
     Expression binary = _helper.forest.createBinary(offset,
         _helper.createVariableGet(read, fileOffset), binaryOperator, value);
     VariableDeclaration write = _helper.forest
@@ -516,7 +519,6 @@
       bool isPostIncDec: false}) {
     return new CompoundPropertySet(receiver, name, binaryOperator, value,
         forEffect: voidContext,
-        readOnlyReceiver: false,
         readOffset: fileOffset,
         binaryOffset: offset,
         writeOffset: fileOffset)
@@ -533,9 +535,11 @@
     }
     VariableDeclaration variable =
         _helper.forest.createVariableDeclarationForValue(receiver);
+    _helper.registerVariableDeclaration(variable);
     VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
         _forest.createPropertyGet(fileOffset,
             _helper.createVariableGet(variable, receiver.fileOffset), name));
+    _helper.registerVariableDeclaration(read);
     Expression binary = _helper.forest.createBinary(offset,
         _helper.createVariableGet(read, fileOffset), binaryOperator, value);
     VariableDeclaration write = _helper.forest
@@ -695,6 +699,7 @@
     VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
         _forest.createPropertyGet(
             fileOffset, _forest.createThisExpression(fileOffset), name));
+    _helper.registerVariableDeclaration(read);
     Expression binary = _helper.forest.createBinary(offset,
         _helper.createVariableGet(read, fileOffset), binaryOperator, value);
     VariableDeclaration write = _helper.forest
@@ -751,6 +756,7 @@
   Expression buildSimpleRead() {
     VariableDeclaration variable =
         _helper.forest.createVariableDeclarationForValue(receiverExpression);
+    _helper.registerVariableDeclaration(variable);
     PropertyGet read = _forest.createPropertyGet(
         fileOffset,
         _helper.createVariableGet(variable, receiverExpression.fileOffset,
@@ -764,6 +770,7 @@
   Expression buildAssignment(Expression value, {bool voidContext = false}) {
     VariableDeclaration variable =
         _helper.forest.createVariableDeclarationForValue(receiverExpression);
+    _helper.registerVariableDeclaration(variable);
     PropertySet read = _helper.forest.createPropertySet(
         fileOffset,
         _helper.createVariableGet(variable, receiverExpression.fileOffset,
@@ -898,6 +905,7 @@
     }
     VariableDeclaration read =
         _helper.forest.createVariableDeclarationForValue(_createRead());
+    _helper.registerVariableDeclaration(read);
     Expression binary = _helper.forest.createBinary(offset,
         _helper.createVariableGet(read, fileOffset), binaryOperator, value);
     VariableDeclaration write = _helper.forest
@@ -976,6 +984,7 @@
     Expression receiverValue;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
     } else {
@@ -994,19 +1003,17 @@
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
     Expression result = _forest.createIndexSet(
         fileOffset, receiverValue, index, value,
-        forEffect: voidContext, readOnlyReceiver: readOnlyReceiver);
+        forEffect: voidContext);
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
         ..fileOffset = fileOffset;
@@ -1019,23 +1026,20 @@
       {bool voidContext: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
 
     Expression result = new IfNullIndexSet(receiverValue, index, value,
         readOffset: fileOffset,
         testOffset: offset,
         writeOffset: fileOffset,
-        forEffect: voidContext,
-        readOnlyReceiver: readOnlyReceiver)
+        forEffect: voidContext)
       ..fileOffset = offset;
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
@@ -1051,15 +1055,13 @@
       bool isPostIncDec: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
 
     Expression result = new CompoundIndexSet(
@@ -1068,8 +1070,7 @@
         binaryOffset: offset,
         writeOffset: fileOffset,
         forEffect: voidContext,
-        forPostIncDec: isPostIncDec,
-        readOnlyReceiver: readOnlyReceiver);
+        forPostIncDec: isPostIncDec);
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
         ..fileOffset = fileOffset;
@@ -1166,7 +1167,7 @@
     _reportNonNullableInNullAwareWarningIfNeeded();
     Expression receiver = _helper.forest.createThisExpression(fileOffset);
     return _forest.createIndexSet(fileOffset, receiver, index, value,
-        forEffect: voidContext, readOnlyReceiver: true);
+        forEffect: voidContext);
   }
 
   @override
@@ -1178,8 +1179,7 @@
         readOffset: fileOffset,
         testOffset: offset,
         writeOffset: fileOffset,
-        forEffect: voidContext,
-        readOnlyReceiver: true)
+        forEffect: voidContext)
       ..fileOffset = offset;
   }
 
@@ -1195,8 +1195,7 @@
         binaryOffset: offset,
         writeOffset: fileOffset,
         forEffect: voidContext,
-        forPostIncDec: isPostIncDec,
-        readOnlyReceiver: true);
+        forPostIncDec: isPostIncDec);
   }
 
   @override
@@ -1490,6 +1489,7 @@
     }
     VariableDeclaration read =
         _helper.forest.createVariableDeclarationForValue(_createRead());
+    _helper.registerVariableDeclaration(read);
     Expression binary = _helper.forest.createBinary(offset,
         _helper.createVariableGet(read, fileOffset), binaryOperator, value);
     VariableDeclaration write = _helper.forest
@@ -1723,8 +1723,7 @@
           _helper.createVariableGet(extensionThis, fileOffset),
           writeTarget,
           value,
-          forEffect: forEffect,
-          readOnlyReceiver: true);
+          forEffect: forEffect);
     }
     write.fileOffset = offset;
     return write;
@@ -2001,6 +2000,7 @@
     if (isNullAware) {
       VariableDeclaration variable =
           _helper.forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       return new NullAwareExtension(
           variable,
           _createRead(_helper.createVariableGet(variable, variable.fileOffset,
@@ -2033,6 +2033,7 @@
     if (isNullAware) {
       VariableDeclaration variable =
           _helper.forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       return new NullAwareExtension(
           variable,
           _createWrite(
@@ -2040,24 +2041,22 @@
               _helper.createVariableGet(variable, variable.fileOffset,
                   forNullGuardedAccess: true),
               value,
-              forEffect: voidContext,
-              readOnlyReceiver: true))
+              forEffect: voidContext))
         ..fileOffset = fileOffset;
     } else {
-      return _createWrite(fileOffset, receiver, value,
-          forEffect: voidContext, readOnlyReceiver: false);
+      return _createWrite(fileOffset, receiver, value, forEffect: voidContext);
     }
   }
 
   Expression _createWrite(int offset, Expression receiver, Expression value,
-      {bool readOnlyReceiver, bool forEffect}) {
+      {bool forEffect}) {
     Expression write;
     if (writeTarget == null) {
       write = _makeInvalidWrite(value);
     } else {
       write = new ExtensionSet(
           extension, explicitTypeArguments, receiver, writeTarget, value,
-          readOnlyReceiver: readOnlyReceiver, forEffect: forEffect);
+          forEffect: forEffect);
     }
     write.fileOffset = offset;
     return write;
@@ -2069,6 +2068,7 @@
     if (isNullAware) {
       VariableDeclaration variable =
           _helper.forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       Expression read = _createRead(_helper.createVariableGet(
           variable, receiver.fileOffset,
           forNullGuardedAccess: true));
@@ -2077,8 +2077,7 @@
           _helper.createVariableGet(variable, receiver.fileOffset,
               forNullGuardedAccess: true),
           value,
-          forEffect: voidContext,
-          readOnlyReceiver: true);
+          forEffect: voidContext);
       return new NullAwareExtension(
           variable,
           new IfNullSet(read, write, forEffect: voidContext)
@@ -2113,13 +2112,11 @@
           _helper.createVariableGet(variable, receiver.fileOffset,
               forNullGuardedAccess: true),
           binary,
-          forEffect: voidContext,
-          readOnlyReceiver: true);
+          forEffect: voidContext);
       return new NullAwareExtension(variable, write)..fileOffset = offset;
     } else {
       return new CompoundExtensionSet(extension, explicitTypeArguments,
           receiver, targetName, readTarget, binaryOperator, value, writeTarget,
-          readOnlyReceiver: false,
           forEffect: voidContext,
           readOffset: fileOffset,
           binaryOffset: offset,
@@ -2150,8 +2147,7 @@
               _helper.createVariableGet(variable, receiver.fileOffset,
                   forNullGuardedAccess: true),
               binary,
-              forEffect: voidContext,
-              readOnlyReceiver: true)
+              forEffect: voidContext)
             ..fileOffset = fileOffset);
       return new NullAwareExtension(
           variable, new LocalPostIncDec(read, write)..fileOffset = offset)
@@ -2159,15 +2155,17 @@
     } else {
       VariableDeclaration variable =
           _helper.forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       VariableDeclaration read = _helper.forest
           .createVariableDeclarationForValue(_createRead(
               _helper.createVariableGet(variable, receiver.fileOffset)));
+      _helper.registerVariableDeclaration(read);
       Expression binary = _helper.forest.createBinary(offset,
           _helper.createVariableGet(read, fileOffset), binaryOperator, value);
       VariableDeclaration write = _helper.forest
           .createVariableDeclarationForValue(_createWrite(fileOffset,
               _helper.createVariableGet(variable, receiver.fileOffset), binary,
-              forEffect: voidContext, readOnlyReceiver: true)
+              forEffect: voidContext)
             ..fileOffset = fileOffset);
       return new PropertyPostIncDec(variable, read, write)..fileOffset = offset;
     }
@@ -2182,6 +2180,7 @@
     if (isNullAware) {
       receiverVariable =
           _helper.forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(receiverVariable);
       receiverExpression = _helper.createVariableGet(
           receiverVariable, receiverVariable.fileOffset,
           forNullGuardedAccess: true);
@@ -2356,6 +2355,7 @@
     Expression receiverValue;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
     } else {
@@ -2419,15 +2419,13 @@
       {bool voidContext: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
+      _helper.registerVariableDeclaration(variable);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
     Expression result = new IfNullExtensionIndexSet(
         extension,
@@ -2440,8 +2438,7 @@
         readOffset: fileOffset,
         testOffset: offset,
         writeOffset: fileOffset,
-        forEffect: voidContext,
-        readOnlyReceiver: readOnlyReceiver)
+        forEffect: voidContext)
       ..fileOffset = offset;
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
@@ -2457,15 +2454,12 @@
       bool isPostIncDec: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
     Expression result = new CompoundExtensionIndexSet(
         extension,
@@ -2480,8 +2474,7 @@
         binaryOffset: offset,
         writeOffset: fileOffset,
         forEffect: voidContext,
-        forPostIncDec: isPostIncDec,
-        readOnlyReceiver: readOnlyReceiver);
+        forPostIncDec: isPostIncDec);
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
         ..fileOffset = fileOffset;
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 1666a65..9a41855 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
@@ -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.9
+
 library fasta.expression_generator_helper;
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
@@ -161,4 +163,6 @@
   ///
   /// This is needed for type promotion.
   void registerVariableAssignment(VariableDeclaration variable);
+
+  void registerVariableDeclaration(VariableDeclaration variable);
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 273a4e7..4c6d8d9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.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.9
+
 library fasta.fangorn;
 
 import 'dart:core' hide MapEntry;
@@ -706,12 +708,10 @@
 
   IndexSet createIndexSet(
       int fileOffset, Expression receiver, Expression index, Expression value,
-      {bool forEffect, bool readOnlyReceiver}) {
+      {bool forEffect}) {
     assert(fileOffset != null);
     assert(forEffect != null);
-    assert(readOnlyReceiver != null);
-    return new IndexSet(receiver, index, value,
-        forEffect: forEffect, readOnlyReceiver: readOnlyReceiver)
+    return new IndexSet(receiver, index, value, forEffect: forEffect)
       ..fileOffset = fileOffset;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
index 9ee07dd..590534c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.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.9
+
 import "package:kernel/ast.dart"
     show
         Arguments,
@@ -36,11 +38,18 @@
 
   final ProcedureKind kind;
 
-  ForwardingNode(this._combinedMemberSignature, this.kind);
+  final ClassMember _superClassMember;
+
+  final ClassMember _mixedInMember;
+
+  ForwardingNode(this._combinedMemberSignature, this.kind,
+      this._superClassMember, this._mixedInMember);
 
   /// Finishes handling of this node by propagating covariance and creating
   /// forwarding stubs if necessary.
-  Member finalize() => _computeCovarianceFixes();
+  ///
+  /// If a stub is created, this is returned. Otherwise `null` is returned.
+  Procedure finalize() => _computeCovarianceFixes();
 
   /// Tag the parameters of [interfaceMember] that need type checks
   ///
@@ -52,13 +61,18 @@
   /// occurs in [enclosingClass]'s interface.  If parameters need checks but
   /// they would not be checked in an inherited implementation, a forwarding
   /// stub is introduced as a place to put the checks.
-  Member _computeCovarianceFixes() {
+  ///
+  /// If a stub is created, this is returned. Otherwise `null` is returned.
+  Procedure _computeCovarianceFixes() {
     SourceClassBuilder classBuilder = _combinedMemberSignature.classBuilder;
     ClassMember canonicalMember = _combinedMemberSignature.canonicalMember;
     Member interfaceMember =
         canonicalMember.getMember(_combinedMemberSignature.hierarchy);
 
-    if (_combinedMemberSignature.members.length == 1) {
+    bool needMixinStub =
+        classBuilder.isMixinApplication && _mixedInMember != null;
+
+    if (_combinedMemberSignature.members.length == 1 && !needMixinStub) {
       // Covariance can only come from [interfaceMember] so we never need a
       // forwarding stub.
       if (_combinedMemberSignature.neededLegacyErasure) {
@@ -68,10 +82,13 @@
             copyLocation: false);
       } else {
         // Nothing to do.
-        return interfaceMember;
+        return null;
       }
     }
 
+    // TODO(johnniwinther): Remove this. This relies upon the order of the
+    // declarations matching the order in which members are returned from the
+    // [ClassHierarchy].
     bool cannotReuseExistingMember =
         !(_combinedMemberSignature.isCanonicalMemberFirst ||
             _combinedMemberSignature.isCanonicalMemberDeclared);
@@ -81,60 +98,88 @@
             _combinedMemberSignature.needsCovarianceMerging;
     bool stubNeeded = cannotReuseExistingMember ||
         (canonicalMember.classBuilder != classBuilder &&
-            needsTypeOrCovarianceUpdate);
+            needsTypeOrCovarianceUpdate) ||
+        needMixinStub;
+    bool needsSuperImpl = _superClassMember != null &&
+        _superClassMember.getCovariance(_combinedMemberSignature.hierarchy) !=
+            _combinedMemberSignature.combinedMemberSignatureCovariance;
     if (stubNeeded) {
       Procedure stub = _combinedMemberSignature.createMemberFromSignature(
           copyLocation: false);
-      if (_combinedMemberSignature.needsCovarianceMerging ||
-          _combinedMemberSignature.needsSuperImpl) {
-        // This is a forward stub.
+      bool needsForwardingStub =
+          _combinedMemberSignature.needsCovarianceMerging || needsSuperImpl;
+      if (needsForwardingStub || needMixinStub) {
+        ProcedureStubKind stubKind;
         Member finalTarget;
-        if (interfaceMember is Procedure && interfaceMember.isForwardingStub) {
-          finalTarget = interfaceMember.forwardingStubInterfaceTarget;
+        if (needsForwardingStub) {
+          stubKind = ProcedureStubKind.AbstractForwardingStub;
+          if (interfaceMember is Procedure) {
+            switch (interfaceMember.stubKind) {
+              case ProcedureStubKind.Regular:
+              case ProcedureStubKind.NoSuchMethodForwarder:
+                finalTarget = interfaceMember;
+                break;
+              case ProcedureStubKind.AbstractForwardingStub:
+              case ProcedureStubKind.ConcreteForwardingStub:
+              case ProcedureStubKind.MemberSignature:
+              case ProcedureStubKind.AbstractMixinStub:
+              case ProcedureStubKind.ConcreteMixinStub:
+                finalTarget = interfaceMember.stubTarget;
+                break;
+            }
+          } else {
+            finalTarget = interfaceMember;
+          }
         } else {
+          stubKind = ProcedureStubKind.AbstractMixinStub;
           finalTarget =
-              interfaceMember.memberSignatureOrigin ?? interfaceMember;
+              _mixedInMember.getMember(_combinedMemberSignature.hierarchy);
         }
-        stub.stubKind = ProcedureStubKind.ForwardingStub;
+
+        stub.stubKind = stubKind;
         stub.stubTarget = finalTarget;
-        if (_combinedMemberSignature.needsSuperImpl) {
+        if (needsSuperImpl ||
+            (needMixinStub && _superClassMember == _mixedInMember)) {
           _createForwardingImplIfNeeded(
-              stub.function, stub.name, classBuilder.cls);
+              stub.function, stub.name, classBuilder.cls,
+              isForwardingStub: needsForwardingStub);
         }
       }
+
       return stub;
     } else {
       if (_combinedMemberSignature.needsCovarianceMerging) {
         _combinedMemberSignature.combinedMemberSignatureCovariance
             .applyCovariance(interfaceMember);
       }
-      if (_combinedMemberSignature.needsSuperImpl) {
+      if (needsSuperImpl) {
         _createForwardingImplIfNeeded(
-            interfaceMember.function, interfaceMember.name, classBuilder.cls);
+            interfaceMember.function, interfaceMember.name, classBuilder.cls,
+            isForwardingStub: true);
       }
-      return interfaceMember;
+      return null;
     }
   }
 
   void _createForwardingImplIfNeeded(
-      FunctionNode function, Name name, Class enclosingClass) {
+      FunctionNode function, Name name, Class enclosingClass,
+      {bool isForwardingStub}) {
+    assert(isForwardingStub != null);
     if (function.body != null) {
       // There is already an implementation; nothing further needs to be done.
       return;
     }
-    // Find the concrete implementation in the superclass; this is what we need
-    // to forward to.  If we can't find one, then the method is fully abstract
-    // and we don't need to do anything.
-    Class superclass = enclosingClass.superclass;
-    if (superclass == null) return;
+    // If there is no concrete implementation in the superclass, then the method
+    // is fully abstract and we don't need to do anything.
+    if (_superClassMember == null) {
+      return;
+    }
     Procedure procedure = function.parent;
-    Member superTarget = _combinedMemberSignature.hierarchy
-        .getDispatchTargetKernel(
-            superclass, procedure.name, kind == ProcedureKind.Setter);
-    if (superTarget == null) return;
+    Member superTarget =
+        _superClassMember.getMember(_combinedMemberSignature.hierarchy);
     if (superTarget is Procedure && superTarget.isForwardingStub) {
       Procedure superProcedure = superTarget;
-      superTarget = superProcedure.forwardingStubSuperTarget;
+      superTarget = superProcedure.concreteForwardingStubTarget;
     } else {
       superTarget = superTarget.memberSignatureOrigin ?? superTarget;
     }
@@ -178,7 +223,9 @@
     }
     function.body = new ReturnStatement(superCall)..parent = function;
     procedure.transformerFlags |= TransformerFlag.superCalls;
-    procedure.stubKind = ProcedureStubKind.ForwardingSuperStub;
+    procedure.stubKind = isForwardingStub
+        ? ProcedureStubKind.ConcreteForwardingStub
+        : ProcedureStubKind.ConcreteMixinStub;
     procedure.stubTarget = superTarget;
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index a636968..f37b35c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.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.9
+
 library fasta.implicit_type;
 
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
@@ -170,8 +172,7 @@
         if (type != overriddenType) {
           String name = fieldBuilder.fullNameForErrors;
           fieldBuilder.classBuilder.addProblem(
-              templateCantInferTypeDueToInconsistentOverrides
-                  .withArguments(name),
+              templateCantInferTypeDueToNoCombinedSignature.withArguments(name),
               fieldBuilder.charOffset,
               name.length,
               wasHandled: true);
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_type_argument.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_type_argument.dart
index 2ab9dfb..c6daddf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_type_argument.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_type_argument.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.md file.
 
+// @dart = 2.9
+
 library fasta.implicit_type_argument;
 
 import 'package:kernel/ast.dart'
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 76afeea..d0363bb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -2,9 +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 file.
 
+// @dart = 2.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:_fe_analyzer_shared/src/util/link.dart';
+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;
@@ -61,20 +64,6 @@
 
   InferenceVisitor(this.inferrer);
 
-  Expression _clone(Expression node) {
-    if (node is ThisExpression) {
-      return new ThisExpression()..fileOffset = node.fileOffset;
-    } else if (node is VariableGet) {
-      assert(
-          node.variable.isFinal,
-          "Trying to clone VariableGet of non-final variable"
-          " ${node.variable}.");
-      return new VariableGet(node.variable, node.promotedType)
-        ..fileOffset = node.fileOffset;
-    }
-    throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
-  }
-
   ExpressionInferenceResult _unhandledExpression(
       Expression node, DartType typeContext) {
     unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
@@ -387,7 +376,7 @@
     Expression condition =
         inferrer.ensureAssignableResult(expectedType, conditionResult);
     node.condition = condition..parent = node;
-    inferrer.flowAnalysis.conditional_thenBegin(node.condition);
+    inferrer.flowAnalysis.conditional_thenBegin(node.condition, node);
     bool isThenReachable = inferrer.flowAnalysis.isReachable;
     ExpressionInferenceResult thenResult = inferrer
         .inferExpression(node.then, typeContext, true, isVoidAllowed: true);
@@ -500,7 +489,7 @@
     }
 
     VariableDeclaration receiverVariable;
-    if (node.forEffect || node.readOnlyReceiver) {
+    if (node.forEffect || isPureExpression(receiver)) {
       // No need for receiver variable.
     } else {
       receiverVariable = createVariable(receiver, receiverResult.inferredType);
@@ -551,9 +540,9 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+    if (isPureExpression(receiver)) {
       readReceiver = receiver;
-      writeReceiver = _clone(receiver);
+      writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -1105,6 +1094,8 @@
         node.hasImplicitReturnType ? null : node.function.returnType;
     DartType inferredType =
         visitFunctionNode(node.function, null, returnContext, node.fileOffset);
+    inferrer.library.checkBoundsInFunctionNode(node.function,
+        inferrer.typeSchemaEnvironment, inferrer.library.fileUri);
     node.variable.type = inferredType;
     inferrer.flowAnalysis.functionExpression_end();
     return const StatementInferenceResult();
@@ -1116,6 +1107,11 @@
     inferrer.flowAnalysis.functionExpression_begin(node);
     DartType inferredType =
         visitFunctionNode(node.function, typeContext, null, node.fileOffset);
+    // In anonymous functions the return type isn't declared, so
+    // it shouldn't be checked.
+    inferrer.library.checkBoundsInFunctionNode(
+        node.function, inferrer.typeSchemaEnvironment, inferrer.library.fileUri,
+        skipReturnType: true);
     inferrer.flowAnalysis.functionExpression_end();
     return new ExpressionInferenceResult(inferredType, node);
   }
@@ -1183,15 +1179,18 @@
     } else {
       VariableDeclaration variable =
           createVariable(left, lhsResult.inferredType);
-      MethodInvocation equalsNull = createEqualsNull(
-          left.fileOffset, createVariableGet(variable), equalsMember);
+      Expression equalsNull = inferrer.createEqualsNull(
+          lhsResult.expression.fileOffset,
+          createVariableGet(variable),
+          equalsMember);
       VariableGet variableGet = createVariableGet(variable);
       if (inferrer.library.isNonNullableByDefault &&
           !identical(nonNullableLhsType, originalLhsType)) {
         variableGet.promotedType = nonNullableLhsType;
       }
       ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull, rhsResult.expression, variableGet, inferredType);
+          equalsNull, rhsResult.expression, variableGet, inferredType)
+        ..fileOffset = node.fileOffset;
       replacement = new Let(variable, conditional)
         ..fileOffset = node.fileOffset;
     }
@@ -1209,7 +1208,7 @@
     Expression condition =
         inferrer.ensureAssignableResult(expectedType, conditionResult);
     node.condition = condition..parent = node;
-    inferrer.flowAnalysis.ifStatement_thenBegin(condition);
+    inferrer.flowAnalysis.ifStatement_thenBegin(condition, node);
     StatementInferenceResult thenResult = inferrer.inferStatement(node.then);
     if (thenResult.hasChanged) {
       node.then = thenResult.statement..parent = node;
@@ -1475,7 +1474,7 @@
       Expression condition =
           inferrer.ensureAssignableResult(boolType, conditionResult);
       element.condition = condition..parent = element;
-      inferrer.flowAnalysis.ifStatement_thenBegin(condition);
+      inferrer.flowAnalysis.ifStatement_thenBegin(condition, element);
       ExpressionInferenceResult thenResult = inferElement(
           element.then,
           inferredTypeArgument,
@@ -1778,7 +1777,7 @@
         isVoidAllowed: false);
     Expression left = inferrer.ensureAssignableResult(boolType, leftResult);
     node.left = left..parent = node;
-    inferrer.flowAnalysis.logicalBinaryOp_rightBegin(node.left,
+    inferrer.flowAnalysis.logicalBinaryOp_rightBegin(node.left, node,
         isAnd: node.operatorEnum == LogicalExpressionOperator.AND);
     ExpressionInferenceResult rightResult = inferrer.inferExpression(
         node.right, boolType, !inferrer.isTopLevel,
@@ -2053,7 +2052,7 @@
       Expression condition =
           inferrer.ensureAssignableResult(boolType, conditionResult);
       entry.condition = condition..parent = entry;
-      inferrer.flowAnalysis.ifStatement_thenBegin(condition);
+      inferrer.flowAnalysis.ifStatement_thenBegin(condition, entry);
       // Note that this recursive invocation of inferMapEntry will add two types
       // to actualTypes; they are the actual types of the current invocation if
       // the 'else' branch is empty.
@@ -2740,9 +2739,9 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+    if (isPureExpression(receiver)) {
       readReceiver = receiver;
-      writeReceiver = _clone(receiver);
+      writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
       inferrer.instrumentation?.record(
@@ -2852,8 +2851,8 @@
       //
       //     let v1 = o in v1.a == null ? v1.a = b : null
       //
-      MethodInvocation equalsNull =
-          createEqualsNull(node.fileOffset, read, equalsMember);
+      Expression equalsNull =
+          inferrer.createEqualsNull(node.fileOffset, read, equalsMember);
       ConditionalExpression conditional = new ConditionalExpression(equalsNull,
           write, new NullLiteral()..fileOffset = node.fileOffset, inferredType)
         ..fileOffset = node.fileOffset;
@@ -2866,7 +2865,7 @@
       //     let v1 = o in let v2 = v1.a in v2 == null ? v1.a = b : v2
       //
       VariableDeclaration readVariable = createVariable(read, readType);
-      MethodInvocation equalsNull = createEqualsNull(
+      Expression equalsNull = inferrer.createEqualsNull(
           node.fileOffset, createVariableGet(readVariable), equalsMember);
       VariableGet variableGet = createVariableGet(readVariable);
       if (inferrer.library.isNonNullableByDefault &&
@@ -2918,8 +2917,8 @@
       //
       //     a == null ? a = b : null
       //
-      MethodInvocation equalsNull =
-          createEqualsNull(node.fileOffset, read, equalsMember);
+      Expression equalsNull =
+          inferrer.createEqualsNull(node.fileOffset, read, equalsMember);
       replacement = new ConditionalExpression(
           equalsNull,
           writeResult.expression,
@@ -2932,7 +2931,7 @@
       //      let v1 = a in v1 == null ? a = b : v1
       //
       VariableDeclaration readVariable = createVariable(read, readType);
-      MethodInvocation equalsNull = createEqualsNull(
+      Expression equalsNull = inferrer.createEqualsNull(
           node.fileOffset, createVariableGet(readVariable), equalsMember);
       VariableGet variableGet = createVariableGet(readVariable);
       if (inferrer.library.isNonNullableByDefault &&
@@ -2973,8 +2972,14 @@
 
     Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
-    ExpressionInferenceResult replacement = _computeIndexGet(node.fileOffset,
-        receiver, receiverType, indexGetTarget, index, readCheckKind);
+    ExpressionInferenceResult replacement = _computeIndexGet(
+        node.fileOffset,
+        receiver,
+        receiverType,
+        indexGetTarget,
+        index,
+        indexType,
+        readCheckKind);
     return inferrer.createNullAwareExpressionInferenceResult(
         replacement.inferredType, replacement.expression, nullAwareGuards);
   }
@@ -2989,7 +2994,7 @@
     DartType receiverType = receiverResult.nullAwareActionType;
 
     VariableDeclaration receiverVariable;
-    if (!node.forEffect && !node.readOnlyReceiver) {
+    if (!node.forEffect && !isPureExpression(receiver)) {
       receiverVariable = createVariable(receiver, receiverType);
       receiver = createVariableGet(receiverVariable);
     }
@@ -3008,7 +3013,7 @@
     Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
     VariableDeclaration indexVariable;
-    if (!node.forEffect) {
+    if (!node.forEffect && !isPureExpression(index)) {
       indexVariable = createVariable(index, indexResult.inferredType);
       index = createVariableGet(indexVariable);
     }
@@ -3018,30 +3023,36 @@
     Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
 
     VariableDeclaration valueVariable;
-    if (!node.forEffect) {
+    Expression returnedValue;
+    if (node.forEffect) {
+    } else if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
+    } else {
       valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
     }
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
     DartType inferredType = valueResult.inferredType;
 
-    Expression assignment = _computeIndexSet(
-        node.fileOffset, receiver, receiverType, indexSetTarget, index, value);
+    Expression assignment = _computeIndexSet(node.fileOffset, receiver,
+        receiverType, indexSetTarget, index, indexType, value, valueType);
 
     Expression replacement;
     if (node.forEffect) {
       replacement = assignment;
     } else {
-      assert(indexVariable != null);
-      assert(valueVariable != null);
       VariableDeclaration assignmentVariable =
           createVariable(assignment, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(valueVariable,
-              createLet(assignmentVariable, createVariableGet(valueVariable))));
+      replacement = createLet(assignmentVariable, returnedValue);
+      if (valueVariable != null) {
+        replacement = createLet(valueVariable, replacement);
+      }
+      if (indexVariable != null) {
+        replacement = createLet(indexVariable, replacement);
+      }
       if (receiverVariable != null) {
         replacement = createLet(receiverVariable, replacement);
       }
@@ -3068,14 +3079,25 @@
 
     Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
-    VariableDeclaration indexVariable =
-        createVariable(index, indexResult.inferredType);
+    VariableDeclaration indexVariable;
+    if (!isPureExpression(index)) {
+      indexVariable = createVariable(index, indexResult.inferredType);
+      index = createVariableGet(indexVariable);
+    }
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
     Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
-    VariableDeclaration valueVariable =
-        createVariable(value, valueResult.inferredType);
+
+    VariableDeclaration valueVariable;
+    Expression returnedValue;
+    if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
+    } else {
+      valueVariable = createVariable(value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
+    }
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
@@ -3083,10 +3105,10 @@
 
     Expression assignment;
     if (indexSetTarget.isMissing) {
-      assignment = inferrer.createMissingSuperIndexSet(node.fileOffset,
-          createVariableGet(indexVariable), createVariableGet(valueVariable));
+      assignment =
+          inferrer.createMissingSuperIndexSet(node.fileOffset, index, value);
     } else {
-      assert(indexSetTarget.isInstanceMember);
+      assert(indexSetTarget.isInstanceMember || indexSetTarget.isObjectMember);
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
           node.fileOffset,
@@ -3094,21 +3116,20 @@
           new InstrumentationValueForMember(node.setter));
       assignment = new SuperMethodInvocation(
           indexSetName,
-          new Arguments(<Expression>[
-            createVariableGet(indexVariable),
-            createVariableGet(valueVariable)
-          ])
+          new Arguments(<Expression>[index, value])
             ..fileOffset = node.fileOffset,
           indexSetTarget.member)
         ..fileOffset = node.fileOffset;
     }
     VariableDeclaration assignmentVariable =
         createVariable(assignment, const VoidType());
-    Expression replacement = new Let(
-        indexVariable,
-        createLet(valueVariable,
-            createLet(assignmentVariable, createVariableGet(valueVariable))))
-      ..fileOffset = node.fileOffset;
+    Expression replacement = createLet(assignmentVariable, returnedValue);
+    if (valueVariable != null) {
+      replacement = createLet(valueVariable, replacement);
+    }
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
+    }
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -3128,8 +3149,11 @@
     Expression receiver =
         inferrer.ensureAssignableResult(receiverType, receiverResult);
 
-    VariableDeclaration receiverVariable =
-        createVariable(receiver, receiverType);
+    VariableDeclaration receiverVariable;
+    if (!isPureExpression(receiver)) {
+      receiverVariable = createVariable(receiver, receiverType);
+      receiver = createVariableGet(receiverVariable);
+    }
 
     ObjectAccessTarget target = new ExtensionAccessTarget(
         node.setter, null, ProcedureKind.Operator, extensionTypeArguments);
@@ -3142,38 +3166,38 @@
 
     Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
-    VariableDeclaration indexVariable =
-        createVariable(index, indexResult.inferredType);
-
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
     Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
-    VariableDeclaration valueVariable =
-        createVariable(value, valueResult.inferredType);
+
+    VariableDeclaration valueVariable;
+    Expression returnedValue;
+    if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
+    } else {
+      valueVariable = createVariable(value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
+    }
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
     DartType inferredType = valueResult.inferredType;
 
-    Expression assignment = _computeIndexSet(
-        node.fileOffset,
-        createVariableGet(receiverVariable),
-        receiverType,
-        target,
-        createVariableGet(indexVariable),
-        createVariableGet(valueVariable));
+    Expression assignment = _computeIndexSet(node.fileOffset, receiver,
+        receiverType, target, index, indexType, value, valueType);
 
     VariableDeclaration assignmentVariable =
         createVariable(assignment, const VoidType());
-    Expression replacement = new Let(
-        receiverVariable,
-        createLet(
-            indexVariable,
-            createLet(
-                valueVariable,
-                createLet(
-                    assignmentVariable, createVariableGet(valueVariable)))))
-      ..fileOffset = node.fileOffset;
+    Expression replacement = createLet(assignmentVariable, returnedValue);
+    if (valueVariable != null) {
+      replacement = createLet(valueVariable, replacement);
+    }
+    if (receiverVariable != null) {
+      replacement = createLet(receiverVariable, replacement);
+    }
+    replacement.fileOffset = node.fileOffset;
+
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -3190,8 +3214,8 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver = receiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
-      writeReceiver = _clone(readReceiver);
+    if (isPureExpression(readReceiver)) {
+      writeReceiver = clonePureExpression(readReceiver);
     } else {
       receiverVariable = createVariable(readReceiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -3220,14 +3244,28 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
 
-    Expression readIndex = createVariableGet(indexVariable);
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
-    ExpressionInferenceResult readResult = _computeIndexGet(node.readOffset,
-        readReceiver, receiverType, readTarget, readIndex, checkKind);
+    ExpressionInferenceResult readResult = _computeIndexGet(
+        node.readOffset,
+        readReceiver,
+        receiverType,
+        readTarget,
+        readIndex,
+        readIndexType,
+        checkKind);
     reportNonNullableInNullAwareWarningIfNeeded(
         readResult.inferredType, "??=", node.readOffset);
     Expression read = readResult.expression;
@@ -3238,7 +3276,6 @@
         .findInterfaceMember(readType, equalsName, node.testOffset)
         .member;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -3253,15 +3290,26 @@
             inferrer.library.library);
 
     VariableDeclaration valueVariable;
+    Expression returnedValue;
     if (node.forEffect) {
       // No need for value variable.
+    } else if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
     } else {
       valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
     }
 
-    Expression write = _computeIndexSet(node.writeOffset, writeReceiver,
-        receiverType, writeTarget, writeIndex, value);
+    Expression write = _computeIndexSet(
+        node.writeOffset,
+        writeReceiver,
+        receiverType,
+        writeTarget,
+        writeIndex,
+        writeIndexType,
+        value,
+        valueType);
 
     Expression inner;
     if (node.forEffect) {
@@ -3278,12 +3326,12 @@
       //     let indexVariable = a in
       //         o[indexVariable] == null ? o.[]=(indexVariable, b) : null
       //
-      MethodInvocation equalsNull =
-          createEqualsNull(node.testOffset, read, equalsMember);
+      Expression equalsNull =
+          inferrer.createEqualsNull(node.testOffset, read, equalsMember);
       ConditionalExpression conditional = new ConditionalExpression(equalsNull,
           write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
-      inner = createLet(indexVariable, conditional);
+      inner = conditional;
     } else {
       // Encode `Extension(o)[a] ??= b` as, if `node.readOnlyReceiver` is false,
       // as:
@@ -3309,10 +3357,8 @@
       //        : readVariable
       //
       //
-      assert(valueVariable != null);
-
       VariableDeclaration readVariable = createVariable(read, readType);
-      MethodInvocation equalsNull = createEqualsNull(
+      Expression equalsNull = inferrer.createEqualsNull(
           node.testOffset, createVariableGet(readVariable), equalsMember);
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
@@ -3321,14 +3367,17 @@
           !identical(nonNullableReadType, readType)) {
         variableGet.promotedType = nonNullableReadType;
       }
+      Expression result = createLet(writeVariable, returnedValue);
+      if (valueVariable != null) {
+        result = createLet(valueVariable, result);
+      }
       ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))),
-          variableGet,
-          inferredType)
+          equalsNull, result, variableGet, inferredType)
         ..fileOffset = node.fileOffset;
-      inner = createLet(indexVariable, createLet(readVariable, conditional));
+      inner = createLet(readVariable, conditional);
+    }
+    if (indexVariable != null) {
+      inner = createLet(indexVariable, inner);
     }
 
     Expression replacement;
@@ -3372,13 +3421,20 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
 
-    Expression readIndex = createVariableGet(indexVariable);
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -3387,7 +3443,7 @@
     if (readTarget.isMissing) {
       read = inferrer.createMissingSuperIndexGet(node.readOffset, readIndex);
     } else {
-      assert(readTarget.isInstanceMember);
+      assert(readTarget.isInstanceMember || readTarget.isObjectMember);
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
           node.readOffset,
@@ -3415,11 +3471,15 @@
             inferrer.library.library);
 
     VariableDeclaration valueVariable;
+    Expression returnedValue;
     if (node.forEffect) {
       // No need for a value variable.
+    } else if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
     } else {
       valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
     }
 
     Expression write;
@@ -3428,7 +3488,7 @@
       write = inferrer.createMissingSuperIndexSet(
           node.writeOffset, writeIndex, value);
     } else {
-      assert(writeTarget.isInstanceMember);
+      assert(writeTarget.isInstanceMember || writeTarget.isObjectMember);
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
           node.writeOffset,
@@ -3449,12 +3509,12 @@
       //     let v1 = a in
       //        super[v1] == null ? super.[]=(v1, b) : null
       //
-      MethodInvocation equalsNull =
-          createEqualsNull(node.testOffset, read, equalsMember);
-      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
-          write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
+      assert(valueVariable == null);
+      Expression equalsNull =
+          inferrer.createEqualsNull(node.testOffset, read, equalsMember);
+      replacement = new ConditionalExpression(equalsNull, write,
+          new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
-      replacement = createLet(indexVariable, conditional);
     } else {
       // Encode `o[a] ??= b` as:
       //
@@ -3466,29 +3526,29 @@
       //           v3)
       //        : v2
       //
-      assert(valueVariable != null);
 
       VariableDeclaration readVariable = createVariable(read, readType);
-      MethodInvocation equalsNull = createEqualsNull(
+      Expression equalsNull = inferrer.createEqualsNull(
           node.testOffset, createVariableGet(readVariable), equalsMember);
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      VariableGet variableGet = createVariableGet(readVariable);
+      VariableGet readVariableGet = createVariableGet(readVariable);
       if (inferrer.library.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
-        variableGet.promotedType = nonNullableReadType;
+        readVariableGet.promotedType = nonNullableReadType;
+      }
+      Expression result = createLet(writeVariable, returnedValue);
+      if (valueVariable != null) {
+        result = createLet(valueVariable, result);
       }
       ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))),
-          variableGet,
-          inferredType)
+          equalsNull, result, readVariableGet, inferredType)
         ..fileOffset = node.fileOffset;
-      replacement =
-          createLet(indexVariable, createLet(readVariable, conditional));
+      replacement = createLet(readVariable, conditional);
     }
-
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
+    }
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -3511,9 +3571,9 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+    if (isPureExpression(receiver)) {
       readReceiver = receiver;
-      writeReceiver = _clone(receiver);
+      writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -3540,9 +3600,17 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
 
-    Expression readIndex = createVariableGet(indexVariable);
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
@@ -3552,6 +3620,7 @@
         receiverType,
         readTarget,
         readIndex,
+        readIndexType,
         MethodContravarianceCheckKind.none);
     reportNonNullableInNullAwareWarningIfNeeded(
         readResult.inferredType, "??=", node.readOffset);
@@ -3563,7 +3632,6 @@
         .findInterfaceMember(readType, equalsName, node.testOffset)
         .member;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -3578,15 +3646,26 @@
             inferrer.library.library);
 
     VariableDeclaration valueVariable;
+    Expression returnedValue;
     if (node.forEffect) {
       // No need for a value variable.
+    } else if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
     } else {
       valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
     }
 
-    Expression write = _computeIndexSet(node.writeOffset, writeReceiver,
-        receiverType, writeTarget, writeIndex, value);
+    Expression write = _computeIndexSet(
+        node.writeOffset,
+        writeReceiver,
+        receiverType,
+        writeTarget,
+        writeIndex,
+        writeIndexType,
+        value,
+        valueType);
 
     Expression replacement;
     if (node.forEffect) {
@@ -3597,12 +3676,12 @@
       //        receiverVariable[indexVariable] == null
       //          ? receiverVariable.[]=(indexVariable, b) : null
       //
-      MethodInvocation equalsNull =
-          createEqualsNull(node.testOffset, read, equalsMember);
-      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
-          write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
+      assert(valueVariable == null);
+      Expression equalsNull =
+          inferrer.createEqualsNull(node.testOffset, read, equalsMember);
+      replacement = new ConditionalExpression(equalsNull, write,
+          new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
-      replacement = createLet(indexVariable, conditional);
     } else {
       // Encode `Extension(o)[a] ??= b` as:
       //
@@ -3616,27 +3695,27 @@
       //           valueVariable)
       //        : readVariable
       //
-      assert(valueVariable != null);
-
       VariableDeclaration readVariable = createVariable(read, readType);
-      MethodInvocation equalsNull = createEqualsNull(
+      Expression equalsNull = inferrer.createEqualsNull(
           node.testOffset, createVariableGet(readVariable), equalsMember);
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      VariableGet variableGet = createVariableGet(readVariable);
+      VariableGet readVariableGet = createVariableGet(readVariable);
       if (inferrer.library.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
-        variableGet.promotedType = nonNullableReadType;
+        readVariableGet.promotedType = nonNullableReadType;
+      }
+      Expression result = createLet(writeVariable, returnedValue);
+      if (valueVariable != null) {
+        result = createLet(valueVariable, result);
       }
       ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))),
-          variableGet,
-          inferredType)
+          equalsNull, result, readVariableGet, inferredType)
         ..fileOffset = node.fileOffset;
-      replacement =
-          createLet(indexVariable, createLet(readVariable, conditional));
+      replacement = createLet(readVariable, conditional);
+    }
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
     }
     if (receiverVariable != null) {
       replacement = new Let(receiverVariable, replacement);
@@ -3645,6 +3724,11 @@
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
+  bool _isNull(Expression node) {
+    return node is NullLiteral ||
+        node is ConstantExpression && node.constant is NullConstant;
+  }
+
   /// Creates an equals expression of using [left] and [right] as operands.
   ///
   /// [fileOffset] is used as the file offset for created nodes. [leftType] is
@@ -3656,16 +3740,40 @@
       {bool isNot}) {
     assert(isNot != null);
     inferrer.flowAnalysis.equalityOp_rightBegin(left, leftType);
-    ObjectAccessTarget equalsTarget = inferrer.findInterfaceMember(
-        leftType, equalsName, fileOffset,
-        includeExtensionMethods: true);
-
     bool typeNeeded = !inferrer.isTopLevel;
+
+    Expression equals;
     ExpressionInferenceResult rightResult = inferrer.inferExpression(
         right, const UnknownType(), typeNeeded,
         isVoidAllowed: false);
 
-    assert(equalsTarget.isInstanceMember || equalsTarget.isNever);
+    if (inferrer.useNewMethodInvocationEncoding) {
+      if (_isNull(right)) {
+        equals = new EqualsNull(left, isNot: isNot)..fileOffset = fileOffset;
+      } else if (_isNull(left)) {
+        equals = new EqualsNull(rightResult.expression, isNot: isNot)
+          ..fileOffset = fileOffset;
+      }
+      if (equals != null) {
+        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(
+        leftType, equalsName, fileOffset,
+        includeExtensionMethods: true);
+
+    assert(
+        equalsTarget.isInstanceMember ||
+            equalsTarget.isObjectMember ||
+            equalsTarget.isNever,
+        "Unexpected equals target $equalsTarget for "
+        "$left ($leftType) == $right.");
     if (inferrer.instrumentation != null && leftType == const DynamicType()) {
       inferrer.instrumentation.record(
           inferrer.uriForInstrumentation,
@@ -3687,17 +3795,43 @@
         nullabilityNullTypeErrorTemplate:
             templateArgumentTypeNotAssignableNullabilityNullType);
 
-    Expression equals = new MethodInvocation(
-        left,
-        equalsName,
-        new Arguments(<Expression>[
-          right,
-        ])
-          ..fileOffset = fileOffset,
-        equalsTarget.member)
-      ..fileOffset = fileOffset;
-    if (isNot) {
-      equals = new Not(equals)..fileOffset = fileOffset;
+    if (inferrer.useNewMethodInvocationEncoding) {
+      if (equalsTarget.isInstanceMember || equalsTarget.isObjectMember) {
+        FunctionType functionType =
+            inferrer.getFunctionType(equalsTarget, leftType);
+        equals = new EqualsCall(left, right,
+            isNot: isNot,
+            functionType: functionType,
+            interfaceTarget: equalsTarget.member)
+          ..fileOffset = fileOffset;
+      } else {
+        assert(equalsTarget.isNever);
+        FunctionType functionType = new FunctionType(
+            [const DynamicType()],
+            const NeverType(Nullability.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,
+            isNot: isNot, functionType: functionType, interfaceTarget: target)
+          ..fileOffset = fileOffset;
+      }
+    } else {
+      equals = new MethodInvocation(
+          left,
+          equalsName,
+          new Arguments(<Expression>[
+            right,
+          ])
+            ..fileOffset = fileOffset,
+          equalsTarget.member)
+        ..fileOffset = fileOffset;
+      if (isNot) {
+        equals = new Not(equals)..fileOffset = fileOffset;
+      }
     }
     inferrer.flowAnalysis.equalityOp_end(
         equals, right, rightResult.inferredType,
@@ -3748,6 +3882,7 @@
               contextType, leftType, rightType,
               isNonNullableByDefault: inferrer.isNonNullableByDefault);
     }
+
     ExpressionInferenceResult rightResult = inferrer.inferExpression(
         right, rightContextType, typeNeeded,
         isVoidAllowed: true);
@@ -3769,6 +3904,10 @@
               isNonNullableByDefault: inferrer.isNonNullableByDefault);
     }
 
+    if (!inferrer.isNonNullableByDefault) {
+      binaryType = legacyErasure(binaryType);
+    }
+
     Expression binary;
     switch (binaryTarget.kind) {
       case ObjectAccessTargetKind.missing:
@@ -3792,14 +3931,81 @@
               ..fileOffset = fileOffset)
           ..fileOffset = fileOffset;
         break;
-      case ObjectAccessTargetKind.instanceMember:
-      case ObjectAccessTargetKind.nullableInstanceMember:
       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;
+        }
+        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;
+        }
+        break;
       case ObjectAccessTargetKind.never:
-        if (binaryTarget.isInstanceMember &&
+        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;
+        }
+        break;
+      case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
+        if ((binaryTarget.isInstanceMember || binaryTarget.isObjectMember) &&
             inferrer.instrumentation != null &&
             leftType == const DynamicType()) {
           inferrer.instrumentation.record(
@@ -3809,15 +4015,30 @@
               new InstrumentationValueForMember(binaryTarget.member));
         }
 
-        binary = new MethodInvocation(
-            left,
-            binaryName,
-            new Arguments(<Expression>[
-              right,
-            ])
-              ..fileOffset = fileOffset,
-            binaryTarget.member)
-          ..fileOffset = fileOffset;
+        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)
+            ..fileOffset = fileOffset;
+        } else {
+          binary = new MethodInvocation(
+              left,
+              binaryName,
+              new Arguments(<Expression>[
+                right,
+              ])
+                ..fileOffset = fileOffset,
+              binaryTarget.member)
+            ..fileOffset = fileOffset;
+        }
 
         if (binaryCheckKind ==
             MethodContravarianceCheckKind.checkMethodReturn) {
@@ -3837,10 +4058,6 @@
         break;
     }
 
-    if (!inferrer.isNonNullableByDefault) {
-      binaryType = legacyErasure(binaryType);
-    }
-
     if (!inferrer.isTopLevel && binaryTarget.isNullable) {
       return new ExpressionInferenceResult(
           binaryType,
@@ -3893,14 +4110,54 @@
               ..fileOffset = fileOffset)
           ..fileOffset = fileOffset;
         break;
-      case ObjectAccessTargetKind.instanceMember:
-      case ObjectAccessTargetKind.nullableInstanceMember:
       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;
+        }
+        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;
+        }
+        break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-      case ObjectAccessTargetKind.never:
-        if (unaryTarget.isInstanceMember &&
+        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;
+        }
+        break;
+      case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
+        if ((unaryTarget.isInstanceMember || unaryTarget.isObjectMember) &&
             inferrer.instrumentation != null &&
             expressionType == const DynamicType()) {
           inferrer.instrumentation.record(
@@ -3910,12 +4167,24 @@
               new InstrumentationValueForMember(unaryTarget.member));
         }
 
-        unary = new MethodInvocation(
-            expression,
-            unaryName,
-            new Arguments(<Expression>[])..fileOffset = fileOffset,
-            unaryTarget.member)
-          ..fileOffset = fileOffset;
+        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)
+            ..fileOffset = fileOffset;
+        } else {
+          unary = new MethodInvocation(
+              expression,
+              unaryName,
+              new Arguments(<Expression>[])..fileOffset = fileOffset,
+              unaryTarget.member)
+            ..fileOffset = fileOffset;
+        }
 
         if (unaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
           if (inferrer.instrumentation != null) {
@@ -3965,6 +4234,7 @@
       DartType receiverType,
       ObjectAccessTarget readTarget,
       Expression readIndex,
+      DartType indexType,
       MethodContravarianceCheckKind readCheckKind) {
     Expression read;
     DartType readType = inferrer.getReturnType(readTarget, receiverType);
@@ -3989,22 +4259,118 @@
               ..fileOffset = fileOffset)
           ..fileOffset = fileOffset;
         break;
-      case ObjectAccessTargetKind.instanceMember:
-      case ObjectAccessTargetKind.nullableInstanceMember:
       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;
+        }
+        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;
+        }
+        break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-      case ObjectAccessTargetKind.never:
-        read = new MethodInvocation(
-            readReceiver,
-            indexGetName,
-            new Arguments(<Expression>[
-              readIndex,
-            ])
-              ..fileOffset = fileOffset,
-            readTarget.member)
-          ..fileOffset = fileOffset;
+        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;
+        }
+        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)
+            ..fileOffset = fileOffset;
+        } else {
+          read = new MethodInvocation(
+              readReceiver,
+              indexGetName,
+              new Arguments(<Expression>[
+                readIndex,
+              ])
+                ..fileOffset = fileOffset,
+              readTarget.member)
+            ..fileOffset = fileOffset;
+        }
         if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
           if (inferrer.instrumentation != null) {
             inferrer.instrumentation.record(
@@ -4051,20 +4417,20 @@
       DartType receiverType,
       ObjectAccessTarget writeTarget,
       Expression index,
-      Expression value) {
+      DartType indexType,
+      Expression value,
+      DartType valueType) {
     Expression write;
     switch (writeTarget.kind) {
       case ObjectAccessTargetKind.missing:
         write = inferrer.createMissingIndexSet(
             fileOffset, receiver, receiverType, index, value,
-            forEffect: true, readOnlyReceiver: true);
+            forEffect: true);
         break;
       case ObjectAccessTargetKind.ambiguous:
         write = inferrer.createMissingIndexSet(
             fileOffset, receiver, receiverType, index, value,
-            forEffect: true,
-            readOnlyReceiver: true,
-            extensionAccessCandidates: writeTarget.candidates);
+            forEffect: true, extensionAccessCandidates: writeTarget.candidates);
         break;
       case ObjectAccessTargetKind.extensionMember:
       case ObjectAccessTargetKind.nullableExtensionMember:
@@ -4076,19 +4442,104 @@
               ..fileOffset = fileOffset)
           ..fileOffset = fileOffset;
         break;
-      case ObjectAccessTargetKind.instanceMember:
-      case ObjectAccessTargetKind.nullableInstanceMember:
       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;
+        }
+        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;
+        }
+        break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-      case ObjectAccessTargetKind.never:
-        write = new MethodInvocation(
-            receiver,
-            indexSetName,
-            new Arguments(<Expression>[index, value])..fileOffset = fileOffset,
-            writeTarget.member)
-          ..fileOffset = fileOffset;
+        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;
+        }
+        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)
+            ..fileOffset = fileOffset;
+        } else {
+          write = new MethodInvocation(
+              receiver,
+              indexSetName,
+              new Arguments(<Expression>[index, value])
+                ..fileOffset = fileOffset,
+              writeTarget.member)
+            ..fileOffset = fileOffset;
+        }
         break;
     }
     if (!inferrer.isTopLevel && writeTarget.isNullable) {
@@ -4167,14 +4618,49 @@
             break;
         }
         break;
-      case ObjectAccessTargetKind.instanceMember:
-      case ObjectAccessTargetKind.nullableInstanceMember:
+      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;
+        }
+        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;
+        }
+        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;
+        }
+        break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
-      case ObjectAccessTargetKind.dynamic:
-      case ObjectAccessTargetKind.never:
-        if (readTarget.isInstanceMember &&
+        if (inferrer.useNewMethodInvocationEncoding) {
+          read = new FunctionTearOff(receiver)..fileOffset = fileOffset;
+        } else {
+          read = new PropertyGet(receiver, propertyName, readTarget.member)
+            ..fileOffset = fileOffset;
+        }
+        break;
+      case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
+      case ObjectAccessTargetKind.nullableInstanceMember:
+        Member member = readTarget.member;
+        if ((readTarget.isInstanceMember || readTarget.isObjectMember) &&
             inferrer.instrumentation != null &&
             receiverType == const DynamicType()) {
           inferrer.instrumentation.record(
@@ -4183,10 +4669,37 @@
               'target',
               new InstrumentationValueForMember(readTarget.member));
         }
-        read = new PropertyGet(receiver, propertyName, readTarget.member)
-          ..fileOffset = fileOffset;
+        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: readTarget.member, resultType: readType)
+              ..fileOffset = fileOffset;
+          } else {
+            read = new InstanceGet(kind, receiver, propertyName,
+                interfaceTarget: readTarget.member, resultType: readType)
+              ..fileOffset = fileOffset;
+          }
+        } else {
+          read = new PropertyGet(receiver, propertyName, readTarget.member)
+            ..fileOffset = fileOffset;
+        }
         bool checkReturn = false;
-        if (readTarget.isInstanceMember && !isThisReceiver) {
+        if ((readTarget.isInstanceMember || readTarget.isObjectMember) &&
+            !isThisReceiver) {
           Member interfaceMember = readTarget.member;
           if (interfaceMember is Procedure) {
             checkReturn =
@@ -4213,7 +4726,6 @@
             ..isForNonNullableByDefault = inferrer.isNonNullableByDefault
             ..fileOffset = fileOffset;
         }
-        Member member = readTarget.member;
         if (member is Procedure && member.kind == ProcedureKind.Method) {
           readResult = inferrer.instantiateTearOff(readType, typeContext, read);
         }
@@ -4297,16 +4809,67 @@
             ..fileOffset = fileOffset;
         }
         break;
-      case ObjectAccessTargetKind.instanceMember:
-      case ObjectAccessTargetKind.nullableInstanceMember:
       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;
+        }
+        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;
+        }
+        break;
       case ObjectAccessTargetKind.callFunction:
       case ObjectAccessTargetKind.nullableCallFunction:
       case ObjectAccessTargetKind.dynamic:
-      case ObjectAccessTargetKind.never:
-        write =
-            new PropertySet(receiver, propertyName, value, writeTarget.member)
-              ..fileOffset = fileOffset;
+        if (inferrer.useNewMethodInvocationEncoding) {
+          write = new DynamicSet(
+              DynamicAccessKind.Dynamic, receiver, propertyName, value)
+            ..fileOffset = fileOffset;
+        } else {
+          write =
+              new PropertySet(receiver, propertyName, value, writeTarget.member)
+                ..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;
+        }
         break;
     }
     if (!inferrer.isTopLevel && writeTarget.isNullable) {
@@ -4334,8 +4897,8 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver = receiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver) {
-      writeReceiver = _clone(readReceiver);
+    if (isPureExpression(readReceiver)) {
+      writeReceiver = clonePureExpression(readReceiver);
     } else {
       receiverVariable = createVariable(readReceiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -4354,14 +4917,29 @@
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
-    Expression readIndex = createVariableGet(indexVariable);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
+
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
-    ExpressionInferenceResult readResult = _computeIndexGet(node.readOffset,
-        readReceiver, receiverType, readTarget, readIndex, readCheckKind);
+    ExpressionInferenceResult readResult = _computeIndexGet(
+        node.readOffset,
+        readReceiver,
+        receiverType,
+        readTarget,
+        readIndex,
+        readIndexType,
+        readCheckKind);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
 
@@ -4396,7 +4974,6 @@
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -4412,8 +4989,15 @@
       valueExpression = createVariableGet(valueVariable);
     }
 
-    Expression write = _computeIndexSet(node.writeOffset, writeReceiver,
-        receiverType, writeTarget, writeIndex, valueExpression);
+    Expression write = _computeIndexSet(
+        node.writeOffset,
+        writeReceiver,
+        receiverType,
+        writeTarget,
+        writeIndex,
+        writeIndexType,
+        valueExpression,
+        valueType);
 
     Expression inner;
     if (node.forEffect) {
@@ -4423,7 +5007,7 @@
       //
       //     let v1 = o in let v2 = a in v1.[]=(v2, v1.[](v2) + b)
       //
-      inner = createLet(indexVariable, write);
+      inner = write;
     } else if (node.forPostIncDec) {
       // Encode `o[a]++` as:
       //
@@ -4437,10 +5021,8 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      inner = createLet(
-          indexVariable,
-          createLet(leftVariable,
-              createLet(writeVariable, createVariableGet(leftVariable))));
+      inner = createLet(leftVariable,
+          createLet(writeVariable, createVariableGet(leftVariable)));
     } else {
       // Encode `o[a] += b` as:
       //
@@ -4454,10 +5036,11 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      inner = createLet(
-          indexVariable,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))));
+      inner = createLet(valueVariable,
+          createLet(writeVariable, createVariableGet(valueVariable)));
+    }
+    if (indexVariable != null) {
+      inner = createLet(indexVariable, inner);
     }
 
     Expression replacement;
@@ -4619,9 +5202,18 @@
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
-    Expression readIndex = createVariableGet(indexVariable);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
+
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
@@ -4629,7 +5221,7 @@
     if (readTarget.isMissing) {
       read = inferrer.createMissingSuperIndexGet(node.readOffset, readIndex);
     } else {
-      assert(readTarget.isInstanceMember);
+      assert(readTarget.isInstanceMember || readTarget.isObjectMember);
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
           node.readOffset,
@@ -4676,7 +5268,6 @@
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -4701,7 +5292,7 @@
       write = inferrer.createMissingSuperIndexSet(
           node.writeOffset, writeIndex, valueExpression);
     } else {
-      assert(writeTarget.isInstanceMember);
+      assert(writeTarget.isInstanceMember || writeTarget.isObjectMember);
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
           node.writeOffset,
@@ -4723,7 +5314,7 @@
       //
       //     let v1 = a in super.[]=(v1, super.[](v1) + b)
       //
-      replacement = createLet(indexVariable, write);
+      replacement = write;
     } else if (node.forPostIncDec) {
       // Encode `super[a]++` as:
       //
@@ -4736,10 +5327,8 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(leftVariable,
-              createLet(writeVariable, createVariableGet(leftVariable))));
+      replacement = createLet(leftVariable,
+          createLet(writeVariable, createVariableGet(leftVariable)));
     } else {
       // Encode `super[a] += b` as:
       //
@@ -4753,12 +5342,12 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))));
+      replacement = createLet(valueVariable,
+          createLet(writeVariable, createVariableGet(valueVariable)));
     }
-
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
+    }
     return new ExpressionInferenceResult(
         node.forPostIncDec ? readType : binaryType, replacement);
   }
@@ -4787,9 +5376,9 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+    if (isPureExpression(receiver)) {
       readReceiver = receiver;
-      writeReceiver = _clone(receiver);
+      writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -4800,9 +5389,18 @@
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
-    Expression readIndex = createVariableGet(indexVariable);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
+
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
@@ -4812,6 +5410,7 @@
         receiverType,
         readTarget,
         readIndex,
+        readIndexType,
         MethodContravarianceCheckKind.none);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
@@ -4849,7 +5448,6 @@
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
     binary = inferrer.ensureAssignable(valueType, binaryType, binary,
@@ -4864,8 +5462,15 @@
       valueExpression = createVariableGet(valueVariable);
     }
 
-    Expression write = _computeIndexSet(node.writeOffset, writeReceiver,
-        receiverType, writeTarget, writeIndex, valueExpression);
+    Expression write = _computeIndexSet(
+        node.writeOffset,
+        writeReceiver,
+        receiverType,
+        writeTarget,
+        writeIndex,
+        writeIndexType,
+        valueExpression,
+        valueType);
 
     Expression replacement;
     if (node.forEffect) {
@@ -4877,7 +5482,7 @@
       //     let indexVariable = a in
       //         receiverVariable.[]=(receiverVariable, o.[](indexVariable) + b)
       //
-      replacement = createLet(indexVariable, write);
+      replacement = write;
     } else if (node.forPostIncDec) {
       // Encode `Extension(o)[a]++` as:
       //
@@ -4893,10 +5498,8 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(leftVariable,
-              createLet(writeVariable, createVariableGet(leftVariable))));
+      replacement = createLet(leftVariable,
+          createLet(writeVariable, createVariableGet(leftVariable)));
     } else {
       // Encode `Extension(o)[a] += b` as:
       //
@@ -4912,12 +5515,12 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))));
+      replacement = createLet(valueVariable,
+          createLet(writeVariable, createVariableGet(valueVariable)));
     }
-
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
+    }
     if (receiverVariable != null) {
       replacement = new Let(receiverVariable, replacement);
     }
@@ -4962,7 +5565,7 @@
     ObjectAccessTarget target = inferrer.findInterfaceMember(
         receiverType, node.name, node.fileOffset,
         setter: true, instrumented: true, includeExtensionMethods: true);
-    if (target.isInstanceMember) {
+    if (target.isInstanceMember || target.isObjectMember) {
       if (inferrer.instrumentation != null &&
           receiverType == const DynamicType()) {
         inferrer.instrumentation.record(
@@ -5059,10 +5662,11 @@
       //           receiverVariable.name = value : null)
       //
 
-      MethodInvocation readEqualsNull =
-          createEqualsNull(node.readOffset, read, readEqualsMember);
+      Expression readEqualsNull =
+          inferrer.createEqualsNull(node.readOffset, read, readEqualsMember);
       replacement = new ConditionalExpression(readEqualsNull, write,
-          new NullLiteral()..fileOffset = node.writeOffset, inferredType);
+          new NullLiteral()..fileOffset = node.writeOffset, inferredType)
+        ..fileOffset = node.writeOffset;
     } else {
       // Encode `receiver?.name ??= value` as:
       //
@@ -5074,15 +5678,16 @@
       //
       assert(readVariable != null);
 
-      MethodInvocation readEqualsNull =
-          createEqualsNull(receiverVariable.fileOffset, read, readEqualsMember);
+      Expression readEqualsNull = inferrer.createEqualsNull(
+          receiverVariable.fileOffset, read, readEqualsMember);
       VariableGet variableGet = createVariableGet(readVariable);
       if (inferrer.library.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
         variableGet.promotedType = nonNullableReadType;
       }
       ConditionalExpression condition = new ConditionalExpression(
-          readEqualsNull, write, variableGet, inferredType);
+          readEqualsNull, write, variableGet, inferredType)
+        ..fileOffset = receiverVariable.fileOffset;
       replacement = createLet(readVariable, condition);
     }
 
@@ -5280,7 +5885,11 @@
     }
 
     if (target is Procedure && target.kind == ProcedureKind.Method) {
-      return inferrer.instantiateTearOff(type, typeContext, node);
+      Expression tearOff = node;
+      if (inferrer.useNewMethodInvocationEncoding) {
+        tearOff = new StaticTearOff(node.target)..fileOffset = node.fileOffset;
+      }
+      return inferrer.instantiateTearOff(type, typeContext, tearOff);
     } else {
       return new ExpressionInferenceResult(type, node);
     }
@@ -5358,12 +5967,7 @@
     }
     assert(node.interfaceTarget == null || node.interfaceTarget is Procedure);
     return inferrer.inferSuperMethodInvocation(
-        node,
-        typeContext,
-        node.interfaceTarget != null
-            ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget,
-                isPotentiallyNullable: false)
-            : const ObjectAccessTarget.missing());
+        node, typeContext, node.interfaceTarget);
   }
 
   @override
@@ -5377,12 +5981,7 @@
           new InstrumentationValueForMember(node.interfaceTarget));
     }
     return inferrer.inferSuperPropertyGet(
-        node,
-        typeContext,
-        node.interfaceTarget != null
-            ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget,
-                isPotentiallyNullable: false)
-            : const ObjectAccessTarget.missing());
+        node, typeContext, node.interfaceTarget);
   }
 
   @override
@@ -5393,13 +5992,15 @@
         inferrer.thisType.classNode.supertype.classNode,
         inferrer.library.library);
 
-    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
-        receiverType, node.name, node.fileOffset,
-        setter: true, instrumented: true);
-    if (writeTarget.isInstanceMember) {
-      node.interfaceTarget = writeTarget.member;
-    }
+    ObjectAccessTarget writeTarget = node.interfaceTarget != null
+        ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget,
+            isPotentiallyNullable: false)
+        : const ObjectAccessTarget.missing();
     DartType writeContext = inferrer.getSetterType(writeTarget, receiverType);
+    if (node.interfaceTarget != null) {
+      writeContext = inferrer.computeTypeFromSuperClass(
+          node.interfaceTarget.enclosingClass, writeContext);
+    }
     ExpressionInferenceResult rhsResult = inferrer.inferExpression(
         node.value, writeContext ?? const UnknownType(), true,
         isVoidAllowed: true);
@@ -5678,15 +6279,23 @@
         declaredOrInferredType, rhsResult,
         fileOffset: node.fileOffset,
         isVoidAllowed: declaredOrInferredType is VoidType);
-    inferrer.flowAnalysis.write(variable, rhsResult.inferredType);
+    inferrer.flowAnalysis
+        .write(variable, rhsResult.inferredType, rhsResult.expression);
     DartType resultType = rhsResult.inferredType;
     Expression resultExpression;
     if (variable.lateSetter != null) {
-      resultExpression = new MethodInvocation(
-          new VariableGet(variable.lateSetter)..fileOffset = node.fileOffset,
-          callName,
-          new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset)
-        ..fileOffset = node.fileOffset;
+      if (inferrer.useNewMethodInvocationEncoding) {
+        resultExpression = new LocalFunctionInvocation(variable.lateSetter,
+            new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset,
+            functionType: variable.lateSetter.type)
+          ..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;
+      }
       // Future calls to flow analysis will be using `resultExpression` to refer
       // to the variable set, so instruct flow analysis to forward the
       // expression information.
@@ -5768,12 +6377,13 @@
         if (initializerType is TypeParameterType) {
           inferrer.flowAnalysis.promote(node, initializerType);
         }
-      } else if (!node.isFinal) {
+      } else {
         // TODO(paulberry): `initializerType` is sometimes `null` during top
         // level inference.  Figure out how to prevent this.
         if (initializerType != null) {
-          inferrer.flowAnalysis
-              .write(node, initializerType, viaInitializer: true);
+          inferrer.flowAnalysis.initialize(
+              node, initializerType, initializerResult.expression,
+              isFinal: node.isFinal, isLate: node.isLate);
         }
       }
       Expression initializer = inferrer.ensureAssignableResult(
@@ -5837,7 +6447,11 @@
           new FunctionNode(
               node.initializer == null
                   ? late_lowering.createGetterBodyWithoutInitializer(
-                      inferrer.coreTypes, fileOffset, node.name, node.type,
+                      inferrer.coreTypes,
+                      fileOffset,
+                      node.name,
+                      node.type,
+                      inferrer.useNewMethodInvocationEncoding,
                       createVariableRead: createVariableRead,
                       createIsSetRead: createIsSetRead,
                       isSetEncoding: isSetEncoding,
@@ -5849,6 +6463,7 @@
                           node.name,
                           node.type,
                           node.initializer,
+                          inferrer.useNewMethodInvocationEncoding,
                           createVariableRead: createVariableRead,
                           createVariableWrite: createVariableWrite,
                           createIsSetRead: createIsSetRead,
@@ -5861,6 +6476,7 @@
                           node.name,
                           node.type,
                           node.initializer,
+                          inferrer.useNewMethodInvocationEncoding,
                           createVariableRead: createVariableRead,
                           createVariableWrite: createVariableWrite,
                           createIsSetRead: createIsSetRead,
@@ -5893,6 +6509,7 @@
                             node.name,
                             setterParameter,
                             node.type,
+                            inferrer.useNewMethodInvocationEncoding,
                             shouldReturnValue: true,
                             createVariableRead: createVariableRead,
                             createVariableWrite: createVariableWrite,
@@ -5924,6 +6541,7 @@
         node.initializer = new StaticInvocation(
             inferrer.coreTypes.createSentinelMethod,
             new Arguments([], types: [node.type])..fileOffset = fileOffset)
+          ..fileOffset = fileOffset
           ..parent = node;
       } else {
         node.initializer = null;
@@ -5944,7 +6562,10 @@
     VariableDeclarationImpl variable = node.variable;
     DartType promotedType;
     DartType declaredOrInferredType = variable.lateType ?? variable.type;
-    if (inferrer.isNonNullableByDefault) {
+    if (isExtensionThis(variable)) {
+      // Don't promote the synthetic variable `#this` that we use to represent
+      // `this` inside extension methods.
+    } else if (inferrer.isNonNullableByDefault) {
       if (node.forNullGuardedAccess) {
         DartType nonNullableType = inferrer.computeNonNullable(variable.type);
         if (nonNullableType != variable.type) {
@@ -5972,11 +6593,18 @@
     if (variable.isLocalFunction) {
       return inferrer.instantiateTearOff(resultType, typeContext, node);
     } else if (variable.lateGetter != null) {
-      resultExpression = new MethodInvocation(
-          new VariableGet(variable.lateGetter)..fileOffset = node.fileOffset,
-          callName,
-          new Arguments(<Expression>[])..fileOffset = node.fileOffset)
-        ..fileOffset = node.fileOffset;
+      if (inferrer.useNewMethodInvocationEncoding) {
+        resultExpression = new LocalFunctionInvocation(variable.lateGetter,
+            new Arguments(<Expression>[])..fileOffset = node.fileOffset,
+            functionType: variable.lateGetter.type)
+          ..fileOffset = node.fileOffset;
+      } else {
+        resultExpression = new MethodInvocation(
+            new VariableGet(variable.lateGetter)..fileOffset = node.fileOffset,
+            callName,
+            new Arguments(<Expression>[])..fileOffset = node.fileOffset)
+          ..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.
@@ -6235,6 +6863,97 @@
       }
     }
   }
+
+  @override
+  ExpressionInferenceResult visitDynamicGet(
+      DynamicGet node, DartType typeContext) {
+    // TODO: implement visitDynamicGet
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitInstanceGet(
+      InstanceGet node, DartType typeContext) {
+    // TODO: implement visitInstanceGet
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitInstanceTearOff(
+      InstanceTearOff node, DartType typeContext) {
+    // TODO: implement visitInstanceTearOff
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitDynamicInvocation(
+      DynamicInvocation node, DartType typeContext) {
+    // TODO: implement visitDynamicInvocation
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitDynamicSet(
+      DynamicSet node, DartType typeContext) {
+    // TODO: implement visitDynamicSet
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitEqualsCall(
+      EqualsCall node, DartType typeContext) {
+    // TODO: implement visitEqualsCall
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitEqualsNull(
+      EqualsNull node, DartType typeContext) {
+    // TODO: implement visitEqualsNull
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitFunctionInvocation(
+      FunctionInvocation node, DartType typeContext) {
+    // TODO: implement visitFunctionInvocation
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitInstanceInvocation(
+      InstanceInvocation node, DartType typeContext) {
+    // TODO: implement visitInstanceInvocation
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitInstanceSet(
+      InstanceSet node, DartType typeContext) {
+    // TODO: implement visitInstanceSet
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitLocalFunctionInvocation(
+      LocalFunctionInvocation node, DartType typeContext) {
+    // TODO: implement visitLocalFunctionInvocation
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitStaticTearOff(
+      StaticTearOff node, DartType typeContext) {
+    // TODO: implement visitStaticTearOff
+    throw new UnimplementedError();
+  }
+
+  @override
+  ExpressionInferenceResult visitFunctionTearOff(
+      FunctionTearOff node, DartType arg) {
+    // TODO: implement visitFunctionTearOff
+    throw new UnimplementedError();
+  }
 }
 
 class ForInResult {
@@ -6286,7 +7005,7 @@
         isVoidAllowed: true);
 
     variableSet.value = rhs..parent = variableSet;
-    inferrer.flowAnalysis.write(variableSet.variable, rhsType);
+    inferrer.flowAnalysis.write(variableSet.variable, rhsType, null);
     return variableSet;
   }
 }
@@ -6320,7 +7039,7 @@
     if (error != null) {
       _rhs = error;
     } else {
-      if (writeTarget.isInstanceMember) {
+      if (writeTarget.isInstanceMember || writeTarget.isObjectMember) {
         if (inferrer.instrumentation != null &&
             receiverType == const DynamicType()) {
           inferrer.instrumentation.record(
@@ -6368,7 +7087,7 @@
     ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
         receiverType, superPropertySet.name, superPropertySet.fileOffset,
         setter: true, instrumented: true);
-    if (writeTarget.isInstanceMember) {
+    if (writeTarget.isInstanceMember || writeTarget.isObjectMember) {
       superPropertySet.interfaceTarget = writeTarget.member;
     }
     return _writeType = inferrer.getSetterType(writeTarget, receiverType);
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 9504a6e..b5160f0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.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.9
+
 /// This file declares a "shadow hierarchy" of concrete classes which extend
 /// the kernel class hierarchy, adding methods and fields needed by the
 /// BodyBuilder.
@@ -1785,10 +1787,6 @@
   /// The member used for the write operation.
   final Member setter;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
@@ -1810,13 +1808,11 @@
       this.binaryName,
       this.rhs,
       this.setter,
-      {this.readOnlyReceiver,
-      this.forEffect,
+      {this.forEffect,
       this.readOffset,
       this.binaryOffset,
       this.writeOffset})
-      : assert(readOnlyReceiver != null),
-        assert(forEffect != null),
+      : assert(forEffect != null),
         assert(readOffset != null),
         assert(binaryOffset != null),
         assert(writeOffset != null) {
@@ -1885,10 +1881,6 @@
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   /// The file offset for the read operation.
   final int readOffset;
 
@@ -1900,13 +1892,8 @@
 
   CompoundPropertySet(
       this.receiver, this.propertyName, this.binaryName, this.rhs,
-      {this.forEffect,
-      this.readOnlyReceiver,
-      this.readOffset,
-      this.binaryOffset,
-      this.writeOffset})
+      {this.forEffect, this.readOffset, this.binaryOffset, this.writeOffset})
       : assert(forEffect != null),
-        assert(readOnlyReceiver != null),
         assert(readOffset != null),
         assert(binaryOffset != null),
         assert(writeOffset != null) {
@@ -2253,12 +2240,8 @@
 
   final bool forEffect;
 
-  final bool readOnlyReceiver;
-
-  IndexSet(this.receiver, this.index, this.value,
-      {this.forEffect, this.readOnlyReceiver})
-      : assert(forEffect != null),
-        assert(readOnlyReceiver != null) {
+  IndexSet(this.receiver, this.index, this.value, {this.forEffect})
+      : assert(forEffect != null) {
     receiver?.parent = this;
     index?.parent = this;
     value?.parent = this;
@@ -2446,6 +2429,20 @@
   String toString() {
     return "ExtensionIndexSet(${toStringInternal()})";
   }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.write(extension.name);
+    if (explicitTypeArguments != null) {
+      printer.writeTypeArguments(explicitTypeArguments);
+    }
+    printer.write('(');
+    printer.writeExpression(receiver);
+    printer.write(')[');
+    printer.writeExpression(index);
+    printer.write('] = ');
+    printer.writeExpression(value);
+  }
 }
 
 /// Internal expression representing an if-null index assignment.
@@ -2493,16 +2490,8 @@
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   IfNullIndexSet(this.receiver, this.index, this.value,
-      {this.readOffset,
-      this.testOffset,
-      this.writeOffset,
-      this.forEffect,
-      this.readOnlyReceiver: false})
+      {this.readOffset, this.testOffset, this.writeOffset, this.forEffect})
       : assert(readOffset != null),
         assert(testOffset != null),
         assert(writeOffset != null),
@@ -2688,24 +2677,15 @@
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   IfNullExtensionIndexSet(this.extension, this.explicitTypeArguments,
       this.receiver, this.getter, this.setter, this.index, this.value,
-      {this.readOffset,
-      this.testOffset,
-      this.writeOffset,
-      this.forEffect,
-      this.readOnlyReceiver})
+      {this.readOffset, this.testOffset, this.writeOffset, this.forEffect})
       : assert(explicitTypeArguments == null ||
             explicitTypeArguments.length == extension.typeParameters.length),
         assert(readOffset != null),
         assert(testOffset != null),
         assert(writeOffset != null),
-        assert(forEffect != null),
-        assert(readOnlyReceiver != null) {
+        assert(forEffect != null) {
     receiver?.parent = this;
     index?.parent = this;
     value?.parent = this;
@@ -2792,17 +2772,12 @@
   /// If `true`, the expression is a post-fix inc/dec expression.
   final bool forPostIncDec;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   CompoundIndexSet(this.receiver, this.index, this.binaryName, this.rhs,
       {this.readOffset,
       this.binaryOffset,
       this.writeOffset,
       this.forEffect,
-      this.forPostIncDec,
-      this.readOnlyReceiver: false})
+      this.forPostIncDec})
       : assert(forEffect != null) {
     receiver?.parent = this;
     index?.parent = this;
@@ -2846,6 +2821,29 @@
   String toString() {
     return "CompoundIndexSet(${toStringInternal()})";
   }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver);
+    printer.write('[');
+    printer.writeExpression(index);
+    printer.write(']');
+    if (forPostIncDec &&
+        (binaryName.text == '+' || binaryName.text == '-') &&
+        rhs is IntLiteral &&
+        (rhs as IntLiteral).value == 1) {
+      if (binaryName.text == '+') {
+        printer.write('++');
+      } else {
+        printer.write('--');
+      }
+    } else {
+      printer.write(' ');
+      printer.write(binaryName.text);
+      printer.write('= ');
+      printer.writeExpression(rhs);
+    }
+  }
 }
 
 /// Internal expression representing a null-aware compound assignment.
@@ -3225,10 +3223,6 @@
   /// If `true`, the expression is a post-fix inc/dec expression.
   final bool forPostIncDec;
 
-  /// If `true` the receiver can be cloned instead of creating a temporary
-  /// variable.
-  final bool readOnlyReceiver;
-
   CompoundExtensionIndexSet(
       this.extension,
       this.explicitTypeArguments,
@@ -3242,16 +3236,14 @@
       this.binaryOffset,
       this.writeOffset,
       this.forEffect,
-      this.forPostIncDec,
-      this.readOnlyReceiver})
+      this.forPostIncDec})
       : assert(explicitTypeArguments == null ||
             explicitTypeArguments.length == extension.typeParameters.length),
         assert(readOffset != null),
         assert(binaryOffset != null),
         assert(writeOffset != null),
         assert(forEffect != null),
-        assert(forPostIncDec != null),
-        assert(readOnlyReceiver != null) {
+        assert(forPostIncDec != null) {
     receiver?.parent = this;
     index?.parent = this;
     rhs?.parent = this;
@@ -3336,16 +3328,11 @@
   /// value.
   final bool forEffect;
 
-  /// If `true` the receiver can be cloned instead of creating a temporary
-  /// variable.
-  final bool readOnlyReceiver;
-
   ExtensionSet(this.extension, this.explicitTypeArguments, this.receiver,
       this.target, this.value,
-      {this.readOnlyReceiver, this.forEffect})
+      {this.forEffect})
       : assert(explicitTypeArguments == null ||
             explicitTypeArguments.length == extension.typeParameters.length),
-        assert(readOnlyReceiver != null),
         assert(forEffect != null) {
     receiver?.parent = this;
     value?.parent = this;
@@ -3749,21 +3736,37 @@
   return new VariableGet(variable)..fileOffset = variable.fileOffset;
 }
 
-/// Creates a `e == null` test for the expression [left] using the [fileOffset]
-/// as file offset for the created nodes and [equalsMember] as the interface
-/// target of the created method invocation.
-MethodInvocation createEqualsNull(
-    int fileOffset, Expression left, Member equalsMember) {
-  return new MethodInvocation(
-      left,
-      equalsName,
-      new Arguments(<Expression>[new NullLiteral()..fileOffset = fileOffset])
-        ..fileOffset = fileOffset)
-    ..fileOffset = fileOffset
-    ..interfaceTarget = equalsMember;
-}
-
 ExpressionStatement createExpressionStatement(Expression expression) {
   return new ExpressionStatement(expression)
     ..fileOffset = expression.fileOffset;
 }
+
+/// Returns `true` if [node] is a pure expression.
+///
+/// A pure expression is an expression that is deterministic and side effect
+/// free, such as `this` or a variable get of a final variable.
+bool isPureExpression(Expression node) {
+  if (node is ThisExpression) {
+    return true;
+  } else if (node is VariableGet) {
+    return node.variable.isFinal && !node.variable.isLate;
+  }
+  return false;
+}
+
+/// Returns a clone of [node].
+///
+/// This assumes that `isPureExpression(node)` is `true`.
+Expression clonePureExpression(Expression node) {
+  if (node is ThisExpression) {
+    return new ThisExpression()..fileOffset = node.fileOffset;
+  } else if (node is VariableGet) {
+    assert(
+        node.variable.isFinal && !node.variable.isLate,
+        "Trying to clone VariableGet of non-final variable"
+        " ${node.variable}.");
+    return new VariableGet(node.variable, node.promotedType)
+      ..fileOffset = node.fileOffset;
+  }
+  throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/invalid_type.dart b/pkg/front_end/lib/src/fasta/kernel/invalid_type.dart
index fd05fdb..c361101 100644
--- a/pkg/front_end/lib/src/fasta/kernel/invalid_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/invalid_type.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/visitor.dart';
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart
index c8165a2..8724cfa 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_api.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.9
+
 /// This library exports all API from Kernel that can be used throughout fasta.
 library fasta.kernel_api;
 
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 19f4d2e..4733e7b 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
@@ -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.9
+
 /// This library exports all API from Kernel's ast.dart that can be used
 /// throughout fasta.
 library fasta.kernel_ast_api;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index c0b1459..93eed48 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.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.9
+
 library fasta.kernel_builder;
 
 import 'package:kernel/ast.dart'
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 cf9d6cb..55c93c5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_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.9
+
 library fasta.kernel_constants;
 
 import 'package:front_end/src/fasta/builder/library_builder.dart';
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 5f55924..5135011 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_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.9
+
 library fasta.kernel_target;
 
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
@@ -130,10 +132,6 @@
 
   Component component;
 
-  /// Temporary field meant for testing only. Follow-up CLs should get rid of
-  /// this and integrate coverage properly.
-  constants.ConstantCoverage constantCoverageForTesting;
-
   // 'dynamic' is always nullable.
   // TODO(johnniwinther): Why isn't this using a FixedTypeBuilder?
   final TypeBuilder dynamicType = new NamedTypeBuilder(
@@ -644,7 +642,7 @@
     IndexedClass indexedClass = builder.referencesFromIndexed;
     Constructor referenceFrom;
     if (indexedClass != null) {
-      referenceFrom = indexedClass.lookupConstructor("");
+      referenceFrom = indexedClass.lookupConstructor(new Name(""));
     }
 
     /// From [Dart Programming Language Specification, 4th Edition](
@@ -695,7 +693,7 @@
     IndexedClass indexedClass = builder.referencesFromIndexed;
     Constructor referenceFrom;
     if (indexedClass != null) {
-      referenceFrom = indexedClass.lookupConstructor("");
+      referenceFrom = indexedClass.lookupConstructor(new Name(""));
     }
 
     if (supertype is ClassBuilder) {
@@ -706,7 +704,8 @@
       void addSyntheticConstructor(String name, MemberBuilder memberBuilder) {
         if (memberBuilder.member is Constructor) {
           substitutionMap ??= builder.getSubstitutionMap(superclassBuilder.cls);
-          Constructor referenceFrom = indexedClass?.lookupConstructor(name);
+          Constructor referenceFrom = indexedClass
+              ?.lookupConstructor(new Name(name, indexedClass.library));
           builder.addSyntheticConstructor(_makeMixinApplicationConstructor(
               builder,
               builder.cls.mixin,
@@ -1251,7 +1250,6 @@
             isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
         errorOnUnevaluatedConstant: errorOnUnevaluatedConstant);
     ticker.logMs("Evaluated constants");
-    constantCoverageForTesting = coverage;
 
     coverage.constructorCoverage.forEach((Uri fileUri, Set<Reference> value) {
       Source source = uriToSource[fileUri];
@@ -1336,7 +1334,7 @@
   void verify() {
     // TODO(ahe): How to handle errors.
     verifyComponent(component,
-        skipPlatform: context.options.verifySkipPlatform);
+        skipPlatform: context.options.skipPlatformVerification);
     ClassHierarchy hierarchy =
         new ClassHierarchy(component, new CoreTypes(component),
             onAmbiguousSupertypes: (Class cls, Supertype a, Supertype b) {
@@ -1344,7 +1342,7 @@
     });
     verifyGetStaticType(
         new TypeEnvironment(loader.coreTypes, hierarchy), component,
-        skipPlatform: context.options.verifySkipPlatform);
+        skipPlatform: context.options.skipPlatformVerification);
     ticker.logMs("Verified component");
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_variable_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_variable_builder.dart
index c3400b1..31afc39 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_variable_builder.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.9
+
 library fasta.kernel_variable_builder;
 
 import 'package:kernel/ast.dart' show VariableDeclaration;
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 02ee9f2..577359b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/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.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/core_types.dart';
 
@@ -20,8 +22,13 @@
 ///
 /// 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,
+Statement createGetterWithInitializer(
+    CoreTypes coreTypes,
+    int fileOffset,
+    String name,
+    DartType type,
+    Expression initializer,
+    bool useNewMethodInvocationEncoding,
     {Expression createVariableRead({bool needsPromotion}),
     Expression createVariableWrite(Expression value),
     Expression createIsSetRead(),
@@ -94,23 +101,27 @@
           createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
           type: type.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
-      return new ReturnStatement(
-          new Let(
-              variable,
-              new ConditionalExpression(
-                  new MethodInvocation(
+      return new ReturnStatement(new Let(
+          variable,
+          new ConditionalExpression(
+              useNewMethodInvocationEncoding
+                  ? (new EqualsNull(
+                      new VariableGet(variable)..fileOffset = fileOffset,
+                      isNot: false)
+                    ..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)
+                ..fileOffset = fileOffset,
+              createVariableWrite(initializer)..fileOffset = fileOffset,
+              new VariableGet(variable, type)..fileOffset = fileOffset,
+              type)
             ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
   }
   throw new UnsupportedError("Unexpected IsSetEncoding $isSetEncoding");
@@ -118,8 +129,13 @@
 
 /// 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,
+Statement createGetterWithInitializerWithRecheck(
+    CoreTypes coreTypes,
+    int fileOffset,
+    String name,
+    DartType type,
+    Expression initializer,
+    bool useNewMethodInvocationEncoding,
     {Expression createVariableRead({bool needsPromotion}),
     Expression createVariableWrite(Expression value),
     Expression createIsSetRead(),
@@ -240,22 +256,32 @@
           createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
           type: type.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
-      return new ReturnStatement(
-          new Let(
-              variable,
-              new ConditionalExpression(
-                  new MethodInvocation(
+      return new ReturnStatement(new Let(
+          variable,
+          new ConditionalExpression(
+              useNewMethodInvocationEncoding
+                  ? (new EqualsNull(
+                      new VariableGet(variable)..fileOffset = fileOffset,
+                      isNot: false)
+                    ..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(
-                          new MethodInvocation(
+                ..fileOffset = fileOffset,
+              new Let(
+                  temp,
+                  new ConditionalExpression(
+                      useNewMethodInvocationEncoding
+                          ? (new EqualsNull(
+                              createVariableRead(needsPromotion: false)
+                                ..fileOffset = fileOffset,
+                              isNot: false)
+                            ..fileOffset = fileOffset)
+                          : new MethodInvocation(
                               createVariableRead(needsPromotion: false)
                                 ..fileOffset = fileOffset,
                               equalsName,
@@ -263,17 +289,17 @@
                                 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)
+                        ..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;
   }
   throw new UnsupportedError("Unexpected IsSetEncoding $isSetEncoding");
@@ -282,7 +308,11 @@
 /// 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,
+    CoreTypes coreTypes,
+    int fileOffset,
+    String name,
+    DartType type,
+    bool useNewMethodInvocationEncoding,
     {Expression createVariableRead({bool needsPromotion}),
     Expression createIsSetRead(),
     IsSetEncoding isSetEncoding,
@@ -346,23 +376,27 @@
           createVariableRead()..fileOffset = fileOffset,
           type: type.withDeclaredNullability(Nullability.nullable))
         ..fileOffset = fileOffset;
-      return new ReturnStatement(
-          new Let(
-              variable,
-              new ConditionalExpression(
-                  new MethodInvocation(
+      return new ReturnStatement(new Let(
+          variable,
+          new ConditionalExpression(
+              useNewMethodInvocationEncoding
+                  ? (new EqualsNull(
+                      new VariableGet(variable)..fileOffset = fileOffset,
+                      isNot: false)
+                    ..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)
+                ..fileOffset = fileOffset,
+              exception,
+              new VariableGet(variable, type)..fileOffset = fileOffset,
+              type)
             ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset)
         ..fileOffset = fileOffset;
   }
   throw new UnsupportedError("Unexpected IsSetEncoding $isSetEncoding");
@@ -417,8 +451,13 @@
 
 /// 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,
+Statement createSetterBodyFinal(
+    CoreTypes coreTypes,
+    int fileOffset,
+    String name,
+    VariableDeclaration parameter,
+    DartType type,
+    bool useNewMethodInvocationEncoding,
     {bool shouldReturnValue,
     Expression createVariableRead(),
     Expression createVariableWrite(Expression value),
@@ -500,12 +539,16 @@
       //      throw '...';
       //    }
       return new IfStatement(
-        new MethodInvocation(
-            createVariableRead()..fileOffset = fileOffset,
-            equalsName,
-            new Arguments(
-                <Expression>[new NullLiteral()..fileOffset = fileOffset])
+        useNewMethodInvocationEncoding
+            ? (new EqualsNull(createVariableRead()..fileOffset = fileOffset,
+                isNot: false)
               ..fileOffset = fileOffset)
+            : new MethodInvocation(
+                createVariableRead()..fileOffset = fileOffset,
+                equalsName,
+                new Arguments(
+                    <Expression>[new NullLiteral()..fileOffset = fileOffset])
+                  ..fileOffset = fileOffset)
           ..fileOffset = fileOffset,
         createReturn(createVariableWrite(
             new VariableGet(parameter)..fileOffset = fileOffset)
diff --git a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
index 9c26327..3639f4a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.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.9
+
 import 'package:kernel/ast.dart'
     show
         Arguments,
@@ -15,6 +17,7 @@
         Name,
         Procedure,
         ProcedureKind,
+        Reference,
         ReturnStatement;
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
@@ -50,8 +53,8 @@
     LoadLibrary expression = createLoadLibrary(charOffset, forest, null);
     String prefix = expression.import.name;
     Name name = new Name('_#loadLibrary_$prefix', parent.library);
-    Procedure referencesFrom =
-        parent.lookupLibraryReferenceProcedure(name.text, false);
+    Reference reference =
+        parent.referencesFromIndexed?.lookupGetterReference(name);
     tearoff = new Procedure(
         name,
         ProcedureKind.Method,
@@ -60,7 +63,7 @@
                 parent.nonNullable, <DartType>[const DynamicType()])),
         fileUri: parent.library.fileUri,
         isStatic: true,
-        reference: referencesFrom?.reference)
+        reference: reference)
       ..startFileOffset = charOffset
       ..fileOffset = charOffset
       ..isNonNullableByDefault = parent.isNonNullableByDefault;
diff --git a/pkg/front_end/lib/src/fasta/kernel/member_covariance.dart b/pkg/front_end/lib/src/fasta/kernel/member_covariance.dart
index 6a5eaaf..6d4a9f1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/member_covariance.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/member_covariance.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.9
+
 import 'dart:math';
 
 import 'package:kernel/ast.dart' hide MapEntry;
diff --git a/pkg/front_end/lib/src/fasta/kernel/metadata_collector.dart b/pkg/front_end/lib/src/fasta/kernel/metadata_collector.dart
index 82f84f5..f77e230 100644
--- a/pkg/front_end/lib/src/fasta/kernel/metadata_collector.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/metadata_collector.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.9
+
 import 'package:kernel/kernel.dart' show Member, MetadataRepository, NamedNode;
 
 /// The collector to add target specific metadata to.
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 3a12ab4..0d82df2 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
@@ -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.9
+
 library fasta.redirecting_factory_body;
 
 import 'package:kernel/ast.dart'
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 a7a85b9..220157ef 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -2,50 +2,17 @@
 // for 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.transform_collections;
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart'
-    show
-        Arguments,
-        AsExpression,
-        Block,
-        BlockExpression,
-        Class,
-        ConditionalExpression,
-        DartType,
-        DynamicType,
-        Expression,
-        ExpressionStatement,
-        Field,
-        ForInStatement,
-        ForStatement,
-        IfStatement,
-        InterfaceType,
-        Let,
-        Library,
-        ListConcatenation,
-        ListLiteral,
-        MapConcatenation,
-        MapEntry,
-        MapLiteral,
-        MethodInvocation,
-        Name,
-        Not,
-        NullLiteral,
-        Procedure,
-        PropertyGet,
-        SetConcatenation,
-        SetLiteral,
-        Statement,
-        StaticInvocation,
-        transformList,
-        TreeNode,
-        VariableDeclaration,
-        VariableGet;
+import 'package:kernel/ast.dart';
 
 import 'package:kernel/core_types.dart' show CoreTypes;
+import 'package:kernel/src/legacy_erasure.dart';
+import 'package:kernel/type_algebra.dart';
 
 import 'package:kernel/type_environment.dart'
     show SubtypeCheckMode, TypeEnvironment;
@@ -75,19 +42,25 @@
   final SourceLoader _loader;
   final TypeEnvironment _typeEnvironment;
   final Procedure _listAdd;
+  FunctionType _listAddFunctionType;
   final Procedure _listAddAll;
+  FunctionType _listAddAllFunctionType;
   final Procedure _listOf;
   final Procedure _setFactory;
   final Procedure _setAdd;
+  FunctionType _setAddFunctionType;
   final Procedure _setAddAll;
+  FunctionType _setAddAllFunctionType;
   final Procedure _setOf;
   final Procedure _objectEquals;
   final Procedure _mapEntries;
   final Procedure _mapPut;
+  FunctionType _mapPutFunctionType;
   final Class _mapEntryClass;
   final Field _mapEntryKey;
   final Field _mapEntryValue;
   final SourceLoaderDataForTesting _dataForTesting;
+  final bool useNewMethodInvocationEncoding;
 
   /// Library that contains the transformed nodes.
   ///
@@ -124,7 +97,15 @@
             _loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'key'),
         _mapEntryValue =
             _loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'value'),
-        _dataForTesting = _loader.dataForTesting;
+        _dataForTesting = _loader.dataForTesting,
+        useNewMethodInvocationEncoding =
+            _loader.target.backendTarget.supportsNewMethodInvocationEncoding {
+    _listAddFunctionType = _listAdd.getterType;
+    _listAddAllFunctionType = _listAddAll.getterType;
+    _setAddFunctionType = _setAdd.getterType;
+    _setAddAllFunctionType = _setAddAll.getterType;
+    _mapPutFunctionType = _mapPut.getterType;
+  }
 
   TreeNode _translateListOrSet(
       Expression node, DartType elementType, List<Expression> elements,
@@ -139,6 +120,9 @@
     // If there were only expressions, we are done.
     if (index == elements.length) return node;
 
+    InterfaceType receiverType = isSet
+        ? _typeEnvironment.setType(elementType, _currentLibrary.nonNullable)
+        : _typeEnvironment.listType(elementType, _currentLibrary.nonNullable);
     VariableDeclaration result;
     if (index == 0 && elements[index] is SpreadElement) {
       SpreadElement initialSpread = elements[index];
@@ -156,8 +140,7 @@
                   new Arguments([value], types: [elementType])
                     ..fileOffset = node.fileOffset)
                 ..fileOffset = node.fileOffset,
-              _typeEnvironment.setType(
-                  elementType, _currentLibrary.nonNullable));
+              receiverType);
         } else {
           result = _createVariable(
               new StaticInvocation(
@@ -165,8 +148,7 @@
                   new Arguments([value], types: [elementType])
                     ..fileOffset = node.fileOffset)
                 ..fileOffset = node.fileOffset,
-              _typeEnvironment.listType(
-                  elementType, _currentLibrary.nonNullable));
+              receiverType);
         }
       }
     }
@@ -180,8 +162,7 @@
           result = _createVariable(
               _createSetLiteral(
                   node.fileOffset, elementType, elements.sublist(0, index)),
-              _typeEnvironment.setType(
-                  elementType, _currentLibrary.nonNullable));
+              receiverType);
         } else {
           // TODO(johnniwinther): When all the back ends handle set literals we
           //  can use remove this branch.
@@ -193,12 +174,12 @@
                   new Arguments([], types: [elementType])
                     ..fileOffset = node.fileOffset)
                 ..fileOffset = node.fileOffset,
-              _typeEnvironment.setType(
-                  elementType, _currentLibrary.nonNullable));
+              receiverType);
           body = [result];
           // Add the elements up to the first non-expression.
           for (int j = 0; j < index; ++j) {
-            _addExpressionElement(elements[j], isSet, result, body);
+            _addExpressionElement(
+                elements[j], receiverType, isSet, result, body);
           }
         }
       } else {
@@ -207,50 +188,65 @@
         result = _createVariable(
             _createListLiteral(
                 node.fileOffset, elementType, elements.sublist(0, index)),
-            _typeEnvironment.listType(
-                elementType, _currentLibrary.nonNullable));
+            receiverType);
       }
     }
     body ??= [result];
     // Translate the elements starting with the first non-expression.
     for (; index < elements.length; ++index) {
-      _translateElement(elements[index], elementType, isSet, result, body);
+      _translateElement(
+          elements[index], receiverType, elementType, isSet, result, body);
     }
 
     return _createBlockExpression(
         node.fileOffset, _createBlock(body), _createVariableGet(result));
   }
 
-  void _translateElement(Expression element, DartType elementType, bool isSet,
-      VariableDeclaration result, List<Statement> body) {
+  void _translateElement(
+      Expression element,
+      InterfaceType receiverType,
+      DartType elementType,
+      bool isSet,
+      VariableDeclaration result,
+      List<Statement> body) {
     if (element is SpreadElement) {
-      _translateSpreadElement(element, elementType, isSet, result, body);
+      _translateSpreadElement(
+          element, receiverType, elementType, isSet, result, body);
     } else if (element is IfElement) {
-      _translateIfElement(element, elementType, isSet, result, body);
+      _translateIfElement(
+          element, receiverType, elementType, isSet, result, body);
     } else if (element is ForElement) {
-      _translateForElement(element, elementType, isSet, result, body);
+      _translateForElement(
+          element, receiverType, elementType, isSet, result, body);
     } else if (element is ForInElement) {
-      _translateForInElement(element, elementType, isSet, result, body);
+      _translateForInElement(
+          element, receiverType, elementType, isSet, result, body);
     } else {
       _addExpressionElement(
-          element.accept<TreeNode>(this), isSet, result, body);
+          element.accept<TreeNode>(this), receiverType, isSet, result, body);
     }
   }
 
-  void _addExpressionElement(Expression element, bool isSet,
-      VariableDeclaration result, List<Statement> body) {
+  void _addExpressionElement(Expression element, InterfaceType receiverType,
+      bool isSet, VariableDeclaration result, List<Statement> body) {
     body.add(_createExpressionStatement(
-        _createAdd(_createVariableGet(result), element, isSet)));
+        _createAdd(_createVariableGet(result), receiverType, element, isSet)));
   }
 
-  void _translateIfElement(IfElement element, DartType elementType, bool isSet,
-      VariableDeclaration result, List<Statement> body) {
+  void _translateIfElement(
+      IfElement element,
+      InterfaceType receiverType,
+      DartType elementType,
+      bool isSet,
+      VariableDeclaration result,
+      List<Statement> body) {
     List<Statement> thenStatements = [];
-    _translateElement(element.then, elementType, isSet, result, thenStatements);
+    _translateElement(
+        element.then, receiverType, elementType, isSet, result, thenStatements);
     List<Statement> elseStatements;
     if (element.otherwise != null) {
-      _translateElement(element.otherwise, elementType, isSet, result,
-          elseStatements = <Statement>[]);
+      _translateElement(element.otherwise, receiverType, elementType, isSet,
+          result, elseStatements = <Statement>[]);
     }
     Statement thenBody = thenStatements.length == 1
         ? thenStatements.first
@@ -261,14 +257,22 @@
           ? elseStatements.first
           : _createBlock(elseStatements);
     }
-    body.add(_createIf(element.fileOffset,
-        element.condition.accept<TreeNode>(this), thenBody, elseBody));
+    IfStatement ifStatement = _createIf(element.fileOffset,
+        element.condition.accept<TreeNode>(this), thenBody, elseBody);
+    _dataForTesting?.registerAlias(element, ifStatement);
+    body.add(ifStatement);
   }
 
-  void _translateForElement(ForElement element, DartType elementType,
-      bool isSet, VariableDeclaration result, List<Statement> body) {
+  void _translateForElement(
+      ForElement element,
+      InterfaceType receiverType,
+      DartType elementType,
+      bool isSet,
+      VariableDeclaration result,
+      List<Statement> body) {
     List<Statement> statements = <Statement>[];
-    _translateElement(element.body, elementType, isSet, result, statements);
+    _translateElement(
+        element.body, receiverType, elementType, isSet, result, statements);
     Statement loopBody =
         statements.length == 1 ? statements.first : _createBlock(statements);
     ForStatement loop = _createForStatement(
@@ -283,8 +287,13 @@
     body.add(loop);
   }
 
-  void _translateForInElement(ForInElement element, DartType elementType,
-      bool isSet, VariableDeclaration result, List<Statement> body) {
+  void _translateForInElement(
+      ForInElement element,
+      InterfaceType receiverType,
+      DartType elementType,
+      bool isSet,
+      VariableDeclaration result,
+      List<Statement> body) {
     List<Statement> statements;
     Statement prologue = element.prologue;
     if (prologue == null) {
@@ -294,7 +303,8 @@
       statements =
           prologue is Block ? prologue.statements : <Statement>[prologue];
     }
-    _translateElement(element.body, elementType, isSet, result, statements);
+    _translateElement(
+        element.body, receiverType, elementType, isSet, result, statements);
     Statement loopBody =
         statements.length == 1 ? statements.first : _createBlock(statements);
     if (element.problem != null) {
@@ -308,8 +318,13 @@
     body.add(loop);
   }
 
-  void _translateSpreadElement(SpreadElement element, DartType elementType,
-      bool isSet, VariableDeclaration result, List<Statement> body) {
+  void _translateSpreadElement(
+      SpreadElement element,
+      InterfaceType receiverType,
+      DartType elementType,
+      bool isSet,
+      VariableDeclaration result,
+      List<Statement> body) {
     Expression value = element.expression.accept<TreeNode>(this);
 
     final bool typeMatches = element.elementType != null &&
@@ -331,8 +346,8 @@
         value = _createNullCheckedVariableGet(temp);
       }
 
-      Statement statement = _createExpressionStatement(
-          _createAddAll(_createVariableGet(result), value, isSet));
+      Statement statement = _createExpressionStatement(_createAddAll(
+          _createVariableGet(result), receiverType, value, isSet));
 
       if (element.isNullAware) {
         statement = _createIf(
@@ -365,13 +380,16 @@
             elementType);
         loopBody = _createBlock(<Statement>[
           castedVar,
-          _createExpressionStatement(_createAdd(
-              _createVariableGet(result), _createVariableGet(castedVar), isSet))
+          _createExpressionStatement(_createAdd(_createVariableGet(result),
+              receiverType, _createVariableGet(castedVar), isSet))
         ]);
       } else {
         variable = _createForInVariable(element.fileOffset, elementType);
         loopBody = _createExpressionStatement(_createAdd(
-            _createVariableGet(result), _createVariableGet(variable), isSet));
+            _createVariableGet(result),
+            receiverType,
+            _createVariableGet(variable),
+            isSet));
       }
       Statement statement =
           _createForInStatement(element.fileOffset, variable, value, loopBody);
@@ -425,52 +443,66 @@
     if (i == node.entries.length) return node;
 
     // Build a block expression and create an empty map.
+    InterfaceType receiverType = _typeEnvironment.mapType(
+        node.keyType, node.valueType, _currentLibrary.nonNullable);
     VariableDeclaration result = _createVariable(
         _createMapLiteral(node.fileOffset, node.keyType, node.valueType, []),
-        _typeEnvironment.mapType(
-            node.keyType, node.valueType, _currentLibrary.nonNullable));
+        receiverType);
     List<Statement> body = [result];
     // Add all the entries up to the first control-flow entry.
     for (int j = 0; j < i; ++j) {
-      _addNormalEntry(node.entries[j], result, body);
+      _addNormalEntry(node.entries[j], receiverType, result, body);
     }
     for (; i < node.entries.length; ++i) {
-      _translateEntry(
-          node.entries[i], node.keyType, node.valueType, result, body);
+      _translateEntry(node.entries[i], receiverType, node.keyType,
+          node.valueType, result, body);
     }
 
     return _createBlockExpression(
         node.fileOffset, _createBlock(body), _createVariableGet(result));
   }
 
-  void _translateEntry(MapEntry entry, DartType keyType, DartType valueType,
-      VariableDeclaration result, List<Statement> body) {
+  void _translateEntry(
+      MapEntry entry,
+      InterfaceType receiverType,
+      DartType keyType,
+      DartType valueType,
+      VariableDeclaration result,
+      List<Statement> body) {
     if (entry is SpreadMapEntry) {
-      _translateSpreadEntry(entry, keyType, valueType, result, body);
+      _translateSpreadEntry(
+          entry, receiverType, keyType, valueType, result, body);
     } else if (entry is IfMapEntry) {
-      _translateIfEntry(entry, keyType, valueType, result, body);
+      _translateIfEntry(entry, receiverType, keyType, valueType, result, body);
     } else if (entry is ForMapEntry) {
-      _translateForEntry(entry, keyType, valueType, result, body);
+      _translateForEntry(entry, receiverType, keyType, valueType, result, body);
     } else if (entry is ForInMapEntry) {
-      _translateForInEntry(entry, keyType, valueType, result, body);
+      _translateForInEntry(
+          entry, receiverType, keyType, valueType, result, body);
     } else {
-      _addNormalEntry(entry.accept<TreeNode>(this), result, body);
+      _addNormalEntry(entry.accept<TreeNode>(this), receiverType, result, body);
     }
   }
 
-  void _addNormalEntry(
-      MapEntry entry, VariableDeclaration result, List<Statement> body) {
-    body.add(_createExpressionStatement(_createIndexSet(
-        entry.fileOffset, _createVariableGet(result), entry.key, entry.value)));
+  void _addNormalEntry(MapEntry entry, InterfaceType receiverType,
+      VariableDeclaration result, List<Statement> body) {
+    body.add(_createExpressionStatement(_createIndexSet(entry.fileOffset,
+        _createVariableGet(result), receiverType, entry.key, entry.value)));
   }
 
-  void _translateIfEntry(IfMapEntry entry, DartType keyType, DartType valueType,
-      VariableDeclaration result, List<Statement> body) {
+  void _translateIfEntry(
+      IfMapEntry entry,
+      InterfaceType receiverType,
+      DartType keyType,
+      DartType valueType,
+      VariableDeclaration result,
+      List<Statement> body) {
     List<Statement> thenBody = [];
-    _translateEntry(entry.then, keyType, valueType, result, thenBody);
+    _translateEntry(
+        entry.then, receiverType, keyType, valueType, result, thenBody);
     List<Statement> elseBody;
     if (entry.otherwise != null) {
-      _translateEntry(entry.otherwise, keyType, valueType, result,
+      _translateEntry(entry.otherwise, receiverType, keyType, valueType, result,
           elseBody = <Statement>[]);
     }
     Statement thenStatement =
@@ -480,14 +512,22 @@
       elseStatement =
           elseBody.length == 1 ? elseBody.first : _createBlock(elseBody);
     }
-    body.add(_createIf(entry.fileOffset, entry.condition.accept<TreeNode>(this),
-        thenStatement, elseStatement));
+    IfStatement ifStatement = _createIf(entry.fileOffset,
+        entry.condition.accept<TreeNode>(this), thenStatement, elseStatement);
+    _dataForTesting?.registerAlias(entry, ifStatement);
+    body.add(ifStatement);
   }
 
-  void _translateForEntry(ForMapEntry entry, DartType keyType,
-      DartType valueType, VariableDeclaration result, List<Statement> body) {
+  void _translateForEntry(
+      ForMapEntry entry,
+      InterfaceType receiverType,
+      DartType keyType,
+      DartType valueType,
+      VariableDeclaration result,
+      List<Statement> body) {
     List<Statement> statements = <Statement>[];
-    _translateEntry(entry.body, keyType, valueType, result, statements);
+    _translateEntry(
+        entry.body, receiverType, keyType, valueType, result, statements);
     Statement loopBody =
         statements.length == 1 ? statements.first : _createBlock(statements);
     ForStatement loop = _createForStatement(entry.fileOffset, entry.variables,
@@ -498,8 +538,13 @@
     body.add(loop);
   }
 
-  void _translateForInEntry(ForInMapEntry entry, DartType keyType,
-      DartType valueType, VariableDeclaration result, List<Statement> body) {
+  void _translateForInEntry(
+      ForInMapEntry entry,
+      InterfaceType receiverType,
+      DartType keyType,
+      DartType valueType,
+      VariableDeclaration result,
+      List<Statement> body) {
     List<Statement> statements;
     Statement prologue = entry.prologue;
     if (prologue == null) {
@@ -509,7 +554,8 @@
       statements =
           prologue is Block ? prologue.statements : <Statement>[prologue];
     }
-    _translateEntry(entry.body, keyType, valueType, result, statements);
+    _translateEntry(
+        entry.body, receiverType, keyType, valueType, result, statements);
     Statement loopBody =
         statements.length == 1 ? statements.first : _createBlock(statements);
     if (entry.problem != null) {
@@ -523,8 +569,13 @@
     body.add(loop);
   }
 
-  void _translateSpreadEntry(SpreadMapEntry entry, DartType keyType,
-      DartType valueType, VariableDeclaration result, List<Statement> body) {
+  void _translateSpreadEntry(
+      SpreadMapEntry entry,
+      InterfaceType receiverType,
+      DartType keyType,
+      DartType valueType,
+      VariableDeclaration result,
+      List<Statement> body) {
     Expression value = entry.expression.accept<TreeNode>(this);
 
     final DartType entryType = new InterfaceType(_mapEntryClass,
@@ -573,6 +624,7 @@
         _createExpressionStatement(_createIndexSet(
             entry.expression.fileOffset,
             _createVariableGet(result),
+            receiverType,
             _createVariableGet(keyVar),
             _createVariableGet(valueVar)))
       ]);
@@ -581,6 +633,7 @@
       loopBody = _createExpressionStatement(_createIndexSet(
           entry.expression.fileOffset,
           _createVariableGet(result),
+          receiverType,
           _createGetKey(
               entry.expression.fileOffset, _createVariableGet(variable)),
           _createGetValue(
@@ -839,53 +892,101 @@
       ..fileOffset = expression.fileOffset;
   }
 
-  MethodInvocation _createAdd(
-      Expression receiver, Expression argument, bool isSet) {
+  Expression _createAdd(Expression receiver, InterfaceType receiverType,
+      Expression argument, bool isSet) {
     assert(receiver != null);
     assert(argument != null);
     assert(argument.fileOffset != TreeNode.noOffset,
         "No fileOffset on ${argument}.");
-    return new MethodInvocation(receiver, new Name('add'),
-        new Arguments([argument]), isSet ? _setAdd : _listAdd)
-      ..fileOffset = argument.fileOffset
-      ..isInvariant = true;
+    if (useNewMethodInvocationEncoding) {
+      FunctionType 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,
+          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;
+    }
   }
 
-  MethodInvocation _createAddAll(
-      Expression receiver, Expression argument, bool isSet) {
+  Expression _createAddAll(Expression receiver, InterfaceType receiverType,
+      Expression argument, bool isSet) {
     assert(receiver != null);
     assert(argument != null);
     assert(argument.fileOffset != TreeNode.noOffset,
         "No fileOffset on ${argument}.");
-    return new MethodInvocation(receiver, new Name('addAll'),
-        new Arguments([argument]), isSet ? _setAddAll : _listAddAll)
-      ..fileOffset = argument.fileOffset
-      ..isInvariant = true;
+    if (useNewMethodInvocationEncoding) {
+      FunctionType 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,
+          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;
+    }
   }
 
   Expression _createEqualsNull(Expression expression, {bool notEquals: false}) {
     assert(expression != null);
     assert(expression.fileOffset != TreeNode.noOffset);
-    Expression check = new MethodInvocation(
-        expression,
-        new Name('=='),
-        new Arguments([new NullLiteral()..fileOffset = expression.fileOffset]),
-        _objectEquals)
-      ..fileOffset = expression.fileOffset;
-    if (notEquals) {
-      check = new Not(check)..fileOffset = expression.fileOffset;
+    if (useNewMethodInvocationEncoding) {
+      return new EqualsNull(expression, isNot: notEquals)
+        ..fileOffset = expression.fileOffset;
+    } else {
+      Expression check = new MethodInvocation(
+          expression,
+          new Name('=='),
+          new Arguments(
+              [new NullLiteral()..fileOffset = expression.fileOffset]),
+          _objectEquals)
+        ..fileOffset = expression.fileOffset;
+      if (notEquals) {
+        check = new Not(check)..fileOffset = expression.fileOffset;
+      }
+      return check;
     }
-    return check;
   }
 
-  MethodInvocation _createIndexSet(
-      int fileOffset, Expression receiver, Expression key, Expression value) {
+  Expression _createIndexSet(int fileOffset, Expression receiver,
+      InterfaceType receiverType, Expression key, Expression value) {
     assert(fileOffset != null);
     assert(fileOffset != TreeNode.noOffset);
-    return new MethodInvocation(
-        receiver, new Name('[]='), new Arguments([key, value]), _mapPut)
-      ..fileOffset = fileOffset
-      ..isInvariant = true;
+    if (useNewMethodInvocationEncoding) {
+      FunctionType 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, interfaceTarget: _mapPut)
+        ..fileOffset = fileOffset
+        ..isInvariant = true;
+    } else {
+      return new MethodInvocation(
+          receiver, new Name('[]='), new Arguments([key, value]), _mapPut)
+        ..fileOffset = fileOffset
+        ..isInvariant = true;
+    }
   }
 
   AsExpression _createImplicitAs(
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 67f0898..250493f 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
@@ -2,31 +2,20 @@
 // for 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.transform_set_literals;
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart'
-    show
-        Arguments,
-        Block,
-        BlockExpression,
-        Expression,
-        ExpressionStatement,
-        InterfaceType,
-        Library,
-        MethodInvocation,
-        Name,
-        Procedure,
-        SetLiteral,
-        Statement,
-        StaticInvocation,
-        TreeNode,
-        VariableDeclaration,
-        VariableGet;
+import 'package:kernel/ast.dart';
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
+import 'package:kernel/src/legacy_erasure.dart' show legacyErasure;
+
+import 'package:kernel/type_algebra.dart' show Substitution;
+
 import 'package:kernel/visitor.dart' show Transformer;
 
 import '../source/source_loader.dart' show SourceLoader;
@@ -38,6 +27,8 @@
   final CoreTypes coreTypes;
   final Procedure setFactory;
   final Procedure addMethod;
+  FunctionType _addMethodFunctionType;
+  final bool useNewMethodInvocationEncoding;
 
   /// Library that contains the transformed nodes.
   ///
@@ -58,29 +49,45 @@
   SetLiteralTransformer(SourceLoader loader)
       : coreTypes = loader.coreTypes,
         setFactory = _findSetFactory(loader.coreTypes),
-        addMethod = _findAddMethod(loader.coreTypes);
+        addMethod = _findAddMethod(loader.coreTypes),
+        useNewMethodInvocationEncoding =
+            loader.target.backendTarget.supportsNewMethodInvocationEncoding {
+    _addMethodFunctionType = addMethod.getterType;
+  }
 
   TreeNode visitSetLiteral(SetLiteral node) {
     if (node.isConst) return node;
 
     // Create the set: Set<E> setVar = new Set<E>();
+    DartType receiverType;
     VariableDeclaration setVar = new VariableDeclaration.forValue(
         new StaticInvocation(
             setFactory, new Arguments([], types: [node.typeArgument])),
-        type: new InterfaceType(coreTypes.setClass, _currentLibrary.nonNullable,
-            [node.typeArgument]));
+        type: receiverType = new InterfaceType(coreTypes.setClass,
+            _currentLibrary.nonNullable, [node.typeArgument]));
 
     // Now create a list of all statements needed.
     List<Statement> statements = [setVar];
     for (int i = 0; i < node.expressions.length; i++) {
       Expression entry = node.expressions[i].accept<TreeNode>(this);
-      MethodInvocation methodInvocation = new MethodInvocation(
-          new VariableGet(setVar),
-          new Name("add"),
-          new Arguments([entry]),
-          addMethod)
-        ..fileOffset = entry.fileOffset
-        ..isInvariant = true;
+      Expression methodInvocation;
+      if (useNewMethodInvocationEncoding) {
+        FunctionType 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, 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;
+      }
       statements.add(new ExpressionStatement(methodInvocation)
         ..fileOffset = methodInvocation.fileOffset);
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index 48a5c3f..8b6464e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart'
     show
         BottomType,
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 ee11a13..82a9dc9 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
@@ -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.9
+
 library fasta.type_builder_computer;
 
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
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 76a901f..4784bf2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.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.9
+
 import 'dart:convert' show json;
 
 import 'package:kernel/ast.dart'
@@ -35,6 +37,7 @@
         SymbolConstant,
         TearOffConstant,
         TreeNode,
+        Typedef,
         TypedefType,
         TypeLiteralConstant,
         TypeParameter,
@@ -142,7 +145,26 @@
   }
 
   void defaultDartType(DartType type) {}
-  void visitTypedefType(TypedefType node) {}
+
+  void visitTypedefType(TypedefType node) {
+    Typedef typedefNode = node.typedefNode;
+    result.add(nameForEntity(
+        typedefNode,
+        typedefNode.name,
+        typedefNode.enclosingLibrary.importUri,
+        typedefNode.enclosingLibrary.fileUri));
+    if (node.typeArguments.isNotEmpty) {
+      result.add("<");
+      bool first = true;
+      for (DartType typeArg in node.typeArguments) {
+        if (!first) result.add(", ");
+        typeArg.accept(this);
+        first = false;
+      }
+      result.add(">");
+    }
+    addNullability(node.nullability);
+  }
 
   void visitInvalidType(InvalidType node) {
     // TODO(askesc): Throw internal error if InvalidType appears in diagnostics.
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index 1eaf2b3..e55e325 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.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.9
+
 import 'dart:io' show BytesBuilder, File, IOSink;
 
 import 'dart:typed_data' show Uint8List;
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index a15a5c9..ddfef29 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.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.9
+
 library fasta.verifier;
 
 import 'dart:core' hide MapEntry;
@@ -111,9 +113,9 @@
   TreeNode get localContext {
     TreeNode result = getSameLibraryLastSeenTreeNode(withLocation: true);
     if (result == null &&
-        currentClassOrMember != null &&
-        _isInSameLibrary(currentLibrary, currentClassOrMember)) {
-      result = currentClassOrMember;
+        currentClassOrExtensionOrMember != null &&
+        _isInSameLibrary(currentLibrary, currentClassOrExtensionOrMember)) {
+      result = currentClassOrExtensionOrMember;
     }
     return result;
   }
@@ -172,7 +174,7 @@
 
   @override
   problem(TreeNode node, String details, {TreeNode context, TreeNode origin}) {
-    node ??= (context ?? currentClassOrMember);
+    node ??= (context ?? currentClassOrExtensionOrMember);
     int offset = node?.fileOffset ?? -1;
     Uri file = node?.location?.file ?? fileUri;
     Uri uri = file == null ? null : file;
@@ -241,6 +243,14 @@
   }
 
   @override
+  void visitExtension(Extension node) {
+    enterTreeNode(node);
+    fileUri = checkLocation(node, node.name, node.fileUri);
+    super.visitExtension(node);
+    exitTreeNode(node);
+  }
+
+  @override
   void visitField(Field node) {
     enterTreeNode(node);
     fileUri = checkLocation(node, node.name.text, node.fileUri);
diff --git a/pkg/front_end/lib/src/fasta/library_graph.dart b/pkg/front_end/lib/src/fasta/library_graph.dart
index 5a75f85..5b93e51 100644
--- a/pkg/front_end/lib/src/fasta/library_graph.dart
+++ b/pkg/front_end/lib/src/fasta/library_graph.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.9
+
 library fasta.library_graph;
 
 import 'package:kernel/kernel.dart'
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index cfdb636..41da009 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.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.9
+
 library fasta.loader;
 
 import 'dart:collection' show Queue;
@@ -306,7 +308,7 @@
       List<LocatedMessage> context,
       bool problemOnLibrary: false,
       List<Uri> involvedFiles}) {
-    severity = target.fixSeverity(severity, message, fileUri);
+    severity ??= message.code.severity;
     if (severity == Severity.ignored) return null;
     String trace = """
 message: ${message.message}
diff --git a/pkg/front_end/lib/src/fasta/messages.dart b/pkg/front_end/lib/src/fasta/messages.dart
index 396f054..3f1330a 100644
--- a/pkg/front_end/lib/src/fasta/messages.dart
+++ b/pkg/front_end/lib/src/fasta/messages.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.9
+
 library fasta.messages;
 
 import 'package:kernel/ast.dart'
diff --git a/pkg/front_end/lib/src/fasta/modifier.dart b/pkg/front_end/lib/src/fasta/modifier.dart
index c93ef12..32a6aa2 100644
--- a/pkg/front_end/lib/src/fasta/modifier.dart
+++ b/pkg/front_end/lib/src/fasta/modifier.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.9
+
 library fasta.modifier;
 
 import 'problems.dart' show unhandled;
diff --git a/pkg/front_end/lib/src/fasta/names.dart b/pkg/front_end/lib/src/fasta/names.dart
index 229b64b..ba20ec8 100644
--- a/pkg/front_end/lib/src/fasta/names.dart
+++ b/pkg/front_end/lib/src/fasta/names.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.9
+
 library front_end.src.fasta.names;
 
 import 'package:kernel/ast.dart' show Name;
diff --git a/pkg/front_end/lib/src/fasta/operator.dart b/pkg/front_end/lib/src/fasta/operator.dart
index 1617a5a..917c385 100644
--- a/pkg/front_end/lib/src/fasta/operator.dart
+++ b/pkg/front_end/lib/src/fasta/operator.dart
@@ -31,7 +31,7 @@
   unaryMinus,
 }
 
-Operator operatorFromString(String string) {
+Operator? operatorFromString(String string) {
   if (identical("+", string)) return Operator.add;
   if (identical("&", string)) return Operator.bitwiseAnd;
   if (identical("~", string)) return Operator.bitwiseNot;
@@ -101,7 +101,6 @@
     case Operator.unaryMinus:
       return "unary-";
   }
-  return null;
 }
 
 int operatorRequiredArgumentCount(Operator operator) {
@@ -133,5 +132,4 @@
     case Operator.indexSet:
       return 2;
   }
-  return -1;
 }
diff --git a/pkg/front_end/lib/src/fasta/problems.dart b/pkg/front_end/lib/src/fasta/problems.dart
index f1d61a2..db9552f 100644
--- a/pkg/front_end/lib/src/fasta/problems.dart
+++ b/pkg/front_end/lib/src/fasta/problems.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.9
+
 library fasta.problems;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart'
diff --git a/pkg/front_end/lib/src/fasta/rewrite_severity.dart b/pkg/front_end/lib/src/fasta/rewrite_severity.dart
deleted file mode 100644
index 5fd9ae8..0000000
--- a/pkg/front_end/lib/src/fasta/rewrite_severity.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-
-import 'messages.dart' as msg;
-
-Severity rewriteSeverity(
-    Severity severity, msg.Code<Object> code, Uri fileUri) {
-  if (severity != Severity.ignored) {
-    return severity;
-  }
-
-  String path = fileUri.path;
-  String fastaPath = "/pkg/front_end/lib/src/fasta/";
-  int index = path.indexOf(fastaPath);
-  if (index == -1) {
-    fastaPath = "/pkg/front_end/tool/_fasta/";
-    index = path.indexOf(fastaPath);
-    if (index == -1) return severity;
-  }
-  if (code == msg.codeUseOfDeprecatedIdentifier) {
-    // TODO(ahe): Remove the exceptions below.
-    // We plan to remove all uses of deprecated identifiers from Fasta. The
-    // strategy is to remove files from the list below one by one. To get
-    // started on cleaning up a given file, simply remove it from the list
-    // below and compile Fasta with itself to get a list of remaining call
-    // sites.
-    switch (path.substring(fastaPath.length + index)) {
-      case "command_line.dart":
-      case "kernel/body_builder.dart":
-        return severity;
-    }
-  }
-  return Severity.error;
-}
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 709e438..5fa0edf 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.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.9
+
 library fasta.scope;
 
 import 'package:kernel/ast.dart' hide MapEntry;
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 bc81fc6..2787514 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.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.9
+
 library fasta.diet_listener;
 
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
diff --git a/pkg/front_end/lib/src/fasta/source/directive_listener.dart b/pkg/front_end/lib/src/fasta/source/directive_listener.dart
index f912c9e..3c29fe1 100644
--- a/pkg/front_end/lib/src/fasta/source/directive_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/directive_listener.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.9
+
 /// Listener used in combination with `TopLevelParser` to extract the URIs of
 /// import, part, and export directives.
 library front_end.src.fasta.source.directive_listener;
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 98a5907..c8aa4b5 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.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.9
+
 library fasta.outline_builder;
 
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
diff --git a/pkg/front_end/lib/src/fasta/source/scope_listener.dart b/pkg/front_end/lib/src/fasta/source/scope_listener.dart
index 29bbad1..c445403 100644
--- a/pkg/front_end/lib/src/fasta/source/scope_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/scope_listener.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.9
+
 library fasta.scope_listener;
 
 import 'package:_fe_analyzer_shared/src/parser/block_kind.dart' show BlockKind;
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 b2645dd..f944fe9 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
@@ -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.9
+
 library fasta.source_class_builder;
 
 import 'package:front_end/src/fasta/kernel/combined_member_signature.dart';
@@ -418,8 +420,8 @@
             typeParameter.name,
             Variance.keywordString(variance));
       }
-      library.reportTypeArgumentIssue(
-          message, fileUri, fileOffset, typeParameter);
+      library.reportTypeArgumentIssue(message, fileUri, fileOffset,
+          typeParameter: typeParameter);
     }
   }
 
@@ -427,49 +429,42 @@
       Supertype supertype, TypeEnvironment typeEnvironment) {
     SourceLibraryBuilder libraryBuilder = this.library;
     Library library = libraryBuilder.library;
-    final DartType bottomType = library.isNonNullableByDefault
-        ? const NeverType(Nullability.nonNullable)
-        : const NullType();
 
-    Set<TypeArgumentIssue> issues = {};
-    issues.addAll(findTypeArgumentIssues(
-            library,
-            new InterfaceType(supertype.classNode, library.nonNullable,
-                supertype.typeArguments),
-            typeEnvironment,
-            SubtypeCheckMode.ignoringNullabilities,
-            bottomType,
-            allowSuperBounded: false) ??
-        const []);
-    if (library.isNonNullableByDefault) {
-      issues.addAll(findTypeArgumentIssues(
-              library,
-              new InterfaceType(supertype.classNode, library.nonNullable,
-                  supertype.typeArguments),
-              typeEnvironment,
-              SubtypeCheckMode.withNullabilities,
-              bottomType,
-              allowSuperBounded: false) ??
-          const []);
-    }
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        library,
+        new InterfaceType(
+            supertype.classNode, library.nonNullable, supertype.typeArguments),
+        typeEnvironment,
+        libraryBuilder.isNonNullableByDefault
+            ? SubtypeCheckMode.withNullabilities
+            : SubtypeCheckMode.ignoringNullabilities,
+        allowSuperBounded: false);
     for (TypeArgumentIssue issue in issues) {
       DartType argument = issue.argument;
       TypeParameter typeParameter = issue.typeParameter;
       bool inferred = libraryBuilder.inferredTypes.contains(argument);
-      if (argument is FunctionType && argument.typeParameters.length > 0) {
+      if (isGenericFunctionTypeOrAlias(argument)) {
         if (inferred) {
+          // Supertype can't be or contain super-bounded types, so null is
+          // passed for super-bounded hint here.
           libraryBuilder.reportTypeArgumentIssue(
               templateGenericFunctionTypeInferredAsActualTypeArgument
                   .withArguments(argument, library.isNonNullableByDefault),
               fileUri,
               charOffset,
-              null);
+              typeParameter: null,
+              superBoundedAttempt: null,
+              superBoundedAttemptInverted: null);
         } else {
+          // Supertype can't be or contain super-bounded types, so null is
+          // passed for super-bounded hint here.
           libraryBuilder.reportTypeArgumentIssue(
               messageGenericFunctionTypeUsedAsActualTypeArgument,
               fileUri,
               charOffset,
-              null);
+              typeParameter: null,
+              superBoundedAttempt: null,
+              superBoundedAttemptInverted: null);
         }
       } else {
         void reportProblem(
@@ -477,6 +472,8 @@
                     Message Function(DartType, DartType, String, String, String,
                         String, bool)>
                 template) {
+          // Supertype can't be or contain super-bounded types, so null is
+          // passed for super-bounded hint here.
           libraryBuilder.reportTypeArgumentIssue(
               template.withArguments(
                   argument,
@@ -488,7 +485,9 @@
                   library.isNonNullableByDefault),
               fileUri,
               charOffset,
-              typeParameter);
+              typeParameter: typeParameter,
+              superBoundedAttempt: null,
+              superBoundedAttemptInverted: null);
         }
 
         if (inferred) {
@@ -811,9 +810,19 @@
         new Arguments.forwarded(procedure.function, library.library),
         procedure.fileOffset,
         /*isSuper=*/ false);
-    Expression result = new MethodInvocation(new ThisExpression(),
-        noSuchMethodName, new Arguments([invocation]), noSuchMethodInterface)
-      ..fileOffset = procedure.fileOffset;
+    Expression result;
+    if (library
+        .loader.target.backendTarget.supportsNewMethodInvocationEncoding) {
+      result = new InstanceInvocation(InstanceAccessKind.Instance,
+          new ThisExpression(), noSuchMethodName, new Arguments([invocation]),
+          functionType: noSuchMethodInterface.getterType,
+          interfaceTarget: noSuchMethodInterface)
+        ..fileOffset = procedure.fileOffset;
+    } else {
+      result = new MethodInvocation(new ThisExpression(), noSuchMethodName,
+          new Arguments([invocation]), noSuchMethodInterface)
+        ..fileOffset = procedure.fileOffset;
+    }
     if (procedure.function.returnType is! VoidType) {
       result = new AsExpression(result, procedure.function.returnType)
         ..isTypeError = true
@@ -833,7 +842,7 @@
   }
 
   void _addRedirectingConstructor(ProcedureBuilder constructorBuilder,
-      SourceLibraryBuilder library, Field referenceFrom) {
+      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
     // source code.
@@ -851,12 +860,12 @@
     if (constructorsField == null) {
       ListLiteral literal = new ListLiteral(<Expression>[]);
       Name name = new Name(redirectingName, library.library);
-      Field field = new Field(name,
+      Field field = new Field.immutable(name,
           isStatic: true,
+          isFinal: true,
           initializer: literal,
           fileUri: cls.fileUri,
-          getterReference: referenceFrom?.getterReference,
-          setterReference: referenceFrom?.setterReference)
+          getterReference: getterReference)
         ..fileOffset = cls.fileOffset;
       cls.addField(field);
       constructorsField = new DillFieldBuilder(field, this);
@@ -898,9 +907,11 @@
                 // is actually in the kernel tree. This call creates a StaticGet
                 // to [declaration.target] in a field `_redirecting#` which is
                 // only legal to do to things in the kernel tree.
-                Field referenceFrom =
-                    referencesFromIndexed?.lookupField("_redirecting#");
-                _addRedirectingConstructor(declaration, library, referenceFrom);
+                Reference getterReference =
+                    referencesFromIndexed?.lookupGetterReference(new Name(
+                        "_redirecting#", referencesFromIndexed.library));
+                _addRedirectingConstructor(
+                    declaration, library, getterReference);
               }
               if (targetBuilder is FunctionBuilder) {
                 List<DartType> typeArguments = declaration.typeArguments ??
@@ -948,13 +959,11 @@
     return count;
   }
 
-  void checkOverride(
-      Types types,
-      Member declaredMember,
-      Member interfaceMember,
-      bool isSetter,
-      callback(Member declaredMember, Member interfaceMember, bool isSetter),
-      {bool isInterfaceCheck = false}) {
+  void checkOverride(Types types, Member declaredMember, Member interfaceMember,
+      bool isSetter, callback(Member interfaceMember, bool isSetter),
+      {bool isInterfaceCheck, bool declaredNeedsLegacyErasure}) {
+    assert(isInterfaceCheck != null);
+    assert(declaredNeedsLegacyErasure != null);
     if (declaredMember == interfaceMember) {
       return;
     }
@@ -968,21 +977,34 @@
       if (declaredMember.kind == interfaceMember.kind) {
         if (declaredMember.kind == ProcedureKind.Method ||
             declaredMember.kind == ProcedureKind.Operator) {
-          bool seenCovariant = checkMethodOverride(types, declaredMember,
-              interfaceMember, interfaceMemberOrigin, isInterfaceCheck);
+          bool seenCovariant = checkMethodOverride(
+              types,
+              declaredMember,
+              interfaceMember,
+              interfaceMemberOrigin,
+              isInterfaceCheck,
+              declaredNeedsLegacyErasure);
           if (seenCovariant) {
-            handleSeenCovariant(
-                types, declaredMember, interfaceMember, isSetter, callback);
+            handleSeenCovariant(types, interfaceMember, isSetter, callback);
           }
         } else if (declaredMember.kind == ProcedureKind.Getter) {
-          checkGetterOverride(types, declaredMember, interfaceMember,
-              interfaceMemberOrigin, isInterfaceCheck);
+          checkGetterOverride(
+              types,
+              declaredMember,
+              interfaceMember,
+              interfaceMemberOrigin,
+              isInterfaceCheck,
+              declaredNeedsLegacyErasure);
         } else if (declaredMember.kind == ProcedureKind.Setter) {
-          bool seenCovariant = checkSetterOverride(types, declaredMember,
-              interfaceMember, interfaceMemberOrigin, isInterfaceCheck);
+          bool seenCovariant = checkSetterOverride(
+              types,
+              declaredMember,
+              interfaceMember,
+              interfaceMemberOrigin,
+              isInterfaceCheck,
+              declaredNeedsLegacyErasure);
           if (seenCovariant) {
-            handleSeenCovariant(
-                types, declaredMember, interfaceMember, isSetter, callback);
+            handleSeenCovariant(types, interfaceMember, isSetter, callback);
           }
         } else {
           assert(
@@ -1005,15 +1027,24 @@
               !interfaceMember.isConst) ||
           interfaceMember is Procedure && interfaceMember.isSetter;
       if (declaredMemberHasGetter && interfaceMemberHasGetter) {
-        checkGetterOverride(types, declaredMember, interfaceMember,
-            interfaceMemberOrigin, isInterfaceCheck);
+        checkGetterOverride(
+            types,
+            declaredMember,
+            interfaceMember,
+            interfaceMemberOrigin,
+            isInterfaceCheck,
+            declaredNeedsLegacyErasure);
       }
       if (declaredMemberHasSetter && interfaceMemberHasSetter) {
-        bool seenCovariant = checkSetterOverride(types, declaredMember,
-            interfaceMember, interfaceMemberOrigin, isInterfaceCheck);
+        bool seenCovariant = checkSetterOverride(
+            types,
+            declaredMember,
+            interfaceMember,
+            interfaceMemberOrigin,
+            isInterfaceCheck,
+            declaredNeedsLegacyErasure);
         if (seenCovariant) {
-          handleSeenCovariant(
-              types, declaredMember, interfaceMember, isSetter, callback);
+          handleSeenCovariant(types, interfaceMember, isSetter, callback);
         }
       }
     }
@@ -1183,7 +1214,8 @@
       Member interfaceMemberOrigin,
       FunctionNode declaredFunction,
       FunctionNode interfaceFunction,
-      bool isInterfaceCheck) {
+      bool isInterfaceCheck,
+      bool declaredNeedsLegacyErasure) {
     Substitution interfaceSubstitution = Substitution.empty;
     if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
       Class enclosingClass = interfaceMember.enclosingClass;
@@ -1236,6 +1268,9 @@
           if (!library.isNonNullableByDefault) {
             computedBound = legacyErasure(computedBound);
           }
+          if (declaredNeedsLegacyErasure) {
+            declaredBound = legacyErasure(declaredBound);
+          }
           if (!types
               .performNullabilityAwareMutualSubtypesCheck(
                   declaredBound, computedBound)
@@ -1294,6 +1329,7 @@
       bool isCovariant,
       VariableDeclaration declaredParameter,
       bool isInterfaceCheck,
+      bool declaredNeedsLegacyErasure,
       {bool asIfDeclaredParameter = false}) {
     if (interfaceSubstitution != null) {
       interfaceType = interfaceSubstitution.substituteType(interfaceType);
@@ -1301,6 +1337,9 @@
     if (declaredSubstitution != null) {
       declaredType = declaredSubstitution.substituteType(declaredType);
     }
+    if (declaredNeedsLegacyErasure) {
+      declaredType = legacyErasure(declaredType);
+    }
 
     if (!declaredMember.isNonNullableByDefault &&
         interfaceMember.isNonNullableByDefault) {
@@ -1390,7 +1429,8 @@
       Procedure declaredMember,
       Procedure interfaceMember,
       Member interfaceMemberOrigin,
-      bool isInterfaceCheck) {
+      bool isInterfaceCheck,
+      bool declaredNeedsLegacyErasure) {
     assert(declaredMember.kind == interfaceMember.kind);
     assert(declaredMember.kind == ProcedureKind.Method ||
         declaredMember.kind == ProcedureKind.Operator);
@@ -1405,7 +1445,8 @@
         interfaceMemberOrigin,
         declaredFunction,
         interfaceFunction,
-        isInterfaceCheck);
+        isInterfaceCheck,
+        declaredNeedsLegacyErasure);
 
     Substitution declaredSubstitution =
         _computeDeclaredSubstitution(types, declaredMember);
@@ -1421,7 +1462,8 @@
         interfaceFunction.returnType,
         false,
         null,
-        isInterfaceCheck);
+        isInterfaceCheck,
+        declaredNeedsLegacyErasure);
     if (declaredFunction.positionalParameters.length <
         interfaceFunction.positionalParameters.length) {
       reportInvalidOverride(
@@ -1430,15 +1472,15 @@
           templateOverrideFewerPositionalArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
                   "${declaredMember.name.text}",
-              "${interfaceMember.enclosingClass.name}."
-                  "${interfaceMember.name.text}"),
+              "${interfaceMemberOrigin.enclosingClass.name}."
+                  "${interfaceMemberOrigin.name.text}"),
           declaredMember.fileOffset,
           noLength,
           context: [
             templateOverriddenMethodCause
-                .withArguments(interfaceMember.name.text)
-                .withLocation(interfaceMember.fileUri,
-                    interfaceMember.fileOffset, noLength)
+                .withArguments(interfaceMemberOrigin.name.text)
+                .withLocation(interfaceMemberOrigin.fileUri,
+                    interfaceMemberOrigin.fileOffset, noLength)
           ]);
     }
     if (interfaceFunction.requiredParameterCount <
@@ -1449,15 +1491,15 @@
           templateOverrideMoreRequiredArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
                   "${declaredMember.name.text}",
-              "${interfaceMember.enclosingClass.name}."
-                  "${interfaceMember.name.text}"),
+              "${interfaceMemberOrigin.enclosingClass.name}."
+                  "${interfaceMemberOrigin.name.text}"),
           declaredMember.fileOffset,
           noLength,
           context: [
             templateOverriddenMethodCause
-                .withArguments(interfaceMember.name.text)
-                .withLocation(interfaceMember.fileUri,
-                    interfaceMember.fileOffset, noLength)
+                .withArguments(interfaceMemberOrigin.name.text)
+                .withLocation(interfaceMemberOrigin.fileUri,
+                    interfaceMemberOrigin.fileOffset, noLength)
           ]);
     }
     for (int i = 0;
@@ -1490,7 +1532,8 @@
           interfaceParameter.type,
           declaredParameter.isCovariant || interfaceParameter.isCovariant,
           declaredParameter,
-          isInterfaceCheck);
+          isInterfaceCheck,
+          declaredNeedsLegacyErasure);
       if (declaredParameter.isCovariant) seenCovariant = true;
     }
     if (declaredFunction.namedParameters.isEmpty &&
@@ -1568,8 +1611,10 @@
           interfaceNamedParameters.current.type,
           declaredParameter.isCovariant,
           declaredParameter,
-          isInterfaceCheck);
+          isInterfaceCheck,
+          declaredNeedsLegacyErasure);
       if (declaredMember.isNonNullableByDefault &&
+          !declaredNeedsLegacyErasure &&
           declaredParameter.isRequired &&
           interfaceMember.isNonNullableByDefault &&
           !interfaceNamedParameters.current.isRequired) {
@@ -1606,7 +1651,8 @@
       Member declaredMember,
       Member interfaceMember,
       Member interfaceMemberOrigin,
-      bool isInterfaceCheck) {
+      bool isInterfaceCheck,
+      bool declaredNeedsLegacyErasure) {
     Substitution interfaceSubstitution = _computeInterfaceSubstitution(
         types,
         declaredMember,
@@ -1614,7 +1660,8 @@
         interfaceMemberOrigin,
         /* declaredFunction = */ null,
         /* interfaceFunction = */ null,
-        isInterfaceCheck);
+        isInterfaceCheck,
+        declaredNeedsLegacyErasure);
     Substitution declaredSubstitution =
         _computeDeclaredSubstitution(types, declaredMember);
     DartType declaredType = declaredMember.getterType;
@@ -1630,7 +1677,8 @@
         interfaceType,
         /* isCovariant = */ false,
         /* declaredParameter = */ null,
-        isInterfaceCheck);
+        isInterfaceCheck,
+        declaredNeedsLegacyErasure);
   }
 
   /// Checks whether [declaredMember] correctly overrides [interfaceMember].
@@ -1646,7 +1694,8 @@
       Member declaredMember,
       Member interfaceMember,
       Member interfaceMemberOrigin,
-      bool isInterfaceCheck) {
+      bool isInterfaceCheck,
+      bool declaredNeedsLegacyErasure) {
     Substitution interfaceSubstitution = _computeInterfaceSubstitution(
         types,
         declaredMember,
@@ -1654,7 +1703,8 @@
         interfaceMemberOrigin,
         /* declaredFunction = */ null,
         /* interfaceFunction = */ null,
-        isInterfaceCheck);
+        isInterfaceCheck,
+        declaredNeedsLegacyErasure);
     Substitution declaredSubstitution =
         _computeDeclaredSubstitution(types, declaredMember);
     DartType declaredType = declaredMember.setterType;
@@ -1680,6 +1730,7 @@
         isCovariant,
         declaredParameter,
         isInterfaceCheck,
+        declaredNeedsLegacyErasure,
         asIfDeclaredParameter: true);
     return isCovariant;
   }
@@ -1746,9 +1797,23 @@
 /// 'dart:_interceptors' that implements both `int` and `double`, and `JsArray`
 /// in `dart:js` that implement both `ListMixin` and `JsObject`.
 bool shouldOverrideProblemBeOverlooked(ClassBuilder classBuilder) {
+  return getOverlookedOverrideProblemChoice(classBuilder) != null;
+}
+
+/// Returns the index of the member to use if an override problems should be
+/// overlooked.
+///
+/// This is needed for the current encoding of some JavaScript implementation
+/// classes that are not valid Dart. For instance `JSInt` in
+/// 'dart:_interceptors' that implements both `int` and `double`, and `JsArray`
+/// in `dart:js` that implement both `ListMixin` and `JsObject`.
+int getOverlookedOverrideProblemChoice(ClassBuilder classBuilder) {
   String uri = '${classBuilder.library.importUri}';
-  return uri == 'dart:js' &&
-          classBuilder.fileUri.pathSegments.last == 'js.dart' ||
-      uri == 'dart:_interceptors' &&
-          classBuilder.fileUri.pathSegments.last == 'js_number.dart';
+  if (uri == 'dart:js' && classBuilder.fileUri.pathSegments.last == 'js.dart') {
+    return 0;
+  } else if (uri == 'dart:_interceptors' &&
+      classBuilder.fileUri.pathSegments.last == 'js_number.dart') {
+    return 1;
+  }
+  return null;
 }
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 28b3fb8..744ce07 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
@@ -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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
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 fdc6b3a..39531a8 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
@@ -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.9
+
 library fasta.source_library_builder;
 
 import 'dart:convert' show jsonEncode;
@@ -13,6 +15,9 @@
 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'
     show
         Arguments,
@@ -26,7 +31,6 @@
         Extension,
         Field,
         FunctionNode,
-        FunctionType,
         InterfaceType,
         InvalidType,
         Library,
@@ -59,14 +63,15 @@
 import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
 
 import 'package:kernel/reference_from_index.dart'
-    show IndexedClass, IndexedLibrary;
+    show IndexedClass, IndexedContainer, IndexedLibrary;
 
 import 'package:kernel/src/bounds_checks.dart'
     show
         TypeArgumentIssue,
         findTypeArgumentIssues,
         findTypeArgumentIssuesForInvocation,
-        getGenericTypeName;
+        getGenericTypeName,
+        isGenericFunctionTypeOrAlias;
 
 import 'package:kernel/type_algebra.dart' show Substitution, substitute;
 
@@ -179,7 +184,7 @@
   final List<ConstructorReferenceBuilder> constructorReferences =
       <ConstructorReferenceBuilder>[];
 
-  final List<SourceLibraryBuilder> parts = <SourceLibraryBuilder>[];
+  final List<LibraryBuilder> parts = <LibraryBuilder>[];
 
   // Can I use library.parts instead? See SourceLibraryBuilder.addPart.
   final List<int> partOffsets = <int>[];
@@ -976,13 +981,14 @@
     library.procedures.sort(compareProcedures);
 
     if (unserializableExports != null) {
-      Field referenceFrom = referencesFromIndexed?.lookupField("_exports#");
-      library.addField(new Field(new Name("_exports#", library),
+      Name fieldName = new Name("_exports#", library);
+      Reference getterReference =
+          referencesFromIndexed?.lookupGetterReference(fieldName);
+      library.addField(new Field.immutable(fieldName,
           initializer: new StringLiteral(jsonEncode(unserializableExports)),
           isStatic: true,
           isConst: true,
-          getterReference: referenceFrom?.getterReference,
-          setterReference: referenceFrom?.setterReference));
+          getterReference: getterReference));
     }
 
     return library;
@@ -1031,7 +1037,7 @@
   void includeParts(Set<Uri> usedParts) {
     Set<Uri> seenParts = new Set<Uri>();
     for (int i = 0; i < parts.length; i++) {
-      SourceLibraryBuilder part = parts[i];
+      LibraryBuilder part = parts[i];
       int partOffset = partOffsets[i];
       if (part == this) {
         addProblem(messagePartOfSelf, -1, noLength, fileUri);
@@ -1059,28 +1065,39 @@
     }
   }
 
-  bool includePart(
-      SourceLibraryBuilder part, Set<Uri> usedParts, int partOffset) {
-    if (part.partOfUri != null) {
-      if (uriIsValid(part.partOfUri) && part.partOfUri != importUri) {
-        // This is an error, but the part is not removed from the list of parts,
-        // so that metadata annotations can be associated with it.
-        addProblem(
-            templatePartOfUriMismatch.withArguments(
-                part.fileUri, importUri, part.partOfUri),
-            partOffset,
-            noLength,
-            fileUri);
-        return false;
-      }
-    } else if (part.partOfName != null) {
-      if (name != null) {
-        if (part.partOfName != name) {
+  bool includePart(LibraryBuilder part, Set<Uri> usedParts, int partOffset) {
+    if (part is SourceLibraryBuilder) {
+      if (part.partOfUri != null) {
+        if (uriIsValid(part.partOfUri) && part.partOfUri != importUri) {
           // This is an error, but the part is not removed from the list of
           // parts, so that metadata annotations can be associated with it.
           addProblem(
-              templatePartOfLibraryNameMismatch.withArguments(
-                  part.fileUri, name, part.partOfName),
+              templatePartOfUriMismatch.withArguments(
+                  part.fileUri, importUri, part.partOfUri),
+              partOffset,
+              noLength,
+              fileUri);
+          return false;
+        }
+      } else if (part.partOfName != null) {
+        if (name != null) {
+          if (part.partOfName != name) {
+            // This is an error, but the part is not removed from the list of
+            // parts, so that metadata annotations can be associated with it.
+            addProblem(
+                templatePartOfLibraryNameMismatch.withArguments(
+                    part.fileUri, name, part.partOfName),
+                partOffset,
+                noLength,
+                fileUri);
+            return false;
+          }
+        } else {
+          // This is an error, but the part is not removed from the list of
+          // parts, so that metadata annotations can be associated with it.
+          addProblem(
+              templatePartOfUseUri.withArguments(
+                  part.fileUri, fileUri, part.partOfName),
               partOffset,
               noLength,
               fileUri);
@@ -1089,119 +1106,124 @@
       } else {
         // This is an error, but the part is not removed from the list of parts,
         // so that metadata annotations can be associated with it.
-        addProblem(
-            templatePartOfUseUri.withArguments(
-                part.fileUri, fileUri, part.partOfName),
-            partOffset,
-            noLength,
-            fileUri);
+        assert(!part.isPart);
+        if (uriIsValid(part.fileUri)) {
+          addProblem(templateMissingPartOf.withArguments(part.fileUri),
+              partOffset, noLength, fileUri);
+        }
         return false;
       }
+
+      // Language versions have to match. Except if (at least) one of them is
+      // invalid in which case we've already gotten an error about this.
+      if (languageVersion != part.languageVersion &&
+          languageVersion.valid &&
+          part.languageVersion.valid) {
+        // This is an error, but the part is not removed from the list of
+        // parts, so that metadata annotations can be associated with it.
+        List<LocatedMessage> context = <LocatedMessage>[];
+        if (languageVersion.isExplicit) {
+          context.add(messageLanguageVersionLibraryContext.withLocation(
+              languageVersion.fileUri,
+              languageVersion.charOffset,
+              languageVersion.charCount));
+        }
+        if (part.languageVersion.isExplicit) {
+          context.add(messageLanguageVersionPartContext.withLocation(
+              part.languageVersion.fileUri,
+              part.languageVersion.charOffset,
+              part.languageVersion.charCount));
+        }
+        addProblem(
+            messageLanguageVersionMismatchInPart, partOffset, noLength, fileUri,
+            context: context);
+      }
+
+      part.validatePart(this, usedParts);
+      NameIterator partDeclarations = part.nameIterator;
+      while (partDeclarations.moveNext()) {
+        String name = partDeclarations.name;
+        Builder declaration = partDeclarations.current;
+
+        if (declaration.next != null) {
+          List<Builder> duplicated = <Builder>[];
+          while (declaration.next != null) {
+            duplicated.add(declaration);
+            partDeclarations.moveNext();
+            declaration = partDeclarations.current;
+          }
+          duplicated.add(declaration);
+          // Handle duplicated declarations in the part.
+          //
+          // Duplicated declarations are handled by creating a linked list using
+          // the `next` field. This is preferred over making all scope entries
+          // be a `List<Declaration>`.
+          //
+          // We maintain the linked list so that the last entry is easy to
+          // recognize (it's `next` field is null). This means that it is
+          // reversed with respect to source code order. Since kernel doesn't
+          // allow duplicated declarations, we ensure that we only add the first
+          // declaration to the kernel tree.
+          //
+          // Since the duplicated declarations are stored in reverse order, we
+          // iterate over them in reverse order as this is simpler and normally
+          // not a problem. However, in this case we need to call [addBuilder]
+          // in source order as it would otherwise create cycles.
+          //
+          // We also need to be careful preserving the order of the links. The
+          // part library still keeps these declarations in its scope so that
+          // DietListener can find them.
+          for (int i = duplicated.length; i > 0; i--) {
+            Builder declaration = duplicated[i - 1];
+            // No reference: There should be no duplicates when using
+            // references.
+            addBuilder(name, declaration, declaration.charOffset);
+          }
+        } else {
+          // No reference: The part is in the same loader so the reference
+          // - if needed - was already added.
+          addBuilder(name, declaration, declaration.charOffset);
+        }
+      }
+      types.addAll(part.types);
+      constructorReferences.addAll(part.constructorReferences);
+      part.partOfLibrary = this;
+      part.scope.becomePartOf(scope);
+      // TODO(ahe): Include metadata from part?
+
+      nativeMethods.addAll(part.nativeMethods);
+      boundlessTypeVariables.addAll(part.boundlessTypeVariables);
+      // Check that the targets are different. This is not normally a problem
+      // but is for patch files.
+      if (library != part.library && part.library.problemsAsJson != null) {
+        library.problemsAsJson ??= <String>[];
+        library.problemsAsJson.addAll(part.library.problemsAsJson);
+      }
+      List<FieldBuilder> partImplicitlyTypedFields =
+          part.takeImplicitlyTypedFields();
+      if (partImplicitlyTypedFields != null) {
+        if (_implicitlyTypedFields == null) {
+          _implicitlyTypedFields = partImplicitlyTypedFields;
+        } else {
+          _implicitlyTypedFields.addAll(partImplicitlyTypedFields);
+        }
+      }
+      return true;
     } else {
-      // This is an error, but the part is not removed from the list of parts,
-      // so that metadata annotations can be associated with it.
-      assert(!part.isPart);
+      assert(part is DillLibraryBuilder);
+      // Trying to add a dill library builder as a part means that it exists
+      // as a stand-alone library in the dill file.
+      // This means, that it's not a part (if it had been it would be been
+      // "merged in" to the real library and thus not been a library on its own)
+      // so we behave like if it's a library with a missing "part of"
+      // declaration (i.e. as it was a SourceLibraryBuilder without a "part of"
+      // declaration).
       if (uriIsValid(part.fileUri)) {
         addProblem(templateMissingPartOf.withArguments(part.fileUri),
             partOffset, noLength, fileUri);
       }
       return false;
     }
-
-    // Language versions have to match. Except if (at least) one of them is
-    // invalid in which case we've already gotten an error about this.
-    if (languageVersion != part.languageVersion &&
-        languageVersion.valid &&
-        part.languageVersion.valid) {
-      // This is an error, but the part is not removed from the list of
-      // parts, so that metadata annotations can be associated with it.
-      List<LocatedMessage> context = <LocatedMessage>[];
-      if (languageVersion.isExplicit) {
-        context.add(messageLanguageVersionLibraryContext.withLocation(
-            languageVersion.fileUri,
-            languageVersion.charOffset,
-            languageVersion.charCount));
-      }
-      if (part.languageVersion.isExplicit) {
-        context.add(messageLanguageVersionPartContext.withLocation(
-            part.languageVersion.fileUri,
-            part.languageVersion.charOffset,
-            part.languageVersion.charCount));
-      }
-      addProblem(
-          messageLanguageVersionMismatchInPart, partOffset, noLength, fileUri,
-          context: context);
-    }
-
-    part.validatePart(this, usedParts);
-    NameIterator partDeclarations = part.nameIterator;
-    while (partDeclarations.moveNext()) {
-      String name = partDeclarations.name;
-      Builder declaration = partDeclarations.current;
-
-      if (declaration.next != null) {
-        List<Builder> duplicated = <Builder>[];
-        while (declaration.next != null) {
-          duplicated.add(declaration);
-          partDeclarations.moveNext();
-          declaration = partDeclarations.current;
-        }
-        duplicated.add(declaration);
-        // Handle duplicated declarations in the part.
-        //
-        // Duplicated declarations are handled by creating a linked list using
-        // the `next` field. This is preferred over making all scope entries be
-        // a `List<Declaration>`.
-        //
-        // We maintain the linked list so that the last entry is easy to
-        // recognize (it's `next` field is null). This means that it is
-        // reversed with respect to source code order. Since kernel doesn't
-        // allow duplicated declarations, we ensure that we only add the first
-        // declaration to the kernel tree.
-        //
-        // Since the duplicated declarations are stored in reverse order, we
-        // iterate over them in reverse order as this is simpler and normally
-        // not a problem. However, in this case we need to call [addBuilder] in
-        // source order as it would otherwise create cycles.
-        //
-        // We also need to be careful preserving the order of the links. The
-        // part library still keeps these declarations in its scope so that
-        // DietListener can find them.
-        for (int i = duplicated.length; i > 0; i--) {
-          Builder declaration = duplicated[i - 1];
-          // No reference: There should be no duplicates when using references.
-          addBuilder(name, declaration, declaration.charOffset);
-        }
-      } else {
-        // No reference: The part is in the same loader so the reference
-        // - if needed - was already added.
-        addBuilder(name, declaration, declaration.charOffset);
-      }
-    }
-    types.addAll(part.types);
-    constructorReferences.addAll(part.constructorReferences);
-    part.partOfLibrary = this;
-    part.scope.becomePartOf(scope);
-    // TODO(ahe): Include metadata from part?
-
-    nativeMethods.addAll(part.nativeMethods);
-    boundlessTypeVariables.addAll(part.boundlessTypeVariables);
-    // Check that the targets are different. This is not normally a problem
-    // but is for patch files.
-    if (library != part.library && part.library.problemsAsJson != null) {
-      library.problemsAsJson ??= <String>[];
-      library.problemsAsJson.addAll(part.library.problemsAsJson);
-    }
-    List<FieldBuilder> partImplicitlyTypedFields =
-        part.takeImplicitlyTypedFields();
-    if (partImplicitlyTypedFields != null) {
-      if (_implicitlyTypedFields == null) {
-        _implicitlyTypedFields = partImplicitlyTypedFields;
-      } else {
-        _implicitlyTypedFields.addAll(partImplicitlyTypedFields);
-      }
-    }
-    return true;
   }
 
   void buildInitialScopes() {
@@ -1268,7 +1290,9 @@
                     // so replacing a field with a getter/setter pair still
                     // exports correctly.
                     library.additionalExports.add(member.getterReference);
-                    library.additionalExports.add(member.setterReference);
+                    if (member.hasSetter) {
+                      library.additionalExports.add(member.setterReference);
+                    }
                   } else {
                     library.additionalExports.add(member.reference);
                   }
@@ -2114,10 +2138,6 @@
     if (hasInitializer) {
       modifiers |= hasInitializerMask;
     }
-    Field referenceFrom;
-    Field lateIsSetReferenceFrom;
-    Procedure getterReferenceFrom;
-    Procedure setterReferenceFrom;
     final bool fieldIsLateWithLowering = (modifiers & lateMask) != 0 &&
         loader.target.backendTarget.isLateFieldLoweringEnabled(
             hasInitializer: hasInitializer,
@@ -2136,6 +2156,13 @@
     if (isExtension) {
       extensionName = currentTypeParameterScopeBuilder.name;
     }
+
+    Reference fieldGetterReference;
+    Reference fieldSetterReference;
+    Reference lateIsSetGetterReference;
+    Reference lateIsSetSetterReference;
+    Reference getterReference;
+    Reference setterReference;
     if (referencesFrom != null) {
       String nameToLookup = SourceFieldBuilder.createFieldName(
           FieldNameType.Field, name,
@@ -2144,80 +2171,58 @@
           isExtensionMethod: isExtension,
           extensionName: extensionName,
           isSynthesized: fieldIsLateWithLowering);
-
-      if (_currentClassReferencesFromIndexed != null) {
-        referenceFrom =
-            _currentClassReferencesFromIndexed.lookupField(nameToLookup);
-        if (fieldIsLateWithLowering) {
-          lateIsSetReferenceFrom = _currentClassReferencesFromIndexed
-              .lookupField(SourceFieldBuilder.createFieldName(
-                  FieldNameType.IsSetField, name,
-                  isInstanceMember: isInstanceMember,
-                  className: className,
-                  isExtensionMethod: isExtension,
-                  extensionName: extensionName,
-                  isSynthesized: fieldIsLateWithLowering));
-          getterReferenceFrom =
-              _currentClassReferencesFromIndexed.lookupProcedureNotSetter(
-                  SourceFieldBuilder.createFieldName(FieldNameType.Getter, name,
-                      isInstanceMember: isInstanceMember,
-                      className: className,
-                      isExtensionMethod: isExtension,
-                      extensionName: extensionName,
-                      isSynthesized: fieldIsLateWithLowering));
-          setterReferenceFrom =
-              _currentClassReferencesFromIndexed.lookupProcedureSetter(
-                  SourceFieldBuilder.createFieldName(FieldNameType.Setter, name,
-                      isInstanceMember: isInstanceMember,
-                      className: className,
-                      isExtensionMethod: isExtension,
-                      extensionName: extensionName,
-                      isSynthesized: fieldIsLateWithLowering));
-        }
-      } else {
-        referenceFrom = referencesFromIndexed.lookupField(nameToLookup);
-        if (fieldIsLateWithLowering) {
-          lateIsSetReferenceFrom = referencesFromIndexed.lookupField(
-              SourceFieldBuilder.createFieldName(FieldNameType.IsSetField, name,
-                  isInstanceMember: isInstanceMember,
-                  className: className,
-                  isExtensionMethod: isExtension,
-                  extensionName: extensionName,
-                  isSynthesized: fieldIsLateWithLowering));
-          getterReferenceFrom = referencesFromIndexed.lookupProcedureNotSetter(
-              SourceFieldBuilder.createFieldName(FieldNameType.Getter, name,
-                  isInstanceMember: isInstanceMember,
-                  className: className,
-                  isExtensionMethod: isExtension,
-                  extensionName: extensionName,
-                  isSynthesized: fieldIsLateWithLowering));
-          setterReferenceFrom = referencesFromIndexed.lookupProcedureSetter(
-              SourceFieldBuilder.createFieldName(FieldNameType.Setter, name,
-                  isInstanceMember: isInstanceMember,
-                  className: className,
-                  isExtensionMethod: isExtension,
-                  extensionName: extensionName,
-                  isSynthesized: fieldIsLateWithLowering));
-        }
+      IndexedContainer indexedContainer =
+          _currentClassReferencesFromIndexed ?? referencesFromIndexed;
+      Name nameToLookupName = new Name(nameToLookup, indexedContainer.library);
+      fieldGetterReference =
+          indexedContainer.lookupGetterReference(nameToLookupName);
+      fieldSetterReference =
+          indexedContainer.lookupSetterReference(nameToLookupName);
+      if (fieldIsLateWithLowering) {
+        String lateIsSetName = SourceFieldBuilder.createFieldName(
+            FieldNameType.IsSetField, name,
+            isInstanceMember: isInstanceMember,
+            className: className,
+            isExtensionMethod: isExtension,
+            extensionName: extensionName,
+            isSynthesized: fieldIsLateWithLowering);
+        Name lateIsSetNameName =
+            new Name(lateIsSetName, indexedContainer.library);
+        lateIsSetGetterReference =
+            indexedContainer.lookupGetterReference(lateIsSetNameName);
+        lateIsSetSetterReference =
+            indexedContainer.lookupSetterReference(lateIsSetNameName);
+        getterReference = indexedContainer.lookupGetterReference(new Name(
+            SourceFieldBuilder.createFieldName(FieldNameType.Getter, name,
+                isInstanceMember: isInstanceMember,
+                className: className,
+                isExtensionMethod: isExtension,
+                extensionName: extensionName,
+                isSynthesized: fieldIsLateWithLowering),
+            indexedContainer.library));
+        setterReference = indexedContainer.lookupSetterReference(new Name(
+            SourceFieldBuilder.createFieldName(FieldNameType.Setter, name,
+                isInstanceMember: isInstanceMember,
+                className: className,
+                isExtensionMethod: isExtension,
+                extensionName: extensionName,
+                isSynthesized: fieldIsLateWithLowering),
+            indexedContainer.library));
       }
     }
-    SourceFieldBuilder fieldBuilder = new SourceFieldBuilder(
-        metadata,
-        type,
-        name,
-        modifiers,
-        isTopLevel,
-        this,
-        charOffset,
-        charEndOffset,
-        referenceFrom,
-        lateIsSetReferenceFrom,
-        getterReferenceFrom,
-        setterReferenceFrom);
+
+    SourceFieldBuilder fieldBuilder = new SourceFieldBuilder(metadata, type,
+        name, modifiers, isTopLevel, this, charOffset, charEndOffset,
+        fieldGetterReference: fieldGetterReference,
+        fieldSetterReference: fieldSetterReference,
+        lateIsSetGetterReference: lateIsSetGetterReference,
+        lateIsSetSetterReference: lateIsSetSetterReference,
+        getterReference: getterReference,
+        setterReference: setterReference);
     fieldBuilder.constInitializerToken = constInitializerToken;
     addBuilder(name, fieldBuilder, charOffset,
-        getterReference: referenceFrom?.getterReference,
-        setterReference: referenceFrom?.setterReference);
+        getterReference: fieldGetterReference,
+        setterReference: fieldSetterReference);
     if (type == null && fieldBuilder.next == null) {
       // Only the first one (the last one in the linked list of next pointers)
       // are added to the tree, had parent pointers and can infer correctly.
@@ -2253,10 +2258,11 @@
       String nativeMethodName,
       {Token beginInitializers}) {
     MetadataCollector metadataCollector = loader.target.metadataCollector;
-    Constructor referenceFrom;
+    Member referenceFrom;
     if (_currentClassReferencesFromIndexed != null) {
-      referenceFrom =
-          _currentClassReferencesFromIndexed.lookupConstructor(constructorName);
+      referenceFrom = _currentClassReferencesFromIndexed.lookupConstructor(
+          new Name(
+              constructorName, _currentClassReferencesFromIndexed.library));
     }
     ConstructorBuilder constructorBuilder = new ConstructorBuilderImpl(
         metadata,
@@ -2320,16 +2326,18 @@
         returnType = addVoidType(charOffset);
       }
     }
-    Procedure referenceFrom;
-    Procedure tearOffReferenceFrom;
+    Reference procedureReference;
+    Reference tearOffReference;
     if (referencesFrom != null) {
       if (_currentClassReferencesFromIndexed != null) {
         if (kind == ProcedureKind.Setter) {
-          referenceFrom =
-              _currentClassReferencesFromIndexed.lookupProcedureSetter(name);
+          procedureReference =
+              _currentClassReferencesFromIndexed.lookupSetterReference(
+                  new Name(name, _currentClassReferencesFromIndexed.library));
         } else {
-          referenceFrom =
-              _currentClassReferencesFromIndexed.lookupProcedureNotSetter(name);
+          procedureReference =
+              _currentClassReferencesFromIndexed.lookupGetterReference(
+                  new Name(name, _currentClassReferencesFromIndexed.library));
         }
       } else {
         if (currentTypeParameterScopeBuilder.kind ==
@@ -2342,11 +2350,11 @@
               currentTypeParameterScopeBuilder.name,
               name);
           if (extensionIsStatic && kind == ProcedureKind.Setter) {
-            referenceFrom =
-                referencesFromIndexed.lookupProcedureSetter(nameToLookup);
+            procedureReference = referencesFromIndexed.lookupSetterReference(
+                new Name(nameToLookup, referencesFromIndexed.library));
           } else {
-            referenceFrom =
-                referencesFromIndexed.lookupProcedureNotSetter(nameToLookup);
+            procedureReference = referencesFromIndexed.lookupGetterReference(
+                new Name(nameToLookup, referencesFromIndexed.library));
           }
           if (kind == ProcedureKind.Method) {
             String tearOffNameToLookup =
@@ -2356,15 +2364,16 @@
                     ProcedureKind.Getter,
                     currentTypeParameterScopeBuilder.name,
                     name);
-            tearOffReferenceFrom = referencesFromIndexed
-                .lookupProcedureNotSetter(tearOffNameToLookup);
+            tearOffReference = referencesFromIndexed.lookupGetterReference(
+                new Name(tearOffNameToLookup, referencesFromIndexed.library));
           }
         } else {
           if (kind == ProcedureKind.Setter) {
-            referenceFrom = referencesFromIndexed.lookupProcedureSetter(name);
+            procedureReference = referencesFromIndexed.lookupSetterReference(
+                new Name(name, referencesFromIndexed.library));
           } else {
-            referenceFrom =
-                referencesFromIndexed.lookupProcedureNotSetter(name);
+            procedureReference = referencesFromIndexed.lookupGetterReference(
+                new Name(name, referencesFromIndexed.library));
           }
         }
       }
@@ -2382,8 +2391,8 @@
         charOffset,
         charOpenParenOffset,
         charEndOffset,
-        referenceFrom,
-        tearOffReferenceFrom,
+        procedureReference,
+        tearOffReference,
         asyncModifier,
         isExtensionInstanceMember,
         nativeMethodName);
@@ -2391,7 +2400,7 @@
         procedureBuilder.procedure, documentationComment);
     checkTypeVariables(typeVariables, procedureBuilder);
     addBuilder(name, procedureBuilder, charOffset,
-        getterReference: referenceFrom?.reference);
+        getterReference: procedureReference);
     if (nativeMethodName != null) {
       addNativeMethod(procedureBuilder);
     }
@@ -2429,8 +2438,10 @@
       procedureName = name;
     }
 
-    Procedure referenceFrom = _currentClassReferencesFromIndexed
-        ?.lookupProcedureNotSetter(procedureName);
+    Reference reference = _currentClassReferencesFromIndexed
+        ?.lookupConstructor(
+            new Name(procedureName, _currentClassReferencesFromIndexed.library))
+        ?.reference;
 
     ProcedureBuilder procedureBuilder;
     if (redirectionTarget != null) {
@@ -2449,7 +2460,7 @@
           charOffset,
           charOpenParenOffset,
           charEndOffset,
-          referenceFrom,
+          reference,
           nativeMethodName,
           redirectionTarget);
     } else {
@@ -2469,7 +2480,7 @@
           charOffset,
           charOpenParenOffset,
           charEndOffset,
-          referenceFrom,
+          reference,
           null,
           asyncModifier,
           /* isExtensionInstanceMember = */ false,
@@ -2494,7 +2505,7 @@
 
     factoryDeclaration.resolveTypes(procedureBuilder.typeVariables, this);
     addBuilder(procedureName, procedureBuilder, charOffset,
-        getterReference: referenceFrom?.reference);
+        getterReference: reference);
     if (nativeMethodName != null) {
       addNativeMethod(procedureBuilder);
     }
@@ -2733,8 +2744,10 @@
       }
     }
 
-    for (SourceLibraryBuilder part in parts) {
-      part.addDependencies(library, seen);
+    for (LibraryBuilder part in parts) {
+      if (part is SourceLibraryBuilder) {
+        part.addDependencies(library, seen);
+      }
     }
   }
 
@@ -3226,7 +3239,7 @@
           inferredTypes.contains(argument);
       offset =
           typeArgumentsInfo?.getOffsetForIndex(issue.index, offset) ?? offset;
-      if (argument is FunctionType && argument.typeParameters.length > 0) {
+      if (isGenericFunctionTypeOrAlias(argument)) {
         if (issueInferred) {
           message = templateGenericFunctionTypeInferredAsActualTypeArgument
               .withArguments(argument, isNonNullableByDefault);
@@ -3277,20 +3290,30 @@
         }
       }
 
-      reportTypeArgumentIssue(message, fileUri, offset, typeParameter);
+      reportTypeArgumentIssue(message, fileUri, offset,
+          typeParameter: typeParameter,
+          superBoundedAttempt: issue.enclosingType,
+          superBoundedAttemptInverted: issue.invertedType);
     }
   }
 
   void reportTypeArgumentIssue(Message message, Uri fileUri, int fileOffset,
-      TypeParameter typeParameter) {
+      {TypeParameter typeParameter,
+      DartType superBoundedAttempt,
+      DartType superBoundedAttemptInverted}) {
     List<LocatedMessage> context;
     if (typeParameter != null && typeParameter.fileOffset != -1) {
       // It looks like when parameters come from patch files, they don't
       // have a reportable location.
-      context = <LocatedMessage>[
-        messageIncorrectTypeArgumentVariable.withLocation(
-            typeParameter.location.file, typeParameter.fileOffset, noLength)
-      ];
+      (context ??= <LocatedMessage>[]).add(
+          messageIncorrectTypeArgumentVariable.withLocation(
+              typeParameter.location.file, typeParameter.fileOffset, noLength));
+    }
+    if (superBoundedAttemptInverted != null && superBoundedAttempt != null) {
+      (context ??= <LocatedMessage>[]).add(templateSuperBoundedHint
+          .withArguments(superBoundedAttempt, superBoundedAttemptInverted,
+              isNonNullableByDefault)
+          .withLocation(fileUri, fileOffset, noLength));
     }
     addProblem(message, fileOffset, noLength, fileUri, context: context);
   }
@@ -3349,27 +3372,16 @@
 
   void checkBoundsInTypeParameters(TypeEnvironment typeEnvironment,
       List<TypeParameter> typeParameters, Uri fileUri) {
-    final DartType bottomType = library.isNonNullableByDefault
-        ? const NeverType(Nullability.nonNullable)
-        : const NullType();
-
     // Check in bounds of own type variables.
     for (TypeParameter parameter in typeParameters) {
-      Set<TypeArgumentIssue> issues = {};
-      issues.addAll(findTypeArgumentIssues(
-              library,
-              parameter.bound,
-              typeEnvironment,
-              SubtypeCheckMode.ignoringNullabilities,
-              bottomType,
-              allowSuperBounded: true) ??
-          const []);
-      if (library.isNonNullableByDefault) {
-        issues.addAll(findTypeArgumentIssues(library, parameter.bound,
-                typeEnvironment, SubtypeCheckMode.withNullabilities, bottomType,
-                allowSuperBounded: true) ??
-            const []);
-      }
+      List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+          library,
+          parameter.bound,
+          typeEnvironment,
+          isNonNullableByDefault
+              ? SubtypeCheckMode.withNullabilities
+              : SubtypeCheckMode.ignoringNullabilities,
+          allowSuperBounded: true);
       for (TypeArgumentIssue issue in issues) {
         DartType argument = issue.argument;
         TypeParameter typeParameter = issue.typeParameter;
@@ -3382,12 +3394,12 @@
           continue;
         }
 
-        if (argument is FunctionType && argument.typeParameters.length > 0) {
+        if (isGenericFunctionTypeOrAlias(argument)) {
           reportTypeArgumentIssue(
               messageGenericFunctionTypeUsedAsActualTypeArgument,
               fileUri,
               parameter.fileOffset,
-              null);
+              typeParameter: null);
         } else {
           reportTypeArgumentIssue(
               templateIncorrectTypeArgument.withArguments(
@@ -3398,7 +3410,9 @@
                   library.isNonNullableByDefault),
               fileUri,
               parameter.fileOffset,
-              typeParameter);
+              typeParameter: typeParameter,
+              superBoundedAttempt: issue.enclosingType,
+              superBoundedAttemptInverted: issue.invertedType);
         }
       }
     }
@@ -3410,7 +3424,8 @@
       List<VariableDeclaration> positionalParameters,
       List<VariableDeclaration> namedParameters,
       DartType returnType,
-      int requiredParameterCount}) {
+      int requiredParameterCount,
+      bool skipReturnType = false}) {
     if (typeParameters != null) {
       for (TypeParameter parameter in typeParameters) {
         checkBoundsInType(
@@ -3434,21 +3449,15 @@
             allowSuperBounded: true);
       }
     }
-    if (returnType != null) {
-      final DartType bottomType = isNonNullableByDefault
-          ? const NeverType(Nullability.nonNullable)
-          : const NullType();
-      Set<TypeArgumentIssue> issues = {};
-      issues.addAll(findTypeArgumentIssues(library, returnType, typeEnvironment,
-              SubtypeCheckMode.ignoringNullabilities, bottomType,
-              allowSuperBounded: true) ??
-          const []);
-      if (isNonNullableByDefault) {
-        issues.addAll(findTypeArgumentIssues(library, returnType,
-                typeEnvironment, SubtypeCheckMode.withNullabilities, bottomType,
-                allowSuperBounded: true) ??
-            const []);
-      }
+    if (!skipReturnType && returnType != null) {
+      List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+          library,
+          returnType,
+          typeEnvironment,
+          isNonNullableByDefault
+              ? SubtypeCheckMode.withNullabilities
+              : SubtypeCheckMode.ignoringNullabilities,
+          allowSuperBounded: true);
       for (TypeArgumentIssue issue in issues) {
         DartType argument = issue.argument;
         TypeParameter typeParameter = issue.typeParameter;
@@ -3456,12 +3465,12 @@
         // We don't need to check if [argument] was inferred or specified
         // here, because inference in return types boils down to instantiate-
         // -to-bound, and it can't provide a type that violates the bound.
-        if (argument is FunctionType && argument.typeParameters.length > 0) {
+        if (isGenericFunctionTypeOrAlias(argument)) {
           reportTypeArgumentIssue(
               messageGenericFunctionTypeUsedAsActualTypeArgument,
               fileUri,
               fileOffset,
-              null);
+              typeParameter: null);
         } else {
           reportTypeArgumentIssue(
               templateIncorrectTypeArgumentInReturnType.withArguments(
@@ -3472,7 +3481,9 @@
                   isNonNullableByDefault),
               fileUri,
               fileOffset,
-              typeParameter);
+              typeParameter: typeParameter,
+              superBoundedAttempt: issue.enclosingType,
+              superBoundedAttemptInverted: issue.invertedType);
         }
       }
     }
@@ -3507,14 +3518,16 @@
   }
 
   void checkBoundsInFunctionNode(
-      FunctionNode function, TypeEnvironment typeEnvironment, Uri fileUri) {
+      FunctionNode function, TypeEnvironment typeEnvironment, Uri fileUri,
+      {bool skipReturnType = false}) {
     checkBoundsInFunctionNodeParts(
         typeEnvironment, fileUri, function.fileOffset,
         typeParameters: function.typeParameters,
         positionalParameters: function.positionalParameters,
         namedParameters: function.namedParameters,
         returnType: function.returnType,
-        requiredParameterCount: function.requiredParameterCount);
+        requiredParameterCount: function.requiredParameterCount,
+        skipReturnType: skipReturnType);
   }
 
   void checkBoundsInListLiteral(
@@ -3545,20 +3558,14 @@
   void checkBoundsInType(
       DartType type, TypeEnvironment typeEnvironment, Uri fileUri, int offset,
       {bool inferred, bool allowSuperBounded = true}) {
-    final DartType bottomType = isNonNullableByDefault
-        ? const NeverType(Nullability.nonNullable)
-        : const NullType();
-    Set<TypeArgumentIssue> issues = {};
-    issues.addAll(findTypeArgumentIssues(library, type, typeEnvironment,
-            SubtypeCheckMode.ignoringNullabilities, bottomType,
-            allowSuperBounded: allowSuperBounded) ??
-        const []);
-    if (isNonNullableByDefault) {
-      issues.addAll(findTypeArgumentIssues(library, type, typeEnvironment,
-              SubtypeCheckMode.withNullabilities, bottomType,
-              allowSuperBounded: allowSuperBounded) ??
-          const []);
-    }
+    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
+        library,
+        type,
+        typeEnvironment,
+        isNonNullableByDefault
+            ? SubtypeCheckMode.withNullabilities
+            : SubtypeCheckMode.ignoringNullabilities,
+        allowSuperBounded: allowSuperBounded);
     reportTypeArgumentIssues(issues, fileUri, offset, inferred: inferred);
   }
 
@@ -3615,25 +3622,15 @@
     final DartType bottomType = isNonNullableByDefault
         ? const NeverType(Nullability.nonNullable)
         : const NullType();
-    Set<TypeArgumentIssue> issues = {};
-    issues.addAll(findTypeArgumentIssuesForInvocation(
-            library,
-            parameters,
-            arguments,
-            typeEnvironment,
-            SubtypeCheckMode.ignoringNullabilities,
-            bottomType) ??
-        const []);
-    if (isNonNullableByDefault) {
-      issues.addAll(findTypeArgumentIssuesForInvocation(
-              library,
-              parameters,
-              arguments,
-              typeEnvironment,
-              SubtypeCheckMode.withNullabilities,
-              bottomType) ??
-          const []);
-    }
+    List<TypeArgumentIssue> issues = findTypeArgumentIssuesForInvocation(
+        library,
+        parameters,
+        arguments,
+        typeEnvironment,
+        isNonNullableByDefault
+            ? SubtypeCheckMode.withNullabilities
+            : SubtypeCheckMode.ignoringNullabilities,
+        bottomType);
     if (issues.isNotEmpty) {
       DartType targetReceiver;
       if (klass != null) {
@@ -3702,25 +3699,15 @@
     final DartType bottomType = isNonNullableByDefault
         ? const NeverType(Nullability.nonNullable)
         : const NullType();
-    Set<TypeArgumentIssue> issues = {};
-    issues.addAll(findTypeArgumentIssuesForInvocation(
-            library,
-            instantiatedMethodParameters,
-            arguments.types,
-            typeEnvironment,
-            SubtypeCheckMode.ignoringNullabilities,
-            bottomType) ??
-        const []);
-    if (isNonNullableByDefault) {
-      issues.addAll(findTypeArgumentIssuesForInvocation(
-              library,
-              instantiatedMethodParameters,
-              arguments.types,
-              typeEnvironment,
-              SubtypeCheckMode.withNullabilities,
-              bottomType) ??
-          const []);
-    }
+    List<TypeArgumentIssue> issues = findTypeArgumentIssuesForInvocation(
+        library,
+        instantiatedMethodParameters,
+        arguments.types,
+        typeEnvironment,
+        isNonNullableByDefault
+            ? SubtypeCheckMode.withNullabilities
+            : SubtypeCheckMode.ignoringNullabilities,
+        bottomType);
     reportTypeArgumentIssues(issues, fileUri, offset,
         typeArgumentsInfo: getTypeArgumentsInfo(arguments),
         targetReceiver: receiverType,
@@ -3797,15 +3784,6 @@
           referencesFromIndexed.lookupIndexedClass(name);
     }
   }
-
-  Procedure lookupLibraryReferenceProcedure(String name, bool setter) {
-    if (referencesFrom == null) return null;
-    if (setter) {
-      return referencesFromIndexed.lookupProcedureSetter(name);
-    } else {
-      return referencesFromIndexed.lookupProcedureNotSetter(name);
-    }
-  }
 }
 
 // The kind of type parameter scope built by a [TypeParameterScopeBuilder]
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 54420e8..bfcc018 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.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.9
+
 library fasta.source_loader;
 
 import 'dart:convert' show utf8;
@@ -216,6 +218,7 @@
             -1,
             library.importUri);
       } else if (uri.scheme == SourceLibraryBuilder.MALFORMED_URI_SCHEME) {
+        library.addProblemAtAccessors(messageExpectedUri);
         bytes = synthesizeSourceForMissingFile(library.importUri, null);
       }
       if (bytes != null) {
@@ -456,7 +459,7 @@
       DietListener listener = createDietListener(library);
       DietParser parser = new DietParser(listener);
       parser.parseUnit(tokens);
-      for (SourceLibraryBuilder part in library.parts) {
+      for (LibraryBuilder part in library.parts) {
         if (part.partOfLibrary != library) {
           // Part was included in multiple libraries. Skip it here.
           continue;
@@ -1463,10 +1466,18 @@
 }
 
 class _GrowableList<E> {
-  factory _GrowableList() => null;
+  factory _GrowableList(int length) => null;
   factory _GrowableList.empty() => null;
   factory _GrowableList.filled() => null;
   factory _GrowableList.generate(int length, E generator(int index)) => null;
+  factory _GrowableList._literal1(E e0) => null;
+  factory _GrowableList._literal2(E e0, E e1) => null;
+  factory _GrowableList._literal3(E e0, E e1, E e2) => null;
+  factory _GrowableList._literal4(E e0, E e1, E e2, E e3) => null;
+  factory _GrowableList._literal5(E e0, E e1, E e2, E e3, E e4) => null;
+  factory _GrowableList._literal6(E e0, E e1, E e2, E e3, E e4, E e5) => null;
+  factory _GrowableList._literal7(E e0, E e1, E e2, E e3, E e4, E e5, E e6) => null;
+  factory _GrowableList._literal8(E e0, E e1, E e2, E e3, E e4, E e5, E e6, E e7) => null;
 }
 
 class _List<E> {
@@ -1520,7 +1531,7 @@
   factory Set() = Set<E>._fake;
   external factory Set._fake();
   external factory Set.of();
-  void add(E element) {}
+  bool add(E element) {}
   void addAll(Iterable<E> iterable) {}
 }
 
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 4061bce..dc61bf9 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
@@ -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.9
+
 library fasta.source_type_alias_builder;
 
 import 'package:kernel/ast.dart'
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
index f3af4a5..83721d7 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener_impl.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener_impl.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.9
+
 library fasta.stack_listener_impl;
 
 import 'package:_fe_analyzer_shared/src/messages/codes.dart' show Message;
@@ -77,7 +79,7 @@
   }
 
   /// Used to report an internal error encountered in the stack listener.
-  dynamic internalProblem(Message message, int charOffset, Uri uri) {
+  internalProblem(Message message, int charOffset, Uri uri) {
     return problems.internalProblem(message, charOffset, uri);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/source/value_kinds.dart b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
index e533e56..3fc36cc 100644
--- a/pkg/front_end/lib/src/fasta/source/value_kinds.dart
+++ b/pkg/front_end/lib/src/fasta/source/value_kinds.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.9
+
 import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
     show NullValue;
 
diff --git a/pkg/front_end/lib/src/fasta/target.dart b/pkg/front_end/lib/src/fasta/target.dart
index 8d2efd9..82ecb31 100644
--- a/pkg/front_end/lib/src/fasta/target.dart
+++ b/pkg/front_end/lib/src/fasta/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.9
+
 library fasta.target;
 
 import 'package:kernel/ast.dart' show Component;
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 264ad8e..8acd6b8 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.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.9
+
 library fasta.target_implementation;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
@@ -22,8 +24,6 @@
 
 import 'messages.dart' show FormattedMessage, LocatedMessage, Message;
 
-import 'rewrite_severity.dart' show rewriteSeverity;
-
 import 'target.dart' show Target;
 
 import 'ticker.dart' show Ticker;
@@ -190,11 +190,6 @@
         involvedFiles: involvedFiles);
   }
 
-  Severity fixSeverity(Severity severity, Message message, Uri fileUri) {
-    severity ??= message.code.severity;
-    return rewriteSeverity(severity, message.code, fileUri);
-  }
-
   String get currentSdkVersionString {
     return CompilerContext.current.options.currentSdkVersion;
   }
diff --git a/pkg/front_end/lib/src/fasta/ticker.dart b/pkg/front_end/lib/src/fasta/ticker.dart
index b785cba..3c9d9c5 100644
--- a/pkg/front_end/lib/src/fasta/ticker.dart
+++ b/pkg/front_end/lib/src/fasta/ticker.dart
@@ -9,7 +9,7 @@
 
   bool isVerbose;
 
-  Duration previousTick;
+  late Duration previousTick;
 
   Ticker({this.isVerbose: true}) {
     previousTick = sw.elapsed;
diff --git a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
index 4de8315..4029c5c 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/closure_context.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.md file.
 
+// @dart = 2.9
+
 part of 'type_inferrer.dart';
 
 /// Keeps track of information about the innermost function or closure being
@@ -544,30 +546,75 @@
               statement.expression.fileOffset,
               noLength)
             ..parent = statement;
-        } else if (flattenedExpressionType is! VoidType &&
-            !inferrer.typeSchemaEnvironment
-                .performNullabilityAwareSubtypeCheck(
-                    flattenedExpressionType, futureValueType)
-                .isSubtypeWhenUsingNullabilities()) {
-          // It is a compile-time error if s is `return e;`, flatten(S) is not
-          // void, S is not assignable to T_v, and flatten(S) is not a subtype
-          // of T_v.
-          statement.expression = inferrer.ensureAssignable(
-              futureValueType, expressionType, statement.expression,
-              fileOffset: statement.expression.fileOffset,
-              runtimeCheckedType:
-                  inferrer.computeGreatestClosure2(_returnContext),
-              declaredContextType: returnType,
-              isVoidAllowed: false,
-              errorTemplate: templateInvalidReturnAsync,
-              nullabilityErrorTemplate: templateInvalidReturnAsyncNullability,
-              nullabilityPartErrorTemplate:
-                  templateInvalidReturnAsyncPartNullability,
-              nullabilityNullErrorTemplate:
-                  templateInvalidReturnAsyncNullabilityNull,
-              nullabilityNullTypeErrorTemplate:
-                  templateInvalidReturnAsyncNullabilityNullType)
-            ..parent = statement;
+        } else {
+          DartType futureOrType =
+              inferrer.computeGreatestClosure2(_returnContext);
+          if (flattenedExpressionType is! VoidType &&
+              !inferrer.typeSchemaEnvironment
+                  .performNullabilityAwareSubtypeCheck(
+                      flattenedExpressionType, futureValueType)
+                  .isSubtypeWhenUsingNullabilities()) {
+            // It is a compile-time error if s is `return e;`, flatten(S) is not
+            // void, S is not assignable to T_v, and flatten(S) is not a subtype
+            // of T_v.
+            statement.expression = inferrer.ensureAssignable(
+                futureValueType, expressionType, statement.expression,
+                fileOffset: statement.expression.fileOffset,
+                runtimeCheckedType: futureOrType,
+                declaredContextType: returnType,
+                isVoidAllowed: false,
+                errorTemplate: templateInvalidReturnAsync,
+                nullabilityErrorTemplate: templateInvalidReturnAsyncNullability,
+                nullabilityPartErrorTemplate:
+                    templateInvalidReturnAsyncPartNullability,
+                nullabilityNullErrorTemplate:
+                    templateInvalidReturnAsyncNullabilityNull,
+                nullabilityNullTypeErrorTemplate:
+                    templateInvalidReturnAsyncNullabilityNullType)
+              ..parent = statement;
+          }
+          // For `return e`:
+          // When `f` is an asynchronous non-generator with future value type
+          // T_v, evaluation proceeds as follows:
+          //
+          //    The expression `e` is evaluated to an object `o`.
+          //      If the run-time type of `o` is a subtype of `Future<T_v>`,
+          //         let `v` be a fresh variable bound to `o` and
+          //         evaluate `await v` to an object `r`;
+          //         otherwise let `r` be `o`.
+          //    A dynamic error occurs unless the dynamic type of `r`
+          //      is a subtype of the actual value of T_v.
+          //    Then the return statement `s` completes returning `r`.
+          DartType futureType = new InterfaceType(
+              inferrer.coreTypes.futureClass,
+              Nullability.nonNullable,
+              [futureValueType]);
+          VariableDeclaration variable;
+          Expression isOperand;
+          Expression awaitOperand;
+          Expression resultExpression;
+          if (isPureExpression(statement.expression)) {
+            isOperand = clonePureExpression(statement.expression);
+            awaitOperand = clonePureExpression(statement.expression);
+            resultExpression = statement.expression;
+          } else {
+            variable = createVariable(statement.expression, expressionType);
+            isOperand = createVariableGet(variable);
+            awaitOperand = createVariableGet(variable);
+            resultExpression = createVariableGet(variable);
+          }
+          Expression replacement = new ConditionalExpression(
+              new IsExpression(isOperand, futureType)
+                ..fileOffset = statement.fileOffset,
+              new AwaitExpression(awaitOperand)
+                ..fileOffset = statement.fileOffset,
+              resultExpression,
+              futureOrType)
+            ..fileOffset = statement.fileOffset;
+          if (variable != null) {
+            replacement = createLet(variable, replacement);
+          }
+          statement.expression = replacement..parent = statement;
         }
       }
     } else {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart b/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart
index 8710222..1083882 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/factor_type.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/factor_type.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.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/type_environment.dart';
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
index 9219313..4039519 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.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.9
+
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
index 4d04ad4..43b4e0e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart' show DartType, Library, NeverType, Nullability;
 
 import 'package:kernel/src/standard_bounds.dart';
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
index 4b5d0f8..fd6c2f6e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 
 import 'package:kernel/core_types.dart';
@@ -374,7 +376,8 @@
     //
     // Under constraint _ <: X <: Q.
     if (p is TypeParameterType &&
-        isTypeParameterTypeWithoutNullabilityMarker(p, _currentLibrary) &&
+        isTypeParameterTypeWithoutNullabilityMarker(p,
+            isNonNullableByDefault: _currentLibrary.isNonNullableByDefault) &&
         _parametersToConstrain.contains(p.parameter)) {
       _constrainParameterUpper(p.parameter, q);
       return true;
@@ -384,7 +387,8 @@
     //
     // Under constraint P <: X <: _.
     if (q is TypeParameterType &&
-        isTypeParameterTypeWithoutNullabilityMarker(q, _currentLibrary) &&
+        isTypeParameterTypeWithoutNullabilityMarker(q,
+            isNonNullableByDefault: _currentLibrary.isNonNullableByDefault) &&
         _parametersToConstrain.contains(q.parameter)) {
       _constrainParameterLower(q.parameter, p);
       return true;
@@ -403,9 +407,12 @@
     // If P is a legacy type P0* then the match holds under constraint set C:
     //
     // Only if P0 is a subtype match for Q under constraint set C.
-    if (isLegacyTypeConstructorApplication(p, _currentLibrary)) {
+    if (isLegacyTypeConstructorApplication(p,
+        isNonNullableByDefault: _currentLibrary.isNonNullableByDefault)) {
       return _isNullabilityAwareSubtypeMatch(
-          computeTypeWithoutNullabilityMarker(p, _currentLibrary), q,
+          computeTypeWithoutNullabilityMarker(p,
+              isNonNullableByDefault: _currentLibrary.isNonNullableByDefault),
+          q,
           constrainSupertype: constrainSupertype);
     }
 
@@ -415,12 +422,16 @@
     // set C.
     // Or if P is not dynamic or void and P is a subtype match for Q0? under
     // constraint set C.
-    if (isLegacyTypeConstructorApplication(q, _currentLibrary)) {
+    if (isLegacyTypeConstructorApplication(q,
+        isNonNullableByDefault: _currentLibrary.isNonNullableByDefault)) {
       final int baseConstraintCount = _protoConstraints.length;
 
       if ((p is DynamicType || p is VoidType) &&
           _isNullabilityAwareSubtypeMatch(
-              p, computeTypeWithoutNullabilityMarker(q, _currentLibrary),
+              p,
+              computeTypeWithoutNullabilityMarker(q,
+                  isNonNullableByDefault:
+                      _currentLibrary.isNonNullableByDefault),
               constrainSupertype: constrainSupertype)) {
         return true;
       }
@@ -485,10 +496,10 @@
     // Or if P is a subtype match for Q0 under empty constraint set C.
     if (isNullableTypeConstructorApplication(q)) {
       final int baseConstraintCount = _protoConstraints.length;
-      final DartType rawP =
-          computeTypeWithoutNullabilityMarker(p, _currentLibrary);
-      final DartType rawQ =
-          computeTypeWithoutNullabilityMarker(q, _currentLibrary);
+      final DartType rawP = computeTypeWithoutNullabilityMarker(p,
+          isNonNullableByDefault: _currentLibrary.isNonNullableByDefault);
+      final DartType rawQ = computeTypeWithoutNullabilityMarker(q,
+          isNonNullableByDefault: _currentLibrary.isNonNullableByDefault);
 
       if (isNullableTypeConstructorApplication(p) &&
           _isNullabilityAwareSubtypeMatch(rawP, rawQ,
@@ -549,7 +560,10 @@
     if (isNullableTypeConstructorApplication(p)) {
       final int baseConstraintCount = _protoConstraints.length;
       if (_isNullabilityAwareSubtypeMatch(
-              computeTypeWithoutNullabilityMarker(p, _currentLibrary), q,
+              computeTypeWithoutNullabilityMarker(p,
+                  isNonNullableByDefault:
+                      _currentLibrary.isNonNullableByDefault),
+              q,
               constrainSupertype: constrainSupertype) &&
           _isNullabilityAwareSubtypeMatch(const NullType(), q,
               constrainSupertype: constrainSupertype)) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
index 85bbacd..25d68b1 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_demotion.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/src/replacement_visitor.dart';
 
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 1a58eb6..9d674c0 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
@@ -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.md file.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 import 'package:front_end/src/fasta/kernel/internal_ast.dart';
 
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 addccd7..4dd7287 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
@@ -2,16 +2,20 @@
 // 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:core' hide MapEntry;
 
-import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart'
+    hide Reference; // Work around https://github.com/dart-lang/sdk/issues/44667
 
 import 'package:_fe_analyzer_shared/src/util/link.dart';
 
 import 'package:front_end/src/fasta/kernel/internal_ast.dart';
 import 'package:front_end/src/fasta/type_inference/type_demotion.dart';
 
-import 'package:kernel/ast.dart';
+import 'package:kernel/ast.dart'
+    hide Reference; // Work around https://github.com/dart-lang/sdk/issues/44667
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/type_algebra.dart';
@@ -238,6 +242,9 @@
 
   NnbdMode get nnbdMode => library.loader.nnbdMode;
 
+  bool get useNewMethodInvocationEncoding =>
+      library.loader.target.backendTarget.supportsNewMethodInvocationEncoding;
+
   DartType get bottomType => isNonNullableByDefault
       ? const NeverType(Nullability.nonNullable)
       : const NullType();
@@ -622,6 +629,9 @@
             fileOffset, helper.uri);
     }
 
+    if (!identical(result, expression)) {
+      flowAnalysis?.forwardExpression(result, expression);
+    }
     return result;
   }
 
@@ -677,9 +687,20 @@
     VariableDeclaration t =
         new VariableDeclaration.forValue(expression, type: expressionType)
           ..fileOffset = fileOffset;
-    Expression nullCheck = new MethodInvocation(new VariableGet(t), equalsName,
-        new Arguments(<Expression>[new NullLiteral()..fileOffset = fileOffset]))
-      ..fileOffset = fileOffset;
+    Expression nullCheck;
+    // TODO(johnniwinther): Avoid null-check for non-nullable expressions.
+    if (useNewMethodInvocationEncoding) {
+      nullCheck = new EqualsNull(new VariableGet(t)..fileOffset = fileOffset,
+          isNot: false)
+        ..fileOffset = fileOffset;
+    } else {
+      nullCheck = new MethodInvocation(
+          new VariableGet(t)..fileOffset = fileOffset,
+          equalsName,
+          new Arguments(
+              <Expression>[new NullLiteral()..fileOffset = fileOffset]))
+        ..fileOffset = fileOffset;
+    }
     PropertyGet tearOff =
         new PropertyGet(new VariableGet(t), callName, callMember)
           ..fileOffset = fileOffset;
@@ -989,10 +1010,9 @@
       Member member =
           _getInterfaceMember(coreTypes.objectClass, name, setter, fileOffset);
       if (member != null) {
-        return new ObjectAccessTarget.interfaceMember(member,
-            // Null implements all Object members so this is not considered a
-            // potentially nullable access.
-            isPotentiallyNullable: false);
+        // Null implements all Object members so this is not considered a
+        // potentially nullable access.
+        return new ObjectAccessTarget.objectMember(member);
       }
       if (includeExtensionMethods && receiverBound is! DynamicType) {
         ObjectAccessTarget target = _findExtensionMember(
@@ -1051,7 +1071,7 @@
     }
     if (instrumented &&
         receiverBound != const DynamicType() &&
-        target.isInstanceMember) {
+        (target.isInstanceMember || target.isObjectMember)) {
       instrumentation?.record(uriForInstrumentation, fileOffset, 'target',
           new InstrumentationValueForMember(target.member));
     }
@@ -1112,6 +1132,39 @@
     return null;
   }
 
+  /// Returns [type] as passed from [superClass] to the current class.
+  ///
+  /// If a legacy class occurs between the current class and [superClass] then
+  /// [type] needs to be legacy erased. For instance
+  ///
+  ///    // Opt in:
+  ///    class Super {
+  ///      int extendedMethod(int i, {required int j}) => i;
+  ///    }
+  ///    class Mixin {
+  ///      int mixedInMethod(int i, {required int j}) => i;
+  ///    }
+  ///    // Opt out:
+  ///    class Legacy extends Super with Mixin {}
+  ///    // Opt in:
+  ///    class Class extends Legacy {
+  ///      test() {
+  ///        // Ok to call `Legacy.extendedMethod` since its type is
+  ///        // `int* Function(int*, {int* j})`.
+  ///        super.extendedMethod(null);
+  ///        // Ok to call `Legacy.mixedInMethod` since its type is
+  ///        // `int* Function(int*, {int* j})`.
+  ///        super.mixedInMethod(null);
+  ///      }
+  ///    }
+  ///
+  DartType computeTypeFromSuperClass(Class superClass, DartType type) {
+    if (needsLegacyErasure(thisType.classNode, superClass)) {
+      type = legacyErasure(type);
+    }
+    return type;
+  }
+
   /// Returns the type of [target] when accessed as a getter on [receiverType].
   ///
   /// For instance
@@ -1139,6 +1192,7 @@
       case ObjectAccessTargetKind.never:
         return const NeverType(Nullability.nonNullable);
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         return getGetterTypeForMemberTarget(target.member, receiverType);
       case ObjectAccessTargetKind.extensionMember:
@@ -1154,7 +1208,7 @@
                 .toList();
             Substitution substitution = Substitution.fromPairs(
                 extensionTypeParameters, target.inferredExtensionTypeArguments);
-            return substitution.substituteType(new FunctionType(
+            DartType resultType = substitution.substituteType(new FunctionType(
                 functionType.positionalParameters.skip(1).toList(),
                 functionType.returnType,
                 library.nonNullable,
@@ -1164,6 +1218,10 @@
                     .toList(),
                 requiredParameterCount:
                     functionType.requiredParameterCount - 1));
+            if (!isNonNullableByDefault) {
+              resultType = legacyErasure(resultType);
+            }
+            return resultType;
           case ProcedureKind.Getter:
             FunctionType functionType =
                 target.member.function.computeFunctionType(library.nonNullable);
@@ -1173,7 +1231,12 @@
                 .toList();
             Substitution substitution = Substitution.fromPairs(
                 extensionTypeParameters, target.inferredExtensionTypeArguments);
-            return substitution.substituteType(functionType.returnType);
+            DartType resultType =
+                substitution.substituteType(functionType.returnType);
+            if (!isNonNullableByDefault) {
+              resultType = legacyErasure(resultType);
+            }
+            return resultType;
           case ProcedureKind.Setter:
           case ProcedureKind.Factory:
             break;
@@ -1212,6 +1275,9 @@
             .substituteType(calleeType);
       }
     }
+    if (!isNonNullableByDefault) {
+      calleeType = legacyErasure(calleeType);
+    }
     return calleeType;
   }
 
@@ -1246,6 +1312,7 @@
       case ObjectAccessTargetKind.ambiguous:
         return unknownFunction;
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         return _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
@@ -1254,8 +1321,12 @@
         switch (target.extensionMethodKind) {
           case ProcedureKind.Method:
           case ProcedureKind.Operator:
-            return target.member.function
-                .computeFunctionType(library.nonNullable);
+            FunctionType functionType =
+                target.member.function.computeFunctionType(library.nonNullable);
+            if (!isNonNullableByDefault) {
+              functionType = legacyErasure(functionType);
+            }
+            return functionType;
           case ProcedureKind.Getter:
             // TODO(johnniwinther): Handle implicit .call on extension getter.
             return _getFunctionType(target.member.function.returnType);
@@ -1286,6 +1357,7 @@
   DartType getReturnType(ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         FunctionType functionType = _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
@@ -1302,7 +1374,10 @@
               Substitution substitution = Substitution.fromPairs(
                   functionType.typeParameters,
                   target.inferredExtensionTypeArguments);
-              return substitution.substituteType(returnType);
+              returnType = substitution.substituteType(returnType);
+            }
+            if (!isNonNullableByDefault) {
+              returnType = legacyErasure(returnType);
             }
             return returnType;
           default:
@@ -1327,6 +1402,7 @@
       ObjectAccessTarget target, DartType receiverType, int index) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         FunctionType functionType = _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
@@ -1344,7 +1420,10 @@
             Substitution substitution = Substitution.fromPairs(
                 functionType.typeParameters,
                 target.inferredExtensionTypeArguments);
-            return substitution.substituteType(keyType);
+            keyType = substitution.substituteType(keyType);
+          }
+          if (!isNonNullableByDefault) {
+            keyType = legacyErasure(keyType);
           }
           return keyType;
         }
@@ -1384,6 +1463,7 @@
   DartType getIndexKeyType(ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         FunctionType functionType = _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
@@ -1403,7 +1483,10 @@
                 Substitution substitution = Substitution.fromPairs(
                     functionType.typeParameters,
                     target.inferredExtensionTypeArguments);
-                return substitution.substituteType(keyType);
+                keyType = substitution.substituteType(keyType);
+              }
+              if (!isNonNullableByDefault) {
+                keyType = legacyErasure(keyType);
               }
               return keyType;
             }
@@ -1444,6 +1527,7 @@
       ObjectAccessTarget target, DartType receiverType) {
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         FunctionType functionType = _getFunctionType(
             getGetterTypeForMemberTarget(target.member, receiverType));
@@ -1463,7 +1547,10 @@
                 Substitution substitution = Substitution.fromPairs(
                     functionType.typeParameters,
                     target.inferredExtensionTypeArguments);
-                return substitution.substituteType(indexType);
+                indexType = substitution.substituteType(indexType);
+              }
+              if (!isNonNullableByDefault) {
+                indexType = legacyErasure(indexType);
               }
               return indexType;
             }
@@ -1488,6 +1575,9 @@
   FunctionType _getFunctionType(DartType calleeType) {
     calleeType = resolveTypeParameter(calleeType);
     if (calleeType is FunctionType) {
+      if (!isNonNullableByDefault) {
+        calleeType = legacyErasure(calleeType);
+      }
       return calleeType;
     }
     return unknownFunction;
@@ -1496,6 +1586,9 @@
   FunctionType getFunctionTypeForImplicitCall(DartType calleeType) {
     calleeType = resolveTypeParameter(calleeType);
     if (calleeType is FunctionType) {
+      if (!isNonNullableByDefault) {
+        calleeType = legacyErasure(calleeType);
+      }
       return calleeType;
     } else if (calleeType is InterfaceType) {
       Member member =
@@ -1503,6 +1596,9 @@
       if (member != null) {
         DartType callType = getGetterTypeForMemberTarget(member, calleeType);
         if (callType is FunctionType) {
+          if (!isNonNullableByDefault) {
+            callType = legacyErasure(callType);
+          }
           return callType;
         }
       }
@@ -1525,7 +1621,7 @@
   /// Otherwise return the given [member].
   Member getRealTarget(Member member) {
     if (member is Procedure && member.isForwardingStub) {
-      return member.forwardingStubInterfaceTarget;
+      return member.abstractForwardingStubTarget;
     }
     return member;
   }
@@ -1540,6 +1636,7 @@
       case ObjectAccessTargetKind.invalid:
         return const InvalidType();
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         Member interfaceMember = target.member;
         Class memberClass = interfaceMember.enclosingClass;
@@ -1567,6 +1664,9 @@
                 .substituteType(setterType);
           }
         }
+        if (!isNonNullableByDefault) {
+          setterType = legacyErasure(setterType);
+        }
         return setterType;
       case ObjectAccessTargetKind.extensionMember:
       case ObjectAccessTargetKind.nullableExtensionMember:
@@ -1580,8 +1680,12 @@
                 .toList();
             Substitution substitution = Substitution.fromPairs(
                 extensionTypeParameters, target.inferredExtensionTypeArguments);
-            return substitution
+            DartType setterType = substitution
                 .substituteType(functionType.positionalParameters[1]);
+            if (!isNonNullableByDefault) {
+              setterType = legacyErasure(setterType);
+            }
+            return setterType;
           case ProcedureKind.Method:
           case ProcedureKind.Getter:
           case ProcedureKind.Factory:
@@ -2173,10 +2277,12 @@
       if (argMessage != null) {
         return new WrapInProblemInferenceResult(
             const InvalidType(),
+            const InvalidType(),
             argMessage.messageObject,
             argMessage.charOffset,
             argMessage.length,
-            helper);
+            helper,
+            isInapplicable: true);
       } else {
         // Argument counts and names match. Compare types.
         int positionalShift = isImplicitExtensionMember ? 1 : 0;
@@ -2233,9 +2339,10 @@
 
     if (!isNonNullableByDefault) {
       inferredType = legacyErasure(inferredType);
+      calleeType = legacyErasure(calleeType);
     }
 
-    return new SuccessfulInferenceResult(inferredType);
+    return new SuccessfulInferenceResult(inferredType, calleeType);
   }
 
   DartType inferLocalFunction(FunctionNode function, DartType typeContext,
@@ -2407,16 +2514,13 @@
     // `void` if `B’` contains no `yield` expressions.  Otherwise, let `M` be
     // the least upper bound of the types of the `return` expressions in `B’`,
     // or `void` if `B’` contains no `return` expressions.
-    DartType inferredReturnType;
     if (needToSetReturnType) {
-      inferredReturnType = closureContext.inferReturnType(this,
+      DartType inferredReturnType = closureContext.inferReturnType(this,
           hasImplicitReturn: flowAnalysis.isReachable);
-    }
 
-    // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with
-    // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi`
-    // denoted as optional or named parameters, if appropriate).
-    if (needToSetReturnType) {
+      // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B`
+      // with type `<T0, ..., Tn>(R0, ..., Rn) -> M'` (with some of the `Ri` and
+      // `xi` denoted as optional or named parameters, if appropriate).
       instrumentation?.record(uriForInstrumentation, fileOffset, 'returnType',
           new InstrumentationValueForType(inferredReturnType));
       function.returnType = inferredReturnType;
@@ -2488,11 +2592,17 @@
         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;
+    }
     return createNullAwareExpressionInferenceResult(
-        result.inferredType,
-        result.applyResult(new MethodInvocation(receiver, name, arguments)
-          ..fileOffset = fileOffset),
-        nullAwareGuards);
+        result.inferredType, result.applyResult(expression), nullAwareGuards);
   }
 
   ExpressionInferenceResult _inferNeverInvocation(
@@ -2512,10 +2622,18 @@
         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;
+    }
     return createNullAwareExpressionInferenceResult(
         const NeverType(Nullability.nonNullable),
-        result.applyResult(new MethodInvocation(receiver, name, arguments)
-          ..fileOffset = fileOffset),
+        result.applyResult(expression),
         nullAwareGuards);
   }
 
@@ -2642,15 +2760,49 @@
       {bool isImplicitCall}) {
     assert(isImplicitCall != null);
     assert(target.isCallFunction || target.isNullableCallFunction);
-    FunctionType functionType = getFunctionType(target, receiverType);
+    FunctionType declaredFunctionType = getFunctionType(target, receiverType);
     InvocationInferenceResult result = inferInvocation(
-        typeContext, fileOffset, functionType, arguments,
+        typeContext, fileOffset, declaredFunctionType, arguments,
         hoistedExpressions: hoistedExpressions,
         receiverType: receiverType,
         isImplicitCall: isImplicitCall);
-    Expression replacement = result.applyResult(
-        new MethodInvocation(receiver, callName, arguments)
-          ..fileOffset = fileOffset);
+    Expression expression;
+    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;
+        if (variable.parent is FunctionDeclaration) {
+          assert(inferredFunctionType != unknownFunction,
+              "Unknown function type for local function invocation.");
+          expression = new LocalFunctionInvocation(variable, arguments,
+              functionType: inferredFunctionType)
+            ..fileOffset = receiver.fileOffset;
+        }
+      }
+      expression ??= new FunctionInvocation(
+          target.isNullableCallFunction
+              ? FunctionAccessKind.Nullable
+              : (inferredFunctionType == unknownFunction
+                  ? FunctionAccessKind.Function
+                  : FunctionAccessKind.FunctionType),
+          receiver,
+          arguments,
+          functionType: inferredFunctionType == unknownFunction
+              ? null
+              : inferredFunctionType)
+        ..fileOffset = fileOffset;
+    } else {
+      expression = new MethodInvocation(receiver, callName, arguments)
+        ..fileOffset = fileOffset;
+    }
+    Expression replacement = result.applyResult(expression);
     if (!isTopLevel && target.isNullableCallFunction) {
       if (isImplicitCall) {
         replacement = helper.wrapInProblem(
@@ -2673,6 +2825,16 @@
         result.inferredType, replacement, nullAwareGuards);
   }
 
+  FunctionType _computeFunctionTypeForArguments(
+      Arguments arguments, DartType type) {
+    return new FunctionType(
+        new List<DartType>.filled(arguments.positional.length, type),
+        type,
+        library.nonNullable,
+        namedParameters: new List<NamedType>.generate(arguments.named.length,
+            (int index) => new NamedType(arguments.named[index].name, type)));
+  }
+
   ExpressionInferenceResult _inferInstanceMethodInvocation(
       int fileOffset,
       Link<NullAwareGuard> nullAwareGuards,
@@ -2688,7 +2850,9 @@
     assert(isImplicitCall != null);
     assert(isSpecialCasedBinaryOperator != null);
     assert(isSpecialCasedTernaryOperator != null);
-    assert(target.isInstanceMember || target.isNullableInstanceMember);
+    assert(target.isInstanceMember ||
+        target.isObjectMember ||
+        target.isNullableInstanceMember);
     Procedure method = target.member;
     assert(method.kind == ProcedureKind.Method,
         "Unexpected instance method $method");
@@ -2715,7 +2879,7 @@
     }
 
     DartType calleeType = getGetterType(target, receiverType);
-    FunctionType functionType = getFunctionType(target, receiverType);
+    FunctionType declaredFunctionType = getFunctionType(target, receiverType);
 
     bool contravariantCheck = false;
     if (receiver is! ThisExpression &&
@@ -2725,20 +2889,64 @@
       contravariantCheck = true;
     }
     InvocationInferenceResult result = inferInvocation(
-        typeContext, fileOffset, functionType, arguments,
+        typeContext, fileOffset, declaredFunctionType, arguments,
         hoistedExpressions: hoistedExpressions,
         receiverType: receiverType,
         isImplicitCall: isImplicitCall,
         isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
         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, interfaceTarget: method)
+          ..fileOffset = fileOffset;
+      }
+    } else {
+      expression = new MethodInvocation(receiver, methodName, arguments, method)
+        ..fileOffset = fileOffset;
+    }
     Expression replacement;
     if (contravariantCheck) {
       // TODO(johnniwinther): Merge with the replacement computation below.
-      replacement = new AsExpression(
-          new MethodInvocation(receiver, methodName, arguments, method)
-            ..fileOffset = fileOffset,
-          result.inferredType)
+      replacement = new AsExpression(expression, result.inferredType)
         ..isTypeError = true
         ..isCovarianceCheck = true
         ..isForNonNullableByDefault = isNonNullableByDefault
@@ -2749,15 +2957,13 @@
         instrumentation.record(uriForInstrumentation, offset, 'checkReturn',
             new InstrumentationValueForType(result.inferredType));
       }
+    } else {
+      replacement = expression;
     }
 
     _checkBoundsInMethodInvocation(
         target, receiverType, calleeType, methodName, arguments, fileOffset);
 
-    replacement ??=
-        new MethodInvocation(receiver, methodName, arguments, method)
-          ..fileOffset = fileOffset;
-
     replacement = result.applyResult(replacement);
     if (!isTopLevel && target.isNullable) {
       if (isImplicitCall) {
@@ -2792,7 +2998,9 @@
       List<VariableDeclaration> hoistedExpressions,
       {bool isExpressionInvocation}) {
     assert(isExpressionInvocation != null);
-    assert(target.isInstanceMember || target.isNullableInstanceMember);
+    assert(target.isInstanceMember ||
+        target.isObjectMember ||
+        target.isNullableInstanceMember);
     Procedure getter = target.member;
     assert(getter.kind == ProcedureKind.Getter);
 
@@ -2828,8 +3036,33 @@
       receiver = _hoist(receiver, receiverType, hoistedExpressions);
     }
 
-    PropertyGet originalPropertyGet =
-        new PropertyGet(receiver, getter.name, getter)..fileOffset = fileOffset;
+    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;
+    }
     Expression propertyGet = originalPropertyGet;
     if (calleeType is! DynamicType &&
         receiver is! ThisExpression &&
@@ -2886,11 +3119,29 @@
           nullAwareAction.receiver == originalPropertyGet) {
         invocationResult = new ExpressionInferenceResult(
             invocationResult.inferredType,
-            new MethodInvocation(
-                originalPropertyGet.receiver,
-                originalPropertyGet.name,
-                nullAwareAction.arguments,
-                originalPropertyGet.interfaceTarget)
+            new MethodInvocation(originalReceiver, originalName,
+                nullAwareAction.arguments, originalTarget)
+              ..fileOffset = nullAwareAction.fileOffset);
+      } else 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 DynamicInvocation &&
+          nullAwareAction.receiver == originalPropertyGet) {
+        invocationResult = new ExpressionInferenceResult(
+            invocationResult.inferredType,
+            new MethodInvocation(originalReceiver, originalName,
+                nullAwareAction.arguments, originalTarget)
+              ..fileOffset = nullAwareAction.fileOffset);
+      } else if (nullAwareAction is FunctionInvocation &&
+          nullAwareAction.receiver == originalPropertyGet) {
+        invocationResult = new ExpressionInferenceResult(
+            invocationResult.inferredType,
+            new MethodInvocation(originalReceiver, originalName,
+                nullAwareAction.arguments, originalTarget)
               ..fileOffset = nullAwareAction.fileOffset);
       }
     }
@@ -2937,7 +3188,9 @@
       List<VariableDeclaration> hoistedExpressions,
       {bool isExpressionInvocation}) {
     assert(isExpressionInvocation != null);
-    assert(target.isInstanceMember || target.isNullableInstanceMember);
+    assert(target.isInstanceMember ||
+        target.isObjectMember ||
+        target.isNullableInstanceMember);
     Field field = target.member;
 
     DartType calleeType = getGetterType(target, receiverType);
@@ -2952,8 +3205,34 @@
       receiver = _hoist(receiver, receiverType, hoistedExpressions);
     }
 
-    PropertyGet originalPropertyGet =
-        new PropertyGet(receiver, field.name, field)..fileOffset = fileOffset;
+    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;
+    }
     Expression propertyGet = originalPropertyGet;
     if (receiver is! ThisExpression &&
         calleeType is! DynamicType &&
@@ -3011,11 +3290,29 @@
           nullAwareAction.receiver == originalPropertyGet) {
         invocationResult = new ExpressionInferenceResult(
             invocationResult.inferredType,
-            new MethodInvocation(
-                originalPropertyGet.receiver,
-                originalPropertyGet.name,
-                nullAwareAction.arguments,
-                originalPropertyGet.interfaceTarget)
+            new MethodInvocation(originalReceiver, originalName,
+                nullAwareAction.arguments, originalTarget)
+              ..fileOffset = nullAwareAction.fileOffset);
+      } else 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 DynamicInvocation &&
+          nullAwareAction.receiver == originalPropertyGet) {
+        invocationResult = new ExpressionInferenceResult(
+            invocationResult.inferredType,
+            new MethodInvocation(originalReceiver, originalName,
+                nullAwareAction.arguments, originalTarget)
+              ..fileOffset = nullAwareAction.fileOffset);
+      } else if (nullAwareAction is FunctionInvocation &&
+          nullAwareAction.receiver == originalPropertyGet) {
+        invocationResult = new ExpressionInferenceResult(
+            invocationResult.inferredType,
+            new MethodInvocation(originalReceiver, originalName,
+                nullAwareAction.arguments, originalTarget)
               ..fileOffset = nullAwareAction.fileOffset);
       }
     }
@@ -3049,6 +3346,7 @@
 
     switch (target.kind) {
       case ObjectAccessTargetKind.instanceMember:
+      case ObjectAccessTargetKind.objectMember:
       case ObjectAccessTargetKind.nullableInstanceMember:
         Member member = target.member;
         if (member is Procedure) {
@@ -3169,7 +3467,9 @@
         actualMethodName = callName;
       } else {
         actualReceiverType = receiverType;
-        interfaceTarget = target.isInstanceMember ? target.member : null;
+        interfaceTarget = (target.isInstanceMember || target.isObjectMember)
+            ? target.member
+            : null;
         actualMethodName = methodName;
       }
       library.checkBoundsInMethodInvocation(
@@ -3187,7 +3487,9 @@
 
   bool isSpecialCasedBinaryOperatorForReceiverType(
       ObjectAccessTarget target, DartType receiverType) {
-    return (target.isInstanceMember || target.isNullableInstanceMember) &&
+    return (target.isInstanceMember ||
+            target.isObjectMember ||
+            target.isNullableInstanceMember) &&
         target.member is Procedure &&
         typeSchemaEnvironment.isSpecialCasesBinaryForReceiverType(
             target.member, receiverType,
@@ -3195,7 +3497,9 @@
   }
 
   bool isSpecialCasedTernaryOperator(ObjectAccessTarget target) {
-    return (target.isInstanceMember || target.isNullableInstanceMember) &&
+    return (target.isInstanceMember ||
+            target.isObjectMember ||
+            target.isNullableInstanceMember) &&
         target.member is Procedure &&
         typeSchemaEnvironment.isSpecialCasedTernaryOperator(target.member,
             isNonNullableByDefault: isNonNullableByDefault);
@@ -3205,8 +3509,11 @@
   ExpressionInferenceResult inferSuperMethodInvocation(
       SuperMethodInvocation expression,
       DartType typeContext,
-      ObjectAccessTarget target) {
-    assert(target.isInstanceMember || target.isMissing);
+      Procedure procedure) {
+    ObjectAccessTarget target = procedure != null
+        ? new ObjectAccessTarget.interfaceMember(procedure,
+            isPotentiallyNullable: false)
+        : const ObjectAccessTarget.missing();
     int fileOffset = expression.fileOffset;
     Name methodName = expression.name;
     Arguments arguments = expression.arguments;
@@ -3215,6 +3522,12 @@
         isSpecialCasedBinaryOperatorForReceiverType(target, receiverType);
     DartType calleeType = getGetterType(target, receiverType);
     FunctionType functionType = getFunctionType(target, receiverType);
+    if (procedure != null) {
+      calleeType =
+          computeTypeFromSuperClass(procedure.enclosingClass, calleeType);
+      functionType =
+          computeTypeFromSuperClass(procedure.enclosingClass, functionType);
+    }
     if (isNonNullableByDefault &&
         expression.name == equalsName &&
         functionType.positionalParameters.length == 1) {
@@ -3228,7 +3541,7 @@
         typeContext, fileOffset, functionType, arguments,
         isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
         receiverType: receiverType,
-        isImplicitExtensionMember: target.isExtensionMember);
+        isImplicitExtensionMember: false);
     DartType inferredType = result.inferredType;
     if (methodName.text == '==') {
       inferredType = coreTypes.boolRawType(library.nonNullable);
@@ -3259,16 +3572,20 @@
   }
 
   /// Performs the core type inference algorithm for super property get.
-  ExpressionInferenceResult inferSuperPropertyGet(SuperPropertyGet expression,
-      DartType typeContext, ObjectAccessTarget readTarget) {
-    assert(readTarget.isInstanceMember || readTarget.isMissing);
+  ExpressionInferenceResult inferSuperPropertyGet(
+      SuperPropertyGet expression, DartType typeContext, Member member) {
+    ObjectAccessTarget readTarget = member != null
+        ? new ObjectAccessTarget.interfaceMember(member,
+            isPotentiallyNullable: false)
+        : const ObjectAccessTarget.missing();
     DartType receiverType = thisType;
     DartType inferredType = getGetterType(readTarget, receiverType);
-    if (readTarget.isInstanceMember) {
-      Member member = readTarget.member;
-      if (member is Procedure && member.kind == ProcedureKind.Method) {
-        return instantiateTearOff(inferredType, typeContext, expression);
-      }
+    if (member != null) {
+      inferredType =
+          computeTypeFromSuperClass(member.enclosingClass, inferredType);
+    }
+    if (member is Procedure && member.kind == ProcedureKind.Method) {
+      return instantiateTearOff(inferredType, typeContext, expression);
     }
     return new ExpressionInferenceResult(inferredType, expression);
   }
@@ -3349,7 +3666,7 @@
       DartType receiverType, ObjectAccessTarget target,
       {bool isThisReceiver}) {
     assert(isThisReceiver != null);
-    if (target.isInstanceMember) {
+    if (target.isInstanceMember || target.isObjectMember) {
       Member interfaceMember = target.member;
       if (interfaceMember is Field ||
           interfaceMember is Procedure &&
@@ -3499,6 +3816,14 @@
       }
       return null;
     }
+    if (expression is StaticTearOff) {
+      Member target = expression.target;
+      if (target.enclosingClass != null) {
+        return templateInvalidCastStaticMethod;
+      } else {
+        return templateInvalidCastTopLevelFunction;
+      }
+    }
     if (expression is VariableGet) {
       VariableDeclaration variable = expression.variable;
       if (variable is VariableDeclarationImpl && variable.isLocalFunction) {
@@ -3668,13 +3993,11 @@
   Expression createMissingIndexSet(int fileOffset, Expression receiver,
       DartType receiverType, Expression index, Expression value,
       {bool forEffect,
-      bool readOnlyReceiver,
       List<ExtensionAccessCandidate> extensionAccessCandidates}) {
     assert(forEffect != null);
-    assert(readOnlyReceiver != null);
     if (isTopLevel) {
       return engine.forest.createIndexSet(fileOffset, receiver, index, value,
-          forEffect: forEffect, readOnlyReceiver: readOnlyReceiver);
+          forEffect: forEffect);
     } else {
       return _reportMissingOrAmbiguousMember(
           fileOffset,
@@ -3723,6 +4046,25 @@
           templateAmbiguousExtensionOperator);
     }
   }
+
+  /// Creates a `e == null` test for the expression [left] using the
+  /// [fileOffset] as file offset for the created nodes and [equalsMember] as
+  /// the interface target of the created method invocation.
+  Expression createEqualsNull(
+      int fileOffset, Expression left, Member equalsMember) {
+    if (useNewMethodInvocationEncoding) {
+      return new EqualsNull(left, isNot: false)..fileOffset = fileOffset;
+    } else {
+      return new MethodInvocation(
+          left,
+          equalsName,
+          new Arguments(
+              <Expression>[new NullLiteral()..fileOffset = fileOffset])
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset
+        ..interfaceTarget = equalsMember;
+    }
+  }
 }
 
 abstract class MixinInferrer {
@@ -3939,27 +4281,42 @@
 abstract class InvocationInferenceResult {
   DartType get inferredType;
 
+  DartType get functionType;
+
   /// Applies the result of the inference to the expression being inferred.
   ///
   /// A successful result leaves [expression] intact, and an error detected
   /// during inference would wrap the expression into an [InvalidExpression].
   Expression applyResult(Expression expression);
+
+  /// Returns `true` if the arguments of the call where not applicable to the
+  /// target.
+  bool get isInapplicable;
 }
 
 class SuccessfulInferenceResult implements InvocationInferenceResult {
   @override
   final DartType inferredType;
 
-  SuccessfulInferenceResult(this.inferredType);
+  @override
+  final FunctionType functionType;
+
+  SuccessfulInferenceResult(this.inferredType, this.functionType);
 
   @override
   Expression applyResult(Expression expression) => expression;
+
+  @override
+  bool get isInapplicable => false;
 }
 
 class WrapInProblemInferenceResult implements InvocationInferenceResult {
   @override
   final DartType inferredType;
 
+  @override
+  final DartType functionType;
+
   final Message message;
 
   final int fileOffset;
@@ -3968,8 +4325,13 @@
 
   final InferenceHelper helper;
 
-  WrapInProblemInferenceResult(this.inferredType, this.message, this.fileOffset,
-      this.length, this.helper);
+  @override
+  final bool isInapplicable;
+
+  WrapInProblemInferenceResult(this.inferredType, this.functionType,
+      this.message, this.fileOffset, this.length, this.helper,
+      {this.isInapplicable})
+      : assert(isInapplicable != null);
 
   @override
   Expression applyResult(Expression expression) {
@@ -4050,13 +4412,14 @@
     _inferrer.flowAnalysis.nullAwareAccess_end();
     // End non-nullable promotion of the initializer of [_nullAwareVariable].
     _inferrer.flowAnalysis.nullAwareAccess_end();
-    MethodInvocation equalsNull = createEqualsNull(_nullAwareFileOffset,
+    Expression equalsNull = _inferrer.createEqualsNull(_nullAwareFileOffset,
         createVariableGet(_nullAwareVariable), _nullAwareEquals);
     ConditionalExpression condition = new ConditionalExpression(
         equalsNull,
         new NullLiteral()..fileOffset = _nullAwareFileOffset,
         nullAwareAction,
-        inferredType);
+        inferredType)
+      ..fileOffset = _nullAwareFileOffset;
     return new Let(_nullAwareVariable, condition)
       ..fileOffset = _nullAwareFileOffset;
   }
@@ -4109,14 +4472,18 @@
 }
 
 enum ObjectAccessTargetKind {
-  /// A valid access to a statically known instance member. The access is
-  /// either non-nullable or potentially nullable on a `Object` member.
+  /// A valid access to a statically known instance member on a non-nullable
+  /// receiver.
   instanceMember,
 
   /// A potentially nullable access to a statically known instance member. This
   /// is an erroneous case and a compile-time error is reported.
   nullableInstanceMember,
 
+  /// A valid access to a statically known instance Object member on a
+  /// potentially nullable receiver.
+  objectMember,
+
   /// A (non-nullable) access to the `.call` method of a function. This is used
   /// for access on `Function` and on function types.
   callFunction,
@@ -4172,6 +4539,13 @@
         member);
   }
 
+  /// Creates an access to the Object [member].
+  factory ObjectAccessTarget.objectMember(Member member) {
+    assert(member != null);
+    return new ObjectAccessTarget.internal(
+        ObjectAccessTargetKind.objectMember, member);
+  }
+
   /// Creates an access to the extension [member].
   factory ObjectAccessTarget.extensionMember(
       Member member,
@@ -4213,6 +4587,9 @@
   /// Returns `true` if this is an access to an instance member.
   bool get isInstanceMember => kind == ObjectAccessTargetKind.instanceMember;
 
+  /// Returns `true` if this is an access to an Object member.
+  bool get isObjectMember => kind == ObjectAccessTargetKind.objectMember;
+
   /// Returns `true` if this is an access to an extension member.
   bool get isExtensionMember => kind == ObjectAccessTargetKind.extensionMember;
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
index 2ae32bf..f94934e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart'
     show DartType, Expression, TypeParameterType, VariableDeclaration;
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
index 0e93526..883df40 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart'
     show
         DartType,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
index e6338be..f07e42a 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/src/replacement_visitor.dart';
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index 59cbd3c..0e12020 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.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.md file.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart' hide MapEntry;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -147,8 +149,6 @@
     if (isNonNullableByDefault) {
       if (contextType is! NeverType &&
           type1 is! NeverType &&
-          isSubtypeOf(contextType, coreTypes.numNonNullableRawType,
-              SubtypeCheckMode.withNullabilities) &&
           isSubtypeOf(type1, coreTypes.numNonNullableRawType,
               SubtypeCheckMode.withNullabilities)) {
         // If e is an expression of the form e1 + e2, e1 - e2, e1 * e2, e1 % e2
diff --git a/pkg/front_end/lib/src/fasta/uri_translator.dart b/pkg/front_end/lib/src/fasta/uri_translator.dart
index be2af3c..55222b2 100644
--- a/pkg/front_end/lib/src/fasta/uri_translator.dart
+++ b/pkg/front_end/lib/src/fasta/uri_translator.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.9
+
 library fasta.uri_translator;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
diff --git a/pkg/front_end/lib/src/fasta/util/bytes_sink.dart b/pkg/front_end/lib/src/fasta/util/bytes_sink.dart
index d945e92..4e3b61f 100644
--- a/pkg/front_end/lib/src/fasta/util/bytes_sink.dart
+++ b/pkg/front_end/lib/src/fasta/util/bytes_sink.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.9
+
 import 'dart:io' show BytesBuilder;
 
 // TODO(ahe): https://github.com/dart-lang/sdk/issues/28316
diff --git a/pkg/front_end/lib/src/fasta/util/direct_parser_ast.dart b/pkg/front_end/lib/src/fasta/util/direct_parser_ast.dart
index 3331e01..9a2fcea 100644
--- a/pkg/front_end/lib/src/fasta/util/direct_parser_ast.dart
+++ b/pkg/front_end/lib/src/fasta/util/direct_parser_ast.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.9
+
 import 'dart:typed_data' show Uint8List;
 
 import 'dart:io' show File;
diff --git a/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart b/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
index 70be181..cc76576 100644
--- a/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
+++ b/pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.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.9
+
 import 'package:_fe_analyzer_shared/src/parser/assert.dart';
 import 'package:_fe_analyzer_shared/src/parser/block_kind.dart';
 import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart';
diff --git a/pkg/front_end/lib/src/fasta/util/textual_outline.dart b/pkg/front_end/lib/src/fasta/util/textual_outline.dart
index 676582d..3f1cb92 100644
--- a/pkg/front_end/lib/src/fasta/util/textual_outline.dart
+++ b/pkg/front_end/lib/src/fasta/util/textual_outline.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.9
+
 import 'dart:typed_data' show Uint8List;
 
 import 'dart:io' show File;
@@ -11,6 +13,9 @@
 
 import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
 
+import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
+    show ScannerConfiguration;
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ErrorToken, LanguageVersionToken, Scanner;
 
@@ -418,7 +423,8 @@
 //              "show A, B, C hide A show A" would be empty.
 
 String textualOutline(List<int> rawBytes,
-    {bool throwOnUnexpected: false,
+    {ScannerConfiguration configuration,
+    bool throwOnUnexpected: false,
     bool performModelling: false,
     bool addMarkerForUnknownForTest: false}) {
   Uint8List bytes = new Uint8List(rawBytes.length + 1);
@@ -428,8 +434,9 @@
 
   BoxedInt originalPosition = new BoxedInt(0);
 
-  Utf8BytesScanner scanner = new Utf8BytesScanner(bytes, includeComments: false,
-      languageVersionChanged:
+  Utf8BytesScanner scanner = new Utf8BytesScanner(bytes,
+      includeComments: false,
+      configuration: configuration, languageVersionChanged:
           (Scanner scanner, LanguageVersionToken languageVersion) {
     parsedChunks.add(
         new _LanguageVersionChunk(languageVersion.major, languageVersion.minor)
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index ae668cb..ac52474 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.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.9
+
 /// Defines the front-end API for converting source code to Dart Kernel objects.
 library front_end.kernel_generator_impl;
 
@@ -65,6 +67,7 @@
     bool retainDataForTesting: false,
     bool includeHierarchyAndCoreTypes: false}) async {
   ProcessedOptions options = CompilerContext.current.options;
+  options.reportNullSafetyCompilationModeInfo();
   FileSystem fs = options.fileSystem;
 
   Loader sourceLoader;
diff --git a/pkg/front_end/lib/src/scheme_based_file_system.dart b/pkg/front_end/lib/src/scheme_based_file_system.dart
index c2b3981..f52f214 100644
--- a/pkg/front_end/lib/src/scheme_based_file_system.dart
+++ b/pkg/front_end/lib/src/scheme_based_file_system.dart
@@ -12,7 +12,7 @@
 
   @override
   FileSystemEntity entityForUri(Uri uri) {
-    FileSystem delegate = fileSystemByScheme[uri.scheme];
+    FileSystem? delegate = fileSystemByScheme[uri.scheme];
     if (delegate == null) {
       throw new FileSystemException(
           uri,
diff --git a/pkg/front_end/lib/src/testing/compiler_common.dart b/pkg/front_end/lib/src/testing/compiler_common.dart
index 3164c83..5f0e775 100644
--- a/pkg/front_end/lib/src/testing/compiler_common.dart
+++ b/pkg/front_end/lib/src/testing/compiler_common.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.9
+
 /// Common compiler options and helper functions used for testing.
 library front_end.testing.compiler_options_common;
 
diff --git a/pkg/front_end/lib/src/testing/id_extractor.dart b/pkg/front_end/lib/src/testing/id_extractor.dart
index f9fcbd3..93af7c6 100644
--- a/pkg/front_end/lib/src/testing/id_extractor.dart
+++ b/pkg/front_end/lib/src/testing/id_extractor.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.9
+
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:kernel/ast.dart';
 import '../api_prototype/lowering_predicates.dart';
@@ -196,6 +198,20 @@
     computeForMember(node);
   }
 
+  _visitInvocation(Expression node, Name name) {
+    if (name.name == '[]') {
+      computeForNode(node, computeDefaultNodeId(node));
+    } else if (name.name == '[]=') {
+      computeForNode(node, createUpdateId(node));
+    } else {
+      if (node.fileOffset != TreeNode.noOffset) {
+        // TODO(johnniwinther): Ensure file offset on all method invocations.
+        // Skip synthetic invocation created in the collection transformer.
+        computeForNode(node, createInvokeId(node));
+      }
+    }
+  }
+
   @override
   visitMethodInvocation(MethodInvocation node) {
     TreeNode receiver = node.receiver;
@@ -204,27 +220,58 @@
       // This is an invocation of a named local function.
       computeForNode(node, createInvokeId(node.receiver));
       node.arguments.accept(this);
-    } else if (node.name.text == '==' &&
+    } else if (node.name.name == '==' &&
         receiver is VariableGet &&
         receiver.variable.name == null) {
       // This is a desugared `?.`.
-    } else if (node.name.text == '[]') {
-      computeForNode(node, computeDefaultNodeId(node));
-      super.visitMethodInvocation(node);
-    } else if (node.name.text == '[]=') {
-      computeForNode(node, createUpdateId(node));
-      super.visitMethodInvocation(node);
     } else {
-      if (node.fileOffset != TreeNode.noOffset) {
-        // TODO(johnniwinther): Ensure file offset on all method invocations.
-        // Skip synthetic invocation created in the collection transformer.
-        computeForNode(node, createInvokeId(node));
-      }
+      _visitInvocation(node, node.name);
       super.visitMethodInvocation(node);
     }
   }
 
   @override
+  visitDynamicInvocation(DynamicInvocation node) {
+    _visitInvocation(node, node.name);
+    super.visitDynamicInvocation(node);
+  }
+
+  @override
+  visitFunctionInvocation(FunctionInvocation node) {
+    _visitInvocation(node, node.name);
+    super.visitFunctionInvocation(node);
+  }
+
+  @override
+  visitLocalFunctionInvocation(LocalFunctionInvocation node) {
+    computeForNode(node, createInvokeId(node));
+    super.visitLocalFunctionInvocation(node);
+  }
+
+  @override
+  visitEqualsCall(EqualsCall node) {
+    _visitInvocation(node, Name.equalsName);
+    super.visitEqualsCall(node);
+  }
+
+  @override
+  visitEqualsNull(EqualsNull node) {
+    Expression receiver = node.expression;
+    if (receiver is VariableGet && receiver.variable.name == null) {
+      // This is a desugared `?.`.
+    } else {
+      _visitInvocation(node, Name.equalsName);
+    }
+    super.visitEqualsNull(node);
+  }
+
+  @override
+  visitInstanceInvocation(InstanceInvocation node) {
+    _visitInvocation(node, node.name);
+    super.visitInstanceInvocation(node);
+  }
+
+  @override
   visitLoadLibrary(LoadLibrary node) {
     computeForNode(node, createInvokeId(node));
   }
@@ -236,6 +283,30 @@
   }
 
   @override
+  visitDynamicGet(DynamicGet node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    super.visitDynamicGet(node);
+  }
+
+  @override
+  visitFunctionTearOff(FunctionTearOff node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    super.visitFunctionTearOff(node);
+  }
+
+  @override
+  visitInstanceGet(InstanceGet node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    super.visitInstanceGet(node);
+  }
+
+  @override
+  visitInstanceTearOff(InstanceTearOff node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    super.visitInstanceTearOff(node);
+  }
+
+  @override
   visitVariableDeclaration(VariableDeclaration node) {
     if (node.name != null && node.parent is! FunctionDeclaration) {
       // Skip synthetic variables and function declaration variables.
@@ -278,6 +349,18 @@
   }
 
   @override
+  visitDynamicSet(DynamicSet node) {
+    computeForNode(node, createUpdateId(node));
+    super.visitDynamicSet(node);
+  }
+
+  @override
+  visitInstanceSet(InstanceSet node) {
+    computeForNode(node, createUpdateId(node));
+    super.visitInstanceSet(node);
+  }
+
+  @override
   visitVariableSet(VariableSet node) {
     if (node.variable.name != null) {
       // Skip use of synthetic variables.
@@ -446,8 +529,11 @@
     TreeNode parent = node.parent;
     if (node.fileOffset == TreeNode.noOffset ||
         (parent is PropertyGet ||
+                parent is InstanceGet ||
                 parent is PropertySet ||
-                parent is MethodInvocation) &&
+                parent is InstanceSet ||
+                parent is MethodInvocation ||
+                parent is InstanceInvocation) &&
             parent.fileOffset == node.fileOffset) {
       // Skip implicit this expressions.
     } else {
@@ -479,6 +565,12 @@
   }
 
   @override
+  visitStaticTearOff(StaticTearOff node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    super.visitStaticTearOff(node);
+  }
+
+  @override
   visitStaticSet(StaticSet node) {
     computeForNode(node, createUpdateId(node));
     super.visitStaticSet(node);
@@ -525,4 +617,16 @@
         node, computeDefaultNodeId(node, skipNodeWithNoOffset: true));
     return super.visitBlock(node);
   }
+
+  @override
+  visitConditionalExpression(ConditionalExpression node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    return super.visitConditionalExpression(node);
+  }
+
+  @override
+  visitLogicalExpression(LogicalExpression node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    return super.visitLogicalExpression(node);
+  }
 }
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index 52c8586..69fb201 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.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.9
+
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 import 'package:_fe_analyzer_shared/src/testing/id.dart'
     show ActualData, ClassId, Id, IdKind, IdValue, MemberId, NodeId;
@@ -157,19 +159,21 @@
       Member member;
       int offset;
       if (id.className != null) {
-        Class cls = lookupClass(library, id.className);
-        member = lookupClassMember(cls, id.memberName, required: false);
-        if (member != null) {
-          offset = member.fileOffset;
-          if (offset == -1) {
+        Class cls = lookupClass(library, id.className, required: false);
+        if (cls != null) {
+          member = lookupClassMember(cls, id.memberName, required: false);
+          if (member != null) {
+            offset = member.fileOffset;
+            if (offset == -1) {
+              offset = cls.fileOffset;
+            }
+          } else {
             offset = cls.fileOffset;
           }
-        } else {
-          offset = cls.fileOffset;
         }
       } else {
-        member = lookupLibraryMember(library, id.memberName);
-        offset = member.fileOffset;
+        member = lookupLibraryMember(library, id.memberName, required: false);
+        offset = member?.fileOffset ?? 0;
       }
       if (offset == -1) {
         offset = 0;
@@ -182,8 +186,8 @@
       if (extension != null) {
         return extension.fileOffset;
       }
-      Class cls = lookupClass(library, id.className);
-      return cls.fileOffset;
+      Class cls = lookupClass(library, id.className, required: false);
+      return cls?.fileOffset ?? 0;
     }
     return null;
   }
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index 1b71339..a277ce2 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.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.9
+
 import 'package:kernel/ast.dart';
 
 import '../fasta/builder/class_builder.dart';
@@ -24,6 +26,14 @@
   return member.name.text;
 }
 
+/// Returns a canonical qualified name for [member].
+String getQualifiedMemberName(Member member) {
+  if (member.enclosingClass != null) {
+    return '${member.enclosingClass.name}.${getMemberName(member)}';
+  }
+  return getMemberName(member);
+}
+
 /// Returns the enclosing [Member] for [node].
 Member getEnclosingMember(TreeNode node) {
   while (node is! Member) {
diff --git a/pkg/front_end/lib/widget_cache.dart b/pkg/front_end/lib/widget_cache.dart
index 5c9f6d3..695ed83 100644
--- a/pkg/front_end/lib/widget_cache.dart
+++ b/pkg/front_end/lib/widget_cache.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.9
+
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/kernel.dart';
 
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 2350d4d..245cd2d 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -69,6 +69,8 @@
 CantUseSuperBoundedTypeForInstanceCreation/example: Fail
 ClassInNullAwareReceiver/analyzerCode: Fail
 ColonInPlaceOfIn/example: Fail
+CompilingWithSoundNullSafety/analyzerCode: Fail
+CompilingWithoutSoundNullSafety/analyzerCode: Fail
 ConflictingModifiers/part_wrapped_script1: Fail
 ConflictingModifiers/script1: Fail
 ConflictsWithConstructor/example: Fail
@@ -172,6 +174,8 @@
 DirectiveAfterDeclaration/part_wrapped_script2: Fail
 DirectiveAfterDeclaration/script1: Fail
 DirectiveAfterDeclaration/script2: Fail
+DuplicateDeferred/example: Fail
+DuplicatePrefix/example: Fail
 DuplicatedDeclarationUse/analyzerCode: Fail # No corresponding analyzer code.
 DuplicatedDeclarationUse/part_wrapped_script1: Fail
 DuplicatedDeclarationUse/part_wrapped_script2: Fail
@@ -179,7 +183,6 @@
 DuplicatedDeclarationUse/script2: Fail # Wrong error.
 DuplicatedDefinition/analyzerCode: Fail
 DuplicatedDefinition/example: Fail
-DuplicateDeferred/example: Fail
 DuplicatedExport/part_wrapped_script: Fail # Exporting file in the (now) part.
 DuplicatedExportInType/analyzerCode: Fail
 DuplicatedExportInType/example: Fail
@@ -191,7 +194,6 @@
 DuplicatedName/example: Fail
 DuplicatedNamedArgument/example: Fail
 DuplicatedParameterName/example: Fail
-DuplicatePrefix/example: Fail
 Encoding/analyzerCode: Fail
 EnumConstantSameNameAsEnclosing/example: Fail
 EnumInstantiation/example: Fail
@@ -271,7 +273,6 @@
 ExternalFactoryWithBody/script1: Fail
 ExternalFieldConstructorInitializer/analyzerCode: Fail
 ExternalFieldInitializer/analyzerCode: Fail
-ExtraneousModifier/part_wrapped_script1: Fail
 ExtraneousModifier/part_wrapped_script10: Fail
 ExtraneousModifier/part_wrapped_script11: Fail
 ExtraneousModifier/part_wrapped_script12: Fail
@@ -280,8 +281,9 @@
 ExtraneousModifier/part_wrapped_script17: Fail
 ExtraneousModifier/part_wrapped_script18: Fail
 ExtraneousModifier/part_wrapped_script19: Fail
-ExtraneousModifier/part_wrapped_script2: Fail
+ExtraneousModifier/part_wrapped_script1: Fail
 ExtraneousModifier/part_wrapped_script20: Fail
+ExtraneousModifier/part_wrapped_script2: Fail
 ExtraneousModifier/part_wrapped_script3: Fail
 ExtraneousModifier/part_wrapped_script4: Fail
 ExtraneousModifier/part_wrapped_script5: Fail
@@ -289,7 +291,6 @@
 ExtraneousModifier/part_wrapped_script7: Fail
 ExtraneousModifier/part_wrapped_script8: Fail
 ExtraneousModifier/part_wrapped_script9: Fail
-ExtraneousModifier/script1: Fail
 ExtraneousModifier/script10: Fail
 ExtraneousModifier/script11: Fail
 ExtraneousModifier/script12: Fail
@@ -298,8 +299,9 @@
 ExtraneousModifier/script17: Fail
 ExtraneousModifier/script18: Fail
 ExtraneousModifier/script19: Fail
-ExtraneousModifier/script2: Fail
+ExtraneousModifier/script1: Fail
 ExtraneousModifier/script20: Fail
+ExtraneousModifier/script2: Fail
 ExtraneousModifier/script3: Fail
 ExtraneousModifier/script4: Fail
 ExtraneousModifier/script5: Fail
@@ -315,12 +317,14 @@
 FastaUsageShort/analyzerCode: Fail
 FastaUsageShort/example: Fail
 FfiDartTypeMismatch/analyzerCode: Fail
+FfiEmptyStruct/analyzerCode: Fail
 FfiExceptionalReturnNull/analyzerCode: Fail
 FfiExpectedConstant/analyzerCode: Fail
 FfiExpectedExceptionalReturn/analyzerCode: Fail
 FfiExpectedNoExceptionalReturn/analyzerCode: Fail
 FfiExtendsOrImplementsSealedClass/analyzerCode: Fail
 FfiFieldAnnotation/analyzerCode: Fail
+FfiFieldCyclic/analyzerCode: Fail
 FfiFieldInitializer/analyzerCode: Fail
 FfiFieldNoAnnotation/analyzerCode: Fail
 FfiNotStatic/analyzerCode: Fail
@@ -394,10 +398,10 @@
 IncompatibleRedirecteeFunctionType/part_wrapped_script6: Fail
 IncompatibleRedirecteeFunctionType/script6: Fail # Triggers multiple errors.
 IncompatibleRedirecteeFunctionTypeWarning/example: Fail
-IncorrectTypeArgumentInferredWarning/example: Fail
 IncorrectTypeArgumentInReturnTypeWarning/example: Fail
 IncorrectTypeArgumentInSupertypeInferredWarning/example: Fail
 IncorrectTypeArgumentInSupertypeWarning/example: Fail
+IncorrectTypeArgumentInferredWarning/example: Fail
 IncorrectTypeArgumentQualifiedInferredWarning/example: Fail
 IncorrectTypeArgumentQualifiedWarning/example: Fail
 IncorrectTypeArgumentWarning/example: Fail
@@ -486,6 +490,8 @@
 JsInteropJSClassExtendsDartClass/example: Fail # Web compiler specific
 JsInteropNamedParameters/analyzerCode: Fail # Web compiler specific
 JsInteropNamedParameters/example: Fail # Web compiler specific
+JsInteropNativeClassInAnnotation/analyzerCode: Fail # Web compiler specific
+JsInteropNativeClassInAnnotation/example: Fail # Web compiler specific
 JsInteropNonExternalConstructor/analyzerCode: Fail # Web compiler specific
 JsInteropNonExternalConstructor/example: Fail # Web compiler specific
 JsInteropNonExternalMember/analyzerCode: Fail # Web compiler specific
@@ -560,6 +566,9 @@
 NeverValueWarning/analyzerCode: Fail
 NeverValueWarning/example: Fail
 NoFormals/example: Fail
+NoSuchNamedParameter/example: Fail
+NoUnnamedConstructorInObject/analyzerCode: Fail
+NoUnnamedConstructorInObject/example: Fail
 NonAgnosticConstant/analyzerCode: Fail
 NonAgnosticConstant/example: Fail
 NonAsciiIdentifier/expression: Fail
@@ -567,6 +576,7 @@
 NonConstConstructor/example: Fail
 NonConstFactory/example: Fail
 NonInstanceTypeVariableUse/example: Fail
+NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
 NonNullableInNullAware/analyzerCode: Fail
 NonNullableInNullAware/example: Fail
 NonNullableNotAssignedError/analyzerCode: Fail
@@ -576,17 +586,14 @@
 NonNullableOptOutExplicit/example: Fail
 NonNullableOptOutImplicit/analyzerCode: Fail
 NonNullableOptOutImplicit/example: Fail
-NonNullAwareSpreadIsNull/analyzerCode: Fail # There's no analyzer code for that error yet.
 NonPartOfDirectiveInPart/part_wrapped_script1: Fail
 NonPartOfDirectiveInPart/script1: Fail
-NoSuchNamedParameter/example: Fail
 NotAConstantExpression/example: Fail
-NotAnLvalue/example: Fail
 NotAType/example: Fail
+NotAnLvalue/example: Fail
 NotBinaryOperator/analyzerCode: Fail
 NotConstantExpression/example: Fail
-NoUnnamedConstructorInObject/analyzerCode: Fail
-NoUnnamedConstructorInObject/example: Fail
+NullAwareCascadeOutOfOrder/example: Fail
 NullableExpressionCallError/analyzerCode: Fail
 NullableExpressionCallError/example: Fail
 NullableExpressionCallWarning/analyzerCode: Fail
@@ -621,7 +628,6 @@
 NullableTearoffError/example: Fail
 NullableTearoffWarning/analyzerCode: Fail
 NullableTearoffWarning/example: Fail
-NullAwareCascadeOutOfOrder/example: Fail
 OperatorMinusParameterMismatch/example: Fail
 OperatorParameterMismatch0/analyzerCode: Fail
 OperatorParameterMismatch0/example: Fail
@@ -719,13 +725,13 @@
 StrongWithWeakDillLibrary/spelling: Fail
 SuperAsExpression/example: Fail
 SuperAsIdentifier/example: Fail
+SuperNullAware/example: Fail
 SuperclassHasNoDefaultConstructor/example: Fail
 SuperclassHasNoGetter/example: Fail
 SuperclassHasNoMethod/example: Fail
 SuperclassHasNoSetter/example: Fail
 SuperclassMethodArgumentMismatch/analyzerCode: Fail
 SuperclassMethodArgumentMismatch/example: Fail
-SuperNullAware/example: Fail
 SupertypeIsFunction/analyzerCode: Fail
 SupertypeIsFunction/example: Fail
 SupertypeIsIllegal/example: Fail
@@ -750,14 +756,14 @@
 TypeArgumentMismatch/example: Fail
 TypeArgumentsOnTypeVariable/part_wrapped_script1: Fail
 TypeArgumentsOnTypeVariable/script1: Fail
+TypeNotFound/example: Fail
+TypeVariableDuplicatedName/example: Fail
+TypeVariableSameNameAsEnclosing/example: Fail
 TypedefNotFunction/example: Fail
 TypedefNotType/example: Fail # Feature not yet enabled by default.
 TypedefNullableType/analyzerCode: Fail
 TypedefTypeVariableNotConstructor/analyzerCode: Fail # Feature not yet enabled by default.
 TypedefTypeVariableNotConstructor/example: Fail # Feature not yet enabled by default.
-TypeNotFound/example: Fail
-TypeVariableDuplicatedName/example: Fail
-TypeVariableSameNameAsEnclosing/example: Fail
 UnexpectedToken/part_wrapped_script1: Fail
 UnexpectedToken/script1: Fail
 UnmatchedToken/part_wrapped_script1: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 96f20a7..2e197e9 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1914,7 +1914,7 @@
 
 IncrementalCompilerIllegalParameter:
   template: "Illegal parameter name '#string' found during expression compilation."
-  
+
 IncrementalCompilerIllegalTypeParameter:
   template: "Illegal type parameter name '#string' found during expression compilation."
 
@@ -3563,6 +3563,21 @@
     #num2%12.3 bytes/ms, and
     #num3%12.3 ms/libraries.
 
+CantInferTypesDueToNoCombinedSignature:
+  template: "Can't infer types for '#name' as the overridden members don't have a combined signature."
+  tip: "Try adding explicit types."
+  analyzerCode: COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE
+  script: |
+    class A {
+      void method(int a, String b) {}
+    }
+    class B {
+      void method(String a, int b) {}
+    }
+    class C implements A, B {
+      void method(a, b) {}
+    }
+
 CantInferTypeDueToNoCombinedSignature:
   template: "Can't infer a type for '#name' as the overridden members don't have a combined signature."
   tip: "Try adding an explicit type."
@@ -3595,18 +3610,6 @@
       get getter;
     }
 
-CantInferTypeDueToInconsistentOverrides:
-  template: "Can't infer a type for '#name' as some of the overridden members have different types."
-  tip: "Try adding an explicit type."
-  analyzerCode: INVALID_METHOD_OVERRIDE
-  external: testcases/inference/inconsistent_overrides.dart
-
-CantInferReturnTypeDueToInconsistentOverrides:
-  template: "Can't infer a return type for '#name' as some of the overridden members have different types."
-  tip: "Try adding an explicit type."
-  analyzerCode: INVALID_METHOD_OVERRIDE
-  external: testcases/inference/inconsistent_overrides.dart
-
 CantInferTypeDueToCircularity:
   template: "Can't infer the type of '#string': circularity found during type inference."
   tip: "Specify the type explicitly."
@@ -3713,10 +3716,6 @@
   template: "The field that corresponds to the parameter."
   severity: CONTEXT
 
-UseOfDeprecatedIdentifier:
-  template: "'#name' is deprecated."
-  severity: IGNORED
-
 InitializeFromDillNotSelfContained:
   template: |
     Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
@@ -3854,10 +3853,10 @@
     from the import.
   analyzerCode: CONST_DEFERRED_CLASS
   script: |
-    import "dart:core" deferred as prefix;
+    import "dart:convert" deferred as prefix;
 
     main() {
-      const prefix.Object();
+      const prefix.JsonCodec();
     }
 
 CyclicRedirectingFactoryConstructors:
@@ -4136,6 +4135,10 @@
   template: "This is the type variable whose bound isn't conformed to."
   severity: CONTEXT
 
+SuperBoundedHint:
+  template: "If you want '#type' to be a super-bounded type, note that the inverted type '#type2' must then satisfy its bounds, which it does not."
+  severity: CONTEXT
+
 InferredPackageUri:
   template: "Interpreting this as package URI, '#uri'."
   severity: WARNING
@@ -4230,6 +4233,18 @@
   template: "Expected type '#type' to be '#type2', which is the Dart type corresponding to '#type3'."
   external: test/ffi_test.dart
 
+FfiEmptyStruct:
+  # Used by dart:ffi
+  template: "Struct '#name' is empty. Empty structs are undefined behavior."
+  external: test/ffi_test.dart
+
+FfiEmptyStructWarning:
+  # Used by dart:ffi
+  template: "Struct '#name' is empty. Support for empty structs is deprecated and will be removed in the next stable version of Dart. Use Opaque instead."
+  analyzerCode: EMPTY_STRUCT_WARNING
+  severity: INFO
+  external: test/ffi_test.dart
+
 FfiTypeInvalid:
   # Used by dart:ffi
   template: "Expected type '#type' to be a valid and instantiated subtype of 'NativeType'."
@@ -4245,6 +4260,20 @@
   template: "Field '#name' requires no annotation to declare its native type, it is a Pointer which is represented by the same type in Dart and native code."
   external: test/ffi_test.dart
 
+FfiFieldCyclic:
+  # Used by dart:ffi
+  template: |
+    Struct '#name' contains itself. Cycle elements:
+    #names
+  external: test/ffi_test.dart
+
+FfiNonConstantTypeArgumentWarning:
+  # Used by dart:ffi
+  template: "Support for using non-constant type arguments '#type' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type."
+  analyzerCode: NON_CONSTANT_TYPE_ARGUMENT_WARNING
+  severity: INFO
+  external: test/ffi_test.dart
+
 FfiNotStatic:
   # Used by dart:ffi
   template: "#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code."
@@ -4253,6 +4282,7 @@
 FfiFieldInitializer:
   # Used by dart:ffi
   template: "Field '#name' is a dart:ffi Pointer to a struct field and therefore cannot be initialized before constructor execution."
+  tip: "Mark the field as external to avoid having to initialize it."
   external: test/ffi_test.dart
 
 FfiExtendsOrImplementsSealedClass:
@@ -4651,6 +4681,9 @@
   template: "Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class."
   tip: "Try replacing them with normal or optional parameters."
 
+JsInteropNativeClassInAnnotation:
+  template: "JS interop class '#name' conflicts with natively supported class '#name2' in '#string3'."
+
 JsInteropNonExternalConstructor:
   template: "JS interop classes do not support non-external constructors."
   tip: "Try annotating with `external`."
@@ -4906,3 +4939,25 @@
 ExportedMain:
   template: "This is exported 'main' declaration."
   severity: CONTEXT
+
+UnexpectedModifierInNonNnbd:
+  template: "The modifier '#lexeme' is only available in null safe libraries."
+  exampleAllowMoreCodes: true
+  analyzerCode: UNEXPECTED_TOKEN
+  script:
+    - "late int x;"
+
+CompilingWithSoundNullSafety:
+  template: "Compiling with sound null safety"
+  configuration: nnbd-strong,compile
+  severity: INFO
+  script: |
+    main() {}
+
+CompilingWithoutSoundNullSafety:
+  template: "Compiling without sound null safety"
+  configuration: nnbd-weak,compile
+  severity: INFO
+  script: |
+    // @dart=2.9
+    main() {}
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.expect
index 0ec0417..5689179 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.expect
@@ -41,7 +41,7 @@
       handleAsyncModifier(null, null)
       beginBlockFunctionBody({)
         handleNoTypeArguments([)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
         handleIdentifier(, expression)
         handleNoTypeArguments(])
         handleNoArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.intertwined.expect
index 923a947..091a47f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.intertwined.expect
@@ -113,7 +113,7 @@
                                                       parseSend((, expression)
                                                         ensureIdentifier((, expression)
                                                           reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
                                                           rewriter()
                                                           listener: handleIdentifier(, expression)
                                                         listener: handleNoTypeArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.expect
index 7cd89f8..75b5105 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.expect
@@ -199,7 +199,7 @@
                     endArguments(0, (, ))
                     handleSend(D, ,)
                     handleRecoverableError(PositionalAfterNamedArgument, ], ])
-                    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+                    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
                     handleIdentifier(, expression)
                     handleNoTypeArguments(])
                     handleNoArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.intertwined.expect
index 19fb2c9..a41ebf5 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.intertwined.expect
@@ -449,7 +449,7 @@
                                                                               parseSend(,, expression)
                                                                                 ensureIdentifier(,, expression)
                                                                                   reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                                                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+                                                                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
                                                                                   rewriter()
                                                                                   listener: handleIdentifier(, expression)
                                                                                 listener: handleNoTypeArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_02.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_02.dart.expect
index 8031306..9598908 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_02.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_02.dart.expect
@@ -31,5 +31,5 @@
     endTopLevelMethod(void, null, })
   endTopLevelDeclaration()
   handleErrorToken(UnmatchedToken([))
-  handleRecoverableError(Message[UnmatchedToken, Can't find ']' to match '['., null, {string: ], token: [}], UnmatchedToken([), UnmatchedToken([))
+  handleRecoverableError(Message[UnmatchedToken, Can't find ']' to match '['., null, {string: ], lexeme: [}], UnmatchedToken([), UnmatchedToken([))
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_02.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_02.dart.intertwined.expect
index e1b6a96..a83baa2 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_02.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_02.dart.intertwined.expect
@@ -63,5 +63,5 @@
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(UnmatchedToken([))
     listener: handleErrorToken(UnmatchedToken([))
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ']' to match '['., null, {string: ], token: [}], UnmatchedToken([), UnmatchedToken([))
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ']' to match '['., null, {string: ], lexeme: [}], UnmatchedToken([), UnmatchedToken([))
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.expect
index cd7549e..e053cfc 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.expect
@@ -36,14 +36,14 @@
           handleSend(foo, ))
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
           handleExpressionStatement(;)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
           handleSend(, ))
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
           handleExpressionStatement(;)
-          handleRecoverableError(Message[UnexpectedToken, Unexpected token ')'., null, {token: )}], ), ))
+          handleRecoverableError(Message[UnexpectedToken, Unexpected token ')'., null, {lexeme: )}], ), ))
           handleEmptyStatement(;)
         endBlock(3, {, }, BlockKind(statement))
       endBlockFunctionBody(1, {, })
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.intertwined.expect
index 29aa2f0..787bbaa 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.intertwined.expect
@@ -72,7 +72,7 @@
                                   parseSend(;, expression)
                                     ensureIdentifier(;, expression)
                                       reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                       rewriter()
                                       listener: handleIdentifier(, expression)
                                     listener: handleNoTypeArguments())
@@ -84,8 +84,8 @@
                               listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
                             rewriter()
                           listener: handleExpressionStatement(;)
-                reportRecoverableError(), Message[UnexpectedToken, Unexpected token ')'., null, {token: )}])
-                  listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ')'., null, {token: )}], ), ))
+                reportRecoverableError(), Message[UnexpectedToken, Unexpected token ')'., null, {lexeme: )}])
+                  listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ')'., null, {lexeme: )}], ), ))
                 notEofOrValue(}, ;)
                 parseStatement())
                   parseStatementX())
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.expect
index 1afd0ff..d4b6a44 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.expect
@@ -44,14 +44,14 @@
               handleSend(bar, ))
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
               handleExpressionStatement(;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
               handleIdentifier(, expression)
               handleNoTypeArguments())
               handleNoArguments())
               handleSend(, ))
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
               handleExpressionStatement(;)
-              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
               handleEmptyStatement(;)
             endBlockFunctionBody(3, {, })
           endFunctionExpression((, ))
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.intertwined.expect
index 16e5973..a3b498e 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.intertwined.expect
@@ -104,7 +104,7 @@
                                                                       parseSend(;, expression)
                                                                         ensureIdentifier(;, expression)
                                                                           reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                                                           rewriter()
                                                                           listener: handleIdentifier(, expression)
                                                                         listener: handleNoTypeArguments())
@@ -116,8 +116,8 @@
                                                                   listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
                                                                 rewriter()
                                                               listener: handleExpressionStatement(;)
-                                                    reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-                                                      listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+                                                    reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+                                                      listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
                                                     notEofOrValue(}, ;)
                                                     parseStatement())
                                                       parseStatementX())
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_05.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_05.dart.expect
index cbe4515..aeaa26a 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_05.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_05.dart.expect
@@ -32,5 +32,5 @@
     endTopLevelMethod(void, null, })
   endTopLevelDeclaration()
   handleErrorToken(UnmatchedToken([))
-  handleRecoverableError(Message[UnmatchedToken, Can't find ']' to match '['., null, {string: ], token: [}], UnmatchedToken([), UnmatchedToken([))
+  handleRecoverableError(Message[UnmatchedToken, Can't find ']' to match '['., null, {string: ], lexeme: [}], UnmatchedToken([), UnmatchedToken([))
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_05.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_05.dart.intertwined.expect
index 3bc07e7..3e561c0 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_05.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_05.dart.intertwined.expect
@@ -69,5 +69,5 @@
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(UnmatchedToken([))
     listener: handleErrorToken(UnmatchedToken([))
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ']' to match '['., null, {string: ], token: [}], UnmatchedToken([), UnmatchedToken([))
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ']' to match '['., null, {string: ], lexeme: [}], UnmatchedToken([), UnmatchedToken([))
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.expect
index 9e03ffc..38d9d89 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.expect
@@ -27,7 +27,7 @@
             handleNoConstructorReferenceContinuationAfterTypeArguments(()
           endConstructorReference(C, null, ()
           beginArguments(()
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {token: ;}], ;, ;)
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {lexeme: ;}], ;, ;)
             handleIdentifier(, expression)
             handleNoTypeArguments(;)
             handleNoArguments(;)
@@ -39,5 +39,5 @@
     endTopLevelMethod(main, null, })
   endTopLevelDeclaration()
   handleErrorToken(UnmatchedToken(())
-  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.intertwined.expect
index b87515d..0964dbc 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.intertwined.expect
@@ -57,7 +57,7 @@
                                           parseSend((, expression)
                                             ensureIdentifier((, expression)
                                               reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
-                                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {token: ;}], ;, ;)
+                                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {lexeme: ;}], ;, ;)
                                               rewriter()
                                               listener: handleIdentifier(, expression)
                                             listener: handleNoTypeArguments(;)
@@ -76,5 +76,5 @@
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(UnmatchedToken(())
     listener: handleErrorToken(UnmatchedToken(())
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/comment_on_non_ascii_identifier.dart.expect b/pkg/front_end/parser_testcases/error_recovery/comment_on_non_ascii_identifier.dart.expect
index d241e52..f1f56f6 100644
--- a/pkg/front_end/parser_testcases/error_recovery/comment_on_non_ascii_identifier.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/comment_on_non_ascii_identifier.dart.expect
@@ -101,11 +101,11 @@
     endTopLevelMethod(main, null, })
   endTopLevelDeclaration()
   handleErrorToken(NonAsciiIdentifierToken(230))
-  handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: æ, codePoint: 230}], NonAsciiIdentifierToken(230), NonAsciiIdentifierToken(230))
+  handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: æ, unicode: 230}], NonAsciiIdentifierToken(230), NonAsciiIdentifierToken(230))
   handleErrorToken(NonAsciiIdentifierToken(198))
-  handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'Æ' (U+00C6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: Æ, codePoint: 198}], NonAsciiIdentifierToken(198), NonAsciiIdentifierToken(198))
+  handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'Æ' (U+00C6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: Æ, unicode: 198}], NonAsciiIdentifierToken(198), NonAsciiIdentifierToken(198))
   handleErrorToken(NonAsciiIdentifierToken(230))
-  handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: æ, codePoint: 230}], NonAsciiIdentifierToken(230), NonAsciiIdentifierToken(230))
+  handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: æ, unicode: 230}], NonAsciiIdentifierToken(230), NonAsciiIdentifierToken(230))
   handleErrorToken(NonAsciiIdentifierToken(198))
-  handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'Æ' (U+00C6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: Æ, codePoint: 198}], NonAsciiIdentifierToken(198), NonAsciiIdentifierToken(198))
+  handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'Æ' (U+00C6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: Æ, unicode: 198}], NonAsciiIdentifierToken(198), NonAsciiIdentifierToken(198))
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/comment_on_non_ascii_identifier.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/comment_on_non_ascii_identifier.dart.intertwined.expect
index 7413d26..4c19be1 100644
--- a/pkg/front_end/parser_testcases/error_recovery/comment_on_non_ascii_identifier.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/comment_on_non_ascii_identifier.dart.intertwined.expect
@@ -224,11 +224,11 @@
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(NonAsciiIdentifierToken(230))
     listener: handleErrorToken(NonAsciiIdentifierToken(230))
-    listener: handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: æ, codePoint: 230}], NonAsciiIdentifierToken(230), NonAsciiIdentifierToken(230))
+    listener: handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: æ, unicode: 230}], NonAsciiIdentifierToken(230), NonAsciiIdentifierToken(230))
     listener: handleErrorToken(NonAsciiIdentifierToken(198))
-    listener: handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'Æ' (U+00C6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: Æ, codePoint: 198}], NonAsciiIdentifierToken(198), NonAsciiIdentifierToken(198))
+    listener: handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'Æ' (U+00C6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: Æ, unicode: 198}], NonAsciiIdentifierToken(198), NonAsciiIdentifierToken(198))
     listener: handleErrorToken(NonAsciiIdentifierToken(230))
-    listener: handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: æ, codePoint: 230}], NonAsciiIdentifierToken(230), NonAsciiIdentifierToken(230))
+    listener: handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'æ' (U+00E6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: æ, unicode: 230}], NonAsciiIdentifierToken(230), NonAsciiIdentifierToken(230))
     listener: handleErrorToken(NonAsciiIdentifierToken(198))
-    listener: handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'Æ' (U+00C6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: Æ, codePoint: 198}], NonAsciiIdentifierToken(198), NonAsciiIdentifierToken(198))
+    listener: handleRecoverableError(Message[NonAsciiIdentifier, The non-ASCII character 'Æ' (U+00C6) can't be used in identifiers, only in strings and comments., Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)., {character: Æ, unicode: 198}], NonAsciiIdentifierToken(198), NonAsciiIdentifierToken(198))
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/constructor_recovery_operator.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/constructor_recovery_operator.crash_dart.expect
index 91ce6a3..4a792a7 100644
--- a/pkg/front_end/parser_testcases/error_recovery/constructor_recovery_operator.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/constructor_recovery_operator.crash_dart.expect
@@ -96,7 +96,7 @@
             endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
             handleNoInitializers()
             handleAsyncModifier(null, null)
-            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}], /, /)
+            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}], /, /)
             handleInvalidFunctionBody({)
           endClassConstructor(null, Foo, (, null, })
         endMember()
@@ -137,14 +137,14 @@
             endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
             handleNoInitializers()
             handleAsyncModifier(null, null)
-            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
             handleInvalidFunctionBody({)
           endClassConstructor(null, Foo, (, null, })
         endMember()
         beginMetadataStar(.)
         endMetadataStar(0)
         beginMember()
-          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got '.'., null, {token: .}], ., .)
+          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got '.'., null, {lexeme: .}], ., .)
           handleInvalidMember(.)
         endMember()
         beginMetadataStar(/)
@@ -184,7 +184,7 @@
             endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
             handleNoInitializers()
             handleAsyncModifier(null, null)
-            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}], /, /)
+            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}], /, /)
             handleInvalidFunctionBody({)
           endClassMethod(null, foo, (, null, })
         endMember()
@@ -225,14 +225,14 @@
             endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
             handleNoInitializers()
             handleAsyncModifier(null, null)
-            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
             handleInvalidFunctionBody({)
           endClassMethod(null, foo, (, null, })
         endMember()
         beginMetadataStar(.)
         endMetadataStar(0)
         beginMember()
-          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got '.'., null, {token: .}], ., .)
+          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got '.'., null, {lexeme: .}], ., .)
           handleInvalidMember(.)
         endMember()
         beginMetadataStar(/)
diff --git a/pkg/front_end/parser_testcases/error_recovery/constructor_recovery_operator.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/constructor_recovery_operator.crash_dart.intertwined.expect
index 99def95..3c1d1d2 100644
--- a/pkg/front_end/parser_testcases/error_recovery/constructor_recovery_operator.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/constructor_recovery_operator.crash_dart.intertwined.expect
@@ -54,8 +54,8 @@
                 inPlainSync()
                 parseFunctionBody(), false, true)
                   ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-                    reportRecoverableError(/, Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}])
-                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}], /, /)
+                    reportRecoverableError(/, Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}])
+                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}], /, /)
                     insertBlock())
                       rewriter()
                       rewriter()
@@ -149,8 +149,8 @@
                 inPlainSync()
                 parseFunctionBody(), false, true)
                   ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-                    reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
-                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+                    reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}])
+                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
                     insertBlock())
                       rewriter()
                       rewriter()
@@ -165,7 +165,7 @@
               listener: beginMember()
               recoverFromInvalidMember(}, }, null, null, null, null, null, null, }, Instance of 'NoType', null, DeclarationKind.Class, Foo)
                 reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
-                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got '.'., null, {token: .}], ., .)
+                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got '.'., null, {lexeme: .}], ., .)
                 listener: handleInvalidMember(.)
                 listener: endMember()
             notEofOrValue(}, /)
@@ -255,8 +255,8 @@
                 inPlainSync()
                 parseFunctionBody(), false, true)
                   ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-                    reportRecoverableError(/, Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}])
-                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}], /, /)
+                    reportRecoverableError(/, Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}])
+                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}], /, /)
                     insertBlock())
                       rewriter()
                       rewriter()
@@ -350,8 +350,8 @@
                 inPlainSync()
                 parseFunctionBody(), false, true)
                   ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-                    reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
-                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+                    reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}])
+                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
                     insertBlock())
                       rewriter()
                       rewriter()
@@ -366,7 +366,7 @@
               listener: beginMember()
               recoverFromInvalidMember(}, }, null, null, null, null, null, null, }, Instance of 'NoType', null, DeclarationKind.Class, Foo)
                 reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
-                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got '.'., null, {token: .}], ., .)
+                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got '.'., null, {lexeme: .}], ., .)
                 listener: handleInvalidMember(.)
                 listener: endMember()
             notEofOrValue(}, /)
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
index ed0f16b..5d938b3 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
@@ -29,16 +29,16 @@
       handleAsyncModifier(async, null)
       beginBlockFunctionBody({)
         beginForStatement(for)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
           handleSend(, ))
           handleForInitializerExpressionStatement(, true)
           handleRecoverableError(Message[ExpectedButGot, Expected 'in' before this., null, {string: in}], ), ))
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
           beginForInExpression())
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
             handleIdentifier(, expression)
             handleNoTypeArguments())
             handleNoArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect
index e1a476f..cdf3a58 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect
@@ -42,7 +42,7 @@
                           parseSend((, expression)
                             ensureIdentifier((, expression)
                               reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                               rewriter()
                               listener: handleIdentifier(, expression)
                             listener: handleNoTypeArguments())
@@ -55,7 +55,7 @@
                 parseForInRest(, await, for, ))
                   parseForInLoopPartsRest(, await, for, ))
                     reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                     listener: beginForInExpression())
                     parseExpression(in)
                       parsePrecedenceExpression(in, 1, true)
@@ -64,7 +64,7 @@
                             parseSend(in, expression)
                               ensureIdentifier(in, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
index 3a5b7b2..0affd02 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
@@ -29,14 +29,14 @@
       handleAsyncModifier(null, null)
       beginBlockFunctionBody({)
         beginForStatement(for)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
           handleSend(, ))
           handleForInitializerExpressionStatement(, false)
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect
index 55ccd48..5b5f651 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect
@@ -42,7 +42,7 @@
                           parseSend((, expression)
                             ensureIdentifier((, expression)
                               reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                               rewriter()
                               listener: handleIdentifier(, expression)
                             listener: handleNoTypeArguments())
@@ -64,7 +64,7 @@
                               parseSend(;, expression)
                                 ensureIdentifier(;, expression)
                                   reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                   rewriter()
                                   listener: handleIdentifier(, expression)
                                 listener: handleNoTypeArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
index 6e8b00d..0b3a014 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
@@ -4,10 +4,14 @@
 f() { m(T<R(<Z
               ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_38415.crash:1:15: Expected ';' after this.
 f() { m(T<R(<Z
               ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_38415.crash:1:12: Can't find ')' to match '('.
 f() { m(T<R(<Z
            ^
@@ -53,6 +57,7 @@
                 handleType(Z, null)
               endTypeArguments(1, <, >)
               handleRecoverableError(Message[ExpectedButGot, Expected '[' before this., null, {string: [}], , )
+              // WARNING: Reporting at eof for .
               handleLiteralList(0, [, null, ])
             endArguments(1, (, ))
             handleSend(R, })
@@ -60,16 +65,17 @@
         endArguments(1, (, ))
         handleSend(m, })
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+        // WARNING: Reporting at eof for .
         handleExpressionStatement(;)
       endBlockFunctionBody(1, {, })
     endTopLevelMethod(f, null, })
   endTopLevelDeclaration()
   handleErrorToken(UnmatchedToken(())
-  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
   handleErrorToken(UnmatchedToken(<))
-  handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, token: <}], UnmatchedToken(<), UnmatchedToken(<))
+  handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, lexeme: <}], UnmatchedToken(<), UnmatchedToken(<))
   handleErrorToken(UnmatchedToken(())
-  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
   handleErrorToken(UnmatchedToken({))
-  handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, token: {}], UnmatchedToken({), UnmatchedToken({))
+  handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, lexeme: {}], UnmatchedToken({), UnmatchedToken({))
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect
index 846b118..117af04 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect
@@ -84,6 +84,7 @@
                                                                   listener: endTypeArguments(1, <, >)
                                                                   reportRecoverableError(), Message[ExpectedButGot, Expected '[' before this., null, {string: [}])
                                                                     listener: handleRecoverableError(Message[ExpectedButGot, Expected '[' before this., null, {string: [}], , )
+                                                                    listener: // WARNING: Reporting at eof for .
                                                                   rewriter()
                                                                   parseLiteralListSuffix(>, null)
                                                                     rewriteSquareBrackets(>)
@@ -100,6 +101,7 @@
                   ensureSemicolon())
                     reportRecoverableError([, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
                       listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+                      listener: // WARNING: Reporting at eof for .
                     rewriter()
                   listener: handleExpressionStatement(;)
           notEofOrValue(}, })
@@ -108,11 +110,11 @@
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(UnmatchedToken(())
     listener: handleErrorToken(UnmatchedToken(())
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
     listener: handleErrorToken(UnmatchedToken(<))
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, token: <}], UnmatchedToken(<), UnmatchedToken(<))
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, lexeme: <}], UnmatchedToken(<), UnmatchedToken(<))
     listener: handleErrorToken(UnmatchedToken(())
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
     listener: handleErrorToken(UnmatchedToken({))
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, token: {}], UnmatchedToken({), UnmatchedToken({))
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, lexeme: {}], UnmatchedToken({), UnmatchedToken({))
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
index 6b57708..33f3de8 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
@@ -8,14 +8,20 @@
 n<S e(
       ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39024.crash:1:7: A function declaration needs an explicit list of parameters.
 n<S e(
       ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39024.crash:1:7: Expected a function body, but got ''.
 n<S e(
       ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39024.crash:1:6: Can't find ')' to match '('.
 n<S e(
      ^
@@ -37,19 +43,22 @@
         handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], S, S)
       endTypeArguments(1, <, >)
       handleType(n, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+      // WARNING: Reporting at eof for .
       handleIdentifier(, topLevelFunctionDeclaration)
       handleNoTypeVariables()
       handleRecoverableError(MissingFunctionParameters, , )
+      // WARNING: Reporting at eof for .
       beginFormalParameters((, MemberKind.TopLevelMethod)
       endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
       handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
+      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {lexeme: }], , )
+      // WARNING: Reporting at eof for .
       handleInvalidFunctionBody({)
     endTopLevelMethod(n, null, })
   endTopLevelDeclaration()
   handleErrorToken(UnmatchedToken(())
-  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
   handleErrorToken(UnmatchedToken(<))
-  handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, token: <}], UnmatchedToken(<), UnmatchedToken(<))
+  handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, lexeme: <}], UnmatchedToken(<), UnmatchedToken(<))
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
index ff3cb76..cc9940e 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
@@ -21,9 +21,10 @@
         listener: endTypeArguments(1, <, >)
         listener: handleType(n, null)
         ensureIdentifierPotentiallyRecovered(>, topLevelFunctionDeclaration, false)
-          insertSyntheticIdentifier(>, topLevelFunctionDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
-            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
-              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+          insertSyntheticIdentifier(>, topLevelFunctionDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+              listener: // WARNING: Reporting at eof for .
             rewriter()
           listener: handleIdentifier(, topLevelFunctionDeclaration)
         parseMethodTypeVar()
@@ -32,6 +33,7 @@
           missingParameterMessage(MemberKind.TopLevelMethod)
           reportRecoverableError(, MissingFunctionParameters)
             listener: handleRecoverableError(MissingFunctionParameters, , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
           parseFormalParametersRest((, MemberKind.TopLevelMethod)
             listener: beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -41,8 +43,9 @@
           inPlainSync()
         parseFunctionBody(), false, false)
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
+            reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {lexeme: }])
+              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {lexeme: }], , )
+              listener: // WARNING: Reporting at eof for .
             insertBlock())
               rewriter()
               rewriter()
@@ -51,7 +54,7 @@
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(UnmatchedToken(())
     listener: handleErrorToken(UnmatchedToken(())
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
     listener: handleErrorToken(UnmatchedToken(<))
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, token: <}], UnmatchedToken(<), UnmatchedToken(<))
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, lexeme: <}], UnmatchedToken(<), UnmatchedToken(<))
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
index 5eccfef..6b960ce 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
@@ -8,10 +8,14 @@
 typedef F<Glib.=
                 ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39033.crash:1:17: Expected ';' after this.
 typedef F<Glib.=
                 ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 beginCompilationUnit(typedef)
   beginMetadataStar(typedef)
   endMetadataStar(0)
@@ -28,11 +32,13 @@
         endTypeVariable(., 0, null, null)
         handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], Glib, Glib)
       endTypeVariables(<, >)
-      handleRecoverableError(Message[ExpectedType, Expected a type, but got ''., null, {token: }], , )
+      handleRecoverableError(Message[ExpectedType, Expected a type, but got ''., null, {lexeme: }], , )
+      // WARNING: Reporting at eof for .
       handleIdentifier(, typeReference)
       handleNoTypeArguments()
       handleType(, null)
       handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
     endFunctionTypeAlias(typedef, =, ;)
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect
index 311343c..c85f9e8 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect
@@ -27,7 +27,8 @@
           listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], Glib, Glib)
         listener: endTypeVariables(<, >)
         reportRecoverableErrorWithToken(, Instance of 'Template<(Token) => Message>')
-          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ''., null, {token: }], , )
+          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got ''., null, {lexeme: }], , )
+          listener: // WARNING: Reporting at eof for .
         rewriter()
         listener: handleIdentifier(, typeReference)
         listener: handleNoTypeArguments()
@@ -35,6 +36,7 @@
         ensureSemicolon()
           reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
             listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
         listener: endFunctionTypeAlias(typedef, =, ;)
   listener: endTopLevelDeclaration()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect
index 431957c..11497d9 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect
@@ -20,7 +20,7 @@
   beginMetadataStar({)
   endMetadataStar(0)
   beginTopLevelMember({)
-    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {token: {}], {, {)
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {lexeme: {}], {, {)
     beginBlock({, BlockKind(invalid))
       beginTypeArguments(<)
         handleIdentifier(, typeReference)
@@ -34,9 +34,9 @@
     handleInvalidTopLevelDeclaration(})
   endTopLevelDeclaration()
   handleErrorToken(UnmatchedToken(())
-  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+  handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
   handleErrorToken(UnmatchedToken(<))
-  handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, token: <}], UnmatchedToken(<), UnmatchedToken(<))
+  handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, lexeme: <}], UnmatchedToken(<), UnmatchedToken(<))
   handleErrorToken(UnmatchedToken({))
-  handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, token: {}], UnmatchedToken({), UnmatchedToken({))
+  handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, lexeme: {}], UnmatchedToken({), UnmatchedToken({))
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.intertwined.expect
index feb6d9d..c386263 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.intertwined.expect
@@ -9,7 +9,7 @@
     listener: beginTopLevelMember({)
     parseInvalidTopLevelDeclaration(UnmatchedToken({))
       reportRecoverableErrorWithToken({, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {token: {}], {, {)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {lexeme: {}], {, {)
       parseInvalidBlock(UnmatchedToken({))
         parseBlock(UnmatchedToken({), BlockKind(invalid))
           ensureBlock(UnmatchedToken({), null, null)
@@ -51,9 +51,9 @@
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(UnmatchedToken(())
     listener: handleErrorToken(UnmatchedToken(())
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), token: (}], UnmatchedToken((), UnmatchedToken(())
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
     listener: handleErrorToken(UnmatchedToken(<))
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, token: <}], UnmatchedToken(<), UnmatchedToken(<))
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '>' to match '<'., null, {string: >, lexeme: <}], UnmatchedToken(<), UnmatchedToken(<))
     listener: handleErrorToken(UnmatchedToken({))
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, token: {}], UnmatchedToken({), UnmatchedToken({))
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, lexeme: {}], UnmatchedToken({), UnmatchedToken({))
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect
index b249f5c..e04d438 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect
@@ -8,7 +8,7 @@
   beginMetadataStar({)
   endMetadataStar(0)
   beginTopLevelMember({)
-    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {token: {}], {, {)
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {lexeme: {}], {, {)
     beginBlock({, BlockKind(invalid))
       beginTypeArguments(<)
         handleIdentifier(, typeReference)
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.intertwined.expect
index 41508be..caab7bd 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.intertwined.expect
@@ -9,7 +9,7 @@
     listener: beginTopLevelMember({)
     parseInvalidTopLevelDeclaration()
       reportRecoverableErrorWithToken({, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {token: {}], {, {)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {lexeme: {}], {, {)
       parseInvalidBlock()
         parseBlock(, BlockKind(invalid))
           ensureBlock(, null, null)
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect
index 9d88a31..f1b7c51 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect
@@ -42,7 +42,7 @@
             handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], A, A)
           endVariablesDeclaration(1, ;)
           beginTypeArguments(<)
-            handleRecoverableError(Message[ExpectedType, Expected a type, but got '}'., null, {token: }}], }, })
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got '}'., null, {lexeme: }}], }, })
             handleIdentifier(, typeReference)
             handleNoTypeArguments(})
             handleType(, null)
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.intertwined.expect
index 5c0352c..c6ddd9b 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.intertwined.expect
@@ -70,7 +70,7 @@
                                   parseLiteralListSetMapOrFunction(;, null)
                                     listener: beginTypeArguments(<)
                                     reportRecoverableErrorWithToken(}, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '}'., null, {token: }}], }, })
+                                      listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '}'., null, {lexeme: }}], }, })
                                     rewriter()
                                     listener: handleIdentifier(, typeReference)
                                     listener: handleNoTypeArguments(})
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
index 74d4738..43a90df 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
@@ -24,21 +24,25 @@
 () async => a b < c $? >
                         ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 parser/error_recovery/issue_39202.crash:1:25: Expected ';' after this.
 () async => a b < c $? >
                         ^...
 
+WARNING: Reporting at eof --- see below for details.
+
 beginCompilationUnit(()
   beginMetadataStar(()
   endMetadataStar(0)
   beginTopLevelMember(()
-    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '('., null, {token: (}], (, ()
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '('., null, {lexeme: (}], (, ()
     handleInvalidTopLevelDeclaration(()
   endTopLevelDeclaration())
   beginMetadataStar())
   endMetadataStar(0)
   beginTopLevelMember())
-    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ')'., null, {token: )}], ), ))
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ')'., null, {lexeme: )}], ), ))
     handleInvalidTopLevelDeclaration())
   endTopLevelDeclaration(async)
   beginMetadataStar(async)
@@ -72,10 +76,12 @@
         handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], c, c)
       endTypeArguments(1, <, >)
       handleType(b, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+      // WARNING: Reporting at eof for .
       handleIdentifier(, topLevelVariableDeclaration)
       handleNoFieldInitializer()
       handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
     endTopLevelFields(null, null, null, null, null, 1, b, ;)
   endTopLevelDeclaration()
 endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
index ee3b3ec..9d7c575 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
@@ -9,7 +9,7 @@
     listener: beginTopLevelMember(()
     parseInvalidTopLevelDeclaration()
       reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '('., null, {token: (}], (, ()
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '('., null, {lexeme: (}], (, ()
       listener: handleInvalidTopLevelDeclaration(()
   listener: endTopLevelDeclaration())
   parseTopLevelDeclarationImpl((, Instance of 'DirectiveContext')
@@ -19,7 +19,7 @@
     listener: beginTopLevelMember())
     parseInvalidTopLevelDeclaration(()
       reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ')'., null, {token: )}], ), ))
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ')'., null, {lexeme: )}], ), ))
       listener: handleInvalidTopLevelDeclaration())
   listener: endTopLevelDeclaration(async)
   parseTopLevelDeclarationImpl(), Instance of 'DirectiveContext')
@@ -88,9 +88,10 @@
         listener: endTypeArguments(1, <, >)
         listener: handleType(b, null)
         ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
-          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
-            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
-              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+              listener: // WARNING: Reporting at eof for .
             rewriter()
           listener: handleIdentifier(, topLevelVariableDeclaration)
         parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
@@ -98,6 +99,7 @@
         ensureSemicolon()
           reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
             listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
         listener: endTopLevelFields(null, null, null, null, null, 1, b, ;)
   listener: endTopLevelDeclaration()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect
index ee6d967..dd50f65 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect
@@ -40,7 +40,7 @@
             endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
             handleNoInitializers()
             handleAsyncModifier(null, null)
-            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}], /, /)
+            handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}], /, /)
             handleInvalidFunctionBody({)
           endClassConstructor(null, C, (, null, })
         endMember()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.intertwined.expect
index f3f8e88..e8df55f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.intertwined.expect
@@ -54,8 +54,8 @@
                 inPlainSync()
                 parseFunctionBody(), false, true)
                   ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-                    reportRecoverableError(/, Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}])
-                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {token: /}], /, /)
+                    reportRecoverableError(/, Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}])
+                      listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '/'., null, {lexeme: /}], /, /)
                     insertBlock())
                       rewriter()
                       rewriter()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.expect
index fe48acf..e4aa63a 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.expect
@@ -76,7 +76,7 @@
       handleClassWithClause(with)
       handleClassOrMixinImplements(null, 0)
       handleClassHeader(class, class, null)
-      handleRecoverableError(Message[UnexpectedToken, Unexpected token '>'., null, {token: >}], >, >)
+      handleRecoverableError(Message[UnexpectedToken, Unexpected token '>'., null, {lexeme: >}], >, >)
       handleNoType(>)
       handleClassExtends(null, 1)
       handleClassNoWithClause()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.intertwined.expect
index ae6d79e..6f4bbfe9 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_41265.crash_dart.intertwined.expect
@@ -123,7 +123,7 @@
               parseClassOrMixinImplementsOpt())
             skipUnexpectedTokenOpt(), [extends, with, implements, {])
               reportRecoverableErrorWithToken(>, Instance of 'Template<(Token) => Message>')
-                listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token '>'., null, {token: >}], >, >)
+                listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token '>'., null, {lexeme: >}], >, >)
             parseClassExtendsOpt(>)
               listener: handleNoType(>)
               listener: handleClassExtends(null, 1)
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart
index 39aa295..9604d9e 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart
@@ -1 +1 @@
-Stream<List<>>
\ No newline at end of file
+Stream<List<>> /* nothing here */
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.expect
index 9efa6dc..c04b45f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.expect
@@ -1,40 +1,52 @@
 Problems reported:
 
-parser/error_recovery/issue_42229.crash:1:8: Expected '>' after this.
-Stream<List<>>
-       ^^^^
+parser/error_recovery/issue_42229.crash:1:34: Expected an identifier, but got ''.
+Stream<List<>> /* nothing here */
+                                 ^...
 
-parser/error_recovery/issue_42229.crash:1:1: A function declaration needs an explicit list of parameters.
-Stream<List<>>
-^^^^^^
+WARNING: Reporting at eof --- see below for details.
 
-parser/error_recovery/issue_42229.crash:1:15: Expected a function body, but got ''.
-Stream<List<>>
-              ^...
+parser/error_recovery/issue_42229.crash:1:13: Expected a type, but got '>>'.
+Stream<List<>> /* nothing here */
+            ^^
+
+parser/error_recovery/issue_42229.crash:1:34: Expected an identifier, but got ''.
+Stream<List<>> /* nothing here */
+                                 ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+parser/error_recovery/issue_42229.crash:1:34: Expected ';' after this.
+Stream<List<>> /* nothing here */
+                                 ^...
+
+WARNING: Reporting at eof --- see below for details.
 
 beginCompilationUnit(Stream)
   beginMetadataStar(Stream)
   endMetadataStar(0)
   beginTopLevelMember(Stream)
-    beginTopLevelMethod(, null)
-      handleNoType()
-      handleIdentifier(Stream, topLevelFunctionDeclaration)
-      beginTypeVariables(<)
-        beginMetadataStar(List)
-        endMetadataStar(0)
-        handleIdentifier(List, typeVariableDeclaration)
-        beginTypeVariable(List)
-          handleTypeVariablesDefined(List, 1)
-          handleNoType(List)
-        endTypeVariable(<, 0, null, null)
-        handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-      endTypeVariables(<, )
-      handleRecoverableError(MissingFunctionParameters, Stream, Stream)
-      beginFormalParameters((, MemberKind.TopLevelMethod)
-      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-      handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-      handleInvalidFunctionBody({)
-    endTopLevelMethod(Stream, null, })
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+    // WARNING: Reporting at eof for .
+    beginFields()
+      handleIdentifier(Stream, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {lexeme: >>}], >>, >>)
+          handleIdentifier(, typeReference)
+          handleNoTypeArguments(>>)
+          handleType(, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Stream, null)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+      // WARNING: Reporting at eof for .
+      handleIdentifier(, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
+    endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.intertwined.expect
index 099ee94..25548f5 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.intertwined.expect
@@ -8,50 +8,44 @@
       listener: endMetadataStar(0)
     parseTopLevelMemberImpl()
       listener: beginTopLevelMember(Stream)
-      isReservedKeyword(<)
-      parseTopLevelMethod(, null, , Instance of 'NoType', null, Stream, false)
-        listener: beginTopLevelMethod(, null)
-        listener: handleNoType()
-        ensureIdentifierPotentiallyRecovered(, topLevelFunctionDeclaration, false)
-          listener: handleIdentifier(Stream, topLevelFunctionDeclaration)
-        parseMethodTypeVar(Stream)
-          listener: beginTypeVariables(<)
-          parseMetadataStar(<)
-            listener: beginMetadataStar(List)
-            listener: endMetadataStar(0)
-          ensureIdentifier(<, typeVariableDeclaration)
-            listener: handleIdentifier(List, typeVariableDeclaration)
-          listener: beginTypeVariable(List)
-          listener: handleTypeVariablesDefined(List, 1)
-          listener: handleNoType(List)
-          listener: endTypeVariable(<, 0, null, null)
-          reportRecoverableError(List, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
-            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-          parseMetadataStar(<)
-          ensureIdentifier(<, typeVariableDeclaration)
-            reportRecoverableErrorWithToken(>>, Instance of 'Template<(Token) => Message>')
+      insertSyntheticIdentifier(>, methodDeclaration, message: null, messageOnToken: null)
+        reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+          listener: // WARNING: Reporting at eof for .
+        rewriter()
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', , DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Stream, typeReference)
+        listener: beginTypeArguments(<)
+        ensureIdentifier(<, typeReference)
+          listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        reportRecoverableErrorWithToken(>>, Instance of 'Template<(Token) => Message>')
+          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {lexeme: >>}], >>, >>)
+        rewriter()
+        listener: handleIdentifier(, typeReference)
+        listener: handleNoTypeArguments(>>)
+        listener: handleType(, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Stream, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+              listener: // WARNING: Reporting at eof for .
             rewriter()
-          listener: endTypeVariables(<, )
-        parseGetterOrFormalParameters(, Stream, false, MemberKind.TopLevelMethod)
-          missingParameterMessage(MemberKind.TopLevelMethod)
-          reportRecoverableError(Stream, MissingFunctionParameters)
-            listener: handleRecoverableError(MissingFunctionParameters, Stream, Stream)
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
-          parseFormalParametersRest((, MemberKind.TopLevelMethod)
-            listener: beginFormalParameters((, MemberKind.TopLevelMethod)
-            listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-        parseAsyncModifierOpt())
-          listener: handleAsyncModifier(null, null)
-          inPlainSync()
-        parseFunctionBody(), false, false)
-          ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-            insertBlock())
-              rewriter()
-              rewriter()
-          listener: handleInvalidFunctionBody({)
-        listener: endTopLevelMethod(Stream, null, })
+        listener: endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(Stream)
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.parser.expect
index 96c4fba..8f68d8f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.parser.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.parser.expect
@@ -1,11 +1,5 @@
 NOTICE: Stream was rewritten by parser!
 
-Stream<List<>>>(){}
+Stream<List<>> ;
 
-ERROR: Loop in tokens:  (SimpleToken, EOF, 14)) was seen before (linking to (, SyntheticBeginToken, OPEN_PAREN, 14)!
-
-
-
-Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]>>[SimpleToken][SyntheticStringToken]>[SyntheticToken][SimpleToken]([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken]
-
-ERROR: Loop in tokens:  (SimpleToken, EOF, 14)) was seen before (linking to (, SyntheticBeginToken, OPEN_PAREN, 14)!
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken][SyntheticStringToken]>[SimpleToken]>[SimpleToken] [SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.scanner.expect
index 6ca03d9..6b5fffa 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.scanner.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229.crash_dart.scanner.expect
@@ -1,3 +1,3 @@
-Stream<List<>>
+Stream<List<>> 
 
-Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]>>[SimpleToken][SimpleToken]
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]>>[SimpleToken] [SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.expect
index 0f7bb9e..308e34f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.expect
@@ -1,40 +1,44 @@
 Problems reported:
 
-parser/error_recovery/issue_42229_prime.crash:1:8: Expected '>' after this.
-Stream<List<> >
-       ^^^^
-
-parser/error_recovery/issue_42229_prime.crash:1:1: A function declaration needs an explicit list of parameters.
-Stream<List<> >
-^^^^^^
-
-parser/error_recovery/issue_42229_prime.crash:1:16: Expected a function body, but got ''.
+parser/error_recovery/issue_42229_prime.crash:1:16: Expected an identifier, but got ''.
 Stream<List<> >
                ^...
 
+WARNING: Reporting at eof --- see below for details.
+
+parser/error_recovery/issue_42229_prime.crash:1:13: Expected a type, but got '>'.
+Stream<List<> >
+            ^
+
+parser/error_recovery/issue_42229_prime.crash:1:16: Expected ';' after this.
+Stream<List<> >
+               ^...
+
+WARNING: Reporting at eof --- see below for details.
+
 beginCompilationUnit(Stream)
   beginMetadataStar(Stream)
   endMetadataStar(0)
   beginTopLevelMember(Stream)
-    beginTopLevelMethod(, null)
-      handleNoType()
-      handleIdentifier(Stream, topLevelFunctionDeclaration)
-      beginTypeVariables(<)
-        beginMetadataStar(List)
-        endMetadataStar(0)
-        handleIdentifier(List, typeVariableDeclaration)
-        beginTypeVariable(List)
-          handleTypeVariablesDefined(List, 1)
-          handleNoType(List)
-        endTypeVariable(<, 0, null, null)
-        handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-      endTypeVariables(<, >)
-      handleRecoverableError(MissingFunctionParameters, Stream, Stream)
-      beginFormalParameters((, MemberKind.TopLevelMethod)
-      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-      handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-      handleInvalidFunctionBody({)
-    endTopLevelMethod(Stream, null, })
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+    // WARNING: Reporting at eof for .
+    beginFields()
+      handleIdentifier(Stream, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleRecoverableError(Message[ExpectedType, Expected a type, but got '>'., null, {lexeme: >}], >, >)
+          handleIdentifier(, typeReference)
+          handleNoTypeArguments(>)
+          handleType(, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Stream, null)
+      handleIdentifier(, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
+    endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.intertwined.expect
index a66f17e..3aface3 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.intertwined.expect
@@ -8,50 +8,39 @@
       listener: endMetadataStar(0)
     parseTopLevelMemberImpl()
       listener: beginTopLevelMember(Stream)
-      isReservedKeyword(<)
-      parseTopLevelMethod(, null, , Instance of 'NoType', null, Stream, false)
-        listener: beginTopLevelMethod(, null)
-        listener: handleNoType()
-        ensureIdentifierPotentiallyRecovered(, topLevelFunctionDeclaration, false)
-          listener: handleIdentifier(Stream, topLevelFunctionDeclaration)
-        parseMethodTypeVar(Stream)
-          listener: beginTypeVariables(<)
-          parseMetadataStar(<)
-            listener: beginMetadataStar(List)
-            listener: endMetadataStar(0)
-          ensureIdentifier(<, typeVariableDeclaration)
-            listener: handleIdentifier(List, typeVariableDeclaration)
-          listener: beginTypeVariable(List)
-          listener: handleTypeVariablesDefined(List, 1)
-          listener: handleNoType(List)
-          listener: endTypeVariable(<, 0, null, null)
-          reportRecoverableError(List, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
-            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-          parseMetadataStar(<)
-          ensureIdentifier(<, typeVariableDeclaration)
-            reportRecoverableErrorWithToken(>, Instance of 'Template<(Token) => Message>')
-            rewriter()
-          listener: endTypeVariables(<, >)
-        parseGetterOrFormalParameters(>, Stream, false, MemberKind.TopLevelMethod)
-          missingParameterMessage(MemberKind.TopLevelMethod)
-          reportRecoverableError(Stream, MissingFunctionParameters)
-            listener: handleRecoverableError(MissingFunctionParameters, Stream, Stream)
+      insertSyntheticIdentifier(>, methodDeclaration, message: null, messageOnToken: null)
+        reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+          listener: // WARNING: Reporting at eof for .
+        rewriter()
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', , DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Stream, typeReference)
+        listener: beginTypeArguments(<)
+        ensureIdentifier(<, typeReference)
+          listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        reportRecoverableErrorWithToken(>, Instance of 'Template<(Token) => Message>')
+          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '>'., null, {lexeme: >}], >, >)
+        rewriter()
+        listener: handleIdentifier(, typeReference)
+        listener: handleNoTypeArguments(>)
+        listener: handleType(, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Stream, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
-          parseFormalParametersRest((, MemberKind.TopLevelMethod)
-            listener: beginFormalParameters((, MemberKind.TopLevelMethod)
-            listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-        parseAsyncModifierOpt())
-          listener: handleAsyncModifier(null, null)
-          inPlainSync()
-        parseFunctionBody(), false, false)
-          ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-            insertBlock())
-              rewriter()
-              rewriter()
-          listener: handleInvalidFunctionBody({)
-        listener: endTopLevelMethod(Stream, null, })
+        listener: endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(Stream)
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.parser.expect
index 69e3549..61baa3f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.parser.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime.crash_dart.parser.expect
@@ -1,5 +1,5 @@
 NOTICE: Stream was rewritten by parser!
 
-Stream<List<> >(){}
+Stream<List<> >;
 
-Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken][SyntheticStringToken]>[SimpleToken] >[SimpleToken]([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken][SimpleToken]
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken][SyntheticStringToken]>[SimpleToken] >[SimpleToken][SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_2.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_2.crash_dart.expect
index 7dd3706c..2d08e02 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_2.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_2.crash_dart.expect
@@ -13,7 +13,7 @@
       beginTypeArguments(<)
         handleIdentifier(List, typeReference)
         beginTypeArguments(<)
-          handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {token: >>}], >>, >>)
+          handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {lexeme: >>}], >>, >>)
           handleIdentifier(, typeReference)
           handleNoTypeArguments(>>)
           handleType(, null)
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_2.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_2.crash_dart.intertwined.expect
index 695a462..485e5a0 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_2.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_2.crash_dart.intertwined.expect
@@ -17,7 +17,7 @@
           listener: handleIdentifier(List, typeReference)
         listener: beginTypeArguments(<)
         reportRecoverableErrorWithToken(>>, Instance of 'Template<(Token) => Message>')
-          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {token: >>}], >>, >>)
+          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {lexeme: >>}], >>, >>)
         rewriter()
         listener: handleIdentifier(, typeReference)
         listener: handleNoTypeArguments(>>)
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.expect
index adf4aeb..b9194da 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.expect
@@ -1,40 +1,47 @@
 Problems reported:
 
-parser/error_recovery/issue_42229_prime_3.crash:1:8: Expected '>' after this.
-Stream<List<x>> 
-       ^^^^
-
-parser/error_recovery/issue_42229_prime_3.crash:1:1: A function declaration needs an explicit list of parameters.
-Stream<List<x>> 
-^^^^^^
-
-parser/error_recovery/issue_42229_prime_3.crash:1:17: Expected a function body, but got ''.
+parser/error_recovery/issue_42229_prime_3.crash:1:17: Expected an identifier, but got ''.
 Stream<List<x>> 
                 ^...
 
+WARNING: Reporting at eof --- see below for details.
+
+parser/error_recovery/issue_42229_prime_3.crash:1:17: Expected an identifier, but got ''.
+Stream<List<x>> 
+                ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+parser/error_recovery/issue_42229_prime_3.crash:1:17: Expected ';' after this.
+Stream<List<x>> 
+                ^...
+
+WARNING: Reporting at eof --- see below for details.
+
 beginCompilationUnit(Stream)
   beginMetadataStar(Stream)
   endMetadataStar(0)
   beginTopLevelMember(Stream)
-    beginTopLevelMethod(, null)
-      handleNoType()
-      handleIdentifier(Stream, topLevelFunctionDeclaration)
-      beginTypeVariables(<)
-        beginMetadataStar(List)
-        endMetadataStar(0)
-        handleIdentifier(List, typeVariableDeclaration)
-        beginTypeVariable(List)
-          handleTypeVariablesDefined(List, 1)
-          handleNoType(List)
-        endTypeVariable(<, 0, null, null)
-        handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-      endTypeVariables(<, >)
-      handleRecoverableError(MissingFunctionParameters, Stream, Stream)
-      beginFormalParameters((, MemberKind.TopLevelMethod)
-      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-      handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-      handleInvalidFunctionBody({)
-    endTopLevelMethod(Stream, null, })
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+    // WARNING: Reporting at eof for .
+    beginFields()
+      handleIdentifier(Stream, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleIdentifier(x, typeReference)
+          handleNoTypeArguments(>)
+          handleType(x, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Stream, null)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+      // WARNING: Reporting at eof for .
+      handleIdentifier(, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
+    endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   endTopLevelDeclaration()
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.intertwined.expect
index 12b92e9..69d438c 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.intertwined.expect
@@ -8,46 +8,40 @@
       listener: endMetadataStar(0)
     parseTopLevelMemberImpl()
       listener: beginTopLevelMember(Stream)
-      isReservedKeyword(<)
-      parseTopLevelMethod(, null, , Instance of 'NoType', null, Stream, false)
-        listener: beginTopLevelMethod(, null)
-        listener: handleNoType()
-        ensureIdentifierPotentiallyRecovered(, topLevelFunctionDeclaration, false)
-          listener: handleIdentifier(Stream, topLevelFunctionDeclaration)
-        parseMethodTypeVar(Stream)
-          listener: beginTypeVariables(<)
-          parseMetadataStar(<)
-            listener: beginMetadataStar(List)
-            listener: endMetadataStar(0)
-          ensureIdentifier(<, typeVariableDeclaration)
-            listener: handleIdentifier(List, typeVariableDeclaration)
-          listener: beginTypeVariable(List)
-          listener: handleTypeVariablesDefined(List, 1)
-          listener: handleNoType(List)
-          listener: endTypeVariable(<, 0, null, null)
-          reportRecoverableError(List, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
-            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], List, List)
-          listener: endTypeVariables(<, >)
-        parseGetterOrFormalParameters(>, Stream, false, MemberKind.TopLevelMethod)
-          missingParameterMessage(MemberKind.TopLevelMethod)
-          reportRecoverableError(Stream, MissingFunctionParameters)
-            listener: handleRecoverableError(MissingFunctionParameters, Stream, Stream)
+      insertSyntheticIdentifier(>, methodDeclaration, message: null, messageOnToken: null)
+        reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+          listener: // WARNING: Reporting at eof for .
+        rewriter()
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', , DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Stream, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(x, typeReference)
+        listener: handleNoTypeArguments(>)
+        listener: handleType(x, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Stream, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+              listener: // WARNING: Reporting at eof for .
+            rewriter()
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
           rewriter()
-          parseFormalParametersRest((, MemberKind.TopLevelMethod)
-            listener: beginFormalParameters((, MemberKind.TopLevelMethod)
-            listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
-        parseAsyncModifierOpt())
-          listener: handleAsyncModifier(null, null)
-          inPlainSync()
-        parseFunctionBody(), false, false)
-          ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(, Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
-            insertBlock())
-              rewriter()
-              rewriter()
-          listener: handleInvalidFunctionBody({)
-        listener: endTopLevelMethod(Stream, null, })
+        listener: endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(Stream)
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.parser.expect
index 356a3d2..a3a072f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.parser.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_3.crash_dart.parser.expect
@@ -1,5 +1,5 @@
 NOTICE: Stream was rewritten by parser!
 
-Stream<List<x>> (){}
+Stream<List<x>> ;
 
-Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]x[StringToken]>[SimpleToken]>[SimpleToken] ([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken][SimpleToken]
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]x[StringToken]>[SimpleToken]>[SimpleToken] [SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart
new file mode 100644
index 0000000..c5b7aa3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart
@@ -0,0 +1 @@
+Stream<List<x>> y;
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.expect
new file mode 100644
index 0000000..c639885
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.expect
@@ -0,0 +1,21 @@
+beginCompilationUnit(Stream)
+  beginMetadataStar(Stream)
+  endMetadataStar(0)
+  beginTopLevelMember(Stream)
+    beginFields()
+      handleIdentifier(Stream, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleIdentifier(x, typeReference)
+          handleNoTypeArguments(>)
+          handleType(x, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Stream, null)
+      handleIdentifier(y, topLevelVariableDeclaration)
+      handleNoFieldInitializer(;)
+    endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.intertwined.expect
new file mode 100644
index 0000000..8d42e4b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.intertwined.expect
@@ -0,0 +1,32 @@
+parseUnit(Stream)
+  skipErrorTokens(Stream)
+  listener: beginCompilationUnit(Stream)
+  syntheticPreviousToken(Stream)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(Stream)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(Stream)
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', y, DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Stream, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(x, typeReference)
+        listener: handleNoTypeArguments(>)
+        listener: handleType(x, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Stream, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(y, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(y, y, null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer(;)
+        listener: endTopLevelFields(null, null, null, null, null, 1, Stream, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(Stream)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.parser.expect
new file mode 100644
index 0000000..bfb0cca
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+Stream<List<x>> y;
+
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]x[StringToken]>[SimpleToken]>[SimpleToken] y[StringToken];[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.scanner.expect
new file mode 100644
index 0000000..ece7ab8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_4.crash_dart.scanner.expect
@@ -0,0 +1,3 @@
+Stream<List<x>> y;
+
+Stream[StringToken]<[BeginToken]List[StringToken]<[BeginToken]x[StringToken]>>[SimpleToken] y[StringToken];[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart
new file mode 100644
index 0000000..b6fc4c6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart
@@ -0,0 +1 @@
+hello
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.expect
new file mode 100644
index 0000000..afecf7c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.expect
@@ -0,0 +1,23 @@
+Problems reported:
+
+parser/error_recovery/issue_42229_prime_5:1:1: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+hello
+^^^^^
+
+parser/error_recovery/issue_42229_prime_5:1:1: Expected ';' after this.
+hello
+^^^^^
+
+beginCompilationUnit(hello)
+  beginMetadataStar(hello)
+  endMetadataStar(0)
+  beginTopLevelMember(hello)
+    beginFields()
+      handleRecoverableError(MissingConstFinalVarOrType, hello, hello)
+      handleNoType()
+      handleIdentifier(hello, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], hello, hello)
+    endTopLevelFields(null, null, null, null, null, 1, hello, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.intertwined.expect
new file mode 100644
index 0000000..ed05b5e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.intertwined.expect
@@ -0,0 +1,28 @@
+parseUnit(hello)
+  skipErrorTokens(hello)
+  listener: beginCompilationUnit(hello)
+  syntheticPreviousToken(hello)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(hello)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(hello)
+      isReservedKeyword()
+      parseFields(, null, null, null, null, null, null, , Instance of 'NoType', hello, DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        reportRecoverableError(hello, MissingConstFinalVarOrType)
+          listener: handleRecoverableError(MissingConstFinalVarOrType, hello, hello)
+        listener: handleNoType()
+        ensureIdentifierPotentiallyRecovered(, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(hello, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(hello, hello, null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon(hello)
+          reportRecoverableError(hello, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], hello, hello)
+          rewriter()
+        listener: endTopLevelFields(null, null, null, null, null, 1, hello, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(hello)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.parser.expect
new file mode 100644
index 0000000..0026649
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+hello;
+
+hello[StringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.scanner.expect
new file mode 100644
index 0000000..d26b1f2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_5.dart.scanner.expect
@@ -0,0 +1,3 @@
+hello
+
+hello[StringToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart
new file mode 100644
index 0000000..3aa7912
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart
@@ -0,0 +1 @@
+const foo
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.expect
new file mode 100644
index 0000000..bc06b28
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.expect
@@ -0,0 +1,23 @@
+Problems reported:
+
+parser/error_recovery/issue_42229_prime_6:1:7: The const variable 'foo' must be initialized.
+const foo
+      ^^^
+
+parser/error_recovery/issue_42229_prime_6:1:7: Expected ';' after this.
+const foo
+      ^^^
+
+beginCompilationUnit(const)
+  beginMetadataStar(const)
+  endMetadataStar(0)
+  beginTopLevelMember(const)
+    beginFields()
+      handleNoType(const)
+      handleIdentifier(foo, topLevelVariableDeclaration)
+      handleRecoverableError(Message[ConstFieldWithoutInitializer, The const variable 'foo' must be initialized., Try adding an initializer ('= expression') to the declaration., {name: foo}], foo, foo)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], foo, foo)
+    endTopLevelFields(null, null, null, null, const, 1, const, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.intertwined.expect
new file mode 100644
index 0000000..c70f970
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.intertwined.expect
@@ -0,0 +1,27 @@
+parseUnit(const)
+  skipErrorTokens(const)
+  listener: beginCompilationUnit(const)
+  syntheticPreviousToken(const)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(const)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(const)
+      parseFields(, null, null, null, null, null, const, const, Instance of 'NoType', foo, DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        listener: handleNoType(const)
+        ensureIdentifierPotentiallyRecovered(const, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(foo, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(foo, foo, null, null, null, const, DeclarationKind.TopLevel, null)
+          reportRecoverableError(foo, Message[ConstFieldWithoutInitializer, The const variable 'foo' must be initialized., Try adding an initializer ('= expression') to the declaration., {name: foo}])
+            listener: handleRecoverableError(Message[ConstFieldWithoutInitializer, The const variable 'foo' must be initialized., Try adding an initializer ('= expression') to the declaration., {name: foo}], foo, foo)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon(foo)
+          reportRecoverableError(foo, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], foo, foo)
+          rewriter()
+        listener: endTopLevelFields(null, null, null, null, const, 1, const, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(const)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.parser.expect
new file mode 100644
index 0000000..3b31882
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+const foo;
+
+const[KeywordToken] foo[StringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.scanner.expect
new file mode 100644
index 0000000..35e6c3a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42229_prime_6.dart.scanner.expect
@@ -0,0 +1,3 @@
+const foo
+
+const[KeywordToken] foo[StringToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.expect
index 705b02f..26b7c41 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.expect
@@ -91,7 +91,7 @@
           handleNoArguments([])
           handleSend(foo, [])
           handleEndingBinaryExpression(..)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
           handleIdentifier(, expression)
           handleNoTypeArguments(])
           handleNoArguments(])
@@ -124,7 +124,7 @@
               handleNoArguments([])
               handleSend(foo, [])
               handleEndingBinaryExpression(..)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
               handleIdentifier(, expression)
               handleNoTypeArguments(])
               handleNoArguments(])
@@ -146,7 +146,7 @@
           handleNoArguments([)
           handleSend(foo, [)
           handleEndingBinaryExpression(..)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
           handleIdentifier(, expression)
           handleNoTypeArguments(])
           handleNoArguments(])
@@ -179,7 +179,7 @@
               handleNoArguments([)
               handleSend(foo, [)
               handleEndingBinaryExpression(..)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
               handleIdentifier(, expression)
               handleNoTypeArguments(])
               handleNoArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.intertwined.expect
index 9b81d3a..988b4a5 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.intertwined.expect
@@ -203,7 +203,7 @@
                                   parseSend([, expression)
                                     ensureIdentifier([, expression)
                                       reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
                                       rewriter()
                                       listener: handleIdentifier(, expression)
                                     listener: handleNoTypeArguments(])
@@ -296,7 +296,7 @@
                                                                       parseSend([, expression)
                                                                         ensureIdentifier([, expression)
                                                                           reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
                                                                           rewriter()
                                                                           listener: handleIdentifier(, expression)
                                                                         listener: handleNoTypeArguments(])
@@ -349,7 +349,7 @@
                                   parseSend([, expression)
                                     ensureIdentifier([, expression)
                                       reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
                                       rewriter()
                                       listener: handleIdentifier(, expression)
                                     listener: handleNoTypeArguments(])
@@ -439,7 +439,7 @@
                                                                       parseSend([, expression)
                                                                         ensureIdentifier([, expression)
                                                                           reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
+                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {lexeme: ]}], ], ])
                                                                           rewriter()
                                                                           listener: handleIdentifier(, expression)
                                                                         listener: handleNoTypeArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.expect
index 9919798..07ee768 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.expect
@@ -178,7 +178,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(assert)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
             handleIdentifier(assert, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -218,7 +218,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(break)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
             handleIdentifier(break, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -232,7 +232,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(case)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
             handleIdentifier(case, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -246,7 +246,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(catch)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
             handleIdentifier(catch, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -260,7 +260,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(class)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
             handleIdentifier(class, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -274,7 +274,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(const)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
             handleIdentifier(const, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -288,7 +288,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(continue)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
             handleIdentifier(continue, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -315,7 +315,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(default)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
             handleIdentifier(default, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -342,7 +342,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(do)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
             handleIdentifier(do, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -369,7 +369,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(else)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
             handleIdentifier(else, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -383,7 +383,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(enum)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
             handleIdentifier(enum, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -410,7 +410,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(extends)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
             handleIdentifier(extends, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -463,7 +463,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(false)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
             handleIdentifier(false, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -477,7 +477,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(final)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
             handleIdentifier(final, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -491,7 +491,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(finally)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
             handleIdentifier(finally, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -505,7 +505,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(for)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
             handleIdentifier(for, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -558,7 +558,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(if)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
             handleIdentifier(if, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -598,7 +598,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(in)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
             handleIdentifier(in, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -638,7 +638,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(is)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
             handleIdentifier(is, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -704,7 +704,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(new)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
             handleIdentifier(new, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -718,7 +718,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(null)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
             handleIdentifier(null, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -823,7 +823,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(rethrow)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
             handleIdentifier(rethrow, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -837,7 +837,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(return)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
             handleIdentifier(return, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -903,7 +903,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(super)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
             handleIdentifier(super, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -917,7 +917,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(switch)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
             handleIdentifier(switch, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -944,7 +944,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(this)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
             handleIdentifier(this, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -958,7 +958,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(throw)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
             handleIdentifier(throw, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -972,7 +972,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(true)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
             handleIdentifier(true, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -986,7 +986,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(try)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
             handleIdentifier(try, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -1013,7 +1013,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(var)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
             handleIdentifier(var, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -1027,7 +1027,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(void)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
             handleIdentifier(void, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -1041,7 +1041,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(while)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
             handleIdentifier(while, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -1055,7 +1055,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(with)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
             handleIdentifier(with, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect
index ef8682d..6b24bf7 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect
@@ -89,7 +89,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
                   listener: handleIdentifier(assert, fieldDeclaration)
                 parseFieldInitializerOpt(assert, assert, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -165,7 +165,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
                   listener: handleIdentifier(break, fieldDeclaration)
                 parseFieldInitializerOpt(break, break, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -193,7 +193,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
                   listener: handleIdentifier(case, fieldDeclaration)
                 parseFieldInitializerOpt(case, case, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -221,7 +221,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
                   listener: handleIdentifier(catch, fieldDeclaration)
                 parseFieldInitializerOpt(catch, catch, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -249,7 +249,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
                   listener: handleIdentifier(class, fieldDeclaration)
                 parseFieldInitializerOpt(class, class, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -277,7 +277,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
                   listener: handleIdentifier(const, fieldDeclaration)
                 parseFieldInitializerOpt(const, const, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -305,7 +305,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
                   listener: handleIdentifier(continue, fieldDeclaration)
                 parseFieldInitializerOpt(continue, continue, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -357,7 +357,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
                   listener: handleIdentifier(default, fieldDeclaration)
                 parseFieldInitializerOpt(default, default, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -409,7 +409,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
                   listener: handleIdentifier(do, fieldDeclaration)
                 parseFieldInitializerOpt(do, do, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -461,7 +461,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
                   listener: handleIdentifier(else, fieldDeclaration)
                 parseFieldInitializerOpt(else, else, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -489,7 +489,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
                   listener: handleIdentifier(enum, fieldDeclaration)
                 parseFieldInitializerOpt(enum, enum, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -541,7 +541,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
                   listener: handleIdentifier(extends, fieldDeclaration)
                 parseFieldInitializerOpt(extends, extends, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -641,7 +641,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
                   listener: handleIdentifier(false, fieldDeclaration)
                 parseFieldInitializerOpt(false, false, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -669,7 +669,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
                   listener: handleIdentifier(final, fieldDeclaration)
                 parseFieldInitializerOpt(final, final, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -697,7 +697,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
                   listener: handleIdentifier(finally, fieldDeclaration)
                 parseFieldInitializerOpt(finally, finally, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -725,7 +725,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
                   listener: handleIdentifier(for, fieldDeclaration)
                 parseFieldInitializerOpt(for, for, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -826,7 +826,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
                   listener: handleIdentifier(if, fieldDeclaration)
                 parseFieldInitializerOpt(if, if, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -902,7 +902,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
                   listener: handleIdentifier(in, fieldDeclaration)
                 parseFieldInitializerOpt(in, in, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -978,7 +978,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
                   listener: handleIdentifier(is, fieldDeclaration)
                 parseFieldInitializerOpt(is, is, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1102,7 +1102,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
                   listener: handleIdentifier(new, fieldDeclaration)
                 parseFieldInitializerOpt(new, new, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1130,7 +1130,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
                   listener: handleIdentifier(null, fieldDeclaration)
                 parseFieldInitializerOpt(null, null, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1327,7 +1327,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
                   listener: handleIdentifier(rethrow, fieldDeclaration)
                 parseFieldInitializerOpt(rethrow, rethrow, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1355,7 +1355,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
                   listener: handleIdentifier(return, fieldDeclaration)
                 parseFieldInitializerOpt(return, return, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1480,7 +1480,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
                   listener: handleIdentifier(super, fieldDeclaration)
                 parseFieldInitializerOpt(super, super, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1508,7 +1508,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
                   listener: handleIdentifier(switch, fieldDeclaration)
                 parseFieldInitializerOpt(switch, switch, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1559,7 +1559,7 @@
                   listener: handleType(int, null)
                   ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false)
                     reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
                     listener: handleIdentifier(this, fieldDeclaration)
                   parseFieldInitializerOpt(this, this, null, null, null, null, DeclarationKind.Class, WrapperClass)
                     listener: beginFieldInitializer(=)
@@ -1587,7 +1587,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
                   listener: handleIdentifier(throw, fieldDeclaration)
                 parseFieldInitializerOpt(throw, throw, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1615,7 +1615,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
                   listener: handleIdentifier(true, fieldDeclaration)
                 parseFieldInitializerOpt(true, true, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1643,7 +1643,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
                   listener: handleIdentifier(try, fieldDeclaration)
                 parseFieldInitializerOpt(try, try, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1695,7 +1695,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
                   listener: handleIdentifier(var, fieldDeclaration)
                 parseFieldInitializerOpt(var, var, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1723,7 +1723,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
                   listener: handleIdentifier(void, fieldDeclaration)
                 parseFieldInitializerOpt(void, void, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1751,7 +1751,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
                   listener: handleIdentifier(while, fieldDeclaration)
                 parseFieldInitializerOpt(while, while, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1779,7 +1779,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                   listener: handleIdentifier(with, fieldDeclaration)
                 parseFieldInitializerOpt(with, with, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect
index c3ffe0e..8fcefc7 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect
@@ -608,7 +608,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(assert)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
             handleIdentifier(assert, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -781,7 +781,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(break)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
             handleIdentifier(break, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -814,7 +814,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {token: break}], break, break)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {lexeme: break}], break, break)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(break)
                 handleNoArguments(break)
@@ -846,7 +846,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(case)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
             handleIdentifier(case, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -879,7 +879,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
                 handleIdentifier(case, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -906,7 +906,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(catch)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
             handleIdentifier(catch, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -939,7 +939,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
                 handleIdentifier(catch, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -966,7 +966,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(class)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
             handleIdentifier(class, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -999,7 +999,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
                 handleIdentifier(class, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -1026,7 +1026,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(const)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
             handleIdentifier(const, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1060,7 +1060,7 @@
               endIfStatement(if, null)
               beginReturnStatement(return)
                 beginConstExpression(const)
-                  handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                  handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                   handleIdentifier(, constructorReference)
                   beginConstructorReference()
                     handleNoTypeArguments(()
@@ -1090,7 +1090,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(continue)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
             handleIdentifier(continue, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1123,7 +1123,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {token: continue}], continue, continue)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {lexeme: continue}], continue, continue)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(continue)
                 handleNoArguments(continue)
@@ -1213,7 +1213,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(default)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
             handleIdentifier(default, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1246,7 +1246,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
                 handleIdentifier(default, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -1331,7 +1331,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(do)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
             handleIdentifier(do, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1364,7 +1364,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {token: do}], do, do)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {lexeme: do}], do, do)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(do)
                 handleNoArguments(do)
@@ -1388,7 +1388,7 @@
                 endDoWhileStatementBody(;)
                 handleRecoverableError(Message[ExpectedButGot, Expected 'while' before this., null, {string: while}], }, })
                 handleRecoverableError(Message[ExpectedToken, Expected to find '('., null, {string: (}], }, })
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {lexeme: }}], }, })
                 handleIdentifier(, expression)
                 handleNoTypeArguments())
                 handleNoArguments())
@@ -1464,7 +1464,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(else)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
             handleIdentifier(else, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1497,21 +1497,21 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {lexeme: else}], else, else)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(else)
                 handleNoArguments(else)
                 handleSend(, else)
                 handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], else, else)
               endReturnStatement(true, return, ;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {lexeme: else}], else, else)
               handleIdentifier(, expression)
               handleNoTypeArguments(else)
               handleNoArguments(else)
               handleSend(, else)
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], else, else)
               handleExpressionStatement(;)
-              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], else, else)
+              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], else, else)
               handleIdentifier(x, expression)
               handleNoTypeArguments(-)
               handleNoArguments(-)
@@ -1534,7 +1534,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(enum)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
             handleIdentifier(enum, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1567,7 +1567,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
                 handleIdentifier(enum, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -1652,7 +1652,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(extends)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
             handleIdentifier(extends, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1685,7 +1685,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
                 handleIdentifier(extends, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -1886,7 +1886,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(false)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
             handleIdentifier(false, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1945,7 +1945,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(final)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
             handleIdentifier(final, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1978,7 +1978,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {token: final}], final, final)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {lexeme: final}], final, final)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(final)
                 handleNoArguments(final)
@@ -1989,7 +1989,7 @@
               endMetadataStar(0)
               handleNoType(final)
               beginVariablesDeclaration((, null, final)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                 handleIdentifier(, localVariableDeclaration)
                 beginInitializedIdentifier()
                   handleNoVariableInitializer()
@@ -2005,14 +2005,14 @@
               endBinaryExpression(-)
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
               handleExpressionStatement(;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
               handleIdentifier(, expression)
               handleNoTypeArguments())
               handleNoArguments())
               handleSend(, ))
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
               handleExpressionStatement(;)
-              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
               handleRecoverableError(UnsupportedPrefixPlus, +, +)
               handleIdentifier(, expression)
               handleNoTypeArguments(+)
@@ -2032,7 +2032,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(finally)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
             handleIdentifier(finally, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2065,7 +2065,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
                 handleIdentifier(finally, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -2092,7 +2092,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(for)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
             handleIdentifier(for, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2125,7 +2125,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {token: for}], for, for)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {lexeme: for}], for, for)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(for)
                 handleNoArguments(for)
@@ -2142,7 +2142,7 @@
                 endBinaryExpression(-)
                 handleForInitializerExpressionStatement(1, false)
                 handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                 handleIdentifier(, expression)
                 handleNoTypeArguments())
                 handleNoArguments())
@@ -2346,7 +2346,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(if)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
             handleIdentifier(if, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2379,7 +2379,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {token: if}], if, if)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(if)
                 handleNoArguments(if)
@@ -2533,7 +2533,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(in)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
             handleIdentifier(in, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2566,7 +2566,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
                 handleIdentifier(in, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -2709,7 +2709,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(is)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
             handleIdentifier(is, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2742,13 +2742,13 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {token: is}], is, is)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {lexeme: is}], is, is)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(is)
                 handleNoArguments(is)
                 handleSend(, is)
                 beginIsOperatorType(is)
-                  handleRecoverableError(Message[ExpectedType, Expected a type, but got '('., null, {token: (}], (, ()
+                  handleRecoverableError(Message[ExpectedType, Expected a type, but got '('., null, {lexeme: (}], (, ()
                   handleIdentifier(, typeReference)
                   handleNoTypeArguments(()
                   handleType(, null)
@@ -3010,7 +3010,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(new)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
             handleIdentifier(new, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3044,7 +3044,7 @@
               endIfStatement(if, null)
               beginReturnStatement(return)
                 beginNewExpression(new)
-                  handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                  handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                   handleIdentifier(, constructorReference)
                   beginConstructorReference()
                     handleNoTypeArguments(()
@@ -3074,7 +3074,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(null)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
             handleIdentifier(null, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3539,7 +3539,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(rethrow)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
             handleIdentifier(rethrow, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3572,7 +3572,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
                 handleIdentifier(rethrow, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -3599,7 +3599,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(return)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
             handleIdentifier(return, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3632,7 +3632,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[UnexpectedToken, Unexpected token 'return'., null, {token: return}], return, return)
+                handleRecoverableError(Message[UnexpectedToken, Unexpected token 'return'., null, {lexeme: return}], return, return)
                 handleIdentifier(x, expression)
                 handleNoTypeArguments(-)
                 handleNoArguments(-)
@@ -3887,7 +3887,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(super)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
             handleIdentifier(super, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3946,7 +3946,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(switch)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
             handleIdentifier(switch, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3979,7 +3979,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {token: switch}], switch, switch)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {lexeme: switch}], switch, switch)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(switch)
                 handleNoArguments(switch)
@@ -4076,7 +4076,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(this)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
             handleIdentifier(this, fieldDeclaration)
             handleNoFieldInitializer(()
             handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], this, this)
@@ -4087,7 +4087,7 @@
         beginMember()
           beginMethod(null, null, null, null, null, ()
             handleNoType(;)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
             handleIdentifier(, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4146,7 +4146,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(throw)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
             handleIdentifier(throw, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4202,7 +4202,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(true)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
             handleIdentifier(true, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4261,7 +4261,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(try)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
             handleIdentifier(try, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4294,7 +4294,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {token: try}], try, try)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {lexeme: try}], try, try)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(try)
                 handleNoArguments(try)
@@ -4387,7 +4387,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(var)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
             handleIdentifier(var, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4420,7 +4420,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {token: var}], var, var)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {lexeme: var}], var, var)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(var)
                 handleNoArguments(var)
@@ -4431,7 +4431,7 @@
               endMetadataStar(0)
               handleNoType(var)
               beginVariablesDeclaration((, null, var)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                 handleIdentifier(, localVariableDeclaration)
                 beginInitializedIdentifier()
                   handleNoVariableInitializer()
@@ -4447,14 +4447,14 @@
               endBinaryExpression(-)
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
               handleExpressionStatement(;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
               handleIdentifier(, expression)
               handleNoTypeArguments())
               handleNoArguments())
               handleSend(, ))
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
               handleExpressionStatement(;)
-              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
               handleRecoverableError(UnsupportedPrefixPlus, +, +)
               handleIdentifier(, expression)
               handleNoTypeArguments(+)
@@ -4474,7 +4474,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(void)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
             handleIdentifier(void, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4507,7 +4507,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {token: void}], void, void)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {lexeme: void}], void, void)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(void)
                 handleNoArguments(void)
@@ -4518,7 +4518,7 @@
               endMetadataStar(0)
               handleVoidKeyword(void)
               beginVariablesDeclaration((, null, null)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                 handleIdentifier(, localVariableDeclaration)
                 beginInitializedIdentifier()
                   handleNoVariableInitializer()
@@ -4534,14 +4534,14 @@
               endBinaryExpression(-)
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
               handleExpressionStatement(;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
               handleIdentifier(, expression)
               handleNoTypeArguments())
               handleNoArguments())
               handleSend(, ))
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
               handleExpressionStatement(;)
-              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+              handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
               handleRecoverableError(UnsupportedPrefixPlus, +, +)
               handleIdentifier(, expression)
               handleNoTypeArguments(+)
@@ -4561,7 +4561,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(while)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
             handleIdentifier(while, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4594,7 +4594,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {token: while}], while, while)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {lexeme: while}], while, while)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(while)
                 handleNoArguments(while)
@@ -4632,7 +4632,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(with)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
             handleIdentifier(with, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4665,7 +4665,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                 handleIdentifier(with, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect
index bfd0eb21..a05d812 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect
@@ -323,7 +323,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
                   listener: handleIdentifier(assert, methodDeclaration)
                 parseQualifiedRestOpt(assert, methodDeclarationContinuation)
                 parseMethodTypeVar(assert)
@@ -745,7 +745,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
                   listener: handleIdentifier(break, methodDeclaration)
                 parseQualifiedRestOpt(break, methodDeclarationContinuation)
                 parseMethodTypeVar(break)
@@ -832,7 +832,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {token: break}], break, break)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {lexeme: break}], break, break)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(break)
@@ -921,7 +921,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
                   listener: handleIdentifier(case, methodDeclaration)
                 parseQualifiedRestOpt(case, methodDeclarationContinuation)
                 parseMethodTypeVar(case)
@@ -1008,7 +1008,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
                                     listener: handleIdentifier(case, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(case)
@@ -1065,7 +1065,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
                   listener: handleIdentifier(catch, methodDeclaration)
                 parseQualifiedRestOpt(catch, methodDeclarationContinuation)
                 parseMethodTypeVar(catch)
@@ -1152,7 +1152,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
                                     listener: handleIdentifier(catch, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(catch)
@@ -1209,7 +1209,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
                   listener: handleIdentifier(class, methodDeclaration)
                 parseQualifiedRestOpt(class, methodDeclarationContinuation)
                 parseMethodTypeVar(class)
@@ -1296,7 +1296,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
                                     listener: handleIdentifier(class, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(class)
@@ -1353,7 +1353,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
                   listener: handleIdentifier(const, methodDeclaration)
                 parseQualifiedRestOpt(const, methodDeclarationContinuation)
                 parseMethodTypeVar(const)
@@ -1440,9 +1440,9 @@
                                   listener: beginConstExpression(const)
                                   parseConstructorReference(const, null)
                                     ensureIdentifier(const, constructorReference)
-                                      insertSyntheticIdentifier(const, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], messageOnToken: null)
-                                        reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                                      insertSyntheticIdentifier(const, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], messageOnToken: null)
+                                        reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}])
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                                         rewriter()
                                       listener: handleIdentifier(, constructorReference)
                                     listener: beginConstructorReference()
@@ -1503,7 +1503,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
                   listener: handleIdentifier(continue, methodDeclaration)
                 parseQualifiedRestOpt(continue, methodDeclarationContinuation)
                 parseMethodTypeVar(continue)
@@ -1590,7 +1590,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {token: continue}], continue, continue)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {lexeme: continue}], continue, continue)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(continue)
@@ -1820,7 +1820,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
                   listener: handleIdentifier(default, methodDeclaration)
                 parseQualifiedRestOpt(default, methodDeclarationContinuation)
                 parseMethodTypeVar(default)
@@ -1907,7 +1907,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
                                     listener: handleIdentifier(default, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(default)
@@ -2105,7 +2105,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
                   listener: handleIdentifier(do, methodDeclaration)
                 parseQualifiedRestOpt(do, methodDeclarationContinuation)
                 parseMethodTypeVar(do)
@@ -2192,7 +2192,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {token: do}], do, do)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {lexeme: do}], do, do)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(do)
@@ -2271,7 +2271,7 @@
                                     parseSend((, expression)
                                       ensureIdentifier((, expression)
                                         reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {lexeme: }}], }, })
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments())
@@ -2445,7 +2445,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
                   listener: handleIdentifier(else, methodDeclaration)
                 parseQualifiedRestOpt(else, methodDeclarationContinuation)
                 parseMethodTypeVar(else)
@@ -2532,7 +2532,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {lexeme: else}], else, else)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(else)
@@ -2560,7 +2560,7 @@
                                     parseSend(;, expression)
                                       ensureIdentifier(;, expression)
                                         reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {lexeme: else}], else, else)
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments(else)
@@ -2572,8 +2572,8 @@
                                 listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], else, else)
                               rewriter()
                             listener: handleExpressionStatement(;)
-                  reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-                    listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], else, else)
+                  reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+                    listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], else, else)
                   notEofOrValue(}, ()
                   parseStatement(else)
                     parseStatementX(else)
@@ -2638,7 +2638,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
                   listener: handleIdentifier(enum, methodDeclaration)
                 parseQualifiedRestOpt(enum, methodDeclarationContinuation)
                 parseMethodTypeVar(enum)
@@ -2725,7 +2725,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
                                     listener: handleIdentifier(enum, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(enum)
@@ -2923,7 +2923,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
                   listener: handleIdentifier(extends, methodDeclaration)
                 parseQualifiedRestOpt(extends, methodDeclarationContinuation)
                 parseMethodTypeVar(extends)
@@ -3010,7 +3010,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
                                     listener: handleIdentifier(extends, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(extends)
@@ -3490,7 +3490,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
                   listener: handleIdentifier(false, methodDeclaration)
                 parseQualifiedRestOpt(false, methodDeclarationContinuation)
                 parseMethodTypeVar(false)
@@ -3630,7 +3630,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
                   listener: handleIdentifier(final, methodDeclaration)
                 parseQualifiedRestOpt(final, methodDeclarationContinuation)
                 parseMethodTypeVar(final)
@@ -3717,7 +3717,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {token: final}], final, final)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {lexeme: final}], final, final)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(final)
@@ -3743,7 +3743,7 @@
                           parseOptionallyInitializedIdentifier(final)
                             ensureIdentifier(final, localVariableDeclaration)
                               reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                               rewriter()
                               listener: handleIdentifier(, localVariableDeclaration)
                             listener: beginInitializedIdentifier()
@@ -3799,7 +3799,7 @@
                                     parseSend(;, expression)
                                       ensureIdentifier(;, expression)
                                         reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments())
@@ -3811,8 +3811,8 @@
                                 listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
                               rewriter()
                             listener: handleExpressionStatement(;)
-                  reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-                    listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+                  reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+                    listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
                   notEofOrValue(}, +)
                   parseStatement())
                     parseStatementX())
@@ -3864,7 +3864,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
                   listener: handleIdentifier(finally, methodDeclaration)
                 parseQualifiedRestOpt(finally, methodDeclarationContinuation)
                 parseMethodTypeVar(finally)
@@ -3951,7 +3951,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
                                     listener: handleIdentifier(finally, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(finally)
@@ -4008,7 +4008,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
                   listener: handleIdentifier(for, methodDeclaration)
                 parseQualifiedRestOpt(for, methodDeclarationContinuation)
                 parseMethodTypeVar(for)
@@ -4095,7 +4095,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {token: for}], for, for)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {lexeme: for}], for, for)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(for)
@@ -4151,7 +4151,7 @@
                                       parseSend(;, expression)
                                         ensureIdentifier(;, expression)
                                           reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                           rewriter()
                                           listener: handleIdentifier(, expression)
                                         listener: handleNoTypeArguments())
@@ -4641,7 +4641,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
                   listener: handleIdentifier(if, methodDeclaration)
                 parseQualifiedRestOpt(if, methodDeclarationContinuation)
                 parseMethodTypeVar(if)
@@ -4728,7 +4728,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {token: if}], if, if)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(if)
@@ -5104,7 +5104,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
                   listener: handleIdentifier(in, methodDeclaration)
                 parseQualifiedRestOpt(in, methodDeclarationContinuation)
                 parseMethodTypeVar(in)
@@ -5191,7 +5191,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
                                     listener: handleIdentifier(in, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(in)
@@ -5530,7 +5530,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
                   listener: handleIdentifier(is, methodDeclaration)
                 parseQualifiedRestOpt(is, methodDeclarationContinuation)
                 parseMethodTypeVar(is)
@@ -5617,7 +5617,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {token: is}], is, is)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {lexeme: is}], is, is)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(is)
@@ -5628,7 +5628,7 @@
                               listener: beginIsOperatorType(is)
                               computeTypeAfterIsOrAs(is)
                               reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '('., null, {token: (}], (, ()
+                                listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '('., null, {lexeme: (}], (, ()
                               rewriter()
                               listener: handleIdentifier(, typeReference)
                               listener: handleNoTypeArguments(()
@@ -6270,7 +6270,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
                   listener: handleIdentifier(new, methodDeclaration)
                 parseQualifiedRestOpt(new, methodDeclarationContinuation)
                 parseMethodTypeVar(new)
@@ -6357,9 +6357,9 @@
                                   listener: beginNewExpression(new)
                                   parseConstructorReference(new, null)
                                     ensureIdentifier(new, constructorReference)
-                                      insertSyntheticIdentifier(new, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], messageOnToken: null)
-                                        reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                                      insertSyntheticIdentifier(new, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], messageOnToken: null)
+                                        reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}])
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                                         rewriter()
                                       listener: handleIdentifier(, constructorReference)
                                     listener: beginConstructorReference()
@@ -6420,7 +6420,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
                   listener: handleIdentifier(null, methodDeclaration)
                 parseQualifiedRestOpt(null, methodDeclarationContinuation)
                 parseMethodTypeVar(null)
@@ -7549,7 +7549,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
                   listener: handleIdentifier(rethrow, methodDeclaration)
                 parseQualifiedRestOpt(rethrow, methodDeclarationContinuation)
                 parseMethodTypeVar(rethrow)
@@ -7636,7 +7636,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
                                     listener: handleIdentifier(rethrow, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(rethrow)
@@ -7693,7 +7693,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
                   listener: handleIdentifier(return, methodDeclaration)
                 parseQualifiedRestOpt(return, methodDeclarationContinuation)
                 parseMethodTypeVar(return)
@@ -7778,7 +7778,7 @@
                               parsePrimary(return, expression)
                                 inPlainSync()
                                 reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token 'return'., null, {token: return}], return, return)
+                                  listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token 'return'., null, {lexeme: return}], return, return)
                                 parsePrimary(return, expression)
                                   parseParenthesizedExpressionOrFunctionLiteral(return)
                                     parseParenthesizedExpression(return)
@@ -8399,7 +8399,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
                   listener: handleIdentifier(super, methodDeclaration)
                 parseQualifiedRestOpt(super, methodDeclarationContinuation)
                 parseMethodTypeVar(super)
@@ -8538,7 +8538,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
                   listener: handleIdentifier(switch, methodDeclaration)
                 parseQualifiedRestOpt(switch, methodDeclarationContinuation)
                 parseMethodTypeVar(switch)
@@ -8625,7 +8625,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {token: switch}], switch, switch)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {lexeme: switch}], switch, switch)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(switch)
@@ -8868,7 +8868,7 @@
                   listener: handleType(int, null)
                   ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false)
                     reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
                     listener: handleIdentifier(this, fieldDeclaration)
                   parseFieldInitializerOpt(this, this, null, null, null, null, DeclarationKind.Class, WrapperClass)
                     listener: handleNoFieldInitializer(()
@@ -8890,8 +8890,8 @@
                   listener: handleNoType(;)
                   ensureIdentifierPotentiallyRecovered(;, methodDeclaration, false)
                     insertSyntheticIdentifier(;, methodDeclaration, message: null, messageOnToken: null)
-                      reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
-                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                      reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}])
+                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                       rewriter()
                     listener: handleIdentifier(, methodDeclaration)
                   parseQualifiedRestOpt(, methodDeclarationContinuation)
@@ -9031,7 +9031,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
                   listener: handleIdentifier(throw, methodDeclaration)
                 parseQualifiedRestOpt(throw, methodDeclarationContinuation)
                 parseMethodTypeVar(throw)
@@ -9171,7 +9171,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
                   listener: handleIdentifier(true, methodDeclaration)
                 parseQualifiedRestOpt(true, methodDeclarationContinuation)
                 parseMethodTypeVar(true)
@@ -9311,7 +9311,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
                   listener: handleIdentifier(try, methodDeclaration)
                 parseQualifiedRestOpt(try, methodDeclarationContinuation)
                 parseMethodTypeVar(try)
@@ -9398,7 +9398,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {token: try}], try, try)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {lexeme: try}], try, try)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(try)
@@ -9634,7 +9634,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
                   listener: handleIdentifier(var, methodDeclaration)
                 parseQualifiedRestOpt(var, methodDeclarationContinuation)
                 parseMethodTypeVar(var)
@@ -9721,7 +9721,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {token: var}], var, var)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {lexeme: var}], var, var)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(var)
@@ -9747,7 +9747,7 @@
                           parseOptionallyInitializedIdentifier(var)
                             ensureIdentifier(var, localVariableDeclaration)
                               reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                               rewriter()
                               listener: handleIdentifier(, localVariableDeclaration)
                             listener: beginInitializedIdentifier()
@@ -9803,7 +9803,7 @@
                                     parseSend(;, expression)
                                       ensureIdentifier(;, expression)
                                         reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments())
@@ -9815,8 +9815,8 @@
                                 listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
                               rewriter()
                             listener: handleExpressionStatement(;)
-                  reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-                    listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+                  reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+                    listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
                   notEofOrValue(}, +)
                   parseStatement())
                     parseStatementX())
@@ -9868,7 +9868,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
                   listener: handleIdentifier(void, methodDeclaration)
                 parseQualifiedRestOpt(void, methodDeclarationContinuation)
                 parseMethodTypeVar(void)
@@ -9955,7 +9955,7 @@
                                   parseSend(return, expression)
                                     ensureIdentifier(return, expression)
                                       reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {token: void}], void, void)
+                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {lexeme: void}], void, void)
                                       rewriter()
                                       listener: handleIdentifier(, expression)
                                     listener: handleNoTypeArguments(void)
@@ -9982,7 +9982,7 @@
                             parseOptionallyInitializedIdentifier(void)
                               ensureIdentifier(void, localVariableDeclaration)
                                 reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                                 rewriter()
                                 listener: handleIdentifier(, localVariableDeclaration)
                               listener: beginInitializedIdentifier()
@@ -10038,7 +10038,7 @@
                                     parseSend(;, expression)
                                       ensureIdentifier(;, expression)
                                         reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments())
@@ -10050,8 +10050,8 @@
                                 listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
                               rewriter()
                             listener: handleExpressionStatement(;)
-                  reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-                    listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+                  reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+                    listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
                   notEofOrValue(}, +)
                   parseStatement())
                     parseStatementX())
@@ -10103,7 +10103,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
                   listener: handleIdentifier(while, methodDeclaration)
                 parseQualifiedRestOpt(while, methodDeclarationContinuation)
                 parseMethodTypeVar(while)
@@ -10190,7 +10190,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {token: while}], while, while)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {lexeme: while}], while, while)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(while)
@@ -10284,7 +10284,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                   listener: handleIdentifier(with, methodDeclaration)
                 parseQualifiedRestOpt(with, methodDeclarationContinuation)
                 parseMethodTypeVar(with)
@@ -10371,7 +10371,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                                     listener: handleIdentifier(with, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(with)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.expect
index c634476..acdbaf9 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.expect
@@ -166,7 +166,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(assert)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
       handleIdentifier(assert, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -206,7 +206,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(break)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
       handleIdentifier(break, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -220,7 +220,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(case)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
       handleIdentifier(case, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -234,7 +234,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(catch)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
       handleIdentifier(catch, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -248,7 +248,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(class)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
       handleIdentifier(class, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -262,7 +262,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(const)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
       handleIdentifier(const, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -276,7 +276,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(continue)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
       handleIdentifier(continue, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -303,7 +303,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(default)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
       handleIdentifier(default, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -330,7 +330,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(do)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
       handleIdentifier(do, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -357,7 +357,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(else)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
       handleIdentifier(else, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -371,7 +371,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(enum)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
       handleIdentifier(enum, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -398,7 +398,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(extends)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
       handleIdentifier(extends, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -451,7 +451,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(false)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
       handleIdentifier(false, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -465,7 +465,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(final)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
       handleIdentifier(final, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -479,7 +479,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(finally)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
       handleIdentifier(finally, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -493,7 +493,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(for)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
       handleIdentifier(for, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -546,7 +546,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(if)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
       handleIdentifier(if, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -586,7 +586,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(in)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
       handleIdentifier(in, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -626,7 +626,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(is)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
       handleIdentifier(is, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -692,7 +692,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(new)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
       handleIdentifier(new, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -706,7 +706,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(null)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
       handleIdentifier(null, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -811,7 +811,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(rethrow)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
       handleIdentifier(rethrow, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -825,7 +825,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(return)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
       handleIdentifier(return, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -891,7 +891,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(super)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
       handleIdentifier(super, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -905,7 +905,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(switch)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
       handleIdentifier(switch, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -932,7 +932,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(this)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
       handleIdentifier(this, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -946,7 +946,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(throw)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
       handleIdentifier(throw, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -960,7 +960,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(true)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
       handleIdentifier(true, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -974,7 +974,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(try)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
       handleIdentifier(try, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -1001,7 +1001,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(var)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
       handleIdentifier(var, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -1015,7 +1015,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(void)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
       handleIdentifier(void, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -1029,7 +1029,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(while)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
       handleIdentifier(while, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -1043,7 +1043,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(with)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
       handleIdentifier(with, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.intertwined.expect
index b6db767..3177f42 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.intertwined.expect
@@ -65,7 +65,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
           listener: handleIdentifier(assert, topLevelVariableDeclaration)
         parseFieldInitializerOpt(assert, assert, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -141,7 +141,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
           listener: handleIdentifier(break, topLevelVariableDeclaration)
         parseFieldInitializerOpt(break, break, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -169,7 +169,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
           listener: handleIdentifier(case, topLevelVariableDeclaration)
         parseFieldInitializerOpt(case, case, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -197,7 +197,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
           listener: handleIdentifier(catch, topLevelVariableDeclaration)
         parseFieldInitializerOpt(catch, catch, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -225,7 +225,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
           listener: handleIdentifier(class, topLevelVariableDeclaration)
         parseFieldInitializerOpt(class, class, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -253,7 +253,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
           listener: handleIdentifier(const, topLevelVariableDeclaration)
         parseFieldInitializerOpt(const, const, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -281,7 +281,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
           listener: handleIdentifier(continue, topLevelVariableDeclaration)
         parseFieldInitializerOpt(continue, continue, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -333,7 +333,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
           listener: handleIdentifier(default, topLevelVariableDeclaration)
         parseFieldInitializerOpt(default, default, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -385,7 +385,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
           listener: handleIdentifier(do, topLevelVariableDeclaration)
         parseFieldInitializerOpt(do, do, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -437,7 +437,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
           listener: handleIdentifier(else, topLevelVariableDeclaration)
         parseFieldInitializerOpt(else, else, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -465,7 +465,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
           listener: handleIdentifier(enum, topLevelVariableDeclaration)
         parseFieldInitializerOpt(enum, enum, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -517,7 +517,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
           listener: handleIdentifier(extends, topLevelVariableDeclaration)
         parseFieldInitializerOpt(extends, extends, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -617,7 +617,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
           listener: handleIdentifier(false, topLevelVariableDeclaration)
         parseFieldInitializerOpt(false, false, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -645,7 +645,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
           listener: handleIdentifier(final, topLevelVariableDeclaration)
         parseFieldInitializerOpt(final, final, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -673,7 +673,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
           listener: handleIdentifier(finally, topLevelVariableDeclaration)
         parseFieldInitializerOpt(finally, finally, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -701,7 +701,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
           listener: handleIdentifier(for, topLevelVariableDeclaration)
         parseFieldInitializerOpt(for, for, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -801,7 +801,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
           listener: handleIdentifier(if, topLevelVariableDeclaration)
         parseFieldInitializerOpt(if, if, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -877,7 +877,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
           listener: handleIdentifier(in, topLevelVariableDeclaration)
         parseFieldInitializerOpt(in, in, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -953,7 +953,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
           listener: handleIdentifier(is, topLevelVariableDeclaration)
         parseFieldInitializerOpt(is, is, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1077,7 +1077,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
           listener: handleIdentifier(new, topLevelVariableDeclaration)
         parseFieldInitializerOpt(new, new, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1105,7 +1105,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
           listener: handleIdentifier(null, topLevelVariableDeclaration)
         parseFieldInitializerOpt(null, null, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1301,7 +1301,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
           listener: handleIdentifier(rethrow, topLevelVariableDeclaration)
         parseFieldInitializerOpt(rethrow, rethrow, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1329,7 +1329,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
           listener: handleIdentifier(return, topLevelVariableDeclaration)
         parseFieldInitializerOpt(return, return, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1453,7 +1453,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
           listener: handleIdentifier(super, topLevelVariableDeclaration)
         parseFieldInitializerOpt(super, super, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1481,7 +1481,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
           listener: handleIdentifier(switch, topLevelVariableDeclaration)
         parseFieldInitializerOpt(switch, switch, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1531,7 +1531,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, false)
           reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
           listener: handleIdentifier(this, topLevelVariableDeclaration)
         parseFieldInitializerOpt(this, this, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1559,7 +1559,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
           listener: handleIdentifier(throw, topLevelVariableDeclaration)
         parseFieldInitializerOpt(throw, throw, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1587,7 +1587,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
           listener: handleIdentifier(true, topLevelVariableDeclaration)
         parseFieldInitializerOpt(true, true, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1615,7 +1615,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
           listener: handleIdentifier(try, topLevelVariableDeclaration)
         parseFieldInitializerOpt(try, try, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1667,7 +1667,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
           listener: handleIdentifier(var, topLevelVariableDeclaration)
         parseFieldInitializerOpt(var, var, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1695,7 +1695,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
           listener: handleIdentifier(void, topLevelVariableDeclaration)
         parseFieldInitializerOpt(void, void, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1723,7 +1723,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
           listener: handleIdentifier(while, topLevelVariableDeclaration)
         parseFieldInitializerOpt(while, while, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1751,7 +1751,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
           listener: handleIdentifier(with, topLevelVariableDeclaration)
         parseFieldInitializerOpt(with, with, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.expect
index ab9b7d5..0c446fc 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.expect
@@ -586,7 +586,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(assert)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
       handleIdentifier(assert, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -756,7 +756,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(break)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
       handleIdentifier(break, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -788,7 +788,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {token: break}], break, break)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {lexeme: break}], break, break)
           handleIdentifier(, expression)
           handleNoTypeArguments(break)
           handleNoArguments(break)
@@ -820,7 +820,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(case)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
       handleIdentifier(case, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -852,7 +852,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
           handleIdentifier(case, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -879,7 +879,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(catch)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
       handleIdentifier(catch, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -911,7 +911,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
           handleIdentifier(catch, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -938,7 +938,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(class)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
       handleIdentifier(class, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -970,7 +970,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
           handleIdentifier(class, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -997,7 +997,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(const)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
       handleIdentifier(const, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1030,7 +1030,7 @@
         endIfStatement(if, null)
         beginReturnStatement(return)
           beginConstExpression(const)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
             handleIdentifier(, constructorReference)
             beginConstructorReference()
               handleNoTypeArguments(()
@@ -1060,7 +1060,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(continue)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
       handleIdentifier(continue, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1092,7 +1092,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {token: continue}], continue, continue)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {lexeme: continue}], continue, continue)
           handleIdentifier(, expression)
           handleNoTypeArguments(continue)
           handleNoArguments(continue)
@@ -1181,7 +1181,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(default)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
       handleIdentifier(default, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1213,7 +1213,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
           handleIdentifier(default, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -1297,7 +1297,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(do)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
       handleIdentifier(do, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1329,7 +1329,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {token: do}], do, do)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {lexeme: do}], do, do)
           handleIdentifier(, expression)
           handleNoTypeArguments(do)
           handleNoArguments(do)
@@ -1353,7 +1353,7 @@
           endDoWhileStatementBody(;)
           handleRecoverableError(Message[ExpectedButGot, Expected 'while' before this., null, {string: while}], }, })
           handleRecoverableError(Message[ExpectedToken, Expected to find '('., null, {string: (}], }, })
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {lexeme: }}], }, })
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
@@ -1428,7 +1428,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(else)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
       handleIdentifier(else, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1460,21 +1460,21 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {lexeme: else}], else, else)
           handleIdentifier(, expression)
           handleNoTypeArguments(else)
           handleNoArguments(else)
           handleSend(, else)
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], else, else)
         endReturnStatement(true, return, ;)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {lexeme: else}], else, else)
         handleIdentifier(, expression)
         handleNoTypeArguments(else)
         handleNoArguments(else)
         handleSend(, else)
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], else, else)
         handleExpressionStatement(;)
-        handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], else, else)
+        handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], else, else)
         handleIdentifier(x, expression)
         handleNoTypeArguments(-)
         handleNoArguments(-)
@@ -1497,7 +1497,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(enum)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
       handleIdentifier(enum, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1529,7 +1529,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
           handleIdentifier(enum, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -1613,7 +1613,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(extends)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
       handleIdentifier(extends, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1645,7 +1645,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
           handleIdentifier(extends, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -1843,7 +1843,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(false)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
       handleIdentifier(false, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1901,7 +1901,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(final)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
       handleIdentifier(final, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1933,7 +1933,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {token: final}], final, final)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {lexeme: final}], final, final)
           handleIdentifier(, expression)
           handleNoTypeArguments(final)
           handleNoArguments(final)
@@ -1944,7 +1944,7 @@
         endMetadataStar(0)
         handleNoType(final)
         beginVariablesDeclaration((, null, final)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
           handleIdentifier(, localVariableDeclaration)
           beginInitializedIdentifier()
             handleNoVariableInitializer()
@@ -1960,14 +1960,14 @@
         endBinaryExpression(-)
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
         handleExpressionStatement(;)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
         handleIdentifier(, expression)
         handleNoTypeArguments())
         handleNoArguments())
         handleSend(, ))
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
         handleExpressionStatement(;)
-        handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+        handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
         handleRecoverableError(UnsupportedPrefixPlus, +, +)
         handleIdentifier(, expression)
         handleNoTypeArguments(+)
@@ -1987,7 +1987,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(finally)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
       handleIdentifier(finally, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2019,7 +2019,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
           handleIdentifier(finally, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -2046,7 +2046,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(for)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
       handleIdentifier(for, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2078,7 +2078,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {token: for}], for, for)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {lexeme: for}], for, for)
           handleIdentifier(, expression)
           handleNoTypeArguments(for)
           handleNoArguments(for)
@@ -2095,7 +2095,7 @@
           endBinaryExpression(-)
           handleForInitializerExpressionStatement(1, false)
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
@@ -2296,7 +2296,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(if)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
       handleIdentifier(if, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2328,7 +2328,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {token: if}], if, if)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
           handleIdentifier(, expression)
           handleNoTypeArguments(if)
           handleNoArguments(if)
@@ -2480,7 +2480,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(in)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
       handleIdentifier(in, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2512,7 +2512,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
           handleIdentifier(in, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -2653,7 +2653,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(is)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
       handleIdentifier(is, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2685,13 +2685,13 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {token: is}], is, is)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {lexeme: is}], is, is)
           handleIdentifier(, expression)
           handleNoTypeArguments(is)
           handleNoArguments(is)
           handleSend(, is)
           beginIsOperatorType(is)
-            handleRecoverableError(Message[ExpectedType, Expected a type, but got '('., null, {token: (}], (, ()
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got '('., null, {lexeme: (}], (, ()
             handleIdentifier(, typeReference)
             handleNoTypeArguments(()
             handleType(, null)
@@ -2949,7 +2949,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(new)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
       handleIdentifier(new, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2982,7 +2982,7 @@
         endIfStatement(if, null)
         beginReturnStatement(return)
           beginNewExpression(new)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
             handleIdentifier(, constructorReference)
             beginConstructorReference()
               handleNoTypeArguments(()
@@ -3012,7 +3012,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(null)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
       handleIdentifier(null, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3469,7 +3469,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(rethrow)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
       handleIdentifier(rethrow, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3501,7 +3501,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
           handleIdentifier(rethrow, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -3528,7 +3528,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(return)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
       handleIdentifier(return, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3560,7 +3560,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[UnexpectedToken, Unexpected token 'return'., null, {token: return}], return, return)
+          handleRecoverableError(Message[UnexpectedToken, Unexpected token 'return'., null, {lexeme: return}], return, return)
           handleIdentifier(x, expression)
           handleNoTypeArguments(-)
           handleNoArguments(-)
@@ -3811,7 +3811,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(super)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
       handleIdentifier(super, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3869,7 +3869,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(switch)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
       handleIdentifier(switch, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3901,7 +3901,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {token: switch}], switch, switch)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {lexeme: switch}], switch, switch)
           handleIdentifier(, expression)
           handleNoTypeArguments(switch)
           handleNoArguments(switch)
@@ -3997,7 +3997,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(this)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
       handleIdentifier(this, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4055,7 +4055,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(throw)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
       handleIdentifier(throw, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4110,7 +4110,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(true)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
       handleIdentifier(true, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4168,7 +4168,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(try)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
       handleIdentifier(try, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4200,7 +4200,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {token: try}], try, try)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {lexeme: try}], try, try)
           handleIdentifier(, expression)
           handleNoTypeArguments(try)
           handleNoArguments(try)
@@ -4292,7 +4292,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(var)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
       handleIdentifier(var, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4324,7 +4324,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {token: var}], var, var)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {lexeme: var}], var, var)
           handleIdentifier(, expression)
           handleNoTypeArguments(var)
           handleNoArguments(var)
@@ -4335,7 +4335,7 @@
         endMetadataStar(0)
         handleNoType(var)
         beginVariablesDeclaration((, null, var)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
           handleIdentifier(, localVariableDeclaration)
           beginInitializedIdentifier()
             handleNoVariableInitializer()
@@ -4351,14 +4351,14 @@
         endBinaryExpression(-)
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
         handleExpressionStatement(;)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
         handleIdentifier(, expression)
         handleNoTypeArguments())
         handleNoArguments())
         handleSend(, ))
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
         handleExpressionStatement(;)
-        handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+        handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
         handleRecoverableError(UnsupportedPrefixPlus, +, +)
         handleIdentifier(, expression)
         handleNoTypeArguments(+)
@@ -4378,7 +4378,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(void)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
       handleIdentifier(void, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4410,7 +4410,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {token: void}], void, void)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {lexeme: void}], void, void)
           handleIdentifier(, expression)
           handleNoTypeArguments(void)
           handleNoArguments(void)
@@ -4421,7 +4421,7 @@
         endMetadataStar(0)
         handleVoidKeyword(void)
         beginVariablesDeclaration((, null, null)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
           handleIdentifier(, localVariableDeclaration)
           beginInitializedIdentifier()
             handleNoVariableInitializer()
@@ -4437,14 +4437,14 @@
         endBinaryExpression(-)
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
         handleExpressionStatement(;)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
         handleIdentifier(, expression)
         handleNoTypeArguments())
         handleNoArguments())
         handleSend(, ))
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
         handleExpressionStatement(;)
-        handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+        handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
         handleRecoverableError(UnsupportedPrefixPlus, +, +)
         handleIdentifier(, expression)
         handleNoTypeArguments(+)
@@ -4464,7 +4464,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(while)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
       handleIdentifier(while, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4496,7 +4496,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {token: while}], while, while)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {lexeme: while}], while, while)
           handleIdentifier(, expression)
           handleNoTypeArguments(while)
           handleNoArguments(while)
@@ -4534,7 +4534,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(with)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
       handleIdentifier(with, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4566,7 +4566,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
           handleIdentifier(with, expression)
           handleNoTypeArguments(()
           beginArguments(()
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.intertwined.expect
index 1ce425d..9328908 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.intertwined.expect
@@ -291,7 +291,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
           listener: handleIdentifier(assert, topLevelFunctionDeclaration)
         parseMethodTypeVar(assert)
           listener: handleNoTypeVariables(()
@@ -701,7 +701,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
           listener: handleIdentifier(break, topLevelFunctionDeclaration)
         parseMethodTypeVar(break)
           listener: handleNoTypeVariables(()
@@ -784,7 +784,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {token: break}], break, break)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {lexeme: break}], break, break)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(break)
@@ -873,7 +873,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
           listener: handleIdentifier(case, topLevelFunctionDeclaration)
         parseMethodTypeVar(case)
           listener: handleNoTypeVariables(()
@@ -956,7 +956,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
                             listener: handleIdentifier(case, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(case)
@@ -1013,7 +1013,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
           listener: handleIdentifier(catch, topLevelFunctionDeclaration)
         parseMethodTypeVar(catch)
           listener: handleNoTypeVariables(()
@@ -1096,7 +1096,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
                             listener: handleIdentifier(catch, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(catch)
@@ -1153,7 +1153,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
           listener: handleIdentifier(class, topLevelFunctionDeclaration)
         parseMethodTypeVar(class)
           listener: handleNoTypeVariables(()
@@ -1236,7 +1236,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
                             listener: handleIdentifier(class, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(class)
@@ -1293,7 +1293,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
           listener: handleIdentifier(const, topLevelFunctionDeclaration)
         parseMethodTypeVar(const)
           listener: handleNoTypeVariables(()
@@ -1376,9 +1376,9 @@
                           listener: beginConstExpression(const)
                           parseConstructorReference(const, null)
                             ensureIdentifier(const, constructorReference)
-                              insertSyntheticIdentifier(const, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], messageOnToken: null)
-                                reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                              insertSyntheticIdentifier(const, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], messageOnToken: null)
+                                reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}])
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                                 rewriter()
                               listener: handleIdentifier(, constructorReference)
                             listener: beginConstructorReference()
@@ -1439,7 +1439,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
           listener: handleIdentifier(continue, topLevelFunctionDeclaration)
         parseMethodTypeVar(continue)
           listener: handleNoTypeVariables(()
@@ -1522,7 +1522,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {token: continue}], continue, continue)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {lexeme: continue}], continue, continue)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(continue)
@@ -1748,7 +1748,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
           listener: handleIdentifier(default, topLevelFunctionDeclaration)
         parseMethodTypeVar(default)
           listener: handleNoTypeVariables(()
@@ -1831,7 +1831,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
                             listener: handleIdentifier(default, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(default)
@@ -2025,7 +2025,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
           listener: handleIdentifier(do, topLevelFunctionDeclaration)
         parseMethodTypeVar(do)
           listener: handleNoTypeVariables(()
@@ -2108,7 +2108,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {token: do}], do, do)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {lexeme: do}], do, do)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(do)
@@ -2187,7 +2187,7 @@
                             parseSend((, expression)
                               ensureIdentifier((, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {lexeme: }}], }, })
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
@@ -2357,7 +2357,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
           listener: handleIdentifier(else, topLevelFunctionDeclaration)
         parseMethodTypeVar(else)
           listener: handleNoTypeVariables(()
@@ -2440,7 +2440,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {lexeme: else}], else, else)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(else)
@@ -2468,7 +2468,7 @@
                             parseSend(;, expression)
                               ensureIdentifier(;, expression)
                                 reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {lexeme: else}], else, else)
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments(else)
@@ -2480,8 +2480,8 @@
                         listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], else, else)
                       rewriter()
                     listener: handleExpressionStatement(;)
-          reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], else, else)
+          reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], else, else)
           notEofOrValue(}, ()
           parseStatement(else)
             parseStatementX(else)
@@ -2546,7 +2546,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
           listener: handleIdentifier(enum, topLevelFunctionDeclaration)
         parseMethodTypeVar(enum)
           listener: handleNoTypeVariables(()
@@ -2629,7 +2629,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
                             listener: handleIdentifier(enum, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(enum)
@@ -2823,7 +2823,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
           listener: handleIdentifier(extends, topLevelFunctionDeclaration)
         parseMethodTypeVar(extends)
           listener: handleNoTypeVariables(()
@@ -2906,7 +2906,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
                             listener: handleIdentifier(extends, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(extends)
@@ -3374,7 +3374,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
           listener: handleIdentifier(false, topLevelFunctionDeclaration)
         parseMethodTypeVar(false)
           listener: handleNoTypeVariables(()
@@ -3510,7 +3510,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
           listener: handleIdentifier(final, topLevelFunctionDeclaration)
         parseMethodTypeVar(final)
           listener: handleNoTypeVariables(()
@@ -3593,7 +3593,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {token: final}], final, final)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {lexeme: final}], final, final)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(final)
@@ -3619,7 +3619,7 @@
                   parseOptionallyInitializedIdentifier(final)
                     ensureIdentifier(final, localVariableDeclaration)
                       reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                       rewriter()
                       listener: handleIdentifier(, localVariableDeclaration)
                     listener: beginInitializedIdentifier()
@@ -3675,7 +3675,7 @@
                             parseSend(;, expression)
                               ensureIdentifier(;, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
@@ -3687,8 +3687,8 @@
                         listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
                       rewriter()
                     listener: handleExpressionStatement(;)
-          reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+          reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
           notEofOrValue(}, +)
           parseStatement())
             parseStatementX())
@@ -3740,7 +3740,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
           listener: handleIdentifier(finally, topLevelFunctionDeclaration)
         parseMethodTypeVar(finally)
           listener: handleNoTypeVariables(()
@@ -3823,7 +3823,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
                             listener: handleIdentifier(finally, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(finally)
@@ -3880,7 +3880,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
           listener: handleIdentifier(for, topLevelFunctionDeclaration)
         parseMethodTypeVar(for)
           listener: handleNoTypeVariables(()
@@ -3963,7 +3963,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {token: for}], for, for)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {lexeme: for}], for, for)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(for)
@@ -4019,7 +4019,7 @@
                               parseSend(;, expression)
                                 ensureIdentifier(;, expression)
                                   reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                   rewriter()
                                   listener: handleIdentifier(, expression)
                                 listener: handleNoTypeArguments())
@@ -4496,7 +4496,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
           listener: handleIdentifier(if, topLevelFunctionDeclaration)
         parseMethodTypeVar(if)
           listener: handleNoTypeVariables(()
@@ -4579,7 +4579,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {token: if}], if, if)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {lexeme: if}], if, if)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(if)
@@ -4947,7 +4947,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
           listener: handleIdentifier(in, topLevelFunctionDeclaration)
         parseMethodTypeVar(in)
           listener: handleNoTypeVariables(()
@@ -5030,7 +5030,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
                             listener: handleIdentifier(in, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(in)
@@ -5361,7 +5361,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
           listener: handleIdentifier(is, topLevelFunctionDeclaration)
         parseMethodTypeVar(is)
           listener: handleNoTypeVariables(()
@@ -5444,7 +5444,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {token: is}], is, is)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {lexeme: is}], is, is)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(is)
@@ -5455,7 +5455,7 @@
                       listener: beginIsOperatorType(is)
                       computeTypeAfterIsOrAs(is)
                       reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                        listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '('., null, {token: (}], (, ()
+                        listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '('., null, {lexeme: (}], (, ()
                       rewriter()
                       listener: handleIdentifier(, typeReference)
                       listener: handleNoTypeArguments(()
@@ -6081,7 +6081,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
           listener: handleIdentifier(new, topLevelFunctionDeclaration)
         parseMethodTypeVar(new)
           listener: handleNoTypeVariables(()
@@ -6164,9 +6164,9 @@
                           listener: beginNewExpression(new)
                           parseConstructorReference(new, null)
                             ensureIdentifier(new, constructorReference)
-                              insertSyntheticIdentifier(new, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], messageOnToken: null)
-                                reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                              insertSyntheticIdentifier(new, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], messageOnToken: null)
+                                reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}])
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                                 rewriter()
                               listener: handleIdentifier(, constructorReference)
                             listener: beginConstructorReference()
@@ -6227,7 +6227,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
           listener: handleIdentifier(null, topLevelFunctionDeclaration)
         parseMethodTypeVar(null)
           listener: handleNoTypeVariables(()
@@ -7322,7 +7322,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
           listener: handleIdentifier(rethrow, topLevelFunctionDeclaration)
         parseMethodTypeVar(rethrow)
           listener: handleNoTypeVariables(()
@@ -7405,7 +7405,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
                             listener: handleIdentifier(rethrow, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(rethrow)
@@ -7462,7 +7462,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
           listener: handleIdentifier(return, topLevelFunctionDeclaration)
         parseMethodTypeVar(return)
           listener: handleNoTypeVariables(()
@@ -7543,7 +7543,7 @@
                       parsePrimary(return, expression)
                         inPlainSync()
                         reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-                          listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token 'return'., null, {token: return}], return, return)
+                          listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token 'return'., null, {lexeme: return}], return, return)
                         parsePrimary(return, expression)
                           parseParenthesizedExpressionOrFunctionLiteral(return)
                             parseParenthesizedExpression(return)
@@ -8147,7 +8147,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
           listener: handleIdentifier(super, topLevelFunctionDeclaration)
         parseMethodTypeVar(super)
           listener: handleNoTypeVariables(()
@@ -8282,7 +8282,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
           listener: handleIdentifier(switch, topLevelFunctionDeclaration)
         parseMethodTypeVar(switch)
           listener: handleNoTypeVariables(()
@@ -8365,7 +8365,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {token: switch}], switch, switch)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {lexeme: switch}], switch, switch)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(switch)
@@ -8603,7 +8603,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, false)
           reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
           listener: handleIdentifier(this, topLevelFunctionDeclaration)
         parseMethodTypeVar(this)
           listener: handleNoTypeVariables(()
@@ -8738,7 +8738,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
           listener: handleIdentifier(throw, topLevelFunctionDeclaration)
         parseMethodTypeVar(throw)
           listener: handleNoTypeVariables(()
@@ -8874,7 +8874,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
           listener: handleIdentifier(true, topLevelFunctionDeclaration)
         parseMethodTypeVar(true)
           listener: handleNoTypeVariables(()
@@ -9010,7 +9010,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
           listener: handleIdentifier(try, topLevelFunctionDeclaration)
         parseMethodTypeVar(try)
           listener: handleNoTypeVariables(()
@@ -9093,7 +9093,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {token: try}], try, try)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {lexeme: try}], try, try)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(try)
@@ -9325,7 +9325,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
           listener: handleIdentifier(var, topLevelFunctionDeclaration)
         parseMethodTypeVar(var)
           listener: handleNoTypeVariables(()
@@ -9408,7 +9408,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {token: var}], var, var)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {lexeme: var}], var, var)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(var)
@@ -9434,7 +9434,7 @@
                   parseOptionallyInitializedIdentifier(var)
                     ensureIdentifier(var, localVariableDeclaration)
                       reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                       rewriter()
                       listener: handleIdentifier(, localVariableDeclaration)
                     listener: beginInitializedIdentifier()
@@ -9490,7 +9490,7 @@
                             parseSend(;, expression)
                               ensureIdentifier(;, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
@@ -9502,8 +9502,8 @@
                         listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
                       rewriter()
                     listener: handleExpressionStatement(;)
-          reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+          reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
           notEofOrValue(}, +)
           parseStatement())
             parseStatementX())
@@ -9555,7 +9555,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
           listener: handleIdentifier(void, topLevelFunctionDeclaration)
         parseMethodTypeVar(void)
           listener: handleNoTypeVariables(()
@@ -9638,7 +9638,7 @@
                           parseSend(return, expression)
                             ensureIdentifier(return, expression)
                               reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {token: void}], void, void)
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {lexeme: void}], void, void)
                               rewriter()
                               listener: handleIdentifier(, expression)
                             listener: handleNoTypeArguments(void)
@@ -9665,7 +9665,7 @@
                     parseOptionallyInitializedIdentifier(void)
                       ensureIdentifier(void, localVariableDeclaration)
                         reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
+                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {lexeme: (}], (, ()
                         rewriter()
                         listener: handleIdentifier(, localVariableDeclaration)
                       listener: beginInitializedIdentifier()
@@ -9721,7 +9721,7 @@
                             parseSend(;, expression)
                               ensureIdentifier(;, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {lexeme: )}], ), ))
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
@@ -9733,8 +9733,8 @@
                         listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
                       rewriter()
                     listener: handleExpressionStatement(;)
-          reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}])
-            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ), ))
+          reportRecoverableError(;, Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}])
+            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ), ))
           notEofOrValue(}, +)
           parseStatement())
             parseStatementX())
@@ -9786,7 +9786,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
           listener: handleIdentifier(while, topLevelFunctionDeclaration)
         parseMethodTypeVar(while)
           listener: handleNoTypeVariables(()
@@ -9869,7 +9869,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {token: while}], while, while)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {lexeme: while}], while, while)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(while)
@@ -9963,7 +9963,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
           listener: handleIdentifier(with, topLevelFunctionDeclaration)
         parseMethodTypeVar(with)
           listener: handleNoTypeVariables(()
@@ -10046,7 +10046,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                             listener: handleIdentifier(with, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(with)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.expect
index f7f2800..d218353 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.expect
@@ -470,7 +470,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: abstract}], abstract, abstract)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: abstract}], abstract, abstract)
       handleIdentifier(abstract, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -481,7 +481,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: abstract}], abstract, abstract)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: abstract}], abstract, abstract)
       handleIdentifier(abstract, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -497,7 +497,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: as}], as, as)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: as}], as, as)
       handleIdentifier(as, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -508,7 +508,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: as}], as, as)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: as}], as, as)
       handleIdentifier(as, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -524,7 +524,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
       handleIdentifier(assert, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -535,7 +535,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
       handleIdentifier(assert, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -601,7 +601,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
       handleIdentifier(break, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -612,7 +612,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
       handleIdentifier(break, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -628,7 +628,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
       handleIdentifier(case, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -639,7 +639,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
       handleIdentifier(case, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -655,7 +655,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
       handleIdentifier(catch, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -666,7 +666,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
       handleIdentifier(catch, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -682,7 +682,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
       handleIdentifier(class, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -693,7 +693,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
       handleIdentifier(class, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -709,7 +709,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
       handleIdentifier(const, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -720,7 +720,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
       handleIdentifier(const, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -736,7 +736,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
       handleIdentifier(continue, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -747,7 +747,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
       handleIdentifier(continue, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -763,7 +763,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: covariant}], covariant, covariant)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: covariant}], covariant, covariant)
       handleIdentifier(covariant, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -774,7 +774,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: covariant}], covariant, covariant)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: covariant}], covariant, covariant)
       handleIdentifier(covariant, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -790,7 +790,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
       handleIdentifier(default, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -801,7 +801,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
       handleIdentifier(default, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -817,7 +817,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: deferred}], deferred, deferred)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: deferred}], deferred, deferred)
       handleIdentifier(deferred, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -828,7 +828,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: deferred}], deferred, deferred)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: deferred}], deferred, deferred)
       handleIdentifier(deferred, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -844,7 +844,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
       handleIdentifier(do, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -855,7 +855,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
       handleIdentifier(do, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -871,7 +871,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: dynamic}], dynamic, dynamic)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: dynamic}], dynamic, dynamic)
       handleIdentifier(dynamic, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -882,7 +882,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: dynamic}], dynamic, dynamic)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: dynamic}], dynamic, dynamic)
       handleIdentifier(dynamic, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -898,7 +898,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
       handleIdentifier(else, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -909,7 +909,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
       handleIdentifier(else, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -925,7 +925,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
       handleIdentifier(enum, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -936,7 +936,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
       handleIdentifier(enum, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -952,7 +952,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: export}], export, export)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: export}], export, export)
       handleIdentifier(export, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -963,7 +963,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: export}], export, export)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: export}], export, export)
       handleIdentifier(export, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -979,7 +979,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
       handleIdentifier(extends, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -990,7 +990,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
       handleIdentifier(extends, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1006,7 +1006,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extension}], extension, extension)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extension}], extension, extension)
       handleIdentifier(extension, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1017,7 +1017,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extension}], extension, extension)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extension}], extension, extension)
       handleIdentifier(extension, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1033,7 +1033,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: external}], external, external)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: external}], external, external)
       handleIdentifier(external, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1044,7 +1044,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: external}], external, external)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: external}], external, external)
       handleIdentifier(external, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1060,7 +1060,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: factory}], factory, factory)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: factory}], factory, factory)
       handleIdentifier(factory, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1071,7 +1071,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: factory}], factory, factory)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: factory}], factory, factory)
       handleIdentifier(factory, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1087,7 +1087,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
       handleIdentifier(false, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1098,7 +1098,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
       handleIdentifier(false, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1114,7 +1114,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
       handleIdentifier(final, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1125,7 +1125,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
       handleIdentifier(final, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1141,7 +1141,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
       handleIdentifier(finally, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1152,7 +1152,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
       handleIdentifier(finally, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1168,7 +1168,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
       handleIdentifier(for, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1179,7 +1179,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
       handleIdentifier(for, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1195,7 +1195,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: Function}], Function, Function)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: Function}], Function, Function)
       handleIdentifier(Function, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1206,7 +1206,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: Function}], Function, Function)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: Function}], Function, Function)
       handleIdentifier(Function, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1222,7 +1222,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: get}], get, get)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: get}], get, get)
       handleIdentifier(get, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1233,7 +1233,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: get}], get, get)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: get}], get, get)
       handleIdentifier(get, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1274,7 +1274,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
       handleIdentifier(if, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1285,7 +1285,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
       handleIdentifier(if, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1301,7 +1301,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: implements}], implements, implements)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: implements}], implements, implements)
       handleIdentifier(implements, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1312,7 +1312,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: implements}], implements, implements)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: implements}], implements, implements)
       handleIdentifier(implements, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1328,7 +1328,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: import}], import, import)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: import}], import, import)
       handleIdentifier(import, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1339,7 +1339,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: import}], import, import)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: import}], import, import)
       handleIdentifier(import, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1355,7 +1355,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
       handleIdentifier(in, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1366,7 +1366,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
       handleIdentifier(in, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1407,7 +1407,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: interface}], interface, interface)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: interface}], interface, interface)
       handleIdentifier(interface, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1418,7 +1418,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: interface}], interface, interface)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: interface}], interface, interface)
       handleIdentifier(interface, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1434,7 +1434,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
       handleIdentifier(is, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1445,7 +1445,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
       handleIdentifier(is, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1461,7 +1461,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: late}], late, late)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: late}], late, late)
       handleIdentifier(late, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1472,7 +1472,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: late}], late, late)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: late}], late, late)
       handleIdentifier(late, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1488,7 +1488,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: library}], library, library)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: library}], library, library)
       handleIdentifier(library, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1499,7 +1499,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: library}], library, library)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: library}], library, library)
       handleIdentifier(library, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1515,7 +1515,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: mixin}], mixin, mixin)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: mixin}], mixin, mixin)
       handleIdentifier(mixin, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1526,7 +1526,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: mixin}], mixin, mixin)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: mixin}], mixin, mixin)
       handleIdentifier(mixin, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1567,7 +1567,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
       handleIdentifier(new, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1578,7 +1578,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
       handleIdentifier(new, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1594,7 +1594,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
       handleIdentifier(null, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1605,7 +1605,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
       handleIdentifier(null, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1671,7 +1671,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: operator}], operator, operator)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: operator}], operator, operator)
       handleIdentifier(operator, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1682,7 +1682,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: operator}], operator, operator)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: operator}], operator, operator)
       handleIdentifier(operator, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1723,7 +1723,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: part}], part, part)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: part}], part, part)
       handleIdentifier(part, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1734,7 +1734,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: part}], part, part)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: part}], part, part)
       handleIdentifier(part, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1775,7 +1775,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: required}], required, required)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: required}], required, required)
       handleIdentifier(required, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1786,7 +1786,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: required}], required, required)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: required}], required, required)
       handleIdentifier(required, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1802,7 +1802,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
       handleIdentifier(rethrow, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1813,7 +1813,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
       handleIdentifier(rethrow, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1829,7 +1829,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
       handleIdentifier(return, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1840,7 +1840,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
       handleIdentifier(return, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1856,7 +1856,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: set}], set, set)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: set}], set, set)
       handleIdentifier(set, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1867,7 +1867,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: set}], set, set)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: set}], set, set)
       handleIdentifier(set, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1933,7 +1933,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: static}], static, static)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: static}], static, static)
       handleIdentifier(static, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1944,7 +1944,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: static}], static, static)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: static}], static, static)
       handleIdentifier(static, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1960,7 +1960,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
       handleIdentifier(super, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1971,7 +1971,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
       handleIdentifier(super, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1987,7 +1987,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
       handleIdentifier(switch, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1998,7 +1998,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
       handleIdentifier(switch, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2039,7 +2039,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
       handleIdentifier(this, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2050,7 +2050,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
       handleIdentifier(this, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2066,7 +2066,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
       handleIdentifier(throw, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2077,7 +2077,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
       handleIdentifier(throw, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2093,7 +2093,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
       handleIdentifier(true, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2104,7 +2104,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
       handleIdentifier(true, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2120,7 +2120,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
       handleIdentifier(try, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2131,7 +2131,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
       handleIdentifier(try, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2147,7 +2147,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: typedef}], typedef, typedef)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: typedef}], typedef, typedef)
       handleIdentifier(typedef, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2158,7 +2158,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: typedef}], typedef, typedef)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: typedef}], typedef, typedef)
       handleIdentifier(typedef, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2174,7 +2174,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
       handleIdentifier(var, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2185,7 +2185,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
       handleIdentifier(var, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2201,7 +2201,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
       handleIdentifier(void, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2213,7 +2213,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {token: =}], =, =)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {lexeme: =}], =, =)
       handleIdentifier(, typedefDeclaration)
       handleNoTypeVariables(=)
       handleRecoverableError(MissingTypedefParameters, =, =)
@@ -2225,7 +2225,7 @@
   beginMetadataStar(=)
   endMetadataStar(0)
   beginTopLevelMember(=)
-    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '='., null, {token: =}], =, =)
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '='., null, {lexeme: =}], =, =)
     handleInvalidTopLevelDeclaration(=)
   endTopLevelDeclaration(void)
   beginMetadataStar(void)
@@ -2247,7 +2247,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
       handleIdentifier(while, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2258,7 +2258,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
       handleIdentifier(while, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2274,7 +2274,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
       handleIdentifier(with, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2285,7 +2285,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
       handleIdentifier(with, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.intertwined.expect
index cc71477..45f76b0 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.intertwined.expect
@@ -14,7 +14,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(abstract, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: abstract}], abstract, abstract)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: abstract}], abstract, abstract)
           listener: handleIdentifier(abstract, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(abstract, MemberKind.FunctionTypeAlias)
@@ -35,7 +35,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(abstract, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: abstract}], abstract, abstract)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: abstract}], abstract, abstract)
           listener: handleIdentifier(abstract, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -61,7 +61,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(as, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: as}], as, as)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: as}], as, as)
           listener: handleIdentifier(as, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(as, MemberKind.FunctionTypeAlias)
@@ -82,7 +82,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(as, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: as}], as, as)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: as}], as, as)
           listener: handleIdentifier(as, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -108,7 +108,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
           listener: handleIdentifier(assert, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(assert, MemberKind.FunctionTypeAlias)
@@ -129,7 +129,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: assert}], assert, assert)
           listener: handleIdentifier(assert, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -241,7 +241,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
           listener: handleIdentifier(break, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(break, MemberKind.FunctionTypeAlias)
@@ -262,7 +262,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: break}], break, break)
           listener: handleIdentifier(break, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -288,7 +288,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
           listener: handleIdentifier(case, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(case, MemberKind.FunctionTypeAlias)
@@ -309,7 +309,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: case}], case, case)
           listener: handleIdentifier(case, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -335,7 +335,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
           listener: handleIdentifier(catch, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(catch, MemberKind.FunctionTypeAlias)
@@ -356,7 +356,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: catch}], catch, catch)
           listener: handleIdentifier(catch, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -382,7 +382,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
           listener: handleIdentifier(class, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(class, MemberKind.FunctionTypeAlias)
@@ -403,7 +403,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: class}], class, class)
           listener: handleIdentifier(class, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -429,7 +429,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
           listener: handleIdentifier(const, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(const, MemberKind.FunctionTypeAlias)
@@ -450,7 +450,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: const}], const, const)
           listener: handleIdentifier(const, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -476,7 +476,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
           listener: handleIdentifier(continue, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(continue, MemberKind.FunctionTypeAlias)
@@ -497,7 +497,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: continue}], continue, continue)
           listener: handleIdentifier(continue, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -523,7 +523,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(covariant, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: covariant}], covariant, covariant)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: covariant}], covariant, covariant)
           listener: handleIdentifier(covariant, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(covariant, MemberKind.FunctionTypeAlias)
@@ -544,7 +544,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(covariant, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: covariant}], covariant, covariant)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: covariant}], covariant, covariant)
           listener: handleIdentifier(covariant, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -570,7 +570,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
           listener: handleIdentifier(default, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(default, MemberKind.FunctionTypeAlias)
@@ -591,7 +591,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: default}], default, default)
           listener: handleIdentifier(default, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -617,7 +617,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(deferred, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: deferred}], deferred, deferred)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: deferred}], deferred, deferred)
           listener: handleIdentifier(deferred, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(deferred, MemberKind.FunctionTypeAlias)
@@ -638,7 +638,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(deferred, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: deferred}], deferred, deferred)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: deferred}], deferred, deferred)
           listener: handleIdentifier(deferred, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -664,7 +664,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
           listener: handleIdentifier(do, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(do, MemberKind.FunctionTypeAlias)
@@ -685,7 +685,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: do}], do, do)
           listener: handleIdentifier(do, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -711,7 +711,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(dynamic, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: dynamic}], dynamic, dynamic)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: dynamic}], dynamic, dynamic)
           listener: handleIdentifier(dynamic, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(dynamic, MemberKind.FunctionTypeAlias)
@@ -732,7 +732,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(dynamic, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: dynamic}], dynamic, dynamic)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: dynamic}], dynamic, dynamic)
           listener: handleIdentifier(dynamic, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -758,7 +758,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
           listener: handleIdentifier(else, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(else, MemberKind.FunctionTypeAlias)
@@ -779,7 +779,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: else}], else, else)
           listener: handleIdentifier(else, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -805,7 +805,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
           listener: handleIdentifier(enum, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(enum, MemberKind.FunctionTypeAlias)
@@ -826,7 +826,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: enum}], enum, enum)
           listener: handleIdentifier(enum, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -852,7 +852,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(export, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: export}], export, export)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: export}], export, export)
           listener: handleIdentifier(export, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(export, MemberKind.FunctionTypeAlias)
@@ -873,7 +873,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(export, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: export}], export, export)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: export}], export, export)
           listener: handleIdentifier(export, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -899,7 +899,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
           listener: handleIdentifier(extends, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(extends, MemberKind.FunctionTypeAlias)
@@ -920,7 +920,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extends}], extends, extends)
           listener: handleIdentifier(extends, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -946,7 +946,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(extension, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extension}], extension, extension)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extension}], extension, extension)
           listener: handleIdentifier(extension, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(extension, MemberKind.FunctionTypeAlias)
@@ -967,7 +967,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(extension, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extension}], extension, extension)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: extension}], extension, extension)
           listener: handleIdentifier(extension, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -993,7 +993,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(external, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: external}], external, external)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: external}], external, external)
           listener: handleIdentifier(external, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(external, MemberKind.FunctionTypeAlias)
@@ -1014,7 +1014,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(external, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: external}], external, external)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: external}], external, external)
           listener: handleIdentifier(external, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1040,7 +1040,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(factory, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: factory}], factory, factory)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: factory}], factory, factory)
           listener: handleIdentifier(factory, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(factory, MemberKind.FunctionTypeAlias)
@@ -1061,7 +1061,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(factory, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: factory}], factory, factory)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: factory}], factory, factory)
           listener: handleIdentifier(factory, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1087,7 +1087,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
           listener: handleIdentifier(false, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(false, MemberKind.FunctionTypeAlias)
@@ -1108,7 +1108,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: false}], false, false)
           listener: handleIdentifier(false, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1134,7 +1134,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
           listener: handleIdentifier(final, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(final, MemberKind.FunctionTypeAlias)
@@ -1155,7 +1155,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: final}], final, final)
           listener: handleIdentifier(final, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1181,7 +1181,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
           listener: handleIdentifier(finally, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(finally, MemberKind.FunctionTypeAlias)
@@ -1202,7 +1202,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: finally}], finally, finally)
           listener: handleIdentifier(finally, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1228,7 +1228,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
           listener: handleIdentifier(for, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(for, MemberKind.FunctionTypeAlias)
@@ -1249,7 +1249,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: for}], for, for)
           listener: handleIdentifier(for, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1275,7 +1275,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(Function, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: Function}], Function, Function)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: Function}], Function, Function)
           listener: handleIdentifier(Function, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(Function, MemberKind.FunctionTypeAlias)
@@ -1296,7 +1296,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(Function, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: Function}], Function, Function)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: Function}], Function, Function)
           listener: handleIdentifier(Function, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1322,7 +1322,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(get, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: get}], get, get)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: get}], get, get)
           listener: handleIdentifier(get, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(get, MemberKind.FunctionTypeAlias)
@@ -1343,7 +1343,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(get, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: get}], get, get)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: get}], get, get)
           listener: handleIdentifier(get, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1412,7 +1412,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
           listener: handleIdentifier(if, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(if, MemberKind.FunctionTypeAlias)
@@ -1433,7 +1433,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: if}], if, if)
           listener: handleIdentifier(if, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1459,7 +1459,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(implements, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: implements}], implements, implements)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: implements}], implements, implements)
           listener: handleIdentifier(implements, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(implements, MemberKind.FunctionTypeAlias)
@@ -1480,7 +1480,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(implements, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: implements}], implements, implements)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: implements}], implements, implements)
           listener: handleIdentifier(implements, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1506,7 +1506,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(import, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: import}], import, import)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: import}], import, import)
           listener: handleIdentifier(import, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(import, MemberKind.FunctionTypeAlias)
@@ -1527,7 +1527,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(import, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: import}], import, import)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: import}], import, import)
           listener: handleIdentifier(import, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1553,7 +1553,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
           listener: handleIdentifier(in, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(in, MemberKind.FunctionTypeAlias)
@@ -1574,7 +1574,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: in}], in, in)
           listener: handleIdentifier(in, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1643,7 +1643,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(interface, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: interface}], interface, interface)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: interface}], interface, interface)
           listener: handleIdentifier(interface, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(interface, MemberKind.FunctionTypeAlias)
@@ -1664,7 +1664,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(interface, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: interface}], interface, interface)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: interface}], interface, interface)
           listener: handleIdentifier(interface, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1690,7 +1690,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
           listener: handleIdentifier(is, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(is, MemberKind.FunctionTypeAlias)
@@ -1711,7 +1711,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: is}], is, is)
           listener: handleIdentifier(is, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1737,7 +1737,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: late}], late, late)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: late}], late, late)
           listener: handleIdentifier(late, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(late, MemberKind.FunctionTypeAlias)
@@ -1758,7 +1758,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: late}], late, late)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: late}], late, late)
           listener: handleIdentifier(late, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1784,7 +1784,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(library, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: library}], library, library)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: library}], library, library)
           listener: handleIdentifier(library, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(library, MemberKind.FunctionTypeAlias)
@@ -1805,7 +1805,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(library, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: library}], library, library)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: library}], library, library)
           listener: handleIdentifier(library, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1831,7 +1831,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(mixin, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: mixin}], mixin, mixin)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: mixin}], mixin, mixin)
           listener: handleIdentifier(mixin, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(mixin, MemberKind.FunctionTypeAlias)
@@ -1852,7 +1852,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(mixin, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: mixin}], mixin, mixin)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: mixin}], mixin, mixin)
           listener: handleIdentifier(mixin, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1921,7 +1921,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
           listener: handleIdentifier(new, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(new, MemberKind.FunctionTypeAlias)
@@ -1942,7 +1942,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: new}], new, new)
           listener: handleIdentifier(new, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1968,7 +1968,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
           listener: handleIdentifier(null, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(null, MemberKind.FunctionTypeAlias)
@@ -1989,7 +1989,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: null}], null, null)
           listener: handleIdentifier(null, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2101,7 +2101,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(operator, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: operator}], operator, operator)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: operator}], operator, operator)
           listener: handleIdentifier(operator, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(operator, MemberKind.FunctionTypeAlias)
@@ -2122,7 +2122,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(operator, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: operator}], operator, operator)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: operator}], operator, operator)
           listener: handleIdentifier(operator, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2191,7 +2191,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(part, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: part}], part, part)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: part}], part, part)
           listener: handleIdentifier(part, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(part, MemberKind.FunctionTypeAlias)
@@ -2212,7 +2212,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(part, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: part}], part, part)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: part}], part, part)
           listener: handleIdentifier(part, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2281,7 +2281,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(required, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: required}], required, required)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: required}], required, required)
           listener: handleIdentifier(required, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(required, MemberKind.FunctionTypeAlias)
@@ -2302,7 +2302,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(required, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: required}], required, required)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: required}], required, required)
           listener: handleIdentifier(required, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2328,7 +2328,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
           listener: handleIdentifier(rethrow, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(rethrow, MemberKind.FunctionTypeAlias)
@@ -2349,7 +2349,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: rethrow}], rethrow, rethrow)
           listener: handleIdentifier(rethrow, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2375,7 +2375,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
           listener: handleIdentifier(return, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(return, MemberKind.FunctionTypeAlias)
@@ -2396,7 +2396,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: return}], return, return)
           listener: handleIdentifier(return, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2422,7 +2422,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(set, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: set}], set, set)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: set}], set, set)
           listener: handleIdentifier(set, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(set, MemberKind.FunctionTypeAlias)
@@ -2443,7 +2443,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(set, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: set}], set, set)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: set}], set, set)
           listener: handleIdentifier(set, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2555,7 +2555,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(static, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: static}], static, static)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: static}], static, static)
           listener: handleIdentifier(static, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(static, MemberKind.FunctionTypeAlias)
@@ -2576,7 +2576,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(static, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: static}], static, static)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: static}], static, static)
           listener: handleIdentifier(static, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2602,7 +2602,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
           listener: handleIdentifier(super, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(super, MemberKind.FunctionTypeAlias)
@@ -2623,7 +2623,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: super}], super, super)
           listener: handleIdentifier(super, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2649,7 +2649,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
           listener: handleIdentifier(switch, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(switch, MemberKind.FunctionTypeAlias)
@@ -2670,7 +2670,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: switch}], switch, switch)
           listener: handleIdentifier(switch, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2739,7 +2739,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
           listener: handleIdentifier(this, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(this, MemberKind.FunctionTypeAlias)
@@ -2760,7 +2760,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: this}], this, this)
           listener: handleIdentifier(this, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2786,7 +2786,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
           listener: handleIdentifier(throw, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(throw, MemberKind.FunctionTypeAlias)
@@ -2807,7 +2807,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: throw}], throw, throw)
           listener: handleIdentifier(throw, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2833,7 +2833,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
           listener: handleIdentifier(true, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(true, MemberKind.FunctionTypeAlias)
@@ -2854,7 +2854,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: true}], true, true)
           listener: handleIdentifier(true, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2880,7 +2880,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
           listener: handleIdentifier(try, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(try, MemberKind.FunctionTypeAlias)
@@ -2901,7 +2901,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: try}], try, try)
           listener: handleIdentifier(try, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2927,7 +2927,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(typedef, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: typedef}], typedef, typedef)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: typedef}], typedef, typedef)
           listener: handleIdentifier(typedef, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(typedef, MemberKind.FunctionTypeAlias)
@@ -2948,7 +2948,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(typedef, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: typedef}], typedef, typedef)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: typedef}], typedef, typedef)
           listener: handleIdentifier(typedef, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2974,7 +2974,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
           listener: handleIdentifier(var, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(var, MemberKind.FunctionTypeAlias)
@@ -2995,7 +2995,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: var}], var, var)
           listener: handleIdentifier(var, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -3021,7 +3021,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: void}], void, void)
           listener: handleIdentifier(void, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(void, MemberKind.FunctionTypeAlias)
@@ -3042,9 +3042,9 @@
         listener: beginFunctionTypeAlias(typedef)
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, false)
-          insertSyntheticIdentifier(void, typedefDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {token: =}], messageOnToken: null)
-            reportRecoverableError(=, Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {token: =}])
-              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {token: =}], =, =)
+          insertSyntheticIdentifier(void, typedefDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {lexeme: =}], messageOnToken: null)
+            reportRecoverableError(=, Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {lexeme: =}])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {lexeme: =}], =, =)
             rewriter()
           listener: handleIdentifier(, typedefDeclaration)
         listener: handleNoTypeVariables(=)
@@ -3069,7 +3069,7 @@
     listener: beginTopLevelMember(=)
     parseInvalidTopLevelDeclaration(;)
       reportRecoverableErrorWithToken(=, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '='., null, {token: =}], =, =)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '='., null, {lexeme: =}], =, =)
       listener: handleInvalidTopLevelDeclaration(=)
   listener: endTopLevelDeclaration(void)
   parseTopLevelDeclarationImpl(=, Instance of 'DirectiveContext')
@@ -3111,7 +3111,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
           listener: handleIdentifier(while, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(while, MemberKind.FunctionTypeAlias)
@@ -3132,7 +3132,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: while}], while, while)
           listener: handleIdentifier(while, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -3158,7 +3158,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
           listener: handleIdentifier(with, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(with, MemberKind.FunctionTypeAlias)
@@ -3179,7 +3179,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
           listener: handleIdentifier(with, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
diff --git a/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.expect b/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.expect
index a86e853..486a686 100644
--- a/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.expect
@@ -44,7 +44,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(with)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
             handleIdentifier(with, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -62,7 +62,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(with)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
             handleIdentifier(with, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(7)
@@ -76,7 +76,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(get)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
             handleIdentifier(with, methodDeclaration)
             handleNoTypeVariables(=>)
             handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
@@ -91,7 +91,7 @@
         beginMember()
           beginMethod(null, null, null, null, set, with)
             handleVoidKeyword(void)
-            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
             handleIdentifier(with, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -121,7 +121,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(with)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
       handleIdentifier(with, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -138,7 +138,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(with)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
       handleIdentifier(with, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(7)
diff --git a/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.intertwined.expect
index 4c53a03..2b0370c 100644
--- a/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.intertwined.expect
@@ -41,7 +41,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                   listener: handleIdentifier(with, methodDeclaration)
                 parseQualifiedRestOpt(with, methodDeclarationContinuation)
                 parseMethodTypeVar(with)
@@ -85,7 +85,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                   listener: handleIdentifier(with, fieldDeclaration)
                 parseFieldInitializerOpt(with, with, null, null, null, null, DeclarationKind.Class, C)
                   listener: beginFieldInitializer(=)
@@ -113,7 +113,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(get, methodDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                   listener: handleIdentifier(with, methodDeclaration)
                 parseQualifiedRestOpt(with, methodDeclarationContinuation)
                 listener: handleNoTypeVariables(=>)
@@ -152,7 +152,7 @@
                 listener: handleVoidKeyword(void)
                 ensureIdentifierPotentiallyRecovered(set, methodDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
                   listener: handleIdentifier(with, methodDeclaration)
                 parseQualifiedRestOpt(with, methodDeclarationContinuation)
                 listener: handleNoTypeVariables(()
@@ -205,7 +205,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
           listener: handleIdentifier(with, topLevelFunctionDeclaration)
         parseMethodTypeVar(with)
           listener: handleNoTypeVariables(()
@@ -245,7 +245,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {lexeme: with}], with, with)
           listener: handleIdentifier(with, topLevelVariableDeclaration)
         parseFieldInitializerOpt(with, with, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
diff --git a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.expect
index 7b27d65..4e6493f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.expect
Binary files differ
diff --git a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.intertwined.expect
index 28afeda..70ee37c 100644
--- a/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/utf_16_le_content.crash_dart.intertwined.expect
@@ -9,7 +9,7 @@
     listener: beginTopLevelMember(/)
     parseInvalidTopLevelDeclaration(AsciiControlCharacterToken(0))
       reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {lexeme: /}], /, /)
       listener: handleInvalidTopLevelDeclaration(/)
   listener: endTopLevelDeclaration(/)
   parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
@@ -19,7 +19,7 @@
     listener: beginTopLevelMember(/)
     parseInvalidTopLevelDeclaration(/)
       reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {lexeme: /}], /, /)
       listener: handleInvalidTopLevelDeclaration(/)
   listener: endTopLevelDeclaration(C)
   parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
@@ -140,8 +140,8 @@
           inPlainSync()
         parseFunctionBody(), false, false)
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(2, Message[ExpectedFunctionBody, Expected a function body, but got '2'., null, {token: 2}])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '2'., null, {token: 2}], 2, 2)
+            reportRecoverableError(2, Message[ExpectedFunctionBody, Expected a function body, but got '2'., null, {lexeme: 2}])
+              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '2'., null, {lexeme: 2}], 2, 2)
             insertBlock())
               rewriter()
               rewriter()
@@ -155,7 +155,7 @@
     listener: beginTopLevelMember(2)
     parseInvalidTopLevelDeclaration(})
       reportRecoverableErrorWithToken(2, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '2'., null, {token: 2}], 2, 2)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '2'., null, {lexeme: 2}], 2, 2)
       listener: handleInvalidTopLevelDeclaration(2)
   listener: endTopLevelDeclaration(0)
   parseTopLevelDeclarationImpl(2, Instance of 'DirectiveContext')
@@ -165,7 +165,7 @@
     listener: beginTopLevelMember(0)
     parseInvalidTopLevelDeclaration(2)
       reportRecoverableErrorWithToken(0, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '0'., null, {token: 0}], 0, 0)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '0'., null, {lexeme: 0}], 0, 0)
       listener: handleInvalidTopLevelDeclaration(0)
   listener: endTopLevelDeclaration(2)
   parseTopLevelDeclarationImpl(0, Instance of 'DirectiveContext')
@@ -175,7 +175,7 @@
     listener: beginTopLevelMember(2)
     parseInvalidTopLevelDeclaration(0)
       reportRecoverableErrorWithToken(2, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '2'., null, {token: 2}], 2, 2)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '2'., null, {lexeme: 2}], 2, 2)
       listener: handleInvalidTopLevelDeclaration(2)
   listener: endTopLevelDeclaration(0)
   parseTopLevelDeclarationImpl(2, Instance of 'DirectiveContext')
@@ -185,7 +185,7 @@
     listener: beginTopLevelMember(0)
     parseInvalidTopLevelDeclaration(2)
       reportRecoverableErrorWithToken(0, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '0'., null, {token: 0}], 0, 0)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '0'., null, {lexeme: 0}], 0, 0)
       listener: handleInvalidTopLevelDeclaration(0)
   listener: endTopLevelDeclaration(,)
   parseTopLevelDeclarationImpl(0, Instance of 'DirectiveContext')
@@ -195,7 +195,7 @@
     listener: beginTopLevelMember(,)
     parseInvalidTopLevelDeclaration(0)
       reportRecoverableErrorWithToken(,, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ','., null, {token: ,}], ,, ,)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got ','., null, {lexeme: ,}], ,, ,)
       listener: handleInvalidTopLevelDeclaration(,)
   listener: endTopLevelDeclaration(t)
   parseTopLevelDeclarationImpl(,, Instance of 'DirectiveContext')
@@ -670,7 +670,7 @@
     listener: beginTopLevelMember(/)
     parseInvalidTopLevelDeclaration(;)
       reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {lexeme: /}], /, /)
       listener: handleInvalidTopLevelDeclaration(/)
   listener: endTopLevelDeclaration(/)
   parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
@@ -680,7 +680,7 @@
     listener: beginTopLevelMember(/)
     parseInvalidTopLevelDeclaration(/)
       reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {lexeme: /}], /, /)
       listener: handleInvalidTopLevelDeclaration(/)
   listener: endTopLevelDeclaration(f)
   parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
@@ -795,8 +795,8 @@
           inPlainSync()
         parseFunctionBody(), false, false)
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}])
+              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
             insertBlock())
               rewriter()
               rewriter()
@@ -810,7 +810,7 @@
     listener: beginTopLevelMember(.)
     parseInvalidTopLevelDeclaration(})
       reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {lexeme: .}], ., .)
       listener: handleInvalidTopLevelDeclaration(.)
   listener: endTopLevelDeclaration(A)
   parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
@@ -1326,7 +1326,7 @@
     listener: beginTopLevelMember(/)
     parseInvalidTopLevelDeclaration(;)
       reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {lexeme: /}], /, /)
       listener: handleInvalidTopLevelDeclaration(/)
   listener: endTopLevelDeclaration(/)
   parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
@@ -1336,7 +1336,7 @@
     listener: beginTopLevelMember(/)
     parseInvalidTopLevelDeclaration(/)
       reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {lexeme: /}], /, /)
       listener: handleInvalidTopLevelDeclaration(/)
   listener: endTopLevelDeclaration(B)
   parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
@@ -1389,7 +1389,7 @@
     listener: beginTopLevelMember(-)
     parseInvalidTopLevelDeclaration(;)
       reportRecoverableErrorWithToken(-, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '-'., null, {token: -}], -, -)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '-'., null, {lexeme: -}], -, -)
       listener: handleInvalidTopLevelDeclaration(-)
   listener: endTopLevelDeclaration(s)
   parseTopLevelDeclarationImpl(-, Instance of 'DirectiveContext')
@@ -1798,8 +1798,8 @@
           inPlainSync()
         parseFunctionBody(), false, false)
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}])
+              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
             insertBlock())
               rewriter()
               rewriter()
@@ -1813,7 +1813,7 @@
     listener: beginTopLevelMember(.)
     parseInvalidTopLevelDeclaration(})
       reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {lexeme: .}], ., .)
       listener: handleInvalidTopLevelDeclaration(.)
   listener: endTopLevelDeclaration(m)
   parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
@@ -1886,8 +1886,8 @@
           inPlainSync()
         parseFunctionBody(), false, false)
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}])
+              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
             insertBlock())
               rewriter()
               rewriter()
@@ -1901,7 +1901,7 @@
     listener: beginTopLevelMember(.)
     parseInvalidTopLevelDeclaration(})
       reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {lexeme: .}], ., .)
       listener: handleInvalidTopLevelDeclaration(.)
   listener: endTopLevelDeclaration(/)
   parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
@@ -1911,7 +1911,7 @@
     listener: beginTopLevelMember(/)
     parseInvalidTopLevelDeclaration(.)
       reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {lexeme: /}], /, /)
       listener: handleInvalidTopLevelDeclaration(/)
   listener: endTopLevelDeclaration(/)
   parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
@@ -1921,7 +1921,7 @@
     listener: beginTopLevelMember(/)
     parseInvalidTopLevelDeclaration(/)
       reportRecoverableErrorWithToken(/, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {token: /}], /, /)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '/'., null, {lexeme: /}], /, /)
       listener: handleInvalidTopLevelDeclaration(/)
   listener: endTopLevelDeclaration(T)
   parseTopLevelDeclarationImpl(/, Instance of 'DirectiveContext')
@@ -2141,7 +2141,7 @@
     listener: beginTopLevelMember(-)
     parseInvalidTopLevelDeclaration(;)
       reportRecoverableErrorWithToken(-, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '-'., null, {token: -}], -, -)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '-'., null, {lexeme: -}], -, -)
       listener: handleInvalidTopLevelDeclaration(-)
   listener: endTopLevelDeclaration(1)
   parseTopLevelDeclarationImpl(-, Instance of 'DirectiveContext')
@@ -2151,7 +2151,7 @@
     listener: beginTopLevelMember(1)
     parseInvalidTopLevelDeclaration(-)
       reportRecoverableErrorWithToken(1, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '1'., null, {token: 1}], 1, 1)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '1'., null, {lexeme: 1}], 1, 1)
       listener: handleInvalidTopLevelDeclaration(1)
   listener: endTopLevelDeclaration(6)
   parseTopLevelDeclarationImpl(1, Instance of 'DirectiveContext')
@@ -2161,7 +2161,7 @@
     listener: beginTopLevelMember(6)
     parseInvalidTopLevelDeclaration(1)
       reportRecoverableErrorWithToken(6, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '6'., null, {token: 6}], 6, 6)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '6'., null, {lexeme: 6}], 6, 6)
       listener: handleInvalidTopLevelDeclaration(6)
   listener: endTopLevelDeclaration(L)
   parseTopLevelDeclarationImpl(6, Instance of 'DirectiveContext')
@@ -2192,8 +2192,8 @@
           inPlainSync()
         parseFunctionBody(), false, false)
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}])
+              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
             insertBlock())
               rewriter()
               rewriter()
@@ -2207,7 +2207,7 @@
     listener: beginTopLevelMember(.)
     parseInvalidTopLevelDeclaration(})
       reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {lexeme: .}], ., .)
       listener: handleInvalidTopLevelDeclaration(.)
   listener: endTopLevelDeclaration(m)
   parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
@@ -2515,611 +2515,611 @@
     listener: handleErrorToken(EncodingErrorToken())
     listener: handleRecoverableError(Encoding, EncodingErrorToken(), EncodingErrorToken())
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(UnterminatedString("))
     listener: handleRecoverableError(Message[UnterminatedString, String starting with " must end with "., null, {string: ", string2: "}], UnterminatedString("), UnterminatedString("))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(UnterminatedString("))
     listener: handleRecoverableError(Message[UnterminatedString, String starting with " must end with "., null, {string: ", string2: "}], UnterminatedString("), UnterminatedString("))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
     listener: handleErrorToken(AsciiControlCharacterToken(0))
-    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {codePoint: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
+    listener: handleRecoverableError(Message[AsciiControlCharacter, The control character U+0000 can only be used in strings and comments., null, {unicode: 0}], AsciiControlCharacterToken(0), AsciiControlCharacterToken(0))
   listener: endCompilationUnit(114, )
diff --git a/pkg/front_end/parser_testcases/extensions/covariant.dart.expect b/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
index 0b1d80d..9afdfed 100644
--- a/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
+++ b/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
@@ -56,7 +56,7 @@
             beginFormalParameters((, MemberKind.ExtensionNonStaticMethod)
               beginMetadataStar(covariant)
               endMetadataStar(0)
-              handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {token: covariant}], covariant, covariant)
+              handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {lexeme: covariant}], covariant, covariant)
               beginFormalParameter(covariant, MemberKind.ExtensionNonStaticMethod, null, covariant, null)
                 handleIdentifier(A, typeReference)
                 handleNoTypeArguments(child)
diff --git a/pkg/front_end/parser_testcases/extensions/covariant.dart.intertwined.expect b/pkg/front_end/parser_testcases/extensions/covariant.dart.intertwined.expect
index 2c95ee7..6bd925a 100644
--- a/pkg/front_end/parser_testcases/extensions/covariant.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/extensions/covariant.dart.intertwined.expect
@@ -99,7 +99,7 @@
                         listener: beginMetadataStar(covariant)
                         listener: endMetadataStar(0)
                       reportRecoverableErrorWithToken(covariant, Instance of 'Template<(Token) => Message>')
-                        listener: handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {token: covariant}], covariant, covariant)
+                        listener: handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {lexeme: covariant}], covariant, covariant)
                       listener: beginFormalParameter(covariant, MemberKind.ExtensionNonStaticMethod, null, covariant, null)
                       listener: handleIdentifier(A, typeReference)
                       listener: handleNoTypeArguments(child)
diff --git a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect
index 160198b..57bc44a 100644
--- a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect
+++ b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect
@@ -56,7 +56,7 @@
             beginFormalParameters((, MemberKind.ExtensionStaticMethod)
               beginMetadataStar(covariant)
               endMetadataStar(0)
-              handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {token: covariant}], covariant, covariant)
+              handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {lexeme: covariant}], covariant, covariant)
               beginFormalParameter(covariant, MemberKind.ExtensionStaticMethod, null, covariant, null)
                 handleIdentifier(A, typeReference)
                 handleNoTypeArguments(child)
diff --git a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.intertwined.expect b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.intertwined.expect
index 43700a3..d98b093 100644
--- a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.intertwined.expect
@@ -99,7 +99,7 @@
                         listener: beginMetadataStar(covariant)
                         listener: endMetadataStar(0)
                       reportRecoverableErrorWithToken(covariant, Instance of 'Template<(Token) => Message>')
-                        listener: handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {token: covariant}], covariant, covariant)
+                        listener: handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {lexeme: covariant}], covariant, covariant)
                       listener: beginFormalParameter(covariant, MemberKind.ExtensionStaticMethod, null, covariant, null)
                       listener: handleIdentifier(A, typeReference)
                       listener: handleNoTypeArguments(child)
diff --git a/pkg/front_end/parser_testcases/general/ambiguous_builder_01.dart.expect b/pkg/front_end/parser_testcases/general/ambiguous_builder_01.dart.expect
index 5bdec1e..f96c13a 100644
--- a/pkg/front_end/parser_testcases/general/ambiguous_builder_01.dart.expect
+++ b/pkg/front_end/parser_testcases/general/ambiguous_builder_01.dart.expect
@@ -44,14 +44,14 @@
       beginFormalParameters((, MemberKind.TopLevelMethod)
       endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
       handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
       handleInvalidFunctionBody({)
     endTopLevelMethod(x, null, })
   endTopLevelDeclaration(.)
   beginMetadataStar(.)
   endMetadataStar(0)
   beginTopLevelMember(.)
-    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {lexeme: .}], ., .)
     handleInvalidTopLevelDeclaration(.)
   endTopLevelDeclaration(y)
   beginMetadataStar(y)
@@ -77,14 +77,14 @@
       beginFormalParameters((, MemberKind.TopLevelMethod)
       endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
       handleAsyncModifier(null, null)
-      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
       handleInvalidFunctionBody({)
     endTopLevelMethod(x, null, })
   endTopLevelDeclaration(.)
   beginMetadataStar(.)
   endMetadataStar(0)
   beginTopLevelMember(.)
-    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {lexeme: .}], ., .)
     handleInvalidTopLevelDeclaration(.)
   endTopLevelDeclaration(z)
   beginMetadataStar(z)
diff --git a/pkg/front_end/parser_testcases/general/ambiguous_builder_01.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/ambiguous_builder_01.dart.intertwined.expect
index ef23755..c9238c0 100644
--- a/pkg/front_end/parser_testcases/general/ambiguous_builder_01.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/general/ambiguous_builder_01.dart.intertwined.expect
@@ -29,8 +29,8 @@
           inPlainSync()
         parseFunctionBody(), false, false)
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}])
+              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
             insertBlock())
               rewriter()
               rewriter()
@@ -44,7 +44,7 @@
     listener: beginTopLevelMember(.)
     parseInvalidTopLevelDeclaration(})
       reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {lexeme: .}], ., .)
       listener: handleInvalidTopLevelDeclaration(.)
   listener: endTopLevelDeclaration(y)
   parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
@@ -99,8 +99,8 @@
           inPlainSync()
         parseFunctionBody(), false, false)
           ensureBlock(), Instance of 'Template<(Token) => Message>', null)
-            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}])
-              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {token: .}], ., .)
+            reportRecoverableError(., Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}])
+              listener: handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got '.'., null, {lexeme: .}], ., .)
             insertBlock())
               rewriter()
               rewriter()
@@ -114,7 +114,7 @@
     listener: beginTopLevelMember(.)
     parseInvalidTopLevelDeclaration(})
       reportRecoverableErrorWithToken(., Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {token: .}], ., .)
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '.'., null, {lexeme: .}], ., .)
       listener: handleInvalidTopLevelDeclaration(.)
   listener: endTopLevelDeclaration(z)
   parseTopLevelDeclarationImpl(., Instance of 'DirectiveContext')
diff --git a/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.expect b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.expect
index 4f4ca4b..0d03eb7 100644
--- a/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.expect
+++ b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.expect
@@ -28,5 +28,5 @@
     endTopLevelMethod(main, null, })
   endTopLevelDeclaration()
   handleErrorToken(UnmatchedToken({))
-  handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, token: {}], UnmatchedToken({), UnmatchedToken({))
+  handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, lexeme: {}], UnmatchedToken({), UnmatchedToken({))
 endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.intertwined.expect
index 7a76420..8c28f4cf 100644
--- a/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.intertwined.expect
@@ -64,5 +64,5 @@
   listener: endTopLevelDeclaration()
   reportAllErrorTokens(UnmatchedToken({))
     listener: handleErrorToken(UnmatchedToken({))
-    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, token: {}], UnmatchedToken({), UnmatchedToken({))
+    listener: handleRecoverableError(Message[UnmatchedToken, Can't find '}' to match '{'., null, {string: }, lexeme: {}], UnmatchedToken({), UnmatchedToken({))
   listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect
index d5836cb..3c769e2 100644
--- a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect
@@ -8,7 +8,7 @@
   beginMetadataStar(class)
   endMetadataStar(0)
   beginClassOrNamedMixinApplicationPrelude(class)
-    handleRecoverableError(Message[BuiltInIdentifierInDeclaration, Can't use 'operator' as a name here., null, {token: operator}], operator, operator)
+    handleRecoverableError(Message[BuiltInIdentifierInDeclaration, Can't use 'operator' as a name here., null, {lexeme: operator}], operator, operator)
     handleIdentifier(operator, classOrMixinDeclaration)
     handleNoTypeVariables({)
     beginClassDeclaration(class, null, operator)
diff --git a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.intertwined.expect
index 5926593..2b3c832 100644
--- a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.intertwined.expect
@@ -12,7 +12,7 @@
         listener: beginClassOrNamedMixinApplicationPrelude(class)
         ensureIdentifier(class, classOrMixinDeclaration)
           reportRecoverableErrorWithToken(operator, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[BuiltInIdentifierInDeclaration, Can't use 'operator' as a name here., null, {token: operator}], operator, operator)
+            listener: handleRecoverableError(Message[BuiltInIdentifierInDeclaration, Can't use 'operator' as a name here., null, {lexeme: operator}], operator, operator)
           listener: handleIdentifier(operator, classOrMixinDeclaration)
         listener: handleNoTypeVariables({)
         listener: beginClassDeclaration(class, null, operator)
diff --git a/pkg/front_end/parser_testcases/nnbd/error_recovery/abstract_placement.dart.expect b/pkg/front_end/parser_testcases/nnbd/error_recovery/abstract_placement.dart.expect
index 12e6b31..2baf5d9 100644
--- a/pkg/front_end/parser_testcases/nnbd/error_recovery/abstract_placement.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/error_recovery/abstract_placement.dart.expect
@@ -158,7 +158,7 @@
   endMetadataStar(0)
   beginTopLevelMember(var)
     handleRecoverableError(Message[ModifierOutOfOrder, The modifier 'abstract' should be before the modifier 'var'., Try re-ordering the modifiers., {string: abstract, string2: var}], abstract, abstract)
-    handleRecoverableError(Message[ExtraneousModifier, Can't have modifier 'abstract' here., Try removing 'abstract'., {token: abstract}], abstract, abstract)
+    handleRecoverableError(Message[ExtraneousModifier, Can't have modifier 'abstract' here., Try removing 'abstract'., {lexeme: abstract}], abstract, abstract)
     beginFields(})
       handleNoType(abstract)
       handleIdentifier(foo, topLevelVariableDeclaration)
@@ -180,7 +180,7 @@
         beginMetadataStar(covariant)
         endMetadataStar(0)
         handleRecoverableError(Message[ModifierOutOfOrder, The modifier 'required' should be before the modifier 'covariant'., Try re-ordering the modifiers., {string: required, string2: covariant}], required, required)
-        handleRecoverableError(Message[ExtraneousModifier, Can't have modifier 'required' here., Try removing 'required'., {token: required}], required, required)
+        handleRecoverableError(Message[ExtraneousModifier, Can't have modifier 'required' here., Try removing 'required'., {lexeme: required}], required, required)
         beginMember()
           beginFields({)
             handleRecoverableError(MissingConstFinalVarOrType, x, x)
diff --git a/pkg/front_end/parser_testcases/nnbd/error_recovery/abstract_placement.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/error_recovery/abstract_placement.dart.intertwined.expect
index 0ce64ff..153ca2c 100644
--- a/pkg/front_end/parser_testcases/nnbd/error_recovery/abstract_placement.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/error_recovery/abstract_placement.dart.intertwined.expect
@@ -185,7 +185,7 @@
       reportRecoverableError(abstract, Message[ModifierOutOfOrder, The modifier 'abstract' should be before the modifier 'var'., Try re-ordering the modifiers., {string: abstract, string2: var}])
         listener: handleRecoverableError(Message[ModifierOutOfOrder, The modifier 'abstract' should be before the modifier 'var'., Try re-ordering the modifiers., {string: abstract, string2: var}], abstract, abstract)
       reportRecoverableErrorWithToken(abstract, Instance of 'Template<(Token) => Message>')
-        listener: handleRecoverableError(Message[ExtraneousModifier, Can't have modifier 'abstract' here., Try removing 'abstract'., {token: abstract}], abstract, abstract)
+        listener: handleRecoverableError(Message[ExtraneousModifier, Can't have modifier 'abstract' here., Try removing 'abstract'., {lexeme: abstract}], abstract, abstract)
       parseFields(}, null, null, null, null, null, var, abstract, Instance of 'NoType', foo, DeclarationKind.TopLevel, null, false)
         listener: beginFields(})
         listener: handleNoType(abstract)
@@ -228,7 +228,7 @@
               reportRecoverableError(required, Message[ModifierOutOfOrder, The modifier 'required' should be before the modifier 'covariant'., Try re-ordering the modifiers., {string: required, string2: covariant}])
                 listener: handleRecoverableError(Message[ModifierOutOfOrder, The modifier 'required' should be before the modifier 'covariant'., Try re-ordering the modifiers., {string: required, string2: covariant}], required, required)
               reportRecoverableErrorWithToken(required, Instance of 'Template<(Token) => Message>')
-                listener: handleRecoverableError(Message[ExtraneousModifier, Can't have modifier 'required' here., Try removing 'required'., {token: required}], required, required)
+                listener: handleRecoverableError(Message[ExtraneousModifier, Can't have modifier 'required' here., Try removing 'required'., {lexeme: required}], required, required)
               listener: beginMember()
               isReservedKeyword(;)
               parseFields({, null, null, null, covariant, null, null, required, Instance of 'NoType', x, DeclarationKind.Class, Bar, false)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39776_prime5.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_39776_prime5.dart.expect
index 3804bfe..f733ac0 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_39776_prime5.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39776_prime5.dart.expect
@@ -15,7 +15,7 @@
     beginTopLevelMethod(, null)
       handleNoType()
       handleIdentifier(foo, topLevelFunctionDeclaration)
-      handleRecoverableError(Message[UnexpectedToken, Unexpected token '!'., null, {token: !}], !, !)
+      handleRecoverableError(Message[UnexpectedToken, Unexpected token '!'., null, {lexeme: !}], !, !)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
       endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
@@ -30,7 +30,7 @@
     beginTopLevelMethod(;, null)
       handleNoType(;)
       handleIdentifier(bar, topLevelFunctionDeclaration)
-      handleRecoverableError(Message[UnexpectedToken, Unexpected token '!'., null, {token: !}], !, !)
+      handleRecoverableError(Message[UnexpectedToken, Unexpected token '!'., null, {lexeme: !}], !, !)
       beginTypeVariables(<)
         beginMetadataStar(T)
         endMetadataStar(0)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_39776_prime5.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_39776_prime5.dart.intertwined.expect
index 0fef178..468cde8 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_39776_prime5.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_39776_prime5.dart.intertwined.expect
@@ -16,7 +16,7 @@
           listener: handleIdentifier(foo, topLevelFunctionDeclaration)
         parseMethodTypeVar(foo)
           reportRecoverableErrorWithToken(!, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token '!'., null, {token: !}], !, !)
+            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token '!'., null, {lexeme: !}], !, !)
           listener: handleNoTypeVariables(()
         parseGetterOrFormalParameters(!, foo, false, MemberKind.TopLevelMethod)
           parseFormalParameters(!, MemberKind.TopLevelMethod)
@@ -53,7 +53,7 @@
           listener: handleIdentifier(bar, topLevelFunctionDeclaration)
         parseMethodTypeVar(bar)
           reportRecoverableErrorWithToken(!, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token '!'., null, {token: !}], !, !)
+            listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token '!'., null, {lexeme: !}], !, !)
           listener: beginTypeVariables(<)
           listener: beginMetadataStar(T)
           listener: endMetadataStar(0)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.expect
index 088c5a4..d0ea866 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.expect
@@ -60,7 +60,7 @@
           handleParenthesizedExpression(()
           handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], ;, ;)
           handleConditionalExpressionColon()
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {token: ;}], ;, ;)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {lexeme: ;}], ;, ;)
           handleIdentifier(, expression)
           handleNoTypeArguments(;)
           handleNoArguments(;)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.intertwined.expect
index 5573577..707c726 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.intertwined.expect
@@ -153,7 +153,7 @@
                                 parseSend(:, expression)
                                   ensureIdentifier(:, expression)
                                     reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {token: ;}], ;, ;)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {lexeme: ;}], ;, ;)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(;)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.expect
index 1357097..9f72c57 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.expect
@@ -78,7 +78,7 @@
               handleNoType(Foo)
             endTypeVariable(>, 0, null, null)
           endTypeVariables(<, >)
-          handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ;, ;)
+          handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ;, ;)
           beginFunctionExpression(()
             beginFormalParameters((, MemberKind.Local)
               beginMetadataStar(b)
@@ -95,7 +95,7 @@
           endFunctionExpression((, })
           handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], }, })
           handleConditionalExpressionColon()
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {lexeme: }}], }, })
           handleIdentifier(, expression)
           handleNoTypeArguments(})
           handleNoArguments(})
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.intertwined.expect
index ee731af..2079800 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.intertwined.expect
@@ -138,7 +138,7 @@
                                   listener: endTypeVariables(<, >)
                                   parseLiteralFunctionSuffix(>)
                                     reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {token: ;}], ;, ;)
+                                      listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ;, ;)
                                     parseFunctionExpression(>)
                                       listener: beginFunctionExpression(()
                                       parseFormalParametersRequiredOpt(>, MemberKind.Local)
@@ -177,7 +177,7 @@
                                 parseSend(:, expression)
                                   ensureIdentifier(:, expression)
                                     reportRecoverableErrorWithToken(}, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {lexeme: }}], }, })
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(})
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart
new file mode 100644
index 0000000..b2d9af7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart
@@ -0,0 +1 @@
+Future<List<>>
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.expect
new file mode 100644
index 0000000..311b6f8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.expect
@@ -0,0 +1,52 @@
+Problems reported:
+
+parser/nnbd/issue_44477:1:15: Expected an identifier, but got ''.
+Future<List<>>
+              ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+parser/nnbd/issue_44477:1:13: Expected a type, but got '>>'.
+Future<List<>>
+            ^^
+
+parser/nnbd/issue_44477:1:15: Expected an identifier, but got ''.
+Future<List<>>
+              ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+parser/nnbd/issue_44477:1:15: Expected ';' after this.
+Future<List<>>
+              ^...
+
+WARNING: Reporting at eof --- see below for details.
+
+beginCompilationUnit(Future)
+  beginMetadataStar(Future)
+  endMetadataStar(0)
+  beginTopLevelMember(Future)
+    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+    // WARNING: Reporting at eof for .
+    beginFields()
+      handleIdentifier(Future, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {lexeme: >>}], >>, >>)
+          handleIdentifier(, typeReference)
+          handleNoTypeArguments(>>)
+          handleType(, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+      endTypeArguments(1, <, >)
+      handleType(Future, null)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+      // WARNING: Reporting at eof for .
+      handleIdentifier(, topLevelVariableDeclaration)
+      handleNoFieldInitializer()
+      handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+      // WARNING: Reporting at eof for .
+    endTopLevelFields(null, null, null, null, null, 1, Future, ;)
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.intertwined.expect
new file mode 100644
index 0000000..e90884d
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.intertwined.expect
@@ -0,0 +1,51 @@
+parseUnit(Future)
+  skipErrorTokens(Future)
+  listener: beginCompilationUnit(Future)
+  syntheticPreviousToken(Future)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(Future)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(Future)
+      insertSyntheticIdentifier(>, methodDeclaration, message: null, messageOnToken: null)
+        reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+          listener: // WARNING: Reporting at eof for .
+        rewriter()
+      parseFields(, null, null, null, null, null, null, , Instance of 'ComplexTypeInfo', , DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        ensureIdentifier(, typeReference)
+          listener: handleIdentifier(Future, typeReference)
+        listener: beginTypeArguments(<)
+        ensureIdentifier(<, typeReference)
+          listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        reportRecoverableErrorWithToken(>>, Instance of 'Template<(Token) => Message>')
+          listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '>>'., null, {lexeme: >>}], >>, >>)
+        rewriter()
+        listener: handleIdentifier(, typeReference)
+        listener: handleNoTypeArguments(>>)
+        listener: handleType(, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(Future, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {lexeme: }], , )
+              listener: // WARNING: Reporting at eof for .
+            rewriter()
+          listener: handleIdentifier(, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer()
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+            listener: // WARNING: Reporting at eof for .
+          rewriter()
+        listener: endTopLevelFields(null, null, null, null, null, 1, Future, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(Future)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.parser.expect
new file mode 100644
index 0000000..63970d7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+Future<List<>>;
+
+Future[StringToken]<[BeginToken]List[StringToken]<[BeginToken][SyntheticStringToken]>[SimpleToken]>[SimpleToken][SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.scanner.expect
new file mode 100644
index 0000000..f023442
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_44477.dart.scanner.expect
@@ -0,0 +1,3 @@
+Future<List<>>
+
+Future[StringToken]<[BeginToken]List[StringToken]<[BeginToken]>>[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart
new file mode 100644
index 0000000..e437881
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart
@@ -0,0 +1,32 @@
+// https://github.com/dart-lang/sdk/issues/44379
+
+int x1;
+late int x2;
+late List<int> x3;
+late final int x4;
+late x5;
+; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+late;
+; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+
+main(List<String> args) {
+  int y1;
+  late int y2;
+  late List<int> y3;
+  late final int y4;
+  late y5;
+  ; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+  late;
+  ; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+}
+
+class Foo {
+  int z1;
+  late int z2;
+  late List<int> x3;
+  late final int z4;
+  late z5;
+  ; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+  late;
+  ; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.expect b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.expect
new file mode 100644
index 0000000..405a6f7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.expect
@@ -0,0 +1,343 @@
+Problems reported:
+
+parser/non-nnbd/use_late_in_non_nnbd:4:1: The modifier 'late' is only available in null safe libraries.
+late int x2;
+^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:5:1: The modifier 'late' is only available in null safe libraries.
+late List<int> x3;
+^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:6:1: The modifier 'late' is only available in null safe libraries.
+late final int x4;
+^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:8:1: Unexpected token ';'.
+; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+^
+
+parser/non-nnbd/use_late_in_non_nnbd:9:1: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+late;
+^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:10:1: Unexpected token ';'.
+; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+^
+
+parser/non-nnbd/use_late_in_non_nnbd:14:3: The modifier 'late' is only available in null safe libraries.
+  late int y2;
+  ^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:15:3: The modifier 'late' is only available in null safe libraries.
+  late List<int> y3;
+  ^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:16:3: The modifier 'late' is only available in null safe libraries.
+  late final int y4;
+  ^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:25:3: The modifier 'late' is only available in null safe libraries.
+  late int z2;
+  ^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:26:3: The modifier 'late' is only available in null safe libraries.
+  late List<int> x3;
+  ^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:27:3: The modifier 'late' is only available in null safe libraries.
+  late final int z4;
+  ^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:29:3: Expected a class member, but got ';'.
+  ; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+  ^
+
+parser/non-nnbd/use_late_in_non_nnbd:30:3: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+  late;
+  ^^^^
+
+parser/non-nnbd/use_late_in_non_nnbd:31:3: Expected a class member, but got ';'.
+  ; // Meant to confuse so `.next`-ing makes it look like the end of a field.
+  ^
+
+beginCompilationUnit(int)
+  beginMetadataStar(int)
+  endMetadataStar(0)
+  beginTopLevelMember(int)
+    beginFields()
+      handleIdentifier(int, typeReference)
+      handleNoTypeArguments(x1)
+      handleType(int, null)
+      handleIdentifier(x1, topLevelVariableDeclaration)
+      handleNoFieldInitializer(;)
+    endTopLevelFields(null, null, null, null, null, 1, int, ;)
+  endTopLevelDeclaration(late)
+  beginMetadataStar(late)
+  endMetadataStar(0)
+  beginTopLevelMember(late)
+    handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+    beginFields(late)
+      handleIdentifier(int, typeReference)
+      handleNoTypeArguments(x2)
+      handleType(int, null)
+      handleIdentifier(x2, topLevelVariableDeclaration)
+      handleNoFieldInitializer(;)
+    endTopLevelFields(null, null, null, late, null, 1, int, ;)
+  endTopLevelDeclaration(late)
+  beginMetadataStar(late)
+  endMetadataStar(0)
+  beginTopLevelMember(late)
+    handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+    beginFields(late)
+      handleIdentifier(List, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(>)
+        handleType(int, null)
+      endTypeArguments(1, <, >)
+      handleType(List, null)
+      handleIdentifier(x3, topLevelVariableDeclaration)
+      handleNoFieldInitializer(;)
+    endTopLevelFields(null, null, null, late, null, 1, List, ;)
+  endTopLevelDeclaration(late)
+  beginMetadataStar(late)
+  endMetadataStar(0)
+  beginTopLevelMember(late)
+    handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+    beginFields(late)
+      handleIdentifier(int, typeReference)
+      handleNoTypeArguments(x4)
+      handleType(int, null)
+      handleIdentifier(x4, topLevelVariableDeclaration)
+      handleNoFieldInitializer(;)
+    endTopLevelFields(null, null, null, late, final, 1, final, ;)
+  endTopLevelDeclaration(late)
+  beginMetadataStar(late)
+  endMetadataStar(0)
+  beginTopLevelMember(late)
+    beginFields(;)
+      handleIdentifier(late, typeReference)
+      handleNoTypeArguments(x5)
+      handleType(late, null)
+      handleIdentifier(x5, topLevelVariableDeclaration)
+      handleNoFieldInitializer(;)
+    endTopLevelFields(null, null, null, null, null, 1, late, ;)
+  endTopLevelDeclaration(;)
+  beginMetadataStar(;)
+  endMetadataStar(0)
+  beginTopLevelMember(;)
+    handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ;, ;)
+    handleInvalidTopLevelDeclaration(;)
+  endTopLevelDeclaration(late)
+  beginMetadataStar(late)
+  endMetadataStar(0)
+  beginTopLevelMember(late)
+    beginFields(;)
+      handleRecoverableError(MissingConstFinalVarOrType, late, late)
+      handleNoType(;)
+      handleIdentifier(late, topLevelVariableDeclaration)
+      handleNoFieldInitializer(;)
+    endTopLevelFields(null, null, null, null, null, 1, late, ;)
+  endTopLevelDeclaration(;)
+  beginMetadataStar(;)
+  endMetadataStar(0)
+  beginTopLevelMember(;)
+    handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ;, ;)
+    handleInvalidTopLevelDeclaration(;)
+  endTopLevelDeclaration(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(;, null)
+      handleNoType(;)
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginMetadataStar(List)
+        endMetadataStar(0)
+        beginFormalParameter(List, MemberKind.TopLevelMethod, null, null, null)
+          handleIdentifier(List, typeReference)
+          beginTypeArguments(<)
+            handleIdentifier(String, typeReference)
+            handleNoTypeArguments(>)
+            handleType(String, null)
+          endTypeArguments(1, <, >)
+          handleType(List, null)
+          handleIdentifier(args, formalParameterDeclaration)
+          handleFormalParameterWithoutValue())
+        endFormalParameter(null, null, args, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(y1)
+        handleType(int, null)
+        beginVariablesDeclaration(y1, null, null)
+          handleIdentifier(y1, localVariableDeclaration)
+          beginInitializedIdentifier(y1)
+            handleNoVariableInitializer(y1)
+          endInitializedIdentifier(y1)
+        endVariablesDeclaration(1, ;)
+        handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(y2)
+        handleType(int, null)
+        beginVariablesDeclaration(y2, late, null)
+          handleIdentifier(y2, localVariableDeclaration)
+          beginInitializedIdentifier(y2)
+            handleNoVariableInitializer(y2)
+          endInitializedIdentifier(y2)
+        endVariablesDeclaration(1, ;)
+        handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+        beginMetadataStar(List)
+        endMetadataStar(0)
+        handleIdentifier(List, typeReference)
+        beginTypeArguments(<)
+          handleIdentifier(int, typeReference)
+          handleNoTypeArguments(>)
+          handleType(int, null)
+        endTypeArguments(1, <, >)
+        handleType(List, null)
+        beginVariablesDeclaration(y3, late, null)
+          handleIdentifier(y3, localVariableDeclaration)
+          beginInitializedIdentifier(y3)
+            handleNoVariableInitializer(y3)
+          endInitializedIdentifier(y3)
+        endVariablesDeclaration(1, ;)
+        handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(y4)
+        handleType(int, null)
+        beginVariablesDeclaration(y4, late, final)
+          handleIdentifier(y4, localVariableDeclaration)
+          beginInitializedIdentifier(y4)
+            handleNoVariableInitializer(y4)
+          endInitializedIdentifier(y4)
+        endVariablesDeclaration(1, ;)
+        beginMetadataStar(late)
+        endMetadataStar(0)
+        handleIdentifier(late, typeReference)
+        handleNoTypeArguments(y5)
+        handleType(late, null)
+        beginVariablesDeclaration(y5, null, null)
+          handleIdentifier(y5, localVariableDeclaration)
+          beginInitializedIdentifier(y5)
+            handleNoVariableInitializer(y5)
+          endInitializedIdentifier(y5)
+        endVariablesDeclaration(1, ;)
+        handleEmptyStatement(;)
+        handleIdentifier(late, expression)
+        handleNoTypeArguments(;)
+        handleNoArguments(;)
+        handleSend(late, ;)
+        handleExpressionStatement(;)
+        handleEmptyStatement(;)
+      endBlockFunctionBody(8, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(Foo, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(class, null, Foo)
+      handleNoType(Foo)
+      handleClassExtends(null, 1)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginFields({)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(z1)
+            handleType(int, null)
+            handleIdentifier(z1, fieldDeclaration)
+            handleNoFieldInitializer(;)
+          endClassFields(null, null, null, null, null, null, 1, int, ;)
+        endMember()
+        beginMetadataStar(late)
+        endMetadataStar(0)
+        handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+        beginMember()
+          beginFields(late)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(z2)
+            handleType(int, null)
+            handleIdentifier(z2, fieldDeclaration)
+            handleNoFieldInitializer(;)
+          endClassFields(null, null, null, null, late, null, 1, int, ;)
+        endMember()
+        beginMetadataStar(late)
+        endMetadataStar(0)
+        handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+        beginMember()
+          beginFields(late)
+            handleIdentifier(List, typeReference)
+            beginTypeArguments(<)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(>)
+              handleType(int, null)
+            endTypeArguments(1, <, >)
+            handleType(List, null)
+            handleIdentifier(x3, fieldDeclaration)
+            handleNoFieldInitializer(;)
+          endClassFields(null, null, null, null, late, null, 1, List, ;)
+        endMember()
+        beginMetadataStar(late)
+        endMetadataStar(0)
+        handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+        beginMember()
+          beginFields(late)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(z4)
+            handleType(int, null)
+            handleIdentifier(z4, fieldDeclaration)
+            handleNoFieldInitializer(;)
+          endClassFields(null, null, null, null, late, final, 1, final, ;)
+        endMember()
+        beginMetadataStar(late)
+        endMetadataStar(0)
+        beginMember()
+          beginFields(;)
+            handleIdentifier(late, typeReference)
+            handleNoTypeArguments(z5)
+            handleType(late, null)
+            handleIdentifier(z5, fieldDeclaration)
+            handleNoFieldInitializer(;)
+          endClassFields(null, null, null, null, null, null, 1, late, ;)
+        endMember()
+        beginMetadataStar(;)
+        endMetadataStar(0)
+        beginMember()
+          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got ';'., null, {lexeme: ;}], ;, ;)
+          handleInvalidMember(;)
+        endMember()
+        beginMetadataStar(late)
+        endMetadataStar(0)
+        beginMember()
+          beginFields(;)
+            handleRecoverableError(MissingConstFinalVarOrType, late, late)
+            handleNoType(;)
+            handleIdentifier(late, fieldDeclaration)
+            handleNoFieldInitializer(;)
+          endClassFields(null, null, null, null, null, null, 1, late, ;)
+        endMember()
+        beginMetadataStar(;)
+        endMetadataStar(0)
+        beginMember()
+          handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got ';'., null, {lexeme: ;}], ;, ;)
+          handleInvalidMember(;)
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 8, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration()
+endCompilationUnit(10, )
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.intertwined.expect b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.intertwined.expect
new file mode 100644
index 0000000..350fa9e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.intertwined.expect
@@ -0,0 +1,500 @@
+parseUnit(int)
+  skipErrorTokens(int)
+  listener: beginCompilationUnit(int)
+  syntheticPreviousToken(int)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(int)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(int)
+      parseFields(, null, null, null, null, null, null, , Instance of 'SimpleType', x1, DeclarationKind.TopLevel, null, false)
+        listener: beginFields()
+        listener: handleIdentifier(int, typeReference)
+        listener: handleNoTypeArguments(x1)
+        listener: handleType(int, null)
+        ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(x1, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(x1, x1, null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer(;)
+        listener: endTopLevelFields(null, null, null, null, null, 1, int, ;)
+  listener: endTopLevelDeclaration(late)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(late)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(late)
+      indicatesMethodOrField(;)
+      reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+      parseFields(late, null, null, null, null, late, null, late, Instance of 'SimpleType', x2, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(late)
+        listener: handleIdentifier(int, typeReference)
+        listener: handleNoTypeArguments(x2)
+        listener: handleType(int, null)
+        ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(x2, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(x2, x2, late, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer(;)
+        listener: endTopLevelFields(null, null, null, late, null, 1, int, ;)
+  listener: endTopLevelDeclaration(late)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(late)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(late)
+      indicatesMethodOrField(;)
+      reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+      parseFields(late, null, null, null, null, late, null, late, Instance of 'SimpleTypeWith1Argument', x3, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(late)
+        listener: handleIdentifier(List, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(int, typeReference)
+        listener: handleNoTypeArguments(>)
+        listener: handleType(int, null)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(List, null)
+        ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(x3, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(x3, x3, late, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer(;)
+        listener: endTopLevelFields(null, null, null, late, null, 1, List, ;)
+  listener: endTopLevelDeclaration(late)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(late)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(late)
+      indicatesMethodOrField(;)
+      reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+      parseFields(late, null, null, null, null, late, final, final, Instance of 'SimpleType', x4, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(late)
+        listener: handleIdentifier(int, typeReference)
+        listener: handleNoTypeArguments(x4)
+        listener: handleType(int, null)
+        ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(x4, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(x4, x4, late, null, null, final, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer(;)
+        listener: endTopLevelFields(null, null, null, late, final, 1, final, ;)
+  listener: endTopLevelDeclaration(late)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(late)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(late)
+      parseFields(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', x5, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        listener: handleIdentifier(late, typeReference)
+        listener: handleNoTypeArguments(x5)
+        listener: handleType(late, null)
+        ensureIdentifierPotentiallyRecovered(late, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(x5, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(x5, x5, null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer(;)
+        listener: endTopLevelFields(null, null, null, null, null, 1, late, ;)
+  listener: endTopLevelDeclaration(;)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(;)
+      listener: endMetadataStar(0)
+    listener: beginTopLevelMember(;)
+    parseInvalidTopLevelDeclaration(;)
+      reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ;, ;)
+      listener: handleInvalidTopLevelDeclaration(;)
+  listener: endTopLevelDeclaration(late)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(late)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(late)
+      isReservedKeyword(;)
+      parseFields(;, null, null, null, null, null, null, ;, Instance of 'NoType', late, DeclarationKind.TopLevel, null, false)
+        listener: beginFields(;)
+        reportRecoverableError(late, MissingConstFinalVarOrType)
+          listener: handleRecoverableError(MissingConstFinalVarOrType, late, late)
+        listener: handleNoType(;)
+        ensureIdentifierPotentiallyRecovered(;, topLevelVariableDeclaration, false)
+          listener: handleIdentifier(late, topLevelVariableDeclaration)
+        parseFieldInitializerOpt(late, late, null, null, null, null, DeclarationKind.TopLevel, null)
+          listener: handleNoFieldInitializer(;)
+        listener: endTopLevelFields(null, null, null, null, null, 1, late, ;)
+  listener: endTopLevelDeclaration(;)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(;)
+      listener: endMetadataStar(0)
+    listener: beginTopLevelMember(;)
+    parseInvalidTopLevelDeclaration(;)
+      reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[UnexpectedToken, Unexpected token ';'., null, {lexeme: ;}], ;, ;)
+      listener: handleInvalidTopLevelDeclaration(;)
+  listener: endTopLevelDeclaration(main)
+  parseTopLevelDeclarationImpl(;, Instance of 'DirectiveContext')
+    parseMetadataStar(;)
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(;)
+      listener: beginTopLevelMember(main)
+      isReservedKeyword(()
+      parseTopLevelMethod(;, null, ;, Instance of 'NoType', null, main, false)
+        listener: beginTopLevelMethod(;, null)
+        listener: handleNoType(;)
+        ensureIdentifierPotentiallyRecovered(;, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(main, topLevelFunctionDeclaration)
+        parseMethodTypeVar(main)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(main, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+                parseMetadataStar(()
+                  listener: beginMetadataStar(List)
+                  listener: endMetadataStar(0)
+                listener: beginFormalParameter(List, MemberKind.TopLevelMethod, null, null, null)
+                listener: handleIdentifier(List, typeReference)
+                listener: beginTypeArguments(<)
+                listener: handleIdentifier(String, typeReference)
+                listener: handleNoTypeArguments(>)
+                listener: handleType(String, null)
+                listener: endTypeArguments(1, <, >)
+                listener: handleType(List, null)
+                ensureIdentifier(>, formalParameterDeclaration)
+                  listener: handleIdentifier(args, formalParameterDeclaration)
+                listener: handleFormalParameterWithoutValue())
+                listener: endFormalParameter(null, null, args, null, null, FormalParameterKind.mandatory, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, int)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(y1)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(y1)
+                listener: handleType(int, null)
+                listener: beginVariablesDeclaration(y1, null, null)
+                parseVariablesDeclarationRest(int, true)
+                  parseOptionallyInitializedIdentifier(int)
+                    ensureIdentifier(int, localVariableDeclaration)
+                      listener: handleIdentifier(y1, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(y1)
+                    parseVariableInitializerOpt(y1)
+                      listener: handleNoVariableInitializer(y1)
+                    listener: endInitializedIdentifier(y1)
+                  ensureSemicolon(y1)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, late)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                indicatesMethodOrField(;)
+                reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+                  listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+                looksLikeLocalFunction(y2)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(y2)
+                listener: handleType(int, null)
+                listener: beginVariablesDeclaration(y2, late, null)
+                parseVariablesDeclarationRest(int, true)
+                  parseOptionallyInitializedIdentifier(int)
+                    ensureIdentifier(int, localVariableDeclaration)
+                      listener: handleIdentifier(y2, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(y2)
+                    parseVariableInitializerOpt(y2)
+                      listener: handleNoVariableInitializer(y2)
+                    listener: endInitializedIdentifier(y2)
+                  ensureSemicolon(y2)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, late)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                indicatesMethodOrField(;)
+                reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+                  listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+                looksLikeLocalFunction(y3)
+                listener: beginMetadataStar(List)
+                listener: endMetadataStar(0)
+                listener: handleIdentifier(List, typeReference)
+                listener: beginTypeArguments(<)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(>)
+                listener: handleType(int, null)
+                listener: endTypeArguments(1, <, >)
+                listener: handleType(List, null)
+                listener: beginVariablesDeclaration(y3, late, null)
+                parseVariablesDeclarationRest(>, true)
+                  parseOptionallyInitializedIdentifier(>)
+                    ensureIdentifier(>, localVariableDeclaration)
+                      listener: handleIdentifier(y3, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(y3)
+                    parseVariableInitializerOpt(y3)
+                      listener: handleNoVariableInitializer(y3)
+                    listener: endInitializedIdentifier(y3)
+                  ensureSemicolon(y3)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, late)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                indicatesMethodOrField(;)
+                reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+                  listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+                looksLikeLocalFunction(y4)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(y4)
+                listener: handleType(int, null)
+                listener: beginVariablesDeclaration(y4, late, final)
+                parseVariablesDeclarationRest(int, true)
+                  parseOptionallyInitializedIdentifier(int)
+                    ensureIdentifier(int, localVariableDeclaration)
+                      listener: handleIdentifier(y4, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(y4)
+                    parseVariableInitializerOpt(y4)
+                      listener: handleNoVariableInitializer(y4)
+                    listener: endInitializedIdentifier(y4)
+                  ensureSemicolon(y4)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, late)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                looksLikeLocalFunction(y5)
+                listener: beginMetadataStar(late)
+                listener: endMetadataStar(0)
+                listener: handleIdentifier(late, typeReference)
+                listener: handleNoTypeArguments(y5)
+                listener: handleType(late, null)
+                listener: beginVariablesDeclaration(y5, null, null)
+                parseVariablesDeclarationRest(late, true)
+                  parseOptionallyInitializedIdentifier(late)
+                    ensureIdentifier(late, localVariableDeclaration)
+                      listener: handleIdentifier(y5, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(y5)
+                    parseVariableInitializerOpt(y5)
+                      listener: handleNoVariableInitializer(y5)
+                    listener: endInitializedIdentifier(y5)
+                  ensureSemicolon(y5)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, ;)
+          parseStatement(;)
+            parseStatementX(;)
+              parseEmptyStatement(;)
+                listener: handleEmptyStatement(;)
+          notEofOrValue(}, late)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                looksLikeLocalFunction(late)
+                parseExpressionStatement(;)
+                  parseExpression(;)
+                    parsePrecedenceExpression(;, 1, true)
+                      parseUnaryExpression(;, true)
+                        parsePrimary(;, expression)
+                          parseSendOrFunctionLiteral(;, expression)
+                            parseSend(;, expression)
+                              ensureIdentifier(;, expression)
+                                listener: handleIdentifier(late, expression)
+                              listener: handleNoTypeArguments(;)
+                              parseArgumentsOpt(late)
+                                listener: handleNoArguments(;)
+                              listener: handleSend(late, ;)
+                  ensureSemicolon(late)
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, ;)
+          parseStatement(;)
+            parseStatementX(;)
+              parseEmptyStatement(;)
+                listener: handleEmptyStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(8, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration(class)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(class)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(}, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(}, class)
+      parseClassOrNamedMixinApplication(null, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(class)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(Foo, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(class, null, Foo)
+        parseClass(Foo, class, class, Foo)
+          parseClassHeaderOpt(Foo, class, class)
+            parseClassExtendsOpt(Foo)
+              listener: handleNoType(Foo)
+              listener: handleClassExtends(null, 1)
+            parseWithClauseOpt(Foo)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(Foo)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(Foo, DeclarationKind.Class, Foo)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, Foo)
+              parseMetadataStar({)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseFields({, null, null, null, null, null, null, {, Instance of 'SimpleType', z1, DeclarationKind.Class, Foo, false)
+                listener: beginFields({)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(z1)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false)
+                  listener: handleIdentifier(z1, fieldDeclaration)
+                parseFieldInitializerOpt(z1, z1, null, null, null, null, DeclarationKind.Class, Foo)
+                  listener: handleNoFieldInitializer(;)
+                listener: endClassFields(null, null, null, null, null, null, 1, int, ;)
+              listener: endMember()
+            notEofOrValue(}, late)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Foo)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(late)
+                listener: endMetadataStar(0)
+              indicatesMethodOrField(;)
+              reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+                listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+              listener: beginMember()
+              parseFields(late, null, null, null, null, late, null, late, Instance of 'SimpleType', z2, DeclarationKind.Class, Foo, false)
+                listener: beginFields(late)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(z2)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false)
+                  listener: handleIdentifier(z2, fieldDeclaration)
+                parseFieldInitializerOpt(z2, z2, late, null, null, null, DeclarationKind.Class, Foo)
+                  listener: handleNoFieldInitializer(;)
+                listener: endClassFields(null, null, null, null, late, null, 1, int, ;)
+              listener: endMember()
+            notEofOrValue(}, late)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Foo)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(late)
+                listener: endMetadataStar(0)
+              indicatesMethodOrField(;)
+              reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+                listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+              listener: beginMember()
+              parseFields(late, null, null, null, null, late, null, late, Instance of 'SimpleTypeWith1Argument', x3, DeclarationKind.Class, Foo, false)
+                listener: beginFields(late)
+                listener: handleIdentifier(List, typeReference)
+                listener: beginTypeArguments(<)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(>)
+                listener: handleType(int, null)
+                listener: endTypeArguments(1, <, >)
+                listener: handleType(List, null)
+                ensureIdentifierPotentiallyRecovered(>, fieldDeclaration, false)
+                  listener: handleIdentifier(x3, fieldDeclaration)
+                parseFieldInitializerOpt(x3, x3, late, null, null, null, DeclarationKind.Class, Foo)
+                  listener: handleNoFieldInitializer(;)
+                listener: endClassFields(null, null, null, null, late, null, 1, List, ;)
+              listener: endMember()
+            notEofOrValue(}, late)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Foo)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(late)
+                listener: endMetadataStar(0)
+              indicatesMethodOrField(;)
+              reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
+                listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'late' is only available in null safe libraries., null, {lexeme: late}], late, late)
+              listener: beginMember()
+              parseFields(late, null, null, null, null, late, final, final, Instance of 'SimpleType', z4, DeclarationKind.Class, Foo, false)
+                listener: beginFields(late)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(z4)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false)
+                  listener: handleIdentifier(z4, fieldDeclaration)
+                parseFieldInitializerOpt(z4, z4, late, null, null, final, DeclarationKind.Class, Foo)
+                  listener: handleNoFieldInitializer(;)
+                listener: endClassFields(null, null, null, null, late, final, 1, final, ;)
+              listener: endMember()
+            notEofOrValue(}, late)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Foo)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(late)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseFields(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', z5, DeclarationKind.Class, Foo, false)
+                listener: beginFields(;)
+                listener: handleIdentifier(late, typeReference)
+                listener: handleNoTypeArguments(z5)
+                listener: handleType(late, null)
+                ensureIdentifierPotentiallyRecovered(late, fieldDeclaration, false)
+                  listener: handleIdentifier(z5, fieldDeclaration)
+                parseFieldInitializerOpt(z5, z5, null, null, null, null, DeclarationKind.Class, Foo)
+                  listener: handleNoFieldInitializer(;)
+                listener: endClassFields(null, null, null, null, null, null, 1, late, ;)
+              listener: endMember()
+            notEofOrValue(}, ;)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Foo)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(;)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              recoverFromInvalidMember(;, ;, null, null, null, null, null, null, ;, Instance of 'NoType', null, DeclarationKind.Class, Foo)
+                reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
+                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got ';'., null, {lexeme: ;}], ;, ;)
+                listener: handleInvalidMember(;)
+                listener: endMember()
+            notEofOrValue(}, late)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Foo)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(late)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(;)
+              parseFields(;, null, null, null, null, null, null, ;, Instance of 'NoType', late, DeclarationKind.Class, Foo, false)
+                listener: beginFields(;)
+                reportRecoverableError(late, MissingConstFinalVarOrType)
+                  listener: handleRecoverableError(MissingConstFinalVarOrType, late, late)
+                listener: handleNoType(;)
+                ensureIdentifierPotentiallyRecovered(;, fieldDeclaration, false)
+                  listener: handleIdentifier(late, fieldDeclaration)
+                parseFieldInitializerOpt(late, late, null, null, null, null, DeclarationKind.Class, Foo)
+                  listener: handleNoFieldInitializer(;)
+                listener: endClassFields(null, null, null, null, null, null, 1, late, ;)
+              listener: endMember()
+            notEofOrValue(}, ;)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Foo)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(;)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              recoverFromInvalidMember(;, ;, null, null, null, null, null, null, ;, Instance of 'NoType', null, DeclarationKind.Class, Foo)
+                reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
+                  listener: handleRecoverableError(Message[ExpectedClassMember, Expected a class member, but got ';'., null, {lexeme: ;}], ;, ;)
+                listener: handleInvalidMember(;)
+                listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 8, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(int)
+  listener: endCompilationUnit(10, )
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.parser.expect b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.parser.expect
new file mode 100644
index 0000000..272afaa
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.parser.expect
@@ -0,0 +1,61 @@
+int x1;
+late int x2;
+late List<int> x3;
+late final int x4;
+late x5;
+;
+late;
+;
+
+main(List<String> args) {
+int y1;
+late int y2;
+late List<int> y3;
+late final int y4;
+late y5;
+;
+late;
+;
+}
+
+class Foo {
+int z1;
+late int z2;
+late List<int> x3;
+late final int z4;
+late z5;
+;
+late;
+;
+}
+
+int[StringToken] x1[StringToken];[SimpleToken]
+late[StringToken] int[StringToken] x2[StringToken];[SimpleToken]
+late[StringToken] List[StringToken]<[BeginToken]int[StringToken]>[SimpleToken] x3[StringToken];[SimpleToken]
+late[StringToken] final[KeywordToken] int[StringToken] x4[StringToken];[SimpleToken]
+late[StringToken] x5[StringToken];[SimpleToken]
+;[SimpleToken]
+late[StringToken];[SimpleToken]
+;[SimpleToken]
+
+main[StringToken]([BeginToken]List[StringToken]<[BeginToken]String[StringToken]>[SimpleToken] args[StringToken])[SimpleToken] {[BeginToken]
+int[StringToken] y1[StringToken];[SimpleToken]
+late[StringToken] int[StringToken] y2[StringToken];[SimpleToken]
+late[StringToken] List[StringToken]<[BeginToken]int[StringToken]>[SimpleToken] y3[StringToken];[SimpleToken]
+late[StringToken] final[KeywordToken] int[StringToken] y4[StringToken];[SimpleToken]
+late[StringToken] y5[StringToken];[SimpleToken]
+;[SimpleToken]
+late[StringToken];[SimpleToken]
+;[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Foo[StringToken] {[BeginToken]
+int[StringToken] z1[StringToken];[SimpleToken]
+late[StringToken] int[StringToken] z2[StringToken];[SimpleToken]
+late[StringToken] List[StringToken]<[BeginToken]int[StringToken]>[SimpleToken] x3[StringToken];[SimpleToken]
+late[StringToken] final[KeywordToken] int[StringToken] z4[StringToken];[SimpleToken]
+late[StringToken] z5[StringToken];[SimpleToken]
+;[SimpleToken]
+late[StringToken];[SimpleToken]
+;[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.scanner.expect b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.scanner.expect
new file mode 100644
index 0000000..272afaa
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_late_in_non_nnbd.dart.scanner.expect
@@ -0,0 +1,61 @@
+int x1;
+late int x2;
+late List<int> x3;
+late final int x4;
+late x5;
+;
+late;
+;
+
+main(List<String> args) {
+int y1;
+late int y2;
+late List<int> y3;
+late final int y4;
+late y5;
+;
+late;
+;
+}
+
+class Foo {
+int z1;
+late int z2;
+late List<int> x3;
+late final int z4;
+late z5;
+;
+late;
+;
+}
+
+int[StringToken] x1[StringToken];[SimpleToken]
+late[StringToken] int[StringToken] x2[StringToken];[SimpleToken]
+late[StringToken] List[StringToken]<[BeginToken]int[StringToken]>[SimpleToken] x3[StringToken];[SimpleToken]
+late[StringToken] final[KeywordToken] int[StringToken] x4[StringToken];[SimpleToken]
+late[StringToken] x5[StringToken];[SimpleToken]
+;[SimpleToken]
+late[StringToken];[SimpleToken]
+;[SimpleToken]
+
+main[StringToken]([BeginToken]List[StringToken]<[BeginToken]String[StringToken]>[SimpleToken] args[StringToken])[SimpleToken] {[BeginToken]
+int[StringToken] y1[StringToken];[SimpleToken]
+late[StringToken] int[StringToken] y2[StringToken];[SimpleToken]
+late[StringToken] List[StringToken]<[BeginToken]int[StringToken]>[SimpleToken] y3[StringToken];[SimpleToken]
+late[StringToken] final[KeywordToken] int[StringToken] y4[StringToken];[SimpleToken]
+late[StringToken] y5[StringToken];[SimpleToken]
+;[SimpleToken]
+late[StringToken];[SimpleToken]
+;[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Foo[StringToken] {[BeginToken]
+int[StringToken] z1[StringToken];[SimpleToken]
+late[StringToken] int[StringToken] z2[StringToken];[SimpleToken]
+late[StringToken] List[StringToken]<[BeginToken]int[StringToken]>[SimpleToken] x3[StringToken];[SimpleToken]
+late[StringToken] final[KeywordToken] int[StringToken] z4[StringToken];[SimpleToken]
+late[StringToken] z5[StringToken];[SimpleToken]
+;[SimpleToken]
+late[StringToken];[SimpleToken]
+;[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart
new file mode 100644
index 0000000..bc770a6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart
@@ -0,0 +1,17 @@
+void foo1({required int x1}) {
+  print(x);
+}
+
+void foo2({required x2}) {
+  print(x);
+}
+
+void foo3({required required x3}) {
+  print(x);
+}
+
+class Foo {
+  void foo4({required covariant int x4}) {
+    print(x);
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.expect b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.expect
new file mode 100644
index 0000000..645cb48
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.expect
@@ -0,0 +1,175 @@
+Problems reported:
+
+parser/non-nnbd/use_required_in_non_nnbd:1:12: The modifier 'required' is only available in null safe libraries.
+void foo1({required int x1}) {
+           ^^^^^^^^
+
+parser/non-nnbd/use_required_in_non_nnbd:9:12: The modifier 'required' is only available in null safe libraries.
+void foo3({required required x3}) {
+           ^^^^^^^^
+
+parser/non-nnbd/use_required_in_non_nnbd:14:14: The modifier 'required' is only available in null safe libraries.
+  void foo4({required covariant int x4}) {
+             ^^^^^^^^
+
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null)
+      handleVoidKeyword(void)
+      handleIdentifier(foo1, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginOptionalFormalParameters({)
+          beginMetadataStar(required)
+          endMetadataStar(0)
+          handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'required' is only available in null safe libraries., null, {lexeme: required}], required, required)
+          beginFormalParameter(int, MemberKind.TopLevelMethod, required, null, null)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(x1)
+            handleType(int, null)
+            handleIdentifier(x1, formalParameterDeclaration)
+            handleFormalParameterWithoutValue(})
+          endFormalParameter(null, null, x1, null, null, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+        endOptionalFormalParameters(1, {, })
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(print, expression)
+        handleNoTypeArguments(()
+        beginArguments(()
+          handleIdentifier(x, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(x, ))
+        endArguments(1, (, ))
+        handleSend(print, ;)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(}, null)
+      handleVoidKeyword(void)
+      handleIdentifier(foo2, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginOptionalFormalParameters({)
+          beginMetadataStar(required)
+          endMetadataStar(0)
+          beginFormalParameter(required, MemberKind.TopLevelMethod, null, null, null)
+            handleIdentifier(required, typeReference)
+            handleNoTypeArguments(x2)
+            handleType(required, null)
+            handleIdentifier(x2, formalParameterDeclaration)
+            handleFormalParameterWithoutValue(})
+          endFormalParameter(null, null, x2, null, null, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+        endOptionalFormalParameters(1, {, })
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(print, expression)
+        handleNoTypeArguments(()
+        beginArguments(()
+          handleIdentifier(x, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(x, ))
+        endArguments(1, (, ))
+        handleSend(print, ;)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(}, null)
+      handleVoidKeyword(void)
+      handleIdentifier(foo3, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+        beginOptionalFormalParameters({)
+          beginMetadataStar(required)
+          endMetadataStar(0)
+          handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'required' is only available in null safe libraries., null, {lexeme: required}], required, required)
+          beginFormalParameter(required, MemberKind.TopLevelMethod, required, null, null)
+            handleIdentifier(required, typeReference)
+            handleNoTypeArguments(x3)
+            handleType(required, null)
+            handleIdentifier(x3, formalParameterDeclaration)
+            handleFormalParameterWithoutValue(})
+          endFormalParameter(null, null, x3, null, null, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+        endOptionalFormalParameters(1, {, })
+      endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(print, expression)
+        handleNoTypeArguments(()
+        beginArguments(()
+          handleIdentifier(x, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(x, ))
+        endArguments(1, (, ))
+        handleSend(print, ;)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(Foo, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(class, null, Foo)
+      handleNoType(Foo)
+      handleClassExtends(null, 1)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(void)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, foo4)
+            handleVoidKeyword(void)
+            handleIdentifier(foo4, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginOptionalFormalParameters({)
+                beginMetadataStar(required)
+                endMetadataStar(0)
+                handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'required' is only available in null safe libraries., null, {lexeme: required}], required, required)
+                beginFormalParameter(covariant, MemberKind.NonStaticMethod, required, covariant, null)
+                  handleIdentifier(int, typeReference)
+                  handleNoTypeArguments(x4)
+                  handleType(int, null)
+                  handleIdentifier(x4, formalParameterDeclaration)
+                  handleFormalParameterWithoutValue(})
+                endFormalParameter(null, null, x4, null, null, FormalParameterKind.optionalNamed, MemberKind.NonStaticMethod)
+              endOptionalFormalParameters(1, {, })
+            endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(x, expression)
+                handleNoTypeArguments())
+                handleNoArguments())
+                handleSend(x, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, void, (, null, })
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration()
+endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.intertwined.expect b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.intertwined.expect
new file mode 100644
index 0000000..baad9f3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.intertwined.expect
@@ -0,0 +1,360 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, , Instance of 'VoidType', null, foo1, false)
+        listener: beginTopLevelMethod(, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(foo1, topLevelFunctionDeclaration)
+        parseMethodTypeVar(foo1)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(foo1, foo1, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(foo1, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseOptionalNamedParameters((, MemberKind.TopLevelMethod)
+                listener: beginOptionalFormalParameters({)
+                parseFormalParameter({, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+                  parseMetadataStar({)
+                    listener: beginMetadataStar(required)
+                    listener: endMetadataStar(0)
+                  reportRecoverableErrorWithToken(required, Instance of 'Template<(Token) => Message>')
+                    listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'required' is only available in null safe libraries., null, {lexeme: required}], required, required)
+                  listener: beginFormalParameter(int, MemberKind.TopLevelMethod, required, null, null)
+                  listener: handleIdentifier(int, typeReference)
+                  listener: handleNoTypeArguments(x1)
+                  listener: handleType(int, null)
+                  ensureIdentifier(int, formalParameterDeclaration)
+                    listener: handleIdentifier(x1, formalParameterDeclaration)
+                  listener: handleFormalParameterWithoutValue(})
+                  listener: endFormalParameter(null, null, x1, null, null, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+                listener: endOptionalFormalParameters(1, {, })
+              ensureCloseParen(}, ()
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, print)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(print)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            looksLikeFunctionBody(;)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(print, expression)
+                              listener: handleNoTypeArguments(()
+                              parseArgumentsOpt(print)
+                                parseArguments(print)
+                                  parseArgumentsRest(()
+                                    listener: beginArguments(()
+                                    parseExpression(()
+                                      parsePrecedenceExpression((, 1, true)
+                                        parseUnaryExpression((, true)
+                                          parsePrimary((, expression)
+                                            parseSendOrFunctionLiteral((, expression)
+                                              parseSend((, expression)
+                                                ensureIdentifier((, expression)
+                                                  listener: handleIdentifier(x, expression)
+                                                listener: handleNoTypeArguments())
+                                                parseArgumentsOpt(x)
+                                                  listener: handleNoArguments())
+                                                listener: handleSend(x, ))
+                                    listener: endArguments(1, (, ))
+                              listener: handleSend(print, ;)
+                  ensureSemicolon())
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration(void)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(})
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(}, null, }, Instance of 'VoidType', null, foo2, false)
+        listener: beginTopLevelMethod(}, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(foo2, topLevelFunctionDeclaration)
+        parseMethodTypeVar(foo2)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(foo2, foo2, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(foo2, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseOptionalNamedParameters((, MemberKind.TopLevelMethod)
+                listener: beginOptionalFormalParameters({)
+                parseFormalParameter({, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+                  parseMetadataStar({)
+                    listener: beginMetadataStar(required)
+                    listener: endMetadataStar(0)
+                  listener: beginFormalParameter(required, MemberKind.TopLevelMethod, null, null, null)
+                  listener: handleIdentifier(required, typeReference)
+                  listener: handleNoTypeArguments(x2)
+                  listener: handleType(required, null)
+                  ensureIdentifier(required, formalParameterDeclaration)
+                    listener: handleIdentifier(x2, formalParameterDeclaration)
+                  listener: handleFormalParameterWithoutValue(})
+                  listener: endFormalParameter(null, null, x2, null, null, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+                listener: endOptionalFormalParameters(1, {, })
+              ensureCloseParen(}, ()
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, print)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(print)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            looksLikeFunctionBody(;)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(print, expression)
+                              listener: handleNoTypeArguments(()
+                              parseArgumentsOpt(print)
+                                parseArguments(print)
+                                  parseArgumentsRest(()
+                                    listener: beginArguments(()
+                                    parseExpression(()
+                                      parsePrecedenceExpression((, 1, true)
+                                        parseUnaryExpression((, true)
+                                          parsePrimary((, expression)
+                                            parseSendOrFunctionLiteral((, expression)
+                                              parseSend((, expression)
+                                                ensureIdentifier((, expression)
+                                                  listener: handleIdentifier(x, expression)
+                                                listener: handleNoTypeArguments())
+                                                parseArgumentsOpt(x)
+                                                  listener: handleNoArguments())
+                                                listener: handleSend(x, ))
+                                    listener: endArguments(1, (, ))
+                              listener: handleSend(print, ;)
+                  ensureSemicolon())
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration(void)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(})
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(}, null, }, Instance of 'VoidType', null, foo3, false)
+        listener: beginTopLevelMethod(}, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(foo3, topLevelFunctionDeclaration)
+        parseMethodTypeVar(foo3)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(foo3, foo3, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(foo3, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              parseOptionalNamedParameters((, MemberKind.TopLevelMethod)
+                listener: beginOptionalFormalParameters({)
+                parseFormalParameter({, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+                  parseMetadataStar({)
+                    listener: beginMetadataStar(required)
+                    listener: endMetadataStar(0)
+                  reportRecoverableErrorWithToken(required, Instance of 'Template<(Token) => Message>')
+                    listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'required' is only available in null safe libraries., null, {lexeme: required}], required, required)
+                  listener: beginFormalParameter(required, MemberKind.TopLevelMethod, required, null, null)
+                  listener: handleIdentifier(required, typeReference)
+                  listener: handleNoTypeArguments(x3)
+                  listener: handleType(required, null)
+                  ensureIdentifier(required, formalParameterDeclaration)
+                    listener: handleIdentifier(x3, formalParameterDeclaration)
+                  listener: handleFormalParameterWithoutValue(})
+                  listener: endFormalParameter(null, null, x3, null, null, FormalParameterKind.optionalNamed, MemberKind.TopLevelMethod)
+                listener: endOptionalFormalParameters(1, {, })
+              ensureCloseParen(}, ()
+              listener: endFormalParameters(1, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, print)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(print)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            looksLikeFunctionBody(;)
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(print, expression)
+                              listener: handleNoTypeArguments(()
+                              parseArgumentsOpt(print)
+                                parseArguments(print)
+                                  parseArgumentsRest(()
+                                    listener: beginArguments(()
+                                    parseExpression(()
+                                      parsePrecedenceExpression((, 1, true)
+                                        parseUnaryExpression((, true)
+                                          parsePrimary((, expression)
+                                            parseSendOrFunctionLiteral((, expression)
+                                              parseSend((, expression)
+                                                ensureIdentifier((, expression)
+                                                  listener: handleIdentifier(x, expression)
+                                                listener: handleNoTypeArguments())
+                                                parseArgumentsOpt(x)
+                                                  listener: handleNoArguments())
+                                                listener: handleSend(x, ))
+                                    listener: endArguments(1, (, ))
+                              listener: handleSend(print, ;)
+                  ensureSemicolon())
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration(class)
+  parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+    parseMetadataStar(})
+      listener: beginMetadataStar(class)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(}, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(}, class)
+      parseClassOrNamedMixinApplication(null, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(class)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(Foo, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(class, null, Foo)
+        parseClass(Foo, class, class, Foo)
+          parseClassHeaderOpt(Foo, class, class)
+            parseClassExtendsOpt(Foo)
+              listener: handleNoType(Foo)
+              listener: handleClassExtends(null, 1)
+            parseWithClauseOpt(Foo)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(Foo)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(Foo, DeclarationKind.Class, Foo)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, void)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, Foo)
+              parseMetadataStar({)
+                listener: beginMetadataStar(void)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod({, null, null, null, null, null, null, {, Instance of 'VoidType', null, foo4, DeclarationKind.Class, Foo, false)
+                listener: beginMethod(null, null, null, null, null, foo4)
+                listener: handleVoidKeyword(void)
+                ensureIdentifierPotentiallyRecovered(void, methodDeclaration, false)
+                  listener: handleIdentifier(foo4, methodDeclaration)
+                parseQualifiedRestOpt(foo4, methodDeclarationContinuation)
+                parseMethodTypeVar(foo4)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(foo4, foo4, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(foo4, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseOptionalNamedParameters((, MemberKind.NonStaticMethod)
+                        listener: beginOptionalFormalParameters({)
+                        parseFormalParameter({, FormalParameterKind.optionalNamed, MemberKind.NonStaticMethod)
+                          parseMetadataStar({)
+                            listener: beginMetadataStar(required)
+                            listener: endMetadataStar(0)
+                          reportRecoverableErrorWithToken(required, Instance of 'Template<(Token) => Message>')
+                            listener: handleRecoverableError(Message[UnexpectedModifierInNonNnbd, The modifier 'required' is only available in null safe libraries., null, {lexeme: required}], required, required)
+                          listener: beginFormalParameter(covariant, MemberKind.NonStaticMethod, required, covariant, null)
+                          listener: handleIdentifier(int, typeReference)
+                          listener: handleNoTypeArguments(x4)
+                          listener: handleType(int, null)
+                          ensureIdentifier(int, formalParameterDeclaration)
+                            listener: handleIdentifier(x4, formalParameterDeclaration)
+                          listener: handleFormalParameterWithoutValue(})
+                          listener: endFormalParameter(null, null, x4, null, null, FormalParameterKind.optionalNamed, MemberKind.NonStaticMethod)
+                        listener: endOptionalFormalParameters(1, {, })
+                      ensureCloseParen(}, ()
+                      listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, print)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(print)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(print, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(print)
+                                        parseArguments(print)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseSendOrFunctionLiteral((, expression)
+                                                      parseSend((, expression)
+                                                        ensureIdentifier((, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments())
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments())
+                                                        listener: handleSend(x, ))
+                                            listener: endArguments(1, (, ))
+                                      listener: handleSend(print, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, void, (, null, })
+              listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(4, )
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.parser.expect b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.parser.expect
new file mode 100644
index 0000000..468262a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.parser.expect
@@ -0,0 +1,35 @@
+void foo1({required int x1}) {
+print(x);
+}
+
+void foo2({required x2}) {
+print(x);
+}
+
+void foo3({required required x3}) {
+print(x);
+}
+
+class Foo {
+void foo4({required covariant int x4}) {
+print(x);
+}
+}
+
+void[KeywordToken] foo1[StringToken]([BeginToken]{[BeginToken]required[StringToken] int[StringToken] x1[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]x[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+void[KeywordToken] foo2[StringToken]([BeginToken]{[BeginToken]required[StringToken] x2[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]x[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+void[KeywordToken] foo3[StringToken]([BeginToken]{[BeginToken]required[StringToken] required[StringToken] x3[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]x[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Foo[StringToken] {[BeginToken]
+void[KeywordToken] foo4[StringToken]([BeginToken]{[BeginToken]required[StringToken] covariant[KeywordToken] int[StringToken] x4[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]x[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.scanner.expect b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.scanner.expect
new file mode 100644
index 0000000..468262a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/non-nnbd/use_required_in_non_nnbd.dart.scanner.expect
@@ -0,0 +1,35 @@
+void foo1({required int x1}) {
+print(x);
+}
+
+void foo2({required x2}) {
+print(x);
+}
+
+void foo3({required required x3}) {
+print(x);
+}
+
+class Foo {
+void foo4({required covariant int x4}) {
+print(x);
+}
+}
+
+void[KeywordToken] foo1[StringToken]([BeginToken]{[BeginToken]required[StringToken] int[StringToken] x1[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]x[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+void[KeywordToken] foo2[StringToken]([BeginToken]{[BeginToken]required[StringToken] x2[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]x[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+void[KeywordToken] foo3[StringToken]([BeginToken]{[BeginToken]required[StringToken] required[StringToken] x3[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]x[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Foo[StringToken] {[BeginToken]
+void[KeywordToken] foo4[StringToken]([BeginToken]{[BeginToken]required[StringToken] covariant[KeywordToken] int[StringToken] x4[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]x[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 20a36d8..6893010 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -6,7 +6,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.6.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   _fe_analyzer_shared:
diff --git a/pkg/front_end/test/analyser_ignored/load_dill_twice_lib_1.dart b/pkg/front_end/test/analyser_ignored/load_dill_twice_lib_1.dart
index ca76918..443c3b5 100644
--- a/pkg/front_end/test/analyser_ignored/load_dill_twice_lib_1.dart
+++ b/pkg/front_end/test/analyser_ignored/load_dill_twice_lib_1.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.9
+
 export 'load_dill_twice_lib_2.dart';
 
 // Use annotation to force proper printing.
diff --git a/pkg/front_end/test/analyser_ignored/load_dill_twice_lib_2.dart b/pkg/front_end/test/analyser_ignored/load_dill_twice_lib_2.dart
index 5e9d38a..0ba97dd 100644
--- a/pkg/front_end/test/analyser_ignored/load_dill_twice_lib_2.dart
+++ b/pkg/front_end/test/analyser_ignored/load_dill_twice_lib_2.dart
@@ -2,4 +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
+
 int foo() => 42;
diff --git a/pkg/front_end/test/analyser_ignored/load_dill_twice_test.dart b/pkg/front_end/test/analyser_ignored/load_dill_twice_test.dart
index ba07019..922ff5d 100644
--- a/pkg/front_end/test/analyser_ignored/load_dill_twice_test.dart
+++ b/pkg/front_end/test/analyser_ignored/load_dill_twice_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Platform, exit;
 
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
diff --git a/pkg/front_end/test/ast_nodes_has_to_string_test.dart b/pkg/front_end/test/ast_nodes_has_to_string_test.dart
index 9b0dc9f..028bedf 100644
--- a/pkg/front_end/test/ast_nodes_has_to_string_test.dart
+++ b/pkg/front_end/test/ast_nodes_has_to_string_test.dart
@@ -1,3 +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.md file.
+
+// @dart = 2.9
+
 import 'dart:io' show File, Platform, stdin, exitCode;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart';
diff --git a/pkg/front_end/test/binary_md_dill_reader.dart b/pkg/front_end/test/binary_md_dill_reader.dart
index 271ffd8..d25607e 100644
--- a/pkg/front_end/test/binary_md_dill_reader.dart
+++ b/pkg/front_end/test/binary_md_dill_reader.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.9
+
 import "dart:math" as math;
 
 class BinaryMdDillReader {
diff --git a/pkg/front_end/test/binary_md_vm_tags_and_version_test.dart b/pkg/front_end/test/binary_md_vm_tags_and_version_test.dart
index d9f412e..fdf5330 100644
--- a/pkg/front_end/test/binary_md_vm_tags_and_version_test.dart
+++ b/pkg/front_end/test/binary_md_vm_tags_and_version_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.
 
+// @dart = 2.9
+
 import 'dart:io' show File, Platform;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
diff --git a/pkg/front_end/test/class_hierarchy/class_hierarchy_test.dart b/pkg/front_end/test/class_hierarchy/class_hierarchy_test.dart
new file mode 100644
index 0000000..5fb09fd
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/class_hierarchy_test.dart
@@ -0,0 +1,309 @@
+// 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' show Directory, Platform;
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
+import 'package:_fe_analyzer_shared/src/testing/id.dart';
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/fasta/kernel/kernel_api.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:front_end/src/testing/id_testing_utils.dart';
+import 'package:front_end/src/fasta/kernel/class_hierarchy_builder.dart';
+import 'package:front_end/src/testing/id_extractor.dart';
+import 'package:kernel/ast.dart';
+
+main(List<String> args) async {
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
+  await runTests<Features>(dataDir,
+      args: args,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(
+          const ClassHierarchyDataComputer(), [cfeNonNullableConfig]));
+}
+
+class ClassHierarchyDataComputer extends DataComputer<Features> {
+  const ClassHierarchyDataComputer();
+
+  /// Function that computes a data mapping for [library].
+  ///
+  /// Fills [actualMap] with the data.
+  void computeLibraryData(
+      TestConfig config,
+      InternalCompilerResult compilerResult,
+      Library library,
+      Map<Id, ActualData<Features>> actualMap,
+      {bool verbose}) {
+    new InheritanceDataExtractor(compilerResult, actualMap)
+        .computeForLibrary(library);
+  }
+
+  @override
+  void computeClassData(
+      TestConfig config,
+      InternalCompilerResult compilerResult,
+      Class cls,
+      Map<Id, ActualData<Features>> actualMap,
+      {bool verbose}) {
+    new InheritanceDataExtractor(compilerResult, actualMap)
+        .computeForClass(cls);
+  }
+
+  @override
+  bool get supportsErrors => true;
+
+  @override
+  Features computeErrorData(TestConfig config, InternalCompilerResult compiler,
+      Id id, List<FormattedMessage> errors) {
+    return null; //errorsToText(errors, useCodes: true);
+  }
+
+  @override
+  DataInterpreter<Features> get dataValidator =>
+      const FeaturesDataInterpreter();
+}
+
+class Tag {
+  static const String superclasses = 'superclasses';
+  static const String interfaces = 'interfaces';
+  static const String hasNoSuchMethod = 'hasNoSuchMethod';
+  static const String abstractMembers = 'abstractMembers';
+  static const String classBuilder = 'classBuilder';
+  static const String isSourceDeclaration = 'isSourceDeclaration';
+  static const String isSynthesized = 'isSynthesized';
+  static const String member = 'member';
+  static const String maxInheritancePath = 'maxInheritancePath';
+  static const String declaredOverrides = 'declared-overrides';
+  static const String mixinApplicationOverrides = 'mixin-overrides';
+  static const String inheritedImplements = 'inherited-implements';
+  static const String abstractForwardingStub = 'abstractForwardingStub';
+  static const String concreteForwardingStub = 'concreteForwardingStub';
+  static const String memberSignature = 'memberSignature';
+  static const String abstractMixinStub = 'abstractMixinStub';
+  static const String concreteMixinStub = 'concreteMixinStub';
+  static const String declarations = 'declarations';
+  static const String stubTarget = 'stubTarget';
+  static const String type = 'type';
+  static const String covariance = 'covariance';
+}
+
+class InheritanceDataExtractor extends CfeDataExtractor<Features> {
+  final InternalCompilerResult _compilerResult;
+
+  InheritanceDataExtractor(
+      this._compilerResult, Map<Id, ActualData<Features>> actualMap)
+      : super(_compilerResult, actualMap);
+
+  CoreTypes get _coreTypes => _compilerResult.coreTypes;
+
+  ClassHierarchyBuilder get _classHierarchyBuilder =>
+      _compilerResult.kernelTargetForTesting.loader.builderHierarchy;
+
+  @override
+  void computeForClass(Class node) {
+    super.computeForClass(node);
+    ClassHierarchyNode classHierarchyNode =
+        _classHierarchyBuilder.getNodeFromClass(node);
+    ClassHierarchyNodeDataForTesting data = classHierarchyNode.dataForTesting;
+    void addMember(ClassMember classMember,
+        {bool isSetter, bool isClassMember}) {
+      Member member = classMember.getMember(_classHierarchyBuilder);
+      Member memberOrigin = member.memberSignatureOrigin ?? member;
+      if (memberOrigin.enclosingClass == _coreTypes.objectClass) {
+        return;
+      }
+      Features features = new Features();
+
+      String memberName = classMemberName(classMember);
+      memberName += isClassMember ? '#cls' : '#int';
+      MemberId id = new MemberId.internal(memberName, className: node.name);
+
+      TreeNode nodeWithOffset;
+      if (member.enclosingClass == node) {
+        nodeWithOffset = computeTreeNodeWithOffset(member);
+      } else {
+        nodeWithOffset = computeTreeNodeWithOffset(node);
+      }
+      if (classMember.isSourceDeclaration) {
+        features.add(Tag.isSourceDeclaration);
+      }
+      if (classMember.isSynthesized) {
+        features.add(Tag.isSynthesized);
+        if (member.enclosingClass != node) {
+          features[Tag.member] = memberQualifiedName(member);
+        }
+        if (classMember.hasDeclarations) {
+          for (ClassMember declaration in classMember.declarations) {
+            features.addElement(
+                Tag.declarations, classMemberQualifiedName(declaration));
+          }
+        }
+      }
+      features[Tag.classBuilder] = classMember.classBuilder.name;
+
+      Set<ClassMember> declaredOverrides =
+          data.declaredOverrides[data.aliasMap[classMember] ?? classMember];
+      if (declaredOverrides != null) {
+        for (ClassMember override in declaredOverrides) {
+          features.addElement(
+              Tag.declaredOverrides, classMemberQualifiedName(override));
+        }
+      }
+
+      Set<ClassMember> mixinApplicationOverrides = data
+          .mixinApplicationOverrides[data.aliasMap[classMember] ?? classMember];
+      if (mixinApplicationOverrides != null) {
+        for (ClassMember override in mixinApplicationOverrides) {
+          features.addElement(Tag.mixinApplicationOverrides,
+              classMemberQualifiedName(override));
+        }
+      }
+
+      Set<ClassMember> inheritedImplements =
+          data.inheritedImplements[data.aliasMap[classMember] ?? classMember];
+      if (inheritedImplements != null) {
+        for (ClassMember implement in inheritedImplements) {
+          features.addElement(
+              Tag.inheritedImplements, classMemberQualifiedName(implement));
+        }
+      }
+
+      if (member.enclosingClass == node && member is Procedure) {
+        switch (member.stubKind) {
+          case ProcedureStubKind.Regular:
+            // TODO: Handle this case.
+            break;
+          case ProcedureStubKind.AbstractForwardingStub:
+            features.add(Tag.abstractForwardingStub);
+            features[Tag.type] = procedureType(member);
+            features[Tag.covariance] =
+                classMember.getCovariance(_classHierarchyBuilder).toString();
+            break;
+          case ProcedureStubKind.ConcreteForwardingStub:
+            features.add(Tag.concreteForwardingStub);
+            features[Tag.type] = procedureType(member);
+            features[Tag.covariance] =
+                classMember.getCovariance(_classHierarchyBuilder).toString();
+            features[Tag.stubTarget] = memberQualifiedName(member.stubTarget);
+            break;
+          case ProcedureStubKind.NoSuchMethodForwarder:
+            // TODO: Handle this case.
+            break;
+          case ProcedureStubKind.MemberSignature:
+            features.add(Tag.memberSignature);
+            features[Tag.type] = procedureType(member);
+            features[Tag.covariance] =
+                classMember.getCovariance(_classHierarchyBuilder).toString();
+            break;
+          case ProcedureStubKind.AbstractMixinStub:
+            features.add(Tag.abstractMixinStub);
+            break;
+          case ProcedureStubKind.ConcreteMixinStub:
+            features.add(Tag.concreteMixinStub);
+            features[Tag.stubTarget] = memberQualifiedName(member.stubTarget);
+            break;
+        }
+      }
+
+      registerValue(nodeWithOffset?.location?.file, nodeWithOffset?.fileOffset,
+          id, features, member);
+    }
+
+    classHierarchyNode.classMemberMap
+        ?.forEach((Name name, ClassMember classMember) {
+      addMember(classMember, isSetter: false, isClassMember: true);
+    });
+    classHierarchyNode.classSetterMap
+        ?.forEach((Name name, ClassMember classMember) {
+      addMember(classMember, isSetter: true, isClassMember: true);
+    });
+    classHierarchyNode.interfaceMemberMap
+        ?.forEach((Name name, ClassMember classMember) {
+      if (!identical(classMember, classHierarchyNode.classMemberMap[name])) {
+        addMember(classMember, isSetter: false, isClassMember: false);
+      }
+    });
+    classHierarchyNode.interfaceSetterMap
+        ?.forEach((Name name, ClassMember classMember) {
+      if (!identical(classMember, classHierarchyNode.classSetterMap[name])) {
+        addMember(classMember, isSetter: true, isClassMember: false);
+      }
+    });
+  }
+
+  @override
+  Features computeClassValue(Id id, Class node) {
+    Features features = new Features();
+    ClassHierarchyNode classHierarchyNode =
+        _classHierarchyBuilder.getNodeFromClass(node);
+    ClassHierarchyNodeDataForTesting data = classHierarchyNode.dataForTesting;
+    classHierarchyNode.superclasses.forEach((Supertype supertype) {
+      features.addElement(Tag.superclasses, supertypeToText(supertype));
+    });
+    classHierarchyNode.interfaces.forEach((Supertype supertype) {
+      features.addElement(Tag.interfaces, supertypeToText(supertype));
+    });
+    if (data.abstractMembers != null) {
+      for (ClassMember abstractMember in data.abstractMembers) {
+        features.addElement(
+            Tag.abstractMembers, classMemberQualifiedName(abstractMember));
+      }
+    }
+    features[Tag.maxInheritancePath] =
+        '${classHierarchyNode.maxInheritancePath}';
+    if (classHierarchyNode.hasNoSuchMethod) {
+      features.add(Tag.hasNoSuchMethod);
+    }
+    return features;
+  }
+}
+
+String classMemberName(ClassMember classMember) {
+  String name = classMember.name.text;
+  if (classMember.forSetter) {
+    name += '=';
+  }
+  return name;
+}
+
+String classMemberQualifiedName(ClassMember classMember) {
+  return '${classMember.classBuilder.name}.${classMemberName(classMember)}';
+}
+
+String memberName(Member member) {
+  String name = member.name.text;
+  if (member is Procedure && member.isSetter) {
+    name += '=';
+  }
+  return name;
+}
+
+String memberQualifiedName(Member member) {
+  return '${member.enclosingClass.name}.${memberName(member)}';
+}
+
+String procedureType(Procedure procedure) {
+  if (procedure.kind == ProcedureKind.Getter) {
+    return typeToText(procedure.function.returnType,
+        TypeRepresentation.analyzerNonNullableByDefault);
+  } else if (procedure.kind == ProcedureKind.Setter) {
+    return typeToText(procedure.function.positionalParameters.single.type,
+        TypeRepresentation.analyzerNonNullableByDefault);
+  } else {
+    Nullability functionTypeNullability;
+    if (procedure.enclosingLibrary.isNonNullableByDefault) {
+      functionTypeNullability = procedure.enclosingLibrary.nonNullable;
+    } else {
+      // We don't create a member signature when the member is just
+      // a substitution. We should still take the nullability to be
+      // legacy, though.
+      functionTypeNullability = procedure.enclosingLibrary.nonNullable;
+    }
+    return typeToText(
+        procedure.function.computeThisFunctionType(functionTypeNullability),
+        TypeRepresentation.analyzerNonNullableByDefault);
+  }
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_extends_field.dart b/pkg/front_end/test/class_hierarchy/data/abstract_extends_field.dart
new file mode 100644
index 0000000..fbd6127
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_extends_field.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.
+
+/*class: AbstractSuper:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class AbstractSuper {
+  /*member: AbstractSuper.extendedConcreteField#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  /*member: AbstractSuper.extendedConcreteField=#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int extendedConcreteField = 0;
+
+  /*member: AbstractSuper.extendedAbstractField#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  /*member: AbstractSuper.extendedAbstractField=#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractField;
+
+  /*member: AbstractSuper.declaredConcreteExtendsConcreteField#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  /*member: AbstractSuper.declaredConcreteExtendsConcreteField=#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int declaredConcreteExtendsConcreteField = 0;
+
+  /*member: AbstractSuper.declaredAbstractExtendsConcreteField#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  /*member: AbstractSuper.declaredAbstractExtendsConcreteField=#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int declaredAbstractExtendsConcreteField = 0;
+
+  /*member: AbstractSuper.declaredConcreteExtendsAbstractField#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  /*member: AbstractSuper.declaredConcreteExtendsAbstractField=#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  abstract int declaredConcreteExtendsAbstractField;
+
+  /*member: AbstractSuper.declaredAbstractExtendsAbstractField#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  /*member: AbstractSuper.declaredAbstractExtendsAbstractField=#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+/*class: AbstractClass:
+ maxInheritancePath=2,
+ superclasses=[
+  AbstractSuper,
+  Object]
+*/
+abstract class AbstractClass extends AbstractSuper {
+  /*member: AbstractClass.extendedConcreteField#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.extendedConcreteField=#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractField#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.extendedAbstractField=#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteField#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredConcreteField=#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  int declaredConcreteField = 0;
+
+  /*member: AbstractClass.declaredAbstractField#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredAbstractField=#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  abstract int declaredAbstractField;
+
+  /*member: AbstractClass.declaredConcreteExtendsConcreteField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    AbstractSuper.declaredConcreteExtendsConcreteField,
+    AbstractSuper.declaredConcreteExtendsConcreteField=],
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredConcreteExtendsConcreteField=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    AbstractSuper.declaredConcreteExtendsConcreteField,
+    AbstractSuper.declaredConcreteExtendsConcreteField=],
+   isSourceDeclaration
+  */
+  int declaredConcreteExtendsConcreteField = 0;
+
+  /*member: AbstractClass.declaredAbstractExtendsConcreteField#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=AbstractSuper.declaredAbstractExtendsConcreteField
+  */
+  /*member: AbstractClass.declaredAbstractExtendsConcreteField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsConcreteField,
+    AbstractSuper.declaredAbstractExtendsConcreteField],
+   declared-overrides=[
+    AbstractSuper.declaredAbstractExtendsConcreteField,
+    AbstractSuper.declaredAbstractExtendsConcreteField=],
+   isSynthesized
+  */
+  /*member: AbstractClass.declaredAbstractExtendsConcreteField=#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=AbstractSuper.declaredAbstractExtendsConcreteField
+  */
+  /*member: AbstractClass.declaredAbstractExtendsConcreteField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsConcreteField=,
+    AbstractSuper.declaredAbstractExtendsConcreteField=],
+   declared-overrides=[
+    AbstractSuper.declaredAbstractExtendsConcreteField,
+    AbstractSuper.declaredAbstractExtendsConcreteField=],
+   isSynthesized
+  */
+  abstract int declaredAbstractExtendsConcreteField;
+
+  /*member: AbstractClass.declaredConcreteExtendsAbstractField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    AbstractSuper.declaredConcreteExtendsAbstractField,
+    AbstractSuper.declaredConcreteExtendsAbstractField=],
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredConcreteExtendsAbstractField=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    AbstractSuper.declaredConcreteExtendsAbstractField,
+    AbstractSuper.declaredConcreteExtendsAbstractField=],
+   isSourceDeclaration
+  */
+  int declaredConcreteExtendsAbstractField = 0;
+
+  /*member: AbstractClass.declaredAbstractExtendsAbstractField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    AbstractSuper.declaredAbstractExtendsAbstractField,
+    AbstractSuper.declaredAbstractExtendsAbstractField=],
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredAbstractExtendsAbstractField=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    AbstractSuper.declaredAbstractExtendsAbstractField,
+    AbstractSuper.declaredAbstractExtendsAbstractField=],
+   isSourceDeclaration
+  */
+  int declaredAbstractExtendsAbstractField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_extends_final_field.dart b/pkg/front_end/test/class_hierarchy/data/abstract_extends_final_field.dart
new file mode 100644
index 0000000..b5ed4db
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_extends_final_field.dart
@@ -0,0 +1,116 @@
+// 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: AbstractSuper:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class AbstractSuper {
+  /*member: AbstractSuper.extendedConcreteField#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  final int extendedConcreteField = 0;
+
+  /*member: AbstractSuper.extendedAbstractField#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractField;
+
+  /*member: AbstractSuper.declaredConcreteExtendsConcreteField#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  final int declaredConcreteExtendsConcreteField = 0;
+
+  /*member: AbstractSuper.declaredAbstractExtendsConcreteField#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  final int declaredAbstractExtendsConcreteField = 0;
+
+  /*member: AbstractSuper.declaredConcreteExtendsAbstractField#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  abstract final int declaredConcreteExtendsAbstractField;
+
+  /*member: AbstractSuper.declaredAbstractExtendsAbstractField#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+/*class: AbstractClass:
+ maxInheritancePath=2,
+ superclasses=[
+  AbstractSuper,
+  Object]
+*/
+abstract class AbstractClass extends AbstractSuper {
+  /*member: AbstractClass.extendedConcreteField#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractField#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteField#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  final int declaredConcreteField = 0;
+
+  /*member: AbstractClass.declaredAbstractField#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  abstract final int declaredAbstractField;
+
+  /*member: AbstractClass.declaredConcreteExtendsConcreteField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[AbstractSuper.declaredConcreteExtendsConcreteField],
+   isSourceDeclaration
+  */
+  final int declaredConcreteExtendsConcreteField = 0;
+
+  /*member: AbstractClass.declaredAbstractExtendsConcreteField#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=AbstractSuper.declaredAbstractExtendsConcreteField
+  */
+  /*member: AbstractClass.declaredAbstractExtendsConcreteField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsConcreteField,
+    AbstractSuper.declaredAbstractExtendsConcreteField],
+   declared-overrides=[AbstractSuper.declaredAbstractExtendsConcreteField],
+   isSynthesized
+  */
+  abstract final int declaredAbstractExtendsConcreteField;
+
+  /*member: AbstractClass.declaredConcreteExtendsAbstractField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[AbstractSuper.declaredConcreteExtendsAbstractField],
+   isSourceDeclaration
+  */
+  final int declaredConcreteExtendsAbstractField = 0;
+
+  /*member: AbstractClass.declaredAbstractExtendsAbstractField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsAbstractField,
+    AbstractSuper.declaredAbstractExtendsAbstractField],
+   declared-overrides=[AbstractSuper.declaredAbstractExtendsAbstractField],
+   isSynthesized
+  */
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_extends_getter.dart b/pkg/front_end/test/class_hierarchy/data/abstract_extends_getter.dart
new file mode 100644
index 0000000..6900a41
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_extends_getter.dart
@@ -0,0 +1,116 @@
+// 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: AbstractSuper:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class AbstractSuper {
+  /*member: AbstractSuper.extendedConcreteGetter#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int get extendedConcreteGetter => 0;
+
+  /*member: AbstractSuper.extendedAbstractGetter#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int get extendedAbstractGetter;
+
+  /*member: AbstractSuper.declaredConcreteExtendsConcreteGetter#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int get declaredConcreteExtendsConcreteGetter => 0;
+
+  /*member: AbstractSuper.declaredAbstractExtendsConcreteGetter#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int get declaredAbstractExtendsConcreteGetter => 0;
+
+  /*member: AbstractSuper.declaredConcreteExtendsAbstractGetter#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int get declaredConcreteExtendsAbstractGetter;
+
+  /*member: AbstractSuper.declaredAbstractExtendsAbstractGetter#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+/*class: AbstractClass:
+ maxInheritancePath=2,
+ superclasses=[
+  AbstractSuper,
+  Object]
+*/
+abstract class AbstractClass extends AbstractSuper {
+  /*member: AbstractClass.extendedConcreteGetter#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractGetter#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteGetter#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  int get declaredConcreteGetter => 0;
+
+  /*member: AbstractClass.declaredAbstractGetter#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  int get declaredAbstractGetter;
+
+  /*member: AbstractClass.declaredConcreteExtendsConcreteGetter#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[AbstractSuper.declaredConcreteExtendsConcreteGetter],
+   isSourceDeclaration
+  */
+  int get declaredConcreteExtendsConcreteGetter => 0;
+
+  /*member: AbstractClass.declaredAbstractExtendsConcreteGetter#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=AbstractSuper.declaredAbstractExtendsConcreteGetter
+  */
+  /*member: AbstractClass.declaredAbstractExtendsConcreteGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsConcreteGetter,
+    AbstractSuper.declaredAbstractExtendsConcreteGetter],
+   declared-overrides=[AbstractSuper.declaredAbstractExtendsConcreteGetter],
+   isSynthesized
+  */
+  int get declaredAbstractExtendsConcreteGetter;
+
+  /*member: AbstractClass.declaredConcreteExtendsAbstractGetter#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[AbstractSuper.declaredConcreteExtendsAbstractGetter],
+   isSourceDeclaration
+  */
+  int get declaredConcreteExtendsAbstractGetter => 0;
+
+  /*member: AbstractClass.declaredAbstractExtendsAbstractGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsAbstractGetter,
+    AbstractSuper.declaredAbstractExtendsAbstractGetter],
+   declared-overrides=[AbstractSuper.declaredAbstractExtendsAbstractGetter],
+   isSynthesized
+  */
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_extends_method.dart b/pkg/front_end/test/class_hierarchy/data/abstract_extends_method.dart
new file mode 100644
index 0000000..7bbce15
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_extends_method.dart
@@ -0,0 +1,114 @@
+// 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: AbstractSuper:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class AbstractSuper {
+  /*member: AbstractSuper.extendedConcreteMethod#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void extendedConcreteMethod() {}
+
+  /*member: AbstractSuper.extendedAbstractMethod#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void extendedAbstractMethod();
+
+  /*member: AbstractSuper.declaredConcreteExtendsConcreteMethod#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void declaredConcreteExtendsConcreteMethod() {}
+
+  /*member: AbstractSuper.declaredAbstractExtendsConcreteMethod#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void declaredAbstractExtendsConcreteMethod() {}
+
+  /*member: AbstractSuper.declaredConcreteExtendsAbstractMethod#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void declaredConcreteExtendsAbstractMethod();
+
+  /*member: AbstractSuper.declaredAbstractExtendsAbstractMethod#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+/*class: AbstractClass:
+ maxInheritancePath=2,
+ superclasses=[
+  AbstractSuper,
+  Object]
+*/
+/*member: AbstractClass.declaredAbstractExtendsConcreteMethod#cls:
+ classBuilder=AbstractClass,
+ isSynthesized,
+ member=AbstractSuper.declaredAbstractExtendsConcreteMethod
+*/
+abstract class AbstractClass extends AbstractSuper {
+  /*member: AbstractClass.extendedConcreteMethod#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractMethod#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteMethod#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  void declaredConcreteMethod() {}
+
+  /*member: AbstractClass.declaredAbstractMethod#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  void declaredAbstractMethod();
+
+  /*member: AbstractClass.declaredConcreteExtendsConcreteMethod#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[AbstractSuper.declaredConcreteExtendsConcreteMethod],
+   isSourceDeclaration
+  */
+  void declaredConcreteExtendsConcreteMethod() {}
+
+  /*member: AbstractClass.declaredAbstractExtendsConcreteMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsConcreteMethod,
+    AbstractSuper.declaredAbstractExtendsConcreteMethod],
+   declared-overrides=[AbstractSuper.declaredAbstractExtendsConcreteMethod],
+   isSynthesized
+  */
+  void declaredAbstractExtendsConcreteMethod();
+
+  /*member: AbstractClass.declaredConcreteExtendsAbstractMethod#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[AbstractSuper.declaredConcreteExtendsAbstractMethod],
+   isSourceDeclaration
+  */
+  void declaredConcreteExtendsAbstractMethod() {}
+
+  /*member: AbstractClass.declaredAbstractExtendsAbstractMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsAbstractMethod,
+    AbstractSuper.declaredAbstractExtendsAbstractMethod],
+   declared-overrides=[AbstractSuper.declaredAbstractExtendsAbstractMethod],
+   isSynthesized
+  */
+  void declaredAbstractExtendsAbstractMethod();
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_extends_setter.dart b/pkg/front_end/test/class_hierarchy/data/abstract_extends_setter.dart
new file mode 100644
index 0000000..dbbd9a1
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_extends_setter.dart
@@ -0,0 +1,116 @@
+// 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: AbstractSuper:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class AbstractSuper {
+  /*member: AbstractSuper.extendedConcreteSetter=#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void set extendedConcreteSetter(int value) {}
+
+  /*member: AbstractSuper.extendedAbstractSetter=#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void set extendedAbstractSetter(int value);
+
+  /*member: AbstractSuper.declaredConcreteExtendsConcreteSetter=#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+
+  /*member: AbstractSuper.declaredAbstractExtendsConcreteSetter=#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void set declaredAbstractExtendsConcreteSetter(int value) {}
+
+  /*member: AbstractSuper.declaredConcreteExtendsAbstractSetter=#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void set declaredConcreteExtendsAbstractSetter(int value);
+
+  /*member: AbstractSuper.declaredAbstractExtendsAbstractSetter=#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+/*class: AbstractClass:
+ maxInheritancePath=2,
+ superclasses=[
+  AbstractSuper,
+  Object]
+*/
+abstract class AbstractClass extends AbstractSuper {
+  /*member: AbstractClass.extendedConcreteSetter=#cls:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractSetter=#int:
+   classBuilder=AbstractSuper,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteSetter=#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  void set declaredConcreteSetter(int value) {}
+
+  /*member: AbstractClass.declaredAbstractSetter=#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  void set declaredAbstractSetter(int value);
+
+  /*member: AbstractClass.declaredConcreteExtendsConcreteSetter=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[AbstractSuper.declaredConcreteExtendsConcreteSetter=],
+   isSourceDeclaration
+  */
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+
+  /*member: AbstractClass.declaredAbstractExtendsConcreteSetter=#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=AbstractSuper.declaredAbstractExtendsConcreteSetter=
+  */
+  /*member: AbstractClass.declaredAbstractExtendsConcreteSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsConcreteSetter=,
+    AbstractSuper.declaredAbstractExtendsConcreteSetter=],
+   declared-overrides=[AbstractSuper.declaredAbstractExtendsConcreteSetter=],
+   isSynthesized
+  */
+  void set declaredAbstractExtendsConcreteSetter(int value);
+
+  /*member: AbstractClass.declaredConcreteExtendsAbstractSetter=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[AbstractSuper.declaredConcreteExtendsAbstractSetter=],
+   isSourceDeclaration
+  */
+  void set declaredConcreteExtendsAbstractSetter(int value) {}
+
+  /*member: AbstractClass.declaredAbstractExtendsAbstractSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractExtendsAbstractSetter=,
+    AbstractSuper.declaredAbstractExtendsAbstractSetter=],
+   declared-overrides=[AbstractSuper.declaredAbstractExtendsAbstractSetter=],
+   isSynthesized
+  */
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_implements_field.dart b/pkg/front_end/test/class_hierarchy/data/abstract_implements_field.dart
new file mode 100644
index 0000000..273a40d
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_implements_field.dart
@@ -0,0 +1,192 @@
+// 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: Interface:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface {
+  /*member: Interface.implementedConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.implementedConcreteField=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int implementedConcreteField = 0;
+
+  /*member: Interface.implementedAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.implementedAbstractField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract int implementedAbstractField;
+
+  /*member: Interface.declaredConcreteImplementsConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.declaredConcreteImplementsConcreteField=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int declaredConcreteImplementsConcreteField = 0;
+
+  /*member: Interface.declaredAbstractImplementsConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.declaredAbstractImplementsConcreteField=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int declaredAbstractImplementsConcreteField = 0;
+
+  /*member: Interface.declaredConcreteImplementsAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.declaredConcreteImplementsAbstractField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract int declaredConcreteImplementsAbstractField;
+
+  /*member: Interface.declaredAbstractImplementsAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.declaredAbstractImplementsAbstractField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+/*class: AbstractClass:
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface {
+  /*member: AbstractClass.implementedConcreteField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.implementedConcreteField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.implementedAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.implementedAbstractField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteField#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredConcreteField=#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  int declaredConcreteField = 0;
+
+  /*member: AbstractClass.declaredAbstractField#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredAbstractField=#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  abstract int declaredAbstractField;
+
+  /*member: AbstractClass.declaredConcreteImplementsConcreteField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface.declaredConcreteImplementsConcreteField,
+    Interface.declaredConcreteImplementsConcreteField=],
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredConcreteImplementsConcreteField=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface.declaredConcreteImplementsConcreteField,
+    Interface.declaredConcreteImplementsConcreteField=],
+   isSourceDeclaration
+  */
+  int declaredConcreteImplementsConcreteField = 0;
+
+  /*member: AbstractClass.declaredAbstractImplementsConcreteField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsConcreteField,
+    Interface.declaredAbstractImplementsConcreteField],
+   declared-overrides=[
+    Interface.declaredAbstractImplementsConcreteField,
+    Interface.declaredAbstractImplementsConcreteField=],
+   isSynthesized
+  */
+  /*member: AbstractClass.declaredAbstractImplementsConcreteField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsConcreteField=,
+    Interface.declaredAbstractImplementsConcreteField=],
+   declared-overrides=[
+    Interface.declaredAbstractImplementsConcreteField,
+    Interface.declaredAbstractImplementsConcreteField=],
+   isSynthesized
+  */
+  abstract int declaredAbstractImplementsConcreteField;
+
+  /*member: AbstractClass.declaredConcreteImplementsAbstractField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface.declaredConcreteImplementsAbstractField,
+    Interface.declaredConcreteImplementsAbstractField=],
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declaredConcreteImplementsAbstractField=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface.declaredConcreteImplementsAbstractField,
+    Interface.declaredConcreteImplementsAbstractField=],
+   isSourceDeclaration
+  */
+  int declaredConcreteImplementsAbstractField = 0;
+
+  /*member: AbstractClass.declaredAbstractImplementsAbstractField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsAbstractField,
+    Interface.declaredAbstractImplementsAbstractField],
+   declared-overrides=[
+    Interface.declaredAbstractImplementsAbstractField,
+    Interface.declaredAbstractImplementsAbstractField=],
+   isSynthesized
+  */
+  /*member: AbstractClass.declaredAbstractImplementsAbstractField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsAbstractField=,
+    Interface.declaredAbstractImplementsAbstractField=],
+   declared-overrides=[
+    Interface.declaredAbstractImplementsAbstractField,
+    Interface.declaredAbstractImplementsAbstractField=],
+   isSynthesized
+  */
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_implements_final_field.dart b/pkg/front_end/test/class_hierarchy/data/abstract_implements_final_field.dart
new file mode 100644
index 0000000..cb20cef
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_implements_final_field.dart
@@ -0,0 +1,110 @@
+// 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: Interface:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface {
+  /*member: Interface.implementedConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  final int implementedConcreteField = 0;
+
+  /*member: Interface.implementedAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract final int implementedAbstractField;
+
+  /*member: Interface.declaredConcreteImplementsConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  final int declaredConcreteImplementsConcreteField = 0;
+
+  /*member: Interface.declaredAbstractImplementsConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  final int declaredAbstractImplementsConcreteField = 0;
+
+  /*member: Interface.declaredConcreteImplementsAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract final int declaredConcreteImplementsAbstractField;
+
+  /*member: Interface.declaredAbstractImplementsAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+/*class: AbstractClass:
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface {
+  /*member: AbstractClass.implementedConcreteField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.implementedAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteField#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  final int declaredConcreteField = 0;
+
+  /*member: AbstractClass.declaredAbstractField#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  abstract final int declaredAbstractField;
+
+  /*member: AbstractClass.declaredConcreteImplementsConcreteField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[Interface.declaredConcreteImplementsConcreteField],
+   isSourceDeclaration
+  */
+  final int declaredConcreteImplementsConcreteField = 0;
+
+  /*member: AbstractClass.declaredAbstractImplementsConcreteField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsConcreteField,
+    Interface.declaredAbstractImplementsConcreteField],
+   declared-overrides=[Interface.declaredAbstractImplementsConcreteField],
+   isSynthesized
+  */
+  abstract final int declaredAbstractImplementsConcreteField;
+
+  /*member: AbstractClass.declaredConcreteImplementsAbstractField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[Interface.declaredConcreteImplementsAbstractField],
+   isSourceDeclaration
+  */
+  final int declaredConcreteImplementsAbstractField = 0;
+
+  /*member: AbstractClass.declaredAbstractImplementsAbstractField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsAbstractField,
+    Interface.declaredAbstractImplementsAbstractField],
+   declared-overrides=[Interface.declaredAbstractImplementsAbstractField],
+   isSynthesized
+  */
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_implements_getter.dart b/pkg/front_end/test/class_hierarchy/data/abstract_implements_getter.dart
new file mode 100644
index 0000000..2c44f41
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_implements_getter.dart
@@ -0,0 +1,110 @@
+// 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: Interface:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface {
+  /*member: Interface.implementedConcreteGetter#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get implementedConcreteGetter => 0;
+
+  /*member: Interface.implementedAbstractGetter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get implementedAbstractGetter;
+
+  /*member: Interface.declaredConcreteImplementsConcreteGetter#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get declaredConcreteImplementsConcreteGetter => 0;
+
+  /*member: Interface.declaredAbstractImplementsConcreteGetter#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get declaredAbstractImplementsConcreteGetter => 0;
+
+  /*member: Interface.declaredConcreteImplementsAbstractGetter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get declaredConcreteImplementsAbstractGetter;
+
+  /*member: Interface.declaredAbstractImplementsAbstractGetter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+/*class: AbstractClass:
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface {
+  /*member: AbstractClass.implementedConcreteGetter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.implementedAbstractGetter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteGetter#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  int get declaredConcreteGetter => 0;
+
+  /*member: AbstractClass.declaredAbstractGetter#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  int get declaredAbstractGetter;
+
+  /*member: AbstractClass.declaredConcreteImplementsConcreteGetter#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[Interface.declaredConcreteImplementsConcreteGetter],
+   isSourceDeclaration
+  */
+  int get declaredConcreteImplementsConcreteGetter => 0;
+
+  /*member: AbstractClass.declaredAbstractImplementsConcreteGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsConcreteGetter,
+    Interface.declaredAbstractImplementsConcreteGetter],
+   declared-overrides=[Interface.declaredAbstractImplementsConcreteGetter],
+   isSynthesized
+  */
+  int get declaredAbstractImplementsConcreteGetter;
+
+  /*member: AbstractClass.declaredConcreteImplementsAbstractGetter#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[Interface.declaredConcreteImplementsAbstractGetter],
+   isSourceDeclaration
+  */
+  int get declaredConcreteImplementsAbstractGetter => 0;
+
+  /*member: AbstractClass.declaredAbstractImplementsAbstractGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsAbstractGetter,
+    Interface.declaredAbstractImplementsAbstractGetter],
+   declared-overrides=[Interface.declaredAbstractImplementsAbstractGetter],
+   isSynthesized
+  */
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_implements_method.dart b/pkg/front_end/test/class_hierarchy/data/abstract_implements_method.dart
new file mode 100644
index 0000000..3b9071e
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_implements_method.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.
+
+/*class: Interface:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface {
+  /*member: Interface.implementedConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void implementedConcreteMethod() {}
+
+  /*member: Interface.implementedAbstractMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void implementedAbstractMethod();
+
+  /*member: Interface.declaredConcreteImplementsConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void declaredConcreteImplementsConcreteMethod() {}
+
+  /*member: Interface.declaredAbstractImplementsConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void declaredAbstractImplementsConcreteMethod() {}
+
+  /*member: Interface.declaredConcreteImplementsAbstractMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void declaredConcreteImplementsAbstractMethod();
+
+  /*member: Interface.declaredAbstractImplementsAbstractMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+/*class: AbstractClass:
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface {
+  /*member: AbstractClass.implementedConcreteMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.implementedAbstractMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteMethod#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  void declaredConcreteMethod() {}
+
+  /*member: AbstractClass.declaredAbstractMethod#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  void declaredAbstractMethod();
+
+  /*member: AbstractClass.declaredConcreteImplementsConcreteMethod#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[Interface.declaredConcreteImplementsConcreteMethod],
+   isSourceDeclaration
+  */
+  void declaredConcreteImplementsConcreteMethod() {}
+
+  /*member: AbstractClass.declaredAbstractImplementsConcreteMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsConcreteMethod,
+    Interface.declaredAbstractImplementsConcreteMethod],
+   declared-overrides=[Interface.declaredAbstractImplementsConcreteMethod],
+   isSynthesized
+  */
+  void declaredAbstractImplementsConcreteMethod();
+
+  /*member: AbstractClass.declaredConcreteImplementsAbstractMethod#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[Interface.declaredConcreteImplementsAbstractMethod],
+   isSourceDeclaration
+  */
+  void declaredConcreteImplementsAbstractMethod() {}
+
+  /*member: AbstractClass.declaredAbstractImplementsAbstractMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsAbstractMethod,
+    Interface.declaredAbstractImplementsAbstractMethod],
+   declared-overrides=[Interface.declaredAbstractImplementsAbstractMethod],
+   isSynthesized
+  */
+  void declaredAbstractImplementsAbstractMethod();
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/abstract_implements_setter.dart b/pkg/front_end/test/class_hierarchy/data/abstract_implements_setter.dart
new file mode 100644
index 0000000..601fb9d
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/abstract_implements_setter.dart
@@ -0,0 +1,110 @@
+// 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: Interface:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface {
+  /*member: Interface.implementedConcreteSetter=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set implementedConcreteSetter(int value) {}
+
+  /*member: Interface.implementedAbstractSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set implementedAbstractSetter(int value);
+
+  /*member: Interface.declaredConcreteImplementsConcreteSetter=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+
+  /*member: Interface.declaredAbstractImplementsConcreteSetter=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set declaredAbstractImplementsConcreteSetter(int value) {}
+
+  /*member: Interface.declaredConcreteImplementsAbstractSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set declaredConcreteImplementsAbstractSetter(int value);
+
+  /*member: Interface.declaredAbstractImplementsAbstractSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+/*class: AbstractClass:
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface {
+  /*member: AbstractClass.implementedConcreteSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.implementedAbstractSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.declaredConcreteSetter=#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  void set declaredConcreteSetter(int value) {}
+
+  /*member: AbstractClass.declaredAbstractSetter=#int:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  void set declaredAbstractSetter(int value);
+
+  /*member: AbstractClass.declaredConcreteImplementsConcreteSetter=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[Interface.declaredConcreteImplementsConcreteSetter=],
+   isSourceDeclaration
+  */
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+
+  /*member: AbstractClass.declaredAbstractImplementsConcreteSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsConcreteSetter=,
+    Interface.declaredAbstractImplementsConcreteSetter=],
+   declared-overrides=[Interface.declaredAbstractImplementsConcreteSetter=],
+   isSynthesized
+  */
+  void set declaredAbstractImplementsConcreteSetter(int value);
+
+  /*member: AbstractClass.declaredConcreteImplementsAbstractSetter=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[Interface.declaredConcreteImplementsAbstractSetter=],
+   isSourceDeclaration
+  */
+  void set declaredConcreteImplementsAbstractSetter(int value) {}
+
+  /*member: AbstractClass.declaredAbstractImplementsAbstractSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declaredAbstractImplementsAbstractSetter=,
+    Interface.declaredAbstractImplementsAbstractSetter=],
+   declared-overrides=[Interface.declaredAbstractImplementsAbstractSetter=],
+   isSynthesized
+  */
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_extends_field.dart b/pkg/front_end/test/class_hierarchy/data/concrete_extends_field.dart
new file mode 100644
index 0000000..549ab8d
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_extends_field.dart
@@ -0,0 +1,219 @@
+// 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: ConcreteSuper:
+ abstractMembers=[
+  ConcreteSuper.declaredAbstractExtendsAbstractField,
+  ConcreteSuper.declaredAbstractExtendsAbstractField=,
+  ConcreteSuper.declaredConcreteExtendsAbstractField,
+  ConcreteSuper.declaredConcreteExtendsAbstractField=,
+  ConcreteSuper.extendedAbstractField,
+  ConcreteSuper.extendedAbstractField=],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class ConcreteSuper {
+  /*member: ConcreteSuper.extendedConcreteField#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSuper.extendedConcreteField=#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int extendedConcreteField = 0;
+
+  /*member: ConcreteSuper.extendedAbstractField#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSuper.extendedAbstractField=#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractField;
+
+  /*member: ConcreteSuper.declaredConcreteExtendsConcreteField#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSuper.declaredConcreteExtendsConcreteField=#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int declaredConcreteExtendsConcreteField = 0;
+
+  /*member: ConcreteSuper.declaredAbstractExtendsConcreteField#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSuper.declaredAbstractExtendsConcreteField=#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int declaredAbstractExtendsConcreteField = 0;
+
+  /*member: ConcreteSuper.declaredConcreteExtendsAbstractField#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSuper.declaredConcreteExtendsAbstractField=#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  abstract int declaredConcreteExtendsAbstractField;
+
+  /*member: ConcreteSuper.declaredAbstractExtendsAbstractField#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSuper.declaredAbstractExtendsAbstractField=#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractExtendsAbstractField,
+  ConcreteClass.declaredAbstractExtendsAbstractField=,
+  ConcreteClass.declaredAbstractField,
+  ConcreteClass.declaredAbstractField=,
+  ConcreteSuper.extendedAbstractField,
+  ConcreteSuper.extendedAbstractField=],
+ maxInheritancePath=2,
+ superclasses=[
+  ConcreteSuper,
+  Object]
+*/
+class ConcreteClass extends ConcreteSuper {
+  /*member: ConcreteClass.extendedConcreteField#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.extendedConcreteField=#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractField#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.extendedAbstractField=#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteField#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declaredConcreteField=#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  int declaredConcreteField = 0;
+
+  /*member: ConcreteClass.declaredAbstractField#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declaredAbstractField=#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  abstract int declaredAbstractField;
+
+  /*member: ConcreteClass.declaredConcreteExtendsConcreteField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    ConcreteSuper.declaredConcreteExtendsConcreteField,
+    ConcreteSuper.declaredConcreteExtendsConcreteField=],
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declaredConcreteExtendsConcreteField=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    ConcreteSuper.declaredConcreteExtendsConcreteField,
+    ConcreteSuper.declaredConcreteExtendsConcreteField=],
+   isSourceDeclaration
+  */
+  int declaredConcreteExtendsConcreteField = 0;
+
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteField#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.declaredAbstractExtendsConcreteField],
+   isSynthesized,
+   member=ConcreteSuper.declaredAbstractExtendsConcreteField
+  */
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsConcreteField,
+    ConcreteSuper.declaredAbstractExtendsConcreteField],
+   declared-overrides=[
+    ConcreteSuper.declaredAbstractExtendsConcreteField,
+    ConcreteSuper.declaredAbstractExtendsConcreteField=],
+   isSynthesized
+  */
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteField=#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.declaredAbstractExtendsConcreteField=],
+   isSynthesized,
+   member=ConcreteSuper.declaredAbstractExtendsConcreteField
+  */
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsConcreteField=,
+    ConcreteSuper.declaredAbstractExtendsConcreteField=],
+   declared-overrides=[
+    ConcreteSuper.declaredAbstractExtendsConcreteField,
+    ConcreteSuper.declaredAbstractExtendsConcreteField=],
+   isSynthesized
+  */
+  abstract int declaredAbstractExtendsConcreteField;
+
+  /*member: ConcreteClass.declaredConcreteExtendsAbstractField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    ConcreteSuper.declaredConcreteExtendsAbstractField,
+    ConcreteSuper.declaredConcreteExtendsAbstractField=],
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declaredConcreteExtendsAbstractField=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    ConcreteSuper.declaredConcreteExtendsAbstractField,
+    ConcreteSuper.declaredConcreteExtendsAbstractField=],
+   isSourceDeclaration
+  */
+  int declaredConcreteExtendsAbstractField = 0;
+
+  /*member: ConcreteClass.declaredAbstractExtendsAbstractField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsAbstractField,
+    ConcreteSuper.declaredAbstractExtendsAbstractField],
+   declared-overrides=[
+    ConcreteSuper.declaredAbstractExtendsAbstractField,
+    ConcreteSuper.declaredAbstractExtendsAbstractField=],
+   isSynthesized
+  */
+  /*member: ConcreteClass.declaredAbstractExtendsAbstractField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsAbstractField=,
+    ConcreteSuper.declaredAbstractExtendsAbstractField=],
+   declared-overrides=[
+    ConcreteSuper.declaredAbstractExtendsAbstractField,
+    ConcreteSuper.declaredAbstractExtendsAbstractField=],
+   isSynthesized
+  */
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_extends_final_field.dart b/pkg/front_end/test/class_hierarchy/data/concrete_extends_final_field.dart
new file mode 100644
index 0000000..10334b2
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_extends_final_field.dart
@@ -0,0 +1,125 @@
+// 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: ConcreteSuper:
+ abstractMembers=[
+  ConcreteSuper.declaredAbstractExtendsAbstractField,
+  ConcreteSuper.declaredConcreteExtendsAbstractField,
+  ConcreteSuper.extendedAbstractField],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class ConcreteSuper {
+  /*member: ConcreteSuper.extendedConcreteField#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  final int extendedConcreteField = 0;
+
+  /*member: ConcreteSuper.extendedAbstractField#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractField;
+
+  /*member: ConcreteSuper.declaredConcreteExtendsConcreteField#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  final int declaredConcreteExtendsConcreteField = 0;
+
+  /*member: ConcreteSuper.declaredAbstractExtendsConcreteField#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  final int declaredAbstractExtendsConcreteField = 0;
+
+  /*member: ConcreteSuper.declaredConcreteExtendsAbstractField#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  abstract final int declaredConcreteExtendsAbstractField;
+
+  /*member: ConcreteSuper.declaredAbstractExtendsAbstractField#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractExtendsAbstractField,
+  ConcreteClass.declaredAbstractField,
+  ConcreteSuper.extendedAbstractField],
+ maxInheritancePath=2,
+ superclasses=[
+  ConcreteSuper,
+  Object]
+*/
+class ConcreteClass extends ConcreteSuper {
+  /*member: ConcreteClass.extendedConcreteField#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractField#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteField#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  final int declaredConcreteField = 0;
+
+  /*member: ConcreteClass.declaredAbstractField#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  abstract final int declaredAbstractField;
+
+  /*member: ConcreteClass.declaredConcreteExtendsConcreteField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[ConcreteSuper.declaredConcreteExtendsConcreteField],
+   isSourceDeclaration
+  */
+  final int declaredConcreteExtendsConcreteField = 0;
+
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteField#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.declaredAbstractExtendsConcreteField],
+   isSynthesized,
+   member=ConcreteSuper.declaredAbstractExtendsConcreteField
+  */
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsConcreteField,
+    ConcreteSuper.declaredAbstractExtendsConcreteField],
+   declared-overrides=[ConcreteSuper.declaredAbstractExtendsConcreteField],
+   isSynthesized
+  */
+  abstract final int declaredAbstractExtendsConcreteField;
+
+  /*member: ConcreteClass.declaredConcreteExtendsAbstractField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[ConcreteSuper.declaredConcreteExtendsAbstractField],
+   isSourceDeclaration
+  */
+  final int declaredConcreteExtendsAbstractField = 0;
+
+  /*member: ConcreteClass.declaredAbstractExtendsAbstractField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsAbstractField,
+    ConcreteSuper.declaredAbstractExtendsAbstractField],
+   declared-overrides=[ConcreteSuper.declaredAbstractExtendsAbstractField],
+   isSynthesized
+  */
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_extends_getter.dart b/pkg/front_end/test/class_hierarchy/data/concrete_extends_getter.dart
new file mode 100644
index 0000000..8bf90fe
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_extends_getter.dart
@@ -0,0 +1,125 @@
+// 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: ConcreteSuper:
+ abstractMembers=[
+  ConcreteSuper.declaredAbstractExtendsAbstractGetter,
+  ConcreteSuper.declaredConcreteExtendsAbstractGetter,
+  ConcreteSuper.extendedAbstractGetter],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class ConcreteSuper {
+  /*member: ConcreteSuper.extendedConcreteGetter#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int get extendedConcreteGetter => 0;
+
+  /*member: ConcreteSuper.extendedAbstractGetter#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int get extendedAbstractGetter;
+
+  /*member: ConcreteSuper.declaredConcreteExtendsConcreteGetter#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int get declaredConcreteExtendsConcreteGetter => 0;
+
+  /*member: ConcreteSuper.declaredAbstractExtendsConcreteGetter#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int get declaredAbstractExtendsConcreteGetter => 0;
+
+  /*member: ConcreteSuper.declaredConcreteExtendsAbstractGetter#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int get declaredConcreteExtendsAbstractGetter;
+
+  /*member: ConcreteSuper.declaredAbstractExtendsAbstractGetter#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractExtendsAbstractGetter,
+  ConcreteClass.declaredAbstractGetter,
+  ConcreteSuper.extendedAbstractGetter],
+ maxInheritancePath=2,
+ superclasses=[
+  ConcreteSuper,
+  Object]
+*/
+class ConcreteClass extends ConcreteSuper {
+  /*member: ConcreteClass.extendedConcreteGetter#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractGetter#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteGetter#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  int get declaredConcreteGetter => 0;
+
+  /*member: ConcreteClass.declaredAbstractGetter#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  int get declaredAbstractGetter;
+
+  /*member: ConcreteClass.declaredConcreteExtendsConcreteGetter#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[ConcreteSuper.declaredConcreteExtendsConcreteGetter],
+   isSourceDeclaration
+  */
+  int get declaredConcreteExtendsConcreteGetter => 0;
+
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteGetter#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.declaredAbstractExtendsConcreteGetter],
+   isSynthesized,
+   member=ConcreteSuper.declaredAbstractExtendsConcreteGetter
+  */
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsConcreteGetter,
+    ConcreteSuper.declaredAbstractExtendsConcreteGetter],
+   declared-overrides=[ConcreteSuper.declaredAbstractExtendsConcreteGetter],
+   isSynthesized
+  */
+  int get declaredAbstractExtendsConcreteGetter;
+
+  /*member: ConcreteClass.declaredConcreteExtendsAbstractGetter#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[ConcreteSuper.declaredConcreteExtendsAbstractGetter],
+   isSourceDeclaration
+  */
+  int get declaredConcreteExtendsAbstractGetter => 0;
+
+  /*member: ConcreteClass.declaredAbstractExtendsAbstractGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsAbstractGetter,
+    ConcreteSuper.declaredAbstractExtendsAbstractGetter],
+   declared-overrides=[ConcreteSuper.declaredAbstractExtendsAbstractGetter],
+   isSynthesized
+  */
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_extends_method.dart b/pkg/front_end/test/class_hierarchy/data/concrete_extends_method.dart
new file mode 100644
index 0000000..d35a461
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_extends_method.dart
@@ -0,0 +1,123 @@
+// 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: ConcreteSuper:
+ abstractMembers=[
+  ConcreteSuper.declaredAbstractExtendsAbstractMethod,
+  ConcreteSuper.declaredConcreteExtendsAbstractMethod,
+  ConcreteSuper.extendedAbstractMethod],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class ConcreteSuper {
+  /*member: ConcreteSuper.extendedConcreteMethod#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void extendedConcreteMethod() {}
+
+  /*member: ConcreteSuper.extendedAbstractMethod#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void extendedAbstractMethod();
+
+  /*member: ConcreteSuper.declaredConcreteExtendsConcreteMethod#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void declaredConcreteExtendsConcreteMethod() {}
+
+  /*member: ConcreteSuper.declaredAbstractExtendsConcreteMethod#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void declaredAbstractExtendsConcreteMethod() {}
+
+  /*member: ConcreteSuper.declaredConcreteExtendsAbstractMethod#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void declaredConcreteExtendsAbstractMethod();
+
+  /*member: ConcreteSuper.declaredAbstractExtendsAbstractMethod#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractExtendsAbstractMethod,
+  ConcreteClass.declaredAbstractMethod,
+  ConcreteSuper.extendedAbstractMethod],
+ maxInheritancePath=2,
+ superclasses=[
+  ConcreteSuper,
+  Object]
+*/
+class ConcreteClass extends ConcreteSuper {
+  /*member: ConcreteClass.extendedConcreteMethod#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractMethod#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteMethod#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  void declaredConcreteMethod() {}
+
+  /*member: ConcreteClass.declaredAbstractMethod#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  void declaredAbstractMethod();
+
+  /*member: ConcreteClass.declaredConcreteExtendsConcreteMethod#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[ConcreteSuper.declaredConcreteExtendsConcreteMethod],
+   isSourceDeclaration
+  */
+  void declaredConcreteExtendsConcreteMethod() {}
+
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteMethod#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.declaredAbstractExtendsConcreteMethod],
+   isSynthesized,
+   member=ConcreteSuper.declaredAbstractExtendsConcreteMethod
+  */
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsConcreteMethod,
+    ConcreteSuper.declaredAbstractExtendsConcreteMethod],
+   declared-overrides=[ConcreteSuper.declaredAbstractExtendsConcreteMethod],
+   isSynthesized
+  */
+  void declaredAbstractExtendsConcreteMethod();
+
+  /*member: ConcreteClass.declaredConcreteExtendsAbstractMethod#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[ConcreteSuper.declaredConcreteExtendsAbstractMethod],
+   isSourceDeclaration
+  */
+  void declaredConcreteExtendsAbstractMethod() {}
+
+  /*member: ConcreteClass.declaredAbstractExtendsAbstractMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsAbstractMethod,
+    ConcreteSuper.declaredAbstractExtendsAbstractMethod],
+   declared-overrides=[ConcreteSuper.declaredAbstractExtendsAbstractMethod],
+   isSynthesized
+  */
+  void declaredAbstractExtendsAbstractMethod();
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_extends_setter.dart b/pkg/front_end/test/class_hierarchy/data/concrete_extends_setter.dart
new file mode 100644
index 0000000..35a7340
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_extends_setter.dart
@@ -0,0 +1,125 @@
+// 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: ConcreteSuper:
+ abstractMembers=[
+  ConcreteSuper.declaredAbstractExtendsAbstractSetter=,
+  ConcreteSuper.declaredConcreteExtendsAbstractSetter=,
+  ConcreteSuper.extendedAbstractSetter=],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class ConcreteSuper {
+  /*member: ConcreteSuper.extendedConcreteSetter=#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void set extendedConcreteSetter(int value) {}
+
+  /*member: ConcreteSuper.extendedAbstractSetter=#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void set extendedAbstractSetter(int value);
+
+  /*member: ConcreteSuper.declaredConcreteExtendsConcreteSetter=#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+
+  /*member: ConcreteSuper.declaredAbstractExtendsConcreteSetter=#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void set declaredAbstractExtendsConcreteSetter(int value) {}
+
+  /*member: ConcreteSuper.declaredConcreteExtendsAbstractSetter=#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void set declaredConcreteExtendsAbstractSetter(int value);
+
+  /*member: ConcreteSuper.declaredAbstractExtendsAbstractSetter=#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractExtendsAbstractSetter=,
+  ConcreteClass.declaredAbstractSetter=,
+  ConcreteSuper.extendedAbstractSetter=],
+ maxInheritancePath=2,
+ superclasses=[
+  ConcreteSuper,
+  Object]
+*/
+class ConcreteClass extends ConcreteSuper {
+  /*member: ConcreteClass.extendedConcreteSetter=#cls:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractSetter=#int:
+   classBuilder=ConcreteSuper,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteSetter=#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  void set declaredConcreteSetter(int value) {}
+
+  /*member: ConcreteClass.declaredAbstractSetter=#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  void set declaredAbstractSetter(int value);
+
+  /*member: ConcreteClass.declaredConcreteExtendsConcreteSetter=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[ConcreteSuper.declaredConcreteExtendsConcreteSetter=],
+   isSourceDeclaration
+  */
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteSetter=#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.declaredAbstractExtendsConcreteSetter=],
+   isSynthesized,
+   member=ConcreteSuper.declaredAbstractExtendsConcreteSetter=
+  */
+  /*member: ConcreteClass.declaredAbstractExtendsConcreteSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsConcreteSetter=,
+    ConcreteSuper.declaredAbstractExtendsConcreteSetter=],
+   declared-overrides=[ConcreteSuper.declaredAbstractExtendsConcreteSetter=],
+   isSynthesized
+  */
+  void set declaredAbstractExtendsConcreteSetter(int value);
+
+  /*member: ConcreteClass.declaredConcreteExtendsAbstractSetter=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[ConcreteSuper.declaredConcreteExtendsAbstractSetter=],
+   isSourceDeclaration
+  */
+  void set declaredConcreteExtendsAbstractSetter(int value) {}
+
+  /*member: ConcreteClass.declaredAbstractExtendsAbstractSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractExtendsAbstractSetter=,
+    ConcreteSuper.declaredAbstractExtendsAbstractSetter=],
+   declared-overrides=[ConcreteSuper.declaredAbstractExtendsAbstractSetter=],
+   isSynthesized
+  */
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_implements_field.dart b/pkg/front_end/test/class_hierarchy/data/concrete_implements_field.dart
new file mode 100644
index 0000000..dabaa18
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_implements_field.dart
@@ -0,0 +1,210 @@
+// 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: Interface:
+ abstractMembers=[
+  Interface.declaredAbstractImplementsAbstractField,
+  Interface.declaredAbstractImplementsAbstractField=,
+  Interface.declaredConcreteImplementsAbstractField,
+  Interface.declaredConcreteImplementsAbstractField=,
+  Interface.implementedAbstractField,
+  Interface.implementedAbstractField=],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface {
+  /*member: Interface.implementedConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.implementedConcreteField=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int implementedConcreteField = 0;
+
+  /*member: Interface.implementedAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.implementedAbstractField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract int implementedAbstractField;
+
+  /*member: Interface.declaredConcreteImplementsConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.declaredConcreteImplementsConcreteField=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int declaredConcreteImplementsConcreteField = 0;
+
+  /*member: Interface.declaredAbstractImplementsConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.declaredAbstractImplementsConcreteField=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int declaredAbstractImplementsConcreteField = 0;
+
+  /*member: Interface.declaredConcreteImplementsAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.declaredConcreteImplementsAbstractField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract int declaredConcreteImplementsAbstractField;
+
+  /*member: Interface.declaredAbstractImplementsAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.declaredAbstractImplementsAbstractField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractField,
+  ConcreteClass.declaredAbstractField=,
+  ConcreteClass.declaredAbstractImplementsAbstractField,
+  ConcreteClass.declaredAbstractImplementsAbstractField=,
+  ConcreteClass.declaredAbstractImplementsConcreteField,
+  ConcreteClass.declaredAbstractImplementsConcreteField=,
+  Interface.implementedAbstractField,
+  Interface.implementedAbstractField=,
+  Interface.implementedConcreteField,
+  Interface.implementedConcreteField=],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface {
+  /*member: ConcreteClass.implementedConcreteField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.implementedConcreteField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.implementedAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.implementedAbstractField=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteField#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declaredConcreteField=#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  int declaredConcreteField = 0;
+
+  /*member: ConcreteClass.declaredAbstractField#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declaredAbstractField=#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  abstract int declaredAbstractField;
+
+  /*member: ConcreteClass.declaredConcreteImplementsConcreteField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface.declaredConcreteImplementsConcreteField,
+    Interface.declaredConcreteImplementsConcreteField=],
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declaredConcreteImplementsConcreteField=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface.declaredConcreteImplementsConcreteField,
+    Interface.declaredConcreteImplementsConcreteField=],
+   isSourceDeclaration
+  */
+  int declaredConcreteImplementsConcreteField = 0;
+
+  /*member: ConcreteClass.declaredAbstractImplementsConcreteField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsConcreteField,
+    Interface.declaredAbstractImplementsConcreteField],
+   declared-overrides=[
+    Interface.declaredAbstractImplementsConcreteField,
+    Interface.declaredAbstractImplementsConcreteField=],
+   isSynthesized
+  */
+  /*member: ConcreteClass.declaredAbstractImplementsConcreteField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsConcreteField=,
+    Interface.declaredAbstractImplementsConcreteField=],
+   declared-overrides=[
+    Interface.declaredAbstractImplementsConcreteField,
+    Interface.declaredAbstractImplementsConcreteField=],
+   isSynthesized
+  */
+  abstract int declaredAbstractImplementsConcreteField;
+
+  /*member: ConcreteClass.declaredConcreteImplementsAbstractField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface.declaredConcreteImplementsAbstractField,
+    Interface.declaredConcreteImplementsAbstractField=],
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declaredConcreteImplementsAbstractField=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface.declaredConcreteImplementsAbstractField,
+    Interface.declaredConcreteImplementsAbstractField=],
+   isSourceDeclaration
+  */
+  int declaredConcreteImplementsAbstractField = 0;
+
+  /*member: ConcreteClass.declaredAbstractImplementsAbstractField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsAbstractField,
+    Interface.declaredAbstractImplementsAbstractField],
+   declared-overrides=[
+    Interface.declaredAbstractImplementsAbstractField,
+    Interface.declaredAbstractImplementsAbstractField=],
+   isSynthesized
+  */
+  /*member: ConcreteClass.declaredAbstractImplementsAbstractField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsAbstractField=,
+    Interface.declaredAbstractImplementsAbstractField=],
+   declared-overrides=[
+    Interface.declaredAbstractImplementsAbstractField,
+    Interface.declaredAbstractImplementsAbstractField=],
+   isSynthesized
+  */
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_implements_final_field.dart b/pkg/front_end/test/class_hierarchy/data/concrete_implements_final_field.dart
new file mode 100644
index 0000000..20a42b0
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_implements_final_field.dart
@@ -0,0 +1,120 @@
+// 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: Interface:
+ abstractMembers=[
+  Interface.declaredAbstractImplementsAbstractField,
+  Interface.declaredConcreteImplementsAbstractField,
+  Interface.implementedAbstractField],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface {
+  /*member: Interface.implementedConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  final int implementedConcreteField = 0;
+
+  /*member: Interface.implementedAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract final int implementedAbstractField;
+
+  /*member: Interface.declaredConcreteImplementsConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  final int declaredConcreteImplementsConcreteField = 0;
+
+  /*member: Interface.declaredAbstractImplementsConcreteField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  final int declaredAbstractImplementsConcreteField = 0;
+
+  /*member: Interface.declaredConcreteImplementsAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract final int declaredConcreteImplementsAbstractField;
+
+  /*member: Interface.declaredAbstractImplementsAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractField,
+  ConcreteClass.declaredAbstractImplementsAbstractField,
+  ConcreteClass.declaredAbstractImplementsConcreteField,
+  Interface.implementedAbstractField,
+  Interface.implementedConcreteField],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface {
+  /*member: ConcreteClass.implementedConcreteField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.implementedAbstractField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteField#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  final int declaredConcreteField = 0;
+
+  /*member: ConcreteClass.declaredAbstractField#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  abstract final int declaredAbstractField;
+
+  /*member: ConcreteClass.declaredConcreteImplementsConcreteField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[Interface.declaredConcreteImplementsConcreteField],
+   isSourceDeclaration
+  */
+  final int declaredConcreteImplementsConcreteField = 0;
+
+  /*member: ConcreteClass.declaredAbstractImplementsConcreteField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsConcreteField,
+    Interface.declaredAbstractImplementsConcreteField],
+   declared-overrides=[Interface.declaredAbstractImplementsConcreteField],
+   isSynthesized
+  */
+  abstract final int declaredAbstractImplementsConcreteField;
+
+  /*member: ConcreteClass.declaredConcreteImplementsAbstractField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[Interface.declaredConcreteImplementsAbstractField],
+   isSourceDeclaration
+  */
+  final int declaredConcreteImplementsAbstractField = 0;
+
+  /*member: ConcreteClass.declaredAbstractImplementsAbstractField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsAbstractField,
+    Interface.declaredAbstractImplementsAbstractField],
+   declared-overrides=[Interface.declaredAbstractImplementsAbstractField],
+   isSynthesized
+  */
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_implements_getter.dart b/pkg/front_end/test/class_hierarchy/data/concrete_implements_getter.dart
new file mode 100644
index 0000000..80dbb0a
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_implements_getter.dart
@@ -0,0 +1,118 @@
+// 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: Interface:
+ abstractMembers=[
+  Interface.declaredAbstractImplementsAbstractGetter,
+  Interface.declaredConcreteImplementsAbstractGetter,
+  Interface.implementedAbstractGetter],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface {
+  /*member: Interface.implementedConcreteGetter#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get implementedConcreteGetter => 0;
+
+  /*member: Interface.implementedAbstractGetter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get implementedAbstractGetter;
+
+  /*member: Interface.declaredConcreteImplementsConcreteGetter#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get declaredConcreteImplementsConcreteGetter => 0;
+
+  /*member: Interface.declaredAbstractImplementsConcreteGetter#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get declaredAbstractImplementsConcreteGetter => 0;
+
+  /*member: Interface.declaredConcreteImplementsAbstractGetter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get declaredConcreteImplementsAbstractGetter;
+
+  /*member: Interface.declaredAbstractImplementsAbstractGetter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractGetter,
+  ConcreteClass.declaredAbstractImplementsAbstractGetter,
+  ConcreteClass.declaredAbstractImplementsConcreteGetter,
+  Interface.implementedAbstractGetter,
+  Interface.implementedConcreteGetter],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+/*member: ConcreteClass.implementedConcreteGetter#int:
+ classBuilder=Interface,
+ isSourceDeclaration
+*/
+/*member: ConcreteClass.implementedAbstractGetter#int:
+ classBuilder=Interface,
+ isSourceDeclaration
+*/
+class ConcreteClass implements Interface {
+  /*member: ConcreteClass.declaredConcreteGetter#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  int get declaredConcreteGetter => 0;
+
+  /*member: ConcreteClass.declaredAbstractGetter#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  int get declaredAbstractGetter;
+
+  /*member: ConcreteClass.declaredConcreteImplementsConcreteGetter#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[Interface.declaredConcreteImplementsConcreteGetter],
+   isSourceDeclaration
+  */
+  int get declaredConcreteImplementsConcreteGetter => 0;
+
+  /*member: ConcreteClass.declaredAbstractImplementsConcreteGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsConcreteGetter,
+    Interface.declaredAbstractImplementsConcreteGetter],
+   declared-overrides=[Interface.declaredAbstractImplementsConcreteGetter],
+   isSynthesized
+  */
+  int get declaredAbstractImplementsConcreteGetter;
+
+  /*member: ConcreteClass.declaredConcreteImplementsAbstractGetter#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[Interface.declaredConcreteImplementsAbstractGetter],
+   isSourceDeclaration
+  */
+  int get declaredConcreteImplementsAbstractGetter => 0;
+
+  /*member: ConcreteClass.declaredAbstractImplementsAbstractGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsAbstractGetter,
+    Interface.declaredAbstractImplementsAbstractGetter],
+   declared-overrides=[Interface.declaredAbstractImplementsAbstractGetter],
+   isSynthesized
+  */
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_implements_method.dart b/pkg/front_end/test/class_hierarchy/data/concrete_implements_method.dart
new file mode 100644
index 0000000..a040731
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_implements_method.dart
@@ -0,0 +1,118 @@
+// 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: Interface:
+ abstractMembers=[
+  Interface.declaredAbstractImplementsAbstractMethod,
+  Interface.declaredConcreteImplementsAbstractMethod,
+  Interface.implementedAbstractMethod],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface {
+  /*member: Interface.implementedConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void implementedConcreteMethod() {}
+
+  /*member: Interface.implementedAbstractMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void implementedAbstractMethod();
+
+  /*member: Interface.declaredConcreteImplementsConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void declaredConcreteImplementsConcreteMethod() {}
+
+  /*member: Interface.declaredAbstractImplementsConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void declaredAbstractImplementsConcreteMethod() {}
+
+  /*member: Interface.declaredConcreteImplementsAbstractMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void declaredConcreteImplementsAbstractMethod();
+
+  /*member: Interface.declaredAbstractImplementsAbstractMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractImplementsAbstractMethod,
+  ConcreteClass.declaredAbstractImplementsConcreteMethod,
+  ConcreteClass.declaredAbstractMethod,
+  Interface.implementedAbstractMethod,
+  Interface.implementedConcreteMethod],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface {
+  /*member: ConcreteClass.implementedConcreteMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.implementedAbstractMethod#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteMethod#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  void declaredConcreteMethod() {}
+
+  /*member: ConcreteClass.declaredAbstractMethod#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  void declaredAbstractMethod();
+
+  /*member: ConcreteClass.declaredConcreteImplementsConcreteMethod#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[Interface.declaredConcreteImplementsConcreteMethod],
+   isSourceDeclaration
+  */
+  void declaredConcreteImplementsConcreteMethod() {}
+
+  /*member: ConcreteClass.declaredAbstractImplementsConcreteMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsConcreteMethod,
+    Interface.declaredAbstractImplementsConcreteMethod],
+   declared-overrides=[Interface.declaredAbstractImplementsConcreteMethod],
+   isSynthesized
+  */
+  void declaredAbstractImplementsConcreteMethod();
+
+  /*member: ConcreteClass.declaredConcreteImplementsAbstractMethod#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[Interface.declaredConcreteImplementsAbstractMethod],
+   isSourceDeclaration
+  */
+  void declaredConcreteImplementsAbstractMethod() {}
+
+  /*member: ConcreteClass.declaredAbstractImplementsAbstractMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsAbstractMethod,
+    Interface.declaredAbstractImplementsAbstractMethod],
+   declared-overrides=[Interface.declaredAbstractImplementsAbstractMethod],
+   isSynthesized
+  */
+  void declaredAbstractImplementsAbstractMethod();
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/concrete_implements_setter.dart b/pkg/front_end/test/class_hierarchy/data/concrete_implements_setter.dart
new file mode 100644
index 0000000..92279c3
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/concrete_implements_setter.dart
@@ -0,0 +1,120 @@
+// 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: Interface:
+ abstractMembers=[
+  Interface.declaredAbstractImplementsAbstractSetter=,
+  Interface.declaredConcreteImplementsAbstractSetter=,
+  Interface.implementedAbstractSetter=],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface {
+  /*member: Interface.implementedConcreteSetter=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set implementedConcreteSetter(int value) {}
+
+  /*member: Interface.implementedAbstractSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set implementedAbstractSetter(int value);
+
+  /*member: Interface.declaredConcreteImplementsConcreteSetter=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+
+  /*member: Interface.declaredAbstractImplementsConcreteSetter=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set declaredAbstractImplementsConcreteSetter(int value) {}
+
+  /*member: Interface.declaredConcreteImplementsAbstractSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set declaredConcreteImplementsAbstractSetter(int value);
+
+  /*member: Interface.declaredAbstractImplementsAbstractSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declaredAbstractImplementsAbstractSetter=,
+  ConcreteClass.declaredAbstractImplementsConcreteSetter=,
+  ConcreteClass.declaredAbstractSetter=,
+  Interface.implementedAbstractSetter=,
+  Interface.implementedConcreteSetter=],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface {
+  /*member: ConcreteClass.implementedConcreteSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.implementedAbstractSetter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.declaredConcreteSetter=#cls:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  void set declaredConcreteSetter(int value) {}
+
+  /*member: ConcreteClass.declaredAbstractSetter=#int:
+   classBuilder=ConcreteClass,
+   isSourceDeclaration
+  */
+  void set declaredAbstractSetter(int value);
+
+  /*member: ConcreteClass.declaredConcreteImplementsConcreteSetter=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[Interface.declaredConcreteImplementsConcreteSetter=],
+   isSourceDeclaration
+  */
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+
+  /*member: ConcreteClass.declaredAbstractImplementsConcreteSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsConcreteSetter=,
+    Interface.declaredAbstractImplementsConcreteSetter=],
+   declared-overrides=[Interface.declaredAbstractImplementsConcreteSetter=],
+   isSynthesized
+  */
+  void set declaredAbstractImplementsConcreteSetter(int value);
+
+  /*member: ConcreteClass.declaredConcreteImplementsAbstractSetter=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[Interface.declaredConcreteImplementsAbstractSetter=],
+   isSourceDeclaration
+  */
+  void set declaredConcreteImplementsAbstractSetter(int value) {}
+
+  /*member: ConcreteClass.declaredAbstractImplementsAbstractSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declaredAbstractImplementsAbstractSetter=,
+    Interface.declaredAbstractImplementsAbstractSetter=],
+   declared-overrides=[Interface.declaredAbstractImplementsAbstractSetter=],
+   isSynthesized
+  */
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/conflict.dart b/pkg/front_end/test/class_hierarchy/data/conflict.dart
new file mode 100644
index 0000000..10003cd
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/conflict.dart
@@ -0,0 +1,37 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedFieldDeclaredMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedFieldDeclaredMethod=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int extendedFieldDeclaredMethod = 0;
+}
+
+/*class: Class:
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+/*member: Class.extendedFieldDeclaredMethod=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+class Class extends Super {
+  /*member: Class.extendedFieldDeclaredMethod#cls:
+   classBuilder=Class,
+   isSourceDeclaration
+  */
+  void extendedFieldDeclaredMethod() {}
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/covariance.dart b/pkg/front_end/test/class_hierarchy/data/covariance.dart
new file mode 100644
index 0000000..e65d4ea
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/covariance.dart
@@ -0,0 +1,438 @@
+// 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.
+
+// From language/covariant_override/tear_off_type_test
+
+// If a parameter is directly or indirectly a covariant override, its type in
+// the method tear-off should become Object?.
+
+/*class: M1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class M1 {
+  /*member: M1.method#cls:
+   classBuilder=M1,
+   isSourceDeclaration
+  */
+  method(covariant int a, int b) {}
+}
+
+/*class: M2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class M2 {
+  /*member: M2.method#cls:
+   classBuilder=M2,
+   isSourceDeclaration
+  */
+  method(int a, covariant int b) {}
+}
+
+/*class: _C&Object&M1:
+ interfaces=[M1],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+
+/*member: _C&Object&M1.method#cls:
+ classBuilder=_C&Object&M1,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=M1.method
+*/
+/*member: _C&Object&M1.method#int:
+ classBuilder=_C&Object&M1,
+ concreteMixinStub,
+ declarations=[M1.method],
+ isSynthesized,
+ stubTarget=M1.method
+*/
+
+/*class: _C&Object&M1&M2:
+ interfaces=[
+  M1,
+  M2],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  _C&Object&M1]
+*/
+
+/*member: _C&Object&M1&M2.method#cls:
+ classBuilder=_C&Object&M1&M2,
+ concreteForwardingStub,
+ covariance=Covariance(0:Covariant,1:Covariant),
+ isSynthesized,
+ stubTarget=M2.method,
+ type=dynamic Function(int, int)
+*/
+/*member: _C&Object&M1&M2.method#int:
+ classBuilder=_C&Object&M1&M2,
+ concreteForwardingStub,
+ covariance=Covariance(0:Covariant,1:Covariant),
+ declarations=[
+  M2.method,
+  _C&Object&M1.method],
+ isSynthesized,
+ stubTarget=M2.method,
+ type=dynamic Function(int, int)
+*/
+
+/*class: C:
+ interfaces=[
+  M1,
+  M2],
+ maxInheritancePath=4,
+ superclasses=[
+  Object,
+  _C&Object&M1,
+  _C&Object&M1&M2]
+*/
+class C extends Object with M1, M2 {
+  /*member: C.method#cls:
+   classBuilder=C,
+   inherited-implements=[_C&Object&M1&M2.method],
+   isSynthesized,
+   member=_C&Object&M1&M2.method
+  */
+  /*member: C.method#int:
+   classBuilder=_C&Object&M1&M2,
+   declarations=[
+    M2.method,
+    _C&Object&M1.method],
+   isSynthesized,
+   member=_C&Object&M1&M2.method
+  */
+}
+
+/*class: Direct:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Direct {
+  /*member: Direct.positional#cls:
+   classBuilder=Direct,
+   isSourceDeclaration
+  */
+  void positional(covariant int a, int b, covariant int c, int d, int e) {}
+
+  /*member: Direct.optional#cls:
+   classBuilder=Direct,
+   isSourceDeclaration
+  */
+  void optional(
+      [covariant int a = 0, int b = 0, covariant int c = 0, int d = 0]) {}
+
+  /*member: Direct.named#cls:
+   classBuilder=Direct,
+   isSourceDeclaration
+  */
+  void named(
+      {covariant int a = 0, int b = 0, covariant int c = 0, int d = 0}) {}
+}
+
+/*class: Inherited:
+ maxInheritancePath=2,
+ superclasses=[
+  Direct,
+  Object]
+*/
+class Inherited extends Direct {
+  /*member: Inherited.positional#cls:
+   classBuilder=Direct,
+   isSourceDeclaration
+  */
+
+  /*member: Inherited.optional#cls:
+   classBuilder=Direct,
+   isSourceDeclaration
+  */
+
+  /*member: Inherited.named#cls:
+   classBuilder=Direct,
+   isSourceDeclaration
+  */
+}
+
+// ---
+
+/*class: Override1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Override1 {
+  /*member: Override1.method#cls:
+   classBuilder=Override1,
+   isSourceDeclaration
+  */
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+/*class: Override2:
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Override1]
+*/
+class Override2 extends Override1 {
+  /*member: Override2.method#cls:
+   classBuilder=Override2,
+   declared-overrides=[Override1.method],
+   isSourceDeclaration
+  */
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+/*class: Override3:
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Override1,
+  Override2]
+*/
+class Override3 extends Override2 {
+  /*member: Override3.method#cls:
+   classBuilder=Override3,
+   declared-overrides=[Override2.method],
+   isSourceDeclaration
+  */
+  void method(int a, int b, int c, int d, int e) {}
+}
+
+// ---
+
+/*class: Implement1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Implement1 {
+  /*member: Implement1.method#cls:
+   classBuilder=Implement1,
+   isSourceDeclaration
+  */
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+/*class: Implement2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Implement2 {
+  /*member: Implement2.method#cls:
+   classBuilder=Implement2,
+   isSourceDeclaration
+  */
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+/*class: Implement3:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Implement3 {
+  /*member: Implement3.method#cls:
+   classBuilder=Implement3,
+   isSourceDeclaration
+  */
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+/*class: Implement4:
+ interfaces=[Implement3],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class Implement4 implements Implement3 {
+  /*member: Implement4.method#cls:
+   classBuilder=Implement4,
+   declared-overrides=[Implement3.method],
+   isSourceDeclaration
+  */
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+/*class: Implement5:
+ interfaces=[
+  Implement1,
+  Implement2,
+  Implement3,
+  Implement4],
+ maxInheritancePath=3,
+ superclasses=[Object]
+*/
+class Implement5 implements Implement1, Implement2, Implement4 {
+  /*member: Implement5.method#cls:
+   classBuilder=Implement5,
+   declared-overrides=[
+    Implement1.method,
+    Implement2.method,
+    Implement4.method],
+   isSourceDeclaration
+  */
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+// ---
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.method#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.method#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+/*class: Mixin1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Mixin1 {
+  /*member: Mixin1.method#cls:
+   classBuilder=Mixin1,
+   isSourceDeclaration
+  */
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+/*class: Mixin2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Mixin2 {
+  /*member: Mixin2.method#cls:
+   classBuilder=Mixin2,
+   isSourceDeclaration
+  */
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+/*class: Superclass:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Superclass {
+  /*member: Superclass.method#cls:
+   classBuilder=Superclass,
+   isSourceDeclaration
+  */
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+/*class: _Mixed&Superclass&Mixin1:
+ interfaces=[Mixin1],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Superclass]
+*/
+
+/*member: _Mixed&Superclass&Mixin1.method#cls:
+ classBuilder=_Mixed&Superclass&Mixin1,
+ concreteForwardingStub,
+ covariance=Covariance(2:Covariant,4:Covariant),
+ isSynthesized,
+ stubTarget=Mixin1.method,
+ type=void Function(int, int, int, int, int)
+*/
+/*member: _Mixed&Superclass&Mixin1.method#int:
+ classBuilder=_Mixed&Superclass&Mixin1,
+ concreteForwardingStub,
+ covariance=Covariance(2:Covariant,4:Covariant),
+ declarations=[
+  Mixin1.method,
+  Superclass.method],
+ isSynthesized,
+ stubTarget=Mixin1.method,
+ type=void Function(int, int, int, int, int)
+*/
+
+/*class: _Mixed&Superclass&Mixin1&Mixin2:
+ interfaces=[
+  Mixin1,
+  Mixin2],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Superclass,
+  _Mixed&Superclass&Mixin1]
+*/
+
+/*member: _Mixed&Superclass&Mixin1&Mixin2.method#cls:
+ classBuilder=_Mixed&Superclass&Mixin1&Mixin2,
+ concreteForwardingStub,
+ covariance=Covariance(2:Covariant,3:Covariant,4:Covariant),
+ isSynthesized,
+ stubTarget=Mixin2.method,
+ type=void Function(int, int, int, int, int)
+*/
+/*member: _Mixed&Superclass&Mixin1&Mixin2.method#int:
+ classBuilder=_Mixed&Superclass&Mixin1&Mixin2,
+ concreteForwardingStub,
+ covariance=Covariance(2:Covariant,3:Covariant,4:Covariant),
+ declarations=[
+  Mixin2.method,
+  _Mixed&Superclass&Mixin1.method],
+ isSynthesized,
+ stubTarget=Mixin2.method,
+ type=void Function(int, int, int, int, int)
+*/
+
+/*class: Mixed:
+ interfaces=[
+  Interface1,
+  Interface2,
+  Mixin1,
+  Mixin2],
+ maxInheritancePath=4,
+ superclasses=[
+  Object,
+  Superclass,
+  _Mixed&Superclass&Mixin1,
+  _Mixed&Superclass&Mixin1&Mixin2]
+*/
+class Mixed extends Superclass
+    with Mixin1, Mixin2
+    implements Interface1, Interface2 {
+  /*member: Mixed.method#cls:
+   classBuilder=Mixed,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant,1:Covariant,2:Covariant,3:Covariant,4:Covariant),
+   inherited-implements=[Mixed.method],
+   isSynthesized,
+   stubTarget=Mixin2.method,
+   type=void Function(int, int, int, int, int)
+  */
+  /*member: Mixed.method#int:
+   classBuilder=Mixed,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant,1:Covariant,2:Covariant,3:Covariant,4:Covariant),
+   declarations=[
+    Interface1.method,
+    Interface2.method,
+    _Mixed&Superclass&Mixin1&Mixin2.method],
+   isSynthesized,
+   stubTarget=Mixin2.method,
+   type=void Function(int, int, int, int, int)
+  */
+}
+
+void main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/covariant_equals.dart b/pkg/front_end/test/class_hierarchy/data/covariant_equals.dart
new file mode 100644
index 0000000..5c20e81
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/covariant_equals.dart
@@ -0,0 +1,61 @@
+// 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
+
+/*class: A:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class A {
+  /*member: A.==#cls:
+   classBuilder=A,
+   declared-overrides=[Object.==],
+   isSourceDeclaration
+  */
+  bool operator ==(covariant A other) => true;
+}
+
+/*class: B:
+ maxInheritancePath=2,
+ superclasses=[
+  A,
+  Object]
+*/
+class B extends A {
+  /*member: B.==#cls:
+   classBuilder=B,
+   declared-overrides=[A.==],
+   isSourceDeclaration
+  */
+  bool operator ==(other) => true;
+}
+
+/*class: C:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class C<T> {
+  /*member: C.==#cls:
+   classBuilder=C,
+   declared-overrides=[Object.==],
+   isSourceDeclaration
+  */
+  bool operator ==(covariant C<T> other) => true;
+}
+
+/*class: D:
+ maxInheritancePath=2,
+ superclasses=[
+  C<int>,
+  Object]
+*/
+class D extends C<int> {
+  /*member: D.==#cls:
+   classBuilder=C,
+   isSourceDeclaration
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/declares.dart b/pkg/front_end/test/class_hierarchy/data/declares.dart
new file mode 100644
index 0000000..ea7fd5b
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/declares.dart
@@ -0,0 +1,223 @@
+// 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: Super:
+ abstractMembers=[
+  Super.extendedAbstractDeclaredAbstractMethod,
+  Super.extendedAbstractDeclaredConcreteMethod,
+  Super.extendedAbstractImplementedDeclaredAbstractMethod,
+  Super.extendedAbstractImplementedDeclaredConcreteMethod],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedConcreteDeclaredConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteDeclaredConcreteMethod() {}
+
+  /*member: Super.extendedAbstractDeclaredConcreteMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractDeclaredConcreteMethod();
+
+  /*member: Super.extendedConcreteDeclaredAbstractMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteDeclaredAbstractMethod() {}
+  /*member: Super.extendedAbstractDeclaredAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractDeclaredAbstractMethod();
+
+  /*member: Super.extendedConcreteImplementedDeclaredConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+
+  /*member: Super.extendedAbstractImplementedDeclaredConcreteMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedDeclaredConcreteMethod();
+
+  /*member: Super.extendedConcreteImplementedDeclaredAbstractMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedDeclaredAbstractMethod() {}
+
+  /*member: Super.extendedAbstractImplementedDeclaredAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedDeclaredAbstractMethod();
+}
+
+/*class: Interface:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface {
+  /*member: Interface.implementedDeclaredConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void implementedDeclaredConcreteMethod() {}
+
+  /*member: Interface.implementedDeclaredAbstractMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void implementedDeclaredAbstractMethod() {}
+
+  /*member: Interface.extendedConcreteImplementedDeclaredConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+
+  /*member: Interface.extendedAbstractImplementedDeclaredConcreteMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedDeclaredConcreteMethod() {}
+
+  /*member: Interface.extendedConcreteImplementedDeclaredAbstractMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedDeclaredAbstractMethod() {}
+
+  /*member: Interface.extendedAbstractImplementedDeclaredAbstractMethod#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedDeclaredAbstractMethod() {}
+}
+
+/*class: Class:
+ abstractMembers=[
+  Class.extendedAbstractDeclaredAbstractMethod,
+  Class.extendedAbstractImplementedDeclaredAbstractMethod,
+  Class.implementedDeclaredAbstractMethod],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class Class extends Super implements Interface {
+  /*member: Class.extendedConcreteDeclaredConcreteMethod#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.extendedConcreteDeclaredConcreteMethod],
+   isSourceDeclaration
+  */
+  void extendedConcreteDeclaredConcreteMethod() {}
+
+  /*member: Class.extendedAbstractDeclaredConcreteMethod#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.extendedAbstractDeclaredConcreteMethod],
+   isSourceDeclaration
+  */
+  void extendedAbstractDeclaredConcreteMethod() {}
+
+  /*member: Class.extendedConcreteDeclaredAbstractMethod#cls:
+   classBuilder=Class,
+   inherited-implements=[Class.extendedConcreteDeclaredAbstractMethod],
+   isSynthesized,
+   member=Super.extendedConcreteDeclaredAbstractMethod
+  */
+  /*member: Class.extendedConcreteDeclaredAbstractMethod#int:
+   classBuilder=Class,
+   declarations=[
+    Class.extendedConcreteDeclaredAbstractMethod,
+    Super.extendedConcreteDeclaredAbstractMethod],
+   declared-overrides=[Super.extendedConcreteDeclaredAbstractMethod],
+   isSynthesized
+  */
+  void extendedConcreteDeclaredAbstractMethod();
+
+  /*member: Class.extendedAbstractDeclaredAbstractMethod#int:
+   classBuilder=Class,
+   declarations=[
+    Class.extendedAbstractDeclaredAbstractMethod,
+    Super.extendedAbstractDeclaredAbstractMethod],
+   declared-overrides=[Super.extendedAbstractDeclaredAbstractMethod],
+   isSynthesized
+  */
+  void extendedAbstractDeclaredAbstractMethod();
+
+  /*member: Class.implementedDeclaredConcreteMethod#cls:
+   classBuilder=Class,
+   declared-overrides=[Interface.implementedDeclaredConcreteMethod],
+   isSourceDeclaration
+  */
+  void implementedDeclaredConcreteMethod() {}
+
+  /*member: Class.implementedDeclaredAbstractMethod#int:
+   classBuilder=Class,
+   declarations=[
+    Class.implementedDeclaredAbstractMethod,
+    Interface.implementedDeclaredAbstractMethod],
+   declared-overrides=[Interface.implementedDeclaredAbstractMethod],
+   isSynthesized
+  */
+  void implementedDeclaredAbstractMethod();
+
+  /*member: Class.extendedConcreteImplementedDeclaredConcreteMethod#cls:
+   classBuilder=Class,
+   declared-overrides=[
+    Interface.extendedConcreteImplementedDeclaredConcreteMethod,
+    Super.extendedConcreteImplementedDeclaredConcreteMethod],
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+
+  /*member: Class.extendedAbstractImplementedDeclaredConcreteMethod#cls:
+   classBuilder=Class,
+   declared-overrides=[
+    Interface.extendedAbstractImplementedDeclaredConcreteMethod,
+    Super.extendedAbstractImplementedDeclaredConcreteMethod],
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedDeclaredConcreteMethod() {}
+
+  /*member: Class.extendedConcreteImplementedDeclaredAbstractMethod#cls:
+   classBuilder=Class,
+   inherited-implements=[Class.extendedConcreteImplementedDeclaredAbstractMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedDeclaredAbstractMethod
+  */
+  /*member: Class.extendedConcreteImplementedDeclaredAbstractMethod#int:
+   classBuilder=Class,
+   declarations=[
+    Class.extendedConcreteImplementedDeclaredAbstractMethod,
+    Interface.extendedConcreteImplementedDeclaredAbstractMethod,
+    Super.extendedConcreteImplementedDeclaredAbstractMethod],
+   declared-overrides=[
+    Interface.extendedConcreteImplementedDeclaredAbstractMethod,
+    Super.extendedConcreteImplementedDeclaredAbstractMethod],
+   isSynthesized
+  */
+  void extendedConcreteImplementedDeclaredAbstractMethod();
+
+  /*member: Class.extendedAbstractImplementedDeclaredAbstractMethod#int:
+   classBuilder=Class,
+   declarations=[
+    Class.extendedAbstractImplementedDeclaredAbstractMethod,
+    Interface.extendedAbstractImplementedDeclaredAbstractMethod,
+    Super.extendedAbstractImplementedDeclaredAbstractMethod],
+   declared-overrides=[
+    Interface.extendedAbstractImplementedDeclaredAbstractMethod,
+    Super.extendedAbstractImplementedDeclaredAbstractMethod],
+   isSynthesized
+  */
+  void extendedAbstractImplementedDeclaredAbstractMethod();
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/extend_multiple_field.dart b/pkg/front_end/test/class_hierarchy/data/extend_multiple_field.dart
new file mode 100644
index 0000000..ab7a907
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/extend_multiple_field.dart
@@ -0,0 +1,535 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int extendedConcreteField = 0;
+
+  /*member: Super.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractField;
+
+  /*member: Super.extendedConcreteImplementedField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteImplementedField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int extendedConcreteImplementedField = 0;
+
+  /*member: Super.extendedAbstractImplementedField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractImplementedField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractImplementedField;
+
+  /*member: Super.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteImplementedMultipleField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int extendedConcreteImplementedMultipleField = 0;
+
+  /*member: Super.extendedAbstractImplementedMultipleField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractImplementedMultipleField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractImplementedMultipleField;
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.extendedConcreteImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedConcreteImplementedField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int extendedConcreteImplementedField = 0;
+
+  /*member: Interface1.extendedAbstractImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedAbstractImplementedField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int extendedAbstractImplementedField = 0;
+
+  /*member: Interface1.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedConcreteImplementedMultipleField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int extendedConcreteImplementedMultipleField = 0;
+
+  /*member: Interface1.extendedAbstractImplementedMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedAbstractImplementedMultipleField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int extendedAbstractImplementedMultipleField = 0;
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Interface2.extendedConcreteImplementedMultipleField=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int extendedConcreteImplementedMultipleField = 0;
+
+  /*member: Interface2.extendedAbstractImplementedMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Interface2.extendedAbstractImplementedMultipleField=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int extendedAbstractImplementedMultipleField = 0;
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.extendedConcreteField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedField#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedField,
+    Super.extendedConcreteImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedField=#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedField=,
+    Super.extendedConcreteImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleField,
+    Interface2.extendedConcreteImplementedMultipleField,
+    Super.extendedConcreteImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMultipleField=#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMultipleField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleField=,
+    Interface2.extendedConcreteImplementedMultipleField=,
+    Super.extendedConcreteImplementedMultipleField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+
+  /*member: AbstractClass.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.extendedAbstractField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedField,
+    Super.extendedAbstractImplementedField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedField
+  */
+  /*member: AbstractClass.extendedAbstractImplementedField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedField=,
+    Super.extendedAbstractImplementedField=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedField=
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleField,
+    Interface2.extendedAbstractImplementedMultipleField,
+    Super.extendedAbstractImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleField
+  */
+  /*member: AbstractClass.extendedAbstractImplementedMultipleField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleField=,
+    Interface2.extendedAbstractImplementedMultipleField=,
+    Super.extendedAbstractImplementedMultipleField=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleField=
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractImplementedField,
+  AbstractClass.extendedAbstractImplementedField=,
+  AbstractClass.extendedAbstractImplementedMultipleField,
+  AbstractClass.extendedAbstractImplementedMultipleField=,
+  Super.extendedAbstractField,
+  Super.extendedAbstractField=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object,
+  Super]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSub.extendedConcreteField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedField#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedField,
+    Super.extendedConcreteImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedField=#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedField=,
+    Super.extendedConcreteImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleField,
+    Interface2.extendedConcreteImplementedMultipleField,
+    Super.extendedConcreteImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleField=#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedMultipleField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleField=,
+    Interface2.extendedConcreteImplementedMultipleField=,
+    Super.extendedConcreteImplementedMultipleField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+
+  /*member: ConcreteSub.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSub.extendedAbstractField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedField,
+    Super.extendedAbstractImplementedField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedField
+  */
+  /*member: ConcreteSub.extendedAbstractImplementedField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedField=,
+    Super.extendedAbstractImplementedField=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedField=
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleField,
+    Interface2.extendedAbstractImplementedMultipleField,
+    Super.extendedAbstractImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleField
+  */
+  /*member: ConcreteSub.extendedAbstractImplementedMultipleField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleField=,
+    Interface2.extendedAbstractImplementedMultipleField=,
+    Super.extendedAbstractImplementedMultipleField=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleField=
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Interface1.extendedAbstractImplementedField,
+  Interface1.extendedAbstractImplementedField=,
+  Interface1.extendedAbstractImplementedMultipleField,
+  Interface1.extendedAbstractImplementedMultipleField=,
+  Interface2.extendedAbstractImplementedMultipleField,
+  Interface2.extendedAbstractImplementedMultipleField=,
+  Super.extendedAbstractField,
+  Super.extendedAbstractField=,
+  Super.extendedAbstractImplementedField,
+  Super.extendedAbstractImplementedField=,
+  Super.extendedAbstractImplementedMultipleField,
+  Super.extendedAbstractImplementedMultipleField=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {
+  /*member: ConcreteClass.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.extendedConcreteField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedField#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedField,
+    Super.extendedConcreteImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedField=#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedField=,
+    Super.extendedConcreteImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleField,
+    Interface2.extendedConcreteImplementedMultipleField,
+    Super.extendedConcreteImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleField=#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedMultipleField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleField=,
+    Interface2.extendedConcreteImplementedMultipleField=,
+    Super.extendedConcreteImplementedMultipleField=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+
+  /*member: ConcreteClass.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.extendedAbstractField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedField,
+    Super.extendedAbstractImplementedField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedField
+  */
+  /*member: ConcreteClass.extendedAbstractImplementedField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedField=,
+    Super.extendedAbstractImplementedField=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedField=
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedMultipleField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleField,
+    Interface2.extendedAbstractImplementedMultipleField,
+    Super.extendedAbstractImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleField
+  */
+  /*member: ConcreteClass.extendedAbstractImplementedMultipleField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleField=,
+    Interface2.extendedAbstractImplementedMultipleField=,
+    Super.extendedAbstractImplementedMultipleField=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleField=
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/extend_multiple_final_field.dart b/pkg/front_end/test/class_hierarchy/data/extend_multiple_final_field.dart
new file mode 100644
index 0000000..72bcf32
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/extend_multiple_final_field.dart
@@ -0,0 +1,311 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final int extendedConcreteField = 0;
+
+  /*member: Super.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractField;
+
+  /*member: Super.extendedConcreteImplementedField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final int extendedConcreteImplementedField = 0;
+
+  /*member: Super.extendedAbstractImplementedField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractImplementedField;
+
+  /*member: Super.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final int extendedConcreteImplementedMultipleField = 0;
+
+  /*member: Super.extendedAbstractImplementedMultipleField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractImplementedMultipleField;
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.extendedConcreteImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final int extendedConcreteImplementedField = 0;
+
+  /*member: Interface1.extendedAbstractImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final int extendedAbstractImplementedField = 0;
+
+  /*member: Interface1.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final int extendedConcreteImplementedMultipleField = 0;
+
+  /*member: Interface1.extendedAbstractImplementedMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final int extendedAbstractImplementedMultipleField = 0;
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  final int extendedConcreteImplementedMultipleField = 0;
+
+  /*member: Interface2.extendedAbstractImplementedMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  final int extendedAbstractImplementedMultipleField = 0;
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedField#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedField,
+    Super.extendedConcreteImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleField,
+    Interface2.extendedConcreteImplementedMultipleField,
+    Super.extendedConcreteImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleField,
+    Interface2.extendedAbstractImplementedMultipleField,
+    Super.extendedAbstractImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleField
+  */
+
+  /*member: AbstractClass.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedField,
+    Super.extendedAbstractImplementedField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedField
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractImplementedField,
+  AbstractClass.extendedAbstractImplementedMultipleField,
+  Super.extendedAbstractField],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object,
+  Super]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedField#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedField,
+    Super.extendedConcreteImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedField
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleField#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleField,
+    Interface2.extendedConcreteImplementedMultipleField,
+    Super.extendedConcreteImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleField
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleField,
+    Interface2.extendedAbstractImplementedMultipleField,
+    Super.extendedAbstractImplementedMultipleField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleField
+  */
+
+  /*member: ConcreteSub.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSub.extendedAbstractImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedField,
+    Super.extendedAbstractImplementedField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedField
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Interface1.extendedAbstractImplementedField,
+  Interface1.extendedAbstractImplementedMultipleField,
+  Interface2.extendedAbstractImplementedMultipleField,
+  Super.extendedAbstractField,
+  Super.extendedAbstractImplementedField,
+  Super.extendedAbstractImplementedMultipleField],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+/*member: ConcreteClass.extendedConcreteField#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: ConcreteClass.extendedConcreteImplementedField#cls:
+ classBuilder=ConcreteClass,
+ inherited-implements=[ConcreteClass.extendedConcreteImplementedField],
+ isSynthesized,
+ member=Super.extendedConcreteImplementedField
+*/
+/*member: ConcreteClass.extendedConcreteImplementedMultipleField#cls:
+ classBuilder=ConcreteClass,
+ inherited-implements=[ConcreteClass.extendedConcreteImplementedMultipleField],
+ isSynthesized,
+ member=Super.extendedConcreteImplementedMultipleField
+*/
+/*member: ConcreteClass.extendedConcreteImplementedField#int:
+ classBuilder=ConcreteClass,
+ declarations=[
+  Interface1.extendedConcreteImplementedField,
+  Super.extendedConcreteImplementedField],
+ isSynthesized,
+ member=Super.extendedConcreteImplementedField
+*/
+/*member: ConcreteClass.extendedConcreteImplementedMultipleField#int:
+ classBuilder=ConcreteClass,
+ declarations=[
+  Interface1.extendedConcreteImplementedMultipleField,
+  Interface2.extendedConcreteImplementedMultipleField,
+  Super.extendedConcreteImplementedMultipleField],
+ isSynthesized,
+ member=Super.extendedConcreteImplementedMultipleField
+*/
+/*member: ConcreteClass.extendedAbstractImplementedMultipleField#int:
+ classBuilder=ConcreteClass,
+ declarations=[
+  Interface1.extendedAbstractImplementedMultipleField,
+  Interface2.extendedAbstractImplementedMultipleField,
+  Super.extendedAbstractImplementedMultipleField],
+ isSynthesized,
+ member=Super.extendedAbstractImplementedMultipleField
+*/
+/*member: ConcreteClass.extendedAbstractField#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: ConcreteClass.extendedAbstractImplementedField#int:
+ classBuilder=ConcreteClass,
+ declarations=[
+  Interface1.extendedAbstractImplementedField,
+  Super.extendedAbstractImplementedField],
+ isSynthesized,
+ member=Super.extendedAbstractImplementedField
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/extend_multiple_getter.dart b/pkg/front_end/test/class_hierarchy/data/extend_multiple_getter.dart
new file mode 100644
index 0000000..ba561c9
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/extend_multiple_getter.dart
@@ -0,0 +1,318 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedConcreteGetter => 0;
+
+  /*member: Super.extendedAbstractGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedAbstractGetter;
+
+  /*member: Super.extendedConcreteImplementedGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedConcreteImplementedGetter => 0;
+
+  /*member: Super.extendedAbstractImplementedGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedAbstractImplementedGetter;
+
+  /*member: Super.extendedConcreteImplementedMultipleGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedConcreteImplementedMultipleGetter => 0;
+
+  /*member: Super.extendedAbstractImplementedMultipleGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedAbstractImplementedMultipleGetter;
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.extendedConcreteImplementedGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int get extendedConcreteImplementedGetter => 0;
+
+  /*member: Interface1.extendedAbstractImplementedGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int get extendedAbstractImplementedGetter => 0;
+
+  /*member: Interface1.extendedConcreteImplementedMultipleGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int get extendedConcreteImplementedMultipleGetter => 0;
+
+  /*member: Interface1.extendedAbstractImplementedMultipleGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int get extendedAbstractImplementedMultipleGetter => 0;
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.extendedConcreteImplementedMultipleGetter#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int get extendedConcreteImplementedMultipleGetter => 0;
+
+  /*member: Interface2.extendedAbstractImplementedMultipleGetter#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int get extendedAbstractImplementedMultipleGetter => 0;
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedGetter#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedGetter
+  */
+  /*member: AbstractClass.extendedConcreteImplementedGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedGetter,
+    Super.extendedConcreteImplementedGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedGetter
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedMultipleGetter#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleGetter
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMultipleGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleGetter,
+    Interface2.extendedConcreteImplementedMultipleGetter,
+    Super.extendedConcreteImplementedMultipleGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleGetter
+  */
+
+  /*member: AbstractClass.extendedAbstractGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedGetter,
+    Super.extendedAbstractImplementedGetter],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedGetter
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedMultipleGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleGetter,
+    Interface2.extendedAbstractImplementedMultipleGetter,
+    Super.extendedAbstractImplementedMultipleGetter],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleGetter
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractImplementedGetter,
+  AbstractClass.extendedAbstractImplementedMultipleGetter,
+  Super.extendedAbstractGetter],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object,
+  Super]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedGetter#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedGetter
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedGetter,
+    Super.extendedConcreteImplementedGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedGetter
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleGetter#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedMultipleGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleGetter
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleGetter,
+    Interface2.extendedConcreteImplementedMultipleGetter,
+    Super.extendedConcreteImplementedMultipleGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleGetter
+  */
+
+  /*member: ConcreteSub.extendedAbstractGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedGetter,
+    Super.extendedAbstractImplementedGetter],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedGetter
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedMultipleGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleGetter,
+    Interface2.extendedAbstractImplementedMultipleGetter,
+    Super.extendedAbstractImplementedMultipleGetter],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleGetter
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Interface1.extendedAbstractImplementedGetter,
+  Interface1.extendedAbstractImplementedMultipleGetter,
+  Interface2.extendedAbstractImplementedMultipleGetter,
+  Super.extendedAbstractGetter,
+  Super.extendedAbstractImplementedGetter,
+  Super.extendedAbstractImplementedMultipleGetter],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {
+  /*member: ConcreteClass.extendedConcreteGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedGetter#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedGetter
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedGetter,
+    Super.extendedConcreteImplementedGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedGetter
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleGetter#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedMultipleGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleGetter
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleGetter,
+    Interface2.extendedConcreteImplementedMultipleGetter,
+    Super.extendedConcreteImplementedMultipleGetter],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleGetter
+  */
+
+  /*member: ConcreteClass.extendedAbstractGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedGetter,
+    Super.extendedAbstractImplementedGetter],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedGetter
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedMultipleGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleGetter,
+    Interface2.extendedAbstractImplementedMultipleGetter,
+    Super.extendedAbstractImplementedMultipleGetter],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleGetter
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/extend_multiple_method.dart b/pkg/front_end/test/class_hierarchy/data/extend_multiple_method.dart
new file mode 100644
index 0000000..c0b274a
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/extend_multiple_method.dart
@@ -0,0 +1,314 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteMethod() {}
+
+  /*member: Super.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractMethod();
+
+  /*member: Super.extendedConcreteImplementedMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedMethod() {}
+
+  /*member: Super.extendedAbstractImplementedMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedMethod();
+
+  /*member: Super.extendedConcreteImplementedMultipleMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedMultipleMethod() {}
+
+  /*member: Super.extendedAbstractImplementedMultipleMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedMultipleMethod();
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.extendedConcreteImplementedMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedMethod() {}
+
+  /*member: Interface1.extendedAbstractImplementedMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedMethod() {}
+
+  /*member: Interface1.extendedConcreteImplementedMultipleMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedMultipleMethod() {}
+
+  /*member: Interface1.extendedAbstractImplementedMultipleMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedMultipleMethod() {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.extendedConcreteImplementedMultipleMethod#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedMultipleMethod() {}
+  /*member: Interface2.extendedAbstractImplementedMultipleMethod#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedMultipleMethod() {}
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Super,
+  Object]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedMethod#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMethod,
+    Super.extendedConcreteImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedMultipleMethod#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleMethod
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleMethod,
+    Interface2.extendedConcreteImplementedMultipleMethod,
+    Super.extendedConcreteImplementedMultipleMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleMethod
+  */
+
+  /*member: AbstractClass.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMethod,
+    Super.extendedAbstractImplementedMethod],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMethod
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleMethod,
+    Interface2.extendedAbstractImplementedMultipleMethod,
+    Super.extendedAbstractImplementedMultipleMethod],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleMethod
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractImplementedMethod,
+  AbstractClass.extendedAbstractImplementedMultipleMethod,
+  Super.extendedAbstractMethod],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object,
+  Super]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedMethod#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMethod,
+    Super.extendedConcreteImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleMethod#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedMultipleMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleMethod
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleMethod,
+    Interface2.extendedConcreteImplementedMultipleMethod,
+    Super.extendedConcreteImplementedMultipleMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleMethod
+  */
+
+  /*member: ConcreteSub.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMethod,
+    Super.extendedAbstractImplementedMethod],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMethod
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleMethod,
+    Interface2.extendedAbstractImplementedMultipleMethod,
+    Super.extendedAbstractImplementedMultipleMethod],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleMethod
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Interface1.extendedAbstractImplementedMethod,
+  Interface1.extendedAbstractImplementedMultipleMethod,
+  Interface2.extendedAbstractImplementedMultipleMethod,
+  Super.extendedAbstractImplementedMethod,
+  Super.extendedAbstractImplementedMultipleMethod,
+  Super.extendedAbstractMethod],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {
+  /*member: ConcreteClass.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedMethod#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMethod,
+    Super.extendedConcreteImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleMethod#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedMultipleMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleMethod
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleMethod,
+    Interface2.extendedConcreteImplementedMultipleMethod,
+    Super.extendedConcreteImplementedMultipleMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleMethod
+  */
+
+  /*member: ConcreteClass.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMethod,
+    Super.extendedAbstractImplementedMethod],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMethod
+  */
+  /*member: ConcreteClass.extendedAbstractImplementedMultipleMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleMethod,
+    Interface2.extendedAbstractImplementedMultipleMethod,
+    Super.extendedAbstractImplementedMultipleMethod],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleMethod
+  */
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/extend_multiple_setter.dart b/pkg/front_end/test/class_hierarchy/data/extend_multiple_setter.dart
new file mode 100644
index 0000000..fbfc164
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/extend_multiple_setter.dart
@@ -0,0 +1,318 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteSetter(int value) {}
+
+  /*member: Super.extendedAbstractSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractSetter(int value);
+
+  /*member: Super.extendedConcreteImplementedSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteImplementedSetter(int value) {}
+
+  /*member: Super.extendedAbstractImplementedSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractImplementedSetter(int value);
+
+  /*member: Super.extendedConcreteImplementedMultipleSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+
+  /*member: Super.extendedAbstractImplementedMultipleSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractImplementedMultipleSetter(int value);
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.extendedConcreteImplementedSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedConcreteImplementedSetter(int value) {}
+
+  /*member: Interface1.extendedAbstractImplementedSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedAbstractImplementedSetter(int value) {}
+
+  /*member: Interface1.extendedConcreteImplementedMultipleSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+
+  /*member: Interface1.extendedAbstractImplementedMultipleSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedAbstractImplementedMultipleSetter(int value) {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.extendedConcreteImplementedMultipleSetter=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+
+  /*member: Interface2.extendedAbstractImplementedMultipleSetter=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set extendedAbstractImplementedMultipleSetter(int value) {}
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedSetter=#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedSetter=
+  */
+  /*member: AbstractClass.extendedConcreteImplementedSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedSetter=,
+    Super.extendedConcreteImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedSetter=
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedMultipleSetter=#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleSetter=
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMultipleSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleSetter=,
+    Interface2.extendedConcreteImplementedMultipleSetter=,
+    Super.extendedConcreteImplementedMultipleSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleSetter=
+  */
+
+  /*member: AbstractClass.extendedAbstractSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedSetter=,
+    Super.extendedAbstractImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedSetter=
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedMultipleSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleSetter=,
+    Interface2.extendedAbstractImplementedMultipleSetter=,
+    Super.extendedAbstractImplementedMultipleSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleSetter=
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractImplementedMultipleSetter=,
+  AbstractClass.extendedAbstractImplementedSetter=,
+  Super.extendedAbstractSetter=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object,
+  Super]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedSetter=#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedSetter=
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedSetter=,
+    Super.extendedConcreteImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedSetter=
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleSetter=#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedMultipleSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleSetter=
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMultipleSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleSetter=,
+    Interface2.extendedConcreteImplementedMultipleSetter=,
+    Super.extendedConcreteImplementedMultipleSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleSetter=
+  */
+
+  /*member: ConcreteSub.extendedAbstractSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedSetter=,
+    Super.extendedAbstractImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedSetter=
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedMultipleSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleSetter=,
+    Interface2.extendedAbstractImplementedMultipleSetter=,
+    Super.extendedAbstractImplementedMultipleSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleSetter=
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Interface1.extendedAbstractImplementedMultipleSetter=,
+  Interface1.extendedAbstractImplementedSetter=,
+  Interface2.extendedAbstractImplementedMultipleSetter=,
+  Super.extendedAbstractImplementedMultipleSetter=,
+  Super.extendedAbstractImplementedSetter=,
+  Super.extendedAbstractSetter=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {
+  /*member: ConcreteClass.extendedConcreteSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedSetter=#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedSetter=
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedSetter=,
+    Super.extendedConcreteImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedSetter=
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleSetter=#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedMultipleSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleSetter=
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedMultipleSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMultipleSetter=,
+    Interface2.extendedConcreteImplementedMultipleSetter=,
+    Super.extendedConcreteImplementedMultipleSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMultipleSetter=
+  */
+
+  /*member: ConcreteClass.extendedAbstractSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedSetter=,
+    Super.extendedAbstractImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedSetter=
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedMultipleSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMultipleSetter=,
+    Interface2.extendedAbstractImplementedMultipleSetter=,
+    Super.extendedAbstractImplementedMultipleSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedMultipleSetter=
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_field.dart b/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_field.dart
new file mode 100644
index 0000000..d9a3756
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_field.dart
@@ -0,0 +1,675 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteCovariantField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteCovariantField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  covariant int extendedConcreteCovariantField = 0;
+
+  /*member: Super.extendedAbstractCovariantField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractCovariantField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract covariant int extendedAbstractCovariantField;
+
+  /*member: Super.extendedConcreteCovariantImplementedField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteCovariantImplementedField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  covariant int extendedConcreteCovariantImplementedField = 0;
+
+  /*member: Super.extendedAbstractCovariantImplementedField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractCovariantImplementedField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract covariant int extendedAbstractCovariantImplementedField;
+
+  /*member: Super.extendedConcreteImplementedCovariantField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteImplementedCovariantField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int extendedConcreteImplementedCovariantField = 0;
+
+  /*member: Super.extendedAbstractImplementedCovariantField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractImplementedCovariantField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractImplementedCovariantField;
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.extendedConcreteCovariantImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedConcreteCovariantImplementedField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int extendedConcreteCovariantImplementedField = 0;
+
+  /*member: Interface1.extendedAbstractCovariantImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedAbstractCovariantImplementedField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int extendedAbstractCovariantImplementedField = 0;
+
+  /*member: Interface1.extendedConcreteImplementedCovariantField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedConcreteImplementedCovariantField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  covariant int extendedConcreteImplementedCovariantField = 0;
+
+  /*member: Interface1.extendedAbstractImplementedCovariantField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedAbstractImplementedCovariantField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  covariant int extendedAbstractImplementedCovariantField = 0;
+
+  /*member: Interface1.implementsMultipleCovariantField1#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.implementsMultipleCovariantField1=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  covariant int implementsMultipleCovariantField1 = 0;
+
+  /*member: Interface1.implementsMultipleCovariantField2#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.implementsMultipleCovariantField2=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int implementsMultipleCovariantField2 = 0;
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.implementsMultipleCovariantField1#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Interface2.implementsMultipleCovariantField1=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int implementsMultipleCovariantField1 = 0;
+
+  /*member: Interface2.implementsMultipleCovariantField2#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Interface2.implementsMultipleCovariantField2=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  covariant int implementsMultipleCovariantField2 = 0;
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteCovariantField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.extendedConcreteCovariantField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedConcreteCovariantImplementedField#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: AbstractClass.extendedConcreteCovariantImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedField,
+    Super.extendedConcreteCovariantImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: AbstractClass.extendedConcreteCovariantImplementedField=#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: AbstractClass.extendedConcreteCovariantImplementedField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedField=,
+    Super.extendedConcreteCovariantImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedCovariantField#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedCovariantField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedCovariantField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantField,
+    Super.extendedConcreteImplementedCovariantField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedCovariantField
+  */
+  /*member: AbstractClass.extendedConcreteImplementedCovariantField=#cls:
+   classBuilder=AbstractClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantField,
+   type=int
+  */
+  /*member: AbstractClass.extendedConcreteImplementedCovariantField=#int:
+   classBuilder=AbstractClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantField=,
+    Super.extendedConcreteImplementedCovariantField=],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantField,
+   type=int
+  */
+
+  /*member: AbstractClass.extendedAbstractCovariantField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.extendedAbstractCovariantField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractCovariantImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedField,
+    Super.extendedAbstractCovariantImplementedField],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedField
+  */
+  /*member: AbstractClass.extendedAbstractCovariantImplementedField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedField=,
+    Super.extendedAbstractCovariantImplementedField=],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedField=
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedCovariantField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantField,
+    Super.extendedAbstractImplementedCovariantField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedCovariantField
+  */
+  /*member: AbstractClass.extendedAbstractImplementedCovariantField=#int:
+   abstractForwardingStub,
+   classBuilder=AbstractClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantField=,
+    Super.extendedAbstractImplementedCovariantField=],
+   isSynthesized,
+   type=int
+  */
+
+  /*member: AbstractClass.implementsMultipleCovariantField1#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField1,
+    Interface2.implementsMultipleCovariantField1],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField1
+  */
+  /*member: AbstractClass.implementsMultipleCovariantField1=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField1=,
+    Interface2.implementsMultipleCovariantField1=],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField1
+  */
+
+  /*member: AbstractClass.implementsMultipleCovariantField2#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField2,
+    Interface2.implementsMultipleCovariantField2],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField2
+  */
+  /*member: AbstractClass.implementsMultipleCovariantField2=#int:
+   abstractForwardingStub,
+   classBuilder=AbstractClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.implementsMultipleCovariantField2=,
+    Interface2.implementsMultipleCovariantField2=],
+   isSynthesized,
+   type=int
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractCovariantImplementedField,
+  AbstractClass.extendedAbstractCovariantImplementedField=,
+  AbstractClass.extendedAbstractImplementedCovariantField,
+  AbstractClass.extendedAbstractImplementedCovariantField=,
+  AbstractClass.implementsMultipleCovariantField1,
+  AbstractClass.implementsMultipleCovariantField1=,
+  AbstractClass.implementsMultipleCovariantField2,
+  AbstractClass.implementsMultipleCovariantField2=,
+  Super.extendedAbstractCovariantField,
+  Super.extendedAbstractCovariantField=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object,
+  Super]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteCovariantField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSub.extendedConcreteCovariantField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedConcreteCovariantImplementedField#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteCovariantImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: ConcreteSub.extendedConcreteCovariantImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedField,
+    Super.extendedConcreteCovariantImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: ConcreteSub.extendedConcreteCovariantImplementedField=#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteCovariantImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: ConcreteSub.extendedConcreteCovariantImplementedField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedField=,
+    Super.extendedConcreteCovariantImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedCovariantField#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedCovariantField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedCovariantField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedCovariantField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantField,
+    Super.extendedConcreteImplementedCovariantField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedCovariantField
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedCovariantField=#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedCovariantField=],
+   isSynthesized,
+   member=AbstractClass.extendedConcreteImplementedCovariantField=
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedCovariantField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantField=,
+    Super.extendedConcreteImplementedCovariantField=],
+   isSynthesized,
+   member=AbstractClass.extendedConcreteImplementedCovariantField=
+  */
+
+  /*member: ConcreteSub.extendedAbstractCovariantField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSub.extendedAbstractCovariantField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedAbstractCovariantImplementedField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedField,
+    Super.extendedAbstractCovariantImplementedField],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedField
+  */
+  /*member: ConcreteSub.extendedAbstractCovariantImplementedField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedField=,
+    Super.extendedAbstractCovariantImplementedField=],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedField=
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedCovariantField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantField,
+    Super.extendedAbstractImplementedCovariantField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedCovariantField
+  */
+  /*member: ConcreteSub.extendedAbstractImplementedCovariantField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantField=,
+    Super.extendedAbstractImplementedCovariantField=],
+   isSynthesized,
+   member=AbstractClass.extendedAbstractImplementedCovariantField=
+  */
+
+  /*member: ConcreteSub.implementsMultipleCovariantField1#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField1,
+    Interface2.implementsMultipleCovariantField1],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField1
+  */
+  /*member: ConcreteSub.implementsMultipleCovariantField1=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField1=,
+    Interface2.implementsMultipleCovariantField1=],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField1
+  */
+
+  /*member: ConcreteSub.implementsMultipleCovariantField2#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField2,
+    Interface2.implementsMultipleCovariantField2],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField2
+  */
+  /*member: ConcreteSub.implementsMultipleCovariantField2=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField2=,
+    Interface2.implementsMultipleCovariantField2=],
+   isSynthesized,
+   member=AbstractClass.implementsMultipleCovariantField2=
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Interface1.extendedAbstractCovariantImplementedField,
+  Interface1.extendedAbstractCovariantImplementedField=,
+  Interface1.extendedAbstractImplementedCovariantField,
+  Interface1.extendedAbstractImplementedCovariantField=,
+  Interface1.implementsMultipleCovariantField1,
+  Interface1.implementsMultipleCovariantField1=,
+  Interface1.implementsMultipleCovariantField2,
+  Interface1.implementsMultipleCovariantField2=,
+  Interface2.implementsMultipleCovariantField1,
+  Interface2.implementsMultipleCovariantField1=,
+  Interface2.implementsMultipleCovariantField2,
+  Interface2.implementsMultipleCovariantField2=,
+  Super.extendedAbstractCovariantField,
+  Super.extendedAbstractCovariantField=,
+  Super.extendedAbstractCovariantImplementedField,
+  Super.extendedAbstractCovariantImplementedField=,
+  Super.extendedAbstractImplementedCovariantField,
+  Super.extendedAbstractImplementedCovariantField=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {
+  /*member: ConcreteClass.extendedConcreteCovariantField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.extendedConcreteCovariantField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedConcreteCovariantImplementedField#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteCovariantImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: ConcreteClass.extendedConcreteCovariantImplementedField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedField,
+    Super.extendedConcreteCovariantImplementedField],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: ConcreteClass.extendedConcreteCovariantImplementedField=#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteCovariantImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+  /*member: ConcreteClass.extendedConcreteCovariantImplementedField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedField=,
+    Super.extendedConcreteCovariantImplementedField=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedField
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedCovariantField#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedCovariantField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedCovariantField
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedCovariantField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantField,
+    Super.extendedConcreteImplementedCovariantField],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedCovariantField
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedCovariantField=#cls:
+   classBuilder=ConcreteClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedCovariantField=],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantField,
+   type=int
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedCovariantField=#int:
+   classBuilder=ConcreteClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantField=,
+    Super.extendedConcreteImplementedCovariantField=],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantField,
+   type=int
+  */
+
+  /*member: ConcreteClass.extendedAbstractCovariantField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.extendedAbstractCovariantField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractCovariantImplementedField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedField,
+    Super.extendedAbstractCovariantImplementedField],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedField
+  */
+  /*member: ConcreteClass.extendedAbstractCovariantImplementedField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedField=,
+    Super.extendedAbstractCovariantImplementedField=],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedField=
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedCovariantField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantField,
+    Super.extendedAbstractImplementedCovariantField],
+   isSynthesized,
+   member=Super.extendedAbstractImplementedCovariantField
+  */
+  /*member: ConcreteClass.extendedAbstractImplementedCovariantField=#int:
+   abstractForwardingStub,
+   classBuilder=ConcreteClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantField=,
+    Super.extendedAbstractImplementedCovariantField=],
+   isSynthesized,
+   type=int
+  */
+
+  /*member: ConcreteClass.implementsMultipleCovariantField1#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField1,
+    Interface2.implementsMultipleCovariantField1],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField1
+  */
+  /*member: ConcreteClass.implementsMultipleCovariantField1=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField1=,
+    Interface2.implementsMultipleCovariantField1=],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField1
+  */
+
+  /*member: ConcreteClass.implementsMultipleCovariantField2#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantField2,
+    Interface2.implementsMultipleCovariantField2],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantField2
+  */
+  /*member: ConcreteClass.implementsMultipleCovariantField2=#int:
+   abstractForwardingStub,
+   classBuilder=ConcreteClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.implementsMultipleCovariantField2=,
+    Interface2.implementsMultipleCovariantField2=],
+   isSynthesized,
+   type=int
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_method.dart b/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_method.dart
new file mode 100644
index 0000000..b2174b7
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_method.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.
+
+/*class: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteCovariantMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteCovariantMethod(covariant int i) {}
+
+  /*member: Super.extendedAbstractCovariantMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractCovariantMethod(covariant int i);
+
+  /*member: Super.extendedConcreteCovariantImplementedMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteCovariantImplementedMethod(covariant int i) {}
+
+  /*member: Super.extendedAbstractCovariantImplementedMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractCovariantImplementedMethod(covariant int i);
+
+  /*member: Super.extendedConcreteImplementedCovariantMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedCovariantMethod(int i) {}
+
+  /*member: Super.extendedAbstractImplementedCovariantMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedCovariantMethod(int i);
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.extendedConcreteCovariantImplementedMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedConcreteCovariantImplementedMethod(int i) {}
+
+  /*member: Interface1.extendedAbstractCovariantImplementedMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedAbstractCovariantImplementedMethod(int i) {}
+
+  /*member: Interface1.extendedConcreteImplementedCovariantMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedCovariantMethod(covariant int i) {}
+
+  /*member: Interface1.extendedAbstractImplementedCovariantMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedCovariantMethod(covariant int i) {}
+
+  /*member: Interface1.implementsMultipleCovariantMethod1#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  void implementsMultipleCovariantMethod1(covariant int i) {}
+  /*member: Interface1.implementsMultipleCovariantMethod2#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void implementsMultipleCovariantMethod2(int i) {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.implementsMultipleCovariantMethod1#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+
+  void implementsMultipleCovariantMethod1(int i) {}
+  /*member: Interface2.implementsMultipleCovariantMethod2#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void implementsMultipleCovariantMethod2(covariant int i) {}
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Super,
+  Object]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteCovariantMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractCovariantMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedConcreteCovariantImplementedMethod#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedMethod
+  */
+  /*member: AbstractClass.extendedConcreteCovariantImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedMethod,
+    Super.extendedConcreteCovariantImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedMethod
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedCovariantMethod#int:
+   abstractForwardingStub,
+   classBuilder=AbstractClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantMethod,
+    Super.extendedAbstractImplementedCovariantMethod],
+   isSynthesized,
+   type=void Function(int)
+  */
+  /*member: AbstractClass.extendedAbstractCovariantImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedMethod,
+    Super.extendedAbstractCovariantImplementedMethod],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedMethod
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedCovariantMethod#cls:
+   classBuilder=AbstractClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantMethod,
+   type=void Function(int)
+  */
+  /*member: AbstractClass.extendedConcreteImplementedCovariantMethod#int:
+   classBuilder=AbstractClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantMethod,
+    Super.extendedConcreteImplementedCovariantMethod],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantMethod,
+   type=void Function(int)
+  */
+
+  /*member: AbstractClass.implementsMultipleCovariantMethod1#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantMethod1,
+    Interface2.implementsMultipleCovariantMethod1],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantMethod1
+  */
+
+  /*member: AbstractClass.implementsMultipleCovariantMethod2#int:
+   abstractForwardingStub,
+   classBuilder=AbstractClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.implementsMultipleCovariantMethod2,
+    Interface2.implementsMultipleCovariantMethod2],
+   isSynthesized,
+   type=void Function(int)
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractCovariantImplementedMethod,
+  AbstractClass.extendedAbstractImplementedCovariantMethod,
+  AbstractClass.implementsMultipleCovariantMethod1,
+  AbstractClass.implementsMultipleCovariantMethod2,
+  Super.extendedAbstractCovariantMethod],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object,
+  Super]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteCovariantMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedAbstractCovariantMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedConcreteCovariantImplementedMethod#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteCovariantImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedMethod
+  */
+  /*member: ConcreteSub.extendedConcreteCovariantImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedMethod,
+    Super.extendedConcreteCovariantImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedMethod
+  */
+
+  /*member: ConcreteSub.extendedAbstractCovariantImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedMethod,
+    Super.extendedAbstractCovariantImplementedMethod],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedMethod
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedCovariantMethod#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedCovariantMethod],
+   isSynthesized,
+   member=AbstractClass.extendedConcreteImplementedCovariantMethod
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedCovariantMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantMethod,
+    Super.extendedConcreteImplementedCovariantMethod],
+   isSynthesized,
+   member=AbstractClass.extendedConcreteImplementedCovariantMethod
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedCovariantMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantMethod,
+    Super.extendedAbstractImplementedCovariantMethod],
+   isSynthesized,
+   member=AbstractClass.extendedAbstractImplementedCovariantMethod
+  */
+
+  /*member: ConcreteSub.implementsMultipleCovariantMethod1#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantMethod1,
+    Interface2.implementsMultipleCovariantMethod1],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantMethod1
+  */
+
+  /*member: ConcreteSub.implementsMultipleCovariantMethod2#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantMethod2,
+    Interface2.implementsMultipleCovariantMethod2],
+   isSynthesized,
+   member=AbstractClass.implementsMultipleCovariantMethod2
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Interface1.extendedAbstractCovariantImplementedMethod,
+  Interface1.extendedAbstractImplementedCovariantMethod,
+  Interface1.implementsMultipleCovariantMethod1,
+  Interface1.implementsMultipleCovariantMethod2,
+  Interface2.implementsMultipleCovariantMethod1,
+  Interface2.implementsMultipleCovariantMethod2,
+  Super.extendedAbstractCovariantImplementedMethod,
+  Super.extendedAbstractCovariantMethod,
+  Super.extendedAbstractImplementedCovariantMethod],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {
+  /*member: ConcreteClass.extendedConcreteCovariantMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractCovariantMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedConcreteCovariantImplementedMethod#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteCovariantImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedMethod
+  */
+  /*member: ConcreteClass.extendedConcreteCovariantImplementedMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedMethod,
+    Super.extendedConcreteCovariantImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedMethod
+  */
+
+  /*member: ConcreteClass.extendedAbstractCovariantImplementedMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedMethod,
+    Super.extendedAbstractCovariantImplementedMethod],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedMethod
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedCovariantMethod#cls:
+   classBuilder=ConcreteClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedCovariantMethod],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantMethod,
+   type=void Function(int)
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedCovariantMethod#int:
+   classBuilder=ConcreteClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantMethod,
+    Super.extendedConcreteImplementedCovariantMethod],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantMethod,
+   type=void Function(int)
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedCovariantMethod#int:
+   abstractForwardingStub,
+   classBuilder=ConcreteClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantMethod,
+    Super.extendedAbstractImplementedCovariantMethod],
+   isSynthesized,
+   type=void Function(int)
+  */
+
+  /*member: ConcreteClass.implementsMultipleCovariantMethod1#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantMethod1,
+    Interface2.implementsMultipleCovariantMethod1],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantMethod1
+  */
+
+  /*member: ConcreteClass.implementsMultipleCovariantMethod2#int:
+   abstractForwardingStub,
+   classBuilder=ConcreteClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.implementsMultipleCovariantMethod2,
+    Interface2.implementsMultipleCovariantMethod2],
+   isSynthesized,
+   type=void Function(int)
+  */
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_setter.dart b/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_setter.dart
new file mode 100644
index 0000000..82c0ead
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/forwarding_stubs_setter.dart
@@ -0,0 +1,403 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteCovariantSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteCovariantSetter(covariant int i) {}
+
+  /*member: Super.extendedAbstractCovariantSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractCovariantSetter(covariant int i);
+
+  /*member: Super.extendedConcreteCovariantImplementedSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteCovariantImplementedSetter(covariant int i) {}
+
+  /*member: Super.extendedAbstractCovariantImplementedSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractCovariantImplementedSetter(covariant int i);
+
+  /*member: Super.extendedConcreteImplementedCovariantSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteImplementedCovariantSetter(int i) {}
+
+  /*member: Super.extendedAbstractImplementedCovariantSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractImplementedCovariantSetter(int i);
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.extendedConcreteCovariantImplementedSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedConcreteCovariantImplementedSetter(int i) {}
+
+  /*member: Interface1.extendedAbstractCovariantImplementedSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedAbstractCovariantImplementedSetter(int i) {}
+
+  /*member: Interface1.extendedConcreteImplementedCovariantSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedConcreteImplementedCovariantSetter(covariant int i) {}
+
+  /*member: Interface1.extendedAbstractImplementedCovariantSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedAbstractImplementedCovariantSetter(covariant int i) {}
+
+  /*member: Interface1.implementsMultipleCovariantSetter1=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set implementsMultipleCovariantSetter1(covariant int i) {}
+
+  /*member: Interface1.implementsMultipleCovariantSetter2=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set implementsMultipleCovariantSetter2(int i) {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.implementsMultipleCovariantSetter1=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set implementsMultipleCovariantSetter1(int i) {}
+
+  /*member: Interface2.implementsMultipleCovariantSetter2=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set implementsMultipleCovariantSetter2(covariant int i) {}
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteCovariantSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedConcreteCovariantImplementedSetter=#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedSetter=
+  */
+  /*member: AbstractClass.extendedConcreteCovariantImplementedSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedSetter=,
+    Super.extendedConcreteCovariantImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedSetter=
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedCovariantSetter=#cls:
+   classBuilder=AbstractClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantSetter=,
+   type=int
+  */
+  /*member: AbstractClass.extendedConcreteImplementedCovariantSetter=#int:
+   classBuilder=AbstractClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantSetter=,
+    Super.extendedConcreteImplementedCovariantSetter=],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantSetter=,
+   type=int
+  */
+
+  /*member: AbstractClass.extendedAbstractCovariantSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: AbstractClass.extendedAbstractCovariantImplementedSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedSetter=,
+    Super.extendedAbstractCovariantImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedSetter=
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedCovariantSetter=#int:
+   abstractForwardingStub,
+   classBuilder=AbstractClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantSetter=,
+    Super.extendedAbstractImplementedCovariantSetter=],
+   isSynthesized,
+   type=int
+  */
+
+  /*member: AbstractClass.implementsMultipleCovariantSetter1=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantSetter1=,
+    Interface2.implementsMultipleCovariantSetter1=],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantSetter1=
+  */
+
+  /*member: AbstractClass.implementsMultipleCovariantSetter2=#int:
+   abstractForwardingStub,
+   classBuilder=AbstractClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.implementsMultipleCovariantSetter2=,
+    Interface2.implementsMultipleCovariantSetter2=],
+   isSynthesized,
+   type=int
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractCovariantImplementedSetter=,
+  AbstractClass.extendedAbstractImplementedCovariantSetter=,
+  AbstractClass.implementsMultipleCovariantSetter1=,
+  AbstractClass.implementsMultipleCovariantSetter2=,
+  Super.extendedAbstractCovariantSetter=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object,
+  Super]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteCovariantSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedConcreteCovariantImplementedSetter=#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteCovariantImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedSetter=
+  */
+  /*member: ConcreteSub.extendedConcreteCovariantImplementedSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedSetter=,
+    Super.extendedConcreteCovariantImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedSetter=
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedCovariantSetter=#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedCovariantSetter=],
+   isSynthesized,
+   member=AbstractClass.extendedConcreteImplementedCovariantSetter=
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedCovariantSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantSetter=,
+    Super.extendedConcreteImplementedCovariantSetter=],
+   isSynthesized,
+   member=AbstractClass.extendedConcreteImplementedCovariantSetter=
+  */
+
+  /*member: ConcreteSub.extendedAbstractCovariantSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.extendedAbstractCovariantImplementedSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedSetter=,
+    Super.extendedAbstractCovariantImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedSetter=
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedCovariantSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantSetter=,
+    Super.extendedAbstractImplementedCovariantSetter=],
+   isSynthesized,
+   member=AbstractClass.extendedAbstractImplementedCovariantSetter=
+  */
+
+  /*member: ConcreteSub.implementsMultipleCovariantSetter1=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantSetter1=,
+    Interface2.implementsMultipleCovariantSetter1=],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantSetter1=
+  */
+
+  /*member: ConcreteSub.implementsMultipleCovariantSetter2=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantSetter2=,
+    Interface2.implementsMultipleCovariantSetter2=],
+   isSynthesized,
+   member=AbstractClass.implementsMultipleCovariantSetter2=
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Interface1.extendedAbstractCovariantImplementedSetter=,
+  Interface1.extendedAbstractImplementedCovariantSetter=,
+  Interface1.implementsMultipleCovariantSetter1=,
+  Interface1.implementsMultipleCovariantSetter2=,
+  Interface2.implementsMultipleCovariantSetter1=,
+  Interface2.implementsMultipleCovariantSetter2=,
+  Super.extendedAbstractCovariantImplementedSetter=,
+  Super.extendedAbstractCovariantSetter=,
+  Super.extendedAbstractImplementedCovariantSetter=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {
+  /*member: ConcreteClass.extendedConcreteCovariantSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedConcreteCovariantImplementedSetter=#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteCovariantImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedSetter=
+  */
+  /*member: ConcreteClass.extendedConcreteCovariantImplementedSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedConcreteCovariantImplementedSetter=,
+    Super.extendedConcreteCovariantImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteCovariantImplementedSetter=
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedCovariantSetter=#cls:
+   classBuilder=ConcreteClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedCovariantSetter=],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantSetter=,
+   type=int
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedCovariantSetter=#int:
+   classBuilder=ConcreteClass,
+   concreteForwardingStub,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedConcreteImplementedCovariantSetter=,
+    Super.extendedConcreteImplementedCovariantSetter=],
+   isSynthesized,
+   stubTarget=Super.extendedConcreteImplementedCovariantSetter=,
+   type=int
+  */
+
+  /*member: ConcreteClass.extendedAbstractCovariantSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteClass.extendedAbstractCovariantImplementedSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.extendedAbstractCovariantImplementedSetter=,
+    Super.extendedAbstractCovariantImplementedSetter=],
+   isSynthesized,
+   member=Super.extendedAbstractCovariantImplementedSetter=
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedCovariantSetter=#int:
+   abstractForwardingStub,
+   classBuilder=ConcreteClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.extendedAbstractImplementedCovariantSetter=,
+    Super.extendedAbstractImplementedCovariantSetter=],
+   isSynthesized,
+   type=int
+  */
+
+  /*member: ConcreteClass.implementsMultipleCovariantSetter1=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementsMultipleCovariantSetter1=,
+    Interface2.implementsMultipleCovariantSetter1=],
+   isSynthesized,
+   member=Interface1.implementsMultipleCovariantSetter1=
+  */
+
+  /*member: ConcreteClass.implementsMultipleCovariantSetter2=#int:
+   abstractForwardingStub,
+   classBuilder=ConcreteClass,
+   covariance=Covariance(0:Covariant),
+   declarations=[
+    Interface1.implementsMultipleCovariantSetter2=,
+    Interface2.implementsMultipleCovariantSetter2=],
+   isSynthesized,
+   type=int
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/getter_setter.dart b/pkg/front_end/test/class_hierarchy/data/getter_setter.dart
new file mode 100644
index 0000000..7823072
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/getter_setter.dart
@@ -0,0 +1,1184 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedGetterDeclaredField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  String get extendedGetterDeclaredField => '';
+
+  /*member: Super.extendedGetterMixedInField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  String get extendedGetterMixedInField => '';
+
+  /*member: Super.extendedGetterImplementedField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  String get extendedGetterImplementedField => '';
+
+  /*member: Super.extendedGetterDeclaredSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  String get extendedGetterDeclaredSetter => '';
+
+  /*member: Super.extendedGetterMixedInSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  String get extendedGetterMixedInSetter => '';
+
+  /*member: Super.extendedGetterImplementedSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  String get extendedGetterImplementedSetter => '';
+
+  /*member: Super.extendedFieldDeclaredSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final String extendedFieldDeclaredSetter = '';
+
+  /*member: Super.extendedFieldMixedInSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final String extendedFieldMixedInSetter = '';
+
+  /*member: Super.extendedFieldImplementedSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final String extendedFieldImplementedSetter = '';
+
+  /*member: Super.extendedSetterDeclaredField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedSetterDeclaredField(int value) {}
+
+  /*member: Super.extendedSetterMixedInField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedSetterMixedInField(int value) {}
+
+  /*member: Super.extendedSetterImplementedField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedSetterImplementedField(int value) {}
+
+  /*member: Super.extendedSetterDeclaredGetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedSetterDeclaredGetter(int value) {}
+
+  /*member: Super.extendedSetterMixedInGetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedSetterMixedInGetter(int value) {}
+
+  /*member: Super.extendedSetterImplementedGetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedSetterImplementedGetter(int value) {}
+}
+
+/*class: Mixin:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Mixin {
+  /*member: Mixin.extendedGetterMixedInField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  /*member: Mixin.extendedGetterMixedInField=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int extendedGetterMixedInField = 0;
+
+  /*member: Mixin.extendedGetterMixedInSetter=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set extendedGetterMixedInSetter(int value) {}
+
+  /*member: Mixin.extendedFieldMixedInSetter=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set extendedFieldMixedInSetter(int value) {}
+
+  /*member: Mixin.extendedSetterMixedInField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  final String extendedSetterMixedInField = '';
+
+  /*member: Mixin.extendedSetterMixedInGetter#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  String get extendedSetterMixedInGetter => '';
+
+  /*member: Mixin.mixedInGetterDeclaredField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  String get mixedInGetterDeclaredField => '';
+
+  /*member: Mixin.mixedInGetterImplementedField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  String get mixedInGetterImplementedField => '';
+
+  /*member: Mixin.mixedInGetterDeclaredSetter#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  String get mixedInGetterDeclaredSetter => '';
+
+  /*member: Mixin.mixedInGetterImplementedSetter#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  String get mixedInGetterImplementedSetter => '';
+
+  /*member: Mixin.mixedInFieldDeclaredSetter#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  final String mixedInFieldDeclaredSetter = '';
+
+  /*member: Mixin.mixedInFieldImplementedSetter#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  final String mixedInFieldImplementedSetter = '';
+
+  /*member: Mixin.mixedInSetterDeclaredField=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set mixedInSetterDeclaredField(int value) {}
+
+  /*member: Mixin.mixedInSetterImplementedField=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set mixedInSetterImplementedField(int value) {}
+
+  /*member: Mixin.mixedInSetterDeclaredGetter=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set mixedInSetterDeclaredGetter(int value) {}
+
+  /*member: Mixin.mixedInSetterImplementedGetter=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set mixedInSetterImplementedGetter(int value) {}
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface1 {
+  /*member: Interface1.extendedGetterImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.extendedGetterImplementedField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int extendedGetterImplementedField = 0;
+
+  /*member: Interface1.extendedGetterImplementedSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedGetterImplementedSetter(int value) {}
+
+  /*member: Interface1.extendedFieldImplementedSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set extendedFieldImplementedSetter(int value) {}
+
+  /*member: Interface1.extendedSetterImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final String extendedSetterImplementedField = '';
+
+  /*member: Interface1.extendedSetterImplementedGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  String get extendedSetterImplementedGetter => '';
+
+  /*member: Interface1.mixedInGetterImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.mixedInGetterImplementedField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int mixedInGetterImplementedField = 0;
+
+  /*member: Interface1.mixedInGetterImplementedSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set mixedInGetterImplementedSetter(int value) {}
+
+  /*member: Interface1.mixedInFieldImplementedSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set mixedInFieldImplementedSetter(int value) {}
+
+  /*member: Interface1.mixedInSetterImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final String mixedInSetterImplementedField = '';
+
+  /*member: Interface1.mixedInSetterImplementedGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  String get mixedInSetterImplementedGetter => '';
+
+  /*member: Interface1.implementedGetterDeclaredField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  String get implementedGetterDeclaredField => '';
+
+  /*member: Interface1.implementedGetterImplementedField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  String get implementedGetterImplementedField => '';
+
+  /*member: Interface1.implementedGetterDeclaredSetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  String get implementedGetterDeclaredSetter => '';
+
+  /*member: Interface1.implementedGetterImplementedSetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  String get implementedGetterImplementedSetter => '';
+
+  /*member: Interface1.implementedFieldDeclaredSetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final String implementedFieldDeclaredSetter = '';
+
+  /*member: Interface1.implementedFieldImplementedSetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final String implementedFieldImplementedSetter = '';
+
+  /*member: Interface1.implementedSetterDeclaredField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set implementedSetterDeclaredField(int value) {}
+
+  /*member: Interface1.implementedSetterImplementedField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set implementedSetterImplementedField(int value) {}
+
+  /*member: Interface1.implementedSetterDeclaredGetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set implementedSetterDeclaredGetter(int value) {}
+
+  /*member: Interface1.implementedSetterImplementedGetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set implementedSetterImplementedGetter(int value) {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface2 {
+  /*member: Interface2.implementedGetterImplementedField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Interface2.implementedGetterImplementedField=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int implementedGetterImplementedField = 0;
+
+  /*member: Interface2.implementedGetterImplementedSetter=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set implementedGetterImplementedSetter(int value) {}
+
+  /*member: Interface2.implementedFieldImplementedSetter=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set implementedFieldImplementedSetter(int value) {}
+
+  /*member: Interface2.implementedSetterImplementedField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  final String implementedSetterImplementedField = '';
+
+  /*member: Interface2.implementedSetterImplementedGetter#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  String get implementedSetterImplementedGetter => '';
+}
+
+/*class: _Class&Super&Mixin:
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: _Class&Super&Mixin.extendedGetterMixedInField#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedGetterMixedInField
+*/
+/*member: _Class&Super&Mixin.extendedGetterMixedInField#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedGetterMixedInField,
+  Super.extendedGetterMixedInField],
+ isSynthesized,
+ stubTarget=Mixin.extendedGetterMixedInField
+*/
+/*member: _Class&Super&Mixin.extendedGetterMixedInField=#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedGetterMixedInField
+*/
+/*member: _Class&Super&Mixin.extendedGetterMixedInField=#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.extendedGetterMixedInField=],
+ isSynthesized,
+ stubTarget=Mixin.extendedGetterMixedInField
+*/
+
+/*member: _Class&Super&Mixin.extendedSetterMixedInField#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedSetterMixedInField
+*/
+/*member: _Class&Super&Mixin.extendedSetterMixedInField#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.extendedSetterMixedInField],
+ isSynthesized,
+ stubTarget=Mixin.extendedSetterMixedInField
+*/
+/*member: _Class&Super&Mixin.extendedSetterMixedInField=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedSetterMixedInGetter#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedSetterMixedInGetter
+*/
+/*member: _Class&Super&Mixin.extendedSetterMixedInGetter#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.extendedSetterMixedInGetter],
+ isSynthesized,
+ stubTarget=Mixin.extendedSetterMixedInGetter
+*/
+/*member: _Class&Super&Mixin.extendedSetterMixedInGetter=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.mixedInGetterDeclaredField#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInGetterDeclaredField
+*/
+/*member: _Class&Super&Mixin.mixedInGetterDeclaredField#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInGetterDeclaredField],
+ isSynthesized,
+ stubTarget=Mixin.mixedInGetterDeclaredField
+*/
+
+/*member: _Class&Super&Mixin.mixedInGetterImplementedField#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInGetterImplementedField
+*/
+/*member: _Class&Super&Mixin.mixedInGetterImplementedField#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInGetterImplementedField],
+ isSynthesized,
+ stubTarget=Mixin.mixedInGetterImplementedField
+*/
+
+/*member: _Class&Super&Mixin.mixedInGetterDeclaredSetter#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInGetterDeclaredSetter
+*/
+/*member: _Class&Super&Mixin.mixedInGetterDeclaredSetter#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInGetterDeclaredSetter],
+ isSynthesized,
+ stubTarget=Mixin.mixedInGetterDeclaredSetter
+*/
+
+/*member: _Class&Super&Mixin.mixedInGetterImplementedSetter#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInGetterImplementedSetter
+*/
+/*member: _Class&Super&Mixin.mixedInGetterImplementedSetter#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInGetterImplementedSetter],
+ isSynthesized,
+ stubTarget=Mixin.mixedInGetterImplementedSetter
+*/
+
+/*member: _Class&Super&Mixin.mixedInFieldDeclaredSetter#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInFieldDeclaredSetter
+*/
+/*member: _Class&Super&Mixin.mixedInFieldDeclaredSetter#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInFieldDeclaredSetter],
+ isSynthesized,
+ stubTarget=Mixin.mixedInFieldDeclaredSetter
+*/
+
+/*member: _Class&Super&Mixin.mixedInFieldImplementedSetter#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInFieldImplementedSetter
+*/
+/*member: _Class&Super&Mixin.mixedInFieldImplementedSetter#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInFieldImplementedSetter],
+ isSynthesized,
+ stubTarget=Mixin.mixedInFieldImplementedSetter
+*/
+
+/*member: _Class&Super&Mixin.extendedGetterMixedInSetter#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: _Class&Super&Mixin.extendedGetterMixedInSetter=#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedGetterMixedInSetter=
+*/
+/*member: _Class&Super&Mixin.extendedGetterMixedInSetter=#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.extendedGetterMixedInSetter=],
+ isSynthesized,
+ stubTarget=Mixin.extendedGetterMixedInSetter=
+*/
+
+/*member: _Class&Super&Mixin.extendedFieldMixedInSetter#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: _Class&Super&Mixin.extendedFieldMixedInSetter=#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedFieldMixedInSetter=
+*/
+/*member: _Class&Super&Mixin.extendedFieldMixedInSetter=#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.extendedFieldMixedInSetter=],
+ isSynthesized,
+ stubTarget=Mixin.extendedFieldMixedInSetter=
+*/
+
+/*member: _Class&Super&Mixin.extendedGetterDeclaredField#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedGetterImplementedField#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedGetterDeclaredSetter#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedGetterImplementedSetter#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedFieldDeclaredSetter#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedFieldImplementedSetter#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.mixedInSetterDeclaredField=#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInSetterDeclaredField=
+*/
+/*member: _Class&Super&Mixin.mixedInSetterDeclaredField=#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInSetterDeclaredField=],
+ isSynthesized,
+ stubTarget=Mixin.mixedInSetterDeclaredField=
+*/
+
+/*member: _Class&Super&Mixin.mixedInSetterImplementedField=#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInSetterImplementedField=
+*/
+/*member: _Class&Super&Mixin.mixedInSetterImplementedField=#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInSetterImplementedField=],
+ isSynthesized,
+ stubTarget=Mixin.mixedInSetterImplementedField=
+*/
+
+/*member: _Class&Super&Mixin.mixedInSetterDeclaredGetter=#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInSetterDeclaredGetter=
+*/
+/*member: _Class&Super&Mixin.mixedInSetterDeclaredGetter=#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInSetterDeclaredGetter=],
+ isSynthesized,
+ stubTarget=Mixin.mixedInSetterDeclaredGetter=
+*/
+
+/*member: _Class&Super&Mixin.mixedInSetterImplementedGetter=#cls:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInSetterImplementedGetter=
+*/
+/*member: _Class&Super&Mixin.mixedInSetterImplementedGetter=#int:
+ classBuilder=_Class&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInSetterImplementedGetter=],
+ isSynthesized,
+ stubTarget=Mixin.mixedInSetterImplementedGetter=
+*/
+
+/*member: _Class&Super&Mixin.extendedSetterDeclaredField=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedSetterImplementedField=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedSetterDeclaredGetter=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _Class&Super&Mixin.extendedSetterImplementedGetter=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*class: Class:
+ interfaces=[
+  Interface1,
+  Interface2,
+  Mixin],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Super,
+  _Class&Super&Mixin]
+*/
+abstract class Class extends Super
+    with Mixin
+    implements Interface1, Interface2 {
+  /*member: Class.extendedGetterMixedInField#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedGetterMixedInField
+  */
+  /*member: Class.extendedGetterMixedInField#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[
+    Mixin.extendedGetterMixedInField,
+    Super.extendedGetterMixedInField],
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedGetterMixedInField
+  */
+  /*member: Class.extendedGetterMixedInField=#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedGetterMixedInField=
+  */
+  /*member: Class.extendedGetterMixedInField=#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.extendedGetterMixedInField=],
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedGetterMixedInField=
+  */
+
+  /*member: Class.extendedSetterMixedInField#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedSetterMixedInField
+  */
+  /*member: Class.extendedSetterMixedInField#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.extendedSetterMixedInField],
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedSetterMixedInField
+  */
+  /*member: Class.extendedSetterMixedInField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: Class.extendedSetterMixedInGetter#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedSetterMixedInGetter
+  */
+  /*member: Class.extendedSetterMixedInGetter#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.extendedSetterMixedInGetter],
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedSetterMixedInGetter
+  */
+  /*member: Class.extendedSetterMixedInGetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: Class.mixedInGetterImplementedField#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInGetterImplementedField
+  */
+  /*member: Class.mixedInGetterImplementedField#int:
+   classBuilder=Class,
+   declarations=[
+    Interface1.mixedInGetterImplementedField,
+    _Class&Super&Mixin.mixedInGetterImplementedField],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInGetterImplementedField
+  */
+  /*member: Class.mixedInGetterImplementedField=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  /*member: Class.mixedInGetterImplementedSetter#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInGetterImplementedSetter
+  */
+  /*member: Class.mixedInGetterImplementedSetter#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.mixedInGetterImplementedSetter],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInGetterImplementedSetter
+  */
+  /*member: Class.mixedInGetterImplementedSetter=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  /*member: Class.mixedInFieldImplementedSetter#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInFieldImplementedSetter
+  */
+  /*member: Class.mixedInFieldImplementedSetter#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.mixedInFieldImplementedSetter],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInFieldImplementedSetter
+  */
+  /*member: Class.mixedInFieldImplementedSetter=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  /*member: Class.extendedGetterMixedInSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Class.extendedGetterMixedInSetter=#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedGetterMixedInSetter=
+  */
+  /*member: Class.extendedGetterMixedInSetter=#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.extendedGetterMixedInSetter=],
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedGetterMixedInSetter=
+  */
+
+  /*member: Class.extendedFieldMixedInSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Class.extendedFieldMixedInSetter=#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedFieldMixedInSetter=
+  */
+  /*member: Class.extendedFieldMixedInSetter=#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.extendedFieldMixedInSetter=],
+   isSynthesized,
+   member=_Class&Super&Mixin.extendedFieldMixedInSetter=
+  */
+
+  /*member: Class.extendedGetterImplementedField#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=Super.extendedGetterImplementedField
+  */
+  /*member: Class.extendedGetterImplementedField#int:
+   classBuilder=Class,
+   declarations=[
+    Interface1.extendedGetterImplementedField,
+    Super.extendedGetterImplementedField],
+   isSynthesized,
+   member=Super.extendedGetterImplementedField
+  */
+  /*member: Class.extendedGetterImplementedField=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  /*member: Class.extendedGetterImplementedSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Class.extendedGetterImplementedSetter=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  /*member: Class.extendedFieldImplementedSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Class.extendedFieldImplementedSetter=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  /*member: Class.mixedInSetterImplementedField#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Class.mixedInSetterImplementedField=#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInSetterImplementedField=
+  */
+  /*member: Class.mixedInSetterImplementedField=#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.mixedInSetterImplementedField=],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInSetterImplementedField=
+  */
+
+  /*member: Class.mixedInSetterImplementedGetter#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Class.mixedInSetterImplementedGetter=#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInSetterImplementedGetter=
+  */
+  /*member: Class.mixedInSetterImplementedGetter=#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.mixedInSetterImplementedGetter=],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInSetterImplementedGetter=
+  */
+
+  /*member: Class.extendedSetterImplementedField#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Class.extendedSetterImplementedField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: Class.extendedSetterImplementedGetter#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Class.extendedSetterImplementedGetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: Class.implementedGetterImplementedField#int:
+   classBuilder=Class,
+   declarations=[
+    Interface1.implementedGetterImplementedField,
+    Interface2.implementedGetterImplementedField],
+   isSynthesized,
+   member=Interface1.implementedGetterImplementedField
+  */
+  /*member: Class.implementedGetterImplementedField=#int:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+
+  /*member: Class.implementedGetterImplementedSetter#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Class.implementedGetterImplementedSetter=#int:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+
+  /*member: Class.implementedFieldImplementedSetter#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Class.implementedFieldImplementedSetter=#int:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+
+  /*member: Class.implementedSetterImplementedField#int:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Class.implementedSetterImplementedField=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  /*member: Class.implementedSetterImplementedGetter#int:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Class.implementedSetterImplementedGetter=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+
+  /*member: Class.extendedGetterDeclaredField#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.extendedGetterDeclaredField],
+   isSourceDeclaration
+  */
+  /*member: Class.extendedGetterDeclaredField=#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.extendedGetterDeclaredField],
+   isSourceDeclaration
+  */
+  int extendedGetterDeclaredField = 0;
+
+  /*member: Class.extendedGetterDeclaredSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Class.extendedGetterDeclaredSetter=#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.extendedGetterDeclaredSetter],
+   isSourceDeclaration
+  */
+  void set extendedGetterDeclaredSetter(int value) {}
+
+  /*member: Class.extendedFieldDeclaredSetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Class.extendedFieldDeclaredSetter=#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.extendedFieldDeclaredSetter],
+   isSourceDeclaration
+  */
+  void set extendedFieldDeclaredSetter(int value) {}
+
+  /*member: Class.extendedSetterDeclaredField#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.extendedSetterDeclaredField=],
+   isSourceDeclaration
+  */
+  /*member: Class.extendedSetterDeclaredField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final String extendedSetterDeclaredField = '';
+
+  /*member: Class.extendedSetterDeclaredGetter#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.extendedSetterDeclaredGetter=],
+   isSourceDeclaration
+  */
+  /*member: Class.extendedSetterDeclaredGetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  String get extendedSetterDeclaredGetter => '';
+
+  /*member: Class.mixedInGetterDeclaredField#cls:
+   classBuilder=Class,
+   declared-overrides=[_Class&Super&Mixin.mixedInGetterDeclaredField],
+   isSourceDeclaration
+  */
+  /*member: Class.mixedInGetterDeclaredField=#cls:
+   classBuilder=Class,
+   declared-overrides=[_Class&Super&Mixin.mixedInGetterDeclaredField],
+   isSourceDeclaration
+  */
+  int mixedInGetterDeclaredField = 0;
+
+  /*member: Class.mixedInGetterDeclaredSetter#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInGetterDeclaredSetter
+  */
+  /*member: Class.mixedInGetterDeclaredSetter#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.mixedInGetterDeclaredSetter],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInGetterDeclaredSetter
+  */
+  /*member: Class.mixedInGetterDeclaredSetter=#cls:
+   classBuilder=Class,
+   declared-overrides=[_Class&Super&Mixin.mixedInGetterDeclaredSetter],
+   isSourceDeclaration
+  */
+  void set mixedInGetterDeclaredSetter(int value) {}
+
+  /*member: Class.mixedInFieldDeclaredSetter#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInFieldDeclaredSetter
+  */
+  /*member: Class.mixedInFieldDeclaredSetter#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.mixedInFieldDeclaredSetter],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInFieldDeclaredSetter
+  */
+  /*member: Class.mixedInFieldDeclaredSetter=#cls:
+   classBuilder=Class,
+   declared-overrides=[_Class&Super&Mixin.mixedInFieldDeclaredSetter],
+   isSourceDeclaration
+  */
+  void set mixedInFieldDeclaredSetter(int value) {}
+
+  /*member: Class.mixedInSetterDeclaredField#cls:
+   classBuilder=Class,
+   declared-overrides=[_Class&Super&Mixin.mixedInSetterDeclaredField=],
+   isSourceDeclaration
+  */
+  /*member: Class.mixedInSetterDeclaredField=#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInSetterDeclaredField=
+  */
+  /*member: Class.mixedInSetterDeclaredField=#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.mixedInSetterDeclaredField=],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInSetterDeclaredField=
+  */
+  final String mixedInSetterDeclaredField = '';
+
+  /*member: Class.mixedInSetterDeclaredGetter#cls:
+   classBuilder=Class,
+   declared-overrides=[_Class&Super&Mixin.mixedInSetterDeclaredGetter=],
+   isSourceDeclaration
+  */
+  /*member: Class.mixedInSetterDeclaredGetter=#cls:
+   classBuilder=Class,
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInSetterDeclaredGetter=
+  */
+  /*member: Class.mixedInSetterDeclaredGetter=#int:
+   classBuilder=_Class&Super&Mixin,
+   declarations=[Mixin.mixedInSetterDeclaredGetter=],
+   isSynthesized,
+   member=_Class&Super&Mixin.mixedInSetterDeclaredGetter=
+  */
+  String get mixedInSetterDeclaredGetter => '';
+
+  /*member: Class.implementedGetterDeclaredField#cls:
+   classBuilder=Class,
+   declared-overrides=[Interface1.implementedGetterDeclaredField],
+   isSourceDeclaration
+  */
+  /*member: Class.implementedGetterDeclaredField=#cls:
+   classBuilder=Class,
+   declared-overrides=[Interface1.implementedGetterDeclaredField],
+   isSourceDeclaration
+  */
+  int implementedGetterDeclaredField = 0;
+
+  /*member: Class.implementedGetterDeclaredSetter#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Class.implementedGetterDeclaredSetter=#cls:
+   classBuilder=Class,
+   declared-overrides=[Interface1.implementedGetterDeclaredSetter],
+   isSourceDeclaration
+  */
+  void set implementedGetterDeclaredSetter(int value) {}
+
+  /*member: Class.implementedFieldDeclaredSetter#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Class.implementedFieldDeclaredSetter=#cls:
+   classBuilder=Class,
+   declared-overrides=[Interface1.implementedFieldDeclaredSetter],
+   isSourceDeclaration
+  */
+  void set implementedFieldDeclaredSetter(int value) {}
+
+  /*member: Class.implementedSetterDeclaredField#cls:
+   classBuilder=Class,
+   declared-overrides=[Interface1.implementedSetterDeclaredField=],
+   isSourceDeclaration
+  */
+  /*member: Class.implementedSetterDeclaredField=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final String implementedSetterDeclaredField = '';
+
+  /*member: Class.implementedSetterDeclaredGetter#cls:
+   classBuilder=Class,
+   declared-overrides=[Interface1.implementedSetterDeclaredGetter=],
+   isSourceDeclaration
+  */
+
+  /*member: Class.implementedSetterDeclaredGetter=#int:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  String get implementedSetterDeclaredGetter => '';
+
+  /*member: Class.declaredGetterDeclaredSetter#cls:
+   classBuilder=Class,
+   isSourceDeclaration
+  */
+  String get declaredGetterDeclaredSetter => '';
+
+  /*member: Class.declaredGetterDeclaredSetter=#cls:
+   classBuilder=Class,
+   isSourceDeclaration
+  */
+  void set declaredGetterDeclaredSetter(int value) {}
+
+  /*member: Class.declaredFieldDeclaredSetter#cls:
+   classBuilder=Class,
+   isSourceDeclaration
+  */
+  final String declaredFieldDeclaredSetter = '';
+
+  /*member: Class.declaredFieldDeclaredSetter=#cls:
+   classBuilder=Class,
+   isSourceDeclaration
+  */
+  void set declaredFieldDeclaredSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/implement_multiple_field.dart b/pkg/front_end/test/class_hierarchy/data/implement_multiple_field.dart
new file mode 100644
index 0000000..b68d55b
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/implement_multiple_field.dart
@@ -0,0 +1,293 @@
+// 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: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.implementMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.implementMultipleField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int implementMultipleField = 0;
+
+  /*member: Interface1.declareConcreteImplementMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.declareConcreteImplementMultipleField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int declareConcreteImplementMultipleField = 0;
+
+  /*member: Interface1.declareAbstractImplementMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  /*member: Interface1.declareAbstractImplementMultipleField=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int declareAbstractImplementMultipleField = 0;
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.implementMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Interface2.implementMultipleField=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int implementMultipleField = 0;
+
+  /*member: Interface2.declareConcreteImplementMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Interface2.declareConcreteImplementMultipleField=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int declareConcreteImplementMultipleField = 0;
+
+  /*member: Interface2.declareAbstractImplementMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  /*member: Interface2.declareAbstractImplementMultipleField=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int declareAbstractImplementMultipleField = 0;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declareAbstractImplementMultipleField,
+  ConcreteClass.declareAbstractImplementMultipleField=,
+  Interface1.implementMultipleField,
+  Interface1.implementMultipleField=,
+  Interface2.implementMultipleField,
+  Interface2.implementMultipleField=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface1, Interface2 {
+  /*member: ConcreteClass.implementMultipleField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementMultipleField,
+    Interface2.implementMultipleField],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+  /*member: ConcreteClass.implementMultipleField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementMultipleField=,
+    Interface2.implementMultipleField=],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+
+  /*member: ConcreteClass.declareConcreteImplementMultipleField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleField,
+    Interface1.declareConcreteImplementMultipleField=,
+    Interface2.declareConcreteImplementMultipleField,
+    Interface2.declareConcreteImplementMultipleField=],
+   isSourceDeclaration
+  */
+  /*member: ConcreteClass.declareConcreteImplementMultipleField=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleField,
+    Interface1.declareConcreteImplementMultipleField=,
+    Interface2.declareConcreteImplementMultipleField,
+    Interface2.declareConcreteImplementMultipleField=],
+   isSourceDeclaration
+  */
+  int declareConcreteImplementMultipleField = 0;
+
+  /*member: ConcreteClass.declareAbstractImplementMultipleField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField=,
+    Interface2.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField=],
+   isSynthesized
+  */
+  /*member: ConcreteClass.declareAbstractImplementMultipleField=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declareAbstractImplementMultipleField=,
+    Interface1.declareAbstractImplementMultipleField=,
+    Interface2.declareAbstractImplementMultipleField=],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField=,
+    Interface2.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField=],
+   isSynthesized
+  */
+  abstract int declareAbstractImplementMultipleField;
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface1, Interface2 {
+  /*member: AbstractClass.implementMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleField,
+    Interface2.implementMultipleField],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+  /*member: AbstractClass.implementMultipleField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleField=,
+    Interface2.implementMultipleField=],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+
+  /*member: AbstractClass.declareConcreteImplementMultipleField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleField,
+    Interface1.declareConcreteImplementMultipleField=,
+    Interface2.declareConcreteImplementMultipleField,
+    Interface2.declareConcreteImplementMultipleField=],
+   isSourceDeclaration
+  */
+  /*member: AbstractClass.declareConcreteImplementMultipleField=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleField,
+    Interface1.declareConcreteImplementMultipleField=,
+    Interface2.declareConcreteImplementMultipleField,
+    Interface2.declareConcreteImplementMultipleField=],
+   isSourceDeclaration
+  */
+  int declareConcreteImplementMultipleField = 0;
+
+  /*member: AbstractClass.declareAbstractImplementMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField=,
+    Interface2.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField=],
+   isSynthesized
+  */
+  /*member: AbstractClass.declareAbstractImplementMultipleField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleField=,
+    Interface1.declareAbstractImplementMultipleField=,
+    Interface2.declareAbstractImplementMultipleField=],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField=,
+    Interface2.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField=],
+   isSynthesized
+  */
+  abstract int declareAbstractImplementMultipleField;
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.declareAbstractImplementMultipleField,
+  AbstractClass.declareAbstractImplementMultipleField=,
+  AbstractClass.implementMultipleField,
+  AbstractClass.implementMultipleField=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.declareConcreteImplementMultipleField#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+  /*member: ConcreteSub.declareConcreteImplementMultipleField=#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.declareAbstractImplementMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField],
+   isSynthesized,
+   member=AbstractClass.declareAbstractImplementMultipleField
+  */
+  /*member: ConcreteSub.declareAbstractImplementMultipleField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleField=,
+    Interface1.declareAbstractImplementMultipleField=,
+    Interface2.declareAbstractImplementMultipleField=],
+   isSynthesized,
+   member=AbstractClass.declareAbstractImplementMultipleField=
+  */
+
+  /*member: ConcreteSub.implementMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleField,
+    Interface2.implementMultipleField],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+  /*member: ConcreteSub.implementMultipleField=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleField=,
+    Interface2.implementMultipleField=],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/implement_multiple_final_field.dart b/pkg/front_end/test/class_hierarchy/data/implement_multiple_final_field.dart
new file mode 100644
index 0000000..c3a5321
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/implement_multiple_final_field.dart
@@ -0,0 +1,175 @@
+// 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: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.implementMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final int implementMultipleField = 0;
+
+  /*member: Interface1.declareConcreteImplementMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final int declareConcreteImplementMultipleField = 0;
+
+  /*member: Interface1.declareAbstractImplementMultipleField#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  final int declareAbstractImplementMultipleField = 0;
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.implementMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  final int implementMultipleField = 0;
+
+  /*member: Interface2.declareConcreteImplementMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  final int declareConcreteImplementMultipleField = 0;
+
+  /*member: Interface2.declareAbstractImplementMultipleField#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  final int declareAbstractImplementMultipleField = 0;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declareAbstractImplementMultipleField,
+  Interface1.implementMultipleField,
+  Interface2.implementMultipleField],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface1, Interface2 {
+  /*member: ConcreteClass.implementMultipleField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementMultipleField,
+    Interface2.implementMultipleField],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+
+  /*member: ConcreteClass.declareConcreteImplementMultipleField#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleField,
+    Interface2.declareConcreteImplementMultipleField],
+   isSourceDeclaration
+  */
+  final int declareConcreteImplementMultipleField = 0;
+
+  /*member: ConcreteClass.declareAbstractImplementMultipleField#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField],
+   isSynthesized
+  */
+  abstract final int declareAbstractImplementMultipleField;
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface1, Interface2 {
+  /*member: AbstractClass.implementMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleField,
+    Interface2.implementMultipleField],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+
+  /*member: AbstractClass.declareConcreteImplementMultipleField#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleField,
+    Interface2.declareConcreteImplementMultipleField],
+   isSourceDeclaration
+  */
+  final int declareConcreteImplementMultipleField = 0;
+
+  /*member: AbstractClass.declareAbstractImplementMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField],
+   isSynthesized
+  */
+  abstract final int declareAbstractImplementMultipleField;
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.declareAbstractImplementMultipleField,
+  AbstractClass.implementMultipleField],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.declareConcreteImplementMultipleField#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.declareAbstractImplementMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleField,
+    Interface1.declareAbstractImplementMultipleField,
+    Interface2.declareAbstractImplementMultipleField],
+   isSynthesized,
+   member=AbstractClass.declareAbstractImplementMultipleField
+  */
+
+  /*member: ConcreteSub.implementMultipleField#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleField,
+    Interface2.implementMultipleField],
+   isSynthesized,
+   member=Interface1.implementMultipleField
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/implement_multiple_getter.dart b/pkg/front_end/test/class_hierarchy/data/implement_multiple_getter.dart
new file mode 100644
index 0000000..2460469
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/implement_multiple_getter.dart
@@ -0,0 +1,175 @@
+// 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: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.implementMultipleGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int get implementMultipleGetter => 0;
+
+  /*member: Interface1.declareConcreteImplementMultipleGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int get declareConcreteImplementMultipleGetter => 0;
+
+  /*member: Interface1.declareAbstractImplementMultipleGetter#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  int get declareAbstractImplementMultipleGetter => 0;
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.implementMultipleGetter#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int get implementMultipleGetter => 0;
+
+  /*member: Interface2.declareConcreteImplementMultipleGetter#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int get declareConcreteImplementMultipleGetter => 0;
+
+  /*member: Interface2.declareAbstractImplementMultipleGetter#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  int get declareAbstractImplementMultipleGetter => 0;
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declareAbstractImplementMultipleGetter,
+  Interface1.implementMultipleGetter,
+  Interface2.implementMultipleGetter],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface1, Interface2 {
+  /*member: ConcreteClass.implementMultipleGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementMultipleGetter,
+    Interface2.implementMultipleGetter],
+   isSynthesized,
+   member=Interface1.implementMultipleGetter
+  */
+
+  /*member: ConcreteClass.declareConcreteImplementMultipleGetter#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleGetter,
+    Interface2.declareConcreteImplementMultipleGetter],
+   isSourceDeclaration
+  */
+  int get declareConcreteImplementMultipleGetter => 0;
+
+  /*member: ConcreteClass.declareAbstractImplementMultipleGetter#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declareAbstractImplementMultipleGetter,
+    Interface1.declareAbstractImplementMultipleGetter,
+    Interface2.declareAbstractImplementMultipleGetter],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleGetter,
+    Interface2.declareAbstractImplementMultipleGetter],
+   isSynthesized
+  */
+  int get declareAbstractImplementMultipleGetter;
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface1, Interface2 {
+  /*member: AbstractClass.implementMultipleGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleGetter,
+    Interface2.implementMultipleGetter],
+   isSynthesized,
+   member=Interface1.implementMultipleGetter
+  */
+
+  /*member: AbstractClass.declareConcreteImplementMultipleGetter#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleGetter,
+    Interface2.declareConcreteImplementMultipleGetter],
+   isSourceDeclaration
+  */
+  int get declareConcreteImplementMultipleGetter => 0;
+
+  /*member: AbstractClass.declareAbstractImplementMultipleGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleGetter,
+    Interface1.declareAbstractImplementMultipleGetter,
+    Interface2.declareAbstractImplementMultipleGetter],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleGetter,
+    Interface2.declareAbstractImplementMultipleGetter],
+   isSynthesized
+  */
+  int get declareAbstractImplementMultipleGetter;
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.declareAbstractImplementMultipleGetter,
+  AbstractClass.implementMultipleGetter],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.declareConcreteImplementMultipleGetter#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.declareAbstractImplementMultipleGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleGetter,
+    Interface1.declareAbstractImplementMultipleGetter,
+    Interface2.declareAbstractImplementMultipleGetter],
+   isSynthesized,
+   member=AbstractClass.declareAbstractImplementMultipleGetter
+  */
+
+  /*member: ConcreteSub.implementMultipleGetter#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleGetter,
+    Interface2.implementMultipleGetter],
+   isSynthesized,
+   member=Interface1.implementMultipleGetter
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/implement_multiple_method.dart b/pkg/front_end/test/class_hierarchy/data/implement_multiple_method.dart
new file mode 100644
index 0000000..99d540c
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/implement_multiple_method.dart
@@ -0,0 +1,171 @@
+// 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: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.implementMultipleMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void implementMultipleMethod() {}
+
+  /*member: Interface1.declareConcreteImplementMultipleMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void declareConcreteImplementMultipleMethod() {}
+
+  /*member: Interface1.declareAbstractImplementMultipleMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void declareAbstractImplementMultipleMethod() {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.implementMultipleMethod#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void implementMultipleMethod() {}
+  /*member: Interface2.declareConcreteImplementMultipleMethod#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void declareConcreteImplementMultipleMethod() {}
+  /*member: Interface2.declareAbstractImplementMultipleMethod#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void declareAbstractImplementMultipleMethod() {}
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declareAbstractImplementMultipleMethod,
+  Interface1.implementMultipleMethod,
+  Interface2.implementMultipleMethod],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface1, Interface2 {
+  /*member: ConcreteClass.implementMultipleMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementMultipleMethod,
+    Interface2.implementMultipleMethod],
+   isSynthesized,
+   member=Interface1.implementMultipleMethod
+  */
+
+  /*member: ConcreteClass.declareConcreteImplementMultipleMethod#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleMethod,
+    Interface2.declareConcreteImplementMultipleMethod],
+   isSourceDeclaration
+  */
+  void declareConcreteImplementMultipleMethod() {}
+
+  /*member: ConcreteClass.declareAbstractImplementMultipleMethod#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declareAbstractImplementMultipleMethod,
+    Interface1.declareAbstractImplementMultipleMethod,
+    Interface2.declareAbstractImplementMultipleMethod],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleMethod,
+    Interface2.declareAbstractImplementMultipleMethod],
+   isSynthesized
+  */
+  void declareAbstractImplementMultipleMethod();
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+abstract class AbstractClass implements Interface1, Interface2 {
+  /*member: AbstractClass.implementMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleMethod,
+    Interface2.implementMultipleMethod],
+   isSynthesized,
+   member=Interface1.implementMultipleMethod
+  */
+
+  /*member: AbstractClass.declareConcreteImplementMultipleMethod#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleMethod,
+    Interface2.declareConcreteImplementMultipleMethod],
+   isSourceDeclaration
+  */
+  void declareConcreteImplementMultipleMethod() {}
+
+  /*member: AbstractClass.declareAbstractImplementMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleMethod,
+    Interface1.declareAbstractImplementMultipleMethod,
+    Interface2.declareAbstractImplementMultipleMethod],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleMethod,
+    Interface2.declareAbstractImplementMultipleMethod],
+   isSynthesized
+  */
+  void declareAbstractImplementMultipleMethod();
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.declareAbstractImplementMultipleMethod,
+  AbstractClass.implementMultipleMethod],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.declareConcreteImplementMultipleMethod#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.declareAbstractImplementMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleMethod,
+    Interface1.declareAbstractImplementMultipleMethod,
+    Interface2.declareAbstractImplementMultipleMethod],
+   isSynthesized,
+   member=AbstractClass.declareAbstractImplementMultipleMethod
+  */
+
+  /*member: ConcreteSub.implementMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleMethod,
+    Interface2.implementMultipleMethod],
+   isSynthesized,
+   member=Interface1.implementMultipleMethod
+  */
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/implement_multiple_setter.dart b/pkg/front_end/test/class_hierarchy/data/implement_multiple_setter.dart
new file mode 100644
index 0000000..1ddc683
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/implement_multiple_setter.dart
@@ -0,0 +1,176 @@
+// 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: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface1 {
+  /*member: Interface1.implementMultipleSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set implementMultipleSetter(int i) {}
+
+  /*member: Interface1.declareConcreteImplementMultipleSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set declareConcreteImplementMultipleSetter(int i) {}
+
+  /*member: Interface1.declareAbstractImplementMultipleSetter=#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void set declareAbstractImplementMultipleSetter(int i) {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface2 {
+  /*member: Interface2.implementMultipleSetter=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set implementMultipleSetter(int i) {}
+
+  /*member: Interface2.declareConcreteImplementMultipleSetter=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set declareConcreteImplementMultipleSetter(int i) {}
+
+  /*member: Interface2.declareAbstractImplementMultipleSetter=#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void set declareAbstractImplementMultipleSetter(int i) {}
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  ConcreteClass.declareAbstractImplementMultipleSetter=,
+  Interface1.implementMultipleSetter=,
+  Interface2.implementMultipleSetter=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class ConcreteClass implements Interface1, Interface2 {
+  /*member: ConcreteClass.implementMultipleSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    Interface1.implementMultipleSetter=,
+    Interface2.implementMultipleSetter=],
+   isSynthesized,
+   member=Interface1.implementMultipleSetter=
+  */
+
+  /*member: ConcreteClass.declareConcreteImplementMultipleSetter=#cls:
+   classBuilder=ConcreteClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleSetter=,
+    Interface2.declareConcreteImplementMultipleSetter=],
+   isSourceDeclaration
+  */
+  void set declareConcreteImplementMultipleSetter(int i) {}
+
+  /*member: ConcreteClass.declareAbstractImplementMultipleSetter=#int:
+   classBuilder=ConcreteClass,
+   declarations=[
+    ConcreteClass.declareAbstractImplementMultipleSetter=,
+    Interface1.declareAbstractImplementMultipleSetter=,
+    Interface2.declareAbstractImplementMultipleSetter=],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleSetter=,
+    Interface2.declareAbstractImplementMultipleSetter=],
+   isSynthesized
+  */
+  void set declareAbstractImplementMultipleSetter(int i);
+}
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  /*member: AbstractClass.implementMultipleSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleSetter=,
+    Interface2.implementMultipleSetter=],
+   isSynthesized,
+   member=Interface1.implementMultipleSetter=
+  */
+
+  /*member: AbstractClass.declareConcreteImplementMultipleSetter=#cls:
+   classBuilder=AbstractClass,
+   declared-overrides=[
+    Interface1.declareConcreteImplementMultipleSetter=,
+    Interface2.declareConcreteImplementMultipleSetter=],
+   isSourceDeclaration
+  */
+  void set declareConcreteImplementMultipleSetter(int i) {}
+
+  /*member: AbstractClass.declareAbstractImplementMultipleSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleSetter=,
+    Interface1.declareAbstractImplementMultipleSetter=,
+    Interface2.declareAbstractImplementMultipleSetter=],
+   declared-overrides=[
+    Interface1.declareAbstractImplementMultipleSetter=,
+    Interface2.declareAbstractImplementMultipleSetter=],
+   isSynthesized
+  */
+  void set declareAbstractImplementMultipleSetter(int i);
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.declareAbstractImplementMultipleSetter=,
+  AbstractClass.implementMultipleSetter=],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  AbstractClass,
+  Object]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.declareConcreteImplementMultipleSetter=#cls:
+   classBuilder=AbstractClass,
+   isSourceDeclaration
+  */
+
+  /*member: ConcreteSub.declareAbstractImplementMultipleSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    AbstractClass.declareAbstractImplementMultipleSetter=,
+    Interface1.declareAbstractImplementMultipleSetter=,
+    Interface2.declareAbstractImplementMultipleSetter=],
+   isSynthesized,
+   member=AbstractClass.declareAbstractImplementMultipleSetter=
+  */
+
+  /*member: ConcreteSub.implementMultipleSetter=#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementMultipleSetter=,
+    Interface2.implementMultipleSetter=],
+   isSynthesized,
+   member=Interface1.implementMultipleSetter=
+  */
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/in_out_in/in.dart b/pkg/front_end/test/class_hierarchy/data/in_out_in/in.dart
new file mode 100644
index 0000000..2c7d774
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/in_out_in/in.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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.method#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int method(int i) => i;
+}
+
+/*class: SuperQ:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class SuperQ {
+  /*member: SuperQ.method#cls:
+   classBuilder=SuperQ,
+   isSourceDeclaration
+  */
+  int? method(int? i) => i;
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/in_out_in/main.dart b/pkg/front_end/test/class_hierarchy/data/in_out_in/main.dart
new file mode 100644
index 0000000..1eb489c
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/in_out_in/main.dart
@@ -0,0 +1,59 @@
+// 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 'in.dart';
+import 'out.dart';
+
+/*class: Class:
+ interfaces=[SuperQ],
+ maxInheritancePath=3,
+ superclasses=[
+  LegacyClass,
+  Object,
+  Super]
+*/
+class Class extends LegacyClass implements SuperQ {
+  /*member: Class.method#cls:
+   classBuilder=Class,
+   inherited-implements=[Class.method],
+   isSynthesized,
+   member=Super.method
+  */
+  /*member: Class.method#int:
+   classBuilder=Class,
+   covariance=Covariance.empty(),
+   declarations=[
+    LegacyClass.method,
+    SuperQ.method],
+   isSynthesized,
+   memberSignature,
+   type=int? Function(int?)
+  */
+}
+
+/*class: ClassQ:
+ interfaces=[Super],
+ maxInheritancePath=3,
+ superclasses=[
+  LegacyClassQ,
+  Object,
+  SuperQ]
+*/
+/*member: ClassQ.method#cls:
+ classBuilder=ClassQ,
+ inherited-implements=[ClassQ.method],
+ isSynthesized,
+ member=SuperQ.method
+*/
+/*member: ClassQ.method#int:
+ classBuilder=ClassQ,
+ covariance=Covariance.empty(),
+ declarations=[
+  LegacyClassQ.method,
+  Super.method],
+ isSynthesized,
+ memberSignature,
+ type=int Function(int)
+*/
+class ClassQ extends LegacyClassQ implements Super {}
diff --git a/pkg/front_end/test/class_hierarchy/data/in_out_in/out.dart b/pkg/front_end/test/class_hierarchy/data/in_out_in/out.dart
new file mode 100644
index 0000000..ddfc71b
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/in_out_in/out.dart
@@ -0,0 +1,51 @@
+// 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 'in.dart';
+
+/*class: LegacyClass:
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+class LegacyClass extends Super {
+  /*member: LegacyClass.method#cls:
+   classBuilder=LegacyClass,
+   isSynthesized,
+   member=Super.method
+  */
+  /*member: LegacyClass.method#int:
+   classBuilder=LegacyClass,
+   covariance=Covariance.empty(),
+   declarations=[Super.method],
+   isSynthesized,
+   memberSignature,
+   type=int* Function(int*)*
+  */
+}
+
+/*class: LegacyClassQ:
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  SuperQ]
+*/
+class LegacyClassQ extends SuperQ {
+  /*member: LegacyClassQ.method#cls:
+   classBuilder=LegacyClassQ,
+   isSynthesized,
+   member=SuperQ.method
+  */
+  /*member: LegacyClassQ.method#int:
+   classBuilder=LegacyClassQ,
+   covariance=Covariance.empty(),
+   declarations=[SuperQ.method],
+   isSynthesized,
+   memberSignature,
+   type=int* Function(int*)*
+  */
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/infer_parameter_opt_out.dart b/pkg/front_end/test/class_hierarchy/data/infer_parameter_opt_out.dart
new file mode 100644
index 0000000..4c1858f
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/infer_parameter_opt_out.dart
@@ -0,0 +1,153 @@
+// 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
+
+/*class: A:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class A {
+  /*member: A.method#cls:
+   classBuilder=A,
+   isSourceDeclaration
+  */
+  dynamic method(dynamic o, {dynamic named}) {}
+}
+
+/*class: B:
+ maxInheritancePath=2,
+ superclasses=[
+  A,
+  Object]
+*/
+abstract class B extends A {
+  /*member: B.method#cls:
+   classBuilder=B,
+   isSynthesized,
+   member=A.method
+  */
+  /*member: B.method#int:
+   classBuilder=B,
+   declarations=[
+    A.method,
+    B.method],
+   declared-overrides=[A.method],
+   isSynthesized
+  */
+  Object method(Object o, {Object named});
+}
+
+/*class: C1:
+ interfaces=[B],
+ maxInheritancePath=3,
+ superclasses=[
+  A,
+  Object]
+*/
+class C1 extends A implements B {
+  /*member: C1.method#cls:
+   classBuilder=C1,
+   declared-overrides=[
+    A.method,
+    B.method],
+   isSourceDeclaration
+  */
+  method(o, {named}) {}
+}
+
+/*class: C2:
+ maxInheritancePath=3,
+ superclasses=[
+  A,
+  B,
+  Object]
+*/
+class C2 extends B implements A {
+  /*member: C2.method#cls:
+   classBuilder=C2,
+   declared-overrides=[
+    A.method,
+    B.method],
+   isSourceDeclaration
+  */
+  method(o, {named}) {}
+}
+
+/*class: C3:
+ interfaces=[
+  A,
+  B],
+ maxInheritancePath=3,
+ superclasses=[Object]
+*/
+class C3 implements A, B {
+  /*member: C3.method#cls:
+   classBuilder=C3,
+   declared-overrides=[
+    A.method,
+    B.method],
+   isSourceDeclaration
+  */
+  method(o, {named}) {}
+}
+
+/*class: C4:
+ interfaces=[
+  A,
+  B],
+ maxInheritancePath=3,
+ superclasses=[Object]
+*/
+class C4 implements B, A {
+  /*member: C4.method#cls:
+   classBuilder=C4,
+   declared-overrides=[
+    A.method,
+    B.method],
+   isSourceDeclaration
+  */
+  method(o, {named}) {}
+}
+
+/*class: D:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class D {
+  /*member: D.==#int:
+   classBuilder=D,
+   declarations=[
+    D.==,
+    Object.==],
+   declared-overrides=[Object.==],
+   isSynthesized
+  */
+  bool operator ==(Object other);
+}
+
+/*class: F:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class F {}
+
+/*class: E:
+ interfaces=[
+  D,
+  F],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class E implements D, F {
+  /*member: E.==#cls:
+   classBuilder=E,
+   declared-overrides=[
+    D.==,
+    F.==,
+    Object.==],
+   isSourceDeclaration
+  */
+  bool operator ==(other) => true;
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/late.dart b/pkg/front_end/test/class_hierarchy/data/late.dart
new file mode 100644
index 0000000..5b0ff6a
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/late.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.
+
+/*class: Interface:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Interface {
+  /*member: Interface.implementedLateFieldDeclaredGetterSetter#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.implementedLateFieldDeclaredGetterSetter=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  late int implementedLateFieldDeclaredGetterSetter;
+}
+
+/*class: Class:
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class Class implements Interface {
+/*member: Class.implementedLateFieldDeclaredGetterSetter#cls:
+ classBuilder=Class,
+ declared-overrides=[
+  Interface.implementedLateFieldDeclaredGetterSetter,
+  Interface.implementedLateFieldDeclaredGetterSetter=],
+ isSourceDeclaration
+*/
+  int get implementedLateFieldDeclaredGetterSetter => 0;
+
+/*member: Class.implementedLateFieldDeclaredGetterSetter=#cls:
+ classBuilder=Class,
+ declared-overrides=[
+  Interface.implementedLateFieldDeclaredGetterSetter,
+  Interface.implementedLateFieldDeclaredGetterSetter=],
+ isSourceDeclaration
+*/
+  void set implementedLateFieldDeclaredGetterSetter(int value) {}
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/marker.options b/pkg/front_end/test/class_hierarchy/data/marker.options
new file mode 100644
index 0000000..8b2da11
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/marker.options
@@ -0,0 +1 @@
+cfe:nnbd=pkg/front_end/test/class_hierarchy/class_hierarchy_test.dart
diff --git a/pkg/front_end/test/class_hierarchy/data/member_signatures/lib.dart b/pkg/front_end/test/class_hierarchy/data/member_signatures/lib.dart
new file mode 100644
index 0000000..af6c533
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/member_signatures/lib.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.
+
+/*class: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Super {
+  /*member: Super.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteMethod(int i) {}
+
+  /*member: Super.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractMethod(int i);
+
+  /*member: Super.extendedConcreteImplementedMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedMethod(int i) {}
+
+  /*member: Super.extendedAbstractImplementedMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedMethod(int i);
+}
+
+/*class: Interface1:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface1 {
+  /*member: Interface1.extendedConcreteImplementedMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedConcreteImplementedMethod(int i) {}
+
+  /*member: Interface1.extendedAbstractImplementedMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void extendedAbstractImplementedMethod(int i) {}
+
+  /*member: Interface1.implementedMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void implementedMethod(int i) {}
+
+  /*member: Interface1.implementedMultipleMethod#cls:
+   classBuilder=Interface1,
+   isSourceDeclaration
+  */
+  void implementedMultipleMethod(int i) {}
+}
+
+/*class: Interface2:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface2 {
+  /*member: Interface2.implementedMultipleMethod#cls:
+   classBuilder=Interface2,
+   isSourceDeclaration
+  */
+  void implementedMultipleMethod(int i) {}
+}
diff --git a/pkg/front_end/test/class_hierarchy/data/member_signatures/main.dart b/pkg/front_end/test/class_hierarchy/data/member_signatures/main.dart
new file mode 100644
index 0000000..a7260ed
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/member_signatures/main.dart
@@ -0,0 +1,364 @@
+// 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 'lib.dart';
+
+/*class: AbstractClass:
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Super,
+  Object]
+*/
+abstract class AbstractClass extends Super implements Interface1, Interface2 {
+  /*member: AbstractClass.extendedConcreteMethod#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteMethod
+  */
+  /*member: AbstractClass.extendedConcreteMethod#int:
+   classBuilder=AbstractClass,
+   covariance=Covariance.empty(),
+   declarations=[Super.extendedConcreteMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: AbstractClass.extendedAbstractMethod#int:
+   classBuilder=AbstractClass,
+   covariance=Covariance.empty(),
+   declarations=[Super.extendedAbstractMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: AbstractClass.extendedConcreteImplementedMethod#cls:
+   classBuilder=AbstractClass,
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+  /*member: AbstractClass.extendedConcreteImplementedMethod#int:
+   classBuilder=AbstractClass,
+   covariance=Covariance.empty(),
+   declarations=[
+    Interface1.extendedConcreteImplementedMethod,
+    Super.extendedConcreteImplementedMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: AbstractClass.extendedAbstractImplementedMethod#int:
+   classBuilder=AbstractClass,
+   covariance=Covariance.empty(),
+   declarations=[
+    Interface1.extendedAbstractImplementedMethod,
+    Super.extendedAbstractImplementedMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: AbstractClass.implementedMethod#int:
+   classBuilder=AbstractClass,
+   covariance=Covariance.empty(),
+   declarations=[Interface1.implementedMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: AbstractClass.implementedMultipleMethod#int:
+   classBuilder=AbstractClass,
+   covariance=Covariance.empty(),
+   declarations=[
+    Interface1.implementedMultipleMethod,
+    Interface2.implementedMultipleMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+}
+
+/*class: ConcreteSub:
+ abstractMembers=[
+  AbstractClass.extendedAbstractImplementedMethod,
+  AbstractClass.extendedAbstractMethod,
+  AbstractClass.implementedMethod,
+  AbstractClass.implementedMultipleMethod],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=3,
+ superclasses=[
+  Super,
+  AbstractClass,
+  Object]
+*/
+class ConcreteSub extends AbstractClass {
+  /*member: ConcreteSub.extendedConcreteMethod#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteMethod],
+   isSynthesized,
+   member=Super.extendedConcreteMethod
+  */
+  /*member: ConcreteSub.extendedConcreteMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[Super.extendedConcreteMethod],
+   isSynthesized,
+   member=AbstractClass.extendedConcreteMethod
+  */
+
+  /*member: ConcreteSub.extendedAbstractMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[Super.extendedAbstractMethod],
+   isSynthesized,
+   member=AbstractClass.extendedAbstractMethod
+  */
+
+  /*member: ConcreteSub.extendedConcreteImplementedMethod#cls:
+   classBuilder=ConcreteSub,
+   inherited-implements=[AbstractClass.extendedConcreteImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+  /*member: ConcreteSub.extendedConcreteImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedConcreteImplementedMethod,
+    Super.extendedConcreteImplementedMethod],
+   isSynthesized,
+   member=AbstractClass.extendedConcreteImplementedMethod
+  */
+
+  /*member: ConcreteSub.extendedAbstractImplementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.extendedAbstractImplementedMethod,
+    Super.extendedAbstractImplementedMethod],
+   isSynthesized,
+   member=AbstractClass.extendedAbstractImplementedMethod
+  */
+
+  /*member: ConcreteSub.implementedMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[Interface1.implementedMethod],
+   isSynthesized,
+   member=AbstractClass.implementedMethod
+  */
+
+  /*member: ConcreteSub.implementedMultipleMethod#int:
+   classBuilder=AbstractClass,
+   declarations=[
+    Interface1.implementedMultipleMethod,
+    Interface2.implementedMultipleMethod],
+   isSynthesized,
+   member=AbstractClass.implementedMultipleMethod
+  */
+}
+
+/*class: ConcreteClass:
+ abstractMembers=[
+  Super.extendedAbstractImplementedMethod,
+  Super.extendedAbstractMethod,
+  Interface1.extendedAbstractImplementedMethod,
+  Interface1.implementedMethod,
+  Interface1.implementedMultipleMethod,
+  Interface2.implementedMultipleMethod],
+ interfaces=[
+  Interface1,
+  Interface2],
+ maxInheritancePath=2,
+ superclasses=[
+  Super,
+  Object]
+*/
+class ConcreteClass extends Super implements Interface1, Interface2 {
+  /*member: ConcreteClass.extendedConcreteMethod#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteMethod],
+   isSynthesized,
+   member=Super.extendedConcreteMethod
+  */
+  /*member: ConcreteClass.extendedConcreteMethod#int:
+   classBuilder=ConcreteClass,
+   covariance=Covariance.empty(),
+   declarations=[Super.extendedConcreteMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: ConcreteClass.extendedAbstractMethod#int:
+   classBuilder=ConcreteClass,
+   covariance=Covariance.empty(),
+   declarations=[Super.extendedAbstractMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: ConcreteClass.extendedConcreteImplementedMethod#cls:
+   classBuilder=ConcreteClass,
+   inherited-implements=[ConcreteClass.extendedConcreteImplementedMethod],
+   isSynthesized,
+   member=Super.extendedConcreteImplementedMethod
+  */
+  /*member: ConcreteClass.extendedConcreteImplementedMethod#int:
+   classBuilder=ConcreteClass,
+   covariance=Covariance.empty(),
+   declarations=[
+    Interface1.extendedConcreteImplementedMethod,
+    Super.extendedConcreteImplementedMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: ConcreteClass.extendedAbstractImplementedMethod#int:
+   classBuilder=ConcreteClass,
+   covariance=Covariance.empty(),
+   declarations=[
+    Interface1.extendedAbstractImplementedMethod,
+    Super.extendedAbstractImplementedMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: ConcreteClass.implementedMethod#int:
+   classBuilder=ConcreteClass,
+   covariance=Covariance.empty(),
+   declarations=[Interface1.implementedMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+
+  /*member: ConcreteClass.implementedMultipleMethod#int:
+   classBuilder=ConcreteClass,
+   covariance=Covariance.empty(),
+   declarations=[
+    Interface1.implementedMultipleMethod,
+    Interface2.implementedMultipleMethod],
+   isSynthesized,
+   memberSignature,
+   type=void Function(int*)*
+  */
+}
+
+/*class: OptOutInterface:
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+/*member: OptOutInterface.extendedConcreteImplementedMethod#cls:
+ classBuilder=OptOutInterface,
+ isSynthesized,
+ member=Super.extendedConcreteImplementedMethod
+*/
+/*member: OptOutInterface.extendedConcreteImplementedMethod#int:
+ classBuilder=OptOutInterface,
+ covariance=Covariance.empty(),
+ declarations=[Super.extendedConcreteImplementedMethod],
+ isSynthesized,
+ memberSignature,
+ type=void Function(int*)*
+*/
+/*member: OptOutInterface.extendedAbstractImplementedMethod#int:
+ classBuilder=OptOutInterface,
+ covariance=Covariance.empty(),
+ declarations=[Super.extendedAbstractImplementedMethod],
+ isSynthesized,
+ memberSignature,
+ type=void Function(int*)*
+*/
+/*member: OptOutInterface.extendedConcreteMethod#cls:
+ classBuilder=OptOutInterface,
+ isSynthesized,
+ member=Super.extendedConcreteMethod
+*/
+/*member: OptOutInterface.extendedConcreteMethod#int:
+ classBuilder=OptOutInterface,
+ covariance=Covariance.empty(),
+ declarations=[Super.extendedConcreteMethod],
+ isSynthesized,
+ memberSignature,
+ type=void Function(int*)*
+*/
+/*member: OptOutInterface.extendedAbstractMethod#int:
+ classBuilder=OptOutInterface,
+ covariance=Covariance.empty(),
+ declarations=[Super.extendedAbstractMethod],
+ isSynthesized,
+ memberSignature,
+ type=void Function(int*)*
+*/
+abstract class OptOutInterface extends Super {}
+
+/*class: ClassImplementsOptOut:
+ interfaces=[OptOutInterface],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Super]
+*/
+/*member: ClassImplementsOptOut.extendedConcreteImplementedMethod#int:
+ classBuilder=ClassImplementsOptOut,
+ covariance=Covariance.empty(),
+ declarations=[
+  OptOutInterface.extendedConcreteImplementedMethod,
+  Super.extendedConcreteImplementedMethod],
+ isSynthesized,
+ memberSignature,
+ type=void Function(int*)*
+*/
+/*member: ClassImplementsOptOut.extendedAbstractImplementedMethod#int:
+ classBuilder=ClassImplementsOptOut,
+ covariance=Covariance.empty(),
+ declarations=[
+  OptOutInterface.extendedAbstractImplementedMethod,
+  Super.extendedAbstractImplementedMethod],
+ isSynthesized,
+ memberSignature,
+ type=void Function(int*)*
+*/
+/*member: ClassImplementsOptOut.extendedConcreteMethod#cls:
+ classBuilder=ClassImplementsOptOut,
+ isSynthesized,
+ member=Super.extendedConcreteMethod
+*/
+/*member: ClassImplementsOptOut.extendedConcreteImplementedMethod#cls:
+ classBuilder=ClassImplementsOptOut,
+ isSynthesized,
+ member=Super.extendedConcreteImplementedMethod
+*/
+/*member: ClassImplementsOptOut.extendedConcreteMethod#int:
+ classBuilder=ClassImplementsOptOut,
+ covariance=Covariance.empty(),
+ declarations=[
+  OptOutInterface.extendedConcreteMethod,
+  Super.extendedConcreteMethod],
+ isSynthesized,
+ memberSignature,
+ type=void Function(int*)*
+*/
+/*member: ClassImplementsOptOut.extendedAbstractMethod#int:
+ classBuilder=ClassImplementsOptOut,
+ covariance=Covariance.empty(),
+ declarations=[
+  OptOutInterface.extendedAbstractMethod,
+  Super.extendedAbstractMethod],
+ isSynthesized,
+ memberSignature,
+ type=void Function(int*)*
+*/
+abstract class ClassImplementsOptOut extends Super implements OptOutInterface {}
diff --git a/pkg/front_end/test/class_hierarchy/data/mix_in_field.dart b/pkg/front_end/test/class_hierarchy/data/mix_in_field.dart
new file mode 100644
index 0000000..01f7b92
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/mix_in_field.dart
@@ -0,0 +1,765 @@
+// 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: Super:
+ abstractMembers=[
+  Super.extendedAbstractField,
+  Super.extendedAbstractField=,
+  Super.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField=,
+  Super.extendedAbstractMixedInConcreteField,
+  Super.extendedAbstractMixedInConcreteField=],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int extendedConcreteField = 0;
+
+  /*member: Super.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractField;
+
+  /*member: Super.extendedConcreteMixedInConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteMixedInConcreteField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int extendedConcreteMixedInConcreteField = 0;
+
+  /*member: Super.extendedAbstractMixedInConcreteField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractMixedInConcreteField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractMixedInConcreteField;
+
+  /*member: Super.extendedConcreteMixedInAbstractField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedConcreteMixedInAbstractField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int extendedConcreteMixedInAbstractField = 0;
+
+  /*member: Super.extendedAbstractMixedInAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: Super.extendedAbstractMixedInAbstractField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractMixedInAbstractField;
+}
+
+/*class: Mixin:
+ abstractMembers=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Mixin.extendedAbstractMixedInAbstractField=,
+  Mixin.extendedConcreteMixedInAbstractField,
+  Mixin.extendedConcreteMixedInAbstractField=,
+  Mixin.mixedInAbstractField,
+  Mixin.mixedInAbstractField=],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Mixin {
+  /*member: Mixin.mixedInConcreteField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  /*member: Mixin.mixedInConcreteField=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int mixedInConcreteField = 0;
+
+  /*member: Mixin.mixedInAbstractField#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  /*member: Mixin.mixedInAbstractField=#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  abstract int mixedInAbstractField;
+
+  /*member: Mixin.extendedConcreteMixedInConcreteField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  /*member: Mixin.extendedConcreteMixedInConcreteField=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int extendedConcreteMixedInConcreteField = 0;
+
+  /*member: Mixin.extendedAbstractMixedInConcreteField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  /*member: Mixin.extendedAbstractMixedInConcreteField=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int extendedAbstractMixedInConcreteField = 0;
+
+  /*member: Mixin.extendedConcreteMixedInAbstractField#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  /*member: Mixin.extendedConcreteMixedInAbstractField=#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  abstract int extendedConcreteMixedInAbstractField;
+
+  /*member: Mixin.extendedAbstractMixedInAbstractField#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  /*member: Mixin.extendedAbstractMixedInAbstractField=#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  abstract int extendedAbstractMixedInAbstractField;
+}
+
+/*class: _ClassMixin&Super&Mixin:
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteField#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteField#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteField=#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteField=#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteField=],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteField,
+  Super.extendedConcreteMixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/ /*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField=#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField=#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteField=,
+  Super.extendedConcreteMixedInConcreteField=],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteField,
+  Super.extendedAbstractMixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField=#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField=#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteField=,
+  Super.extendedAbstractMixedInConcreteField=],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Mixin.extendedConcreteMixedInAbstractField=,
+  Super.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField=]
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField=#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField=#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractField=,
+  Super.extendedConcreteMixedInAbstractField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Mixin.extendedConcreteMixedInAbstractField=,
+  Super.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField=]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteField#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteField=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.mixedInAbstractField,
+  Mixin.mixedInAbstractField=]
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInAbstractField=#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInAbstractField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.mixedInAbstractField,
+  Mixin.mixedInAbstractField=]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Mixin.extendedAbstractMixedInAbstractField=,
+  Super.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField=]
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField=#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractField=,
+  Super.extendedAbstractMixedInAbstractField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Mixin.extendedAbstractMixedInAbstractField=,
+  Super.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField=]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractField#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractField=#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*class: ClassMixin:
+ abstractMembers=[
+  Super.extendedAbstractField,
+  Super.extendedAbstractField=,
+  _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField,
+  _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField=,
+  _ClassMixin&Super&Mixin.mixedInAbstractField,
+  _ClassMixin&Super&Mixin.mixedInAbstractField=],
+ interfaces=[Mixin],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Super,
+  _ClassMixin&Super&Mixin]
+*/
+class ClassMixin extends Super with Mixin {
+  /*member: ClassMixin.mixedInConcreteField#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.mixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteField
+  */
+  /*member: ClassMixin.mixedInConcreteField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteField
+  */
+  /*member: ClassMixin.mixedInConcreteField=#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.mixedInConcreteField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteField=
+  */
+  /*member: ClassMixin.mixedInConcreteField=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInConcreteField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteField=
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInConcreteField#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField
+  */
+  /*member: ClassMixin.extendedConcreteMixedInConcreteField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInConcreteField,
+    Super.extendedConcreteMixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField
+  */
+  /*member: ClassMixin.extendedConcreteMixedInConcreteField=#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField=
+  */
+  /*member: ClassMixin.extendedConcreteMixedInConcreteField=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInConcreteField=,
+    Super.extendedConcreteMixedInConcreteField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField=
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInConcreteField#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField
+  */
+  /*member: ClassMixin.extendedAbstractMixedInConcreteField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInConcreteField,
+    Super.extendedAbstractMixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField
+  */
+  /*member: ClassMixin.extendedAbstractMixedInConcreteField=#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField=
+  */
+  /*member: ClassMixin.extendedAbstractMixedInConcreteField=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInConcreteField=,
+    Super.extendedAbstractMixedInConcreteField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField=
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInAbstractField#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField],
+   isSynthesized,
+   member=Super.extendedConcreteMixedInAbstractField
+  */
+  /*member: ClassMixin.extendedConcreteMixedInAbstractField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInAbstractField,
+    Super.extendedConcreteMixedInAbstractField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField
+  */
+  /*member: ClassMixin.extendedConcreteMixedInAbstractField=#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField=],
+   isSynthesized,
+   member=Super.extendedConcreteMixedInAbstractField
+  */
+  /*member: ClassMixin.extendedConcreteMixedInAbstractField=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInAbstractField=,
+    Super.extendedConcreteMixedInAbstractField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField=
+  */
+
+  /*member: ClassMixin.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ClassMixin.extendedConcreteField=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ClassMixin.mixedInAbstractField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInAbstractField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInAbstractField
+  */
+  /*member: ClassMixin.mixedInAbstractField=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInAbstractField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInAbstractField=
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInAbstractField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInAbstractField,
+    Super.extendedAbstractMixedInAbstractField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField
+  */
+  /*member: ClassMixin.extendedAbstractMixedInAbstractField=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInAbstractField=,
+    Super.extendedAbstractMixedInAbstractField=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField=
+  */
+
+  /*member: ClassMixin.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  /*member: ClassMixin.extendedAbstractField=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+}
+
+/*class: NamedMixin:
+ abstractMembers=[
+  NamedMixin.extendedAbstractMixedInAbstractField,
+  NamedMixin.extendedAbstractMixedInAbstractField=,
+  NamedMixin.mixedInAbstractField,
+  NamedMixin.mixedInAbstractField=,
+  Super.extendedAbstractField,
+  Super.extendedAbstractField=],
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: NamedMixin.mixedInConcreteField#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.mixedInConcreteField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.mixedInConcreteField,
+  Mixin.mixedInConcreteField=],
+ stubTarget=Mixin.mixedInConcreteField
+*/
+/*member: NamedMixin.mixedInConcreteField#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+/*member: NamedMixin.mixedInConcreteField=#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.mixedInConcreteField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.mixedInConcreteField,
+  Mixin.mixedInConcreteField=],
+ stubTarget=Mixin.mixedInConcreteField
+*/
+/*member: NamedMixin.mixedInConcreteField=#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteField=],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInConcreteField#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInConcreteField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInConcreteField,
+  Mixin.extendedConcreteMixedInConcreteField=,
+  Super.extendedConcreteMixedInConcreteField,
+  Super.extendedConcreteMixedInConcreteField=],
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteField#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteField,
+  Super.extendedConcreteMixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteField=#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInConcreteField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInConcreteField,
+  Mixin.extendedConcreteMixedInConcreteField=,
+  Super.extendedConcreteMixedInConcreteField,
+  Super.extendedConcreteMixedInConcreteField=],
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteField=#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteField=,
+  Super.extendedConcreteMixedInConcreteField=],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInConcreteField#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedAbstractMixedInConcreteField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInConcreteField,
+  Mixin.extendedAbstractMixedInConcreteField=,
+  Super.extendedAbstractMixedInConcreteField,
+  Super.extendedAbstractMixedInConcreteField=],
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteField#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteField,
+  Super.extendedAbstractMixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteField=#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedAbstractMixedInConcreteField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInConcreteField,
+  Mixin.extendedAbstractMixedInConcreteField=,
+  Super.extendedAbstractMixedInConcreteField,
+  Super.extendedAbstractMixedInConcreteField=],
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteField=#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteField=,
+  Super.extendedAbstractMixedInConcreteField=],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInAbstractField#cls:
+ classBuilder=NamedMixin,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInAbstractField],
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractField
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Mixin.extendedConcreteMixedInAbstractField=,
+  Super.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField=]
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractField=#cls:
+ classBuilder=NamedMixin,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInAbstractField=],
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractField
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractField=#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractField=,
+  Super.extendedConcreteMixedInAbstractField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Mixin.extendedConcreteMixedInAbstractField=,
+  Super.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField=]
+*/
+
+/*member: NamedMixin.extendedConcreteField#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: NamedMixin.extendedConcreteField=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: NamedMixin.mixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[Mixin.mixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.mixedInAbstractField,
+  Mixin.mixedInAbstractField=]
+*/
+/*member: NamedMixin.mixedInAbstractField=#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[Mixin.mixedInAbstractField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.mixedInAbstractField,
+  Mixin.mixedInAbstractField=]
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Mixin.extendedAbstractMixedInAbstractField=,
+  Super.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField=]
+*/
+/*member: NamedMixin.extendedAbstractMixedInAbstractField=#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractField=,
+  Super.extendedAbstractMixedInAbstractField=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Mixin.extendedAbstractMixedInAbstractField=,
+  Super.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField=]
+*/
+
+/*member: NamedMixin.extendedAbstractField#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: NamedMixin.extendedAbstractField=#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/mix_in_final_field.dart b/pkg/front_end/test/class_hierarchy/data/mix_in_final_field.dart
new file mode 100644
index 0000000..b1e0208
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/mix_in_final_field.dart
@@ -0,0 +1,413 @@
+// 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: Super:
+ abstractMembers=[
+  Super.extendedAbstractField,
+  Super.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInConcreteField],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final int extendedConcreteField = 0;
+
+  /*member: Super.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractField;
+
+  /*member: Super.extendedConcreteMixedInConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final int extendedConcreteMixedInConcreteField = 0;
+
+  /*member: Super.extendedAbstractMixedInConcreteField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractMixedInConcreteField;
+
+  /*member: Super.extendedConcreteMixedInAbstractField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  final int extendedConcreteMixedInAbstractField = 0;
+
+  /*member: Super.extendedAbstractMixedInAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractMixedInAbstractField;
+}
+
+/*class: Mixin:
+ abstractMembers=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Mixin.extendedConcreteMixedInAbstractField,
+  Mixin.mixedInAbstractField],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Mixin {
+  /*member: Mixin.mixedInConcreteField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  final int mixedInConcreteField = 0;
+
+  /*member: Mixin.mixedInAbstractField#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  abstract final int mixedInAbstractField;
+
+  /*member: Mixin.extendedConcreteMixedInConcreteField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  final int extendedConcreteMixedInConcreteField = 0;
+
+  /*member: Mixin.extendedAbstractMixedInConcreteField#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  final int extendedAbstractMixedInConcreteField = 0;
+
+  /*member: Mixin.extendedConcreteMixedInAbstractField#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  abstract final int extendedConcreteMixedInAbstractField;
+
+  /*member: Mixin.extendedAbstractMixedInAbstractField#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  abstract final int extendedAbstractMixedInAbstractField;
+}
+
+/*class: _ClassMixin&Super&Mixin:
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteField#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteField#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteField,
+  Super.extendedConcreteMixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteField,
+  Super.extendedAbstractMixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractField
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteField#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractField]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractField#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*class: ClassMixin:
+ abstractMembers=[
+  Super.extendedAbstractField,
+  _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField,
+  _ClassMixin&Super&Mixin.mixedInAbstractField],
+ interfaces=[Mixin],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Super,
+  _ClassMixin&Super&Mixin]
+*/
+class ClassMixin extends Super with Mixin {
+  /*member: ClassMixin.mixedInConcreteField#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.mixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteField
+  */
+  /*member: ClassMixin.mixedInConcreteField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteField
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInConcreteField#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField
+  */
+  /*member: ClassMixin.extendedConcreteMixedInConcreteField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInConcreteField,
+    Super.extendedConcreteMixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteField
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInConcreteField#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField
+  */
+  /*member: ClassMixin.extendedAbstractMixedInConcreteField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInConcreteField,
+    Super.extendedAbstractMixedInConcreteField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteField
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInAbstractField#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField],
+   isSynthesized,
+   member=Super.extendedConcreteMixedInAbstractField
+  */
+  /*member: ClassMixin.extendedConcreteMixedInAbstractField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInAbstractField,
+    Super.extendedConcreteMixedInAbstractField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractField
+  */
+
+  /*member: ClassMixin.extendedConcreteField#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ClassMixin.mixedInAbstractField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInAbstractField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInAbstractField
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInAbstractField#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInAbstractField,
+    Super.extendedAbstractMixedInAbstractField],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractField
+  */
+
+  /*member: ClassMixin.extendedAbstractField#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+}
+
+/*class: NamedMixin:
+ abstractMembers=[
+  NamedMixin.extendedAbstractMixedInAbstractField,
+  NamedMixin.mixedInAbstractField,
+  Super.extendedAbstractField],
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: NamedMixin.mixedInConcreteField#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.mixedInConcreteField],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInConcreteField],
+ stubTarget=Mixin.mixedInConcreteField
+*/
+/*member: NamedMixin.mixedInConcreteField#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteField
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInConcreteField#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInConcreteField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInConcreteField,
+  Super.extendedConcreteMixedInConcreteField],
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteField#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteField,
+  Super.extendedConcreteMixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteField
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInConcreteField#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedAbstractMixedInConcreteField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInConcreteField,
+  Super.extendedAbstractMixedInConcreteField],
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteField#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteField,
+  Super.extendedAbstractMixedInConcreteField],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteField
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInAbstractField#cls:
+ classBuilder=NamedMixin,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInAbstractField],
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractField
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractField,
+  Super.extendedConcreteMixedInAbstractField]
+*/
+
+/*member: NamedMixin.extendedConcreteField#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: NamedMixin.mixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[Mixin.mixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractField]
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInAbstractField#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractField,
+  Super.extendedAbstractMixedInAbstractField]
+*/
+
+/*member: NamedMixin.extendedAbstractField#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/mix_in_getter.dart b/pkg/front_end/test/class_hierarchy/data/mix_in_getter.dart
new file mode 100644
index 0000000..e4edc5c
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/mix_in_getter.dart
@@ -0,0 +1,412 @@
+// 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: Super:
+ abstractMembers=[
+  Super.extendedAbstractGetter,
+  Super.extendedAbstractMixedInAbstractGetter,
+  Super.extendedAbstractMixedInConcreteGetter],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedConcreteGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedConcreteGetter => 0;
+
+  /*member: Super.extendedAbstractGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedAbstractGetter;
+
+  /*member: Super.extendedConcreteMixedInConcreteGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedConcreteMixedInConcreteGetter => 0;
+
+  /*member: Super.extendedAbstractMixedInConcreteGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedAbstractMixedInConcreteGetter;
+
+  /*member: Super.extendedConcreteMixedInAbstractGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedConcreteMixedInAbstractGetter => 0;
+
+  /*member: Super.extendedAbstractMixedInAbstractGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  int get extendedAbstractMixedInAbstractGetter;
+}
+
+/*class: Mixin:
+ abstractMembers=[
+  Mixin.extendedAbstractMixedInAbstractGetter,
+  Mixin.extendedConcreteMixedInAbstractGetter,
+  Mixin.mixedInAbstractGetter],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Mixin {
+  /*member: Mixin.mixedInConcreteGetter#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int get mixedInConcreteGetter => 0;
+
+  /*member: Mixin.mixedInAbstractGetter#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int get mixedInAbstractGetter;
+
+  /*member: Mixin.extendedConcreteMixedInConcreteGetter#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int get extendedConcreteMixedInConcreteGetter => 0;
+
+  /*member: Mixin.extendedAbstractMixedInConcreteGetter#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int get extendedAbstractMixedInConcreteGetter => 0;
+
+  /*member: Mixin.extendedConcreteMixedInAbstractGetter#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int get extendedConcreteMixedInAbstractGetter;
+
+  /*member: Mixin.extendedAbstractMixedInAbstractGetter#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  int get extendedAbstractMixedInAbstractGetter;
+}
+
+/*class: _ClassMixin&Super&Mixin:
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteGetter#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteGetter
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteGetter#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteGetter],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteGetter
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteGetter#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteGetter
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteGetter#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteGetter,
+  Super.extendedConcreteMixedInConcreteGetter],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteGetter
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteGetter#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteGetter
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteGetter#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteGetter,
+  Super.extendedAbstractMixedInConcreteGetter],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteGetter
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractGetter#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractGetter
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractGetter#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractGetter,
+  Super.extendedConcreteMixedInAbstractGetter],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractGetter,
+  Super.extendedConcreteMixedInAbstractGetter]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteGetter#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInAbstractGetter#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInAbstractGetter],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractGetter]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractGetter#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractGetter,
+  Super.extendedAbstractMixedInAbstractGetter],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractGetter,
+  Super.extendedAbstractMixedInAbstractGetter]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractGetter#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*class: ClassMixin:
+ abstractMembers=[
+  Super.extendedAbstractGetter,
+  _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractGetter,
+  _ClassMixin&Super&Mixin.mixedInAbstractGetter],
+ interfaces=[Mixin],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Super,
+  _ClassMixin&Super&Mixin]
+*/
+class ClassMixin extends Super with Mixin {
+  /*member: ClassMixin.mixedInConcreteGetter#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.mixedInConcreteGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteGetter
+  */
+  /*member: ClassMixin.mixedInConcreteGetter#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInConcreteGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteGetter
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInConcreteGetter#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteGetter
+  */
+  /*member: ClassMixin.extendedConcreteMixedInConcreteGetter#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInConcreteGetter,
+    Super.extendedConcreteMixedInConcreteGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteGetter
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInConcreteGetter#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteGetter
+  */
+  /*member: ClassMixin.extendedAbstractMixedInConcreteGetter#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInConcreteGetter,
+    Super.extendedAbstractMixedInConcreteGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteGetter
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInAbstractGetter#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractGetter],
+   isSynthesized,
+   member=Super.extendedConcreteMixedInAbstractGetter
+  */
+  /*member: ClassMixin.extendedConcreteMixedInAbstractGetter#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInAbstractGetter,
+    Super.extendedConcreteMixedInAbstractGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractGetter
+  */
+
+  /*member: ClassMixin.extendedConcreteGetter#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ClassMixin.mixedInAbstractGetter#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInAbstractGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInAbstractGetter
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInAbstractGetter#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInAbstractGetter,
+    Super.extendedAbstractMixedInAbstractGetter],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractGetter
+  */
+
+  /*member: ClassMixin.extendedAbstractGetter#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+}
+
+/*class: NamedMixin:
+ abstractMembers=[
+  NamedMixin.extendedAbstractMixedInAbstractGetter,
+  NamedMixin.mixedInAbstractGetter,
+  Super.extendedAbstractGetter],
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: NamedMixin.mixedInConcreteGetter#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.mixedInConcreteGetter],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInConcreteGetter],
+ stubTarget=Mixin.mixedInConcreteGetter
+*/
+/*member: NamedMixin.mixedInConcreteGetter#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteGetter],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteGetter
+*/
+/*member: NamedMixin.mixedInAbstractGetter#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[Mixin.mixedInAbstractGetter],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractGetter]
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInConcreteGetter#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInConcreteGetter],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInConcreteGetter,
+  Super.extendedConcreteMixedInConcreteGetter],
+ stubTarget=Mixin.extendedConcreteMixedInConcreteGetter
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteGetter#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteGetter,
+  Super.extendedConcreteMixedInConcreteGetter],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteGetter
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInConcreteGetter#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedAbstractMixedInConcreteGetter],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInConcreteGetter,
+  Super.extendedAbstractMixedInConcreteGetter],
+ stubTarget=Mixin.extendedAbstractMixedInConcreteGetter
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteGetter#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteGetter,
+  Super.extendedAbstractMixedInConcreteGetter],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteGetter
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInAbstractGetter#cls:
+ classBuilder=NamedMixin,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInAbstractGetter],
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractGetter
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractGetter#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractGetter,
+  Super.extendedConcreteMixedInAbstractGetter],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractGetter,
+  Super.extendedConcreteMixedInAbstractGetter]
+*/
+
+/*member: NamedMixin.extendedConcreteGetter#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInAbstractGetter#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractGetter,
+  Super.extendedAbstractMixedInAbstractGetter],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractGetter,
+  Super.extendedAbstractMixedInAbstractGetter]
+*/
+
+/*member: NamedMixin.extendedAbstractGetter#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/mix_in_method.dart b/pkg/front_end/test/class_hierarchy/data/mix_in_method.dart
new file mode 100644
index 0000000..9e80172
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/mix_in_method.dart
@@ -0,0 +1,403 @@
+// 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: Super:
+ abstractMembers=[
+  Super.extendedAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteMethod() {}
+
+  /*member: Super.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractMethod();
+
+  /*member: Super.extendedConcreteMixedInConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteMixedInConcreteMethod() {}
+
+  /*member: Super.extendedAbstractMixedInConcreteMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractMixedInConcreteMethod();
+
+  /*member: Super.extendedConcreteMixedInAbstractMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteMixedInAbstractMethod() {}
+
+  /*member: Super.extendedAbstractMixedInAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+/*class: Mixin:
+ abstractMembers=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Mixin.mixedInAbstractMethod],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Mixin {
+  /*member: Mixin.mixedInConcreteMethod#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void mixedInConcreteMethod() {}
+
+  /*member: Mixin.mixedInAbstractMethod#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void mixedInAbstractMethod();
+
+  /*member: Mixin.extendedConcreteMixedInConcreteMethod#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void extendedConcreteMixedInConcreteMethod() {}
+
+  /*member: Mixin.extendedAbstractMixedInConcreteMethod#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void extendedAbstractMixedInConcreteMethod() {}
+
+  /*member: Mixin.extendedConcreteMixedInAbstractMethod#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void extendedConcreteMixedInAbstractMethod();
+
+  /*member: Mixin.extendedAbstractMixedInAbstractMethod#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+/*class: _ClassMixin&Super&Mixin:
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteMethod
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractMethod#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractMethod
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Super.extendedConcreteMixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Super.extendedConcreteMixedInAbstractMethod]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMethod#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractMethod]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMethod#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteMethod#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteMethod
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteMethod
+*/
+
+/*class: ClassMixin:
+ abstractMembers=[
+  Super.extendedAbstractMethod,
+  _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractMethod,
+  _ClassMixin&Super&Mixin.mixedInAbstractMethod],
+ interfaces=[Mixin],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Super,
+  _ClassMixin&Super&Mixin]
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteMethod
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteMethod,
+  Super.extendedConcreteMixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteMethod
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteMethod
+*/
+/*member: ClassMixin.mixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInConcreteMethod],
+ isSynthesized,
+ member=_ClassMixin&Super&Mixin.mixedInConcreteMethod
+*/
+/*member: ClassMixin.extendedConcreteMixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteMethod,
+  Super.extendedConcreteMixedInConcreteMethod],
+ isSynthesized,
+ member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod
+*/
+/*member: ClassMixin.extendedAbstractMixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ isSynthesized,
+ member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod
+*/
+class ClassMixin extends Super with Mixin {
+  /*member: ClassMixin.extendedConcreteMixedInConcreteMethod#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod
+  */
+
+  /*member: ClassMixin.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInAbstractMethod#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractMethod],
+   isSynthesized,
+   member=Super.extendedConcreteMixedInAbstractMethod
+  */
+  /*member: ClassMixin.extendedConcreteMixedInAbstractMethod#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInAbstractMethod,
+    Super.extendedConcreteMixedInAbstractMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractMethod
+  */
+
+  /*member: ClassMixin.mixedInConcreteMethod#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.mixedInConcreteMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteMethod
+  */
+
+  /*member: ClassMixin.mixedInAbstractMethod#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInAbstractMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInAbstractMethod
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInConcreteMethod#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInAbstractMethod#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInAbstractMethod,
+    Super.extendedAbstractMixedInAbstractMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractMethod
+  */
+
+  /*member: ClassMixin.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+}
+
+/*class: NamedMixin:
+ abstractMembers=[
+  NamedMixin.extendedAbstractMixedInAbstractMethod,
+  NamedMixin.mixedInAbstractMethod,
+  Super.extendedAbstractMethod],
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteMethod#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInConcreteMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInConcreteMethod,
+  Super.extendedConcreteMixedInConcreteMethod],
+ stubTarget=Mixin.extendedConcreteMixedInConcreteMethod
+*/
+/*member: NamedMixin.extendedConcreteMethod#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: NamedMixin.mixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[Mixin.mixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractMethod]
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Super.extendedConcreteMixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Super.extendedConcreteMixedInAbstractMethod]
+*/
+/*member: NamedMixin.extendedAbstractMixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod]
+*/
+/*member: NamedMixin.extendedAbstractMethod#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractMethod#cls:
+ classBuilder=NamedMixin,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInAbstractMethod],
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractMethod
+*/
+/*member: NamedMixin.mixedInConcreteMethod#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.mixedInConcreteMethod],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInConcreteMethod],
+ stubTarget=Mixin.mixedInConcreteMethod
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteMethod#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedAbstractMixedInConcreteMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInConcreteMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ stubTarget=Mixin.extendedAbstractMixedInConcreteMethod
+*/
+/*member: NamedMixin.mixedInConcreteMethod#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteMethod
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteMethod#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteMethod,
+  Super.extendedConcreteMixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteMethod
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteMethod#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteMethod
+*/
+class NamedMixin = Super with Mixin;
diff --git a/pkg/front_end/test/class_hierarchy/data/mix_in_override.dart b/pkg/front_end/test/class_hierarchy/data/mix_in_override.dart
new file mode 100644
index 0000000..2f8edef
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/mix_in_override.dart
@@ -0,0 +1,411 @@
+// 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: Super:
+ abstractMembers=[
+  Super.extendedAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteMethod() {}
+
+  /*member: Super.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractMethod();
+
+  /*member: Super.extendedConcreteMixedInConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteMixedInConcreteMethod() {}
+
+  /*member: Super.extendedAbstractMixedInConcreteMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractMixedInConcreteMethod();
+
+  /*member: Super.extendedConcreteMixedInAbstractMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedConcreteMixedInAbstractMethod() {}
+
+  /*member: Super.extendedAbstractMixedInAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+/*class: Mixin:
+ abstractMembers=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Mixin.mixedInAbstractMethod],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Mixin {
+  /*member: Mixin.mixedInConcreteMethod#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void mixedInConcreteMethod(int i) {}
+
+  /*member: Mixin.mixedInAbstractMethod#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void mixedInAbstractMethod(int i);
+
+  /*member: Mixin.extendedConcreteMixedInConcreteMethod#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void extendedConcreteMixedInConcreteMethod(int i) {}
+
+  /*member: Mixin.extendedAbstractMixedInConcreteMethod#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void extendedAbstractMixedInConcreteMethod(int i) {}
+
+  /*member: Mixin.extendedConcreteMixedInAbstractMethod#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void extendedConcreteMixedInAbstractMethod(int i);
+
+  /*member: Mixin.extendedAbstractMixedInAbstractMethod#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void extendedAbstractMixedInAbstractMethod(int i);
+}
+
+/*class: _ClassMixin&Super&Mixin:
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteMethod
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractMethod#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractMethod
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Super.extendedConcreteMixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Super.extendedConcreteMixedInAbstractMethod]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMethod#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractMethod]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMethod#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*class: ClassMixin:
+ abstractMembers=[
+  Super.extendedAbstractMethod,
+  _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractMethod,
+  _ClassMixin&Super&Mixin.mixedInAbstractMethod],
+ interfaces=[Mixin],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Super,
+  _ClassMixin&Super&Mixin]
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteMethod
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteMethod,
+  Super.extendedConcreteMixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteMethod
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteMethod
+*/
+/*member: ClassMixin.mixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInConcreteMethod],
+ isSynthesized,
+ member=_ClassMixin&Super&Mixin.mixedInConcreteMethod
+*/
+/*member: ClassMixin.extendedConcreteMixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteMethod,
+  Super.extendedConcreteMixedInConcreteMethod],
+ isSynthesized,
+ member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod
+*/
+/*member: ClassMixin.extendedAbstractMixedInConcreteMethod#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ isSynthesized,
+ member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod
+*/
+class ClassMixin extends Super with Mixin {
+  /*member: ClassMixin.extendedConcreteMixedInConcreteMethod#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteMethod
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInAbstractMethod#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractMethod],
+   isSynthesized,
+   member=Super.extendedConcreteMixedInAbstractMethod
+  */
+  /*member: ClassMixin.extendedConcreteMixedInAbstractMethod#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInAbstractMethod,
+    Super.extendedConcreteMixedInAbstractMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractMethod
+  */
+
+  /*member: ClassMixin.extendedConcreteMethod#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ClassMixin.mixedInAbstractMethod#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInAbstractMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInAbstractMethod
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInAbstractMethod#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInAbstractMethod,
+    Super.extendedAbstractMixedInAbstractMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractMethod
+  */
+
+  /*member: ClassMixin.extendedAbstractMethod#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: _ClassMixin&Super&Mixin.mixedInConcreteMethod#cls:
+   classBuilder=_ClassMixin&Super&Mixin,
+   concreteMixinStub,
+   isSynthesized,
+   stubTarget=Mixin.mixedInConcreteMethod
+  */
+
+  /*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod#cls:
+   classBuilder=_ClassMixin&Super&Mixin,
+   concreteMixinStub,
+   isSynthesized,
+   stubTarget=Mixin.extendedAbstractMixedInConcreteMethod
+  */
+
+  /*member: ClassMixin.mixedInConcreteMethod#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.mixedInConcreteMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteMethod
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInConcreteMethod#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteMethod
+  */
+}
+
+/*class: NamedMixin:
+ abstractMembers=[
+  NamedMixin.extendedAbstractMixedInAbstractMethod,
+  NamedMixin.mixedInAbstractMethod,
+  Super.extendedAbstractMethod],
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInConcreteMethod#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInConcreteMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInConcreteMethod,
+  Super.extendedConcreteMixedInConcreteMethod],
+ stubTarget=Mixin.extendedConcreteMixedInConcreteMethod
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInAbstractMethod#cls:
+ classBuilder=NamedMixin,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInAbstractMethod],
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractMethod
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Super.extendedConcreteMixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractMethod,
+  Super.extendedConcreteMixedInAbstractMethod]
+*/
+
+/*member: NamedMixin.extendedConcreteMethod#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: NamedMixin.mixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[Mixin.mixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractMethod]
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInAbstractMethod#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractMethod,
+  Super.extendedAbstractMixedInAbstractMethod]
+*/
+
+/*member: NamedMixin.extendedAbstractMethod#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: NamedMixin.mixedInConcreteMethod#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.mixedInConcreteMethod],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInConcreteMethod],
+ stubTarget=Mixin.mixedInConcreteMethod
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInConcreteMethod#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedAbstractMixedInConcreteMethod],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInConcreteMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ stubTarget=Mixin.extendedAbstractMixedInConcreteMethod
+*/
+/*member: NamedMixin.mixedInConcreteMethod#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteMethod
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteMethod#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteMethod,
+  Super.extendedConcreteMixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteMethod
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteMethod#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteMethod,
+  Super.extendedAbstractMixedInConcreteMethod],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteMethod
+*/
+class NamedMixin = Super with Mixin;
diff --git a/pkg/front_end/test/class_hierarchy/data/mix_in_setter.dart b/pkg/front_end/test/class_hierarchy/data/mix_in_setter.dart
new file mode 100644
index 0000000..758f3dd
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/mix_in_setter.dart
@@ -0,0 +1,413 @@
+// 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: Super:
+ abstractMembers=[
+  Super.extendedAbstractMixedInAbstractSetter=,
+  Super.extendedAbstractMixedInConcreteSetter=,
+  Super.extendedAbstractSetter=],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedConcreteSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteSetter(int i) {}
+
+  /*member: Super.extendedAbstractSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractSetter(int i);
+
+  /*member: Super.extendedConcreteMixedInConcreteSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteMixedInConcreteSetter(int i) {}
+
+  /*member: Super.extendedAbstractMixedInConcreteSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractMixedInConcreteSetter(int i);
+
+  /*member: Super.extendedConcreteMixedInAbstractSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedConcreteMixedInAbstractSetter(int i) {}
+
+  /*member: Super.extendedAbstractMixedInAbstractSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void set extendedAbstractMixedInAbstractSetter(int i);
+}
+
+/*class: Mixin:
+ abstractMembers=[
+  Mixin.extendedAbstractMixedInAbstractSetter=,
+  Mixin.extendedConcreteMixedInAbstractSetter=,
+  Mixin.mixedInAbstractSetter=],
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Mixin {
+  /*member: Mixin.mixedInConcreteSetter=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set mixedInConcreteSetter(int i) {}
+
+  /*member: Mixin.mixedInAbstractSetter=#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set mixedInAbstractSetter(int i);
+
+  /*member: Mixin.extendedConcreteMixedInConcreteSetter=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set extendedConcreteMixedInConcreteSetter(int i) {}
+
+  /*member: Mixin.extendedAbstractMixedInConcreteSetter=#cls:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set extendedAbstractMixedInConcreteSetter(int i) {}
+
+  /*member: Mixin.extendedConcreteMixedInAbstractSetter=#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set extendedConcreteMixedInAbstractSetter(int i);
+
+  /*member: Mixin.extendedAbstractMixedInAbstractSetter=#int:
+   classBuilder=Mixin,
+   isSourceDeclaration
+  */
+  void set extendedAbstractMixedInAbstractSetter(int i);
+}
+
+/*class: _ClassMixin&Super&Mixin:
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteSetter=#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteSetter=
+*/
+/*member: _ClassMixin&Super&Mixin.mixedInConcreteSetter=#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteSetter=],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteSetter=
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteSetter=#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteSetter=
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteSetter=#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteSetter=,
+  Super.extendedConcreteMixedInConcreteSetter=],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteSetter=
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteSetter=#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteSetter=
+*/
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteSetter=#int:
+ classBuilder=_ClassMixin&Super&Mixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteSetter=,
+  Super.extendedAbstractMixedInConcreteSetter=],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteSetter=
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractSetter=#cls:
+ classBuilder=_ClassMixin&Super&Mixin,
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractSetter=
+*/
+/*member: _ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractSetter=#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractSetter=,
+  Super.extendedConcreteMixedInAbstractSetter=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractSetter=,
+  Super.extendedConcreteMixedInAbstractSetter=]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedConcreteSetter=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: _ClassMixin&Super&Mixin.mixedInAbstractSetter=#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[Mixin.mixedInAbstractSetter=],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractSetter=]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractSetter=#int:
+ abstractMixinStub,
+ classBuilder=_ClassMixin&Super&Mixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractSetter=,
+  Super.extendedAbstractMixedInAbstractSetter=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractSetter=,
+  Super.extendedAbstractMixedInAbstractSetter=]
+*/
+
+/*member: _ClassMixin&Super&Mixin.extendedAbstractSetter=#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*class: ClassMixin:
+ abstractMembers=[
+  Super.extendedAbstractSetter=,
+  _ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractSetter=,
+  _ClassMixin&Super&Mixin.mixedInAbstractSetter=],
+ interfaces=[Mixin],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  Super,
+  _ClassMixin&Super&Mixin]
+*/
+class ClassMixin extends Super with Mixin {
+  /*member: ClassMixin.mixedInConcreteSetter=#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.mixedInConcreteSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteSetter=
+  */
+  /*member: ClassMixin.mixedInConcreteSetter=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInConcreteSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInConcreteSetter=
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInConcreteSetter=#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteSetter=
+  */
+  /*member: ClassMixin.extendedConcreteMixedInConcreteSetter=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInConcreteSetter=,
+    Super.extendedConcreteMixedInConcreteSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInConcreteSetter=
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInConcreteSetter=#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteSetter=
+  */
+  /*member: ClassMixin.extendedAbstractMixedInConcreteSetter=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInConcreteSetter=,
+    Super.extendedAbstractMixedInConcreteSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInConcreteSetter=
+  */
+
+  /*member: ClassMixin.extendedConcreteMixedInAbstractSetter=#cls:
+   classBuilder=ClassMixin,
+   inherited-implements=[_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractSetter=],
+   isSynthesized,
+   member=Super.extendedConcreteMixedInAbstractSetter=
+  */
+  /*member: ClassMixin.extendedConcreteMixedInAbstractSetter=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedConcreteMixedInAbstractSetter=,
+    Super.extendedConcreteMixedInAbstractSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedConcreteMixedInAbstractSetter=
+  */
+
+  /*member: ClassMixin.extendedConcreteSetter=#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+
+  /*member: ClassMixin.mixedInAbstractSetter=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[Mixin.mixedInAbstractSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.mixedInAbstractSetter=
+  */
+
+  /*member: ClassMixin.extendedAbstractMixedInAbstractSetter=#int:
+   classBuilder=_ClassMixin&Super&Mixin,
+   declarations=[
+    Mixin.extendedAbstractMixedInAbstractSetter=,
+    Super.extendedAbstractMixedInAbstractSetter=],
+   isSynthesized,
+   member=_ClassMixin&Super&Mixin.extendedAbstractMixedInAbstractSetter=
+  */
+
+  /*member: ClassMixin.extendedAbstractSetter=#int:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+}
+
+/*class: NamedMixin:
+ abstractMembers=[
+  NamedMixin.extendedAbstractMixedInAbstractSetter=,
+  NamedMixin.mixedInAbstractSetter=,
+  Super.extendedAbstractSetter=],
+ interfaces=[Mixin],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+
+/*member: NamedMixin.mixedInConcreteSetter=#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.mixedInConcreteSetter=],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInConcreteSetter=],
+ stubTarget=Mixin.mixedInConcreteSetter=
+*/
+/*member: NamedMixin.mixedInConcreteSetter=#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[Mixin.mixedInConcreteSetter=],
+ isSynthesized,
+ stubTarget=Mixin.mixedInConcreteSetter=
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInConcreteSetter=#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInConcreteSetter=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInConcreteSetter=,
+  Super.extendedConcreteMixedInConcreteSetter=],
+ stubTarget=Mixin.extendedConcreteMixedInConcreteSetter=
+*/
+/*member: NamedMixin.extendedConcreteMixedInConcreteSetter=#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedConcreteMixedInConcreteSetter=,
+  Super.extendedConcreteMixedInConcreteSetter=],
+ isSynthesized,
+ stubTarget=Mixin.extendedConcreteMixedInConcreteSetter=
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInConcreteSetter=#cls:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ inherited-implements=[NamedMixin.extendedAbstractMixedInConcreteSetter=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInConcreteSetter=,
+  Super.extendedAbstractMixedInConcreteSetter=],
+ stubTarget=Mixin.extendedAbstractMixedInConcreteSetter=
+*/
+/*member: NamedMixin.extendedAbstractMixedInConcreteSetter=#int:
+ classBuilder=NamedMixin,
+ concreteMixinStub,
+ declarations=[
+  Mixin.extendedAbstractMixedInConcreteSetter=,
+  Super.extendedAbstractMixedInConcreteSetter=],
+ isSynthesized,
+ stubTarget=Mixin.extendedAbstractMixedInConcreteSetter=
+*/
+
+/*member: NamedMixin.extendedConcreteMixedInAbstractSetter=#cls:
+ classBuilder=NamedMixin,
+ inherited-implements=[NamedMixin.extendedConcreteMixedInAbstractSetter=],
+ isSynthesized,
+ member=Super.extendedConcreteMixedInAbstractSetter=
+*/
+/*member: NamedMixin.extendedConcreteMixedInAbstractSetter=#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedConcreteMixedInAbstractSetter=,
+  Super.extendedConcreteMixedInAbstractSetter=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedConcreteMixedInAbstractSetter=,
+  Super.extendedConcreteMixedInAbstractSetter=]
+*/
+
+/*member: NamedMixin.extendedConcreteSetter=#cls:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+
+/*member: NamedMixin.mixedInAbstractSetter=#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[Mixin.mixedInAbstractSetter=],
+ isSynthesized,
+ mixin-overrides=[Mixin.mixedInAbstractSetter=]
+*/
+
+/*member: NamedMixin.extendedAbstractMixedInAbstractSetter=#int:
+ abstractMixinStub,
+ classBuilder=NamedMixin,
+ declarations=[
+  Mixin.extendedAbstractMixedInAbstractSetter=,
+  Super.extendedAbstractMixedInAbstractSetter=],
+ isSynthesized,
+ mixin-overrides=[
+  Mixin.extendedAbstractMixedInAbstractSetter=,
+  Super.extendedAbstractMixedInAbstractSetter=]
+*/
+
+/*member: NamedMixin.extendedAbstractSetter=#int:
+ classBuilder=Super,
+ isSourceDeclaration
+*/
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/no_such_method.dart b/pkg/front_end/test/class_hierarchy/data/no_such_method.dart
new file mode 100644
index 0000000..c29b312
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/no_such_method.dart
@@ -0,0 +1,780 @@
+// 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: Interface:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+abstract class Interface {
+  /*member: Interface.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void method();
+
+  /*member: Interface.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int get getter;
+
+  /*member: Interface.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  void set setter(int value);
+
+  /*member: Interface.field#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: Interface.field=#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  int field;
+
+  /*member: Interface.finalField#cls:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  final int finalField;
+}
+
+/*class: SuperAbstract:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class SuperAbstract {
+  /*member: SuperAbstract.noSuchMethod#int:
+   classBuilder=SuperAbstract,
+   declarations=[
+    Object.noSuchMethod,
+    SuperAbstract.noSuchMethod],
+   declared-overrides=[Object.noSuchMethod],
+   isSynthesized
+  */
+  noSuchMethod(Invocation invocation);
+}
+
+/*class: FromSuperAbstract:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  SuperAbstract]
+*/
+class FromSuperAbstract extends SuperAbstract implements Interface {
+  /*member: FromSuperAbstract.noSuchMethod#int:
+   classBuilder=FromSuperAbstract,
+   declarations=[
+    Object.noSuchMethod,
+    SuperAbstract.noSuchMethod],
+   isSynthesized,
+   member=SuperAbstract.noSuchMethod
+  */
+
+  /*member: FromSuperAbstract.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: FromSuperAbstract.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperAbstract.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperAbstract.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperAbstract.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperAbstract.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+}
+
+/*class: SuperConcrete:
+ hasNoSuchMethod,
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class SuperConcrete {
+  /*member: SuperConcrete.noSuchMethod#cls:
+   classBuilder=SuperConcrete,
+   declared-overrides=[Object.noSuchMethod],
+   isSourceDeclaration
+  */
+  @override
+  noSuchMethod(Invocation invocation) {
+    return null;
+  }
+}
+
+/*class: FromSuperConcrete:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ hasNoSuchMethod,
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  SuperConcrete]
+*/
+class FromSuperConcrete extends SuperConcrete implements Interface {
+  /*member: FromSuperConcrete.noSuchMethod#cls:
+   classBuilder=FromSuperConcrete,
+   inherited-implements=[FromSuperConcrete.noSuchMethod],
+   isSynthesized,
+   member=SuperConcrete.noSuchMethod
+  */
+  /*member: FromSuperConcrete.noSuchMethod#int:
+   classBuilder=FromSuperConcrete,
+   declarations=[
+    Object.noSuchMethod,
+    SuperConcrete.noSuchMethod],
+   isSynthesized,
+   member=SuperConcrete.noSuchMethod
+  */
+
+  /*member: FromSuperConcrete.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: FromSuperConcrete.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperConcrete.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperConcrete.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperConcrete.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperConcrete.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+}
+
+/*class: FromSuperConcreteAbstract:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ hasNoSuchMethod,
+ interfaces=[
+  Interface,
+  SuperAbstract],
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  SuperConcrete]
+*/
+class FromSuperConcreteAbstract extends SuperConcrete
+    implements SuperAbstract, Interface {
+  /*member: FromSuperConcreteAbstract.noSuchMethod#cls:
+   classBuilder=FromSuperConcreteAbstract,
+   inherited-implements=[FromSuperConcreteAbstract.noSuchMethod],
+   isSynthesized,
+   member=SuperConcrete.noSuchMethod
+  */
+  /*member: FromSuperConcreteAbstract.noSuchMethod#int:
+   classBuilder=FromSuperConcreteAbstract,
+   declarations=[
+    Object.noSuchMethod,
+    SuperAbstract.noSuchMethod,
+    SuperConcrete.noSuchMethod],
+   isSynthesized,
+   member=SuperConcrete.noSuchMethod
+  */
+
+  /*member: FromSuperConcreteAbstract.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: FromSuperConcreteAbstract.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperConcreteAbstract.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperConcreteAbstract.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperConcreteAbstract.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromSuperConcreteAbstract.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+}
+
+/*class: MixinAbstract:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class MixinAbstract {
+  /*member: MixinAbstract.noSuchMethod#int:
+   classBuilder=MixinAbstract,
+   declarations=[
+    MixinAbstract.noSuchMethod,
+    Object.noSuchMethod],
+   declared-overrides=[Object.noSuchMethod],
+   isSynthesized
+  */
+  noSuchMethod(Invocation invocation);
+}
+
+/*class: FromMixinAbstract:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[
+  MixinAbstract,
+  Object]
+*/
+class FromMixinAbstract extends MixinAbstract implements Interface {
+  /*member: FromMixinAbstract.noSuchMethod#int:
+   classBuilder=FromMixinAbstract,
+   declarations=[
+    MixinAbstract.noSuchMethod,
+    Object.noSuchMethod],
+   isSynthesized,
+   member=MixinAbstract.noSuchMethod
+  */
+
+  /*member: FromMixinAbstract.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: FromMixinAbstract.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinAbstract.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinAbstract.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinAbstract.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinAbstract.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+}
+
+/*class: MixinConcrete:
+ hasNoSuchMethod,
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class MixinConcrete {
+  /*member: MixinConcrete.noSuchMethod#cls:
+   classBuilder=MixinConcrete,
+   declared-overrides=[Object.noSuchMethod],
+   isSourceDeclaration
+  */
+  @override
+  noSuchMethod(Invocation invocation) {
+    return null;
+  }
+}
+
+/*class: _FromMixinConcrete&Object&MixinConcrete:
+ hasNoSuchMethod,
+ interfaces=[MixinConcrete],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+
+/*member: _FromMixinConcrete&Object&MixinConcrete.noSuchMethod#cls:
+ classBuilder=_FromMixinConcrete&Object&MixinConcrete,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=MixinConcrete.noSuchMethod
+*/
+/*member: _FromMixinConcrete&Object&MixinConcrete.noSuchMethod#int:
+ classBuilder=_FromMixinConcrete&Object&MixinConcrete,
+ concreteMixinStub,
+ declarations=[
+  MixinConcrete.noSuchMethod,
+  Object.noSuchMethod],
+ isSynthesized,
+ stubTarget=MixinConcrete.noSuchMethod
+*/
+
+/*class: FromMixinConcrete:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ hasNoSuchMethod,
+ interfaces=[
+  Interface,
+  MixinConcrete],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  _FromMixinConcrete&Object&MixinConcrete]
+*/
+class FromMixinConcrete with MixinConcrete implements Interface {
+  /*member: FromMixinConcrete.noSuchMethod#cls:
+   classBuilder=FromMixinConcrete,
+   inherited-implements=[FromMixinConcrete.noSuchMethod],
+   isSynthesized,
+   member=_FromMixinConcrete&Object&MixinConcrete.noSuchMethod
+  */
+  /*member: FromMixinConcrete.noSuchMethod#int:
+   classBuilder=FromMixinConcrete,
+   declarations=[
+    Object.noSuchMethod,
+    _FromMixinConcrete&Object&MixinConcrete.noSuchMethod],
+   isSynthesized,
+   member=_FromMixinConcrete&Object&MixinConcrete.noSuchMethod
+  */
+
+  /*member: FromMixinConcrete.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: FromMixinConcrete.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinConcrete.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinConcrete.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinConcrete.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinConcrete.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+}
+
+/*class: _FromMixinConcreteAbstract&Object&MixinConcrete:
+ hasNoSuchMethod,
+ interfaces=[MixinConcrete],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+
+/*member: _FromMixinConcreteAbstract&Object&MixinConcrete.noSuchMethod#cls:
+ classBuilder=_FromMixinConcreteAbstract&Object&MixinConcrete,
+ concreteMixinStub,
+ isSynthesized,
+ stubTarget=MixinConcrete.noSuchMethod
+*/
+/*member: _FromMixinConcreteAbstract&Object&MixinConcrete.noSuchMethod#int:
+ classBuilder=_FromMixinConcreteAbstract&Object&MixinConcrete,
+ concreteMixinStub,
+ declarations=[
+  MixinConcrete.noSuchMethod,
+  Object.noSuchMethod],
+ isSynthesized,
+ stubTarget=MixinConcrete.noSuchMethod
+*/
+
+/*class: _FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract:
+ hasNoSuchMethod,
+ interfaces=[
+  MixinAbstract,
+  MixinConcrete],
+ maxInheritancePath=3,
+ superclasses=[
+  Object,
+  _FromMixinConcreteAbstract&Object&MixinConcrete]
+*/
+
+/*member: _FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract.noSuchMethod#cls:
+ classBuilder=_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract,
+ isSynthesized,
+ member=_FromMixinConcreteAbstract&Object&MixinConcrete.noSuchMethod
+*/
+/*member: _FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract.noSuchMethod#int:
+ abstractMixinStub,
+ classBuilder=_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract,
+ declarations=[
+  MixinAbstract.noSuchMethod,
+  MixinAbstract.noSuchMethod,
+  _FromMixinConcreteAbstract&Object&MixinConcrete.noSuchMethod],
+ isSynthesized,
+ mixin-overrides=[
+  MixinAbstract.noSuchMethod,
+  _FromMixinConcreteAbstract&Object&MixinConcrete.noSuchMethod]
+*/
+
+/*class: FromMixinConcreteAbstract:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ hasNoSuchMethod,
+ interfaces=[
+  Interface,
+  MixinAbstract,
+  MixinConcrete],
+ maxInheritancePath=4,
+ superclasses=[
+  Object,
+  _FromMixinConcreteAbstract&Object&MixinConcrete,
+  _FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract]
+*/
+class FromMixinConcreteAbstract
+    with MixinConcrete, MixinAbstract
+    implements Interface {
+  /*member: FromMixinConcreteAbstract.noSuchMethod#cls:
+   classBuilder=FromMixinConcreteAbstract,
+   inherited-implements=[FromMixinConcreteAbstract.noSuchMethod],
+   isSynthesized,
+   member=_FromMixinConcreteAbstract&Object&MixinConcrete.noSuchMethod
+  */
+  /*member: FromMixinConcreteAbstract.noSuchMethod#int:
+   classBuilder=FromMixinConcreteAbstract,
+   declarations=[
+    Object.noSuchMethod,
+    _FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract.noSuchMethod],
+   isSynthesized,
+   member=_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract.noSuchMethod
+  */
+
+  /*member: FromMixinConcreteAbstract.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: FromMixinConcreteAbstract.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinConcreteAbstract.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinConcreteAbstract.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinConcreteAbstract.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromMixinConcreteAbstract.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+}
+
+/*class: InterfaceAbstract:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class InterfaceAbstract {
+  /*member: InterfaceAbstract.noSuchMethod#int:
+   classBuilder=InterfaceAbstract,
+   declarations=[
+    InterfaceAbstract.noSuchMethod,
+    Object.noSuchMethod],
+   declared-overrides=[Object.noSuchMethod],
+   isSynthesized
+  */
+  noSuchMethod(Invocation invocation);
+}
+
+/*class: FromInterfaceAbstract:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ interfaces=[
+  Interface,
+  InterfaceAbstract],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class FromInterfaceAbstract implements InterfaceAbstract, Interface {
+  /*member: FromInterfaceAbstract.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: FromInterfaceAbstract.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromInterfaceAbstract.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromInterfaceAbstract.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromInterfaceAbstract.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromInterfaceAbstract.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+}
+
+/*class: InterfaceConcrete:
+ hasNoSuchMethod,
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class InterfaceConcrete {
+  /*member: InterfaceConcrete.noSuchMethod#cls:
+   classBuilder=InterfaceConcrete,
+   declared-overrides=[Object.noSuchMethod],
+   isSourceDeclaration
+  */
+  @override
+  noSuchMethod(Invocation invocation) {
+    return null;
+  }
+}
+
+/*class: FromInterfaceConcrete:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ interfaces=[
+  Interface,
+  InterfaceConcrete],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class FromInterfaceConcrete implements InterfaceConcrete, Interface {
+  /*member: FromInterfaceConcrete.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: FromInterfaceConcrete.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromInterfaceConcrete.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromInterfaceConcrete.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromInterfaceConcrete.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: FromInterfaceConcrete.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+}
+
+/*class: DeclaredAbstract:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class DeclaredAbstract implements Interface {
+  /*member: DeclaredAbstract.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: DeclaredAbstract.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredAbstract.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredAbstract.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredAbstract.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredAbstract.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredAbstract.noSuchMethod#int:
+   classBuilder=DeclaredAbstract,
+   declarations=[
+    DeclaredAbstract.noSuchMethod,
+    Object.noSuchMethod],
+   declared-overrides=[Object.noSuchMethod],
+   isSynthesized
+  */
+  noSuchMethod(Invocation invocation);
+}
+
+/*class: DeclaredConcrete:
+ abstractMembers=[
+  Interface.field,
+  Interface.field=,
+  Interface.finalField,
+  Interface.getter,
+  Interface.method,
+  Interface.setter=],
+ hasNoSuchMethod,
+ interfaces=[Interface],
+ maxInheritancePath=2,
+ superclasses=[Object]
+*/
+class DeclaredConcrete implements Interface {
+  /*member: DeclaredConcrete.field#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+  /*member: DeclaredConcrete.field=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredConcrete.finalField#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredConcrete.method#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredConcrete.getter#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredConcrete.setter=#int:
+   classBuilder=Interface,
+   isSourceDeclaration
+  */
+
+  /*member: DeclaredConcrete.noSuchMethod#cls:
+   classBuilder=DeclaredConcrete,
+   declared-overrides=[Object.noSuchMethod],
+   isSourceDeclaration
+  */
+  @override
+  noSuchMethod(Invocation invocation) {
+    return null;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/test/class_hierarchy/data/override.dart b/pkg/front_end/test/class_hierarchy/data/override.dart
new file mode 100644
index 0000000..a3e687a
--- /dev/null
+++ b/pkg/front_end/test/class_hierarchy/data/override.dart
@@ -0,0 +1,87 @@
+// 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: Super:
+ maxInheritancePath=1,
+ superclasses=[Object]
+*/
+class Super {
+  /*member: Super.extendedMethod1#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedMethod1(int i) {}
+
+  /*member: Super.extendedMethod2#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void extendedMethod2(num i) {}
+
+  /*member: Super.overriddenMethod1#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void overriddenMethod1(int i) {}
+
+  /*member: Super.overriddenMethod2#cls:
+   classBuilder=Super,
+   isSourceDeclaration
+  */
+  void overriddenMethod2(num n) {}
+}
+
+/*class: Class:
+ maxInheritancePath=2,
+ superclasses=[
+  Object,
+  Super]
+*/
+/*member: Class.extendedMethod1#cls:
+ classBuilder=Class,
+ inherited-implements=[Class.extendedMethod1],
+ isSynthesized,
+ member=Super.extendedMethod1
+*/
+/*member: Class.extendedMethod2#cls:
+ classBuilder=Class,
+ inherited-implements=[Class.extendedMethod2],
+ isSynthesized,
+ member=Super.extendedMethod2
+*/
+class Class extends Super {
+  /*member: Class.extendedMethod1#int:
+   classBuilder=Class,
+   declarations=[
+    Class.extendedMethod1,
+    Super.extendedMethod1],
+   declared-overrides=[Super.extendedMethod1],
+   isSynthesized
+  */
+  void extendedMethod1(num n);
+
+  /*member: Class.extendedMethod2#int:
+   classBuilder=Class,
+   declarations=[
+    Class.extendedMethod2,
+    Super.extendedMethod2],
+   declared-overrides=[Super.extendedMethod2],
+   isSynthesized
+  */
+  void extendedMethod2(int i);
+
+  /*member: Class.overriddenMethod1#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.overriddenMethod1],
+   isSourceDeclaration
+  */
+  void overriddenMethod1(num n) {}
+
+  /*member: Class.overriddenMethod2#cls:
+   classBuilder=Class,
+   declared-overrides=[Super.overriddenMethod2],
+   isSourceDeclaration
+  */
+  void overriddenMethod2(int n) {}
+}
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 41045b5..d83bf84 100644
--- a/pkg/front_end/test/comments_on_certain_arguments_tool.dart
+++ b/pkg/front_end/test/comments_on_certain_arguments_tool.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.9
+
 import 'dart:convert' show utf8;
 import 'dart:io'
     show Directory, File, FileSystemEntity, exitCode, stdin, stdout;
diff --git a/pkg/front_end/test/compile_dart2js_with_no_sdk_test.dart b/pkg/front_end/test/compile_dart2js_with_no_sdk_test.dart
index 4939c11..513b868 100644
--- a/pkg/front_end/test/compile_dart2js_with_no_sdk_test.dart
+++ b/pkg/front_end/test/compile_dart2js_with_no_sdk_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 
 import 'incremental_load_from_dill_suite.dart'
diff --git a/pkg/front_end/test/compile_with_no_sdk_test.dart b/pkg/front_end/test/compile_with_no_sdk_test.dart
index b096688..5c7f5ca 100644
--- a/pkg/front_end/test/compile_with_no_sdk_test.dart
+++ b/pkg/front_end/test/compile_with_no_sdk_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/api_prototype/memory_file_system.dart';
 
diff --git a/pkg/front_end/test/constant_evaluator_benchmark.dart b/pkg/front_end/test/constant_evaluator_benchmark.dart
index f0e722c..5de0a0a 100644
--- a/pkg/front_end/test/constant_evaluator_benchmark.dart
+++ b/pkg/front_end/test/constant_evaluator_benchmark.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.9
+
 import 'dart:io' show File;
 import 'dart:typed_data' show Uint8List;
 
diff --git a/pkg/front_end/test/covariance_check/covariance_check_test.dart b/pkg/front_end/test/covariance_check/covariance_check_test.dart
index 99dcbbc..ed0e223 100644
--- a/pkg/front_end/test/covariance_check/covariance_check_test.dart
+++ b/pkg/front_end/test/covariance_check/covariance_check_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
diff --git a/pkg/front_end/test/crashing_test_case_minimizer.dart b/pkg/front_end/test/crashing_test_case_minimizer.dart
index ea8ac64..57c27f6 100644
--- a/pkg/front_end/test/crashing_test_case_minimizer.dart
+++ b/pkg/front_end/test/crashing_test_case_minimizer.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.9
+
 import 'dart:convert' show jsonDecode;
 
 import 'dart:io' show File;
@@ -56,6 +58,12 @@
           settings.targetString = "flutter";
         } else if (arg.startsWith("--target=ddc")) {
           settings.targetString = "ddc";
+        } else if (arg == "--noTryToDeleteEmptyFilesUpFront") {
+          settings.noTryToDeleteEmptyFilesUpFront = true;
+        } else if (arg.startsWith("--wantErrorOnReload=")) {
+          String wantErrorOnReload =
+              arg.substring("--wantErrorOnReload=".length);
+          settings.lookForErrorErrorOnReload = wantErrorOnReload;
         } else if (arg == "--oldBlockDelete") {
           settings.oldBlockDelete = true;
         } else if (arg == "--lineDelete") {
diff --git a/pkg/front_end/test/crashing_test_case_minimizer_impl.dart b/pkg/front_end/test/crashing_test_case_minimizer_impl.dart
index 8bda7f4..0749061 100644
--- a/pkg/front_end/test/crashing_test_case_minimizer_impl.dart
+++ b/pkg/front_end/test/crashing_test_case_minimizer_impl.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.9
+
 import 'dart:async' show Future, StreamSubscription;
 
 import 'dart:convert' show JsonEncoder, jsonDecode, utf8;
@@ -51,7 +53,7 @@
 import 'package:front_end/src/fasta/util/textual_outline.dart'
     show textualOutline;
 
-import 'package:kernel/ast.dart' show Component;
+import 'package:kernel/ast.dart' show Component, LibraryPart;
 
 import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
 
@@ -85,12 +87,14 @@
   bool widgetTransformation = false;
   final List<Uri> invalidate = [];
   String targetString = "VM";
+  bool noTryToDeleteEmptyFilesUpFront = false;
   bool oldBlockDelete = false;
   bool lineDelete = false;
   bool byteDelete = false;
   bool askAboutRedirectCrashTarget = false;
   bool autoUncoverAllCrashes = false;
   int stackTraceMatches = 1;
+  String lookForErrorErrorOnReload;
   final Set<String> askedAboutRedirect = {};
   final List<Map<String, dynamic>> fileSystems = [];
   final Set<String> allAutoRedirects = {};
@@ -114,6 +118,7 @@
       'widgetTransformation': widgetTransformation,
       'invalidate': invalidate.map((uri) => uri.toString()).toList(),
       'targetString': targetString,
+      'noTryToDeleteEmptyFilesUpFront': noTryToDeleteEmptyFilesUpFront,
       'oldBlockDelete': oldBlockDelete,
       'lineDelete': lineDelete,
       'byteDelete': byteDelete,
@@ -123,6 +128,7 @@
       'askedAboutRedirect': askedAboutRedirect.toList(),
       'fileSystems': fileSystems,
       'allAutoRedirects': allAutoRedirects.toList(),
+      'lookForErrorErrorOnReload': lookForErrorErrorOnReload,
     };
   }
 
@@ -137,6 +143,7 @@
     invalidate.addAll(
         (json["invalidate"] as List).map((uriString) => Uri.parse(uriString)));
     targetString = json["targetString"];
+    noTryToDeleteEmptyFilesUpFront = json["noTryToDeleteEmptyFilesUpFront"];
     oldBlockDelete = json["oldBlockDelete"];
     lineDelete = json["lineDelete"];
     byteDelete = json["byteDelete"];
@@ -149,11 +156,19 @@
     fileSystems.addAll((json["fileSystems"] as List).cast());
     allAutoRedirects.clear();
     allAutoRedirects.addAll((json["allAutoRedirects"] as List).cast());
+    lookForErrorErrorOnReload = json["lookForErrorErrorOnReload"];
 
     _fsNotInitial.initializeFromJson(fileSystems.removeLast());
   }
 }
 
+// TODO(jensj): The different cuts and inlines in this file aren't tested.
+// The probably should be. So they should probably be factored out so they can
+// be tested and then tested.
+// Similarly the whole +/- 1 thing to cut out what we want is weird and should
+// be factored out into helpers too, or we should have some sort of visitor
+// that can include the "real" numbers (which should then also be tested).
+
 class TestMinimizer {
   final TestMinimizerSettings _settings;
   _FakeFileSystem get _fs => _settings._fs;
@@ -163,6 +178,7 @@
   bool _skip = false;
   bool _check = false;
   int _currentFsNum = -1;
+  bool _gotWantedError = false;
 
   Component _latestComponent;
   IncrementalCompiler _latestCrashingIncrementalCompiler;
@@ -177,7 +193,8 @@
       stdin.echoMode = false;
       stdin.lineMode = false;
     } catch (e) {
-      print("error setting settings on stdin");
+      print("Trying to setup 'stdin' failed. Continuing anyway, "
+          "but 'q', 'i' etc might not work.");
     }
     _stdinSubscription = stdin.listen((List<int> event) {
       if (event.length == 1 && event.single == "q".codeUnits.single) {
@@ -322,20 +339,22 @@
       }
 
       // Try to delete empty files.
-      bool changedSome2 = true;
-      while (changedSome2) {
-        if (await _shouldQuit()) break;
-        changedSome2 = false;
-        for (int i = 0; i < uris.length; i++) {
+      if (!_settings.noTryToDeleteEmptyFilesUpFront) {
+        bool changedSome2 = true;
+        while (changedSome2) {
           if (await _shouldQuit()) break;
-          Uri uri = uris[i];
-          if (_fs.data[uri] == null || _fs.data[uri].isNotEmpty) continue;
-          print("About to work on file $i of ${uris.length}");
-          await _deleteContent(uris, i, false, initialComponent,
-              deleteFile: true);
-          if (_fs.data[uri] == null) {
-            changedSome = true;
-            changedSome2 = true;
+          changedSome2 = false;
+          for (int i = 0; i < uris.length; i++) {
+            if (await _shouldQuit()) break;
+            Uri uri = uris[i];
+            if (_fs.data[uri] == null || _fs.data[uri].isNotEmpty) continue;
+            print("About to work on file $i of ${uris.length}");
+            await _deleteContent(uris, i, false, initialComponent,
+                deleteFile: true);
+            if (_fs.data[uri] == null) {
+              changedSome = true;
+              changedSome2 = true;
+            }
           }
         }
       }
@@ -425,6 +444,15 @@
           }
         }
       }
+
+      // Partially a sanity-check, and partially to make sure there's a latest
+      // component for [_tryToRemoveUnreferencedFileContent] to work with (if
+      // crashing after an invalidation).
+      if (!await _crashesOnCompile(initialComponent)) {
+        throw "At a state where we should crash, we didn't!";
+      }
+      await _tryToRemoveUnreferencedFileContent(initialComponent,
+          deleteFile: true);
     }
 
     if (await _shouldQuit()) {
@@ -544,6 +572,10 @@
           _replaceRange(replacements, originalBytes);
 
       // Step 2: Find the last import/export.
+      // TODO(jensj): This doesn't work if
+      // * The file we're inlining into doesn't have any imports/exports but do
+      //   have a `library` declaration.
+      // * The file we're inlining has a library declaration.
       int offsetOfLast = 0;
       ast = getAST(withoutInlineable,
           includeBody: false,
@@ -689,20 +721,20 @@
 
     // TODO(jensj): don't use full uris.
     print("""
-        # 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.md file.
-        
-        # Reproduce a crash.
-        
-        type: newworld""");
+# 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.
+
+# Reproduce a crash.
+
+type: newworld""");
     if (_settings.widgetTransformation) {
       print("trackWidgetCreation: true");
       print("target: DDC # basically needed for widget creation to be run");
     }
     print("""
-        worlds:
-          - entry: $_mainUri""");
+worlds:
+  - entry: $_mainUri""");
     if (_settings.experimentalInvalidation) {
       print("    experiments: alternative-invalidation-strategy");
     }
@@ -876,9 +908,11 @@
     bool removedSome = false;
     if (await _shouldQuit()) return;
     for (MapEntry<Uri, Uint8List> entry in _fs.data.entries) {
-      if (entry.value == null || entry.value.isEmpty) continue;
+      if (entry.value == null) continue;
+      if (!deleteFile && entry.value.isEmpty) continue;
       if (!entry.key.toString().endsWith(".dart")) continue;
-      if (!neededUris.contains(entry.key) && _fs.data[entry.key].length != 0) {
+      if (!neededUris.contains(entry.key) &&
+          (deleteFile || _fs.data[entry.key].length != 0)) {
         if (deleteFile) {
           _fs.data[entry.key] = null;
         } else {
@@ -1423,6 +1457,10 @@
             }
 
             // Try to remove "extends", "implements" etc.
+            // TODO(jensj): The below removes from the "extends" (etc) until
+            // (but excluding) the "{". This should be improved so it can remove
+            // _one_ part at a time. E:g. if it says "class A implements B, C {"
+            // we could try to remove "B, " or ", C" etc.
             if (decl.getClassExtends().extendsKeyword != null) {
               helper.replacements.add(new _Replacement(
                   decl.getClassExtends().extendsKeyword.offset - 1,
@@ -1728,8 +1766,9 @@
   }
 
   bool _isUriNnbd(Uri uri) {
+    Uri asImportUri = _getImportUri(uri);
     LibraryBuilder libraryBuilder = _latestCrashingIncrementalCompiler
-        .userCode.loader.builders[_getImportUri(uri)];
+        .userCode.loader.builders[asImportUri];
     if (libraryBuilder != null) {
       return libraryBuilder.isNonNullableByDefault;
     }
@@ -1737,17 +1776,25 @@
     for (LibraryBuilder libraryBuilder
         in _latestCrashingIncrementalCompiler.userCode.loader.builders.values) {
       if (libraryBuilder.importUri == uri) {
-        print("Found $uri as ${libraryBuilder.importUri} "
-            "(!= ${_getImportUri(uri)})");
+        print("Found $uri as ${libraryBuilder.importUri} (!= ${asImportUri})");
         return libraryBuilder.isNonNullableByDefault;
       }
+      // Check parts too.
+      for (LibraryPart part in libraryBuilder.library.parts) {
+        Uri thisPartUri = libraryBuilder.importUri.resolve(part.partUri);
+        if (thisPartUri == uri || thisPartUri == asImportUri) {
+          print("Found $uri as part of ${libraryBuilder.importUri}");
+          return libraryBuilder.isNonNullableByDefault;
+        }
+      }
     }
-    // This might be parts?
     throw "Couldn't lookup $uri at all!";
   }
 
   Future<bool> _crashesOnCompile(Component initialComponent) async {
     IncrementalCompiler incrementalCompiler;
+    _gotWantedError = false;
+    bool didNotGetWantedErrorAfterFirstCompile = true;
     if (_settings.noPlatform) {
       incrementalCompiler = new IncrementalCompiler(_setupCompilerContext());
     } else {
@@ -1758,21 +1805,34 @@
     try {
       _latestComponent = await incrementalCompiler.computeDelta();
       if (_settings.serialize) {
+        // We're asked to serialize, probably because it crashes in
+        // serialization.
         ByteSink sink = new ByteSink();
         BinaryPrinter printer = new BinaryPrinter(sink);
         printer.writeComponentFile(_latestComponent);
-        sink.builder.takeBytes();
       }
+
+      if (_gotWantedError) didNotGetWantedErrorAfterFirstCompile = false;
+
       for (Uri uri in _settings.invalidate) {
         incrementalCompiler.invalidate(uri);
         Component delta = await incrementalCompiler.computeDelta();
         if (_settings.serialize) {
+          // We're asked to serialize, probably because it crashes in
+          // serialization.
           ByteSink sink = new ByteSink();
           BinaryPrinter printer = new BinaryPrinter(sink);
           printer.writeComponentFile(delta);
           sink.builder.takeBytes();
         }
       }
+      if (_settings.lookForErrorErrorOnReload != null &&
+          _gotWantedError &&
+          didNotGetWantedErrorAfterFirstCompile) {
+        // We throw here so the "compile crashes"... This is looking for
+        // crashes after-all :)
+        throw "Got the wanted error!";
+      }
       _latestComponent = null; // if it didn't crash this isn't relevant.
       return false;
     } catch (e, st) {
@@ -1879,6 +1939,12 @@
     options.omitPlatform = false;
     options.onDiagnostic = (DiagnosticMessage message) {
       // don't care.
+      // Except if we're looking to trigger a specific error on reload.
+      if (_settings.lookForErrorErrorOnReload != null &&
+          message.ansiFormatted.first
+              .contains(_settings.lookForErrorErrorOnReload)) {
+        _gotWantedError = true;
+      }
     };
     if (_settings.noPlatform) {
       options.librariesSpecificationUri = null;
diff --git a/pkg/front_end/test/deps_test.dart b/pkg/front_end/test/deps_test.dart
index 3bb12a7..c542bc5 100644
--- a/pkg/front_end/test/deps_test.dart
+++ b/pkg/front_end/test/deps_test.dart
@@ -1,3 +1,9 @@
+// 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.md file.
+
+// @dart = 2.9
+
 import 'dart:io';
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart';
diff --git a/pkg/front_end/test/desugar_test.dart b/pkg/front_end/test/desugar_test.dart
index b61a6a7..3ebad1e 100644
--- a/pkg/front_end/test/desugar_test.dart
+++ b/pkg/front_end/test/desugar_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.
 
+// @dart = 2.9
+
 /// Test to ensure that desugaring APIs used by clients like dart2js are
 /// always up to date.
 ///
diff --git a/pkg/front_end/test/dijkstras_sssp_algorithm.dart b/pkg/front_end/test/dijkstras_sssp_algorithm.dart
index b8f9789..0c93386 100644
--- a/pkg/front_end/test/dijkstras_sssp_algorithm.dart
+++ b/pkg/front_end/test/dijkstras_sssp_algorithm.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.9
+
 import 'dart:collection';
 
 /// Dijkstra's algorithm for single source shortest path.
diff --git a/pkg/front_end/test/dill_round_trip_test.dart b/pkg/front_end/test/dill_round_trip_test.dart
index a04c5e1..2842c9e 100644
--- a/pkg/front_end/test/dill_round_trip_test.dart
+++ b/pkg/front_end/test/dill_round_trip_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
 
 import 'package:kernel/ast.dart' show Component;
diff --git a/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart b/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart
index 8887306..85cce5b 100644
--- a/pkg/front_end/test/enable_non_nullable/enable_non_nullable_test.dart
+++ b/pkg/front_end/test/enable_non_nullable/enable_non_nullable_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.md file.
 
+// @dart = 2.9
+
 import 'dart:io';
 
 import 'package:expect/expect.dart';
diff --git a/pkg/front_end/test/explicit_creation_test.dart b/pkg/front_end/test/explicit_creation_test.dart
index 7e8246a..a0378d2 100644
--- a/pkg/front_end/test/explicit_creation_test.dart
+++ b/pkg/front_end/test/explicit_creation_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.
 
+// @dart = 2.9
+
 import 'dart:io';
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart';
diff --git a/pkg/front_end/test/extensions/data/ambiguous/lib1.dart b/pkg/front_end/test/extensions/data/ambiguous/lib1.dart
index 486d104..3e96ec7 100644
--- a/pkg/front_end/test/extensions/data/ambiguous/lib1.dart
+++ b/pkg/front_end/test/extensions/data/ambiguous/lib1.dart
@@ -4,7 +4,11 @@
 
 // @dart = 2.9
 
-/*library: scope=[AmbiguousExtension1,AmbiguousExtension2,UnambiguousExtension1]*/
+/*library: scope=[
+  AmbiguousExtension1,
+  AmbiguousExtension2,
+  UnambiguousExtension1,
+  async.dart.FutureExtensions]*/
 
 /*class: AmbiguousExtension1:
  builder-name=AmbiguousExtension1,
diff --git a/pkg/front_end/test/extensions/data/ambiguous/lib2.dart b/pkg/front_end/test/extensions/data/ambiguous/lib2.dart
index 859fc4c..60dab6f 100644
--- a/pkg/front_end/test/extensions/data/ambiguous/lib2.dart
+++ b/pkg/front_end/test/extensions/data/ambiguous/lib2.dart
@@ -4,7 +4,11 @@
 
 // @dart = 2.9
 
-/*library: scope=[AmbiguousExtension1,AmbiguousExtension2,UnambiguousExtension2]*/
+/*library: scope=[
+  AmbiguousExtension1,
+  AmbiguousExtension2,
+  UnambiguousExtension2,
+  async.dart.FutureExtensions]*/
 
 /*class: AmbiguousExtension1:
  builder-name=AmbiguousExtension1,
diff --git a/pkg/front_end/test/extensions/data/ambiguous/main.dart b/pkg/front_end/test/extensions/data/ambiguous/main.dart
index 7fda5a5..76b412c 100644
--- a/pkg/front_end/test/extensions/data/ambiguous/main.dart
+++ b/pkg/front_end/test/extensions/data/ambiguous/main.dart
@@ -5,13 +5,13 @@
 // @dart = 2.9
 
 /*library: scope=[
- lib1.dart.AmbiguousExtension1,
- lib1.dart.AmbiguousExtension2,
- lib1.dart.UnambiguousExtension1,
- lib2.dart.AmbiguousExtension1,
- lib2.dart.AmbiguousExtension2,
- lib2.dart.UnambiguousExtension2]
-*/
+  async.dart.FutureExtensions,
+  lib1.dart.AmbiguousExtension1,
+  lib1.dart.AmbiguousExtension2,
+  lib1.dart.UnambiguousExtension1,
+  lib2.dart.AmbiguousExtension1,
+  lib2.dart.AmbiguousExtension2,
+  lib2.dart.UnambiguousExtension2]*/
 
 import 'lib1.dart';
 import 'lib2.dart';
diff --git a/pkg/front_end/test/extensions/data/as_show/lib.dart b/pkg/front_end/test/extensions/data/as_show/lib.dart
index 713c232..2511ba6 100644
--- a/pkg/front_end/test/extensions/data/as_show/lib.dart
+++ b/pkg/front_end/test/extensions/data/as_show/lib.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[Extension1]*/
+/*library: scope=[
+  Extension1,
+  async.dart.FutureExtensions]*/
 
 /*class: Extension1:
  builder-name=Extension1,
diff --git a/pkg/front_end/test/extensions/data/as_show/main.dart b/pkg/front_end/test/extensions/data/as_show/main.dart
index f214d01..c65f8c0 100644
--- a/pkg/front_end/test/extensions/data/as_show/main.dart
+++ b/pkg/front_end/test/extensions/data/as_show/main.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[lib.dart.Extension1,origin.dart.Extension2]*/
+/*library: scope=[
+  async.dart.FutureExtensions,
+  lib.dart.Extension1,
+  origin.dart.Extension2]*/
 
 import 'lib.dart' as lib1;
 import 'lib.dart' show Extension1;
diff --git a/pkg/front_end/test/extensions/data/as_show/origin.dart b/pkg/front_end/test/extensions/data/as_show/origin.dart
index 757fd60..abbeee6 100644
--- a/pkg/front_end/test/extensions/data/as_show/origin.dart
+++ b/pkg/front_end/test/extensions/data/as_show/origin.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[Extension2]*/
+/*library: scope=[
+  Extension2,
+  async.dart.FutureExtensions]*/
 
 /*class: Extension2:
  builder-name=Extension2,
diff --git a/pkg/front_end/test/extensions/data/explicit_this.dart b/pkg/front_end/test/extensions/data/explicit_this.dart
index b56b7fc..e1fcd49 100644
--- a/pkg/front_end/test/extensions/data/explicit_this.dart
+++ b/pkg/front_end/test/extensions/data/explicit_this.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2]*/
+/*library: scope=[
+  A2,
+  async.dart.FutureExtensions]*/
 
 class A1 {
   Object field;
diff --git a/pkg/front_end/test/extensions/data/export_twice/lib1.dart b/pkg/front_end/test/extensions/data/export_twice/lib1.dart
index ccfb0b9..14a21cd 100644
--- a/pkg/front_end/test/extensions/data/export_twice/lib1.dart
+++ b/pkg/front_end/test/extensions/data/export_twice/lib1.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[E]*/
+/*library: scope=[
+  E,
+  async.dart.FutureExtensions]*/
 
 class A {}
 
diff --git a/pkg/front_end/test/extensions/data/export_twice/lib2.dart b/pkg/front_end/test/extensions/data/export_twice/lib2.dart
index f52e3cd1..e3d0760 100644
--- a/pkg/front_end/test/extensions/data/export_twice/lib2.dart
+++ b/pkg/front_end/test/extensions/data/export_twice/lib2.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.
 
+/*library: scope=[async.dart.FutureExtensions]*/
+
 // @dart = 2.9
 
 export 'lib1.dart' show E;
diff --git a/pkg/front_end/test/extensions/data/export_twice/main.dart b/pkg/front_end/test/extensions/data/export_twice/main.dart
index 216536b..919a7ff 100644
--- a/pkg/front_end/test/extensions/data/export_twice/main.dart
+++ b/pkg/front_end/test/extensions/data/export_twice/main.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[lib1.dart.E]*/
+/*library: scope=[
+  async.dart.FutureExtensions,
+  lib1.dart.E]*/
 
 import 'lib1.dart';
 import 'lib2.dart';
diff --git a/pkg/front_end/test/extensions/data/export_unnamed/lib.dart b/pkg/front_end/test/extensions/data/export_unnamed/lib.dart
index 17d6f89..b6fab4b 100644
--- a/pkg/front_end/test/extensions/data/export_unnamed/lib.dart
+++ b/pkg/front_end/test/extensions/data/export_unnamed/lib.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[NamedExtension,_extension#0]*/
+/*library: scope=[
+  NamedExtension,
+  _extension#0,
+  async.dart.FutureExtensions]*/
 
 /*class: _extension#0:
  builder-name=_extension#0,
diff --git a/pkg/front_end/test/extensions/data/export_unnamed/main.dart b/pkg/front_end/test/extensions/data/export_unnamed/main.dart
index 132f4bb..5e37c32 100644
--- a/pkg/front_end/test/extensions/data/export_unnamed/main.dart
+++ b/pkg/front_end/test/extensions/data/export_unnamed/main.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[lib.dart.NamedExtension]*/
+/*library: scope=[
+  async.dart.FutureExtensions,
+  lib.dart.NamedExtension]*/
 
 import 'lib.dart';
 
diff --git a/pkg/front_end/test/extensions/data/extension_on_type_variable.dart b/pkg/front_end/test/extensions/data/extension_on_type_variable.dart
index c4a88ce..5f7bb41 100644
--- a/pkg/front_end/test/extensions/data/extension_on_type_variable.dart
+++ b/pkg/front_end/test/extensions/data/extension_on_type_variable.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[GeneralGeneric]*/
+/*library: scope=[
+  GeneralGeneric,
+  async.dart.FutureExtensions]*/
 
 /*class: GeneralGeneric:
  builder-name=GeneralGeneric,
diff --git a/pkg/front_end/test/extensions/data/implicit_this.dart b/pkg/front_end/test/extensions/data/implicit_this.dart
index b50862b..733fb79 100644
--- a/pkg/front_end/test/extensions/data/implicit_this.dart
+++ b/pkg/front_end/test/extensions/data/implicit_this.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2]*/
+/*library: scope=[
+  A2,
+  async.dart.FutureExtensions]*/
 
 class A1 {
   Object field;
diff --git a/pkg/front_end/test/extensions/data/instance_members.dart b/pkg/front_end/test/extensions/data/instance_members.dart
index 3b3f248..6bd7d39 100644
--- a/pkg/front_end/test/extensions/data/instance_members.dart
+++ b/pkg/front_end/test/extensions/data/instance_members.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2,B2]*/
+/*library: scope=[
+  A2,
+  B2,
+  async.dart.FutureExtensions]*/
 
 class A1 {}
 
diff --git a/pkg/front_end/test/extensions/data/named_declarations.dart b/pkg/front_end/test/extensions/data/named_declarations.dart
index ecde7e2..5f7d266 100644
--- a/pkg/front_end/test/extensions/data/named_declarations.dart
+++ b/pkg/front_end/test/extensions/data/named_declarations.dart
@@ -4,7 +4,12 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2,B2,B3,B4]*/
+/*library: scope=[
+  A2,
+  B2,
+  B3,
+  B4,
+  async.dart.FutureExtensions]*/
 
 class A1 {}
 
diff --git a/pkg/front_end/test/extensions/data/other_kinds.dart b/pkg/front_end/test/extensions/data/other_kinds.dart
index 289e358..d38a105 100644
--- a/pkg/front_end/test/extensions/data/other_kinds.dart
+++ b/pkg/front_end/test/extensions/data/other_kinds.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2]*/
+/*library: scope=[
+  A2,
+  async.dart.FutureExtensions]*/
 
 class A1 {
   int _instanceField;
diff --git a/pkg/front_end/test/extensions/data/part/main.dart b/pkg/front_end/test/extensions/data/part/main.dart
new file mode 100644
index 0000000..124b206
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/part/main.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.
+
+/*library: scope=[
+  Extension,
+  _extension#0,
+  async.dart.FutureExtensions]*/
+
+part 'part.dart';
+
+main() {
+  0.intMethod();
+  ''.stringMethod();
+}
diff --git a/pkg/front_end/test/extensions/data/part/part.dart b/pkg/front_end/test/extensions/data/part/part.dart
new file mode 100644
index 0000000..468a7a7
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/part/part.dart
@@ -0,0 +1,55 @@
+// 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 'main.dart';
+
+/*class: Extension:
+ builder-name=Extension,
+ builder-onType=int,
+ extension-members=[
+  intMethod=Extension|intMethod,
+  tearoff intMethod=Extension|get#intMethod],
+ extension-name=Extension,
+ extension-onType=int!
+*/
+extension Extension on int {
+  /*member: Extension|intMethod:
+   builder-name=intMethod,
+   builder-params=[#this],
+   member-name=Extension|intMethod,
+   member-params=[#this]
+  */
+  /*member: Extension|get#intMethod:
+   builder-name=intMethod,
+   builder-params=[#this],
+   member-name=Extension|get#intMethod,
+   member-params=[#this]
+  */
+  intMethod() {}
+}
+
+/*class: _extension#0:
+ builder-name=_extension#0,
+ builder-onType=String,
+ extension-members=[
+  stringMethod=_extension#0|stringMethod,
+  tearoff stringMethod=_extension#0|get#stringMethod],
+ extension-name=_extension#0,
+ extension-onType=String!
+*/
+extension on String {
+  /*member: _extension#0|stringMethod:
+   builder-name=stringMethod,
+   builder-params=[#this],
+   member-name=_extension#0|stringMethod,
+   member-params=[#this]
+  */
+  /*member: _extension#0|get#stringMethod:
+   builder-name=stringMethod,
+   builder-params=[#this],
+   member-name=_extension#0|get#stringMethod,
+   member-params=[#this]
+  */
+  stringMethod() {}
+}
diff --git a/pkg/front_end/test/extensions/data/patching/main.dart b/pkg/front_end/test/extensions/data/patching/main.dart
index 692cfaa..43fab2c 100644
--- a/pkg/front_end/test/extensions/data/patching/main.dart
+++ b/pkg/front_end/test/extensions/data/patching/main.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[origin.dart.Extension,origin.dart.GenericExtension]*/
+/*library: scope=[
+  async.dart.FutureExtensions,
+  origin.dart.Extension,
+  origin.dart.GenericExtension]*/
 
 // ignore: uri_does_not_exist
 import 'dart:test';
diff --git a/pkg/front_end/test/extensions/data/patching/origin.dart b/pkg/front_end/test/extensions/data/patching/origin.dart
index c1c0176..f11eb98 100644
--- a/pkg/front_end/test/extensions/data/patching/origin.dart
+++ b/pkg/front_end/test/extensions/data/patching/origin.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[Extension,GenericExtension]*/
+/*library: scope=[
+  Extension,
+  GenericExtension,
+  async.dart.FutureExtensions]*/
 
 /*class: Extension:
  builder-name=Extension,
diff --git a/pkg/front_end/test/extensions/data/prefix/lib1.dart b/pkg/front_end/test/extensions/data/prefix/lib1.dart
index 3646dda..37dcd3b 100644
--- a/pkg/front_end/test/extensions/data/prefix/lib1.dart
+++ b/pkg/front_end/test/extensions/data/prefix/lib1.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[HiddenExtension1,ShownExtension1]*/
+/*library: scope=[
+  HiddenExtension1,
+  ShownExtension1,
+  async.dart.FutureExtensions]*/
 
 /*class: ShownExtension1:
  builder-name=ShownExtension1,
diff --git a/pkg/front_end/test/extensions/data/prefix/lib2.dart b/pkg/front_end/test/extensions/data/prefix/lib2.dart
index 8affe92..6c32e13 100644
--- a/pkg/front_end/test/extensions/data/prefix/lib2.dart
+++ b/pkg/front_end/test/extensions/data/prefix/lib2.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[HiddenExtension2,ShownExtension2]*/
+/*library: scope=[
+  HiddenExtension2,
+  ShownExtension2,
+  async.dart.FutureExtensions]*/
 
 /*class: HiddenExtension2:
  builder-name=HiddenExtension2,
diff --git a/pkg/front_end/test/extensions/data/prefix/lib3.dart b/pkg/front_end/test/extensions/data/prefix/lib3.dart
index 80105ee..a7245a0 100644
--- a/pkg/front_end/test/extensions/data/prefix/lib3.dart
+++ b/pkg/front_end/test/extensions/data/prefix/lib3.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[ShownExtension3]*/
+/*library: scope=[
+  ShownExtension3,
+  async.dart.FutureExtensions]*/
 
 /*class: ShownExtension3:
  builder-name=ShownExtension3,
diff --git a/pkg/front_end/test/extensions/data/prefix/main.dart b/pkg/front_end/test/extensions/data/prefix/main.dart
index e988aa1..db772d9 100644
--- a/pkg/front_end/test/extensions/data/prefix/main.dart
+++ b/pkg/front_end/test/extensions/data/prefix/main.dart
@@ -5,10 +5,10 @@
 // @dart = 2.9
 
 /*library: scope=[
- lib1.dart.ShownExtension1,
- lib2.dart.ShownExtension2,
- lib3.dart.ShownExtension3]
-*/
+  async.dart.FutureExtensions,
+  lib1.dart.ShownExtension1,
+  lib2.dart.ShownExtension2,
+  lib3.dart.ShownExtension3]*/
 
 import 'lib1.dart' as lib1 show ShownExtension1;
 import 'lib2.dart' as lib2 hide HiddenExtension2;
diff --git a/pkg/front_end/test/extensions/data/reexport/lib.dart b/pkg/front_end/test/extensions/data/reexport/lib.dart
index b787d79..c250d6a 100644
--- a/pkg/front_end/test/extensions/data/reexport/lib.dart
+++ b/pkg/front_end/test/extensions/data/reexport/lib.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.
 
+/*library: scope=[async.dart.FutureExtensions]*/
+
 // @dart = 2.9
 
 export 'lib1.dart';
diff --git a/pkg/front_end/test/extensions/data/reexport/lib1.dart b/pkg/front_end/test/extensions/data/reexport/lib1.dart
index da11a1f..ecf38c5 100644
--- a/pkg/front_end/test/extensions/data/reexport/lib1.dart
+++ b/pkg/front_end/test/extensions/data/reexport/lib1.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[ClashingExtension,UniqueExtension1]*/
+/*library: scope=[
+  ClashingExtension,
+  UniqueExtension1,
+  async.dart.FutureExtensions]*/
 
 /*class: ClashingExtension:
  builder-name=ClashingExtension,
diff --git a/pkg/front_end/test/extensions/data/reexport/lib2.dart b/pkg/front_end/test/extensions/data/reexport/lib2.dart
index e30d364..56e8c50 100644
--- a/pkg/front_end/test/extensions/data/reexport/lib2.dart
+++ b/pkg/front_end/test/extensions/data/reexport/lib2.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[ClashingExtension,UniqueExtension2]*/
+/*library: scope=[
+  ClashingExtension,
+  UniqueExtension2,
+  async.dart.FutureExtensions]*/
 
 /*class: ClashingExtension:
  builder-name=ClashingExtension,
diff --git a/pkg/front_end/test/extensions/data/reexport/main.dart b/pkg/front_end/test/extensions/data/reexport/main.dart
index 1e06107..7238499 100644
--- a/pkg/front_end/test/extensions/data/reexport/main.dart
+++ b/pkg/front_end/test/extensions/data/reexport/main.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[lib1.dart.UniqueExtension1,lib2.dart.UniqueExtension2]*/
+/*library: scope=[
+  async.dart.FutureExtensions,
+  lib1.dart.UniqueExtension1,
+  lib2.dart.UniqueExtension2]*/
 
 import 'lib.dart';
 
diff --git a/pkg/front_end/test/extensions/data/show_hide/lib1.dart b/pkg/front_end/test/extensions/data/show_hide/lib1.dart
index 3646dda..37dcd3b 100644
--- a/pkg/front_end/test/extensions/data/show_hide/lib1.dart
+++ b/pkg/front_end/test/extensions/data/show_hide/lib1.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[HiddenExtension1,ShownExtension1]*/
+/*library: scope=[
+  HiddenExtension1,
+  ShownExtension1,
+  async.dart.FutureExtensions]*/
 
 /*class: ShownExtension1:
  builder-name=ShownExtension1,
diff --git a/pkg/front_end/test/extensions/data/show_hide/lib2.dart b/pkg/front_end/test/extensions/data/show_hide/lib2.dart
index 8affe92..6c32e13 100644
--- a/pkg/front_end/test/extensions/data/show_hide/lib2.dart
+++ b/pkg/front_end/test/extensions/data/show_hide/lib2.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[HiddenExtension2,ShownExtension2]*/
+/*library: scope=[
+  HiddenExtension2,
+  ShownExtension2,
+  async.dart.FutureExtensions]*/
 
 /*class: HiddenExtension2:
  builder-name=HiddenExtension2,
diff --git a/pkg/front_end/test/extensions/data/show_hide/main.dart b/pkg/front_end/test/extensions/data/show_hide/main.dart
index 622bf60..60ba8f4 100644
--- a/pkg/front_end/test/extensions/data/show_hide/main.dart
+++ b/pkg/front_end/test/extensions/data/show_hide/main.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[lib1.dart.ShownExtension1,lib2.dart.ShownExtension2]*/
+/*library: scope=[
+  async.dart.FutureExtensions,
+  lib1.dart.ShownExtension1,
+  lib2.dart.ShownExtension2]*/
 
 import 'lib1.dart' show ShownExtension1;
 import 'lib2.dart' hide HiddenExtension2;
diff --git a/pkg/front_end/test/extensions/data/static_members.dart b/pkg/front_end/test/extensions/data/static_members.dart
index f11b66d..eab1942 100644
--- a/pkg/front_end/test/extensions/data/static_members.dart
+++ b/pkg/front_end/test/extensions/data/static_members.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2,B2]*/
+/*library: scope=[
+  A2,
+  B2,
+  async.dart.FutureExtensions]*/
 
 class A1 {}
 
diff --git a/pkg/front_end/test/extensions/data/super.dart b/pkg/front_end/test/extensions/data/super.dart
index 0123d92..df22e8f 100644
--- a/pkg/front_end/test/extensions/data/super.dart
+++ b/pkg/front_end/test/extensions/data/super.dart
@@ -4,7 +4,9 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2]*/
+/*library: scope=[
+  A2,
+  async.dart.FutureExtensions]*/
 
 class A1 {
   method1() {}
diff --git a/pkg/front_end/test/extensions/data/type_variables.dart b/pkg/front_end/test/extensions/data/type_variables.dart
index e04f82d..8153930 100644
--- a/pkg/front_end/test/extensions/data/type_variables.dart
+++ b/pkg/front_end/test/extensions/data/type_variables.dart
@@ -4,7 +4,11 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2,A3,A4]*/
+/*library: scope=[
+  A2,
+  A3,
+  A4,
+  async.dart.FutureExtensions]*/
 
 class A1<T> {}
 
diff --git a/pkg/front_end/test/extensions/data/unnamed_declarations.dart b/pkg/front_end/test/extensions/data/unnamed_declarations.dart
index 7577c5f..ffa10b4 100644
--- a/pkg/front_end/test/extensions/data/unnamed_declarations.dart
+++ b/pkg/front_end/test/extensions/data/unnamed_declarations.dart
@@ -4,7 +4,13 @@
 
 // @dart = 2.9
 
-/*library: scope=[_extension#0,_extension#1,_extension#2,_extension#3,_extension#4]*/
+/*library: scope=[
+  _extension#0,
+  _extension#1,
+  _extension#2,
+  _extension#3,
+  _extension#4,
+  async.dart.FutureExtensions]*/
 
 class A1 {}
 
diff --git a/pkg/front_end/test/extensions/data/use_as_type.dart b/pkg/front_end/test/extensions/data/use_as_type.dart
index b928105..5cdc007 100644
--- a/pkg/front_end/test/extensions/data/use_as_type.dart
+++ b/pkg/front_end/test/extensions/data/use_as_type.dart
@@ -4,7 +4,10 @@
 
 // @dart = 2.9
 
-/*library: scope=[A2,B2]*/
+/*library: scope=[
+  A2,
+  B2,
+  async.dart.FutureExtensions]*/
 
 class A1 {}
 
diff --git a/pkg/front_end/test/extensions/extensions_test.dart b/pkg/front_end/test/extensions/extensions_test.dart
index 9cf6d7e..5ccb1e8 100644
--- a/pkg/front_end/test/extensions/extensions_test.dart
+++ b/pkg/front_end/test/extensions/extensions_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
diff --git a/pkg/front_end/test/fasta/ambiguous_export_test.dart b/pkg/front_end/test/fasta/ambiguous_export_test.dart
index a1ac89a..b1e492b 100644
--- a/pkg/front_end/test/fasta/ambiguous_export_test.dart
+++ b/pkg/front_end/test/fasta/ambiguous_export_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.md file.
 
+// @dart = 2.9
+
 import 'package:async_helper/async_helper.dart' show asyncTest;
 
 import 'package:expect/expect.dart' show Expect;
@@ -21,7 +23,7 @@
 main() async {
   await asyncTest(() async {
     Library library = new Library(Uri.parse("org.dartlang.fasta:library"));
-    Field field = new Field(new Name("_exports#", library),
+    Field field = new Field.immutable(new Name("_exports#", library),
         initializer: new StringLiteral('{"main":"Problem with main"}'));
     library.addField(field);
     Component component = new Component(libraries: <Library>[library]);
diff --git a/pkg/front_end/test/fasta/analyze_src_with_lints_test.dart b/pkg/front_end/test/fasta/analyze_src_with_lints_test.dart
index 8ede953..652d6b7 100644
--- a/pkg/front_end/test/fasta/analyze_src_with_lints_test.dart
+++ b/pkg/front_end/test/fasta/analyze_src_with_lints_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.
 
+// @dart = 2.9
+
 import "package:testing/src/run_tests.dart" as testing show main;
 
 main() async {
diff --git a/pkg/front_end/test/fasta/analyze_test.dart b/pkg/front_end/test/fasta/analyze_test.dart
index cf52a50..044385e 100644
--- a/pkg/front_end/test/fasta/analyze_test.dart
+++ b/pkg/front_end/test/fasta/analyze_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.
 
+// @dart = 2.9
+
 import "package:testing/src/run_tests.dart" as testing show main;
 
 main() {
diff --git a/pkg/front_end/test/fasta/assert_locations_test.dart b/pkg/front_end/test/fasta/assert_locations_test.dart
index 532b311..c94a1e4 100644
--- a/pkg/front_end/test/fasta/assert_locations_test.dart
+++ b/pkg/front_end/test/fasta/assert_locations_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.md file.
 
+// @dart = 2.9
+
 library fasta.test.assert_locations_test;
 
 import 'package:async_helper/async_helper.dart' show asyncTest;
diff --git a/pkg/front_end/test/fasta/bootstrap_test.dart b/pkg/front_end/test/fasta/bootstrap_test.dart
index f48318a..bc75787 100644
--- a/pkg/front_end/test/fasta/bootstrap_test.dart
+++ b/pkg/front_end/test/fasta/bootstrap_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, File, Platform;
 
 import 'package:async_helper/async_helper.dart' show asyncEnd, asyncStart;
diff --git a/pkg/front_end/test/fasta/expression_suite.dart b/pkg/front_end/test/fasta/expression_suite.dart
index 2b29aa0..ddf7d48 100644
--- a/pkg/front_end/test/fasta/expression_suite.dart
+++ b/pkg/front_end/test/fasta/expression_suite.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.md file.
 
+// @dart = 2.9
+
 library fasta.test.expression_test;
 
 import "dart:convert" show JsonEncoder;
diff --git a/pkg/front_end/test/fasta/fast_strong_suite.dart b/pkg/front_end/test/fasta/fast_strong_suite.dart
index 8a0d844..e4395cb 100644
--- a/pkg/front_end/test/fasta/fast_strong_suite.dart
+++ b/pkg/front_end/test/fasta/fast_strong_suite.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.md file.
 
+// @dart = 2.9
+
 library fasta.test.fast_strong_test;
 
 import 'dart:io' show Platform;
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 3ebb511..6adfa4c 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_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.
 
+// @dart = 2.9
+
 /// Test of toString on generators.
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
diff --git a/pkg/front_end/test/fasta/incremental_expectations.dart b/pkg/front_end/test/fasta/incremental_expectations.dart
index 6ac7b34..9839f4d 100644
--- a/pkg/front_end/test/fasta/incremental_expectations.dart
+++ b/pkg/front_end/test/fasta/incremental_expectations.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.9
+
 library fasta.test.incremental_expectations;
 
 import "dart:convert" show JsonDecoder, JsonEncoder;
diff --git a/pkg/front_end/test/fasta/incremental_hello_test.dart b/pkg/front_end/test/fasta/incremental_hello_test.dart
index f7435f6..4e10f32 100644
--- a/pkg/front_end/test/fasta/incremental_hello_test.dart
+++ b/pkg/front_end/test/fasta/incremental_hello_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.md file.
 
+// @dart = 2.9
+
 library fasta.test.incremental_dynamic_test;
 
 import 'package:async_helper/async_helper.dart' show asyncTest;
diff --git a/pkg/front_end/test/fasta/incremental_source_files.dart b/pkg/front_end/test/fasta/incremental_source_files.dart
index c6d6931..4108b62 100644
--- a/pkg/front_end/test/fasta/incremental_source_files.dart
+++ b/pkg/front_end/test/fasta/incremental_source_files.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.md file.
 
+// @dart = 2.9
+
 library fasta.test.incremental_source_files;
 
 /// Expand a file with diffs in common merge conflict format into a [List] that
diff --git a/pkg/front_end/test/fasta/incremental_suite.dart b/pkg/front_end/test/fasta/incremental_suite.dart
index 46c13e9..0fc4330 100644
--- a/pkg/front_end/test/fasta/incremental_suite.dart
+++ b/pkg/front_end/test/fasta/incremental_suite.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.md file.
 
+// @dart = 2.9
+
 library fasta.test.incremental_test;
 
 import "dart:convert" show JsonEncoder;
diff --git a/pkg/front_end/test/fasta/link_test.dart b/pkg/front_end/test/fasta/link_test.dart
index 1eec73e..a0b7b06 100644
--- a/pkg/front_end/test/fasta/link_test.dart
+++ b/pkg/front_end/test/fasta/link_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/util/link.dart' show Link, LinkBuilder;
 
 import 'package:expect/expect.dart' show Expect;
diff --git a/pkg/front_end/test/fasta/messages_suite.dart b/pkg/front_end/test/fasta/messages_suite.dart
index 9a370f4..9795ed4 100644
--- a/pkg/front_end/test/fasta/messages_suite.dart
+++ b/pkg/front_end/test/fasta/messages_suite.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.9
+
 import "dart:convert" show utf8;
 
 import 'dart:io' show File, Platform;
@@ -26,7 +28,7 @@
 import "package:yaml/yaml.dart" show YamlList, YamlMap, YamlNode, loadYamlNode;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart'
-    show CompilerOptions;
+    show CompilerOptions, InvocationMode;
 
 import 'package:front_end/src/api_prototype/experimental_flags.dart'
     show ExperimentalFlag;
@@ -70,8 +72,9 @@
 
 class Configuration {
   final NnbdMode nnbdMode;
+  final Set<InvocationMode> invocationModes;
 
-  const Configuration(this.nnbdMode);
+  const Configuration(this.nnbdMode, this.invocationModes);
 
   CompilerOptions apply(CompilerOptions options) {
     if (nnbdMode != null) {
@@ -80,10 +83,12 @@
     } else {
       options.explicitExperimentalFlags[ExperimentalFlag.nonNullable] = false;
     }
+    options.invocationModes = invocationModes;
     return options;
   }
 
-  static const Configuration defaultConfiguration = const Configuration(null);
+  static const Configuration defaultConfiguration =
+      const Configuration(null, const {});
 }
 
 class MessageTestSuite extends ChainContext {
@@ -345,12 +350,25 @@
             break;
 
           case "configuration":
-            if (value == "nnbd-weak") {
-              configuration = const Configuration(NnbdMode.Weak);
-            } else if (value == "nnbd-strong") {
-              configuration = const Configuration(NnbdMode.Strong);
-            } else {
-              throw new ArgumentError("Unknown configuration '$value'.");
+            if (value is String) {
+              NnbdMode nnbdMode;
+              Set<InvocationMode> invocationModes = {};
+              for (String part in value.split(',')) {
+                if (part.isEmpty) continue;
+                if (part == "nnbd-weak") {
+                  nnbdMode = NnbdMode.Weak;
+                } else if (part == "nnbd-strong") {
+                  nnbdMode = NnbdMode.Strong;
+                } else {
+                  InvocationMode invocationMode = InvocationMode.fromName(part);
+                  if (invocationMode != null) {
+                    invocationModes.add(invocationMode);
+                  } else {
+                    throw new ArgumentError("Unknown configuration '$part'.");
+                  }
+                }
+              }
+              configuration = new Configuration(nnbdMode, invocationModes);
             }
             break;
 
diff --git a/pkg/front_end/test/fasta/object_supertype_test.dart b/pkg/front_end/test/fasta/object_supertype_test.dart
index 1f37142..d6e0ae6 100644
--- a/pkg/front_end/test/fasta/object_supertype_test.dart
+++ b/pkg/front_end/test/fasta/object_supertype_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.
 
+// @dart = 2.9
+
 import "dart:convert" show json;
 
 import "package:_fe_analyzer_shared/src/messages/diagnostic_message.dart"
diff --git a/pkg/front_end/test/fasta/outline_suite.dart b/pkg/front_end/test/fasta/outline_suite.dart
index 4bb4b58..0c9fbfd 100644
--- a/pkg/front_end/test/fasta/outline_suite.dart
+++ b/pkg/front_end/test/fasta/outline_suite.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.md file.
 
+// @dart = 2.9
+
 library fasta.test.outline_test;
 
 import 'testing/suite.dart';
diff --git a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
index 8e0033f..791ecbe 100644
--- a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/literal_entry_info_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/parser/parser.dart';
 import 'package:_fe_analyzer_shared/src/parser/async_modifier.dart';
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
diff --git a/pkg/front_end/test/fasta/parser/parser_suite.dart b/pkg/front_end/test/fasta/parser/parser_suite.dart
index 8ea1ada..9c9f13a 100644
--- a/pkg/front_end/test/fasta/parser/parser_suite.dart
+++ b/pkg/front_end/test/fasta/parser/parser_suite.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.md file.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
     show ParserError, parse;
 
diff --git a/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart b/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
index 5445a78..3d26339 100644
--- a/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
+++ b/pkg/front_end/test/fasta/parser/token_stream_rewriter_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/parser/token_stream_rewriter.dart';
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ScannerResult, scanString;
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 044da66..a14f5e0 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/parser/parser.dart';
 import 'package:_fe_analyzer_shared/src/parser/type_info.dart';
 import 'package:_fe_analyzer_shared/src/parser/type_info_impl.dart';
@@ -65,7 +67,6 @@
     expectInfo(noType, 'C*', required: false);
     expectInfo(noType, 'C do', required: false);
 
-    expectInfo(noType, 'C.a', required: false);
     expectInfo(noType, 'C.a;', required: false);
     expectInfo(noType, 'C.a(', required: false);
     expectInfo(noType, 'C.a<', required: false);
@@ -73,11 +74,9 @@
     expectInfo(noType, 'C.a*', required: false);
     expectInfo(noType, 'C.a do', required: false);
 
-    expectInfo(noType, 'C<T>', required: false);
     expectInfo(noType, 'C<T>;', required: false);
     expectInfo(noType, 'C<T>(', required: false);
     expectInfo(noType, 'C<T> do', required: false);
-    expectInfo(noType, 'C<void>', required: false);
 
     expectInfo(noType, 'C<T>= foo', required: false);
     expectInfo(noType, 'C<T>= get', required: false);
@@ -97,9 +96,6 @@
     expectInfo(noType, 'C<T>>= operator', required: false);
     expectInfo(noType, 'C<T>>= Function', required: false);
 
-    expectInfo(noType, 'C<S,T>', required: false);
-    expectInfo(noType, 'C<S<T>>', required: false);
-    expectInfo(noType, 'C.a<T>', required: false);
     expectInfo(noType, 'C<S,T>=', required: false);
     expectInfo(noType, 'C<S<T>>=', required: false);
     expectInfo(noType, 'C.a<T>=', required: false);
@@ -235,7 +231,7 @@
 @reflectiveTest
 class PrefixedTypeInfoTest {
   void test_compute() {
-    expectInfo(prefixedType, 'C.a', required: true);
+    expectInfo(prefixedType, 'C.a', required: null /* i.e. both */);
     expectInfo(prefixedType, 'C.a;', required: true);
     expectInfo(prefixedType, 'C.a(', required: true);
     expectInfo(prefixedType, 'C.a<', required: true);
@@ -466,7 +462,7 @@
 @reflectiveTest
 class SimpleTypeWith1ArgumentTest {
   void test_compute_gt() {
-    expectInfo(simpleTypeWith1Argument, 'C<T>', required: true);
+    expectInfo(simpleTypeWith1Argument, 'C<T>', required: null /* i.e. both */);
     expectInfo(simpleTypeWith1Argument, 'C<T>;', required: true);
     expectInfo(simpleTypeWith1Argument, 'C<T>(', required: true);
     expectInfo(simpleTypeWith1Argument, 'C<T> do', required: true);
@@ -949,13 +945,15 @@
   }
 
   void test_computeType_identifierTypeArg() {
-    expectComplexInfo('C<void>', required: true, expectedCalls: [
-      'handleIdentifier C typeReference',
-      'beginTypeArguments <',
-      'handleVoidKeyword void',
-      'endTypeArguments 1 < >',
-      'handleType C null',
-    ]);
+    expectComplexInfo('C<void>',
+        required: null /* i.e. both */,
+        expectedCalls: [
+          'handleIdentifier C typeReference',
+          'beginTypeArguments <',
+          'handleVoidKeyword void',
+          'endTypeArguments 1 < >',
+          'handleType C null',
+        ]);
   }
 
   void test_computeType_identifierTypeArg_questionMark() {
@@ -969,7 +967,7 @@
   }
 
   void test_computeType_identifierTypeArgComplex() {
-    expectComplexInfo('C<S,T>', required: true, expectedCalls: [
+    expectComplexInfo('C<S,T>', required: null /* i.e. both */, expectedCalls: [
       'handleIdentifier C typeReference',
       'beginTypeArguments <',
       'handleIdentifier S typeReference',
@@ -981,19 +979,21 @@
       'endTypeArguments 2 < >',
       'handleType C null',
     ]);
-    expectComplexInfo('C<S<T>>', required: true, expectedCalls: [
-      'handleIdentifier C typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier S typeReference',
-      'beginTypeArguments <',
-      'handleIdentifier T typeReference',
-      'handleNoTypeArguments >',
-      'handleType T null',
-      'endTypeArguments 1 < >',
-      'handleType S null',
-      'endTypeArguments 1 < >',
-      'handleType C null',
-    ]);
+    expectComplexInfo('C<S<T>>',
+        required: null /* i.e. both */,
+        expectedCalls: [
+          'handleIdentifier C typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier S typeReference',
+          'beginTypeArguments <',
+          'handleIdentifier T typeReference',
+          'handleNoTypeArguments >',
+          'handleType T null',
+          'endTypeArguments 1 < >',
+          'handleType S null',
+          'endTypeArguments 1 < >',
+          'handleType C null',
+        ]);
     expectComplexInfo('C<S,T> f', expectedAfter: 'f', expectedCalls: [
       'handleIdentifier C typeReference',
       'beginTypeArguments <',
@@ -1219,8 +1219,7 @@
           error(codeExpectedButGot, 6, 6)
         ]);
 
-    expectInfo(noType, 'C<>', required: false);
-    expectComplexInfo('C<>', required: true, expectedCalls: [
+    expectComplexInfo('C<>', required: null /* i.e. both */, expectedCalls: [
       'handleIdentifier C typeReference',
       'beginTypeArguments <',
       'handleIdentifier  typeReference',
@@ -1341,7 +1340,7 @@
   }
 
   void test_computeType_prefixedTypeArg() {
-    expectComplexInfo('C.a<T>', required: true, expectedCalls: [
+    expectComplexInfo('C.a<T>', required: null /* i.e. both */, expectedCalls: [
       'handleIdentifier C prefixedTypeReference',
       'handleIdentifier a typeReferenceContinuation',
       'handleQualified .',
@@ -2514,6 +2513,8 @@
   }
 }
 
+/// Note that if [required] is null it is run both with required [true] and
+/// [false] and expect the same in both situations.
 void expectComplexInfo(String source,
     {bool required,
     bool inDeclaration = false,
@@ -2687,7 +2688,7 @@
   while (start is ErrorToken) {
     start = start.next;
   }
-  return new SyntheticToken(TokenType.EOF, 0)..setNext(start);
+  return new SyntheticToken(TokenType.EOF, -1)..setNext(start);
 }
 
 int countGtGtAndNullEnd(Token token) {
diff --git a/pkg/front_end/test/fasta/reexport_test.dart b/pkg/front_end/test/fasta/reexport_test.dart
index 62112e0..c754291 100644
--- a/pkg/front_end/test/fasta/reexport_test.dart
+++ b/pkg/front_end/test/fasta/reexport_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.
 
+// @dart = 2.9
+
 import "package:async_helper/async_helper.dart" show asyncTest;
 
 import "package:front_end/src/testing/compiler_common.dart" show compileUnit;
diff --git a/pkg/front_end/test/fasta/scanner/scanner_suite.dart b/pkg/front_end/test/fasta/scanner/scanner_suite.dart
index e71149e..7039a40 100644
--- a/pkg/front_end/test/fasta/scanner/scanner_suite.dart
+++ b/pkg/front_end/test/fasta/scanner/scanner_suite.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.md file.
 
+// @dart = 2.9
+
 import 'package:testing/testing.dart' show Chain, ChainContext, Step, runMe;
 
 import '../../utils/scanner_chain.dart' show Read, Scan;
diff --git a/pkg/front_end/test/fasta/sdk_test.dart b/pkg/front_end/test/fasta/sdk_test.dart
index 27073c4..00d03a6 100644
--- a/pkg/front_end/test/fasta/sdk_test.dart
+++ b/pkg/front_end/test/fasta/sdk_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.md file.
 
+// @dart = 2.9
+
 library fasta.test.sdk_test;
 
 import 'testing/suite.dart';
diff --git a/pkg/front_end/test/fasta/strong1_suite.dart b/pkg/front_end/test/fasta/strong1_suite.dart
index cb30b7e..7fbcb8d 100644
--- a/pkg/front_end/test/fasta/strong1_suite.dart
+++ b/pkg/front_end/test/fasta/strong1_suite.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.md file.
 
+// @dart = 2.9
+
 import 'strong_tester.dart';
 
 main(List<String> arguments) {
diff --git a/pkg/front_end/test/fasta/strong2_suite.dart b/pkg/front_end/test/fasta/strong2_suite.dart
index 10fafaf..311509b 100644
--- a/pkg/front_end/test/fasta/strong2_suite.dart
+++ b/pkg/front_end/test/fasta/strong2_suite.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.md file.
 
+// @dart = 2.9
+
 import 'strong_tester.dart';
 
 main(List<String> arguments) {
diff --git a/pkg/front_end/test/fasta/strong3_suite.dart b/pkg/front_end/test/fasta/strong3_suite.dart
index 044c7e8..5bb5913 100644
--- a/pkg/front_end/test/fasta/strong3_suite.dart
+++ b/pkg/front_end/test/fasta/strong3_suite.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.md file.
 
+// @dart = 2.9
+
 import 'strong_tester.dart';
 
 main(List<String> arguments) {
diff --git a/pkg/front_end/test/fasta/strong4_suite.dart b/pkg/front_end/test/fasta/strong4_suite.dart
index 9e459e3..9db4367 100644
--- a/pkg/front_end/test/fasta/strong4_suite.dart
+++ b/pkg/front_end/test/fasta/strong4_suite.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.md file.
 
+// @dart = 2.9
+
 import 'strong_tester.dart';
 
 main(List<String> arguments) {
diff --git a/pkg/front_end/test/fasta/strong_tester.dart b/pkg/front_end/test/fasta/strong_tester.dart
index 83d9ab3..c514438 100644
--- a/pkg/front_end/test/fasta/strong_tester.dart
+++ b/pkg/front_end/test/fasta/strong_tester.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.md file.
 
+// @dart = 2.9
+
 library fasta.test.strong_test;
 
 import 'dart:io' show Platform;
diff --git a/pkg/front_end/test/fasta/super_mixins_test.dart b/pkg/front_end/test/fasta/super_mixins_test.dart
index c776f0a..ecfe1c9 100644
--- a/pkg/front_end/test/fasta/super_mixins_test.dart
+++ b/pkg/front_end/test/fasta/super_mixins_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.md file.
 
+// @dart = 2.9
+
 library fasta.test.incremental_dynamic_test;
 
 import "package:_fe_analyzer_shared/src/messages/diagnostic_message.dart"
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 44c9145..e5a4357 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.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.md file.
 
+// @dart = 2.9
+
 library fasta.testing.suite;
 
 import 'dart:convert' show jsonDecode;
@@ -50,6 +52,9 @@
 
 import 'package:front_end/src/fasta/dill/dill_target.dart' show DillTarget;
 
+import 'package:front_end/src/fasta/incremental_compiler.dart'
+    show IncrementalCompiler;
+
 import 'package:front_end/src/fasta/kernel/class_hierarchy_builder.dart'
     show ClassHierarchyNode;
 
@@ -188,6 +193,10 @@
   {
     "name": "TextSerializationFailure",
     "group": "Fail"
+  },
+  {
+    "name": "SemiFuzzFailure",
+    "group": "Fail"
   }
 ]
 ''';
@@ -276,6 +285,7 @@
   final bool onlyCrashes;
   final Map<ExperimentalFlag, bool> explicitExperimentalFlags;
   final bool skipVm;
+  final bool semiFuzz;
   final bool verify;
   final bool weak;
   final Map<Component, KernelTarget> componentToTarget =
@@ -295,6 +305,9 @@
   String get updateExpectationsOption => '${UPDATE_EXPECTATIONS}=true';
 
   @override
+  bool get canBeFixWithUpdateExpectations => true;
+
+  @override
   final ExpectationSet expectationSet =
       new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
 
@@ -312,6 +325,7 @@
       this.updateExpectations,
       bool updateComments,
       this.skipVm,
+      this.semiFuzz,
       bool kernelTextSerialization,
       bool fullCompile,
       this.verify,
@@ -371,6 +385,9 @@
         steps.add(const WriteDill());
         steps.add(const Run());
       }
+      if (semiFuzz) {
+        steps.add(const FuzzCompiles());
+      }
     }
   }
 
@@ -699,6 +716,7 @@
     bool updateExpectations = environment[UPDATE_EXPECTATIONS] == "true";
     bool updateComments = environment[UPDATE_COMMENTS] == "true";
     bool skipVm = environment["skipVm"] == "true";
+    bool semiFuzz = environment["semiFuzz"] == "true";
     bool verify = environment["verify"] != "false";
     bool kernelTextSerialization =
         environment.containsKey(KERNEL_TEXT_SERIALIZATION);
@@ -718,6 +736,7 @@
         updateExpectations,
         updateComments,
         skipVm,
+        semiFuzz,
         kernelTextSerialization,
         environment.containsKey(ENABLE_FULL_COMPILE),
         verify,
@@ -725,7 +744,7 @@
   }
 }
 
-class Run extends Step<ComponentResult, int, FastaContext> {
+class Run extends Step<ComponentResult, ComponentResult, FastaContext> {
   const Run();
 
   String get name => "run";
@@ -734,7 +753,8 @@
 
   bool get isRuntime => true;
 
-  Future<Result<int>> run(ComponentResult result, FastaContext context) async {
+  Future<Result<ComponentResult>> run(
+      ComponentResult result, FastaContext context) async {
     FolderOptions folderOptions =
         context.computeFolderOptions(result.description);
     Map<ExperimentalFlag, bool> experimentalFlags = folderOptions
@@ -765,17 +785,18 @@
           // In this case we expect and want a runtime error.
           if (runResult.outcome == ExpectationSet.Default["RuntimeError"]) {
             // We convert this to pass because that's exactly what we'd expect.
-            return pass(0);
+            return pass(result);
           } else {
             // Different outcome - that's a failure!
-            return new Result<int>(runResult.output,
+            return new Result<ComponentResult>(result,
                 ExpectationSet.Default["MissingRuntimeError"], runResult.error);
           }
         }
-        return runResult;
+        return new Result<ComponentResult>(
+            result, runResult.outcome, runResult.error);
       case "none":
       case "noneWithJs":
-        return pass(0);
+        return pass(result);
       default:
         throw new ArgumentError(
             "Unsupported run target '${folderOptions.target}'.");
@@ -957,6 +978,237 @@
   }
 }
 
+class CompilationSetup {
+  final TestOptions testOptions;
+  final FolderOptions folderOptions;
+  final ProcessedOptions options;
+  final List<Iterable<String>> errors;
+  final ProcessedOptions Function(
+          NnbdMode nnbdMode,
+          AllowedExperimentalFlags allowedExperimentalFlags,
+          Map<ExperimentalFlag, Version> experimentEnabledVersion,
+          Map<ExperimentalFlag, Version> experimentReleasedVersion)
+      createProcessedOptions;
+
+  CompilationSetup(this.testOptions, this.folderOptions, this.options,
+      this.errors, this.createProcessedOptions);
+}
+
+CompilationSetup createCompilationSetup(
+    TestDescription description, FastaContext context) {
+  List<Iterable<String>> errors = <Iterable<String>>[];
+
+  Uri librariesSpecificationUri =
+      context.computeLibrariesSpecificationUri(description);
+  TestOptions testOptions = context.computeTestOptions(description);
+  FolderOptions folderOptions = context.computeFolderOptions(description);
+  Map<ExperimentalFlag, bool> experimentalFlags = folderOptions
+      .computeExplicitExperimentalFlags(context.explicitExperimentalFlags);
+  NnbdMode nnbdMode = context.weak ||
+          !isExperimentEnabled(ExperimentalFlag.nonNullable,
+              explicitExperimentalFlags: experimentalFlags)
+      ? NnbdMode.Weak
+      : (folderOptions.nnbdAgnosticMode ? NnbdMode.Agnostic : NnbdMode.Strong);
+  List<Uri> inputs = <Uri>[description.uri];
+
+  ProcessedOptions createProcessedOptions(
+      NnbdMode nnbdMode,
+      AllowedExperimentalFlags allowedExperimentalFlags,
+      Map<ExperimentalFlag, Version> experimentEnabledVersion,
+      Map<ExperimentalFlag, Version> experimentReleasedVersion) {
+    CompilerOptions compilerOptions = new CompilerOptions()
+      ..onDiagnostic = (DiagnosticMessage message) {
+        errors.add(message.plainTextFormatted);
+      }
+      ..environmentDefines = folderOptions.defines
+      ..explicitExperimentalFlags = experimentalFlags
+      ..nnbdMode = nnbdMode
+      ..librariesSpecificationUri = librariesSpecificationUri
+      ..allowedExperimentalFlagsForTesting = allowedExperimentalFlags
+      ..experimentEnabledVersionForTesting = experimentEnabledVersion
+      ..experimentReleasedVersionForTesting = experimentReleasedVersion
+      ..skipPlatformVerification = true
+      ..target = createTarget(folderOptions, context);
+    if (folderOptions.overwriteCurrentSdkVersion != null) {
+      compilerOptions.currentSdkVersion =
+          folderOptions.overwriteCurrentSdkVersion;
+    }
+    return new ProcessedOptions(options: compilerOptions, inputs: inputs);
+  }
+
+  // Disable colors to ensure that expectation files are the same across
+  // platforms and independent of stdin/stderr.
+  colors.enableColors = false;
+
+  ProcessedOptions options = createProcessedOptions(
+      nnbdMode,
+      testOptions.allowedExperimentalFlags,
+      testOptions.experimentEnabledVersion,
+      testOptions.experimentReleasedVersion);
+
+  return new CompilationSetup(
+      testOptions, folderOptions, options, errors, createProcessedOptions);
+}
+
+class FuzzCompiles
+    extends Step<ComponentResult, ComponentResult, FastaContext> {
+  const FuzzCompiles();
+
+  String get name {
+    return "semifuzz";
+  }
+
+  Future<Result<ComponentResult>> run(
+      ComponentResult result, FastaContext context) async {
+    bool originalFlag = context.explicitExperimentalFlags[
+        ExperimentalFlag.alternativeInvalidationStrategy];
+    context.explicitExperimentalFlags[
+        ExperimentalFlag.alternativeInvalidationStrategy] = true;
+
+    CompilationSetup compilationSetup =
+        createCompilationSetup(result.description, context);
+
+    Target backendTarget = compilationSetup.options.target;
+    if (backendTarget is TestVmTarget) {
+      // For the fuzzing we want to run the VM transformations, i.e. have the
+      // incremental compiler behave as normal.
+      backendTarget.enabled = true;
+    }
+
+    UriTranslator uriTranslator =
+        await context.computeUriTranslator(result.description);
+
+    Component platform = await context.loadPlatform();
+    IncrementalCompiler incrementalCompiler =
+        new IncrementalCompiler.fromComponent(
+            new CompilerContext(compilationSetup.options), platform);
+    final Component component = await incrementalCompiler.computeDelta();
+
+    final Set<Uri> userLibraries =
+        createUserLibrariesImportUriSet(component, uriTranslator);
+    final bool expectErrors = compilationSetup.errors.isNotEmpty;
+    List<Iterable<String>> originalErrors =
+        new List<Iterable<String>>.from(compilationSetup.errors);
+
+    Set<Uri> intersectionUserLibraries =
+        result.userLibraries.intersection(userLibraries);
+    if (intersectionUserLibraries.length != userLibraries.length ||
+        userLibraries.length != result.userLibraries.length) {
+      return new Result<ComponentResult>(
+          result,
+          context.expectationSet["SemiFuzzFailure"],
+          "Got a different amount of user libraries on first compile "
+          "compared to 'original' compilation:\n\n"
+          "This compile:\n"
+          "${userLibraries.map((e) => e.toString()).join("\n")}\n\n"
+          "Original compile:\n"
+          "${result.userLibraries.map((e) => e.toString()).join("\n")}");
+    }
+
+    compilationSetup.errors.clear();
+    for (Uri importUri in userLibraries) {
+      incrementalCompiler.invalidate(importUri);
+      final Component newComponent =
+          await incrementalCompiler.computeDelta(fullComponent: true);
+
+      final Set<Uri> newUserLibraries =
+          createUserLibrariesImportUriSet(newComponent, uriTranslator);
+      final bool gotErrors = compilationSetup.errors.isNotEmpty;
+
+      if (expectErrors != gotErrors) {
+        if (expectErrors) {
+          String errorsString =
+              originalErrors.map((error) => error.join('\n')).join('\n\n');
+          return new Result<ComponentResult>(
+              result,
+              context.expectationSet["SemiFuzzFailure"],
+              "Expected these errors:\n${errorsString}\n\n"
+              "but didn't get any after invalidating $importUri");
+        } else {
+          String errorsString = compilationSetup.errors
+              .map((error) => error.join('\n'))
+              .join('\n\n');
+          return new Result<ComponentResult>(
+              result,
+              context.expectationSet["SemiFuzzFailure"],
+              "Unexpected errors:\n${errorsString}\n\n"
+              "after invalidating $importUri");
+        }
+      }
+
+      Set<Uri> intersectionUserLibraries =
+          userLibraries.intersection(newUserLibraries);
+      if (intersectionUserLibraries.length != newUserLibraries.length ||
+          newUserLibraries.length != userLibraries.length) {
+        return new Result<ComponentResult>(
+            result,
+            context.expectationSet["SemiFuzzFailure"],
+            "Got a different amount of user libraries on recompile "
+            "compared to 'original' compilation after having invalidated "
+            "$importUri.\n\n"
+            "This compile:\n"
+            "${newUserLibraries.map((e) => e.toString()).join("\n")}\n\n"
+            "Original compile:\n"
+            "${result.userLibraries.map((e) => e.toString()).join("\n")}");
+      }
+    }
+
+    context.explicitExperimentalFlags[
+        ExperimentalFlag.alternativeInvalidationStrategy] = originalFlag;
+
+    return pass(result);
+  }
+}
+
+Target createTarget(FolderOptions folderOptions, FastaContext context) {
+  TargetFlags targetFlags = new TargetFlags(
+    forceLateLoweringsForTesting: folderOptions.forceLateLowerings,
+    forceLateLoweringSentinelForTesting:
+        folderOptions.forceLateLoweringSentinel,
+    forceStaticFieldLoweringForTesting: folderOptions.forceStaticFieldLowering,
+    forceNoExplicitGetterCallsForTesting:
+        folderOptions.forceNoExplicitGetterCalls,
+    enableNullSafety: !context.weak,
+  );
+  Target target;
+  switch (folderOptions.target) {
+    case "vm":
+      target = new TestVmTarget(targetFlags);
+      break;
+    case "none":
+      target = new NoneTarget(targetFlags);
+      break;
+    case "noneWithJs":
+      target = new NoneWithJsTarget(targetFlags);
+      break;
+    default:
+      throw new ArgumentError(
+          "Unsupported test target '${folderOptions.target}'.");
+  }
+  return target;
+}
+
+Set<Uri> createUserLibrariesImportUriSet(
+    Component component, UriTranslator uriTranslator) {
+  Set<Uri> knownUris =
+      component.libraries.map((Library library) => library.importUri).toSet();
+  Set<Uri> userLibraries = component.libraries
+      .where((Library library) =>
+          library.importUri.scheme != 'dart' &&
+          library.importUri.scheme != 'package')
+      .map((Library library) => library.importUri)
+      .toSet();
+  // Mark custom "dart:" libraries defined in the test-specific libraries.json
+  // file as user libraries.
+  // Note that this method takes a uriTranslator directly because of
+  // inconsistencies with targets (namely that test-specific libraries.json
+  // specifies target 'none' even if the target is 'vm', which works because
+  // the normal testing pipeline use target 'none' for the dill loader).
+  userLibraries.addAll(uriTranslator.dartLibraries.allLibraries
+      .map((LibraryInfo info) => info.importUri));
+  return userLibraries.intersection(knownUris);
+}
+
 class Outline extends Step<TestDescription, ComponentResult, FastaContext> {
   final bool fullCompile;
 
@@ -972,77 +1224,35 @@
 
   Future<Result<ComponentResult>> run(
       TestDescription description, FastaContext context) async {
-    List<Iterable<String>> errors = <Iterable<String>>[];
+    CompilationSetup compilationSetup =
+        createCompilationSetup(description, context);
 
-    Uri librariesSpecificationUri =
-        context.computeLibrariesSpecificationUri(description);
-    TestOptions testOptions = context.computeTestOptions(description);
-    FolderOptions folderOptions = context.computeFolderOptions(description);
-    Map<ExperimentalFlag, bool> experimentalFlags = folderOptions
-        .computeExplicitExperimentalFlags(context.explicitExperimentalFlags);
-    NnbdMode nnbdMode = context.weak ||
-            !isExperimentEnabled(ExperimentalFlag.nonNullable,
-                explicitExperimentalFlags: experimentalFlags)
-        ? NnbdMode.Weak
-        : (folderOptions.nnbdAgnosticMode
-            ? NnbdMode.Agnostic
-            : NnbdMode.Strong);
-    List<Uri> inputs = <Uri>[description.uri];
-
-    ProcessedOptions createProcessedOptions(
-        NnbdMode nnbdMode,
-        AllowedExperimentalFlags allowedExperimentalFlags,
-        Map<ExperimentalFlag, Version> experimentEnabledVersion,
-        Map<ExperimentalFlag, Version> experimentReleasedVersion) {
-      CompilerOptions compilerOptions = new CompilerOptions()
-        ..onDiagnostic = (DiagnosticMessage message) {
-          errors.add(message.plainTextFormatted);
-        }
-        ..environmentDefines = folderOptions.defines
-        ..explicitExperimentalFlags = experimentalFlags
-        ..nnbdMode = nnbdMode
-        ..librariesSpecificationUri = librariesSpecificationUri
-        ..allowedExperimentalFlagsForTesting = allowedExperimentalFlags
-        ..experimentEnabledVersionForTesting = experimentEnabledVersion
-        ..experimentReleasedVersionForTesting = experimentReleasedVersion;
-      if (folderOptions.overwriteCurrentSdkVersion != null) {
-        compilerOptions.currentSdkVersion =
-            folderOptions.overwriteCurrentSdkVersion;
-      }
-      return new ProcessedOptions(options: compilerOptions, inputs: inputs);
-    }
-
-    // Disable colors to ensure that expectation files are the same across
-    // platforms and independent of stdin/stderr.
-    colors.enableColors = false;
-
-    ProcessedOptions options = createProcessedOptions(
-        nnbdMode,
-        testOptions.allowedExperimentalFlags,
-        testOptions.experimentEnabledVersion,
-        testOptions.experimentReleasedVersion);
-
-    if (testOptions.linkDependencies.isNotEmpty &&
-        testOptions.component == null) {
+    if (compilationSetup.testOptions.linkDependencies.isNotEmpty &&
+        compilationSetup.testOptions.component == null) {
       // Compile linked dependency.
-      ProcessedOptions linkOptions = options;
-      if (testOptions.nnbdMode != null) {
-        linkOptions = createProcessedOptions(
-            testOptions.nnbdMode,
-            testOptions.allowedExperimentalFlags,
-            testOptions.experimentEnabledVersion,
-            testOptions.experimentReleasedVersion);
+      ProcessedOptions linkOptions = compilationSetup.options;
+      if (compilationSetup.testOptions.nnbdMode != null) {
+        linkOptions = compilationSetup.createProcessedOptions(
+            compilationSetup.testOptions.nnbdMode,
+            compilationSetup.testOptions.allowedExperimentalFlags,
+            compilationSetup.testOptions.experimentEnabledVersion,
+            compilationSetup.testOptions.experimentReleasedVersion);
       }
       await CompilerContext.runWithOptions(linkOptions, (_) async {
-        KernelTarget sourceTarget = await outlineInitialization(context,
-            description, folderOptions, testOptions.linkDependencies.toList());
-        if (testOptions.errors != null) {
-          errors.addAll(testOptions.errors);
+        KernelTarget sourceTarget = await outlineInitialization(
+            context,
+            description,
+            linkOptions,
+            compilationSetup.testOptions.linkDependencies.toList());
+        if (compilationSetup.testOptions.errors != null) {
+          compilationSetup.errors.addAll(compilationSetup.testOptions.errors);
         }
         Component p = await sourceTarget.buildOutlines();
         if (fullCompile) {
           p = await sourceTarget.buildComponent(
-              verify: folderOptions.noVerify ? false : context.verify);
+              verify: compilationSetup.folderOptions.noVerify
+                  ? false
+                  : context.verify);
         }
 
         // To avoid possible crash in mixin transformation in the transformation
@@ -1062,27 +1272,29 @@
           }
         }
 
-        testOptions.component = p;
+        compilationSetup.testOptions.component = p;
         List<Library> keepLibraries = <Library>[];
         for (Library lib in p.libraries) {
-          if (testOptions.linkDependencies.contains(lib.importUri)) {
+          if (compilationSetup.testOptions.linkDependencies
+              .contains(lib.importUri)) {
             keepLibraries.add(lib);
           }
         }
         p.libraries.clear();
         p.libraries.addAll(keepLibraries);
-        testOptions.errors = errors.toList();
-        errors.clear();
+        compilationSetup.testOptions.errors = compilationSetup.errors.toList();
+        compilationSetup.errors.clear();
       });
     }
 
-    return await CompilerContext.runWithOptions(options, (_) async {
-      Component alsoAppend = testOptions.component;
+    return await CompilerContext.runWithOptions(compilationSetup.options,
+        (_) async {
+      Component alsoAppend = compilationSetup.testOptions.component;
       if (description.uri.pathSegments.last.endsWith(".no_link.dart")) {
         alsoAppend = null;
       }
-      KernelTarget sourceTarget = await outlineInitialization(
-          context, description, folderOptions, <Uri>[description.uri],
+      KernelTarget sourceTarget = await outlineInitialization(context,
+          description, compilationSetup.options, <Uri>[description.uri],
           alsoAppend: alsoAppend);
       ValidatingInstrumentation instrumentation =
           new ValidatingInstrumentation();
@@ -1092,78 +1304,48 @@
       context.componentToTarget.clear();
       context.componentToTarget[p] = sourceTarget;
       context.componentToDiagnostics.clear();
-      context.componentToDiagnostics[p] = errors;
-      Set<Uri> userLibraries = p.libraries
-          .where((Library library) =>
-              library.importUri.scheme != 'dart' &&
-              library.importUri.scheme != 'package')
-          .map((Library library) => library.importUri)
-          .toSet();
-      // Mark custom dart: libraries defined in the test-specific libraries.json
-      // file as user libraries.
-      UriTranslator uriTranslator = sourceTarget.uriTranslator;
-      userLibraries.addAll(uriTranslator.dartLibraries.allLibraries
-          .map((LibraryInfo info) => info.importUri));
+      context.componentToDiagnostics[p] = compilationSetup.errors;
+      Set<Uri> userLibraries =
+          createUserLibrariesImportUriSet(p, sourceTarget.uriTranslator);
       if (fullCompile) {
         p = await sourceTarget.buildComponent(
-            verify: folderOptions.noVerify ? false : context.verify);
+            verify: compilationSetup.folderOptions.noVerify
+                ? false
+                : context.verify);
         instrumentation.finish();
         if (instrumentation.hasProblems) {
           if (updateComments) {
             await instrumentation.fixSource(description.uri, false);
           } else {
             return new Result<ComponentResult>(
-                new ComponentResult(description, p, userLibraries, options,
-                    sourceTarget, sourceTarget.constantCoverageForTesting),
+                new ComponentResult(description, p, userLibraries,
+                    compilationSetup.options, sourceTarget),
                 context.expectationSet["InstrumentationMismatch"],
                 instrumentation.problemsAsString,
-                autoFixCommand: '${UPDATE_COMMENTS}=true');
+                autoFixCommand: '${UPDATE_COMMENTS}=true',
+                canBeFixWithUpdateExpectations: true);
           }
         }
       }
-      return pass(new ComponentResult(description, p, userLibraries, options,
-          sourceTarget, sourceTarget.constantCoverageForTesting));
+      return pass(new ComponentResult(description, p, userLibraries,
+          compilationSetup.options, sourceTarget));
     });
   }
 
   Future<KernelTarget> outlineInitialization(
       FastaContext context,
       TestDescription description,
-      FolderOptions testOptions,
+      ProcessedOptions options,
       List<Uri> entryPoints,
       {Component alsoAppend}) async {
     Component platform = await context.loadPlatform();
     Ticker ticker = new Ticker();
     UriTranslator uriTranslator =
         await context.computeUriTranslator(description);
-    TargetFlags targetFlags = new TargetFlags(
-      forceLateLoweringsForTesting: testOptions.forceLateLowerings,
-      forceLateLoweringSentinelForTesting:
-          testOptions.forceLateLoweringSentinel,
-      forceStaticFieldLoweringForTesting: testOptions.forceStaticFieldLowering,
-      forceNoExplicitGetterCallsForTesting:
-          testOptions.forceNoExplicitGetterCalls,
-      enableNullSafety: !context.weak,
-    );
-    Target target;
-    switch (testOptions.target) {
-      case "vm":
-        target = new TestVmTarget(targetFlags);
-        break;
-      case "none":
-        target = new NoneTarget(targetFlags);
-        break;
-      case "noneWithJs":
-        target = new NoneWithJsTarget(targetFlags);
-        break;
-      default:
-        throw new ArgumentError(
-            "Unsupported test target '${testOptions.target}'.");
-    }
     DillTarget dillTarget = new DillTarget(
       ticker,
       uriTranslator,
-      target,
+      options.target,
     );
     dillTarget.loader.appendLibraries(platform);
     if (alsoAppend != null) {
@@ -1185,30 +1367,32 @@
 
   Future<Result<ComponentResult>> run(
       ComponentResult result, FastaContext context) async {
-    Component component = result.component;
-    KernelTarget sourceTarget = context.componentToTarget[component];
-    context.componentToTarget.remove(component);
-    Target backendTarget = sourceTarget.backendTarget;
-    if (backendTarget is TestVmTarget) {
-      backendTarget.enabled = true;
-    }
-    try {
-      if (sourceTarget.loader.coreTypes != null) {
-        sourceTarget.runBuildTransformations();
-      }
-    } finally {
+    return await CompilerContext.runWithOptions(result.options, (_) async {
+      Component component = result.component;
+      KernelTarget sourceTarget = context.componentToTarget[component];
+      context.componentToTarget.remove(component);
+      Target backendTarget = sourceTarget.backendTarget;
       if (backendTarget is TestVmTarget) {
-        backendTarget.enabled = false;
+        backendTarget.enabled = true;
       }
-    }
-    List<String> errors = VerifyTransformed.verify(component);
-    if (errors.isNotEmpty) {
-      return new Result<ComponentResult>(
-          result,
-          context.expectationSet["TransformVerificationError"],
-          errors.join('\n'));
-    }
-    return pass(result);
+      try {
+        if (sourceTarget.loader.coreTypes != null) {
+          sourceTarget.runBuildTransformations();
+        }
+      } finally {
+        if (backendTarget is TestVmTarget) {
+          backendTarget.enabled = false;
+        }
+      }
+      List<String> errors = VerifyTransformed.verify(component);
+      if (errors.isNotEmpty) {
+        return new Result<ComponentResult>(
+            result,
+            context.expectationSet["TransformVerificationError"],
+            errors.join('\n'));
+      }
+      return pass(result);
+    });
   }
 }
 
diff --git a/pkg/front_end/test/fasta/text_serialization1_suite.dart b/pkg/front_end/test/fasta/text_serialization1_suite.dart
index 1a9ba5e..bccfbcd 100644
--- a/pkg/front_end/test/fasta/text_serialization1_suite.dart
+++ b/pkg/front_end/test/fasta/text_serialization1_suite.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.md file.
 
+// @dart = 2.9
+
 import 'text_serialization_tester.dart';
 
 main(List<String> arguments) {
diff --git a/pkg/front_end/test/fasta/text_serialization2_suite.dart b/pkg/front_end/test/fasta/text_serialization2_suite.dart
index b922a21..8b5b2ca 100644
--- a/pkg/front_end/test/fasta/text_serialization2_suite.dart
+++ b/pkg/front_end/test/fasta/text_serialization2_suite.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.md file.
 
+// @dart = 2.9
+
 import 'text_serialization_tester.dart';
 
 main(List<String> arguments) {
diff --git a/pkg/front_end/test/fasta/text_serialization3_suite.dart b/pkg/front_end/test/fasta/text_serialization3_suite.dart
index f14949c5..682d486 100644
--- a/pkg/front_end/test/fasta/text_serialization3_suite.dart
+++ b/pkg/front_end/test/fasta/text_serialization3_suite.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.md file.
 
+// @dart = 2.9
+
 import 'text_serialization_tester.dart';
 
 main(List<String> arguments) {
diff --git a/pkg/front_end/test/fasta/text_serialization4_suite.dart b/pkg/front_end/test/fasta/text_serialization4_suite.dart
index 9807292..c6043fc 100644
--- a/pkg/front_end/test/fasta/text_serialization4_suite.dart
+++ b/pkg/front_end/test/fasta/text_serialization4_suite.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.md file.
 
+// @dart = 2.9
+
 import 'text_serialization_tester.dart';
 
 main(List<String> arguments) {
diff --git a/pkg/front_end/test/fasta/text_serialization_tester.dart b/pkg/front_end/test/fasta/text_serialization_tester.dart
index 13ee181..25c4081 100644
--- a/pkg/front_end/test/fasta/text_serialization_tester.dart
+++ b/pkg/front_end/test/fasta/text_serialization_tester.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.md file.
 
+// @dart = 2.9
+
 library fasta.test.text_serialization_test;
 
 import 'dart:io' show Platform;
diff --git a/pkg/front_end/test/fasta/textual_outline_suite.dart b/pkg/front_end/test/fasta/textual_outline_suite.dart
index 702b2fc..7688f80 100644
--- a/pkg/front_end/test/fasta/textual_outline_suite.dart
+++ b/pkg/front_end/test/fasta/textual_outline_suite.dart
@@ -2,10 +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.md file.
 
+// @dart = 2.9
+
 library fasta.test.textual_outline_test;
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
+    show ScannerConfiguration;
+
 import 'package:dart_style/dart_style.dart' show DartFormatter;
 
 import 'package:front_end/src/fasta/util/textual_outline.dart';
@@ -56,6 +61,9 @@
   @override
   String get updateExpectationsOption => '${UPDATE_EXPECTATIONS}=true';
 
+  @override
+  bool get canBeFixWithUpdateExpectations => true;
+
   Context(this.updateExpectations);
 
   final List<Step> steps = const <Step>[
@@ -78,7 +86,9 @@
       String result = textualOutline(bytes,
           throwOnUnexpected: true,
           performModelling: modelled,
-          addMarkerForUnknownForTest: modelled);
+          addMarkerForUnknownForTest: modelled,
+          configuration:
+              const ScannerConfiguration(enableExtensionMethods: true));
       if (result == null) {
         return new Result(
             null, context.expectationSet["EmptyOutput"], description.uri);
diff --git a/pkg/front_end/test/fasta/tool_test.dart b/pkg/front_end/test/fasta/tool_test.dart
index fe44a8b..6f77ade 100644
--- a/pkg/front_end/test/fasta/tool_test.dart
+++ b/pkg/front_end/test/fasta/tool_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.
 
+// @dart = 2.9
+
 /// Tests the tool `pkg/front_end/tool/fasta`.
 
 import "dart:io";
diff --git a/pkg/front_end/test/fasta/type_inference/factor_type_test.dart b/pkg/front_end/test/fasta/type_inference/factor_type_test.dart
index f68d6d5..aec0ef1 100644
--- a/pkg/front_end/test/fasta/type_inference/factor_type_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/factor_type_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/flow_analysis/factory_type_test_helper.dart';
 import 'package:expect/expect.dart';
 import 'package:front_end/src/api_prototype/compiler_options.dart';
diff --git a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_nnbd_test.dart b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_nnbd_test.dart
index 9bc5b5d..889f6c6 100644
--- a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_nnbd_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_nnbd_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/type_inference/type_constraint_gatherer.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
diff --git a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
index d690cba..ec32ecf 100644
--- a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/type_inference/type_constraint_gatherer.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
diff --git a/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart b/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
index a804319..1f063e3 100644
--- a/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_inference_engine_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:kernel/ast.dart';
 import 'package:test/test.dart';
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_elimination_nnbd_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_elimination_nnbd_test.dart
index aa491cc..1643d2f 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_elimination_nnbd_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_elimination_nnbd_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/type_inference/type_schema.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart'
     as typeSchemaElimination;
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart
index 3d30f92..55e7235 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_elimination_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_elimination_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/type_inference/type_schema.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart'
     as typeSchemaElimination;
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
index 5818a50..68f81d6 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/type_inference/type_schema.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
index e57d799..7f6b961 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/type_inference/type_schema.dart';
 import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_test.dart
index 8c6f5a2..2891915 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/fasta/type_inference/type_schema.dart';
 import 'package:kernel/ast.dart';
 import 'package:kernel/visitor.dart';
diff --git a/pkg/front_end/test/fasta/types/dart2js_benchmark.dart b/pkg/front_end/test/fasta/types/dart2js_benchmark.dart
index 414a69a..7ef67e3 100644
--- a/pkg/front_end/test/fasta/types/dart2js_benchmark.dart
+++ b/pkg/front_end/test/fasta/types/dart2js_benchmark.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.9
+
 import "dart:io" show Platform;
 
 import "subtypes_benchmark.dart" show run;
diff --git a/pkg/front_end/test/fasta/types/dart2js_benchmark_test.dart b/pkg/front_end/test/fasta/types/dart2js_benchmark_test.dart
index 551647d..b3084ea 100644
--- a/pkg/front_end/test/fasta/types/dart2js_benchmark_test.dart
+++ b/pkg/front_end/test/fasta/types/dart2js_benchmark_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.
 
+// @dart = 2.9
+
 import "dart2js_benchmark.dart" as bench show main;
 
 main() => bench.main();
diff --git a/pkg/front_end/test/fasta/types/dill_hierachy_test.dart b/pkg/front_end/test/fasta/types/dill_hierachy_test.dart
index 3250327..a5bd0e4 100644
--- a/pkg/front_end/test/fasta/types/dill_hierachy_test.dart
+++ b/pkg/front_end/test/fasta/types/dill_hierachy_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.
 
+// @dart = 2.9
+
 import "package:async_helper/async_helper.dart" show asyncTest;
 
 import "package:expect/expect.dart" show Expect;
diff --git a/pkg/front_end/test/fasta/types/fasta_legacy_upper_bound_test.dart b/pkg/front_end/test/fasta/types/fasta_legacy_upper_bound_test.dart
index b1ac139..653a912 100644
--- a/pkg/front_end/test/fasta/types/fasta_legacy_upper_bound_test.dart
+++ b/pkg/front_end/test/fasta/types/fasta_legacy_upper_bound_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.
 
+// @dart = 2.9
+
 import "package:kernel/ast.dart" show DartType, Library;
 
 import "package:kernel/target/targets.dart" show NoneTarget, TargetFlags;
diff --git a/pkg/front_end/test/fasta/types/fasta_types_test.dart b/pkg/front_end/test/fasta/types/fasta_types_test.dart
index bfbde70..25778ab 100644
--- a/pkg/front_end/test/fasta/types/fasta_types_test.dart
+++ b/pkg/front_end/test/fasta/types/fasta_types_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.
 
+// @dart = 2.9
+
 import "package:async_helper/async_helper.dart" show asyncTest;
 
 import "package:kernel/ast.dart" show Component, DartType;
diff --git a/pkg/front_end/test/fasta/types/hashcode_test.dart b/pkg/front_end/test/fasta/types/hashcode_test.dart
index 404d446..e27c2fe 100644
--- a/pkg/front_end/test/fasta/types/hashcode_test.dart
+++ b/pkg/front_end/test/fasta/types/hashcode_test.dart
@@ -1,3 +1,9 @@
+// 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.md file.
+
+// @dart = 2.9
+
 import 'package:expect/expect.dart';
 import 'package:kernel/kernel.dart';
 
diff --git a/pkg/front_end/test/fasta/types/kernel_legacy_upper_bound_test.dart b/pkg/front_end/test/fasta/types/kernel_legacy_upper_bound_test.dart
index e353327..cddafb7 100644
--- a/pkg/front_end/test/fasta/types/kernel_legacy_upper_bound_test.dart
+++ b/pkg/front_end/test/fasta/types/kernel_legacy_upper_bound_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.
 
+// @dart = 2.9
+
 import "legacy_upper_bound_helper.dart" show LegacyUpperBoundTest;
 
 import "package:kernel/ast.dart" show DartType, Library;
diff --git a/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart b/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart
index fef974e..8d54c8a 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser_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.
 
+// @dart = 2.9
+
 import "package:expect/expect.dart" show Expect;
 
 import "package:kernel/ast.dart" show Component, DartType, Library;
diff --git a/pkg/front_end/test/fasta/types/large_app_benchmark.dart b/pkg/front_end/test/fasta/types/large_app_benchmark.dart
index 94a5601..45e9417 100644
--- a/pkg/front_end/test/fasta/types/large_app_benchmark.dart
+++ b/pkg/front_end/test/fasta/types/large_app_benchmark.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.9
+
 import "dart:io" show Platform;
 
 import "subtypes_benchmark.dart" show run;
diff --git a/pkg/front_end/test/fasta/types/large_app_benchmark_test.dart b/pkg/front_end/test/fasta/types/large_app_benchmark_test.dart
index 4dca6c8..4dc83be 100644
--- a/pkg/front_end/test/fasta/types/large_app_benchmark_test.dart
+++ b/pkg/front_end/test/fasta/types/large_app_benchmark_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.
 
+// @dart = 2.9
+
 import "large_app_benchmark.dart" as bench show main;
 
 main() => bench.main();
diff --git a/pkg/front_end/test/fasta/types/legacy_upper_bound_helper.dart b/pkg/front_end/test/fasta/types/legacy_upper_bound_helper.dart
index 5a50c9e..3d4c7d6 100644
--- a/pkg/front_end/test/fasta/types/legacy_upper_bound_helper.dart
+++ b/pkg/front_end/test/fasta/types/legacy_upper_bound_helper.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.9
+
 import "package:async_helper/async_helper.dart" show asyncTest;
 
 import "package:expect/expect.dart" show Expect;
diff --git a/pkg/front_end/test/fasta/types/shared_type_tests.dart b/pkg/front_end/test/fasta/types/shared_type_tests.dart
index fa1d750..fc8f7e3 100644
--- a/pkg/front_end/test/fasta/types/shared_type_tests.dart
+++ b/pkg/front_end/test/fasta/types/shared_type_tests.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.9
+
 import "package:expect/expect.dart" show Expect;
 
 import "package:kernel/type_environment.dart";
diff --git a/pkg/front_end/test/fasta/types/subtypes_benchmark.dart b/pkg/front_end/test/fasta/types/subtypes_benchmark.dart
index 8a81b61..ef6dfb0 100644
--- a/pkg/front_end/test/fasta/types/subtypes_benchmark.dart
+++ b/pkg/front_end/test/fasta/types/subtypes_benchmark.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.9
+
 import "dart:convert" show json, utf8;
 
 import "dart:io" show File, gzip;
diff --git a/pkg/front_end/test/fasta/uri_translator_test.dart b/pkg/front_end/test/fasta/uri_translator_test.dart
index 9d29352..15733f8 100644
--- a/pkg/front_end/test/fasta/uri_translator_test.dart
+++ b/pkg/front_end/test/fasta/uri_translator_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/base/libraries_specification.dart';
 import 'package:front_end/src/fasta/uri_translator.dart';
 import 'package:package_config/package_config.dart';
diff --git a/pkg/front_end/test/fasta/util/direct_parser_ast_test.dart b/pkg/front_end/test/fasta/util/direct_parser_ast_test.dart
index 4f2c82f..aab38dd 100644
--- a/pkg/front_end/test/fasta/util/direct_parser_ast_test.dart
+++ b/pkg/front_end/test/fasta/util/direct_parser_ast_test.dart
@@ -1,3 +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.md file.
+
+// @dart = 2.9
+
 import 'dart:convert';
 import 'dart:io';
 
diff --git a/pkg/front_end/test/fasta/weak_suite.dart b/pkg/front_end/test/fasta/weak_suite.dart
index 604a480..ec9df5e 100644
--- a/pkg/front_end/test/fasta/weak_suite.dart
+++ b/pkg/front_end/test/fasta/weak_suite.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.md file.
 
+// @dart = 2.9
+
 library fasta.test.weak_test;
 
 import 'testing/suite.dart';
diff --git a/pkg/front_end/test/ffi_test.dart b/pkg/front_end/test/ffi_test.dart
index f032f75..b617fa0 100644
--- a/pkg/front_end/test/ffi_test.dart
+++ b/pkg/front_end/test/ffi_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.
 
+// @dart = 2.9
+
 import 'package:expect/expect.dart';
 
 main() {
diff --git a/pkg/front_end/test/flutter_gallery_leak_tester.dart b/pkg/front_end/test/flutter_gallery_leak_tester.dart
index fa3a949..37b66be 100644
--- a/pkg/front_end/test/flutter_gallery_leak_tester.dart
+++ b/pkg/front_end/test/flutter_gallery_leak_tester.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.9
+
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
diff --git a/pkg/front_end/test/hot_reload_e2e_test.dart b/pkg/front_end/test/hot_reload_e2e_test.dart
index d64dcd3..419354b 100644
--- a/pkg/front_end/test/hot_reload_e2e_test.dart
+++ b/pkg/front_end/test/hot_reload_e2e_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.
 
+// @dart = 2.9
+
 /// Integration test that runs the incremental compiler, runs the compiled
 /// program, incrementally rebuild portions of the app, and triggers a hot
 /// reload on the running program.
@@ -37,6 +39,8 @@
 
 import 'package:front_end/src/fasta/hybrid_file_system.dart'
     show HybridFileSystem;
+import 'package:kernel/target/targets.dart';
+import 'package:vm/target/vm.dart';
 
 import 'tool/reload.dart' show RemoteVm;
 
@@ -304,7 +308,9 @@
   var options = new CompilerOptions()
     ..sdkRoot = sdkRoot
     ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
-    ..fileSystem = fs;
+    ..fileSystem = fs
+    ..target = new VmTarget(new TargetFlags())
+    ..environmentDefines = {};
   return new IncrementalKernelGenerator(options, entryUri);
 }
 
diff --git a/pkg/front_end/test/id_testing/data/library_with_name.dart b/pkg/front_end/test/id_testing/data/library_with_name.dart
index cd9b07e..fabca66 100644
--- a/pkg/front_end/test/id_testing/data/library_with_name.dart
+++ b/pkg/front_end/test/id_testing/data/library_with_name.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.9
+
 /*library: file=main.dart,name=lib*/
 library lib;
 
diff --git a/pkg/front_end/test/id_testing/id_testing_test.dart b/pkg/front_end/test/id_testing/id_testing_test.dart
index 6de53f5..590515a 100644
--- a/pkg/front_end/test/id_testing/id_testing_test.dart
+++ b/pkg/front_end/test/id_testing/id_testing_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, StringDataInterpreter, runTests;
diff --git a/pkg/front_end/test/id_tests/assigned_variables_test.dart b/pkg/front_end/test/id_tests/assigned_variables_test.dart
index 51832e2..c74e39b 100644
--- a/pkg/front_end/test/id_tests/assigned_variables_test.dart
+++ b/pkg/front_end/test/id_tests/assigned_variables_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
@@ -71,6 +73,8 @@
   _Data computeMemberValue(Id id, Member member) {
     return new _Data(
         _convertVars(_assignedVariables.declaredAtTopLevel),
+        _convertVars(_assignedVariables.readAnywhere),
+        _convertVars(_assignedVariables.readCapturedAnywhere),
         _convertVars(_assignedVariables.writtenAnywhere),
         _convertVars(_assignedVariables.capturedAnywhere));
   }
@@ -91,6 +95,8 @@
     if (!_assignedVariables.isTracked(alias)) return null;
     return new _Data(
         _convertVars(_assignedVariables.declaredInNode(alias)),
+        _convertVars(_assignedVariables.readInNode(alias)),
+        _convertVars(_assignedVariables.readCapturedInNode(alias)),
         _convertVars(_assignedVariables.writtenInNode(alias)),
         _convertVars(_assignedVariables.capturedInNode(alias)));
   }
@@ -105,6 +111,12 @@
     if (actualData.declared.isNotEmpty) {
       parts.add('declared=${_setToString(actualData.declared)}');
     }
+    if (actualData.read.isNotEmpty) {
+      parts.add('read=${_setToString(actualData.read)}');
+    }
+    if (actualData.readCaptured.isNotEmpty) {
+      parts.add('readCaptured=${_setToString(actualData.readCaptured)}');
+    }
     if (actualData.assigned.isNotEmpty) {
       parts.add('assigned=${_setToString(actualData.assigned)}');
     }
@@ -138,9 +150,14 @@
 class _Data {
   final Set<String> declared;
 
+  final Set<String> read;
+
+  final Set<String> readCaptured;
+
   final Set<String> assigned;
 
   final Set<String> captured;
 
-  _Data(this.declared, this.assigned, this.captured);
+  _Data(this.declared, this.read, this.readCaptured, this.assigned,
+      this.captured);
 }
diff --git a/pkg/front_end/test/id_tests/constant_test.dart b/pkg/front_end/test/id_tests/constant_test.dart
index 8de3c2e..3091acf 100644
--- a/pkg/front_end/test/id_tests/constant_test.dart
+++ b/pkg/front_end/test/id_tests/constant_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
diff --git a/pkg/front_end/test/id_tests/definite_assignment_test.dart b/pkg/front_end/test/id_tests/definite_assignment_test.dart
index 68b66ed..5dd584d 100644
--- a/pkg/front_end/test/id_tests/definite_assignment_test.dart
+++ b/pkg/front_end/test/id_tests/definite_assignment_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
diff --git a/pkg/front_end/test/id_tests/definite_unassignment_test.dart b/pkg/front_end/test/id_tests/definite_unassignment_test.dart
index b22affb..fdc8ce2 100644
--- a/pkg/front_end/test/id_tests/definite_unassignment_test.dart
+++ b/pkg/front_end/test/id_tests/definite_unassignment_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
diff --git a/pkg/front_end/test/id_tests/inheritance_test.dart b/pkg/front_end/test/id_tests/inheritance_test.dart
index f39b8d2..261efa6 100644
--- a/pkg/front_end/test/id_tests/inheritance_test.dart
+++ b/pkg/front_end/test/id_tests/inheritance_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
diff --git a/pkg/front_end/test/id_tests/nullability_test.dart b/pkg/front_end/test/id_tests/nullability_test.dart
index 7b1e603..4980ffb 100644
--- a/pkg/front_end/test/id_tests/nullability_test.dart
+++ b/pkg/front_end/test/id_tests/nullability_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
diff --git a/pkg/front_end/test/id_tests/reachability_test.dart b/pkg/front_end/test/id_tests/reachability_test.dart
index 1cdf867..cf37a57 100644
--- a/pkg/front_end/test/id_tests/reachability_test.dart
+++ b/pkg/front_end/test/id_tests/reachability_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
diff --git a/pkg/front_end/test/id_tests/type_promotion_test.dart b/pkg/front_end/test/id_tests/type_promotion_test.dart
index 5e963c7..1ac5fb3 100644
--- a/pkg/front_end/test/id_tests/type_promotion_test.dart
+++ b/pkg/front_end/test/id_tests/type_promotion_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
diff --git a/pkg/front_end/test/incremental_bulk_compiler_full.dart b/pkg/front_end/test/incremental_bulk_compiler_full.dart
index 03ac980..ac018cb 100644
--- a/pkg/front_end/test/incremental_bulk_compiler_full.dart
+++ b/pkg/front_end/test/incremental_bulk_compiler_full.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.9
+
 import 'package:expect/expect.dart' show Expect;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart'
diff --git a/pkg/front_end/test/incremental_bulk_compiler_smoke_suite.dart b/pkg/front_end/test/incremental_bulk_compiler_smoke_suite.dart
index 28f3352..98f1f3b 100644
--- a/pkg/front_end/test/incremental_bulk_compiler_smoke_suite.dart
+++ b/pkg/front_end/test/incremental_bulk_compiler_smoke_suite.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.9
+
 import 'package:testing/testing.dart' show Chain, runMe;
 
 import 'incremental_bulk_compiler_full.dart' show Context;
diff --git a/pkg/front_end/test/incremental_compiler_leak_test.dart b/pkg/front_end/test/incremental_compiler_leak_test.dart
index 9cefae5..d304ccb 100644
--- a/pkg/front_end/test/incremental_compiler_leak_test.dart
+++ b/pkg/front_end/test/incremental_compiler_leak_test.dart
@@ -1,3 +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.md file.
+
+// @dart = 2.9
+
 import 'dart:async';
 import 'dart:io';
 
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 844ecd5..13eaccb 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
@@ -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.9
+
 import 'dart:io' show Directory, File;
 
 import 'package:expect/expect.dart' show Expect;
diff --git a/pkg/front_end/test/incremental_dart2js_test.dart b/pkg/front_end/test/incremental_dart2js_test.dart
index 1ea9b17..5fef9dc 100644
--- a/pkg/front_end/test/incremental_dart2js_test.dart
+++ b/pkg/front_end/test/incremental_dart2js_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.
 
+// @dart = 2.9
+
 import "incremental_dart2js_tester.dart";
 
 main(List<String> args) async {
diff --git a/pkg/front_end/test/incremental_dart2js_tester.dart b/pkg/front_end/test/incremental_dart2js_tester.dart
index 05b5538..8cadcc1 100644
--- a/pkg/front_end/test/incremental_dart2js_tester.dart
+++ b/pkg/front_end/test/incremental_dart2js_tester.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.9
+
 import "dart:developer";
 import 'dart:io' show Platform;
 
diff --git a/pkg/front_end/test/incremental_flutter_tester.dart b/pkg/front_end/test/incremental_flutter_tester.dart
index 4d2aa12..10bb00e 100644
--- a/pkg/front_end/test/incremental_flutter_tester.dart
+++ b/pkg/front_end/test/incremental_flutter_tester.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.9
+
 import 'dart:io' show Directory, File, exit;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart'
diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart
index 3a00d7e..371df29 100644
--- a/pkg/front_end/test/incremental_load_from_dill_suite.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_suite.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.9
+
 import 'dart:developer' show debugger;
 
 import 'dart:io' show Directory, File;
@@ -831,18 +833,20 @@
       }
 
       if (!noFullComponent) {
-        List<Library> entryLib = component.libraries
-            .where((Library lib) =>
-                entries.contains(lib.importUri) ||
-                entries.contains(lib.fileUri))
-            .toList();
-        if (entryLib.length != entries.length) {
-          return new Result<TestData>(
-              data,
-              UnexpectedEntryToLibraryCount,
-              "Expected the entries to become libraries. "
-              "Got ${entryLib.length} libraries for the expected "
-              "${entries.length} entries.");
+        if (world["checkEntries"] != false) {
+          List<Library> entryLib = component.libraries
+              .where((Library lib) =>
+                  entries.contains(lib.importUri) ||
+                  entries.contains(lib.fileUri))
+              .toList();
+          if (entryLib.length != entries.length) {
+            return new Result<TestData>(
+                data,
+                UnexpectedEntryToLibraryCount,
+                "Expected the entries to become libraries. "
+                "Got ${entryLib.length} libraries for the expected "
+                "${entries.length} entries.");
+          }
         }
       }
       if (compiler.initializedFromDill != expectInitializeFromDill) {
@@ -1120,7 +1124,8 @@
           "${extra}Unexpected serialized representation. "
           "Fix or update $uri to contain the below:\n\n"
           "$actualSerialized",
-          autoFixCommand: "updateExpectations=true");
+          autoFixCommand: "updateExpectations=true",
+          canBeFixWithUpdateExpectations: true);
     }
   }
   return null;
@@ -1202,7 +1207,6 @@
         Set<Member> members = info.lazyDeclaredGettersAndCalls.toSet();
         for (Field f in c.fields) {
           if (f.isStatic) continue;
-          if (!f.hasImplicitGetter) continue;
           if (!members.remove(f)) {
             return new Result<TestData>(
                 data,
@@ -1240,7 +1244,7 @@
         Set<Member> members = info.lazyDeclaredSetters.toSet();
         for (Field f in c.fields) {
           if (f.isStatic) continue;
-          if (!f.hasImplicitSetter) continue;
+          if (!f.hasSetter) continue;
           if (!members.remove(f)) {
             return new Result<TestData>(data, ClassHierarchyError,
                 "Didn't find $f in lazyDeclaredSetters for $c");
@@ -1825,9 +1829,14 @@
         invalidatedUris.map((uri) => uri.pathSegments.last).toSet();
     Set<Uri> result = new Set<Uri>();
     for (Uri uri in invalidatedImportUrisForTesting) {
-      if (uri.pathSegments.last == "nonexisting.dart") continue;
+      if (uri.pathSegments.isNotEmpty &&
+          uri.pathSegments.last == "nonexisting.dart") {
+        continue;
+      }
       if (invalidatedFilenames.contains(entryPoint.pathSegments.last) ||
-          invalidatedFilenames.contains(uri.pathSegments.last)) result.add(uri);
+          invalidatedFilenames.contains(uri.pathSegments.last)) {
+        result.add(uri);
+      }
     }
 
     return result.isEmpty ? null : result;
@@ -1910,13 +1919,10 @@
         .toList()
         .isNotEmpty) continue;
     Name fieldName = new Name("unique_SimulateTransformer");
-    Field field = new Field(fieldName,
+    Field field = new Field.immutable(fieldName,
         isFinal: true,
         getterReference: lib.reference.canonicalName
             ?.getChildFromFieldWithName(fieldName)
-            ?.reference,
-        setterReference: lib.reference.canonicalName
-            ?.getChildFromFieldSetterWithName(fieldName)
             ?.reference);
     lib.addField(field);
     for (Class c in lib.classes) {
@@ -1925,13 +1931,10 @@
           .toList()
           .isNotEmpty) continue;
       fieldName = new Name("unique_SimulateTransformer");
-      field = new Field(fieldName,
+      field = new Field.immutable(fieldName,
           isFinal: true,
           getterReference: c.reference.canonicalName
               ?.getChildFromFieldWithName(fieldName)
-              ?.reference,
-          setterReference: c.reference.canonicalName
-              ?.getChildFromFieldSetterWithName(fieldName)
               ?.reference);
       c.addField(field);
     }
diff --git a/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart b/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart
index 1f8b19a..6f1bc12 100644
--- a/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_invalid_dill_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.
 
+// @dart = 2.9
+
 import 'dart:io' show File;
 
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
diff --git a/pkg/front_end/test/incremental_utils.dart b/pkg/front_end/test/incremental_utils.dart
index f91e823..0d7251b 100644
--- a/pkg/front_end/test/incremental_utils.dart
+++ b/pkg/front_end/test/incremental_utils.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.9
+
 import 'dart:convert' show utf8;
 
 import "package:front_end/src/api_prototype/file_system.dart" show FileSystem;
diff --git a/pkg/front_end/test/issue_34856_test.dart b/pkg/front_end/test/issue_34856_test.dart
index 7e78eb1..8d41b6f 100644
--- a/pkg/front_end/test/issue_34856_test.dart
+++ b/pkg/front_end/test/issue_34856_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.
 
+// @dart = 2.9
+
 import 'dart:io' show File;
 
 import 'package:async_helper/async_helper.dart' show asyncTest;
diff --git a/pkg/front_end/test/kernel_generator_test.dart b/pkg/front_end/test/kernel_generator_test.dart
index 20e3b57..209e853 100644
--- a/pkg/front_end/test/kernel_generator_test.dart
+++ b/pkg/front_end/test/kernel_generator_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.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart'
     show EmptyStatement, Component, ReturnStatement, StaticInvocation;
 
diff --git a/pkg/front_end/test/language_versioning/language_versioning_test.dart b/pkg/front_end/test/language_versioning/language_versioning_test.dart
index b44c90d..912905c 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, File, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:_fe_analyzer_shared/src/testing/features.dart';
diff --git a/pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart b/pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart
index 3e20772..16a442b 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_up_to_date_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_up_to_date_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Platform, Process, ProcessResult;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart';
diff --git a/pkg/front_end/test/lint_suite.dart b/pkg/front_end/test/lint_suite.dart
index 8547196..d5b0da7 100644
--- a/pkg/front_end/test/lint_suite.dart
+++ b/pkg/front_end/test/lint_suite.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.9
+
 import 'dart:io' show Directory, File, FileSystemEntity;
 
 import 'dart:typed_data' show Uint8List;
diff --git a/pkg/front_end/test/member_covariance_test.dart b/pkg/front_end/test/member_covariance_test.dart
index 6f541df..62d44a3 100644
--- a/pkg/front_end/test/member_covariance_test.dart
+++ b/pkg/front_end/test/member_covariance_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.
 
+// @dart = 2.9
+
 import 'package:expect/expect.dart';
 import 'package:front_end/src/fasta/kernel/kernel_ast_api.dart';
 import 'package:front_end/src/fasta/kernel/member_covariance.dart';
diff --git a/pkg/front_end/test/memory_file_system_test.dart b/pkg/front_end/test/memory_file_system_test.dart
index 4364582..802eace7 100644
--- a/pkg/front_end/test/memory_file_system_test.dart
+++ b/pkg/front_end/test/memory_file_system_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 // SharedOptions=--supermixin
 
+// @dart = 2.9
+
 library front_end.test.memory_file_system_test;
 
 import 'dart:convert';
diff --git a/pkg/front_end/test/messages_json_test.dart b/pkg/front_end/test/messages_json_test.dart
index e0f5620..e8fe28a 100644
--- a/pkg/front_end/test/messages_json_test.dart
+++ b/pkg/front_end/test/messages_json_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessage, getMessageUri;
 
@@ -20,8 +22,8 @@
 main() {
   for (int i = 0; i < Severity.values.length; i++) {
     Severity severity = Severity.values[i];
-    Code code = new Code("MyCodeName", null);
-    Message message = new Message(code);
+    Code code = new Code("MyCodeName");
+    Message message = new Message(code, message: '');
     LocatedMessage locatedMessage1 =
         new LocatedMessage(Uri.parse("what:ever/fun_1.dart"), 117, 2, message);
     FormattedMessage formattedMessage2 = new FormattedMessage(
diff --git a/pkg/front_end/test/mixin_export_test.dart b/pkg/front_end/test/mixin_export_test.dart
index bf97cc2..6b75f19 100644
--- a/pkg/front_end/test/mixin_export_test.dart
+++ b/pkg/front_end/test/mixin_export_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.
 
+// @dart = 2.9
+
 import 'package:async_helper/async_helper.dart' show asyncTest;
 
 import 'package:front_end/src/testing/compiler_common.dart';
diff --git a/pkg/front_end/test/packages_format_error_test.dart b/pkg/front_end/test/packages_format_error_test.dart
index 14f97c8..7514228 100644
--- a/pkg/front_end/test/packages_format_error_test.dart
+++ b/pkg/front_end/test/packages_format_error_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessage, getMessageCodeObject;
 
diff --git a/pkg/front_end/test/parser_all_suite.dart b/pkg/front_end/test/parser_all_suite.dart
index 9b60aae..837567f 100644
--- a/pkg/front_end/test/parser_all_suite.dart
+++ b/pkg/front_end/test/parser_all_suite.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.9
+
 import 'package:testing/testing.dart' show Chain, ChainContext, runMe;
 
 import 'parser_suite.dart';
diff --git a/pkg/front_end/test/parser_suite.dart b/pkg/front_end/test/parser_suite.dart
index 8ef6ae8..6221db7 100644
--- a/pkg/front_end/test/parser_suite.dart
+++ b/pkg/front_end/test/parser_suite.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.9
+
 import 'dart:convert' show jsonDecode;
 
 import 'dart:io' show File;
@@ -101,6 +103,9 @@
   @override
   String get updateExpectationsOption => '${UPDATE_EXPECTATIONS}=true';
 
+  @override
+  bool get canBeFixWithUpdateExpectations => true;
+
   final bool addTrace;
   final bool annotateLines;
   final String suiteName;
@@ -452,6 +457,14 @@
     }
   }
 
+  bool checkEof(Token token) {
+    bool result = super.checkEof(token);
+    if (result) {
+      errors.add("WARNING: Reporting at eof --- see below for details.");
+    }
+    return result;
+  }
+
   void handleRecoverableError(
       Message message, Token startToken, Token endToken) {
     if (source != null) {
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index 63a1210..fca16c8 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.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:_fe_analyzer_shared/src/parser/assert.dart';
 import 'package:_fe_analyzer_shared/src/parser/block_kind.dart';
 import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart';
@@ -11,6 +13,7 @@
 import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
 import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+// ignore: import_of_legacy_library_into_null_safe
 import 'package:front_end/src/fasta/messages.dart';
 
 // THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
@@ -50,9 +53,25 @@
     }
   }
 
-  void seen(Token token) {}
+  bool checkEof(Token token) {
+    if (token.isEof) {
+      doPrint("// WARNING: Reporting at eof for $token.");
+      return true;
+    }
+    Token? next = token.next;
+    while (next != null && next.offset == token.offset && !next.isEof) {
+      next = next.next;
+    }
+    if (next != null && next.offset == token.offset && next.isEof) {
+      doPrint("// WARNING: Reporting at the eof offset for $token.");
+      return true;
+    }
+    return false;
+  }
 
-  Uri get uri => null;
+  void seen(Token? token) {}
+
+  Uri? get uri => null;
 
   void logEvent(String name) {
     doPrint('logEvent(' '$name)');
@@ -71,7 +90,7 @@
     doPrint('endArguments(' '$count, ' '$beginToken, ' '$endToken)');
   }
 
-  void handleAsyncModifier(Token asyncToken, Token starToken) {
+  void handleAsyncModifier(Token? asyncToken, Token? starToken) {
     seen(asyncToken);
     seen(starToken);
     doPrint('handleAsyncModifier(' '$asyncToken, ' '$starToken)');
@@ -167,7 +186,7 @@
     indent++;
   }
 
-  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+  void beginClassDeclaration(Token begin, Token? abstractToken, Token name) {
     seen(begin);
     seen(abstractToken);
     seen(name);
@@ -175,20 +194,20 @@
     indent++;
   }
 
-  void handleClassExtends(Token extendsKeyword, int typeCount) {
+  void handleClassExtends(Token? extendsKeyword, int typeCount) {
     seen(extendsKeyword);
     doPrint('handleClassExtends(' '$extendsKeyword, ' '$typeCount)');
   }
 
   void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
+      Token? implementsKeyword, int interfacesCount) {
     seen(implementsKeyword);
     doPrint('handleClassOrMixinImplements('
         '$implementsKeyword, '
         '$interfacesCount)');
   }
 
-  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+  void handleClassHeader(Token begin, Token classKeyword, Token? nativeToken) {
     seen(begin);
     seen(classKeyword);
     seen(nativeToken);
@@ -213,7 +232,7 @@
     indent++;
   }
 
-  void handleMixinOn(Token onKeyword, int typeCount) {
+  void handleMixinOn(Token? onKeyword, int typeCount) {
     seen(onKeyword);
     doPrint('handleMixinOn(' '$onKeyword, ' '$typeCount)');
   }
@@ -246,7 +265,7 @@
     indent++;
   }
 
-  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+  void beginExtensionDeclaration(Token extensionKeyword, Token? name) {
     seen(extensionKeyword);
     seen(name);
     doPrint('beginExtensionDeclaration(' '$extensionKeyword, ' '$name)');
@@ -311,7 +330,7 @@
   }
 
   void endConstructorReference(
-      Token start, Token periodBeforeName, Token endToken) {
+      Token start, Token? periodBeforeName, Token endToken) {
     indent--;
     seen(start);
     seen(periodBeforeName);
@@ -399,7 +418,7 @@
   }
 
   void beginFactoryMethod(
-      Token lastConsumed, Token externalToken, Token constToken) {
+      Token lastConsumed, Token? externalToken, Token? constToken) {
     seen(lastConsumed);
     seen(externalToken);
     seen(constToken);
@@ -446,8 +465,8 @@
         '$endToken)');
   }
 
-  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
-      Token covariantToken, Token varFinalOrConst) {
+  void beginFormalParameter(Token token, MemberKind kind, Token? requiredToken,
+      Token? covariantToken, Token? varFinalOrConst) {
     seen(token);
     seen(requiredToken);
     seen(covariantToken);
@@ -462,11 +481,11 @@
   }
 
   void endFormalParameter(
-      Token thisKeyword,
-      Token periodAfterThis,
+      Token? thisKeyword,
+      Token? periodAfterThis,
       Token nameToken,
-      Token initializerStart,
-      Token initializerEnd,
+      Token? initializerStart,
+      Token? initializerEnd,
       FormalParameterKind kind,
       MemberKind memberKind) {
     indent--;
@@ -509,12 +528,12 @@
   }
 
   void endClassFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -540,12 +559,12 @@
   }
 
   void endMixinFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -571,12 +590,12 @@
   }
 
   void endExtensionFields(
-      Token abstractToken,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? abstractToken,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -653,7 +672,7 @@
     doPrint('endForStatementBody(' '$token)');
   }
 
-  void handleForInLoopParts(Token awaitToken, Token forToken,
+  void handleForInLoopParts(Token? awaitToken, Token forToken,
       Token leftParenthesis, Token inKeyword) {
     seen(awaitToken);
     seen(forToken);
@@ -763,7 +782,7 @@
   }
 
   void endFunctionTypeAlias(
-      Token typedefKeyword, Token equals, Token endToken) {
+      Token typedefKeyword, Token? equals, Token endToken) {
     indent--;
     seen(typedefKeyword);
     seen(equals);
@@ -782,7 +801,7 @@
   }
 
   void beginNamedMixinApplication(
-      Token begin, Token abstractToken, Token name) {
+      Token begin, Token? abstractToken, Token name) {
     seen(begin);
     seen(abstractToken);
     seen(name);
@@ -797,7 +816,7 @@
   }
 
   void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
-      Token implementsKeyword, Token endToken) {
+      Token? implementsKeyword, Token endToken) {
     indent--;
     seen(begin);
     seen(classKeyword);
@@ -845,7 +864,7 @@
     indent++;
   }
 
-  void endIfStatement(Token ifToken, Token elseToken) {
+  void endIfStatement(Token ifToken, Token? elseToken) {
     indent--;
     seen(ifToken);
     seen(elseToken);
@@ -882,20 +901,20 @@
     indent++;
   }
 
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+  void handleImportPrefix(Token? deferredKeyword, Token? asKeyword) {
     seen(deferredKeyword);
     seen(asKeyword);
     doPrint('handleImportPrefix(' '$deferredKeyword, ' '$asKeyword)');
   }
 
-  void endImport(Token importKeyword, Token semicolon) {
+  void endImport(Token importKeyword, Token? semicolon) {
     indent--;
     seen(importKeyword);
     seen(semicolon);
     doPrint('endImport(' '$importKeyword, ' '$semicolon)');
   }
 
-  void handleRecoverImport(Token semicolon) {
+  void handleRecoverImport(Token? semicolon) {
     seen(semicolon);
     doPrint('handleRecoverImport(' '$semicolon)');
   }
@@ -917,7 +936,7 @@
     indent++;
   }
 
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token? equalSign) {
     indent--;
     seen(ifKeyword);
     seen(leftParen);
@@ -1074,7 +1093,7 @@
     indent++;
   }
 
-  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {
+  void handleInterpolationExpression(Token leftBracket, Token? rightBracket) {
     seen(leftBracket);
     seen(rightBracket);
     doPrint('handleInterpolationExpression(' '$leftBracket, ' '$rightBracket)');
@@ -1106,8 +1125,13 @@
     doPrint('endMember()');
   }
 
-  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
-      Token varFinalOrConst, Token getOrSet, Token name) {
+  void beginMethod(
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? varFinalOrConst,
+      Token? getOrSet,
+      Token name) {
     seen(externalToken);
     seen(staticToken);
     seen(covariantToken);
@@ -1124,8 +1148,8 @@
     indent++;
   }
 
-  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1140,8 +1164,8 @@
         '$endToken)');
   }
 
-  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endMixinMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1156,8 +1180,8 @@
         '$endToken)');
   }
 
-  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endExtensionMethod(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1172,8 +1196,8 @@
         '$endToken)');
   }
 
-  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endClassConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1188,8 +1212,8 @@
         '$endToken)');
   }
 
-  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
+  void endMixinConstructor(Token? getOrSet, Token beginToken, Token beginParam,
+      Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1204,8 +1228,8 @@
         '$endToken)');
   }
 
-  void endExtensionConstructor(Token getOrSet, Token beginToken,
-      Token beginParam, Token beginInitializers, Token endToken) {
+  void endExtensionConstructor(Token? getOrSet, Token beginToken,
+      Token beginParam, Token? beginInitializers, Token endToken) {
     indent--;
     seen(getOrSet);
     seen(beginToken);
@@ -1237,7 +1261,7 @@
     indent++;
   }
 
-  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+  void endMetadata(Token beginToken, Token? periodBeforeName, Token endToken) {
     indent--;
     seen(beginToken);
     seen(periodBeforeName);
@@ -1334,7 +1358,7 @@
     doPrint('handleEmptyFunctionBody(' '$semicolon)');
   }
 
-  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
+  void handleExpressionFunctionBody(Token arrowToken, Token? endToken) {
     seen(arrowToken);
     seen(endToken);
     doPrint('handleExpressionFunctionBody(' '$arrowToken, ' '$endToken)');
@@ -1448,11 +1472,11 @@
   }
 
   void endTopLevelFields(
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
+      Token? externalToken,
+      Token? staticToken,
+      Token? covariantToken,
+      Token? lateToken,
+      Token? varFinalOrConst,
       int count,
       Token beginToken,
       Token endToken) {
@@ -1475,14 +1499,14 @@
         '$endToken)');
   }
 
-  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {
+  void beginTopLevelMethod(Token lastConsumed, Token? externalToken) {
     seen(lastConsumed);
     seen(externalToken);
     doPrint('beginTopLevelMethod(' '$lastConsumed, ' '$externalToken)');
     indent++;
   }
 
-  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+  void endTopLevelMethod(Token beginToken, Token? getOrSet, Token endToken) {
     indent--;
     seen(beginToken);
     seen(getOrSet);
@@ -1514,7 +1538,7 @@
     doPrint('endCatchClause(' '$token)');
   }
 
-  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
+  void handleCatchBlock(Token? onKeyword, Token? catchKeyword, Token? comma) {
     seen(onKeyword);
     seen(catchKeyword);
     seen(comma);
@@ -1526,7 +1550,8 @@
     doPrint('handleFinallyBlock(' '$finallyKeyword)');
   }
 
-  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+  void endTryStatement(
+      int catchCount, Token tryKeyword, Token? finallyKeyword) {
     indent--;
     seen(tryKeyword);
     seen(finallyKeyword);
@@ -1534,7 +1559,7 @@
         'endTryStatement(' '$catchCount, ' '$tryKeyword, ' '$finallyKeyword)');
   }
 
-  void handleType(Token beginToken, Token questionMark) {
+  void handleType(Token beginToken, Token? questionMark) {
     seen(beginToken);
     seen(questionMark);
     doPrint('handleType(' '$beginToken, ' '$questionMark)');
@@ -1556,7 +1581,7 @@
     indent++;
   }
 
-  void endFunctionType(Token functionToken, Token questionMark) {
+  void endFunctionType(Token functionToken, Token? questionMark) {
     indent--;
     seen(functionToken);
     seen(questionMark);
@@ -1598,7 +1623,7 @@
   }
 
   void endTypeVariable(
-      Token token, int index, Token extendsOrSuper, Token variance) {
+      Token token, int index, Token? extendsOrSuper, Token? variance) {
     indent--;
     seen(token);
     seen(extendsOrSuper);
@@ -1623,7 +1648,7 @@
     doPrint('endTypeVariables(' '$beginToken, ' '$endToken)');
   }
 
-  void reportVarianceModifierNotEnabled(Token variance) {
+  void reportVarianceModifierNotEnabled(Token? variance) {
     seen(variance);
     doPrint('reportVarianceModifierNotEnabled(' '$variance)');
   }
@@ -1642,7 +1667,7 @@
   }
 
   void beginVariablesDeclaration(
-      Token token, Token lateToken, Token varFinalOrConst) {
+      Token token, Token? lateToken, Token? varFinalOrConst) {
     seen(token);
     seen(lateToken);
     seen(varFinalOrConst);
@@ -1653,7 +1678,7 @@
     indent++;
   }
 
-  void endVariablesDeclaration(int count, Token endToken) {
+  void endVariablesDeclaration(int count, Token? endToken) {
     indent--;
     seen(endToken);
     doPrint('endVariablesDeclaration(' '$count, ' '$endToken)');
@@ -1740,7 +1765,7 @@
     doPrint('endConstExpression(' '$token)');
   }
 
-  void beginForControlFlow(Token awaitToken, Token forToken) {
+  void beginForControlFlow(Token? awaitToken, Token forToken) {
     seen(awaitToken);
     seen(forToken);
     doPrint('beginForControlFlow(' '$awaitToken, ' '$forToken)');
@@ -1798,7 +1823,7 @@
     indent++;
   }
 
-  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
+  void endFunctionTypedFormalParameter(Token nameToken, Token? question) {
     indent--;
     seen(nameToken);
     seen(question);
@@ -1811,7 +1836,7 @@
   }
 
   void handleIndexedExpression(
-      Token question, Token openSquareBracket, Token closeSquareBracket) {
+      Token? question, Token openSquareBracket, Token closeSquareBracket) {
     seen(question);
     seen(openSquareBracket);
     seen(closeSquareBracket);
@@ -1833,7 +1858,7 @@
     doPrint('endIsOperatorType(' '$operator)');
   }
 
-  void handleIsOperator(Token isOperator, Token not) {
+  void handleIsOperator(Token isOperator, Token? not) {
     seen(isOperator);
     seen(not);
     doPrint('handleIsOperator(' '$isOperator, ' '$not)');
@@ -1874,7 +1899,7 @@
   }
 
   void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
-      Token commaToken, Token semicolonToken) {
+      Token? commaToken, Token semicolonToken) {
     indent--;
     seen(assertKeyword);
     seen(leftParenthesis);
@@ -1899,7 +1924,7 @@
   }
 
   void handleLiteralList(
-      int count, Token leftBracket, Token constKeyword, Token rightBracket) {
+      int count, Token leftBracket, Token? constKeyword, Token rightBracket) {
     seen(leftBracket);
     seen(constKeyword);
     seen(rightBracket);
@@ -1913,7 +1938,7 @@
   void handleLiteralSetOrMap(
     int count,
     Token leftBrace,
-    Token constKeyword,
+    Token? constKeyword,
     Token rightBrace,
     bool hasSetEntry,
   ) {
@@ -2033,8 +2058,8 @@
   void endSwitchCase(
       int labelCount,
       int expressionCount,
-      Token defaultKeyword,
-      Token colonAfterDefault,
+      Token? defaultKeyword,
+      Token? colonAfterDefault,
       int statementCount,
       Token firstToken,
       Token endToken) {
@@ -2110,7 +2135,7 @@
     indent++;
   }
 
-  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+  void endYieldStatement(Token yieldToken, Token? starToken, Token endToken) {
     indent--;
     seen(yieldToken);
     seen(starToken);
@@ -2118,7 +2143,7 @@
     doPrint('endYieldStatement(' '$yieldToken, ' '$starToken, ' '$endToken)');
   }
 
-  void endInvalidYieldStatement(Token beginToken, Token starToken,
+  void endInvalidYieldStatement(Token beginToken, Token? starToken,
       Token endToken, MessageCode errorCode) {
     indent--;
     seen(beginToken);
@@ -2137,6 +2162,7 @@
     seen(endToken);
     doPrint(
         'handleRecoverableError(' '$message, ' '$startToken, ' '$endToken)');
+    checkEof(endToken);
   }
 
   void handleErrorToken(ErrorToken token) {
@@ -2170,7 +2196,7 @@
   }
 
   void handleCommentReference(
-      Token newKeyword, Token prefix, Token period, Token token) {
+      Token? newKeyword, Token? prefix, Token? period, Token token) {
     seen(newKeyword);
     seen(prefix);
     seen(period);
diff --git a/pkg/front_end/test/parser_test_listener_creator.dart b/pkg/front_end/test/parser_test_listener_creator.dart
index 1acfac3..787e7f6 100644
--- a/pkg/front_end/test/parser_test_listener_creator.dart
+++ b/pkg/front_end/test/parser_test_listener_creator.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.9
+
 import 'dart:io';
 import 'dart:typed_data';
 
@@ -37,6 +39,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:_fe_analyzer_shared/src/parser/assert.dart';
 import 'package:_fe_analyzer_shared/src/parser/block_kind.dart';
 import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart';
@@ -46,6 +50,7 @@
 import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
 import 'package:_fe_analyzer_shared/src/scanner/error_token.dart';
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+// ignore: import_of_legacy_library_into_null_safe
 import 'package:front_end/src/fasta/messages.dart';
 
 // THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
@@ -85,7 +90,23 @@
     }
   }
 
-  void seen(Token token) {}
+  bool checkEof(Token token) {
+    if (token.isEof) {
+      doPrint("// WARNING: Reporting at eof for $token.");
+      return true;
+    }
+    Token? next = token.next;
+    while (next != null && next.offset == token.offset && !next.isEof) {
+      next = next.next;
+    }
+    if (next != null && next.offset == token.offset && next.isEof) {
+      doPrint("// WARNING: Reporting at the eof offset for $token.");
+      return true;
+    }
+    return false;
+  }
+
+  void seen(Token? token) {}
 
 """);
 
@@ -178,6 +199,9 @@
           // It redirects to give an error message, so also do that here.
           out.write("  handleRecoverableError("
               "token.assertionMessage, token, token);");
+        } else if (currentMethodName == "handleRecoverableError") {
+          // Check for reporting on eof.
+          out.write("checkEof(endToken);");
         }
 
         out.write("}");
diff --git a/pkg/front_end/test/parser_test_parser.dart b/pkg/front_end/test/parser_test_parser.dart
index 8033a37..fd3ed9b 100644
--- a/pkg/front_end/test/parser_test_parser.dart
+++ b/pkg/front_end/test/parser_test_parser.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.9
+
 import 'package:_fe_analyzer_shared/src/parser/assert.dart';
 import 'package:_fe_analyzer_shared/src/parser/block_kind.dart';
 import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart';
diff --git a/pkg/front_end/test/parser_test_parser_creator.dart b/pkg/front_end/test/parser_test_parser_creator.dart
index aa1e573..d1ab0c5 100644
--- a/pkg/front_end/test/parser_test_parser_creator.dart
+++ b/pkg/front_end/test/parser_test_parser_creator.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.9
+
 import 'dart:io';
 import 'dart:typed_data';
 
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index 9e5e116..e22e19f 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 
 import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
diff --git a/pkg/front_end/test/precedence_info_test.dart b/pkg/front_end/test/precedence_info_test.dart
index 61244aa..fd88c3e 100644
--- a/pkg/front_end/test/precedence_info_test.dart
+++ b/pkg/front_end/test/precedence_info_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
 import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
     show AbstractScanner;
diff --git a/pkg/front_end/test/predicates/data/late.dart b/pkg/front_end/test/predicates/data/late.dart
index 55cfbb6..ebf4162 100644
--- a/pkg/front_end/test/predicates/data/late.dart
+++ b/pkg/front_end/test/predicates/data/late.dart
@@ -2,184 +2,842 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*member: _#topLevelNonNullableWithoutInitializer:lateField*/
-/*member: topLevelNonNullableWithoutInitializer:lateFieldGetter*/
-/*member: topLevelNonNullableWithoutInitializer=:lateFieldSetter*/
-/*member: _#topLevelNonNullableWithoutInitializer#isSet:lateIsSetField*/
+/*member: _#topLevelNonNullableWithoutInitializer:
+ lateField,
+ lateFieldName=topLevelNonNullableWithoutInitializer,
+ lateFieldTarget=_#topLevelNonNullableWithoutInitializer
+*/
+/*member: topLevelNonNullableWithoutInitializer:
+ lateFieldGetter,
+ lateFieldName=topLevelNonNullableWithoutInitializer,
+ lateFieldTarget=_#topLevelNonNullableWithoutInitializer
+*/
+/*member: topLevelNonNullableWithoutInitializer=:
+ lateFieldName=topLevelNonNullableWithoutInitializer,
+ lateFieldSetter,
+ lateFieldTarget=_#topLevelNonNullableWithoutInitializer
+*/
 late int topLevelNonNullableWithoutInitializer;
-/*member: _#finalTopLevelNonNullableWithoutInitializer:lateField*/
-/*member: finalTopLevelNonNullableWithoutInitializer:lateFieldGetter*/
-/*member: finalTopLevelNonNullableWithoutInitializer=:lateFieldSetter*/
-/*member: _#finalTopLevelNonNullableWithoutInitializer#isSet:lateIsSetField*/
+/*member: _#finalTopLevelNonNullableWithoutInitializer:
+ lateField,
+ lateFieldName=finalTopLevelNonNullableWithoutInitializer,
+ lateFieldTarget=_#finalTopLevelNonNullableWithoutInitializer
+*/
+/*member: finalTopLevelNonNullableWithoutInitializer:
+ lateFieldGetter,
+ lateFieldName=finalTopLevelNonNullableWithoutInitializer,
+ lateFieldTarget=_#finalTopLevelNonNullableWithoutInitializer
+*/
+/*member: finalTopLevelNonNullableWithoutInitializer=:
+ lateFieldName=finalTopLevelNonNullableWithoutInitializer,
+ lateFieldSetter,
+ lateFieldTarget=_#finalTopLevelNonNullableWithoutInitializer
+*/
 late final int finalTopLevelNonNullableWithoutInitializer;
-/*member: _#topLevelNullableWithoutInitializer:lateField*/
-/*member: _#topLevelNullableWithoutInitializer#isSet:lateIsSetField*/
-/*member: topLevelNullableWithoutInitializer:lateFieldGetter*/
-/*member: topLevelNullableWithoutInitializer=:lateFieldSetter*/
+/*member: _#topLevelNullableWithoutInitializer:
+ lateField,
+ lateFieldName=topLevelNullableWithoutInitializer,
+ lateFieldTarget=_#topLevelNullableWithoutInitializer
+*/
+/*is-null.member: _#topLevelNullableWithoutInitializer#isSet:
+ lateFieldName=topLevelNullableWithoutInitializer,
+ lateFieldTarget=_#topLevelNullableWithoutInitializer,
+ lateIsSetField
+*/
+/*member: topLevelNullableWithoutInitializer:
+ lateFieldGetter,
+ lateFieldName=topLevelNullableWithoutInitializer,
+ lateFieldTarget=_#topLevelNullableWithoutInitializer
+*/
+/*member: topLevelNullableWithoutInitializer=:
+ lateFieldName=topLevelNullableWithoutInitializer,
+ lateFieldSetter,
+ lateFieldTarget=_#topLevelNullableWithoutInitializer
+*/
 late int? topLevelNullableWithoutInitializer;
-/*member: _#finalTopLevelNullableWithoutInitializer:lateField*/
-/*member: _#finalTopLevelNullableWithoutInitializer#isSet:lateIsSetField*/
-/*member: finalTopLevelNullableWithoutInitializer:lateFieldGetter*/
-/*member: finalTopLevelNullableWithoutInitializer=:lateFieldSetter*/
+/*member: _#finalTopLevelNullableWithoutInitializer:
+ lateField,
+ lateFieldName=finalTopLevelNullableWithoutInitializer,
+ lateFieldTarget=_#finalTopLevelNullableWithoutInitializer
+*/
+/*is-null.member: _#finalTopLevelNullableWithoutInitializer#isSet:
+ lateFieldName=finalTopLevelNullableWithoutInitializer,
+ lateFieldTarget=_#finalTopLevelNullableWithoutInitializer,
+ lateIsSetField
+*/
+/*member: finalTopLevelNullableWithoutInitializer:
+ lateFieldGetter,
+ lateFieldName=finalTopLevelNullableWithoutInitializer,
+ lateFieldTarget=_#finalTopLevelNullableWithoutInitializer
+*/
+/*member: finalTopLevelNullableWithoutInitializer=:
+ lateFieldName=finalTopLevelNullableWithoutInitializer,
+ lateFieldSetter,
+ lateFieldTarget=_#finalTopLevelNullableWithoutInitializer
+*/
 late final int? finalTopLevelNullableWithoutInitializer;
-/*member: _#topLevelNonNullableWithInitializer:lateField*/
-/*member: topLevelNonNullableWithInitializer:lateFieldGetter*/
-/*member: topLevelNonNullableWithInitializer=:lateFieldSetter*/
-/*member: _#topLevelNonNullableWithInitializer#isSet:lateIsSetField*/
-late int topLevelNonNullableWithInitializer = 0;
-/*member: _#finalTopLevelNonNullableWithInitializer:lateField*/
-/*member: finalTopLevelNonNullableWithInitializer:lateFieldGetter*/
-/*member: _#finalTopLevelNonNullableWithInitializer#isSet:lateIsSetField*/
-late final int finalTopLevelNonNullableWithInitializer = 0;
-/*member: _#topLevelNullableWithInitializer:lateField*/
-/*member: _#topLevelNullableWithInitializer#isSet:lateIsSetField*/
-/*member: topLevelNullableWithInitializer:lateFieldGetter*/
-/*member: topLevelNullableWithInitializer=:lateFieldSetter*/
-late int? topLevelNullableWithInitializer = 0;
-/*member: _#finalTopLevelNullableWithInitializer:lateField*/
-/*member: _#finalTopLevelNullableWithInitializer#isSet:lateIsSetField*/
-/*member: finalTopLevelNullableWithInitializer:lateFieldGetter*/
-late final int? finalTopLevelNullableWithInitializer = 0;
+/*member: _#topLevelNonNullableWithInitializer:
+ lateField,
+ lateFieldInitializer=1,
+ lateFieldName=topLevelNonNullableWithInitializer,
+ lateFieldTarget=_#topLevelNonNullableWithInitializer
+*/
+/*member: topLevelNonNullableWithInitializer:
+ lateFieldGetter,
+ lateFieldInitializer=1,
+ lateFieldName=topLevelNonNullableWithInitializer,
+ lateFieldTarget=_#topLevelNonNullableWithInitializer
+*/
+/*member: topLevelNonNullableWithInitializer=:
+ lateFieldInitializer=1,
+ lateFieldName=topLevelNonNullableWithInitializer,
+ lateFieldSetter,
+ lateFieldTarget=_#topLevelNonNullableWithInitializer
+*/
+late int topLevelNonNullableWithInitializer = 1;
+/*member: _#finalTopLevelNonNullableWithInitializer:
+ lateField,
+ lateFieldInitializer=2,
+ lateFieldName=finalTopLevelNonNullableWithInitializer,
+ lateFieldTarget=_#finalTopLevelNonNullableWithInitializer
+*/
+/*member: finalTopLevelNonNullableWithInitializer:
+ lateFieldGetter,
+ lateFieldInitializer=2,
+ lateFieldName=finalTopLevelNonNullableWithInitializer,
+ lateFieldTarget=_#finalTopLevelNonNullableWithInitializer
+*/
+late final int finalTopLevelNonNullableWithInitializer = 2;
+/*member: _#topLevelNullableWithInitializer:
+ lateField,
+ lateFieldInitializer=3,
+ lateFieldName=topLevelNullableWithInitializer,
+ lateFieldTarget=_#topLevelNullableWithInitializer
+*/
+/*is-null.member: _#topLevelNullableWithInitializer#isSet:
+ lateFieldInitializer=3,
+ lateFieldName=topLevelNullableWithInitializer,
+ lateFieldTarget=_#topLevelNullableWithInitializer,
+ lateIsSetField
+*/
+/*member: topLevelNullableWithInitializer:
+ lateFieldGetter,
+ lateFieldInitializer=3,
+ lateFieldName=topLevelNullableWithInitializer,
+ lateFieldTarget=_#topLevelNullableWithInitializer
+*/
+/*member: topLevelNullableWithInitializer=:
+ lateFieldInitializer=3,
+ lateFieldName=topLevelNullableWithInitializer,
+ lateFieldSetter,
+ lateFieldTarget=_#topLevelNullableWithInitializer
+*/
+late int? topLevelNullableWithInitializer = 3;
+/*member: _#finalTopLevelNullableWithInitializer:
+ lateField,
+ lateFieldInitializer=4,
+ lateFieldName=finalTopLevelNullableWithInitializer,
+ lateFieldTarget=_#finalTopLevelNullableWithInitializer
+*/
+/*is-null.member: _#finalTopLevelNullableWithInitializer#isSet:
+ lateFieldInitializer=4,
+ lateFieldName=finalTopLevelNullableWithInitializer,
+ lateFieldTarget=_#finalTopLevelNullableWithInitializer,
+ lateIsSetField
+*/
+/*member: finalTopLevelNullableWithInitializer:
+ lateFieldGetter,
+ lateFieldInitializer=4,
+ lateFieldName=finalTopLevelNullableWithInitializer,
+ lateFieldTarget=_#finalTopLevelNullableWithInitializer
+*/
+late final int? finalTopLevelNullableWithInitializer = 4;
 
 class Class {
-  /*member: Class._#Class#instanceNonNullableWithoutInitializer#isSet:lateIsSetField*/
-  /*member: Class._#Class#instanceNonNullableWithoutInitializer:lateField*/
-  /*member: Class.instanceNonNullableWithoutInitializer:lateFieldGetter*/
-  /*member: Class.instanceNonNullableWithoutInitializer=:lateFieldSetter*/
+  /*member: Class._#Class#instanceNonNullableWithoutInitializer:
+   lateField,
+   lateFieldName=instanceNonNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#instanceNonNullableWithoutInitializer
+  */
+  /*member: Class.instanceNonNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=instanceNonNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#instanceNonNullableWithoutInitializer
+  */
+  /*member: Class.instanceNonNullableWithoutInitializer=:
+   lateFieldName=instanceNonNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#instanceNonNullableWithoutInitializer
+  */
   late int instanceNonNullableWithoutInitializer;
-  /*member: Class._#Class#finalInstanceNonNullableWithoutInitializer#isSet:lateIsSetField*/
-  /*member: Class._#Class#finalInstanceNonNullableWithoutInitializer:lateField*/
-  /*member: Class.finalInstanceNonNullableWithoutInitializer:lateFieldGetter*/
-  /*member: Class.finalInstanceNonNullableWithoutInitializer=:lateFieldSetter*/
+  /*member: Class._#Class#finalInstanceNonNullableWithoutInitializer:
+   lateField,
+   lateFieldName=finalInstanceNonNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNonNullableWithoutInitializer
+  */
+  /*member: Class.finalInstanceNonNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=finalInstanceNonNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNonNullableWithoutInitializer
+  */
+  /*member: Class.finalInstanceNonNullableWithoutInitializer=:
+   lateFieldName=finalInstanceNonNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#finalInstanceNonNullableWithoutInitializer
+  */
   late final int finalInstanceNonNullableWithoutInitializer;
-  /*member: Class._#Class#instanceNullableWithoutInitializer:lateField*/
-  /*member: Class._#Class#instanceNullableWithoutInitializer#isSet:lateIsSetField*/
-  /*member: Class.instanceNullableWithoutInitializer:lateFieldGetter*/
-  /*member: Class.instanceNullableWithoutInitializer=:lateFieldSetter*/
+  /*member: Class._#Class#instanceNullableWithoutInitializer:
+   lateField,
+   lateFieldName=instanceNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#instanceNullableWithoutInitializer
+  */
+  /*is-null.member: Class._#Class#instanceNullableWithoutInitializer#isSet:
+   lateFieldName=instanceNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#instanceNullableWithoutInitializer,
+   lateIsSetField
+  */
+  /*member: Class.instanceNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=instanceNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#instanceNullableWithoutInitializer
+  */
+  /*member: Class.instanceNullableWithoutInitializer=:
+   lateFieldName=instanceNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#instanceNullableWithoutInitializer
+  */
   late int? instanceNullableWithoutInitializer;
-  /*member: Class._#Class#finalInstanceNullableWithoutInitializer:lateField*/
-  /*member: Class._#Class#finalInstanceNullableWithoutInitializer#isSet:lateIsSetField*/
-  /*member: Class.finalInstanceNullableWithoutInitializer:lateFieldGetter*/
-  /*member: Class.finalInstanceNullableWithoutInitializer=:lateFieldSetter*/
+  /*member: Class._#Class#finalInstanceNullableWithoutInitializer:
+   lateField,
+   lateFieldName=finalInstanceNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNullableWithoutInitializer
+  */
+  /*is-null.member: Class._#Class#finalInstanceNullableWithoutInitializer#isSet:
+   lateFieldName=finalInstanceNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNullableWithoutInitializer,
+   lateIsSetField
+  */
+  /*member: Class.finalInstanceNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=finalInstanceNullableWithoutInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNullableWithoutInitializer
+  */
+  /*member: Class.finalInstanceNullableWithoutInitializer=:
+   lateFieldName=finalInstanceNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#finalInstanceNullableWithoutInitializer
+  */
   late final int? finalInstanceNullableWithoutInitializer;
-  /*member: Class._#Class#instanceNonNullableWithInitializer#isSet:lateIsSetField*/
-  /*member: Class._#Class#instanceNonNullableWithInitializer:lateField*/
-  /*member: Class.instanceNonNullableWithInitializer:lateFieldGetter*/
-  /*member: Class.instanceNonNullableWithInitializer=:lateFieldSetter*/
-  late int instanceNonNullableWithInitializer = 0;
-  /*member: Class._#Class#finalInstanceNonNullableWithInitializer#isSet:lateIsSetField*/
-  /*member: Class._#Class#finalInstanceNonNullableWithInitializer:lateField*/
-  /*member: Class.finalInstanceNonNullableWithInitializer:lateFieldGetter*/
-  late final int finalInstanceNonNullableWithInitializer = 0;
-  /*member: Class._#Class#instanceNullableWithInitializer:lateField*/
-  /*member: Class._#Class#instanceNullableWithInitializer#isSet:lateIsSetField*/
-  /*member: Class.instanceNullableWithInitializer:lateFieldGetter*/
-  /*member: Class.instanceNullableWithInitializer=:lateFieldSetter*/
-  late int? instanceNullableWithInitializer = 0;
-  /*member: Class._#Class#finalInstanceNullableWithInitializer:lateField*/
-  /*member: Class._#Class#finalInstanceNullableWithInitializer#isSet:lateIsSetField*/
-  /*member: Class.finalInstanceNullableWithInitializer:lateFieldGetter*/
-  late final int? finalInstanceNullableWithInitializer = 0;
+  /*member: Class._#Class#instanceNonNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=5,
+   lateFieldName=instanceNonNullableWithInitializer,
+   lateFieldTarget=Class._#Class#instanceNonNullableWithInitializer
+  */
+  /*member: Class.instanceNonNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=5,
+   lateFieldName=instanceNonNullableWithInitializer,
+   lateFieldTarget=Class._#Class#instanceNonNullableWithInitializer
+  */
+  /*member: Class.instanceNonNullableWithInitializer=:
+   lateFieldInitializer=5,
+   lateFieldName=instanceNonNullableWithInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#instanceNonNullableWithInitializer
+  */
+  late int instanceNonNullableWithInitializer = 5;
+  /*member: Class._#Class#finalInstanceNonNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=6,
+   lateFieldName=finalInstanceNonNullableWithInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNonNullableWithInitializer
+  */
+  /*member: Class.finalInstanceNonNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=6,
+   lateFieldName=finalInstanceNonNullableWithInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNonNullableWithInitializer
+  */
+  late final int finalInstanceNonNullableWithInitializer = 6;
+  /*member: Class._#Class#instanceNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=7,
+   lateFieldName=instanceNullableWithInitializer,
+   lateFieldTarget=Class._#Class#instanceNullableWithInitializer
+  */
+  /*is-null.member: Class._#Class#instanceNullableWithInitializer#isSet:
+   lateFieldInitializer=7,
+   lateFieldName=instanceNullableWithInitializer,
+   lateFieldTarget=Class._#Class#instanceNullableWithInitializer,
+   lateIsSetField
+  */
+  /*member: Class.instanceNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=7,
+   lateFieldName=instanceNullableWithInitializer,
+   lateFieldTarget=Class._#Class#instanceNullableWithInitializer
+  */
+  /*member: Class.instanceNullableWithInitializer=:
+   lateFieldInitializer=7,
+   lateFieldName=instanceNullableWithInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#instanceNullableWithInitializer
+  */
+  late int? instanceNullableWithInitializer = 7;
+  /*member: Class._#Class#finalInstanceNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=8,
+   lateFieldName=finalInstanceNullableWithInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNullableWithInitializer
+  */
+  /*is-null.member: Class._#Class#finalInstanceNullableWithInitializer#isSet:
+   lateFieldInitializer=8,
+   lateFieldName=finalInstanceNullableWithInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNullableWithInitializer,
+   lateIsSetField
+  */
+  /*member: Class.finalInstanceNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=8,
+   lateFieldName=finalInstanceNullableWithInitializer,
+   lateFieldTarget=Class._#Class#finalInstanceNullableWithInitializer
+  */
+  late final int? finalInstanceNullableWithInitializer = 8;
 
-  /*member: Class._#staticNonNullableWithoutInitializer#isSet:lateIsSetField*/
-  /*member: Class._#staticNonNullableWithoutInitializer:lateField*/
-  /*member: Class.staticNonNullableWithoutInitializer:lateFieldGetter*/
-  /*member: Class.staticNonNullableWithoutInitializer=:lateFieldSetter*/
+  /*member: Class._#staticNonNullableWithoutInitializer:
+   lateField,
+   lateFieldName=staticNonNullableWithoutInitializer,
+   lateFieldTarget=Class._#staticNonNullableWithoutInitializer
+  */
+  /*member: Class.staticNonNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=staticNonNullableWithoutInitializer,
+   lateFieldTarget=Class._#staticNonNullableWithoutInitializer
+  */
+  /*member: Class.staticNonNullableWithoutInitializer=:
+   lateFieldName=staticNonNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#staticNonNullableWithoutInitializer
+  */
   static late int staticNonNullableWithoutInitializer;
-  /*member: Class._#finalStaticNonNullableWithoutInitializer#isSet:lateIsSetField*/
-  /*member: Class._#finalStaticNonNullableWithoutInitializer:lateField*/
-  /*member: Class.finalStaticNonNullableWithoutInitializer:lateFieldGetter*/
-  /*member: Class.finalStaticNonNullableWithoutInitializer=:lateFieldSetter*/
+  /*member: Class._#finalStaticNonNullableWithoutInitializer:
+   lateField,
+   lateFieldName=finalStaticNonNullableWithoutInitializer,
+   lateFieldTarget=Class._#finalStaticNonNullableWithoutInitializer
+  */
+  /*member: Class.finalStaticNonNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=finalStaticNonNullableWithoutInitializer,
+   lateFieldTarget=Class._#finalStaticNonNullableWithoutInitializer
+  */
+  /*member: Class.finalStaticNonNullableWithoutInitializer=:
+   lateFieldName=finalStaticNonNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#finalStaticNonNullableWithoutInitializer
+  */
   static late final int finalStaticNonNullableWithoutInitializer;
-  /*member: Class._#staticNullableWithoutInitializer:lateField*/
-  /*member: Class._#staticNullableWithoutInitializer#isSet:lateIsSetField*/
-  /*member: Class.staticNullableWithoutInitializer:lateFieldGetter*/
-  /*member: Class.staticNullableWithoutInitializer=:lateFieldSetter*/
+  /*member: Class._#staticNullableWithoutInitializer:
+   lateField,
+   lateFieldName=staticNullableWithoutInitializer,
+   lateFieldTarget=Class._#staticNullableWithoutInitializer
+  */
+  /*is-null.member: Class._#staticNullableWithoutInitializer#isSet:
+   lateFieldName=staticNullableWithoutInitializer,
+   lateFieldTarget=Class._#staticNullableWithoutInitializer,
+   lateIsSetField
+  */
+  /*member: Class.staticNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=staticNullableWithoutInitializer,
+   lateFieldTarget=Class._#staticNullableWithoutInitializer
+  */
+  /*member: Class.staticNullableWithoutInitializer=:
+   lateFieldName=staticNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#staticNullableWithoutInitializer
+  */
   static late int? staticNullableWithoutInitializer;
-  /*member: Class._#finalStaticNullableWithoutInitializer:lateField*/
-  /*member: Class._#finalStaticNullableWithoutInitializer#isSet:lateIsSetField*/
-  /*member: Class.finalStaticNullableWithoutInitializer:lateFieldGetter*/
-  /*member: Class.finalStaticNullableWithoutInitializer=:lateFieldSetter*/
+  /*member: Class._#finalStaticNullableWithoutInitializer:
+   lateField,
+   lateFieldName=finalStaticNullableWithoutInitializer,
+   lateFieldTarget=Class._#finalStaticNullableWithoutInitializer
+  */
+  /*is-null.member: Class._#finalStaticNullableWithoutInitializer#isSet:
+   lateFieldName=finalStaticNullableWithoutInitializer,
+   lateFieldTarget=Class._#finalStaticNullableWithoutInitializer,
+   lateIsSetField
+  */
+  /*member: Class.finalStaticNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=finalStaticNullableWithoutInitializer,
+   lateFieldTarget=Class._#finalStaticNullableWithoutInitializer
+  */
+  /*member: Class.finalStaticNullableWithoutInitializer=:
+   lateFieldName=finalStaticNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#finalStaticNullableWithoutInitializer
+  */
   static late final int? finalStaticNullableWithoutInitializer;
-  /*member: Class._#staticNonNullableWithInitializer#isSet:lateIsSetField*/
-  /*member: Class._#staticNonNullableWithInitializer:lateField*/
-  /*member: Class.staticNonNullableWithInitializer:lateFieldGetter*/
-  /*member: Class.staticNonNullableWithInitializer=:lateFieldSetter*/
-  static late int staticNonNullableWithInitializer = 0;
-  /*member: Class._#finalStaticNonNullableWithInitializer#isSet:lateIsSetField*/
-  /*member: Class._#finalStaticNonNullableWithInitializer:lateField*/
-  /*member: Class.finalStaticNonNullableWithInitializer:lateFieldGetter*/
-  static late final int finalStaticNonNullableWithInitializer = 0;
-  /*member: Class._#staticNullableWithInitializer:lateField*/
-  /*member: Class._#staticNullableWithInitializer#isSet:lateIsSetField*/
-  /*member: Class.staticNullableWithInitializer:lateFieldGetter*/
-  /*member: Class.staticNullableWithInitializer=:lateFieldSetter*/
-  static late int? staticNullableWithInitializer = 0;
-  /*member: Class._#finalStaticNullableWithInitializer:lateField*/
-  /*member: Class._#finalStaticNullableWithInitializer#isSet:lateIsSetField*/
-  /*member: Class.finalStaticNullableWithInitializer:lateFieldGetter*/
-  static late final int? finalStaticNullableWithInitializer = 0;
+  /*member: Class._#staticNonNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=9,
+   lateFieldName=staticNonNullableWithInitializer,
+   lateFieldTarget=Class._#staticNonNullableWithInitializer
+  */
+  /*member: Class.staticNonNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=9,
+   lateFieldName=staticNonNullableWithInitializer,
+   lateFieldTarget=Class._#staticNonNullableWithInitializer
+  */
+  /*member: Class.staticNonNullableWithInitializer=:
+   lateFieldInitializer=9,
+   lateFieldName=staticNonNullableWithInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#staticNonNullableWithInitializer
+  */
+  static late int staticNonNullableWithInitializer = 9;
+  /*member: Class._#finalStaticNonNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=10,
+   lateFieldName=finalStaticNonNullableWithInitializer,
+   lateFieldTarget=Class._#finalStaticNonNullableWithInitializer
+  */
+  /*member: Class.finalStaticNonNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=10,
+   lateFieldName=finalStaticNonNullableWithInitializer,
+   lateFieldTarget=Class._#finalStaticNonNullableWithInitializer
+  */
+  static late final int finalStaticNonNullableWithInitializer = 10;
+  /*member: Class._#staticNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=11,
+   lateFieldName=staticNullableWithInitializer,
+   lateFieldTarget=Class._#staticNullableWithInitializer
+  */
+  /*is-null.member: Class._#staticNullableWithInitializer#isSet:
+   lateFieldInitializer=11,
+   lateFieldName=staticNullableWithInitializer,
+   lateFieldTarget=Class._#staticNullableWithInitializer,
+   lateIsSetField
+  */
+  /*member: Class.staticNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=11,
+   lateFieldName=staticNullableWithInitializer,
+   lateFieldTarget=Class._#staticNullableWithInitializer
+  */
+  /*member: Class.staticNullableWithInitializer=:
+   lateFieldInitializer=11,
+   lateFieldName=staticNullableWithInitializer,
+   lateFieldSetter,
+   lateFieldTarget=Class._#staticNullableWithInitializer
+  */
+  static late int? staticNullableWithInitializer = 11;
+  /*member: Class._#finalStaticNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=12,
+   lateFieldName=finalStaticNullableWithInitializer,
+   lateFieldTarget=Class._#finalStaticNullableWithInitializer
+  */
+  /*is-null.member: Class._#finalStaticNullableWithInitializer#isSet:
+   lateFieldInitializer=12,
+   lateFieldName=finalStaticNullableWithInitializer,
+   lateFieldTarget=Class._#finalStaticNullableWithInitializer,
+   lateIsSetField
+  */
+  /*member: Class.finalStaticNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=12,
+   lateFieldName=finalStaticNullableWithInitializer,
+   lateFieldTarget=Class._#finalStaticNullableWithInitializer
+  */
+  static late final int? finalStaticNullableWithInitializer = 12;
+}
+
+extension on int? {
+  /*member: _#_extension#0|unnamedExtensionNonNullableWithoutInitializer:
+   lateField,
+   lateFieldName=_extension#0|unnamedExtensionNonNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNonNullableWithoutInitializer
+  */
+  /*member: _extension#0|unnamedExtensionNonNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=_extension#0|unnamedExtensionNonNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNonNullableWithoutInitializer
+  */
+  /*member: _extension#0|unnamedExtensionNonNullableWithoutInitializer=:
+   lateFieldName=_extension#0|unnamedExtensionNonNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNonNullableWithoutInitializer
+  */
+  static late int unnamedExtensionNonNullableWithoutInitializer;
+  /*member: _#_extension#0|finalUnnamedExtensionNonNullableWithoutInitializer:
+   lateField,
+   lateFieldName=_extension#0|finalUnnamedExtensionNonNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNonNullableWithoutInitializer
+  */
+  /*member: _extension#0|finalUnnamedExtensionNonNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=_extension#0|finalUnnamedExtensionNonNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNonNullableWithoutInitializer
+  */
+  /*member: _extension#0|finalUnnamedExtensionNonNullableWithoutInitializer=:
+   lateFieldName=_extension#0|finalUnnamedExtensionNonNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNonNullableWithoutInitializer
+  */
+  static late final int finalUnnamedExtensionNonNullableWithoutInitializer;
+  /*member: _#_extension#0|unnamedExtensionNullableWithoutInitializer:
+   lateField,
+   lateFieldName=_extension#0|unnamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNullableWithoutInitializer
+  */
+  /*is-null.member: _#_extension#0|unnamedExtensionNullableWithoutInitializer#isSet:
+   lateFieldName=_extension#0|unnamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNullableWithoutInitializer,
+   lateIsSetField
+  */
+  /*member: _extension#0|unnamedExtensionNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=_extension#0|unnamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNullableWithoutInitializer
+  */
+  /*member: _extension#0|unnamedExtensionNullableWithoutInitializer=:
+   lateFieldName=_extension#0|unnamedExtensionNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNullableWithoutInitializer
+  */
+  static late int? unnamedExtensionNullableWithoutInitializer;
+  /*member: _#_extension#0|finalUnnamedExtensionNullableWithoutInitializer:
+   lateField,
+   lateFieldName=_extension#0|finalUnnamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNullableWithoutInitializer
+  */
+  /*is-null.member: _#_extension#0|finalUnnamedExtensionNullableWithoutInitializer#isSet:
+   lateFieldName=_extension#0|finalUnnamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNullableWithoutInitializer,
+   lateIsSetField
+  */
+  /*member: _extension#0|finalUnnamedExtensionNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=_extension#0|finalUnnamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNullableWithoutInitializer
+  */
+  /*member: _extension#0|finalUnnamedExtensionNullableWithoutInitializer=:
+   lateFieldName=_extension#0|finalUnnamedExtensionNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNullableWithoutInitializer
+  */
+  static late final int? finalUnnamedExtensionNullableWithoutInitializer;
+  /*member: _#_extension#0|unnamedExtensionNonNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=13,
+   lateFieldName=_extension#0|unnamedExtensionNonNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNonNullableWithInitializer
+  */
+  /*member: _extension#0|unnamedExtensionNonNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=13,
+   lateFieldName=_extension#0|unnamedExtensionNonNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNonNullableWithInitializer
+  */
+  /*member: _extension#0|unnamedExtensionNonNullableWithInitializer=:
+   lateFieldInitializer=13,
+   lateFieldName=_extension#0|unnamedExtensionNonNullableWithInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNonNullableWithInitializer
+  */
+  static late int unnamedExtensionNonNullableWithInitializer = 13;
+  /*member: _#_extension#0|finalUnnamedExtensionNonNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=14,
+   lateFieldName=_extension#0|finalUnnamedExtensionNonNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNonNullableWithInitializer
+  */
+  /*member: _extension#0|finalUnnamedExtensionNonNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=14,
+   lateFieldName=_extension#0|finalUnnamedExtensionNonNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNonNullableWithInitializer
+  */
+  static late final int finalUnnamedExtensionNonNullableWithInitializer = 14;
+  /*member: _#_extension#0|unnamedExtensionNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=15,
+   lateFieldName=_extension#0|unnamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNullableWithInitializer
+  */
+  /*is-null.member: _#_extension#0|unnamedExtensionNullableWithInitializer#isSet:
+   lateFieldInitializer=15,
+   lateFieldName=_extension#0|unnamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNullableWithInitializer,
+   lateIsSetField
+  */
+  /*member: _extension#0|unnamedExtensionNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=15,
+   lateFieldName=_extension#0|unnamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNullableWithInitializer
+  */
+  /*member: _extension#0|unnamedExtensionNullableWithInitializer=:
+   lateFieldInitializer=15,
+   lateFieldName=_extension#0|unnamedExtensionNullableWithInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|unnamedExtensionNullableWithInitializer
+  */
+  static late int? unnamedExtensionNullableWithInitializer = 15;
+  /*member: _#_extension#0|finalUnnamedExtensionNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=16,
+   lateFieldName=_extension#0|finalUnnamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNullableWithInitializer
+  */
+  /*is-null.member: _#_extension#0|finalUnnamedExtensionNullableWithInitializer#isSet:
+   lateFieldInitializer=16,
+   lateFieldName=_extension#0|finalUnnamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNullableWithInitializer,
+   lateIsSetField
+  */
+  /*member: _extension#0|finalUnnamedExtensionNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=16,
+   lateFieldName=_extension#0|finalUnnamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#_extension#0|finalUnnamedExtensionNullableWithInitializer
+  */
+  static late final int? finalUnnamedExtensionNullableWithInitializer = 16;
+}
+
+extension Extension on int? {
+  /*member: _#Extension|namedExtensionNonNullableWithoutInitializer:
+   lateField,
+   lateFieldName=Extension|namedExtensionNonNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNonNullableWithoutInitializer
+  */
+  /*member: Extension|namedExtensionNonNullableWithoutInitializer=:
+   lateFieldName=Extension|namedExtensionNonNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#Extension|namedExtensionNonNullableWithoutInitializer
+  */
+  /*member: Extension|namedExtensionNonNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=Extension|namedExtensionNonNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNonNullableWithoutInitializer
+  */
+  static late int namedExtensionNonNullableWithoutInitializer;
+  /*member: _#Extension|finalNamedExtensionNonNullableWithoutInitializer:
+   lateField,
+   lateFieldName=Extension|finalNamedExtensionNonNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNonNullableWithoutInitializer
+  */
+  /*member: Extension|finalNamedExtensionNonNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=Extension|finalNamedExtensionNonNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNonNullableWithoutInitializer
+  */
+  /*member: Extension|finalNamedExtensionNonNullableWithoutInitializer=:
+   lateFieldName=Extension|finalNamedExtensionNonNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#Extension|finalNamedExtensionNonNullableWithoutInitializer
+  */
+  static late final int finalNamedExtensionNonNullableWithoutInitializer;
+  /*member: _#Extension|namedExtensionNullableWithoutInitializer:
+   lateField,
+   lateFieldName=Extension|namedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNullableWithoutInitializer
+  */
+  /*is-null.member: _#Extension|namedExtensionNullableWithoutInitializer#isSet:
+   lateFieldName=Extension|namedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNullableWithoutInitializer,
+   lateIsSetField
+  */
+  /*member: Extension|namedExtensionNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=Extension|namedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNullableWithoutInitializer
+  */
+  /*member: Extension|namedExtensionNullableWithoutInitializer=:
+   lateFieldName=Extension|namedExtensionNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#Extension|namedExtensionNullableWithoutInitializer
+  */
+  static late int? namedExtensionNullableWithoutInitializer;
+  /*member: _#Extension|finalNamedExtensionNullableWithoutInitializer:
+   lateField,
+   lateFieldName=Extension|finalNamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNullableWithoutInitializer
+  */
+  /*is-null.member: _#Extension|finalNamedExtensionNullableWithoutInitializer#isSet:
+   lateFieldName=Extension|finalNamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNullableWithoutInitializer,
+   lateIsSetField
+  */
+  /*member: Extension|finalNamedExtensionNullableWithoutInitializer:
+   lateFieldGetter,
+   lateFieldName=Extension|finalNamedExtensionNullableWithoutInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNullableWithoutInitializer
+  */
+  /*member: Extension|finalNamedExtensionNullableWithoutInitializer=:
+   lateFieldName=Extension|finalNamedExtensionNullableWithoutInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#Extension|finalNamedExtensionNullableWithoutInitializer
+  */
+  static late final int? finalNamedExtensionNullableWithoutInitializer;
+  /*member: _#Extension|namedExtensionNonNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=17,
+   lateFieldName=Extension|namedExtensionNonNullableWithInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNonNullableWithInitializer
+  */
+  /*member: Extension|namedExtensionNonNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=17,
+   lateFieldName=Extension|namedExtensionNonNullableWithInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNonNullableWithInitializer
+  */
+  /*member: Extension|namedExtensionNonNullableWithInitializer=:
+   lateFieldInitializer=17,
+   lateFieldName=Extension|namedExtensionNonNullableWithInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#Extension|namedExtensionNonNullableWithInitializer
+  */
+  static late int namedExtensionNonNullableWithInitializer = 17;
+  /*member: _#Extension|finalNamedExtensionNonNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=18,
+   lateFieldName=Extension|finalNamedExtensionNonNullableWithInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNonNullableWithInitializer
+  */
+  /*member: Extension|finalNamedExtensionNonNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=18,
+   lateFieldName=Extension|finalNamedExtensionNonNullableWithInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNonNullableWithInitializer
+  */
+  static late final int finalNamedExtensionNonNullableWithInitializer = 18;
+  /*member: _#Extension|namedExtensionNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=19,
+   lateFieldName=Extension|namedExtensionNullableWithInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNullableWithInitializer
+  */
+  /*is-null.member: _#Extension|namedExtensionNullableWithInitializer#isSet:
+   lateFieldInitializer=19,
+   lateFieldName=Extension|namedExtensionNullableWithInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNullableWithInitializer,
+   lateIsSetField
+  */
+  /*member: Extension|namedExtensionNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=19,
+   lateFieldName=Extension|namedExtensionNullableWithInitializer,
+   lateFieldTarget=_#Extension|namedExtensionNullableWithInitializer
+  */
+  /*member: Extension|namedExtensionNullableWithInitializer=:
+   lateFieldInitializer=19,
+   lateFieldName=Extension|namedExtensionNullableWithInitializer,
+   lateFieldSetter,
+   lateFieldTarget=_#Extension|namedExtensionNullableWithInitializer
+  */
+  static late int? namedExtensionNullableWithInitializer = 19;
+  /*member: _#Extension|finalNamedExtensionNullableWithInitializer:
+   lateField,
+   lateFieldInitializer=20,
+   lateFieldName=Extension|finalNamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNullableWithInitializer
+  */
+  /*is-null.member: _#Extension|finalNamedExtensionNullableWithInitializer#isSet:
+   lateFieldInitializer=20,
+   lateFieldName=Extension|finalNamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNullableWithInitializer,
+   lateIsSetField
+  */
+  /*member: Extension|finalNamedExtensionNullableWithInitializer:
+   lateFieldGetter,
+   lateFieldInitializer=20,
+   lateFieldName=Extension|finalNamedExtensionNullableWithInitializer,
+   lateFieldTarget=_#Extension|finalNamedExtensionNullableWithInitializer
+  */
+  static late final int? finalNamedExtensionNullableWithInitializer = 20;
 }
 
 method() {
   late int
       /*
-   lateIsSetLocal,
-   lateLocal,
-   lateLocalGetter,
-   lateLocalSetter
-  */
+       lateLocal,
+       lateLocalGetter,
+       lateLocalSetter
+      */
       localNonNullableWithoutInitializer;
   late final int
       /*
-       lateIsSetLocal,
        lateLocal,
        lateLocalGetter,
        lateLocalSetter
       */
       finalLocalNonNullableWithoutInitializer;
   late int?
-      /*
-   lateIsSetLocal,
-   lateLocal,
-   lateLocalGetter,
-   lateLocalSetter
-  */
+      /*is-null.
+       lateIsSetLocal,
+       lateLocal,
+       lateLocalGetter,
+       lateLocalSetter
+      */
+      /*sentinel.
+       lateLocal,
+       lateLocalGetter,
+       lateLocalSetter
+      */
       localNullableWithoutInitializer;
   late final int?
-      /*
+      /*is-null.
        lateIsSetLocal,
        lateLocal,
        lateLocalGetter,
        lateLocalSetter
       */
+      /*sentinel.
+       lateLocal,
+       lateLocalGetter,
+       lateLocalSetter
+      */
       finalLocalNullableWithoutInitializer;
   late int
       /*
-   lateIsSetLocal,
-   lateLocal,
-   lateLocalGetter,
-   lateLocalSetter
-  */
-      localNonNullableWithInitializer = 0;
+       lateLocal,
+       lateLocalGetter,
+       lateLocalSetter
+      */
+      localNonNullableWithInitializer = 21;
   late final int /*
-   lateIsSetLocal,
-   lateLocal,
-   lateLocalGetter
-  */
-      finalLocalNonNullableWithInitializer = 0;
+       lateLocal,
+       lateLocalGetter
+      */
+      finalLocalNonNullableWithInitializer = 22;
   late int?
-      /*
-   lateIsSetLocal,
-   lateLocal,
-   lateLocalGetter,
-   lateLocalSetter
-  */
-      localNullableWithInitializer = 0;
-  late final int? /*
-   lateIsSetLocal,
-   lateLocal,
-   lateLocalGetter
-  */
-      finalLocalNullableWithInitializer = 0;
+      /*is-null.
+       lateIsSetLocal,
+       lateLocal,
+       lateLocalGetter,
+       lateLocalSetter
+      */
+      /*sentinel.
+       lateLocal,
+       lateLocalGetter,
+       lateLocalSetter
+      */
+      localNullableWithInitializer = 23;
+  late final int?
+      /*is-null.
+       lateIsSetLocal,
+       lateLocal,
+       lateLocalGetter
+      */
+      /*sentinel.
+       lateLocal,
+       lateLocalGetter
+      */
+      finalLocalNullableWithInitializer = 24;
 }
diff --git a/pkg/front_end/test/predicates/data/late_names.dart b/pkg/front_end/test/predicates/data/late_names.dart
new file mode 100644
index 0000000..a67c9e9
--- /dev/null
+++ b/pkg/front_end/test/predicates/data/late_names.dart
@@ -0,0 +1,461 @@
+// 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.
+
+/*member: _#a:
+ lateField,
+ lateFieldName=a,
+ lateFieldTarget=_#a
+*/
+/*is-null.member: _#a#isSet:
+ lateFieldName=a,
+ lateFieldTarget=_#a,
+ lateIsSetField
+*/
+/*member: a:
+ lateFieldGetter,
+ lateFieldName=a,
+ lateFieldTarget=_#a
+*/
+/*member: a=:
+ lateFieldName=a,
+ lateFieldSetter,
+ lateFieldTarget=_#a
+*/
+late int? a;
+
+/*member: _#aa:
+ lateField,
+ lateFieldName=aa,
+ lateFieldTarget=_#aa
+*/
+/*is-null.member: _#aa#isSet:
+ lateFieldName=aa,
+ lateFieldTarget=_#aa,
+ lateIsSetField
+*/
+/*member: aa:
+ lateFieldGetter,
+ lateFieldName=aa,
+ lateFieldTarget=_#aa
+*/
+/*member: aa=:
+ lateFieldName=aa,
+ lateFieldSetter,
+ lateFieldTarget=_#aa
+*/
+late int? aa;
+
+/*member: _#_a:
+ lateField,
+ lateFieldName=_a,
+ lateFieldTarget=_#_a
+*/
+/*is-null.member: _#_a#isSet:
+ lateFieldName=_a,
+ lateFieldTarget=_#_a,
+ lateIsSetField
+*/
+/*member: _a:
+ lateFieldGetter,
+ lateFieldName=_a,
+ lateFieldTarget=_#_a
+*/
+/*member: _a=:
+ lateFieldName=_a,
+ lateFieldSetter,
+ lateFieldTarget=_#_a
+*/
+late int? _a;
+
+class Class {
+  /*member: Class._#Class#a:
+   lateField,
+   lateFieldName=a,
+   lateFieldTarget=Class._#Class#a
+  */
+  /*is-null.member: Class._#Class#a#isSet:
+   lateFieldName=a,
+   lateFieldTarget=Class._#Class#a,
+   lateIsSetField
+  */
+  /*member: Class.a:
+   lateFieldGetter,
+   lateFieldName=a,
+   lateFieldTarget=Class._#Class#a
+  */
+  /*member: Class.a=:
+   lateFieldName=a,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#a
+  */
+  late int? a;
+  /*member: Class._#Class#aa:
+   lateField,
+   lateFieldName=aa,
+   lateFieldTarget=Class._#Class#aa
+  */
+  /*is-null.member: Class._#Class#aa#isSet:
+   lateFieldName=aa,
+   lateFieldTarget=Class._#Class#aa,
+   lateIsSetField
+  */
+  /*member: Class.aa:
+   lateFieldGetter,
+   lateFieldName=aa,
+   lateFieldTarget=Class._#Class#aa
+  */
+  /*member: Class.aa=:
+   lateFieldName=aa,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#aa
+  */
+  late int? aa;
+  /*member: Class._#Class#_a:
+   lateField,
+   lateFieldName=_a,
+   lateFieldTarget=Class._#Class#_a
+  */
+  /*is-null.member: Class._#Class#_a#isSet:
+   lateFieldName=_a,
+   lateFieldTarget=Class._#Class#_a,
+   lateIsSetField
+  */
+  /*member: Class._a:
+   lateFieldGetter,
+   lateFieldName=_a,
+   lateFieldTarget=Class._#Class#_a
+  */
+  /*member: Class._a=:
+   lateFieldName=_a,
+   lateFieldSetter,
+   lateFieldTarget=Class._#Class#_a
+  */
+  late int? _a;
+
+  /*member: Class._#b:
+   lateField,
+   lateFieldName=b,
+   lateFieldTarget=Class._#b
+  */
+  /*is-null.member: Class._#b#isSet:
+   lateFieldName=b,
+   lateFieldTarget=Class._#b,
+   lateIsSetField
+  */
+  /*member: Class.b:
+   lateFieldGetter,
+   lateFieldName=b,
+   lateFieldTarget=Class._#b
+  */
+  /*member: Class.b=:
+   lateFieldName=b,
+   lateFieldSetter,
+   lateFieldTarget=Class._#b
+  */
+  static late int? b;
+  /*member: Class._#bb:
+   lateField,
+   lateFieldName=bb,
+   lateFieldTarget=Class._#bb
+  */
+  /*is-null.member: Class._#bb#isSet:
+   lateFieldName=bb,
+   lateFieldTarget=Class._#bb,
+   lateIsSetField
+  */
+  /*member: Class.bb:
+   lateFieldGetter,
+   lateFieldName=bb,
+   lateFieldTarget=Class._#bb
+  */
+  /*member: Class.bb=:
+   lateFieldName=bb,
+   lateFieldSetter,
+   lateFieldTarget=Class._#bb
+  */
+  static late int? bb;
+  /*member: Class._#_b:
+   lateField,
+   lateFieldName=_b,
+   lateFieldTarget=Class._#_b
+  */
+  /*is-null.member: Class._#_b#isSet:
+   lateFieldName=_b,
+   lateFieldTarget=Class._#_b,
+   lateIsSetField
+  */
+  /*member: Class._b:
+   lateFieldGetter,
+   lateFieldName=_b,
+   lateFieldTarget=Class._#_b
+  */
+  /*member: Class._b=:
+   lateFieldName=_b,
+   lateFieldSetter,
+   lateFieldTarget=Class._#_b
+  */
+  static late int? _b;
+}
+
+class _Class {
+  /*member: _Class._#_Class#a:
+   lateField,
+   lateFieldName=a,
+   lateFieldTarget=_Class._#_Class#a
+  */
+  /*is-null.member: _Class._#_Class#a#isSet:
+   lateFieldName=a,
+   lateFieldTarget=_Class._#_Class#a,
+   lateIsSetField
+  */
+  /*member: _Class.a:
+   lateFieldGetter,
+   lateFieldName=a,
+   lateFieldTarget=_Class._#_Class#a
+  */
+  /*member: _Class.a=:
+   lateFieldName=a,
+   lateFieldSetter,
+   lateFieldTarget=_Class._#_Class#a
+  */
+  late int? a;
+  /*member: _Class._#_Class#aa:
+   lateField,
+   lateFieldName=aa,
+   lateFieldTarget=_Class._#_Class#aa
+  */
+  /*is-null.member: _Class._#_Class#aa#isSet:
+   lateFieldName=aa,
+   lateFieldTarget=_Class._#_Class#aa,
+   lateIsSetField
+  */
+  /*member: _Class.aa:
+   lateFieldGetter,
+   lateFieldName=aa,
+   lateFieldTarget=_Class._#_Class#aa
+  */
+  /*member: _Class.aa=:
+   lateFieldName=aa,
+   lateFieldSetter,
+   lateFieldTarget=_Class._#_Class#aa
+  */
+  late int? aa;
+  /*member: _Class._#_Class#_a:
+   lateField,
+   lateFieldName=_a,
+   lateFieldTarget=_Class._#_Class#_a
+  */
+  /*is-null.member: _Class._#_Class#_a#isSet:
+   lateFieldName=_a,
+   lateFieldTarget=_Class._#_Class#_a,
+   lateIsSetField
+  */
+  /*member: _Class._a:
+   lateFieldGetter,
+   lateFieldName=_a,
+   lateFieldTarget=_Class._#_Class#_a
+  */
+  /*member: _Class._a=:
+   lateFieldName=_a,
+   lateFieldSetter,
+   lateFieldTarget=_Class._#_Class#_a
+  */
+  late int? _a;
+
+  /*member: _Class._#b:
+   lateField,
+   lateFieldName=b,
+   lateFieldTarget=_Class._#b
+  */
+  /*is-null.member: _Class._#b#isSet:
+   lateFieldName=b,
+   lateFieldTarget=_Class._#b,
+   lateIsSetField
+  */
+  /*member: _Class.b:
+   lateFieldGetter,
+   lateFieldName=b,
+   lateFieldTarget=_Class._#b
+  */
+  /*member: _Class.b=:
+   lateFieldName=b,
+   lateFieldSetter,
+   lateFieldTarget=_Class._#b
+  */
+  static late int? b;
+  /*member: _Class._#bb:
+   lateField,
+   lateFieldName=bb,
+   lateFieldTarget=_Class._#bb
+  */
+  /*is-null.member: _Class._#bb#isSet:
+   lateFieldName=bb,
+   lateFieldTarget=_Class._#bb,
+   lateIsSetField
+  */
+  /*member: _Class.bb:
+   lateFieldGetter,
+   lateFieldName=bb,
+   lateFieldTarget=_Class._#bb
+  */
+  /*member: _Class.bb=:
+   lateFieldName=bb,
+   lateFieldSetter,
+   lateFieldTarget=_Class._#bb
+  */
+  static late int? bb;
+  /*member: _Class._#_b:
+   lateField,
+   lateFieldName=_b,
+   lateFieldTarget=_Class._#_b
+  */
+  /*is-null.member: _Class._#_b#isSet:
+   lateFieldName=_b,
+   lateFieldTarget=_Class._#_b,
+   lateIsSetField
+  */
+  /*member: _Class._b:
+   lateFieldGetter,
+   lateFieldName=_b,
+   lateFieldTarget=_Class._#_b
+  */
+  /*member: _Class._b=:
+   lateFieldName=_b,
+   lateFieldSetter,
+   lateFieldTarget=_Class._#_b
+  */
+  static late int? _b;
+}
+
+extension on int? {
+  /*member: _#_extension#0|a:
+   lateField,
+   lateFieldName=_extension#0|a,
+   lateFieldTarget=_#_extension#0|a
+  */
+  /*is-null.member: _#_extension#0|a#isSet:
+   lateFieldName=_extension#0|a,
+   lateFieldTarget=_#_extension#0|a,
+   lateIsSetField
+  */
+  /*member: _extension#0|a:
+   lateFieldGetter,
+   lateFieldName=_extension#0|a,
+   lateFieldTarget=_#_extension#0|a
+  */
+  /*member: _extension#0|a=:
+   lateFieldName=_extension#0|a,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|a
+  */
+  static late int? a;
+  /*member: _#_extension#0|aa:
+   lateField,
+   lateFieldName=_extension#0|aa,
+   lateFieldTarget=_#_extension#0|aa
+  */
+  /*is-null.member: _#_extension#0|aa#isSet:
+   lateFieldName=_extension#0|aa,
+   lateFieldTarget=_#_extension#0|aa,
+   lateIsSetField
+  */
+  /*member: _extension#0|aa:
+   lateFieldGetter,
+   lateFieldName=_extension#0|aa,
+   lateFieldTarget=_#_extension#0|aa
+  */
+  /*member: _extension#0|aa=:
+   lateFieldName=_extension#0|aa,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|aa
+  */
+  static late int? aa;
+  /*member: _#_extension#0|_b:
+   lateField,
+   lateFieldName=_extension#0|_b,
+   lateFieldTarget=_#_extension#0|_b
+  */
+  /*is-null.member: _#_extension#0|_b#isSet:
+   lateFieldName=_extension#0|_b,
+   lateFieldTarget=_#_extension#0|_b,
+   lateIsSetField
+  */
+  /*member: _extension#0|_b:
+   lateFieldGetter,
+   lateFieldName=_extension#0|_b,
+   lateFieldTarget=_#_extension#0|_b
+  */
+  /*member: _extension#0|_b=:
+   lateFieldName=_extension#0|_b,
+   lateFieldSetter,
+   lateFieldTarget=_#_extension#0|_b
+  */
+  static late int? _b;
+}
+
+extension _Extension on int? {
+  /*member: _#_Extension|a:
+   lateField,
+   lateFieldName=_Extension|a,
+   lateFieldTarget=_#_Extension|a
+  */
+  /*is-null.member: _#_Extension|a#isSet:
+   lateFieldName=_Extension|a,
+   lateFieldTarget=_#_Extension|a,
+   lateIsSetField
+  */
+  /*member: _Extension|a:
+   lateFieldGetter,
+   lateFieldName=_Extension|a,
+   lateFieldTarget=_#_Extension|a
+  */
+  /*member: _Extension|a=:
+   lateFieldName=_Extension|a,
+   lateFieldSetter,
+   lateFieldTarget=_#_Extension|a
+  */
+  static late int? a;
+  /*member: _#_Extension|aa:
+   lateField,
+   lateFieldName=_Extension|aa,
+   lateFieldTarget=_#_Extension|aa
+  */
+  /*is-null.member: _#_Extension|aa#isSet:
+   lateFieldName=_Extension|aa,
+   lateFieldTarget=_#_Extension|aa,
+   lateIsSetField
+  */
+  /*member: _Extension|aa:
+   lateFieldGetter,
+   lateFieldName=_Extension|aa,
+   lateFieldTarget=_#_Extension|aa
+  */
+  /*member: _Extension|aa=:
+   lateFieldName=_Extension|aa,
+   lateFieldSetter,
+   lateFieldTarget=_#_Extension|aa
+  */
+  static late int? aa;
+  /*member: _#_Extension|_b:
+   lateField,
+   lateFieldName=_Extension|_b,
+   lateFieldTarget=_#_Extension|_b
+  */
+  /*is-null.member: _#_Extension|_b#isSet:
+   lateFieldName=_Extension|_b,
+   lateFieldTarget=_#_Extension|_b,
+   lateIsSetField
+  */
+  /*member: _Extension|_b:
+   lateFieldGetter,
+   lateFieldName=_Extension|_b,
+   lateFieldTarget=_#_Extension|_b
+  */
+  /*member: _Extension|_b=:
+   lateFieldName=_Extension|_b,
+   lateFieldSetter,
+   lateFieldTarget=_#_Extension|_b
+  */
+  static late int? _b;
+}
diff --git a/pkg/front_end/test/predicates/data/marker.options b/pkg/front_end/test/predicates/data/marker.options
index afd83e5..1053541 100644
--- a/pkg/front_end/test/predicates/data/marker.options
+++ b/pkg/front_end/test/predicates/data/marker.options
@@ -1 +1,2 @@
-cfe=pkg/front_end/test/predicates/predicate_test.dart
+is-null=pkg/front_end/test/predicates/predicate_test.dart
+sentinel=pkg/front_end/test/predicates/predicate_test.dart
diff --git a/pkg/front_end/test/predicates/predicate_test.dart b/pkg/front_end/test/predicates/predicate_test.dart
index f62f803..5d98cff 100644
--- a/pkg/front_end/test/predicates/predicate_test.dart
+++ b/pkg/front_end/test/predicates/predicate_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
@@ -9,12 +11,18 @@
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:_fe_analyzer_shared/src/testing/features.dart';
 import 'package:front_end/src/api_prototype/experimental_flags.dart';
+import 'package:front_end/src/base/nnbd_mode.dart';
 import 'package:front_end/src/testing/id_extractor.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:front_end/src/api_prototype/lowering_predicates.dart';
 import 'package:kernel/ast.dart';
+import 'package:kernel/src/printer.dart';
 import 'package:kernel/target/targets.dart';
 
+const String isNullMarker = 'is-null';
+const String sentinelMarker = 'sentinel';
+
 main(List<String> args) async {
   Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
   await runTests<Features>(dataDir,
@@ -22,20 +30,33 @@
       createUriForFileName: createUriForFileName,
       onFailure: onFailure,
       runTest: runTestFor(const PredicateDataComputer(), [
-        const TestConfig(cfeMarker, 'cfe',
+        const TestConfig(isNullMarker, 'use is-null',
             explicitExperimentalFlags: const {
               ExperimentalFlag.nonNullable: true
             },
             targetFlags: const TargetFlags(
-                forceLateLoweringsForTesting: LateLowering.all))
+                forceLateLoweringsForTesting: LateLowering.all,
+                forceLateLoweringSentinelForTesting: false),
+            nnbdMode: NnbdMode.Strong),
+        const TestConfig(sentinelMarker, 'use sentinel',
+            explicitExperimentalFlags: const {
+              ExperimentalFlag.nonNullable: true
+            },
+            targetFlags: const TargetFlags(
+                forceLateLoweringsForTesting: LateLowering.all,
+                forceLateLoweringSentinelForTesting: true),
+            nnbdMode: NnbdMode.Strong)
       ]));
 }
 
 class Tags {
   static const String lateField = 'lateField';
+  static const String lateFieldName = 'lateFieldName';
   static const String lateIsSetField = 'lateIsSetField';
   static const String lateFieldGetter = 'lateFieldGetter';
   static const String lateFieldSetter = 'lateFieldSetter';
+  static const String lateFieldTarget = 'lateFieldTarget';
+  static const String lateFieldInitializer = 'lateFieldInitializer';
 
   static const String lateLocal = 'lateLocal';
   static const String lateIsSetLocal = 'lateIsSetLocal';
@@ -95,19 +116,44 @@
       Features features = new Features();
       if (isLateLoweredField(node)) {
         features.add(Tags.lateField);
+        features[Tags.lateFieldName] =
+            extractFieldNameFromLateLoweredField(node).text;
       }
       if (isLateLoweredIsSetField(node)) {
         features.add(Tags.lateIsSetField);
+        features[Tags.lateFieldName] =
+            extractFieldNameFromLateLoweredIsSetField(node).text;
+      }
+      Field target = getLateFieldTarget(node);
+      if (target != null) {
+        features[Tags.lateFieldTarget] = getQualifiedMemberName(target);
+      }
+      Expression initializer = getLateFieldInitializer(node);
+      if (initializer != null) {
+        features[Tags.lateFieldInitializer] =
+            initializer.toText(astTextStrategyForTesting);
       }
       return features;
     } else if (node is Procedure) {
       Features features = new Features();
       if (isLateLoweredFieldGetter(node)) {
         features.add(Tags.lateFieldGetter);
+        features[Tags.lateFieldName] =
+            extractFieldNameFromLateLoweredFieldGetter(node).text;
       }
-
       if (isLateLoweredFieldSetter(node)) {
         features.add(Tags.lateFieldSetter);
+        features[Tags.lateFieldName] =
+            extractFieldNameFromLateLoweredFieldSetter(node).text;
+      }
+      Field target = getLateFieldTarget(node);
+      if (target != null) {
+        features[Tags.lateFieldTarget] = getQualifiedMemberName(target);
+      }
+      Expression initializer = getLateFieldInitializer(node);
+      if (initializer != null) {
+        features[Tags.lateFieldInitializer] =
+            initializer.toText(astTextStrategyForTesting);
       }
       return features;
     }
diff --git a/pkg/front_end/test/read_dill_from_binary_md_test.dart b/pkg/front_end/test/read_dill_from_binary_md_test.dart
index 2331db5..fc73545 100644
--- a/pkg/front_end/test/read_dill_from_binary_md_test.dart
+++ b/pkg/front_end/test/read_dill_from_binary_md_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.
 
+// @dart = 2.9
+
 import 'dart:io' show File, Platform;
 
 import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags;
diff --git a/pkg/front_end/test/relativize_test.dart b/pkg/front_end/test/relativize_test.dart
index bc8a132..28c4acc 100644
--- a/pkg/front_end/test/relativize_test.dart
+++ b/pkg/front_end/test/relativize_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/util/relativize.dart';
 import 'package:test/test.dart';
 
diff --git a/pkg/front_end/test/resolve_input_uri_test.dart b/pkg/front_end/test/resolve_input_uri_test.dart
index f8eda33..3705440 100644
--- a/pkg/front_end/test/resolve_input_uri_test.dart
+++ b/pkg/front_end/test/resolve_input_uri_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/util/relativize.dart';
 import 'package:expect/expect.dart' show Expect;
 import 'package:front_end/src/fasta/resolve_input_uri.dart';
diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index 08f0bc6..7b59523 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_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.
 
+// @dart=2.9
+
 import 'dart:convert';
 
 import 'package:_fe_analyzer_shared/src/scanner/error_token.dart' as fasta;
diff --git a/pkg/front_end/test/scanner_replacement_test.dart b/pkg/front_end/test/scanner_replacement_test.dart
index a523793..867e68e 100644
--- a/pkg/front_end/test/scanner_replacement_test.dart
+++ b/pkg/front_end/test/scanner_replacement_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/scanner/token.dart' as fasta;
 import 'package:_fe_analyzer_shared/src/scanner/error_token.dart' as fasta;
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index d6cdad2..4a62db4 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/base/errors.dart';
 import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
     show AbstractScanner, ScannerConfiguration;
diff --git a/pkg/front_end/test/scheme_based_file_system_test.dart b/pkg/front_end/test/scheme_based_file_system_test.dart
index e6b374b..f5c018e 100644
--- a/pkg/front_end/test/scheme_based_file_system_test.dart
+++ b/pkg/front_end/test/scheme_based_file_system_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/api_prototype/file_system.dart';
 import 'package:front_end/src/scheme_based_file_system.dart';
 
diff --git a/pkg/front_end/test/severity_index_test.dart b/pkg/front_end/test/severity_index_test.dart
index 2077e6d..8dc6f14 100644
--- a/pkg/front_end/test/severity_index_test.dart
+++ b/pkg/front_end/test/severity_index_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
 /// Test that Severity has the expected indexes. Note that this is important
diff --git a/pkg/front_end/test/simple_stats.dart b/pkg/front_end/test/simple_stats.dart
index 062d59d..b163e67 100644
--- a/pkg/front_end/test/simple_stats.dart
+++ b/pkg/front_end/test/simple_stats.dart
@@ -1,3 +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.md file.
+
+// @dart = 2.9
+
 import 'dart:math' as math;
 
 class SimpleTTestStat {
diff --git a/pkg/front_end/test/spell_checking_cleanup_lists.dart b/pkg/front_end/test/spell_checking_cleanup_lists.dart
index af7d5bd..6f38991 100644
--- a/pkg/front_end/test/spell_checking_cleanup_lists.dart
+++ b/pkg/front_end/test/spell_checking_cleanup_lists.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.9
+
 import 'dart:io';
 
 import 'spell_checking_utils.dart' as spell;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 6c4e50f..e422e9d 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -20,6 +20,8 @@
 acon
 acov
 across
+activated
+adequate
 adi
 affecting
 afterwards
@@ -33,8 +35,10 @@
 aligned
 alive
 allocate
+allocator
 altered
 analogous
+analogy
 annotate
 ansi
 answering
@@ -175,6 +179,7 @@
 cl
 claim
 claimed
+claims
 clamp
 clarification
 clashes
@@ -326,6 +331,7 @@
 disjoint
 dispatched
 distribute
+diverged
 divided
 dmitryas
 doc
@@ -372,14 +378,17 @@
 eof
 eq
 equation
+erased
 erasure
 es
+establish
 established
 estimate
 eval
 exhausted
 existentially
 exp
+expando
 expense
 exportable
 exportee
@@ -396,6 +405,7 @@
 factored
 fangorn
 fasta
+favored
 favoring
 fc
 fcon
@@ -417,6 +427,7 @@
 fieldformal
 file's
 filenames
+finally's
 finv
 firsts
 fishy
@@ -433,6 +444,7 @@
 foo
 foobar
 footer
+forcing
 foreign
 formed
 former
@@ -454,6 +466,8 @@
 gardening
 gen
 generation
+getable
+getables
 gets
 getter1a
 getter1b
@@ -481,8 +495,10 @@
 gzip
 gzipped
 h
+hacky
 hadn't
 hang
+hardcode
 harness
 hashes
 hashing
@@ -496,6 +512,7 @@
 highlights
 hillerstrom
 histogram
+history
 hit
 hoc
 hopefully
@@ -524,6 +541,7 @@
 implying
 importantly
 imprecise
+improperly
 inapplicable
 inc
 incomparable
@@ -534,6 +552,8 @@
 indexing
 indirection
 individual
+inequality
+influence
 informative
 infos
 init
@@ -555,6 +575,7 @@
 interleaved
 intermediate
 interpolations
+interrupted
 intersects
 interval
 intervals
@@ -596,9 +617,11 @@
 k’s
 l
 lacks
+lags
 lang
 largest
 lattice
+launched
 launcher
 layer
 layout
@@ -742,6 +765,7 @@
 nullary
 nullification
 nullify
+nullness
 nulls
 o
 oauth
@@ -818,6 +842,7 @@
 pi
 picking
 pkg
+play
 player
 plugin
 pm
@@ -836,12 +861,14 @@
 preexisted
 preexisting
 preorder
+presubmit
 prev
 prime
 printer
 printf
 println
 proc
+proceeds
 producers
 product
 progresses
@@ -894,7 +921,10 @@
 react
 realign
 realise
+reapplies
 reassigned
+rebased
+rebasing
 rebind
 rebuild
 rebuilds
@@ -902,6 +932,7 @@
 recalculation
 recall
 received
+receivers
 recheck
 recognizing
 recompiled
@@ -926,6 +957,7 @@
 registering
 rehash
 reindexed
+reinstate
 reissued
 rejoin
 relatively
@@ -956,6 +988,7 @@
 resumed
 ret
 reusage
+rewinds
 rewrites
 rewrote
 rf
@@ -976,6 +1009,7 @@
 rs
 runnable
 s
+sanitizing
 saw
 say
 sb
@@ -986,6 +1020,7 @@
 sdk's
 seconds
 sections
+selectively
 selectors
 semantically
 semver
@@ -997,6 +1032,9 @@
 serve
 server
 service
+session
+setable
+setables
 setaf
 sh
 sha1hash
@@ -1043,6 +1081,7 @@
 sparse
 spec
 spec'ed
+specialization
 specially
 specifics
 speeding
@@ -1052,11 +1091,13 @@
 sra
 srawlins
 src
+ssa
 st
 stability
 stacktrace
 stacktraces
 stale
+stand
 starter
 statics
 stderr
@@ -1067,6 +1108,7 @@
 sticky
 stmt
 stopped
+storage
 str
 strategies
 streak
@@ -1165,6 +1207,7 @@
 tops
 tput
 tracker
+traditional
 transformers
 transforming
 translation
@@ -1173,6 +1216,7 @@
 trees
 tricky
 trips
+trivially
 ts
 tty
 tuple
@@ -1205,12 +1249,15 @@
 unconditionally
 unconstrained
 undeclare
+undergo
 undo
 undoable
 unequal
 unescape
 unexact
+unexpectedly
 unfinalized
+unfold
 unfolds
 unfuture
 unfutured
@@ -1234,6 +1281,7 @@
 unpleasant
 unreachable
 unseen
+unset
 unshadowed
 unsortable
 unsound
@@ -1256,11 +1304,13 @@
 util
 utils
 v
+validly
 variable's
 variances
 variant
 variants
 variation
+vars
 vary
 vb
 vector
@@ -1270,6 +1320,7 @@
 vice
 video
 violated
+violating
 visit*
 visitors
 visits
@@ -1302,6 +1353,7 @@
 worthwhile
 worthy
 writeln
+wrongfully
 wrt
 wtf
 www
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 7806bde..9b60eea 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -119,6 +119,7 @@
 although
 altogether
 always
+ambiguity
 ambiguous
 among
 amongst
@@ -649,6 +650,7 @@
 convenient
 conventional
 conventions
+conversion
 convert
 converted
 convertible
@@ -827,6 +829,7 @@
 detected
 detecting
 detection
+detector
 detects
 determination
 determine
@@ -994,6 +997,7 @@
 enforcement
 engine
 engineers
+enhance
 enhancing
 enough
 ensure
@@ -1138,6 +1142,7 @@
 facilitate
 fact
 fact's
+facto
 factories
 factory
 facts
@@ -1213,6 +1218,7 @@
 flattened
 flexibility
 flexible
+flip
 float
 flow
 flow's
@@ -1280,6 +1286,7 @@
 gathering
 general
 generalized
+generalizes
 generally
 generate
 generated
@@ -1594,6 +1601,7 @@
 invalidation
 invariant
 invariantly
+inversion
 invert
 inverted
 investigate
@@ -2385,6 +2393,7 @@
 reasoning
 reasons
 reassign
+rebase
 receive
 receiver
 recent
@@ -2428,6 +2437,7 @@
 references
 referencing
 referred
+referring
 refers
 refine
 refinement
@@ -3333,6 +3343,7 @@
 worklist
 works
 world
+worry
 worth
 would
 wouldn't
diff --git a/pkg/front_end/test/spell_checking_list_messages.txt b/pkg/front_end/test/spell_checking_list_messages.txt
index debea18..f8c8578 100644
--- a/pkg/front_end/test/spell_checking_list_messages.txt
+++ b/pkg/front_end/test/spell_checking_list_messages.txt
@@ -10,6 +10,8 @@
 # automatic tools might move it to the top of the file.
 
 JS
+adjusting
+api
 argument(s)
 assigning
 b
@@ -28,6 +30,7 @@
 e.g
 enum's
 f
+ffi
 flutter_runner
 futureor
 h
@@ -40,6 +43,7 @@
 name.stack
 nameokempty
 native('native
+natively
 nativetype
 nnbd
 nosuchmethod
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 49cac17..d3bc3e1a 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -25,6 +25,7 @@
 amortized
 analyses
 animal
+animated
 annoying
 anon
 aoo
@@ -48,8 +49,10 @@
 bail
 bailing
 bailout
+barbar
 bash
 bat
+bazbaz
 bbb
 bc
 bench
@@ -95,6 +98,7 @@
 cc
 ccc
 cell
+cf
 charset
 checkme
 checkout
@@ -153,6 +157,7 @@
 ctrl
 cumulative
 cursor
+cuts
 cx
 dacoharkes
 dadd
@@ -276,11 +281,25 @@
 foo13
 foo14
 foo15
+foo1a
+foo1b
 foo2
+foo2a
+foo2b
+foo3a
+foo3b
 foo4
+foo4a
+foo4b
 foo5
+foo5a
+foo5b
 foo6
+foo6a
+foo6b
 foo7
+foo7a
+foo7b
 foo8
 foo9
 foo\"bar'baz
@@ -298,6 +317,8 @@
 fulfill
 func
 futures
+fuzz
+fuzzing
 fx
 gallery
 gamma
@@ -343,13 +364,16 @@
 in1
 in2
 inclosure
+inconsistencies
 increased
 incrementally
 increments
 indents
+ing
 initializer2
 inlinable
 inlineable
+inlines
 instance2
 insufficient
 intdiv
@@ -488,7 +512,11 @@
 okay
 ol
 onull
+oo
+oocf
 ooo
+oovf
+opacity
 operate
 ops
 optimal
@@ -502,6 +530,7 @@
 pack
 paging
 paint
+parameterized
 party
 pause
 paused
@@ -538,6 +567,7 @@
 protected
 proved
 provider
+proxy
 pseudocode
 pubspec
 pv
@@ -597,11 +627,13 @@
 scheduler
 screen
 scripts
+scroll
 sdkroot
 sdks
 secondary
 segment
 selection
+semifuzz
 sensitive
 services
 setter1a
@@ -705,6 +737,7 @@
 unassignment
 unawaited
 unbreak
+uncaught
 unconverted
 uncover
 uncovers
@@ -728,6 +761,7 @@
 vars
 verbatim
 versioned
+vf
 vp
 vt
 vte
@@ -754,3 +788,4 @@
 year
 yxxx
 yy
+zz
diff --git a/pkg/front_end/test/spell_checking_utils.dart b/pkg/front_end/test/spell_checking_utils.dart
index b0f33a3..c08fb4c 100644
--- a/pkg/front_end/test/spell_checking_utils.dart
+++ b/pkg/front_end/test/spell_checking_utils.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.9
+
 import 'dart:io' show File, stdin, stdout;
 
 import "utils/io_utils.dart";
diff --git a/pkg/front_end/test/spell_checking_utils_test.dart b/pkg/front_end/test/spell_checking_utils_test.dart
index 658c88e..07c8904 100644
--- a/pkg/front_end/test/spell_checking_utils_test.dart
+++ b/pkg/front_end/test/spell_checking_utils_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.
 
+// @dart = 2.9
+
 import 'spell_checking_utils.dart';
 
 void main() {
diff --git a/pkg/front_end/test/spelling_test_base.dart b/pkg/front_end/test/spelling_test_base.dart
index bd0ea9f..f63a61c 100644
--- a/pkg/front_end/test/spelling_test_base.dart
+++ b/pkg/front_end/test/spelling_test_base.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.9
+
 import 'dart:io' show File, Platform;
 
 import 'dart:typed_data' show Uint8List;
diff --git a/pkg/front_end/test/spelling_test_external_targets.dart b/pkg/front_end/test/spelling_test_external_targets.dart
index 79ff96c..9bae907 100644
--- a/pkg/front_end/test/spelling_test_external_targets.dart
+++ b/pkg/front_end/test/spelling_test_external_targets.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.9
+
 import 'dart:io' show Directory, File, FileSystemEntity;
 
 import 'package:testing/testing.dart'
diff --git a/pkg/front_end/test/spelling_test_not_src_suite.dart b/pkg/front_end/test/spelling_test_not_src_suite.dart
index a6205de..6504052 100644
--- a/pkg/front_end/test/spelling_test_not_src_suite.dart
+++ b/pkg/front_end/test/spelling_test_not_src_suite.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.9
+
 import 'package:testing/testing.dart' show Chain, runMe;
 
 import 'spelling_test_base.dart';
diff --git a/pkg/front_end/test/spelling_test_src_suite.dart b/pkg/front_end/test/spelling_test_src_suite.dart
index dfd1117..4ea5bb0 100644
--- a/pkg/front_end/test/spelling_test_src_suite.dart
+++ b/pkg/front_end/test/spelling_test_src_suite.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.9
+
 import 'package:testing/testing.dart' show Chain, runMe;
 
 import 'spelling_test_base.dart';
diff --git a/pkg/front_end/test/split_dill_test.dart b/pkg/front_end/test/split_dill_test.dart
index 0ed6a0f..24e4782 100644
--- a/pkg/front_end/test/split_dill_test.dart
+++ b/pkg/front_end/test/split_dill_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, File, Platform, Process, ProcessResult;
 
 import 'dart:typed_data' show Uint8List;
diff --git a/pkg/front_end/test/src/base/libraries_specification_test.dart b/pkg/front_end/test/src/base/libraries_specification_test.dart
index 9d488aa..14cbae1 100644
--- a/pkg/front_end/test/src/base/libraries_specification_test.dart
+++ b/pkg/front_end/test/src/base/libraries_specification_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/base/libraries_specification.dart';
 import 'package:test/test.dart';
 
diff --git a/pkg/front_end/test/src/base/processed_options_test.dart b/pkg/front_end/test/src/base/processed_options_test.dart
index b004fb1..f8a87cb 100644
--- a/pkg/front_end/test/src/base/processed_options_test.dart
+++ b/pkg/front_end/test/src/base/processed_options_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/api_prototype/memory_file_system.dart';
 import 'package:front_end/src/base/processed_options.dart';
diff --git a/pkg/front_end/test/standard_file_system_test.dart b/pkg/front_end/test/standard_file_system_test.dart
index 5f5fd02..a7becd7 100644
--- a/pkg/front_end/test/standard_file_system_test.dart
+++ b/pkg/front_end/test/standard_file_system_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 // SharedOptions=--supermixin
 
+// @dart = 2.9
+
 library front_end.test.standard_file_system_test;
 
 import 'dart:convert';
diff --git a/pkg/front_end/test/static_types/analysis_helper.dart b/pkg/front_end/test/static_types/analysis_helper.dart
index f6c6981..539d58e 100644
--- a/pkg/front_end/test/static_types/analysis_helper.dart
+++ b/pkg/front_end/test/static_types/analysis_helper.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.9
+
 import 'dart:convert' as json;
 import 'dart:io';
 
@@ -263,6 +265,24 @@
   }
 
   @override
+  void visitDynamicGet(DynamicGet node) {
+    registerError(node, "Dynamic access of '${node.name}'.");
+    super.visitDynamicGet(node);
+  }
+
+  @override
+  void visitDynamicSet(DynamicSet node) {
+    registerError(node, "Dynamic update to '${node.name}'.");
+    super.visitDynamicSet(node);
+  }
+
+  @override
+  void visitDynamicInvocation(DynamicInvocation node) {
+    registerError(node, "Dynamic invocation of '${node.name}'.");
+    super.visitDynamicInvocation(node);
+  }
+
+  @override
   void visitPropertyGet(PropertyGet node) {
     DartType receiverType = node.receiver.getStaticType(staticTypeContext);
     if (receiverType is DynamicType && node.interfaceTarget == null) {
diff --git a/pkg/front_end/test/static_types/cfe_allowed.json b/pkg/front_end/test/static_types/cfe_allowed.json
index 9dd0b5b..63088f0 100644
--- a/pkg/front_end/test/static_types/cfe_allowed.json
+++ b/pkg/front_end/test/static_types/cfe_allowed.json
@@ -3,9 +3,6 @@
     "Dynamic invocation of 'split'.": 1
   },
   "pkg/front_end/lib/src/base/libraries_specification.dart": {
-    "Dynamic invocation of 'containsKey'.": 1,
-    "Dynamic invocation of '[]'.": 8,
-    "Dynamic invocation of 'forEach'.": 1,
     "Dynamic invocation of 'toList'.": 1,
     "Dynamic invocation of 'map'.": 1,
     "Dynamic invocation of '[]='.": 1
@@ -17,7 +14,6 @@
   "pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart": {
     "Dynamic access of 'data'.": 1,
     "Dynamic access of 'start'.": 1,
-    "Dynamic access of 'length'.": 1,
     "Dynamic access of 'boolValue'.": 2
   },
   "pkg/kernel/lib/transformations/value_class.dart": {
@@ -39,14 +35,5 @@
   },
   "pkg/front_end/lib/src/fasta/kernel/body_builder.dart": {
     "Dynamic invocation of 'buildForEffect'.": 1
-  },
-  "pkg/_fe_analyzer_shared/lib/src/util/link.dart": {
-    "Dynamic access of 'isEmpty'.": 1
-  },
-  "pkg/_fe_analyzer_shared/lib/src/util/link_implementation.dart": {
-    "Dynamic access of 'isNotEmpty'.": 1,
-    "Dynamic access of 'head'.": 1,
-    "Dynamic access of 'tail'.": 1,
-    "Dynamic access of 'isEmpty'.": 1
   }
 }
\ No newline at end of file
diff --git a/pkg/front_end/test/static_types/cfe_dynamic_test.dart b/pkg/front_end/test/static_types/cfe_dynamic_test.dart
index 306dc85..672ff9d 100644
--- a/pkg/front_end/test/static_types/cfe_dynamic_test.dart
+++ b/pkg/front_end/test/static_types/cfe_dynamic_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.
 
+// @dart = 2.9
+
 import 'analysis_helper.dart';
 
 /// Filter function used to only analysis cfe source code.
diff --git a/pkg/front_end/test/static_types/data/binary.dart b/pkg/front_end/test/static_types/data/binary.dart
new file mode 100644
index 0000000..edb5d12
--- /dev/null
+++ b/pkg/front_end/test/static_types/data/binary.dart
@@ -0,0 +1,78 @@
+// 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.
+
+/*cfe.library: nnbd=false*/
+
+/*cfe:nnbd.library: nnbd=true*/
+
+num numTopLevel = /*cfe.int*/ /*cfe:nnbd.int!*/ 0;
+int intTopLevel = /*cfe.int*/ /*cfe:nnbd.int!*/ 0;
+double doubleTopLevel = /*cfe.double*/ /*cfe:nnbd.double!*/ 0.0;
+dynamic dynamicTopLevel = /*cfe.int*/ /*cfe:nnbd.int!*/ 0;
+
+main() {
+  /*cfe.num*/ /*cfe:nnbd.num!*/ numTopLevel
+      /*cfe.invoke: num*/ /*cfe:nnbd.invoke: num!*/ +
+      /*cfe.num*/ /*cfe:nnbd.num!*/ numTopLevel;
+
+  /*cfe.num*/ /*cfe:nnbd.num!*/ numTopLevel
+      /*cfe.invoke: num*/ /*cfe:nnbd.invoke: num!*/ +
+      /*cfe.int*/ /*cfe:nnbd.int!*/ intTopLevel;
+
+  /*cfe.num*/ /*cfe:nnbd.num!*/ numTopLevel
+      /*cfe.invoke: num*/ /*cfe:nnbd.invoke: double!*/ +
+      /*cfe.double*/ /*cfe:nnbd.double!*/ doubleTopLevel;
+
+  /*cfe.num*/ /*cfe:nnbd.num!*/ numTopLevel
+      /*cfe.invoke: num*/ /*cfe:nnbd.invoke: num!*/ +
+      /*cfe.as: num*/ /*cfe:nnbd.as: num!*/ /*dynamic*/ dynamicTopLevel;
+
+  /*cfe.int*/ /*cfe:nnbd.int!*/ intTopLevel
+      /*cfe.invoke: num*/ /*cfe:nnbd.invoke: num!*/ +
+      /*cfe.num*/ /*cfe:nnbd.num!*/ numTopLevel;
+
+  /*cfe.int*/ /*cfe:nnbd.int!*/ intTopLevel
+      /*cfe.invoke: int*/ /*cfe:nnbd.invoke: int!*/ +
+      /*cfe.int*/ /*cfe:nnbd.int!*/ intTopLevel;
+
+  /*cfe.int*/ /*cfe:nnbd.int!*/ intTopLevel
+      /*cfe.invoke: double*/ /*cfe:nnbd.invoke: double!*/ +
+      /*cfe.double*/ /*cfe:nnbd.double!*/ doubleTopLevel;
+
+  /*cfe.int*/ /*cfe:nnbd.int!*/ intTopLevel
+      /*cfe.invoke: num*/ /*cfe:nnbd.invoke: num!*/ +
+      /*cfe.as: num*/ /*cfe:nnbd.as: num!*/ /*dynamic*/ dynamicTopLevel;
+
+  /*cfe.double*/ /*cfe:nnbd.double!*/ doubleTopLevel
+      /*cfe.invoke: double*/ /*cfe:nnbd.invoke: double!*/ +
+      /*cfe.num*/ /*cfe:nnbd.num!*/ numTopLevel;
+
+  /*cfe.double*/ /*cfe:nnbd.double!*/ doubleTopLevel
+      /*cfe.invoke: double*/ /*cfe:nnbd.invoke: double!*/ +
+      /*cfe.int*/ /*cfe:nnbd.int!*/ intTopLevel;
+
+  /*cfe.double*/ /*cfe:nnbd.double!*/ doubleTopLevel
+      /*cfe.invoke: double*/ /*cfe:nnbd.invoke: double!*/ +
+      /*cfe.double*/ /*cfe:nnbd.double!*/ doubleTopLevel;
+
+  /*cfe.double*/ /*cfe:nnbd.double!*/ doubleTopLevel
+      /*cfe.invoke: double*/ /*cfe:nnbd.invoke: double!*/ +
+      /*cfe.as: num*/ /*cfe:nnbd.as: num!*/ /*dynamic*/ dynamicTopLevel;
+
+  /*dynamic*/ dynamicTopLevel
+      /*invoke: dynamic*/ +
+      /*cfe.num*/ /*cfe:nnbd.num!*/ numTopLevel;
+
+  /*dynamic*/ dynamicTopLevel
+      /*invoke: dynamic*/ +
+      /*cfe.int*/ /*cfe:nnbd.int!*/ intTopLevel;
+
+  /*dynamic*/ dynamicTopLevel
+      /*invoke: dynamic*/ +
+      /*cfe.double*/ /*cfe:nnbd.double!*/ doubleTopLevel;
+
+  /*dynamic*/ dynamicTopLevel
+      /*invoke: dynamic*/ +
+      /*dynamic*/ dynamicTopLevel;
+}
diff --git a/pkg/front_end/test/static_types/data/if_null.dart b/pkg/front_end/test/static_types/data/if_null.dart
index 2f38469..c4e18b6 100644
--- a/pkg/front_end/test/static_types/data/if_null.dart
+++ b/pkg/front_end/test/static_types/data/if_null.dart
@@ -12,10 +12,11 @@
   String? foo() => /*Null*/ null;
   String bar() => /*String!*/ "bar";
 
-  var s = /*invoke: String?*/ foo() ?? /*invoke: String!*/ bar();
+  var s = /*invoke: String?*/ foo() /*String!*/ ?? /*invoke: String!*/ bar();
   /*String!*/ s;
 
-  String s2 = /*invoke: String?*/ hest1/*<String?>*/() ?? /*String!*/ "fisk";
+  String
+      s2 = /*invoke: String?*/ hest1/*<String?>*/() /*String!*/ ?? /*String!*/ "fisk";
 }
 
 // ------------------------- If-null property set. -----------------------------
@@ -24,22 +25,24 @@
 }
 
 test2(A2 a) {
-  var s =
-      (/*A2!*/ a. /*String?*/ /*update: String!*/ foo ??= /*String!*/ "bar");
+  var s = (/*A2!*/ a
+      . /*String?*/ /*update: String!*/ foo /*String!*/ ??= /*String!*/ "bar");
   /*String!*/ s;
 }
 
 // ------------------------------ If-null set. ---------------------------------
 test3() {
   String? s = /*Null*/ null;
-  var s2 = (/*String?*/ /*update: String!*/ s ??= /*String!*/ "bar");
+  var s2 =
+      (/*String?*/ /*update: String!*/ s /*String!*/ ??= /*String!*/ "bar");
   /*String!*/ s2;
 }
 
 // --------------------------- If-null index set. ------------------------------
 test4() {
   List<String?> list = /*List<String?>!*/ [/*Null*/ null];
-  var s = (/*List<String?>!*/ list /*String?*/ /*update: void*/ [/*int!*/ 0] ??=
+  var s = (/*List<String?>!*/ list /*String?*/ /*update: void*/ [
+          /*int!*/ 0] /*String!*/ ??=
       /*String!*/ "bar");
   /*String!*/ s;
 }
@@ -52,7 +55,7 @@
 
 class B5 extends A5 {
   test5() {
-    var s = (super[/*int!*/ 0] ??= /*String!*/ "bar");
+    var s = (super[/*int!*/ 0] /*String!*/ ??= /*String!*/ "bar");
     /*String!*/ s;
   }
 }
@@ -65,7 +68,7 @@
 
 test6() {
   var s = (E6(/*double!*/ 3.14) /*invoke: String?|void*/ [
-      /*int!*/ 0] ??= /*String!*/ "bar");
+      /*int!*/ 0] /*String!*/ ??= /*String!*/ "bar");
   /*String!*/ s;
 }
 
@@ -76,12 +79,12 @@
 }
 
 test7(A7? a) {
-  var s =
-      (/*A7?*/ a?. /*String!*/ /*update: String!*/ foo ??= /*String!*/ "bar");
+  var s = (/*A7?|String?|String!*/ a
+      ?. /*String!*/ /*update: String!*/ foo ??= /*String!*/ "bar");
   /*String?*/ s;
 
-  var s2 =
-      (/*A7?*/ a?. /*String?*/ /*update: String!*/ bar ??= /*String!*/ "bar");
+  var s2 = (/*A7?|String?|String!*/ a
+      ?. /*String?*/ /*update: String!*/ bar ??= /*String!*/ "bar");
   /*String?*/ s2;
 }
 
diff --git a/pkg/front_end/test/static_types/data/never.dart b/pkg/front_end/test/static_types/data/never.dart
index b86d17f..b41471f 100644
--- a/pkg/front_end/test/static_types/data/never.dart
+++ b/pkg/front_end/test/static_types/data/never.dart
@@ -7,11 +7,11 @@
 // TODO(johnniwinther): Ensure static type of Never access is Never.
 
 propertyGet(Never never) {
-  var v1 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.dynamic*/ foo;
-  var v2 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.int!*/ hashCode;
-  var v3 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.Type!*/ runtimeType;
-  var v4 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.dynamic*/ toString;
-  var v5 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.dynamic*/ noSuchMethod;
+  var v1 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.Never*/ foo;
+  var v2 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.Never*/ hashCode;
+  var v3 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.Never*/ runtimeType;
+  var v4 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.Never*/ toString;
+  var v5 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.Never*/ noSuchMethod;
 }
 
 propertySet(Never never) {
@@ -20,28 +20,28 @@
 }
 
 methodInvocation(Never never, Invocation invocation) {
-  var v1 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: dynamic*/ foo();
-  var v2 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: dynamic*/ hashCode();
-  var v3 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: dynamic*/ runtimeType();
-  var v4 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: dynamic*/ toString();
+  var v1 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: Never*/ foo();
+  var v2 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: Never*/ hashCode();
+  var v3 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: Never*/ runtimeType();
+  var v4 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: Never*/ toString();
   var v5 = /*cfe:nnbd.Never*/ never
-      . /*cfe:nnbd.invoke: dynamic*/ toString(foo: /*cfe:nnbd.int!*/ 42);
-  var v6 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: dynamic*/ noSuchMethod(
+      . /*cfe:nnbd.invoke: Never*/ toString(foo: /*cfe:nnbd.int!*/ 42);
+  var v6 = /*cfe:nnbd.Never*/ never. /*cfe:nnbd.invoke: Never*/ noSuchMethod(
       /*cfe:nnbd.Invocation!*/ invocation);
   var v7 = /*cfe:nnbd.Never*/ never
-      . /*cfe:nnbd.invoke: dynamic*/ noSuchMethod(/*cfe:nnbd.int!*/ 42);
+      . /*cfe:nnbd.invoke: Never*/ noSuchMethod(/*cfe:nnbd.int!*/ 42);
 }
 
 equals(Never never) {
-  var v1 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.invoke: bool!*/ == /*cfe:nnbd.Null*/ null;
-  var v2 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.invoke: bool!*/ == /*cfe:nnbd.Never*/ never;
+  var v1 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.invoke: bool!*/ == null;
+  var v2 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.invoke: Never*/ == /*cfe:nnbd.Never*/ never;
 }
 
 operator(Never never) {
-  var v1 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.invoke: dynamic*/ + /*cfe:nnbd.Never*/ never;
-  var v2 = /*cfe:nnbd.invoke: dynamic*/ - /*cfe:nnbd.Never*/ never;
-  var v3 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.dynamic*/ [
+  var v1 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.invoke: Never*/ + /*cfe:nnbd.Never*/ never;
+  var v2 = /*cfe:nnbd.invoke: Never*/ - /*cfe:nnbd.Never*/ never;
+  var v3 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.Never*/ [
       /*cfe:nnbd.Never*/ never];
-  var v4 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.update: dynamic*/ [
+  var v4 = /*cfe:nnbd.Never*/ never /*cfe:nnbd.update: Never*/ [
       /*cfe:nnbd.Never*/ never] = /*cfe:nnbd.Never*/ never;
 }
diff --git a/pkg/front_end/test/static_types/data/null_aware_for_in.dart b/pkg/front_end/test/static_types/data/null_aware_for_in.dart
index 48f0917..42c998b 100644
--- a/pkg/front_end/test/static_types/data/null_aware_for_in.dart
+++ b/pkg/front_end/test/static_types/data/null_aware_for_in.dart
@@ -17,5 +17,5 @@
       Class c in
       /*cfe.as: Iterable<dynamic>*/
       /*cfe:nnbd.as: Iterable<dynamic>!*/
-      /*dynamic*/ o?. /*dynamic*/ iterable) {}
+      /*dynamic|dynamic*/ o?. /*dynamic*/ iterable) {}
 }
diff --git a/pkg/front_end/test/static_types/data/prefix_postfix.dart b/pkg/front_end/test/static_types/data/prefix_postfix.dart
index b40092f..c2a58d9 100644
--- a/pkg/front_end/test/static_types/data/prefix_postfix.dart
+++ b/pkg/front_end/test/static_types/data/prefix_postfix.dart
@@ -243,7 +243,8 @@
 testInstanceOnClass(Class c) {
   /*cfe.Class*/
   /*cfe:nnbd.Class!*/
-  c. /*cfe.update: num*/ /*cfe:nnbd.update: num!*/
+  c. /*cfe.update: num*/
+          /*cfe:nnbd.update: num!*/
           /*cfe.num*/
           /*cfe:nnbd.num!*/
           numInstance
@@ -255,7 +256,8 @@
 
   /*cfe.Class*/
   /*cfe:nnbd.Class!*/
-  c. /*cfe.update: num*/ /*cfe:nnbd.update: num!*/
+  c. /*cfe.update: num*/
+          /*cfe:nnbd.update: num!*/
           /*cfe.num*/
           /*cfe:nnbd.num!*/
           numInstance
diff --git a/pkg/front_end/test/static_types/data/promoted_access.dart b/pkg/front_end/test/static_types/data/promoted_access.dart
index 3e87292..82085cb 100644
--- a/pkg/front_end/test/static_types/data/promoted_access.dart
+++ b/pkg/front_end/test/static_types/data/promoted_access.dart
@@ -13,9 +13,9 @@
       /*cfe.T & Class<dynamic>*/
       /*cfe:nnbd.T! & Class<dynamic>!*/
       o. /*invoke: dynamic*/ method(/*Null*/ null);
-      /*cfe.T & Class<dynamic>*/ /*cfe:nnbd.T! & Class<dynamic>!*/ o
+      /*cfe.T & Class<dynamic>|dynamic*/ /*cfe:nnbd.T! & Class<dynamic>!|dynamic*/ o
           ?. /*invoke: dynamic*/ method(/*Null*/ null);
-      /*cfe.T & Class<dynamic>*/ /*cfe:nnbd.T! & Class<dynamic>!*/ o
+      /*cfe.T & Class<dynamic>|dynamic*/ /*cfe:nnbd.T! & Class<dynamic>!|dynamic*/ o
           ?. /*dynamic*/ property;
     }
   }
@@ -26,9 +26,9 @@
     /*cfe.T & Class<dynamic>*/
     /*cfe:nnbd.T! & Class<dynamic>!*/
     o. /*invoke: dynamic*/ method(/*Null*/ null);
-    /*cfe.T & Class<dynamic>*/ /*cfe:nnbd.T! & Class<dynamic>!*/ o
+    /*cfe.T & Class<dynamic>|dynamic*/ /*cfe:nnbd.T! & Class<dynamic>!|dynamic*/ o
         ?. /*invoke: dynamic*/ method(/*Null*/ null);
-    /*cfe.T & Class<dynamic>*/ /*cfe:nnbd.T! & Class<dynamic>!*/ o
+    /*cfe.T & Class<dynamic>|dynamic*/ /*cfe:nnbd.T! & Class<dynamic>!|dynamic*/ o
         ?. /*dynamic*/ property;
   }
 }
diff --git a/pkg/front_end/test/static_types/static_type_test.dart b/pkg/front_end/test/static_types/static_type_test.dart
index cad8d52..c90118c 100644
--- a/pkg/front_end/test/static_types/static_type_test.dart
+++ b/pkg/front_end/test/static_types/static_type_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
diff --git a/pkg/front_end/test/summary_generator_test.dart b/pkg/front_end/test/summary_generator_test.dart
index d641234..04deb3b 100644
--- a/pkg/front_end/test/summary_generator_test.dart
+++ b/pkg/front_end/test/summary_generator_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.
 
+// @dart = 2.9
+
 import 'package:front_end/src/api_prototype/front_end.dart';
 import 'package:front_end/src/testing/compiler_common.dart';
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/test/test_generator_test.dart b/pkg/front_end/test/test_generator_test.dart
index 2ad6f36..8e35ddc 100644
--- a/pkg/front_end/test/test_generator_test.dart
+++ b/pkg/front_end/test/test_generator_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.
 
+// @dart = 2.9
+
 import 'dart:io' show exitCode, File, stdout;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart';
diff --git a/pkg/front_end/test/testing_utils.dart b/pkg/front_end/test/testing_utils.dart
index b966e74..ba228a0 100644
--- a/pkg/front_end/test/testing_utils.dart
+++ b/pkg/front_end/test/testing_utils.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.9
+
 import 'dart:io' show Directory, Process, ProcessResult;
 
 import 'package:testing/testing.dart' show Chain, TestDescription;
diff --git a/pkg/front_end/test/text_representation/data/expressions.dart b/pkg/front_end/test/text_representation/data/expressions.dart
index cbad9e3..4d70d21 100644
--- a/pkg/front_end/test/text_representation/data/expressions.dart
+++ b/pkg/front_end/test/text_representation/data/expressions.dart
@@ -382,7 +382,9 @@
 exprMap() => {0: "foo", 1: "bar"};
 
 /*member: exprAwait:await o*/
-exprAwait(o) async => await o;
+exprAwait(o) async {
+  await o;
+}
 
 /*member: exprLoadLibrary:prefix.loadLibrary()*/
 exprLoadLibrary() => prefix.loadLibrary();
@@ -421,12 +423,12 @@
       return t;
     };
 
-/*normal|limited.member: exprNullAware:let final Class? #0 = variable in #0.{Object.==}(null) ?{dynamic} null : #0{Class}.{Class.field}*/
-/*verbose.member: exprNullAware:let final expressions::Class? #0 = variable in #0.{dart.core::Object.==}(null) ?{dynamic} null : #0{expressions::Class}.{expressions::Class.field}*/
+/*normal|limited.member: exprNullAware:let final Class? #0 = variable in #0 == null ?{dynamic} null : #0{Class}.{Class.field}*/
+/*verbose.member: exprNullAware:let final expressions::Class? #0 = variable in #0 == null ?{dynamic} null : #0{expressions::Class}.{expressions::Class.field}*/
 exprNullAware(Class? variable) => variable?.field;
 
-/*normal|limited.member: exprIfNull:let final int? #0 = i in #0.{num.==}(null) ?{int} 42 : #0{int}*/
-/*verbose.member: exprIfNull:let final dart.core::int? #0 = i in #0.{dart.core::num.==}(null) ?{dart.core::int} 42 : #0{dart.core::int}*/
+/*normal|limited.member: exprIfNull:let final int? #0 = i in #0 == null ?{int} 42 : #0{int}*/
+/*verbose.member: exprIfNull:let final dart.core::int? #0 = i in #0 == null ?{dart.core::int} 42 : #0{dart.core::int}*/
 exprIfNull(int? i) => i ?? 42;
 
 /*normal|limited.member: exprNestedDeep:<Object>[1, <Object>[2, <Object>[3, <int>[4]]]]*/
@@ -483,3 +485,21 @@
 /*normal|limited.member: exprPrecedence4:(b ?{int} 0 : 1).{num.+}(2)*/
 /*verbose.member: exprPrecedence4:(b ?{dart.core::int} 0 : 1).{dart.core::num.+}(2)*/
 exprPrecedence4(bool b) => (b ? 0 : 1) + 2;
+
+/*member: exprAssignmentEqualsNull1:(a = b) == null*/
+exprAssignmentEqualsNull1(String a, String b) => (a = b) == null;
+
+/*member: exprAssignmentEqualsNull2:a = b == null*/
+exprAssignmentEqualsNull2(bool a, String b) => a = b == null;
+
+/*member: exprAssignmentEqualsNull3:a = b == null*/
+exprAssignmentEqualsNull3(bool a, String b) => a = (b == null);
+
+/*member: exprAssignmentEquals1:(a = b) == c*/
+exprAssignmentEquals1(String a, String b, String c) => (a = b) == c;
+
+/*member: exprAssignmentEquals2:a = b == c*/
+exprAssignmentEquals2(bool a, String b, String c) => a = b == c;
+
+/*member: exprAssignmentEquals3:a = b == c*/
+exprAssignmentEquals3(bool a, String b, String c) => a = (b == c);
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 362672b..22643b3 100644
--- a/pkg/front_end/test/text_representation/empty_reference_test.dart
+++ b/pkg/front_end/test/text_representation/empty_reference_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.
 
+// @dart = 2.9
+
 import 'package:expect/expect.dart';
 import 'package:kernel/ast.dart';
 import 'text_representation_test.dart';
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 6c6582b..a71ada8 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
@@ -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.9
+
 import 'package:expect/expect.dart';
 import 'package:front_end/src/fasta/kernel/collections.dart';
 import 'package:front_end/src/fasta/kernel/forest.dart';
@@ -588,7 +590,6 @@
           readOffset: TreeNode.noOffset,
           binaryOffset: TreeNode.noOffset,
           writeOffset: TreeNode.noOffset,
-          readOnlyReceiver: false,
           forEffect: false),
       '''
 0.foo += 1''');
@@ -608,7 +609,27 @@
 
 void _testSuperIndexSet() {}
 
-void _testExtensionIndexSet() {}
+void _testExtensionIndexSet() {
+  Library library = new Library(dummyUri);
+  Extension extension = new Extension(
+      name: 'Extension', typeParameters: [new TypeParameter('T')]);
+  library.addExtension(extension);
+  Procedure setter =
+      new Procedure(new Name(''), ProcedureKind.Method, new FunctionNode(null));
+  library.addProcedure(setter);
+
+  testExpression(
+      new ExtensionIndexSet(extension, null, new IntLiteral(0), setter,
+          new IntLiteral(1), new IntLiteral(2)),
+      '''
+Extension(0)[1] = 2''');
+
+  testExpression(
+      new ExtensionIndexSet(extension, [const VoidType()], new IntLiteral(0),
+          setter, new IntLiteral(1), new IntLiteral(2)),
+      '''
+Extension<void>(0)[1] = 2''');
+}
 
 void _testIfNullIndexSet() {}
 
@@ -616,7 +637,38 @@
 
 void _testIfNullExtensionIndexSet() {}
 
-void _testCompoundIndexSet() {}
+void _testCompoundIndexSet() {
+  testExpression(
+      new CompoundIndexSet(new IntLiteral(0), new IntLiteral(1), new Name('+'),
+          new IntLiteral(2),
+          forEffect: false, forPostIncDec: false),
+      '''
+0[1] += 2''');
+  testExpression(
+      new CompoundIndexSet(new IntLiteral(0), new IntLiteral(1), new Name('+'),
+          new IntLiteral(1),
+          forEffect: false, forPostIncDec: true),
+      '''
+0[1]++''');
+  testExpression(
+      new CompoundIndexSet(new IntLiteral(0), new IntLiteral(1), new Name('-'),
+          new IntLiteral(1),
+          forEffect: false, forPostIncDec: true),
+      '''
+0[1]--''');
+  testExpression(
+      new CompoundIndexSet(new IntLiteral(0), new IntLiteral(1), new Name('*'),
+          new IntLiteral(1),
+          forEffect: false, forPostIncDec: true),
+      '''
+0[1] *= 1''');
+  testExpression(
+      new CompoundIndexSet(new IntLiteral(0), new IntLiteral(1), new Name('+'),
+          new IntLiteral(2),
+          forEffect: false, forPostIncDec: true),
+      '''
+0[1] += 2''');
+}
 
 void _testNullAwareCompoundSet() {
   testExpression(
diff --git a/pkg/front_end/test/text_representation/text_representation_test.dart b/pkg/front_end/test/text_representation/text_representation_test.dart
index 8d57260..d9019d0 100644
--- a/pkg/front_end/test/text_representation/text_representation_test.dart
+++ b/pkg/front_end/test/text_representation/text_representation_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.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, Platform;
 import 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
@@ -154,14 +156,16 @@
 
   @override
   String computeMemberValue(Id id, Member node) {
-    if (node.name.text == 'stmtVariableDeclarationMulti') {
-      print(node);
-    }
     if (node.name.text.startsWith(expressionMarker)) {
       if (node is Procedure) {
         Statement body = node.function.body;
         if (body is ReturnStatement) {
           return body.expression.toText(strategy);
+        } else if (body is Block &&
+            body.statements.isNotEmpty &&
+            body.statements.first is ExpressionStatement) {
+          ExpressionStatement statement = body.statements.first;
+          return statement.expression.toText(strategy);
         }
       } else if (node is Field && node.initializer != null) {
         return node.initializer.toText(strategy);
diff --git a/pkg/front_end/test/textual_outline_test.dart b/pkg/front_end/test/textual_outline_test.dart
index 4a059e8..b6ea904 100644
--- a/pkg/front_end/test/textual_outline_test.dart
+++ b/pkg/front_end/test/textual_outline_test.dart
@@ -1,3 +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.md file.
+
+// @dart = 2.9
+
 import "dart:convert";
 import "package:front_end/src/fasta/util/textual_outline.dart";
 
diff --git a/pkg/front_end/test/token_test.dart b/pkg/front_end/test/token_test.dart
index d1d2a03..4a1249c 100644
--- a/pkg/front_end/test/token_test.dart
+++ b/pkg/front_end/test/token_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.
 
+// @dart = 2.9
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ScannerConfiguration, scanString;
 import 'package:_fe_analyzer_shared/src/scanner/token.dart';
diff --git a/pkg/front_end/test/tool/reload.dart b/pkg/front_end/test/tool/reload.dart
index 78d669e..6d86a82 100644
--- a/pkg/front_end/test/tool/reload.dart
+++ b/pkg/front_end/test/tool/reload.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.9
+
 /// A helper library to connect to an existing VM and trigger a hot-reload via
 /// its service protocol.
 ///
diff --git a/pkg/front_end/test/type_labeler_test.dart b/pkg/front_end/test/type_labeler_test.dart
index 40e862f..8814e5e 100644
--- a/pkg/front_end/test/type_labeler_test.dart
+++ b/pkg/front_end/test/type_labeler_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.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart';
 
 import 'package:front_end/src/fasta/kernel/type_labeler.dart';
@@ -182,17 +184,17 @@
   check({funGenericBar: "T Function<T extends Bar<T>>(T)"}, 1);
 
   // Add some members for testing instance constants
-  Field booField = new Field(new Name("boo"), type: boolType);
+  Field booField = new Field.immutable(new Name("boo"), type: boolType);
   fooClass.fields.add(booField);
-  Field valueField = new Field(new Name("value"), type: intType);
+  Field valueField = new Field.immutable(new Name("value"), type: intType);
   foo2Class.fields.add(valueField);
-  Field nextField = new Field(new Name("next"), type: foo2);
+  Field nextField = new Field.immutable(new Name("next"), type: foo2);
   foo2Class.fields.add(nextField);
-  Field xField = new Field(new Name("x"),
+  Field xField = new Field.immutable(new Name("x"),
       type: new TypeParameterType(
           bazClass.typeParameters[0], Nullability.legacy));
   bazClass.fields.add(xField);
-  Field yField = new Field(new Name("y"),
+  Field yField = new Field.immutable(new Name("y"),
       type: new TypeParameterType(
           bazClass.typeParameters[1], Nullability.legacy));
   bazClass.fields.add(yField);
diff --git a/pkg/front_end/test/unit_test_suites.dart b/pkg/front_end/test/unit_test_suites.dart
index a0d190f..fde99ac 100644
--- a/pkg/front_end/test/unit_test_suites.dart
+++ b/pkg/front_end/test/unit_test_suites.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.md file.
 
+// @dart = 2.9
+
 import 'dart:async' show Timer;
 import 'dart:convert' show jsonEncode;
 import 'dart:io' show File, Platform, exitCode;
@@ -138,24 +140,30 @@
       "matches": matchedExpectations,
     }));
     if (!matchedExpectations) {
-      String failureLog = result.log;
+      StringBuffer sb = new StringBuffer();
+      sb.write(result.log);
       if (result.error != null) {
-        failureLog = "$failureLog\n\n${result.error}";
+        sb.write("\n\n${result.error}");
       }
       if (result.trace != null) {
-        failureLog = "$failureLog\n\n${result.trace}";
+        sb.write("\n\n${result.trace}");
       }
+      sb.write("\n\nTo re-run this test, run:");
+      sb.write("\n\n   dart pkg/front_end/test/unit_test_suites.dart -p "
+          "$testName");
       if (result.autoFixCommand != null) {
-        failureLog = "$failureLog\n\n"
-            "To re-run this test, run:\n\n"
-            "   dart pkg/front_end/test/unit_test_suites.dart -p $testName\n\n"
-            "To automatically update the test expectations, run:\n\n"
-            "   dart pkg/front_end/test/unit_test_suites.dart -p $testName "
-            "-D${result.autoFixCommand}\n";
-      } else {
-        failureLog = "$failureLog\n\nRe-run this test: dart "
-            "pkg/front_end/test/unit_test_suites.dart -p $testName";
+        sb.write("\n\nTo automatically update the test expectations, run:");
+        sb.write("\n\n   dart pkg/front_end/test/unit_test_suites.dart -p "
+            "$testName -D${result.autoFixCommand}");
+        if (result.canBeFixWithUpdateExpectations) {
+          sb.write('\n\nTo update test expectations for all tests at once, '
+              'run:');
+          sb.write('\n\n  dart pkg/front_end/tool/update_expectations.dart');
+          sb.write('\n\nNote that this takes a long time and should only be '
+              'used when many tests need updating.\n');
+        }
       }
+      String failureLog = sb.toString();
       String outcome = "${result.outcome}";
       logsPort.send(jsonEncode({
         "name": testName,
@@ -288,7 +296,7 @@
       "../../testing.json"),
 ];
 
-const Duration timeoutDuration = Duration(minutes: 25);
+const Duration timeoutDuration = Duration(minutes: 30);
 
 class SuiteConfiguration {
   final String name;
diff --git a/pkg/front_end/test/utils/io_utils.dart b/pkg/front_end/test/utils/io_utils.dart
index 7fdd197..6cd9daa 100644
--- a/pkg/front_end/test/utils/io_utils.dart
+++ b/pkg/front_end/test/utils/io_utils.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.md file.
 
+// @dart = 2.9
+
 import 'dart:io' show Directory, File, Platform, Process, ProcessResult;
 
 String computeRepoDir() {
diff --git a/pkg/front_end/test/utils/kernel_chain.dart b/pkg/front_end/test/utils/kernel_chain.dart
index f5f4ba8..5afe941 100644
--- a/pkg/front_end/test/utils/kernel_chain.dart
+++ b/pkg/front_end/test/utils/kernel_chain.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.md file.
 
+// @dart = 2.9
+
 library fasta.testing.kernel_chain;
 
 import 'dart:io' show Directory, File, IOSink, Platform;
@@ -23,8 +25,6 @@
 import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
 
 import 'package:front_end/src/fasta/fasta_codes.dart' show templateUnspecified;
-import 'package:front_end/src/fasta/kernel/constant_evaluator.dart'
-    show ConstantCoverage;
 
 import 'package:front_end/src/fasta/kernel/kernel_target.dart'
     show KernelTarget;
@@ -34,7 +34,7 @@
 import 'package:front_end/src/fasta/messages.dart'
     show DiagnosticMessageFromJson, LocatedMessage;
 
-import 'package:kernel/ast.dart' show Component, Library;
+import 'package:kernel/ast.dart' show Component, Library, Reference, Source;
 
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
@@ -68,6 +68,8 @@
 
   String get updateExpectationsOption;
 
+  bool get canBeFixWithUpdateExpectations;
+
   ExpectationSet get expectationSet;
 
   Expectation get expectationFileMismatch =>
@@ -98,7 +100,10 @@
             output, onMismatch, "$uri doesn't match ${expectedFile.uri}\n$diff",
             autoFixCommand: onMismatch == expectationFileMismatch
                 ? updateExpectationsOption
-                : null);
+                : null,
+            canBeFixWithUpdateExpectations:
+                onMismatch == expectationFileMismatch &&
+                    canBeFixWithUpdateExpectations);
       } else {
         return new Result<O>.pass(output);
       }
@@ -295,24 +300,26 @@
         buffer.writeln(extraConstantString);
       }
     }
-    // TODO(jensj): Don't comment this out. Will be done in a follow-up-CL.
-    // if (result.constantCoverage != null) {
-    //   ConstantCoverage constantCoverage = result.constantCoverage;
-    //   if (constantCoverage.constructorCoverage.isNotEmpty) {
-    //     buffer.writeln("");
-    //     buffer.writeln("");
-    //     buffer.writeln("Constructor coverage from constants:");
-    //     for (MapEntry<Uri, Set<Reference>> entry
-    //         in constantCoverage.constructorCoverage.entries) {
-    //       buffer.writeln("${entry.key}:");
-    //       for (Reference reference in entry.value) {
-    //         buffer.writeln(
-    //             "- ${reference.node} (from ${reference.node.location})");
-    //       }
-    //       buffer.writeln("");
-    //     }
-    //   }
-    // }
+    bool printedConstantCoverageHeader = false;
+    for (Source source in result.component.uriToSource.values) {
+      if (!result.isUserLibraryImportUri(source.importUri)) continue;
+
+      if (source.constantCoverageConstructors != null &&
+          source.constantCoverageConstructors.isNotEmpty) {
+        if (!printedConstantCoverageHeader) {
+          buffer.writeln("");
+          buffer.writeln("");
+          buffer.writeln("Constructor coverage from constants:");
+          printedConstantCoverageHeader = true;
+        }
+        buffer.writeln("${source.fileUri}:");
+        for (Reference reference in source.constantCoverageConstructors) {
+          buffer
+              .writeln("- ${reference.node} (from ${reference.node.location})");
+        }
+        buffer.writeln("");
+      }
+    }
 
     String actual = "$buffer";
     String binariesPath =
@@ -413,14 +420,8 @@
     Uri uri = tmp.uri.resolve("generated.dill");
     File generated = new File.fromUri(uri);
     IOSink sink = generated.openWrite();
-    result = new ComponentResult(
-        result.description,
-        result.component,
-        result.userLibraries,
-        result.options,
-        result.sourceTarget,
-        result.constantCoverage,
-        uri);
+    result = new ComponentResult(result.description, result.component,
+        result.userLibraries, result.options, result.sourceTarget, uri);
     try {
       new BinaryPrinter(sink).writeComponentFile(component);
     } catch (e, s) {
@@ -519,13 +520,16 @@
   final ProcessedOptions options;
   final KernelTarget sourceTarget;
   final List<String> extraConstantStrings = [];
-  final ConstantCoverage constantCoverage;
 
   ComponentResult(this.description, this.component, this.userLibraries,
-      this.options, this.sourceTarget, this.constantCoverage,
+      this.options, this.sourceTarget,
       [this.outputUri]);
 
   bool isUserLibrary(Library library) {
-    return userLibraries.contains(library.importUri);
+    return isUserLibraryImportUri(library.importUri);
+  }
+
+  bool isUserLibraryImportUri(Uri importUri) {
+    return userLibraries.contains(importUri);
   }
 }
diff --git a/pkg/front_end/test/utils/scanner_chain.dart b/pkg/front_end/test/utils/scanner_chain.dart
index 1bf5b45..635ef6d 100644
--- a/pkg/front_end/test/utils/scanner_chain.dart
+++ b/pkg/front_end/test/utils/scanner_chain.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.md file.
 
+// @dart = 2.9
+
 library fasta.testing.scanner_chain;
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
diff --git a/pkg/front_end/test/utils/validating_instrumentation.dart b/pkg/front_end/test/utils/validating_instrumentation.dart
index 9680b32..184e7cb 100644
--- a/pkg/front_end/test/utils/validating_instrumentation.dart
+++ b/pkg/front_end/test/utils/validating_instrumentation.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.md file.
 
+// @dart = 2.9
+
 import 'dart:convert' show utf8;
 
 import 'dart:io' show File;
diff --git a/pkg/front_end/test/vm_service_coverage.dart b/pkg/front_end/test/vm_service_coverage.dart
index 7c69754..f5fd805 100644
--- a/pkg/front_end/test/vm_service_coverage.dart
+++ b/pkg/front_end/test/vm_service_coverage.dart
@@ -1,3 +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.md file.
+
+// @dart = 2.9
+
 import 'dart:async';
 
 import 'vm_service_helper.dart' as vmService;
diff --git a/pkg/front_end/test/vm_service_coverage_constant_evaluator.dart b/pkg/front_end/test/vm_service_coverage_constant_evaluator.dart
index d042077..5ea2bd0 100644
--- a/pkg/front_end/test/vm_service_coverage_constant_evaluator.dart
+++ b/pkg/front_end/test/vm_service_coverage_constant_evaluator.dart
@@ -1,3 +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.md file.
+
+// @dart = 2.9
+
 import 'vm_service_coverage.dart' as helper;
 
 main(List<String> args) async {
diff --git a/pkg/front_end/test/vm_service_for_leak_detection.dart b/pkg/front_end/test/vm_service_for_leak_detection.dart
index 748756e..6df63cc 100644
--- a/pkg/front_end/test/vm_service_for_leak_detection.dart
+++ b/pkg/front_end/test/vm_service_for_leak_detection.dart
@@ -1,3 +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
+
 import 'dart:io';
 
 import "vm_service_heap_helper.dart" as helper;
diff --git a/pkg/front_end/test/vm_service_heap_finder.dart b/pkg/front_end/test/vm_service_heap_finder.dart
index 2e85184..6fb49d91 100644
--- a/pkg/front_end/test/vm_service_heap_finder.dart
+++ b/pkg/front_end/test/vm_service_heap_finder.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.9
+
 import "dart:io";
 
 import "vm_service_helper.dart" as vmService;
diff --git a/pkg/front_end/test/vm_service_heap_helper.dart b/pkg/front_end/test/vm_service_heap_helper.dart
index f4841d0..c011aea 100644
--- a/pkg/front_end/test/vm_service_heap_helper.dart
+++ b/pkg/front_end/test/vm_service_heap_helper.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.9
+
 import "dijkstras_sssp_algorithm.dart";
 import "vm_service_helper.dart" as vmService;
 
diff --git a/pkg/front_end/test/vm_service_helper.dart b/pkg/front_end/test/vm_service_helper.dart
index a80eb5a..8906a43 100644
--- a/pkg/front_end/test/vm_service_helper.dart
+++ b/pkg/front_end/test/vm_service_helper.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.9
+
 import "dart:convert";
 import "dart:io";
 
diff --git a/pkg/front_end/testcases/agnostic/as.dart.weak.expect b/pkg/front_end/testcases/agnostic/as.dart.weak.expect
index f28c31a..40e7073 100644
--- a/pkg/front_end/testcases/agnostic/as.dart.weak.expect
+++ b/pkg/front_end/testcases/agnostic/as.dart.weak.expect
@@ -8,5 +8,5 @@
 
 constants  {
   #C1 = <Null>[]
-  #C2 = <core::int*>[]
+  #C2 = <core::int?>[]
 }
diff --git a/pkg/front_end/testcases/agnostic/as.dart.weak.transformed.expect b/pkg/front_end/testcases/agnostic/as.dart.weak.transformed.expect
index f28c31a..40e7073 100644
--- a/pkg/front_end/testcases/agnostic/as.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/as.dart.weak.transformed.expect
@@ -8,5 +8,5 @@
 
 constants  {
   #C1 = <Null>[]
-  #C2 = <core::int*>[]
+  #C2 = <core::int?>[]
 }
diff --git a/pkg/front_end/testcases/agnostic/identical.dart.outline.expect b/pkg/front_end/testcases/agnostic/identical.dart.outline.expect
index a3ec3dc..6f87884 100644
--- a/pkg/front_end/testcases/agnostic/identical.dart.outline.expect
+++ b/pkg/front_end/testcases/agnostic/identical.dart.outline.expect
@@ -12,6 +12,5 @@
 Extra constant evaluation status:
 Evaluated: ListLiteral @ org-dartlang-testcase:///identical.dart:5:16 -> ListConstant(const <int>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///identical.dart:6:17 -> ListConstant(const <int?>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///identical.dart:7:21 -> ListConstant(const <int>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///identical.dart:7:24 -> ListConstant(const <int?>[])
-Extra constant evaluation: evaluated: 5, effectively constant: 4
+Evaluated: StaticInvocation @ org-dartlang-testcase:///identical.dart:7:11 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 3, effectively constant: 3
diff --git a/pkg/front_end/testcases/agnostic/identical.dart.strong.expect b/pkg/front_end/testcases/agnostic/identical.dart.strong.expect
index fd8a51e..0e4519e 100644
--- a/pkg/front_end/testcases/agnostic/identical.dart.strong.expect
+++ b/pkg/front_end/testcases/agnostic/identical.dart.strong.expect
@@ -1,26 +1,14 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/identical.dart:7:11: Error: Constant evaluation error:
-// const c = identical(a, b);
-//           ^
-// pkg/front_end/testcases/agnostic/identical.dart:7:11: Context: Constant value is not strong/weak mode agnostic.
-// const c = identical(a, b);
-//           ^
-// pkg/front_end/testcases/agnostic/identical.dart:7:7: Context: While analyzing:
-// const c = identical(a, b);
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
 static const field core::List<core::int?> b = #C2;
-static const field core::bool c = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field core::bool c = #C3;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int>[]
   #C2 = <core::int?>[]
+  #C3 = false
 }
diff --git a/pkg/front_end/testcases/agnostic/identical.dart.strong.transformed.expect b/pkg/front_end/testcases/agnostic/identical.dart.strong.transformed.expect
index fd8a51e..0e4519e 100644
--- a/pkg/front_end/testcases/agnostic/identical.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/identical.dart.strong.transformed.expect
@@ -1,26 +1,14 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/identical.dart:7:11: Error: Constant evaluation error:
-// const c = identical(a, b);
-//           ^
-// pkg/front_end/testcases/agnostic/identical.dart:7:11: Context: Constant value is not strong/weak mode agnostic.
-// const c = identical(a, b);
-//           ^
-// pkg/front_end/testcases/agnostic/identical.dart:7:7: Context: While analyzing:
-// const c = identical(a, b);
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
 static const field core::List<core::int?> b = #C2;
-static const field core::bool c = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field core::bool c = #C3;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int>[]
   #C2 = <core::int?>[]
+  #C3 = false
 }
diff --git a/pkg/front_end/testcases/agnostic/identical.dart.weak.expect b/pkg/front_end/testcases/agnostic/identical.dart.weak.expect
index 4a31c8f..f5a7aaa 100644
--- a/pkg/front_end/testcases/agnostic/identical.dart.weak.expect
+++ b/pkg/front_end/testcases/agnostic/identical.dart.weak.expect
@@ -3,11 +3,12 @@
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
-static const field core::List<core::int?> b = #C1;
-static const field core::bool c = #C2;
+static const field core::List<core::int?> b = #C2;
+static const field core::bool c = #C3;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int*>[]
-  #C2 = true
+  #C2 = <core::int?>[]
+  #C3 = false
 }
diff --git a/pkg/front_end/testcases/agnostic/identical.dart.weak.transformed.expect b/pkg/front_end/testcases/agnostic/identical.dart.weak.transformed.expect
index 4a31c8f..f5a7aaa 100644
--- a/pkg/front_end/testcases/agnostic/identical.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/identical.dart.weak.transformed.expect
@@ -3,11 +3,12 @@
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
-static const field core::List<core::int?> b = #C1;
-static const field core::bool c = #C2;
+static const field core::List<core::int?> b = #C2;
+static const field core::bool c = #C3;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int*>[]
-  #C2 = true
+  #C2 = <core::int?>[]
+  #C3 = false
 }
diff --git a/pkg/front_end/testcases/agnostic/map.dart.outline.expect b/pkg/front_end/testcases/agnostic/map.dart.outline.expect
index e1ceefa..5661432 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.outline.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.outline.expect
@@ -12,6 +12,5 @@
 Extra constant evaluation status:
 Evaluated: ListLiteral @ org-dartlang-testcase:///map.dart:5:16 -> ListConstant(const <int>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///map.dart:6:17 -> ListConstant(const <int?>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///map.dart:7:12 -> ListConstant(const <int>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///map.dart:7:18 -> ListConstant(const <int?>[])
-Extra constant evaluation: evaluated: 5, effectively constant: 4
+Evaluated: MapLiteral @ org-dartlang-testcase:///map.dart:7:11 -> InstanceConstant(const _ImmutableMap<List<int?>, int>{_ImmutableMap._kvPairs: const <dynamic>[const <int>[], 0, const <int?>[], 1]})
+Extra constant evaluation: evaluated: 3, effectively constant: 3
diff --git a/pkg/front_end/testcases/agnostic/map.dart.strong.expect b/pkg/front_end/testcases/agnostic/map.dart.strong.expect
index 021aca0..4802fa3 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.strong.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.strong.expect
@@ -1,26 +1,17 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/map.dart:7:11: Error: Constant evaluation error:
-// const c = {a: 0, b: 1};
-//           ^
-// pkg/front_end/testcases/agnostic/map.dart:7:18: Context: Constant value is not strong/weak mode agnostic.
-// const c = {a: 0, b: 1};
-//                  ^
-// pkg/front_end/testcases/agnostic/map.dart:7:7: Context: While analyzing:
-// const c = {a: 0, b: 1};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
 static const field core::List<core::int?> b = #C2;
-static const field core::Map<core::List<core::int?>, core::int> c = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field core::Map<core::List<core::int?>, core::int> c = #C6;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int>[]
   #C2 = <core::int?>[]
+  #C3 = 0
+  #C4 = 1
+  #C5 = <dynamic>[#C1, #C3, #C2, #C4]
+  #C6 = core::_ImmutableMap<core::List<core::int?>, core::int> {_kvPairs:#C5}
 }
diff --git a/pkg/front_end/testcases/agnostic/map.dart.strong.transformed.expect b/pkg/front_end/testcases/agnostic/map.dart.strong.transformed.expect
index 021aca0..4802fa3 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.strong.transformed.expect
@@ -1,26 +1,17 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/map.dart:7:11: Error: Constant evaluation error:
-// const c = {a: 0, b: 1};
-//           ^
-// pkg/front_end/testcases/agnostic/map.dart:7:18: Context: Constant value is not strong/weak mode agnostic.
-// const c = {a: 0, b: 1};
-//                  ^
-// pkg/front_end/testcases/agnostic/map.dart:7:7: Context: While analyzing:
-// const c = {a: 0, b: 1};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
 static const field core::List<core::int?> b = #C2;
-static const field core::Map<core::List<core::int?>, core::int> c = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field core::Map<core::List<core::int?>, core::int> c = #C6;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int>[]
   #C2 = <core::int?>[]
+  #C3 = 0
+  #C4 = 1
+  #C5 = <dynamic>[#C1, #C3, #C2, #C4]
+  #C6 = core::_ImmutableMap<core::List<core::int?>, core::int> {_kvPairs:#C5}
 }
diff --git a/pkg/front_end/testcases/agnostic/map.dart.weak.expect b/pkg/front_end/testcases/agnostic/map.dart.weak.expect
index 1d3e649..2104776 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.weak.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.weak.expect
@@ -1,25 +1,17 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/map.dart:7:11: Error: Constant evaluation error:
-// const c = {a: 0, b: 1};
-//           ^
-// pkg/front_end/testcases/agnostic/map.dart:7:18: Context: The key '<int>[]' conflicts with another existing key in the map.
-// const c = {a: 0, b: 1};
-//                  ^
-// pkg/front_end/testcases/agnostic/map.dart:7:7: Context: While analyzing:
-// const c = {a: 0, b: 1};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
-static const field core::List<core::int?> b = #C1;
-static const field core::Map<core::List<core::int?>, core::int> c = invalid-expression "The key '<int>[]' conflicts with another existing key in the map.";
+static const field core::List<core::int?> b = #C2;
+static const field core::Map<core::List<core::int?>, core::int> c = #C6;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int*>[]
+  #C2 = <core::int?>[]
+  #C3 = 0
+  #C4 = 1
+  #C5 = <dynamic>[#C1, #C3, #C2, #C4]
+  #C6 = core::_ImmutableMap<core::List<core::int?>*, core::int*> {_kvPairs:#C5}
 }
diff --git a/pkg/front_end/testcases/agnostic/map.dart.weak.transformed.expect b/pkg/front_end/testcases/agnostic/map.dart.weak.transformed.expect
index 1d3e649..2104776 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.weak.transformed.expect
@@ -1,25 +1,17 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/map.dart:7:11: Error: Constant evaluation error:
-// const c = {a: 0, b: 1};
-//           ^
-// pkg/front_end/testcases/agnostic/map.dart:7:18: Context: The key '<int>[]' conflicts with another existing key in the map.
-// const c = {a: 0, b: 1};
-//                  ^
-// pkg/front_end/testcases/agnostic/map.dart:7:7: Context: While analyzing:
-// const c = {a: 0, b: 1};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
-static const field core::List<core::int?> b = #C1;
-static const field core::Map<core::List<core::int?>, core::int> c = invalid-expression "The key '<int>[]' conflicts with another existing key in the map.";
+static const field core::List<core::int?> b = #C2;
+static const field core::Map<core::List<core::int?>, core::int> c = #C6;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int*>[]
+  #C2 = <core::int?>[]
+  #C3 = 0
+  #C4 = 1
+  #C5 = <dynamic>[#C1, #C3, #C2, #C4]
+  #C6 = core::_ImmutableMap<core::List<core::int?>*, core::int*> {_kvPairs:#C5}
 }
diff --git a/pkg/front_end/testcases/agnostic/set.dart.outline.expect b/pkg/front_end/testcases/agnostic/set.dart.outline.expect
index 53dca31..a0da86e 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.outline.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.outline.expect
@@ -12,6 +12,5 @@
 Extra constant evaluation status:
 Evaluated: ListLiteral @ org-dartlang-testcase:///set.dart:5:16 -> ListConstant(const <int>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///set.dart:6:17 -> ListConstant(const <int?>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///set.dart:7:12 -> ListConstant(const <int>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///set.dart:7:15 -> ListConstant(const <int?>[])
-Extra constant evaluation: evaluated: 5, effectively constant: 4
+Evaluated: SetLiteral @ org-dartlang-testcase:///set.dart:7:11 -> InstanceConstant(const _UnmodifiableSet<List<int?>>{_UnmodifiableSet._map: const _ImmutableMap<List<int?>, Null>{_ImmutableMap._kvPairs: const <dynamic>[const <int>[], null, const <int?>[], null]}})
+Extra constant evaluation: evaluated: 3, effectively constant: 3
diff --git a/pkg/front_end/testcases/agnostic/set.dart.strong.expect b/pkg/front_end/testcases/agnostic/set.dart.strong.expect
index ad0fc3d..9da7c28 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.strong.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.strong.expect
@@ -1,26 +1,17 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/set.dart:7:11: Error: Constant evaluation error:
-// const c = {a, b};
-//           ^
-// pkg/front_end/testcases/agnostic/set.dart:7:15: Context: Constant value is not strong/weak mode agnostic.
-// const c = {a, b};
-//               ^
-// pkg/front_end/testcases/agnostic/set.dart:7:7: Context: While analyzing:
-// const c = {a, b};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
 static const field core::List<core::int?> b = #C2;
-static const field core::Set<core::List<core::int?>> c = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field core::Set<core::List<core::int?>> c = #C6;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int>[]
   #C2 = <core::int?>[]
+  #C3 = null
+  #C4 = <dynamic>[#C1, #C3, #C2, #C3]
+  #C5 = core::_ImmutableMap<core::List<core::int?>, Null> {_kvPairs:#C4}
+  #C6 = col::_UnmodifiableSet<core::List<core::int?>> {_map:#C5}
 }
diff --git a/pkg/front_end/testcases/agnostic/set.dart.strong.transformed.expect b/pkg/front_end/testcases/agnostic/set.dart.strong.transformed.expect
index ad0fc3d..9da7c28 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.strong.transformed.expect
@@ -1,26 +1,17 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/set.dart:7:11: Error: Constant evaluation error:
-// const c = {a, b};
-//           ^
-// pkg/front_end/testcases/agnostic/set.dart:7:15: Context: Constant value is not strong/weak mode agnostic.
-// const c = {a, b};
-//               ^
-// pkg/front_end/testcases/agnostic/set.dart:7:7: Context: While analyzing:
-// const c = {a, b};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
 static const field core::List<core::int?> b = #C2;
-static const field core::Set<core::List<core::int?>> c = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field core::Set<core::List<core::int?>> c = #C6;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int>[]
   #C2 = <core::int?>[]
+  #C3 = null
+  #C4 = <dynamic>[#C1, #C3, #C2, #C3]
+  #C5 = core::_ImmutableMap<core::List<core::int?>, Null> {_kvPairs:#C4}
+  #C6 = col::_UnmodifiableSet<core::List<core::int?>> {_map:#C5}
 }
diff --git a/pkg/front_end/testcases/agnostic/set.dart.weak.expect b/pkg/front_end/testcases/agnostic/set.dart.weak.expect
index f33d0a9..8c54370 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.weak.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.weak.expect
@@ -1,25 +1,17 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/set.dart:7:11: Error: Constant evaluation error:
-// const c = {a, b};
-//           ^
-// pkg/front_end/testcases/agnostic/set.dart:7:15: Context: The element '<int>[]' conflicts with another existing element in the set.
-// const c = {a, b};
-//               ^
-// pkg/front_end/testcases/agnostic/set.dart:7:7: Context: While analyzing:
-// const c = {a, b};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
-static const field core::List<core::int?> b = #C1;
-static const field core::Set<core::List<core::int?>> c = invalid-expression "The element '<int>[]' conflicts with another existing element in the set.";
+static const field core::List<core::int?> b = #C2;
+static const field core::Set<core::List<core::int?>> c = #C6;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int*>[]
+  #C2 = <core::int?>[]
+  #C3 = null
+  #C4 = <dynamic>[#C1, #C3, #C2, #C3]
+  #C5 = core::_ImmutableMap<core::List<core::int?>*, Null> {_kvPairs:#C4}
+  #C6 = col::_UnmodifiableSet<core::List<core::int?>*> {_map:#C5}
 }
diff --git a/pkg/front_end/testcases/agnostic/set.dart.weak.transformed.expect b/pkg/front_end/testcases/agnostic/set.dart.weak.transformed.expect
index f33d0a9..8c54370 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.weak.transformed.expect
@@ -1,25 +1,17 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/agnostic/set.dart:7:11: Error: Constant evaluation error:
-// const c = {a, b};
-//           ^
-// pkg/front_end/testcases/agnostic/set.dart:7:15: Context: The element '<int>[]' conflicts with another existing element in the set.
-// const c = {a, b};
-//               ^
-// pkg/front_end/testcases/agnostic/set.dart:7:7: Context: While analyzing:
-// const c = {a, b};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 static const field core::List<core::int> a = #C1;
-static const field core::List<core::int?> b = #C1;
-static const field core::Set<core::List<core::int?>> c = invalid-expression "The element '<int>[]' conflicts with another existing element in the set.";
+static const field core::List<core::int?> b = #C2;
+static const field core::Set<core::List<core::int?>> c = #C6;
 static method main() → dynamic {}
 
 constants  {
   #C1 = <core::int*>[]
+  #C2 = <core::int?>[]
+  #C3 = null
+  #C4 = <dynamic>[#C1, #C3, #C2, #C3]
+  #C5 = core::_ImmutableMap<core::List<core::int?>*, Null> {_kvPairs:#C4}
+  #C6 = col::_UnmodifiableSet<core::List<core::int?>*> {_map:#C5}
 }
diff --git a/pkg/front_end/testcases/expression/class_static3.expression.yaml.expect b/pkg/front_end/testcases/expression/class_static3.expression.yaml.expect
index 54da0ac..9fcf6bc 100644
--- a/pkg/front_end/testcases/expression/class_static3.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/class_static3.expression.yaml.expect
@@ -4,7 +4,7 @@
               ^^^^^^^^^
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
-  return #lib1::globalVar.{dart.core::num::+}(invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:13: Error: Getter not found: 'staticVar'.\nglobalVar + staticVar + 5\n            ^^^^^^^^^" as{TypeError,ForDynamic} dart.core::num).{dart.core::num::+}(5);
+  return #lib1::globalVar.{dart.core::num::+}(invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:13: Error: Getter not found: 'staticVar'.\nglobalVar + staticVar + 5\n            ^^^^^^^^^").{dart.core::num::+}(5);
 Errors: {
 }
 static method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
diff --git a/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml.expect b/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml.expect
index 15bc127..6ca1293 100644
--- a/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/from_vm_cc_linked_hash_map.expression.yaml.expect
@@ -5,12 +5,12 @@
     if(!a._usedData.{dart.core::Object::==}(b._usedData) || !a._deletedKeys.{dart.core::Object::==}(b._deletedKeys) || !a._hashMask.{dart.core::Object::==}(b._hashMask) || !a._index.length.{dart.core::Object::==}(b._index.length) || !a._data.length.{dart.core::Object::==}(b._data.length)) {
       return false;
     }
-    for (dart.core::int* i = 0; i.{dart.core::num::<}(a._index.length as{TypeError,ForDynamic} dart.core::num); i = i.{dart.core::num::+}(1)) {
+    for (dart.core::int* i = 0; i.{dart.core::num::<}(a._index.length as{TypeError,ForDynamic} dart.core::num*); i = i.{dart.core::num::+}(1)) {
       if(!a._index.[](i).{dart.core::Object::==}(b._index.[](i))) {
         return false;
       }
     }
-    for (dart.core::int* i = 0; i.{dart.core::num::<}(a._data.length as{TypeError,ForDynamic} dart.core::num); i = i.{dart.core::num::+}(1)) {
+    for (dart.core::int* i = 0; i.{dart.core::num::<}(a._data.length as{TypeError,ForDynamic} dart.core::num*); i = i.{dart.core::num::+}(1)) {
       dynamic ad = a._data.[](i);
       dynamic bd = b._data.[](i);
       if(!dart.core::identical(ad, bd) && !(ad.{dart.core::Object::==}(a) && bd.{dart.core::Object::==}(b))) {
diff --git a/pkg/front_end/testcases/expression/missing_variable_types.expression.yaml.expect b/pkg/front_end/testcases/expression/missing_variable_types.expression.yaml.expect
index 3fed1d3..cbffcf7 100644
--- a/pkg/front_end/testcases/expression/missing_variable_types.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/missing_variable_types.expression.yaml.expect
@@ -1,4 +1,4 @@
 Errors: {
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr(dynamic s) → dynamic
-  return this.{main::D::m}(this.{main::D::id}<dart.core::List<main::D::T*>*>((s = <dynamic>[]) as{TypeError} dart.core::List<main::D::T*>*));
+  return this.{main::D::m}(this.{main::D::id}<dart.core::List<main::D::T*>*>((s = dart.core::_GrowableList::•<dynamic>(0)) as{TypeError} dart.core::List<main::D::T*>*));
diff --git a/pkg/front_end/testcases/expression/set_literal.expression.yaml.expect b/pkg/front_end/testcases/expression/set_literal.expression.yaml.expect
index e622baa..88031b2 100644
--- a/pkg/front_end/testcases/expression/set_literal.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/set_literal.expression.yaml.expect
@@ -2,6 +2,6 @@
 }
 method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
   return block {
-    final dart.core::Set<dart.core::String*>* #t1 = dart.collection::LinkedHashSet::•<dart.core::String*>();
+    final dart.core::Set<dart.core::String*>* #t1 = new dart.collection::_CompactLinkedHashSet::•<dart.core::String*>();
     #t1.{dart.core::Set::add}{Invariant}("a");
   } =>#t1;
diff --git a/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline.expect
index 94df769..cdead34 100644
--- a/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline.expect
@@ -1,7 +1,24 @@
-extension A ;
-on C (){}
-extension B ;
-on C (){}
+extension A on C {
+  void method() {}
+  int get getter => 42;
+  void set setter(int value) {}
+  int get property => 42;
+  int operator +(int i) => i;
+  int operator -() => 0;
+  int operator [](int i) => i;
+}
+
+extension B on C {
+  void method() {}
+  int get getter => 42;
+  void set setter(int value) {}
+  void set property(int value) {}
+  int operator +(int i) => i;
+  int operator -() => 0;
+  void operator []=(int i, int j) {}
+}
+
 class C {}
+
 errors(C c) {}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..181cba7e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+class C {}
+
+errors(C c) {}
+
+extension A on C {
+  int get getter => 42;
+  int get property => 42;
+  int operator +(int i) => i;
+  int operator -() => 0;
+  int operator [](int i) => i;
+  void method() {}
+  void set setter(int value) {}
+}
+
+extension B on C {
+  int get getter => 42;
+  int operator +(int i) => i;
+  int operator -() => 0;
+  void method() {}
+  void operator []=(int i, int j) {}
+  void set property(int value) {}
+  void set setter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.strong.expect b/pkg/front_end/testcases/extensions/annotations.dart.strong.expect
index 441d5bd..ac0bdc2 100644
--- a/pkg/front_end/testcases/extensions/annotations.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/annotations.dart.strong.expect
@@ -41,3 +41,8 @@
   #C2 = null
   #C3 = core::pragma {name:#C1, options:#C2}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotations.dart:
+- pragma._ (from org-dartlang-sdk:///sdk/lib/core/annotations.dart:188:9)
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/annotations.dart.strong.transformed.expect
index 441d5bd..ac0bdc2 100644
--- a/pkg/front_end/testcases/extensions/annotations.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/annotations.dart.strong.transformed.expect
@@ -41,3 +41,8 @@
   #C2 = null
   #C3 = core::pragma {name:#C1, options:#C2}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotations.dart:
+- pragma._ (from org-dartlang-sdk:///sdk/lib/core/annotations.dart:188:9)
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/annotations.dart.textual_outline.expect
index dc4aa33..29e0b7f 100644
--- a/pkg/front_end/testcases/extensions/annotations.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/annotations.dart.textual_outline.expect
@@ -4,8 +4,14 @@
   @pragma('dart2js:noInline')
   static staticMethod() {}
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  @pragma('dart2js:noInline')
+  extensionInstanceMethod() {}
+  @pragma('dart2js:noInline')
+  static extensionStaticMethod() {}
+}
+
 @pragma('dart2js:noInline')
 topLevelMethod() {}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/annotations.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ad11530
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/annotations.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class Class {
+  @pragma('dart2js:noInline')
+  instanceMethod() {}
+  @pragma('dart2js:noInline')
+  static staticMethod() {}
+}
+
+extension Extension on Class {
+  @pragma('dart2js:noInline')
+  extensionInstanceMethod() {}
+  @pragma('dart2js:noInline')
+  static extensionStaticMethod() {}
+}
+
+main() {}
+@pragma('dart2js:noInline')
+topLevelMethod() {}
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect
index 49c2279..101e634 100644
--- a/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect
@@ -1,3 +1,7 @@
-extension Extension ;
-on int (){}
+extension Extension on int {
+  syncStarMethod() sync* {}
+  asyncMethod() async {}
+  asyncStarMethod() async* {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..52c36dd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+extension Extension on int {
+  asyncMethod() async {}
+  asyncStarMethod() async* {}
+  syncStarMethod() sync* {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect
index fe2d23d..fe4b2b0 100644
--- a/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect
@@ -1,9 +1,29 @@
-extension Extension1<T extends Object> (){}
-on T (){}
-extension Extension2<T extends String> (){}
-on T (){}
-extension Extension3<T extends dynamic> (){}
-on T (){}
-extension Extension4<T> (){}
-on T (){}
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fe4b2b0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,29 @@
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline.expect
index fe33481..3fef925 100644
--- a/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline.expect
@@ -1,7 +1,7 @@
-extension ;
-mixin on int {}
-extension extension ;
-on int (){}
-extension as ;
-on int (){}
+extension mixin on int {}
+
+extension extension on int {}
+
+extension as on int {}
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..94a2d44
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+extension as on int {}
+
+extension extension on int {}
+
+extension mixin on int {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline.expect
index b4fd451..cb13225 100644
--- a/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline.expect
@@ -1,15 +1,23 @@
 class A {
   String get call => "My name is A";
 }
+
 class B {
   String Function() get call => () => "My name is B";
 }
-extension on ;
-int (){}
-extension on ;
-num (){}
-extension on ;
-String (){}
+
+extension on int {
+  String get call => "My name is int";
+}
+
+extension on num {
+  String get call => "My name is num";
+}
+
+extension on String {
+  String Function() get call => () => "My name is String";
+}
+
 main() {}
 var topLevel1 = 1(10);
 var topLevel2 = 1("10");
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..30be637
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline_modelled.expect
@@ -0,0 +1,32 @@
+A a = new A();
+B b = new B();
+
+class A {
+  String get call => "My name is A";
+}
+
+class B {
+  String Function() get call => () => "My name is B";
+}
+
+errors() {}
+
+extension on String {
+  String Function() get call => () => "My name is String";
+}
+
+extension on int {
+  String get call => "My name is int";
+}
+
+extension on num {
+  String get call => "My name is num";
+}
+
+main() {}
+var topLevel1 = 1(10);
+var topLevel2 = 1("10");
+var topLevel3 = 1.0(10);
+var topLevel4 = 1.0("10");
+var topLevel5 = a(2);
+var topLevel6 = a(2, "3");
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline.expect
index 57b1a20..ee9c440 100644
--- a/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline.expect
@@ -1,9 +1,16 @@
 part 'check_bounds_lib.dart';
+
 class A {}
+
 class B extends A {}
+
 class Class<T extends A> {}
-extension Extension<T extends B> (){}
-on Class<T> (){}
+
+extension Extension<T extends B> on Class<T> {
+  method() {}
+  genericMethod<S extends B>(S s) {}
+}
+
 main() {}
 test() {}
 final A a = new A();
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2b09fba
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,47 @@
+part 'check_bounds_lib.dart';
+
+class A {}
+
+class B extends A {}
+
+class Class<T extends A> {}
+
+extension Extension<T extends B> on Class<T> {
+  genericMethod<S extends B>(S s) {}
+  method() {}
+}
+
+final A a = new A();
+final Class<A> classA = new Class<A>();
+final Class<B> classB = new Class<B>();
+final field1 = classA.method();
+final field10 = Extension<A>(classA).genericMethod<B>(a);
+final field11 = Extension<B>(classA).genericMethod(a);
+final field12 = Extension<B>(classA).genericMethod<A>(a);
+final field13 = Extension<B>(classA).genericMethod<B>(a);
+final field14 = classB.method();
+final field15 = Extension(classB).method();
+final field16 = Extension<A>(classB).method();
+final field17 = Extension<B>(classB).method();
+final field18 = classB.genericMethod(a);
+final field19 = classB.genericMethod<A>(a);
+final field2 = Extension(classA).method();
+final field20 = classB.genericMethod<B>(a);
+final field21 = Extension(classB).genericMethod(a);
+final field22 = Extension(classB).genericMethod<A>(a);
+final field23 = Extension(classB).genericMethod<B>(a);
+final field24 = Extension<A>(classB).genericMethod(a);
+final field25 = Extension<A>(classB).genericMethod<A>(a);
+final field26 = Extension<A>(classB).genericMethod<B>(a);
+final field27 = Extension<B>(classB).genericMethod(a);
+final field28 = Extension<B>(classB).genericMethod<A>(a);
+final field29 = Extension<B>(classB).genericMethod<B>(a);
+final field3 = Extension<A>(classA).method();
+final field4 = Extension<B>(classA).method();
+final field5 = Extension(classA).genericMethod(a);
+final field6 = Extension(classA).genericMethod<A>(a);
+final field7 = Extension(classA).genericMethod<B>(a);
+final field8 = Extension<A>(classA).genericMethod(a);
+final field9 = Extension<A>(classA).genericMethod<A>(a);
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/compounds.dart.textual_outline.expect
index 78776b5..4e5e0d2 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.textual_outline.expect
@@ -5,20 +5,34 @@
   bool operator ==(Object other) => other is Number && value == other.value;
   String toString() => 'Number($value)';
 }
-extension NumberExtension ;
-on Number (){}
+
+extension NumberExtension on Number {
+  Number operator +(Object other) {}
+  Number operator -(Object other) {}
+}
+
 class Class {
   Number field;
   Class(this.field);
 }
-extension ClassExtension ;
-on Class (){}
+
+extension ClassExtension on Class {
+  Number get property => field;
+  void set property(Number value) {}
+  testImplicitProperties() {}
+}
+
 class IntClass {
   int field;
   IntClass(this.field);
 }
-extension IntClassExtension ;
-on IntClass (){}
+
+extension IntClassExtension on IntClass {
+  int get property => field;
+  void set property(int value) {}
+  testImplicitProperties() {}
+}
+
 main() {}
 testLocals() {}
 testProperties() {}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/compounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fada7bd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/compounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,45 @@
+class Class {
+  Class(this.field);
+  Number field;
+}
+
+class IntClass {
+  IntClass(this.field);
+  int field;
+}
+
+class Number {
+  Number(this.value);
+  String toString() => 'Number($value)';
+  bool operator ==(Object other) => other is Number && value == other.value;
+  final int value;
+  int get hashCode => value.hashCode;
+}
+
+expect(expected, actual, [expectNull = false]) {}
+
+extension ClassExtension on Class {
+  Number get property => field;
+  testImplicitProperties() {}
+  void set property(Number value) {}
+}
+
+extension IntClassExtension on IntClass {
+  int get property => field;
+  testImplicitProperties() {}
+  void set property(int value) {}
+}
+
+extension NumberExtension on Number {
+  Number operator +(Object other) {}
+  Number operator -(Object other) {}
+}
+
+main() {}
+testExplicitIntProperties() {}
+testExplicitNullAwareIntProperties(IntClass v) {}
+testExplicitNullAwareProperties(Class v) {}
+testExplicitProperties() {}
+testIntProperties() {}
+testLocals() {}
+testProperties() {}
diff --git a/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline.expect
index 1550bbb..eb8b109 100644
--- a/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline.expect
@@ -1,5 +1,11 @@
-extension Extension ;
-on String (){}
+extension Extension on String {
+  int get noSuchMethod => 42;
+  void set hashCode(int value) {}
+  int runtimeType() {}
+  operator ==(other) => false;
+  static String toString() => 'Foo';
+}
+
 main() {}
 errors() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f5441b5
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+errors() {}
+expect(expected, actual) {}
+
+extension Extension on String {
+  int get noSuchMethod => 42;
+  int runtimeType() {}
+  operator ==(other) => false;
+  static String toString() => 'Foo';
+  void set hashCode(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline.expect
index 5a2e29f..0f53c9b 100644
--- a/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline.expect
@@ -1,10 +1,21 @@
 class Class1 {}
+
 class Class2 {}
-extension DuplicateExtensionName ;
-on Class1 (){}
-extension DuplicateExtensionName ;
-on Class2 (){}
-extension UniqueExtensionName ;
-on Class1 (){}
+
+extension DuplicateExtensionName on Class1 {
+  uniqueMethod1() {}
+  duplicateMethodName2() => 1;
+}
+
+extension DuplicateExtensionName on Class2 {
+  uniqueMethod2() {}
+  duplicateMethodName2() => 2;
+}
+
+extension UniqueExtensionName on Class1 {
+  duplicateMethodName1() => 1;
+  duplicateMethodName1() => 2;
+}
+
 main() {}
 errors() {}
diff --git a/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..481736e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+class Class1 {}
+
+class Class2 {}
+
+errors() {}
+
+extension DuplicateExtensionName on Class1 {
+  duplicateMethodName2() => 1;
+  uniqueMethod1() {}
+}
+
+extension DuplicateExtensionName on Class2 {
+  duplicateMethodName2() => 2;
+  uniqueMethod2() {}
+}
+
+extension UniqueExtensionName on Class1 {
+  duplicateMethodName1() => 1;
+  duplicateMethodName1() => 2;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/default_values.dart.textual_outline.expect
index aa7d513..76863ce 100644
--- a/pkg/front_end/testcases/extensions/default_values.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/default_values.dart.textual_outline.expect
@@ -1,5 +1,12 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  method0([a]) => a;
+  method1([a = 42]) => a;
+  method2({b = 87}) => b;
+  method3({c = staticMethod}) => c();
+  static staticMethod() => 123;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/default_values.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..dac2c87e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/default_values.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+class Class {}
+
+expect(expected, actual) {}
+
+extension Extension on Class {
+  method0([a]) => a;
+  method1([a = 42]) => a;
+  method2({b = 87}) => b;
+  method3({c = staticMethod}) => c();
+  static staticMethod() => 123;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline.expect
index adb6b12..dd71c14 100644
--- a/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline.expect
@@ -1,11 +1,47 @@
 class Class {
   var field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  readGetter() {}
+  writeSetterRequired(value) {}
+  writeSetterOptional([value]) {}
+  writeSetterNamed({value}) {}
+  get tearOffGetterNoArgs => readGetter;
+  get tearOffGetterRequired => writeSetterRequired;
+  get tearOffGetterOptional => writeSetterOptional;
+  get tearOffGetterNamed => writeSetterNamed;
+  get property => this.field;
+  set property(value) {}
+  invocations(value) {}
+  tearOffs(value) {}
+  getterCalls(value) {}
+}
+
 class GenericClass<T> {
   T field;
 }
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  T readGetter() {}
+  writeSetterRequired(T value) {}
+  writeSetterOptional([T value]) {}
+  writeSetterNamed({T value}) {}
+  genericWriteSetterRequired<S extends T>(S value) {}
+  genericWriteSetterOptional<S extends T>([S value]) {}
+  genericWriteSetterNamed<S extends T>({S value}) {}
+  T get property => this.field;
+  void set property(T value) {}
+  get tearOffGetterNoArgs => readGetter;
+  get tearOffGetterRequired => writeSetterRequired;
+  get tearOffGetterOptional => writeSetterOptional;
+  get tearOffGetterNamed => writeSetterNamed;
+  get tearOffGetterGenericRequired => genericWriteSetterRequired;
+  get tearOffGetterGenericOptional => genericWriteSetterOptional;
+  get tearOffGetterGenericNamed => genericWriteSetterNamed;
+  invocations<S extends T>(S value) {}
+  tearOffs<S extends T>(S value) {}
+  getterCalls<S extends T>(S value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9e4b234
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,47 @@
+class Class {
+  var field;
+}
+
+class GenericClass<T> {
+  T field;
+}
+
+extension Extension on Class {
+  get property => this.field;
+  get tearOffGetterNamed => writeSetterNamed;
+  get tearOffGetterNoArgs => readGetter;
+  get tearOffGetterOptional => writeSetterOptional;
+  get tearOffGetterRequired => writeSetterRequired;
+  getterCalls(value) {}
+  invocations(value) {}
+  readGetter() {}
+  set property(value) {}
+  tearOffs(value) {}
+  writeSetterNamed({value}) {}
+  writeSetterOptional([value]) {}
+  writeSetterRequired(value) {}
+}
+
+extension GenericExtension<T> on GenericClass<T> {
+  T get property => this.field;
+  T readGetter() {}
+  genericWriteSetterNamed<S extends T>({S value}) {}
+  genericWriteSetterOptional<S extends T>([S value]) {}
+  genericWriteSetterRequired<S extends T>(S value) {}
+  get tearOffGetterGenericNamed => genericWriteSetterNamed;
+  get tearOffGetterGenericOptional => genericWriteSetterOptional;
+  get tearOffGetterGenericRequired => genericWriteSetterRequired;
+  get tearOffGetterNamed => writeSetterNamed;
+  get tearOffGetterNoArgs => readGetter;
+  get tearOffGetterOptional => writeSetterOptional;
+  get tearOffGetterRequired => writeSetterRequired;
+  getterCalls<S extends T>(S value) {}
+  invocations<S extends T>(S value) {}
+  tearOffs<S extends T>(S value) {}
+  void set property(T value) {}
+  writeSetterNamed({T value}) {}
+  writeSetterOptional([T value]) {}
+  writeSetterRequired(T value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline.expect
index 34dd7dc..44997e9 100644
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline.expect
@@ -1,6 +1,33 @@
 class Class<T> {
   static var field;
 }
-extension Extension<T> (){}
-on Class<T> (){}
+
+extension Extension<T> on Class<T> {
+  static get property => Class.field;
+  static set property(value) {}
+  static var field;
+  static readGetter() {}
+  static writeSetterRequired(value) {}
+  static writeSetterOptional([value]) {}
+  static writeSetterNamed({value}) {}
+  static genericWriteSetterRequired<S>(S value) {}
+  static genericWriteSetterOptional<S>([S value]) {}
+  static genericWriteSetterNamed<S>({S value}) {}
+  static get tearOffGetterNoArgs => readGetter;
+  static get tearOffGetterRequired => writeSetterRequired;
+  static get tearOffGetterOptional => writeSetterOptional;
+  static get tearOffGetterNamed => writeSetterNamed;
+  static get tearOffGetterGenericRequired => genericWriteSetterRequired;
+  static get tearOffGetterGenericOptional => genericWriteSetterOptional;
+  static get tearOffGetterGenericNamed => genericWriteSetterNamed;
+  static invocationsFromStaticContext(int value) {}
+  static tearOffsFromStaticContext(int value) {}
+  static fieldAccessFromStaticContext() {}
+  static getterCallsFromStaticContext(int value) {}
+  invocationsFromInstanceContext(T value) {}
+  tearOffsFromInstanceContext(T value) {}
+  fieldAccessFromInstanceContext() {}
+  getterCallsFromInstanceContext(T value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cbd1559
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,33 @@
+class Class<T> {
+  static var field;
+}
+
+extension Extension<T> on Class<T> {
+  fieldAccessFromInstanceContext() {}
+  getterCallsFromInstanceContext(T value) {}
+  invocationsFromInstanceContext(T value) {}
+  static fieldAccessFromStaticContext() {}
+  static genericWriteSetterNamed<S>({S value}) {}
+  static genericWriteSetterOptional<S>([S value]) {}
+  static genericWriteSetterRequired<S>(S value) {}
+  static get property => Class.field;
+  static get tearOffGetterGenericNamed => genericWriteSetterNamed;
+  static get tearOffGetterGenericOptional => genericWriteSetterOptional;
+  static get tearOffGetterGenericRequired => genericWriteSetterRequired;
+  static get tearOffGetterNamed => writeSetterNamed;
+  static get tearOffGetterNoArgs => readGetter;
+  static get tearOffGetterOptional => writeSetterOptional;
+  static get tearOffGetterRequired => writeSetterRequired;
+  static getterCallsFromStaticContext(int value) {}
+  static invocationsFromStaticContext(int value) {}
+  static readGetter() {}
+  static set property(value) {}
+  static tearOffsFromStaticContext(int value) {}
+  static var field;
+  static writeSetterNamed({value}) {}
+  static writeSetterOptional([value]) {}
+  static writeSetterRequired(value) {}
+  tearOffsFromInstanceContext(T value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline.expect
index 2b221a1..5ee7ab2 100644
--- a/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline.expect
@@ -1,9 +1,14 @@
 class Class {
   noSuchMethod(Invocation i) => 123;
 }
-extension ClassExtension ;
-on Class (){}
-extension Extension ;
-on dynamic (){}
+
+extension ClassExtension on Class {
+  int method() => 42;
+}
+
+extension Extension on dynamic {
+  int method() => 87;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..df09e5e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class Class {
+  noSuchMethod(Invocation i) => 123;
+}
+
+expect(expected, actual) {}
+
+extension ClassExtension on Class {
+  int method() => 42;
+}
+
+extension Extension on dynamic {
+  int method() => 87;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline.expect
index e338221..0bc2528 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline.expect
@@ -2,9 +2,20 @@
   int field1 = 42;
   int field2 = 87;
 }
-extension Extension1 ;
-on Class (){}
-extension Extension2 ;
-on Class (){}
+
+extension Extension1 on Class {
+  int get field => field1;
+  void set field(int value) {}
+  int method() => field1;
+  int genericMethod<T extends num>(T t) => field1 + t;
+}
+
+extension Extension2 on Class {
+  int get field => field2;
+  void set field(int value) {}
+  int method() => field2;
+  int genericMethod<T extends num>(T t) => field2 + t;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..95799c3
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+class Class {
+  int field1 = 42;
+  int field2 = 87;
+}
+
+expect(expected, actual) {}
+
+extension Extension1 on Class {
+  int genericMethod<T extends num>(T t) => field1 + t;
+  int get field => field1;
+  int method() => field1;
+  void set field(int value) {}
+}
+
+extension Extension2 on Class {
+  int genericMethod<T extends num>(T t) => field2 + t;
+  int get field => field2;
+  int method() => field2;
+  void set field(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline.expect
index 1777e12..076a719 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline.expect
@@ -1,7 +1,15 @@
 class A {}
+
 class B extends A {}
+
 class C extends B {}
+
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  T get property => null;
+  T method(T t) => null;
+  S genericMethod1<S>(S s) => null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79d6ba0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class A {}
+
+class B extends A {}
+
+class C extends B {}
+
+class GenericClass<T> {}
+
+extension GenericExtension<T> on GenericClass<T> {
+  S genericMethod1<S>(S s) => null;
+  T get property => null;
+  T method(T t) => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline.expect
index 7319a83..b8ab337 100644
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline.expect
@@ -3,9 +3,21 @@
   T field2;
   Class(this.field1, this.field2);
 }
-extension Extension1<T extends num> (){}
-on Class<T> (){}
-extension Extension2<T extends num> (){}
-on Class<T> (){}
+
+extension Extension1<T extends num> on Class<T> {
+  static String latestType;
+  T get field {}
+  void set field(T value) {}
+  T method() {}
+  T genericMethod<S extends num>(S t) {}
+}
+
+extension Extension2<T extends num> on Class<T> {
+  T get field => field2;
+  void set field(T value) {}
+  T method() => field2;
+  T genericMethod<S extends num>(S t) => field2 + t;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f800b7a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class Class<T extends num> {
+  Class(this.field1, this.field2);
+  T field1;
+  T field2;
+}
+
+expect(expected, actual) {}
+
+extension Extension1<T extends num> on Class<T> {
+  T genericMethod<S extends num>(S t) {}
+  T get field {}
+  T method() {}
+  static String latestType;
+  void set field(T value) {}
+}
+
+extension Extension2<T extends num> on Class<T> {
+  T genericMethod<S extends num>(S t) => field2 + t;
+  T get field => field2;
+  T method() => field2;
+  void set field(T value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline.expect
index 0425549..c1b8b08 100644
--- a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline.expect
@@ -1,5 +1,6 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {}
+
 errors(Class c) {}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..43c658b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class Class {}
+
+errors(Class c) {}
+
+extension Extension on Class {}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline.expect
index 7519a03..8efd4bb 100644
--- a/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline.expect
@@ -2,6 +2,11 @@
   Object field;
   void method1() {}
 }
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  void method2() => this.method1();
+  Object method3() => this.field;
+  void method4(Object o) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ca8cb86
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class A1 {
+  Object field;
+  void method1() {}
+}
+
+extension A2 on A1 {
+  Object method3() => this.field;
+  void method2() => this.method1();
+  void method4(Object o) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline.expect
index e6e0f3d..3acad15 100644
--- a/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline.expect
@@ -1,7 +1,10 @@
 class Class<T> {
   T method(T a) => a;
 }
-extension Extension<T> (){}
-on Class<T> (){}
+
+extension Extension<T> on Class<T> {
+  T call(T a) => method(a);
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7edde0e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class Class<T> {
+  T method(T a) => a;
+}
+
+expect(expected, actual) {}
+
+extension Extension<T> on Class<T> {
+  T call(T a) => method(a);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_constructor.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_constructor.dart.textual_outline.expect
index cc9ad4c..ac6bee2 100644
--- a/pkg/front_end/testcases/extensions/extension_constructor.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_constructor.dart.textual_outline.expect
@@ -1,4 +1,9 @@
 class Class {}
-extension Extension ;
-on Class (){}
+extension Extension on Class {
+  Extension() {}
+  Extension.named() {}
+  factory Extension.fact() => null;
+  factory Extension.redirect() = Extension;
+  method() {}
+}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.textual_outline.expect
index 9179aa3..26dc2e9 100644
--- a/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.textual_outline.expect
@@ -1,3 +1,10 @@
-extension E<U> (){}
-on String (){}
+extension E<U> on String {
+  U field1 = null;
+  int field2 = () { U x = null; return null; }();
+  List<U> field3 = null;
+  U Function(U) field4 = null;
+  List<U> Function(List<U>) field5 = null;
+  int field6 = <E>() { E x = null; return null; }<String>();
+  int field7 = <E>() { E x = null; return null; }<U>();
+}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect
index 6d262f3..f9f55d9 100644
--- a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect
@@ -1,3 +1,46 @@
-extension Extension<T> (){}
-on int (){}
+extension Extension<T> on int {
+  int get duplicateInstanceGetter => 0;
+  int get duplicateInstanceGetter => 0;
+  void set duplicateInstanceSetter(int value) {}
+  void set duplicateInstanceSetter(int value) {}
+  void duplicateInstanceMethod() {}
+  void duplicateInstanceMethod() {}
+  static int duplicateStaticField = 0;
+  static int duplicateStaticField = 0;
+  static int get duplicateStaticGetter => 0;
+  static int get duplicateStaticGetter => 0;
+  static void set duplicateStaticSetter(int value) {}
+  static void set duplicateStaticSetter(int value) {}
+  static void duplicateStaticMethod() {}
+  static void duplicateStaticMethod() {}
+  int get duplicateInstanceGetterPlusSetter => 0;
+  int get duplicateInstanceGetterPlusSetter => 0;
+  void set duplicateInstanceGetterPlusSetter(int value) {}
+  int get duplicateInstanceSetterPlusGetter => 0;
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  int get duplicateInstanceGetterAndSetter => 0;
+  int get duplicateInstanceGetterAndSetter => 0;
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static void set duplicateStaticGetterPlusSetter(int value) {}
+  static int get duplicateStaticSetterPlusGetter => 0;
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static int get duplicateStaticGetterAndSetter => 0;
+  static int get duplicateStaticGetterAndSetter => 0;
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  int get instanceGetterAndStaticSetter => 0;
+  static void set instanceGetterAndStaticSetter(int value) {}
+  static int get instanceSetterAndStaticGetter => 0;
+  void set instanceSetterAndStaticGetter(int value) {}
+  int get instanceGetterAndStaticField => 0;
+  static int instanceGetterAndStaticField = 0;
+  void set instanceSetterAndStaticField(int value) {}
+  static final int instanceGetterAndStaticField = 0;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..88f38e3
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline_modelled.expect
@@ -0,0 +1,46 @@
+extension Extension<T> on int {
+  int get duplicateInstanceGetter => 0;
+  int get duplicateInstanceGetter => 0;
+  int get duplicateInstanceGetterAndSetter => 0;
+  int get duplicateInstanceGetterAndSetter => 0;
+  int get duplicateInstanceGetterPlusSetter => 0;
+  int get duplicateInstanceGetterPlusSetter => 0;
+  int get duplicateInstanceSetterPlusGetter => 0;
+  int get instanceGetterAndStaticField => 0;
+  int get instanceGetterAndStaticSetter => 0;
+  static final int instanceGetterAndStaticField = 0;
+  static int duplicateStaticField = 0;
+  static int duplicateStaticField = 0;
+  static int get duplicateStaticGetter => 0;
+  static int get duplicateStaticGetter => 0;
+  static int get duplicateStaticGetterAndSetter => 0;
+  static int get duplicateStaticGetterAndSetter => 0;
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static int get duplicateStaticSetterPlusGetter => 0;
+  static int get instanceSetterAndStaticGetter => 0;
+  static int instanceGetterAndStaticField = 0;
+  static void duplicateStaticMethod() {}
+  static void duplicateStaticMethod() {}
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  static void set duplicateStaticGetterPlusSetter(int value) {}
+  static void set duplicateStaticSetter(int value) {}
+  static void set duplicateStaticSetter(int value) {}
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static void set instanceGetterAndStaticSetter(int value) {}
+  void duplicateInstanceMethod() {}
+  void duplicateInstanceMethod() {}
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  void set duplicateInstanceGetterPlusSetter(int value) {}
+  void set duplicateInstanceSetter(int value) {}
+  void set duplicateInstanceSetter(int value) {}
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  void set instanceSetterAndStaticField(int value) {}
+  void set instanceSetterAndStaticGetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline.expect
index ee11ab1..5ed8d9d8 100644
--- a/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline.expect
@@ -1,7 +1,11 @@
 import 'package:expect/expect.dart';
+
 class C {
   int get one => 1;
 }
-extension E ;
-on C (){}
+
+extension E on C {
+  int get two => 2;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5ed8d9d8
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+import 'package:expect/expect.dart';
+
+class C {
+  int get one => 1;
+}
+
+extension E on C {
+  int get two => 2;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline.expect
index 6785be5..f06572f 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline.expect
@@ -1,10 +1,24 @@
 class Class {
   int field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  int get simpleSetter => field;
+  set simpleSetter(int value) {}
+  int get mutatingSetter => field;
+  set mutatingSetter(int value) {}
+  int get setterWithReturn => field;
+  set setterWithReturn(int value) {}
+  int get setterWithClosure => field;
+  set setterWithClosure(int value) {}
+  testInternal() {}
+}
+
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  set setter(T value) {}
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..171d483
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+class Class {
+  int field;
+}
+
+class GenericClass<T> {}
+
+expect(expected, actual) {}
+
+extension Extension on Class {
+  int get mutatingSetter => field;
+  int get setterWithClosure => field;
+  int get setterWithReturn => field;
+  int get simpleSetter => field;
+  set mutatingSetter(int value) {}
+  set setterWithClosure(int value) {}
+  set setterWithReturn(int value) {}
+  set simpleSetter(int value) {}
+  testInternal() {}
+}
+
+extension GenericExtension<T> on GenericClass<T> {
+  set setter(T value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline.expect
index ee14f80..1a91b18 100644
--- a/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline.expect
@@ -1,5 +1,8 @@
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  set setter(T value) {}
+}
+
 error() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c2d2db9
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class GenericClass<T> {}
+
+error() {}
+expect(expected, actual) {}
+
+extension GenericExtension<T> on GenericClass<T> {
+  set setter(T value) {}
+}
diff --git a/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline.expect
index 6f0f637..c0519a0 100644
--- a/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline.expect
@@ -1,4 +1,7 @@
 class Class<T> {}
-extension Extension<T> (){}
-on Class<T> (){}
+
+extension Extension<T> on Class<T> {
+  R method<R>(T t) => null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c0519a0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class Class<T> {}
+
+extension Extension<T> on Class<T> {
+  R method<R>(T t) => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline.expect
index 7cb1042..0207a05 100644
--- a/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline.expect
@@ -2,10 +2,19 @@
   int get m1 => 0;
   void set m2(int x) {}
 }
-extension Extension0 ;
-on Class (){}
-extension Extension1 ;
-on Class (){}
+
+extension Extension0 on Class {
+  void set m1(int x) {}
+  int get m2 => 0;
+  void set m3(int x) {}
+  int get m4 => 0;
+}
+
+extension Extension1 on Class {
+  int get m3 => 0;
+  void set m4(int x) {}
+}
+
 main() {}
 errors() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3da20ad
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class {
+  int get m1 => 0;
+  void set m2(int x) {}
+}
+
+errors() {}
+expect(expected, actual) {}
+
+extension Extension0 on Class {
+  int get m2 => 0;
+  int get m4 => 0;
+  void set m1(int x) {}
+  void set m3(int x) {}
+}
+
+extension Extension1 on Class {
+  int get m3 => 0;
+  void set m4(int x) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/if_null.dart.textual_outline.expect
index 3220178..473e89a 100644
--- a/pkg/front_end/testcases/extensions/if_null.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/if_null.dart.textual_outline.expect
@@ -1,6 +1,11 @@
 class Class {
   int field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  int get property => field;
+  void set property(int value) {}
+  int method() => field;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/if_null.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f29446e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/if_null.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class Class {
+  int field;
+}
+
+extension Extension on Class {
+  int get property => field;
+  int method() => field;
+  void set property(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline.expect
index 1777e12..076a719 100644
--- a/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline.expect
@@ -1,7 +1,15 @@
 class A {}
+
 class B extends A {}
+
 class C extends B {}
+
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  T get property => null;
+  T method(T t) => null;
+  S genericMethod1<S>(S s) => null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79d6ba0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class A {}
+
+class B extends A {}
+
+class C extends B {}
+
+class GenericClass<T> {}
+
+extension GenericExtension<T> on GenericClass<T> {
+  S genericMethod1<S>(S s) => null;
+  T get property => null;
+  T method(T t) => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline.expect
index 7519a03..89eff23 100644
--- a/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline.expect
@@ -2,6 +2,11 @@
   Object field;
   void method1() {}
 }
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  void method2() => method1();
+  Object method3() => field;
+  void method4(Object o) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..eb7a0dd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class A1 {
+  Object field;
+  void method1() {}
+}
+
+extension A2 on A1 {
+  Object method3() => field;
+  void method2() => method1();
+  void method4(Object o) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.expect b/pkg/front_end/testcases/extensions/index.dart.strong.expect
index f9f0d76..81557be 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.expect
@@ -70,23 +70,23 @@
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
   self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::int* #t44 = 1 in let final core::String* #t45 = "2" in let final void #t46 = self::Extension|[]=<core::int*, core::String*>(#t43, #t44, #t45) in #t45);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::String* #t44 = "2" in let final void #t45 = self::Extension|[]=<core::int*, core::String*>(#t43, 1, #t44) in #t44);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t47 = map1 in let final core::int* #t48 = 1 in self::Extension|[]<core::int*, core::String*>(#t47, #t48).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t47, #t48, "3") : null;
+  let final self::MapLike<core::int*, core::String*>* #t46 = map1 in let final core::int* #t47 = 1 in self::Extension|[]<core::int*, core::String*>(#t46, #t47).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t46, #t47, "3") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t49 = map1 in let final core::int* #t50 = 1 in let final core::String* #t51 = self::Extension|[]<core::int*, core::String*>(#t49, #t50) in #t51.{core::String::==}(null) ?{core::String*} let final core::String* #t52 = "4" in let final void #t53 = self::Extension|[]=<core::int*, core::String*>(#t49, #t50, #t52) in #t52 : #t51);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t48 = map1 in let final core::int* #t49 = 1 in let final core::String* #t50 = self::Extension|[]<core::int*, core::String*>(#t48, #t49) in #t50.{core::String::==}(null) ?{core::String*} let final core::String* #t51 = "4" in let final void #t52 = self::Extension|[]=<core::int*, core::String*>(#t48, #t49, #t51) in #t51 : #t50);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t54 = map1 in let final core::int* #t55 = 2 in self::Extension|[]<core::int*, core::String*>(#t54, #t55).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t54, #t55, "2") : null;
+  let final self::MapLike<core::int*, core::String*>* #t53 = map1 in let final core::int* #t54 = 2 in self::Extension|[]<core::int*, core::String*>(#t53, #t54).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t53, #t54, "2") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
-  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t56 = map1 in let final core::int* #t57 = 3 in let final core::String* #t58 = self::Extension|[]<core::int*, core::String*>(#t56, #t57) in #t58.{core::String::==}(null) ?{core::String*} let final core::String* #t59 = "3" in let final void #t60 = self::Extension|[]=<core::int*, core::String*>(#t56, #t57, #t59) in #t59 : #t58);
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t55 = map1 in let final core::int* #t56 = 3 in let final core::String* #t57 = self::Extension|[]<core::int*, core::String*>(#t55, #t56) in #t57.{core::String::==}(null) ?{core::String*} let final core::String* #t58 = "3" in let final void #t59 = self::Extension|[]=<core::int*, core::String*>(#t55, #t56, #t58) in #t58 : #t57);
   self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
   self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
-  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t61 = map2 in let final core::int* #t62 = 0 in let final core::int* #t63 = 1 in let final void #t64 = self::Extension|[]=<core::int*, core::int*>(#t61, #t62, #t63) in #t63);
-  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t60 = map2 in let final core::int* #t61 = 1 in let final void #t62 = self::Extension|[]=<core::int*, core::int*>(#t60, 0, #t61) in #t61);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t63 = map2 in let final core::int* #t64 = 0 in let final core::int* #t65 = self::Extension|[]<core::int*, core::int*>(#t63, #t64).{core::num::+}(2) in let final void #t66 = self::Extension|[]=<core::int*, core::int*>(#t63, #t64, #t65) in #t65);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t67 = map2 in let final core::int* #t68 = 0 in let final core::int* #t69 = self::Extension|[]<core::int*, core::int*>(#t67, #t68).{core::num::+}(2) in let final void #t70 = self::Extension|[]=<core::int*, core::int*>(#t67, #t68, #t69) in #t69);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t71 = map2 in let final core::int* #t72 = 0 in let final core::int* #t73 = self::Extension|[]<core::int*, core::int*>(#t71, #t72) in let final void #t74 = self::Extension|[]=<core::int*, core::int*>(#t71, #t72, #t73.{core::num::+}(1)) in #t73);
   self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t75 = map2 in let final core::int* #t76 = 0 in let final core::int* #t77 = self::Extension|[]<core::int*, core::int*>(#t75, #t76).{core::num::-}(1) in let final void #t78 = self::Extension|[]=<core::int*, core::int*>(#t75, #t76, #t77) in #t77);
   self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method explicitInferredTypeArguments() → dynamic {
@@ -97,23 +97,23 @@
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
   self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t81 = map1 in let final core::int* #t82 = 1 in let final core::String* #t83 = "2" in let final void #t84 = self::Extension|[]=<core::int*, core::String*>(#t81, #t82, #t83) in #t83);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t79 = map1 in let final core::String* #t80 = "2" in let final void #t81 = self::Extension|[]=<core::int*, core::String*>(#t79, 1, #t80) in #t80);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t85 = map1 in let final core::int* #t86 = 1 in self::Extension|[]<core::int*, core::String*>(#t85, #t86).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t85, #t86, "3") : null;
+  let final self::MapLike<core::int*, core::String*>* #t82 = map1 in let final core::int* #t83 = 1 in self::Extension|[]<core::int*, core::String*>(#t82, #t83).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t82, #t83, "3") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t87 = map1 in let final core::int* #t88 = 1 in let final core::String* #t89 = self::Extension|[]<core::int*, core::String*>(#t87, #t88) in #t89.{core::String::==}(null) ?{core::String*} let final core::String* #t90 = "4" in let final void #t91 = self::Extension|[]=<core::int*, core::String*>(#t87, #t88, #t90) in #t90 : #t89);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t84 = map1 in let final core::int* #t85 = 1 in let final core::String* #t86 = self::Extension|[]<core::int*, core::String*>(#t84, #t85) in #t86.{core::String::==}(null) ?{core::String*} let final core::String* #t87 = "4" in let final void #t88 = self::Extension|[]=<core::int*, core::String*>(#t84, #t85, #t87) in #t87 : #t86);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t92 = map1 in let final core::int* #t93 = 2 in self::Extension|[]<core::int*, core::String*>(#t92, #t93).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t92, #t93, "2") : null;
+  let final self::MapLike<core::int*, core::String*>* #t89 = map1 in let final core::int* #t90 = 2 in self::Extension|[]<core::int*, core::String*>(#t89, #t90).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t89, #t90, "2") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
-  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t94 = map1 in let final core::int* #t95 = 3 in let final core::String* #t96 = self::Extension|[]<core::int*, core::String*>(#t94, #t95) in #t96.{core::String::==}(null) ?{core::String*} let final core::String* #t97 = "3" in let final void #t98 = self::Extension|[]=<core::int*, core::String*>(#t94, #t95, #t97) in #t97 : #t96);
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t91 = map1 in let final core::int* #t92 = 3 in let final core::String* #t93 = self::Extension|[]<core::int*, core::String*>(#t91, #t92) in #t93.{core::String::==}(null) ?{core::String*} let final core::String* #t94 = "3" in let final void #t95 = self::Extension|[]=<core::int*, core::String*>(#t91, #t92, #t94) in #t94 : #t93);
   self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
   self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
-  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = 1 in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
-  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t96 = map2 in let final core::int* #t97 = 1 in let final void #t98 = self::Extension|[]=<core::int*, core::int*>(#t96, 0, #t97) in #t97);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = self::Extension|[]<core::int*, core::int*>(#t99, #t100).{core::num::+}(2) in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109.{core::num::+}(1)) in #t109);
   self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112).{core::num::-}(1) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113) in #t113);
   self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
index 771f107..e570b06 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
@@ -70,23 +70,23 @@
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
   self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::int* #t44 = 1 in let final core::String* #t45 = "2" in let final void #t46 = self::Extension|[]=<core::int*, core::String*>(#t43, #t44, #t45) in #t45);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::String* #t44 = "2" in let final void #t45 = self::Extension|[]=<core::int*, core::String*>(#t43, 1, #t44) in #t44);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t47 = map1 in let final core::int* #t48 = 1 in self::Extension|[]<core::int*, core::String*>(#t47, #t48).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t47, #t48, "3") : null;
+  let final self::MapLike<core::int*, core::String*>* #t46 = map1 in let final core::int* #t47 = 1 in self::Extension|[]<core::int*, core::String*>(#t46, #t47).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t46, #t47, "3") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t49 = map1 in let final core::int* #t50 = 1 in let final core::String* #t51 = self::Extension|[]<core::int*, core::String*>(#t49, #t50) in #t51.{core::String::==}(null) ?{core::String*} let final core::String* #t52 = "4" in let final void #t53 = self::Extension|[]=<core::int*, core::String*>(#t49, #t50, #t52) in #t52 : #t51);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t48 = map1 in let final core::int* #t49 = 1 in let final core::String* #t50 = self::Extension|[]<core::int*, core::String*>(#t48, #t49) in #t50.{core::String::==}(null) ?{core::String*} let final core::String* #t51 = "4" in let final void #t52 = self::Extension|[]=<core::int*, core::String*>(#t48, #t49, #t51) in #t51 : #t50);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t54 = map1 in let final core::int* #t55 = 2 in self::Extension|[]<core::int*, core::String*>(#t54, #t55).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t54, #t55, "2") : null;
+  let final self::MapLike<core::int*, core::String*>* #t53 = map1 in let final core::int* #t54 = 2 in self::Extension|[]<core::int*, core::String*>(#t53, #t54).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t53, #t54, "2") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
-  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t56 = map1 in let final core::int* #t57 = 3 in let final core::String* #t58 = self::Extension|[]<core::int*, core::String*>(#t56, #t57) in #t58.{core::String::==}(null) ?{core::String*} let final core::String* #t59 = "3" in let final void #t60 = self::Extension|[]=<core::int*, core::String*>(#t56, #t57, #t59) in #t59 : #t58);
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t55 = map1 in let final core::int* #t56 = 3 in let final core::String* #t57 = self::Extension|[]<core::int*, core::String*>(#t55, #t56) in #t57.{core::String::==}(null) ?{core::String*} let final core::String* #t58 = "3" in let final void #t59 = self::Extension|[]=<core::int*, core::String*>(#t55, #t56, #t58) in #t58 : #t57);
   self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
   self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
-  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t61 = map2 in let final core::int* #t62 = 0 in let final core::int* #t63 = 1 in let final void #t64 = self::Extension|[]=<core::int*, core::int*>(#t61, #t62, #t63) in #t63);
-  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t60 = map2 in let final core::int* #t61 = 1 in let final void #t62 = self::Extension|[]=<core::int*, core::int*>(#t60, 0, #t61) in #t61);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t63 = map2 in let final core::int* #t64 = 0 in let final core::int* #t65 = self::Extension|[]<core::int*, core::int*>(#t63, #t64).{core::num::+}(2) in let final void #t66 = self::Extension|[]=<core::int*, core::int*>(#t63, #t64, #t65) in #t65);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t67 = map2 in let final core::int* #t68 = 0 in let final core::int* #t69 = self::Extension|[]<core::int*, core::int*>(#t67, #t68).{core::num::+}(2) in let final void #t70 = self::Extension|[]=<core::int*, core::int*>(#t67, #t68, #t69) in #t69);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t71 = map2 in let final core::int* #t72 = 0 in let final core::int* #t73 = self::Extension|[]<core::int*, core::int*>(#t71, #t72) in let final void #t74 = self::Extension|[]=<core::int*, core::int*>(#t71, #t72, #t73.{core::num::+}(1)) in #t73);
   self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t75 = map2 in let final core::int* #t76 = 0 in let final core::int* #t77 = self::Extension|[]<core::int*, core::int*>(#t75, #t76).{core::num::-}(1) in let final void #t78 = self::Extension|[]=<core::int*, core::int*>(#t75, #t76, #t77) in #t77);
   self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method explicitInferredTypeArguments() → dynamic {
@@ -97,23 +97,23 @@
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
   self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t81 = map1 in let final core::int* #t82 = 1 in let final core::String* #t83 = "2" in let final void #t84 = self::Extension|[]=<core::int*, core::String*>(#t81, #t82, #t83) in #t83);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t79 = map1 in let final core::String* #t80 = "2" in let final void #t81 = self::Extension|[]=<core::int*, core::String*>(#t79, 1, #t80) in #t80);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t85 = map1 in let final core::int* #t86 = 1 in self::Extension|[]<core::int*, core::String*>(#t85, #t86).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t85, #t86, "3") : null;
+  let final self::MapLike<core::int*, core::String*>* #t82 = map1 in let final core::int* #t83 = 1 in self::Extension|[]<core::int*, core::String*>(#t82, #t83).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t82, #t83, "3") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t87 = map1 in let final core::int* #t88 = 1 in let final core::String* #t89 = self::Extension|[]<core::int*, core::String*>(#t87, #t88) in #t89.{core::String::==}(null) ?{core::String*} let final core::String* #t90 = "4" in let final void #t91 = self::Extension|[]=<core::int*, core::String*>(#t87, #t88, #t90) in #t90 : #t89);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t84 = map1 in let final core::int* #t85 = 1 in let final core::String* #t86 = self::Extension|[]<core::int*, core::String*>(#t84, #t85) in #t86.{core::String::==}(null) ?{core::String*} let final core::String* #t87 = "4" in let final void #t88 = self::Extension|[]=<core::int*, core::String*>(#t84, #t85, #t87) in #t87 : #t86);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t92 = map1 in let final core::int* #t93 = 2 in self::Extension|[]<core::int*, core::String*>(#t92, #t93).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t92, #t93, "2") : null;
+  let final self::MapLike<core::int*, core::String*>* #t89 = map1 in let final core::int* #t90 = 2 in self::Extension|[]<core::int*, core::String*>(#t89, #t90).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t89, #t90, "2") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
-  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t94 = map1 in let final core::int* #t95 = 3 in let final core::String* #t96 = self::Extension|[]<core::int*, core::String*>(#t94, #t95) in #t96.{core::String::==}(null) ?{core::String*} let final core::String* #t97 = "3" in let final void #t98 = self::Extension|[]=<core::int*, core::String*>(#t94, #t95, #t97) in #t97 : #t96);
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t91 = map1 in let final core::int* #t92 = 3 in let final core::String* #t93 = self::Extension|[]<core::int*, core::String*>(#t91, #t92) in #t93.{core::String::==}(null) ?{core::String*} let final core::String* #t94 = "3" in let final void #t95 = self::Extension|[]=<core::int*, core::String*>(#t91, #t92, #t94) in #t94 : #t93);
   self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
   self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
-  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = 1 in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
-  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t96 = map2 in let final core::int* #t97 = 1 in let final void #t98 = self::Extension|[]=<core::int*, core::int*>(#t96, 0, #t97) in #t97);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = self::Extension|[]<core::int*, core::int*>(#t99, #t100).{core::num::+}(2) in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109.{core::num::+}(1)) in #t109);
   self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112).{core::num::-}(1) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113) in #t113);
   self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -150,7 +150,6 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:46:18 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:48:20 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:48:20 -> IntConstant(0)
-Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:44 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:49 -> StringConstant("2")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:49 -> StringConstant("2")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:62:32 -> IntConstant(1)
@@ -165,7 +164,6 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:44 -> IntConstant(3)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:51 -> StringConstant("3")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:51 -> StringConstant("3")
-Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:39 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:44 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:44 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:73:39 -> IntConstant(0)
@@ -176,7 +174,6 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:75:39 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:77:41 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:77:41 -> IntConstant(0)
-Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:31 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:36 -> StringConstant("2")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:36 -> StringConstant("2")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:91:19 -> IntConstant(1)
@@ -191,7 +188,6 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:31 -> IntConstant(3)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:38 -> StringConstant("3")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:38 -> StringConstant("3")
-Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:29 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:34 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:34 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:102:29 -> IntConstant(0)
@@ -202,4 +198,4 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:104:29 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:106:31 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:106:31 -> IntConstant(0)
-Extra constant evaluation: evaluated: 579, effectively constant: 78
+Extra constant evaluation: evaluated: 571, effectively constant: 74
diff --git a/pkg/front_end/testcases/extensions/index.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/index.dart.textual_outline.expect
index ac9d9f4..78005ed 100644
--- a/pkg/front_end/testcases/extensions/index.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.textual_outline.expect
@@ -3,8 +3,12 @@
   V get(Object key) => _map[key];
   V put(K key, V value) => _map[key] = value;
 }
-extension Extension<K, V> (){}
-on MapLike<K, V> (){}
+
+extension Extension<K, V> on MapLike<K, V> {
+  V operator [](Object key) => get(key);
+  void operator []=(K key, V value) => put(key, value);
+}
+
 main() {}
 implicit() {}
 explicitWithTypeArguments() {}
diff --git a/pkg/front_end/testcases/extensions/index.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/index.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d0d5ec9
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/index.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class MapLike<K, V> {
+  V get(Object key) => _map[key];
+  V put(K key, V value) => _map[key] = value;
+  final Map<K, V> _map = {};
+}
+
+expect(expected, actual) {}
+explicitInferredTypeArguments() {}
+explicitWithTypeArguments() {}
+
+extension Extension<K, V> on MapLike<K, V> {
+  V operator [](Object key) => get(key);
+  void operator []=(K key, V value) => put(key, value);
+}
+
+implicit() {}
+main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline.expect
index 296e8e0..a9ea239 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline.expect
@@ -3,15 +3,27 @@
   Class1(this.field);
   String toString() => 'Class1($field)';
 }
+
 class Class2 {
   int field;
   Class2(this.field);
   String toString() => 'Class2($field)';
 }
-extension Extension1 ;
-on Class1 (){}
-extension Extension2 ;
-on Class2 (){}
+
+extension Extension1 on Class1 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  set property(int value) {}
+}
+
+extension Extension2 on Class2 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  set property(int value) {}
+}
+
 main() {}
 testExtension1() {}
 testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e584bee
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+class Class1 {
+  Class1(this.field);
+  String toString() => 'Class1($field)';
+  int field;
+}
+
+class Class2 {
+  Class2(this.field);
+  String toString() => 'Class2($field)';
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension Extension1 on Class1 {
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  int method() {}
+  set property(int value) {}
+}
+
+extension Extension2 on Class2 {
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  int method() {}
+  set property(int value) {}
+}
+
+main() {}
+testExtension1() {}
+testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline.expect
index 9e94fcd..8e3e499 100644
--- a/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline.expect
@@ -1,4 +1,10 @@
 class Class1 {}
-extension Extension1 ;
-on Class1 (){}
+
+extension Extension1 on Class1 {
+  static staticMethod() {}
+  static get staticProperty {}
+  static set staticProperty(int value) {}
+  static var staticField = 42;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d5db1d4
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+class Class1 {}
+
+extension Extension1 on Class1 {
+  static get staticProperty {}
+  static set staticProperty(int value) {}
+  static staticMethod() {}
+  static var staticField = 42;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline.expect
index e84610c..1fd012e 100644
--- a/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline.expect
@@ -1,7 +1,17 @@
 class A1 {}
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  A1 method1() {}
+  A1 method2<T>(T o) {}
+  A1 method3<T>([T o]) {}
+  A1 method4<T>({T o}) {}
+}
+
 class B1<T> {}
-extension B2<T> (){}
-on B1<T> (){}
+
+extension B2<T> on B1<T> {
+  B1<T> method1() {}
+  B1<T> method2<S>(S o) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..bfacdaa
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class A1 {}
+
+class B1<T> {}
+
+extension A2 on A1 {
+  A1 method1() {}
+  A1 method2<T>(T o) {}
+  A1 method3<T>([T o]) {}
+  A1 method4<T>({T o}) {}
+}
+
+extension B2<T> on B1<T> {
+  B1<T> method1() {}
+  B1<T> method2<S>(S o) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline.expect
index 296e8e0..5d3c178 100644
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline.expect
@@ -3,15 +3,23 @@
   Class1(this.field);
   String toString() => 'Class1($field)';
 }
+
 class Class2 {
   int field;
   Class2(this.field);
   String toString() => 'Class2($field)';
 }
-extension Extension1 ;
-on Class1 (){}
-extension Extension2 ;
-on Class2 (){}
+
+extension Extension1 on Class1 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+}
+
+extension Extension2 on Class2 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+}
+
 main() {}
 testExtension1() {}
 testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ab11e38
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline_modelled.expect
@@ -0,0 +1,27 @@
+class Class1 {
+  Class1(this.field);
+  String toString() => 'Class1($field)';
+  int field;
+}
+
+class Class2 {
+  Class2(this.field);
+  String toString() => 'Class2($field)';
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension Extension1 on Class1 {
+  int genericMethod<T extends num>(T t) {}
+  int method() {}
+}
+
+extension Extension2 on Class2 {
+  int genericMethod<T extends num>(T t) {}
+  int method() {}
+}
+
+main() {}
+testExtension1() {}
+testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline.expect
index 3731a57..ad984f3 100644
--- a/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline.expect
@@ -1,9 +1,16 @@
 class Class {
   int field;
 }
-extension on ;
-Class (){}
-extension on ;
-Class (){}
+
+extension on Class {
+  int get property1 => property2;
+  void set property1(int value) => field = value;
+}
+
+extension on Class {
+  int get property2 => field;
+  void set property2(int value) => property1 = value;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b4a0cb3
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class Class {
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension on Class {
+  int get property1 => property2;
+  void set property1(int value) => field = value;
+}
+
+extension on Class {
+  int get property2 => field;
+  void set property2(int value) => property1 = value;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline.expect
index a8a7820..fda67e5 100644
--- a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline.expect
@@ -1,7 +1,13 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  method(a) {}
+}
+
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  method() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cccd074
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+class Class {}
+
+class GenericClass<T> {}
+
+extension Extension on Class {
+  method(a) {}
+}
+
+extension GenericExtension<T> on GenericClass<T> {
+  method() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline.expect
index ce040db..2654863 100644
--- a/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline.expect
@@ -1,4 +1,11 @@
-extension Extension ;
-on String (){}
+extension Extension on String {
+  static method() {}
+  static get getter => null;
+  static set setter(_) {}
+  static get property => null;
+  static set property(_) {}
+  static var field;
+}
+
 main() {}
 errors() {}
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0abe64c
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+errors() {}
+
+extension Extension on String {
+  static get getter => null;
+  static get property => null;
+  static method() {}
+  static set property(_) {}
+  static set setter(_) {}
+  static var field;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38600.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38600.dart.textual_outline.expect
index fd2b304..43bf0c2 100644
--- a/pkg/front_end/testcases/extensions/issue38600.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38600.dart.textual_outline.expect
@@ -1,4 +1,5 @@
 class Class<T> {}
-extension try<T> (){}
+extension on{}
+try<T> (){}
 on Class<T> (){}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38712.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38712.dart.textual_outline.expect
index 80db8ca..ec4321b 100644
--- a/pkg/front_end/testcases/extensions/issue38712.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38712.dart.textual_outline.expect
@@ -1,2 +1,2 @@
-extension C (){}
+extension C on{}
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline.expect
index 3843d11..07df337 100644
--- a/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline.expect
@@ -1,3 +1,8 @@
-extension C ;
-on int (){}
+extension C on int {
+  static int property2;
+  static void set property2(int x) {}
+  static void set property3(int x) {}
+  int get property3 => 1;
+}
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8b89684
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+extension C on int {
+  int get property3 => 1;
+  static int property2;
+  static void set property2(int x) {}
+  static void set property3(int x) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38745.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38745.dart.textual_outline.expect
index 61466b7..d0a4d03 100644
--- a/pkg/front_end/testcases/extensions/issue38745.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38745.dart.textual_outline.expect
@@ -1,5 +1,11 @@
 class C<T> {}
-extension ext<T> (){}
-on C<T> (){}
+extension ext<T> on C<T> {
+  int field;
+  final int property = 42;
+  void set property(int value) {}
+  final int property2 = 42;
+  static void set property2(int value) {}
+  method() {}
+}
 main() {}
 errors() {}
diff --git a/pkg/front_end/testcases/extensions/issue38755.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/issue38755.dart.strong.transformed.expect
index 724ef26..a04ed8e 100644
--- a/pkg/front_end/testcases/extensions/issue38755.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/issue38755.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   method myMap = self::A|myMap;
   tearoff myMap = self::A|get#myMap;
 }
-static final field core::List<core::String*>* list = self::A|myMap<core::String*, core::String*>(<core::String*>["a", "b", "c"], (core::String* it) → core::String* => it);
+static final field core::List<core::String*>* list = self::A|myMap<core::String*, core::String*>(core::_GrowableList::_literal3<core::String*>("a", "b", "c"), (core::String* it) → core::String* => it);
 static method A|myMap<T extends core::Object* = dynamic, R extends core::Object* = dynamic>(lowered final core::List<self::A|myMap::T*>* #this, (self::A|myMap::T*) →* self::A|myMap::R* block) → core::List<self::A|myMap::R*>* {
   return #this.{core::Iterable::map}<self::A|myMap::R*>(block).{core::Iterable::toList}();
 }
diff --git a/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline.expect
index b013cb4..c52f04b 100644
--- a/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline.expect
@@ -1,4 +1,7 @@
 final list = ["a", "b", "c"].myMap((it) => it);
-extension A<T> (){}
-on List<T> (){}
+
+extension A<T> on List<T> {
+  List<R> myMap<R>(R Function(T) block) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fd90a7a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+extension A<T> on List<T> {
+  List<R> myMap<R>(R Function(T) block) {}
+}
+
+final list = ["a", "b", "c"].myMap((it) => it);
+main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline.expect
index cc9ad4c..349b61f 100644
--- a/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline.expect
@@ -1,4 +1,10 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  void method1({bool b = false, String s = ', '}) => null;
+  void method2([bool b = false, String s = ', ']) => null;
+  void method3(int i, {bool b = false, String s = ', '}) {}
+  void method4(int i, [bool b = false, String s = ', ']) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..349b61f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+class Class {}
+
+extension Extension on Class {
+  void method1({bool b = false, String s = ', '}) => null;
+  void method2([bool b = false, String s = ', ']) => null;
+  void method3(int i, {bool b = false, String s = ', '}) {}
+  void method4(int i, [bool b = false, String s = ', ']) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.strong.expect b/pkg/front_end/testcases/extensions/issue39527.dart.strong.expect
index 8131831..16896b4 100644
--- a/pkg/front_end/testcases/extensions/issue39527.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.strong.expect
@@ -25,15 +25,15 @@
 }
 static method Extension1|[](lowered final self::C* #this, core::int* index) → self::C*
   return let final self::C* #t1 = #this in block {
-    let final self::C* #t2 = #t1 in #t2.{self::C::value} = #t2.{self::C::value}.{core::num::+}(index.{core::num::+}(1));
+    #t1.{self::C::value} = #t1.{self::C::value}.{core::num::+}(index.{core::num::+}(1));
   } =>#t1;
 static method Extension1|[]=(lowered final self::C* #this, core::int* index, self::C* other) → void
-  return let final self::C* #t3 = #this in #t3.{self::C::value} = #t3.{self::C::value}.{core::num::+}(other.{self::C::value}.{core::num::+}(index).{core::num::+}(1));
+  return #this.{self::C::value} = #this.{self::C::value}.{core::num::+}(other.{self::C::value}.{core::num::+}(index).{core::num::+}(1));
 static method Extension1|-(lowered final self::C* #this, core::int* val) → self::C*
   return #this;
 static method main() → dynamic {
   self::C* c = new self::C::•();
-  let final self::C* #t4 = c in let final core::int* #t5 = 42 in let final self::C* #t6 = self::Extension1|-(self::Extension1|[](#t4, #t5), 1) in let final void #t7 = self::Extension1|[]=(#t4, #t5, #t6) in #t6;
-  let final self::C* #t8 = c in let final core::int* #t9 = 42 in self::Extension1|[]=(#t8, #t9, self::Extension1|-(self::Extension1|[](#t8, #t9), 1));
+  let final self::C* #t2 = c in let final core::int* #t3 = 42 in let final self::C* #t4 = self::Extension1|-(self::Extension1|[](#t2, #t3), 1) in let final void #t5 = self::Extension1|[]=(#t2, #t3, #t4) in #t4;
+  let final self::C* #t6 = c in let final core::int* #t7 = 42 in self::Extension1|[]=(#t6, #t7, self::Extension1|-(self::Extension1|[](#t6, #t7), 1));
   self::Extension1|[]=(c, 42, self::Extension1|-(self::Extension1|[](c, 42), 1));
 }
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
index 85bc50b..59b0317 100644
--- a/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
@@ -25,16 +25,16 @@
 }
 static method Extension1|[](lowered final self::C* #this, core::int* index) → self::C*
   return let final self::C* #t1 = #this in block {
-    let final self::C* #t2 = #t1 in #t2.{self::C::value} = #t2.{self::C::value}.{core::num::+}(index.{core::num::+}(1));
+    #t1.{self::C::value} = #t1.{self::C::value}.{core::num::+}(index.{core::num::+}(1));
   } =>#t1;
 static method Extension1|[]=(lowered final self::C* #this, core::int* index, self::C* other) → void
-  return let final self::C* #t3 = #this in #t3.{self::C::value} = #t3.{self::C::value}.{core::num::+}(other.{self::C::value}.{core::num::+}(index).{core::num::+}(1));
+  return #this.{self::C::value} = #this.{self::C::value}.{core::num::+}(other.{self::C::value}.{core::num::+}(index).{core::num::+}(1));
 static method Extension1|-(lowered final self::C* #this, core::int* val) → self::C*
   return #this;
 static method main() → dynamic {
   self::C* c = new self::C::•();
-  let final self::C* #t4 = c in let final core::int* #t5 = 42 in let final self::C* #t6 = self::Extension1|-(self::Extension1|[](#t4, #t5), 1) in let final void #t7 = self::Extension1|[]=(#t4, #t5, #t6) in #t6;
-  let final self::C* #t8 = c in let final core::int* #t9 = 42 in self::Extension1|[]=(#t8, #t9, self::Extension1|-(self::Extension1|[](#t8, #t9), 1));
+  let final self::C* #t2 = c in let final core::int* #t3 = 42 in let final self::C* #t4 = self::Extension1|-(self::Extension1|[](#t2, #t3), 1) in let final void #t5 = self::Extension1|[]=(#t2, #t3, #t4) in #t4;
+  let final self::C* #t6 = c in let final core::int* #t7 = 42 in self::Extension1|[]=(#t6, #t7, self::Extension1|-(self::Extension1|[](#t6, #t7), 1));
   self::Extension1|[]=(c, 42, self::Extension1|-(self::Extension1|[](c, 42), 1));
 }
 
@@ -44,4 +44,4 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:19:19 -> IntConstant(42)
 Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:22:17 -> IntConstant(42)
 Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:22:17 -> IntConstant(42)
-Extra constant evaluation: evaluated: 56, effectively constant: 4
+Extra constant evaluation: evaluated: 52, effectively constant: 4
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline.expect
index 7ec2575..586004b 100644
--- a/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline.expect
@@ -1,6 +1,12 @@
 class C {
   int value = 0;
 }
-extension Extension1 ;
-on C (){}
+
+extension Extension1 on C {
+  C operator [](int index) => this..value += index + 1;
+  void operator []=(int index, C other) =>
+      this.value += other.value + index + 1;
+  C operator -(int val) => this;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..56b4c36
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class C {
+  int value = 0;
+}
+
+extension Extension1 on C {
+  C operator -(int val) => this;
+  C operator [](int index) => this..value += index + 1;
+  void operator []=(int index, C other) =>
+      this.value += other.value + index + 1;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline.expect
index 9e92bb8..2b64dea 100644
--- a/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline.expect
@@ -1,4 +1,7 @@
 class C {}
-extension E ;
-on C (){}
+
+extension E on C {
+  void f(String b) {}
+}
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2b64dea
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class C {}
+
+extension E on C {
+  void f(String b) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline.expect
index a0ad8ac..ee456e8 100644
--- a/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline.expect
@@ -1,4 +1,7 @@
 import 'dart:async';
+
 void main() {}
-extension Extension<T> (){}
-on Stream<T> (){}
+
+extension Extension<T> on Stream<T> {
+  StreamSubscription<T> call(Function onData) {}
+}
diff --git a/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a5b08bb
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+import 'dart:async';
+
+extension Extension<T> on Stream<T> {
+  StreamSubscription<T> call(Function onData) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline.expect
index bcdffa4..86e8aaa 100644
--- a/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline.expect
@@ -1,5 +1,7 @@
-extension SafeAccess<T> (){}
-on Iterable<T> (){}
+extension SafeAccess<T> on Iterable<T> {
+  T get safeFirst {}
+}
+
 main() {}
 void test() {}
 void errors() {}
diff --git a/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b4b03d34
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+extension SafeAccess<T> on Iterable<T> {
+  T get safeFirst {}
+}
+
+main() {}
+void errors() {}
+void test() {}
diff --git a/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline.expect
index e32df9a..e806109 100644
--- a/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline.expect
@@ -1,5 +1,9 @@
 class A {}
+
 class B {}
-extension on ;
-A (){}
+
+extension on A {
+  void foo(A a, B b) {}
+}
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e806109
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class A {}
+
+class B {}
+
+extension on A {
+  void foo(A a, B b) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline.expect
index 4eec6f8..c3323e8 100644
--- a/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline.expect
@@ -5,7 +5,10 @@
   int get id => value;
   void set id(int v) {}
 }
-extension Ext ;
-on C (){}
+
+extension Ext on C {
+  int get id => this.value + 1;
+}
+
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6c5f1e6
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class C {
+  C() : value = 0 {}
+  init() {}
+  int get id => value;
+  int value;
+  void set id(int v) {}
+}
+
+extension Ext on C {
+  int get id => this.value + 1;
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline.expect
index 2f9718a..5f989b2 100644
--- a/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline.expect
@@ -1,6 +1,9 @@
-extension Test<T> (){}
-on T (){}
+extension Test<T> on T {
+  T Function(T) get test => (a) => this;
+}
+
 class Foo<S extends num> {
   void test1(S x) {}
 }
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9aaf1c7
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Foo<S extends num> {
+  void test1(S x) {}
+}
+
+extension Test<T> on T {
+  T Function(T) get test => (a) => this;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline.expect
index d11cf6d..83182ff 100644
--- a/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline.expect
@@ -1,6 +1,9 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  void set setter(int value) {}
+}
+
 var c = new Class();
 var missingGetter = c.setter += 42;
 main() {}
diff --git a/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..94e9a17
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class {}
+
+extension Extension on Class {
+  void set setter(int value) {}
+}
+
+main() {}
+var c = new Class();
+var missingGetter = c.setter += 42;
diff --git a/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline.expect
index c1528bd..8970b3e 100644
--- a/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline.expect
@@ -1,4 +1,8 @@
 class A<T> {}
-extension Extension<T> (){}
-on A<A<T>> (){}
+
+extension Extension<T> on A<A<T>> {
+  method1() {}
+  method2<A>(A a) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8970b3e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class A<T> {}
+
+extension Extension<T> on A<A<T>> {
+  method1() {}
+  method2<A>(A a) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline.expect
index 54442ce..378b04c 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline.expect
@@ -1,7 +1,13 @@
 class Class {
   int field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  int get property => field;
+  void set property(int value) {}
+  int method() => field;
+  testImplicitThis() {}
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..dc73414
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class Class {
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension Extension on Class {
+  int get property => field;
+  int method() => field;
+  testImplicitThis() {}
+  void set property(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline.expect
index 72efc6a..7b1f078 100644
--- a/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline.expect
@@ -1,7 +1,14 @@
-extension<R, T> on ;
-R Function(T) {}
+extension<R, T> on R Function(T) {
+  Type get returnType => R;
+  Type get parameterType => T;
+}
+
 class Class<T extends Class<T>> {}
+
 class Subclass extends Class<Subclass> {}
-extension<T extends Class<T>> on ;
-dynamic Function<S extends T>(T, S) {}
+
+extension<T extends Class<T>> on dynamic Function<S extends T>(T, S) {
+  Type get parameterType => T;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d84ff38
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class Class<T extends Class<T>> {}
+
+class Subclass extends Class<Subclass> {}
+
+extension<R, T> on R Function(T) {
+  Type get parameterType => T;
+  Type get returnType => R;
+}
+
+extension<T extends Class<T>> on dynamic Function<S extends T>(T, S) {
+  Type get parameterType => T;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline.expect
index 9edafca..9aa7eba 100644
--- a/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline.expect
@@ -1,7 +1,13 @@
-extension BestCom<T extends num> (){}
-on Iterable<T> (){}
-extension BestList<T> (){}
-on List<T> (){}
-extension BestSpec ;
-on List<num> (){}
+extension BestCom<T extends num> on Iterable<T> {
+  T best() => null;
+}
+
+extension BestList<T> on List<T> {
+  T best() => null;
+}
+
+extension BestSpec on List<num> {
+  num best() => null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9aa7eba
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+extension BestCom<T extends num> on Iterable<T> {
+  T best() => null;
+}
+
+extension BestList<T> on List<T> {
+  T best() => null;
+}
+
+extension BestSpec on List<num> {
+  num best() => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline.expect
index a75ec57..d757af3 100644
--- a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline.expect
@@ -1,8 +1,16 @@
 class Struct {}
+
 class StructA extends Struct {}
+
 class StructB extends Struct {}
+
 class NonStruct {}
-extension Extension<T extends Struct> (){}
-on T (){}
+
+extension Extension<T extends Struct> on T {
+  T method() => this;
+  T get property => this;
+  void set property(T value) {}
+}
+
 main() {}
 testNonStruct() {}
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..16a0644
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,16 @@
+class NonStruct {}
+
+class Struct {}
+
+class StructA extends Struct {}
+
+class StructB extends Struct {}
+
+extension Extension<T extends Struct> on T {
+  T get property => this;
+  T method() => this;
+  void set property(T value) {}
+}
+
+main() {}
+testNonStruct() {}
diff --git a/pkg/front_end/testcases/extensions/operators.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/operators.dart.textual_outline.expect
index 3ed1892..908102a 100644
--- a/pkg/front_end/testcases/extensions/operators.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/operators.dart.textual_outline.expect
@@ -9,8 +9,13 @@
   bool operator ==(Object other) {}
   String toString() => 'Complex($real,$imaginary)';
 }
-extension Operators ;
-on Complex (){}
+
+extension Operators on Complex {
+  Complex operator +(Complex other) => add(other);
+  Complex operator -(Complex other) => sub(other);
+  Complex operator -() => negate();
+}
+
 main() {}
 implicit() {}
 explicit() {}
diff --git a/pkg/front_end/testcases/extensions/operators.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/operators.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d77488d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/operators.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class Complex {
+  Complex add(Complex other) {}
+  Complex negate() {}
+  Complex sub(Complex other) {}
+  String toString() => 'Complex($real,$imaginary)';
+  bool operator ==(Object other) {}
+  const Complex(this.real, this.imaginary);
+  final double imaginary;
+  final double real;
+  int get hashCode => real.hashCode * 13 + imaginary.hashCode * 19;
+}
+
+expect(expected, actual) {}
+explicit() {}
+
+extension Operators on Complex {
+  Complex operator +(Complex other) => add(other);
+  Complex operator -() => negate();
+  Complex operator -(Complex other) => sub(other);
+}
+
+implicit() {}
+main() {}
+void errors(Complex c) {}
diff --git a/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline.expect
index bd1c7e9..85d642c 100644
--- a/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline.expect
@@ -6,6 +6,16 @@
   static int getStaticField() => _staticField;
   static void setStaticField(int value) {}
 }
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  int get instanceProperty => getInstanceField();
+  void set instanceProperty(int value) {}
+  int operator +(int value) {}
+  int operator -(int value) {}
+  int operator -() {}
+  static int staticField = A1.getStaticField();
+  static int get staticProperty => A1.getStaticField();
+  static void set staticProperty(int value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1e10a1c
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class A1 {
+  int _instanceField;
+  int getInstanceField() => _instanceField;
+  static int _staticField = 0;
+  static int getStaticField() => _staticField;
+  static void setStaticField(int value) {}
+  void setInstanceField(int value) {}
+}
+
+extension A2 on A1 {
+  int get instanceProperty => getInstanceField();
+  int operator +(int value) {}
+  int operator -() {}
+  int operator -(int value) {}
+  static int get staticProperty => A1.getStaticField();
+  static int staticField = A1.getStaticField();
+  static void set staticProperty(int value) {}
+  void set instanceProperty(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/static_access.dart.textual_outline.expect
index cc9ad4c..af89663 100644
--- a/pkg/front_end/testcases/extensions/static_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/static_access.dart.textual_outline.expect
@@ -1,4 +1,14 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  static method() {}
+  static genericMethod<T>(T t) {}
+  static get property => 42;
+  static set property(value) {}
+  static var field;
+  instanceMethod() {}
+  get instanceProperty => 42;
+  set instanceProperty(value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/static_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d7a88d1
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/static_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class Class {}
+
+extension Extension on Class {
+  get instanceProperty => 42;
+  instanceMethod() {}
+  set instanceProperty(value) {}
+  static genericMethod<T>(T t) {}
+  static get property => 42;
+  static method() {}
+  static set property(value) {}
+  static var field;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline.expect
index cc9ad4c..38dbcbf 100644
--- a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline.expect
@@ -1,4 +1,9 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  instanceMethod() {}
+  get instanceProperty => 42;
+  set instanceProperty(value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..114f677
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class {}
+
+extension Extension on Class {
+  get instanceProperty => 42;
+  instanceMethod() {}
+  set instanceProperty(value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline.expect
index 9c93cbd..45dbc23 100644
--- a/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline.expect
@@ -1,5 +1,11 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  T id<T>(T t) => t;
+  T Function<T>(T) get getter => id;
+  method() {}
+  errors() {}
+}
+
 main() {}
 errors() {}
diff --git a/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5ce0c980
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class Class {}
+
+errors() {}
+
+extension Extension on Class {
+  T Function<T>(T) get getter => id;
+  T id<T>(T t) => t;
+  errors() {}
+  method() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/type_variable_bound.dart.strong.expect b/pkg/front_end/testcases/extensions/type_variable_bound.dart.strong.expect
index 3dfb6be..a20912a 100644
--- a/pkg/front_end/testcases/extensions/type_variable_bound.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/type_variable_bound.dart.strong.expect
@@ -45,7 +45,7 @@
   return new self::Class::•();
 }
 static method test2<T extends self::Class* = self::Class*>(self::test2::T* t2) → dynamic {
-  if(self::test2::T*.{core::Type::==}(self::SubClass*)) {
+  if(self::test2::T*.{core::Type::==}(#C1)) {
     self::SubClass* subClass = self::BoundExtension|method2<self::Class*>(t2) as{TypeError} self::SubClass*;
   }
 }
@@ -55,3 +55,7 @@
   }
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::SubClass*)
+}
diff --git a/pkg/front_end/testcases/extensions/type_variable_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/type_variable_bound.dart.strong.transformed.expect
index 79b6d8f..a20912a 100644
--- a/pkg/front_end/testcases/extensions/type_variable_bound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/type_variable_bound.dart.strong.transformed.expect
@@ -45,7 +45,7 @@
   return new self::Class::•();
 }
 static method test2<T extends self::Class* = self::Class*>(self::test2::T* t2) → dynamic {
-  if(self::test2::T*.{core::Type::==}(self::SubClass*)) {
+  if(self::test2::T*.{core::Type::==}(#C1)) {
     self::SubClass* subClass = self::BoundExtension|method2<self::Class*>(t2) as{TypeError} self::SubClass*;
   }
 }
@@ -56,7 +56,6 @@
 }
 static method main() → dynamic {}
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_variable_bound.dart:27:12 -> TypeLiteralConstant(SubClass*)
-Extra constant evaluation: evaluated: 23, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(self::SubClass*)
+}
diff --git a/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline.expect
index a9b3ce3..59d5ad1 100644
--- a/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline.expect
@@ -1,10 +1,16 @@
 // @dart = 2.8
-extension Extension<T> (){}
-on T (){}
-extension BoundExtension<T extends Class> (){}
-on T (){}
+extension Extension<T> on T {
+  T method1() => this;
+}
+
+extension BoundExtension<T extends Class> on T {
+  T method2() => this;
+}
+
 class Class {}
+
 class SubClass extends Class {}
+
 Class test1<T>(T t1) {}
 test2<T extends Class>(T t2) {}
 test3<T>(T t3) {}
diff --git a/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a08e473
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline_modelled.expect
@@ -0,0 +1,18 @@
+// @dart = 2.8
+Class test1<T>(T t1) {}
+
+class Class {}
+
+class SubClass extends Class {}
+
+extension BoundExtension<T extends Class> on T {
+  T method2() => this;
+}
+
+extension Extension<T> on T {
+  T method1() => this;
+}
+
+main() {}
+test2<T extends Class>(T t2) {}
+test3<T>(T t3) {}
diff --git a/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline.expect
index 60b1f69..4f3bfdf 100644
--- a/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline.expect
@@ -1,8 +1,14 @@
 class A1<T> {}
-extension A2<T> (){}
-on A1<T> (){}
-extension A3<T extends A1<T>> (){}
-on A1<T> (){}
-extension A4<T> (){}
-on A1<T> (){}
+
+extension A2<T> on A1<T> {
+  A1<T> method1<S extends T>() {}
+  A1<T> method2<S extends A1<T>>(S o) {}
+}
+
+extension A3<T extends A1<T>> on A1<T> {}
+
+extension A4<T> on A1<T> {
+  method<T>() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4f3bfdf
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class A1<T> {}
+
+extension A2<T> on A1<T> {
+  A1<T> method1<S extends T>() {}
+  A1<T> method2<S extends A1<T>>(S o) {}
+}
+
+extension A3<T extends A1<T>> on A1<T> {}
+
+extension A4<T> on A1<T> {
+  method<T>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline.expect
index 8641f18..792016b 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline.expect
@@ -3,15 +3,27 @@
   Class1(this.field);
   String toString() => 'Class1($field)';
 }
+
 class Class2 {
   int field;
   Class2(this.field);
   String toString() => 'Class2($field)';
 }
-extension on ;
-Class1 (){}
-extension on ;
-Class2 (){}
+
+extension on Class1 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  set property(int value) {}
+}
+
+extension on Class2 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  set property(int value) {}
+}
+
 main() {}
 testExtension1() {}
 testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..66a7a5b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+class Class1 {
+  Class1(this.field);
+  String toString() => 'Class1($field)';
+  int field;
+}
+
+class Class2 {
+  Class2(this.field);
+  String toString() => 'Class2($field)';
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension on Class1 {
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  int method() {}
+  set property(int value) {}
+}
+
+extension on Class2 {
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  int method() {}
+  set property(int value) {}
+}
+
+main() {}
+testExtension1() {}
+testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/use_this.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/use_this.dart.textual_outline.expect
index e84610c..f12590a 100644
--- a/pkg/front_end/testcases/extensions/use_this.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/use_this.dart.textual_outline.expect
@@ -1,7 +1,15 @@
 class A1 {}
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  A1 method1() {}
+  A1 method2<T>(T o) {}
+}
+
 class B1<T> {}
-extension B2<T> (){}
-on B1<T> (){}
+
+extension B2<T> on B1<T> {
+  B1<T> method1() {}
+  B1<T> method2<S>(S o) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/use_this.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/use_this.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f79fb58
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/use_this.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class A1 {}
+
+class B1<T> {}
+
+extension A2 on A1 {
+  A1 method1() {}
+  A1 method2<T>(T o) {}
+}
+
+extension B2<T> on B1<T> {
+  B1<T> method1() {}
+  B1<T> method2<S>(S o) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/DeltaBlue.dart.strong.expect b/pkg/front_end/testcases/general/DeltaBlue.dart.strong.expect
index d1cc44e..9e26317 100644
--- a/pkg/front_end/testcases/general/DeltaBlue.dart.strong.expect
+++ b/pkg/front_end/testcases/general/DeltaBlue.dart.strong.expect
@@ -533,3 +533,9 @@
   #C21 = "required"
   #C22 = self::Strength {value:#C20, name:#C21}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///DeltaBlue.dart:
+- Strength. (from org-dartlang-testcase:///DeltaBlue.dart:59:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/DeltaBlue.dart.strong.transformed.expect b/pkg/front_end/testcases/general/DeltaBlue.dart.strong.transformed.expect
index d1cc44e..a21d5791 100644
--- a/pkg/front_end/testcases/general/DeltaBlue.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/DeltaBlue.dart.strong.transformed.expect
@@ -265,7 +265,7 @@
   }
 }
 class Variable extends core::Object {
-  field core::List<self::Constraint*>* constraints = <self::Constraint*>[];
+  field core::List<self::Constraint*>* constraints = core::_GrowableList::•<self::Constraint*>(0);
   field self::Constraint* determinedBy = null;
   field core::int* mark = 0;
   field self::Strength* walkStrength = #C18;
@@ -337,7 +337,7 @@
     return plan;
   }
   method extractPlanFromConstraints(core::List<self::Constraint*>* constraints) → self::Plan* {
-    core::List<self::Constraint*>* sources = <self::Constraint*>[];
+    core::List<self::Constraint*>* sources = core::_GrowableList::•<self::Constraint*>(0);
     for (core::int* i = 0; i.{core::num::<}(constraints.{core::List::length}); i = i.{core::num::+}(1)) {
       self::Constraint* c = constraints.{core::List::[]}(i);
       if(c.{self::Constraint::isInput}() && c.{self::Constraint::isSatisfied}())
@@ -346,7 +346,7 @@
     return this.{self::Planner::makePlan}(sources);
   }
   method addPropagate(self::Constraint* c, core::int* mark) → core::bool* {
-    core::List<self::Constraint*>* todo = <self::Constraint*>[c];
+    core::List<self::Constraint*>* todo = core::_GrowableList::_literal1<self::Constraint*>(c);
     while (todo.{core::List::length}.{core::num::>}(0)) {
       self::Constraint* d = todo.{core::List::removeLast}();
       if(d.{self::Constraint::output}().{self::Variable::mark}.{core::num::==}(mark)) {
@@ -362,8 +362,8 @@
     out.{self::Variable::determinedBy} = null;
     out.{self::Variable::walkStrength} = #C18;
     out.{self::Variable::stay} = true;
-    core::List<self::Constraint*>* unsatisfied = <self::Constraint*>[];
-    core::List<self::Variable*>* todo = <self::Variable*>[out];
+    core::List<self::Constraint*>* unsatisfied = core::_GrowableList::•<self::Constraint*>(0);
+    core::List<self::Variable*>* todo = core::_GrowableList::_literal1<self::Variable*>(out);
     while (todo.{core::List::length}.{core::num::>}(0)) {
       self::Variable* v = todo.{core::List::removeLast}();
       for (core::int* i = 0; i.{core::num::<}(v.{self::Variable::constraints}.{core::List::length}); i = i.{core::num::+}(1)) {
@@ -402,7 +402,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Plan extends core::Object {
-  field core::List<self::Constraint*>* list = <self::Constraint*>[];
+  field core::List<self::Constraint*>* list = core::_GrowableList::•<self::Constraint*>(0);
   synthetic constructor •() → self::Plan*
     : super core::Object::•()
     ;
@@ -458,7 +458,7 @@
   }
   new self::StayConstraint::•(last, #C9);
   self::EditConstraint* edit = new self::EditConstraint::•(first, #C6);
-  self::Plan* plan = self::planner.{self::Planner::extractPlanFromConstraints}(<self::Constraint*>[edit]);
+  self::Plan* plan = self::planner.{self::Planner::extractPlanFromConstraints}(core::_GrowableList::_literal1<self::Constraint*>(edit));
   for (core::int* i = 0; i.{core::num::<}(100); i = i.{core::num::+}(1)) {
     first.{self::Variable::value} = i;
     plan.{self::Plan::execute}();
@@ -474,7 +474,7 @@
   self::Variable* offset = new self::Variable::•("offset", 1000);
   self::Variable* src = null;
   self::Variable* dst = null;
-  core::List<self::Variable*>* dests = <self::Variable*>[];
+  core::List<self::Variable*>* dests = core::_GrowableList::•<self::Variable*>(0);
   for (core::int* i = 0; i.{core::num::<}(n); i = i.{core::num::+}(1)) {
     src = new self::Variable::•("src", i);
     dst = new self::Variable::•("dst", i);
@@ -501,7 +501,7 @@
 }
 static method change(self::Variable* v, core::int* newValue) → void {
   self::EditConstraint* edit = new self::EditConstraint::•(v, #C6);
-  self::Plan* plan = self::planner.{self::Planner::extractPlanFromConstraints}(<self::EditConstraint*>[edit]);
+  self::Plan* plan = self::planner.{self::Planner::extractPlanFromConstraints}(core::_GrowableList::_literal1<self::EditConstraint*>(edit));
   for (core::int* i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
     v.{self::Variable::value} = newValue;
     plan.{self::Plan::execute}();
@@ -533,3 +533,9 @@
   #C21 = "required"
   #C22 = self::Strength {value:#C20, name:#C21}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///DeltaBlue.dart:
+- Strength. (from org-dartlang-testcase:///DeltaBlue.dart:59:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/abstract_members.dart.outline.expect b/pkg/front_end/testcases/general/abstract_members.dart.outline.expect
index c556119..d4b2ca4 100644
--- a/pkg/front_end/testcases/general/abstract_members.dart.outline.expect
+++ b/pkg/front_end/testcases/general/abstract_members.dart.outline.expect
@@ -12,6 +12,26 @@
 //   var interfaceMethod1;
 //       ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general/abstract_members.dart:27:16: Error: Can't inherit members that conflict with each other.
+// abstract class B extends A {
+//                ^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_members.dart:33:7: Error: Can't inherit members that conflict with each other.
+// class MyClass extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
 // pkg/front_end/testcases/general/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property1=
@@ -50,6 +70,36 @@
 //   void interfaceMethod3() {}
 //        ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general/abstract_members.dart:42:7: Error: Can't inherit members that conflict with each other.
+// class MyMock1 extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_members.dart:48:7: Error: Can't inherit members that conflict with each other.
+// class MyMock2 extends MyMock1 {
+//       ^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_members.dart:54:7: Error: Can't inherit members that conflict with each other.
+// class MyMock3 extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
 // pkg/front_end/testcases/general/abstract_members.dart:54:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property1=
diff --git a/pkg/front_end/testcases/general/abstract_members.dart.strong.expect b/pkg/front_end/testcases/general/abstract_members.dart.strong.expect
index 9a2d8e1..a798711 100644
--- a/pkg/front_end/testcases/general/abstract_members.dart.strong.expect
+++ b/pkg/front_end/testcases/general/abstract_members.dart.strong.expect
@@ -12,6 +12,26 @@
 //   var interfaceMethod1;
 //       ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general/abstract_members.dart:27:16: Error: Can't inherit members that conflict with each other.
+// abstract class B extends A {
+//                ^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_members.dart:33:7: Error: Can't inherit members that conflict with each other.
+// class MyClass extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
 // pkg/front_end/testcases/general/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property1=
@@ -50,6 +70,36 @@
 //   void interfaceMethod3() {}
 //        ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general/abstract_members.dart:42:7: Error: Can't inherit members that conflict with each other.
+// class MyMock1 extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_members.dart:48:7: Error: Can't inherit members that conflict with each other.
+// class MyMock2 extends MyMock1 {
+//       ^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/abstract_members.dart:54:7: Error: Can't inherit members that conflict with each other.
+// class MyMock3 extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:6:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/abstract_members.dart:12:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
 // pkg/front_end/testcases/general/abstract_members.dart:54:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property1=
diff --git a/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.outline.expect b/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.outline.expect
index 2f6b693..d789cb9 100644
--- a/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.outline.expect
+++ b/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.outline.expect
@@ -25,12 +25,12 @@
 // pkg/front_end/testcases/general/abstract_overrides_concrete.dart:23:7: Error: The implementation of 'foo' in the non-abstract class 'F' does not conform to its interface.
 // class F extends E {}
 //       ^
-// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:6:8: Context: The method 'A.foo' has fewer positional arguments than those of overridden method 'E.foo'.
+// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:6:8: Context: The method 'A.foo' has fewer positional arguments than those of overridden method 'I.foo'.
 //   void foo() {}
 //        ^
-// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:21:16: Context: This is the overridden method ('foo').
-// abstract class E extends A implements I {}
-//                ^
+// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:10:8: Context: This is the overridden method ('foo').
+//   void foo([a]);
+//        ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.strong.expect b/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.strong.expect
index 0529482..90c7a87 100644
--- a/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.strong.expect
+++ b/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.strong.expect
@@ -25,12 +25,12 @@
 // pkg/front_end/testcases/general/abstract_overrides_concrete.dart:23:7: Error: The implementation of 'foo' in the non-abstract class 'F' does not conform to its interface.
 // class F extends E {}
 //       ^
-// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:6:8: Context: The method 'A.foo' has fewer positional arguments than those of overridden method 'E.foo'.
+// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:6:8: Context: The method 'A.foo' has fewer positional arguments than those of overridden method 'I.foo'.
 //   void foo() {}
 //        ^
-// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:21:16: Context: This is the overridden method ('foo').
-// abstract class E extends A implements I {}
-//                ^
+// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:10:8: Context: This is the overridden method ('foo').
+//   void foo([a]);
+//        ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.strong.transformed.expect b/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.strong.transformed.expect
index 0529482..90c7a87 100644
--- a/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/abstract_overrides_concrete.dart.strong.transformed.expect
@@ -25,12 +25,12 @@
 // pkg/front_end/testcases/general/abstract_overrides_concrete.dart:23:7: Error: The implementation of 'foo' in the non-abstract class 'F' does not conform to its interface.
 // class F extends E {}
 //       ^
-// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:6:8: Context: The method 'A.foo' has fewer positional arguments than those of overridden method 'E.foo'.
+// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:6:8: Context: The method 'A.foo' has fewer positional arguments than those of overridden method 'I.foo'.
 //   void foo() {}
 //        ^
-// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:21:16: Context: This is the overridden method ('foo').
-// abstract class E extends A implements I {}
-//                ^
+// pkg/front_end/testcases/general/abstract_overrides_concrete.dart:10:8: Context: This is the overridden method ('foo').
+//   void foo([a]);
+//        ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.outline.expect b/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.outline.expect
index 54ce84a..c9348b9 100644
--- a/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.outline.expect
+++ b/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.outline.expect
@@ -7,6 +7,7 @@
     ;
   method foo() → self::A*
     ;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -15,7 +16,6 @@
   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
 }
 abstract class B extends self::A {
diff --git a/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.strong.expect b/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.strong.expect
index 732160e..c52e1a4 100644
--- a/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.strong.expect
+++ b/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.strong.expect
@@ -8,6 +8,7 @@
     ;
   method foo() → self::A*
     return null;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -16,7 +17,6 @@
   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
 }
 abstract class B extends self::A {
diff --git a/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.strong.transformed.expect b/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.strong.transformed.expect
index 732160e..c52e1a4 100644
--- a/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.strong.transformed.expect
@@ -8,6 +8,7 @@
     ;
   method foo() → self::A*
     return null;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -16,7 +17,6 @@
   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
 }
 abstract class B extends self::A {
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
index 742c6ea..e27f5c8 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
@@ -59,3 +59,10 @@
   #C11 = 42
   #C12 = self::Fisk<core::int*> {x:#C11}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_on_enum_values.dart:
+- Foo. (from org-dartlang-testcase:///annotation_on_enum_values.dart:15:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Fisk.fisk (from org-dartlang-testcase:///annotation_on_enum_values.dart:12:9)
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
index 742c6ea..e27f5c8 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
@@ -59,3 +59,10 @@
   #C11 = 42
   #C12 = self::Fisk<core::int*> {x:#C11}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_on_enum_values.dart:
+- Foo. (from org-dartlang-testcase:///annotation_on_enum_values.dart:15:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Fisk.fisk (from org-dartlang-testcase:///annotation_on_enum_values.dart:12:9)
diff --git a/pkg/front_end/testcases/general/annotation_top.dart.strong.expect b/pkg/front_end/testcases/general/annotation_top.dart.strong.expect
index e0a2535..b8fa4b8 100644
--- a/pkg/front_end/testcases/general/annotation_top.dart.strong.expect
+++ b/pkg/front_end/testcases/general/annotation_top.dart.strong.expect
@@ -57,3 +57,9 @@
   #C1 = core::Object {}
   #C2 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_top.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- A. (from org-dartlang-testcase:///annotation_top.dart:12:9)
diff --git a/pkg/front_end/testcases/general/annotation_top.dart.strong.transformed.expect b/pkg/front_end/testcases/general/annotation_top.dart.strong.transformed.expect
index e0a2535..b8fa4b8 100644
--- a/pkg/front_end/testcases/general/annotation_top.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_top.dart.strong.transformed.expect
@@ -57,3 +57,9 @@
   #C1 = core::Object {}
   #C2 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_top.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- A. (from org-dartlang-testcase:///annotation_top.dart:12:9)
diff --git a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
index 4c86065..de080e6 100644
--- a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
+++ b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.expect
@@ -60,3 +60,10 @@
   #C2 = self::Bar {}
   #C3 = null
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_variable_declaration.dart:
+- Bar. (from org-dartlang-testcase:///annotation_variable_declaration.dart:8:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Bar.named (from org-dartlang-testcase:///annotation_variable_declaration.dart:9:9)
diff --git a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
index 4c86065..de080e6 100644
--- a/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_variable_declaration.dart.strong.transformed.expect
@@ -60,3 +60,10 @@
   #C2 = self::Bar {}
   #C3 = null
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_variable_declaration.dart:
+- Bar. (from org-dartlang-testcase:///annotation_variable_declaration.dart:8:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Bar.named (from org-dartlang-testcase:///annotation_variable_declaration.dart:9:9)
diff --git a/pkg/front_end/testcases/general/arithmetic.dart.strong.transformed.expect b/pkg/front_end/testcases/general/arithmetic.dart.strong.transformed.expect
index ed95ed2..0f2a3e1 100644
--- a/pkg/front_end/testcases/general/arithmetic.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/arithmetic.dart.strong.transformed.expect
@@ -14,5 +14,5 @@
 static method main() → dynamic {
   self::foo(4, 5);
   self::foo(6, 7);
-  self::loop(<dynamic>["dfg"]);
+  self::loop(core::_GrowableList::_literal1<dynamic>("dfg"));
 }
diff --git a/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect b/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
index 33ab33f..2a42c83 100644
--- a/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 
 import "dart:async";
 
-static field core::List<core::String*>* stringList = <core::String*>["bar"];
+static field core::List<core::String*>* stringList = core::_GrowableList::_literal1<core::String*>("bar");
 static method asyncString() → asy::Future<core::String*>* /* originally async */ {
   final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
   core::bool* :is_sync = false;
diff --git a/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
index 78818d9..760f00e 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
@@ -44,18 +44,18 @@
       #L1:
       {
         core::String* expected = "1 2 3 4 5 6 7 8 9 10";
-        :async_temporary_2 = new self::Node::•("2", <self::Node*>[]);
-        [yield] let dynamic #t4 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("7", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
-        [yield] let dynamic #t5 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("6", <self::Node*>[_in::unsafeCast<self::Node*>(:result)])), :async_op_then, :async_op_error, :async_op) in null;
+        :async_temporary_2 = new self::Node::•("2", core::_GrowableList::•<self::Node*>(0));
+        [yield] let dynamic #t4 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("7", core::_GrowableList::•<self::Node*>(0))), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t5 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("6", core::_GrowableList::_literal1<self::Node*>(_in::unsafeCast<self::Node*>(:result)))), :async_op_then, :async_op_error, :async_op) in null;
         :async_temporary_1 = _in::unsafeCast<self::Node*>(:result);
-        [yield] let dynamic #t6 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("8", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t6 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("8", core::_GrowableList::•<self::Node*>(0))), :async_op_then, :async_op_error, :async_op) in null;
         :async_temporary_0 = _in::unsafeCast<self::Node*>(:result);
-        [yield] let dynamic #t7 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("9", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
-        [yield] let dynamic #t8 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("4", <self::Node*>[new self::Node::•("5", <self::Node*>[_in::unsafeCast<self::Node*>(:async_temporary_1), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)])])), :async_op_then, :async_op_error, :async_op) in null;
-        [yield] let dynamic #t9 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("3", <self::Node*>[_in::unsafeCast<self::Node*>(:result)])), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t7 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("9", core::_GrowableList::•<self::Node*>(0))), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t8 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("4", core::_GrowableList::_literal1<self::Node*>(new self::Node::•("5", core::_GrowableList::_literal3<self::Node*>(_in::unsafeCast<self::Node*>(:async_temporary_1), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)))))), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t9 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("3", core::_GrowableList::_literal1<self::Node*>(_in::unsafeCast<self::Node*>(:result)))), :async_op_then, :async_op_error, :async_op) in null;
         :async_temporary_0 = _in::unsafeCast<self::Node*>(:result);
-        [yield] let dynamic #t10 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("10", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
-        self::Node* node = new self::Node::•("1", <self::Node*>[_in::unsafeCast<self::Node*>(:async_temporary_2), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)]);
+        [yield] let dynamic #t10 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("10", core::_GrowableList::•<self::Node*>(0))), :async_op_then, :async_op_error, :async_op) in null;
+        self::Node* node = new self::Node::•("1", core::_GrowableList::_literal3<self::Node*>(_in::unsafeCast<self::Node*>(:async_temporary_2), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)));
         core::String* actual = node.{self::Node::toSimpleString}() as{TypeError,ForDynamic} core::String*;
         core::print(actual);
         if(!actual.{core::String::==}(expected)) {
diff --git a/pkg/front_end/testcases/general/await_complex.dart.strong.expect b/pkg/front_end/testcases/general/await_complex.dart.strong.expect
index 60f6730..efab03a 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.strong.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.strong.expect
@@ -56,54 +56,54 @@
 static method dummy() → dynamic
   return 1;
 static method staticMembers() → dynamic async {
-  core::num* a = self::C::staticField.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* a = self::C::staticField.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, a);
-  core::num* f = (self::C::staticField = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* f = (self::C::staticField = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, f);
-  core::num* b = self::C::staticGetter.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* b = self::C::staticGetter.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, b);
-  core::num* c = (self::C::staticSetter = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* c = (self::C::staticSetter = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, c);
-  core::num* d = self::C::staticFoo(2).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* d = self::C::staticFoo(2).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(3, d);
-  core::num* e = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* e = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(5, e);
 }
 static method topLevelMembers() → dynamic async {
-  core::num* a = self::globalVariable.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* a = self::globalVariable.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, a);
-  core::num* b = self::topLevelGetter.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* b = self::topLevelGetter.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, b);
-  core::num* c = (self::topLevelSetter = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* c = (self::topLevelSetter = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, c);
-  core::num* d = self::topLevelFoo(1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* d = self::topLevelFoo(1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, d);
-  core::num* e = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* e = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(5, e);
 }
 static method instanceMembers() → dynamic async {
   self::C* inst = new self::C::•();
-  core::num* a = inst.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* a = inst.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, a);
-  core::num* b = inst.{self::C::getter}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* b = inst.{self::C::getter}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, b);
-  core::num* c = (inst.{self::C::setter} = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* c = (inst.{self::C::setter} = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, c);
-  core::num* d = inst.{self::C::foo}(1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* d = inst.{self::C::foo}(1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, d);
-  core::num* e = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* e = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(5, e);
 }
 static method others() → dynamic async {
   core::String* a = "${self::globalVariable} ${await self::dummy()} ".{core::String::+}(await "someString");
   self::expect("1 1 someString", a);
   self::C* c = new self::C::•();
-  core::num* d = c.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* d = c.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   core::int* cnt = 2;
   core::List<core::int*>* b = <core::int*>[1, 2, 3];
   b.{core::List::[]=}(cnt, await self::dummy() as{TypeError,ForDynamic} core::int*);
   self::expect(1, b.{core::List::[]}(cnt));
-  core::num* e = b.{core::List::[]}(0).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* e = b.{core::List::[]}(0).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, e);
 }
 static method conditionals() → dynamic async {
diff --git a/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect
index 8b69c50..51ef2df 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect
@@ -77,27 +77,27 @@
       {
         :async_temporary_0 = self::C::staticField;
         [yield] let dynamic #t1 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, a);
         :async_temporary_1 = self::C::staticField = 1;
         [yield] let dynamic #t2 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* f = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* f = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, f);
         :async_temporary_2 = self::C::staticGetter;
         [yield] let dynamic #t3 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, b);
         :async_temporary_3 = self::C::staticSetter = 1;
         [yield] let dynamic #t4 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, c);
         :async_temporary_4 = self::C::staticFoo(2);
         [yield] let dynamic #t5 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(3, d);
         :async_temporary_5 = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1));
         [yield] let dynamic #t6 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_5).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_5).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(5, e);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -132,23 +132,23 @@
       {
         :async_temporary_0 = self::globalVariable;
         [yield] let dynamic #t7 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, a);
         :async_temporary_1 = self::topLevelGetter;
         [yield] let dynamic #t8 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, b);
         :async_temporary_2 = self::topLevelSetter = 1;
         [yield] let dynamic #t9 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, c);
         :async_temporary_3 = self::topLevelFoo(1);
         [yield] let dynamic #t10 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, d);
         :async_temporary_4 = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1));
         [yield] let dynamic #t11 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(5, e);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -184,23 +184,23 @@
         self::C* inst = new self::C::•();
         :async_temporary_0 = inst.{self::C::field};
         [yield] let dynamic #t12 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, a);
         :async_temporary_1 = inst.{self::C::getter};
         [yield] let dynamic #t13 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, b);
         :async_temporary_2 = inst.{self::C::setter} = 1;
         [yield] let dynamic #t14 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, c);
         :async_temporary_3 = inst.{self::C::foo}(1);
         [yield] let dynamic #t15 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, d);
         :async_temporary_4 = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1));
         [yield] let dynamic #t16 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(5, e);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -242,9 +242,9 @@
         self::C* c = new self::C::•();
         :async_temporary_1 = c.{self::C::field};
         [yield] let dynamic #t19 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         core::int* cnt = 2;
-        core::List<core::int*>* b = <core::int*>[1, 2, 3];
+        core::List<core::int*>* b = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
         :async_temporary_3 = b;
         :async_temporary_2 = cnt;
         [yield] let dynamic #t20 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
@@ -252,7 +252,7 @@
         self::expect(1, b.{core::List::[]}(cnt));
         :async_temporary_4 = b.{core::List::[]}(0);
         [yield] let dynamic #t21 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, e);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -354,7 +354,7 @@
       #L6:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = core::_GrowableList::_literal2<core::Function*>(#C1, #C2).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t26 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -433,7 +433,7 @@
       #L7:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = core::_GrowableList::_literal2<core::Function*>(#C1, #C2).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t33 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -637,7 +637,7 @@
                 :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
                 return :controller_stream;
               }
-              :async_temporary_0 = <dynamic>[42];
+              :async_temporary_0 = core::_GrowableList::_literal1<dynamic>(42);
               [yield] let dynamic #t55 = asy::_awaitHelper(testStream1.call().{asy::Stream::toList}(), :async_op_then, :async_op_error, :async_op) in null;
               self::expectList(_in::unsafeCast<core::List<dynamic>*>(:async_temporary_0), _in::unsafeCast<core::List<core::int*>>(:result));
               function testStream2() → asy::Stream<core::int*>* /* originally async* */ {
@@ -674,7 +674,7 @@
                 :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
                 return :controller_stream;
               }
-              :async_temporary_1 = <dynamic>[42];
+              :async_temporary_1 = core::_GrowableList::_literal1<dynamic>(42);
               [yield] let dynamic #t57 = asy::_awaitHelper(testStream2.call().{asy::Stream::toList}(), :async_op_then, :async_op_error, :async_op) in null;
               self::expectList(_in::unsafeCast<core::List<dynamic>*>(:async_temporary_1), _in::unsafeCast<core::List<core::int*>>(:result));
             }
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect
index e178bdf..c96fec3e 100644
--- a/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
       try {
         #L1:
         {
-          final core::List<core::int*>* #t1 = <core::int*>[];
+          final core::List<core::int*>* #t1 = core::_GrowableList::•<core::int*>(0);
           [yield] let dynamic #t2 = asy::_awaitHelper(this.{self::C::_m}(), :async_op_then, :async_op_error, :async_op) in null;
           #t1.{core::List::add}(_in::unsafeCast<core::int*>(:result));
           :return_value = block {} =>#t1;
diff --git a/pkg/front_end/testcases/general/bug32414b.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug32414b.dart.strong.transformed.expect
index 1422239..6378088 100644
--- a/pkg/front_end/testcases/general/bug32414b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug32414b.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method test() → void {
-  core::List<dynamic>* l = <dynamic>[1, "hello"];
+  core::List<dynamic>* l = core::_GrowableList::_literal2<dynamic>(1, "hello");
   core::List<core::String*>* l2 = l.{core::Iterable::map}<core::String*>((dynamic element) → core::String* => element.{core::Object::toString}()).{core::Iterable::toList}();
 }
 static method main() → void {}
diff --git a/pkg/front_end/testcases/general/bug33099.dart.outline.expect b/pkg/front_end/testcases/general/bug33099.dart.outline.expect
index 22c739f..1b77963 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.outline.expect
@@ -41,6 +41,8 @@
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → void
+    return super.{self::MyTest::foo}();
   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
@@ -68,4 +70,4 @@
 Extra constant evaluation status:
 Evaluated: StaticGet @ org-dartlang-testcase:///bug33099.dart:14:4 -> InstanceConstant(const _FailingTest{})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///bug33099.dart:7:40 -> InstanceConstant(const _FailingTest{})
-Extra constant evaluation: evaluated: 2, effectively constant: 2
+Extra constant evaluation: evaluated: 3, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.expect
index 6e4306c..7fb694a 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.expect
@@ -41,6 +41,8 @@
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → void
+    return super.{self::MyTest::foo}();
   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
@@ -59,9 +61,9 @@
 }
 static const field self::_FailingTest* failingTest = #C1;
 static method main() → dynamic {
-  mir::ClassMirror* classMirror = mir::reflectClass(self::MyTest2*);
+  mir::ClassMirror* classMirror = mir::reflectClass(#C2);
   classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol* symbol, mir::MethodMirror* memberMirror) → Null {
-    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C2)) {
+    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C3)) {
       core::print(memberMirror);
       core::print(self::_hasFailingTestAnnotation(memberMirror));
     }
@@ -80,5 +82,12 @@
 
 constants  {
   #C1 = self::_FailingTest {}
-  #C2 = #foo
+  #C2 = TypeLiteralConstant(self::MyTest2*)
+  #C3 = #foo
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bug33099.dart:
+- _FailingTest. (from org-dartlang-testcase:///bug33099.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
index 1c01215..188bd50 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
@@ -41,6 +41,8 @@
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
+  @#C1
+  method foo() → void {}
   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
@@ -51,8 +53,6 @@
   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
-  @#C1
-  method foo() → void {}
 }
 class MyTest2 extends self::_MyTest2&Object&MyTest {
   synthetic constructor •() → self::MyTest2*
@@ -61,9 +61,9 @@
 }
 static const field self::_FailingTest* failingTest = #C1;
 static method main() → dynamic {
-  mir::ClassMirror* classMirror = mir::reflectClass(self::MyTest2*);
+  mir::ClassMirror* classMirror = mir::reflectClass(#C2);
   classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol* symbol, mir::MethodMirror* memberMirror) → Null {
-    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C2)) {
+    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C3)) {
       core::print(memberMirror);
       core::print(self::_hasFailingTestAnnotation(memberMirror));
     }
@@ -82,9 +82,12 @@
 
 constants  {
   #C1 = self::_FailingTest {}
-  #C2 = #foo
+  #C2 = TypeLiteralConstant(self::MyTest2*)
+  #C3 = #foo
 }
 
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///bug33099.dart:21:42 -> TypeLiteralConstant(MyTest2*)
-Extra constant evaluation: evaluated: 33, effectively constant: 1
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bug33099.dart:
+- _FailingTest. (from org-dartlang-testcase:///bug33099.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
index b800d2a..2ca85ca 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
@@ -52,7 +52,7 @@
     try {
       #L1:
       {
-        :return_value = <core::Object*>[1];
+        :return_value = core::_GrowableList::_literal1<core::Object*>(1);
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -68,7 +68,7 @@
   return :async_future;
 }
 static method f2() → core::List<core::Object*>*
-  return <core::Object*>[2];
+  return core::_GrowableList::_literal1<core::Object*>(2);
 static method f3() → asy::Future<core::Object*>* /* originally async */ {
   final asy::_Future<core::Object*>* :async_future = new asy::_Future::•<core::Object*>();
   core::bool* :is_sync = false;
diff --git a/pkg/front_end/testcases/general/bug33298.dart.strong.expect b/pkg/front_end/testcases/general/bug33298.dart.strong.expect
index aafe97f..dd1be41 100644
--- a/pkg/front_end/testcases/general/bug33298.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug33298.dart.strong.expect
@@ -71,6 +71,6 @@
   core::List<core::String*>* list5 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(c.{self::C::call}<core::String*>).{core::Iterable::toList}();
   core::List<core::String*>* list6 = <core::String*>["a", "b", "c"].{core::Iterable::map}<dynamic>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/bug33298.dart:28:44: Error: The argument type 'T Function<T>(T)' can't be assigned to the parameter type 'dynamic Function(String)'.
   List<String> list6 = ['a', 'b', 'c'].map(c).toList();
-                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) → dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
+                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/bug33298.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33298.dart.strong.transformed.expect
index aafe97f..4605193 100644
--- a/pkg/front_end/testcases/general/bug33298.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33298.dart.strong.transformed.expect
@@ -62,15 +62,15 @@
 }
 static method test() → dynamic {
   self::A* a = new self::A::•();
-  core::List<core::String*>* list1 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(a.{self::A::call}).{core::Iterable::toList}();
-  core::List<core::String*>* list2 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1.==(null) ?{(core::String*) →* core::String*} null : #t1.{self::A::call}).{core::Iterable::toList}();
+  core::List<core::String*>* list1 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(a.{self::A::call}).{core::Iterable::toList}();
+  core::List<core::String*>* list2 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1.==(null) ?{(core::String*) →* core::String*} null : #t1.{self::A::call}).{core::Iterable::toList}();
   self::B<core::String*>* b = new self::B::•<core::String*>();
-  core::List<core::String*>* list3 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(b.{self::B::call}).{core::Iterable::toList}();
-  core::List<core::String*>* list4 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2.==(null) ?{(core::String*) →* core::String*} null : #t2.{self::B::call}).{core::Iterable::toList}();
+  core::List<core::String*>* list3 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(b.{self::B::call}).{core::Iterable::toList}();
+  core::List<core::String*>* list4 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2.==(null) ?{(core::String*) →* core::String*} null : #t2.{self::B::call}).{core::Iterable::toList}();
   self::C* c = new self::C::•();
-  core::List<core::String*>* list5 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(c.{self::C::call}<core::String*>).{core::Iterable::toList}();
-  core::List<core::String*>* list6 = <core::String*>["a", "b", "c"].{core::Iterable::map}<dynamic>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/bug33298.dart:28:44: Error: The argument type 'T Function<T>(T)' can't be assigned to the parameter type 'dynamic Function(String)'.
+  core::List<core::String*>* list5 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(c.{self::C::call}<core::String*>).{core::Iterable::toList}();
+  core::List<core::String*>* list6 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<dynamic>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/bug33298.dart:28:44: Error: The argument type 'T Function<T>(T)' can't be assigned to the parameter type 'dynamic Function(String)'.
   List<String> list6 = ['a', 'b', 'c'].map(c).toList();
-                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) → dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
+                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/build_issue_2688.dart.outline.expect b/pkg/front_end/testcases/general/build_issue_2688.dart.outline.expect
index 43701f7..63c6cb2 100644
--- a/pkg/front_end/testcases/general/build_issue_2688.dart.outline.expect
+++ b/pkg/front_end/testcases/general/build_issue_2688.dart.outline.expect
@@ -385,141 +385,169 @@
   synthetic constructor •() → self::_Class&Super&M0*
     : super self::Super::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M0::property
 }
 abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1*
     : super self::_Class&Super&M0::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M1::property
 }
 abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2*
     : super self::_Class&Super&M0&M1::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M2::property
 }
 abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3*
     : super self::_Class&Super&M0&M1&M2::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M3::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4*
     : super self::_Class&Super&M0&M1&M2&M3::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M4::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5*
     : super self::_Class&Super&M0&M1&M2&M3&M4::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M5::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M6::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M7::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M8::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M9::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M10::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M11::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M12::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M13::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M14::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M15::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M16::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M17::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M18::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M19::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M20::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M21::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M22::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M23::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M24::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M25::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M26::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M27::property
 }
 class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
   synthetic constructor •() → self::Class*
diff --git a/pkg/front_end/testcases/general/build_issue_2688.dart.strong.expect b/pkg/front_end/testcases/general/build_issue_2688.dart.strong.expect
index eee4f5a..226f3df 100644
--- a/pkg/front_end/testcases/general/build_issue_2688.dart.strong.expect
+++ b/pkg/front_end/testcases/general/build_issue_2688.dart.strong.expect
@@ -386,141 +386,169 @@
   synthetic constructor •() → self::_Class&Super&M0*
     : super self::Super::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M0::property
 }
 abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1*
     : super self::_Class&Super&M0::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M1::property
 }
 abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2*
     : super self::_Class&Super&M0&M1::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M2::property
 }
 abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3*
     : super self::_Class&Super&M0&M1&M2::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M3::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4*
     : super self::_Class&Super&M0&M1&M2&M3::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M4::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5*
     : super self::_Class&Super&M0&M1&M2&M3&M4::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M5::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M6::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M7::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M8::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M9::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M10::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M11::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M12::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M13::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M14::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M15::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M16::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M17::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M18::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M19::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M20::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M21::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M22::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M23::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M24::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M25::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M26::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27*
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
     ;
+  abstract mixin-stub get property() → core::int*; -> self::M27::property
 }
 class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
   synthetic constructor •() → self::Class*
diff --git a/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect
index b2f0be3..d342580 100644
--- a/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect
@@ -26,10 +26,10 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  core::List<core::int*>* list = let final core::List<core::int*>* #t1 = <core::int*>[1] in block {
+  core::List<core::int*>* list = let final core::List<core::int*>* #t1 = core::_GrowableList::_literal1<core::int*>(1) in block {
     #t1.{core::List::add}(2);
     #t1.{core::List::add}(3);
-    #t1.{core::List::addAll}(<core::int*>[4, 5]);
+    #t1.{core::List::addAll}(core::_GrowableList::_literal2<core::int*>(4, 5));
   } =>#t1;
   core::print(list);
   let final core::List<core::int*>* #t2 = list in block {
@@ -44,10 +44,10 @@
     #t3.{core::List::[]=}(0, 87);
   } =>#t3;
   core::print(list);
-  list = let final core::List<core::int*>* #t4 = <core::int*>[let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:26:5: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+  list = let final core::List<core::int*>* #t4 = core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:26:5: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
  - 'List' is from 'dart:core'.
     [1]
-    ^" in <core::int*>[1] as{TypeError} core::int*] in block {
+    ^" in core::_GrowableList::_literal1<core::int*>(1) as{TypeError} core::int*) in block {
     invalid-expression "pkg/front_end/testcases/general/cascade.dart:28:13: Error: The getter 'last' isn't defined for the class 'int'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
     ..first.last.toString()
diff --git a/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.expect b/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.expect
index b3ae2c0..efb9d56 100644
--- a/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.expect
@@ -1,22 +1,21 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "deferred_lib.dart" as def;
 
 import "org-dartlang-testcase:///deferred_lib.dart" deferred as lib;
 
 static method main() → dynamic {}
 static method test() → dynamic {
-  core::print(let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::C*);
+  core::print(let final dynamic #t1 = CheckLibraryIsLoaded(lib) in #C1);
 }
 
 library;
-import self as def;
+import self as self2;
 import "dart:core" as core;
 
 class C extends core::Object {
   static field core::int* y = 1;
-  synthetic constructor •() → def::C*
+  synthetic constructor •() → self2::C*
     : super core::Object::•()
     ;
   static method m() → core::int*
@@ -35,3 +34,7 @@
 static field core::int* x = 0;
 static method m(dynamic x) → dynamic
   return null;
+
+constants  {
+  #C1 = TypeLiteralConstant(self2::C*)
+}
diff --git a/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.transformed.expect
index fdd58da..2813c9c5 100644
--- a/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.transformed.expect
@@ -1,22 +1,21 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "deferred_lib.dart" as def;
 
 import "org-dartlang-testcase:///deferred_lib.dart" deferred as lib;
 
 static method main() → dynamic {}
 static method test() → dynamic {
-  core::print(let final core::Object* #t1 = CheckLibraryIsLoaded(lib) in def::C*);
+  core::print(let final core::Object* #t1 = CheckLibraryIsLoaded(lib) in #C1);
 }
 
 library;
-import self as def;
+import self as self2;
 import "dart:core" as core;
 
 class C extends core::Object {
   static field core::int* y = 1;
-  synthetic constructor •() → def::C*
+  synthetic constructor •() → self2::C*
     : super core::Object::•()
     ;
   static method m() → core::int*
@@ -36,7 +35,6 @@
 static method m(dynamic x) → dynamic
   return null;
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///check_deferred_read_type.dart:9:13 -> TypeLiteralConstant(C*)
-Extra constant evaluation: evaluated: 4, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(self2::C*)
+}
diff --git a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.expect b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.expect
index 41cf43f..94978d1 100644
--- a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.expect
+++ b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.expect
@@ -43,3 +43,11 @@
   core::print(new self::A::•());
   core::print(new self::B::•());
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_redirect_to_nonconst.dart:
+- A. (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:6:9)
+- A.bad (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:8:3)
+- B. (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:12:9)
diff --git a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.transformed.expect b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.transformed.expect
index 41cf43f..94978d1 100644
--- a/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/const_redirect_to_nonconst.dart.strong.transformed.expect
@@ -43,3 +43,11 @@
   core::print(new self::A::•());
   core::print(new self::B::•());
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_redirect_to_nonconst.dart:
+- A. (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:6:9)
+- A.bad (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:8:3)
+- B. (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:12:9)
diff --git a/pkg/front_end/testcases/general/constants/circularity.dart.strong.expect b/pkg/front_end/testcases/general/constants/circularity.dart.strong.expect
index ad07bf9..adecbb6 100644
--- a/pkg/front_end/testcases/general/constants/circularity.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/circularity.dart.strong.expect
@@ -132,3 +132,12 @@
   #C5 = self::Class2 {field:#C3}
   #C6 = self::Class4 {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///circularity.dart:
+- Class1. (from org-dartlang-testcase:///circularity.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class2. (from org-dartlang-testcase:///circularity.dart:21:9)
+- Class3. (from org-dartlang-testcase:///circularity.dart:29:9)
+- Class4. (from org-dartlang-testcase:///circularity.dart:37:9)
diff --git a/pkg/front_end/testcases/general/constants/circularity.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/circularity.dart.strong.transformed.expect
index ad07bf9..adecbb6 100644
--- a/pkg/front_end/testcases/general/constants/circularity.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/circularity.dart.strong.transformed.expect
@@ -132,3 +132,12 @@
   #C5 = self::Class2 {field:#C3}
   #C6 = self::Class4 {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///circularity.dart:
+- Class1. (from org-dartlang-testcase:///circularity.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class2. (from org-dartlang-testcase:///circularity.dart:21:9)
+- Class3. (from org-dartlang-testcase:///circularity.dart:29:9)
+- Class4. (from org-dartlang-testcase:///circularity.dart:37:9)
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.expect
index 2f17318..fdc09aa 100644
--- a/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.expect
@@ -204,3 +204,17 @@
   #C3 = 1
   #C4 = self::Foo {x:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_asserts.dart:
+- Foo. (from org-dartlang-testcase:///const_asserts.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Foo.withMessage (from org-dartlang-testcase:///const_asserts.dart:14:9)
+- Foo.withInvalidMessage (from org-dartlang-testcase:///const_asserts.dart:16:9)
+- Foo.withInvalidCondition (from org-dartlang-testcase:///const_asserts.dart:17:9)
+- Foo.withNullConditionFromEnv1 (from org-dartlang-testcase:///const_asserts.dart:18:9)
+- Foo.withNullConditionFromEnv2 (from org-dartlang-testcase:///const_asserts.dart:20:9)
+- Bar.withMessage (from org-dartlang-testcase:///const_asserts.dart:26:9)
+- Bar.withoutMessage (from org-dartlang-testcase:///const_asserts.dart:27:9)
+- Bar.withEmptyMessage (from org-dartlang-testcase:///const_asserts.dart:28:9)
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.transformed.expect
index 5302b40..dd0f5c5 100644
--- a/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.transformed.expect
@@ -211,3 +211,17 @@
 Evaluated: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:13:50 -> BoolConstant(true)
 Evaluated: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:15:73 -> StringConstant("btw foo was false")
 Extra constant evaluation: evaluated: 34, effectively constant: 4
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_asserts.dart:
+- Foo. (from org-dartlang-testcase:///const_asserts.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Foo.withMessage (from org-dartlang-testcase:///const_asserts.dart:14:9)
+- Foo.withInvalidMessage (from org-dartlang-testcase:///const_asserts.dart:16:9)
+- Foo.withInvalidCondition (from org-dartlang-testcase:///const_asserts.dart:17:9)
+- Foo.withNullConditionFromEnv1 (from org-dartlang-testcase:///const_asserts.dart:18:9)
+- Foo.withNullConditionFromEnv2 (from org-dartlang-testcase:///const_asserts.dart:20:9)
+- Bar.withMessage (from org-dartlang-testcase:///const_asserts.dart:26:9)
+- Bar.withoutMessage (from org-dartlang-testcase:///const_asserts.dart:27:9)
+- Bar.withEmptyMessage (from org-dartlang-testcase:///const_asserts.dart:28:9)
diff --git a/pkg/front_end/testcases/general/constants/const_collections.dart.strong.expect b/pkg/front_end/testcases/general/constants/const_collections.dart.strong.expect
index 43efaee..58d0c68 100644
--- a/pkg/front_end/testcases/general/constants/const_collections.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/const_collections.dart.strong.expect
@@ -513,3 +513,12 @@
   #C25 = core::_ImmutableMap<core::String*, Null> {_kvPairs:#C24}
   #C26 = col::_UnmodifiableSet<core::String*> {_map:#C25}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_collections.dart:
+- CustomIterable. (from org-dartlang-testcase:///const_collections.dart:79:9)
+- IterableBase. (from org-dartlang-sdk:///sdk/lib/collection/iterable.dart:218:9)
+- WithEquals. (from org-dartlang-testcase:///const_collections.dart:72:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- CustomMap. (from org-dartlang-testcase:///const_collections.dart:84:9)
diff --git a/pkg/front_end/testcases/general/constants/const_collections.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/const_collections.dart.strong.transformed.expect
index 9b88a94..f26aca0 100644
--- a/pkg/front_end/testcases/general/constants/const_collections.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/const_collections.dart.strong.transformed.expect
@@ -224,7 +224,7 @@
     : super col::IterableBase::•()
     ;
   get iterator() → core::Iterator<core::int*>*
-    return <core::int*>[].{core::Iterable::iterator};
+    return core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
   abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::ConstIterable::cast::R*>*; -> core::Iterable::cast
   abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::int*>* other) → core::Iterable<core::int*>*; -> core::Iterable::followedBy
   abstract member-signature method map<T extends core::Object* = dynamic>((core::int*) →* self::ConstIterable::map::T* f) → core::Iterable<self::ConstIterable::map::T*>*; -> core::Iterable::map
@@ -285,7 +285,7 @@
     : super col::IterableBase::•()
     ;
   get iterator() → core::Iterator<core::String*>*
-    return <core::String*>[].{core::Iterable::iterator};
+    return core::_GrowableList::•<core::String*>(0).{core::Iterable::iterator};
   abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::CustomIterable::cast::R*>*; -> core::Iterable::cast
   abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::String*>* other) → core::Iterable<core::String*>*; -> core::Iterable::followedBy
   abstract member-signature method map<T extends core::Object* = dynamic>((core::String*) →* self::CustomIterable::map::T* f) → core::Iterable<self::CustomIterable::map::T*>*; -> core::Iterable::map
@@ -329,7 +329,7 @@
     ;
   @#C4
   get entries() → core::Iterable<core::MapEntry<core::String*, core::String*>*>*
-    return <core::MapEntry<core::String*, core::String*>*>[];
+    return core::_GrowableList::•<core::MapEntry<core::String*, core::String*>*>(0);
   @#C4
   operator [](core::Object* key) → core::String*
     return throw new core::UnimplementedError::•();
@@ -513,3 +513,12 @@
   #C25 = core::_ImmutableMap<core::String*, Null> {_kvPairs:#C24}
   #C26 = col::_UnmodifiableSet<core::String*> {_map:#C25}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_collections.dart:
+- CustomIterable. (from org-dartlang-testcase:///const_collections.dart:79:9)
+- IterableBase. (from org-dartlang-sdk:///sdk/lib/collection/iterable.dart:218:9)
+- WithEquals. (from org-dartlang-testcase:///const_collections.dart:72:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- CustomMap. (from org-dartlang-testcase:///const_collections.dart:84:9)
diff --git a/pkg/front_end/testcases/general/constants/const_constructor_coverage.dart.strong.expect b/pkg/front_end/testcases/general/constants/const_constructor_coverage.dart.strong.expect
index 19a070b..6ea8c4e 100644
--- a/pkg/front_end/testcases/general/constants/const_constructor_coverage.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/const_constructor_coverage.dart.strong.expect
@@ -127,3 +127,28 @@
   #C3 = con::Bar {baz:#C2}
   #C4 = con::Foo {bar:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_constructor_coverage.dart:
+- Foo. (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:9:15)
+- Foo.named1 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:10:15)
+- Foo.named2 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:11:15)
+- Foo.named3 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:12:15)
+
+org-dartlang-testcase:///const_constructor_coverage_lib1.dart:
+- Bar. (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:17:15)
+- Baz. (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:9:15)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Bar.named1 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:18:15)
+- Baz.named1 (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:10:15)
+- Baz.named5 (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:14:15)
+- Baz.named6 (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:15:15)
+- Foo.named3 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:12:15)
+
+org-dartlang-testcase:///const_constructor_coverage_lib2.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Bar.named3 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:20:15)
+- Baz.named4 (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:13:15)
+- Foo.named2 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:11:15)
+- Bar.named2 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:19:15)
diff --git a/pkg/front_end/testcases/general/constants/const_constructor_coverage.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/const_constructor_coverage.dart.strong.transformed.expect
index 19a070b..6ea8c4e 100644
--- a/pkg/front_end/testcases/general/constants/const_constructor_coverage.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/const_constructor_coverage.dart.strong.transformed.expect
@@ -127,3 +127,28 @@
   #C3 = con::Bar {baz:#C2}
   #C4 = con::Foo {bar:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_constructor_coverage.dart:
+- Foo. (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:9:15)
+- Foo.named1 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:10:15)
+- Foo.named2 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:11:15)
+- Foo.named3 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:12:15)
+
+org-dartlang-testcase:///const_constructor_coverage_lib1.dart:
+- Bar. (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:17:15)
+- Baz. (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:9:15)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Bar.named1 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:18:15)
+- Baz.named1 (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:10:15)
+- Baz.named5 (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:14:15)
+- Baz.named6 (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:15:15)
+- Foo.named3 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:12:15)
+
+org-dartlang-testcase:///const_constructor_coverage_lib2.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Bar.named3 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:20:15)
+- Baz.named4 (from org-dartlang-testcase:///const_constructor_coverage_lib2.dart:13:15)
+- Foo.named2 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:11:15)
+- Bar.named2 (from org-dartlang-testcase:///const_constructor_coverage_lib1.dart:19:15)
diff --git a/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.expect b/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.expect
index 1c887af..b8bb029 100644
--- a/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.expect
@@ -50,3 +50,8 @@
 constants  {
   #C1 = true
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_43431.dart:
+- Foo. (from org-dartlang-testcase:///issue_43431.dart:6:9)
diff --git a/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.transformed.expect
index 1c887af..b8bb029 100644
--- a/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.transformed.expect
@@ -50,3 +50,8 @@
 constants  {
   #C1 = true
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_43431.dart:
+- Foo. (from org-dartlang-testcase:///issue_43431.dart:6:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.outline.expect
index 2f0bfb0..870f990 100644
--- a/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.outline.expect
@@ -29,32 +29,32 @@
 import self as self;
 import "dart:core" as core;
 
-static const field core::int* shiftNegative1 = 2.{core::int::<<}(1.{core::int::unary-}());
+static const field core::int* shiftNegative1 = 2.{core::int::<<}(1.{core::int::unary-}(){() →* core::int*}){(core::int*) →* core::int*};
 static const field core::int* shiftNegative2 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
 Try correcting the operator to an existing operator, or defining a '>>>' operator.
 const int shiftNegative2 = 2 >>> -1;
                              ^^^" as{TypeError,ForDynamic} core::int*;
-static const field core::int* shiftNegative3 = 2.{core::int::>>}(1.{core::int::unary-}());
-static const field core::int* modZero = 2.{core::num::%}(0);
+static const field core::int* shiftNegative3 = 2.{core::int::>>}(1.{core::int::unary-}(){() →* core::int*}){(core::int*) →* core::int*};
+static const field core::int* modZero = 2.{core::num::%}(0){(core::num*) →* core::int*};
 static const field core::int* divZero = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
 const int divZero = 2 / 0;
-                      ^" in 2.{core::num::/}(0) as{TypeError} core::int*;
-static const field core::int* intdivZero = 2.{core::num::~/}(0);
-static const field core::int* unaryMinus = 2.{core::int::unary-}();
-static const field core::int* unaryTilde = 2.{core::int::~}();
+                      ^" in 2.{core::num::/}(0){(core::num*) →* core::double*} as{TypeError} core::int*;
+static const field core::int* intdivZero = 2.{core::num::~/}(0){(core::num*) →* core::int*};
+static const field core::int* unaryMinus = 2.{core::int::unary-}(){() →* core::int*};
+static const field core::int* unaryTilde = 2.{core::int::~}(){() →* core::int*};
 static const field core::int* unaryPlus = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:13:23: Error: This couldn't be parsed.
 const int unaryPlus = +2;
-                      ^".+(2) as{TypeError,ForDynamic} core::int*;
-static const field core::int* binaryPlus = 40.{core::num::+}(2);
-static const field core::int* binaryMinus = 44.{core::num::-}(2);
-static const field core::int* binaryTimes = 21.{core::num::*}(2);
-static const field core::double* binaryDiv = 84.{core::num::/}(2);
-static const field core::int* binaryTildeDiv = 84.{core::num::~/}(2);
-static const field core::int* binaryMod = 85.{core::num::%}(43);
-static const field core::int* binaryOr = 32.{core::int::|}(10);
-static const field core::int* binaryAnd = 63.{core::int::&}(106);
-static const field core::int* binaryXor = 63.{core::int::^}(21);
-static const field core::int* binaryShift1 = 21.{core::int::<<}(1);
+                      ^"{dynamic}.+(2) as{TypeError,ForDynamic} core::int*;
+static const field core::int* binaryPlus = 40.{core::num::+}(2){(core::num*) →* core::int*};
+static const field core::int* binaryMinus = 44.{core::num::-}(2){(core::num*) →* core::int*};
+static const field core::int* binaryTimes = 21.{core::num::*}(2){(core::num*) →* core::int*};
+static const field core::double* binaryDiv = 84.{core::num::/}(2){(core::num*) →* core::double*};
+static const field core::int* binaryTildeDiv = 84.{core::num::~/}(2){(core::num*) →* core::int*};
+static const field core::int* binaryMod = 85.{core::num::%}(43){(core::num*) →* core::int*};
+static const field core::int* binaryOr = 32.{core::int::|}(10){(core::int*) →* core::int*};
+static const field core::int* binaryAnd = 63.{core::int::&}(106){(core::int*) →* core::int*};
+static const field core::int* binaryXor = 63.{core::int::^}(21){(core::int*) →* core::int*};
+static const field core::int* binaryShift1 = 21.{core::int::<<}(1){(core::int*) →* core::int*};
 static const field core::int* binaryShift2 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
 Try correcting the operator to an existing operator, or defining a '>>>' operator.
 const int binaryShift2 = 84 >>> 1;
@@ -63,45 +63,45 @@
 Try correcting the operator to an existing operator, or defining a '>>>' operator.
 const int binaryShift3 = 21 >>> 64;
                             ^^^" as{TypeError,ForDynamic} core::int*;
-static const field core::int* binaryShift4 = 84.{core::int::>>}(1);
-static const field core::int* binaryShift5 = 1.{core::int::unary-}().{core::int::>>}(1);
-static const field core::bool* binaryLess = 42.{core::num::<}(42);
-static const field core::bool* binaryLessEqual = 42.{core::num::<=}(42);
-static const field core::bool* binaryGreaterEqual = 42.{core::num::>=}(42);
-static const field core::bool* binaryGreater = 42.{core::num::>}(42);
-static const field core::int* doubleTruncateDiv = 84.2.{core::double::~/}(2);
-static const field core::int* doubleTruncateDivZero = 84.2.{core::double::~/}(0);
-static const field core::int* doubleTruncateDivNull = 84.2.{core::double::~/}(null);
-static const field core::double* doubleNan = 0.{core::num::/}(0);
-static const field core::int* doubleTruncateDivNaN = 84.2.{core::double::~/}(self::doubleNan);
+static const field core::int* binaryShift4 = 84.{core::int::>>}(1){(core::int*) →* core::int*};
+static const field core::int* binaryShift5 = 1.{core::int::unary-}(){() →* core::int*}.{core::int::>>}(1){(core::int*) →* core::int*};
+static const field core::bool* binaryLess = 42.{core::num::<}(42){(core::num*) →* core::bool*};
+static const field core::bool* binaryLessEqual = 42.{core::num::<=}(42){(core::num*) →* core::bool*};
+static const field core::bool* binaryGreaterEqual = 42.{core::num::>=}(42){(core::num*) →* core::bool*};
+static const field core::bool* binaryGreater = 42.{core::num::>}(42){(core::num*) →* core::bool*};
+static const field core::int* doubleTruncateDiv = 84.2.{core::double::~/}(2){(core::num*) →* core::int*};
+static const field core::int* doubleTruncateDivZero = 84.2.{core::double::~/}(0){(core::num*) →* core::int*};
+static const field core::int* doubleTruncateDivNull = 84.2.{core::double::~/}(null){(core::num*) →* core::int*};
+static const field core::double* doubleNan = 0.{core::num::/}(0){(core::num*) →* core::double*};
+static const field core::int* doubleTruncateDivNaN = 84.2.{core::double::~/}(self::doubleNan){(core::num*) →* core::int*};
 static const field core::int* bigNumber = -9223372036854775808;
 static method main() → dynamic
   ;
 
 
 Extra constant evaluation status:
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:5:33 -> DoubleConstant(-1.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:7:33 -> DoubleConstant(-1.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:9:23 -> DoubleConstant(Infinity)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:11:24 -> DoubleConstant(-2.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:12:24 -> DoubleConstant(4294967293.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:15:27 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:16:28 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:17:28 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:18:29 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:19:30 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:20:26 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:21:25 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:22:26 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:23:26 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:24:29 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:30:29 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:31:29 -> DoubleConstant(4294967295.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:32:28 -> BoolConstant(false)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:33:33 -> BoolConstant(true)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:34:36 -> BoolConstant(true)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:35:31 -> BoolConstant(false)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:37:36 -> DoubleConstant(42.0)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:40:27 -> DoubleConstant(NaN)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:5:33 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:7:33 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:9:23 -> DoubleConstant(Infinity)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:11:24 -> DoubleConstant(-2.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:12:24 -> DoubleConstant(4294967293.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:15:27 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:16:28 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:17:28 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:18:29 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:19:30 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:20:26 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:21:25 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:22:26 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:23:26 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:24:29 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:30:29 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:31:29 -> DoubleConstant(4294967295.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:32:28 -> BoolConstant(false)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:33:33 -> BoolConstant(true)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:34:36 -> BoolConstant(true)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:35:31 -> BoolConstant(false)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:37:36 -> DoubleConstant(42.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///number_folds.dart:40:27 -> DoubleConstant(NaN)
 Evaluated: StaticGet @ org-dartlang-testcase:///number_folds.dart:41:42 -> DoubleConstant(NaN)
 Extra constant evaluation: evaluated: 38, effectively constant: 24
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/various.dart.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.outline.expect
index 41ed046..f015e56 100644
--- a/pkg/front_end/testcases/general/constants/js_semantics/various.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.outline.expect
@@ -25,17 +25,17 @@
 static const field core::bool* zeroPointZeroIdentical = core::identical(0.0, 0.0);
 static const field core::bool* zeroPointZeroIdenticalToZero = core::identical(0.0, 0);
 static const field core::bool* zeroIdenticalToZeroPointZero = core::identical(0, 0.0);
-static const field core::bool* nanIdentical = core::identical(0.{core::num::/}(0), 0.{core::num::/}(0));
+static const field core::bool* nanIdentical = core::identical(0.{core::num::/}(0){(core::num*) →* core::double*}, 0.{core::num::/}(0){(core::num*) →* core::double*});
 static const field core::bool* stringIdentical = core::identical("hello", "hello");
 static const field core::bool* string2Identical = core::identical("hello", "world");
-static const field core::bool* zeroPointZeroEqual = 0.0.{core::num::==}(0.0);
-static const field core::bool* zeroPointZeroEqualToZero = 0.0.{core::num::==}(0);
-static const field core::bool* zeroEqualToZeroPointZero = 0.{core::num::==}(0.0);
-static const field core::bool* nanEqual = 0.{core::num::/}(0).{core::num::==}(0.{core::num::/}(0));
-static const field core::bool* stringEqual = "hello".{core::String::==}("hello");
-static const field core::bool* string2Equal = "hello".{core::String::==}("world");
+static const field core::bool* zeroPointZeroEqual = 0.0 =={core::num::==}{(core::Object*) →* core::bool*} 0.0;
+static const field core::bool* zeroPointZeroEqualToZero = 0.0 =={core::num::==}{(core::Object*) →* core::bool*} 0;
+static const field core::bool* zeroEqualToZeroPointZero = 0 =={core::num::==}{(core::Object*) →* core::bool*} 0.0;
+static const field core::bool* nanEqual = 0.{core::num::/}(0){(core::num*) →* core::double*} =={core::num::==}{(core::Object*) →* core::bool*} 0.{core::num::/}(0){(core::num*) →* core::double*};
+static const field core::bool* stringEqual = "hello" =={core::String::==}{(core::Object*) →* core::bool*} "hello";
+static const field core::bool* string2Equal = "hello" =={core::String::==}{(core::Object*) →* core::bool*} "world";
 static const field core::int* intFortyTwo = 42;
-static const field core::String* intStringConcat = "hello${self::intFortyTwo.{core::num::*}(self::intFortyTwo)}";
+static const field core::String* intStringConcat = "hello${self::intFortyTwo.{core::num::*}(self::intFortyTwo){(core::num*) →* core::int*}}";
 
 
 Extra constant evaluation status:
@@ -61,11 +61,11 @@
 Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:35:22 -> BoolConstant(false)
 Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:36:25 -> BoolConstant(true)
 Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:37:26 -> BoolConstant(false)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:39:32 -> BoolConstant(true)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:40:38 -> BoolConstant(true)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:41:36 -> BoolConstant(true)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:42:24 -> BoolConstant(false)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:43:29 -> BoolConstant(true)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:44:30 -> BoolConstant(false)
+Evaluated: EqualsCall @ org-dartlang-testcase:///various.dart:39:32 -> BoolConstant(true)
+Evaluated: EqualsCall @ org-dartlang-testcase:///various.dart:40:38 -> BoolConstant(true)
+Evaluated: EqualsCall @ org-dartlang-testcase:///various.dart:41:36 -> BoolConstant(true)
+Evaluated: EqualsCall @ org-dartlang-testcase:///various.dart:42:24 -> BoolConstant(false)
+Evaluated: EqualsCall @ org-dartlang-testcase:///various.dart:43:29 -> BoolConstant(true)
+Evaluated: EqualsCall @ org-dartlang-testcase:///various.dart:44:30 -> BoolConstant(false)
 Evaluated: StringConcatenation @ org-dartlang-testcase:///various.dart:47:30 -> StringConstant("hello1764")
 Extra constant evaluation: evaluated: 29, effectively constant: 29
diff --git a/pkg/front_end/testcases/general/constants/various.dart.strong.expect b/pkg/front_end/testcases/general/constants/various.dart.strong.expect
index e7197ff..6d3d9c5 100644
--- a/pkg/front_end/testcases/general/constants/various.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/various.dart.strong.expect
@@ -624,3 +624,13 @@
   #C21 = tearoff self::id1
   #C22 = partial-instantiation self::id1 <core::int*>
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///various.dart:
+- ExtendsFoo2. (from org-dartlang-testcase:///various.dart:121:9)
+- Foo. (from org-dartlang-testcase:///various.dart:109:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ConstClassWithFailingAssertWithEmptyMessage. (from org-dartlang-testcase:///various.dart:144:9)
+- ClassWithTypeArguments. (from org-dartlang-testcase:///various.dart:151:9)
+- ConstClassWithFinalFields2. (from org-dartlang-testcase:///various.dart:177:9)
diff --git a/pkg/front_end/testcases/general/constants/various.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/various.dart.strong.transformed.expect
index 077f295..9b064ee 100644
--- a/pkg/front_end/testcases/general/constants/various.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/various.dart.strong.transformed.expect
@@ -628,3 +628,13 @@
 Extra constant evaluation status:
 Evaluated: PropertyGet @ org-dartlang-testcase:///various.dart:111:26 -> IntConstant(5)
 Extra constant evaluation: evaluated: 12, effectively constant: 1
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///various.dart:
+- ExtendsFoo2. (from org-dartlang-testcase:///various.dart:121:9)
+- Foo. (from org-dartlang-testcase:///various.dart:109:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ConstClassWithFailingAssertWithEmptyMessage. (from org-dartlang-testcase:///various.dart:144:9)
+- ClassWithTypeArguments. (from org-dartlang-testcase:///various.dart:151:9)
+- ConstClassWithFinalFields2. (from org-dartlang-testcase:///various.dart:177:9)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.outline.expect
index 9745070..0d9ff2d 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.outline.expect
@@ -12,13 +12,13 @@
 class Foo extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
   const constructor •(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert(const core::bool::fromEnvironment("foo").{core::Object::==}(false), "foo was ${const core::bool::fromEnvironment("foo")}"), assert(const core::bool::fromEnvironment("foo").{core::Object::==}(false)), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::>}(0){(core::num) → core::bool}, "x is not positive"), assert(x.{core::num::>}(0){(core::num) → core::bool}), assert(const core::bool::fromEnvironment("foo") =={core::Object::==}{(core::Object) → core::bool} false, "foo was ${const core::bool::fromEnvironment("foo")}"), assert(const core::bool::fromEnvironment("foo") =={core::Object::==}{(core::Object) → core::bool} false), super core::Object::•()
     ;
   const constructor withMessage(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${const core::bool::fromEnvironment("foo")}"), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, "btw foo was ${const core::bool::fromEnvironment("foo")}"), super core::Object::•()
     ;
   const constructor withInvalidMessage(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, x), super core::Object::•()
     ;
   const constructor withInvalidCondition(core::int x) → self::Foo
     : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
@@ -29,10 +29,10 @@
 class Bar extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
   const constructor withMessage(core::int x) → self::Bar
-    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    : self::Bar::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, "x is not negative"), super core::Object::•()
     ;
   const constructor withoutMessage(core::int x) → self::Bar
-    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    : self::Bar::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}), super core::Object::•()
     ;
 }
 static const field self::Foo foo1 = const self::Foo::•(1);
@@ -49,11 +49,11 @@
 
 
 Extra constant evaluation status:
-Evaluated with empty environment: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:10:50 -> BoolConstant(true)
+Evaluated with empty environment: EqualsCall @ org-dartlang-testcase:///const_asserts.dart:10:50 -> BoolConstant(true)
 Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:10:22 -> BoolConstant(false)
 Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:11:59 -> StringConstant("foo was false")
 Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:11:30 -> BoolConstant(false)
-Evaluated with empty environment: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:12:50 -> BoolConstant(true)
+Evaluated with empty environment: EqualsCall @ org-dartlang-testcase:///const_asserts.dart:12:50 -> BoolConstant(true)
 Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:12:22 -> BoolConstant(false)
 Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:14:73 -> StringConstant("btw foo was false")
 Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:14:44 -> BoolConstant(false)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.expect
index f4a03a1..c8fbdb9 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.expect
@@ -72,13 +72,13 @@
 class Foo extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
   const constructor •(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert((#C2).{core::Object::==}(false), "foo was ${#C3}"), assert((#C4).{core::Object::==}(false)), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::>}(0){(core::num) → core::bool}, "x is not positive"), assert(x.{core::num::>}(0){(core::num) → core::bool}), assert((#C2) =={core::Object::==}{(core::Object) → core::bool} false, "foo was ${#C3}"), assert((#C4) =={core::Object::==}{(core::Object) → core::bool} false), super core::Object::•()
     ;
   const constructor withMessage(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${#C5}"), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, "btw foo was ${#C5}"), super core::Object::•()
     ;
   const constructor withInvalidMessage(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, x), super core::Object::•()
     ;
   const constructor withInvalidCondition(core::int x) → self::Foo
     : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
@@ -89,10 +89,10 @@
 class Bar extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
   const constructor withMessage(core::int x) → self::Bar
-    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    : self::Bar::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, "x is not negative"), super core::Object::•()
     ;
   const constructor withoutMessage(core::int x) → self::Bar
-    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    : self::Bar::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}), super core::Object::•()
     ;
 }
 static const field self::Foo foo1 = #C9;
@@ -119,8 +119,19 @@
   #C6 = 1
   #C7 = false
   #C8 = "foo was "
-  #C9 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1).==(#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1).==(#C7))}
+  #C9 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1) =={core::Object::==}{(core::Object) → core::bool} (#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1) =={core::Object::==}{(core::Object) → core::bool} (#C7))}
   #C10 = 42
   #C11 = "btw foo was "
   #C12 = eval self::Foo{x:#C10, assert(#C7, "${#C11}${const core::bool::fromEnvironment(#C1)}")}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_asserts.dart:
+- Foo. (from org-dartlang-testcase:///const_asserts.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Foo.withMessage (from org-dartlang-testcase:///const_asserts.dart:13:9)
+- Foo.withInvalidMessage (from org-dartlang-testcase:///const_asserts.dart:15:9)
+- Foo.withInvalidCondition (from org-dartlang-testcase:///const_asserts.dart:16:9)
+- Bar.withMessage (from org-dartlang-testcase:///const_asserts.dart:21:9)
+- Bar.withoutMessage (from org-dartlang-testcase:///const_asserts.dart:22:9)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.transformed.expect
index 84a0f93..0224dd0 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.transformed.expect
@@ -72,13 +72,13 @@
 class Foo extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
   const constructor •(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert((#C2).{core::Object::==}(false), "foo was ${#C3}"), assert((#C4).{core::Object::==}(false)), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::>}(0){(core::num) → core::bool}, "x is not positive"), assert(x.{core::num::>}(0){(core::num) → core::bool}), assert((#C2) =={core::Object::==}{(core::Object) → core::bool} false, "foo was ${#C3}"), assert((#C4) =={core::Object::==}{(core::Object) → core::bool} false), super core::Object::•()
     ;
   const constructor withMessage(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${#C5}"), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, "btw foo was ${#C5}"), super core::Object::•()
     ;
   const constructor withInvalidMessage(core::int x) → self::Foo
-    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    : self::Foo::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, x), super core::Object::•()
     ;
   const constructor withInvalidCondition(core::int x) → self::Foo
     : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
@@ -89,10 +89,10 @@
 class Bar extends core::Object /*hasConstConstructor*/  {
   final field core::int x;
   const constructor withMessage(core::int x) → self::Bar
-    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    : self::Bar::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}, "x is not negative"), super core::Object::•()
     ;
   const constructor withoutMessage(core::int x) → self::Bar
-    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    : self::Bar::x = x, assert(x.{core::num::<}(0){(core::num) → core::bool}), super core::Object::•()
     ;
 }
 static const field self::Foo foo1 = #C9;
@@ -119,22 +119,33 @@
   #C6 = 1
   #C7 = false
   #C8 = "foo was "
-  #C9 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1).==(#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1).==(#C7))}
+  #C9 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1) =={core::Object::==}{(core::Object) → core::bool} (#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1) =={core::Object::==}{(core::Object) → core::bool} (#C7))}
   #C10 = 42
   #C11 = "btw foo was "
   #C12 = eval self::Foo{x:#C10, assert(#C7, "${#C11}${const core::bool::fromEnvironment(#C1)}")}
-  #C13 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1).==(#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1).==(#C7))}
+  #C13 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1) =={core::Object::==}{(core::Object) → core::bool} (#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1) =={core::Object::==}{(core::Object) → core::bool} (#C7))}
 }
 
 Extra constant evaluation status:
-Evaluated with empty environment: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:10:50 -> BoolConstant(true)
+Evaluated with empty environment: EqualsCall @ org-dartlang-testcase:///const_asserts.dart:10:50 -> BoolConstant(true)
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:10:22 -> BoolConstant(false)
 Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:11:59 -> StringConstant("foo was false")
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:11:30 -> BoolConstant(false)
-Evaluated with empty environment: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:12:50 -> BoolConstant(true)
+Evaluated with empty environment: EqualsCall @ org-dartlang-testcase:///const_asserts.dart:12:50 -> BoolConstant(true)
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:12:22 -> BoolConstant(false)
 Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:14:73 -> StringConstant("btw foo was false")
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:14:44 -> BoolConstant(false)
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:25:24 -> InstanceConstant(const Foo{Foo.x: 1})
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:25:24 -> InstanceConstant(const Foo{Foo.x: 1})
 Extra constant evaluation: evaluated: 34, effectively constant: 10
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_asserts.dart:
+- Foo. (from org-dartlang-testcase:///const_asserts.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Foo.withMessage (from org-dartlang-testcase:///const_asserts.dart:13:9)
+- Foo.withInvalidMessage (from org-dartlang-testcase:///const_asserts.dart:15:9)
+- Foo.withInvalidCondition (from org-dartlang-testcase:///const_asserts.dart:16:9)
+- Bar.withMessage (from org-dartlang-testcase:///const_asserts.dart:21:9)
+- Bar.withoutMessage (from org-dartlang-testcase:///const_asserts.dart:22:9)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.outline.expect
index 8dfa191..76fe0d1 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.outline.expect
@@ -36,11 +36,9 @@
 Evaluated: SetLiteral @ org-dartlang-testcase:///const_collections.dart:21:44 -> SetConstant(const <bool>{false})
 Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:23:16 -> ListConstant(const <int>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:24:17 -> ListConstant(const <int?>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:25:27 -> ListConstant(const <int>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:25:30 -> ListConstant(const <int?>[])
+Evaluated: SetLiteral @ org-dartlang-testcase:///const_collections.dart:25:26 -> SetConstant(const <List<int?>>{const <int>[], const <int?>[]})
 Evaluated with empty environment: MapLiteral @ org-dartlang-testcase:///const_collections.dart:27:38 -> MapConstant(const <bool, bool>{false: false})
 Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_collections.dart:28:8 -> BoolConstant(false)
 Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_collections.dart:28:37 -> BoolConstant(false)
-Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:31:27 -> ListConstant(const <int>[])
-Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:31:33 -> ListConstant(const <int?>[])
-Extra constant evaluation: evaluated: 25, effectively constant: 20
+Evaluated: MapLiteral @ org-dartlang-testcase:///const_collections.dart:31:26 -> MapConstant(const <List<int?>, int>{const <int>[]: 0, const <int?>[]: 1})
+Extra constant evaluation: evaluated: 21, effectively constant: 18
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.expect
index d0164af..0fd3e2b 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.expect
@@ -6,26 +6,6 @@
 // const Map<bool> MapWithUnevaluated = {
 //       ^
 //
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:26: Error: Constant evaluation error:
-// const setNotAgnosticOK = {a, b};
-//                          ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:30: Context: Constant value is not strong/weak mode agnostic.
-// const setNotAgnosticOK = {a, b};
-//                              ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:7: Context: While analyzing:
-// const setNotAgnosticOK = {a, b};
-//       ^
-//
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:26: Error: Constant evaluation error:
-// const mapNotAgnosticOK = {a: 0, b: 1};
-//                          ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:33: Context: Constant value is not strong/weak mode agnostic.
-// const mapNotAgnosticOK = {a: 0, b: 1};
-//                                 ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:7: Context: While analyzing:
-// const mapNotAgnosticOK = {a: 0, b: 1};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -35,16 +15,16 @@
 static const field core::Set<core::bool> setWithUnevaluatedSpread = #C12;
 static const field core::List<core::int> a = #C13;
 static const field core::List<core::int?> b = #C14;
-static const field core::Set<core::List<core::int?>> setNotAgnosticOK = invalid-expression "Constant value is not strong/weak mode agnostic.";
-static const field invalid-type MapWithUnevaluated = #C15;
-static const field core::Map<core::List<core::int?>, core::int> mapNotAgnosticOK = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field core::Set<core::List<core::int?>> setNotAgnosticOK = #C15;
+static const field invalid-type MapWithUnevaluated = #C16;
+static const field core::Map<core::List<core::int?>, core::int> mapNotAgnosticOK = #C19;
 static method main() → dynamic {
   core::print(#C5);
   core::print(#C8);
   core::print(#C10);
   core::print(#C12);
   core::print(<core::String>{"hello"});
-  core::print(#C17);
+  core::print(#C21);
 }
 
 constants  {
@@ -62,7 +42,11 @@
   #C12 = eval #C9 + const <dynamic>{const core::bool::fromEnvironment(#C1)} + const <dynamic>{const core::bool::fromEnvironment(#C2)} + #C9 + #C11
   #C13 = <core::int>[]
   #C14 = <core::int?>[]
-  #C15 = eval const <dynamic, dynamic>{const core::bool::fromEnvironment(#C1): const core::bool::fromEnvironment(#C2)}
-  #C16 = "hello"
-  #C17 = <core::String>{#C16}
+  #C15 = <core::List<core::int?>>{#C13, #C14}
+  #C16 = eval const <dynamic, dynamic>{const core::bool::fromEnvironment(#C1): const core::bool::fromEnvironment(#C2)}
+  #C17 = 0
+  #C18 = 1
+  #C19 = <core::List<core::int?>, core::int>{#C13:#C17, #C14:#C18)
+  #C20 = "hello"
+  #C21 = <core::String>{#C20}
 }
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.transformed.expect
index 734ed41..d9dd342 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.transformed.expect
@@ -6,26 +6,6 @@
 // const Map<bool> MapWithUnevaluated = {
 //       ^
 //
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:26: Error: Constant evaluation error:
-// const setNotAgnosticOK = {a, b};
-//                          ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:30: Context: Constant value is not strong/weak mode agnostic.
-// const setNotAgnosticOK = {a, b};
-//                              ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:7: Context: While analyzing:
-// const setNotAgnosticOK = {a, b};
-//       ^
-//
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:26: Error: Constant evaluation error:
-// const mapNotAgnosticOK = {a: 0, b: 1};
-//                          ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:33: Context: Constant value is not strong/weak mode agnostic.
-// const mapNotAgnosticOK = {a: 0, b: 1};
-//                                 ^
-// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:7: Context: While analyzing:
-// const mapNotAgnosticOK = {a: 0, b: 1};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -35,16 +15,16 @@
 static const field core::Set<core::bool> setWithUnevaluatedSpread = #C12;
 static const field core::List<core::int> a = #C13;
 static const field core::List<core::int?> b = #C14;
-static const field core::Set<core::List<core::int?>> setNotAgnosticOK = invalid-expression "Constant value is not strong/weak mode agnostic.";
-static const field invalid-type MapWithUnevaluated = #C15;
-static const field core::Map<core::List<core::int?>, core::int> mapNotAgnosticOK = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field core::Set<core::List<core::int?>> setNotAgnosticOK = #C15;
+static const field invalid-type MapWithUnevaluated = #C16;
+static const field core::Map<core::List<core::int?>, core::int> mapNotAgnosticOK = #C19;
 static method main() → dynamic {
-  core::print(#C16);
-  core::print(#C17);
-  core::print(#C18);
-  core::print(#C19);
-  core::print(<core::String>{"hello"});
+  core::print(#C20);
   core::print(#C21);
+  core::print(#C22);
+  core::print(#C23);
+  core::print(<core::String>{"hello"});
+  core::print(#C25);
 }
 
 constants  {
@@ -62,13 +42,17 @@
   #C12 = eval #C9 + const <dynamic>{const core::bool::fromEnvironment(#C1)} + const <dynamic>{const core::bool::fromEnvironment(#C2)} + #C9 + #C11
   #C13 = <core::int>[]
   #C14 = <core::int?>[]
-  #C15 = eval const <dynamic, dynamic>{const core::bool::fromEnvironment(#C1): const core::bool::fromEnvironment(#C2)}
-  #C16 = eval const <dynamic>[const core::bool::fromEnvironment(#C1)] + const <dynamic>[const core::bool::fromEnvironment(#C2)] + #C4
-  #C17 = eval #C4 + const <dynamic>[const core::bool::fromEnvironment(#C1)] + const <dynamic>[const core::bool::fromEnvironment(#C2)] + #C4 + #C7
-  #C18 = eval const <dynamic>{const core::bool::fromEnvironment(#C1)} + const <dynamic>{const core::bool::fromEnvironment(#C2)} + #C9
-  #C19 = eval #C9 + const <dynamic>{const core::bool::fromEnvironment(#C1)} + const <dynamic>{const core::bool::fromEnvironment(#C2)} + #C9 + #C11
-  #C20 = "hello"
-  #C21 = <core::String>{#C20}
+  #C15 = <core::List<core::int?>>{#C13, #C14}
+  #C16 = eval const <dynamic, dynamic>{const core::bool::fromEnvironment(#C1): const core::bool::fromEnvironment(#C2)}
+  #C17 = 0
+  #C18 = 1
+  #C19 = <core::List<core::int?>, core::int>{#C13:#C17, #C14:#C18)
+  #C20 = eval const <dynamic>[const core::bool::fromEnvironment(#C1)] + const <dynamic>[const core::bool::fromEnvironment(#C2)] + #C4
+  #C21 = eval #C4 + const <dynamic>[const core::bool::fromEnvironment(#C1)] + const <dynamic>[const core::bool::fromEnvironment(#C2)] + #C4 + #C7
+  #C22 = eval const <dynamic>{const core::bool::fromEnvironment(#C1)} + const <dynamic>{const core::bool::fromEnvironment(#C2)} + #C9
+  #C23 = eval #C9 + const <dynamic>{const core::bool::fromEnvironment(#C1)} + const <dynamic>{const core::bool::fromEnvironment(#C2)} + #C9 + #C11
+  #C24 = "hello"
+  #C25 = <core::String>{#C24}
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.outline.expect
index 55d4864..a4388e8 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.outline.expect
@@ -2,9 +2,9 @@
 import self as self;
 import "dart:core" as core;
 
-static const field core::int foo = 42.{core::num::*}(42);
+static const field core::int foo = 42.{core::num::*}(42){(core::num) → core::int};
 static const field core::String bar = "hello ${const core::String::fromEnvironment("baz", defaultValue: "world")}!";
-static const field core::bool baz = true && true && (false || true) && 42.{core::num::==}(21.{core::num::*}(4).{core::num::/}(2));
+static const field core::bool baz = true && true && (false || true) && 42 =={core::num::==}{(core::Object) → core::bool} 21.{core::num::*}(4){(core::num) → core::int}.{core::num::/}(2){(core::num) → core::double};
 static const field core::Symbol blaSymbol = #_x;
 static method main() → dynamic
   ;
@@ -13,7 +13,7 @@
 
 
 Extra constant evaluation status:
-Evaluated: MethodInvocation @ org-dartlang-testcase:///rudimentary_test_01.dart:5:20 -> IntConstant(1764)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///rudimentary_test_01.dart:5:20 -> IntConstant(1764)
 Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///rudimentary_test_01.dart:6:18 -> StringConstant("hello world!")
 Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///rudimentary_test_01.dart:7:27 -> StringConstant("world")
 Evaluated: LogicalExpression @ org-dartlang-testcase:///rudimentary_test_01.dart:8:50 -> BoolConstant(true)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.outline.expect
index e60e513..9d8a83e 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.outline.expect
@@ -76,7 +76,7 @@
     : this self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
  - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
   const Class.method(T t) : this(-t);
-                                 ^" in t.{self::A::unary-}() as{TypeError,ForNonNullableByDefault} <BottomType>)
+                                 ^" in t.{self::A::unary-}(){() → self::A} as{TypeError,ForNonNullableByDefault} <BottomType>)
     ;
 }
 class Subclass<T extends self::A = self::A> extends self::Class<self::Subclass::T> /*hasConstConstructor*/  {
@@ -96,7 +96,7 @@
 static const field core::bool barFromEnvOrNull = const core::bool::fromEnvironment("bar", defaultValue: self::barFromEnvOrNull0!);
 static const field core::bool notBarFromEnvOrNull = !self::barFromEnvOrNull;
 static const field core::bool conditionalOnNull = self::barFromEnvOrNull ?{core::bool} true : false;
-static const field core::bool nullAwareOnNull = let final core::bool #t2 = self::barFromEnvOrNull in #t2.{core::Object::==}(null) ?{core::bool} true : #t2;
+static const field core::bool nullAwareOnNull = let final core::bool #t2 = self::barFromEnvOrNull in #t2 == null ?{core::bool} true : #t2;
 static const field core::bool andOnNull = self::barFromEnvOrNull && true;
 static const field core::bool andOnNull2 = true && self::barFromEnvOrNull;
 static const field core::bool orOnNull = self::barFromEnvOrNull || true;
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.expect
index 8f2590a..666cda7 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.expect
@@ -104,7 +104,7 @@
     : this self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
  - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
   const Class.method(T t) : this(-t);
-                                 ^" in t.{self::A::unary-}() as{TypeError,ForNonNullableByDefault} <BottomType>)
+                                 ^" in t.{self::A::unary-}(){() → self::A} as{TypeError,ForNonNullableByDefault} <BottomType>)
     ;
 }
 class Subclass<T extends self::A = self::A> extends self::Class<self::Subclass::T> /*hasConstConstructor*/  {
@@ -191,8 +191,8 @@
   core::print(#C37);
   core::print(#C38);
   core::print(#C20);
-  core::print((#C20).{self::Foo::saved});
-  core::print((#C20).{self::Foo::value});
+  core::print((#C20).{self::Foo::saved}{core::bool});
+  core::print((#C20).{self::Foo::value}{core::int});
 }
 
 library /*isNonNullableByDefault*/;
@@ -216,7 +216,7 @@
   #C12 = eval !const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
   #C13 = false
   #C14 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) ?{core::bool} #C8 : #C13
-  #C15 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!).==(#C9) ?{core::bool} #C8 : const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C15 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) == null ?{core::bool} #C8 : const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
   #C16 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) && (#C8)
   #C17 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) || (#C8)
   #C18 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) || (#C13)
@@ -248,3 +248,17 @@
   #C44 = eval const core::bool::fromEnvironment(#C2) ?{core::bool?} const core::bool::fromEnvironment(#C1) : #C9
   #C45 = eval (const core::bool::fromEnvironment(#C2) ?{core::bool?} const core::bool::fromEnvironment(#C1) : #C9)!
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///various.dart:
+- C. (from org-dartlang-testcase:///various.dart:92:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class.redirect (from org-dartlang-testcase:///various.dart:99:9)
+- Class. (from org-dartlang-testcase:///various.dart:98:9)
+- A. (from org-dartlang-testcase:///various.dart:80:9)
+- Class.method (from org-dartlang-testcase:///various.dart:100:9)
+- Subclass. (from org-dartlang-testcase:///various.dart:104:9)
+- B. (from org-dartlang-testcase:///various.dart:86:9)
+- Foo. (from org-dartlang-testcase:///various.dart:31:9)
+- ConstClassWithF. (from org-dartlang-testcase:///various.dart:120:9)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.transformed.expect
index 858bb47..cae94a4 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.transformed.expect
@@ -104,7 +104,7 @@
     : this self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
  - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
   const Class.method(T t) : this(-t);
-                                 ^" in t.{self::A::unary-}() as{TypeError,ForNonNullableByDefault} <BottomType>)
+                                 ^" in t.{self::A::unary-}(){() → self::A} as{TypeError,ForNonNullableByDefault} <BottomType>)
     ;
 }
 class Subclass<T extends self::A = self::A> extends self::Class<self::Subclass::T> /*hasConstConstructor*/  {
@@ -191,8 +191,8 @@
   core::print(#C50);
   core::print(#C51);
   core::print(#C52);
-  core::print((#C52).{self::Foo::saved});
-  core::print((#C52).{self::Foo::value});
+  core::print((#C52).{self::Foo::saved}{core::bool});
+  core::print((#C52).{self::Foo::value}{core::int});
 }
 
 library /*isNonNullableByDefault*/;
@@ -216,7 +216,7 @@
   #C12 = eval !const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
   #C13 = false
   #C14 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) ?{core::bool} #C8 : #C13
-  #C15 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!).==(#C9) ?{core::bool} #C8 : const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C15 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) == null ?{core::bool} #C8 : const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
   #C16 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) && (#C8)
   #C17 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) || (#C8)
   #C18 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) || (#C13)
@@ -282,3 +282,17 @@
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:128:33 -> BoolConstant(true)
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:130:33 -> NullConstant(null)
 Extra constant evaluation: evaluated: 66, effectively constant: 24
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///various.dart:
+- C. (from org-dartlang-testcase:///various.dart:92:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class.redirect (from org-dartlang-testcase:///various.dart:99:9)
+- Class. (from org-dartlang-testcase:///various.dart:98:9)
+- A. (from org-dartlang-testcase:///various.dart:80:9)
+- Class.method (from org-dartlang-testcase:///various.dart:100:9)
+- Subclass. (from org-dartlang-testcase:///various.dart:104:9)
+- B. (from org-dartlang-testcase:///various.dart:86:9)
+- Foo. (from org-dartlang-testcase:///various.dart:31:9)
+- ConstClassWithF. (from org-dartlang-testcase:///various.dart:120:9)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.outline.expect
index 4b3859b..1578765 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.outline.expect
@@ -110,13 +110,13 @@
 Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:53:5 -> BoolConstant(true)
 Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:55:5 -> BoolConstant(true)
 Evaluated: TypeLiteral @ org-dartlang-testcase:///various_2_lib.dart:17:27 -> TypeLiteralConstant(Object)
-Evaluated: StaticGet @ org-dartlang-testcase:///various_2_lib.dart:18:12 -> TearOffConstant(identical)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///various_2_lib.dart:18:12 -> TearOffConstant(identical)
 Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various_2_lib.dart:20:39 -> PartialInstantiationConstant(id2<int>)
 Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various_2_lib.dart:20:11 -> BoolConstant(false)
 Evaluated with empty environment: Instantiation @ org-dartlang-testcase:///various_2_lib.dart:20:41 -> PartialInstantiationConstant(id1<int>)
-Evaluated: StaticGet @ org-dartlang-testcase:///various_2_lib.dart:20:41 -> TearOffConstant(id1)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///various_2_lib.dart:20:41 -> TearOffConstant(id1)
 Evaluated with empty environment: Instantiation @ org-dartlang-testcase:///various_2_lib.dart:20:47 -> PartialInstantiationConstant(id2<int>)
-Evaluated: StaticGet @ org-dartlang-testcase:///various_2_lib.dart:20:47 -> TearOffConstant(id2)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///various_2_lib.dart:20:47 -> TearOffConstant(id2)
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various_2_lib.dart:21:24 -> InstanceConstant(const Class<int>{Class.field: 0})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various_2_lib.dart:22:25 -> InstanceConstant(const Class<dynamic>{Class.field: const <int>[42]})
 Evaluated: TypeLiteral @ org-dartlang-testcase:///various_2_lib.dart:23:29 -> TypeLiteralConstant(dynamic Function(dynamic))
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect
index 08cdf8e..c554f17 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect
@@ -126,3 +126,12 @@
   #C22 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
   #C23 = tearoff core::identical
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///various_2.dart:
+- Class. (from org-dartlang-testcase:///various_2_lib.dart:8:9)
+
+org-dartlang-testcase:///various_2_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class. (from org-dartlang-testcase:///various_2_lib.dart:8:9)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect
index 6932698..79894cf 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect
@@ -135,3 +135,12 @@
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various_2.dart:37:5 -> BoolConstant(false)
 Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various_2_lib.dart:20:39 -> PartialInstantiationConstant(id2<int>)
 Extra constant evaluation: evaluated: 41, effectively constant: 4
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///various_2.dart:
+- Class. (from org-dartlang-testcase:///various_2_lib.dart:8:9)
+
+org-dartlang-testcase:///various_2_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class. (from org-dartlang-testcase:///various_2_lib.dart:8:9)
diff --git a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
index 5bf2809..a95f0d2 100644
--- a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.expect
@@ -48,3 +48,9 @@
 constants  {
   #C1 = self::_Y<Null> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constructor_const_inference.dart:
+- _Y. (from org-dartlang-testcase:///constructor_const_inference.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
index 5bf2809..a95f0d2 100644
--- a/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constructor_const_inference.dart.strong.transformed.expect
@@ -48,3 +48,9 @@
 constants  {
   #C1 = self::_Y<Null> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constructor_const_inference.dart:
+- _Y. (from org-dartlang-testcase:///constructor_const_inference.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/control_flow_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection.dart.strong.transformed.expect
index 17ab5b6..2e4b07e 100644
--- a/pkg/front_end/testcases/general/control_flow_collection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 static method main() → dynamic {
   final core::List<core::int*>* aList = block {
-    final core::List<core::int*>* #t1 = <core::int*>[1];
+    final core::List<core::int*>* #t1 = core::_GrowableList::_literal1<core::int*>(1);
     if(self::oracle() as{TypeError,ForDynamic} core::bool*)
       #t1.{core::List::add}{Invariant}(2);
     if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -16,14 +16,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t1.{core::List::add}{Invariant}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(5, 6, 7).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}{Invariant}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(8, 9, 10).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -46,14 +46,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t2.{core::Set::add}{Invariant}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(5, 6, 7).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t2.{core::Set::add}{Invariant}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(8, 9, 10).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -76,14 +76,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t3.{core::Map::[]=}{Invariant}(4, 4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(5, 6, 7).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t3.{core::Map::[]=}{Invariant}(i, i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(8, 9, 10).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
index da6a4b7..3cc42c4 100644
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
@@ -453,7 +453,7 @@
   return true;
 static method testIfElement(dynamic dynVar, core::List<core::int*>* listInt, core::List<core::double*>* listDouble, core::Map<core::String*, core::int*>* mapToInt, core::Map<core::String*, core::double*>* mapToDouble) → dynamic {
   core::List<core::int*>* list10 = block {
-    final core::List<core::int*>* #t1 = <core::int*>[];
+    final core::List<core::int*>* #t1 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t1.{core::List::add}{Invariant}(42);
   } =>#t1;
@@ -470,7 +470,7 @@
     #t3.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t3;
   core::List<dynamic>* list11 = block {
-    final core::List<dynamic>* #t4 = <dynamic>[];
+    final core::List<dynamic>* #t4 = core::_GrowableList::•<dynamic>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t4.{core::List::add}{Invariant}(dynVar);
   } =>#t4;
@@ -487,31 +487,31 @@
     #t6.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t6;
   core::List<core::List<core::int*>*>* list12 = block {
-    final core::List<core::List<core::int*>*>* #t7 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t7 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t7.{core::List::add}{Invariant}(<core::int*>[42]);
+      #t7.{core::List::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t7;
   core::Set<core::List<core::int*>*>* set12 = block {
     final core::Set<core::List<core::int*>*>* #t8 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t8.{core::Set::add}{Invariant}(<core::int*>[42]);
+      #t8.{core::Set::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t8.{core::Set::add}{Invariant}(null);
   } =>#t8;
   core::Map<core::String*, core::List<core::int*>*>* map12 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t9 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t9.{core::Map::[]=}{Invariant}("bar", <core::int*>[42]);
+      #t9.{core::Map::[]=}{Invariant}("bar", core::_GrowableList::_literal1<core::int*>(42));
     #t9.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t9;
   core::List<core::int*>* list20 = block {
-    final core::List<core::int*>* #t10 = <core::int*>[];
+    final core::List<core::int*>* #t10 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t10.{core::List::addAll}{Invariant}(<core::int*>[42]);
+      #t10.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t10;
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t11 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t11.{core::Set::addAll}{Invariant}(<core::int*>[42]);
+      #t11.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t11.{core::Set::add}{Invariant}(null);
   } =>#t11;
   core::Map<core::String*, core::int*>* map20 = block {
@@ -526,14 +526,14 @@
     #t12.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t12;
   core::List<dynamic>* list21 = block {
-    final core::List<dynamic>* #t14 = <dynamic>[];
+    final core::List<dynamic>* #t14 = core::_GrowableList::•<dynamic>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t14.{core::List::addAll}{Invariant}(<dynamic>[dynVar]);
+      #t14.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
   } =>#t14;
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t15 = new col::_CompactLinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t15.{core::Set::addAll}{Invariant}(<dynamic>[dynVar]);
+      #t15.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
     #t15.{core::Set::add}{Invariant}(null);
   } =>#t15;
   core::Map<core::String*, dynamic>* map21 = block {
@@ -548,20 +548,20 @@
     #t16.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t16;
   core::List<core::List<core::int*>*>* list22 = block {
-    final core::List<core::List<core::int*>*>* #t18 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t18 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t18.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+      #t18.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
   } =>#t18;
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t19 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t19.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+      #t19.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
     #t19.{core::Set::add}{Invariant}(null);
   } =>#t19;
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t20 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::_literal1<core::int*>(42)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::Map::[]=}{Invariant}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
@@ -570,16 +570,16 @@
     #t20.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t20;
   core::List<core::int*>* list30 = block {
-    final core::List<core::int*>* #t22 = <core::int*>[];
+    final core::List<core::int*>* #t22 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t22.{core::List::addAll}{Invariant}(<core::int*>[42]);
+        #t22.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t22;
   core::Set<core::int*>* set30 = block {
     final core::Set<core::int*>* #t23 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t23.{core::Set::addAll}{Invariant}(<core::int*>[42]);
+        #t23.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t23.{core::Set::add}{Invariant}(null);
   } =>#t23;
   core::Map<core::String*, core::int*>* map30 = block {
@@ -595,16 +595,16 @@
     #t24.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t24;
   core::List<dynamic>* list31 = block {
-    final core::List<dynamic>* #t26 = <dynamic>[];
+    final core::List<dynamic>* #t26 = core::_GrowableList::•<dynamic>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t26.{core::List::addAll}{Invariant}(<dynamic>[dynVar]);
+        #t26.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
   } =>#t26;
   core::Set<dynamic>* set31 = block {
     final core::Set<dynamic>* #t27 = new col::_CompactLinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t27.{core::Set::addAll}{Invariant}(<dynamic>[dynVar]);
+        #t27.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
     #t27.{core::Set::add}{Invariant}(null);
   } =>#t27;
   core::Map<core::String*, dynamic>* map31 = block {
@@ -620,23 +620,23 @@
     #t28.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t28;
   core::List<core::List<core::int*>*>* list33 = block {
-    final core::List<core::List<core::int*>*>* #t30 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t30 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t30.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+        #t30.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
   } =>#t30;
   core::Set<core::List<core::int*>*>* set33 = block {
     final core::Set<core::List<core::int*>*>* #t31 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t31.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+        #t31.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
     #t31.{core::Set::add}{Invariant}(null);
   } =>#t31;
   core::Map<core::String*, core::List<core::int*>*>* map33 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t32 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::_literal1<core::int*>(42)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t33 = :sync-for-iterator.{core::Iterator::current};
           #t32.{core::Map::[]=}{Invariant}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
@@ -645,25 +645,25 @@
     #t32.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t32;
   core::List<core::List<core::int*>*>* list40 = block {
-    final core::List<core::List<core::int*>*>* #t34 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t34 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t34.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t34.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t34;
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t35 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t35.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t35.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t35.{core::Set::add}{Invariant}(null);
   } =>#t35;
   core::Map<core::String*, core::List<core::int*>*>* map40 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:39:34: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
   Map<String, List<int>> map40 = {if (oracle(\"foo\")) ...{\"bar\", []}, \"baz\": null};
                                  ^";
   core::List<core::List<core::int*>*>* list41 = block {
-    final core::List<core::List<core::int*>*>* #t36 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t36 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t36.{core::List::addAll}{Invariant}( block {
         final core::Set<core::List<core::int*>*>* #t37 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
-        #t37.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t37.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
       } =>#t37);
   } =>#t36;
   core::Set<core::List<core::int*>*>* set41 = block {
@@ -671,28 +671,28 @@
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t38.{core::Set::addAll}{Invariant}( block {
         final core::Set<core::List<core::int*>*>* #t39 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
-        #t39.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t39.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
       } =>#t39);
     #t38.{core::Set::add}{Invariant}(null);
   } =>#t38;
   core::List<core::List<core::int*>*>* list42 = block {
-    final core::List<core::List<core::int*>*>* #t40 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t40 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t40.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t40.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t40;
   core::Set<core::List<core::int*>*>* set42 = block {
     final core::Set<core::List<core::int*>*>* #t41 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t41.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t41.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t41.{core::Set::add}{Invariant}(null);
   } =>#t41;
   core::Map<core::String*, core::List<core::int*>*>* map42 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t42 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t43 = :sync-for-iterator.{core::Iterator::current};
           #t42.{core::Map::[]=}{Invariant}(#t43.{core::MapEntry::key}, #t43.{core::MapEntry::value});
@@ -701,14 +701,14 @@
     #t42.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t42;
   core::List<core::int*>* list50 = block {
-    final core::List<core::int*>* #t44 = <core::int*>[];
+    final core::List<core::int*>* #t44 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t44.{core::List::addAll}{Invariant}(<core::int*>[]);
+      #t44.{core::List::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t44;
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t45 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t45.{core::Set::addAll}{Invariant}(<core::int*>[]);
+      #t45.{core::Set::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t45.{core::Set::add}{Invariant}(null);
   } =>#t45;
   core::Map<core::String*, core::int*>* map50 = block {
@@ -723,7 +723,7 @@
     #t46.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t46;
   core::List<core::int*>* list51 = block {
-    final core::List<core::int*>* #t48 = <core::int*>[];
+    final core::List<core::int*>* #t48 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t48.{core::List::addAll}{Invariant}( block {
         final core::Set<core::int*>* #t49 = new col::_CompactLinkedHashSet::•<core::int*>();
@@ -738,16 +738,16 @@
     #t50.{core::Set::add}{Invariant}(null);
   } =>#t50;
   core::List<core::int*>* list52 = block {
-    final core::List<core::int*>* #t52 = <core::int*>[];
+    final core::List<core::int*>* #t52 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t52.{core::List::addAll}{Invariant}(<core::int*>[]);
+        #t52.{core::List::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t52;
   core::Set<core::int*>* set52 = block {
     final core::Set<core::int*>* #t53 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t53.{core::Set::addAll}{Invariant}(<core::int*>[]);
+        #t53.{core::Set::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t53.{core::Set::add}{Invariant}(null);
   } =>#t53;
   core::Map<core::String*, core::int*>* map52 = block {
@@ -763,20 +763,20 @@
     #t54.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t54;
   core::List<core::List<core::int*>*>* list60 = block {
-    final core::List<core::List<core::int*>*>* #t56 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t56 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t56.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t56.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t56;
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t57 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t57.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t57.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t57.{core::Set::add}{Invariant}(null);
   } =>#t57;
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t58 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t59 = :sync-for-iterator.{core::Iterator::current};
         #t58.{core::Map::[]=}{Invariant}(#t59.{core::MapEntry::key}, #t59.{core::MapEntry::value});
@@ -785,23 +785,23 @@
     #t58.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t58;
   core::List<core::List<core::int*>*>* list61 = block {
-    final core::List<core::List<core::int*>*>* #t60 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t60 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t60.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t60.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t60;
   core::Set<core::List<core::int*>*>* set61 = block {
     final core::Set<core::List<core::int*>*>* #t61 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t61.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t61.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t61.{core::Set::add}{Invariant}(null);
   } =>#t61;
   core::Map<core::String*, core::List<core::int*>*>* map61 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t62 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t63 = :sync-for-iterator.{core::Iterator::current};
           #t62.{core::Map::[]=}{Invariant}(#t63.{core::MapEntry::key}, #t63.{core::MapEntry::value});
@@ -810,31 +810,31 @@
     #t62.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t62;
   core::List<core::List<core::int*>*>* list70 = block {
-    final core::List<core::List<core::int*>*>* #t64 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t64 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t64.{core::List::add}{Invariant}(<core::int*>[]);
+      #t64.{core::List::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t64;
   core::Set<core::List<core::int*>*>* set70 = block {
     final core::Set<core::List<core::int*>*>* #t65 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t65.{core::Set::add}{Invariant}(<core::int*>[]);
+      #t65.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t65.{core::Set::add}{Invariant}(null);
   } =>#t65;
   core::List<core::List<core::int*>*>* list71 = block {
-    final core::List<core::List<core::int*>*>* #t66 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t66 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t66.{core::List::add}{Invariant}(<core::int*>[]);
+        #t66.{core::List::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t66;
   core::Set<core::List<core::int*>*>* set71 = block {
     final core::Set<core::List<core::int*>*>* #t67 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t67.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t67.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t67.{core::Set::add}{Invariant}(null);
   } =>#t67;
   core::List<core::num*>* list80 = block {
-    final core::List<core::num*>* #t68 = <core::num*>[];
+    final core::List<core::num*>* #t68 = core::_GrowableList::•<core::num*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t68.{core::List::add}{Invariant}(42);
     else
@@ -857,7 +857,7 @@
     #t70.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t70;
   core::List<core::num*>* list81 = block {
-    final core::List<core::num*>* #t71 = <core::num*>[];
+    final core::List<core::num*>* #t71 = core::_GrowableList::•<core::num*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t71.{core::List::addAll}{Invariant}(listInt);
     else
@@ -890,7 +890,7 @@
     #t73.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t73;
   core::List<dynamic>* list82 = block {
-    final core::List<dynamic>* #t76 = <dynamic>[];
+    final core::List<dynamic>* #t76 = core::_GrowableList::•<dynamic>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t76.{core::List::addAll}{Invariant}(listInt);
     else
@@ -916,7 +916,7 @@
     #t78.{core::Set::add}{Invariant}(null);
   } =>#t78;
   core::List<core::num*>* list83 = block {
-    final core::List<core::num*>* #t79 = <core::num*>[];
+    final core::List<core::num*>* #t79 = core::_GrowableList::•<core::num*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t79.{core::List::add}{Invariant}(42);
     else
@@ -944,7 +944,7 @@
     #t81.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t81;
   core::List<core::int*>* list90 = block {
-    final core::List<core::int*>* #t83 = <core::int*>[];
+    final core::List<core::int*>* #t83 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t83.{core::List::add}{Invariant}(dynVar as{TypeError,ForDynamic} core::int*);
   } =>#t83;
@@ -961,7 +961,7 @@
     #t85.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t85;
   core::List<core::int*>* list91 = block {
-    final core::List<core::int*>* #t86 = <core::int*>[];
+    final core::List<core::int*>* #t86 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
       core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -1003,7 +1003,7 @@
     #t92.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t92;
   core::List<core::int*>* list100 = block {
-    final core::List<core::int*>* #t96 = <core::int*>[];
+    final core::List<core::int*>* #t96 = core::_GrowableList::•<core::int*>(0);
     if(dynVar as{TypeError,ForDynamic} core::bool*)
       #t96.{core::List::add}{Invariant}(42);
   } =>#t96;
@@ -1020,7 +1020,7 @@
 }
 static method testIfElementErrors(core::Map<core::int*, core::int*>* map) → dynamic {
   block {
-    final core::List<core::int*>* #t99 = <core::int*>[];
+    final core::List<core::int*>* #t99 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t99.{core::List::add}{Invariant}(let final<BottomType> #t100 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:87:28: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[if (oracle(\"foo\")) \"bar\"];
@@ -1043,18 +1043,18 @@
     #t103.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t103;
   block {
-    final core::List<core::int*>* #t105 = <core::int*>[];
+    final core::List<core::int*>* #t105 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t105.{core::List::addAll}{Invariant}(<core::int*>[let final<BottomType> #t106 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:90:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      #t105.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t106 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:90:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[if (oracle(\"foo\")) ...[\"bar\"]];
-                               ^" in "bar" as{TypeError} core::int*]);
+                               ^" in "bar" as{TypeError} core::int*));
   } =>#t105;
   block {
     final core::Set<core::int*>* #t107 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t107.{core::Set::addAll}{Invariant}(<core::int*>[let final<BottomType> #t108 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:91:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      #t107.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t108 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:91:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{if (oracle(\"foo\")) ...[\"bar\"], null};
-                               ^" in "bar" as{TypeError} core::int*]);
+                               ^" in "bar" as{TypeError} core::int*));
     #t107.{core::Set::add}{Invariant}(null);
   } =>#t107;
   block {
@@ -1071,7 +1071,7 @@
     #t109.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t109;
   block {
-    final core::List<core::int*>* #t112 = <core::int*>[];
+    final core::List<core::int*>* #t112 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t112.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:93:31: Error: Unexpected type 'Map<int, int>' of a spread.  Expected 'dynamic' or an Iterable.
  - 'Map' is from 'dart:core'.
@@ -1095,7 +1095,7 @@
   <String, int>{if (oracle(\"foo\")) ...[\"bar\"], \"baz\": null};
                                       ^": null};
   block {
-    final core::List<core::String*>* #t114 = <core::String*>[];
+    final core::List<core::String*>* #t114 = core::_GrowableList::•<core::String*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t114.{core::List::add}{Invariant}(let final<BottomType> #t115 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:96:31: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
   <String>[if (oracle(\"foo\")) 42 else 3.14];
@@ -1130,7 +1130,7 @@
     #t120.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t120;
   block {
-    final core::List<core::int*>* #t123 = <core::int*>[];
+    final core::List<core::int*>* #t123 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t123.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:99:31: Error: Unexpected type 'Map<int, int>' of a spread.  Expected 'dynamic' or an Iterable.
  - 'Map' is from 'dart:core'.
@@ -1158,7 +1158,7 @@
   <String, int>{if (oracle(\"foo\")) ...[42] else \"bar\": 42, \"baz\": null};
                                       ^": null};
   block {
-    final core::List<core::int*>* #t125 = <core::int*>[];
+    final core::List<core::int*>* #t125 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t125.{core::List::add}{Invariant}(42);
     else
@@ -1204,7 +1204,7 @@
   var map13 = {if (oracle(\"foo\")) \"bar\": 3.14 else 42};
                                                    ^": null};
   core::List<core::int*>* list20 = block {
-    final core::List<core::int*>* #t127 = <core::int*>[];
+    final core::List<core::int*>* #t127 = core::_GrowableList::•<core::int*>(0);
     if(let final<BottomType> #t128 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:112:27: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
   List<int> list20 = [if (42) 42];
                           ^" in 42 as{TypeError} core::bool*)
@@ -1225,7 +1225,7 @@
       #t131.{core::Map::[]=}{Invariant}(42, 42);
   } =>#t131;
   core::List<core::String*>* list40 = block {
-    final core::List<core::String*>* #t133 = <core::String*>[];
+    final core::List<core::String*>* #t133 = core::_GrowableList::•<core::String*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t133.{core::List::add}{Invariant}(let final<BottomType> #t134 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:115:53: Error: A value of type 'bool' can't be assigned to a variable of type 'String'.
   List<String> list40 = <String>[if (oracle(\"foo\")) true else 42];
@@ -1271,7 +1271,7 @@
 }
 static method testForElement(dynamic dynVar, core::List<core::int*>* listInt, core::List<core::double*>* listDouble, core::int* index, core::Map<core::String*, core::int*>* mapStringInt, core::Map<core::String*, core::double*>* mapStringDouble) → dynamic {
   core::List<core::int*>* list10 = block {
-    final core::List<core::int*>* #t145 = <core::int*>[];
+    final core::List<core::int*>* #t145 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t145.{core::List::add}{Invariant}(42);
   } =>#t145;
@@ -1288,7 +1288,7 @@
     #t147.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t147;
   core::List<dynamic>* list11 = block {
-    final core::List<dynamic>* #t148 = <dynamic>[];
+    final core::List<dynamic>* #t148 = core::_GrowableList::•<dynamic>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t148.{core::List::add}{Invariant}(dynVar);
   } =>#t148;
@@ -1305,31 +1305,31 @@
     #t150.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t150;
   core::List<core::List<core::int*>*>* list12 = block {
-    final core::List<core::List<core::int*>*>* #t151 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t151 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t151.{core::List::add}{Invariant}(<core::int*>[42]);
+      #t151.{core::List::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t151;
   core::Set<core::List<core::int*>*>* set12 = block {
     final core::Set<core::List<core::int*>*>* #t152 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t152.{core::Set::add}{Invariant}(<core::int*>[42]);
+      #t152.{core::Set::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t152.{core::Set::add}{Invariant}(null);
   } =>#t152;
   core::Map<core::String*, core::List<core::int*>*>* map12 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t153 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t153.{core::Map::[]=}{Invariant}("bar", <core::int*>[42]);
+      #t153.{core::Map::[]=}{Invariant}("bar", core::_GrowableList::_literal1<core::int*>(42));
     #t153.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t153;
   core::List<core::int*>* list20 = block {
-    final core::List<core::int*>* #t154 = <core::int*>[];
+    final core::List<core::int*>* #t154 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t154.{core::List::addAll}{Invariant}(<core::int*>[42]);
+      #t154.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t154;
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t155 = new col::_CompactLinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t155.{core::Set::addAll}{Invariant}(<core::int*>[42]);
+      #t155.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t155.{core::Set::add}{Invariant}(null);
   } =>#t155;
   core::Map<core::String*, core::int*>* map20 = block {
@@ -1344,14 +1344,14 @@
     #t156.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t156;
   core::List<dynamic>* list21 = block {
-    final core::List<dynamic>* #t158 = <dynamic>[];
+    final core::List<dynamic>* #t158 = core::_GrowableList::•<dynamic>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t158.{core::List::addAll}{Invariant}(<dynamic>[dynVar]);
+      #t158.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
   } =>#t158;
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t159 = new col::_CompactLinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t159.{core::Set::addAll}{Invariant}(<dynamic>[dynVar]);
+      #t159.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
     #t159.{core::Set::add}{Invariant}(null);
   } =>#t159;
   core::Map<core::String*, dynamic>* map21 = block {
@@ -1366,20 +1366,20 @@
     #t160.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t160;
   core::List<core::List<core::int*>*>* list22 = block {
-    final core::List<core::List<core::int*>*>* #t162 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t162 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t162.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+      #t162.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
   } =>#t162;
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t163 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t163.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+      #t163.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
     #t163.{core::Set::add}{Invariant}(null);
   } =>#t163;
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t164 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::_literal1<core::int*>(42)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t165 = :sync-for-iterator.{core::Iterator::current};
         #t164.{core::Map::[]=}{Invariant}(#t165.{core::MapEntry::key}, #t165.{core::MapEntry::value});
@@ -1388,16 +1388,16 @@
     #t164.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t164;
   core::List<core::int*>* list30 = block {
-    final core::List<core::int*>* #t166 = <core::int*>[];
+    final core::List<core::int*>* #t166 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t166.{core::List::addAll}{Invariant}(<core::int*>[42]);
+        #t166.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t166;
   core::Set<core::int*>* set30 = block {
     final core::Set<core::int*>* #t167 = new col::_CompactLinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t167.{core::Set::addAll}{Invariant}(<core::int*>[42]);
+        #t167.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t167.{core::Set::add}{Invariant}(null);
   } =>#t167;
   core::Map<core::String*, core::int*>* map30 = block {
@@ -1413,16 +1413,16 @@
     #t168.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t168;
   core::List<dynamic>* list31 = block {
-    final core::List<dynamic>* #t170 = <dynamic>[];
+    final core::List<dynamic>* #t170 = core::_GrowableList::•<dynamic>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t170.{core::List::addAll}{Invariant}(<dynamic>[dynVar]);
+        #t170.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
   } =>#t170;
   core::Set<dynamic>* set31 = block {
     final core::Set<dynamic>* #t171 = new col::_CompactLinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t171.{core::Set::addAll}{Invariant}(<dynamic>[dynVar]);
+        #t171.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
     #t171.{core::Set::add}{Invariant}(null);
   } =>#t171;
   core::Map<core::String*, dynamic>* map31 = block {
@@ -1438,23 +1438,23 @@
     #t172.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t172;
   core::List<core::List<core::int*>*>* list33 = block {
-    final core::List<core::List<core::int*>*>* #t174 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t174 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t174.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+        #t174.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
   } =>#t174;
   core::Set<core::List<core::int*>*>* set33 = block {
     final core::Set<core::List<core::int*>*>* #t175 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t175.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+        #t175.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
     #t175.{core::Set::add}{Invariant}(null);
   } =>#t175;
   core::Map<core::String*, core::List<core::int*>*>* map33 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t176 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::_literal1<core::int*>(42)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t177 = :sync-for-iterator.{core::Iterator::current};
           #t176.{core::Map::[]=}{Invariant}(#t177.{core::MapEntry::key}, #t177.{core::MapEntry::value});
@@ -1463,20 +1463,20 @@
     #t176.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t176;
   core::List<core::List<core::int*>*>* list40 = block {
-    final core::List<core::List<core::int*>*>* #t178 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t178 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t178.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t178.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t178;
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t179 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t179.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t179.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t179.{core::Set::add}{Invariant}(null);
   } =>#t179;
   core::Map<core::String*, core::List<core::int*>*>* map40 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t180 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t181 = :sync-for-iterator.{core::Iterator::current};
         #t180.{core::Map::[]=}{Invariant}(#t181.{core::MapEntry::key}, #t181.{core::MapEntry::value});
@@ -1485,11 +1485,11 @@
     #t180.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t180;
   core::List<core::List<core::int*>*>* list41 = block {
-    final core::List<core::List<core::int*>*>* #t182 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t182 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t182.{core::List::addAll}{Invariant}( block {
         final core::Set<core::List<core::int*>*>* #t183 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
-        #t183.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t183.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
       } =>#t183);
   } =>#t182;
   core::Set<core::List<core::int*>*>* set41 = block {
@@ -1497,28 +1497,28 @@
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t184.{core::Set::addAll}{Invariant}( block {
         final core::Set<core::List<core::int*>*>* #t185 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
-        #t185.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t185.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
       } =>#t185);
     #t184.{core::Set::add}{Invariant}(null);
   } =>#t184;
   core::List<core::List<core::int*>*>* list42 = block {
-    final core::List<core::List<core::int*>*>* #t186 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t186 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t186.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t186.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t186;
   core::Set<core::List<core::int*>*>* set42 = block {
     final core::Set<core::List<core::int*>*>* #t187 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t187.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t187.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t187.{core::Set::add}{Invariant}(null);
   } =>#t187;
   core::Map<core::String*, core::List<core::int*>*>* map42 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t188 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t189 = :sync-for-iterator.{core::Iterator::current};
           #t188.{core::Map::[]=}{Invariant}(#t189.{core::MapEntry::key}, #t189.{core::MapEntry::value});
@@ -1527,14 +1527,14 @@
     #t188.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t188;
   core::List<core::int*>* list50 = block {
-    final core::List<core::int*>* #t190 = <core::int*>[];
+    final core::List<core::int*>* #t190 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t190.{core::List::addAll}{Invariant}(<core::int*>[]);
+      #t190.{core::List::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t190;
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t191 = new col::_CompactLinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t191.{core::Set::addAll}{Invariant}(<core::int*>[]);
+      #t191.{core::Set::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t191.{core::Set::add}{Invariant}(null);
   } =>#t191;
   core::Map<core::String*, core::int*>* map50 = block {
@@ -1549,7 +1549,7 @@
     #t192.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t192;
   core::List<core::int*>* list51 = block {
-    final core::List<core::int*>* #t194 = <core::int*>[];
+    final core::List<core::int*>* #t194 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t194.{core::List::addAll}{Invariant}( block {
         final core::Set<core::int*>* #t195 = new col::_CompactLinkedHashSet::•<core::int*>();
@@ -1564,33 +1564,33 @@
     #t196.{core::Set::add}{Invariant}(null);
   } =>#t196;
   core::List<core::int*>* list52 = block {
-    final core::List<core::int*>* #t198 = <core::int*>[];
+    final core::List<core::int*>* #t198 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t198.{core::List::addAll}{Invariant}(<core::int*>[]);
+        #t198.{core::List::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t198;
   core::Set<core::int*>* set52 = block {
     final core::Set<core::int*>* #t199 = new col::_CompactLinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t199.{core::Set::addAll}{Invariant}(<core::int*>[]);
+        #t199.{core::Set::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t199.{core::Set::add}{Invariant}(null);
   } =>#t199;
   core::List<core::List<core::int*>*>* list60 = block {
-    final core::List<core::List<core::int*>*>* #t200 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t200 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t200.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t200.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t200;
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t201 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t201.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t201.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t201.{core::Set::add}{Invariant}(null);
   } =>#t201;
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t202 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t203 = :sync-for-iterator.{core::Iterator::current};
         #t202.{core::Map::[]=}{Invariant}(#t203.{core::MapEntry::key}, #t203.{core::MapEntry::value});
@@ -1599,23 +1599,23 @@
     #t202.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t202;
   core::List<core::List<core::int*>*>* list61 = block {
-    final core::List<core::List<core::int*>*>* #t204 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t204 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t204.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t204.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t204;
   core::Set<core::List<core::int*>*>* set61 = block {
     final core::Set<core::List<core::int*>*>* #t205 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t205.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t205.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t205.{core::Set::add}{Invariant}(null);
   } =>#t205;
   core::Map<core::String*, core::List<core::int*>*>* map61 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t206 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t207 = :sync-for-iterator.{core::Iterator::current};
           #t206.{core::Map::[]=}{Invariant}(#t207.{core::MapEntry::key}, #t207.{core::MapEntry::value});
@@ -1624,44 +1624,44 @@
     #t206.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t206;
   core::List<core::List<core::int*>*>* list70 = block {
-    final core::List<core::List<core::int*>*>* #t208 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t208 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t208.{core::List::add}{Invariant}(<core::int*>[]);
+      #t208.{core::List::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t208;
   core::Set<core::List<core::int*>*>* set70 = block {
     final core::Set<core::List<core::int*>*>* #t209 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t209.{core::Set::add}{Invariant}(<core::int*>[]);
+      #t209.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t209.{core::Set::add}{Invariant}(null);
   } =>#t209;
   core::Map<core::String*, core::List<core::int*>*>* map70 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t210 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t210.{core::Map::[]=}{Invariant}("bar", <core::int*>[]);
+      #t210.{core::Map::[]=}{Invariant}("bar", core::_GrowableList::•<core::int*>(0));
     #t210.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t210;
   core::List<core::List<core::int*>*>* list71 = block {
-    final core::List<core::List<core::int*>*>* #t211 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t211 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t211.{core::List::add}{Invariant}(<core::int*>[]);
+        #t211.{core::List::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t211;
   core::Set<core::List<core::int*>*>* set71 = block {
     final core::Set<core::List<core::int*>*>* #t212 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t212.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t212.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t212.{core::Set::add}{Invariant}(null);
   } =>#t212;
   core::Map<core::String*, core::List<core::int*>*>* map71 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t213 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t213.{core::Map::[]=}{Invariant}("bar", <core::int*>[]);
+        #t213.{core::Map::[]=}{Invariant}("bar", core::_GrowableList::•<core::int*>(0));
     #t213.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t213;
   core::List<core::num*>* list80 = block {
-    final core::List<core::num*>* #t214 = <core::num*>[];
+    final core::List<core::num*>* #t214 = core::_GrowableList::•<core::num*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t214.{core::List::add}{Invariant}(42);
@@ -1687,7 +1687,7 @@
     #t216.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t216;
   core::List<core::num*>* list81 = block {
-    final core::List<core::num*>* #t217 = <core::num*>[];
+    final core::List<core::num*>* #t217 = core::_GrowableList::•<core::num*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t217.{core::List::addAll}{Invariant}(listInt);
@@ -1723,7 +1723,7 @@
     #t219.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t219;
   core::List<dynamic>* list82 = block {
-    final core::List<dynamic>* #t222 = <dynamic>[];
+    final core::List<dynamic>* #t222 = core::_GrowableList::•<dynamic>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t222.{core::List::addAll}{Invariant}(listInt);
@@ -1759,7 +1759,7 @@
     #t224.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t224;
   core::List<core::num*>* list83 = block {
-    final core::List<core::num*>* #t227 = <core::num*>[];
+    final core::List<core::num*>* #t227 = core::_GrowableList::•<core::num*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t227.{core::List::add}{Invariant}(42);
@@ -1790,7 +1790,7 @@
     #t229.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t229;
   core::List<core::int*>* list90 = block {
-    final core::List<core::int*>* #t231 = <core::int*>[];
+    final core::List<core::int*>* #t231 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t231.{core::List::add}{Invariant}(dynVar as{TypeError,ForDynamic} core::int*);
   } =>#t231;
@@ -1807,7 +1807,7 @@
     #t233.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t233;
   core::List<core::int*>* list91 = block {
-    final core::List<core::int*>* #t234 = <core::int*>[];
+    final core::List<core::int*>* #t234 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
       core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -1849,7 +1849,7 @@
     #t240.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t240;
   core::List<core::int*>* list100 = block {
-    final core::List<core::int*>* #t244 = <core::int*>[];
+    final core::List<core::int*>* #t244 = core::_GrowableList::•<core::int*>(0);
     for (final core::int* #t245 = index = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; index = index.{core::num::+}(1))
       #t244.{core::List::add}{Invariant}(42);
   } =>#t244;
@@ -1864,9 +1864,9 @@
       #t248.{core::Map::[]=}{Invariant}("bar", 42);
   } =>#t248;
   core::List<core::int*>* list110 = block {
-    final core::List<core::int*>* #t250 = <core::int*>[];
+    final core::List<core::int*>* #t250 = core::_GrowableList::•<core::int*>(0);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t250.{core::List::add}{Invariant}(i);
@@ -1876,7 +1876,7 @@
   core::Set<core::int*>* set110 = block {
     final core::Set<core::int*>* #t251 = new col::_CompactLinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t251.{core::Set::add}{Invariant}(i);
@@ -1887,7 +1887,7 @@
   core::Map<core::String*, core::int*>* map110 = block {
     final core::Map<core::String*, core::int*>* #t252 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t252.{core::Map::[]=}{Invariant}("bar", i);
@@ -1896,7 +1896,7 @@
     #t252.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t252;
   core::List<core::int*>* list120 = block {
-    final core::List<core::int*>* #t253 = <core::int*>[];
+    final core::List<core::int*>* #t253 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -1928,7 +1928,7 @@
     #t255.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t255;
   core::List<core::int*>* list130 = block {
-    final core::List<core::int*>* #t256 = <core::int*>[];
+    final core::List<core::int*>* #t256 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 1; i.{core::num::<}(2); i = i.{core::num::+}(1))
       #t256.{core::List::add}{Invariant}(i);
   } =>#t256;
@@ -1960,7 +1960,7 @@
       #L1:
       {
         block {
-          final core::List<core::int*>* #t259 = <core::int*>[];
+          final core::List<core::int*>* #t259 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             #t259.{core::List::add}{Invariant}(let final<BottomType> #t260 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:210:45: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[for (int i = 0; oracle(\"foo\"); i++) \"bar\"];
@@ -1987,18 +1987,18 @@
                                                                ^" in "baz" as{TypeError} core::int*, null);
         } =>#t263;
         block {
-          final core::List<core::int*>* #t267 = <core::int*>[];
+          final core::List<core::int*>* #t267 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-            #t267.{core::List::addAll}{Invariant}(<core::int*>[let final<BottomType> #t268 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:213:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            #t267.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t268 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:213:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"]];
-                                                ^" in "bar" as{TypeError} core::int*]);
+                                                ^" in "bar" as{TypeError} core::int*));
         } =>#t267;
         block {
           final core::Set<core::int*>* #t269 = new col::_CompactLinkedHashSet::•<core::int*>();
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-            #t269.{core::Set::addAll}{Invariant}(<core::int*>[let final<BottomType> #t270 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:214:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            #t269.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t270 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:214:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"], null};
-                                                ^" in "bar" as{TypeError} core::int*]);
+                                                ^" in "bar" as{TypeError} core::int*));
           #t269.{core::Set::add}{Invariant}(null);
         } =>#t269;
         block {
@@ -2019,7 +2019,7 @@
                                                                     ^" in "baz" as{TypeError} core::int*, null);
         } =>#t271;
         block {
-          final core::List<core::int*>* #t276 = <core::int*>[];
+          final core::List<core::int*>* #t276 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             #t276.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:216:48: Error: Unexpected type 'Map<int, int>' of a spread.  Expected 'dynamic' or an Iterable.
  - 'Map' is from 'dart:core'.
@@ -2043,7 +2043,7 @@
   <int, int>{for (int i = 0; oracle(\"foo\"); i++) ...list, 42: null};
                                                     ^": null};
         block {
-          final core::List<core::String*>* #t278 = <core::String*>[];
+          final core::List<core::String*>* #t278 = core::_GrowableList::•<core::String*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
               #t278.{core::List::add}{Invariant}(let final<BottomType> #t279 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:219:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
@@ -2081,7 +2081,7 @@
           #t284.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t284;
         block {
-          final core::List<core::int*>* #t287 = <core::int*>[];
+          final core::List<core::int*>* #t287 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
               #t287.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:222:62: Error: Unexpected type 'Map<int, int>' of a spread.  Expected 'dynamic' or an Iterable.
@@ -2111,7 +2111,7 @@
   <String, int>{for (int i = 0; oracle(\"foo\"); i++) if (oracle()) ...list else \"bar\": 42, \"baz\": null};
                                                                      ^": null};
         block {
-          final core::List<core::int*>* #t289 = <core::int*>[];
+          final core::List<core::int*>* #t289 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
               #t289.{core::List::add}{Invariant}(42);
@@ -2142,9 +2142,9 @@
                                                                                     ^": null};
         final core::int* i = 0;
         block {
-          final core::List<core::int*>* #t291 = <core::int*>[];
+          final core::List<core::int*>* #t291 = core::_GrowableList::•<core::int*>(0);
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal1<core::int*>(1).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t292 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2159,7 +2159,7 @@
         block {
           final core::Set<core::int*>* #t293 = new col::_CompactLinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal1<core::int*>(1).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t294 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2175,7 +2175,7 @@
         block {
           final core::Map<core::String*, core::int*>* #t295 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal1<core::int*>(1).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t296 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2189,7 +2189,7 @@
           #t295.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t295;
         core::List<dynamic>* list10 = block {
-          final core::List<dynamic>* #t297 = <dynamic>[];
+          final core::List<dynamic>* #t297 = core::_GrowableList::•<dynamic>(0);
           {
             core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t298 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:234:31: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
@@ -2230,13 +2230,13 @@
           #t301.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t301;
         core::List<core::int*>* list20 = block {
-          final core::List<core::int*>* #t303 = <core::int*>[];
+          final core::List<core::int*>* #t303 = core::_GrowableList::•<core::int*>(0);
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t304 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:237:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t304 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:237:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
                                ^" in "not" as{TypeError} core::int*, let final<BottomType> #t305 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:237:39: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
-                                      ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
+                                      ^" in "int" as{TypeError} core::int*).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t303.{core::List::add}{Invariant}(i);
@@ -2246,11 +2246,11 @@
         core::Set<core::int*>* set20 = block {
           final core::Set<core::int*>* #t306 = new col::_CompactLinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t307 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:238:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t307 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:238:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t308 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:238:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
-                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t306.{core::Set::add}{Invariant}(i);
@@ -2261,11 +2261,11 @@
         core::Map<core::String*, core::int*>* map20 = block {
           final core::Map<core::String*, core::int*>* #t309 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t310 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:239:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t310 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:239:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t311 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:239:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
-                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t309.{core::Map::[]=}{Invariant}("bar", i);
@@ -2273,7 +2273,7 @@
           }
           #t309.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t309;
-        final core::List<dynamic>* #t312 = <dynamic>[];
+        final core::List<dynamic>* #t312 = core::_GrowableList::•<dynamic>(0);
         {
           asy::Stream<dynamic>* :stream = let final<BottomType> #t313 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:240:37: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
@@ -2355,13 +2355,13 @@
         core::Map<core::String*, dynamic>* map30 = block {
           #t322.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t322;
-        final core::List<core::int*>* #t327 = <core::int*>[];
+        final core::List<core::int*>* #t327 = core::_GrowableList::•<core::int*>(0);
         {
-          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t328 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:243:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t328 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:243:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
                                                          ^" in "not" as{TypeError} core::int*, let final<BottomType> #t329 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:243:65: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
-                                                                ^" in "int" as{TypeError} core::int*]);
+                                                                ^" in "int" as{TypeError} core::int*));
           asy::_StreamIterator<core::int*>* :for-iterator = new asy::_StreamIterator::•<core::int*>(:stream);
           try
             #L5:
@@ -2384,11 +2384,11 @@
         core::List<core::int*>* list40 = block {} =>#t327;
         final core::Set<core::int*>* #t333 = new col::_CompactLinkedHashSet::•<core::int*>();
         {
-          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t334 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:244:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t334 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:244:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t335 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:244:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
-                                                               ^" in "int" as{TypeError} core::int*]);
+                                                               ^" in "int" as{TypeError} core::int*));
           asy::_StreamIterator<core::int*>* :for-iterator = new asy::_StreamIterator::•<core::int*>(:stream);
           try
             #L6:
@@ -2413,11 +2413,11 @@
         } =>#t333;
         final core::Map<core::String*, core::int*>* #t339 = <core::String*, core::int*>{};
         {
-          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t340 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:245:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t340 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:245:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t341 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:245:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
-                                                               ^" in "int" as{TypeError} core::int*]);
+                                                               ^" in "int" as{TypeError} core::int*));
           asy::_StreamIterator<core::int*>* :for-iterator = new asy::_StreamIterator::•<core::int*>(:stream);
           try
             #L7:
@@ -2441,7 +2441,7 @@
           #t339.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t339;
         core::List<core::int*>* list50 = block {
-          final core::List<core::int*>* #t345 = <core::int*>[];
+          final core::List<core::int*>* #t345 = core::_GrowableList::•<core::int*>(0);
           for (; ; )
             #t345.{core::List::add}{Invariant}(42);
         } =>#t345;
@@ -2458,7 +2458,7 @@
           #t347.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t347;
         core::List<core::int*>* list60 = block {
-          final core::List<core::int*>* #t348 = <core::int*>[];
+          final core::List<core::int*>* #t348 = core::_GrowableList::•<core::int*>(0);
           for (; let final<BottomType> #t349 = invalid-expression "pkg/front_end/testcases/general/control_flow_collection_inference.dart:249:24: Error: A value of type 'String' can't be assigned to a variable of type 'bool'.
   var list60 = [for (; \"not bool\";) 42];
                        ^" in "not bool" as{TypeError} core::bool*; )
@@ -2495,7 +2495,7 @@
 }
 static method testForElementErrorsNotAsync(asy::Stream<core::int*>* stream) → dynamic {
   block {
-    final core::List<core::int*>* #t354 = <core::int*>[];
+    final core::List<core::int*>* #t354 = core::_GrowableList::•<core::int*>(0);
     await for (core::int* i in stream)
       #t354.{core::List::add}{Invariant}(i);
   } =>#t354;
@@ -2512,7 +2512,7 @@
 }
 static method testPromotion(self::A* a) → dynamic {
   core::List<core::int*>* list10 = block {
-    final core::List<core::int*>* #t357 = <core::int*>[];
+    final core::List<core::int*>* #t357 = core::_GrowableList::•<core::int*>(0);
     if(a is self::B*)
       #t357.{core::List::add}{Invariant}(a{self::B*}.{self::B::foo});
   } =>#t357;
diff --git a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
index e05fa7c..2ca3173 100644
--- a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.outline.expect
@@ -55,7 +55,7 @@
     : super self::A::•()
     ;
   forwarding-stub method foo(covariant core::num* x) → void
-    return super.{self::A::foo}(x);
+    return super.{self::B::foo}(x);
 }
 class D extends self::_D&A&B implements self::C {
   synthetic constructor •() → self::D*
diff --git a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
index b3bcf67..60fc7d3 100644
--- a/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
+++ b/pkg/front_end/testcases/general/covariant_parameter_in_superclass_of_mixin_application.dart.strong.expect
@@ -55,7 +55,7 @@
     : super self::A::•()
     ;
   forwarding-stub method foo(covariant core::num* x) → void
-    return super.{self::A::foo}(x);
+    return super.{self::B::foo}(x);
 }
 class D extends self::_D&A&B implements self::C {
   synthetic constructor •() → self::D*
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
index 608fb62..2e4c25a 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
@@ -676,3 +676,11 @@
   #C31 = self::AnotherEnum {index:#C9, _name:#C30}
   #C32 = <self::AnotherEnum*>[#C27, #C29, #C31]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///duplicated_declarations.dart:
+- Enum#1. (from org-dartlang-testcase:///duplicated_declarations.dart:81:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Enum. (from org-dartlang-testcase:///duplicated_declarations.dart:74:6)
+- AnotherEnum. (from org-dartlang-testcase:///duplicated_declarations.dart:87:6)
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
index 7b42d92..7187612 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
@@ -52,3 +52,9 @@
 static method bar() → dynamic {
   invalid-expression "This assertion failed.";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_01_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_01_lib1.dart:6:9)
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
index 7b42d92..7187612 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
@@ -52,3 +52,9 @@
 static method bar() → dynamic {
   invalid-expression "This assertion failed.";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_01_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_01_lib1.dart:6:9)
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
index 1aae9ef..616bd79 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
@@ -76,3 +76,9 @@
 import "org-dartlang-testcase:///error_location_02_lib2.dart";
 
 static const field err::Foo* fooField2 = invalid-expression "This assertion failed.";
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_02_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_02_lib1.dart:6:9)
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
index 1aae9ef..616bd79 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
@@ -76,3 +76,9 @@
 import "org-dartlang-testcase:///error_location_02_lib2.dart";
 
 static const field err::Foo* fooField2 = invalid-expression "This assertion failed.";
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_02_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_02_lib1.dart:6:9)
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
index 18b8f4f..8a85eea 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
@@ -77,3 +77,12 @@
 import "org-dartlang-testcase:///error_location_03_lib1.dart";
 
 static const field err::Foo* fooField2 = invalid-expression "This assertion failed.";
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_03_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_03_lib1.dart:6:9)
+
+org-dartlang-testcase:///error_location_03_lib3.dart:
+- Foo. (from org-dartlang-testcase:///error_location_03_lib1.dart:6:9)
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
index 18b8f4f..8a85eea 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
@@ -77,3 +77,12 @@
 import "org-dartlang-testcase:///error_location_03_lib1.dart";
 
 static const field err::Foo* fooField2 = invalid-expression "This assertion failed.";
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_03_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_03_lib1.dart:6:9)
+
+org-dartlang-testcase:///error_location_03_lib3.dart:
+- Foo. (from org-dartlang-testcase:///error_location_03_lib1.dart:6:9)
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
index 972534b..43d683c 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
@@ -68,3 +68,9 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method bar() → dynamic {}
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_04_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_04_lib1.dart:6:9)
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
index 972534b..43d683c 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
@@ -68,3 +68,9 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method bar() → dynamic {}
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_04_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_04_lib1.dart:6:9)
diff --git a/pkg/front_end/testcases/general/error_recovery/for_in_with_colon.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/for_in_with_colon.dart.strong.transformed.expect
index bcd06a8..1e157c0 100644
--- a/pkg/front_end/testcases/general/error_recovery/for_in_with_colon.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/for_in_with_colon.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
 
 static method main() → dynamic {
   {
-    core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+    core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int* i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.transformed.expect
index 7981214..6cdea36 100644
--- a/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39060.dart.strong.transformed.expect
@@ -27,10 +27,11 @@
 // ^
 //
 import self as self;
+import "dart:core" as core;
 
 static method main() → dynamic {
   {
     invalid-type A;
-    <invalid-type>[];
+    core::_GrowableList::•<invalid-type>(0);
   }
 }
diff --git a/pkg/front_end/testcases/general/export_test.dart.strong.expect b/pkg/front_end/testcases/general/export_test.dart.strong.expect
index 8dbe328..497ce03 100644
--- a/pkg/front_end/testcases/general/export_test.dart.strong.expect
+++ b/pkg/front_end/testcases/general/export_test.dart.strong.expect
@@ -1,12 +1,15 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:developer" as dev;
 additionalExports = (core::print)
 
 import "dart:developer" show UserTag;
 export "dart:core" show print;
 
 static method main() → dynamic {
-  core::print(dev::UserTag*);
+  core::print(#C1);
+}
+
+constants  {
+  #C1 = TypeLiteralConstant(dev::UserTag*)
 }
diff --git a/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
index 0676de4..497ce03 100644
--- a/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
@@ -1,17 +1,15 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:developer" as dev;
 additionalExports = (core::print)
 
 import "dart:developer" show UserTag;
 export "dart:core" show print;
 
 static method main() → dynamic {
-  core::print(dev::UserTag*);
+  core::print(#C1);
 }
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///export_test.dart:14:9 -> TypeLiteralConstant(UserTag*)
-Extra constant evaluation: evaluated: 2, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(dev::UserTag*)
+}
diff --git a/pkg/front_end/testcases/general/expressions.dart.strong.expect b/pkg/front_end/testcases/general/expressions.dart.strong.expect
index 90c7dca..5cb0aef 100644
--- a/pkg/front_end/testcases/general/expressions.dart.strong.expect
+++ b/pkg/front_end/testcases/general/expressions.dart.strong.expect
@@ -72,9 +72,9 @@
   self::caller(({dynamic x = #C1}) → Null {
     core::print("<anon> was called with ${x}");
   });
-  core::print(core::int*.{core::Type::toString}());
-  core::print(core::int*);
-  core::print(let final core::Type* #t5 = core::int* in block {
+  core::print((#C3).{core::Type::toString}());
+  core::print(#C3);
+  core::print(let final core::Type* #t5 = #C3 in block {
     #t5.{core::Type::toString}();
   } =>#t5);
   try {
@@ -92,4 +92,10 @@
 constants  {
   #C1 = null
   #C2 = core::Object {}
+  #C3 = TypeLiteralConstant(core::int*)
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///expressions.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
index a1dbb58..0e8e94f 100644
--- a/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
@@ -35,7 +35,7 @@
   }
   for (; false; ) {
   }
-  core::List<core::String*>* list = <core::String*>["Hello, World!"];
+  core::List<core::String*>* list = core::_GrowableList::_literal1<core::String*>("Hello, World!");
   core::print(list.{core::List::[]}(i));
   list.{core::List::[]=}(i, "Hello, Brave New World!");
   core::print(list.{core::List::[]}(i));
@@ -72,9 +72,9 @@
   self::caller(({dynamic x = #C1}) → Null {
     core::print("<anon> was called with ${x}");
   });
-  core::print(core::int*.{core::Type::toString}());
-  core::print(core::int*);
-  core::print(let final core::Type* #t5 = core::int* in block {
+  core::print((#C3).{core::Type::toString}());
+  core::print(#C3);
+  core::print(let final core::Type* #t5 = #C3 in block {
     #t5.{core::Type::toString}();
   } =>#t5);
   try {
@@ -92,13 +92,16 @@
 constants  {
   #C1 = null
   #C2 = core::Object {}
+  #C3 = TypeLiteralConstant(core::int*)
 }
 
 Extra constant evaluation status:
 Evaluated: StringConcatenation @ org-dartlang-testcase:///expressions.dart:21:8 -> StringConstant("foobar")
-Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:70:10 -> TypeLiteralConstant(int*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:71:9 -> TypeLiteralConstant(int*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:72:9 -> TypeLiteralConstant(int*)
 Evaluated: VariableGetImpl @ org-dartlang-testcase:///expressions.dart:72:9 -> TypeLiteralConstant(int*)
 Evaluated: VariableGet @ org-dartlang-testcase:///expressions.dart:72:9 -> TypeLiteralConstant(int*)
-Extra constant evaluation: evaluated: 138, effectively constant: 6
+Extra constant evaluation: evaluated: 135, effectively constant: 3
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///expressions.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/external_import.dart.strong.expect b/pkg/front_end/testcases/general/external_import.dart.strong.expect
index 92724dc..0a7d177 100644
--- a/pkg/front_end/testcases/general/external_import.dart.strong.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.strong.expect
@@ -15,3 +15,8 @@
   #C5 = "dart-ext:/usr/local/somewhere"
   #C6 = _in::ExternalName {name:#C5}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///external_import.dart:
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
diff --git a/pkg/front_end/testcases/general/external_import.dart.strong.transformed.expect b/pkg/front_end/testcases/general/external_import.dart.strong.transformed.expect
index 92724dc..0a7d177 100644
--- a/pkg/front_end/testcases/general/external_import.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.strong.transformed.expect
@@ -15,3 +15,8 @@
   #C5 = "dart-ext:/usr/local/somewhere"
   #C6 = _in::ExternalName {name:#C5}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///external_import.dart:
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart b/pkg/front_end/testcases/general/ffi_sample.dart
deleted file mode 100644
index db95797..0000000
--- a/pkg/front_end/testcases/general/ffi_sample.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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.
-
-// This test was adapted from samples/ffi/coordinate.dart
-
-import 'dart:ffi';
-
-import "package:ffi/ffi.dart";
-
-/// Sample struct for dart:ffi library.
-class Coordinate extends Struct {
-  @Double()
-  double x;
-
-  @Double()
-  double y;
-
-  Pointer<Coordinate> next;
-
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
-    return allocate<Coordinate>().ref
-      ..x = x
-      ..y = y
-      ..next = next;
-  }
-}
-
-main() {}
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect b/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect
deleted file mode 100644
index c1e27d7..0000000
--- a/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect
+++ /dev/null
@@ -1,36 +0,0 @@
-library;
-import self as self;
-import "dart:ffi" as ffi;
-import "dart:core" as core;
-
-import "dart:ffi";
-import "package:ffi/ffi.dart";
-
-class Coordinate extends ffi::Struct {
-  @ffi::Double::•()
-  field core::double* x;
-  @ffi::Double::•()
-  field core::double* y;
-  field ffi::Pointer<self::Coordinate*>* next;
-  static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate*
-    ;
-  abstract member-signature get _addressOf() → core::Object*; -> ffi::Struct::_addressOf
-  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 method main() → dynamic
-  ;
-
-
-Extra constant evaluation status:
-Evaluated: ConstructorInvocation @ org-dartlang-testcase:///ffi_sample.dart:13:4 -> InstanceConstant(const Double{})
-Evaluated: ConstructorInvocation @ org-dartlang-testcase:///ffi_sample.dart:16:4 -> InstanceConstant(const Double{})
-Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.strong.expect b/pkg/front_end/testcases/general/ffi_sample.dart.strong.expect
deleted file mode 100644
index a853421..0000000
--- a/pkg/front_end/testcases/general/ffi_sample.dart.strong.expect
+++ /dev/null
@@ -1,39 +0,0 @@
-library;
-import self as self;
-import "dart:ffi" as ffi;
-import "dart:core" as core;
-import "package:ffi/src/allocation.dart" as all;
-
-import "dart:ffi";
-import "package:ffi/ffi.dart";
-
-class Coordinate extends ffi::Struct {
-  @#C1
-  field core::double* x = null;
-  @#C1
-  field core::double* y = null;
-  field ffi::Pointer<self::Coordinate*>* next = null;
-  static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
-    return let final self::Coordinate* #t1 = ffi::StructPointer|get#ref<self::Coordinate*>(all::allocate<self::Coordinate*>()) in block {
-      #t1.{self::Coordinate::x} = x;
-      #t1.{self::Coordinate::y} = y;
-      #t1.{self::Coordinate::next} = next;
-    } =>#t1;
-  }
-  abstract member-signature get _addressOf() → core::Object*; -> ffi::Struct::_addressOf
-  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 method main() → dynamic {}
-
-constants  {
-  #C1 = ffi::Double {}
-}
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect b/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect
deleted file mode 100644
index 324ae5f..0000000
--- a/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect
+++ /dev/null
@@ -1,70 +0,0 @@
-library;
-import self as self;
-import "dart:core" as core;
-import "dart:ffi" as ffi;
-import "package:ffi/src/allocation.dart" as all;
-
-import "dart:ffi";
-import "package:ffi/ffi.dart";
-
-@#C3
-@#C8
-class Coordinate extends ffi::Struct {
-  @#C3
-  static final field core::int* #sizeOf = (#C11).{core::List::[]}(ffi::_abi());
-  @#C3
-  constructor #fromPointer(dynamic #pointer) → dynamic
-    : super ffi::Struct::_fromPointer(#pointer)
-    ;
-  static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
-    return let final self::Coordinate* #t1 = ffi::StructPointer|get#ref<self::Coordinate*>(all::allocate<self::Coordinate*>()) in block {
-      #t1.{self::Coordinate::x} = x;
-      #t1.{self::Coordinate::y} = y;
-      #t1.{self::Coordinate::next} = next;
-    } =>#t1;
-  }
-  abstract member-signature get _addressOf() → core::Object*; -> ffi::Struct::_addressOf
-  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
-  get x() → core::double*
-    return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C13).{core::List::[]}(ffi::_abi()));
-  set x(core::double* #v) → void
-    return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C13).{core::List::[]}(ffi::_abi()), #v);
-  get y() → core::double*
-    return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C15).{core::List::[]}(ffi::_abi()));
-  set y(core::double* #v) → void
-    return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C15).{core::List::[]}(ffi::_abi()), #v);
-  get next() → ffi::Pointer<self::Coordinate*>*
-    return ffi::_fromAddress<self::Coordinate*>(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C17).{core::List::[]}(ffi::_abi())));
-  set next(ffi::Pointer<self::Coordinate*>* #v) → void
-    return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C17).{core::List::[]}(ffi::_abi()), #v.{ffi::Pointer::address});
-}
-static method main() → dynamic {}
-
-constants  {
-  #C1 = "vm:entry-point"
-  #C2 = null
-  #C3 = core::pragma {name:#C1, options:#C2}
-  #C4 = "vm:ffi:struct-fields"
-  #C5 = TypeLiteralConstant(ffi::Double)
-  #C6 = TypeLiteralConstant(ffi::Pointer<ffi::NativeType>)
-  #C7 = <core::Type>[#C5, #C5, #C6]
-  #C8 = core::pragma {name:#C4, options:#C7}
-  #C9 = 24
-  #C10 = 20
-  #C11 = <core::int*>[#C9, #C10, #C9]
-  #C12 = 0
-  #C13 = <core::int*>[#C12, #C12, #C12]
-  #C14 = 8
-  #C15 = <core::int*>[#C14, #C14, #C14]
-  #C16 = 16
-  #C17 = <core::int*>[#C16, #C16, #C16]
-}
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.textual_outline.expect b/pkg/front_end/testcases/general/ffi_sample.dart.textual_outline.expect
deleted file mode 100644
index eb10d58..0000000
--- a/pkg/front_end/testcases/general/ffi_sample.dart.textual_outline.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-import 'dart:ffi';
-import "package:ffi/ffi.dart";
-
-class Coordinate extends Struct {
-  @Double()
-  double x;
-  @Double()
-  double y;
-  Pointer<Coordinate> next;
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {}
-}
-
-main() {}
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/ffi_sample.dart.textual_outline_modelled.expect
deleted file mode 100644
index 2b9a9f6..0000000
--- a/pkg/front_end/testcases/general/ffi_sample.dart.textual_outline_modelled.expect
+++ /dev/null
@@ -1,13 +0,0 @@
-import "package:ffi/ffi.dart";
-import 'dart:ffi';
-
-class Coordinate extends Struct {
-  Pointer<Coordinate> next;
-  @Double()
-  double x;
-  @Double()
-  double y;
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {}
-}
-
-main() {}
diff --git a/pkg/front_end/testcases/general/flutter_issue64155.dart.outline.expect b/pkg/front_end/testcases/general/flutter_issue64155.dart.outline.expect
index 3587c68..098d875 100644
--- a/pkg/front_end/testcases/general/flutter_issue64155.dart.outline.expect
+++ b/pkg/front_end/testcases/general/flutter_issue64155.dart.outline.expect
@@ -66,6 +66,8 @@
   const synthetic constructor •() → self::_Class1&Object&TestMixin*
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::Response<core::String*>*>* fetch) → asy::Future<core::String*>*
+    return super.{self::TestMixin::test}(fetch);
   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
@@ -87,6 +89,8 @@
   const synthetic constructor •() → self::_Class2&Object&TestMixin*
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::PagingResponse<core::String*>*>* fetch) → asy::Future<core::String*>*
+    return super.{self::TestMixin::test}(fetch);
   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
diff --git a/pkg/front_end/testcases/general/flutter_issue64155.dart.strong.expect b/pkg/front_end/testcases/general/flutter_issue64155.dart.strong.expect
index 299c36f..6c86016 100644
--- a/pkg/front_end/testcases/general/flutter_issue64155.dart.strong.expect
+++ b/pkg/front_end/testcases/general/flutter_issue64155.dart.strong.expect
@@ -86,6 +86,8 @@
   const synthetic constructor •() → self::_Class1&Object&TestMixin*
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::Response<core::String*>*>* fetch) → asy::Future<core::String*>*
+    return super.{self::TestMixin::test}(fetch);
   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
@@ -103,13 +105,15 @@
     ;
   method _test() → dynamic {
     final self::Response<core::String*>* response = new self::Response::•<core::String*>("test");
-    this.{self::TestMixin::test}(asy::Future::value<self::Response<core::String*>*>(response));
+    this.{self::_Class1&Object&TestMixin::test}(asy::Future::value<self::Response<core::String*>*>(response));
   }
 }
 abstract class _Class2&Object&TestMixin = core::Object with self::TestMixin<self::PagingResponse<core::String*>*, core::String*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class2&Object&TestMixin*
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::PagingResponse<core::String*>*>* fetch) → asy::Future<core::String*>*
+    return super.{self::TestMixin::test}(fetch);
   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
@@ -127,7 +131,7 @@
     ;
   method _test() → dynamic {
     final self::PagingResponse<core::String*>* response = new self::PagingResponse::•<core::String*>(new self::PagingResponseData::•<core::String*>(<core::String*>["test"]));
-    this.{self::TestMixin::test}(asy::Future::value<self::PagingResponse<core::String*>*>(response));
+    this.{self::_Class2&Object&TestMixin::test}(asy::Future::value<self::PagingResponse<core::String*>*>(response));
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/flutter_issue64155.dart.strong.transformed.expect b/pkg/front_end/testcases/general/flutter_issue64155.dart.strong.transformed.expect
index 97f034a..f8c0120 100644
--- a/pkg/front_end/testcases/general/flutter_issue64155.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/flutter_issue64155.dart.strong.transformed.expect
@@ -113,16 +113,6 @@
   const synthetic constructor •() → self::_Class1&Object&TestMixin*
     : 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
   method test(generic-covariant-impl asy::Future<self::Response<core::String*>*>* fetch) → asy::Future<core::String*>* /* originally async */ {
     final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
     core::bool* :is_sync = false;
@@ -168,20 +158,6 @@
     :is_sync = true;
     return :async_future;
   }
-}
-class Class1 extends self::_Class1&Object&TestMixin {
-  synthetic constructor •() → self::Class1*
-    : super self::_Class1&Object&TestMixin::•()
-    ;
-  method _test() → dynamic {
-    final self::Response<core::String*>* response = new self::Response::•<core::String*>("test");
-    this.{self::TestMixin::test}(asy::Future::value<self::Response<core::String*>*>(response));
-  }
-}
-abstract class _Class2&Object&TestMixin extends core::Object implements self::TestMixin<self::PagingResponse<core::String*>*, core::String*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
-  const synthetic constructor •() → self::_Class2&Object&TestMixin*
-    : 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
@@ -192,6 +168,20 @@
   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
+}
+class Class1 extends self::_Class1&Object&TestMixin {
+  synthetic constructor •() → self::Class1*
+    : super self::_Class1&Object&TestMixin::•()
+    ;
+  method _test() → dynamic {
+    final self::Response<core::String*>* response = new self::Response::•<core::String*>("test");
+    this.{self::_Class1&Object&TestMixin::test}(asy::Future::value<self::Response<core::String*>*>(response));
+  }
+}
+abstract class _Class2&Object&TestMixin extends core::Object implements self::TestMixin<self::PagingResponse<core::String*>*, core::String*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_Class2&Object&TestMixin*
+    : super core::Object::•()
+    ;
   method test(generic-covariant-impl asy::Future<self::PagingResponse<core::String*>*>* fetch) → asy::Future<core::String*>* /* originally async */ {
     final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
     core::bool* :is_sync = false;
@@ -237,14 +227,24 @@
     :is_sync = true;
     return :async_future;
   }
+  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
 }
 class Class2 extends self::_Class2&Object&TestMixin {
   synthetic constructor •() → self::Class2*
     : super self::_Class2&Object&TestMixin::•()
     ;
   method _test() → dynamic {
-    final self::PagingResponse<core::String*>* response = new self::PagingResponse::•<core::String*>(new self::PagingResponseData::•<core::String*>(<core::String*>["test"]));
-    this.{self::TestMixin::test}(asy::Future::value<self::PagingResponse<core::String*>*>(response));
+    final self::PagingResponse<core::String*>* response = new self::PagingResponse::•<core::String*>(new self::PagingResponseData::•<core::String*>(core::_GrowableList::_literal1<core::String*>("test")));
+    this.{self::_Class2&Object&TestMixin::test}(asy::Future::value<self::PagingResponse<core::String*>*>(response));
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
index ea2e504..cdc7b5c 100644
--- a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
@@ -98,7 +98,7 @@
     core::String* local;
     dynamic untypedLocal;
     {
-      core::Iterator<core::String*>* :sync-for-iterator = <core::String*>[].{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = core::_GrowableList::•<core::String*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -107,7 +107,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -116,7 +116,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -125,7 +125,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -134,7 +134,7 @@
       }
     }
     {
-      core::Iterator<core::double*>* :sync-for-iterator = <core::double*>[].{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = core::_GrowableList::•<core::double*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::double* #t5 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -143,7 +143,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -152,7 +152,7 @@
       }
     }
     {
-      core::Iterator<core::bool*>* :sync-for-iterator = <core::bool*>[].{core::Iterable::iterator};
+      core::Iterator<core::bool*>* :sync-for-iterator = core::_GrowableList::•<core::bool*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::bool* #t7 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -161,7 +161,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -170,7 +170,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t9 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -179,7 +179,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t10 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -189,7 +189,7 @@
     }
     self::C* c = new self::C::•();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t11 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -198,7 +198,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t12 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -207,7 +207,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t13 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -220,7 +220,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t14 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -233,7 +233,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t15 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -250,7 +250,7 @@
     for (main() in []) {}
          ^^^^";
       {
-        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t16 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -267,7 +267,7 @@
     for (var x, y in <int>[]) {
          ^^^";
       {
-        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t17 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -283,7 +283,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t18 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.outline.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.outline.expect
index 587242a..597b9c0 100644
--- a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.outline.expect
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.outline.expect
@@ -58,6 +58,20 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The type 'int' of the getter 'C2.property5' is not assignable to the type 'String' of the inherited setter 'C1.property5'.
+//   int get property5; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:76:10: Context: This is the declaration of the setter 'C1.property5'.
+//   String property5;
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The type 'String' of the getter 'C2.property6' is not assignable to the type 'int' of the inherited setter 'C1.property6'.
+//   String get property6; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:78:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The return type of the method 'C2.property5' is 'int', which does not match the return type, 'String', of the overridden method, 'C1.property5'.
 // Change to a subtype of 'String'.
 //   int get property5; // error
@@ -66,13 +80,6 @@
 //   String property5;
 //          ^
 //
-// pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The type 'int' of the getter 'C2.property5' is not assignable to the type 'String' of the inherited setter 'C1.property5'.
-//   int get property5; // error
-//           ^^^^^^^^^
-// pkg/front_end/testcases/general/getter_vs_setter_type.dart:76:10: Context: This is the declaration of the setter 'C1.property5'.
-//   String property5;
-//          ^^^^^^^^^
-//
 // pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The return type of the method 'C2.property6' is 'String', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   String get property6; // error
@@ -81,13 +88,6 @@
 //   int property6;
 //       ^
 //
-// pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The type 'String' of the getter 'C2.property6' is not assignable to the type 'int' of the inherited setter 'C1.property6'.
-//   String get property6; // error
-//              ^^^^^^^^^
-// pkg/front_end/testcases/general/getter_vs_setter_type.dart:78:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/general/getter_vs_setter_type.dart:115:16: Error: The type 'int' of the inherited getter 'D1.property2' is not assignable to the type 'String' of the inherited setter 'D2.property2'.
 // abstract class D3 implements D1, D2 /* error on property2 and property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.strong.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.strong.expect
index 1515fe4..3a83a52 100644
--- a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.strong.expect
@@ -58,6 +58,20 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The type 'int' of the getter 'C2.property5' is not assignable to the type 'String' of the inherited setter 'C1.property5'.
+//   int get property5; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:76:10: Context: This is the declaration of the setter 'C1.property5'.
+//   String property5;
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The type 'String' of the getter 'C2.property6' is not assignable to the type 'int' of the inherited setter 'C1.property6'.
+//   String get property6; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:78:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The return type of the method 'C2.property5' is 'int', which does not match the return type, 'String', of the overridden method, 'C1.property5'.
 // Change to a subtype of 'String'.
 //   int get property5; // error
@@ -66,13 +80,6 @@
 //   String property5;
 //          ^
 //
-// pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The type 'int' of the getter 'C2.property5' is not assignable to the type 'String' of the inherited setter 'C1.property5'.
-//   int get property5; // error
-//           ^^^^^^^^^
-// pkg/front_end/testcases/general/getter_vs_setter_type.dart:76:10: Context: This is the declaration of the setter 'C1.property5'.
-//   String property5;
-//          ^^^^^^^^^
-//
 // pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The return type of the method 'C2.property6' is 'String', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   String get property6; // error
@@ -81,13 +88,6 @@
 //   int property6;
 //       ^
 //
-// pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The type 'String' of the getter 'C2.property6' is not assignable to the type 'int' of the inherited setter 'C1.property6'.
-//   String get property6; // error
-//              ^^^^^^^^^
-// pkg/front_end/testcases/general/getter_vs_setter_type.dart:78:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/general/getter_vs_setter_type.dart:115:16: Error: The type 'int' of the inherited getter 'D1.property2' is not assignable to the type 'String' of the inherited setter 'D2.property2'.
 // abstract class D3 implements D1, D2 /* error on property2 and property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect
index 47e2d86..4c98331 100644
--- a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect
@@ -19,6 +19,7 @@
   static num get property9 => 0;
   static void set property9(String value) {}
 }
+
 abstract class B1 {
   int get property1;
   int get property2;
@@ -28,6 +29,7 @@
   final String property6;
   B1(this.property4, this.property5, this.property6);
 }
+
 abstract class B2 implements B1 {
   void set property1(int i);
   void set property2(String i);
@@ -36,6 +38,7 @@
   void set property5(String i);
   void set property6(int i);
 }
+
 abstract class C1 {
   void set property1(int i);
   void set property2(String i);
@@ -44,6 +47,7 @@
   String property5;
   int property6;
 }
+
 abstract class C2 implements C1 {
   int get property1;
   int get property2;
@@ -52,18 +56,48 @@
   int get property5;
   String get property6;
 }
+
 abstract class D1 {
   int get property1;
   int get property2;
   String get property3;
 }
+
 abstract class D2 {
   void set property1(int i);
   void set property2(String i);
   void set property3(int i);
 }
+
 abstract class D3 implements D1, D2 {}
+
 abstract class D4 implements D3 {}
-extension Extension<T extends num, S extends T> (){}
-on int (){}
+
+extension Extension<T extends num, S extends T> on int {
+  int get property1 => 0;
+  void set property1(int i) {}
+  num get property2a => 0;
+  void set property2a(int i) {}
+  int get property2b => 0;
+  void set property2b(num i) {}
+  String get property3 => '';
+  void set property3(int i) {}
+  S get property4 => 0;
+  void set property4(S i) {}
+  S get property5a => 0;
+  void set property5a(T i) {}
+  T get property5b => 0;
+  void set property5b(S i) {}
+  String get property6 => '';
+  void set property6(S i) {}
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8a => 0;
+  static void set property8a(num value) {}
+  static num get property8b => 0;
+  static void set property8b(int value) {}
+  static num get property9 => 0;
+  static void set property9(String value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect
index e2ee020..0d0827c 100644
--- a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect
@@ -73,4 +73,31 @@
 
 abstract class D4 implements D3 {}
 
+extension Extension<T extends num, S extends T> on int {
+  S get property4 => 0;
+  S get property5a => 0;
+  String get property3 => '';
+  String get property6 => '';
+  T get property5b => 0;
+  int get property1 => 0;
+  int get property2b => 0;
+  num get property2a => 0;
+  static int get property7 => 0;
+  static int get property8a => 0;
+  static num get property8b => 0;
+  static num get property9 => 0;
+  static void set property7(int value) {}
+  static void set property8a(num value) {}
+  static void set property8b(int value) {}
+  static void set property9(String value) {}
+  void set property1(int i) {}
+  void set property2a(int i) {}
+  void set property2b(num i) {}
+  void set property3(int i) {}
+  void set property4(S i) {}
+  void set property5a(T i) {}
+  void set property5b(S i) {}
+  void set property6(S i) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/hierarchy.dart b/pkg/front_end/testcases/general/hierarchy.dart
new file mode 100644
index 0000000..8c4f658
--- /dev/null
+++ b/pkg/front_end/testcases/general/hierarchy.dart
@@ -0,0 +1,61 @@
+// 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.
+
+abstract class A1 {
+  void extendedClassMember() {}
+  void extendedInterfaceMember();
+}
+
+abstract class A2 {
+  void mixedInClassMember() {}
+  void mixedInInterfaceMember();
+}
+
+abstract class A3 extends A1 with A2 {
+  void declaredClassMember() {}
+  void declaredInterfaceMember();
+}
+
+abstract class A4 = A1 with A2;
+
+abstract class A5 implements A1 {}
+
+class A6 extends A1 implements A1 {}
+
+abstract class B1 {
+  void twiceInterfaceMember() {}
+  void extendedAndImplementedMember() {}
+}
+
+abstract class B2 {
+  void twiceInterfaceMember() {}
+}
+
+abstract class B3 {
+  void extendedAndImplementedMember() {}
+}
+
+abstract class B4 extends B3 implements B1, B2 {}
+
+class B5 extends B4 {}
+
+class B6 extends B3 implements B1, B2 {}
+
+abstract class C1 {
+  void mixedInAndImplementedClassMember() {}
+  void mixedInAndImplementedInterfaceMember();
+}
+
+class C2 {
+  void mixedInAndImplementedClassMember() {}
+  void mixedInAndImplementedInterfaceMember() {}
+}
+
+abstract class C3 with C1 implements C2 {}
+
+class C4 extends C3 {}
+
+class C5 with C1 implements C2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.outline.expect b/pkg/front_end/testcases/general/hierarchy.dart.outline.expect
new file mode 100644
index 0000000..66c5f61
--- /dev/null
+++ b/pkg/front_end/testcases/general/hierarchy.dart.outline.expect
@@ -0,0 +1,320 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: The non-abstract class 'A6' is missing implementations for these members:
+//  - A1.extendedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A6 extends A1 implements A1 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:7:8: Context: 'A1.extendedInterfaceMember' is defined here.
+//   void extendedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:41:7: Error: The non-abstract class 'B5' is missing implementations for these members:
+//  - B1.twiceInterfaceMember
+//  - B2.twiceInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B5 extends B4 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:27:8: Context: 'B1.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:32:8: Context: 'B2.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:43:7: Error: The non-abstract class 'B6' is missing implementations for these members:
+//  - B1.twiceInterfaceMember
+//  - B2.twiceInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B6 extends B3 implements B1, B2 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:27:8: Context: 'B1.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:32:8: Context: 'B2.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:57:7: Error: The non-abstract class 'C4' is missing implementations for these members:
+//  - C1.mixedInAndImplementedInterfaceMember
+//  - C2.mixedInAndImplementedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C4 extends C3 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:47:8: Context: 'C1.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:52:8: Context: 'C2.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:59:7: Error: The non-abstract class 'C5' is missing implementations for these members:
+//  - C1.mixedInAndImplementedInterfaceMember
+//  - C2.mixedInAndImplementedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C5 with C1 implements C2 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:47:8: Context: 'C1.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:52:8: Context: 'C2.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
+// Try removing one of the occurrences.
+// class A6 extends A1 implements A1 {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A1 extends core::Object {
+  synthetic constructor •() → self::A1*
+    ;
+  method extendedClassMember() → void
+    ;
+  abstract method extendedInterfaceMember() → void;
+  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
+}
+abstract class A2 extends core::Object {
+  synthetic constructor •() → self::A2*
+    ;
+  method mixedInClassMember() → void
+    ;
+  abstract method mixedInInterfaceMember() → void;
+  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
+}
+abstract class _A3&A1&A2 = self::A1 with self::A2 /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_A3&A1&A2*
+    : super self::A1::•()
+    ;
+  mixin-super-stub method mixedInClassMember() → void
+    return super.{self::A2::mixedInClassMember}();
+  abstract mixin-stub method mixedInInterfaceMember() → void; -> self::A2::mixedInInterfaceMember
+}
+abstract class A3 extends self::_A3&A1&A2 {
+  synthetic constructor •() → self::A3*
+    ;
+  method declaredClassMember() → void
+    ;
+  abstract method declaredInterfaceMember() → void;
+}
+abstract class A4 = self::A1 with self::A2 {
+  synthetic constructor •() → self::A4*
+    : super self::A1::•()
+    ;
+  mixin-super-stub method mixedInClassMember() → void
+    return super.{self::A2::mixedInClassMember}();
+  abstract mixin-stub method mixedInInterfaceMember() → void; -> self::A2::mixedInInterfaceMember
+}
+abstract class A5 extends core::Object implements self::A1 {
+  synthetic constructor •() → self::A5*
+    ;
+  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
+}
+class A6 extends self::A1 implements self::A1 {
+  synthetic constructor •() → self::A6*
+    ;
+}
+abstract class B1 extends core::Object {
+  synthetic constructor •() → self::B1*
+    ;
+  method twiceInterfaceMember() → void
+    ;
+  method extendedAndImplementedMember() → void
+    ;
+  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
+}
+abstract class B2 extends core::Object {
+  synthetic constructor •() → self::B2*
+    ;
+  method twiceInterfaceMember() → void
+    ;
+  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
+}
+abstract class B3 extends core::Object {
+  synthetic constructor •() → self::B3*
+    ;
+  method extendedAndImplementedMember() → void
+    ;
+  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
+}
+abstract class B4 extends self::B3 implements self::B1, self::B2 {
+  synthetic constructor •() → self::B4*
+    ;
+}
+class B5 extends self::B4 {
+  synthetic constructor •() → self::B5*
+    ;
+}
+class B6 extends self::B3 implements self::B1, self::B2 {
+  synthetic constructor •() → self::B6*
+    ;
+}
+abstract class C1 extends core::Object {
+  synthetic constructor •() → self::C1*
+    ;
+  method mixedInAndImplementedClassMember() → void
+    ;
+  abstract method mixedInAndImplementedInterfaceMember() → void;
+  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
+}
+class C2 extends core::Object {
+  synthetic constructor •() → self::C2*
+    ;
+  method mixedInAndImplementedClassMember() → void
+    ;
+  method mixedInAndImplementedInterfaceMember() → void
+    ;
+  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
+}
+abstract class _C3&Object&C1 = core::Object with self::C1 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C3&Object&C1*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method mixedInAndImplementedClassMember() → void
+    return super.{self::C1::mixedInAndImplementedClassMember}();
+  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
+  abstract mixin-stub method mixedInAndImplementedInterfaceMember() → void; -> self::C1::mixedInAndImplementedInterfaceMember
+}
+abstract class C3 extends self::_C3&Object&C1 implements self::C2 {
+  synthetic constructor •() → self::C3*
+    ;
+}
+class C4 extends self::C3 {
+  synthetic constructor •() → self::C4*
+    ;
+}
+abstract class _C5&Object&C1 = core::Object with self::C1 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C5&Object&C1*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method mixedInAndImplementedClassMember() → void
+    return super.{self::C1::mixedInAndImplementedClassMember}();
+  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
+  abstract mixin-stub method mixedInAndImplementedInterfaceMember() → void; -> self::C1::mixedInAndImplementedInterfaceMember
+}
+class C5 extends self::_C5&Object&C1 implements self::C2 {
+  synthetic constructor •() → self::C5*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.strong.expect b/pkg/front_end/testcases/general/hierarchy.dart.strong.expect
new file mode 100644
index 0000000..3c3d062
--- /dev/null
+++ b/pkg/front_end/testcases/general/hierarchy.dart.strong.expect
@@ -0,0 +1,325 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: The non-abstract class 'A6' is missing implementations for these members:
+//  - A1.extendedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A6 extends A1 implements A1 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:7:8: Context: 'A1.extendedInterfaceMember' is defined here.
+//   void extendedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:41:7: Error: The non-abstract class 'B5' is missing implementations for these members:
+//  - B1.twiceInterfaceMember
+//  - B2.twiceInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B5 extends B4 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:27:8: Context: 'B1.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:32:8: Context: 'B2.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:43:7: Error: The non-abstract class 'B6' is missing implementations for these members:
+//  - B1.twiceInterfaceMember
+//  - B2.twiceInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B6 extends B3 implements B1, B2 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:27:8: Context: 'B1.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:32:8: Context: 'B2.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:57:7: Error: The non-abstract class 'C4' is missing implementations for these members:
+//  - C1.mixedInAndImplementedInterfaceMember
+//  - C2.mixedInAndImplementedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C4 extends C3 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:47:8: Context: 'C1.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:52:8: Context: 'C2.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:59:7: Error: The non-abstract class 'C5' is missing implementations for these members:
+//  - C1.mixedInAndImplementedInterfaceMember
+//  - C2.mixedInAndImplementedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C5 with C1 implements C2 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:47:8: Context: 'C1.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:52:8: Context: 'C2.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
+// Try removing one of the occurrences.
+// class A6 extends A1 implements A1 {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A1 extends core::Object {
+  synthetic constructor •() → self::A1*
+    : super core::Object::•()
+    ;
+  method extendedClassMember() → void {}
+  abstract method extendedInterfaceMember() → void;
+  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
+}
+abstract class A2 extends core::Object {
+  synthetic constructor •() → self::A2*
+    : super core::Object::•()
+    ;
+  method mixedInClassMember() → void {}
+  abstract method mixedInInterfaceMember() → void;
+  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
+}
+abstract class _A3&A1&A2 = self::A1 with self::A2 /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_A3&A1&A2*
+    : super self::A1::•()
+    ;
+  mixin-super-stub method mixedInClassMember() → void
+    return super.{self::A2::mixedInClassMember}();
+  abstract mixin-stub method mixedInInterfaceMember() → void; -> self::A2::mixedInInterfaceMember
+}
+abstract class A3 extends self::_A3&A1&A2 {
+  synthetic constructor •() → self::A3*
+    : super self::_A3&A1&A2::•()
+    ;
+  method declaredClassMember() → void {}
+  abstract method declaredInterfaceMember() → void;
+}
+abstract class A4 = self::A1 with self::A2 {
+  synthetic constructor •() → self::A4*
+    : super self::A1::•()
+    ;
+  mixin-super-stub method mixedInClassMember() → void
+    return super.{self::A2::mixedInClassMember}();
+  abstract mixin-stub method mixedInInterfaceMember() → void; -> self::A2::mixedInInterfaceMember
+}
+abstract class A5 extends core::Object implements self::A1 {
+  synthetic constructor •() → self::A5*
+    : 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
+}
+class A6 extends self::A1 implements self::A1 {
+  synthetic constructor •() → self::A6*
+    : super self::A1::•()
+    ;
+}
+abstract class B1 extends core::Object {
+  synthetic constructor •() → self::B1*
+    : super core::Object::•()
+    ;
+  method twiceInterfaceMember() → void {}
+  method extendedAndImplementedMember() → void {}
+  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
+}
+abstract class B2 extends core::Object {
+  synthetic constructor •() → self::B2*
+    : super core::Object::•()
+    ;
+  method twiceInterfaceMember() → void {}
+  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
+}
+abstract class B3 extends core::Object {
+  synthetic constructor •() → self::B3*
+    : super core::Object::•()
+    ;
+  method extendedAndImplementedMember() → void {}
+  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
+}
+abstract class B4 extends self::B3 implements self::B1, self::B2 {
+  synthetic constructor •() → self::B4*
+    : super self::B3::•()
+    ;
+}
+class B5 extends self::B4 {
+  synthetic constructor •() → self::B5*
+    : super self::B4::•()
+    ;
+}
+class B6 extends self::B3 implements self::B1, self::B2 {
+  synthetic constructor •() → self::B6*
+    : super self::B3::•()
+    ;
+}
+abstract class C1 extends core::Object {
+  synthetic constructor •() → self::C1*
+    : super core::Object::•()
+    ;
+  method mixedInAndImplementedClassMember() → void {}
+  abstract method mixedInAndImplementedInterfaceMember() → void;
+  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
+}
+class C2 extends core::Object {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  method mixedInAndImplementedClassMember() → void {}
+  method mixedInAndImplementedInterfaceMember() → void {}
+  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
+}
+abstract class _C3&Object&C1 = core::Object with self::C1 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C3&Object&C1*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method mixedInAndImplementedClassMember() → void
+    return super.{self::C1::mixedInAndImplementedClassMember}();
+  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
+  abstract mixin-stub method mixedInAndImplementedInterfaceMember() → void; -> self::C1::mixedInAndImplementedInterfaceMember
+}
+abstract class C3 extends self::_C3&Object&C1 implements self::C2 {
+  synthetic constructor •() → self::C3*
+    : super self::_C3&Object&C1::•()
+    ;
+}
+class C4 extends self::C3 {
+  synthetic constructor •() → self::C4*
+    : super self::C3::•()
+    ;
+}
+abstract class _C5&Object&C1 = core::Object with self::C1 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C5&Object&C1*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method mixedInAndImplementedClassMember() → void
+    return super.{self::C1::mixedInAndImplementedClassMember}();
+  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
+  abstract mixin-stub method mixedInAndImplementedInterfaceMember() → void; -> self::C1::mixedInAndImplementedInterfaceMember
+}
+class C5 extends self::_C5&Object&C1 implements self::C2 {
+  synthetic constructor •() → self::C5*
+    : super self::_C5&Object&C1::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.strong.transformed.expect b/pkg/front_end/testcases/general/hierarchy.dart.strong.transformed.expect
new file mode 100644
index 0000000..ec7dd97
--- /dev/null
+++ b/pkg/front_end/testcases/general/hierarchy.dart.strong.transformed.expect
@@ -0,0 +1,341 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: The non-abstract class 'A6' is missing implementations for these members:
+//  - A1.extendedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class A6 extends A1 implements A1 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:7:8: Context: 'A1.extendedInterfaceMember' is defined here.
+//   void extendedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:41:7: Error: The non-abstract class 'B5' is missing implementations for these members:
+//  - B1.twiceInterfaceMember
+//  - B2.twiceInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B5 extends B4 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:27:8: Context: 'B1.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:32:8: Context: 'B2.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:43:7: Error: The non-abstract class 'B6' is missing implementations for these members:
+//  - B1.twiceInterfaceMember
+//  - B2.twiceInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class B6 extends B3 implements B1, B2 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:27:8: Context: 'B1.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:32:8: Context: 'B2.twiceInterfaceMember' is defined here.
+//   void twiceInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:57:7: Error: The non-abstract class 'C4' is missing implementations for these members:
+//  - C1.mixedInAndImplementedInterfaceMember
+//  - C2.mixedInAndImplementedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C4 extends C3 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:47:8: Context: 'C1.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:52:8: Context: 'C2.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:59:7: Error: The non-abstract class 'C5' is missing implementations for these members:
+//  - C1.mixedInAndImplementedInterfaceMember
+//  - C2.mixedInAndImplementedInterfaceMember
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C5 with C1 implements C2 {}
+//       ^^
+// pkg/front_end/testcases/general/hierarchy.dart:47:8: Context: 'C1.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/hierarchy.dart:52:8: Context: 'C2.mixedInAndImplementedInterfaceMember' is defined here.
+//   void mixedInAndImplementedInterfaceMember() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/hierarchy.dart:24:7: Error: 'A1' can't be used in both 'extends' and 'implements' clauses.
+// Try removing one of the occurrences.
+// class A6 extends A1 implements A1 {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A1 extends core::Object {
+  synthetic constructor •() → self::A1*
+    : super core::Object::•()
+    ;
+  method extendedClassMember() → void {}
+  abstract method extendedInterfaceMember() → void;
+  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
+}
+abstract class A2 extends core::Object {
+  synthetic constructor •() → self::A2*
+    : super core::Object::•()
+    ;
+  method mixedInClassMember() → void {}
+  abstract method mixedInInterfaceMember() → void;
+  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
+}
+abstract class _A3&A1&A2 extends self::A1 implements self::A2 /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_A3&A1&A2*
+    : super self::A1::•()
+    ;
+  method mixedInClassMember() → void {}
+  abstract method mixedInInterfaceMember() → void;
+  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
+}
+abstract class A3 extends self::_A3&A1&A2 {
+  synthetic constructor •() → self::A3*
+    : super self::_A3&A1&A2::•()
+    ;
+  method declaredClassMember() → void {}
+  abstract method declaredInterfaceMember() → void;
+}
+abstract class A4 extends self::A1 implements self::A2 /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::A4*
+    : super self::A1::•()
+    ;
+  method mixedInClassMember() → void {}
+  abstract method mixedInInterfaceMember() → void;
+  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
+}
+abstract class A5 extends core::Object implements self::A1 {
+  synthetic constructor •() → self::A5*
+    : 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
+}
+class A6 extends self::A1 implements self::A1 {
+  synthetic constructor •() → self::A6*
+    : super self::A1::•()
+    ;
+}
+abstract class B1 extends core::Object {
+  synthetic constructor •() → self::B1*
+    : super core::Object::•()
+    ;
+  method twiceInterfaceMember() → void {}
+  method extendedAndImplementedMember() → void {}
+  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
+}
+abstract class B2 extends core::Object {
+  synthetic constructor •() → self::B2*
+    : super core::Object::•()
+    ;
+  method twiceInterfaceMember() → void {}
+  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
+}
+abstract class B3 extends core::Object {
+  synthetic constructor •() → self::B3*
+    : super core::Object::•()
+    ;
+  method extendedAndImplementedMember() → void {}
+  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
+}
+abstract class B4 extends self::B3 implements self::B1, self::B2 {
+  synthetic constructor •() → self::B4*
+    : super self::B3::•()
+    ;
+}
+class B5 extends self::B4 {
+  synthetic constructor •() → self::B5*
+    : super self::B4::•()
+    ;
+}
+class B6 extends self::B3 implements self::B1, self::B2 {
+  synthetic constructor •() → self::B6*
+    : super self::B3::•()
+    ;
+}
+abstract class C1 extends core::Object {
+  synthetic constructor •() → self::C1*
+    : super core::Object::•()
+    ;
+  method mixedInAndImplementedClassMember() → void {}
+  abstract method mixedInAndImplementedInterfaceMember() → void;
+  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
+}
+class C2 extends core::Object {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  method mixedInAndImplementedClassMember() → void {}
+  method mixedInAndImplementedInterfaceMember() → void {}
+  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
+}
+abstract class _C3&Object&C1 extends core::Object implements self::C1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C3&Object&C1*
+    : super core::Object::•()
+    ;
+  method mixedInAndImplementedClassMember() → void {}
+  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
+  abstract method mixedInAndImplementedInterfaceMember() → void;
+}
+abstract class C3 extends self::_C3&Object&C1 implements self::C2 {
+  synthetic constructor •() → self::C3*
+    : super self::_C3&Object&C1::•()
+    ;
+}
+class C4 extends self::C3 {
+  synthetic constructor •() → self::C4*
+    : super self::C3::•()
+    ;
+}
+abstract class _C5&Object&C1 extends core::Object implements self::C1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C5&Object&C1*
+    : super core::Object::•()
+    ;
+  method mixedInAndImplementedClassMember() → void {}
+  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
+  abstract method mixedInAndImplementedInterfaceMember() → void;
+}
+class C5 extends self::_C5&Object&C1 implements self::C2 {
+  synthetic constructor •() → self::C5*
+    : super self::_C5&Object&C1::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.textual_outline.expect b/pkg/front_end/testcases/general/hierarchy.dart.textual_outline.expect
new file mode 100644
index 0000000..15a7cc5
--- /dev/null
+++ b/pkg/front_end/testcases/general/hierarchy.dart.textual_outline.expect
@@ -0,0 +1,57 @@
+abstract class A1 {
+  void extendedClassMember() {}
+  void extendedInterfaceMember();
+}
+
+abstract class A2 {
+  void mixedInClassMember() {}
+  void mixedInInterfaceMember();
+}
+
+abstract class A3 extends A1 with A2 {
+  void declaredClassMember() {}
+  void declaredInterfaceMember();
+}
+
+abstract class A4 = A1 with A2;
+
+abstract class A5 implements A1 {}
+
+class A6 extends A1 implements A1 {}
+
+abstract class B1 {
+  void twiceInterfaceMember() {}
+  void extendedAndImplementedMember() {}
+}
+
+abstract class B2 {
+  void twiceInterfaceMember() {}
+}
+
+abstract class B3 {
+  void extendedAndImplementedMember() {}
+}
+
+abstract class B4 extends B3 implements B1, B2 {}
+
+class B5 extends B4 {}
+
+class B6 extends B3 implements B1, B2 {}
+
+abstract class C1 {
+  void mixedInAndImplementedClassMember() {}
+  void mixedInAndImplementedInterfaceMember();
+}
+
+class C2 {
+  void mixedInAndImplementedClassMember() {}
+  void mixedInAndImplementedInterfaceMember() {}
+}
+
+abstract class C3 with C1 implements C2 {}
+
+class C4 extends C3 {}
+
+class C5 with C1 implements C2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/hierarchy.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/hierarchy.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..916bcc2
--- /dev/null
+++ b/pkg/front_end/testcases/general/hierarchy.dart.textual_outline_modelled.expect
@@ -0,0 +1,57 @@
+abstract class A1 {
+  void extendedClassMember() {}
+  void extendedInterfaceMember();
+}
+
+abstract class A2 {
+  void mixedInClassMember() {}
+  void mixedInInterfaceMember();
+}
+
+abstract class A3 extends A1 with A2 {
+  void declaredClassMember() {}
+  void declaredInterfaceMember();
+}
+
+abstract class A4 = A1 with A2;
+
+abstract class A5 implements A1 {}
+
+abstract class B1 {
+  void extendedAndImplementedMember() {}
+  void twiceInterfaceMember() {}
+}
+
+abstract class B2 {
+  void twiceInterfaceMember() {}
+}
+
+abstract class B3 {
+  void extendedAndImplementedMember() {}
+}
+
+abstract class B4 extends B3 implements B1, B2 {}
+
+abstract class C1 {
+  void mixedInAndImplementedClassMember() {}
+  void mixedInAndImplementedInterfaceMember();
+}
+
+abstract class C3 with C1 implements C2 {}
+
+class A6 extends A1 implements A1 {}
+
+class B5 extends B4 {}
+
+class B6 extends B3 implements B1, B2 {}
+
+class C2 {
+  void mixedInAndImplementedClassMember() {}
+  void mixedInAndImplementedInterfaceMember() {}
+}
+
+class C4 extends C3 {}
+
+class C5 with C1 implements C2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/if_null_in_list_literal.dart.strong.transformed.expect b/pkg/front_end/testcases/general/if_null_in_list_literal.dart.strong.transformed.expect
index 0cc41e9..188b5b3 100644
--- a/pkg/front_end/testcases/general/if_null_in_list_literal.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/if_null_in_list_literal.dart.strong.transformed.expect
@@ -5,5 +5,5 @@
 static method main() → dynamic {
   core::Object* a;
   core::Object* b;
-  return <core::Object*>[let final core::Object* #t1 = a in #t1.{core::Object::==}(null) ?{core::Object*} b : #t1];
+  return core::_GrowableList::_literal1<core::Object*>(let final core::Object* #t1 = a in #t1.{core::Object::==}(null) ?{core::Object*} b : #t1);
 }
diff --git a/pkg/front_end/testcases/general/implicit_constructor_02.dart b/pkg/front_end/testcases/general/implicit_constructor_02.dart
new file mode 100644
index 0000000..818c138
--- /dev/null
+++ b/pkg/front_end/testcases/general/implicit_constructor_02.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// Derived from co19/Language/Mixins/Mixin_Application/implicit_constructor_t02
+
+class A {
+  bool v1;
+  num v2;
+  A(bool this.v1, num this.v2);
+}
+
+class M1 {
+  num v2 = -1;
+}
+
+class C = A with M1;
+
+main() {
+  C c = new C(true, 2);
+  expect(true, c.v1);
+  expect(-1, c.v2);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/general/implicit_constructor_02.dart.outline.expect b/pkg/front_end/testcases/general/implicit_constructor_02.dart.outline.expect
new file mode 100644
index 0000000..eee145b
--- /dev/null
+++ b/pkg/front_end/testcases/general/implicit_constructor_02.dart.outline.expect
@@ -0,0 +1,48 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::bool* v1;
+  field core::num* v2;
+  constructor •(core::bool* v1, core::num* v2) → self::A*
+    ;
+  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
+}
+class M1 extends core::Object {
+  field core::num* v2;
+  synthetic constructor •() → self::M1*
+    ;
+  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
+}
+class C = self::A with self::M1 {
+  synthetic constructor •(core::bool* v1, core::num* v2) → self::C*
+    : super self::A::•(v1, v2)
+    ;
+  mixin-super-stub get v2() → core::num*
+    return super.{self::M1::v2};
+  mixin-super-stub set v2(core::num* value) → void
+    return super.{self::M1::v2} = value;
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/implicit_constructor_02.dart.strong.expect b/pkg/front_end/testcases/general/implicit_constructor_02.dart.strong.expect
new file mode 100644
index 0000000..ceafb22f
--- /dev/null
+++ b/pkg/front_end/testcases/general/implicit_constructor_02.dart.strong.expect
@@ -0,0 +1,55 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::bool* v1;
+  field core::num* v2;
+  constructor •(core::bool* v1, core::num* v2) → self::A*
+    : self::A::v1 = v1, self::A::v2 = v2, 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
+}
+class M1 extends core::Object {
+  field core::num* v2 = 1.{core::int::unary-}();
+  synthetic constructor •() → self::M1*
+    : 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
+}
+class C = self::A with self::M1 {
+  synthetic constructor •(core::bool* v1, core::num* v2) → self::C*
+    : super self::A::•(v1, v2)
+    ;
+  mixin-super-stub get v2() → core::num*
+    return super.{self::M1::v2};
+  mixin-super-stub set v2(core::num* value) → void
+    return super.{self::M1::v2} = value;
+}
+static method main() → dynamic {
+  self::C* c = new self::C::•(true, 2);
+  self::expect(true, c.{self::A::v1});
+  self::expect(1.{core::int::unary-}(), c.{self::C::v2});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/general/implicit_constructor_02.dart.strong.transformed.expect b/pkg/front_end/testcases/general/implicit_constructor_02.dart.strong.transformed.expect
new file mode 100644
index 0000000..35f26e3
--- /dev/null
+++ b/pkg/front_end/testcases/general/implicit_constructor_02.dart.strong.transformed.expect
@@ -0,0 +1,69 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::bool* v1;
+  field core::num* v2;
+  constructor •(core::bool* v1, core::num* v2) → self::A*
+    : self::A::v1 = v1, self::A::v2 = v2, 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
+}
+class M1 extends core::Object {
+  field core::num* v2 = 1.{core::int::unary-}();
+  synthetic constructor •() → self::M1*
+    : 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
+}
+class C extends self::A implements self::M1 /*isEliminatedMixin*/  {
+  field core::num* v2 = 1.{core::int::unary-}();
+  synthetic constructor •(core::bool* v1, core::num* v2) → self::C*
+    : super self::A::•(v1, v2)
+    ;
+  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 method main() → dynamic {
+  self::C* c = new self::C::•(true, 2);
+  self::expect(true, c.{self::A::v1});
+  self::expect(1.{core::int::unary-}(), c.{self::C::v2});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///implicit_constructor_02.dart:14:12 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///implicit_constructor_02.dart:14:12 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///implicit_constructor_02.dart:22:10 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 22, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/implicit_constructor_02.dart.textual_outline.expect b/pkg/front_end/testcases/general/implicit_constructor_02.dart.textual_outline.expect
new file mode 100644
index 0000000..9b741d7
--- /dev/null
+++ b/pkg/front_end/testcases/general/implicit_constructor_02.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+class A {
+  bool v1;
+  num v2;
+  A(bool this.v1, num this.v2);
+}
+
+class M1 {
+  num v2 = -1;
+}
+
+class C = A with M1;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/general/implicit_constructor_02.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/implicit_constructor_02.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fca520a
--- /dev/null
+++ b/pkg/front_end/testcases/general/implicit_constructor_02.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class A {
+  A(bool this.v1, num this.v2);
+  bool v1;
+  num v2;
+}
+
+class C = A with M1;
+
+class M1 {
+  num v2 = -1;
+}
+
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/implicit_new.dart.strong.transformed.expect b/pkg/front_end/testcases/general/implicit_new.dart.strong.transformed.expect
index ee6950c..e510a2f 100644
--- a/pkg/front_end/testcases/general/implicit_new.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/implicit_new.dart.strong.transformed.expect
@@ -86,8 +86,8 @@
   self::f(new self::Foo::•());
   self::f(new self::Bar::named());
   self::f(new self::Bar::named());
-  core::List<core::Object*>* l = <core::Object*>[new self::Foo::•(), new self::Bar::named()];
-  l = <core::Object*>[new self::Foo::•(), new self::Bar::named()];
+  core::List<core::Object*>* l = core::_GrowableList::_literal2<core::Object*>(new self::Foo::•(), new self::Bar::named());
+  l = core::_GrowableList::_literal2<core::Object*>(new self::Foo::•(), new self::Bar::named());
   core::Map<core::String*, core::Object*>* m = <core::String*, core::Object*>{"foo": new self::Foo::•(), "bar": new self::Bar::named()};
   m = <core::String*, core::Object*>{"foo": new self::Foo::•(), "bar": new self::Bar::named()};
   self::IndexTester* i = new self::IndexTester::•();
diff --git a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
index 8c879e7..bd4c14f 100644
--- a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field2; // error
 //       ^^^^^^
@@ -13,7 +13,7 @@
 //   var field2 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field4 = 0; // error
 //       ^^^^^^
@@ -24,7 +24,7 @@
 //   var field4 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field6; // error
 //       ^^^^^^
@@ -35,7 +35,7 @@
 //   String field6;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field8 = 0; // error
 //       ^^^^^^
@@ -46,7 +46,7 @@
 //   String field8;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field11; // error
 //       ^^^^^^^
@@ -57,7 +57,7 @@
 //   S field11;
 //     ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
@@ -68,7 +68,7 @@
 //   String field17;
 //          ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field18; // error
 //       ^^^^^^^
@@ -79,7 +79,7 @@
 //   var field18 = '';
 //       ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field2; // error
 //       ^^^^^^
@@ -90,7 +90,7 @@
 //   var field2 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field4 = 0; // error
 //       ^^^^^^
@@ -101,7 +101,7 @@
 //   var field4 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field6; // error
 //       ^^^^^^
@@ -112,7 +112,7 @@
 //   String field6;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field8 = 0; // error
 //       ^^^^^^
@@ -123,7 +123,7 @@
 //   String field8;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
@@ -134,7 +134,7 @@
 //   String field17;
 //          ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field18; // error
 //       ^^^^^^^
diff --git a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
index 0400159..475cdb3 100644
--- a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field2; // error
 //       ^^^^^^
@@ -13,7 +13,7 @@
 //   var field2 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field4 = 0; // error
 //       ^^^^^^
@@ -24,7 +24,7 @@
 //   var field4 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field6; // error
 //       ^^^^^^
@@ -35,7 +35,7 @@
 //   String field6;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field8 = 0; // error
 //       ^^^^^^
@@ -46,7 +46,7 @@
 //   String field8;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field11; // error
 //       ^^^^^^^
@@ -57,7 +57,7 @@
 //   S field11;
 //     ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
@@ -68,7 +68,7 @@
 //   String field17;
 //          ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field18; // error
 //       ^^^^^^^
@@ -79,7 +79,7 @@
 //   var field18 = '';
 //       ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field2; // error
 //       ^^^^^^
@@ -90,7 +90,7 @@
 //   var field2 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field4 = 0; // error
 //       ^^^^^^
@@ -101,7 +101,7 @@
 //   var field4 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field6; // error
 //       ^^^^^^
@@ -112,7 +112,7 @@
 //   String field6;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field8 = 0; // error
 //       ^^^^^^
@@ -123,7 +123,7 @@
 //   String field8;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
@@ -134,7 +134,7 @@
 //   String field17;
 //          ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the overridden members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var field18; // error
 //       ^^^^^^^
diff --git a/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.outline.expect b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.outline.expect
index f522e20..2bf067c 100644
--- a/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.outline.expect
+++ b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.outline.expect
@@ -35,6 +35,7 @@
   synthetic constructor •() → self::_Class&Base&MixinA*
     : super self::Base::•()
     ;
+  abstract mixin-stub method method(core::Object* t) → dynamic; -> self::MixinA::method
 }
 abstract class Class extends self::_Class&Base&MixinA {
   synthetic constructor •() → self::Class*
@@ -104,6 +105,7 @@
   synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin*
     : super self::YamlNode::•()
     ;
+  abstract mixin-stub operator [](core::Object* key) → dynamic; -> self::MapMixin::[]
 }
 abstract class _YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin = self::_YamlMap&YamlNode&MapMixin with self::UnmodifiableMapMixin<dynamic, dynamic> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin*
diff --git a/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.expect b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.expect
index 1f40ec1..bf294a6 100644
--- a/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.expect
@@ -37,6 +37,7 @@
   synthetic constructor •() → self::_Class&Base&MixinA*
     : super self::Base::•()
     ;
+  abstract mixin-stub method method(core::Object* t) → dynamic; -> self::MixinA::method
 }
 abstract class Class extends self::_Class&Base&MixinA {
   synthetic constructor •() → self::Class*
@@ -110,6 +111,7 @@
   synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin*
     : super self::YamlNode::•()
     ;
+  abstract mixin-stub operator [](core::Object* key) → dynamic; -> self::MapMixin::[]
 }
 abstract class _YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin = self::_YamlMap&YamlNode&MapMixin with self::UnmodifiableMapMixin<dynamic, dynamic> /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin*
diff --git a/pkg/front_end/testcases/general/invalid_cast.dart.outline.expect b/pkg/front_end/testcases/general/invalid_cast.dart.outline.expect
index cc0f041..c096df0 100644
--- a/pkg/front_end/testcases/general/invalid_cast.dart.outline.expect
+++ b/pkg/front_end/testcases/general/invalid_cast.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::fact2];
+  static final field dynamic _redirecting# = <dynamic>[self::C::fact2];
   constructor •() → self::C*
     ;
   constructor nonFact() → self::C*
diff --git a/pkg/front_end/testcases/general/invalid_cast.dart.strong.expect b/pkg/front_end/testcases/general/invalid_cast.dart.strong.expect
index fb2b5bb..8c699de 100644
--- a/pkg/front_end/testcases/general/invalid_cast.dart.strong.expect
+++ b/pkg/front_end/testcases/general/invalid_cast.dart.strong.expect
@@ -65,7 +65,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::fact2];
+  static final field dynamic _redirecting# = <dynamic>[self::C::fact2];
   constructor •() → self::C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/invalid_cast.dart.strong.transformed.expect b/pkg/front_end/testcases/general/invalid_cast.dart.strong.transformed.expect
index 0ab1a94..7701181 100644
--- a/pkg/front_end/testcases/general/invalid_cast.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/invalid_cast.dart.strong.transformed.expect
@@ -65,7 +65,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::fact2];
+  static final field dynamic _redirecting# = <dynamic>[self::C::fact2];
   constructor •() → self::C*
     : super core::Object::•()
     ;
@@ -104,7 +104,7 @@
  - 'Object' is from 'dart:core'.
 Change the type of the list literal or the context in which it is used.
   List<int> a = <Object>[];
-                        ^" in <core::Object*>[];
+                        ^" in core::_GrowableList::•<core::Object*>(0);
   core::Map<core::int*, core::String*>* b = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/invalid_cast.dart:21:40: Error: The map literal type 'Map<Object, String>' isn't of expected type 'Map<int, String>'.
  - 'Map' is from 'dart:core'.
  - 'Object' is from 'dart:core'.
@@ -154,7 +154,7 @@
 }
 static method ok() → dynamic {
   function localFunction(core::int* i) → void {}
-  core::List<core::int*>* a = <core::int*>[];
+  core::List<core::int*>* a = core::_GrowableList::•<core::int*>(0);
   core::Map<core::int*, core::String*>* b = <core::int*, core::String*>{};
   core::Map<core::int*, core::String*>* c = <core::int*, core::String*>{};
   (core::int*) →* core::int* d = (core::int* i) → core::int* => i;
diff --git a/pkg/front_end/testcases/general/invalid_operator.dart.outline.expect b/pkg/front_end/testcases/general/invalid_operator.dart.outline.expect
index 9ee095c..63dfbeb 100644
--- a/pkg/front_end/testcases/general/invalid_operator.dart.outline.expect
+++ b/pkg/front_end/testcases/general/invalid_operator.dart.outline.expect
@@ -560,6 +560,14 @@
 //   operator ~<T>() => true;
 //              ^
 //
+// pkg/front_end/testcases/general/invalid_operator.dart:137:12: Error: Can't infer types for '==' as the overridden members don't have a combined signature.
+// Try adding explicit types.
+//   operator ==<T>(a) => true;
+//            ^^
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:17: Context: This is one of the overridden members.
+//   bool operator ==(Object other) native "Object_equals";
+//                 ^^
+//
 // pkg/front_end/testcases/general/invalid_operator.dart:6:12: Error: The method 'Operators1.==' has fewer positional arguments than those of overridden method 'Object.=='.
 //   operator ==() => true;
 //            ^
@@ -588,14 +596,6 @@
 //   bool operator ==(Object other) native "Object_equals";
 //                 ^
 //
-// pkg/front_end/testcases/general/invalid_operator.dart:137:12: Error: The return type of the method 'Operators7.==' is 'dynamic', which does not match the return type, 'bool', of the overridden method, 'Object.=='.
-// Change to a subtype of 'bool'.
-//   operator ==<T>(a) => true;
-//            ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:21:17: Context: This is the overridden method ('==').
-//   bool operator ==(Object other) native "Object_equals";
-//                 ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -906,7 +906,7 @@
 class Operators7 extends core::Object {
   synthetic constructor •() → self::Operators7*
     ;
-  operator ==<T extends core::Object* = dynamic>(dynamic a) → dynamic
+  operator ==<T extends core::Object* = dynamic>(invalid-type a) → invalid-type
     ;
   operator ><T extends core::Object* = dynamic>(dynamic a) → dynamic
     ;
diff --git a/pkg/front_end/testcases/general/invalid_operator.dart.strong.expect b/pkg/front_end/testcases/general/invalid_operator.dart.strong.expect
index 1c0ff49..c65d2ea 100644
--- a/pkg/front_end/testcases/general/invalid_operator.dart.strong.expect
+++ b/pkg/front_end/testcases/general/invalid_operator.dart.strong.expect
@@ -560,6 +560,14 @@
 //   operator ~<T>() => true;
 //              ^
 //
+// pkg/front_end/testcases/general/invalid_operator.dart:137:12: Error: Can't infer types for '==' as the overridden members don't have a combined signature.
+// Try adding explicit types.
+//   operator ==<T>(a) => true;
+//            ^^
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:17: Context: This is one of the overridden members.
+//   bool operator ==(Object other) native "Object_equals";
+//                 ^^
+//
 // pkg/front_end/testcases/general/invalid_operator.dart:6:12: Error: The method 'Operators1.==' has fewer positional arguments than those of overridden method 'Object.=='.
 //   operator ==() => true;
 //            ^
@@ -588,14 +596,6 @@
 //   bool operator ==(Object other) native "Object_equals";
 //                 ^
 //
-// pkg/front_end/testcases/general/invalid_operator.dart:137:12: Error: The return type of the method 'Operators7.==' is 'dynamic', which does not match the return type, 'bool', of the overridden method, 'Object.=='.
-// Change to a subtype of 'bool'.
-//   operator ==<T>(a) => true;
-//            ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:21:17: Context: This is the overridden method ('==').
-//   bool operator ==(Object other) native "Object_equals";
-//                 ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -913,7 +913,7 @@
   synthetic constructor •() → self::Operators7*
     : super core::Object::•()
     ;
-  operator ==<T extends core::Object* = dynamic>(dynamic a) → dynamic
+  operator ==<T extends core::Object* = dynamic>(invalid-type a) → invalid-type
     return true;
   operator ><T extends core::Object* = dynamic>(dynamic a) → dynamic
     return true;
diff --git a/pkg/front_end/testcases/general/invocations.dart.strong.expect b/pkg/front_end/testcases/general/invocations.dart.strong.expect
index 4be4068..2e5cbcb 100644
--- a/pkg/front_end/testcases/general/invocations.dart.strong.expect
+++ b/pkg/front_end/testcases/general/invocations.dart.strong.expect
@@ -59,11 +59,11 @@
       print(\"Hello, World!\") +
       ^" in core::print("Hello, World!")).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:14:7: Error: Method not found: 'z'.
       z(\"Hello, World!\") +
-      ^" as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:15:7: Error: Getter not found: 'z'.
+      ^" as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:15:7: Error: Getter not found: 'z'.
       z.print(\"Hello, World!\") +
-      ^".print("Hello, World!") as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:16:7: Error: Getter not found: 'y'.
+      ^".print("Hello, World!") as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:16:7: Error: Getter not found: 'y'.
       y.z.print(\"Hello, World!\") +
-      ^".z.print("Hello, World!") as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:17:7: Error: Getter not found: 'x'.
+      ^".z.print("Hello, World!") as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:17:7: Error: Getter not found: 'x'.
       x.y.z.print(\"Hello, World!\");
-      ^".y.z.print("Hello, World!") as{TypeError,ForDynamic} core::num);
+      ^".y.z.print("Hello, World!") as{TypeError,ForDynamic} core::num*);
 }
diff --git a/pkg/front_end/testcases/general/invocations.dart.strong.transformed.expect b/pkg/front_end/testcases/general/invocations.dart.strong.transformed.expect
index ccec25c..7d45504 100644
--- a/pkg/front_end/testcases/general/invocations.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/invocations.dart.strong.transformed.expect
@@ -61,9 +61,9 @@
       z(\"Hello, World!\") +
       ^").{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:15:7: Error: Getter not found: 'z'.
       z.print(\"Hello, World!\") +
-      ^".print("Hello, World!") as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:16:7: Error: Getter not found: 'y'.
+      ^".print("Hello, World!") as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:16:7: Error: Getter not found: 'y'.
       y.z.print(\"Hello, World!\") +
-      ^".z.print("Hello, World!") as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:17:7: Error: Getter not found: 'x'.
+      ^".z.print("Hello, World!") as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:17:7: Error: Getter not found: 'x'.
       x.y.z.print(\"Hello, World!\");
-      ^".y.z.print("Hello, World!") as{TypeError,ForDynamic} core::num);
+      ^".y.z.print("Hello, World!") as{TypeError,ForDynamic} core::num*);
 }
diff --git a/pkg/front_end/testcases/general/issue31767.dart.outline.expect b/pkg/front_end/testcases/general/issue31767.dart.outline.expect
index adbdb2c..43bfbd8 100644
--- a/pkg/front_end/testcases/general/issue31767.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue31767.dart.outline.expect
@@ -28,6 +28,8 @@
   synthetic constructor foo(core::int* x, [core::int* y, core::int* z]) → self::D*
     : super self::C::foo(x, y, z)
     ;
+  mixin-super-stub get w2() → core::int*
+    return super.{self::M::w2};
 }
 abstract class N extends iss::A /*isMixinDeclaration*/  {
   get w2() → core::int*
@@ -37,6 +39,8 @@
   synthetic constructor foo(core::int* x, [core::int* y, core::int* z, iss::_A* a]) → self::E*
     : super iss::A::foo(x, y, z, a)
     ;
+  mixin-super-stub get w2() → core::int*
+    return super.{self::N::w2};
 }
 static field core::StringBuffer* sb;
 static method p(core::String* name, core::int* value) → core::int*
diff --git a/pkg/front_end/testcases/general/issue31767.dart.strong.expect b/pkg/front_end/testcases/general/issue31767.dart.strong.expect
index 66290c1..8e1ff2d 100644
--- a/pkg/front_end/testcases/general/issue31767.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue31767.dart.strong.expect
@@ -29,6 +29,8 @@
   synthetic constructor foo(core::int* x, [core::int* y = #C1, core::int* z = #C1]) → self::D*
     : super self::C::foo(x, y, z)
     ;
+  mixin-super-stub get w2() → core::int*
+    return super.{self::M::w2};
 }
 abstract class N extends iss::A /*isMixinDeclaration*/  {
   get w2() → core::int*
@@ -38,6 +40,8 @@
   synthetic constructor foo(core::int* x, [core::int* y = #C2, core::int* z = #C2, iss::_A* a = #C4]) → self::E*
     : super iss::A::foo(x, y, z, a)
     ;
+  mixin-super-stub get w2() → core::int*
+    return super.{self::N::w2};
 }
 static field core::StringBuffer* sb;
 static method p(core::String* name, core::int* value) → core::int* {
@@ -58,12 +62,12 @@
   self::D* d = new self::D::foo(1, 2);
   self::expect("x = 1, y = 2, z = 0, ", self::sb.{core::StringBuffer::toString}());
   self::expect(3, d.{self::C::w});
-  self::expect(9, d.{self::M::w2});
+  self::expect(9, d.{self::D::w2});
   self::sb = new core::StringBuffer::•();
   self::E* e = new self::E::foo(1, 2);
   self::expect("x = 1, y = 2, z = 3, ", self::sb.{core::StringBuffer::toString}());
   self::expect(6, e.{iss::A::w});
-  self::expect(36, e.{self::N::w2});
+  self::expect(36, e.{self::E::w2});
   self::expect(5, e.{iss::A::a}.{iss::_A::field});
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -119,3 +123,12 @@
   #C3 = 5
   #C4 = iss::_A {field:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue31767.dart:
+- _A. (from org-dartlang-testcase:///issue31767_lib.dart:20:9)
+
+org-dartlang-testcase:///issue31767_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- _A. (from org-dartlang-testcase:///issue31767_lib.dart:20:9)
diff --git a/pkg/front_end/testcases/general/issue31767.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue31767.dart.strong.transformed.expect
index 19fdcee..1692006 100644
--- a/pkg/front_end/testcases/general/issue31767.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue31767.dart.strong.transformed.expect
@@ -62,12 +62,12 @@
   self::D* d = new self::D::foo(1, 2);
   self::expect("x = 1, y = 2, z = 0, ", self::sb.{core::StringBuffer::toString}());
   self::expect(3, d.{self::C::w});
-  self::expect(9, d.{self::M::w2});
+  self::expect(9, d.{self::D::w2});
   self::sb = new core::StringBuffer::•();
   self::E* e = new self::E::foo(1, 2);
   self::expect("x = 1, y = 2, z = 3, ", self::sb.{core::StringBuffer::toString}());
   self::expect(6, e.{iss::A::w});
-  self::expect(36, e.{self::N::w2});
+  self::expect(36, e.{self::E::w2});
   self::expect(5, e.{iss::A::a}.{iss::_A::field});
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -123,3 +123,12 @@
   #C3 = 5
   #C4 = iss::_A {field:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue31767.dart:
+- _A. (from org-dartlang-testcase:///issue31767_lib.dart:20:9)
+
+org-dartlang-testcase:///issue31767_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- _A. (from org-dartlang-testcase:///issue31767_lib.dart:20:9)
diff --git a/pkg/front_end/testcases/general/issue34714.dart.outline.expect b/pkg/front_end/testcases/general/issue34714.dart.outline.expect
index 04e8e0b..7d7ca21 100644
--- a/pkg/front_end/testcases/general/issue34714.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue34714.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   static factory •<T extends core::Object* = dynamic>() → self::A<self::A::•::T*>*
     let dynamic #redirecting_factory = self::B::• in let self::A::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/issue34714.dart.strong.expect b/pkg/front_end/testcases/general/issue34714.dart.strong.expect
index f0ced51..e023b92 100644
--- a/pkg/front_end/testcases/general/issue34714.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue34714.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   static factory •<T extends core::Object* = dynamic>() → self::A<self::A::•::T*>*
     let dynamic #redirecting_factory = self::B::• in let self::A::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/issue34714.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue34714.dart.strong.transformed.expect
index 38f9b49..61b902a 100644
--- a/pkg/front_end/testcases/general/issue34714.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue34714.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   static factory •<T extends core::Object* = dynamic>() → self::A<self::A::•::T*>*
     let<BottomType> #redirecting_factory = self::B::• in let self::A::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/issue39344.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue39344.dart.strong.transformed.expect
index c0a0a59..f5e9af5 100644
--- a/pkg/front_end/testcases/general/issue39344.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue39344.dart.strong.transformed.expect
@@ -43,7 +43,7 @@
     ;
   method method1a(generic-covariant-impl self::Class::T* t) → void {
     if(t is self::B*) {
-      core::List<self::Class::T*>* ys = <self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}];
+      core::List<self::Class::T*>* ys = core::_GrowableList::_literal1<self::Class::T*>(t{self::Class::T* & self::B* /* '*' & '*' = '*' */});
       self::xs = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/issue39344.dart:19:12: Error: A value of type 'List<T>' can't be assigned to a variable of type 'List<B>'.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
@@ -53,7 +53,7 @@
   }
   method method1b(generic-covariant-impl self::Class::T* t) → void {
     if(t is self::B*) {
-      core::List<core::List<self::Class::T*>*>* yss = <core::List<self::Class::T*>*>[<self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}]];
+      core::List<core::List<self::Class::T*>*>* yss = core::_GrowableList::_literal1<core::List<self::Class::T*>*>(core::_GrowableList::_literal1<self::Class::T*>(t{self::Class::T* & self::B* /* '*' & '*' = '*' */}));
       self::xss = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/issue39344.dart:31:13: Error: A value of type 'List<List<T>>' can't be assigned to a variable of type 'List<List<B>>'.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
@@ -64,7 +64,7 @@
   method method2a(generic-covariant-impl self::Class::T* t) → void {
     dynamic alias;
     if(t is self::B*) {
-      core::List<self::Class::T*>* ys = <self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}];
+      core::List<self::Class::T*>* ys = core::_GrowableList::_literal1<self::Class::T*>(t{self::Class::T* & self::B* /* '*' & '*' = '*' */});
       alias = ys;
       self::xs = alias as{TypeError,ForDynamic} core::List<self::B*>*;
     }
@@ -72,7 +72,7 @@
   method method2b(generic-covariant-impl self::Class::T* t) → void {
     dynamic alias;
     if(t is self::B*) {
-      core::List<core::List<self::Class::T*>*>* yss = <core::List<self::Class::T*>*>[<self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}]];
+      core::List<core::List<self::Class::T*>*>* yss = core::_GrowableList::_literal1<core::List<self::Class::T*>*>(core::_GrowableList::_literal1<self::Class::T*>(t{self::Class::T* & self::B* /* '*' & '*' = '*' */}));
       alias = yss;
       self::xss = alias as{TypeError,ForDynamic} core::List<core::List<self::B*>*>*;
     }
diff --git a/pkg/front_end/testcases/general/issue40242.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue40242.dart.textual_outline.expect
index c862500..4b76f91 100644
--- a/pkg/front_end/testcases/general/issue40242.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/issue40242.dart.textual_outline.expect
@@ -1,5 +1,8 @@
 class C {}
-extension E ;
-on C (){}
+
+extension E on C {
+  errors() {}
+}
+
 errors() {}
 main() {}
diff --git a/pkg/front_end/testcases/general/issue40242.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue40242.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..91844c5
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue40242.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class C {}
+
+errors() {}
+
+extension E on C {
+  errors() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect
index 58436b7..96339d0 100644
--- a/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
           :async_temporary_1 = x.{core::num::+}(1);
           :async_temporary_0 = x.{core::num::+}(2);
           [yield] let dynamic #t1 = asy::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
-          :async_temporary_2 = <core::int*>[_in::unsafeCast<core::int*>(:async_temporary_1), _in::unsafeCast<core::int*>(:async_temporary_0), _in::unsafeCast<Null>(:result)];
+          :async_temporary_2 = core::_GrowableList::_literal3<core::int*>(_in::unsafeCast<core::int*>(:async_temporary_1), _in::unsafeCast<core::int*>(:async_temporary_0), _in::unsafeCast<Null>(:result));
         }
         else {
           :async_temporary_2 = null;
diff --git a/pkg/front_end/testcases/general/issue40982.dart.outline.expect b/pkg/front_end/testcases/general/issue40982.dart.outline.expect
index 642ab52..90a0ef0 100644
--- a/pkg/front_end/testcases/general/issue40982.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue40982.dart.outline.expect
@@ -78,6 +78,10 @@
   synthetic constructor •() → self::_E1&A&D*
     : super self::A::•()
     ;
+  mixin-super-stub get value() → core::int*
+    return super.{self::D::value};
+  mixin-super-stub set value(core::int* value) → void
+    return super.{self::D::value} = value;
 }
 class E1 extends self::_E1&A&D /*hasConstConstructor*/  {
   const constructor •() → self::E1*
@@ -88,6 +92,10 @@
   synthetic constructor •() → self::E2*
     : super self::A::•()
     ;
+  mixin-super-stub get value() → core::int*
+    return super.{self::D::value};
+  mixin-super-stub set value(core::int* value) → void
+    return super.{self::D::value} = value;
 }
 class E3 extends self::E2 /*hasConstConstructor*/  {
   const constructor •() → self::E3*
diff --git a/pkg/front_end/testcases/general/issue40982.dart.strong.expect b/pkg/front_end/testcases/general/issue40982.dart.strong.expect
index d5bdf49..9eb651c 100644
--- a/pkg/front_end/testcases/general/issue40982.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue40982.dart.strong.expect
@@ -78,6 +78,10 @@
   synthetic constructor •() → self::_E1&A&D*
     : super self::A::•()
     ;
+  mixin-super-stub get value() → core::int*
+    return super.{self::D::value};
+  mixin-super-stub set value(core::int* value) → void
+    return super.{self::D::value} = value;
 }
 class E1 extends self::_E1&A&D /*hasConstConstructor*/  {
   const constructor •() → self::E1*
@@ -88,6 +92,10 @@
   synthetic constructor •() → self::E2*
     : super self::A::•()
     ;
+  mixin-super-stub get value() → core::int*
+    return super.{self::D::value};
+  mixin-super-stub set value(core::int* value) → void
+    return super.{self::D::value} = value;
 }
 class E3 extends self::E2 /*hasConstConstructor*/  {
   const constructor •() → self::E3*
diff --git a/pkg/front_end/testcases/general/issue41070.dart.strong.expect b/pkg/front_end/testcases/general/issue41070.dart.strong.expect
index 4d2a484..71da7fe 100644
--- a/pkg/front_end/testcases/general/issue41070.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue41070.dart.strong.expect
@@ -50,3 +50,10 @@
   #C1 = 42
   #C2 = self::Application {x:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue41070.dart:
+- Application. (from org-dartlang-testcase:///issue41070.dart:12:7)
+- Base. (from org-dartlang-testcase:///issue41070.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue41070.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue41070.dart.strong.transformed.expect
index 76c0ef2..30b4c02 100644
--- a/pkg/front_end/testcases/general/issue41070.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue41070.dart.strong.transformed.expect
@@ -60,3 +60,10 @@
   #C1 = 42
   #C2 = self::Application {x:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue41070.dart:
+- Application. (from org-dartlang-testcase:///issue41070.dart:12:7)
+- Base. (from org-dartlang-testcase:///issue41070.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/issue41210a.dart b/pkg/front_end/testcases/general/issue41210a.dart
index 7f16a06..78cfc3c 100644
--- a/pkg/front_end/testcases/general/issue41210a.dart
+++ b/pkg/front_end/testcases/general/issue41210a.dart
@@ -24,6 +24,10 @@
 
 class E with A, D {} // ok
 
+abstract class F implements Interface {}
+
+class G with A, F {} // ok
+
 main() {
   print(C().method(0));
 }
diff --git a/pkg/front_end/testcases/general/issue41210a.dart.outline.expect b/pkg/front_end/testcases/general/issue41210a.dart.outline.expect
index f56ad37..20bf60b 100644
--- a/pkg/front_end/testcases/general/issue41210a.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue41210a.dart.outline.expect
@@ -5,12 +5,12 @@
 // pkg/front_end/testcases/general/issue41210a.dart:21:7: Error: Applying the mixin 'B' to 'Object with A' introduces an erroneous override of 'method'.
 // class C with A, B {} // error
 //       ^
-// pkg/front_end/testcases/general/issue41210a.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'A.method'.
+// pkg/front_end/testcases/general/issue41210a.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'Object with A.method'.
 //   String method(num i);
 //          ^
-// pkg/front_end/testcases/general/issue41210a.dart:14:10: Context: This is the overridden method ('method').
-//   String method(num i, {String s = "hello"}) => s;
-//          ^
+// pkg/front_end/testcases/general/issue41210a.dart:21:7: Context: This is the overridden method ('method').
+// class C with A, B {} // error
+//       ^
 //
 import self as self;
 import "dart:core" as core;
@@ -78,6 +78,8 @@
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::num* i, {core::String* s}) → core::String*
+    return super.{self::A::method}(i, s: s);
   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
@@ -93,16 +95,16 @@
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
-  abstract member-signature method method(core::num* i, {core::String* s}) → core::String*; -> self::A::method
+  abstract mixin-stub method method(core::num* i) → core::String*; -> self::B::method
 }
 class C extends self::_C&Object&A&B {
   synthetic constructor •() → self::C*
     ;
-  abstract member-signature method method(core::num* i, {core::String* s}) → core::String*; -> self::A::method
 }
 abstract class D extends core::Object implements self::Interface, self::Interface2 {
   synthetic constructor •() → self::D*
     ;
+  abstract forwarding-stub method method(covariant core::num* i) → core::String*;
   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
@@ -113,12 +115,13 @@
   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
-  abstract forwarding-stub method method(covariant core::num* i) → core::String*;
 }
 abstract class _E&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::num* i, {core::String* s}) → core::String*
+    return super.{self::A::method}(i, s: s);
   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
@@ -135,11 +138,51 @@
     : super self::_E&Object&A::•()
     ;
   forwarding-stub method method(covariant core::num* i, {core::String* s}) → core::String*
-    return super.{self::A::method}(i, s: s);
+    return super.{self::_E&Object&A::method}(i, s: s);
 }
 class E extends self::_E&Object&A&D {
   synthetic constructor •() → self::E*
     ;
 }
+abstract class F extends core::Object implements self::Interface {
+  synthetic constructor •() → self::F*
+    ;
+  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
+}
+abstract class _G&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_G&Object&A*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method method(core::num* i, {core::String* s}) → core::String*
+    return super.{self::A::method}(i, s: s);
+  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
+}
+abstract class _G&Object&A&F = self::_G&Object&A with self::F /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_G&Object&A&F*
+    : super self::_G&Object&A::•()
+    ;
+}
+class G extends self::_G&Object&A&F {
+  synthetic constructor •() → self::G*
+    ;
+}
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/general/issue41210a.dart.strong.expect b/pkg/front_end/testcases/general/issue41210a.dart.strong.expect
index 024bfb0..2766232 100644
--- a/pkg/front_end/testcases/general/issue41210a.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue41210a.dart.strong.expect
@@ -5,12 +5,12 @@
 // pkg/front_end/testcases/general/issue41210a.dart:21:7: Error: Applying the mixin 'B' to 'Object with A' introduces an erroneous override of 'method'.
 // class C with A, B {} // error
 //       ^
-// pkg/front_end/testcases/general/issue41210a.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'A.method'.
+// pkg/front_end/testcases/general/issue41210a.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'Object with A.method'.
 //   String method(num i);
 //          ^
-// pkg/front_end/testcases/general/issue41210a.dart:14:10: Context: This is the overridden method ('method').
-//   String method(num i, {String s = "hello"}) => s;
-//          ^
+// pkg/front_end/testcases/general/issue41210a.dart:21:7: Context: This is the overridden method ('method').
+// class C with A, B {} // error
+//       ^
 //
 import self as self;
 import "dart:core" as core;
@@ -81,6 +81,8 @@
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{self::A::method}(i, s: s);
   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
@@ -96,18 +98,18 @@
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
-  abstract member-signature method method(core::num* i, {core::String* s = #C1}) → core::String*; -> self::A::method
+  abstract mixin-stub method method(core::num* i) → core::String*; -> self::B::method
 }
 class C extends self::_C&Object&A&B {
   synthetic constructor •() → self::C*
     : super self::_C&Object&A&B::•()
     ;
-  abstract member-signature method method(core::num* i, {core::String* s = #C1}) → core::String*; -> self::A::method
 }
 abstract class D extends core::Object implements self::Interface, self::Interface2 {
   synthetic constructor •() → self::D*
     : super core::Object::•()
     ;
+  abstract forwarding-stub method method(covariant core::num* i) → core::String*;
   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
@@ -118,12 +120,13 @@
   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
-  abstract forwarding-stub method method(covariant core::num* i) → core::String*;
 }
 abstract class _E&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{self::A::method}(i, s: s);
   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
@@ -140,15 +143,57 @@
     : super self::_E&Object&A::•()
     ;
   forwarding-stub method method(covariant core::num* i, {core::String* s = #C1}) → core::String*
-    return super.{self::A::method}(i, s: s);
+    return super.{self::_E&Object&A::method}(i, s: s);
 }
 class E extends self::_E&Object&A&D {
   synthetic constructor •() → self::E*
     : super self::_E&Object&A&D::•()
     ;
 }
+abstract class F extends core::Object implements self::Interface {
+  synthetic constructor •() → self::F*
+    : 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
+}
+abstract class _G&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_G&Object&A*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{self::A::method}(i, s: s);
+  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
+}
+abstract class _G&Object&A&F = self::_G&Object&A with self::F /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_G&Object&A&F*
+    : super self::_G&Object&A::•()
+    ;
+}
+class G extends self::_G&Object&A&F {
+  synthetic constructor •() → self::G*
+    : super self::_G&Object&A&F::•()
+    ;
+}
 static method main() → dynamic {
-  core::print(new self::C::•().{self::C::method}(0));
+  core::print(new self::C::•().{self::_C&Object&A&B::method}(0));
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/general/issue41210a.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue41210a.dart.strong.transformed.expect
new file mode 100644
index 0000000..85cb978
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue41210a.dart.strong.transformed.expect
@@ -0,0 +1,180 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue41210a.dart:21:7: Error: Applying the mixin 'B' to 'Object with A' introduces an erroneous override of 'method'.
+// class C with A, B {} // error
+//       ^
+// pkg/front_end/testcases/general/issue41210a.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'Object with A.method'.
+//   String method(num i);
+//          ^
+// pkg/front_end/testcases/general/issue41210a.dart:21:7: Context: This is the overridden method ('method').
+// class C with A, B {} // error
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → self::Interface*
+    : super core::Object::•()
+    ;
+  abstract method method(core::num* i) → core::String*;
+  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
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2*
+    : super core::Object::•()
+    ;
+  abstract method method(covariant core::int* i) → core::String*;
+  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
+}
+abstract class A extends core::Object implements self::Interface /*isMixinDeclaration*/  {
+  method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return s;
+  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
+}
+abstract class B extends core::Object implements self::Interface {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  abstract method method(core::num* i) → core::String*;
+  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
+}
+abstract class _C&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A*
+    : super core::Object::•()
+    ;
+  method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return s;
+  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
+}
+abstract class _C&Object&A&B extends self::_C&Object&A implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A&B*
+    : super self::_C&Object&A::•()
+    ;
+  abstract member-signature method method(core::num* i, {core::String* s = #C1}) → core::String*; -> self::_C&Object&A::method
+  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
+}
+class C extends self::_C&Object&A&B {
+  synthetic constructor •() → self::C*
+    : super self::_C&Object&A&B::•()
+    ;
+  abstract member-signature method method(core::num* i, {core::String* s = #C1}) → core::String*; -> self::_C&Object&A::method
+}
+abstract class D extends core::Object implements self::Interface, self::Interface2 {
+  synthetic constructor •() → self::D*
+    : 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
+  abstract forwarding-stub method method(covariant core::num* i) → core::String*;
+}
+abstract class _E&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_E&Object&A*
+    : super core::Object::•()
+    ;
+  method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return s;
+  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
+}
+abstract class _E&Object&A&D extends self::_E&Object&A implements self::D /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_E&Object&A&D*
+    : super self::_E&Object&A::•()
+    ;
+  forwarding-stub method method(covariant core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{self::A::method}(i, s: s);
+  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
+}
+class E extends self::_E&Object&A&D {
+  synthetic constructor •() → self::E*
+    : super self::_E&Object&A&D::•()
+    ;
+}
+static method main() → dynamic {
+  core::print(new self::C::•().{self::C::method}(0));
+}
+
+constants  {
+  #C1 = "hello"
+}
diff --git a/pkg/front_end/testcases/general/issue41210a.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue41210a.dart.textual_outline.expect
index 8fc1032..599fc0f 100644
--- a/pkg/front_end/testcases/general/issue41210a.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/issue41210a.dart.textual_outline.expect
@@ -20,4 +20,8 @@
 
 class E with A, D {}
 
+abstract class F implements Interface {}
+
+class G with A, F {}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/issue41210a.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue41210a.dart.textual_outline_modelled.expect
index 6ec25da..d6c9646 100644
--- a/pkg/front_end/testcases/general/issue41210a.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/general/issue41210a.dart.textual_outline_modelled.expect
@@ -4,6 +4,8 @@
 
 abstract class D implements Interface, Interface2 {}
 
+abstract class F implements Interface {}
+
 abstract class Interface {
   String method(num i);
 }
@@ -16,6 +18,8 @@
 
 class E with A, D {}
 
+class G with A, F {}
+
 main() {}
 mixin A implements Interface {
   String method(num i, {String s = "hello"}) => s;
diff --git a/pkg/front_end/testcases/general/issue41210b/issue41210.dart b/pkg/front_end/testcases/general/issue41210b/issue41210.dart
index 01f7b3b..08bd4e4 100644
--- a/pkg/front_end/testcases/general/issue41210b/issue41210.dart
+++ b/pkg/front_end/testcases/general/issue41210b/issue41210.dart
@@ -8,6 +8,8 @@
 
 class E with A, D {} // ok
 
+class G with A, F {} // ok
+
 main() {
   print(C().method(0));
 }
diff --git a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.outline.expect b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.outline.expect
index ac3f13c..525ba41 100644
--- a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.outline.expect
@@ -5,12 +5,12 @@
 // pkg/front_end/testcases/general/issue41210b/issue41210.dart:7:7: Error: Applying the mixin 'B' to 'Object with A' introduces an erroneous override of 'method'.
 // class C with A, B {} // error
 //       ^
-// pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'A.method'.
+// pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'Object with A.method'.
 //   String method(num i);
 //          ^
-// pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart:14:10: Context: This is the overridden method ('method').
-//   String method(num i, {String s = "hello"}) => s;
-//          ^
+// pkg/front_end/testcases/general/issue41210b/issue41210.dart:7:7: Context: This is the overridden method ('method').
+// class C with A, B {} // error
+//       ^
 //
 import self as self;
 import "dart:core" as core;
@@ -22,33 +22,112 @@
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::num* i, {core::String* s}) → core::String*
+    return super.{iss::A::method}(i, s: s);
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::A::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::A::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::A::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::A::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::A::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::A::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::A::runtimeType
 }
 abstract class _C&Object&A&B = self::_C&Object&A with iss::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
-  abstract member-signature method method(core::num* i, {core::String* s}) → core::String*; -> iss::A::method
+  abstract mixin-stub method method(core::num* i) → core::String*; -> iss::B::method
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::B::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::B::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::B::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::B::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::B::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::B::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::B::runtimeType
 }
 class C extends self::_C&Object&A&B {
   synthetic constructor •() → self::C*
     ;
-  abstract member-signature method method(core::num* i, {core::String* s}) → core::String*; -> iss::A::method
 }
 abstract class _E&Object&A = core::Object with iss::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E&Object&A*
     : super core::Object::•()
     ;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::A::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::A::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::A::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::A::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::A::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::A::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::A::runtimeType
+  mixin-super-stub method method(core::num* i, {core::String* s}) → core::String*
+    return super.{iss::A::method}(i, s: s);
 }
 abstract class _E&Object&A&D = self::_E&Object&A with iss::D /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E&Object&A&D*
     : super self::_E&Object&A::•()
     ;
-  abstract forwarding-stub method method(covariant core::num* i, {core::String* s}) → core::String*;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::D::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::D::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::D::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::D::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::D::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::D::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::D::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::D::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::D::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::D::runtimeType
+  forwarding-stub method method(covariant core::num* i) → core::String*
+    return super.{self::_E&Object&A::method}(i);
 }
 class E extends self::_E&Object&A&D {
   synthetic constructor •() → self::E*
     ;
-  abstract member-signature method method(covariant core::num* i, {core::String* s}) → core::String*; -> self::_E&Object&A&D::method
+}
+abstract class _G&Object&A = core::Object with iss::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_G&Object&A*
+    : super core::Object::•()
+    ;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::A::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::A::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::A::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::A::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::A::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::A::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::A::runtimeType
+  mixin-super-stub method method(core::num* i, {core::String* s}) → core::String*
+    return super.{iss::A::method}(i, s: s);
+}
+abstract class _G&Object&A&F = self::_G&Object&A with iss::F /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_G&Object&A&F*
+    : super self::_G&Object&A::•()
+    ;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::F::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::F::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::F::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::F::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::F::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::F::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::F::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::F::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::F::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::F::runtimeType
+}
+class G extends self::_G&Object&A&F {
+  synthetic constructor •() → self::G*
+    ;
 }
 static method main() → dynamic
   ;
@@ -131,6 +210,20 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   abstract forwarding-stub method method(covariant core::num* i) → core::String*;
 }
+abstract class F extends core::Object implements iss::Interface {
+  synthetic constructor •() → iss::F*
+    ;
+  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
+}
 
 constants  {
   #C1 = "hello"
diff --git a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.strong.expect b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.strong.expect
index daad075..eb41372 100644
--- a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.strong.expect
@@ -5,12 +5,12 @@
 // pkg/front_end/testcases/general/issue41210b/issue41210.dart:7:7: Error: Applying the mixin 'B' to 'Object with A' introduces an erroneous override of 'method'.
 // class C with A, B {} // error
 //       ^
-// pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'A.method'.
+// pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'Object with A.method'.
 //   String method(num i);
 //          ^
-// pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart:14:10: Context: This is the overridden method ('method').
-//   String method(num i, {String s = "hello"}) => s;
-//          ^
+// pkg/front_end/testcases/general/issue41210b/issue41210.dart:7:7: Context: This is the overridden method ('method').
+// class C with A, B {} // error
+//       ^
 //
 import self as self;
 import "dart:core" as core;
@@ -22,38 +22,118 @@
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{iss::A::method}(i, s: s);
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::A::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::A::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::A::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::A::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::A::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::A::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::A::runtimeType
 }
 abstract class _C&Object&A&B = self::_C&Object&A with iss::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
-  abstract member-signature method method(core::num* i, {core::String* s = #C1}) → core::String*; -> iss::A::method
+  abstract mixin-stub method method(core::num* i) → core::String*; -> iss::B::method
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::B::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::B::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::B::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::B::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::B::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::B::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::B::runtimeType
 }
 class C extends self::_C&Object&A&B {
   synthetic constructor •() → self::C*
     : super self::_C&Object&A&B::•()
     ;
-  abstract member-signature method method(core::num* i, {core::String* s = #C1}) → core::String*; -> iss::A::method
 }
 abstract class _E&Object&A = core::Object with iss::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E&Object&A*
     : super core::Object::•()
     ;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::A::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::A::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::A::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::A::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::A::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::A::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::A::runtimeType
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{iss::A::method}(i, s: s);
 }
 abstract class _E&Object&A&D = self::_E&Object&A with iss::D /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E&Object&A&D*
     : super self::_E&Object&A::•()
     ;
-  abstract forwarding-stub method method(covariant core::num* i, {core::String* s = #C1}) → core::String*;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::D::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::D::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::D::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::D::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::D::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::D::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::D::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::D::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::D::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::D::runtimeType
+  forwarding-stub method method(covariant core::num* i) → core::String*
+    return super.{self::_E&Object&A::method}(i);
 }
 class E extends self::_E&Object&A&D {
   synthetic constructor •() → self::E*
     : super self::_E&Object&A&D::•()
     ;
-  abstract member-signature method method(covariant core::num* i, {core::String* s = #C1}) → core::String*; -> self::_E&Object&A&D::method
+}
+abstract class _G&Object&A = core::Object with iss::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_G&Object&A*
+    : super core::Object::•()
+    ;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::A::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::A::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::A::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::A::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::A::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::A::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::A::runtimeType
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{iss::A::method}(i, s: s);
+}
+abstract class _G&Object&A&F = self::_G&Object&A with iss::F /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_G&Object&A&F*
+    : super self::_G&Object&A::•()
+    ;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::F::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::F::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::F::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::F::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::F::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::F::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::F::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::F::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::F::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::F::runtimeType
+}
+class G extends self::_G&Object&A&F {
+  synthetic constructor •() → self::G*
+    : super self::_G&Object&A&F::•()
+    ;
 }
 static method main() → dynamic {
-  core::print(new self::C::•().{self::C::method}(0));
+  core::print(new self::C::•().{self::_C&Object&A&B::method}(0));
 }
 
 library;
@@ -138,6 +218,21 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   abstract forwarding-stub method method(covariant core::num* i) → core::String*;
 }
+abstract class F extends core::Object implements iss::Interface {
+  synthetic constructor •() → iss::F*
+    : 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
+}
 
 constants  {
   #C1 = "hello"
diff --git a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.strong.transformed.expect
new file mode 100644
index 0000000..d4b65d7
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.strong.transformed.expect
@@ -0,0 +1,188 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue41210b/issue41210.dart:7:7: Error: Applying the mixin 'B' to 'Object with A' introduces an erroneous override of 'method'.
+// class C with A, B {} // error
+//       ^
+// pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart:18:10: Context: The method 'B.method' has fewer named arguments than those of overridden method 'Object with A.method'.
+//   String method(num i);
+//          ^
+// pkg/front_end/testcases/general/issue41210b/issue41210.dart:7:7: Context: This is the overridden method ('method').
+// class C with A, B {} // error
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+import "issue41210_lib.dart" as iss;
+
+import "org-dartlang-testcase:///issue41210_lib.dart";
+
+abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A*
+    : super core::Object::•()
+    ;
+  method /* from org-dartlang-testcase:///issue41210_lib.dart */ method(core::num* i, {core::String* s = #C1}) → core::String*
+    return s;
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator /* from org-dartlang-testcase:///issue41210_lib.dart */ ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ toString() → core::String*; -> core::Object::toString
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&A&B*
+    : super self::_C&Object&A::•()
+    ;
+  abstract member-signature method method(core::num* i, {core::String* s = #C1}) → core::String*; -> self::_C&Object&A::method
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator /* from org-dartlang-testcase:///issue41210_lib.dart */ ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ toString() → core::String*; -> core::Object::toString
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class C extends self::_C&Object&A&B {
+  synthetic constructor •() → self::C*
+    : super self::_C&Object&A&B::•()
+    ;
+  abstract member-signature method method(core::num* i, {core::String* s = #C1}) → core::String*; -> self::_C&Object&A::method
+}
+abstract class _E&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_E&Object&A*
+    : super core::Object::•()
+    ;
+  method /* from org-dartlang-testcase:///issue41210_lib.dart */ method(core::num* i, {core::String* s = #C1}) → core::String*
+    return s;
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator /* from org-dartlang-testcase:///issue41210_lib.dart */ ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ toString() → core::String*; -> core::Object::toString
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _E&Object&A&D extends self::_E&Object&A implements iss::D /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_E&Object&A&D*
+    : super self::_E&Object&A::•()
+    ;
+  abstract forwarding-stub method method(covariant core::num* i, {core::String* s = #C1}) → core::String*;
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator /* from org-dartlang-testcase:///issue41210_lib.dart */ ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ toString() → core::String*; -> core::Object::toString
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib.dart */ noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib.dart */ runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class E extends self::_E&Object&A&D {
+  synthetic constructor •() → self::E*
+    : super self::_E&Object&A&D::•()
+    ;
+  abstract member-signature method method(covariant core::num* i, {core::String* s = #C1}) → core::String*; -> self::_E&Object&A&D::method
+}
+static method main() → dynamic {
+  core::print(new self::C::•().{self::C::method}(0));
+}
+
+library;
+import self as iss;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → iss::Interface*
+    : super core::Object::•()
+    ;
+  abstract method method(core::num* i) → core::String*;
+  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
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → iss::Interface2*
+    : super core::Object::•()
+    ;
+  abstract method method(covariant core::int* i) → core::String*;
+  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
+}
+abstract class A extends core::Object implements iss::Interface /*isMixinDeclaration*/  {
+  method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return s;
+  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
+}
+abstract class B extends core::Object implements iss::Interface {
+  synthetic constructor •() → iss::B*
+    : super core::Object::•()
+    ;
+  abstract method method(core::num* i) → core::String*;
+  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
+}
+abstract class D extends core::Object implements iss::Interface, iss::Interface2 {
+  synthetic constructor •() → iss::D*
+    : 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
+  abstract forwarding-stub method method(covariant core::num* i) → core::String*;
+}
+
+constants  {
+  #C1 = "hello"
+}
diff --git a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.textual_outline.expect
index 7354b67..8c473d0 100644
--- a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.textual_outline.expect
@@ -4,4 +4,6 @@
 
 class E with A, D {}
 
+class G with A, F {}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.textual_outline_modelled.expect
index 7354b67..8c473d0 100644
--- a/pkg/front_end/testcases/general/issue41210b/issue41210.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/general/issue41210b/issue41210.dart.textual_outline_modelled.expect
@@ -4,4 +4,6 @@
 
 class E with A, D {}
 
+class G with A, F {}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart b/pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart
index 61a4823..a209b30 100644
--- a/pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart
+++ b/pkg/front_end/testcases/general/issue41210b/issue41210_lib.dart
@@ -19,3 +19,5 @@
 }
 
 abstract class D implements Interface, Interface2 {}
+
+abstract class F implements Interface {}
diff --git a/pkg/front_end/testcases/general/issue42997.dart.strong.expect b/pkg/front_end/testcases/general/issue42997.dart.strong.expect
index 40813a7..cfae480 100644
--- a/pkg/front_end/testcases/general/issue42997.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue42997.dart.strong.expect
@@ -57,7 +57,7 @@
   method dispose() → void {
     for (final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/issue42997.dart:12:10: Error: Can't use 'PropertyState' because it is declared more than once.
     for (PropertyState<Object, Object>> state in _states) ;
-         ^".<(core::Object*); invalid-expression "pkg/front_end/testcases/general/issue42997.dart:12:30: Error: This couldn't be parsed.
+         ^".<(#C1); invalid-expression "pkg/front_end/testcases/general/issue42997.dart:12:30: Error: This couldn't be parsed.
     for (PropertyState<Object, Object>> state in _states) ;
                              ^" as{TypeError,ForDynamic} core::bool*; invalid-expression "pkg/front_end/testcases/general/issue42997.dart:12:30: Error: This couldn't be parsed.
     for (PropertyState<Object, Object>> state in _states) ;
@@ -81,3 +81,7 @@
 }
 static method main() → dynamic {}
 static abstract method PropertyState() → dynamic;
+
+constants  {
+  #C1 = TypeLiteralConstant(core::Object*)
+}
diff --git a/pkg/front_end/testcases/general/issue42997.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue42997.dart.strong.transformed.expect
index b501d6e..96d6a7c 100644
--- a/pkg/front_end/testcases/general/issue42997.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue42997.dart.strong.transformed.expect
@@ -57,7 +57,7 @@
   method dispose() → void {
     for (final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/issue42997.dart:12:10: Error: Can't use 'PropertyState' because it is declared more than once.
     for (PropertyState<Object, Object>> state in _states) ;
-         ^".<(core::Object*); invalid-expression "pkg/front_end/testcases/general/issue42997.dart:12:30: Error: This couldn't be parsed.
+         ^".<(#C1); invalid-expression "pkg/front_end/testcases/general/issue42997.dart:12:30: Error: This couldn't be parsed.
     for (PropertyState<Object, Object>> state in _states) ;
                              ^"; invalid-expression "pkg/front_end/testcases/general/issue42997.dart:12:30: Error: This couldn't be parsed.
     for (PropertyState<Object, Object>> state in _states) ;
@@ -82,7 +82,6 @@
 static method main() → dynamic {}
 static abstract method PropertyState() → dynamic;
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///issue42997.dart:12:24 -> TypeLiteralConstant(Object*)
-Extra constant evaluation: evaluated: 2, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(core::Object*)
+}
diff --git a/pkg/front_end/testcases/general/issue44347.dart b/pkg/front_end/testcases/general/issue44347.dart
new file mode 100644
index 0000000..0389b03
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44347.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.
+
+test() {
+  Set<int>.();
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/issue44347.dart.outline.expect b/pkg/front_end/testcases/general/issue44347.dart.outline.expect
new file mode 100644
index 0000000..a29647d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44347.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue44347.dart.strong.expect b/pkg/front_end/testcases/general/issue44347.dart.strong.expect
new file mode 100644
index 0000000..df1f308
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44347.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
+//   Set<int>.();
+//            ^
+//
+import self as self;
+import "dart:collection" as col;
+import "dart:core" as core;
+
+static method test() → dynamic {
+  col::LinkedHashSet::•<core::int*>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44347.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue44347.dart.strong.transformed.expect
new file mode 100644
index 0000000..a3adab2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44347.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
+//   Set<int>.();
+//            ^
+//
+import self as self;
+import "dart:collection" as col;
+import "dart:core" as core;
+
+static method test() → dynamic {
+  new col::_CompactLinkedHashSet::•<core::int*>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44347.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue44347.dart.textual_outline.expect
new file mode 100644
index 0000000..ec6b9e0
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44347.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44347.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue44347.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f67dbb0
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44347.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart b/pkg/front_end/testcases/general/issue44476.dart
new file mode 100644
index 0000000..d8459e2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart
@@ -0,0 +1,16 @@
+// 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 A<X extends int> {}
+
+foo(A<num> x) {
+  bar(A<num> y) {
+    barbar(A<num> yy) => null;
+  }
+  var baz = (A<num> z) {
+    var bazbaz = (A<num> zz) => null;
+  };
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart.outline.expect b/pkg/front_end/testcases/general/issue44476.dart.outline.expect
new file mode 100644
index 0000000..7f40fcf
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.outline.expect
@@ -0,0 +1,33 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44476.dart:7:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// foo(A<num> x) {
+//            ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::int* = core::int*> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    ;
+  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 method foo(self::A<core::num*>* x) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue44476.dart.strong.expect b/pkg/front_end/testcases/general/issue44476.dart.strong.expect
new file mode 100644
index 0000000..136f9b1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.strong.expect
@@ -0,0 +1,88 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44476.dart:7:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// foo(A<num> x) {
+//            ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:9:19: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//     barbar(A<num> yy) => null;
+//                   ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:8:14: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   bar(A<num> y) {
+//              ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:12:26: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//     var bazbaz = (A<num> zz) => null;
+//                          ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:12:9: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var bazbaz = (A<num> zz) => null;
+//         ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:11:21: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   var baz = (A<num> z) {
+//                     ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:11:7: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   var baz = (A<num> z) {
+//       ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::int* = core::int*> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    : 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 method foo(self::A<core::num*>* x) → dynamic {
+  function bar(self::A<core::num*>* y) → Null {
+    function barbar(self::A<core::num*>* yy) → Null
+      return null;
+  }
+  (self::A<core::num*>*) →* Null baz = (self::A<core::num*>* z) → Null {
+    (self::A<core::num*>*) →* Null bazbaz = (self::A<core::num*>* zz) → Null => null;
+  };
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue44476.dart.strong.transformed.expect
new file mode 100644
index 0000000..136f9b1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.strong.transformed.expect
@@ -0,0 +1,88 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44476.dart:7:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// foo(A<num> x) {
+//            ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:9:19: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//     barbar(A<num> yy) => null;
+//                   ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:8:14: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   bar(A<num> y) {
+//              ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:12:26: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//     var bazbaz = (A<num> zz) => null;
+//                          ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:12:9: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//     var bazbaz = (A<num> zz) => null;
+//         ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:11:21: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   var baz = (A<num> z) {
+//                     ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/issue44476.dart:11:7: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   var baz = (A<num> z) {
+//       ^
+// pkg/front_end/testcases/general/issue44476.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::int* = core::int*> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X*>*
+    : 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 method foo(self::A<core::num*>* x) → dynamic {
+  function bar(self::A<core::num*>* y) → Null {
+    function barbar(self::A<core::num*>* yy) → Null
+      return null;
+  }
+  (self::A<core::num*>*) →* Null baz = (self::A<core::num*>* z) → Null {
+    (self::A<core::num*>*) →* Null bazbaz = (self::A<core::num*>* zz) → Null => null;
+  };
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue44476.dart.textual_outline.expect
new file mode 100644
index 0000000..c3257fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+class A<X extends int> {}
+
+foo(A<num> x) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44476.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue44476.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c3257fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44476.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+class A<X extends int> {}
+
+foo(A<num> x) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/literals.dart.strong.transformed.expect b/pkg/front_end/testcases/general/literals.dart.strong.transformed.expect
index 8ef3e48..ae7c90f 100644
--- a/pkg/front_end/testcases/general/literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/literals.dart.strong.transformed.expect
@@ -19,8 +19,8 @@
   core::print(null);
 }
 static method testList() → dynamic {
-  core::print(<dynamic>[]);
-  core::print(<core::String*>["a", "b"]);
+  core::print(core::_GrowableList::•<dynamic>(0));
+  core::print(core::_GrowableList::_literal2<core::String*>("a", "b"));
 }
 static method testMap() → dynamic {
   core::print(<dynamic, dynamic>{});
diff --git a/pkg/front_end/testcases/general/local_generic_function.dart.strong.transformed.expect b/pkg/front_end/testcases/general/local_generic_function.dart.strong.transformed.expect
index 487fec1..328d4cc 100644
--- a/pkg/front_end/testcases/general/local_generic_function.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/local_generic_function.dart.strong.transformed.expect
@@ -5,5 +5,5 @@
 static method main() → dynamic {
   function f<T extends core::Object* = dynamic>(core::List<T*>* l) → T*
     return l.{core::List::[]}(0);
-  core::int* x = f.call<core::int*>(<core::int*>[0]);
+  core::int* x = f.call<core::int*>(core::_GrowableList::_literal1<core::int*>(0));
 }
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.expect
index 28519d4..191ed7b 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.expect
@@ -69,3 +69,9 @@
 constants  {
   #C1 = self::Constant {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///magic_const.dart:
+- Constant. (from org-dartlang-testcase:///magic_const.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
index d40ba2b8..7e7a8a4 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
@@ -73,3 +73,9 @@
 Extra constant evaluation status:
 Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///magic_const.dart:21:8 -> BoolConstant(false)
 Extra constant evaluation: evaluated: 2, effectively constant: 1
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///magic_const.dart:
+- Constant. (from org-dartlang-testcase:///magic_const.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect b/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
index b5f94c3..0b8666f 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
@@ -41,3 +41,9 @@
   #C10 = self::E {index:#C8, _name:#C9}
   #C11 = <self::E*>[#C4, #C7, #C10]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///metadata_enum.dart:
+- E. (from org-dartlang-testcase:///metadata_enum.dart:8:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
index b5f94c3..0b8666f 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
@@ -41,3 +41,9 @@
   #C10 = self::E {index:#C8, _name:#C9}
   #C11 = <self::E*>[#C4, #C7, #C10]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///metadata_enum.dart:
+- E. (from org-dartlang-testcase:///metadata_enum.dart:8:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/micro.dart.strong.transformed.expect b/pkg/front_end/testcases/general/micro.dart.strong.transformed.expect
index 74e0279..30a9c46 100644
--- a/pkg/front_end/testcases/general/micro.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/micro.dart.strong.transformed.expect
@@ -146,6 +146,6 @@
   dynamic c = subBox.{self::FinalBox::finalField};
   self::makeDynamicCall(new self::DynamicReceiver1::•());
   self::makeDynamicCall(new self::DynamicReceiver2::•());
-  core::List<core::String*>* list = <core::String*>["string"];
+  core::List<core::String*>* list = core::_GrowableList::_literal1<core::String*>("string");
   core::String* d = list.{core::List::[]}(0);
 }
diff --git a/pkg/front_end/testcases/general/mixin.dart.outline.expect b/pkg/front_end/testcases/general/mixin.dart.outline.expect
index 6bd0c09..e09c2b0 100644
--- a/pkg/front_end/testcases/general/mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.outline.expect
@@ -6,6 +6,8 @@
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M1::m}();
   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
@@ -21,6 +23,8 @@
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M2::m}();
 }
 class B extends self::_B&Object&M1&M2 {
   constructor •(dynamic value) → self::B*
@@ -62,6 +66,8 @@
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M1::m}();
   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
@@ -77,6 +83,8 @@
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M2::m}();
 }
 class C extends self::_C&Object&M1&M2 {
   constructor •(dynamic value) → self::C*
@@ -102,6 +110,8 @@
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::G1::m}();
   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
diff --git a/pkg/front_end/testcases/general/mixin.dart.strong.expect b/pkg/front_end/testcases/general/mixin.dart.strong.expect
index 2851dfc..1f1f19e 100644
--- a/pkg/front_end/testcases/general/mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.strong.expect
@@ -6,6 +6,8 @@
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M1::m}();
   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
@@ -21,6 +23,8 @@
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M2::m}();
 }
 class B extends self::_B&Object&M1&M2 {
   constructor •(dynamic value) → self::B*
@@ -65,6 +69,8 @@
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M1::m}();
   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
@@ -80,6 +86,8 @@
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M2::m}();
 }
 class C extends self::_C&Object&M1&M2 {
   constructor •(dynamic value) → self::C*
@@ -107,6 +115,8 @@
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::G1::m}();
   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
@@ -124,9 +134,9 @@
     ;
 }
 static method main() → dynamic {
-  new self::B::•(null).{self::M2::m}();
-  new self::C::•(null).{self::M2::m}();
-  new self::D::•<dynamic>().{self::G1::m}();
-  new self::D::•<core::int*>().{self::G1::m}();
-  new self::D::•<core::List<core::int*>*>().{self::G1::m}();
+  new self::B::•(null).{self::_B&Object&M1&M2::m}();
+  new self::C::•(null).{self::_C&Object&M1&M2::m}();
+  new self::D::•<dynamic>().{self::_D&Object&G1::m}();
+  new self::D::•<core::int*>().{self::_D&Object&G1::m}();
+  new self::D::•<core::List<core::int*>*>().{self::_D&Object&G1::m}();
 }
diff --git a/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
index 0ddd631..a6c21d2 100644
--- a/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
@@ -6,6 +6,8 @@
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
+  method m() → dynamic
+    return core::print("M1");
   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
@@ -16,8 +18,6 @@
   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
-  method m() → dynamic
-    return core::print("M1");
 }
 abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
@@ -79,6 +79,8 @@
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
+  method m() → dynamic
+    return core::print("M1");
   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
@@ -89,8 +91,6 @@
   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
-  method m() → dynamic
-    return core::print("M1");
 }
 abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
@@ -135,6 +135,8 @@
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
+  method m() → dynamic
+    return core::print(self::_D&Object&G1::S*);
   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
@@ -145,8 +147,6 @@
   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
-  method m() → dynamic
-    return core::print(self::_D&Object&G1::S*);
 }
 class D<S extends core::Object* = dynamic> extends self::_D&Object&G1<self::D::S*> {
   synthetic constructor •() → self::D<self::D::S*>*
@@ -154,9 +154,9 @@
     ;
 }
 static method main() → dynamic {
-  new self::B::•(null).{self::M2::m}();
-  new self::C::•(null).{self::M2::m}();
-  new self::D::•<dynamic>().{self::G1::m}();
-  new self::D::•<core::int*>().{self::G1::m}();
-  new self::D::•<core::List<core::int*>*>().{self::G1::m}();
+  new self::B::•(null).{self::_B&Object&M1&M2::m}();
+  new self::C::•(null).{self::_C&Object&M1&M2::m}();
+  new self::D::•<dynamic>().{self::_D&Object&G1::m}();
+  new self::D::•<core::int*>().{self::_D&Object&G1::m}();
+  new self::D::•<core::List<core::int*>*>().{self::_D&Object&G1::m}();
 }
diff --git a/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect b/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
index 7ea8f01..db60ecb 100644
--- a/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_application_override.dart.outline.expect
@@ -203,7 +203,8 @@
   synthetic constructor •() → self::A0*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1&S&M1*
@@ -214,7 +215,8 @@
   synthetic constructor •() → self::A1*
     : super self::_A1&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1*
@@ -230,13 +232,15 @@
   synthetic constructor •() → self::A2*
     : super self::_A2&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A0X = self::_A0X&S&M with self::MX {
   synthetic constructor •() → self::A0X*
@@ -252,7 +256,8 @@
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A1X = self::_A1X&S&M1&M with self::MX {
   synthetic constructor •() → self::A1X*
@@ -273,7 +278,8 @@
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A2X = self::_A2X&S&M1&M2&M with self::MX {
   synthetic constructor •() → self::A2X*
@@ -284,7 +290,8 @@
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B0 extends self::_B0&S&M {
   synthetic constructor •() → self::B0*
@@ -299,7 +306,8 @@
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B1 extends self::_B1&S&M1&M {
   synthetic constructor •() → self::B1*
@@ -319,7 +327,8 @@
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B2 extends self::_B2&S&M1&M2&M {
   synthetic constructor •() → self::B2*
@@ -329,7 +338,8 @@
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M&MX*
@@ -349,7 +359,8 @@
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
@@ -374,7 +385,8 @@
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
diff --git a/pkg/front_end/testcases/general/mixin_application_override.dart.strong.expect b/pkg/front_end/testcases/general/mixin_application_override.dart.strong.expect
index 5279085..56cdffa 100644
--- a/pkg/front_end/testcases/general/mixin_application_override.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_application_override.dart.strong.expect
@@ -206,7 +206,8 @@
   synthetic constructor •() → self::A0*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1&S&M1*
@@ -217,7 +218,8 @@
   synthetic constructor •() → self::A1*
     : super self::_A1&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1*
@@ -233,13 +235,15 @@
   synthetic constructor •() → self::A2*
     : super self::_A2&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A0X = self::_A0X&S&M with self::MX {
   synthetic constructor •() → self::A0X*
@@ -255,7 +259,8 @@
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A1X = self::_A1X&S&M1&M with self::MX {
   synthetic constructor •() → self::A1X*
@@ -276,7 +281,8 @@
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A2X = self::_A2X&S&M1&M2&M with self::MX {
   synthetic constructor •() → self::A2X*
@@ -287,7 +293,8 @@
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B0 extends self::_B0&S&M {
   synthetic constructor •() → self::B0*
@@ -303,7 +310,8 @@
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B1 extends self::_B1&S&M1&M {
   synthetic constructor •() → self::B1*
@@ -324,7 +332,8 @@
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B2 extends self::_B2&S&M1&M2&M {
   synthetic constructor •() → self::B2*
@@ -335,7 +344,8 @@
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M&MX*
@@ -356,7 +366,8 @@
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
@@ -382,7 +393,8 @@
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
index a645393..ffe0ebf 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
@@ -53,6 +53,8 @@
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
   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
@@ -68,6 +70,8 @@
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
   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
@@ -103,6 +107,8 @@
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -118,6 +124,8 @@
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -133,6 +141,8 @@
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -152,6 +162,8 @@
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
index d80d9f8..94fa4c4 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
@@ -53,6 +53,8 @@
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
   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
@@ -68,6 +70,8 @@
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
   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
@@ -104,6 +108,8 @@
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -119,6 +125,8 @@
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -134,6 +142,8 @@
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -154,6 +164,8 @@
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
index 0206494..fb7371c 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
@@ -53,6 +53,7 @@
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
+  method foo() → dynamic {}
   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
@@ -63,12 +64,12 @@
   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
-  method foo() → dynamic {}
 }
 abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
+  method foo() → dynamic {}
   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
@@ -79,7 +80,6 @@
   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
-  method foo() → dynamic {}
 }
 class C extends self::_C&Object&N {
   synthetic constructor •() → self::C*
@@ -106,6 +106,7 @@
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
+  method bar() → dynamic {}
   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
@@ -116,12 +117,12 @@
   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
-  method bar() → dynamic {}
 }
 abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
+  method bar() → dynamic {}
   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
@@ -132,12 +133,12 @@
   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
-  method bar() → dynamic {}
 }
 abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
+  method bar() → dynamic {}
   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
@@ -148,7 +149,6 @@
   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
-  method bar() → dynamic {}
 }
 class C2 extends self::_C2&Object&M2 {
   synthetic constructor •() → self::C2*
@@ -159,6 +159,7 @@
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
+  method bar() → dynamic {}
   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
@@ -169,7 +170,6 @@
   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
-  method bar() → dynamic {}
 }
 abstract class C3 extends self::_C3&Object&M2 {
   synthetic constructor •() → self::C3*
diff --git a/pkg/front_end/testcases/general/mixin_covariant.dart.outline.expect b/pkg/front_end/testcases/general/mixin_covariant.dart.outline.expect
index 6abaa8b..222ba3a 100644
--- a/pkg/front_end/testcases/general/mixin_covariant.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_covariant.dart.outline.expect
@@ -45,6 +45,8 @@
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(covariant core::int* a, core::int* b) → dynamic
+    return super.{self::M1::method}(a, b);
   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
@@ -61,7 +63,7 @@
     : super self::_C&Object&M1::•()
     ;
   forwarding-stub method method(covariant core::int* a, covariant core::int* b) → dynamic
-    return super.{self::M1::method}(a, b);
+    return super.{self::M2::method}(a, b);
 }
 class C extends self::_C&Object&M1&M2 {
   synthetic constructor •() → self::C*
@@ -284,20 +286,20 @@
     : super self::Superclass::•()
     ;
   forwarding-stub method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, covariant core::int* e) → void
-    return super.{self::Superclass::method}(a, b, c, d, e);
+    return super.{self::Mixin1::method}(a, b, c, d, e);
 }
 abstract class _Mixed&Superclass&Mixin1&Mixin2 = self::_Mixed&Superclass&Mixin1 with self::Mixin2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Mixed&Superclass&Mixin1&Mixin2*
     : super self::_Mixed&Superclass&Mixin1::•()
     ;
   forwarding-stub method method(core::int* a, core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
-    return super.{self::Superclass::method}(a, b, c, d, e);
+    return super.{self::Mixin2::method}(a, b, c, d, e);
 }
 class Mixed extends self::_Mixed&Superclass&Mixin1&Mixin2 implements self::Interface1, self::Interface2 {
   synthetic constructor •() → self::Mixed*
     ;
   forwarding-stub method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
-    return super.{self::Superclass::method}(a, b, c, d, e);
+    return super.{self::Mixin2::method}(a, b, c, d, e);
 }
 static method main() → void
   ;
diff --git a/pkg/front_end/testcases/general/mixin_covariant.dart.strong.expect b/pkg/front_end/testcases/general/mixin_covariant.dart.strong.expect
index 4c79ba0..4fd3d8d 100644
--- a/pkg/front_end/testcases/general/mixin_covariant.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_covariant.dart.strong.expect
@@ -45,6 +45,8 @@
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(covariant core::int* a, core::int* b) → dynamic
+    return super.{self::M1::method}(a, b);
   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
@@ -61,7 +63,7 @@
     : super self::_C&Object&M1::•()
     ;
   forwarding-stub method method(covariant core::int* a, covariant core::int* b) → dynamic
-    return super.{self::M1::method}(a, b);
+    return super.{self::M2::method}(a, b);
 }
 class C extends self::_C&Object&M1&M2 {
   synthetic constructor •() → self::C*
@@ -284,21 +286,21 @@
     : super self::Superclass::•()
     ;
   forwarding-stub method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, covariant core::int* e) → void
-    return super.{self::Superclass::method}(a, b, c, d, e);
+    return super.{self::Mixin1::method}(a, b, c, d, e);
 }
 abstract class _Mixed&Superclass&Mixin1&Mixin2 = self::_Mixed&Superclass&Mixin1 with self::Mixin2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Mixed&Superclass&Mixin1&Mixin2*
     : super self::_Mixed&Superclass&Mixin1::•()
     ;
   forwarding-stub method method(core::int* a, core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
-    return super.{self::Superclass::method}(a, b, c, d, e);
+    return super.{self::Mixin2::method}(a, b, c, d, e);
 }
 class Mixed extends self::_Mixed&Superclass&Mixin1&Mixin2 implements self::Interface1, self::Interface2 {
   synthetic constructor •() → self::Mixed*
     : super self::_Mixed&Superclass&Mixin1&Mixin2::•()
     ;
   forwarding-stub method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
-    return super.{self::Superclass::method}(a, b, c, d, e);
+    return super.{self::Mixin2::method}(a, b, c, d, e);
 }
 static method main() → void {
   self::testDirect();
diff --git a/pkg/front_end/testcases/general/mixin_covariant.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_covariant.dart.strong.transformed.expect
index af45d4a..8069ae7 100644
--- a/pkg/front_end/testcases/general/mixin_covariant.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_covariant.dart.strong.transformed.expect
@@ -45,6 +45,7 @@
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
+  method method(covariant core::int* a, core::int* b) → dynamic {}
   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
@@ -55,7 +56,6 @@
   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
-  method method(covariant core::int* a, core::int* b) → dynamic {}
 }
 abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
@@ -326,7 +326,7 @@
     : super self::_Mixed&Superclass&Mixin1&Mixin2::•()
     ;
   forwarding-stub method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
-    return super.{self::Superclass::method}(a, b, c, d, e);
+    return super.{self::Mixin2::method}(a, b, c, d, e);
 }
 static method main() → void {
   self::testDirect();
diff --git a/pkg/front_end/testcases/general/mixin_covariant2.dart.outline.expect b/pkg/front_end/testcases/general/mixin_covariant2.dart.outline.expect
index 8a608cb..01e76d1 100644
--- a/pkg/front_end/testcases/general/mixin_covariant2.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_covariant2.dart.outline.expect
@@ -50,11 +50,14 @@
   synthetic constructor •() → self::_Class&Superclass&Mixin*
     : super self::Superclass::•()
     ;
-  abstract forwarding-stub method method2(covariant core::num* argument1, core::num* argument2) → core::String*;
+  mixin-super-stub method method1(core::num* argument1, core::num* argument2) → core::String*
+    return super.{self::Mixin::method1}(argument1, argument2);
+  mixin-super-stub method method2(covariant core::int* argument1, core::num* argument2) → core::String*
+    return super.{self::Mixin::method2}(argument1, argument2);
   forwarding-stub method method3(core::num* argument1, covariant core::num* argument2) → core::String*
-    return super.{self::Superclass::method3}(argument1, argument2);
-  forwarding-stub method method4(covariant core::num* argument1, covariant core::num* argument2) → core::String*
-    return super.{self::Superclass::method4}(argument1, argument2);
+    return super.{self::Mixin::method3}(argument1, argument2);
+  forwarding-stub method method4(covariant core::int* argument1, covariant core::int* argument2) → core::String*
+    return super.{self::Mixin::method4}(argument1, argument2);
 }
 class Class extends self::_Class&Superclass&Mixin {
   synthetic constructor •() → self::Class*
diff --git a/pkg/front_end/testcases/general/mixin_covariant2.dart.strong.expect b/pkg/front_end/testcases/general/mixin_covariant2.dart.strong.expect
index 62e8537..f6a8a4d 100644
--- a/pkg/front_end/testcases/general/mixin_covariant2.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_covariant2.dart.strong.expect
@@ -52,11 +52,14 @@
   synthetic constructor •() → self::_Class&Superclass&Mixin*
     : super self::Superclass::•()
     ;
-  abstract forwarding-stub method method2(covariant core::num* argument1, core::num* argument2) → core::String*;
+  mixin-super-stub method method1(core::num* argument1, core::num* argument2) → core::String*
+    return super.{self::Mixin::method1}(argument1, argument2);
+  mixin-super-stub method method2(covariant core::int* argument1, core::num* argument2) → core::String*
+    return super.{self::Mixin::method2}(argument1, argument2);
   forwarding-stub method method3(core::num* argument1, covariant core::num* argument2) → core::String*
-    return super.{self::Superclass::method3}(argument1, argument2);
-  forwarding-stub method method4(covariant core::num* argument1, covariant core::num* argument2) → core::String*
-    return super.{self::Superclass::method4}(argument1, argument2);
+    return super.{self::Mixin::method3}(argument1, argument2);
+  forwarding-stub method method4(covariant core::int* argument1, covariant core::int* argument2) → core::String*
+    return super.{self::Mixin::method4}(argument1, argument2);
 }
 class Class extends self::_Class&Superclass&Mixin {
   synthetic constructor •() → self::Class*
@@ -65,7 +68,7 @@
 }
 static method main() → dynamic {
   self::Class* c = new self::Class::•();
-  self::expect("Mixin", c.{self::Mixin::method1}(0, 1));
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method1}(0, 1));
   self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method2}(0, 1));
   self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method3}(0, 1));
   self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method4}(0, 1));
diff --git a/pkg/front_end/testcases/general/mixin_covariant2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_covariant2.dart.strong.transformed.expect
new file mode 100644
index 0000000..59eca02
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_covariant2.dart.strong.transformed.expect
@@ -0,0 +1,109 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass*
+    : super core::Object::•()
+    ;
+  method method1(core::num* argument1, core::num* argument2) → core::String*
+    return "Superclass";
+  method method2(core::num* argument1, core::num* argument2) → core::String*
+    return "Superclass";
+  method method3(core::num* argument1, covariant core::int* argument2) → core::String*
+    return "Superclass";
+  method method4(core::num* argument1, covariant core::num* argument2) → core::String*
+    return "Superclass";
+  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
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin*
+    : super core::Object::•()
+    ;
+  method method1(core::num* argument1, core::num* argument2) → core::String*
+    return "Mixin";
+  method method2(covariant core::int* argument1, core::num* argument2) → core::String*
+    return "Mixin";
+  method method3(core::num* argument1, core::num* argument2) → core::String*
+    return "Mixin";
+  method method4(covariant core::int* argument1, core::int* argument2) → core::String*
+    return "Mixin";
+  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
+}
+abstract class _Class&Superclass&Mixin extends self::Superclass implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_Class&Superclass&Mixin*
+    : super self::Superclass::•()
+    ;
+  method method1(core::num* argument1, core::num* argument2) → core::String*
+    return "Mixin";
+  method method2(covariant core::int* argument1, core::num* argument2) → core::String*
+    return "Mixin";
+  method method3(core::num* argument1, covariant core::num* argument2) → core::String*
+    return "Mixin";
+  method method4(covariant core::int* argument1, covariant core::int* argument2) → core::String*
+    return "Mixin";
+  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
+}
+class Class extends self::_Class&Superclass&Mixin {
+  synthetic constructor •() → self::Class*
+    : super self::_Class&Superclass&Mixin::•()
+    ;
+}
+static method main() → dynamic {
+  self::Class* c = new self::Class::•();
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method1}(0, 1));
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method2}(0, 1));
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method3}(0, 1));
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method4}(0, 1));
+  self::Superclass* s = c;
+  self::expect("Mixin", s.{self::Superclass::method1}(0.5, 1.5));
+  self::throws(() → core::String* => s.{self::Superclass::method2}(0.5, 1.5));
+  self::expect("Mixin", s.{self::Superclass::method3}(0.5, 1));
+  self::throws(() → core::String* => s.{self::Superclass::method4}(0.5, 1));
+  self::expect("Mixin", s.{self::Superclass::method4}(1, 0.5));
+  self::Mixin* m = c;
+  self::expect("Mixin", m.{self::Mixin::method1}(0, 1));
+  self::expect("Mixin", m.{self::Mixin::method2}(0, 1));
+  self::expect("Mixin", m.{self::Mixin::method3}(0, 1));
+  self::expect("Mixin", m.{self::Mixin::method4}(0, 1));
+}
+static method expect(dynamic expected, dynamic actual) → void {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() →* void f) → void {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic _) {
+    return;
+  }
+  throw "Expected exception";
+}
diff --git a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
index 2fcf532..4366b2f 100644
--- a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
@@ -41,6 +41,12 @@
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
+  mixin-super-stub get _field() → self::B*
+    return super.{self::C::_field};
+  mixin-super-stub set _field(generic-covariant-impl self::B* value) → void
+    return super.{self::C::_field} = value;
+  mixin-super-stub method foo(generic-covariant-impl self::B* x) → dynamic
+    return super.{self::C::foo}(x);
   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
diff --git a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
index a06cb3c..5465909 100644
--- a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
@@ -45,6 +45,12 @@
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
+  mixin-super-stub get _field() → self::B*
+    return super.{self::C::_field};
+  mixin-super-stub set _field(generic-covariant-impl self::B* value) → void
+    return super.{self::C::_field} = value;
+  mixin-super-stub method foo(generic-covariant-impl self::B* x) → dynamic
+    return super.{self::C::foo}(x);
   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
@@ -68,5 +74,5 @@
 }
 static method main() → dynamic {
   self::Foo* foo = new self::Foo::•();
-  foo.{self::C::foo}(new self::B::•());
+  foo.{self::_Foo&Object&C::foo}(new self::B::•());
 }
diff --git a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
index 86683a1..9828c0d 100644
--- a/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
@@ -46,6 +46,9 @@
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
+  method foo(generic-covariant-impl self::B* x) → dynamic {
+    this.{self::C::_field} = x;
+  }
   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
@@ -56,9 +59,6 @@
   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
-  method foo(generic-covariant-impl self::B* x) → dynamic {
-    this.{self::C::_field} = x;
-  }
 }
 class Foo extends self::_Foo&Object&C {
   synthetic constructor •() → self::Foo*
@@ -72,5 +72,5 @@
 }
 static method main() → dynamic {
   self::Foo* foo = new self::Foo::•();
-  foo.{self::C::foo}(new self::B::•());
+  foo.{self::_Foo&Object&C::foo}(new self::B::•());
 }
diff --git a/pkg/front_end/testcases/general/mixin_stubs.dart b/pkg/front_end/testcases/general/mixin_stubs.dart
new file mode 100644
index 0000000..59f0691
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_stubs.dart
@@ -0,0 +1,98 @@
+// 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.
+
+abstract class Super {
+  void concreteExtendsConcreteMixin() {}
+  void concreteExtendsAbstractMixin() {}
+  void abstractExtendsConcreteMixin();
+  void abstractExtendsAbstractMixin();
+}
+
+abstract class MixinClass {
+  void concreteExtendsConcreteMixin() {}
+  void concreteExtendsAbstractMixin();
+  void concreteMixin() {}
+  void abstractExtendsConcreteMixin() {}
+  void abstractExtendsAbstractMixin();
+  void abstractMixin();
+}
+
+mixin Mixin {
+  void concreteExtendsConcreteMixin() {}
+  void concreteExtendsAbstractMixin();
+  void concreteMixin() {}
+  void abstractExtendsConcreteMixin() {}
+  void abstractExtendsAbstractMixin();
+  void abstractMixin();
+}
+
+abstract class ClassEqMixinClass = Super with MixinClass;
+
+abstract class ClassExtendsMixinClass extends Super with MixinClass {}
+
+abstract class ClassEqMixin = Super with Mixin;
+
+abstract class ClassExtendsMixin extends Super with Mixin {}
+
+abstract class SubclassEqMixinClass extends ClassEqMixinClass {
+  method() {
+    concreteExtendsConcreteMixin();
+    concreteExtendsAbstractMixin();
+    concreteMixin();
+    abstractExtendsConcreteMixin();
+    abstractExtendsAbstractMixin();
+    abstractMixin();
+    super.concreteExtendsConcreteMixin();
+    super.concreteExtendsAbstractMixin();
+    super.concreteMixin();
+    super.abstractExtendsConcreteMixin();
+  }
+}
+
+abstract class SubclassExtendsMixinClass extends ClassExtendsMixinClass {
+  method() {
+    concreteExtendsConcreteMixin();
+    concreteMixin();
+    concreteExtendsAbstractMixin();
+    abstractExtendsConcreteMixin();
+    abstractExtendsAbstractMixin();
+    abstractMixin();
+    super.concreteExtendsConcreteMixin();
+    super.concreteExtendsAbstractMixin();
+    super.concreteMixin();
+    super.abstractExtendsConcreteMixin();
+  }
+}
+
+abstract class SubclassEqMixin extends ClassEqMixin {
+  method() {
+    concreteExtendsConcreteMixin();
+    concreteExtendsAbstractMixin();
+    concreteMixin();
+    abstractExtendsConcreteMixin();
+    abstractExtendsAbstractMixin();
+    abstractMixin();
+    super.concreteExtendsConcreteMixin();
+    super.concreteExtendsAbstractMixin();
+    super.concreteMixin();
+    super.abstractExtendsConcreteMixin();
+  }
+}
+
+abstract class SubclassExtendsMixin extends ClassExtendsMixin {
+  method() {
+    concreteExtendsConcreteMixin();
+    concreteExtendsAbstractMixin();
+    concreteMixin();
+    abstractExtendsConcreteMixin();
+    abstractExtendsAbstractMixin();
+    abstractMixin();
+    super.concreteExtendsConcreteMixin();
+    super.concreteExtendsAbstractMixin();
+    super.concreteMixin();
+    super.abstractExtendsConcreteMixin();
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/mixin_stubs.dart.outline.expect b/pkg/front_end/testcases/general/mixin_stubs.dart.outline.expect
new file mode 100644
index 0000000..8f9542d
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_stubs.dart.outline.expect
@@ -0,0 +1,158 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super*
+    ;
+  method concreteExtendsConcreteMixin() → void
+    ;
+  method concreteExtendsAbstractMixin() → void
+    ;
+  abstract method abstractExtendsConcreteMixin() → void;
+  abstract method abstractExtendsAbstractMixin() → void;
+  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
+}
+abstract class MixinClass extends core::Object {
+  synthetic constructor •() → self::MixinClass*
+    ;
+  method concreteExtendsConcreteMixin() → void
+    ;
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void
+    ;
+  method abstractExtendsConcreteMixin() → void
+    ;
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+  method concreteExtendsConcreteMixin() → void
+    ;
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void
+    ;
+  method abstractExtendsConcreteMixin() → void
+    ;
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class ClassEqMixinClass = self::Super with self::MixinClass {
+  synthetic constructor •() → self::ClassEqMixinClass*
+    : super self::Super::•()
+    ;
+  mixin-super-stub method concreteExtendsConcreteMixin() → void
+    return super.{self::MixinClass::concreteExtendsConcreteMixin}();
+  abstract mixin-stub method concreteExtendsAbstractMixin() → void; -> self::MixinClass::concreteExtendsAbstractMixin
+  mixin-super-stub method concreteMixin() → void
+    return super.{self::MixinClass::concreteMixin}();
+  mixin-super-stub method abstractExtendsConcreteMixin() → void
+    return super.{self::MixinClass::abstractExtendsConcreteMixin}();
+  abstract mixin-stub method abstractExtendsAbstractMixin() → void; -> self::MixinClass::abstractExtendsAbstractMixin
+  abstract mixin-stub method abstractMixin() → void; -> self::MixinClass::abstractMixin
+}
+abstract class _ClassExtendsMixinClass&Super&MixinClass = self::Super with self::MixinClass /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassExtendsMixinClass&Super&MixinClass*
+    : super self::Super::•()
+    ;
+  mixin-super-stub method concreteExtendsConcreteMixin() → void
+    return super.{self::MixinClass::concreteExtendsConcreteMixin}();
+  abstract mixin-stub method concreteExtendsAbstractMixin() → void; -> self::MixinClass::concreteExtendsAbstractMixin
+  mixin-super-stub method concreteMixin() → void
+    return super.{self::MixinClass::concreteMixin}();
+  mixin-super-stub method abstractExtendsConcreteMixin() → void
+    return super.{self::MixinClass::abstractExtendsConcreteMixin}();
+  abstract mixin-stub method abstractExtendsAbstractMixin() → void; -> self::MixinClass::abstractExtendsAbstractMixin
+  abstract mixin-stub method abstractMixin() → void; -> self::MixinClass::abstractMixin
+}
+abstract class ClassExtendsMixinClass extends self::_ClassExtendsMixinClass&Super&MixinClass {
+  synthetic constructor •() → self::ClassExtendsMixinClass*
+    ;
+}
+abstract class ClassEqMixin = self::Super with self::Mixin {
+  synthetic constructor •() → self::ClassEqMixin*
+    : super self::Super::•()
+    ;
+  mixin-super-stub method concreteExtendsConcreteMixin() → void
+    return super.{self::Mixin::concreteExtendsConcreteMixin}();
+  abstract mixin-stub method concreteExtendsAbstractMixin() → void; -> self::Mixin::concreteExtendsAbstractMixin
+  mixin-super-stub method concreteMixin() → void
+    return super.{self::Mixin::concreteMixin}();
+  mixin-super-stub method abstractExtendsConcreteMixin() → void
+    return super.{self::Mixin::abstractExtendsConcreteMixin}();
+  abstract mixin-stub method abstractExtendsAbstractMixin() → void; -> self::Mixin::abstractExtendsAbstractMixin
+  abstract mixin-stub method abstractMixin() → void; -> self::Mixin::abstractMixin
+}
+abstract class _ClassExtendsMixin&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassExtendsMixin&Super&Mixin*
+    : super self::Super::•()
+    ;
+  mixin-super-stub method concreteExtendsConcreteMixin() → void
+    return super.{self::Mixin::concreteExtendsConcreteMixin}();
+  abstract mixin-stub method concreteExtendsAbstractMixin() → void; -> self::Mixin::concreteExtendsAbstractMixin
+  mixin-super-stub method concreteMixin() → void
+    return super.{self::Mixin::concreteMixin}();
+  mixin-super-stub method abstractExtendsConcreteMixin() → void
+    return super.{self::Mixin::abstractExtendsConcreteMixin}();
+  abstract mixin-stub method abstractExtendsAbstractMixin() → void; -> self::Mixin::abstractExtendsAbstractMixin
+  abstract mixin-stub method abstractMixin() → void; -> self::Mixin::abstractMixin
+}
+abstract class ClassExtendsMixin extends self::_ClassExtendsMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassExtendsMixin*
+    ;
+}
+abstract class SubclassEqMixinClass extends self::ClassEqMixinClass {
+  synthetic constructor •() → self::SubclassEqMixinClass*
+    ;
+  method method() → dynamic
+    ;
+}
+abstract class SubclassExtendsMixinClass extends self::ClassExtendsMixinClass {
+  synthetic constructor •() → self::SubclassExtendsMixinClass*
+    ;
+  method method() → dynamic
+    ;
+}
+abstract class SubclassEqMixin extends self::ClassEqMixin {
+  synthetic constructor •() → self::SubclassEqMixin*
+    ;
+  method method() → dynamic
+    ;
+}
+abstract class SubclassExtendsMixin extends self::ClassExtendsMixin {
+  synthetic constructor •() → self::SubclassExtendsMixin*
+    ;
+  method method() → dynamic
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/mixin_stubs.dart.strong.expect b/pkg/front_end/testcases/general/mixin_stubs.dart.strong.expect
new file mode 100644
index 0000000..1a74047
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_stubs.dart.strong.expect
@@ -0,0 +1,197 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super*
+    : super core::Object::•()
+    ;
+  method concreteExtendsConcreteMixin() → void {}
+  method concreteExtendsAbstractMixin() → void {}
+  abstract method abstractExtendsConcreteMixin() → void;
+  abstract method abstractExtendsAbstractMixin() → void;
+  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
+}
+abstract class MixinClass extends core::Object {
+  synthetic constructor •() → self::MixinClass*
+    : super core::Object::•()
+    ;
+  method concreteExtendsConcreteMixin() → void {}
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void {}
+  method abstractExtendsConcreteMixin() → void {}
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+  method concreteExtendsConcreteMixin() → void {}
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void {}
+  method abstractExtendsConcreteMixin() → void {}
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class ClassEqMixinClass = self::Super with self::MixinClass {
+  synthetic constructor •() → self::ClassEqMixinClass*
+    : super self::Super::•()
+    ;
+  mixin-super-stub method concreteExtendsConcreteMixin() → void
+    return super.{self::MixinClass::concreteExtendsConcreteMixin}();
+  abstract mixin-stub method concreteExtendsAbstractMixin() → void; -> self::MixinClass::concreteExtendsAbstractMixin
+  mixin-super-stub method concreteMixin() → void
+    return super.{self::MixinClass::concreteMixin}();
+  mixin-super-stub method abstractExtendsConcreteMixin() → void
+    return super.{self::MixinClass::abstractExtendsConcreteMixin}();
+  abstract mixin-stub method abstractExtendsAbstractMixin() → void; -> self::MixinClass::abstractExtendsAbstractMixin
+  abstract mixin-stub method abstractMixin() → void; -> self::MixinClass::abstractMixin
+}
+abstract class _ClassExtendsMixinClass&Super&MixinClass = self::Super with self::MixinClass /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassExtendsMixinClass&Super&MixinClass*
+    : super self::Super::•()
+    ;
+  mixin-super-stub method concreteExtendsConcreteMixin() → void
+    return super.{self::MixinClass::concreteExtendsConcreteMixin}();
+  abstract mixin-stub method concreteExtendsAbstractMixin() → void; -> self::MixinClass::concreteExtendsAbstractMixin
+  mixin-super-stub method concreteMixin() → void
+    return super.{self::MixinClass::concreteMixin}();
+  mixin-super-stub method abstractExtendsConcreteMixin() → void
+    return super.{self::MixinClass::abstractExtendsConcreteMixin}();
+  abstract mixin-stub method abstractExtendsAbstractMixin() → void; -> self::MixinClass::abstractExtendsAbstractMixin
+  abstract mixin-stub method abstractMixin() → void; -> self::MixinClass::abstractMixin
+}
+abstract class ClassExtendsMixinClass extends self::_ClassExtendsMixinClass&Super&MixinClass {
+  synthetic constructor •() → self::ClassExtendsMixinClass*
+    : super self::_ClassExtendsMixinClass&Super&MixinClass::•()
+    ;
+}
+abstract class ClassEqMixin = self::Super with self::Mixin {
+  synthetic constructor •() → self::ClassEqMixin*
+    : super self::Super::•()
+    ;
+  mixin-super-stub method concreteExtendsConcreteMixin() → void
+    return super.{self::Mixin::concreteExtendsConcreteMixin}();
+  abstract mixin-stub method concreteExtendsAbstractMixin() → void; -> self::Mixin::concreteExtendsAbstractMixin
+  mixin-super-stub method concreteMixin() → void
+    return super.{self::Mixin::concreteMixin}();
+  mixin-super-stub method abstractExtendsConcreteMixin() → void
+    return super.{self::Mixin::abstractExtendsConcreteMixin}();
+  abstract mixin-stub method abstractExtendsAbstractMixin() → void; -> self::Mixin::abstractExtendsAbstractMixin
+  abstract mixin-stub method abstractMixin() → void; -> self::Mixin::abstractMixin
+}
+abstract class _ClassExtendsMixin&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassExtendsMixin&Super&Mixin*
+    : super self::Super::•()
+    ;
+  mixin-super-stub method concreteExtendsConcreteMixin() → void
+    return super.{self::Mixin::concreteExtendsConcreteMixin}();
+  abstract mixin-stub method concreteExtendsAbstractMixin() → void; -> self::Mixin::concreteExtendsAbstractMixin
+  mixin-super-stub method concreteMixin() → void
+    return super.{self::Mixin::concreteMixin}();
+  mixin-super-stub method abstractExtendsConcreteMixin() → void
+    return super.{self::Mixin::abstractExtendsConcreteMixin}();
+  abstract mixin-stub method abstractExtendsAbstractMixin() → void; -> self::Mixin::abstractExtendsAbstractMixin
+  abstract mixin-stub method abstractMixin() → void; -> self::Mixin::abstractMixin
+}
+abstract class ClassExtendsMixin extends self::_ClassExtendsMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassExtendsMixin*
+    : super self::_ClassExtendsMixin&Super&Mixin::•()
+    ;
+}
+abstract class SubclassEqMixinClass extends self::ClassEqMixinClass {
+  synthetic constructor •() → self::SubclassEqMixinClass*
+    : super self::ClassEqMixinClass::•()
+    ;
+  method method() → dynamic {
+    this.{self::ClassEqMixinClass::concreteExtendsConcreteMixin}();
+    this.{self::ClassEqMixinClass::concreteExtendsAbstractMixin}();
+    this.{self::ClassEqMixinClass::concreteMixin}();
+    this.{self::ClassEqMixinClass::abstractExtendsConcreteMixin}();
+    this.{self::ClassEqMixinClass::abstractExtendsAbstractMixin}();
+    this.{self::ClassEqMixinClass::abstractMixin}();
+    super.{self::ClassEqMixinClass::concreteExtendsConcreteMixin}();
+    super.{self::Super::concreteExtendsAbstractMixin}();
+    super.{self::ClassEqMixinClass::concreteMixin}();
+    super.{self::ClassEqMixinClass::abstractExtendsConcreteMixin}();
+  }
+}
+abstract class SubclassExtendsMixinClass extends self::ClassExtendsMixinClass {
+  synthetic constructor •() → self::SubclassExtendsMixinClass*
+    : super self::ClassExtendsMixinClass::•()
+    ;
+  method method() → dynamic {
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteExtendsConcreteMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteExtendsAbstractMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::abstractExtendsConcreteMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::abstractExtendsAbstractMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::abstractMixin}();
+    super.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteExtendsConcreteMixin}();
+    super.{self::Super::concreteExtendsAbstractMixin}();
+    super.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteMixin}();
+    super.{self::_ClassExtendsMixinClass&Super&MixinClass::abstractExtendsConcreteMixin}();
+  }
+}
+abstract class SubclassEqMixin extends self::ClassEqMixin {
+  synthetic constructor •() → self::SubclassEqMixin*
+    : super self::ClassEqMixin::•()
+    ;
+  method method() → dynamic {
+    this.{self::ClassEqMixin::concreteExtendsConcreteMixin}();
+    this.{self::ClassEqMixin::concreteExtendsAbstractMixin}();
+    this.{self::ClassEqMixin::concreteMixin}();
+    this.{self::ClassEqMixin::abstractExtendsConcreteMixin}();
+    this.{self::ClassEqMixin::abstractExtendsAbstractMixin}();
+    this.{self::ClassEqMixin::abstractMixin}();
+    super.{self::ClassEqMixin::concreteExtendsConcreteMixin}();
+    super.{self::Super::concreteExtendsAbstractMixin}();
+    super.{self::ClassEqMixin::concreteMixin}();
+    super.{self::ClassEqMixin::abstractExtendsConcreteMixin}();
+  }
+}
+abstract class SubclassExtendsMixin extends self::ClassExtendsMixin {
+  synthetic constructor •() → self::SubclassExtendsMixin*
+    : super self::ClassExtendsMixin::•()
+    ;
+  method method() → dynamic {
+    this.{self::_ClassExtendsMixin&Super&Mixin::concreteExtendsConcreteMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::concreteExtendsAbstractMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::concreteMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::abstractExtendsConcreteMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::abstractExtendsAbstractMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::abstractMixin}();
+    super.{self::_ClassExtendsMixin&Super&Mixin::concreteExtendsConcreteMixin}();
+    super.{self::Super::concreteExtendsAbstractMixin}();
+    super.{self::_ClassExtendsMixin&Super&Mixin::concreteMixin}();
+    super.{self::_ClassExtendsMixin&Super&Mixin::abstractExtendsConcreteMixin}();
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/mixin_stubs.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_stubs.dart.strong.transformed.expect
new file mode 100644
index 0000000..53cf7f1
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_stubs.dart.strong.transformed.expect
@@ -0,0 +1,225 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super*
+    : super core::Object::•()
+    ;
+  method concreteExtendsConcreteMixin() → void {}
+  method concreteExtendsAbstractMixin() → void {}
+  abstract method abstractExtendsConcreteMixin() → void;
+  abstract method abstractExtendsAbstractMixin() → void;
+  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
+}
+abstract class MixinClass extends core::Object {
+  synthetic constructor •() → self::MixinClass*
+    : super core::Object::•()
+    ;
+  method concreteExtendsConcreteMixin() → void {}
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void {}
+  method abstractExtendsConcreteMixin() → void {}
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+  method concreteExtendsConcreteMixin() → void {}
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void {}
+  method abstractExtendsConcreteMixin() → void {}
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class ClassEqMixinClass extends self::Super implements self::MixinClass /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::ClassEqMixinClass*
+    : super self::Super::•()
+    ;
+  method concreteExtendsConcreteMixin() → void {}
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void {}
+  method abstractExtendsConcreteMixin() → void {}
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class _ClassExtendsMixinClass&Super&MixinClass extends self::Super implements self::MixinClass /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassExtendsMixinClass&Super&MixinClass*
+    : super self::Super::•()
+    ;
+  method concreteExtendsConcreteMixin() → void {}
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void {}
+  method abstractExtendsConcreteMixin() → void {}
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class ClassExtendsMixinClass extends self::_ClassExtendsMixinClass&Super&MixinClass {
+  synthetic constructor •() → self::ClassExtendsMixinClass*
+    : super self::_ClassExtendsMixinClass&Super&MixinClass::•()
+    ;
+}
+abstract class ClassEqMixin extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::ClassEqMixin*
+    : super self::Super::•()
+    ;
+  method concreteExtendsConcreteMixin() → void {}
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void {}
+  method abstractExtendsConcreteMixin() → void {}
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class _ClassExtendsMixin&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassExtendsMixin&Super&Mixin*
+    : super self::Super::•()
+    ;
+  method concreteExtendsConcreteMixin() → void {}
+  abstract method concreteExtendsAbstractMixin() → void;
+  method concreteMixin() → void {}
+  method abstractExtendsConcreteMixin() → void {}
+  abstract method abstractExtendsAbstractMixin() → void;
+  abstract method abstractMixin() → void;
+  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
+}
+abstract class ClassExtendsMixin extends self::_ClassExtendsMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassExtendsMixin*
+    : super self::_ClassExtendsMixin&Super&Mixin::•()
+    ;
+}
+abstract class SubclassEqMixinClass extends self::ClassEqMixinClass {
+  synthetic constructor •() → self::SubclassEqMixinClass*
+    : super self::ClassEqMixinClass::•()
+    ;
+  method method() → dynamic {
+    this.{self::ClassEqMixinClass::concreteExtendsConcreteMixin}();
+    this.{self::ClassEqMixinClass::concreteExtendsAbstractMixin}();
+    this.{self::ClassEqMixinClass::concreteMixin}();
+    this.{self::ClassEqMixinClass::abstractExtendsConcreteMixin}();
+    this.{self::ClassEqMixinClass::abstractExtendsAbstractMixin}();
+    this.{self::ClassEqMixinClass::abstractMixin}();
+    super.{self::ClassEqMixinClass::concreteExtendsConcreteMixin}();
+    super.{self::Super::concreteExtendsAbstractMixin}();
+    super.{self::ClassEqMixinClass::concreteMixin}();
+    super.{self::ClassEqMixinClass::abstractExtendsConcreteMixin}();
+  }
+}
+abstract class SubclassExtendsMixinClass extends self::ClassExtendsMixinClass {
+  synthetic constructor •() → self::SubclassExtendsMixinClass*
+    : super self::ClassExtendsMixinClass::•()
+    ;
+  method method() → dynamic {
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteExtendsConcreteMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteExtendsAbstractMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::abstractExtendsConcreteMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::abstractExtendsAbstractMixin}();
+    this.{self::_ClassExtendsMixinClass&Super&MixinClass::abstractMixin}();
+    super.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteExtendsConcreteMixin}();
+    super.{self::Super::concreteExtendsAbstractMixin}();
+    super.{self::_ClassExtendsMixinClass&Super&MixinClass::concreteMixin}();
+    super.{self::_ClassExtendsMixinClass&Super&MixinClass::abstractExtendsConcreteMixin}();
+  }
+}
+abstract class SubclassEqMixin extends self::ClassEqMixin {
+  synthetic constructor •() → self::SubclassEqMixin*
+    : super self::ClassEqMixin::•()
+    ;
+  method method() → dynamic {
+    this.{self::ClassEqMixin::concreteExtendsConcreteMixin}();
+    this.{self::ClassEqMixin::concreteExtendsAbstractMixin}();
+    this.{self::ClassEqMixin::concreteMixin}();
+    this.{self::ClassEqMixin::abstractExtendsConcreteMixin}();
+    this.{self::ClassEqMixin::abstractExtendsAbstractMixin}();
+    this.{self::ClassEqMixin::abstractMixin}();
+    super.{self::ClassEqMixin::concreteExtendsConcreteMixin}();
+    super.{self::Super::concreteExtendsAbstractMixin}();
+    super.{self::ClassEqMixin::concreteMixin}();
+    super.{self::ClassEqMixin::abstractExtendsConcreteMixin}();
+  }
+}
+abstract class SubclassExtendsMixin extends self::ClassExtendsMixin {
+  synthetic constructor •() → self::SubclassExtendsMixin*
+    : super self::ClassExtendsMixin::•()
+    ;
+  method method() → dynamic {
+    this.{self::_ClassExtendsMixin&Super&Mixin::concreteExtendsConcreteMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::concreteExtendsAbstractMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::concreteMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::abstractExtendsConcreteMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::abstractExtendsAbstractMixin}();
+    this.{self::_ClassExtendsMixin&Super&Mixin::abstractMixin}();
+    super.{self::_ClassExtendsMixin&Super&Mixin::concreteExtendsConcreteMixin}();
+    super.{self::Super::concreteExtendsAbstractMixin}();
+    super.{self::_ClassExtendsMixin&Super&Mixin::concreteMixin}();
+    super.{self::_ClassExtendsMixin&Super&Mixin::abstractExtendsConcreteMixin}();
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/mixin_stubs.dart.textual_outline.expect b/pkg/front_end/testcases/general/mixin_stubs.dart.textual_outline.expect
new file mode 100644
index 0000000..9a72527
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_stubs.dart.textual_outline.expect
@@ -0,0 +1,49 @@
+abstract class Super {
+  void concreteExtendsConcreteMixin() {}
+  void concreteExtendsAbstractMixin() {}
+  void abstractExtendsConcreteMixin();
+  void abstractExtendsAbstractMixin();
+}
+
+abstract class MixinClass {
+  void concreteExtendsConcreteMixin() {}
+  void concreteExtendsAbstractMixin();
+  void concreteMixin() {}
+  void abstractExtendsConcreteMixin() {}
+  void abstractExtendsAbstractMixin();
+  void abstractMixin();
+}
+
+mixin Mixin {
+  void concreteExtendsConcreteMixin() {}
+  void concreteExtendsAbstractMixin();
+  void concreteMixin() {}
+  void abstractExtendsConcreteMixin() {}
+  void abstractExtendsAbstractMixin();
+  void abstractMixin();
+}
+abstract class ClassEqMixinClass = Super with MixinClass;
+
+abstract class ClassExtendsMixinClass extends Super with MixinClass {}
+
+abstract class ClassEqMixin = Super with Mixin;
+
+abstract class ClassExtendsMixin extends Super with Mixin {}
+
+abstract class SubclassEqMixinClass extends ClassEqMixinClass {
+  method() {}
+}
+
+abstract class SubclassExtendsMixinClass extends ClassExtendsMixinClass {
+  method() {}
+}
+
+abstract class SubclassEqMixin extends ClassEqMixin {
+  method() {}
+}
+
+abstract class SubclassExtendsMixin extends ClassExtendsMixin {
+  method() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/mixin_stubs.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/mixin_stubs.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b8362ad
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_stubs.dart.textual_outline_modelled.expect
@@ -0,0 +1,48 @@
+abstract class ClassEqMixin = Super with Mixin;
+abstract class ClassEqMixinClass = Super with MixinClass;
+
+abstract class ClassExtendsMixin extends Super with Mixin {}
+
+abstract class ClassExtendsMixinClass extends Super with MixinClass {}
+
+abstract class MixinClass {
+  void abstractExtendsAbstractMixin();
+  void abstractExtendsConcreteMixin() {}
+  void abstractMixin();
+  void concreteExtendsAbstractMixin();
+  void concreteExtendsConcreteMixin() {}
+  void concreteMixin() {}
+}
+
+abstract class SubclassEqMixin extends ClassEqMixin {
+  method() {}
+}
+
+abstract class SubclassEqMixinClass extends ClassEqMixinClass {
+  method() {}
+}
+
+abstract class SubclassExtendsMixin extends ClassExtendsMixin {
+  method() {}
+}
+
+abstract class SubclassExtendsMixinClass extends ClassExtendsMixinClass {
+  method() {}
+}
+
+abstract class Super {
+  void abstractExtendsAbstractMixin();
+  void abstractExtendsConcreteMixin();
+  void concreteExtendsAbstractMixin() {}
+  void concreteExtendsConcreteMixin() {}
+}
+
+main() {}
+mixin Mixin {
+  void abstractExtendsAbstractMixin();
+  void abstractExtendsConcreteMixin() {}
+  void abstractMixin();
+  void concreteExtendsAbstractMixin();
+  void concreteExtendsConcreteMixin() {}
+  void concreteMixin() {}
+}
diff --git a/pkg/front_end/testcases/general/mixin_super_repeated.dart.outline.expect b/pkg/front_end/testcases/general/mixin_super_repeated.dart.outline.expect
index 54fe5ac..1a4626c 100644
--- a/pkg/front_end/testcases/general/mixin_super_repeated.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_super_repeated.dart.outline.expect
@@ -43,16 +43,28 @@
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
+  mixin-super-stub get m() → dynamic
+    return super.{self::M::m};
+  mixin-super-stub set m(dynamic value) → void
+    return super.{self::M::m} = value;
 }
 abstract class _Named&S&M&N = self::_Named&S&M with self::N /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
+  mixin-super-stub get superM() → dynamic
+    return super.{self::N::superM};
+  mixin-super-stub set superM(dynamic value) → void
+    return super.{self::N::superM} = value;
 }
 class Named = self::_Named&S&M&N with self::M {
   synthetic constructor •() → self::Named*
     : super self::_Named&S&M&N::•()
     ;
+  mixin-super-stub get m() → dynamic
+    return super.{self::M::m};
+  mixin-super-stub set m(dynamic value) → void
+    return super.{self::M::m} = value;
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.expect b/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.expect
index 2dfa48d..e9d4ae3 100644
--- a/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.expect
@@ -47,25 +47,37 @@
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
+  mixin-super-stub get m() → dynamic
+    return super.{self::M::m};
+  mixin-super-stub set m(dynamic value) → void
+    return super.{self::M::m} = value;
 }
 abstract class _Named&S&M&N = self::_Named&S&M with self::N /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
+  mixin-super-stub get superM() → dynamic
+    return super.{self::N::superM};
+  mixin-super-stub set superM(dynamic value) → void
+    return super.{self::N::superM} = value;
 }
 class Named = self::_Named&S&M&N with self::M {
   synthetic constructor •() → self::Named*
     : super self::_Named&S&M&N::•()
     ;
+  mixin-super-stub get m() → dynamic
+    return super.{self::M::m};
+  mixin-super-stub set m(dynamic value) → void
+    return super.{self::M::m} = value;
 }
 static method main() → dynamic {
   self::Named* named = new self::Named::•();
-  named.{self::M::m} = 42;
-  named.{self::N::superM} = 87;
-  if(!named.{self::M::m}.{core::Object::==}(42)) {
+  named.{self::Named::m} = 42;
+  named.{self::_Named&S&M&N::superM} = 87;
+  if(!named.{self::Named::m}.{core::Object::==}(42)) {
     throw "Bad mixin translation of set:superM";
   }
-  if(!named.{self::N::superM}.{core::Object::==}(87)) {
+  if(!named.{self::_Named&S&M&N::superM}.{core::Object::==}(87)) {
     throw "Bad mixin translation of get:superM";
   }
 }
diff --git a/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.transformed.expect
index 2d6e534..94ee731 100644
--- a/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_super_repeated.dart.strong.transformed.expect
@@ -63,11 +63,11 @@
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
+  get superM() → dynamic
+    return super.{self::M::m};
   set superM(dynamic value) → void {
     super.{self::M::m} = value;
   }
-  get superM() → dynamic
-    return super.{self::M::m};
 }
 class Named extends self::_Named&S&M&N implements self::M /*isEliminatedMixin*/  {
   field dynamic m = null;
@@ -87,12 +87,12 @@
 }
 static method main() → dynamic {
   self::Named* named = new self::Named::•();
-  named.{self::M::m} = 42;
-  named.{self::N::superM} = 87;
-  if(!named.{self::M::m}.{core::Object::==}(42)) {
+  named.{self::Named::m} = 42;
+  named.{self::_Named&S&M&N::superM} = 87;
+  if(!named.{self::Named::m}.{core::Object::==}(42)) {
     throw "Bad mixin translation of set:superM";
   }
-  if(!named.{self::N::superM}.{core::Object::==}(87)) {
+  if(!named.{self::_Named&S&M&N::superM}.{core::Object::==}(87)) {
     throw "Bad mixin translation of get:superM";
   }
 }
diff --git a/pkg/front_end/testcases/general/no_such_method_private_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/general/no_such_method_private_setter.dart.strong.transformed.expect
index ddb32d6..3e79735 100644
--- a/pkg/front_end/testcases/general/no_such_method_private_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/no_such_method_private_setter.dart.strong.transformed.expect
@@ -22,7 +22,7 @@
   no-such-method-forwarder get /* from org-dartlang-testcase:///no_such_method_private_setter_lib.dart */ _x() → core::int*
     return this.{self::Foo::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set /* from org-dartlang-testcase:///no_such_method_private_setter_lib.dart */ _x(core::int* value) → void
-    return this.{self::Foo::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Foo::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {
   no_::baz(new self::Foo::•());
diff --git a/pkg/front_end/testcases/general/nsm_covariance.dart.strong.transformed.expect b/pkg/front_end/testcases/general/nsm_covariance.dart.strong.transformed.expect
index ee2b26a..63f9b2e 100644
--- a/pkg/front_end/testcases/general/nsm_covariance.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/nsm_covariance.dart.strong.transformed.expect
@@ -60,11 +60,11 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method _method1(core::int* a, covariant core::int* b, generic-covariant-impl core::int* c, covariant generic-covariant-impl core::int* d) → void
-    return this.{self::D3::noSuchMethod}(new core::_InvocationMirror::_withType(#C3, 0, #C4, core::List::unmodifiable<dynamic>(<dynamic>[a, b, c, d]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
+    return this.{self::D3::noSuchMethod}(new core::_InvocationMirror::_withType(#C3, 0, #C4, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal4<dynamic>(a, b, c, d)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
   no-such-method-forwarder method _method2({core::int* a = #C1, covariant core::int* b = #C1, generic-covariant-impl core::int* c = #C1, covariant generic-covariant-impl core::int* d = #C1}) → void
     return this.{self::D3::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C4, #C5, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: a, #C9: b, #C10: c, #C11: d})));
   no-such-method-forwarder method _method3(covariant core::int* a, generic-covariant-impl core::int* b) → void
-    return this.{self::D3::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C4, core::List::unmodifiable<dynamic>(<dynamic>[a, b]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
+    return this.{self::D3::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C4, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal2<dynamic>(a, b)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
   no-such-method-forwarder method _method4({covariant core::int* a = #C1, generic-covariant-impl core::int* b = #C1}) → void
     return this.{self::D3::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 0, #C4, #C5, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: a, #C9: b})));
 }
@@ -85,11 +85,11 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method _method1(core::int* x, covariant core::int* y, generic-covariant-impl core::int* z, covariant generic-covariant-impl core::int* w) → void
-    return this.{self::D4::noSuchMethod}(new core::_InvocationMirror::_withType(#C3, 0, #C4, core::List::unmodifiable<dynamic>(<dynamic>[x, y, z, w]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
+    return this.{self::D4::noSuchMethod}(new core::_InvocationMirror::_withType(#C3, 0, #C4, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal4<dynamic>(x, y, z, w)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
   no-such-method-forwarder method _method2({core::int* a = #C1, covariant core::int* b = #C1, generic-covariant-impl core::int* c = #C1, covariant generic-covariant-impl core::int* d = #C1}) → void
     return this.{self::D4::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C4, #C5, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: a, #C9: b, #C10: c, #C11: d})));
   no-such-method-forwarder method _method3(covariant core::int* x, generic-covariant-impl core::int* y) → void
-    return this.{self::D4::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C4, core::List::unmodifiable<dynamic>(<dynamic>[x, y]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
+    return this.{self::D4::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C4, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal2<dynamic>(x, y)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
   no-such-method-forwarder method _method4({covariant core::int* a = #C1, generic-covariant-impl core::int* b = #C1}) → void
     return this.{self::D4::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 0, #C4, #C5, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: a, #C9: b})));
 }
@@ -192,11 +192,11 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method _method1(core::int* a, covariant core::int* b, generic-covariant-impl core::int* c, covariant generic-covariant-impl core::int* d) → void
-    return this.{nsm::C3::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 0, #C4, core::List::unmodifiable<dynamic>(<dynamic>[a, b, c, d]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
+    return this.{nsm::C3::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 0, #C4, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal4<dynamic>(a, b, c, d)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
   no-such-method-forwarder method _method2({core::int* a = #C1, covariant core::int* b = #C1, generic-covariant-impl core::int* c = #C1, covariant generic-covariant-impl core::int* d = #C1}) → void
     return this.{nsm::C3::noSuchMethod}(new core::_InvocationMirror::_withType(#C15, 0, #C4, #C5, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: a, #C9: b, #C10: c, #C11: d})));
   no-such-method-forwarder method _method3(covariant core::int* a, generic-covariant-impl core::int* b) → void
-    return this.{nsm::C3::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 0, #C4, core::List::unmodifiable<dynamic>(<dynamic>[a, b]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
+    return this.{nsm::C3::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 0, #C4, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal2<dynamic>(a, b)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
   no-such-method-forwarder method _method4({covariant core::int* a = #C1, generic-covariant-impl core::int* b = #C1}) → void
     return this.{nsm::C3::noSuchMethod}(new core::_InvocationMirror::_withType(#C17, 0, #C4, #C5, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: a, #C9: b})));
 }
@@ -217,11 +217,11 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method _method1(core::int* x, covariant core::int* y, generic-covariant-impl core::int* z, covariant generic-covariant-impl core::int* w) → void
-    return this.{nsm::C4::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 0, #C4, core::List::unmodifiable<dynamic>(<dynamic>[x, y, z, w]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
+    return this.{nsm::C4::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 0, #C4, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal4<dynamic>(x, y, z, w)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
   no-such-method-forwarder method _method2({core::int* a = #C1, covariant core::int* b = #C1, generic-covariant-impl core::int* c = #C1, covariant generic-covariant-impl core::int* d = #C1}) → void
     return this.{nsm::C4::noSuchMethod}(new core::_InvocationMirror::_withType(#C15, 0, #C4, #C5, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: a, #C9: b, #C10: c, #C11: d})));
   no-such-method-forwarder method _method3(covariant core::int* x, generic-covariant-impl core::int* y) → void
-    return this.{nsm::C4::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 0, #C4, core::List::unmodifiable<dynamic>(<dynamic>[x, y]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
+    return this.{nsm::C4::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 0, #C4, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal2<dynamic>(x, y)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C6)));
   no-such-method-forwarder method _method4({covariant core::int* a = #C1, generic-covariant-impl core::int* b = #C1}) → void
     return this.{nsm::C4::noSuchMethod}(new core::_InvocationMirror::_withType(#C17, 0, #C4, #C5, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: a, #C9: b})));
 }
diff --git a/pkg/front_end/testcases/general/null_aware_spread.dart.strong.transformed.expect b/pkg/front_end/testcases/general/null_aware_spread.dart.strong.transformed.expect
index e5e1b00..485db8b 100644
--- a/pkg/front_end/testcases/general/null_aware_spread.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/null_aware_spread.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 static method nullAwareListSpread(core::List<core::String*>* list) → dynamic {
   list = block {
-    final core::List<core::String*>* #t1 = <core::String*>["foo"];
+    final core::List<core::String*>* #t1 = core::_GrowableList::_literal1<core::String*>("foo");
     final core::Iterable<core::String*>* #t2 = list;
     if(!#t2.{core::Object::==}(null))
       #t1.{core::List::addAll}{Invariant}(#t2);
diff --git a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
index efc4e77..47a50d4 100644
--- a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
@@ -318,7 +318,7 @@
 Try correcting the operator to an existing operator, or defining a 'unary-' operator.
   print(-foo);
         ^");
-  core::print(<invalid-type>[]);
+  core::print(core::_GrowableList::•<invalid-type>(0));
   core::print(invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:37:9: Error: This couldn't be parsed.
   print(>foo);
         ^".>(foo));
diff --git a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.outline.expect b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.outline.expect
index b870822..0cc2e71 100644
--- a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.outline.expect
+++ b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.outline.expect
@@ -1,95 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromGetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
-//   num get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
-//   int get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:54:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromSetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
-//   set getterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
-//   set getterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromSetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
-//   set setterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
-//   set setterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:56:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromGetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
-//   num get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
-//   int get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:78:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromGetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
-//   num get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
-//   int get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromSetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
-//   set getterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
-//   set getterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromSetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
-//   set setterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
-//   set setterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:84:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromGetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
-//   num get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
-//   int get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -148,10 +57,10 @@
 abstract class D extends self::A implements self::B {
   synthetic constructor •() → self::D*
     ;
-  abstract get getterFromGetter() → invalid-type;
-  abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → invalid-type;
-  abstract set setterFromGetter(invalid-type value) → void;
+  abstract get getterFromGetter() → core::int*;
+  abstract set setterFromSetter(core::num* value) → void;
+  abstract get getterFromSetter() → core::num*;
+  abstract set setterFromGetter(core::int* value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract member-signature get setterFromGetter() → core::int*; -> self::B::setterFromGetter
@@ -180,10 +89,10 @@
 abstract class F extends core::Object implements self::A, self::B {
   synthetic constructor •() → self::F*
     ;
-  abstract get getterFromGetter() → invalid-type;
-  abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → invalid-type;
-  abstract set setterFromGetter(invalid-type value) → void;
+  abstract get getterFromGetter() → core::int*;
+  abstract set setterFromSetter(core::num* value) → void;
+  abstract get getterFromSetter() → core::num*;
+  abstract set setterFromGetter(core::int* value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract member-signature get setterFromGetter() → core::int*; -> self::B::setterFromGetter
diff --git a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.expect b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.expect
index 1eaabf2..a188410 100644
--- a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.expect
+++ b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.expect
@@ -1,95 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromGetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
-//   num get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
-//   int get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:54:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromSetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
-//   set getterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
-//   set getterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromSetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
-//   set setterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
-//   set setterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:56:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromGetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
-//   num get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
-//   int get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:78:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromGetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
-//   num get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
-//   int get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromSetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
-//   set getterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
-//   set getterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromSetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
-//   set setterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
-//   set setterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:84:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromGetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
-//   num get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
-//   int get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -152,10 +61,10 @@
   synthetic constructor •() → self::D*
     : super self::A::•()
     ;
-  abstract get getterFromGetter() → invalid-type;
-  abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → invalid-type;
-  abstract set setterFromGetter(invalid-type value) → void;
+  abstract get getterFromGetter() → core::int*;
+  abstract set setterFromSetter(core::num* value) → void;
+  abstract get getterFromSetter() → core::num*;
+  abstract set setterFromGetter(core::int* value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract member-signature get setterFromGetter() → core::int*; -> self::B::setterFromGetter
@@ -186,10 +95,10 @@
   synthetic constructor •() → self::F*
     : super core::Object::•()
     ;
-  abstract get getterFromGetter() → invalid-type;
-  abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → invalid-type;
-  abstract set setterFromGetter(invalid-type value) → void;
+  abstract get getterFromGetter() → core::int*;
+  abstract set setterFromSetter(core::num* value) → void;
+  abstract get getterFromSetter() → core::num*;
+  abstract set setterFromGetter(core::int* value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract member-signature get setterFromGetter() → core::int*; -> self::B::setterFromGetter
diff --git a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.transformed.expect b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.transformed.expect
index 1eaabf2..a188410 100644
--- a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.transformed.expect
@@ -1,95 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromGetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
-//   num get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
-//   int get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:54:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromSetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
-//   set getterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
-//   set getterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromSetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
-//   set setterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
-//   set setterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:56:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromGetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
-//   num get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
-//   int get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:78:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromGetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
-//   num get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
-//   int get getterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get getterFromSetter;
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
-//   set getterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
-//   set getterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromSetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
-//   set setterFromSetter(num value);
-//       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
-//   set setterFromSetter(int value);
-//       ^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:84:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set setterFromGetter(value);
-//                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
-//   num get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
-//   int get setterFromGetter;
-//           ^^^^^^^^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -152,10 +61,10 @@
   synthetic constructor •() → self::D*
     : super self::A::•()
     ;
-  abstract get getterFromGetter() → invalid-type;
-  abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → invalid-type;
-  abstract set setterFromGetter(invalid-type value) → void;
+  abstract get getterFromGetter() → core::int*;
+  abstract set setterFromSetter(core::num* value) → void;
+  abstract get getterFromSetter() → core::num*;
+  abstract set setterFromGetter(core::int* value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract member-signature get setterFromGetter() → core::int*; -> self::B::setterFromGetter
@@ -186,10 +95,10 @@
   synthetic constructor •() → self::F*
     : super core::Object::•()
     ;
-  abstract get getterFromGetter() → invalid-type;
-  abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → invalid-type;
-  abstract set setterFromGetter(invalid-type value) → void;
+  abstract get getterFromGetter() → core::int*;
+  abstract set setterFromSetter(core::num* value) → void;
+  abstract get getterFromSetter() → core::num*;
+  abstract set setterFromGetter(core::int* value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract member-signature get setterFromGetter() → core::int*; -> self::B::setterFromGetter
diff --git a/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.outline.expect b/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.outline.expect
index a493720..3b1e61e 100644
--- a/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.outline.expect
+++ b/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.outline.expect
@@ -47,18 +47,46 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/patch_lib.dart:8:8: Error: Expected a URI.
+// import ':c';
+//        ^
+//
 import self as self3;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/patch_lib.dart:9:1: Error: Expected a URI.
+// export ':d';
+// ^
+//
 import self as self4;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/origin_lib.dart:5:8: Error: Expected a URI.
+// import ':a';
+//        ^
+//
 import self as self5;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/origin_lib.dart:6:1: Error: Expected a URI.
+// export ':b';
+// ^
+//
 import self as self6;
 
 
diff --git a/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.strong.expect b/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.strong.expect
index 02eadb5..2ff6f4b 100644
--- a/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.strong.expect
@@ -50,18 +50,46 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/patch_lib.dart:8:8: Error: Expected a URI.
+// import ':c';
+//        ^
+//
 import self as self2;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/patch_lib.dart:9:1: Error: Expected a URI.
+// export ':d';
+// ^
+//
 import self as self3;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/origin_lib.dart:5:8: Error: Expected a URI.
+// import ':a';
+//        ^
+//
 import self as self4;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/origin_lib.dart:6:1: Error: Expected a URI.
+// export ':b';
+// ^
+//
 import self as self5;
 
 
diff --git a/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.strong.transformed.expect
index 02eadb5..2ff6f4b 100644
--- a/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.strong.transformed.expect
@@ -50,18 +50,46 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/patch_lib.dart:8:8: Error: Expected a URI.
+// import ':c';
+//        ^
+//
 import self as self2;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/patch_lib.dart:9:1: Error: Expected a URI.
+// export ':d';
+// ^
+//
 import self as self3;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/origin_lib.dart:5:8: Error: Expected a URI.
+// import ':a';
+//        ^
+//
 import self as self4;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/platform_invalid_uris/origin_lib.dart:6:1: Error: Expected a URI.
+// export ':b';
+// ^
+//
 import self as self5;
 
 
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart b/pkg/front_end/testcases/general/pure_index_expressions.dart
new file mode 100644
index 0000000..975089a
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart
@@ -0,0 +1,215 @@
+// 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
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+  Class operator +(Class cls) => cls;
+
+  void indexGetSetForEffect(Map<Class, Class> map) {
+    final Class self = this;
+    map[this] ??= this;
+    map[self] ??= self;
+
+    map[this] = this;
+    map[self] = self;
+
+    map[this];
+    map[self];
+
+    map[this] += this;
+    map[self] += self;
+  }
+
+  void indexGetSetForValue(Map<Class, Class> map) {
+    final Class self = this;
+    var v;
+    v = map[this] ??= this;
+    v = map[self] ??= self;
+
+    v = map[this] = this;
+    v = map[self] = self;
+
+    v = map[this];
+    v = map[self];
+
+    v = map[this] += this;
+    v = map[self] += self;
+  }
+
+  void implicitExtensionGetSetForEffect(int i) {
+    final Class self = this;
+    i[this] ??= this;
+    i[self] ??= self;
+
+    i[this] = this;
+    i[self] = self;
+
+    i[this];
+    i[self];
+
+    i[this] += this;
+    i[self] += self;
+  }
+
+  void implicitExtensionGetSetForValue(int i) {
+    final Class self = this;
+    var v;
+    v = i[this] ??= this;
+    v = i[self] ??= self;
+
+    v = i[this] = this;
+    v = i[self] = self;
+
+    v = i[this];
+    v = i[self];
+
+    v = i[this] += this;
+    v = i[self] += self;
+  }
+
+  void explicitExtensionGetSetForEffect(int i) {
+    final Class self = this;
+    Extension(i)[this] ??= this;
+    Extension(i)[self] ??= self;
+
+    Extension(i)[this] = this;
+    Extension(i)[self] = self;
+
+    Extension(i)[this];
+    Extension(i)[self];
+
+    Extension(i)[this] += this;
+    Extension(i)[self] += self;
+  }
+
+  void explicitExtensionGetSetForValue(int i) {
+    final Class self = this;
+    var v;
+    v = Extension(i)[this] ??= this;
+    v = Extension(i)[self] ??= self;
+
+    v = Extension(i)[this] = this;
+    v = Extension(i)[self] = self;
+
+    v = Extension(i)[this];
+    v = Extension(i)[self];
+
+    v = Extension(i)[this] += this;
+    v = Extension(i)[self] += self;
+  }
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {
+    final Class self = this;
+    super[this] ??= this;
+    super[self] ??= self;
+
+    super[this] = this;
+    super[self] = self;
+
+    super[this];
+    super[self];
+
+    super[this] += this;
+    super[self] += self;
+  }
+
+  void superIndexGetSetForValue() {
+    final Class self = this;
+    var v;
+    v = super[this] ??= this;
+    v = super[self] ??= self;
+
+    v = super[this] = this;
+    v = super[self] = self;
+
+    v = super[this];
+    v = super[self];
+
+    v = super[this] += this;
+    v = super[self] += self;
+  }
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+
+  void implicitExtensionGetSetForEffect() {
+    final Class2 self = this;
+    this[this] ??= this;
+    self[self] ??= self;
+
+    this[this] = this;
+    self[self] = self;
+
+    this[this];
+    self[self];
+
+    this[this] += this;
+    self[self] += self;
+  }
+
+  void implicitExtensionGetSetForValue() {
+    final Class2 self = this;
+    var v;
+    v = this[this] ??= this;
+    v = self[self] ??= self;
+
+    v = this[this] = this;
+    v = self[self] = self;
+
+    v = this[this];
+    v = self[self];
+
+    v = this[this] += this;
+    v = self[self] += self;
+  }
+
+  void explicitExtensionGetSetForEffect() {
+    final Class2 self = this;
+    Extension2(this)[this] ??= this;
+    Extension2(self)[self] ??= self;
+
+    Extension2(this)[this] = this;
+    Extension2(self)[self] = self;
+
+    Extension2(this)[this];
+    Extension2(self)[self];
+
+    Extension2(this)[this] += this;
+    Extension2(self)[self] += self;
+  }
+
+  void explicitExtensionGetSetForValue() {
+    final Class2 self = this;
+    var v;
+    v = Extension2(this)[this] ??= this;
+    v = Extension2(self)[self] ??= self;
+
+    v = Extension2(this)[this] = this;
+    v = Extension2(self)[self] = self;
+
+    v = Extension2(this)[this];
+    v = Extension2(self)[self];
+
+    v = Extension2(this)[this] += this;
+    v = Extension2(self)[self] += self;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.outline.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.outline.expect
new file mode 100644
index 0000000..df6fc30
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.outline.expect
@@ -0,0 +1,86 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  operator [](self::Class* cls) → self::Class*
+    ;
+  operator []=(self::Class* cls, self::Class* value) → void
+    ;
+  operator +(self::Class* cls) → self::Class*
+    ;
+  method indexGetSetForEffect(core::Map<self::Class*, self::Class*>* map) → void
+    ;
+  method indexGetSetForValue(core::Map<self::Class*, self::Class*>* map) → void
+    ;
+  method implicitExtensionGetSetForEffect(core::int* i) → void
+    ;
+  method implicitExtensionGetSetForValue(core::int* i) → void
+    ;
+  method explicitExtensionGetSetForEffect(core::int* i) → void
+    ;
+  method explicitExtensionGetSetForValue(core::int* i) → void
+    ;
+  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
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass*
+    ;
+  method superIndexGetSetForEffect() → void
+    ;
+  method superIndexGetSetForValue() → void
+    ;
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    ;
+  operator +(self::Class2* cls) → self::Class2*
+    ;
+  method implicitExtensionGetSetForEffect() → void
+    ;
+  method implicitExtensionGetSetForValue() → void
+    ;
+  method explicitExtensionGetSetForEffect() → void
+    ;
+  method explicitExtensionGetSetForValue() → void
+    ;
+  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
+}
+extension Extension on core::int* {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2* {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static method Extension|[](lowered final core::int* #this, self::Class* cls) → self::Class*
+  ;
+static method Extension|[]=(lowered final core::int* #this, self::Class* cls, self::Class* value) → void
+  ;
+static method Extension2|[](lowered final self::Class2* #this, self::Class2* cls) → self::Class2*
+  ;
+static method Extension2|[]=(lowered final self::Class2* #this, self::Class2* cls, self::Class2* value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.expect
new file mode 100644
index 0000000..ed17f97
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.expect
@@ -0,0 +1,199 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  operator [](self::Class* cls) → self::Class*
+    return new self::Class::•();
+  operator []=(self::Class* cls, self::Class* value) → void {}
+  operator +(self::Class* cls) → self::Class*
+    return cls;
+  method indexGetSetForEffect(core::Map<self::Class*, self::Class*>* map) → void {
+    final self::Class* self = this;
+    let final core::Map<self::Class*, self::Class*>* #t1 = map in #t1.{core::Map::[]}(this).{self::Class::==}(null) ?{self::Class*} #t1.{core::Map::[]=}(this, this) : null;
+    let final core::Map<self::Class*, self::Class*>* #t2 = map in #t2.{core::Map::[]}(self).{self::Class::==}(null) ?{self::Class*} #t2.{core::Map::[]=}(self, self) : null;
+    map.{core::Map::[]=}(this, this);
+    map.{core::Map::[]=}(self, self);
+    map.{core::Map::[]}(this);
+    map.{core::Map::[]}(self);
+    let final core::Map<self::Class*, self::Class*>* #t3 = map in #t3.{core::Map::[]=}(this, #t3.{core::Map::[]}(this).{self::Class::+}(this));
+    let final core::Map<self::Class*, self::Class*>* #t4 = map in #t4.{core::Map::[]=}(self, #t4.{core::Map::[]}(self).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(core::Map<self::Class*, self::Class*>* map) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::Map<self::Class*, self::Class*>* #t5 = map in let final self::Class* #t6 = #t5.{core::Map::[]}(this) in #t6.{self::Class::==}(null) ?{self::Class*} let final void #t7 = #t5.{core::Map::[]=}(this, this) in this : #t6;
+    v = let final core::Map<self::Class*, self::Class*>* #t8 = map in let final self::Class* #t9 = #t8.{core::Map::[]}(self) in #t9.{self::Class::==}(null) ?{self::Class*} let final void #t10 = #t8.{core::Map::[]=}(self, self) in self : #t9;
+    v = let final core::Map<self::Class*, self::Class*>* #t11 = map in let final void #t12 = #t11.{core::Map::[]=}(this, this) in this;
+    v = let final core::Map<self::Class*, self::Class*>* #t13 = map in let final void #t14 = #t13.{core::Map::[]=}(self, self) in self;
+    v = map.{core::Map::[]}(this);
+    v = map.{core::Map::[]}(self);
+    v = let final core::Map<self::Class*, self::Class*>* #t15 = map in let final self::Class* #t16 = #t15.{core::Map::[]}(this).{self::Class::+}(this) in let final void #t17 = #t15.{core::Map::[]=}(this, #t16) in #t16;
+    v = let final core::Map<self::Class*, self::Class*>* #t18 = map in let final self::Class* #t19 = #t18.{core::Map::[]}(self).{self::Class::+}(self) in let final void #t20 = #t18.{core::Map::[]=}(self, #t19) in #t19;
+  }
+  method implicitExtensionGetSetForEffect(core::int* i) → void {
+    final self::Class* self = this;
+    let final core::int* #t21 = i in self::Extension|[](#t21, this).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t21, this, this) : null;
+    let final core::int* #t22 = i in self::Extension|[](#t22, self).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t22, self, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int* #t23 = i in self::Extension|[]=(#t23, this, self::Extension|[](#t23, this).{self::Class::+}(this));
+    let final core::int* #t24 = i in self::Extension|[]=(#t24, self, self::Extension|[](#t24, self).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int* i) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::int* #t25 = i in let final self::Class* #t26 = self::Extension|[](#t25, this) in #t26.{self::Class::==}(null) ?{self::Class*} let final void #t27 = self::Extension|[]=(#t25, this, this) in this : #t26;
+    v = let final core::int* #t28 = i in let final self::Class* #t29 = self::Extension|[](#t28, self) in #t29.{self::Class::==}(null) ?{self::Class*} let final void #t30 = self::Extension|[]=(#t28, self, self) in self : #t29;
+    v = let final core::int* #t31 = i in let final void #t32 = self::Extension|[]=(#t31, this, this) in this;
+    v = let final core::int* #t33 = i in let final void #t34 = self::Extension|[]=(#t33, self, self) in self;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int* #t35 = i in let final self::Class* #t36 = self::Extension|[](#t35, this).{self::Class::+}(this) in let final void #t37 = self::Extension|[]=(#t35, this, #t36) in #t36;
+    v = let final core::int* #t38 = i in let final self::Class* #t39 = self::Extension|[](#t38, self).{self::Class::+}(self) in let final void #t40 = self::Extension|[]=(#t38, self, #t39) in #t39;
+  }
+  method explicitExtensionGetSetForEffect(core::int* i) → void {
+    final self::Class* self = this;
+    let final core::int* #t41 = i in self::Extension|[](#t41, this).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t41, this, this) : null;
+    let final core::int* #t42 = i in self::Extension|[](#t42, self).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t42, self, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int* #t43 = i in self::Extension|[]=(#t43, this, self::Extension|[](#t43, this).{self::Class::+}(this));
+    let final core::int* #t44 = i in self::Extension|[]=(#t44, self, self::Extension|[](#t44, self).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int* i) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::int* #t45 = i in let final self::Class* #t46 = self::Extension|[](#t45, this) in #t46.{self::Class::==}(null) ?{self::Class*} let final void #t47 = self::Extension|[]=(#t45, this, this) in this : #t46;
+    v = let final core::int* #t48 = i in let final self::Class* #t49 = self::Extension|[](#t48, self) in #t49.{self::Class::==}(null) ?{self::Class*} let final void #t50 = self::Extension|[]=(#t48, self, self) in self : #t49;
+    v = let final core::int* #t51 = i in let final void #t52 = self::Extension|[]=(#t51, this, this) in this;
+    v = let final core::int* #t53 = i in let final void #t54 = self::Extension|[]=(#t53, self, self) in self;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int* #t55 = i in let final self::Class* #t56 = self::Extension|[](#t55, this).{self::Class::+}(this) in let final void #t57 = self::Extension|[]=(#t55, this, #t56) in #t56;
+    v = let final core::int* #t58 = i in let final self::Class* #t59 = self::Extension|[](#t58, self).{self::Class::+}(self) in let final void #t60 = self::Extension|[]=(#t58, self, #t59) in #t59;
+  }
+  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
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass*
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    final self::Class* self = this;
+    super.{self::Class::[]}(this).{self::Class::==}(null) ?{self::Class*} super.{self::Class::[]=}(this, this) : null;
+    super.{self::Class::[]}(self).{self::Class::==}(null) ?{self::Class*} super.{self::Class::[]=}(self, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    super.{self::Class::[]=}(self, super.{self::Class::[]}(self).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final self::Class* #t61 = super.{self::Class::[]}(this) in #t61.{self::Class::==}(null) ?{self::Class*} let final void #t62 = super.{self::Class::[]=}(this, this) in this : #t61;
+    v = let final self::Class* #t63 = super.{self::Class::[]}(self) in #t63.{self::Class::==}(null) ?{self::Class*} let final void #t64 = super.{self::Class::[]=}(self, self) in self : #t63;
+    v = let final void #t65 = super.{self::Class::[]=}(this, this) in this;
+    v = let final void #t66 = super.{self::Class::[]=}(self, self) in self;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class* #t67 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t68 = super.{self::Class::[]=}(this, #t67) in #t67;
+    v = let final self::Class* #t69 = super.{self::Class::[]}(self).{self::Class::+}(self) in let final void #t70 = super.{self::Class::[]=}(self, #t69) in #t69;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    : super core::Object::•()
+    ;
+  operator +(self::Class2* cls) → self::Class2*
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    final self::Class2* self = this;
+    self::Extension2|[](this, this).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(this, this, this) : null;
+    self::Extension2|[](self, self).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(self, self, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    self::Extension2|[]=(self, self, self::Extension2|[](self, self).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    final self::Class2* self = this;
+    dynamic v;
+    v = let final self::Class2* #t71 = self::Extension2|[](this, this) in #t71.{self::Class2::==}(null) ?{self::Class2*} let final void #t72 = self::Extension2|[]=(this, this, this) in this : #t71;
+    v = let final self::Class2* #t73 = self::Extension2|[](self, self) in #t73.{self::Class2::==}(null) ?{self::Class2*} let final void #t74 = self::Extension2|[]=(self, self, self) in self : #t73;
+    v = let final void #t75 = self::Extension2|[]=(this, this, this) in this;
+    v = let final void #t76 = self::Extension2|[]=(self, self, self) in self;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2* #t77 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t78 = self::Extension2|[]=(this, this, #t77) in #t77;
+    v = let final self::Class2* #t79 = self::Extension2|[](self, self).{self::Class2::+}(self) in let final void #t80 = self::Extension2|[]=(self, self, #t79) in #t79;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    final self::Class2* self = this;
+    self::Extension2|[](this, this).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(this, this, this) : null;
+    self::Extension2|[](self, self).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(self, self, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    self::Extension2|[]=(self, self, self::Extension2|[](self, self).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    final self::Class2* self = this;
+    dynamic v;
+    v = let final self::Class2* #t81 = self::Extension2|[](this, this) in #t81.{self::Class2::==}(null) ?{self::Class2*} let final void #t82 = self::Extension2|[]=(this, this, this) in this : #t81;
+    v = let final self::Class2* #t83 = self::Extension2|[](self, self) in #t83.{self::Class2::==}(null) ?{self::Class2*} let final void #t84 = self::Extension2|[]=(self, self, self) in self : #t83;
+    v = let final void #t85 = self::Extension2|[]=(this, this, this) in this;
+    v = let final void #t86 = self::Extension2|[]=(self, self, self) in self;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2* #t87 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t88 = self::Extension2|[]=(this, this, #t87) in #t87;
+    v = let final self::Class2* #t89 = self::Extension2|[](self, self).{self::Class2::+}(self) in let final void #t90 = self::Extension2|[]=(self, self, #t89) in #t89;
+  }
+  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
+}
+extension Extension on core::int* {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2* {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static method Extension|[](lowered final core::int* #this, self::Class* cls) → self::Class*
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int* #this, self::Class* cls, self::Class* value) → void {}
+static method Extension2|[](lowered final self::Class2* #this, self::Class2* cls) → self::Class2*
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2* #this, self::Class2* cls, self::Class2* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.transformed.expect
new file mode 100644
index 0000000..ed17f97
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.transformed.expect
@@ -0,0 +1,199 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  operator [](self::Class* cls) → self::Class*
+    return new self::Class::•();
+  operator []=(self::Class* cls, self::Class* value) → void {}
+  operator +(self::Class* cls) → self::Class*
+    return cls;
+  method indexGetSetForEffect(core::Map<self::Class*, self::Class*>* map) → void {
+    final self::Class* self = this;
+    let final core::Map<self::Class*, self::Class*>* #t1 = map in #t1.{core::Map::[]}(this).{self::Class::==}(null) ?{self::Class*} #t1.{core::Map::[]=}(this, this) : null;
+    let final core::Map<self::Class*, self::Class*>* #t2 = map in #t2.{core::Map::[]}(self).{self::Class::==}(null) ?{self::Class*} #t2.{core::Map::[]=}(self, self) : null;
+    map.{core::Map::[]=}(this, this);
+    map.{core::Map::[]=}(self, self);
+    map.{core::Map::[]}(this);
+    map.{core::Map::[]}(self);
+    let final core::Map<self::Class*, self::Class*>* #t3 = map in #t3.{core::Map::[]=}(this, #t3.{core::Map::[]}(this).{self::Class::+}(this));
+    let final core::Map<self::Class*, self::Class*>* #t4 = map in #t4.{core::Map::[]=}(self, #t4.{core::Map::[]}(self).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(core::Map<self::Class*, self::Class*>* map) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::Map<self::Class*, self::Class*>* #t5 = map in let final self::Class* #t6 = #t5.{core::Map::[]}(this) in #t6.{self::Class::==}(null) ?{self::Class*} let final void #t7 = #t5.{core::Map::[]=}(this, this) in this : #t6;
+    v = let final core::Map<self::Class*, self::Class*>* #t8 = map in let final self::Class* #t9 = #t8.{core::Map::[]}(self) in #t9.{self::Class::==}(null) ?{self::Class*} let final void #t10 = #t8.{core::Map::[]=}(self, self) in self : #t9;
+    v = let final core::Map<self::Class*, self::Class*>* #t11 = map in let final void #t12 = #t11.{core::Map::[]=}(this, this) in this;
+    v = let final core::Map<self::Class*, self::Class*>* #t13 = map in let final void #t14 = #t13.{core::Map::[]=}(self, self) in self;
+    v = map.{core::Map::[]}(this);
+    v = map.{core::Map::[]}(self);
+    v = let final core::Map<self::Class*, self::Class*>* #t15 = map in let final self::Class* #t16 = #t15.{core::Map::[]}(this).{self::Class::+}(this) in let final void #t17 = #t15.{core::Map::[]=}(this, #t16) in #t16;
+    v = let final core::Map<self::Class*, self::Class*>* #t18 = map in let final self::Class* #t19 = #t18.{core::Map::[]}(self).{self::Class::+}(self) in let final void #t20 = #t18.{core::Map::[]=}(self, #t19) in #t19;
+  }
+  method implicitExtensionGetSetForEffect(core::int* i) → void {
+    final self::Class* self = this;
+    let final core::int* #t21 = i in self::Extension|[](#t21, this).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t21, this, this) : null;
+    let final core::int* #t22 = i in self::Extension|[](#t22, self).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t22, self, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int* #t23 = i in self::Extension|[]=(#t23, this, self::Extension|[](#t23, this).{self::Class::+}(this));
+    let final core::int* #t24 = i in self::Extension|[]=(#t24, self, self::Extension|[](#t24, self).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int* i) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::int* #t25 = i in let final self::Class* #t26 = self::Extension|[](#t25, this) in #t26.{self::Class::==}(null) ?{self::Class*} let final void #t27 = self::Extension|[]=(#t25, this, this) in this : #t26;
+    v = let final core::int* #t28 = i in let final self::Class* #t29 = self::Extension|[](#t28, self) in #t29.{self::Class::==}(null) ?{self::Class*} let final void #t30 = self::Extension|[]=(#t28, self, self) in self : #t29;
+    v = let final core::int* #t31 = i in let final void #t32 = self::Extension|[]=(#t31, this, this) in this;
+    v = let final core::int* #t33 = i in let final void #t34 = self::Extension|[]=(#t33, self, self) in self;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int* #t35 = i in let final self::Class* #t36 = self::Extension|[](#t35, this).{self::Class::+}(this) in let final void #t37 = self::Extension|[]=(#t35, this, #t36) in #t36;
+    v = let final core::int* #t38 = i in let final self::Class* #t39 = self::Extension|[](#t38, self).{self::Class::+}(self) in let final void #t40 = self::Extension|[]=(#t38, self, #t39) in #t39;
+  }
+  method explicitExtensionGetSetForEffect(core::int* i) → void {
+    final self::Class* self = this;
+    let final core::int* #t41 = i in self::Extension|[](#t41, this).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t41, this, this) : null;
+    let final core::int* #t42 = i in self::Extension|[](#t42, self).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t42, self, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int* #t43 = i in self::Extension|[]=(#t43, this, self::Extension|[](#t43, this).{self::Class::+}(this));
+    let final core::int* #t44 = i in self::Extension|[]=(#t44, self, self::Extension|[](#t44, self).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int* i) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::int* #t45 = i in let final self::Class* #t46 = self::Extension|[](#t45, this) in #t46.{self::Class::==}(null) ?{self::Class*} let final void #t47 = self::Extension|[]=(#t45, this, this) in this : #t46;
+    v = let final core::int* #t48 = i in let final self::Class* #t49 = self::Extension|[](#t48, self) in #t49.{self::Class::==}(null) ?{self::Class*} let final void #t50 = self::Extension|[]=(#t48, self, self) in self : #t49;
+    v = let final core::int* #t51 = i in let final void #t52 = self::Extension|[]=(#t51, this, this) in this;
+    v = let final core::int* #t53 = i in let final void #t54 = self::Extension|[]=(#t53, self, self) in self;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int* #t55 = i in let final self::Class* #t56 = self::Extension|[](#t55, this).{self::Class::+}(this) in let final void #t57 = self::Extension|[]=(#t55, this, #t56) in #t56;
+    v = let final core::int* #t58 = i in let final self::Class* #t59 = self::Extension|[](#t58, self).{self::Class::+}(self) in let final void #t60 = self::Extension|[]=(#t58, self, #t59) in #t59;
+  }
+  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
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass*
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    final self::Class* self = this;
+    super.{self::Class::[]}(this).{self::Class::==}(null) ?{self::Class*} super.{self::Class::[]=}(this, this) : null;
+    super.{self::Class::[]}(self).{self::Class::==}(null) ?{self::Class*} super.{self::Class::[]=}(self, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    super.{self::Class::[]=}(self, super.{self::Class::[]}(self).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final self::Class* #t61 = super.{self::Class::[]}(this) in #t61.{self::Class::==}(null) ?{self::Class*} let final void #t62 = super.{self::Class::[]=}(this, this) in this : #t61;
+    v = let final self::Class* #t63 = super.{self::Class::[]}(self) in #t63.{self::Class::==}(null) ?{self::Class*} let final void #t64 = super.{self::Class::[]=}(self, self) in self : #t63;
+    v = let final void #t65 = super.{self::Class::[]=}(this, this) in this;
+    v = let final void #t66 = super.{self::Class::[]=}(self, self) in self;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class* #t67 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t68 = super.{self::Class::[]=}(this, #t67) in #t67;
+    v = let final self::Class* #t69 = super.{self::Class::[]}(self).{self::Class::+}(self) in let final void #t70 = super.{self::Class::[]=}(self, #t69) in #t69;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    : super core::Object::•()
+    ;
+  operator +(self::Class2* cls) → self::Class2*
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    final self::Class2* self = this;
+    self::Extension2|[](this, this).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(this, this, this) : null;
+    self::Extension2|[](self, self).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(self, self, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    self::Extension2|[]=(self, self, self::Extension2|[](self, self).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    final self::Class2* self = this;
+    dynamic v;
+    v = let final self::Class2* #t71 = self::Extension2|[](this, this) in #t71.{self::Class2::==}(null) ?{self::Class2*} let final void #t72 = self::Extension2|[]=(this, this, this) in this : #t71;
+    v = let final self::Class2* #t73 = self::Extension2|[](self, self) in #t73.{self::Class2::==}(null) ?{self::Class2*} let final void #t74 = self::Extension2|[]=(self, self, self) in self : #t73;
+    v = let final void #t75 = self::Extension2|[]=(this, this, this) in this;
+    v = let final void #t76 = self::Extension2|[]=(self, self, self) in self;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2* #t77 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t78 = self::Extension2|[]=(this, this, #t77) in #t77;
+    v = let final self::Class2* #t79 = self::Extension2|[](self, self).{self::Class2::+}(self) in let final void #t80 = self::Extension2|[]=(self, self, #t79) in #t79;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    final self::Class2* self = this;
+    self::Extension2|[](this, this).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(this, this, this) : null;
+    self::Extension2|[](self, self).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(self, self, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    self::Extension2|[]=(self, self, self::Extension2|[](self, self).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    final self::Class2* self = this;
+    dynamic v;
+    v = let final self::Class2* #t81 = self::Extension2|[](this, this) in #t81.{self::Class2::==}(null) ?{self::Class2*} let final void #t82 = self::Extension2|[]=(this, this, this) in this : #t81;
+    v = let final self::Class2* #t83 = self::Extension2|[](self, self) in #t83.{self::Class2::==}(null) ?{self::Class2*} let final void #t84 = self::Extension2|[]=(self, self, self) in self : #t83;
+    v = let final void #t85 = self::Extension2|[]=(this, this, this) in this;
+    v = let final void #t86 = self::Extension2|[]=(self, self, self) in self;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2* #t87 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t88 = self::Extension2|[]=(this, this, #t87) in #t87;
+    v = let final self::Class2* #t89 = self::Extension2|[](self, self).{self::Class2::+}(self) in let final void #t90 = self::Extension2|[]=(self, self, #t89) in #t89;
+  }
+  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
+}
+extension Extension on core::int* {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2* {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static method Extension|[](lowered final core::int* #this, self::Class* cls) → self::Class*
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int* #this, self::Class* cls, self::Class* value) → void {}
+static method Extension2|[](lowered final self::Class2* #this, self::Class2* cls) → self::Class2*
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2* #this, self::Class2* cls, self::Class2* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline.expect
new file mode 100644
index 0000000..a529cd5
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline.expect
@@ -0,0 +1,37 @@
+// @dart = 2.9
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+  Class operator +(Class cls) => cls;
+  void indexGetSetForEffect(Map<Class, Class> map) {}
+  void indexGetSetForValue(Map<Class, Class> map) {}
+  void implicitExtensionGetSetForEffect(int i) {}
+  void implicitExtensionGetSetForValue(int i) {}
+  void explicitExtensionGetSetForEffect(int i) {}
+  void explicitExtensionGetSetForValue(int i) {}
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {}
+  void superIndexGetSetForValue() {}
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+  void implicitExtensionGetSetForEffect() {}
+  void implicitExtensionGetSetForValue() {}
+  void explicitExtensionGetSetForEffect() {}
+  void explicitExtensionGetSetForValue() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f0fb925
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline_modelled.expect
@@ -0,0 +1,37 @@
+// @dart = 2.9
+class Class {
+  Class operator +(Class cls) => cls;
+  Class operator [](Class cls) => new Class();
+  void explicitExtensionGetSetForEffect(int i) {}
+  void explicitExtensionGetSetForValue(int i) {}
+  void implicitExtensionGetSetForEffect(int i) {}
+  void implicitExtensionGetSetForValue(int i) {}
+  void indexGetSetForEffect(Map<Class, Class> map) {}
+  void indexGetSetForValue(Map<Class, Class> map) {}
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+  void explicitExtensionGetSetForEffect() {}
+  void explicitExtensionGetSetForValue() {}
+  void implicitExtensionGetSetForEffect() {}
+  void implicitExtensionGetSetForValue() {}
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {}
+  void superIndexGetSetForValue() {}
+}
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/qualified.dart.outline.expect b/pkg/front_end/testcases/general/qualified.dart.outline.expect
index a2be5c4..fcf8ecc 100644
--- a/pkg/front_end/testcases/general/qualified.dart.outline.expect
+++ b/pkg/front_end/testcases/general/qualified.dart.outline.expect
@@ -51,6 +51,8 @@
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{lib::Mixin::foo}();
 }
 class WithMixin extends self::_WithMixin&Supertype&Mixin {
   synthetic constructor •() → self::WithMixin*
@@ -71,7 +73,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C<T extends core::Object* = dynamic> extends core::Object { // from org-dartlang-testcase:///qualified_part.dart
-  static field dynamic _redirecting# = <dynamic>[self::C::b];
+  static final field dynamic _redirecting# = <dynamic>[self::C::b];
   constructor •() → self::C<self::C::T*>*
     ;
   constructor a() → self::C<self::C::T*>*
@@ -101,7 +103,7 @@
 
 typedef VoidFunction = () →* void;
 class C<T extends core::Object* = dynamic> extends self::C<lib::C::T*> {
-  static field dynamic _redirecting# = <dynamic>[lib::C::b];
+  static final field dynamic _redirecting# = <dynamic>[lib::C::b];
   constructor •() → lib::C<lib::C::T*>*
     ;
   constructor a() → lib::C<lib::C::T*>*
diff --git a/pkg/front_end/testcases/general/qualified.dart.strong.expect b/pkg/front_end/testcases/general/qualified.dart.strong.expect
index 235cf2c..a51969d 100644
--- a/pkg/front_end/testcases/general/qualified.dart.strong.expect
+++ b/pkg/front_end/testcases/general/qualified.dart.strong.expect
@@ -49,6 +49,8 @@
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{lib::Mixin::foo}();
 }
 class WithMixin extends self::_WithMixin&Supertype&Mixin {
   synthetic constructor •() → self::WithMixin*
@@ -71,7 +73,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C<T extends core::Object* = dynamic> extends core::Object { // from org-dartlang-testcase:///qualified_part.dart
-  static field dynamic _redirecting# = <dynamic>[self::C::b];
+  static final field dynamic _redirecting# = <dynamic>[self::C::b];
   constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
@@ -99,7 +101,7 @@
   new lib::C::a<core::String*>();
   new lib::C::a<core::String*>();
   new self::WithMixin::•().{lib::Supertype::supertypeMethod}();
-  new self::WithMixin::•().{lib::Mixin::foo}();
+  new self::WithMixin::•().{self::_WithMixin&Supertype&Mixin::foo}();
   new self::IllegalSupertype::•();
 }
 
@@ -112,7 +114,7 @@
 
 typedef VoidFunction = () →* void;
 class C<T extends core::Object* = dynamic> extends self::C<lib::C::T*> {
-  static field dynamic _redirecting# = <dynamic>[lib::C::b];
+  static final field dynamic _redirecting# = <dynamic>[lib::C::b];
   constructor •() → lib::C<lib::C::T*>*
     : super self::C::•()
     ;
diff --git a/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect b/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
index 60c9dc5..3937b15 100644
--- a/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/qualified.dart.strong.transformed.expect
@@ -84,7 +84,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C<T extends core::Object* = dynamic> extends core::Object { // from org-dartlang-testcase:///qualified_part.dart
-  static field dynamic _redirecting# = <dynamic>[self::C::b];
+  static final field dynamic _redirecting# = <dynamic>[self::C::b];
   constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
@@ -112,7 +112,7 @@
   new lib::C::a<core::String*>();
   new lib::C::a<core::String*>();
   new self::WithMixin::•().{lib::Supertype::supertypeMethod}();
-  new self::WithMixin::•().{lib::Mixin::foo}();
+  new self::WithMixin::•().{self::_WithMixin&Supertype&Mixin::foo}();
   new self::IllegalSupertype::•();
 }
 
@@ -125,7 +125,7 @@
 
 typedef VoidFunction = () →* void;
 class C<T extends core::Object* = dynamic> extends self::C<lib::C::T*> {
-  static field dynamic _redirecting# = <dynamic>[lib::C::b];
+  static final field dynamic _redirecting# = <dynamic>[lib::C::b];
   constructor •() → lib::C<lib::C::T*>*
     : super self::C::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_constructor.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_constructor.dart.outline.expect
index 2a6e7ee..6128d70 100644
--- a/pkg/front_end/testcases/general/redirecting_constructor.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_constructor.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::fisk];
+  static final field dynamic _redirecting# = <dynamic>[self::A::fisk];
   constructor •() → self::A*
     ;
   static factory fisk() → self::A*
diff --git a/pkg/front_end/testcases/general/redirecting_constructor.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_constructor.dart.strong.expect
index 43520af..7443e13 100644
--- a/pkg/front_end/testcases/general/redirecting_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_constructor.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::fisk];
+  static final field dynamic _redirecting# = <dynamic>[self::A::fisk];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_constructor.dart.strong.transformed.expect
index ff02ffa..0ed4fed 100644
--- a/pkg/front_end/testcases/general/redirecting_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_constructor.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::fisk];
+  static final field dynamic _redirecting# = <dynamic>[self::A::fisk];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory.dart.outline.expect
index 0b2651b..9a9214d 100644
--- a/pkg/front_end/testcases/general/redirecting_factory.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory.dart.outline.expect
@@ -12,7 +12,7 @@
 import "dart:core" as core;
 
 abstract class FooBase<Tf extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::FooBase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::FooBase::•];
   abstract get x() → core::int*;
   static factory •<Tf extends core::Object* = dynamic>(core::int* x) → self::FooBase<self::FooBase::•::Tf*>*
     let dynamic #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf* #typeArg0 = null in invalid-expression;
@@ -28,7 +28,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class Foo<T extends core::Object* = dynamic> extends core::Object implements self::FooBase<dynamic> {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   static factory •<T extends core::Object* = dynamic>(core::int* x) → self::Foo<self::Foo::•::T*>*
     let dynamic #redirecting_factory = self::Bar::• in let core::String* #typeArg0 = null in let self::Foo::•::T* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -74,7 +74,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCase<A extends core::Object* = dynamic, B extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
   static factory •<A extends core::Object* = dynamic, B extends core::Object* = dynamic>() → self::SimpleCase<self::SimpleCase::•::A*, self::SimpleCase::•::B*>*
     let dynamic #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A* #typeArg0 = null in let self::SimpleCase::•::B* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -89,7 +89,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCaseImpl<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai*, self::SimpleCaseImpl::Bi*> {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
   static factory •<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() → self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai*, self::SimpleCaseImpl::•::Bi*>*
     let dynamic #redirecting_factory = self::SimpleCaseImpl2::• in let self::SimpleCaseImpl::•::Ai* #typeArg0 = null in let self::SimpleCaseImpl::•::Bi* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/redirecting_factory.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory.dart.strong.expect
index b6af2c6..71c6c5f 100644
--- a/pkg/front_end/testcases/general/redirecting_factory.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory.dart.strong.expect
@@ -12,7 +12,7 @@
 import "dart:core" as core;
 
 abstract class FooBase<Tf extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::FooBase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::FooBase::•];
   abstract get x() → core::int*;
   static factory •<Tf extends core::Object* = dynamic>(core::int* x) → self::FooBase<self::FooBase::•::Tf*>*
     let dynamic #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf* #typeArg0 = null in invalid-expression;
@@ -28,7 +28,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class Foo<T extends core::Object* = dynamic> extends core::Object implements self::FooBase<dynamic> {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   static factory •<T extends core::Object* = dynamic>(core::int* x) → self::Foo<self::Foo::•::T*>*
     let dynamic #redirecting_factory = self::Bar::• in let core::String* #typeArg0 = null in let self::Foo::•::T* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -78,7 +78,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCase<A extends core::Object* = dynamic, B extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
   static factory •<A extends core::Object* = dynamic, B extends core::Object* = dynamic>() → self::SimpleCase<self::SimpleCase::•::A*, self::SimpleCase::•::B*>*
     let dynamic #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A* #typeArg0 = null in let self::SimpleCase::•::B* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -93,7 +93,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCaseImpl<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai*, self::SimpleCaseImpl::Bi*> {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
   static factory •<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() → self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai*, self::SimpleCaseImpl::•::Bi*>*
     let dynamic #redirecting_factory = self::SimpleCaseImpl2::• in let self::SimpleCaseImpl::•::Ai* #typeArg0 = null in let self::SimpleCaseImpl::•::Bi* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
index 405a5a2..7cdb54a 100644
--- a/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
 import "dart:core" as core;
 
 abstract class FooBase<Tf extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::FooBase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::FooBase::•];
   abstract get x() → core::int*;
   static factory •<Tf extends core::Object* = dynamic>(core::int* x) → self::FooBase<self::FooBase::•::Tf*>*
     let <T extends core::Object* = dynamic>(core::int*) →* self::Foo<T*>* #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf* #typeArg0 = null in invalid-expression;
@@ -28,7 +28,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class Foo<T extends core::Object* = dynamic> extends core::Object implements self::FooBase<dynamic> {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   static factory •<T extends core::Object* = dynamic>(core::int* x) → self::Foo<self::Foo::•::T*>*
     let<BottomType> #redirecting_factory = self::Bar::• in let core::String* #typeArg0 = null in let self::Foo::•::T* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -78,7 +78,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCase<A extends core::Object* = dynamic, B extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
   static factory •<A extends core::Object* = dynamic, B extends core::Object* = dynamic>() → self::SimpleCase<self::SimpleCase::•::A*, self::SimpleCase::•::B*>*
     let <Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() →* self::SimpleCaseImpl<Ai*, Bi*>* #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A* #typeArg0 = null in let self::SimpleCase::•::B* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -93,7 +93,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCaseImpl<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai*, self::SimpleCaseImpl::Bi*> {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
   static factory •<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() → self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai*, self::SimpleCaseImpl::•::Bi*>*
     let<BottomType> #redirecting_factory = self::SimpleCaseImpl2::• in let self::SimpleCaseImpl::•::Ai* #typeArg0 = null in let self::SimpleCaseImpl::•::Bi* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.outline.expect
index 9a864d0..7df5d5f 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
+  static final field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
   constructor •() → self::A*
     ;
   static factory first() → self::A*
diff --git a/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.strong.expect
index e3f106c..88615ec 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
+  static final field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.strong.transformed.expect
index 03c3664..cab046f 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_chain_test.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
+  static final field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.outline.expect
index 7d51f0c..23d11ab 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class _X<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::_X::•];
+  static final field dynamic _redirecting# = <dynamic>[self::_X::•];
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let dynamic #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
index 27deb54..85d39b62 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class _X<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::_X::•];
+  static final field dynamic _redirecting# = <dynamic>[self::_X::•];
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let dynamic #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -63,3 +63,9 @@
 constants  {
   #C1 = self::_Y<Null> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_factory_const_inference.dart:
+- _Y. (from org-dartlang-testcase:///redirecting_factory_const_inference.dart:14:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
index 4b6b1c0..17665de 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_const_inference.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class _X<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::_X::•];
+  static final field dynamic _redirecting# = <dynamic>[self::_X::•];
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let<BottomType> #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -63,3 +63,9 @@
 constants  {
   #C1 = self::_Y<Null> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_factory_const_inference.dart:
+- _Y. (from org-dartlang-testcase:///redirecting_factory_const_inference.dart:14:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.outline.expect
index 55876a5..31008cf 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   constructor named(dynamic p) → self::Foo*
     ;
   @self::forFactoryItself
diff --git a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.strong.expect
index 0426b6e..5da2827 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   constructor named(dynamic p) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.strong.transformed.expect
index bcd4eae..4dc094e 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   constructor named(dynamic p) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.outline.expect
index a0e6392..43d5697 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     ;
   static factory redir() → self::A*
diff --git a/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.strong.expect
index 524f4b5..de93fd8 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.strong.transformed.expect
index 2220b80..5aec6a3 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_simple_test.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.outline.expect
index 8e4e605..fe27ae5 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.outline.expect
@@ -21,7 +21,7 @@
     ;
 }
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     ;
   static factory redir() → self::A*
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.strong.expect
index 017afcf..9ada94b 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.strong.expect
@@ -23,7 +23,7 @@
     ;
 }
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.strong.transformed.expect
index 3396ff7..da09dec 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeargs_test.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
     ;
 }
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.outline.expect
index 35e7e80..edba967 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A<T extends core::Object* = dynamic, S extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     ;
   static factory redir<T extends core::Object* = dynamic, S extends core::Object* = dynamic>(self::A::redir::T* t, self::A::redir::S* s) → self::A<self::A::redir::T*, self::A::redir::S*>*
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.strong.expect
index 1a6b1c1..19f5ced 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A<T extends core::Object* = dynamic, S extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.strong.transformed.expect
index 0be30d7..b6de55f 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeparam_test.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A<T extends core::Object* = dynamic, S extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.outline.expect
index 16ca154..2551eab 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.outline.expect
@@ -21,7 +21,7 @@
     ;
 }
 class A<T extends core::Object* = dynamic, S extends self::A::T* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     ;
   static factory redir<T extends core::Object* = dynamic, S extends self::A::redir::T* = dynamic>(self::A::redir::T* t, self::A::redir::S* s) → self::A<self::A::redir::T*, self::A::redir::S*>*
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.strong.expect
index 6c016e3..521ea4e 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.strong.expect
@@ -23,7 +23,7 @@
     ;
 }
 class A<T extends core::Object* = dynamic, S extends self::A::T* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.strong.transformed.expect
index 0e2c3d5..8409594 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_typeparambounds_test.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
     ;
 }
 class A<T extends core::Object* = dynamic, S extends self::A::T* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.outline.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.outline.expect
index c0e71db..abc8779 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.outline.expect
@@ -5,7 +5,7 @@
 import "package:expect/expect.dart";
 
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     ;
   static factory •<T extends core::Object* = dynamic>() → self::A<self::A::•::T*>*
@@ -22,7 +22,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     ;
   static factory •<U extends core::Object* = dynamic, W extends core::Object* = dynamic>() → self::B<self::B::•::U*, self::B::•::W*>*
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.expect
index 4d1fc6a..e9d6519 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.transformed.expect
index 579f622..30b74d9 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.outline.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.outline.expect
index 3eb558f..9e95322 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.outline.expect
@@ -5,7 +5,7 @@
 import "package:expect/expect.dart";
 
 abstract class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     ;
   static factory •<T extends core::Object* = dynamic>() → self::A<self::A::•::T*>*
@@ -22,7 +22,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     ;
   static factory •<U extends core::Object* = dynamic, W extends core::Object* = dynamic>() → self::B<self::B::•::U*, self::B::•::W*>*
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.expect
index aacff54..8f23e49 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 abstract class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.transformed.expect
index 2acaca4..25434a1 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments_subst.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 abstract class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_type_arguments.dart.outline.expect b/pkg/front_end/testcases/general/redirection_type_arguments.dart.outline.expect
index 6575c3a..ca134d1 100644
--- a/pkg/front_end/testcases/general/redirection_type_arguments.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirection_type_arguments.dart.outline.expect
@@ -5,7 +5,7 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.expect b/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.expect
index c2a1aa6..ed8ef82 100644
--- a/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.expect
+++ b/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
     ;
@@ -37,3 +37,10 @@
 constants  {
   #C1 = self::B<core::String*> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirection_type_arguments.dart:
+- B. (from org-dartlang-testcase:///redirection_type_arguments.dart:16:9)
+- A.empty (from org-dartlang-testcase:///redirection_type_arguments.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.transformed.expect
index 78db851..88a256a 100644
--- a/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/redirection_type_arguments.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
     ;
@@ -37,3 +37,10 @@
 constants  {
   #C1 = self::B<core::String*> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirection_type_arguments.dart:
+- B. (from org-dartlang-testcase:///redirection_type_arguments.dart:16:9)
+- A.empty (from org-dartlang-testcase:///redirection_type_arguments.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.transformed.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.transformed.expect
index 442d3ae..d5f89c9 100644
--- a/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.transformed.expect
@@ -102,7 +102,7 @@
         :async_temporary_1 = _in::unsafeCast<self::A*>(:async_temporary_1).{self::A::foo}(_in::unsafeCast<Null>(:result));
         :async_temporary_0 = new self::B::•();
         [yield] let dynamic #t2 = asy::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = <asy::Future<void>*>[_in::unsafeCast<asy::Future<void>*>(:async_temporary_1), _in::unsafeCast<self::B*>(:async_temporary_0).{self::B::bar}(_in::unsafeCast<Null>(:result))];
+        :return_value = core::_GrowableList::_literal2<asy::Future<void>*>(_in::unsafeCast<asy::Future<void>*>(:async_temporary_1), _in::unsafeCast<self::B*>(:async_temporary_0).{self::B::bar}(_in::unsafeCast<Null>(:result)));
         break #L3;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/general/sdk_diagnostic.dart.outline.expect b/pkg/front_end/testcases/general/sdk_diagnostic.dart.outline.expect
index fef85bb..d815435 100644
--- a/pkg/front_end/testcases/general/sdk_diagnostic.dart.outline.expect
+++ b/pkg/front_end/testcases/general/sdk_diagnostic.dart.outline.expect
@@ -12,7 +12,7 @@
 //
 // class C extends Iterable<Object> {
 //       ^
-// sdk/lib/core/iterable.dart:158:19: Context: 'Iterable.iterator' is defined here.
+// sdk/lib/core/iterable.dart:148:19: Context: 'Iterable.iterator' is defined here.
 //   Iterator<E> get iterator;
 //                   ^^^^^^^^
 //
@@ -22,7 +22,6 @@
 class C extends core::Iterable<core::Object*> {
   synthetic constructor •() → self::C*
     ;
-  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
   abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::C::cast::R*>*; -> core::Iterable::cast
   abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::Object*>* other) → core::Iterable<core::Object*>*; -> core::Iterable::followedBy
   abstract member-signature method map<T extends core::Object* = dynamic>((core::Object*) →* self::C::map::T* f) → core::Iterable<self::C::map::T*>*; -> core::Iterable::map
@@ -59,6 +58,7 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
 }
 static method test() → dynamic
   ;
diff --git a/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.expect b/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.expect
index 9c9017f..2418880 100644
--- a/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.expect
+++ b/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.expect
@@ -12,7 +12,7 @@
 //
 // class C extends Iterable<Object> {
 //       ^
-// sdk/lib/core/iterable.dart:158:19: Context: 'Iterable.iterator' is defined here.
+// sdk/lib/core/iterable.dart:148:19: Context: 'Iterable.iterator' is defined here.
 //   Iterator<E> get iterator;
 //                   ^^^^^^^^
 //
@@ -30,7 +30,6 @@
   synthetic constructor •() → self::C*
     : super core::Iterable::•()
     ;
-  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
   abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::C::cast::R*>*; -> core::Iterable::cast
   abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::Object*>* other) → core::Iterable<core::Object*>*; -> core::Iterable::followedBy
   abstract member-signature method map<T extends core::Object* = dynamic>((core::Object*) →* self::C::map::T* f) → core::Iterable<self::C::map::T*>*; -> core::Iterable::map
@@ -67,6 +66,7 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
 }
 static method test() → dynamic {
   invalid-expression "pkg/front_end/testcases/general/sdk_diagnostic.dart:12:8: Error: Too few positional arguments: 1 required, 0 given.
diff --git a/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.transformed.expect b/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.transformed.expect
index 9c9017f..2418880 100644
--- a/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
 //
 // class C extends Iterable<Object> {
 //       ^
-// sdk/lib/core/iterable.dart:158:19: Context: 'Iterable.iterator' is defined here.
+// sdk/lib/core/iterable.dart:148:19: Context: 'Iterable.iterator' is defined here.
 //   Iterator<E> get iterator;
 //                   ^^^^^^^^
 //
@@ -30,7 +30,6 @@
   synthetic constructor •() → self::C*
     : super core::Iterable::•()
     ;
-  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
   abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::C::cast::R*>*; -> core::Iterable::cast
   abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::Object*>* other) → core::Iterable<core::Object*>*; -> core::Iterable::followedBy
   abstract member-signature method map<T extends core::Object* = dynamic>((core::Object*) →* self::C::map::T* f) → core::Iterable<self::C::map::T*>*; -> core::Iterable::map
@@ -67,6 +66,7 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
 }
 static method test() → dynamic {
   invalid-expression "pkg/front_end/testcases/general/sdk_diagnostic.dart:12:8: Error: Too few positional arguments: 1 required, 0 given.
diff --git a/pkg/front_end/testcases/general/spread_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/general/spread_collection.dart.strong.transformed.expect
index ff4b46b..a809466 100644
--- a/pkg/front_end/testcases/general/spread_collection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/spread_collection.dart.strong.transformed.expect
@@ -13,9 +13,9 @@
 
 static method main() → dynamic {
   final core::List<core::int*>* aList = block {
-    final core::List<core::int*>* #t1 = <core::int*>[1];
-    #t1.{core::List::addAll}{Invariant}(<core::int*>[2]);
-    final core::Iterable<core::int*>* #t2 = <core::int*>[3];
+    final core::List<core::int*>* #t1 = core::_GrowableList::_literal1<core::int*>(1);
+    #t1.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(2));
+    final core::Iterable<core::int*>* #t2 = core::_GrowableList::_literal1<core::int*>(3);
     if(!#t2.{core::Object::==}(null))
       #t1.{core::List::addAll}{Invariant}(#t2);
   } =>#t1;
@@ -41,8 +41,8 @@
   final core::Set<core::int*>* aSet = block {
     final core::Set<core::int*>* #t7 = new col::_CompactLinkedHashSet::•<core::int*>();
     #t7.{core::Set::add}{Invariant}(1);
-    #t7.{core::Set::addAll}{Invariant}(<core::int*>[2]);
-    final core::Iterable<core::int*>* #t8 = <core::int*>[3];
+    #t7.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(2));
+    final core::Iterable<core::int*>* #t8 = core::_GrowableList::_literal1<core::int*>(3);
     if(!#t8.{core::Object::==}(null))
       #t7.{core::Set::addAll}{Invariant}(#t8);
   } =>#t7;
diff --git a/pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect
index 8638624..ac19cc2 100644
--- a/pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect
@@ -103,17 +103,17 @@
 static method bar<K extends core::Object* = dynamic, V extends core::Object* = dynamic>() → core::Map<self::bar::K*, self::bar::V*>*
   return null;
 static method foo(dynamic dynVar) → dynamic {
-  core::List<core::int*>* spread = <core::int*>[1, 2, 3];
+  core::List<core::int*>* spread = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
   core::Map<core::String*, core::int*>* mapSpread = <core::String*, core::int*>{"foo": 4, "bar": 2};
   core::int* notSpreadInt = 42;
   () →* core::int* notSpreadFunction = null;
   core::Map<core::int*, core::num*>* mapIntNum = <core::int*, core::num*>{42: 42};
-  core::List<core::num*>* listNum = <core::num*>[42];
+  core::List<core::num*>* listNum = core::_GrowableList::_literal1<core::num*>(42);
   core::List<dynamic>* lhs10 = block {
-    final core::List<dynamic>* #t1 = core::List::of<dynamic>(<dynamic>[]);
+    final core::List<dynamic>* #t1 = core::List::of<dynamic>(core::_GrowableList::•<dynamic>(0));
   } =>#t1;
   core::Set<dynamic>* set10 = block {
-    final core::Set<dynamic>* #t2 = col::LinkedHashSet::of<dynamic>(<dynamic>[]);
+    final core::Set<dynamic>* #t2 = col::LinkedHashSet::of<dynamic>(core::_GrowableList::•<dynamic>(0));
   } =>#t2;
   core::Map<dynamic, dynamic>* map10 = block {
     final core::Map<dynamic, dynamic>* #t3 = <dynamic, dynamic>{};
@@ -199,16 +199,16 @@
   dynamic map21ambiguous = {...(mapSpread as dynamic)};
                            ^";
   core::List<core::int*>* lhs22 = block {
-    final core::List<core::int*>* #t20 = core::List::of<core::int*>(<core::int*>[]);
+    final core::List<core::int*>* #t20 = core::List::of<core::int*>(core::_GrowableList::•<core::int*>(0));
   } =>#t20;
   core::Set<core::int*>* set22 = block {
-    final core::Set<core::int*>* #t21 = col::LinkedHashSet::of<core::int*>(<core::int*>[]);
+    final core::Set<core::int*>* #t21 = col::LinkedHashSet::of<core::int*>(core::_GrowableList::•<core::int*>(0));
     #t21.{core::Set::add}{Invariant}(42);
   } =>#t21;
   core::Set<core::int*>* set22ambiguous = block {
     final core::Set<core::int*>* #t22 = new col::_CompactLinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t23 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -229,16 +229,16 @@
     }
   } =>#t25;
   core::List<core::List<core::int*>*>* lhs23 = block {
-    final core::List<core::List<core::int*>*>* #t27 = core::List::of<core::List<core::int*>*>(<core::List<core::int*>*>[<core::int*>[]]);
+    final core::List<core::List<core::int*>*>* #t27 = core::List::of<core::List<core::int*>*>(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t27;
   core::Set<core::List<core::int*>*>* set23 = block {
-    final core::Set<core::List<core::int*>*>* #t28 = col::LinkedHashSet::of<core::List<core::int*>*>(<core::List<core::int*>*>[<core::int*>[]]);
-    #t28.{core::Set::add}{Invariant}(<core::int*>[42]);
+    final core::Set<core::List<core::int*>*>* #t28 = col::LinkedHashSet::of<core::List<core::int*>*>(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
+    #t28.{core::Set::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t28;
   core::Set<core::List<core::int*>*>* set23ambiguous = block {
     final core::Set<core::List<core::int*>*>* #t29 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t30 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -251,7 +251,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map23 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t32 = <core::String*, core::List<core::int*>*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"baz": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"baz": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t33 = :sync-for-iterator.{core::Iterator::current};
         #t32.{core::Map::[]=}{Invariant}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
@@ -317,9 +317,9 @@
       }
     }
   } =>#t46) as{TypeError} core::int*;
-  core::List<dynamic>* lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:111:38: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+  core::List<dynamic>* lhs40 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:111:38: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
   List<dynamic> lhs40 = <dynamic>[...notSpreadInt];
-                                     ^"];
+                                     ^");
   core::Set<dynamic>* set40 = block {
     final core::Set<dynamic>* #t48 = new col::_CompactLinkedHashSet::•<dynamic>();
     #t48.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:113:37: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
@@ -329,9 +329,9 @@
   core::Map<dynamic, dynamic>* map40 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:115:55: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
   Map<dynamic, dynamic> map40 = <dynamic, dynamic>{...notSpreadInt};
                                                       ^": null};
-  core::List<dynamic>* lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:117:38: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+  core::List<dynamic>* lhs50 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:117:38: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
   List<dynamic> lhs50 = <dynamic>[...notSpreadFunction];
-                                     ^"];
+                                     ^");
   core::Set<dynamic>* set50 = block {
     final core::Set<dynamic>* #t49 = new col::_CompactLinkedHashSet::•<dynamic>();
     #t49.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:119:37: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
@@ -341,9 +341,9 @@
   core::Map<dynamic, dynamic>* map50 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:121:55: Error: Unexpected type 'int Function()' of a map spread entry.  Expected 'dynamic' or a Map.
   Map<dynamic, dynamic> map50 = <dynamic, dynamic>{...notSpreadFunction};
                                                       ^": null};
-  core::List<core::String*>* lhs60 = <core::String*>[invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:123:36: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+  core::List<core::String*>* lhs60 = core::_GrowableList::_literal1<core::String*>(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:123:36: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
   List<String> lhs60 = <String>[...spread];
-                                   ^"];
+                                   ^");
   core::Set<core::String*>* set60 = block {
     final core::Set<core::String*>* #t50 = new col::_CompactLinkedHashSet::•<core::String*>();
     #t50.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:125:35: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
@@ -356,9 +356,9 @@
   core::Map<core::String*, core::String*>* map61 = <core::String*, core::String*>{null: invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:129:51: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
   Map<String, String> map61 = <String, String>{...mapSpread};
                                                   ^"};
-  core::List<core::int*>* lhs70 = <core::int*>[invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type 'Null'.
+  core::List<core::int*>* lhs70 = core::_GrowableList::_literal1<core::int*>(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type 'Null'.
   List<int> lhs70 = <int>[...null];
-                             ^"];
+                             ^");
   core::Set<core::int*>* set70 = block {
     final core::Set<core::int*>* #t51 = new col::_CompactLinkedHashSet::•<core::int*>();
     #t51.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type 'Null'.
@@ -371,7 +371,7 @@
     ...null,
        ^");
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t53 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -385,7 +385,7 @@
   Map<String, int> map70 = <String, int>{...null};
                                             ^": null};
   core::List<core::int*>* lhs80 = block {
-    final core::List<core::int*>* #t55 = <core::int*>[];
+    final core::List<core::int*>* #t55 = core::_GrowableList::•<core::int*>(0);
     final core::Iterable<core::int*>* #t56 = null;
     if(!#t56.{core::Object::==}(null))
       #t55.{core::List::addAll}{Invariant}(#t56);
@@ -410,7 +410,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t63 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -442,7 +442,7 @@
     }
   } =>#t68;
   core::List<core::int*>* list100 = block {
-    final core::List<core::int*>* #t70 = <core::int*>[];
+    final core::List<core::int*>* #t70 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<core::num*>* :sync-for-iterator = listNum.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -469,7 +469,7 @@
     }
   } =>#t73;
   core::List<core::int*>* list110 = block {
-    final core::List<core::int*>* #t77 = <core::int*>[];
+    final core::List<core::int*>* #t77 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
diff --git a/pkg/front_end/testcases/general/statements.dart.strong.transformed.expect b/pkg/front_end/testcases/general/statements.dart.strong.transformed.expect
index 91dfee3..dd17252 100644
--- a/pkg/front_end/testcases/general/statements.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/statements.dart.strong.transformed.expect
@@ -84,7 +84,7 @@
   }
   while (false)
   {
-    core::Iterator<core::String*>* :sync-for-iterator = <core::String*>["Hello from for-in!"].{core::Iterable::iterator};
+    core::Iterator<core::String*>* :sync-for-iterator = core::_GrowableList::_literal1<core::String*>("Hello from for-in!").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String* s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -93,7 +93,7 @@
     }
   }
   {
-    core::Iterator<core::String*>* :sync-for-iterator = <core::String*>["Hello from for-in without block!"].{core::Iterable::iterator};
+    core::Iterator<core::String*>* :sync-for-iterator = core::_GrowableList::_literal1<core::String*>("Hello from for-in without block!").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String* s = :sync-for-iterator.{core::Iterator::current};
       core::print(s);
@@ -101,7 +101,7 @@
   }
   dynamic s;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>["Hello from for-in without decl!"].{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::_literal1<dynamic>("Hello from for-in without decl!").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -111,7 +111,7 @@
     }
   }
   {
-    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>["Hello from for-in without decl and block!"].{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::_literal1<dynamic>("Hello from for-in without decl and block!").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t5 = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/general/super_set_abstract.dart b/pkg/front_end/testcases/general/super_set_abstract.dart
new file mode 100644
index 0000000..2bc0c7d
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_abstract.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.
+
+class SuperClass {
+  void set setter(int o) {}
+}
+
+abstract class Class extends SuperClass {
+  void set setter(Object o);
+}
+
+class SubClass extends Class {
+  void set setter(Object o) {
+    super.setter = '$o';
+  }
+}
+
+test() {
+  new SubClass().setter = '0';
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/super_set_abstract.dart.outline.expect b/pkg/front_end/testcases/general/super_set_abstract.dart.outline.expect
new file mode 100644
index 0000000..265157d
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_abstract.dart.outline.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class SuperClass extends core::Object {
+  synthetic constructor •() → self::SuperClass*
+    ;
+  set setter(core::int* o) → void
+    ;
+  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
+}
+abstract class Class extends self::SuperClass {
+  synthetic constructor •() → self::Class*
+    ;
+  abstract set setter(core::Object* o) → void;
+}
+class SubClass extends self::Class {
+  synthetic constructor •() → self::SubClass*
+    ;
+  set setter(core::Object* o) → void
+    ;
+}
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/super_set_abstract.dart.strong.expect b/pkg/front_end/testcases/general/super_set_abstract.dart.strong.expect
new file mode 100644
index 0000000..e1d8a1a
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_abstract.dart.strong.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/super_set_abstract.dart:15:24: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+//     super.setter = '$o';
+//                        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class SuperClass extends core::Object {
+  synthetic constructor •() → self::SuperClass*
+    : super core::Object::•()
+    ;
+  set setter(core::int* o) → void {}
+  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
+}
+abstract class Class extends self::SuperClass {
+  synthetic constructor •() → self::Class*
+    : super self::SuperClass::•()
+    ;
+  abstract set setter(core::Object* o) → void;
+}
+class SubClass extends self::Class {
+  synthetic constructor •() → self::SubClass*
+    : super self::Class::•()
+    ;
+  set setter(core::Object* o) → void {
+    super.{self::SuperClass::setter} = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/super_set_abstract.dart:15:24: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+    super.setter = '\$o';
+                       ^" in "${o}" as{TypeError} core::int*;
+  }
+}
+static method test() → dynamic {
+  new self::SubClass::•().{self::SubClass::setter} = "0";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/super_set_abstract.dart.strong.transformed.expect b/pkg/front_end/testcases/general/super_set_abstract.dart.strong.transformed.expect
new file mode 100644
index 0000000..e1d8a1a
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_abstract.dart.strong.transformed.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/super_set_abstract.dart:15:24: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+//     super.setter = '$o';
+//                        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class SuperClass extends core::Object {
+  synthetic constructor •() → self::SuperClass*
+    : super core::Object::•()
+    ;
+  set setter(core::int* o) → void {}
+  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
+}
+abstract class Class extends self::SuperClass {
+  synthetic constructor •() → self::Class*
+    : super self::SuperClass::•()
+    ;
+  abstract set setter(core::Object* o) → void;
+}
+class SubClass extends self::Class {
+  synthetic constructor •() → self::SubClass*
+    : super self::Class::•()
+    ;
+  set setter(core::Object* o) → void {
+    super.{self::SuperClass::setter} = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/super_set_abstract.dart:15:24: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+    super.setter = '\$o';
+                       ^" in "${o}" as{TypeError} core::int*;
+  }
+}
+static method test() → dynamic {
+  new self::SubClass::•().{self::SubClass::setter} = "0";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/super_set_abstract.dart.textual_outline.expect b/pkg/front_end/testcases/general/super_set_abstract.dart.textual_outline.expect
new file mode 100644
index 0000000..0310022
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_abstract.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+class SuperClass {
+  void set setter(int o) {}
+}
+
+abstract class Class extends SuperClass {
+  void set setter(Object o);
+}
+
+class SubClass extends Class {
+  void set setter(Object o) {}
+}
+
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/super_set_abstract.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/super_set_abstract.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2833ed3
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_abstract.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+abstract class Class extends SuperClass {
+  void set setter(Object o);
+}
+
+class SubClass extends Class {
+  void set setter(Object o) {}
+}
+
+class SuperClass {
+  void set setter(int o) {}
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/general/super_set_covariant.dart b/pkg/front_end/testcases/general/super_set_covariant.dart
new file mode 100644
index 0000000..41561ff
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_covariant.dart
@@ -0,0 +1,26 @@
+// 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 SuperClass {
+  void set setter(Object o) {}
+}
+
+abstract class Class extends SuperClass {
+  // TODO(johnniwinther): Should this introduce a concrete forwarding stub, and
+  // if so, should the target of the super set below be the forwarding super
+  // stub?
+  void set setter(covariant int o);
+}
+
+class SubClass extends Class {
+  void set setter(covariant int o) {
+    super.setter = '$o';
+  }
+}
+
+test() {
+  new SubClass().setter = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/super_set_covariant.dart.outline.expect b/pkg/front_end/testcases/general/super_set_covariant.dart.outline.expect
new file mode 100644
index 0000000..550fdb5
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_covariant.dart.outline.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class SuperClass extends core::Object {
+  synthetic constructor •() → self::SuperClass*
+    ;
+  set setter(core::Object* o) → void
+    ;
+  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
+}
+abstract class Class extends self::SuperClass {
+  synthetic constructor •() → self::Class*
+    ;
+  forwarding-stub forwarding-semi-stub set setter(covariant core::int* o) → void
+    return super.{self::SuperClass::setter} = o;
+}
+class SubClass extends self::Class {
+  synthetic constructor •() → self::SubClass*
+    ;
+  set setter(covariant core::int* o) → void
+    ;
+}
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/super_set_covariant.dart.strong.expect b/pkg/front_end/testcases/general/super_set_covariant.dart.strong.expect
new file mode 100644
index 0000000..a1604af
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_covariant.dart.strong.expect
@@ -0,0 +1,48 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/super_set_covariant.dart:18:24: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+//     super.setter = '$o';
+//                        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class SuperClass extends core::Object {
+  synthetic constructor •() → self::SuperClass*
+    : super core::Object::•()
+    ;
+  set setter(core::Object* o) → void {}
+  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
+}
+abstract class Class extends self::SuperClass {
+  synthetic constructor •() → self::Class*
+    : super self::SuperClass::•()
+    ;
+  forwarding-stub forwarding-semi-stub set setter(covariant core::int* o) → void
+    return super.{self::SuperClass::setter} = o;
+}
+class SubClass extends self::Class {
+  synthetic constructor •() → self::SubClass*
+    : super self::Class::•()
+    ;
+  set setter(covariant core::int* o) → void {
+    super.{self::Class::setter} = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/super_set_covariant.dart:18:24: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+    super.setter = '\$o';
+                       ^" in "${o}" as{TypeError} core::int*;
+  }
+}
+static method test() → dynamic {
+  new self::SubClass::•().{self::SubClass::setter} = 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/super_set_covariant.dart.strong.transformed.expect b/pkg/front_end/testcases/general/super_set_covariant.dart.strong.transformed.expect
new file mode 100644
index 0000000..a1604af
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_covariant.dart.strong.transformed.expect
@@ -0,0 +1,48 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/super_set_covariant.dart:18:24: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+//     super.setter = '$o';
+//                        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class SuperClass extends core::Object {
+  synthetic constructor •() → self::SuperClass*
+    : super core::Object::•()
+    ;
+  set setter(core::Object* o) → void {}
+  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
+}
+abstract class Class extends self::SuperClass {
+  synthetic constructor •() → self::Class*
+    : super self::SuperClass::•()
+    ;
+  forwarding-stub forwarding-semi-stub set setter(covariant core::int* o) → void
+    return super.{self::SuperClass::setter} = o;
+}
+class SubClass extends self::Class {
+  synthetic constructor •() → self::SubClass*
+    : super self::Class::•()
+    ;
+  set setter(covariant core::int* o) → void {
+    super.{self::Class::setter} = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/super_set_covariant.dart:18:24: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+    super.setter = '\$o';
+                       ^" in "${o}" as{TypeError} core::int*;
+  }
+}
+static method test() → dynamic {
+  new self::SubClass::•().{self::SubClass::setter} = 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/super_set_covariant.dart.textual_outline.expect b/pkg/front_end/testcases/general/super_set_covariant.dart.textual_outline.expect
new file mode 100644
index 0000000..8a079ae
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_covariant.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+class SuperClass {
+  void set setter(Object o) {}
+}
+
+abstract class Class extends SuperClass {
+  void set setter(covariant int o);
+}
+
+class SubClass extends Class {
+  void set setter(covariant int o) {}
+}
+
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/super_set_covariant.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/super_set_covariant.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b6f108c
--- /dev/null
+++ b/pkg/front_end/testcases/general/super_set_covariant.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+abstract class Class extends SuperClass {
+  void set setter(covariant int o);
+}
+
+class SubClass extends Class {
+  void set setter(covariant int o) {}
+}
+
+class SuperClass {
+  void set setter(Object o) {}
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline.expect
index 8e696a0..35d1d71 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline.expect
@@ -1,3 +1,24 @@
-extension Foo<U> (){}
-on List (){}
+extension Foo<U> on List {
+  static U foo1() {}
+  static List<U> foo1Prime() {}
+  static void foo2(U x) {}
+  static void foo2Prime(List<U> x) {}
+  static void foo3() {}
+  static U Function() foo8() {}
+  static List<U> Function() foo8Prime() {}
+  static void Function(U) foo9() {}
+  static void Function(List<U>) foo9Prime() {}
+  static void foo10(U Function()) {}
+  static void foo10Prime(List<U> Function()) {}
+  static void foo11(void Function(U)) {}
+  static void foo12(void Function(U) b) {}
+  static void foo12Prime(void Function(List<U>) b) {}
+  static void foo13(void Function(U b)) {}
+  static void foo13Prime(void Function(List<U> b)) {}
+  static U foo14 = null;
+  static List<U> foo14Prime = null;
+  static U Function(U) foo15 = null;
+  static List<U> Function(List<U>) foo15Prime = null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..72cd4cf
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+extension Foo<U> on List {
+  static List<U> Function() foo8Prime() {}
+  static List<U> Function(List<U>) foo15Prime = null;
+  static List<U> foo14Prime = null;
+  static List<U> foo1Prime() {}
+  static U Function() foo8() {}
+  static U Function(U) foo15 = null;
+  static U foo1() {}
+  static U foo14 = null;
+  static void Function(List<U>) foo9Prime() {}
+  static void Function(U) foo9() {}
+  static void foo10(U Function()) {}
+  static void foo10Prime(List<U> Function()) {}
+  static void foo11(void Function(U)) {}
+  static void foo12(void Function(U) b) {}
+  static void foo12Prime(void Function(List<U>) b) {}
+  static void foo13(void Function(U b)) {}
+  static void foo13Prime(void Function(List<U> b)) {}
+  static void foo2(U x) {}
+  static void foo2Prime(List<U> x) {}
+  static void foo3() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/type_variable_bound_access.dart.strong.expect b/pkg/front_end/testcases/general/type_variable_bound_access.dart.strong.expect
index 6ef6535..3700707 100644
--- a/pkg/front_end/testcases/general/type_variable_bound_access.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_variable_bound_access.dart.strong.expect
@@ -41,7 +41,7 @@
     return this.{self::NumClass::field1}.{core::num::+}(invalid-expression "pkg/front_end/testcases/general/type_variable_bound_access.dart:22:36: Error: The getter 'length' isn't defined for the class 'num'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'length'.
   num method2() => field1 + field2.length;
-                                   ^^^^^^" as{TypeError,ForDynamic} core::num);
+                                   ^^^^^^" as{TypeError,ForDynamic} core::num*);
   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
diff --git a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.expect b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.expect
index 1222789..fe9dcbd 100644
--- a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.expect
@@ -70,13 +70,13 @@
     : super core::Object::•()
     ;
   static method staticMethod() → self::C<dynamic>* {
-    core::print(invalid-type);
+    core::print(#C1);
     invalid-type t;
     self::C<invalid-type>* l;
     self::C<self::C<invalid-type>*>* ll;
-    #C1;
     #C2;
     #C3;
+    #C4;
     #C5;
     #C6;
   }
@@ -85,9 +85,9 @@
     self::C::T* t;
     self::C<self::C::T*>* l;
     self::C<self::C<self::C::T*>*>* ll;
-    #C1;
     #C2;
     #C3;
+    #C4;
     #C5;
     #C6;
   }
@@ -105,10 +105,16 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = self::C<invalid-type> {}
-  #C2 = <invalid-type>[]
-  #C3 = <self::C<invalid-type>*>[]
-  #C4 = TypeLiteralConstant(invalid-type)
-  #C5 = <core::Object*>[#C4]
-  #C6 = <core::Object*>[#C1]
+  #C1 = TypeLiteralConstant(invalid-type)
+  #C2 = self::C<invalid-type> {}
+  #C3 = <invalid-type>[]
+  #C4 = <self::C<invalid-type>*>[]
+  #C5 = <core::Object*>[#C1]
+  #C6 = <core::Object*>[#C2]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///type_variable_uses.dart:
+- C. (from org-dartlang-testcase:///type_variable_uses.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
index 020bf8e..fe9dcbd 100644
--- a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
@@ -70,13 +70,13 @@
     : super core::Object::•()
     ;
   static method staticMethod() → self::C<dynamic>* {
-    core::print(invalid-type);
+    core::print(#C1);
     invalid-type t;
     self::C<invalid-type>* l;
     self::C<self::C<invalid-type>*>* ll;
-    #C1;
     #C2;
     #C3;
+    #C4;
     #C5;
     #C6;
   }
@@ -85,9 +85,9 @@
     self::C::T* t;
     self::C<self::C::T*>* l;
     self::C<self::C<self::C::T*>*>* ll;
-    #C1;
     #C2;
     #C3;
+    #C4;
     #C5;
     #C6;
   }
@@ -105,14 +105,16 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = self::C<invalid-type> {}
-  #C2 = <invalid-type>[]
-  #C3 = <self::C<invalid-type>*>[]
-  #C4 = TypeLiteralConstant(invalid-type)
-  #C5 = <core::Object*>[#C4]
-  #C6 = <core::Object*>[#C1]
+  #C1 = TypeLiteralConstant(invalid-type)
+  #C2 = self::C<invalid-type> {}
+  #C3 = <invalid-type>[]
+  #C4 = <self::C<invalid-type>*>[]
+  #C5 = <core::Object*>[#C1]
+  #C6 = <core::Object*>[#C2]
 }
 
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_variable_uses.dart:8:11 -> TypeLiteralConstant(<invalid>)
-Extra constant evaluation: evaluated: 4, effectively constant: 1
+
+Constructor coverage from constants:
+org-dartlang-testcase:///type_variable_uses.dart:
+- C. (from org-dartlang-testcase:///type_variable_uses.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
index f5999a8..63d1a23 100644
--- a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
@@ -51,7 +51,7 @@
     return (z as core::Map<self::D::foo3::T2*, self::D::Q*>*).{core::Map::values};
   }
   method foo4(dynamic w) → core::Map<self::D::P*, self::D::Q*>* {
-    core::List<core::Map<self::D::P*, self::D::Q*>*>* list = <core::Map<self::D::P*, self::D::Q*>*>[w as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*];
+    core::List<core::Map<self::D::P*, self::D::Q*>*>* list = core::_GrowableList::_literal1<core::Map<self::D::P*, self::D::Q*>*>(w as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*);
     return w as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*;
   }
 }
diff --git a/pkg/front_end/testcases/general/void_methods.dart.strong.expect b/pkg/front_end/testcases/general/void_methods.dart.strong.expect
index a65b8e4..70705a1 100644
--- a/pkg/front_end/testcases/general/void_methods.dart.strong.expect
+++ b/pkg/front_end/testcases/general/void_methods.dart.strong.expect
@@ -10,7 +10,7 @@
   set first(dynamic x) → void
     return let final core::List<dynamic>* #t1 = this.{self::Foo::list} in let final core::int* #t2 = 0 in let final dynamic #t3 = x in let final void #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3;
   operator []=(dynamic x, dynamic y) → void
-    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final dynamic #t6 = x as{TypeError,ForDynamic} core::int in let final dynamic #t7 = y in let final void #t8 = #t5.{core::List::[]=}(#t6, #t7) in #t7;
+    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final dynamic #t6 = x as{TypeError,ForDynamic} core::int* in let final dynamic #t7 = y in let final void #t8 = #t5.{core::List::[]=}(#t6, #t7) in #t7;
   method clear() → void
     return this.{self::Foo::list}.{core::List::clear}();
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect
index e79e5a8..8844178 100644
--- a/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect
@@ -3,14 +3,14 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  field core::List<dynamic>* list = <dynamic>[1, 2, 3];
+  field core::List<dynamic>* list = core::_GrowableList::_literal3<dynamic>(1, 2, 3);
   synthetic constructor •() → self::Foo*
     : super core::Object::•()
     ;
   set first(dynamic x) → void
     return let final core::List<dynamic>* #t1 = this.{self::Foo::list} in let final core::int* #t2 = 0 in let final dynamic #t3 = x in let final void #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3;
   operator []=(dynamic x, dynamic y) → void
-    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final core::int #t6 = x as{TypeError,ForDynamic} core::int in let final dynamic #t7 = y in let final void #t8 = #t5.{core::List::[]=}(#t6, #t7) in #t7;
+    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final core::int* #t6 = x as{TypeError,ForDynamic} core::int* in let final dynamic #t7 = y in let final void #t8 = #t5.{core::List::[]=}(#t6, #t7) in #t7;
   method clear() → void
     return this.{self::Foo::list}.{core::List::clear}();
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline.expect
index bb04737..06dc10a 100644
--- a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline.expect
@@ -1,8 +1,15 @@
 class A<X extends int> {}
+
 class B {
   A<num> fieldOfA;
   static A<num> staticFieldOfA;
 }
-extension E<X extends A<num>> (){}
-on A (){}
+
+extension E<X extends A<num>> on A {
+  static A<num> fieldOfE;
+  A<num> fooOfE() => null;
+  void barOfE(A<num> a) {}
+  void bazOfE<Y extends A<num>>() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4fd7430
--- /dev/null
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class A<X extends int> {}
+
+class B {
+  A<num> fieldOfA;
+  static A<num> staticFieldOfA;
+}
+
+extension E<X extends A<num>> on A {
+  A<num> fooOfE() => null;
+  static A<num> fieldOfE;
+  void barOfE(A<num> a) {}
+  void bazOfE<Y extends A<num>>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.expect b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.expect
index 6100074..99bdeb7 100644
--- a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.expect
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.expect
@@ -57,3 +57,13 @@
   #C3 = con::B {d:#C1, s:#C2}
   #C4 = 3.14
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_lib.dart:
+- _B&A&M. (from org-dartlang-testcase:///const_lib.dart:15:7)
+- A. (from org-dartlang-testcase:///const_lib.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+
+org-dartlang-testcase:///main.dart:
+- B. (from org-dartlang-testcase:///const_lib.dart:16:9)
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.transformed.expect
index 6100074..99bdeb7 100644
--- a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.transformed.expect
@@ -57,3 +57,13 @@
   #C3 = con::B {d:#C1, s:#C2}
   #C4 = 3.14
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_lib.dart:
+- _B&A&M. (from org-dartlang-testcase:///const_lib.dart:15:7)
+- A. (from org-dartlang-testcase:///const_lib.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+
+org-dartlang-testcase:///main.dart:
+- B. (from org-dartlang-testcase:///const_lib.dart:16:9)
diff --git a/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.outline.expect b/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.outline.expect
index 5fd69f1..856c6d2 100644
--- a/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.outline.expect
+++ b/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.outline.expect
@@ -15,6 +15,10 @@
   synthetic constructor •() → self2::_Foo&B&D*
     : super self2::B::•()
     ;
+  mixin-super-stub operator ==(dynamic dynamic) → core::bool*
+    return super.{self2::D::==}(dynamic);
+  mixin-super-stub method x() → void
+    return super.{self2::D::x}();
 }
 class Foo extends self2::_Foo&B&D {
   synthetic constructor •() → self2::Foo*
diff --git a/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.strong.expect b/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.strong.expect
index b447568..454b091 100644
--- a/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.strong.expect
+++ b/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.strong.expect
@@ -14,11 +14,11 @@
     throw "what?";
   foo1.{mix::_Foo&B&D::x}();
   mix2::Foo* foo2 = new mix2::Foo::•();
-  if(foo2.{mix2::D::==}(null))
+  if(foo2.{mix2::_Foo&B&D::==}(null))
     throw "what?";
-  if(!foo2.{mix2::D::==}(foo2))
+  if(!foo2.{mix2::_Foo&B&D::==}(foo2))
     throw "what?";
-  foo2.{mix2::D::x}();
+  foo2.{mix2::_Foo&B&D::x}();
 }
 
 library;
@@ -29,6 +29,10 @@
   synthetic constructor •() → mix2::_Foo&B&D*
     : super mix2::B::•()
     ;
+  mixin-super-stub operator ==(dynamic dynamic) → core::bool*
+    return super.{mix2::D::==}(dynamic);
+  mixin-super-stub method x() → void
+    return super.{mix2::D::x}();
 }
 class Foo extends mix2::_Foo&B&D {
   synthetic constructor •() → mix2::Foo*
diff --git a/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.strong.transformed.expect b/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.strong.transformed.expect
index 162e4c9..23930b7 100644
--- a/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/with_dependencies/mixin_from_dill/mixin_from_dill.dart.strong.transformed.expect
@@ -14,11 +14,11 @@
     throw "what?";
   foo1.{mix::_Foo&B&D::x}();
   mix2::Foo* foo2 = new mix2::Foo::•();
-  if(foo2.{mix2::D::==}(null))
+  if(foo2.{mix2::_Foo&B&D::==}(null))
     throw "what?";
-  if(!foo2.{mix2::D::==}(foo2))
+  if(!foo2.{mix2::_Foo&B&D::==}(foo2))
     throw "what?";
-  foo2.{mix2::D::x}();
+  foo2.{mix2::_Foo&B&D::x}();
 }
 
 library;
diff --git a/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.expect b/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.expect
index 663835f..8283fbb 100644
--- a/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.expect
+++ b/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.expect
@@ -6,7 +6,7 @@
 
 typedef G<unrelated T extends core::Object* = dynamic> = (() →* dynamic) →* dynamic;
 static method main() → dynamic {
-  core::print((() →* dynamic) →* dynamic);
+  core::print(#C1);
 }
 
 library;
@@ -14,3 +14,7 @@
 import "dart:core" as core;
 
 typedef F<unrelated T extends core::Object* = dynamic> = () →* dynamic;
+
+constants  {
+  #C1 = TypeLiteralConstant((() →* dynamic) →* dynamic)
+}
diff --git a/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.transformed.expect b/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.transformed.expect
index 749e9d0..8283fbb 100644
--- a/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 
 typedef G<unrelated T extends core::Object* = dynamic> = (() →* dynamic) →* dynamic;
 static method main() → dynamic {
-  core::print((() →* dynamic) →* dynamic);
+  core::print(#C1);
 }
 
 library;
@@ -15,7 +15,6 @@
 
 typedef F<unrelated T extends core::Object* = dynamic> = () →* dynamic;
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///variance_from_dill.dart:5:9 -> TypeLiteralConstant(dynamic Function(dynamic Function()*)*)
-Extra constant evaluation: evaluated: 2, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant((() →* dynamic) →* dynamic)
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.expect
index d1cc44e..2f3b038 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.expect
@@ -533,3 +533,9 @@
   #C21 = "required"
   #C22 = self::Strength {value:#C20, name:#C21}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///DeltaBlue.dart:
+- Strength. (from org-dartlang-testcase:///DeltaBlue.dart:61:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.transformed.expect
index d1cc44e..20311a0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/DeltaBlue.dart.weak.transformed.expect
@@ -265,7 +265,7 @@
   }
 }
 class Variable extends core::Object {
-  field core::List<self::Constraint*>* constraints = <self::Constraint*>[];
+  field core::List<self::Constraint*>* constraints = core::_GrowableList::•<self::Constraint*>(0);
   field self::Constraint* determinedBy = null;
   field core::int* mark = 0;
   field self::Strength* walkStrength = #C18;
@@ -337,7 +337,7 @@
     return plan;
   }
   method extractPlanFromConstraints(core::List<self::Constraint*>* constraints) → self::Plan* {
-    core::List<self::Constraint*>* sources = <self::Constraint*>[];
+    core::List<self::Constraint*>* sources = core::_GrowableList::•<self::Constraint*>(0);
     for (core::int* i = 0; i.{core::num::<}(constraints.{core::List::length}); i = i.{core::num::+}(1)) {
       self::Constraint* c = constraints.{core::List::[]}(i);
       if(c.{self::Constraint::isInput}() && c.{self::Constraint::isSatisfied}())
@@ -346,7 +346,7 @@
     return this.{self::Planner::makePlan}(sources);
   }
   method addPropagate(self::Constraint* c, core::int* mark) → core::bool* {
-    core::List<self::Constraint*>* todo = <self::Constraint*>[c];
+    core::List<self::Constraint*>* todo = core::_GrowableList::_literal1<self::Constraint*>(c);
     while (todo.{core::List::length}.{core::num::>}(0)) {
       self::Constraint* d = todo.{core::List::removeLast}();
       if(d.{self::Constraint::output}().{self::Variable::mark}.{core::num::==}(mark)) {
@@ -362,8 +362,8 @@
     out.{self::Variable::determinedBy} = null;
     out.{self::Variable::walkStrength} = #C18;
     out.{self::Variable::stay} = true;
-    core::List<self::Constraint*>* unsatisfied = <self::Constraint*>[];
-    core::List<self::Variable*>* todo = <self::Variable*>[out];
+    core::List<self::Constraint*>* unsatisfied = core::_GrowableList::•<self::Constraint*>(0);
+    core::List<self::Variable*>* todo = core::_GrowableList::_literal1<self::Variable*>(out);
     while (todo.{core::List::length}.{core::num::>}(0)) {
       self::Variable* v = todo.{core::List::removeLast}();
       for (core::int* i = 0; i.{core::num::<}(v.{self::Variable::constraints}.{core::List::length}); i = i.{core::num::+}(1)) {
@@ -402,7 +402,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class Plan extends core::Object {
-  field core::List<self::Constraint*>* list = <self::Constraint*>[];
+  field core::List<self::Constraint*>* list = core::_GrowableList::•<self::Constraint*>(0);
   synthetic constructor •() → self::Plan*
     : super core::Object::•()
     ;
@@ -458,7 +458,7 @@
   }
   new self::StayConstraint::•(last, #C9);
   self::EditConstraint* edit = new self::EditConstraint::•(first, #C6);
-  self::Plan* plan = self::planner.{self::Planner::extractPlanFromConstraints}(<self::Constraint*>[edit]);
+  self::Plan* plan = self::planner.{self::Planner::extractPlanFromConstraints}(core::_GrowableList::_literal1<self::Constraint*>(edit));
   for (core::int* i = 0; i.{core::num::<}(100); i = i.{core::num::+}(1)) {
     first.{self::Variable::value} = i;
     plan.{self::Plan::execute}();
@@ -474,7 +474,7 @@
   self::Variable* offset = new self::Variable::•("offset", 1000);
   self::Variable* src = null;
   self::Variable* dst = null;
-  core::List<self::Variable*>* dests = <self::Variable*>[];
+  core::List<self::Variable*>* dests = core::_GrowableList::•<self::Variable*>(0);
   for (core::int* i = 0; i.{core::num::<}(n); i = i.{core::num::+}(1)) {
     src = new self::Variable::•("src", i);
     dst = new self::Variable::•("dst", i);
@@ -501,7 +501,7 @@
 }
 static method change(self::Variable* v, core::int* newValue) → void {
   self::EditConstraint* edit = new self::EditConstraint::•(v, #C6);
-  self::Plan* plan = self::planner.{self::Planner::extractPlanFromConstraints}(<self::EditConstraint*>[edit]);
+  self::Plan* plan = self::planner.{self::Planner::extractPlanFromConstraints}(core::_GrowableList::_literal1<self::EditConstraint*>(edit));
   for (core::int* i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
     v.{self::Variable::value} = newValue;
     plan.{self::Plan::execute}();
@@ -533,3 +533,9 @@
   #C21 = "required"
   #C22 = self::Strength {value:#C20, name:#C21}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///DeltaBlue.dart:
+- Strength. (from org-dartlang-testcase:///DeltaBlue.dart:61:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart.weak.expect
index 3fb40fc..999fa79 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart.weak.expect
@@ -12,6 +12,26 @@
 //   var interfaceMethod1;
 //       ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:29:16: Error: Can't inherit members that conflict with each other.
+// abstract class B extends A {
+//                ^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:8:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:14:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:35:7: Error: Can't inherit members that conflict with each other.
+// class MyClass extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:8:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:14:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
 // pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:35:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property1=
@@ -50,6 +70,36 @@
 //   void interfaceMethod3() {}
 //        ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:44:7: Error: Can't inherit members that conflict with each other.
+// class MyMock1 extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:8:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:14:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:50:7: Error: Can't inherit members that conflict with each other.
+// class MyMock2 extends MyMock1 {
+//       ^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:8:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:14:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:56:7: Error: Can't inherit members that conflict with each other.
+// class MyMock3 extends B {
+//       ^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:8:8: Context: This is one inherited member.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:14:7: Context: This is the other inherited member.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+//
 // pkg/front_end/testcases/general_nnbd_opt_out/abstract_members.dart:56:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property1=
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method.dart.weak.expect
index 732160e..c52e1a4 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method.dart.weak.expect
@@ -8,6 +8,7 @@
     ;
   method foo() → self::A*
     return null;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -16,7 +17,6 @@
   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
 }
 abstract class B extends self::A {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method.dart.weak.transformed.expect
index 732160e..c52e1a4 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/abstract_overrides_concrete_with_no_such_method.dart.weak.transformed.expect
@@ -8,6 +8,7 @@
     ;
   method foo() → self::A*
     return null;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -16,7 +17,6 @@
   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
 }
 abstract class B extends self::A {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
index 742c6ea..fb849d9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
@@ -59,3 +59,10 @@
   #C11 = 42
   #C12 = self::Fisk<core::int*> {x:#C11}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_on_enum_values.dart:
+- Foo. (from org-dartlang-testcase:///annotation_on_enum_values.dart:17:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Fisk.fisk (from org-dartlang-testcase:///annotation_on_enum_values.dart:14:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
index 742c6ea..fb849d9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
@@ -59,3 +59,10 @@
   #C11 = 42
   #C12 = self::Fisk<core::int*> {x:#C11}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_on_enum_values.dart:
+- Foo. (from org-dartlang-testcase:///annotation_on_enum_values.dart:17:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Fisk.fisk (from org-dartlang-testcase:///annotation_on_enum_values.dart:14:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.expect
index e0a2535..41693bf 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.expect
@@ -57,3 +57,9 @@
   #C1 = core::Object {}
   #C2 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_top.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- A. (from org-dartlang-testcase:///annotation_top.dart:14:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.transformed.expect
index e0a2535..41693bf 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_top.dart.weak.transformed.expect
@@ -57,3 +57,9 @@
   #C1 = core::Object {}
   #C2 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_top.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- A. (from org-dartlang-testcase:///annotation_top.dart:14:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.expect
index 4c86065..a3070a4 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.expect
@@ -60,3 +60,10 @@
   #C2 = self::Bar {}
   #C3 = null
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_variable_declaration.dart:
+- Bar. (from org-dartlang-testcase:///annotation_variable_declaration.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Bar.named (from org-dartlang-testcase:///annotation_variable_declaration.dart:11:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.transformed.expect
index 4c86065..a3070a4 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_variable_declaration.dart.weak.transformed.expect
@@ -60,3 +60,10 @@
   #C2 = self::Bar {}
   #C3 = null
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///annotation_variable_declaration.dart:
+- Bar. (from org-dartlang-testcase:///annotation_variable_declaration.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Bar.named (from org-dartlang-testcase:///annotation_variable_declaration.dart:11:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/arithmetic.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/arithmetic.dart.weak.transformed.expect
index ed95ed2..0f2a3e1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/arithmetic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/arithmetic.dart.weak.transformed.expect
@@ -14,5 +14,5 @@
 static method main() → dynamic {
   self::foo(4, 5);
   self::foo(6, 7);
-  self::loop(<dynamic>["dfg"]);
+  self::loop(core::_GrowableList::_literal1<dynamic>("dfg"));
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.weak.transformed.expect
index 33ab33f..2a42c83 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/async_function.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 
 import "dart:async";
 
-static field core::List<core::String*>* stringList = <core::String*>["bar"];
+static field core::List<core::String*>* stringList = core::_GrowableList::_literal1<core::String*>("bar");
 static method asyncString() → asy::Future<core::String*>* /* originally async */ {
   final asy::_Future<core::String*>* :async_future = new asy::_Future::•<core::String*>();
   core::bool* :is_sync = false;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.weak.transformed.expect
index 78818d9..760f00e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/async_nested.dart.weak.transformed.expect
@@ -44,18 +44,18 @@
       #L1:
       {
         core::String* expected = "1 2 3 4 5 6 7 8 9 10";
-        :async_temporary_2 = new self::Node::•("2", <self::Node*>[]);
-        [yield] let dynamic #t4 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("7", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
-        [yield] let dynamic #t5 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("6", <self::Node*>[_in::unsafeCast<self::Node*>(:result)])), :async_op_then, :async_op_error, :async_op) in null;
+        :async_temporary_2 = new self::Node::•("2", core::_GrowableList::•<self::Node*>(0));
+        [yield] let dynamic #t4 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("7", core::_GrowableList::•<self::Node*>(0))), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t5 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("6", core::_GrowableList::_literal1<self::Node*>(_in::unsafeCast<self::Node*>(:result)))), :async_op_then, :async_op_error, :async_op) in null;
         :async_temporary_1 = _in::unsafeCast<self::Node*>(:result);
-        [yield] let dynamic #t6 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("8", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t6 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("8", core::_GrowableList::•<self::Node*>(0))), :async_op_then, :async_op_error, :async_op) in null;
         :async_temporary_0 = _in::unsafeCast<self::Node*>(:result);
-        [yield] let dynamic #t7 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("9", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
-        [yield] let dynamic #t8 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("4", <self::Node*>[new self::Node::•("5", <self::Node*>[_in::unsafeCast<self::Node*>(:async_temporary_1), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)])])), :async_op_then, :async_op_error, :async_op) in null;
-        [yield] let dynamic #t9 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("3", <self::Node*>[_in::unsafeCast<self::Node*>(:result)])), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t7 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("9", core::_GrowableList::•<self::Node*>(0))), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t8 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("4", core::_GrowableList::_literal1<self::Node*>(new self::Node::•("5", core::_GrowableList::_literal3<self::Node*>(_in::unsafeCast<self::Node*>(:async_temporary_1), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)))))), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t9 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("3", core::_GrowableList::_literal1<self::Node*>(_in::unsafeCast<self::Node*>(:result)))), :async_op_then, :async_op_error, :async_op) in null;
         :async_temporary_0 = _in::unsafeCast<self::Node*>(:result);
-        [yield] let dynamic #t10 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("10", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
-        self::Node* node = new self::Node::•("1", <self::Node*>[_in::unsafeCast<self::Node*>(:async_temporary_2), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)]);
+        [yield] let dynamic #t10 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("10", core::_GrowableList::•<self::Node*>(0))), :async_op_then, :async_op_error, :async_op) in null;
+        self::Node* node = new self::Node::•("1", core::_GrowableList::_literal3<self::Node*>(_in::unsafeCast<self::Node*>(:async_temporary_2), _in::unsafeCast<self::Node*>(:async_temporary_0), _in::unsafeCast<self::Node*>(:result)));
         core::String* actual = node.{self::Node::toSimpleString}() as{TypeError,ForDynamic} core::String*;
         core::print(actual);
         if(!actual.{core::String::==}(expected)) {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.expect
index 60f6730..efab03a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.expect
@@ -56,54 +56,54 @@
 static method dummy() → dynamic
   return 1;
 static method staticMembers() → dynamic async {
-  core::num* a = self::C::staticField.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* a = self::C::staticField.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, a);
-  core::num* f = (self::C::staticField = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* f = (self::C::staticField = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, f);
-  core::num* b = self::C::staticGetter.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* b = self::C::staticGetter.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, b);
-  core::num* c = (self::C::staticSetter = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* c = (self::C::staticSetter = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, c);
-  core::num* d = self::C::staticFoo(2).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* d = self::C::staticFoo(2).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(3, d);
-  core::num* e = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* e = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(5, e);
 }
 static method topLevelMembers() → dynamic async {
-  core::num* a = self::globalVariable.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* a = self::globalVariable.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, a);
-  core::num* b = self::topLevelGetter.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* b = self::topLevelGetter.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, b);
-  core::num* c = (self::topLevelSetter = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* c = (self::topLevelSetter = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, c);
-  core::num* d = self::topLevelFoo(1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* d = self::topLevelFoo(1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, d);
-  core::num* e = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* e = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(5, e);
 }
 static method instanceMembers() → dynamic async {
   self::C* inst = new self::C::•();
-  core::num* a = inst.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* a = inst.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, a);
-  core::num* b = inst.{self::C::getter}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* b = inst.{self::C::getter}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, b);
-  core::num* c = (inst.{self::C::setter} = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* c = (inst.{self::C::setter} = 1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, c);
-  core::num* d = inst.{self::C::foo}(1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* d = inst.{self::C::foo}(1).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, d);
-  core::num* e = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* e = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1)).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(5, e);
 }
 static method others() → dynamic async {
   core::String* a = "${self::globalVariable} ${await self::dummy()} ".{core::String::+}(await "someString");
   self::expect("1 1 someString", a);
   self::C* c = new self::C::•();
-  core::num* d = c.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* d = c.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   core::int* cnt = 2;
   core::List<core::int*>* b = <core::int*>[1, 2, 3];
   b.{core::List::[]=}(cnt, await self::dummy() as{TypeError,ForDynamic} core::int*);
   self::expect(1, b.{core::List::[]}(cnt));
-  core::num* e = b.{core::List::[]}(0).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num);
+  core::num* e = b.{core::List::[]}(0).{core::num::+}(await self::dummy() as{TypeError,ForDynamic} core::num*);
   self::expect(2, e);
 }
 static method conditionals() → dynamic async {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.transformed.expect
index 8b69c50..51ef2df 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await_complex.dart.weak.transformed.expect
@@ -77,27 +77,27 @@
       {
         :async_temporary_0 = self::C::staticField;
         [yield] let dynamic #t1 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, a);
         :async_temporary_1 = self::C::staticField = 1;
         [yield] let dynamic #t2 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* f = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* f = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, f);
         :async_temporary_2 = self::C::staticGetter;
         [yield] let dynamic #t3 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, b);
         :async_temporary_3 = self::C::staticSetter = 1;
         [yield] let dynamic #t4 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, c);
         :async_temporary_4 = self::C::staticFoo(2);
         [yield] let dynamic #t5 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(3, d);
         :async_temporary_5 = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1));
         [yield] let dynamic #t6 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_5).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_5).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(5, e);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -132,23 +132,23 @@
       {
         :async_temporary_0 = self::globalVariable;
         [yield] let dynamic #t7 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, a);
         :async_temporary_1 = self::topLevelGetter;
         [yield] let dynamic #t8 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, b);
         :async_temporary_2 = self::topLevelSetter = 1;
         [yield] let dynamic #t9 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, c);
         :async_temporary_3 = self::topLevelFoo(1);
         [yield] let dynamic #t10 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, d);
         :async_temporary_4 = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1));
         [yield] let dynamic #t11 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(5, e);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -184,23 +184,23 @@
         self::C* inst = new self::C::•();
         :async_temporary_0 = inst.{self::C::field};
         [yield] let dynamic #t12 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* a = _in::unsafeCast<core::int*>(:async_temporary_0).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, a);
         :async_temporary_1 = inst.{self::C::getter};
         [yield] let dynamic #t13 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* b = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, b);
         :async_temporary_2 = inst.{self::C::setter} = 1;
         [yield] let dynamic #t14 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* c = _in::unsafeCast<core::int*>(:async_temporary_2).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, c);
         :async_temporary_3 = inst.{self::C::foo}(1);
         [yield] let dynamic #t15 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_3).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, d);
         :async_temporary_4 = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1));
         [yield] let dynamic #t16 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(5, e);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -242,9 +242,9 @@
         self::C* c = new self::C::•();
         :async_temporary_1 = c.{self::C::field};
         [yield] let dynamic #t19 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* d = _in::unsafeCast<core::int*>(:async_temporary_1).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         core::int* cnt = 2;
-        core::List<core::int*>* b = <core::int*>[1, 2, 3];
+        core::List<core::int*>* b = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
         :async_temporary_3 = b;
         :async_temporary_2 = cnt;
         [yield] let dynamic #t20 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
@@ -252,7 +252,7 @@
         self::expect(1, b.{core::List::[]}(cnt));
         :async_temporary_4 = b.{core::List::[]}(0);
         [yield] let dynamic #t21 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
-        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num);
+        core::num* e = _in::unsafeCast<core::int*>(:async_temporary_4).{core::num::+}(:result as{TypeError,ForDynamic} core::num*);
         self::expect(2, e);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -354,7 +354,7 @@
       #L6:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = core::_GrowableList::_literal2<core::Function*>(#C1, #C2).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t26 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -433,7 +433,7 @@
       #L7:
       {
         {
-          core::Iterator<core::Function*>* :sync-for-iterator = <core::Function*>[#C1, #C2].{core::Iterable::iterator};
+          core::Iterator<core::Function*>* :sync-for-iterator = core::_GrowableList::_literal2<core::Function*>(#C1, #C2).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             final core::Function* #t33 = :sync-for-iterator.{core::Iterator::current};
             {
@@ -637,7 +637,7 @@
                 :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
                 return :controller_stream;
               }
-              :async_temporary_0 = <dynamic>[42];
+              :async_temporary_0 = core::_GrowableList::_literal1<dynamic>(42);
               [yield] let dynamic #t55 = asy::_awaitHelper(testStream1.call().{asy::Stream::toList}(), :async_op_then, :async_op_error, :async_op) in null;
               self::expectList(_in::unsafeCast<core::List<dynamic>*>(:async_temporary_0), _in::unsafeCast<core::List<core::int*>>(:result));
               function testStream2() → asy::Stream<core::int*>* /* originally async* */ {
@@ -674,7 +674,7 @@
                 :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
                 return :controller_stream;
               }
-              :async_temporary_1 = <dynamic>[42];
+              :async_temporary_1 = core::_GrowableList::_literal1<dynamic>(42);
               [yield] let dynamic #t57 = asy::_awaitHelper(testStream2.call().{asy::Stream::toList}(), :async_op_then, :async_op_error, :async_op) in null;
               self::expectList(_in::unsafeCast<core::List<dynamic>*>(:async_temporary_1), _in::unsafeCast<core::List<core::int*>>(:result));
             }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.weak.transformed.expect
index e178bdf..c96fec3e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/await_in_cascade.dart.weak.transformed.expect
@@ -23,7 +23,7 @@
       try {
         #L1:
         {
-          final core::List<core::int*>* #t1 = <core::int*>[];
+          final core::List<core::int*>* #t1 = core::_GrowableList::•<core::int*>(0);
           [yield] let dynamic #t2 = asy::_awaitHelper(this.{self::C::_m}(), :async_op_then, :async_op_error, :async_op) in null;
           #t1.{core::List::add}(_in::unsafeCast<core::int*>(:result));
           :return_value = block {} =>#t1;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug32414b.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug32414b.dart.weak.transformed.expect
index 1422239..6378088 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug32414b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug32414b.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method test() → void {
-  core::List<dynamic>* l = <dynamic>[1, "hello"];
+  core::List<dynamic>* l = core::_GrowableList::_literal2<dynamic>(1, "hello");
   core::List<core::String*>* l2 = l.{core::Iterable::map}<core::String*>((dynamic element) → core::String* => element.{core::Object::toString}()).{core::Iterable::toList}();
 }
 static method main() → void {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
index 6e4306c..9b4bb6a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
@@ -41,6 +41,8 @@
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → void
+    return super.{self::MyTest::foo}();
   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
@@ -59,9 +61,9 @@
 }
 static const field self::_FailingTest* failingTest = #C1;
 static method main() → dynamic {
-  mir::ClassMirror* classMirror = mir::reflectClass(self::MyTest2*);
+  mir::ClassMirror* classMirror = mir::reflectClass(#C2);
   classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol* symbol, mir::MethodMirror* memberMirror) → Null {
-    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C2)) {
+    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C3)) {
       core::print(memberMirror);
       core::print(self::_hasFailingTestAnnotation(memberMirror));
     }
@@ -80,5 +82,12 @@
 
 constants  {
   #C1 = self::_FailingTest {}
-  #C2 = #foo
+  #C2 = TypeLiteralConstant(self::MyTest2*)
+  #C3 = #foo
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bug33099.dart:
+- _FailingTest. (from org-dartlang-testcase:///bug33099.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
index 34304c6..bb18f32 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
@@ -41,6 +41,8 @@
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
+  @#C1
+  method foo() → void {}
   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
@@ -51,8 +53,6 @@
   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
-  @#C1
-  method foo() → void {}
 }
 class MyTest2 extends self::_MyTest2&Object&MyTest {
   synthetic constructor •() → self::MyTest2*
@@ -61,9 +61,9 @@
 }
 static const field self::_FailingTest* failingTest = #C1;
 static method main() → dynamic {
-  mir::ClassMirror* classMirror = mir::reflectClass(self::MyTest2*);
+  mir::ClassMirror* classMirror = mir::reflectClass(#C2);
   classMirror.{mir::ClassMirror::instanceMembers}.{core::Map::forEach}((core::Symbol* symbol, mir::MethodMirror* memberMirror) → Null {
-    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C2)) {
+    if(memberMirror.{mir::DeclarationMirror::simpleName}.{core::Symbol::==}(#C3)) {
       core::print(memberMirror);
       core::print(self::_hasFailingTestAnnotation(memberMirror));
     }
@@ -82,9 +82,12 @@
 
 constants  {
   #C1 = self::_FailingTest {}
-  #C2 = #foo
+  #C2 = TypeLiteralConstant(self::MyTest2*)
+  #C3 = #foo
 }
 
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///bug33099.dart:23:42 -> TypeLiteralConstant(MyTest2*)
-Extra constant evaluation: evaluated: 33, effectively constant: 1
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bug33099.dart:
+- _FailingTest. (from org-dartlang-testcase:///bug33099.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.weak.transformed.expect
index b800d2a..2ca85ca 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33206.dart.weak.transformed.expect
@@ -52,7 +52,7 @@
     try {
       #L1:
       {
-        :return_value = <core::Object*>[1];
+        :return_value = core::_GrowableList::_literal1<core::Object*>(1);
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -68,7 +68,7 @@
   return :async_future;
 }
 static method f2() → core::List<core::Object*>*
-  return <core::Object*>[2];
+  return core::_GrowableList::_literal1<core::Object*>(2);
 static method f3() → asy::Future<core::Object*>* /* originally async */ {
   final asy::_Future<core::Object*>* :async_future = new asy::_Future::•<core::Object*>();
   core::bool* :is_sync = false;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart.weak.expect
index 1edc07f..7bf8079 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart.weak.expect
@@ -71,6 +71,6 @@
   core::List<core::String*>* list5 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(c.{self::C::call}<core::String*>).{core::Iterable::toList}();
   core::List<core::String*>* list6 = <core::String*>["a", "b", "c"].{core::Iterable::map}<dynamic>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart:30:44: Error: The argument type 'T Function<T>(T)' can't be assigned to the parameter type 'dynamic Function(String)'.
   List<String> list6 = ['a', 'b', 'c'].map(c).toList();
-                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) → dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
+                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart.weak.transformed.expect
index 1edc07f..d01a7f6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart.weak.transformed.expect
@@ -62,15 +62,15 @@
 }
 static method test() → dynamic {
   self::A* a = new self::A::•();
-  core::List<core::String*>* list1 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(a.{self::A::call}).{core::Iterable::toList}();
-  core::List<core::String*>* list2 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1.==(null) ?{(core::String*) →* core::String*} null : #t1.{self::A::call}).{core::Iterable::toList}();
+  core::List<core::String*>* list1 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(a.{self::A::call}).{core::Iterable::toList}();
+  core::List<core::String*>* list2 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1.==(null) ?{(core::String*) →* core::String*} null : #t1.{self::A::call}).{core::Iterable::toList}();
   self::B<core::String*>* b = new self::B::•<core::String*>();
-  core::List<core::String*>* list3 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(b.{self::B::call}).{core::Iterable::toList}();
-  core::List<core::String*>* list4 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2.==(null) ?{(core::String*) →* core::String*} null : #t2.{self::B::call}).{core::Iterable::toList}();
+  core::List<core::String*>* list3 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(b.{self::B::call}).{core::Iterable::toList}();
+  core::List<core::String*>* list4 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2.==(null) ?{(core::String*) →* core::String*} null : #t2.{self::B::call}).{core::Iterable::toList}();
   self::C* c = new self::C::•();
-  core::List<core::String*>* list5 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(c.{self::C::call}<core::String*>).{core::Iterable::toList}();
-  core::List<core::String*>* list6 = <core::String*>["a", "b", "c"].{core::Iterable::map}<dynamic>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart:30:44: Error: The argument type 'T Function<T>(T)' can't be assigned to the parameter type 'dynamic Function(String)'.
+  core::List<core::String*>* list5 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(c.{self::C::call}<core::String*>).{core::Iterable::toList}();
+  core::List<core::String*>* list6 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<dynamic>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/bug33298.dart:30:44: Error: The argument type 'T Function<T>(T)' can't be assigned to the parameter type 'dynamic Function(String)'.
   List<String> list6 = ['a', 'b', 'c'].map(c).toList();
-                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) → dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
+                                           ^" in (let final self::C* #t4 = c in #t4.==(null) ?{<T extends core::Object* = dynamic>(T*) →* T*} null : #t4.{self::C::call}) as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}() as{TypeError} core::List<core::String*>*;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/cascade.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/cascade.dart.weak.transformed.expect
index 8361133..a102674 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/cascade.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/cascade.dart.weak.transformed.expect
@@ -26,10 +26,10 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  core::List<core::int*>* list = let final core::List<core::int*>* #t1 = <core::int*>[1] in block {
+  core::List<core::int*>* list = let final core::List<core::int*>* #t1 = core::_GrowableList::_literal1<core::int*>(1) in block {
     #t1.{core::List::add}(2);
     #t1.{core::List::add}(3);
-    #t1.{core::List::addAll}(<core::int*>[4, 5]);
+    #t1.{core::List::addAll}(core::_GrowableList::_literal2<core::int*>(4, 5));
   } =>#t1;
   core::print(list);
   let final core::List<core::int*>* #t2 = list in block {
@@ -44,10 +44,10 @@
     #t3.{core::List::[]=}(0, 87);
   } =>#t3;
   core::print(list);
-  list = let final core::List<core::int*>* #t4 = <core::int*>[let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/cascade.dart:28:5: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
+  list = let final core::List<core::int*>* #t4 = core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/cascade.dart:28:5: Error: A value of type 'List<int>' can't be assigned to a variable of type 'int'.
  - 'List' is from 'dart:core'.
     [1]
-    ^" in <core::int*>[1] as{TypeError} core::int*] in block {
+    ^" in core::_GrowableList::_literal1<core::int*>(1) as{TypeError} core::int*) in block {
     invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/cascade.dart:30:13: Error: The getter 'last' isn't defined for the class 'int'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
     ..first.last.toString()
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.expect
index b3ae2c0..efb9d56 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.expect
@@ -1,22 +1,21 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "deferred_lib.dart" as def;
 
 import "org-dartlang-testcase:///deferred_lib.dart" deferred as lib;
 
 static method main() → dynamic {}
 static method test() → dynamic {
-  core::print(let final dynamic #t1 = CheckLibraryIsLoaded(lib) in def::C*);
+  core::print(let final dynamic #t1 = CheckLibraryIsLoaded(lib) in #C1);
 }
 
 library;
-import self as def;
+import self as self2;
 import "dart:core" as core;
 
 class C extends core::Object {
   static field core::int* y = 1;
-  synthetic constructor •() → def::C*
+  synthetic constructor •() → self2::C*
     : super core::Object::•()
     ;
   static method m() → core::int*
@@ -35,3 +34,7 @@
 static field core::int* x = 0;
 static method m(dynamic x) → dynamic
   return null;
+
+constants  {
+  #C1 = TypeLiteralConstant(self2::C*)
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.transformed.expect
index 156d0a6..2813c9c5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.transformed.expect
@@ -1,22 +1,21 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "deferred_lib.dart" as def;
 
 import "org-dartlang-testcase:///deferred_lib.dart" deferred as lib;
 
 static method main() → dynamic {}
 static method test() → dynamic {
-  core::print(let final core::Object* #t1 = CheckLibraryIsLoaded(lib) in def::C*);
+  core::print(let final core::Object* #t1 = CheckLibraryIsLoaded(lib) in #C1);
 }
 
 library;
-import self as def;
+import self as self2;
 import "dart:core" as core;
 
 class C extends core::Object {
   static field core::int* y = 1;
-  synthetic constructor •() → def::C*
+  synthetic constructor •() → self2::C*
     : super core::Object::•()
     ;
   static method m() → core::int*
@@ -36,7 +35,6 @@
 static method m(dynamic x) → dynamic
   return null;
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///check_deferred_read_type.dart:11:13 -> TypeLiteralConstant(C*)
-Extra constant evaluation: evaluated: 4, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(self2::C*)
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.expect
index b3b2c22..d3aac88 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.expect
@@ -43,3 +43,11 @@
   core::print(new self::A::•());
   core::print(new self::B::•());
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_redirect_to_nonconst.dart:
+- A. (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:8:9)
+- A.bad (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:10:3)
+- B. (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:14:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.transformed.expect
index b3b2c22..d3aac88 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/const_redirect_to_nonconst.dart.weak.transformed.expect
@@ -43,3 +43,11 @@
   core::print(new self::A::•());
   core::print(new self::B::•());
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_redirect_to_nonconst.dart:
+- A. (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:8:9)
+- A.bad (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:10:3)
+- B. (from org-dartlang-testcase:///const_redirect_to_nonconst.dart:14:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.expect
index 5bf2809..e2fb0a4 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.expect
@@ -48,3 +48,9 @@
 constants  {
   #C1 = self::_Y<Null> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constructor_const_inference.dart:
+- _Y. (from org-dartlang-testcase:///constructor_const_inference.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.transformed.expect
index 5bf2809..e2fb0a4 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/constructor_const_inference.dart.weak.transformed.expect
@@ -48,3 +48,9 @@
 constants  {
   #C1 = self::_Y<Null> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constructor_const_inference.dart:
+- _Y. (from org-dartlang-testcase:///constructor_const_inference.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.weak.transformed.expect
index 09e88b5..b49f9a8 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 
 static method main() → dynamic {
   final core::List<core::int*>* aList = block {
-    final core::List<core::int*>* #t1 = <core::int*>[1];
+    final core::List<core::int*>* #t1 = core::_GrowableList::_literal1<core::int*>(1);
     if(self::oracle() as{TypeError,ForDynamic} core::bool*)
       #t1.{core::List::add}{Invariant}(2);
     if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -16,14 +16,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t1.{core::List::add}{Invariant}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(5, 6, 7).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t1.{core::List::add}{Invariant}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(8, 9, 10).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -46,14 +46,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t2.{core::Set::add}{Invariant}(4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(5, 6, 7).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t2.{core::Set::add}{Invariant}(i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(8, 9, 10).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
@@ -76,14 +76,14 @@
       if(self::oracle() as{TypeError,ForDynamic} core::bool*)
         #t3.{core::Map::[]=}{Invariant}(4, 4);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[5, 6, 7].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(5, 6, 7).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t3.{core::Map::[]=}{Invariant}(i, i);
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[8, 9, 10].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(8, 9, 10).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         if(self::oracle() as{TypeError,ForDynamic} core::bool*)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.weak.transformed.expect
index 6adb0fe..18135e9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart.weak.transformed.expect
@@ -453,7 +453,7 @@
   return true;
 static method testIfElement(dynamic dynVar, core::List<core::int*>* listInt, core::List<core::double*>* listDouble, core::Map<core::String*, core::int*>* mapToInt, core::Map<core::String*, core::double*>* mapToDouble) → dynamic {
   core::List<core::int*>* list10 = block {
-    final core::List<core::int*>* #t1 = <core::int*>[];
+    final core::List<core::int*>* #t1 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t1.{core::List::add}{Invariant}(42);
   } =>#t1;
@@ -470,7 +470,7 @@
     #t3.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t3;
   core::List<dynamic>* list11 = block {
-    final core::List<dynamic>* #t4 = <dynamic>[];
+    final core::List<dynamic>* #t4 = core::_GrowableList::•<dynamic>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t4.{core::List::add}{Invariant}(dynVar);
   } =>#t4;
@@ -487,31 +487,31 @@
     #t6.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t6;
   core::List<core::List<core::int*>*>* list12 = block {
-    final core::List<core::List<core::int*>*>* #t7 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t7 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t7.{core::List::add}{Invariant}(<core::int*>[42]);
+      #t7.{core::List::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t7;
   core::Set<core::List<core::int*>*>* set12 = block {
     final core::Set<core::List<core::int*>*>* #t8 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t8.{core::Set::add}{Invariant}(<core::int*>[42]);
+      #t8.{core::Set::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t8.{core::Set::add}{Invariant}(null);
   } =>#t8;
   core::Map<core::String*, core::List<core::int*>*>* map12 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t9 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t9.{core::Map::[]=}{Invariant}("bar", <core::int*>[42]);
+      #t9.{core::Map::[]=}{Invariant}("bar", core::_GrowableList::_literal1<core::int*>(42));
     #t9.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t9;
   core::List<core::int*>* list20 = block {
-    final core::List<core::int*>* #t10 = <core::int*>[];
+    final core::List<core::int*>* #t10 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t10.{core::List::addAll}{Invariant}(<core::int*>[42]);
+      #t10.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t10;
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t11 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t11.{core::Set::addAll}{Invariant}(<core::int*>[42]);
+      #t11.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t11.{core::Set::add}{Invariant}(null);
   } =>#t11;
   core::Map<core::String*, core::int*>* map20 = block {
@@ -526,14 +526,14 @@
     #t12.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t12;
   core::List<dynamic>* list21 = block {
-    final core::List<dynamic>* #t14 = <dynamic>[];
+    final core::List<dynamic>* #t14 = core::_GrowableList::•<dynamic>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t14.{core::List::addAll}{Invariant}(<dynamic>[dynVar]);
+      #t14.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
   } =>#t14;
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t15 = new col::_CompactLinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t15.{core::Set::addAll}{Invariant}(<dynamic>[dynVar]);
+      #t15.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
     #t15.{core::Set::add}{Invariant}(null);
   } =>#t15;
   core::Map<core::String*, dynamic>* map21 = block {
@@ -548,20 +548,20 @@
     #t16.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t16;
   core::List<core::List<core::int*>*>* list22 = block {
-    final core::List<core::List<core::int*>*>* #t18 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t18 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t18.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+      #t18.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
   } =>#t18;
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t19 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t19.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+      #t19.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
     #t19.{core::Set::add}{Invariant}(null);
   } =>#t19;
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t20 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::_literal1<core::int*>(42)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t21 = :sync-for-iterator.{core::Iterator::current};
         #t20.{core::Map::[]=}{Invariant}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
@@ -570,16 +570,16 @@
     #t20.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t20;
   core::List<core::int*>* list30 = block {
-    final core::List<core::int*>* #t22 = <core::int*>[];
+    final core::List<core::int*>* #t22 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t22.{core::List::addAll}{Invariant}(<core::int*>[42]);
+        #t22.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t22;
   core::Set<core::int*>* set30 = block {
     final core::Set<core::int*>* #t23 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t23.{core::Set::addAll}{Invariant}(<core::int*>[42]);
+        #t23.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t23.{core::Set::add}{Invariant}(null);
   } =>#t23;
   core::Map<core::String*, core::int*>* map30 = block {
@@ -595,16 +595,16 @@
     #t24.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t24;
   core::List<dynamic>* list31 = block {
-    final core::List<dynamic>* #t26 = <dynamic>[];
+    final core::List<dynamic>* #t26 = core::_GrowableList::•<dynamic>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t26.{core::List::addAll}{Invariant}(<dynamic>[dynVar]);
+        #t26.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
   } =>#t26;
   core::Set<dynamic>* set31 = block {
     final core::Set<dynamic>* #t27 = new col::_CompactLinkedHashSet::•<dynamic>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t27.{core::Set::addAll}{Invariant}(<dynamic>[dynVar]);
+        #t27.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
     #t27.{core::Set::add}{Invariant}(null);
   } =>#t27;
   core::Map<core::String*, dynamic>* map31 = block {
@@ -620,23 +620,23 @@
     #t28.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t28;
   core::List<core::List<core::int*>*>* list33 = block {
-    final core::List<core::List<core::int*>*>* #t30 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t30 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t30.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+        #t30.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
   } =>#t30;
   core::Set<core::List<core::int*>*>* set33 = block {
     final core::Set<core::List<core::int*>*>* #t31 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t31.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+        #t31.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
     #t31.{core::Set::add}{Invariant}(null);
   } =>#t31;
   core::Map<core::String*, core::List<core::int*>*>* map33 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t32 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::_literal1<core::int*>(42)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t33 = :sync-for-iterator.{core::Iterator::current};
           #t32.{core::Map::[]=}{Invariant}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
@@ -645,25 +645,25 @@
     #t32.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t32;
   core::List<core::List<core::int*>*>* list40 = block {
-    final core::List<core::List<core::int*>*>* #t34 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t34 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t34.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t34.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t34;
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t35 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t35.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t35.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t35.{core::Set::add}{Invariant}(null);
   } =>#t35;
   core::Map<core::String*, core::List<core::int*>*>* map40 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:41:34: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
   Map<String, List<int>> map40 = {if (oracle(\"foo\")) ...{\"bar\", []}, \"baz\": null};
                                  ^";
   core::List<core::List<core::int*>*>* list41 = block {
-    final core::List<core::List<core::int*>*>* #t36 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t36 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t36.{core::List::addAll}{Invariant}( block {
         final core::Set<core::List<core::int*>*>* #t37 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
-        #t37.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t37.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
       } =>#t37);
   } =>#t36;
   core::Set<core::List<core::int*>*>* set41 = block {
@@ -671,28 +671,28 @@
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t38.{core::Set::addAll}{Invariant}( block {
         final core::Set<core::List<core::int*>*>* #t39 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
-        #t39.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t39.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
       } =>#t39);
     #t38.{core::Set::add}{Invariant}(null);
   } =>#t38;
   core::List<core::List<core::int*>*>* list42 = block {
-    final core::List<core::List<core::int*>*>* #t40 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t40 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t40.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t40.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t40;
   core::Set<core::List<core::int*>*>* set42 = block {
     final core::Set<core::List<core::int*>*>* #t41 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t41.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t41.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t41.{core::Set::add}{Invariant}(null);
   } =>#t41;
   core::Map<core::String*, core::List<core::int*>*>* map42 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t42 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t43 = :sync-for-iterator.{core::Iterator::current};
           #t42.{core::Map::[]=}{Invariant}(#t43.{core::MapEntry::key}, #t43.{core::MapEntry::value});
@@ -701,14 +701,14 @@
     #t42.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t42;
   core::List<core::int*>* list50 = block {
-    final core::List<core::int*>* #t44 = <core::int*>[];
+    final core::List<core::int*>* #t44 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t44.{core::List::addAll}{Invariant}(<core::int*>[]);
+      #t44.{core::List::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t44;
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t45 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t45.{core::Set::addAll}{Invariant}(<core::int*>[]);
+      #t45.{core::Set::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t45.{core::Set::add}{Invariant}(null);
   } =>#t45;
   core::Map<core::String*, core::int*>* map50 = block {
@@ -723,7 +723,7 @@
     #t46.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t46;
   core::List<core::int*>* list51 = block {
-    final core::List<core::int*>* #t48 = <core::int*>[];
+    final core::List<core::int*>* #t48 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t48.{core::List::addAll}{Invariant}( block {
         final core::Set<core::int*>* #t49 = new col::_CompactLinkedHashSet::•<core::int*>();
@@ -738,16 +738,16 @@
     #t50.{core::Set::add}{Invariant}(null);
   } =>#t50;
   core::List<core::int*>* list52 = block {
-    final core::List<core::int*>* #t52 = <core::int*>[];
+    final core::List<core::int*>* #t52 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t52.{core::List::addAll}{Invariant}(<core::int*>[]);
+        #t52.{core::List::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t52;
   core::Set<core::int*>* set52 = block {
     final core::Set<core::int*>* #t53 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t53.{core::Set::addAll}{Invariant}(<core::int*>[]);
+        #t53.{core::Set::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t53.{core::Set::add}{Invariant}(null);
   } =>#t53;
   core::Map<core::String*, core::int*>* map52 = block {
@@ -763,20 +763,20 @@
     #t54.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t54;
   core::List<core::List<core::int*>*>* list60 = block {
-    final core::List<core::List<core::int*>*>* #t56 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t56 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t56.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t56.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t56;
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t57 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t57.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t57.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t57.{core::Set::add}{Invariant}(null);
   } =>#t57;
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t58 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t59 = :sync-for-iterator.{core::Iterator::current};
         #t58.{core::Map::[]=}{Invariant}(#t59.{core::MapEntry::key}, #t59.{core::MapEntry::value});
@@ -785,23 +785,23 @@
     #t58.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t58;
   core::List<core::List<core::int*>*>* list61 = block {
-    final core::List<core::List<core::int*>*>* #t60 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t60 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t60.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t60.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t60;
   core::Set<core::List<core::int*>*>* set61 = block {
     final core::Set<core::List<core::int*>*>* #t61 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t61.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t61.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t61.{core::Set::add}{Invariant}(null);
   } =>#t61;
   core::Map<core::String*, core::List<core::int*>*>* map61 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t62 = <core::String*, core::List<core::int*>*>{};
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t63 = :sync-for-iterator.{core::Iterator::current};
           #t62.{core::Map::[]=}{Invariant}(#t63.{core::MapEntry::key}, #t63.{core::MapEntry::value});
@@ -810,31 +810,31 @@
     #t62.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t62;
   core::List<core::List<core::int*>*>* list70 = block {
-    final core::List<core::List<core::int*>*>* #t64 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t64 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t64.{core::List::add}{Invariant}(<core::int*>[]);
+      #t64.{core::List::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t64;
   core::Set<core::List<core::int*>*>* set70 = block {
     final core::Set<core::List<core::int*>*>* #t65 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t65.{core::Set::add}{Invariant}(<core::int*>[]);
+      #t65.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t65.{core::Set::add}{Invariant}(null);
   } =>#t65;
   core::List<core::List<core::int*>*>* list71 = block {
-    final core::List<core::List<core::int*>*>* #t66 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t66 = core::_GrowableList::•<core::List<core::int*>*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t66.{core::List::add}{Invariant}(<core::int*>[]);
+        #t66.{core::List::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t66;
   core::Set<core::List<core::int*>*>* set71 = block {
     final core::Set<core::List<core::int*>*>* #t67 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t67.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t67.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t67.{core::Set::add}{Invariant}(null);
   } =>#t67;
   core::List<core::num*>* list80 = block {
-    final core::List<core::num*>* #t68 = <core::num*>[];
+    final core::List<core::num*>* #t68 = core::_GrowableList::•<core::num*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t68.{core::List::add}{Invariant}(42);
     else
@@ -857,7 +857,7 @@
     #t70.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t70;
   core::List<core::num*>* list81 = block {
-    final core::List<core::num*>* #t71 = <core::num*>[];
+    final core::List<core::num*>* #t71 = core::_GrowableList::•<core::num*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t71.{core::List::addAll}{Invariant}(listInt);
     else
@@ -890,7 +890,7 @@
     #t73.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t73;
   core::List<dynamic>* list82 = block {
-    final core::List<dynamic>* #t76 = <dynamic>[];
+    final core::List<dynamic>* #t76 = core::_GrowableList::•<dynamic>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t76.{core::List::addAll}{Invariant}(listInt);
     else
@@ -916,7 +916,7 @@
     #t78.{core::Set::add}{Invariant}(null);
   } =>#t78;
   core::List<core::num*>* list83 = block {
-    final core::List<core::num*>* #t79 = <core::num*>[];
+    final core::List<core::num*>* #t79 = core::_GrowableList::•<core::num*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t79.{core::List::add}{Invariant}(42);
     else
@@ -944,7 +944,7 @@
     #t81.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t81;
   core::List<core::int*>* list90 = block {
-    final core::List<core::int*>* #t83 = <core::int*>[];
+    final core::List<core::int*>* #t83 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t83.{core::List::add}{Invariant}(dynVar as{TypeError,ForDynamic} core::int*);
   } =>#t83;
@@ -961,7 +961,7 @@
     #t85.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t85;
   core::List<core::int*>* list91 = block {
-    final core::List<core::int*>* #t86 = <core::int*>[];
+    final core::List<core::int*>* #t86 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*) {
       core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -1003,7 +1003,7 @@
     #t92.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t92;
   core::List<core::int*>* list100 = block {
-    final core::List<core::int*>* #t96 = <core::int*>[];
+    final core::List<core::int*>* #t96 = core::_GrowableList::•<core::int*>(0);
     if(dynVar as{TypeError,ForDynamic} core::bool*)
       #t96.{core::List::add}{Invariant}(42);
   } =>#t96;
@@ -1020,7 +1020,7 @@
 }
 static method testIfElementErrors(core::Map<core::int*, core::int*>* map) → dynamic {
   block {
-    final core::List<core::int*>* #t99 = <core::int*>[];
+    final core::List<core::int*>* #t99 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t99.{core::List::add}{Invariant}(let final<BottomType> #t100 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:89:28: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[if (oracle(\"foo\")) \"bar\"];
@@ -1043,18 +1043,18 @@
     #t103.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t103;
   block {
-    final core::List<core::int*>* #t105 = <core::int*>[];
+    final core::List<core::int*>* #t105 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t105.{core::List::addAll}{Invariant}(<core::int*>[let final<BottomType> #t106 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:92:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      #t105.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t106 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:92:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[if (oracle(\"foo\")) ...[\"bar\"]];
-                               ^" in "bar" as{TypeError} core::int*]);
+                               ^" in "bar" as{TypeError} core::int*));
   } =>#t105;
   block {
     final core::Set<core::int*>* #t107 = new col::_CompactLinkedHashSet::•<core::int*>();
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
-      #t107.{core::Set::addAll}{Invariant}(<core::int*>[let final<BottomType> #t108 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:93:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+      #t107.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t108 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:93:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{if (oracle(\"foo\")) ...[\"bar\"], null};
-                               ^" in "bar" as{TypeError} core::int*]);
+                               ^" in "bar" as{TypeError} core::int*));
     #t107.{core::Set::add}{Invariant}(null);
   } =>#t107;
   block {
@@ -1071,7 +1071,7 @@
     #t109.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t109;
   block {
-    final core::List<core::int*>* #t112 = <core::int*>[];
+    final core::List<core::int*>* #t112 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t112.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:95:31: Error: Unexpected type 'Map<int, int>' of a spread.  Expected 'dynamic' or an Iterable.
  - 'Map' is from 'dart:core'.
@@ -1095,7 +1095,7 @@
   <String, int>{if (oracle(\"foo\")) ...[\"bar\"], \"baz\": null};
                                       ^": null};
   block {
-    final core::List<core::String*>* #t114 = <core::String*>[];
+    final core::List<core::String*>* #t114 = core::_GrowableList::•<core::String*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t114.{core::List::add}{Invariant}(let final<BottomType> #t115 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:98:31: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
   <String>[if (oracle(\"foo\")) 42 else 3.14];
@@ -1130,7 +1130,7 @@
     #t120.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t120;
   block {
-    final core::List<core::int*>* #t123 = <core::int*>[];
+    final core::List<core::int*>* #t123 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t123.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:101:31: Error: Unexpected type 'Map<int, int>' of a spread.  Expected 'dynamic' or an Iterable.
  - 'Map' is from 'dart:core'.
@@ -1158,7 +1158,7 @@
   <String, int>{if (oracle(\"foo\")) ...[42] else \"bar\": 42, \"baz\": null};
                                       ^": null};
   block {
-    final core::List<core::int*>* #t125 = <core::int*>[];
+    final core::List<core::int*>* #t125 = core::_GrowableList::•<core::int*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t125.{core::List::add}{Invariant}(42);
     else
@@ -1204,7 +1204,7 @@
   var map13 = {if (oracle(\"foo\")) \"bar\": 3.14 else 42};
                                                    ^": null};
   core::List<core::int*>* list20 = block {
-    final core::List<core::int*>* #t127 = <core::int*>[];
+    final core::List<core::int*>* #t127 = core::_GrowableList::•<core::int*>(0);
     if(let final<BottomType> #t128 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:114:27: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
   List<int> list20 = [if (42) 42];
                           ^" in 42 as{TypeError} core::bool*)
@@ -1225,7 +1225,7 @@
       #t131.{core::Map::[]=}{Invariant}(42, 42);
   } =>#t131;
   core::List<core::String*>* list40 = block {
-    final core::List<core::String*>* #t133 = <core::String*>[];
+    final core::List<core::String*>* #t133 = core::_GrowableList::•<core::String*>(0);
     if(self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*)
       #t133.{core::List::add}{Invariant}(let final<BottomType> #t134 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:117:53: Error: A value of type 'bool' can't be assigned to a variable of type 'String'.
   List<String> list40 = <String>[if (oracle(\"foo\")) true else 42];
@@ -1271,7 +1271,7 @@
 }
 static method testForElement(dynamic dynVar, core::List<core::int*>* listInt, core::List<core::double*>* listDouble, core::int* index, core::Map<core::String*, core::int*>* mapStringInt, core::Map<core::String*, core::double*>* mapStringDouble) → dynamic {
   core::List<core::int*>* list10 = block {
-    final core::List<core::int*>* #t145 = <core::int*>[];
+    final core::List<core::int*>* #t145 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t145.{core::List::add}{Invariant}(42);
   } =>#t145;
@@ -1288,7 +1288,7 @@
     #t147.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t147;
   core::List<dynamic>* list11 = block {
-    final core::List<dynamic>* #t148 = <dynamic>[];
+    final core::List<dynamic>* #t148 = core::_GrowableList::•<dynamic>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t148.{core::List::add}{Invariant}(dynVar);
   } =>#t148;
@@ -1305,31 +1305,31 @@
     #t150.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t150;
   core::List<core::List<core::int*>*>* list12 = block {
-    final core::List<core::List<core::int*>*>* #t151 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t151 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t151.{core::List::add}{Invariant}(<core::int*>[42]);
+      #t151.{core::List::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t151;
   core::Set<core::List<core::int*>*>* set12 = block {
     final core::Set<core::List<core::int*>*>* #t152 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t152.{core::Set::add}{Invariant}(<core::int*>[42]);
+      #t152.{core::Set::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t152.{core::Set::add}{Invariant}(null);
   } =>#t152;
   core::Map<core::String*, core::List<core::int*>*>* map12 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t153 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t153.{core::Map::[]=}{Invariant}("bar", <core::int*>[42]);
+      #t153.{core::Map::[]=}{Invariant}("bar", core::_GrowableList::_literal1<core::int*>(42));
     #t153.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t153;
   core::List<core::int*>* list20 = block {
-    final core::List<core::int*>* #t154 = <core::int*>[];
+    final core::List<core::int*>* #t154 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t154.{core::List::addAll}{Invariant}(<core::int*>[42]);
+      #t154.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t154;
   core::Set<core::int*>* set20 = block {
     final core::Set<core::int*>* #t155 = new col::_CompactLinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t155.{core::Set::addAll}{Invariant}(<core::int*>[42]);
+      #t155.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t155.{core::Set::add}{Invariant}(null);
   } =>#t155;
   core::Map<core::String*, core::int*>* map20 = block {
@@ -1344,14 +1344,14 @@
     #t156.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t156;
   core::List<dynamic>* list21 = block {
-    final core::List<dynamic>* #t158 = <dynamic>[];
+    final core::List<dynamic>* #t158 = core::_GrowableList::•<dynamic>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t158.{core::List::addAll}{Invariant}(<dynamic>[dynVar]);
+      #t158.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
   } =>#t158;
   core::Set<dynamic>* set21 = block {
     final core::Set<dynamic>* #t159 = new col::_CompactLinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t159.{core::Set::addAll}{Invariant}(<dynamic>[dynVar]);
+      #t159.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
     #t159.{core::Set::add}{Invariant}(null);
   } =>#t159;
   core::Map<core::String*, dynamic>* map21 = block {
@@ -1366,20 +1366,20 @@
     #t160.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t160;
   core::List<core::List<core::int*>*>* list22 = block {
-    final core::List<core::List<core::int*>*>* #t162 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t162 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t162.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+      #t162.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
   } =>#t162;
   core::Set<core::List<core::int*>*>* set22 = block {
     final core::Set<core::List<core::int*>*>* #t163 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t163.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+      #t163.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
     #t163.{core::Set::add}{Invariant}(null);
   } =>#t163;
   core::Map<core::String*, core::List<core::int*>*>* map22 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t164 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::_literal1<core::int*>(42)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t165 = :sync-for-iterator.{core::Iterator::current};
         #t164.{core::Map::[]=}{Invariant}(#t165.{core::MapEntry::key}, #t165.{core::MapEntry::value});
@@ -1388,16 +1388,16 @@
     #t164.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t164;
   core::List<core::int*>* list30 = block {
-    final core::List<core::int*>* #t166 = <core::int*>[];
+    final core::List<core::int*>* #t166 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t166.{core::List::addAll}{Invariant}(<core::int*>[42]);
+        #t166.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t166;
   core::Set<core::int*>* set30 = block {
     final core::Set<core::int*>* #t167 = new col::_CompactLinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t167.{core::Set::addAll}{Invariant}(<core::int*>[42]);
+        #t167.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
     #t167.{core::Set::add}{Invariant}(null);
   } =>#t167;
   core::Map<core::String*, core::int*>* map30 = block {
@@ -1413,16 +1413,16 @@
     #t168.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t168;
   core::List<dynamic>* list31 = block {
-    final core::List<dynamic>* #t170 = <dynamic>[];
+    final core::List<dynamic>* #t170 = core::_GrowableList::•<dynamic>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t170.{core::List::addAll}{Invariant}(<dynamic>[dynVar]);
+        #t170.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
   } =>#t170;
   core::Set<dynamic>* set31 = block {
     final core::Set<dynamic>* #t171 = new col::_CompactLinkedHashSet::•<dynamic>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t171.{core::Set::addAll}{Invariant}(<dynamic>[dynVar]);
+        #t171.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<dynamic>(dynVar));
     #t171.{core::Set::add}{Invariant}(null);
   } =>#t171;
   core::Map<core::String*, dynamic>* map31 = block {
@@ -1438,23 +1438,23 @@
     #t172.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t172;
   core::List<core::List<core::int*>*>* list33 = block {
-    final core::List<core::List<core::int*>*>* #t174 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t174 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t174.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+        #t174.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
   } =>#t174;
   core::Set<core::List<core::int*>*>* set33 = block {
     final core::Set<core::List<core::int*>*>* #t175 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t175.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[42]]);
+        #t175.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(42)));
     #t175.{core::Set::add}{Invariant}(null);
   } =>#t175;
   core::Map<core::String*, core::List<core::int*>*>* map33 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t176 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[42]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::_literal1<core::int*>(42)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t177 = :sync-for-iterator.{core::Iterator::current};
           #t176.{core::Map::[]=}{Invariant}(#t177.{core::MapEntry::key}, #t177.{core::MapEntry::value});
@@ -1463,20 +1463,20 @@
     #t176.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t176;
   core::List<core::List<core::int*>*>* list40 = block {
-    final core::List<core::List<core::int*>*>* #t178 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t178 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t178.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t178.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t178;
   core::Set<core::List<core::int*>*>* set40 = block {
     final core::Set<core::List<core::int*>*>* #t179 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t179.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t179.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t179.{core::Set::add}{Invariant}(null);
   } =>#t179;
   core::Map<core::String*, core::List<core::int*>*>* map40 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t180 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t181 = :sync-for-iterator.{core::Iterator::current};
         #t180.{core::Map::[]=}{Invariant}(#t181.{core::MapEntry::key}, #t181.{core::MapEntry::value});
@@ -1485,11 +1485,11 @@
     #t180.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t180;
   core::List<core::List<core::int*>*>* list41 = block {
-    final core::List<core::List<core::int*>*>* #t182 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t182 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t182.{core::List::addAll}{Invariant}( block {
         final core::Set<core::List<core::int*>*>* #t183 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
-        #t183.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t183.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
       } =>#t183);
   } =>#t182;
   core::Set<core::List<core::int*>*>* set41 = block {
@@ -1497,28 +1497,28 @@
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t184.{core::Set::addAll}{Invariant}( block {
         final core::Set<core::List<core::int*>*>* #t185 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
-        #t185.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t185.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
       } =>#t185);
     #t184.{core::Set::add}{Invariant}(null);
   } =>#t184;
   core::List<core::List<core::int*>*>* list42 = block {
-    final core::List<core::List<core::int*>*>* #t186 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t186 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t186.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t186.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t186;
   core::Set<core::List<core::int*>*>* set42 = block {
     final core::Set<core::List<core::int*>*>* #t187 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t187.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t187.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t187.{core::Set::add}{Invariant}(null);
   } =>#t187;
   core::Map<core::String*, core::List<core::int*>*>* map42 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t188 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t189 = :sync-for-iterator.{core::Iterator::current};
           #t188.{core::Map::[]=}{Invariant}(#t189.{core::MapEntry::key}, #t189.{core::MapEntry::value});
@@ -1527,14 +1527,14 @@
     #t188.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t188;
   core::List<core::int*>* list50 = block {
-    final core::List<core::int*>* #t190 = <core::int*>[];
+    final core::List<core::int*>* #t190 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t190.{core::List::addAll}{Invariant}(<core::int*>[]);
+      #t190.{core::List::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t190;
   core::Set<core::int*>* set50 = block {
     final core::Set<core::int*>* #t191 = new col::_CompactLinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t191.{core::Set::addAll}{Invariant}(<core::int*>[]);
+      #t191.{core::Set::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t191.{core::Set::add}{Invariant}(null);
   } =>#t191;
   core::Map<core::String*, core::int*>* map50 = block {
@@ -1549,7 +1549,7 @@
     #t192.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t192;
   core::List<core::int*>* list51 = block {
-    final core::List<core::int*>* #t194 = <core::int*>[];
+    final core::List<core::int*>* #t194 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t194.{core::List::addAll}{Invariant}( block {
         final core::Set<core::int*>* #t195 = new col::_CompactLinkedHashSet::•<core::int*>();
@@ -1564,33 +1564,33 @@
     #t196.{core::Set::add}{Invariant}(null);
   } =>#t196;
   core::List<core::int*>* list52 = block {
-    final core::List<core::int*>* #t198 = <core::int*>[];
+    final core::List<core::int*>* #t198 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t198.{core::List::addAll}{Invariant}(<core::int*>[]);
+        #t198.{core::List::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t198;
   core::Set<core::int*>* set52 = block {
     final core::Set<core::int*>* #t199 = new col::_CompactLinkedHashSet::•<core::int*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t199.{core::Set::addAll}{Invariant}(<core::int*>[]);
+        #t199.{core::Set::addAll}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t199.{core::Set::add}{Invariant}(null);
   } =>#t199;
   core::List<core::List<core::int*>*>* list60 = block {
-    final core::List<core::List<core::int*>*>* #t200 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t200 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t200.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t200.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t200;
   core::Set<core::List<core::int*>*>* set60 = block {
     final core::Set<core::List<core::int*>*>* #t201 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t201.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+      #t201.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t201.{core::Set::add}{Invariant}(null);
   } =>#t201;
   core::Map<core::String*, core::List<core::int*>*>* map60 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t202 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t203 = :sync-for-iterator.{core::Iterator::current};
         #t202.{core::Map::[]=}{Invariant}(#t203.{core::MapEntry::key}, #t203.{core::MapEntry::value});
@@ -1599,23 +1599,23 @@
     #t202.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t202;
   core::List<core::List<core::int*>*>* list61 = block {
-    final core::List<core::List<core::int*>*>* #t204 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t204 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t204.{core::List::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t204.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t204;
   core::Set<core::List<core::int*>*>* set61 = block {
     final core::Set<core::List<core::int*>*>* #t205 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t205.{core::Set::addAll}{Invariant}(<core::List<core::int*>*>[<core::int*>[]]);
+        #t205.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
     #t205.{core::Set::add}{Invariant}(null);
   } =>#t205;
   core::Map<core::String*, core::List<core::int*>*>* map61 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t206 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*) {
-        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+        core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"bar": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::MapEntry<core::String*, core::List<core::int*>*>* #t207 = :sync-for-iterator.{core::Iterator::current};
           #t206.{core::Map::[]=}{Invariant}(#t207.{core::MapEntry::key}, #t207.{core::MapEntry::value});
@@ -1624,44 +1624,44 @@
     #t206.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t206;
   core::List<core::List<core::int*>*>* list70 = block {
-    final core::List<core::List<core::int*>*>* #t208 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t208 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t208.{core::List::add}{Invariant}(<core::int*>[]);
+      #t208.{core::List::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t208;
   core::Set<core::List<core::int*>*>* set70 = block {
     final core::Set<core::List<core::int*>*>* #t209 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t209.{core::Set::add}{Invariant}(<core::int*>[]);
+      #t209.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t209.{core::Set::add}{Invariant}(null);
   } =>#t209;
   core::Map<core::String*, core::List<core::int*>*>* map70 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t210 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-      #t210.{core::Map::[]=}{Invariant}("bar", <core::int*>[]);
+      #t210.{core::Map::[]=}{Invariant}("bar", core::_GrowableList::•<core::int*>(0));
     #t210.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t210;
   core::List<core::List<core::int*>*>* list71 = block {
-    final core::List<core::List<core::int*>*>* #t211 = <core::List<core::int*>*>[];
+    final core::List<core::List<core::int*>*>* #t211 = core::_GrowableList::•<core::List<core::int*>*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t211.{core::List::add}{Invariant}(<core::int*>[]);
+        #t211.{core::List::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
   } =>#t211;
   core::Set<core::List<core::int*>*>* set71 = block {
     final core::Set<core::List<core::int*>*>* #t212 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t212.{core::Set::add}{Invariant}(<core::int*>[]);
+        #t212.{core::Set::add}{Invariant}(core::_GrowableList::•<core::int*>(0));
     #t212.{core::Set::add}{Invariant}(null);
   } =>#t212;
   core::Map<core::String*, core::List<core::int*>*>* map71 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t213 = <core::String*, core::List<core::int*>*>{};
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
-        #t213.{core::Map::[]=}{Invariant}("bar", <core::int*>[]);
+        #t213.{core::Map::[]=}{Invariant}("bar", core::_GrowableList::•<core::int*>(0));
     #t213.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t213;
   core::List<core::num*>* list80 = block {
-    final core::List<core::num*>* #t214 = <core::num*>[];
+    final core::List<core::num*>* #t214 = core::_GrowableList::•<core::num*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t214.{core::List::add}{Invariant}(42);
@@ -1687,7 +1687,7 @@
     #t216.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t216;
   core::List<core::num*>* list81 = block {
-    final core::List<core::num*>* #t217 = <core::num*>[];
+    final core::List<core::num*>* #t217 = core::_GrowableList::•<core::num*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t217.{core::List::addAll}{Invariant}(listInt);
@@ -1723,7 +1723,7 @@
     #t219.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t219;
   core::List<dynamic>* list82 = block {
-    final core::List<dynamic>* #t222 = <dynamic>[];
+    final core::List<dynamic>* #t222 = core::_GrowableList::•<dynamic>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t222.{core::List::addAll}{Invariant}(listInt);
@@ -1759,7 +1759,7 @@
     #t224.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t224;
   core::List<core::num*>* list83 = block {
-    final core::List<core::num*>* #t227 = <core::num*>[];
+    final core::List<core::num*>* #t227 = core::_GrowableList::•<core::num*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
         #t227.{core::List::add}{Invariant}(42);
@@ -1790,7 +1790,7 @@
     #t229.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t229;
   core::List<core::int*>* list90 = block {
-    final core::List<core::int*>* #t231 = <core::int*>[];
+    final core::List<core::int*>* #t231 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
       #t231.{core::List::add}{Invariant}(dynVar as{TypeError,ForDynamic} core::int*);
   } =>#t231;
@@ -1807,7 +1807,7 @@
     #t233.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t233;
   core::List<core::int*>* list91 = block {
-    final core::List<core::int*>* #t234 = <core::int*>[];
+    final core::List<core::int*>* #t234 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1)) {
       core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -1849,7 +1849,7 @@
     #t240.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t240;
   core::List<core::int*>* list100 = block {
-    final core::List<core::int*>* #t244 = <core::int*>[];
+    final core::List<core::int*>* #t244 = core::_GrowableList::•<core::int*>(0);
     for (final core::int* #t245 = index = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; index = index.{core::num::+}(1))
       #t244.{core::List::add}{Invariant}(42);
   } =>#t244;
@@ -1864,9 +1864,9 @@
       #t248.{core::Map::[]=}{Invariant}("bar", 42);
   } =>#t248;
   core::List<core::int*>* list110 = block {
-    final core::List<core::int*>* #t250 = <core::int*>[];
+    final core::List<core::int*>* #t250 = core::_GrowableList::•<core::int*>(0);
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t250.{core::List::add}{Invariant}(i);
@@ -1876,7 +1876,7 @@
   core::Set<core::int*>* set110 = block {
     final core::Set<core::int*>* #t251 = new col::_CompactLinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t251.{core::Set::add}{Invariant}(i);
@@ -1887,7 +1887,7 @@
   core::Map<core::String*, core::int*>* map110 = block {
     final core::Map<core::String*, core::int*>* #t252 = <core::String*, core::int*>{};
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         core::int* i = :sync-for-iterator.{core::Iterator::current};
         #t252.{core::Map::[]=}{Invariant}("bar", i);
@@ -1896,7 +1896,7 @@
     #t252.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t252;
   core::List<core::int*>* list120 = block {
-    final core::List<core::int*>* #t253 = <core::int*>[];
+    final core::List<core::int*>* #t253 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -1928,7 +1928,7 @@
     #t255.{core::Map::[]=}{Invariant}("baz", null);
   } =>#t255;
   core::List<core::int*>* list130 = block {
-    final core::List<core::int*>* #t256 = <core::int*>[];
+    final core::List<core::int*>* #t256 = core::_GrowableList::•<core::int*>(0);
     for (core::int* i = 1; i.{core::num::<}(2); i = i.{core::num::+}(1))
       #t256.{core::List::add}{Invariant}(i);
   } =>#t256;
@@ -1960,7 +1960,7 @@
       #L1:
       {
         block {
-          final core::List<core::int*>* #t259 = <core::int*>[];
+          final core::List<core::int*>* #t259 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             #t259.{core::List::add}{Invariant}(let final<BottomType> #t260 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:212:45: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[for (int i = 0; oracle(\"foo\"); i++) \"bar\"];
@@ -1987,18 +1987,18 @@
                                                                ^" in "baz" as{TypeError} core::int*, null);
         } =>#t263;
         block {
-          final core::List<core::int*>* #t267 = <core::int*>[];
+          final core::List<core::int*>* #t267 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-            #t267.{core::List::addAll}{Invariant}(<core::int*>[let final<BottomType> #t268 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:215:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            #t267.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t268 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:215:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>[for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"]];
-                                                ^" in "bar" as{TypeError} core::int*]);
+                                                ^" in "bar" as{TypeError} core::int*));
         } =>#t267;
         block {
           final core::Set<core::int*>* #t269 = new col::_CompactLinkedHashSet::•<core::int*>();
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
-            #t269.{core::Set::addAll}{Invariant}(<core::int*>[let final<BottomType> #t270 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:216:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            #t269.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t270 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:216:49: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   <int>{for (int i = 0; oracle(\"foo\"); i++) ...[\"bar\"], null};
-                                                ^" in "bar" as{TypeError} core::int*]);
+                                                ^" in "bar" as{TypeError} core::int*));
           #t269.{core::Set::add}{Invariant}(null);
         } =>#t269;
         block {
@@ -2019,7 +2019,7 @@
                                                                     ^" in "baz" as{TypeError} core::int*, null);
         } =>#t271;
         block {
-          final core::List<core::int*>* #t276 = <core::int*>[];
+          final core::List<core::int*>* #t276 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             #t276.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:218:48: Error: Unexpected type 'Map<int, int>' of a spread.  Expected 'dynamic' or an Iterable.
  - 'Map' is from 'dart:core'.
@@ -2043,7 +2043,7 @@
   <int, int>{for (int i = 0; oracle(\"foo\"); i++) ...list, 42: null};
                                                     ^": null};
         block {
-          final core::List<core::String*>* #t278 = <core::String*>[];
+          final core::List<core::String*>* #t278 = core::_GrowableList::•<core::String*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
               #t278.{core::List::add}{Invariant}(let final<BottomType> #t279 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:221:62: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
@@ -2081,7 +2081,7 @@
           #t284.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t284;
         block {
-          final core::List<core::int*>* #t287 = <core::int*>[];
+          final core::List<core::int*>* #t287 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
               #t287.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:224:62: Error: Unexpected type 'Map<int, int>' of a spread.  Expected 'dynamic' or an Iterable.
@@ -2111,7 +2111,7 @@
   <String, int>{for (int i = 0; oracle(\"foo\"); i++) if (oracle()) ...list else \"bar\": 42, \"baz\": null};
                                                                      ^": null};
         block {
-          final core::List<core::int*>* #t289 = <core::int*>[];
+          final core::List<core::int*>* #t289 = core::_GrowableList::•<core::int*>(0);
           for (core::int* i = 0; self::oracle<core::String*>("foo") as{TypeError,ForDynamic} core::bool*; i = i.{core::num::+}(1))
             if(self::oracle<dynamic>() as{TypeError,ForDynamic} core::bool*)
               #t289.{core::List::add}{Invariant}(42);
@@ -2142,9 +2142,9 @@
                                                                                     ^": null};
         final core::int* i = 0;
         block {
-          final core::List<core::int*>* #t291 = <core::int*>[];
+          final core::List<core::int*>* #t291 = core::_GrowableList::•<core::int*>(0);
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal1<core::int*>(1).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t292 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2159,7 +2159,7 @@
         block {
           final core::Set<core::int*>* #t293 = new col::_CompactLinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal1<core::int*>(1).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t294 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2175,7 +2175,7 @@
         block {
           final core::Map<core::String*, core::int*>* #t295 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1].{core::Iterable::iterator};
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal1<core::int*>(1).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               final core::int* #t296 = :sync-for-iterator.{core::Iterator::current};
               {
@@ -2189,7 +2189,7 @@
           #t295.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t295;
         core::List<dynamic>* list10 = block {
-          final core::List<dynamic>* #t297 = <dynamic>[];
+          final core::List<dynamic>* #t297 = core::_GrowableList::•<dynamic>(0);
           {
             core::Iterator<dynamic>* :sync-for-iterator = (let final<BottomType> #t298 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:236:31: Error: The type 'String' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Iterable' is from 'dart:core'.
@@ -2230,13 +2230,13 @@
           #t301.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t301;
         core::List<core::int*>* list20 = block {
-          final core::List<core::int*>* #t303 = <core::int*>[];
+          final core::List<core::int*>* #t303 = core::_GrowableList::•<core::int*>(0);
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t304 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t304 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:32: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
                                ^" in "not" as{TypeError} core::int*, let final<BottomType> #t305 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:239:39: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list20 = [for (int i in [\"not\", \"int\"]) i];
-                                      ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
+                                      ^" in "int" as{TypeError} core::int*).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t303.{core::List::add}{Invariant}(i);
@@ -2246,11 +2246,11 @@
         core::Set<core::int*>* set20 = block {
           final core::Set<core::int*>* #t306 = new col::_CompactLinkedHashSet::•<core::int*>();
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t307 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t307 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t308 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:240:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set20 = {for (int i in [\"not\", \"int\"]) i, null};
-                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t306.{core::Set::add}{Invariant}(i);
@@ -2261,11 +2261,11 @@
         core::Map<core::String*, core::int*>* map20 = block {
           final core::Map<core::String*, core::int*>* #t309 = <core::String*, core::int*>{};
           {
-            core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[let final<BottomType> #t310 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+            core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t310 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:31: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
                               ^" in "not" as{TypeError} core::int*, let final<BottomType> #t311 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:241:38: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map20 = {for (int i in [\"not\", \"int\"]) \"bar\": i, \"baz\": null};
-                                     ^" in "int" as{TypeError} core::int*].{core::Iterable::iterator};
+                                     ^" in "int" as{TypeError} core::int*).{core::Iterable::iterator};
             for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
               core::int* i = :sync-for-iterator.{core::Iterator::current};
               #t309.{core::Map::[]=}{Invariant}("bar", i);
@@ -2273,7 +2273,7 @@
           }
           #t309.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t309;
-        final core::List<dynamic>* #t312 = <dynamic>[];
+        final core::List<dynamic>* #t312 = core::_GrowableList::•<dynamic>(0);
         {
           asy::Stream<dynamic>* :stream = let final<BottomType> #t313 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:242:37: Error: The type 'String' used in the 'for' loop must implement 'Stream<dynamic>'.
  - 'Stream' is from 'dart:async'.
@@ -2355,13 +2355,13 @@
         core::Map<core::String*, dynamic>* map30 = block {
           #t322.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t322;
-        final core::List<core::int*>* #t327 = <core::int*>[];
+        final core::List<core::int*>* #t327 = core::_GrowableList::•<core::int*>(0);
         {
-          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t328 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t328 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:58: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
                                                          ^" in "not" as{TypeError} core::int*, let final<BottomType> #t329 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:245:65: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var list40 = [await for (int i in Stream.fromIterable([\"not\", \"int\"])) i];
-                                                                ^" in "int" as{TypeError} core::int*]);
+                                                                ^" in "int" as{TypeError} core::int*));
           asy::_StreamIterator<core::int*>* :for-iterator = new asy::_StreamIterator::•<core::int*>(:stream);
           try
             #L5:
@@ -2384,11 +2384,11 @@
         core::List<core::int*>* list40 = block {} =>#t327;
         final core::Set<core::int*>* #t333 = new col::_CompactLinkedHashSet::•<core::int*>();
         {
-          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t334 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t334 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t335 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:246:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var set40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) i, null};
-                                                               ^" in "int" as{TypeError} core::int*]);
+                                                               ^" in "int" as{TypeError} core::int*));
           asy::_StreamIterator<core::int*>* :for-iterator = new asy::_StreamIterator::•<core::int*>(:stream);
           try
             #L6:
@@ -2413,11 +2413,11 @@
         } =>#t333;
         final core::Map<core::String*, core::int*>* #t339 = <core::String*, core::int*>{};
         {
-          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(<core::int*>[let final<BottomType> #t340 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+          asy::Stream<core::int*> :stream = asy::Stream::fromIterable<core::int*>(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t340 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:57: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
                                                         ^" in "not" as{TypeError} core::int*, let final<BottomType> #t341 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:247:64: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   var map40 = {await for (int i in Stream.fromIterable([\"not\", \"int\"])) \"bar\": i, \"baz\": null};
-                                                               ^" in "int" as{TypeError} core::int*]);
+                                                               ^" in "int" as{TypeError} core::int*));
           asy::_StreamIterator<core::int*>* :for-iterator = new asy::_StreamIterator::•<core::int*>(:stream);
           try
             #L7:
@@ -2441,7 +2441,7 @@
           #t339.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t339;
         core::List<core::int*>* list50 = block {
-          final core::List<core::int*>* #t345 = <core::int*>[];
+          final core::List<core::int*>* #t345 = core::_GrowableList::•<core::int*>(0);
           for (; ; )
             #t345.{core::List::add}{Invariant}(42);
         } =>#t345;
@@ -2458,7 +2458,7 @@
           #t347.{core::Map::[]=}{Invariant}("baz", null);
         } =>#t347;
         core::List<core::int*>* list60 = block {
-          final core::List<core::int*>* #t348 = <core::int*>[];
+          final core::List<core::int*>* #t348 = core::_GrowableList::•<core::int*>(0);
           for (; let final<BottomType> #t349 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection_inference.dart:251:24: Error: A value of type 'String' can't be assigned to a variable of type 'bool'.
   var list60 = [for (; \"not bool\";) 42];
                        ^" in "not bool" as{TypeError} core::bool*; )
@@ -2495,7 +2495,7 @@
 }
 static method testForElementErrorsNotAsync(asy::Stream<core::int*>* stream) → dynamic {
   block {
-    final core::List<core::int*>* #t354 = <core::int*>[];
+    final core::List<core::int*>* #t354 = core::_GrowableList::•<core::int*>(0);
     await for (core::int* i in stream)
       #t354.{core::List::add}{Invariant}(i);
   } =>#t354;
@@ -2512,7 +2512,7 @@
 }
 static method testPromotion(self::A* a) → dynamic {
   core::List<core::int*>* list10 = block {
-    final core::List<core::int*>* #t357 = <core::int*>[];
+    final core::List<core::int*>* #t357 = core::_GrowableList::•<core::int*>(0);
     if(a is self::B*)
       #t357.{core::List::add}{Invariant}(a{self::B*}.{self::B::foo});
   } =>#t357;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.expect
index b3bcf67..60fc7d3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_parameter_in_superclass_of_mixin_application.dart.weak.expect
@@ -55,7 +55,7 @@
     : super self::A::•()
     ;
   forwarding-stub method foo(covariant core::num* x) → void
-    return super.{self::A::foo}(x);
+    return super.{self::B::foo}(x);
 }
 class D extends self::_D&A&B implements self::C {
   synthetic constructor •() → self::D*
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
index d6ea288..43846a2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
@@ -676,3 +676,11 @@
   #C31 = self::AnotherEnum {index:#C9, _name:#C30}
   #C32 = <self::AnotherEnum*>[#C27, #C29, #C31]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///duplicated_declarations.dart:
+- Enum#1. (from org-dartlang-testcase:///duplicated_declarations.dart:83:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Enum. (from org-dartlang-testcase:///duplicated_declarations.dart:76:6)
+- AnotherEnum. (from org-dartlang-testcase:///duplicated_declarations.dart:89:6)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
index 01eb26d..a7b3c36 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
@@ -52,3 +52,9 @@
 static method bar() → dynamic {
   invalid-expression "This assertion failed.";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_01_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_01_lib1.dart:8:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
index 01eb26d..a7b3c36 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
@@ -52,3 +52,9 @@
 static method bar() → dynamic {
   invalid-expression "This assertion failed.";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_01_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_01_lib1.dart:8:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
index 323bb1d..6e25d1b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
@@ -76,3 +76,9 @@
 import "org-dartlang-testcase:///error_location_02_lib2.dart";
 
 static const field err::Foo* fooField2 = invalid-expression "This assertion failed.";
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_02_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_02_lib1.dart:8:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
index 323bb1d..6e25d1b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
@@ -76,3 +76,9 @@
 import "org-dartlang-testcase:///error_location_02_lib2.dart";
 
 static const field err::Foo* fooField2 = invalid-expression "This assertion failed.";
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_02_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_02_lib1.dart:8:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
index e0eca30..a391e0e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
@@ -77,3 +77,12 @@
 import "org-dartlang-testcase:///error_location_03_lib1.dart";
 
 static const field err::Foo* fooField2 = invalid-expression "This assertion failed.";
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_03_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_03_lib1.dart:8:9)
+
+org-dartlang-testcase:///error_location_03_lib3.dart:
+- Foo. (from org-dartlang-testcase:///error_location_03_lib1.dart:8:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
index e0eca30..a391e0e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
@@ -77,3 +77,12 @@
 import "org-dartlang-testcase:///error_location_03_lib1.dart";
 
 static const field err::Foo* fooField2 = invalid-expression "This assertion failed.";
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_03_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_03_lib1.dart:8:9)
+
+org-dartlang-testcase:///error_location_03_lib3.dart:
+- Foo. (from org-dartlang-testcase:///error_location_03_lib1.dart:8:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
index eaf451a..3da6aa1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
@@ -68,3 +68,9 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method bar() → dynamic {}
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_04_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_04_lib1.dart:8:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
index eaf451a..3da6aa1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
@@ -68,3 +68,9 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method bar() → dynamic {}
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///error_location_04_lib2.dart:
+- Foo. (from org-dartlang-testcase:///error_location_04_lib1.dart:8:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.expect
index 8dbe328..497ce03 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.expect
@@ -1,12 +1,15 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:developer" as dev;
 additionalExports = (core::print)
 
 import "dart:developer" show UserTag;
 export "dart:core" show print;
 
 static method main() → dynamic {
-  core::print(dev::UserTag*);
+  core::print(#C1);
+}
+
+constants  {
+  #C1 = TypeLiteralConstant(dev::UserTag*)
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.transformed.expect
index 405fb55..497ce03 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.transformed.expect
@@ -1,17 +1,15 @@
 library;
 import self as self;
 import "dart:core" as core;
-import "dart:developer" as dev;
 additionalExports = (core::print)
 
 import "dart:developer" show UserTag;
 export "dart:core" show print;
 
 static method main() → dynamic {
-  core::print(dev::UserTag*);
+  core::print(#C1);
 }
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///export_test.dart:16:9 -> TypeLiteralConstant(UserTag*)
-Extra constant evaluation: evaluated: 2, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(dev::UserTag*)
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.expect
index 9b072b2..8c295b6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.expect
@@ -72,9 +72,9 @@
   self::caller(({dynamic x = #C1}) → Null {
     core::print("<anon> was called with ${x}");
   });
-  core::print(core::int*.{core::Type::toString}());
-  core::print(core::int*);
-  core::print(let final core::Type* #t5 = core::int* in block {
+  core::print((#C3).{core::Type::toString}());
+  core::print(#C3);
+  core::print(let final core::Type* #t5 = #C3 in block {
     #t5.{core::Type::toString}();
   } =>#t5);
   try {
@@ -92,4 +92,10 @@
 constants  {
   #C1 = null
   #C2 = core::Object {}
+  #C3 = TypeLiteralConstant(core::int*)
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///expressions.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.transformed.expect
index e1c2ce2..b57f1a5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.transformed.expect
@@ -35,7 +35,7 @@
   }
   for (; false; ) {
   }
-  core::List<core::String*>* list = <core::String*>["Hello, World!"];
+  core::List<core::String*>* list = core::_GrowableList::_literal1<core::String*>("Hello, World!");
   core::print(list.{core::List::[]}(i));
   list.{core::List::[]=}(i, "Hello, Brave New World!");
   core::print(list.{core::List::[]}(i));
@@ -72,9 +72,9 @@
   self::caller(({dynamic x = #C1}) → Null {
     core::print("<anon> was called with ${x}");
   });
-  core::print(core::int*.{core::Type::toString}());
-  core::print(core::int*);
-  core::print(let final core::Type* #t5 = core::int* in block {
+  core::print((#C3).{core::Type::toString}());
+  core::print(#C3);
+  core::print(let final core::Type* #t5 = #C3 in block {
     #t5.{core::Type::toString}();
   } =>#t5);
   try {
@@ -92,13 +92,16 @@
 constants  {
   #C1 = null
   #C2 = core::Object {}
+  #C3 = TypeLiteralConstant(core::int*)
 }
 
 Extra constant evaluation status:
 Evaluated: StringConcatenation @ org-dartlang-testcase:///expressions.dart:23:8 -> StringConstant("foobar")
-Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:72:10 -> TypeLiteralConstant(int*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:73:9 -> TypeLiteralConstant(int*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:74:9 -> TypeLiteralConstant(int*)
 Evaluated: VariableGetImpl @ org-dartlang-testcase:///expressions.dart:74:9 -> TypeLiteralConstant(int*)
 Evaluated: VariableGet @ org-dartlang-testcase:///expressions.dart:74:9 -> TypeLiteralConstant(int*)
-Extra constant evaluation: evaluated: 138, effectively constant: 6
+Extra constant evaluation: evaluated: 135, effectively constant: 3
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///expressions.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.expect
index 8379e80..ae59d80 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.expect
@@ -15,3 +15,8 @@
   #C5 = "dart-ext:/usr/local/somewhere"
   #C6 = _in::ExternalName {name:#C5}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///external_import.dart:
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.transformed.expect
index 8379e80..ae59d80 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/external_import.dart.weak.transformed.expect
@@ -15,3 +15,8 @@
   #C5 = "dart-ext:/usr/local/somewhere"
   #C6 = _in::ExternalName {name:#C5}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///external_import.dart:
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart
index 97b91dd..a424674 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart
@@ -20,8 +20,9 @@
 
   Pointer<Coordinate> next;
 
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
-    return allocate<Coordinate>().ref
+  factory Coordinate.allocate( 
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {
+    return allocator<Coordinate>().ref
       ..x = x
       ..y = y
       ..next = next;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.strong.transformed.expect
index 241578e..387fd15 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
   @#C3
   static final field core::int* #sizeOf = (#C6).{core::List::[]}(ffi::_abi());
   @#C3
-  constructor #fromPointer(dynamic #pointer) → dynamic
+  constructor #fromTypedDataBase(dynamic #pointer) → dynamic
     : super ffi::Struct::_fromPointer(#pointer)
     ;
   static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.textual_outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.textual_outline.expect
index e4af729..299f784 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.textual_outline.expect
@@ -8,7 +8,8 @@
   @Double()
   double y;
   Pointer<Coordinate> next;
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {}
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {}
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.textual_outline_modelled.expect
index a7af7c2..2f99722 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.textual_outline_modelled.expect
@@ -8,7 +8,8 @@
   double x;
   @Double()
   double y;
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {}
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {}
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.expect
index a853421..3d65f9e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.expect
@@ -2,7 +2,6 @@
 import self as self;
 import "dart:ffi" as ffi;
 import "dart:core" as core;
-import "package:ffi/src/allocation.dart" as all;
 
 import "dart:ffi";
 import "package:ffi/ffi.dart";
@@ -13,8 +12,8 @@
   @#C1
   field core::double* y = null;
   field ffi::Pointer<self::Coordinate*>* next = null;
-  static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
-    return let final self::Coordinate* #t1 = ffi::StructPointer|get#ref<self::Coordinate*>(all::allocate<self::Coordinate*>()) in block {
+  static factory allocate(ffi::Allocator* allocator, core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
+    return let final self::Coordinate* #t1 = ffi::StructPointer|get#ref<self::Coordinate*>(ffi::AllocatorAlloc|call<self::Coordinate*>(allocator)) in block {
       #t1.{self::Coordinate::x} = x;
       #t1.{self::Coordinate::y} = y;
       #t1.{self::Coordinate::next} = next;
@@ -37,3 +36,8 @@
 constants  {
   #C1 = ffi::Double {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///ffi_sample.dart:
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect
index 324ae5f..c53e92f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect
@@ -1,8 +1,12 @@
+//
+// Problems outside component:
+//
+// third_party/pkg/ffi/lib/src/allocation.dart: Info: Support for using non-constant type arguments 'T' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type.
+//
 library;
 import self as self;
 import "dart:core" as core;
 import "dart:ffi" as ffi;
-import "package:ffi/src/allocation.dart" as all;
 
 import "dart:ffi";
 import "package:ffi/ffi.dart";
@@ -13,11 +17,11 @@
   @#C3
   static final field core::int* #sizeOf = (#C11).{core::List::[]}(ffi::_abi());
   @#C3
-  constructor #fromPointer(dynamic #pointer) → dynamic
+  constructor #fromTypedDataBase(dynamic #pointer) → dynamic
     : super ffi::Struct::_fromPointer(#pointer)
     ;
-  static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
-    return let final self::Coordinate* #t1 = ffi::StructPointer|get#ref<self::Coordinate*>(all::allocate<self::Coordinate*>()) in block {
+  static factory allocate(ffi::Allocator* allocator, core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
+    return let final self::Coordinate* #t1 = ffi::StructPointer|get#ref<self::Coordinate*>(ffi::AllocatorAlloc|call<self::Coordinate*>(allocator)) in block {
       #t1.{self::Coordinate::x} = x;
       #t1.{self::Coordinate::y} = y;
       #t1.{self::Coordinate::next} = next;
@@ -68,3 +72,8 @@
   #C16 = 16
   #C17 = <core::int*>[#C16, #C16, #C16]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///ffi_sample.dart:
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.transformed.expect
index 7eb73d5..2f1d77e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.transformed.expect
@@ -98,7 +98,7 @@
     core::String* local;
     dynamic untypedLocal;
     {
-      core::Iterator<core::String*>* :sync-for-iterator = <core::String*>[].{core::Iterable::iterator};
+      core::Iterator<core::String*>* :sync-for-iterator = core::_GrowableList::•<core::String*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::String* #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -107,7 +107,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -116,7 +116,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -125,7 +125,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -134,7 +134,7 @@
       }
     }
     {
-      core::Iterator<core::double*>* :sync-for-iterator = <core::double*>[].{core::Iterable::iterator};
+      core::Iterator<core::double*>* :sync-for-iterator = core::_GrowableList::•<core::double*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::double* #t5 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -143,7 +143,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -152,7 +152,7 @@
       }
     }
     {
-      core::Iterator<core::bool*>* :sync-for-iterator = <core::bool*>[].{core::Iterable::iterator};
+      core::Iterator<core::bool*>* :sync-for-iterator = core::_GrowableList::•<core::bool*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::bool* #t7 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -161,7 +161,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t8 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -170,7 +170,7 @@
       }
     }
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t9 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -179,7 +179,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t10 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -189,7 +189,7 @@
     }
     self::C* c = new self::C::•();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::int* #t11 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -198,7 +198,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t12 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -207,7 +207,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t13 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -220,7 +220,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t14 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -233,7 +233,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t15 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -250,7 +250,7 @@
     for (main() in []) {}
          ^^^^";
       {
-        core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+        core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final dynamic #t16 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -267,7 +267,7 @@
     for (var x, y in <int>[]) {
          ^^^";
       {
-        core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+        core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
         for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
           final core::int* #t17 = :sync-for-iterator.{core::Iterator::current};
           {
@@ -283,7 +283,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t18 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/if_null_in_list_literal.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/if_null_in_list_literal.dart.weak.transformed.expect
index 0cc41e9..188b5b3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/if_null_in_list_literal.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/if_null_in_list_literal.dart.weak.transformed.expect
@@ -5,5 +5,5 @@
 static method main() → dynamic {
   core::Object* a;
   core::Object* b;
-  return <core::Object*>[let final core::Object* #t1 = a in #t1.{core::Object::==}(null) ?{core::Object*} b : #t1];
+  return core::_GrowableList::_literal1<core::Object*>(let final core::Object* #t1 = a in #t1.{core::Object::==}(null) ?{core::Object*} b : #t1);
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_new.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_new.dart.weak.transformed.expect
index d5261cc..ecfe40c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_new.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_new.dart.weak.transformed.expect
@@ -86,8 +86,8 @@
   self::f(new self::Foo::•());
   self::f(new self::Bar::named());
   self::f(new self::Bar::named());
-  core::List<core::Object*>* l = <core::Object*>[new self::Foo::•(), new self::Bar::named()];
-  l = <core::Object*>[new self::Foo::•(), new self::Bar::named()];
+  core::List<core::Object*>* l = core::_GrowableList::_literal2<core::Object*>(new self::Foo::•(), new self::Bar::named());
+  l = core::_GrowableList::_literal2<core::Object*>(new self::Foo::•(), new self::Bar::named());
   core::Map<core::String*, core::Object*>* m = <core::String*, core::Object*>{"foo": new self::Foo::•(), "bar": new self::Bar::named()};
   m = <core::String*, core::Object*>{"foo": new self::Foo::•(), "bar": new self::Bar::named()};
   self::IndexTester* i = new self::IndexTester::•();
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart.weak.expect
index 66b58bc..ca5af00 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart.weak.expect
@@ -65,7 +65,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::fact2];
+  static final field dynamic _redirecting# = <dynamic>[self::C::fact2];
   constructor •() → self::C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart.weak.transformed.expect
index 4b8fb16..214f497 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart.weak.transformed.expect
@@ -65,7 +65,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::fact2];
+  static final field dynamic _redirecting# = <dynamic>[self::C::fact2];
   constructor •() → self::C*
     : super core::Object::•()
     ;
@@ -104,7 +104,7 @@
  - 'Object' is from 'dart:core'.
 Change the type of the list literal or the context in which it is used.
   List<int> a = <Object>[];
-                        ^" in <core::Object*>[];
+                        ^" in core::_GrowableList::•<core::Object*>(0);
   core::Map<core::int*, core::String*>* b = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invalid_cast.dart:23:40: Error: The map literal type 'Map<Object, String>' isn't of expected type 'Map<int, String>'.
  - 'Map' is from 'dart:core'.
  - 'Object' is from 'dart:core'.
@@ -154,7 +154,7 @@
 }
 static method ok() → dynamic {
   function localFunction(core::int* i) → void {}
-  core::List<core::int*>* a = <core::int*>[];
+  core::List<core::int*>* a = core::_GrowableList::•<core::int*>(0);
   core::Map<core::int*, core::String*>* b = <core::int*, core::String*>{};
   core::Map<core::int*, core::String*>* c = <core::int*, core::String*>{};
   (core::int*) →* core::int* d = (core::int* i) → core::int* => i;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart.weak.expect
index 3566c3d..6c22e73 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart.weak.expect
@@ -59,11 +59,11 @@
       print(\"Hello, World!\") +
       ^" in core::print("Hello, World!")).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:16:7: Error: Method not found: 'z'.
       z(\"Hello, World!\") +
-      ^" as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:17:7: Error: Getter not found: 'z'.
+      ^" as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:17:7: Error: Getter not found: 'z'.
       z.print(\"Hello, World!\") +
-      ^".print("Hello, World!") as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:18:7: Error: Getter not found: 'y'.
+      ^".print("Hello, World!") as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:18:7: Error: Getter not found: 'y'.
       y.z.print(\"Hello, World!\") +
-      ^".z.print("Hello, World!") as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:19:7: Error: Getter not found: 'x'.
+      ^".z.print("Hello, World!") as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:19:7: Error: Getter not found: 'x'.
       x.y.z.print(\"Hello, World!\");
-      ^".y.z.print("Hello, World!") as{TypeError,ForDynamic} core::num);
+      ^".y.z.print("Hello, World!") as{TypeError,ForDynamic} core::num*);
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart.weak.transformed.expect
index 6643440..93219c5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart.weak.transformed.expect
@@ -61,9 +61,9 @@
       z(\"Hello, World!\") +
       ^").{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:17:7: Error: Getter not found: 'z'.
       z.print(\"Hello, World!\") +
-      ^".print("Hello, World!") as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:18:7: Error: Getter not found: 'y'.
+      ^".print("Hello, World!") as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:18:7: Error: Getter not found: 'y'.
       y.z.print(\"Hello, World!\") +
-      ^".z.print("Hello, World!") as{TypeError,ForDynamic} core::num).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:19:7: Error: Getter not found: 'x'.
+      ^".z.print("Hello, World!") as{TypeError,ForDynamic} core::num*).{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/invocations.dart:19:7: Error: Getter not found: 'x'.
       x.y.z.print(\"Hello, World!\");
-      ^".y.z.print("Hello, World!") as{TypeError,ForDynamic} core::num);
+      ^".y.z.print("Hello, World!") as{TypeError,ForDynamic} core::num*);
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue39344.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue39344.dart.weak.transformed.expect
index 7874ca5..b28b175 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue39344.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue39344.dart.weak.transformed.expect
@@ -43,7 +43,7 @@
     ;
   method method1a(generic-covariant-impl self::Class::T* t) → void {
     if(t is self::B*) {
-      core::List<self::Class::T*>* ys = <self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}];
+      core::List<self::Class::T*>* ys = core::_GrowableList::_literal1<self::Class::T*>(t{self::Class::T* & self::B* /* '*' & '*' = '*' */});
       self::xs = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/issue39344.dart:21:12: Error: A value of type 'List<T>' can't be assigned to a variable of type 'List<B>'.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/issue39344.dart'.
@@ -53,7 +53,7 @@
   }
   method method1b(generic-covariant-impl self::Class::T* t) → void {
     if(t is self::B*) {
-      core::List<core::List<self::Class::T*>*>* yss = <core::List<self::Class::T*>*>[<self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}]];
+      core::List<core::List<self::Class::T*>*>* yss = core::_GrowableList::_literal1<core::List<self::Class::T*>*>(core::_GrowableList::_literal1<self::Class::T*>(t{self::Class::T* & self::B* /* '*' & '*' = '*' */}));
       self::xss = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/issue39344.dart:33:13: Error: A value of type 'List<List<T>>' can't be assigned to a variable of type 'List<List<B>>'.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/issue39344.dart'.
@@ -64,7 +64,7 @@
   method method2a(generic-covariant-impl self::Class::T* t) → void {
     dynamic alias;
     if(t is self::B*) {
-      core::List<self::Class::T*>* ys = <self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}];
+      core::List<self::Class::T*>* ys = core::_GrowableList::_literal1<self::Class::T*>(t{self::Class::T* & self::B* /* '*' & '*' = '*' */});
       alias = ys;
       self::xs = alias as{TypeError,ForDynamic} core::List<self::B*>*;
     }
@@ -72,7 +72,7 @@
   method method2b(generic-covariant-impl self::Class::T* t) → void {
     dynamic alias;
     if(t is self::B*) {
-      core::List<core::List<self::Class::T*>*>* yss = <core::List<self::Class::T*>*>[<self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}]];
+      core::List<core::List<self::Class::T*>*>* yss = core::_GrowableList::_literal1<core::List<self::Class::T*>*>(core::_GrowableList::_literal1<self::Class::T*>(t{self::Class::T* & self::B* /* '*' & '*' = '*' */}));
       alias = yss;
       self::xss = alias as{TypeError,ForDynamic} core::List<core::List<self::B*>*>*;
     }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/literals.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/literals.dart.weak.transformed.expect
index 8ef3e48..ae7c90f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/literals.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/literals.dart.weak.transformed.expect
@@ -19,8 +19,8 @@
   core::print(null);
 }
 static method testList() → dynamic {
-  core::print(<dynamic>[]);
-  core::print(<core::String*>["a", "b"]);
+  core::print(core::_GrowableList::•<dynamic>(0));
+  core::print(core::_GrowableList::_literal2<core::String*>("a", "b"));
 }
 static method testMap() → dynamic {
   core::print(<dynamic, dynamic>{});
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/local_generic_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/local_generic_function.dart.weak.transformed.expect
index 487fec1..328d4cc 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/local_generic_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/local_generic_function.dart.weak.transformed.expect
@@ -5,5 +5,5 @@
 static method main() → dynamic {
   function f<T extends core::Object* = dynamic>(core::List<T*>* l) → T*
     return l.{core::List::[]}(0);
-  core::int* x = f.call<core::int*>(<core::int*>[0]);
+  core::int* x = f.call<core::int*>(core::_GrowableList::_literal1<core::int*>(0));
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.expect
index ce8e878..6d8e8308 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.expect
@@ -69,3 +69,9 @@
 constants  {
   #C1 = self::Constant {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///magic_const.dart:
+- Constant. (from org-dartlang-testcase:///magic_const.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
index ab4a00c..160e248 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
@@ -73,3 +73,9 @@
 Extra constant evaluation status:
 Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///magic_const.dart:23:8 -> BoolConstant(false)
 Extra constant evaluation: evaluated: 2, effectively constant: 1
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///magic_const.dart:
+- Constant. (from org-dartlang-testcase:///magic_const.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
index b5f94c3..f409662 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
@@ -41,3 +41,9 @@
   #C10 = self::E {index:#C8, _name:#C9}
   #C11 = <self::E*>[#C4, #C7, #C10]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///metadata_enum.dart:
+- E. (from org-dartlang-testcase:///metadata_enum.dart:10:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
index b5f94c3..f409662 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
@@ -41,3 +41,9 @@
   #C10 = self::E {index:#C8, _name:#C9}
   #C11 = <self::E*>[#C4, #C7, #C10]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///metadata_enum.dart:
+- E. (from org-dartlang-testcase:///metadata_enum.dart:10:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/micro.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/micro.dart.weak.transformed.expect
index 74e0279..30a9c46 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/micro.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/micro.dart.weak.transformed.expect
@@ -146,6 +146,6 @@
   dynamic c = subBox.{self::FinalBox::finalField};
   self::makeDynamicCall(new self::DynamicReceiver1::•());
   self::makeDynamicCall(new self::DynamicReceiver2::•());
-  core::List<core::String*>* list = <core::String*>["string"];
+  core::List<core::String*>* list = core::_GrowableList::_literal1<core::String*>("string");
   core::String* d = list.{core::List::[]}(0);
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
index 2851dfc..1f1f19e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
@@ -6,6 +6,8 @@
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M1::m}();
   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
@@ -21,6 +23,8 @@
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M2::m}();
 }
 class B extends self::_B&Object&M1&M2 {
   constructor •(dynamic value) → self::B*
@@ -65,6 +69,8 @@
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M1::m}();
   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
@@ -80,6 +86,8 @@
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M2::m}();
 }
 class C extends self::_C&Object&M1&M2 {
   constructor •(dynamic value) → self::C*
@@ -107,6 +115,8 @@
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::G1::m}();
   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
@@ -124,9 +134,9 @@
     ;
 }
 static method main() → dynamic {
-  new self::B::•(null).{self::M2::m}();
-  new self::C::•(null).{self::M2::m}();
-  new self::D::•<dynamic>().{self::G1::m}();
-  new self::D::•<core::int*>().{self::G1::m}();
-  new self::D::•<core::List<core::int*>*>().{self::G1::m}();
+  new self::B::•(null).{self::_B&Object&M1&M2::m}();
+  new self::C::•(null).{self::_C&Object&M1&M2::m}();
+  new self::D::•<dynamic>().{self::_D&Object&G1::m}();
+  new self::D::•<core::int*>().{self::_D&Object&G1::m}();
+  new self::D::•<core::List<core::int*>*>().{self::_D&Object&G1::m}();
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
index 0ddd631..a6c21d2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
@@ -6,6 +6,8 @@
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
+  method m() → dynamic
+    return core::print("M1");
   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
@@ -16,8 +18,6 @@
   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
-  method m() → dynamic
-    return core::print("M1");
 }
 abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
@@ -79,6 +79,8 @@
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
+  method m() → dynamic
+    return core::print("M1");
   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
@@ -89,8 +91,6 @@
   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
-  method m() → dynamic
-    return core::print("M1");
 }
 abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
@@ -135,6 +135,8 @@
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
+  method m() → dynamic
+    return core::print(self::_D&Object&G1::S*);
   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
@@ -145,8 +147,6 @@
   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
-  method m() → dynamic
-    return core::print(self::_D&Object&G1::S*);
 }
 class D<S extends core::Object* = dynamic> extends self::_D&Object&G1<self::D::S*> {
   synthetic constructor •() → self::D<self::D::S*>*
@@ -154,9 +154,9 @@
     ;
 }
 static method main() → dynamic {
-  new self::B::•(null).{self::M2::m}();
-  new self::C::•(null).{self::M2::m}();
-  new self::D::•<dynamic>().{self::G1::m}();
-  new self::D::•<core::int*>().{self::G1::m}();
-  new self::D::•<core::List<core::int*>*>().{self::G1::m}();
+  new self::B::•(null).{self::_B&Object&M1&M2::m}();
+  new self::C::•(null).{self::_C&Object&M1&M2::m}();
+  new self::D::•<dynamic>().{self::_D&Object&G1::m}();
+  new self::D::•<core::int*>().{self::_D&Object&G1::m}();
+  new self::D::•<core::List<core::int*>*>().{self::_D&Object&G1::m}();
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.weak.expect
index 67c9729..9bddb8c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_application_override.dart.weak.expect
@@ -206,7 +206,8 @@
   synthetic constructor •() → self::A0*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A1&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A1&S&M1*
@@ -217,7 +218,8 @@
   synthetic constructor •() → self::A1*
     : super self::_A1&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A2&S&M1 = self::S with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A2&S&M1*
@@ -233,13 +235,15 @@
   synthetic constructor •() → self::A2*
     : super self::_A2&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _A0X&S&M = self::S with self::M /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A0X = self::_A0X&S&M with self::MX {
   synthetic constructor •() → self::A0X*
@@ -255,7 +259,8 @@
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A1X = self::_A1X&S&M1&M with self::MX {
   synthetic constructor •() → self::A1X*
@@ -276,7 +281,8 @@
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class A2X = self::_A2X&S&M1&M2&M with self::MX {
   synthetic constructor •() → self::A2X*
@@ -287,7 +293,8 @@
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B0 extends self::_B0&S&M {
   synthetic constructor •() → self::B0*
@@ -303,7 +310,8 @@
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B1 extends self::_B1&S&M1&M {
   synthetic constructor •() → self::B1*
@@ -324,7 +332,8 @@
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 class B2 extends self::_B2&S&M1&M2&M {
   synthetic constructor •() → self::B2*
@@ -335,7 +344,8 @@
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B0X&S&M&MX*
@@ -356,7 +366,8 @@
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
@@ -382,7 +393,8 @@
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
-  abstract member-signature method foo([dynamic x = #C1]) → dynamic; -> self::S::foo
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
 }
 abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
index 7d4f4df..dc46359 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
@@ -53,6 +53,8 @@
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
   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
@@ -68,6 +70,8 @@
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::M::foo}();
   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
@@ -104,6 +108,8 @@
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -119,6 +125,8 @@
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -134,6 +142,8 @@
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
@@ -154,6 +164,8 @@
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
+  mixin-super-stub method bar() → dynamic
+    return super.{self::M2::bar}();
   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
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
index 302eded..ad31c58 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
@@ -53,6 +53,7 @@
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
+  method foo() → dynamic {}
   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
@@ -63,12 +64,12 @@
   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
-  method foo() → dynamic {}
 }
 abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
+  method foo() → dynamic {}
   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
@@ -79,7 +80,6 @@
   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
-  method foo() → dynamic {}
 }
 class C extends self::_C&Object&N {
   synthetic constructor •() → self::C*
@@ -106,6 +106,7 @@
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
+  method bar() → dynamic {}
   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
@@ -116,12 +117,12 @@
   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
-  method bar() → dynamic {}
 }
 abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
+  method bar() → dynamic {}
   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
@@ -132,12 +133,12 @@
   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
-  method bar() → dynamic {}
 }
 abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
+  method bar() → dynamic {}
   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
@@ -148,7 +149,6 @@
   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
-  method bar() → dynamic {}
 }
 class C2 extends self::_C2&Object&M2 {
   synthetic constructor •() → self::C2*
@@ -159,6 +159,7 @@
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
+  method bar() → dynamic {}
   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
@@ -169,7 +170,6 @@
   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
-  method bar() → dynamic {}
 }
 abstract class C3 extends self::_C3&Object&M2 {
   synthetic constructor •() → self::C3*
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.expect
index a06cb3c..5465909 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.expect
@@ -45,6 +45,12 @@
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
+  mixin-super-stub get _field() → self::B*
+    return super.{self::C::_field};
+  mixin-super-stub set _field(generic-covariant-impl self::B* value) → void
+    return super.{self::C::_field} = value;
+  mixin-super-stub method foo(generic-covariant-impl self::B* x) → dynamic
+    return super.{self::C::foo}(x);
   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
@@ -68,5 +74,5 @@
 }
 static method main() → dynamic {
   self::Foo* foo = new self::Foo::•();
-  foo.{self::C::foo}(new self::B::•());
+  foo.{self::_Foo&Object&C::foo}(new self::B::•());
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.transformed.expect
index 86683a1..9828c0d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_inherited_setter_for_mixed_in_field.dart.weak.transformed.expect
@@ -46,6 +46,9 @@
   synthetic constructor •() → self::_Foo&Object&C*
     : super core::Object::•()
     ;
+  method foo(generic-covariant-impl self::B* x) → dynamic {
+    this.{self::C::_field} = x;
+  }
   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
@@ -56,9 +59,6 @@
   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
-  method foo(generic-covariant-impl self::B* x) → dynamic {
-    this.{self::C::_field} = x;
-  }
 }
 class Foo extends self::_Foo&Object&C {
   synthetic constructor •() → self::Foo*
@@ -72,5 +72,5 @@
 }
 static method main() → dynamic {
   self::Foo* foo = new self::Foo::•();
-  foo.{self::C::foo}(new self::B::•());
+  foo.{self::_Foo&Object&C::foo}(new self::B::•());
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.expect
index 2dfa48d..e9d4ae3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.expect
@@ -47,25 +47,37 @@
   synthetic constructor •() → self::_Named&S&M*
     : super self::S::•()
     ;
+  mixin-super-stub get m() → dynamic
+    return super.{self::M::m};
+  mixin-super-stub set m(dynamic value) → void
+    return super.{self::M::m} = value;
 }
 abstract class _Named&S&M&N = self::_Named&S&M with self::N /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
+  mixin-super-stub get superM() → dynamic
+    return super.{self::N::superM};
+  mixin-super-stub set superM(dynamic value) → void
+    return super.{self::N::superM} = value;
 }
 class Named = self::_Named&S&M&N with self::M {
   synthetic constructor •() → self::Named*
     : super self::_Named&S&M&N::•()
     ;
+  mixin-super-stub get m() → dynamic
+    return super.{self::M::m};
+  mixin-super-stub set m(dynamic value) → void
+    return super.{self::M::m} = value;
 }
 static method main() → dynamic {
   self::Named* named = new self::Named::•();
-  named.{self::M::m} = 42;
-  named.{self::N::superM} = 87;
-  if(!named.{self::M::m}.{core::Object::==}(42)) {
+  named.{self::Named::m} = 42;
+  named.{self::_Named&S&M&N::superM} = 87;
+  if(!named.{self::Named::m}.{core::Object::==}(42)) {
     throw "Bad mixin translation of set:superM";
   }
-  if(!named.{self::N::superM}.{core::Object::==}(87)) {
+  if(!named.{self::_Named&S&M&N::superM}.{core::Object::==}(87)) {
     throw "Bad mixin translation of get:superM";
   }
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.transformed.expect
index 2d6e534..94ee731 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_super_repeated.dart.weak.transformed.expect
@@ -63,11 +63,11 @@
   synthetic constructor •() → self::_Named&S&M&N*
     : super self::_Named&S&M::•()
     ;
+  get superM() → dynamic
+    return super.{self::M::m};
   set superM(dynamic value) → void {
     super.{self::M::m} = value;
   }
-  get superM() → dynamic
-    return super.{self::M::m};
 }
 class Named extends self::_Named&S&M&N implements self::M /*isEliminatedMixin*/  {
   field dynamic m = null;
@@ -87,12 +87,12 @@
 }
 static method main() → dynamic {
   self::Named* named = new self::Named::•();
-  named.{self::M::m} = 42;
-  named.{self::N::superM} = 87;
-  if(!named.{self::M::m}.{core::Object::==}(42)) {
+  named.{self::Named::m} = 42;
+  named.{self::_Named&S&M&N::superM} = 87;
+  if(!named.{self::Named::m}.{core::Object::==}(42)) {
     throw "Bad mixin translation of set:superM";
   }
-  if(!named.{self::N::superM}.{core::Object::==}(87)) {
+  if(!named.{self::_Named&S&M&N::superM}.{core::Object::==}(87)) {
     throw "Bad mixin translation of get:superM";
   }
 }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/no_such_method_private_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/no_such_method_private_setter.dart.weak.transformed.expect
index ddb32d6..3e79735 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/no_such_method_private_setter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/no_such_method_private_setter.dart.weak.transformed.expect
@@ -22,7 +22,7 @@
   no-such-method-forwarder get /* from org-dartlang-testcase:///no_such_method_private_setter_lib.dart */ _x() → core::int*
     return this.{self::Foo::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set /* from org-dartlang-testcase:///no_such_method_private_setter_lib.dart */ _x(core::int* value) → void
-    return this.{self::Foo::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Foo::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {
   no_::baz(new self::Foo::•());
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.weak.transformed.expect
index e5e1b00..485db8b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/null_aware_spread.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 
 static method nullAwareListSpread(core::List<core::String*>* list) → dynamic {
   list = block {
-    final core::List<core::String*>* #t1 = <core::String*>["foo"];
+    final core::List<core::String*>* #t1 = core::_GrowableList::_literal1<core::String*>("foo");
     final core::Iterable<core::String*>* #t2 = list;
     if(!#t2.{core::Object::==}(null))
       #t1.{core::List::addAll}{Invariant}(#t2);
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.transformed.expect
index 715890e..fb71500 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.transformed.expect
@@ -318,7 +318,7 @@
 Try correcting the operator to an existing operator, or defining a 'unary-' operator.
   print(-foo);
         ^");
-  core::print(<invalid-type>[]);
+  core::print(core::_GrowableList::•<invalid-type>(0));
   core::print(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:39:9: Error: This couldn't be parsed.
   print(>foo);
         ^".>(foo));
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.expect
index 4965963..ec198b7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.expect
@@ -49,6 +49,8 @@
   synthetic constructor •() → self::_WithMixin&Supertype&Mixin*
     : super lib::Supertype::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{lib::Mixin::foo}();
 }
 class WithMixin extends self::_WithMixin&Supertype&Mixin {
   synthetic constructor •() → self::WithMixin*
@@ -71,7 +73,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C<T extends core::Object* = dynamic> extends core::Object { // from org-dartlang-testcase:///qualified_part.dart
-  static field dynamic _redirecting# = <dynamic>[self::C::b];
+  static final field dynamic _redirecting# = <dynamic>[self::C::b];
   constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
@@ -99,7 +101,7 @@
   new lib::C::a<core::String*>();
   new lib::C::a<core::String*>();
   new self::WithMixin::•().{lib::Supertype::supertypeMethod}();
-  new self::WithMixin::•().{lib::Mixin::foo}();
+  new self::WithMixin::•().{self::_WithMixin&Supertype&Mixin::foo}();
   new self::IllegalSupertype::•();
 }
 
@@ -112,7 +114,7 @@
 
 typedef VoidFunction = () →* void;
 class C<T extends core::Object* = dynamic> extends self::C<lib::C::T*> {
-  static field dynamic _redirecting# = <dynamic>[lib::C::b];
+  static final field dynamic _redirecting# = <dynamic>[lib::C::b];
   constructor •() → lib::C<lib::C::T*>*
     : super self::C::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.transformed.expect
index f02b9cc..9998bef 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/qualified.dart.weak.transformed.expect
@@ -84,7 +84,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C<T extends core::Object* = dynamic> extends core::Object { // from org-dartlang-testcase:///qualified_part.dart
-  static field dynamic _redirecting# = <dynamic>[self::C::b];
+  static final field dynamic _redirecting# = <dynamic>[self::C::b];
   constructor •() → self::C<self::C::T*>*
     : super core::Object::•()
     ;
@@ -112,7 +112,7 @@
   new lib::C::a<core::String*>();
   new lib::C::a<core::String*>();
   new self::WithMixin::•().{lib::Supertype::supertypeMethod}();
-  new self::WithMixin::•().{lib::Mixin::foo}();
+  new self::WithMixin::•().{self::_WithMixin&Supertype&Mixin::foo}();
   new self::IllegalSupertype::•();
 }
 
@@ -125,7 +125,7 @@
 
 typedef VoidFunction = () →* void;
 class C<T extends core::Object* = dynamic> extends self::C<lib::C::T*> {
-  static field dynamic _redirecting# = <dynamic>[lib::C::b];
+  static final field dynamic _redirecting# = <dynamic>[lib::C::b];
   constructor •() → lib::C<lib::C::T*>*
     : super self::C::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_constructor.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_constructor.dart.weak.expect
index 43520af..7443e13 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_constructor.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_constructor.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::fisk];
+  static final field dynamic _redirecting# = <dynamic>[self::A::fisk];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_constructor.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_constructor.dart.weak.transformed.expect
index ff02ffa..0ed4fed 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_constructor.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_constructor.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::fisk];
+  static final field dynamic _redirecting# = <dynamic>[self::A::fisk];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.expect
index 42cc2c5..7a6504b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.expect
@@ -12,7 +12,7 @@
 import "dart:core" as core;
 
 abstract class FooBase<Tf extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::FooBase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::FooBase::•];
   abstract get x() → core::int*;
   static factory •<Tf extends core::Object* = dynamic>(core::int* x) → self::FooBase<self::FooBase::•::Tf*>*
     let dynamic #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf* #typeArg0 = null in invalid-expression;
@@ -28,7 +28,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class Foo<T extends core::Object* = dynamic> extends core::Object implements self::FooBase<dynamic> {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   static factory •<T extends core::Object* = dynamic>(core::int* x) → self::Foo<self::Foo::•::T*>*
     let dynamic #redirecting_factory = self::Bar::• in let core::String* #typeArg0 = null in let self::Foo::•::T* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -78,7 +78,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCase<A extends core::Object* = dynamic, B extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
   static factory •<A extends core::Object* = dynamic, B extends core::Object* = dynamic>() → self::SimpleCase<self::SimpleCase::•::A*, self::SimpleCase::•::B*>*
     let dynamic #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A* #typeArg0 = null in let self::SimpleCase::•::B* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -93,7 +93,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCaseImpl<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai*, self::SimpleCaseImpl::Bi*> {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
   static factory •<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() → self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai*, self::SimpleCaseImpl::•::Bi*>*
     let dynamic #redirecting_factory = self::SimpleCaseImpl2::• in let self::SimpleCaseImpl::•::Ai* #typeArg0 = null in let self::SimpleCaseImpl::•::Bi* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.transformed.expect
index c4ed837..a63abfb 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 import "dart:core" as core;
 
 abstract class FooBase<Tf extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::FooBase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::FooBase::•];
   abstract get x() → core::int*;
   static factory •<Tf extends core::Object* = dynamic>(core::int* x) → self::FooBase<self::FooBase::•::Tf*>*
     let <T extends core::Object* = dynamic>(core::int*) →* self::Foo<T*>* #redirecting_factory = self::Foo::• in let self::FooBase::•::Tf* #typeArg0 = null in invalid-expression;
@@ -28,7 +28,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class Foo<T extends core::Object* = dynamic> extends core::Object implements self::FooBase<dynamic> {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   static factory •<T extends core::Object* = dynamic>(core::int* x) → self::Foo<self::Foo::•::T*>*
     let<BottomType> #redirecting_factory = self::Bar::• in let core::String* #typeArg0 = null in let self::Foo::•::T* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -78,7 +78,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCase<A extends core::Object* = dynamic, B extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCase::•];
   static factory •<A extends core::Object* = dynamic, B extends core::Object* = dynamic>() → self::SimpleCase<self::SimpleCase::•::A*, self::SimpleCase::•::B*>*
     let <Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() →* self::SimpleCaseImpl<Ai*, Bi*>* #redirecting_factory = self::SimpleCaseImpl::• in let self::SimpleCase::•::A* #typeArg0 = null in let self::SimpleCase::•::B* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -93,7 +93,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class SimpleCaseImpl<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic> extends core::Object implements self::SimpleCase<self::SimpleCaseImpl::Ai*, self::SimpleCaseImpl::Bi*> {
-  static field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
+  static final field dynamic _redirecting# = <dynamic>[self::SimpleCaseImpl::•];
   static factory •<Ai extends core::Object* = dynamic, Bi extends core::Object* = dynamic>() → self::SimpleCaseImpl<self::SimpleCaseImpl::•::Ai*, self::SimpleCaseImpl::•::Bi*>*
     let<BottomType> #redirecting_factory = self::SimpleCaseImpl2::• in let self::SimpleCaseImpl::•::Ai* #typeArg0 = null in let self::SimpleCaseImpl::•::Bi* #typeArg1 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_chain_test.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_chain_test.dart.weak.expect
index e3f106c..88615ec 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_chain_test.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_chain_test.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
+  static final field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_chain_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_chain_test.dart.weak.transformed.expect
index 03c3664..cab046f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_chain_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_chain_test.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
+  static final field dynamic _redirecting# = <dynamic>[self::A::first, self::A::second];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.expect
index 27deb54..86194ea 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class _X<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::_X::•];
+  static final field dynamic _redirecting# = <dynamic>[self::_X::•];
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let dynamic #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -63,3 +63,9 @@
 constants  {
   #C1 = self::_Y<Null> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_factory_const_inference.dart:
+- _Y. (from org-dartlang-testcase:///redirecting_factory_const_inference.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.transformed.expect
index 4b6b1c0..2027839 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_const_inference.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class _X<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::_X::•];
+  static final field dynamic _redirecting# = <dynamic>[self::_X::•];
   static factory •<T extends core::Object* = dynamic>() → self::_X<self::_X::•::T*>*
     let<BottomType> #redirecting_factory = self::_Y::• in let self::_X::•::T* #typeArg0 = null in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -63,3 +63,9 @@
 constants  {
   #C1 = self::_Y<Null> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirecting_factory_const_inference.dart:
+- _Y. (from org-dartlang-testcase:///redirecting_factory_const_inference.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_metadata.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_metadata.dart.weak.expect
index 0426b6e..5da2827 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_metadata.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_metadata.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   constructor named(dynamic p) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_metadata.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_metadata.dart.weak.transformed.expect
index bcd4eae..4dc094e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_metadata.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_metadata.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Foo::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Foo::•];
   constructor named(dynamic p) → self::Foo*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_simple_test.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_simple_test.dart.weak.expect
index 524f4b5..de93fd8 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_simple_test.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_simple_test.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_simple_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_simple_test.dart.weak.transformed.expect
index 2220b80..5aec6a3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_simple_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_simple_test.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeargs_test.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeargs_test.dart.weak.expect
index 017afcf..9ada94b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeargs_test.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeargs_test.dart.weak.expect
@@ -23,7 +23,7 @@
     ;
 }
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeargs_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeargs_test.dart.weak.transformed.expect
index 3396ff7..da09dec 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeargs_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeargs_test.dart.weak.transformed.expect
@@ -23,7 +23,7 @@
     ;
 }
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparam_test.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparam_test.dart.weak.expect
index 1a6b1c1..19f5ced 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparam_test.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparam_test.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A<T extends core::Object* = dynamic, S extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparam_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparam_test.dart.weak.transformed.expect
index 0be30d7..b6de55f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparam_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparam_test.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class A<T extends core::Object* = dynamic, S extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparambounds_test.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparambounds_test.dart.weak.expect
index 6c016e3..521ea4e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparambounds_test.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparambounds_test.dart.weak.expect
@@ -23,7 +23,7 @@
     ;
 }
 class A<T extends core::Object* = dynamic, S extends self::A::T* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparambounds_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparambounds_test.dart.weak.transformed.expect
index 0e2c3d5..8409594 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparambounds_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirecting_factory_typeparambounds_test.dart.weak.transformed.expect
@@ -23,7 +23,7 @@
     ;
 }
 class A<T extends core::Object* = dynamic, S extends self::A::T* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::redir];
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir];
   constructor •(self::A::T* t, self::A::S* s) → self::A<self::A::T*, self::A::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.weak.expect
index 4d1fc6a..e9d6519 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.weak.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.weak.transformed.expect
index 579f622..30b74d9 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.weak.expect
index aacff54..8f23e49 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.weak.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 abstract class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.weak.transformed.expect
index 2acaca4..25434a1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_chain_type_arguments_subst.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 abstract class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   constructor empty() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 abstract class B<U extends core::Object* = dynamic, W extends core::Object* = dynamic> extends self::A<self::B::U*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::•];
+  static final field dynamic _redirecting# = <dynamic>[self::B::•];
   constructor empty() → self::B<self::B::U*, self::B::W*>*
     : super self::A::empty()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.expect
index c2a1aa6..d6c5a68 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
     ;
@@ -37,3 +37,10 @@
 constants  {
   #C1 = self::B<core::String*> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirection_type_arguments.dart:
+- B. (from org-dartlang-testcase:///redirection_type_arguments.dart:18:9)
+- A.empty (from org-dartlang-testcase:///redirection_type_arguments.dart:14:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.transformed.expect
index 78db851..7119399 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/redirection_type_arguments.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[self::A::•];
+  static final field dynamic _redirecting# = <dynamic>[self::A::•];
   const constructor empty() → self::A*
     : super core::Object::•()
     ;
@@ -37,3 +37,10 @@
 constants  {
   #C1 = self::B<core::String*> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///redirection_type_arguments.dart:
+- B. (from org-dartlang-testcase:///redirection_type_arguments.dart:18:9)
+- A.empty (from org-dartlang-testcase:///redirection_type_arguments.dart:14:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart.weak.expect
index 73f42bd..50bca4d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart.weak.expect
@@ -12,7 +12,7 @@
 //
 // class C extends Iterable<Object> {
 //       ^
-// sdk/lib/core/iterable.dart:158:19: Context: 'Iterable.iterator' is defined here.
+// sdk/lib/core/iterable.dart:148:19: Context: 'Iterable.iterator' is defined here.
 //   Iterator<E> get iterator;
 //                   ^^^^^^^^
 //
@@ -30,7 +30,6 @@
   synthetic constructor •() → self::C*
     : super core::Iterable::•()
     ;
-  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
   abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::C::cast::R*>*; -> core::Iterable::cast
   abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::Object*>* other) → core::Iterable<core::Object*>*; -> core::Iterable::followedBy
   abstract member-signature method map<T extends core::Object* = dynamic>((core::Object*) →* self::C::map::T* f) → core::Iterable<self::C::map::T*>*; -> core::Iterable::map
@@ -67,6 +66,7 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
 }
 static method test() → dynamic {
   invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart:14:8: Error: Too few positional arguments: 1 required, 0 given.
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart.weak.transformed.expect
index 73f42bd..50bca4d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 //
 // class C extends Iterable<Object> {
 //       ^
-// sdk/lib/core/iterable.dart:158:19: Context: 'Iterable.iterator' is defined here.
+// sdk/lib/core/iterable.dart:148:19: Context: 'Iterable.iterator' is defined here.
 //   Iterator<E> get iterator;
 //                   ^^^^^^^^
 //
@@ -30,7 +30,6 @@
   synthetic constructor •() → self::C*
     : super core::Iterable::•()
     ;
-  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
   abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::C::cast::R*>*; -> core::Iterable::cast
   abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::Object*>* other) → core::Iterable<core::Object*>*; -> core::Iterable::followedBy
   abstract member-signature method map<T extends core::Object* = dynamic>((core::Object*) →* self::C::map::T* f) → core::Iterable<self::C::map::T*>*; -> core::Iterable::map
@@ -67,6 +66,7 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+  abstract member-signature get iterator() → core::Iterator<core::Object*>*; -> core::Iterable::iterator
 }
 static method test() → dynamic {
   invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/sdk_diagnostic.dart:14:8: Error: Too few positional arguments: 1 required, 0 given.
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.weak.transformed.expect
index 2972e81..a68c3f0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection.dart.weak.transformed.expect
@@ -13,9 +13,9 @@
 
 static method main() → dynamic {
   final core::List<core::int*>* aList = block {
-    final core::List<core::int*>* #t1 = <core::int*>[1];
-    #t1.{core::List::addAll}{Invariant}(<core::int*>[2]);
-    final core::Iterable<core::int*>* #t2 = <core::int*>[3];
+    final core::List<core::int*>* #t1 = core::_GrowableList::_literal1<core::int*>(1);
+    #t1.{core::List::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(2));
+    final core::Iterable<core::int*>* #t2 = core::_GrowableList::_literal1<core::int*>(3);
     if(!#t2.{core::Object::==}(null))
       #t1.{core::List::addAll}{Invariant}(#t2);
   } =>#t1;
@@ -41,8 +41,8 @@
   final core::Set<core::int*>* aSet = block {
     final core::Set<core::int*>* #t7 = new col::_CompactLinkedHashSet::•<core::int*>();
     #t7.{core::Set::add}{Invariant}(1);
-    #t7.{core::Set::addAll}{Invariant}(<core::int*>[2]);
-    final core::Iterable<core::int*>* #t8 = <core::int*>[3];
+    #t7.{core::Set::addAll}{Invariant}(core::_GrowableList::_literal1<core::int*>(2));
+    final core::Iterable<core::int*>* #t8 = core::_GrowableList::_literal1<core::int*>(3);
     if(!#t8.{core::Object::==}(null))
       #t7.{core::Set::addAll}{Invariant}(#t8);
   } =>#t7;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.weak.transformed.expect
index d10c002..b5daed3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart.weak.transformed.expect
@@ -103,17 +103,17 @@
 static method bar<K extends core::Object* = dynamic, V extends core::Object* = dynamic>() → core::Map<self::bar::K*, self::bar::V*>*
   return null;
 static method foo(dynamic dynVar) → dynamic {
-  core::List<core::int*>* spread = <core::int*>[1, 2, 3];
+  core::List<core::int*>* spread = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
   core::Map<core::String*, core::int*>* mapSpread = <core::String*, core::int*>{"foo": 4, "bar": 2};
   core::int* notSpreadInt = 42;
   () →* core::int* notSpreadFunction = null;
   core::Map<core::int*, core::num*>* mapIntNum = <core::int*, core::num*>{42: 42};
-  core::List<core::num*>* listNum = <core::num*>[42];
+  core::List<core::num*>* listNum = core::_GrowableList::_literal1<core::num*>(42);
   core::List<dynamic>* lhs10 = block {
-    final core::List<dynamic>* #t1 = core::List::of<dynamic>(<dynamic>[]);
+    final core::List<dynamic>* #t1 = core::List::of<dynamic>(core::_GrowableList::•<dynamic>(0));
   } =>#t1;
   core::Set<dynamic>* set10 = block {
-    final core::Set<dynamic>* #t2 = col::LinkedHashSet::of<dynamic>(<dynamic>[]);
+    final core::Set<dynamic>* #t2 = col::LinkedHashSet::of<dynamic>(core::_GrowableList::•<dynamic>(0));
   } =>#t2;
   core::Map<dynamic, dynamic>* map10 = block {
     final core::Map<dynamic, dynamic>* #t3 = <dynamic, dynamic>{};
@@ -199,16 +199,16 @@
   dynamic map21ambiguous = {...(mapSpread as dynamic)};
                            ^";
   core::List<core::int*>* lhs22 = block {
-    final core::List<core::int*>* #t20 = core::List::of<core::int*>(<core::int*>[]);
+    final core::List<core::int*>* #t20 = core::List::of<core::int*>(core::_GrowableList::•<core::int*>(0));
   } =>#t20;
   core::Set<core::int*>* set22 = block {
-    final core::Set<core::int*>* #t21 = col::LinkedHashSet::of<core::int*>(<core::int*>[]);
+    final core::Set<core::int*>* #t21 = col::LinkedHashSet::of<core::int*>(core::_GrowableList::•<core::int*>(0));
     #t21.{core::Set::add}{Invariant}(42);
   } =>#t21;
   core::Set<core::int*>* set22ambiguous = block {
     final core::Set<core::int*>* #t22 = new col::_CompactLinkedHashSet::•<core::int*>();
     {
-      core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[].{core::Iterable::iterator};
+      core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::•<core::int*>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t23 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -229,16 +229,16 @@
     }
   } =>#t25;
   core::List<core::List<core::int*>*>* lhs23 = block {
-    final core::List<core::List<core::int*>*>* #t27 = core::List::of<core::List<core::int*>*>(<core::List<core::int*>*>[<core::int*>[]]);
+    final core::List<core::List<core::int*>*>* #t27 = core::List::of<core::List<core::int*>*>(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
   } =>#t27;
   core::Set<core::List<core::int*>*>* set23 = block {
-    final core::Set<core::List<core::int*>*>* #t28 = col::LinkedHashSet::of<core::List<core::int*>*>(<core::List<core::int*>*>[<core::int*>[]]);
-    #t28.{core::Set::add}{Invariant}(<core::int*>[42]);
+    final core::Set<core::List<core::int*>*>* #t28 = col::LinkedHashSet::of<core::List<core::int*>*>(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)));
+    #t28.{core::Set::add}{Invariant}(core::_GrowableList::_literal1<core::int*>(42));
   } =>#t28;
   core::Set<core::List<core::int*>*>* set23ambiguous = block {
     final core::Set<core::List<core::int*>*>* #t29 = new col::_CompactLinkedHashSet::•<core::List<core::int*>*>();
     {
-      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = <core::List<core::int*>*>[<core::int*>[]].{core::Iterable::iterator};
+      core::Iterator<core::List<core::int*>*>* :sync-for-iterator = core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0)).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t30 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -251,7 +251,7 @@
   core::Map<core::String*, core::List<core::int*>*>* map23 = block {
     final core::Map<core::String*, core::List<core::int*>*>* #t32 = <core::String*, core::List<core::int*>*>{};
     {
-      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"baz": <core::int*>[]}.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<core::String*, core::List<core::int*>*>>* :sync-for-iterator = <core::String*, core::List<core::int*>*>{"baz": core::_GrowableList::•<core::int*>(0)}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final core::MapEntry<core::String*, core::List<core::int*>*>* #t33 = :sync-for-iterator.{core::Iterator::current};
         #t32.{core::Map::[]=}{Invariant}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
@@ -317,9 +317,9 @@
       }
     }
   } =>#t46) as{TypeError} core::int*;
-  core::List<dynamic>* lhs40 = <dynamic>[invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:113:38: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+  core::List<dynamic>* lhs40 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:113:38: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
   List<dynamic> lhs40 = <dynamic>[...notSpreadInt];
-                                     ^"];
+                                     ^");
   core::Set<dynamic>* set40 = block {
     final core::Set<dynamic>* #t48 = new col::_CompactLinkedHashSet::•<dynamic>();
     #t48.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:115:37: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
@@ -329,9 +329,9 @@
   core::Map<dynamic, dynamic>* map40 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:117:55: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
   Map<dynamic, dynamic> map40 = <dynamic, dynamic>{...notSpreadInt};
                                                       ^": null};
-  core::List<dynamic>* lhs50 = <dynamic>[invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:119:38: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
+  core::List<dynamic>* lhs50 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:119:38: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
   List<dynamic> lhs50 = <dynamic>[...notSpreadFunction];
-                                     ^"];
+                                     ^");
   core::Set<dynamic>* set50 = block {
     final core::Set<dynamic>* #t49 = new col::_CompactLinkedHashSet::•<dynamic>();
     #t49.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:121:37: Error: Unexpected type 'int Function()' of a spread.  Expected 'dynamic' or an Iterable.
@@ -341,9 +341,9 @@
   core::Map<dynamic, dynamic>* map50 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:123:55: Error: Unexpected type 'int Function()' of a map spread entry.  Expected 'dynamic' or a Map.
   Map<dynamic, dynamic> map50 = <dynamic, dynamic>{...notSpreadFunction};
                                                       ^": null};
-  core::List<core::String*>* lhs60 = <core::String*>[invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:125:36: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
+  core::List<core::String*>* lhs60 = core::_GrowableList::_literal1<core::String*>(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:125:36: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
   List<String> lhs60 = <String>[...spread];
-                                   ^"];
+                                   ^");
   core::Set<core::String*>* set60 = block {
     final core::Set<core::String*>* #t50 = new col::_CompactLinkedHashSet::•<core::String*>();
     #t50.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:127:35: Error: Can't assign spread elements of type 'int' to collection elements of type 'String'.
@@ -356,9 +356,9 @@
   core::Map<core::String*, core::String*>* map61 = <core::String*, core::String*>{null: invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:131:51: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
   Map<String, String> map61 = <String, String>{...mapSpread};
                                                   ^"};
-  core::List<core::int*>* lhs70 = <core::int*>[invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:133:30: Error: Can't spread a value with static type 'Null'.
+  core::List<core::int*>* lhs70 = core::_GrowableList::_literal1<core::int*>(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:133:30: Error: Can't spread a value with static type 'Null'.
   List<int> lhs70 = <int>[...null];
-                             ^"];
+                             ^");
   core::Set<core::int*>* set70 = block {
     final core::Set<core::int*>* #t51 = new col::_CompactLinkedHashSet::•<core::int*>();
     #t51.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/spread_collection_inference.dart:135:29: Error: Can't spread a value with static type 'Null'.
@@ -371,7 +371,7 @@
     ...null,
        ^");
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t53 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -385,7 +385,7 @@
   Map<String, int> map70 = <String, int>{...null};
                                             ^": null};
   core::List<core::int*>* lhs80 = block {
-    final core::List<core::int*>* #t55 = <core::int*>[];
+    final core::List<core::int*>* #t55 = core::_GrowableList::•<core::int*>(0);
     final core::Iterable<core::int*>* #t56 = null;
     if(!#t56.{core::Object::==}(null))
       #t55.{core::List::addAll}{Invariant}(#t56);
@@ -410,7 +410,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t63 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -442,7 +442,7 @@
     }
   } =>#t68;
   core::List<core::int*>* list100 = block {
-    final core::List<core::int*>* #t70 = <core::int*>[];
+    final core::List<core::int*>* #t70 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<core::num*>* :sync-for-iterator = listNum.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -469,7 +469,7 @@
     }
   } =>#t73;
   core::List<core::int*>* list110 = block {
-    final core::List<core::int*>* #t77 = <core::int*>[];
+    final core::List<core::int*>* #t77 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<dynamic>* :sync-for-iterator = (dynVar as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.transformed.expect
index 91dfee3..dd17252 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.transformed.expect
@@ -84,7 +84,7 @@
   }
   while (false)
   {
-    core::Iterator<core::String*>* :sync-for-iterator = <core::String*>["Hello from for-in!"].{core::Iterable::iterator};
+    core::Iterator<core::String*>* :sync-for-iterator = core::_GrowableList::_literal1<core::String*>("Hello from for-in!").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String* s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -93,7 +93,7 @@
     }
   }
   {
-    core::Iterator<core::String*>* :sync-for-iterator = <core::String*>["Hello from for-in without block!"].{core::Iterable::iterator};
+    core::Iterator<core::String*>* :sync-for-iterator = core::_GrowableList::_literal1<core::String*>("Hello from for-in without block!").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String* s = :sync-for-iterator.{core::Iterator::current};
       core::print(s);
@@ -101,7 +101,7 @@
   }
   dynamic s;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>["Hello from for-in without decl!"].{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::_literal1<dynamic>("Hello from for-in without decl!").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
       {
@@ -111,7 +111,7 @@
     }
   }
   {
-    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>["Hello from for-in without decl and block!"].{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::_literal1<dynamic>("Hello from for-in without decl and block!").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t5 = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
index dec49a6..0feb0ae 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart.weak.expect
@@ -41,7 +41,7 @@
     return this.{self::NumClass::field1}.{core::num::+}(invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/type_variable_bound_access.dart:24:36: Error: The getter 'length' isn't defined for the class 'num'.
 Try correcting the name to the name of an existing getter, or defining a getter or field named 'length'.
   num method2() => field1 + field2.length;
-                                   ^^^^^^" as{TypeError,ForDynamic} core::num);
+                                   ^^^^^^" as{TypeError,ForDynamic} core::num*);
   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
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.expect
index 3f3a1f0..ddc2500 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.expect
@@ -70,13 +70,13 @@
     : super core::Object::•()
     ;
   static method staticMethod() → self::C<dynamic>* {
-    core::print(invalid-type);
+    core::print(#C1);
     invalid-type t;
     self::C<invalid-type>* l;
     self::C<self::C<invalid-type>*>* ll;
-    #C1;
     #C2;
     #C3;
+    #C4;
     #C5;
     #C6;
   }
@@ -85,9 +85,9 @@
     self::C::T* t;
     self::C<self::C::T*>* l;
     self::C<self::C<self::C::T*>*>* ll;
-    #C1;
     #C2;
     #C3;
+    #C4;
     #C5;
     #C6;
   }
@@ -105,10 +105,16 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = self::C<invalid-type> {}
-  #C2 = <invalid-type>[]
-  #C3 = <self::C<invalid-type>*>[]
-  #C4 = TypeLiteralConstant(invalid-type)
-  #C5 = <core::Object*>[#C4]
-  #C6 = <core::Object*>[#C1]
+  #C1 = TypeLiteralConstant(invalid-type)
+  #C2 = self::C<invalid-type> {}
+  #C3 = <invalid-type>[]
+  #C4 = <self::C<invalid-type>*>[]
+  #C5 = <core::Object*>[#C1]
+  #C6 = <core::Object*>[#C2]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///type_variable_uses.dart:
+- C. (from org-dartlang-testcase:///type_variable_uses.dart:8:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
index 8deddad..ddc2500 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
@@ -70,13 +70,13 @@
     : super core::Object::•()
     ;
   static method staticMethod() → self::C<dynamic>* {
-    core::print(invalid-type);
+    core::print(#C1);
     invalid-type t;
     self::C<invalid-type>* l;
     self::C<self::C<invalid-type>*>* ll;
-    #C1;
     #C2;
     #C3;
+    #C4;
     #C5;
     #C6;
   }
@@ -85,9 +85,9 @@
     self::C::T* t;
     self::C<self::C::T*>* l;
     self::C<self::C<self::C::T*>*>* ll;
-    #C1;
     #C2;
     #C3;
+    #C4;
     #C5;
     #C6;
   }
@@ -105,14 +105,16 @@
 static method main() → dynamic {}
 
 constants  {
-  #C1 = self::C<invalid-type> {}
-  #C2 = <invalid-type>[]
-  #C3 = <self::C<invalid-type>*>[]
-  #C4 = TypeLiteralConstant(invalid-type)
-  #C5 = <core::Object*>[#C4]
-  #C6 = <core::Object*>[#C1]
+  #C1 = TypeLiteralConstant(invalid-type)
+  #C2 = self::C<invalid-type> {}
+  #C3 = <invalid-type>[]
+  #C4 = <self::C<invalid-type>*>[]
+  #C5 = <core::Object*>[#C1]
+  #C6 = <core::Object*>[#C2]
 }
 
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_variable_uses.dart:10:11 -> TypeLiteralConstant(<invalid>)
-Extra constant evaluation: evaluated: 4, effectively constant: 1
+
+Constructor coverage from constants:
+org-dartlang-testcase:///type_variable_uses.dart:
+- C. (from org-dartlang-testcase:///type_variable_uses.dart:8:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.expect
index a65b8e4..70705a1 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.expect
@@ -10,7 +10,7 @@
   set first(dynamic x) → void
     return let final core::List<dynamic>* #t1 = this.{self::Foo::list} in let final core::int* #t2 = 0 in let final dynamic #t3 = x in let final void #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3;
   operator []=(dynamic x, dynamic y) → void
-    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final dynamic #t6 = x as{TypeError,ForDynamic} core::int in let final dynamic #t7 = y in let final void #t8 = #t5.{core::List::[]=}(#t6, #t7) in #t7;
+    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final dynamic #t6 = x as{TypeError,ForDynamic} core::int* in let final dynamic #t7 = y in let final void #t8 = #t5.{core::List::[]=}(#t6, #t7) in #t7;
   method clear() → void
     return this.{self::Foo::list}.{core::List::clear}();
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.transformed.expect
index 9358d88..7332e9e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.transformed.expect
@@ -3,14 +3,14 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  field core::List<dynamic>* list = <dynamic>[1, 2, 3];
+  field core::List<dynamic>* list = core::_GrowableList::_literal3<dynamic>(1, 2, 3);
   synthetic constructor •() → self::Foo*
     : super core::Object::•()
     ;
   set first(dynamic x) → void
     return let final core::List<dynamic>* #t1 = this.{self::Foo::list} in let final core::int* #t2 = 0 in let final dynamic #t3 = x in let final void #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3;
   operator []=(dynamic x, dynamic y) → void
-    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final core::int #t6 = x as{TypeError,ForDynamic} core::int in let final dynamic #t7 = y in let final void #t8 = #t5.{core::List::[]=}(#t6, #t7) in #t7;
+    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final core::int* #t6 = x as{TypeError,ForDynamic} core::int* in let final dynamic #t7 = y in let final void #t8 = #t5.{core::List::[]=}(#t6, #t7) in #t7;
   method clear() → void
     return this.{self::Foo::list}.{core::List::clear}();
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.expect b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.expect
index 4321535..b452cdb 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.expect
@@ -112,21 +112,21 @@
 }
 static field core::bool* enableRead = true;
 static method read(core::int* value) → core::int*
-  return self::enableRead ?{core::int*} value : 1.{core::int::unary-}();
+  return self::enableRead ?{core::int*} value : 1.{core::int::unary-}(){() →* core::int*};
 static method method1() → core::int*
   return 0;
 static method method2(core::int* a) → core::int*
-  return a.{core::int::unary-}();
+  return a.{core::int::unary-}(){() →* core::int*};
 static method method3(core::int* a, core::int* b) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method method4(core::int* a, [core::int* b = #C8]) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method method5([core::int* a = #C8, core::int* b = #C8]) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method method6(core::int* a, {core::int* b = #C8}) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method method7({core::int* a = #C8, core::int* b = #C8}) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method main() → dynamic {
   self::callField(new self::Class::•());
   self::callGetter(new self::Class::•());
@@ -136,42 +136,42 @@
 static method callField(self::Class* c) → dynamic {
   self::expect(0, c.{self::Class::field1a}());
   self::expect(0, c.{self::Class::field1b}());
-  self::expect(42.{core::int::unary-}(), let final self::Class* #t1 = c in let final core::int* #t2 = self::read(42) in #t1.{self::Class::field2}(#t2));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t3 = c in let final core::int* #t4 = self::read(12) in let final core::int* #t5 = self::read(23) in #t3.{self::Class::field3}(#t4, #t5));
+  self::expect(42.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t1 = c in let final core::int* #t2 = self::read(42) in #t1.{self::Class::field2}(#t2));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t3 = c in let final core::int* #t4 = self::read(12) in let final core::int* #t5 = self::read(23) in #t3.{self::Class::field3}(#t4, #t5));
   self::expect(12, let final self::Class* #t6 = c in let final core::int* #t7 = self::read(12) in #t6.{self::Class::field4}(#t7));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t8 = c in let final core::int* #t9 = self::read(12) in let final core::int* #t10 = self::read(23) in #t8.{self::Class::field4}(#t9, #t10));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t8 = c in let final core::int* #t9 = self::read(12) in let final core::int* #t10 = self::read(23) in #t8.{self::Class::field4}(#t9, #t10));
   self::expect(0, c.{self::Class::field5}());
   self::expect(12, let final self::Class* #t11 = c in let final core::int* #t12 = self::read(12) in #t11.{self::Class::field5}(#t12));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t13 = c in let final core::int* #t14 = self::read(12) in let final core::int* #t15 = self::read(23) in #t13.{self::Class::field5}(#t14, #t15));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t13 = c in let final core::int* #t14 = self::read(12) in let final core::int* #t15 = self::read(23) in #t13.{self::Class::field5}(#t14, #t15));
   self::expect(12, let final self::Class* #t16 = c in let final core::int* #t17 = self::read(12) in #t16.{self::Class::field6}(#t17));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t18 = c in let final core::int* #t19 = self::read(12) in let final core::int* #t20 = self::read(23) in #t18.{self::Class::field6}(#t19, b: #t20));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t18 = c in let final core::int* #t19 = self::read(12) in let final core::int* #t20 = self::read(23) in #t18.{self::Class::field6}(#t19, b: #t20));
   self::expect(0, c.{self::Class::field7}());
   self::expect(12, let final self::Class* #t21 = c in let final core::int* #t22 = self::read(12) in #t21.{self::Class::field7}(a: #t22));
-  self::expect(23.{core::int::unary-}(), let final self::Class* #t23 = c in let final core::int* #t24 = self::read(23) in #t23.{self::Class::field7}(b: #t24));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t25 = c in let final core::int* #t26 = self::read(12) in let final core::int* #t27 = self::read(23) in #t25.{self::Class::field7}(a: #t26, b: #t27));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t28 = c in let final core::int* #t29 = self::read(23) in let final core::int* #t30 = self::read(12) in #t28.{self::Class::field7}(b: #t29, a: #t30));
+  self::expect(23.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t23 = c in let final core::int* #t24 = self::read(23) in #t23.{self::Class::field7}(b: #t24));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t25 = c in let final core::int* #t26 = self::read(12) in let final core::int* #t27 = self::read(23) in #t25.{self::Class::field7}(a: #t26, b: #t27));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t28 = c in let final core::int* #t29 = self::read(23) in let final core::int* #t30 = self::read(12) in #t28.{self::Class::field7}(b: #t29, a: #t30));
 }
 static method callGetter(self::Class* c) → dynamic {
   self::expect(0, c.{self::Class::getter1a}());
   self::expect(0, c.{self::Class::getter1b}());
-  self::expect(42.{core::int::unary-}(), let final self::Class* #t31 = c in let final core::int* #t32 = self::read(42) in #t31.{self::Class::getter2}(#t32));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t33 = c in let final core::int* #t34 = self::read(12) in let final core::int* #t35 = self::read(23) in #t33.{self::Class::getter3}(#t34, #t35));
+  self::expect(42.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t31 = c in let final core::int* #t32 = self::read(42) in #t31.{self::Class::getter2}(#t32));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t33 = c in let final core::int* #t34 = self::read(12) in let final core::int* #t35 = self::read(23) in #t33.{self::Class::getter3}(#t34, #t35));
   self::expect(12, let final self::Class* #t36 = c in let final core::int* #t37 = self::read(12) in #t36.{self::Class::getter4}(#t37));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t38 = c in let final core::int* #t39 = self::read(12) in let final core::int* #t40 = self::read(23) in #t38.{self::Class::getter4}(#t39, #t40));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t38 = c in let final core::int* #t39 = self::read(12) in let final core::int* #t40 = self::read(23) in #t38.{self::Class::getter4}(#t39, #t40));
   self::expect(0, c.{self::Class::getter5}());
   self::expect(12, let final self::Class* #t41 = c in let final core::int* #t42 = self::read(12) in #t41.{self::Class::getter5}(#t42));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t43 = c in let final core::int* #t44 = self::read(12) in let final core::int* #t45 = self::read(23) in #t43.{self::Class::getter5}(#t44, #t45));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t43 = c in let final core::int* #t44 = self::read(12) in let final core::int* #t45 = self::read(23) in #t43.{self::Class::getter5}(#t44, #t45));
   self::expect(12, let final self::Class* #t46 = c in let final core::int* #t47 = self::read(12) in #t46.{self::Class::getter6}(#t47));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t48 = c in let final core::int* #t49 = self::read(12) in let final core::int* #t50 = self::read(23) in #t48.{self::Class::getter6}(#t49, b: #t50));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t48 = c in let final core::int* #t49 = self::read(12) in let final core::int* #t50 = self::read(23) in #t48.{self::Class::getter6}(#t49, b: #t50));
   self::expect(0, c.{self::Class::getter7}());
   self::expect(12, let final self::Class* #t51 = c in let final core::int* #t52 = self::read(12) in #t51.{self::Class::getter7}(a: #t52));
-  self::expect(23.{core::int::unary-}(), let final self::Class* #t53 = c in let final core::int* #t54 = self::read(23) in #t53.{self::Class::getter7}(b: #t54));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t55 = c in let final core::int* #t56 = self::read(12) in let final core::int* #t57 = self::read(23) in #t55.{self::Class::getter7}(a: #t56, b: #t57));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t58 = c in let final core::int* #t59 = self::read(23) in let final core::int* #t60 = self::read(12) in #t58.{self::Class::getter7}(b: #t59, a: #t60));
+  self::expect(23.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t53 = c in let final core::int* #t54 = self::read(23) in #t53.{self::Class::getter7}(b: #t54));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t55 = c in let final core::int* #t56 = self::read(12) in let final core::int* #t57 = self::read(23) in #t55.{self::Class::getter7}(a: #t56, b: #t57));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t58 = c in let final core::int* #t59 = self::read(23) in let final core::int* #t60 = self::read(12) in #t58.{self::Class::getter7}(b: #t59, a: #t60));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   self::enableRead = true;
-  if(!expected.{core::Object::==}(actual))
+  if(expected !={core::Object::==}{(core::Object*) →* core::bool*} actual)
     throw "Expected ${expected}, ${actual}";
 }
 
diff --git a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.transformed.expect b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.transformed.expect
index e9cba62..7462ff3 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.transformed.expect
@@ -112,21 +112,21 @@
 }
 static field core::bool* enableRead = true;
 static method read(core::int* value) → core::int*
-  return self::enableRead ?{core::int*} value : 1.{core::int::unary-}();
+  return self::enableRead ?{core::int*} value : 1.{core::int::unary-}(){() →* core::int*};
 static method method1() → core::int*
   return 0;
 static method method2(core::int* a) → core::int*
-  return a.{core::int::unary-}();
+  return a.{core::int::unary-}(){() →* core::int*};
 static method method3(core::int* a, core::int* b) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method method4(core::int* a, [core::int* b = #C8]) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method method5([core::int* a = #C8, core::int* b = #C8]) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method method6(core::int* a, {core::int* b = #C8}) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method method7({core::int* a = #C8, core::int* b = #C8}) → core::int*
-  return a.{core::num::-}(b);
+  return a.{core::num::-}(b){(core::num*) →* core::int*};
 static method main() → dynamic {
   self::callField(new self::Class::•());
   self::callGetter(new self::Class::•());
@@ -136,42 +136,42 @@
 static method callField(self::Class* c) → dynamic {
   self::expect(0, c.{self::Class::field1a}());
   self::expect(0, c.{self::Class::field1b}());
-  self::expect(42.{core::int::unary-}(), let final self::Class* #t1 = c in let final core::int* #t2 = self::read(42) in #t1.{self::Class::field2}(#t2));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t3 = c in let final core::int* #t4 = self::read(12) in let final core::int* #t5 = self::read(23) in #t3.{self::Class::field3}(#t4, #t5));
+  self::expect(42.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t1 = c in let final core::int* #t2 = self::read(42) in #t1.{self::Class::field2}(#t2));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t3 = c in let final core::int* #t4 = self::read(12) in let final core::int* #t5 = self::read(23) in #t3.{self::Class::field3}(#t4, #t5));
   self::expect(12, let final self::Class* #t6 = c in let final core::int* #t7 = self::read(12) in #t6.{self::Class::field4}(#t7));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t8 = c in let final core::int* #t9 = self::read(12) in let final core::int* #t10 = self::read(23) in #t8.{self::Class::field4}(#t9, #t10));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t8 = c in let final core::int* #t9 = self::read(12) in let final core::int* #t10 = self::read(23) in #t8.{self::Class::field4}(#t9, #t10));
   self::expect(0, c.{self::Class::field5}());
   self::expect(12, let final self::Class* #t11 = c in let final core::int* #t12 = self::read(12) in #t11.{self::Class::field5}(#t12));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t13 = c in let final core::int* #t14 = self::read(12) in let final core::int* #t15 = self::read(23) in #t13.{self::Class::field5}(#t14, #t15));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t13 = c in let final core::int* #t14 = self::read(12) in let final core::int* #t15 = self::read(23) in #t13.{self::Class::field5}(#t14, #t15));
   self::expect(12, let final self::Class* #t16 = c in let final core::int* #t17 = self::read(12) in #t16.{self::Class::field6}(#t17));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t18 = c in let final core::int* #t19 = self::read(12) in let final core::int* #t20 = self::read(23) in #t18.{self::Class::field6}(#t19, b: #t20));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t18 = c in let final core::int* #t19 = self::read(12) in let final core::int* #t20 = self::read(23) in #t18.{self::Class::field6}(#t19, b: #t20));
   self::expect(0, c.{self::Class::field7}());
   self::expect(12, let final self::Class* #t21 = c in let final core::int* #t22 = self::read(12) in #t21.{self::Class::field7}(a: #t22));
-  self::expect(23.{core::int::unary-}(), let final self::Class* #t23 = c in let final core::int* #t24 = self::read(23) in #t23.{self::Class::field7}(b: #t24));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t25 = c in let final core::int* #t26 = self::read(12) in let final core::int* #t27 = self::read(23) in #t25.{self::Class::field7}(a: #t26, b: #t27));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t28 = c in let final core::int* #t29 = self::read(23) in let final core::int* #t30 = self::read(12) in #t28.{self::Class::field7}(b: #t29, a: #t30));
+  self::expect(23.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t23 = c in let final core::int* #t24 = self::read(23) in #t23.{self::Class::field7}(b: #t24));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t25 = c in let final core::int* #t26 = self::read(12) in let final core::int* #t27 = self::read(23) in #t25.{self::Class::field7}(a: #t26, b: #t27));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t28 = c in let final core::int* #t29 = self::read(23) in let final core::int* #t30 = self::read(12) in #t28.{self::Class::field7}(b: #t29, a: #t30));
 }
 static method callGetter(self::Class* c) → dynamic {
   self::expect(0, c.{self::Class::getter1a}());
   self::expect(0, c.{self::Class::getter1b}());
-  self::expect(42.{core::int::unary-}(), let final self::Class* #t31 = c in let final core::int* #t32 = self::read(42) in #t31.{self::Class::getter2}(#t32));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t33 = c in let final core::int* #t34 = self::read(12) in let final core::int* #t35 = self::read(23) in #t33.{self::Class::getter3}(#t34, #t35));
+  self::expect(42.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t31 = c in let final core::int* #t32 = self::read(42) in #t31.{self::Class::getter2}(#t32));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t33 = c in let final core::int* #t34 = self::read(12) in let final core::int* #t35 = self::read(23) in #t33.{self::Class::getter3}(#t34, #t35));
   self::expect(12, let final self::Class* #t36 = c in let final core::int* #t37 = self::read(12) in #t36.{self::Class::getter4}(#t37));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t38 = c in let final core::int* #t39 = self::read(12) in let final core::int* #t40 = self::read(23) in #t38.{self::Class::getter4}(#t39, #t40));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t38 = c in let final core::int* #t39 = self::read(12) in let final core::int* #t40 = self::read(23) in #t38.{self::Class::getter4}(#t39, #t40));
   self::expect(0, c.{self::Class::getter5}());
   self::expect(12, let final self::Class* #t41 = c in let final core::int* #t42 = self::read(12) in #t41.{self::Class::getter5}(#t42));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t43 = c in let final core::int* #t44 = self::read(12) in let final core::int* #t45 = self::read(23) in #t43.{self::Class::getter5}(#t44, #t45));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t43 = c in let final core::int* #t44 = self::read(12) in let final core::int* #t45 = self::read(23) in #t43.{self::Class::getter5}(#t44, #t45));
   self::expect(12, let final self::Class* #t46 = c in let final core::int* #t47 = self::read(12) in #t46.{self::Class::getter6}(#t47));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t48 = c in let final core::int* #t49 = self::read(12) in let final core::int* #t50 = self::read(23) in #t48.{self::Class::getter6}(#t49, b: #t50));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t48 = c in let final core::int* #t49 = self::read(12) in let final core::int* #t50 = self::read(23) in #t48.{self::Class::getter6}(#t49, b: #t50));
   self::expect(0, c.{self::Class::getter7}());
   self::expect(12, let final self::Class* #t51 = c in let final core::int* #t52 = self::read(12) in #t51.{self::Class::getter7}(a: #t52));
-  self::expect(23.{core::int::unary-}(), let final self::Class* #t53 = c in let final core::int* #t54 = self::read(23) in #t53.{self::Class::getter7}(b: #t54));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t55 = c in let final core::int* #t56 = self::read(12) in let final core::int* #t57 = self::read(23) in #t55.{self::Class::getter7}(a: #t56, b: #t57));
-  self::expect(11.{core::int::unary-}(), let final self::Class* #t58 = c in let final core::int* #t59 = self::read(23) in let final core::int* #t60 = self::read(12) in #t58.{self::Class::getter7}(b: #t59, a: #t60));
+  self::expect(23.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t53 = c in let final core::int* #t54 = self::read(23) in #t53.{self::Class::getter7}(b: #t54));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t55 = c in let final core::int* #t56 = self::read(12) in let final core::int* #t57 = self::read(23) in #t55.{self::Class::getter7}(a: #t56, b: #t57));
+  self::expect(11.{core::int::unary-}(){() →* core::int*}, let final self::Class* #t58 = c in let final core::int* #t59 = self::read(23) in let final core::int* #t60 = self::read(12) in #t58.{self::Class::getter7}(b: #t59, a: #t60));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   self::enableRead = true;
-  if(!expected.{core::Object::==}(actual))
+  if(expected !={core::Object::==}{(core::Object*) →* core::bool*} actual)
     throw "Expected ${expected}, ${actual}";
 }
 
@@ -187,21 +187,21 @@
 }
 
 Extra constant evaluation status:
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:7:45 -> IntConstant(-1)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:130:10 -> IntConstant(-42)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:131:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:133:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:136:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:138:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:141:10 -> IntConstant(-23)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:142:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:143:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:149:10 -> IntConstant(-42)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:150:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:152:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:155:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:157:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:160:10 -> IntConstant(-23)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:161:10 -> IntConstant(-11)
-Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:162:10 -> IntConstant(-11)
-Extra constant evaluation: evaluated: 322, effectively constant: 17
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:7:45 -> IntConstant(-1)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:130:10 -> IntConstant(-42)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:131:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:133:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:136:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:138:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:141:10 -> IntConstant(-23)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:142:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:143:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:149:10 -> IntConstant(-42)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:150:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:152:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:155:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:157:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:160:10 -> IntConstant(-23)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:161:10 -> IntConstant(-11)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///getter_call.dart:162:10 -> IntConstant(-11)
+Extra constant evaluation: evaluated: 321, effectively constant: 17
diff --git a/pkg/front_end/testcases/implicit_getter_calls/this_field_call.dart.strong.expect b/pkg/front_end/testcases/implicit_getter_calls/this_field_call.dart.strong.expect
index 3c9883b..21856f2 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/this_field_call.dart.strong.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/this_field_call.dart.strong.expect
@@ -21,5 +21,5 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  new self::A::•<core::int*>((core::int* x) → Null {}).{self::A::foo}(3);
+  new self::A::•<core::int*>((core::int* x) → Null {}).{self::A::foo}(3){(core::int*) →* dynamic};
 }
diff --git a/pkg/front_end/testcases/implicit_getter_calls/this_field_call.dart.strong.transformed.expect b/pkg/front_end/testcases/implicit_getter_calls/this_field_call.dart.strong.transformed.expect
index 3c9883b..21856f2 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/this_field_call.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/this_field_call.dart.strong.transformed.expect
@@ -21,5 +21,5 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  new self::A::•<core::int*>((core::int* x) → Null {}).{self::A::foo}(3);
+  new self::A::•<core::int*>((core::int* x) → Null {}).{self::A::foo}(3){(core::int*) →* dynamic};
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml.world.1.expect
index 136a4b6..cd92eb8 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_13.yaml.world.1.expect
@@ -7,6 +7,16 @@
     synthetic constructor •() → main::ABC*
       : super a::AB::•()
       ;
+    abstract mixin-stub get _identityHashCode() → dart.core::int*; -> a::C::_identityHashCode
+    abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> a::C::_instanceOf
+    abstract mixin-stub method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> a::C::_simpleInstanceOf
+    abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> a::C::_simpleInstanceOfTrue
+    abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> a::C::_simpleInstanceOfFalse
+    abstract mixin-stub operator ==(dynamic other) → dart.core::bool*; -> a::C::==
+    abstract mixin-stub get hashCode() → dart.core::int*; -> a::C::hashCode
+    abstract mixin-stub method toString() → dart.core::String*; -> a::C::toString
+    abstract mixin-stub method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> a::C::noSuchMethod
+    abstract mixin-stub get runtimeType() → dart.core::Type*; -> a::C::runtimeType
   }
 }
 library from "package:module/a.dart" as a {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml.world.1.expect
index 309dfe4..cde35c2 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/changing_modules_8.yaml.world.1.expect
@@ -12,7 +12,7 @@
   import "package:module/lib2.dart";
 
   abstract class XSet extends dart.core::Object {
-    static field dynamic _redirecting# = <dynamic>[lib1::XSet::identity];
+    static final field dynamic _redirecting# = <dynamic>[lib1::XSet::identity];
     static factory identity() → lib1::XSet*
       let dynamic #redirecting_factory = lib2::XLinkedHashSet::identity in invalid-expression;
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
@@ -33,7 +33,7 @@
   import "package:module/lib3.dart";
 
   class XLinkedHashSet extends dart.core::Object implements lib1::XSet {
-    static field dynamic _redirecting# = <dynamic>[lib2::XLinkedHashSet::identity];
+    static final field dynamic _redirecting# = <dynamic>[lib2::XLinkedHashSet::identity];
     static factory identity() → lib2::XLinkedHashSet*
       let dynamic #redirecting_factory = lib3::XIdentityHashSet::• in invalid-expression;
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect
index 223e672..3b0a7e5 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect
@@ -9,7 +9,7 @@
 //
 
   class C extends dart.core::Object {
-    static field dynamic _redirecting# = <dynamic>[lib::C::e4];
+    static final field dynamic _redirecting# = <dynamic>[lib::C::e4];
     constructor •() → lib::C*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.2.expect
index cb55d11..bec03e7 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.2.expect
@@ -9,7 +9,7 @@
 //
 
   class C extends dart.core::Object {
-    static field dynamic _redirecting# = <dynamic>[lib::C::e4];
+    static final field dynamic _redirecting# = <dynamic>[lib::C::e4];
     constructor •() → lib::C*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml
new file mode 100644
index 0000000..1f4e0da3
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml
@@ -0,0 +1,56 @@
+# 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.
+
+type: newworld
+target: VM
+worlds:
+  - entry: main.dart
+    sources:
+      .dart_tool/package_config.json: |
+        {
+          "configVersion": 2,
+          "packages": [
+            {
+              "name": "flutter",
+              "rootUri": "../flutter",
+              "languageVersion": "2.12"
+            }
+          ]
+        }
+      main.dart: |
+        import 'package:flutter/object.dart';
+        import 'lib.dart';
+        
+        class Adaptor extends RenderFoo with LibMixin {}
+
+        class AdaptorElement extends RenderObject {
+          Adaptor get renderObject => super.renderObject;
+          void foo() {
+            print(renderObject.constraints.axis);
+          }
+        }
+      lib.dart: |
+        import 'package:flutter/object.dart';
+        mixin LibMixin on RenderObject {}
+      flutter/object.dart: |
+        class RenderFoo extends RenderObject {
+          FooConstraints get constraints => super.constraints as FooConstraints;
+        }
+        class FooConstraints extends Constraints {
+          String get axis => "hello";
+        }
+        class Constraints {}
+        class RenderObject {
+          Constraints get constraints => new Constraints();
+          RenderObject get renderObject => this;
+        }
+    expectedLibraryCount: 3
+
+  - entry: main.dart
+    worldType: updated
+    errors: true
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 3
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml.world.1.expect
new file mode 100644
index 0000000..03611f5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml.world.1.expect
@@ -0,0 +1,100 @@
+main = <No Member>;
+library from "package:flutter/object.dart" as obj {
+
+  class RenderFoo extends obj::RenderObject {
+    synthetic constructor •() → obj::RenderFoo
+      : super obj::RenderObject::•()
+      ;
+    get constraints() → obj::FooConstraints
+      return super.{obj::RenderObject::constraints} as{ForNonNullableByDefault} obj::FooConstraints;
+  }
+  class FooConstraints extends obj::Constraints {
+    synthetic constructor •() → obj::FooConstraints
+      : super obj::Constraints::•()
+      ;
+    get axis() → dart.core::String
+      return "hello";
+  }
+  class Constraints extends dart.core::Object {
+    synthetic constructor •() → obj::Constraints
+      : super dart.core::Object::•()
+      ;
+  }
+  class RenderObject extends dart.core::Object {
+    synthetic constructor •() → obj::RenderObject
+      : super dart.core::Object::•()
+      ;
+    get constraints() → obj::Constraints
+      return new obj::Constraints::•();
+    get renderObject() → obj::RenderObject
+      return this;
+  }
+}
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "package:flutter/object.dart";
+
+  abstract class LibMixin extends obj::RenderObject /*isMixinDeclaration*/  {
+    abstract member-signature get constraints() → obj::Constraints*; -> obj::RenderObject::constraints
+    abstract member-signature get renderObject() → obj::RenderObject*; -> obj::RenderObject::renderObject
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "package:flutter/object.dart";
+  import "org-dartlang-test:///lib.dart";
+
+  abstract class _Adaptor&RenderFoo&LibMixin extends obj::RenderFoo implements lib::LibMixin /*isAnonymousMixin,isEliminatedMixin*/  {
+    synthetic constructor •() → main::_Adaptor&RenderFoo&LibMixin*
+      : super obj::RenderFoo::•()
+      ;
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ constraints() → obj::Constraints*; -> obj::RenderObject::constraints
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ renderObject() → obj::RenderObject*; -> obj::RenderObject::renderObject
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator /* from org-dartlang-test:///lib.dart */ ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+  class Adaptor extends main::_Adaptor&RenderFoo&LibMixin {
+    synthetic constructor •() → main::Adaptor*
+      : super main::_Adaptor&RenderFoo&LibMixin::•()
+      ;
+  }
+  class AdaptorElement extends obj::RenderObject {
+    synthetic constructor •() → main::AdaptorElement*
+      : super obj::RenderObject::•()
+      ;
+    get renderObject() → main::Adaptor*
+      return super.{obj::RenderObject::renderObject} as{TypeError} main::Adaptor*;
+    method foo() → void {
+      dart.core::print(this.{main::AdaptorElement::renderObject}.{main::_Adaptor&RenderFoo&LibMixin::constraints}.{obj::FooConstraints::axis});
+    }
+    abstract member-signature get constraints() → obj::Constraints*; -> obj::RenderObject::constraints
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml.world.2.expect
new file mode 100644
index 0000000..e251ab0
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/error_on_recompile_with_no_change.yaml.world.2.expect
@@ -0,0 +1,109 @@
+main = <No Member>;
+library from "package:flutter/object.dart" as obj {
+
+  class RenderFoo extends obj::RenderObject {
+    synthetic constructor •() → obj::RenderFoo
+      : super obj::RenderObject::•()
+      ;
+    get constraints() → obj::FooConstraints
+      return super.{obj::RenderObject::constraints} as{ForNonNullableByDefault} obj::FooConstraints;
+  }
+  class FooConstraints extends obj::Constraints {
+    synthetic constructor •() → obj::FooConstraints
+      : super obj::Constraints::•()
+      ;
+    get axis() → dart.core::String
+      return "hello";
+  }
+  class Constraints extends dart.core::Object {
+    synthetic constructor •() → obj::Constraints
+      : super dart.core::Object::•()
+      ;
+  }
+  class RenderObject extends dart.core::Object {
+    synthetic constructor •() → obj::RenderObject
+      : super dart.core::Object::•()
+      ;
+    get constraints() → obj::Constraints
+      return new obj::Constraints::•();
+    get renderObject() → obj::RenderObject
+      return this;
+  }
+}
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "package:flutter/object.dart";
+
+  abstract class LibMixin extends obj::RenderObject /*isMixinDeclaration*/  {
+    abstract member-signature get constraints() → obj::Constraints*; -> obj::RenderObject::constraints
+    abstract member-signature get renderObject() → obj::RenderObject*; -> obj::RenderObject::renderObject
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:9:36: Error: The getter 'axis' isn't defined for the class 'Constraints'.
+//  - 'Constraints' is from 'package:flutter/object.dart' ('org-dartlang-test:///flutter/object.dart').
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'axis'.
+//     print(renderObject.constraints.axis);
+//                                    ^^^^
+//
+
+  import "package:flutter/object.dart";
+  import "org-dartlang-test:///lib.dart";
+
+  abstract class _Adaptor&RenderFoo&LibMixin extends obj::RenderFoo implements lib::LibMixin /*isAnonymousMixin,isEliminatedMixin*/  {
+    synthetic constructor •() → main::_Adaptor&RenderFoo&LibMixin*
+      : super obj::RenderFoo::•()
+      ;
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ constraints() → obj::Constraints*; -> obj::RenderObject::constraints
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ renderObject() → obj::RenderObject*; -> obj::RenderObject::renderObject
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator /* from org-dartlang-test:///lib.dart */ ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method /* from org-dartlang-test:///lib.dart */ noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get /* from org-dartlang-test:///lib.dart */ runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+  class Adaptor extends main::_Adaptor&RenderFoo&LibMixin {
+    synthetic constructor •() → main::Adaptor*
+      : super main::_Adaptor&RenderFoo&LibMixin::•()
+      ;
+  }
+  class AdaptorElement extends obj::RenderObject {
+    synthetic constructor •() → main::AdaptorElement*
+      : super obj::RenderObject::•()
+      ;
+    get renderObject() → main::Adaptor*
+      return super.{obj::RenderObject::renderObject} as{TypeError} main::Adaptor*;
+    method foo() → void {
+      dart.core::print(invalid-expression "org-dartlang-test:///main.dart:9:36: Error: The getter 'axis' isn't defined for the class 'Constraints'.\n - 'Constraints' is from 'package:flutter/object.dart' ('org-dartlang-test:///flutter/object.dart').\nTry correcting the name to the name of an existing getter, or defining a getter or field named 'axis'.\n    print(renderObject.constraints.axis);\n                                   ^^^^");
+    }
+    abstract member-signature get constraints() → obj::Constraints*; -> obj::RenderObject::constraints
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect
index 6ad0475..f93c1a3 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect
@@ -9,7 +9,7 @@
     @#C3
     static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
     @#C3
-    constructor #fromPointer(dynamic #pointer) → dynamic
+    constructor #fromTypedDataBase(dynamic #pointer) → dynamic
       : super dart.ffi::Struct::_fromPointer(#pointer)
       ;
     static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect
index 0baac00..466b63f 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect
@@ -9,7 +9,7 @@
     @#C3
     static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
     @#C3
-    constructor #fromPointer(dynamic #pointer) → dynamic
+    constructor #fromTypedDataBase(dynamic #pointer) → dynamic
       : super dart.ffi::Struct::_fromPointer(#pointer)
       ;
     static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect
index a3cbec1..5d79437 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect
@@ -9,7 +9,7 @@
     @#C3
     static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
     @#C3
-    constructor #fromPointer(dynamic #pointer) → dynamic
+    constructor #fromTypedDataBase(dynamic #pointer) → dynamic
       : super dart.ffi::Struct::_fromPointer(#pointer)
       ;
     static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_issue_66122.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_issue_66122.yaml.world.1.expect
index 04687de..83dfce6 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_issue_66122.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_issue_66122.yaml.world.1.expect
@@ -6,6 +6,7 @@
   abstract class AfterLayoutMixin<T extends fra::StatefulWidget* = fra::StatefulWidget*> extends fra::State<aft::AfterLayoutMixin::T*> /*isMixinDeclaration*/  {
     abstract member-signature get _widget() → aft::AfterLayoutMixin::T*; -> fra::State::_widget
     abstract member-signature set _widget(generic-covariant-impl aft::AfterLayoutMixin::T* value) → void; -> fra::State::_widget
+    abstract member-signature method toString() → dart.core::String*; -> fra::_State&Object&Diagnosticable::toString
     abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
     abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
@@ -23,6 +24,8 @@
     const synthetic constructor •() → fra::_State&Object&Diagnosticable
       : super dart.core::Object::•()
       ;
+    mixin-super-stub method toString() → dart.core::String
+      return super.{fra::Diagnosticable::toString}();
   }
   abstract class State<T extends fra::StatefulWidget = fra::StatefulWidget> extends fra::_State&Object&Diagnosticable {
     generic-covariant-impl field fra::State::T? _widget = null;
@@ -66,6 +69,7 @@
       ;
     abstract member-signature get _widget() → main::HotReloadIssue*; -> fra::State::_widget
     abstract member-signature set _widget(generic-covariant-impl main::HotReloadIssue* value) → void; -> fra::State::_widget
+    abstract member-signature method toString() → dart.core::String*; -> fra::_State&Object&Diagnosticable::toString
     abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
     abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_issue_66122.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_issue_66122.yaml.world.2.expect
index f4a141b..7e07afc 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_issue_66122.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_issue_66122.yaml.world.2.expect
@@ -6,6 +6,7 @@
   abstract class AfterLayoutMixin<T extends fra::StatefulWidget* = fra::StatefulWidget*> extends fra::State<aft::AfterLayoutMixin::T*> /*isMixinDeclaration*/  {
     abstract member-signature get _widget() → aft::AfterLayoutMixin::T*; -> fra::State::_widget
     abstract member-signature set _widget(generic-covariant-impl aft::AfterLayoutMixin::T* value) → void; -> fra::State::_widget
+    abstract member-signature method toString() → dart.core::String*; -> fra::_State&Object&Diagnosticable::toString
     abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
     abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
@@ -23,6 +24,8 @@
     const synthetic constructor •() → fra::_State&Object&Diagnosticable
       : super dart.core::Object::•()
       ;
+    mixin-super-stub method toString() → dart.core::String
+      return super.{fra::Diagnosticable::toString}();
   }
   abstract class State<T extends fra::StatefulWidget = fra::StatefulWidget> extends fra::_State&Object&Diagnosticable {
     generic-covariant-impl field fra::State::T? _widget = null;
@@ -64,6 +67,13 @@
     synthetic constructor •() → main::__HotReloadIssueState&State&AfterLayoutMixin*
       : super fra::State::•()
       ;
+    abstract mixin-stub get _widget() → main::HotReloadIssue*; -> aft::AfterLayoutMixin::_widget
+    abstract mixin-stub set _widget(generic-covariant-impl main::HotReloadIssue* value) → void; -> aft::AfterLayoutMixin::_widget
+    abstract mixin-stub method toString() → dart.core::String*; -> aft::AfterLayoutMixin::toString
+    abstract mixin-stub operator ==(dynamic other) → dart.core::bool*; -> aft::AfterLayoutMixin::==
+    abstract mixin-stub get hashCode() → dart.core::int*; -> aft::AfterLayoutMixin::hashCode
+    abstract mixin-stub method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> aft::AfterLayoutMixin::noSuchMethod
+    abstract mixin-stub get runtimeType() → dart.core::Type*; -> aft::AfterLayoutMixin::runtimeType
   }
   class _HotReloadIssueState extends main::__HotReloadIssueState&State&AfterLayoutMixin {
     synthetic constructor •() → main::_HotReloadIssueState*
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.1.expect
index d40aeb92..d4fdb52 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.1.expect
@@ -45,7 +45,7 @@
       return #C7;
   }
   class Bar extends fra::Widget /*hasConstConstructor*/  {
-    static field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
+    static final field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
     const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
@@ -53,7 +53,7 @@
       let dynamic #redirecting_factory = foo::Bar::_ in invalid-expression;
   }
   class Baz extends fra::Widget /*hasConstConstructor*/  {
-    static field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
+    static final field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
     const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.2.expect
index ec1cec8..5db0fd8 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.2.expect
@@ -45,7 +45,7 @@
       return #C7;
   }
   class Bar extends fra::Widget /*hasConstConstructor*/  {
-    static field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
+    static final field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
     const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
@@ -53,7 +53,7 @@
       let dynamic #redirecting_factory = foo::Bar::_ in invalid-expression;
   }
   class Baz extends fra::Widget /*hasConstConstructor*/  {
-    static field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
+    static final field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
     const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.3.expect
index d40aeb92..d4fdb52 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.3.expect
@@ -45,7 +45,7 @@
       return #C7;
   }
   class Bar extends fra::Widget /*hasConstConstructor*/  {
-    static field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
+    static final field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isLegacy*/;
     const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
@@ -53,7 +53,7 @@
       let dynamic #redirecting_factory = foo::Bar::_ in invalid-expression;
   }
   class Baz extends fra::Widget /*hasConstConstructor*/  {
-    static field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
+    static final field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isLegacy*/;
     const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml
index 3cf6bc9..2620942c 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml
@@ -11,11 +11,12 @@
       main.dart: |
         // The space makes the scheme invalid -- this causes Uri.parse to throw.
         part ' package:foo/bar.dart';
-    expectedLibraryCount: 2
+    expectedLibraryCount: 1
     errors: true
   - entry: main.dart
     errors: false
     worldType: updated
+    checkInvalidatedFiles: false
     invalidate:
       - main.dart
     sources:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.1.expect
index 38a3f82..8763205 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml.world.1.expect
@@ -1,5 +1,12 @@
 main = <No Member>;
 library from "org-dartlang-malformed-uri:?+package%3Afoo%2Fbar.dart" as ?+p {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:2:6: Error: Expected a URI.
+// part ' package:foo/bar.dart';
+//      ^
+//
 
 }
 library from "org-dartlang-test:///main.dart" as main {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml
new file mode 100644
index 0000000..a77a588
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml
@@ -0,0 +1,22 @@
+# 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.md file.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    errors: true
+    sources:
+      main.dart: |
+        part '$foo';
+        main() {}
+    expectedLibraryCount: 1
+
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    checkInvalidatedFiles: false
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml.world.1.expect
new file mode 100644
index 0000000..144eef3
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml.world.1.expect
@@ -0,0 +1,23 @@
+main = main::main;
+library from "org-dartlang-malformed-uri:bad5" as bad5 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Expected a URI.
+// part '$foo';
+//      ^
+//
+
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:7: Error: Can't use string interpolation in a URI.
+// part '$foo';
+//       ^
+//
+
+  part org-dartlang-malformed-uri:bad5;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml.world.2.expect
new file mode 100644
index 0000000..144eef3
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_uri_as_part.yaml.world.2.expect
@@ -0,0 +1,23 @@
+main = main::main;
+library from "org-dartlang-malformed-uri:bad5" as bad5 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Expected a URI.
+// part '$foo';
+//      ^
+//
+
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:7: Error: Can't use string interpolation in a URI.
+// part '$foo';
+//       ^
+//
+
+  part org-dartlang-malformed-uri:bad5;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_32366.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_32366.yaml.world.1.expect
index 4ebbef1..3cb283a 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_32366.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_32366.yaml.world.1.expect
@@ -5,7 +5,6 @@
     synthetic constructor •() → main::AIterator*
       : super dart.core::Iterator::•()
       ;
-    abstract member-signature method moveNext() → dart.core::bool*; -> dart.core::Iterator::moveNext
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
@@ -16,6 +15,7 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    abstract member-signature method moveNext() → dart.core::bool*; -> dart.core::Iterator::moveNext
   }
   class Foo extends dart.core::Object {
     final field dynamic a;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_32366.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_32366.yaml.world.2.expect
index f8aea1f..e82a2d4 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_32366.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_32366.yaml.world.2.expect
@@ -34,7 +34,6 @@
     synthetic constructor •() → main::BIterator*
       : super dart.core::Iterator::•()
       ;
-    abstract member-signature method moveNext() → dart.core::bool*; -> dart.core::Iterator::moveNext
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
@@ -45,6 +44,7 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    abstract member-signature method moveNext() → dart.core::bool*; -> dart.core::Iterator::moveNext
   }
   class Foo extends dart.core::Object {
     final field invalid-type kjsdf = null;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expect
index aca5281..d9b1730 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_41976.yaml.world.1.expect
@@ -2,7 +2,7 @@
 library from "org-dartlang-test:///foo.dart" as foo {
 
   abstract class Key extends dart.core::Object /*hasConstConstructor*/  {
-    static field dynamic _redirecting# = <dynamic>[foo::Key::•];
+    static final field dynamic _redirecting# = <dynamic>[foo::Key::•];
     const constructor empty() → foo::Key*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml
new file mode 100644
index 0000000..63f5ae4
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml
@@ -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.md file.
+
+# Reproduce a crash.
+
+type: newworld
+worlds:
+  - entry: app/main.dart
+    experiments: alternative-invalidation-strategy
+    sources:
+      app/.dart_tool/package_config.json: |
+        {
+          "configVersion": 2,
+          "packages": [
+            {
+              "name": "flutter",
+              "rootUri": "../../flutter",
+              "languageVersion": "2.12"
+            }
+          ]
+        }
+      app/main.dart: |
+        import "package:flutter/lib1.dart";
+        class _Bar extends RestorableProperty {}
+      flutter/lib1.dart: |
+        import "lib2.dart";
+        abstract class RestorableProperty extends ChangeNotifier {
+          bool _debugAssertNotDisposed() { return true; }
+        }
+      flutter/lib2.dart: |
+        class ChangeNotifier {
+          bool _debugAssertNotDisposed() { return true; }
+        }
+    expectedLibraryCount: 3
+
+  - entry: app/main.dart
+    experiments: alternative-invalidation-strategy
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - app/main.dart
+    expectedLibraryCount: 3
+    expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml.world.1.expect
new file mode 100644
index 0000000..fab130fd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml.world.1.expect
@@ -0,0 +1,47 @@
+main = <No Member>;
+library from "org-dartlang-test:///app/main.dart" as main {
+
+  import "package:flutter/lib1.dart";
+
+  class _Bar extends lib1::RestorableProperty {
+    synthetic constructor •() → main::_Bar*
+      : super lib1::RestorableProperty::•()
+      ;
+    abstract member-signature method _debugAssertNotDisposed() → dart.core::bool*; -> lib1::RestorableProperty::_debugAssertNotDisposed
+    abstract member-signature method _debugAssertNotDisposed() → dart.core::bool*; -> lib2::ChangeNotifier::_debugAssertNotDisposed
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
+library from "package:flutter/lib1.dart" as lib1 {
+
+  import "package:flutter/lib2.dart";
+
+  abstract class RestorableProperty extends lib2::ChangeNotifier {
+    synthetic constructor •() → lib1::RestorableProperty
+      : super lib2::ChangeNotifier::•()
+      ;
+    method _debugAssertNotDisposed() → dart.core::bool {
+      return true;
+    }
+  }
+}
+library from "package:flutter/lib2.dart" as lib2 {
+
+  class ChangeNotifier extends dart.core::Object {
+    synthetic constructor •() → lib2::ChangeNotifier
+      : super dart.core::Object::•()
+      ;
+    method _debugAssertNotDisposed() → dart.core::bool {
+      return true;
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml.world.2.expect
new file mode 100644
index 0000000..fab130fd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/issue_44523.yaml.world.2.expect
@@ -0,0 +1,47 @@
+main = <No Member>;
+library from "org-dartlang-test:///app/main.dart" as main {
+
+  import "package:flutter/lib1.dart";
+
+  class _Bar extends lib1::RestorableProperty {
+    synthetic constructor •() → main::_Bar*
+      : super lib1::RestorableProperty::•()
+      ;
+    abstract member-signature method _debugAssertNotDisposed() → dart.core::bool*; -> lib1::RestorableProperty::_debugAssertNotDisposed
+    abstract member-signature method _debugAssertNotDisposed() → dart.core::bool*; -> lib2::ChangeNotifier::_debugAssertNotDisposed
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
+library from "package:flutter/lib1.dart" as lib1 {
+
+  import "package:flutter/lib2.dart";
+
+  abstract class RestorableProperty extends lib2::ChangeNotifier {
+    synthetic constructor •() → lib1::RestorableProperty
+      : super lib2::ChangeNotifier::•()
+      ;
+    method _debugAssertNotDisposed() → dart.core::bool {
+      return true;
+    }
+  }
+}
+library from "package:flutter/lib2.dart" as lib2 {
+
+  class ChangeNotifier extends dart.core::Object {
+    synthetic constructor •() → lib2::ChangeNotifier
+      : super dart.core::Object::•()
+      ;
+    method _debugAssertNotDisposed() → dart.core::bool {
+      return true;
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.1.expect
index 7648024..9ba33da 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.1.expect
@@ -46,7 +46,7 @@
       : super mai2::SuperClass::•()
       ;
     forwarding-stub method method(covariant dart.core::num* i) → void
-      return super.{mai2::SuperClass::method}(i);
+      return super.{mai2::Mixin::method}(i);
   }
   class Class extends mai2::_Class&SuperClass&Mixin {
     synthetic constructor •() → mai2::Class*
@@ -64,5 +64,5 @@
       ;
   }
   static method method() → dynamic
-    return new mai::SubClass::•().{mai2::_Class&SuperClass&Mixin::method}(0);
+    return new mai::SubClass::•().{mai2::_Class&SuperClass&Mixin::method}(0){(dart.core::num*) →* void};
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.2.expect
index 1fdd7b3..19afe72 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.2.expect
@@ -47,7 +47,7 @@
       : super mai2::SuperClass::•()
       ;
     forwarding-stub method method(covariant dart.core::num* i) → void
-      return super.{mai2::SuperClass::method}(i);
+      return super.{mai2::Mixin::method}(i);
   }
   class Class extends mai2::_Class&SuperClass&Mixin {
     synthetic constructor •() → mai2::Class*
@@ -65,5 +65,5 @@
       ;
   }
   static method method() → dynamic
-    return new mai::SubClass::•().{mai2::_Class&SuperClass&Mixin::method}(0);
+    return new mai::SubClass::•().{mai2::_Class&SuperClass&Mixin::method}(0){(dart.core::num*) →* void};
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.3.expect
index 7648024..9ba33da 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_application_declares.yaml.world.3.expect
@@ -46,7 +46,7 @@
       : super mai2::SuperClass::•()
       ;
     forwarding-stub method method(covariant dart.core::num* i) → void
-      return super.{mai2::SuperClass::method}(i);
+      return super.{mai2::Mixin::method}(i);
   }
   class Class extends mai2::_Class&SuperClass&Mixin {
     synthetic constructor •() → mai2::Class*
@@ -64,5 +64,5 @@
       ;
   }
   static method method() → dynamic
-    return new mai::SubClass::•().{mai2::_Class&SuperClass&Mixin::method}(0);
+    return new mai::SubClass::•().{mai2::_Class&SuperClass&Mixin::method}(0){(dart.core::num*) →* void};
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_11.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_11.yaml.world.1.expect
index 34e3fcb..5157f4f 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_11.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_11.yaml.world.1.expect
@@ -4,7 +4,7 @@
   import "org-dartlang-test:///lib2.dart";
 
   class Foo extends dart.core::Object {
-    static field dynamic _redirecting# = <dynamic>[lib1::Foo::•];
+    static final field dynamic _redirecting# = <dynamic>[lib1::Foo::•];
     static factory •() → lib1::Foo*
       let dynamic #redirecting_factory = lib2::Bar::• in invalid-expression;
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_11.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_11.yaml.world.2.expect
index eda724f..7eec56c 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_11.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_11.yaml.world.2.expect
@@ -4,7 +4,7 @@
   import "org-dartlang-test:///lib2.dart";
 
   class Foo extends dart.core::Object {
-    static field dynamic _redirecting# = <dynamic>[lib1::Foo::•];
+    static final field dynamic _redirecting# = <dynamic>[lib1::Foo::•];
     static factory •() → lib1::Foo*
       let dynamic #redirecting_factory = lib2::Bar::• in invalid-expression;
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_16.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_16.yaml.world.1.expect
index 0e957f8..724237f 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_16.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_16.yaml.world.1.expect
@@ -37,7 +37,7 @@
     no-such-method-forwarder method /* from org-dartlang-test:///lib1.dart */ method() → void
       return this.{main::Foo1::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
     no-such-method-forwarder set /* from org-dartlang-test:///lib1.dart */ setter(dart.core::bool* b) → void
-      return this.{main::Foo1::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(<dynamic>[b]), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
+      return this.{main::Foo1::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(b)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
   }
   class Foo2 extends dart.core::Object implements lib1::Bar {
     synthetic constructor •() → main::Foo2*
@@ -62,9 +62,9 @@
     no-such-method-forwarder method /* from org-dartlang-test:///lib1.dart */ method() → void
       return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
     no-such-method-forwarder set /* from org-dartlang-test:///lib1.dart */ setter(dart.core::bool* b) → void
-      return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(<dynamic>[b]), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
+      return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(b)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
     no-such-method-forwarder set /* from org-dartlang-test:///lib1.dart */ field(dart.core::bool* value) → void
-      return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C8, 2, #C2, dart.core::List::unmodifiable<dynamic>(<dynamic>[value]), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
+      return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C8, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
   }
 }
 constants  {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_16.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_16.yaml.world.2.expect
index 8675350..80df4d2 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_16.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_16.yaml.world.2.expect
@@ -37,7 +37,7 @@
     no-such-method-forwarder method /* from org-dartlang-test:///lib1.dart */ method() → void
       return this.{main::Foo1::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
     no-such-method-forwarder set /* from org-dartlang-test:///lib1.dart */ setter(dart.core::bool* b) → void
-      return this.{main::Foo1::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(<dynamic>[b]), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
+      return this.{main::Foo1::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(b)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
   }
   class Foo2 extends dart.core::Object implements lib1::Bar {
     synthetic constructor •() → main::Foo2*
@@ -62,9 +62,9 @@
     no-such-method-forwarder method /* from org-dartlang-test:///lib1.dart */ method() → void
       return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
     no-such-method-forwarder set /* from org-dartlang-test:///lib1.dart */ setter(dart.core::bool* b) → void
-      return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(<dynamic>[b]), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
+      return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(b)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
     no-such-method-forwarder set /* from org-dartlang-test:///lib1.dart */ field(dart.core::bool* value) → void
-      return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C8, 2, #C2, dart.core::List::unmodifiable<dynamic>(<dynamic>[value]), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
+      return this.{main::Foo2::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C8, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4)));
   }
 }
 constants  {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
index 4547b87..f1541bb 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
@@ -8,40 +8,9 @@
       : super dart.core::Object::•()
       ;
     abstract member-signature get length() → dart.core::int*; -> dart.core::List::length
+    abstract member-signature set length(dart.core::int* newLength) → void; -> dart.core::List::length
     abstract member-signature operator [](dart.core::int* index) → dart.core::int*; -> dart.core::List::[]
     abstract member-signature operator []=(dart.core::int* index, generic-covariant-impl dart.core::int* value) → void; -> dart.core::List::[]=
-    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ toString() → dart.core::String
-      return dart.collection::IterableBase::iterableToFullString(this, "[", "]");
-    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
-    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
-    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
-    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
-    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
-    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
-    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
-    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
-    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
-    abstract member-signature set length(dart.core::int* newLength) → void; -> dart.core::List::length
-    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ iterator() → dart.core::Iterator<dart.core::int*>
-      return new dart._internal::ListIterator::•<dart.core::int*>(this);
-    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ elementAt(dart.core::int index) → dart.core::int*
-      return this.{dart.core::List::[]}(index);
-    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ followedBy(generic-covariant-impl dart.core::Iterable<dart.core::int*> other) → dart.core::Iterable<dart.core::int*>
-      return dart._internal::FollowedByIterable::firstEfficient<dart.core::int*>(this, other);
-    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ forEach((dart.core::int*) → void action) → void {
-      dart.core::int length = this.{dart.core::List::length};
-      for (dart.core::int i = 0; i.{dart.core::num::<}(length); i = i.{dart.core::num::+}(1)) {
-        action.call(this.{dart.core::List::[]}(i));
-        if(!length.{dart.core::num::==}(this.{dart.core::List::length})) {
-          throw new dart.core::ConcurrentModificationError::•(this);
-        }
-      }
-    }
-    @#C3
-    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ isEmpty() → dart.core::bool
-      return this.{dart.core::List::length}.{dart.core::num::==}(0);
-    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ isNotEmpty() → dart.core::bool
-      return !this.{dart.collection::ListMixin::isEmpty};
     get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ first() → dart.core::int* {
       if(this.{dart.core::List::length}.{dart.core::num::==}(0))
         throw dart._internal::IterableElementError::noElement();
@@ -62,6 +31,26 @@
         throw dart._internal::IterableElementError::noElement();
       this.{dart.core::List::[]=}(this.{dart.core::List::length}.{dart.core::num::-}(1), value);
     }
+    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ iterator() → dart.core::Iterator<dart.core::int*>
+      return new dart._internal::ListIterator::•<dart.core::int*>(this);
+    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ elementAt(dart.core::int index) → dart.core::int*
+      return this.{dart.core::List::[]}(index);
+    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ followedBy(generic-covariant-impl dart.core::Iterable<dart.core::int*> other) → dart.core::Iterable<dart.core::int*>
+      return dart._internal::FollowedByIterable::firstEfficient<dart.core::int*>(this, other);
+    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ forEach((dart.core::int*) → void action) → void {
+      dart.core::int length = this.{dart.core::List::length};
+      for (dart.core::int i = 0; i.{dart.core::num::<}(length); i = i.{dart.core::num::+}(1)) {
+        action.call(this.{dart.core::List::[]}(i));
+        if(!length.{dart.core::num::==}(this.{dart.core::List::length})) {
+          throw new dart.core::ConcurrentModificationError::•(this);
+        }
+      }
+    }
+    @#C3
+    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ isEmpty() → dart.core::bool
+      return this.{dart.core::List::length}.{dart.core::num::==}(0);
+    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ isNotEmpty() → dart.core::bool
+      return !this.{dart.collection::ListMixin::isEmpty};
     get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ single() → dart.core::int* {
       if(this.{dart.core::List::length}.{dart.core::num::==}(0))
         throw dart._internal::IterableElementError::noElement();
@@ -264,7 +253,7 @@
       this.{dart.collection::ListMixin::_filter}(test, true);
     }
     method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ _filter((dart.core::int*) → dart.core::bool test, dart.core::bool retainMatching) → void {
-      dart.core::List<dart.core::int*> retained = <dart.core::int*>[];
+      dart.core::List<dart.core::int*> retained = dart.core::_GrowableList::•<dart.core::int*>(0);
       dart.core::int length = this.{dart.core::List::length};
       for (dart.core::int i = 0; i.{dart.core::num::<}(length); i = i.{dart.core::num::+}(1)) {
         dart.core::int* element = this.{dart.core::List::[]}(i);
@@ -296,9 +285,6 @@
     method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ sort([(dart.core::int*, dart.core::int*) →? dart.core::int compare = #C2]) → void {
       dart._internal::Sort::sort<dart.core::int*>(this, let final (dart.core::int*, dart.core::int*) →? dart.core::int #t4 = compare in #t4.{dart.core::Object::==}(null) ?{(dart.core::int*, dart.core::int*) → dart.core::int} #C6 : #t4{(dart.core::int*, dart.core::int*) → dart.core::int});
     }
-    static method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ _compareAny(dynamic a, dynamic b) → dart.core::int {
-      return dart.core::Comparable::compare(a as{ForNonNullableByDefault} dart.core::Comparable<dynamic>, b as{ForNonNullableByDefault} dart.core::Comparable<dynamic>);
-    }
     method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ shuffle([dart.math::Random? random = #C2]) → void {
       random.{dart.core::Object::==}(null) ?{dart.math::Random} random = dart.math::Random::•() : null;
       if(random{dart.math::Random}.{dart.core::Object::==}(null))
@@ -525,6 +511,20 @@
     }
     get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ reversed() → dart.core::Iterable<dart.core::int*>
       return new dart._internal::ReversedListIterable::•<dart.core::int*>(this);
+    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ toString() → dart.core::String
+      return dart.collection::IterableBase::iterableToFullString(this, "[", "]");
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    static method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ _compareAny(dynamic a, dynamic b) → dart.core::int {
+      return dart.core::Comparable::compare(a as{ForNonNullableByDefault} dart.core::Comparable<dynamic>, b as{ForNonNullableByDefault} dart.core::Comparable<dynamic>);
+    }
   }
   class WithListMixin extends main::_WithListMixin&Object&ListMixin {
     field dart.core::int* length = 2;
@@ -535,57 +535,6 @@
       return index;
     operator []=(dart.core::int* index, generic-covariant-impl dart.core::int* value) → void
       return null;
-    abstract member-signature get iterator() → dart.core::Iterator<dart.core::int*>*; -> dart.collection::ListMixin::iterator
-    abstract member-signature method elementAt(dart.core::int* index) → dart.core::int*; -> dart.collection::ListMixin::elementAt
-    abstract member-signature method followedBy(generic-covariant-impl dart.core::Iterable<dart.core::int*>* other) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::followedBy
-    abstract member-signature method forEach((dart.core::int*) →* void action) → void; -> dart.collection::ListMixin::forEach
-    abstract member-signature get isEmpty() → dart.core::bool*; -> dart.collection::ListMixin::isEmpty
-    abstract member-signature get isNotEmpty() → dart.core::bool*; -> dart.collection::ListMixin::isNotEmpty
-    abstract member-signature method contains(dart.core::Object* element) → dart.core::bool*; -> dart.collection::ListMixin::contains
-    abstract member-signature method every((dart.core::int*) →* dart.core::bool* test) → dart.core::bool*; -> dart.collection::ListMixin::every
-    abstract member-signature method any((dart.core::int*) →* dart.core::bool* test) → dart.core::bool*; -> dart.collection::ListMixin::any
-    abstract member-signature method firstWhere((dart.core::int*) →* dart.core::bool* test, {generic-covariant-impl () →* dart.core::int* orElse = #C2}) → dart.core::int*; -> dart.collection::ListMixin::firstWhere
-    abstract member-signature method lastWhere((dart.core::int*) →* dart.core::bool* test, {generic-covariant-impl () →* dart.core::int* orElse = #C2}) → dart.core::int*; -> dart.collection::ListMixin::lastWhere
-    abstract member-signature method singleWhere((dart.core::int*) →* dart.core::bool* test, {generic-covariant-impl () →* dart.core::int* orElse = #C2}) → dart.core::int*; -> dart.collection::ListMixin::singleWhere
-    abstract member-signature method join([dart.core::String* separator = #C4]) → dart.core::String*; -> dart.collection::ListMixin::join
-    abstract member-signature method where((dart.core::int*) →* dart.core::bool* test) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::where
-    abstract member-signature method whereType<T extends dart.core::Object* = dynamic>() → dart.core::Iterable<main::WithListMixin::whereType::T*>*; -> dart.collection::ListMixin::whereType
-    abstract member-signature method map<T extends dart.core::Object* = dynamic>((dart.core::int*) →* main::WithListMixin::map::T* f) → dart.core::Iterable<main::WithListMixin::map::T*>*; -> dart.collection::ListMixin::map
-    abstract member-signature method expand<T extends dart.core::Object* = dynamic>((dart.core::int*) →* dart.core::Iterable<main::WithListMixin::expand::T*>* f) → dart.core::Iterable<main::WithListMixin::expand::T*>*; -> dart.collection::ListMixin::expand
-    abstract member-signature method reduce(generic-covariant-impl (dart.core::int*, dart.core::int*) →* dart.core::int* combine) → dart.core::int*; -> dart.collection::ListMixin::reduce
-    abstract member-signature method fold<T extends dart.core::Object* = dynamic>(main::WithListMixin::fold::T* initialValue, (main::WithListMixin::fold::T*, dart.core::int*) →* main::WithListMixin::fold::T* combine) → main::WithListMixin::fold::T*; -> dart.collection::ListMixin::fold
-    abstract member-signature method skip(dart.core::int* count) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::skip
-    abstract member-signature method skipWhile((dart.core::int*) →* dart.core::bool* test) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::skipWhile
-    abstract member-signature method take(dart.core::int* count) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::take
-    abstract member-signature method takeWhile((dart.core::int*) →* dart.core::bool* test) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::takeWhile
-    abstract member-signature method toList({dart.core::bool* growable = #C5}) → dart.core::List<dart.core::int*>*; -> dart.collection::ListMixin::toList
-    abstract member-signature method toSet() → dart.core::Set<dart.core::int*>*; -> dart.collection::ListMixin::toSet
-    abstract member-signature method addAll(generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable) → void; -> dart.collection::ListMixin::addAll
-    abstract member-signature method remove(dart.core::Object* element) → dart.core::bool*; -> dart.collection::ListMixin::remove
-    abstract member-signature method _closeGap(dart.core::int* start, dart.core::int* end) → void; -> dart.collection::ListMixin::_closeGap
-    abstract member-signature method removeWhere((dart.core::int*) →* dart.core::bool* test) → void; -> dart.collection::ListMixin::removeWhere
-    abstract member-signature method retainWhere((dart.core::int*) →* dart.core::bool* test) → void; -> dart.collection::ListMixin::retainWhere
-    abstract member-signature method _filter((dart.core::int*) →* dart.core::bool* test, dart.core::bool* retainMatching) → void; -> dart.collection::ListMixin::_filter
-    abstract member-signature method cast<R extends dart.core::Object* = dynamic>() → dart.core::List<main::WithListMixin::cast::R*>*; -> dart.collection::ListMixin::cast
-    abstract member-signature method sort([(dart.core::int*, dart.core::int*) →* dart.core::int* compare = #C2]) → void; -> dart.collection::ListMixin::sort
-    abstract member-signature method shuffle([dart.math::Random* random = #C2]) → void; -> dart.collection::ListMixin::shuffle
-    abstract member-signature method asMap() → dart.core::Map<dart.core::int*, dart.core::int*>*; -> dart.collection::ListMixin::asMap
-    abstract member-signature operator +(generic-covariant-impl dart.core::List<dart.core::int*>* other) → dart.core::List<dart.core::int*>*; -> dart.collection::ListMixin::+
-    abstract member-signature method sublist(dart.core::int* start, [dart.core::int* end = #C2]) → dart.core::List<dart.core::int*>*; -> dart.collection::ListMixin::sublist
-    abstract member-signature method getRange(dart.core::int* start, dart.core::int* end) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::getRange
-    abstract member-signature method removeRange(dart.core::int* start, dart.core::int* end) → void; -> dart.collection::ListMixin::removeRange
-    abstract member-signature method fillRange(dart.core::int* start, dart.core::int* end, [generic-covariant-impl dart.core::int* fill = #C2]) → void; -> dart.collection::ListMixin::fillRange
-    abstract member-signature method setRange(dart.core::int* start, dart.core::int* end, generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable, [dart.core::int* skipCount = #C7]) → void; -> dart.collection::ListMixin::setRange
-    abstract member-signature method replaceRange(dart.core::int* start, dart.core::int* end, generic-covariant-impl dart.core::Iterable<dart.core::int*>* newContents) → void; -> dart.collection::ListMixin::replaceRange
-    abstract member-signature method indexOf(generic-covariant-impl dart.core::Object* element, [dart.core::int* start = #C7]) → dart.core::int*; -> dart.collection::ListMixin::indexOf
-    abstract member-signature method indexWhere((dart.core::int*) →* dart.core::bool* test, [dart.core::int* start = #C7]) → dart.core::int*; -> dart.collection::ListMixin::indexWhere
-    abstract member-signature method lastIndexOf(generic-covariant-impl dart.core::Object* element, [dart.core::int* start = #C2]) → dart.core::int*; -> dart.collection::ListMixin::lastIndexOf
-    abstract member-signature method lastIndexWhere((dart.core::int*) →* dart.core::bool* test, [dart.core::int* start = #C2]) → dart.core::int*; -> dart.collection::ListMixin::lastIndexWhere
-    abstract member-signature method insert(dart.core::int* index, generic-covariant-impl dart.core::int* element) → void; -> dart.collection::ListMixin::insert
-    abstract member-signature method removeAt(dart.core::int* index) → dart.core::int*; -> dart.collection::ListMixin::removeAt
-    abstract member-signature method insertAll(dart.core::int* index, generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable) → void; -> dart.collection::ListMixin::insertAll
-    abstract member-signature method setAll(dart.core::int* index, generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable) → void; -> dart.collection::ListMixin::setAll
-    abstract member-signature get reversed() → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::reversed
   }
 }
 constants  {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
index 4547b87..f1541bb 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
@@ -8,40 +8,9 @@
       : super dart.core::Object::•()
       ;
     abstract member-signature get length() → dart.core::int*; -> dart.core::List::length
+    abstract member-signature set length(dart.core::int* newLength) → void; -> dart.core::List::length
     abstract member-signature operator [](dart.core::int* index) → dart.core::int*; -> dart.core::List::[]
     abstract member-signature operator []=(dart.core::int* index, generic-covariant-impl dart.core::int* value) → void; -> dart.core::List::[]=
-    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ toString() → dart.core::String
-      return dart.collection::IterableBase::iterableToFullString(this, "[", "]");
-    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
-    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
-    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
-    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
-    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
-    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
-    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
-    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
-    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
-    abstract member-signature set length(dart.core::int* newLength) → void; -> dart.core::List::length
-    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ iterator() → dart.core::Iterator<dart.core::int*>
-      return new dart._internal::ListIterator::•<dart.core::int*>(this);
-    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ elementAt(dart.core::int index) → dart.core::int*
-      return this.{dart.core::List::[]}(index);
-    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ followedBy(generic-covariant-impl dart.core::Iterable<dart.core::int*> other) → dart.core::Iterable<dart.core::int*>
-      return dart._internal::FollowedByIterable::firstEfficient<dart.core::int*>(this, other);
-    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ forEach((dart.core::int*) → void action) → void {
-      dart.core::int length = this.{dart.core::List::length};
-      for (dart.core::int i = 0; i.{dart.core::num::<}(length); i = i.{dart.core::num::+}(1)) {
-        action.call(this.{dart.core::List::[]}(i));
-        if(!length.{dart.core::num::==}(this.{dart.core::List::length})) {
-          throw new dart.core::ConcurrentModificationError::•(this);
-        }
-      }
-    }
-    @#C3
-    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ isEmpty() → dart.core::bool
-      return this.{dart.core::List::length}.{dart.core::num::==}(0);
-    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ isNotEmpty() → dart.core::bool
-      return !this.{dart.collection::ListMixin::isEmpty};
     get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ first() → dart.core::int* {
       if(this.{dart.core::List::length}.{dart.core::num::==}(0))
         throw dart._internal::IterableElementError::noElement();
@@ -62,6 +31,26 @@
         throw dart._internal::IterableElementError::noElement();
       this.{dart.core::List::[]=}(this.{dart.core::List::length}.{dart.core::num::-}(1), value);
     }
+    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ iterator() → dart.core::Iterator<dart.core::int*>
+      return new dart._internal::ListIterator::•<dart.core::int*>(this);
+    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ elementAt(dart.core::int index) → dart.core::int*
+      return this.{dart.core::List::[]}(index);
+    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ followedBy(generic-covariant-impl dart.core::Iterable<dart.core::int*> other) → dart.core::Iterable<dart.core::int*>
+      return dart._internal::FollowedByIterable::firstEfficient<dart.core::int*>(this, other);
+    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ forEach((dart.core::int*) → void action) → void {
+      dart.core::int length = this.{dart.core::List::length};
+      for (dart.core::int i = 0; i.{dart.core::num::<}(length); i = i.{dart.core::num::+}(1)) {
+        action.call(this.{dart.core::List::[]}(i));
+        if(!length.{dart.core::num::==}(this.{dart.core::List::length})) {
+          throw new dart.core::ConcurrentModificationError::•(this);
+        }
+      }
+    }
+    @#C3
+    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ isEmpty() → dart.core::bool
+      return this.{dart.core::List::length}.{dart.core::num::==}(0);
+    get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ isNotEmpty() → dart.core::bool
+      return !this.{dart.collection::ListMixin::isEmpty};
     get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ single() → dart.core::int* {
       if(this.{dart.core::List::length}.{dart.core::num::==}(0))
         throw dart._internal::IterableElementError::noElement();
@@ -264,7 +253,7 @@
       this.{dart.collection::ListMixin::_filter}(test, true);
     }
     method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ _filter((dart.core::int*) → dart.core::bool test, dart.core::bool retainMatching) → void {
-      dart.core::List<dart.core::int*> retained = <dart.core::int*>[];
+      dart.core::List<dart.core::int*> retained = dart.core::_GrowableList::•<dart.core::int*>(0);
       dart.core::int length = this.{dart.core::List::length};
       for (dart.core::int i = 0; i.{dart.core::num::<}(length); i = i.{dart.core::num::+}(1)) {
         dart.core::int* element = this.{dart.core::List::[]}(i);
@@ -296,9 +285,6 @@
     method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ sort([(dart.core::int*, dart.core::int*) →? dart.core::int compare = #C2]) → void {
       dart._internal::Sort::sort<dart.core::int*>(this, let final (dart.core::int*, dart.core::int*) →? dart.core::int #t4 = compare in #t4.{dart.core::Object::==}(null) ?{(dart.core::int*, dart.core::int*) → dart.core::int} #C6 : #t4{(dart.core::int*, dart.core::int*) → dart.core::int});
     }
-    static method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ _compareAny(dynamic a, dynamic b) → dart.core::int {
-      return dart.core::Comparable::compare(a as{ForNonNullableByDefault} dart.core::Comparable<dynamic>, b as{ForNonNullableByDefault} dart.core::Comparable<dynamic>);
-    }
     method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ shuffle([dart.math::Random? random = #C2]) → void {
       random.{dart.core::Object::==}(null) ?{dart.math::Random} random = dart.math::Random::•() : null;
       if(random{dart.math::Random}.{dart.core::Object::==}(null))
@@ -525,6 +511,20 @@
     }
     get /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ reversed() → dart.core::Iterable<dart.core::int*>
       return new dart._internal::ReversedListIterable::•<dart.core::int*>(this);
+    method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ toString() → dart.core::String
+      return dart.collection::IterableBase::iterableToFullString(this, "[", "]");
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    static method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/collection/list.dart */ _compareAny(dynamic a, dynamic b) → dart.core::int {
+      return dart.core::Comparable::compare(a as{ForNonNullableByDefault} dart.core::Comparable<dynamic>, b as{ForNonNullableByDefault} dart.core::Comparable<dynamic>);
+    }
   }
   class WithListMixin extends main::_WithListMixin&Object&ListMixin {
     field dart.core::int* length = 2;
@@ -535,57 +535,6 @@
       return index;
     operator []=(dart.core::int* index, generic-covariant-impl dart.core::int* value) → void
       return null;
-    abstract member-signature get iterator() → dart.core::Iterator<dart.core::int*>*; -> dart.collection::ListMixin::iterator
-    abstract member-signature method elementAt(dart.core::int* index) → dart.core::int*; -> dart.collection::ListMixin::elementAt
-    abstract member-signature method followedBy(generic-covariant-impl dart.core::Iterable<dart.core::int*>* other) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::followedBy
-    abstract member-signature method forEach((dart.core::int*) →* void action) → void; -> dart.collection::ListMixin::forEach
-    abstract member-signature get isEmpty() → dart.core::bool*; -> dart.collection::ListMixin::isEmpty
-    abstract member-signature get isNotEmpty() → dart.core::bool*; -> dart.collection::ListMixin::isNotEmpty
-    abstract member-signature method contains(dart.core::Object* element) → dart.core::bool*; -> dart.collection::ListMixin::contains
-    abstract member-signature method every((dart.core::int*) →* dart.core::bool* test) → dart.core::bool*; -> dart.collection::ListMixin::every
-    abstract member-signature method any((dart.core::int*) →* dart.core::bool* test) → dart.core::bool*; -> dart.collection::ListMixin::any
-    abstract member-signature method firstWhere((dart.core::int*) →* dart.core::bool* test, {generic-covariant-impl () →* dart.core::int* orElse = #C2}) → dart.core::int*; -> dart.collection::ListMixin::firstWhere
-    abstract member-signature method lastWhere((dart.core::int*) →* dart.core::bool* test, {generic-covariant-impl () →* dart.core::int* orElse = #C2}) → dart.core::int*; -> dart.collection::ListMixin::lastWhere
-    abstract member-signature method singleWhere((dart.core::int*) →* dart.core::bool* test, {generic-covariant-impl () →* dart.core::int* orElse = #C2}) → dart.core::int*; -> dart.collection::ListMixin::singleWhere
-    abstract member-signature method join([dart.core::String* separator = #C4]) → dart.core::String*; -> dart.collection::ListMixin::join
-    abstract member-signature method where((dart.core::int*) →* dart.core::bool* test) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::where
-    abstract member-signature method whereType<T extends dart.core::Object* = dynamic>() → dart.core::Iterable<main::WithListMixin::whereType::T*>*; -> dart.collection::ListMixin::whereType
-    abstract member-signature method map<T extends dart.core::Object* = dynamic>((dart.core::int*) →* main::WithListMixin::map::T* f) → dart.core::Iterable<main::WithListMixin::map::T*>*; -> dart.collection::ListMixin::map
-    abstract member-signature method expand<T extends dart.core::Object* = dynamic>((dart.core::int*) →* dart.core::Iterable<main::WithListMixin::expand::T*>* f) → dart.core::Iterable<main::WithListMixin::expand::T*>*; -> dart.collection::ListMixin::expand
-    abstract member-signature method reduce(generic-covariant-impl (dart.core::int*, dart.core::int*) →* dart.core::int* combine) → dart.core::int*; -> dart.collection::ListMixin::reduce
-    abstract member-signature method fold<T extends dart.core::Object* = dynamic>(main::WithListMixin::fold::T* initialValue, (main::WithListMixin::fold::T*, dart.core::int*) →* main::WithListMixin::fold::T* combine) → main::WithListMixin::fold::T*; -> dart.collection::ListMixin::fold
-    abstract member-signature method skip(dart.core::int* count) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::skip
-    abstract member-signature method skipWhile((dart.core::int*) →* dart.core::bool* test) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::skipWhile
-    abstract member-signature method take(dart.core::int* count) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::take
-    abstract member-signature method takeWhile((dart.core::int*) →* dart.core::bool* test) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::takeWhile
-    abstract member-signature method toList({dart.core::bool* growable = #C5}) → dart.core::List<dart.core::int*>*; -> dart.collection::ListMixin::toList
-    abstract member-signature method toSet() → dart.core::Set<dart.core::int*>*; -> dart.collection::ListMixin::toSet
-    abstract member-signature method addAll(generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable) → void; -> dart.collection::ListMixin::addAll
-    abstract member-signature method remove(dart.core::Object* element) → dart.core::bool*; -> dart.collection::ListMixin::remove
-    abstract member-signature method _closeGap(dart.core::int* start, dart.core::int* end) → void; -> dart.collection::ListMixin::_closeGap
-    abstract member-signature method removeWhere((dart.core::int*) →* dart.core::bool* test) → void; -> dart.collection::ListMixin::removeWhere
-    abstract member-signature method retainWhere((dart.core::int*) →* dart.core::bool* test) → void; -> dart.collection::ListMixin::retainWhere
-    abstract member-signature method _filter((dart.core::int*) →* dart.core::bool* test, dart.core::bool* retainMatching) → void; -> dart.collection::ListMixin::_filter
-    abstract member-signature method cast<R extends dart.core::Object* = dynamic>() → dart.core::List<main::WithListMixin::cast::R*>*; -> dart.collection::ListMixin::cast
-    abstract member-signature method sort([(dart.core::int*, dart.core::int*) →* dart.core::int* compare = #C2]) → void; -> dart.collection::ListMixin::sort
-    abstract member-signature method shuffle([dart.math::Random* random = #C2]) → void; -> dart.collection::ListMixin::shuffle
-    abstract member-signature method asMap() → dart.core::Map<dart.core::int*, dart.core::int*>*; -> dart.collection::ListMixin::asMap
-    abstract member-signature operator +(generic-covariant-impl dart.core::List<dart.core::int*>* other) → dart.core::List<dart.core::int*>*; -> dart.collection::ListMixin::+
-    abstract member-signature method sublist(dart.core::int* start, [dart.core::int* end = #C2]) → dart.core::List<dart.core::int*>*; -> dart.collection::ListMixin::sublist
-    abstract member-signature method getRange(dart.core::int* start, dart.core::int* end) → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::getRange
-    abstract member-signature method removeRange(dart.core::int* start, dart.core::int* end) → void; -> dart.collection::ListMixin::removeRange
-    abstract member-signature method fillRange(dart.core::int* start, dart.core::int* end, [generic-covariant-impl dart.core::int* fill = #C2]) → void; -> dart.collection::ListMixin::fillRange
-    abstract member-signature method setRange(dart.core::int* start, dart.core::int* end, generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable, [dart.core::int* skipCount = #C7]) → void; -> dart.collection::ListMixin::setRange
-    abstract member-signature method replaceRange(dart.core::int* start, dart.core::int* end, generic-covariant-impl dart.core::Iterable<dart.core::int*>* newContents) → void; -> dart.collection::ListMixin::replaceRange
-    abstract member-signature method indexOf(generic-covariant-impl dart.core::Object* element, [dart.core::int* start = #C7]) → dart.core::int*; -> dart.collection::ListMixin::indexOf
-    abstract member-signature method indexWhere((dart.core::int*) →* dart.core::bool* test, [dart.core::int* start = #C7]) → dart.core::int*; -> dart.collection::ListMixin::indexWhere
-    abstract member-signature method lastIndexOf(generic-covariant-impl dart.core::Object* element, [dart.core::int* start = #C2]) → dart.core::int*; -> dart.collection::ListMixin::lastIndexOf
-    abstract member-signature method lastIndexWhere((dart.core::int*) →* dart.core::bool* test, [dart.core::int* start = #C2]) → dart.core::int*; -> dart.collection::ListMixin::lastIndexWhere
-    abstract member-signature method insert(dart.core::int* index, generic-covariant-impl dart.core::int* element) → void; -> dart.collection::ListMixin::insert
-    abstract member-signature method removeAt(dart.core::int* index) → dart.core::int*; -> dart.collection::ListMixin::removeAt
-    abstract member-signature method insertAll(dart.core::int* index, generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable) → void; -> dart.collection::ListMixin::insertAll
-    abstract member-signature method setAll(dart.core::int* index, generic-covariant-impl dart.core::Iterable<dart.core::int*>* iterable) → void; -> dart.collection::ListMixin::setAll
-    abstract member-signature get reversed() → dart.core::Iterable<dart.core::int*>*; -> dart.collection::ListMixin::reversed
   }
 }
 constants  {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
index 6042f23..5d03f68 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
@@ -5,6 +5,7 @@
     const synthetic constructor •() → main::_A&Object&B*
       : super dart.core::Object::•()
       ;
+    method bar() → dynamic {}
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
@@ -15,7 +16,6 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
-    method bar() → dynamic {}
   }
   class A extends main::_A&Object&B {
     synthetic constructor •() → main::A*
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
index 6042f23..5d03f68 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
@@ -5,6 +5,7 @@
     const synthetic constructor •() → main::_A&Object&B*
       : super dart.core::Object::•()
       ;
+    method bar() → dynamic {}
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
@@ -15,7 +16,6 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
-    method bar() → dynamic {}
   }
   class A extends main::_A&Object&B {
     synthetic constructor •() → main::A*
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_30.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_30.yaml.world.1.expect
index 58431c8..b796916 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_30.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_30.yaml.world.1.expect
@@ -9,7 +9,7 @@
     late static field dart.core::int? field9 = 42;
     late static field dart.core::int? field10;
     late static final field dart.core::int? field11 = 42;
-    late static final field dart.core::int? field12;
+    late static final [setter] field dart.core::int? field12;
     synthetic constructor •() → main::C
       : super dart.core::Object::•()
       ;
@@ -17,7 +17,7 @@
   late static field dart.core::int? field1 = 42;
   late static field dart.core::int? field2;
   late static final field dart.core::int? field3 = 42;
-  late static final field dart.core::int? field4;
+  late static final [setter] field dart.core::int? field4;
   static method main() → dynamic {
     main::field1 = 43;
     main::field2 = 42;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_30.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_30.yaml.world.2.expect
index f93a253..4fc4b62e 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_30.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_30.yaml.world.2.expect
@@ -9,7 +9,7 @@
     late static field dart.core::int? field9 = 42;
     late static field dart.core::int? field10;
     late static final field dart.core::int? field11 = 42;
-    late static final field dart.core::int? field12;
+    late static final [setter] field dart.core::int? field12;
     synthetic constructor •() → main::C
       : super dart.core::Object::•()
       ;
@@ -17,7 +17,7 @@
   late static field dart.core::int? field1 = 42;
   late static field dart.core::int? field2;
   late static final field dart.core::int? field3 = 42;
-  late static final field dart.core::int? field4;
+  late static final [setter] field dart.core::int? field4;
   static method main() → dynamic {
     main::field1 = 44;
     main::field2 = 43;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_32.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_32.yaml.world.1.expect
index 4758b1b..6e4cb7b 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_32.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_32.yaml.world.1.expect
@@ -15,11 +15,11 @@
   late static field dart.core::int? field1 = 42;
   late static field dart.core::int? field2;
   late static final field dart.core::int? field3 = 42;
-  late static final field dart.core::int? field4;
+  late static final [setter] field dart.core::int? field4;
   late static field dart.core::int? _extension#0|field5 = 42;
   late static field dart.core::int? _extension#0|field6;
   late static final field dart.core::int? _extension#0|field7 = 42;
-  late static final field dart.core::int? _extension#0|field8;
+  late static final [setter] field dart.core::int? _extension#0|field8;
   static method main() → dynamic {
     main::field1 = 43;
     main::field2 = 42;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_32.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_32.yaml.world.2.expect
index a6ebd95..4e6c63f 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_32.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_32.yaml.world.2.expect
@@ -15,11 +15,11 @@
   late static field dart.core::int? field1 = 42;
   late static field dart.core::int? field2;
   late static final field dart.core::int? field3 = 42;
-  late static final field dart.core::int? field4;
+  late static final [setter] field dart.core::int? field4;
   late static field dart.core::int? _extension#0|field5 = 42;
   late static field dart.core::int? _extension#0|field6;
   late static final field dart.core::int? _extension#0|field7 = 42;
-  late static final field dart.core::int? _extension#0|field8;
+  late static final [setter] field dart.core::int? _extension#0|field8;
   static method main() → dynamic {
     main::field1 = 44;
     main::field2 = 43;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect
index 6ad0475..f93c1a3 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect
@@ -9,7 +9,7 @@
     @#C3
     static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
     @#C3
-    constructor #fromPointer(dynamic #pointer) → dynamic
+    constructor #fromTypedDataBase(dynamic #pointer) → dynamic
       : super dart.ffi::Struct::_fromPointer(#pointer)
       ;
     static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect
index 05ed4f7..01f4106 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect
@@ -9,7 +9,7 @@
     @#C3
     static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
     @#C3
-    constructor #fromPointer(dynamic #pointer) → dynamic
+    constructor #fromTypedDataBase(dynamic #pointer) → dynamic
       : super dart.ffi::Struct::_fromPointer(#pointer)
       ;
     static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect
index b1b1bda..2c057af 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect
@@ -9,7 +9,7 @@
     @#C3
     static final field dart.core::int* #sizeOf = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
     @#C3
-    constructor #fromPointer(dynamic #pointer) → dynamic
+    constructor #fromTypedDataBase(dynamic #pointer) → dynamic
       : super dart.ffi::Struct::_fromPointer(#pointer)
       ;
     static factory allocate(dart.core::double* x, dart.core::double* y, dart.ffi::Pointer<lib::Coordinate*>* next) → lib::Coordinate* {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect
index d9d9f57..ef7a0e0 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.1.expect
@@ -7,6 +7,9 @@
     const synthetic constructor •() → libA::_Bar&Object&Foo*
       : super dart.core::Object::•()
       ;
+    method /* from org-dartlang-test:///main.dart */ method() → dynamic {
+      dart.core::print("A");
+    }
     abstract member-signature get /* from org-dartlang-test:///main.dart */ _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method /* from org-dartlang-test:///main.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method /* from org-dartlang-test:///main.dart */ _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
@@ -17,16 +20,13 @@
     abstract member-signature method /* from org-dartlang-test:///main.dart */ toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method /* from org-dartlang-test:///main.dart */ noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get /* from org-dartlang-test:///main.dart */ runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
-    method /* from org-dartlang-test:///main.dart */ method() → dynamic {
-      dart.core::print("A");
-    }
   }
   class Bar extends libA::_Bar&Object&Foo {
     synthetic constructor •() → libA::Bar*
       : super libA::_Bar&Object&Foo::•()
       ;
     method method2() → dynamic {
-      this.{main::Foo::method}();
+      this.{libA::_Bar&Object&Foo::method}();
     }
   }
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect
index 0ee806c..bcbc356 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml.world.2.expect
@@ -7,6 +7,9 @@
     const synthetic constructor •() → libA::_Bar&Object&Foo*
       : super dart.core::Object::•()
       ;
+    method /* from org-dartlang-test:///main.dart */ method() → dynamic {
+      dart.core::print("B");
+    }
     abstract member-signature get /* from org-dartlang-test:///main.dart */ _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method /* from org-dartlang-test:///main.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method /* from org-dartlang-test:///main.dart */ _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
@@ -17,16 +20,13 @@
     abstract member-signature method /* from org-dartlang-test:///main.dart */ toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method /* from org-dartlang-test:///main.dart */ noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get /* from org-dartlang-test:///main.dart */ runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
-    method /* from org-dartlang-test:///main.dart */ method() → dynamic {
-      dart.core::print("B");
-    }
   }
   class Bar extends libA::_Bar&Object&Foo {
     synthetic constructor •() → libA::Bar*
       : super libA::_Bar&Object&Foo::•()
       ;
     method method2() → dynamic {
-      this.{main::Foo::method}();
+      this.{libA::_Bar&Object&Foo::method}();
     }
   }
 }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml
new file mode 100644
index 0000000..7ce01e9f
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml
@@ -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.md file.
+
+# Reproduce a crash.
+
+type: newworld
+trackWidgetCreation: true
+target: VM
+worlds:
+  - entry: main.dart
+    experiments: alternative-invalidation-strategy
+    sources:
+      main.dart: |
+        class Foo {
+          factory Foo.bar() {
+            return null;
+          }
+          void bar() {}
+        }
+    expectedLibraryCount: 1
+
+  - entry: main.dart
+    experiments: alternative-invalidation-strategy
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 1
+    expectsRebuildBodiesOnly: true
+
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml.world.1.expect
new file mode 100644
index 0000000..3416529
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml.world.1.expect
@@ -0,0 +1,20 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  class Foo extends dart.core::Object {
+    static factory bar() → main::Foo* {
+      return null;
+    }
+    method bar() → void {}
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml.world.2.expect
new file mode 100644
index 0000000..3416529
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter.yaml.world.2.expect
@@ -0,0 +1,20 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  class Foo extends dart.core::Object {
+    static factory bar() → main::Foo* {
+      return null;
+    }
+    method bar() → void {}
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml
new file mode 100644
index 0000000..8b31333
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml
@@ -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.md file.
+
+# Reproduce a crash.
+
+type: newworld
+trackWidgetCreation: true
+target: VM
+worlds:
+  - entry: main.dart
+    experiments: alternative-invalidation-strategy
+    sources:
+      main.dart: |
+        class Foo {
+          Foo();
+          factory Foo.bar() = Baz;
+          void bar() {}
+        }
+        class Baz extends Foo {}
+    expectedLibraryCount: 1
+
+  - entry: main.dart
+    experiments: alternative-invalidation-strategy
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 1
+    expectsRebuildBodiesOnly: true
+
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml.world.1.expect
new file mode 100644
index 0000000..47fdc2b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml.world.1.expect
@@ -0,0 +1,28 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  class Foo extends dart.core::Object {
+    static final field dynamic _redirecting# = <dynamic>[main::Foo::bar];
+    constructor •() → main::Foo*
+      : super dart.core::Object::•()
+      ;
+    static factory bar() → main::Foo*
+      let dynamic #redirecting_factory = main::Baz::• in invalid-expression;
+    method bar() → void {}
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+  class Baz extends main::Foo {
+    synthetic constructor •() → main::Baz*
+      : super main::Foo::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml.world.2.expect
new file mode 100644
index 0000000..47fdc2b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_45_flutter_prime_1.yaml.world.2.expect
@@ -0,0 +1,28 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+  class Foo extends dart.core::Object {
+    static final field dynamic _redirecting# = <dynamic>[main::Foo::bar];
+    constructor •() → main::Foo*
+      : super dart.core::Object::•()
+      ;
+    static factory bar() → main::Foo*
+      let dynamic #redirecting_factory = main::Baz::• in invalid-expression;
+    method bar() → void {}
+    abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+    abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+    abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+    abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+    abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+  class Baz extends main::Foo {
+    synthetic constructor •() → main::Baz*
+      : super main::Foo::•()
+      ;
+  }
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml
new file mode 100644
index 0000000..aba97dff
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml
@@ -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.md file.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    checkEntries: false
+    sources:
+      main.dart: |
+        part of 'lib.dart';
+        partMethod() {}
+      lib.dart: |
+        part 'main.dart';
+        main() {}
+    expectedLibraryCount: 1
+
+  - entry: main.dart
+    checkEntries: false
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 1
+
+  - entry: main.dart
+    checkEntries: false
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - lib.dart
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.1.expect
new file mode 100644
index 0000000..1d3c1ac
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.1.expect
@@ -0,0 +1,7 @@
+main = lib::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.2.expect
new file mode 100644
index 0000000..1d3c1ac
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = lib::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.3.expect
new file mode 100644
index 0000000..1d3c1ac
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_entry.yaml.world.3.expect
@@ -0,0 +1,7 @@
+main = lib::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml
new file mode 100644
index 0000000..e599398
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml
@@ -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.md file.
+
+type: newworld
+worlds:
+  - entry: package:foo/main.dart
+    checkEntries: false
+    sources:
+      .packages: |
+        foo:.
+      main.dart: |
+        part of 'lib.dart';
+        partMethod() {}
+      lib.dart: |
+        part 'main.dart';
+        main() {}
+    expectedLibraryCount: 1
+
+  - entry: package:foo/main.dart
+    checkEntries: false
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 1
+
+  - entry: package:foo/main.dart
+    checkEntries: false
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - lib.dart
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.1.expect
new file mode 100644
index 0000000..c9c3c86
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.1.expect
@@ -0,0 +1,7 @@
+main = lib::main;
+library from "package:foo/lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.2.expect
new file mode 100644
index 0000000..c9c3c86
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.2.expect
@@ -0,0 +1,7 @@
+main = lib::main;
+library from "package:foo/lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.3.expect
new file mode 100644
index 0000000..c9c3c86
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry.yaml.world.3.expect
@@ -0,0 +1,7 @@
+main = lib::main;
+library from "package:foo/lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml
new file mode 100644
index 0000000..3d91b09
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml
@@ -0,0 +1,37 @@
+# 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.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    warnings: true
+    checkEntries: false
+    sources:
+      .packages: |
+        foo:.
+      main.dart: |
+        part of 'lib.dart';
+        partMethod() {}
+      lib.dart: |
+        part 'main.dart';
+        main() {}
+    expectedLibraryCount: 1
+
+  - entry: main.dart
+    warnings: true
+    checkEntries: false
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 1
+
+  - entry: main.dart
+    warnings: true
+    checkEntries: false
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - lib.dart
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.1.expect
new file mode 100644
index 0000000..e826847
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.1.expect
@@ -0,0 +1,12 @@
+main = lib::main;
+//
+// Problems in component:
+//
+// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
+//
+library from "package:foo/lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.2.expect
new file mode 100644
index 0000000..e826847
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.2.expect
@@ -0,0 +1,12 @@
+main = lib::main;
+//
+// Problems in component:
+//
+// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
+//
+library from "package:foo/lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.3.expect
new file mode 100644
index 0000000..e826847
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_as_package_entry_2.yaml.world.3.expect
@@ -0,0 +1,12 @@
+main = lib::main;
+//
+// Problems in component:
+//
+// org-dartlang-test:///main.dart: Warning: Interpreting this as package URI, 'package:foo/main.dart'.
+//
+library from "package:foo/lib.dart" as lib {
+
+  part main.dart;
+  static method main() → dynamic {}
+  static method /* from org-dartlang-test:///main.dart */ partMethod() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml
new file mode 100644
index 0000000..4343977
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml
@@ -0,0 +1,31 @@
+# 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.md file.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    errors: true
+    sources:
+      main.dart: |
+        part 'lib.dart';
+        main() {}
+      lib.dart: |
+        methodFromLib() {}
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - lib.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.1.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.1.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.2.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.2.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.3.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of.yaml.world.3.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml
new file mode 100644
index 0000000..eacf043
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml
@@ -0,0 +1,33 @@
+# 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.md file.
+
+type: newworld
+worlds:
+  - entry: package:foo/main.dart
+    errors: true
+    sources:
+      .packages: |
+        foo:.
+      main.dart: |
+        part 'lib.dart';
+        main() {}
+      lib.dart: |
+        methodFromLib() {}
+    expectedLibraryCount: 2
+
+  - entry: package:foo/main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
+
+  - entry: package:foo/main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - lib.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.1.expect
new file mode 100644
index 0000000..fc6881c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.1.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "package:foo/lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "package:foo/main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.2.expect
new file mode 100644
index 0000000..fc6881c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.2.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "package:foo/lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "package:foo/main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.3.expect
new file mode 100644
index 0000000..fc6881c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_as_package.yaml.world.3.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "package:foo/lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "package:foo/main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml
new file mode 100644
index 0000000..a5edd21
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml
@@ -0,0 +1,34 @@
+# 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.md file.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    experiments: alternative-invalidation-strategy
+    errors: true
+    sources:
+      main.dart: |
+        part 'lib.dart';
+        main() {}
+      lib.dart: |
+        methodFromLib() {}
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    experiments: alternative-invalidation-strategy
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    experiments: alternative-invalidation-strategy
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    invalidate:
+      - lib.dart
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.1.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.1.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.2.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.2.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.3.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_experimental_invalidation.yaml.world.3.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml
new file mode 100644
index 0000000..e9c5703
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml
@@ -0,0 +1,39 @@
+# 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.md file.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    errors: true
+    sources:
+      main.dart: |
+        part 'lib.dart';
+        main() {}
+      lib.dart: |
+        methodFromLib() {}
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    errors: true
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        part 'lib.dart';
+        main() {}
+      lib.dart: |
+        methodFromLib() {}
+    expectedLibraryCount: 2
+
+  - entry: main.dart
+    errors: true
+    invalidate:
+      - lib.dart
+    sources:
+      main.dart: |
+        part 'lib.dart';
+        main() {}
+      lib.dart: |
+        methodFromLib() {}
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.1.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.1.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.2.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.2.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.3.expect
new file mode 100644
index 0000000..bf0e799
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/part_not_part_of_initialized_from_dill.yaml.world.3.expect
@@ -0,0 +1,17 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  static method methodFromLib() → dynamic {}
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:1:6: Error: Can't use 'org-dartlang-test:///lib.dart' as a part, because it has no 'part of' declaration.
+// part 'lib.dart';
+//      ^
+//
+
+  part lib.dart;
+  static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/inference/abstract_class_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/abstract_class_instantiation.dart.strong.transformed.expect
index 9318230..054a9d0 100644
--- a/pkg/front_end/testcases/inference/abstract_class_instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/abstract_class_instantiation.dart.strong.transformed.expect
@@ -50,6 +50,6 @@
 static method test() → void {
   dynamic x = throw new core::AbstractClassInstantiationError::•("C");
   dynamic y = let final core::Object* #t1 = 1 in throw new core::AbstractClassInstantiationError::•("D");
-  self::D<core::List<core::int*>*>* z = let final core::Object* #t2 = <dynamic>[] in throw new core::AbstractClassInstantiationError::•("D");
+  self::D<core::List<core::int*>*>* z = let final core::Object* #t2 = core::_GrowableList::•<dynamic>(0) in throw new core::AbstractClassInstantiationError::•("D");
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.strong.transformed.expect
index 6dba553..f79049f 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
             [yield] true;
           }
           {
-            :iterator.{core::_SyncIterator::_yieldEachIterable} = <core::num*>[3, 4.0];
+            :iterator.{core::_SyncIterator::_yieldEachIterable} = core::_GrowableList::_literal2<core::num*>(3, 4.0);
             [yield] true;
           }
         }
diff --git a/pkg/front_end/testcases/inference/bug31436.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bug31436.dart.strong.transformed.expect
index e1194d4..055a113 100644
--- a/pkg/front_end/testcases/inference/bug31436.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/bug31436.dart.strong.transformed.expect
@@ -5,12 +5,12 @@
 static method block_test() → void {
   () →* core::List<core::Object*>* g;
   g = () → core::List<core::Object*>* {
-    return <core::Object*>[3];
+    return core::_GrowableList::_literal1<core::Object*>(3);
   };
   assert(g is () →* core::List<core::Object*>*);
   assert(!(g is () →* core::List<core::int*>*));
   g.call().{core::List::add}("hello");
-  core::List<core::int*>* l = <core::int*>[3];
+  core::List<core::int*>* l = core::_GrowableList::_literal1<core::int*>(3);
   g = () → core::List<core::int*>* {
     return l;
   };
@@ -40,11 +40,11 @@
 }
 static method arrow_test() → void {
   () →* core::List<core::Object*>* g;
-  g = () → core::List<core::Object*>* => <core::Object*>[3];
+  g = () → core::List<core::Object*>* => core::_GrowableList::_literal1<core::Object*>(3);
   assert(g is () →* core::List<core::Object*>*);
   assert(!(g is () →* core::List<core::int*>*));
   g.call().{core::List::add}("hello");
-  core::List<core::int*>* l = <core::int*>[3];
+  core::List<core::int*>* l = core::_GrowableList::_literal1<core::int*>(3);
   g = () → core::List<core::int*>* => l;
   assert(g is () →* core::List<core::Object*>*);
   assert(g is () →* core::List<core::int*>*);
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bug32291.dart.strong.transformed.expect
index b8775a7..1af625e 100644
--- a/pkg/front_end/testcases/inference/bug32291.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/bug32291.dart.strong.transformed.expect
@@ -3,8 +3,8 @@
 import "dart:core" as core;
 
 static method main() → void {
-  core::List<core::List<core::String*>*>* l = <core::List<core::String*>*>[<core::String*>["hi", "world"]];
-  core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.{core::List::==}(null) ?{core::List<core::String*>*} <core::String*>[] : #t1);
+  core::List<core::List<core::String*>*>* l = core::_GrowableList::_literal1<core::List<core::String*>*>(core::_GrowableList::_literal2<core::String*>("hi", "world"));
+  core::Iterable<core::List<core::String*>*>* i1 = l.{core::Iterable::map}<core::List<core::String*>*>((core::List<core::String*>* ll) → core::List<core::String*>* => let final core::List<core::String*>* #t1 = ll in #t1.{core::List::==}(null) ?{core::List<core::String*>*} core::_GrowableList::•<core::String*>(0) : #t1);
   core::Iterable<core::int*>* i2 = i1.{core::Iterable::map}<core::int*>((core::List<core::String*>* l) → core::int* => l.{core::List::length});
   core::print(i2);
 }
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.strong.expect b/pkg/front_end/testcases/inference/bug33324.dart.strong.expect
index 5f874e7..74b0bb6 100644
--- a/pkg/front_end/testcases/inference/bug33324.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/bug33324.dart.strong.expect
@@ -4,7 +4,7 @@
 
 static method foo() → core::int* {
   core::Function* f = (dynamic x) → dynamic => x;
-  core::List<dynamic>* l = <core::String*>["bar"].{core::Iterable::map}<dynamic>(f as{TypeError} (core::String*) → dynamic).{core::Iterable::toList}();
+  core::List<dynamic>* l = <core::String*>["bar"].{core::Iterable::map}<dynamic>(f as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}();
   l.{core::List::add}(42);
   return l.{core::Iterable::first}.length as{TypeError,ForDynamic} core::int*;
 }
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect
index 5f874e7..f5164b7 100644
--- a/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
 
 static method foo() → core::int* {
   core::Function* f = (dynamic x) → dynamic => x;
-  core::List<dynamic>* l = <core::String*>["bar"].{core::Iterable::map}<dynamic>(f as{TypeError} (core::String*) → dynamic).{core::Iterable::toList}();
+  core::List<dynamic>* l = core::_GrowableList::_literal1<core::String*>("bar").{core::Iterable::map}<dynamic>(f as{TypeError} (core::String*) →* dynamic).{core::Iterable::toList}();
   l.{core::List::add}(42);
   return l.{core::Iterable::first}.length as{TypeError,ForDynamic} core::int*;
 }
diff --git a/pkg/front_end/testcases/inference/complex_predecrement.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/complex_predecrement.dart.strong.transformed.expect
index ff145dc..58d23b5 100644
--- a/pkg/front_end/testcases/inference/complex_predecrement.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/complex_predecrement.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  core::List<core::int*>* foo = <core::int*>[1, 2, 3];
+  core::List<core::int*>* foo = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
   core::print(let final core::List<core::int*>* #t1 = foo in let final core::int* #t2 = 0 in let final core::int* #t3 = #t1.{core::List::[]}(#t2).{core::num::-}(1) in let final void #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3);
 }
 
diff --git a/pkg/front_end/testcases/inference/conditional_upwards_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conditional_upwards_inference.dart.strong.transformed.expect
index c929f40..a0810b4 100644
--- a/pkg/front_end/testcases/inference/conditional_upwards_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/conditional_upwards_inference.dart.strong.transformed.expect
@@ -19,8 +19,8 @@
 }
 static method main() → dynamic {
   core::bool* b = false;
-  core::List<core::int*>* l1 = <core::int*>[1];
-  core::List<core::int*>* l2 = <core::int*>[2];
+  core::List<core::int*>* l1 = core::_GrowableList::_literal1<core::int*>(1);
+  core::List<core::int*>* l2 = core::_GrowableList::_literal1<core::int*>(2);
   self::C<core::int*>* x = new self::C::•<core::int*>(l1);
   self::C<core::int*>* y = new self::C::•<core::int*>(l2);
   self::C<core::int*>* z = new self::C::•<core::int*>(b ?{core::List<core::int*>*} l1 : l2);
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
index 39b351a..4fa520d 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
@@ -1,51 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get field1 => null;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
-//   dynamic field1;
-//           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
-//   int field1;
-//       ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set field1(value) {}
-//              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
-//   dynamic field1;
-//           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
-//   int field1;
-//       ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get field2 => null;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
-//   int field2;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
-//   dynamic field2;
-//           ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set field2(value) {}
-//              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
-//   int field2;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
-//   dynamic field2;
-//           ^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -84,13 +37,13 @@
 class B extends self::A implements self::I {
   synthetic constructor •() → self::B*
     ;
-  get field1() → invalid-type
+  get field1() → core::int*
     ;
-  get field2() → invalid-type
+  get field2() → core::int*
     ;
-  set field1(invalid-type value) → void
+  set field1(dynamic value) → void
     ;
-  set field2(invalid-type value) → void
+  set field2(dynamic value) → void
     ;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
index 537432c..24a2f0c 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
@@ -1,51 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get field1 => null;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
-//   dynamic field1;
-//           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
-//   int field1;
-//       ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set field1(value) {}
-//              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
-//   dynamic field1;
-//           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
-//   int field1;
-//       ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get field2 => null;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
-//   int field2;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
-//   dynamic field2;
-//           ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set field2(value) {}
-//              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
-//   int field2;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
-//   dynamic field2;
-//           ^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -87,11 +40,11 @@
   synthetic constructor •() → self::B*
     : super self::A::•()
     ;
-  get field1() → invalid-type
+  get field1() → core::int*
     return null;
-  get field2() → invalid-type
+  get field2() → core::int*
     return null;
-  set field1(invalid-type value) → void {}
-  set field2(invalid-type value) → void {}
+  set field1(dynamic value) → void {}
+  set field2(dynamic value) → void {}
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
index 537432c..24a2f0c 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
@@ -1,51 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get field1 => null;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
-//   dynamic field1;
-//           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
-//   int field1;
-//       ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set field1(value) {}
-//              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
-//   dynamic field1;
-//           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
-//   int field1;
-//       ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get field2 => null;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
-//   int field2;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
-//   dynamic field2;
-//           ^^^^^^
-//
-// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   set field2(value) {}
-//              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
-//   int field2;
-//       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
-//   dynamic field2;
-//           ^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -87,11 +40,11 @@
   synthetic constructor •() → self::B*
     : super self::A::•()
     ;
-  get field1() → invalid-type
+  get field1() → core::int*
     return null;
-  get field2() → invalid-type
+  get field2() → core::int*
     return null;
-  set field1(invalid-type value) → void {}
-  set field2(invalid-type value) → void {}
+  set field1(dynamic value) → void {}
+  set field2(dynamic value) → void {}
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.outline.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.outline.expect
index 9a21f6c..904fd97 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.outline.expect
@@ -1,29 +1,4 @@
 library test;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get a => null;
-//       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
-//   final I1 a = null;
-//            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
-//   final I2 a = null;
-//            ^
-//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get a => null;
-//       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
-//   final I2 a = null;
-//            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
-//   final I1 a = null;
-//            ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -80,7 +55,7 @@
 class C1 extends core::Object implements self::A, self::B {
   synthetic constructor •() → self::C1*
     ;
-  get a() → invalid-type
+  get a() → self::I2*
     ;
   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
@@ -96,7 +71,7 @@
 class C2 extends core::Object implements self::B, self::A {
   synthetic constructor •() → self::C2*
     ;
-  get a() → invalid-type
+  get a() → self::I2*
     ;
   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
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
index 28c663f..edd05fe 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
@@ -1,29 +1,4 @@
 library test;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get a => null;
-//       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
-//   final I1 a = null;
-//            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
-//   final I2 a = null;
-//            ^
-//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get a => null;
-//       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
-//   final I2 a = null;
-//            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
-//   final I1 a = null;
-//            ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -85,7 +60,7 @@
   synthetic constructor •() → self::C1*
     : super core::Object::•()
     ;
-  get a() → invalid-type
+  get a() → self::I2*
     return null;
   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
@@ -102,7 +77,7 @@
   synthetic constructor •() → self::C2*
     : super core::Object::•()
     ;
-  get a() → invalid-type
+  get a() → self::I2*
     return null;
   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
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect
index 28c663f..edd05fe 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect
@@ -1,29 +1,4 @@
 library test;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get a => null;
-//       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
-//   final I1 a = null;
-//            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
-//   final I2 a = null;
-//            ^
-//
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   get a => null;
-//       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
-//   final I2 a = null;
-//            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
-//   final I1 a = null;
-//            ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -85,7 +60,7 @@
   synthetic constructor •() → self::C1*
     : super core::Object::•()
     ;
-  get a() → invalid-type
+  get a() → self::I2*
     return null;
   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
@@ -102,7 +77,7 @@
   synthetic constructor •() → self::C2*
     : super core::Object::•()
     ;
-  get a() → invalid-type
+  get a() → self::I2*
     return null;
   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
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.outline.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.outline.expect
index 43ee8e9..19f0100 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.outline.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
index d3047a9..f8a6f85 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect
index d3047a9..f8a6f85 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.expect
index ef24c30..5cf994f 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.expect
@@ -26,3 +26,9 @@
   #C1 = 42
   #C2 = self::C<core::int*> {t:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constructors_infer_from_arguments_const.dart:
+- C. (from org-dartlang-testcase:///constructors_infer_from_arguments_const.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.transformed.expect
index ef24c30..5cf994f 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const.dart.strong.transformed.expect
@@ -26,3 +26,9 @@
   #C1 = 42
   #C2 = self::C<core::int*> {t:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constructors_infer_from_arguments_const.dart:
+- C. (from org-dartlang-testcase:///constructors_infer_from_arguments_const.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.expect
index a14060b..f64a716 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.expect
@@ -41,3 +41,10 @@
   #C1 = 0
   #C2 = self::C<core::int*> {x:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constructors_infer_from_arguments_const_with_upper_bound.dart:
+- C. (from org-dartlang-testcase:///constructors_infer_from_arguments_const_with_upper_bound.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- D. (from org-dartlang-testcase:///constructors_infer_from_arguments_const_with_upper_bound.dart:14:9)
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.transformed.expect
index a14060b..f64a716 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_const_with_upper_bound.dart.strong.transformed.expect
@@ -41,3 +41,10 @@
   #C1 = 0
   #C2 = self::C<core::int*> {x:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constructors_infer_from_arguments_const_with_upper_bound.dart:
+- C. (from org-dartlang-testcase:///constructors_infer_from_arguments_const_with_upper_bound.dart:10:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- D. (from org-dartlang-testcase:///constructors_infer_from_arguments_const_with_upper_bound.dart:14:9)
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.strong.transformed.expect
index 760a01e..48ed791 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_downwards_from_constructor.dart.strong.transformed.expect
@@ -18,8 +18,8 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  self::C<core::int*>* x = new self::C::•<core::int*>(<core::int*>[123]);
+  self::C<core::int*>* x = new self::C::•<core::int*>(core::_GrowableList::_literal1<core::int*>(123));
   self::C<core::int*>* y = x;
-  self::C<dynamic>* a = new self::C::•<dynamic>(<dynamic>[123]);
-  self::C<core::Object*>* b = new self::C::•<core::Object*>(<core::Object*>[123]);
+  self::C<dynamic>* a = new self::C::•<dynamic>(core::_GrowableList::_literal1<dynamic>(123));
+  self::C<core::Object*>* b = new self::C::•<core::Object*>(core::_GrowableList::_literal1<core::Object*>(123));
 }
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.strong.transformed.expect
index a4ae7f6..d74aad4 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_named.dart.strong.transformed.expect
@@ -19,5 +19,5 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  self::C<core::int*>* x = new self::C::named<core::int*>(<core::int*>[]);
+  self::C<core::int*>* x = new self::C::named<core::int*>(core::_GrowableList::•<core::int*>(0));
 }
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.strong.transformed.expect
index 1a362f1..fa86723 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting.dart.strong.transformed.expect
@@ -22,5 +22,5 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  self::C<core::int*>* x = new self::C::named<core::int*>(<core::int*>[42]);
+  self::C<core::int*>* x = new self::C::named<core::int*>(core::_GrowableList::_literal1<core::int*>(42));
 }
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.outline.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.outline.expect
index d1ddfdb..024beff 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class C<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::•];
+  static final field dynamic _redirecting# = <dynamic>[self::C::•];
   abstract get t() → self::C::T*;
   abstract set t(generic-covariant-impl self::C::T* x) → void;
   static factory •<T extends core::Object* = dynamic>(self::C::•::T* t) → self::C<self::C::•::T*>*
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.strong.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.strong.expect
index 431d27e..d10efba 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class C<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::•];
+  static final field dynamic _redirecting# = <dynamic>[self::C::•];
   abstract get t() → self::C::T*;
   abstract set t(generic-covariant-impl self::C::T* x) → void;
   static factory •<T extends core::Object* = dynamic>(self::C::•::T* t) → self::C<self::C::•::T*>*
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.strong.transformed.expect
index 715e434..381acf8 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class C<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::•];
+  static final field dynamic _redirecting# = <dynamic>[self::C::•];
   abstract get t() → self::C::T*;
   abstract set t(generic-covariant-impl self::C::T* x) → void;
   static factory •<T extends core::Object* = dynamic>(self::C::•::T* t) → self::C<self::C::•::T*>*
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.outline.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.outline.expect
index f616186..9f89adf 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class C<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::•];
+  static final field dynamic _redirecting# = <dynamic>[self::C::•];
   abstract get t() → self::C::T*;
   abstract set t(generic-covariant-impl self::C::T* x) → void;
   static factory •<T extends core::Object* = dynamic>(self::C::•::T* t) → self::C<self::C::•::T*>*
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.expect
index 522e51a..ac3f37a 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class C<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::•];
+  static final field dynamic _redirecting# = <dynamic>[self::C::•];
   abstract get t() → self::C::T*;
   abstract set t(generic-covariant-impl self::C::T* x) → void;
   static factory •<T extends core::Object* = dynamic>(self::C::•::T* t) → self::C<self::C::•::T*>*
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.transformed.expect
index c1e821e..9bae319 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_redirecting_factory_to_factory.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class C<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::•];
+  static final field dynamic _redirecting# = <dynamic>[self::C::•];
   abstract get t() → self::C::T*;
   abstract set t(generic-covariant-impl self::C::T* x) → void;
   static factory •<T extends core::Object* = dynamic>(self::C::•::T* t) → self::C<self::C::•::T*>*
diff --git a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.transformed.expect
index 41089c5..9a82bf3 100644
--- a/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downward_inference_miscellaneous.dart.strong.transformed.expect
@@ -25,7 +25,7 @@
     core::int* y = 3;
     function f(core::List<core::Map<core::int*, core::String*>*>* l) → void {}
     ;
-    f.call(<core::Map<core::int*, core::String*>*>[<core::int*, core::String*>{y: x}]);
+    f.call(core::_GrowableList::_literal1<core::Map<core::int*, core::String*>*>(<core::int*, core::String*>{y: x}));
   }
   {
     function f(core::int* x) → core::int*
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.expect
index bb4970f..5fdfe4d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.expect
@@ -57,3 +57,10 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Foo.named (from org-dartlang-testcase:///downwards_inference_annotations.dart:10:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.transformed.expect
index bb4970f..5fdfe4d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.strong.transformed.expect
@@ -57,3 +57,10 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Foo.named (from org-dartlang-testcase:///downwards_inference_annotations.dart:10:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.expect
index 65e5724..bc1bc95 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.expect
@@ -42,3 +42,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_class_members.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_class_members.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.transformed.expect
index 65e5724..bc1bc95 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.strong.transformed.expect
@@ -42,3 +42,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_class_members.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_class_members.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect
index ae4549c..21d93c9 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.expect
@@ -28,3 +28,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_for_loop_variable.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_for_loop_variable.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect
index 25d38f1..c63b4f8 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_for_loop_variable.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
   for (@#C1 core::int* i = 0; i.{core::num::<}(1); i = i.{core::num::+}(1)) {
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[0].{core::Iterable::iterator};
+    core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal1<core::int*>(0).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       @#C1 core::int* i = :sync-for-iterator.{core::Iterator::current};
       {}
@@ -33,3 +33,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_for_loop_variable.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_for_loop_variable.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect
index 850b5e9..bd79165 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.expect
@@ -27,3 +27,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_locals.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_locals.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect
index 850b5e9..bd79165 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals.dart.strong.transformed.expect
@@ -27,3 +27,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_locals.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_locals.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect
index 4d10ffe..4f025f27 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.expect
@@ -28,3 +28,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_locals_referring_to_locals.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_locals_referring_to_locals.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect
index 4d10ffe..4f025f27 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_locals_referring_to_locals.dart.strong.transformed.expect
@@ -28,3 +28,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_locals_referring_to_locals.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_locals_referring_to_locals.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect
index c34abe5..d7a402b 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.expect
@@ -39,3 +39,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_parameter.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_parameter.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect
index c34abe5..d7a402b 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter.dart.strong.transformed.expect
@@ -39,3 +39,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_parameter.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_parameter.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
index 2bd8ed8..b72210d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.expect
@@ -26,3 +26,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_parameter_local.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_parameter_local.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
index 2bd8ed8..b72210d 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_parameter_local.dart.strong.transformed.expect
@@ -26,3 +26,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_parameter_local.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_parameter_local.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
index ebb93a8..59529f1 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.expect
@@ -26,3 +26,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_type_variable_local.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_type_variable_local.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
index ebb93a8..59529f1 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_type_variable_local.dart.strong.transformed.expect
@@ -26,3 +26,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_type_variable_local.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_type_variable_local.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.expect
index 05db32f..17384f4 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.expect
@@ -24,3 +24,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_typedef.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_typedef.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.transformed.expect
index 05db32f..17384f4 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_typedef.dart.strong.transformed.expect
@@ -24,3 +24,9 @@
 constants  {
   #C1 = self::Foo {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///downwards_inference_annotations_typedef.dart:
+- Foo. (from org-dartlang-testcase:///downwards_inference_annotations_typedef.dart:9:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.strong.transformed.expect
index a30551f..7cffea5 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart.strong.transformed.expect
@@ -11,9 +11,9 @@
 
 static method test() → void {
   core::List<core::int*>* l;
-  l = <core::int*>[let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart:10:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+  l = core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_assignment_statements.dart:10:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   l = /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"];
-                                                                       ^" in "hello" as{TypeError} core::int*];
-  l = l = <core::int*>[1];
+                                                                       ^" in "hello" as{TypeError} core::int*);
+  l = l = core::_GrowableList::_literal1<core::int*>(1);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
index 1d08476..3c726ad 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
@@ -20,9 +20,9 @@
       #L1:
       {
         dynamic d;
-        [yield] let dynamic #t1 = asy::_awaitHelper(<core::int*>[d as{TypeError,ForDynamic} core::int*], :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t1 = asy::_awaitHelper(core::_GrowableList::_literal1<core::int*>(d as{TypeError,ForDynamic} core::int*), :async_op_then, :async_op_error, :async_op) in null;
         core::List<core::int*>* l0 = _in::unsafeCast<core::List<core::int*>*>(:result);
-        [yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::List<core::int*>*>(<core::int*>[d as{TypeError,ForDynamic} core::int*]), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(d as{TypeError,ForDynamic} core::int*)), :async_op_then, :async_op_error, :async_op) in null;
         core::List<core::int*>* l1 = _in::unsafeCast<core::List<core::int*>*>(:result);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.outline.expect
index daf5d03..9f2d3d5 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.outline.expect
@@ -10,7 +10,6 @@
     ;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError, () →* void onDone, core::bool* cancelOnError}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -55,6 +54,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError, () →* void onDone, core::bool* cancelOnError}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method F<T extends core::Object* = dynamic>() → self::F::T*
   ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.expect
index 503c83f..0887aa4 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.expect
@@ -10,7 +10,6 @@
     return null;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen = #C1, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel = #C1}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -55,6 +54,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method F<T extends core::Object* = dynamic>() → self::F::T*
   return null;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
index 313ed02..7754fb8 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
@@ -11,7 +11,6 @@
     return null;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen = #C1, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel = #C1}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -56,6 +55,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method F<T extends core::Object* = dynamic>() → self::F::T*
   return null;
@@ -255,21 +255,21 @@
       #L7:
       {
         {
-          core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+          core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             core::int* x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          core::Iterator<core::num*>* :sync-for-iterator = <core::num*>[1, 2, 3].{core::Iterable::iterator};
+          core::Iterator<core::num*>* :sync-for-iterator = core::_GrowableList::_literal3<core::num*>(1, 2, 3).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             core::num* x = :sync-for-iterator.{core::Iterator::current};
             {}
           }
         }
         {
-          core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3].{core::Iterable::iterator};
+          core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator};
           for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
             core::int* x = :sync-for-iterator.{core::Iterator::current};
             {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.transformed.expect
index c66599a..dd5383b 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.transformed.expect
@@ -36,5 +36,5 @@
 static field self::A* t1 = let final self::A* #t1 = new self::A::•() in block {
   #t1.{self::A::b} = new self::B::•<core::int*>(1);
 } =>#t1;
-static field core::List<self::B<core::int*>*>* t2 = <self::B<core::int*>*>[new self::B::•<core::int*>(2)];
+static field core::List<self::B<core::int*>*>* t2 = core::_GrowableList::_literal1<self::B<core::int*>*>(new self::B::•<core::int*>(2));
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.strong.transformed.expect
index 69f8074..425c3c2 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level_2.dart.strong.transformed.expect
@@ -17,5 +17,5 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::A<core::int*>*>* t1 = <self::A<core::int*>*>[new self::A::•<core::int*>(1)];
+static field core::List<self::A<core::int*>*>* t1 = core::_GrowableList::_literal1<self::A<core::int*>*>(new self::A::•<core::int*>(1));
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.strong.transformed.expect
index 0ef4029..061bac6 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart.strong.transformed.expect
@@ -116,46 +116,46 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method test() → void {
-  new self::F0::•(<core::int*>[]);
-  new self::F0::•(<core::int*>[3]);
-  new self::F0::•(<core::int*>[let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:32:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+  new self::F0::•(core::_GrowableList::•<core::int*>(0));
+  new self::F0::•(core::_GrowableList::_literal1<core::int*>(3));
+  new self::F0::•(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:32:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]);
-                                                                       ^" in "hello" as{TypeError} core::int*]);
-  new self::F0::•(<core::int*>[let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:34:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                       ^" in "hello" as{TypeError} core::int*));
+  new self::F0::•(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:34:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                               ^" in "hello" as{TypeError} core::int*, 3]);
-  new self::F1::•(a: <core::int*>[]);
-  new self::F1::•(a: <core::int*>[3]);
-  new self::F1::•(a: <core::int*>[let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:41:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*, 3));
+  new self::F1::•(a: core::_GrowableList::•<core::int*>(0));
+  new self::F1::•(a: core::_GrowableList::_literal1<core::int*>(3));
+  new self::F1::•(a: core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:41:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"
-                                               ^" in "hello" as{TypeError} core::int*]);
-  new self::F1::•(a: <core::int*>[let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:44:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*));
+  new self::F1::•(a: core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:44:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                               ^" in "hello" as{TypeError} core::int*, 3]);
-  new self::F2::•(<core::int*>[]);
-  new self::F2::•(<core::int*>[3]);
-  new self::F2::•(<core::int*>[let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:51:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*, 3));
+  new self::F2::•(core::_GrowableList::•<core::int*>(0));
+  new self::F2::•(core::_GrowableList::_literal1<core::int*>(3));
+  new self::F2::•(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:51:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]);
-                                                                       ^" in "hello" as{TypeError} core::int*]);
-  new self::F2::•(<core::int*>[let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:53:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                       ^" in "hello" as{TypeError} core::int*));
+  new self::F2::•(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:53:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                               ^" in "hello" as{TypeError} core::int*, 3]);
-  new self::F3::•(<core::Iterable<core::int*>*>[]);
-  new self::F3::•(<core::Iterable<core::int*>*>[<core::int*>[3]]);
-  new self::F3::•(<core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:62:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*, 3));
+  new self::F3::•(core::_GrowableList::•<core::Iterable<core::int*>*>(0));
+  new self::F3::•(core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F3::•(core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:62:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]
-                                                                     ^" in "hello" as{TypeError} core::int*]]);
-  new self::F3::•(<core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:65:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*)));
+  new self::F3::•(core::_GrowableList::_literal2<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:65:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"],
-                                                                     ^" in "hello" as{TypeError} core::int*], <core::int*>[3]]);
-  new self::F4::•(a: <core::Iterable<core::int*>*>[]);
-  new self::F4::•(a: <core::Iterable<core::int*>*>[<core::int*>[3]]);
-  new self::F4::•(a: <core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:74:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*), core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F4::•(a: core::_GrowableList::•<core::Iterable<core::int*>*>(0));
+  new self::F4::•(a: core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F4::•(a: core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:74:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]
-                                                                     ^" in "hello" as{TypeError} core::int*]]);
-  new self::F4::•(a: <core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:77:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*)));
+  new self::F4::•(a: core::_GrowableList::_literal2<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_constructor_arguments_infer_downwards.dart:77:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"],
-                                                                     ^" in "hello" as{TypeError} core::int*], <core::int*>[3]]);
+                                                                     ^" in "hello" as{TypeError} core::int*), core::_GrowableList::_literal1<core::int*>(3)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.strong.transformed.expect
index 50c0c51..e29bda1 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart.strong.transformed.expect
@@ -51,46 +51,46 @@
 static method f3(core::Iterable<core::Iterable<core::int*>*>* a) → void {}
 static method f4({core::Iterable<core::Iterable<core::int*>*>* a = #C1}) → void {}
 static method test() → void {
-  self::f0(<core::int*>[]);
-  self::f0(<core::int*>[3]);
-  self::f0(<core::int*>[let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:16:71: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+  self::f0(core::_GrowableList::•<core::int*>(0));
+  self::f0(core::_GrowableList::_literal1<core::int*>(3));
+  self::f0(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:16:71: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   f0(/*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]);
-                                                                      ^" in "hello" as{TypeError} core::int*]);
-  self::f0(<core::int*>[let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:17:71: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                      ^" in "hello" as{TypeError} core::int*));
+  self::f0(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:17:71: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   f0(/*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\", 3]);
-                                                                      ^" in "hello" as{TypeError} core::int*, 3]);
-  self::f1(a: <core::int*>[]);
-  self::f1(a: <core::int*>[3]);
-  self::f1(a: <core::int*>[let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:21:74: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                      ^" in "hello" as{TypeError} core::int*, 3));
+  self::f1(a: core::_GrowableList::•<core::int*>(0));
+  self::f1(a: core::_GrowableList::_literal1<core::int*>(3));
+  self::f1(a: core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:21:74: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   f1(a: /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]);
-                                                                         ^" in "hello" as{TypeError} core::int*]);
-  self::f1(a: <core::int*>[let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:23:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                         ^" in "hello" as{TypeError} core::int*));
+  self::f1(a: core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:23:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                               ^" in "hello" as{TypeError} core::int*, 3]);
-  self::f2(<core::int*>[]);
-  self::f2(<core::int*>[3]);
-  self::f2(<core::int*>[let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:29:71: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*, 3));
+  self::f2(core::_GrowableList::•<core::int*>(0));
+  self::f2(core::_GrowableList::_literal1<core::int*>(3));
+  self::f2(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:29:71: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   f2(/*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]);
-                                                                      ^" in "hello" as{TypeError} core::int*]);
-  self::f2(<core::int*>[let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:30:71: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                      ^" in "hello" as{TypeError} core::int*));
+  self::f2(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:30:71: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   f2(/*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\", 3]);
-                                                                      ^" in "hello" as{TypeError} core::int*, 3]);
-  self::f3(<core::Iterable<core::int*>*>[]);
-  self::f3(<core::Iterable<core::int*>*>[<core::int*>[3]]);
-  self::f3(<core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:37:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                      ^" in "hello" as{TypeError} core::int*, 3));
+  self::f3(core::_GrowableList::•<core::Iterable<core::int*>*>(0));
+  self::f3(core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3)));
+  self::f3(core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:37:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]
-                                                                     ^" in "hello" as{TypeError} core::int*]]);
-  self::f3(<core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:40:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*)));
+  self::f3(core::_GrowableList::_literal2<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:40:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"],
-                                                                     ^" in "hello" as{TypeError} core::int*], <core::int*>[3]]);
-  self::f4(a: <core::Iterable<core::int*>*>[]);
-  self::f4(a: <core::Iterable<core::int*>*>[<core::int*>[3]]);
-  self::f4(a: <core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:49:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*), core::_GrowableList::_literal1<core::int*>(3)));
+  self::f4(a: core::_GrowableList::•<core::Iterable<core::int*>*>(0));
+  self::f4(a: core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3)));
+  self::f4(a: core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:49:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]
-                                                                     ^" in "hello" as{TypeError} core::int*]]);
-  self::f4(a: <core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:52:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*)));
+  self::f4(a: core::_GrowableList::_literal2<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_arguments_infer_downwards.dart:52:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"],
-                                                                     ^" in "hello" as{TypeError} core::int*], <core::int*>[3]]);
+                                                                     ^" in "hello" as{TypeError} core::int*), core::_GrowableList::_literal1<core::int*>(3)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.transformed.expect
index 4e084a6..2dba555 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart.strong.transformed.expect
@@ -87,18 +87,18 @@
   }
   {
     (core::int*) →* core::List<core::String*>* l0 = (core::int* x) → Null => null;
-    (core::int*) →* core::List<core::String*>* l1 = (core::int* x) → core::List<core::String*>* => <core::String*>["hello"];
+    (core::int*) →* core::List<core::String*>* l1 = (core::int* x) → core::List<core::String*>* => core::_GrowableList::_literal1<core::String*>("hello");
     (core::int*) →* core::List<core::String*>* l2 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:42:76: Error: A value of type 'List<String> Function(String)' can't be assigned to a variable of type 'List<String> Function(int)'.
  - 'List' is from 'dart:core'.
         l2 = /*error:INVALID_ASSIGNMENT*/ /*@ returnType=List<String*>* */ (String
-                                                                           ^" in ((core::String* x) → core::List<core::String*>* => <core::String*>["hello"]) as{TypeError} (core::int*) →* core::List<core::String*>*;
-    (core::int*) →* core::List<core::String*>* l3 = (core::int* x) → core::List<core::String*>* => <core::String*>[let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:46:58: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
+                                                                           ^" in ((core::String* x) → core::List<core::String*>* => core::_GrowableList::_literal1<core::String*>("hello")) as{TypeError} (core::int*) →* core::List<core::String*>*;
+    (core::int*) →* core::List<core::String*>* l3 = (core::int* x) → core::List<core::String*>* => core::_GrowableList::_literal1<core::String*>(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:46:58: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
               /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ 3
-                                                         ^" in 3 as{TypeError} core::String*];
+                                                         ^" in 3 as{TypeError} core::String*);
     (core::int*) →* core::List<core::String*>* l4 = (core::int* x) → core::List<core::String*>* {
-      return <core::String*>[let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:50:52: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
+      return core::_GrowableList::_literal1<core::String*>(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_function_expressions.dart:50:52: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
         /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ 3
-                                                   ^" in 3 as{TypeError} core::String*];
+                                                   ^" in 3 as{TypeError} core::String*);
     };
   }
   {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.strong.transformed.expect
index 3231434..b50f945 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_function_of_t_using_the_t.dart.strong.transformed.expect
@@ -13,10 +13,10 @@
     function f<T extends core::Object* = dynamic>(T* x) → core::List<T*>*
       return null;
     <T extends core::Object* = dynamic>(T*) →* core::List<T*>* v2 = f;
-    v2 = <S extends core::Object* = dynamic>(S* x) → core::List<S*>* => <S*>[x];
+    v2 = <S extends core::Object* = dynamic>(S* x) → core::List<S*>* => core::_GrowableList::_literal1<S*>(x);
     core::Iterable<core::int*>* r = v2.call<core::int*>(42);
     core::Iterable<core::String*>* s = v2.call<core::String*>("hello");
-    core::Iterable<core::List<core::int*>*>* t = v2.call<core::List<core::int*>*>(<core::int*>[]);
+    core::Iterable<core::List<core::int*>*>* t = v2.call<core::List<core::int*>*>(core::_GrowableList::•<core::int*>(0));
     core::Iterable<core::num*>* u = v2.call<core::num*>(42);
     core::Iterable<core::num*>* v = v2.call<core::num*>(42);
   }
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.strong.transformed.expect
index 81acf78..70d6890 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_empty_list.dart.strong.transformed.expect
@@ -31,8 +31,8 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → void {
-  new self::F3::•<dynamic>(<core::Iterable<dynamic>*>[]);
-  new self::F4::•<dynamic>(a: <core::Iterable<dynamic>*>[]);
+  new self::F3::•<dynamic>(core::_GrowableList::•<core::Iterable<dynamic>*>(0));
+  new self::F4::•<dynamic>(a: core::_GrowableList::•<core::Iterable<dynamic>*>(0));
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.strong.transformed.expect
index 95c87b4..ed667a8 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart.strong.transformed.expect
@@ -116,54 +116,54 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method test() → void {
-  new self::F0::•<core::int*>(<core::int*>[]);
-  new self::F0::•<core::int*>(<core::int*>[3]);
-  new self::F0::•<core::int*>(<core::int*>[let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:32:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+  new self::F0::•<core::int*>(core::_GrowableList::•<core::int*>(0));
+  new self::F0::•<core::int*>(core::_GrowableList::_literal1<core::int*>(3));
+  new self::F0::•<core::int*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:32:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]);
-                                                                       ^" in "hello" as{TypeError} core::int*]);
-  new self::F0::•<core::int*>(<core::int*>[let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:34:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                       ^" in "hello" as{TypeError} core::int*));
+  new self::F0::•<core::int*>(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:34:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                               ^" in "hello" as{TypeError} core::int*, 3]);
-  new self::F1::•<core::int*>(a: <core::int*>[]);
-  new self::F1::•<core::int*>(a: <core::int*>[3]);
-  new self::F1::•<core::int*>(a: <core::int*>[let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:41:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*, 3));
+  new self::F1::•<core::int*>(a: core::_GrowableList::•<core::int*>(0));
+  new self::F1::•<core::int*>(a: core::_GrowableList::_literal1<core::int*>(3));
+  new self::F1::•<core::int*>(a: core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:41:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"
-                                               ^" in "hello" as{TypeError} core::int*]);
-  new self::F1::•<core::int*>(a: <core::int*>[let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:44:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*));
+  new self::F1::•<core::int*>(a: core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:44:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                               ^" in "hello" as{TypeError} core::int*, 3]);
-  new self::F2::•<core::int*>(<core::int*>[]);
-  new self::F2::•<core::int*>(<core::int*>[3]);
-  new self::F2::•<core::int*>(<core::int*>[let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:51:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*, 3));
+  new self::F2::•<core::int*>(core::_GrowableList::•<core::int*>(0));
+  new self::F2::•<core::int*>(core::_GrowableList::_literal1<core::int*>(3));
+  new self::F2::•<core::int*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:51:72: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]);
-                                                                       ^" in "hello" as{TypeError} core::int*]);
-  new self::F2::•<core::int*>(<core::int*>[let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:53:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                       ^" in "hello" as{TypeError} core::int*));
+  new self::F2::•<core::int*>(core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:53:48: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                               ^" in "hello" as{TypeError} core::int*, 3]);
-  new self::F3::•<core::int*>(<core::Iterable<core::int*>*>[]);
-  new self::F3::•<core::int*>(<core::Iterable<core::int*>*>[<core::int*>[3]]);
-  new self::F3::•<core::int*>(<core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:62:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                               ^" in "hello" as{TypeError} core::int*, 3));
+  new self::F3::•<core::int*>(core::_GrowableList::•<core::Iterable<core::int*>*>(0));
+  new self::F3::•<core::int*>(core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F3::•<core::int*>(core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:62:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]
-                                                                     ^" in "hello" as{TypeError} core::int*]]);
-  new self::F3::•<core::int*>(<core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:65:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*)));
+  new self::F3::•<core::int*>(core::_GrowableList::_literal2<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:65:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"],
-                                                                     ^" in "hello" as{TypeError} core::int*], <core::int*>[3]]);
-  new self::F4::•<core::int*>(a: <core::Iterable<core::int*>*>[]);
-  new self::F4::•<core::int*>(a: <core::Iterable<core::int*>*>[<core::int*>[3]]);
-  new self::F4::•<core::int*>(a: <core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:74:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*), core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F4::•<core::int*>(a: core::_GrowableList::•<core::Iterable<core::int*>*>(0));
+  new self::F4::•<core::int*>(a: core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F4::•<core::int*>(a: core::_GrowableList::_literal1<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:74:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"]
-                                                                     ^" in "hello" as{TypeError} core::int*]]);
-  new self::F4::•<core::int*>(a: <core::Iterable<core::int*>*>[<core::int*>[let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:77:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                                     ^" in "hello" as{TypeError} core::int*)));
+  new self::F4::•<core::int*>(a: core::_GrowableList::_literal2<core::Iterable<core::int*>*>(core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_constructor_arguments_infer_downwards.dart:77:70: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
     /*@ typeArgs=int* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"],
-                                                                     ^" in "hello" as{TypeError} core::int*], <core::int*>[3]]);
-  new self::F3::•<dynamic>(<core::Iterable<dynamic>*>[]);
-  self::F3<core::int*>* f31 = new self::F3::•<core::int*>(<core::List<core::int*>*>[<core::int*>[3]]);
-  self::F3<core::String*>* f32 = new self::F3::•<core::String*>(<core::List<core::String*>*>[<core::String*>["hello"]]);
-  self::F3<core::Object*>* f33 = new self::F3::•<core::Object*>(<core::List<core::Object*>*>[<core::String*>["hello"], <core::int*>[3]]);
-  new self::F4::•<dynamic>(a: <core::Iterable<dynamic>*>[]);
-  new self::F4::•<core::int*>(a: <core::List<core::int*>*>[<core::int*>[3]]);
-  new self::F4::•<core::String*>(a: <core::List<core::String*>*>[<core::String*>["hello"]]);
-  new self::F4::•<core::Object*>(a: <core::List<core::Object*>*>[<core::String*>["hello"], <core::int*>[3]]);
+                                                                     ^" in "hello" as{TypeError} core::int*), core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F3::•<dynamic>(core::_GrowableList::•<core::Iterable<dynamic>*>(0));
+  self::F3<core::int*>* f31 = new self::F3::•<core::int*>(core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3)));
+  self::F3<core::String*>* f32 = new self::F3::•<core::String*>(core::_GrowableList::_literal1<core::List<core::String*>*>(core::_GrowableList::_literal1<core::String*>("hello")));
+  self::F3<core::Object*>* f33 = new self::F3::•<core::Object*>(core::_GrowableList::_literal2<core::List<core::Object*>*>(core::_GrowableList::_literal1<core::String*>("hello"), core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F4::•<dynamic>(a: core::_GrowableList::•<core::Iterable<dynamic>*>(0));
+  new self::F4::•<core::int*>(a: core::_GrowableList::_literal1<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3)));
+  new self::F4::•<core::String*>(a: core::_GrowableList::_literal1<core::List<core::String*>*>(core::_GrowableList::_literal1<core::String*>("hello")));
+  new self::F4::•<core::Object*>(a: core::_GrowableList::_literal2<core::List<core::Object*>*>(core::_GrowableList::_literal1<core::String*>("hello"), core::_GrowableList::_literal1<core::int*>(3)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.transformed.expect
index 5fa06c8..bd249c6 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart.strong.transformed.expect
@@ -95,18 +95,18 @@
       return null;
     <S extends core::Object* = dynamic>(core::int*) →* core::List<core::String*>* v = f;
     v = <T extends core::Object* = dynamic>(core::int* x) → Null => null;
-    v = <T extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>* => <core::String*>["hello"];
+    v = <T extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>* => core::_GrowableList::_literal1<core::String*>("hello");
     v = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:43:75: Error: A value of type 'List<String> Function<T>(String)' can't be assigned to a variable of type 'List<String> Function<S>(int)'.
  - 'List' is from 'dart:core'.
     v = /*error:INVALID_ASSIGNMENT*/ <T> /*@ returnType=List<String*>* */ (String
-                                                                          ^" in (<T extends core::Object* = dynamic>(core::String* x) → core::List<core::String*>* => <core::String*>["hello"]) as{TypeError} <S extends core::Object* = dynamic>(core::int*) →* core::List<core::String*>*;
-    v = <T extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>* => <core::String*>[let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:46:54: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
+                                                                          ^" in (<T extends core::Object* = dynamic>(core::String* x) → core::List<core::String*>* => core::_GrowableList::_literal1<core::String*>("hello")) as{TypeError} <S extends core::Object* = dynamic>(core::int*) →* core::List<core::String*>*;
+    v = <T extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>* => core::_GrowableList::_literal1<core::String*>(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:46:54: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
           /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ 3
-                                                     ^" in 3 as{TypeError} core::String*];
+                                                     ^" in 3 as{TypeError} core::String*);
     v = <T extends core::Object* = dynamic>(core::int* x) → core::List<core::String*>* {
-      return <core::String*>[let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:50:52: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
+      return core::_GrowableList::_literal1<core::String*>(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_generic_function_expressions.dart:50:52: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
         /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ 3
-                                                   ^" in 3 as{TypeError} core::String*];
+                                                   ^" in 3 as{TypeError} core::String*);
     };
   }
   {
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.strong.transformed.expect
index cbee34a..6f8cca2 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart.strong.transformed.expect
@@ -287,12 +287,12 @@
     self::A<self::C<core::int*>*, core::String*>* a0 = new self::E::•<core::int*, core::String*>("hello");
   }
   {
-    self::A<core::int*, core::String*>* a0 = new self::F::•<core::int*, core::String*>(3, "hello", a: <core::int*>[3], b: <core::String*>["hello"]);
-    self::A<core::int*, core::String*>* a1 = new self::F::•<core::int*, core::String*>(3, "hello", a: <core::int*>[let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart:118:54: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+    self::A<core::int*, core::String*>* a0 = new self::F::•<core::int*, core::String*>(3, "hello", a: core::_GrowableList::_literal1<core::int*>(3), b: core::_GrowableList::_literal1<core::String*>("hello"));
+    self::A<core::int*, core::String*>* a1 = new self::F::•<core::int*, core::String*>(3, "hello", a: core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart:118:54: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
           /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"
-                                                     ^" in "hello" as{TypeError} core::int*], b: <core::String*>[let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart:121:54: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
+                                                     ^" in "hello" as{TypeError} core::int*), b: core::_GrowableList::_literal1<core::String*>(let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart:121:54: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
           /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ 3
-                                                     ^" in 3 as{TypeError} core::String*]);
+                                                     ^" in 3 as{TypeError} core::String*));
     self::A<core::int*, core::String*>* a2 = new self::F::named<core::int*, core::String*>(3, "hello", 3, "hello");
     self::A<core::int*, core::String*>* a3 = new self::F::named<core::int*, core::String*>(3, "hello");
     self::A<core::int*, core::String*>* a4 = new self::F::named<core::int*, core::String*>(3, "hello", let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_instance_creations_infer_downwards.dart:129:48: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.strong.transformed.expect
index fc86f60..59c3f05 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart.strong.transformed.expect
@@ -70,56 +70,56 @@
                                                                                         ^"]) → void {}
 static method main() → void {
   {
-    core::List<core::int*>* l0 = <core::int*>[];
-    core::List<core::int*>* l1 = <core::int*>[3];
-    core::List<core::int*>* l2 = <core::int*>[let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:19:50: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+    core::List<core::int*>* l0 = core::_GrowableList::•<core::int*>(0);
+    core::List<core::int*>* l1 = core::_GrowableList::_literal1<core::int*>(3);
+    core::List<core::int*>* l2 = core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:19:50: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"
-                                                 ^" in "hello" as{TypeError} core::int*];
-    core::List<core::int*>* l3 = <core::int*>[let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:22:50: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                 ^" in "hello" as{TypeError} core::int*);
+    core::List<core::int*>* l3 = core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:22:50: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                                 ^" in "hello" as{TypeError} core::int*, 3];
+                                                 ^" in "hello" as{TypeError} core::int*, 3);
   }
   {
-    core::List<dynamic>* l0 = <dynamic>[];
-    core::List<dynamic>* l1 = <dynamic>[3];
-    core::List<dynamic>* l2 = <dynamic>["hello"];
-    core::List<dynamic>* l3 = <dynamic>["hello", 3];
+    core::List<dynamic>* l0 = core::_GrowableList::•<dynamic>(0);
+    core::List<dynamic>* l1 = core::_GrowableList::_literal1<dynamic>(3);
+    core::List<dynamic>* l2 = core::_GrowableList::_literal1<dynamic>("hello");
+    core::List<dynamic>* l3 = core::_GrowableList::_literal2<dynamic>("hello", 3);
   }
   {
     core::List<core::int*>* l0 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:33:61: Error: The list literal type 'List<num>' isn't of expected type 'List<int>'.
  - 'List' is from 'dart:core'.
 Change the type of the list literal or the context in which it is used.
     List<int> l0 = /*error:INVALID_CAST_LITERAL_LIST*/ <num>[];
-                                                            ^" in <core::num*>[];
+                                                            ^" in core::_GrowableList::•<core::num*>(0);
     core::List<core::int*>* l1 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:34:61: Error: The list literal type 'List<num>' isn't of expected type 'List<int>'.
  - 'List' is from 'dart:core'.
 Change the type of the list literal or the context in which it is used.
     List<int> l1 = /*error:INVALID_CAST_LITERAL_LIST*/ <num>[3];
-                                                            ^" in <core::num*>[3];
+                                                            ^" in core::_GrowableList::_literal1<core::num*>(3);
     core::List<core::int*>* l2 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:35:61: Error: The list literal type 'List<num>' isn't of expected type 'List<int>'.
  - 'List' is from 'dart:core'.
 Change the type of the list literal or the context in which it is used.
     List<int> l2 = /*error:INVALID_CAST_LITERAL_LIST*/ <num>[
-                                                            ^" in <core::num*>[let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:36:50: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
+                                                            ^" in core::_GrowableList::_literal1<core::num*>(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:36:50: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
       /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"
-                                                 ^" in "hello" as{TypeError} core::num*];
+                                                 ^" in "hello" as{TypeError} core::num*);
     core::List<core::int*>* l3 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:38:61: Error: The list literal type 'List<num>' isn't of expected type 'List<int>'.
  - 'List' is from 'dart:core'.
 Change the type of the list literal or the context in which it is used.
     List<int> l3 = /*error:INVALID_CAST_LITERAL_LIST*/ <num>[
-                                                            ^" in <core::num*>[let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:39:50: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
+                                                            ^" in core::_GrowableList::_literal2<core::num*>(let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:39:50: Error: A value of type 'String' can't be assigned to a variable of type 'num'.
       /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                                 ^" in "hello" as{TypeError} core::num*, 3];
+                                                 ^" in "hello" as{TypeError} core::num*, 3);
   }
   {
-    core::Iterable<core::int*>* i0 = <core::int*>[];
-    core::Iterable<core::int*>* i1 = <core::int*>[3];
-    core::Iterable<core::int*>* i2 = <core::int*>[let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:47:50: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+    core::Iterable<core::int*>* i0 = core::_GrowableList::•<core::int*>(0);
+    core::Iterable<core::int*>* i1 = core::_GrowableList::_literal1<core::int*>(3);
+    core::Iterable<core::int*>* i2 = core::_GrowableList::_literal1<core::int*>(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:47:50: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\"
-                                                 ^" in "hello" as{TypeError} core::int*];
-    core::Iterable<core::int*>* i3 = <core::int*>[let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:50:50: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
+                                                 ^" in "hello" as{TypeError} core::int*);
+    core::Iterable<core::int*>* i3 = core::_GrowableList::_literal2<core::int*>(let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:50:50: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
       /*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ \"hello\",
-                                                 ^" in "hello" as{TypeError} core::int*, 3];
+                                                 ^" in "hello" as{TypeError} core::int*, 3);
   }
   {
     const core::List<core::int*>* c2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_downwards.dart:58:89: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.transformed.expect
index e16a1a8..660139a 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.transformed.expect
@@ -29,11 +29,11 @@
     return null;
   abstract get assertDOf() → (core::List<(self::DartType*) →* void>*) →* (self::DartType*) →* void;
   method method((core::List<(self::DartType*) →* void>*) →* (self::DartType*) →* void assertEOf) → dynamic {
-    let final core::List<(self::DartType*) →* void>* #t1 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in this.{self::C::assertAOf}.call(#t1);
-    self::C::assertBOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
-    self::C::assertCOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
-    let final core::List<(self::DartType*) →* void>* #t2 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in this.{self::C::assertDOf}.call(#t2);
-    assertEOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
+    let final core::List<(self::DartType*) →* void>* #t1 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in this.{self::C::assertAOf}.call(#t1);
+    self::C::assertBOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
+    self::C::assertCOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
+    let final core::List<(self::DartType*) →* void>* #t2 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in this.{self::C::assertDOf}.call(#t2);
+    assertEOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
   }
   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
@@ -53,10 +53,10 @@
     ;
   abstract get assertDOf() → (core::List<(self::DartType*) →* void>*) →* (self::DartType*) →* void;
   method method((core::List<(self::DartType*) →* void>*) →* (self::DartType*) →* void assertEOf) → dynamic {
-    let final core::List<(self::DartType*) →* void>* #t3 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in this.{self::G::assertAOf}.call(#t3);
-    let final core::List<(self::DartType*) →* void>* #t4 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in this.{self::G::assertAOf}.call(#t4);
-    let final core::List<(self::DartType*) →* void>* #t5 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in this.{self::G::assertDOf}.call(#t5);
-    assertEOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
+    let final core::List<(self::DartType*) →* void>* #t3 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in this.{self::G::assertAOf}.call(#t3);
+    let final core::List<(self::DartType*) →* void>* #t4 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in this.{self::G::assertAOf}.call(#t4);
+    let final core::List<(self::DartType*) →* void>* #t5 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in this.{self::G::assertDOf}.call(#t5);
+    assertEOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
   }
   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
@@ -76,16 +76,16 @@
   return null;
 static method test() → dynamic {
   (core::List<(self::DartType*) →* void>*) →* (self::DartType*) →* void assertAOf;
-  assertAOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
-  self::assertBOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
-  self::assertCOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
-  self::C::assertBOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
-  self::C::assertCOf.call(<(self::DartType*) →* void>[self::_isInt, self::_isString]);
+  assertAOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
+  self::assertBOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
+  self::assertCOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
+  self::C::assertBOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
+  self::C::assertCOf.call(core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString));
   self::C* c;
-  let final self::C* #t6 = c in let final core::List<(self::DartType*) →* void>* #t7 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in #t6.{self::C::assertAOf}.call(#t7);
-  let final self::C* #t8 = c in let final core::List<(self::DartType*) →* void>* #t9 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in #t8.{self::C::assertDOf}.call(#t9);
+  let final self::C* #t6 = c in let final core::List<(self::DartType*) →* void>* #t7 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in #t6.{self::C::assertAOf}.call(#t7);
+  let final self::C* #t8 = c in let final core::List<(self::DartType*) →* void>* #t9 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in #t8.{self::C::assertDOf}.call(#t9);
   self::G<core::int*>* g;
-  let final self::G<core::int*>* #t10 = g in let final core::List<(self::DartType*) →* void>* #t11 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in #t10.{self::G::assertAOf}.call(#t11);
-  let final self::G<core::int*>* #t12 = g in let final core::List<(self::DartType*) →* void>* #t13 = <(self::DartType*) →* void>[self::_isInt, self::_isString] in #t12.{self::G::assertDOf}.call(#t13);
+  let final self::G<core::int*>* #t10 = g in let final core::List<(self::DartType*) →* void>* #t11 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in #t10.{self::G::assertAOf}.call(#t11);
+  let final self::G<core::int*>* #t12 = g in let final core::List<(self::DartType*) →* void>* #t13 = core::_GrowableList::_literal2<(self::DartType*) →* void>(self::_isInt, self::_isString) in #t12.{self::G::assertDOf}.call(#t13);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.outline.expect
index e2413d9..fa0d3a1 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.outline.expect
@@ -10,7 +10,6 @@
     ;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError, () →* void onDone, core::bool* cancelOnError}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -55,6 +54,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError, () →* void onDone, core::bool* cancelOnError}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method foo() → asy::Stream<core::List<core::int*>*>* async* 
   ;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.expect
index 2420358..d6d38a5 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.expect
@@ -37,7 +37,6 @@
     return null;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen = #C1, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel = #C1}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -82,6 +81,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method foo() → asy::Stream<core::List<core::int*>*>* async* {
   yield<core::int*>[];
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
index 6772134..5421bab 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
@@ -37,7 +37,6 @@
     return null;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen = #C1, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel = #C1}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -82,6 +81,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method foo() → asy::Stream<core::List<core::int*>*>* /* originally async* */ {
   asy::_AsyncStarStreamController<core::List<core::int*>*>* :controller;
@@ -97,7 +97,7 @@
       try {
         #L1:
         {
-          if(:controller.{asy::_AsyncStarStreamController::add}(<core::int*>[]))
+          if(:controller.{asy::_AsyncStarStreamController::add}(core::_GrowableList::•<core::int*>(0)))
             return null;
           else
             [yield] null;
@@ -113,7 +113,7 @@
  - 'List' is from 'dart:core'.
  - 'Stream' is from 'dart:async'.
   yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
-                                                               ^" in <dynamic>[] as{TypeError} asy::Stream<core::List<core::int*>*>*))
+                                                               ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} asy::Stream<core::List<core::int*>*>*))
             return null;
           else
             [yield] null;
@@ -151,7 +151,7 @@
  - 'List' is from 'dart:core'.
  - 'Map' is from 'dart:core'.
   yield /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
-                                                              ^" in <dynamic>[] as{TypeError} core::Map<core::int*, core::int*>*;
+                                                              ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} core::Map<core::int*, core::int*>*;
           [yield] true;
         }
         {
@@ -163,7 +163,7 @@
           [yield] true;
         }
         {
-          :iterator.{core::_SyncIterator::_yieldEachIterable} = <core::Map<core::int*, core::int*>*>[];
+          :iterator.{core::_SyncIterator::_yieldEachIterable} = core::_GrowableList::•<core::Map<core::int*, core::int*>*>(0);
           [yield] true;
         }
       }
diff --git a/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
index 99706f8..31f36c1 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
index 780ffb76..5e4f03c 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
index 3b12a3e..b811bc8 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
index f715984..dfb8161 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
index 8095cd9..2e741e8 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   asy::Future<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
index 2bb0e59..b0315bb 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   asy::Future<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
index 1b90060..d191f4c 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<core::bool*>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
index 09ef601..43a3960 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<core::bool*>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
index 97bec60..5f3d17d 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<core::bool*>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
index 947f092..91d19c76 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<core::bool*>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
index 1ea35fe..09ebce0 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   asy::Future<core::bool*>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
index 8acc631..de83970 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   asy::Future<core::bool*>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.transformed.expect
index fb4af0a..53eb93c 100644
--- a/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_downwards_method_target.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
 
 static method test() → dynamic {
   asy::Future<core::int*>* f;
-  asy::Future<core::List<core::int*>*>* b = f.{asy::Future::then}<core::List<dynamic>*>((core::int* x) → core::List<dynamic>* => <dynamic>[]).{asy::Future::whenComplete}(() → Null {}) as{TypeError} asy::Future<core::List<core::int*>*>*;
-  b = f.{asy::Future::then}<core::List<core::int*>*>((core::int* x) → core::List<core::int*>* => <core::int*>[]);
+  asy::Future<core::List<core::int*>*>* b = f.{asy::Future::then}<core::List<dynamic>*>((core::int* x) → core::List<dynamic>* => core::_GrowableList::•<dynamic>(0)).{asy::Future::whenComplete}(() → Null {}) as{TypeError} asy::Future<core::List<core::int*>*>*;
+  b = f.{asy::Future::then}<core::List<core::int*>*>((core::int* x) → core::List<core::int*>* => core::_GrowableList::•<core::int*>(0));
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.transformed.expect
index cf41d05..f4262fd 100644
--- a/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.transformed.expect
@@ -26,7 +26,7 @@
  - 'List' is from 'dart:core'.
  - 'Future' is from 'dart:async'.
       /*@returnType=FutureOr<Future<List<int*>*>*>**/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
-                                                                                                  ^" in <dynamic>[] as{TypeError} FutureOr<asy::Future<core::List<core::int*>*>*>*);
+                                                                                                  ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} FutureOr<asy::Future<core::List<core::int*>*>*>*);
   asy::Future<core::List<core::int*>*>* y = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/future_then_explicit_future.dart:16:25: Error: A value of type 'Future<Future<List<int>>>' can't be assigned to a variable of type 'Future<List<int>>'.
  - 'Future' is from 'dart:async'.
  - 'List' is from 'dart:core'.
@@ -35,7 +35,7 @@
 }
 static method m2() → dynamic {
   asy::Future<core::int*>* f;
-  asy::Future<core::List<core::int*>*>* x = f.{asy::Future::then}<core::List<core::int*>*>((core::int* x) → core::List<core::int*>* => <core::int*>[]);
+  asy::Future<core::List<core::int*>*>* x = f.{asy::Future::then}<core::List<core::int*>*>((core::int* x) → core::List<core::int*>* => core::_GrowableList::•<core::int*>(0));
   asy::Future<core::List<core::int*>*>* y = x;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
index 41975f17..ecd8f2b 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
@@ -25,13 +25,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   self::MyFuture<core::int*>* f;
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
index 31e558a..4a8f5e5 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
@@ -33,13 +33,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method main() → void {
   self::MyFuture<core::double*>* f = self::foo().{self::MyFuture::then}<core::double*>((dynamic _) → core::double* => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
index d6e485a..392a7e75 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
@@ -32,13 +32,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method main() → void {
   self::MyFuture<core::double*>* f = self::foo().{self::MyFuture::then}<core::double*>((dynamic _) → core::double* => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
index c213ce8..659d9cf 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
@@ -32,13 +32,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   asy::Future<core::double*>* f = self::foo().{asy::Future::then}<core::double*>((dynamic _) → core::double* => 2.3);
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
index 2d0d430..5fc430a 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
@@ -24,13 +24,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method g1(core::bool* x) → asy::Future<core::int*>* /* originally async */ {
   final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
index e4ad380..2ba5916 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
@@ -24,13 +24,13 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method g1(core::bool* x) → asy::Future<core::int*>* /* originally async */ {
   final asy::_Future<core::int*>* :async_future = new asy::_Future::•<core::int*>();
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
index cdf55f7..e47a237 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
@@ -31,19 +31,19 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field self::MyFuture<dynamic>* f;
 static field asy::Future<core::int*>* t1 = self::f.{self::MyFuture::then}<core::int*>((dynamic _) → asy::Future<core::int*>* => asy::Future::value<core::int*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/future_union_downwards.dart:21:47: Error: The argument type 'String' can't be assigned to the parameter type 'FutureOr<int>'.
         new /*@ typeArgs=int* */ Future.value('hi'));
                                               ^" in "hi" as{TypeError} FutureOr<core::int*>?));
-static field asy::Future<core::List<core::int*>*>* t2 = self::f.{self::MyFuture::then}<core::List<core::int*>*>((dynamic _) → core::List<core::int*>* => <core::int*>[3]);
+static field asy::Future<core::List<core::int*>*>* t2 = self::f.{self::MyFuture::then}<core::List<core::int*>*>((dynamic _) → core::List<core::int*>* => core::_GrowableList::_literal1<core::int*>(3));
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
@@ -56,7 +56,7 @@
     try {
       #L1:
       {
-        :return_value = <core::int*>[3];
+        :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -83,7 +83,7 @@
     try {
       #L2:
       {
-        :return_value = asy::Future::value<core::List<core::int*>*>(<core::int*>[3]);
+        :return_value = asy::Future::value<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3));
         break #L2;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
index 3338e9b..3e5228e 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
@@ -24,17 +24,17 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field self::MyFuture<dynamic>* f;
 static field asy::Future<core::int*>* t1 = self::f.{self::MyFuture::then}<core::int*>((dynamic _) → self::MyFuture<core::int*>* => new self::MyFuture::value<core::int*>("hi"));
-static field asy::Future<core::List<core::int*>*>* t2 = self::f.{self::MyFuture::then}<core::List<core::int*>*>((dynamic _) → core::List<core::int*>* => <core::int*>[3]);
+static field asy::Future<core::List<core::int*>*>* t2 = self::f.{self::MyFuture::then}<core::List<core::int*>*>((dynamic _) → core::List<core::int*>* => core::_GrowableList::_literal1<core::int*>(3));
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
@@ -47,7 +47,7 @@
     try {
       #L1:
       {
-        :return_value = <core::int*>[3];
+        :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -74,7 +74,7 @@
     try {
       #L2:
       {
-        :return_value = new self::MyFuture::value<core::List<core::int*>*>(<core::int*>[3]);
+        :return_value = new self::MyFuture::value<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3));
         break #L2;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
index d89cd97..b5b7c73 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
@@ -31,19 +31,19 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field asy::Future<dynamic>* f;
 static field asy::Future<core::int*>* t1 = self::f.{asy::Future::then}<core::int*>((dynamic _) → asy::Future<core::int*>* => asy::Future::value<core::int*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/future_union_downwards_3.dart:21:47: Error: The argument type 'String' can't be assigned to the parameter type 'FutureOr<int>'.
         new /*@ typeArgs=int* */ Future.value('hi'));
                                               ^" in "hi" as{TypeError} FutureOr<core::int*>?));
-static field asy::Future<core::List<core::int*>*>* t2 = self::f.{asy::Future::then}<core::List<core::int*>*>((dynamic _) → core::List<core::int*>* => <core::int*>[3]);
+static field asy::Future<core::List<core::int*>*>* t2 = self::f.{asy::Future::then}<core::List<core::int*>*>((dynamic _) → core::List<core::int*>* => core::_GrowableList::_literal1<core::int*>(3));
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
@@ -56,7 +56,7 @@
     try {
       #L1:
       {
-        :return_value = <core::int*>[3];
+        :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -83,7 +83,7 @@
     try {
       #L2:
       {
-        :return_value = asy::Future::value<core::List<core::int*>*>(<core::int*>[3]);
+        :return_value = asy::Future::value<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3));
         break #L2;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
index b7ad80a..82d9f9b 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
@@ -24,17 +24,17 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[onError]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
   no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
-    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
+    return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field asy::Future<dynamic>* f;
 static field asy::Future<core::int*>* t1 = self::f.{asy::Future::then}<core::int*>((dynamic _) → self::MyFuture<core::int*>* => new self::MyFuture::value<core::int*>("hi"));
-static field asy::Future<core::List<core::int*>*>* t2 = self::f.{asy::Future::then}<core::List<core::int*>*>((dynamic _) → core::List<core::int*>* => <core::int*>[3]);
+static field asy::Future<core::List<core::int*>*>* t2 = self::f.{asy::Future::then}<core::List<core::int*>*>((dynamic _) → core::List<core::int*>* => core::_GrowableList::_literal1<core::int*>(3));
 static method g2() → asy::Future<core::List<core::int*>*>* /* originally async */ {
   final asy::_Future<core::List<core::int*>*>* :async_future = new asy::_Future::•<core::List<core::int*>*>();
   core::bool* :is_sync = false;
@@ -47,7 +47,7 @@
     try {
       #L1:
       {
-        :return_value = <core::int*>[3];
+        :return_value = core::_GrowableList::_literal1<core::int*>(3);
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -74,7 +74,7 @@
     try {
       #L2:
       {
-        :return_value = new self::MyFuture::value<core::List<core::int*>*>(<core::int*>[3]);
+        :return_value = new self::MyFuture::value<core::List<core::int*>*>(core::_GrowableList::_literal1<core::int*>(3));
         break #L2;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
index a59d7c8..7438fe3 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
@@ -36,7 +36,7 @@
       {
         asy::Future<core::List<self::A*>*>* f1 = null;
         asy::Future<core::List<self::A*>*>* f2 = null;
-        [yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::wait<core::List<self::A*>*>(<asy::Future<core::List<self::A*>*>*>[f1, f2]), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::wait<core::List<self::A*>*>(core::_GrowableList::_literal2<asy::Future<core::List<self::A*>*>*>(f1, f2)), :async_op_then, :async_op_error, :async_op) in null;
         core::List<core::List<self::A*>*>* merged = _in::unsafeCast<core::List<core::List<self::A*>*>>(:result);
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
index 448d38f..e541778 100644
--- a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
@@ -46,10 +46,10 @@
       {
         asy::Future<self::B*>* b = asy::Future::value<self::B*>(new self::B::•());
         asy::Future<self::C*>* c = asy::Future::value<self::C*>(new self::C::•());
-        core::List<asy::Future<self::A*>*>* lll = <asy::Future<self::A*>*>[b, c];
+        core::List<asy::Future<self::A*>*>* lll = core::_GrowableList::_literal2<asy::Future<self::A*>*>(b, c);
         [yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::wait<self::A*>(lll), :async_op_then, :async_op_error, :async_op) in null;
         core::List<self::A*>* result = _in::unsafeCast<core::List<self::A*>>(:result);
-        [yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::wait<self::A*>(<asy::Future<self::A*>*>[b, c]), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::wait<self::A*>(core::_GrowableList::_literal2<asy::Future<self::A*>*>(b, c)), :async_op_then, :async_op_error, :async_op) in null;
         core::List<self::A*>* result2 = _in::unsafeCast<core::List<self::A*>>(:result);
         core::List<self::A*>* list = result;
         list = result2;
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.outline.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.outline.expect
index 121e609..3d1f663 100644
--- a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.outline.expect
@@ -2,15 +2,15 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:13:3: Error: Declared type variables of 'D.m' doesn't match those on overridden method 'C.m'.
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:13:3: Error: Can't infer types for 'm' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   m(x) => x;
 //   ^
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:9:5: Context: This is the overridden method ('m').
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:9:5: Context: This is one of the overridden members.
 //   T m<T>(T x) => x;
 //     ^
 //
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:13:3: Error: The return type of the method 'D.m' is 'dynamic', which does not match the return type, 'T', of the overridden method, 'C.m'.
-// Change to a subtype of 'T'.
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:13:3: Error: Declared type variables of 'D.m' doesn't match those on overridden method 'C.m'.
 //   m(x) => x;
 //   ^
 // pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:9:5: Context: This is the overridden method ('m').
@@ -39,7 +39,7 @@
 class D extends self::C {
   synthetic constructor •() → self::D*
     ;
-  method m(dynamic x) → dynamic
+  method m(invalid-type x) → invalid-type
     ;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
index 7f0c572..c76a23d 100644
--- a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
@@ -2,15 +2,15 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:13:3: Error: Declared type variables of 'D.m' doesn't match those on overridden method 'C.m'.
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:13:3: Error: Can't infer types for 'm' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   m(x) => x;
 //   ^
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:9:5: Context: This is the overridden method ('m').
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:9:5: Context: This is one of the overridden members.
 //   T m<T>(T x) => x;
 //     ^
 //
-// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:13:3: Error: The return type of the method 'D.m' is 'dynamic', which does not match the return type, 'T', of the overridden method, 'C.m'.
-// Change to a subtype of 'T'.
+// pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:13:3: Error: Declared type variables of 'D.m' doesn't match those on overridden method 'C.m'.
 //   m(x) => x;
 //   ^
 // pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:9:5: Context: This is the overridden method ('m').
@@ -45,7 +45,7 @@
   synthetic constructor •() → self::D*
     : super self::C::•()
     ;
-  method m(dynamic x) → dynamic
+  method m(invalid-type x) → invalid-type
     return x;
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.strong.transformed.expect
index 0e19c3a..4ef2311 100644
--- a/pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart.strong.transformed.expect
@@ -12,9 +12,9 @@
 static method f<T extends core::Object* = dynamic>(core::List<self::f::T*>* s) → self::f::T*
   return null;
 static method test() → dynamic {
-  core::String* x = self::f<core::String*>(<core::String*>["hi"]);
-  core::String* y = self::f<core::String*>(<core::String*>[let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart:13:79: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
+  core::String* x = self::f<core::String*>(core::_GrowableList::_literal1<core::String*>("hi"));
+  core::String* y = self::f<core::String*>(core::_GrowableList::_literal1<core::String*>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/generic_methods_downwards_inference_affects_arguments.dart:13:79: Error: A value of type 'int' can't be assigned to a variable of type 'String'.
           /*@ typeArgs=String* */ [/*error:LIST_ELEMENT_TYPE_NOT_ASSIGNABLE*/ 42]);
-                                                                              ^" in 42 as{TypeError} core::String*]);
+                                                                              ^" in 42 as{TypeError} core::String*));
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.strong.expect
index ec3999b..646895c 100644
--- a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.strong.expect
@@ -28,7 +28,7 @@
                                                                                                                           ^" as{TypeError,ForDynamic} FutureOr<core::String*>*));
   asy::Future<core::String*>* results3 = results.{asy::Future::then}<core::String*>((core::List<core::int*>* list) → FutureOr<core::String*>* => list.{core::Iterable::fold}<FutureOr<core::String*>*>("", let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart:31:111: Error: The argument type 'String Function(String, int)' can't be assigned to the parameter type 'FutureOr<String> Function(FutureOr<String>, int)'.
                   /*info:INFERRED_TYPE_CLOSURE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ /*@ returnType=String* */ (String
-                                                                                                              ^" in ((core::String* x, core::int* y) → core::String* => x.{core::String::+}(y.{core::int::toString}())) as{TypeError} (FutureOr<core::String*>*, core::int*) → FutureOr<core::String*>*));
+                                                                                                              ^" in ((core::String* x, core::int* y) → core::String* => x.{core::String::+}(y.{core::int::toString}())) as{TypeError} (FutureOr<core::String*>*, core::int*) →* FutureOr<core::String*>*));
   asy::Future<core::String*>* results4 = results.{asy::Future::then}<core::String*>((core::List<core::int*>* list) → core::String* => list.{core::Iterable::fold}<core::String*>("", (core::String* x, core::int* y) → core::String* => x.{core::String::+}(y.{core::int::toString}())));
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.strong.transformed.expect
index 9864c5c..e6ccc64e 100644
--- a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
 static method make(core::int* x) → asy::Future<core::int*>*
   return asy::Future::•<core::int*>(() → core::int* => x);
 static method test() → dynamic {
-  core::Iterable<asy::Future<core::int*>*>* list = <core::int*>[1, 2, 3].{core::Iterable::map}<asy::Future<core::int*>*>(#C1);
+  core::Iterable<asy::Future<core::int*>*>* list = core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::map}<asy::Future<core::int*>*>(#C1);
   asy::Future<core::List<core::int*>*>* results = asy::Future::wait<core::int*>(list);
   asy::Future<core::String*>* results2 = results.{asy::Future::then}<core::String*>((core::List<core::int*>* list) → FutureOr<core::String*>* => list.{core::Iterable::fold}<FutureOr<core::String*>*>("", (FutureOr<core::String*>* x, core::int* y) → FutureOr<core::String*>* => invalid-expression "pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart:23:123: Error: The operator '+' isn't defined for the class 'FutureOr<String>'.
 Try correcting the operator to an existing operator, or defining a '+' operator.
@@ -28,7 +28,7 @@
                                                                                                                           ^"));
   asy::Future<core::String*>* results3 = results.{asy::Future::then}<core::String*>((core::List<core::int*>* list) → FutureOr<core::String*>* => list.{core::Iterable::fold}<FutureOr<core::String*>*>("", let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart:31:111: Error: The argument type 'String Function(String, int)' can't be assigned to the parameter type 'FutureOr<String> Function(FutureOr<String>, int)'.
                   /*info:INFERRED_TYPE_CLOSURE,error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ /*@ returnType=String* */ (String
-                                                                                                              ^" in ((core::String* x, core::int* y) → core::String* => x.{core::String::+}(y.{core::int::toString}())) as{TypeError} (FutureOr<core::String*>*, core::int*) → FutureOr<core::String*>*));
+                                                                                                              ^" in ((core::String* x, core::int* y) → core::String* => x.{core::String::+}(y.{core::int::toString}())) as{TypeError} (FutureOr<core::String*>*, core::int*) →* FutureOr<core::String*>*));
   asy::Future<core::String*>* results4 = results.{asy::Future::then}<core::String*>((core::List<core::int*>* list) → core::String* => list.{core::Iterable::fold}<core::String*>("", (core::String* x, core::int* y) → core::String* => x.{core::String::+}(y.{core::int::toString}())));
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.strong.transformed.expect
index 854ab35..944df3a 100644
--- a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 import "dart:math" as math;
 
 class Trace extends core::Object {
-  field core::List<self::Frame*>* frames = <self::Frame*>[];
+  field core::List<self::Frame*>* frames = core::_GrowableList::•<self::Frame*>(0);
   synthetic constructor •() → self::Trace*
     : super core::Object::•()
     ;
@@ -37,7 +37,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  core::List<self::Trace*>* traces = <self::Trace*>[];
+  core::List<self::Trace*>* traces = core::_GrowableList::•<self::Trace*>(0);
   core::int* longest = traces.{core::Iterable::map}<core::int*>((self::Trace* trace) → core::int* {
     return trace.{self::Trace::frames}.{core::Iterable::map}<core::int*>((self::Frame* frame) → core::int* => frame.{self::Frame::location}.{core::String::length}).{core::Iterable::fold}<core::int*>(0, #C1<core::int*>);
   }).{core::Iterable::fold}<core::int*>(0, #C1<core::int*>);
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
index b735a9b..6756bd4 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
@@ -2,8 +2,8 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer types for 'f' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   f(x, {y}) {}
 //   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
@@ -13,32 +13,10 @@
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   f(x, {y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
-//   A f(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
-//   I f(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   f(x, {y}) {}
-//         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
-//   A f(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
-//   I f(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:3: Error: Can't infer types for 'g' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   g(x, {y}) {}
-//     ^
+//   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
@@ -46,21 +24,10 @@
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   g(x, {y}) {}
-//         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
-//   A g(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
-//   A g(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:3: Error: Can't infer types for 'h' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   h(x, {y}) {}
-//         ^
+//   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the overridden members.
 //   A h(A x, {A y}) {}
 //     ^
@@ -96,9 +63,9 @@
     ;
   method f(invalid-type x, {invalid-type y}) → invalid-type
     ;
-  method g(invalid-type x, {invalid-type y}) → self::A*
+  method g(invalid-type x, {invalid-type y}) → invalid-type
     ;
-  method h(self::A* x, {invalid-type y}) → self::A*
+  method h(invalid-type x, {invalid-type y}) → invalid-type
     ;
 }
 class I extends core::Object {
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
index dedc39b..2948381e 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
@@ -2,8 +2,8 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer types for 'f' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   f(x, {y}) {}
 //   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
@@ -13,32 +13,10 @@
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   f(x, {y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
-//   A f(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
-//   I f(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   f(x, {y}) {}
-//         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
-//   A f(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
-//   I f(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:3: Error: Can't infer types for 'g' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   g(x, {y}) {}
-//     ^
+//   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
@@ -46,21 +24,10 @@
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   g(x, {y}) {}
-//         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
-//   A g(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
-//   A g(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:3: Error: Can't infer types for 'h' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   h(x, {y}) {}
-//         ^
+//   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the overridden members.
 //   A h(A x, {A y}) {}
 //     ^
@@ -94,8 +61,8 @@
     : super self::A::•()
     ;
   method f(invalid-type x, {invalid-type y = #C1}) → invalid-type {}
-  method g(invalid-type x, {invalid-type y = #C1}) → self::A* {}
-  method h(self::A* x, {invalid-type y = #C1}) → self::A* {}
+  method g(invalid-type x, {invalid-type y = #C1}) → invalid-type {}
+  method h(invalid-type x, {invalid-type y = #C1}) → invalid-type {}
 }
 class I extends core::Object {
   synthetic constructor •() → self::I*
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
index dedc39b..2948381e 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
@@ -2,8 +2,8 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer types for 'f' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   f(x, {y}) {}
 //   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
@@ -13,32 +13,10 @@
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   f(x, {y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
-//   A f(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
-//   I f(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   f(x, {y}) {}
-//         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
-//   A f(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
-//   I f(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:3: Error: Can't infer types for 'g' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   g(x, {y}) {}
-//     ^
+//   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
@@ -46,21 +24,10 @@
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   g(x, {y}) {}
-//         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
-//   A g(A x, {A y}) {}
-//     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
-//   A g(I x, {I y}) {}
-//     ^
-//
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
-// Try adding an explicit type.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:3: Error: Can't infer types for 'h' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   h(x, {y}) {}
-//         ^
+//   ^
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the overridden members.
 //   A h(A x, {A y}) {}
 //     ^
@@ -94,8 +61,8 @@
     : super self::A::•()
     ;
   method f(invalid-type x, {invalid-type y = #C1}) → invalid-type {}
-  method g(invalid-type x, {invalid-type y = #C1}) → self::A* {}
-  method h(self::A* x, {invalid-type y = #C1}) → self::A* {}
+  method g(invalid-type x, {invalid-type y = #C1}) → invalid-type {}
+  method h(invalid-type x, {invalid-type y = #C1}) → invalid-type {}
 }
 class I extends core::Object {
   synthetic constructor •() → self::I*
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart
index d316140..df45278 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_super.dart
@@ -24,51 +24,44 @@
 
 class Test extends Base {
   void test() {
-    super. /*@target=Base.member*/ member = /*@ typeArgs=B* */ f();
+    super.member = /*@ typeArgs=B* */ f();
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=B.+*/ += /*@ typeArgs=C* */ f();
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=B.**/ *= /*@ typeArgs=B* */ f();
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=B.&*/ &= /*@ typeArgs=A* */ f();
 
-    /*@target=B.-*/ --super
-        . /*@target=Base.member*/ /*@target=Base.member*/ member;
+    /*@target=B.-*/ --super. /*@target=Base.member*/ member;
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=B.-*/ --;
 
-    var /*@ type=B* */ v1 =
-        super. /*@target=Base.member*/ member = /*@ typeArgs=B* */ f();
+    var /*@ type=B* */ v1 = super.member = /*@ typeArgs=B* */ f();
 
-    var /*@ type=B* */ v2 =
-        super. /*@target=Base.member*/ /*@target=Base.member*/ member
-            /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
+    var /*@ type=B* */ v2 = super. /*@target=Base.member*/ member
+        /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
 
-    var /*@ type=A* */ v3 =
-        super. /*@target=Base.member*/ /*@target=Base.member*/ member
-            /*@target=B.+*/ += /*@ typeArgs=C* */ f();
+    var /*@ type=A* */ v3 = super. /*@target=Base.member*/ member
+        /*@target=B.+*/ += /*@ typeArgs=C* */ f();
 
-    var /*@ type=B* */ v4 =
-        super. /*@target=Base.member*/ /*@target=Base.member*/ member
-            /*@target=B.**/ *= /*@ typeArgs=B* */ f();
+    var /*@ type=B* */ v4 = super. /*@target=Base.member*/ member
+        /*@target=B.**/ *= /*@ typeArgs=B* */ f();
 
-    var /*@ type=C* */ v5 =
-        super. /*@target=Base.member*/ /*@target=Base.member*/ member
-            /*@target=B.&*/ &= /*@ typeArgs=A* */ f();
+    var /*@ type=C* */ v5 = super. /*@target=Base.member*/ member
+        /*@target=B.&*/ &= /*@ typeArgs=A* */ f();
 
     var /*@ type=B* */ v6 =
-        /*@target=B.-*/ --super
-            . /*@target=Base.member*/ /*@target=Base.member*/ member;
+        /*@target=B.-*/ --super. /*@target=Base.member*/ member;
 
     var /*@ type=B* */ v7 = super
-        . /*@ type=B* */ /*@target=Base.member*/ /*@target=Base.member*/
+        . /*@ type=B* */ /*@target=Base.member*/
         /*@ type=B* */ member /*@target=B.-*/ --;
   }
 }
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart
index b4877f3..77e0929 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_super_upwards.dart
@@ -17,98 +17,82 @@
 
 class Test1 extends Base {
   void test() {
-    var /*@ type=int* */ v1 =
-        super. /*@target=Base.intProp*/ intProp = getInt();
+    var /*@ type=int* */ v1 = super.intProp = getInt();
 
-    var /*@ type=int* */ v4 =
-        super. /*@target=Base.intProp*/ /*@target=Base.intProp*/ intProp
-            /*@target=num.==*/ ??= getInt();
+    var /*@ type=int* */ v4 = super. /*@target=Base.intProp*/ intProp
+        /*@target=num.==*/ ??= getInt();
 
-    var /*@ type=int* */ v7 =
-        super. /*@target=Base.intProp*/ /*@target=Base.intProp*/ intProp
-            /*@target=num.+*/ += getInt();
+    var /*@ type=int* */ v7 = super. /*@target=Base.intProp*/ intProp
+        /*@target=num.+*/ += getInt();
 
     var /*@ type=int* */ v10 = /*@target=num.+*/ ++super
-        . /*@target=Base.intProp*/ /*@target=Base.intProp*/ intProp;
+        . /*@target=Base.intProp*/ intProp;
 
     var /*@ type=int* */ v11 = super
-        . /*@ type=int* */ /*@target=Base.intProp*/ /*@target=Base.intProp*/
+        . /*@ type=int* */ /*@target=Base.intProp*/
         /*@ type=int* */ intProp /*@target=num.+*/ ++;
   }
 }
 
 class Test2 extends Base {
   void test() {
-    var /*@ type=int* */ v1 =
-        super. /*@target=Base.numProp*/ numProp = getInt();
+    var /*@ type=int* */ v1 = super.numProp = getInt();
 
-    var /*@ type=num* */ v2 =
-        super. /*@target=Base.numProp*/ numProp = getNum();
+    var /*@ type=num* */ v2 = super.numProp = getNum();
 
-    var /*@ type=double* */ v3 =
-        super. /*@target=Base.numProp*/ numProp = getDouble();
+    var /*@ type=double* */ v3 = super.numProp = getDouble();
 
-    var /*@ type=num* */ v4 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.==*/ ??= getInt();
+    var /*@ type=num* */ v4 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.==*/ ??= getInt();
 
-    var /*@ type=num* */ v5 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.==*/ ??= getNum();
+    var /*@ type=num* */ v5 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.==*/ ??= getNum();
 
-    var /*@ type=num* */ v6 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.==*/ ??= getDouble();
+    var /*@ type=num* */ v6 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.==*/ ??= getDouble();
 
-    var /*@ type=num* */ v7 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.+*/ += getInt();
+    var /*@ type=num* */ v7 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.+*/ += getInt();
 
-    var /*@ type=num* */ v8 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.+*/ += getNum();
+    var /*@ type=num* */ v8 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.+*/ += getNum();
 
     var /*@ type=num* */ v9 = super
             .
-            /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
+            /*@target=Base.numProp*/ numProp
         /*@target=num.+*/ += getDouble();
 
     var /*@ type=num* */ v10 = /*@target=num.+*/ ++super
-        . /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp;
+        . /*@target=Base.numProp*/ numProp;
 
     var /*@ type=num* */ v11 = super
         .
-        /*@ type=num* */ /*@target=Base.numProp*/ /*@target=Base.numProp*/
+        /*@ type=num* */ /*@target=Base.numProp*/
         /*@ type=num* */ numProp /*@target=num.+*/ ++;
   }
 }
 
 class Test3 extends Base {
   void test3() {
-    var /*@ type=double* */ v3 =
-        super. /*@target=Base.doubleProp*/ doubleProp = getDouble();
+    var /*@ type=double* */ v3 = super.doubleProp = getDouble();
 
-    var /*@ type=double* */ v6 = super
-            . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/ doubleProp
+    var /*@ type=double* */ v6 = super. /*@target=Base.doubleProp*/ doubleProp
         /*@target=num.==*/ ??= getDouble();
 
-    var /*@ type=double* */ v7 = super
-            . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/ doubleProp
+    var /*@ type=double* */ v7 = super. /*@target=Base.doubleProp*/ doubleProp
         /*@target=double.+*/ += getInt();
 
-    var /*@ type=double* */ v8 = super
-            . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/ doubleProp
+    var /*@ type=double* */ v8 = super. /*@target=Base.doubleProp*/ doubleProp
         /*@target=double.+*/ += getNum();
 
-    var /*@ type=double* */ v9 = super
-            . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/ doubleProp
+    var /*@ type=double* */ v9 = super. /*@target=Base.doubleProp*/ doubleProp
         /*@target=double.+*/ += getDouble();
 
     var /*@ type=double* */ v10 = /*@target=double.+*/ ++super
-        . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/ doubleProp;
+        . /*@target=Base.doubleProp*/ doubleProp;
 
     var /*@ type=double* */ v11 = super
-        . /*@ type=double* */ /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/
+        . /*@ type=double* */ /*@target=Base.doubleProp*/
         /*@ type=double* */ doubleProp /*@target=double.+*/ ++;
   }
 }
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect
index 28cd597..6fd22e3 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect
@@ -2,35 +2,13 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
-//   num get x;
-//           ^
-//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   var x;
-//       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
-//   int get x;
-//           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
-//   double get x;
-//              ^
-//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   var x;
-//       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
-//   num get x;
-//           ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
@@ -104,7 +82,7 @@
     ;
 }
 class F extends self::A implements self::C {
-  field invalid-type x;
+  field core::int* x;
   synthetic constructor •() → self::F*
     ;
 }
@@ -114,7 +92,7 @@
     ;
 }
 class H extends self::C implements self::D {
-  field invalid-type x;
+  field core::double* x;
   synthetic constructor •() → self::H*
     ;
 }
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
index 044f2fd..4c56b7e 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
@@ -2,35 +2,13 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
-//   num get x;
-//           ^
-//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   var x;
-//       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
-//   int get x;
-//           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
-//   double get x;
-//              ^
-//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   var x;
-//       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
-//   num get x;
-//           ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
@@ -109,7 +87,7 @@
     ;
 }
 class F extends self::A implements self::C {
-  field invalid-type x = null;
+  field core::int* x = null;
   synthetic constructor •() → self::F*
     : super self::A::•()
     ;
@@ -121,7 +99,7 @@
     ;
 }
 class H extends self::C implements self::D {
-  field invalid-type x = null;
+  field core::double* x = null;
   synthetic constructor •() → self::H*
     : super self::C::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect
index 044f2fd..4c56b7e 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect
@@ -2,35 +2,13 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
-//   num get x;
-//           ^
-//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   var x;
-//       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
-//   int get x;
-//           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
-//   double get x;
-//              ^
-//
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
-// Try adding an explicit type.
-//   var x;
-//       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
-//   num get x;
-//           ^
 // pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
@@ -109,7 +87,7 @@
     ;
 }
 class F extends self::A implements self::C {
-  field invalid-type x = null;
+  field core::int* x = null;
   synthetic constructor •() → self::F*
     : super self::A::•()
     ;
@@ -121,7 +99,7 @@
     ;
 }
 class H extends self::C implements self::D {
-  field invalid-type x = null;
+  field core::double* x = null;
   synthetic constructor •() → self::H*
     : super self::C::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
index c48e0cc..1d43d47 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
@@ -77,6 +77,8 @@
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
+  mixin-super-stub get x() → core::int*
+    return super.{self::B::x};
   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
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
index a0ba133..c7c2a14 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
@@ -83,6 +83,8 @@
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
+  mixin-super-stub get x() → core::int*
+    return super.{self::B::x};
   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
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
index 5ec6724..3341f60 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
@@ -83,6 +83,8 @@
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
+  get x() → core::int*
+    return 0;
   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
@@ -93,8 +95,6 @@
   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
-  get x() → core::int*
-    return 0;
 }
 class G extends self::_G&Object&B {
   field core::int* x = null;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
index 5c519d3..fa329d7 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
@@ -77,6 +77,8 @@
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
+  mixin-super-stub set x(core::int* value) → void
+    return super.{self::B::x} = value;
   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
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
index 91b4992..476388a 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
@@ -82,6 +82,8 @@
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
+  mixin-super-stub set x(core::int* value) → void
+    return super.{self::B::x} = value;
   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
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
index ed1e30b..34e2520 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
@@ -82,6 +82,7 @@
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
+  set x(core::int* value) → void {}
   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
@@ -92,7 +93,6 @@
   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
-  set x(core::int* value) → void {}
 }
 class G extends self::_G&Object&B {
   field core::int* x = null;
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.transformed.expect
index 1879718..69e2baf 100644
--- a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.transformed.expect
@@ -104,9 +104,9 @@
 static field self::B* b = new self::B::•(invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:19:46: Error: Getter not found: 'x'.
 var b = new B(/*error:UNDEFINED_IDENTIFIER*/ x); // allocations
                                              ^");
-static field core::List<dynamic>* c1 = <dynamic>[invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:21:34: Error: Getter not found: 'x'.
+static field core::List<dynamic>* c1 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:21:34: Error: Getter not found: 'x'.
   /*error:UNDEFINED_IDENTIFIER*/ x
-                                 ^"];
+                                 ^");
 static field core::List<dynamic>* c2 = #C1;
 static field core::Map<dynamic, dynamic>* d = <dynamic, dynamic>{"a": "b"};
 static field self::A* e = let final self::A* #t1 = new self::A::•() in block {
@@ -132,7 +132,7 @@
   b = /*error:INVALID_ASSIGNMENT*/ \"hi\";
                                    ^" in "hi" as{TypeError} self::B*;
   self::b = new self::B::•(3);
-  self::c1 = <dynamic>[];
+  self::c1 = core::_GrowableList::•<dynamic>(0);
   self::c1 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:41:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
  - 'Set' is from 'dart:core'.
  - 'List' is from 'dart:core'.
@@ -140,7 +140,7 @@
                                                           ^" in ( block {
     final core::Set<dynamic>* #t5 = new col::_CompactLinkedHashSet::•<dynamic>();
   } =>#t5) as{TypeError} core::List<dynamic>*;
-  self::c2 = <dynamic>[];
+  self::c2 = core::_GrowableList::•<dynamic>(0);
   self::c2 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:43:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
  - 'Set' is from 'dart:core'.
  - 'List' is from 'dart:core'.
@@ -182,7 +182,7 @@
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart'.
   j = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ [];
-                                                         ^" in <dynamic>[] as{TypeError} self::B*;
+                                                         ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} self::B*;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.strong.transformed.expect
index 74ddf33..2917089 100644
--- a/pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_list_literal_nested_in_map_literal.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
 static method getResource(core::String* str) → self::Resource*
   return null;
 static method main() → dynamic {
-  core::Map<core::String*, core::List<self::Folder*>*>* map = <core::String*, core::List<self::Folder*>*>{"pkgA": <self::Folder*>[self::getResource("/pkgA/lib/") as{TypeError} self::Folder*], "pkgB": <self::Folder*>[self::getResource("/pkgB/lib/") as{TypeError} self::Folder*]};
-  core::List<core::Map<core::String*, self::Folder*>*>* list = <core::Map<core::String*, self::Folder*>*>[<core::String*, self::Folder*>{"pkgA": self::getResource("/pkgA/lib/") as{TypeError} self::Folder*}, <core::String*, self::Folder*>{"pkgB": self::getResource("/pkgB/lib/") as{TypeError} self::Folder*}];
-  self::Foo<core::List<self::Folder*>*>* foo = new self::Foo::•<core::List<self::Folder*>*>(<self::Folder*>[self::getResource("/pkgA/lib/") as{TypeError} self::Folder*]);
+  core::Map<core::String*, core::List<self::Folder*>*>* map = <core::String*, core::List<self::Folder*>*>{"pkgA": core::_GrowableList::_literal1<self::Folder*>(self::getResource("/pkgA/lib/") as{TypeError} self::Folder*), "pkgB": core::_GrowableList::_literal1<self::Folder*>(self::getResource("/pkgB/lib/") as{TypeError} self::Folder*)};
+  core::List<core::Map<core::String*, self::Folder*>*>* list = core::_GrowableList::_literal2<core::Map<core::String*, self::Folder*>*>(<core::String*, self::Folder*>{"pkgA": self::getResource("/pkgA/lib/") as{TypeError} self::Folder*}, <core::String*, self::Folder*>{"pkgB": self::getResource("/pkgB/lib/") as{TypeError} self::Folder*});
+  self::Foo<core::List<self::Folder*>*>* foo = new self::Foo::•<core::List<self::Folder*>*>(core::_GrowableList::_literal1<self::Folder*>(self::getResource("/pkgA/lib/") as{TypeError} self::Folder*));
 }
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart b/pkg/front_end/testcases/inference/infer_method_missing_params.dart
index a9f6d88..ef8130c 100644
--- a/pkg/front_end/testcases/inference/infer_method_missing_params.dart
+++ b/pkg/front_end/testcases/inference/infer_method_missing_params.dart
@@ -11,18 +11,21 @@
   int f(int x, int y);
   int g(int x, [int y]);
   int h(int x, {int y});
+  int i(int x, {int y});
 }
 
 abstract class B {
   int f(int x);
   int g(int x);
   int h(int x);
+  int i(int x, {int z});
 }
 
 abstract class C implements A, B {
   f(x, y);
   g(x, [y]);
   h(x, {y});
+  i(x, {y, z});
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.outline.expect b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.outline.expect
index b30b053..bacc059 100644
--- a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.outline.expect
@@ -2,10 +2,32 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:23:3: Error: The method 'C.f' has more required arguments than those of overridden method 'B.f'.
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:25:3: Error: Can't infer types for 'f' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   f(x, y);
 //   ^
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:17:7: Context: This is the overridden method ('f').
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:11:7: Context: This is one of the overridden members.
+//   int f(int x, int y);
+//       ^
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:18:7: Context: This is one of the overridden members.
+//   int f(int x);
+//       ^
+//
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:28:3: Error: Can't infer types for 'i' as the overridden members don't have a combined signature.
+// Try adding explicit types.
+//   i(x, {y, z});
+//   ^
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:14:7: Context: This is one of the overridden members.
+//   int i(int x, {int y});
+//       ^
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:21:7: Context: This is one of the overridden members.
+//   int i(int x, {int z});
+//       ^
+//
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:25:3: Error: The method 'C.f' has more required arguments than those of overridden method 'B.f'.
+//   f(x, y);
+//   ^
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:18:7: Context: This is the overridden method ('f').
 //   int f(int x);
 //       ^
 //
@@ -18,6 +40,7 @@
   abstract method f(core::int* x, core::int* y) → core::int*;
   abstract method g(core::int* x, [core::int* y]) → core::int*;
   abstract method h(core::int* x, {core::int* y}) → core::int*;
+  abstract method i(core::int* x, {core::int* y}) → core::int*;
   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
@@ -35,6 +58,7 @@
   abstract method f(core::int* x) → core::int*;
   abstract method g(core::int* x) → core::int*;
   abstract method h(core::int* x) → core::int*;
+  abstract method i(core::int* x, {core::int* z}) → core::int*;
   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
@@ -49,9 +73,10 @@
 abstract class C extends core::Object implements self::A, self::B {
   synthetic constructor •() → self::C*
     ;
-  abstract method f(core::int* x, core::int* y) → core::int*;
+  abstract method f(invalid-type x, invalid-type y) → invalid-type;
   abstract method g(core::int* x, [core::int* y]) → core::int*;
   abstract method h(core::int* x, {core::int* y}) → core::int*;
+  abstract method i(invalid-type x, {invalid-type y, invalid-type z}) → invalid-type;
   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
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
index ecaea8f..4b3051b 100644
--- a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.strong.expect
@@ -2,10 +2,32 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:23:3: Error: The method 'C.f' has more required arguments than those of overridden method 'B.f'.
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:25:3: Error: Can't infer types for 'f' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   f(x, y);
 //   ^
-// pkg/front_end/testcases/inference/infer_method_missing_params.dart:17:7: Context: This is the overridden method ('f').
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:11:7: Context: This is one of the overridden members.
+//   int f(int x, int y);
+//       ^
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:18:7: Context: This is one of the overridden members.
+//   int f(int x);
+//       ^
+//
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:28:3: Error: Can't infer types for 'i' as the overridden members don't have a combined signature.
+// Try adding explicit types.
+//   i(x, {y, z});
+//   ^
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:14:7: Context: This is one of the overridden members.
+//   int i(int x, {int y});
+//       ^
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:21:7: Context: This is one of the overridden members.
+//   int i(int x, {int z});
+//       ^
+//
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:25:3: Error: The method 'C.f' has more required arguments than those of overridden method 'B.f'.
+//   f(x, y);
+//   ^
+// pkg/front_end/testcases/inference/infer_method_missing_params.dart:18:7: Context: This is the overridden method ('f').
 //   int f(int x);
 //       ^
 //
@@ -19,6 +41,7 @@
   abstract method f(core::int* x, core::int* y) → core::int*;
   abstract method g(core::int* x, [core::int* y = #C1]) → core::int*;
   abstract method h(core::int* x, {core::int* y = #C1}) → core::int*;
+  abstract method i(core::int* x, {core::int* y = #C1}) → core::int*;
   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
@@ -37,6 +60,7 @@
   abstract method f(core::int* x) → core::int*;
   abstract method g(core::int* x) → core::int*;
   abstract method h(core::int* x) → core::int*;
+  abstract method i(core::int* x, {core::int* z = #C1}) → core::int*;
   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
@@ -52,9 +76,10 @@
   synthetic constructor •() → self::C*
     : super core::Object::•()
     ;
-  abstract method f(core::int* x, core::int* y) → core::int*;
+  abstract method f(invalid-type x, invalid-type y) → invalid-type;
   abstract method g(core::int* x, [core::int* y = #C1]) → core::int*;
   abstract method h(core::int* x, {core::int* y = #C1}) → core::int*;
+  abstract method i(invalid-type x, {invalid-type y = #C1, invalid-type z = #C1}) → invalid-type;
   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
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.textual_outline.expect b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.textual_outline.expect
index ef2bee8..25f7d42 100644
--- a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.textual_outline.expect
@@ -4,18 +4,21 @@
   int f(int x, int y);
   int g(int x, [int y]);
   int h(int x, {int y});
+  int i(int x, {int y});
 }
 
 abstract class B {
   int f(int x);
   int g(int x);
   int h(int x);
+  int i(int x, {int z});
 }
 
 abstract class C implements A, B {
   f(x, y);
   g(x, [y]);
   h(x, {y});
+  i(x, {y, z});
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.textual_outline_modelled.expect
index ef2bee8..25f7d42 100644
--- a/pkg/front_end/testcases/inference/infer_method_missing_params.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/inference/infer_method_missing_params.dart.textual_outline_modelled.expect
@@ -4,18 +4,21 @@
   int f(int x, int y);
   int g(int x, [int y]);
   int h(int x, {int y});
+  int i(int x, {int y});
 }
 
 abstract class B {
   int f(int x);
   int g(int x);
   int h(int x);
+  int i(int x, {int z});
 }
 
 abstract class C implements A, B {
   f(x, y);
   g(x, [y]);
   h(x, {y});
+  i(x, {y, z});
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.strong.transformed.expect
index e547269..e0d92ec 100644
--- a/pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_return_of_statement_lambda.dart.strong.transformed.expect
@@ -3,8 +3,8 @@
 import "dart:core" as core;
 
 static method strings() → core::List<core::String*>* {
-  core::Iterable<core::String*>* stuff = <dynamic>[].{core::Iterable::expand}<core::String*>((dynamic i) → core::List<core::String*>* {
-    return <core::String*>[];
+  core::Iterable<core::String*>* stuff = core::_GrowableList::•<dynamic>(0).{core::Iterable::expand}<core::String*>((dynamic i) → core::List<core::String*>* {
+    return core::_GrowableList::•<core::String*>(0);
   });
   return stuff.{core::Iterable::toList}();
 }
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
index d675a14..a2a130e 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop.dart.strong.transformed.expect
@@ -105,7 +105,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method test() → dynamic {
-  core::List<self::Foo*>* list = <self::Foo*>[];
+  core::List<self::Foo*>* list = core::_GrowableList::•<self::Foo*>(0);
   {
     core::Iterator<self::Foo*>* :sync-for-iterator = list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.outline.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.outline.expect
index 3ceab23e..98b90b7 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.outline.expect
@@ -57,7 +57,6 @@
     ;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError, () →* void onDone, core::bool* cancelOnError}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -102,6 +101,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError, () →* void onDone, core::bool* cancelOnError}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method test() → dynamic async 
   ;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.expect
index 040669a..fc3c8e8 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.expect
@@ -100,7 +100,6 @@
     return null;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen = #C1, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel = #C1}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -145,6 +144,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method test() → dynamic async {
   self::MyStream<self::Foo*>* myStream = self::MyStream::•<self::Foo*>();
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
index 4aa6578..e1ed3dc 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
@@ -195,7 +195,6 @@
     return null;
   abstract member-signature get isBroadcast() → core::bool*; -> asy::Stream::isBroadcast
   abstract member-signature method asBroadcastStream({(asy::StreamSubscription<self::MyStream::T*>*) →* void onListen = #C1, (asy::StreamSubscription<self::MyStream::T*>*) →* void onCancel = #C1}) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::asBroadcastStream
-  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
   abstract member-signature method where((self::MyStream::T*) →* core::bool* test) → asy::Stream<self::MyStream::T*>*; -> asy::Stream::where
   abstract member-signature method map<S extends core::Object* = dynamic>((self::MyStream::T*) →* self::MyStream::map::S* convert) → asy::Stream<self::MyStream::map::S*>*; -> asy::Stream::map
   abstract member-signature method asyncMap<E extends core::Object* = dynamic>((self::MyStream::T*) →* FutureOr<self::MyStream::asyncMap::E*>* convert) → asy::Stream<self::MyStream::asyncMap::E*>*; -> asy::Stream::asyncMap
@@ -240,6 +239,7 @@
   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
+  abstract member-signature method listen((self::MyStream::T*) →* void onData, {core::Function* onError = #C1, () →* void onDone = #C1, core::bool* cancelOnError = #C1}) → asy::StreamSubscription<self::MyStream::T*>*; -> asy::Stream::listen
 }
 static method test() → dynamic /* originally async */ {
   final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
index d291d40..7fcd694 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
@@ -33,3 +33,9 @@
   #C3 = self::E {index:#C1, _name:#C2}
   #C4 = <self::E*>[#C3]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inferred_type_is_enum.dart:
+- E. (from org-dartlang-testcase:///inferred_type_is_enum.dart:8:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
index d291d40..7fcd694 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
@@ -33,3 +33,9 @@
   #C3 = self::E {index:#C1, _name:#C2}
   #C4 = <self::E*>[#C3]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inferred_type_is_enum.dart:
+- E. (from org-dartlang-testcase:///inferred_type_is_enum.dart:8:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
index 3eb7ad4..2c64c5a 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
@@ -33,3 +33,9 @@
   #C3 = self::E {index:#C1, _name:#C2}
   #C4 = <self::E*>[#C3]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inferred_type_is_enum_values.dart:
+- E. (from org-dartlang-testcase:///inferred_type_is_enum_values.dart:8:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
index 3eb7ad4..2c64c5a 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
@@ -33,3 +33,9 @@
   #C3 = self::E {index:#C1, _name:#C2}
   #C4 = <self::E*>[#C3]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///inferred_type_is_enum_values.dart:
+- E. (from org-dartlang-testcase:///inferred_type_is_enum_values.dart:8:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.strong.transformed.expect
index 5fbc81e..468a854 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<() →* core::Object*>* v = <() →* core::Object*>[#C1, #C2];
+static field core::List<() →* core::Object*>* v = core::_GrowableList::_literal2<() →* core::Object*>(#C1, #C2);
 static method f() → core::int*
   return null;
 static method g() → core::String*
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.strong.transformed.expect
index 5db9025..302d4f1 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<((core::String*) →* core::int*) →* core::Object*>* v = <((core::String*) →* core::int*) →* core::Object*>[#C1, #C2];
+static field core::List<((core::String*) →* core::int*) →* core::Object*>* v = core::_GrowableList::_literal2<((core::String*) →* core::int*) →* core::Object*>(#C1, #C2);
 static method f((core::String*) →* core::int* x) → core::int*
   return null;
 static method g((core::String*) →* core::int* x) → core::String*
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.strong.transformed.expect
index 7d05c01..d3dbe88 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<({x: core::int*}) →* core::Object*>* v = <({x: core::int*}) →* core::Object*>[#C1, #C2];
+static field core::List<({x: core::int*}) →* core::Object*>* v = core::_GrowableList::_literal2<({x: core::int*}) →* core::Object*>(#C1, #C2);
 static method f({core::int* x = #C3}) → core::int*
   return null;
 static method g({core::int* x = #C3}) → core::String*
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.strong.transformed.expect
index 2eb4e4d..d9781ac 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<([core::int*]) →* core::Object*>* v = <([core::int*]) →* core::Object*>[#C1, #C2];
+static field core::List<([core::int*]) →* core::Object*>* v = core::_GrowableList::_literal2<([core::int*]) →* core::Object*>(#C1, #C2);
 static method f([core::int* x = #C3]) → core::int*
   return null;
 static method g([core::int* x = #C3]) → core::String*
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.strong.transformed.expect
index 5a739ef..a8897a0 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<(core::int*) →* core::Object*>* v = <(core::int*) →* core::Object*>[#C1, #C2];
+static field core::List<(core::int*) →* core::Object*>* v = core::_GrowableList::_literal2<(core::int*) →* core::Object*>(#C1, #C2);
 static method f(core::int* x) → core::int*
   return null;
 static method g(core::int* x) → core::String*
diff --git a/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.strong.transformed.expect
index f378eb9..f770ccb 100644
--- a/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/lambda_does_not_have_propagated_type_hint.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
 static method bar() → void {
   dynamic list;
   try {
-    list = <core::String*>[];
+    list = core::_GrowableList::•<core::String*>(0);
   }
   on dynamic catch(final dynamic _) {
     return;
diff --git a/pkg/front_end/testcases/inference/list_literal_typed.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/list_literal_typed.dart.strong.transformed.expect
index 87ba7a9..08d625d 100644
--- a/pkg/front_end/testcases/inference/list_literal_typed.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/list_literal_typed.dart.strong.transformed.expect
@@ -2,13 +2,13 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<core::int*>* a = <core::int*>[];
-static field core::List<core::double*>* b = <core::double*>[1.0, 2.0, 3.0];
-static field core::List<core::List<core::int*>*>* c = <core::List<core::int*>*>[];
-static field core::List<dynamic>* d = <dynamic>[1, 2.0, false];
+static field core::List<core::int*>* a = core::_GrowableList::•<core::int*>(0);
+static field core::List<core::double*>* b = core::_GrowableList::_literal3<core::double*>(1.0, 2.0, 3.0);
+static field core::List<core::List<core::int*>*>* c = core::_GrowableList::•<core::List<core::int*>*>(0);
+static field core::List<dynamic>* d = core::_GrowableList::_literal3<dynamic>(1, 2.0, false);
 static method main() → dynamic {
-  core::List<core::int*>* a = <core::int*>[];
-  core::List<core::double*>* b = <core::double*>[1.0, 2.0, 3.0];
-  core::List<core::List<core::int*>*>* c = <core::List<core::int*>*>[];
-  core::List<dynamic>* d = <dynamic>[1, 2.0, false];
+  core::List<core::int*>* a = core::_GrowableList::•<core::int*>(0);
+  core::List<core::double*>* b = core::_GrowableList::_literal3<core::double*>(1.0, 2.0, 3.0);
+  core::List<core::List<core::int*>*>* c = core::_GrowableList::•<core::List<core::int*>*>(0);
+  core::List<dynamic>* d = core::_GrowableList::_literal3<dynamic>(1, 2.0, false);
 }
diff --git a/pkg/front_end/testcases/inference/list_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/list_literals.dart.strong.transformed.expect
index cf02cf7..6714e68 100644
--- a/pkg/front_end/testcases/inference/list_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/list_literals.dart.strong.transformed.expect
@@ -18,7 +18,7 @@
 import "dart:core" as core;
 
 static method test1() → dynamic {
-  core::List<core::int*>* x = <core::int*>[1, 2, 3];
+  core::List<core::int*>* x = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
   x.{core::List::add}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/list_literals.dart:10:70: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
   x. /*@target=List.add*/ add(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi');
                                                                      ^" in "hi" as{TypeError} core::int*);
@@ -29,7 +29,7 @@
   core::List<core::num*>* y = x;
 }
 static method test2() → dynamic {
-  core::List<core::num*>* x = <core::num*>[1, 2.0, 3];
+  core::List<core::num*>* x = core::_GrowableList::_literal3<core::num*>(1, 2.0, 3);
   x.{core::List::add}(let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/list_literals.dart:18:70: Error: The argument type 'String' can't be assigned to the parameter type 'num'.
   x. /*@target=List.add*/ add(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi');
                                                                      ^" in "hi" as{TypeError} core::num*);
diff --git a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.transformed.expect
index 56e22ce..e5fb9e6 100644
--- a/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/list_literals_can_infer_null_bottom.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method test1() → dynamic {
-  core::List<Null>* x = <Null>[null];
+  core::List<Null>* x = core::_GrowableList::_literal1<Null>(null);
   x.{core::List::add}(42 as{TypeError} Null);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/list_literals_top_level.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/list_literals_top_level.dart.strong.transformed.expect
index 03e500a..0c92bb15 100644
--- a/pkg/front_end/testcases/inference/list_literals_top_level.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/list_literals_top_level.dart.strong.transformed.expect
@@ -17,8 +17,8 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<core::int*>* x1 = <core::int*>[1, 2, 3];
-static field core::List<core::num*>* x2 = <core::num*>[1, 2.0, 3];
+static field core::List<core::int*>* x1 = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
+static field core::List<core::num*>* x2 = core::_GrowableList::_literal3<core::num*>(1, 2.0, 3);
 static method test1() → dynamic {
   self::x1.{core::List::add}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/list_literals_top_level.dart:10:71: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
   x1. /*@target=List.add*/ add(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/ 'hi');
diff --git a/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
index 57169ca..6c31a1f 100644
--- a/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
@@ -72,7 +72,7 @@
       function :sync_op(core::_SyncIterator<dynamic>* :iterator, dynamic :exception, dynamic :stack_trace) → core::bool* yielding {
         {
           {
-            :iterator.{core::_SyncIterator::_yieldEachIterable} = <(core::int*) →* core::int*>[(core::int* x) → core::int* => x];
+            :iterator.{core::_SyncIterator::_yieldEachIterable} = core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x);
             [yield] true;
           }
         }
@@ -129,7 +129,7 @@
         try {
           #L3:
           {
-            if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(<(core::int*) →* core::int*>[(core::int* x) → core::int* => x])))
+            if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))))
               return null;
             else
               [yield] null;
diff --git a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
index 5049806..939a1a6 100644
--- a/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/non_const_invocation.dart.strong.transformed.expect
@@ -16,9 +16,9 @@
   get v4() → self::Bar<((self::Foo::T*) →* self::Foo::T*) →* self::Foo::T*>*
     return new self::Bar::•<((self::Foo::T*) →* self::Foo::T*) →* self::Foo::T*>();
   get v5() → core::List<self::Foo::T*>*
-    return <self::Foo::T*>[];
+    return core::_GrowableList::•<self::Foo::T*>(0);
   get v6() → core::List<(self::Foo::T*) →* self::Foo::T*>*
-    return <(self::Foo::T*) →* self::Foo::T*>[];
+    return core::_GrowableList::•<(self::Foo::T*) →* self::Foo::T*>(0);
   get v7() → core::Map<self::Foo::T*, self::Foo::T*>*
     return <self::Foo::T*, self::Foo::T*>{};
   get v8() → core::Map<(self::Foo::T*) →* self::Foo::T*, self::Foo::T*>*
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.transformed.expect
index ec63329..7c4682e 100644
--- a/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator.dart.strong.transformed.expect
@@ -4,6 +4,6 @@
 
 static method main() → dynamic {
   core::List<core::int*>* x;
-  core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::int*>*} <core::int*>[] : #t1;
+  core::List<core::int*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::int*>*} core::_GrowableList::•<core::int*>(0) : #t1;
   core::List<core::int*>* z = y;
 }
diff --git a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.transformed.expect
index c4ca3fe..02d005c 100644
--- a/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/null_coalescing_operator_2.dart.strong.transformed.expect
@@ -4,5 +4,5 @@
 
 static method main() → dynamic {
   core::List<core::int*>* x;
-  core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::num*>*} <core::num*>[] : #t1;
+  core::List<core::num*>* y = let final core::List<core::int*>* #t1 = x in #t1.{core::List::==}(null) ?{core::List<core::num*>*} core::_GrowableList::•<core::num*>(0) : #t1;
 }
diff --git a/pkg/front_end/testcases/inference/property_get_toplevel.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/property_get_toplevel.dart.strong.transformed.expect
index 85b4185..32c55ca 100644
--- a/pkg/front_end/testcases/inference/property_get_toplevel.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/property_get_toplevel.dart.strong.transformed.expect
@@ -24,5 +24,5 @@
 }
 static field self::C* c = new self::C::•();
 static field () →* core::int* function_ref = self::c.{self::C::function};
-static field core::List<() →* core::int*>* function_ref_list = <() →* core::int*>[self::c.{self::C::function}];
+static field core::List<() →* core::int*>* function_ref_list = core::_GrowableList::_literal1<() →* core::int*>(self::c.{self::C::function});
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/property_set.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/property_set.dart.strong.transformed.expect
index 286b94e..29bdd38 100644
--- a/pkg/front_end/testcases/inference/property_set.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/property_set.dart.strong.transformed.expect
@@ -23,23 +23,23 @@
   self::A<core::int*>* a_int = new self::A::•<core::int*>();
   self::A<core::Object*>* a_object = new self::A::•<core::Object*>();
   self::A<dynamic>* a_dynamic = new self::A::•<dynamic>();
-  core::List<core::int*>* x_int = a_int.{self::A::x} = <core::int*>[0];
-  core::List<core::int*>* y_int = a_int.{self::A::y} = <core::int*>[0];
-  core::List<core::Object*>* x_object = a_object.{self::A::x} = <core::Object*>[0];
-  core::List<core::Object*>* y_object = a_object.{self::A::y} = <core::Object*>[0];
-  core::List<dynamic>* x_dynamic = a_dynamic.{self::A::x} = <dynamic>[0];
-  core::List<dynamic>* y_dynamic = a_dynamic.{self::A::y} = <dynamic>[0];
-  core::List<core::int*>* x_int_explicit = a_int.{self::A::x} = <core::int*>[0];
-  core::List<core::int*>* y_int_explicit = a_int.{self::A::y} = <core::int*>[0];
-  core::List<core::int*>* x_object_explicit = a_object.{self::A::x} = <core::int*>[0];
-  core::List<core::int*>* y_object_explicit = a_object.{self::A::y} = <core::int*>[0];
-  core::List<core::int*>* x_dynamic_explicit = a_dynamic.{self::A::x} = <core::int*>[0];
-  core::List<core::int*>* y_dynamic_explicit = a_dynamic.{self::A::y} = <core::int*>[0];
-  core::List<core::int*>* x_int_downward = a_int.{self::A::x} = <core::int*>[0];
-  core::List<core::int*>* y_int_downward = a_int.{self::A::y} = <core::int*>[0];
-  core::List<core::int*>* x_object_downward = (a_object.{self::A::x} = <core::Object*>[0]) as{TypeError} core::List<core::int*>*;
-  core::List<core::int*>* y_object_downward = (a_object.{self::A::y} = <core::Object*>[0]) as{TypeError} core::List<core::int*>*;
-  core::List<core::int*>* x_dynamic_downward = (a_dynamic.{self::A::x} = <dynamic>[0]) as{TypeError} core::List<core::int*>*;
-  core::List<core::int*>* y_dynamic_downward = (a_dynamic.{self::A::y} = <dynamic>[0]) as{TypeError} core::List<core::int*>*;
+  core::List<core::int*>* x_int = a_int.{self::A::x} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* y_int = a_int.{self::A::y} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::Object*>* x_object = a_object.{self::A::x} = core::_GrowableList::_literal1<core::Object*>(0);
+  core::List<core::Object*>* y_object = a_object.{self::A::y} = core::_GrowableList::_literal1<core::Object*>(0);
+  core::List<dynamic>* x_dynamic = a_dynamic.{self::A::x} = core::_GrowableList::_literal1<dynamic>(0);
+  core::List<dynamic>* y_dynamic = a_dynamic.{self::A::y} = core::_GrowableList::_literal1<dynamic>(0);
+  core::List<core::int*>* x_int_explicit = a_int.{self::A::x} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* y_int_explicit = a_int.{self::A::y} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* x_object_explicit = a_object.{self::A::x} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* y_object_explicit = a_object.{self::A::y} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* x_dynamic_explicit = a_dynamic.{self::A::x} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* y_dynamic_explicit = a_dynamic.{self::A::y} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* x_int_downward = a_int.{self::A::x} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* y_int_downward = a_int.{self::A::y} = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::int*>* x_object_downward = (a_object.{self::A::x} = core::_GrowableList::_literal1<core::Object*>(0)) as{TypeError} core::List<core::int*>*;
+  core::List<core::int*>* y_object_downward = (a_object.{self::A::y} = core::_GrowableList::_literal1<core::Object*>(0)) as{TypeError} core::List<core::int*>*;
+  core::List<core::int*>* x_dynamic_downward = (a_dynamic.{self::A::x} = core::_GrowableList::_literal1<dynamic>(0)) as{TypeError} core::List<core::int*>*;
+  core::List<core::int*>* y_dynamic_downward = (a_dynamic.{self::A::y} = core::_GrowableList::_literal1<dynamic>(0)) as{TypeError} core::List<core::int*>*;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.expect b/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.expect
index e08b136..1c7e0ba 100644
--- a/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.expect
@@ -3,5 +3,9 @@
 import "dart:core" as core;
 
 typedef F = () →* void;
-static final field core::Type* x = () →* void;
+static final field core::Type* x = #C1;
 static method main() → dynamic {}
+
+constants  {
+  #C1 = TypeLiteralConstant(() →* void)
+}
diff --git a/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.transformed.expect
index 1892d0c..1c7e0ba 100644
--- a/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.transformed.expect
@@ -3,10 +3,9 @@
 import "dart:core" as core;
 
 typedef F = () →* void;
-static final field core::Type* x = () →* void;
+static final field core::Type* x = #C1;
 static method main() → dynamic {}
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///reference_to_typedef.dart:9:11 -> TypeLiteralConstant(void Function()*)
-Extra constant evaluation: evaluated: 1, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(() →* void)
+}
diff --git a/pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.strong.transformed.expect
index d1ef879..b689fb3 100644
--- a/pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/subexpressions_of_explicitly_typed_fields.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  field core::List<core::num*>* x = <core::num*>[0];
+  field core::List<core::num*>* x = core::_GrowableList::_literal1<core::num*>(0);
   synthetic constructor •() → self::C*
     : super core::Object::•()
     ;
@@ -18,5 +18,5 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<core::num*>* y = <core::num*>[0];
+static field core::List<core::num*>* y = core::_GrowableList::_literal1<core::num*>(0);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/super_property_set_substitution.dart b/pkg/front_end/testcases/inference/super_property_set_substitution.dart
index 2101e53..413ff6e 100644
--- a/pkg/front_end/testcases/inference/super_property_set_substitution.dart
+++ b/pkg/front_end/testcases/inference/super_property_set_substitution.dart
@@ -21,7 +21,7 @@
   E<Future<U>> get x => null;
   void set x(Object x) {}
   void g() {
-    super. /*@target=B.x*/ x = /*@ typeArgs=D<Future<C::U*>*>* */ f();
+    super.x = /*@ typeArgs=D<Future<C::U*>*>* */ f();
   }
 }
 
diff --git a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
index 340170ef..659f28e 100644
--- a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
@@ -71,7 +71,7 @@
     function :sync_op(core::_SyncIterator<dynamic>* :iterator, dynamic :exception, dynamic :stack_trace) → core::bool* yielding {
       {
         {
-          :iterator.{core::_SyncIterator::_yieldEachIterable} = <(core::int*) →* core::int*>[(core::int* x) → core::int* => x];
+          :iterator.{core::_SyncIterator::_yieldEachIterable} = core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x);
           [yield] true;
         }
       }
@@ -128,7 +128,7 @@
       try {
         #L3:
         {
-          if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(<(core::int*) →* core::int*>[(core::int* x) → core::int* => x])))
+          if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))))
             return null;
           else
             [yield] null;
diff --git a/pkg/front_end/testcases/inference/try_catch_promotion.dart.outline.expect b/pkg/front_end/testcases/inference/try_catch_promotion.dart.outline.expect
index db93300..1575bda 100644
--- a/pkg/front_end/testcases/inference/try_catch_promotion.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/try_catch_promotion.dart.outline.expect
@@ -23,6 +23,7 @@
 class E extends core::StackTrace {
   synthetic constructor •() → self::E*
     ;
+  abstract member-signature method toString() → core::String*; -> core::StackTrace::toString
   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
diff --git a/pkg/front_end/testcases/inference/try_catch_promotion.dart.strong.expect b/pkg/front_end/testcases/inference/try_catch_promotion.dart.strong.expect
index 17d888d..adbb087 100644
--- a/pkg/front_end/testcases/inference/try_catch_promotion.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/try_catch_promotion.dart.strong.expect
@@ -26,6 +26,7 @@
   synthetic constructor •() → self::E*
     : super core::StackTrace::•()
     ;
+  abstract member-signature method toString() → core::String*; -> core::StackTrace::toString
   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
diff --git a/pkg/front_end/testcases/inference/try_catch_promotion.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/try_catch_promotion.dart.strong.transformed.expect
index 17d888d..adbb087 100644
--- a/pkg/front_end/testcases/inference/try_catch_promotion.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/try_catch_promotion.dart.strong.transformed.expect
@@ -26,6 +26,7 @@
   synthetic constructor •() → self::E*
     : super core::StackTrace::•()
     ;
+  abstract member-signature method toString() → core::String*; -> core::StackTrace::toString
   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
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.strong.transformed.expect
index 89d0bd3..951265d 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   return 1;
 });
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 static method main() → dynamic {
   self::v;
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.transformed.expect
index 2e3ca1e6..c8e4727 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.transformed.expect
@@ -31,5 +31,5 @@
   return 1;
 });
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.strong.transformed.expect
index 322ca8f..fd6b5b4 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   return 1;
 });
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 static method main() → dynamic {
   self::v;
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.strong.transformed.expect
index b005e12..bff0cad 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   return 1;
 });
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 static method main() → dynamic {
   self::v;
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.transformed.expect
index 938f89a..c983f6b 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.transformed.expect
@@ -31,5 +31,5 @@
   return 1;
 });
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.strong.transformed.expect
index 129610f..cf09c4f 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   return 1;
 });
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 static method main() → dynamic {
   self::v;
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.strong.transformed.expect
index 4700f6a..6a725de 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param.dart.strong.transformed.expect
@@ -8,4 +8,4 @@
   });
 }
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.strong.transformed.expect
index 00386c6..9c69fce 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.strong.transformed.expect
@@ -8,7 +8,7 @@
   });
 }
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 
 constants  {
   #C1 = tearoff self::f
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.strong.transformed.expect
index bc2b33d..5b31f4c 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_dynamic.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  core::List<dynamic>* v = <dynamic>[() → core::int* {
+  core::List<dynamic>* v = core::_GrowableList::_literal1<dynamic>(() → core::int* {
     return 1;
-  }];
+  });
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.strong.transformed.expect
index b747c51..71c0bd2 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_typed.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
 
 typedef F = () →* core::int*;
 static method main() → dynamic {
-  core::List<() →* core::int*>* v = <() →* core::int*>[() → core::int* {
+  core::List<() →* core::int*>* v = core::_GrowableList::_literal1<() →* core::int*>(() → core::int* {
     return 1;
-  }];
+  });
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.strong.transformed.expect
index 5b2da50..cda2936 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_in_list_untyped.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic {
-  core::List<() →* core::int*>* v = <() →* core::int*>[() → core::int* {
+  core::List<() →* core::int*>* v = core::_GrowableList::_literal1<() →* core::int*>(() → core::int* {
     return 1;
-  }];
+  });
 }
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.strong.transformed.expect
index 102bdb33..f2717b8 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_dynamic_param.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   method f<T extends core::Object* = dynamic>(() →* self::C::f::T* g) → core::List<self::C::f::T*>*
-    return <self::C::f::T*>[g.call()];
+    return core::_GrowableList::_literal1<self::C::f::T*>(g.call());
   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
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.strong.transformed.expect
index 9921b26..c33bf91 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_explicit_type_param.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   method f<T extends core::Object* = dynamic>(() →* self::C::f::T* g) → core::List<self::C::f::T*>*
-    return <self::C::f::T*>[g.call()];
+    return core::_GrowableList::_literal1<self::C::f::T*>(g.call());
   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
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.strong.transformed.expect
index 9921b26..c33bf91 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_method_call_implicit_type_param.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   method f<T extends core::Object* = dynamic>(() →* self::C::f::T* g) → core::List<self::C::f::T*>*
-    return <self::C::f::T*>[g.call()];
+    return core::_GrowableList::_literal1<self::C::f::T*>(g.call());
   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
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
index fbcc92b..beb0961 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.expect
@@ -65,3 +65,9 @@
   #C9 = core::_ImmutableMap<(core::Object*) →* Null, Null> {_kvPairs:#C7}
   #C10 = core::_ImmutableMap<Null, (core::Object*) →* Null> {_kvPairs:#C7}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_invocation.dart:
+- Bar. (from org-dartlang-testcase:///const_invocation.dart:24:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
index fbcc92b..beb0961 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart.strong.transformed.expect
@@ -65,3 +65,9 @@
   #C9 = core::_ImmutableMap<(core::Object*) →* Null, Null> {_kvPairs:#C7}
   #C10 = core::_ImmutableMap<Null, (core::Object*) →* Null> {_kvPairs:#C7}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_invocation.dart:
+- Bar. (from org-dartlang-testcase:///const_invocation.dart:24:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect
index b80c8e2..70eab38 100644
--- a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.expect
@@ -13,7 +13,7 @@
 static field core::int* intValue = 0;
 static field core::num* numValue = 0;
 static field core::double* doubleValue = 0.0;
-static field invalid-type a = () → core::num* => self::intValue.{core::num::+}(self::b as{TypeError,ForDynamic} core::num);
+static field invalid-type a = () → core::num* => self::intValue.{core::num::+}(self::b as{TypeError,ForDynamic} core::num*);
 static field dynamic b = self::a.call();
 static field () →* core::num* c = () → core::num* => self::numValue.{core::num::+}(self::d);
 static field core::num* d = self::c.call();
diff --git a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.transformed.expect
index b80c8e2..70eab38 100644
--- a/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/dependency_only_if_overloaded.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
 static field core::int* intValue = 0;
 static field core::num* numValue = 0;
 static field core::double* doubleValue = 0.0;
-static field invalid-type a = () → core::num* => self::intValue.{core::num::+}(self::b as{TypeError,ForDynamic} core::num);
+static field invalid-type a = () → core::num* => self::intValue.{core::num::+}(self::b as{TypeError,ForDynamic} core::num*);
 static field dynamic b = self::a.call();
 static field () →* core::num* c = () → core::num* => self::numValue.{core::num::+}(self::d);
 static field core::num* d = self::c.call();
diff --git a/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.strong.transformed.expect
index f211b44..d837da1 100644
--- a/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level.dart.strong.transformed.expect
@@ -33,5 +33,5 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::B<core::int*>*>* t3 = <self::B<core::int*>*>[new self::B::•<core::int*>(3)];
+static field core::List<self::B<core::int*>*>* t3 = core::_GrowableList::_literal1<self::B<core::int*>*>(new self::B::•<core::int*>(3));
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.strong.transformed.expect
index aaa7123..8a0e9d7 100644
--- a/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/downwards_inference_inside_top_level_2.dart.strong.transformed.expect
@@ -17,5 +17,5 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::A<core::int*>*>* t2 = <self::A<core::int*>*>[new self::A::•<core::int*>(2)];
+static field core::List<self::A<core::int*>*>* t2 = core::_GrowableList::_literal1<self::A<core::int*>*>(new self::A::•<core::int*>(2));
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.transformed.expect
index d239253..c46cd53 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<core::double*>* a = <core::double*>[];
+static field core::List<core::double*>* a = core::_GrowableList::•<core::double*>(0);
 static field core::double* b = let final core::List<core::double*>* #t1 = self::a in let final core::int* #t2 = 0 in let final core::double* #t3 = 1.0 in let final void #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart
index 0b116bc..553dbee 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super.dart
@@ -24,52 +24,46 @@
 
 class Test extends Base {
   void test() {
-    super. /*@target=Base.member*/ member = /*@ typeArgs=B* */ f();
+    super.member = /*@ typeArgs=B* */ f();
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=B.+*/ += /*@ typeArgs=C* */ f();
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=B.**/ *= /*@ typeArgs=B* */ f();
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=B.&*/ &= /*@ typeArgs=A* */ f();
 
-    /*@target=B.-*/ --super
-        . /*@target=Base.member*/ /*@target=Base.member*/ member;
+    /*@target=B.-*/ --super. /*@target=Base.member*/ member;
 
-    super. /*@target=Base.member*/ /*@target=Base.member*/ member
+    super. /*@target=Base.member*/ member
         /*@target=B.-*/ --;
 
-    var /*@ type=B* */ v1 =
-        super. /*@target=Base.member*/ member = /*@ typeArgs=B* */ f();
+    var /*@ type=B* */ v1 = super.member = /*@ typeArgs=B* */ f();
 
-    var /*@ type=B* */ v2 =
-        super. /*@target=Base.member*/ /*@target=Base.member*/ member
-            /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
+    var /*@ type=B* */ v2 = super. /*@target=Base.member*/ member
+        /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
 
-    var /*@ type=A* */ v3 =
-        super. /*@target=Base.member*/ /*@target=Base.member*/ member
-            /*@target=B.+*/ += /*@ typeArgs=C* */ f();
+    var /*@ type=A* */ v3 = super. /*@target=Base.member*/ member
+        /*@target=B.+*/ += /*@ typeArgs=C* */ f();
 
-    var /*@ type=B* */ v4 =
-        super. /*@target=Base.member*/ /*@target=Base.member*/ member
-            /*@target=B.**/ *= /*@ typeArgs=B* */ f();
+    var /*@ type=B* */ v4 = super. /*@target=Base.member*/ member
+        /*@target=B.**/ *= /*@ typeArgs=B* */ f();
 
-    var /*@ type=C* */ v5 =
-        super. /*@target=Base.member*/ /*@target=Base.member*/ member
-            /*@target=B.&*/ &= /*@ typeArgs=A* */ f();
+    var /*@ type=C* */ v5 = super. /*@target=Base.member*/ member
+        /*@target=B.&*/ &= /*@ typeArgs=A* */ f();
 
     var /*@ type=B* */ v6 = /*@target=B.-*/ --super
         .
-        /*@target=Base.member*/ /*@target=Base.member*/ member;
+        /*@target=Base.member*/ member;
 
     var /*@ type=B* */ v7 = super
         .
-        /*@ type=B* */ /*@target=Base.member*/ /*@target=Base.member*/
+        /*@ type=B* */ /*@target=Base.member*/
         /*@ type=B* */ member /*@target=B.-*/ --;
   }
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart
index 599d5f3..ef3dee1 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_super_upwards.dart
@@ -17,116 +17,97 @@
 
 class Test1 extends Base {
   void test() {
-    var /*@ type=int* */ v1 =
-        super. /*@target=Base.intProp*/ intProp = getInt();
+    var /*@ type=int* */ v1 = super.intProp = getInt();
 
-    var /*@ type=num* */ v2 =
-        super. /*@target=Base.intProp*/ intProp = getNum();
+    var /*@ type=num* */ v2 = super.intProp = getNum();
 
-    var /*@ type=int* */ v4 =
-        super. /*@target=Base.intProp*/ /*@target=Base.intProp*/ intProp
-            /*@target=num.==*/ ??= getInt();
+    var /*@ type=int* */ v4 = super. /*@target=Base.intProp*/ intProp
+        /*@target=num.==*/ ??= getInt();
 
-    var /*@ type=num* */ v5 =
-        super. /*@target=Base.intProp*/ /*@target=Base.intProp*/ intProp
-            /*@target=num.==*/ ??= getNum();
+    var /*@ type=num* */ v5 = super. /*@target=Base.intProp*/ intProp
+        /*@target=num.==*/ ??= getNum();
 
-    var /*@ type=int* */ v7 =
-        super. /*@target=Base.intProp*/ /*@target=Base.intProp*/ intProp
-            /*@target=num.+*/ += getInt();
+    var /*@ type=int* */ v7 = super. /*@target=Base.intProp*/ intProp
+        /*@target=num.+*/ += getInt();
 
-    var /*@ type=num* */ v8 =
-        super. /*@target=Base.intProp*/ /*@target=Base.intProp*/ intProp
-            /*@target=num.+*/ += getNum();
+    var /*@ type=num* */ v8 = super. /*@target=Base.intProp*/ intProp
+        /*@target=num.+*/ += getNum();
 
     var /*@ type=int* */ v10 = /*@target=num.+*/ ++super
-        . /*@target=Base.intProp*/ /*@target=Base.intProp*/ intProp;
+        . /*@target=Base.intProp*/ intProp;
 
     var /*@ type=int* */ v11 = super
-        . /*@ type=int* */ /*@target=Base.intProp*/ /*@target=Base.intProp*/
+        . /*@ type=int* */ /*@target=Base.intProp*/
         /*@ type=int* */ intProp /*@target=num.+*/ ++;
   }
 }
 
 class Test2 extends Base {
   void test() {
-    var /*@ type=int* */ v1 =
-        super. /*@target=Base.numProp*/ numProp = getInt();
+    var /*@ type=int* */ v1 = super.numProp = getInt();
 
-    var /*@ type=num* */ v2 =
-        super. /*@target=Base.numProp*/ numProp = getNum();
+    var /*@ type=num* */ v2 = super.numProp = getNum();
 
-    var /*@ type=double* */ v3 =
-        super. /*@target=Base.numProp*/ numProp = getDouble();
+    var /*@ type=double* */ v3 = super.numProp = getDouble();
 
-    var /*@ type=num* */ v4 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.==*/ ??= getInt();
+    var /*@ type=num* */ v4 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.==*/ ??= getInt();
 
-    var /*@ type=num* */ v5 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.==*/ ??= getNum();
+    var /*@ type=num* */ v5 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.==*/ ??= getNum();
 
-    var /*@ type=num* */ v6 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.==*/ ??= getDouble();
+    var /*@ type=num* */ v6 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.==*/ ??= getDouble();
 
-    var /*@ type=num* */ v7 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.+*/ += getInt();
+    var /*@ type=num* */ v7 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.+*/ += getInt();
 
-    var /*@ type=num* */ v8 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.+*/ += getNum();
+    var /*@ type=num* */ v8 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.+*/ += getNum();
 
-    var /*@ type=num* */ v9 =
-        super. /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp
-            /*@target=num.+*/ += getDouble();
+    var /*@ type=num* */ v9 = super. /*@target=Base.numProp*/ numProp
+        /*@target=num.+*/ += getDouble();
 
     var /*@ type=num* */ v10 = /*@target=num.+*/ ++super
-        . /*@target=Base.numProp*/ /*@target=Base.numProp*/ numProp;
+        . /*@target=Base.numProp*/ numProp;
 
     var /*@ type=num* */ v11 = super
-        . /*@ type=num* */ /*@target=Base.numProp*/ /*@target=Base.numProp*/
+        . /*@ type=num* */ /*@target=Base.numProp*/
         /*@ type=num* */ numProp /*@target=num.+*/ ++;
   }
 }
 
 class Test3 extends Base {
   void test3() {
-    var /*@ type=num* */ v2 =
-        super. /*@target=Base.doubleProp*/ doubleProp = getNum();
+    var /*@ type=num* */ v2 = super.doubleProp = getNum();
 
-    var /*@ type=double* */ v3 =
-        super. /*@target=Base.doubleProp*/ doubleProp = getDouble();
+    var /*@ type=double* */ v3 = super.doubleProp = getDouble();
 
-    var /*@ type=num* */ v5 = super
-            . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/ doubleProp
+    var /*@ type=num* */ v5 = super. /*@target=Base.doubleProp*/ doubleProp
         /*@target=num.==*/ ??= getNum();
 
-    var /*@ type=double* */ v6 = super
-            . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/ doubleProp
+    var /*@ type=double* */ v6 = super. /*@target=Base.doubleProp*/ doubleProp
         /*@target=num.==*/ ??= getDouble();
 
     var /*@ type=double* */ v7 = super
-        . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/
+        . /*@target=Base.doubleProp*/
         doubleProp /*@target=double.+*/ += getInt();
 
     var /*@ type=double* */ v8 = super
-        . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/
+        . /*@target=Base.doubleProp*/
         doubleProp /*@target=double.+*/ += getNum();
 
     var /*@ type=double* */ v9 = super
-        . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/
+        . /*@target=Base.doubleProp*/
         doubleProp /*@target=double.+*/ += getDouble();
 
     var /*@ type=double* */ v10 =
         /*@target=double.+*/ ++super
-            . /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/
+            . /*@target=Base.doubleProp*/
             doubleProp;
 
     var /*@ type=double* */ v11 = super
-        . /*@ type=double* */ /*@target=Base.doubleProp*/ /*@target=Base.doubleProp*/
+        . /*@ type=double* */ /*@target=Base.doubleProp*/
         /*@ type=double* */ doubleProp /*@target=double.+*/ ++;
   }
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.outline.expect
index 0ebb072..35488cf 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.outline.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
index 8ae0ce1..871301b 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect
index 8ae0ce1..871301b 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
index d9e8e4e..abca250 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
@@ -13,7 +13,7 @@
 //   void set x(B value);
 //            ^
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var y;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
index 3bfa8c0..497e214 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
@@ -13,7 +13,7 @@
 //   void set x(B value);
 //            ^
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var y;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
index 3bfa8c0..497e214 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
@@ -13,7 +13,7 @@
 //   void set x(B value);
 //            ^
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var y;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.outline.expect
index c38c16a..b029148 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.outline.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
index 37df60c..6282349 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect
index 37df60c..6282349 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
index 0d41588..9d11e0e 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
index ae57d36..001d19d 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
index ae57d36..001d19d 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
 // Try adding an explicit type.
 //   var x;
 //       ^
diff --git a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.transformed.expect
index 30af47a..e068583 100644
--- a/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/list_literals_can_infer_null_top_level.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<Null>* x = <Null>[null];
+static field core::List<Null>* x = core::_GrowableList::_literal1<Null>(null);
 static method main() → dynamic {
   self::x;
 }
diff --git a/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.strong.transformed.expect
index 4151ea0..c23ee62 100644
--- a/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/property_get_toplevel.dart.strong.transformed.expect
@@ -26,7 +26,7 @@
 static field core::int* field_ref = self::c.{self::C::field};
 static field core::int* getter_ref = self::c.{self::C::getter};
 static field () →* core::int* function_ref = self::c.{self::C::function};
-static field core::List<core::int*>* field_ref_list = <core::int*>[self::c.{self::C::field}];
-static field core::List<core::int*>* getter_ref_list = <core::int*>[self::c.{self::C::getter}];
-static field core::List<() →* core::int*>* function_ref_list = <() →* core::int*>[self::c.{self::C::function}];
+static field core::List<core::int*>* field_ref_list = core::_GrowableList::_literal1<core::int*>(self::c.{self::C::field});
+static field core::List<core::int*>* getter_ref_list = core::_GrowableList::_literal1<core::int*>(self::c.{self::C::getter});
+static field core::List<() →* core::int*>* function_ref_list = core::_GrowableList::_literal1<() →* core::int*>(self::c.{self::C::function});
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/switch.dart.strong.expect b/pkg/front_end/testcases/inference_new/switch.dart.strong.expect
index 027ced3..6e55000 100644
--- a/pkg/front_end/testcases/inference_new/switch.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/switch.dart.strong.expect
@@ -41,3 +41,9 @@
 constants  {
   #C1 = self::C<core::int*> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch.dart:
+- C. (from org-dartlang-testcase:///switch.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference_new/switch.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/switch.dart.strong.transformed.expect
index 027ced3..6e55000 100644
--- a/pkg/front_end/testcases/inference_new/switch.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/switch.dart.strong.transformed.expect
@@ -41,3 +41,9 @@
 constants  {
   #C1 = self::C<core::int*> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch.dart:
+- C. (from org-dartlang-testcase:///switch.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.strong.transformed.expect
index 129610f..cf09c4f 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   return 1;
 });
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 static method main() → dynamic {
   self::v;
 }
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.strong.transformed.expect
index 129610f..cf09c4f 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
   return 1;
 });
 static method f<T extends core::Object* = dynamic>(() →* self::f::T* g) → core::List<self::f::T*>*
-  return <self::f::T*>[g.call()];
+  return core::_GrowableList::_literal1<self::f::T*>(g.call());
 static method main() → dynamic {
   self::v;
 }
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.strong.transformed.expect
index 7089cfc..c250022 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_literal_list.dart.strong.transformed.expect
@@ -22,7 +22,7 @@
     : super core::Object::•()
     ;
   method foo() → dynamic {
-    core::List<self::A<core::num*>*>* a = <self::A<core::num*>*>[];
+    core::List<self::A<core::num*>*>* a = core::_GrowableList::•<self::A<core::num*>*>(0);
   }
   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
@@ -36,5 +36,5 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  core::List<self::A<core::num*>*>* a = <self::A<core::num*>*>[];
+  core::List<self::A<core::num*>*>* a = core::_GrowableList::•<self::A<core::num*>*>(0);
 }
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.strong.transformed.expect
index 186472b..55af917 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_literal_list_with_generic_argument.dart.strong.transformed.expect
@@ -22,8 +22,8 @@
     : super core::Object::•()
     ;
   method fun() → dynamic {
-    core::List<self::A<self::B::U*>*>* foo = <self::A<self::B::U*>*>[];
-    core::List<self::A<core::num*>*>* bar = <self::A<core::num*>*>[];
+    core::List<self::A<self::B::U*>*>* foo = core::_GrowableList::•<self::A<self::B::U*>*>(0);
+    core::List<self::A<core::num*>*>* bar = core::_GrowableList::•<self::A<core::num*>*>(0);
   }
   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
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.transformed.expect
index 0508b6c..7f370d6 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list.dart.strong.transformed.expect
@@ -8,7 +8,7 @@
     : super core::Object::•()
     ;
   method foo() → dynamic {
-    core::List<(core::num*) →* dynamic>* a = <(core::num*) →* dynamic>[];
+    core::List<(core::num*) →* dynamic>* a = core::_GrowableList::•<(core::num*) →* dynamic>(0);
   }
   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
@@ -22,5 +22,5 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  core::List<(core::num*) →* dynamic>* a = <(core::num*) →* dynamic>[];
+  core::List<(core::num*) →* dynamic>* a = core::_GrowableList::•<(core::num*) →* dynamic>(0);
 }
diff --git a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
index cf2c35d..f92729b 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/body_typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
@@ -8,8 +8,8 @@
     : super core::Object::•()
     ;
   method fun() → dynamic {
-    core::List<(self::B::U*) →* dynamic>* foo = <(self::B::U*) →* dynamic>[];
-    core::List<(core::num*) →* dynamic>* bar = <(core::num*) →* dynamic>[];
+    core::List<(self::B::U*) →* dynamic>* foo = core::_GrowableList::•<(self::B::U*) →* dynamic>(0);
+    core::List<(core::num*) →* dynamic>* bar = core::_GrowableList::•<(core::num*) →* dynamic>(0);
   }
   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
@@ -23,5 +23,5 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  core::List<(core::num*) →* dynamic>* bar = <(core::num*) →* dynamic>[];
+  core::List<(core::num*) →* dynamic>* bar = core::_GrowableList::•<(core::num*) →* dynamic>(0);
 }
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.strong.transformed.expect
index 52cdb64..a4aa8b0 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/contravariant_dependence_in_literals.dart.strong.transformed.expect
@@ -17,6 +17,6 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::C<core::num*, (Null) →* void>*>* lc = <self::C<core::num*, (Null) →* void>*>[];
+static field core::List<self::C<core::num*, (Null) →* void>*>* lc = core::_GrowableList::•<self::C<core::num*, (Null) →* void>*>(0);
 static field core::Map<self::C<core::num*, (Null) →* void>*, self::C<core::num*, (Null) →* void>*>* mc = <self::C<core::num*, (Null) →* void>*, self::C<core::num*, (Null) →* void>*>{};
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.strong.transformed.expect
index eaaf4d5..c874a62 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/contravariant_mutual_dependence_in_literals.dart.strong.transformed.expect
@@ -32,8 +32,8 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::D<(Null, Null) →* void, (Null, Null) →* void>*>* ld = <self::D<(Null, Null) →* void, (Null, Null) →* void>*>[];
+static field core::List<self::D<(Null, Null) →* void, (Null, Null) →* void>*>* ld = core::_GrowableList::•<self::D<(Null, Null) →* void, (Null, Null) →* void>*>(0);
 static field core::Map<self::D<(Null, Null) →* void, (Null, Null) →* void>*, self::D<(Null, Null) →* void, (Null, Null) →* void>*>* md = <self::D<(Null, Null) →* void, (Null, Null) →* void>*, self::D<(Null, Null) →* void, (Null, Null) →* void>*>{};
-static field core::List<self::E<(Null) →* void>*>* le = <self::E<(Null) →* void>*>[];
+static field core::List<self::E<(Null) →* void>*>* le = core::_GrowableList::•<self::E<(Null) →* void>*>(0);
 static field core::Map<self::E<(Null) →* void>*, self::E<(Null) →* void>*>* me = <self::E<(Null) →* void>*, self::E<(Null) →* void>*>{};
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.strong.transformed.expect
index f4627cb..4c4e54a 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/covariant_dependence_in_literals.dart.strong.transformed.expect
@@ -77,12 +77,12 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::C<dynamic, self::A<dynamic>*>*>* lc = <self::C<dynamic, self::A<dynamic>*>*>[];
+static field core::List<self::C<dynamic, self::A<dynamic>*>*>* lc = core::_GrowableList::•<self::C<dynamic, self::A<dynamic>*>*>(0);
 static field core::Map<self::C<dynamic, self::A<dynamic>*>*, self::C<dynamic, self::A<dynamic>*>*>* mc = <self::C<dynamic, self::A<dynamic>*>*, self::C<dynamic, self::A<dynamic>*>*>{};
-static field core::List<self::D<core::num*, self::A<core::num*>*>*>* ld = <self::D<core::num*, self::A<core::num*>*>*>[];
+static field core::List<self::D<core::num*, self::A<core::num*>*>*>* ld = core::_GrowableList::•<self::D<core::num*, self::A<core::num*>*>*>(0);
 static field core::Map<self::D<core::num*, self::A<core::num*>*>*, self::D<core::num*, self::A<core::num*>*>*>* md = <self::D<core::num*, self::A<core::num*>*>*, self::D<core::num*, self::A<core::num*>*>*>{};
-static field core::List<self::E<dynamic, () →* dynamic>*>* le = <self::E<dynamic, () →* dynamic>*>[];
+static field core::List<self::E<dynamic, () →* dynamic>*>* le = core::_GrowableList::•<self::E<dynamic, () →* dynamic>*>(0);
 static field core::Map<self::E<dynamic, () →* dynamic>*, self::E<dynamic, () →* dynamic>*>* me = <self::E<dynamic, () →* dynamic>*, self::E<dynamic, () →* dynamic>*>{};
-static field core::List<self::F<core::num*, () →* core::num*>*>* lf = <self::F<core::num*, () →* core::num*>*>[];
+static field core::List<self::F<core::num*, () →* core::num*>*>* lf = core::_GrowableList::•<self::F<core::num*, () →* core::num*>*>(0);
 static field core::Map<self::F<core::num*, () →* core::num*>*, self::F<core::num*, () →* core::num*>*>* mf = <self::F<core::num*, () →* core::num*>*, self::F<core::num*, () →* core::num*>*>{};
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.strong.transformed.expect
index b532365..555394a 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/covariant_mutual_dependence_in_literals.dart.strong.transformed.expect
@@ -77,10 +77,10 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::D<self::B<dynamic, dynamic>*, self::C<dynamic, dynamic>*>*>* ld = <self::D<self::B<dynamic, dynamic>*, self::C<dynamic, dynamic>*>*>[];
+static field core::List<self::D<self::B<dynamic, dynamic>*, self::C<dynamic, dynamic>*>*>* ld = core::_GrowableList::•<self::D<self::B<dynamic, dynamic>*, self::C<dynamic, dynamic>*>*>(0);
 static field core::Map<self::D<self::B<dynamic, dynamic>*, self::C<dynamic, dynamic>*>*, self::D<self::B<dynamic, dynamic>*, self::C<dynamic, dynamic>*>*>* md = <self::D<self::B<dynamic, dynamic>*, self::C<dynamic, dynamic>*>*, self::D<self::B<dynamic, dynamic>*, self::C<dynamic, dynamic>*>*>{};
-static field core::List<self::E<self::B<dynamic, dynamic>*, () →* dynamic>*>* le = <self::E<self::B<dynamic, dynamic>*, () →* dynamic>*>[];
+static field core::List<self::E<self::B<dynamic, dynamic>*, () →* dynamic>*>* le = core::_GrowableList::•<self::E<self::B<dynamic, dynamic>*, () →* dynamic>*>(0);
 static field core::Map<self::E<self::B<dynamic, dynamic>*, () →* dynamic>*, self::E<self::B<dynamic, dynamic>*, () →* dynamic>*>* me = <self::E<self::B<dynamic, dynamic>*, () →* dynamic>*, self::E<self::B<dynamic, dynamic>*, () →* dynamic>*>{};
-static field core::List<self::F<() →* dynamic>*>* lf = <self::F<() →* dynamic>*>[];
+static field core::List<self::F<() →* dynamic>*>* lf = core::_GrowableList::•<self::F<() →* dynamic>*>(0);
 static field core::Map<self::F<() →* dynamic>*, self::F<() →* dynamic>*>* mf = <self::F<() →* dynamic>*, self::F<() →* dynamic>*>{};
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.strong.transformed.expect
index edf4bbf..71cc20d 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/dependence_in_literals.dart.strong.transformed.expect
@@ -47,8 +47,8 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::C<dynamic, (Null) →* dynamic>*>* lc = <self::C<dynamic, (Null) →* dynamic>*>[];
+static field core::List<self::C<dynamic, (Null) →* dynamic>*>* lc = core::_GrowableList::•<self::C<dynamic, (Null) →* dynamic>*>(0);
 static field core::Map<self::C<dynamic, (Null) →* dynamic>*, self::C<dynamic, (Null) →* dynamic>*>* mc = <self::C<dynamic, (Null) →* dynamic>*, self::C<dynamic, (Null) →* dynamic>*>{};
-static field core::List<self::D<core::num*, (Null) →* core::num*>*>* ld = <self::D<core::num*, (Null) →* core::num*>*>[];
+static field core::List<self::D<core::num*, (Null) →* core::num*>*>* ld = core::_GrowableList::•<self::D<core::num*, (Null) →* core::num*>*>(0);
 static field core::Map<self::D<core::num*, (Null) →* core::num*>*, self::D<core::num*, (Null) →* core::num*>*>* md = <self::D<core::num*, (Null) →* core::num*>*, self::D<core::num*, (Null) →* core::num*>*>{};
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.strong.transformed.expect
index 33fac9a..1468342 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/literal_list.dart.strong.transformed.expect
@@ -17,5 +17,5 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::A<core::num*>*>* a = <self::A<core::num*>*>[];
+static field core::List<self::A<core::num*>*>* a = core::_GrowableList::•<self::A<core::num*>*>(0);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.strong.transformed.expect
index a42b37a..6c9f709 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/literal_list_with_generic_argument.dart.strong.transformed.expect
@@ -18,8 +18,8 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<S extends core::Object* = dynamic> extends core::Object {
-  final field core::List<self::A<self::B::S*>*>* foo = <self::A<self::B::S*>*>[];
-  final field core::List<self::A<core::num*>*>* bar = <self::A<core::num*>*>[];
+  final field core::List<self::A<self::B::S*>*>* foo = core::_GrowableList::•<self::A<self::B::S*>*>(0);
+  final field core::List<self::A<core::num*>*>* bar = core::_GrowableList::•<self::A<core::num*>*>(0);
   synthetic constructor •() → self::B<self::B::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.strong.transformed.expect
index 57e2111..57d3ec5 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/mutual_dependence_in_literals.dart.strong.transformed.expect
@@ -152,22 +152,22 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<self::C1<(Null) →* dynamic, (Null) →* dynamic>*>* lc1 = <self::C1<(Null) →* dynamic, (Null) →* dynamic>*>[];
+static field core::List<self::C1<(Null) →* dynamic, (Null) →* dynamic>*>* lc1 = core::_GrowableList::•<self::C1<(Null) →* dynamic, (Null) →* dynamic>*>(0);
 static field core::Map<self::C1<(Null) →* dynamic, (Null) →* dynamic>*, self::C1<(Null) →* dynamic, (Null) →* dynamic>*>* mc1 = <self::C1<(Null) →* dynamic, (Null) →* dynamic>*, self::C1<(Null) →* dynamic, (Null) →* dynamic>*>{};
-static field core::List<self::C2<(Null) →* dynamic, (Null) →* dynamic>*>* lc2 = <self::C2<(Null) →* dynamic, (Null) →* dynamic>*>[];
+static field core::List<self::C2<(Null) →* dynamic, (Null) →* dynamic>*>* lc2 = core::_GrowableList::•<self::C2<(Null) →* dynamic, (Null) →* dynamic>*>(0);
 static field core::Map<self::C2<(Null) →* dynamic, (Null) →* dynamic>*, self::C2<(Null) →* dynamic, (Null) →* dynamic>*>* mc2 = <self::C2<(Null) →* dynamic, (Null) →* dynamic>*, self::C2<(Null) →* dynamic, (Null) →* dynamic>*>{};
-static field core::List<self::C3<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>* lc3 = <self::C3<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>[];
+static field core::List<self::C3<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>* lc3 = core::_GrowableList::•<self::C3<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>(0);
 static field core::Map<self::C3<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*, self::C3<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>* mc3 = <self::C3<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*, self::C3<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>{};
-static field core::List<self::C4<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>* lc4 = <self::C4<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>[];
+static field core::List<self::C4<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>* lc4 = core::_GrowableList::•<self::C4<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>(0);
 static field core::Map<self::C4<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*, self::C4<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>* mc4 = <self::C4<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*, self::C4<(Null, Null) →* dynamic, (Null, Null) →* dynamic>*>{};
-static field core::List<self::D1<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>* ld1 = <self::D1<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>[];
+static field core::List<self::D1<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>* ld1 = core::_GrowableList::•<self::D1<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>(0);
 static field core::Map<self::D1<self::B<dynamic, dynamic>*, (Null) →* dynamic>*, self::D1<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>* md1 = <self::D1<self::B<dynamic, dynamic>*, (Null) →* dynamic>*, self::D1<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>{};
-static field core::List<self::D2<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>* ld2 = <self::D2<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>[];
+static field core::List<self::D2<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>* ld2 = core::_GrowableList::•<self::D2<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>(0);
 static field core::Map<self::D2<self::B<dynamic, dynamic>*, (Null) →* dynamic>*, self::D2<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>* md2 = <self::D2<self::B<dynamic, dynamic>*, (Null) →* dynamic>*, self::D2<self::B<dynamic, dynamic>*, (Null) →* dynamic>*>{};
-static field core::List<self::D3<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>* ld3 = <self::D3<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>[];
+static field core::List<self::D3<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>* ld3 = core::_GrowableList::•<self::D3<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>(0);
 static field core::Map<self::D3<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*, self::D3<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>* md3 = <self::D3<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*, self::D3<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>{};
-static field core::List<self::D4<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>* ld4 = <self::D4<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>[];
+static field core::List<self::D4<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>* ld4 = core::_GrowableList::•<self::D4<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>(0);
 static field core::Map<self::D4<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*, self::D4<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>* md4 = <self::D4<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*, self::D4<self::B<dynamic, dynamic>*, (Null, Null) →* dynamic>*>{};
-static field core::List<self::E<(Null) →* dynamic>*>* le = <self::E<(Null) →* dynamic>*>[];
+static field core::List<self::E<(Null) →* dynamic>*>* le = core::_GrowableList::•<self::E<(Null) →* dynamic>*>(0);
 static field core::Map<self::E<(Null) →* dynamic>*, self::E<(Null) →* dynamic>*>* me = <self::E<(Null) →* dynamic>*, self::E<(Null) →* dynamic>*>{};
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.transformed.expect
index e5555e7..94f6c04 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list.dart.strong.transformed.expect
@@ -3,5 +3,5 @@
 import "dart:core" as core;
 
 typedef A<contravariant T extends core::num* = core::num*> = (T*) →* dynamic;
-static field core::List<(core::num*) →* dynamic>* a = <(core::num*) →* dynamic>[];
+static field core::List<(core::num*) →* dynamic>* a = core::_GrowableList::•<(core::num*) →* dynamic>(0);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
index 8f09136..db93d8e 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/typedef_literal_list_with_generic_argument.dart.strong.transformed.expect
@@ -4,8 +4,8 @@
 
 typedef A<contravariant T extends core::Object* = dynamic> = (T*) →* dynamic;
 class B<S extends core::Object* = dynamic> extends core::Object {
-  final field core::List<(self::B::S*) →* dynamic>* foo = <(self::B::S*) →* dynamic>[];
-  final field core::List<(core::num*) →* dynamic>* bar = <(core::num*) →* dynamic>[];
+  final field core::List<(self::B::S*) →* dynamic>* foo = core::_GrowableList::•<(self::B::S*) →* dynamic>(0);
+  final field core::List<(core::num*) →* dynamic>* bar = core::_GrowableList::•<(core::num*) →* dynamic>(0);
   synthetic constructor •() → self::B<self::B::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.textual_outline.expect
index 4e4aaf6..042fbfc 100644
--- a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.textual_outline.expect
@@ -1,6 +1,6 @@
 class A {
-  late num ;
-  invariantField;
+  late
+  num invariantField;
   covariant late num ;
   covariantField;
 }
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.textual_outline.expect
index 1932ec0..5e18cfd 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.textual_outline.expect
@@ -2,12 +2,9 @@
 
 methodDirect<T>(T value) {}
 var fieldDirect = <T>(T value) {
-  late;
-  final T local2;
-  late;
-  final int local4;
-  late;
-  final FutureOr<int> local6;
+  late final T local2;
+  late final int local4;
+  late final FutureOr<int> local6;
   local2 = value;
   local4 = 0;
   local6 = 0;
@@ -17,12 +14,9 @@
 };
 methodConditional<T>(bool b, T value) {}
 var fieldConditional = <T>(bool b, T value) {
-  late;
-  final T local2;
-  late;
-  final int local4;
-  late;
-  final FutureOr<int> local6;
+  late final T local2;
+  late final int local4;
+  late final FutureOr<int> local6;
   if (b) {
     local2 = value;
     local4 = 0;
@@ -37,8 +31,7 @@
 };
 methodCompound() {}
 var fieldCompound = () {
-  late;
-  final int local4;
+  late final int local4;
   local4 = 0;
   local4 += 0;
 };
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.textual_outline_modelled.expect
index be04eb0..ba94702 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.textual_outline_modelled.expect
@@ -5,18 +5,14 @@
 methodConditional<T>(bool b, T value) {}
 methodDirect<T>(T value) {}
 var fieldCompound = () {
-  late;
-  final int local4;
+  late final int local4;
   local4 = 0;
   local4 += 0;
 };
 var fieldConditional = <T>(bool b, T value) {
-  late;
-  final T local2;
-  late;
-  final int local4;
-  late;
-  final FutureOr<int> local6;
+  late final T local2;
+  late final int local4;
+  late final FutureOr<int> local6;
   if (b) {
     local2 = value;
     local4 = 0;
@@ -30,12 +26,9 @@
   local6 = 0;
 };
 var fieldDirect = <T>(T value) {
-  late;
-  final T local2;
-  late;
-  final int local4;
-  late;
-  final FutureOr<int> local6;
+  late final T local2;
+  late final int local4;
+  late final FutureOr<int> local6;
   local2 = value;
   local4 = 0;
   local6 = 0;
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.textual_outline.expect
index 8b2d8e6..7c35b6a 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.textual_outline.expect
@@ -1,8 +1,53 @@
 import 'dart:async';
+
 methodDirect<T>(T value) {}
-var fieldDirect = <T>(T value) { T local1; late T ;local2; int local3; late int ;local4; FutureOr<int> local5; late FutureOr;<int> [];local6; late T ;local7 = value; local1; local2; local3; local4; local5; local6; local7; };
+var fieldDirect = <T>(T value) {
+  T local1;
+  late T local2;
+  int local3;
+  late int local4;
+  FutureOr<int> local5;
+  late FutureOr<int> local6;
+  late T local7 = value;
+  local1;
+  local2;
+  local3;
+  local4;
+  local5;
+  local6;
+  local7;
+};
 methodConditional<T>(bool b, T value) {}
-var fieldConditional = <T>(bool b, T value) { T local1; late T ;local2; int local3; late int ;local4; FutureOr<int> local5; late FutureOr;<int> [];local6; late T ;local7 = value; if (b) { local1 = value; local2 = value; local3 = 0; local4 = 0; local5 = 0; local6 = 0; local7; } local1; local2; local3; local4; local5; local6; local7; };
+var fieldConditional = <T>(bool b, T value) {
+  T local1;
+  late T local2;
+  int local3;
+  late int local4;
+  FutureOr<int> local5;
+  late FutureOr<int> local6;
+  late T local7 = value;
+  if (b) {
+    local1 = value;
+    local2 = value;
+    local3 = 0;
+    local4 = 0;
+    local5 = 0;
+    local6 = 0;
+    local7;
+  }
+  local1;
+  local2;
+  local3;
+  local4;
+  local5;
+  local6;
+  local7;
+};
 methodCompound() {}
-var fieldCompound = () { int local3; late int ;local4; local3 += 0; local4 += 0; };
+var fieldCompound = () {
+  int local3;
+  late int local4;
+  local3 += 0;
+  local4 += 0;
+};
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.textual_outline_modelled.expect
index 46a4371..10d1b40 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.textual_outline_modelled.expect
@@ -6,24 +6,18 @@
 methodDirect<T>(T value) {}
 var fieldCompound = () {
   int local3;
-  late int;
-  local4;
+  late int local4;
   local3 += 0;
   local4 += 0;
 };
 var fieldConditional = <T>(bool b, T value) {
   T local1;
-  late T;
-  local2;
+  late T local2;
   int local3;
-  late int;
-  local4;
+  late int local4;
   FutureOr<int> local5;
-  late FutureOr;
-  <int>[];
-  local6;
-  late T;
-  local7 = value;
+  late FutureOr<int> local6;
+  late T local7 = value;
   if (b) {
     local1 = value;
     local2 = value;
@@ -43,17 +37,12 @@
 };
 var fieldDirect = <T>(T value) {
   T local1;
-  late T;
-  local2;
+  late T local2;
   int local3;
-  late int;
-  local4;
+  late int local4;
   FutureOr<int> local5;
-  late FutureOr;
-  <int>[];
-  local6;
-  late T;
-  local7 = value;
+  late FutureOr<int> local6;
+  late T local7 = value;
   local1;
   local2;
   local3;
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.outline.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.outline.expect
index 7c87b5f..08e7b3e 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.outline.expect
@@ -2,6 +2,13 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
 // Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
 //   void set property6(int i); // error
@@ -10,12 +17,12 @@
 //   late final int? property6;
 //                   ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
-//   void set property6(int i); // error
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
 //            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
-//   late final int? property6;
-//                   ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
 //
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
@@ -25,13 +32,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect
index 1e3b9c1..f982c6a 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect
@@ -2,6 +2,13 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
 // Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
 //   void set property6(int i); // error
@@ -10,12 +17,12 @@
 //   late final int? property6;
 //                   ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
-//   void set property6(int i); // error
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
 //            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
-//   late final int? property6;
-//                   ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
 //
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
@@ -25,13 +32,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect
index 1e3b9c1..f982c6a 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect
@@ -2,6 +2,13 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
 // Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
 //   void set property6(int i); // error
@@ -10,12 +17,12 @@
 //   late final int? property6;
 //                   ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
-//   void set property6(int i); // error
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
 //            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
-//   late final int? property6;
-//                   ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
 //
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
@@ -25,13 +32,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.textual_outline.expect
index 2045647..2470729 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.textual_outline.expect
@@ -1,19 +1,18 @@
 abstract class A {
-  late int ;
-  property4;
-  late int;
-  operator? (){}
-  property5;
+  late
+  int property4;
+  late
+  int? property5;
   covariant late int ;
   property6;
   A(this.property4, this.property5, this.property6);
 }
 abstract class B1 {
-  late ;
+  late
   final int property4;
-  late ;
+  late
   final int property5;
-  late ;
+  late
   final int? property6;
   B1(this.property4, this.property5, this.property6);
 }
@@ -23,12 +22,12 @@
   void set property6(int i);
 }
 abstract class C1 {
-  late int ;
-  property4;
-  late int ;
-  property5;
-  late int ;
-  property6;
+  late
+  int property4;
+  late
+  int property5;
+  late
+  int property6;
   C1(this.property4, this.property5, this.property6);
 }
 abstract class C2 implements C1 {
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect
index f3ffff6..8d9af18 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect
@@ -2,6 +2,13 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
 // Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
 //   void set property6(int i); // error
@@ -10,12 +17,12 @@
 //   late final int? property6;
 //                   ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
-//   void set property6(int i); // error
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
 //            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
-//   late final int? property6;
-//                   ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
 //
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
@@ -25,13 +32,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect
index f3ffff6..8d9af18 100644
--- a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect
@@ -2,6 +2,13 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
 // Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
 //   void set property6(int i); // error
@@ -10,12 +17,12 @@
 //   late final int? property6;
 //                   ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
-//   void set property6(int i); // error
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
 //            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
-//   late final int? property6;
-//                   ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
 //
 // pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
@@ -25,13 +32,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 import "dart:_internal" as _in;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart
index d444b164..be4ad50 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart
@@ -48,7 +48,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.expect
index 16fa8e0..477672b 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.expect
@@ -72,7 +72,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.transformed.expect
index 16fa8e0..477672b 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.strong.transformed.expect
@@ -72,7 +72,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.textual_outline.expect
index 4b4ba1f..6df6180 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.textual_outline.expect
@@ -1,8 +1,8 @@
 int nonNullableTopLevelFieldReads = 0;
-late ;
+late
 final int nonNullableTopLevelField = nonNullableTopLevelFieldReads++ == 0 ? nonNullableTopLevelField + 1 : 0;
 int nullableTopLevelFieldReads = 0;
-late ;
+late
 final int? nullableTopLevelField = nullableTopLevelFieldReads++ == 0 ? nullableTopLevelField.hashCode : 0;
 class Class {
   static int nonNullableStaticFieldReads = 0;
@@ -12,10 +12,10 @@
   static late ;
   final int? nullableStaticField = nullableStaticFieldReads++ == 0 ? nullableStaticField.hashCode : 0;
   int nonNullableInstanceFieldReads = 0;
-  late ;
+  late
   final int nonNullableInstanceField = nonNullableInstanceFieldReads++ == 0 ? nonNullableInstanceField + 1 : 0;
   int nullableInstanceFieldReads = 0;
-  late ;
+  late
   final int? nullableInstanceField = nullableInstanceFieldReads++ == 0 ? nullableInstanceField.hashCode : 0;
 }
 void main() {}
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.expect
index ad9e30d..f0df89a 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.expect
@@ -99,7 +99,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.transformed.expect
index ad9e30d..f0df89a 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.transformed.expect
@@ -99,7 +99,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart
index 2f01985..9c2a8e0 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart
@@ -57,7 +57,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.expect
index df72516..74f12ef 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.expect
@@ -75,7 +75,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.transformed.expect
index df72516..74f12ef 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.transformed.expect
@@ -75,7 +75,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.textual_outline.expect
index 181da77..6a82617 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.textual_outline.expect
@@ -1,9 +1,9 @@
 import 'initializer_rewrite_from_opt_out_lib.dart';
 int nonNullableTopLevelFieldReads = 0;
-late ;
+late
 final int nonNullableTopLevelField = nonNullableTopLevelFieldReads++ == 0 ? nonNullableTopLevelField : computeInitialValue();
 int nullableTopLevelFieldReads = 0;
-late ;
+late
 final int? nullableTopLevelField = nullableTopLevelFieldReads++ == 0 ? nullableTopLevelField : computeInitialValue();
 class Class {
   static int nonNullableStaticFieldReads = 0;
@@ -13,10 +13,10 @@
   static late ;
   final int? nullableStaticField = nullableStaticFieldReads++ == 0 ? nullableStaticField : computeInitialValue();
   int nonNullableInstanceFieldReads = 0;
-  late ;
+  late
   final int nonNullableInstanceField = nonNullableInstanceFieldReads++ == 0 ? nonNullableInstanceField : computeInitialValue();
   int nullableInstanceFieldReads = 0;
-  late ;
+  late
   final int? nullableInstanceField = nullableInstanceFieldReads++ == 0 ? nullableInstanceField : computeInitialValue();
 }
 void main() {}
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.expect
index fc0e98b..c0f506a 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.expect
@@ -102,7 +102,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.transformed.expect
index fc0e98b..c0f506a 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.transformed.expect
@@ -102,7 +102,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.textual_outline.expect
index 27c1e25..a65dd27 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.textual_outline.expect
@@ -1,17 +1,18 @@
 class Class {
-  late int ;
-  field = 10;
+  late int field = 10;
   Class.constructor1();
   Class.constructor2(this.field);
   Class.constructor3(int value) : this.field = value + 1;
   Class.constructor4([this.field = 42]);
 }
+
 class Subclass extends Class {
   Subclass.constructor1() : super.constructor1();
   Subclass.constructor2(int value) : super.constructor2(value);
   Subclass.constructor3(int value) : super.constructor3(value);
   Subclass.constructor4([int value = 87]) : super.constructor4(value);
 }
+
 test1() {}
 test2() {}
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..dc89fb9
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.textual_outline_modelled.expect
@@ -0,0 +1,20 @@
+class Class {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  Class.constructor1();
+  Class.constructor2(this.field);
+  Class.constructor3(int value) : this.field = value + 1;
+  Class.constructor4([this.field = 42]);
+  int field = 10;
+}
+class Subclass extends Class {
+  Subclass.constructor1() : super.constructor1();
+  Subclass.constructor2(int value) : super.constructor2(value);
+  Subclass.constructor3(int value) : super.constructor3(value);
+  Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+expect(expected, actual) {}
+main() {}
+test1() {}
+test2() {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart
index 637dae7..6e83a66 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart
@@ -85,7 +85,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
index 7fe4159..6e465d7 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
@@ -93,7 +93,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
index 7fe4159..6e465d7 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
@@ -93,7 +93,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.textual_outline.expect
index fc1edad..b4a35e3 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.textual_outline.expect
@@ -1,17 +1,18 @@
 class Class {
-  late int ;
-  field;
+  late int field;
   Class.constructor1();
   Class.constructor2(this.field);
   Class.constructor3(int value) : this.field = value + 1;
   Class.constructor4([this.field = 42]);
 }
+
 class Subclass extends Class {
   Subclass.constructor1() : super.constructor1();
   Subclass.constructor2(int value) : super.constructor2(value);
   Subclass.constructor3(int value) : super.constructor3(value);
   Subclass.constructor4([int value = 87]) : super.constructor4(value);
 }
+
 test1() {}
 test2() {}
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..342930e
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  Class.constructor1();
+  Class.constructor2(this.field);
+  Class.constructor3(int value) : this.field = value + 1;
+  Class.constructor4([this.field = 42]);
+  int field;
+}
+class Subclass extends Class {
+  Subclass.constructor1() : super.constructor1();
+  Subclass.constructor2(int value) : super.constructor2(value);
+  Subclass.constructor3(int value) : super.constructor3(value);
+  Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+expect(expected, actual) {}
+main() {}
+test1() {}
+test2() {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
index 1710036..5c9ecce 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
@@ -96,7 +96,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
index 1710036..5c9ecce 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
@@ -96,7 +96,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart
index 168a7d0..24676a7 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart
@@ -89,7 +89,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
index d212088..c480ab9 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
@@ -98,7 +98,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
index d212088..c480ab9 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
@@ -98,7 +98,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.textual_outline.expect
index 05f1676..b950438 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.textual_outline.expect
@@ -1,17 +1,18 @@
 class Class {
-  late ;
-  final int field;
+  late final int field;
   Class.constructor1();
   Class.constructor2(this.field);
   Class.constructor3(int value) : this.field = value + 1;
   Class.constructor4([this.field = 42]);
 }
+
 class Subclass extends Class {
   Subclass.constructor1() : super.constructor1();
   Subclass.constructor2(int value) : super.constructor2(value);
   Subclass.constructor3(int value) : super.constructor3(value);
   Subclass.constructor4([int value = 87]) : super.constructor4(value);
 }
+
 test1() {}
 test2() {}
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..21f03d0
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  Class.constructor1();
+  Class.constructor2(this.field);
+  Class.constructor3(int value) : this.field = value + 1;
+  Class.constructor4([this.field = 42]);
+  final int field;
+}
+class Subclass extends Class {
+  Subclass.constructor1() : super.constructor1();
+  Subclass.constructor2(int value) : super.constructor2(value);
+  Subclass.constructor3(int value) : super.constructor3(value);
+  Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+expect(expected, actual) {}
+main() {}
+test1() {}
+test2() {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
index effd7a1..2f21d23 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
@@ -101,7 +101,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
index effd7a1..2f21d23 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
@@ -101,7 +101,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.textual_outline.expect
index ece8159..9da4eef 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.textual_outline.expect
@@ -1,19 +1,20 @@
 int? initField() => 10;
+
 class Class {
-  late int;
-  operator? (){}
-  field = initField();
+  late int? field = initField();
   Class.constructor1();
   Class.constructor2(this.field);
   Class.constructor3(int value) : this.field = value + 1;
   Class.constructor4([this.field = 42]);
 }
+
 class Subclass extends Class {
   Subclass.constructor1() : super.constructor1();
   Subclass.constructor2(int value) : super.constructor2(value);
   Subclass.constructor3(int value) : super.constructor3(value);
   Subclass.constructor4([int value = 87]) : super.constructor4(value);
 }
+
 test1() {}
 test2() {}
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f6e9106
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  Class.constructor1();
+  Class.constructor2(this.field);
+  Class.constructor3(int value) : this.field = value + 1;
+  Class.constructor4([this.field = 42]);
+  int? field = initField();
+}
+class Subclass extends Class {
+  Subclass.constructor1() : super.constructor1();
+  Subclass.constructor2(int value) : super.constructor2(value);
+  Subclass.constructor3(int value) : super.constructor3(value);
+  Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+expect(expected, actual) {}
+int? initField() => 10;
+main() {}
+test1() {}
+test2() {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart
index 387ecbf..b08cd8d 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart
@@ -85,7 +85,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
index 76deb58..1692057 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
@@ -96,7 +96,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
index 76deb58..1692057 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -96,7 +96,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.textual_outline.expect
index d595eca..69c707c 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.textual_outline.expect
@@ -1,18 +1,18 @@
 class Class {
-  late int;
-  operator? (){}
-  field;
+  late int? field;
   Class.constructor1();
   Class.constructor2(this.field);
   Class.constructor3(int value) : this.field = value + 1;
   Class.constructor4([this.field = 42]);
 }
+
 class Subclass extends Class {
   Subclass.constructor1() : super.constructor1();
   Subclass.constructor2(int value) : super.constructor2(value);
   Subclass.constructor3(int value) : super.constructor3(value);
   Subclass.constructor4([int value = 87]) : super.constructor4(value);
 }
+
 test1() {}
 test2() {}
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5750785
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  Class.constructor1();
+  Class.constructor2(this.field);
+  Class.constructor3(int value) : this.field = value + 1;
+  Class.constructor4([this.field = 42]);
+  int? field;
+}
+class Subclass extends Class {
+  Subclass.constructor1() : super.constructor1();
+  Subclass.constructor2(int value) : super.constructor2(value);
+  Subclass.constructor3(int value) : super.constructor3(value);
+  Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+expect(expected, actual) {}
+main() {}
+test1() {}
+test2() {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
index 76deb58..1692057 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.expect
@@ -96,7 +96,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
index 76deb58..1692057 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -96,7 +96,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart
index 17346d7..7505ea0 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart
@@ -89,7 +89,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
index 310cc22..e4e4f30 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
@@ -101,7 +101,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
index 310cc22..e4e4f30 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
@@ -101,7 +101,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.textual_outline.expect
index cfc9fd3..14cc7955 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.textual_outline.expect
@@ -1,17 +1,18 @@
 class Class {
-  late ;
-  final int? field;
+  late final int? field;
   Class.constructor1();
   Class.constructor2(this.field);
   Class.constructor3(int value) : this.field = value + 1;
   Class.constructor4([this.field = 42]);
 }
+
 class Subclass extends Class {
   Subclass.constructor1() : super.constructor1();
   Subclass.constructor2(int value) : super.constructor2(value);
   Subclass.constructor3(int value) : super.constructor3(value);
   Subclass.constructor4([int value = 87]) : super.constructor4(value);
 }
+
 test1() {}
 test2() {}
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..196bf87
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  Class.constructor1();
+  Class.constructor2(this.field);
+  Class.constructor3(int value) : this.field = value + 1;
+  Class.constructor4([this.field = 42]);
+  final int? field;
+}
+class Subclass extends Class {
+  Subclass.constructor1() : super.constructor1();
+  Subclass.constructor2(int value) : super.constructor2(value);
+  Subclass.constructor3(int value) : super.constructor3(value);
+  Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+expect(expected, actual) {}
+main() {}
+test1() {}
+test2() {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
index 310cc22..e4e4f30 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.expect
@@ -101,7 +101,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
index 310cc22..e4e4f30 100644
--- a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.weak.transformed.expect
@@ -101,7 +101,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.transformed.expect
index c24f503..9d0dbc9 100644
--- a/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40093.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
     core::print(i);
   }
   {
-    core::Iterator<core::int> :sync-for-iterator = <core::int>[].{core::Iterable::iterator};
+    core::Iterator<core::int> :sync-for-iterator = core::_GrowableList::•<core::int>(0).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.transformed.expect
index c24f503..9d0dbc9 100644
--- a/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40093.dart.weak.transformed.expect
@@ -20,7 +20,7 @@
     core::print(i);
   }
   {
-    core::Iterator<core::int> :sync-for-iterator = <core::int>[].{core::Iterable::iterator};
+    core::Iterator<core::int> :sync-for-iterator = core::_GrowableList::•<core::int>(0).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.textual_outline.expect
index 654ad93..f1b177b 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.textual_outline.expect
@@ -1,7 +1,7 @@
 class C {
   num pi = 3.14;
-  late num ;
-  p1 = this.pi;
+  late
+  num p1 = this.pi;
   late ;
   final p2 = this.pi;
 }
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.textual_outline.expect
index af1e25c..b38c3b2 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.textual_outline.expect
@@ -1,8 +1,9 @@
 abstract class A {
-  late int ;
-  x;
+  late int x;
 }
+
 class _B implements A {
   int x = 3;
 }
+
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8364103
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+abstract class A {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  int x;
+}
+class _B implements A {
+  int x = 3;
+}
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.transformed.expect
index 6e6d809..6854c03 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
   no-such-method-forwarder get /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x() → core::int?
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
   no-such-method-forwarder set /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x(core::int? value) → void
-    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {
   new self::C::•();
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
index bf446b5..8d7842a 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
@@ -14,9 +14,9 @@
   no-such-method-forwarder get /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x() → core::int?
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
   no-such-method-forwarder set /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x#isSet(core::bool value) → void
-    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder set /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x(core::int? value) → void
-    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {
   new self::C::•();
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline.expect
index aad20ad..f848f78 100644
--- a/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline.expect
@@ -1,12 +1,13 @@
 class A<T> {
-  late T ;
-  x;
+  late T x;
 }
+
 class B<T> {
   T? _y;
   T? get y => _y;
   set y(T? val) {}
 }
+
 main() {}
 expect(expected, actual) {}
 throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fe9c799
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class A<T> {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  T x;
+}
+class B<T> {
+  T? _y;
+  T? get y => _y;
+  set y(T? val) {}
+}
+expect(expected, actual) {}
+main() {}
+throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart b/pkg/front_end/testcases/late_lowering/issue44372.dart
index 2550604..0415076 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart
@@ -35,7 +35,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect
index 2e8255b..6d44223 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.expect
@@ -40,7 +40,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect
index 2e8255b..6d44223 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect
index 16f8718..bc6ab71 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.expect
@@ -52,7 +52,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect
index 16f8718..bc6ab71 100644
--- a/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue44372.dart.weak.transformed.expect
@@ -52,7 +52,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.expect
index 3adbaa8..40eb00c 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.expect
@@ -170,3 +170,9 @@
 constants  {
   #C1 = self::Annotation {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_annotations.dart:
+- Annotation. (from org-dartlang-testcase:///late_annotations.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
index f9033f9..5f7ea3c 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
@@ -179,3 +179,9 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///late_annotations.dart:16:16 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///late_annotations.dart:72:25 -> IntConstant(0)
 Extra constant evaluation: evaluated: 268, effectively constant: 6
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_annotations.dart:
+- Annotation. (from org-dartlang-testcase:///late_annotations.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.textual_outline.expect
index 9c08694..e124df6 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.textual_outline.expect
@@ -2,23 +2,23 @@
   const Annotation();
 }
 @Annotation()
-late int ;
-topLevelField;
+late
+int topLevelField;
 @Annotation()
-late ;
+late
 final int finalTopLevelField;
 @Annotation()
-late ;
+late
 final int finalTopLevelFieldWithInitializer = 0;
 class A {
   @Annotation()
-  late int ;
-  instanceField;
+  late
+  int instanceField;
   @Annotation()
-  late ;
+  late
   final int finalInstanceField;
   @Annotation()
-  late ;
+  late
   final int finalInstanceFieldWithInitializer = 0;
   @Annotation()
   covariant late num ;
@@ -35,13 +35,13 @@
 }
 mixin B {
   @Annotation()
-  late int ;
-  instanceField;
+  late
+  int instanceField;
   @Annotation()
-  late ;
+  late
   final int finalInstanceField;
   @Annotation()
-  late ;
+  late
   final int finalInstanceFieldWithInitializer = 0;
   @Annotation()
   covariant late num ;
@@ -56,6 +56,15 @@
   static late ;
   final int finalStaticFieldWithInitializer = 0;
 }
-extension Extension ;
-on A (){}
+extension Extension on A {
+  @Annotation()
+  static late int ;
+  extensionStaticField;
+  @Annotation()
+  static late ;
+  final int finalExtensionStaticField;
+  @Annotation()
+  static late ;
+  final int finalExtensionStaticFieldWithInitializer = 0;
+}
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
index ad7345c..053c333 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
@@ -269,3 +269,9 @@
 constants  {
   #C1 = self::Annotation {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_annotations.dart:
+- Annotation. (from org-dartlang-testcase:///late_annotations.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
index ad7345c..053c333 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
@@ -269,3 +269,9 @@
 constants  {
   #C1 = self::Annotation {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_annotations.dart:
+- Annotation. (from org-dartlang-testcase:///late_annotations.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.textual_outline.expect
index 44ab46b..40fa799 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.textual_outline.expect
@@ -1,22 +1,27 @@
-late int ;
-lateTopLevelField1 = 123;
+late
+int lateTopLevelField1 = 123;
 class Class<T> {
   static late int ;
   lateStaticField1 = 87;
   static late int ;
   lateStaticField2 = 42;
   static staticMethod() {}
-  late int ;
-  lateInstanceField = 16;
+  late
+  int lateInstanceField = 16;
   final T field;
-  late T ;
-  lateGenericField1 = field;
-  late T ;
-  lateGenericField2 = field;
+  late
+  T lateGenericField1 = field;
+  late
+  T lateGenericField2 = field;
   Class(this.field);
   instanceMethod(T value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static late int ;
+  lateExtensionField1 = 87;
+  static late int ;
+  lateExtensionField2 = 42;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart
index 9d17619..5b68b28 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart
@@ -85,7 +85,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
index e6c2ae9..8bbf5d9 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
@@ -103,7 +103,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
index e6c2ae9..8bbf5d9 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
@@ -103,7 +103,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.textual_outline.expect
index 4d948d2..45d52d8 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.textual_outline.expect
@@ -1,19 +1,24 @@
-late int ;
-lateTopLevelField;
+late
+int lateTopLevelField;
 class Class<T> {
   static late int ;
   lateStaticField1;
   static late int ;
   lateStaticField2;
   static staticMethod() {}
-  late int ;
-  lateInstanceField;
-  late T ;
-  lateGenericInstanceField;
+  late
+  int lateInstanceField;
+  late
+  T lateGenericInstanceField;
   instanceMethod(T value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static late int ;
+  lateExtensionField1;
+  static late int ;
+  lateExtensionField2;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
index d782319..c20d687 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
@@ -123,7 +123,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
index d782319..c20d687 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
@@ -123,7 +123,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.textual_outline.expect
index 09efd13..08e1682 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.textual_outline.expect
@@ -10,7 +10,7 @@
 }
 int? lateTopLevelField1Init;
 int initLateTopLevelField1(int value) {}
-late ;
+late
 final int lateTopLevelField1 = initLateTopLevelField1(123);
 class Class<T> {
   static int? lateStaticField1Init;
@@ -24,17 +24,26 @@
   static staticMethod() {}
   int? lateInstanceFieldInit;
   int initLateInstanceField(int value) {}
-  late ;
+  late
   final int lateInstanceField = initLateInstanceField(16);
   T? lateGenericFieldInit;
   T initLateGenericField(T value) {}
   final T field;
-  late ;
+  late
   final T lateGenericField = initLateGenericField(field);
   Class(this.field);
   instanceMethod() {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static int? lateExtensionField1Init;
+  static int initLateExtensionField1(int value) {}
+  static late ;
+  final int lateExtensionField1 = initLateExtensionField1(87);
+  static int? lateExtensionField2Init;
+  static int initLateExtensionField2(int value) {}
+  static late ;
+  final int lateExtensionField2 = initLateExtensionField2(42);
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart
index 9aaefc1..34d4626 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart
@@ -79,7 +79,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
index 13abe89..f425376 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
@@ -109,7 +109,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
index 13abe89..f425376 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
@@ -109,7 +109,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.textual_outline.expect
index 7d7bf93..7a7f054 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.textual_outline.expect
@@ -1,4 +1,4 @@
-late ;
+late
 final int lateTopLevelField;
 class Class {
   static late ;
@@ -6,12 +6,17 @@
   static late ;
   final int lateStaticField2;
   static staticMethod() {}
-  late ;
+  late
   final int lateInstanceField;
   instanceMethod() {}
 }
-extension Extension ;
-on Class (){}
+extension Extension on Class {
+  static late ;
+  final int lateExtensionField1;
+  static late ;
+  final int lateExtensionField2;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
index 63c7b11..e2db739 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
@@ -129,7 +129,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
index 63c7b11..e2db739 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
@@ -129,7 +129,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart
index 31db7ec..10e63d9 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 main() {
-  bool b = false;
+  bool b = (() => false)();
   late final int lateLocal;
 
   if (b) {
@@ -50,7 +50,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
index 2240a48..103a9f9 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
@@ -4,7 +4,7 @@
 import "dart:_internal" as _in;
 
 static method main() → dynamic {
-  core::bool b = false;
+  core::bool b = (() → core::bool => false).call();
   lowered final core::int? #lateLocal;
   function #lateLocal#get() → core::int
     return let final core::int? #t1 = #lateLocal in #t1.==(null) ?{core::int} throw new _in::LateError::localNI("lateLocal") : #t1{core::int};
@@ -57,7 +57,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
index 2240a48..103a9f9 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
 import "dart:_internal" as _in;
 
 static method main() → dynamic {
-  core::bool b = false;
+  core::bool b = (() → core::bool => false).call();
   lowered final core::int? #lateLocal;
   function #lateLocal#get() → core::int
     return let final core::int? #t1 = #lateLocal in #t1.==(null) ?{core::int} throw new _in::LateError::localNI("lateLocal") : #t1{core::int};
@@ -57,7 +57,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
index 8f08ee7..4ed637a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
@@ -4,7 +4,7 @@
 import "dart:_internal" as _in;
 
 static method main() → dynamic {
-  core::bool b = false;
+  core::bool b = (() → core::bool => false).call();
   lowered final core::int? #lateLocal;
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
@@ -60,7 +60,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
index 8f08ee7..4ed637a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
@@ -4,7 +4,7 @@
 import "dart:_internal" as _in;
 
 static method main() → dynamic {
-  core::bool b = false;
+  core::bool b = (() → core::bool => false).call();
   lowered final core::int? #lateLocal;
   lowered core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
@@ -60,7 +60,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.textual_outline.expect
index fe6b1c3..14bd840 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.textual_outline.expect
@@ -1,6 +1,6 @@
 int? lateTopLevelField1Init;
 int? initLateTopLevelField1(int value) {}
-late ;
+late
 final int? lateTopLevelField1 = initLateTopLevelField1(123);
 class Class<T> {
   static int? lateStaticField1Init;
@@ -14,17 +14,26 @@
   static staticMethod() {}
   int? lateInstanceFieldInit;
   int? initLateInstanceField(int value) {}
-  late ;
+  late
   final int? lateInstanceField = initLateInstanceField(16);
   T? lateGenericInstanceFieldInit;
   T? initLateGenericInstanceField(T? value) {}
   final T? field;
-  late ;
+  late
   final T? lateGenericInstanceField = initLateGenericInstanceField(field);
   Class(this.field);
   instanceMethod() {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static int? lateExtensionField1Init;
+  static int? initLateExtensionField1(int value) {}
+  static late ;
+  final int? lateExtensionField1 = initLateExtensionField1(87);
+  static int? lateExtensionField2Init;
+  static int? initLateExtensionField2(int value) {}
+  static late ;
+  final int? lateExtensionField2 = initLateExtensionField2(42);
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart
index 525ba2c..6a06cad 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart
@@ -90,7 +90,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
index d2f5afa..b107b44 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
@@ -146,7 +146,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
index d2f5afa..b107b44 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -146,7 +146,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.textual_outline.expect
index 4d93692..8837f31 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.textual_outline.expect
@@ -1,4 +1,4 @@
-late ;
+late
 final int? lateTopLevelField;
 class Class<T> {
   static late ;
@@ -6,14 +6,19 @@
   static late ;
   final int? lateStaticField2;
   static staticMethod() {}
-  late ;
+  late
   final int? lateInstanceField;
-  late ;
+  late
   final T? lateGenericInstanceField;
   instanceMethod(T value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static late ;
+  final int? lateExtensionField1;
+  static late ;
+  final int? lateExtensionField2;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
index d2f5afa..b107b44 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.expect
@@ -146,7 +146,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
index d2f5afa..b107b44 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -146,7 +146,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
index 494d850..d76da4c 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
@@ -45,7 +45,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
index 5d5693d..9fa00df 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
@@ -54,7 +54,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
index 15d60ff..b844175 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -54,7 +54,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
index 5d5693d..9fa00df 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
@@ -54,7 +54,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
index 15d60ff..b844175 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -54,7 +54,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.textual_outline.expect
index fc1c0c8..234fa27 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.textual_outline.expect
@@ -18,18 +18,16 @@
 late ;
 var field6 = method6();
 class C<T> {
-  late FutureOr ;
-  field1;
-  late FutureOr;
-  operator? (){}
-  field2;
-  late FutureOr<T> (){}
-  field3;
-  late FutureOr<T?> (){}
-  field4;
-  late FutureOr<T?>(){}
-  operator? (){}
-  field5;
+  late
+  FutureOr field1;
+  late
+  FutureOr? field2;
+  late
+  FutureOr<T> field3;
+  late
+  FutureOr<T?> field4;
+  late
+  FutureOr<T?>? field5;
   method() {}
 }
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart
index 0fbd507..f64dacf 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart
@@ -29,7 +29,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
index a8ded51..40781ea 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
@@ -38,7 +38,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
index a8ded51..40781ea 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
@@ -38,7 +38,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
index 44d30d6..237c5ac 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
@@ -41,7 +41,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
index 44d30d6..237c5ac 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
@@ -41,7 +41,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.textual_outline.expect
index 83c95c1..f3cbcfe 100644
--- a/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_lowering_bitmasks.dart.textual_outline.expect
@@ -1,12 +1,12 @@
 main() {}
 method() {}
-late int ;
-uninitializedNonFinalTopLevelField;
-late ;
+late
+int uninitializedNonFinalTopLevelField;
+late
 final int uninitializedFinalTopLevelField;
-late int ;
-initializedNonFinalTopLevelField = 0;
-late ;
+late
+int initializedNonFinalTopLevelField = 0;
+late
 final int initializedFinalTopLevelField = 0;
 class Class {
   static late int ;
@@ -17,12 +17,12 @@
   initializedNonFinalStaticField = 0;
   static late ;
   final int initializedFinalStaticField = 0;
-  late int ;
-  uninitializedNonFinalInstanceField;
-  late ;
+  late
+  int uninitializedNonFinalInstanceField;
+  late
   final int uninitializedFinalInstanceField;
-  late int ;
-  initializedNonFinalInstanceField = 0;
-  late ;
+  late
+  int initializedNonFinalInstanceField = 0;
+  late
   final int initializedFinalInstanceField = 0;
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.textual_outline.expect
index c0352a0..83b91b4 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.textual_outline.expect
@@ -1,7 +1,6 @@
 int? lateTopLevelField1Init() => 123;
-late int;
-?
-lateTopLevelField1 = lateTopLevelField1Init();
+late
+int? lateTopLevelField1 = lateTopLevelField1Init();
 class Class<T> {
   static int? lateStaticField1Init() => 87;
   static late int;
@@ -13,18 +12,25 @@
   lateStaticField2 = lateStaticField2Init();
   static staticMethod() {}
   int? lateInstanceFieldInit() => 16;
-  late int;
-  operator? (){}
-  lateInstanceField = lateInstanceFieldInit();
+  late
+  int? lateInstanceField = lateInstanceFieldInit();
   final T? field;
   T? lateGenericInstanceFieldInit() => field;
-  late T;
-  operator? (){}
-  lateGenericInstanceField = lateGenericInstanceFieldInit();
+  late
+  T? lateGenericInstanceField = lateGenericInstanceFieldInit();
   Class(this.field);
   instanceMethod(T? value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static int? lateExtensionField1Init() => 87;
+  static late int;
+  operator? (){}
+  lateExtensionField1 = lateExtensionField1Init();
+  static int? lateExtensionField2Init() => 42;
+  static late int;
+  operator? (){}
+  lateExtensionField2 = lateExtensionField2Init();
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart
index b594a40..a161f23 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart
@@ -78,7 +78,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
index 5faf637..d01d771 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
@@ -119,7 +119,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
index 5faf637..d01d771 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -119,7 +119,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.textual_outline.expect
index f958db7..d0cb971 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.textual_outline.expect
@@ -1,6 +1,5 @@
-late int;
-?
-lateTopLevelField;
+late
+int? lateTopLevelField;
 class Class<T> {
   static late int;
   operator? (){}
@@ -9,16 +8,21 @@
   operator? (){}
   lateStaticField2;
   static staticMethod() {}
-  late int;
-  operator? (){}
-  lateInstanceField;
-  late T;
-  operator? (){}
-  lateGenericInstanceField;
+  late
+  int? lateInstanceField;
+  late
+  T? lateGenericInstanceField;
   instanceMethod(T? value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static late int;
+  operator? (){}
+  lateExtensionField1;
+  static late int;
+  operator? (){}
+  lateExtensionField2;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
index 5faf637..d01d771 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
@@ -119,7 +119,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
index 5faf637..d01d771 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -119,7 +119,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart
index 0e29214..ff5dfcd 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart
@@ -30,7 +30,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
index a635204..7fa4edc 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
@@ -42,7 +42,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
index a635204..7fa4edc 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -42,7 +42,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
index a635204..7fa4edc 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.expect
@@ -42,7 +42,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
index a635204..7fa4edc 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -42,7 +42,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart b/pkg/front_end/testcases/late_lowering/late_override.dart
new file mode 100644
index 0000000..d2a3ddd
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_override.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.
+
+class Interface {
+  late int implementedLateFieldDeclaredGetterSetter;
+}
+
+class Class implements Interface {
+  int get implementedLateFieldDeclaredGetterSetter => 0;
+
+  void set implementedLateFieldDeclaredGetterSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.outline.expect
new file mode 100644
index 0000000..4278a64
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.outline.expect
@@ -0,0 +1,21 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  field core::int? _#Interface#implementedLateFieldDeclaredGetterSetter;
+  synthetic constructor •() → self::Interface
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int;
+  set implementedLateFieldDeclaredGetterSetter(core::int #t1) → void;
+}
+class Class extends core::Object implements self::Interface {
+  synthetic constructor •() → self::Class
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    ;
+  set implementedLateFieldDeclaredGetterSetter(core::int value) → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.strong.expect
new file mode 100644
index 0000000..0dffea5
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.strong.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Interface extends core::Object {
+  field core::int? _#Interface#implementedLateFieldDeclaredGetterSetter = null;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    return let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} in #t1.==(null) ?{core::int} throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter") : #t1{core::int};
+  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+}
+class Class extends core::Object implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    return 0;
+  set implementedLateFieldDeclaredGetterSetter(core::int value) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.strong.transformed.expect
new file mode 100644
index 0000000..0dffea5
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Interface extends core::Object {
+  field core::int? _#Interface#implementedLateFieldDeclaredGetterSetter = null;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    return let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} in #t1.==(null) ?{core::int} throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter") : #t1{core::int};
+  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+}
+class Class extends core::Object implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    return 0;
+  set implementedLateFieldDeclaredGetterSetter(core::int value) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.textual_outline.expect
new file mode 100644
index 0000000..24986e8
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+class Interface {
+  late int implementedLateFieldDeclaredGetterSetter;
+}
+
+class Class implements Interface {
+  int get implementedLateFieldDeclaredGetterSetter => 0;
+  void set implementedLateFieldDeclaredGetterSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..61b08f4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class Class implements Interface {
+  int get implementedLateFieldDeclaredGetterSetter => 0;
+  void set implementedLateFieldDeclaredGetterSetter(int value) {}
+}
+class Interface {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  int implementedLateFieldDeclaredGetterSetter;
+}
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.expect
new file mode 100644
index 0000000..3f8b983
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Interface extends core::Object {
+  field core::int? _#Interface#implementedLateFieldDeclaredGetterSetter = null;
+  field core::bool _#Interface#implementedLateFieldDeclaredGetterSetter#isSet = false;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    return this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet} ?{core::int} let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} in #t1{core::int} : throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter");
+  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void {
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet} = true;
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+  }
+}
+class Class extends core::Object implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    return 0;
+  set implementedLateFieldDeclaredGetterSetter(core::int value) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/late_override.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.transformed.expect
new file mode 100644
index 0000000..3f8b983
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_override.dart.weak.transformed.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Interface extends core::Object {
+  field core::int? _#Interface#implementedLateFieldDeclaredGetterSetter = null;
+  field core::bool _#Interface#implementedLateFieldDeclaredGetterSetter#isSet = false;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    return this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet} ?{core::int} let final core::int? #t1 = this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} in #t1{core::int} : throw new _in::LateError::fieldNI("implementedLateFieldDeclaredGetterSetter");
+  set implementedLateFieldDeclaredGetterSetter(core::int #t2) → void {
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter#isSet} = true;
+    this.{self::Interface::_#Interface#implementedLateFieldDeclaredGetterSetter} = #t2;
+  }
+}
+class Class extends core::Object implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  get implementedLateFieldDeclaredGetterSetter() → core::int
+    return 0;
+  set implementedLateFieldDeclaredGetterSetter(core::int value) → void {}
+}
+static method main() → dynamic {}
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 0b84933..74694bf 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
@@ -134,28 +134,28 @@
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
     core::print(s);
   }
-  return "hest";
+  return let final core::String #t8 = "hest" in #t8 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t8 : #t8;
 }
 static method fisk() → dynamic async {
   lowered core::String? #s1;
   function #s1#get() → core::String
-    return let final core::String? #t8 = #s1 in #t8.==(null) ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
+    return let final core::String? #t9 = #s1 in #t9.==(null) ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
   late String s1 = await hest(); // Error.
-                   ^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::String : #t8{core::String};
-  function #s1#set(core::String #t9) → dynamic
-    return #s1 = #t9;
+                   ^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::String : #t9{core::String};
+  function #s1#set(core::String #t10) → dynamic
+    return #s1 = #t10;
   lowered core::String? #s2;
   function #s2#get() → core::String
-    return let final core::String? #t10 = #s2 in #t10.==(null) ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
+    return let final core::String? #t11 = #s2 in #t11.==(null) ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}'; // Error.
-                             ^^^^^"}${#C1}" : #t10{core::String};
-  function #s2#set(core::String #t11) → dynamic
-    return #s2 = #t11;
+                             ^^^^^"}${#C1}" : #t11{core::String};
+  function #s2#set(core::String #t12) → dynamic
+    return #s2 = #t12;
   lowered core::Function? #f;
   function #f#get() → core::Function
-    return let final core::Function? #t12 = #f in #t12.==(null) ?{core::Function} #f = () → asy::Future<dynamic> async => await self::hest() : #t12{core::Function};
-  function #f#set(core::Function #t13) → dynamic
-    return #f = #t13;
+    return let final core::Function? #t13 = #f in #t13.==(null) ?{core::Function} #f = () → asy::Future<dynamic> async => let final dynamic #t14 = await self::hest() in #t14 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t14 : #t14 : #t13{core::Function};
+  function #f#set(core::Function #t15) → dynamic
+    return #f = #t15;
 }
 static method main() → dynamic {}
 
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 f251299..09236c4 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
@@ -122,7 +122,7 @@
     core::print("baz");
   }
   {
-    core::Iterator<core::String> :sync-for-iterator = <core::String>["baz"].{core::Iterable::iterator};
+    core::Iterator<core::String> :sync-for-iterator = core::_GrowableList::_literal1<core::String>("baz").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -131,7 +131,7 @@
     }
   }
   block {
-    final core::List<core::int> #t7 = <core::int>[];
+    final core::List<core::int> #t7 = core::_GrowableList::•<core::int>(0);
     for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1))
       #t7.{core::List::add}{Invariant}(i);
   } =>#t7;
@@ -148,12 +148,14 @@
   dynamic :saved_try_context_var1;
   dynamic :exception0;
   dynamic :stack_trace0;
+  FutureOr<dynamic>:async_temporary_0;
+  FutureOr<dynamic>:async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
       {
         {
-          asy::Stream<core::String> :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
+          asy::Stream<core::String> :stream = asy::Stream::fromIterable<core::String>(core::_GrowableList::_literal1<core::String>("hest"));
           asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
           try
             #L2:
@@ -175,7 +177,15 @@
               :result;
             }
         }
-        :return_value = "hest";
+        final core::String #t11 = "hest";
+        if(#t11 is asy::Future<dynamic>) {
+          [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_1 = _in::unsafeCast<core::String>(:result);
+        }
+        else {
+          :async_temporary_1 = #t11;
+        }
+        :return_value = :async_temporary_1;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -204,21 +214,21 @@
       {
         lowered core::String? #s1;
         function #s1#get() → core::String
-          return let final core::String? #t11 = #s1 in #t11.==(null) ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
+          return let final core::String? #t13 = #s1 in #t13.==(null) ?{core::String} #s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
   late String s1 = await hest(); // Error.
-                   ^^^^^" : #t11{core::String};
-        function #s1#set(core::String #t12) → dynamic
-          return #s1 = #t12;
+                   ^^^^^" : #t13{core::String};
+        function #s1#set(core::String #t14) → dynamic
+          return #s1 = #t14;
         lowered core::String? #s2;
         function #s2#get() → core::String
-          return let final core::String? #t13 = #s2 in #t13.==(null) ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
+          return let final core::String? #t15 = #s2 in #t15.==(null) ?{core::String} #s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}'; // Error.
-                             ^^^^^"}${#C1}" : #t13{core::String};
-        function #s2#set(core::String #t14) → dynamic
-          return #s2 = #t14;
+                             ^^^^^"}${#C1}" : #t15{core::String};
+        function #s2#set(core::String #t16) → dynamic
+          return #s2 = #t16;
         lowered core::Function? #f;
         function #f#get() → core::Function
-          return let final core::Function? #t15 = #f in #t15.==(null) ?{core::Function} #f = () → asy::Future<dynamic> /* originally async */ {
+          return let final core::Function? #t17 = #f in #t17.==(null) ?{core::Function} #f = () → asy::Future<dynamic> /* originally async */ {
             final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
             core::bool* :is_sync = false;
             FutureOr<dynamic>? :return_value;
@@ -227,12 +237,21 @@
             core::int :await_jump_var = 0;
             dynamic :await_ctx_var;
             dynamic :saved_try_context_var0;
+            FutureOr<dynamic>:async_temporary_0;
             function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
               try {
                 #L4:
                 {
-                  [yield] let dynamic #t16 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                  :return_value = :result;
+                  [yield] let dynamic #t18 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  final dynamic #t19 = :result;
+                  if(#t19 is asy::Future<dynamic>) {
+                    [yield] let dynamic #t20 = asy::_awaitHelper(#t19, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = :result;
+                  }
+                  else {
+                    :async_temporary_0 = #t19;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L4;
                 }
                 asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -246,9 +265,9 @@
             :async_op.call();
             :is_sync = true;
             return :async_future;
-          } : #t15{core::Function};
-        function #f#set(core::Function #t17) → dynamic
-          return #f = #t17;
+          } : #t17{core::Function};
+        function #f#set(core::Function #t21) → dynamic
+          return #f = #t21;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
       return;
@@ -270,4 +289,4 @@
 
 Extra constant evaluation status:
 Evaluated: VariableGet @ org-dartlang-testcase:///later.dart:46:18 -> IntConstant(42)
-Extra constant evaluation: evaluated: 207, effectively constant: 1
+Extra constant evaluation: evaluated: 234, effectively constant: 1
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/later.dart.textual_outline.expect
index ba6d922..ec9372a 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.textual_outline.expect
@@ -1,8 +1,8 @@
 // @dart = 2.9999
 class A {
   int a = 42;
-  late int ;
-  b = (this.a * 2) >> 1;
+  late
+  int b = (this.a * 2) >> 1;
   foo(late int x) {}
 }
 bar(late int x) {}
@@ -10,12 +10,12 @@
 hest() async {}
 fisk() async {}
 class B {
-  late ;
+  late
   final int x = 42;
   const B();
 }
 class C {
-  late ;
+  late
   final int x;
   initVars() {}
 }
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 7123dd80..0d0243b 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
@@ -154,7 +154,7 @@
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
     core::print(s);
   }
-  return "hest";
+  return let final core::String #t8 = "hest" in #t8 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t8 : #t8;
 }
 static method fisk() → dynamic async {
   lowered core::String? #s1;
@@ -168,9 +168,9 @@
     }
     return #s1{core::String};
   }
-  function #s1#set(core::String #t8) → dynamic {
+  function #s1#set(core::String #t9) → dynamic {
     #s1#isSet = true;
-    return #s1 = #t8;
+    return #s1 = #t9;
   }
   lowered core::String? #s2;
   lowered core::bool #s2#isSet = false;
@@ -183,22 +183,22 @@
     }
     return #s2{core::String};
   }
-  function #s2#set(core::String #t9) → dynamic {
+  function #s2#set(core::String #t10) → dynamic {
     #s2#isSet = true;
-    return #s2 = #t9;
+    return #s2 = #t10;
   }
   lowered core::Function? #f;
   lowered core::bool #f#isSet = false;
   function #f#get() → core::Function {
     if(!#f#isSet) {
-      #f = () → asy::Future<dynamic> async => await self::hest();
+      #f = () → asy::Future<dynamic> async => let final dynamic #t11 = await self::hest() in #t11 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t11 : #t11;
       #f#isSet = true;
     }
     return #f{core::Function};
   }
-  function #f#set(core::Function #t10) → dynamic {
+  function #f#set(core::Function #t12) → dynamic {
     #f#isSet = true;
-    return #f = #t10;
+    return #f = #t12;
   }
 }
 static method main() → dynamic {}
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 11b98b1..7fe5b1b 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
@@ -142,7 +142,7 @@
     core::print("baz");
   }
   {
-    core::Iterator<core::String> :sync-for-iterator = <core::String>["baz"].{core::Iterable::iterator};
+    core::Iterator<core::String> :sync-for-iterator = core::_GrowableList::_literal1<core::String>("baz").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -151,7 +151,7 @@
     }
   }
   block {
-    final core::List<core::int> #t7 = <core::int>[];
+    final core::List<core::int> #t7 = core::_GrowableList::•<core::int>(0);
     for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1))
       #t7.{core::List::add}{Invariant}(i);
   } =>#t7;
@@ -168,12 +168,14 @@
   dynamic :saved_try_context_var1;
   dynamic :exception0;
   dynamic :stack_trace0;
+  FutureOr<dynamic>:async_temporary_0;
+  FutureOr<dynamic>:async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
       {
         {
-          asy::Stream<core::String> :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
+          asy::Stream<core::String> :stream = asy::Stream::fromIterable<core::String>(core::_GrowableList::_literal1<core::String>("hest"));
           asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
           try
             #L2:
@@ -195,7 +197,15 @@
               :result;
             }
         }
-        :return_value = "hest";
+        final core::String #t11 = "hest";
+        if(#t11 is asy::Future<dynamic>) {
+          [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_1 = _in::unsafeCast<core::String>(:result);
+        }
+        else {
+          :async_temporary_1 = #t11;
+        }
+        :return_value = :async_temporary_1;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -233,9 +243,9 @@
           }
           return #s1{core::String};
         }
-        function #s1#set(core::String #t11) → dynamic {
+        function #s1#set(core::String #t13) → dynamic {
           #s1#isSet = true;
-          return #s1 = #t11;
+          return #s1 = #t13;
         }
         lowered core::String? #s2;
         lowered core::bool #s2#isSet = false;
@@ -248,9 +258,9 @@
           }
           return #s2{core::String};
         }
-        function #s2#set(core::String #t12) → dynamic {
+        function #s2#set(core::String #t14) → dynamic {
           #s2#isSet = true;
-          return #s2 = #t12;
+          return #s2 = #t14;
         }
         lowered core::Function? #f;
         lowered core::bool #f#isSet = false;
@@ -265,12 +275,21 @@
               core::int :await_jump_var = 0;
               dynamic :await_ctx_var;
               dynamic :saved_try_context_var0;
+              FutureOr<dynamic>:async_temporary_0;
               function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
                 try {
                   #L4:
                   {
-                    [yield] let dynamic #t13 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                    :return_value = :result;
+                    [yield] let dynamic #t15 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                    final dynamic #t16 = :result;
+                    if(#t16 is asy::Future<dynamic>) {
+                      [yield] let dynamic #t17 = asy::_awaitHelper(#t16, :async_op_then, :async_op_error, :async_op) in null;
+                      :async_temporary_0 = :result;
+                    }
+                    else {
+                      :async_temporary_0 = #t16;
+                    }
+                    :return_value = :async_temporary_0;
                     break #L4;
                   }
                   asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -289,9 +308,9 @@
           }
           return #f{core::Function};
         }
-        function #f#set(core::Function #t14) → dynamic {
+        function #f#set(core::Function #t18) → dynamic {
           #f#isSet = true;
-          return #f = #t14;
+          return #f = #t18;
         }
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/late_lowering/override.dart b/pkg/front_end/testcases/late_lowering/override.dart
index 69afea9..87d8858 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart
+++ b/pkg/front_end/testcases/late_lowering/override.dart
@@ -91,7 +91,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.strong.expect b/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
index bc88c3f..6fa984a 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.strong.expect
@@ -113,7 +113,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
index 6b5321f..31e4f1c 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
@@ -113,7 +113,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/override.dart.textual_outline.expect
index b463007..cfa03cf 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.textual_outline.expect
@@ -1,22 +1,15 @@
 class Class {
-  late int ;
-  field1;
-  late int ;
-  field2;
-  late ;
-  final int field3;
-  late ;
-  final int field4;
+  late int field1;
+  late int field2;
+  late final int field3;
+  late final int field4;
 }
+
 class SubClass extends Class {
-  late int ;
-  field1;
-  late int ;
-  field2 = 0;
-  late ;
-  final int field3;
-  late ;
-  final int field4 = 0;
+  late int field1;
+  late int field2 = 0;
+  late final int field3;
+  late final int field4 = 0;
   int get directField1 => super.field1;
   void set directField1(int value) {}
   int get directField2 => super.field2;
@@ -24,6 +17,7 @@
   int get directField3 => super.field3;
   int get directField4 => super.field4;
 }
+
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/override.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..42e50bd
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/override.dart.textual_outline_modelled.expect
@@ -0,0 +1,45 @@
+class Class {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  int field1;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  int field2;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int field3;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int field4;
+}
+class SubClass extends Class {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  int field1;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  int field2 = 0;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int field3;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int field4 = 0;
+  int get directField1 => super.field1;
+  int get directField2 => super.field2;
+  int get directField3 => super.field3;
+  int get directField4 => super.field4;
+  void set directField1(int value) {}
+  void set directField2(int value) {}
+}
+expect(expected, actual) {}
+main() {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
index ee8f06d..9b3ba60 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
@@ -148,7 +148,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
index ee8f06d..9b3ba60 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
@@ -148,7 +148,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart
index 6ef5ecc..c6fd9a3 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart
@@ -45,7 +45,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.expect
index a40aad4..600c0c9 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.expect
@@ -81,7 +81,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
index 270a287..474f90a 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
@@ -81,7 +81,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.textual_outline.expect
index 4594586..a38c2ae 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.textual_outline.expect
@@ -1,19 +1,18 @@
 class A {
-  late ;
-  final int x;
-  late ;
-  final int? y;
+  late final int x;
+  late final int? y;
 }
+
 class B extends A {
   int get x => 1;
   int? get y => 1;
 }
+
 class C extends A {
-  late ;
-  final int x = 2;
-  late ;
-  final int? y = 2;
+  late final int x = 2;
+  late final int? y = 2;
 }
+
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5650775
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,27 @@
+class A {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int x;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int? y;
+}
+class B extends A {
+  int? get y => 1;
+  int get x => 1;
+}
+class C extends A {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int x = 2;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int? y = 2;
+}
+expect(expected, actual) {}
+main() {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
index ed7604c..1cb53d8 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
@@ -93,7 +93,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
index ed7604c..1cb53d8 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
@@ -93,7 +93,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.textual_outline.expect
index 83c95c1..f3cbcfe 100644
--- a/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/skip_late_final_uninitialized_instance_fields/main.dart.textual_outline.expect
@@ -1,12 +1,12 @@
 main() {}
 method() {}
-late int ;
-uninitializedNonFinalTopLevelField;
-late ;
+late
+int uninitializedNonFinalTopLevelField;
+late
 final int uninitializedFinalTopLevelField;
-late int ;
-initializedNonFinalTopLevelField = 0;
-late ;
+late
+int initializedNonFinalTopLevelField = 0;
+late
 final int initializedFinalTopLevelField = 0;
 class Class {
   static late int ;
@@ -17,12 +17,12 @@
   initializedNonFinalStaticField = 0;
   static late ;
   final int initializedFinalStaticField = 0;
-  late int ;
-  uninitializedNonFinalInstanceField;
-  late ;
+  late
+  int uninitializedNonFinalInstanceField;
+  late
   final int uninitializedFinalInstanceField;
-  late int ;
-  initializedNonFinalInstanceField = 0;
-  late ;
+  late
+  int initializedNonFinalInstanceField = 0;
+  late
   final int initializedFinalInstanceField = 0;
 }
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.textual_outline.expect
index 7432afc..2fcb7a6 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.textual_outline.expect
@@ -1,7 +1,7 @@
 class A {
-  late int ;
-  x;
+  late int x;
   A.foo(this.x);
   A.bar();
 }
+
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..16afc20
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class A {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  A.bar();
+  A.foo(this.x);
+  int x;
+}
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline.expect
index 521d4d6..9e2ee67 100644
--- a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline.expect
@@ -1,21 +1,10 @@
-late int;
-?
-nullableTopLevelField;
-late int ;
-nonNullableTopLevelField;
-late int;
-?
-nullableTopLevelFieldWithInitializer = null;
-late int ;
-nonNullableTopLevelFieldWithInitializer = 0;
-late ;
-final int? nullableFinalTopLevelField;
-late ;
-final int nonNullableFinalTopLevelField;
-late ;
-final int? nullableFinalTopLevelFieldWithInitializer = null;
-late ;
-final int nonNullableFinalTopLevelFieldWithInitializer = 0;
-late Never ;
-neverTopLevelField;
+late int? nullableTopLevelField;
+late int nonNullableTopLevelField;
+late int? nullableTopLevelFieldWithInitializer = null;
+late int nonNullableTopLevelFieldWithInitializer = 0;
+late final int? nullableFinalTopLevelField;
+late final int nonNullableFinalTopLevelField;
+late final int? nullableFinalTopLevelFieldWithInitializer = null;
+late final int nonNullableFinalTopLevelFieldWithInitializer = 0;
+late Never neverTopLevelField;
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8b9ef40
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline_modelled.expect
@@ -0,0 +1,37 @@
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+int? nullableTopLevelField;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+int nonNullableTopLevelField;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+int? nullableTopLevelFieldWithInitializer = null;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+int nonNullableTopLevelFieldWithInitializer = 0;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+final int? nullableFinalTopLevelField;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+final int nonNullableFinalTopLevelField;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+final int? nullableFinalTopLevelFieldWithInitializer = null;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+final int nonNullableFinalTopLevelFieldWithInitializer = 0;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+Never neverTopLevelField;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
index 69a99ab..a2e1e46 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
@@ -26,6 +26,10 @@
   external abstract final int externalFinalInstanceField;
   external abstract covariant num externalCovariantInstanceField;
 }
-extension Extension ;
-on A (){}
+extension Extension on A {
+  abstract int extensionInstanceField;
+  abstract final int finalExtensionInstanceField;
+  abstract static int extensionStaticField = 0;
+  abstract static final int finalExtensionStaticField = 0;
+}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.expect b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.expect
index a4b4cdc..6769397 100644
--- a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.expect
@@ -263,35 +263,35 @@
   }
   function local() → FutureOr<self::A> async {
     if(true) {
-      return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
+      return let final self::B? #t6 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return x; // Error.
-             ^" in x as{TypeError,ForNonNullableByDefault} self::A;
+             ^" in x as{TypeError,ForNonNullableByDefault} self::A in #t6 is asy::Future<self::A> ?{FutureOr<self::A>} await #t6 : #t6;
     }
     else {
-      return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
+      return let final asy::Future<self::B?> #t8 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<B?>.value(x); // Error.
-                 ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A;
+                 ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A in #t8 is asy::Future<self::A> ?{FutureOr<self::A>} await #t8 : #t8;
     }
   }
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   return x; // Error.
          ^" in x as{TypeError,ForNonNullableByDefault} self::A;
 }
 static method bar(core::List<self::B?> x, core::List<core::List<self::B?>> l, core::Map<core::List<self::B?>, core::List<self::B?>> m) → core::List<self::A> {
-  self::barContext(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  self::barContext(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   barContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>);
-  core::List<self::A> y = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -314,16 +314,16 @@
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   <List<A>, List<A>>{...m}; // Error.
                         ^"};
-  for (final core::List<self::B?> #t11 in l) {
-    core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  for (final core::List<self::B?> #t13 in l) {
+    core::List<self::A> y = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
 Try changing the type of the variable.
   for (List<A> y in l) {} // Error.
-               ^" in #t11 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
+               ^" in #t13 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
   }
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -331,52 +331,52 @@
          ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>;
 }
 static method baz(self::C c) → void {
-  self::bazContext(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
+  self::bazContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
   bazContext(c);
-             ^" in (let final self::C #t15 = c in #t15.==(null) ?{() → core::num?} null : #t15.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
+             ^" in (let final self::C #t17 = c in #t17.==(null) ?{() → core::num?} null : #t17.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
 }
 static method boz(Null x) → self::A {
-  self::fooContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} self::A);
-  self::fooContext(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(null); // Error.
              ^" in null as{TypeError,ForNonNullableByDefault} self::A);
-  self::A a1 = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a1 = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a1 = x; // Error.
          ^" in x as{TypeError,ForNonNullableByDefault} self::A;
-  self::A a2 = let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a2 = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a2 = null; // Error.
          ^" in null as{TypeError,ForNonNullableByDefault} self::A;
   if(true) {
-    return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return x; // Error.
            ^" in x as{TypeError,ForNonNullableByDefault} self::A;
   }
   else {
-    return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return null; // Error.
            ^" in null as{TypeError,ForNonNullableByDefault} self::A;
   }
   function local() → FutureOr<self::A> async {
     if(true) {
-      return let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
+      return let final Null #t24 = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return null; // Error.
-             ^" in null as{TypeError,ForNonNullableByDefault} self::A;
+             ^" in null as{TypeError,ForNonNullableByDefault} self::A in #t24 is asy::Future<self::A> ?{FutureOr<self::A>} await #t24 : #t24;
     }
     else {
-      return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
+      return let final asy::Future<Null> #t26 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<Null>.value(null); // Error.
-                 ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A;
+                 ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A in #t26 is asy::Future<self::A> ?{FutureOr<self::A>} await #t26 : #t26;
     }
   }
 }
@@ -385,3 +385,9 @@
 constants  {
   #C1 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///assignability_error_messages.dart:
+- A. (from org-dartlang-testcase:///assignability_error_messages.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.transformed.expect
index d02c7bc..c855781 100644
--- a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.strong.transformed.expect
@@ -180,6 +180,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -213,14 +214,14 @@
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a = x; // Error.
         ^" in let self::B? #t4 = x in #t4.==(null) ?{self::A} #t4 as{TypeError,ForNonNullableByDefault} self::A : #t4{self::A};
-  <self::A>[invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:29:10: Error: Can't assign spread elements of type 'B?' to collection elements of type 'A' because 'B?' is nullable and 'A' isn't.
+  core::_GrowableList::_literal1<self::A>(invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:29:10: Error: Can't assign spread elements of type 'B?' to collection elements of type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   <A>[...l]; // Error.
-         ^"];
-  <self::A>[invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:30:10: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+         ^");
+  core::_GrowableList::_literal1<self::A>(invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:30:10: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
   <A>[...l2]; // Error.
-         ^"];
+         ^");
   <self::A, self::A>{invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:31:13: Error: Can't assign spread entry keys of type 'B?' to map entry keys of type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -280,25 +281,45 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<self::A>:async_temporary_0;
+    FutureOr<self::A>:async_temporary_1;
+    FutureOr<self::A>:async_temporary_2;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L4:
         {
           if(true) {
-            :return_value = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
+            final self::B? #t10 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return x; // Error.
-             ^" in let self::B? #t11 = x in #t11.==(null) ?{self::A} #t11 as{TypeError,ForNonNullableByDefault} self::A : #t11{self::A};
+             ^" in let self::B? #t12 = x in #t12.==(null) ?{self::A} #t12 as{TypeError,ForNonNullableByDefault} self::A : #t12{self::A};
+            if(#t10 is asy::Future<self::A>) {
+              [yield] let dynamic #t13 = asy::_awaitHelper(#t10, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_0 = _in::unsafeCast<self::B?>(:result);
+            }
+            else {
+              :async_temporary_0 = #t10;
+            }
+            :return_value = :async_temporary_0;
             break #L4;
           }
           else {
-            :return_value = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
+            final asy::Future<self::B?> #t14 = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<B?>.value(x); // Error.
                  ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A;
+            if(#t14 is asy::Future<self::A>) {
+              [yield] let dynamic #t16 = asy::_awaitHelper(#t14, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_2 = _in::unsafeCast<self::B?>(:result);
+            }
+            else {
+              :async_temporary_2 = #t14;
+            }
+            :return_value = :async_temporary_2;
             break #L4;
           }
         }
@@ -314,31 +335,31 @@
     :is_sync = true;
     return :async_future;
   }
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   return x; // Error.
-         ^" in let self::B? #t14 = x in #t14.==(null) ?{self::A} #t14 as{TypeError,ForNonNullableByDefault} self::A : #t14{self::A};
+         ^" in let self::B? #t18 = x in #t18.==(null) ?{self::A} #t18 as{TypeError,ForNonNullableByDefault} self::A : #t18{self::A};
 }
 static method bar(core::List<self::B?> x, core::List<core::List<self::B?>> l, core::Map<core::List<self::B?>, core::List<self::B?>> m) → core::List<self::A> {
-  self::barContext(let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  self::barContext(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   barContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>);
-  core::List<self::A> y = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::List<self::A> y = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   List<A> y = x; // Error.
               ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>;
-  <core::List<self::A>>[invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:55:16: Error: Can't assign spread elements of type 'List<B?>' to collection elements of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::_GrowableList::_literal1<core::List<self::A>>(invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:55:16: Error: Can't assign spread elements of type 'List<B?>' to collection elements of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   <List<A>>[...l]; // Error.
-               ^"];
+               ^");
   <core::List<self::A>, core::List<self::A>>{invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:56:25: Error: Can't assign spread entry keys of type 'List<B?>' to map entry keys of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -353,19 +374,19 @@
   {
     core::Iterator<core::List<self::B?>> :sync-for-iterator = l.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-      final core::List<self::B?> #t17 = :sync-for-iterator.{core::Iterator::current};
+      final core::List<self::B?> #t21 = :sync-for-iterator.{core::Iterator::current};
       {
-        core::List<self::A> y = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+        core::List<self::A> y = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
 Try changing the type of the variable.
   for (List<A> y in l) {} // Error.
-               ^" in #t17 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
+               ^" in #t21 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
       }
     }
   }
-  return let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -373,38 +394,38 @@
          ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>;
 }
 static method baz(self::C c) → void {
-  self::bazContext(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
+  self::bazContext(let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
   bazContext(c);
-             ^" in (let final self::C #t21 = c in #t21.==(null) ?{() → core::num?} null : #t21.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
+             ^" in (let final self::C #t25 = c in #t25.==(null) ?{() → core::num?} null : #t25.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
 }
 static method boz(Null x) → self::A {
-  self::fooContext(let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(x); // Error.
-             ^" in let Null #t23 = x in #t23.==(null) ?{self::A} #t23 as{TypeError,ForNonNullableByDefault} self::A : #t23{self::A});
-  self::fooContext(let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+             ^" in let Null #t27 = x in #t27.==(null) ?{self::A} #t27 as{TypeError,ForNonNullableByDefault} self::A : #t27{self::A});
+  self::fooContext(let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(null); // Error.
-             ^" in let Null #t25 = null in #t25.==(null) ?{self::A} #t25 as{TypeError,ForNonNullableByDefault} self::A : #t25{self::A});
-  self::A a1 = let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+             ^" in let Null #t29 = null in #t29.==(null) ?{self::A} #t29 as{TypeError,ForNonNullableByDefault} self::A : #t29{self::A});
+  self::A a1 = let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a1 = x; // Error.
-         ^" in let Null #t27 = x in #t27.==(null) ?{self::A} #t27 as{TypeError,ForNonNullableByDefault} self::A : #t27{self::A};
-  self::A a2 = let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+         ^" in let Null #t31 = x in #t31.==(null) ?{self::A} #t31 as{TypeError,ForNonNullableByDefault} self::A : #t31{self::A};
+  self::A a2 = let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a2 = null; // Error.
-         ^" in let Null #t29 = null in #t29.==(null) ?{self::A} #t29 as{TypeError,ForNonNullableByDefault} self::A : #t29{self::A};
+         ^" in let Null #t33 = null in #t33.==(null) ?{self::A} #t33 as{TypeError,ForNonNullableByDefault} self::A : #t33{self::A};
   if(true) {
-    return let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return x; // Error.
-           ^" in let Null #t31 = x in #t31.==(null) ?{self::A} #t31 as{TypeError,ForNonNullableByDefault} self::A : #t31{self::A};
+           ^" in let Null #t35 = x in #t35.==(null) ?{self::A} #t35 as{TypeError,ForNonNullableByDefault} self::A : #t35{self::A};
   }
   else {
-    return let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return null; // Error.
-           ^" in let Null #t33 = null in #t33.==(null) ?{self::A} #t33 as{TypeError,ForNonNullableByDefault} self::A : #t33{self::A};
+           ^" in let Null #t37 = null in #t37.==(null) ?{self::A} #t37 as{TypeError,ForNonNullableByDefault} self::A : #t37{self::A};
   }
   function local() → FutureOr<self::A> /* originally async */ {
     final asy::_Future<self::A> :async_future = new asy::_Future::•<self::A>();
@@ -414,23 +435,43 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<self::A>:async_temporary_0;
+    FutureOr<self::A>:async_temporary_1;
+    FutureOr<self::A>:async_temporary_2;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L5:
         {
           if(true) {
-            :return_value = let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
+            final Null #t38 = let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return null; // Error.
-             ^" in let Null #t35 = null in #t35.==(null) ?{self::A} #t35 as{TypeError,ForNonNullableByDefault} self::A : #t35{self::A};
+             ^" in let Null #t40 = null in #t40.==(null) ?{self::A} #t40 as{TypeError,ForNonNullableByDefault} self::A : #t40{self::A};
+            if(#t38 is asy::Future<self::A>) {
+              [yield] let dynamic #t41 = asy::_awaitHelper(#t38, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_0 = _in::unsafeCast<Null>(:result);
+            }
+            else {
+              :async_temporary_0 = #t38;
+            }
+            :return_value = :async_temporary_0;
             break #L5;
           }
           else {
-            :return_value = let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
+            final asy::Future<Null> #t42 = let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<Null>.value(null); // Error.
                  ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A;
+            if(#t42 is asy::Future<self::A>) {
+              [yield] let dynamic #t44 = asy::_awaitHelper(#t42, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_2 = _in::unsafeCast<Null>(:result);
+            }
+            else {
+              :async_temporary_2 = #t42;
+            }
+            :return_value = :async_temporary_2;
             break #L5;
           }
         }
@@ -466,4 +507,10 @@
 Evaluated: MethodInvocation @ org-dartlang-testcase:///assignability_error_messages.dart:77:14 -> BoolConstant(true)
 Evaluated: VariableGet @ org-dartlang-testcase:///assignability_error_messages.dart:77:14 -> NullConstant(null)
 Evaluated: VariableGet @ org-dartlang-testcase:///assignability_error_messages.dart:77:14 -> NullConstant(null)
-Extra constant evaluation: evaluated: 210, effectively constant: 12
+Extra constant evaluation: evaluated: 266, effectively constant: 12
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///assignability_error_messages.dart:
+- A. (from org-dartlang-testcase:///assignability_error_messages.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.expect b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.expect
index a4b4cdc..6769397 100644
--- a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.expect
@@ -263,35 +263,35 @@
   }
   function local() → FutureOr<self::A> async {
     if(true) {
-      return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
+      return let final self::B? #t6 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return x; // Error.
-             ^" in x as{TypeError,ForNonNullableByDefault} self::A;
+             ^" in x as{TypeError,ForNonNullableByDefault} self::A in #t6 is asy::Future<self::A> ?{FutureOr<self::A>} await #t6 : #t6;
     }
     else {
-      return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
+      return let final asy::Future<self::B?> #t8 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<B?>.value(x); // Error.
-                 ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A;
+                 ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A in #t8 is asy::Future<self::A> ?{FutureOr<self::A>} await #t8 : #t8;
     }
   }
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   return x; // Error.
          ^" in x as{TypeError,ForNonNullableByDefault} self::A;
 }
 static method bar(core::List<self::B?> x, core::List<core::List<self::B?>> l, core::Map<core::List<self::B?>, core::List<self::B?>> m) → core::List<self::A> {
-  self::barContext(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  self::barContext(let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   barContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>);
-  core::List<self::A> y = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -314,16 +314,16 @@
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   <List<A>, List<A>>{...m}; // Error.
                         ^"};
-  for (final core::List<self::B?> #t11 in l) {
-    core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  for (final core::List<self::B?> #t13 in l) {
+    core::List<self::A> y = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
 Try changing the type of the variable.
   for (List<A> y in l) {} // Error.
-               ^" in #t11 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
+               ^" in #t13 as{TypeError,ForNonNullableByDefault} core::List<self::A>;
   }
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -331,52 +331,52 @@
          ^" in x as{TypeError,ForNonNullableByDefault} core::List<self::A>;
 }
 static method baz(self::C c) → void {
-  self::bazContext(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
+  self::bazContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
   bazContext(c);
-             ^" in (let final self::C #t15 = c in #t15.==(null) ?{() → core::num?} null : #t15.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
+             ^" in (let final self::C #t17 = c in #t17.==(null) ?{() → core::num?} null : #t17.{self::C::call}) as{TypeError,ForNonNullableByDefault} () → core::num);
 }
 static method boz(Null x) → self::A {
-  self::fooContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(x); // Error.
              ^" in x as{TypeError,ForNonNullableByDefault} self::A);
-  self::fooContext(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(null); // Error.
              ^" in null as{TypeError,ForNonNullableByDefault} self::A);
-  self::A a1 = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a1 = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a1 = x; // Error.
          ^" in x as{TypeError,ForNonNullableByDefault} self::A;
-  self::A a2 = let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a2 = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a2 = null; // Error.
          ^" in null as{TypeError,ForNonNullableByDefault} self::A;
   if(true) {
-    return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return x; // Error.
            ^" in x as{TypeError,ForNonNullableByDefault} self::A;
   }
   else {
-    return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return null; // Error.
            ^" in null as{TypeError,ForNonNullableByDefault} self::A;
   }
   function local() → FutureOr<self::A> async {
     if(true) {
-      return let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
+      return let final Null #t24 = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return null; // Error.
-             ^" in null as{TypeError,ForNonNullableByDefault} self::A;
+             ^" in null as{TypeError,ForNonNullableByDefault} self::A in #t24 is asy::Future<self::A> ?{FutureOr<self::A>} await #t24 : #t24;
     }
     else {
-      return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
+      return let final asy::Future<Null> #t26 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<Null>.value(null); // Error.
-                 ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A;
+                 ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A in #t26 is asy::Future<self::A> ?{FutureOr<self::A>} await #t26 : #t26;
     }
   }
 }
@@ -385,3 +385,9 @@
 constants  {
   #C1 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///assignability_error_messages.dart:
+- A. (from org-dartlang-testcase:///assignability_error_messages.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.transformed.expect
index 9ec61e2..242b2b4 100644
--- a/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/assignability_error_messages.dart.weak.transformed.expect
@@ -180,6 +180,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -213,14 +214,14 @@
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a = x; // Error.
         ^" in x;
-  <self::A>[invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:29:10: Error: Can't assign spread elements of type 'B?' to collection elements of type 'A' because 'B?' is nullable and 'A' isn't.
+  core::_GrowableList::_literal1<self::A>(invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:29:10: Error: Can't assign spread elements of type 'B?' to collection elements of type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   <A>[...l]; // Error.
-         ^"];
-  <self::A>[invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:30:10: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+         ^");
+  core::_GrowableList::_literal1<self::A>(invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:30:10: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
   <A>[...l2]; // Error.
-         ^"];
+         ^");
   <self::A, self::A>{invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:31:13: Error: Can't assign spread entry keys of type 'B?' to map entry keys of type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -280,25 +281,45 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<self::A>:async_temporary_0;
+    FutureOr<self::A>:async_temporary_1;
+    FutureOr<self::A>:async_temporary_2;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L4:
         {
           if(true) {
-            :return_value = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
+            final self::B? #t6 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:43:14: Error: A value of type 'B?' can't be returned from an async function with return type 'FutureOr<A>' because 'B?' is nullable and 'FutureOr<A>' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return x; // Error.
              ^" in x;
+            if(#t6 is asy::Future<self::A>) {
+              [yield] let dynamic #t8 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_0 = _in::unsafeCast<self::B?>(:result);
+            }
+            else {
+              :async_temporary_0 = #t6;
+            }
+            :return_value = :async_temporary_0;
             break #L4;
           }
           else {
-            :return_value = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
+            final asy::Future<self::B?> #t9 = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:45:18: Error: A value of type 'Future<B?>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<B?>.value(x); // Error.
                  ^" in asy::Future::value<self::B?>(x) as{TypeError,ForNonNullableByDefault} self::A;
+            if(#t9 is asy::Future<self::A>) {
+              [yield] let dynamic #t11 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_2 = _in::unsafeCast<self::B?>(:result);
+            }
+            else {
+              :async_temporary_2 = #t9;
+            }
+            :return_value = :async_temporary_2;
             break #L4;
           }
         }
@@ -314,31 +335,31 @@
     :is_sync = true;
     return :async_future;
   }
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:49:10: Error: A value of type 'B?' can't be returned from a function with return type 'A' because 'B?' is nullable and 'A' isn't.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   return x; // Error.
          ^" in x;
 }
 static method bar(core::List<self::B?> x, core::List<core::List<self::B?>> l, core::Map<core::List<self::B?>, core::List<self::B?>> m) → core::List<self::A> {
-  self::barContext(let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  self::barContext(let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:53:14: Error: The argument type 'List<B?>' can't be assigned to the parameter type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   barContext(x); // Error.
              ^" in x);
-  core::List<self::A> y = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::List<self::A> y = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:54:15: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   List<A> y = x; // Error.
               ^" in x;
-  <core::List<self::A>>[invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:55:16: Error: Can't assign spread elements of type 'List<B?>' to collection elements of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  core::_GrowableList::_literal1<core::List<self::A>>(invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:55:16: Error: Can't assign spread elements of type 'List<B?>' to collection elements of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   <List<A>>[...l]; // Error.
-               ^"];
+               ^");
   <core::List<self::A>, core::List<self::A>>{invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:56:25: Error: Can't assign spread entry keys of type 'List<B?>' to map entry keys of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -353,19 +374,19 @@
   {
     core::Iterator<core::List<self::B?>> :sync-for-iterator = l.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-      final core::List<self::B?> #t11 = :sync-for-iterator.{core::Iterator::current};
+      final core::List<self::B?> #t15 = :sync-for-iterator.{core::Iterator::current};
       {
-        core::List<self::A> y = let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
+        core::List<self::A> y = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:57:16: Error: A value of type 'List<B?>' can't be assigned to a variable of type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
 Try changing the type of the variable.
   for (List<A> y in l) {} // Error.
-               ^" in #t11;
+               ^" in #t15;
       }
     }
   }
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
+  return let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:58:10: Error: A value of type 'List<B?>' can't be returned from a function with return type 'List<A>' because 'B?' is nullable and 'A' isn't.
  - 'List' is from 'dart:core'.
  - 'B' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
@@ -373,35 +394,35 @@
          ^" in x;
 }
 static method baz(self::C c) → void {
-  self::bazContext(let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
+  self::bazContext(let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:62:14: Error: The argument type 'num? Function()' can't be assigned to the parameter type 'num Function()' because 'num?' is nullable and 'num' isn't.
   bazContext(c);
-             ^" in let final self::C #t15 = c in #t15.==(null) ?{() → core::num?} null : #t15.{self::C::call});
+             ^" in let final self::C #t19 = c in #t19.==(null) ?{() → core::num?} null : #t19.{self::C::call});
 }
 static method boz(Null x) → self::A {
-  self::fooContext(let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:66:14: Error: The argument type 'Null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(x); // Error.
              ^" in x);
-  self::fooContext(let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
+  self::fooContext(let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:67:14: Error: The value 'null' can't be assigned to the parameter type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   fooContext(null); // Error.
              ^" in null);
-  self::A a1 = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a1 = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:68:10: Error: A value of type 'Null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a1 = x; // Error.
          ^" in x;
-  self::A a2 = let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
+  self::A a2 = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:69:10: Error: The value 'null' can't be assigned to a variable of type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
   A a2 = null; // Error.
          ^" in null;
   if(true) {
-    return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:71:12: Error: A value of type 'Null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return x; // Error.
            ^" in x;
   }
   else {
-    return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
+    return let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:73:12: Error: The value 'null' can't be returned from a function with return type 'A' because 'A' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
     return null; // Error.
            ^" in null;
@@ -414,23 +435,43 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<self::A>:async_temporary_0;
+    FutureOr<self::A>:async_temporary_1;
+    FutureOr<self::A>:async_temporary_2;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L5:
         {
           if(true) {
-            :return_value = let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
+            final Null #t26 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:77:14: Error: The value 'null' can't be returned from an async function with return type 'FutureOr<A>' because 'FutureOr<A>' is not nullable.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return null; // Error.
              ^" in null;
+            if(#t26 is asy::Future<self::A>) {
+              [yield] let dynamic #t28 = asy::_awaitHelper(#t26, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_0 = _in::unsafeCast<Null>(:result);
+            }
+            else {
+              :async_temporary_0 = #t26;
+            }
+            :return_value = :async_temporary_0;
             break #L5;
           }
           else {
-            :return_value = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
+            final asy::Future<Null> #t29 = let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/assignability_error_messages.dart:79:18: Error: A value of type 'Future<Null>' can't be returned from an async function with return type 'FutureOr<A>'.
  - 'Future' is from 'dart:async'.
  - 'A' is from 'pkg/front_end/testcases/nnbd/assignability_error_messages.dart'.
       return new Future<Null>.value(null); // Error.
                  ^" in asy::Future::value<Null>(null) as{TypeError,ForNonNullableByDefault} self::A;
+            if(#t29 is asy::Future<self::A>) {
+              [yield] let dynamic #t31 = asy::_awaitHelper(#t29, :async_op_then, :async_op_error, :async_op) in null;
+              :async_temporary_2 = _in::unsafeCast<Null>(:result);
+            }
+            else {
+              :async_temporary_2 = #t29;
+            }
+            :return_value = :async_temporary_2;
             break #L5;
           }
         }
@@ -452,3 +493,9 @@
 constants  {
   #C1 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///assignability_error_messages.dart:
+- A. (from org-dartlang-testcase:///assignability_error_messages.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.outline.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.outline.expect
index 8b55238..f0666bf 100644
--- a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.outline.expect
@@ -95,141 +95,169 @@
   synthetic constructor •() → self::_Class&Super&M0
     : super self::Super::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M0::property
 }
 abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1
     : super self::_Class&Super&M0::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M1::property
 }
 abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2
     : super self::_Class&Super&M0&M1::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M2::property
 }
 abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3
     : super self::_Class&Super&M0&M1&M2::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M3::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4
     : super self::_Class&Super&M0&M1&M2&M3::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M4::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5
     : super self::_Class&Super&M0&M1&M2&M3&M4::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M5::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M6::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M7::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M8::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M9::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M10::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M11::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M12::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M13::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M14::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M15::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M16::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M17::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M18::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M19::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M20::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M21::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M22::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M23::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M24::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M25::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M26::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M27::property
 }
 class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
   synthetic constructor •() → self::Class
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.expect
index 974275d..2ae4ce3 100644
--- a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.strong.expect
@@ -96,141 +96,169 @@
   synthetic constructor •() → self::_Class&Super&M0
     : super self::Super::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M0::property
 }
 abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1
     : super self::_Class&Super&M0::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M1::property
 }
 abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2
     : super self::_Class&Super&M0&M1::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M2::property
 }
 abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3
     : super self::_Class&Super&M0&M1&M2::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M3::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4
     : super self::_Class&Super&M0&M1&M2&M3::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M4::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5
     : super self::_Class&Super&M0&M1&M2&M3&M4::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M5::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M6::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M7::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M8::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M9::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M10::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M11::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M12::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M13::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M14::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M15::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M16::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M17::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M18::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M19::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M20::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M21::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M22::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M23::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M24::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M25::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M26::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M27::property
 }
 class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
   synthetic constructor •() → self::Class
diff --git a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.expect b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.expect
index 974275d..2ae4ce3 100644
--- a/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/build_issue_2688.dart.weak.expect
@@ -96,141 +96,169 @@
   synthetic constructor •() → self::_Class&Super&M0
     : super self::Super::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M0::property
 }
 abstract class _Class&Super&M0&M1 = self::_Class&Super&M0 with self::M1 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1
     : super self::_Class&Super&M0::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M1::property
 }
 abstract class _Class&Super&M0&M1&M2 = self::_Class&Super&M0&M1 with self::M2 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2
     : super self::_Class&Super&M0&M1::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M2::property
 }
 abstract class _Class&Super&M0&M1&M2&M3 = self::_Class&Super&M0&M1&M2 with self::M3 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3
     : super self::_Class&Super&M0&M1&M2::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M3::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4 = self::_Class&Super&M0&M1&M2&M3 with self::M4 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4
     : super self::_Class&Super&M0&M1&M2&M3::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M4::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5 = self::_Class&Super&M0&M1&M2&M3&M4 with self::M5 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5
     : super self::_Class&Super&M0&M1&M2&M3&M4::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M5::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6 = self::_Class&Super&M0&M1&M2&M3&M4&M5 with self::M6 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M6::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6 with self::M7 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M7::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7 with self::M8 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M8::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8 with self::M9 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M9::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9 with self::M10 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M10::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10 with self::M11 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M11::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11 with self::M12 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M12::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12 with self::M13 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M13::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13 with self::M14 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M14::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14 with self::M15 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M15::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15 with self::M16 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M16::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16 with self::M17 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M17::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17 with self::M18 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M18::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18 with self::M19 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M19::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19 with self::M20 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M20::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20 with self::M21 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M21::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21 with self::M22 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M22::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22 with self::M23 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M23::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23 with self::M24 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M24::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24 with self::M25 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M25::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25 with self::M26 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M26::property
 }
 abstract class _Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 = self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26 with self::M27 /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27
     : super self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26::•()
     ;
+  abstract mixin-stub get property() → core::int; -> self::M27::property
 }
 class Class extends self::_Class&Super&M0&M1&M2&M3&M4&M5&M6&M7&M8&M9&M10&M11&M12&M13&M14&M15&M16&M17&M18&M19&M20&M21&M22&M23&M24&M25&M26&M27 {
   synthetic constructor •() → self::Class
diff --git a/pkg/front_end/testcases/nnbd/const_canonical_type.dart b/pkg/front_end/testcases/nnbd/const_canonical_type.dart
new file mode 100644
index 0000000..28029ab
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_canonical_type.dart
@@ -0,0 +1,84 @@
+// 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';
+
+class Check {
+  final _ignored;
+
+  const Check(x, y)
+      : assert(identical(x, y)),
+      _ignored = identical(x, y) ? 42 : 1 ~/ 0;
+}
+
+void expectEqual(x, y) {
+  if (x != y) {
+    throw "Arguments were supposed to be identical.";
+  }
+}
+
+class A<X> {
+  const A();
+}
+
+typedef F1 = A<FutureOr<dynamic>> Function();
+typedef F2 = A<dynamic> Function();
+typedef F3 = A<FutureOr<FutureOr<dynamic>?>> Function();
+typedef F4 = A Function();
+
+test1() {
+  const c = A;
+  var v = A;
+
+  expectEqual(c, c);
+  expectEqual(c, A);
+  expectEqual(A, A);
+  expectEqual(v, v);
+  expectEqual(v, A);
+
+  const cf1 = F1;
+  const cf2 = F2;
+  const cf3 = F3;
+  const cf4 = F4;
+  var vf1 = F1;
+  var vf2 = F2;
+  var vf3 = F3;
+  var vf4 = F4;
+
+  expectEqual(cf1, cf2);
+  expectEqual(cf2, cf3);
+  expectEqual(cf3, cf4);
+  expectEqual(cf4, vf1);
+  expectEqual(vf1, vf2);
+  expectEqual(vf2, vf3);
+  expectEqual(vf3, vf4);
+
+  const a1 = A<List<F1>>();
+  const a2 = A<List<F2>>();
+  const a3 = A<List<F3>>();
+  const a4 = A<List<F4>>();
+
+  return const <dynamic>[
+    Check(c, c),
+    Check(c, A),
+    Check(A, A),
+
+    Check(cf1, cf2),
+    Check(cf2, cf3),
+    Check(cf3, cf4),
+
+    Check(a1, a2),
+    Check(a2, a3),
+    Check(a3, a4),
+    Check(a4, const A<List<F1>>()),
+    Check(const A<List<F1>>(), const A<List<F2>>()),
+    Check(const A<List<F2>>(), const A<List<F3>>()),
+    Check(const A<List<F3>>(), const A<List<F4>>()),
+    Check(const A<List<F4>>(), a1),
+  ];
+}
+
+main() {
+  test1();
+}
diff --git a/pkg/front_end/testcases/nnbd/const_canonical_type.dart.outline.expect b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.outline.expect
new file mode 100644
index 0000000..5239ad1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.outline.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef F1 = () → self::A<FutureOr<dynamic>>;
+typedef F2 = () → self::A<dynamic>;
+typedef F3 = () → self::A<FutureOr<FutureOr<dynamic>?>>;
+typedef F4 = () → self::A<dynamic>;
+class Check extends core::Object /*hasConstConstructor*/  {
+  final field dynamic _ignored;
+  const constructor •(dynamic x, dynamic y) → self::Check
+    : assert(core::identical(x, y)), self::Check::_ignored = core::identical(x, y) ?{core::int} 42 : 1.{core::num::~/}(0), super core::Object::•()
+    ;
+}
+class A<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+static method expectEqual(dynamic x, dynamic y) → void
+  ;
+static method test1() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/const_canonical_type.dart.strong.expect b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.strong.expect
new file mode 100644
index 0000000..1631d801
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.strong.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef F1 = () → self::A<FutureOr<dynamic>>;
+typedef F2 = () → self::A<dynamic>;
+typedef F3 = () → self::A<FutureOr<FutureOr<dynamic>?>>;
+typedef F4 = () → self::A<dynamic>;
+class Check extends core::Object /*hasConstConstructor*/  {
+  final field dynamic _ignored;
+  const constructor •(dynamic x, dynamic y) → self::Check
+    : assert(core::identical(x, y)), self::Check::_ignored = core::identical(x, y) ?{core::int} 42 : 1.{core::num::~/}(0), super core::Object::•()
+    ;
+}
+class A<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+static method expectEqual(dynamic x, dynamic y) → void {
+  if(!x.{core::Object::==}(y)) {
+    throw "Arguments were supposed to be identical.";
+  }
+}
+static method test1() → dynamic {
+  core::Type v = #C1;
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(v, v);
+  self::expectEqual(v, #C1);
+  core::Type vf1 = #C2;
+  core::Type vf2 = #C2;
+  core::Type vf3 = #C2;
+  core::Type vf4 = #C2;
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, vf1);
+  self::expectEqual(vf1, vf2);
+  self::expectEqual(vf2, vf3);
+  self::expectEqual(vf3, vf4);
+  return #C5;
+}
+static method main() → dynamic {
+  self::test1();
+}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::A<dynamic>)
+  #C2 = TypeLiteralConstant(() → self::A<dynamic>)
+  #C3 = 42
+  #C4 = self::Check {_ignored:#C3}
+  #C5 = <dynamic>[#C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_canonical_type.dart:
+- A. (from org-dartlang-testcase:///const_canonical_type.dart:22:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Check. (from org-dartlang-testcase:///const_canonical_type.dart:10:9)
diff --git a/pkg/front_end/testcases/nnbd/const_canonical_type.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..1631d801
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.strong.transformed.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef F1 = () → self::A<FutureOr<dynamic>>;
+typedef F2 = () → self::A<dynamic>;
+typedef F3 = () → self::A<FutureOr<FutureOr<dynamic>?>>;
+typedef F4 = () → self::A<dynamic>;
+class Check extends core::Object /*hasConstConstructor*/  {
+  final field dynamic _ignored;
+  const constructor •(dynamic x, dynamic y) → self::Check
+    : assert(core::identical(x, y)), self::Check::_ignored = core::identical(x, y) ?{core::int} 42 : 1.{core::num::~/}(0), super core::Object::•()
+    ;
+}
+class A<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+static method expectEqual(dynamic x, dynamic y) → void {
+  if(!x.{core::Object::==}(y)) {
+    throw "Arguments were supposed to be identical.";
+  }
+}
+static method test1() → dynamic {
+  core::Type v = #C1;
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(v, v);
+  self::expectEqual(v, #C1);
+  core::Type vf1 = #C2;
+  core::Type vf2 = #C2;
+  core::Type vf3 = #C2;
+  core::Type vf4 = #C2;
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, vf1);
+  self::expectEqual(vf1, vf2);
+  self::expectEqual(vf2, vf3);
+  self::expectEqual(vf3, vf4);
+  return #C5;
+}
+static method main() → dynamic {
+  self::test1();
+}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::A<dynamic>)
+  #C2 = TypeLiteralConstant(() → self::A<dynamic>)
+  #C3 = 42
+  #C4 = self::Check {_ignored:#C3}
+  #C5 = <dynamic>[#C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_canonical_type.dart:
+- A. (from org-dartlang-testcase:///const_canonical_type.dart:22:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Check. (from org-dartlang-testcase:///const_canonical_type.dart:10:9)
diff --git a/pkg/front_end/testcases/nnbd/const_canonical_type.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.textual_outline.expect
new file mode 100644
index 0000000..9d7cc05
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.textual_outline.expect
@@ -0,0 +1,21 @@
+import 'dart:async';
+
+class Check {
+  final _ignored;
+  const Check(x, y)
+      : assert(identical(x, y)),
+        _ignored = identical(x, y) ? 42 : 1 ~/ 0;
+}
+
+void expectEqual(x, y) {}
+
+class A<X> {
+  const A();
+}
+
+typedef F1 = A<FutureOr<dynamic>> Function();
+typedef F2 = A<dynamic> Function();
+typedef F3 = A<FutureOr<FutureOr<dynamic>?>> Function();
+typedef F4 = A Function();
+test1() {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/const_canonical_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cfadbda
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.textual_outline_modelled.expect
@@ -0,0 +1,20 @@
+import 'dart:async';
+
+class A<X> {
+  const A();
+}
+
+class Check {
+  const Check(x, y)
+      : assert(identical(x, y)),
+        _ignored = identical(x, y) ? 42 : 1 ~/ 0;
+  final _ignored;
+}
+
+main() {}
+test1() {}
+typedef F1 = A<FutureOr<dynamic>> Function();
+typedef F2 = A<dynamic> Function();
+typedef F3 = A<FutureOr<FutureOr<dynamic>?>> Function();
+typedef F4 = A Function();
+void expectEqual(x, y) {}
diff --git a/pkg/front_end/testcases/nnbd/const_canonical_type.dart.weak.expect b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.weak.expect
new file mode 100644
index 0000000..43eae4f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.weak.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef F1 = () → self::A<FutureOr<dynamic>>;
+typedef F2 = () → self::A<dynamic>;
+typedef F3 = () → self::A<FutureOr<FutureOr<dynamic>?>>;
+typedef F4 = () → self::A<dynamic>;
+class Check extends core::Object /*hasConstConstructor*/  {
+  final field dynamic _ignored;
+  const constructor •(dynamic x, dynamic y) → self::Check
+    : assert(core::identical(x, y)), self::Check::_ignored = core::identical(x, y) ?{core::int} 42 : 1.{core::num::~/}(0), super core::Object::•()
+    ;
+}
+class A<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+static method expectEqual(dynamic x, dynamic y) → void {
+  if(!x.{core::Object::==}(y)) {
+    throw "Arguments were supposed to be identical.";
+  }
+}
+static method test1() → dynamic {
+  core::Type v = #C1;
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(v, v);
+  self::expectEqual(v, #C1);
+  core::Type vf1 = #C2;
+  core::Type vf2 = #C2;
+  core::Type vf3 = #C2;
+  core::Type vf4 = #C2;
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, vf1);
+  self::expectEqual(vf1, vf2);
+  self::expectEqual(vf2, vf3);
+  self::expectEqual(vf3, vf4);
+  return #C5;
+}
+static method main() → dynamic {
+  self::test1();
+}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::A<dynamic>*)
+  #C2 = TypeLiteralConstant(() →* self::A<dynamic>*)
+  #C3 = 42
+  #C4 = self::Check {_ignored:#C3}
+  #C5 = <dynamic>[#C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_canonical_type.dart:
+- A. (from org-dartlang-testcase:///const_canonical_type.dart:22:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Check. (from org-dartlang-testcase:///const_canonical_type.dart:10:9)
diff --git a/pkg/front_end/testcases/nnbd/const_canonical_type.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.weak.transformed.expect
new file mode 100644
index 0000000..43eae4f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_canonical_type.dart.weak.transformed.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef F1 = () → self::A<FutureOr<dynamic>>;
+typedef F2 = () → self::A<dynamic>;
+typedef F3 = () → self::A<FutureOr<FutureOr<dynamic>?>>;
+typedef F4 = () → self::A<dynamic>;
+class Check extends core::Object /*hasConstConstructor*/  {
+  final field dynamic _ignored;
+  const constructor •(dynamic x, dynamic y) → self::Check
+    : assert(core::identical(x, y)), self::Check::_ignored = core::identical(x, y) ?{core::int} 42 : 1.{core::num::~/}(0), super core::Object::•()
+    ;
+}
+class A<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+static method expectEqual(dynamic x, dynamic y) → void {
+  if(!x.{core::Object::==}(y)) {
+    throw "Arguments were supposed to be identical.";
+  }
+}
+static method test1() → dynamic {
+  core::Type v = #C1;
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(#C1, #C1);
+  self::expectEqual(v, v);
+  self::expectEqual(v, #C1);
+  core::Type vf1 = #C2;
+  core::Type vf2 = #C2;
+  core::Type vf3 = #C2;
+  core::Type vf4 = #C2;
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, vf1);
+  self::expectEqual(vf1, vf2);
+  self::expectEqual(vf2, vf3);
+  self::expectEqual(vf3, vf4);
+  return #C5;
+}
+static method main() → dynamic {
+  self::test1();
+}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::A<dynamic>*)
+  #C2 = TypeLiteralConstant(() →* self::A<dynamic>*)
+  #C3 = 42
+  #C4 = self::Check {_ignored:#C3}
+  #C5 = <dynamic>[#C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_canonical_type.dart:
+- A. (from org-dartlang-testcase:///const_canonical_type.dart:22:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Check. (from org-dartlang-testcase:///const_canonical_type.dart:10:9)
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 1ba909d..deac28e 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
@@ -37,7 +37,7 @@
     : super core::Object::•()
     ;
 }
-static field core::bool inStrongMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field core::bool inStrongMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
 static const field core::bool f_is_fType = #C1;
 static const field core::bool f_is_gType = #C2;
 static const field core::bool g_is_fType = #C1;
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 5d2b393..3817966 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
@@ -37,7 +37,7 @@
     : super core::Object::•()
     ;
 }
-static field core::bool inStrongMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field core::bool inStrongMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
 static const field core::bool f_is_fType = #C1;
 static const field core::bool f_is_gType = #C1;
 static const field core::bool g_is_fType = #C1;
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.expect
index a0b9eae..a1b3d15 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.expect
@@ -52,3 +52,9 @@
   #C2 = null
   #C3 = self::Class {y:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_check.dart:
+- Class. (from org-dartlang-testcase:///constant_null_check.dart:13:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.transformed.expect
index a0b9eae..a1b3d15 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.transformed.expect
@@ -52,3 +52,9 @@
   #C2 = null
   #C3 = self::Class {y:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_check.dart:
+- Class. (from org-dartlang-testcase:///constant_null_check.dart:13:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.expect
index a0b9eae..a1b3d15 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.expect
@@ -52,3 +52,9 @@
   #C2 = null
   #C3 = self::Class {y:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_check.dart:
+- Class. (from org-dartlang-testcase:///constant_null_check.dart:13:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.transformed.expect
index a0b9eae..a1b3d15 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.transformed.expect
@@ -52,3 +52,9 @@
   #C2 = null
   #C3 = self::Class {y:#C1}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_check.dart:
+- Class. (from org-dartlang-testcase:///constant_null_check.dart:13:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart b/pkg/front_end/testcases/nnbd/constant_null_is.dart
index bdbd2fd..e252cca 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart
@@ -20,7 +20,7 @@
 const c11 = null is FutureOr<Never?>;
 const c12 = null is FutureOr<Never>?;
 const e1 = const Class<int>.constructor1(null);
-const e2 = const Class<int?>.constructor1(null);
+const e2 = const Class<List<int>>.constructor1(<Null>[null]);
 const e3 = const Class<Null>.constructor1(null);
 const e4 = const Class<int>.constructor2(null);
 const e5 = const Class<int?>.constructor2(null);
@@ -59,15 +59,17 @@
       "Class<int>.constructor1(null).field");
   expect(true, new Class<int?>.constructor1(null).field,
       "new Class<int?>.constructor1(null).field");
-  // const Class<int?> is evaluated as const Class<int*> in weak mode:
-  expect(!isWeakMode, e2.field, "const Class<int?>.constructor1(null).field");
+  // const Class<List<int>> is evaluated as const Class<List<int*>*> in weak
+  // mode:
+  expect(isWeakMode, e2.field,
+      "const Class<List<int>>.constructor1(<Null>[null]).field");
   expect(new Class<Null>.constructor1(null).field, e3.field,
       "Class<Null>.constructor1(null).field");
   expect(new Class<int>.constructor2(null).field, e4.field,
       "Class<int>.constructor2(null).field");
   expect(true, new Class<int?>.constructor2(null).field,
       "new Class<int?>.constructor2(null).field");
-  // const Class<int?> is evaluated as const Class<int*> in weak mode:
+  // const Class<int?> is evaluated as const Class<int?> in weak mode:
   expect(new Class<int?>.constructor2(null).field, e5.field,
       "Class<int?>.constructor2(null).field");
   expect(new Class<Null>.constructor2(null).field, e6.field,
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect
index 02239ae..b6390e6 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect
@@ -34,7 +34,7 @@
 static const field core::bool c11 = null is{ForNonNullableByDefault} FutureOr<Never?>;
 static const field core::bool c12 = null is{ForNonNullableByDefault} FutureOr<Never>?;
 static const field self::Class<core::int> e1 = const self::Class::constructor1<core::int>(null);
-static const field self::Class<core::int?> e2 = const self::Class::constructor1<core::int?>(null);
+static const field self::Class<core::List<core::int>> e2 = const self::Class::constructor1<core::List<core::int>>(const <Null>[null]);
 static const field self::Class<Null> e3 = const self::Class::constructor1<Null>(null);
 static const field self::Class<core::int> e4 = const self::Class::constructor2<core::int>(null);
 static const field self::Class<core::int?> e5 = const self::Class::constructor2<core::int?>(null);
@@ -66,7 +66,7 @@
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:20:18 -> BoolConstant(true)
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:21:18 -> BoolConstant(true)
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:22:18 -> InstanceConstant(const Class<int>{Class.field: false})
-Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:23:18 -> InstanceConstant(const Class<int?>{Class.field: true})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:23:18 -> InstanceConstant(const Class<List<int>>{Class.field: false})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:24:18 -> InstanceConstant(const Class<Null>{Class.field: true})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:25:18 -> InstanceConstant(const Class<int>{Class.field: true})
 Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:26:18 -> InstanceConstant(const Class<int?>{Class.field: true})
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.expect
index fd5c283..6432e62 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.expect
@@ -34,16 +34,16 @@
 static const field core::bool c11 = #C2;
 static const field core::bool c12 = #C2;
 static const field self::Class<core::int> e1 = #C4;
-static const field self::Class<core::int?> e2 = #C5;
+static const field self::Class<core::List<core::int>> e2 = #C5;
 static const field self::Class<Null> e3 = #C6;
 static const field self::Class<core::int> e4 = #C7;
-static const field self::Class<core::int?> e5 = #C5;
+static const field self::Class<core::int?> e5 = #C8;
 static const field self::Class<Null> e6 = #C6;
 static const field self::Class<core::int> e7 = #C4;
-static const field self::Class<core::int?> e8 = #C8;
-static const field self::Class<Null> e9 = #C9;
+static const field self::Class<core::int?> e8 = #C9;
+static const field self::Class<Null> e9 = #C10;
 static const field self::Class<core::int> e10 = #C7;
-static const field self::Class<core::int?> e11 = #C5;
+static const field self::Class<core::int?> e11 = #C8;
 static const field self::Class<Null> e12 = #C6;
 static method main() → dynamic {
   self::expect(null is{ForNonNullableByDefault} core::int?, #C2, "null is int?");
@@ -61,18 +61,18 @@
   self::expect(null is{ForNonNullableByDefault} FutureOr<Never>?, #C2, "null is FutureOr<Never>?");
   self::expect(new self::Class::constructor1<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor1(null).field");
   self::expect(true, new self::Class::constructor1<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor1(null).field");
-  self::expect(!self::isWeakMode, (#C5).{self::Class::field}, "const Class<int?>.constructor1(null).field");
+  self::expect(self::isWeakMode, (#C5).{self::Class::field}, "const Class<List<int>>.constructor1(<Null>[null]).field");
   self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor1(null).field");
   self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor2(null).field");
   self::expect(true, new self::Class::constructor2<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<int?>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor2(null).field");
   self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor2(null).field");
   self::expect(new self::Class::constructor3<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<Null>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C10).{self::Class::field}, "Class<Null>.constructor3(null).field");
   self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<int?>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor4(null).field");
   self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor4(null).field");
 }
 static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
@@ -85,9 +85,19 @@
   #C2 = true
   #C3 = false
   #C4 = self::Class<core::int> {field:#C3}
-  #C5 = self::Class<core::int?> {field:#C2}
+  #C5 = self::Class<core::List<core::int>> {field:#C3}
   #C6 = self::Class<Null> {field:#C2}
   #C7 = self::Class<core::int> {field:#C2}
-  #C8 = self::Class<core::int?> {field:#C3}
-  #C9 = self::Class<Null> {field:#C3}
+  #C8 = self::Class<core::int?> {field:#C2}
+  #C9 = self::Class<core::int?> {field:#C3}
+  #C10 = self::Class<Null> {field:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_is.dart:
+- Class.constructor1 (from org-dartlang-testcase:///constant_null_is.dart:38:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class.constructor2 (from org-dartlang-testcase:///constant_null_is.dart:39:9)
+- Class.constructor3 (from org-dartlang-testcase:///constant_null_is.dart:40:9)
+- Class.constructor4 (from org-dartlang-testcase:///constant_null_is.dart:41:9)
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect
index a6548c6..33c269a 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect
@@ -34,16 +34,16 @@
 static const field core::bool c11 = #C2;
 static const field core::bool c12 = #C2;
 static const field self::Class<core::int> e1 = #C4;
-static const field self::Class<core::int?> e2 = #C5;
+static const field self::Class<core::List<core::int>> e2 = #C5;
 static const field self::Class<Null> e3 = #C6;
 static const field self::Class<core::int> e4 = #C7;
-static const field self::Class<core::int?> e5 = #C5;
+static const field self::Class<core::int?> e5 = #C8;
 static const field self::Class<Null> e6 = #C6;
 static const field self::Class<core::int> e7 = #C4;
-static const field self::Class<core::int?> e8 = #C8;
-static const field self::Class<Null> e9 = #C9;
+static const field self::Class<core::int?> e8 = #C9;
+static const field self::Class<Null> e9 = #C10;
 static const field self::Class<core::int> e10 = #C7;
-static const field self::Class<core::int?> e11 = #C5;
+static const field self::Class<core::int?> e11 = #C8;
 static const field self::Class<Null> e12 = #C6;
 static method main() → dynamic {
   self::expect(null is{ForNonNullableByDefault} core::int?, #C2, "null is int?");
@@ -61,18 +61,18 @@
   self::expect(null is{ForNonNullableByDefault} FutureOr<Never>?, #C2, "null is FutureOr<Never>?");
   self::expect(new self::Class::constructor1<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor1(null).field");
   self::expect(true, new self::Class::constructor1<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor1(null).field");
-  self::expect(!self::isWeakMode, (#C5).{self::Class::field}, "const Class<int?>.constructor1(null).field");
+  self::expect(self::isWeakMode, (#C5).{self::Class::field}, "const Class<List<int>>.constructor1(<Null>[null]).field");
   self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor1(null).field");
   self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor2(null).field");
   self::expect(true, new self::Class::constructor2<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<int?>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor2(null).field");
   self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor2(null).field");
   self::expect(new self::Class::constructor3<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<Null>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C10).{self::Class::field}, "Class<Null>.constructor3(null).field");
   self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<int?>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor4(null).field");
   self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor4(null).field");
 }
 static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
@@ -85,11 +85,12 @@
   #C2 = true
   #C3 = false
   #C4 = self::Class<core::int> {field:#C3}
-  #C5 = self::Class<core::int?> {field:#C2}
+  #C5 = self::Class<core::List<core::int>> {field:#C3}
   #C6 = self::Class<Null> {field:#C2}
   #C7 = self::Class<core::int> {field:#C2}
-  #C8 = self::Class<core::int?> {field:#C3}
-  #C9 = self::Class<Null> {field:#C3}
+  #C8 = self::Class<core::int?> {field:#C2}
+  #C9 = self::Class<core::int?> {field:#C3}
+  #C10 = self::Class<Null> {field:#C3}
 }
 
 Extra constant evaluation status:
@@ -107,4 +108,13 @@
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:56:15 -> BoolConstant(true)
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:57:15 -> BoolConstant(true)
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:7:40 -> BoolConstant(false)
-Extra constant evaluation: evaluated: 102, effectively constant: 14
+Extra constant evaluation: evaluated: 101, effectively constant: 14
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_is.dart:
+- Class.constructor1 (from org-dartlang-testcase:///constant_null_is.dart:38:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class.constructor2 (from org-dartlang-testcase:///constant_null_is.dart:39:9)
+- Class.constructor3 (from org-dartlang-testcase:///constant_null_is.dart:40:9)
+- Class.constructor4 (from org-dartlang-testcase:///constant_null_is.dart:41:9)
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.textual_outline.expect
index fcfd9f0..df16424 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.textual_outline.expect
@@ -15,7 +15,7 @@
 const c11 = null is FutureOr<Never?>;
 const c12 = null is FutureOr<Never>?;
 const e1 = const Class<int>.constructor1(null);
-const e2 = const Class<int?>.constructor1(null);
+const e2 = const Class<List<int>>.constructor1(<Null>[null]);
 const e3 = const Class<Null>.constructor1(null);
 const e4 = const Class<int>.constructor2(null);
 const e5 = const Class<int?>.constructor2(null);
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.textual_outline_modelled.expect
index 3c072a2..58b8052 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.textual_outline_modelled.expect
@@ -25,7 +25,7 @@
 const e10 = const Class<int>.constructor4(null);
 const e11 = const Class<int?>.constructor4(null);
 const e12 = const Class<Null>.constructor4(null);
-const e2 = const Class<int?>.constructor1(null);
+const e2 = const Class<List<int>>.constructor1(<Null>[null]);
 const e3 = const Class<Null>.constructor1(null);
 const e4 = const Class<int>.constructor2(null);
 const e5 = const Class<int?>.constructor2(null);
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.expect
index 5ff7516..d9f07b7 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.expect
@@ -34,17 +34,17 @@
 static const field core::bool c11 = #C2;
 static const field core::bool c12 = #C2;
 static const field self::Class<core::int> e1 = #C4;
-static const field self::Class<core::int?> e2 = #C4;
-static const field self::Class<Null> e3 = #C5;
-static const field self::Class<core::int> e4 = #C6;
-static const field self::Class<core::int?> e5 = #C6;
-static const field self::Class<Null> e6 = #C5;
+static const field self::Class<core::List<core::int>> e2 = #C5;
+static const field self::Class<Null> e3 = #C6;
+static const field self::Class<core::int> e4 = #C7;
+static const field self::Class<core::int?> e5 = #C8;
+static const field self::Class<Null> e6 = #C6;
 static const field self::Class<core::int> e7 = #C4;
-static const field self::Class<core::int?> e8 = #C4;
-static const field self::Class<Null> e9 = #C7;
-static const field self::Class<core::int> e10 = #C6;
-static const field self::Class<core::int?> e11 = #C6;
-static const field self::Class<Null> e12 = #C5;
+static const field self::Class<core::int?> e8 = #C9;
+static const field self::Class<Null> e9 = #C10;
+static const field self::Class<core::int> e10 = #C7;
+static const field self::Class<core::int?> e11 = #C8;
+static const field self::Class<Null> e12 = #C6;
 static method main() → dynamic {
   self::expect(null is{ForNonNullableByDefault} core::int?, #C2, "null is int?");
   self::expect(null is{ForNonNullableByDefault} core::int, #C3, "null is int");
@@ -61,19 +61,19 @@
   self::expect(null is{ForNonNullableByDefault} FutureOr<Never>?, #C2, "null is FutureOr<Never>?");
   self::expect(new self::Class::constructor1<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor1(null).field");
   self::expect(true, new self::Class::constructor1<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor1(null).field");
-  self::expect(!self::isWeakMode, (#C4).{self::Class::field}, "const Class<int?>.constructor1(null).field");
-  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor1(null).field");
-  self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor2(null).field");
+  self::expect(self::isWeakMode, (#C5).{self::Class::field}, "const Class<List<int>>.constructor1(<Null>[null]).field");
+  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor1(null).field");
+  self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor2(null).field");
   self::expect(true, new self::Class::constructor2<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor2(null).field");
   self::expect(new self::Class::constructor3<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<Null>.constructor3(null).field");
-  self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int?>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor4(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C10).{self::Class::field}, "Class<Null>.constructor3(null).field");
+  self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor4(null).field");
 }
 static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
   if(!expected.{core::Object::==}(actual))
@@ -85,7 +85,19 @@
   #C2 = true
   #C3 = false
   #C4 = self::Class<core::int*> {field:#C3}
-  #C5 = self::Class<Null> {field:#C2}
-  #C6 = self::Class<core::int*> {field:#C2}
-  #C7 = self::Class<Null> {field:#C3}
+  #C5 = self::Class<core::List<core::int*>*> {field:#C2}
+  #C6 = self::Class<Null> {field:#C2}
+  #C7 = self::Class<core::int*> {field:#C2}
+  #C8 = self::Class<core::int?> {field:#C2}
+  #C9 = self::Class<core::int?> {field:#C3}
+  #C10 = self::Class<Null> {field:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_is.dart:
+- Class.constructor1 (from org-dartlang-testcase:///constant_null_is.dart:38:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class.constructor2 (from org-dartlang-testcase:///constant_null_is.dart:39:9)
+- Class.constructor3 (from org-dartlang-testcase:///constant_null_is.dart:40:9)
+- Class.constructor4 (from org-dartlang-testcase:///constant_null_is.dart:41:9)
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect
index 72bc3fa..9710d1f 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect
@@ -34,17 +34,17 @@
 static const field core::bool c11 = #C2;
 static const field core::bool c12 = #C2;
 static const field self::Class<core::int> e1 = #C4;
-static const field self::Class<core::int?> e2 = #C4;
-static const field self::Class<Null> e3 = #C5;
-static const field self::Class<core::int> e4 = #C6;
-static const field self::Class<core::int?> e5 = #C6;
-static const field self::Class<Null> e6 = #C5;
+static const field self::Class<core::List<core::int>> e2 = #C5;
+static const field self::Class<Null> e3 = #C6;
+static const field self::Class<core::int> e4 = #C7;
+static const field self::Class<core::int?> e5 = #C8;
+static const field self::Class<Null> e6 = #C6;
 static const field self::Class<core::int> e7 = #C4;
-static const field self::Class<core::int?> e8 = #C4;
-static const field self::Class<Null> e9 = #C7;
-static const field self::Class<core::int> e10 = #C6;
-static const field self::Class<core::int?> e11 = #C6;
-static const field self::Class<Null> e12 = #C5;
+static const field self::Class<core::int?> e8 = #C9;
+static const field self::Class<Null> e9 = #C10;
+static const field self::Class<core::int> e10 = #C7;
+static const field self::Class<core::int?> e11 = #C8;
+static const field self::Class<Null> e12 = #C6;
 static method main() → dynamic {
   self::expect(null is{ForNonNullableByDefault} core::int?, #C2, "null is int?");
   self::expect(null is{ForNonNullableByDefault} core::int, #C3, "null is int");
@@ -61,19 +61,19 @@
   self::expect(null is{ForNonNullableByDefault} FutureOr<Never>?, #C2, "null is FutureOr<Never>?");
   self::expect(new self::Class::constructor1<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor1(null).field");
   self::expect(true, new self::Class::constructor1<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor1(null).field");
-  self::expect(!self::isWeakMode, (#C4).{self::Class::field}, "const Class<int?>.constructor1(null).field");
-  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor1(null).field");
-  self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor2(null).field");
+  self::expect(self::isWeakMode, (#C5).{self::Class::field}, "const Class<List<int>>.constructor1(<Null>[null]).field");
+  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor1(null).field");
+  self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor2(null).field");
   self::expect(true, new self::Class::constructor2<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor2(null).field");
   self::expect(new self::Class::constructor3<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<Null>.constructor3(null).field");
-  self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int?>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor4(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C10).{self::Class::field}, "Class<Null>.constructor3(null).field");
+  self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor4(null).field");
 }
 static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
   if(!expected.{core::Object::==}(actual))
@@ -85,9 +85,12 @@
   #C2 = true
   #C3 = false
   #C4 = self::Class<core::int*> {field:#C3}
-  #C5 = self::Class<Null> {field:#C2}
-  #C6 = self::Class<core::int*> {field:#C2}
-  #C7 = self::Class<Null> {field:#C3}
+  #C5 = self::Class<core::List<core::int*>*> {field:#C2}
+  #C6 = self::Class<Null> {field:#C2}
+  #C7 = self::Class<core::int*> {field:#C2}
+  #C8 = self::Class<core::int?> {field:#C2}
+  #C9 = self::Class<core::int?> {field:#C3}
+  #C10 = self::Class<Null> {field:#C3}
 }
 
 Extra constant evaluation status:
@@ -105,4 +108,13 @@
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:56:15 -> BoolConstant(true)
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:57:15 -> BoolConstant(true)
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:7:40 -> BoolConstant(true)
-Extra constant evaluation: evaluated: 102, effectively constant: 14
+Extra constant evaluation: evaluated: 101, effectively constant: 14
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_is.dart:
+- Class.constructor1 (from org-dartlang-testcase:///constant_null_is.dart:38:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class.constructor2 (from org-dartlang-testcase:///constant_null_is.dart:39:9)
+- Class.constructor3 (from org-dartlang-testcase:///constant_null_is.dart:40:9)
+- Class.constructor4 (from org-dartlang-testcase:///constant_null_is.dart:41:9)
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.strong.expect b/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
index d2ed836..0e0cfb3 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
@@ -106,3 +106,12 @@
   #C16 = true
   #C17 = tearoff core::identical
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constants.dart:
+- Class. (from org-dartlang-testcase:///constants_lib.dart:8:9)
+
+org-dartlang-testcase:///constants_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class. (from org-dartlang-testcase:///constants_lib.dart:8:9)
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 d2ed836..0e0cfb3 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
@@ -106,3 +106,12 @@
   #C16 = true
   #C17 = tearoff core::identical
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constants.dart:
+- Class. (from org-dartlang-testcase:///constants_lib.dart:8:9)
+
+org-dartlang-testcase:///constants_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class. (from org-dartlang-testcase:///constants_lib.dart:8:9)
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.weak.expect b/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
index be9f59d..759f798 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
@@ -88,13 +88,13 @@
   return t;
 
 constants  {
-  #C1 = TypeLiteralConstant(core::Object)
+  #C1 = TypeLiteralConstant(core::Object*)
   #C2 = tearoff con::id
   #C3 = partial-instantiation con::id <core::int*>
   #C4 = 0
   #C5 = con::Class<core::int*> {field:#C4}
-  #C6 = TypeLiteralConstant((dynamic) → dynamic)
-  #C7 = TypeLiteralConstant(<T extends core::Object? = dynamic>(T%) → T%)
+  #C6 = TypeLiteralConstant((dynamic) →* dynamic)
+  #C7 = TypeLiteralConstant(<T extends core::Object? = dynamic>(T*) →* T*)
   #C8 = <core::int*>[#C4]
   #C9 = null
   #C10 = <dynamic>[#C4, #C9]
@@ -106,3 +106,12 @@
   #C16 = true
   #C17 = tearoff core::identical
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constants.dart:
+- Class. (from org-dartlang-testcase:///constants_lib.dart:8:9)
+
+org-dartlang-testcase:///constants_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class. (from org-dartlang-testcase:///constants_lib.dart:8:9)
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 be9f59d..759f798 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
@@ -88,13 +88,13 @@
   return t;
 
 constants  {
-  #C1 = TypeLiteralConstant(core::Object)
+  #C1 = TypeLiteralConstant(core::Object*)
   #C2 = tearoff con::id
   #C3 = partial-instantiation con::id <core::int*>
   #C4 = 0
   #C5 = con::Class<core::int*> {field:#C4}
-  #C6 = TypeLiteralConstant((dynamic) → dynamic)
-  #C7 = TypeLiteralConstant(<T extends core::Object? = dynamic>(T%) → T%)
+  #C6 = TypeLiteralConstant((dynamic) →* dynamic)
+  #C7 = TypeLiteralConstant(<T extends core::Object? = dynamic>(T*) →* T*)
   #C8 = <core::int*>[#C4]
   #C9 = null
   #C10 = <dynamic>[#C4, #C9]
@@ -106,3 +106,12 @@
   #C16 = true
   #C17 = tearoff core::identical
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constants.dart:
+- Class. (from org-dartlang-testcase:///constants_lib.dart:8:9)
+
+org-dartlang-testcase:///constants_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class. (from org-dartlang-testcase:///constants_lib.dart:8:9)
diff --git a/pkg/front_end/testcases/nnbd/covariant_late_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/covariant_late_field.dart.textual_outline.expect
index 4e4aaf6..042fbfc 100644
--- a/pkg/front_end/testcases/nnbd/covariant_late_field.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/covariant_late_field.dart.textual_outline.expect
@@ -1,6 +1,6 @@
 class A {
-  late num ;
-  invariantField;
+  late
+  num invariantField;
   covariant late num ;
   covariantField;
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.textual_outline.expect
index 1932ec0..5e18cfd 100644
--- a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.textual_outline.expect
@@ -2,12 +2,9 @@
 
 methodDirect<T>(T value) {}
 var fieldDirect = <T>(T value) {
-  late;
-  final T local2;
-  late;
-  final int local4;
-  late;
-  final FutureOr<int> local6;
+  late final T local2;
+  late final int local4;
+  late final FutureOr<int> local6;
   local2 = value;
   local4 = 0;
   local6 = 0;
@@ -17,12 +14,9 @@
 };
 methodConditional<T>(bool b, T value) {}
 var fieldConditional = <T>(bool b, T value) {
-  late;
-  final T local2;
-  late;
-  final int local4;
-  late;
-  final FutureOr<int> local6;
+  late final T local2;
+  late final int local4;
+  late final FutureOr<int> local6;
   if (b) {
     local2 = value;
     local4 = 0;
@@ -37,8 +31,7 @@
 };
 methodCompound() {}
 var fieldCompound = () {
-  late;
-  final int local4;
+  late final int local4;
   local4 = 0;
   local4 += 0;
 };
diff --git a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.textual_outline_modelled.expect
index be04eb0..ba94702 100644
--- a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.textual_outline_modelled.expect
@@ -5,18 +5,14 @@
 methodConditional<T>(bool b, T value) {}
 methodDirect<T>(T value) {}
 var fieldCompound = () {
-  late;
-  final int local4;
+  late final int local4;
   local4 = 0;
   local4 += 0;
 };
 var fieldConditional = <T>(bool b, T value) {
-  late;
-  final T local2;
-  late;
-  final int local4;
-  late;
-  final FutureOr<int> local6;
+  late final T local2;
+  late final int local4;
+  late final FutureOr<int> local6;
   if (b) {
     local2 = value;
     local4 = 0;
@@ -30,12 +26,9 @@
   local6 = 0;
 };
 var fieldDirect = <T>(T value) {
-  late;
-  final T local2;
-  late;
-  final int local4;
-  late;
-  final FutureOr<int> local6;
+  late final T local2;
+  late final int local4;
+  late final FutureOr<int> local6;
   local2 = value;
   local4 = 0;
   local6 = 0;
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.textual_outline.expect
index 8b2d8e6..7c35b6a 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.textual_outline.expect
@@ -1,8 +1,53 @@
 import 'dart:async';
+
 methodDirect<T>(T value) {}
-var fieldDirect = <T>(T value) { T local1; late T ;local2; int local3; late int ;local4; FutureOr<int> local5; late FutureOr;<int> [];local6; late T ;local7 = value; local1; local2; local3; local4; local5; local6; local7; };
+var fieldDirect = <T>(T value) {
+  T local1;
+  late T local2;
+  int local3;
+  late int local4;
+  FutureOr<int> local5;
+  late FutureOr<int> local6;
+  late T local7 = value;
+  local1;
+  local2;
+  local3;
+  local4;
+  local5;
+  local6;
+  local7;
+};
 methodConditional<T>(bool b, T value) {}
-var fieldConditional = <T>(bool b, T value) { T local1; late T ;local2; int local3; late int ;local4; FutureOr<int> local5; late FutureOr;<int> [];local6; late T ;local7 = value; if (b) { local1 = value; local2 = value; local3 = 0; local4 = 0; local5 = 0; local6 = 0; local7; } local1; local2; local3; local4; local5; local6; local7; };
+var fieldConditional = <T>(bool b, T value) {
+  T local1;
+  late T local2;
+  int local3;
+  late int local4;
+  FutureOr<int> local5;
+  late FutureOr<int> local6;
+  late T local7 = value;
+  if (b) {
+    local1 = value;
+    local2 = value;
+    local3 = 0;
+    local4 = 0;
+    local5 = 0;
+    local6 = 0;
+    local7;
+  }
+  local1;
+  local2;
+  local3;
+  local4;
+  local5;
+  local6;
+  local7;
+};
 methodCompound() {}
-var fieldCompound = () { int local3; late int ;local4; local3 += 0; local4 += 0; };
+var fieldCompound = () {
+  int local3;
+  late int local4;
+  local3 += 0;
+  local4 += 0;
+};
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.textual_outline_modelled.expect
index 46a4371..10d1b40 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.textual_outline_modelled.expect
@@ -6,24 +6,18 @@
 methodDirect<T>(T value) {}
 var fieldCompound = () {
   int local3;
-  late int;
-  local4;
+  late int local4;
   local3 += 0;
   local4 += 0;
 };
 var fieldConditional = <T>(bool b, T value) {
   T local1;
-  late T;
-  local2;
+  late T local2;
   int local3;
-  late int;
-  local4;
+  late int local4;
   FutureOr<int> local5;
-  late FutureOr;
-  <int>[];
-  local6;
-  late T;
-  local7 = value;
+  late FutureOr<int> local6;
+  late T local7 = value;
   if (b) {
     local1 = value;
     local2 = value;
@@ -43,17 +37,12 @@
 };
 var fieldDirect = <T>(T value) {
   T local1;
-  late T;
-  local2;
+  late T local2;
   int local3;
-  late int;
-  local4;
+  late int local4;
   FutureOr<int> local5;
-  late FutureOr;
-  <int>[];
-  local6;
-  late T;
-  local7 = value;
+  late FutureOr<int> local6;
+  late T local7 = value;
   local1;
   local2;
   local3;
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect
index ad8ddc8..d7c8546 100644
--- a/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect
@@ -1,11 +1,41 @@
-extension Extension1<T extends Object> (){}
-on T (){}
-extension Extension2<T extends String> (){}
-on T (){}
-extension Extension3<T extends dynamic> (){}
-on T (){}
-extension Extension4<T> (){}
-on T (){}
-extension Extension5<T extends Object?> (){}
-on T (){}
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension5<T extends Object?> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d7c8546
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,41 @@
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension5<T extends Object?> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline.expect
index 8b38ea1..b573756 100644
--- a/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline.expect
@@ -1,5 +1,7 @@
-extension Extension ;
-on Never (){}
+extension Extension on Never {
+  extensionMethod() {}
+}
+
 implicitAccess(Never never) {}
 explicitAccess(Never never) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4edd53e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+explicitAccess(Never never) {}
+
+extension Extension on Never {
+  extensionMethod() {}
+}
+
+implicitAccess(Never never) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.strong.expect b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.strong.expect
index 4f5c95f..7994771 100644
--- a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.strong.expect
@@ -57,7 +57,7 @@
   return new self::Class::•();
 }
 static method test2<T extends self::Class = self::Class>(self::test2::T t2) → dynamic {
-  if(self::test2::T.{core::Type::==}(self::SubClass)) {
+  if(self::test2::T.{core::Type::==}(#C1)) {
     self::SubClass subClass = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart:26:28: Error: A value of type 'T' can't be assigned to a variable of type 'SubClass'.
  - 'SubClass' is from 'pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart'.
     SubClass subClass = t2.method2();
@@ -74,3 +74,7 @@
   }
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::SubClass)
+}
diff --git a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.strong.transformed.expect
index c60f2f0..a0d52ef 100644
--- a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.strong.transformed.expect
@@ -57,7 +57,7 @@
   return new self::Class::•();
 }
 static method test2<T extends self::Class = self::Class>(self::test2::T t2) → dynamic {
-  if(self::test2::T.{core::Type::==}(self::SubClass)) {
+  if(self::test2::T.{core::Type::==}(#C1)) {
     self::SubClass subClass = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart:26:28: Error: A value of type 'T' can't be assigned to a variable of type 'SubClass'.
  - 'SubClass' is from 'pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart'.
     SubClass subClass = t2.method2();
@@ -75,7 +75,6 @@
 }
 static method main() → dynamic {}
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///extension_type_variable_bound.dart:25:12 -> TypeLiteralConstant(SubClass)
-Extra constant evaluation: evaluated: 24, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(self::SubClass)
+}
diff --git a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline.expect
index 0434002..7f86fba 100644
--- a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline.expect
@@ -1,9 +1,15 @@
-extension Extension<T> (){}
-on T (){}
-extension BoundExtension<T extends Class> (){}
-on T (){}
+extension Extension<T> on T {
+  T method1() => this;
+}
+
+extension BoundExtension<T extends Class> on T {
+  T method2() => this;
+}
+
 class Class {}
+
 class SubClass extends Class {}
+
 Class test1<T>(T t1) {}
 test2<T extends Class>(T t2) {}
 test3<T>(T t3) {}
diff --git a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d20dc15
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+Class test1<T>(T t1) {}
+
+class Class {}
+
+class SubClass extends Class {}
+
+extension BoundExtension<T extends Class> on T {
+  T method2() => this;
+}
+
+extension Extension<T> on T {
+  T method1() => this;
+}
+
+main() {}
+test2<T extends Class>(T t2) {}
+test3<T>(T t3) {}
diff --git a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.weak.expect b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.weak.expect
index 4f5c95f..bb758a4 100644
--- a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.weak.expect
@@ -57,7 +57,7 @@
   return new self::Class::•();
 }
 static method test2<T extends self::Class = self::Class>(self::test2::T t2) → dynamic {
-  if(self::test2::T.{core::Type::==}(self::SubClass)) {
+  if(self::test2::T.{core::Type::==}(#C1)) {
     self::SubClass subClass = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart:26:28: Error: A value of type 'T' can't be assigned to a variable of type 'SubClass'.
  - 'SubClass' is from 'pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart'.
     SubClass subClass = t2.method2();
@@ -74,3 +74,7 @@
   }
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = TypeLiteralConstant(self::SubClass*)
+}
diff --git a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.weak.transformed.expect
index c60f2f0..f53f0bc 100644
--- a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.weak.transformed.expect
@@ -57,7 +57,7 @@
   return new self::Class::•();
 }
 static method test2<T extends self::Class = self::Class>(self::test2::T t2) → dynamic {
-  if(self::test2::T.{core::Type::==}(self::SubClass)) {
+  if(self::test2::T.{core::Type::==}(#C1)) {
     self::SubClass subClass = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart:26:28: Error: A value of type 'T' can't be assigned to a variable of type 'SubClass'.
  - 'SubClass' is from 'pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart'.
     SubClass subClass = t2.method2();
@@ -75,7 +75,6 @@
 }
 static method main() → dynamic {}
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///extension_type_variable_bound.dart:25:12 -> TypeLiteralConstant(SubClass)
-Extra constant evaluation: evaluated: 24, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(self::SubClass*)
+}
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline.expect
index cafad59..ac7f418 100644
--- a/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline.expect
@@ -1,6 +1,7 @@
 external int topLevelField = 0;
 external final int finalTopLevelField = 0;
 external const int constField = 0;
+
 abstract class A {
   external int fieldWithInitializer = 0;
   external int initializedField1;
@@ -9,10 +10,17 @@
   external static int staticField = 0;
   external static final int finalStaticField = 0;
 }
+
 mixin B {
   external static int staticField = 0;
   external static final int finalStaticField = 0;
 }
-extension Extension ;
-on A (){}
+
+extension Extension on A {
+  external int extensionInstanceField = 0;
+  external final int finalExtensionInstanceField = 0;
+  external static int extensionStaticField = 0;
+  external static final int finalExtensionStaticField = 0;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..322cf16
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+abstract class A {
+  A(this.initializedField1) : this.initializedField2 = 0;
+  external int fieldWithInitializer = 0;
+  external int initializedField1;
+  external int initializedField2;
+  external static final int finalStaticField = 0;
+  external static int staticField = 0;
+}
+
+extension Extension on A {
+  external final int finalExtensionInstanceField = 0;
+  external int extensionInstanceField = 0;
+  external static final int finalExtensionStaticField = 0;
+  external static int extensionStaticField = 0;
+}
+
+external const int constField = 0;
+external final int finalTopLevelField = 0;
+external int topLevelField = 0;
+main() {}
+mixin B {
+  external static final int finalStaticField = 0;
+  external static int staticField = 0;
+}
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.strong.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.strong.expect
index cbc138b..660d848 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.strong.expect
@@ -123,3 +123,9 @@
 constants  {
   #C1 = self::Annotation {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///external_fields.dart:
+- Annotation. (from org-dartlang-testcase:///external_fields.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.strong.transformed.expect
index cbc138b..660d848 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.strong.transformed.expect
@@ -123,3 +123,9 @@
 constants  {
   #C1 = self::Annotation {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///external_fields.dart:
+- Annotation. (from org-dartlang-testcase:///external_fields.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline.expect
index d337a98..e1bc41f 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline.expect
@@ -1,12 +1,14 @@
 class Annotation {
   const Annotation();
 }
+
 @Annotation()
 external int topLevelField;
 @Annotation()
 external final int finalTopLevelField;
 external var untypedTopLevelField;
 external final untypedFinalTopLevelField;
+
 class A {
   @Annotation()
   external int instanceField;
@@ -24,6 +26,7 @@
   external static var untypedStaticField;
   external static final untypedFinalStaticField;
 }
+
 mixin B {
   @Annotation()
   external int instanceField;
@@ -41,8 +44,22 @@
   external static var untypedStaticField;
   external static final untypedFinalStaticField;
 }
-extension Extension ;
-on A (){}
+
+extension Extension on A {
+  @Annotation()
+  external int extensionInstanceField;
+  @Annotation()
+  external final int finalExtensionInstanceField;
+  @Annotation()
+  external static int extensionStaticField;
+  @Annotation()
+  external static final int finalExtensionStaticField;
+  external var untypedExtensionInstanceField;
+  external final untypedFinalExtensionInstanceField;
+  external static var untypedExtensionStaticField;
+  external static final untypedFinalExtensionStaticField;
+}
+
 class C implements A {
   external var instanceField;
   external final finalInstanceField;
@@ -51,4 +68,5 @@
   external final untypedFinalInstanceField;
   external var untypedCovariantInstanceField;
 }
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c5e3169
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline_modelled.expect
@@ -0,0 +1,70 @@
+class A {
+  @Annotation()
+  external covariant num covariantInstanceField;
+  external covariant var untypedCovariantInstanceField;
+  @Annotation()
+  external final int finalInstanceField;
+  external final untypedFinalInstanceField;
+  @Annotation()
+  external int instanceField;
+  @Annotation()
+  external static final int finalStaticField;
+  external static final untypedFinalStaticField;
+  @Annotation()
+  external static int staticField;
+  external static var untypedStaticField;
+  external var untypedInstanceField;
+}
+
+class Annotation {
+  const Annotation();
+}
+
+class C implements A {
+  external final finalInstanceField;
+  external final untypedFinalInstanceField;
+  external var covariantInstanceField;
+  external var instanceField;
+  external var untypedCovariantInstanceField;
+  external var untypedInstanceField;
+}
+
+extension Extension on A {
+  @Annotation()
+  external final int finalExtensionInstanceField;
+  external final untypedFinalExtensionInstanceField;
+  @Annotation()
+  external int extensionInstanceField;
+  @Annotation()
+  external static final int finalExtensionStaticField;
+  external static final untypedFinalExtensionStaticField;
+  @Annotation()
+  external static int extensionStaticField;
+  external static var untypedExtensionStaticField;
+  external var untypedExtensionInstanceField;
+}
+
+@Annotation()
+external final int finalTopLevelField;
+external final untypedFinalTopLevelField;
+@Annotation()
+external int topLevelField;
+external var untypedTopLevelField;
+main() {}
+mixin B {
+  @Annotation()
+  external covariant num covariantInstanceField;
+  external covariant var untypedCovariantInstanceField;
+  @Annotation()
+  external final int finalInstanceField;
+  external final untypedFinalInstanceField;
+  @Annotation()
+  external int instanceField;
+  @Annotation()
+  external static final int finalStaticField;
+  external static final untypedFinalStaticField;
+  @Annotation()
+  external static int staticField;
+  external static var untypedStaticField;
+  external var untypedInstanceField;
+}
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.weak.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.weak.expect
index cbc138b..660d848 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.weak.expect
@@ -123,3 +123,9 @@
 constants  {
   #C1 = self::Annotation {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///external_fields.dart:
+- Annotation. (from org-dartlang-testcase:///external_fields.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.weak.transformed.expect
index cbc138b..660d848 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.weak.transformed.expect
@@ -123,3 +123,9 @@
 constants  {
   #C1 = self::Annotation {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///external_fields.dart:
+- Annotation. (from org-dartlang-testcase:///external_fields.dart:6:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart b/pkg/front_end/testcases/nnbd/ffi_sample.dart
new file mode 100644
index 0000000..c45b492
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart
@@ -0,0 +1,30 @@
+// 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.
+
+// This test was adapted from samples/ffi/coordinate.dart
+
+import 'dart:ffi';
+
+import "package:ffi/ffi.dart";
+
+/// Sample struct for dart:ffi library.
+class Coordinate extends Struct {
+  @Double()
+  external double x;
+
+  @Double()
+  external double y;
+
+  external Pointer<Coordinate> next;
+
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {
+    return allocator<Coordinate>().ref
+      ..x = x
+      ..y = y
+      ..next = next;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.outline.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.outline.expect
new file mode 100644
index 0000000..ad4664a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.outline.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:ffi" as ffi;
+import "dart:core" as core;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+class Coordinate extends ffi::Struct {
+  @ffi::Double::•()
+  external get x() → core::double;
+  @ffi::Double::•()
+  external set x(core::double #externalFieldValue) → void;
+  @ffi::Double::•()
+  external get y() → core::double;
+  @ffi::Double::•()
+  external set y(core::double #externalFieldValue) → void;
+  external get next() → ffi::Pointer<self::Coordinate>;
+  external set next(ffi::Pointer<self::Coordinate> #externalFieldValue) → void;
+  static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer<self::Coordinate> next) → self::Coordinate
+    ;
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///ffi_sample.dart:13:4 -> InstanceConstant(const Double{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///ffi_sample.dart:13:4 -> InstanceConstant(const Double{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///ffi_sample.dart:16:4 -> InstanceConstant(const Double{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///ffi_sample.dart:16:4 -> InstanceConstant(const Double{})
+Extra constant evaluation: evaluated: 4, effectively constant: 4
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect
new file mode 100644
index 0000000..ff96753
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:ffi" as ffi;
+import "dart:core" as core;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+class Coordinate extends ffi::Struct {
+  @#C1
+  external get x() → core::double;
+  @#C1
+  external set x(core::double #externalFieldValue) → void;
+  @#C1
+  external get y() → core::double;
+  @#C1
+  external set y(core::double #externalFieldValue) → void;
+  external get next() → ffi::Pointer<self::Coordinate>;
+  external set next(ffi::Pointer<self::Coordinate> #externalFieldValue) → void;
+  static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer<self::Coordinate> next) → self::Coordinate {
+    return let final self::Coordinate #t1 = ffi::StructPointer|get#ref<self::Coordinate>(ffi::AllocatorAlloc|call<self::Coordinate>(allocator)) in block {
+      #t1.{self::Coordinate::x} = x;
+      #t1.{self::Coordinate::y} = y;
+      #t1.{self::Coordinate::next} = next;
+    } =>#t1;
+  }
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = ffi::Double {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///ffi_sample.dart:
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect
new file mode 100644
index 0000000..ac239e8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect
@@ -0,0 +1,73 @@
+//
+// Problems outside component:
+//
+// third_party/pkg/ffi/lib/src/allocation.dart: Info: Support for using non-constant type arguments 'T' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type.
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+@#C3
+@#C8
+class Coordinate extends ffi::Struct {
+  @#C3
+  static final field core::int* #sizeOf = (#C11).{core::List::[]}(ffi::_abi())/*isLegacy*/;
+  @#C3
+  constructor #fromTypedDataBase(dynamic #pointer) → dynamic
+    : super ffi::Struct::_fromPointer(#pointer)
+    ;
+  @#C12
+  get x() → core::double
+    return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi()));
+  @#C12
+  set x(core::double #externalFieldValue) → void
+    return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi()), #externalFieldValue);
+  @#C12
+  get y() → core::double
+    return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi()));
+  @#C12
+  set y(core::double #externalFieldValue) → void
+    return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi()), #externalFieldValue);
+  get next() → ffi::Pointer<self::Coordinate>
+    return ffi::_fromAddress<self::Coordinate>(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi())));
+  set next(ffi::Pointer<self::Coordinate> #externalFieldValue) → void
+    return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi()), #externalFieldValue.{ffi::Pointer::address});
+  static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer<self::Coordinate> next) → self::Coordinate {
+    return let final self::Coordinate #t1 = ffi::StructPointer|get#ref<self::Coordinate>(ffi::AllocatorAlloc|call<self::Coordinate>(allocator)) in block {
+      #t1.{self::Coordinate::x} = x;
+      #t1.{self::Coordinate::y} = y;
+      #t1.{self::Coordinate::next} = next;
+    } =>#t1;
+  }
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "vm:entry-point"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+  #C4 = "vm:ffi:struct-fields"
+  #C5 = TypeLiteralConstant(ffi::Double)
+  #C6 = TypeLiteralConstant(ffi::Pointer<ffi::NativeType>)
+  #C7 = <core::Type>[#C5, #C5, #C6]
+  #C8 = core::pragma {name:#C4, options:#C7}
+  #C9 = 24
+  #C10 = 20
+  #C11 = <core::int*>[#C9, #C10, #C9]
+  #C12 = ffi::Double {}
+  #C13 = 0
+  #C14 = <core::int*>[#C13, #C13, #C13]
+  #C15 = 8
+  #C16 = <core::int*>[#C15, #C15, #C15]
+  #C17 = 16
+  #C18 = <core::int*>[#C17, #C17, #C17]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///ffi_sample.dart:
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.textual_outline.expect
new file mode 100644
index 0000000..326d793
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+import 'dart:ffi';
+import "package:ffi/ffi.dart";
+
+class Coordinate extends Struct {
+  @Double()
+  external double x;
+  @Double()
+  external double y;
+  external Pointer<Coordinate> next;
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..88e9317
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+import "package:ffi/ffi.dart";
+import 'dart:ffi';
+
+class Coordinate extends Struct {
+  external Pointer<Coordinate> next;
+  @Double()
+  external double x;
+  @Double()
+  external double y;
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect
new file mode 100644
index 0000000..ff96753
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:ffi" as ffi;
+import "dart:core" as core;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+class Coordinate extends ffi::Struct {
+  @#C1
+  external get x() → core::double;
+  @#C1
+  external set x(core::double #externalFieldValue) → void;
+  @#C1
+  external get y() → core::double;
+  @#C1
+  external set y(core::double #externalFieldValue) → void;
+  external get next() → ffi::Pointer<self::Coordinate>;
+  external set next(ffi::Pointer<self::Coordinate> #externalFieldValue) → void;
+  static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer<self::Coordinate> next) → self::Coordinate {
+    return let final self::Coordinate #t1 = ffi::StructPointer|get#ref<self::Coordinate>(ffi::AllocatorAlloc|call<self::Coordinate>(allocator)) in block {
+      #t1.{self::Coordinate::x} = x;
+      #t1.{self::Coordinate::y} = y;
+      #t1.{self::Coordinate::next} = next;
+    } =>#t1;
+  }
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = ffi::Double {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///ffi_sample.dart:
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect
new file mode 100644
index 0000000..ac239e8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect
@@ -0,0 +1,73 @@
+//
+// Problems outside component:
+//
+// third_party/pkg/ffi/lib/src/allocation.dart: Info: Support for using non-constant type arguments 'T' in this FFI API is deprecated and will be removed in the next stable version of Dart. Rewrite the code to ensure that type arguments are compile time constants referring to a valid native type.
+//
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+@#C3
+@#C8
+class Coordinate extends ffi::Struct {
+  @#C3
+  static final field core::int* #sizeOf = (#C11).{core::List::[]}(ffi::_abi())/*isLegacy*/;
+  @#C3
+  constructor #fromTypedDataBase(dynamic #pointer) → dynamic
+    : super ffi::Struct::_fromPointer(#pointer)
+    ;
+  @#C12
+  get x() → core::double
+    return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi()));
+  @#C12
+  set x(core::double #externalFieldValue) → void
+    return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C14).{core::List::[]}(ffi::_abi()), #externalFieldValue);
+  @#C12
+  get y() → core::double
+    return ffi::_loadDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi()));
+  @#C12
+  set y(core::double #externalFieldValue) → void
+    return ffi::_storeDouble(this.{ffi::Struct::_addressOf}, (#C16).{core::List::[]}(ffi::_abi()), #externalFieldValue);
+  get next() → ffi::Pointer<self::Coordinate>
+    return ffi::_fromAddress<self::Coordinate>(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi())));
+  set next(ffi::Pointer<self::Coordinate> #externalFieldValue) → void
+    return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C18).{core::List::[]}(ffi::_abi()), #externalFieldValue.{ffi::Pointer::address});
+  static factory allocate(ffi::Allocator allocator, core::double x, core::double y, ffi::Pointer<self::Coordinate> next) → self::Coordinate {
+    return let final self::Coordinate #t1 = ffi::StructPointer|get#ref<self::Coordinate>(ffi::AllocatorAlloc|call<self::Coordinate>(allocator)) in block {
+      #t1.{self::Coordinate::x} = x;
+      #t1.{self::Coordinate::y} = y;
+      #t1.{self::Coordinate::next} = next;
+    } =>#t1;
+  }
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "vm:entry-point"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+  #C4 = "vm:ffi:struct-fields"
+  #C5 = TypeLiteralConstant(ffi::Double)
+  #C6 = TypeLiteralConstant(ffi::Pointer<ffi::NativeType>)
+  #C7 = <core::Type>[#C5, #C5, #C6]
+  #C8 = core::pragma {name:#C4, options:#C7}
+  #C9 = 24
+  #C10 = 20
+  #C11 = <core::int*>[#C9, #C10, #C9]
+  #C12 = ffi::Double {}
+  #C13 = 0
+  #C14 = <core::int*>[#C13, #C13, #C13]
+  #C15 = 8
+  #C16 = <core::int*>[#C15, #C15, #C15]
+  #C17 = 16
+  #C18 = <core::int*>[#C17, #C17, #C17]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///ffi_sample.dart:
+- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:122:9)
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.outline.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.outline.expect
index 6bd460cb..0b3f427 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.outline.expect
@@ -26,6 +26,8 @@
   const synthetic constructor •() → self::_Class1&Object&TestMixin
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String>
+    return super.{self::TestMixin::test}(fetch);
 }
 class Class1 extends self::_Class1&Object&TestMixin {
   synthetic constructor •() → self::Class1
@@ -37,6 +39,8 @@
   const synthetic constructor •() → self::_Class2&Object&TestMixin
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String>
+    return super.{self::TestMixin::test}(fetch);
 }
 class Class2 extends self::_Class2&Object&TestMixin {
   synthetic constructor •() → self::Class2
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.expect
index 9854241..bda20dd 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.expect
@@ -21,7 +21,7 @@
         else {
           throw core::Exception::•("Invalid response type");
         }
-    return result;
+    return let final self::TestMixin::T% #t1 = result in #t1 is asy::Future<self::TestMixin::T%> ?{FutureOr<self::TestMixin::T%>} await #t1 : #t1;
   }
 }
 class PagingResponse<T extends core::Object? = dynamic> extends core::Object {
@@ -46,6 +46,8 @@
   const synthetic constructor •() → self::_Class1&Object&TestMixin
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String>
+    return super.{self::TestMixin::test}(fetch);
 }
 class Class1 extends self::_Class1&Object&TestMixin {
   synthetic constructor •() → self::Class1
@@ -53,13 +55,15 @@
     ;
   method _test() → dynamic {
     final self::Response<core::String> response = new self::Response::•<core::String>("test");
-    this.{self::TestMixin::test}(asy::Future::value<self::Response<core::String>>(response));
+    this.{self::_Class1&Object&TestMixin::test}(asy::Future::value<self::Response<core::String>>(response));
   }
 }
 abstract class _Class2&Object&TestMixin = core::Object with self::TestMixin<self::PagingResponse<core::String>, core::String> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class2&Object&TestMixin
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String>
+    return super.{self::TestMixin::test}(fetch);
 }
 class Class2 extends self::_Class2&Object&TestMixin {
   synthetic constructor •() → self::Class2
@@ -67,7 +71,7 @@
     ;
   method _test() → dynamic {
     final self::PagingResponse<core::String> response = new self::PagingResponse::•<core::String>(new self::PagingResponseData::•<core::String>(<core::String>["test"]));
-    this.{self::TestMixin::test}(asy::Future::value<self::PagingResponse<core::String>>(response));
+    this.{self::_Class2&Object&TestMixin::test}(asy::Future::value<self::PagingResponse<core::String>>(response));
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
index c6344c1..e23e8dd 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.strong.transformed.expect
@@ -14,6 +14,7 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<self::TestMixin::T%>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
@@ -35,7 +36,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final self::TestMixin::T% #t2 = result;
+          if(#t2 is asy::Future<self::TestMixin::T%>) {
+            [yield] let dynamic #t3 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<self::TestMixin::T%>(:result);
+          }
+          else {
+            :async_temporary_0 = #t2;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -82,11 +91,12 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L2:
         {
-          [yield] let dynamic #t2 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
+          [yield] let dynamic #t4 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
           final self::Response<core::String> response = _in::unsafeCast<self::Response<core::String>>(:result);
           core::String result;
           if(response is{ForNonNullableByDefault} self::Response<dynamic>) {
@@ -103,7 +113,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final core::String #t5 = result;
+          if(#t5 is asy::Future<core::String>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::String>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -125,7 +143,7 @@
     ;
   method _test() → dynamic {
     final self::Response<core::String> response = new self::Response::•<core::String>("test");
-    this.{self::TestMixin::test}(asy::Future::value<self::Response<core::String>>(response));
+    this.{self::_Class1&Object&TestMixin::test}(asy::Future::value<self::Response<core::String>>(response));
   }
 }
 abstract class _Class2&Object&TestMixin extends core::Object implements self::TestMixin<self::PagingResponse<core::String>, core::String> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
@@ -141,11 +159,12 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L3:
         {
-          [yield] let dynamic #t3 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
+          [yield] let dynamic #t7 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
           final self::PagingResponse<core::String> response = _in::unsafeCast<self::PagingResponse<core::String>>(:result);
           core::String result;
           if(response is{ForNonNullableByDefault} self::Response<dynamic>) {
@@ -162,7 +181,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final core::String #t8 = result;
+          if(#t8 is asy::Future<core::String>) {
+            [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::String>(:result);
+          }
+          else {
+            :async_temporary_0 = #t8;
+          }
+          :return_value = :async_temporary_0;
           break #L3;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -183,8 +210,8 @@
     : super self::_Class2&Object&TestMixin::•()
     ;
   method _test() → dynamic {
-    final self::PagingResponse<core::String> response = new self::PagingResponse::•<core::String>(new self::PagingResponseData::•<core::String>(<core::String>["test"]));
-    this.{self::TestMixin::test}(asy::Future::value<self::PagingResponse<core::String>>(response));
+    final self::PagingResponse<core::String> response = new self::PagingResponse::•<core::String>(new self::PagingResponseData::•<core::String>(core::_GrowableList::_literal1<core::String>("test")));
+    this.{self::_Class2&Object&TestMixin::test}(asy::Future::value<self::PagingResponse<core::String>>(response));
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.expect
index 9854241..bda20dd 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.expect
@@ -21,7 +21,7 @@
         else {
           throw core::Exception::•("Invalid response type");
         }
-    return result;
+    return let final self::TestMixin::T% #t1 = result in #t1 is asy::Future<self::TestMixin::T%> ?{FutureOr<self::TestMixin::T%>} await #t1 : #t1;
   }
 }
 class PagingResponse<T extends core::Object? = dynamic> extends core::Object {
@@ -46,6 +46,8 @@
   const synthetic constructor •() → self::_Class1&Object&TestMixin
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::Response<core::String>> fetch) → asy::Future<core::String>
+    return super.{self::TestMixin::test}(fetch);
 }
 class Class1 extends self::_Class1&Object&TestMixin {
   synthetic constructor •() → self::Class1
@@ -53,13 +55,15 @@
     ;
   method _test() → dynamic {
     final self::Response<core::String> response = new self::Response::•<core::String>("test");
-    this.{self::TestMixin::test}(asy::Future::value<self::Response<core::String>>(response));
+    this.{self::_Class1&Object&TestMixin::test}(asy::Future::value<self::Response<core::String>>(response));
   }
 }
 abstract class _Class2&Object&TestMixin = core::Object with self::TestMixin<self::PagingResponse<core::String>, core::String> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class2&Object&TestMixin
     : super core::Object::•()
     ;
+  mixin-super-stub method test(generic-covariant-impl asy::Future<self::PagingResponse<core::String>> fetch) → asy::Future<core::String>
+    return super.{self::TestMixin::test}(fetch);
 }
 class Class2 extends self::_Class2&Object&TestMixin {
   synthetic constructor •() → self::Class2
@@ -67,7 +71,7 @@
     ;
   method _test() → dynamic {
     final self::PagingResponse<core::String> response = new self::PagingResponse::•<core::String>(new self::PagingResponseData::•<core::String>(<core::String>["test"]));
-    this.{self::TestMixin::test}(asy::Future::value<self::PagingResponse<core::String>>(response));
+    this.{self::_Class2&Object&TestMixin::test}(asy::Future::value<self::PagingResponse<core::String>>(response));
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
index c6344c1..e23e8dd 100644
--- a/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/flutter_issue64155.dart.weak.transformed.expect
@@ -14,6 +14,7 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<self::TestMixin::T%>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
@@ -35,7 +36,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final self::TestMixin::T% #t2 = result;
+          if(#t2 is asy::Future<self::TestMixin::T%>) {
+            [yield] let dynamic #t3 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<self::TestMixin::T%>(:result);
+          }
+          else {
+            :async_temporary_0 = #t2;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -82,11 +91,12 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L2:
         {
-          [yield] let dynamic #t2 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
+          [yield] let dynamic #t4 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
           final self::Response<core::String> response = _in::unsafeCast<self::Response<core::String>>(:result);
           core::String result;
           if(response is{ForNonNullableByDefault} self::Response<dynamic>) {
@@ -103,7 +113,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final core::String #t5 = result;
+          if(#t5 is asy::Future<core::String>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::String>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -125,7 +143,7 @@
     ;
   method _test() → dynamic {
     final self::Response<core::String> response = new self::Response::•<core::String>("test");
-    this.{self::TestMixin::test}(asy::Future::value<self::Response<core::String>>(response));
+    this.{self::_Class1&Object&TestMixin::test}(asy::Future::value<self::Response<core::String>>(response));
   }
 }
 abstract class _Class2&Object&TestMixin extends core::Object implements self::TestMixin<self::PagingResponse<core::String>, core::String> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
@@ -141,11 +159,12 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L3:
         {
-          [yield] let dynamic #t3 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
+          [yield] let dynamic #t7 = asy::_awaitHelper(fetch, :async_op_then, :async_op_error, :async_op) in null;
           final self::PagingResponse<core::String> response = _in::unsafeCast<self::PagingResponse<core::String>>(:result);
           core::String result;
           if(response is{ForNonNullableByDefault} self::Response<dynamic>) {
@@ -162,7 +181,15 @@
               else {
                 throw core::Exception::•("Invalid response type");
               }
-          :return_value = result;
+          final core::String #t8 = result;
+          if(#t8 is asy::Future<core::String>) {
+            [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::String>(:result);
+          }
+          else {
+            :async_temporary_0 = #t8;
+          }
+          :return_value = :async_temporary_0;
           break #L3;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -183,8 +210,8 @@
     : super self::_Class2&Object&TestMixin::•()
     ;
   method _test() → dynamic {
-    final self::PagingResponse<core::String> response = new self::PagingResponse::•<core::String>(new self::PagingResponseData::•<core::String>(<core::String>["test"]));
-    this.{self::TestMixin::test}(asy::Future::value<self::PagingResponse<core::String>>(response));
+    final self::PagingResponse<core::String> response = new self::PagingResponse::•<core::String>(new self::PagingResponseData::•<core::String>(core::_GrowableList::_literal1<core::String>("test")));
+    this.{self::_Class2&Object&TestMixin::test}(asy::Future::value<self::PagingResponse<core::String>>(response));
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
index a4e5658..4b3f76a 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.strong.transformed.expect
@@ -63,7 +63,7 @@
     }
   }
   block {
-    final core::List<core::int> #t3 = <core::int>[];
+    final core::List<core::int> #t3 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'Iterable<int>?' is nullable and 'Iterable<dynamic>' isn't.
  - 'Iterable' is from 'dart:core'.
@@ -87,7 +87,7 @@
     }
   }
   block {
-    final core::List<core::int> #t8 = <core::int>[];
+    final core::List<core::int> #t8 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
  - 'List' is from 'dart:core'.
@@ -115,7 +115,7 @@
     }
   }
   block {
-    final core::List<core::int> #t13 = <core::int>[];
+    final core::List<core::int> #t13 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
@@ -146,7 +146,7 @@
     }
   }
   block {
-    final core::List<core::int> #t18 = <core::int>[];
+    final core::List<core::int> #t18 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
@@ -172,7 +172,7 @@
     }
   }
   block {
-    final core::List<core::int> #t21 = <core::int>[];
+    final core::List<core::int> #t21 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<core::int> :sync-for-iterator = i1.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -189,7 +189,7 @@
     }
   }
   block {
-    final core::List<core::int> #t22 = <core::int>[];
+    final core::List<core::int> #t22 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<core::int> :sync-for-iterator = l1.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -209,7 +209,7 @@
     }
   }
   block {
-    final core::List<core::int> #t24 = <core::int>[];
+    final core::List<core::int> #t24 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
diff --git a/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
index 43b2e84..346bcb4 100644
--- a/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forin.dart.weak.transformed.expect
@@ -63,7 +63,7 @@
     }
   }
   block {
-    final core::List<core::int> #t2 = <core::int>[];
+    final core::List<core::int> #t2 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:10:18: Error: The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'Iterable<int>?' is nullable and 'Iterable<dynamic>' isn't.
  - 'Iterable' is from 'dart:core'.
@@ -87,7 +87,7 @@
     }
   }
   block {
-    final core::List<core::int> #t5 = <core::int>[];
+    final core::List<core::int> #t5 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:13:18: Error: The type 'List<int>?' used in the 'for' loop must implement 'Iterable<dynamic>' because 'List<int>?' is nullable and 'Iterable<dynamic>' isn't.
  - 'List' is from 'dart:core'.
@@ -115,7 +115,7 @@
     }
   }
   block {
-    final core::List<core::int> #t9 = <core::int>[];
+    final core::List<core::int> #t9 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:16:18: Error: The type 'Object' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
@@ -146,7 +146,7 @@
     }
   }
   block {
-    final core::List<core::int> #t14 = <core::int>[];
+    final core::List<core::int> #t14 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/forin.dart:19:18: Error: The type 'Object?' used in the 'for' loop must implement 'Iterable<dynamic>'.
  - 'Object' is from 'dart:core'.
@@ -172,7 +172,7 @@
     }
   }
   block {
-    final core::List<core::int> #t17 = <core::int>[];
+    final core::List<core::int> #t17 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<core::int> :sync-for-iterator = i1.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -189,7 +189,7 @@
     }
   }
   block {
-    final core::List<core::int> #t18 = <core::int>[];
+    final core::List<core::int> #t18 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<core::int> :sync-for-iterator = l1.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -209,7 +209,7 @@
     }
   }
   block {
-    final core::List<core::int> #t20 = <core::int>[];
+    final core::List<core::int> #t20 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (d as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
diff --git a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.expect b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.expect
index f936ed5..f526302 100644
--- a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.expect
@@ -1,52 +1,37 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:8:12: Error: Constant evaluation error:
-// const c2 = {a: 0, b: 1};
-//            ^
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:8:19: Context: The key '<int>[]' conflicts with another existing key in the map.
-// const c2 = {a: 0, b: 1};
-//                   ^
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:8:7: Context: While analyzing:
-// const c2 = {a: 0, b: 1};
-//       ^
-//
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:9:12: Error: Constant evaluation error:
-// const c3 = {a, b};
-//            ^
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:9:16: Context: The element '<int>[]' conflicts with another existing element in the set.
-// const c3 = {a, b};
-//                ^
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:9:7: Context: While analyzing:
-// const c3 = {a, b};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 import "org-dartlang-testcase:///from_agnostic_lib.dart";
 
 static const field core::bool c1 = #C1;
-static const field core::Map<core::List<core::int?>, core::int> c2 = invalid-expression "The key '<int>[]' conflicts with another existing key in the map.";
-static const field core::Set<core::List<core::int?>> c3 = invalid-expression "The element '<int>[]' conflicts with another existing element in the set.";
+static const field core::Map<core::List<core::int?>, core::int> c2 = #C7;
+static const field core::Set<core::List<core::int?>> c3 = #C11;
 static const field core::List<core::int> c4 = #C2;
-static const field core::List<core::int?> c5 = #C2;
+static const field core::List<core::int?> c5 = #C4;
 static method main() → dynamic {
   #C2;
-  #C2;
+  #C4;
 }
 
 library /*isNonNullableByDefault*/;
 import self as self2;
 import "dart:core" as core;
 
-static const field core::List<core::int> a = #C3;
+static const field core::List<core::int> a = #C12;
 static const field core::List<core::int?> b = #C4;
 
 constants  {
-  #C1 = true
+  #C1 = false
   #C2 = <core::int*>[]
-  #C3 = <core::int>[]
+  #C3 = 0
   #C4 = <core::int?>[]
+  #C5 = 1
+  #C6 = <dynamic>[#C2, #C3, #C4, #C5]
+  #C7 = core::_ImmutableMap<core::List<core::int?>*, core::int*> {_kvPairs:#C6}
+  #C8 = null
+  #C9 = <dynamic>[#C2, #C8, #C4, #C8]
+  #C10 = core::_ImmutableMap<core::List<core::int?>*, Null> {_kvPairs:#C9}
+  #C11 = col::_UnmodifiableSet<core::List<core::int?>*> {_map:#C10}
+  #C12 = <core::int>[]
 }
diff --git a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.transformed.expect
index f936ed5..f526302 100644
--- a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.transformed.expect
@@ -1,52 +1,37 @@
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:8:12: Error: Constant evaluation error:
-// const c2 = {a: 0, b: 1};
-//            ^
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:8:19: Context: The key '<int>[]' conflicts with another existing key in the map.
-// const c2 = {a: 0, b: 1};
-//                   ^
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:8:7: Context: While analyzing:
-// const c2 = {a: 0, b: 1};
-//       ^
-//
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:9:12: Error: Constant evaluation error:
-// const c3 = {a, b};
-//            ^
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:9:16: Context: The element '<int>[]' conflicts with another existing element in the set.
-// const c3 = {a, b};
-//                ^
-// pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:9:7: Context: While analyzing:
-// const c3 = {a, b};
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
 import "org-dartlang-testcase:///from_agnostic_lib.dart";
 
 static const field core::bool c1 = #C1;
-static const field core::Map<core::List<core::int?>, core::int> c2 = invalid-expression "The key '<int>[]' conflicts with another existing key in the map.";
-static const field core::Set<core::List<core::int?>> c3 = invalid-expression "The element '<int>[]' conflicts with another existing element in the set.";
+static const field core::Map<core::List<core::int?>, core::int> c2 = #C7;
+static const field core::Set<core::List<core::int?>> c3 = #C11;
 static const field core::List<core::int> c4 = #C2;
-static const field core::List<core::int?> c5 = #C2;
+static const field core::List<core::int?> c5 = #C4;
 static method main() → dynamic {
   #C2;
-  #C2;
+  #C4;
 }
 
 library /*isNonNullableByDefault*/;
 import self as self2;
 import "dart:core" as core;
 
-static const field core::List<core::int> a = #C3;
+static const field core::List<core::int> a = #C12;
 static const field core::List<core::int?> b = #C4;
 
 constants  {
-  #C1 = true
+  #C1 = false
   #C2 = <core::int*>[]
-  #C3 = <core::int>[]
+  #C3 = 0
   #C4 = <core::int?>[]
+  #C5 = 1
+  #C6 = <dynamic>[#C2, #C3, #C4, #C5]
+  #C7 = core::_ImmutableMap<core::List<core::int?>*, core::int*> {_kvPairs:#C6}
+  #C8 = null
+  #C9 = <dynamic>[#C2, #C8, #C4, #C8]
+  #C10 = core::_ImmutableMap<core::List<core::int?>*, Null> {_kvPairs:#C9}
+  #C11 = col::_UnmodifiableSet<core::List<core::int?>*> {_map:#C10}
+  #C12 = <core::int>[]
 }
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.outline.expect
index da98632..a05e6c9 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.outline.expect
@@ -37,6 +37,13 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   num get property6; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6 = 0;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The return type of the method 'C2.property6' is 'num', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   num get property6; // error
@@ -45,13 +52,6 @@
 //   int property6 = 0;
 //       ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   num get property6; // error
-//           ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6 = 0;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:116:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
 // abstract class D3 implements D1, D2 /* error on property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.expect
index f2f3537..c6058f6 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.expect
@@ -37,6 +37,13 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   num get property6; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6 = 0;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The return type of the method 'C2.property6' is 'num', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   num get property6; // error
@@ -45,13 +52,6 @@
 //   int property6 = 0;
 //       ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   num get property6; // error
-//           ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6 = 0;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:116:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
 // abstract class D3 implements D1, D2 /* error on property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect
index 806128e..8fae4ef 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect
@@ -4,6 +4,7 @@
 void set property2(num value) {}
 num get property3 => 0;
 void set property3(int value) {}
+
 abstract class A {
   int get property1;
   void set property1(int i);
@@ -21,6 +22,7 @@
   static num get property9 => 0;
   static void set property9(int value) {}
 }
+
 abstract class B1 {
   int get property1;
   int get property2;
@@ -30,6 +32,7 @@
   final num property6;
   B1(this.property4, this.property5, this.property6);
 }
+
 abstract class B2 implements B1 {
   void set property1(int i);
   void set property2(num i);
@@ -38,6 +41,7 @@
   void set property5(num i);
   void set property6(int i);
 }
+
 abstract class C1 {
   void set property1(int i);
   void set property2(num i);
@@ -46,6 +50,7 @@
   num property5 = 0;
   int property6 = 0;
 }
+
 abstract class C2 implements C1 {
   int get property1;
   int get property2;
@@ -54,18 +59,42 @@
   int get property5;
   num get property6;
 }
+
 abstract class D1 {
   int get property1;
   int get property2;
   num get property3;
 }
+
 abstract class D2 {
   void set property1(int i);
   void set property2(num i);
   void set property3(int i);
 }
+
 abstract class D3 implements D1, D2 {}
+
 abstract class D4 implements D3 {}
-extension Extension<T, S extends T> (){}
-on int (){}
+
+extension Extension<T, S extends T> on int {
+  int get property1 => 0;
+  void set property1(int i) {}
+  int get property2 => 0;
+  void set property2(num i) {}
+  num get property3 => 0;
+  void set property3(int i) {}
+  S get property4 => 0;
+  void set property4(S i) {}
+  S get property5 => 0;
+  void set property5(T i) {}
+  T get property6 => 0;
+  void set property6(S i) {}
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8 => 0;
+  static void set property8(num value) {}
+  static num get property9 => 0;
+  static void set property9(int value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect
index feb0a3a..75210d1 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect
@@ -69,6 +69,27 @@
 
 abstract class D4 implements D3 {}
 
+extension Extension<T, S extends T> on int {
+  S get property4 => 0;
+  S get property5 => 0;
+  T get property6 => 0;
+  int get property1 => 0;
+  int get property2 => 0;
+  num get property3 => 0;
+  static int get property7 => 0;
+  static int get property8 => 0;
+  static num get property9 => 0;
+  static void set property7(int value) {}
+  static void set property8(num value) {}
+  static void set property9(int value) {}
+  void set property1(int i) {}
+  void set property2(num i) {}
+  void set property3(int i) {}
+  void set property4(S i) {}
+  void set property5(T i) {}
+  void set property6(S i) {}
+}
+
 int get property1 => 0;
 int get property2 => 0;
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.expect
index f2f3537..c6058f6 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.expect
@@ -37,6 +37,13 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   num get property6; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6 = 0;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The return type of the method 'C2.property6' is 'num', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   num get property6; // error
@@ -45,13 +52,6 @@
 //   int property6 = 0;
 //       ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   num get property6; // error
-//           ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6 = 0;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:116:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
 // abstract class D3 implements D1, D2 /* error on property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.outline.expect
index 36042d2..40bce371 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.outline.expect
@@ -9,6 +9,13 @@
 //   late final int? property6;
 //                   ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -17,13 +24,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.expect
index e53ccba4..4d7c28b 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.expect
@@ -9,6 +9,13 @@
 //   late final int? property6;
 //                   ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -17,13 +24,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.transformed.expect
index e53ccba4..4d7c28b 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.transformed.expect
@@ -9,6 +9,13 @@
 //   late final int? property6;
 //                   ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -17,13 +24,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.textual_outline.expect
index 2045647..2470729 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.textual_outline.expect
@@ -1,19 +1,18 @@
 abstract class A {
-  late int ;
-  property4;
-  late int;
-  operator? (){}
-  property5;
+  late
+  int property4;
+  late
+  int? property5;
   covariant late int ;
   property6;
   A(this.property4, this.property5, this.property6);
 }
 abstract class B1 {
-  late ;
+  late
   final int property4;
-  late ;
+  late
   final int property5;
-  late ;
+  late
   final int? property6;
   B1(this.property4, this.property5, this.property6);
 }
@@ -23,12 +22,12 @@
   void set property6(int i);
 }
 abstract class C1 {
-  late int ;
-  property4;
-  late int ;
-  property5;
-  late int ;
-  property6;
+  late
+  int property4;
+  late
+  int property5;
+  late
+  int property6;
   C1(this.property4, this.property5, this.property6);
 }
 abstract class C2 implements C1 {
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.expect
index e53ccba4..4d7c28b 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.expect
@@ -9,6 +9,13 @@
 //   late final int? property6;
 //                   ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -17,13 +24,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.transformed.expect
index e53ccba4..4d7c28b 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.transformed.expect
@@ -9,6 +9,13 @@
 //   late final int? property6;
 //                   ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -17,13 +24,6 @@
 //   late int property6;
 //            ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
-//   late int property6;
-//            ^^^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.outline.expect
index ced9893..73e689a 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.outline.expect
@@ -37,6 +37,13 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -45,13 +52,6 @@
 //   int property6;
 //       ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
 // abstract class D3 implements D1, D2 /* error on property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.expect
index 93b128d..c6bf46a 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.expect
@@ -37,6 +37,13 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -45,13 +52,6 @@
 //   int property6;
 //       ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
 // abstract class D3 implements D1, D2 /* error on property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.transformed.expect
index 93b128d..c6bf46a 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.transformed.expect
@@ -37,6 +37,13 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -45,13 +52,6 @@
 //   int property6;
 //       ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
 // abstract class D3 implements D1, D2 /* error on property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect
index 1bfebe7..b5c6ecb 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect
@@ -4,6 +4,7 @@
 void set property2(int? value) {}
 int? get property3 => 0;
 void set property3(int value) {}
+
 abstract class A {
   int get property1;
   void set property1(int i);
@@ -22,6 +23,7 @@
   static int? get property9 => 0;
   static void set property9(int value) {}
 }
+
 abstract class B1 {
   int get property1;
   int get property2;
@@ -31,6 +33,7 @@
   final int? property6;
   B1(this.property4, this.property5, this.property6);
 }
+
 abstract class B2 implements B1 {
   void set property1(int i);
   void set property2(int? i);
@@ -39,6 +42,7 @@
   void set property5(int? i);
   void set property6(int i);
 }
+
 abstract class C1 {
   void set property1(int i);
   void set property2(int? i);
@@ -48,6 +52,7 @@
   int property6;
   C1(this.property4, this.property5, this.property6);
 }
+
 abstract class C2 implements C1 {
   int get property1;
   int get property2;
@@ -56,18 +61,44 @@
   int get property5;
   int? get property6;
 }
+
 abstract class D1 {
   int get property1;
   int get property2;
   int? get property3;
 }
+
 abstract class D2 {
   void set property1(int i);
   void set property2(int? i);
   void set property3(int i);
 }
+
 abstract class D3 implements D1, D2 {}
+
 abstract class D4 implements D3 {}
-extension Extension<T extends num> (){}
-on int (){}
+
+extension Extension<T extends num> on int {
+  int get property1 => 0;
+  void set property1(int i) {}
+  int get property2 => 0;
+  void set property2(int? i) {}
+  int? get property3 => 0;
+  void set property3(int i) {}
+  T get property4a => 0;
+  void set property4a(T i) {}
+  T? get property4b => 0;
+  void set property4b(T? i) {}
+  T get property5 => 0;
+  void set property5(T? i) {}
+  T? get property6 => 0;
+  void set property6(T i) {}
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8 => 0;
+  static void set property8(int? value) {}
+  static int? get property9 => 0;
+  static void set property9(int value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect
index 30cbfa9..9aaca1d 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect
@@ -71,6 +71,29 @@
 
 abstract class D4 implements D3 {}
 
+extension Extension<T extends num> on int {
+  T? get property4b => 0;
+  T? get property6 => 0;
+  T get property4a => 0;
+  T get property5 => 0;
+  int? get property3 => 0;
+  int get property1 => 0;
+  int get property2 => 0;
+  static int? get property9 => 0;
+  static int get property7 => 0;
+  static int get property8 => 0;
+  static void set property7(int value) {}
+  static void set property8(int? value) {}
+  static void set property9(int value) {}
+  void set property1(int i) {}
+  void set property2(int? i) {}
+  void set property3(int i) {}
+  void set property4a(T i) {}
+  void set property4b(T? i) {}
+  void set property5(T? i) {}
+  void set property6(T i) {}
+}
+
 int? get property3 => 0;
 int get property1 => 0;
 int get property2 => 0;
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.expect
index 93b128d..c6bf46a 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.expect
@@ -37,6 +37,13 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -45,13 +52,6 @@
 //   int property6;
 //       ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
 // abstract class D3 implements D1, D2 /* error on property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.transformed.expect
index 93b128d..c6bf46a 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.transformed.expect
@@ -37,6 +37,13 @@
 //   void set property3(int i);
 //            ^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
 // Change to a subtype of 'int'.
 //   int? get property6; // error
@@ -45,13 +52,6 @@
 //   int property6;
 //       ^
 //
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
-//   int? get property6; // error
-//            ^^^^^^^^^
-// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
-//   int property6;
-//       ^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
 // abstract class D3 implements D1, D2 /* error on property3 */ {}
 //                ^
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
index c4ec443..91b9c97 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
@@ -53,7 +53,7 @@
   core::String s2 = let final core::String? #t9 = s in #t9.{core::String::==}(null) ?{core::String} s = "bar" : #t9{core::String};
 }
 static method test4() → dynamic {
-  core::List<core::String?> list = <core::String?>[null];
+  core::List<core::String?> list = core::_GrowableList::_literal1<core::String?>(null);
   core::String s = let final core::List<core::String?> #t10 = list in let final core::int #t11 = 0 in let final core::String? #t12 = #t10.{core::List::[]}(#t11) in #t12.{core::String::==}(null) ?{core::String} let final core::String #t13 = "bar" in let final void #t14 = #t10.{core::List::[]=}(#t11, #t13) in #t13 : #t12{core::String};
 }
 static method E6|[]=(lowered final core::double #this, core::int index, core::String? value) → void {}
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline.expect
index c41c8b4..6e6c210 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline.expect
@@ -1,24 +1,34 @@
 T hest1<T>() => throw "hest";
 test1() {}
+
 class A2 {
   String? foo;
 }
+
 test2(A2 a) {}
 test3() {}
 test4() {}
+
 class A5 {
   void operator []=(int index, String? value) {}
   String? operator [](int index) => null;
 }
+
 class B5 extends A5 {
   test5() {}
 }
-extension E6 ;
-on double (){}
+
+extension E6 on double {
+  void operator []=(int index, String? value) {}
+  String? operator [](int index) => null;
+}
+
 test6() {}
+
 class A7 {
   String foo = "foo";
   String? bar;
 }
+
 test7(A7? a) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1621b7e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline_modelled.expect
@@ -0,0 +1,32 @@
+T hest1<T>() => throw "hest";
+
+class A2 {
+  String? foo;
+}
+
+class A5 {
+  String? operator [](int index) => null;
+  void operator []=(int index, String? value) {}
+}
+
+class A7 {
+  String? bar;
+  String foo = "foo";
+}
+
+class B5 extends A5 {
+  test5() {}
+}
+
+extension E6 on double {
+  String? operator [](int index) => null;
+  void operator []=(int index, String? value) {}
+}
+
+main() {}
+test1() {}
+test2(A2 a) {}
+test3() {}
+test4() {}
+test6() {}
+test7(A7? a) {}
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
index c4ec443..91b9c97 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
@@ -53,7 +53,7 @@
   core::String s2 = let final core::String? #t9 = s in #t9.{core::String::==}(null) ?{core::String} s = "bar" : #t9{core::String};
 }
 static method test4() → dynamic {
-  core::List<core::String?> list = <core::String?>[null];
+  core::List<core::String?> list = core::_GrowableList::_literal1<core::String?>(null);
   core::String s = let final core::List<core::String?> #t10 = list in let final core::int #t11 = 0 in let final core::String? #t12 = #t10.{core::List::[]}(#t11) in #t12.{core::String::==}(null) ?{core::String} let final core::String #t13 = "bar" in let final void #t14 = #t10.{core::List::[]=}(#t11, #t13) in #t13 : #t12{core::String};
 }
 static method E6|[]=(lowered final core::double #this, core::int index, core::String? value) → void {}
diff --git a/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect
index f5314e4..c7299a7 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
     core::print(i);
   }
   {
-    core::Iterator<core::int> :sync-for-iterator = <core::int>[].{core::Iterable::iterator};
+    core::Iterator<core::int> :sync-for-iterator = core::_GrowableList::•<core::int>(0).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect
index f5314e4..c7299a7 100644
--- a/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40093.dart.weak.transformed.expect
@@ -20,7 +20,7 @@
     core::print(i);
   }
   {
-    core::Iterator<core::int> :sync-for-iterator = <core::int>[].{core::Iterable::iterator};
+    core::Iterator<core::int> :sync-for-iterator = core::_GrowableList::•<core::int>(0).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int i = :sync-for-iterator.{core::Iterator::current};
       {
diff --git a/pkg/front_end/testcases/nnbd/issue40945.dart b/pkg/front_end/testcases/nnbd/issue40945.dart
new file mode 100644
index 0000000..060aa8c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40945.dart
@@ -0,0 +1,16 @@
+// 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 C {
+  void set test(int v) {}
+  dynamic get test => 3.14;
+}
+
+test() {
+  C c = new C();
+  c.test = 1;
+  c.test;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue40945.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue40945.dart.outline.expect
new file mode 100644
index 0000000..3cf2669
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40945.dart.outline.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40945.dart:7:15: Error: The type 'dynamic' of the getter 'C.test' is not a subtype of the type 'int' of the setter 'C.test'.
+//   dynamic get test => 3.14;
+//               ^^^^
+// pkg/front_end/testcases/nnbd/issue40945.dart:6:12: Context: This is the declaration of the setter 'C.test'.
+//   void set test(int v) {}
+//            ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    ;
+  set test(core::int v) → void
+    ;
+  get test() → dynamic
+    ;
+}
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue40945.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue40945.dart.strong.expect
new file mode 100644
index 0000000..b38f082d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40945.dart.strong.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40945.dart:7:15: Error: The type 'dynamic' of the getter 'C.test' is not a subtype of the type 'int' of the setter 'C.test'.
+//   dynamic get test => 3.14;
+//               ^^^^
+// pkg/front_end/testcases/nnbd/issue40945.dart:6:12: Context: This is the declaration of the setter 'C.test'.
+//   void set test(int v) {}
+//            ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  set test(core::int v) → void {}
+  get test() → dynamic
+    return 3.14;
+}
+static method test() → dynamic {
+  self::C c = new self::C::•();
+  c.{self::C::test} = 1;
+  c.{self::C::test};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue40945.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue40945.dart.strong.transformed.expect
new file mode 100644
index 0000000..b38f082d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40945.dart.strong.transformed.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40945.dart:7:15: Error: The type 'dynamic' of the getter 'C.test' is not a subtype of the type 'int' of the setter 'C.test'.
+//   dynamic get test => 3.14;
+//               ^^^^
+// pkg/front_end/testcases/nnbd/issue40945.dart:6:12: Context: This is the declaration of the setter 'C.test'.
+//   void set test(int v) {}
+//            ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  set test(core::int v) → void {}
+  get test() → dynamic
+    return 3.14;
+}
+static method test() → dynamic {
+  self::C c = new self::C::•();
+  c.{self::C::test} = 1;
+  c.{self::C::test};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue40945.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue40945.dart.textual_outline.expect
new file mode 100644
index 0000000..1da15dd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40945.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+class C {
+  void set test(int v) {}
+  dynamic get test => 3.14;
+}
+
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue40945.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue40945.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f5a215c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40945.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class C {
+  dynamic get test => 3.14;
+  void set test(int v) {}
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/nnbd/issue40945.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue40945.dart.weak.expect
new file mode 100644
index 0000000..b38f082d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40945.dart.weak.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40945.dart:7:15: Error: The type 'dynamic' of the getter 'C.test' is not a subtype of the type 'int' of the setter 'C.test'.
+//   dynamic get test => 3.14;
+//               ^^^^
+// pkg/front_end/testcases/nnbd/issue40945.dart:6:12: Context: This is the declaration of the setter 'C.test'.
+//   void set test(int v) {}
+//            ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  set test(core::int v) → void {}
+  get test() → dynamic
+    return 3.14;
+}
+static method test() → dynamic {
+  self::C c = new self::C::•();
+  c.{self::C::test} = 1;
+  c.{self::C::test};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue40945.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue40945.dart.weak.transformed.expect
new file mode 100644
index 0000000..b38f082d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40945.dart.weak.transformed.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40945.dart:7:15: Error: The type 'dynamic' of the getter 'C.test' is not a subtype of the type 'int' of the setter 'C.test'.
+//   dynamic get test => 3.14;
+//               ^^^^
+// pkg/front_end/testcases/nnbd/issue40945.dart:6:12: Context: This is the declaration of the setter 'C.test'.
+//   void set test(int v) {}
+//            ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  set test(core::int v) → void {}
+  get test() → dynamic
+    return 3.14;
+}
+static method test() → dynamic {
+  self::C c = new self::C::•();
+  c.{self::C::test} = 1;
+  c.{self::C::test};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41102.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41102.dart.strong.transformed.expect
index 0ee6323..d96e91a 100644
--- a/pkg/front_end/testcases/nnbd/issue41102.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41102.dart.strong.transformed.expect
@@ -68,7 +68,7 @@
 import "dart:async";
 
 static final field asy::StreamTransformer<core::Object?, core::Object?> t = new asy::_StreamHandlerTransformer::•<core::Object?, core::Object?>(handleData: (core::Object? data, asy::EventSink<core::Object?> sink) → void => asy::Future::microtask<void>(() → void => sink.{asy::EventSink::add}(data)), handleDone: (asy::EventSink<core::Object?> sink) → void => asy::Future::microtask<void>(() → void => sink.{asy::EventSink::close}()));
-static final field core::List<dynamic> s1 = <dynamic>[];
+static final field core::List<dynamic> s1 = core::_GrowableList::•<dynamic>(0);
 static final field core::int? s2 = let final core::List<dynamic> #t1 = self::s1 in #t1.{core::List::==}(null) ?{core::int?} null : #t1.{core::List::length};
 static final field core::List<core::int> s3 = core::_List::filled<core::int>(2, let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41102.dart:17:36: Error: The value 'null' can't be assigned to the parameter type 'int' because 'int' is not nullable.
 final s3 = new List<int>.filled(2, null);
diff --git a/pkg/front_end/testcases/nnbd/issue41102.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41102.dart.weak.transformed.expect
index 61062c1..7a6a1c4 100644
--- a/pkg/front_end/testcases/nnbd/issue41102.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41102.dart.weak.transformed.expect
@@ -68,7 +68,7 @@
 import "dart:async";
 
 static final field asy::StreamTransformer<core::Object?, core::Object?> t = new asy::_StreamHandlerTransformer::•<core::Object?, core::Object?>(handleData: (core::Object? data, asy::EventSink<core::Object?> sink) → void => asy::Future::microtask<void>(() → void => sink.{asy::EventSink::add}(data)), handleDone: (asy::EventSink<core::Object?> sink) → void => asy::Future::microtask<void>(() → void => sink.{asy::EventSink::close}()));
-static final field core::List<dynamic> s1 = <dynamic>[];
+static final field core::List<dynamic> s1 = core::_GrowableList::•<dynamic>(0);
 static final field core::int? s2 = let final core::List<dynamic> #t1 = self::s1 in #t1.{core::List::==}(null) ?{core::int?} null : #t1.{core::List::length};
 static final field core::List<core::int> s3 = core::_List::filled<core::int>(2, let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41102.dart:17:36: Error: The value 'null' can't be assigned to the parameter type 'int' because 'int' is not nullable.
 final s3 = new List<int>.filled(2, null);
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
index 5f03cd5..c611839 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
     try {
       #L1:
       {
-        core::List<core::String>? a = <core::String>[];
+        core::List<core::String>? a = core::_GrowableList::•<core::String>(0);
         core::Iterable<core::String>? b = let final core::List<core::String>? #t1 = a in #t1.{core::List::==}(null) ?{core::Iterable<core::String>?} null : #t1{core::List<core::String>}.{core::Iterable::map}<core::String>((core::String e) → core::String => e);
         core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2.{core::Object::==}(null) ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
         core::print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
index 5f03cd5..c611839 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.transformed.expect
@@ -15,7 +15,7 @@
     try {
       #L1:
       {
-        core::List<core::String>? a = <core::String>[];
+        core::List<core::String>? a = core::_GrowableList::•<core::String>(0);
         core::Iterable<core::String>? b = let final core::List<core::String>? #t1 = a in #t1.{core::List::==}(null) ?{core::Iterable<core::String>?} null : #t1{core::List<core::String>}.{core::Iterable::map}<core::String>((core::String e) → core::String => e);
         core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2.{core::Object::==}(null) ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
         core::print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.expect
index 11217a1..ca6b488 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.expect
@@ -55,19 +55,19 @@
   (core::int) → core::String x6 = (core::int v) → Never {
     return self::throwing();
   };
-  (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => throw v;
+  (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => let final Never #t1 = throw v in #t1 is asy::Future<Never> ?{FutureOr<core::String>} await #t1 : #t1;
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> async {
     throw v;
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> async {
-    return throw v;
+    return let final Never #t2 = throw v in #t2 is asy::Future<Never> ?{FutureOr<core::String>} await #t2 : #t2;
   };
-  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => self::throwing();
+  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => let final Never #t3 = self::throwing() in #t3 is asy::Future<Never> ?{FutureOr<core::String>} await #t3 : #t3;
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> async {
     self::throwing();
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> async {
-    return self::throwing();
+    return let final Never #t4 = self::throwing() in #t4 is asy::Future<Never> ?{FutureOr<core::String>} await #t4 : #t4;
   };
 }
 static method errors() → void async {
@@ -77,7 +77,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
   };
@@ -87,7 +87,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
   };
@@ -97,7 +97,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
   };
@@ -107,7 +107,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
   };
@@ -117,17 +117,17 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<core::String> async {
     try {
-      return throw v;
+      return let final Never #t10 = throw v in #t10 is asy::Future<core::String> ?{FutureOr<core::String>} await #t10 : #t10;
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
   };
@@ -137,17 +137,17 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<core::String> async {
     try {
-      return self::throwing();
+      return let final Never #t13 = self::throwing() in #t13 is asy::Future<core::String> ?{FutureOr<core::String>} await #t13 : #t13;
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
   };
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
index 3e9bef1..515ceec 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.strong.transformed.expect
@@ -37,6 +37,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 static method throwing() → Never
   return throw "";
@@ -63,11 +64,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
         {
-          :return_value = throw v;
+          final Never #t1 = throw v;
+          if(#t1 is asy::Future<Never>) {
+            [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t1;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -116,11 +127,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L3:
         {
-          :return_value = throw v;
+          final Never #t3 = throw v;
+          if(#t3 is asy::Future<Never>) {
+            [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t3;
+          }
+          :return_value = :async_temporary_0;
           break #L3;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -143,11 +164,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L4:
         {
-          :return_value = self::throwing();
+          final Never #t5 = self::throwing();
+          if(#t5 is asy::Future<Never>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
           break #L4;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -196,11 +227,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L6:
         {
-          :return_value = self::throwing();
+          final Never #t7 = self::throwing();
+          if(#t7 is asy::Future<Never>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t7;
+          }
+          :return_value = :async_temporary_0;
           break #L6;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -234,7 +275,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
         };
@@ -244,7 +285,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
         };
@@ -254,7 +295,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
         };
@@ -264,7 +305,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
         };
@@ -285,7 +326,7 @@
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
                 break #L8;
@@ -310,17 +351,28 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          dynamic :saved_try_context_var1;
+          FutureOr<core::String>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L9:
               {
                 try {
-                  :return_value = throw v;
+                  final Never #t14 = throw v;
+                  if(#t14 is asy::Future<core::String>) {
+                    [yield] let dynamic #t15 = asy::_awaitHelper(#t14, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<Never>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t14;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L9;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
                 break #L9;
@@ -354,7 +406,7 @@
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
                 break #L10;
@@ -379,17 +431,28 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          dynamic :saved_try_context_var1;
+          FutureOr<core::String>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L11:
               {
                 try {
-                  :return_value = self::throwing();
+                  final Never #t18 = self::throwing();
+                  if(#t18 is asy::Future<core::String>) {
+                    [yield] let dynamic #t19 = asy::_awaitHelper(#t18, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<Never>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t18;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L11;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
                 break #L11;
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
index 3ced126..344471e 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
@@ -56,19 +56,19 @@
   (core::int) → core::String x6 = (core::int v) → Never {
     return let final Never #t3 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
-  (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => throw v;
+  (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => let final Never #t4 = throw v in #t4 is asy::Future<Never> ?{FutureOr<core::String>} await #t4 : #t4;
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> async {
     throw v;
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> async {
-    return throw v;
+    return let final Never #t5 = throw v in #t5 is asy::Future<Never> ?{FutureOr<core::String>} await #t5 : #t5;
   };
-  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => let final Never #t4 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => let final Never #t6 = let final Never #t7 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t6 is asy::Future<Never> ?{FutureOr<core::String>} await #t6 : #t6;
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> async {
-    let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    let final Never #t8 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> async {
-    return let final Never #t6 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    return let final Never #t9 = let final Never #t10 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t9 is asy::Future<Never> ?{FutureOr<core::String>} await #t9 : #t9;
   };
 }
 static method errors() → void async {
@@ -78,7 +78,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
   };
@@ -88,27 +88,27 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
   };
   (core::int) → core::String x5 = (core::int v) → core::String {
     try {
-      let final Never #t9 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+      let final Never #t13 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
   };
   (core::int) → core::String x6 = (core::int v) → core::String {
     try {
-      return let final Never #t11 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+      return let final Never #t15 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
   };
@@ -118,37 +118,37 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<core::String> async {
     try {
-      return throw v;
+      return let final Never #t18 = throw v in #t18 is asy::Future<core::String> ?{FutureOr<core::String>} await #t18 : #t18;
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<core::String> async {
     try {
-      let final Never #t15 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+      let final Never #t20 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<core::String> async {
     try {
-      return let final Never #t17 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+      return let final Never #t22 = let final Never #t23 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t22 is asy::Future<core::String> ?{FutureOr<core::String>} await #t22 : #t22;
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
   };
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
index e3ff8f7..5ebb180 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
@@ -64,11 +64,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
         {
-          :return_value = throw v;
+          final Never #t4 = throw v;
+          if(#t4 is asy::Future<Never>) {
+            [yield] let dynamic #t5 = asy::_awaitHelper(#t4, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t4;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -117,11 +127,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L3:
         {
-          :return_value = throw v;
+          final Never #t6 = throw v;
+          if(#t6 is asy::Future<Never>) {
+            [yield] let dynamic #t7 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t6;
+          }
+          :return_value = :async_temporary_0;
           break #L3;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -144,11 +164,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L4:
         {
-          :return_value = let final Never #t4 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          final Never #t8 = let final Never #t9 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          if(#t8 is asy::Future<Never>) {
+            [yield] let dynamic #t10 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t8;
+          }
+          :return_value = :async_temporary_0;
           break #L4;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -175,7 +205,7 @@
       try {
         #L5:
         {
-          let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          let final Never #t11 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
         return;
@@ -197,11 +227,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::String>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L6:
         {
-          :return_value = let final Never #t6 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          final Never #t12 = let final Never #t13 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+          if(#t12 is asy::Future<Never>) {
+            [yield] let dynamic #t14 = asy::_awaitHelper(#t12, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Never>(:result);
+          }
+          else {
+            :async_temporary_0 = #t12;
+          }
+          :return_value = :async_temporary_0;
           break #L6;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -235,7 +275,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
         };
@@ -245,27 +285,27 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
         };
         (core::int) → core::String x5 = (core::int v) → core::String {
           try {
-            let final Never #t9 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+            let final Never #t17 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
         };
         (core::int) → core::String x6 = (core::int v) → core::String {
           try {
-            return let final Never #t11 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+            return let final Never #t19 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
         };
@@ -286,7 +326,7 @@
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
                 break #L8;
@@ -311,17 +351,28 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          dynamic :saved_try_context_var1;
+          FutureOr<core::String>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L9:
               {
                 try {
-                  :return_value = throw v;
+                  final Never #t22 = throw v;
+                  if(#t22 is asy::Future<core::String>) {
+                    [yield] let dynamic #t23 = asy::_awaitHelper(#t22, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<Never>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t22;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L9;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
                 break #L9;
@@ -351,11 +402,11 @@
               #L10:
               {
                 try {
-                  let final Never #t15 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+                  let final Never #t25 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
                 break #L10;
@@ -380,17 +431,28 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          dynamic :saved_try_context_var1;
+          FutureOr<core::String>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L11:
               {
                 try {
-                  :return_value = let final Never #t17 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+                  final Never #t27 = let final Never #t28 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+                  if(#t27 is asy::Future<core::String>) {
+                    [yield] let dynamic #t29 = asy::_awaitHelper(#t27, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<Never>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t27;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L11;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
                 break #L11;
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.expect
index eff260bc..6eef4f6 100644
--- a/pkg/front_end/testcases/nnbd/issue41273.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.expect
@@ -13,7 +13,7 @@
     Never n7 = x{Never}.call();
     Never n8 = x{Never}.runtimeType();
     Never n9 = x{Never}.toString;
-    x{Never}.runtimeType = core::Object;
+    x{Never}.runtimeType = #C1;
     x{Never}.toString = () → core::String => "";
     Never v1 = x{Never}.toString();
     Never v2 = x{Never}.runtimeType;
@@ -29,3 +29,7 @@
 static method main() → dynamic {
   self::test(null);
 }
+
+constants  {
+  #C1 = TypeLiteralConstant(core::Object)
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect
index 368f224..6eef4f6 100644
--- a/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
     Never n7 = x{Never}.call();
     Never n8 = x{Never}.runtimeType();
     Never n9 = x{Never}.toString;
-    x{Never}.runtimeType = core::Object;
+    x{Never}.runtimeType = #C1;
     x{Never}.toString = () → core::String => "";
     Never v1 = x{Never}.toString();
     Never v2 = x{Never}.runtimeType;
@@ -30,7 +30,6 @@
   self::test(null);
 }
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///issue41273.dart:16:21 -> TypeLiteralConstant(Object)
-Extra constant evaluation: evaluated: 49, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(core::Object)
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect
index 8c49c0f..e220d05 100644
--- a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect
@@ -14,7 +14,7 @@
     Never n7 = let final Never #t15 = (let final Never #t16 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     Never n8 = let final Never #t17 = (let final Never #t18 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     Never n9 = let final Never #t19 = (let final Never #t20 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
-    (let final Never #t21 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType = core::Object;
+    (let final Never #t21 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType = #C1;
     (let final Never #t22 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString = () → core::String => "";
     Never v1 = let final Never #t23 = (let final Never #t24 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     Never v2 = let final Never #t25 = (let final Never #t26 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
@@ -30,3 +30,7 @@
 static method main() → dynamic {
   self::test(null);
 }
+
+constants  {
+  #C1 = TypeLiteralConstant(core::Object*)
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect
index e7749a6..e220d05 100644
--- a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect
@@ -14,7 +14,7 @@
     Never n7 = let final Never #t15 = (let final Never #t16 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     Never n8 = let final Never #t17 = (let final Never #t18 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     Never n9 = let final Never #t19 = (let final Never #t20 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
-    (let final Never #t21 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType = core::Object;
+    (let final Never #t21 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType = #C1;
     (let final Never #t22 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString = () → core::String => "";
     Never v1 = let final Never #t23 = (let final Never #t24 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     Never v2 = let final Never #t25 = (let final Never #t26 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
@@ -31,7 +31,6 @@
   self::test(null);
 }
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///issue41273.dart:16:21 -> TypeLiteralConstant(Object)
-Extra constant evaluation: evaluated: 175, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(core::Object*)
+}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline.expect
index 6fca9a1..3e3ff63 100644
--- a/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline.expect
@@ -1,15 +1,20 @@
 class A {
   foo() => 23;
 }
-extension B ;
-on A;
-? { foo() => 42; bar() => 87; }
-extension C ;
-on A (){}
-extension D ;
-on int ;
-Function(){}
-? { int call() => 76; }
+
+extension B on A? {
+  foo() => 42;
+  bar() => 87;
+}
+
+extension C on A {
+  bar() => 123;
+}
+
+extension D on int Function()? {
+  int call() => 76;
+}
+
 main() {}
 testA(A? a) {}
 testFunction(int Function()? f) {}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..545b414
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+class A {
+  foo() => 23;
+}
+
+expect(expected, actual) {}
+
+extension B on A? {
+  bar() => 87;
+  foo() => 42;
+}
+
+extension C on A {
+  bar() => 123;
+}
+
+extension D on int Function()? {
+  int call() => 76;
+}
+
+main() {}
+testA(A? a) {}
+testFunction(int Function()? f) {}
diff --git a/pkg/front_end/testcases/nnbd/issue41386b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41386b.dart.strong.transformed.expect
index 5e52bce..240cc0d 100644
--- a/pkg/front_end/testcases/nnbd/issue41386b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41386b.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 static method test() → void {
   core::Map<dynamic, dynamic> map = <dynamic, dynamic>{};
   map.{core::Map::[]}(0).foo;
-  core::Iterable<core::String> elements = <core::String>[];
+  core::Iterable<core::String> elements = core::_GrowableList::•<core::String>(0);
   core::List<dynamic> list = core::List::from<dynamic>(elements);
   core::List::from<dynamic>(elements).{core::Iterable::forEach}((dynamic element) → void => element.foo);
 }
diff --git a/pkg/front_end/testcases/nnbd/issue41386b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41386b.dart.weak.transformed.expect
index 5e52bce..240cc0d 100644
--- a/pkg/front_end/testcases/nnbd/issue41386b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41386b.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 static method test() → void {
   core::Map<dynamic, dynamic> map = <dynamic, dynamic>{};
   map.{core::Map::[]}(0).foo;
-  core::Iterable<core::String> elements = <core::String>[];
+  core::Iterable<core::String> elements = core::_GrowableList::•<core::String>(0);
   core::List<dynamic> list = core::List::from<dynamic>(elements);
   core::List::from<dynamic>(elements).{core::Iterable::forEach}((dynamic element) → void => element.foo);
 }
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect
index fbcd99e..d7881ae 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect
@@ -34,61 +34,61 @@
 static method getNull() → dynamic
   return null;
 static method getFutureNull() → asy::Future<dynamic> async {
-  return null;
+  return let final Null #t1 = null in #t1 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t1 : #t1;
 }
 static method getFutureBool() → asy::Future<core::bool> async {
-  return true;
+  return let final core::bool #t2 = true in #t2 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t2 : #t2;
 }
 static method test1() → asy::Future<core::bool> async 
-  return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+  return let final dynamic #t3 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t3 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t3 : #t3;
 static method test2() → asy::Future<core::bool>
   return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
 static method test3() → core::bool
   return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
 static method test4() → asy::Future<core::bool> async 
-  return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+  return let final dynamic #t4 = await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t4 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t4 : #t4;
 static method test5() → asy::Future<core::bool>
-  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
 Future<bool> test5() => getFutureNull(); // error
                         ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
 static method test6() → asy::Future<core::bool>
   return self::getFutureBool();
 static method test7() → asy::Future<core::bool> async 
-  return self::getFutureBool();
+  return let final asy::Future<core::bool> #t6 = self::getFutureBool() in #t6 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t6 : #t6;
 static method test() → dynamic async {
   function test1() → asy::Future<core::bool> async 
-    return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+    return let final dynamic #t7 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t7 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t7 : #t7;
   function test2() → asy::Future<core::bool>
     return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
   function test3() → core::bool
     return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
   function test4() → asy::Future<core::bool> async 
-    return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+    return let final dynamic #t8 = await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t8 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t8 : #t8;
   function test5() → asy::Future<core::bool>
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> test5() => getFutureNull(); // error
                           ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   function test6() → asy::Future<core::bool>
     return self::getFutureBool();
   function test7() → asy::Future<core::bool> async 
-    return self::getFutureBool();
-  asy::Future<core::bool> var1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+    return let final asy::Future<core::bool> #t10 = self::getFutureBool() in #t10 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t10 : #t10;
+  asy::Future<core::bool> var1 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var1 = (() async => await getNull())(); // error
-                                                   ^" in (() → asy::Future<dynamic> async => await self::getNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
+                                                   ^" in (() → asy::Future<dynamic> async => let final dynamic #t12 = await self::getNull() in #t12 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t12 : #t12).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
   core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
-  asy::Future<core::bool> var4 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+  asy::Future<core::bool> var4 = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var4 = (() async => await getFutureNull())(); // error
-                                                         ^" in (() → asy::Future<dynamic> async => await self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
-  asy::Future<core::bool> var5 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+                                                         ^" in (() → asy::Future<dynamic> async => let final dynamic #t14 = await self::getFutureNull() in #t14 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t14 : #t14).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
+  asy::Future<core::bool> var5 = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var5 = (() => getFutureNull())(); // error
                                              ^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   asy::Future<core::bool> var6 = (() → asy::Future<core::bool> => self::getFutureBool()).call();
-  asy::Future<core::bool> var7 = (() → asy::Future<core::bool> async => self::getFutureBool()).call();
+  asy::Future<core::bool> var7 = (() → asy::Future<core::bool> async => let final asy::Future<core::bool> #t16 = self::getFutureBool() in #t16 is asy::Future<core::bool> ?{FutureOr<dynamic>} await #t16 : #t16).call();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
index b4ab7d2..2b35c4f 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect
@@ -30,6 +30,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method getNull() → dynamic
   return null;
@@ -41,11 +42,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<dynamic>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
       {
-        :return_value = null;
+        final Null #t1 = null;
+        if(#t1 is asy::Future<dynamic>) {
+          [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<Null>(:result);
+        }
+        else {
+          :async_temporary_0 = #t1;
+        }
+        :return_value = :async_temporary_0;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -68,11 +79,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L2:
       {
-        :return_value = true;
+        final core::bool #t3 = true;
+        if(#t3 is asy::Future<core::bool>) {
+          [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t3;
+        }
+        :return_value = :async_temporary_0;
         break #L2;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -96,12 +117,21 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L3:
       {
-        [yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        [yield] let dynamic #t5 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+        final FutureOr<core::bool>#t6 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        if(#t6 is asy::Future<core::bool>) {
+          [yield] let dynamic #t7 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t6;
+        }
+        :return_value = :async_temporary_0;
         break #L3;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -129,12 +159,21 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
       {
-        [yield] let dynamic #t2 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        [yield] let dynamic #t8 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+        final FutureOr<core::bool>#t9 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        if(#t9 is asy::Future<core::bool>) {
+          [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t9;
+        }
+        :return_value = :async_temporary_0;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -150,7 +189,7 @@
   return :async_future;
 }
 static method test5() → asy::Future<core::bool>
-  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+  return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
 Future<bool> test5() => getFutureNull(); // error
                         ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -164,11 +203,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L5:
       {
-        :return_value = self::getFutureBool();
+        final asy::Future<core::bool> #t12 = self::getFutureBool();
+        if(#t12 is asy::Future<core::bool>) {
+          [yield] let dynamic #t13 = asy::_awaitHelper(#t12, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t12;
+        }
+        :return_value = :async_temporary_0;
         break #L5;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -204,12 +253,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L7:
               {
-                [yield] let dynamic #t4 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                [yield] let dynamic #t14 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final FutureOr<core::bool>#t15 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                if(#t15 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t15;
+                }
+                :return_value = :async_temporary_0;
                 break #L7;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -237,12 +295,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L8:
               {
-                [yield] let dynamic #t5 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                [yield] let dynamic #t17 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final FutureOr<core::bool>#t18 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                if(#t18 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t19 = asy::_awaitHelper(#t18, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t18;
+                }
+                :return_value = :async_temporary_0;
                 break #L8;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -258,7 +325,7 @@
           return :async_future;
         }
         function test5() → asy::Future<core::bool>
-          return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+          return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> test5() => getFutureNull(); // error
                           ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -272,11 +339,21 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L9:
               {
-                :return_value = self::getFutureBool();
+                final asy::Future<core::bool> #t21 = self::getFutureBool();
+                if(#t21 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t22 = asy::_awaitHelper(#t21, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t21;
+                }
+                :return_value = :async_temporary_0;
                 break #L9;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -291,7 +368,7 @@
           :is_sync = true;
           return :async_future;
         }
-        asy::Future<core::bool> var1 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var1 = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var1 = (() async => await getNull())(); // error
                                                    ^" in (() → asy::Future<dynamic> /* originally async */ {
@@ -303,12 +380,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L10:
               {
-                [yield] let dynamic #t8 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result;
+                [yield] let dynamic #t24 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final dynamic #t25 = :result;
+                if(#t25 is asy::Future<dynamic>) {
+                  [yield] let dynamic #t26 = asy::_awaitHelper(#t25, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = :result;
+                }
+                else {
+                  :async_temporary_0 = #t25;
+                }
+                :return_value = :async_temporary_0;
                 break #L10;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -325,7 +411,7 @@
         }).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
         asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
         core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
-        asy::Future<core::bool> var4 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var4 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var4 = (() async => await getFutureNull())(); // error
                                                          ^" in (() → asy::Future<dynamic> /* originally async */ {
@@ -337,12 +423,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L11:
               {
-                [yield] let dynamic #t10 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result;
+                [yield] let dynamic #t28 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final dynamic #t29 = :result;
+                if(#t29 is asy::Future<dynamic>) {
+                  [yield] let dynamic #t30 = asy::_awaitHelper(#t29, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = :result;
+                }
+                else {
+                  :async_temporary_0 = #t29;
+                }
+                :return_value = :async_temporary_0;
                 break #L11;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -357,7 +452,7 @@
           :is_sync = true;
           return :async_future;
         }).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
-        asy::Future<core::bool> var5 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var5 = let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var5 = (() => getFutureNull())(); // error
                                              ^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -370,11 +465,21 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L12:
               {
-                :return_value = self::getFutureBool();
+                final asy::Future<core::bool> #t32 = self::getFutureBool();
+                if(#t32 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t33 = asy::_awaitHelper(#t32, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t32;
+                }
+                :return_value = :async_temporary_0;
                 break #L12;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect
index fbcd99e..d7881ae 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect
@@ -34,61 +34,61 @@
 static method getNull() → dynamic
   return null;
 static method getFutureNull() → asy::Future<dynamic> async {
-  return null;
+  return let final Null #t1 = null in #t1 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t1 : #t1;
 }
 static method getFutureBool() → asy::Future<core::bool> async {
-  return true;
+  return let final core::bool #t2 = true in #t2 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t2 : #t2;
 }
 static method test1() → asy::Future<core::bool> async 
-  return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+  return let final dynamic #t3 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t3 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t3 : #t3;
 static method test2() → asy::Future<core::bool>
   return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
 static method test3() → core::bool
   return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
 static method test4() → asy::Future<core::bool> async 
-  return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+  return let final dynamic #t4 = await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t4 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t4 : #t4;
 static method test5() → asy::Future<core::bool>
-  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
 Future<bool> test5() => getFutureNull(); // error
                         ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
 static method test6() → asy::Future<core::bool>
   return self::getFutureBool();
 static method test7() → asy::Future<core::bool> async 
-  return self::getFutureBool();
+  return let final asy::Future<core::bool> #t6 = self::getFutureBool() in #t6 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t6 : #t6;
 static method test() → dynamic async {
   function test1() → asy::Future<core::bool> async 
-    return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+    return let final dynamic #t7 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t7 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t7 : #t7;
   function test2() → asy::Future<core::bool>
     return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
   function test3() → core::bool
     return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
   function test4() → asy::Future<core::bool> async 
-    return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+    return let final dynamic #t8 = await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool> in #t8 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t8 : #t8;
   function test5() → asy::Future<core::bool>
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> test5() => getFutureNull(); // error
                           ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   function test6() → asy::Future<core::bool>
     return self::getFutureBool();
   function test7() → asy::Future<core::bool> async 
-    return self::getFutureBool();
-  asy::Future<core::bool> var1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+    return let final asy::Future<core::bool> #t10 = self::getFutureBool() in #t10 is asy::Future<core::bool> ?{FutureOr<core::bool>} await #t10 : #t10;
+  asy::Future<core::bool> var1 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var1 = (() async => await getNull())(); // error
-                                                   ^" in (() → asy::Future<dynamic> async => await self::getNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
+                                                   ^" in (() → asy::Future<dynamic> async => let final dynamic #t12 = await self::getNull() in #t12 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t12 : #t12).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
   core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
-  asy::Future<core::bool> var4 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+  asy::Future<core::bool> var4 = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var4 = (() async => await getFutureNull())(); // error
-                                                         ^" in (() → asy::Future<dynamic> async => await self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
-  asy::Future<core::bool> var5 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+                                                         ^" in (() → asy::Future<dynamic> async => let final dynamic #t14 = await self::getFutureNull() in #t14 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t14 : #t14).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
+  asy::Future<core::bool> var5 = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var5 = (() => getFutureNull())(); // error
                                              ^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
   asy::Future<core::bool> var6 = (() → asy::Future<core::bool> => self::getFutureBool()).call();
-  asy::Future<core::bool> var7 = (() → asy::Future<core::bool> async => self::getFutureBool()).call();
+  asy::Future<core::bool> var7 = (() → asy::Future<core::bool> async => let final asy::Future<core::bool> #t16 = self::getFutureBool() in #t16 is asy::Future<core::bool> ?{FutureOr<dynamic>} await #t16 : #t16).call();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
index b4ab7d2..2b35c4f 100644
--- a/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437a.dart.weak.transformed.expect
@@ -30,6 +30,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method getNull() → dynamic
   return null;
@@ -41,11 +42,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<dynamic>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
       {
-        :return_value = null;
+        final Null #t1 = null;
+        if(#t1 is asy::Future<dynamic>) {
+          [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<Null>(:result);
+        }
+        else {
+          :async_temporary_0 = #t1;
+        }
+        :return_value = :async_temporary_0;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -68,11 +79,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L2:
       {
-        :return_value = true;
+        final core::bool #t3 = true;
+        if(#t3 is asy::Future<core::bool>) {
+          [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t3;
+        }
+        :return_value = :async_temporary_0;
         break #L2;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -96,12 +117,21 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L3:
       {
-        [yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        [yield] let dynamic #t5 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+        final FutureOr<core::bool>#t6 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        if(#t6 is asy::Future<core::bool>) {
+          [yield] let dynamic #t7 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t6;
+        }
+        :return_value = :async_temporary_0;
         break #L3;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -129,12 +159,21 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
       {
-        [yield] let dynamic #t2 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        [yield] let dynamic #t8 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+        final FutureOr<core::bool>#t9 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+        if(#t9 is asy::Future<core::bool>) {
+          [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t9;
+        }
+        :return_value = :async_temporary_0;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -150,7 +189,7 @@
   return :async_future;
 }
 static method test5() → asy::Future<core::bool>
-  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+  return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
 Future<bool> test5() => getFutureNull(); // error
                         ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -164,11 +203,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::bool>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L5:
       {
-        :return_value = self::getFutureBool();
+        final asy::Future<core::bool> #t12 = self::getFutureBool();
+        if(#t12 is asy::Future<core::bool>) {
+          [yield] let dynamic #t13 = asy::_awaitHelper(#t12, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+        }
+        else {
+          :async_temporary_0 = #t12;
+        }
+        :return_value = :async_temporary_0;
         break #L5;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -204,12 +253,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L7:
               {
-                [yield] let dynamic #t4 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                [yield] let dynamic #t14 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final FutureOr<core::bool>#t15 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                if(#t15 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t15;
+                }
+                :return_value = :async_temporary_0;
                 break #L7;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -237,12 +295,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L8:
               {
-                [yield] let dynamic #t5 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                [yield] let dynamic #t17 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final FutureOr<core::bool>#t18 = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
+                if(#t18 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t19 = asy::_awaitHelper(#t18, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t18;
+                }
+                :return_value = :async_temporary_0;
                 break #L8;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -258,7 +325,7 @@
           return :async_future;
         }
         function test5() → asy::Future<core::bool>
-          return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
+          return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> test5() => getFutureNull(); // error
                           ^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -272,11 +339,21 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<core::bool>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L9:
               {
-                :return_value = self::getFutureBool();
+                final asy::Future<core::bool> #t21 = self::getFutureBool();
+                if(#t21 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t22 = asy::_awaitHelper(#t21, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t21;
+                }
+                :return_value = :async_temporary_0;
                 break #L9;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -291,7 +368,7 @@
           :is_sync = true;
           return :async_future;
         }
-        asy::Future<core::bool> var1 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var1 = let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var1 = (() async => await getNull())(); // error
                                                    ^" in (() → asy::Future<dynamic> /* originally async */ {
@@ -303,12 +380,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L10:
               {
-                [yield] let dynamic #t8 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result;
+                [yield] let dynamic #t24 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final dynamic #t25 = :result;
+                if(#t25 is asy::Future<dynamic>) {
+                  [yield] let dynamic #t26 = asy::_awaitHelper(#t25, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = :result;
+                }
+                else {
+                  :async_temporary_0 = #t25;
+                }
+                :return_value = :async_temporary_0;
                 break #L10;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -325,7 +411,7 @@
         }).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
         asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
         core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
-        asy::Future<core::bool> var4 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var4 = let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var4 = (() async => await getFutureNull())(); // error
                                                          ^" in (() → asy::Future<dynamic> /* originally async */ {
@@ -337,12 +423,21 @@
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
           dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L11:
               {
-                [yield] let dynamic #t10 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
-                :return_value = :result;
+                [yield] let dynamic #t28 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
+                final dynamic #t29 = :result;
+                if(#t29 is asy::Future<dynamic>) {
+                  [yield] let dynamic #t30 = asy::_awaitHelper(#t29, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = :result;
+                }
+                else {
+                  :async_temporary_0 = #t29;
+                }
+                :return_value = :async_temporary_0;
                 break #L11;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -357,7 +452,7 @@
           :is_sync = true;
           return :async_future;
         }).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
-        asy::Future<core::bool> var5 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
+        asy::Future<core::bool> var5 = let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
  - 'Future' is from 'dart:async'.
   Future<bool> var5 = (() => getFutureNull())(); // error
                                              ^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -370,11 +465,21 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L12:
               {
-                :return_value = self::getFutureBool();
+                final asy::Future<core::bool> #t32 = self::getFutureBool();
+                if(#t32 is asy::Future<core::bool>) {
+                  [yield] let dynamic #t33 = asy::_awaitHelper(#t32, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<core::bool>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t32;
+                }
+                :return_value = :async_temporary_0;
                 break #L12;
               }
               asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue41657.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41657.dart.strong.transformed.expect
index b2b28aa..0099f42 100644
--- a/pkg/front_end/testcases/nnbd/issue41657.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41657.dart.strong.transformed.expect
@@ -27,9 +27,9 @@
 import self as self;
 import "dart:core" as core;
 
-static final field core::bool isLegacySubtyping1a = <Null>[] is{ForNonNullableByDefault} core::List<core::int>;
+static final field core::bool isLegacySubtyping1a = core::_GrowableList::•<Null>(0) is{ForNonNullableByDefault} core::List<core::int>;
 static const field core::bool isLegacySubtyping1b = #C1;
-static final field core::bool isLegacySubtyping2a = <core::int?>[] is{ForNonNullableByDefault} core::List<core::int>;
+static final field core::bool isLegacySubtyping2a = core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>;
 static const field core::bool isLegacySubtyping2b = #C1;
 static const field core::List<core::int> assertLegacySubtyping1 = invalid-expression "Expected constant '<Null>[]' to be of type 'List<int>', but was of type 'List<Null>'.
  - 'List' is from 'dart:core'.";
diff --git a/pkg/front_end/testcases/nnbd/issue41657.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41657.dart.weak.expect
index 0065c49..574dddd 100644
--- a/pkg/front_end/testcases/nnbd/issue41657.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41657.dart.weak.expect
@@ -20,5 +20,5 @@
 constants  {
   #C1 = true
   #C2 = <Null>[]
-  #C3 = <core::int*>[]
+  #C3 = <core::int?>[]
 }
diff --git a/pkg/front_end/testcases/nnbd/issue41657.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41657.dart.weak.transformed.expect
index 0065c49..c5fa19e 100644
--- a/pkg/front_end/testcases/nnbd/issue41657.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41657.dart.weak.transformed.expect
@@ -2,9 +2,9 @@
 import self as self;
 import "dart:core" as core;
 
-static final field core::bool isLegacySubtyping1a = <Null>[] is{ForNonNullableByDefault} core::List<core::int>;
+static final field core::bool isLegacySubtyping1a = core::_GrowableList::•<Null>(0) is{ForNonNullableByDefault} core::List<core::int>;
 static const field core::bool isLegacySubtyping1b = #C1;
-static final field core::bool isLegacySubtyping2a = <core::int?>[] is{ForNonNullableByDefault} core::List<core::int>;
+static final field core::bool isLegacySubtyping2a = core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>;
 static const field core::bool isLegacySubtyping2b = #C1;
 static const field core::List<core::int> assertLegacySubtyping1 = #C2;
 static const field core::List<core::int> assertLegacySubtyping2 = #C3;
@@ -20,5 +20,5 @@
 constants  {
   #C1 = true
   #C2 = <Null>[]
-  #C3 = <core::int*>[]
+  #C3 = <core::int?>[]
 }
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.expect
index f0b15fb..58eebef 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.expect
@@ -34,23 +34,23 @@
     return s.{core::num::+}(1);
   };
   <S extends FutureOr<core::num> = FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num> = FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> async {
-    return (await t).{core::num::+}(1);
+    return let final core::num #t1 = (await t).{core::num::+}(1) in #t1 is asy::Future<core::num> ?{FutureOr<dynamic>} await #t1 : #t1;
   };
 }
 static method test2(self::C<core::num?> c) → dynamic {
   <S extends core::num? = core::num?>(S%) → core::num f1 = c.{self::C::field1} = <S extends core::num? = core::num?>(S% s) → core::num {
-    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
     return s + 1; // error
              ^" in s.{core::num::+}(1);
   };
   <S extends FutureOr<core::num?> = FutureOr<core::num?>>(S%, FutureOr<core::num?>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num?> = FutureOr<core::num?>>(S% s, FutureOr<core::num?>t) → asy::Future<core::num> async {
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
+    return let final core::num #t3 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
     return (await t) + 1; // error
-                     ^" in (await t).{core::num::+}(1);
+                     ^" in (await t).{core::num::+}(1) in #t3 is asy::Future<core::num> ?{FutureOr<dynamic>} await #t3 : #t3;
   };
 }
 static method test3<S extends core::num? = core::num?>(self::test3::S% s) → dynamic
-  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
 test3<S extends num?>(S s) => s + 1; // error
                                 ^" in s.{core::num::+}(1);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
index b287a57..b08be8f 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.strong.transformed.expect
@@ -43,12 +43,21 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<dynamic>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
         {
           [yield] let dynamic #t1 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1);
+          final core::num #t2 = _in::unsafeCast<core::num>(:result).{core::num::+}(1);
+          if(#t2 is asy::Future<core::num>) {
+            [yield] let dynamic #t3 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t2;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -66,7 +75,7 @@
 }
 static method test2(self::C<core::num?> c) → dynamic {
   <S extends core::num? = core::num?>(S%) → core::num f1 = c.{self::C::field1} = <S extends core::num? = core::num?>(S% s) → core::num {
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+    return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
     return s + 1; // error
              ^" in s.{core::num::+}(1);
   };
@@ -79,15 +88,24 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<dynamic>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L2:
         {
-          final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
+          final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
     return (await t) + 1; // error
                      ^";
-          [yield] let dynamic #t4 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = _in::unsafeCast<core::num?>(:result).{core::num::+}(1);
+          [yield] let dynamic #t6 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
+          final core::num #t7 = _in::unsafeCast<core::num?>(:result).{core::num::+}(1);
+          if(#t7 is asy::Future<core::num>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t7;
+          }
+          :return_value = :async_temporary_0;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -104,7 +122,7 @@
   };
 }
 static method test3<S extends core::num? = core::num?>(self::test3::S% s) → dynamic
-  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+  return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
 test3<S extends num?>(S s) => s + 1; // error
                                 ^" in s.{core::num::+}(1);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.expect
index f0b15fb..58eebef 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.expect
@@ -34,23 +34,23 @@
     return s.{core::num::+}(1);
   };
   <S extends FutureOr<core::num> = FutureOr<core::num>>(S, FutureOr<core::num>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num> = FutureOr<core::num>>(S s, FutureOr<core::num>t) → asy::Future<core::num> async {
-    return (await t).{core::num::+}(1);
+    return let final core::num #t1 = (await t).{core::num::+}(1) in #t1 is asy::Future<core::num> ?{FutureOr<dynamic>} await #t1 : #t1;
   };
 }
 static method test2(self::C<core::num?> c) → dynamic {
   <S extends core::num? = core::num?>(S%) → core::num f1 = c.{self::C::field1} = <S extends core::num? = core::num?>(S% s) → core::num {
-    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
     return s + 1; // error
              ^" in s.{core::num::+}(1);
   };
   <S extends FutureOr<core::num?> = FutureOr<core::num?>>(S%, FutureOr<core::num?>) → asy::Future<core::num> f2 = c.{self::C::field2} = <S extends FutureOr<core::num?> = FutureOr<core::num?>>(S% s, FutureOr<core::num?>t) → asy::Future<core::num> async {
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
+    return let final core::num #t3 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
     return (await t) + 1; // error
-                     ^" in (await t).{core::num::+}(1);
+                     ^" in (await t).{core::num::+}(1) in #t3 is asy::Future<core::num> ?{FutureOr<dynamic>} await #t3 : #t3;
   };
 }
 static method test3<S extends core::num? = core::num?>(self::test3::S% s) → dynamic
-  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
 test3<S extends num?>(S s) => s + 1; // error
                                 ^" in s.{core::num::+}(1);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
index b287a57..b08be8f 100644
--- a/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41697.dart.weak.transformed.expect
@@ -43,12 +43,21 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<dynamic>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L1:
         {
           [yield] let dynamic #t1 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = _in::unsafeCast<core::num>(:result).{core::num::+}(1);
+          final core::num #t2 = _in::unsafeCast<core::num>(:result).{core::num::+}(1);
+          if(#t2 is asy::Future<core::num>) {
+            [yield] let dynamic #t3 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t2;
+          }
+          :return_value = :async_temporary_0;
           break #L1;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -66,7 +75,7 @@
 }
 static method test2(self::C<core::num?> c) → dynamic {
   <S extends core::num? = core::num?>(S%) → core::num f1 = c.{self::C::field1} = <S extends core::num? = core::num?>(S% s) → core::num {
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+    return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:33:14: Error: Operator '+' cannot be called on 'S' because it is potentially null.
     return s + 1; // error
              ^" in s.{core::num::+}(1);
   };
@@ -79,15 +88,24 @@
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
     dynamic :saved_try_context_var0;
+    FutureOr<dynamic>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L2:
         {
-          final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
+          final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:36:22: Error: Operator '+' cannot be called on 'num?' because it is potentially null.
     return (await t) + 1; // error
                      ^";
-          [yield] let dynamic #t4 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
-          :return_value = _in::unsafeCast<core::num?>(:result).{core::num::+}(1);
+          [yield] let dynamic #t6 = asy::_awaitHelper(t, :async_op_then, :async_op_error, :async_op) in null;
+          final core::num #t7 = _in::unsafeCast<core::num?>(:result).{core::num::+}(1);
+          if(#t7 is asy::Future<core::num>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t7;
+          }
+          :return_value = :async_temporary_0;
           break #L2;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -104,7 +122,7 @@
   };
 }
 static method test3<S extends core::num? = core::num?>(self::test3::S% s) → dynamic
-  return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
+  return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41697.dart:40:33: Error: Operator '+' cannot be called on 'S' because it is potentially null.
 test3<S extends num?>(S s) => s + 1; // error
                                 ^" in s.{core::num::+}(1);
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42362.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42362.dart.outline.expect
index dbb74c3..b2b3256 100644
--- a/pkg/front_end/testcases/nnbd/issue42362.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42362.dart.outline.expect
@@ -87,7 +87,7 @@
 
 class A extends core::Object {
   final field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
   constructor constructor1([core::int i]) → self::A
     ;
   constructor constructor2({core::int i}) → self::A
@@ -145,7 +145,7 @@
 }
 class C extends core::Object implements self::B {
   field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
   constructor constructor1([core::int i]) → self::C
     ;
   constructor constructor2({core::int i}) → self::C
diff --git a/pkg/front_end/testcases/nnbd/issue42362.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42362.dart.strong.expect
index 327d48b..176ff0d 100644
--- a/pkg/front_end/testcases/nnbd/issue42362.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42362.dart.strong.expect
@@ -103,7 +103,7 @@
 
 class A extends core::Object {
   final field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
   constructor constructor1([core::int i = #C1]) → self::A
     : self::A::i = i, super core::Object::•()
     ;
@@ -170,7 +170,7 @@
 }
 class C extends core::Object implements self::B {
   field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
   constructor constructor1([core::int i = #C1]) → self::C
     : self::C::i = i, super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue42362.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42362.dart.strong.transformed.expect
index d74b206..f25a954 100644
--- a/pkg/front_end/testcases/nnbd/issue42362.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42362.dart.strong.transformed.expect
@@ -103,7 +103,7 @@
 
 class A extends core::Object {
   final field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
   constructor constructor1([core::int i = #C1]) → self::A
     : self::A::i = i, super core::Object::•()
     ;
@@ -170,7 +170,7 @@
 }
 class C extends core::Object implements self::B {
   field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
   constructor constructor1([core::int i = #C1]) → self::C
     : self::C::i = i, super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue42362.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42362.dart.weak.expect
index 327d48b..176ff0d 100644
--- a/pkg/front_end/testcases/nnbd/issue42362.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42362.dart.weak.expect
@@ -103,7 +103,7 @@
 
 class A extends core::Object {
   final field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
   constructor constructor1([core::int i = #C1]) → self::A
     : self::A::i = i, super core::Object::•()
     ;
@@ -170,7 +170,7 @@
 }
 class C extends core::Object implements self::B {
   field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
   constructor constructor1([core::int i = #C1]) → self::C
     : self::C::i = i, super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue42362.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42362.dart.weak.transformed.expect
index 9e8520e..43212c4 100644
--- a/pkg/front_end/testcases/nnbd/issue42362.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42362.dart.weak.transformed.expect
@@ -103,7 +103,7 @@
 
 class A extends core::Object {
   final field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::factory3, self::A::factory4, self::A::factory5, self::A::factory6, self::A::factory7]/*isLegacy*/;
   constructor constructor1([core::int i = #C1]) → self::A
     : self::A::i = i, super core::Object::•()
     ;
@@ -170,7 +170,7 @@
 }
 class C extends core::Object implements self::B {
   field core::int i;
-  static field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::factory3, self::C::factory4, self::C::factory5, self::C::factory6, self::C::factory7]/*isLegacy*/;
   constructor constructor1([core::int i = #C1]) → self::C
     : self::C::i = i, super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart b/pkg/front_end/testcases/nnbd/issue42429.dart
index 5023f9a..9ef8843 100644
--- a/pkg/front_end/testcases/nnbd/issue42429.dart
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart
@@ -30,6 +30,9 @@
   FNowhere<num?> fNowhereNumNullable; // Error.
   FNowhere<int?> fNowhereIntNullable; // Error.
   FNowhere<Null> fNowhereNull; // Error.
+  FArgument<Object?> fArgumentObjectNullable; // Error.
+  FArgument<dynamic> fArgumentDynamic; // Error.
+  FArgument<void> fArgumentVoid; // Error.
 
   A<Object?> aObjectNullable; // Ok.
   A<dynamic> aDynamic; // Ok.
@@ -37,9 +40,6 @@
   A<num> aNum; // Ok.
   A<int> aInt; // Ok.
   A<Never> aNever; // Ok.
-  FArgument<Object?> fArgumentObjectNullable; // Ok.
-  FArgument<dynamic> fArgumentDynamic; // Ok.
-  FArgument<void> fArgumentVoid; // Ok.
   FArgument<num> fArgumentNum; // Ok.
   FArgument<int> fArgumentInt; // Ok.
   FArgument<Never> fArgumentNever; // Ok.
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.strong.expect
index eebb429..77cfde0 100644
--- a/pkg/front_end/testcases/nnbd/issue42429.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.strong.expect
@@ -167,6 +167,31 @@
 // typedef FNowhere<X extends num> = Function();
 //                  ^
 //
+// pkg/front_end/testcases/nnbd/issue42429.dart:33:22: Error: Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Object?> fArgumentObjectNullable; // Error.
+//                      ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:34:22: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<dynamic> fArgumentDynamic; // Error.
+//                      ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:35:19: Error: Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<void> fArgumentVoid; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -200,15 +225,15 @@
   () → dynamic fNowhereNumNullable;
   () → dynamic fNowhereIntNullable;
   () → dynamic fNowhereNull;
+  (core::Object?) → dynamic fArgumentObjectNullable;
+  (dynamic) → dynamic fArgumentDynamic;
+  (void) → dynamic fArgumentVoid;
   self::A<core::Object?> aObjectNullable;
   self::A<dynamic> aDynamic;
   self::A<void> aVoid;
   self::A<core::num> aNum;
   self::A<core::int> aInt;
   self::A<Never> aNever;
-  (core::Object?) → dynamic fArgumentObjectNullable;
-  (dynamic) → dynamic fArgumentDynamic;
-  (void) → dynamic fArgumentVoid;
   (core::num) → dynamic fArgumentNum;
   (core::int) → dynamic fArgumentInt;
   (Never) → dynamic fArgumentNever;
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.strong.transformed.expect
index eebb429..77cfde0 100644
--- a/pkg/front_end/testcases/nnbd/issue42429.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.strong.transformed.expect
@@ -167,6 +167,31 @@
 // typedef FNowhere<X extends num> = Function();
 //                  ^
 //
+// pkg/front_end/testcases/nnbd/issue42429.dart:33:22: Error: Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Object?> fArgumentObjectNullable; // Error.
+//                      ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:34:22: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<dynamic> fArgumentDynamic; // Error.
+//                      ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:35:19: Error: Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<void> fArgumentVoid; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -200,15 +225,15 @@
   () → dynamic fNowhereNumNullable;
   () → dynamic fNowhereIntNullable;
   () → dynamic fNowhereNull;
+  (core::Object?) → dynamic fArgumentObjectNullable;
+  (dynamic) → dynamic fArgumentDynamic;
+  (void) → dynamic fArgumentVoid;
   self::A<core::Object?> aObjectNullable;
   self::A<dynamic> aDynamic;
   self::A<void> aVoid;
   self::A<core::num> aNum;
   self::A<core::int> aInt;
   self::A<Never> aNever;
-  (core::Object?) → dynamic fArgumentObjectNullable;
-  (dynamic) → dynamic fArgumentDynamic;
-  (void) → dynamic fArgumentVoid;
   (core::num) → dynamic fArgumentNum;
   (core::int) → dynamic fArgumentInt;
   (Never) → dynamic fArgumentNever;
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.weak.expect
index eebb429..77cfde0 100644
--- a/pkg/front_end/testcases/nnbd/issue42429.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.weak.expect
@@ -167,6 +167,31 @@
 // typedef FNowhere<X extends num> = Function();
 //                  ^
 //
+// pkg/front_end/testcases/nnbd/issue42429.dart:33:22: Error: Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Object?> fArgumentObjectNullable; // Error.
+//                      ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:34:22: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<dynamic> fArgumentDynamic; // Error.
+//                      ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:35:19: Error: Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<void> fArgumentVoid; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -200,15 +225,15 @@
   () → dynamic fNowhereNumNullable;
   () → dynamic fNowhereIntNullable;
   () → dynamic fNowhereNull;
+  (core::Object?) → dynamic fArgumentObjectNullable;
+  (dynamic) → dynamic fArgumentDynamic;
+  (void) → dynamic fArgumentVoid;
   self::A<core::Object?> aObjectNullable;
   self::A<dynamic> aDynamic;
   self::A<void> aVoid;
   self::A<core::num> aNum;
   self::A<core::int> aInt;
   self::A<Never> aNever;
-  (core::Object?) → dynamic fArgumentObjectNullable;
-  (dynamic) → dynamic fArgumentDynamic;
-  (void) → dynamic fArgumentVoid;
   (core::num) → dynamic fArgumentNum;
   (core::int) → dynamic fArgumentInt;
   (Never) → dynamic fArgumentNever;
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.weak.transformed.expect
index eebb429..77cfde0 100644
--- a/pkg/front_end/testcases/nnbd/issue42429.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.weak.transformed.expect
@@ -167,6 +167,31 @@
 // typedef FNowhere<X extends num> = Function();
 //                  ^
 //
+// pkg/front_end/testcases/nnbd/issue42429.dart:33:22: Error: Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Object?> fArgumentObjectNullable; // Error.
+//                      ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:34:22: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<dynamic> fArgumentDynamic; // Error.
+//                      ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:35:19: Error: Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<void> fArgumentVoid; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -200,15 +225,15 @@
   () → dynamic fNowhereNumNullable;
   () → dynamic fNowhereIntNullable;
   () → dynamic fNowhereNull;
+  (core::Object?) → dynamic fArgumentObjectNullable;
+  (dynamic) → dynamic fArgumentDynamic;
+  (void) → dynamic fArgumentVoid;
   self::A<core::Object?> aObjectNullable;
   self::A<dynamic> aDynamic;
   self::A<void> aVoid;
   self::A<core::num> aNum;
   self::A<core::int> aInt;
   self::A<Never> aNever;
-  (core::Object?) → dynamic fArgumentObjectNullable;
-  (dynamic) → dynamic fArgumentDynamic;
-  (void) → dynamic fArgumentVoid;
   (core::num) → dynamic fArgumentNum;
   (core::int) → dynamic fArgumentInt;
   (Never) → dynamic fArgumentNever;
diff --git a/pkg/front_end/testcases/nnbd/issue42540.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42540.dart.strong.expect
index aaf931d..c1d787d 100644
--- a/pkg/front_end/testcases/nnbd/issue42540.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42540.dart.strong.expect
@@ -7,6 +7,6 @@
   return null;
 static method fn() → asy::Future<core::Object> async {
   core::Object o = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::Object;
-  return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object>;
+  return let final dynamic #t1 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object> in #t1 is asy::Future<core::Object> ?{FutureOr<core::Object>} await #t1 : #t1;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42540.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42540.dart.strong.transformed.expect
index 4e127a6..b5edde0 100644
--- a/pkg/front_end/testcases/nnbd/issue42540.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42540.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method getNull() → dynamic
   return null;
@@ -14,6 +15,7 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::Object>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -21,7 +23,15 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
         core::Object o = let dynamic #t2 = :result in #t2.==(null) ?{core::Object} #t2 as{TypeError,ForDynamic,ForNonNullableByDefault} core::Object : #t2{core::Object};
         [yield] let dynamic #t3 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = let dynamic #t4 = :result in #t4.==(null) ?{FutureOr<core::Object>} #t4 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object> : #t4{FutureOr<core::Object>};
+        final FutureOr<core::Object>#t4 = let dynamic #t5 = :result in #t5.==(null) ?{FutureOr<core::Object>} #t5 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object> : #t5{FutureOr<core::Object>};
+        if(#t4 is asy::Future<core::Object>) {
+          [yield] let dynamic #t6 = asy::_awaitHelper(#t4, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::Object>(:result);
+        }
+        else {
+          :async_temporary_0 = #t4;
+        }
+        :return_value = :async_temporary_0;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue42540.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42540.dart.weak.expect
index aaf931d..c1d787d 100644
--- a/pkg/front_end/testcases/nnbd/issue42540.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42540.dart.weak.expect
@@ -7,6 +7,6 @@
   return null;
 static method fn() → asy::Future<core::Object> async {
   core::Object o = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::Object;
-  return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object>;
+  return let final dynamic #t1 = await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::Object> in #t1 is asy::Future<core::Object> ?{FutureOr<core::Object>} await #t1 : #t1;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42540.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42540.dart.weak.transformed.expect
index e61b30d..36497a3 100644
--- a/pkg/front_end/testcases/nnbd/issue42540.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42540.dart.weak.transformed.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method getNull() → dynamic
   return null;
@@ -14,6 +15,7 @@
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
   dynamic :saved_try_context_var0;
+  FutureOr<core::Object>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
@@ -21,7 +23,15 @@
         [yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
         core::Object o = :result;
         [yield] let dynamic #t2 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
-        :return_value = :result;
+        final FutureOr<core::Object>#t3 = :result;
+        if(#t3 is asy::Future<core::Object>) {
+          [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<core::Object>(:result);
+        }
+        else {
+          :async_temporary_0 = #t3;
+        }
+        :return_value = :async_temporary_0;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
index 8826a30..819fad7 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
@@ -28,19 +28,19 @@
 
 
 Extra constant evaluation status:
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:664:13 -> SymbolConstant(#catchError)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:664:13 -> ListConstant(const <Type*>[])
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:664:13 -> SymbolConstant(#test)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:701:13 -> SymbolConstant(#whenComplete)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:701:13 -> ListConstant(const <Type*>[])
-Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:701:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:728:13 -> SymbolConstant(#timeout)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:728:13 -> ListConstant(const <Type*>[])
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:728:13 -> SymbolConstant(#onTimeout)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:625:13 -> SymbolConstant(#then)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:625:13 -> SymbolConstant(#onError)
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:712:13 -> SymbolConstant(#asStream)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:712:13 -> ListConstant(const <Type*>[])
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:712:13 -> ListConstant(const <dynamic>[])
-Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:712:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:639:13 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:639:13 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:639:13 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:675:13 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:675:13 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:675:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> SymbolConstant(#onTimeout)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:602:13 -> SymbolConstant(#then)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:602:13 -> SymbolConstant(#onError)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:684:13 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:684:13 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:684:13 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:684:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
 Extra constant evaluation: evaluated: 61, effectively constant: 15
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.expect
index e5372a7..e446f7c 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.expect
@@ -42,11 +42,11 @@
  - 'Future' is from 'dart:async'.
  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
-                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> async => let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> async => let final self::Divergent<core::int> #t2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
  - 'Future' is from 'dart:async'.
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
-                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>>).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
+                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>> in #t2 is asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> ?{FutureOr<dynamic>} await #t2 : #t2).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
new file mode 100644
index 0000000..5ae2bec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.strong.transformed.expect
@@ -0,0 +1,126 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+//  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+//  - 'Future' is from 'dart:async'.
+//   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/issue42546.dart:14:75: Error: A value of type 'Future<Divergent<Divergent<Divergent<int>>>>' can't be assigned to a variable of type 'Future<Divergent<Divergent<int>>>'.
+//  - 'Future' is from 'dart:async'.
+//  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+//   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+//                                                                           ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class Divergent<T extends core::Object? = dynamic> extends core::Object implements asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>> {
+  synthetic constructor •() → self::Divergent<self::Divergent::T%>
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return super.{core::Object::noSuchMethod}(invocation);
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) →? core::bool test = #C1}) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ whenComplete(() → FutureOr<void>action) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl () →? FutureOr<self::Divergent<self::Divergent<self::Divergent::T%>>>onTimeout = #C1}) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C9: onTimeout}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::Divergent<self::Divergent<self::Divergent::T%>>) → FutureOr<self::Divergent::then::R%>onValue, {core::Function? onError = #C1}) → asy::Future<self::Divergent::then::R%>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 0, core::List::unmodifiable<core::Type*>(core::_GrowableList::_literal1<core::Type*>(self::Divergent::then::R%)), core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onValue)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C11: onError}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent::then::R%>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+}
+static method test() → 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;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        asy::Future<self::Divergent<self::Divergent<core::int>>> x = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:75: Error: A value of type 'Future<Divergent<Divergent<Divergent<int>>>>' can't be assigned to a variable of type 'Future<Divergent<Divergent<int>>>'.
+ - 'Future' is from 'dart:async'.
+ - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> /* originally async */ {
+          final asy::_Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> :async_future = new asy::_Future::•<self::Divergent<self::Divergent<self::Divergent<core::int>>>>();
+          core::bool* :is_sync = false;
+          FutureOr<self::Divergent<self::Divergent<self::Divergent<core::int>>>>? :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;
+          FutureOr<dynamic>:async_temporary_0;
+          function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+            try {
+              #L2:
+              {
+                final self::Divergent<core::int> #t2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+ - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+ - 'Future' is from 'dart:async'.
+  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>>;
+                if(#t2 is asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>) {
+                  [yield] let dynamic #t4 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<self::Divergent<self::Divergent<core::int>>>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t2;
+                }
+                :return_value = :async_temporary_0;
+                break #L2;
+              }
+              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              return;
+            }
+            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.call();
+          :is_sync = true;
+          return :async_future;
+        }).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+  #C2 = #catchError
+  #C3 = <core::Type*>[]
+  #C4 = #test
+  #C5 = #whenComplete
+  #C6 = <dynamic>[]
+  #C7 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C6}
+  #C8 = #timeout
+  #C9 = #onTimeout
+  #C10 = #then
+  #C11 = #onError
+  #C12 = #asStream
+}
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.expect
index e5372a7..e446f7c 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.expect
@@ -42,11 +42,11 @@
  - 'Future' is from 'dart:async'.
  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
-                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> async => let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> async => let final self::Divergent<core::int> #t2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
  - 'Future' is from 'dart:async'.
   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
-                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>>).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
+                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>> in #t2 is asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> ?{FutureOr<dynamic>} await #t2 : #t2).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
new file mode 100644
index 0000000..5ae2bec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.weak.transformed.expect
@@ -0,0 +1,126 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+//  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+//  - 'Future' is from 'dart:async'.
+//   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+//                                                          ^
+//
+// pkg/front_end/testcases/nnbd/issue42546.dart:14:75: Error: A value of type 'Future<Divergent<Divergent<Divergent<int>>>>' can't be assigned to a variable of type 'Future<Divergent<Divergent<int>>>'.
+//  - 'Future' is from 'dart:async'.
+//  - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+//   Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+//                                                                           ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class Divergent<T extends core::Object? = dynamic> extends core::Object implements asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>> {
+  synthetic constructor •() → self::Divergent<self::Divergent::T%>
+    : super core::Object::•()
+    ;
+  method noSuchMethod(core::Invocation invocation) → dynamic
+    return super.{core::Object::noSuchMethod}(invocation);
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError, {(core::Object) →? core::bool test = #C1}) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onError)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C4: test}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ whenComplete(() → FutureOr<void>action) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ timeout(core::Duration timeLimit, {generic-covariant-impl () →? FutureOr<self::Divergent<self::Divergent<self::Divergent::T%>>>onTimeout = #C1}) → asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(timeLimit)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C9: onTimeout}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::Divergent<self::Divergent<self::Divergent::T%>>) → FutureOr<self::Divergent::then::R%>onValue, {core::Function? onError = #C1}) → asy::Future<self::Divergent::then::R%>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 0, core::List::unmodifiable<core::Type*>(core::_GrowableList::_literal1<core::Type*>(self::Divergent::then::R%)), core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(onValue)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C11: onError}))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::Divergent::then::R%>;
+  no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ asStream() → asy::Stream<self::Divergent<self::Divergent<self::Divergent::T%>>>
+    return this.{self::Divergent::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<self::Divergent<self::Divergent<self::Divergent::T%>>>;
+}
+static method test() → 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;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        asy::Future<self::Divergent<self::Divergent<core::int>>> x = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:75: Error: A value of type 'Future<Divergent<Divergent<Divergent<int>>>>' can't be assigned to a variable of type 'Future<Divergent<Divergent<int>>>'.
+ - 'Future' is from 'dart:async'.
+ - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+                                                                          ^" in (() → asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> /* originally async */ {
+          final asy::_Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>> :async_future = new asy::_Future::•<self::Divergent<self::Divergent<self::Divergent<core::int>>>>();
+          core::bool* :is_sync = false;
+          FutureOr<self::Divergent<self::Divergent<self::Divergent<core::int>>>>? :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;
+          FutureOr<dynamic>:async_temporary_0;
+          function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+            try {
+              #L2:
+              {
+                final self::Divergent<core::int> #t2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue42546.dart:14:58: Error: A value of type 'Divergent<int>' can't be returned from an async function with return type 'Future<Divergent<Divergent<Divergent<int>>>>'.
+ - 'Divergent' is from 'pkg/front_end/testcases/nnbd/issue42546.dart'.
+ - 'Future' is from 'dart:async'.
+  Future<Divergent<Divergent<int>>> x = (() async => new Divergent<int>())();
+                                                         ^" in new self::Divergent::•<core::int>() as{TypeError,ForNonNullableByDefault} self::Divergent<self::Divergent<self::Divergent<core::int>>>;
+                if(#t2 is asy::Future<self::Divergent<self::Divergent<self::Divergent<core::int>>>>) {
+                  [yield] let dynamic #t4 = asy::_awaitHelper(#t2, :async_op_then, :async_op_error, :async_op) in null;
+                  :async_temporary_0 = _in::unsafeCast<self::Divergent<self::Divergent<core::int>>>(:result);
+                }
+                else {
+                  :async_temporary_0 = #t2;
+                }
+                :return_value = :async_temporary_0;
+                break #L2;
+              }
+              asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+              return;
+            }
+            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.call();
+          :is_sync = true;
+          return :async_future;
+        }).call() as{TypeError,ForNonNullableByDefault} asy::Future<self::Divergent<self::Divergent<core::int>>>;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+  #C2 = #catchError
+  #C3 = <core::Type*>[]
+  #C4 = #test
+  #C5 = #whenComplete
+  #C6 = <dynamic>[]
+  #C7 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C6}
+  #C8 = #timeout
+  #C9 = #onTimeout
+  #C10 = #then
+  #C11 = #onError
+  #C12 = #asStream
+}
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart b/pkg/front_end/testcases/nnbd/issue42743.dart
index 2ac0239..174904c 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 main() async {
-  bool b = true;
+  bool b = (() => true)();
   (_) {
     if (b) return 42;
   };
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.expect
index ca71c73..eaaabba4 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.expect
@@ -4,13 +4,13 @@
 import "dart:async" as asy;
 
 static method main() → dynamic async {
-  core::bool b = true;
+  core::bool b = (() → core::bool => true).call();
   (dynamic _) → core::int? {
     if(b)
       return 42;
   };
   (dynamic _) → asy::Future<core::int?> async {
     if(b)
-      return 42;
+      return let final core::int #t1 = 42 in #t1 is asy::Future<core::int?> ?{FutureOr<dynamic>} await #t1 : #t1;
   };
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
index e489262..1509333 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
@@ -15,7 +16,7 @@
     try {
       #L1:
       {
-        core::bool b = true;
+        core::bool b = (() → core::bool => true).call();
         (dynamic _) → core::int? {
           if(b)
             return 42;
@@ -28,12 +29,22 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L2:
               {
                 if(b) {
-                  :return_value = 42;
+                  final core::int #t1 = 42;
+                  if(#t1 is asy::Future<core::int?>) {
+                    [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t1;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L2;
                 }
               }
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.expect
index ca71c73..eaaabba4 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.expect
@@ -4,13 +4,13 @@
 import "dart:async" as asy;
 
 static method main() → dynamic async {
-  core::bool b = true;
+  core::bool b = (() → core::bool => true).call();
   (dynamic _) → core::int? {
     if(b)
       return 42;
   };
   (dynamic _) → asy::Future<core::int?> async {
     if(b)
-      return 42;
+      return let final core::int #t1 = 42 in #t1 is asy::Future<core::int?> ?{FutureOr<dynamic>} await #t1 : #t1;
   };
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
index e489262..1509333 100644
--- a/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42743.dart.weak.transformed.expect
@@ -2,6 +2,7 @@
 import self as self;
 import "dart:async" as asy;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method main() → dynamic /* originally async */ {
   final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
@@ -15,7 +16,7 @@
     try {
       #L1:
       {
-        core::bool b = true;
+        core::bool b = (() → core::bool => true).call();
         (dynamic _) → core::int? {
           if(b)
             return 42;
@@ -28,12 +29,22 @@
           (core::Object, core::StackTrace) → dynamic :async_op_error;
           core::int :await_jump_var = 0;
           dynamic :await_ctx_var;
+          dynamic :saved_try_context_var0;
+          FutureOr<dynamic>:async_temporary_0;
           function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
             try {
               #L2:
               {
                 if(b) {
-                  :return_value = 42;
+                  final core::int #t1 = 42;
+                  if(#t1 is asy::Future<core::int?>) {
+                    [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+                  }
+                  else {
+                    :async_temporary_0 = #t1;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L2;
                 }
               }
diff --git a/pkg/front_end/testcases/nnbd/issue42758.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42758.dart.strong.transformed.expect
index b50eeff..abe5174 100644
--- a/pkg/front_end/testcases/nnbd/issue42758.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42758.dart.strong.transformed.expect
@@ -83,25 +83,25 @@
     final core::List<Never> #t1 = core::List::of<Never>(n1);
   } =>#t1;
   core::List<Never> l2 = block {
-    final core::List<Never> #t2 = <Never>[];
+    final core::List<Never> #t2 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t3 = n1;
     if(!#t3.{core::Object::==}(null))
       #t2.{core::List::addAll}{Invariant}(#t3{core::Iterable<Never>});
   } =>#t2;
-  core::List<dynamic> l3 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:8:16: Error: Can't spread a value with static type 'Never?'.
+  core::List<dynamic> l3 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:8:16: Error: Can't spread a value with static type 'Never?'.
   var l3 = [...n2];
-               ^"];
+               ^");
   core::List<Never> l4 = block {
-    final core::List<Never> #t4 = <Never>[];
+    final core::List<Never> #t4 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t5 = n2;
     if(!#t5.{core::Object::==}(null))
       #t4.{core::List::addAll}{Invariant}(#t5{core::Iterable<Never>});
   } =>#t4;
-  core::List<dynamic> l5 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:10:16: Error: Can't spread a value with static type 'Null'.
+  core::List<dynamic> l5 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:10:16: Error: Can't spread a value with static type 'Null'.
   var l5 = [...n3];
-               ^"];
+               ^");
   core::List<Never> l6 = block {
-    final core::List<Never> #t6 = <Never>[];
+    final core::List<Never> #t6 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t7 = n3;
     if(!#t7.{core::Object::==}(null))
       #t6.{core::List::addAll}{Invariant}(#t7{core::Iterable<Never>});
@@ -204,25 +204,25 @@
     final core::List<Never> #t28 = core::List::of<Never>(n1);
   } =>#t28;
   core::List<Never> l2 = block {
-    final core::List<Never> #t29 = <Never>[];
+    final core::List<Never> #t29 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t30 = n1;
     if(!#t30.{core::Object::==}(null))
       #t29.{core::List::addAll}{Invariant}(#t30{core::Iterable<Never>});
   } =>#t29;
-  core::List<dynamic> l3 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:30:16: Error: Can't spread a value with static type 'N2'.
+  core::List<dynamic> l3 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:30:16: Error: Can't spread a value with static type 'N2'.
   var l3 = [...n2];
-               ^"];
+               ^");
   core::List<Never> l4 = block {
-    final core::List<Never> #t31 = <Never>[];
+    final core::List<Never> #t31 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t32 = n2;
     if(!#t32.{core::Object::==}(null))
       #t31.{core::List::addAll}{Invariant}(#t32{core::Iterable<Never>});
   } =>#t31;
-  core::List<dynamic> l5 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:32:16: Error: Can't spread a value with static type 'N3'.
+  core::List<dynamic> l5 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:32:16: Error: Can't spread a value with static type 'N3'.
   var l5 = [...n3];
-               ^"];
+               ^");
   core::List<Never> l6 = block {
-    final core::List<Never> #t33 = <Never>[];
+    final core::List<Never> #t33 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t34 = n3;
     if(!#t34.{core::Object::==}(null))
       #t33.{core::List::addAll}{Invariant}(#t34{core::Iterable<Never>});
diff --git a/pkg/front_end/testcases/nnbd/issue42758.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42758.dart.weak.transformed.expect
index ffce698..a2b4bb2 100644
--- a/pkg/front_end/testcases/nnbd/issue42758.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42758.dart.weak.transformed.expect
@@ -84,25 +84,25 @@
     final core::List<Never> #t1 = core::List::of<Never>(let final Never #t2 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
   } =>#t1;
   core::List<Never> l2 = block {
-    final core::List<Never> #t3 = <Never>[];
+    final core::List<Never> #t3 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t4 = let final Never #t5 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     if(!#t4.{core::Object::==}(null))
       #t3.{core::List::addAll}{Invariant}(#t4{core::Iterable<Never>});
   } =>#t3;
-  core::List<dynamic> l3 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:8:16: Error: Can't spread a value with static type 'Never?'.
+  core::List<dynamic> l3 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:8:16: Error: Can't spread a value with static type 'Never?'.
   var l3 = [...n2];
-               ^"];
+               ^");
   core::List<Never> l4 = block {
-    final core::List<Never> #t6 = <Never>[];
+    final core::List<Never> #t6 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t7 = n2;
     if(!#t7.{core::Object::==}(null))
       #t6.{core::List::addAll}{Invariant}(#t7{core::Iterable<Never>});
   } =>#t6;
-  core::List<dynamic> l5 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:10:16: Error: Can't spread a value with static type 'Null'.
+  core::List<dynamic> l5 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:10:16: Error: Can't spread a value with static type 'Null'.
   var l5 = [...n3];
-               ^"];
+               ^");
   core::List<Never> l6 = block {
-    final core::List<Never> #t8 = <Never>[];
+    final core::List<Never> #t8 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t9 = n3;
     if(!#t9.{core::Object::==}(null))
       #t8.{core::List::addAll}{Invariant}(#t9{core::Iterable<Never>});
@@ -205,25 +205,25 @@
     final core::List<Never> #t52 = core::List::of<Never>(let final self::test2::N1 #t53 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
   } =>#t52;
   core::List<Never> l2 = block {
-    final core::List<Never> #t54 = <Never>[];
+    final core::List<Never> #t54 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t55 = let final self::test2::N1 #t56 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     if(!#t55.{core::Object::==}(null))
       #t54.{core::List::addAll}{Invariant}(#t55{core::Iterable<Never>});
   } =>#t54;
-  core::List<dynamic> l3 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:30:16: Error: Can't spread a value with static type 'N2'.
+  core::List<dynamic> l3 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:30:16: Error: Can't spread a value with static type 'N2'.
   var l3 = [...n2];
-               ^"];
+               ^");
   core::List<Never> l4 = block {
-    final core::List<Never> #t57 = <Never>[];
+    final core::List<Never> #t57 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t58 = n2;
     if(!#t58.{core::Object::==}(null))
       #t57.{core::List::addAll}{Invariant}(#t58{core::Iterable<Never>});
   } =>#t57;
-  core::List<dynamic> l5 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:32:16: Error: Can't spread a value with static type 'N3'.
+  core::List<dynamic> l5 = core::_GrowableList::_literal1<dynamic>(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:32:16: Error: Can't spread a value with static type 'N3'.
   var l5 = [...n3];
-               ^"];
+               ^");
   core::List<Never> l6 = block {
-    final core::List<Never> #t59 = <Never>[];
+    final core::List<Never> #t59 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t60 = n3;
     if(!#t60.{core::Object::==}(null))
       #t59.{core::List::addAll}{Invariant}(#t60{core::Iterable<Never>});
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.outline.expect
index 1b6e3c7..08fff2c 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_1.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.outline.expect
@@ -4,7 +4,7 @@
 
 class C extends core::Object {
   field Never n;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(Never n) → self::C
     let dynamic #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.expect
index 579f1e9..ed2262c 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.expect
@@ -11,7 +11,7 @@
 
 class C extends core::Object {
   field Never n = null;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(Never n) → self::C
     let dynamic #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.transformed.expect
index 9bf278b..9ff052a 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
 
 class C extends core::Object {
   field Never n = null;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(Never n) → self::C
     let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.expect
index 579f1e9..ed2262c 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.expect
@@ -11,7 +11,7 @@
 
 class C extends core::Object {
   field Never n = null;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(Never n) → self::C
     let dynamic #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.transformed.expect
index 9bf278b..9ff052a 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
 
 class C extends core::Object {
   field Never n = null;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(Never n) → self::C
     let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.outline.expect
index b211f2f..afe3abd 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_2.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.outline.expect
@@ -4,7 +4,7 @@
 
 class C extends core::Object {
   final field dynamic n;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(dynamic n) → self::C
     let dynamic #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.expect
index 1a0f908..9f4202d 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.expect
@@ -12,7 +12,7 @@
 
 class C extends core::Object {
   final field dynamic n = null;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(dynamic n) → self::C
     let dynamic #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.transformed.expect
index ba70d21..bb9f753 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
 
 class C extends core::Object {
   final field dynamic n = null;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(dynamic n) → self::C
     let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.expect
index 1a0f908..9f4202d 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.expect
@@ -12,7 +12,7 @@
 
 class C extends core::Object {
   final field dynamic n = null;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(dynamic n) → self::C
     let dynamic #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.transformed.expect
index ba70d21..bb9f753 100644
--- a/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
 
 class C extends core::Object {
   final field dynamic n = null;
-  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::•]/*isLegacy*/;
   static factory •(dynamic n) → self::C
     let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline.expect
index 003e9d3..dab2d82 100644
--- a/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline.expect
@@ -1,41 +1,39 @@
 class A {
   num fieldNonNullableOfA;
-  late num ;
-  fieldLateNonNullableOfA;
+  late num fieldLateNonNullableOfA;
   final dynamic fieldFinalDynamicOfA;
-  late ;
-  final dynamic fieldLateFinalDynamicOfA;
+  late final dynamic fieldLateFinalDynamicOfA;
 }
+
 abstract class AbstractA {
   external num fieldExternalNonNullableOfAbstractA;
   abstract num fieldAbstractNonNullableOfAbstractA;
   external final dynamic fieldExternalFinalDynamicOfAbstractA;
   abstract final dynamic fieldAbstractFinalDynamicOfAbstractA;
 }
+
 class B {
   num fieldNonNullableOfB;
-  late num ;
-  fieldLateNonNullableOfB;
+  late num fieldLateNonNullableOfB;
   final dynamic fieldFinalDynamicOfB;
-  late ;
-  final dynamic fieldLateFinalDynamicOfB;
+  late final dynamic fieldLateFinalDynamicOfB;
   factory B() => throw 42;
 }
+
 abstract class AbstractB {
   external num fieldExternalNonNullableOfAbstractB;
   abstract num fieldAbstractNonNullableOfAbstractB;
   external final dynamic fieldExternalFinalDynamicOfAbstractB;
   abstract final dynamic fieldAbstractFinalDynamicOfAbstractB;
 }
+
 mixin M {
   num fieldNonNullableOfM;
-  late num ;
-  fieldLateNonNullableOfM;
+  late num fieldLateNonNullableOfM;
   external num fieldExternalNonNullableOfM;
   abstract num fieldAbstractNonNullableOfM;
   final dynamic fieldFinalDynamicOfM;
-  late ;
-  final dynamic fieldLateFinalDynamicOfM;
+  late final dynamic fieldLateFinalDynamicOfM;
   external final dynamic fieldExternalFinalDynamicOfM;
   abstract final dynamic fieldAbstractFinalDynamicOfM;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..284430e8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline_modelled.expect
@@ -0,0 +1,54 @@
+abstract class AbstractA {
+  abstract final dynamic fieldAbstractFinalDynamicOfAbstractA;
+  abstract num fieldAbstractNonNullableOfAbstractA;
+  external final dynamic fieldExternalFinalDynamicOfAbstractA;
+  external num fieldExternalNonNullableOfAbstractA;
+}
+abstract class AbstractB {
+  abstract final dynamic fieldAbstractFinalDynamicOfAbstractB;
+  abstract num fieldAbstractNonNullableOfAbstractB;
+  external final dynamic fieldExternalFinalDynamicOfAbstractB;
+  external num fieldExternalNonNullableOfAbstractB;
+}
+class A {
+  num fieldNonNullableOfA;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final dynamic fieldFinalDynamicOfA;
+  num fieldLateNonNullableOfA;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final dynamic fieldLateFinalDynamicOfA;
+}
+class B {
+  num fieldNonNullableOfB;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final dynamic fieldFinalDynamicOfB;
+  num fieldLateNonNullableOfB;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  factory B() => throw 42;
+  final dynamic fieldLateFinalDynamicOfB;
+}
+main() {}
+mixin M {
+  num fieldNonNullableOfM;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  abstract num fieldAbstractNonNullableOfM;
+  external num fieldExternalNonNullableOfM;
+  final dynamic fieldFinalDynamicOfM;
+  num fieldLateNonNullableOfM;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  abstract final dynamic fieldAbstractFinalDynamicOfM;
+  external final dynamic fieldExternalFinalDynamicOfM;
+  final dynamic fieldLateFinalDynamicOfM;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.outline.expect
index 6cde1626..02689e0 100644
--- a/pkg/front_end/testcases/nnbd/issue43211.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.outline.expect
@@ -121,7 +121,7 @@
     ;
 }
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor internal(dynamic _) → self::C
     ;
   static factory redirect(self::A<self::A<Null>>? a) → self::C
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.strong.expect
index 2119a28..39c2e9c 100644
--- a/pkg/front_end/testcases/nnbd/issue43211.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.strong.expect
@@ -221,7 +221,7 @@
   }
 }
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor internal(dynamic _) → self::C
     : super core::Object::•() {
     self::A<self::A<Null>>? a;
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.strong.transformed.expect
index 1eb8c28..f850b72 100644
--- a/pkg/front_end/testcases/nnbd/issue43211.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.strong.transformed.expect
@@ -221,7 +221,7 @@
   }
 }
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor internal(dynamic _) → self::C
     : super core::Object::•() {
     self::A<self::A<Null>>? a;
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect
index f38556f..f3d6cdd 100644
--- a/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect
@@ -1,17 +1,24 @@
 class A<X extends A<X>?> {}
+
 class D<X extends num> {}
-extension Extension1<X extends A<X>?> (){}
-on A<X> (){}
-extension ext2<X extends A<Null>?> (){}
-on A<X> (){}
+
+extension Extension1<X extends A<X>?> on A<X> {
+  void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {}
+  void method2<Y extends String>(D<Y> a, D<String>? b) {}
+}
+
+extension ext2<X extends A<Null>?> on A<X> {}
+
 class B<X extends A<Null>?> implements A<X> {
   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {}
   void method2<Y extends String>(D<Y> a, D<String>? b) {}
 }
+
 class C {
   factory C.redirect(A<A<Null>>? a) = C.internal;
   factory C.fact(A<A<Null>>? a) {}
   C.internal(_) {}
 }
+
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..36a6a66
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class A<X extends A<X>?> {}
+
+class B<X extends A<Null>?> implements A<X> {
+  void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {}
+  void method2<Y extends String>(D<Y> a, D<String>? b) {}
+}
+
+class C {
+  C.internal(_) {}
+  factory C.fact(A<A<Null>>? a) {}
+  factory C.redirect(A<A<Null>>? a) = C.internal;
+}
+
+class D<X extends num> {}
+
+extension Extension1<X extends A<X>?> on A<X> {
+  void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {}
+  void method2<Y extends String>(D<Y> a, D<String>? b) {}
+}
+
+extension ext2<X extends A<Null>?> on A<X> {}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.weak.expect
index 2119a28..39c2e9c 100644
--- a/pkg/front_end/testcases/nnbd/issue43211.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.weak.expect
@@ -221,7 +221,7 @@
   }
 }
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor internal(dynamic _) → self::C
     : super core::Object::•() {
     self::A<self::A<Null>>? a;
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.weak.transformed.expect
index 1eb8c28..f850b72 100644
--- a/pkg/front_end/testcases/nnbd/issue43211.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.weak.transformed.expect
@@ -221,7 +221,7 @@
   }
 }
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor internal(dynamic _) → self::C
     : super core::Object::•() {
     self::A<self::A<Null>>? a;
diff --git a/pkg/front_end/testcases/nnbd/issue43256.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43256.dart.strong.transformed.expect
index 4fddc1b..afc253c 100644
--- a/pkg/front_end/testcases/nnbd/issue43256.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43256.dart.strong.transformed.expect
@@ -52,9 +52,9 @@
 
 static field core::int i = 1;
 static field core::Map<core::int, core::String>? nullableMap = <core::int, core::String>{1: "Let", 2: "it", 3: "be"};
-static field core::List<core::int>? nullableList = <core::int>[1, 2, 3];
+static field core::List<core::int>? nullableList = core::_GrowableList::_literal3<core::int>(1, 2, 3);
 static field dynamic dynamicMap = <core::int, core::String>{1: "Let", 2: "it", 3: "be"};
-static field dynamic dynamicList = <core::int>[1, 2, 3];
+static field dynamic dynamicList = core::_GrowableList::_literal3<core::int>(1, 2, 3);
 static field core::Map<dynamic, dynamic> map1 = block {
   final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
   if(self::i.{core::num::>}(0))
@@ -89,7 +89,7 @@
     #t4.{core::Set::addAll}{Invariant}(self::nullableList!);
 } =>#t4;
 static field core::List<dynamic> list1 = block {
-  final core::List<dynamic> #t5 = <dynamic>[];
+  final core::List<dynamic> #t5 = core::_GrowableList::•<dynamic>(0);
   if(self::i.{core::num::>}(0))
     #t5.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/issue43256.dart:29:17: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
   if (i > 0) ...nullableList, // error
@@ -142,7 +142,7 @@
       #t9.{core::Set::addAll}{Invariant}(z);
   } =>#t9;
   core::List<dynamic> list2 = block {
-    final core::List<dynamic> #t10 = <dynamic>[];
+    final core::List<dynamic> #t10 = core::_GrowableList::•<dynamic>(0);
     if(self::i.{core::num::>}(0))
       #t10.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
     if (i > 0) ...x, // error
diff --git a/pkg/front_end/testcases/nnbd/issue43256.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43256.dart.weak.transformed.expect
index 4fddc1b..afc253c 100644
--- a/pkg/front_end/testcases/nnbd/issue43256.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43256.dart.weak.transformed.expect
@@ -52,9 +52,9 @@
 
 static field core::int i = 1;
 static field core::Map<core::int, core::String>? nullableMap = <core::int, core::String>{1: "Let", 2: "it", 3: "be"};
-static field core::List<core::int>? nullableList = <core::int>[1, 2, 3];
+static field core::List<core::int>? nullableList = core::_GrowableList::_literal3<core::int>(1, 2, 3);
 static field dynamic dynamicMap = <core::int, core::String>{1: "Let", 2: "it", 3: "be"};
-static field dynamic dynamicList = <core::int>[1, 2, 3];
+static field dynamic dynamicList = core::_GrowableList::_literal3<core::int>(1, 2, 3);
 static field core::Map<dynamic, dynamic> map1 = block {
   final core::Map<dynamic, dynamic> #t1 = <dynamic, dynamic>{};
   if(self::i.{core::num::>}(0))
@@ -89,7 +89,7 @@
     #t4.{core::Set::addAll}{Invariant}(self::nullableList!);
 } =>#t4;
 static field core::List<dynamic> list1 = block {
-  final core::List<dynamic> #t5 = <dynamic>[];
+  final core::List<dynamic> #t5 = core::_GrowableList::•<dynamic>(0);
   if(self::i.{core::num::>}(0))
     #t5.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/issue43256.dart:29:17: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
   if (i > 0) ...nullableList, // error
@@ -142,7 +142,7 @@
       #t9.{core::Set::addAll}{Invariant}(z);
   } =>#t9;
   core::List<dynamic> list2 = block {
-    final core::List<dynamic> #t10 = <dynamic>[];
+    final core::List<dynamic> #t10 = core::_GrowableList::•<dynamic>(0);
     if(self::i.{core::num::>}(0))
       #t10.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
     if (i > 0) ...x, // error
diff --git a/pkg/front_end/testcases/nnbd/issue43276.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43276.dart.outline.expect
index 83d2e51..ac7b8e7 100644
--- a/pkg/front_end/testcases/nnbd/issue43276.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43276.dart.outline.expect
@@ -16,7 +16,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor gen({core::int i}) → self::C
     ;
   static factory fact({core::int i}) → self::C
diff --git a/pkg/front_end/testcases/nnbd/issue43276.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43276.dart.strong.expect
index bcb7771..d62d171 100644
--- a/pkg/front_end/testcases/nnbd/issue43276.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue43276.dart.strong.expect
@@ -16,7 +16,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor gen({core::int i = #C1}) → self::C
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue43276.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43276.dart.strong.transformed.expect
index 744265d..18f6cd7 100644
--- a/pkg/front_end/testcases/nnbd/issue43276.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43276.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor gen({core::int i = #C1}) → self::C
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue43276.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43276.dart.weak.expect
index bcb7771..d62d171 100644
--- a/pkg/front_end/testcases/nnbd/issue43276.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue43276.dart.weak.expect
@@ -16,7 +16,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor gen({core::int i = #C1}) → self::C
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue43276.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43276.dart.weak.transformed.expect
index 744265d..18f6cd7 100644
--- a/pkg/front_end/testcases/nnbd/issue43276.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43276.dart.weak.transformed.expect
@@ -16,7 +16,7 @@
 import "dart:core" as core;
 
 class C extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isLegacy*/;
   constructor gen({core::int i = #C1}) → self::C
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect
index 989f770..c4cdc58 100644
--- a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect
@@ -3,9 +3,16 @@
   A bar;
   A(this.bar);
 }
+
 test<T extends A?>(A? a, T t, dynamic d, int x) {}
+
 class B {}
-extension Extension ;
-on B (){}
+
+extension Extension on B {
+  int? get fooExtension => null;
+  void set fooExtension(int? value) {}
+  B get barExtension => new B();
+}
+
 testExtension<T extends B?>(B? b, T t, int x) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect
index ffcd116..b16d6f7 100644
--- a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect
@@ -1,9 +1,17 @@
-bar<T extends A?>(A? a, T t, dynamic d, int x) {}
-
 class A {
   A(this.bar);
   A bar;
   int? foo;
 }
 
+class B {}
+
+extension Extension on B {
+  B get barExtension => new B();
+  int? get fooExtension => null;
+  void set fooExtension(int? value) {}
+}
+
 main() {}
+test<T extends A?>(A? a, T t, dynamic d, int x) {}
+testExtension<T extends B?>(B? b, T t, int x) {}
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline.expect
index d4f44a6..579892c 100644
--- a/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline.expect
@@ -1,27 +1,25 @@
 class A {
-  late ;
-  final int foo = 42;
+  late final int foo = 42;
   const A();
 }
+
 class B {
-  late ;
-  final int foo = 42;
-  late ;
-  final String bar = "foobar";
+  late final int foo = 42;
+  late final String bar = "foobar";
   const B();
 }
+
 class C {
-  late ;
-  final int foo = 42;
+  late final int foo = 42;
   const C();
   const C.another();
 }
+
 class D {
-  late ;
-  final int foo = 42;
-  late ;
-  final String bar = "foobar";
+  late final int foo = 42;
+  late final String bar = "foobar";
   const D();
   const D.another();
 }
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8e86312
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline_modelled.expect
@@ -0,0 +1,39 @@
+class A {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  const A();
+  final int foo = 42;
+}
+class B {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int foo = 42;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  const B();
+  final String bar = "foobar";
+}
+class C {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  const C();
+  const C.another();
+  final int foo = 42;
+}
+class D {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  final int foo = 42;
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  const D();
+  const D.another();
+  final String bar = "foobar";
+}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline.expect
index eb34b94..2341156 100644
--- a/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline.expect
@@ -1,5 +1,7 @@
-extension E<T> (){}
-on T (){}
+extension E<T> on T {
+  T Function(T) get f => (T t) => t;
+}
+
 method1<S>(S s) {}
 method2<S extends dynamic>(S s) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c47013a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+extension E<T> on T {
+  T Function(T) get f => (T t) => t;
+}
+
+main() {}
+method1<S>(S s) {}
+method2<S extends dynamic>(S s) {}
+throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/issue43689.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43689.dart.outline.expect
index 35b1c6f..e84a44f 100644
--- a/pkg/front_end/testcases/nnbd/issue43689.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43689.dart.outline.expect
@@ -12,7 +12,7 @@
 import self as self;
 import "dart:core" as core;
 
-late static final field core::int y;
+late static final [setter] field core::int y;
 static method test() → dynamic
   ;
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/nnbd/issue43689.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43689.dart.strong.expect
index 64c8656..bee2422 100644
--- a/pkg/front_end/testcases/nnbd/issue43689.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue43689.dart.strong.expect
@@ -26,7 +26,7 @@
 import self as self;
 import "dart:core" as core;
 
-late static final field core::int y;
+late static final [setter] field core::int y;
 static method test() → dynamic {
   late final core::int x;
   late final core::int? x = invalid-expression "pkg/front_end/testcases/nnbd/issue43689.dart:10:19: Error: 'x' is already declared in this scope.
diff --git a/pkg/front_end/testcases/nnbd/issue43689.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43689.dart.strong.transformed.expect
index 4d8f37a..6fcf485 100644
--- a/pkg/front_end/testcases/nnbd/issue43689.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43689.dart.strong.transformed.expect
@@ -26,7 +26,7 @@
 import self as self;
 import "dart:core" as core;
 
-late static final field core::int y;
+late static final [setter] field core::int y;
 static method test() → dynamic {
   late final core::int x;
   function #x#initializer() → core::int?
diff --git a/pkg/front_end/testcases/nnbd/issue43689.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43689.dart.textual_outline.expect
index efaf61b..d26f6fb 100644
--- a/pkg/front_end/testcases/nnbd/issue43689.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43689.dart.textual_outline.expect
@@ -1,6 +1,4 @@
-late ;
-final int y;
-late ;
-final int? y;
+late final int y;
+late final int? y;
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43689.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43689.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..400ab13
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43689.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+final int y;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+final int? y;
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43689.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43689.dart.weak.expect
index 64c8656..bee2422 100644
--- a/pkg/front_end/testcases/nnbd/issue43689.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue43689.dart.weak.expect
@@ -26,7 +26,7 @@
 import self as self;
 import "dart:core" as core;
 
-late static final field core::int y;
+late static final [setter] field core::int y;
 static method test() → dynamic {
   late final core::int x;
   late final core::int? x = invalid-expression "pkg/front_end/testcases/nnbd/issue43689.dart:10:19: Error: 'x' is already declared in this scope.
diff --git a/pkg/front_end/testcases/nnbd/issue43689.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43689.dart.weak.transformed.expect
index 4d8f37a..6fcf485 100644
--- a/pkg/front_end/testcases/nnbd/issue43689.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43689.dart.weak.transformed.expect
@@ -26,7 +26,7 @@
 import self as self;
 import "dart:core" as core;
 
-late static final field core::int y;
+late static final [setter] field core::int y;
 static method test() → dynamic {
   late final core::int x;
   function #x#initializer() → core::int?
diff --git a/pkg/front_end/testcases/nnbd/issue43918.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43918.dart.outline.expect
index 9bff7b0..1b9a3e0 100644
--- a/pkg/front_end/testcases/nnbd/issue43918.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43918.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class A<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(self::A::•::T% value) → self::A<self::A::•::T%>
     let dynamic #redirecting_factory = self::_A::• in let self::A::•::T% #typeArg0 = null in invalid-expression;
 }
@@ -12,7 +12,7 @@
     ;
 }
 abstract class B<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(core::int value) → self::B<self::B::•::T%>
     let dynamic #redirecting_factory = self::_B::• in let self::B::•::T% #typeArg0 = null in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue43918.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43918.dart.strong.expect
index 33ae9c2..152826c 100644
--- a/pkg/front_end/testcases/nnbd/issue43918.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue43918.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class A<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(self::A::•::T% value) → self::A<self::A::•::T%>
     let dynamic #redirecting_factory = self::_A::• in let self::A::•::T% #typeArg0 = null in invalid-expression;
 }
@@ -13,7 +13,7 @@
     ;
 }
 abstract class B<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(core::int value) → self::B<self::B::•::T%>
     let dynamic #redirecting_factory = self::_B::• in let self::B::•::T% #typeArg0 = null in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue43918.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43918.dart.strong.transformed.expect
index 1669379..c6913c5 100644
--- a/pkg/front_end/testcases/nnbd/issue43918.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43918.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class A<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(self::A::•::T% value) → self::A<self::A::•::T%>
     let<BottomType> #redirecting_factory = self::_A::• in let self::A::•::T% #typeArg0 = null in invalid-expression;
 }
@@ -13,7 +13,7 @@
     ;
 }
 abstract class B<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(core::int value) → self::B<self::B::•::T%>
     let<BottomType> #redirecting_factory = self::_B::• in let self::B::•::T% #typeArg0 = null in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue43918.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43918.dart.weak.expect
index 33ae9c2..152826c 100644
--- a/pkg/front_end/testcases/nnbd/issue43918.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue43918.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class A<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(self::A::•::T% value) → self::A<self::A::•::T%>
     let dynamic #redirecting_factory = self::_A::• in let self::A::•::T% #typeArg0 = null in invalid-expression;
 }
@@ -13,7 +13,7 @@
     ;
 }
 abstract class B<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(core::int value) → self::B<self::B::•::T%>
     let dynamic #redirecting_factory = self::_B::• in let self::B::•::T% #typeArg0 = null in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue43918.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43918.dart.weak.transformed.expect
index 1669379..c6913c5 100644
--- a/pkg/front_end/testcases/nnbd/issue43918.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43918.dart.weak.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 abstract class A<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::A::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(self::A::•::T% value) → self::A<self::A::•::T%>
     let<BottomType> #redirecting_factory = self::_A::• in let self::A::•::T% #typeArg0 = null in invalid-expression;
 }
@@ -13,7 +13,7 @@
     ;
 }
 abstract class B<T extends core::Object? = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::B::•]/*isLegacy*/;
   static factory •<T extends core::Object? = dynamic>(core::int value) → self::B<self::B::•::T%>
     let<BottomType> #redirecting_factory = self::_B::• in let self::B::•::T% #typeArg0 = null in invalid-expression;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue44362.dart b/pkg/front_end/testcases/nnbd/issue44362.dart
new file mode 100644
index 0000000..5d00edd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44362.dart
@@ -0,0 +1,13 @@
+// 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.
+
+foo<X>(X? x) {
+  if (x is int) {
+    bar(x);
+  }
+}
+
+bar<Y>(dynamic y) {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue44362.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue44362.dart.outline.expect
new file mode 100644
index 0000000..81e9d0f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44362.dart.outline.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method foo<X extends core::Object? = dynamic>(self::foo::X? x) → dynamic
+  ;
+static method bar<Y extends core::Object? = dynamic>(dynamic y) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue44362.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue44362.dart.strong.expect
new file mode 100644
index 0000000..3e32ea9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44362.dart.strong.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method foo<X extends core::Object? = dynamic>(self::foo::X? x) → dynamic {
+  if(x is{ForNonNullableByDefault} core::int) {
+    self::bar<dynamic>(x{self::foo::X? & core::int /* '?' & '!' = '!' */});
+  }
+}
+static method bar<Y extends core::Object? = dynamic>(dynamic y) → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue44362.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue44362.dart.strong.transformed.expect
new file mode 100644
index 0000000..3e32ea9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44362.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method foo<X extends core::Object? = dynamic>(self::foo::X? x) → dynamic {
+  if(x is{ForNonNullableByDefault} core::int) {
+    self::bar<dynamic>(x{self::foo::X? & core::int /* '?' & '!' = '!' */});
+  }
+}
+static method bar<Y extends core::Object? = dynamic>(dynamic y) → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue44362.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue44362.dart.textual_outline.expect
new file mode 100644
index 0000000..395f9d1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44362.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+foo<X>(X? x) {}
+bar<Y>(dynamic y) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue44362.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue44362.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..86912e9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44362.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+bar<Y>(dynamic y) {}
+foo<X>(X? x) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue44362.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue44362.dart.weak.expect
new file mode 100644
index 0000000..3e32ea9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44362.dart.weak.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method foo<X extends core::Object? = dynamic>(self::foo::X? x) → dynamic {
+  if(x is{ForNonNullableByDefault} core::int) {
+    self::bar<dynamic>(x{self::foo::X? & core::int /* '?' & '!' = '!' */});
+  }
+}
+static method bar<Y extends core::Object? = dynamic>(dynamic y) → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue44362.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue44362.dart.weak.transformed.expect
new file mode 100644
index 0000000..3e32ea9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44362.dart.weak.transformed.expect
@@ -0,0 +1,11 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method foo<X extends core::Object? = dynamic>(self::foo::X? x) → dynamic {
+  if(x is{ForNonNullableByDefault} core::int) {
+    self::bar<dynamic>(x{self::foo::X? & core::int /* '?' & '!' = '!' */});
+  }
+}
+static method bar<Y extends core::Object? = dynamic>(dynamic y) → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart b/pkg/front_end/testcases/nnbd/issue44595.dart
new file mode 100644
index 0000000..1fa204e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44595.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.
+
+import "dart:async";
+
+T id<T>(T value) => value;
+
+main() async {
+  FutureOr<int> x = 1 + id(1);
+
+  FutureOr<int> y = 1 + id(1)
+    ..checkStaticType<Exactly<int>>();
+  FutureOr<int> z = 1 + contextType(1)
+    ..checkStaticType<Exactly<int>>();
+}
+
+extension<T> on T {
+  void checkStaticType<R extends Exactly<T>>() {}
+}
+
+typedef Exactly<T> = T Function(T);
+T contextType<T>(Object? o) => o as T;
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.outline.expect
new file mode 100644
index 0000000..59b9de9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.outline.expect
@@ -0,0 +1,21 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
+extension _extension#0<T extends core::Object? = dynamic> on T% {
+  method checkStaticType = self::_extension#0|checkStaticType;
+  tearoff checkStaticType = self::_extension#0|get#checkStaticType;
+}
+static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
+  ;
+static method main() → dynamic async 
+  ;
+static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void
+  ;
+static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
+  return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
+static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.expect
new file mode 100644
index 0000000..2c6d5bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
+extension _extension#0<T extends core::Object? = dynamic> on T% {
+  method checkStaticType = self::_extension#0|checkStaticType;
+  tearoff checkStaticType = self::_extension#0|get#checkStaticType;
+}
+static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
+  return value;
+static method main() → dynamic async {
+  FutureOr<core::int>x = 1.{core::num::+}(self::id<core::int>(1));
+  FutureOr<core::int>y = let final core::int #t1 = 1.{core::num::+}(self::id<core::int>(1)) in block {
+    self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t1);
+  } =>#t1;
+  FutureOr<core::int>z = let final core::int #t2 = 1.{core::num::+}(self::contextType<core::int>(1)) in block {
+    self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
+  } =>#t2;
+}
+static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void {}
+static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
+  return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
+static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
+  return o as{ForNonNullableByDefault} self::contextType::T%;
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
new file mode 100644
index 0000000..5861f8c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.strong.transformed.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
+extension _extension#0<T extends core::Object? = dynamic> on T% {
+  method checkStaticType = self::_extension#0|checkStaticType;
+  tearoff checkStaticType = self::_extension#0|get#checkStaticType;
+}
+static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
+  return value;
+static method main() → 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;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        FutureOr<core::int>x = 1.{core::num::+}(self::id<core::int>(1));
+        FutureOr<core::int>y = let final core::int #t1 = 1.{core::num::+}(self::id<core::int>(1)) in block {
+          self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t1);
+        } =>#t1;
+        FutureOr<core::int>z = let final core::int #t2 = 1.{core::num::+}(self::contextType<core::int>(1)) in block {
+          self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
+        } =>#t2;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void {}
+static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
+  return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
+static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
+  return o as{ForNonNullableByDefault} self::contextType::T%;
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.textual_outline.expect
new file mode 100644
index 0000000..219eb6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+import "dart:async";
+
+T id<T>(T value) => value;
+main() async {}
+
+extension<T> on T {
+  void checkStaticType<R extends Exactly<T>>() {}
+}
+
+typedef Exactly<T> = T Function(T);
+T contextType<T>(Object? o) => o as T;
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..70d1eb0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+import "dart:async";
+
+T contextType<T>(Object? o) => o as T;
+T id<T>(T value) => value;
+
+extension<T> on T {
+  void checkStaticType<R extends Exactly<T>>() {}
+}
+
+main() async {}
+typedef Exactly<T> = T Function(T);
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.expect
new file mode 100644
index 0000000..2c6d5bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
+extension _extension#0<T extends core::Object? = dynamic> on T% {
+  method checkStaticType = self::_extension#0|checkStaticType;
+  tearoff checkStaticType = self::_extension#0|get#checkStaticType;
+}
+static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
+  return value;
+static method main() → dynamic async {
+  FutureOr<core::int>x = 1.{core::num::+}(self::id<core::int>(1));
+  FutureOr<core::int>y = let final core::int #t1 = 1.{core::num::+}(self::id<core::int>(1)) in block {
+    self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t1);
+  } =>#t1;
+  FutureOr<core::int>z = let final core::int #t2 = 1.{core::num::+}(self::contextType<core::int>(1)) in block {
+    self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
+  } =>#t2;
+}
+static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void {}
+static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
+  return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
+static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
+  return o as{ForNonNullableByDefault} self::contextType::T%;
diff --git a/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
new file mode 100644
index 0000000..5861f8c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue44595.dart.weak.transformed.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+typedef Exactly<invariant T extends dynamic = dynamic> = (T%) → T%;
+extension _extension#0<T extends core::Object? = dynamic> on T% {
+  method checkStaticType = self::_extension#0|checkStaticType;
+  tearoff checkStaticType = self::_extension#0|get#checkStaticType;
+}
+static method id<T extends core::Object? = dynamic>(self::id::T% value) → self::id::T%
+  return value;
+static method main() → 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;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        FutureOr<core::int>x = 1.{core::num::+}(self::id<core::int>(1));
+        FutureOr<core::int>y = let final core::int #t1 = 1.{core::num::+}(self::id<core::int>(1)) in block {
+          self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t1);
+        } =>#t1;
+        FutureOr<core::int>z = let final core::int #t2 = 1.{core::num::+}(self::contextType<core::int>(1)) in block {
+          self::_extension#0|checkStaticType<core::int, (core::int) → core::int>(#t2);
+        } =>#t2;
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method _extension#0|checkStaticType<T extends core::Object? = dynamic, R extends (self::_extension#0|checkStaticType::T%) → self::_extension#0|checkStaticType::T% = (dynamic) → dynamic>(lowered final self::_extension#0|checkStaticType::T% #this) → void {}
+static method _extension#0|get#checkStaticType<T extends core::Object? = dynamic>(lowered final self::_extension#0|get#checkStaticType::T% #this) → <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void
+  return <R extends (self::_extension#0|get#checkStaticType::T%) → self::_extension#0|get#checkStaticType::T% = (dynamic) → dynamic>() → void => self::_extension#0|checkStaticType<self::_extension#0|get#checkStaticType::T%, R>(#this);
+static method contextType<T extends core::Object? = dynamic>(core::Object? o) → self::contextType::T%
+  return o as{ForNonNullableByDefault} self::contextType::T%;
diff --git a/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline.expect
index 2f9718a..5f989b2 100644
--- a/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline.expect
@@ -1,6 +1,9 @@
-extension Test<T> (){}
-on T (){}
+extension Test<T> on T {
+  T Function(T) get test => (a) => this;
+}
+
 class Foo<S extends num> {
   void test1(S x) {}
 }
+
 void main() {}
diff --git a/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9aaf1c7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Foo<S extends num> {
+  void test1(S x) {}
+}
+
+extension Test<T> on T {
+  T Function(T) get test => (a) => this;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/late.dart.outline.expect b/pkg/front_end/testcases/nnbd/late.dart.outline.expect
index 414a031..4800daf 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.outline.expect
@@ -10,8 +10,8 @@
   late field self::Class lateInstanceFieldThis;
   late final field self::Class lateFinalInstanceFieldThis;
   late static field core::int lateStaticField;
-  late static final field core::int lateFinalStaticField1;
-  late static final field core::int lateFinalStaticField2;
+  late static final [setter] field core::int lateFinalStaticField1;
+  late static final [setter] field core::int lateFinalStaticField2;
   late static final field core::int lateFinalStaticFieldWithInit;
   synthetic constructor •() → self::Class
     ;
@@ -21,7 +21,7 @@
     ;
 }
 late static field core::int lateTopLevelField;
-late static final field core::int lateFinalTopLevelField;
+late static final [setter] field core::int lateFinalTopLevelField;
 late static final field core::int lateFinalTopLevelFieldWithInit;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/late.dart.strong.expect b/pkg/front_end/testcases/nnbd/late.dart.strong.expect
index 4c32d9b..eaf8c2c 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.strong.expect
@@ -41,8 +41,8 @@
   late field self::Class lateInstanceFieldThis = this;
   late final field self::Class lateFinalInstanceFieldThis = this;
   late static field core::int lateStaticField;
-  late static final field core::int lateFinalStaticField1;
-  late static final field core::int lateFinalStaticField2;
+  late static final [setter] field core::int lateFinalStaticField1;
+  late static final [setter] field core::int lateFinalStaticField2;
   late static final field core::int lateFinalStaticFieldWithInit = 0;
   synthetic constructor •() → self::Class
     : super core::Object::•()
@@ -74,7 +74,7 @@
   }
 }
 late static field core::int lateTopLevelField;
-late static final field core::int lateFinalTopLevelField;
+late static final [setter] field core::int lateFinalTopLevelField;
 late static final field core::int lateFinalTopLevelFieldWithInit = 0;
 static method main() → dynamic {}
 static method noErrors() → dynamic {
diff --git a/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
index 4c32d9b..eaf8c2c 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
@@ -41,8 +41,8 @@
   late field self::Class lateInstanceFieldThis = this;
   late final field self::Class lateFinalInstanceFieldThis = this;
   late static field core::int lateStaticField;
-  late static final field core::int lateFinalStaticField1;
-  late static final field core::int lateFinalStaticField2;
+  late static final [setter] field core::int lateFinalStaticField1;
+  late static final [setter] field core::int lateFinalStaticField2;
   late static final field core::int lateFinalStaticFieldWithInit = 0;
   synthetic constructor •() → self::Class
     : super core::Object::•()
@@ -74,7 +74,7 @@
   }
 }
 late static field core::int lateTopLevelField;
-late static final field core::int lateFinalTopLevelField;
+late static final [setter] field core::int lateFinalTopLevelField;
 late static final field core::int lateFinalTopLevelFieldWithInit = 0;
 static method main() → dynamic {}
 static method noErrors() → dynamic {
diff --git a/pkg/front_end/testcases/nnbd/late.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/late.dart.textual_outline.expect
index f7b7941..78b3d91 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.textual_outline.expect
@@ -1,21 +1,21 @@
-late int ;
-lateTopLevelField;
-late ;
+late
+int lateTopLevelField;
+late
 final int lateFinalTopLevelField;
-late ;
+late
 final int lateFinalTopLevelFieldWithInit = 0;
 class Class {
-  late int ;
-  lateInstanceField;
-  late ;
+  late
+  int lateInstanceField;
+  late
   final int lateFinalInstanceField1;
-  late ;
+  late
   final int lateFinalInstanceField2;
-  late ;
+  late
   final int lateFinalInstanceFieldWithInit = 0;
-  late Class ;
-  lateInstanceFieldThis = this;
-  late ;
+  late
+  Class lateInstanceFieldThis = this;
+  late
   final Class lateFinalInstanceFieldThis = this;
   static late int ;
   lateStaticField;
diff --git a/pkg/front_end/testcases/nnbd/late.dart.weak.expect b/pkg/front_end/testcases/nnbd/late.dart.weak.expect
index 4c32d9b..eaf8c2c 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.weak.expect
@@ -41,8 +41,8 @@
   late field self::Class lateInstanceFieldThis = this;
   late final field self::Class lateFinalInstanceFieldThis = this;
   late static field core::int lateStaticField;
-  late static final field core::int lateFinalStaticField1;
-  late static final field core::int lateFinalStaticField2;
+  late static final [setter] field core::int lateFinalStaticField1;
+  late static final [setter] field core::int lateFinalStaticField2;
   late static final field core::int lateFinalStaticFieldWithInit = 0;
   synthetic constructor •() → self::Class
     : super core::Object::•()
@@ -74,7 +74,7 @@
   }
 }
 late static field core::int lateTopLevelField;
-late static final field core::int lateFinalTopLevelField;
+late static final [setter] field core::int lateFinalTopLevelField;
 late static final field core::int lateFinalTopLevelFieldWithInit = 0;
 static method main() → dynamic {}
 static method noErrors() → dynamic {
diff --git a/pkg/front_end/testcases/nnbd/late.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/late.dart.weak.transformed.expect
index 4c32d9b..eaf8c2c 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.weak.transformed.expect
@@ -41,8 +41,8 @@
   late field self::Class lateInstanceFieldThis = this;
   late final field self::Class lateFinalInstanceFieldThis = this;
   late static field core::int lateStaticField;
-  late static final field core::int lateFinalStaticField1;
-  late static final field core::int lateFinalStaticField2;
+  late static final [setter] field core::int lateFinalStaticField1;
+  late static final [setter] field core::int lateFinalStaticField2;
   late static final field core::int lateFinalStaticFieldWithInit = 0;
   synthetic constructor •() → self::Class
     : super core::Object::•()
@@ -74,7 +74,7 @@
   }
 }
 late static field core::int lateTopLevelField;
-late static final field core::int lateFinalTopLevelField;
+late static final [setter] field core::int lateFinalTopLevelField;
 late static final field core::int lateFinalTopLevelFieldWithInit = 0;
 static method main() → dynamic {}
 static method noErrors() → dynamic {
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
index df47af6..17dcee5 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
@@ -120,7 +120,7 @@
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
     core::print(s);
   }
-  return "hest";
+  return let final core::String #t2 = "hest" in #t2 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t2 : #t2;
 }
 static method fisk() → dynamic async {
   late core::String s1 = invalid-expression "pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
@@ -129,7 +129,7 @@
   late core::String s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}';
                              ^^^^^"}${#C1}";
-  late core::Function f = () → asy::Future<dynamic> async => await self::hest();
+  late core::Function f = () → asy::Future<dynamic> async => let final dynamic #t3 = await self::hest() in #t3 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t3 : #t3;
 }
 static method main() → dynamic {}
 
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 c198bf3..53a4028 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -109,7 +109,7 @@
     core::print("baz");
   }
   {
-    core::Iterator<core::String> :sync-for-iterator = <core::String>["baz"].{core::Iterable::iterator};
+    core::Iterator<core::String> :sync-for-iterator = core::_GrowableList::_literal1<core::String>("baz").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -118,7 +118,7 @@
     }
   }
   block {
-    final core::List<core::int> #t1 = <core::int>[];
+    final core::List<core::int> #t1 = core::_GrowableList::•<core::int>(0);
     for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1))
       #t1.{core::List::add}{Invariant}(i);
   } =>#t1;
@@ -135,12 +135,14 @@
   dynamic :saved_try_context_var1;
   dynamic :exception0;
   dynamic :stack_trace0;
+  FutureOr<dynamic>:async_temporary_0;
+  FutureOr<dynamic>:async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
       {
         {
-          asy::Stream<core::String> :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
+          asy::Stream<core::String> :stream = asy::Stream::fromIterable<core::String>(core::_GrowableList::_literal1<core::String>("hest"));
           asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
           try
             #L2:
@@ -162,7 +164,15 @@
               :result;
             }
         }
-        :return_value = "hest";
+        final core::String #t5 = "hest";
+        if(#t5 is asy::Future<dynamic>) {
+          [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_1 = _in::unsafeCast<core::String>(:result);
+        }
+        else {
+          :async_temporary_1 = #t5;
+        }
+        :return_value = :async_temporary_1;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -209,12 +219,21 @@
             core::int :await_jump_var = 0;
             dynamic :await_ctx_var;
             dynamic :saved_try_context_var0;
+            FutureOr<dynamic>:async_temporary_0;
             function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
               try {
                 #L4:
                 {
-                  [yield] let dynamic #t5 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                  :return_value = :result;
+                  [yield] let dynamic #t7 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  final dynamic #t8 = :result;
+                  if(#t8 is asy::Future<dynamic>) {
+                    [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = :result;
+                  }
+                  else {
+                    :async_temporary_0 = #t8;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L4;
                 }
                 asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/later.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/later.dart.textual_outline.expect
index bf423f2..d06dcad 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.textual_outline.expect
@@ -1,7 +1,7 @@
 class A {
   int a = 42;
-  late int ;
-  b = (this.a * 2) >> 1;
+  late
+  int b = (this.a * 2) >> 1;
   foo(late int x) {}
 }
 bar(late int x) {}
@@ -9,12 +9,12 @@
 hest() async {}
 fisk() async {}
 class B {
-  late ;
+  late
   final int x = 42;
   const B();
 }
 class C {
-  late ;
+  late
   final int x;
   initVars() {}
 }
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
index df47af6..17dcee5 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
@@ -120,7 +120,7 @@
   await for (core::String s in asy::Stream::fromIterable<core::String>(<core::String>["hest"])) {
     core::print(s);
   }
-  return "hest";
+  return let final core::String #t2 = "hest" in #t2 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t2 : #t2;
 }
 static method fisk() → dynamic async {
   late core::String s1 = invalid-expression "pkg/front_end/testcases/nnbd/later.dart:38:20: Error: `await` expressions are not supported in late local initializers.
@@ -129,7 +129,7 @@
   late core::String s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/nnbd/later.dart:39:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}';
                              ^^^^^"}${#C1}";
-  late core::Function f = () → asy::Future<dynamic> async => await self::hest();
+  late core::Function f = () → asy::Future<dynamic> async => let final dynamic #t3 = await self::hest() in #t3 is asy::Future<dynamic> ?{FutureOr<dynamic>} await #t3 : #t3;
 }
 static method main() → dynamic {}
 
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 c198bf3..53a4028 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -109,7 +109,7 @@
     core::print("baz");
   }
   {
-    core::Iterator<core::String> :sync-for-iterator = <core::String>["baz"].{core::Iterable::iterator};
+    core::Iterator<core::String> :sync-for-iterator = core::_GrowableList::_literal1<core::String>("baz").{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::String s = :sync-for-iterator.{core::Iterator::current};
       {
@@ -118,7 +118,7 @@
     }
   }
   block {
-    final core::List<core::int> #t1 = <core::int>[];
+    final core::List<core::int> #t1 = core::_GrowableList::•<core::int>(0);
     for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1))
       #t1.{core::List::add}{Invariant}(i);
   } =>#t1;
@@ -135,12 +135,14 @@
   dynamic :saved_try_context_var1;
   dynamic :exception0;
   dynamic :stack_trace0;
+  FutureOr<dynamic>:async_temporary_0;
+  FutureOr<dynamic>:async_temporary_1;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L1:
       {
         {
-          asy::Stream<core::String> :stream = asy::Stream::fromIterable<core::String>(<core::String>["hest"]);
+          asy::Stream<core::String> :stream = asy::Stream::fromIterable<core::String>(core::_GrowableList::_literal1<core::String>("hest"));
           asy::_StreamIterator<core::String>? :for-iterator = new asy::_StreamIterator::•<core::String>(:stream);
           try
             #L2:
@@ -162,7 +164,15 @@
               :result;
             }
         }
-        :return_value = "hest";
+        final core::String #t5 = "hest";
+        if(#t5 is asy::Future<dynamic>) {
+          [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_1 = _in::unsafeCast<core::String>(:result);
+        }
+        else {
+          :async_temporary_1 = #t5;
+        }
+        :return_value = :async_temporary_1;
         break #L1;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -209,12 +219,21 @@
             core::int :await_jump_var = 0;
             dynamic :await_ctx_var;
             dynamic :saved_try_context_var0;
+            FutureOr<dynamic>:async_temporary_0;
             function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
               try {
                 #L4:
                 {
-                  [yield] let dynamic #t5 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                  :return_value = :result;
+                  [yield] let dynamic #t7 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                  final dynamic #t8 = :result;
+                  if(#t8 is asy::Future<dynamic>) {
+                    [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+                    :async_temporary_0 = :result;
+                  }
+                  else {
+                    :async_temporary_0 = #t8;
+                  }
+                  :return_value = :async_temporary_0;
                   break #L4;
                 }
                 asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/mix_in_field.dart.outline.expect b/pkg/front_end/testcases/nnbd/mix_in_field.dart.outline.expect
index 100ffd1..06abbef 100644
--- a/pkg/front_end/testcases/nnbd/mix_in_field.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/mix_in_field.dart.outline.expect
@@ -13,6 +13,10 @@
   synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
+  mixin-super-stub get m() → FutureOr<Null>
+    return super.{self::Mixin::m};
+  mixin-super-stub set m(FutureOr<Null>value) → void
+    return super.{self::Mixin::m} = value;
 }
 class Class extends self::_Class&Object&Mixin {
   synthetic constructor •() → self::Class
diff --git a/pkg/front_end/testcases/nnbd/mix_in_field.dart.strong.expect b/pkg/front_end/testcases/nnbd/mix_in_field.dart.strong.expect
index f87569c..8015a15 100644
--- a/pkg/front_end/testcases/nnbd/mix_in_field.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/mix_in_field.dart.strong.expect
@@ -14,13 +14,17 @@
   synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
+  mixin-super-stub get m() → FutureOr<Null>
+    return super.{self::Mixin::m};
+  mixin-super-stub set m(FutureOr<Null>value) → void
+    return super.{self::Mixin::m} = value;
 }
 class Class extends self::_Class&Object&Mixin {
   synthetic constructor •() → self::Class
     : super self::_Class&Object&Mixin::•()
     ;
   method test(dynamic t1) → dynamic {
-    this.{self::Mixin::m} = t1 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<Null>;
+    this.{self::_Class&Object&Mixin::m} = t1 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<Null>;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/mix_in_field.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/mix_in_field.dart.strong.transformed.expect
index 0f52fef..632f92c 100644
--- a/pkg/front_end/testcases/nnbd/mix_in_field.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/mix_in_field.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
     : super self::_Class&Object&Mixin::•()
     ;
   method test(dynamic t1) → dynamic {
-    this.{self::Mixin::m} = t1 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<Null>;
+    this.{self::_Class&Object&Mixin::m} = t1 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<Null>;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/mix_in_field.dart.weak.expect b/pkg/front_end/testcases/nnbd/mix_in_field.dart.weak.expect
index f87569c..8015a15 100644
--- a/pkg/front_end/testcases/nnbd/mix_in_field.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/mix_in_field.dart.weak.expect
@@ -14,13 +14,17 @@
   synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
+  mixin-super-stub get m() → FutureOr<Null>
+    return super.{self::Mixin::m};
+  mixin-super-stub set m(FutureOr<Null>value) → void
+    return super.{self::Mixin::m} = value;
 }
 class Class extends self::_Class&Object&Mixin {
   synthetic constructor •() → self::Class
     : super self::_Class&Object&Mixin::•()
     ;
   method test(dynamic t1) → dynamic {
-    this.{self::Mixin::m} = t1 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<Null>;
+    this.{self::_Class&Object&Mixin::m} = t1 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<Null>;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/mix_in_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/mix_in_field.dart.weak.transformed.expect
index 0f52fef..632f92c 100644
--- a/pkg/front_end/testcases/nnbd/mix_in_field.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/mix_in_field.dart.weak.transformed.expect
@@ -21,7 +21,7 @@
     : super self::_Class&Object&Mixin::•()
     ;
   method test(dynamic t1) → dynamic {
-    this.{self::Mixin::m} = t1 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<Null>;
+    this.{self::_Class&Object&Mixin::m} = t1 as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<Null>;
   }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.textual_outline.expect
index a81aa68..98dd013 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.textual_outline.expect
@@ -20,11 +20,12 @@
   X fieldOfN;
   Y fieldOfN2;
 }
-extension P ;
-on Foo (){}
+extension P on Foo {
+  static int staticFieldOfE;
+}
 int? nullableTopLevelField;
-late int ;
-lateTopLevelField;
+late
+int lateTopLevelField;
 int topLevelFieldWithInitializer = 42;
 class C<X extends Object?, Y extends Object> {
   static int? staticFieldOfX;
@@ -37,12 +38,12 @@
   Y? fieldOfX6;
   static late int ;
   lateStaticFieldOfC;
-  late int ;
-  fieldOfC7;
-  late X ;
-  fieldOfC8;
-  late Y ;
-  fieldOfC9;
+  late
+  int fieldOfC7;
+  late
+  X fieldOfC8;
+  late
+  Y fieldOfC9;
   int fieldOfC10;
   C.foo(this.fieldOfC10);
   C.bar(this.fieldOfC10);
@@ -58,13 +59,17 @@
   Y? fieldOfL6;
   static late int ;
   lateStaticFieldOfM;
-  late int ;
-  fieldOfM7;
-  late X ;
-  fieldOfM8;
-  late Y ;
-  fieldOfM9;
+  late
+  int fieldOfM7;
+  late
+  X fieldOfM8;
+  late
+  Y fieldOfM9;
 }
-extension Q ;
-on Foo (){}
+extension Q on Foo {
+  static int? staticFieldOfQ;
+  static late int ;
+  lateStaticFieldOfQ;
+  static int staticFieldOfQInitialized = 42;
+}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/null_aware_static_access.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_aware_static_access.dart.strong.transformed.expect
index 5af0f3e..51e735b 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_static_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_static_access.dart.strong.transformed.expect
@@ -77,7 +77,7 @@
   static set staticMember2(core::int? value) → void {}
   static method staticMethod() → void {}
   static get property() → core::List<core::int>
-    return <core::int>[0];
+    return core::_GrowableList::_literal1<core::int>(0);
   static get property2() → core::Map<core::int, core::int?>
     return <core::int, core::int?>{};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_aware_static_access.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_aware_static_access.dart.weak.transformed.expect
index 5af0f3e..51e735b 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_static_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_static_access.dart.weak.transformed.expect
@@ -77,7 +77,7 @@
   static set staticMember2(core::int? value) → void {}
   static method staticMethod() → void {}
   static get property() → core::List<core::int>
-    return <core::int>[0];
+    return core::_GrowableList::_literal1<core::int>(0);
   static get property2() → core::Map<core::int, core::int?>
     return <core::int, core::int?>{};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline.expect
index 78062c2..abb5f99 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline.expect
@@ -1,6 +1,9 @@
 class Class {
   Class method() => this;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  Class extensionMethod() => this;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..abb5f99
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class {
+  Class method() => this;
+}
+
+extension Extension on Class {
+  Class extensionMethod() => this;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline.expect
index 438dfcd..13b04f9 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline.expect
@@ -4,19 +4,42 @@
   Class1 get property1 => new Class1();
   Class2 get property2 => new Class2();
 }
-extension Extension1 ;
-on Class1 (){}
+
+extension Extension1 on Class1 {
+  Class1? get nullable1 => property1;
+  void set nullable1(Class1? value) {}
+  Class1 nonNullable1Method() => nonNullable1;
+  Class1? operator [](Class1? key) => nullable1;
+  void operator []=(Class1? key, Class1? value) {}
+  Class1? operator +(int value) => nullable1;
+  Class1? operator -() => nullable1;
+  Class1 get nonNullable1 => property1;
+  Class2 get nonNullable2 => property2;
+}
+
 class Class2 {
   Class2 get property => this;
   void set property(Class2 value) {}
 }
-extension Extension2 ;
-on Class2 (){}
+
+extension Extension2 on Class2 {
+  Class2 nonNullable2Method() => nonNullable2;
+  Class2 operator [](Class2? key) => property;
+  void operator []=(Class2? key, Class2? value) => property;
+  Class2 operator +(int value) => property;
+  Class2 operator -() => property;
+  Class2 get nonNullable2 => property;
+  void set nonNullable2(Class2 value) {}
+}
+
 class Class3 {
   Class2? get property => null;
 }
-extension Extension3 ;
-on Class3 (){}
+
+extension Extension3 on Class3 {
+  Class2? operator [](Class3? key) => property;
+}
+
 main() {}
 void propertyAccess(Class1? n1) {}
 void indexAccess(Class1? n1, Class2? n2, Class3? n3) {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79f7c01
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,48 @@
+class Class1 {
+  Class1? get property => null;
+  Class1 get property1 => new Class1();
+  Class2 get property2 => new Class2();
+  void set property(Class1? value) {}
+}
+
+class Class2 {
+  Class2 get property => this;
+  void set property(Class2 value) {}
+}
+
+class Class3 {
+  Class2? get property => null;
+}
+
+extension Extension1 on Class1 {
+  Class1? get nullable1 => property1;
+  Class1? operator +(int value) => nullable1;
+  Class1? operator -() => nullable1;
+  Class1? operator [](Class1? key) => nullable1;
+  Class1 get nonNullable1 => property1;
+  Class1 nonNullable1Method() => nonNullable1;
+  Class2 get nonNullable2 => property2;
+  void operator []=(Class1? key, Class1? value) {}
+  void set nullable1(Class1? value) {}
+}
+
+extension Extension2 on Class2 {
+  Class2 get nonNullable2 => property;
+  Class2 nonNullable2Method() => nonNullable2;
+  Class2 operator +(int value) => property;
+  Class2 operator -() => property;
+  Class2 operator [](Class2? key) => property;
+  void operator []=(Class2? key, Class2? value) => property;
+  void set nonNullable2(Class2 value) {}
+}
+
+extension Extension3 on Class3 {
+  Class2? operator [](Class3? key) => property;
+}
+
+main() {}
+void ifNull(Class1? n1) {}
+void indexAccess(Class1? n1, Class2? n2, Class3? n3) {}
+void operatorAccess(Class1? n1, Class2? n2) {}
+void propertyAccess(Class1? n1) {}
+void throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline.expect
index 438dfcd..13b04f9 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline.expect
@@ -4,19 +4,42 @@
   Class1 get property1 => new Class1();
   Class2 get property2 => new Class2();
 }
-extension Extension1 ;
-on Class1 (){}
+
+extension Extension1 on Class1 {
+  Class1? get nullable1 => property1;
+  void set nullable1(Class1? value) {}
+  Class1 nonNullable1Method() => nonNullable1;
+  Class1? operator [](Class1? key) => nullable1;
+  void operator []=(Class1? key, Class1? value) {}
+  Class1? operator +(int value) => nullable1;
+  Class1? operator -() => nullable1;
+  Class1 get nonNullable1 => property1;
+  Class2 get nonNullable2 => property2;
+}
+
 class Class2 {
   Class2 get property => this;
   void set property(Class2 value) {}
 }
-extension Extension2 ;
-on Class2 (){}
+
+extension Extension2 on Class2 {
+  Class2 nonNullable2Method() => nonNullable2;
+  Class2 operator [](Class2? key) => property;
+  void operator []=(Class2? key, Class2? value) => property;
+  Class2 operator +(int value) => property;
+  Class2 operator -() => property;
+  Class2 get nonNullable2 => property;
+  void set nonNullable2(Class2 value) {}
+}
+
 class Class3 {
   Class2? get property => null;
 }
-extension Extension3 ;
-on Class3 (){}
+
+extension Extension3 on Class3 {
+  Class2? operator [](Class3? key) => property;
+}
+
 main() {}
 void propertyAccess(Class1? n1) {}
 void indexAccess(Class1? n1, Class2? n2, Class3? n3) {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79f7c01
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,48 @@
+class Class1 {
+  Class1? get property => null;
+  Class1 get property1 => new Class1();
+  Class2 get property2 => new Class2();
+  void set property(Class1? value) {}
+}
+
+class Class2 {
+  Class2 get property => this;
+  void set property(Class2 value) {}
+}
+
+class Class3 {
+  Class2? get property => null;
+}
+
+extension Extension1 on Class1 {
+  Class1? get nullable1 => property1;
+  Class1? operator +(int value) => nullable1;
+  Class1? operator -() => nullable1;
+  Class1? operator [](Class1? key) => nullable1;
+  Class1 get nonNullable1 => property1;
+  Class1 nonNullable1Method() => nonNullable1;
+  Class2 get nonNullable2 => property2;
+  void operator []=(Class1? key, Class1? value) {}
+  void set nullable1(Class1? value) {}
+}
+
+extension Extension2 on Class2 {
+  Class2 get nonNullable2 => property;
+  Class2 nonNullable2Method() => nonNullable2;
+  Class2 operator +(int value) => property;
+  Class2 operator -() => property;
+  Class2 operator [](Class2? key) => property;
+  void operator []=(Class2? key, Class2? value) => property;
+  void set nonNullable2(Class2 value) {}
+}
+
+extension Extension3 on Class3 {
+  Class2? operator [](Class3? key) => property;
+}
+
+main() {}
+void ifNull(Class1? n1) {}
+void indexAccess(Class1? n1, Class2? n2, Class3? n3) {}
+void operatorAccess(Class1? n1, Class2? n2) {}
+void propertyAccess(Class1? n1) {}
+void throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline.expect
index e3e40af..2be2b70 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline.expect
@@ -3,9 +3,14 @@
   int operator [](int index) => index;
   void operator []=(int index, int value) {}
 }
+
 class Class2 {
   int field = 42;
 }
-extension Extension ;
-on Class2 (){}
+
+extension Extension on Class2 {
+  int operator [](int index) => field;
+  void operator []=(int index, int value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2be2b70
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline_modelled.expect
@@ -0,0 +1,16 @@
+class Class1 {
+  Class2? get field => null;
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+class Class2 {
+  int field = 42;
+}
+
+extension Extension on Class2 {
+  int operator [](int index) => field;
+  void operator []=(int index, int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.expect
index 3b43c3b..c8e0ecb 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.expect
@@ -58,3 +58,9 @@
 constants  {
   #C1 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///nullable_access.dart:
+- A. (from org-dartlang-testcase:///nullable_access.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.transformed.expect
index 3b43c3b..c8e0ecb 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.strong.transformed.expect
@@ -58,3 +58,9 @@
 constants  {
   #C1 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///nullable_access.dart:
+- A. (from org-dartlang-testcase:///nullable_access.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.expect
index 3b43c3b..c8e0ecb 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.expect
@@ -58,3 +58,9 @@
 constants  {
   #C1 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///nullable_access.dart:
+- A. (from org-dartlang-testcase:///nullable_access.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.transformed.expect
index 3b43c3b..c8e0ecb 100644
--- a/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_access.dart.weak.transformed.expect
@@ -58,3 +58,9 @@
 constants  {
   #C1 = self::A {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///nullable_access.dart:
+- A. (from org-dartlang-testcase:///nullable_access.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline.expect
index 8bd081e..3eef1e7 100644
--- a/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline.expect
@@ -1,8 +1,10 @@
 class A {
   String text = "";
 }
-extension on ;
-A;
-? { String get text => "Lily was here"; }
+
+extension on A? {
+  String get text => "Lily was here";
+}
+
 void main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ff2587a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class A {
+  String text = "";
+}
+
+expect(expected, actual) {}
+
+extension on A? {
+  String get text => "Lily was here";
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
index b1e0890..a1e7f4f 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
@@ -20,10 +20,10 @@
     return n;
 }
 static method foo() → dynamic {
-  return <core::List<self::A<Null>?>>[<Null>[], <self::A<Null>>[]];
+  return core::_GrowableList::_literal2<core::List<self::A<Null>?>>(core::_GrowableList::•<Null>(0), core::_GrowableList::•<self::A<Null>>(0));
 }
 static method bar() → dynamic {
-  return <core::List<self::A<Null>?>>[#C1, #C2];
+  return core::_GrowableList::_literal2<core::List<self::A<Null>?>>(#C1, #C2);
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.transformed.expect
index 82c9494..99a17fe 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.weak.transformed.expect
@@ -20,10 +20,10 @@
     return n;
 }
 static method foo() → dynamic {
-  return <core::List<self::A<Null>?>>[<Null>[], <self::A<Null>>[]];
+  return core::_GrowableList::_literal2<core::List<self::A<Null>?>>(core::_GrowableList::•<Null>(0), core::_GrowableList::•<self::A<Null>>(0));
 }
 static method bar() → dynamic {
-  return <core::List<self::A<Null>?>>[#C1, #C2];
+  return core::_GrowableList::_literal2<core::List<self::A<Null>?>>(#C1, #C2);
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline.expect
index f75f2e0..ff978cb 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline.expect
@@ -3,8 +3,11 @@
   void set setter(String v) {}
   void operator []=(int index, String value) {}
 }
-extension on ;
-C;
-? { void set setter(String v) { this?.m = v; } void operator []=(int index, String value) { this?.m = '$index$value'; } }
+
+extension on C? {
+  void set setter(String v) {}
+  void operator []=(int index, String value) {}
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7a84dd6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class C {
+  String m = "";
+  void operator []=(int index, String value) {}
+  void set setter(String v) {}
+}
+
+expect(expected, actual) {}
+
+extension on C? {
+  void operator []=(int index, String value) {}
+  void set setter(String v) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.outline.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.outline.expect
index a3f0156..ece5e4e 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.outline.expect
@@ -62,7 +62,7 @@
     ;
 }
 class C1 extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
   static factory •() → self::C1
     let dynamic #redirecting_factory = self::C2::• in let core::int? #typeArg0 = null in invalid-expression;
 }
@@ -71,7 +71,7 @@
     ;
 }
 class D extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
   constructor foo(core::num x) → self::D
     ;
   static factory bar(core::num? x) → self::D
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.strong.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.strong.expect
index 5ca1bf7..6721314 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.strong.expect
@@ -62,7 +62,7 @@
   method hest(core::num value) → void {}
 }
 class C1 extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
   static factory •() → self::C1
     let dynamic #redirecting_factory = self::C2::• in let core::int? #typeArg0 = null in invalid-expression;
 }
@@ -72,7 +72,7 @@
     ;
 }
 class D extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
   constructor foo(core::num x) → self::D
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.strong.transformed.expect
index de6bd24..730260d 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.strong.transformed.expect
@@ -62,7 +62,7 @@
   method hest(core::num value) → void {}
 }
 class C1 extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
   static factory •() → self::C1
     let<BottomType> #redirecting_factory = self::C2::• in let core::int? #typeArg0 = null in invalid-expression;
 }
@@ -72,7 +72,7 @@
     ;
 }
 class D extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
   constructor foo(core::num x) → self::D
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.weak.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.weak.expect
index 5ca1bf7..6721314 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.weak.expect
@@ -62,7 +62,7 @@
   method hest(core::num value) → void {}
 }
 class C1 extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
   static factory •() → self::C1
     let dynamic #redirecting_factory = self::C2::• in let core::int? #typeArg0 = null in invalid-expression;
 }
@@ -72,7 +72,7 @@
     ;
 }
 class D extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
   constructor foo(core::num x) → self::D
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.weak.transformed.expect
index de6bd24..730260d 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.weak.transformed.expect
@@ -62,7 +62,7 @@
   method hest(core::num value) → void {}
 }
 class C1 extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::C1::•]/*isLegacy*/;
   static factory •() → self::C1
     let<BottomType> #redirecting_factory = self::C2::• in let core::int? #typeArg0 = null in invalid-expression;
 }
@@ -72,7 +72,7 @@
     ;
 }
 class D extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[self::D::bar]/*isLegacy*/;
   constructor foo(core::num x) → self::D
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.outline.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.outline.expect
index eca66dc..1599471 100644
--- a/pkg/front_end/testcases/nnbd/override_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.outline.expect
@@ -24,21 +24,10 @@
 //   int method1d();
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:8: Error: Can't infer types for 'method5a' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   void method5a(x, y); // error
-//                 ^
-// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
-//   void method5a(int x, num y);
 //        ^^^^^^^^
-// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
-//   void method5a(num x, int y);
-//        ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
-//   void method5a(x, y); // error
-//                    ^
 // pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
 //   void method5a(int x, num y);
 //        ^^^^^^^^
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.strong.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.strong.expect
index 0a80f3f..ae3903b 100644
--- a/pkg/front_end/testcases/nnbd/override_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.strong.expect
@@ -24,21 +24,10 @@
 //   int method1d();
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:8: Error: Can't infer types for 'method5a' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   void method5a(x, y); // error
-//                 ^
-// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
-//   void method5a(int x, num y);
 //        ^^^^^^^^
-// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
-//   void method5a(num x, int y);
-//        ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
-//   void method5a(x, y); // error
-//                    ^
 // pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
 //   void method5a(int x, num y);
 //        ^^^^^^^^
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.strong.transformed.expect
index 0a80f3f..ae3903b 100644
--- a/pkg/front_end/testcases/nnbd/override_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.strong.transformed.expect
@@ -24,21 +24,10 @@
 //   int method1d();
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:8: Error: Can't infer types for 'method5a' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   void method5a(x, y); // error
-//                 ^
-// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
-//   void method5a(int x, num y);
 //        ^^^^^^^^
-// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
-//   void method5a(num x, int y);
-//        ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
-//   void method5a(x, y); // error
-//                    ^
 // pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
 //   void method5a(int x, num y);
 //        ^^^^^^^^
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.weak.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.weak.expect
index 0a80f3f..ae3903b 100644
--- a/pkg/front_end/testcases/nnbd/override_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.weak.expect
@@ -24,21 +24,10 @@
 //   int method1d();
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:8: Error: Can't infer types for 'method5a' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   void method5a(x, y); // error
-//                 ^
-// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
-//   void method5a(int x, num y);
 //        ^^^^^^^^
-// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
-//   void method5a(num x, int y);
-//        ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
-//   void method5a(x, y); // error
-//                    ^
 // pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
 //   void method5a(int x, num y);
 //        ^^^^^^^^
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.weak.transformed.expect
index 0a80f3f..ae3903b 100644
--- a/pkg/front_end/testcases/nnbd/override_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.weak.transformed.expect
@@ -24,21 +24,10 @@
 //   int method1d();
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:8: Error: Can't infer types for 'method5a' as the overridden members don't have a combined signature.
+// Try adding explicit types.
 //   void method5a(x, y); // error
-//                 ^
-// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
-//   void method5a(int x, num y);
 //        ^^^^^^^^
-// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
-//   void method5a(num x, int y);
-//        ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
-// Try adding an explicit type.
-//   void method5a(x, y); // error
-//                    ^
 // pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
 //   void method5a(int x, num y);
 //        ^^^^^^^^
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 f6d9603..d067529 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
@@ -254,3 +254,13 @@
   #C28 = self::ClassWithFunction<core::int> {field:#C27}
   #C29 = self::ClassWithFunction<core::int> {field:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///potentially_constant_type_as.dart:
+- Class. (from org-dartlang-testcase:///potentially_constant_type_as.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ClassWithBound. (from org-dartlang-testcase:///potentially_constant_type_as.dart:22:9)
+- ClassWithBound.withValue (from org-dartlang-testcase:///potentially_constant_type_as.dart:24:9)
+- ClassWithList. (from org-dartlang-testcase:///potentially_constant_type_as.dart:30:9)
+- ClassWithFunction. (from org-dartlang-testcase:///potentially_constant_type_as.dart:36:9)
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 f6d9603..d067529 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
@@ -254,3 +254,13 @@
   #C28 = self::ClassWithFunction<core::int> {field:#C27}
   #C29 = self::ClassWithFunction<core::int> {field:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///potentially_constant_type_as.dart:
+- Class. (from org-dartlang-testcase:///potentially_constant_type_as.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ClassWithBound. (from org-dartlang-testcase:///potentially_constant_type_as.dart:22:9)
+- ClassWithBound.withValue (from org-dartlang-testcase:///potentially_constant_type_as.dart:24:9)
+- ClassWithList. (from org-dartlang-testcase:///potentially_constant_type_as.dart:30:9)
+- ClassWithFunction. (from org-dartlang-testcase:///potentially_constant_type_as.dart:36:9)
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 03c1430..9abe043 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
@@ -237,7 +237,7 @@
   #C20 = self::ClassWithList<core::String*> {field:#C19}
   #C21 = tearoff self::dynamicFunction
   #C22 = self::ClassWithFunction<dynamic> {field:#C21}
-  #C23 = self::ClassWithFunction<core::Object*> {field:#C21}
+  #C23 = self::ClassWithFunction<core::Object?> {field:#C21}
   #C24 = tearoff self::objectFunction
   #C25 = self::ClassWithFunction<dynamic> {field:#C24}
   #C26 = self::ClassWithFunction<void> {field:#C24}
@@ -246,3 +246,13 @@
   #C29 = self::ClassWithFunction<core::int*> {field:#C3}
   #C30 = self::ClassWithFunction<core::Object*> {field:#C24}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///potentially_constant_type_as.dart:
+- Class. (from org-dartlang-testcase:///potentially_constant_type_as.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ClassWithBound. (from org-dartlang-testcase:///potentially_constant_type_as.dart:22:9)
+- ClassWithBound.withValue (from org-dartlang-testcase:///potentially_constant_type_as.dart:24:9)
+- ClassWithList. (from org-dartlang-testcase:///potentially_constant_type_as.dart:30:9)
+- ClassWithFunction. (from org-dartlang-testcase:///potentially_constant_type_as.dart:36:9)
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 03c1430..9abe043 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
@@ -237,7 +237,7 @@
   #C20 = self::ClassWithList<core::String*> {field:#C19}
   #C21 = tearoff self::dynamicFunction
   #C22 = self::ClassWithFunction<dynamic> {field:#C21}
-  #C23 = self::ClassWithFunction<core::Object*> {field:#C21}
+  #C23 = self::ClassWithFunction<core::Object?> {field:#C21}
   #C24 = tearoff self::objectFunction
   #C25 = self::ClassWithFunction<dynamic> {field:#C24}
   #C26 = self::ClassWithFunction<void> {field:#C24}
@@ -246,3 +246,13 @@
   #C29 = self::ClassWithFunction<core::int*> {field:#C3}
   #C30 = self::ClassWithFunction<core::Object*> {field:#C24}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///potentially_constant_type_as.dart:
+- Class. (from org-dartlang-testcase:///potentially_constant_type_as.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ClassWithBound. (from org-dartlang-testcase:///potentially_constant_type_as.dart:22:9)
+- ClassWithBound.withValue (from org-dartlang-testcase:///potentially_constant_type_as.dart:24:9)
+- ClassWithList. (from org-dartlang-testcase:///potentially_constant_type_as.dart:30:9)
+- ClassWithFunction. (from org-dartlang-testcase:///potentially_constant_type_as.dart:36:9)
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 8ff2377..dd71e24 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
@@ -113,3 +113,13 @@
   #C32 = self::ClassWithFunction<core::num> {field:#C19}
   #C33 = self::ClassWithFunction<core::int> {field:#C19}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///potentially_constant_type_is.dart:
+- Class. (from org-dartlang-testcase:///potentially_constant_type_is.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ClassWithBound. (from org-dartlang-testcase:///potentially_constant_type_is.dart:22:9)
+- ClassWithBound.withValue (from org-dartlang-testcase:///potentially_constant_type_is.dart:24:9)
+- ClassWithList. (from org-dartlang-testcase:///potentially_constant_type_is.dart:30:9)
+- ClassWithFunction. (from org-dartlang-testcase:///potentially_constant_type_is.dart:36:9)
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 8ff2377..dd71e24 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
@@ -113,3 +113,13 @@
   #C32 = self::ClassWithFunction<core::num> {field:#C19}
   #C33 = self::ClassWithFunction<core::int> {field:#C19}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///potentially_constant_type_is.dart:
+- Class. (from org-dartlang-testcase:///potentially_constant_type_is.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ClassWithBound. (from org-dartlang-testcase:///potentially_constant_type_is.dart:22:9)
+- ClassWithBound.withValue (from org-dartlang-testcase:///potentially_constant_type_is.dart:24:9)
+- ClassWithList. (from org-dartlang-testcase:///potentially_constant_type_is.dart:30:9)
+- ClassWithFunction. (from org-dartlang-testcase:///potentially_constant_type_is.dart:36:9)
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 839df94..da6412f 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
@@ -58,24 +58,24 @@
   #C17;
   #C18;
   #C18;
-  #C16;
-  #C20;
+  #C19;
   #C21;
   #C22;
   #C23;
-  #C23;
-  #C23;
+  #C24;
+  #C24;
   #C24;
   #C25;
   #C26;
   #C27;
   #C28;
   #C29;
-  #C29;
+  #C30;
   #C30;
   #C31;
   #C32;
   #C33;
+  #C34;
 }
 
 constants  {
@@ -94,22 +94,33 @@
   #C13 = self::ClassWithList<core::int*> {field:#C4}
   #C14 = self::ClassWithList<core::String*> {field:#C4}
   #C15 = self::ClassWithFunction<dynamic> {field:#C4}
-  #C16 = self::ClassWithFunction<core::Object*> {field:#C4}
+  #C16 = self::ClassWithFunction<core::Object?> {field:#C4}
   #C17 = self::ClassWithFunction<void> {field:#C4}
   #C18 = self::ClassWithFunction<core::int*> {field:#C4}
-  #C19 = false
-  #C20 = self::Class<core::num*> {field:#C19}
-  #C21 = self::Class<core::int*> {field:#C19}
-  #C22 = self::Class<core::String*> {field:#C19}
-  #C23 = self::ClassWithBound<core::double*> {field:#C19}
-  #C24 = self::ClassWithBound<core::num*> {field:#C19}
-  #C25 = self::ClassWithList<dynamic> {field:#C19}
-  #C26 = self::ClassWithList<core::num*> {field:#C19}
-  #C27 = self::ClassWithList<core::int*> {field:#C19}
-  #C28 = self::ClassWithList<core::String*> {field:#C19}
-  #C29 = self::ClassWithFunction<dynamic> {field:#C19}
-  #C30 = self::ClassWithFunction<core::Object*> {field:#C19}
-  #C31 = self::ClassWithFunction<void> {field:#C19}
-  #C32 = self::ClassWithFunction<core::num*> {field:#C19}
-  #C33 = self::ClassWithFunction<core::int*> {field:#C19}
+  #C19 = self::ClassWithFunction<core::Object*> {field:#C4}
+  #C20 = false
+  #C21 = self::Class<core::num*> {field:#C20}
+  #C22 = self::Class<core::int*> {field:#C20}
+  #C23 = self::Class<core::String*> {field:#C20}
+  #C24 = self::ClassWithBound<core::double*> {field:#C20}
+  #C25 = self::ClassWithBound<core::num*> {field:#C20}
+  #C26 = self::ClassWithList<dynamic> {field:#C20}
+  #C27 = self::ClassWithList<core::num*> {field:#C20}
+  #C28 = self::ClassWithList<core::int*> {field:#C20}
+  #C29 = self::ClassWithList<core::String*> {field:#C20}
+  #C30 = self::ClassWithFunction<dynamic> {field:#C20}
+  #C31 = self::ClassWithFunction<core::Object*> {field:#C20}
+  #C32 = self::ClassWithFunction<void> {field:#C20}
+  #C33 = self::ClassWithFunction<core::num*> {field:#C20}
+  #C34 = self::ClassWithFunction<core::int*> {field:#C20}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///potentially_constant_type_is.dart:
+- Class. (from org-dartlang-testcase:///potentially_constant_type_is.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ClassWithBound. (from org-dartlang-testcase:///potentially_constant_type_is.dart:22:9)
+- ClassWithBound.withValue (from org-dartlang-testcase:///potentially_constant_type_is.dart:24:9)
+- ClassWithList. (from org-dartlang-testcase:///potentially_constant_type_is.dart:30:9)
+- ClassWithFunction. (from org-dartlang-testcase:///potentially_constant_type_is.dart:36:9)
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 839df94..da6412f 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
@@ -58,24 +58,24 @@
   #C17;
   #C18;
   #C18;
-  #C16;
-  #C20;
+  #C19;
   #C21;
   #C22;
   #C23;
-  #C23;
-  #C23;
+  #C24;
+  #C24;
   #C24;
   #C25;
   #C26;
   #C27;
   #C28;
   #C29;
-  #C29;
+  #C30;
   #C30;
   #C31;
   #C32;
   #C33;
+  #C34;
 }
 
 constants  {
@@ -94,22 +94,33 @@
   #C13 = self::ClassWithList<core::int*> {field:#C4}
   #C14 = self::ClassWithList<core::String*> {field:#C4}
   #C15 = self::ClassWithFunction<dynamic> {field:#C4}
-  #C16 = self::ClassWithFunction<core::Object*> {field:#C4}
+  #C16 = self::ClassWithFunction<core::Object?> {field:#C4}
   #C17 = self::ClassWithFunction<void> {field:#C4}
   #C18 = self::ClassWithFunction<core::int*> {field:#C4}
-  #C19 = false
-  #C20 = self::Class<core::num*> {field:#C19}
-  #C21 = self::Class<core::int*> {field:#C19}
-  #C22 = self::Class<core::String*> {field:#C19}
-  #C23 = self::ClassWithBound<core::double*> {field:#C19}
-  #C24 = self::ClassWithBound<core::num*> {field:#C19}
-  #C25 = self::ClassWithList<dynamic> {field:#C19}
-  #C26 = self::ClassWithList<core::num*> {field:#C19}
-  #C27 = self::ClassWithList<core::int*> {field:#C19}
-  #C28 = self::ClassWithList<core::String*> {field:#C19}
-  #C29 = self::ClassWithFunction<dynamic> {field:#C19}
-  #C30 = self::ClassWithFunction<core::Object*> {field:#C19}
-  #C31 = self::ClassWithFunction<void> {field:#C19}
-  #C32 = self::ClassWithFunction<core::num*> {field:#C19}
-  #C33 = self::ClassWithFunction<core::int*> {field:#C19}
+  #C19 = self::ClassWithFunction<core::Object*> {field:#C4}
+  #C20 = false
+  #C21 = self::Class<core::num*> {field:#C20}
+  #C22 = self::Class<core::int*> {field:#C20}
+  #C23 = self::Class<core::String*> {field:#C20}
+  #C24 = self::ClassWithBound<core::double*> {field:#C20}
+  #C25 = self::ClassWithBound<core::num*> {field:#C20}
+  #C26 = self::ClassWithList<dynamic> {field:#C20}
+  #C27 = self::ClassWithList<core::num*> {field:#C20}
+  #C28 = self::ClassWithList<core::int*> {field:#C20}
+  #C29 = self::ClassWithList<core::String*> {field:#C20}
+  #C30 = self::ClassWithFunction<dynamic> {field:#C20}
+  #C31 = self::ClassWithFunction<core::Object*> {field:#C20}
+  #C32 = self::ClassWithFunction<void> {field:#C20}
+  #C33 = self::ClassWithFunction<core::num*> {field:#C20}
+  #C34 = self::ClassWithFunction<core::int*> {field:#C20}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///potentially_constant_type_is.dart:
+- Class. (from org-dartlang-testcase:///potentially_constant_type_is.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- ClassWithBound. (from org-dartlang-testcase:///potentially_constant_type_is.dart:22:9)
+- ClassWithBound.withValue (from org-dartlang-testcase:///potentially_constant_type_is.dart:24:9)
+- ClassWithList. (from org-dartlang-testcase:///potentially_constant_type_is.dart:30:9)
+- ClassWithFunction. (from org-dartlang-testcase:///potentially_constant_type_is.dart:36:9)
diff --git a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.textual_outline.expect
index 059663f..82cafac 100644
--- a/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_non_nullable_field.dart.textual_outline.expect
@@ -1,7 +1,7 @@
 int x;
 int? y;
-late int ;
-z;
+late
+int z;
 class A<T extends Object?> {
   static int x;
   static int? y;
@@ -9,15 +9,14 @@
   z;
   int lx;
   int? ly;
-  late int;
-  operator? (){}
-  lz;
+  late
+  int? lz;
   int lv;
   int lu;
   T lt;
   T? ls;
-  late T ;
-  lr;
+  late
+  T lr;
   T lp;
   T lq;
   A(this.lv, this.lp, T t) : this.lu = 42, this.lq = t;
diff --git a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline.expect
index cbd0809..6f73b5c 100644
--- a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline.expect
@@ -6,8 +6,20 @@
   Function get functionGetter => () {};
   void Function() get functionTypeGetter => () {};
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  int operator +(int value) => 0;
+  int operator -() => 0;
+  int operator [](int index) => 0;
+  void operator []=(int index, int value) {}
+  int call() => 0;
+  int get extensionProperty => 0;
+  void set extensionProperty(int value) {}
+  int extensionMethod() => 0;
+  Function get extensionFunctionGetter => () {};
+  void Function() get extensionFunctionTypeGetter => () {};
+}
+
 Function? get nullableFunction => () {};
 void Function()? get nullableFunctionType => () {};
 int? get nullableInt => 0;
@@ -47,6 +59,7 @@
 var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
 var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
 var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
-var topLevelExtensionFunctionTypeGetter = nullableClass.extensionFunctionTypeGetter();
+var topLevelExtensionFunctionTypeGetter =
+    nullableClass.extensionFunctionTypeGetter();
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fe7c996
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,66 @@
+Class? get nullableClass => new Class();
+Function? get nullableFunction => () {};
+Map<dynamic, dynamic>? get nullableMap => {};
+
+class Class {
+  Function functionField = () {};
+  Function get functionGetter => () {};
+  int method() => 0;
+  int property = 0;
+  void Function() functionTypeField = () {};
+  void Function() get functionTypeGetter => () {};
+}
+
+extension Extension on Class {
+  Function get extensionFunctionGetter => () {};
+  int call() => 0;
+  int extensionMethod() => 0;
+  int get extensionProperty => 0;
+  int operator +(int value) => 0;
+  int operator -() => 0;
+  int operator [](int index) => 0;
+  void Function() get extensionFunctionTypeGetter => () {};
+  void operator []=(int index, int value) {}
+  void set extensionProperty(int value) {}
+}
+
+int? get nullableInt => 0;
+main() {}
+test() {}
+var topLevelBinary = nullableInt + 0;
+var topLevelExtensionBinary = nullableClass + 0;
+var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
+var topLevelExtensionFunctionTypeGetter =
+    nullableClass.extensionFunctionTypeGetter();
+var topLevelExtensionFunctionTypeImplicitCall = nullableClass();
+var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
+var topLevelExtensionIndexGet = nullableClass[0];
+var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+var topLevelExtensionIndexSet = nullableClass[0] = 1;
+var topLevelExtensionMethodInvocation = nullableClass.extensionMethod();
+var topLevelExtensionMethodTearOff = nullableClass.extensionMethod;
+var topLevelExtensionPropertyGet = nullableClass.extensionProperty;
+var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+var topLevelExtensionPropertySet = nullableClass.extensionProperty = 1;
+var topLevelExtensionUnary = -nullableClass;
+var topLevelFunctionExplicitCall = nullableFunction.call();
+var topLevelFunctionField = nullableClass.functionField();
+var topLevelFunctionGetter = nullableClass.functionGetter();
+var topLevelFunctionImplicitCall = nullableFunction();
+var topLevelFunctionTearOff = nullableFunction.call;
+var topLevelFunctionTypeExplicitCall = nullableFunctionType.call();
+var topLevelFunctionTypeField = nullableClass.functionTypeField();
+var topLevelFunctionTypeGetter = nullableClass.functionTypeGetter();
+var topLevelFunctionTypeImplicitCall = nullableFunctionType();
+var topLevelFunctionTypeTearOff = nullableFunctionType.call;
+var topLevelIndexGet = nullableMap[0];
+var topLevelIndexGetSet = nullableMap[0] += 1;
+var topLevelIndexSet = nullableMap[0] = 1;
+var topLevelMethodInvocation = nullableClass.method();
+var topLevelMethodTearOff = nullableClass.method;
+var topLevelPropertyGet = nullableClass.property;
+var topLevelPropertyGetSet = nullableClass.property += 1;
+var topLevelPropertySet = nullableClass.property = 1;
+var topLevelUnary = -nullableInt;
+void Function()? get nullableFunctionType => () {};
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart
new file mode 100644
index 0000000..9b143d6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart
@@ -0,0 +1,232 @@
+// 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.
+
+bool b = true;
+
+abstract class Map<K, V> {
+  V operator [](K index);
+  void operator []=(K index, V value);
+}
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+  Class operator +(Class cls) => cls;
+
+  void indexGetSetForEffect(Map<Class, Class> map) {
+    late final Class self;
+    if (b) self = this;
+    map[this] ??= this;
+    map[self] ??= self;
+
+    map[this] = this;
+    map[self] = self;
+
+    map[this];
+    map[self];
+
+    map[this] += this;
+    map[self] += self;
+  }
+
+  void indexGetSetForValue(Map<Class, Class> map) {
+    late final Class self;
+    if (b) self = this;
+    var v;
+    v = map[this] ??= this;
+    v = map[self] ??= self;
+
+    v = map[this] = this;
+    v = map[self] = self;
+
+    v = map[this];
+    v = map[self];
+
+    v = map[this] += this;
+    v = map[self] += self;
+  }
+
+  void implicitExtensionGetSetForEffect(int i) {
+    late final Class self;
+    if (b) self = this;
+    i[this] ??= this;
+    i[self] ??= self;
+
+    i[this] = this;
+    i[self] = self;
+
+    i[this];
+    i[self];
+
+    i[this] += this;
+    i[self] += self;
+  }
+
+  void implicitExtensionGetSetForValue(int i) {
+    late final Class self;
+    if (b) self = this;
+    var v;
+    v = i[this] ??= this;
+    v = i[self] ??= self;
+
+    v = i[this] = this;
+    v = i[self] = self;
+
+    v = i[this];
+    v = i[self];
+
+    v = i[this] += this;
+    v = i[self] += self;
+  }
+
+  void explicitExtensionGetSetForEffect(int i) {
+    late final Class self;
+    if (b) self = this;
+    Extension(i)[this] ??= this;
+    Extension(i)[self] ??= self;
+
+    Extension(i)[this] = this;
+    Extension(i)[self] = self;
+
+    Extension(i)[this];
+    Extension(i)[self];
+
+    Extension(i)[this] += this;
+    Extension(i)[self] += self;
+  }
+
+  void explicitExtensionGetSetForValue(int i) {
+    late final Class self;
+    if (b) self = this;
+    var v;
+    v = Extension(i)[this] ??= this;
+    v = Extension(i)[self] ??= self;
+
+    v = Extension(i)[this] = this;
+    v = Extension(i)[self] = self;
+
+    v = Extension(i)[this];
+    v = Extension(i)[self];
+
+    v = Extension(i)[this] += this;
+    v = Extension(i)[self] += self;
+  }
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {
+    late final Class self;
+    if (b) self = this;
+    super[this] ??= this;
+    super[self] ??= self;
+
+    super[this] = this;
+    super[self] = self;
+
+    super[this];
+    super[self];
+
+    super[this] += this;
+    super[self] += self;
+  }
+
+  void superIndexGetSetForValue() {
+    late final Class self;
+    if (b) self = this;
+    var v;
+    v = super[this] ??= this;
+    v = super[self] ??= self;
+
+    v = super[this] = this;
+    v = super[self] = self;
+
+    v = super[this];
+    v = super[self];
+
+    v = super[this] += this;
+    v = super[self] += self;
+  }
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+
+  void implicitExtensionGetSetForEffect() {
+    late final Class2 self;
+    if (b) self = this;
+    this[this] ??= this;
+    self[self] ??= self;
+
+    this[this] = this;
+    self[self] = self;
+
+    this[this];
+    self[self];
+
+    this[this] += this;
+    self[self] += self;
+  }
+
+  void implicitExtensionGetSetForValue() {
+    late final Class2 self;
+    if (b) self = this;
+    var v;
+    v = this[this] ??= this;
+    v = self[self] ??= self;
+
+    v = this[this] = this;
+    v = self[self] = self;
+
+    v = this[this];
+    v = self[self];
+
+    v = this[this] += this;
+    v = self[self] += self;
+  }
+
+  void explicitExtensionGetSetForEffect() {
+    late final Class2 self;
+    if (b) self = this;
+    Extension2(this)[this] ??= this;
+    Extension2(self)[self] ??= self;
+
+    Extension2(this)[this] = this;
+    Extension2(self)[self] = self;
+
+    Extension2(this)[this];
+    Extension2(self)[self];
+
+    Extension2(this)[this] += this;
+    Extension2(self)[self] += self;
+  }
+
+  void explicitExtensionGetSetForValue() {
+    late final Class2 self;
+    if (b) self = this;
+    var v;
+    v = Extension2(this)[this] ??= this;
+    v = Extension2(self)[self] ??= self;
+
+    v = Extension2(this)[this] = this;
+    v = Extension2(self)[self] = self;
+
+    v = Extension2(this)[this];
+    v = Extension2(self)[self];
+
+    v = Extension2(this)[this] += this;
+    v = Extension2(self)[self] += self;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.outline.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.outline.expect
new file mode 100644
index 0000000..f44d475
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.outline.expect
@@ -0,0 +1,73 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    ;
+  operator [](self::Class cls) → self::Class
+    ;
+  operator []=(self::Class cls, self::Class value) → void
+    ;
+  operator +(self::Class cls) → self::Class
+    ;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void
+    ;
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void
+    ;
+  method implicitExtensionGetSetForEffect(core::int i) → void
+    ;
+  method implicitExtensionGetSetForValue(core::int i) → void
+    ;
+  method explicitExtensionGetSetForEffect(core::int i) → void
+    ;
+  method explicitExtensionGetSetForValue(core::int i) → void
+    ;
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    ;
+  method superIndexGetSetForEffect() → void
+    ;
+  method superIndexGetSetForValue() → void
+    ;
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    ;
+  method implicitExtensionGetSetForEffect() → void
+    ;
+  method implicitExtensionGetSetForValue() → void
+    ;
+  method explicitExtensionGetSetForEffect() → void
+    ;
+  method explicitExtensionGetSetForValue() → void
+    ;
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  ;
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void
+  ;
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  ;
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.expect
new file mode 100644
index 0000000..84d1907
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.expect
@@ -0,0 +1,334 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:25:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[this] ??= this;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:26:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[self] ??= self;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:42:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[this] ??= this;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:43:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[self] ??= self;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:58:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[this] ??= this;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:59:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[self] ??= self;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:75:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:76:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:91:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[this] ??= this;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:92:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[self] ??= self;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:108:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:109:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:126:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:127:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:143:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[this] ??= this;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:144:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[self] ??= self;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:168:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     this[this] ??= this;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:169:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     self[self] ??= self;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:185:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = this[this] ??= this;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:186:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = self[self] ??= self;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:201:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(this)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:202:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(self)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:218:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(this)[this] ??= this;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:219:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(self)[self] ??= self;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    : super core::Object::•()
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  operator [](self::Class cls) → self::Class
+    return new self::Class::•();
+  operator []=(self::Class cls, self::Class value) → void {}
+  operator +(self::Class cls) → self::Class
+    return cls;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final self::Map<self::Class, self::Class> #t1 = map in #t1.{self::Map::[]}(this).{core::Object::==}(null) ?{self::Class} #t1.{self::Map::[]=}(this, this) : null;
+    let final self::Map<self::Class, self::Class> #t2 = map in let final self::Class #t3 = self in #t2.{self::Map::[]}(#t3).{core::Object::==}(null) ?{self::Class} #t2.{self::Map::[]=}(#t3, self) : null;
+    map.{self::Map::[]=}(this, this);
+    map.{self::Map::[]=}(self, self);
+    map.{self::Map::[]}(this);
+    map.{self::Map::[]}(self);
+    let final self::Map<self::Class, self::Class> #t4 = map in #t4.{self::Map::[]=}(this, #t4.{self::Map::[]}(this).{self::Class::+}(this));
+    let final self::Map<self::Class, self::Class> #t5 = map in let final self::Class #t6 = self in #t5.{self::Map::[]=}(#t6, #t5.{self::Map::[]}(#t6).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Map<self::Class, self::Class> #t7 = map in let final self::Class #t8 = #t7.{self::Map::[]}(this) in #t8.{core::Object::==}(null) ?{self::Class} let final void #t9 = #t7.{self::Map::[]=}(this, this) in this : #t8;
+    v = let final self::Map<self::Class, self::Class> #t10 = map in let final self::Class #t11 = self in let final self::Class #t12 = #t10.{self::Map::[]}(#t11) in #t12.{core::Object::==}(null) ?{self::Class} let final self::Class #t13 = self in let final void #t14 = #t10.{self::Map::[]=}(#t11, #t13) in #t13 : #t12;
+    v = let final self::Map<self::Class, self::Class> #t15 = map in let final void #t16 = #t15.{self::Map::[]=}(this, this) in this;
+    v = let final self::Map<self::Class, self::Class> #t17 = map in let final self::Class #t18 = self in let final self::Class #t19 = self in let final void #t20 = #t17.{self::Map::[]=}(#t18, #t19) in #t19;
+    v = map.{self::Map::[]}(this);
+    v = map.{self::Map::[]}(self);
+    v = let final self::Map<self::Class, self::Class> #t21 = map in let final self::Class #t22 = #t21.{self::Map::[]}(this).{self::Class::+}(this) in let final void #t23 = #t21.{self::Map::[]=}(this, #t22) in #t22;
+    v = let final self::Map<self::Class, self::Class> #t24 = map in let final self::Class #t25 = self in let final self::Class #t26 = #t24.{self::Map::[]}(#t25).{self::Class::+}(self) in let final void #t27 = #t24.{self::Map::[]=}(#t25, #t26) in #t26;
+  }
+  method implicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t28 = i in self::Extension|[](#t28, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t28, this, this) : null;
+    let final core::int #t29 = i in let final self::Class #t30 = self in self::Extension|[](#t29, #t30).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t29, #t30, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t31 = i in self::Extension|[]=(#t31, this, self::Extension|[](#t31, this).{self::Class::+}(this));
+    let final core::int #t32 = i in let final self::Class #t33 = self in self::Extension|[]=(#t32, #t33, self::Extension|[](#t32, #t33).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t34 = i in let final self::Class #t35 = self::Extension|[](#t34, this) in #t35.{core::Object::==}(null) ?{self::Class} let final void #t36 = self::Extension|[]=(#t34, this, this) in this : #t35;
+    v = let final core::int #t37 = i in let final self::Class #t38 = self in let final self::Class #t39 = self::Extension|[](#t37, #t38) in #t39.{core::Object::==}(null) ?{self::Class} let final self::Class #t40 = self in let final void #t41 = self::Extension|[]=(#t37, #t38, #t40) in #t40 : #t39;
+    v = let final core::int #t42 = i in let final void #t43 = self::Extension|[]=(#t42, this, this) in this;
+    v = let final core::int #t44 = i in let final self::Class #t45 = self in let final self::Class #t46 = self in let final void #t47 = self::Extension|[]=(#t44, #t45, #t46) in #t46;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t48 = i in let final self::Class #t49 = self::Extension|[](#t48, this).{self::Class::+}(this) in let final void #t50 = self::Extension|[]=(#t48, this, #t49) in #t49;
+    v = let final core::int #t51 = i in let final self::Class #t52 = self in let final self::Class #t53 = self::Extension|[](#t51, #t52).{self::Class::+}(self) in let final void #t54 = self::Extension|[]=(#t51, #t52, #t53) in #t53;
+  }
+  method explicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t55 = i in self::Extension|[](#t55, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t55, this, this) : null;
+    let final core::int #t56 = i in let final self::Class #t57 = self in self::Extension|[](#t56, #t57).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t56, #t57, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t58 = i in self::Extension|[]=(#t58, this, self::Extension|[](#t58, this).{self::Class::+}(this));
+    let final core::int #t59 = i in let final self::Class #t60 = self in self::Extension|[]=(#t59, #t60, self::Extension|[](#t59, #t60).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t61 = i in let final self::Class #t62 = self::Extension|[](#t61, this) in #t62.{core::Object::==}(null) ?{self::Class} let final void #t63 = self::Extension|[]=(#t61, this, this) in this : #t62;
+    v = let final core::int #t64 = i in let final self::Class #t65 = self in let final self::Class #t66 = self::Extension|[](#t64, #t65) in #t66.{core::Object::==}(null) ?{self::Class} let final self::Class #t67 = self in let final void #t68 = self::Extension|[]=(#t64, #t65, #t67) in #t67 : #t66;
+    v = let final core::int #t69 = i in let final void #t70 = self::Extension|[]=(#t69, this, this) in this;
+    v = let final core::int #t71 = i in let final self::Class #t72 = self in let final void #t73 = self::Extension|[]=(#t71, self, #t72) in #t72;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t74 = i in let final self::Class #t75 = self::Extension|[](#t74, this).{self::Class::+}(this) in let final void #t76 = self::Extension|[]=(#t74, this, #t75) in #t75;
+    v = let final core::int #t77 = i in let final self::Class #t78 = self in let final self::Class #t79 = self::Extension|[](#t77, #t78).{self::Class::+}(self) in let final void #t80 = self::Extension|[]=(#t77, #t78, #t79) in #t79;
+  }
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    super.{self::Class::[]}(this).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(this, this) : null;
+    let final self::Class #t81 = self in super.{self::Class::[]}(#t81).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(#t81, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    let final self::Class #t82 = self in super.{self::Class::[]=}(#t82, super.{self::Class::[]}(#t82).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class #t83 = super.{self::Class::[]}(this) in #t83.{core::Object::==}(null) ?{self::Class} let final void #t84 = super.{self::Class::[]=}(this, this) in this : #t83;
+    v = let final self::Class #t85 = self in let final self::Class #t86 = super.{self::Class::[]}(#t85) in #t86.{core::Object::==}(null) ?{self::Class} let final self::Class #t87 = self in let final void #t88 = super.{self::Class::[]=}(#t85, #t87) in #t87 : #t86;
+    v = let final void #t89 = super.{self::Class::[]=}(this, this) in this;
+    v = let final self::Class #t90 = self in let final self::Class #t91 = self in let final void #t92 = super.{self::Class::[]=}(#t90, #t91) in #t91;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class #t93 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t94 = super.{self::Class::[]=}(this, #t93) in #t93;
+    v = let final self::Class #t95 = self in let final self::Class #t96 = super.{self::Class::[]}(#t95).{self::Class::+}(self) in let final void #t97 = super.{self::Class::[]=}(#t95, #t96) in #t96;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    : super core::Object::•()
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t98 = self in let final self::Class2 #t99 = self in self::Extension2|[](#t98, #t99).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t98, #t99, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t100 = self in let final self::Class2 #t101 = self in self::Extension2|[]=(#t100, #t101, self::Extension2|[](#t100, #t101).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t102 = self::Extension2|[](this, this) in #t102.{core::Object::==}(null) ?{self::Class2} let final void #t103 = self::Extension2|[]=(this, this, this) in this : #t102;
+    v = let final self::Class2 #t104 = self in let final self::Class2 #t105 = self in let final self::Class2 #t106 = self::Extension2|[](#t104, #t105) in #t106.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t107 = self in let final void #t108 = self::Extension2|[]=(#t104, #t105, #t107) in #t107 : #t106;
+    v = let final void #t109 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t110 = self in let final self::Class2 #t111 = self in let final self::Class2 #t112 = self in let final void #t113 = self::Extension2|[]=(#t110, #t111, #t112) in #t112;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t114 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t115 = self::Extension2|[]=(this, this, #t114) in #t114;
+    v = let final self::Class2 #t116 = self in let final self::Class2 #t117 = self in let final self::Class2 #t118 = self::Extension2|[](#t116, #t117).{self::Class2::+}(self) in let final void #t119 = self::Extension2|[]=(#t116, #t117, #t118) in #t118;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t120 = self in let final self::Class2 #t121 = self in self::Extension2|[](#t120, #t121).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t120, #t121, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t122 = self in let final self::Class2 #t123 = self in self::Extension2|[]=(#t122, #t123, self::Extension2|[](#t122, #t123).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t124 = self::Extension2|[](this, this) in #t124.{core::Object::==}(null) ?{self::Class2} let final void #t125 = self::Extension2|[]=(this, this, this) in this : #t124;
+    v = let final self::Class2 #t126 = self in let final self::Class2 #t127 = self in let final self::Class2 #t128 = self::Extension2|[](#t126, #t127) in #t128.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t129 = self in let final void #t130 = self::Extension2|[]=(#t126, #t127, #t129) in #t129 : #t128;
+    v = let final void #t131 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t132 = self in let final self::Class2 #t133 = self in let final void #t134 = self::Extension2|[]=(#t132, self, #t133) in #t133;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t135 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t136 = self::Extension2|[]=(this, this, #t135) in #t135;
+    v = let final self::Class2 #t137 = self in let final self::Class2 #t138 = self in let final self::Class2 #t139 = self::Extension2|[](#t137, #t138).{self::Class2::+}(self) in let final void #t140 = self::Extension2|[]=(#t137, #t138, #t139) in #t139;
+  }
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b = true;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void {}
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.transformed.expect
new file mode 100644
index 0000000..84d1907
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.transformed.expect
@@ -0,0 +1,334 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:25:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[this] ??= this;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:26:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[self] ??= self;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:42:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[this] ??= this;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:43:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[self] ??= self;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:58:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[this] ??= this;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:59:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[self] ??= self;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:75:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:76:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:91:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[this] ??= this;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:92:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[self] ??= self;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:108:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:109:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:126:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:127:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:143:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[this] ??= this;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:144:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[self] ??= self;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:168:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     this[this] ??= this;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:169:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     self[self] ??= self;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:185:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = this[this] ??= this;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:186:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = self[self] ??= self;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:201:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(this)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:202:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(self)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:218:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(this)[this] ??= this;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:219:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(self)[self] ??= self;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    : super core::Object::•()
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  operator [](self::Class cls) → self::Class
+    return new self::Class::•();
+  operator []=(self::Class cls, self::Class value) → void {}
+  operator +(self::Class cls) → self::Class
+    return cls;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final self::Map<self::Class, self::Class> #t1 = map in #t1.{self::Map::[]}(this).{core::Object::==}(null) ?{self::Class} #t1.{self::Map::[]=}(this, this) : null;
+    let final self::Map<self::Class, self::Class> #t2 = map in let final self::Class #t3 = self in #t2.{self::Map::[]}(#t3).{core::Object::==}(null) ?{self::Class} #t2.{self::Map::[]=}(#t3, self) : null;
+    map.{self::Map::[]=}(this, this);
+    map.{self::Map::[]=}(self, self);
+    map.{self::Map::[]}(this);
+    map.{self::Map::[]}(self);
+    let final self::Map<self::Class, self::Class> #t4 = map in #t4.{self::Map::[]=}(this, #t4.{self::Map::[]}(this).{self::Class::+}(this));
+    let final self::Map<self::Class, self::Class> #t5 = map in let final self::Class #t6 = self in #t5.{self::Map::[]=}(#t6, #t5.{self::Map::[]}(#t6).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Map<self::Class, self::Class> #t7 = map in let final self::Class #t8 = #t7.{self::Map::[]}(this) in #t8.{core::Object::==}(null) ?{self::Class} let final void #t9 = #t7.{self::Map::[]=}(this, this) in this : #t8;
+    v = let final self::Map<self::Class, self::Class> #t10 = map in let final self::Class #t11 = self in let final self::Class #t12 = #t10.{self::Map::[]}(#t11) in #t12.{core::Object::==}(null) ?{self::Class} let final self::Class #t13 = self in let final void #t14 = #t10.{self::Map::[]=}(#t11, #t13) in #t13 : #t12;
+    v = let final self::Map<self::Class, self::Class> #t15 = map in let final void #t16 = #t15.{self::Map::[]=}(this, this) in this;
+    v = let final self::Map<self::Class, self::Class> #t17 = map in let final self::Class #t18 = self in let final self::Class #t19 = self in let final void #t20 = #t17.{self::Map::[]=}(#t18, #t19) in #t19;
+    v = map.{self::Map::[]}(this);
+    v = map.{self::Map::[]}(self);
+    v = let final self::Map<self::Class, self::Class> #t21 = map in let final self::Class #t22 = #t21.{self::Map::[]}(this).{self::Class::+}(this) in let final void #t23 = #t21.{self::Map::[]=}(this, #t22) in #t22;
+    v = let final self::Map<self::Class, self::Class> #t24 = map in let final self::Class #t25 = self in let final self::Class #t26 = #t24.{self::Map::[]}(#t25).{self::Class::+}(self) in let final void #t27 = #t24.{self::Map::[]=}(#t25, #t26) in #t26;
+  }
+  method implicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t28 = i in self::Extension|[](#t28, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t28, this, this) : null;
+    let final core::int #t29 = i in let final self::Class #t30 = self in self::Extension|[](#t29, #t30).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t29, #t30, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t31 = i in self::Extension|[]=(#t31, this, self::Extension|[](#t31, this).{self::Class::+}(this));
+    let final core::int #t32 = i in let final self::Class #t33 = self in self::Extension|[]=(#t32, #t33, self::Extension|[](#t32, #t33).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t34 = i in let final self::Class #t35 = self::Extension|[](#t34, this) in #t35.{core::Object::==}(null) ?{self::Class} let final void #t36 = self::Extension|[]=(#t34, this, this) in this : #t35;
+    v = let final core::int #t37 = i in let final self::Class #t38 = self in let final self::Class #t39 = self::Extension|[](#t37, #t38) in #t39.{core::Object::==}(null) ?{self::Class} let final self::Class #t40 = self in let final void #t41 = self::Extension|[]=(#t37, #t38, #t40) in #t40 : #t39;
+    v = let final core::int #t42 = i in let final void #t43 = self::Extension|[]=(#t42, this, this) in this;
+    v = let final core::int #t44 = i in let final self::Class #t45 = self in let final self::Class #t46 = self in let final void #t47 = self::Extension|[]=(#t44, #t45, #t46) in #t46;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t48 = i in let final self::Class #t49 = self::Extension|[](#t48, this).{self::Class::+}(this) in let final void #t50 = self::Extension|[]=(#t48, this, #t49) in #t49;
+    v = let final core::int #t51 = i in let final self::Class #t52 = self in let final self::Class #t53 = self::Extension|[](#t51, #t52).{self::Class::+}(self) in let final void #t54 = self::Extension|[]=(#t51, #t52, #t53) in #t53;
+  }
+  method explicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t55 = i in self::Extension|[](#t55, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t55, this, this) : null;
+    let final core::int #t56 = i in let final self::Class #t57 = self in self::Extension|[](#t56, #t57).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t56, #t57, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t58 = i in self::Extension|[]=(#t58, this, self::Extension|[](#t58, this).{self::Class::+}(this));
+    let final core::int #t59 = i in let final self::Class #t60 = self in self::Extension|[]=(#t59, #t60, self::Extension|[](#t59, #t60).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t61 = i in let final self::Class #t62 = self::Extension|[](#t61, this) in #t62.{core::Object::==}(null) ?{self::Class} let final void #t63 = self::Extension|[]=(#t61, this, this) in this : #t62;
+    v = let final core::int #t64 = i in let final self::Class #t65 = self in let final self::Class #t66 = self::Extension|[](#t64, #t65) in #t66.{core::Object::==}(null) ?{self::Class} let final self::Class #t67 = self in let final void #t68 = self::Extension|[]=(#t64, #t65, #t67) in #t67 : #t66;
+    v = let final core::int #t69 = i in let final void #t70 = self::Extension|[]=(#t69, this, this) in this;
+    v = let final core::int #t71 = i in let final self::Class #t72 = self in let final void #t73 = self::Extension|[]=(#t71, self, #t72) in #t72;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t74 = i in let final self::Class #t75 = self::Extension|[](#t74, this).{self::Class::+}(this) in let final void #t76 = self::Extension|[]=(#t74, this, #t75) in #t75;
+    v = let final core::int #t77 = i in let final self::Class #t78 = self in let final self::Class #t79 = self::Extension|[](#t77, #t78).{self::Class::+}(self) in let final void #t80 = self::Extension|[]=(#t77, #t78, #t79) in #t79;
+  }
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    super.{self::Class::[]}(this).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(this, this) : null;
+    let final self::Class #t81 = self in super.{self::Class::[]}(#t81).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(#t81, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    let final self::Class #t82 = self in super.{self::Class::[]=}(#t82, super.{self::Class::[]}(#t82).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class #t83 = super.{self::Class::[]}(this) in #t83.{core::Object::==}(null) ?{self::Class} let final void #t84 = super.{self::Class::[]=}(this, this) in this : #t83;
+    v = let final self::Class #t85 = self in let final self::Class #t86 = super.{self::Class::[]}(#t85) in #t86.{core::Object::==}(null) ?{self::Class} let final self::Class #t87 = self in let final void #t88 = super.{self::Class::[]=}(#t85, #t87) in #t87 : #t86;
+    v = let final void #t89 = super.{self::Class::[]=}(this, this) in this;
+    v = let final self::Class #t90 = self in let final self::Class #t91 = self in let final void #t92 = super.{self::Class::[]=}(#t90, #t91) in #t91;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class #t93 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t94 = super.{self::Class::[]=}(this, #t93) in #t93;
+    v = let final self::Class #t95 = self in let final self::Class #t96 = super.{self::Class::[]}(#t95).{self::Class::+}(self) in let final void #t97 = super.{self::Class::[]=}(#t95, #t96) in #t96;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    : super core::Object::•()
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t98 = self in let final self::Class2 #t99 = self in self::Extension2|[](#t98, #t99).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t98, #t99, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t100 = self in let final self::Class2 #t101 = self in self::Extension2|[]=(#t100, #t101, self::Extension2|[](#t100, #t101).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t102 = self::Extension2|[](this, this) in #t102.{core::Object::==}(null) ?{self::Class2} let final void #t103 = self::Extension2|[]=(this, this, this) in this : #t102;
+    v = let final self::Class2 #t104 = self in let final self::Class2 #t105 = self in let final self::Class2 #t106 = self::Extension2|[](#t104, #t105) in #t106.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t107 = self in let final void #t108 = self::Extension2|[]=(#t104, #t105, #t107) in #t107 : #t106;
+    v = let final void #t109 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t110 = self in let final self::Class2 #t111 = self in let final self::Class2 #t112 = self in let final void #t113 = self::Extension2|[]=(#t110, #t111, #t112) in #t112;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t114 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t115 = self::Extension2|[]=(this, this, #t114) in #t114;
+    v = let final self::Class2 #t116 = self in let final self::Class2 #t117 = self in let final self::Class2 #t118 = self::Extension2|[](#t116, #t117).{self::Class2::+}(self) in let final void #t119 = self::Extension2|[]=(#t116, #t117, #t118) in #t118;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t120 = self in let final self::Class2 #t121 = self in self::Extension2|[](#t120, #t121).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t120, #t121, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t122 = self in let final self::Class2 #t123 = self in self::Extension2|[]=(#t122, #t123, self::Extension2|[](#t122, #t123).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t124 = self::Extension2|[](this, this) in #t124.{core::Object::==}(null) ?{self::Class2} let final void #t125 = self::Extension2|[]=(this, this, this) in this : #t124;
+    v = let final self::Class2 #t126 = self in let final self::Class2 #t127 = self in let final self::Class2 #t128 = self::Extension2|[](#t126, #t127) in #t128.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t129 = self in let final void #t130 = self::Extension2|[]=(#t126, #t127, #t129) in #t129 : #t128;
+    v = let final void #t131 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t132 = self in let final self::Class2 #t133 = self in let final void #t134 = self::Extension2|[]=(#t132, self, #t133) in #t133;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t135 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t136 = self::Extension2|[]=(this, this, #t135) in #t135;
+    v = let final self::Class2 #t137 = self in let final self::Class2 #t138 = self in let final self::Class2 #t139 = self::Extension2|[](#t137, #t138).{self::Class2::+}(self) in let final void #t140 = self::Extension2|[]=(#t137, #t138, #t139) in #t139;
+  }
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b = true;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void {}
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline.expect
new file mode 100644
index 0000000..beb5b6c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline.expect
@@ -0,0 +1,43 @@
+bool b = true;
+
+abstract class Map<K, V> {
+  V operator [](K index);
+  void operator []=(K index, V value);
+}
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+  Class operator +(Class cls) => cls;
+  void indexGetSetForEffect(Map<Class, Class> map) {}
+  void indexGetSetForValue(Map<Class, Class> map) {}
+  void implicitExtensionGetSetForEffect(int i) {}
+  void implicitExtensionGetSetForValue(int i) {}
+  void explicitExtensionGetSetForEffect(int i) {}
+  void explicitExtensionGetSetForValue(int i) {}
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {}
+  void superIndexGetSetForValue() {}
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+  void implicitExtensionGetSetForEffect() {}
+  void implicitExtensionGetSetForValue() {}
+  void explicitExtensionGetSetForEffect() {}
+  void explicitExtensionGetSetForValue() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5088689
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline_modelled.expect
@@ -0,0 +1,43 @@
+abstract class Map<K, V> {
+  V operator [](K index);
+  void operator []=(K index, V value);
+}
+
+bool b = true;
+
+class Class {
+  Class operator +(Class cls) => cls;
+  Class operator [](Class cls) => new Class();
+  void explicitExtensionGetSetForEffect(int i) {}
+  void explicitExtensionGetSetForValue(int i) {}
+  void implicitExtensionGetSetForEffect(int i) {}
+  void implicitExtensionGetSetForValue(int i) {}
+  void indexGetSetForEffect(Map<Class, Class> map) {}
+  void indexGetSetForValue(Map<Class, Class> map) {}
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+  void explicitExtensionGetSetForEffect() {}
+  void explicitExtensionGetSetForValue() {}
+  void implicitExtensionGetSetForEffect() {}
+  void implicitExtensionGetSetForValue() {}
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {}
+  void superIndexGetSetForValue() {}
+}
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.expect
new file mode 100644
index 0000000..84d1907
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.expect
@@ -0,0 +1,334 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:25:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[this] ??= this;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:26:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[self] ??= self;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:42:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[this] ??= this;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:43:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[self] ??= self;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:58:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[this] ??= this;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:59:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[self] ??= self;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:75:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:76:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:91:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[this] ??= this;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:92:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[self] ??= self;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:108:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:109:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:126:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:127:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:143:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[this] ??= this;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:144:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[self] ??= self;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:168:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     this[this] ??= this;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:169:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     self[self] ??= self;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:185:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = this[this] ??= this;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:186:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = self[self] ??= self;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:201:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(this)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:202:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(self)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:218:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(this)[this] ??= this;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:219:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(self)[self] ??= self;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    : super core::Object::•()
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  operator [](self::Class cls) → self::Class
+    return new self::Class::•();
+  operator []=(self::Class cls, self::Class value) → void {}
+  operator +(self::Class cls) → self::Class
+    return cls;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final self::Map<self::Class, self::Class> #t1 = map in #t1.{self::Map::[]}(this).{core::Object::==}(null) ?{self::Class} #t1.{self::Map::[]=}(this, this) : null;
+    let final self::Map<self::Class, self::Class> #t2 = map in let final self::Class #t3 = self in #t2.{self::Map::[]}(#t3).{core::Object::==}(null) ?{self::Class} #t2.{self::Map::[]=}(#t3, self) : null;
+    map.{self::Map::[]=}(this, this);
+    map.{self::Map::[]=}(self, self);
+    map.{self::Map::[]}(this);
+    map.{self::Map::[]}(self);
+    let final self::Map<self::Class, self::Class> #t4 = map in #t4.{self::Map::[]=}(this, #t4.{self::Map::[]}(this).{self::Class::+}(this));
+    let final self::Map<self::Class, self::Class> #t5 = map in let final self::Class #t6 = self in #t5.{self::Map::[]=}(#t6, #t5.{self::Map::[]}(#t6).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Map<self::Class, self::Class> #t7 = map in let final self::Class #t8 = #t7.{self::Map::[]}(this) in #t8.{core::Object::==}(null) ?{self::Class} let final void #t9 = #t7.{self::Map::[]=}(this, this) in this : #t8;
+    v = let final self::Map<self::Class, self::Class> #t10 = map in let final self::Class #t11 = self in let final self::Class #t12 = #t10.{self::Map::[]}(#t11) in #t12.{core::Object::==}(null) ?{self::Class} let final self::Class #t13 = self in let final void #t14 = #t10.{self::Map::[]=}(#t11, #t13) in #t13 : #t12;
+    v = let final self::Map<self::Class, self::Class> #t15 = map in let final void #t16 = #t15.{self::Map::[]=}(this, this) in this;
+    v = let final self::Map<self::Class, self::Class> #t17 = map in let final self::Class #t18 = self in let final self::Class #t19 = self in let final void #t20 = #t17.{self::Map::[]=}(#t18, #t19) in #t19;
+    v = map.{self::Map::[]}(this);
+    v = map.{self::Map::[]}(self);
+    v = let final self::Map<self::Class, self::Class> #t21 = map in let final self::Class #t22 = #t21.{self::Map::[]}(this).{self::Class::+}(this) in let final void #t23 = #t21.{self::Map::[]=}(this, #t22) in #t22;
+    v = let final self::Map<self::Class, self::Class> #t24 = map in let final self::Class #t25 = self in let final self::Class #t26 = #t24.{self::Map::[]}(#t25).{self::Class::+}(self) in let final void #t27 = #t24.{self::Map::[]=}(#t25, #t26) in #t26;
+  }
+  method implicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t28 = i in self::Extension|[](#t28, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t28, this, this) : null;
+    let final core::int #t29 = i in let final self::Class #t30 = self in self::Extension|[](#t29, #t30).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t29, #t30, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t31 = i in self::Extension|[]=(#t31, this, self::Extension|[](#t31, this).{self::Class::+}(this));
+    let final core::int #t32 = i in let final self::Class #t33 = self in self::Extension|[]=(#t32, #t33, self::Extension|[](#t32, #t33).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t34 = i in let final self::Class #t35 = self::Extension|[](#t34, this) in #t35.{core::Object::==}(null) ?{self::Class} let final void #t36 = self::Extension|[]=(#t34, this, this) in this : #t35;
+    v = let final core::int #t37 = i in let final self::Class #t38 = self in let final self::Class #t39 = self::Extension|[](#t37, #t38) in #t39.{core::Object::==}(null) ?{self::Class} let final self::Class #t40 = self in let final void #t41 = self::Extension|[]=(#t37, #t38, #t40) in #t40 : #t39;
+    v = let final core::int #t42 = i in let final void #t43 = self::Extension|[]=(#t42, this, this) in this;
+    v = let final core::int #t44 = i in let final self::Class #t45 = self in let final self::Class #t46 = self in let final void #t47 = self::Extension|[]=(#t44, #t45, #t46) in #t46;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t48 = i in let final self::Class #t49 = self::Extension|[](#t48, this).{self::Class::+}(this) in let final void #t50 = self::Extension|[]=(#t48, this, #t49) in #t49;
+    v = let final core::int #t51 = i in let final self::Class #t52 = self in let final self::Class #t53 = self::Extension|[](#t51, #t52).{self::Class::+}(self) in let final void #t54 = self::Extension|[]=(#t51, #t52, #t53) in #t53;
+  }
+  method explicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t55 = i in self::Extension|[](#t55, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t55, this, this) : null;
+    let final core::int #t56 = i in let final self::Class #t57 = self in self::Extension|[](#t56, #t57).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t56, #t57, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t58 = i in self::Extension|[]=(#t58, this, self::Extension|[](#t58, this).{self::Class::+}(this));
+    let final core::int #t59 = i in let final self::Class #t60 = self in self::Extension|[]=(#t59, #t60, self::Extension|[](#t59, #t60).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t61 = i in let final self::Class #t62 = self::Extension|[](#t61, this) in #t62.{core::Object::==}(null) ?{self::Class} let final void #t63 = self::Extension|[]=(#t61, this, this) in this : #t62;
+    v = let final core::int #t64 = i in let final self::Class #t65 = self in let final self::Class #t66 = self::Extension|[](#t64, #t65) in #t66.{core::Object::==}(null) ?{self::Class} let final self::Class #t67 = self in let final void #t68 = self::Extension|[]=(#t64, #t65, #t67) in #t67 : #t66;
+    v = let final core::int #t69 = i in let final void #t70 = self::Extension|[]=(#t69, this, this) in this;
+    v = let final core::int #t71 = i in let final self::Class #t72 = self in let final void #t73 = self::Extension|[]=(#t71, self, #t72) in #t72;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t74 = i in let final self::Class #t75 = self::Extension|[](#t74, this).{self::Class::+}(this) in let final void #t76 = self::Extension|[]=(#t74, this, #t75) in #t75;
+    v = let final core::int #t77 = i in let final self::Class #t78 = self in let final self::Class #t79 = self::Extension|[](#t77, #t78).{self::Class::+}(self) in let final void #t80 = self::Extension|[]=(#t77, #t78, #t79) in #t79;
+  }
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    super.{self::Class::[]}(this).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(this, this) : null;
+    let final self::Class #t81 = self in super.{self::Class::[]}(#t81).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(#t81, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    let final self::Class #t82 = self in super.{self::Class::[]=}(#t82, super.{self::Class::[]}(#t82).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class #t83 = super.{self::Class::[]}(this) in #t83.{core::Object::==}(null) ?{self::Class} let final void #t84 = super.{self::Class::[]=}(this, this) in this : #t83;
+    v = let final self::Class #t85 = self in let final self::Class #t86 = super.{self::Class::[]}(#t85) in #t86.{core::Object::==}(null) ?{self::Class} let final self::Class #t87 = self in let final void #t88 = super.{self::Class::[]=}(#t85, #t87) in #t87 : #t86;
+    v = let final void #t89 = super.{self::Class::[]=}(this, this) in this;
+    v = let final self::Class #t90 = self in let final self::Class #t91 = self in let final void #t92 = super.{self::Class::[]=}(#t90, #t91) in #t91;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class #t93 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t94 = super.{self::Class::[]=}(this, #t93) in #t93;
+    v = let final self::Class #t95 = self in let final self::Class #t96 = super.{self::Class::[]}(#t95).{self::Class::+}(self) in let final void #t97 = super.{self::Class::[]=}(#t95, #t96) in #t96;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    : super core::Object::•()
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t98 = self in let final self::Class2 #t99 = self in self::Extension2|[](#t98, #t99).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t98, #t99, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t100 = self in let final self::Class2 #t101 = self in self::Extension2|[]=(#t100, #t101, self::Extension2|[](#t100, #t101).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t102 = self::Extension2|[](this, this) in #t102.{core::Object::==}(null) ?{self::Class2} let final void #t103 = self::Extension2|[]=(this, this, this) in this : #t102;
+    v = let final self::Class2 #t104 = self in let final self::Class2 #t105 = self in let final self::Class2 #t106 = self::Extension2|[](#t104, #t105) in #t106.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t107 = self in let final void #t108 = self::Extension2|[]=(#t104, #t105, #t107) in #t107 : #t106;
+    v = let final void #t109 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t110 = self in let final self::Class2 #t111 = self in let final self::Class2 #t112 = self in let final void #t113 = self::Extension2|[]=(#t110, #t111, #t112) in #t112;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t114 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t115 = self::Extension2|[]=(this, this, #t114) in #t114;
+    v = let final self::Class2 #t116 = self in let final self::Class2 #t117 = self in let final self::Class2 #t118 = self::Extension2|[](#t116, #t117).{self::Class2::+}(self) in let final void #t119 = self::Extension2|[]=(#t116, #t117, #t118) in #t118;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t120 = self in let final self::Class2 #t121 = self in self::Extension2|[](#t120, #t121).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t120, #t121, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t122 = self in let final self::Class2 #t123 = self in self::Extension2|[]=(#t122, #t123, self::Extension2|[](#t122, #t123).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t124 = self::Extension2|[](this, this) in #t124.{core::Object::==}(null) ?{self::Class2} let final void #t125 = self::Extension2|[]=(this, this, this) in this : #t124;
+    v = let final self::Class2 #t126 = self in let final self::Class2 #t127 = self in let final self::Class2 #t128 = self::Extension2|[](#t126, #t127) in #t128.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t129 = self in let final void #t130 = self::Extension2|[]=(#t126, #t127, #t129) in #t129 : #t128;
+    v = let final void #t131 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t132 = self in let final self::Class2 #t133 = self in let final void #t134 = self::Extension2|[]=(#t132, self, #t133) in #t133;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t135 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t136 = self::Extension2|[]=(this, this, #t135) in #t135;
+    v = let final self::Class2 #t137 = self in let final self::Class2 #t138 = self in let final self::Class2 #t139 = self::Extension2|[](#t137, #t138).{self::Class2::+}(self) in let final void #t140 = self::Extension2|[]=(#t137, #t138, #t139) in #t139;
+  }
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b = true;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void {}
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.transformed.expect
new file mode 100644
index 0000000..84d1907
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.transformed.expect
@@ -0,0 +1,334 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:25:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[this] ??= this;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:26:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[self] ??= self;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:42:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[this] ??= this;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:43:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[self] ??= self;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:58:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[this] ??= this;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:59:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[self] ??= self;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:75:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:76:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:91:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[this] ??= this;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:92:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[self] ??= self;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:108:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:109:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:126:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:127:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:143:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[this] ??= this;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:144:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[self] ??= self;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:168:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     this[this] ??= this;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:169:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     self[self] ??= self;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:185:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = this[this] ??= this;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:186:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = self[self] ??= self;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:201:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(this)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:202:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(self)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:218:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(this)[this] ??= this;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:219:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(self)[self] ??= self;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    : super core::Object::•()
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  operator [](self::Class cls) → self::Class
+    return new self::Class::•();
+  operator []=(self::Class cls, self::Class value) → void {}
+  operator +(self::Class cls) → self::Class
+    return cls;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final self::Map<self::Class, self::Class> #t1 = map in #t1.{self::Map::[]}(this).{core::Object::==}(null) ?{self::Class} #t1.{self::Map::[]=}(this, this) : null;
+    let final self::Map<self::Class, self::Class> #t2 = map in let final self::Class #t3 = self in #t2.{self::Map::[]}(#t3).{core::Object::==}(null) ?{self::Class} #t2.{self::Map::[]=}(#t3, self) : null;
+    map.{self::Map::[]=}(this, this);
+    map.{self::Map::[]=}(self, self);
+    map.{self::Map::[]}(this);
+    map.{self::Map::[]}(self);
+    let final self::Map<self::Class, self::Class> #t4 = map in #t4.{self::Map::[]=}(this, #t4.{self::Map::[]}(this).{self::Class::+}(this));
+    let final self::Map<self::Class, self::Class> #t5 = map in let final self::Class #t6 = self in #t5.{self::Map::[]=}(#t6, #t5.{self::Map::[]}(#t6).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Map<self::Class, self::Class> #t7 = map in let final self::Class #t8 = #t7.{self::Map::[]}(this) in #t8.{core::Object::==}(null) ?{self::Class} let final void #t9 = #t7.{self::Map::[]=}(this, this) in this : #t8;
+    v = let final self::Map<self::Class, self::Class> #t10 = map in let final self::Class #t11 = self in let final self::Class #t12 = #t10.{self::Map::[]}(#t11) in #t12.{core::Object::==}(null) ?{self::Class} let final self::Class #t13 = self in let final void #t14 = #t10.{self::Map::[]=}(#t11, #t13) in #t13 : #t12;
+    v = let final self::Map<self::Class, self::Class> #t15 = map in let final void #t16 = #t15.{self::Map::[]=}(this, this) in this;
+    v = let final self::Map<self::Class, self::Class> #t17 = map in let final self::Class #t18 = self in let final self::Class #t19 = self in let final void #t20 = #t17.{self::Map::[]=}(#t18, #t19) in #t19;
+    v = map.{self::Map::[]}(this);
+    v = map.{self::Map::[]}(self);
+    v = let final self::Map<self::Class, self::Class> #t21 = map in let final self::Class #t22 = #t21.{self::Map::[]}(this).{self::Class::+}(this) in let final void #t23 = #t21.{self::Map::[]=}(this, #t22) in #t22;
+    v = let final self::Map<self::Class, self::Class> #t24 = map in let final self::Class #t25 = self in let final self::Class #t26 = #t24.{self::Map::[]}(#t25).{self::Class::+}(self) in let final void #t27 = #t24.{self::Map::[]=}(#t25, #t26) in #t26;
+  }
+  method implicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t28 = i in self::Extension|[](#t28, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t28, this, this) : null;
+    let final core::int #t29 = i in let final self::Class #t30 = self in self::Extension|[](#t29, #t30).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t29, #t30, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t31 = i in self::Extension|[]=(#t31, this, self::Extension|[](#t31, this).{self::Class::+}(this));
+    let final core::int #t32 = i in let final self::Class #t33 = self in self::Extension|[]=(#t32, #t33, self::Extension|[](#t32, #t33).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t34 = i in let final self::Class #t35 = self::Extension|[](#t34, this) in #t35.{core::Object::==}(null) ?{self::Class} let final void #t36 = self::Extension|[]=(#t34, this, this) in this : #t35;
+    v = let final core::int #t37 = i in let final self::Class #t38 = self in let final self::Class #t39 = self::Extension|[](#t37, #t38) in #t39.{core::Object::==}(null) ?{self::Class} let final self::Class #t40 = self in let final void #t41 = self::Extension|[]=(#t37, #t38, #t40) in #t40 : #t39;
+    v = let final core::int #t42 = i in let final void #t43 = self::Extension|[]=(#t42, this, this) in this;
+    v = let final core::int #t44 = i in let final self::Class #t45 = self in let final self::Class #t46 = self in let final void #t47 = self::Extension|[]=(#t44, #t45, #t46) in #t46;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t48 = i in let final self::Class #t49 = self::Extension|[](#t48, this).{self::Class::+}(this) in let final void #t50 = self::Extension|[]=(#t48, this, #t49) in #t49;
+    v = let final core::int #t51 = i in let final self::Class #t52 = self in let final self::Class #t53 = self::Extension|[](#t51, #t52).{self::Class::+}(self) in let final void #t54 = self::Extension|[]=(#t51, #t52, #t53) in #t53;
+  }
+  method explicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t55 = i in self::Extension|[](#t55, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t55, this, this) : null;
+    let final core::int #t56 = i in let final self::Class #t57 = self in self::Extension|[](#t56, #t57).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t56, #t57, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t58 = i in self::Extension|[]=(#t58, this, self::Extension|[](#t58, this).{self::Class::+}(this));
+    let final core::int #t59 = i in let final self::Class #t60 = self in self::Extension|[]=(#t59, #t60, self::Extension|[](#t59, #t60).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t61 = i in let final self::Class #t62 = self::Extension|[](#t61, this) in #t62.{core::Object::==}(null) ?{self::Class} let final void #t63 = self::Extension|[]=(#t61, this, this) in this : #t62;
+    v = let final core::int #t64 = i in let final self::Class #t65 = self in let final self::Class #t66 = self::Extension|[](#t64, #t65) in #t66.{core::Object::==}(null) ?{self::Class} let final self::Class #t67 = self in let final void #t68 = self::Extension|[]=(#t64, #t65, #t67) in #t67 : #t66;
+    v = let final core::int #t69 = i in let final void #t70 = self::Extension|[]=(#t69, this, this) in this;
+    v = let final core::int #t71 = i in let final self::Class #t72 = self in let final void #t73 = self::Extension|[]=(#t71, self, #t72) in #t72;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t74 = i in let final self::Class #t75 = self::Extension|[](#t74, this).{self::Class::+}(this) in let final void #t76 = self::Extension|[]=(#t74, this, #t75) in #t75;
+    v = let final core::int #t77 = i in let final self::Class #t78 = self in let final self::Class #t79 = self::Extension|[](#t77, #t78).{self::Class::+}(self) in let final void #t80 = self::Extension|[]=(#t77, #t78, #t79) in #t79;
+  }
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    super.{self::Class::[]}(this).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(this, this) : null;
+    let final self::Class #t81 = self in super.{self::Class::[]}(#t81).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(#t81, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    let final self::Class #t82 = self in super.{self::Class::[]=}(#t82, super.{self::Class::[]}(#t82).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class #t83 = super.{self::Class::[]}(this) in #t83.{core::Object::==}(null) ?{self::Class} let final void #t84 = super.{self::Class::[]=}(this, this) in this : #t83;
+    v = let final self::Class #t85 = self in let final self::Class #t86 = super.{self::Class::[]}(#t85) in #t86.{core::Object::==}(null) ?{self::Class} let final self::Class #t87 = self in let final void #t88 = super.{self::Class::[]=}(#t85, #t87) in #t87 : #t86;
+    v = let final void #t89 = super.{self::Class::[]=}(this, this) in this;
+    v = let final self::Class #t90 = self in let final self::Class #t91 = self in let final void #t92 = super.{self::Class::[]=}(#t90, #t91) in #t91;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class #t93 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t94 = super.{self::Class::[]=}(this, #t93) in #t93;
+    v = let final self::Class #t95 = self in let final self::Class #t96 = super.{self::Class::[]}(#t95).{self::Class::+}(self) in let final void #t97 = super.{self::Class::[]=}(#t95, #t96) in #t96;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    : super core::Object::•()
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t98 = self in let final self::Class2 #t99 = self in self::Extension2|[](#t98, #t99).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t98, #t99, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t100 = self in let final self::Class2 #t101 = self in self::Extension2|[]=(#t100, #t101, self::Extension2|[](#t100, #t101).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t102 = self::Extension2|[](this, this) in #t102.{core::Object::==}(null) ?{self::Class2} let final void #t103 = self::Extension2|[]=(this, this, this) in this : #t102;
+    v = let final self::Class2 #t104 = self in let final self::Class2 #t105 = self in let final self::Class2 #t106 = self::Extension2|[](#t104, #t105) in #t106.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t107 = self in let final void #t108 = self::Extension2|[]=(#t104, #t105, #t107) in #t107 : #t106;
+    v = let final void #t109 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t110 = self in let final self::Class2 #t111 = self in let final self::Class2 #t112 = self in let final void #t113 = self::Extension2|[]=(#t110, #t111, #t112) in #t112;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t114 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t115 = self::Extension2|[]=(this, this, #t114) in #t114;
+    v = let final self::Class2 #t116 = self in let final self::Class2 #t117 = self in let final self::Class2 #t118 = self::Extension2|[](#t116, #t117).{self::Class2::+}(self) in let final void #t119 = self::Extension2|[]=(#t116, #t117, #t118) in #t118;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t120 = self in let final self::Class2 #t121 = self in self::Extension2|[](#t120, #t121).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t120, #t121, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t122 = self in let final self::Class2 #t123 = self in self::Extension2|[]=(#t122, #t123, self::Extension2|[](#t122, #t123).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t124 = self::Extension2|[](this, this) in #t124.{core::Object::==}(null) ?{self::Class2} let final void #t125 = self::Extension2|[]=(this, this, this) in this : #t124;
+    v = let final self::Class2 #t126 = self in let final self::Class2 #t127 = self in let final self::Class2 #t128 = self::Extension2|[](#t126, #t127) in #t128.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t129 = self in let final void #t130 = self::Extension2|[]=(#t126, #t127, #t129) in #t129 : #t128;
+    v = let final void #t131 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t132 = self in let final self::Class2 #t133 = self in let final void #t134 = self::Extension2|[]=(#t132, self, #t133) in #t133;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t135 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t136 = self::Extension2|[]=(this, this, #t135) in #t135;
+    v = let final self::Class2 #t137 = self in let final self::Class2 #t138 = self in let final self::Class2 #t139 = self::Extension2|[](#t137, #t138).{self::Class2::+}(self) in let final void #t140 = self::Extension2|[]=(#t137, #t138, #t139) in #t139;
+  }
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b = true;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void {}
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_async.dart.strong.expect
index 2c50b42..7fe1ab7 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.strong.expect
@@ -28,6 +28,6 @@
   }, (core::Object e, core::StackTrace s) → void {
     completer.{asy::Completer::completeError}(e, s);
   });
-  return completer.{asy::Completer::future};
+  return let final asy::Future<void> #t1 = completer.{asy::Completer::future} in #t1 is asy::Future<void> ?{FutureOr<void>} await #t1 : #t1;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
index b9094ae..d88bd46 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.strong.transformed.expect
@@ -106,6 +106,8 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<void>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
@@ -142,7 +144,15 @@
         }, (core::Object e, core::StackTrace s) → void {
           completer.{asy::Completer::completeError}(e, s);
         });
-        :return_value = completer.{asy::Completer::future};
+        final asy::Future<void> #t7 = completer.{asy::Completer::future};
+        if(#t7 is asy::Future<void>) {
+          [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<void>(:result);
+        }
+        else {
+          :async_temporary_0 = #t7;
+        }
+        :return_value = :async_temporary_0;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_async.dart.weak.expect
index 2c50b42..7fe1ab7 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.weak.expect
@@ -28,6 +28,6 @@
   }, (core::Object e, core::StackTrace s) → void {
     completer.{asy::Completer::completeError}(e, s);
   });
-  return completer.{asy::Completer::future};
+  return let final asy::Future<void> #t1 = completer.{asy::Completer::future} in #t1 is asy::Future<void> ?{FutureOr<void>} await #t1 : #t1;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
index b9094ae..d88bd46 100644
--- a/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_async.dart.weak.transformed.expect
@@ -106,6 +106,8 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<void>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L4:
@@ -142,7 +144,15 @@
         }, (core::Object e, core::StackTrace s) → void {
           completer.{asy::Completer::completeError}(e, s);
         });
-        :return_value = completer.{asy::Completer::future};
+        final asy::Future<void> #t7 = completer.{asy::Completer::future};
+        if(#t7 is asy::Future<void>) {
+          [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<void>(:result);
+        }
+        else {
+          :async_temporary_0 = #t7;
+        }
+        :return_value = :async_temporary_0;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart b/pkg/front_end/testcases/nnbd/return_from_async.dart
new file mode 100644
index 0000000..93e646e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart
@@ -0,0 +1,98 @@
+// 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 'dart:async';
+
+bool caughtFutureOrInt = false;
+
+FutureOr<int> throwFutureOrInt() async {
+  throw 'FutureOr<int>';
+}
+
+Future<int> callFutureOrInt() async {
+  try {
+    return throwFutureOrInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureOrInt = true;
+    return 0;
+  }
+}
+
+bool caughtInt = false;
+
+int throwInt() {
+  throw 'int';
+}
+
+Future<int> callInt() async {
+  try {
+    return throwInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtInt = true;
+    return 0;
+  }
+}
+
+bool caughtFutureInt = false;
+
+Future<int> throwFutureInt() async {
+  throw 'Future<int>';
+}
+
+Future<int> callFutureInt() async {
+  try {
+    return throwFutureInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureInt = true;
+    return 0;
+  }
+}
+
+bool caughtDynamic = false;
+
+dynamic throwDynamic() {
+  throw 'dynamic';
+}
+
+Future<int> callDynamic() async {
+  try {
+    return throwDynamic();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtDynamic = true;
+    return 0;
+  }
+}
+
+bool caughtFutureNum = false;
+
+Future<int> throwFutureNum() async {
+  throw 'Future<num>';
+}
+
+Future<num> callFutureNum() async {
+  try {
+    return throwFutureNum();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureNum = true;
+    return 0;
+  }
+}
+
+void main() async {
+  await callFutureOrInt();
+  if (!caughtFutureOrInt) throw 'Uncaught async return';
+  await callInt();
+  if (!caughtInt) throw 'Uncaught async return';
+  await callFutureInt();
+  if (!caughtFutureInt) throw 'Uncaught async return';
+  await callDynamic();
+  if (!caughtDynamic) throw 'Uncaught async return';
+  await callFutureNum();
+  if (!caughtFutureNum) throw 'Uncaught async return';
+}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.outline.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.outline.expect
new file mode 100644
index 0000000..fce58f8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.outline.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt;
+static field core::bool caughtInt;
+static field core::bool caughtFutureInt;
+static field core::bool caughtDynamic;
+static field core::bool caughtFutureNum;
+static method throwFutureOrInt() → FutureOr<core::int> async 
+  ;
+static method callFutureOrInt() → asy::Future<core::int> async 
+  ;
+static method throwInt() → core::int
+  ;
+static method callInt() → asy::Future<core::int> async 
+  ;
+static method throwFutureInt() → asy::Future<core::int> async 
+  ;
+static method callFutureInt() → asy::Future<core::int> async 
+  ;
+static method throwDynamic() → dynamic
+  ;
+static method callDynamic() → asy::Future<core::int> async 
+  ;
+static method throwFutureNum() → asy::Future<core::int> async 
+  ;
+static method callFutureNum() → asy::Future<core::num> async 
+  ;
+static method main() → void async 
+  ;
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.expect
new file mode 100644
index 0000000..07f9c6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.expect
@@ -0,0 +1,94 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method throwFutureOrInt() → FutureOr<core::int> async {
+  throw "FutureOr<int>";
+}
+static method callFutureOrInt() → asy::Future<core::int> async {
+  try {
+    return let final FutureOr<core::int>#t1 = self::throwFutureOrInt() in #t1 is asy::Future<core::int> ?{FutureOr<core::int>} await #t1 : #t1;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureOrInt = true;
+    return let final core::int #t2 = 0 in #t2 is asy::Future<core::int> ?{FutureOr<core::int>} await #t2 : #t2;
+  }
+}
+static method throwInt() → core::int {
+  throw "int";
+}
+static method callInt() → asy::Future<core::int> async {
+  try {
+    return let final core::int #t3 = self::throwInt() in #t3 is asy::Future<core::int> ?{FutureOr<core::int>} await #t3 : #t3;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtInt = true;
+    return let final core::int #t4 = 0 in #t4 is asy::Future<core::int> ?{FutureOr<core::int>} await #t4 : #t4;
+  }
+}
+static method throwFutureInt() → asy::Future<core::int> async {
+  throw "Future<int>";
+}
+static method callFutureInt() → asy::Future<core::int> async {
+  try {
+    return let final asy::Future<core::int> #t5 = self::throwFutureInt() in #t5 is asy::Future<core::int> ?{FutureOr<core::int>} await #t5 : #t5;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureInt = true;
+    return let final core::int #t6 = 0 in #t6 is asy::Future<core::int> ?{FutureOr<core::int>} await #t6 : #t6;
+  }
+}
+static method throwDynamic() → dynamic {
+  throw "dynamic";
+}
+static method callDynamic() → asy::Future<core::int> async {
+  try {
+    return let final dynamic #t7 = self::throwDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int> in #t7 is asy::Future<core::int> ?{FutureOr<core::int>} await #t7 : #t7;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtDynamic = true;
+    return let final core::int #t8 = 0 in #t8 is asy::Future<core::int> ?{FutureOr<core::int>} await #t8 : #t8;
+  }
+}
+static method throwFutureNum() → asy::Future<core::int> async {
+  throw "Future<num>";
+}
+static method callFutureNum() → asy::Future<core::num> async {
+  try {
+    return let final asy::Future<core::int> #t9 = self::throwFutureNum() in #t9 is asy::Future<core::num> ?{FutureOr<core::num>} await #t9 : #t9;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureNum = true;
+    return let final core::int #t10 = 0 in #t10 is asy::Future<core::num> ?{FutureOr<core::num>} await #t10 : #t10;
+  }
+}
+static method main() → void async {
+  await self::callFutureOrInt();
+  if(!self::caughtFutureOrInt)
+    throw "Uncaught async return";
+  await self::callInt();
+  if(!self::caughtInt)
+    throw "Uncaught async return";
+  await self::callFutureInt();
+  if(!self::caughtFutureInt)
+    throw "Uncaught async return";
+  await self::callDynamic();
+  if(!self::caughtDynamic)
+    throw "Uncaught async return";
+  await self::callFutureNum();
+  if(!self::caughtFutureNum)
+    throw "Uncaught async return";
+}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.transformed.expect
new file mode 100644
index 0000000..5bd5d9f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.strong.transformed.expect
@@ -0,0 +1,433 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method throwFutureOrInt() → FutureOr<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 {
+      #L1:
+      {
+        throw "FutureOr<int>";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureOrInt() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        try {
+          final FutureOr<core::int>#t1 = self::throwFutureOrInt();
+          if(#t1 is asy::Future<core::int>) {
+            [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t1;
+          }
+          :return_value = :async_temporary_0;
+          break #L2;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureOrInt = true;
+          final core::int #t3 = 0;
+          if(#t3 is asy::Future<core::int>) {
+            [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t3;
+          }
+          :return_value = :async_temporary_2;
+          break #L2;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwInt() → core::int {
+  throw "int";
+}
+static method callInt() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        try {
+          final core::int #t5 = self::throwInt();
+          if(#t5 is asy::Future<core::int>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
+          break #L3;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtInt = true;
+          final core::int #t7 = 0;
+          if(#t7 is asy::Future<core::int>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t7;
+          }
+          :return_value = :async_temporary_2;
+          break #L3;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwFutureInt() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 {
+      #L4:
+      {
+        throw "Future<int>";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureInt() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        try {
+          final asy::Future<core::int> #t9 = self::throwFutureInt();
+          if(#t9 is asy::Future<core::int>) {
+            [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t9;
+          }
+          :return_value = :async_temporary_0;
+          break #L5;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureInt = true;
+          final core::int #t11 = 0;
+          if(#t11 is asy::Future<core::int>) {
+            [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t11;
+          }
+          :return_value = :async_temporary_2;
+          break #L5;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwDynamic() → dynamic {
+  throw "dynamic";
+}
+static method callDynamic() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L6:
+      {
+        try {
+          final FutureOr<core::int>#t13 = self::throwDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int>;
+          if(#t13 is asy::Future<core::int>) {
+            [yield] let dynamic #t14 = asy::_awaitHelper(#t13, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t13;
+          }
+          :return_value = :async_temporary_0;
+          break #L6;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtDynamic = true;
+          final core::int #t15 = 0;
+          if(#t15 is asy::Future<core::int>) {
+            [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t15;
+          }
+          :return_value = :async_temporary_2;
+          break #L6;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwFutureNum() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 {
+      #L7:
+      {
+        throw "Future<num>";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureNum() → asy::Future<core::num> /* originally async */ {
+  final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
+  core::bool* :is_sync = false;
+  FutureOr<core::num>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::num>:async_temporary_0;
+  FutureOr<core::num>:async_temporary_1;
+  FutureOr<core::num>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L8:
+      {
+        try {
+          final asy::Future<core::int> #t17 = self::throwFutureNum();
+          if(#t17 is asy::Future<core::num>) {
+            [yield] let dynamic #t18 = asy::_awaitHelper(#t17, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t17;
+          }
+          :return_value = :async_temporary_0;
+          break #L8;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureNum = true;
+          final core::int #t19 = 0;
+          if(#t19 is asy::Future<core::num>) {
+            [yield] let dynamic #t20 = asy::_awaitHelper(#t19, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t19;
+          }
+          :return_value = :async_temporary_2;
+          break #L8;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method main() → void /* 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;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L9:
+      {
+        [yield] let dynamic #t21 = asy::_awaitHelper(self::callFutureOrInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureOrInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t22 = asy::_awaitHelper(self::callInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t23 = asy::_awaitHelper(self::callFutureInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t24 = asy::_awaitHelper(self::callDynamic(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtDynamic)
+          throw "Uncaught async return";
+        [yield] let dynamic #t25 = asy::_awaitHelper(self::callFutureNum(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::num>(:result);
+        if(!self::caughtFutureNum)
+          throw "Uncaught async return";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline.expect
new file mode 100644
index 0000000..bc32d23
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+import 'dart:async';
+
+bool caughtFutureOrInt = false;
+FutureOr<int> throwFutureOrInt() async {}
+Future<int> callFutureOrInt() async {}
+bool caughtInt = false;
+int throwInt() {}
+Future<int> callInt() async {}
+bool caughtFutureInt = false;
+Future<int> throwFutureInt() async {}
+Future<int> callFutureInt() async {}
+bool caughtDynamic = false;
+dynamic throwDynamic() {}
+Future<int> callDynamic() async {}
+bool caughtFutureNum = false;
+Future<int> throwFutureNum() async {}
+Future<num> callFutureNum() async {}
+void main() async {}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7a7e905
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.textual_outline_modelled.expect
@@ -0,0 +1,18 @@
+import 'dart:async';
+
+Future<int> callDynamic() async {}
+Future<int> callFutureInt() async {}
+Future<int> callFutureOrInt() async {}
+Future<int> callInt() async {}
+Future<int> throwFutureInt() async {}
+Future<int> throwFutureNum() async {}
+Future<num> callFutureNum() async {}
+FutureOr<int> throwFutureOrInt() async {}
+bool caughtDynamic = false;
+bool caughtFutureInt = false;
+bool caughtFutureNum = false;
+bool caughtFutureOrInt = false;
+bool caughtInt = false;
+dynamic throwDynamic() {}
+int throwInt() {}
+void main() async {}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.expect
new file mode 100644
index 0000000..07f9c6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.expect
@@ -0,0 +1,94 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method throwFutureOrInt() → FutureOr<core::int> async {
+  throw "FutureOr<int>";
+}
+static method callFutureOrInt() → asy::Future<core::int> async {
+  try {
+    return let final FutureOr<core::int>#t1 = self::throwFutureOrInt() in #t1 is asy::Future<core::int> ?{FutureOr<core::int>} await #t1 : #t1;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureOrInt = true;
+    return let final core::int #t2 = 0 in #t2 is asy::Future<core::int> ?{FutureOr<core::int>} await #t2 : #t2;
+  }
+}
+static method throwInt() → core::int {
+  throw "int";
+}
+static method callInt() → asy::Future<core::int> async {
+  try {
+    return let final core::int #t3 = self::throwInt() in #t3 is asy::Future<core::int> ?{FutureOr<core::int>} await #t3 : #t3;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtInt = true;
+    return let final core::int #t4 = 0 in #t4 is asy::Future<core::int> ?{FutureOr<core::int>} await #t4 : #t4;
+  }
+}
+static method throwFutureInt() → asy::Future<core::int> async {
+  throw "Future<int>";
+}
+static method callFutureInt() → asy::Future<core::int> async {
+  try {
+    return let final asy::Future<core::int> #t5 = self::throwFutureInt() in #t5 is asy::Future<core::int> ?{FutureOr<core::int>} await #t5 : #t5;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureInt = true;
+    return let final core::int #t6 = 0 in #t6 is asy::Future<core::int> ?{FutureOr<core::int>} await #t6 : #t6;
+  }
+}
+static method throwDynamic() → dynamic {
+  throw "dynamic";
+}
+static method callDynamic() → asy::Future<core::int> async {
+  try {
+    return let final dynamic #t7 = self::throwDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int> in #t7 is asy::Future<core::int> ?{FutureOr<core::int>} await #t7 : #t7;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtDynamic = true;
+    return let final core::int #t8 = 0 in #t8 is asy::Future<core::int> ?{FutureOr<core::int>} await #t8 : #t8;
+  }
+}
+static method throwFutureNum() → asy::Future<core::int> async {
+  throw "Future<num>";
+}
+static method callFutureNum() → asy::Future<core::num> async {
+  try {
+    return let final asy::Future<core::int> #t9 = self::throwFutureNum() in #t9 is asy::Future<core::num> ?{FutureOr<core::num>} await #t9 : #t9;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureNum = true;
+    return let final core::int #t10 = 0 in #t10 is asy::Future<core::num> ?{FutureOr<core::num>} await #t10 : #t10;
+  }
+}
+static method main() → void async {
+  await self::callFutureOrInt();
+  if(!self::caughtFutureOrInt)
+    throw "Uncaught async return";
+  await self::callInt();
+  if(!self::caughtInt)
+    throw "Uncaught async return";
+  await self::callFutureInt();
+  if(!self::caughtFutureInt)
+    throw "Uncaught async return";
+  await self::callDynamic();
+  if(!self::caughtDynamic)
+    throw "Uncaught async return";
+  await self::callFutureNum();
+  if(!self::caughtFutureNum)
+    throw "Uncaught async return";
+}
diff --git a/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.transformed.expect
new file mode 100644
index 0000000..5bd5d9f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/return_from_async.dart.weak.transformed.expect
@@ -0,0 +1,433 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method throwFutureOrInt() → FutureOr<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 {
+      #L1:
+      {
+        throw "FutureOr<int>";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureOrInt() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        try {
+          final FutureOr<core::int>#t1 = self::throwFutureOrInt();
+          if(#t1 is asy::Future<core::int>) {
+            [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t1;
+          }
+          :return_value = :async_temporary_0;
+          break #L2;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureOrInt = true;
+          final core::int #t3 = 0;
+          if(#t3 is asy::Future<core::int>) {
+            [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t3;
+          }
+          :return_value = :async_temporary_2;
+          break #L2;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwInt() → core::int {
+  throw "int";
+}
+static method callInt() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        try {
+          final core::int #t5 = self::throwInt();
+          if(#t5 is asy::Future<core::int>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
+          break #L3;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtInt = true;
+          final core::int #t7 = 0;
+          if(#t7 is asy::Future<core::int>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t7;
+          }
+          :return_value = :async_temporary_2;
+          break #L3;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwFutureInt() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 {
+      #L4:
+      {
+        throw "Future<int>";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureInt() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        try {
+          final asy::Future<core::int> #t9 = self::throwFutureInt();
+          if(#t9 is asy::Future<core::int>) {
+            [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t9;
+          }
+          :return_value = :async_temporary_0;
+          break #L5;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureInt = true;
+          final core::int #t11 = 0;
+          if(#t11 is asy::Future<core::int>) {
+            [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t11;
+          }
+          :return_value = :async_temporary_2;
+          break #L5;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwDynamic() → dynamic {
+  throw "dynamic";
+}
+static method callDynamic() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L6:
+      {
+        try {
+          final FutureOr<core::int>#t13 = self::throwDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int>;
+          if(#t13 is asy::Future<core::int>) {
+            [yield] let dynamic #t14 = asy::_awaitHelper(#t13, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t13;
+          }
+          :return_value = :async_temporary_0;
+          break #L6;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtDynamic = true;
+          final core::int #t15 = 0;
+          if(#t15 is asy::Future<core::int>) {
+            [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t15;
+          }
+          :return_value = :async_temporary_2;
+          break #L6;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method throwFutureNum() → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 {
+      #L7:
+      {
+        throw "Future<num>";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureNum() → asy::Future<core::num> /* originally async */ {
+  final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
+  core::bool* :is_sync = false;
+  FutureOr<core::num>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::num>:async_temporary_0;
+  FutureOr<core::num>:async_temporary_1;
+  FutureOr<core::num>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L8:
+      {
+        try {
+          final asy::Future<core::int> #t17 = self::throwFutureNum();
+          if(#t17 is asy::Future<core::num>) {
+            [yield] let dynamic #t18 = asy::_awaitHelper(#t17, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t17;
+          }
+          :return_value = :async_temporary_0;
+          break #L8;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureNum = true;
+          final core::int #t19 = 0;
+          if(#t19 is asy::Future<core::num>) {
+            [yield] let dynamic #t20 = asy::_awaitHelper(#t19, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t19;
+          }
+          :return_value = :async_temporary_2;
+          break #L8;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method main() → void /* 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;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L9:
+      {
+        [yield] let dynamic #t21 = asy::_awaitHelper(self::callFutureOrInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureOrInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t22 = asy::_awaitHelper(self::callInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t23 = asy::_awaitHelper(self::callFutureInt(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t24 = asy::_awaitHelper(self::callDynamic(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtDynamic)
+          throw "Uncaught async return";
+        [yield] let dynamic #t25 = asy::_awaitHelper(self::callFutureNum(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::num>(:result);
+        if(!self::caughtFutureNum)
+          throw "Uncaught async return";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
index ad7fa70..dab461b 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
@@ -103,7 +103,7 @@
 static method returnAsync4() → FutureOr<core::int?> async {}
 static method returnAsync5() → dynamic async {}
 static method returnAsync6() → asy::Future<core::int?> async {
-  return null;
+  return let final Null #t6 = null in #t6 is asy::Future<core::int?> ?{FutureOr<core::int?>} await #t6 : #t6;
 }
 static method returnAsync7() → asy::Future<core::int?> async {}
 static method yieldSync() → core::Iterable<dynamic> sync* {}
@@ -133,7 +133,7 @@
     default:
       {}
   }
-  return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+  return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
 Enum caseReturn2(Enum e) /* error */ {
      ^" in null;
@@ -141,38 +141,38 @@
 static method localFunctions() → dynamic {
   function returnImplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnImplicit() /* error */ {
   ^" in null;
   }
   function returnExplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
     return null; // error
            ^" in null as{TypeError,ForNonNullableByDefault} core::String;
   }
   function returnMixed(core::bool b) → core::String {
     if(b) {
       core::print("foo");
-      return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+      return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
       return null; // error
              ^" in null as{TypeError,ForNonNullableByDefault} core::String;
     }
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnMixed(bool b) /* error */ {
   ^" in null;
   }
   function returnAsync1() → asy::Future<dynamic> async {}
   function returnAsync2() → FutureOr<dynamic> async {}
   function returnAsync3() → FutureOr<core::int> async {
-    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
   }
   function returnAsync4() → FutureOr<core::int?> async {}
   function returnAsync5() → asy::Future<Null> async {}
   function returnAsync6() → asy::Future<core::int?> async {
-    return null;
+    return let final Null #t13 = null in #t13 is asy::Future<core::int?> ?{FutureOr<core::int?>} await #t13 : #t13;
   }
   function returnAsync7() → asy::Future<core::int?> async {}
   function yieldSync() → core::Iterable<dynamic> sync* {}
@@ -202,7 +202,7 @@
       default:
         {}
     }
-    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
   Enum caseReturn2(Enum e) /* error */ {
   ^" in null;
@@ -230,3 +230,9 @@
   #C6 = self::Enum {index:#C4, _name:#C5}
   #C7 = <self::Enum>[#C3, #C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///return_null.dart:
+- Enum. (from org-dartlang-testcase:///return_null.dart:43:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
index dfdc501..af2d2ae 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
@@ -55,6 +55,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -226,11 +227,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::int?>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L6:
       {
-        :return_value = null;
+        final Null #t8 = null;
+        if(#t8 is asy::Future<core::int?>) {
+          [yield] let dynamic #t9 = asy::_awaitHelper(#t8, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<Null>(:result);
+        }
+        else {
+          :async_temporary_0 = #t8;
+        }
+        :return_value = :async_temporary_0;
         break #L6;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -332,7 +343,7 @@
     default:
       {}
   }
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+  return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
 Enum caseReturn2(Enum e) /* error */ {
      ^" in null;
@@ -340,24 +351,24 @@
 static method localFunctions() → dynamic {
   function returnImplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnImplicit() /* error */ {
   ^" in null;
   }
   function returnExplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
     return null; // error
-           ^" in let Null #t11 = null in #t11.==(null) ?{core::String} #t11 as{TypeError,ForNonNullableByDefault} core::String : #t11{core::String};
+           ^" in let Null #t13 = null in #t13.==(null) ?{core::String} #t13 as{TypeError,ForNonNullableByDefault} core::String : #t13{core::String};
   }
   function returnMixed(core::bool b) → core::String {
     if(b) {
       core::print("foo");
-      return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+      return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
       return null; // error
-             ^" in let Null #t13 = null in #t13.==(null) ?{core::String} #t13 as{TypeError,ForNonNullableByDefault} core::String : #t13{core::String};
+             ^" in let Null #t15 = null in #t15.==(null) ?{core::String} #t15 as{TypeError,ForNonNullableByDefault} core::String : #t15{core::String};
     }
-    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnMixed(bool b) /* error */ {
   ^" in null;
   }
@@ -421,7 +432,7 @@
       try {
         #L15:
         {
-          :return_value = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+          :return_value = let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
           break #L15;
@@ -494,11 +505,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::int?>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L18:
         {
-          :return_value = null;
+          final Null #t18 = null;
+          if(#t18 is asy::Future<core::int?>) {
+            [yield] let dynamic #t19 = asy::_awaitHelper(#t18, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Null>(:result);
+          }
+          else {
+            :async_temporary_0 = #t18;
+          }
+          :return_value = :async_temporary_0;
           break #L18;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -600,7 +621,7 @@
       default:
         {}
     }
-    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+    return let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
   Enum caseReturn2(Enum e) /* error */ {
   ^" in null;
@@ -642,4 +663,10 @@
 Evaluated: MethodInvocation @ org-dartlang-testcase:///return_null.dart:75:14 -> BoolConstant(true)
 Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:75:14 -> NullConstant(null)
 Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:75:14 -> NullConstant(null)
-Extra constant evaluation: evaluated: 394, effectively constant: 12
+Extra constant evaluation: evaluated: 422, effectively constant: 12
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///return_null.dart:
+- Enum. (from org-dartlang-testcase:///return_null.dart:43:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
index e747dfe..aef28a4 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
@@ -104,7 +104,7 @@
 static method returnAsync4() → FutureOr<core::int?> async {}
 static method returnAsync5() → dynamic async {}
 static method returnAsync6() → asy::Future<core::int?> async {
-  return null;
+  return let final Null #t6 = null in #t6 is asy::Future<core::int?> ?{FutureOr<core::int?>} await #t6 : #t6;
 }
 static method returnAsync7() → asy::Future<core::int?> async {}
 static method yieldSync() → core::Iterable<dynamic> sync* {}
@@ -137,7 +137,7 @@
     default:
       {}
   }
-  return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+  return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
 Enum caseReturn2(Enum e) /* error */ {
      ^" in null;
@@ -145,38 +145,38 @@
 static method localFunctions() → dynamic {
   function returnImplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnImplicit() /* error */ {
   ^" in null;
   }
   function returnExplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
     return null; // error
            ^" in null as{TypeError,ForNonNullableByDefault} core::String;
   }
   function returnMixed(core::bool b) → core::String {
     if(b) {
       core::print("foo");
-      return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+      return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
       return null; // error
              ^" in null as{TypeError,ForNonNullableByDefault} core::String;
     }
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnMixed(bool b) /* error */ {
   ^" in null;
   }
   function returnAsync1() → asy::Future<dynamic> async {}
   function returnAsync2() → FutureOr<dynamic> async {}
   function returnAsync3() → FutureOr<core::int> async {
-    return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
   }
   function returnAsync4() → FutureOr<core::int?> async {}
   function returnAsync5() → asy::Future<Null> async {}
   function returnAsync6() → asy::Future<core::int?> async {
-    return null;
+    return let final Null #t13 = null in #t13 is asy::Future<core::int?> ?{FutureOr<core::int?>} await #t13 : #t13;
   }
   function returnAsync7() → asy::Future<core::int?> async {}
   function yieldSync() → core::Iterable<dynamic> sync* {}
@@ -209,7 +209,7 @@
       default:
         {}
     }
-    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
   Enum caseReturn2(Enum e) /* error */ {
   ^" in null;
@@ -237,3 +237,9 @@
   #C6 = self::Enum {index:#C4, _name:#C5}
   #C7 = <self::Enum*>[#C3, #C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///return_null.dart:
+- Enum. (from org-dartlang-testcase:///return_null.dart:43:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
index 0c0ae45..dba40e5 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
@@ -227,11 +227,21 @@
   (core::Object, core::StackTrace) → dynamic :async_op_error;
   core::int :await_jump_var = 0;
   dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  FutureOr<core::int?>:async_temporary_0;
   function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
     try {
       #L6:
       {
-        :return_value = null;
+        final Null #t6 = null;
+        if(#t6 is asy::Future<core::int?>) {
+          [yield] let dynamic #t7 = asy::_awaitHelper(#t6, :async_op_then, :async_op_error, :async_op) in null;
+          :async_temporary_0 = _in::unsafeCast<Null>(:result);
+        }
+        else {
+          :async_temporary_0 = #t6;
+        }
+        :return_value = :async_temporary_0;
         break #L6;
       }
       asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -336,7 +346,7 @@
     default:
       {}
   }
-  return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:54:6: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
 Enum caseReturn2(Enum e) /* error */ {
      ^" in null;
@@ -344,24 +354,24 @@
 static method localFunctions() → dynamic {
   function returnImplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:63:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnImplicit() /* error */ {
   ^" in null;
   }
   function returnExplicit() → core::String {
     core::print("foo");
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:69:12: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
     return null; // error
            ^" in null;
   }
   function returnMixed(core::bool b) → core::String {
     if(b) {
       core::print("foo");
-      return let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
+      return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:75:14: Error: The value 'null' can't be returned from a function with return type 'String' because 'String' is not nullable.
       return null; // error
              ^" in null;
     }
-    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:72:3: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String returnMixed(bool b) /* error */ {
   ^" in null;
   }
@@ -425,7 +435,7 @@
       try {
         #L16:
         {
-          :return_value = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+          :return_value = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
           break #L16;
@@ -498,11 +508,21 @@
     (core::Object, core::StackTrace) → dynamic :async_op_error;
     core::int :await_jump_var = 0;
     dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    FutureOr<core::int?>:async_temporary_0;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
         #L19:
         {
-          :return_value = null;
+          final Null #t14 = null;
+          if(#t14 is asy::Future<core::int?>) {
+            [yield] let dynamic #t15 = asy::_awaitHelper(#t14, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<Null>(:result);
+          }
+          else {
+            :async_temporary_0 = #t14;
+          }
+          :return_value = :async_temporary_0;
           break #L19;
         }
         asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -607,7 +627,7 @@
       default:
         {}
     }
-    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
+    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:108:3: Error: A non-null value must be returned since the return type 'Enum' doesn't allow null.
  - 'Enum' is from 'pkg/front_end/testcases/nnbd/return_null.dart'.
   Enum caseReturn2(Enum e) /* error */ {
   ^" in null;
@@ -635,3 +655,9 @@
   #C6 = self::Enum {index:#C4, _name:#C5}
   #C7 = <self::Enum*>[#C3, #C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///return_null.dart:
+- Enum. (from org-dartlang-testcase:///return_null.dart:43:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/spread_if_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/spread_if_null.dart.strong.transformed.expect
index a75a6aa..675eae5 100644
--- a/pkg/front_end/testcases/nnbd/spread_if_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/spread_if_null.dart.strong.transformed.expect
@@ -6,40 +6,40 @@
 static method main() → dynamic {
   core::List<core::int>? list = null;
   core::print( block {
-    final core::List<core::int> #t1 = <core::int>[1, 2];
+    final core::List<core::int> #t1 = core::_GrowableList::_literal2<core::int>(1, 2);
     final core::Iterable<core::int>? #t2 = list;
     if(!#t2.{core::Object::==}(null))
       #t1.{core::List::addAll}{Invariant}(#t2{core::Iterable<core::int>});
     #t1.{core::List::add}{Invariant}(3);
   } =>#t1);
   core::print( block {
-    final core::List<core::int> #t3 = <core::int>[1, 2];
+    final core::List<core::int> #t3 = core::_GrowableList::_literal2<core::int>(1, 2);
     final core::Iterable<core::int>? #t4 = null;
     if(!#t4.{core::Object::==}(null))
       #t3.{core::List::addAll}{Invariant}(#t4{core::Iterable<core::int>});
     #t3.{core::List::add}{Invariant}(3);
   } =>#t3);
   core::List<core::int> list1 = block {
-    final core::List<core::int> #t5 = <core::int>[];
+    final core::List<core::int> #t5 = core::_GrowableList::•<core::int>(0);
     final core::Iterable<core::int>? #t6 = list;
     if(!#t6.{core::Object::==}(null))
       #t5.{core::List::addAll}{Invariant}(#t6{core::Iterable<core::int>});
   } =>#t5;
   core::List<Never> list2 = block {
-    final core::List<Never> #t7 = <Never>[];
+    final core::List<Never> #t7 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t8 = null;
     if(!#t8.{core::Object::==}(null))
       #t7.{core::List::addAll}{Invariant}(#t8{core::Iterable<Never>});
   } =>#t7;
   core::List<core::int> list3 = block {
-    final core::List<core::int> #t9 = <core::int>[1, 2];
+    final core::List<core::int> #t9 = core::_GrowableList::_literal2<core::int>(1, 2);
     final core::Iterable<core::int>? #t10 = list;
     if(!#t10.{core::Object::==}(null))
       #t9.{core::List::addAll}{Invariant}(#t10{core::Iterable<core::int>});
     #t9.{core::List::add}{Invariant}(3);
   } =>#t9;
   core::List<core::int> list4 = block {
-    final core::List<core::int> #t11 = <core::int>[1, 2];
+    final core::List<core::int> #t11 = core::_GrowableList::_literal2<core::int>(1, 2);
     final core::Iterable<core::int>? #t12 = null;
     if(!#t12.{core::Object::==}(null))
       #t11.{core::List::addAll}{Invariant}(#t12{core::Iterable<core::int>});
diff --git a/pkg/front_end/testcases/nnbd/spread_if_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/spread_if_null.dart.weak.transformed.expect
index a75a6aa..675eae5 100644
--- a/pkg/front_end/testcases/nnbd/spread_if_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/spread_if_null.dart.weak.transformed.expect
@@ -6,40 +6,40 @@
 static method main() → dynamic {
   core::List<core::int>? list = null;
   core::print( block {
-    final core::List<core::int> #t1 = <core::int>[1, 2];
+    final core::List<core::int> #t1 = core::_GrowableList::_literal2<core::int>(1, 2);
     final core::Iterable<core::int>? #t2 = list;
     if(!#t2.{core::Object::==}(null))
       #t1.{core::List::addAll}{Invariant}(#t2{core::Iterable<core::int>});
     #t1.{core::List::add}{Invariant}(3);
   } =>#t1);
   core::print( block {
-    final core::List<core::int> #t3 = <core::int>[1, 2];
+    final core::List<core::int> #t3 = core::_GrowableList::_literal2<core::int>(1, 2);
     final core::Iterable<core::int>? #t4 = null;
     if(!#t4.{core::Object::==}(null))
       #t3.{core::List::addAll}{Invariant}(#t4{core::Iterable<core::int>});
     #t3.{core::List::add}{Invariant}(3);
   } =>#t3);
   core::List<core::int> list1 = block {
-    final core::List<core::int> #t5 = <core::int>[];
+    final core::List<core::int> #t5 = core::_GrowableList::•<core::int>(0);
     final core::Iterable<core::int>? #t6 = list;
     if(!#t6.{core::Object::==}(null))
       #t5.{core::List::addAll}{Invariant}(#t6{core::Iterable<core::int>});
   } =>#t5;
   core::List<Never> list2 = block {
-    final core::List<Never> #t7 = <Never>[];
+    final core::List<Never> #t7 = core::_GrowableList::•<Never>(0);
     final core::Iterable<Never>? #t8 = null;
     if(!#t8.{core::Object::==}(null))
       #t7.{core::List::addAll}{Invariant}(#t8{core::Iterable<Never>});
   } =>#t7;
   core::List<core::int> list3 = block {
-    final core::List<core::int> #t9 = <core::int>[1, 2];
+    final core::List<core::int> #t9 = core::_GrowableList::_literal2<core::int>(1, 2);
     final core::Iterable<core::int>? #t10 = list;
     if(!#t10.{core::Object::==}(null))
       #t9.{core::List::addAll}{Invariant}(#t10{core::Iterable<core::int>});
     #t9.{core::List::add}{Invariant}(3);
   } =>#t9;
   core::List<core::int> list4 = block {
-    final core::List<core::int> #t11 = <core::int>[1, 2];
+    final core::List<core::int> #t11 = core::_GrowableList::_literal2<core::int>(1, 2);
     final core::Iterable<core::int>? #t12 = null;
     if(!#t12.{core::Object::==}(null))
       #t11.{core::List::addAll}{Invariant}(#t12{core::Iterable<core::int>});
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect
index 7896b4b..d5ce000 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect
@@ -138,7 +138,7 @@
   let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
   s.{core::String::==}(null) ?{core::String} s = "foo" : null;
   block {
-    final core::List<core::String> #t5 = <core::String>[];
+    final core::List<core::String> #t5 = core::_GrowableList::•<core::String>(0);
     final core::Iterable<core::String>? #t6 = l;
     if(!#t6.{core::Object::==}(null))
       #t5.{core::List::addAll}{Invariant}(#t6{core::Iterable<core::String>});
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline.expect
index d51e2b9..e5febc5 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline.expect
@@ -1,11 +1,17 @@
-extension E ;
-on String (){}
-class A {
-  String operator[](int index) => "foo";
-  void operator[]=(int index, String value) {}
+extension E on String {
+  int get foo => 42;
+  void operator []=(int index, int value) {}
+  int operator [](int index) => 42;
 }
+
+class A {
+  String operator [](int index) => "foo";
+  void operator []=(int index, String value) {}
+}
+
 class B extends A {
   void test() {}
 }
+
 warning(String s, List<String> l, Map<String, int> m) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..77eca74
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class A {
+  String operator [](int index) => "foo";
+  void operator []=(int index, String value) {}
+}
+
+class B extends A {
+  void test() {}
+}
+
+extension E on String {
+  int get foo => 42;
+  int operator [](int index) => 42;
+  void operator []=(int index, int value) {}
+}
+
+main() {}
+warning(String s, List<String> l, Map<String, int> m) {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect
index 7896b4b..d5ce000 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect
@@ -138,7 +138,7 @@
   let final core::String #t4 = s in #t4.{core::String::==}(null) ?{core::String} "foo" : #t4;
   s.{core::String::==}(null) ?{core::String} s = "foo" : null;
   block {
-    final core::List<core::String> #t5 = <core::String>[];
+    final core::List<core::String> #t5 = core::_GrowableList::•<core::String>(0);
     final core::Iterable<core::String>? #t6 = l;
     if(!#t6.{core::Object::==}(null))
       #t5.{core::List::addAll}{Invariant}(#t6{core::Iterable<core::String>});
diff --git a/pkg/front_end/testcases/nnbd/super_bounded_hint.dart b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart
new file mode 100644
index 0000000..1fe49cb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart
@@ -0,0 +1,80 @@
+// 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.
+
+// -------------------------------- Gives hint. -------------------------------
+
+class A<X> {}
+
+typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+
+foo1a(F<A<dynamic>, A<Never>> x) {}
+foo1b(F x) {}
+
+foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+foo2b<X extends F>() {}
+
+class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+
+class Foo3b<X extends F> {}
+
+F<A<dynamic>, A<Never>> foo4a() => throw 42;
+F foo4b() => throw 42;
+
+foo5a({required F<A<dynamic>, A<Never>> x}) {}
+foo5b({required F x}) {}
+
+foo6a() {
+  F<A<dynamic>, A<Never>> x;
+  for (F<A<dynamic>, A<Never>> x in []) {}
+  fooFoo1(F<A<dynamic>, A<Never>> x) {}
+  fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+  F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+  fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+  fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+}
+
+foo6b() {
+  F x;
+  for (F x in []) {}
+  fooFoo1(F x) {}
+  fooFoo2<X extends F>() {}
+  F fooFoo4() => throw 42;
+  fooFoo5({required F x}) {}
+  fooFoo7([F? x]) {}
+}
+
+foo7a([F<A<dynamic>, A<Never>>? x]) {}
+foo7b([F? x]) {}
+
+// ---------------------------- Doesn't give hint. ----------------------------
+
+class B<X extends int> {}
+
+bar1(B<num> x) {}
+
+bar2<X extends B<num>>() {}
+
+class Bar3<X extends B<num>> {}
+
+B<num> bar4() => throw 42;
+
+bar5({required B<num> x}) {}
+
+bar6() {
+  B<num> x;
+  for (B<num> x in []) {}
+  barBar1(B<num> x) {}
+  barBar2<X extends B<num>>() {}
+  B<num> barBar4() => throw 42;
+  barBar5({required B<num> x}) {}
+  barBar7([B<num>? x]) {}
+  new B<dynamic>();
+  new A<B<dynamic>>();
+}
+
+bar7([B<num>? x]) {}
+
+class Bar8 extends B<dynamic> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.outline.expect b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.outline.expect
new file mode 100644
index 0000000..1d220b5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.outline.expect
@@ -0,0 +1,296 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:19:13: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// class Foo3b<X extends F> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo1b(F x) {}
+//         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1b(F x) {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2b<X extends F>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F foo4b() => throw 42;
+//        ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F foo4b() => throw 42;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo5b({required F x}) {}
+//                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5b({required F x}) {}
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo7b([F? x]) {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7b([F? x]) {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:54:13: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar1(B<num> x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:56:6: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2<X extends B<num>>() {}
+//      ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:58:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar3<X extends B<num>> {}
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:60:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+// B<num> bar4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:62:23: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar5({required B<num> x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:76:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar7([B<num>? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:78:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the supertype 'B' of class 'Bar8'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar8 extends B<dynamic> {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends self::A<X> = self::A<dynamic>, contravariant Y extends self::A<Y> = self::A<Never>> = (Y) → X;
+class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    ;
+}
+class Foo3a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::Foo3a<self::Foo3a::X>
+    ;
+}
+class Foo3b<X extends (self::A<Never>) → self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo3b<self::Foo3b::X>
+    ;
+}
+class B<X extends core::int = core::int> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    ;
+}
+class Bar3<X extends self::B<core::num> = self::B<core::num>> extends core::Object {
+  synthetic constructor •() → self::Bar3<self::Bar3::X>
+    ;
+}
+class Bar8 extends self::B<dynamic> {
+  synthetic constructor •() → self::Bar8
+    ;
+}
+static method foo1a((self::A<Never>) → self::A<dynamic> x) → dynamic
+  ;
+static method foo1b((self::A<Never>) → self::A<dynamic> x) → dynamic
+  ;
+static method foo2a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → dynamic
+  ;
+static method foo2b<X extends (self::A<Never>) → self::A<dynamic> = dynamic>() → dynamic
+  ;
+static method foo4a() → (self::A<Never>) → self::A<dynamic>
+  ;
+static method foo4b() → (self::A<Never>) → self::A<dynamic>
+  ;
+static method foo5a({required (self::A<Never>) → self::A<dynamic> x}) → dynamic
+  ;
+static method foo5b({required (self::A<Never>) → self::A<dynamic> x}) → dynamic
+  ;
+static method foo6a() → dynamic
+  ;
+static method foo6b() → dynamic
+  ;
+static method foo7a([(self::A<Never>) →? self::A<dynamic> x]) → dynamic
+  ;
+static method foo7b([(self::A<Never>) →? self::A<dynamic> x]) → dynamic
+  ;
+static method bar1(self::B<core::num> x) → dynamic
+  ;
+static method bar2<X extends self::B<core::num> = self::B<core::num>>() → dynamic
+  ;
+static method bar4() → self::B<core::num>
+  ;
+static method bar5({required self::B<core::num> x}) → dynamic
+  ;
+static method bar6() → dynamic
+  ;
+static method bar7([self::B<core::num>? x]) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.strong.expect b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.strong.expect
new file mode 100644
index 0000000..98725b8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.strong.expect
@@ -0,0 +1,618 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:19:13: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// class Foo3b<X extends F> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo1b(F x) {}
+//         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1b(F x) {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2b<X extends F>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F foo4b() => throw 42;
+//        ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F foo4b() => throw 42;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo5b({required F x}) {}
+//                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5b({required F x}) {}
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo7b([F? x]) {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7b([F? x]) {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:54:13: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar1(B<num> x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:56:6: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2<X extends B<num>>() {}
+//      ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:58:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar3<X extends B<num>> {}
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:60:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+// B<num> bar4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:62:23: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar5({required B<num> x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:76:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar7([B<num>? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:78:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the supertype 'B' of class 'Bar8'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar8 extends B<dynamic> {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:28:27: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F<A<dynamic>, A<Never>> x;
+//                           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:28:27: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F<A<dynamic>, A<Never>> x;
+//                           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:32: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:32: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:37: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:37: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:30:35: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo1(F<A<dynamic>, A<Never>> x) {}
+//                                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:30:35: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo1(F<A<dynamic>, A<Never>> x) {}
+//                                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:31:11: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:31:11: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:32:34: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+//                                  ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:32:34: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:33:45: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+//                                             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:33:45: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:34:37: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+//                                     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:34:37: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:38:5: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F x;
+//     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:38:5: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F x;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:10: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (F x in []) {}
+//          ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:10: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F x in []) {}
+//          ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:15: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (F x in []) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:15: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F x in []) {}
+//               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:40:13: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo1(F x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:40:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo1(F x) {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:41:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo2<X extends F>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:41:11: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo2<X extends F>() {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:42:12: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F fooFoo4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:42:12: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F fooFoo4() => throw 42;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:43:23: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo5({required F x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:43:23: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo5({required F x}) {}
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:44:15: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo7([F? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:44:15: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo7([F? x]) {}
+//               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:65:10: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<num> x;
+//          ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:66:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (B<num> x in []) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:72:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   new B<dynamic>();
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:66:20: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (B<num> x in []) {}
+//                    ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:67:18: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar1(B<num> x) {}
+//                  ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:68:11: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar2<X extends B<num>>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:69:17: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+//   B<num> barBar4() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:70:28: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar5({required B<num> x}) {}
+//                            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:71:20: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar7([B<num>? x]) {}
+//                    ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends self::A<X> = self::A<dynamic>, contravariant Y extends self::A<Y> = self::A<Never>> = (Y) → X;
+class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+class Foo3a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::Foo3a<self::Foo3a::X>
+    : super core::Object::•()
+    ;
+}
+class Foo3b<X extends (self::A<Never>) → self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo3b<self::Foo3b::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::int = core::int> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    : super core::Object::•()
+    ;
+}
+class Bar3<X extends self::B<core::num> = self::B<core::num>> extends core::Object {
+  synthetic constructor •() → self::Bar3<self::Bar3::X>
+    : super core::Object::•()
+    ;
+}
+class Bar8 extends self::B<dynamic> {
+  synthetic constructor •() → self::Bar8
+    : super self::B::•()
+    ;
+}
+static method foo1a((self::A<Never>) → self::A<dynamic> x) → dynamic {}
+static method foo1b((self::A<Never>) → self::A<dynamic> x) → dynamic {}
+static method foo2a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → dynamic {}
+static method foo2b<X extends (self::A<Never>) → self::A<dynamic> = dynamic>() → dynamic {}
+static method foo4a() → (self::A<Never>) → self::A<dynamic>
+  return throw 42;
+static method foo4b() → (self::A<Never>) → self::A<dynamic>
+  return throw 42;
+static method foo5a({required (self::A<Never>) → self::A<dynamic> x = #C1}) → dynamic {}
+static method foo5b({required (self::A<Never>) → self::A<dynamic> x = #C1}) → dynamic {}
+static method foo6a() → dynamic {
+  (self::A<Never>) → self::A<dynamic> x;
+  for ((self::A<Never>) → self::A<dynamic> x in <(self::A<Never>) → self::A<dynamic>>[]) {
+  }
+  function fooFoo1((self::A<Never>) → self::A<dynamic> x) → Null {}
+  function fooFoo2<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → Null {}
+  function fooFoo4() → (self::A<Never>) → self::A<dynamic>
+    return throw 42;
+  function fooFoo5({required (self::A<Never>) → self::A<dynamic> x = #C1}) → Null {}
+  function fooFoo7([(self::A<Never>) →? self::A<dynamic> x = #C1]) → Null {}
+}
+static method foo6b() → dynamic {
+  (self::A<Never>) → self::A<dynamic> x;
+  for ((self::A<Never>) → self::A<dynamic> x in <(self::A<Never>) → self::A<dynamic>>[]) {
+  }
+  function fooFoo1((self::A<Never>) → self::A<dynamic> x) → Null {}
+  function fooFoo2<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → Null {}
+  function fooFoo4() → (self::A<Never>) → self::A<dynamic>
+    return throw 42;
+  function fooFoo5({required (self::A<Never>) → self::A<dynamic> x = #C1}) → Null {}
+  function fooFoo7([(self::A<Never>) →? self::A<dynamic> x = #C1]) → Null {}
+}
+static method foo7a([(self::A<Never>) →? self::A<dynamic> x = #C1]) → dynamic {}
+static method foo7b([(self::A<Never>) →? self::A<dynamic> x = #C1]) → dynamic {}
+static method bar1(self::B<core::num> x) → dynamic {}
+static method bar2<X extends self::B<core::num> = self::B<core::num>>() → dynamic {}
+static method bar4() → self::B<core::num>
+  return throw 42;
+static method bar5({required self::B<core::num> x = #C1}) → dynamic {}
+static method bar6() → dynamic {
+  self::B<core::num> x;
+  for (self::B<core::num> x in <self::B<core::num>>[]) {
+  }
+  function barBar1(self::B<core::num> x) → Null {}
+  function barBar2<X extends self::B<core::num> = self::B<core::num>>() → Null {}
+  function barBar4() → self::B<core::num>
+    return throw 42;
+  function barBar5({required self::B<core::num> x = #C1}) → Null {}
+  function barBar7([self::B<core::num>? x = #C1]) → Null {}
+  new self::B::•<dynamic>();
+  new self::A::•<self::B<dynamic>>();
+}
+static method bar7([self::B<core::num>? x = #C1]) → dynamic {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.strong.transformed.expect
new file mode 100644
index 0000000..edb2e83
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.strong.transformed.expect
@@ -0,0 +1,633 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:19:13: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// class Foo3b<X extends F> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo1b(F x) {}
+//         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1b(F x) {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2b<X extends F>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F foo4b() => throw 42;
+//        ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F foo4b() => throw 42;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo5b({required F x}) {}
+//                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5b({required F x}) {}
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo7b([F? x]) {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7b([F? x]) {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:54:13: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar1(B<num> x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:56:6: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2<X extends B<num>>() {}
+//      ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:58:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar3<X extends B<num>> {}
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:60:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+// B<num> bar4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:62:23: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar5({required B<num> x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:76:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar7([B<num>? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:78:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the supertype 'B' of class 'Bar8'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar8 extends B<dynamic> {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:28:27: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F<A<dynamic>, A<Never>> x;
+//                           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:28:27: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F<A<dynamic>, A<Never>> x;
+//                           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:32: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:32: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:37: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:37: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:30:35: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo1(F<A<dynamic>, A<Never>> x) {}
+//                                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:30:35: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo1(F<A<dynamic>, A<Never>> x) {}
+//                                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:31:11: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:31:11: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:32:34: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+//                                  ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:32:34: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:33:45: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+//                                             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:33:45: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:34:37: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+//                                     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:34:37: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:38:5: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F x;
+//     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:38:5: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F x;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:10: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (F x in []) {}
+//          ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:10: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F x in []) {}
+//          ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:15: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (F x in []) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:15: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F x in []) {}
+//               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:40:13: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo1(F x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:40:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo1(F x) {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:41:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo2<X extends F>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:41:11: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo2<X extends F>() {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:42:12: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F fooFoo4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:42:12: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F fooFoo4() => throw 42;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:43:23: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo5({required F x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:43:23: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo5({required F x}) {}
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:44:15: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo7([F? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:44:15: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo7([F? x]) {}
+//               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:65:10: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<num> x;
+//          ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:66:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (B<num> x in []) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:72:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   new B<dynamic>();
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:66:20: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (B<num> x in []) {}
+//                    ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:67:18: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar1(B<num> x) {}
+//                  ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:68:11: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar2<X extends B<num>>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:69:17: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+//   B<num> barBar4() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:70:28: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar5({required B<num> x}) {}
+//                            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:71:20: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar7([B<num>? x]) {}
+//                    ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends self::A<X> = self::A<dynamic>, contravariant Y extends self::A<Y> = self::A<Never>> = (Y) → X;
+class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+class Foo3a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::Foo3a<self::Foo3a::X>
+    : super core::Object::•()
+    ;
+}
+class Foo3b<X extends (self::A<Never>) → self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo3b<self::Foo3b::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::int = core::int> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    : super core::Object::•()
+    ;
+}
+class Bar3<X extends self::B<core::num> = self::B<core::num>> extends core::Object {
+  synthetic constructor •() → self::Bar3<self::Bar3::X>
+    : super core::Object::•()
+    ;
+}
+class Bar8 extends self::B<dynamic> {
+  synthetic constructor •() → self::Bar8
+    : super self::B::•()
+    ;
+}
+static method foo1a((self::A<Never>) → self::A<dynamic> x) → dynamic {}
+static method foo1b((self::A<Never>) → self::A<dynamic> x) → dynamic {}
+static method foo2a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → dynamic {}
+static method foo2b<X extends (self::A<Never>) → self::A<dynamic> = dynamic>() → dynamic {}
+static method foo4a() → (self::A<Never>) → self::A<dynamic>
+  return throw 42;
+static method foo4b() → (self::A<Never>) → self::A<dynamic>
+  return throw 42;
+static method foo5a({required (self::A<Never>) → self::A<dynamic> x = #C1}) → dynamic {}
+static method foo5b({required (self::A<Never>) → self::A<dynamic> x = #C1}) → dynamic {}
+static method foo6a() → dynamic {
+  (self::A<Never>) → self::A<dynamic> x;
+  {
+    core::Iterator<(self::A<Never>) → self::A<dynamic>> :sync-for-iterator = core::_GrowableList::•<(self::A<Never>) → self::A<dynamic>>(0).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      (self::A<Never>) → self::A<dynamic> x = :sync-for-iterator.{core::Iterator::current};
+      {}
+    }
+  }
+  function fooFoo1((self::A<Never>) → self::A<dynamic> x) → Null {}
+  function fooFoo2<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → Null {}
+  function fooFoo4() → (self::A<Never>) → self::A<dynamic>
+    return throw 42;
+  function fooFoo5({required (self::A<Never>) → self::A<dynamic> x = #C1}) → Null {}
+  function fooFoo7([(self::A<Never>) →? self::A<dynamic> x = #C1]) → Null {}
+}
+static method foo6b() → dynamic {
+  (self::A<Never>) → self::A<dynamic> x;
+  {
+    core::Iterator<(self::A<Never>) → self::A<dynamic>> :sync-for-iterator = core::_GrowableList::•<(self::A<Never>) → self::A<dynamic>>(0).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      (self::A<Never>) → self::A<dynamic> x = :sync-for-iterator.{core::Iterator::current};
+      {}
+    }
+  }
+  function fooFoo1((self::A<Never>) → self::A<dynamic> x) → Null {}
+  function fooFoo2<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → Null {}
+  function fooFoo4() → (self::A<Never>) → self::A<dynamic>
+    return throw 42;
+  function fooFoo5({required (self::A<Never>) → self::A<dynamic> x = #C1}) → Null {}
+  function fooFoo7([(self::A<Never>) →? self::A<dynamic> x = #C1]) → Null {}
+}
+static method foo7a([(self::A<Never>) →? self::A<dynamic> x = #C1]) → dynamic {}
+static method foo7b([(self::A<Never>) →? self::A<dynamic> x = #C1]) → dynamic {}
+static method bar1(self::B<core::num> x) → dynamic {}
+static method bar2<X extends self::B<core::num> = self::B<core::num>>() → dynamic {}
+static method bar4() → self::B<core::num>
+  return throw 42;
+static method bar5({required self::B<core::num> x = #C1}) → dynamic {}
+static method bar6() → dynamic {
+  self::B<core::num> x;
+  {
+    core::Iterator<self::B<core::num>> :sync-for-iterator = core::_GrowableList::•<self::B<core::num>>(0).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      self::B<core::num> x = :sync-for-iterator.{core::Iterator::current};
+      {}
+    }
+  }
+  function barBar1(self::B<core::num> x) → Null {}
+  function barBar2<X extends self::B<core::num> = self::B<core::num>>() → Null {}
+  function barBar4() → self::B<core::num>
+    return throw 42;
+  function barBar5({required self::B<core::num> x = #C1}) → Null {}
+  function barBar7([self::B<core::num>? x = #C1]) → Null {}
+  new self::B::•<dynamic>();
+  new self::A::•<self::B<dynamic>>();
+}
+static method bar7([self::B<core::num>? x = #C1]) → dynamic {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.textual_outline.expect
new file mode 100644
index 0000000..7574af7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.textual_outline.expect
@@ -0,0 +1,36 @@
+class A<X> {}
+
+typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+foo1a(F<A<dynamic>, A<Never>> x) {}
+foo1b(F x) {}
+foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+foo2b<X extends F>() {}
+
+class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+
+class Foo3b<X extends F> {}
+
+F<A<dynamic>, A<Never>> foo4a() => throw 42;
+F foo4b() => throw 42;
+foo5a({required F<A<dynamic>, A<Never>> x}) {}
+foo5b({required F x}) {}
+foo6a() {}
+foo6b() {}
+foo7a([F<A<dynamic>, A<Never>>? x]) {}
+foo7b([F? x]) {}
+
+class B<X extends int> {}
+
+bar1(B<num> x) {}
+bar2<X extends B<num>>() {}
+
+class Bar3<X extends B<num>> {}
+
+B<num> bar4() => throw 42;
+bar5({required B<num> x}) {}
+bar6() {}
+bar7([B<num>? x]) {}
+
+class Bar8 extends B<dynamic> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6dbf57e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.textual_outline_modelled.expect
@@ -0,0 +1,33 @@
+B<num> bar4() => throw 42;
+F<A<dynamic>, A<Never>> foo4a() => throw 42;
+F foo4b() => throw 42;
+bar1(B<num> x) {}
+bar2<X extends B<num>>() {}
+bar5({required B<num> x}) {}
+bar6() {}
+bar7([B<num>? x]) {}
+
+class A<X> {}
+
+class B<X extends int> {}
+
+class Bar3<X extends B<num>> {}
+
+class Bar8 extends B<dynamic> {}
+
+class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+
+class Foo3b<X extends F> {}
+
+foo1a(F<A<dynamic>, A<Never>> x) {}
+foo1b(F x) {}
+foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+foo2b<X extends F>() {}
+foo5a({required F<A<dynamic>, A<Never>> x}) {}
+foo5b({required F x}) {}
+foo6a() {}
+foo6b() {}
+foo7a([F<A<dynamic>, A<Never>>? x]) {}
+foo7b([F? x]) {}
+main() {}
+typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
diff --git a/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.weak.expect b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.weak.expect
new file mode 100644
index 0000000..98725b8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.weak.expect
@@ -0,0 +1,618 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:19:13: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// class Foo3b<X extends F> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo1b(F x) {}
+//         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1b(F x) {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2b<X extends F>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F foo4b() => throw 42;
+//        ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F foo4b() => throw 42;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo5b({required F x}) {}
+//                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5b({required F x}) {}
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo7b([F? x]) {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7b([F? x]) {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:54:13: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar1(B<num> x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:56:6: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2<X extends B<num>>() {}
+//      ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:58:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar3<X extends B<num>> {}
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:60:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+// B<num> bar4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:62:23: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar5({required B<num> x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:76:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar7([B<num>? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:78:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the supertype 'B' of class 'Bar8'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar8 extends B<dynamic> {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:28:27: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F<A<dynamic>, A<Never>> x;
+//                           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:28:27: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F<A<dynamic>, A<Never>> x;
+//                           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:32: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:32: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:37: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:37: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:30:35: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo1(F<A<dynamic>, A<Never>> x) {}
+//                                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:30:35: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo1(F<A<dynamic>, A<Never>> x) {}
+//                                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:31:11: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:31:11: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:32:34: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+//                                  ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:32:34: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:33:45: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+//                                             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:33:45: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:34:37: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+//                                     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:34:37: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:38:5: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F x;
+//     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:38:5: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F x;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:10: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (F x in []) {}
+//          ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:10: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F x in []) {}
+//          ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:15: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (F x in []) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:15: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F x in []) {}
+//               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:40:13: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo1(F x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:40:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo1(F x) {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:41:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo2<X extends F>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:41:11: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo2<X extends F>() {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:42:12: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F fooFoo4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:42:12: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F fooFoo4() => throw 42;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:43:23: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo5({required F x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:43:23: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo5({required F x}) {}
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:44:15: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo7([F? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:44:15: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo7([F? x]) {}
+//               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:65:10: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<num> x;
+//          ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:66:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (B<num> x in []) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:72:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   new B<dynamic>();
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:66:20: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (B<num> x in []) {}
+//                    ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:67:18: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar1(B<num> x) {}
+//                  ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:68:11: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar2<X extends B<num>>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:69:17: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+//   B<num> barBar4() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:70:28: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar5({required B<num> x}) {}
+//                            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:71:20: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar7([B<num>? x]) {}
+//                    ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends self::A<X> = self::A<dynamic>, contravariant Y extends self::A<Y> = self::A<Never>> = (Y) → X;
+class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+class Foo3a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::Foo3a<self::Foo3a::X>
+    : super core::Object::•()
+    ;
+}
+class Foo3b<X extends (self::A<Never>) → self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo3b<self::Foo3b::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::int = core::int> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    : super core::Object::•()
+    ;
+}
+class Bar3<X extends self::B<core::num> = self::B<core::num>> extends core::Object {
+  synthetic constructor •() → self::Bar3<self::Bar3::X>
+    : super core::Object::•()
+    ;
+}
+class Bar8 extends self::B<dynamic> {
+  synthetic constructor •() → self::Bar8
+    : super self::B::•()
+    ;
+}
+static method foo1a((self::A<Never>) → self::A<dynamic> x) → dynamic {}
+static method foo1b((self::A<Never>) → self::A<dynamic> x) → dynamic {}
+static method foo2a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → dynamic {}
+static method foo2b<X extends (self::A<Never>) → self::A<dynamic> = dynamic>() → dynamic {}
+static method foo4a() → (self::A<Never>) → self::A<dynamic>
+  return throw 42;
+static method foo4b() → (self::A<Never>) → self::A<dynamic>
+  return throw 42;
+static method foo5a({required (self::A<Never>) → self::A<dynamic> x = #C1}) → dynamic {}
+static method foo5b({required (self::A<Never>) → self::A<dynamic> x = #C1}) → dynamic {}
+static method foo6a() → dynamic {
+  (self::A<Never>) → self::A<dynamic> x;
+  for ((self::A<Never>) → self::A<dynamic> x in <(self::A<Never>) → self::A<dynamic>>[]) {
+  }
+  function fooFoo1((self::A<Never>) → self::A<dynamic> x) → Null {}
+  function fooFoo2<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → Null {}
+  function fooFoo4() → (self::A<Never>) → self::A<dynamic>
+    return throw 42;
+  function fooFoo5({required (self::A<Never>) → self::A<dynamic> x = #C1}) → Null {}
+  function fooFoo7([(self::A<Never>) →? self::A<dynamic> x = #C1]) → Null {}
+}
+static method foo6b() → dynamic {
+  (self::A<Never>) → self::A<dynamic> x;
+  for ((self::A<Never>) → self::A<dynamic> x in <(self::A<Never>) → self::A<dynamic>>[]) {
+  }
+  function fooFoo1((self::A<Never>) → self::A<dynamic> x) → Null {}
+  function fooFoo2<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → Null {}
+  function fooFoo4() → (self::A<Never>) → self::A<dynamic>
+    return throw 42;
+  function fooFoo5({required (self::A<Never>) → self::A<dynamic> x = #C1}) → Null {}
+  function fooFoo7([(self::A<Never>) →? self::A<dynamic> x = #C1]) → Null {}
+}
+static method foo7a([(self::A<Never>) →? self::A<dynamic> x = #C1]) → dynamic {}
+static method foo7b([(self::A<Never>) →? self::A<dynamic> x = #C1]) → dynamic {}
+static method bar1(self::B<core::num> x) → dynamic {}
+static method bar2<X extends self::B<core::num> = self::B<core::num>>() → dynamic {}
+static method bar4() → self::B<core::num>
+  return throw 42;
+static method bar5({required self::B<core::num> x = #C1}) → dynamic {}
+static method bar6() → dynamic {
+  self::B<core::num> x;
+  for (self::B<core::num> x in <self::B<core::num>>[]) {
+  }
+  function barBar1(self::B<core::num> x) → Null {}
+  function barBar2<X extends self::B<core::num> = self::B<core::num>>() → Null {}
+  function barBar4() → self::B<core::num>
+    return throw 42;
+  function barBar5({required self::B<core::num> x = #C1}) → Null {}
+  function barBar7([self::B<core::num>? x = #C1]) → Null {}
+  new self::B::•<dynamic>();
+  new self::A::•<self::B<dynamic>>();
+}
+static method bar7([self::B<core::num>? x = #C1]) → dynamic {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.weak.transformed.expect
new file mode 100644
index 0000000..edb2e83
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/super_bounded_hint.dart.weak.transformed.expect
@@ -0,0 +1,633 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:19:13: Error: Generic type 'F' can't be used without type arguments in a type variable bound.
+// Try providing type arguments to 'F' here.
+// class Foo3b<X extends F> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: Bound of this variable references variable 'X' from the same declaration.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:11:31: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1a(F<A<dynamic>, A<Never>> x) {}
+//                               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo1b(F x) {}
+//         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:12:9: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo1b(F x) {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:14:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2a<X extends F<A<dynamic>, A<Never>>>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo2b<X extends F>() {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:15:7: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo2b<X extends F>() {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:17:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// class Foo3a<X extends F<A<dynamic>, A<Never>>> {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:21:30: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F<A<dynamic>, A<Never>> foo4a() => throw 42;
+//                              ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// F foo4b() => throw 42;
+//        ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:22:8: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// F foo4b() => throw 42;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:24:41: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5a({required F<A<dynamic>, A<Never>> x}) {}
+//                                         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo5b({required F x}) {}
+//                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:25:19: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo5b({required F x}) {}
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:47:33: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7a([F<A<dynamic>, A<Never>>? x]) {}
+//                                 ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// foo7b([F? x]) {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:48:11: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+// foo7b([F? x]) {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:54:13: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar1(B<num> x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:56:6: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2<X extends B<num>>() {}
+//      ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:58:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar3<X extends B<num>> {}
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:60:12: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+// B<num> bar4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:62:23: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar5({required B<num> x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:76:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// bar7([B<num>? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:78:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the supertype 'B' of class 'Bar8'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar8 extends B<dynamic> {}
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:28:27: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F<A<dynamic>, A<Never>> x;
+//                           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:28:27: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F<A<dynamic>, A<Never>> x;
+//                           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:32: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:32: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:37: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:29:37: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F<A<dynamic>, A<Never>> x in []) {}
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:30:35: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo1(F<A<dynamic>, A<Never>> x) {}
+//                                   ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:30:35: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo1(F<A<dynamic>, A<Never>> x) {}
+//                                   ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:31:11: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:31:11: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo2<X extends F<A<dynamic>, A<Never>>>() {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:32:34: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+//                                  ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:32:34: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F<A<dynamic>, A<Never>> fooFoo4() => throw 42;
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:33:45: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+//                                             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:33:45: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo5({required F<A<dynamic>, A<Never>> x}) {}
+//                                             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:34:37: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+//                                     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:34:37: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo7([F<A<dynamic>, A<Never>>? x]) {}
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:38:5: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F x;
+//     ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:38:5: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F x;
+//     ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:10: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (F x in []) {}
+//          ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:10: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F x in []) {}
+//          ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:15: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (F x in []) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:39:15: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   for (F x in []) {}
+//               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:40:13: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo1(F x) {}
+//             ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:40:13: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo1(F x) {}
+//             ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:41:11: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo2<X extends F>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:41:11: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo2<X extends F>() {}
+//           ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:42:12: Error: Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F' in the return type.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   F fooFoo4() => throw 42;
+//            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:42:12: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   F fooFoo4() => throw 42;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:43:23: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo5({required F x}) {}
+//                       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:43:23: Context: If you want 'F<A<dynamic>, A<Never>>' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo5({required F x}) {}
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:44:15: Error: Inferred type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'F'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   fooFoo7([F? x]) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef F<X extends A<X>, Y extends A<Y>> = X Function(Y);
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:44:15: Context: If you want 'F<A<dynamic>, A<Never>>?' to be a super-bounded type, note that the inverted type 'F<A<Never>, A<Object?>>?' must then satisfy its bounds, which it does not.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/super_bounded_hint.dart'.
+//  - 'Object' is from 'dart:core'.
+//   fooFoo7([F? x]) {}
+//               ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:65:10: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<num> x;
+//          ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:66:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   for (B<num> x in []) {}
+//               ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:72:7: Error: Type argument 'dynamic' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   new B<dynamic>();
+//       ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:66:20: Error: Inferred type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   for (B<num> x in []) {}
+//                    ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:67:18: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar1(B<num> x) {}
+//                  ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:68:11: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar2<X extends B<num>>() {}
+//           ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:69:17: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+//   B<num> barBar4() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:70:28: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar5({required B<num> x}) {}
+//                            ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:71:20: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar7([B<num>? x]) {}
+//                    ^
+// pkg/front_end/testcases/nnbd/super_bounded_hint.dart:52:9: Context: This is the type variable whose bound isn't conformed to.
+// class B<X extends int> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends self::A<X> = self::A<dynamic>, contravariant Y extends self::A<Y> = self::A<Never>> = (Y) → X;
+class A<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+class Foo3a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::Foo3a<self::Foo3a::X>
+    : super core::Object::•()
+    ;
+}
+class Foo3b<X extends (self::A<Never>) → self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::Foo3b<self::Foo3b::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::int = core::int> extends core::Object {
+  synthetic constructor •() → self::B<self::B::X>
+    : super core::Object::•()
+    ;
+}
+class Bar3<X extends self::B<core::num> = self::B<core::num>> extends core::Object {
+  synthetic constructor •() → self::Bar3<self::Bar3::X>
+    : super core::Object::•()
+    ;
+}
+class Bar8 extends self::B<dynamic> {
+  synthetic constructor •() → self::Bar8
+    : super self::B::•()
+    ;
+}
+static method foo1a((self::A<Never>) → self::A<dynamic> x) → dynamic {}
+static method foo1b((self::A<Never>) → self::A<dynamic> x) → dynamic {}
+static method foo2a<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → dynamic {}
+static method foo2b<X extends (self::A<Never>) → self::A<dynamic> = dynamic>() → dynamic {}
+static method foo4a() → (self::A<Never>) → self::A<dynamic>
+  return throw 42;
+static method foo4b() → (self::A<Never>) → self::A<dynamic>
+  return throw 42;
+static method foo5a({required (self::A<Never>) → self::A<dynamic> x = #C1}) → dynamic {}
+static method foo5b({required (self::A<Never>) → self::A<dynamic> x = #C1}) → dynamic {}
+static method foo6a() → dynamic {
+  (self::A<Never>) → self::A<dynamic> x;
+  {
+    core::Iterator<(self::A<Never>) → self::A<dynamic>> :sync-for-iterator = core::_GrowableList::•<(self::A<Never>) → self::A<dynamic>>(0).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      (self::A<Never>) → self::A<dynamic> x = :sync-for-iterator.{core::Iterator::current};
+      {}
+    }
+  }
+  function fooFoo1((self::A<Never>) → self::A<dynamic> x) → Null {}
+  function fooFoo2<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → Null {}
+  function fooFoo4() → (self::A<Never>) → self::A<dynamic>
+    return throw 42;
+  function fooFoo5({required (self::A<Never>) → self::A<dynamic> x = #C1}) → Null {}
+  function fooFoo7([(self::A<Never>) →? self::A<dynamic> x = #C1]) → Null {}
+}
+static method foo6b() → dynamic {
+  (self::A<Never>) → self::A<dynamic> x;
+  {
+    core::Iterator<(self::A<Never>) → self::A<dynamic>> :sync-for-iterator = core::_GrowableList::•<(self::A<Never>) → self::A<dynamic>>(0).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      (self::A<Never>) → self::A<dynamic> x = :sync-for-iterator.{core::Iterator::current};
+      {}
+    }
+  }
+  function fooFoo1((self::A<Never>) → self::A<dynamic> x) → Null {}
+  function fooFoo2<X extends (self::A<Never>) → self::A<dynamic> = (self::A<Never>) → self::A<dynamic>>() → Null {}
+  function fooFoo4() → (self::A<Never>) → self::A<dynamic>
+    return throw 42;
+  function fooFoo5({required (self::A<Never>) → self::A<dynamic> x = #C1}) → Null {}
+  function fooFoo7([(self::A<Never>) →? self::A<dynamic> x = #C1]) → Null {}
+}
+static method foo7a([(self::A<Never>) →? self::A<dynamic> x = #C1]) → dynamic {}
+static method foo7b([(self::A<Never>) →? self::A<dynamic> x = #C1]) → dynamic {}
+static method bar1(self::B<core::num> x) → dynamic {}
+static method bar2<X extends self::B<core::num> = self::B<core::num>>() → dynamic {}
+static method bar4() → self::B<core::num>
+  return throw 42;
+static method bar5({required self::B<core::num> x = #C1}) → dynamic {}
+static method bar6() → dynamic {
+  self::B<core::num> x;
+  {
+    core::Iterator<self::B<core::num>> :sync-for-iterator = core::_GrowableList::•<self::B<core::num>>(0).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      self::B<core::num> x = :sync-for-iterator.{core::Iterator::current};
+      {}
+    }
+  }
+  function barBar1(self::B<core::num> x) → Null {}
+  function barBar2<X extends self::B<core::num> = self::B<core::num>>() → Null {}
+  function barBar4() → self::B<core::num>
+    return throw 42;
+  function barBar5({required self::B<core::num> x = #C1}) → Null {}
+  function barBar7([self::B<core::num>? x = #C1]) → Null {}
+  new self::B::•<dynamic>();
+  new self::A::•<self::B<dynamic>>();
+}
+static method bar7([self::B<core::num>? x = #C1]) → dynamic {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect
index daebafc..7857870 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect
@@ -110,3 +110,9 @@
   #C7 = <self::Enum>[#C3, #C6]
   #C8 = null
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch_nullable_enum.dart:
+- Enum. (from org-dartlang-testcase:///switch_nullable_enum.dart:5:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect
index daebafc..7857870 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect
@@ -110,3 +110,9 @@
   #C7 = <self::Enum>[#C3, #C6]
   #C8 = null
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch_nullable_enum.dart:
+- Enum. (from org-dartlang-testcase:///switch_nullable_enum.dart:5:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect
index 28d2d15..e1e6175 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect
@@ -114,3 +114,9 @@
   #C7 = <self::Enum*>[#C3, #C6]
   #C8 = null
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch_nullable_enum.dart:
+- Enum. (from org-dartlang-testcase:///switch_nullable_enum.dart:5:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect
index 28d2d15..e1e6175 100644
--- a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect
@@ -114,3 +114,9 @@
   #C7 = <self::Enum*>[#C3, #C6]
   #C8 = null
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch_nullable_enum.dart:
+- Enum. (from org-dartlang-testcase:///switch_nullable_enum.dart:5:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.expect
index c678c28..0d7d320 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.expect
@@ -99,3 +99,12 @@
   #C6 = 123
   #C7 = self::D {foo:#C6}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch_redesign_types.dart:
+- D. (from org-dartlang-testcase:///switch_redesign_types.dart:23:9)
+- B. (from org-dartlang-testcase:///switch_redesign_types.dart:15:9)
+- A. (from org-dartlang-testcase:///switch_redesign_types.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C. (from org-dartlang-testcase:///switch_redesign_types.dart:19:9)
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.transformed.expect
index c678c28..0d7d320 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.transformed.expect
@@ -99,3 +99,12 @@
   #C6 = 123
   #C7 = self::D {foo:#C6}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch_redesign_types.dart:
+- D. (from org-dartlang-testcase:///switch_redesign_types.dart:23:9)
+- B. (from org-dartlang-testcase:///switch_redesign_types.dart:15:9)
+- A. (from org-dartlang-testcase:///switch_redesign_types.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C. (from org-dartlang-testcase:///switch_redesign_types.dart:19:9)
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.expect
index c678c28..0d7d320 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.expect
@@ -99,3 +99,12 @@
   #C6 = 123
   #C7 = self::D {foo:#C6}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch_redesign_types.dart:
+- D. (from org-dartlang-testcase:///switch_redesign_types.dart:23:9)
+- B. (from org-dartlang-testcase:///switch_redesign_types.dart:15:9)
+- A. (from org-dartlang-testcase:///switch_redesign_types.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C. (from org-dartlang-testcase:///switch_redesign_types.dart:19:9)
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.transformed.expect
index c678c28..0d7d320 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.transformed.expect
@@ -99,3 +99,12 @@
   #C6 = 123
   #C7 = self::D {foo:#C6}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///switch_redesign_types.dart:
+- D. (from org-dartlang-testcase:///switch_redesign_types.dart:23:9)
+- B. (from org-dartlang-testcase:///switch_redesign_types.dart:15:9)
+- A. (from org-dartlang-testcase:///switch_redesign_types.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- C. (from org-dartlang-testcase:///switch_redesign_types.dart:19:9)
diff --git a/pkg/front_end/testcases/nnbd/uninitialized_non_nullable_late_fields.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/uninitialized_non_nullable_late_fields.dart.textual_outline.expect
index 7432afc..2fcb7a6 100644
--- a/pkg/front_end/testcases/nnbd/uninitialized_non_nullable_late_fields.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/uninitialized_non_nullable_late_fields.dart.textual_outline.expect
@@ -1,7 +1,7 @@
 class A {
-  late int ;
-  x;
+  late int x;
   A.foo(this.x);
   A.bar();
 }
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/uninitialized_non_nullable_late_fields.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/uninitialized_non_nullable_late_fields.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..16afc20
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/uninitialized_non_nullable_late_fields.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class A {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  A.bar();
+  A.foo(this.x);
+  int x;
+}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart
new file mode 100644
index 0000000..1a480bd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart
@@ -0,0 +1,127 @@
+// 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 './const_canonical_type_lib.dart' as oo;
+
+class Check {
+  final _ignored;
+
+  const Check(x, y)
+      : assert(identical(x, y)),
+      _ignored = identical(x, y) ? 42 : 1 ~/ 0;
+}
+
+void expectEqual(x, y) {
+  if (x != y) {
+    throw "Arguments were supposed to be identical.";
+  }
+}
+
+typedef F1 = oo.A<FutureOr<dynamic>> Function();
+typedef F2 = oo.A<dynamic> Function();
+typedef F3 = oo.A<FutureOr<FutureOr<dynamic>?>> Function();
+typedef F4 = oo.A Function();
+
+test1() {
+  const c = oo.A;
+  var v = oo.A;
+
+  expectEqual(c, v);
+  expectEqual(v, oo.c);
+  expectEqual(oo.c, oo.v);
+  expectEqual(oo.v, oo.A);
+  expectEqual(oo.A, c);
+
+  const cf1 = F1;
+  const cf2 = F2;
+  const cf3 = F3;
+  const cf4 = F4;
+  const oocf1 = oo.F1;
+  const oocf2 = oo.F2;
+  const oocf3 = oo.F3;
+  const oocf4 = oo.F4;
+  var vf1 = F1;
+  var vf2 = F2;
+  var vf3 = F3;
+  var vf4 = F4;
+  var oovf1 = oo.F1;
+  var oovf2 = oo.F2;
+  var oovf3 = oo.F3;
+  var oovf4 = oo.F4;
+
+  expectEqual(cf1, cf2);
+  expectEqual(cf2, cf3);
+  expectEqual(cf3, cf4);
+  expectEqual(cf4, oocf1);
+  expectEqual(oocf1, oocf2);
+  expectEqual(oocf2, oocf3);
+  expectEqual(oocf3, oocf4);
+  expectEqual(oocf4, vf1);
+  expectEqual(vf1, vf2);
+  expectEqual(vf2, vf3);
+  expectEqual(vf3, vf4);
+  expectEqual(vf4, oovf1);
+  expectEqual(oovf1, oovf2);
+  expectEqual(oovf2, oovf3);
+  expectEqual(oovf3, oovf4);
+  expectEqual(oovf4, F1);
+  expectEqual(F1, F2);
+  expectEqual(F2, F3);
+  expectEqual(F3, F4);
+  expectEqual(F4, oo.F1);
+  expectEqual(oo.F1, oo.F2);
+  expectEqual(oo.F2, oo.F3);
+  expectEqual(oo.F3, oo.F4);
+  expectEqual(oo.F1, cf1);
+
+  const a1 = oo.A<List<F1>>();
+  const a2 = oo.A<List<F2>>();
+  const a3 = oo.A<List<F3>>();
+  const a4 = oo.A<List<F4>>();
+
+  return const <dynamic>[
+    Check(c, c),
+    Check(c, oo.A),
+    Check(oo.A, oo.A),
+
+    Check(cf1, cf2),
+    Check(cf2, cf3),
+    Check(cf3, cf4),
+    Check(cf4, oocf1),
+    Check(oocf1, oocf2),
+    Check(oocf2, oocf3),
+    Check(oocf3, oocf4),
+    Check(oocf4, F1),
+    Check(F1, F2),
+    Check(F2, F3),
+    Check(F3, F4),
+    Check(F4, oo.F1),
+    Check(oo.F1, oo.F2),
+    Check(oo.F2, oo.F3),
+    Check(oo.F3, oo.F4),
+    Check(oo.F4, cf1),
+
+    Check(a1, a2),
+    Check(a2, a3),
+    Check(a3, a4),
+    Check(a4, oo.a1),
+    Check(oo.a1, oo.a2),
+    Check(oo.a2, oo.a3),
+    Check(oo.a3, oo.a4),
+    Check(oo.a4, const oo.A<List<F1>>()),
+    Check(const oo.A<List<F1>>(), const oo.A<List<F2>>()),
+    Check(const oo.A<List<F2>>(), const oo.A<List<F3>>()),
+    Check(const oo.A<List<F3>>(), const oo.A<List<F4>>()),
+    Check(const oo.A<List<F4>>(), const oo.A<List<oo.F1>>()),
+    Check(const oo.A<List<oo.F1>>(), const oo.A<List<oo.F2>>()),
+    Check(const oo.A<List<oo.F2>>(), const oo.A<List<oo.F3>>()),
+    Check(const oo.A<List<oo.F3>>(), const oo.A<List<oo.F4>>()),
+    Check(const oo.A<List<oo.F4>>(), a1),
+  ];
+}
+
+main() {
+  test1();
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.textual_outline.expect
new file mode 100644
index 0000000..86981f3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.textual_outline.expect
@@ -0,0 +1,17 @@
+import 'dart:async';
+import './const_canonical_type_lib.dart' as oo;
+
+class Check {
+  final _ignored;
+  const Check(x, y)
+      : assert(identical(x, y)),
+        _ignored = identical(x, y) ? 42 : 1 ~/ 0;
+}
+
+void expectEqual(x, y) {}
+typedef F1 = oo.A<FutureOr<dynamic>> Function();
+typedef F2 = oo.A<dynamic> Function();
+typedef F3 = oo.A<FutureOr<FutureOr<dynamic>?>> Function();
+typedef F4 = oo.A Function();
+test1() {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..daaeb63
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+import './const_canonical_type_lib.dart' as oo;
+import 'dart:async';
+
+class Check {
+  const Check(x, y)
+      : assert(identical(x, y)),
+        _ignored = identical(x, y) ? 42 : 1 ~/ 0;
+  final _ignored;
+}
+
+main() {}
+test1() {}
+typedef F1 = oo.A<FutureOr<dynamic>> Function();
+typedef F2 = oo.A<dynamic> Function();
+typedef F3 = oo.A<FutureOr<FutureOr<dynamic>?>> Function();
+typedef F4 = oo.A Function();
+void expectEqual(x, y) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.weak.expect
new file mode 100644
index 0000000..a49b865
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.weak.expect
@@ -0,0 +1,119 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "const_canonical_type_lib.dart" as con;
+import "dart:core" as core;
+
+import "dart:async";
+import "org-dartlang-testcase:///const_canonical_type_lib.dart" as oo;
+
+typedef F1 = () → con::A<FutureOr<dynamic>>;
+typedef F2 = () → con::A<dynamic>;
+typedef F3 = () → con::A<FutureOr<FutureOr<dynamic>?>>;
+typedef F4 = () → con::A<dynamic>;
+class Check extends core::Object /*hasConstConstructor*/  {
+  final field dynamic _ignored;
+  const constructor •(dynamic x, dynamic y) → self::Check
+    : assert(core::identical(x, y)), self::Check::_ignored = core::identical(x, y) ?{core::int} 42 : 1.{core::num::~/}(0), super core::Object::•()
+    ;
+}
+static method expectEqual(dynamic x, dynamic y) → void {
+  if(!x.{core::Object::==}(y)) {
+    throw "Arguments were supposed to be identical.";
+  }
+}
+static method test1() → dynamic {
+  core::Type v = #C1;
+  self::expectEqual(#C1, v);
+  self::expectEqual(v, #C1);
+  self::expectEqual(#C1, con::v);
+  self::expectEqual(con::v, #C1);
+  self::expectEqual(#C1, #C1);
+  core::Type vf1 = #C2;
+  core::Type vf2 = #C2;
+  core::Type vf3 = #C2;
+  core::Type vf4 = #C2;
+  core::Type oovf1 = #C2;
+  core::Type oovf2 = #C2;
+  core::Type oovf3 = #C2;
+  core::Type oovf4 = #C2;
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, vf1);
+  self::expectEqual(vf1, vf2);
+  self::expectEqual(vf2, vf3);
+  self::expectEqual(vf3, vf4);
+  self::expectEqual(vf4, oovf1);
+  self::expectEqual(oovf1, oovf2);
+  self::expectEqual(oovf2, oovf3);
+  self::expectEqual(oovf3, oovf4);
+  self::expectEqual(oovf4, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  return #C5;
+}
+static method main() → dynamic {
+  self::test1();
+}
+
+library;
+import self as con;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef F1 = () →* con::A<FutureOr<dynamic>*>*;
+typedef F2 = () →* con::A<dynamic>*;
+typedef F3 = () →* con::A<FutureOr<FutureOr<dynamic>*>*>*;
+typedef F4 = () →* con::A<dynamic>*;
+class A<X extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → con::A<con::A::X*>*
+    : 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::Type* c = #C1;
+static field core::Type* v = #C1;
+static const field con::A<core::List<() →* con::A<FutureOr<dynamic>*>*>*>* a1 = #C6;
+static const field con::A<core::List<() →* con::A<dynamic>*>*>* a2 = #C6;
+static const field con::A<core::List<() →* con::A<FutureOr<FutureOr<dynamic>*>*>*>*>* a3 = #C6;
+static const field con::A<core::List<() →* con::A<dynamic>*>*>* a4 = #C6;
+
+constants  {
+  #C1 = TypeLiteralConstant(con::A<dynamic>*)
+  #C2 = TypeLiteralConstant(() →* con::A<dynamic>*)
+  #C3 = 42
+  #C4 = self::Check {_ignored:#C3}
+  #C5 = <dynamic>[#C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4]
+  #C6 = con::A<core::List<() →* con::A<dynamic>*>*> {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_canonical_type.dart:
+- A. (from org-dartlang-testcase:///const_canonical_type_lib.dart:10:9)
+- Check. (from org-dartlang-testcase:///const_canonical_type.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+
+org-dartlang-testcase:///const_canonical_type_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- A. (from org-dartlang-testcase:///const_canonical_type_lib.dart:10:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.weak.transformed.expect
new file mode 100644
index 0000000..a49b865
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type.dart.weak.transformed.expect
@@ -0,0 +1,119 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "const_canonical_type_lib.dart" as con;
+import "dart:core" as core;
+
+import "dart:async";
+import "org-dartlang-testcase:///const_canonical_type_lib.dart" as oo;
+
+typedef F1 = () → con::A<FutureOr<dynamic>>;
+typedef F2 = () → con::A<dynamic>;
+typedef F3 = () → con::A<FutureOr<FutureOr<dynamic>?>>;
+typedef F4 = () → con::A<dynamic>;
+class Check extends core::Object /*hasConstConstructor*/  {
+  final field dynamic _ignored;
+  const constructor •(dynamic x, dynamic y) → self::Check
+    : assert(core::identical(x, y)), self::Check::_ignored = core::identical(x, y) ?{core::int} 42 : 1.{core::num::~/}(0), super core::Object::•()
+    ;
+}
+static method expectEqual(dynamic x, dynamic y) → void {
+  if(!x.{core::Object::==}(y)) {
+    throw "Arguments were supposed to be identical.";
+  }
+}
+static method test1() → dynamic {
+  core::Type v = #C1;
+  self::expectEqual(#C1, v);
+  self::expectEqual(v, #C1);
+  self::expectEqual(#C1, con::v);
+  self::expectEqual(con::v, #C1);
+  self::expectEqual(#C1, #C1);
+  core::Type vf1 = #C2;
+  core::Type vf2 = #C2;
+  core::Type vf3 = #C2;
+  core::Type vf4 = #C2;
+  core::Type oovf1 = #C2;
+  core::Type oovf2 = #C2;
+  core::Type oovf3 = #C2;
+  core::Type oovf4 = #C2;
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, vf1);
+  self::expectEqual(vf1, vf2);
+  self::expectEqual(vf2, vf3);
+  self::expectEqual(vf3, vf4);
+  self::expectEqual(vf4, oovf1);
+  self::expectEqual(oovf1, oovf2);
+  self::expectEqual(oovf2, oovf3);
+  self::expectEqual(oovf3, oovf4);
+  self::expectEqual(oovf4, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  self::expectEqual(#C2, #C2);
+  return #C5;
+}
+static method main() → dynamic {
+  self::test1();
+}
+
+library;
+import self as con;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef F1 = () →* con::A<FutureOr<dynamic>*>*;
+typedef F2 = () →* con::A<dynamic>*;
+typedef F3 = () →* con::A<FutureOr<FutureOr<dynamic>*>*>*;
+typedef F4 = () →* con::A<dynamic>*;
+class A<X extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → con::A<con::A::X*>*
+    : 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::Type* c = #C1;
+static field core::Type* v = #C1;
+static const field con::A<core::List<() →* con::A<FutureOr<dynamic>*>*>*>* a1 = #C6;
+static const field con::A<core::List<() →* con::A<dynamic>*>*>* a2 = #C6;
+static const field con::A<core::List<() →* con::A<FutureOr<FutureOr<dynamic>*>*>*>*>* a3 = #C6;
+static const field con::A<core::List<() →* con::A<dynamic>*>*>* a4 = #C6;
+
+constants  {
+  #C1 = TypeLiteralConstant(con::A<dynamic>*)
+  #C2 = TypeLiteralConstant(() →* con::A<dynamic>*)
+  #C3 = 42
+  #C4 = self::Check {_ignored:#C3}
+  #C5 = <dynamic>[#C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4, #C4]
+  #C6 = con::A<core::List<() →* con::A<dynamic>*>*> {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///const_canonical_type.dart:
+- A. (from org-dartlang-testcase:///const_canonical_type_lib.dart:10:9)
+- Check. (from org-dartlang-testcase:///const_canonical_type.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+
+org-dartlang-testcase:///const_canonical_type_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- A. (from org-dartlang-testcase:///const_canonical_type_lib.dart:10:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_canonical_type_lib.dart b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type_lib.dart
new file mode 100644
index 0000000..4c380bd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_canonical_type_lib.dart
@@ -0,0 +1,24 @@
+// 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.6
+
+import 'dart:async';
+
+class A<X> {
+  const A();
+}
+
+typedef F1 = A<FutureOr<dynamic>> Function();
+typedef F2 = A<dynamic> Function();
+typedef F3 = A<FutureOr<FutureOr<dynamic>>> Function();
+typedef F4 = A Function();
+
+const c = A;
+var v = A;
+
+const a1 = A<List<F1>>();
+const a2 = A<List<F2>>();
+const a3 = A<List<F3>>();
+const a4 = A<List<F4>>();
diff --git a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart
index b061200..a5289e6 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart
@@ -21,7 +21,7 @@
 const c11 = null is FutureOr<Never?>;
 const c12 = null is FutureOr<Never>?;
 const e1 = const Class<int>.constructor1(null);
-const e2 = const Class<int?>.constructor1(null);
+const e2 = const Class<List<int>>.constructor1(<Null>[null]);
 const e3 = const Class<Null>.constructor1(null);
 const e4 = const Class<int>.constructor2(null);
 const e5 = const Class<int?>.constructor2(null);
@@ -60,15 +60,17 @@
       "Class<int>.constructor1(null).field");
   expect(true, new Class<int?>.constructor1(null).field,
       "new Class<int?>.constructor1(null).field");
-  // const Class<int?> is evaluated as const Class<int*> in weak mode:
-  expect(!isWeakMode, e2.field, "const Class<int?>.constructor1(null).field");
+  // const Class<List<int>> is evaluated as const Class<List<int*>*> in weak
+  // mode:
+  expect(isWeakMode, e2.field,
+      "const Class<List<int>>.constructor1(<Null>[null]).field");
   expect(new Class<Null>.constructor1(null).field, e3.field,
       "Class<Null>.constructor1(null).field");
   expect(new Class<int>.constructor2(null).field, e4.field,
       "Class<int>.constructor2(null).field");
   expect(true, new Class<int?>.constructor2(null).field,
       "new Class<int?>.constructor2(null).field");
-  // const Class<int?> is evaluated as const Class<int*> in weak mode:
+  // const Class<int?> is evaluated as const Class<int?> in weak mode:
   expect(new Class<int?>.constructor2(null).field, e5.field,
       "Class<int?>.constructor2(null).field");
   expect(new Class<Null>.constructor2(null).field, e6.field,
diff --git a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.textual_outline.expect
index baf0ddd..d5d0290 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.textual_outline.expect
@@ -16,7 +16,7 @@
 const c11 = null is FutureOr<Never?>;
 const c12 = null is FutureOr<Never>?;
 const e1 = const Class<int>.constructor1(null);
-const e2 = const Class<int?>.constructor1(null);
+const e2 = const Class<List<int>>.constructor1(<Null>[null]);
 const e3 = const Class<Null>.constructor1(null);
 const e4 = const Class<int>.constructor2(null);
 const e5 = const Class<int?>.constructor2(null);
diff --git a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.textual_outline_modelled.expect
index 15ed19a8..04b1f5d 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.textual_outline_modelled.expect
@@ -26,7 +26,7 @@
 const e10 = const Class<int>.constructor4(null);
 const e11 = const Class<int?>.constructor4(null);
 const e12 = const Class<Null>.constructor4(null);
-const e2 = const Class<int?>.constructor1(null);
+const e2 = const Class<List<int>>.constructor1(<Null>[null]);
 const e3 = const Class<Null>.constructor1(null);
 const e4 = const Class<int>.constructor2(null);
 const e5 = const Class<int?>.constructor2(null);
diff --git a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.expect
index 470c9c8..cd7b899 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.expect
@@ -36,17 +36,17 @@
 static const field core::bool c11 = #C2;
 static const field core::bool c12 = #C2;
 static const field self::Class<core::int> e1 = #C4;
-static const field self::Class<core::int?> e2 = #C4;
-static const field self::Class<Null> e3 = #C5;
-static const field self::Class<core::int> e4 = #C6;
-static const field self::Class<core::int?> e5 = #C6;
-static const field self::Class<Null> e6 = #C5;
+static const field self::Class<core::List<core::int>> e2 = #C5;
+static const field self::Class<Null> e3 = #C6;
+static const field self::Class<core::int> e4 = #C7;
+static const field self::Class<core::int?> e5 = #C8;
+static const field self::Class<Null> e6 = #C6;
 static const field self::Class<core::int> e7 = #C4;
-static const field self::Class<core::int?> e8 = #C4;
-static const field self::Class<Null> e9 = #C7;
-static const field self::Class<core::int> e10 = #C6;
-static const field self::Class<core::int?> e11 = #C6;
-static const field self::Class<Null> e12 = #C5;
+static const field self::Class<core::int?> e8 = #C9;
+static const field self::Class<Null> e9 = #C10;
+static const field self::Class<core::int> e10 = #C7;
+static const field self::Class<core::int?> e11 = #C8;
+static const field self::Class<Null> e12 = #C6;
 static method main() → dynamic {
   self::expect(null is{ForNonNullableByDefault} core::int?, #C2, "null is int?");
   self::expect(null is{ForNonNullableByDefault} core::int, #C3, "null is int");
@@ -63,19 +63,19 @@
   self::expect(null is{ForNonNullableByDefault} FutureOr<Never>?, #C2, "null is FutureOr<Never>?");
   self::expect(new self::Class::constructor1<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor1(null).field");
   self::expect(true, new self::Class::constructor1<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor1(null).field");
-  self::expect(!self::isWeakMode, (#C4).{self::Class::field}, "const Class<int?>.constructor1(null).field");
-  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor1(null).field");
-  self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor2(null).field");
+  self::expect(self::isWeakMode, (#C5).{self::Class::field}, "const Class<List<int>>.constructor1(<Null>[null]).field");
+  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor1(null).field");
+  self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor2(null).field");
   self::expect(true, new self::Class::constructor2<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor2(null).field");
   self::expect(new self::Class::constructor3<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<Null>.constructor3(null).field");
-  self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int?>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor4(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C10).{self::Class::field}, "Class<Null>.constructor3(null).field");
+  self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor4(null).field");
   con::test();
 }
 static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
@@ -94,24 +94,24 @@
 static const field core::bool* d0 = #C3;
 static const field core::bool* d1 = #C2;
 static const field self::Class<core::int*>* d4 = #C4;
-static const field self::Class<Null>* d5 = #C5;
-static const field self::Class<core::int*>* d6 = #C6;
-static const field self::Class<Null>* d7 = #C5;
+static const field self::Class<Null>* d5 = #C6;
+static const field self::Class<core::int*>* d6 = #C7;
+static const field self::Class<Null>* d7 = #C6;
 static const field self::Class<core::int*>* d8 = #C4;
-static const field self::Class<Null>* d9 = #C7;
-static const field self::Class<core::int*>* d10 = #C6;
-static const field self::Class<Null>* d11 = #C5;
+static const field self::Class<Null>* d9 = #C10;
+static const field self::Class<core::int*>* d10 = #C7;
+static const field self::Class<Null>* d11 = #C6;
 static method test() → dynamic {
   self::expect(null is core::int*, #C3, "null is int (opt-out)");
   self::expect(null is Null, #C2, "null is Null");
   self::expect(new self::Class::constructor1<core::int*>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor1(null).field (opt-out)");
-  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor1(null).field (opt-out)");
-  self::expect(new self::Class::constructor2<core::int*>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor2(null).field (opt-out)");
-  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor2(null).field (opt-out)");
+  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor1(null).field (opt-out)");
+  self::expect(new self::Class::constructor2<core::int*>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor2(null).field (opt-out)");
+  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor2(null).field (opt-out)");
   self::expect(new self::Class::constructor3<core::int*>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor3(null).field (opt-out)");
-  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<Null>.constructor3(null).field (opt-out)");
-  self::expect(new self::Class::constructor4<core::int*>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor4(null).field (opt-out)");
-  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor4(null).field (opt-out)");
+  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C10).{self::Class::field}, "Class<Null>.constructor3(null).field (opt-out)");
+  self::expect(new self::Class::constructor4<core::int*>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor4(null).field (opt-out)");
+  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor4(null).field (opt-out)");
 }
 
 constants  {
@@ -119,7 +119,25 @@
   #C2 = true
   #C3 = false
   #C4 = self::Class<core::int*> {field:#C3}
-  #C5 = self::Class<Null> {field:#C2}
-  #C6 = self::Class<core::int*> {field:#C2}
-  #C7 = self::Class<Null> {field:#C3}
+  #C5 = self::Class<core::List<core::int*>*> {field:#C2}
+  #C6 = self::Class<Null> {field:#C2}
+  #C7 = self::Class<core::int*> {field:#C2}
+  #C8 = self::Class<core::int?> {field:#C2}
+  #C9 = self::Class<core::int?> {field:#C3}
+  #C10 = self::Class<Null> {field:#C3}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_is.dart:
+- Class.constructor1 (from org-dartlang-testcase:///constant_null_is.dart:39:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class.constructor2 (from org-dartlang-testcase:///constant_null_is.dart:40:9)
+- Class.constructor3 (from org-dartlang-testcase:///constant_null_is.dart:41:9)
+- Class.constructor4 (from org-dartlang-testcase:///constant_null_is.dart:42:9)
+
+org-dartlang-testcase:///constant_null_is_lib.dart:
+- Class.constructor1 (from org-dartlang-testcase:///constant_null_is.dart:39:9)
+- Class.constructor2 (from org-dartlang-testcase:///constant_null_is.dart:40:9)
+- Class.constructor3 (from org-dartlang-testcase:///constant_null_is.dart:41:9)
+- Class.constructor4 (from org-dartlang-testcase:///constant_null_is.dart:42:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.transformed.expect
index dc41d03..edf4aad 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.transformed.expect
@@ -36,17 +36,17 @@
 static const field core::bool c11 = #C2;
 static const field core::bool c12 = #C2;
 static const field self::Class<core::int> e1 = #C4;
-static const field self::Class<core::int?> e2 = #C4;
-static const field self::Class<Null> e3 = #C5;
-static const field self::Class<core::int> e4 = #C6;
-static const field self::Class<core::int?> e5 = #C6;
-static const field self::Class<Null> e6 = #C5;
+static const field self::Class<core::List<core::int>> e2 = #C5;
+static const field self::Class<Null> e3 = #C6;
+static const field self::Class<core::int> e4 = #C7;
+static const field self::Class<core::int?> e5 = #C8;
+static const field self::Class<Null> e6 = #C6;
 static const field self::Class<core::int> e7 = #C4;
-static const field self::Class<core::int?> e8 = #C4;
-static const field self::Class<Null> e9 = #C7;
-static const field self::Class<core::int> e10 = #C6;
-static const field self::Class<core::int?> e11 = #C6;
-static const field self::Class<Null> e12 = #C5;
+static const field self::Class<core::int?> e8 = #C9;
+static const field self::Class<Null> e9 = #C10;
+static const field self::Class<core::int> e10 = #C7;
+static const field self::Class<core::int?> e11 = #C8;
+static const field self::Class<Null> e12 = #C6;
 static method main() → dynamic {
   self::expect(null is{ForNonNullableByDefault} core::int?, #C2, "null is int?");
   self::expect(null is{ForNonNullableByDefault} core::int, #C3, "null is int");
@@ -63,19 +63,19 @@
   self::expect(null is{ForNonNullableByDefault} FutureOr<Never>?, #C2, "null is FutureOr<Never>?");
   self::expect(new self::Class::constructor1<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor1(null).field");
   self::expect(true, new self::Class::constructor1<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor1(null).field");
-  self::expect(!self::isWeakMode, (#C4).{self::Class::field}, "const Class<int?>.constructor1(null).field");
-  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor1(null).field");
-  self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor2(null).field");
+  self::expect(self::isWeakMode, (#C5).{self::Class::field}, "const Class<List<int>>.constructor1(<Null>[null]).field");
+  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor1(null).field");
+  self::expect(new self::Class::constructor2<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor2(null).field");
   self::expect(true, new self::Class::constructor2<core::int?>(null).{self::Class::field}, "new Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int?>.constructor2(null).field");
-  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor2(null).field");
+  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor2(null).field");
   self::expect(new self::Class::constructor3<core::int>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int?>.constructor3(null).field");
-  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<Null>.constructor3(null).field");
-  self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int?>.constructor4(null).field");
-  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor4(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<core::int?>(null).{self::Class::field}, (#C9).{self::Class::field}, "Class<int?>.constructor3(null).field");
+  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C10).{self::Class::field}, "Class<Null>.constructor3(null).field");
+  self::expect(new self::Class::constructor4<core::int>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<core::int?>(null).{self::Class::field}, (#C8).{self::Class::field}, "Class<int?>.constructor4(null).field");
+  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor4(null).field");
   con::test();
 }
 static method expect(dynamic expected, dynamic actual, core::String message) → dynamic {
@@ -94,24 +94,24 @@
 static const field core::bool* d0 = #C3;
 static const field core::bool* d1 = #C2;
 static const field self::Class<core::int*>* d4 = #C4;
-static const field self::Class<Null>* d5 = #C5;
-static const field self::Class<core::int*>* d6 = #C6;
-static const field self::Class<Null>* d7 = #C5;
+static const field self::Class<Null>* d5 = #C6;
+static const field self::Class<core::int*>* d6 = #C7;
+static const field self::Class<Null>* d7 = #C6;
 static const field self::Class<core::int*>* d8 = #C4;
-static const field self::Class<Null>* d9 = #C7;
-static const field self::Class<core::int*>* d10 = #C6;
-static const field self::Class<Null>* d11 = #C5;
+static const field self::Class<Null>* d9 = #C10;
+static const field self::Class<core::int*>* d10 = #C7;
+static const field self::Class<Null>* d11 = #C6;
 static method test() → dynamic {
   self::expect(null is core::int*, #C3, "null is int (opt-out)");
   self::expect(null is Null, #C2, "null is Null");
   self::expect(new self::Class::constructor1<core::int*>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor1(null).field (opt-out)");
-  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor1(null).field (opt-out)");
-  self::expect(new self::Class::constructor2<core::int*>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor2(null).field (opt-out)");
-  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor2(null).field (opt-out)");
+  self::expect(new self::Class::constructor1<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor1(null).field (opt-out)");
+  self::expect(new self::Class::constructor2<core::int*>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor2(null).field (opt-out)");
+  self::expect(new self::Class::constructor2<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor2(null).field (opt-out)");
   self::expect(new self::Class::constructor3<core::int*>(null).{self::Class::field}, (#C4).{self::Class::field}, "Class<int>.constructor3(null).field (opt-out)");
-  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<Null>.constructor3(null).field (opt-out)");
-  self::expect(new self::Class::constructor4<core::int*>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<int>.constructor4(null).field (opt-out)");
-  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C5).{self::Class::field}, "Class<Null>.constructor4(null).field (opt-out)");
+  self::expect(new self::Class::constructor3<Null>(null).{self::Class::field}, (#C10).{self::Class::field}, "Class<Null>.constructor3(null).field (opt-out)");
+  self::expect(new self::Class::constructor4<core::int*>(null).{self::Class::field}, (#C7).{self::Class::field}, "Class<int>.constructor4(null).field (opt-out)");
+  self::expect(new self::Class::constructor4<Null>(null).{self::Class::field}, (#C6).{self::Class::field}, "Class<Null>.constructor4(null).field (opt-out)");
 }
 
 constants  {
@@ -119,9 +119,12 @@
   #C2 = true
   #C3 = false
   #C4 = self::Class<core::int*> {field:#C3}
-  #C5 = self::Class<Null> {field:#C2}
-  #C6 = self::Class<core::int*> {field:#C2}
-  #C7 = self::Class<Null> {field:#C3}
+  #C5 = self::Class<core::List<core::int*>*> {field:#C2}
+  #C6 = self::Class<Null> {field:#C2}
+  #C7 = self::Class<core::int*> {field:#C2}
+  #C8 = self::Class<core::int?> {field:#C2}
+  #C9 = self::Class<core::int?> {field:#C3}
+  #C10 = self::Class<Null> {field:#C3}
 }
 
 Extra constant evaluation status:
@@ -141,4 +144,19 @@
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:8:40 -> BoolConstant(true)
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is_lib.dart:24:15 -> BoolConstant(false)
 Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is_lib.dart:25:15 -> BoolConstant(true)
-Extra constant evaluation: evaluated: 139, effectively constant: 16
+Extra constant evaluation: evaluated: 138, effectively constant: 16
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constant_null_is.dart:
+- Class.constructor1 (from org-dartlang-testcase:///constant_null_is.dart:39:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class.constructor2 (from org-dartlang-testcase:///constant_null_is.dart:40:9)
+- Class.constructor3 (from org-dartlang-testcase:///constant_null_is.dart:41:9)
+- Class.constructor4 (from org-dartlang-testcase:///constant_null_is.dart:42:9)
+
+org-dartlang-testcase:///constant_null_is_lib.dart:
+- Class.constructor1 (from org-dartlang-testcase:///constant_null_is.dart:39:9)
+- Class.constructor2 (from org-dartlang-testcase:///constant_null_is.dart:40:9)
+- Class.constructor3 (from org-dartlang-testcase:///constant_null_is.dart:41:9)
+- Class.constructor4 (from org-dartlang-testcase:///constant_null_is.dart:42:9)
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 0124126..584622a 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect
@@ -96,3 +96,12 @@
   #C13 = true
   #C14 = tearoff core::identical
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constants.dart:
+- Class. (from org-dartlang-testcase:///constants_lib.dart:10:9)
+
+org-dartlang-testcase:///constants_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class. (from org-dartlang-testcase:///constants_lib.dart:10:9)
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 0124126..584622a 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
@@ -96,3 +96,12 @@
   #C13 = true
   #C14 = tearoff core::identical
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///constants.dart:
+- Class. (from org-dartlang-testcase:///constants_lib.dart:10:9)
+
+org-dartlang-testcase:///constants_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class. (from org-dartlang-testcase:///constants_lib.dart:10:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart
new file mode 100644
index 0000000..11be33b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart
@@ -0,0 +1,14 @@
+// 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.
+
+// Derived from
+// instantiate_to_bound/non_simple_class_parameterized_typedef_cycle
+
+import 'cyclic_typedef_lib.dart';
+
+class Hest2<TypeX extends Fisk2> {}
+
+typedef Fisk1 = void Function<TypeY extends Hest1>();
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.textual_outline.expect
new file mode 100644
index 0000000..a72af38
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+import 'cyclic_typedef_lib.dart';
+
+class Hest2<TypeX extends Fisk2> {}
+
+typedef Fisk1 = void Function<TypeY extends Hest1>();
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d03bf62
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+import 'cyclic_typedef_lib.dart';
+
+class Hest2<TypeX extends Fisk2> {}
+
+main() {}
+typedef Fisk1 = void Function<TypeY extends Hest1>();
diff --git a/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.weak.expect
new file mode 100644
index 0000000..6fb923f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.weak.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart:10:7: Error: Generic type 'Hest2' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through 'Fisk2'.
+// Try providing type arguments to 'Fisk2' here or to some other raw types in the bounds along the reference chain.
+// class Hest2<TypeX extends Fisk2> {}
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart:10:13: Context: Bound of this variable references raw type 'Fisk2'.
+// class Hest2<TypeX extends Fisk2> {}
+//             ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef_lib.dart:12:31: Context: Bound of this variable references raw type 'Hest2'.
+// typedef Fisk2 = void Function<TypeY extends Hest2>();
+//                               ^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart:12:9: Error: Generic type 'Fisk1' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through 'Hest1'.
+// Try providing type arguments to 'Hest1' here or to some other raw types in the bounds along the reference chain.
+// typedef Fisk1 = void Function<TypeY extends Hest1>();
+//         ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart:12:31: Context: Bound of this variable references raw type 'Hest1'.
+// typedef Fisk1 = void Function<TypeY extends Hest1>();
+//                               ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef_lib.dart:10:13: Context: Bound of this variable references raw type 'Fisk1'.
+// class Hest1<TypeX extends Fisk1> {}
+//             ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///cyclic_typedef_lib.dart";
+
+typedef Fisk1 = <TypeY extends core::Object? = dynamic>() → void;
+class Hest2<TypeX extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hest2<self::Hest2::TypeX%>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "cyclic_typedef.dart" as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///cyclic_typedef.dart";
+
+typedef Fisk2 = <TypeY extends self::Hest2<dynamic> = dynamic>() → void;
+class Hest1<TypeX extends <TypeY extends core::Object? = dynamic>() → void = <TypeY extends core::Object? = dynamic>() → void> extends core::Object {
+  synthetic constructor •() → self2::Hest1<self2::Hest1::TypeX>
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.weak.transformed.expect
new file mode 100644
index 0000000..6fb923f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart.weak.transformed.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart:10:7: Error: Generic type 'Hest2' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through 'Fisk2'.
+// Try providing type arguments to 'Fisk2' here or to some other raw types in the bounds along the reference chain.
+// class Hest2<TypeX extends Fisk2> {}
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart:10:13: Context: Bound of this variable references raw type 'Fisk2'.
+// class Hest2<TypeX extends Fisk2> {}
+//             ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef_lib.dart:12:31: Context: Bound of this variable references raw type 'Hest2'.
+// typedef Fisk2 = void Function<TypeY extends Hest2>();
+//                               ^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart:12:9: Error: Generic type 'Fisk1' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through 'Hest1'.
+// Try providing type arguments to 'Hest1' here or to some other raw types in the bounds along the reference chain.
+// typedef Fisk1 = void Function<TypeY extends Hest1>();
+//         ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef.dart:12:31: Context: Bound of this variable references raw type 'Hest1'.
+// typedef Fisk1 = void Function<TypeY extends Hest1>();
+//                               ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/cyclic_typedef_lib.dart:10:13: Context: Bound of this variable references raw type 'Fisk1'.
+// class Hest1<TypeX extends Fisk1> {}
+//             ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///cyclic_typedef_lib.dart";
+
+typedef Fisk1 = <TypeY extends core::Object? = dynamic>() → void;
+class Hest2<TypeX extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Hest2<self::Hest2::TypeX%>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "cyclic_typedef.dart" as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///cyclic_typedef.dart";
+
+typedef Fisk2 = <TypeY extends self::Hest2<dynamic> = dynamic>() → void;
+class Hest1<TypeX extends <TypeY extends core::Object? = dynamic>() → void = <TypeY extends core::Object? = dynamic>() → void> extends core::Object {
+  synthetic constructor •() → self2::Hest1<self2::Hest1::TypeX>
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef_lib.dart b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef_lib.dart
new file mode 100644
index 0000000..46e47dc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/cyclic_typedef_lib.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Derived from
+// instantiate_to_bound/non_simple_class_parameterized_typedef_cycle
+
+import 'cyclic_typedef.dart';
+
+class Hest1<TypeX extends Fisk1> {}
+
+typedef Fisk2 = void Function<TypeY extends Hest2>();
diff --git a/pkg/front_end/testcases/nnbd_mixed/generic_override.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/generic_override.dart.weak.expect
index e08ec43..30674ab 100644
--- a/pkg/front_end/testcases/nnbd_mixed/generic_override.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/generic_override.dart.weak.expect
@@ -173,6 +173,16 @@
   synthetic constructor •() → gen::LegacyClass3*
     : super self::Class1::•()
     ;
+  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
   abstract member-signature method method1a<T extends core::Object* = dynamic>() → void; -> self::Class1::method1a
   abstract member-signature method method1b<T extends core::Object* = dynamic>() → void; -> self::Class1::method1b
   abstract member-signature method method1c<T extends core::Object* = dynamic>() → void; -> self::Class1::method1c
@@ -185,15 +195,5 @@
   abstract member-signature method method5a<T extends self::Class1* = self::Class1*>() → void; -> self::Class1::method5a
   abstract member-signature method method5b<T extends self::Class1* = self::Class1*>() → void; -> self::Class1::method5b
   abstract member-signature method method5c<T extends self::Class1* = self::Class1*>() → void; -> self::Class1::method5c
-  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 method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/generic_override.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/generic_override.dart.weak.transformed.expect
index e08ec43..30674ab 100644
--- a/pkg/front_end/testcases/nnbd_mixed/generic_override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/generic_override.dart.weak.transformed.expect
@@ -173,6 +173,16 @@
   synthetic constructor •() → gen::LegacyClass3*
     : super self::Class1::•()
     ;
+  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
   abstract member-signature method method1a<T extends core::Object* = dynamic>() → void; -> self::Class1::method1a
   abstract member-signature method method1b<T extends core::Object* = dynamic>() → void; -> self::Class1::method1b
   abstract member-signature method method1c<T extends core::Object* = dynamic>() → void; -> self::Class1::method1c
@@ -185,15 +195,5 @@
   abstract member-signature method method5a<T extends self::Class1* = self::Class1*>() → void; -> self::Class1::method5a
   abstract member-signature method method5b<T extends self::Class1* = self::Class1*>() → void; -> self::Class1::method5b
   abstract member-signature method method5c<T extends self::Class1* = self::Class1*>() → void; -> self::Class1::method5c
-  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 method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart
new file mode 100644
index 0000000..8f9b234
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.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.
+
+abstract class AbstractSuper {
+  int extendedConcreteField = 0;
+
+  abstract int extendedAbstractField;
+
+  int declaredConcreteExtendsConcreteField = 0;
+
+  int declaredAbstractExtendsConcreteField = 0;
+
+  abstract int declaredConcreteExtendsAbstractField;
+
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  int declaredConcreteField = 0;
+
+  abstract int declaredAbstractField;
+
+  int declaredConcreteExtendsConcreteField = 0;
+
+  abstract int declaredAbstractExtendsConcreteField;
+
+  int declaredConcreteExtendsAbstractField = 0;
+
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.textual_outline.expect
new file mode 100644
index 0000000..0b7bb20
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class AbstractSuper {
+  int extendedConcreteField = 0;
+  abstract int extendedAbstractField;
+  int declaredConcreteExtendsConcreteField = 0;
+  int declaredAbstractExtendsConcreteField = 0;
+  abstract int declaredConcreteExtendsAbstractField;
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  int declaredConcreteField = 0;
+  abstract int declaredAbstractField;
+  int declaredConcreteExtendsConcreteField = 0;
+  abstract int declaredAbstractExtendsConcreteField;
+  int declaredConcreteExtendsAbstractField = 0;
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fc83945
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass extends AbstractSuper {
+  abstract int declaredAbstractExtendsAbstractField;
+  abstract int declaredAbstractExtendsConcreteField;
+  abstract int declaredAbstractField;
+  int declaredConcreteExtendsAbstractField = 0;
+  int declaredConcreteExtendsConcreteField = 0;
+  int declaredConcreteField = 0;
+}
+
+abstract class AbstractSuper {
+  abstract int declaredAbstractExtendsAbstractField;
+  abstract int declaredConcreteExtendsAbstractField;
+  abstract int extendedAbstractField;
+  int declaredAbstractExtendsConcreteField = 0;
+  int declaredConcreteExtendsConcreteField = 0;
+  int extendedConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.weak.expect
new file mode 100644
index 0000000..bb1a80e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  field core::int extendedConcreteField = 0;
+  field core::int declaredConcreteExtendsConcreteField = 0;
+  field core::int declaredAbstractExtendsConcreteField = 0;
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract set extendedAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredConcreteExtendsAbstractField() → core::int;
+  abstract set declaredConcreteExtendsAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+  abstract set declaredAbstractExtendsAbstractField(core::int #externalFieldValue) → void;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  field core::int declaredConcreteField = 0;
+  field core::int declaredConcreteExtendsConcreteField = 0;
+  field core::int declaredConcreteExtendsAbstractField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract set declaredAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsConcreteField() → core::int;
+  abstract set declaredAbstractExtendsConcreteField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+  abstract set declaredAbstractExtendsAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..bb1a80e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_field.dart.weak.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  field core::int extendedConcreteField = 0;
+  field core::int declaredConcreteExtendsConcreteField = 0;
+  field core::int declaredAbstractExtendsConcreteField = 0;
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract set extendedAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredConcreteExtendsAbstractField() → core::int;
+  abstract set declaredConcreteExtendsAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+  abstract set declaredAbstractExtendsAbstractField(core::int #externalFieldValue) → void;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  field core::int declaredConcreteField = 0;
+  field core::int declaredConcreteExtendsConcreteField = 0;
+  field core::int declaredConcreteExtendsAbstractField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract set declaredAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsConcreteField() → core::int;
+  abstract set declaredAbstractExtendsConcreteField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+  abstract set declaredAbstractExtendsAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart
new file mode 100644
index 0000000..0abffca
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.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.
+
+abstract class AbstractSuper {
+  final int extendedConcreteField = 0;
+
+  abstract final int extendedAbstractField;
+
+  final int declaredConcreteExtendsConcreteField = 0;
+
+  final int declaredAbstractExtendsConcreteField = 0;
+
+  abstract final int declaredConcreteExtendsAbstractField;
+
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  final int declaredConcreteField = 0;
+
+  abstract final int declaredAbstractField;
+
+  final int declaredConcreteExtendsConcreteField = 0;
+
+  abstract final int declaredAbstractExtendsConcreteField;
+
+  final int declaredConcreteExtendsAbstractField = 0;
+
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.textual_outline.expect
new file mode 100644
index 0000000..56b31e0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class AbstractSuper {
+  final int extendedConcreteField = 0;
+  abstract final int extendedAbstractField;
+  final int declaredConcreteExtendsConcreteField = 0;
+  final int declaredAbstractExtendsConcreteField = 0;
+  abstract final int declaredConcreteExtendsAbstractField;
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  final int declaredConcreteField = 0;
+  abstract final int declaredAbstractField;
+  final int declaredConcreteExtendsConcreteField = 0;
+  abstract final int declaredAbstractExtendsConcreteField;
+  final int declaredConcreteExtendsAbstractField = 0;
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..856c33f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass extends AbstractSuper {
+  abstract final int declaredAbstractExtendsAbstractField;
+  abstract final int declaredAbstractExtendsConcreteField;
+  abstract final int declaredAbstractField;
+  final int declaredConcreteExtendsAbstractField = 0;
+  final int declaredConcreteExtendsConcreteField = 0;
+  final int declaredConcreteField = 0;
+}
+
+abstract class AbstractSuper {
+  abstract final int declaredAbstractExtendsAbstractField;
+  abstract final int declaredConcreteExtendsAbstractField;
+  abstract final int extendedAbstractField;
+  final int declaredAbstractExtendsConcreteField = 0;
+  final int declaredConcreteExtendsConcreteField = 0;
+  final int extendedConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.weak.expect
new file mode 100644
index 0000000..f4368dd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  final field core::int extendedConcreteField = 0;
+  final field core::int declaredConcreteExtendsConcreteField = 0;
+  final field core::int declaredAbstractExtendsConcreteField = 0;
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract get declaredConcreteExtendsAbstractField() → core::int;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  final field core::int declaredConcreteField = 0;
+  final field core::int declaredConcreteExtendsConcreteField = 0;
+  final field core::int declaredConcreteExtendsAbstractField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract get declaredAbstractExtendsConcreteField() → core::int;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..f4368dd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_final_field.dart.weak.transformed.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  final field core::int extendedConcreteField = 0;
+  final field core::int declaredConcreteExtendsConcreteField = 0;
+  final field core::int declaredAbstractExtendsConcreteField = 0;
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract get declaredConcreteExtendsAbstractField() → core::int;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  final field core::int declaredConcreteField = 0;
+  final field core::int declaredConcreteExtendsConcreteField = 0;
+  final field core::int declaredConcreteExtendsAbstractField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract get declaredAbstractExtendsConcreteField() → core::int;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart
new file mode 100644
index 0000000..871245a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.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.
+
+abstract class AbstractSuper {
+  int get extendedConcreteGetter => 0;
+
+  int get extendedAbstractGetter;
+
+  int get declaredConcreteExtendsConcreteGetter => 0;
+
+  int get declaredAbstractExtendsConcreteGetter => 0;
+
+  int get declaredConcreteExtendsAbstractGetter;
+
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  int get declaredConcreteGetter => 0;
+
+  int get declaredAbstractGetter;
+
+  int get declaredConcreteExtendsConcreteGetter => 0;
+
+  int get declaredAbstractExtendsConcreteGetter;
+
+  int get declaredConcreteExtendsAbstractGetter => 0;
+
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.textual_outline.expect
new file mode 100644
index 0000000..acc3521
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class AbstractSuper {
+  int get extendedConcreteGetter => 0;
+  int get extendedAbstractGetter;
+  int get declaredConcreteExtendsConcreteGetter => 0;
+  int get declaredAbstractExtendsConcreteGetter => 0;
+  int get declaredConcreteExtendsAbstractGetter;
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  int get declaredConcreteGetter => 0;
+  int get declaredAbstractGetter;
+  int get declaredConcreteExtendsConcreteGetter => 0;
+  int get declaredAbstractExtendsConcreteGetter;
+  int get declaredConcreteExtendsAbstractGetter => 0;
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fac9d18
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass extends AbstractSuper {
+  int get declaredAbstractExtendsAbstractGetter;
+  int get declaredAbstractExtendsConcreteGetter;
+  int get declaredAbstractGetter;
+  int get declaredConcreteExtendsAbstractGetter => 0;
+  int get declaredConcreteExtendsConcreteGetter => 0;
+  int get declaredConcreteGetter => 0;
+}
+
+abstract class AbstractSuper {
+  int get declaredAbstractExtendsAbstractGetter;
+  int get declaredAbstractExtendsConcreteGetter => 0;
+  int get declaredConcreteExtendsAbstractGetter;
+  int get declaredConcreteExtendsConcreteGetter => 0;
+  int get extendedAbstractGetter;
+  int get extendedConcreteGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.weak.expect
new file mode 100644
index 0000000..bd5fdb7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  get extendedConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractGetter() → core::int;
+  get declaredConcreteExtendsConcreteGetter() → core::int
+    return 0;
+  get declaredAbstractExtendsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredConcreteExtendsAbstractGetter() → core::int;
+  abstract get declaredAbstractExtendsAbstractGetter() → core::int;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  get declaredConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractGetter() → core::int;
+  get declaredConcreteExtendsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractExtendsConcreteGetter() → core::int;
+  get declaredConcreteExtendsAbstractGetter() → core::int
+    return 0;
+  abstract get declaredAbstractExtendsAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.weak.transformed.expect
new file mode 100644
index 0000000..bd5fdb7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_getter.dart.weak.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  get extendedConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractGetter() → core::int;
+  get declaredConcreteExtendsConcreteGetter() → core::int
+    return 0;
+  get declaredAbstractExtendsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredConcreteExtendsAbstractGetter() → core::int;
+  abstract get declaredAbstractExtendsAbstractGetter() → core::int;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  get declaredConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractGetter() → core::int;
+  get declaredConcreteExtendsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractExtendsConcreteGetter() → core::int;
+  get declaredConcreteExtendsAbstractGetter() → core::int
+    return 0;
+  abstract get declaredAbstractExtendsAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart
new file mode 100644
index 0000000..a04b939
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.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.
+
+abstract class AbstractSuper {
+  void extendedConcreteMethod() {}
+
+  void extendedAbstractMethod();
+
+  void declaredConcreteExtendsConcreteMethod() {}
+
+  void declaredAbstractExtendsConcreteMethod() {}
+
+  void declaredConcreteExtendsAbstractMethod();
+
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  void declaredConcreteMethod() {}
+
+  void declaredAbstractMethod();
+
+  void declaredConcreteExtendsConcreteMethod() {}
+
+  void declaredAbstractExtendsConcreteMethod();
+
+  void declaredConcreteExtendsAbstractMethod() {}
+
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.textual_outline.expect
new file mode 100644
index 0000000..91c1cf9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class AbstractSuper {
+  void extendedConcreteMethod() {}
+  void extendedAbstractMethod();
+  void declaredConcreteExtendsConcreteMethod() {}
+  void declaredAbstractExtendsConcreteMethod() {}
+  void declaredConcreteExtendsAbstractMethod();
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  void declaredConcreteMethod() {}
+  void declaredAbstractMethod();
+  void declaredConcreteExtendsConcreteMethod() {}
+  void declaredAbstractExtendsConcreteMethod();
+  void declaredConcreteExtendsAbstractMethod() {}
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..02bde9f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass extends AbstractSuper {
+  void declaredAbstractExtendsAbstractMethod();
+  void declaredAbstractExtendsConcreteMethod();
+  void declaredAbstractMethod();
+  void declaredConcreteExtendsAbstractMethod() {}
+  void declaredConcreteExtendsConcreteMethod() {}
+  void declaredConcreteMethod() {}
+}
+
+abstract class AbstractSuper {
+  void declaredAbstractExtendsAbstractMethod();
+  void declaredAbstractExtendsConcreteMethod() {}
+  void declaredConcreteExtendsAbstractMethod();
+  void declaredConcreteExtendsConcreteMethod() {}
+  void extendedAbstractMethod();
+  void extendedConcreteMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.weak.expect
new file mode 100644
index 0000000..4f4c28e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method declaredConcreteExtendsConcreteMethod() → void {}
+  method declaredAbstractExtendsConcreteMethod() → void {}
+  abstract method declaredConcreteExtendsAbstractMethod() → void;
+  abstract method declaredAbstractExtendsAbstractMethod() → void;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  method declaredConcreteMethod() → void {}
+  abstract method declaredAbstractMethod() → void;
+  method declaredConcreteExtendsConcreteMethod() → void {}
+  abstract method declaredAbstractExtendsConcreteMethod() → void;
+  method declaredConcreteExtendsAbstractMethod() → void {}
+  abstract method declaredAbstractExtendsAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..4f4c28e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_method.dart.weak.transformed.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method declaredConcreteExtendsConcreteMethod() → void {}
+  method declaredAbstractExtendsConcreteMethod() → void {}
+  abstract method declaredConcreteExtendsAbstractMethod() → void;
+  abstract method declaredAbstractExtendsAbstractMethod() → void;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  method declaredConcreteMethod() → void {}
+  abstract method declaredAbstractMethod() → void;
+  method declaredConcreteExtendsConcreteMethod() → void {}
+  abstract method declaredAbstractExtendsConcreteMethod() → void;
+  method declaredConcreteExtendsAbstractMethod() → void {}
+  abstract method declaredAbstractExtendsAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart
new file mode 100644
index 0000000..204409ed
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.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.
+
+abstract class AbstractSuper {
+  void set extendedConcreteSetter(int value) {}
+
+  void set extendedAbstractSetter(int value);
+
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+
+  void set declaredAbstractExtendsConcreteSetter(int value) {}
+
+  void set declaredConcreteExtendsAbstractSetter(int value);
+
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  void set declaredConcreteSetter(int value) {}
+
+  void set declaredAbstractSetter(int value);
+
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+
+  void set declaredAbstractExtendsConcreteSetter(int value);
+
+  void set declaredConcreteExtendsAbstractSetter(int value) {}
+
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..27727ee
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class AbstractSuper {
+  void set extendedConcreteSetter(int value) {}
+  void set extendedAbstractSetter(int value);
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+  void set declaredAbstractExtendsConcreteSetter(int value) {}
+  void set declaredConcreteExtendsAbstractSetter(int value);
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+abstract class AbstractClass extends AbstractSuper {
+  void set declaredConcreteSetter(int value) {}
+  void set declaredAbstractSetter(int value);
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+  void set declaredAbstractExtendsConcreteSetter(int value);
+  void set declaredConcreteExtendsAbstractSetter(int value) {}
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a78ec57
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass extends AbstractSuper {
+  void set declaredAbstractExtendsAbstractSetter(int value);
+  void set declaredAbstractExtendsConcreteSetter(int value);
+  void set declaredAbstractSetter(int value);
+  void set declaredConcreteExtendsAbstractSetter(int value) {}
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+  void set declaredConcreteSetter(int value) {}
+}
+
+abstract class AbstractSuper {
+  void set declaredAbstractExtendsAbstractSetter(int value);
+  void set declaredAbstractExtendsConcreteSetter(int value) {}
+  void set declaredConcreteExtendsAbstractSetter(int value);
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+  void set extendedAbstractSetter(int value);
+  void set extendedConcreteSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.weak.expect
new file mode 100644
index 0000000..c43f685
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  set extendedConcreteSetter(core::int value) → void {}
+  abstract set extendedAbstractSetter(core::int value) → void;
+  set declaredConcreteExtendsConcreteSetter(core::int value) → void {}
+  set declaredAbstractExtendsConcreteSetter(core::int value) → void {}
+  abstract set declaredConcreteExtendsAbstractSetter(core::int value) → void;
+  abstract set declaredAbstractExtendsAbstractSetter(core::int value) → void;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  set declaredConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractSetter(core::int value) → void;
+  set declaredConcreteExtendsConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractExtendsConcreteSetter(core::int value) → void;
+  set declaredConcreteExtendsAbstractSetter(core::int value) → void {}
+  abstract set declaredAbstractExtendsAbstractSetter(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.weak.transformed.expect
new file mode 100644
index 0000000..c43f685
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_extends_setter.dart.weak.transformed.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class AbstractSuper extends core::Object {
+  synthetic constructor •() → self::AbstractSuper
+    : super core::Object::•()
+    ;
+  set extendedConcreteSetter(core::int value) → void {}
+  abstract set extendedAbstractSetter(core::int value) → void;
+  set declaredConcreteExtendsConcreteSetter(core::int value) → void {}
+  set declaredAbstractExtendsConcreteSetter(core::int value) → void {}
+  abstract set declaredConcreteExtendsAbstractSetter(core::int value) → void;
+  abstract set declaredAbstractExtendsAbstractSetter(core::int value) → void;
+}
+abstract class AbstractClass extends self::AbstractSuper {
+  synthetic constructor •() → self::AbstractClass
+    : super self::AbstractSuper::•()
+    ;
+  set declaredConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractSetter(core::int value) → void;
+  set declaredConcreteExtendsConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractExtendsConcreteSetter(core::int value) → void;
+  set declaredConcreteExtendsAbstractSetter(core::int value) → void {}
+  abstract set declaredAbstractExtendsAbstractSetter(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart
new file mode 100644
index 0000000..f35baeb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.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.
+
+abstract class Interface {
+  int implementedConcreteField = 0;
+
+  abstract int implementedAbstractField;
+
+  int declaredConcreteImplementsConcreteField = 0;
+
+  int declaredAbstractImplementsConcreteField = 0;
+
+  abstract int declaredConcreteImplementsAbstractField;
+
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+abstract class AbstractClass implements Interface {
+  int declaredConcreteField = 0;
+
+  abstract int declaredAbstractField;
+
+  int declaredConcreteImplementsConcreteField = 0;
+
+  abstract int declaredAbstractImplementsConcreteField;
+
+  int declaredConcreteImplementsAbstractField = 0;
+
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.textual_outline.expect
new file mode 100644
index 0000000..fd6e284
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class Interface {
+  int implementedConcreteField = 0;
+  abstract int implementedAbstractField;
+  int declaredConcreteImplementsConcreteField = 0;
+  int declaredAbstractImplementsConcreteField = 0;
+  abstract int declaredConcreteImplementsAbstractField;
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+abstract class AbstractClass implements Interface {
+  int declaredConcreteField = 0;
+  abstract int declaredAbstractField;
+  int declaredConcreteImplementsConcreteField = 0;
+  abstract int declaredAbstractImplementsConcreteField;
+  int declaredConcreteImplementsAbstractField = 0;
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..97ad7aa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass implements Interface {
+  abstract int declaredAbstractField;
+  abstract int declaredAbstractImplementsAbstractField;
+  abstract int declaredAbstractImplementsConcreteField;
+  int declaredConcreteField = 0;
+  int declaredConcreteImplementsAbstractField = 0;
+  int declaredConcreteImplementsConcreteField = 0;
+}
+
+abstract class Interface {
+  abstract int declaredAbstractImplementsAbstractField;
+  abstract int declaredConcreteImplementsAbstractField;
+  abstract int implementedAbstractField;
+  int declaredAbstractImplementsConcreteField = 0;
+  int declaredConcreteImplementsConcreteField = 0;
+  int implementedConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.weak.expect
new file mode 100644
index 0000000..0cdcd41
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int implementedConcreteField = 0;
+  field core::int declaredConcreteImplementsConcreteField = 0;
+  field core::int declaredAbstractImplementsConcreteField = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract get implementedAbstractField() → core::int;
+  abstract set implementedAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredConcreteImplementsAbstractField() → core::int;
+  abstract set declaredConcreteImplementsAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+  abstract set declaredAbstractImplementsAbstractField(core::int #externalFieldValue) → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  field core::int declaredConcreteField = 0;
+  field core::int declaredConcreteImplementsConcreteField = 0;
+  field core::int declaredConcreteImplementsAbstractField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract set declaredAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsConcreteField() → core::int;
+  abstract set declaredAbstractImplementsConcreteField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+  abstract set declaredAbstractImplementsAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..0cdcd41
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_field.dart.weak.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int implementedConcreteField = 0;
+  field core::int declaredConcreteImplementsConcreteField = 0;
+  field core::int declaredAbstractImplementsConcreteField = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract get implementedAbstractField() → core::int;
+  abstract set implementedAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredConcreteImplementsAbstractField() → core::int;
+  abstract set declaredConcreteImplementsAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+  abstract set declaredAbstractImplementsAbstractField(core::int #externalFieldValue) → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  field core::int declaredConcreteField = 0;
+  field core::int declaredConcreteImplementsConcreteField = 0;
+  field core::int declaredConcreteImplementsAbstractField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract set declaredAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsConcreteField() → core::int;
+  abstract set declaredAbstractImplementsConcreteField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+  abstract set declaredAbstractImplementsAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart
new file mode 100644
index 0000000..b8ebbba
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.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.
+
+abstract class Interface {
+  final int implementedConcreteField = 0;
+
+  abstract final int implementedAbstractField;
+
+  final int declaredConcreteImplementsConcreteField = 0;
+
+  final int declaredAbstractImplementsConcreteField = 0;
+
+  abstract final int declaredConcreteImplementsAbstractField;
+
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+abstract class AbstractClass implements Interface {
+  final int declaredConcreteField = 0;
+
+  abstract final int declaredAbstractField;
+
+  final int declaredConcreteImplementsConcreteField = 0;
+
+  abstract final int declaredAbstractImplementsConcreteField;
+
+  final int declaredConcreteImplementsAbstractField = 0;
+
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.textual_outline.expect
new file mode 100644
index 0000000..0409a2d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class Interface {
+  final int implementedConcreteField = 0;
+  abstract final int implementedAbstractField;
+  final int declaredConcreteImplementsConcreteField = 0;
+  final int declaredAbstractImplementsConcreteField = 0;
+  abstract final int declaredConcreteImplementsAbstractField;
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+abstract class AbstractClass implements Interface {
+  final int declaredConcreteField = 0;
+  abstract final int declaredAbstractField;
+  final int declaredConcreteImplementsConcreteField = 0;
+  abstract final int declaredAbstractImplementsConcreteField;
+  final int declaredConcreteImplementsAbstractField = 0;
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..71ccf7b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass implements Interface {
+  abstract final int declaredAbstractField;
+  abstract final int declaredAbstractImplementsAbstractField;
+  abstract final int declaredAbstractImplementsConcreteField;
+  final int declaredConcreteField = 0;
+  final int declaredConcreteImplementsAbstractField = 0;
+  final int declaredConcreteImplementsConcreteField = 0;
+}
+
+abstract class Interface {
+  abstract final int declaredAbstractImplementsAbstractField;
+  abstract final int declaredConcreteImplementsAbstractField;
+  abstract final int implementedAbstractField;
+  final int declaredAbstractImplementsConcreteField = 0;
+  final int declaredConcreteImplementsConcreteField = 0;
+  final int implementedConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.weak.expect
new file mode 100644
index 0000000..e1f92ea
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  final field core::int implementedConcreteField = 0;
+  final field core::int declaredConcreteImplementsConcreteField = 0;
+  final field core::int declaredAbstractImplementsConcreteField = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract get implementedAbstractField() → core::int;
+  abstract get declaredConcreteImplementsAbstractField() → core::int;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  final field core::int declaredConcreteField = 0;
+  final field core::int declaredConcreteImplementsConcreteField = 0;
+  final field core::int declaredConcreteImplementsAbstractField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract get declaredAbstractImplementsConcreteField() → core::int;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..e1f92ea
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_final_field.dart.weak.transformed.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  final field core::int implementedConcreteField = 0;
+  final field core::int declaredConcreteImplementsConcreteField = 0;
+  final field core::int declaredAbstractImplementsConcreteField = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract get implementedAbstractField() → core::int;
+  abstract get declaredConcreteImplementsAbstractField() → core::int;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  final field core::int declaredConcreteField = 0;
+  final field core::int declaredConcreteImplementsConcreteField = 0;
+  final field core::int declaredConcreteImplementsAbstractField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract get declaredAbstractImplementsConcreteField() → core::int;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart
new file mode 100644
index 0000000..2a5d904
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.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.
+
+abstract class Interface {
+  int get implementedConcreteGetter => 0;
+
+  int get implementedAbstractGetter;
+
+  int get declaredConcreteImplementsConcreteGetter => 0;
+
+  int get declaredAbstractImplementsConcreteGetter => 0;
+
+  int get declaredConcreteImplementsAbstractGetter;
+
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+abstract class AbstractClass implements Interface {
+  int get declaredConcreteGetter => 0;
+
+  int get declaredAbstractGetter;
+
+  int get declaredConcreteImplementsConcreteGetter => 0;
+
+  int get declaredAbstractImplementsConcreteGetter;
+
+  int get declaredConcreteImplementsAbstractGetter => 0;
+
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.textual_outline.expect
new file mode 100644
index 0000000..4428729
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class Interface {
+  int get implementedConcreteGetter => 0;
+  int get implementedAbstractGetter;
+  int get declaredConcreteImplementsConcreteGetter => 0;
+  int get declaredAbstractImplementsConcreteGetter => 0;
+  int get declaredConcreteImplementsAbstractGetter;
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+abstract class AbstractClass implements Interface {
+  int get declaredConcreteGetter => 0;
+  int get declaredAbstractGetter;
+  int get declaredConcreteImplementsConcreteGetter => 0;
+  int get declaredAbstractImplementsConcreteGetter;
+  int get declaredConcreteImplementsAbstractGetter => 0;
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9430ead
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass implements Interface {
+  int get declaredAbstractGetter;
+  int get declaredAbstractImplementsAbstractGetter;
+  int get declaredAbstractImplementsConcreteGetter;
+  int get declaredConcreteGetter => 0;
+  int get declaredConcreteImplementsAbstractGetter => 0;
+  int get declaredConcreteImplementsConcreteGetter => 0;
+}
+
+abstract class Interface {
+  int get declaredAbstractImplementsAbstractGetter;
+  int get declaredAbstractImplementsConcreteGetter => 0;
+  int get declaredConcreteImplementsAbstractGetter;
+  int get declaredConcreteImplementsConcreteGetter => 0;
+  int get implementedAbstractGetter;
+  int get implementedConcreteGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.weak.expect
new file mode 100644
index 0000000..60896ad
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  get implementedConcreteGetter() → core::int
+    return 0;
+  abstract get implementedAbstractGetter() → core::int;
+  get declaredConcreteImplementsConcreteGetter() → core::int
+    return 0;
+  get declaredAbstractImplementsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredConcreteImplementsAbstractGetter() → core::int;
+  abstract get declaredAbstractImplementsAbstractGetter() → core::int;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  get declaredConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractGetter() → core::int;
+  get declaredConcreteImplementsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractImplementsConcreteGetter() → core::int;
+  get declaredConcreteImplementsAbstractGetter() → core::int
+    return 0;
+  abstract get declaredAbstractImplementsAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.weak.transformed.expect
new file mode 100644
index 0000000..60896ad
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_getter.dart.weak.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  get implementedConcreteGetter() → core::int
+    return 0;
+  abstract get implementedAbstractGetter() → core::int;
+  get declaredConcreteImplementsConcreteGetter() → core::int
+    return 0;
+  get declaredAbstractImplementsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredConcreteImplementsAbstractGetter() → core::int;
+  abstract get declaredAbstractImplementsAbstractGetter() → core::int;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  get declaredConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractGetter() → core::int;
+  get declaredConcreteImplementsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractImplementsConcreteGetter() → core::int;
+  get declaredConcreteImplementsAbstractGetter() → core::int
+    return 0;
+  abstract get declaredAbstractImplementsAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart
new file mode 100644
index 0000000..94043a5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.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.
+
+abstract class Interface {
+  void implementedConcreteMethod() {}
+
+  void implementedAbstractMethod();
+
+  void declaredConcreteImplementsConcreteMethod() {}
+
+  void declaredAbstractImplementsConcreteMethod() {}
+
+  void declaredConcreteImplementsAbstractMethod();
+
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+abstract class AbstractClass implements Interface {
+  void declaredConcreteMethod() {}
+
+  void declaredAbstractMethod();
+
+  void declaredConcreteImplementsConcreteMethod() {}
+
+  void declaredAbstractImplementsConcreteMethod();
+
+  void declaredConcreteImplementsAbstractMethod() {}
+
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.textual_outline.expect
new file mode 100644
index 0000000..590809c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class Interface {
+  void implementedConcreteMethod() {}
+  void implementedAbstractMethod();
+  void declaredConcreteImplementsConcreteMethod() {}
+  void declaredAbstractImplementsConcreteMethod() {}
+  void declaredConcreteImplementsAbstractMethod();
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+abstract class AbstractClass implements Interface {
+  void declaredConcreteMethod() {}
+  void declaredAbstractMethod();
+  void declaredConcreteImplementsConcreteMethod() {}
+  void declaredAbstractImplementsConcreteMethod();
+  void declaredConcreteImplementsAbstractMethod() {}
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..30f918b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass implements Interface {
+  void declaredAbstractImplementsAbstractMethod();
+  void declaredAbstractImplementsConcreteMethod();
+  void declaredAbstractMethod();
+  void declaredConcreteImplementsAbstractMethod() {}
+  void declaredConcreteImplementsConcreteMethod() {}
+  void declaredConcreteMethod() {}
+}
+
+abstract class Interface {
+  void declaredAbstractImplementsAbstractMethod();
+  void declaredAbstractImplementsConcreteMethod() {}
+  void declaredConcreteImplementsAbstractMethod();
+  void declaredConcreteImplementsConcreteMethod() {}
+  void implementedAbstractMethod();
+  void implementedConcreteMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.weak.expect
new file mode 100644
index 0000000..fb0c37a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method implementedConcreteMethod() → void {}
+  abstract method implementedAbstractMethod() → void;
+  method declaredConcreteImplementsConcreteMethod() → void {}
+  method declaredAbstractImplementsConcreteMethod() → void {}
+  abstract method declaredConcreteImplementsAbstractMethod() → void;
+  abstract method declaredAbstractImplementsAbstractMethod() → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  method declaredConcreteMethod() → void {}
+  abstract method declaredAbstractMethod() → void;
+  method declaredConcreteImplementsConcreteMethod() → void {}
+  abstract method declaredAbstractImplementsConcreteMethod() → void;
+  method declaredConcreteImplementsAbstractMethod() → void {}
+  abstract method declaredAbstractImplementsAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..fb0c37a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_method.dart.weak.transformed.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method implementedConcreteMethod() → void {}
+  abstract method implementedAbstractMethod() → void;
+  method declaredConcreteImplementsConcreteMethod() → void {}
+  method declaredAbstractImplementsConcreteMethod() → void {}
+  abstract method declaredConcreteImplementsAbstractMethod() → void;
+  abstract method declaredAbstractImplementsAbstractMethod() → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  method declaredConcreteMethod() → void {}
+  abstract method declaredAbstractMethod() → void;
+  method declaredConcreteImplementsConcreteMethod() → void {}
+  abstract method declaredAbstractImplementsConcreteMethod() → void;
+  method declaredConcreteImplementsAbstractMethod() → void {}
+  abstract method declaredAbstractImplementsAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart
new file mode 100644
index 0000000..0fb2334
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.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.
+
+abstract class Interface {
+  void set implementedConcreteSetter(int value) {}
+
+  void set implementedAbstractSetter(int value);
+
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+
+  void set declaredAbstractImplementsConcreteSetter(int value) {}
+
+  void set declaredConcreteImplementsAbstractSetter(int value);
+
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+abstract class AbstractClass implements Interface {
+  void set declaredConcreteSetter(int value) {}
+
+  void set declaredAbstractSetter(int value);
+
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+
+  void set declaredAbstractImplementsConcreteSetter(int value);
+
+  void set declaredConcreteImplementsAbstractSetter(int value) {}
+
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..6118338
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+abstract class Interface {
+  void set implementedConcreteSetter(int value) {}
+  void set implementedAbstractSetter(int value);
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+  void set declaredAbstractImplementsConcreteSetter(int value) {}
+  void set declaredConcreteImplementsAbstractSetter(int value);
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+abstract class AbstractClass implements Interface {
+  void set declaredConcreteSetter(int value) {}
+  void set declaredAbstractSetter(int value);
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+  void set declaredAbstractImplementsConcreteSetter(int value);
+  void set declaredConcreteImplementsAbstractSetter(int value) {}
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b33b64b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+abstract class AbstractClass implements Interface {
+  void set declaredAbstractImplementsAbstractSetter(int value);
+  void set declaredAbstractImplementsConcreteSetter(int value);
+  void set declaredAbstractSetter(int value);
+  void set declaredConcreteImplementsAbstractSetter(int value) {}
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+  void set declaredConcreteSetter(int value) {}
+}
+
+abstract class Interface {
+  void set declaredAbstractImplementsAbstractSetter(int value);
+  void set declaredAbstractImplementsConcreteSetter(int value) {}
+  void set declaredConcreteImplementsAbstractSetter(int value);
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+  void set implementedAbstractSetter(int value);
+  void set implementedConcreteSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.weak.expect
new file mode 100644
index 0000000..59931d6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.weak.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  set implementedConcreteSetter(core::int value) → void {}
+  abstract set implementedAbstractSetter(core::int value) → void;
+  set declaredConcreteImplementsConcreteSetter(core::int value) → void {}
+  set declaredAbstractImplementsConcreteSetter(core::int value) → void {}
+  abstract set declaredConcreteImplementsAbstractSetter(core::int value) → void;
+  abstract set declaredAbstractImplementsAbstractSetter(core::int value) → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  set declaredConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractSetter(core::int value) → void;
+  set declaredConcreteImplementsConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractImplementsConcreteSetter(core::int value) → void;
+  set declaredConcreteImplementsAbstractSetter(core::int value) → void {}
+  abstract set declaredAbstractImplementsAbstractSetter(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.weak.transformed.expect
new file mode 100644
index 0000000..59931d6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_implements_setter.dart.weak.transformed.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  set implementedConcreteSetter(core::int value) → void {}
+  abstract set implementedAbstractSetter(core::int value) → void;
+  set declaredConcreteImplementsConcreteSetter(core::int value) → void {}
+  set declaredAbstractImplementsConcreteSetter(core::int value) → void {}
+  abstract set declaredConcreteImplementsAbstractSetter(core::int value) → void;
+  abstract set declaredAbstractImplementsAbstractSetter(core::int value) → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  set declaredConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractSetter(core::int value) → void;
+  set declaredConcreteImplementsConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractImplementsConcreteSetter(core::int value) → void;
+  set declaredConcreteImplementsAbstractSetter(core::int value) → void {}
+  abstract set declaredAbstractImplementsAbstractSetter(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart
new file mode 100644
index 0000000..17ea67b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.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.
+
+class Super {
+  void extendedConcreteMixedInAbstractMethod() {}
+  void extendedConcreteMixedInConcreteMethod() {}
+  void extendedConcreteMixedInAbstractImplementedMethod(int i) {}
+  void extendedConcreteMixedInConcreteImplementedMethod(int i) {}
+}
+
+class Interface {
+  void extendedConcreteMixedInAbstractImplementedMethod(covariant num i) {}
+  void extendedConcreteMixedInConcreteImplementedMethod(covariant num i) {}
+}
+
+mixin Mixin {
+  void extendedConcreteMixedInAbstractMethod();
+  void extendedConcreteMixedInConcreteMethod() {}
+  void extendedConcreteMixedInAbstractImplementedMethod(int i);
+  void extendedConcreteMixedInConcreteImplementedMethod(int i) {}
+}
+
+class Class = Super with Mixin implements Interface;
+
+class Sub extends Class {
+  void test() {
+    extendedConcreteMixedInAbstractMethod();
+    super.extendedConcreteMixedInAbstractMethod();
+    extendedConcreteMixedInConcreteMethod();
+    super.extendedConcreteMixedInConcreteMethod();
+
+    extendedConcreteMixedInAbstractImplementedMethod(0);
+    super.extendedConcreteMixedInAbstractImplementedMethod(0);
+    extendedConcreteMixedInConcreteImplementedMethod(0);
+    super.extendedConcreteMixedInConcreteImplementedMethod(0);
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.textual_outline.expect
new file mode 100644
index 0000000..f5c6297
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class Super {
+  void extendedConcreteMixedInAbstractMethod() {}
+  void extendedConcreteMixedInConcreteMethod() {}
+  void extendedConcreteMixedInAbstractImplementedMethod(int i) {}
+  void extendedConcreteMixedInConcreteImplementedMethod(int i) {}
+}
+
+class Interface {
+  void extendedConcreteMixedInAbstractImplementedMethod(covariant num i) {}
+  void extendedConcreteMixedInConcreteImplementedMethod(covariant num i) {}
+}
+
+mixin Mixin {
+  void extendedConcreteMixedInAbstractMethod();
+  void extendedConcreteMixedInConcreteMethod() {}
+  void extendedConcreteMixedInAbstractImplementedMethod(int i);
+  void extendedConcreteMixedInConcreteImplementedMethod(int i) {}
+}
+class Class = Super with Mixin implements Interface;
+
+class Sub extends Class {
+  void test() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1f883cc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+class Class = Super with Mixin implements Interface;
+
+class Interface {
+  void extendedConcreteMixedInAbstractImplementedMethod(covariant num i) {}
+  void extendedConcreteMixedInConcreteImplementedMethod(covariant num i) {}
+}
+
+class Sub extends Class {
+  void test() {}
+}
+
+class Super {
+  void extendedConcreteMixedInAbstractImplementedMethod(int i) {}
+  void extendedConcreteMixedInAbstractMethod() {}
+  void extendedConcreteMixedInConcreteImplementedMethod(int i) {}
+  void extendedConcreteMixedInConcreteMethod() {}
+}
+
+main() {}
+mixin Mixin {
+  void extendedConcreteMixedInAbstractImplementedMethod(int i);
+  void extendedConcreteMixedInAbstractMethod();
+  void extendedConcreteMixedInConcreteImplementedMethod(int i) {}
+  void extendedConcreteMixedInConcreteMethod() {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.weak.expect
new file mode 100644
index 0000000..0f16923
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.weak.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMixedInAbstractMethod() → void {}
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  method extendedConcreteMixedInAbstractImplementedMethod(core::int i) → void {}
+  method extendedConcreteMixedInConcreteImplementedMethod(core::int i) → void {}
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method extendedConcreteMixedInAbstractImplementedMethod(covariant core::num i) → void {}
+  method extendedConcreteMixedInConcreteImplementedMethod(covariant core::num i) → void {}
+}
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+  abstract method extendedConcreteMixedInAbstractMethod() → void;
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  abstract method extendedConcreteMixedInAbstractImplementedMethod(core::int i) → void;
+  method extendedConcreteMixedInConcreteImplementedMethod(core::int i) → void {}
+}
+class Class = self::Super with self::Mixin implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  abstract mixin-stub method extendedConcreteMixedInAbstractMethod() → void; -> self::Mixin::extendedConcreteMixedInAbstractMethod
+  mixin-super-stub method extendedConcreteMixedInConcreteMethod() → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteMethod}();
+  forwarding-stub method extendedConcreteMixedInAbstractImplementedMethod(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteMixedInAbstractImplementedMethod}(i);
+  forwarding-stub method extendedConcreteMixedInConcreteImplementedMethod(covariant core::int i) → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteImplementedMethod}(i);
+}
+class Sub extends self::Class {
+  synthetic constructor •() → self::Sub
+    : super self::Class::•()
+    ;
+  method test() → void {
+    this.{self::Class::extendedConcreteMixedInAbstractMethod}();
+    super.{self::Super::extendedConcreteMixedInAbstractMethod}();
+    this.{self::Class::extendedConcreteMixedInConcreteMethod}();
+    super.{self::Class::extendedConcreteMixedInConcreteMethod}();
+    this.{self::Class::extendedConcreteMixedInAbstractImplementedMethod}(0);
+    super.{self::Class::extendedConcreteMixedInAbstractImplementedMethod}(0);
+    this.{self::Class::extendedConcreteMixedInConcreteImplementedMethod}(0);
+    super.{self::Class::extendedConcreteMixedInConcreteImplementedMethod}(0);
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.weak.transformed.expect
new file mode 100644
index 0000000..8f44020
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/abstract_mixin.dart.weak.transformed.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMixedInAbstractMethod() → void {}
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  method extendedConcreteMixedInAbstractImplementedMethod(core::int i) → void {}
+  method extendedConcreteMixedInConcreteImplementedMethod(core::int i) → void {}
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method extendedConcreteMixedInAbstractImplementedMethod(covariant core::num i) → void {}
+  method extendedConcreteMixedInConcreteImplementedMethod(covariant core::num i) → void {}
+}
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+  abstract method extendedConcreteMixedInAbstractMethod() → void;
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  abstract method extendedConcreteMixedInAbstractImplementedMethod(core::int i) → void;
+  method extendedConcreteMixedInConcreteImplementedMethod(core::int i) → void {}
+}
+class Class extends self::Super implements self::Interface, self::Mixin /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  abstract method extendedConcreteMixedInAbstractMethod() → void;
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  abstract method extendedConcreteMixedInAbstractImplementedMethod(covariant core::int i) → void;
+  method extendedConcreteMixedInConcreteImplementedMethod(covariant core::int i) → void {}
+}
+class Sub extends self::Class {
+  synthetic constructor •() → self::Sub
+    : super self::Class::•()
+    ;
+  method test() → void {
+    this.{self::Class::extendedConcreteMixedInAbstractMethod}();
+    super.{self::Super::extendedConcreteMixedInAbstractMethod}();
+    this.{self::Class::extendedConcreteMixedInConcreteMethod}();
+    super.{self::Class::extendedConcreteMixedInConcreteMethod}();
+    this.{self::Class::extendedConcreteMixedInAbstractImplementedMethod}(0);
+    super.{self::Class::extendedConcreteMixedInAbstractImplementedMethod}(0);
+    this.{self::Class::extendedConcreteMixedInConcreteImplementedMethod}(0);
+    super.{self::Class::extendedConcreteMixedInConcreteImplementedMethod}(0);
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart
new file mode 100644
index 0000000..0ac9669
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.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.
+
+class ConcreteSuper {
+  int extendedConcreteField = 0;
+
+  abstract int extendedAbstractField;
+
+  int declaredConcreteExtendsConcreteField = 0;
+
+  int declaredAbstractExtendsConcreteField = 0;
+
+  abstract int declaredConcreteExtendsAbstractField;
+
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+class ConcreteClass extends ConcreteSuper {
+  int declaredConcreteField = 0;
+
+  abstract int declaredAbstractField;
+
+  int declaredConcreteExtendsConcreteField = 0;
+
+  abstract int declaredAbstractExtendsConcreteField;
+
+  int declaredConcreteExtendsAbstractField = 0;
+
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.textual_outline.expect
new file mode 100644
index 0000000..d3507c8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class ConcreteSuper {
+  int extendedConcreteField = 0;
+  abstract int extendedAbstractField;
+  int declaredConcreteExtendsConcreteField = 0;
+  int declaredAbstractExtendsConcreteField = 0;
+  abstract int declaredConcreteExtendsAbstractField;
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+class ConcreteClass extends ConcreteSuper {
+  int declaredConcreteField = 0;
+  abstract int declaredAbstractField;
+  int declaredConcreteExtendsConcreteField = 0;
+  abstract int declaredAbstractExtendsConcreteField;
+  int declaredConcreteExtendsAbstractField = 0;
+  abstract int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2a62eba
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass extends ConcreteSuper {
+  abstract int declaredAbstractExtendsAbstractField;
+  abstract int declaredAbstractExtendsConcreteField;
+  abstract int declaredAbstractField;
+  int declaredConcreteExtendsAbstractField = 0;
+  int declaredConcreteExtendsConcreteField = 0;
+  int declaredConcreteField = 0;
+}
+
+class ConcreteSuper {
+  abstract int declaredAbstractExtendsAbstractField;
+  abstract int declaredConcreteExtendsAbstractField;
+  abstract int extendedAbstractField;
+  int declaredAbstractExtendsConcreteField = 0;
+  int declaredConcreteExtendsConcreteField = 0;
+  int extendedConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.weak.expect
new file mode 100644
index 0000000..2697e8e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.weak.expect
@@ -0,0 +1,104 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractField
+//  - ConcreteSuper.declaredAbstractExtendsAbstractField=
+//  - ConcreteSuper.declaredConcreteExtendsAbstractField
+//  - ConcreteSuper.declaredConcreteExtendsAbstractField=
+//  - ConcreteSuper.extendedAbstractField
+//  - ConcreteSuper.extendedAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:16:16: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractField' is defined here.
+//   abstract int declaredAbstractExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:16:16: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractField=' is defined here.
+//   abstract int declaredAbstractExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:14:16: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractField' is defined here.
+//   abstract int declaredConcreteExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:14:16: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractField=' is defined here.
+//   abstract int declaredConcreteExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:8:16: Context: 'ConcreteSuper.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:8:16: Context: 'ConcreteSuper.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractField
+//  - ConcreteClass.declaredAbstractExtendsAbstractField=
+//  - ConcreteClass.declaredAbstractField
+//  - ConcreteClass.declaredAbstractField=
+//  - ConcreteSuper.extendedAbstractField
+//  - ConcreteSuper.extendedAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:30:16: Context: 'ConcreteClass.declaredAbstractExtendsAbstractField' is defined here.
+//   abstract int declaredAbstractExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:30:16: Context: 'ConcreteClass.declaredAbstractExtendsAbstractField=' is defined here.
+//   abstract int declaredAbstractExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:22:16: Context: 'ConcreteClass.declaredAbstractField' is defined here.
+//   abstract int declaredAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:22:16: Context: 'ConcreteClass.declaredAbstractField=' is defined here.
+//   abstract int declaredAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:8:16: Context: 'ConcreteSuper.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:8:16: Context: 'ConcreteSuper.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  field core::int extendedConcreteField = 0;
+  field core::int declaredConcreteExtendsConcreteField = 0;
+  field core::int declaredAbstractExtendsConcreteField = 0;
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract set extendedAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredConcreteExtendsAbstractField() → core::int;
+  abstract set declaredConcreteExtendsAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+  abstract set declaredAbstractExtendsAbstractField(core::int #externalFieldValue) → void;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  field core::int declaredConcreteField = 0;
+  field core::int declaredConcreteExtendsConcreteField = 0;
+  field core::int declaredConcreteExtendsAbstractField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract set declaredAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsConcreteField() → core::int;
+  abstract set declaredAbstractExtendsConcreteField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+  abstract set declaredAbstractExtendsAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..2697e8e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart.weak.transformed.expect
@@ -0,0 +1,104 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractField
+//  - ConcreteSuper.declaredAbstractExtendsAbstractField=
+//  - ConcreteSuper.declaredConcreteExtendsAbstractField
+//  - ConcreteSuper.declaredConcreteExtendsAbstractField=
+//  - ConcreteSuper.extendedAbstractField
+//  - ConcreteSuper.extendedAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:16:16: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractField' is defined here.
+//   abstract int declaredAbstractExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:16:16: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractField=' is defined here.
+//   abstract int declaredAbstractExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:14:16: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractField' is defined here.
+//   abstract int declaredConcreteExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:14:16: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractField=' is defined here.
+//   abstract int declaredConcreteExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:8:16: Context: 'ConcreteSuper.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:8:16: Context: 'ConcreteSuper.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractField
+//  - ConcreteClass.declaredAbstractExtendsAbstractField=
+//  - ConcreteClass.declaredAbstractField
+//  - ConcreteClass.declaredAbstractField=
+//  - ConcreteSuper.extendedAbstractField
+//  - ConcreteSuper.extendedAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:30:16: Context: 'ConcreteClass.declaredAbstractExtendsAbstractField' is defined here.
+//   abstract int declaredAbstractExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:30:16: Context: 'ConcreteClass.declaredAbstractExtendsAbstractField=' is defined here.
+//   abstract int declaredAbstractExtendsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:22:16: Context: 'ConcreteClass.declaredAbstractField' is defined here.
+//   abstract int declaredAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:22:16: Context: 'ConcreteClass.declaredAbstractField=' is defined here.
+//   abstract int declaredAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:8:16: Context: 'ConcreteSuper.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_field.dart:8:16: Context: 'ConcreteSuper.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  field core::int extendedConcreteField = 0;
+  field core::int declaredConcreteExtendsConcreteField = 0;
+  field core::int declaredAbstractExtendsConcreteField = 0;
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract set extendedAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredConcreteExtendsAbstractField() → core::int;
+  abstract set declaredConcreteExtendsAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+  abstract set declaredAbstractExtendsAbstractField(core::int #externalFieldValue) → void;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  field core::int declaredConcreteField = 0;
+  field core::int declaredConcreteExtendsConcreteField = 0;
+  field core::int declaredConcreteExtendsAbstractField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract set declaredAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsConcreteField() → core::int;
+  abstract set declaredAbstractExtendsConcreteField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+  abstract set declaredAbstractExtendsAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart
new file mode 100644
index 0000000..998ab9f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.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.
+
+class ConcreteSuper {
+  final int extendedConcreteField = 0;
+
+  abstract final int extendedAbstractField;
+
+  final int declaredConcreteExtendsConcreteField = 0;
+
+  final int declaredAbstractExtendsConcreteField = 0;
+
+  abstract final int declaredConcreteExtendsAbstractField;
+
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+class ConcreteClass extends ConcreteSuper {
+  final int declaredConcreteField = 0;
+
+  abstract final int declaredAbstractField;
+
+  final int declaredConcreteExtendsConcreteField = 0;
+
+  abstract final int declaredAbstractExtendsConcreteField;
+
+  final int declaredConcreteExtendsAbstractField = 0;
+
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.textual_outline.expect
new file mode 100644
index 0000000..b723de4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class ConcreteSuper {
+  final int extendedConcreteField = 0;
+  abstract final int extendedAbstractField;
+  final int declaredConcreteExtendsConcreteField = 0;
+  final int declaredAbstractExtendsConcreteField = 0;
+  abstract final int declaredConcreteExtendsAbstractField;
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+class ConcreteClass extends ConcreteSuper {
+  final int declaredConcreteField = 0;
+  abstract final int declaredAbstractField;
+  final int declaredConcreteExtendsConcreteField = 0;
+  abstract final int declaredAbstractExtendsConcreteField;
+  final int declaredConcreteExtendsAbstractField = 0;
+  abstract final int declaredAbstractExtendsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d18a1d2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass extends ConcreteSuper {
+  abstract final int declaredAbstractExtendsAbstractField;
+  abstract final int declaredAbstractExtendsConcreteField;
+  abstract final int declaredAbstractField;
+  final int declaredConcreteExtendsAbstractField = 0;
+  final int declaredConcreteExtendsConcreteField = 0;
+  final int declaredConcreteField = 0;
+}
+
+class ConcreteSuper {
+  abstract final int declaredAbstractExtendsAbstractField;
+  abstract final int declaredConcreteExtendsAbstractField;
+  abstract final int extendedAbstractField;
+  final int declaredAbstractExtendsConcreteField = 0;
+  final int declaredConcreteExtendsConcreteField = 0;
+  final int extendedConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.weak.expect
new file mode 100644
index 0000000..4b81a56
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.weak.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractField
+//  - ConcreteSuper.declaredConcreteExtendsAbstractField
+//  - ConcreteSuper.extendedAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:16:22: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractField' is defined here.
+//   abstract final int declaredAbstractExtendsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:14:22: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractField' is defined here.
+//   abstract final int declaredConcreteExtendsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:8:22: Context: 'ConcreteSuper.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractField
+//  - ConcreteClass.declaredAbstractField
+//  - ConcreteSuper.extendedAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:30:22: Context: 'ConcreteClass.declaredAbstractExtendsAbstractField' is defined here.
+//   abstract final int declaredAbstractExtendsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:22:22: Context: 'ConcreteClass.declaredAbstractField' is defined here.
+//   abstract final int declaredAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:8:22: Context: 'ConcreteSuper.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  final field core::int extendedConcreteField = 0;
+  final field core::int declaredConcreteExtendsConcreteField = 0;
+  final field core::int declaredAbstractExtendsConcreteField = 0;
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract get declaredConcreteExtendsAbstractField() → core::int;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  final field core::int declaredConcreteField = 0;
+  final field core::int declaredConcreteExtendsConcreteField = 0;
+  final field core::int declaredConcreteExtendsAbstractField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract get declaredAbstractExtendsConcreteField() → core::int;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..4b81a56
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart.weak.transformed.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractField
+//  - ConcreteSuper.declaredConcreteExtendsAbstractField
+//  - ConcreteSuper.extendedAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:16:22: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractField' is defined here.
+//   abstract final int declaredAbstractExtendsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:14:22: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractField' is defined here.
+//   abstract final int declaredConcreteExtendsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:8:22: Context: 'ConcreteSuper.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractField
+//  - ConcreteClass.declaredAbstractField
+//  - ConcreteSuper.extendedAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:30:22: Context: 'ConcreteClass.declaredAbstractExtendsAbstractField' is defined here.
+//   abstract final int declaredAbstractExtendsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:22:22: Context: 'ConcreteClass.declaredAbstractField' is defined here.
+//   abstract final int declaredAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_final_field.dart:8:22: Context: 'ConcreteSuper.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  final field core::int extendedConcreteField = 0;
+  final field core::int declaredConcreteExtendsConcreteField = 0;
+  final field core::int declaredAbstractExtendsConcreteField = 0;
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract get declaredConcreteExtendsAbstractField() → core::int;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  final field core::int declaredConcreteField = 0;
+  final field core::int declaredConcreteExtendsConcreteField = 0;
+  final field core::int declaredConcreteExtendsAbstractField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract get declaredAbstractExtendsConcreteField() → core::int;
+  abstract get declaredAbstractExtendsAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart
new file mode 100644
index 0000000..da7068b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.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.
+
+class ConcreteSuper {
+  int get extendedConcreteGetter => 0;
+
+  int get extendedAbstractGetter;
+
+  int get declaredConcreteExtendsConcreteGetter => 0;
+
+  int get declaredAbstractExtendsConcreteGetter => 0;
+
+  int get declaredConcreteExtendsAbstractGetter;
+
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+class ConcreteClass extends ConcreteSuper {
+  int get declaredConcreteGetter => 0;
+
+  int get declaredAbstractGetter;
+
+  int get declaredConcreteExtendsConcreteGetter => 0;
+
+  int get declaredAbstractExtendsConcreteGetter;
+
+  int get declaredConcreteExtendsAbstractGetter => 0;
+
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.textual_outline.expect
new file mode 100644
index 0000000..e077184
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class ConcreteSuper {
+  int get extendedConcreteGetter => 0;
+  int get extendedAbstractGetter;
+  int get declaredConcreteExtendsConcreteGetter => 0;
+  int get declaredAbstractExtendsConcreteGetter => 0;
+  int get declaredConcreteExtendsAbstractGetter;
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+class ConcreteClass extends ConcreteSuper {
+  int get declaredConcreteGetter => 0;
+  int get declaredAbstractGetter;
+  int get declaredConcreteExtendsConcreteGetter => 0;
+  int get declaredAbstractExtendsConcreteGetter;
+  int get declaredConcreteExtendsAbstractGetter => 0;
+  int get declaredAbstractExtendsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..897f7a1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass extends ConcreteSuper {
+  int get declaredAbstractExtendsAbstractGetter;
+  int get declaredAbstractExtendsConcreteGetter;
+  int get declaredAbstractGetter;
+  int get declaredConcreteExtendsAbstractGetter => 0;
+  int get declaredConcreteExtendsConcreteGetter => 0;
+  int get declaredConcreteGetter => 0;
+}
+
+class ConcreteSuper {
+  int get declaredAbstractExtendsAbstractGetter;
+  int get declaredAbstractExtendsConcreteGetter => 0;
+  int get declaredConcreteExtendsAbstractGetter;
+  int get declaredConcreteExtendsConcreteGetter => 0;
+  int get extendedAbstractGetter;
+  int get extendedConcreteGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.weak.expect
new file mode 100644
index 0000000..626d8af
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.weak.expect
@@ -0,0 +1,80 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractGetter
+//  - ConcreteSuper.declaredConcreteExtendsAbstractGetter
+//  - ConcreteSuper.extendedAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:16:11: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractGetter' is defined here.
+//   int get declaredAbstractExtendsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:14:11: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractGetter' is defined here.
+//   int get declaredConcreteExtendsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:8:11: Context: 'ConcreteSuper.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractGetter
+//  - ConcreteClass.declaredAbstractGetter
+//  - ConcreteSuper.extendedAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:30:11: Context: 'ConcreteClass.declaredAbstractExtendsAbstractGetter' is defined here.
+//   int get declaredAbstractExtendsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:22:11: Context: 'ConcreteClass.declaredAbstractGetter' is defined here.
+//   int get declaredAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:8:11: Context: 'ConcreteSuper.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  get extendedConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractGetter() → core::int;
+  get declaredConcreteExtendsConcreteGetter() → core::int
+    return 0;
+  get declaredAbstractExtendsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredConcreteExtendsAbstractGetter() → core::int;
+  abstract get declaredAbstractExtendsAbstractGetter() → core::int;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  get declaredConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractGetter() → core::int;
+  get declaredConcreteExtendsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractExtendsConcreteGetter() → core::int;
+  get declaredConcreteExtendsAbstractGetter() → core::int
+    return 0;
+  abstract get declaredAbstractExtendsAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.weak.transformed.expect
new file mode 100644
index 0000000..626d8af
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart.weak.transformed.expect
@@ -0,0 +1,80 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractGetter
+//  - ConcreteSuper.declaredConcreteExtendsAbstractGetter
+//  - ConcreteSuper.extendedAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:16:11: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractGetter' is defined here.
+//   int get declaredAbstractExtendsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:14:11: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractGetter' is defined here.
+//   int get declaredConcreteExtendsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:8:11: Context: 'ConcreteSuper.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractGetter
+//  - ConcreteClass.declaredAbstractGetter
+//  - ConcreteSuper.extendedAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:30:11: Context: 'ConcreteClass.declaredAbstractExtendsAbstractGetter' is defined here.
+//   int get declaredAbstractExtendsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:22:11: Context: 'ConcreteClass.declaredAbstractGetter' is defined here.
+//   int get declaredAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_getter.dart:8:11: Context: 'ConcreteSuper.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  get extendedConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractGetter() → core::int;
+  get declaredConcreteExtendsConcreteGetter() → core::int
+    return 0;
+  get declaredAbstractExtendsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredConcreteExtendsAbstractGetter() → core::int;
+  abstract get declaredAbstractExtendsAbstractGetter() → core::int;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  get declaredConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractGetter() → core::int;
+  get declaredConcreteExtendsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractExtendsConcreteGetter() → core::int;
+  get declaredConcreteExtendsAbstractGetter() → core::int
+    return 0;
+  abstract get declaredAbstractExtendsAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart
new file mode 100644
index 0000000..49f2893
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.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.
+
+class ConcreteSuper {
+  void extendedConcreteMethod() {}
+
+  void extendedAbstractMethod();
+
+  void declaredConcreteExtendsConcreteMethod() {}
+
+  void declaredAbstractExtendsConcreteMethod() {}
+
+  void declaredConcreteExtendsAbstractMethod();
+
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+class ConcreteClass extends ConcreteSuper {
+  void declaredConcreteMethod() {}
+
+  void declaredAbstractMethod();
+
+  void declaredConcreteExtendsConcreteMethod() {}
+
+  void declaredAbstractExtendsConcreteMethod();
+
+  void declaredConcreteExtendsAbstractMethod() {}
+
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.textual_outline.expect
new file mode 100644
index 0000000..ccf2808
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class ConcreteSuper {
+  void extendedConcreteMethod() {}
+  void extendedAbstractMethod();
+  void declaredConcreteExtendsConcreteMethod() {}
+  void declaredAbstractExtendsConcreteMethod() {}
+  void declaredConcreteExtendsAbstractMethod();
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+class ConcreteClass extends ConcreteSuper {
+  void declaredConcreteMethod() {}
+  void declaredAbstractMethod();
+  void declaredConcreteExtendsConcreteMethod() {}
+  void declaredAbstractExtendsConcreteMethod();
+  void declaredConcreteExtendsAbstractMethod() {}
+  void declaredAbstractExtendsAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b49277b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass extends ConcreteSuper {
+  void declaredAbstractExtendsAbstractMethod();
+  void declaredAbstractExtendsConcreteMethod();
+  void declaredAbstractMethod();
+  void declaredConcreteExtendsAbstractMethod() {}
+  void declaredConcreteExtendsConcreteMethod() {}
+  void declaredConcreteMethod() {}
+}
+
+class ConcreteSuper {
+  void declaredAbstractExtendsAbstractMethod();
+  void declaredAbstractExtendsConcreteMethod() {}
+  void declaredConcreteExtendsAbstractMethod();
+  void declaredConcreteExtendsConcreteMethod() {}
+  void extendedAbstractMethod();
+  void extendedConcreteMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.weak.expect
new file mode 100644
index 0000000..0eba0b9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.weak.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractMethod
+//  - ConcreteSuper.declaredConcreteExtendsAbstractMethod
+//  - ConcreteSuper.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:16:8: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractMethod' is defined here.
+//   void declaredAbstractExtendsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:14:8: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractMethod' is defined here.
+//   void declaredConcreteExtendsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:8:8: Context: 'ConcreteSuper.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractMethod
+//  - ConcreteClass.declaredAbstractMethod
+//  - ConcreteSuper.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:30:8: Context: 'ConcreteClass.declaredAbstractExtendsAbstractMethod' is defined here.
+//   void declaredAbstractExtendsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:22:8: Context: 'ConcreteClass.declaredAbstractMethod' is defined here.
+//   void declaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:8:8: Context: 'ConcreteSuper.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method declaredConcreteExtendsConcreteMethod() → void {}
+  method declaredAbstractExtendsConcreteMethod() → void {}
+  abstract method declaredConcreteExtendsAbstractMethod() → void;
+  abstract method declaredAbstractExtendsAbstractMethod() → void;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  method declaredConcreteMethod() → void {}
+  abstract method declaredAbstractMethod() → void;
+  method declaredConcreteExtendsConcreteMethod() → void {}
+  abstract method declaredAbstractExtendsConcreteMethod() → void;
+  method declaredConcreteExtendsAbstractMethod() → void {}
+  abstract method declaredAbstractExtendsAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..0eba0b9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart.weak.transformed.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractMethod
+//  - ConcreteSuper.declaredConcreteExtendsAbstractMethod
+//  - ConcreteSuper.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:16:8: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractMethod' is defined here.
+//   void declaredAbstractExtendsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:14:8: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractMethod' is defined here.
+//   void declaredConcreteExtendsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:8:8: Context: 'ConcreteSuper.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractMethod
+//  - ConcreteClass.declaredAbstractMethod
+//  - ConcreteSuper.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:30:8: Context: 'ConcreteClass.declaredAbstractExtendsAbstractMethod' is defined here.
+//   void declaredAbstractExtendsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:22:8: Context: 'ConcreteClass.declaredAbstractMethod' is defined here.
+//   void declaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_method.dart:8:8: Context: 'ConcreteSuper.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method declaredConcreteExtendsConcreteMethod() → void {}
+  method declaredAbstractExtendsConcreteMethod() → void {}
+  abstract method declaredConcreteExtendsAbstractMethod() → void;
+  abstract method declaredAbstractExtendsAbstractMethod() → void;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  method declaredConcreteMethod() → void {}
+  abstract method declaredAbstractMethod() → void;
+  method declaredConcreteExtendsConcreteMethod() → void {}
+  abstract method declaredAbstractExtendsConcreteMethod() → void;
+  method declaredConcreteExtendsAbstractMethod() → void {}
+  abstract method declaredAbstractExtendsAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart
new file mode 100644
index 0000000..e3c8c81
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.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.
+
+class ConcreteSuper {
+  void set extendedConcreteSetter(int value) {}
+
+  void set extendedAbstractSetter(int value);
+
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+
+  void set declaredAbstractExtendsConcreteSetter(int value) {}
+
+  void set declaredConcreteExtendsAbstractSetter(int value);
+
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+class ConcreteClass extends ConcreteSuper {
+  void set declaredConcreteSetter(int value) {}
+
+  void set declaredAbstractSetter(int value);
+
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+
+  void set declaredAbstractExtendsConcreteSetter(int value);
+
+  void set declaredConcreteExtendsAbstractSetter(int value) {}
+
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..74b46ce
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class ConcreteSuper {
+  void set extendedConcreteSetter(int value) {}
+  void set extendedAbstractSetter(int value);
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+  void set declaredAbstractExtendsConcreteSetter(int value) {}
+  void set declaredConcreteExtendsAbstractSetter(int value);
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+class ConcreteClass extends ConcreteSuper {
+  void set declaredConcreteSetter(int value) {}
+  void set declaredAbstractSetter(int value);
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+  void set declaredAbstractExtendsConcreteSetter(int value);
+  void set declaredConcreteExtendsAbstractSetter(int value) {}
+  void set declaredAbstractExtendsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5976614
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass extends ConcreteSuper {
+  void set declaredAbstractExtendsAbstractSetter(int value);
+  void set declaredAbstractExtendsConcreteSetter(int value);
+  void set declaredAbstractSetter(int value);
+  void set declaredConcreteExtendsAbstractSetter(int value) {}
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+  void set declaredConcreteSetter(int value) {}
+}
+
+class ConcreteSuper {
+  void set declaredAbstractExtendsAbstractSetter(int value);
+  void set declaredAbstractExtendsConcreteSetter(int value) {}
+  void set declaredConcreteExtendsAbstractSetter(int value);
+  void set declaredConcreteExtendsConcreteSetter(int value) {}
+  void set extendedAbstractSetter(int value);
+  void set extendedConcreteSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.weak.expect
new file mode 100644
index 0000000..2df220c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.weak.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractSetter=
+//  - ConcreteSuper.declaredConcreteExtendsAbstractSetter=
+//  - ConcreteSuper.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:16:12: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractSetter=' is defined here.
+//   void set declaredAbstractExtendsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:14:12: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractSetter=' is defined here.
+//   void set declaredConcreteExtendsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:8:12: Context: 'ConcreteSuper.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractSetter=
+//  - ConcreteClass.declaredAbstractSetter=
+//  - ConcreteSuper.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:30:12: Context: 'ConcreteClass.declaredAbstractExtendsAbstractSetter=' is defined here.
+//   void set declaredAbstractExtendsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:22:12: Context: 'ConcreteClass.declaredAbstractSetter=' is defined here.
+//   void set declaredAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:8:12: Context: 'ConcreteSuper.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  set extendedConcreteSetter(core::int value) → void {}
+  abstract set extendedAbstractSetter(core::int value) → void;
+  set declaredConcreteExtendsConcreteSetter(core::int value) → void {}
+  set declaredAbstractExtendsConcreteSetter(core::int value) → void {}
+  abstract set declaredConcreteExtendsAbstractSetter(core::int value) → void;
+  abstract set declaredAbstractExtendsAbstractSetter(core::int value) → void;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  set declaredConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractSetter(core::int value) → void;
+  set declaredConcreteExtendsConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractExtendsConcreteSetter(core::int value) → void;
+  set declaredConcreteExtendsAbstractSetter(core::int value) → void {}
+  abstract set declaredAbstractExtendsAbstractSetter(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.weak.transformed.expect
new file mode 100644
index 0000000..2df220c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart.weak.transformed.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:5:7: Error: The non-abstract class 'ConcreteSuper' is missing implementations for these members:
+//  - ConcreteSuper.declaredAbstractExtendsAbstractSetter=
+//  - ConcreteSuper.declaredConcreteExtendsAbstractSetter=
+//  - ConcreteSuper.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:16:12: Context: 'ConcreteSuper.declaredAbstractExtendsAbstractSetter=' is defined here.
+//   void set declaredAbstractExtendsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:14:12: Context: 'ConcreteSuper.declaredConcreteExtendsAbstractSetter=' is defined here.
+//   void set declaredConcreteExtendsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:8:12: Context: 'ConcreteSuper.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractExtendsAbstractSetter=
+//  - ConcreteClass.declaredAbstractSetter=
+//  - ConcreteSuper.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends ConcreteSuper {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:30:12: Context: 'ConcreteClass.declaredAbstractExtendsAbstractSetter=' is defined here.
+//   void set declaredAbstractExtendsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:22:12: Context: 'ConcreteClass.declaredAbstractSetter=' is defined here.
+//   void set declaredAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_extends_setter.dart:8:12: Context: 'ConcreteSuper.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class ConcreteSuper extends core::Object {
+  synthetic constructor •() → self::ConcreteSuper
+    : super core::Object::•()
+    ;
+  set extendedConcreteSetter(core::int value) → void {}
+  abstract set extendedAbstractSetter(core::int value) → void;
+  set declaredConcreteExtendsConcreteSetter(core::int value) → void {}
+  set declaredAbstractExtendsConcreteSetter(core::int value) → void {}
+  abstract set declaredConcreteExtendsAbstractSetter(core::int value) → void;
+  abstract set declaredAbstractExtendsAbstractSetter(core::int value) → void;
+}
+class ConcreteClass extends self::ConcreteSuper {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::ConcreteSuper::•()
+    ;
+  set declaredConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractSetter(core::int value) → void;
+  set declaredConcreteExtendsConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractExtendsConcreteSetter(core::int value) → void;
+  set declaredConcreteExtendsAbstractSetter(core::int value) → void {}
+  abstract set declaredAbstractExtendsAbstractSetter(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart
new file mode 100644
index 0000000..991ee10
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.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.
+
+class Interface {
+  int implementedConcreteField = 0;
+
+  abstract int implementedAbstractField;
+
+  int declaredConcreteImplementsConcreteField = 0;
+
+  int declaredAbstractImplementsConcreteField = 0;
+
+  abstract int declaredConcreteImplementsAbstractField;
+
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+class ConcreteClass implements Interface {
+  int declaredConcreteField = 0;
+
+  abstract int declaredAbstractField;
+
+  int declaredConcreteImplementsConcreteField = 0;
+
+  abstract int declaredAbstractImplementsConcreteField;
+
+  int declaredConcreteImplementsAbstractField = 0;
+
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.textual_outline.expect
new file mode 100644
index 0000000..910a8cf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class Interface {
+  int implementedConcreteField = 0;
+  abstract int implementedAbstractField;
+  int declaredConcreteImplementsConcreteField = 0;
+  int declaredAbstractImplementsConcreteField = 0;
+  abstract int declaredConcreteImplementsAbstractField;
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+class ConcreteClass implements Interface {
+  int declaredConcreteField = 0;
+  abstract int declaredAbstractField;
+  int declaredConcreteImplementsConcreteField = 0;
+  abstract int declaredAbstractImplementsConcreteField;
+  int declaredConcreteImplementsAbstractField = 0;
+  abstract int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f0bdbe5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass implements Interface {
+  abstract int declaredAbstractField;
+  abstract int declaredAbstractImplementsAbstractField;
+  abstract int declaredAbstractImplementsConcreteField;
+  int declaredConcreteField = 0;
+  int declaredConcreteImplementsAbstractField = 0;
+  int declaredConcreteImplementsConcreteField = 0;
+}
+
+class Interface {
+  abstract int declaredAbstractImplementsAbstractField;
+  abstract int declaredConcreteImplementsAbstractField;
+  abstract int implementedAbstractField;
+  int declaredAbstractImplementsConcreteField = 0;
+  int declaredConcreteImplementsConcreteField = 0;
+  int implementedConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.weak.expect
new file mode 100644
index 0000000..3c9afcd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.weak.expect
@@ -0,0 +1,116 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractField
+//  - Interface.declaredAbstractImplementsAbstractField=
+//  - Interface.declaredConcreteImplementsAbstractField
+//  - Interface.declaredConcreteImplementsAbstractField=
+//  - Interface.implementedAbstractField
+//  - Interface.implementedAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:16:16: Context: 'Interface.declaredAbstractImplementsAbstractField' is defined here.
+//   abstract int declaredAbstractImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:16:16: Context: 'Interface.declaredAbstractImplementsAbstractField=' is defined here.
+//   abstract int declaredAbstractImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:14:16: Context: 'Interface.declaredConcreteImplementsAbstractField' is defined here.
+//   abstract int declaredConcreteImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:14:16: Context: 'Interface.declaredConcreteImplementsAbstractField=' is defined here.
+//   abstract int declaredConcreteImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:8:16: Context: 'Interface.implementedAbstractField' is defined here.
+//   abstract int implementedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:8:16: Context: 'Interface.implementedAbstractField=' is defined here.
+//   abstract int implementedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractField
+//  - ConcreteClass.declaredAbstractField=
+//  - ConcreteClass.declaredAbstractImplementsAbstractField
+//  - ConcreteClass.declaredAbstractImplementsAbstractField=
+//  - ConcreteClass.declaredAbstractImplementsConcreteField
+//  - ConcreteClass.declaredAbstractImplementsConcreteField=
+//  - Interface.implementedAbstractField
+//  - Interface.implementedAbstractField=
+//  - Interface.implementedConcreteField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:22:16: Context: 'ConcreteClass.declaredAbstractField' is defined here.
+//   abstract int declaredAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:22:16: Context: 'ConcreteClass.declaredAbstractField=' is defined here.
+//   abstract int declaredAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:30:16: Context: 'ConcreteClass.declaredAbstractImplementsAbstractField' is defined here.
+//   abstract int declaredAbstractImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:30:16: Context: 'ConcreteClass.declaredAbstractImplementsAbstractField=' is defined here.
+//   abstract int declaredAbstractImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:26:16: Context: 'ConcreteClass.declaredAbstractImplementsConcreteField' is defined here.
+//   abstract int declaredAbstractImplementsConcreteField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:26:16: Context: 'ConcreteClass.declaredAbstractImplementsConcreteField=' is defined here.
+//   abstract int declaredAbstractImplementsConcreteField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:8:16: Context: 'Interface.implementedAbstractField' is defined here.
+//   abstract int implementedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:8:16: Context: 'Interface.implementedAbstractField=' is defined here.
+//   abstract int implementedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:6:7: Context: 'Interface.implementedConcreteField' is defined here.
+//   int implementedConcreteField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  field core::int implementedConcreteField = 0;
+  field core::int declaredConcreteImplementsConcreteField = 0;
+  field core::int declaredAbstractImplementsConcreteField = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract get implementedAbstractField() → core::int;
+  abstract set implementedAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredConcreteImplementsAbstractField() → core::int;
+  abstract set declaredConcreteImplementsAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+  abstract set declaredAbstractImplementsAbstractField(core::int #externalFieldValue) → void;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  field core::int declaredConcreteField = 0;
+  field core::int declaredConcreteImplementsConcreteField = 0;
+  field core::int declaredConcreteImplementsAbstractField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract set declaredAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsConcreteField() → core::int;
+  abstract set declaredAbstractImplementsConcreteField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+  abstract set declaredAbstractImplementsAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..3c9afcd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart.weak.transformed.expect
@@ -0,0 +1,116 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractField
+//  - Interface.declaredAbstractImplementsAbstractField=
+//  - Interface.declaredConcreteImplementsAbstractField
+//  - Interface.declaredConcreteImplementsAbstractField=
+//  - Interface.implementedAbstractField
+//  - Interface.implementedAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:16:16: Context: 'Interface.declaredAbstractImplementsAbstractField' is defined here.
+//   abstract int declaredAbstractImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:16:16: Context: 'Interface.declaredAbstractImplementsAbstractField=' is defined here.
+//   abstract int declaredAbstractImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:14:16: Context: 'Interface.declaredConcreteImplementsAbstractField' is defined here.
+//   abstract int declaredConcreteImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:14:16: Context: 'Interface.declaredConcreteImplementsAbstractField=' is defined here.
+//   abstract int declaredConcreteImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:8:16: Context: 'Interface.implementedAbstractField' is defined here.
+//   abstract int implementedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:8:16: Context: 'Interface.implementedAbstractField=' is defined here.
+//   abstract int implementedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractField
+//  - ConcreteClass.declaredAbstractField=
+//  - ConcreteClass.declaredAbstractImplementsAbstractField
+//  - ConcreteClass.declaredAbstractImplementsAbstractField=
+//  - ConcreteClass.declaredAbstractImplementsConcreteField
+//  - ConcreteClass.declaredAbstractImplementsConcreteField=
+//  - Interface.implementedAbstractField
+//  - Interface.implementedAbstractField=
+//  - Interface.implementedConcreteField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:22:16: Context: 'ConcreteClass.declaredAbstractField' is defined here.
+//   abstract int declaredAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:22:16: Context: 'ConcreteClass.declaredAbstractField=' is defined here.
+//   abstract int declaredAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:30:16: Context: 'ConcreteClass.declaredAbstractImplementsAbstractField' is defined here.
+//   abstract int declaredAbstractImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:30:16: Context: 'ConcreteClass.declaredAbstractImplementsAbstractField=' is defined here.
+//   abstract int declaredAbstractImplementsAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:26:16: Context: 'ConcreteClass.declaredAbstractImplementsConcreteField' is defined here.
+//   abstract int declaredAbstractImplementsConcreteField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:26:16: Context: 'ConcreteClass.declaredAbstractImplementsConcreteField=' is defined here.
+//   abstract int declaredAbstractImplementsConcreteField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:8:16: Context: 'Interface.implementedAbstractField' is defined here.
+//   abstract int implementedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:8:16: Context: 'Interface.implementedAbstractField=' is defined here.
+//   abstract int implementedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_field.dart:6:7: Context: 'Interface.implementedConcreteField' is defined here.
+//   int implementedConcreteField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  field core::int implementedConcreteField = 0;
+  field core::int declaredConcreteImplementsConcreteField = 0;
+  field core::int declaredAbstractImplementsConcreteField = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract get implementedAbstractField() → core::int;
+  abstract set implementedAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredConcreteImplementsAbstractField() → core::int;
+  abstract set declaredConcreteImplementsAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+  abstract set declaredAbstractImplementsAbstractField(core::int #externalFieldValue) → void;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  field core::int declaredConcreteField = 0;
+  field core::int declaredConcreteImplementsConcreteField = 0;
+  field core::int declaredConcreteImplementsAbstractField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract set declaredAbstractField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsConcreteField() → core::int;
+  abstract set declaredAbstractImplementsConcreteField(core::int #externalFieldValue) → void;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+  abstract set declaredAbstractImplementsAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart
new file mode 100644
index 0000000..1bacb92
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.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.
+
+class Interface {
+  final int implementedConcreteField = 0;
+
+  abstract final int implementedAbstractField;
+
+  final int declaredConcreteImplementsConcreteField = 0;
+
+  final int declaredAbstractImplementsConcreteField = 0;
+
+  abstract final int declaredConcreteImplementsAbstractField;
+
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+class ConcreteClass implements Interface {
+  final int declaredConcreteField = 0;
+
+  abstract final int declaredAbstractField;
+
+  final int declaredConcreteImplementsConcreteField = 0;
+
+  abstract final int declaredAbstractImplementsConcreteField;
+
+  final int declaredConcreteImplementsAbstractField = 0;
+
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.textual_outline.expect
new file mode 100644
index 0000000..92f0a43
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class Interface {
+  final int implementedConcreteField = 0;
+  abstract final int implementedAbstractField;
+  final int declaredConcreteImplementsConcreteField = 0;
+  final int declaredAbstractImplementsConcreteField = 0;
+  abstract final int declaredConcreteImplementsAbstractField;
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+class ConcreteClass implements Interface {
+  final int declaredConcreteField = 0;
+  abstract final int declaredAbstractField;
+  final int declaredConcreteImplementsConcreteField = 0;
+  abstract final int declaredAbstractImplementsConcreteField;
+  final int declaredConcreteImplementsAbstractField = 0;
+  abstract final int declaredAbstractImplementsAbstractField;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cdd8b25
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass implements Interface {
+  abstract final int declaredAbstractField;
+  abstract final int declaredAbstractImplementsAbstractField;
+  abstract final int declaredAbstractImplementsConcreteField;
+  final int declaredConcreteField = 0;
+  final int declaredConcreteImplementsAbstractField = 0;
+  final int declaredConcreteImplementsConcreteField = 0;
+}
+
+class Interface {
+  abstract final int declaredAbstractImplementsAbstractField;
+  abstract final int declaredConcreteImplementsAbstractField;
+  abstract final int implementedAbstractField;
+  final int declaredAbstractImplementsConcreteField = 0;
+  final int declaredConcreteImplementsConcreteField = 0;
+  final int implementedConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.weak.expect
new file mode 100644
index 0000000..921aaec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.weak.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractField
+//  - Interface.declaredConcreteImplementsAbstractField
+//  - Interface.implementedAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:16:22: Context: 'Interface.declaredAbstractImplementsAbstractField' is defined here.
+//   abstract final int declaredAbstractImplementsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:14:22: Context: 'Interface.declaredConcreteImplementsAbstractField' is defined here.
+//   abstract final int declaredConcreteImplementsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:8:22: Context: 'Interface.implementedAbstractField' is defined here.
+//   abstract final int implementedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractField
+//  - ConcreteClass.declaredAbstractImplementsAbstractField
+//  - ConcreteClass.declaredAbstractImplementsConcreteField
+//  - Interface.implementedAbstractField
+//  - Interface.implementedConcreteField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:22:22: Context: 'ConcreteClass.declaredAbstractField' is defined here.
+//   abstract final int declaredAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:30:22: Context: 'ConcreteClass.declaredAbstractImplementsAbstractField' is defined here.
+//   abstract final int declaredAbstractImplementsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:26:22: Context: 'ConcreteClass.declaredAbstractImplementsConcreteField' is defined here.
+//   abstract final int declaredAbstractImplementsConcreteField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:8:22: Context: 'Interface.implementedAbstractField' is defined here.
+//   abstract final int implementedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:6:13: Context: 'Interface.implementedConcreteField' is defined here.
+//   final int implementedConcreteField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  final field core::int implementedConcreteField = 0;
+  final field core::int declaredConcreteImplementsConcreteField = 0;
+  final field core::int declaredAbstractImplementsConcreteField = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract get implementedAbstractField() → core::int;
+  abstract get declaredConcreteImplementsAbstractField() → core::int;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  final field core::int declaredConcreteField = 0;
+  final field core::int declaredConcreteImplementsConcreteField = 0;
+  final field core::int declaredConcreteImplementsAbstractField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract get declaredAbstractImplementsConcreteField() → core::int;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..921aaec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart.weak.transformed.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractField
+//  - Interface.declaredConcreteImplementsAbstractField
+//  - Interface.implementedAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:16:22: Context: 'Interface.declaredAbstractImplementsAbstractField' is defined here.
+//   abstract final int declaredAbstractImplementsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:14:22: Context: 'Interface.declaredConcreteImplementsAbstractField' is defined here.
+//   abstract final int declaredConcreteImplementsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:8:22: Context: 'Interface.implementedAbstractField' is defined here.
+//   abstract final int implementedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractField
+//  - ConcreteClass.declaredAbstractImplementsAbstractField
+//  - ConcreteClass.declaredAbstractImplementsConcreteField
+//  - Interface.implementedAbstractField
+//  - Interface.implementedConcreteField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:22:22: Context: 'ConcreteClass.declaredAbstractField' is defined here.
+//   abstract final int declaredAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:30:22: Context: 'ConcreteClass.declaredAbstractImplementsAbstractField' is defined here.
+//   abstract final int declaredAbstractImplementsAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:26:22: Context: 'ConcreteClass.declaredAbstractImplementsConcreteField' is defined here.
+//   abstract final int declaredAbstractImplementsConcreteField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:8:22: Context: 'Interface.implementedAbstractField' is defined here.
+//   abstract final int implementedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_final_field.dart:6:13: Context: 'Interface.implementedConcreteField' is defined here.
+//   final int implementedConcreteField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  final field core::int implementedConcreteField = 0;
+  final field core::int declaredConcreteImplementsConcreteField = 0;
+  final field core::int declaredAbstractImplementsConcreteField = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract get implementedAbstractField() → core::int;
+  abstract get declaredConcreteImplementsAbstractField() → core::int;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  final field core::int declaredConcreteField = 0;
+  final field core::int declaredConcreteImplementsConcreteField = 0;
+  final field core::int declaredConcreteImplementsAbstractField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  abstract get declaredAbstractField() → core::int;
+  abstract get declaredAbstractImplementsConcreteField() → core::int;
+  abstract get declaredAbstractImplementsAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart
new file mode 100644
index 0000000..86db3b5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.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.
+
+class Interface {
+  int get implementedConcreteGetter => 0;
+
+  int get implementedAbstractGetter;
+
+  int get declaredConcreteImplementsConcreteGetter => 0;
+
+  int get declaredAbstractImplementsConcreteGetter => 0;
+
+  int get declaredConcreteImplementsAbstractGetter;
+
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+class ConcreteClass implements Interface {
+  int get declaredConcreteGetter => 0;
+
+  int get declaredAbstractGetter;
+
+  int get declaredConcreteImplementsConcreteGetter => 0;
+
+  int get declaredAbstractImplementsConcreteGetter;
+
+  int get declaredConcreteImplementsAbstractGetter => 0;
+
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.textual_outline.expect
new file mode 100644
index 0000000..699fb25
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class Interface {
+  int get implementedConcreteGetter => 0;
+  int get implementedAbstractGetter;
+  int get declaredConcreteImplementsConcreteGetter => 0;
+  int get declaredAbstractImplementsConcreteGetter => 0;
+  int get declaredConcreteImplementsAbstractGetter;
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+class ConcreteClass implements Interface {
+  int get declaredConcreteGetter => 0;
+  int get declaredAbstractGetter;
+  int get declaredConcreteImplementsConcreteGetter => 0;
+  int get declaredAbstractImplementsConcreteGetter;
+  int get declaredConcreteImplementsAbstractGetter => 0;
+  int get declaredAbstractImplementsAbstractGetter;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..80ed155
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass implements Interface {
+  int get declaredAbstractGetter;
+  int get declaredAbstractImplementsAbstractGetter;
+  int get declaredAbstractImplementsConcreteGetter;
+  int get declaredConcreteGetter => 0;
+  int get declaredConcreteImplementsAbstractGetter => 0;
+  int get declaredConcreteImplementsConcreteGetter => 0;
+}
+
+class Interface {
+  int get declaredAbstractImplementsAbstractGetter;
+  int get declaredAbstractImplementsConcreteGetter => 0;
+  int get declaredConcreteImplementsAbstractGetter;
+  int get declaredConcreteImplementsConcreteGetter => 0;
+  int get implementedAbstractGetter;
+  int get implementedConcreteGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.weak.expect
new file mode 100644
index 0000000..5c3ce45
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.weak.expect
@@ -0,0 +1,88 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractGetter
+//  - Interface.declaredConcreteImplementsAbstractGetter
+//  - Interface.implementedAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:16:11: Context: 'Interface.declaredAbstractImplementsAbstractGetter' is defined here.
+//   int get declaredAbstractImplementsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:14:11: Context: 'Interface.declaredConcreteImplementsAbstractGetter' is defined here.
+//   int get declaredConcreteImplementsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:8:11: Context: 'Interface.implementedAbstractGetter' is defined here.
+//   int get implementedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractGetter
+//  - ConcreteClass.declaredAbstractImplementsAbstractGetter
+//  - ConcreteClass.declaredAbstractImplementsConcreteGetter
+//  - Interface.implementedAbstractGetter
+//  - Interface.implementedConcreteGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:22:11: Context: 'ConcreteClass.declaredAbstractGetter' is defined here.
+//   int get declaredAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:30:11: Context: 'ConcreteClass.declaredAbstractImplementsAbstractGetter' is defined here.
+//   int get declaredAbstractImplementsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:26:11: Context: 'ConcreteClass.declaredAbstractImplementsConcreteGetter' is defined here.
+//   int get declaredAbstractImplementsConcreteGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:8:11: Context: 'Interface.implementedAbstractGetter' is defined here.
+//   int get implementedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:6:11: Context: 'Interface.implementedConcreteGetter' is defined here.
+//   int get implementedConcreteGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  get implementedConcreteGetter() → core::int
+    return 0;
+  abstract get implementedAbstractGetter() → core::int;
+  get declaredConcreteImplementsConcreteGetter() → core::int
+    return 0;
+  get declaredAbstractImplementsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredConcreteImplementsAbstractGetter() → core::int;
+  abstract get declaredAbstractImplementsAbstractGetter() → core::int;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  get declaredConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractGetter() → core::int;
+  get declaredConcreteImplementsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractImplementsConcreteGetter() → core::int;
+  get declaredConcreteImplementsAbstractGetter() → core::int
+    return 0;
+  abstract get declaredAbstractImplementsAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.weak.transformed.expect
new file mode 100644
index 0000000..5c3ce45
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart.weak.transformed.expect
@@ -0,0 +1,88 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractGetter
+//  - Interface.declaredConcreteImplementsAbstractGetter
+//  - Interface.implementedAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:16:11: Context: 'Interface.declaredAbstractImplementsAbstractGetter' is defined here.
+//   int get declaredAbstractImplementsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:14:11: Context: 'Interface.declaredConcreteImplementsAbstractGetter' is defined here.
+//   int get declaredConcreteImplementsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:8:11: Context: 'Interface.implementedAbstractGetter' is defined here.
+//   int get implementedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractGetter
+//  - ConcreteClass.declaredAbstractImplementsAbstractGetter
+//  - ConcreteClass.declaredAbstractImplementsConcreteGetter
+//  - Interface.implementedAbstractGetter
+//  - Interface.implementedConcreteGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:22:11: Context: 'ConcreteClass.declaredAbstractGetter' is defined here.
+//   int get declaredAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:30:11: Context: 'ConcreteClass.declaredAbstractImplementsAbstractGetter' is defined here.
+//   int get declaredAbstractImplementsAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:26:11: Context: 'ConcreteClass.declaredAbstractImplementsConcreteGetter' is defined here.
+//   int get declaredAbstractImplementsConcreteGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:8:11: Context: 'Interface.implementedAbstractGetter' is defined here.
+//   int get implementedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_getter.dart:6:11: Context: 'Interface.implementedConcreteGetter' is defined here.
+//   int get implementedConcreteGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  get implementedConcreteGetter() → core::int
+    return 0;
+  abstract get implementedAbstractGetter() → core::int;
+  get declaredConcreteImplementsConcreteGetter() → core::int
+    return 0;
+  get declaredAbstractImplementsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredConcreteImplementsAbstractGetter() → core::int;
+  abstract get declaredAbstractImplementsAbstractGetter() → core::int;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  get declaredConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractGetter() → core::int;
+  get declaredConcreteImplementsConcreteGetter() → core::int
+    return 0;
+  abstract get declaredAbstractImplementsConcreteGetter() → core::int;
+  get declaredConcreteImplementsAbstractGetter() → core::int
+    return 0;
+  abstract get declaredAbstractImplementsAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart
new file mode 100644
index 0000000..7f5079e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.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.
+
+class Interface {
+  void implementedConcreteMethod() {}
+
+  void implementedAbstractMethod();
+
+  void declaredConcreteImplementsConcreteMethod() {}
+
+  void declaredAbstractImplementsConcreteMethod() {}
+
+  void declaredConcreteImplementsAbstractMethod();
+
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+class ConcreteClass implements Interface {
+  void declaredConcreteMethod() {}
+
+  void declaredAbstractMethod();
+
+  void declaredConcreteImplementsConcreteMethod() {}
+
+  void declaredAbstractImplementsConcreteMethod();
+
+  void declaredConcreteImplementsAbstractMethod() {}
+
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.textual_outline.expect
new file mode 100644
index 0000000..ce28f1e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class Interface {
+  void implementedConcreteMethod() {}
+  void implementedAbstractMethod();
+  void declaredConcreteImplementsConcreteMethod() {}
+  void declaredAbstractImplementsConcreteMethod() {}
+  void declaredConcreteImplementsAbstractMethod();
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+class ConcreteClass implements Interface {
+  void declaredConcreteMethod() {}
+  void declaredAbstractMethod();
+  void declaredConcreteImplementsConcreteMethod() {}
+  void declaredAbstractImplementsConcreteMethod();
+  void declaredConcreteImplementsAbstractMethod() {}
+  void declaredAbstractImplementsAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5e58135
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass implements Interface {
+  void declaredAbstractImplementsAbstractMethod();
+  void declaredAbstractImplementsConcreteMethod();
+  void declaredAbstractMethod();
+  void declaredConcreteImplementsAbstractMethod() {}
+  void declaredConcreteImplementsConcreteMethod() {}
+  void declaredConcreteMethod() {}
+}
+
+class Interface {
+  void declaredAbstractImplementsAbstractMethod();
+  void declaredAbstractImplementsConcreteMethod() {}
+  void declaredConcreteImplementsAbstractMethod();
+  void declaredConcreteImplementsConcreteMethod() {}
+  void implementedAbstractMethod();
+  void implementedConcreteMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.weak.expect
new file mode 100644
index 0000000..ff9e0ea
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.weak.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractMethod
+//  - Interface.declaredConcreteImplementsAbstractMethod
+//  - Interface.implementedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:16:8: Context: 'Interface.declaredAbstractImplementsAbstractMethod' is defined here.
+//   void declaredAbstractImplementsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:14:8: Context: 'Interface.declaredConcreteImplementsAbstractMethod' is defined here.
+//   void declaredConcreteImplementsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:8:8: Context: 'Interface.implementedAbstractMethod' is defined here.
+//   void implementedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractImplementsAbstractMethod
+//  - ConcreteClass.declaredAbstractImplementsConcreteMethod
+//  - ConcreteClass.declaredAbstractMethod
+//  - Interface.implementedAbstractMethod
+//  - Interface.implementedConcreteMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:30:8: Context: 'ConcreteClass.declaredAbstractImplementsAbstractMethod' is defined here.
+//   void declaredAbstractImplementsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:26:8: Context: 'ConcreteClass.declaredAbstractImplementsConcreteMethod' is defined here.
+//   void declaredAbstractImplementsConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:22:8: Context: 'ConcreteClass.declaredAbstractMethod' is defined here.
+//   void declaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:8:8: Context: 'Interface.implementedAbstractMethod' is defined here.
+//   void implementedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:6:8: Context: 'Interface.implementedConcreteMethod' is defined here.
+//   void implementedConcreteMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method implementedConcreteMethod() → void {}
+  abstract method implementedAbstractMethod() → void;
+  method declaredConcreteImplementsConcreteMethod() → void {}
+  method declaredAbstractImplementsConcreteMethod() → void {}
+  abstract method declaredConcreteImplementsAbstractMethod() → void;
+  abstract method declaredAbstractImplementsAbstractMethod() → void;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  method declaredConcreteMethod() → void {}
+  abstract method declaredAbstractMethod() → void;
+  method declaredConcreteImplementsConcreteMethod() → void {}
+  abstract method declaredAbstractImplementsConcreteMethod() → void;
+  method declaredConcreteImplementsAbstractMethod() → void {}
+  abstract method declaredAbstractImplementsAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..ff9e0ea
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart.weak.transformed.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractMethod
+//  - Interface.declaredConcreteImplementsAbstractMethod
+//  - Interface.implementedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:16:8: Context: 'Interface.declaredAbstractImplementsAbstractMethod' is defined here.
+//   void declaredAbstractImplementsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:14:8: Context: 'Interface.declaredConcreteImplementsAbstractMethod' is defined here.
+//   void declaredConcreteImplementsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:8:8: Context: 'Interface.implementedAbstractMethod' is defined here.
+//   void implementedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractImplementsAbstractMethod
+//  - ConcreteClass.declaredAbstractImplementsConcreteMethod
+//  - ConcreteClass.declaredAbstractMethod
+//  - Interface.implementedAbstractMethod
+//  - Interface.implementedConcreteMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:30:8: Context: 'ConcreteClass.declaredAbstractImplementsAbstractMethod' is defined here.
+//   void declaredAbstractImplementsAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:26:8: Context: 'ConcreteClass.declaredAbstractImplementsConcreteMethod' is defined here.
+//   void declaredAbstractImplementsConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:22:8: Context: 'ConcreteClass.declaredAbstractMethod' is defined here.
+//   void declaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:8:8: Context: 'Interface.implementedAbstractMethod' is defined here.
+//   void implementedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_method.dart:6:8: Context: 'Interface.implementedConcreteMethod' is defined here.
+//   void implementedConcreteMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method implementedConcreteMethod() → void {}
+  abstract method implementedAbstractMethod() → void;
+  method declaredConcreteImplementsConcreteMethod() → void {}
+  method declaredAbstractImplementsConcreteMethod() → void {}
+  abstract method declaredConcreteImplementsAbstractMethod() → void;
+  abstract method declaredAbstractImplementsAbstractMethod() → void;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  method declaredConcreteMethod() → void {}
+  abstract method declaredAbstractMethod() → void;
+  method declaredConcreteImplementsConcreteMethod() → void {}
+  abstract method declaredAbstractImplementsConcreteMethod() → void;
+  method declaredConcreteImplementsAbstractMethod() → void {}
+  abstract method declaredAbstractImplementsAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart
new file mode 100644
index 0000000..97c2bc9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.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.
+
+class Interface {
+  void set implementedConcreteSetter(int value) {}
+
+  void set implementedAbstractSetter(int value);
+
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+
+  void set declaredAbstractImplementsConcreteSetter(int value) {}
+
+  void set declaredConcreteImplementsAbstractSetter(int value);
+
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+class ConcreteClass implements Interface {
+  void set declaredConcreteSetter(int value) {}
+
+  void set declaredAbstractSetter(int value);
+
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+
+  void set declaredAbstractImplementsConcreteSetter(int value);
+
+  void set declaredConcreteImplementsAbstractSetter(int value) {}
+
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..db91b7f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class Interface {
+  void set implementedConcreteSetter(int value) {}
+  void set implementedAbstractSetter(int value);
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+  void set declaredAbstractImplementsConcreteSetter(int value) {}
+  void set declaredConcreteImplementsAbstractSetter(int value);
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+class ConcreteClass implements Interface {
+  void set declaredConcreteSetter(int value) {}
+  void set declaredAbstractSetter(int value);
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+  void set declaredAbstractImplementsConcreteSetter(int value);
+  void set declaredConcreteImplementsAbstractSetter(int value) {}
+  void set declaredAbstractImplementsAbstractSetter(int value);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..be9240a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class ConcreteClass implements Interface {
+  void set declaredAbstractImplementsAbstractSetter(int value);
+  void set declaredAbstractImplementsConcreteSetter(int value);
+  void set declaredAbstractSetter(int value);
+  void set declaredConcreteImplementsAbstractSetter(int value) {}
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+  void set declaredConcreteSetter(int value) {}
+}
+
+class Interface {
+  void set declaredAbstractImplementsAbstractSetter(int value);
+  void set declaredAbstractImplementsConcreteSetter(int value) {}
+  void set declaredConcreteImplementsAbstractSetter(int value);
+  void set declaredConcreteImplementsConcreteSetter(int value) {}
+  void set implementedAbstractSetter(int value);
+  void set implementedConcreteSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.weak.expect
new file mode 100644
index 0000000..ca9b49b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.weak.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractSetter=
+//  - Interface.declaredConcreteImplementsAbstractSetter=
+//  - Interface.implementedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:16:12: Context: 'Interface.declaredAbstractImplementsAbstractSetter=' is defined here.
+//   void set declaredAbstractImplementsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:14:12: Context: 'Interface.declaredConcreteImplementsAbstractSetter=' is defined here.
+//   void set declaredConcreteImplementsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:8:12: Context: 'Interface.implementedAbstractSetter=' is defined here.
+//   void set implementedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractImplementsAbstractSetter=
+//  - ConcreteClass.declaredAbstractImplementsConcreteSetter=
+//  - ConcreteClass.declaredAbstractSetter=
+//  - Interface.implementedAbstractSetter=
+//  - Interface.implementedConcreteSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:30:12: Context: 'ConcreteClass.declaredAbstractImplementsAbstractSetter=' is defined here.
+//   void set declaredAbstractImplementsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:26:12: Context: 'ConcreteClass.declaredAbstractImplementsConcreteSetter=' is defined here.
+//   void set declaredAbstractImplementsConcreteSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:22:12: Context: 'ConcreteClass.declaredAbstractSetter=' is defined here.
+//   void set declaredAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:8:12: Context: 'Interface.implementedAbstractSetter=' is defined here.
+//   void set implementedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:6:12: Context: 'Interface.implementedConcreteSetter=' is defined here.
+//   void set implementedConcreteSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  set implementedConcreteSetter(core::int value) → void {}
+  abstract set implementedAbstractSetter(core::int value) → void;
+  set declaredConcreteImplementsConcreteSetter(core::int value) → void {}
+  set declaredAbstractImplementsConcreteSetter(core::int value) → void {}
+  abstract set declaredConcreteImplementsAbstractSetter(core::int value) → void;
+  abstract set declaredAbstractImplementsAbstractSetter(core::int value) → void;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  set declaredConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractSetter(core::int value) → void;
+  set declaredConcreteImplementsConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractImplementsConcreteSetter(core::int value) → void;
+  set declaredConcreteImplementsAbstractSetter(core::int value) → void {}
+  abstract set declaredAbstractImplementsAbstractSetter(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.weak.transformed.expect
new file mode 100644
index 0000000..ca9b49b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart.weak.transformed.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:5:7: Error: The non-abstract class 'Interface' is missing implementations for these members:
+//  - Interface.declaredAbstractImplementsAbstractSetter=
+//  - Interface.declaredConcreteImplementsAbstractSetter=
+//  - Interface.implementedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Interface {
+//       ^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:16:12: Context: 'Interface.declaredAbstractImplementsAbstractSetter=' is defined here.
+//   void set declaredAbstractImplementsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:14:12: Context: 'Interface.declaredConcreteImplementsAbstractSetter=' is defined here.
+//   void set declaredConcreteImplementsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:8:12: Context: 'Interface.implementedAbstractSetter=' is defined here.
+//   void set implementedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:19:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declaredAbstractImplementsAbstractSetter=
+//  - ConcreteClass.declaredAbstractImplementsConcreteSetter=
+//  - ConcreteClass.declaredAbstractSetter=
+//  - Interface.implementedAbstractSetter=
+//  - Interface.implementedConcreteSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:30:12: Context: 'ConcreteClass.declaredAbstractImplementsAbstractSetter=' is defined here.
+//   void set declaredAbstractImplementsAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:26:12: Context: 'ConcreteClass.declaredAbstractImplementsConcreteSetter=' is defined here.
+//   void set declaredAbstractImplementsConcreteSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:22:12: Context: 'ConcreteClass.declaredAbstractSetter=' is defined here.
+//   void set declaredAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:8:12: Context: 'Interface.implementedAbstractSetter=' is defined here.
+//   void set implementedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/concrete_implements_setter.dart:6:12: Context: 'Interface.implementedConcreteSetter=' is defined here.
+//   void set implementedConcreteSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  set implementedConcreteSetter(core::int value) → void {}
+  abstract set implementedAbstractSetter(core::int value) → void;
+  set declaredConcreteImplementsConcreteSetter(core::int value) → void {}
+  set declaredAbstractImplementsConcreteSetter(core::int value) → void {}
+  abstract set declaredConcreteImplementsAbstractSetter(core::int value) → void;
+  abstract set declaredAbstractImplementsAbstractSetter(core::int value) → void;
+}
+class ConcreteClass extends core::Object implements self::Interface {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  set declaredConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractSetter(core::int value) → void;
+  set declaredConcreteImplementsConcreteSetter(core::int value) → void {}
+  abstract set declaredAbstractImplementsConcreteSetter(core::int value) → void;
+  set declaredConcreteImplementsAbstractSetter(core::int value) → void {}
+  abstract set declaredAbstractImplementsAbstractSetter(core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart
new file mode 100644
index 0000000..7e7cb73
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart
@@ -0,0 +1,118 @@
+// 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 Super {
+  void extendedMethodDeclaredGetter() {}
+  void extendedMethodDeclaredSetter() {}
+  void extendedMethodDeclaredField() {}
+  int get extendedGetterDeclaredMethod => 0;
+  void set extendedSetterDeclaredMethod(int value) {}
+  int extendedFieldDeclaredMethod = 0;
+
+  void extendedMethodMixedInGetter() {}
+  void extendedMethodMixedInSetter() {}
+  void extendedMethodMixedInField() {}
+  int get extendedGetterMixedInMethod => 0;
+  void set extendedSetterMixedInMethod(int value) {}
+  int extendedFieldMixedInMethod = 0;
+
+  void extendedMethodImplementedGetter() {}
+  void extendedMethodImplementedSetter() {}
+  void extendedMethodImplementedField() {}
+  int get extendedGetterImplementedMethod => 0;
+  void set extendedSetterImplementedMethod(int value) {}
+  int extendedFieldImplementedMethod = 0;
+}
+
+class Mixin {
+  void mixedInMethodDeclaredGetter() {}
+  void mixedInMethodDeclaredSetter() {}
+  void mixedInMethodDeclaredField() {}
+  int get mixedInGetterDeclaredMethod => 0;
+  void set mixedInSetterDeclaredMethod(int value) {}
+  int mixedInFieldDeclaredMethod = 0;
+
+  void mixedInMethodImplementedGetter() {}
+  void mixedInMethodImplementedSetter() {}
+  void mixedInMethodImplementedField() {}
+  int get mixedInGetterImplementedMethod => 0;
+  void set mixedInSetterImplementedMethod(int value) {}
+  int mixedInFieldImplementedMethod = 0;
+
+  int get extendedMethodMixedInGetter => 0;
+  void set extendedMethodMixedInSetter(int value) {}
+  int extendedMethodMixedInField = 0;
+  void extendedGetterMixedInMethod() {}
+  void extendedSetterMixedInMethod() {}
+  void extendedFieldMixedInMethod() {}
+}
+
+class Interface1 {
+  void implementedMethodDeclaredGetter() {}
+  void implementedMethodDeclaredSetter() {}
+  void implementedMethodDeclaredField() {}
+  int get implementedGetterDeclaredMethod => 0;
+  void set implementedSetterDeclaredMethod(int value) {}
+  int implementedFieldDeclaredMethod = 0;
+
+  void implementedMethodImplementedGetter() {}
+  void implementedMethodImplementedSetter() {}
+  void implementedMethodImplementedField() {}
+  int get implementedGetterImplementedMethod => 0;
+  void set implementedSetterImplementedMethod(int value) {}
+  int implementedFieldImplementedMethod = 0;
+
+  int get extendedMethodImplementedGetter => 0;
+  void set extendedMethodImplementedSetter(int value) {}
+  int extendedMethodImplementedField = 0;
+  void extendedGetterImplementedMethod() {}
+  void extendedSetterImplementedMethod() {}
+  void extendedFieldImplementedMethod() {}
+
+  int get mixedInMethodImplementedGetter => 0;
+  void set mixedInMethodImplementedSetter(int value) {}
+  int mixedInMethodImplementedField = 0;
+  void mixedInGetterImplementedMethod() {}
+  void mixedInSetterImplementedMethod() {}
+  void mixedInFieldImplementedMethod() {}
+}
+
+class Interface2 {
+  int get implementedMethodImplementedGetter => 0;
+  void set implementedMethodImplementedSetter(int value) {}
+  int implementedMethodImplementedField = 0;
+  void implementedGetterImplementedMethod() {}
+  void implementedSetterImplementedMethod() {}
+  void implementedFieldImplementedMethod() {}
+}
+
+abstract class Class extends Super
+    with Mixin
+    implements Interface1, Interface2 {
+  int get extendedMethodDeclaredGetter => 0;
+  void set extendedMethodDeclaredSetter(int value) {}
+  int extendedMethodDeclaredField = 0;
+  void extendedGetterDeclaredMethod() {}
+  void extendedSetterDeclaredMethod() {}
+  void extendedFieldDeclaredMethod() {}
+
+  int get mixedInMethodDeclaredGetter => 0;
+  void set mixedInMethodDeclaredSetter(int value) {}
+  int mixedInMethodDeclaredField = 0;
+  void mixedInGetterDeclaredMethod() {}
+  void mixedInSetterDeclaredMethod() {}
+  void mixedInFieldDeclaredMethod() {}
+
+  int get implementedMethodDeclaredGetter => 0;
+  void set implementedMethodDeclaredSetter(int value) {}
+  int implementedMethodDeclaredField = 0;
+  void implementedGetterDeclaredMethod() {}
+  void implementedSetterDeclaredMethod() {}
+  void implementedFieldDeclaredMethod() {}
+
+  void declaredMethodAndSetter() {}
+  void set declaredMethodAndSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.textual_outline.expect
new file mode 100644
index 0000000..079bf85
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.textual_outline.expect
@@ -0,0 +1,104 @@
+class Super {
+  void extendedMethodDeclaredGetter() {}
+  void extendedMethodDeclaredSetter() {}
+  void extendedMethodDeclaredField() {}
+  int get extendedGetterDeclaredMethod => 0;
+  void set extendedSetterDeclaredMethod(int value) {}
+  int extendedFieldDeclaredMethod = 0;
+  void extendedMethodMixedInGetter() {}
+  void extendedMethodMixedInSetter() {}
+  void extendedMethodMixedInField() {}
+  int get extendedGetterMixedInMethod => 0;
+  void set extendedSetterMixedInMethod(int value) {}
+  int extendedFieldMixedInMethod = 0;
+  void extendedMethodImplementedGetter() {}
+  void extendedMethodImplementedSetter() {}
+  void extendedMethodImplementedField() {}
+  int get extendedGetterImplementedMethod => 0;
+  void set extendedSetterImplementedMethod(int value) {}
+  int extendedFieldImplementedMethod = 0;
+}
+
+class Mixin {
+  void mixedInMethodDeclaredGetter() {}
+  void mixedInMethodDeclaredSetter() {}
+  void mixedInMethodDeclaredField() {}
+  int get mixedInGetterDeclaredMethod => 0;
+  void set mixedInSetterDeclaredMethod(int value) {}
+  int mixedInFieldDeclaredMethod = 0;
+  void mixedInMethodImplementedGetter() {}
+  void mixedInMethodImplementedSetter() {}
+  void mixedInMethodImplementedField() {}
+  int get mixedInGetterImplementedMethod => 0;
+  void set mixedInSetterImplementedMethod(int value) {}
+  int mixedInFieldImplementedMethod = 0;
+  int get extendedMethodMixedInGetter => 0;
+  void set extendedMethodMixedInSetter(int value) {}
+  int extendedMethodMixedInField = 0;
+  void extendedGetterMixedInMethod() {}
+  void extendedSetterMixedInMethod() {}
+  void extendedFieldMixedInMethod() {}
+}
+
+class Interface1 {
+  void implementedMethodDeclaredGetter() {}
+  void implementedMethodDeclaredSetter() {}
+  void implementedMethodDeclaredField() {}
+  int get implementedGetterDeclaredMethod => 0;
+  void set implementedSetterDeclaredMethod(int value) {}
+  int implementedFieldDeclaredMethod = 0;
+  void implementedMethodImplementedGetter() {}
+  void implementedMethodImplementedSetter() {}
+  void implementedMethodImplementedField() {}
+  int get implementedGetterImplementedMethod => 0;
+  void set implementedSetterImplementedMethod(int value) {}
+  int implementedFieldImplementedMethod = 0;
+  int get extendedMethodImplementedGetter => 0;
+  void set extendedMethodImplementedSetter(int value) {}
+  int extendedMethodImplementedField = 0;
+  void extendedGetterImplementedMethod() {}
+  void extendedSetterImplementedMethod() {}
+  void extendedFieldImplementedMethod() {}
+  int get mixedInMethodImplementedGetter => 0;
+  void set mixedInMethodImplementedSetter(int value) {}
+  int mixedInMethodImplementedField = 0;
+  void mixedInGetterImplementedMethod() {}
+  void mixedInSetterImplementedMethod() {}
+  void mixedInFieldImplementedMethod() {}
+}
+
+class Interface2 {
+  int get implementedMethodImplementedGetter => 0;
+  void set implementedMethodImplementedSetter(int value) {}
+  int implementedMethodImplementedField = 0;
+  void implementedGetterImplementedMethod() {}
+  void implementedSetterImplementedMethod() {}
+  void implementedFieldImplementedMethod() {}
+}
+
+abstract class Class extends Super
+    with Mixin
+    implements Interface1, Interface2 {
+  int get extendedMethodDeclaredGetter => 0;
+  void set extendedMethodDeclaredSetter(int value) {}
+  int extendedMethodDeclaredField = 0;
+  void extendedGetterDeclaredMethod() {}
+  void extendedSetterDeclaredMethod() {}
+  void extendedFieldDeclaredMethod() {}
+  int get mixedInMethodDeclaredGetter => 0;
+  void set mixedInMethodDeclaredSetter(int value) {}
+  int mixedInMethodDeclaredField = 0;
+  void mixedInGetterDeclaredMethod() {}
+  void mixedInSetterDeclaredMethod() {}
+  void mixedInFieldDeclaredMethod() {}
+  int get implementedMethodDeclaredGetter => 0;
+  void set implementedMethodDeclaredSetter(int value) {}
+  int implementedMethodDeclaredField = 0;
+  void implementedGetterDeclaredMethod() {}
+  void implementedSetterDeclaredMethod() {}
+  void implementedFieldDeclaredMethod() {}
+  void declaredMethodAndSetter() {}
+  void set declaredMethodAndSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..09b395b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.textual_outline_modelled.expect
@@ -0,0 +1,104 @@
+abstract class Class extends Super
+    with Mixin
+    implements Interface1, Interface2 {
+  int extendedMethodDeclaredField = 0;
+  int get extendedMethodDeclaredGetter => 0;
+  int get implementedMethodDeclaredGetter => 0;
+  int get mixedInMethodDeclaredGetter => 0;
+  int implementedMethodDeclaredField = 0;
+  int mixedInMethodDeclaredField = 0;
+  void declaredMethodAndSetter() {}
+  void extendedFieldDeclaredMethod() {}
+  void extendedGetterDeclaredMethod() {}
+  void extendedSetterDeclaredMethod() {}
+  void implementedFieldDeclaredMethod() {}
+  void implementedGetterDeclaredMethod() {}
+  void implementedSetterDeclaredMethod() {}
+  void mixedInFieldDeclaredMethod() {}
+  void mixedInGetterDeclaredMethod() {}
+  void mixedInSetterDeclaredMethod() {}
+  void set declaredMethodAndSetter(int value) {}
+  void set extendedMethodDeclaredSetter(int value) {}
+  void set implementedMethodDeclaredSetter(int value) {}
+  void set mixedInMethodDeclaredSetter(int value) {}
+}
+
+class Interface1 {
+  int extendedMethodImplementedField = 0;
+  int get extendedMethodImplementedGetter => 0;
+  int get implementedGetterDeclaredMethod => 0;
+  int get implementedGetterImplementedMethod => 0;
+  int get mixedInMethodImplementedGetter => 0;
+  int implementedFieldDeclaredMethod = 0;
+  int implementedFieldImplementedMethod = 0;
+  int mixedInMethodImplementedField = 0;
+  void extendedFieldImplementedMethod() {}
+  void extendedGetterImplementedMethod() {}
+  void extendedSetterImplementedMethod() {}
+  void implementedMethodDeclaredField() {}
+  void implementedMethodDeclaredGetter() {}
+  void implementedMethodDeclaredSetter() {}
+  void implementedMethodImplementedField() {}
+  void implementedMethodImplementedGetter() {}
+  void implementedMethodImplementedSetter() {}
+  void mixedInFieldImplementedMethod() {}
+  void mixedInGetterImplementedMethod() {}
+  void mixedInSetterImplementedMethod() {}
+  void set extendedMethodImplementedSetter(int value) {}
+  void set implementedSetterDeclaredMethod(int value) {}
+  void set implementedSetterImplementedMethod(int value) {}
+  void set mixedInMethodImplementedSetter(int value) {}
+}
+
+class Interface2 {
+  int get implementedMethodImplementedGetter => 0;
+  int implementedMethodImplementedField = 0;
+  void implementedFieldImplementedMethod() {}
+  void implementedGetterImplementedMethod() {}
+  void implementedSetterImplementedMethod() {}
+  void set implementedMethodImplementedSetter(int value) {}
+}
+
+class Mixin {
+  int extendedMethodMixedInField = 0;
+  int get extendedMethodMixedInGetter => 0;
+  int get mixedInGetterDeclaredMethod => 0;
+  int get mixedInGetterImplementedMethod => 0;
+  int mixedInFieldDeclaredMethod = 0;
+  int mixedInFieldImplementedMethod = 0;
+  void extendedFieldMixedInMethod() {}
+  void extendedGetterMixedInMethod() {}
+  void extendedSetterMixedInMethod() {}
+  void mixedInMethodDeclaredField() {}
+  void mixedInMethodDeclaredGetter() {}
+  void mixedInMethodDeclaredSetter() {}
+  void mixedInMethodImplementedField() {}
+  void mixedInMethodImplementedGetter() {}
+  void mixedInMethodImplementedSetter() {}
+  void set extendedMethodMixedInSetter(int value) {}
+  void set mixedInSetterDeclaredMethod(int value) {}
+  void set mixedInSetterImplementedMethod(int value) {}
+}
+
+class Super {
+  int extendedFieldDeclaredMethod = 0;
+  int extendedFieldImplementedMethod = 0;
+  int extendedFieldMixedInMethod = 0;
+  int get extendedGetterDeclaredMethod => 0;
+  int get extendedGetterImplementedMethod => 0;
+  int get extendedGetterMixedInMethod => 0;
+  void extendedMethodDeclaredField() {}
+  void extendedMethodDeclaredGetter() {}
+  void extendedMethodDeclaredSetter() {}
+  void extendedMethodImplementedField() {}
+  void extendedMethodImplementedGetter() {}
+  void extendedMethodImplementedSetter() {}
+  void extendedMethodMixedInField() {}
+  void extendedMethodMixedInGetter() {}
+  void extendedMethodMixedInSetter() {}
+  void set extendedSetterDeclaredMethod(int value) {}
+  void set extendedSetterImplementedMethod(int value) {}
+  void set extendedSetterMixedInMethod(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.weak.expect
new file mode 100644
index 0000000..f1538ce
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart.weak.expect
@@ -0,0 +1,323 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:90:16: Error: Can't inherit members that conflict with each other.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:13:8: Context: This is one inherited member.
+//   void extendedMethodMixedInGetter() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:43:11: Context: This is the other inherited member.
+//   int get extendedMethodMixedInGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:93:11: Error: Can't declare a member that conflicts with an inherited one.
+//   int get extendedMethodDeclaredGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:6:8: Context: This is the inherited member.
+//   void extendedMethodDeclaredGetter() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:95:7: Error: Can't declare a member that conflicts with an inherited one.
+//   int extendedMethodDeclaredField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:8:8: Context: This is the inherited member.
+//   void extendedMethodDeclaredField() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:96:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void extendedGetterDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:9:11: Context: This is the inherited member.
+//   int get extendedGetterDeclaredMethod => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:97:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void extendedSetterDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:10:12: Context: This is the inherited member.
+//   void set extendedSetterDeclaredMethod(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:98:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void extendedFieldDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:11:7: Context: This is the inherited member.
+//   int extendedFieldDeclaredMethod = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:100:11: Error: Can't declare a member that conflicts with an inherited one.
+//   int get mixedInMethodDeclaredGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:29:8: Context: This is the inherited member.
+//   void mixedInMethodDeclaredGetter() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:102:7: Error: Can't declare a member that conflicts with an inherited one.
+//   int mixedInMethodDeclaredField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:31:8: Context: This is the inherited member.
+//   void mixedInMethodDeclaredField() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:103:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void mixedInGetterDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:32:11: Context: This is the inherited member.
+//   int get mixedInGetterDeclaredMethod => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:104:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void mixedInSetterDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:33:12: Context: This is the inherited member.
+//   void set mixedInSetterDeclaredMethod(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:105:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void mixedInFieldDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:34:7: Context: This is the inherited member.
+//   int mixedInFieldDeclaredMethod = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:107:11: Error: Can't declare a member that conflicts with an inherited one.
+//   int get implementedMethodDeclaredGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:52:8: Context: This is the inherited member.
+//   void implementedMethodDeclaredGetter() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:109:7: Error: Can't declare a member that conflicts with an inherited one.
+//   int implementedMethodDeclaredField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:54:8: Context: This is the inherited member.
+//   void implementedMethodDeclaredField() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:110:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void implementedGetterDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:55:11: Context: This is the inherited member.
+//   int get implementedGetterDeclaredMethod => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:111:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void implementedSetterDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:56:12: Context: This is the inherited member.
+//   void set implementedSetterDeclaredMethod(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:112:8: Error: Can't declare a member that conflicts with an inherited one.
+//   void implementedFieldDeclaredMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:57:7: Context: This is the inherited member.
+//   int implementedFieldDeclaredMethod = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:115:12: Error: 'declaredMethodAndSetter' is already declared in this scope.
+//   void set declaredMethodAndSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:114:8: Context: Previous declaration of 'declaredMethodAndSetter'.
+//   void declaredMethodAndSetter() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:94:12: Error: Can't declare a member that conflicts with an inherited one.
+//   void set extendedMethodDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:7:8: Context: This is the inherited member.
+//   void extendedMethodDeclaredSetter() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:101:12: Error: Can't declare a member that conflicts with an inherited one.
+//   void set mixedInMethodDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:30:8: Context: This is the inherited member.
+//   void mixedInMethodDeclaredSetter() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:108:12: Error: Can't declare a member that conflicts with an inherited one.
+//   void set implementedMethodDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/conflict.dart:53:8: Context: This is the inherited member.
+//   void implementedMethodDeclaredSetter() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  field core::int extendedFieldDeclaredMethod = 0;
+  field core::int extendedFieldMixedInMethod = 0;
+  field core::int extendedFieldImplementedMethod = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedMethodDeclaredGetter() → void {}
+  method extendedMethodDeclaredSetter() → void {}
+  method extendedMethodDeclaredField() → void {}
+  get extendedGetterDeclaredMethod() → core::int
+    return 0;
+  set extendedSetterDeclaredMethod(core::int value) → void {}
+  method extendedMethodMixedInGetter() → void {}
+  method extendedMethodMixedInSetter() → void {}
+  method extendedMethodMixedInField() → void {}
+  get extendedGetterMixedInMethod() → core::int
+    return 0;
+  set extendedSetterMixedInMethod(core::int value) → void {}
+  method extendedMethodImplementedGetter() → void {}
+  method extendedMethodImplementedSetter() → void {}
+  method extendedMethodImplementedField() → void {}
+  get extendedGetterImplementedMethod() → core::int
+    return 0;
+  set extendedSetterImplementedMethod(core::int value) → void {}
+}
+class Mixin extends core::Object {
+  field core::int mixedInFieldDeclaredMethod = 0;
+  field core::int mixedInFieldImplementedMethod = 0;
+  field core::int extendedMethodMixedInField = 0;
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method mixedInMethodDeclaredGetter() → void {}
+  method mixedInMethodDeclaredSetter() → void {}
+  method mixedInMethodDeclaredField() → void {}
+  get mixedInGetterDeclaredMethod() → core::int
+    return 0;
+  set mixedInSetterDeclaredMethod(core::int value) → void {}
+  method mixedInMethodImplementedGetter() → void {}
+  method mixedInMethodImplementedSetter() → void {}
+  method mixedInMethodImplementedField() → void {}
+  get mixedInGetterImplementedMethod() → core::int
+    return 0;
+  set mixedInSetterImplementedMethod(core::int value) → void {}
+  get extendedMethodMixedInGetter() → core::int
+    return 0;
+  set extendedMethodMixedInSetter(core::int value) → void {}
+  method extendedGetterMixedInMethod() → void {}
+  method extendedSetterMixedInMethod() → void {}
+  method extendedFieldMixedInMethod() → void {}
+}
+class Interface1 extends core::Object {
+  field core::int implementedFieldDeclaredMethod = 0;
+  field core::int implementedFieldImplementedMethod = 0;
+  field core::int extendedMethodImplementedField = 0;
+  field core::int mixedInMethodImplementedField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method implementedMethodDeclaredGetter() → void {}
+  method implementedMethodDeclaredSetter() → void {}
+  method implementedMethodDeclaredField() → void {}
+  get implementedGetterDeclaredMethod() → core::int
+    return 0;
+  set implementedSetterDeclaredMethod(core::int value) → void {}
+  method implementedMethodImplementedGetter() → void {}
+  method implementedMethodImplementedSetter() → void {}
+  method implementedMethodImplementedField() → void {}
+  get implementedGetterImplementedMethod() → core::int
+    return 0;
+  set implementedSetterImplementedMethod(core::int value) → void {}
+  get extendedMethodImplementedGetter() → core::int
+    return 0;
+  set extendedMethodImplementedSetter(core::int value) → void {}
+  method extendedGetterImplementedMethod() → void {}
+  method extendedSetterImplementedMethod() → void {}
+  method extendedFieldImplementedMethod() → void {}
+  get mixedInMethodImplementedGetter() → core::int
+    return 0;
+  set mixedInMethodImplementedSetter(core::int value) → void {}
+  method mixedInGetterImplementedMethod() → void {}
+  method mixedInSetterImplementedMethod() → void {}
+  method mixedInFieldImplementedMethod() → void {}
+}
+class Interface2 extends core::Object {
+  field core::int implementedMethodImplementedField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  get implementedMethodImplementedGetter() → core::int
+    return 0;
+  set implementedMethodImplementedSetter(core::int value) → void {}
+  method implementedGetterImplementedMethod() → void {}
+  method implementedSetterImplementedMethod() → void {}
+  method implementedFieldImplementedMethod() → void {}
+}
+abstract class _Class&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Class&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInMethodDeclaredSetter() → void
+    return super.{self::Mixin::mixedInMethodDeclaredSetter}();
+  mixin-super-stub get mixedInFieldDeclaredMethod() → core::int
+    return super.{self::Mixin::mixedInFieldDeclaredMethod};
+  mixin-super-stub set mixedInFieldDeclaredMethod(core::int value) → void
+    return super.{self::Mixin::mixedInFieldDeclaredMethod} = value;
+  mixin-super-stub get mixedInFieldImplementedMethod() → core::int
+    return super.{self::Mixin::mixedInFieldImplementedMethod};
+  mixin-super-stub set mixedInFieldImplementedMethod(core::int value) → void
+    return super.{self::Mixin::mixedInFieldImplementedMethod} = value;
+  mixin-super-stub get extendedMethodMixedInField() → core::int
+    return super.{self::Mixin::extendedMethodMixedInField};
+  mixin-super-stub set extendedMethodMixedInField(core::int value) → void
+    return super.{self::Mixin::extendedMethodMixedInField} = value;
+  mixin-super-stub method mixedInMethodDeclaredGetter() → void
+    return super.{self::Mixin::mixedInMethodDeclaredGetter}();
+  mixin-super-stub method mixedInMethodDeclaredField() → void
+    return super.{self::Mixin::mixedInMethodDeclaredField}();
+  mixin-super-stub get mixedInGetterDeclaredMethod() → core::int
+    return super.{self::Mixin::mixedInGetterDeclaredMethod};
+  mixin-super-stub method mixedInMethodImplementedGetter() → void
+    return super.{self::Mixin::mixedInMethodImplementedGetter}();
+  mixin-super-stub method mixedInMethodImplementedSetter() → void
+    return super.{self::Mixin::mixedInMethodImplementedSetter}();
+  mixin-super-stub method mixedInMethodImplementedField() → void
+    return super.{self::Mixin::mixedInMethodImplementedField}();
+  mixin-super-stub get mixedInGetterImplementedMethod() → core::int
+    return super.{self::Mixin::mixedInGetterImplementedMethod};
+  mixin-super-stub get extendedMethodMixedInGetter() → core::int
+    return super.{self::Mixin::extendedMethodMixedInGetter};
+  mixin-super-stub method extendedGetterMixedInMethod() → void
+    return super.{self::Mixin::extendedGetterMixedInMethod}();
+  mixin-super-stub method extendedSetterMixedInMethod() → void
+    return super.{self::Mixin::extendedSetterMixedInMethod}();
+  mixin-super-stub method extendedFieldMixedInMethod() → void
+    return super.{self::Mixin::extendedFieldMixedInMethod}();
+  mixin-super-stub set mixedInSetterDeclaredMethod(core::int value) → void
+    return super.{self::Mixin::mixedInSetterDeclaredMethod} = value;
+  mixin-super-stub set mixedInSetterImplementedMethod(core::int value) → void
+    return super.{self::Mixin::mixedInSetterImplementedMethod} = value;
+  mixin-super-stub set extendedMethodMixedInSetter(core::int value) → void
+    return super.{self::Mixin::extendedMethodMixedInSetter} = value;
+}
+abstract class Class extends self::_Class&Super&Mixin implements self::Interface1, self::Interface2 {
+  field core::int extendedMethodDeclaredField = 0;
+  field core::int mixedInMethodDeclaredField = 0;
+  field core::int implementedMethodDeclaredField = 0;
+  synthetic constructor •() → self::Class
+    : super self::_Class&Super&Mixin::•()
+    ;
+  get extendedMethodDeclaredGetter() → core::int
+    return 0;
+  set extendedMethodDeclaredSetter(core::int value) → void {}
+  method extendedGetterDeclaredMethod() → void {}
+  method extendedSetterDeclaredMethod() → void {}
+  method extendedFieldDeclaredMethod() → void {}
+  get mixedInMethodDeclaredGetter() → core::int
+    return 0;
+  set mixedInMethodDeclaredSetter(core::int value) → void {}
+  method mixedInGetterDeclaredMethod() → void {}
+  method mixedInSetterDeclaredMethod() → void {}
+  method mixedInFieldDeclaredMethod() → void {}
+  get implementedMethodDeclaredGetter() → core::int
+    return 0;
+  set implementedMethodDeclaredSetter(core::int value) → void {}
+  method implementedGetterDeclaredMethod() → void {}
+  method implementedSetterDeclaredMethod() → void {}
+  method implementedFieldDeclaredMethod() → void {}
+  method declaredMethodAndSetter() → void {}
+  set declaredMethodAndSetter(core::int value) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart
new file mode 100644
index 0000000..32d8eed
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.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.
+
+// From language/covariant_override/tear_off_type_test
+
+// If a parameter is directly or indirectly a covariant override, its type in
+// the method tear-off should become Object?.
+
+class M1 {
+  method(covariant int a, int b) {}
+}
+
+class M2 {
+  method(int a, covariant int b) {}
+}
+
+class C extends Object with M1, M2 {}
+
+class Direct {
+  void positional(covariant int a, int b, covariant int c, int d, int e) {}
+  void optional(
+      [covariant int a = 0, int b = 0, covariant int c = 0, int d = 0]) {}
+  void named(
+      {covariant int a = 0, int b = 0, covariant int c = 0, int d = 0}) {}
+}
+
+class Inherited extends Direct {}
+
+// ---
+
+class Override1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Override2 extends Override1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Override3 extends Override2 {
+  void method(int a, int b, int c, int d, int e) {}
+}
+
+// ---
+
+abstract class Implement1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Implement2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Implement3 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Implement4 implements Implement3 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Implement5 implements Implement1, Implement2, Implement4 {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+// ---
+
+class Interface1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Interface2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Mixin1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Mixin2 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Superclass {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+class Mixed extends Superclass
+    with Mixin1, Mixin2
+    implements Interface1, Interface2 {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.textual_outline.expect
new file mode 100644
index 0000000..99a4f42
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.textual_outline.expect
@@ -0,0 +1,77 @@
+class M1 {
+  method(covariant int a, int b) {}
+}
+
+class M2 {
+  method(int a, covariant int b) {}
+}
+
+class C extends Object with M1, M2 {}
+
+class Direct {
+  void positional(covariant int a, int b, covariant int c, int d, int e) {}
+  void optional(
+      [covariant int a = 0, int b = 0, covariant int c = 0, int d = 0]) {}
+  void named(
+      {covariant int a = 0, int b = 0, covariant int c = 0, int d = 0}) {}
+}
+
+class Inherited extends Direct {}
+
+class Override1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Override2 extends Override1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Override3 extends Override2 {
+  void method(int a, int b, int c, int d, int e) {}
+}
+
+abstract class Implement1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Implement2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Implement3 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Implement4 implements Implement3 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Implement5 implements Implement1, Implement2, Implement4 {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+class Interface1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Interface2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Mixin1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Mixin2 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Superclass {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+class Mixed extends Superclass
+    with Mixin1, Mixin2
+    implements Interface1, Interface2 {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..dd47260
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.textual_outline_modelled.expect
@@ -0,0 +1,77 @@
+abstract class Implement1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class C extends Object with M1, M2 {}
+
+class Direct {
+  void named(
+      {covariant int a = 0, int b = 0, covariant int c = 0, int d = 0}) {}
+  void optional(
+      [covariant int a = 0, int b = 0, covariant int c = 0, int d = 0]) {}
+  void positional(covariant int a, int b, covariant int c, int d, int e) {}
+}
+
+class Implement2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Implement3 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Implement4 implements Implement3 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Implement5 implements Implement1, Implement2, Implement4 {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+class Inherited extends Direct {}
+
+class Interface1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Interface2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class M1 {
+  method(covariant int a, int b) {}
+}
+
+class M2 {
+  method(int a, covariant int b) {}
+}
+
+class Mixed extends Superclass
+    with Mixin1, Mixin2
+    implements Interface1, Interface2 {}
+
+class Mixin1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Mixin2 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Override1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Override2 extends Override1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Override3 extends Override2 {
+  void method(int a, int b, int c, int d, int e) {}
+}
+
+class Superclass {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.weak.expect
new file mode 100644
index 0000000..17fd9e4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.weak.expect
@@ -0,0 +1,152 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class M1 extends core::Object {
+  synthetic constructor •() → self::M1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b) → dynamic {}
+}
+class M2 extends core::Object {
+  synthetic constructor •() → self::M2
+    : super core::Object::•()
+    ;
+  method method(core::int a, covariant core::int b) → dynamic {}
+}
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1
+    : super core::Object::•()
+    ;
+  mixin-super-stub method method(covariant core::int a, core::int b) → dynamic
+    return super.{self::M1::method}(a, b);
+}
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1&M2
+    : super self::_C&Object&M1::•()
+    ;
+  forwarding-stub method method(covariant core::int a, covariant core::int b) → dynamic
+    return super.{self::M2::method}(a, b);
+}
+class C extends self::_C&Object&M1&M2 {
+  synthetic constructor •() → self::C
+    : super self::_C&Object&M1&M2::•()
+    ;
+}
+class Direct extends core::Object {
+  synthetic constructor •() → self::Direct
+    : super core::Object::•()
+    ;
+  method positional(covariant core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+  method optional([covariant core::int a = #C1, core::int b = #C1, covariant core::int c = #C1, core::int d = #C1]) → void {}
+  method named({covariant core::int a = #C1, core::int b = #C1, covariant core::int c = #C1, core::int d = #C1}) → void {}
+}
+class Inherited extends self::Direct {
+  synthetic constructor •() → self::Inherited
+    : super self::Direct::•()
+    ;
+}
+class Override1 extends core::Object {
+  synthetic constructor •() → self::Override1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Override2 extends self::Override1 {
+  synthetic constructor •() → self::Override2
+    : super self::Override1::•()
+    ;
+  method method(covariant core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+}
+class Override3 extends self::Override2 {
+  synthetic constructor •() → self::Override3
+    : super self::Override2::•()
+    ;
+  method method(covariant core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+}
+abstract class Implement1 extends core::Object {
+  synthetic constructor •() → self::Implement1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Implement2 extends core::Object {
+  synthetic constructor •() → self::Implement2
+    : super core::Object::•()
+    ;
+  method method(core::int a, covariant core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Implement3 extends core::Object {
+  synthetic constructor •() → self::Implement3
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+}
+class Implement4 extends core::Object implements self::Implement3 {
+  synthetic constructor •() → self::Implement4
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, covariant core::int c, covariant core::int d, core::int e) → void {}
+}
+class Implement5 extends core::Object implements self::Implement1, self::Implement2, self::Implement4 {
+  synthetic constructor •() → self::Implement5
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, covariant core::int b, covariant core::int c, covariant core::int d, covariant core::int e) → void {}
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method method(core::int a, covariant core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Mixin1 extends core::Object {
+  synthetic constructor •() → self::Mixin1
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+}
+class Mixin2 extends core::Object {
+  synthetic constructor •() → self::Mixin2
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, core::int c, covariant core::int d, core::int e) → void {}
+}
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, core::int c, core::int d, covariant core::int e) → void {}
+}
+abstract class _Mixed&Superclass&Mixin1 = self::Superclass with self::Mixin1 /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1
+    : super self::Superclass::•()
+    ;
+  forwarding-stub method method(core::int a, core::int b, covariant core::int c, core::int d, covariant core::int e) → void
+    return super.{self::Mixin1::method}(a, b, c, d, e);
+}
+abstract class _Mixed&Superclass&Mixin1&Mixin2 = self::_Mixed&Superclass&Mixin1 with self::Mixin2 /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1&Mixin2
+    : super self::_Mixed&Superclass&Mixin1::•()
+    ;
+  forwarding-stub method method(core::int a, core::int b, covariant core::int c, covariant core::int d, covariant core::int e) → void
+    return super.{self::Mixin2::method}(a, b, c, d, e);
+}
+class Mixed extends self::_Mixed&Superclass&Mixin1&Mixin2 implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::Mixed
+    : super self::_Mixed&Superclass&Mixin1&Mixin2::•()
+    ;
+  forwarding-stub method method(covariant core::int a, covariant core::int b, covariant core::int c, covariant core::int d, covariant core::int e) → void
+    return super.{self::Mixin2::method}(a, b, c, d, e);
+}
+static method main() → void {}
+
+constants  {
+  #C1 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.weak.transformed.expect
new file mode 100644
index 0000000..62abc3c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariance.dart.weak.transformed.expect
@@ -0,0 +1,148 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class M1 extends core::Object {
+  synthetic constructor •() → self::M1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b) → dynamic {}
+}
+class M2 extends core::Object {
+  synthetic constructor •() → self::M2
+    : super core::Object::•()
+    ;
+  method method(core::int a, covariant core::int b) → dynamic {}
+}
+abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b) → dynamic {}
+}
+abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1&M2
+    : super self::_C&Object&M1::•()
+    ;
+  method method(covariant core::int a, covariant core::int b) → dynamic {}
+}
+class C extends self::_C&Object&M1&M2 {
+  synthetic constructor •() → self::C
+    : super self::_C&Object&M1&M2::•()
+    ;
+}
+class Direct extends core::Object {
+  synthetic constructor •() → self::Direct
+    : super core::Object::•()
+    ;
+  method positional(covariant core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+  method optional([covariant core::int a = #C1, core::int b = #C1, covariant core::int c = #C1, core::int d = #C1]) → void {}
+  method named({covariant core::int a = #C1, core::int b = #C1, covariant core::int c = #C1, core::int d = #C1}) → void {}
+}
+class Inherited extends self::Direct {
+  synthetic constructor •() → self::Inherited
+    : super self::Direct::•()
+    ;
+}
+class Override1 extends core::Object {
+  synthetic constructor •() → self::Override1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Override2 extends self::Override1 {
+  synthetic constructor •() → self::Override2
+    : super self::Override1::•()
+    ;
+  method method(covariant core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+}
+class Override3 extends self::Override2 {
+  synthetic constructor •() → self::Override3
+    : super self::Override2::•()
+    ;
+  method method(covariant core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+}
+abstract class Implement1 extends core::Object {
+  synthetic constructor •() → self::Implement1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Implement2 extends core::Object {
+  synthetic constructor •() → self::Implement2
+    : super core::Object::•()
+    ;
+  method method(core::int a, covariant core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Implement3 extends core::Object {
+  synthetic constructor •() → self::Implement3
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+}
+class Implement4 extends core::Object implements self::Implement3 {
+  synthetic constructor •() → self::Implement4
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, covariant core::int c, covariant core::int d, core::int e) → void {}
+}
+class Implement5 extends core::Object implements self::Implement1, self::Implement2, self::Implement4 {
+  synthetic constructor •() → self::Implement5
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, covariant core::int b, covariant core::int c, covariant core::int d, covariant core::int e) → void {}
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method method(covariant core::int a, core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method method(core::int a, covariant core::int b, core::int c, core::int d, core::int e) → void {}
+}
+class Mixin1 extends core::Object {
+  synthetic constructor •() → self::Mixin1
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, covariant core::int c, core::int d, core::int e) → void {}
+}
+class Mixin2 extends core::Object {
+  synthetic constructor •() → self::Mixin2
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, core::int c, covariant core::int d, core::int e) → void {}
+}
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass
+    : super core::Object::•()
+    ;
+  method method(core::int a, core::int b, core::int c, core::int d, covariant core::int e) → void {}
+}
+abstract class _Mixed&Superclass&Mixin1 extends self::Superclass implements self::Mixin1 /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1
+    : super self::Superclass::•()
+    ;
+  method method(core::int a, core::int b, covariant core::int c, core::int d, covariant core::int e) → void {}
+}
+abstract class _Mixed&Superclass&Mixin1&Mixin2 extends self::_Mixed&Superclass&Mixin1 implements self::Mixin2 /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1&Mixin2
+    : super self::_Mixed&Superclass&Mixin1::•()
+    ;
+  method method(core::int a, core::int b, covariant core::int c, covariant core::int d, covariant core::int e) → void {}
+}
+class Mixed extends self::_Mixed&Superclass&Mixin1&Mixin2 implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::Mixed
+    : super self::_Mixed&Superclass&Mixin1&Mixin2::•()
+    ;
+  forwarding-stub method method(covariant core::int a, covariant core::int b, covariant core::int c, covariant core::int d, covariant core::int e) → void
+    return super.{self::Mixin2::method}(a, b, c, d, e);
+}
+static method main() → void {}
+
+constants  {
+  #C1 = 0
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart
new file mode 100644
index 0000000..67fe830
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.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
+
+class A {
+  bool operator ==(covariant A other) => true;
+}
+
+class B extends A {
+  bool operator ==(other) => true;
+}
+
+class C<T> {
+  bool operator ==(covariant C<T> other) => true;
+}
+
+class D extends C<int> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.textual_outline.expect
new file mode 100644
index 0000000..8d0614c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.textual_outline.expect
@@ -0,0 +1,16 @@
+// @dart = 2.9
+class A {
+  bool operator ==(covariant A other) => true;
+}
+
+class B extends A {
+  bool operator ==(other) => true;
+}
+
+class C<T> {
+  bool operator ==(covariant C<T> other) => true;
+}
+
+class D extends C<int> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8d0614c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.textual_outline_modelled.expect
@@ -0,0 +1,16 @@
+// @dart = 2.9
+class A {
+  bool operator ==(covariant A other) => true;
+}
+
+class B extends A {
+  bool operator ==(other) => true;
+}
+
+class C<T> {
+  bool operator ==(covariant C<T> other) => true;
+}
+
+class D extends C<int> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.weak.expect
new file mode 100644
index 0000000..7ffa395
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.weak.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+  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 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
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    return true;
+  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 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
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.weak.transformed.expect
new file mode 100644
index 0000000..7ffa395
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/covariant_equals.dart.weak.transformed.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+  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 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
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  operator ==(covariant self::A* other) → core::bool*
+    return true;
+}
+class C<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T*>*
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::C<self::C::T*>* other) → core::bool*
+    return true;
+  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 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
+}
+class D extends self::C<core::int*> {
+  synthetic constructor •() → self::D*
+    : super self::C::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart
new file mode 100644
index 0000000..2706346
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart
@@ -0,0 +1,59 @@
+// 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 Super {
+  void extendedConcreteDeclaredConcreteMethod() {}
+
+  void extendedAbstractDeclaredConcreteMethod();
+
+  void extendedConcreteDeclaredAbstractMethod() {}
+
+  void extendedAbstractDeclaredAbstractMethod();
+
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+
+  void extendedAbstractImplementedDeclaredConcreteMethod();
+
+  void extendedConcreteImplementedDeclaredAbstractMethod() {}
+
+  void extendedAbstractImplementedDeclaredAbstractMethod();
+}
+
+class Interface {
+  void implementedDeclaredConcreteMethod() {}
+
+  void implementedDeclaredAbstractMethod() {}
+
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+
+  void extendedAbstractImplementedDeclaredConcreteMethod() {}
+
+  void extendedConcreteImplementedDeclaredAbstractMethod() {}
+
+  void extendedAbstractImplementedDeclaredAbstractMethod() {}
+}
+
+class Class extends Super implements Interface {
+  void extendedConcreteDeclaredConcreteMethod() {}
+
+  void extendedAbstractDeclaredConcreteMethod() {}
+
+  void extendedConcreteDeclaredAbstractMethod();
+
+  void extendedAbstractDeclaredAbstractMethod();
+
+  void implementedDeclaredConcreteMethod() {}
+
+  void implementedDeclaredAbstractMethod();
+
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+
+  void extendedAbstractImplementedDeclaredConcreteMethod() {}
+
+  void extendedConcreteImplementedDeclaredAbstractMethod();
+
+  void extendedAbstractImplementedDeclaredAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.textual_outline.expect
new file mode 100644
index 0000000..5b331bb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.textual_outline.expect
@@ -0,0 +1,34 @@
+class Super {
+  void extendedConcreteDeclaredConcreteMethod() {}
+  void extendedAbstractDeclaredConcreteMethod();
+  void extendedConcreteDeclaredAbstractMethod() {}
+  void extendedAbstractDeclaredAbstractMethod();
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+  void extendedAbstractImplementedDeclaredConcreteMethod();
+  void extendedConcreteImplementedDeclaredAbstractMethod() {}
+  void extendedAbstractImplementedDeclaredAbstractMethod();
+}
+
+class Interface {
+  void implementedDeclaredConcreteMethod() {}
+  void implementedDeclaredAbstractMethod() {}
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+  void extendedAbstractImplementedDeclaredConcreteMethod() {}
+  void extendedConcreteImplementedDeclaredAbstractMethod() {}
+  void extendedAbstractImplementedDeclaredAbstractMethod() {}
+}
+
+class Class extends Super implements Interface {
+  void extendedConcreteDeclaredConcreteMethod() {}
+  void extendedAbstractDeclaredConcreteMethod() {}
+  void extendedConcreteDeclaredAbstractMethod();
+  void extendedAbstractDeclaredAbstractMethod();
+  void implementedDeclaredConcreteMethod() {}
+  void implementedDeclaredAbstractMethod();
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+  void extendedAbstractImplementedDeclaredConcreteMethod() {}
+  void extendedConcreteImplementedDeclaredAbstractMethod();
+  void extendedAbstractImplementedDeclaredAbstractMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1dfd1a3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.textual_outline_modelled.expect
@@ -0,0 +1,34 @@
+class Class extends Super implements Interface {
+  void extendedAbstractDeclaredAbstractMethod();
+  void extendedAbstractDeclaredConcreteMethod() {}
+  void extendedAbstractImplementedDeclaredAbstractMethod();
+  void extendedAbstractImplementedDeclaredConcreteMethod() {}
+  void extendedConcreteDeclaredAbstractMethod();
+  void extendedConcreteDeclaredConcreteMethod() {}
+  void extendedConcreteImplementedDeclaredAbstractMethod();
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+  void implementedDeclaredAbstractMethod();
+  void implementedDeclaredConcreteMethod() {}
+}
+
+class Interface {
+  void extendedAbstractImplementedDeclaredAbstractMethod() {}
+  void extendedAbstractImplementedDeclaredConcreteMethod() {}
+  void extendedConcreteImplementedDeclaredAbstractMethod() {}
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+  void implementedDeclaredAbstractMethod() {}
+  void implementedDeclaredConcreteMethod() {}
+}
+
+class Super {
+  void extendedAbstractDeclaredAbstractMethod();
+  void extendedAbstractDeclaredConcreteMethod();
+  void extendedAbstractImplementedDeclaredAbstractMethod();
+  void extendedAbstractImplementedDeclaredConcreteMethod();
+  void extendedConcreteDeclaredAbstractMethod() {}
+  void extendedConcreteDeclaredConcreteMethod() {}
+  void extendedConcreteImplementedDeclaredAbstractMethod() {}
+  void extendedConcreteImplementedDeclaredConcreteMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.weak.expect
new file mode 100644
index 0000000..50391f4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.weak.expect
@@ -0,0 +1,95 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractDeclaredAbstractMethod
+//  - Super.extendedAbstractDeclaredConcreteMethod
+//  - Super.extendedAbstractImplementedDeclaredAbstractMethod
+//  - Super.extendedAbstractImplementedDeclaredConcreteMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:12:8: Context: 'Super.extendedAbstractDeclaredAbstractMethod' is defined here.
+//   void extendedAbstractDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:8:8: Context: 'Super.extendedAbstractDeclaredConcreteMethod' is defined here.
+//   void extendedAbstractDeclaredConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:20:8: Context: 'Super.extendedAbstractImplementedDeclaredAbstractMethod' is defined here.
+//   void extendedAbstractImplementedDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:16:8: Context: 'Super.extendedAbstractImplementedDeclaredConcreteMethod' is defined here.
+//   void extendedAbstractImplementedDeclaredConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:37:7: Error: The non-abstract class 'Class' is missing implementations for these members:
+//  - Class.extendedAbstractDeclaredAbstractMethod
+//  - Class.extendedAbstractImplementedDeclaredAbstractMethod
+//  - Class.implementedDeclaredAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Class extends Super implements Interface {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:44:8: Context: 'Class.extendedAbstractDeclaredAbstractMethod' is defined here.
+//   void extendedAbstractDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:56:8: Context: 'Class.extendedAbstractImplementedDeclaredAbstractMethod' is defined here.
+//   void extendedAbstractImplementedDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:48:8: Context: 'Class.implementedDeclaredAbstractMethod' is defined here.
+//   void implementedDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteDeclaredConcreteMethod() → void {}
+  abstract method extendedAbstractDeclaredConcreteMethod() → void;
+  method extendedConcreteDeclaredAbstractMethod() → void {}
+  abstract method extendedAbstractDeclaredAbstractMethod() → void;
+  method extendedConcreteImplementedDeclaredConcreteMethod() → void {}
+  abstract method extendedAbstractImplementedDeclaredConcreteMethod() → void;
+  method extendedConcreteImplementedDeclaredAbstractMethod() → void {}
+  abstract method extendedAbstractImplementedDeclaredAbstractMethod() → void;
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method implementedDeclaredConcreteMethod() → void {}
+  method implementedDeclaredAbstractMethod() → void {}
+  method extendedConcreteImplementedDeclaredConcreteMethod() → void {}
+  method extendedAbstractImplementedDeclaredConcreteMethod() → void {}
+  method extendedConcreteImplementedDeclaredAbstractMethod() → void {}
+  method extendedAbstractImplementedDeclaredAbstractMethod() → void {}
+}
+class Class extends self::Super implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  method extendedConcreteDeclaredConcreteMethod() → void {}
+  method extendedAbstractDeclaredConcreteMethod() → void {}
+  abstract method extendedConcreteDeclaredAbstractMethod() → void;
+  abstract method extendedAbstractDeclaredAbstractMethod() → void;
+  method implementedDeclaredConcreteMethod() → void {}
+  abstract method implementedDeclaredAbstractMethod() → void;
+  method extendedConcreteImplementedDeclaredConcreteMethod() → void {}
+  method extendedAbstractImplementedDeclaredConcreteMethod() → void {}
+  abstract method extendedConcreteImplementedDeclaredAbstractMethod() → void;
+  abstract method extendedAbstractImplementedDeclaredAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.weak.transformed.expect
new file mode 100644
index 0000000..50391f4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart.weak.transformed.expect
@@ -0,0 +1,95 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractDeclaredAbstractMethod
+//  - Super.extendedAbstractDeclaredConcreteMethod
+//  - Super.extendedAbstractImplementedDeclaredAbstractMethod
+//  - Super.extendedAbstractImplementedDeclaredConcreteMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:12:8: Context: 'Super.extendedAbstractDeclaredAbstractMethod' is defined here.
+//   void extendedAbstractDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:8:8: Context: 'Super.extendedAbstractDeclaredConcreteMethod' is defined here.
+//   void extendedAbstractDeclaredConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:20:8: Context: 'Super.extendedAbstractImplementedDeclaredAbstractMethod' is defined here.
+//   void extendedAbstractImplementedDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:16:8: Context: 'Super.extendedAbstractImplementedDeclaredConcreteMethod' is defined here.
+//   void extendedAbstractImplementedDeclaredConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:37:7: Error: The non-abstract class 'Class' is missing implementations for these members:
+//  - Class.extendedAbstractDeclaredAbstractMethod
+//  - Class.extendedAbstractImplementedDeclaredAbstractMethod
+//  - Class.implementedDeclaredAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Class extends Super implements Interface {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:44:8: Context: 'Class.extendedAbstractDeclaredAbstractMethod' is defined here.
+//   void extendedAbstractDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:56:8: Context: 'Class.extendedAbstractImplementedDeclaredAbstractMethod' is defined here.
+//   void extendedAbstractImplementedDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/declares.dart:48:8: Context: 'Class.implementedDeclaredAbstractMethod' is defined here.
+//   void implementedDeclaredAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteDeclaredConcreteMethod() → void {}
+  abstract method extendedAbstractDeclaredConcreteMethod() → void;
+  method extendedConcreteDeclaredAbstractMethod() → void {}
+  abstract method extendedAbstractDeclaredAbstractMethod() → void;
+  method extendedConcreteImplementedDeclaredConcreteMethod() → void {}
+  abstract method extendedAbstractImplementedDeclaredConcreteMethod() → void;
+  method extendedConcreteImplementedDeclaredAbstractMethod() → void {}
+  abstract method extendedAbstractImplementedDeclaredAbstractMethod() → void;
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method implementedDeclaredConcreteMethod() → void {}
+  method implementedDeclaredAbstractMethod() → void {}
+  method extendedConcreteImplementedDeclaredConcreteMethod() → void {}
+  method extendedAbstractImplementedDeclaredConcreteMethod() → void {}
+  method extendedConcreteImplementedDeclaredAbstractMethod() → void {}
+  method extendedAbstractImplementedDeclaredAbstractMethod() → void {}
+}
+class Class extends self::Super implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  method extendedConcreteDeclaredConcreteMethod() → void {}
+  method extendedAbstractDeclaredConcreteMethod() → void {}
+  abstract method extendedConcreteDeclaredAbstractMethod() → void;
+  abstract method extendedAbstractDeclaredAbstractMethod() → void;
+  method implementedDeclaredConcreteMethod() → void {}
+  abstract method implementedDeclaredAbstractMethod() → void;
+  method extendedConcreteImplementedDeclaredConcreteMethod() → void {}
+  method extendedAbstractImplementedDeclaredConcreteMethod() → void {}
+  abstract method extendedConcreteImplementedDeclaredAbstractMethod() → void;
+  abstract method extendedAbstractImplementedDeclaredAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart
new file mode 100644
index 0000000..92a4681
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart
@@ -0,0 +1,67 @@
+// 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 Super {
+  void superDuplicate1() {}
+  int get superDuplicate1 => 42;
+
+  int get superDuplicate2 => 42;
+  void superDuplicate2() {}
+
+  void extendedDuplicate1() {}
+  void extendedDuplicate2() {}
+}
+
+class Mixin {
+  //void mixinDuplicate1() {}
+  //int get mixinDuplicate1 => 42;
+
+  //int get mixinDuplicate2 => 42;
+  //void mixinDuplicate2() {}
+
+  void mixedInDuplicate1() {}
+  void mixedInDuplicate2() {}
+}
+
+class Interface {
+  void interfaceDuplicate1() {}
+  int get interfaceDuplicate1 => 42;
+
+  int get interfaceDuplicate2 => 42;
+  void interfaceDuplicate2() {}
+
+  void implementedDuplicate1() {}
+  void implementedDuplicate2() {}
+}
+
+abstract class Class extends Super with Mixin implements Interface {
+  void superDuplicate1() {}
+  void superDuplicate2() {}
+
+  void extendedDuplicate1() {}
+  int get extendedDuplicate1 => 42;
+
+  int get extendedDuplicate2 => 42;
+  void extendedDuplicate2() {}
+
+  //void mixinDuplicate1() {}
+  //void mixinDuplicate2() {}
+
+  void mixedInDuplicate1() {}
+  int get mixedInDuplicate1 => 42;
+
+  int get mixedInDuplicate2 => 42;
+  void mixedInDuplicate2() {}
+
+  void interfaceDuplicate1() {}
+  void interfaceDuplicate2() {}
+
+  void implementedDuplicate1() {}
+  int get implementedDuplicate1 => 42;
+
+  int get implementedDuplicate2 => 42;
+  void implementedDuplicate2() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.textual_outline.expect
new file mode 100644
index 0000000..1647703
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.textual_outline.expect
@@ -0,0 +1,43 @@
+class Super {
+  void superDuplicate1() {}
+  int get superDuplicate1 => 42;
+  int get superDuplicate2 => 42;
+  void superDuplicate2() {}
+  void extendedDuplicate1() {}
+  void extendedDuplicate2() {}
+}
+
+class Mixin {
+  void mixedInDuplicate1() {}
+  void mixedInDuplicate2() {}
+}
+
+class Interface {
+  void interfaceDuplicate1() {}
+  int get interfaceDuplicate1 => 42;
+  int get interfaceDuplicate2 => 42;
+  void interfaceDuplicate2() {}
+  void implementedDuplicate1() {}
+  void implementedDuplicate2() {}
+}
+
+abstract class Class extends Super with Mixin implements Interface {
+  void superDuplicate1() {}
+  void superDuplicate2() {}
+  void extendedDuplicate1() {}
+  int get extendedDuplicate1 => 42;
+  int get extendedDuplicate2 => 42;
+  void extendedDuplicate2() {}
+  void mixedInDuplicate1() {}
+  int get mixedInDuplicate1 => 42;
+  int get mixedInDuplicate2 => 42;
+  void mixedInDuplicate2() {}
+  void interfaceDuplicate1() {}
+  void interfaceDuplicate2() {}
+  void implementedDuplicate1() {}
+  int get implementedDuplicate1 => 42;
+  int get implementedDuplicate2 => 42;
+  void implementedDuplicate2() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5255f14
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.textual_outline_modelled.expect
@@ -0,0 +1,43 @@
+abstract class Class extends Super with Mixin implements Interface {
+  int get extendedDuplicate1 => 42;
+  int get extendedDuplicate2 => 42;
+  int get implementedDuplicate1 => 42;
+  int get implementedDuplicate2 => 42;
+  int get mixedInDuplicate1 => 42;
+  int get mixedInDuplicate2 => 42;
+  void extendedDuplicate1() {}
+  void extendedDuplicate2() {}
+  void implementedDuplicate1() {}
+  void implementedDuplicate2() {}
+  void interfaceDuplicate1() {}
+  void interfaceDuplicate2() {}
+  void mixedInDuplicate1() {}
+  void mixedInDuplicate2() {}
+  void superDuplicate1() {}
+  void superDuplicate2() {}
+}
+
+class Interface {
+  int get interfaceDuplicate1 => 42;
+  int get interfaceDuplicate2 => 42;
+  void implementedDuplicate1() {}
+  void implementedDuplicate2() {}
+  void interfaceDuplicate1() {}
+  void interfaceDuplicate2() {}
+}
+
+class Mixin {
+  void mixedInDuplicate1() {}
+  void mixedInDuplicate2() {}
+}
+
+class Super {
+  int get superDuplicate1 => 42;
+  int get superDuplicate2 => 42;
+  void extendedDuplicate1() {}
+  void extendedDuplicate2() {}
+  void superDuplicate1() {}
+  void superDuplicate2() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.weak.expect
new file mode 100644
index 0000000..d51754d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart.weak.expect
@@ -0,0 +1,132 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:7:11: Error: 'superDuplicate1' is already declared in this scope.
+//   int get superDuplicate1 => 42;
+//           ^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:6:8: Context: Previous declaration of 'superDuplicate1'.
+//   void superDuplicate1() {}
+//        ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:10:8: Error: 'superDuplicate2' is already declared in this scope.
+//   void superDuplicate2() {}
+//        ^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:9:11: Context: Previous declaration of 'superDuplicate2'.
+//   int get superDuplicate2 => 42;
+//           ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:29:11: Error: 'interfaceDuplicate1' is already declared in this scope.
+//   int get interfaceDuplicate1 => 42;
+//           ^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:28:8: Context: Previous declaration of 'interfaceDuplicate1'.
+//   void interfaceDuplicate1() {}
+//        ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:32:8: Error: 'interfaceDuplicate2' is already declared in this scope.
+//   void interfaceDuplicate2() {}
+//        ^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:31:11: Context: Previous declaration of 'interfaceDuplicate2'.
+//   int get interfaceDuplicate2 => 42;
+//           ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:43:11: Error: 'extendedDuplicate1' is already declared in this scope.
+//   int get extendedDuplicate1 => 42;
+//           ^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:42:8: Context: Previous declaration of 'extendedDuplicate1'.
+//   void extendedDuplicate1() {}
+//        ^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:46:8: Error: 'extendedDuplicate2' is already declared in this scope.
+//   void extendedDuplicate2() {}
+//        ^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:45:11: Context: Previous declaration of 'extendedDuplicate2'.
+//   int get extendedDuplicate2 => 42;
+//           ^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:52:11: Error: 'mixedInDuplicate1' is already declared in this scope.
+//   int get mixedInDuplicate1 => 42;
+//           ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:51:8: Context: Previous declaration of 'mixedInDuplicate1'.
+//   void mixedInDuplicate1() {}
+//        ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:55:8: Error: 'mixedInDuplicate2' is already declared in this scope.
+//   void mixedInDuplicate2() {}
+//        ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:54:11: Context: Previous declaration of 'mixedInDuplicate2'.
+//   int get mixedInDuplicate2 => 42;
+//           ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:61:11: Error: 'implementedDuplicate1' is already declared in this scope.
+//   int get implementedDuplicate1 => 42;
+//           ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:60:8: Context: Previous declaration of 'implementedDuplicate1'.
+//   void implementedDuplicate1() {}
+//        ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:64:8: Error: 'implementedDuplicate2' is already declared in this scope.
+//   void implementedDuplicate2() {}
+//        ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/duplicates.dart:63:11: Context: Previous declaration of 'implementedDuplicate2'.
+//   int get implementedDuplicate2 => 42;
+//           ^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method superDuplicate1() → void {}
+  get superDuplicate2() → core::int
+    return 42;
+  method extendedDuplicate1() → void {}
+  method extendedDuplicate2() → void {}
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method mixedInDuplicate1() → void {}
+  method mixedInDuplicate2() → void {}
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method interfaceDuplicate1() → void {}
+  get interfaceDuplicate2() → core::int
+    return 42;
+  method implementedDuplicate1() → void {}
+  method implementedDuplicate2() → void {}
+}
+abstract class _Class&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Class&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInDuplicate1() → void
+    return super.{self::Mixin::mixedInDuplicate1}();
+  mixin-super-stub method mixedInDuplicate2() → void
+    return super.{self::Mixin::mixedInDuplicate2}();
+}
+abstract class Class extends self::_Class&Super&Mixin implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Super&Mixin::•()
+    ;
+  method superDuplicate1() → void {}
+  method superDuplicate2() → void {}
+  method extendedDuplicate1() → void {}
+  get extendedDuplicate2() → core::int
+    return 42;
+  method mixedInDuplicate1() → void {}
+  get mixedInDuplicate2() → core::int
+    return 42;
+  method interfaceDuplicate1() → void {}
+  method interfaceDuplicate2() → void {}
+  method implementedDuplicate1() → void {}
+  get implementedDuplicate2() → core::int
+    return 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart
new file mode 100644
index 0000000..ef9ef31
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.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.
+
+abstract class Super {
+  int extendedConcreteField = 0;
+
+  abstract int extendedAbstractField;
+
+  int extendedConcreteImplementedField = 0;
+
+  abstract int extendedAbstractImplementedField;
+
+  int extendedConcreteImplementedMultipleField = 0;
+
+  abstract int extendedAbstractImplementedMultipleField;
+}
+
+class Interface1 {
+  int extendedConcreteImplementedField = 0;
+
+  int extendedAbstractImplementedField = 0;
+
+  int extendedConcreteImplementedMultipleField = 0;
+
+  int extendedAbstractImplementedMultipleField = 0;
+}
+
+class Interface2 {
+  int extendedConcreteImplementedMultipleField = 0;
+
+  int extendedAbstractImplementedMultipleField = 0;
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.textual_outline.expect
new file mode 100644
index 0000000..8e6585a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.textual_outline.expect
@@ -0,0 +1,28 @@
+abstract class Super {
+  int extendedConcreteField = 0;
+  abstract int extendedAbstractField;
+  int extendedConcreteImplementedField = 0;
+  abstract int extendedAbstractImplementedField;
+  int extendedConcreteImplementedMultipleField = 0;
+  abstract int extendedAbstractImplementedMultipleField;
+}
+
+class Interface1 {
+  int extendedConcreteImplementedField = 0;
+  int extendedAbstractImplementedField = 0;
+  int extendedConcreteImplementedMultipleField = 0;
+  int extendedAbstractImplementedMultipleField = 0;
+}
+
+class Interface2 {
+  int extendedConcreteImplementedMultipleField = 0;
+  int extendedAbstractImplementedMultipleField = 0;
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2501812
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,28 @@
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class Super {
+  abstract int extendedAbstractField;
+  abstract int extendedAbstractImplementedField;
+  abstract int extendedAbstractImplementedMultipleField;
+  int extendedConcreteField = 0;
+  int extendedConcreteImplementedField = 0;
+  int extendedConcreteImplementedMultipleField = 0;
+}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  int extendedAbstractImplementedField = 0;
+  int extendedAbstractImplementedMultipleField = 0;
+  int extendedConcreteImplementedField = 0;
+  int extendedConcreteImplementedMultipleField = 0;
+}
+
+class Interface2 {
+  int extendedAbstractImplementedMultipleField = 0;
+  int extendedConcreteImplementedMultipleField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.weak.expect
new file mode 100644
index 0000000..becdaa6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.weak.expect
@@ -0,0 +1,145 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedField
+//  - Interface1.extendedAbstractImplementedMultipleField
+//  - Interface2.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractImplementedField
+//  - Super.extendedAbstractImplementedField=
+//  - Super.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractImplementedMultipleField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:22:7: Context: 'Interface1.extendedAbstractImplementedField' is defined here.
+//   int extendedAbstractImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:26:7: Context: 'Interface1.extendedAbstractImplementedMultipleField' is defined here.
+//   int extendedAbstractImplementedMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:32:7: Context: 'Interface2.extendedAbstractImplementedMultipleField' is defined here.
+//   int extendedAbstractImplementedMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:12:16: Context: 'Super.extendedAbstractImplementedField' is defined here.
+//   abstract int extendedAbstractImplementedField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:12:16: Context: 'Super.extendedAbstractImplementedField=' is defined here.
+//   abstract int extendedAbstractImplementedField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:16:16: Context: 'Super.extendedAbstractImplementedMultipleField' is defined here.
+//   abstract int extendedAbstractImplementedMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:16:16: Context: 'Super.extendedAbstractImplementedMultipleField=' is defined here.
+//   abstract int extendedAbstractImplementedMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedField
+//  - Interface1.extendedAbstractImplementedMultipleField
+//  - Interface2.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractImplementedField
+//  - Super.extendedAbstractImplementedField=
+//  - Super.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractImplementedMultipleField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:22:7: Context: 'Interface1.extendedAbstractImplementedField' is defined here.
+//   int extendedAbstractImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:26:7: Context: 'Interface1.extendedAbstractImplementedMultipleField' is defined here.
+//   int extendedAbstractImplementedMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:32:7: Context: 'Interface2.extendedAbstractImplementedMultipleField' is defined here.
+//   int extendedAbstractImplementedMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:12:16: Context: 'Super.extendedAbstractImplementedField' is defined here.
+//   abstract int extendedAbstractImplementedField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:12:16: Context: 'Super.extendedAbstractImplementedField=' is defined here.
+//   abstract int extendedAbstractImplementedField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:16:16: Context: 'Super.extendedAbstractImplementedMultipleField' is defined here.
+//   abstract int extendedAbstractImplementedMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:16:16: Context: 'Super.extendedAbstractImplementedMultipleField=' is defined here.
+//   abstract int extendedAbstractImplementedMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  field core::int extendedConcreteField = 0;
+  field core::int extendedConcreteImplementedField = 0;
+  field core::int extendedConcreteImplementedMultipleField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract set extendedAbstractField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractImplementedField() → core::int;
+  abstract set extendedAbstractImplementedField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractImplementedMultipleField() → core::int;
+  abstract set extendedAbstractImplementedMultipleField(core::int #externalFieldValue) → void;
+}
+class Interface1 extends core::Object {
+  field core::int extendedConcreteImplementedField = 0;
+  field core::int extendedAbstractImplementedField = 0;
+  field core::int extendedConcreteImplementedMultipleField = 0;
+  field core::int extendedAbstractImplementedMultipleField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  field core::int extendedConcreteImplementedMultipleField = 0;
+  field core::int extendedAbstractImplementedMultipleField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..becdaa6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart.weak.transformed.expect
@@ -0,0 +1,145 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedField
+//  - Interface1.extendedAbstractImplementedMultipleField
+//  - Interface2.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractImplementedField
+//  - Super.extendedAbstractImplementedField=
+//  - Super.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractImplementedMultipleField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:22:7: Context: 'Interface1.extendedAbstractImplementedField' is defined here.
+//   int extendedAbstractImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:26:7: Context: 'Interface1.extendedAbstractImplementedMultipleField' is defined here.
+//   int extendedAbstractImplementedMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:32:7: Context: 'Interface2.extendedAbstractImplementedMultipleField' is defined here.
+//   int extendedAbstractImplementedMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:12:16: Context: 'Super.extendedAbstractImplementedField' is defined here.
+//   abstract int extendedAbstractImplementedField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:12:16: Context: 'Super.extendedAbstractImplementedField=' is defined here.
+//   abstract int extendedAbstractImplementedField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:16:16: Context: 'Super.extendedAbstractImplementedMultipleField' is defined here.
+//   abstract int extendedAbstractImplementedMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:16:16: Context: 'Super.extendedAbstractImplementedMultipleField=' is defined here.
+//   abstract int extendedAbstractImplementedMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedField
+//  - Interface1.extendedAbstractImplementedMultipleField
+//  - Interface2.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractImplementedField
+//  - Super.extendedAbstractImplementedField=
+//  - Super.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractImplementedMultipleField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:22:7: Context: 'Interface1.extendedAbstractImplementedField' is defined here.
+//   int extendedAbstractImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:26:7: Context: 'Interface1.extendedAbstractImplementedMultipleField' is defined here.
+//   int extendedAbstractImplementedMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:32:7: Context: 'Interface2.extendedAbstractImplementedMultipleField' is defined here.
+//   int extendedAbstractImplementedMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:12:16: Context: 'Super.extendedAbstractImplementedField' is defined here.
+//   abstract int extendedAbstractImplementedField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:12:16: Context: 'Super.extendedAbstractImplementedField=' is defined here.
+//   abstract int extendedAbstractImplementedField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:16:16: Context: 'Super.extendedAbstractImplementedMultipleField' is defined here.
+//   abstract int extendedAbstractImplementedMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_field.dart:16:16: Context: 'Super.extendedAbstractImplementedMultipleField=' is defined here.
+//   abstract int extendedAbstractImplementedMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  field core::int extendedConcreteField = 0;
+  field core::int extendedConcreteImplementedField = 0;
+  field core::int extendedConcreteImplementedMultipleField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract set extendedAbstractField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractImplementedField() → core::int;
+  abstract set extendedAbstractImplementedField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractImplementedMultipleField() → core::int;
+  abstract set extendedAbstractImplementedMultipleField(core::int #externalFieldValue) → void;
+}
+class Interface1 extends core::Object {
+  field core::int extendedConcreteImplementedField = 0;
+  field core::int extendedAbstractImplementedField = 0;
+  field core::int extendedConcreteImplementedMultipleField = 0;
+  field core::int extendedAbstractImplementedMultipleField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  field core::int extendedConcreteImplementedMultipleField = 0;
+  field core::int extendedAbstractImplementedMultipleField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart
new file mode 100644
index 0000000..f4c9530
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.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.
+
+abstract class Super {
+  final int extendedConcreteField = 0;
+
+  abstract final int extendedAbstractField;
+
+  final int extendedConcreteImplementedField = 0;
+
+  abstract final int extendedAbstractImplementedField;
+
+  final int extendedConcreteImplementedMultipleField = 0;
+
+  abstract final int extendedAbstractImplementedMultipleField;
+}
+
+class Interface1 {
+  final int extendedConcreteImplementedField = 0;
+
+  final int extendedAbstractImplementedField = 0;
+
+  final int extendedConcreteImplementedMultipleField = 0;
+
+  final int extendedAbstractImplementedMultipleField = 0;
+}
+
+class Interface2 {
+  final int extendedConcreteImplementedMultipleField = 0;
+
+  final int extendedAbstractImplementedMultipleField = 0;
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.textual_outline.expect
new file mode 100644
index 0000000..03a436e5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.textual_outline.expect
@@ -0,0 +1,28 @@
+abstract class Super {
+  final int extendedConcreteField = 0;
+  abstract final int extendedAbstractField;
+  final int extendedConcreteImplementedField = 0;
+  abstract final int extendedAbstractImplementedField;
+  final int extendedConcreteImplementedMultipleField = 0;
+  abstract final int extendedAbstractImplementedMultipleField;
+}
+
+class Interface1 {
+  final int extendedConcreteImplementedField = 0;
+  final int extendedAbstractImplementedField = 0;
+  final int extendedConcreteImplementedMultipleField = 0;
+  final int extendedAbstractImplementedMultipleField = 0;
+}
+
+class Interface2 {
+  final int extendedConcreteImplementedMultipleField = 0;
+  final int extendedAbstractImplementedMultipleField = 0;
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cff7a0d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,28 @@
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class Super {
+  abstract final int extendedAbstractField;
+  abstract final int extendedAbstractImplementedField;
+  abstract final int extendedAbstractImplementedMultipleField;
+  final int extendedConcreteField = 0;
+  final int extendedConcreteImplementedField = 0;
+  final int extendedConcreteImplementedMultipleField = 0;
+}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  final int extendedAbstractImplementedField = 0;
+  final int extendedAbstractImplementedMultipleField = 0;
+  final int extendedConcreteImplementedField = 0;
+  final int extendedConcreteImplementedMultipleField = 0;
+}
+
+class Interface2 {
+  final int extendedAbstractImplementedMultipleField = 0;
+  final int extendedConcreteImplementedMultipleField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.weak.expect
new file mode 100644
index 0000000..e65fe64
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.weak.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedField
+//  - Interface1.extendedAbstractImplementedMultipleField
+//  - Interface2.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractImplementedField
+//  - Super.extendedAbstractImplementedMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:22:13: Context: 'Interface1.extendedAbstractImplementedField' is defined here.
+//   final int extendedAbstractImplementedField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:26:13: Context: 'Interface1.extendedAbstractImplementedMultipleField' is defined here.
+//   final int extendedAbstractImplementedMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:32:13: Context: 'Interface2.extendedAbstractImplementedMultipleField' is defined here.
+//   final int extendedAbstractImplementedMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:12:22: Context: 'Super.extendedAbstractImplementedField' is defined here.
+//   abstract final int extendedAbstractImplementedField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:16:22: Context: 'Super.extendedAbstractImplementedMultipleField' is defined here.
+//   abstract final int extendedAbstractImplementedMultipleField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedField
+//  - Interface1.extendedAbstractImplementedMultipleField
+//  - Interface2.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractImplementedField
+//  - Super.extendedAbstractImplementedMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:22:13: Context: 'Interface1.extendedAbstractImplementedField' is defined here.
+//   final int extendedAbstractImplementedField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:26:13: Context: 'Interface1.extendedAbstractImplementedMultipleField' is defined here.
+//   final int extendedAbstractImplementedMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:32:13: Context: 'Interface2.extendedAbstractImplementedMultipleField' is defined here.
+//   final int extendedAbstractImplementedMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:12:22: Context: 'Super.extendedAbstractImplementedField' is defined here.
+//   abstract final int extendedAbstractImplementedField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:16:22: Context: 'Super.extendedAbstractImplementedMultipleField' is defined here.
+//   abstract final int extendedAbstractImplementedMultipleField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  final field core::int extendedConcreteField = 0;
+  final field core::int extendedConcreteImplementedField = 0;
+  final field core::int extendedConcreteImplementedMultipleField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract get extendedAbstractImplementedField() → core::int;
+  abstract get extendedAbstractImplementedMultipleField() → core::int;
+}
+class Interface1 extends core::Object {
+  final field core::int extendedConcreteImplementedField = 0;
+  final field core::int extendedAbstractImplementedField = 0;
+  final field core::int extendedConcreteImplementedMultipleField = 0;
+  final field core::int extendedAbstractImplementedMultipleField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  final field core::int extendedConcreteImplementedMultipleField = 0;
+  final field core::int extendedAbstractImplementedMultipleField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..e65fe64
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart.weak.transformed.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedField
+//  - Interface1.extendedAbstractImplementedMultipleField
+//  - Interface2.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractImplementedField
+//  - Super.extendedAbstractImplementedMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:22:13: Context: 'Interface1.extendedAbstractImplementedField' is defined here.
+//   final int extendedAbstractImplementedField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:26:13: Context: 'Interface1.extendedAbstractImplementedMultipleField' is defined here.
+//   final int extendedAbstractImplementedMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:32:13: Context: 'Interface2.extendedAbstractImplementedMultipleField' is defined here.
+//   final int extendedAbstractImplementedMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:12:22: Context: 'Super.extendedAbstractImplementedField' is defined here.
+//   abstract final int extendedAbstractImplementedField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:16:22: Context: 'Super.extendedAbstractImplementedMultipleField' is defined here.
+//   abstract final int extendedAbstractImplementedMultipleField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedField
+//  - Interface1.extendedAbstractImplementedMultipleField
+//  - Interface2.extendedAbstractImplementedMultipleField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractImplementedField
+//  - Super.extendedAbstractImplementedMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:22:13: Context: 'Interface1.extendedAbstractImplementedField' is defined here.
+//   final int extendedAbstractImplementedField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:26:13: Context: 'Interface1.extendedAbstractImplementedMultipleField' is defined here.
+//   final int extendedAbstractImplementedMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:32:13: Context: 'Interface2.extendedAbstractImplementedMultipleField' is defined here.
+//   final int extendedAbstractImplementedMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:12:22: Context: 'Super.extendedAbstractImplementedField' is defined here.
+//   abstract final int extendedAbstractImplementedField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_final_field.dart:16:22: Context: 'Super.extendedAbstractImplementedMultipleField' is defined here.
+//   abstract final int extendedAbstractImplementedMultipleField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  final field core::int extendedConcreteField = 0;
+  final field core::int extendedConcreteImplementedField = 0;
+  final field core::int extendedConcreteImplementedMultipleField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract get extendedAbstractImplementedField() → core::int;
+  abstract get extendedAbstractImplementedMultipleField() → core::int;
+}
+class Interface1 extends core::Object {
+  final field core::int extendedConcreteImplementedField = 0;
+  final field core::int extendedAbstractImplementedField = 0;
+  final field core::int extendedConcreteImplementedMultipleField = 0;
+  final field core::int extendedAbstractImplementedMultipleField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  final field core::int extendedConcreteImplementedMultipleField = 0;
+  final field core::int extendedAbstractImplementedMultipleField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart
new file mode 100644
index 0000000..e7cdf82
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.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.
+
+abstract class Super {
+  int get extendedConcreteGetter => 0;
+
+  int get extendedAbstractGetter;
+
+  int get extendedConcreteImplementedGetter => 0;
+
+  int get extendedAbstractImplementedGetter;
+
+  int get extendedConcreteImplementedMultipleGetter => 0;
+
+  int get extendedAbstractImplementedMultipleGetter;
+}
+
+class Interface1 {
+  int get extendedConcreteImplementedGetter => 0;
+
+  int get extendedAbstractImplementedGetter => 0;
+
+  int get extendedConcreteImplementedMultipleGetter => 0;
+
+  int get extendedAbstractImplementedMultipleGetter => 0;
+}
+
+class Interface2 {
+  int get extendedConcreteImplementedMultipleGetter => 0;
+
+  int get extendedAbstractImplementedMultipleGetter => 0;
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.textual_outline.expect
new file mode 100644
index 0000000..2d035e0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.textual_outline.expect
@@ -0,0 +1,28 @@
+abstract class Super {
+  int get extendedConcreteGetter => 0;
+  int get extendedAbstractGetter;
+  int get extendedConcreteImplementedGetter => 0;
+  int get extendedAbstractImplementedGetter;
+  int get extendedConcreteImplementedMultipleGetter => 0;
+  int get extendedAbstractImplementedMultipleGetter;
+}
+
+class Interface1 {
+  int get extendedConcreteImplementedGetter => 0;
+  int get extendedAbstractImplementedGetter => 0;
+  int get extendedConcreteImplementedMultipleGetter => 0;
+  int get extendedAbstractImplementedMultipleGetter => 0;
+}
+
+class Interface2 {
+  int get extendedConcreteImplementedMultipleGetter => 0;
+  int get extendedAbstractImplementedMultipleGetter => 0;
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d52a740
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.textual_outline_modelled.expect
@@ -0,0 +1,28 @@
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class Super {
+  int get extendedAbstractGetter;
+  int get extendedAbstractImplementedGetter;
+  int get extendedAbstractImplementedMultipleGetter;
+  int get extendedConcreteGetter => 0;
+  int get extendedConcreteImplementedGetter => 0;
+  int get extendedConcreteImplementedMultipleGetter => 0;
+}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  int get extendedAbstractImplementedGetter => 0;
+  int get extendedAbstractImplementedMultipleGetter => 0;
+  int get extendedConcreteImplementedGetter => 0;
+  int get extendedConcreteImplementedMultipleGetter => 0;
+}
+
+class Interface2 {
+  int get extendedAbstractImplementedMultipleGetter => 0;
+  int get extendedConcreteImplementedMultipleGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.weak.expect
new file mode 100644
index 0000000..39f968f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.weak.expect
@@ -0,0 +1,127 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedGetter
+//  - Interface1.extendedAbstractImplementedMultipleGetter
+//  - Interface2.extendedAbstractImplementedMultipleGetter
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractImplementedGetter
+//  - Super.extendedAbstractImplementedMultipleGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:22:11: Context: 'Interface1.extendedAbstractImplementedGetter' is defined here.
+//   int get extendedAbstractImplementedGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:26:11: Context: 'Interface1.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:32:11: Context: 'Interface2.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:12:11: Context: 'Super.extendedAbstractImplementedGetter' is defined here.
+//   int get extendedAbstractImplementedGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:16:11: Context: 'Super.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedGetter
+//  - Interface1.extendedAbstractImplementedMultipleGetter
+//  - Interface2.extendedAbstractImplementedMultipleGetter
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractImplementedGetter
+//  - Super.extendedAbstractImplementedMultipleGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:22:11: Context: 'Interface1.extendedAbstractImplementedGetter' is defined here.
+//   int get extendedAbstractImplementedGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:26:11: Context: 'Interface1.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:32:11: Context: 'Interface2.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:12:11: Context: 'Super.extendedAbstractImplementedGetter' is defined here.
+//   int get extendedAbstractImplementedGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:16:11: Context: 'Super.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  get extendedConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractGetter() → core::int;
+  get extendedConcreteImplementedGetter() → core::int
+    return 0;
+  abstract get extendedAbstractImplementedGetter() → core::int;
+  get extendedConcreteImplementedMultipleGetter() → core::int
+    return 0;
+  abstract get extendedAbstractImplementedMultipleGetter() → core::int;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  get extendedConcreteImplementedGetter() → core::int
+    return 0;
+  get extendedAbstractImplementedGetter() → core::int
+    return 0;
+  get extendedConcreteImplementedMultipleGetter() → core::int
+    return 0;
+  get extendedAbstractImplementedMultipleGetter() → core::int
+    return 0;
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  get extendedConcreteImplementedMultipleGetter() → core::int
+    return 0;
+  get extendedAbstractImplementedMultipleGetter() → core::int
+    return 0;
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.weak.transformed.expect
new file mode 100644
index 0000000..39f968f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart.weak.transformed.expect
@@ -0,0 +1,127 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedGetter
+//  - Interface1.extendedAbstractImplementedMultipleGetter
+//  - Interface2.extendedAbstractImplementedMultipleGetter
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractImplementedGetter
+//  - Super.extendedAbstractImplementedMultipleGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:22:11: Context: 'Interface1.extendedAbstractImplementedGetter' is defined here.
+//   int get extendedAbstractImplementedGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:26:11: Context: 'Interface1.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:32:11: Context: 'Interface2.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:12:11: Context: 'Super.extendedAbstractImplementedGetter' is defined here.
+//   int get extendedAbstractImplementedGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:16:11: Context: 'Super.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedGetter
+//  - Interface1.extendedAbstractImplementedMultipleGetter
+//  - Interface2.extendedAbstractImplementedMultipleGetter
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractImplementedGetter
+//  - Super.extendedAbstractImplementedMultipleGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:22:11: Context: 'Interface1.extendedAbstractImplementedGetter' is defined here.
+//   int get extendedAbstractImplementedGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:26:11: Context: 'Interface1.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:32:11: Context: 'Interface2.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:12:11: Context: 'Super.extendedAbstractImplementedGetter' is defined here.
+//   int get extendedAbstractImplementedGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_getter.dart:16:11: Context: 'Super.extendedAbstractImplementedMultipleGetter' is defined here.
+//   int get extendedAbstractImplementedMultipleGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  get extendedConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractGetter() → core::int;
+  get extendedConcreteImplementedGetter() → core::int
+    return 0;
+  abstract get extendedAbstractImplementedGetter() → core::int;
+  get extendedConcreteImplementedMultipleGetter() → core::int
+    return 0;
+  abstract get extendedAbstractImplementedMultipleGetter() → core::int;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  get extendedConcreteImplementedGetter() → core::int
+    return 0;
+  get extendedAbstractImplementedGetter() → core::int
+    return 0;
+  get extendedConcreteImplementedMultipleGetter() → core::int
+    return 0;
+  get extendedAbstractImplementedMultipleGetter() → core::int
+    return 0;
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  get extendedConcreteImplementedMultipleGetter() → core::int
+    return 0;
+  get extendedAbstractImplementedMultipleGetter() → core::int
+    return 0;
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart
new file mode 100644
index 0000000..2bdf042
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.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.
+
+abstract class Super {
+  void extendedConcreteMethod() {}
+
+  void extendedAbstractMethod();
+
+  void extendedConcreteImplementedMethod() {}
+
+  void extendedAbstractImplementedMethod();
+
+  void extendedConcreteImplementedMultipleMethod() {}
+
+  void extendedAbstractImplementedMultipleMethod();
+}
+
+class Interface1 {
+  void extendedConcreteImplementedMethod() {}
+
+  void extendedAbstractImplementedMethod() {}
+
+  void extendedConcreteImplementedMultipleMethod() {}
+
+  void extendedAbstractImplementedMultipleMethod() {}
+}
+
+class Interface2 {
+  void extendedConcreteImplementedMultipleMethod() {}
+
+  void extendedAbstractImplementedMultipleMethod() {}
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.textual_outline.expect
new file mode 100644
index 0000000..ffe3605
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.textual_outline.expect
@@ -0,0 +1,28 @@
+abstract class Super {
+  void extendedConcreteMethod() {}
+  void extendedAbstractMethod();
+  void extendedConcreteImplementedMethod() {}
+  void extendedAbstractImplementedMethod();
+  void extendedConcreteImplementedMultipleMethod() {}
+  void extendedAbstractImplementedMultipleMethod();
+}
+
+class Interface1 {
+  void extendedConcreteImplementedMethod() {}
+  void extendedAbstractImplementedMethod() {}
+  void extendedConcreteImplementedMultipleMethod() {}
+  void extendedAbstractImplementedMultipleMethod() {}
+}
+
+class Interface2 {
+  void extendedConcreteImplementedMultipleMethod() {}
+  void extendedAbstractImplementedMultipleMethod() {}
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9539d08
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,28 @@
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class Super {
+  void extendedAbstractImplementedMethod();
+  void extendedAbstractImplementedMultipleMethod();
+  void extendedAbstractMethod();
+  void extendedConcreteImplementedMethod() {}
+  void extendedConcreteImplementedMultipleMethod() {}
+  void extendedConcreteMethod() {}
+}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  void extendedAbstractImplementedMethod() {}
+  void extendedAbstractImplementedMultipleMethod() {}
+  void extendedConcreteImplementedMethod() {}
+  void extendedConcreteImplementedMultipleMethod() {}
+}
+
+class Interface2 {
+  void extendedAbstractImplementedMultipleMethod() {}
+  void extendedConcreteImplementedMultipleMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.weak.expect
new file mode 100644
index 0000000..2bb4d30
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.weak.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMethod
+//  - Interface1.extendedAbstractImplementedMultipleMethod
+//  - Interface2.extendedAbstractImplementedMultipleMethod
+//  - Super.extendedAbstractImplementedMethod
+//  - Super.extendedAbstractImplementedMultipleMethod
+//  - Super.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:22:8: Context: 'Interface1.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:26:8: Context: 'Interface1.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:32:8: Context: 'Interface2.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:12:8: Context: 'Super.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:16:8: Context: 'Super.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMethod
+//  - Interface1.extendedAbstractImplementedMultipleMethod
+//  - Interface2.extendedAbstractImplementedMultipleMethod
+//  - Super.extendedAbstractImplementedMethod
+//  - Super.extendedAbstractImplementedMultipleMethod
+//  - Super.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:22:8: Context: 'Interface1.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:26:8: Context: 'Interface1.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:32:8: Context: 'Interface2.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:12:8: Context: 'Super.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:16:8: Context: 'Super.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method extendedConcreteImplementedMethod() → void {}
+  abstract method extendedAbstractImplementedMethod() → void;
+  method extendedConcreteImplementedMultipleMethod() → void {}
+  abstract method extendedAbstractImplementedMultipleMethod() → void;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method extendedConcreteImplementedMethod() → void {}
+  method extendedAbstractImplementedMethod() → void {}
+  method extendedConcreteImplementedMultipleMethod() → void {}
+  method extendedAbstractImplementedMultipleMethod() → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method extendedConcreteImplementedMultipleMethod() → void {}
+  method extendedAbstractImplementedMultipleMethod() → void {}
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..2bb4d30
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart.weak.transformed.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMethod
+//  - Interface1.extendedAbstractImplementedMultipleMethod
+//  - Interface2.extendedAbstractImplementedMultipleMethod
+//  - Super.extendedAbstractImplementedMethod
+//  - Super.extendedAbstractImplementedMultipleMethod
+//  - Super.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:22:8: Context: 'Interface1.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:26:8: Context: 'Interface1.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:32:8: Context: 'Interface2.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:12:8: Context: 'Super.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:16:8: Context: 'Super.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMethod
+//  - Interface1.extendedAbstractImplementedMultipleMethod
+//  - Interface2.extendedAbstractImplementedMultipleMethod
+//  - Super.extendedAbstractImplementedMethod
+//  - Super.extendedAbstractImplementedMultipleMethod
+//  - Super.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:22:8: Context: 'Interface1.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:26:8: Context: 'Interface1.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:32:8: Context: 'Interface2.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:12:8: Context: 'Super.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:16:8: Context: 'Super.extendedAbstractImplementedMultipleMethod' is defined here.
+//   void extendedAbstractImplementedMultipleMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method extendedConcreteImplementedMethod() → void {}
+  abstract method extendedAbstractImplementedMethod() → void;
+  method extendedConcreteImplementedMultipleMethod() → void {}
+  abstract method extendedAbstractImplementedMultipleMethod() → void;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method extendedConcreteImplementedMethod() → void {}
+  method extendedAbstractImplementedMethod() → void {}
+  method extendedConcreteImplementedMultipleMethod() → void {}
+  method extendedAbstractImplementedMultipleMethod() → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method extendedConcreteImplementedMultipleMethod() → void {}
+  method extendedAbstractImplementedMultipleMethod() → void {}
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart
new file mode 100644
index 0000000..2026b82
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.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.
+
+abstract class Super {
+  void set extendedConcreteSetter(int value) {}
+
+  void set extendedAbstractSetter(int value);
+
+  void set extendedConcreteImplementedSetter(int value) {}
+
+  void set extendedAbstractImplementedSetter(int value);
+
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+
+  void set extendedAbstractImplementedMultipleSetter(int value);
+}
+
+class Interface1 {
+  void set extendedConcreteImplementedSetter(int value) {}
+
+  void set extendedAbstractImplementedSetter(int value) {}
+
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+
+  void set extendedAbstractImplementedMultipleSetter(int value) {}
+}
+
+class Interface2 {
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+
+  void set extendedAbstractImplementedMultipleSetter(int value) {}
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..be8c083
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.textual_outline.expect
@@ -0,0 +1,28 @@
+abstract class Super {
+  void set extendedConcreteSetter(int value) {}
+  void set extendedAbstractSetter(int value);
+  void set extendedConcreteImplementedSetter(int value) {}
+  void set extendedAbstractImplementedSetter(int value);
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+  void set extendedAbstractImplementedMultipleSetter(int value);
+}
+
+class Interface1 {
+  void set extendedConcreteImplementedSetter(int value) {}
+  void set extendedAbstractImplementedSetter(int value) {}
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+  void set extendedAbstractImplementedMultipleSetter(int value) {}
+}
+
+class Interface2 {
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+  void set extendedAbstractImplementedMultipleSetter(int value) {}
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ad902f2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,28 @@
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class Super {
+  void set extendedAbstractImplementedMultipleSetter(int value);
+  void set extendedAbstractImplementedSetter(int value);
+  void set extendedAbstractSetter(int value);
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+  void set extendedConcreteImplementedSetter(int value) {}
+  void set extendedConcreteSetter(int value) {}
+}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  void set extendedAbstractImplementedMultipleSetter(int value) {}
+  void set extendedAbstractImplementedSetter(int value) {}
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+  void set extendedConcreteImplementedSetter(int value) {}
+}
+
+class Interface2 {
+  void set extendedAbstractImplementedMultipleSetter(int value) {}
+  void set extendedConcreteImplementedMultipleSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.weak.expect
new file mode 100644
index 0000000..e2cfcb3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.weak.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMultipleSetter=
+//  - Interface1.extendedAbstractImplementedSetter=
+//  - Interface2.extendedAbstractImplementedMultipleSetter=
+//  - Super.extendedAbstractImplementedMultipleSetter=
+//  - Super.extendedAbstractImplementedSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:26:12: Context: 'Interface1.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:22:12: Context: 'Interface1.extendedAbstractImplementedSetter=' is defined here.
+//   void set extendedAbstractImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:32:12: Context: 'Interface2.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:16:12: Context: 'Super.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:12:12: Context: 'Super.extendedAbstractImplementedSetter=' is defined here.
+//   void set extendedAbstractImplementedSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMultipleSetter=
+//  - Interface1.extendedAbstractImplementedSetter=
+//  - Interface2.extendedAbstractImplementedMultipleSetter=
+//  - Super.extendedAbstractImplementedMultipleSetter=
+//  - Super.extendedAbstractImplementedSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:26:12: Context: 'Interface1.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:22:12: Context: 'Interface1.extendedAbstractImplementedSetter=' is defined here.
+//   void set extendedAbstractImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:32:12: Context: 'Interface2.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:16:12: Context: 'Super.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:12:12: Context: 'Super.extendedAbstractImplementedSetter=' is defined here.
+//   void set extendedAbstractImplementedSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  set extendedConcreteSetter(core::int value) → void {}
+  abstract set extendedAbstractSetter(core::int value) → void;
+  set extendedConcreteImplementedSetter(core::int value) → void {}
+  abstract set extendedAbstractImplementedSetter(core::int value) → void;
+  set extendedConcreteImplementedMultipleSetter(core::int value) → void {}
+  abstract set extendedAbstractImplementedMultipleSetter(core::int value) → void;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  set extendedConcreteImplementedSetter(core::int value) → void {}
+  set extendedAbstractImplementedSetter(core::int value) → void {}
+  set extendedConcreteImplementedMultipleSetter(core::int value) → void {}
+  set extendedAbstractImplementedMultipleSetter(core::int value) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  set extendedConcreteImplementedMultipleSetter(core::int value) → void {}
+  set extendedAbstractImplementedMultipleSetter(core::int value) → void {}
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.weak.transformed.expect
new file mode 100644
index 0000000..e2cfcb3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart.weak.transformed.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:37:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMultipleSetter=
+//  - Interface1.extendedAbstractImplementedSetter=
+//  - Interface2.extendedAbstractImplementedMultipleSetter=
+//  - Super.extendedAbstractImplementedMultipleSetter=
+//  - Super.extendedAbstractImplementedSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:26:12: Context: 'Interface1.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:22:12: Context: 'Interface1.extendedAbstractImplementedSetter=' is defined here.
+//   void set extendedAbstractImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:32:12: Context: 'Interface2.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:16:12: Context: 'Super.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:12:12: Context: 'Super.extendedAbstractImplementedSetter=' is defined here.
+//   void set extendedAbstractImplementedSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:39:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMultipleSetter=
+//  - Interface1.extendedAbstractImplementedSetter=
+//  - Interface2.extendedAbstractImplementedMultipleSetter=
+//  - Super.extendedAbstractImplementedMultipleSetter=
+//  - Super.extendedAbstractImplementedSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:26:12: Context: 'Interface1.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:22:12: Context: 'Interface1.extendedAbstractImplementedSetter=' is defined here.
+//   void set extendedAbstractImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:32:12: Context: 'Interface2.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:16:12: Context: 'Super.extendedAbstractImplementedMultipleSetter=' is defined here.
+//   void set extendedAbstractImplementedMultipleSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:12:12: Context: 'Super.extendedAbstractImplementedSetter=' is defined here.
+//   void set extendedAbstractImplementedSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/extend_multiple_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int value);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  set extendedConcreteSetter(core::int value) → void {}
+  abstract set extendedAbstractSetter(core::int value) → void;
+  set extendedConcreteImplementedSetter(core::int value) → void {}
+  abstract set extendedAbstractImplementedSetter(core::int value) → void;
+  set extendedConcreteImplementedMultipleSetter(core::int value) → void {}
+  abstract set extendedAbstractImplementedMultipleSetter(core::int value) → void;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  set extendedConcreteImplementedSetter(core::int value) → void {}
+  set extendedAbstractImplementedSetter(core::int value) → void {}
+  set extendedConcreteImplementedMultipleSetter(core::int value) → void {}
+  set extendedAbstractImplementedMultipleSetter(core::int value) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  set extendedConcreteImplementedMultipleSetter(core::int value) → void {}
+  set extendedAbstractImplementedMultipleSetter(core::int value) → void {}
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart
new file mode 100644
index 0000000..a239ed9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.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.
+
+class Super {
+  num field1 = 0;
+  num field2 = 0;
+  num field3 = 0;
+
+  covariant num field4 = 0;
+  covariant int field5 = 0;
+}
+
+class Interface {
+  covariant int field1 = 0;
+  covariant int field2 = 0;
+
+  int field4 = 0;
+  int field5 = 0;
+}
+
+class Class extends Super implements Interface {
+  abstract int field1;
+  abstract String field2;
+  abstract int field3;
+
+  abstract int field4;
+  abstract num field5;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.textual_outline.expect
new file mode 100644
index 0000000..5623cfe94
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.textual_outline.expect
@@ -0,0 +1,24 @@
+class Super {
+  num field1 = 0;
+  num field2 = 0;
+  num field3 = 0;
+  covariant num field4 = 0;
+  covariant int field5 = 0;
+}
+
+class Interface {
+  covariant int field1 = 0;
+  covariant int field2 = 0;
+  int field4 = 0;
+  int field5 = 0;
+}
+
+class Class extends Super implements Interface {
+  abstract int field1;
+  abstract String field2;
+  abstract int field3;
+  abstract int field4;
+  abstract num field5;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..54c91bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class Class extends Super implements Interface {
+  abstract String field2;
+  abstract int field1;
+  abstract int field3;
+  abstract int field4;
+  abstract num field5;
+}
+
+class Interface {
+  covariant int field1 = 0;
+  covariant int field2 = 0;
+  int field4 = 0;
+  int field5 = 0;
+}
+
+class Super {
+  covariant int field5 = 0;
+  covariant num field4 = 0;
+  num field1 = 0;
+  num field2 = 0;
+  num field3 = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.weak.expect
new file mode 100644
index 0000000..fe7b938
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart.weak.expect
@@ -0,0 +1,144 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:24:19: Error: The return type of the method 'Class.field2' is 'String', which does not match the return type, 'num', of the overridden method, 'Super.field2'.
+// Change to a subtype of 'num'.
+//   abstract String field2;
+//                   ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:7:7: Context: This is the overridden method ('field2').
+//   num field2 = 0;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:24:19: Error: The return type of the method 'Class.field2' is 'String', which does not match the return type, 'int', of the overridden method, 'Interface.field2'.
+// Change to a subtype of 'int'.
+//   abstract String field2;
+//                   ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:16:17: Context: This is the overridden method ('field2').
+//   covariant int field2 = 0;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:24:19: Error: The parameter '#externalFieldValue' of the method 'Class.field2' has type 'String', which does not match the corresponding type, 'num', in the overridden method, 'Super.field2'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   abstract String field2;
+//                   ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:7:7: Context: This is the overridden method ('field2').
+//   num field2 = 0;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:24:19: Error: The parameter '#externalFieldValue' of the method 'Class.field2' has type 'String', which does not match the corresponding type, 'int', in the overridden method, 'Interface.field2'.
+// Change to a supertype of 'int', or, for a covariant parameter, a subtype.
+//   abstract String field2;
+//                   ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:16:17: Context: This is the overridden method ('field2').
+//   covariant int field2 = 0;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:25:16: Error: The parameter '#externalFieldValue' of the method 'Class.field3' has type 'int', which does not match the corresponding type, 'num', in the overridden method, 'Super.field3'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   abstract int field3;
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:8:7: Context: This is the overridden method ('field3').
+//   num field3 = 0;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:28:16: Error: The return type of the method 'Class.field5' is 'num', which does not match the return type, 'int', of the overridden method, 'Super.field5'.
+// Change to a subtype of 'int'.
+//   abstract num field5;
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:11:17: Context: This is the overridden method ('field5').
+//   covariant int field5 = 0;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:28:16: Error: The return type of the method 'Class.field5' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface.field5'.
+// Change to a subtype of 'int'.
+//   abstract num field5;
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:19:7: Context: This is the overridden method ('field5').
+//   int field5 = 0;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:22:7: Error: The implementation of 'field1' in the non-abstract class 'Class' does not conform to its interface.
+// class Class extends Super implements Interface {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:6:7: Context: The return type of the method 'Super.field1' is 'num', which does not match the return type, 'int', of the overridden method, 'Class.field1'.
+// Change to a subtype of 'int'.
+//   num field1 = 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:23:16: Context: This is the overridden method ('field1').
+//   abstract int field1;
+//                ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:22:7: Error: The implementation of 'field2' in the non-abstract class 'Class' does not conform to its interface.
+// class Class extends Super implements Interface {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:7:7: Context: The return type of the method 'Super.field2' is 'num', which does not match the return type, 'String', of the overridden method, 'Class.field2'.
+// Change to a subtype of 'String'.
+//   num field2 = 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:24:19: Context: This is the overridden method ('field2').
+//   abstract String field2;
+//                   ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:22:7: Error: The implementation of 'field3' in the non-abstract class 'Class' does not conform to its interface.
+// class Class extends Super implements Interface {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:8:7: Context: The return type of the method 'Super.field3' is 'num', which does not match the return type, 'int', of the overridden method, 'Class.field3'.
+// Change to a subtype of 'int'.
+//   num field3 = 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:25:16: Context: This is the overridden method ('field3').
+//   abstract int field3;
+//                ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:22:7: Error: The implementation of 'field4' in the non-abstract class 'Class' does not conform to its interface.
+// class Class extends Super implements Interface {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:10:17: Context: The return type of the method 'Super.field4' is 'num', which does not match the return type, 'int', of the overridden method, 'Class.field4'.
+// Change to a subtype of 'int'.
+//   covariant num field4 = 0;
+//                 ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_field.dart:27:16: Context: This is the overridden method ('field4').
+//   abstract int field4;
+//                ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  field core::num field1 = 0;
+  field core::num field2 = 0;
+  field core::num field3 = 0;
+  covariant field core::num field4 = 0;
+  covariant field core::int field5 = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+}
+class Interface extends core::Object {
+  covariant field core::int field1 = 0;
+  covariant field core::int field2 = 0;
+  field core::int field4 = 0;
+  field core::int field5 = 0;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+}
+class Class extends self::Super implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  abstract get field1() → core::int;
+  forwarding-stub forwarding-semi-stub set field1(covariant core::int #externalFieldValue) → void
+    return super.{self::Super::field1} = #externalFieldValue;
+  abstract get field2() → core::String;
+  forwarding-stub forwarding-semi-stub set field2(covariant core::String #externalFieldValue) → void
+    return super.{self::Super::field2} = #externalFieldValue;
+  abstract get field3() → core::int;
+  abstract set field3(core::int #externalFieldValue) → void;
+  abstract get field4() → core::int;
+  abstract set field4(covariant core::int #externalFieldValue) → void;
+  abstract get field5() → core::num;
+  abstract set field5(covariant core::num #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart
new file mode 100644
index 0000000..12d4af5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.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.
+
+class Super {
+  void method1(num n) {}
+  void method2(num n) {}
+  void method3(num n) {}
+
+  void method4(covariant num i) {}
+  void method5(covariant int i) {}
+}
+
+class Interface {
+  void method1(covariant int i) {}
+  void method2(covariant int i) {}
+
+  void method4(int i) {}
+  void method5(int i) {}
+}
+
+class Class extends Super implements Interface {
+  void method1(int i);
+  void method2(String i);
+  void method3(int i);
+
+  void method4(int i);
+  void method5(num n);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.textual_outline.expect
new file mode 100644
index 0000000..ceef571
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.textual_outline.expect
@@ -0,0 +1,24 @@
+class Super {
+  void method1(num n) {}
+  void method2(num n) {}
+  void method3(num n) {}
+  void method4(covariant num i) {}
+  void method5(covariant int i) {}
+}
+
+class Interface {
+  void method1(covariant int i) {}
+  void method2(covariant int i) {}
+  void method4(int i) {}
+  void method5(int i) {}
+}
+
+class Class extends Super implements Interface {
+  void method1(int i);
+  void method2(String i);
+  void method3(int i);
+  void method4(int i);
+  void method5(num n);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3456994
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class Class extends Super implements Interface {
+  void method1(int i);
+  void method2(String i);
+  void method3(int i);
+  void method4(int i);
+  void method5(num n);
+}
+
+class Interface {
+  void method1(covariant int i) {}
+  void method2(covariant int i) {}
+  void method4(int i) {}
+  void method5(int i) {}
+}
+
+class Super {
+  void method1(num n) {}
+  void method2(num n) {}
+  void method3(num n) {}
+  void method4(covariant num i) {}
+  void method5(covariant int i) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.weak.expect
new file mode 100644
index 0000000..e46c242
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart.weak.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:24:23: Error: The parameter 'i' of the method 'Class.method2' has type 'String', which does not match the corresponding type, 'num', in the overridden method, 'Super.method2'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   void method2(String i);
+//                       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:7:8: Context: This is the overridden method ('method2').
+//   void method2(num n) {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:24:23: Error: The parameter 'i' of the method 'Class.method2' has type 'String', which does not match the corresponding type, 'int', in the overridden method, 'Interface.method2'.
+// Change to a supertype of 'int', or, for a covariant parameter, a subtype.
+//   void method2(String i);
+//                       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:16:8: Context: This is the overridden method ('method2').
+//   void method2(covariant int i) {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:25:20: Error: The parameter 'i' of the method 'Class.method3' has type 'int', which does not match the corresponding type, 'num', in the overridden method, 'Super.method3'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   void method3(int i);
+//                    ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:8:8: Context: This is the overridden method ('method3').
+//   void method3(num n) {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:22:7: Error: The implementation of 'method2' in the non-abstract class 'Class' does not conform to its interface.
+// class Class extends Super implements Interface {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:7:20: Context: The parameter 'n' of the method 'Super.method2' has type 'num', which does not match the corresponding type, 'String', in the overridden method, 'Class.method2'.
+// Change to a supertype of 'String', or, for a covariant parameter, a subtype.
+//   void method2(num n) {}
+//                    ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_method.dart:24:8: Context: This is the overridden method ('method2').
+//   void method2(String i);
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method method1(core::num n) → void {}
+  method method2(core::num n) → void {}
+  method method3(core::num n) → void {}
+  method method4(covariant core::num i) → void {}
+  method method5(covariant core::int i) → void {}
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  method method1(covariant core::int i) → void {}
+  method method2(covariant core::int i) → void {}
+  method method4(core::int i) → void {}
+  method method5(core::int i) → void {}
+}
+class Class extends self::Super implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  forwarding-stub forwarding-semi-stub method method1(covariant core::int i) → void
+    return super.{self::Super::method1}(i);
+  forwarding-stub forwarding-semi-stub method method2(covariant core::String i) → void
+    return super.{self::Super::method2}(i);
+  abstract method method3(core::int i) → void;
+  abstract method method4(covariant core::int i) → void;
+  abstract method method5(covariant core::num n) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart
new file mode 100644
index 0000000..7c71384
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.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.
+
+class Super {
+  void set setter1(num n) {}
+  void set setter2(num n) {}
+  void set setter3(num n) {}
+
+  void set setter4(covariant num i) {}
+  void set setter5(covariant int i) {}
+}
+
+class Interface {
+  void set setter1(covariant int i) {}
+  void set setter2(covariant int i) {}
+
+  void set setter4(int i) {}
+  void set setter5(int i) {}
+}
+
+class Class extends Super implements Interface {
+  void set setter1(int i);
+  void set setter2(String i);
+  void set setter3(int i);
+
+  void set setter4(int i);
+  void set setter5(num n);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..c7fba79
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.textual_outline.expect
@@ -0,0 +1,24 @@
+class Super {
+  void set setter1(num n) {}
+  void set setter2(num n) {}
+  void set setter3(num n) {}
+  void set setter4(covariant num i) {}
+  void set setter5(covariant int i) {}
+}
+
+class Interface {
+  void set setter1(covariant int i) {}
+  void set setter2(covariant int i) {}
+  void set setter4(int i) {}
+  void set setter5(int i) {}
+}
+
+class Class extends Super implements Interface {
+  void set setter1(int i);
+  void set setter2(String i);
+  void set setter3(int i);
+  void set setter4(int i);
+  void set setter5(num n);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..67cef1c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class Class extends Super implements Interface {
+  void set setter1(int i);
+  void set setter2(String i);
+  void set setter3(int i);
+  void set setter4(int i);
+  void set setter5(num n);
+}
+
+class Interface {
+  void set setter1(covariant int i) {}
+  void set setter2(covariant int i) {}
+  void set setter4(int i) {}
+  void set setter5(int i) {}
+}
+
+class Super {
+  void set setter1(num n) {}
+  void set setter2(num n) {}
+  void set setter3(num n) {}
+  void set setter4(covariant num i) {}
+  void set setter5(covariant int i) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.weak.expect
new file mode 100644
index 0000000..a95406c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart.weak.expect
@@ -0,0 +1,74 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:24:27: Error: The parameter 'i' of the method 'Class.setter2' has type 'String', which does not match the corresponding type, 'num', in the overridden method, 'Super.setter2'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   void set setter2(String i);
+//                           ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:7:12: Context: This is the overridden method ('setter2').
+//   void set setter2(num n) {}
+//            ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:24:27: Error: The parameter 'i' of the method 'Class.setter2' has type 'String', which does not match the corresponding type, 'int', in the overridden method, 'Interface.setter2'.
+// Change to a supertype of 'int', or, for a covariant parameter, a subtype.
+//   void set setter2(String i);
+//                           ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:16:12: Context: This is the overridden method ('setter2').
+//   void set setter2(covariant int i) {}
+//            ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:25:24: Error: The parameter 'i' of the method 'Class.setter3' has type 'int', which does not match the corresponding type, 'num', in the overridden method, 'Super.setter3'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   void set setter3(int i);
+//                        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:8:12: Context: This is the overridden method ('setter3').
+//   void set setter3(num n) {}
+//            ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:22:7: Error: The implementation of 'setter2' in the non-abstract class 'Class' does not conform to its interface.
+// class Class extends Super implements Interface {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:7:24: Context: The parameter 'n' of the method 'Super.setter2' has type 'num', which does not match the corresponding type, 'String', in the overridden method, 'Class.setter2'.
+// Change to a supertype of 'String', or, for a covariant parameter, a subtype.
+//   void set setter2(num n) {}
+//                        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_semi_stub_setter.dart:24:12: Context: This is the overridden method ('setter2').
+//   void set setter2(String i);
+//            ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  set setter1(core::num n) → void {}
+  set setter2(core::num n) → void {}
+  set setter3(core::num n) → void {}
+  set setter4(covariant core::num i) → void {}
+  set setter5(covariant core::int i) → void {}
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  set setter1(covariant core::int i) → void {}
+  set setter2(covariant core::int i) → void {}
+  set setter4(core::int i) → void {}
+  set setter5(core::int i) → void {}
+}
+class Class extends self::Super implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  forwarding-stub forwarding-semi-stub set setter1(covariant core::int i) → void
+    return super.{self::Super::setter1} = i;
+  forwarding-stub forwarding-semi-stub set setter2(covariant core::String i) → void
+    return super.{self::Super::setter2} = i;
+  abstract set setter3(core::int i) → void;
+  abstract set setter4(covariant core::int i) → void;
+  abstract set setter5(covariant core::num n) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart
new file mode 100644
index 0000000..3684037
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.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.
+
+// Derived from language/mixin/forwarding_stub_call_test
+
+// Test for calling a method for which a forwarding super stub has been
+// inserted.
+
+class Super<T> {
+  void method(T t) {}
+}
+
+class Mixin {
+  void method(int t) {}
+}
+
+// A forwarding super stub is inserted:
+//
+//     void method(/*generic-covariant-impl*/ int t) => super.method(t);
+//
+class Class = Super<int> with Mixin;
+
+class Subclass extends Class {
+  void test() {
+    // Test that we can call the method.
+    super.method(0);
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.textual_outline.expect
new file mode 100644
index 0000000..3b2f2c2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+class Super<T> {
+  void method(T t) {}
+}
+
+class Mixin {
+  void method(int t) {}
+}
+
+class Class = Super<int> with Mixin;
+
+class Subclass extends Class {
+  void test() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..547b86a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class Class = Super<int> with Mixin;
+
+class Mixin {
+  void method(int t) {}
+}
+
+class Subclass extends Class {
+  void test() {}
+}
+
+class Super<T> {
+  void method(T t) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.weak.expect
new file mode 100644
index 0000000..bb5cf3f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.weak.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Super<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Super<self::Super::T%>
+    : super core::Object::•()
+    ;
+  method method(generic-covariant-impl self::Super::T% t) → void {}
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method method(core::int t) → void {}
+}
+class Class = self::Super<core::int> with self::Mixin {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  forwarding-stub method method(generic-covariant-impl core::int t) → void
+    return super.{self::Mixin::method}(t);
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method test() → void {
+    super.{self::Class::method}(0);
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.weak.transformed.expect
new file mode 100644
index 0000000..88c7f59
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stub_call.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Super<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Super<self::Super::T%>
+    : super core::Object::•()
+    ;
+  method method(generic-covariant-impl self::Super::T% t) → void {}
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method method(core::int t) → void {}
+}
+class Class extends self::Super<core::int> implements self::Mixin /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  method method(generic-covariant-impl core::int t) → void {}
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method test() → void {
+    super.{self::Class::method}(0);
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart
new file mode 100644
index 0000000..91875b6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.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.
+
+abstract class Super {
+  covariant int extendedConcreteCovariantField = 0;
+
+  abstract covariant int extendedAbstractCovariantField;
+
+  covariant int extendedConcreteCovariantImplementedField = 0;
+
+  abstract covariant int extendedAbstractCovariantImplementedField;
+
+  int extendedConcreteImplementedCovariantField = 0;
+
+  abstract int extendedAbstractImplementedCovariantField;
+}
+
+class Interface1 {
+  int extendedConcreteCovariantImplementedField = 0;
+
+  int extendedAbstractCovariantImplementedField = 0;
+
+  covariant int extendedConcreteImplementedCovariantField = 0;
+
+  covariant int extendedAbstractImplementedCovariantField = 0;
+
+  covariant int implementsMultipleCovariantField1 = 0;
+
+  int implementsMultipleCovariantField2 = 0;
+}
+
+class Interface2 {
+  int implementsMultipleCovariantField1 = 0;
+
+  covariant int implementsMultipleCovariantField2 = 0;
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.textual_outline.expect
new file mode 100644
index 0000000..b2530ea
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.textual_outline.expect
@@ -0,0 +1,30 @@
+abstract class Super {
+  covariant int extendedConcreteCovariantField = 0;
+  abstract covariant int extendedAbstractCovariantField;
+  covariant int extendedConcreteCovariantImplementedField = 0;
+  abstract covariant int extendedAbstractCovariantImplementedField;
+  int extendedConcreteImplementedCovariantField = 0;
+  abstract int extendedAbstractImplementedCovariantField;
+}
+
+class Interface1 {
+  int extendedConcreteCovariantImplementedField = 0;
+  int extendedAbstractCovariantImplementedField = 0;
+  covariant int extendedConcreteImplementedCovariantField = 0;
+  covariant int extendedAbstractImplementedCovariantField = 0;
+  covariant int implementsMultipleCovariantField1 = 0;
+  int implementsMultipleCovariantField2 = 0;
+}
+
+class Interface2 {
+  int implementsMultipleCovariantField1 = 0;
+  covariant int implementsMultipleCovariantField2 = 0;
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..954cbe4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,30 @@
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class Super {
+  abstract covariant int extendedAbstractCovariantField;
+  abstract covariant int extendedAbstractCovariantImplementedField;
+  abstract int extendedAbstractImplementedCovariantField;
+  covariant int extendedConcreteCovariantField = 0;
+  covariant int extendedConcreteCovariantImplementedField = 0;
+  int extendedConcreteImplementedCovariantField = 0;
+}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  covariant int extendedAbstractImplementedCovariantField = 0;
+  covariant int extendedConcreteImplementedCovariantField = 0;
+  covariant int implementsMultipleCovariantField1 = 0;
+  int extendedAbstractCovariantImplementedField = 0;
+  int extendedConcreteCovariantImplementedField = 0;
+  int implementsMultipleCovariantField2 = 0;
+}
+
+class Interface2 {
+  covariant int implementsMultipleCovariantField2 = 0;
+  int implementsMultipleCovariantField1 = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.weak.expect
new file mode 100644
index 0000000..e9fa156
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.weak.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:41:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedField
+//  - Interface1.extendedAbstractImplementedCovariantField
+//  - Interface1.implementsMultipleCovariantField1
+//  - Interface1.implementsMultipleCovariantField2
+//  - Interface2.implementsMultipleCovariantField1
+//  - Interface2.implementsMultipleCovariantField2
+//  - Super.extendedAbstractCovariantField
+//  - Super.extendedAbstractCovariantField=
+//  - Super.extendedAbstractCovariantImplementedField
+//  - Super.extendedAbstractCovariantImplementedField=
+//  - Super.extendedAbstractImplementedCovariantField
+//  - Super.extendedAbstractImplementedCovariantField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:22:7: Context: 'Interface1.extendedAbstractCovariantImplementedField' is defined here.
+//   int extendedAbstractCovariantImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:26:17: Context: 'Interface1.extendedAbstractImplementedCovariantField' is defined here.
+//   covariant int extendedAbstractImplementedCovariantField = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:28:17: Context: 'Interface1.implementsMultipleCovariantField1' is defined here.
+//   covariant int implementsMultipleCovariantField1 = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:30:7: Context: 'Interface1.implementsMultipleCovariantField2' is defined here.
+//   int implementsMultipleCovariantField2 = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:34:7: Context: 'Interface2.implementsMultipleCovariantField1' is defined here.
+//   int implementsMultipleCovariantField1 = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:36:17: Context: 'Interface2.implementsMultipleCovariantField2' is defined here.
+//   covariant int implementsMultipleCovariantField2 = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:8:26: Context: 'Super.extendedAbstractCovariantField' is defined here.
+//   abstract covariant int extendedAbstractCovariantField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:8:26: Context: 'Super.extendedAbstractCovariantField=' is defined here.
+//   abstract covariant int extendedAbstractCovariantField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:12:26: Context: 'Super.extendedAbstractCovariantImplementedField' is defined here.
+//   abstract covariant int extendedAbstractCovariantImplementedField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:12:26: Context: 'Super.extendedAbstractCovariantImplementedField=' is defined here.
+//   abstract covariant int extendedAbstractCovariantImplementedField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:16:16: Context: 'Super.extendedAbstractImplementedCovariantField' is defined here.
+//   abstract int extendedAbstractImplementedCovariantField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:16:16: Context: 'Super.extendedAbstractImplementedCovariantField=' is defined here.
+//   abstract int extendedAbstractImplementedCovariantField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:43:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedField
+//  - Interface1.extendedAbstractImplementedCovariantField
+//  - Interface1.implementsMultipleCovariantField1
+//  - Interface1.implementsMultipleCovariantField2
+//  - Interface2.implementsMultipleCovariantField1
+//  - Interface2.implementsMultipleCovariantField2
+//  - Super.extendedAbstractCovariantField
+//  - Super.extendedAbstractCovariantField=
+//  - Super.extendedAbstractCovariantImplementedField
+//  - Super.extendedAbstractCovariantImplementedField=
+//  - Super.extendedAbstractImplementedCovariantField
+//  - Super.extendedAbstractImplementedCovariantField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:22:7: Context: 'Interface1.extendedAbstractCovariantImplementedField' is defined here.
+//   int extendedAbstractCovariantImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:26:17: Context: 'Interface1.extendedAbstractImplementedCovariantField' is defined here.
+//   covariant int extendedAbstractImplementedCovariantField = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:28:17: Context: 'Interface1.implementsMultipleCovariantField1' is defined here.
+//   covariant int implementsMultipleCovariantField1 = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:30:7: Context: 'Interface1.implementsMultipleCovariantField2' is defined here.
+//   int implementsMultipleCovariantField2 = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:34:7: Context: 'Interface2.implementsMultipleCovariantField1' is defined here.
+//   int implementsMultipleCovariantField1 = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:36:17: Context: 'Interface2.implementsMultipleCovariantField2' is defined here.
+//   covariant int implementsMultipleCovariantField2 = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:8:26: Context: 'Super.extendedAbstractCovariantField' is defined here.
+//   abstract covariant int extendedAbstractCovariantField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:8:26: Context: 'Super.extendedAbstractCovariantField=' is defined here.
+//   abstract covariant int extendedAbstractCovariantField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:12:26: Context: 'Super.extendedAbstractCovariantImplementedField' is defined here.
+//   abstract covariant int extendedAbstractCovariantImplementedField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:12:26: Context: 'Super.extendedAbstractCovariantImplementedField=' is defined here.
+//   abstract covariant int extendedAbstractCovariantImplementedField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:16:16: Context: 'Super.extendedAbstractImplementedCovariantField' is defined here.
+//   abstract int extendedAbstractImplementedCovariantField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:16:16: Context: 'Super.extendedAbstractImplementedCovariantField=' is defined here.
+//   abstract int extendedAbstractImplementedCovariantField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  covariant field core::int extendedConcreteCovariantField = 0;
+  covariant field core::int extendedConcreteCovariantImplementedField = 0;
+  field core::int extendedConcreteImplementedCovariantField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractCovariantField() → core::int;
+  abstract set extendedAbstractCovariantField(covariant core::int #externalFieldValue) → void;
+  abstract get extendedAbstractCovariantImplementedField() → core::int;
+  abstract set extendedAbstractCovariantImplementedField(covariant core::int #externalFieldValue) → void;
+  abstract get extendedAbstractImplementedCovariantField() → core::int;
+  abstract set extendedAbstractImplementedCovariantField(core::int #externalFieldValue) → void;
+}
+class Interface1 extends core::Object {
+  field core::int extendedConcreteCovariantImplementedField = 0;
+  field core::int extendedAbstractCovariantImplementedField = 0;
+  covariant field core::int extendedConcreteImplementedCovariantField = 0;
+  covariant field core::int extendedAbstractImplementedCovariantField = 0;
+  covariant field core::int implementsMultipleCovariantField1 = 0;
+  field core::int implementsMultipleCovariantField2 = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  field core::int implementsMultipleCovariantField1 = 0;
+  covariant field core::int implementsMultipleCovariantField2 = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+  forwarding-stub set extendedConcreteImplementedCovariantField(covariant core::int value) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantField} = value;
+  abstract forwarding-stub set extendedAbstractImplementedCovariantField(covariant core::int #externalFieldValue) → void;
+  abstract forwarding-stub set implementsMultipleCovariantField2(covariant core::int value) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+  forwarding-stub set extendedConcreteImplementedCovariantField(covariant core::int value) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantField} = value;
+  abstract forwarding-stub set extendedAbstractImplementedCovariantField(covariant core::int #externalFieldValue) → void;
+  abstract forwarding-stub set implementsMultipleCovariantField2(covariant core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..e9fa156
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart.weak.transformed.expect
@@ -0,0 +1,179 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:41:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedField
+//  - Interface1.extendedAbstractImplementedCovariantField
+//  - Interface1.implementsMultipleCovariantField1
+//  - Interface1.implementsMultipleCovariantField2
+//  - Interface2.implementsMultipleCovariantField1
+//  - Interface2.implementsMultipleCovariantField2
+//  - Super.extendedAbstractCovariantField
+//  - Super.extendedAbstractCovariantField=
+//  - Super.extendedAbstractCovariantImplementedField
+//  - Super.extendedAbstractCovariantImplementedField=
+//  - Super.extendedAbstractImplementedCovariantField
+//  - Super.extendedAbstractImplementedCovariantField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:22:7: Context: 'Interface1.extendedAbstractCovariantImplementedField' is defined here.
+//   int extendedAbstractCovariantImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:26:17: Context: 'Interface1.extendedAbstractImplementedCovariantField' is defined here.
+//   covariant int extendedAbstractImplementedCovariantField = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:28:17: Context: 'Interface1.implementsMultipleCovariantField1' is defined here.
+//   covariant int implementsMultipleCovariantField1 = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:30:7: Context: 'Interface1.implementsMultipleCovariantField2' is defined here.
+//   int implementsMultipleCovariantField2 = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:34:7: Context: 'Interface2.implementsMultipleCovariantField1' is defined here.
+//   int implementsMultipleCovariantField1 = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:36:17: Context: 'Interface2.implementsMultipleCovariantField2' is defined here.
+//   covariant int implementsMultipleCovariantField2 = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:8:26: Context: 'Super.extendedAbstractCovariantField' is defined here.
+//   abstract covariant int extendedAbstractCovariantField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:8:26: Context: 'Super.extendedAbstractCovariantField=' is defined here.
+//   abstract covariant int extendedAbstractCovariantField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:12:26: Context: 'Super.extendedAbstractCovariantImplementedField' is defined here.
+//   abstract covariant int extendedAbstractCovariantImplementedField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:12:26: Context: 'Super.extendedAbstractCovariantImplementedField=' is defined here.
+//   abstract covariant int extendedAbstractCovariantImplementedField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:16:16: Context: 'Super.extendedAbstractImplementedCovariantField' is defined here.
+//   abstract int extendedAbstractImplementedCovariantField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:16:16: Context: 'Super.extendedAbstractImplementedCovariantField=' is defined here.
+//   abstract int extendedAbstractImplementedCovariantField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:43:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedField
+//  - Interface1.extendedAbstractImplementedCovariantField
+//  - Interface1.implementsMultipleCovariantField1
+//  - Interface1.implementsMultipleCovariantField2
+//  - Interface2.implementsMultipleCovariantField1
+//  - Interface2.implementsMultipleCovariantField2
+//  - Super.extendedAbstractCovariantField
+//  - Super.extendedAbstractCovariantField=
+//  - Super.extendedAbstractCovariantImplementedField
+//  - Super.extendedAbstractCovariantImplementedField=
+//  - Super.extendedAbstractImplementedCovariantField
+//  - Super.extendedAbstractImplementedCovariantField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:22:7: Context: 'Interface1.extendedAbstractCovariantImplementedField' is defined here.
+//   int extendedAbstractCovariantImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:26:17: Context: 'Interface1.extendedAbstractImplementedCovariantField' is defined here.
+//   covariant int extendedAbstractImplementedCovariantField = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:28:17: Context: 'Interface1.implementsMultipleCovariantField1' is defined here.
+//   covariant int implementsMultipleCovariantField1 = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:30:7: Context: 'Interface1.implementsMultipleCovariantField2' is defined here.
+//   int implementsMultipleCovariantField2 = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:34:7: Context: 'Interface2.implementsMultipleCovariantField1' is defined here.
+//   int implementsMultipleCovariantField1 = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:36:17: Context: 'Interface2.implementsMultipleCovariantField2' is defined here.
+//   covariant int implementsMultipleCovariantField2 = 0;
+//                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:8:26: Context: 'Super.extendedAbstractCovariantField' is defined here.
+//   abstract covariant int extendedAbstractCovariantField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:8:26: Context: 'Super.extendedAbstractCovariantField=' is defined here.
+//   abstract covariant int extendedAbstractCovariantField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:12:26: Context: 'Super.extendedAbstractCovariantImplementedField' is defined here.
+//   abstract covariant int extendedAbstractCovariantImplementedField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:12:26: Context: 'Super.extendedAbstractCovariantImplementedField=' is defined here.
+//   abstract covariant int extendedAbstractCovariantImplementedField;
+//                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:16:16: Context: 'Super.extendedAbstractImplementedCovariantField' is defined here.
+//   abstract int extendedAbstractImplementedCovariantField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_field.dart:16:16: Context: 'Super.extendedAbstractImplementedCovariantField=' is defined here.
+//   abstract int extendedAbstractImplementedCovariantField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  covariant field core::int extendedConcreteCovariantField = 0;
+  covariant field core::int extendedConcreteCovariantImplementedField = 0;
+  field core::int extendedConcreteImplementedCovariantField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractCovariantField() → core::int;
+  abstract set extendedAbstractCovariantField(covariant core::int #externalFieldValue) → void;
+  abstract get extendedAbstractCovariantImplementedField() → core::int;
+  abstract set extendedAbstractCovariantImplementedField(covariant core::int #externalFieldValue) → void;
+  abstract get extendedAbstractImplementedCovariantField() → core::int;
+  abstract set extendedAbstractImplementedCovariantField(core::int #externalFieldValue) → void;
+}
+class Interface1 extends core::Object {
+  field core::int extendedConcreteCovariantImplementedField = 0;
+  field core::int extendedAbstractCovariantImplementedField = 0;
+  covariant field core::int extendedConcreteImplementedCovariantField = 0;
+  covariant field core::int extendedAbstractImplementedCovariantField = 0;
+  covariant field core::int implementsMultipleCovariantField1 = 0;
+  field core::int implementsMultipleCovariantField2 = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  field core::int implementsMultipleCovariantField1 = 0;
+  covariant field core::int implementsMultipleCovariantField2 = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+  forwarding-stub set extendedConcreteImplementedCovariantField(covariant core::int value) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantField} = value;
+  abstract forwarding-stub set extendedAbstractImplementedCovariantField(covariant core::int #externalFieldValue) → void;
+  abstract forwarding-stub set implementsMultipleCovariantField2(covariant core::int value) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+  forwarding-stub set extendedConcreteImplementedCovariantField(covariant core::int value) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantField} = value;
+  abstract forwarding-stub set extendedAbstractImplementedCovariantField(covariant core::int #externalFieldValue) → void;
+  abstract forwarding-stub set implementsMultipleCovariantField2(covariant core::int value) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart
new file mode 100644
index 0000000..354068c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.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.
+
+abstract class Super {
+  void extendedConcreteCovariantMethod(covariant int i) {}
+
+  void extendedAbstractCovariantMethod(covariant int i);
+
+  void extendedConcreteCovariantImplementedMethod(covariant int i) {}
+
+  void extendedAbstractCovariantImplementedMethod(covariant int i);
+
+  void extendedConcreteImplementedCovariantMethod(int i) {}
+
+  void extendedAbstractImplementedCovariantMethod(int i);
+}
+
+class Interface1 {
+  void extendedConcreteCovariantImplementedMethod(int i) {}
+
+  void extendedAbstractCovariantImplementedMethod(int i) {}
+
+  void extendedConcreteImplementedCovariantMethod(covariant int i) {}
+
+  void extendedAbstractImplementedCovariantMethod(covariant int i) {}
+
+  void implementsMultipleCovariantMethod1(covariant int i) {}
+
+  void implementsMultipleCovariantMethod2(int i) {}
+}
+
+class Interface2 {
+  void implementsMultipleCovariantMethod1(int i) {}
+
+  void implementsMultipleCovariantMethod2(covariant int i) {}
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.textual_outline.expect
new file mode 100644
index 0000000..fbd3e7e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.textual_outline.expect
@@ -0,0 +1,30 @@
+abstract class Super {
+  void extendedConcreteCovariantMethod(covariant int i) {}
+  void extendedAbstractCovariantMethod(covariant int i);
+  void extendedConcreteCovariantImplementedMethod(covariant int i) {}
+  void extendedAbstractCovariantImplementedMethod(covariant int i);
+  void extendedConcreteImplementedCovariantMethod(int i) {}
+  void extendedAbstractImplementedCovariantMethod(int i);
+}
+
+class Interface1 {
+  void extendedConcreteCovariantImplementedMethod(int i) {}
+  void extendedAbstractCovariantImplementedMethod(int i) {}
+  void extendedConcreteImplementedCovariantMethod(covariant int i) {}
+  void extendedAbstractImplementedCovariantMethod(covariant int i) {}
+  void implementsMultipleCovariantMethod1(covariant int i) {}
+  void implementsMultipleCovariantMethod2(int i) {}
+}
+
+class Interface2 {
+  void implementsMultipleCovariantMethod1(int i) {}
+  void implementsMultipleCovariantMethod2(covariant int i) {}
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..008b02c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,30 @@
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class Super {
+  void extendedAbstractCovariantImplementedMethod(covariant int i);
+  void extendedAbstractCovariantMethod(covariant int i);
+  void extendedAbstractImplementedCovariantMethod(int i);
+  void extendedConcreteCovariantImplementedMethod(covariant int i) {}
+  void extendedConcreteCovariantMethod(covariant int i) {}
+  void extendedConcreteImplementedCovariantMethod(int i) {}
+}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  void extendedAbstractCovariantImplementedMethod(int i) {}
+  void extendedAbstractImplementedCovariantMethod(covariant int i) {}
+  void extendedConcreteCovariantImplementedMethod(int i) {}
+  void extendedConcreteImplementedCovariantMethod(covariant int i) {}
+  void implementsMultipleCovariantMethod1(covariant int i) {}
+  void implementsMultipleCovariantMethod2(int i) {}
+}
+
+class Interface2 {
+  void implementsMultipleCovariantMethod1(int i) {}
+  void implementsMultipleCovariantMethod2(covariant int i) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.weak.expect
new file mode 100644
index 0000000..e15c8ba
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.weak.expect
@@ -0,0 +1,152 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:41:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedMethod
+//  - Interface1.extendedAbstractImplementedCovariantMethod
+//  - Interface1.implementsMultipleCovariantMethod1
+//  - Interface1.implementsMultipleCovariantMethod2
+//  - Interface2.implementsMultipleCovariantMethod1
+//  - Interface2.implementsMultipleCovariantMethod2
+//  - Super.extendedAbstractCovariantImplementedMethod
+//  - Super.extendedAbstractCovariantMethod
+//  - Super.extendedAbstractImplementedCovariantMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:22:8: Context: 'Interface1.extendedAbstractCovariantImplementedMethod' is defined here.
+//   void extendedAbstractCovariantImplementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:26:8: Context: 'Interface1.extendedAbstractImplementedCovariantMethod' is defined here.
+//   void extendedAbstractImplementedCovariantMethod(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:28:8: Context: 'Interface1.implementsMultipleCovariantMethod1' is defined here.
+//   void implementsMultipleCovariantMethod1(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:30:8: Context: 'Interface1.implementsMultipleCovariantMethod2' is defined here.
+//   void implementsMultipleCovariantMethod2(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:34:8: Context: 'Interface2.implementsMultipleCovariantMethod1' is defined here.
+//   void implementsMultipleCovariantMethod1(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:36:8: Context: 'Interface2.implementsMultipleCovariantMethod2' is defined here.
+//   void implementsMultipleCovariantMethod2(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:12:8: Context: 'Super.extendedAbstractCovariantImplementedMethod' is defined here.
+//   void extendedAbstractCovariantImplementedMethod(covariant int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:8:8: Context: 'Super.extendedAbstractCovariantMethod' is defined here.
+//   void extendedAbstractCovariantMethod(covariant int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:16:8: Context: 'Super.extendedAbstractImplementedCovariantMethod' is defined here.
+//   void extendedAbstractImplementedCovariantMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:43:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedMethod
+//  - Interface1.extendedAbstractImplementedCovariantMethod
+//  - Interface1.implementsMultipleCovariantMethod1
+//  - Interface1.implementsMultipleCovariantMethod2
+//  - Interface2.implementsMultipleCovariantMethod1
+//  - Interface2.implementsMultipleCovariantMethod2
+//  - Super.extendedAbstractCovariantImplementedMethod
+//  - Super.extendedAbstractCovariantMethod
+//  - Super.extendedAbstractImplementedCovariantMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:22:8: Context: 'Interface1.extendedAbstractCovariantImplementedMethod' is defined here.
+//   void extendedAbstractCovariantImplementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:26:8: Context: 'Interface1.extendedAbstractImplementedCovariantMethod' is defined here.
+//   void extendedAbstractImplementedCovariantMethod(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:28:8: Context: 'Interface1.implementsMultipleCovariantMethod1' is defined here.
+//   void implementsMultipleCovariantMethod1(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:30:8: Context: 'Interface1.implementsMultipleCovariantMethod2' is defined here.
+//   void implementsMultipleCovariantMethod2(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:34:8: Context: 'Interface2.implementsMultipleCovariantMethod1' is defined here.
+//   void implementsMultipleCovariantMethod1(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:36:8: Context: 'Interface2.implementsMultipleCovariantMethod2' is defined here.
+//   void implementsMultipleCovariantMethod2(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:12:8: Context: 'Super.extendedAbstractCovariantImplementedMethod' is defined here.
+//   void extendedAbstractCovariantImplementedMethod(covariant int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:8:8: Context: 'Super.extendedAbstractCovariantMethod' is defined here.
+//   void extendedAbstractCovariantMethod(covariant int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:16:8: Context: 'Super.extendedAbstractImplementedCovariantMethod' is defined here.
+//   void extendedAbstractImplementedCovariantMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteCovariantMethod(covariant core::int i) → void {}
+  abstract method extendedAbstractCovariantMethod(covariant core::int i) → void;
+  method extendedConcreteCovariantImplementedMethod(covariant core::int i) → void {}
+  abstract method extendedAbstractCovariantImplementedMethod(covariant core::int i) → void;
+  method extendedConcreteImplementedCovariantMethod(core::int i) → void {}
+  abstract method extendedAbstractImplementedCovariantMethod(core::int i) → void;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method extendedConcreteCovariantImplementedMethod(core::int i) → void {}
+  method extendedAbstractCovariantImplementedMethod(core::int i) → void {}
+  method extendedConcreteImplementedCovariantMethod(covariant core::int i) → void {}
+  method extendedAbstractImplementedCovariantMethod(covariant core::int i) → void {}
+  method implementsMultipleCovariantMethod1(covariant core::int i) → void {}
+  method implementsMultipleCovariantMethod2(core::int i) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method implementsMultipleCovariantMethod1(core::int i) → void {}
+  method implementsMultipleCovariantMethod2(covariant core::int i) → void {}
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+  forwarding-stub method extendedConcreteImplementedCovariantMethod(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantMethod}(i);
+  abstract forwarding-stub method extendedAbstractImplementedCovariantMethod(covariant core::int i) → void;
+  abstract forwarding-stub method implementsMultipleCovariantMethod2(covariant core::int i) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+  forwarding-stub method extendedConcreteImplementedCovariantMethod(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantMethod}(i);
+  abstract forwarding-stub method extendedAbstractImplementedCovariantMethod(covariant core::int i) → void;
+  abstract forwarding-stub method implementsMultipleCovariantMethod2(covariant core::int i) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..e15c8ba
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart.weak.transformed.expect
@@ -0,0 +1,152 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:41:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedMethod
+//  - Interface1.extendedAbstractImplementedCovariantMethod
+//  - Interface1.implementsMultipleCovariantMethod1
+//  - Interface1.implementsMultipleCovariantMethod2
+//  - Interface2.implementsMultipleCovariantMethod1
+//  - Interface2.implementsMultipleCovariantMethod2
+//  - Super.extendedAbstractCovariantImplementedMethod
+//  - Super.extendedAbstractCovariantMethod
+//  - Super.extendedAbstractImplementedCovariantMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:22:8: Context: 'Interface1.extendedAbstractCovariantImplementedMethod' is defined here.
+//   void extendedAbstractCovariantImplementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:26:8: Context: 'Interface1.extendedAbstractImplementedCovariantMethod' is defined here.
+//   void extendedAbstractImplementedCovariantMethod(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:28:8: Context: 'Interface1.implementsMultipleCovariantMethod1' is defined here.
+//   void implementsMultipleCovariantMethod1(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:30:8: Context: 'Interface1.implementsMultipleCovariantMethod2' is defined here.
+//   void implementsMultipleCovariantMethod2(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:34:8: Context: 'Interface2.implementsMultipleCovariantMethod1' is defined here.
+//   void implementsMultipleCovariantMethod1(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:36:8: Context: 'Interface2.implementsMultipleCovariantMethod2' is defined here.
+//   void implementsMultipleCovariantMethod2(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:12:8: Context: 'Super.extendedAbstractCovariantImplementedMethod' is defined here.
+//   void extendedAbstractCovariantImplementedMethod(covariant int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:8:8: Context: 'Super.extendedAbstractCovariantMethod' is defined here.
+//   void extendedAbstractCovariantMethod(covariant int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:16:8: Context: 'Super.extendedAbstractImplementedCovariantMethod' is defined here.
+//   void extendedAbstractImplementedCovariantMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:43:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedMethod
+//  - Interface1.extendedAbstractImplementedCovariantMethod
+//  - Interface1.implementsMultipleCovariantMethod1
+//  - Interface1.implementsMultipleCovariantMethod2
+//  - Interface2.implementsMultipleCovariantMethod1
+//  - Interface2.implementsMultipleCovariantMethod2
+//  - Super.extendedAbstractCovariantImplementedMethod
+//  - Super.extendedAbstractCovariantMethod
+//  - Super.extendedAbstractImplementedCovariantMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:22:8: Context: 'Interface1.extendedAbstractCovariantImplementedMethod' is defined here.
+//   void extendedAbstractCovariantImplementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:26:8: Context: 'Interface1.extendedAbstractImplementedCovariantMethod' is defined here.
+//   void extendedAbstractImplementedCovariantMethod(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:28:8: Context: 'Interface1.implementsMultipleCovariantMethod1' is defined here.
+//   void implementsMultipleCovariantMethod1(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:30:8: Context: 'Interface1.implementsMultipleCovariantMethod2' is defined here.
+//   void implementsMultipleCovariantMethod2(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:34:8: Context: 'Interface2.implementsMultipleCovariantMethod1' is defined here.
+//   void implementsMultipleCovariantMethod1(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:36:8: Context: 'Interface2.implementsMultipleCovariantMethod2' is defined here.
+//   void implementsMultipleCovariantMethod2(covariant int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:12:8: Context: 'Super.extendedAbstractCovariantImplementedMethod' is defined here.
+//   void extendedAbstractCovariantImplementedMethod(covariant int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:8:8: Context: 'Super.extendedAbstractCovariantMethod' is defined here.
+//   void extendedAbstractCovariantMethod(covariant int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_method.dart:16:8: Context: 'Super.extendedAbstractImplementedCovariantMethod' is defined here.
+//   void extendedAbstractImplementedCovariantMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteCovariantMethod(covariant core::int i) → void {}
+  abstract method extendedAbstractCovariantMethod(covariant core::int i) → void;
+  method extendedConcreteCovariantImplementedMethod(covariant core::int i) → void {}
+  abstract method extendedAbstractCovariantImplementedMethod(covariant core::int i) → void;
+  method extendedConcreteImplementedCovariantMethod(core::int i) → void {}
+  abstract method extendedAbstractImplementedCovariantMethod(core::int i) → void;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method extendedConcreteCovariantImplementedMethod(core::int i) → void {}
+  method extendedAbstractCovariantImplementedMethod(core::int i) → void {}
+  method extendedConcreteImplementedCovariantMethod(covariant core::int i) → void {}
+  method extendedAbstractImplementedCovariantMethod(covariant core::int i) → void {}
+  method implementsMultipleCovariantMethod1(covariant core::int i) → void {}
+  method implementsMultipleCovariantMethod2(core::int i) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method implementsMultipleCovariantMethod1(core::int i) → void {}
+  method implementsMultipleCovariantMethod2(covariant core::int i) → void {}
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+  forwarding-stub method extendedConcreteImplementedCovariantMethod(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantMethod}(i);
+  abstract forwarding-stub method extendedAbstractImplementedCovariantMethod(covariant core::int i) → void;
+  abstract forwarding-stub method implementsMultipleCovariantMethod2(covariant core::int i) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+  forwarding-stub method extendedConcreteImplementedCovariantMethod(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantMethod}(i);
+  abstract forwarding-stub method extendedAbstractImplementedCovariantMethod(covariant core::int i) → void;
+  abstract forwarding-stub method implementsMultipleCovariantMethod2(covariant core::int i) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart
new file mode 100644
index 0000000..98f53a5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.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.
+
+abstract class Super {
+  void set extendedConcreteCovariantSetter(covariant int i) {}
+
+  void set extendedAbstractCovariantSetter(covariant int i);
+
+  void set extendedConcreteCovariantImplementedSetter(covariant int i) {}
+
+  void set extendedAbstractCovariantImplementedSetter(covariant int i);
+
+  void set extendedConcreteImplementedCovariantSetter(int i) {}
+
+  void set extendedAbstractImplementedCovariantSetter(int i);
+}
+
+class Interface1 {
+  void set extendedConcreteCovariantImplementedSetter(int i) {}
+
+  void set extendedAbstractCovariantImplementedSetter(int i) {}
+
+  void set extendedConcreteImplementedCovariantSetter(covariant int i) {}
+
+  void set extendedAbstractImplementedCovariantSetter(covariant int i) {}
+
+  void set implementsMultipleCovariantSetter1(covariant int i) {}
+
+  void set implementsMultipleCovariantSetter2(int i) {}
+}
+
+class Interface2 {
+  void set implementsMultipleCovariantSetter1(int i) {}
+
+  void set implementsMultipleCovariantSetter2(covariant int i) {}
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..da91369
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.textual_outline.expect
@@ -0,0 +1,30 @@
+abstract class Super {
+  void set extendedConcreteCovariantSetter(covariant int i) {}
+  void set extendedAbstractCovariantSetter(covariant int i);
+  void set extendedConcreteCovariantImplementedSetter(covariant int i) {}
+  void set extendedAbstractCovariantImplementedSetter(covariant int i);
+  void set extendedConcreteImplementedCovariantSetter(int i) {}
+  void set extendedAbstractImplementedCovariantSetter(int i);
+}
+
+class Interface1 {
+  void set extendedConcreteCovariantImplementedSetter(int i) {}
+  void set extendedAbstractCovariantImplementedSetter(int i) {}
+  void set extendedConcreteImplementedCovariantSetter(covariant int i) {}
+  void set extendedAbstractImplementedCovariantSetter(covariant int i) {}
+  void set implementsMultipleCovariantSetter1(covariant int i) {}
+  void set implementsMultipleCovariantSetter2(int i) {}
+}
+
+class Interface2 {
+  void set implementsMultipleCovariantSetter1(int i) {}
+  void set implementsMultipleCovariantSetter2(covariant int i) {}
+}
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..bb9c98b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,30 @@
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class Super {
+  void set extendedAbstractCovariantImplementedSetter(covariant int i);
+  void set extendedAbstractCovariantSetter(covariant int i);
+  void set extendedAbstractImplementedCovariantSetter(int i);
+  void set extendedConcreteCovariantImplementedSetter(covariant int i) {}
+  void set extendedConcreteCovariantSetter(covariant int i) {}
+  void set extendedConcreteImplementedCovariantSetter(int i) {}
+}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  void set extendedAbstractCovariantImplementedSetter(int i) {}
+  void set extendedAbstractImplementedCovariantSetter(covariant int i) {}
+  void set extendedConcreteCovariantImplementedSetter(int i) {}
+  void set extendedConcreteImplementedCovariantSetter(covariant int i) {}
+  void set implementsMultipleCovariantSetter1(covariant int i) {}
+  void set implementsMultipleCovariantSetter2(int i) {}
+}
+
+class Interface2 {
+  void set implementsMultipleCovariantSetter1(int i) {}
+  void set implementsMultipleCovariantSetter2(covariant int i) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.weak.expect
new file mode 100644
index 0000000..bb95986
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.weak.expect
@@ -0,0 +1,152 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:41:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedSetter=
+//  - Interface1.extendedAbstractImplementedCovariantSetter=
+//  - Interface1.implementsMultipleCovariantSetter1=
+//  - Interface1.implementsMultipleCovariantSetter2=
+//  - Interface2.implementsMultipleCovariantSetter1=
+//  - Interface2.implementsMultipleCovariantSetter2=
+//  - Super.extendedAbstractCovariantImplementedSetter=
+//  - Super.extendedAbstractCovariantSetter=
+//  - Super.extendedAbstractImplementedCovariantSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:22:12: Context: 'Interface1.extendedAbstractCovariantImplementedSetter=' is defined here.
+//   void set extendedAbstractCovariantImplementedSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:26:12: Context: 'Interface1.extendedAbstractImplementedCovariantSetter=' is defined here.
+//   void set extendedAbstractImplementedCovariantSetter(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:28:12: Context: 'Interface1.implementsMultipleCovariantSetter1=' is defined here.
+//   void set implementsMultipleCovariantSetter1(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:30:12: Context: 'Interface1.implementsMultipleCovariantSetter2=' is defined here.
+//   void set implementsMultipleCovariantSetter2(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:34:12: Context: 'Interface2.implementsMultipleCovariantSetter1=' is defined here.
+//   void set implementsMultipleCovariantSetter1(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:36:12: Context: 'Interface2.implementsMultipleCovariantSetter2=' is defined here.
+//   void set implementsMultipleCovariantSetter2(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:12:12: Context: 'Super.extendedAbstractCovariantImplementedSetter=' is defined here.
+//   void set extendedAbstractCovariantImplementedSetter(covariant int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:8:12: Context: 'Super.extendedAbstractCovariantSetter=' is defined here.
+//   void set extendedAbstractCovariantSetter(covariant int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:16:12: Context: 'Super.extendedAbstractImplementedCovariantSetter=' is defined here.
+//   void set extendedAbstractImplementedCovariantSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:43:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedSetter=
+//  - Interface1.extendedAbstractImplementedCovariantSetter=
+//  - Interface1.implementsMultipleCovariantSetter1=
+//  - Interface1.implementsMultipleCovariantSetter2=
+//  - Interface2.implementsMultipleCovariantSetter1=
+//  - Interface2.implementsMultipleCovariantSetter2=
+//  - Super.extendedAbstractCovariantImplementedSetter=
+//  - Super.extendedAbstractCovariantSetter=
+//  - Super.extendedAbstractImplementedCovariantSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:22:12: Context: 'Interface1.extendedAbstractCovariantImplementedSetter=' is defined here.
+//   void set extendedAbstractCovariantImplementedSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:26:12: Context: 'Interface1.extendedAbstractImplementedCovariantSetter=' is defined here.
+//   void set extendedAbstractImplementedCovariantSetter(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:28:12: Context: 'Interface1.implementsMultipleCovariantSetter1=' is defined here.
+//   void set implementsMultipleCovariantSetter1(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:30:12: Context: 'Interface1.implementsMultipleCovariantSetter2=' is defined here.
+//   void set implementsMultipleCovariantSetter2(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:34:12: Context: 'Interface2.implementsMultipleCovariantSetter1=' is defined here.
+//   void set implementsMultipleCovariantSetter1(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:36:12: Context: 'Interface2.implementsMultipleCovariantSetter2=' is defined here.
+//   void set implementsMultipleCovariantSetter2(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:12:12: Context: 'Super.extendedAbstractCovariantImplementedSetter=' is defined here.
+//   void set extendedAbstractCovariantImplementedSetter(covariant int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:8:12: Context: 'Super.extendedAbstractCovariantSetter=' is defined here.
+//   void set extendedAbstractCovariantSetter(covariant int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:16:12: Context: 'Super.extendedAbstractImplementedCovariantSetter=' is defined here.
+//   void set extendedAbstractImplementedCovariantSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  set extendedConcreteCovariantSetter(covariant core::int i) → void {}
+  abstract set extendedAbstractCovariantSetter(covariant core::int i) → void;
+  set extendedConcreteCovariantImplementedSetter(covariant core::int i) → void {}
+  abstract set extendedAbstractCovariantImplementedSetter(covariant core::int i) → void;
+  set extendedConcreteImplementedCovariantSetter(core::int i) → void {}
+  abstract set extendedAbstractImplementedCovariantSetter(core::int i) → void;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  set extendedConcreteCovariantImplementedSetter(core::int i) → void {}
+  set extendedAbstractCovariantImplementedSetter(core::int i) → void {}
+  set extendedConcreteImplementedCovariantSetter(covariant core::int i) → void {}
+  set extendedAbstractImplementedCovariantSetter(covariant core::int i) → void {}
+  set implementsMultipleCovariantSetter1(covariant core::int i) → void {}
+  set implementsMultipleCovariantSetter2(core::int i) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  set implementsMultipleCovariantSetter1(core::int i) → void {}
+  set implementsMultipleCovariantSetter2(covariant core::int i) → void {}
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+  forwarding-stub set extendedConcreteImplementedCovariantSetter(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantSetter} = i;
+  abstract forwarding-stub set extendedAbstractImplementedCovariantSetter(covariant core::int i) → void;
+  abstract forwarding-stub set implementsMultipleCovariantSetter2(covariant core::int i) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+  forwarding-stub set extendedConcreteImplementedCovariantSetter(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantSetter} = i;
+  abstract forwarding-stub set extendedAbstractImplementedCovariantSetter(covariant core::int i) → void;
+  abstract forwarding-stub set implementsMultipleCovariantSetter2(covariant core::int i) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.weak.transformed.expect
new file mode 100644
index 0000000..bb95986
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart.weak.transformed.expect
@@ -0,0 +1,152 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:41:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedSetter=
+//  - Interface1.extendedAbstractImplementedCovariantSetter=
+//  - Interface1.implementsMultipleCovariantSetter1=
+//  - Interface1.implementsMultipleCovariantSetter2=
+//  - Interface2.implementsMultipleCovariantSetter1=
+//  - Interface2.implementsMultipleCovariantSetter2=
+//  - Super.extendedAbstractCovariantImplementedSetter=
+//  - Super.extendedAbstractCovariantSetter=
+//  - Super.extendedAbstractImplementedCovariantSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:22:12: Context: 'Interface1.extendedAbstractCovariantImplementedSetter=' is defined here.
+//   void set extendedAbstractCovariantImplementedSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:26:12: Context: 'Interface1.extendedAbstractImplementedCovariantSetter=' is defined here.
+//   void set extendedAbstractImplementedCovariantSetter(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:28:12: Context: 'Interface1.implementsMultipleCovariantSetter1=' is defined here.
+//   void set implementsMultipleCovariantSetter1(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:30:12: Context: 'Interface1.implementsMultipleCovariantSetter2=' is defined here.
+//   void set implementsMultipleCovariantSetter2(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:34:12: Context: 'Interface2.implementsMultipleCovariantSetter1=' is defined here.
+//   void set implementsMultipleCovariantSetter1(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:36:12: Context: 'Interface2.implementsMultipleCovariantSetter2=' is defined here.
+//   void set implementsMultipleCovariantSetter2(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:12:12: Context: 'Super.extendedAbstractCovariantImplementedSetter=' is defined here.
+//   void set extendedAbstractCovariantImplementedSetter(covariant int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:8:12: Context: 'Super.extendedAbstractCovariantSetter=' is defined here.
+//   void set extendedAbstractCovariantSetter(covariant int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:16:12: Context: 'Super.extendedAbstractImplementedCovariantSetter=' is defined here.
+//   void set extendedAbstractImplementedCovariantSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:43:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractCovariantImplementedSetter=
+//  - Interface1.extendedAbstractImplementedCovariantSetter=
+//  - Interface1.implementsMultipleCovariantSetter1=
+//  - Interface1.implementsMultipleCovariantSetter2=
+//  - Interface2.implementsMultipleCovariantSetter1=
+//  - Interface2.implementsMultipleCovariantSetter2=
+//  - Super.extendedAbstractCovariantImplementedSetter=
+//  - Super.extendedAbstractCovariantSetter=
+//  - Super.extendedAbstractImplementedCovariantSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:22:12: Context: 'Interface1.extendedAbstractCovariantImplementedSetter=' is defined here.
+//   void set extendedAbstractCovariantImplementedSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:26:12: Context: 'Interface1.extendedAbstractImplementedCovariantSetter=' is defined here.
+//   void set extendedAbstractImplementedCovariantSetter(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:28:12: Context: 'Interface1.implementsMultipleCovariantSetter1=' is defined here.
+//   void set implementsMultipleCovariantSetter1(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:30:12: Context: 'Interface1.implementsMultipleCovariantSetter2=' is defined here.
+//   void set implementsMultipleCovariantSetter2(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:34:12: Context: 'Interface2.implementsMultipleCovariantSetter1=' is defined here.
+//   void set implementsMultipleCovariantSetter1(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:36:12: Context: 'Interface2.implementsMultipleCovariantSetter2=' is defined here.
+//   void set implementsMultipleCovariantSetter2(covariant int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:12:12: Context: 'Super.extendedAbstractCovariantImplementedSetter=' is defined here.
+//   void set extendedAbstractCovariantImplementedSetter(covariant int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:8:12: Context: 'Super.extendedAbstractCovariantSetter=' is defined here.
+//   void set extendedAbstractCovariantSetter(covariant int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/forwarding_stubs_setter.dart:16:12: Context: 'Super.extendedAbstractImplementedCovariantSetter=' is defined here.
+//   void set extendedAbstractImplementedCovariantSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  set extendedConcreteCovariantSetter(covariant core::int i) → void {}
+  abstract set extendedAbstractCovariantSetter(covariant core::int i) → void;
+  set extendedConcreteCovariantImplementedSetter(covariant core::int i) → void {}
+  abstract set extendedAbstractCovariantImplementedSetter(covariant core::int i) → void;
+  set extendedConcreteImplementedCovariantSetter(core::int i) → void {}
+  abstract set extendedAbstractImplementedCovariantSetter(core::int i) → void;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  set extendedConcreteCovariantImplementedSetter(core::int i) → void {}
+  set extendedAbstractCovariantImplementedSetter(core::int i) → void {}
+  set extendedConcreteImplementedCovariantSetter(covariant core::int i) → void {}
+  set extendedAbstractImplementedCovariantSetter(covariant core::int i) → void {}
+  set implementsMultipleCovariantSetter1(covariant core::int i) → void {}
+  set implementsMultipleCovariantSetter2(core::int i) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  set implementsMultipleCovariantSetter1(core::int i) → void {}
+  set implementsMultipleCovariantSetter2(covariant core::int i) → void {}
+}
+abstract class AbstractClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super self::Super::•()
+    ;
+  forwarding-stub set extendedConcreteImplementedCovariantSetter(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantSetter} = i;
+  abstract forwarding-stub set extendedAbstractImplementedCovariantSetter(covariant core::int i) → void;
+  abstract forwarding-stub set implementsMultipleCovariantSetter2(covariant core::int i) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends self::Super implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super self::Super::•()
+    ;
+  forwarding-stub set extendedConcreteImplementedCovariantSetter(covariant core::int i) → void
+    return super.{self::Super::extendedConcreteImplementedCovariantSetter} = i;
+  abstract forwarding-stub set extendedAbstractImplementedCovariantSetter(covariant core::int i) → void;
+  abstract forwarding-stub set implementsMultipleCovariantSetter2(covariant core::int i) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart
new file mode 100644
index 0000000..4b6f4da
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart
@@ -0,0 +1,115 @@
+// 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 Super {
+  String get extendedGetterDeclaredField => '';
+  String get extendedGetterMixedInField => '';
+  String get extendedGetterImplementedField => '';
+
+  String get extendedGetterDeclaredSetter => '';
+  String get extendedGetterMixedInSetter => '';
+  String get extendedGetterImplementedSetter => '';
+
+  final String extendedFieldDeclaredSetter = '';
+  final String extendedFieldMixedInSetter = '';
+  final String extendedFieldImplementedSetter = '';
+
+  void set extendedSetterDeclaredField(int value) {}
+  void set extendedSetterMixedInField(int value) {}
+  void set extendedSetterImplementedField(int value) {}
+
+  void set extendedSetterDeclaredGetter(int value) {}
+  void set extendedSetterMixedInGetter(int value) {}
+  void set extendedSetterImplementedGetter(int value) {}
+}
+
+abstract class Mixin {
+  int extendedGetterMixedInField = 0;
+  void set extendedGetterMixedInSetter(int value) {}
+  void set extendedFieldMixedInSetter(int value) {}
+  final String extendedSetterMixedInField = '';
+  String get extendedSetterMixedInGetter => '';
+
+  String get mixedInGetterDeclaredField => '';
+  String get mixedInGetterImplementedField => '';
+
+  String get mixedInGetterDeclaredSetter => '';
+  String get mixedInGetterImplementedSetter => '';
+
+  final String mixedInFieldDeclaredSetter = '';
+  final String mixedInFieldImplementedSetter = '';
+
+  void set mixedInSetterDeclaredField(int value) {}
+  void set mixedInSetterImplementedField(int value) {}
+
+  void set mixedInSetterDeclaredGetter(int value) {}
+  void set mixedInSetterImplementedGetter(int value) {}
+}
+
+abstract class Interface1 {
+  int extendedGetterImplementedField = 0;
+  void set extendedGetterImplementedSetter(int value) {}
+  void set extendedFieldImplementedSetter(int value) {}
+  final String extendedSetterImplementedField = '';
+  String get extendedSetterImplementedGetter => '';
+
+  int mixedInGetterImplementedField = 0;
+  void set mixedInGetterImplementedSetter(int value) {}
+  void set mixedInFieldImplementedSetter(int value) {}
+  final String mixedInSetterImplementedField = '';
+  String get mixedInSetterImplementedGetter => '';
+
+  String get implementedGetterDeclaredField => '';
+  String get implementedGetterImplementedField => '';
+
+  String get implementedGetterDeclaredSetter => '';
+  String get implementedGetterImplementedSetter => '';
+
+  final String implementedFieldDeclaredSetter = '';
+  final String implementedFieldImplementedSetter = '';
+
+  void set implementedSetterDeclaredField(int value) {}
+  void set implementedSetterImplementedField(int value) {}
+
+  void set implementedSetterDeclaredGetter(int value) {}
+  void set implementedSetterImplementedGetter(int value) {}
+}
+
+abstract class Interface2 {
+  int implementedGetterImplementedField = 0;
+  void set implementedGetterImplementedSetter(int value) {}
+  void set implementedFieldImplementedSetter(int value) {}
+  final String implementedSetterImplementedField = '';
+  String get implementedSetterImplementedGetter => '';
+}
+
+abstract class Class extends Super
+    with Mixin
+    implements Interface1, Interface2 {
+  int extendedGetterDeclaredField = 0;
+  void set extendedGetterDeclaredSetter(int value) {}
+  void set extendedFieldDeclaredSetter(int value) {}
+  final String extendedSetterDeclaredField = '';
+  String get extendedSetterDeclaredGetter => '';
+
+  int mixedInGetterDeclaredField = 0;
+  void set mixedInGetterDeclaredSetter(int value) {}
+  void set mixedInFieldDeclaredSetter(int value) {}
+  final String mixedInSetterDeclaredField = '';
+  String get mixedInSetterDeclaredGetter => '';
+
+  int implementedGetterDeclaredField = 0;
+  void set implementedGetterDeclaredSetter(int value) {}
+  void set implementedFieldDeclaredSetter(int value) {}
+  final String implementedSetterDeclaredField = '';
+  String get implementedSetterDeclaredGetter => '';
+
+  String get declaredGetterDeclaredSetter => '';
+  void set declaredGetterDeclaredSetter(int value) {}
+
+  final String declaredFieldDeclaredSetter = '';
+  void set declaredFieldDeclaredSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..c0e7660
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.textual_outline.expect
@@ -0,0 +1,92 @@
+abstract class Super {
+  String get extendedGetterDeclaredField => '';
+  String get extendedGetterMixedInField => '';
+  String get extendedGetterImplementedField => '';
+  String get extendedGetterDeclaredSetter => '';
+  String get extendedGetterMixedInSetter => '';
+  String get extendedGetterImplementedSetter => '';
+  final String extendedFieldDeclaredSetter = '';
+  final String extendedFieldMixedInSetter = '';
+  final String extendedFieldImplementedSetter = '';
+  void set extendedSetterDeclaredField(int value) {}
+  void set extendedSetterMixedInField(int value) {}
+  void set extendedSetterImplementedField(int value) {}
+  void set extendedSetterDeclaredGetter(int value) {}
+  void set extendedSetterMixedInGetter(int value) {}
+  void set extendedSetterImplementedGetter(int value) {}
+}
+
+abstract class Mixin {
+  int extendedGetterMixedInField = 0;
+  void set extendedGetterMixedInSetter(int value) {}
+  void set extendedFieldMixedInSetter(int value) {}
+  final String extendedSetterMixedInField = '';
+  String get extendedSetterMixedInGetter => '';
+  String get mixedInGetterDeclaredField => '';
+  String get mixedInGetterImplementedField => '';
+  String get mixedInGetterDeclaredSetter => '';
+  String get mixedInGetterImplementedSetter => '';
+  final String mixedInFieldDeclaredSetter = '';
+  final String mixedInFieldImplementedSetter = '';
+  void set mixedInSetterDeclaredField(int value) {}
+  void set mixedInSetterImplementedField(int value) {}
+  void set mixedInSetterDeclaredGetter(int value) {}
+  void set mixedInSetterImplementedGetter(int value) {}
+}
+
+abstract class Interface1 {
+  int extendedGetterImplementedField = 0;
+  void set extendedGetterImplementedSetter(int value) {}
+  void set extendedFieldImplementedSetter(int value) {}
+  final String extendedSetterImplementedField = '';
+  String get extendedSetterImplementedGetter => '';
+  int mixedInGetterImplementedField = 0;
+  void set mixedInGetterImplementedSetter(int value) {}
+  void set mixedInFieldImplementedSetter(int value) {}
+  final String mixedInSetterImplementedField = '';
+  String get mixedInSetterImplementedGetter => '';
+  String get implementedGetterDeclaredField => '';
+  String get implementedGetterImplementedField => '';
+  String get implementedGetterDeclaredSetter => '';
+  String get implementedGetterImplementedSetter => '';
+  final String implementedFieldDeclaredSetter = '';
+  final String implementedFieldImplementedSetter = '';
+  void set implementedSetterDeclaredField(int value) {}
+  void set implementedSetterImplementedField(int value) {}
+  void set implementedSetterDeclaredGetter(int value) {}
+  void set implementedSetterImplementedGetter(int value) {}
+}
+
+abstract class Interface2 {
+  int implementedGetterImplementedField = 0;
+  void set implementedGetterImplementedSetter(int value) {}
+  void set implementedFieldImplementedSetter(int value) {}
+  final String implementedSetterImplementedField = '';
+  String get implementedSetterImplementedGetter => '';
+}
+
+abstract class Class extends Super
+    with Mixin
+    implements Interface1, Interface2 {
+  int extendedGetterDeclaredField = 0;
+  void set extendedGetterDeclaredSetter(int value) {}
+  void set extendedFieldDeclaredSetter(int value) {}
+  final String extendedSetterDeclaredField = '';
+  String get extendedSetterDeclaredGetter => '';
+  int mixedInGetterDeclaredField = 0;
+  void set mixedInGetterDeclaredSetter(int value) {}
+  void set mixedInFieldDeclaredSetter(int value) {}
+  final String mixedInSetterDeclaredField = '';
+  String get mixedInSetterDeclaredGetter => '';
+  int implementedGetterDeclaredField = 0;
+  void set implementedGetterDeclaredSetter(int value) {}
+  void set implementedFieldDeclaredSetter(int value) {}
+  final String implementedSetterDeclaredField = '';
+  String get implementedSetterDeclaredGetter => '';
+  String get declaredGetterDeclaredSetter => '';
+  void set declaredGetterDeclaredSetter(int value) {}
+  final String declaredFieldDeclaredSetter = '';
+  void set declaredFieldDeclaredSetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ae0e79d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,92 @@
+abstract class Class extends Super
+    with Mixin
+    implements Interface1, Interface2 {
+  String get declaredGetterDeclaredSetter => '';
+  String get extendedSetterDeclaredGetter => '';
+  String get implementedSetterDeclaredGetter => '';
+  String get mixedInSetterDeclaredGetter => '';
+  final String declaredFieldDeclaredSetter = '';
+  final String extendedSetterDeclaredField = '';
+  final String implementedSetterDeclaredField = '';
+  final String mixedInSetterDeclaredField = '';
+  int extendedGetterDeclaredField = 0;
+  int implementedGetterDeclaredField = 0;
+  int mixedInGetterDeclaredField = 0;
+  void set declaredFieldDeclaredSetter(int value) {}
+  void set declaredGetterDeclaredSetter(int value) {}
+  void set extendedFieldDeclaredSetter(int value) {}
+  void set extendedGetterDeclaredSetter(int value) {}
+  void set implementedFieldDeclaredSetter(int value) {}
+  void set implementedGetterDeclaredSetter(int value) {}
+  void set mixedInFieldDeclaredSetter(int value) {}
+  void set mixedInGetterDeclaredSetter(int value) {}
+}
+
+abstract class Interface1 {
+  String get extendedSetterImplementedGetter => '';
+  String get implementedGetterDeclaredField => '';
+  String get implementedGetterDeclaredSetter => '';
+  String get implementedGetterImplementedField => '';
+  String get implementedGetterImplementedSetter => '';
+  String get mixedInSetterImplementedGetter => '';
+  final String extendedSetterImplementedField = '';
+  final String implementedFieldDeclaredSetter = '';
+  final String implementedFieldImplementedSetter = '';
+  final String mixedInSetterImplementedField = '';
+  int extendedGetterImplementedField = 0;
+  int mixedInGetterImplementedField = 0;
+  void set extendedFieldImplementedSetter(int value) {}
+  void set extendedGetterImplementedSetter(int value) {}
+  void set implementedSetterDeclaredField(int value) {}
+  void set implementedSetterDeclaredGetter(int value) {}
+  void set implementedSetterImplementedField(int value) {}
+  void set implementedSetterImplementedGetter(int value) {}
+  void set mixedInFieldImplementedSetter(int value) {}
+  void set mixedInGetterImplementedSetter(int value) {}
+}
+
+abstract class Interface2 {
+  String get implementedSetterImplementedGetter => '';
+  final String implementedSetterImplementedField = '';
+  int implementedGetterImplementedField = 0;
+  void set implementedFieldImplementedSetter(int value) {}
+  void set implementedGetterImplementedSetter(int value) {}
+}
+
+abstract class Mixin {
+  String get extendedSetterMixedInGetter => '';
+  String get mixedInGetterDeclaredField => '';
+  String get mixedInGetterDeclaredSetter => '';
+  String get mixedInGetterImplementedField => '';
+  String get mixedInGetterImplementedSetter => '';
+  final String extendedSetterMixedInField = '';
+  final String mixedInFieldDeclaredSetter = '';
+  final String mixedInFieldImplementedSetter = '';
+  int extendedGetterMixedInField = 0;
+  void set extendedFieldMixedInSetter(int value) {}
+  void set extendedGetterMixedInSetter(int value) {}
+  void set mixedInSetterDeclaredField(int value) {}
+  void set mixedInSetterDeclaredGetter(int value) {}
+  void set mixedInSetterImplementedField(int value) {}
+  void set mixedInSetterImplementedGetter(int value) {}
+}
+
+abstract class Super {
+  String get extendedGetterDeclaredField => '';
+  String get extendedGetterDeclaredSetter => '';
+  String get extendedGetterImplementedField => '';
+  String get extendedGetterImplementedSetter => '';
+  String get extendedGetterMixedInField => '';
+  String get extendedGetterMixedInSetter => '';
+  final String extendedFieldDeclaredSetter = '';
+  final String extendedFieldImplementedSetter = '';
+  final String extendedFieldMixedInSetter = '';
+  void set extendedSetterDeclaredField(int value) {}
+  void set extendedSetterDeclaredGetter(int value) {}
+  void set extendedSetterImplementedField(int value) {}
+  void set extendedSetterImplementedGetter(int value) {}
+  void set extendedSetterMixedInField(int value) {}
+  void set extendedSetterMixedInGetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.weak.expect
new file mode 100644
index 0000000..894fe23
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart.weak.expect
@@ -0,0 +1,550 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the getter 'Super with Mixin.extendedSetterMixedInField' is not a subtype of the type 'int' of the inherited setter 'Super.extendedSetterMixedInField'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:19:12: Context: This is the declaration of the setter 'Super.extendedSetterMixedInField'.
+//   void set extendedSetterMixedInField(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the getter 'Super with Mixin.extendedSetterMixedInGetter' is not a subtype of the type 'int' of the inherited setter 'Super.extendedSetterMixedInGetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:23:12: Context: This is the declaration of the setter 'Super.extendedSetterMixedInGetter'.
+//   void set extendedSetterMixedInGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super.extendedGetterMixedInSetter' is not a subtype of the type 'int' of the setter 'Super with Mixin.extendedGetterMixedInSetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:11:14: Context: This is the declaration of the getter 'Super.extendedGetterMixedInSetter'.
+//   String get extendedGetterMixedInSetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited field 'Super.extendedFieldMixedInSetter' is not a subtype of the type 'int' of the setter 'Super with Mixin.extendedFieldMixedInSetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:15:16: Context: This is the declaration of the field 'Super.extendedFieldMixedInSetter'.
+//   final String extendedFieldMixedInSetter = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: Applying the mixin 'Mixin' to 'Super' introduces an erroneous override of 'extendedGetterMixedInField'.
+// abstract class Class extends Super
+//                ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:28:7: Context: The return type of the method 'Mixin.extendedGetterMixedInField' is 'int', which does not match the return type, 'String', of the overridden method, 'Super.extendedGetterMixedInField'.
+// Change to a subtype of 'String'.
+//   int extendedGetterMixedInField = 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:7:14: Context: This is the overridden method ('extendedGetterMixedInField').
+//   String get extendedGetterMixedInField => '';
+//              ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:93:16: Error: The type 'String' of the field 'Class.extendedSetterDeclaredField' is not a subtype of the type 'int' of the inherited setter 'Super.extendedSetterDeclaredField'.
+//   final String extendedSetterDeclaredField = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:18:12: Context: This is the declaration of the setter 'Super.extendedSetterDeclaredField'.
+//   void set extendedSetterDeclaredField(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:94:14: Error: The type 'String' of the getter 'Class.extendedSetterDeclaredGetter' is not a subtype of the type 'int' of the inherited setter 'Super.extendedSetterDeclaredGetter'.
+//   String get extendedSetterDeclaredGetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:22:12: Context: This is the declaration of the setter 'Super.extendedSetterDeclaredGetter'.
+//   void set extendedSetterDeclaredGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:99:16: Error: The type 'String' of the field 'Class.mixedInSetterDeclaredField' is not a subtype of the type 'int' of the inherited setter 'Super with Mixin.mixedInSetterDeclaredField'.
+//   final String mixedInSetterDeclaredField = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the setter 'Super with Mixin.mixedInSetterDeclaredField'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:100:14: Error: The type 'String' of the getter 'Class.mixedInSetterDeclaredGetter' is not a subtype of the type 'int' of the inherited setter 'Super with Mixin.mixedInSetterDeclaredGetter'.
+//   String get mixedInSetterDeclaredGetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the setter 'Super with Mixin.mixedInSetterDeclaredGetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:105:16: Error: The type 'String' of the field 'Class.implementedSetterDeclaredField' is not a subtype of the type 'int' of the inherited setter 'Interface1.implementedSetterDeclaredField'.
+//   final String implementedSetterDeclaredField = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:72:12: Context: This is the declaration of the setter 'Interface1.implementedSetterDeclaredField'.
+//   void set implementedSetterDeclaredField(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:106:14: Error: The type 'String' of the getter 'Class.implementedSetterDeclaredGetter' is not a subtype of the type 'int' of the inherited setter 'Interface1.implementedSetterDeclaredGetter'.
+//   String get implementedSetterDeclaredGetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:75:12: Context: This is the declaration of the setter 'Interface1.implementedSetterDeclaredGetter'.
+//   void set implementedSetterDeclaredGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:108:14: Error: The type 'String' of the getter 'Class.declaredGetterDeclaredSetter' is not a subtype of the type 'int' of the setter 'Class.declaredGetterDeclaredSetter'.
+//   String get declaredGetterDeclaredSetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:109:12: Context: This is the declaration of the setter 'Class.declaredGetterDeclaredSetter'.
+//   void set declaredGetterDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:111:16: Error: The type 'String' of the getter 'Class.declaredFieldDeclaredSetter' is not a subtype of the type 'int' of the setter 'Class.declaredFieldDeclaredSetter'.
+//   final String declaredFieldDeclaredSetter = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:112:12: Context: This is the declaration of the setter 'Class.declaredFieldDeclaredSetter'.
+//   void set declaredFieldDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:91:12: Error: The type 'String' of the inherited getter 'Super.extendedGetterDeclaredSetter' is not a subtype of the type 'int' of the setter 'Class.extendedGetterDeclaredSetter'.
+//   void set extendedGetterDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:10:14: Context: This is the declaration of the getter 'Super.extendedGetterDeclaredSetter'.
+//   String get extendedGetterDeclaredSetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:92:12: Error: The type 'String' of the inherited field 'Super.extendedFieldDeclaredSetter' is not a subtype of the type 'int' of the setter 'Class.extendedFieldDeclaredSetter'.
+//   void set extendedFieldDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:14:16: Context: This is the declaration of the field 'Super.extendedFieldDeclaredSetter'.
+//   final String extendedFieldDeclaredSetter = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:97:12: Error: The type 'String' of the inherited getter 'Super with Mixin.mixedInGetterDeclaredSetter' is not a subtype of the type 'int' of the setter 'Class.mixedInGetterDeclaredSetter'.
+//   void set mixedInGetterDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the getter 'Super with Mixin.mixedInGetterDeclaredSetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:98:12: Error: The type 'String' of the inherited getter 'Super with Mixin.mixedInFieldDeclaredSetter' is not a subtype of the type 'int' of the setter 'Class.mixedInFieldDeclaredSetter'.
+//   void set mixedInFieldDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the getter 'Super with Mixin.mixedInFieldDeclaredSetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:103:12: Error: The type 'String' of the inherited getter 'Interface1.implementedGetterDeclaredSetter' is not a subtype of the type 'int' of the setter 'Class.implementedGetterDeclaredSetter'.
+//   void set implementedGetterDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:66:14: Context: This is the declaration of the getter 'Interface1.implementedGetterDeclaredSetter'.
+//   String get implementedGetterDeclaredSetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:104:12: Error: The type 'String' of the inherited field 'Interface1.implementedFieldDeclaredSetter' is not a subtype of the type 'int' of the setter 'Class.implementedFieldDeclaredSetter'.
+//   void set implementedFieldDeclaredSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:69:16: Context: This is the declaration of the field 'Interface1.implementedFieldDeclaredSetter'.
+//   final String implementedFieldDeclaredSetter = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super with Mixin.extendedSetterMixedInField' is not a subtype of the type 'int' of the inherited setter 'Super.extendedSetterMixedInField'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the getter 'Super with Mixin.extendedSetterMixedInField'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:19:12: Context: This is the declaration of the setter 'Super.extendedSetterMixedInField'.
+//   void set extendedSetterMixedInField(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super with Mixin.extendedSetterMixedInGetter' is not a subtype of the type 'int' of the inherited setter 'Super.extendedSetterMixedInGetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the getter 'Super with Mixin.extendedSetterMixedInGetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:23:12: Context: This is the declaration of the setter 'Super.extendedSetterMixedInGetter'.
+//   void set extendedSetterMixedInGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: Class 'Class' inherits multiple members named 'Mixin.mixedInGetterImplementedField' with incompatible signatures.
+// Try adding a declaration of 'Mixin.mixedInGetterImplementedField' to 'Class'.
+// abstract class Class extends Super
+//                ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:35:14: Context: This is one of the overridden members.
+//   String get mixedInGetterImplementedField => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:57:7: Context: This is one of the overridden members.
+//   int mixedInGetterImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super with Mixin.mixedInGetterImplementedField' is not a subtype of the type 'int' of the inherited setter 'Interface1.mixedInGetterImplementedField'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the getter 'Super with Mixin.mixedInGetterImplementedField'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:57:7: Context: This is the declaration of the setter 'Interface1.mixedInGetterImplementedField'.
+//   int mixedInGetterImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super with Mixin.mixedInGetterImplementedSetter' is not a subtype of the type 'int' of the inherited setter 'Interface1.mixedInGetterImplementedSetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the getter 'Super with Mixin.mixedInGetterImplementedSetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:58:12: Context: This is the declaration of the setter 'Interface1.mixedInGetterImplementedSetter'.
+//   void set mixedInGetterImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super with Mixin.mixedInFieldImplementedSetter' is not a subtype of the type 'int' of the inherited setter 'Interface1.mixedInFieldImplementedSetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the getter 'Super with Mixin.mixedInFieldImplementedSetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:59:12: Context: This is the declaration of the setter 'Interface1.mixedInFieldImplementedSetter'.
+//   void set mixedInFieldImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super.extendedGetterMixedInSetter' is not a subtype of the type 'int' of the inherited setter 'Super with Mixin.extendedGetterMixedInSetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:11:14: Context: This is the declaration of the getter 'Super.extendedGetterMixedInSetter'.
+//   String get extendedGetterMixedInSetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the setter 'Super with Mixin.extendedGetterMixedInSetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited field 'Super.extendedFieldMixedInSetter' is not a subtype of the type 'int' of the inherited setter 'Super with Mixin.extendedFieldMixedInSetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:15:16: Context: This is the declaration of the field 'Super.extendedFieldMixedInSetter'.
+//   final String extendedFieldMixedInSetter = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the setter 'Super with Mixin.extendedFieldMixedInSetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: Class 'Class' inherits multiple members named 'extendedGetterImplementedField' with incompatible signatures.
+// Try adding a declaration of 'extendedGetterImplementedField' to 'Class'.
+// abstract class Class extends Super
+//                ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:8:14: Context: This is one of the overridden members.
+//   String get extendedGetterImplementedField => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:51:7: Context: This is one of the overridden members.
+//   int extendedGetterImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super.extendedGetterImplementedField' is not a subtype of the type 'int' of the inherited setter 'Interface1.extendedGetterImplementedField'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:8:14: Context: This is the declaration of the getter 'Super.extendedGetterImplementedField'.
+//   String get extendedGetterImplementedField => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:51:7: Context: This is the declaration of the setter 'Interface1.extendedGetterImplementedField'.
+//   int extendedGetterImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Super.extendedGetterImplementedSetter' is not a subtype of the type 'int' of the inherited setter 'Interface1.extendedGetterImplementedSetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:12:14: Context: This is the declaration of the getter 'Super.extendedGetterImplementedSetter'.
+//   String get extendedGetterImplementedSetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:52:12: Context: This is the declaration of the setter 'Interface1.extendedGetterImplementedSetter'.
+//   void set extendedGetterImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited field 'Super.extendedFieldImplementedSetter' is not a subtype of the type 'int' of the inherited setter 'Interface1.extendedFieldImplementedSetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:16:16: Context: This is the declaration of the field 'Super.extendedFieldImplementedSetter'.
+//   final String extendedFieldImplementedSetter = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:53:12: Context: This is the declaration of the setter 'Interface1.extendedFieldImplementedSetter'.
+//   void set extendedFieldImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited field 'Interface1.mixedInSetterImplementedField' is not a subtype of the type 'int' of the inherited setter 'Super with Mixin.mixedInSetterImplementedField'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:60:16: Context: This is the declaration of the field 'Interface1.mixedInSetterImplementedField'.
+//   final String mixedInSetterImplementedField = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the setter 'Super with Mixin.mixedInSetterImplementedField'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Interface1.mixedInSetterImplementedGetter' is not a subtype of the type 'int' of the inherited setter 'Super with Mixin.mixedInSetterImplementedGetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:61:14: Context: This is the declaration of the getter 'Interface1.mixedInSetterImplementedGetter'.
+//   String get mixedInSetterImplementedGetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the declaration of the setter 'Super with Mixin.mixedInSetterImplementedGetter'.
+// abstract class Class extends Super
+//                ^^^^^^^^^^^^^^^^^^^^...
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited field 'Interface1.extendedSetterImplementedField' is not a subtype of the type 'int' of the inherited setter 'Super.extendedSetterImplementedField'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:54:16: Context: This is the declaration of the field 'Interface1.extendedSetterImplementedField'.
+//   final String extendedSetterImplementedField = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:20:12: Context: This is the declaration of the setter 'Super.extendedSetterImplementedField'.
+//   void set extendedSetterImplementedField(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Interface1.extendedSetterImplementedGetter' is not a subtype of the type 'int' of the inherited setter 'Super.extendedSetterImplementedGetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:55:14: Context: This is the declaration of the getter 'Interface1.extendedSetterImplementedGetter'.
+//   String get extendedSetterImplementedGetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:24:12: Context: This is the declaration of the setter 'Super.extendedSetterImplementedGetter'.
+//   void set extendedSetterImplementedGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: Class 'Class' inherits multiple members named 'implementedGetterImplementedField' with incompatible signatures.
+// Try adding a declaration of 'implementedGetterImplementedField' to 'Class'.
+// abstract class Class extends Super
+//                ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:64:14: Context: This is one of the overridden members.
+//   String get implementedGetterImplementedField => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:80:7: Context: This is one of the overridden members.
+//   int implementedGetterImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Interface1.implementedGetterImplementedField' is not a subtype of the type 'int' of the inherited setter 'Interface2.implementedGetterImplementedField'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:64:14: Context: This is the declaration of the getter 'Interface1.implementedGetterImplementedField'.
+//   String get implementedGetterImplementedField => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:80:7: Context: This is the declaration of the setter 'Interface2.implementedGetterImplementedField'.
+//   int implementedGetterImplementedField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Interface1.implementedGetterImplementedSetter' is not a subtype of the type 'int' of the inherited setter 'Interface2.implementedGetterImplementedSetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:67:14: Context: This is the declaration of the getter 'Interface1.implementedGetterImplementedSetter'.
+//   String get implementedGetterImplementedSetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:81:12: Context: This is the declaration of the setter 'Interface2.implementedGetterImplementedSetter'.
+//   void set implementedGetterImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited field 'Interface1.implementedFieldImplementedSetter' is not a subtype of the type 'int' of the inherited setter 'Interface2.implementedFieldImplementedSetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:70:16: Context: This is the declaration of the field 'Interface1.implementedFieldImplementedSetter'.
+//   final String implementedFieldImplementedSetter = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:82:12: Context: This is the declaration of the setter 'Interface2.implementedFieldImplementedSetter'.
+//   void set implementedFieldImplementedSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited field 'Interface2.implementedSetterImplementedField' is not a subtype of the type 'int' of the inherited setter 'Interface1.implementedSetterImplementedField'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:83:16: Context: This is the declaration of the field 'Interface2.implementedSetterImplementedField'.
+//   final String implementedSetterImplementedField = '';
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:73:12: Context: This is the declaration of the setter 'Interface1.implementedSetterImplementedField'.
+//   void set implementedSetterImplementedField(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Error: The type 'String' of the inherited getter 'Interface2.implementedSetterImplementedGetter' is not a subtype of the type 'int' of the inherited setter 'Interface1.implementedSetterImplementedGetter'.
+// abstract class Class extends Super
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:84:14: Context: This is the declaration of the getter 'Interface2.implementedSetterImplementedGetter'.
+//   String get implementedSetterImplementedGetter => '';
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:76:12: Context: This is the declaration of the setter 'Interface1.implementedSetterImplementedGetter'.
+//   void set implementedSetterImplementedGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:90:7: Error: The return type of the method 'Class.extendedGetterDeclaredField' is 'int', which does not match the return type, 'String', of the overridden method, 'Super.extendedGetterDeclaredField'.
+// Change to a subtype of 'String'.
+//   int extendedGetterDeclaredField = 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:6:14: Context: This is the overridden method ('extendedGetterDeclaredField').
+//   String get extendedGetterDeclaredField => '';
+//              ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:96:7: Error: The return type of the method 'Class.mixedInGetterDeclaredField' is 'int', which does not match the return type, 'String', of the overridden method, 'Super with Mixin.mixedInGetterDeclaredField'.
+// Change to a subtype of 'String'.
+//   int mixedInGetterDeclaredField = 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:87:16: Context: This is the overridden method ('mixedInGetterDeclaredField').
+// abstract class Class extends Super
+//                ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:102:7: Error: The return type of the method 'Class.implementedGetterDeclaredField' is 'int', which does not match the return type, 'String', of the overridden method, 'Interface1.implementedGetterDeclaredField'.
+// Change to a subtype of 'String'.
+//   int implementedGetterDeclaredField = 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/getter_setter.dart:63:14: Context: This is the overridden method ('implementedGetterDeclaredField').
+//   String get implementedGetterDeclaredField => '';
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  final field core::String extendedFieldDeclaredSetter = "";
+  final field core::String extendedFieldMixedInSetter = "";
+  final field core::String extendedFieldImplementedSetter = "";
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  get extendedGetterDeclaredField() → core::String
+    return "";
+  get extendedGetterMixedInField() → core::String
+    return "";
+  get extendedGetterImplementedField() → core::String
+    return "";
+  get extendedGetterDeclaredSetter() → core::String
+    return "";
+  get extendedGetterMixedInSetter() → core::String
+    return "";
+  get extendedGetterImplementedSetter() → core::String
+    return "";
+  set extendedSetterDeclaredField(core::int value) → void {}
+  set extendedSetterMixedInField(core::int value) → void {}
+  set extendedSetterImplementedField(core::int value) → void {}
+  set extendedSetterDeclaredGetter(core::int value) → void {}
+  set extendedSetterMixedInGetter(core::int value) → void {}
+  set extendedSetterImplementedGetter(core::int value) → void {}
+}
+abstract class Mixin extends core::Object {
+  field core::int extendedGetterMixedInField = 0;
+  final field core::String extendedSetterMixedInField = "";
+  final field core::String mixedInFieldDeclaredSetter = "";
+  final field core::String mixedInFieldImplementedSetter = "";
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  set extendedGetterMixedInSetter(core::int value) → void {}
+  set extendedFieldMixedInSetter(core::int value) → void {}
+  get extendedSetterMixedInGetter() → core::String
+    return "";
+  get mixedInGetterDeclaredField() → core::String
+    return "";
+  get mixedInGetterImplementedField() → core::String
+    return "";
+  get mixedInGetterDeclaredSetter() → core::String
+    return "";
+  get mixedInGetterImplementedSetter() → core::String
+    return "";
+  set mixedInSetterDeclaredField(core::int value) → void {}
+  set mixedInSetterImplementedField(core::int value) → void {}
+  set mixedInSetterDeclaredGetter(core::int value) → void {}
+  set mixedInSetterImplementedGetter(core::int value) → void {}
+}
+abstract class Interface1 extends core::Object {
+  field core::int extendedGetterImplementedField = 0;
+  final field core::String extendedSetterImplementedField = "";
+  field core::int mixedInGetterImplementedField = 0;
+  final field core::String mixedInSetterImplementedField = "";
+  final field core::String implementedFieldDeclaredSetter = "";
+  final field core::String implementedFieldImplementedSetter = "";
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  set extendedGetterImplementedSetter(core::int value) → void {}
+  set extendedFieldImplementedSetter(core::int value) → void {}
+  get extendedSetterImplementedGetter() → core::String
+    return "";
+  set mixedInGetterImplementedSetter(core::int value) → void {}
+  set mixedInFieldImplementedSetter(core::int value) → void {}
+  get mixedInSetterImplementedGetter() → core::String
+    return "";
+  get implementedGetterDeclaredField() → core::String
+    return "";
+  get implementedGetterImplementedField() → core::String
+    return "";
+  get implementedGetterDeclaredSetter() → core::String
+    return "";
+  get implementedGetterImplementedSetter() → core::String
+    return "";
+  set implementedSetterDeclaredField(core::int value) → void {}
+  set implementedSetterImplementedField(core::int value) → void {}
+  set implementedSetterDeclaredGetter(core::int value) → void {}
+  set implementedSetterImplementedGetter(core::int value) → void {}
+}
+abstract class Interface2 extends core::Object {
+  field core::int implementedGetterImplementedField = 0;
+  final field core::String implementedSetterImplementedField = "";
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  set implementedGetterImplementedSetter(core::int value) → void {}
+  set implementedFieldImplementedSetter(core::int value) → void {}
+  get implementedSetterImplementedGetter() → core::String
+    return "";
+}
+abstract class _Class&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Class&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub get mixedInGetterDeclaredField() → core::String
+    return super.{self::Mixin::mixedInGetterDeclaredField};
+  mixin-super-stub set mixedInSetterDeclaredField(core::int value) → void
+    return super.{self::Mixin::mixedInSetterDeclaredField} = value;
+  mixin-super-stub get mixedInGetterDeclaredSetter() → core::String
+    return super.{self::Mixin::mixedInGetterDeclaredSetter};
+  mixin-super-stub get mixedInFieldDeclaredSetter() → core::String
+    return super.{self::Mixin::mixedInFieldDeclaredSetter};
+  mixin-super-stub get extendedGetterMixedInField() → core::int
+    return super.{self::Mixin::extendedGetterMixedInField};
+  mixin-super-stub set extendedGetterMixedInField(core::int value) → void
+    return super.{self::Mixin::extendedGetterMixedInField} = value;
+  mixin-super-stub get extendedSetterMixedInField() → core::String
+    return super.{self::Mixin::extendedSetterMixedInField};
+  mixin-super-stub get extendedSetterMixedInGetter() → core::String
+    return super.{self::Mixin::extendedSetterMixedInGetter};
+  mixin-super-stub set extendedGetterMixedInSetter(core::int value) → void
+    return super.{self::Mixin::extendedGetterMixedInSetter} = value;
+  mixin-super-stub set extendedFieldMixedInSetter(core::int value) → void
+    return super.{self::Mixin::extendedFieldMixedInSetter} = value;
+  mixin-super-stub set mixedInSetterDeclaredGetter(core::int value) → void
+    return super.{self::Mixin::mixedInSetterDeclaredGetter} = value;
+  mixin-super-stub get mixedInGetterImplementedField() → core::String
+    return super.{self::Mixin::mixedInGetterImplementedField};
+  mixin-super-stub get mixedInGetterImplementedSetter() → core::String
+    return super.{self::Mixin::mixedInGetterImplementedSetter};
+  mixin-super-stub get mixedInFieldImplementedSetter() → core::String
+    return super.{self::Mixin::mixedInFieldImplementedSetter};
+  mixin-super-stub set mixedInSetterImplementedField(core::int value) → void
+    return super.{self::Mixin::mixedInSetterImplementedField} = value;
+  mixin-super-stub set mixedInSetterImplementedGetter(core::int value) → void
+    return super.{self::Mixin::mixedInSetterImplementedGetter} = value;
+}
+abstract class Class extends self::_Class&Super&Mixin implements self::Interface1, self::Interface2 {
+  field core::int extendedGetterDeclaredField = 0;
+  final field core::String extendedSetterDeclaredField = "";
+  field core::int mixedInGetterDeclaredField = 0;
+  final field core::String mixedInSetterDeclaredField = "";
+  field core::int implementedGetterDeclaredField = 0;
+  final field core::String implementedSetterDeclaredField = "";
+  final field core::String declaredFieldDeclaredSetter = "";
+  synthetic constructor •() → self::Class
+    : super self::_Class&Super&Mixin::•()
+    ;
+  set extendedGetterDeclaredSetter(core::int value) → void {}
+  set extendedFieldDeclaredSetter(core::int value) → void {}
+  get extendedSetterDeclaredGetter() → core::String
+    return "";
+  set mixedInGetterDeclaredSetter(core::int value) → void {}
+  set mixedInFieldDeclaredSetter(core::int value) → void {}
+  get mixedInSetterDeclaredGetter() → core::String
+    return "";
+  set implementedGetterDeclaredSetter(core::int value) → void {}
+  set implementedFieldDeclaredSetter(core::int value) → void {}
+  get implementedSetterDeclaredGetter() → core::String
+    return "";
+  get declaredGetterDeclaredSetter() → core::String
+    return "";
+  set declaredGetterDeclaredSetter(core::int value) → void {}
+  set declaredFieldDeclaredSetter(core::int value) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart
new file mode 100644
index 0000000..387a7b4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart
@@ -0,0 +1,35 @@
+// 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 Interface1 {
+  int implementMultipleField = 0;
+
+  int declareConcreteImplementMultipleField = 0;
+
+  int declareAbstractImplementMultipleField = 0;
+}
+
+class Interface2 {
+  int implementMultipleField = 0;
+
+  int declareConcreteImplementMultipleField = 0;
+
+  int declareAbstractImplementMultipleField = 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  int declareConcreteImplementMultipleField = 0;
+
+  abstract int declareAbstractImplementMultipleField;
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  int declareConcreteImplementMultipleField = 0;
+
+  abstract int declareAbstractImplementMultipleField;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.textual_outline.expect
new file mode 100644
index 0000000..21421e9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class Interface1 {
+  int implementMultipleField = 0;
+  int declareConcreteImplementMultipleField = 0;
+  int declareAbstractImplementMultipleField = 0;
+}
+
+class Interface2 {
+  int implementMultipleField = 0;
+  int declareConcreteImplementMultipleField = 0;
+  int declareAbstractImplementMultipleField = 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  int declareConcreteImplementMultipleField = 0;
+  abstract int declareAbstractImplementMultipleField;
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  int declareConcreteImplementMultipleField = 0;
+  abstract int declareAbstractImplementMultipleField;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6b7f513
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+abstract class AbstractClass implements Interface1, Interface2 {
+  abstract int declareAbstractImplementMultipleField;
+  int declareConcreteImplementMultipleField = 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  abstract int declareAbstractImplementMultipleField;
+  int declareConcreteImplementMultipleField = 0;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  int declareAbstractImplementMultipleField = 0;
+  int declareConcreteImplementMultipleField = 0;
+  int implementMultipleField = 0;
+}
+
+class Interface2 {
+  int declareAbstractImplementMultipleField = 0;
+  int declareConcreteImplementMultipleField = 0;
+  int implementMultipleField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.weak.expect
new file mode 100644
index 0000000..4701040
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.weak.expect
@@ -0,0 +1,105 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleField
+//  - ConcreteClass.declareAbstractImplementMultipleField=
+//  - Interface1.implementMultipleField
+//  - Interface2.implementMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:24:16: Context: 'ConcreteClass.declareAbstractImplementMultipleField' is defined here.
+//   abstract int declareAbstractImplementMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:24:16: Context: 'ConcreteClass.declareAbstractImplementMultipleField=' is defined here.
+//   abstract int declareAbstractImplementMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:6:7: Context: 'Interface1.implementMultipleField' is defined here.
+//   int implementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:14:7: Context: 'Interface2.implementMultipleField' is defined here.
+//   int implementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleField
+//  - AbstractClass.declareAbstractImplementMultipleField=
+//  - Interface1.declareAbstractImplementMultipleField
+//  - Interface1.implementMultipleField
+//  - Interface2.declareAbstractImplementMultipleField
+//  - Interface2.implementMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:30:16: Context: 'AbstractClass.declareAbstractImplementMultipleField' is defined here.
+//   abstract int declareAbstractImplementMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:30:16: Context: 'AbstractClass.declareAbstractImplementMultipleField=' is defined here.
+//   abstract int declareAbstractImplementMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:10:7: Context: 'Interface1.declareAbstractImplementMultipleField' is defined here.
+//   int declareAbstractImplementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:6:7: Context: 'Interface1.implementMultipleField' is defined here.
+//   int implementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:18:7: Context: 'Interface2.declareAbstractImplementMultipleField' is defined here.
+//   int declareAbstractImplementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:14:7: Context: 'Interface2.implementMultipleField' is defined here.
+//   int implementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  field core::int implementMultipleField = 0;
+  field core::int declareConcreteImplementMultipleField = 0;
+  field core::int declareAbstractImplementMultipleField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  field core::int implementMultipleField = 0;
+  field core::int declareConcreteImplementMultipleField = 0;
+  field core::int declareAbstractImplementMultipleField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  field core::int declareConcreteImplementMultipleField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  abstract get declareAbstractImplementMultipleField() → core::int;
+  abstract set declareAbstractImplementMultipleField(core::int #externalFieldValue) → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  field core::int declareConcreteImplementMultipleField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  abstract get declareAbstractImplementMultipleField() → core::int;
+  abstract set declareAbstractImplementMultipleField(core::int #externalFieldValue) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..4701040
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart.weak.transformed.expect
@@ -0,0 +1,105 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleField
+//  - ConcreteClass.declareAbstractImplementMultipleField=
+//  - Interface1.implementMultipleField
+//  - Interface2.implementMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:24:16: Context: 'ConcreteClass.declareAbstractImplementMultipleField' is defined here.
+//   abstract int declareAbstractImplementMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:24:16: Context: 'ConcreteClass.declareAbstractImplementMultipleField=' is defined here.
+//   abstract int declareAbstractImplementMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:6:7: Context: 'Interface1.implementMultipleField' is defined here.
+//   int implementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:14:7: Context: 'Interface2.implementMultipleField' is defined here.
+//   int implementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleField
+//  - AbstractClass.declareAbstractImplementMultipleField=
+//  - Interface1.declareAbstractImplementMultipleField
+//  - Interface1.implementMultipleField
+//  - Interface2.declareAbstractImplementMultipleField
+//  - Interface2.implementMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:30:16: Context: 'AbstractClass.declareAbstractImplementMultipleField' is defined here.
+//   abstract int declareAbstractImplementMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:30:16: Context: 'AbstractClass.declareAbstractImplementMultipleField=' is defined here.
+//   abstract int declareAbstractImplementMultipleField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:10:7: Context: 'Interface1.declareAbstractImplementMultipleField' is defined here.
+//   int declareAbstractImplementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:6:7: Context: 'Interface1.implementMultipleField' is defined here.
+//   int implementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:18:7: Context: 'Interface2.declareAbstractImplementMultipleField' is defined here.
+//   int declareAbstractImplementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_field.dart:14:7: Context: 'Interface2.implementMultipleField' is defined here.
+//   int implementMultipleField = 0;
+//       ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  field core::int implementMultipleField = 0;
+  field core::int declareConcreteImplementMultipleField = 0;
+  field core::int declareAbstractImplementMultipleField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  field core::int implementMultipleField = 0;
+  field core::int declareConcreteImplementMultipleField = 0;
+  field core::int declareAbstractImplementMultipleField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  field core::int declareConcreteImplementMultipleField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  abstract get declareAbstractImplementMultipleField() → core::int;
+  abstract set declareAbstractImplementMultipleField(core::int #externalFieldValue) → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  field core::int declareConcreteImplementMultipleField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  abstract get declareAbstractImplementMultipleField() → core::int;
+  abstract set declareAbstractImplementMultipleField(core::int #externalFieldValue) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart
new file mode 100644
index 0000000..3e8c0f1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart
@@ -0,0 +1,35 @@
+// 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 Interface1 {
+  final int implementMultipleField = 0;
+
+  final int declareConcreteImplementMultipleField = 0;
+
+  final int declareAbstractImplementMultipleField = 0;
+}
+
+class Interface2 {
+  final int implementMultipleField = 0;
+
+  final int declareConcreteImplementMultipleField = 0;
+
+  final int declareAbstractImplementMultipleField = 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  final int declareConcreteImplementMultipleField = 0;
+
+  abstract final int declareAbstractImplementMultipleField;
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  final int declareConcreteImplementMultipleField = 0;
+
+  abstract final int declareAbstractImplementMultipleField;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.textual_outline.expect
new file mode 100644
index 0000000..a8edcbd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class Interface1 {
+  final int implementMultipleField = 0;
+  final int declareConcreteImplementMultipleField = 0;
+  final int declareAbstractImplementMultipleField = 0;
+}
+
+class Interface2 {
+  final int implementMultipleField = 0;
+  final int declareConcreteImplementMultipleField = 0;
+  final int declareAbstractImplementMultipleField = 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  final int declareConcreteImplementMultipleField = 0;
+  abstract final int declareAbstractImplementMultipleField;
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  final int declareConcreteImplementMultipleField = 0;
+  abstract final int declareAbstractImplementMultipleField;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c086ea9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+abstract class AbstractClass implements Interface1, Interface2 {
+  abstract final int declareAbstractImplementMultipleField;
+  final int declareConcreteImplementMultipleField = 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  abstract final int declareAbstractImplementMultipleField;
+  final int declareConcreteImplementMultipleField = 0;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  final int declareAbstractImplementMultipleField = 0;
+  final int declareConcreteImplementMultipleField = 0;
+  final int implementMultipleField = 0;
+}
+
+class Interface2 {
+  final int declareAbstractImplementMultipleField = 0;
+  final int declareConcreteImplementMultipleField = 0;
+  final int implementMultipleField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.weak.expect
new file mode 100644
index 0000000..5ebd497f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.weak.expect
@@ -0,0 +1,95 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleField
+//  - Interface1.implementMultipleField
+//  - Interface2.implementMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:24:22: Context: 'ConcreteClass.declareAbstractImplementMultipleField' is defined here.
+//   abstract final int declareAbstractImplementMultipleField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:6:13: Context: 'Interface1.implementMultipleField' is defined here.
+//   final int implementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:14:13: Context: 'Interface2.implementMultipleField' is defined here.
+//   final int implementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleField
+//  - Interface1.declareAbstractImplementMultipleField
+//  - Interface1.implementMultipleField
+//  - Interface2.declareAbstractImplementMultipleField
+//  - Interface2.implementMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:30:22: Context: 'AbstractClass.declareAbstractImplementMultipleField' is defined here.
+//   abstract final int declareAbstractImplementMultipleField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:10:13: Context: 'Interface1.declareAbstractImplementMultipleField' is defined here.
+//   final int declareAbstractImplementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:6:13: Context: 'Interface1.implementMultipleField' is defined here.
+//   final int implementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:18:13: Context: 'Interface2.declareAbstractImplementMultipleField' is defined here.
+//   final int declareAbstractImplementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:14:13: Context: 'Interface2.implementMultipleField' is defined here.
+//   final int implementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  final field core::int implementMultipleField = 0;
+  final field core::int declareConcreteImplementMultipleField = 0;
+  final field core::int declareAbstractImplementMultipleField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  final field core::int implementMultipleField = 0;
+  final field core::int declareConcreteImplementMultipleField = 0;
+  final field core::int declareAbstractImplementMultipleField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  final field core::int declareConcreteImplementMultipleField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  abstract get declareAbstractImplementMultipleField() → core::int;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  final field core::int declareConcreteImplementMultipleField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  abstract get declareAbstractImplementMultipleField() → core::int;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..5ebd497f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart.weak.transformed.expect
@@ -0,0 +1,95 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleField
+//  - Interface1.implementMultipleField
+//  - Interface2.implementMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:24:22: Context: 'ConcreteClass.declareAbstractImplementMultipleField' is defined here.
+//   abstract final int declareAbstractImplementMultipleField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:6:13: Context: 'Interface1.implementMultipleField' is defined here.
+//   final int implementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:14:13: Context: 'Interface2.implementMultipleField' is defined here.
+//   final int implementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleField
+//  - Interface1.declareAbstractImplementMultipleField
+//  - Interface1.implementMultipleField
+//  - Interface2.declareAbstractImplementMultipleField
+//  - Interface2.implementMultipleField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:30:22: Context: 'AbstractClass.declareAbstractImplementMultipleField' is defined here.
+//   abstract final int declareAbstractImplementMultipleField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:10:13: Context: 'Interface1.declareAbstractImplementMultipleField' is defined here.
+//   final int declareAbstractImplementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:6:13: Context: 'Interface1.implementMultipleField' is defined here.
+//   final int implementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:18:13: Context: 'Interface2.declareAbstractImplementMultipleField' is defined here.
+//   final int declareAbstractImplementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_final_field.dart:14:13: Context: 'Interface2.implementMultipleField' is defined here.
+//   final int implementMultipleField = 0;
+//             ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  final field core::int implementMultipleField = 0;
+  final field core::int declareConcreteImplementMultipleField = 0;
+  final field core::int declareAbstractImplementMultipleField = 0;
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+}
+class Interface2 extends core::Object {
+  final field core::int implementMultipleField = 0;
+  final field core::int declareConcreteImplementMultipleField = 0;
+  final field core::int declareAbstractImplementMultipleField = 0;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  final field core::int declareConcreteImplementMultipleField = 0;
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  abstract get declareAbstractImplementMultipleField() → core::int;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  final field core::int declareConcreteImplementMultipleField = 0;
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  abstract get declareAbstractImplementMultipleField() → core::int;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart
new file mode 100644
index 0000000..45d0d3c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart
@@ -0,0 +1,35 @@
+// 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 Interface1 {
+  int get implementMultipleGetter => 0;
+
+  int get declareConcreteImplementMultipleGetter => 0;
+
+  int get declareAbstractImplementMultipleGetter => 0;
+}
+
+class Interface2 {
+  int get implementMultipleGetter => 0;
+
+  int get declareConcreteImplementMultipleGetter => 0;
+
+  int get declareAbstractImplementMultipleGetter => 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  int get declareConcreteImplementMultipleGetter => 0;
+
+  int get declareAbstractImplementMultipleGetter;
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  int get declareConcreteImplementMultipleGetter => 0;
+
+  int get declareAbstractImplementMultipleGetter;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.textual_outline.expect
new file mode 100644
index 0000000..4300f58
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class Interface1 {
+  int get implementMultipleGetter => 0;
+  int get declareConcreteImplementMultipleGetter => 0;
+  int get declareAbstractImplementMultipleGetter => 0;
+}
+
+class Interface2 {
+  int get implementMultipleGetter => 0;
+  int get declareConcreteImplementMultipleGetter => 0;
+  int get declareAbstractImplementMultipleGetter => 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  int get declareConcreteImplementMultipleGetter => 0;
+  int get declareAbstractImplementMultipleGetter;
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  int get declareConcreteImplementMultipleGetter => 0;
+  int get declareAbstractImplementMultipleGetter;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e805c06
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+abstract class AbstractClass implements Interface1, Interface2 {
+  int get declareAbstractImplementMultipleGetter;
+  int get declareConcreteImplementMultipleGetter => 0;
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  int get declareAbstractImplementMultipleGetter;
+  int get declareConcreteImplementMultipleGetter => 0;
+}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  int get declareAbstractImplementMultipleGetter => 0;
+  int get declareConcreteImplementMultipleGetter => 0;
+  int get implementMultipleGetter => 0;
+}
+
+class Interface2 {
+  int get declareAbstractImplementMultipleGetter => 0;
+  int get declareConcreteImplementMultipleGetter => 0;
+  int get implementMultipleGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.weak.expect
new file mode 100644
index 0000000..538cee7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.weak.expect
@@ -0,0 +1,103 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleGetter
+//  - Interface1.implementMultipleGetter
+//  - Interface2.implementMultipleGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:24:11: Context: 'ConcreteClass.declareAbstractImplementMultipleGetter' is defined here.
+//   int get declareAbstractImplementMultipleGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:6:11: Context: 'Interface1.implementMultipleGetter' is defined here.
+//   int get implementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:14:11: Context: 'Interface2.implementMultipleGetter' is defined here.
+//   int get implementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleGetter
+//  - Interface1.declareAbstractImplementMultipleGetter
+//  - Interface1.implementMultipleGetter
+//  - Interface2.declareAbstractImplementMultipleGetter
+//  - Interface2.implementMultipleGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:30:11: Context: 'AbstractClass.declareAbstractImplementMultipleGetter' is defined here.
+//   int get declareAbstractImplementMultipleGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:10:11: Context: 'Interface1.declareAbstractImplementMultipleGetter' is defined here.
+//   int get declareAbstractImplementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:6:11: Context: 'Interface1.implementMultipleGetter' is defined here.
+//   int get implementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:18:11: Context: 'Interface2.declareAbstractImplementMultipleGetter' is defined here.
+//   int get declareAbstractImplementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:14:11: Context: 'Interface2.implementMultipleGetter' is defined here.
+//   int get implementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  get implementMultipleGetter() → core::int
+    return 0;
+  get declareConcreteImplementMultipleGetter() → core::int
+    return 0;
+  get declareAbstractImplementMultipleGetter() → core::int
+    return 0;
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  get implementMultipleGetter() → core::int
+    return 0;
+  get declareConcreteImplementMultipleGetter() → core::int
+    return 0;
+  get declareAbstractImplementMultipleGetter() → core::int
+    return 0;
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  get declareConcreteImplementMultipleGetter() → core::int
+    return 0;
+  abstract get declareAbstractImplementMultipleGetter() → core::int;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  get declareConcreteImplementMultipleGetter() → core::int
+    return 0;
+  abstract get declareAbstractImplementMultipleGetter() → core::int;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.weak.transformed.expect
new file mode 100644
index 0000000..538cee7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart.weak.transformed.expect
@@ -0,0 +1,103 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleGetter
+//  - Interface1.implementMultipleGetter
+//  - Interface2.implementMultipleGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:24:11: Context: 'ConcreteClass.declareAbstractImplementMultipleGetter' is defined here.
+//   int get declareAbstractImplementMultipleGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:6:11: Context: 'Interface1.implementMultipleGetter' is defined here.
+//   int get implementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:14:11: Context: 'Interface2.implementMultipleGetter' is defined here.
+//   int get implementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleGetter
+//  - Interface1.declareAbstractImplementMultipleGetter
+//  - Interface1.implementMultipleGetter
+//  - Interface2.declareAbstractImplementMultipleGetter
+//  - Interface2.implementMultipleGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:30:11: Context: 'AbstractClass.declareAbstractImplementMultipleGetter' is defined here.
+//   int get declareAbstractImplementMultipleGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:10:11: Context: 'Interface1.declareAbstractImplementMultipleGetter' is defined here.
+//   int get declareAbstractImplementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:6:11: Context: 'Interface1.implementMultipleGetter' is defined here.
+//   int get implementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:18:11: Context: 'Interface2.declareAbstractImplementMultipleGetter' is defined here.
+//   int get declareAbstractImplementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_getter.dart:14:11: Context: 'Interface2.implementMultipleGetter' is defined here.
+//   int get implementMultipleGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  get implementMultipleGetter() → core::int
+    return 0;
+  get declareConcreteImplementMultipleGetter() → core::int
+    return 0;
+  get declareAbstractImplementMultipleGetter() → core::int
+    return 0;
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  get implementMultipleGetter() → core::int
+    return 0;
+  get declareConcreteImplementMultipleGetter() → core::int
+    return 0;
+  get declareAbstractImplementMultipleGetter() → core::int
+    return 0;
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  get declareConcreteImplementMultipleGetter() → core::int
+    return 0;
+  abstract get declareAbstractImplementMultipleGetter() → core::int;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  get declareConcreteImplementMultipleGetter() → core::int
+    return 0;
+  abstract get declareAbstractImplementMultipleGetter() → core::int;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart
new file mode 100644
index 0000000..87f4bd8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart
@@ -0,0 +1,35 @@
+// 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 Interface1 {
+  void implementMultipleMethod() {}
+
+  void declareConcreteImplementMultipleMethod() {}
+
+  void declareAbstractImplementMultipleMethod() {}
+}
+
+class Interface2 {
+  void implementMultipleMethod() {}
+
+  void declareConcreteImplementMultipleMethod() {}
+
+  void declareAbstractImplementMultipleMethod() {}
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  void declareConcreteImplementMultipleMethod() {}
+
+  void declareAbstractImplementMultipleMethod();
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  void declareConcreteImplementMultipleMethod() {}
+
+  void declareAbstractImplementMultipleMethod();
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.textual_outline.expect
new file mode 100644
index 0000000..48b2bf4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class Interface1 {
+  void implementMultipleMethod() {}
+  void declareConcreteImplementMultipleMethod() {}
+  void declareAbstractImplementMultipleMethod() {}
+}
+
+class Interface2 {
+  void implementMultipleMethod() {}
+  void declareConcreteImplementMultipleMethod() {}
+  void declareAbstractImplementMultipleMethod() {}
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  void declareConcreteImplementMultipleMethod() {}
+  void declareAbstractImplementMultipleMethod();
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  void declareConcreteImplementMultipleMethod() {}
+  void declareAbstractImplementMultipleMethod();
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..40a8991
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+abstract class AbstractClass implements Interface1, Interface2 {
+  void declareAbstractImplementMultipleMethod();
+  void declareConcreteImplementMultipleMethod() {}
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  void declareAbstractImplementMultipleMethod();
+  void declareConcreteImplementMultipleMethod() {}
+}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  void declareAbstractImplementMultipleMethod() {}
+  void declareConcreteImplementMultipleMethod() {}
+  void implementMultipleMethod() {}
+}
+
+class Interface2 {
+  void declareAbstractImplementMultipleMethod() {}
+  void declareConcreteImplementMultipleMethod() {}
+  void implementMultipleMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.weak.expect
new file mode 100644
index 0000000..66a5d5e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.weak.expect
@@ -0,0 +1,95 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleMethod
+//  - Interface1.implementMultipleMethod
+//  - Interface2.implementMultipleMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:24:8: Context: 'ConcreteClass.declareAbstractImplementMultipleMethod' is defined here.
+//   void declareAbstractImplementMultipleMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:6:8: Context: 'Interface1.implementMultipleMethod' is defined here.
+//   void implementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:14:8: Context: 'Interface2.implementMultipleMethod' is defined here.
+//   void implementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleMethod
+//  - Interface1.declareAbstractImplementMultipleMethod
+//  - Interface1.implementMultipleMethod
+//  - Interface2.declareAbstractImplementMultipleMethod
+//  - Interface2.implementMultipleMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:30:8: Context: 'AbstractClass.declareAbstractImplementMultipleMethod' is defined here.
+//   void declareAbstractImplementMultipleMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:10:8: Context: 'Interface1.declareAbstractImplementMultipleMethod' is defined here.
+//   void declareAbstractImplementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:6:8: Context: 'Interface1.implementMultipleMethod' is defined here.
+//   void implementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:18:8: Context: 'Interface2.declareAbstractImplementMultipleMethod' is defined here.
+//   void declareAbstractImplementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:14:8: Context: 'Interface2.implementMultipleMethod' is defined here.
+//   void implementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method implementMultipleMethod() → void {}
+  method declareConcreteImplementMultipleMethod() → void {}
+  method declareAbstractImplementMultipleMethod() → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method implementMultipleMethod() → void {}
+  method declareConcreteImplementMultipleMethod() → void {}
+  method declareAbstractImplementMultipleMethod() → void {}
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  method declareConcreteImplementMultipleMethod() → void {}
+  abstract method declareAbstractImplementMultipleMethod() → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  method declareConcreteImplementMultipleMethod() → void {}
+  abstract method declareAbstractImplementMultipleMethod() → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..66a5d5e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart.weak.transformed.expect
@@ -0,0 +1,95 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleMethod
+//  - Interface1.implementMultipleMethod
+//  - Interface2.implementMultipleMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:24:8: Context: 'ConcreteClass.declareAbstractImplementMultipleMethod' is defined here.
+//   void declareAbstractImplementMultipleMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:6:8: Context: 'Interface1.implementMultipleMethod' is defined here.
+//   void implementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:14:8: Context: 'Interface2.implementMultipleMethod' is defined here.
+//   void implementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleMethod
+//  - Interface1.declareAbstractImplementMultipleMethod
+//  - Interface1.implementMultipleMethod
+//  - Interface2.declareAbstractImplementMultipleMethod
+//  - Interface2.implementMultipleMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:30:8: Context: 'AbstractClass.declareAbstractImplementMultipleMethod' is defined here.
+//   void declareAbstractImplementMultipleMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:10:8: Context: 'Interface1.declareAbstractImplementMultipleMethod' is defined here.
+//   void declareAbstractImplementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:6:8: Context: 'Interface1.implementMultipleMethod' is defined here.
+//   void implementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:18:8: Context: 'Interface2.declareAbstractImplementMultipleMethod' is defined here.
+//   void declareAbstractImplementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_method.dart:14:8: Context: 'Interface2.implementMultipleMethod' is defined here.
+//   void implementMultipleMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method implementMultipleMethod() → void {}
+  method declareConcreteImplementMultipleMethod() → void {}
+  method declareAbstractImplementMultipleMethod() → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method implementMultipleMethod() → void {}
+  method declareConcreteImplementMultipleMethod() → void {}
+  method declareAbstractImplementMultipleMethod() → void {}
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  method declareConcreteImplementMultipleMethod() → void {}
+  abstract method declareAbstractImplementMultipleMethod() → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  method declareConcreteImplementMultipleMethod() → void {}
+  abstract method declareAbstractImplementMultipleMethod() → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart
new file mode 100644
index 0000000..8c92041
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart
@@ -0,0 +1,35 @@
+// 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 Interface1 {
+  void set implementMultipleSetter(int i) {}
+
+  void set declareConcreteImplementMultipleSetter(int i) {}
+
+  void set declareAbstractImplementMultipleSetter(int i) {}
+}
+
+class Interface2 {
+  void set implementMultipleSetter(int i) {}
+
+  void set declareConcreteImplementMultipleSetter(int i) {}
+
+  void set declareAbstractImplementMultipleSetter(int i) {}
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  void set declareConcreteImplementMultipleSetter(int i) {}
+
+  void set declareAbstractImplementMultipleSetter(int i);
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  void set declareConcreteImplementMultipleSetter(int i) {}
+
+  void set declareAbstractImplementMultipleSetter(int i);
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..d429c5f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class Interface1 {
+  void set implementMultipleSetter(int i) {}
+  void set declareConcreteImplementMultipleSetter(int i) {}
+  void set declareAbstractImplementMultipleSetter(int i) {}
+}
+
+class Interface2 {
+  void set implementMultipleSetter(int i) {}
+  void set declareConcreteImplementMultipleSetter(int i) {}
+  void set declareAbstractImplementMultipleSetter(int i) {}
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  void set declareConcreteImplementMultipleSetter(int i) {}
+  void set declareAbstractImplementMultipleSetter(int i);
+}
+
+abstract class AbstractClass implements Interface1, Interface2 {
+  void set declareConcreteImplementMultipleSetter(int i) {}
+  void set declareAbstractImplementMultipleSetter(int i);
+}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d861905
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+abstract class AbstractClass implements Interface1, Interface2 {
+  void set declareAbstractImplementMultipleSetter(int i);
+  void set declareConcreteImplementMultipleSetter(int i) {}
+}
+
+class ConcreteClass implements Interface1, Interface2 {
+  void set declareAbstractImplementMultipleSetter(int i);
+  void set declareConcreteImplementMultipleSetter(int i) {}
+}
+
+class ConcreteSub extends AbstractClass {}
+
+class Interface1 {
+  void set declareAbstractImplementMultipleSetter(int i) {}
+  void set declareConcreteImplementMultipleSetter(int i) {}
+  void set implementMultipleSetter(int i) {}
+}
+
+class Interface2 {
+  void set declareAbstractImplementMultipleSetter(int i) {}
+  void set declareConcreteImplementMultipleSetter(int i) {}
+  void set implementMultipleSetter(int i) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.weak.expect
new file mode 100644
index 0000000..c960de6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.weak.expect
@@ -0,0 +1,95 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleSetter=
+//  - Interface1.implementMultipleSetter=
+//  - Interface2.implementMultipleSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:24:12: Context: 'ConcreteClass.declareAbstractImplementMultipleSetter=' is defined here.
+//   void set declareAbstractImplementMultipleSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:6:12: Context: 'Interface1.implementMultipleSetter=' is defined here.
+//   void set implementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:14:12: Context: 'Interface2.implementMultipleSetter=' is defined here.
+//   void set implementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleSetter=
+//  - Interface1.declareAbstractImplementMultipleSetter=
+//  - Interface1.implementMultipleSetter=
+//  - Interface2.declareAbstractImplementMultipleSetter=
+//  - Interface2.implementMultipleSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:30:12: Context: 'AbstractClass.declareAbstractImplementMultipleSetter=' is defined here.
+//   void set declareAbstractImplementMultipleSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:10:12: Context: 'Interface1.declareAbstractImplementMultipleSetter=' is defined here.
+//   void set declareAbstractImplementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:6:12: Context: 'Interface1.implementMultipleSetter=' is defined here.
+//   void set implementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:18:12: Context: 'Interface2.declareAbstractImplementMultipleSetter=' is defined here.
+//   void set declareAbstractImplementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:14:12: Context: 'Interface2.implementMultipleSetter=' is defined here.
+//   void set implementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  set implementMultipleSetter(core::int i) → void {}
+  set declareConcreteImplementMultipleSetter(core::int i) → void {}
+  set declareAbstractImplementMultipleSetter(core::int i) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  set implementMultipleSetter(core::int i) → void {}
+  set declareConcreteImplementMultipleSetter(core::int i) → void {}
+  set declareAbstractImplementMultipleSetter(core::int i) → void {}
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  set declareConcreteImplementMultipleSetter(core::int i) → void {}
+  abstract set declareAbstractImplementMultipleSetter(core::int i) → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  set declareConcreteImplementMultipleSetter(core::int i) → void {}
+  abstract set declareAbstractImplementMultipleSetter(core::int i) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.weak.transformed.expect
new file mode 100644
index 0000000..c960de6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart.weak.transformed.expect
@@ -0,0 +1,95 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:21:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - ConcreteClass.declareAbstractImplementMultipleSetter=
+//  - Interface1.implementMultipleSetter=
+//  - Interface2.implementMultipleSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass implements Interface1, Interface2 {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:24:12: Context: 'ConcreteClass.declareAbstractImplementMultipleSetter=' is defined here.
+//   void set declareAbstractImplementMultipleSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:6:12: Context: 'Interface1.implementMultipleSetter=' is defined here.
+//   void set implementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:14:12: Context: 'Interface2.implementMultipleSetter=' is defined here.
+//   void set implementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:33:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - AbstractClass.declareAbstractImplementMultipleSetter=
+//  - Interface1.declareAbstractImplementMultipleSetter=
+//  - Interface1.implementMultipleSetter=
+//  - Interface2.declareAbstractImplementMultipleSetter=
+//  - Interface2.implementMultipleSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:30:12: Context: 'AbstractClass.declareAbstractImplementMultipleSetter=' is defined here.
+//   void set declareAbstractImplementMultipleSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:10:12: Context: 'Interface1.declareAbstractImplementMultipleSetter=' is defined here.
+//   void set declareAbstractImplementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:6:12: Context: 'Interface1.implementMultipleSetter=' is defined here.
+//   void set implementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:18:12: Context: 'Interface2.declareAbstractImplementMultipleSetter=' is defined here.
+//   void set declareAbstractImplementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/implement_multiple_setter.dart:14:12: Context: 'Interface2.implementMultipleSetter=' is defined here.
+//   void set implementMultipleSetter(int i) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  set implementMultipleSetter(core::int i) → void {}
+  set declareConcreteImplementMultipleSetter(core::int i) → void {}
+  set declareAbstractImplementMultipleSetter(core::int i) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  set implementMultipleSetter(core::int i) → void {}
+  set declareConcreteImplementMultipleSetter(core::int i) → void {}
+  set declareAbstractImplementMultipleSetter(core::int i) → void {}
+}
+class ConcreteClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::ConcreteClass
+    : super core::Object::•()
+    ;
+  set declareConcreteImplementMultipleSetter(core::int i) → void {}
+  abstract set declareAbstractImplementMultipleSetter(core::int i) → void;
+}
+abstract class AbstractClass extends core::Object implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::AbstractClass
+    : super core::Object::•()
+    ;
+  set declareConcreteImplementMultipleSetter(core::int i) → void {}
+  abstract set declareAbstractImplementMultipleSetter(core::int i) → void;
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub
+    : super self::AbstractClass::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart
new file mode 100644
index 0000000..1b3c5a2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.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 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+// Class doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class Class /* error */ extends LegacyClass implements SuperQ {
+  test() {
+    int i;
+    // Valid call to `SuperQ.nullabilityMethod`, returns int?.
+    var v1 = nullabilityMethod(null); // ok
+    // Valid super call to `LegacyClass.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `SuperQ.nullabilityGetter`, return int?.
+    var v2 = nullabilityGetter; // ok
+    // Valid read of `LegacyClass.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Valid write to `SuperQ.nullabilitySetter`.
+    nullabilitySetter = null; // ok
+    // Valid write to `LegacyClass.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassQ doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassQ /* error */ extends LegacyClassQ implements Super {
+  test() {
+    int i;
+    // Invalid call to `Super.nullabilityMethod`, returns int!.
+    nullabilityMethod(null); // error
+    // Valid call to `LegacyClassQ.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `Super.nullabilityGetter`, return int.
+    i = nullabilityGetter; // ok
+    // Valid read of `LegacyClassQ.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Invalid write to `Super.nullabilitySetter`.
+    nullabilitySetter = null; // error
+    // Valid write to `LegacyClassQ.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassMixedIn doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassMixedIn /* error */ extends LegacyMixedIn implements SuperQ {
+  test() {
+    int i;
+    // Valid call to `SuperQ.nullabilityMethod`, returns int?.
+    var v1 = nullabilityMethod(null); // ok
+    // Valid super call to `LegacyMixedIn.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `SuperQ.nullabilityGetter`, return int?.
+    var v2 = nullabilityGetter; // ok
+    // Valid read of `LegacyMixedIn.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Valid write to `SuperQ.nullabilitySetter`.
+    nullabilitySetter = null; // ok
+    // Valid write to `LegacyMixedIn.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassMixedInQ doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassMixedInQ /* error */ extends LegacyMixedInQ implements Super {
+  test() {
+    int i;
+    // Invalid call to `Super.nullabilityMethod`, returns int!.
+    nullabilityMethod(null); // error
+    // Valid call to `LegacyMixedInQ.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `Super.nullabilityGetter`, return int.
+    i = nullabilityGetter; // ok
+    // Valid read of `LegacyMixedInQ.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Invalid write to `Super.nullabilitySetter`.
+    nullabilitySetter = null; // error
+    // Valid write to `LegacyMixedInQ.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.textual_outline.expect
new file mode 100644
index 0000000..cb75a13
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.textual_outline.expect
@@ -0,0 +1,20 @@
+import 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+class Class extends LegacyClass implements SuperQ {
+  test() {}
+}
+
+class ClassQ extends LegacyClassQ implements Super {
+  test() {}
+}
+
+class ClassMixedIn extends LegacyMixedIn implements SuperQ {
+  test() {}
+}
+
+class ClassMixedInQ extends LegacyMixedInQ implements Super {
+  test() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ac77493
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.textual_outline_modelled.expect
@@ -0,0 +1,20 @@
+import 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+class Class extends LegacyClass implements SuperQ {
+  test() {}
+}
+
+class ClassMixedIn extends LegacyMixedIn implements SuperQ {
+  test() {}
+}
+
+class ClassMixedInQ extends LegacyMixedInQ implements Super {
+  test() {}
+}
+
+class ClassQ extends LegacyClassQ implements Super {
+  test() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.weak.expect
new file mode 100644
index 0000000..350fd3f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart.weak.expect
@@ -0,0 +1,372 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:9:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'Class' does not conform to its interface.
+// class Class /* error */ extends LegacyClass implements SuperQ {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:9:7: Context: The method 'Super.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+//   int optionalArgumentsMethod(int i) => i;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:34:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassQ' does not conform to its interface.
+// class ClassQ /* error */ extends LegacyClassQ implements Super {
+//       ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:20:8: Context: The method 'SuperQ.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+//   int? optionalArgumentsMethod(int? i) => i;
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:59:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassMixedIn' does not conform to its interface.
+// class ClassMixedIn /* error */ extends LegacyMixedIn implements SuperQ {
+//       ^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:9:7: Context: The method 'Object with Super.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+//   int optionalArgumentsMethod(int i) => i;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:59:7: Error: Class 'ClassMixedIn' inherits multiple members named 'nullabilityMethod' with incompatible signatures.
+// Try adding a declaration of 'nullabilityMethod' to 'ClassMixedIn'.
+// class ClassMixedIn /* error */ extends LegacyMixedIn implements SuperQ {
+//       ^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:6:7: Context: This is one of the overridden members.
+//   int nullabilityMethod(int i, {required int j}) => i;
+//       ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:17:8: Context: This is one of the overridden members.
+//   int? nullabilityMethod(int? i, {int? j}) => i;
+//        ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:84:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassMixedInQ' does not conform to its interface.
+// class ClassMixedInQ /* error */ extends LegacyMixedInQ implements Super {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:20:8: Context: The method 'Object with SuperQ.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+//   int? optionalArgumentsMethod(int? i) => i;
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:84:7: Error: Class 'ClassMixedInQ' inherits multiple members named 'nullabilityMethod' with incompatible signatures.
+// Try adding a declaration of 'nullabilityMethod' to 'ClassMixedInQ'.
+// class ClassMixedInQ /* error */ extends LegacyMixedInQ implements Super {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:17:8: Context: This is one of the overridden members.
+//   int? nullabilityMethod(int? i, {int? j}) => i;
+//        ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart:6:7: Context: This is one of the overridden members.
+//   int nullabilityMethod(int i, {required int j}) => i;
+//       ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:21:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:46:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:52:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+//     nullabilitySetter = null; // error
+//                         ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:63:31: Error: Required named parameter 'j' must be provided.
+//     var v1 = nullabilityMethod(null); // ok
+//                               ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:71:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:96:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+import self as self;
+import "in_out_in_lib2.dart" as in_;
+import "in_out_in_lib1.dart" as in_2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///in_out_in_lib1.dart";
+import "org-dartlang-testcase:///in_out_in_lib2.dart";
+
+class Class extends in_::LegacyClass implements in_2::SuperQ {
+  synthetic constructor •() → self::Class
+    : super in_::LegacyClass::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    core::int? v1 = this.{self::Class::nullabilityMethod}(null);
+    i = super.{in_2::Super::nullabilityMethod}(null);
+    i = this.{in_::LegacyClass::optionalArgumentsMethod}(null, null);
+    i = super.{in_2::Super::optionalArgumentsMethod}(null);
+    let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:21:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_2::Super::optionalArgumentsMethod}(null, null);
+    core::int? v2 = this.{self::Class::nullabilityGetter};
+    i = super.{in_2::Super::nullabilityGetter};
+    this.{self::Class::nullabilitySetter} = null;
+    super.{in_2::Super::nullabilitySetter} = null;
+  }
+  abstract member-signature method nullabilityMethod(core::int? i, {core::int? j = #C1}) → core::int?; -> in_2::Super::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int?; -> in_2::Super::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int? value) → void; -> in_2::Super::nullabilitySetter
+}
+class ClassQ extends in_::LegacyClassQ implements in_2::Super {
+  synthetic constructor •() → self::ClassQ
+    : super in_::LegacyClassQ::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    this.{in_::LegacyClassQ::nullabilityMethod}(null);
+    i = super.{in_2::SuperQ::nullabilityMethod}(null);
+    i = this.{in_::LegacyClassQ::optionalArgumentsMethod}(null, null);
+    i = super.{in_2::SuperQ::optionalArgumentsMethod}(null);
+    let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:46:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_2::SuperQ::optionalArgumentsMethod}(null, null);
+    i = this.{self::ClassQ::nullabilityGetter};
+    i = super.{in_2::SuperQ::nullabilityGetter};
+    this.{self::ClassQ::nullabilitySetter} = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:52:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+    nullabilitySetter = null; // error
+                        ^" in null as{TypeError,ForNonNullableByDefault} core::int;
+    super.{in_2::SuperQ::nullabilitySetter} = null;
+  }
+  abstract member-signature get nullabilityGetter() → core::int; -> in_2::SuperQ::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int value) → void; -> in_2::SuperQ::nullabilitySetter
+}
+class ClassMixedIn extends in_::LegacyMixedIn implements in_2::SuperQ {
+  synthetic constructor •() → self::ClassMixedIn
+    : super in_::LegacyMixedIn::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    invalid-type v1 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:63:31: Error: Required named parameter 'j' must be provided.
+    var v1 = nullabilityMethod(null); // ok
+                              ^" in this.{in_::_LegacyMixedIn&Object&Super::nullabilityMethod}(null);
+    i = super.{in_::_LegacyMixedIn&Object&Super::nullabilityMethod}(null);
+    i = this.{in_::LegacyMixedIn::optionalArgumentsMethod}(null, null);
+    i = super.{in_::_LegacyMixedIn&Object&Super::optionalArgumentsMethod}(null);
+    let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:71:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_::_LegacyMixedIn&Object&Super::optionalArgumentsMethod}(null, null);
+    core::int v2 = this.{in_::_LegacyMixedIn&Object&Super::nullabilityGetter};
+    i = super.{in_::_LegacyMixedIn&Object&Super::nullabilityGetter};
+    this.{self::ClassMixedIn::nullabilitySetter} = null;
+    super.{in_::_LegacyMixedIn&Object&Super::nullabilitySetter} = null;
+  }
+  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 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
+  abstract member-signature set nullabilitySetter(core::int? value) → void; -> in_2::SuperQ::nullabilitySetter
+}
+class ClassMixedInQ extends in_::LegacyMixedInQ implements in_2::Super {
+  synthetic constructor •() → self::ClassMixedInQ
+    : super in_::LegacyMixedInQ::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    this.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilityMethod}(null);
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilityMethod}(null);
+    i = this.{in_::LegacyMixedInQ::optionalArgumentsMethod}(null, null);
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::optionalArgumentsMethod}(null);
+    let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in.dart:96:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_::_LegacyMixedInQ&Object&SuperQ::optionalArgumentsMethod}(null, null);
+    i = this.{self::ClassMixedInQ::nullabilityGetter};
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilityGetter};
+    this.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilitySetter} = null;
+    super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilitySetter} = null;
+  }
+  abstract member-signature get nullabilityGetter() → core::int; -> in_2::Super::nullabilityGetter
+  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 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 method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as in_2;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → in_2::Super
+    : super core::Object::•()
+    ;
+  method nullabilityMethod(core::int i, {required core::int j = #C1}) → core::int
+    return i;
+  get nullabilityGetter() → core::int
+    return 0;
+  set nullabilitySetter(core::int value) → void {}
+  method optionalArgumentsMethod(core::int i) → core::int
+    return i;
+}
+abstract class SuperExtra extends core::Object {
+  synthetic constructor •() → in_2::SuperExtra
+    : super core::Object::•()
+    ;
+  method optionalArgumentsMethod(core::int i, [core::int? j = #C1]) → core::int
+    return i;
+}
+abstract class SuperQ extends core::Object {
+  synthetic constructor •() → in_2::SuperQ
+    : super core::Object::•()
+    ;
+  method nullabilityMethod(core::int? i, {core::int? j = #C1}) → core::int?
+    return i;
+  get nullabilityGetter() → core::int?
+    return null;
+  set nullabilitySetter(core::int? value) → void {}
+  method optionalArgumentsMethod(core::int? i) → core::int?
+    return i;
+}
+
+library;
+import self as in_;
+import "in_out_in_lib1.dart" as in_2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///in_out_in_lib1.dart";
+
+abstract class LegacyClass extends in_2::Super implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyClass*
+    : super in_2::Super::•()
+    ;
+  abstract member-signature method nullabilityMethod(core::int* i, {core::int* j = #C1}) → core::int*; -> in_2::Super::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int*; -> in_2::Super::nullabilityGetter
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+  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
+  abstract member-signature set nullabilitySetter(core::int* value) → void; -> in_2::Super::nullabilitySetter
+}
+abstract class LegacyClassQ extends in_2::SuperQ implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyClassQ*
+    : super in_2::SuperQ::•()
+    ;
+  abstract member-signature method nullabilityMethod(core::int* i, {core::int* j = #C1}) → core::int*; -> in_2::SuperQ::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int*; -> in_2::SuperQ::nullabilityGetter
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+  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
+  abstract member-signature set nullabilitySetter(core::int* value) → void; -> in_2::SuperQ::nullabilitySetter
+}
+abstract class _LegacyMixedIn&Object&Super extends core::Object implements in_2::Super /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → in_::_LegacyMixedIn&Object&Super*
+    : super core::Object::•()
+    ;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///in_out_in_lib1.dart */ nullabilityMethod(core::int i, {required core::int j = #C1}) → core::int
+    return i;
+  get /*isNonNullableByDefault, from org-dartlang-testcase:///in_out_in_lib1.dart */ nullabilityGetter() → core::int
+    return 0;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///in_out_in_lib1.dart */ optionalArgumentsMethod(core::int i) → core::int
+    return i;
+  set /*isNonNullableByDefault, from org-dartlang-testcase:///in_out_in_lib1.dart */ nullabilitySetter(core::int value) → void {}
+  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
+}
+abstract class LegacyMixedIn extends in_::_LegacyMixedIn&Object&Super implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyMixedIn*
+    : super in_::_LegacyMixedIn&Object&Super::•()
+    ;
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+}
+abstract class _LegacyMixedInQ&Object&SuperQ extends core::Object implements in_2::SuperQ /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → in_::_LegacyMixedInQ&Object&SuperQ*
+    : super core::Object::•()
+    ;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///in_out_in_lib1.dart */ nullabilityMethod(core::int? i, {core::int? j = #C1}) → core::int?
+    return i;
+  get /*isNonNullableByDefault, from org-dartlang-testcase:///in_out_in_lib1.dart */ nullabilityGetter() → core::int?
+    return null;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///in_out_in_lib1.dart */ optionalArgumentsMethod(core::int? i) → core::int?
+    return i;
+  set /*isNonNullableByDefault, from org-dartlang-testcase:///in_out_in_lib1.dart */ nullabilitySetter(core::int? value) → void {}
+  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
+}
+abstract class LegacyMixedInQ extends in_::_LegacyMixedInQ&Object&SuperQ implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyMixedInQ*
+    : super in_::_LegacyMixedInQ&Object&SuperQ::•()
+    ;
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.dart
new file mode 100644
index 0000000..62e2d4d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib1.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.
+
+class Super {
+  int nullabilityMethod(int i, {required int j}) => i;
+  int get nullabilityGetter => 0;
+  void set nullabilitySetter(int value) {}
+  int optionalArgumentsMethod(int i) => i;
+}
+
+abstract class SuperExtra {
+  int optionalArgumentsMethod(int i, [int? j]) => i;
+}
+
+abstract class SuperQ {
+  int? nullabilityMethod(int? i, {int? j}) => i;
+  int? get nullabilityGetter => null;
+  void set nullabilitySetter(int? value) {}
+  int? optionalArgumentsMethod(int? i) => i;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib2.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib2.dart
new file mode 100644
index 0000000..30166bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/in_out_in_lib2.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.
+
+// @dart=2.9
+
+import 'in_out_in_lib1.dart';
+
+abstract class LegacyClass extends Super implements SuperExtra {}
+
+abstract class LegacyClassQ extends SuperQ implements SuperExtra {}
+
+abstract class LegacyMixedIn with Super implements SuperExtra {}
+
+abstract class LegacyMixedInQ with SuperQ implements SuperExtra {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/test.options b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/test.options
new file mode 100644
index 0000000..c805a19
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_dill_out_in/test.options
@@ -0,0 +1,2 @@
+in_out_in_lib1.dart
+in_out_in_lib2.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart
new file mode 100644
index 0000000..1b3c5a2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.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 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+// Class doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class Class /* error */ extends LegacyClass implements SuperQ {
+  test() {
+    int i;
+    // Valid call to `SuperQ.nullabilityMethod`, returns int?.
+    var v1 = nullabilityMethod(null); // ok
+    // Valid super call to `LegacyClass.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `SuperQ.nullabilityGetter`, return int?.
+    var v2 = nullabilityGetter; // ok
+    // Valid read of `LegacyClass.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Valid write to `SuperQ.nullabilitySetter`.
+    nullabilitySetter = null; // ok
+    // Valid write to `LegacyClass.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassQ doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassQ /* error */ extends LegacyClassQ implements Super {
+  test() {
+    int i;
+    // Invalid call to `Super.nullabilityMethod`, returns int!.
+    nullabilityMethod(null); // error
+    // Valid call to `LegacyClassQ.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `Super.nullabilityGetter`, return int.
+    i = nullabilityGetter; // ok
+    // Valid read of `LegacyClassQ.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Invalid write to `Super.nullabilitySetter`.
+    nullabilitySetter = null; // error
+    // Valid write to `LegacyClassQ.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassMixedIn doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassMixedIn /* error */ extends LegacyMixedIn implements SuperQ {
+  test() {
+    int i;
+    // Valid call to `SuperQ.nullabilityMethod`, returns int?.
+    var v1 = nullabilityMethod(null); // ok
+    // Valid super call to `LegacyMixedIn.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `SuperQ.nullabilityGetter`, return int?.
+    var v2 = nullabilityGetter; // ok
+    // Valid read of `LegacyMixedIn.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Valid write to `SuperQ.nullabilitySetter`.
+    nullabilitySetter = null; // ok
+    // Valid write to `LegacyMixedIn.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassMixedInQ doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassMixedInQ /* error */ extends LegacyMixedInQ implements Super {
+  test() {
+    int i;
+    // Invalid call to `Super.nullabilityMethod`, returns int!.
+    nullabilityMethod(null); // error
+    // Valid call to `LegacyMixedInQ.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `Super.nullabilityGetter`, return int.
+    i = nullabilityGetter; // ok
+    // Valid read of `LegacyMixedInQ.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Invalid write to `Super.nullabilitySetter`.
+    nullabilitySetter = null; // error
+    // Valid write to `LegacyMixedInQ.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.textual_outline.expect
new file mode 100644
index 0000000..cb75a13
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.textual_outline.expect
@@ -0,0 +1,20 @@
+import 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+class Class extends LegacyClass implements SuperQ {
+  test() {}
+}
+
+class ClassQ extends LegacyClassQ implements Super {
+  test() {}
+}
+
+class ClassMixedIn extends LegacyMixedIn implements SuperQ {
+  test() {}
+}
+
+class ClassMixedInQ extends LegacyMixedInQ implements Super {
+  test() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ac77493
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.textual_outline_modelled.expect
@@ -0,0 +1,20 @@
+import 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+class Class extends LegacyClass implements SuperQ {
+  test() {}
+}
+
+class ClassMixedIn extends LegacyMixedIn implements SuperQ {
+  test() {}
+}
+
+class ClassMixedInQ extends LegacyMixedInQ implements Super {
+  test() {}
+}
+
+class ClassQ extends LegacyClassQ implements Super {
+  test() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.weak.expect
new file mode 100644
index 0000000..8700bf7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart.weak.expect
@@ -0,0 +1,355 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:9:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'Class' does not conform to its interface.
+// class Class /* error */ extends LegacyClass implements SuperQ {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.dart:9:7: Context: The method 'Super.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+//   int optionalArgumentsMethod(int i) => i;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:34:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassQ' does not conform to its interface.
+// class ClassQ /* error */ extends LegacyClassQ implements Super {
+//       ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.dart:20:8: Context: The method 'SuperQ.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+//   int? optionalArgumentsMethod(int? i) => i;
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:59:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassMixedIn' does not conform to its interface.
+// class ClassMixedIn /* error */ extends LegacyMixedIn implements SuperQ {
+//       ^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib2.dart:13:16: Context: The method 'Object with Super.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+// abstract class LegacyMixedIn with Super implements SuperExtra {}
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:84:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassMixedInQ' does not conform to its interface.
+// class ClassMixedInQ /* error */ extends LegacyMixedInQ implements Super {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib2.dart:15:16: Context: The method 'Object with SuperQ.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+// abstract class LegacyMixedInQ with SuperQ implements SuperExtra {}
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:21:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:46:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:52:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+//     nullabilitySetter = null; // error
+//                         ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:71:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:96:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:102:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+//     nullabilitySetter = null; // error
+//                         ^
+//
+import self as self;
+import "in_out_in_lib2.dart" as in_;
+import "in_out_in_lib1.dart" as in_2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///in_out_in_lib1.dart";
+import "org-dartlang-testcase:///in_out_in_lib2.dart";
+
+class Class extends in_::LegacyClass implements in_2::SuperQ {
+  synthetic constructor •() → self::Class
+    : super in_::LegacyClass::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    core::int? v1 = this.{self::Class::nullabilityMethod}(null);
+    i = super.{in_2::Super::nullabilityMethod}(null);
+    i = this.{in_::LegacyClass::optionalArgumentsMethod}(null, null);
+    i = super.{in_2::Super::optionalArgumentsMethod}(null);
+    let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:21:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_2::Super::optionalArgumentsMethod}(null, null);
+    core::int? v2 = this.{self::Class::nullabilityGetter};
+    i = super.{in_2::Super::nullabilityGetter};
+    this.{self::Class::nullabilitySetter} = null;
+    super.{in_2::Super::nullabilitySetter} = null;
+  }
+  abstract member-signature method nullabilityMethod(core::int? i, {core::int? j}) → core::int?; -> in_2::Super::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int?; -> in_2::Super::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int? value) → void; -> in_2::Super::nullabilitySetter
+}
+class ClassQ extends in_::LegacyClassQ implements in_2::Super {
+  synthetic constructor •() → self::ClassQ
+    : super in_::LegacyClassQ::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    this.{in_::LegacyClassQ::nullabilityMethod}(null);
+    i = super.{in_2::SuperQ::nullabilityMethod}(null);
+    i = this.{in_::LegacyClassQ::optionalArgumentsMethod}(null, null);
+    i = super.{in_2::SuperQ::optionalArgumentsMethod}(null);
+    let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:46:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_2::SuperQ::optionalArgumentsMethod}(null, null);
+    i = this.{self::ClassQ::nullabilityGetter};
+    i = super.{in_2::SuperQ::nullabilityGetter};
+    this.{self::ClassQ::nullabilitySetter} = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:52:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+    nullabilitySetter = null; // error
+                        ^" in null as{TypeError,ForNonNullableByDefault} core::int;
+    super.{in_2::SuperQ::nullabilitySetter} = null;
+  }
+  abstract member-signature get nullabilityGetter() → core::int; -> in_2::SuperQ::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int value) → void; -> in_2::SuperQ::nullabilitySetter
+}
+class ClassMixedIn extends in_::LegacyMixedIn implements in_2::SuperQ {
+  synthetic constructor •() → self::ClassMixedIn
+    : super in_::LegacyMixedIn::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    core::int? v1 = this.{self::ClassMixedIn::nullabilityMethod}(null);
+    i = super.{in_::_LegacyMixedIn&Object&Super::nullabilityMethod}(null);
+    i = this.{in_::LegacyMixedIn::optionalArgumentsMethod}(null, null);
+    i = super.{in_::_LegacyMixedIn&Object&Super::optionalArgumentsMethod}(null);
+    let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:71:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_::_LegacyMixedIn&Object&Super::optionalArgumentsMethod}(null, null);
+    core::int? v2 = this.{self::ClassMixedIn::nullabilityGetter};
+    i = super.{in_::_LegacyMixedIn&Object&Super::nullabilityGetter};
+    this.{self::ClassMixedIn::nullabilitySetter} = null;
+    super.{in_::_LegacyMixedIn&Object&Super::nullabilitySetter} = null;
+  }
+  abstract member-signature method nullabilityMethod(core::int? i, {core::int? j}) → core::int?; -> in_::_LegacyMixedIn&Object&Super::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int?; -> in_::_LegacyMixedIn&Object&Super::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int? value) → void; -> in_::_LegacyMixedIn&Object&Super::nullabilitySetter
+}
+class ClassMixedInQ extends in_::LegacyMixedInQ implements in_2::Super {
+  synthetic constructor •() → self::ClassMixedInQ
+    : super in_::LegacyMixedInQ::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    this.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilityMethod}(null);
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilityMethod}(null);
+    i = this.{in_::LegacyMixedInQ::optionalArgumentsMethod}(null, null);
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::optionalArgumentsMethod}(null);
+    let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:96:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_::_LegacyMixedInQ&Object&SuperQ::optionalArgumentsMethod}(null, null);
+    i = this.{self::ClassMixedInQ::nullabilityGetter};
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilityGetter};
+    this.{self::ClassMixedInQ::nullabilitySetter} = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in.dart:102:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+    nullabilitySetter = null; // error
+                        ^" in null as{TypeError,ForNonNullableByDefault} core::int;
+    super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilitySetter} = null;
+  }
+  abstract member-signature get nullabilityGetter() → core::int; -> in_::_LegacyMixedInQ&Object&SuperQ::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int value) → void; -> in_::_LegacyMixedInQ&Object&SuperQ::nullabilitySetter
+}
+static method main() → dynamic {}
+
+library;
+import self as in_;
+import "in_out_in_lib1.dart" as in_2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///in_out_in_lib1.dart";
+
+abstract class LegacyClass extends in_2::Super implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyClass*
+    : super in_2::Super::•()
+    ;
+  abstract member-signature method nullabilityMethod(core::int* i, {core::int* j = #C1}) → core::int*; -> in_2::Super::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int*; -> in_2::Super::nullabilityGetter
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+  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
+  abstract member-signature set nullabilitySetter(core::int* value) → void; -> in_2::Super::nullabilitySetter
+}
+abstract class LegacyClassQ extends in_2::SuperQ implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyClassQ*
+    : super in_2::SuperQ::•()
+    ;
+  abstract member-signature method nullabilityMethod(core::int* i, {core::int* j = #C1}) → core::int*; -> in_2::SuperQ::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int*; -> in_2::SuperQ::nullabilityGetter
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+  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
+  abstract member-signature set nullabilitySetter(core::int* value) → void; -> in_2::SuperQ::nullabilitySetter
+}
+abstract class _LegacyMixedIn&Object&Super = core::Object with in_2::Super /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → in_::_LegacyMixedIn&Object&Super*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method nullabilityMethod(core::int* i, {core::int* j = #C1}) → core::int*
+    return super.{in_2::Super::nullabilityMethod}(i, j: j);
+  mixin-super-stub get nullabilityGetter() → core::int*
+    return super.{in_2::Super::nullabilityGetter};
+  mixin-super-stub method optionalArgumentsMethod(core::int* i) → core::int*
+    return super.{in_2::Super::optionalArgumentsMethod}(i);
+  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
+  mixin-super-stub set nullabilitySetter(core::int* value) → void
+    return super.{in_2::Super::nullabilitySetter} = value;
+}
+abstract class LegacyMixedIn extends in_::_LegacyMixedIn&Object&Super implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyMixedIn*
+    : super in_::_LegacyMixedIn&Object&Super::•()
+    ;
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+}
+abstract class _LegacyMixedInQ&Object&SuperQ = core::Object with in_2::SuperQ /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → in_::_LegacyMixedInQ&Object&SuperQ*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method nullabilityMethod(core::int* i, {core::int* j = #C1}) → core::int*
+    return super.{in_2::SuperQ::nullabilityMethod}(i, j: j);
+  mixin-super-stub get nullabilityGetter() → core::int*
+    return super.{in_2::SuperQ::nullabilityGetter};
+  mixin-super-stub method optionalArgumentsMethod(core::int* i) → core::int*
+    return super.{in_2::SuperQ::optionalArgumentsMethod}(i);
+  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
+  mixin-super-stub set nullabilitySetter(core::int* value) → void
+    return super.{in_2::SuperQ::nullabilitySetter} = value;
+}
+abstract class LegacyMixedInQ extends in_::_LegacyMixedInQ&Object&SuperQ implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyMixedInQ*
+    : super in_::_LegacyMixedInQ&Object&SuperQ::•()
+    ;
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+}
+
+library /*isNonNullableByDefault*/;
+import self as in_2;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → in_2::Super
+    : super core::Object::•()
+    ;
+  method nullabilityMethod(core::int i, {required core::int j = #C1}) → core::int
+    return i;
+  get nullabilityGetter() → core::int
+    return 0;
+  set nullabilitySetter(core::int value) → void {}
+  method optionalArgumentsMethod(core::int i) → core::int
+    return i;
+}
+abstract class SuperExtra extends core::Object {
+  synthetic constructor •() → in_2::SuperExtra
+    : super core::Object::•()
+    ;
+  method optionalArgumentsMethod(core::int i, [core::int? j = #C1]) → core::int
+    return i;
+}
+abstract class SuperQ extends core::Object {
+  synthetic constructor •() → in_2::SuperQ
+    : super core::Object::•()
+    ;
+  method nullabilityMethod(core::int? i, {core::int? j = #C1}) → core::int?
+    return i;
+  get nullabilityGetter() → core::int?
+    return null;
+  set nullabilitySetter(core::int? value) → void {}
+  method optionalArgumentsMethod(core::int? i) → core::int?
+    return i;
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.dart
new file mode 100644
index 0000000..62e2d4d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib1.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.
+
+class Super {
+  int nullabilityMethod(int i, {required int j}) => i;
+  int get nullabilityGetter => 0;
+  void set nullabilitySetter(int value) {}
+  int optionalArgumentsMethod(int i) => i;
+}
+
+abstract class SuperExtra {
+  int optionalArgumentsMethod(int i, [int? j]) => i;
+}
+
+abstract class SuperQ {
+  int? nullabilityMethod(int? i, {int? j}) => i;
+  int? get nullabilityGetter => null;
+  void set nullabilitySetter(int? value) {}
+  int? optionalArgumentsMethod(int? i) => i;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib2.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib2.dart
new file mode 100644
index 0000000..30166bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/in_out_in_lib2.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.
+
+// @dart=2.9
+
+import 'in_out_in_lib1.dart';
+
+abstract class LegacyClass extends Super implements SuperExtra {}
+
+abstract class LegacyClassQ extends SuperQ implements SuperExtra {}
+
+abstract class LegacyMixedIn with Super implements SuperExtra {}
+
+abstract class LegacyMixedInQ with SuperQ implements SuperExtra {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/test.options b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/test.options
new file mode 100644
index 0000000..75b6249
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_dill_in/test.options
@@ -0,0 +1 @@
+in_out_in_lib1.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart
new file mode 100644
index 0000000..1b3c5a2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.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 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+// Class doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class Class /* error */ extends LegacyClass implements SuperQ {
+  test() {
+    int i;
+    // Valid call to `SuperQ.nullabilityMethod`, returns int?.
+    var v1 = nullabilityMethod(null); // ok
+    // Valid super call to `LegacyClass.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `SuperQ.nullabilityGetter`, return int?.
+    var v2 = nullabilityGetter; // ok
+    // Valid read of `LegacyClass.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Valid write to `SuperQ.nullabilitySetter`.
+    nullabilitySetter = null; // ok
+    // Valid write to `LegacyClass.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassQ doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassQ /* error */ extends LegacyClassQ implements Super {
+  test() {
+    int i;
+    // Invalid call to `Super.nullabilityMethod`, returns int!.
+    nullabilityMethod(null); // error
+    // Valid call to `LegacyClassQ.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `Super.nullabilityGetter`, return int.
+    i = nullabilityGetter; // ok
+    // Valid read of `LegacyClassQ.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Invalid write to `Super.nullabilitySetter`.
+    nullabilitySetter = null; // error
+    // Valid write to `LegacyClassQ.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassMixedIn doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassMixedIn /* error */ extends LegacyMixedIn implements SuperQ {
+  test() {
+    int i;
+    // Valid call to `SuperQ.nullabilityMethod`, returns int?.
+    var v1 = nullabilityMethod(null); // ok
+    // Valid super call to `LegacyMixedIn.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `SuperQ.nullabilityGetter`, return int?.
+    var v2 = nullabilityGetter; // ok
+    // Valid read of `LegacyMixedIn.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Valid write to `SuperQ.nullabilitySetter`.
+    nullabilitySetter = null; // ok
+    // Valid write to `LegacyMixedIn.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+// ClassMixedInQ doesn't implement `SuperExtra.optionalArgumentsMethod`.
+class ClassMixedInQ /* error */ extends LegacyMixedInQ implements Super {
+  test() {
+    int i;
+    // Invalid call to `Super.nullabilityMethod`, returns int!.
+    nullabilityMethod(null); // error
+    // Valid call to `LegacyMixedInQ.nullabilityMethod`, returns int*.
+    i = super.nullabilityMethod(null); // ok
+    // Valid call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = optionalArgumentsMethod(null, null); // ok
+    // Valid super call to `SuperExtra.optionalArgumentsMethod`, returns int*.
+    i = super.optionalArgumentsMethod(null); // ok
+    // Invalid super call to `SuperExtra.optionalArgumentsMethod`.
+    super.optionalArgumentsMethod(null, null); // error
+    // Read of `Super.nullabilityGetter`, return int.
+    i = nullabilityGetter; // ok
+    // Valid read of `LegacyMixedInQ.nullabilityGetter`, return int*.
+    i = super.nullabilityGetter; // ok
+    // Invalid write to `Super.nullabilitySetter`.
+    nullabilitySetter = null; // error
+    // Valid write to `LegacyMixedInQ.nullabilitySetter`.
+    super.nullabilitySetter = null; // ok
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.textual_outline.expect
new file mode 100644
index 0000000..cb75a13
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.textual_outline.expect
@@ -0,0 +1,20 @@
+import 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+class Class extends LegacyClass implements SuperQ {
+  test() {}
+}
+
+class ClassQ extends LegacyClassQ implements Super {
+  test() {}
+}
+
+class ClassMixedIn extends LegacyMixedIn implements SuperQ {
+  test() {}
+}
+
+class ClassMixedInQ extends LegacyMixedInQ implements Super {
+  test() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ac77493
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.textual_outline_modelled.expect
@@ -0,0 +1,20 @@
+import 'in_out_in_lib1.dart';
+import 'in_out_in_lib2.dart';
+
+class Class extends LegacyClass implements SuperQ {
+  test() {}
+}
+
+class ClassMixedIn extends LegacyMixedIn implements SuperQ {
+  test() {}
+}
+
+class ClassMixedInQ extends LegacyMixedInQ implements Super {
+  test() {}
+}
+
+class ClassQ extends LegacyClassQ implements Super {
+  test() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.weak.expect
new file mode 100644
index 0000000..68209cb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.weak.expect
@@ -0,0 +1,369 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:9:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'Class' does not conform to its interface.
+// class Class /* error */ extends LegacyClass implements SuperQ {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.dart:9:7: Context: The method 'Super.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+//   int optionalArgumentsMethod(int i) => i;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:34:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassQ' does not conform to its interface.
+// class ClassQ /* error */ extends LegacyClassQ implements Super {
+//       ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.dart:20:8: Context: The method 'SuperQ.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+//   int? optionalArgumentsMethod(int? i) => i;
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:59:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassMixedIn' does not conform to its interface.
+// class ClassMixedIn /* error */ extends LegacyMixedIn implements SuperQ {
+//       ^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib2.dart:13:16: Context: The method 'Object with Super.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+// abstract class LegacyMixedIn with Super implements SuperExtra {}
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:84:7: Error: The implementation of 'optionalArgumentsMethod' in the non-abstract class 'ClassMixedInQ' does not conform to its interface.
+// class ClassMixedInQ /* error */ extends LegacyMixedInQ implements Super {
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib2.dart:15:16: Context: The method 'Object with SuperQ.optionalArgumentsMethod' has fewer positional arguments than those of overridden method 'SuperExtra.optionalArgumentsMethod'.
+// abstract class LegacyMixedInQ with SuperQ implements SuperExtra {}
+//                ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.dart:13:7: Context: This is the overridden method ('optionalArgumentsMethod').
+//   int optionalArgumentsMethod(int i, [int? j]) => i;
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:21:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:38:23: Error: The value 'null' can't be assigned to the parameter type 'int' because 'int' is not nullable.
+//     nullabilityMethod(null); // error
+//                       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:46:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:52:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+//     nullabilitySetter = null; // error
+//                         ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:71:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:88:23: Error: The value 'null' can't be assigned to the parameter type 'int' because 'int' is not nullable.
+//     nullabilityMethod(null); // error
+//                       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:96:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     super.optionalArgumentsMethod(null, null); // error
+//                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:102:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+//     nullabilitySetter = null; // error
+//                         ^
+//
+import self as self;
+import "in_out_in_lib2.dart" as in_;
+import "in_out_in_lib1.dart" as in_2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///in_out_in_lib1.dart";
+import "org-dartlang-testcase:///in_out_in_lib2.dart";
+
+class Class extends in_::LegacyClass implements in_2::SuperQ {
+  synthetic constructor •() → self::Class
+    : super in_::LegacyClass::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    core::int? v1 = this.{self::Class::nullabilityMethod}(null);
+    i = super.{in_2::Super::nullabilityMethod}(null);
+    i = this.{in_::LegacyClass::optionalArgumentsMethod}(null, null);
+    i = super.{in_2::Super::optionalArgumentsMethod}(null);
+    let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:21:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_2::Super::optionalArgumentsMethod}(null, null);
+    core::int? v2 = this.{self::Class::nullabilityGetter};
+    i = super.{in_2::Super::nullabilityGetter};
+    this.{self::Class::nullabilitySetter} = null;
+    super.{in_2::Super::nullabilitySetter} = null;
+  }
+  abstract member-signature method nullabilityMethod(core::int? i) → core::int?; -> in_2::Super::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int?; -> in_2::Super::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int? value) → void; -> in_2::Super::nullabilitySetter
+}
+class ClassQ extends in_::LegacyClassQ implements in_2::Super {
+  synthetic constructor •() → self::ClassQ
+    : super in_::LegacyClassQ::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    this.{self::ClassQ::nullabilityMethod}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:38:23: Error: The value 'null' can't be assigned to the parameter type 'int' because 'int' is not nullable.
+    nullabilityMethod(null); // error
+                      ^" in null as{TypeError,ForNonNullableByDefault} core::int);
+    i = super.{in_2::SuperQ::nullabilityMethod}(null);
+    i = this.{in_::LegacyClassQ::optionalArgumentsMethod}(null, null);
+    i = super.{in_2::SuperQ::optionalArgumentsMethod}(null);
+    let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:46:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_2::SuperQ::optionalArgumentsMethod}(null, null);
+    i = this.{self::ClassQ::nullabilityGetter};
+    i = super.{in_2::SuperQ::nullabilityGetter};
+    this.{self::ClassQ::nullabilitySetter} = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:52:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+    nullabilitySetter = null; // error
+                        ^" in null as{TypeError,ForNonNullableByDefault} core::int;
+    super.{in_2::SuperQ::nullabilitySetter} = null;
+  }
+  abstract member-signature method nullabilityMethod(core::int i) → core::int; -> in_2::SuperQ::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int; -> in_2::SuperQ::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int value) → void; -> in_2::SuperQ::nullabilitySetter
+}
+class ClassMixedIn extends in_::LegacyMixedIn implements in_2::SuperQ {
+  synthetic constructor •() → self::ClassMixedIn
+    : super in_::LegacyMixedIn::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    core::int? v1 = this.{self::ClassMixedIn::nullabilityMethod}(null);
+    i = super.{in_::_LegacyMixedIn&Object&Super::nullabilityMethod}(null);
+    i = this.{in_::LegacyMixedIn::optionalArgumentsMethod}(null, null);
+    i = super.{in_::_LegacyMixedIn&Object&Super::optionalArgumentsMethod}(null);
+    let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:71:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_::_LegacyMixedIn&Object&Super::optionalArgumentsMethod}(null, null);
+    core::int? v2 = this.{self::ClassMixedIn::nullabilityGetter};
+    i = super.{in_::_LegacyMixedIn&Object&Super::nullabilityGetter};
+    this.{self::ClassMixedIn::nullabilitySetter} = null;
+    super.{in_::_LegacyMixedIn&Object&Super::nullabilitySetter} = null;
+  }
+  abstract member-signature method nullabilityMethod(core::int? i) → core::int?; -> in_::_LegacyMixedIn&Object&Super::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int?; -> in_::_LegacyMixedIn&Object&Super::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int? value) → void; -> in_::_LegacyMixedIn&Object&Super::nullabilitySetter
+}
+class ClassMixedInQ extends in_::LegacyMixedInQ implements in_2::Super {
+  synthetic constructor •() → self::ClassMixedInQ
+    : super in_::LegacyMixedInQ::•()
+    ;
+  method test() → dynamic {
+    core::int i;
+    this.{self::ClassMixedInQ::nullabilityMethod}(let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:88:23: Error: The value 'null' can't be assigned to the parameter type 'int' because 'int' is not nullable.
+    nullabilityMethod(null); // error
+                      ^" in null as{TypeError,ForNonNullableByDefault} core::int);
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilityMethod}(null);
+    i = this.{in_::LegacyMixedInQ::optionalArgumentsMethod}(null, null);
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::optionalArgumentsMethod}(null);
+    let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:96:34: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+    super.optionalArgumentsMethod(null, null); // error
+                                 ^" in super.{in_::_LegacyMixedInQ&Object&SuperQ::optionalArgumentsMethod}(null, null);
+    i = this.{self::ClassMixedInQ::nullabilityGetter};
+    i = super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilityGetter};
+    this.{self::ClassMixedInQ::nullabilitySetter} = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart:102:25: Error: The value 'null' can't be assigned to a variable of type 'int' because 'int' is not nullable.
+    nullabilitySetter = null; // error
+                        ^" in null as{TypeError,ForNonNullableByDefault} core::int;
+    super.{in_::_LegacyMixedInQ&Object&SuperQ::nullabilitySetter} = null;
+  }
+  abstract member-signature method nullabilityMethod(core::int i) → core::int; -> in_::_LegacyMixedInQ&Object&SuperQ::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int; -> in_::_LegacyMixedInQ&Object&SuperQ::nullabilityGetter
+  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 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
+  abstract member-signature set nullabilitySetter(core::int value) → void; -> in_::_LegacyMixedInQ&Object&SuperQ::nullabilitySetter
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as in_2;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → in_2::Super
+    : super core::Object::•()
+    ;
+  method nullabilityMethod(core::int i) → core::int
+    return i;
+  get nullabilityGetter() → core::int
+    return 0;
+  set nullabilitySetter(core::int value) → void {}
+  method optionalArgumentsMethod(core::int i) → core::int
+    return i;
+}
+abstract class SuperExtra extends core::Object {
+  synthetic constructor •() → in_2::SuperExtra
+    : super core::Object::•()
+    ;
+  method optionalArgumentsMethod(core::int i, [core::int? j = #C1]) → core::int
+    return i;
+}
+abstract class SuperQ extends core::Object {
+  synthetic constructor •() → in_2::SuperQ
+    : super core::Object::•()
+    ;
+  method nullabilityMethod(core::int? i) → core::int?
+    return i;
+  get nullabilityGetter() → core::int?
+    return null;
+  set nullabilitySetter(core::int? value) → void {}
+  method optionalArgumentsMethod(core::int? i) → core::int?
+    return i;
+}
+
+library;
+import self as in_;
+import "in_out_in_lib1.dart" as in_2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///in_out_in_lib1.dart";
+
+abstract class LegacyClass extends in_2::Super implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyClass*
+    : super in_2::Super::•()
+    ;
+  abstract member-signature method nullabilityMethod(core::int* i) → core::int*; -> in_2::Super::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int*; -> in_2::Super::nullabilityGetter
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+  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
+  abstract member-signature set nullabilitySetter(core::int* value) → void; -> in_2::Super::nullabilitySetter
+}
+abstract class LegacyClassQ extends in_2::SuperQ implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyClassQ*
+    : super in_2::SuperQ::•()
+    ;
+  abstract member-signature method nullabilityMethod(core::int* i) → core::int*; -> in_2::SuperQ::nullabilityMethod
+  abstract member-signature get nullabilityGetter() → core::int*; -> in_2::SuperQ::nullabilityGetter
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+  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
+  abstract member-signature set nullabilitySetter(core::int* value) → void; -> in_2::SuperQ::nullabilitySetter
+}
+abstract class _LegacyMixedIn&Object&Super = core::Object with in_2::Super /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → in_::_LegacyMixedIn&Object&Super*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method nullabilityMethod(core::int* i) → core::int*
+    return super.{in_2::Super::nullabilityMethod}(i);
+  mixin-super-stub get nullabilityGetter() → core::int*
+    return super.{in_2::Super::nullabilityGetter};
+  mixin-super-stub method optionalArgumentsMethod(core::int* i) → core::int*
+    return super.{in_2::Super::optionalArgumentsMethod}(i);
+  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
+  mixin-super-stub set nullabilitySetter(core::int* value) → void
+    return super.{in_2::Super::nullabilitySetter} = value;
+}
+abstract class LegacyMixedIn extends in_::_LegacyMixedIn&Object&Super implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyMixedIn*
+    : super in_::_LegacyMixedIn&Object&Super::•()
+    ;
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+}
+abstract class _LegacyMixedInQ&Object&SuperQ = core::Object with in_2::SuperQ /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → in_::_LegacyMixedInQ&Object&SuperQ*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method nullabilityMethod(core::int* i) → core::int*
+    return super.{in_2::SuperQ::nullabilityMethod}(i);
+  mixin-super-stub get nullabilityGetter() → core::int*
+    return super.{in_2::SuperQ::nullabilityGetter};
+  mixin-super-stub method optionalArgumentsMethod(core::int* i) → core::int*
+    return super.{in_2::SuperQ::optionalArgumentsMethod}(i);
+  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
+  mixin-super-stub set nullabilitySetter(core::int* value) → void
+    return super.{in_2::SuperQ::nullabilitySetter} = value;
+}
+abstract class LegacyMixedInQ extends in_::_LegacyMixedInQ&Object&SuperQ implements in_2::SuperExtra {
+  synthetic constructor •() → in_::LegacyMixedInQ*
+    : super in_::_LegacyMixedInQ&Object&SuperQ::•()
+    ;
+  abstract member-signature method optionalArgumentsMethod(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperExtra::optionalArgumentsMethod
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..551f480
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in.dart.weak.transformed.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "in_out_in_lib2.dart" as in_;
+import "in_out_in_lib1.dart" as in_2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///in_out_in_lib1.dart";
+import "org-dartlang-testcase:///in_out_in_lib2.dart";
+
+class Class extends in_::LegacyClass implements in_2::SuperQ {
+  synthetic constructor •() → self::Class
+    : super in_::LegacyClass::•()
+    ;
+  abstract member-signature method method(core::int? i) → core::int?; -> in_2::Super::method
+  abstract member-signature method method2(core::int i, [core::int? j = #C1]) → core::int; -> in_2::SuperQ::method2
+  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 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
+}
+class ClassQ extends in_::LegacyClassQ implements in_2::Super {
+  synthetic constructor •() → self::ClassQ
+    : super in_::LegacyClassQ::•()
+    ;
+  abstract member-signature method method(core::int i) → core::int; -> in_2::SuperQ::method
+  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 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 method main() → dynamic {
+  new self::Class::•().{self::Class::method2}(0, 0);
+}
+
+library /*isNonNullableByDefault*/;
+import self as in_2;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → in_2::Super
+    : super core::Object::•()
+    ;
+  method method(core::int i) → core::int
+    return i;
+  method method2(core::int i) → core::int
+    return i;
+}
+abstract class SuperQ extends core::Object {
+  synthetic constructor •() → in_2::SuperQ
+    : super core::Object::•()
+    ;
+  method method(core::int? i) → core::int?
+    return i;
+  method method2(core::int i, [core::int? j = #C1]) → core::int
+    return i;
+}
+
+library;
+import self as in_;
+import "in_out_in_lib1.dart" as in_2;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///in_out_in_lib1.dart";
+
+class LegacyClass extends in_2::Super {
+  synthetic constructor •() → in_::LegacyClass*
+    : super in_2::Super::•()
+    ;
+  abstract member-signature method method(core::int* i) → core::int*; -> in_2::Super::method
+  abstract member-signature method method2(core::int* i) → core::int*; -> in_2::Super::method2
+  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
+}
+class LegacyClassQ extends in_2::SuperQ {
+  synthetic constructor •() → in_::LegacyClassQ*
+    : super in_2::SuperQ::•()
+    ;
+  abstract member-signature method method(core::int* i) → core::int*; -> in_2::SuperQ::method
+  abstract member-signature method method2(core::int* i, [core::int* j = #C1]) → core::int*; -> in_2::SuperQ::method2
+  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
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.dart
new file mode 100644
index 0000000..b182a1b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib1.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.
+
+class Super {
+  int nullabilityMethod(int i) => i;
+  int get nullabilityGetter => 0;
+  void set nullabilitySetter(int value) {}
+  int optionalArgumentsMethod(int i) => i;
+}
+
+abstract class SuperExtra {
+  int optionalArgumentsMethod(int i, [int? j]) => i;
+}
+
+abstract class SuperQ {
+  int? nullabilityMethod(int? i) => i;
+  int? get nullabilityGetter => null;
+  void set nullabilitySetter(int? value) {}
+  int? optionalArgumentsMethod(int? i) => i;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib2.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib2.dart
new file mode 100644
index 0000000..30166bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/in_out_in_lib2.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.
+
+// @dart=2.9
+
+import 'in_out_in_lib1.dart';
+
+abstract class LegacyClass extends Super implements SuperExtra {}
+
+abstract class LegacyClassQ extends SuperQ implements SuperExtra {}
+
+abstract class LegacyMixedIn with Super implements SuperExtra {}
+
+abstract class LegacyMixedInQ with SuperQ implements SuperExtra {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart
new file mode 100644
index 0000000..1a5a9c2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart
@@ -0,0 +1,68 @@
+// 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 Super {
+  num extendedMethod() => 0;
+}
+
+class Mixin {
+  num mixedInMethod() => 0;
+}
+
+abstract class Interface1 {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+abstract class Interface2 extends Super with Mixin {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+class ClassExtends extends Super with Mixin implements Interface1 {}
+
+class ClassExtendsWithNoSuchMethod extends Super
+    with Mixin
+    implements Interface1 {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class ClassImplements implements Interface2 {}
+
+class ClassImplementsWithNoSuchMethod implements Interface2 {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+}
+
+class ClassDeclaresExtends extends Super with Mixin {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+class ClassDeclaresImplementsWithNoSuchMethod implements Super, Mixin {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.textual_outline.expect
new file mode 100644
index 0000000..37ad3f0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.textual_outline.expect
@@ -0,0 +1,54 @@
+class Super {
+  num extendedMethod() => 0;
+}
+
+class Mixin {
+  num mixedInMethod() => 0;
+}
+
+abstract class Interface1 {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+abstract class Interface2 extends Super with Mixin {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+class ClassExtends extends Super with Mixin implements Interface1 {}
+
+class ClassExtendsWithNoSuchMethod extends Super
+    with Mixin
+    implements Interface1 {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class ClassImplements implements Interface2 {}
+
+class ClassImplementsWithNoSuchMethod implements Interface2 {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class ClassDeclaresExtends extends Super with Mixin {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+  @override
+  noSuchMethod(Invocation invocation) {}
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+class ClassDeclaresImplementsWithNoSuchMethod implements Super, Mixin {
+  @override
+  noSuchMethod(Invocation invocation) {}
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..47ed758
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.textual_outline_modelled.expect
@@ -0,0 +1,54 @@
+abstract class Interface1 {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+abstract class Interface2 extends Super with Mixin {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+class ClassDeclaresExtends extends Super with Mixin {
+  int extendedMethod();
+  int mixedInMethod();
+}
+
+class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+  int extendedMethod();
+  int mixedInMethod();
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class ClassDeclaresImplementsWithNoSuchMethod implements Super, Mixin {
+  int extendedMethod();
+  int mixedInMethod();
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class ClassExtends extends Super with Mixin implements Interface1 {}
+
+class ClassExtendsWithNoSuchMethod extends Super
+    with Mixin
+    implements Interface1 {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class ClassImplements implements Interface2 {}
+
+class ClassImplementsWithNoSuchMethod implements Interface2 {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class Mixin {
+  num mixedInMethod() => 0;
+}
+
+class Super {
+  num extendedMethod() => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.weak.expect
new file mode 100644
index 0000000..4124088
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.weak.expect
@@ -0,0 +1,265 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:34:7: Error: The non-abstract class 'ClassImplements' is missing implementations for these members:
+//  - Interface2.extendedMethod
+//  - Interface2.mixedInMethod
+//  - Mixin.mixedInMethod
+//  - Super with Mixin.mixedInMethod
+//  - Super.extendedMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassImplements implements Interface2 {}
+//       ^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:19:7: Context: 'Interface2.extendedMethod' is defined here.
+//   int extendedMethod();
+//       ^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:20:7: Context: 'Interface2.mixedInMethod' is defined here.
+//   int mixedInMethod();
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:10:7: Context: 'Mixin.mixedInMethod' is defined here.
+//   num mixedInMethod() => 0;
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:10:7: Context: 'Super with Mixin.mixedInMethod' is defined here.
+//   num mixedInMethod() => 0;
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: 'Super.extendedMethod' is defined here.
+//   num extendedMethod() => 0;
+//       ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:23:7: Error: The implementation of 'mixedInMethod' in the non-abstract class 'ClassExtends' does not conform to its interface.
+// class ClassExtends extends Super with Mixin implements Interface1 {}
+//       ^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:23:7: Context: The return type of the method 'Super with Mixin.mixedInMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface1.mixedInMethod'.
+// Change to a subtype of 'int'.
+// class ClassExtends extends Super with Mixin implements Interface1 {}
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:15:7: Context: This is the overridden method ('mixedInMethod').
+//   int mixedInMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:23:7: Error: The implementation of 'extendedMethod' in the non-abstract class 'ClassExtends' does not conform to its interface.
+// class ClassExtends extends Super with Mixin implements Interface1 {}
+//       ^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: The return type of the method 'Super.extendedMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface1.extendedMethod'.
+// Change to a subtype of 'int'.
+//   num extendedMethod() => 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:14:7: Context: This is the overridden method ('extendedMethod').
+//   int extendedMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:25:7: Error: The implementation of 'mixedInMethod' in the non-abstract class 'ClassExtendsWithNoSuchMethod' does not conform to its interface.
+// class ClassExtendsWithNoSuchMethod extends Super
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:25:7: Context: The return type of the method 'Super with Mixin.mixedInMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface1.mixedInMethod'.
+// Change to a subtype of 'int'.
+// class ClassExtendsWithNoSuchMethod extends Super
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:15:7: Context: This is the overridden method ('mixedInMethod').
+//   int mixedInMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:25:7: Error: The implementation of 'extendedMethod' in the non-abstract class 'ClassExtendsWithNoSuchMethod' does not conform to its interface.
+// class ClassExtendsWithNoSuchMethod extends Super
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: The return type of the method 'Super.extendedMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface1.extendedMethod'.
+// Change to a subtype of 'int'.
+//   num extendedMethod() => 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:14:7: Context: This is the overridden method ('extendedMethod').
+//   int extendedMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:43:7: Error: The implementation of 'extendedMethod' in the non-abstract class 'ClassDeclaresExtends' does not conform to its interface.
+// class ClassDeclaresExtends extends Super with Mixin {
+//       ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: The return type of the method 'Super.extendedMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'ClassDeclaresExtends.extendedMethod'.
+// Change to a subtype of 'int'.
+//   num extendedMethod() => 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:44:7: Context: This is the overridden method ('extendedMethod').
+//   int extendedMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:43:7: Error: The implementation of 'mixedInMethod' in the non-abstract class 'ClassDeclaresExtends' does not conform to its interface.
+// class ClassDeclaresExtends extends Super with Mixin {
+//       ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:43:7: Context: The return type of the method 'Super with Mixin.mixedInMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'ClassDeclaresExtends.mixedInMethod'.
+// Change to a subtype of 'int'.
+// class ClassDeclaresExtends extends Super with Mixin {
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:45:7: Context: This is the overridden method ('mixedInMethod').
+//   int mixedInMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:48:7: Error: The implementation of 'extendedMethod' in the non-abstract class 'ClassDeclaresExtendsWithNoSuchMethod' does not conform to its interface.
+// class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: The return type of the method 'Super.extendedMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'ClassDeclaresExtendsWithNoSuchMethod.extendedMethod'.
+// Change to a subtype of 'int'.
+//   num extendedMethod() => 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:54:7: Context: This is the overridden method ('extendedMethod').
+//   int extendedMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:48:7: Error: The implementation of 'mixedInMethod' in the non-abstract class 'ClassDeclaresExtendsWithNoSuchMethod' does not conform to its interface.
+// class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:48:7: Context: The return type of the method 'Super with Mixin.mixedInMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'ClassDeclaresExtendsWithNoSuchMethod.mixedInMethod'.
+// Change to a subtype of 'int'.
+// class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:55:7: Context: This is the overridden method ('mixedInMethod').
+//   int mixedInMethod();
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedMethod() → core::num
+    return 0;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method mixedInMethod() → core::num
+    return 0;
+}
+abstract class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  abstract method extendedMethod() → core::int;
+  abstract method mixedInMethod() → core::int;
+}
+abstract class _Interface2&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Interface2&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInMethod() → core::num
+    return super.{self::Mixin::mixedInMethod}();
+}
+abstract class Interface2 extends self::_Interface2&Super&Mixin {
+  synthetic constructor •() → self::Interface2
+    : super self::_Interface2&Super&Mixin::•()
+    ;
+  abstract method extendedMethod() → core::int;
+  abstract method mixedInMethod() → core::int;
+}
+abstract class _ClassExtends&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassExtends&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInMethod() → core::num
+    return super.{self::Mixin::mixedInMethod}();
+}
+class ClassExtends extends self::_ClassExtends&Super&Mixin implements self::Interface1 {
+  synthetic constructor •() → self::ClassExtends
+    : super self::_ClassExtends&Super&Mixin::•()
+    ;
+  abstract member-signature method mixedInMethod() → core::int; -> self::Interface1::mixedInMethod
+  abstract member-signature method extendedMethod() → core::int; -> self::Interface1::extendedMethod
+}
+abstract class _ClassExtendsWithNoSuchMethod&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassExtendsWithNoSuchMethod&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInMethod() → core::num
+    return super.{self::Mixin::mixedInMethod}();
+}
+class ClassExtendsWithNoSuchMethod extends self::_ClassExtendsWithNoSuchMethod&Super&Mixin implements self::Interface1 {
+  synthetic constructor •() → self::ClassExtendsWithNoSuchMethod
+    : super self::_ClassExtendsWithNoSuchMethod&Super&Mixin::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract member-signature method mixedInMethod() → core::int; -> self::Interface1::mixedInMethod
+  abstract member-signature method extendedMethod() → core::int; -> self::Interface1::extendedMethod
+}
+class ClassImplements extends core::Object implements self::Interface2 {
+  synthetic constructor •() → self::ClassImplements
+    : super core::Object::•()
+    ;
+}
+class ClassImplementsWithNoSuchMethod extends core::Object implements self::Interface2 {
+  synthetic constructor •() → self::ClassImplementsWithNoSuchMethod
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  no-such-method-forwarder method mixedInMethod() → core::int
+    return this.{self::ClassImplementsWithNoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method extendedMethod() → core::int
+    return this.{self::ClassImplementsWithNoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+}
+abstract class _ClassDeclaresExtends&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassDeclaresExtends&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInMethod() → core::num
+    return super.{self::Mixin::mixedInMethod}();
+}
+class ClassDeclaresExtends extends self::_ClassDeclaresExtends&Super&Mixin {
+  synthetic constructor •() → self::ClassDeclaresExtends
+    : super self::_ClassDeclaresExtends&Super&Mixin::•()
+    ;
+  abstract method extendedMethod() → core::int;
+  abstract method mixedInMethod() → core::int;
+}
+abstract class _ClassDeclaresExtendsWithNoSuchMethod&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassDeclaresExtendsWithNoSuchMethod&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInMethod() → core::num
+    return super.{self::Mixin::mixedInMethod}();
+}
+class ClassDeclaresExtendsWithNoSuchMethod extends self::_ClassDeclaresExtendsWithNoSuchMethod&Super&Mixin {
+  synthetic constructor •() → self::ClassDeclaresExtendsWithNoSuchMethod
+    : super self::_ClassDeclaresExtendsWithNoSuchMethod&Super&Mixin::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract method extendedMethod() → core::int;
+  abstract method mixedInMethod() → core::int;
+}
+class ClassDeclaresImplementsWithNoSuchMethod extends core::Object implements self::Super, self::Mixin {
+  synthetic constructor •() → self::ClassDeclaresImplementsWithNoSuchMethod
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  no-such-method-forwarder method extendedMethod() → core::int
+    return this.{self::ClassDeclaresImplementsWithNoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method mixedInMethod() → core::int
+    return this.{self::ClassDeclaresImplementsWithNoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = #mixedInMethod
+  #C3 = <core::Type*>[]
+  #C4 = <dynamic>[]
+  #C5 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C4}
+  #C6 = #extendedMethod
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.weak.transformed.expect
new file mode 100644
index 0000000..b0ede7c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart.weak.transformed.expect
@@ -0,0 +1,265 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:34:7: Error: The non-abstract class 'ClassImplements' is missing implementations for these members:
+//  - Interface2.extendedMethod
+//  - Interface2.mixedInMethod
+//  - Mixin.mixedInMethod
+//  - Super with Mixin.mixedInMethod
+//  - Super.extendedMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassImplements implements Interface2 {}
+//       ^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:19:7: Context: 'Interface2.extendedMethod' is defined here.
+//   int extendedMethod();
+//       ^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:20:7: Context: 'Interface2.mixedInMethod' is defined here.
+//   int mixedInMethod();
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:10:7: Context: 'Mixin.mixedInMethod' is defined here.
+//   num mixedInMethod() => 0;
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:10:7: Context: 'Super with Mixin.mixedInMethod' is defined here.
+//   num mixedInMethod() => 0;
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: 'Super.extendedMethod' is defined here.
+//   num extendedMethod() => 0;
+//       ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:23:7: Error: The implementation of 'mixedInMethod' in the non-abstract class 'ClassExtends' does not conform to its interface.
+// class ClassExtends extends Super with Mixin implements Interface1 {}
+//       ^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:23:7: Context: The return type of the method 'Super with Mixin.mixedInMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface1.mixedInMethod'.
+// Change to a subtype of 'int'.
+// class ClassExtends extends Super with Mixin implements Interface1 {}
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:15:7: Context: This is the overridden method ('mixedInMethod').
+//   int mixedInMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:23:7: Error: The implementation of 'extendedMethod' in the non-abstract class 'ClassExtends' does not conform to its interface.
+// class ClassExtends extends Super with Mixin implements Interface1 {}
+//       ^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: The return type of the method 'Super.extendedMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface1.extendedMethod'.
+// Change to a subtype of 'int'.
+//   num extendedMethod() => 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:14:7: Context: This is the overridden method ('extendedMethod').
+//   int extendedMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:25:7: Error: The implementation of 'mixedInMethod' in the non-abstract class 'ClassExtendsWithNoSuchMethod' does not conform to its interface.
+// class ClassExtendsWithNoSuchMethod extends Super
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:25:7: Context: The return type of the method 'Super with Mixin.mixedInMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface1.mixedInMethod'.
+// Change to a subtype of 'int'.
+// class ClassExtendsWithNoSuchMethod extends Super
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:15:7: Context: This is the overridden method ('mixedInMethod').
+//   int mixedInMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:25:7: Error: The implementation of 'extendedMethod' in the non-abstract class 'ClassExtendsWithNoSuchMethod' does not conform to its interface.
+// class ClassExtendsWithNoSuchMethod extends Super
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: The return type of the method 'Super.extendedMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'Interface1.extendedMethod'.
+// Change to a subtype of 'int'.
+//   num extendedMethod() => 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:14:7: Context: This is the overridden method ('extendedMethod').
+//   int extendedMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:43:7: Error: The implementation of 'extendedMethod' in the non-abstract class 'ClassDeclaresExtends' does not conform to its interface.
+// class ClassDeclaresExtends extends Super with Mixin {
+//       ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: The return type of the method 'Super.extendedMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'ClassDeclaresExtends.extendedMethod'.
+// Change to a subtype of 'int'.
+//   num extendedMethod() => 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:44:7: Context: This is the overridden method ('extendedMethod').
+//   int extendedMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:43:7: Error: The implementation of 'mixedInMethod' in the non-abstract class 'ClassDeclaresExtends' does not conform to its interface.
+// class ClassDeclaresExtends extends Super with Mixin {
+//       ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:43:7: Context: The return type of the method 'Super with Mixin.mixedInMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'ClassDeclaresExtends.mixedInMethod'.
+// Change to a subtype of 'int'.
+// class ClassDeclaresExtends extends Super with Mixin {
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:45:7: Context: This is the overridden method ('mixedInMethod').
+//   int mixedInMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:48:7: Error: The implementation of 'extendedMethod' in the non-abstract class 'ClassDeclaresExtendsWithNoSuchMethod' does not conform to its interface.
+// class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:6:7: Context: The return type of the method 'Super.extendedMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'ClassDeclaresExtendsWithNoSuchMethod.extendedMethod'.
+// Change to a subtype of 'int'.
+//   num extendedMethod() => 0;
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:54:7: Context: This is the overridden method ('extendedMethod').
+//   int extendedMethod();
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:48:7: Error: The implementation of 'mixedInMethod' in the non-abstract class 'ClassDeclaresExtendsWithNoSuchMethod' does not conform to its interface.
+// class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:48:7: Context: The return type of the method 'Super with Mixin.mixedInMethod' is 'num', which does not match the return type, 'int', of the overridden method, 'ClassDeclaresExtendsWithNoSuchMethod.mixedInMethod'.
+// Change to a subtype of 'int'.
+// class ClassDeclaresExtendsWithNoSuchMethod extends Super with Mixin {
+//       ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/inherited_implements.dart:55:7: Context: This is the overridden method ('mixedInMethod').
+//   int mixedInMethod();
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedMethod() → core::num
+    return 0;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method mixedInMethod() → core::num
+    return 0;
+}
+abstract class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  abstract method extendedMethod() → core::int;
+  abstract method mixedInMethod() → core::int;
+}
+abstract class _Interface2&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_Interface2&Super&Mixin
+    : super self::Super::•()
+    ;
+  method mixedInMethod() → core::num
+    return 0;
+}
+abstract class Interface2 extends self::_Interface2&Super&Mixin {
+  synthetic constructor •() → self::Interface2
+    : super self::_Interface2&Super&Mixin::•()
+    ;
+  abstract method extendedMethod() → core::int;
+  abstract method mixedInMethod() → core::int;
+}
+abstract class _ClassExtends&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassExtends&Super&Mixin
+    : super self::Super::•()
+    ;
+  method mixedInMethod() → core::num
+    return 0;
+}
+class ClassExtends extends self::_ClassExtends&Super&Mixin implements self::Interface1 {
+  synthetic constructor •() → self::ClassExtends
+    : super self::_ClassExtends&Super&Mixin::•()
+    ;
+  abstract member-signature method mixedInMethod() → core::int; -> self::Interface1::mixedInMethod
+  abstract member-signature method extendedMethod() → core::int; -> self::Interface1::extendedMethod
+}
+abstract class _ClassExtendsWithNoSuchMethod&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassExtendsWithNoSuchMethod&Super&Mixin
+    : super self::Super::•()
+    ;
+  method mixedInMethod() → core::num
+    return 0;
+}
+class ClassExtendsWithNoSuchMethod extends self::_ClassExtendsWithNoSuchMethod&Super&Mixin implements self::Interface1 {
+  synthetic constructor •() → self::ClassExtendsWithNoSuchMethod
+    : super self::_ClassExtendsWithNoSuchMethod&Super&Mixin::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract member-signature method mixedInMethod() → core::int; -> self::Interface1::mixedInMethod
+  abstract member-signature method extendedMethod() → core::int; -> self::Interface1::extendedMethod
+}
+class ClassImplements extends core::Object implements self::Interface2 {
+  synthetic constructor •() → self::ClassImplements
+    : super core::Object::•()
+    ;
+}
+class ClassImplementsWithNoSuchMethod extends core::Object implements self::Interface2 {
+  synthetic constructor •() → self::ClassImplementsWithNoSuchMethod
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  no-such-method-forwarder method mixedInMethod() → core::int
+    return this.{self::ClassImplementsWithNoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method extendedMethod() → core::int
+    return this.{self::ClassImplementsWithNoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+}
+abstract class _ClassDeclaresExtends&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassDeclaresExtends&Super&Mixin
+    : super self::Super::•()
+    ;
+  method mixedInMethod() → core::num
+    return 0;
+}
+class ClassDeclaresExtends extends self::_ClassDeclaresExtends&Super&Mixin {
+  synthetic constructor •() → self::ClassDeclaresExtends
+    : super self::_ClassDeclaresExtends&Super&Mixin::•()
+    ;
+  abstract method extendedMethod() → core::int;
+  abstract method mixedInMethod() → core::int;
+}
+abstract class _ClassDeclaresExtendsWithNoSuchMethod&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassDeclaresExtendsWithNoSuchMethod&Super&Mixin
+    : super self::Super::•()
+    ;
+  method mixedInMethod() → core::num
+    return 0;
+}
+class ClassDeclaresExtendsWithNoSuchMethod extends self::_ClassDeclaresExtendsWithNoSuchMethod&Super&Mixin {
+  synthetic constructor •() → self::ClassDeclaresExtendsWithNoSuchMethod
+    : super self::_ClassDeclaresExtendsWithNoSuchMethod&Super&Mixin::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  abstract method extendedMethod() → core::int;
+  abstract method mixedInMethod() → core::int;
+}
+class ClassDeclaresImplementsWithNoSuchMethod extends core::Object implements self::Super, self::Mixin {
+  synthetic constructor •() → self::ClassDeclaresImplementsWithNoSuchMethod
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return super.{core::Object::noSuchMethod}(invocation);
+  }
+  no-such-method-forwarder method extendedMethod() → core::int
+    return this.{self::ClassDeclaresImplementsWithNoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method mixedInMethod() → core::int
+    return this.{self::ClassDeclaresImplementsWithNoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = #mixedInMethod
+  #C3 = <core::Type*>[]
+  #C4 = <dynamic>[]
+  #C5 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C4}
+  #C6 = #extendedMethod
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart
new file mode 100644
index 0000000..82718e4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.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.
+
+// @dart=2.9
+
+import 'member_signature_lib.dart';
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+abstract class OptOutInterface {}
+
+abstract class ClassImplementsOptOut implements OptOutInterface {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.textual_outline.expect
new file mode 100644
index 0000000..5c3366c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+// @dart = 2.9
+import 'member_signature_lib.dart';
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+abstract class OptOutInterface {}
+
+abstract class ClassImplementsOptOut implements OptOutInterface {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cbc81d7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+// @dart = 2.9
+import 'member_signature_lib.dart';
+
+abstract class AbstractClass extends Super implements Interface1, Interface2 {}
+
+abstract class ClassImplementsOptOut implements OptOutInterface {}
+
+abstract class OptOutInterface {}
+
+class ConcreteClass extends Super implements Interface1, Interface2 {}
+
+class ConcreteSub extends AbstractClass {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.weak.expect
new file mode 100644
index 0000000..f789cb9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.weak.expect
@@ -0,0 +1,185 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart:11:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMethod
+//  - Interface1.implementedMethod
+//  - Interface1.implementedMultipleMethod
+//  - Interface2.implementedMultipleMethod
+//  - Super.extendedAbstractImplementedMethod
+//  - Super.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:18:8: Context: 'Interface1.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:20:8: Context: 'Interface1.implementedMethod' is defined here.
+//   void implementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:22:8: Context: 'Interface1.implementedMultipleMethod' is defined here.
+//   void implementedMultipleMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:26:8: Context: 'Interface2.implementedMultipleMethod' is defined here.
+//   void implementedMultipleMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:12:8: Context: 'Super.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart:13:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMethod
+//  - Interface1.implementedMethod
+//  - Interface1.implementedMultipleMethod
+//  - Interface2.implementedMultipleMethod
+//  - Super.extendedAbstractImplementedMethod
+//  - Super.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:18:8: Context: 'Interface1.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:20:8: Context: 'Interface1.implementedMethod' is defined here.
+//   void implementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:22:8: Context: 'Interface1.implementedMultipleMethod' is defined here.
+//   void implementedMultipleMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:26:8: Context: 'Interface2.implementedMultipleMethod' is defined here.
+//   void implementedMultipleMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:12:8: Context: 'Super.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "member_signature_lib.dart" as mem;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///member_signature_lib.dart";
+
+abstract class AbstractClass extends mem::Super implements mem::Interface1, mem::Interface2 {
+  synthetic constructor •() → self::AbstractClass*
+    : super mem::Super::•()
+    ;
+  abstract member-signature method extendedConcreteMethod(core::int* i) → void; -> mem::Super::extendedConcreteMethod
+  abstract member-signature method extendedConcreteImplementedMethod(core::int* i) → void; -> mem::Super::extendedConcreteImplementedMethod
+  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
+  abstract member-signature method extendedAbstractMethod(core::int* i) → void; -> mem::Super::extendedAbstractMethod
+  abstract member-signature method extendedAbstractImplementedMethod(core::int* i) → void; -> mem::Super::extendedAbstractImplementedMethod
+  abstract member-signature method implementedMethod(core::int* i) → void; -> mem::Interface1::implementedMethod
+  abstract member-signature method implementedMultipleMethod(core::int* i) → void; -> mem::Interface1::implementedMultipleMethod
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub*
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends mem::Super implements mem::Interface1, mem::Interface2 {
+  synthetic constructor •() → self::ConcreteClass*
+    : super mem::Super::•()
+    ;
+  abstract member-signature method extendedConcreteMethod(core::int* i) → void; -> mem::Super::extendedConcreteMethod
+  abstract member-signature method extendedConcreteImplementedMethod(core::int* i) → void; -> mem::Super::extendedConcreteImplementedMethod
+  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
+  abstract member-signature method extendedAbstractMethod(core::int* i) → void; -> mem::Super::extendedAbstractMethod
+  abstract member-signature method extendedAbstractImplementedMethod(core::int* i) → void; -> mem::Super::extendedAbstractImplementedMethod
+  abstract member-signature method implementedMethod(core::int* i) → void; -> mem::Interface1::implementedMethod
+  abstract member-signature method implementedMultipleMethod(core::int* i) → void; -> mem::Interface1::implementedMultipleMethod
+}
+abstract class OptOutInterface extends core::Object {
+  synthetic constructor •() → self::OptOutInterface*
+    : 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
+}
+abstract class ClassImplementsOptOut extends core::Object implements self::OptOutInterface {
+  synthetic constructor •() → self::ClassImplementsOptOut*
+    : 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 method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as mem;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → mem::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod(core::int i) → void {}
+  abstract method extendedAbstractMethod(core::int i) → void;
+  method extendedConcreteImplementedMethod(core::int i) → void {}
+  abstract method extendedAbstractImplementedMethod(core::int i) → void;
+}
+abstract class Interface1 extends core::Object {
+  synthetic constructor •() → mem::Interface1
+    : super core::Object::•()
+    ;
+  method extendedConcreteImplementedMethod(core::int i) → void {}
+  method extendedAbstractImplementedMethod(core::int i) → void {}
+  method implementedMethod(core::int i) → void {}
+  method implementedMultipleMethod(core::int i) → void {}
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → mem::Interface2
+    : super core::Object::•()
+    ;
+  method implementedMultipleMethod(core::int i) → void {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.weak.transformed.expect
new file mode 100644
index 0000000..f789cb9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart.weak.transformed.expect
@@ -0,0 +1,185 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart:11:7: Error: The non-abstract class 'ConcreteSub' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMethod
+//  - Interface1.implementedMethod
+//  - Interface1.implementedMultipleMethod
+//  - Interface2.implementedMultipleMethod
+//  - Super.extendedAbstractImplementedMethod
+//  - Super.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteSub extends AbstractClass {}
+//       ^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:18:8: Context: 'Interface1.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:20:8: Context: 'Interface1.implementedMethod' is defined here.
+//   void implementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:22:8: Context: 'Interface1.implementedMultipleMethod' is defined here.
+//   void implementedMultipleMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:26:8: Context: 'Interface2.implementedMultipleMethod' is defined here.
+//   void implementedMultipleMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:12:8: Context: 'Super.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature.dart:13:7: Error: The non-abstract class 'ConcreteClass' is missing implementations for these members:
+//  - Interface1.extendedAbstractImplementedMethod
+//  - Interface1.implementedMethod
+//  - Interface1.implementedMultipleMethod
+//  - Interface2.implementedMultipleMethod
+//  - Super.extendedAbstractImplementedMethod
+//  - Super.extendedAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ConcreteClass extends Super implements Interface1, Interface2 {}
+//       ^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:18:8: Context: 'Interface1.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:20:8: Context: 'Interface1.implementedMethod' is defined here.
+//   void implementedMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:22:8: Context: 'Interface1.implementedMultipleMethod' is defined here.
+//   void implementedMultipleMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:26:8: Context: 'Interface2.implementedMultipleMethod' is defined here.
+//   void implementedMultipleMethod(int i) {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:12:8: Context: 'Super.extendedAbstractImplementedMethod' is defined here.
+//   void extendedAbstractImplementedMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "member_signature_lib.dart" as mem;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///member_signature_lib.dart";
+
+abstract class AbstractClass extends mem::Super implements mem::Interface1, mem::Interface2 {
+  synthetic constructor •() → self::AbstractClass*
+    : super mem::Super::•()
+    ;
+  abstract member-signature method extendedConcreteMethod(core::int* i) → void; -> mem::Super::extendedConcreteMethod
+  abstract member-signature method extendedConcreteImplementedMethod(core::int* i) → void; -> mem::Super::extendedConcreteImplementedMethod
+  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
+  abstract member-signature method extendedAbstractMethod(core::int* i) → void; -> mem::Super::extendedAbstractMethod
+  abstract member-signature method extendedAbstractImplementedMethod(core::int* i) → void; -> mem::Super::extendedAbstractImplementedMethod
+  abstract member-signature method implementedMethod(core::int* i) → void; -> mem::Interface1::implementedMethod
+  abstract member-signature method implementedMultipleMethod(core::int* i) → void; -> mem::Interface1::implementedMultipleMethod
+}
+class ConcreteSub extends self::AbstractClass {
+  synthetic constructor •() → self::ConcreteSub*
+    : super self::AbstractClass::•()
+    ;
+}
+class ConcreteClass extends mem::Super implements mem::Interface1, mem::Interface2 {
+  synthetic constructor •() → self::ConcreteClass*
+    : super mem::Super::•()
+    ;
+  abstract member-signature method extendedConcreteMethod(core::int* i) → void; -> mem::Super::extendedConcreteMethod
+  abstract member-signature method extendedConcreteImplementedMethod(core::int* i) → void; -> mem::Super::extendedConcreteImplementedMethod
+  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
+  abstract member-signature method extendedAbstractMethod(core::int* i) → void; -> mem::Super::extendedAbstractMethod
+  abstract member-signature method extendedAbstractImplementedMethod(core::int* i) → void; -> mem::Super::extendedAbstractImplementedMethod
+  abstract member-signature method implementedMethod(core::int* i) → void; -> mem::Interface1::implementedMethod
+  abstract member-signature method implementedMultipleMethod(core::int* i) → void; -> mem::Interface1::implementedMultipleMethod
+}
+abstract class OptOutInterface extends core::Object {
+  synthetic constructor •() → self::OptOutInterface*
+    : 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
+}
+abstract class ClassImplementsOptOut extends core::Object implements self::OptOutInterface {
+  synthetic constructor •() → self::ClassImplementsOptOut*
+    : 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 method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as mem;
+import "dart:core" as core;
+
+abstract class Super extends core::Object {
+  synthetic constructor •() → mem::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod(core::int i) → void {}
+  abstract method extendedAbstractMethod(core::int i) → void;
+  method extendedConcreteImplementedMethod(core::int i) → void {}
+  abstract method extendedAbstractImplementedMethod(core::int i) → void;
+}
+abstract class Interface1 extends core::Object {
+  synthetic constructor •() → mem::Interface1
+    : super core::Object::•()
+    ;
+  method extendedConcreteImplementedMethod(core::int i) → void {}
+  method extendedAbstractImplementedMethod(core::int i) → void {}
+  method implementedMethod(core::int i) → void {}
+  method implementedMultipleMethod(core::int i) → void {}
+}
+abstract class Interface2 extends core::Object {
+  synthetic constructor •() → mem::Interface2
+    : super core::Object::•()
+    ;
+  method implementedMultipleMethod(core::int i) → void {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_lib.dart
new file mode 100644
index 0000000..536d4d1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/member_signature_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.
+
+abstract class Super {
+  void extendedConcreteMethod(int i) {}
+
+  void extendedAbstractMethod(int i);
+
+  void extendedConcreteImplementedMethod(int i) {}
+
+  void extendedAbstractImplementedMethod(int i);
+}
+
+abstract class Interface1 {
+  void extendedConcreteImplementedMethod(int i) {}
+
+  void extendedAbstractImplementedMethod(int i) {}
+
+  void implementedMethod(int i) {}
+
+  void implementedMultipleMethod(int i) {}
+}
+
+abstract class Interface2 {
+  void implementedMultipleMethod(int i) {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart
new file mode 100644
index 0000000..a302ec1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart
@@ -0,0 +1,37 @@
+// 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 Super {
+  int extendedConcreteField = 0;
+
+  abstract int extendedAbstractField;
+
+  int extendedConcreteMixedInConcreteField = 0;
+
+  abstract int extendedAbstractMixedInConcreteField;
+
+  int extendedConcreteMixedInAbstractField = 0;
+
+  abstract int extendedAbstractMixedInAbstractField;
+}
+
+class Mixin {
+  int mixedInConcreteField = 0;
+
+  abstract int mixedInAbstractField;
+
+  int extendedConcreteMixedInConcreteField = 0;
+
+  int extendedAbstractMixedInConcreteField = 0;
+
+  abstract int extendedConcreteMixedInAbstractField;
+
+  abstract int extendedAbstractMixedInAbstractField;
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.textual_outline.expect
new file mode 100644
index 0000000..e0858b6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+class Super {
+  int extendedConcreteField = 0;
+  abstract int extendedAbstractField;
+  int extendedConcreteMixedInConcreteField = 0;
+  abstract int extendedAbstractMixedInConcreteField;
+  int extendedConcreteMixedInAbstractField = 0;
+  abstract int extendedAbstractMixedInAbstractField;
+}
+
+class Mixin {
+  int mixedInConcreteField = 0;
+  abstract int mixedInAbstractField;
+  int extendedConcreteMixedInConcreteField = 0;
+  int extendedAbstractMixedInConcreteField = 0;
+  abstract int extendedConcreteMixedInAbstractField;
+  abstract int extendedAbstractMixedInAbstractField;
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9c90c6f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,23 @@
+class ClassMixin extends Super with Mixin {}
+
+class Mixin {
+  abstract int extendedAbstractMixedInAbstractField;
+  abstract int extendedConcreteMixedInAbstractField;
+  abstract int mixedInAbstractField;
+  int extendedAbstractMixedInConcreteField = 0;
+  int extendedConcreteMixedInConcreteField = 0;
+  int mixedInConcreteField = 0;
+}
+
+class NamedMixin = Super with Mixin;
+
+class Super {
+  abstract int extendedAbstractField;
+  abstract int extendedAbstractMixedInAbstractField;
+  abstract int extendedAbstractMixedInConcreteField;
+  int extendedConcreteField = 0;
+  int extendedConcreteMixedInAbstractField = 0;
+  int extendedConcreteMixedInConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.weak.expect
new file mode 100644
index 0000000..185fc0d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.weak.expect
@@ -0,0 +1,239 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractMixedInAbstractField
+//  - Super.extendedAbstractMixedInAbstractField=
+//  - Super.extendedAbstractMixedInConcreteField
+//  - Super.extendedAbstractMixedInConcreteField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:12:16: Context: 'Super.extendedAbstractMixedInConcreteField' is defined here.
+//   abstract int extendedAbstractMixedInConcreteField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:12:16: Context: 'Super.extendedAbstractMixedInConcreteField=' is defined here.
+//   abstract int extendedAbstractMixedInConcreteField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.extendedAbstractMixedInAbstractField=
+//  - Mixin.extendedConcreteMixedInAbstractField
+//  - Mixin.extendedConcreteMixedInAbstractField=
+//  - Mixin.mixedInAbstractField
+//  - Mixin.mixedInAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:28:16: Context: 'Mixin.extendedConcreteMixedInAbstractField' is defined here.
+//   abstract int extendedConcreteMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:28:16: Context: 'Mixin.extendedConcreteMixedInAbstractField=' is defined here.
+//   abstract int extendedConcreteMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField=' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.extendedAbstractMixedInAbstractField=
+//  - Mixin.mixedInAbstractField
+//  - Mixin.mixedInAbstractField=
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractMixedInAbstractField
+//  - Super.extendedAbstractMixedInAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField=' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.extendedAbstractMixedInAbstractField=
+//  - Mixin.mixedInAbstractField
+//  - Mixin.mixedInAbstractField=
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractMixedInAbstractField
+//  - Super.extendedAbstractMixedInAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField=' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  field core::int extendedConcreteField = 0;
+  field core::int extendedConcreteMixedInConcreteField = 0;
+  field core::int extendedConcreteMixedInAbstractField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract set extendedAbstractField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractMixedInConcreteField() → core::int;
+  abstract set extendedAbstractMixedInConcreteField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+  abstract set extendedAbstractMixedInAbstractField(core::int #externalFieldValue) → void;
+}
+class Mixin extends core::Object {
+  field core::int mixedInConcreteField = 0;
+  field core::int extendedConcreteMixedInConcreteField = 0;
+  field core::int extendedAbstractMixedInConcreteField = 0;
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  abstract get mixedInAbstractField() → core::int;
+  abstract set mixedInAbstractField(core::int #externalFieldValue) → void;
+  abstract get extendedConcreteMixedInAbstractField() → core::int;
+  abstract set extendedConcreteMixedInAbstractField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+  abstract set extendedAbstractMixedInAbstractField(core::int #externalFieldValue) → void;
+}
+abstract class _ClassMixin&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub get mixedInConcreteField() → core::int
+    return super.{self::Mixin::mixedInConcreteField};
+  mixin-super-stub set mixedInConcreteField(core::int value) → void
+    return super.{self::Mixin::mixedInConcreteField} = value;
+  abstract mixin-stub get mixedInAbstractField() → core::int; -> self::Mixin::mixedInAbstractField
+  abstract mixin-stub set mixedInAbstractField(core::int #externalFieldValue) → void; -> self::Mixin::mixedInAbstractField
+  mixin-super-stub get extendedConcreteMixedInConcreteField() → core::int
+    return super.{self::Mixin::extendedConcreteMixedInConcreteField};
+  mixin-super-stub set extendedConcreteMixedInConcreteField(core::int value) → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteField} = value;
+  mixin-super-stub get extendedAbstractMixedInConcreteField() → core::int
+    return super.{self::Mixin::extendedAbstractMixedInConcreteField};
+  mixin-super-stub set extendedAbstractMixedInConcreteField(core::int value) → void
+    return super.{self::Mixin::extendedAbstractMixedInConcreteField} = value;
+  abstract mixin-stub get extendedConcreteMixedInAbstractField() → core::int; -> self::Mixin::extendedConcreteMixedInAbstractField
+  abstract mixin-stub set extendedConcreteMixedInAbstractField(core::int #externalFieldValue) → void; -> self::Mixin::extendedConcreteMixedInAbstractField
+  abstract mixin-stub get extendedAbstractMixedInAbstractField() → core::int; -> self::Mixin::extendedAbstractMixedInAbstractField
+  abstract mixin-stub set extendedAbstractMixedInAbstractField(core::int #externalFieldValue) → void; -> self::Mixin::extendedAbstractMixedInAbstractField
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin = self::Super with self::Mixin {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub get mixedInConcreteField() → core::int
+    return super.{self::Mixin::mixedInConcreteField};
+  mixin-super-stub set mixedInConcreteField(core::int value) → void
+    return super.{self::Mixin::mixedInConcreteField} = value;
+  abstract mixin-stub get mixedInAbstractField() → core::int; -> self::Mixin::mixedInAbstractField
+  abstract mixin-stub set mixedInAbstractField(core::int #externalFieldValue) → void; -> self::Mixin::mixedInAbstractField
+  mixin-super-stub get extendedConcreteMixedInConcreteField() → core::int
+    return super.{self::Mixin::extendedConcreteMixedInConcreteField};
+  mixin-super-stub set extendedConcreteMixedInConcreteField(core::int value) → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteField} = value;
+  mixin-super-stub get extendedAbstractMixedInConcreteField() → core::int
+    return super.{self::Mixin::extendedAbstractMixedInConcreteField};
+  mixin-super-stub set extendedAbstractMixedInConcreteField(core::int value) → void
+    return super.{self::Mixin::extendedAbstractMixedInConcreteField} = value;
+  abstract mixin-stub get extendedConcreteMixedInAbstractField() → core::int; -> self::Mixin::extendedConcreteMixedInAbstractField
+  abstract mixin-stub set extendedConcreteMixedInAbstractField(core::int #externalFieldValue) → void; -> self::Mixin::extendedConcreteMixedInAbstractField
+  abstract mixin-stub get extendedAbstractMixedInAbstractField() → core::int; -> self::Mixin::extendedAbstractMixedInAbstractField
+  abstract mixin-stub set extendedAbstractMixedInAbstractField(core::int #externalFieldValue) → void; -> self::Mixin::extendedAbstractMixedInAbstractField
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..3e41841
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart.weak.transformed.expect
@@ -0,0 +1,221 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractMixedInAbstractField
+//  - Super.extendedAbstractMixedInAbstractField=
+//  - Super.extendedAbstractMixedInConcreteField
+//  - Super.extendedAbstractMixedInConcreteField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:12:16: Context: 'Super.extendedAbstractMixedInConcreteField' is defined here.
+//   abstract int extendedAbstractMixedInConcreteField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:12:16: Context: 'Super.extendedAbstractMixedInConcreteField=' is defined here.
+//   abstract int extendedAbstractMixedInConcreteField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.extendedAbstractMixedInAbstractField=
+//  - Mixin.extendedConcreteMixedInAbstractField
+//  - Mixin.extendedConcreteMixedInAbstractField=
+//  - Mixin.mixedInAbstractField
+//  - Mixin.mixedInAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:28:16: Context: 'Mixin.extendedConcreteMixedInAbstractField' is defined here.
+//   abstract int extendedConcreteMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:28:16: Context: 'Mixin.extendedConcreteMixedInAbstractField=' is defined here.
+//   abstract int extendedConcreteMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField=' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.extendedAbstractMixedInAbstractField=
+//  - Mixin.mixedInAbstractField
+//  - Mixin.mixedInAbstractField=
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractMixedInAbstractField
+//  - Super.extendedAbstractMixedInAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField=' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.extendedAbstractMixedInAbstractField=
+//  - Mixin.mixedInAbstractField
+//  - Mixin.mixedInAbstractField=
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractField=
+//  - Super.extendedAbstractMixedInAbstractField
+//  - Super.extendedAbstractMixedInAbstractField=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:30:16: Context: 'Mixin.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:22:16: Context: 'Mixin.mixedInAbstractField=' is defined here.
+//   abstract int mixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:8:16: Context: 'Super.extendedAbstractField=' is defined here.
+//   abstract int extendedAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_field.dart:16:16: Context: 'Super.extendedAbstractMixedInAbstractField=' is defined here.
+//   abstract int extendedAbstractMixedInAbstractField;
+//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  field core::int extendedConcreteField = 0;
+  field core::int extendedConcreteMixedInConcreteField = 0;
+  field core::int extendedConcreteMixedInAbstractField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract set extendedAbstractField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractMixedInConcreteField() → core::int;
+  abstract set extendedAbstractMixedInConcreteField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+  abstract set extendedAbstractMixedInAbstractField(core::int #externalFieldValue) → void;
+}
+class Mixin extends core::Object {
+  field core::int mixedInConcreteField = 0;
+  field core::int extendedConcreteMixedInConcreteField = 0;
+  field core::int extendedAbstractMixedInConcreteField = 0;
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  abstract get mixedInAbstractField() → core::int;
+  abstract set mixedInAbstractField(core::int #externalFieldValue) → void;
+  abstract get extendedConcreteMixedInAbstractField() → core::int;
+  abstract set extendedConcreteMixedInAbstractField(core::int #externalFieldValue) → void;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+  abstract set extendedAbstractMixedInAbstractField(core::int #externalFieldValue) → void;
+}
+abstract class _ClassMixin&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  field core::int mixedInConcreteField = 0;
+  field core::int extendedConcreteMixedInConcreteField = 0;
+  field core::int extendedAbstractMixedInConcreteField = 0;
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  abstract get mixedInAbstractField() → core::int;
+  abstract get extendedConcreteMixedInAbstractField() → core::int;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+  abstract set mixedInAbstractField(core::int #externalFieldValue) → void;
+  abstract set extendedConcreteMixedInAbstractField(core::int #externalFieldValue) → void;
+  abstract set extendedAbstractMixedInAbstractField(core::int #externalFieldValue) → void;
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+  field core::int mixedInConcreteField = 0;
+  field core::int extendedConcreteMixedInConcreteField = 0;
+  field core::int extendedAbstractMixedInConcreteField = 0;
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  abstract get mixedInAbstractField() → core::int;
+  abstract get extendedConcreteMixedInAbstractField() → core::int;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+  abstract set mixedInAbstractField(core::int #externalFieldValue) → void;
+  abstract set extendedConcreteMixedInAbstractField(core::int #externalFieldValue) → void;
+  abstract set extendedAbstractMixedInAbstractField(core::int #externalFieldValue) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart
new file mode 100644
index 0000000..a2ece5f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart
@@ -0,0 +1,37 @@
+// 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 Super {
+  final int extendedConcreteField = 0;
+
+  abstract final int extendedAbstractField;
+
+  final int extendedConcreteMixedInConcreteField = 0;
+
+  abstract final int extendedAbstractMixedInConcreteField;
+
+  final int extendedConcreteMixedInAbstractField = 0;
+
+  abstract final int extendedAbstractMixedInAbstractField;
+}
+
+class Mixin {
+  final int mixedInConcreteField = 0;
+
+  abstract final int mixedInAbstractField;
+
+  final int extendedConcreteMixedInConcreteField = 0;
+
+  final int extendedAbstractMixedInConcreteField = 0;
+
+  abstract final int extendedConcreteMixedInAbstractField;
+
+  abstract final int extendedAbstractMixedInAbstractField;
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.textual_outline.expect
new file mode 100644
index 0000000..e4fbdca
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+class Super {
+  final int extendedConcreteField = 0;
+  abstract final int extendedAbstractField;
+  final int extendedConcreteMixedInConcreteField = 0;
+  abstract final int extendedAbstractMixedInConcreteField;
+  final int extendedConcreteMixedInAbstractField = 0;
+  abstract final int extendedAbstractMixedInAbstractField;
+}
+
+class Mixin {
+  final int mixedInConcreteField = 0;
+  abstract final int mixedInAbstractField;
+  final int extendedConcreteMixedInConcreteField = 0;
+  final int extendedAbstractMixedInConcreteField = 0;
+  abstract final int extendedConcreteMixedInAbstractField;
+  abstract final int extendedAbstractMixedInAbstractField;
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a8220b4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.textual_outline_modelled.expect
@@ -0,0 +1,23 @@
+class ClassMixin extends Super with Mixin {}
+
+class Mixin {
+  abstract final int extendedAbstractMixedInAbstractField;
+  abstract final int extendedConcreteMixedInAbstractField;
+  abstract final int mixedInAbstractField;
+  final int extendedAbstractMixedInConcreteField = 0;
+  final int extendedConcreteMixedInConcreteField = 0;
+  final int mixedInConcreteField = 0;
+}
+
+class NamedMixin = Super with Mixin;
+
+class Super {
+  abstract final int extendedAbstractField;
+  abstract final int extendedAbstractMixedInAbstractField;
+  abstract final int extendedAbstractMixedInConcreteField;
+  final int extendedConcreteField = 0;
+  final int extendedConcreteMixedInAbstractField = 0;
+  final int extendedConcreteMixedInConcreteField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.weak.expect
new file mode 100644
index 0000000..aa5c0aa6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.weak.expect
@@ -0,0 +1,159 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractMixedInAbstractField
+//  - Super.extendedAbstractMixedInConcreteField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:16:22: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:12:22: Context: 'Super.extendedAbstractMixedInConcreteField' is defined here.
+//   abstract final int extendedAbstractMixedInConcreteField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.extendedConcreteMixedInAbstractField
+//  - Mixin.mixedInAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:30:22: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:28:22: Context: 'Mixin.extendedConcreteMixedInAbstractField' is defined here.
+//   abstract final int extendedConcreteMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:22:22: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract final int mixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.mixedInAbstractField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractMixedInAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:30:22: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:22:22: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract final int mixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:16:22: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.mixedInAbstractField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractMixedInAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:30:22: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:22:22: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract final int mixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:16:22: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  final field core::int extendedConcreteField = 0;
+  final field core::int extendedConcreteMixedInConcreteField = 0;
+  final field core::int extendedConcreteMixedInAbstractField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract get extendedAbstractMixedInConcreteField() → core::int;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+}
+class Mixin extends core::Object {
+  final field core::int mixedInConcreteField = 0;
+  final field core::int extendedConcreteMixedInConcreteField = 0;
+  final field core::int extendedAbstractMixedInConcreteField = 0;
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  abstract get mixedInAbstractField() → core::int;
+  abstract get extendedConcreteMixedInAbstractField() → core::int;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+}
+abstract class _ClassMixin&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub get mixedInConcreteField() → core::int
+    return super.{self::Mixin::mixedInConcreteField};
+  mixin-super-stub get extendedConcreteMixedInConcreteField() → core::int
+    return super.{self::Mixin::extendedConcreteMixedInConcreteField};
+  mixin-super-stub get extendedAbstractMixedInConcreteField() → core::int
+    return super.{self::Mixin::extendedAbstractMixedInConcreteField};
+  abstract mixin-stub get extendedConcreteMixedInAbstractField() → core::int; -> self::Mixin::extendedConcreteMixedInAbstractField
+  abstract mixin-stub get mixedInAbstractField() → core::int; -> self::Mixin::mixedInAbstractField
+  abstract mixin-stub get extendedAbstractMixedInAbstractField() → core::int; -> self::Mixin::extendedAbstractMixedInAbstractField
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin = self::Super with self::Mixin {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub get mixedInConcreteField() → core::int
+    return super.{self::Mixin::mixedInConcreteField};
+  mixin-super-stub get extendedConcreteMixedInConcreteField() → core::int
+    return super.{self::Mixin::extendedConcreteMixedInConcreteField};
+  mixin-super-stub get extendedAbstractMixedInConcreteField() → core::int
+    return super.{self::Mixin::extendedAbstractMixedInConcreteField};
+  abstract mixin-stub get extendedConcreteMixedInAbstractField() → core::int; -> self::Mixin::extendedConcreteMixedInAbstractField
+  abstract mixin-stub get mixedInAbstractField() → core::int; -> self::Mixin::mixedInAbstractField
+  abstract mixin-stub get extendedAbstractMixedInAbstractField() → core::int; -> self::Mixin::extendedAbstractMixedInAbstractField
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.weak.transformed.expect
new file mode 100644
index 0000000..4a7ba31
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart.weak.transformed.expect
@@ -0,0 +1,153 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractMixedInAbstractField
+//  - Super.extendedAbstractMixedInConcreteField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:16:22: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:12:22: Context: 'Super.extendedAbstractMixedInConcreteField' is defined here.
+//   abstract final int extendedAbstractMixedInConcreteField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.extendedConcreteMixedInAbstractField
+//  - Mixin.mixedInAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:30:22: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:28:22: Context: 'Mixin.extendedConcreteMixedInAbstractField' is defined here.
+//   abstract final int extendedConcreteMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:22:22: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract final int mixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.mixedInAbstractField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractMixedInAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:30:22: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:22:22: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract final int mixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:16:22: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractField
+//  - Mixin.mixedInAbstractField
+//  - Super.extendedAbstractField
+//  - Super.extendedAbstractMixedInAbstractField
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:30:22: Context: 'Mixin.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:22:22: Context: 'Mixin.mixedInAbstractField' is defined here.
+//   abstract final int mixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:8:22: Context: 'Super.extendedAbstractField' is defined here.
+//   abstract final int extendedAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_final_field.dart:16:22: Context: 'Super.extendedAbstractMixedInAbstractField' is defined here.
+//   abstract final int extendedAbstractMixedInAbstractField;
+//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  final field core::int extendedConcreteField = 0;
+  final field core::int extendedConcreteMixedInConcreteField = 0;
+  final field core::int extendedConcreteMixedInAbstractField = 0;
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  abstract get extendedAbstractField() → core::int;
+  abstract get extendedAbstractMixedInConcreteField() → core::int;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+}
+class Mixin extends core::Object {
+  final field core::int mixedInConcreteField = 0;
+  final field core::int extendedConcreteMixedInConcreteField = 0;
+  final field core::int extendedAbstractMixedInConcreteField = 0;
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  abstract get mixedInAbstractField() → core::int;
+  abstract get extendedConcreteMixedInAbstractField() → core::int;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+}
+abstract class _ClassMixin&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  final field core::int mixedInConcreteField = 0;
+  final field core::int extendedConcreteMixedInConcreteField = 0;
+  final field core::int extendedAbstractMixedInConcreteField = 0;
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  abstract get extendedConcreteMixedInAbstractField() → core::int;
+  abstract get mixedInAbstractField() → core::int;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+  final field core::int mixedInConcreteField = 0;
+  final field core::int extendedConcreteMixedInConcreteField = 0;
+  final field core::int extendedAbstractMixedInConcreteField = 0;
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  abstract get extendedConcreteMixedInAbstractField() → core::int;
+  abstract get mixedInAbstractField() → core::int;
+  abstract get extendedAbstractMixedInAbstractField() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart
new file mode 100644
index 0000000..748e722
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart
@@ -0,0 +1,37 @@
+// 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 Super {
+  int get extendedConcreteGetter => 0;
+
+  int get extendedAbstractGetter;
+
+  int get extendedConcreteMixedInConcreteGetter => 0;
+
+  int get extendedAbstractMixedInConcreteGetter;
+
+  int get extendedConcreteMixedInAbstractGetter => 0;
+
+  int get extendedAbstractMixedInAbstractGetter;
+}
+
+class Mixin {
+  int get mixedInConcreteGetter => 0;
+
+  int get mixedInAbstractGetter;
+
+  int get extendedConcreteMixedInConcreteGetter => 0;
+
+  int get extendedAbstractMixedInConcreteGetter => 0;
+
+  int get extendedConcreteMixedInAbstractGetter;
+
+  int get extendedAbstractMixedInAbstractGetter;
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.textual_outline.expect
new file mode 100644
index 0000000..df3e488
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+class Super {
+  int get extendedConcreteGetter => 0;
+  int get extendedAbstractGetter;
+  int get extendedConcreteMixedInConcreteGetter => 0;
+  int get extendedAbstractMixedInConcreteGetter;
+  int get extendedConcreteMixedInAbstractGetter => 0;
+  int get extendedAbstractMixedInAbstractGetter;
+}
+
+class Mixin {
+  int get mixedInConcreteGetter => 0;
+  int get mixedInAbstractGetter;
+  int get extendedConcreteMixedInConcreteGetter => 0;
+  int get extendedAbstractMixedInConcreteGetter => 0;
+  int get extendedConcreteMixedInAbstractGetter;
+  int get extendedAbstractMixedInAbstractGetter;
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e489b9d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.textual_outline_modelled.expect
@@ -0,0 +1,23 @@
+class ClassMixin extends Super with Mixin {}
+
+class Mixin {
+  int get extendedAbstractMixedInAbstractGetter;
+  int get extendedAbstractMixedInConcreteGetter => 0;
+  int get extendedConcreteMixedInAbstractGetter;
+  int get extendedConcreteMixedInConcreteGetter => 0;
+  int get mixedInAbstractGetter;
+  int get mixedInConcreteGetter => 0;
+}
+
+class NamedMixin = Super with Mixin;
+
+class Super {
+  int get extendedAbstractGetter;
+  int get extendedAbstractMixedInAbstractGetter;
+  int get extendedAbstractMixedInConcreteGetter;
+  int get extendedConcreteGetter => 0;
+  int get extendedConcreteMixedInAbstractGetter => 0;
+  int get extendedConcreteMixedInConcreteGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.weak.expect
new file mode 100644
index 0000000..09d72f2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.weak.expect
@@ -0,0 +1,165 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractMixedInAbstractGetter
+//  - Super.extendedAbstractMixedInConcreteGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:16:11: Context: 'Super.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:12:11: Context: 'Super.extendedAbstractMixedInConcreteGetter' is defined here.
+//   int get extendedAbstractMixedInConcreteGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractGetter
+//  - Mixin.extendedConcreteMixedInAbstractGetter
+//  - Mixin.mixedInAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:30:11: Context: 'Mixin.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:28:11: Context: 'Mixin.extendedConcreteMixedInAbstractGetter' is defined here.
+//   int get extendedConcreteMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:22:11: Context: 'Mixin.mixedInAbstractGetter' is defined here.
+//   int get mixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractGetter
+//  - Mixin.mixedInAbstractGetter
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractMixedInAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:30:11: Context: 'Mixin.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:22:11: Context: 'Mixin.mixedInAbstractGetter' is defined here.
+//   int get mixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:16:11: Context: 'Super.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractGetter
+//  - Mixin.mixedInAbstractGetter
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractMixedInAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:30:11: Context: 'Mixin.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:22:11: Context: 'Mixin.mixedInAbstractGetter' is defined here.
+//   int get mixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:16:11: Context: 'Super.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  get extendedConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractGetter() → core::int;
+  get extendedConcreteMixedInConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractMixedInConcreteGetter() → core::int;
+  get extendedConcreteMixedInAbstractGetter() → core::int
+    return 0;
+  abstract get extendedAbstractMixedInAbstractGetter() → core::int;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  get mixedInConcreteGetter() → core::int
+    return 0;
+  abstract get mixedInAbstractGetter() → core::int;
+  get extendedConcreteMixedInConcreteGetter() → core::int
+    return 0;
+  get extendedAbstractMixedInConcreteGetter() → core::int
+    return 0;
+  abstract get extendedConcreteMixedInAbstractGetter() → core::int;
+  abstract get extendedAbstractMixedInAbstractGetter() → core::int;
+}
+abstract class _ClassMixin&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub get mixedInConcreteGetter() → core::int
+    return super.{self::Mixin::mixedInConcreteGetter};
+  mixin-super-stub get extendedConcreteMixedInConcreteGetter() → core::int
+    return super.{self::Mixin::extendedConcreteMixedInConcreteGetter};
+  mixin-super-stub get extendedAbstractMixedInConcreteGetter() → core::int
+    return super.{self::Mixin::extendedAbstractMixedInConcreteGetter};
+  abstract mixin-stub get extendedConcreteMixedInAbstractGetter() → core::int; -> self::Mixin::extendedConcreteMixedInAbstractGetter
+  abstract mixin-stub get mixedInAbstractGetter() → core::int; -> self::Mixin::mixedInAbstractGetter
+  abstract mixin-stub get extendedAbstractMixedInAbstractGetter() → core::int; -> self::Mixin::extendedAbstractMixedInAbstractGetter
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin = self::Super with self::Mixin {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub get mixedInConcreteGetter() → core::int
+    return super.{self::Mixin::mixedInConcreteGetter};
+  mixin-super-stub get extendedConcreteMixedInConcreteGetter() → core::int
+    return super.{self::Mixin::extendedConcreteMixedInConcreteGetter};
+  mixin-super-stub get extendedAbstractMixedInConcreteGetter() → core::int
+    return super.{self::Mixin::extendedAbstractMixedInConcreteGetter};
+  abstract mixin-stub get extendedConcreteMixedInAbstractGetter() → core::int; -> self::Mixin::extendedConcreteMixedInAbstractGetter
+  abstract mixin-stub get mixedInAbstractGetter() → core::int; -> self::Mixin::mixedInAbstractGetter
+  abstract mixin-stub get extendedAbstractMixedInAbstractGetter() → core::int; -> self::Mixin::extendedAbstractMixedInAbstractGetter
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.weak.transformed.expect
new file mode 100644
index 0000000..f307297
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart.weak.transformed.expect
@@ -0,0 +1,165 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractMixedInAbstractGetter
+//  - Super.extendedAbstractMixedInConcreteGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:16:11: Context: 'Super.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:12:11: Context: 'Super.extendedAbstractMixedInConcreteGetter' is defined here.
+//   int get extendedAbstractMixedInConcreteGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractGetter
+//  - Mixin.extendedConcreteMixedInAbstractGetter
+//  - Mixin.mixedInAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:30:11: Context: 'Mixin.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:28:11: Context: 'Mixin.extendedConcreteMixedInAbstractGetter' is defined here.
+//   int get extendedConcreteMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:22:11: Context: 'Mixin.mixedInAbstractGetter' is defined here.
+//   int get mixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractGetter
+//  - Mixin.mixedInAbstractGetter
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractMixedInAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:30:11: Context: 'Mixin.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:22:11: Context: 'Mixin.mixedInAbstractGetter' is defined here.
+//   int get mixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:16:11: Context: 'Super.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractGetter
+//  - Mixin.mixedInAbstractGetter
+//  - Super.extendedAbstractGetter
+//  - Super.extendedAbstractMixedInAbstractGetter
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:30:11: Context: 'Mixin.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:22:11: Context: 'Mixin.mixedInAbstractGetter' is defined here.
+//   int get mixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:8:11: Context: 'Super.extendedAbstractGetter' is defined here.
+//   int get extendedAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_getter.dart:16:11: Context: 'Super.extendedAbstractMixedInAbstractGetter' is defined here.
+//   int get extendedAbstractMixedInAbstractGetter;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  get extendedConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractGetter() → core::int;
+  get extendedConcreteMixedInConcreteGetter() → core::int
+    return 0;
+  abstract get extendedAbstractMixedInConcreteGetter() → core::int;
+  get extendedConcreteMixedInAbstractGetter() → core::int
+    return 0;
+  abstract get extendedAbstractMixedInAbstractGetter() → core::int;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  get mixedInConcreteGetter() → core::int
+    return 0;
+  abstract get mixedInAbstractGetter() → core::int;
+  get extendedConcreteMixedInConcreteGetter() → core::int
+    return 0;
+  get extendedAbstractMixedInConcreteGetter() → core::int
+    return 0;
+  abstract get extendedConcreteMixedInAbstractGetter() → core::int;
+  abstract get extendedAbstractMixedInAbstractGetter() → core::int;
+}
+abstract class _ClassMixin&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  get mixedInConcreteGetter() → core::int
+    return 0;
+  get extendedConcreteMixedInConcreteGetter() → core::int
+    return 0;
+  get extendedAbstractMixedInConcreteGetter() → core::int
+    return 0;
+  abstract get extendedConcreteMixedInAbstractGetter() → core::int;
+  abstract get mixedInAbstractGetter() → core::int;
+  abstract get extendedAbstractMixedInAbstractGetter() → core::int;
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  get mixedInConcreteGetter() → core::int
+    return 0;
+  get extendedConcreteMixedInConcreteGetter() → core::int
+    return 0;
+  get extendedAbstractMixedInConcreteGetter() → core::int
+    return 0;
+  abstract get extendedConcreteMixedInAbstractGetter() → core::int;
+  abstract get mixedInAbstractGetter() → core::int;
+  abstract get extendedAbstractMixedInAbstractGetter() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart
new file mode 100644
index 0000000..89e649d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart
@@ -0,0 +1,37 @@
+// 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 Super {
+  void extendedConcreteMethod() {}
+
+  void extendedAbstractMethod();
+
+  void extendedConcreteMixedInConcreteMethod() {}
+
+  void extendedAbstractMixedInConcreteMethod();
+
+  void extendedConcreteMixedInAbstractMethod() {}
+
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+class Mixin {
+  void mixedInConcreteMethod() {}
+
+  void mixedInAbstractMethod();
+
+  void extendedConcreteMixedInConcreteMethod() {}
+
+  void extendedAbstractMixedInConcreteMethod() {}
+
+  void extendedConcreteMixedInAbstractMethod();
+
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.textual_outline.expect
new file mode 100644
index 0000000..e43b692
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+class Super {
+  void extendedConcreteMethod() {}
+  void extendedAbstractMethod();
+  void extendedConcreteMixedInConcreteMethod() {}
+  void extendedAbstractMixedInConcreteMethod();
+  void extendedConcreteMixedInAbstractMethod() {}
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+class Mixin {
+  void mixedInConcreteMethod() {}
+  void mixedInAbstractMethod();
+  void extendedConcreteMixedInConcreteMethod() {}
+  void extendedAbstractMixedInConcreteMethod() {}
+  void extendedConcreteMixedInAbstractMethod();
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b27951c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,23 @@
+class ClassMixin extends Super with Mixin {}
+
+class Mixin {
+  void extendedAbstractMixedInAbstractMethod();
+  void extendedAbstractMixedInConcreteMethod() {}
+  void extendedConcreteMixedInAbstractMethod();
+  void extendedConcreteMixedInConcreteMethod() {}
+  void mixedInAbstractMethod();
+  void mixedInConcreteMethod() {}
+}
+
+class NamedMixin = Super with Mixin;
+
+class Super {
+  void extendedAbstractMethod();
+  void extendedAbstractMixedInAbstractMethod();
+  void extendedAbstractMixedInConcreteMethod();
+  void extendedConcreteMethod() {}
+  void extendedConcreteMixedInAbstractMethod() {}
+  void extendedConcreteMixedInConcreteMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.weak.expect
new file mode 100644
index 0000000..2c5b765
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.weak.expect
@@ -0,0 +1,159 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+//  - Super.extendedAbstractMixedInConcreteMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:12:8: Context: 'Super.extendedAbstractMixedInConcreteMethod' is defined here.
+//   void extendedAbstractMixedInConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.extendedConcreteMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:28:8: Context: 'Mixin.extendedConcreteMixedInAbstractMethod' is defined here.
+//   void extendedConcreteMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  abstract method extendedAbstractMixedInConcreteMethod() → void;
+  method extendedConcreteMixedInAbstractMethod() → void {}
+  abstract method extendedAbstractMixedInAbstractMethod() → void;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method mixedInConcreteMethod() → void {}
+  abstract method mixedInAbstractMethod() → void;
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  method extendedAbstractMixedInConcreteMethod() → void {}
+  abstract method extendedConcreteMixedInAbstractMethod() → void;
+  abstract method extendedAbstractMixedInAbstractMethod() → void;
+}
+abstract class _ClassMixin&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInConcreteMethod() → void
+    return super.{self::Mixin::mixedInConcreteMethod}();
+  mixin-super-stub method extendedConcreteMixedInConcreteMethod() → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteMethod}();
+  mixin-super-stub method extendedAbstractMixedInConcreteMethod() → void
+    return super.{self::Mixin::extendedAbstractMixedInConcreteMethod}();
+  abstract mixin-stub method extendedConcreteMixedInAbstractMethod() → void; -> self::Mixin::extendedConcreteMixedInAbstractMethod
+  abstract mixin-stub method mixedInAbstractMethod() → void; -> self::Mixin::mixedInAbstractMethod
+  abstract mixin-stub method extendedAbstractMixedInAbstractMethod() → void; -> self::Mixin::extendedAbstractMixedInAbstractMethod
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin = self::Super with self::Mixin {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInConcreteMethod() → void
+    return super.{self::Mixin::mixedInConcreteMethod}();
+  mixin-super-stub method extendedConcreteMixedInConcreteMethod() → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteMethod}();
+  mixin-super-stub method extendedAbstractMixedInConcreteMethod() → void
+    return super.{self::Mixin::extendedAbstractMixedInConcreteMethod}();
+  abstract mixin-stub method extendedConcreteMixedInAbstractMethod() → void; -> self::Mixin::extendedConcreteMixedInAbstractMethod
+  abstract mixin-stub method mixedInAbstractMethod() → void; -> self::Mixin::mixedInAbstractMethod
+  abstract mixin-stub method extendedAbstractMixedInAbstractMethod() → void; -> self::Mixin::extendedAbstractMixedInAbstractMethod
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..ab66dec
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart.weak.transformed.expect
@@ -0,0 +1,153 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+//  - Super.extendedAbstractMixedInConcreteMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:12:8: Context: 'Super.extendedAbstractMixedInConcreteMethod' is defined here.
+//   void extendedAbstractMixedInConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.extendedConcreteMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:28:8: Context: 'Mixin.extendedConcreteMixedInAbstractMethod' is defined here.
+//   void extendedConcreteMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_method.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  abstract method extendedAbstractMixedInConcreteMethod() → void;
+  method extendedConcreteMixedInAbstractMethod() → void {}
+  abstract method extendedAbstractMixedInAbstractMethod() → void;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method mixedInConcreteMethod() → void {}
+  abstract method mixedInAbstractMethod() → void;
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  method extendedAbstractMixedInConcreteMethod() → void {}
+  abstract method extendedConcreteMixedInAbstractMethod() → void;
+  abstract method extendedAbstractMixedInAbstractMethod() → void;
+}
+abstract class _ClassMixin&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  method mixedInConcreteMethod() → void {}
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  method extendedAbstractMixedInConcreteMethod() → void {}
+  abstract method extendedConcreteMixedInAbstractMethod() → void;
+  abstract method mixedInAbstractMethod() → void;
+  abstract method extendedAbstractMixedInAbstractMethod() → void;
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  method mixedInConcreteMethod() → void {}
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  method extendedAbstractMixedInConcreteMethod() → void {}
+  abstract method extendedConcreteMixedInAbstractMethod() → void;
+  abstract method mixedInAbstractMethod() → void;
+  abstract method extendedAbstractMixedInAbstractMethod() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart
new file mode 100644
index 0000000..c841e04
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart
@@ -0,0 +1,37 @@
+// 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 Super {
+  void extendedConcreteMethod() {}
+
+  void extendedAbstractMethod();
+
+  void extendedConcreteMixedInConcreteMethod() {}
+
+  void extendedAbstractMixedInConcreteMethod();
+
+  void extendedConcreteMixedInAbstractMethod() {}
+
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+class Mixin {
+  void mixedInConcreteMethod(int i) {}
+
+  void mixedInAbstractMethod(int i);
+
+  void extendedConcreteMixedInConcreteMethod(int i) {}
+
+  void extendedAbstractMixedInConcreteMethod(int i) {}
+
+  void extendedConcreteMixedInAbstractMethod(int i);
+
+  void extendedAbstractMixedInAbstractMethod(int i);
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.textual_outline.expect
new file mode 100644
index 0000000..00840cb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+class Super {
+  void extendedConcreteMethod() {}
+  void extendedAbstractMethod();
+  void extendedConcreteMixedInConcreteMethod() {}
+  void extendedAbstractMixedInConcreteMethod();
+  void extendedConcreteMixedInAbstractMethod() {}
+  void extendedAbstractMixedInAbstractMethod();
+}
+
+class Mixin {
+  void mixedInConcreteMethod(int i) {}
+  void mixedInAbstractMethod(int i);
+  void extendedConcreteMixedInConcreteMethod(int i) {}
+  void extendedAbstractMixedInConcreteMethod(int i) {}
+  void extendedConcreteMixedInAbstractMethod(int i);
+  void extendedAbstractMixedInAbstractMethod(int i);
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7e10520
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.textual_outline_modelled.expect
@@ -0,0 +1,23 @@
+class ClassMixin extends Super with Mixin {}
+
+class Mixin {
+  void extendedAbstractMixedInAbstractMethod(int i);
+  void extendedAbstractMixedInConcreteMethod(int i) {}
+  void extendedConcreteMixedInAbstractMethod(int i);
+  void extendedConcreteMixedInConcreteMethod(int i) {}
+  void mixedInAbstractMethod(int i);
+  void mixedInConcreteMethod(int i) {}
+}
+
+class NamedMixin = Super with Mixin;
+
+class Super {
+  void extendedAbstractMethod();
+  void extendedAbstractMixedInAbstractMethod();
+  void extendedAbstractMixedInConcreteMethod();
+  void extendedConcreteMethod() {}
+  void extendedConcreteMixedInAbstractMethod() {}
+  void extendedConcreteMixedInConcreteMethod() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.weak.expect
new file mode 100644
index 0000000..77883ed
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart.weak.expect
@@ -0,0 +1,249 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+//  - Super.extendedAbstractMixedInConcreteMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:12:8: Context: 'Super.extendedAbstractMixedInConcreteMethod' is defined here.
+//   void extendedAbstractMixedInConcreteMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.extendedConcreteMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:28:8: Context: 'Mixin.extendedConcreteMixedInAbstractMethod' is defined here.
+//   void extendedConcreteMixedInAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractMethod
+//  - Mixin.mixedInAbstractMethod
+//  - Super.extendedAbstractMethod
+//  - Super.extendedAbstractMixedInAbstractMethod
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:30:8: Context: 'Mixin.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:22:8: Context: 'Mixin.mixedInAbstractMethod' is defined here.
+//   void mixedInAbstractMethod(int i);
+//        ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:8:8: Context: 'Super.extendedAbstractMethod' is defined here.
+//   void extendedAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:16:8: Context: 'Super.extendedAbstractMixedInAbstractMethod' is defined here.
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:33:7: Error: Applying the mixin 'Mixin' to 'Super' introduces an erroneous override of 'extendedConcreteMixedInConcreteMethod'.
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:24:8: Context: The method 'Mixin.extendedConcreteMixedInConcreteMethod' has more required arguments than those of overridden method 'Super.extendedConcreteMixedInConcreteMethod'.
+//   void extendedConcreteMixedInConcreteMethod(int i) {}
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:10:8: Context: This is the overridden method ('extendedConcreteMixedInConcreteMethod').
+//   void extendedConcreteMixedInConcreteMethod() {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:33:7: Error: Applying the mixin 'Mixin' to 'Super' introduces an erroneous override of 'extendedAbstractMixedInConcreteMethod'.
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:26:8: Context: The method 'Mixin.extendedAbstractMixedInConcreteMethod' has more required arguments than those of overridden method 'Super.extendedAbstractMixedInConcreteMethod'.
+//   void extendedAbstractMixedInConcreteMethod(int i) {}
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:12:8: Context: This is the overridden method ('extendedAbstractMixedInConcreteMethod').
+//   void extendedAbstractMixedInConcreteMethod();
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:33:7: Error: Applying the mixin 'Mixin' to 'Super' introduces an erroneous override of 'extendedConcreteMixedInAbstractMethod'.
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:28:8: Context: The method 'Mixin.extendedConcreteMixedInAbstractMethod' has more required arguments than those of overridden method 'Super.extendedConcreteMixedInAbstractMethod'.
+//   void extendedConcreteMixedInAbstractMethod(int i);
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:14:8: Context: This is the overridden method ('extendedConcreteMixedInAbstractMethod').
+//   void extendedConcreteMixedInAbstractMethod() {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:33:7: Error: Applying the mixin 'Mixin' to 'Super' introduces an erroneous override of 'extendedAbstractMixedInAbstractMethod'.
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:30:8: Context: The method 'Mixin.extendedAbstractMixedInAbstractMethod' has more required arguments than those of overridden method 'Super.extendedAbstractMixedInAbstractMethod'.
+//   void extendedAbstractMixedInAbstractMethod(int i);
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:16:8: Context: This is the overridden method ('extendedAbstractMixedInAbstractMethod').
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:33:7: Error: The implementation of 'extendedConcreteMixedInAbstractMethod' in the non-abstract class 'ClassMixin' does not conform to its interface.
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:14:8: Context: The method 'Super.extendedConcreteMixedInAbstractMethod' has fewer positional arguments than those of overridden method 'Super with Mixin.extendedConcreteMixedInAbstractMethod'.
+//   void extendedConcreteMixedInAbstractMethod() {}
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:33:7: Context: This is the overridden method ('extendedConcreteMixedInAbstractMethod').
+// class ClassMixin extends Super with Mixin {}
+//       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:35:7: Error: The mixin application class 'NamedMixin' introduces an erroneous override of 'extendedConcreteMixedInConcreteMethod'.
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:24:8: Context: The method 'Mixin.extendedConcreteMixedInConcreteMethod' has more required arguments than those of overridden method 'Super.extendedConcreteMixedInConcreteMethod'.
+//   void extendedConcreteMixedInConcreteMethod(int i) {}
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:10:8: Context: This is the overridden method ('extendedConcreteMixedInConcreteMethod').
+//   void extendedConcreteMixedInConcreteMethod() {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:35:7: Error: The mixin application class 'NamedMixin' introduces an erroneous override of 'extendedAbstractMixedInConcreteMethod'.
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:26:8: Context: The method 'Mixin.extendedAbstractMixedInConcreteMethod' has more required arguments than those of overridden method 'Super.extendedAbstractMixedInConcreteMethod'.
+//   void extendedAbstractMixedInConcreteMethod(int i) {}
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:12:8: Context: This is the overridden method ('extendedAbstractMixedInConcreteMethod').
+//   void extendedAbstractMixedInConcreteMethod();
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:35:7: Error: The mixin application class 'NamedMixin' introduces an erroneous override of 'extendedConcreteMixedInAbstractMethod'.
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:28:8: Context: The method 'Mixin.extendedConcreteMixedInAbstractMethod' has more required arguments than those of overridden method 'Super.extendedConcreteMixedInAbstractMethod'.
+//   void extendedConcreteMixedInAbstractMethod(int i);
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:14:8: Context: This is the overridden method ('extendedConcreteMixedInAbstractMethod').
+//   void extendedConcreteMixedInAbstractMethod() {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:35:7: Error: The mixin application class 'NamedMixin' introduces an erroneous override of 'extendedAbstractMixedInAbstractMethod'.
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:30:8: Context: The method 'Mixin.extendedAbstractMixedInAbstractMethod' has more required arguments than those of overridden method 'Super.extendedAbstractMixedInAbstractMethod'.
+//   void extendedAbstractMixedInAbstractMethod(int i);
+//        ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_override.dart:16:8: Context: This is the overridden method ('extendedAbstractMixedInAbstractMethod').
+//   void extendedAbstractMixedInAbstractMethod();
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedConcreteMethod() → void {}
+  abstract method extendedAbstractMethod() → void;
+  method extendedConcreteMixedInConcreteMethod() → void {}
+  abstract method extendedAbstractMixedInConcreteMethod() → void;
+  method extendedConcreteMixedInAbstractMethod() → void {}
+  abstract method extendedAbstractMixedInAbstractMethod() → void;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method mixedInConcreteMethod(core::int i) → void {}
+  abstract method mixedInAbstractMethod(core::int i) → void;
+  method extendedConcreteMixedInConcreteMethod(core::int i) → void {}
+  method extendedAbstractMixedInConcreteMethod(core::int i) → void {}
+  abstract method extendedConcreteMixedInAbstractMethod(core::int i) → void;
+  abstract method extendedAbstractMixedInAbstractMethod(core::int i) → void;
+}
+abstract class _ClassMixin&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInConcreteMethod(core::int i) → void
+    return super.{self::Mixin::mixedInConcreteMethod}(i);
+  mixin-super-stub method extendedConcreteMixedInConcreteMethod(core::int i) → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteMethod}(i);
+  mixin-super-stub method extendedAbstractMixedInConcreteMethod(core::int i) → void
+    return super.{self::Mixin::extendedAbstractMixedInConcreteMethod}(i);
+  abstract mixin-stub method extendedConcreteMixedInAbstractMethod(core::int i) → void; -> self::Mixin::extendedConcreteMixedInAbstractMethod
+  abstract mixin-stub method mixedInAbstractMethod(core::int i) → void; -> self::Mixin::mixedInAbstractMethod
+  abstract mixin-stub method extendedAbstractMixedInAbstractMethod(core::int i) → void; -> self::Mixin::extendedAbstractMixedInAbstractMethod
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin = self::Super with self::Mixin {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInConcreteMethod(core::int i) → void
+    return super.{self::Mixin::mixedInConcreteMethod}(i);
+  mixin-super-stub method extendedConcreteMixedInConcreteMethod(core::int i) → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteMethod}(i);
+  mixin-super-stub method extendedAbstractMixedInConcreteMethod(core::int i) → void
+    return super.{self::Mixin::extendedAbstractMixedInConcreteMethod}(i);
+  abstract mixin-stub method extendedConcreteMixedInAbstractMethod(core::int i) → void; -> self::Mixin::extendedConcreteMixedInAbstractMethod
+  abstract mixin-stub method mixedInAbstractMethod(core::int i) → void; -> self::Mixin::mixedInAbstractMethod
+  abstract mixin-stub method extendedAbstractMixedInAbstractMethod(core::int i) → void; -> self::Mixin::extendedAbstractMixedInAbstractMethod
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart
new file mode 100644
index 0000000..3a6cf3f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart
@@ -0,0 +1,37 @@
+// 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 Super {
+  void set extendedConcreteSetter(int i) {}
+
+  void set extendedAbstractSetter(int i);
+
+  void set extendedConcreteMixedInConcreteSetter(int i) {}
+
+  void set extendedAbstractMixedInConcreteSetter(int i);
+
+  void set extendedConcreteMixedInAbstractSetter(int i) {}
+
+  void set extendedAbstractMixedInAbstractSetter(int i);
+}
+
+class Mixin {
+  void set mixedInConcreteSetter(int i) {}
+
+  void set mixedInAbstractSetter(int i);
+
+  void set extendedConcreteMixedInConcreteSetter(int i) {}
+
+  void set extendedAbstractMixedInConcreteSetter(int i) {}
+
+  void set extendedConcreteMixedInAbstractSetter(int i);
+
+  void set extendedAbstractMixedInAbstractSetter(int i);
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.textual_outline.expect
new file mode 100644
index 0000000..92bb982
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+class Super {
+  void set extendedConcreteSetter(int i) {}
+  void set extendedAbstractSetter(int i);
+  void set extendedConcreteMixedInConcreteSetter(int i) {}
+  void set extendedAbstractMixedInConcreteSetter(int i);
+  void set extendedConcreteMixedInAbstractSetter(int i) {}
+  void set extendedAbstractMixedInAbstractSetter(int i);
+}
+
+class Mixin {
+  void set mixedInConcreteSetter(int i) {}
+  void set mixedInAbstractSetter(int i);
+  void set extendedConcreteMixedInConcreteSetter(int i) {}
+  void set extendedAbstractMixedInConcreteSetter(int i) {}
+  void set extendedConcreteMixedInAbstractSetter(int i);
+  void set extendedAbstractMixedInAbstractSetter(int i);
+}
+
+class ClassMixin extends Super with Mixin {}
+
+class NamedMixin = Super with Mixin;
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1cb957d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,23 @@
+class ClassMixin extends Super with Mixin {}
+
+class Mixin {
+  void set extendedAbstractMixedInAbstractSetter(int i);
+  void set extendedAbstractMixedInConcreteSetter(int i) {}
+  void set extendedConcreteMixedInAbstractSetter(int i);
+  void set extendedConcreteMixedInConcreteSetter(int i) {}
+  void set mixedInAbstractSetter(int i);
+  void set mixedInConcreteSetter(int i) {}
+}
+
+class NamedMixin = Super with Mixin;
+
+class Super {
+  void set extendedAbstractMixedInAbstractSetter(int i);
+  void set extendedAbstractMixedInConcreteSetter(int i);
+  void set extendedAbstractSetter(int i);
+  void set extendedConcreteMixedInAbstractSetter(int i) {}
+  void set extendedConcreteMixedInConcreteSetter(int i) {}
+  void set extendedConcreteSetter(int i) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.weak.expect
new file mode 100644
index 0000000..c9a2f79
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.weak.expect
@@ -0,0 +1,159 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractMixedInAbstractSetter=
+//  - Super.extendedAbstractMixedInConcreteSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:16:12: Context: 'Super.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:12:12: Context: 'Super.extendedAbstractMixedInConcreteSetter=' is defined here.
+//   void set extendedAbstractMixedInConcreteSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractSetter=
+//  - Mixin.extendedConcreteMixedInAbstractSetter=
+//  - Mixin.mixedInAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:30:12: Context: 'Mixin.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:28:12: Context: 'Mixin.extendedConcreteMixedInAbstractSetter=' is defined here.
+//   void set extendedConcreteMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:22:12: Context: 'Mixin.mixedInAbstractSetter=' is defined here.
+//   void set mixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractSetter=
+//  - Mixin.mixedInAbstractSetter=
+//  - Super.extendedAbstractMixedInAbstractSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:30:12: Context: 'Mixin.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:22:12: Context: 'Mixin.mixedInAbstractSetter=' is defined here.
+//   void set mixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:16:12: Context: 'Super.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractSetter=
+//  - Mixin.mixedInAbstractSetter=
+//  - Super.extendedAbstractMixedInAbstractSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:30:12: Context: 'Mixin.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:22:12: Context: 'Mixin.mixedInAbstractSetter=' is defined here.
+//   void set mixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:16:12: Context: 'Super.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  set extendedConcreteSetter(core::int i) → void {}
+  abstract set extendedAbstractSetter(core::int i) → void;
+  set extendedConcreteMixedInConcreteSetter(core::int i) → void {}
+  abstract set extendedAbstractMixedInConcreteSetter(core::int i) → void;
+  set extendedConcreteMixedInAbstractSetter(core::int i) → void {}
+  abstract set extendedAbstractMixedInAbstractSetter(core::int i) → void;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  set mixedInConcreteSetter(core::int i) → void {}
+  abstract set mixedInAbstractSetter(core::int i) → void;
+  set extendedConcreteMixedInConcreteSetter(core::int i) → void {}
+  set extendedAbstractMixedInConcreteSetter(core::int i) → void {}
+  abstract set extendedConcreteMixedInAbstractSetter(core::int i) → void;
+  abstract set extendedAbstractMixedInAbstractSetter(core::int i) → void;
+}
+abstract class _ClassMixin&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub set mixedInConcreteSetter(core::int i) → void
+    return super.{self::Mixin::mixedInConcreteSetter} = i;
+  mixin-super-stub set extendedConcreteMixedInConcreteSetter(core::int i) → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteSetter} = i;
+  mixin-super-stub set extendedAbstractMixedInConcreteSetter(core::int i) → void
+    return super.{self::Mixin::extendedAbstractMixedInConcreteSetter} = i;
+  abstract mixin-stub set extendedConcreteMixedInAbstractSetter(core::int i) → void; -> self::Mixin::extendedConcreteMixedInAbstractSetter
+  abstract mixin-stub set mixedInAbstractSetter(core::int i) → void; -> self::Mixin::mixedInAbstractSetter
+  abstract mixin-stub set extendedAbstractMixedInAbstractSetter(core::int i) → void; -> self::Mixin::extendedAbstractMixedInAbstractSetter
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin = self::Super with self::Mixin {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub set mixedInConcreteSetter(core::int i) → void
+    return super.{self::Mixin::mixedInConcreteSetter} = i;
+  mixin-super-stub set extendedConcreteMixedInConcreteSetter(core::int i) → void
+    return super.{self::Mixin::extendedConcreteMixedInConcreteSetter} = i;
+  mixin-super-stub set extendedAbstractMixedInConcreteSetter(core::int i) → void
+    return super.{self::Mixin::extendedAbstractMixedInConcreteSetter} = i;
+  abstract mixin-stub set extendedConcreteMixedInAbstractSetter(core::int i) → void; -> self::Mixin::extendedConcreteMixedInAbstractSetter
+  abstract mixin-stub set mixedInAbstractSetter(core::int i) → void; -> self::Mixin::mixedInAbstractSetter
+  abstract mixin-stub set extendedAbstractMixedInAbstractSetter(core::int i) → void; -> self::Mixin::extendedAbstractMixedInAbstractSetter
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.weak.transformed.expect
new file mode 100644
index 0000000..7bdf664
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart.weak.transformed.expect
@@ -0,0 +1,153 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:5:7: Error: The non-abstract class 'Super' is missing implementations for these members:
+//  - Super.extendedAbstractMixedInAbstractSetter=
+//  - Super.extendedAbstractMixedInConcreteSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:16:12: Context: 'Super.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:12:12: Context: 'Super.extendedAbstractMixedInConcreteSetter=' is defined here.
+//   void set extendedAbstractMixedInConcreteSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:19:7: Error: The non-abstract class 'Mixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractSetter=
+//  - Mixin.extendedConcreteMixedInAbstractSetter=
+//  - Mixin.mixedInAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class Mixin {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:30:12: Context: 'Mixin.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:28:12: Context: 'Mixin.extendedConcreteMixedInAbstractSetter=' is defined here.
+//   void set extendedConcreteMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:22:12: Context: 'Mixin.mixedInAbstractSetter=' is defined here.
+//   void set mixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:33:7: Error: The non-abstract class 'ClassMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractSetter=
+//  - Mixin.mixedInAbstractSetter=
+//  - Super.extendedAbstractMixedInAbstractSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class ClassMixin extends Super with Mixin {}
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:30:12: Context: 'Mixin.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:22:12: Context: 'Mixin.mixedInAbstractSetter=' is defined here.
+//   void set mixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:16:12: Context: 'Super.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:35:7: Error: The non-abstract class 'NamedMixin' is missing implementations for these members:
+//  - Mixin.extendedAbstractMixedInAbstractSetter=
+//  - Mixin.mixedInAbstractSetter=
+//  - Super.extendedAbstractMixedInAbstractSetter=
+//  - Super.extendedAbstractSetter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class NamedMixin = Super with Mixin;
+//       ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:30:12: Context: 'Mixin.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:22:12: Context: 'Mixin.mixedInAbstractSetter=' is defined here.
+//   void set mixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:16:12: Context: 'Super.extendedAbstractMixedInAbstractSetter=' is defined here.
+//   void set extendedAbstractMixedInAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/mix_in_setter.dart:8:12: Context: 'Super.extendedAbstractSetter=' is defined here.
+//   void set extendedAbstractSetter(int i);
+//            ^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  set extendedConcreteSetter(core::int i) → void {}
+  abstract set extendedAbstractSetter(core::int i) → void;
+  set extendedConcreteMixedInConcreteSetter(core::int i) → void {}
+  abstract set extendedAbstractMixedInConcreteSetter(core::int i) → void;
+  set extendedConcreteMixedInAbstractSetter(core::int i) → void {}
+  abstract set extendedAbstractMixedInAbstractSetter(core::int i) → void;
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  set mixedInConcreteSetter(core::int i) → void {}
+  abstract set mixedInAbstractSetter(core::int i) → void;
+  set extendedConcreteMixedInConcreteSetter(core::int i) → void {}
+  set extendedAbstractMixedInConcreteSetter(core::int i) → void {}
+  abstract set extendedConcreteMixedInAbstractSetter(core::int i) → void;
+  abstract set extendedAbstractMixedInAbstractSetter(core::int i) → void;
+}
+abstract class _ClassMixin&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_ClassMixin&Super&Mixin
+    : super self::Super::•()
+    ;
+  set mixedInConcreteSetter(core::int i) → void {}
+  set extendedConcreteMixedInConcreteSetter(core::int i) → void {}
+  set extendedAbstractMixedInConcreteSetter(core::int i) → void {}
+  abstract set extendedConcreteMixedInAbstractSetter(core::int i) → void;
+  abstract set mixedInAbstractSetter(core::int i) → void;
+  abstract set extendedAbstractMixedInAbstractSetter(core::int i) → void;
+}
+class ClassMixin extends self::_ClassMixin&Super&Mixin {
+  synthetic constructor •() → self::ClassMixin
+    : super self::_ClassMixin&Super&Mixin::•()
+    ;
+}
+class NamedMixin extends self::Super implements self::Mixin /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::NamedMixin
+    : super self::Super::•()
+    ;
+  set mixedInConcreteSetter(core::int i) → void {}
+  set extendedConcreteMixedInConcreteSetter(core::int i) → void {}
+  set extendedAbstractMixedInConcreteSetter(core::int i) → void {}
+  abstract set extendedConcreteMixedInAbstractSetter(core::int i) → void;
+  abstract set mixedInAbstractSetter(core::int i) → void;
+  abstract set extendedAbstractMixedInAbstractSetter(core::int i) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart
new file mode 100644
index 0000000..f1e2e06
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.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.
+
+abstract class Interface {
+  void method();
+  int get getter;
+  void set setter(int value);
+  int field;
+  final int finalField;
+}
+
+class SuperAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class FromSuperAbstract extends SuperAbstract implements Interface {}
+
+class SuperConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return null;
+  }
+}
+
+class FromSuperConcrete extends SuperConcrete implements Interface {}
+
+class FromSuperConcreteAbstract extends SuperConcrete
+    implements SuperAbstract, Interface {}
+
+class MixinAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class FromMixinAbstract extends MixinAbstract implements Interface {}
+
+class MixinConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return null;
+  }
+}
+
+class FromMixinConcrete with MixinConcrete implements Interface {}
+
+class FromMixinConcreteAbstract
+    with MixinConcrete, MixinAbstract
+    implements Interface {}
+
+class InterfaceAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class FromInterfaceAbstract implements InterfaceAbstract, Interface {}
+
+class InterfaceConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return null;
+  }
+}
+
+class FromInterfaceConcrete implements InterfaceConcrete, Interface {}
+
+class DeclaredAbstract implements Interface {
+  noSuchMethod(Invocation invocation);
+}
+
+class DeclaredConcrete implements Interface {
+  @override
+  noSuchMethod(Invocation invocation) {
+    return null;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.textual_outline.expect
new file mode 100644
index 0000000..1093cfd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.textual_outline.expect
@@ -0,0 +1,64 @@
+abstract class Interface {
+  void method();
+  int get getter;
+  void set setter(int value);
+  int field;
+  final int finalField;
+}
+
+class SuperAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class FromSuperAbstract extends SuperAbstract implements Interface {}
+
+class SuperConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class FromSuperConcrete extends SuperConcrete implements Interface {}
+
+class FromSuperConcreteAbstract extends SuperConcrete
+    implements SuperAbstract, Interface {}
+
+class MixinAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class FromMixinAbstract extends MixinAbstract implements Interface {}
+
+class MixinConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class FromMixinConcrete with MixinConcrete implements Interface {}
+
+class FromMixinConcreteAbstract
+    with MixinConcrete, MixinAbstract
+    implements Interface {}
+
+class InterfaceAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class FromInterfaceAbstract implements InterfaceAbstract, Interface {}
+
+class InterfaceConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class FromInterfaceConcrete implements InterfaceConcrete, Interface {}
+
+class DeclaredAbstract implements Interface {
+  noSuchMethod(Invocation invocation);
+}
+
+class DeclaredConcrete implements Interface {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..27e9d70
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.textual_outline_modelled.expect
@@ -0,0 +1,64 @@
+abstract class Interface {
+  final int finalField;
+  int field;
+  int get getter;
+  void method();
+  void set setter(int value);
+}
+
+class DeclaredAbstract implements Interface {
+  noSuchMethod(Invocation invocation);
+}
+
+class DeclaredConcrete implements Interface {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class FromInterfaceAbstract implements InterfaceAbstract, Interface {}
+
+class FromInterfaceConcrete implements InterfaceConcrete, Interface {}
+
+class FromMixinAbstract extends MixinAbstract implements Interface {}
+
+class FromMixinConcrete with MixinConcrete implements Interface {}
+
+class FromMixinConcreteAbstract
+    with MixinConcrete, MixinAbstract
+    implements Interface {}
+
+class FromSuperAbstract extends SuperAbstract implements Interface {}
+
+class FromSuperConcrete extends SuperConcrete implements Interface {}
+
+class FromSuperConcreteAbstract extends SuperConcrete
+    implements SuperAbstract, Interface {}
+
+class InterfaceAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class InterfaceConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class MixinAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class MixinConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+class SuperAbstract {
+  noSuchMethod(Invocation invocation);
+}
+
+class SuperConcrete {
+  @override
+  noSuchMethod(Invocation invocation) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.weak.expect
new file mode 100644
index 0000000..0f94026
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.weak.expect
@@ -0,0 +1,370 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:17:7: Error: The non-abstract class 'FromSuperAbstract' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class FromSuperAbstract extends SuperAbstract implements Interface {}
+//       ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:35:7: Error: The non-abstract class 'FromMixinAbstract' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class FromMixinAbstract extends MixinAbstract implements Interface {}
+//       ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:54:7: Error: The non-abstract class 'FromInterfaceAbstract' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class FromInterfaceAbstract implements InterfaceAbstract, Interface {}
+//       ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:63:7: Error: The non-abstract class 'FromInterfaceConcrete' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class FromInterfaceConcrete implements InterfaceConcrete, Interface {}
+//       ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:65:7: Error: The non-abstract class 'DeclaredAbstract' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class DeclaredAbstract implements Interface {
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Error: Field 'field' should be initialized because its type 'int' doesn't allow null.
+//   int field;
+//       ^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Error: Final field 'finalField' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final int finalField;
+//             ^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int field = null;
+  final field core::int finalField = null;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract method method() → void;
+  abstract get getter() → core::int;
+  abstract set setter(core::int value) → void;
+}
+class SuperAbstract extends core::Object {
+  synthetic constructor •() → self::SuperAbstract
+    : super core::Object::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class FromSuperAbstract extends self::SuperAbstract implements self::Interface {
+  synthetic constructor •() → self::FromSuperAbstract
+    : super self::SuperAbstract::•()
+    ;
+}
+class SuperConcrete extends core::Object {
+  synthetic constructor •() → self::SuperConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+}
+class FromSuperConcrete extends self::SuperConcrete implements self::Interface {
+  synthetic constructor •() → self::FromSuperConcrete
+    : super self::SuperConcrete::•()
+    ;
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+class FromSuperConcreteAbstract extends self::SuperConcrete implements self::SuperAbstract, self::Interface {
+  synthetic constructor •() → self::FromSuperConcreteAbstract
+    : super self::SuperConcrete::•()
+    ;
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+class MixinAbstract extends core::Object {
+  synthetic constructor •() → self::MixinAbstract
+    : super core::Object::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class FromMixinAbstract extends self::MixinAbstract implements self::Interface {
+  synthetic constructor •() → self::FromMixinAbstract
+    : super self::MixinAbstract::•()
+    ;
+}
+class MixinConcrete extends core::Object {
+  synthetic constructor •() → self::MixinConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+}
+abstract class _FromMixinConcrete&Object&MixinConcrete = core::Object with self::MixinConcrete /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_FromMixinConcrete&Object&MixinConcrete
+    : super core::Object::•()
+    ;
+  mixin-super-stub method noSuchMethod(core::Invocation invocation) → dynamic
+    return super.{self::MixinConcrete::noSuchMethod}(invocation);
+}
+class FromMixinConcrete extends self::_FromMixinConcrete&Object&MixinConcrete implements self::Interface {
+  synthetic constructor •() → self::FromMixinConcrete
+    : super self::_FromMixinConcrete&Object&MixinConcrete::•()
+    ;
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+abstract class _FromMixinConcreteAbstract&Object&MixinConcrete = core::Object with self::MixinConcrete /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_FromMixinConcreteAbstract&Object&MixinConcrete
+    : super core::Object::•()
+    ;
+  mixin-super-stub method noSuchMethod(core::Invocation invocation) → dynamic
+    return super.{self::MixinConcrete::noSuchMethod}(invocation);
+}
+abstract class _FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract = self::_FromMixinConcreteAbstract&Object&MixinConcrete with self::MixinAbstract /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract
+    : super self::_FromMixinConcreteAbstract&Object&MixinConcrete::•()
+    ;
+  abstract mixin-stub method noSuchMethod(core::Invocation invocation) → dynamic; -> self::MixinAbstract::noSuchMethod
+}
+class FromMixinConcreteAbstract extends self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract implements self::Interface {
+  synthetic constructor •() → self::FromMixinConcreteAbstract
+    : super self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::•()
+    ;
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+class InterfaceAbstract extends core::Object {
+  synthetic constructor •() → self::InterfaceAbstract
+    : super core::Object::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class FromInterfaceAbstract extends core::Object implements self::InterfaceAbstract, self::Interface {
+  synthetic constructor •() → self::FromInterfaceAbstract
+    : super core::Object::•()
+    ;
+}
+class InterfaceConcrete extends core::Object {
+  synthetic constructor •() → self::InterfaceConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+}
+class FromInterfaceConcrete extends core::Object implements self::InterfaceConcrete, self::Interface {
+  synthetic constructor •() → self::FromInterfaceConcrete
+    : super core::Object::•()
+    ;
+}
+class DeclaredAbstract extends core::Object implements self::Interface {
+  synthetic constructor •() → self::DeclaredAbstract
+    : super core::Object::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class DeclaredConcrete extends core::Object implements self::Interface {
+  synthetic constructor •() → self::DeclaredConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = #getter
+  #C3 = <core::Type*>[]
+  #C4 = <dynamic>[]
+  #C5 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C4}
+  #C6 = #field
+  #C7 = #method
+  #C8 = #finalField
+  #C9 = #setter=
+  #C10 = #field=
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.weak.transformed.expect
new file mode 100644
index 0000000..730cbf4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart.weak.transformed.expect
@@ -0,0 +1,374 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:17:7: Error: The non-abstract class 'FromSuperAbstract' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class FromSuperAbstract extends SuperAbstract implements Interface {}
+//       ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:35:7: Error: The non-abstract class 'FromMixinAbstract' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class FromMixinAbstract extends MixinAbstract implements Interface {}
+//       ^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:54:7: Error: The non-abstract class 'FromInterfaceAbstract' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class FromInterfaceAbstract implements InterfaceAbstract, Interface {}
+//       ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:63:7: Error: The non-abstract class 'FromInterfaceConcrete' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class FromInterfaceConcrete implements InterfaceConcrete, Interface {}
+//       ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:65:7: Error: The non-abstract class 'DeclaredAbstract' is missing implementations for these members:
+//  - Interface.field
+//  - Interface.finalField
+//  - Interface.getter
+//  - Interface.method
+//  - Interface.setter=
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class DeclaredAbstract implements Interface {
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Context: 'Interface.field' is defined here.
+//   int field;
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Context: 'Interface.finalField' is defined here.
+//   final int finalField;
+//             ^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:7:11: Context: 'Interface.getter' is defined here.
+//   int get getter;
+//           ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:6:8: Context: 'Interface.method' is defined here.
+//   void method();
+//        ^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:8:12: Context: 'Interface.setter=' is defined here.
+//   void set setter(int value);
+//            ^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:9:7: Error: Field 'field' should be initialized because its type 'int' doesn't allow null.
+//   int field;
+//       ^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/no_such_method.dart:10:13: Error: Final field 'finalField' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final int finalField;
+//             ^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Interface extends core::Object {
+  field core::int field = null;
+  final field core::int finalField = null;
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  abstract method method() → void;
+  abstract get getter() → core::int;
+  abstract set setter(core::int value) → void;
+}
+class SuperAbstract extends core::Object {
+  synthetic constructor •() → self::SuperAbstract
+    : super core::Object::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class FromSuperAbstract extends self::SuperAbstract implements self::Interface {
+  synthetic constructor •() → self::FromSuperAbstract
+    : super self::SuperAbstract::•()
+    ;
+}
+class SuperConcrete extends core::Object {
+  synthetic constructor •() → self::SuperConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+}
+class FromSuperConcrete extends self::SuperConcrete implements self::Interface {
+  synthetic constructor •() → self::FromSuperConcrete
+    : super self::SuperConcrete::•()
+    ;
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+class FromSuperConcreteAbstract extends self::SuperConcrete implements self::SuperAbstract, self::Interface {
+  synthetic constructor •() → self::FromSuperConcreteAbstract
+    : super self::SuperConcrete::•()
+    ;
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::SuperConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+class MixinAbstract extends core::Object {
+  synthetic constructor •() → self::MixinAbstract
+    : super core::Object::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class FromMixinAbstract extends self::MixinAbstract implements self::Interface {
+  synthetic constructor •() → self::FromMixinAbstract
+    : super self::MixinAbstract::•()
+    ;
+}
+class MixinConcrete extends core::Object {
+  synthetic constructor •() → self::MixinConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+}
+abstract class _FromMixinConcrete&Object&MixinConcrete extends core::Object implements self::MixinConcrete /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_FromMixinConcrete&Object&MixinConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+}
+class FromMixinConcrete extends self::_FromMixinConcrete&Object&MixinConcrete implements self::Interface {
+  synthetic constructor •() → self::FromMixinConcrete
+    : super self::_FromMixinConcrete&Object&MixinConcrete::•()
+    ;
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::_FromMixinConcrete&Object&MixinConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+abstract class _FromMixinConcreteAbstract&Object&MixinConcrete extends core::Object implements self::MixinConcrete /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_FromMixinConcreteAbstract&Object&MixinConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+}
+abstract class _FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract extends self::_FromMixinConcreteAbstract&Object&MixinConcrete implements self::MixinAbstract /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract
+    : super self::_FromMixinConcreteAbstract&Object&MixinConcrete::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class FromMixinConcreteAbstract extends self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract implements self::Interface {
+  synthetic constructor •() → self::FromMixinConcreteAbstract
+    : super self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::•()
+    ;
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::_FromMixinConcreteAbstract&Object&MixinConcrete&MixinAbstract::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+class InterfaceAbstract extends core::Object {
+  synthetic constructor •() → self::InterfaceAbstract
+    : super core::Object::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class FromInterfaceAbstract extends core::Object implements self::InterfaceAbstract, self::Interface {
+  synthetic constructor •() → self::FromInterfaceAbstract
+    : super core::Object::•()
+    ;
+}
+class InterfaceConcrete extends core::Object {
+  synthetic constructor •() → self::InterfaceConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+}
+class FromInterfaceConcrete extends core::Object implements self::InterfaceConcrete, self::Interface {
+  synthetic constructor •() → self::FromInterfaceConcrete
+    : super core::Object::•()
+    ;
+}
+class DeclaredAbstract extends core::Object implements self::Interface {
+  synthetic constructor •() → self::DeclaredAbstract
+    : super core::Object::•()
+    ;
+  abstract method noSuchMethod(core::Invocation invocation) → dynamic;
+}
+class DeclaredConcrete extends core::Object implements self::Interface {
+  synthetic constructor •() → self::DeclaredConcrete
+    : super core::Object::•()
+    ;
+  @#C1
+  method noSuchMethod(core::Invocation invocation) → dynamic {
+    return null;
+  }
+  no-such-method-forwarder get getter() → core::int
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder get field() → core::int
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder method method() → void
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder get finalField() → core::int
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+  no-such-method-forwarder set setter(core::int value) → void
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+  no-such-method-forwarder set field(core::int value) → void
+    return this.{self::DeclaredConcrete::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = #getter
+  #C3 = <core::Type*>[]
+  #C4 = <dynamic>[]
+  #C5 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C4}
+  #C6 = #field
+  #C7 = #method
+  #C8 = #finalField
+  #C9 = #setter=
+  #C10 = #field=
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart
new file mode 100644
index 0000000..0231dd6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.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.
+
+// @dart=2.9
+
+class A {}
+
+class B extends A {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.textual_outline.expect
new file mode 100644
index 0000000..354d426
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+// @dart = 2.9
+class A {}
+
+class B extends A {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..354d426
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+// @dart = 2.9
+class A {}
+
+class B extends A {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.weak.expect
new file mode 100644
index 0000000..2bfc463
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.weak.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : 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
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.weak.transformed.expect
new file mode 100644
index 0000000..2bfc463
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/opt_out.dart.weak.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : 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
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart
new file mode 100644
index 0000000..2e1972e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Super {
+  // Not a valid implementation.
+  void extendedMethod1(int i) {}
+
+  // Valid implementation.
+  void extendedMethod2(num i) {}
+
+  void overriddenMethod1(int i) {}
+  void overriddenMethod2(num n) {}
+}
+
+class Class extends Super {
+  // Valid override.
+  void extendedMethod1(num n);
+
+  // Not a valid override.
+  void extendedMethod2(int i);
+
+  // Valid override
+  void overriddenMethod1(num n) {}
+
+  // Not a valid override
+  void overriddenMethod2(int n) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.textual_outline.expect
new file mode 100644
index 0000000..6c67ae9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+class Super {
+  void extendedMethod1(int i) {}
+  void extendedMethod2(num i) {}
+  void overriddenMethod1(int i) {}
+  void overriddenMethod2(num n) {}
+}
+
+class Class extends Super {
+  void extendedMethod1(num n);
+  void extendedMethod2(int i);
+  void overriddenMethod1(num n) {}
+  void overriddenMethod2(int n) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4a6783b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class Class extends Super {
+  void extendedMethod1(num n);
+  void extendedMethod2(int i);
+  void overriddenMethod1(num n) {}
+  void overriddenMethod2(int n) {}
+}
+
+class Super {
+  void extendedMethod1(int i) {}
+  void extendedMethod2(num i) {}
+  void overriddenMethod1(int i) {}
+  void overriddenMethod2(num n) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.weak.expect
new file mode 100644
index 0000000..773c139
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart.weak.expect
@@ -0,0 +1,53 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart:21:28: Error: The parameter 'i' of the method 'Class.extendedMethod2' has type 'int', which does not match the corresponding type, 'num', in the overridden method, 'Super.extendedMethod2'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   void extendedMethod2(int i);
+//                            ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart:10:8: Context: This is the overridden method ('extendedMethod2').
+//   void extendedMethod2(num i) {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart:27:30: Error: The parameter 'n' of the method 'Class.overriddenMethod2' has type 'int', which does not match the corresponding type, 'num', in the overridden method, 'Super.overriddenMethod2'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   void overriddenMethod2(int n) {}
+//                              ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart:13:8: Context: This is the overridden method ('overriddenMethod2').
+//   void overriddenMethod2(num n) {}
+//        ^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart:16:7: Error: The implementation of 'extendedMethod1' in the non-abstract class 'Class' does not conform to its interface.
+// class Class extends Super {
+//       ^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart:7:28: Context: The parameter 'i' of the method 'Super.extendedMethod1' has type 'int', which does not match the corresponding type, 'num', in the overridden method, 'Class.extendedMethod1'.
+// Change to a supertype of 'num', or, for a covariant parameter, a subtype.
+//   void extendedMethod1(int i) {}
+//                            ^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/override.dart:18:8: Context: This is the overridden method ('extendedMethod1').
+//   void extendedMethod1(num n);
+//        ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  method extendedMethod1(core::int i) → void {}
+  method extendedMethod2(core::num i) → void {}
+  method overriddenMethod1(core::int i) → void {}
+  method overriddenMethod2(core::num n) → void {}
+}
+class Class extends self::Super {
+  synthetic constructor •() → self::Class
+    : super self::Super::•()
+    ;
+  abstract method extendedMethod1(core::num n) → void;
+  abstract method extendedMethod2(core::int i) → void;
+  method overriddenMethod1(core::num n) → void {}
+  method overriddenMethod2(core::int n) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart
new file mode 100644
index 0000000..7fcd70b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.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.
+
+// Redirecting factories are encoded using static fields that need to be
+// handled by the class hierarchy builder.
+
+class Class {
+  factory Class.redirect() = Class;
+
+  Class();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.textual_outline.expect
new file mode 100644
index 0000000..29149af
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+class Class {
+  factory Class.redirect() = Class;
+  Class();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1862a83
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+class Class {
+  Class();
+  factory Class.redirect() = Class;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.weak.expect
new file mode 100644
index 0000000..03c441d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.weak.expect
@@ -0,0 +1,13 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class::redirect]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    let dynamic #redirecting_factory = self::Class::• in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.weak.transformed.expect
new file mode 100644
index 0000000..0c7726a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/redirecting_factory.dart.weak.transformed.expect
@@ -0,0 +1,13 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  static final field dynamic _redirecting# = <dynamic>[self::Class::redirect]/*isLegacy*/;
+  constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static factory redirect() → self::Class
+    let<BottomType> #redirecting_factory = self::Class::• in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart
new file mode 100644
index 0000000..3f86658
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart
@@ -0,0 +1,85 @@
+// 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 Super {
+  static void extendedStaticDeclaredInstanceMethod() {}
+  void extendedInstanceDeclaredStaticMethod() {}
+
+  static void set extendedStaticDeclaredInstanceSetter(int value) {}
+  void set extendedInstanceDeclaredStaticSetter(int value) {}
+
+  static int get extendedStaticGetterDeclaredInstanceSetter => 0;
+  int get extendedInstanceGetterDeclaredStaticSetter => 0;
+
+  static void set extendedStaticSetterDeclaredInstanceGetter(int value) {}
+  void set extendedInstanceSetterDeclaredStaticGetter(int value) {}
+
+  static void extendedStaticMixedInInstanceMethod() {}
+  void extendedInstanceMixedInStaticMethod() {}
+
+  static void extendedStaticImplementedInstanceMethod() {}
+  void extendedInstanceImplementedStaticMethod() {}
+}
+
+class Mixin {
+  static void mixedInStaticDeclaredInstanceMethod() {}
+  void mixedInInstanceDeclaredStaticMethod() {}
+
+  static void mixedInStaticImplementedInstanceMethod() {}
+  void mixedInInstanceImplementedStaticMethod() {}
+
+  void extendedStaticMixedInInstanceMethod() {}
+  static void extendedInstanceMixedInStaticMethod() {}
+}
+
+class Interface {
+  static void implementedStaticDeclaredInstanceMethod() {}
+  void implementedInstanceDeclaredStaticMethod() {}
+
+  static void set implementedStaticDeclaredInstanceSetter(int value) {}
+  void set implementedInstanceDeclaredStaticSetter(int value) {}
+
+  static int get implementedStaticGetterDeclaredInstanceSetter => 0;
+  int get implementedInstanceGetterDeclaredStaticSetter => 0;
+
+  static void set implementedStaticSetterDeclaredInstanceGetter(int value) {}
+  void set implementedInstanceSetterDeclaredStaticGetter(int value) {}
+
+  void extendedStaticImplementedInstanceMethod() {}
+  static void extendedInstanceImplementedStaticMethod() {}
+
+  void mixedInStaticImplementedInstanceMethod() {}
+  static void mixedInInstanceImplementedStaticMethod() {}
+}
+
+abstract class Class extends Super with Mixin implements Interface {
+  void extendedStaticDeclaredInstanceMethod() {}
+  static void extendedInstanceDeclaredStaticMethod() {}
+
+  void set extendedStaticDeclaredInstanceSetter(int value) {}
+  static void set extendedInstanceDeclaredStaticSetter(int value) {}
+
+  void set extendedStaticGetterDeclaredInstanceSetter(int value) {}
+  static void set extendedInstanceGetterDeclaredStaticSetter(int value) {}
+
+  int get extendedStaticSetterDeclaredInstanceGetter => 0;
+  static int get extendedInstanceSetterDeclaredStaticGetter => 0;
+
+  void mixedInStaticDeclaredInstanceMethod() {}
+  static void mixedInInstanceDeclaredStaticMethod() {}
+
+  void implementedStaticDeclaredInstanceMethod() {}
+  static void implementedInstanceDeclaredStaticMethod() {}
+
+  void set implementedStaticDeclaredInstanceSetter(int value) {}
+  static void set implementedInstanceDeclaredStaticSetter(int value) {}
+
+  void set implementedStaticGetterDeclaredInstanceSetter(int value) {}
+  static void set implementedInstanceGetterDeclaredStaticSetter(int value) {}
+
+  int get implementedStaticSetterDeclaredInstanceGetter => 0;
+  static int get implementedInstanceSetterDeclaredStaticGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.textual_outline.expect
new file mode 100644
index 0000000..fb0f36e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.textual_outline.expect
@@ -0,0 +1,61 @@
+class Super {
+  static void extendedStaticDeclaredInstanceMethod() {}
+  void extendedInstanceDeclaredStaticMethod() {}
+  static void set extendedStaticDeclaredInstanceSetter(int value) {}
+  void set extendedInstanceDeclaredStaticSetter(int value) {}
+  static int get extendedStaticGetterDeclaredInstanceSetter => 0;
+  int get extendedInstanceGetterDeclaredStaticSetter => 0;
+  static void set extendedStaticSetterDeclaredInstanceGetter(int value) {}
+  void set extendedInstanceSetterDeclaredStaticGetter(int value) {}
+  static void extendedStaticMixedInInstanceMethod() {}
+  void extendedInstanceMixedInStaticMethod() {}
+  static void extendedStaticImplementedInstanceMethod() {}
+  void extendedInstanceImplementedStaticMethod() {}
+}
+
+class Mixin {
+  static void mixedInStaticDeclaredInstanceMethod() {}
+  void mixedInInstanceDeclaredStaticMethod() {}
+  static void mixedInStaticImplementedInstanceMethod() {}
+  void mixedInInstanceImplementedStaticMethod() {}
+  void extendedStaticMixedInInstanceMethod() {}
+  static void extendedInstanceMixedInStaticMethod() {}
+}
+
+class Interface {
+  static void implementedStaticDeclaredInstanceMethod() {}
+  void implementedInstanceDeclaredStaticMethod() {}
+  static void set implementedStaticDeclaredInstanceSetter(int value) {}
+  void set implementedInstanceDeclaredStaticSetter(int value) {}
+  static int get implementedStaticGetterDeclaredInstanceSetter => 0;
+  int get implementedInstanceGetterDeclaredStaticSetter => 0;
+  static void set implementedStaticSetterDeclaredInstanceGetter(int value) {}
+  void set implementedInstanceSetterDeclaredStaticGetter(int value) {}
+  void extendedStaticImplementedInstanceMethod() {}
+  static void extendedInstanceImplementedStaticMethod() {}
+  void mixedInStaticImplementedInstanceMethod() {}
+  static void mixedInInstanceImplementedStaticMethod() {}
+}
+
+abstract class Class extends Super with Mixin implements Interface {
+  void extendedStaticDeclaredInstanceMethod() {}
+  static void extendedInstanceDeclaredStaticMethod() {}
+  void set extendedStaticDeclaredInstanceSetter(int value) {}
+  static void set extendedInstanceDeclaredStaticSetter(int value) {}
+  void set extendedStaticGetterDeclaredInstanceSetter(int value) {}
+  static void set extendedInstanceGetterDeclaredStaticSetter(int value) {}
+  int get extendedStaticSetterDeclaredInstanceGetter => 0;
+  static int get extendedInstanceSetterDeclaredStaticGetter => 0;
+  void mixedInStaticDeclaredInstanceMethod() {}
+  static void mixedInInstanceDeclaredStaticMethod() {}
+  void implementedStaticDeclaredInstanceMethod() {}
+  static void implementedInstanceDeclaredStaticMethod() {}
+  void set implementedStaticDeclaredInstanceSetter(int value) {}
+  static void set implementedInstanceDeclaredStaticSetter(int value) {}
+  void set implementedStaticGetterDeclaredInstanceSetter(int value) {}
+  static void set implementedInstanceGetterDeclaredStaticSetter(int value) {}
+  int get implementedStaticSetterDeclaredInstanceGetter => 0;
+  static int get implementedInstanceSetterDeclaredStaticGetter => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c1f3a13
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.textual_outline_modelled.expect
@@ -0,0 +1,61 @@
+abstract class Class extends Super with Mixin implements Interface {
+  int get extendedStaticSetterDeclaredInstanceGetter => 0;
+  int get implementedStaticSetterDeclaredInstanceGetter => 0;
+  static int get extendedInstanceSetterDeclaredStaticGetter => 0;
+  static int get implementedInstanceSetterDeclaredStaticGetter => 0;
+  static void extendedInstanceDeclaredStaticMethod() {}
+  static void implementedInstanceDeclaredStaticMethod() {}
+  static void mixedInInstanceDeclaredStaticMethod() {}
+  static void set extendedInstanceDeclaredStaticSetter(int value) {}
+  static void set extendedInstanceGetterDeclaredStaticSetter(int value) {}
+  static void set implementedInstanceDeclaredStaticSetter(int value) {}
+  static void set implementedInstanceGetterDeclaredStaticSetter(int value) {}
+  void extendedStaticDeclaredInstanceMethod() {}
+  void implementedStaticDeclaredInstanceMethod() {}
+  void mixedInStaticDeclaredInstanceMethod() {}
+  void set extendedStaticDeclaredInstanceSetter(int value) {}
+  void set extendedStaticGetterDeclaredInstanceSetter(int value) {}
+  void set implementedStaticDeclaredInstanceSetter(int value) {}
+  void set implementedStaticGetterDeclaredInstanceSetter(int value) {}
+}
+
+class Interface {
+  int get implementedInstanceGetterDeclaredStaticSetter => 0;
+  static int get implementedStaticGetterDeclaredInstanceSetter => 0;
+  static void extendedInstanceImplementedStaticMethod() {}
+  static void implementedStaticDeclaredInstanceMethod() {}
+  static void mixedInInstanceImplementedStaticMethod() {}
+  static void set implementedStaticDeclaredInstanceSetter(int value) {}
+  static void set implementedStaticSetterDeclaredInstanceGetter(int value) {}
+  void extendedStaticImplementedInstanceMethod() {}
+  void implementedInstanceDeclaredStaticMethod() {}
+  void mixedInStaticImplementedInstanceMethod() {}
+  void set implementedInstanceDeclaredStaticSetter(int value) {}
+  void set implementedInstanceSetterDeclaredStaticGetter(int value) {}
+}
+
+class Mixin {
+  static void extendedInstanceMixedInStaticMethod() {}
+  static void mixedInStaticDeclaredInstanceMethod() {}
+  static void mixedInStaticImplementedInstanceMethod() {}
+  void extendedStaticMixedInInstanceMethod() {}
+  void mixedInInstanceDeclaredStaticMethod() {}
+  void mixedInInstanceImplementedStaticMethod() {}
+}
+
+class Super {
+  int get extendedInstanceGetterDeclaredStaticSetter => 0;
+  static int get extendedStaticGetterDeclaredInstanceSetter => 0;
+  static void extendedStaticDeclaredInstanceMethod() {}
+  static void extendedStaticImplementedInstanceMethod() {}
+  static void extendedStaticMixedInInstanceMethod() {}
+  static void set extendedStaticDeclaredInstanceSetter(int value) {}
+  static void set extendedStaticSetterDeclaredInstanceGetter(int value) {}
+  void extendedInstanceDeclaredStaticMethod() {}
+  void extendedInstanceImplementedStaticMethod() {}
+  void extendedInstanceMixedInStaticMethod() {}
+  void set extendedInstanceDeclaredStaticSetter(int value) {}
+  void set extendedInstanceSetterDeclaredStaticGetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.weak.expect
new file mode 100644
index 0000000..91d4ae2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.weak.expect
@@ -0,0 +1,158 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:58:15: Error: Can't declare a member that conflicts with an inherited one.
+//   static void extendedInstanceDeclaredStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:7:8: Context: This is the inherited member.
+//   void extendedInstanceDeclaredStaticMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:67:18: Error: Can't declare a member that conflicts with an inherited one.
+//   static int get extendedInstanceSetterDeclaredStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:16:12: Context: This is the inherited member.
+//   void set extendedInstanceSetterDeclaredStaticGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:70:15: Error: Can't declare a member that conflicts with an inherited one.
+//   static void mixedInInstanceDeclaredStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:27:8: Context: This is the inherited member.
+//   void mixedInInstanceDeclaredStaticMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:73:15: Error: Can't declare a member that conflicts with an inherited one.
+//   static void implementedInstanceDeclaredStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:38:8: Context: This is the inherited member.
+//   void implementedInstanceDeclaredStaticMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:82:18: Error: Can't declare a member that conflicts with an inherited one.
+//   static int get implementedInstanceSetterDeclaredStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:47:12: Context: This is the inherited member.
+//   void set implementedInstanceSetterDeclaredStaticGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:61:19: Error: Can't declare a member that conflicts with an inherited one.
+//   static void set extendedInstanceDeclaredStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:10:12: Context: This is the inherited member.
+//   void set extendedInstanceDeclaredStaticSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:64:19: Error: Can't declare a member that conflicts with an inherited one.
+//   static void set extendedInstanceGetterDeclaredStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:13:11: Context: This is the inherited member.
+//   int get extendedInstanceGetterDeclaredStaticSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:76:19: Error: Can't declare a member that conflicts with an inherited one.
+//   static void set implementedInstanceDeclaredStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:41:12: Context: This is the inherited member.
+//   void set implementedInstanceDeclaredStaticSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:79:19: Error: Can't declare a member that conflicts with an inherited one.
+//   static void set implementedInstanceGetterDeclaredStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:44:11: Context: This is the inherited member.
+//   int get implementedInstanceGetterDeclaredStaticSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  static method extendedStaticDeclaredInstanceMethod() → void {}
+  method extendedInstanceDeclaredStaticMethod() → void {}
+  static set extendedStaticDeclaredInstanceSetter(core::int value) → void {}
+  set extendedInstanceDeclaredStaticSetter(core::int value) → void {}
+  static get extendedStaticGetterDeclaredInstanceSetter() → core::int
+    return 0;
+  get extendedInstanceGetterDeclaredStaticSetter() → core::int
+    return 0;
+  static set extendedStaticSetterDeclaredInstanceGetter(core::int value) → void {}
+  set extendedInstanceSetterDeclaredStaticGetter(core::int value) → void {}
+  static method extendedStaticMixedInInstanceMethod() → void {}
+  method extendedInstanceMixedInStaticMethod() → void {}
+  static method extendedStaticImplementedInstanceMethod() → void {}
+  method extendedInstanceImplementedStaticMethod() → void {}
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  static method mixedInStaticDeclaredInstanceMethod() → void {}
+  method mixedInInstanceDeclaredStaticMethod() → void {}
+  static method mixedInStaticImplementedInstanceMethod() → void {}
+  method mixedInInstanceImplementedStaticMethod() → void {}
+  method extendedStaticMixedInInstanceMethod() → void {}
+  static method extendedInstanceMixedInStaticMethod() → void {}
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  static method implementedStaticDeclaredInstanceMethod() → void {}
+  method implementedInstanceDeclaredStaticMethod() → void {}
+  static set implementedStaticDeclaredInstanceSetter(core::int value) → void {}
+  set implementedInstanceDeclaredStaticSetter(core::int value) → void {}
+  static get implementedStaticGetterDeclaredInstanceSetter() → core::int
+    return 0;
+  get implementedInstanceGetterDeclaredStaticSetter() → core::int
+    return 0;
+  static set implementedStaticSetterDeclaredInstanceGetter(core::int value) → void {}
+  set implementedInstanceSetterDeclaredStaticGetter(core::int value) → void {}
+  method extendedStaticImplementedInstanceMethod() → void {}
+  static method extendedInstanceImplementedStaticMethod() → void {}
+  method mixedInStaticImplementedInstanceMethod() → void {}
+  static method mixedInInstanceImplementedStaticMethod() → void {}
+}
+abstract class _Class&Super&Mixin = self::Super with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Class&Super&Mixin
+    : super self::Super::•()
+    ;
+  mixin-super-stub method mixedInInstanceDeclaredStaticMethod() → void
+    return super.{self::Mixin::mixedInInstanceDeclaredStaticMethod}();
+  mixin-super-stub method mixedInInstanceImplementedStaticMethod() → void
+    return super.{self::Mixin::mixedInInstanceImplementedStaticMethod}();
+  mixin-super-stub method extendedStaticMixedInInstanceMethod() → void
+    return super.{self::Mixin::extendedStaticMixedInInstanceMethod}();
+}
+abstract class Class extends self::_Class&Super&Mixin implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Super&Mixin::•()
+    ;
+  method extendedStaticDeclaredInstanceMethod() → void {}
+  static method extendedInstanceDeclaredStaticMethod() → void {}
+  set extendedStaticDeclaredInstanceSetter(core::int value) → void {}
+  static set extendedInstanceDeclaredStaticSetter(core::int value) → void {}
+  set extendedStaticGetterDeclaredInstanceSetter(core::int value) → void {}
+  static set extendedInstanceGetterDeclaredStaticSetter(core::int value) → void {}
+  get extendedStaticSetterDeclaredInstanceGetter() → core::int
+    return 0;
+  static get extendedInstanceSetterDeclaredStaticGetter() → core::int
+    return 0;
+  method mixedInStaticDeclaredInstanceMethod() → void {}
+  static method mixedInInstanceDeclaredStaticMethod() → void {}
+  method implementedStaticDeclaredInstanceMethod() → void {}
+  static method implementedInstanceDeclaredStaticMethod() → void {}
+  set implementedStaticDeclaredInstanceSetter(core::int value) → void {}
+  static set implementedInstanceDeclaredStaticSetter(core::int value) → void {}
+  set implementedStaticGetterDeclaredInstanceSetter(core::int value) → void {}
+  static set implementedInstanceGetterDeclaredStaticSetter(core::int value) → void {}
+  get implementedStaticSetterDeclaredInstanceGetter() → core::int
+    return 0;
+  static get implementedInstanceSetterDeclaredStaticGetter() → core::int
+    return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.weak.transformed.expect
new file mode 100644
index 0000000..4477dde
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart.weak.transformed.expect
@@ -0,0 +1,158 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:58:15: Error: Can't declare a member that conflicts with an inherited one.
+//   static void extendedInstanceDeclaredStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:7:8: Context: This is the inherited member.
+//   void extendedInstanceDeclaredStaticMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:67:18: Error: Can't declare a member that conflicts with an inherited one.
+//   static int get extendedInstanceSetterDeclaredStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:16:12: Context: This is the inherited member.
+//   void set extendedInstanceSetterDeclaredStaticGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:70:15: Error: Can't declare a member that conflicts with an inherited one.
+//   static void mixedInInstanceDeclaredStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:27:8: Context: This is the inherited member.
+//   void mixedInInstanceDeclaredStaticMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:73:15: Error: Can't declare a member that conflicts with an inherited one.
+//   static void implementedInstanceDeclaredStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:38:8: Context: This is the inherited member.
+//   void implementedInstanceDeclaredStaticMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:82:18: Error: Can't declare a member that conflicts with an inherited one.
+//   static int get implementedInstanceSetterDeclaredStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:47:12: Context: This is the inherited member.
+//   void set implementedInstanceSetterDeclaredStaticGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:61:19: Error: Can't declare a member that conflicts with an inherited one.
+//   static void set extendedInstanceDeclaredStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:10:12: Context: This is the inherited member.
+//   void set extendedInstanceDeclaredStaticSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:64:19: Error: Can't declare a member that conflicts with an inherited one.
+//   static void set extendedInstanceGetterDeclaredStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:13:11: Context: This is the inherited member.
+//   int get extendedInstanceGetterDeclaredStaticSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:76:19: Error: Can't declare a member that conflicts with an inherited one.
+//   static void set implementedInstanceDeclaredStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:41:12: Context: This is the inherited member.
+//   void set implementedInstanceDeclaredStaticSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:79:19: Error: Can't declare a member that conflicts with an inherited one.
+//   static void set implementedInstanceGetterDeclaredStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/nnbd_mixed/hierarchy/static.dart:44:11: Context: This is the inherited member.
+//   int get implementedInstanceGetterDeclaredStaticSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Super extends core::Object {
+  synthetic constructor •() → self::Super
+    : super core::Object::•()
+    ;
+  static method extendedStaticDeclaredInstanceMethod() → void {}
+  method extendedInstanceDeclaredStaticMethod() → void {}
+  static set extendedStaticDeclaredInstanceSetter(core::int value) → void {}
+  set extendedInstanceDeclaredStaticSetter(core::int value) → void {}
+  static get extendedStaticGetterDeclaredInstanceSetter() → core::int
+    return 0;
+  get extendedInstanceGetterDeclaredStaticSetter() → core::int
+    return 0;
+  static set extendedStaticSetterDeclaredInstanceGetter(core::int value) → void {}
+  set extendedInstanceSetterDeclaredStaticGetter(core::int value) → void {}
+  static method extendedStaticMixedInInstanceMethod() → void {}
+  method extendedInstanceMixedInStaticMethod() → void {}
+  static method extendedStaticImplementedInstanceMethod() → void {}
+  method extendedInstanceImplementedStaticMethod() → void {}
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  static method mixedInStaticDeclaredInstanceMethod() → void {}
+  method mixedInInstanceDeclaredStaticMethod() → void {}
+  static method mixedInStaticImplementedInstanceMethod() → void {}
+  method mixedInInstanceImplementedStaticMethod() → void {}
+  method extendedStaticMixedInInstanceMethod() → void {}
+  static method extendedInstanceMixedInStaticMethod() → void {}
+}
+class Interface extends core::Object {
+  synthetic constructor •() → self::Interface
+    : super core::Object::•()
+    ;
+  static method implementedStaticDeclaredInstanceMethod() → void {}
+  method implementedInstanceDeclaredStaticMethod() → void {}
+  static set implementedStaticDeclaredInstanceSetter(core::int value) → void {}
+  set implementedInstanceDeclaredStaticSetter(core::int value) → void {}
+  static get implementedStaticGetterDeclaredInstanceSetter() → core::int
+    return 0;
+  get implementedInstanceGetterDeclaredStaticSetter() → core::int
+    return 0;
+  static set implementedStaticSetterDeclaredInstanceGetter(core::int value) → void {}
+  set implementedInstanceSetterDeclaredStaticGetter(core::int value) → void {}
+  method extendedStaticImplementedInstanceMethod() → void {}
+  static method extendedInstanceImplementedStaticMethod() → void {}
+  method mixedInStaticImplementedInstanceMethod() → void {}
+  static method mixedInInstanceImplementedStaticMethod() → void {}
+}
+abstract class _Class&Super&Mixin extends self::Super implements self::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_Class&Super&Mixin
+    : super self::Super::•()
+    ;
+  method mixedInInstanceDeclaredStaticMethod() → void {}
+  method mixedInInstanceImplementedStaticMethod() → void {}
+  method extendedStaticMixedInInstanceMethod() → void {}
+  static method mixedInStaticDeclaredInstanceMethod() → void {}
+  static method mixedInStaticImplementedInstanceMethod() → void {}
+  static method extendedInstanceMixedInStaticMethod() → void {}
+}
+abstract class Class extends self::_Class&Super&Mixin implements self::Interface {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Super&Mixin::•()
+    ;
+  method extendedStaticDeclaredInstanceMethod() → void {}
+  static method extendedInstanceDeclaredStaticMethod() → void {}
+  set extendedStaticDeclaredInstanceSetter(core::int value) → void {}
+  static set extendedInstanceDeclaredStaticSetter(core::int value) → void {}
+  set extendedStaticGetterDeclaredInstanceSetter(core::int value) → void {}
+  static set extendedInstanceGetterDeclaredStaticSetter(core::int value) → void {}
+  get extendedStaticSetterDeclaredInstanceGetter() → core::int
+    return 0;
+  static get extendedInstanceSetterDeclaredStaticGetter() → core::int
+    return 0;
+  method mixedInStaticDeclaredInstanceMethod() → void {}
+  static method mixedInInstanceDeclaredStaticMethod() → void {}
+  method implementedStaticDeclaredInstanceMethod() → void {}
+  static method implementedInstanceDeclaredStaticMethod() → void {}
+  set implementedStaticDeclaredInstanceSetter(core::int value) → void {}
+  static set implementedInstanceDeclaredStaticSetter(core::int value) → void {}
+  set implementedStaticGetterDeclaredInstanceSetter(core::int value) → void {}
+  static set implementedInstanceGetterDeclaredStaticSetter(core::int value) → void {}
+  get implementedStaticSetterDeclaredInstanceGetter() → core::int
+    return 0;
+  static get implementedInstanceSetterDeclaredStaticGetter() → core::int
+    return 0;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/infer_constraints_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/infer_constraints_from_opt_in.dart.weak.transformed.expect
index 267b93e..d9beb51 100644
--- a/pkg/front_end/testcases/nnbd_mixed/infer_constraints_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/infer_constraints_from_opt_in.dart.weak.transformed.expect
@@ -25,16 +25,16 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {
-  core::List<dynamic>* local0 = <dynamic>[];
-  core::List<inf::C<dynamic>*>* local1a = <inf::C<dynamic>*>[inf::field1];
-  core::List<inf::C<dynamic>*>* local1b = <inf::C<dynamic>*>[inf::field2];
-  core::List<inf::C<core::int*>*>* local1c = <inf::C<core::int*>*>[inf::field3];
-  core::List<inf::C<core::int*>*>* local1d = <inf::C<core::int*>*>[inf::field4];
-  core::List<inf::C<core::int*>*>* local1e = <inf::C<core::int*>*>[inf::field5];
-  core::List<inf::C<core::int*>*>* local1f = <inf::C<core::int*>*>[inf::field6];
-  core::List<core::int*>* local1g = <core::int*>[inf::field7];
-  core::List<core::int*>* local1h = <core::int*>[inf::field8];
-  core::List<Null>* local1i = <Null>[null];
+  core::List<dynamic>* local0 = core::_GrowableList::•<dynamic>(0);
+  core::List<inf::C<dynamic>*>* local1a = core::_GrowableList::_literal1<inf::C<dynamic>*>(inf::field1);
+  core::List<inf::C<dynamic>*>* local1b = core::_GrowableList::_literal1<inf::C<dynamic>*>(inf::field2);
+  core::List<inf::C<core::int*>*>* local1c = core::_GrowableList::_literal1<inf::C<core::int*>*>(inf::field3);
+  core::List<inf::C<core::int*>*>* local1d = core::_GrowableList::_literal1<inf::C<core::int*>*>(inf::field4);
+  core::List<inf::C<core::int*>*>* local1e = core::_GrowableList::_literal1<inf::C<core::int*>*>(inf::field5);
+  core::List<inf::C<core::int*>*>* local1f = core::_GrowableList::_literal1<inf::C<core::int*>*>(inf::field6);
+  core::List<core::int*>* local1g = core::_GrowableList::_literal1<core::int*>(inf::field7);
+  core::List<core::int*>* local1h = core::_GrowableList::_literal1<core::int*>(inf::field8);
+  core::List<Null>* local1i = core::_GrowableList::_literal1<Null>(null);
   core::Set<inf::C<dynamic>*>* local2a = block {
     final core::Set<inf::C<dynamic>*>* #t1 = new col::_CompactLinkedHashSet::•<inf::C<dynamic>*>();
     #t1.{core::Set::add}{Invariant}(inf::field1);
@@ -155,16 +155,16 @@
 static field core::int field7;
 static field core::int? field8;
 static method method() → dynamic {
-  core::List<dynamic> local0 = <dynamic>[];
-  core::List<inf::C<dynamic>> local1a = <inf::C<dynamic>>[inf::field1];
-  core::List<inf::C<dynamic>?> local1b = <inf::C<dynamic>?>[inf::field2];
-  core::List<inf::C<core::int>> local1c = <inf::C<core::int>>[inf::field3];
-  core::List<inf::C<core::int>?> local1d = <inf::C<core::int>?>[inf::field4];
-  core::List<inf::C<core::int?>> local1e = <inf::C<core::int?>>[inf::field5];
-  core::List<inf::C<core::int?>?> local1f = <inf::C<core::int?>?>[inf::field6];
-  core::List<core::int> local1g = <core::int>[inf::field7];
-  core::List<core::int?> local1h = <core::int?>[inf::field8];
-  core::List<Null> local1i = <Null>[null];
+  core::List<dynamic> local0 = core::_GrowableList::•<dynamic>(0);
+  core::List<inf::C<dynamic>> local1a = core::_GrowableList::_literal1<inf::C<dynamic>>(inf::field1);
+  core::List<inf::C<dynamic>?> local1b = core::_GrowableList::_literal1<inf::C<dynamic>?>(inf::field2);
+  core::List<inf::C<core::int>> local1c = core::_GrowableList::_literal1<inf::C<core::int>>(inf::field3);
+  core::List<inf::C<core::int>?> local1d = core::_GrowableList::_literal1<inf::C<core::int>?>(inf::field4);
+  core::List<inf::C<core::int?>> local1e = core::_GrowableList::_literal1<inf::C<core::int?>>(inf::field5);
+  core::List<inf::C<core::int?>?> local1f = core::_GrowableList::_literal1<inf::C<core::int?>?>(inf::field6);
+  core::List<core::int> local1g = core::_GrowableList::_literal1<core::int>(inf::field7);
+  core::List<core::int?> local1h = core::_GrowableList::_literal1<core::int?>(inf::field8);
+  core::List<Null> local1i = core::_GrowableList::_literal1<Null>(null);
   core::Set<inf::C<dynamic>?> local2a = block {
     final core::Set<inf::C<dynamic>?> #t17 = new col::_CompactLinkedHashSet::•<inf::C<dynamic>?>();
     #t17.{core::Set::add}{Invariant}(inf::field1);
diff --git a/pkg/front_end/testcases/nnbd_mixed/inheritance_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/inheritance_from_opt_in.dart.weak.expect
index a706f8a..5055729 100644
--- a/pkg/front_end/testcases/nnbd_mixed/inheritance_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/inheritance_from_opt_in.dart.weak.expect
@@ -115,7 +115,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-class LegacyClass4c extends core::Object implements inh::GenericInterface<core::num?> {
+class LegacyClass4c extends core::Object implements inh::GenericInterface<core::num*> {
   synthetic constructor •() → self::LegacyClass4c*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue40512/issue40512.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue40512/issue40512.dart.weak.expect
index ad3788d..a878892 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue40512/issue40512.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue40512/issue40512.dart.weak.expect
@@ -9,18 +9,37 @@
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> baz2::A::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> baz2::A::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> baz2::A::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> baz2::A::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> baz2::A::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> baz2::A::==
+  abstract mixin-stub get hashCode() → core::int*; -> baz2::A::hashCode
+  mixin-super-stub method toString({core::String* s = #C1}) → core::String*
+    return super.{baz2::A::toString}(s: s);
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> baz2::A::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> baz2::A::runtimeType
 }
 abstract class _C&Object&A&B = self::_C&Object&A with baz2::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
-  abstract member-signature method toString({core::String* s = #C1}) → core::String*; -> baz2::A::toString
+  abstract mixin-stub get _identityHashCode() → core::int*; -> baz2::B::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> baz2::B::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> baz2::B::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> baz2::B::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> baz2::B::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> baz2::B::==
+  abstract mixin-stub get hashCode() → core::int*; -> baz2::B::hashCode
+  abstract mixin-stub method toString() → core::String*; -> baz2::B::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> baz2::B::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> baz2::B::runtimeType
 }
 class C extends self::_C&Object&A&B {
   synthetic constructor •() → self::C*
     : super self::_C&Object&A&B::•()
     ;
-  abstract member-signature method toString({core::String* s = #C1}) → core::String*; -> baz2::A::toString
 }
 static method main() → void {
   core::print(new baz2::B::•());
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue40512/issue40512.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue40512/issue40512.dart.weak.transformed.expect
index 0a99e51..44da6f8 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue40512/issue40512.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue40512/issue40512.dart.weak.transformed.expect
@@ -25,7 +25,7 @@
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
-  abstract member-signature method toString({core::String* s = #C1}) → core::String*; -> baz2::A::toString
+  abstract member-signature method toString({core::String* s = #C1}) → core::String*; -> self::_C&Object&A::toString
   abstract member-signature get /* from org-dartlang-testcase:///issue40512_lib.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method /* from org-dartlang-testcase:///issue40512_lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method /* from org-dartlang-testcase:///issue40512_lib.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -40,7 +40,7 @@
   synthetic constructor •() → self::C*
     : super self::_C&Object&A&B::•()
     ;
-  abstract member-signature method toString({core::String* s = #C1}) → core::String*; -> baz2::A::toString
+  abstract member-signature method toString({core::String* s = #C1}) → core::String*; -> self::_C&Object&A::toString
 }
 static method main() → void {
   core::print(new baz2::B::•());
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41210a/issue41210.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue41210a/issue41210.dart.weak.expect
index bbc1cb2..2ba727b 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41210a/issue41210.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41210a/issue41210.dart.weak.expect
@@ -9,21 +9,42 @@
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::A::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::A::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::A::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::A::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::A::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::A::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::A::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::A::runtimeType
+  mixin-super-stub method method({core::String* s = #C1}) → core::String*
+    return super.{iss::A::method}(s: s);
 }
 abstract class _C&Object&A&B = self::_C&Object&A with iss::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
-  abstract member-signature method method({core::String* s = #C1}) → core::String*; -> iss::A::method
+  abstract mixin-stub get _identityHashCode() → core::int*; -> iss::B::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> iss::B::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> iss::B::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> iss::B::==
+  abstract mixin-stub get hashCode() → core::int*; -> iss::B::hashCode
+  abstract mixin-stub method toString() → core::String*; -> iss::B::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> iss::B::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> iss::B::runtimeType
+  abstract mixin-stub method method() → core::String*; -> iss::B::method
 }
 class C extends self::_C&Object&A&B {
   synthetic constructor •() → self::C*
     : super self::_C&Object&A&B::•()
     ;
-  abstract member-signature method method({core::String* s = #C1}) → core::String*; -> iss::A::method
 }
 static method main() → dynamic {
-  core::print(new self::C::•().{self::C::method}());
+  core::print(new self::C::•().{self::_C&Object&A&B::method}());
 }
 
 library;
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41210a/issue41210.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41210a/issue41210.dart.weak.transformed.expect
index ee21372..bb7985d 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41210a/issue41210.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41210a/issue41210.dart.weak.transformed.expect
@@ -26,7 +26,7 @@
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
-  abstract member-signature method method({core::String* s = #C1}) → core::String*; -> iss::A::method
+  abstract member-signature method method({core::String* s = #C1}) → core::String*; -> self::_C&Object&A::method
   abstract member-signature get /* from org-dartlang-testcase:///issue41210_lib1.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib1.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method /* from org-dartlang-testcase:///issue41210_lib1.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -42,7 +42,7 @@
   synthetic constructor •() → self::C*
     : super self::_C&Object&A&B::•()
     ;
-  abstract member-signature method method({core::String* s = #C1}) → core::String*; -> iss::A::method
+  abstract member-signature method method({core::String* s = #C1}) → core::String*; -> self::_C&Object&A::method
 }
 static method main() → dynamic {
   core::print(new self::C::•().{self::C::method}());
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41210b.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue41210b.dart.weak.expect
index 4b28cf6..ec08b47 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41210b.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41210b.dart.weak.expect
@@ -9,6 +9,8 @@
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method({core::String* s = #C1}) → core::String*
+    return super.{iss::A::method}(s: s);
   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
@@ -31,7 +33,7 @@
     ;
 }
 static method main() → dynamic {
-  core::print(new self::C::•().{iss::A::method}());
+  core::print(new self::C::•().{self::_C&Object&A::method}());
 }
 
 library;
@@ -59,6 +61,7 @@
   synthetic constructor •() → iss::B*
     : super core::Object::•()
     ;
+  abstract member-signature method method() → core::String*; -> iss2::Interface::method
   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
@@ -69,7 +72,6 @@
   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
-  abstract member-signature method method() → core::String*; -> iss2::Interface::method
 }
 static method main() → void {}
 
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41210b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41210b.dart.weak.transformed.expect
index 76a5947..f7c6ef0 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41210b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41210b.dart.weak.transformed.expect
@@ -9,6 +9,8 @@
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
+  method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method({core::String* s = #C1}) → core::String*
+    return s;
   abstract member-signature get /* from org-dartlang-testcase:///issue41210b_lib1.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -19,13 +21,12 @@
   abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ toString() → core::String*; -> core::Object::toString
   abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get /* from org-dartlang-testcase:///issue41210b_lib1.dart */ runtimeType() → core::Type*; -> core::Object::runtimeType
-  method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method({core::String* s = #C1}) → core::String*
-    return s;
 }
 abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
+  abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method() → core::String*; -> #lib1::Interface::method
   abstract member-signature get /* from org-dartlang-testcase:///issue41210b_lib1.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -36,7 +37,6 @@
   abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ toString() → core::String*; -> core::Object::toString
   abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get /* from org-dartlang-testcase:///issue41210b_lib1.dart */ runtimeType() → core::Type*; -> core::Object::runtimeType
-  abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method() → core::String*; -> #lib1::Interface::method
 }
 class C extends self::_C&Object&A&B {
   synthetic constructor •() → self::C*
@@ -44,7 +44,7 @@
     ;
 }
 static method main() → dynamic {
-  core::print(new self::C::•().{iss::A::method}());
+  core::print(new self::C::•().{self::_C&Object&A::method}());
 }
 
 library;
@@ -72,6 +72,7 @@
   synthetic constructor •() → iss::B*
     : super core::Object::•()
     ;
+  abstract member-signature method method() → core::String*; -> iss2::Interface::method
   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
@@ -82,7 +83,6 @@
   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
-  abstract member-signature method method() → core::String*; -> iss2::Interface::method
 }
 static method main() → void {}
 
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.expect
index 6654a73..c0a3ef7 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.expect
@@ -24,5 +24,5 @@
 constants  {
   #C1 = <Null>[]
   #C2 = true
-  #C3 = <core::int*>[]
+  #C3 = <core::int?>[]
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.transformed.expect
index 9a8aafd..49fce36 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.transformed.expect
@@ -24,7 +24,7 @@
 constants  {
   #C1 = <Null>[]
   #C2 = true
-  #C3 = <core::int*>[]
+  #C3 = <core::int?>[]
 }
 
 Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.expect
index 3a9fde4..cf0c156 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.expect
@@ -2,6 +2,8 @@
 import self as self;
 import "foundation_binding_lib.dart" as fou;
 import "scheduler_binding_lib.dart" as sch;
+import "dart:core" as core;
+import "dart:async" as asy;
 import "services_binding_lib.dart" as ser;
 
 import "org-dartlang-testcase:///foundation_lib.dart";
@@ -12,6 +14,17 @@
   synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding*
     : super fou::BindingBase::•()
     ;
+  abstract mixin-stub method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<Null>* callback = #C1}) → void; -> sch::SchedulerBinding::registerSignalServiceExtension
+  abstract mixin-stub get _identityHashCode() → core::int*; -> sch::SchedulerBinding::_identityHashCode
+  abstract mixin-stub method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> sch::SchedulerBinding::_instanceOf
+  abstract mixin-stub method _simpleInstanceOf(dynamic type) → core::bool*; -> sch::SchedulerBinding::_simpleInstanceOf
+  abstract mixin-stub method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> sch::SchedulerBinding::_simpleInstanceOfTrue
+  abstract mixin-stub method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> sch::SchedulerBinding::_simpleInstanceOfFalse
+  abstract mixin-stub operator ==(dynamic other) → core::bool*; -> sch::SchedulerBinding::==
+  abstract mixin-stub get hashCode() → core::int*; -> sch::SchedulerBinding::hashCode
+  abstract mixin-stub method toString() → core::String*; -> sch::SchedulerBinding::toString
+  abstract mixin-stub method noSuchMethod(core::Invocation* invocation) → dynamic; -> sch::SchedulerBinding::noSuchMethod
+  abstract mixin-stub get runtimeType() → core::Type*; -> sch::SchedulerBinding::runtimeType
 }
 abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding = self::_TestSchedulerBinding&BindingBase&SchedulerBinding with ser::ServicesBinding /*isAnonymousMixin*/  {
   synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding*
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart
index 7f60cbd..4ac860d 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart
@@ -10,6 +10,8 @@
 
 class E2 = Object with A, D;
 
+class E3 = Object with A, F;
+
 abstract class C6 extends C3 implements C4 {}
 
 abstract class C8 extends C5 implements C7 {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.textual_outline.expect
index 1763bc0..212f813 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.textual_outline.expect
@@ -4,6 +4,7 @@
 class E1 with A, D {}
 
 class E2 = Object with A, D;
+class E3 = Object with A, F;
 
 abstract class C6 extends C3 implements C4 {}
 
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.textual_outline_modelled.expect
index 9bd7263..ea6829e 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.textual_outline_modelled.expect
@@ -8,4 +8,5 @@
 class E1 with A, D {}
 
 class E2 = Object with A, D;
+class E3 = Object with A, F;
 main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.weak.expect
index 1345fdd..11f8668 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.weak.expect
@@ -9,6 +9,8 @@
   const synthetic constructor •() → self::_E1&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{mai::A::method}(i, s: s);
   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
@@ -24,18 +26,20 @@
   const synthetic constructor •() → self::_E1&Object&A&D*
     : super self::_E1&Object&A::•()
     ;
-  abstract forwarding-stub method method(covariant core::num* i, {core::String* s = #C1}) → core::String*;
+  forwarding-stub method method(covariant core::num* i) → core::String*
+    return super.{self::_E1&Object&A::method}(i);
 }
 class E1 extends self::_E1&Object&A&D {
   synthetic constructor •() → self::E1*
     : super self::_E1&Object&A&D::•()
     ;
-  abstract member-signature method method(covariant core::num* i, {core::String* s = #C1}) → core::String*; -> self::_E1&Object&A&D::method
 }
 abstract class _E2&Object&A = core::Object with mai::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E2&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{mai::A::method}(i, s: s);
   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
@@ -51,13 +55,35 @@
   const synthetic constructor •() → self::E2*
     : super self::_E2&Object&A::•()
     ;
-  abstract forwarding-stub method method(covariant core::num* i, {core::String* s = #C1}) → core::String*;
+  forwarding-stub method method(covariant core::num* i) → core::String*
+    return super.{self::_E2&Object&A::method}(i);
+}
+abstract class _E3&Object&A = core::Object with mai::A /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_E3&Object&A*
+    : super core::Object::•()
+    ;
+  mixin-super-stub method method(core::num* i, {core::String* s = #C1}) → core::String*
+    return super.{mai::A::method}(i, s: s);
+  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
+}
+class E3 = self::_E3&Object&A with mai::F /*hasConstConstructor*/  {
+  const synthetic constructor •() → self::E3*
+    : super self::_E3&Object&A::•()
+    ;
 }
 abstract class C6 extends mai::C3 implements mai::C4 {
   synthetic constructor •() → self::C6*
     : super mai::C3::•()
     ;
-  abstract forwarding-stub method method2([covariant core::String* a = #C2]) → dynamic;
   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
@@ -68,12 +94,12 @@
   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
+  abstract forwarding-stub method method2([covariant core::String* a = #C2]) → dynamic;
 }
 abstract class C8 extends mai::C5 implements mai::C7 {
   synthetic constructor •() → self::C8*
     : super mai::C5::•()
     ;
-  abstract forwarding-stub method method2([covariant core::String* a = #C2, core::num* b = #C2]) → dynamic;
   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
@@ -84,6 +110,7 @@
   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
+  abstract forwarding-stub method method2([covariant core::String* a = #C2, core::num* b = #C2]) → dynamic;
 }
 static method main() → dynamic {}
 
@@ -113,6 +140,11 @@
     ;
   abstract forwarding-stub method method(covariant core::num i) → core::String;
 }
+abstract class F extends core::Object implements mai::Interface {
+  synthetic constructor •() → mai::F
+    : super core::Object::•()
+    ;
+}
 abstract class C1 extends core::Object {
   synthetic constructor •() → mai::C1
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.weak.transformed.expect
index 341bd9b..7b32bba 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue43988/main.dart.weak.transformed.expect
@@ -9,6 +9,8 @@
   const synthetic constructor •() → self::_E1&Object&A*
     : super core::Object::•()
     ;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///main_lib.dart */ method(core::num i, {core::String s = #C1}) → core::String
+    return s;
   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
@@ -19,25 +21,25 @@
   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
-  method /*isNonNullableByDefault, from org-dartlang-testcase:///main_lib.dart */ method(core::num i, {core::String s = #C1}) → core::String
-    return s;
 }
 abstract class _E1&Object&A&D extends self::_E1&Object&A implements mai::D /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E1&Object&A&D*
     : super self::_E1&Object&A::•()
     ;
-  abstract forwarding-stub method method(covariant core::num* i, {core::String* s = #C1}) → core::String*;
+  forwarding-stub method method(covariant core::num* i) → core::String*
+    return super.{self::_E1&Object&A::method}(i);
 }
 class E1 extends self::_E1&Object&A&D {
   synthetic constructor •() → self::E1*
     : super self::_E1&Object&A&D::•()
     ;
-  abstract member-signature method method(covariant core::num* i, {core::String* s = #C1}) → core::String*; -> self::_E1&Object&A&D::method
 }
 abstract class _E2&Object&A extends core::Object implements mai::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_E2&Object&A*
     : super core::Object::•()
     ;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///main_lib.dart */ method(core::num i, {core::String s = #C1}) → core::String
+    return s;
   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
@@ -48,20 +50,40 @@
   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
-  method /*isNonNullableByDefault, from org-dartlang-testcase:///main_lib.dart */ method(core::num i, {core::String s = #C1}) → core::String
-    return s;
 }
 class E2 extends self::_E2&Object&A implements mai::D /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::E2*
     : super self::_E2&Object&A::•()
     ;
-  abstract forwarding-stub method method(covariant core::num* i, {core::String* s = #C1}) → core::String*;
+  forwarding-stub method method(covariant core::num* i) → core::String*
+    return super.{self::_E2&Object&A::method}(i);
+}
+abstract class _E3&Object&A extends core::Object implements mai::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_E3&Object&A*
+    : super core::Object::•()
+    ;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///main_lib.dart */ method(core::num i, {core::String s = #C1}) → core::String
+    return s;
+  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
+}
+class E3 extends self::_E3&Object&A implements mai::F /*isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::E3*
+    : super self::_E3&Object&A::•()
+    ;
 }
 abstract class C6 extends mai::C3 implements mai::C4 {
   synthetic constructor •() → self::C6*
     : super mai::C3::•()
     ;
-  abstract forwarding-stub method method2([covariant core::String* a = #C2]) → dynamic;
   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
@@ -72,12 +94,12 @@
   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
+  abstract forwarding-stub method method2([covariant core::String* a = #C2]) → dynamic;
 }
 abstract class C8 extends mai::C5 implements mai::C7 {
   synthetic constructor •() → self::C8*
     : super mai::C5::•()
     ;
-  abstract forwarding-stub method method2([covariant core::String* a = #C2, core::num* b = #C2]) → dynamic;
   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
@@ -88,6 +110,7 @@
   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
+  abstract forwarding-stub method method2([covariant core::String* a = #C2, core::num* b = #C2]) → dynamic;
 }
 static method main() → dynamic {}
 
@@ -117,6 +140,11 @@
     ;
   abstract forwarding-stub method method(covariant core::num i) → core::String;
 }
+abstract class F extends core::Object implements mai::Interface {
+  synthetic constructor •() → mai::F
+    : super core::Object::•()
+    ;
+}
 abstract class C1 extends core::Object {
   synthetic constructor •() → mai::C1
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue43988/main_lib.dart b/pkg/front_end/testcases/nnbd_mixed/issue43988/main_lib.dart
index 5291414..6bcc053 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue43988/main_lib.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/issue43988/main_lib.dart
@@ -16,6 +16,8 @@
 
 abstract class D implements Interface, Interface2 {}
 
+abstract class F implements Interface {}
+
 abstract class C1 {
   method2();
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/literal_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/literal_from_opt_in.dart.weak.expect
index f236f21..6c3539d 100644
--- a/pkg/front_end/testcases/nnbd_mixed/literal_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/literal_from_opt_in.dart.weak.expect
@@ -7,10 +7,10 @@
 
 static method main() → dynamic {
   core::List<lit::Const<core::int*>*>* l1 = #C3;
-  core::List<lit::Const<core::int*>*>* l2 = #C3;
-  core::List<lit::Const<core::int*>*>* l3 = #C6;
+  core::List<lit::Const<core::int*>*>* l2 = #C5;
+  core::List<lit::Const<core::int*>*>* l3 = #C8;
   core::List<lit::Const<core::int*>*>* l4 = #C3;
-  core::List<lit::Const<core::int*>*>* l5 = #C7;
+  core::List<lit::Const<core::int*>*>* l5 = #C9;
 }
 
 library /*isNonNullableByDefault*/;
@@ -24,17 +24,25 @@
     ;
 }
 static const field lit::Const<core::int> a = #C2;
-static const field lit::Const<core::int?> b = #C2;
-static const field lit::Const<core::int?> c = #C5;
+static const field lit::Const<core::int?> b = #C4;
+static const field lit::Const<core::int?> c = #C7;
 static const field lit::Const<core::int>? d = #C2;
-static const field lit::Const<core::int>? e = #C4;
+static const field lit::Const<core::int>? e = #C6;
 
 constants  {
   #C1 = 0
   #C2 = lit::Const<core::int*> {field:#C1}
   #C3 = <lit::Const<core::int*>*>[#C2]
-  #C4 = null
-  #C5 = lit::Const<core::int*> {field:#C4}
-  #C6 = <lit::Const<core::int*>*>[#C5]
-  #C7 = <lit::Const<core::int*>*>[#C4]
+  #C4 = lit::Const<core::int?> {field:#C1}
+  #C5 = <lit::Const<core::int*>*>[#C4]
+  #C6 = null
+  #C7 = lit::Const<core::int?> {field:#C6}
+  #C8 = <lit::Const<core::int*>*>[#C7]
+  #C9 = <lit::Const<core::int*>*>[#C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///literal_from_opt_in_lib.dart:
+- Const. (from org-dartlang-testcase:///literal_from_opt_in_lib.dart:8:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/literal_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/literal_from_opt_in.dart.weak.transformed.expect
index f236f21..6c3539d 100644
--- a/pkg/front_end/testcases/nnbd_mixed/literal_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/literal_from_opt_in.dart.weak.transformed.expect
@@ -7,10 +7,10 @@
 
 static method main() → dynamic {
   core::List<lit::Const<core::int*>*>* l1 = #C3;
-  core::List<lit::Const<core::int*>*>* l2 = #C3;
-  core::List<lit::Const<core::int*>*>* l3 = #C6;
+  core::List<lit::Const<core::int*>*>* l2 = #C5;
+  core::List<lit::Const<core::int*>*>* l3 = #C8;
   core::List<lit::Const<core::int*>*>* l4 = #C3;
-  core::List<lit::Const<core::int*>*>* l5 = #C7;
+  core::List<lit::Const<core::int*>*>* l5 = #C9;
 }
 
 library /*isNonNullableByDefault*/;
@@ -24,17 +24,25 @@
     ;
 }
 static const field lit::Const<core::int> a = #C2;
-static const field lit::Const<core::int?> b = #C2;
-static const field lit::Const<core::int?> c = #C5;
+static const field lit::Const<core::int?> b = #C4;
+static const field lit::Const<core::int?> c = #C7;
 static const field lit::Const<core::int>? d = #C2;
-static const field lit::Const<core::int>? e = #C4;
+static const field lit::Const<core::int>? e = #C6;
 
 constants  {
   #C1 = 0
   #C2 = lit::Const<core::int*> {field:#C1}
   #C3 = <lit::Const<core::int*>*>[#C2]
-  #C4 = null
-  #C5 = lit::Const<core::int*> {field:#C4}
-  #C6 = <lit::Const<core::int*>*>[#C5]
-  #C7 = <lit::Const<core::int*>*>[#C4]
+  #C4 = lit::Const<core::int?> {field:#C1}
+  #C5 = <lit::Const<core::int*>*>[#C4]
+  #C6 = null
+  #C7 = lit::Const<core::int?> {field:#C6}
+  #C8 = <lit::Const<core::int*>*>[#C7]
+  #C9 = <lit::Const<core::int*>*>[#C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///literal_from_opt_in_lib.dart:
+- Const. (from org-dartlang-testcase:///literal_from_opt_in_lib.dart:8:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixed_mixin.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/mixed_mixin.dart.weak.expect
index 55adb86..04e3fe5 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mixed_mixin.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mixed_mixin.dart.weak.expect
@@ -9,6 +9,12 @@
   const synthetic constructor •() → self::_C1&Object&B*
     : super core::Object::•()
     ;
+  mixin-super-stub get a() → core::List<(core::int*) →* core::int*>*
+    return super.{mix::B::a};
+  mixin-super-stub set a(core::List<(core::int*) →* core::int*>* _) → void
+    return super.{mix::B::a} = _;
+  mixin-super-stub method m((core::int*) →* core::int* x) → (core::int*) →* core::int*
+    return super.{mix::B::m}(x);
   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
@@ -24,9 +30,6 @@
   synthetic constructor •() → self::C1*
     : super self::_C1&Object&B::•()
     ;
-  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*; -> mix::B::a
-  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void; -> mix::B::a
-  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*; -> mix::B::m
 }
 static method main() → dynamic {}
 
@@ -61,9 +64,9 @@
   synthetic constructor •() → mix::DiBq1
     : super self::C1::•()
     ;
-  abstract member-signature get a() → core::List<(core::int?) → core::int?>; -> mix::B::a
-  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void; -> mix::B::a
-  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?; -> mix::B::m
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>; -> self::_C1&Object&B::a
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void; -> self::_C1&Object&B::a
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?; -> self::_C1&Object&B::m
   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
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixed_mixin.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/mixed_mixin.dart.weak.transformed.expect
index 2b6628e..9128000 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mixed_mixin.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mixed_mixin.dart.weak.transformed.expect
@@ -9,6 +9,11 @@
   const synthetic constructor •() → self::_C1&Object&B*
     : super core::Object::•()
     ;
+  get /*isNonNullableByDefault, from org-dartlang-testcase:///mixed_mixin_lib.dart */ a() → core::List<(core::int) → core::int>
+    return core::_GrowableList::•<(core::int) → core::int>(0);
+  set /*isNonNullableByDefault, from org-dartlang-testcase:///mixed_mixin_lib.dart */ a(core::List<(core::int) → core::int> _) → void {}
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///mixed_mixin_lib.dart */ m((core::int) → core::int x) → (core::int) → core::int
+    return x;
   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
@@ -19,19 +24,11 @@
   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
-  get /*isNonNullableByDefault, from org-dartlang-testcase:///mixed_mixin_lib.dart */ a() → core::List<(core::int) → core::int>
-    return <(core::int) → core::int>[];
-  set /*isNonNullableByDefault, from org-dartlang-testcase:///mixed_mixin_lib.dart */ a(core::List<(core::int) → core::int> _) → void {}
-  method /*isNonNullableByDefault, from org-dartlang-testcase:///mixed_mixin_lib.dart */ m((core::int) → core::int x) → (core::int) → core::int
-    return x;
 }
 class C1 extends self::_C1&Object&B {
   synthetic constructor •() → self::C1*
     : super self::_C1&Object&B::•()
     ;
-  abstract member-signature get a() → core::List<(core::int*) →* core::int*>*; -> mix::B::a
-  abstract member-signature set a(core::List<(core::int*) →* core::int*>* _) → void; -> mix::B::a
-  abstract member-signature method m((core::int*) →* core::int* x) → (core::int*) →* core::int*; -> mix::B::m
 }
 static method main() → dynamic {}
 
@@ -47,7 +44,7 @@
     : super core::Object::•()
     ;
   get a() → core::List<(core::int) → core::int>
-    return <(core::int) → core::int>[];
+    return core::_GrowableList::•<(core::int) → core::int>(0);
   set a(core::List<(core::int) → core::int> _) → void {}
   method m((core::int) → core::int x) → (core::int) → core::int
     return x;
@@ -57,7 +54,7 @@
     : super core::Object::•()
     ;
   get a() → core::List<(core::int?) → core::int?>
-    return <(core::int?) → core::int?>[];
+    return core::_GrowableList::•<(core::int?) → core::int?>(0);
   set a(core::List<(core::int?) → core::int?> _) → void {}
   method m((core::int?) → core::int? x) → (core::int?) → core::int?
     return x;
@@ -66,9 +63,9 @@
   synthetic constructor •() → mix::DiBq1
     : super self::C1::•()
     ;
-  abstract member-signature get a() → core::List<(core::int?) → core::int?>; -> mix::B::a
-  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void; -> mix::B::a
-  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?; -> mix::B::m
+  abstract member-signature get a() → core::List<(core::int?) → core::int?>; -> self::_C1&Object&B::a
+  abstract member-signature set a(core::List<(core::int?) → core::int?> _) → void; -> self::_C1&Object&B::a
+  abstract member-signature method m((core::int?) → core::int? x) → (core::int?) → core::int?; -> self::_C1&Object&B::m
   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
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart
new file mode 100644
index 0000000..b6a45bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart
@@ -0,0 +1,11 @@
+import 'main_lib.dart';
+
+mixin RenderAnimatedOpacityMixin<T extends RenderObject>
+    on RenderObjectWithChildMixin<T> {}
+
+class RenderAnimatedOpacity extends RenderProxyBox
+    with RenderProxyBoxMixin, RenderAnimatedOpacityMixin<RenderBox> {}
+
+main() {
+  new RenderAnimatedOpacity();
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.textual_outline.expect
new file mode 100644
index 0000000..eebe9b5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+import 'main_lib.dart';
+
+mixin RenderAnimatedOpacityMixin<T extends RenderObject>
+    on RenderObjectWithChildMixin<T> {}
+
+class RenderAnimatedOpacity extends RenderProxyBox
+    with RenderProxyBoxMixin, RenderAnimatedOpacityMixin<RenderBox> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3d75979
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+import 'main_lib.dart';
+
+class RenderAnimatedOpacity extends RenderProxyBox
+    with RenderProxyBoxMixin, RenderAnimatedOpacityMixin<RenderBox> {}
+
+main() {}
+mixin RenderAnimatedOpacityMixin<T extends RenderObject>
+    on RenderObjectWithChildMixin<T> {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.weak.expect
new file mode 100644
index 0000000..8bc2add
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.weak.expect
@@ -0,0 +1,123 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+abstract class RenderAnimatedOpacityMixin<T extends mai::RenderObject = mai::RenderObject> extends mai::RenderObjectWithChildMixin<self::RenderAnimatedOpacityMixin::T> /*isMixinDeclaration*/  {
+}
+abstract class _RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin = mai::RenderProxyBox with mai::RenderProxyBoxMixin<mai::RenderBox> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin
+    : super mai::RenderProxyBox::•()
+    ;
+  mixin-super-stub method hitTestChildren(mai::BoxHitTestResult result, {required mai::Offset position = #C1}) → core::bool
+    return super.{mai::RenderProxyBoxMixin::hitTestChildren}(result, position: position);
+}
+abstract class _RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin&RenderAnimatedOpacityMixin = self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin with self::RenderAnimatedOpacityMixin<mai::RenderBox> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin&RenderAnimatedOpacityMixin
+    : super self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin::•()
+    ;
+}
+class RenderAnimatedOpacity extends self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin&RenderAnimatedOpacityMixin {
+  synthetic constructor •() → self::RenderAnimatedOpacity
+    : super self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin&RenderAnimatedOpacityMixin::•()
+    ;
+}
+static method main() → dynamic {
+  new self::RenderAnimatedOpacity::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Offset extends core::Object {
+  synthetic constructor •() → mai::Offset
+    : super core::Object::•()
+    ;
+}
+class AbstractNode extends core::Object {
+  synthetic constructor •() → mai::AbstractNode
+    : super core::Object::•()
+    ;
+}
+abstract class DiagnosticableTreeMixin extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class HitTestTarget extends core::Object {
+  synthetic constructor •() → mai::HitTestTarget
+    : super core::Object::•()
+    ;
+}
+class HitTestResult extends core::Object {
+  synthetic constructor •() → mai::HitTestResult
+    : super core::Object::•()
+    ;
+}
+class BoxHitTestResult extends mai::HitTestResult {
+  synthetic constructor •() → mai::BoxHitTestResult
+    : super mai::HitTestResult::•()
+    ;
+}
+abstract class _RenderObject&AbstractNode&DiagnosticableTreeMixin extends mai::AbstractNode implements mai::DiagnosticableTreeMixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → mai::_RenderObject&AbstractNode&DiagnosticableTreeMixin
+    : super mai::AbstractNode::•()
+    ;
+}
+abstract class RenderObject extends mai::_RenderObject&AbstractNode&DiagnosticableTreeMixin implements mai::HitTestTarget {
+  synthetic constructor •() → mai::RenderObject
+    : super mai::_RenderObject&AbstractNode&DiagnosticableTreeMixin::•()
+    ;
+}
+abstract class RenderBox extends mai::RenderObject {
+  synthetic constructor •() → mai::RenderBox
+    : super mai::RenderObject::•()
+    ;
+  method hitTest(mai::BoxHitTestResult result, {required mai::Offset position = #C1}) → core::bool
+    return false;
+  method hitTestChildren(mai::BoxHitTestResult result, {required mai::Offset position = #C1}) → core::bool
+    return false;
+}
+abstract class RenderObjectWithChildMixin<ChildType extends mai::RenderObject = mai::RenderObject> extends mai::RenderObject /*isMixinDeclaration*/  {
+  generic-covariant-impl field mai::RenderObjectWithChildMixin::ChildType? _child = null;
+  get child() → mai::RenderObjectWithChildMixin::ChildType?
+    return this.{mai::RenderObjectWithChildMixin::_child};
+}
+abstract class _RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin<T extends mai::RenderBox = mai::RenderBox> extends core::Object implements mai::RenderBox, mai::RenderObjectWithChildMixin<mai::_RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin::T> /*isAnonymousMixin*/  {
+  synthetic constructor •() → mai::_RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin<mai::_RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin::T>
+    : super core::Object::•()
+    ;
+}
+abstract class RenderProxyBoxMixin<T extends mai::RenderBox = mai::RenderBox> extends mai::_RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin<mai::RenderProxyBoxMixin::T> /*isMixinDeclaration*/  {
+  @#C2
+  method hitTestChildren(mai::BoxHitTestResult result, {required mai::Offset position = #C1}) → core::bool {
+    return let final core::bool? #t1 = let final mai::RenderProxyBoxMixin::T? #t2 = this.{mai::RenderObjectWithChildMixin::child} in #t2.{core::Object::==}(null) ?{core::bool?} null : #t2{mai::RenderProxyBoxMixin::T}.{mai::RenderBox::hitTest}(result, position: position) in #t1.{core::Object::==}(null) ?{core::bool} false : #t1{core::bool};
+  }
+}
+abstract class _RenderProxyBox&RenderBox&RenderObjectWithChildMixin extends mai::RenderBox implements mai::RenderObjectWithChildMixin<mai::RenderBox> /*isAnonymousMixin,isEliminatedMixin*/  {
+  generic-covariant-impl field mai::RenderBox? _child = null;
+  synthetic constructor •() → mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin
+    : super mai::RenderBox::•()
+    ;
+  get child() → mai::RenderBox?
+    return this.{mai::RenderObjectWithChildMixin::_child};
+}
+abstract class _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin extends mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin implements mai::RenderProxyBoxMixin<mai::RenderBox> /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin
+    : super mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin::•()
+    ;
+  @#C2
+  method hitTestChildren(mai::BoxHitTestResult result, {required mai::Offset position = #C1}) → core::bool {
+    return let final core::bool? #t3 = let final mai::RenderBox? #t4 = this.{mai::RenderObjectWithChildMixin::child} in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{mai::RenderBox}.{mai::RenderBox::hitTest}(result, position: position) in #t3.{core::Object::==}(null) ?{core::bool} false : #t3{core::bool};
+  }
+}
+class RenderProxyBox extends mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin {
+  synthetic constructor •() → mai::RenderProxyBox
+    : super mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin::•()
+    ;
+}
+
+constants  {
+  #C1 = null
+  #C2 = core::_Override {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..979cddb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main.dart.weak.transformed.expect
@@ -0,0 +1,125 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+abstract class RenderAnimatedOpacityMixin<T extends mai::RenderObject = mai::RenderObject> extends mai::RenderObjectWithChildMixin<self::RenderAnimatedOpacityMixin::T> /*isMixinDeclaration*/  {
+}
+abstract class _RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin extends mai::RenderProxyBox implements mai::RenderProxyBoxMixin<mai::RenderBox> /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin
+    : super mai::RenderProxyBox::•()
+    ;
+  @#C1
+  method /* from org-dartlang-testcase:///main_lib.dart */ hitTestChildren(mai::BoxHitTestResult result, {required mai::Offset position = #C2}) → core::bool {
+    return let final core::bool? #t1 = let final mai::RenderBox? #t2 = this.{mai::RenderObjectWithChildMixin::child} in #t2.{core::Object::==}(null) ?{core::bool?} null : #t2{mai::RenderBox}.{mai::RenderBox::hitTest}(result, position: position) in #t1.{core::Object::==}(null) ?{core::bool} false : #t1{core::bool};
+  }
+}
+abstract class _RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin&RenderAnimatedOpacityMixin extends self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin implements self::RenderAnimatedOpacityMixin<mai::RenderBox> /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin&RenderAnimatedOpacityMixin
+    : super self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin::•()
+    ;
+}
+class RenderAnimatedOpacity extends self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin&RenderAnimatedOpacityMixin {
+  synthetic constructor •() → self::RenderAnimatedOpacity
+    : super self::_RenderAnimatedOpacity&RenderProxyBox&RenderProxyBoxMixin&RenderAnimatedOpacityMixin::•()
+    ;
+}
+static method main() → dynamic {
+  new self::RenderAnimatedOpacity::•();
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Offset extends core::Object {
+  synthetic constructor •() → mai::Offset
+    : super core::Object::•()
+    ;
+}
+class AbstractNode extends core::Object {
+  synthetic constructor •() → mai::AbstractNode
+    : super core::Object::•()
+    ;
+}
+abstract class DiagnosticableTreeMixin extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class HitTestTarget extends core::Object {
+  synthetic constructor •() → mai::HitTestTarget
+    : super core::Object::•()
+    ;
+}
+class HitTestResult extends core::Object {
+  synthetic constructor •() → mai::HitTestResult
+    : super core::Object::•()
+    ;
+}
+class BoxHitTestResult extends mai::HitTestResult {
+  synthetic constructor •() → mai::BoxHitTestResult
+    : super mai::HitTestResult::•()
+    ;
+}
+abstract class _RenderObject&AbstractNode&DiagnosticableTreeMixin extends mai::AbstractNode implements mai::DiagnosticableTreeMixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → mai::_RenderObject&AbstractNode&DiagnosticableTreeMixin
+    : super mai::AbstractNode::•()
+    ;
+}
+abstract class RenderObject extends mai::_RenderObject&AbstractNode&DiagnosticableTreeMixin implements mai::HitTestTarget {
+  synthetic constructor •() → mai::RenderObject
+    : super mai::_RenderObject&AbstractNode&DiagnosticableTreeMixin::•()
+    ;
+}
+abstract class RenderBox extends mai::RenderObject {
+  synthetic constructor •() → mai::RenderBox
+    : super mai::RenderObject::•()
+    ;
+  method hitTest(mai::BoxHitTestResult result, {required mai::Offset position = #C2}) → core::bool
+    return false;
+  method hitTestChildren(mai::BoxHitTestResult result, {required mai::Offset position = #C2}) → core::bool
+    return false;
+}
+abstract class RenderObjectWithChildMixin<ChildType extends mai::RenderObject = mai::RenderObject> extends mai::RenderObject /*isMixinDeclaration*/  {
+  generic-covariant-impl field mai::RenderObjectWithChildMixin::ChildType? _child = null;
+  get child() → mai::RenderObjectWithChildMixin::ChildType?
+    return this.{mai::RenderObjectWithChildMixin::_child};
+}
+abstract class _RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin<T extends mai::RenderBox = mai::RenderBox> extends core::Object implements mai::RenderBox, mai::RenderObjectWithChildMixin<mai::_RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin::T> /*isAnonymousMixin*/  {
+  synthetic constructor •() → mai::_RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin<mai::_RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin::T>
+    : super core::Object::•()
+    ;
+}
+abstract class RenderProxyBoxMixin<T extends mai::RenderBox = mai::RenderBox> extends mai::_RenderProxyBoxMixin&RenderBox&RenderObjectWithChildMixin<mai::RenderProxyBoxMixin::T> /*isMixinDeclaration*/  {
+  @#C1
+  method hitTestChildren(mai::BoxHitTestResult result, {required mai::Offset position = #C2}) → core::bool {
+    return let final core::bool? #t3 = let final mai::RenderProxyBoxMixin::T? #t4 = this.{mai::RenderObjectWithChildMixin::child} in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{mai::RenderProxyBoxMixin::T}.{mai::RenderBox::hitTest}(result, position: position) in #t3.{core::Object::==}(null) ?{core::bool} false : #t3{core::bool};
+  }
+}
+abstract class _RenderProxyBox&RenderBox&RenderObjectWithChildMixin extends mai::RenderBox implements mai::RenderObjectWithChildMixin<mai::RenderBox> /*isAnonymousMixin,isEliminatedMixin*/  {
+  generic-covariant-impl field mai::RenderBox? _child = null;
+  synthetic constructor •() → mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin
+    : super mai::RenderBox::•()
+    ;
+  get child() → mai::RenderBox?
+    return this.{mai::RenderObjectWithChildMixin::_child};
+}
+abstract class _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin extends mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin implements mai::RenderProxyBoxMixin<mai::RenderBox> /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin
+    : super mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin::•()
+    ;
+  @#C1
+  method hitTestChildren(mai::BoxHitTestResult result, {required mai::Offset position = #C2}) → core::bool {
+    return let final core::bool? #t5 = let final mai::RenderBox? #t6 = this.{mai::RenderObjectWithChildMixin::child} in #t6.{core::Object::==}(null) ?{core::bool?} null : #t6{mai::RenderBox}.{mai::RenderBox::hitTest}(result, position: position) in #t5.{core::Object::==}(null) ?{core::bool} false : #t5{core::bool};
+  }
+}
+class RenderProxyBox extends mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin {
+  synthetic constructor •() → mai::RenderProxyBox
+    : super mai::_RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin::•()
+    ;
+}
+
+constants  {
+  #C1 = core::_Override {}
+  #C2 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main_lib.dart b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main_lib.dart
new file mode 100644
index 0000000..1eab9a6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/main_lib.dart
@@ -0,0 +1,42 @@
+class Offset {}
+
+class AbstractNode {}
+
+mixin DiagnosticableTreeMixin {}
+
+abstract class HitTestTarget {}
+
+class HitTestResult {}
+
+class BoxHitTestResult extends HitTestResult {}
+
+abstract class RenderObject extends AbstractNode
+    with DiagnosticableTreeMixin
+    implements HitTestTarget {}
+
+abstract class RenderBox extends RenderObject {
+  bool hitTest(BoxHitTestResult result, {required Offset position}) => false;
+  bool hitTestChildren(BoxHitTestResult result, {required Offset position}) =>
+      false;
+}
+
+mixin RenderObjectWithChildMixin<ChildType extends RenderObject>
+    on RenderObject {
+  ChildType? _child;
+
+  /// The render object's unique child
+  ChildType? get child => _child;
+}
+
+mixin RenderProxyBoxMixin<T extends RenderBox>
+    on RenderBox, RenderObjectWithChildMixin<T> {
+  @override
+  bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
+    return child?.hitTest(result, position: position) ?? false;
+  }
+}
+
+class RenderProxyBox extends RenderBox
+    with
+        RenderObjectWithChildMixin<RenderBox>,
+        RenderProxyBoxMixin<RenderBox> {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/test.options b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/test.options
new file mode 100644
index 0000000..bfe6dc8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_dill2/test.options
@@ -0,0 +1 @@
+main_lib.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in.dart.weak.expect
index d748399..e73124e 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in.dart.weak.expect
@@ -9,6 +9,8 @@
   const synthetic constructor •() → self::_Class&Object&Mixin*
     : super core::Object::•()
     ;
+  mixin-super-stub method method(core::int* i) → core::int*
+    return super.{mix::Mixin::method}(i);
   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
@@ -24,10 +26,9 @@
   synthetic constructor •() → self::Class*
     : super self::_Class&Object&Mixin::•()
     ;
-  abstract member-signature method method(core::int* i) → core::int*; -> mix::Mixin::method
 }
 static method main() → dynamic {
-  core::print(new self::Class::•().{self::Class::method}(null));
+  core::print(new self::Class::•().{self::_Class&Object&Mixin::method}(null));
 }
 
 library /*isNonNullableByDefault*/;
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in.dart.weak.transformed.expect
index 38b26da..bfe469f 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in.dart.weak.transformed.expect
@@ -9,6 +9,8 @@
   const synthetic constructor •() → self::_Class&Object&Mixin*
     : super core::Object::•()
     ;
+  method /*isNonNullableByDefault, from org-dartlang-testcase:///mixin_from_opt_in_lib.dart */ method(core::int? i) → core::int
+    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
   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
@@ -19,17 +21,14 @@
   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
-  method /*isNonNullableByDefault, from org-dartlang-testcase:///mixin_from_opt_in_lib.dart */ method(core::int? i) → core::int
-    return let final core::int? #t1 = i in #t1.{core::num::==}(null) ?{core::int} 0 : #t1{core::int};
 }
 class Class extends self::_Class&Object&Mixin {
   synthetic constructor •() → self::Class*
     : super self::_Class&Object&Mixin::•()
     ;
-  abstract member-signature method method(core::int* i) → core::int*; -> mix::Mixin::method
 }
 static method main() → dynamic {
-  core::print(new self::Class::•().{self::Class::method}(null));
+  core::print(new self::Class::•().{self::_Class&Object&Mixin::method}(null));
 }
 
 library /*isNonNullableByDefault*/;
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in_out_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in_out_in.dart.weak.expect
index 35cfeee..d8ff996 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in_out_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in_out_in.dart.weak.expect
@@ -45,6 +45,12 @@
   synthetic constructor •() → self::_DwB0&C0&B
     : super mix::C0::•()
     ;
+  mixin-super-stub get a() → core::List<(core::int) → core::int>
+    return super.{mix2::B::a};
+  mixin-super-stub set a(core::List<(core::int) → core::int> _) → void
+    return super.{mix2::B::a} = _;
+  mixin-super-stub method m((core::int) → core::int x) → (core::int) → core::int
+    return super.{mix2::B::m}(x);
   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
@@ -64,6 +70,12 @@
   synthetic constructor •() → self::_DwBq0&C0&Bq
     : super mix::C0::•()
     ;
+  mixin-super-stub get a() → core::List<(core::int?) → core::int?>
+    return super.{mix2::Bq::a};
+  mixin-super-stub set a(core::List<(core::int?) → core::int?> _) → void
+    return super.{mix2::Bq::a} = _;
+  mixin-super-stub method m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return super.{mix2::Bq::m}(x);
   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
@@ -117,6 +129,12 @@
   synthetic constructor •() → self::_DwB3&C3&B
     : super mix::C3::•()
     ;
+  mixin-super-stub get a() → core::List<(core::int) → core::int>
+    return super.{mix2::B::a};
+  mixin-super-stub set a(core::List<(core::int) → core::int> _) → void
+    return super.{mix2::B::a} = _;
+  mixin-super-stub method m((core::int) → core::int x) → (core::int) → core::int
+    return super.{mix2::B::m}(x);
   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
@@ -136,6 +154,12 @@
   synthetic constructor •() → self::_DwBq3&C3&Bq
     : super mix::C3::•()
     ;
+  mixin-super-stub get a() → core::List<(core::int?) → core::int?>
+    return super.{mix2::Bq::a};
+  mixin-super-stub set a(core::List<(core::int?) → core::int?> _) → void
+    return super.{mix2::Bq::a} = _;
+  mixin-super-stub method m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return super.{mix2::Bq::m}(x);
   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
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in_out_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in_out_in.dart.weak.transformed.expect
index 3ac39f4..82b6e2d 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in_out_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_in_out_in.dart.weak.transformed.expect
@@ -45,6 +45,11 @@
   synthetic constructor •() → self::_DwB0&C0&B
     : super mix::C0::•()
     ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int) → core::int>
+    return core::_GrowableList::•<(core::int) → core::int>(0);
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int) → core::int> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int) → core::int x) → (core::int) → core::int
+    return x;
   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
@@ -54,11 +59,6 @@
   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
-  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int) → core::int>
-    return <(core::int) → core::int>[];
-  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int) → core::int> _) → void {}
-  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int) → core::int x) → (core::int) → core::int
-    return x;
 }
 class DwB0 extends self::_DwB0&C0&B {
   synthetic constructor •() → self::DwB0
@@ -69,6 +69,11 @@
   synthetic constructor •() → self::_DwBq0&C0&Bq
     : super mix::C0::•()
     ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int?) → core::int?>
+    return core::_GrowableList::•<(core::int?) → core::int?>(0);
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int?) → core::int?> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
   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
@@ -78,11 +83,6 @@
   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
-  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int?) → core::int?>
-    return <(core::int?) → core::int?>[];
-  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int?) → core::int?> _) → void {}
-  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int?) → core::int? x) → (core::int?) → core::int?
-    return x;
 }
 class DwBq0 extends self::_DwBq0&C0&Bq {
   synthetic constructor •() → self::DwBq0
@@ -127,6 +127,11 @@
   synthetic constructor •() → self::_DwB3&C3&B
     : super mix::C3::•()
     ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int) → core::int>
+    return core::_GrowableList::•<(core::int) → core::int>(0);
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int) → core::int> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int) → core::int x) → (core::int) → core::int
+    return x;
   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
@@ -136,11 +141,6 @@
   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
-  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int) → core::int>
-    return <(core::int) → core::int>[];
-  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int) → core::int> _) → void {}
-  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int) → core::int x) → (core::int) → core::int
-    return x;
 }
 class DwB3 extends self::_DwB3&C3&B {
   synthetic constructor •() → self::DwB3
@@ -151,6 +151,11 @@
   synthetic constructor •() → self::_DwBq3&C3&Bq
     : super mix::C3::•()
     ;
+  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int?) → core::int?>
+    return core::_GrowableList::•<(core::int?) → core::int?>(0);
+  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int?) → core::int?> _) → void {}
+  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int?) → core::int? x) → (core::int?) → core::int?
+    return x;
   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
@@ -160,11 +165,6 @@
   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
-  get /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a() → core::List<(core::int?) → core::int?>
-    return <(core::int?) → core::int?>[];
-  set /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ a(core::List<(core::int?) → core::int?> _) → void {}
-  method /* from org-dartlang-testcase:///mixin_from_opt_in_out_in_lib2.dart */ m((core::int?) → core::int? x) → (core::int?) → core::int?
-    return x;
 }
 class DwBq3 extends self::_DwBq3&C3&Bq {
   synthetic constructor •() → self::DwBq3
@@ -226,7 +226,7 @@
     : super core::Object::•()
     ;
   get a() → core::List<(core::int) → core::int>
-    return <(core::int) → core::int>[];
+    return core::_GrowableList::•<(core::int) → core::int>(0);
   set a(core::List<(core::int) → core::int> _) → void {}
   method m((core::int) → core::int x) → (core::int) → core::int
     return x;
@@ -236,7 +236,7 @@
     : super core::Object::•()
     ;
   get a() → core::List<(core::int?) → core::int?>
-    return <(core::int?) → core::int?>[];
+    return core::_GrowableList::•<(core::int?) → core::int?>(0);
   set a(core::List<(core::int?) → core::int?> _) → void {}
   method m((core::int?) → core::int? x) → (core::int?) → core::int?
     return x;
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_out.dart.weak.expect
index 8a40f19..a039b1e 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_out.dart.weak.expect
@@ -9,6 +9,8 @@
   const synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
+  mixin-super-stub method /*isLegacy*/ method(core::int* i) → core::int*
+    return super.{mix::Mixin::method}(i);
   abstract member-signature operator /*isLegacy*/ ==(dynamic other) → core::bool*; -> core::Object::==
 }
 class Class extends self::_Class&Object&Mixin {
@@ -17,7 +19,7 @@
     ;
 }
 static method main() → dynamic {
-  core::print(new self::Class::•().{mix::Mixin::method}(null));
+  core::print(new self::Class::•().{self::_Class&Object&Mixin::method}(null));
 }
 
 library;
diff --git a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_out.dart.weak.transformed.expect
index 75f6938..0aa539f 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mixin_from_opt_out.dart.weak.transformed.expect
@@ -9,9 +9,9 @@
   const synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
-  abstract member-signature operator /*isLegacy, from org-dartlang-testcase:///mixin_from_opt_out_lib.dart */ ==(dynamic other) → core::bool*; -> core::Object::==
   method /*isLegacy, from org-dartlang-testcase:///mixin_from_opt_out_lib.dart */ method(core::int* i) → core::int*
     return let final core::int* #t1 = i in #t1.{core::num::==}(null) ?{core::int*} 0 : #t1;
+  abstract member-signature operator /*isLegacy, from org-dartlang-testcase:///mixin_from_opt_out_lib.dart */ ==(dynamic other) → core::bool*; -> core::Object::==
   abstract member-signature get /*isLegacy, from org-dartlang-testcase:///mixin_from_opt_out_lib.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method /*isLegacy, from org-dartlang-testcase:///mixin_from_opt_out_lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method /*isLegacy, from org-dartlang-testcase:///mixin_from_opt_out_lib.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -28,7 +28,7 @@
     ;
 }
 static method main() → dynamic {
-  core::print(new self::Class::•().{mix::Mixin::method}(null));
+  core::print(new self::Class::•().{self::_Class&Object&Mixin::method}(null));
 }
 
 library;
diff --git a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.transformed.expect
index c929e9f..e26b189 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.transformed.expect
@@ -28,55 +28,55 @@
   no-such-method-forwarder get date() → core::DateTime*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set date(core::DateTime* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get expires() → core::DateTime*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set expires(core::DateTime* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get ifModifiedSince() → core::DateTime*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set ifModifiedSince(core::DateTime* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get host() → core::String*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
   no-such-method-forwarder set host(core::String* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C11, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C11, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get port() → core::int*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set port(core::int* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get contentType() → _ht::ContentType*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} _ht::ContentType*;
   no-such-method-forwarder set contentType(_ht::ContentType* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C15, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C15, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get contentLength() → core::int*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set contentLength(core::int* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C17, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C17, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get persistentConnection() → core::bool*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C18, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
   no-such-method-forwarder set persistentConnection(core::bool* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C19, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C19, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get chunkedTransferEncoding() → core::bool*
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C20, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
   no-such-method-forwarder set chunkedTransferEncoding(core::bool* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C21, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C21, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder operator [](core::String* name) → core::List<core::String*>*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C22, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::List<core::String*>*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C22, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(name)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::List<core::String*>*;
   no-such-method-forwarder method value(core::String* name) → core::String*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C23, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C23, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(name)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
   no-such-method-forwarder method add(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C24}) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C25, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C26: preserveHeaderCase})));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C25, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal2<dynamic>(name, value)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C26: preserveHeaderCase})));
   no-such-method-forwarder method set(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C24}) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C27, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C26: preserveHeaderCase})));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C27, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal2<dynamic>(name, value)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C26: preserveHeaderCase})));
   no-such-method-forwarder method remove(core::String* name, core::Object* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C28, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C28, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal2<dynamic>(name, value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder method removeAll(core::String* name) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C29, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C29, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(name)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder method forEach((core::String*, core::List<core::String*>*) →* void action) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C30, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C30, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(action)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder method noFolding(core::String* name) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C31, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C31, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(name)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/_http/http.dart */ clear() → void
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C32, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.expect
index ee003ce..2572b51 100644
--- a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.expect
@@ -48,19 +48,19 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C extends nev::A {
-  field Null neverField = null;
-  field Null nullField = null;
+  field Never* neverField = null;
+  field Never* nullField = null;
   synthetic constructor •() → self::C*
     : super nev::A::•()
     ;
-  method neverMethod(Null value) → Null
+  method neverMethod(Null value) → Never*
     return value;
-  get neverProperty() → Null
+  get neverProperty() → Never*
     return null;
   set neverProperty(Null value) → void {}
-  method nullMethod(Null value) → Null
+  method nullMethod(Null value) → Never*
     return value;
-  get nullProperty() → Null
+  get nullProperty() → Never*
     return null;
   set nullProperty(Null value) → void {}
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -74,15 +74,15 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field Null optOutNever;
+static field Never* optOutNever;
 static field dynamic inferredOptOutNever = nev::optInNever;
 static method genericMethod<T extends core::Object* = dynamic>() → dynamic {}
 static method main() → dynamic {
   nev::optInNever = self::optOutNever;
-  core::Type* typeNever = Null;
-  self::genericMethod<Null>();
-  new self::GenericClass::•<Null>();
-  Null localNever = null;
+  core::Type* typeNever = #C1;
+  self::genericMethod<Never*>();
+  new self::GenericClass::•<Never*>();
+  Never* localNever = null;
   Null localNull = null;
   dynamic inferredLocalNever = nev::optInNever;
   localNever = localNever;
@@ -109,14 +109,14 @@
   localNull = localNull;
   self::inferredOptOutNever = localNull;
   inferredLocalNever = localNull;
-  localNever = self::inferredOptOutNever as{TypeError,ForDynamic} Null;
-  self::optOutNever = self::inferredOptOutNever as{TypeError,ForDynamic} Null;
+  localNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never*;
+  self::optOutNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never*;
   nev::optInNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never;
   localNull = self::inferredOptOutNever as{TypeError,ForDynamic} Null;
   self::inferredOptOutNever = self::inferredOptOutNever;
   inferredLocalNever = self::inferredOptOutNever;
-  localNever = inferredLocalNever as{TypeError,ForDynamic} Null;
-  self::optOutNever = inferredLocalNever as{TypeError,ForDynamic} Null;
+  localNever = inferredLocalNever as{TypeError,ForDynamic} Never*;
+  self::optOutNever = inferredLocalNever as{TypeError,ForDynamic} Never*;
   nev::optInNever = inferredLocalNever as{TypeError,ForDynamic} Never;
   localNull = inferredLocalNever as{TypeError,ForDynamic} Null;
   self::inferredOptOutNever = inferredLocalNever;
@@ -181,3 +181,7 @@
   return throw "Should never return";
 static method boundedGenericMethod2<T extends Never = Never>() → core::List<nev::boundedGenericMethod2::T>
   return <nev::boundedGenericMethod2::T>[];
+
+constants  {
+  #C1 = TypeLiteralConstant(Never*)
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.transformed.expect
index 34765b6..ce6f78a 100644
--- a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.transformed.expect
@@ -48,19 +48,19 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C extends nev::A {
-  field Null neverField = null;
-  field Null nullField = null;
+  field Never* neverField = null;
+  field Never* nullField = null;
   synthetic constructor •() → self::C*
     : super nev::A::•()
     ;
-  method neverMethod(Null value) → Null
+  method neverMethod(Null value) → Never*
     return value;
-  get neverProperty() → Null
+  get neverProperty() → Never*
     return null;
   set neverProperty(Null value) → void {}
-  method nullMethod(Null value) → Null
+  method nullMethod(Null value) → Never*
     return value;
-  get nullProperty() → Null
+  get nullProperty() → Never*
     return null;
   set nullProperty(Null value) → void {}
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -74,15 +74,15 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field Null optOutNever;
+static field Never* optOutNever;
 static field dynamic inferredOptOutNever = nev::optInNever;
 static method genericMethod<T extends core::Object* = dynamic>() → dynamic {}
 static method main() → dynamic {
   nev::optInNever = self::optOutNever;
-  core::Type* typeNever = Null;
-  self::genericMethod<Null>();
-  new self::GenericClass::•<Null>();
-  Null localNever = null;
+  core::Type* typeNever = #C1;
+  self::genericMethod<Never*>();
+  new self::GenericClass::•<Never*>();
+  Never* localNever = null;
   Null localNull = null;
   dynamic inferredLocalNever = nev::optInNever;
   localNever = localNever;
@@ -109,14 +109,14 @@
   localNull = localNull;
   self::inferredOptOutNever = localNull;
   inferredLocalNever = localNull;
-  localNever = self::inferredOptOutNever as{TypeError,ForDynamic} Null;
-  self::optOutNever = self::inferredOptOutNever as{TypeError,ForDynamic} Null;
+  localNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never*;
+  self::optOutNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never*;
   nev::optInNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never;
   localNull = self::inferredOptOutNever as{TypeError,ForDynamic} Null;
   self::inferredOptOutNever = self::inferredOptOutNever;
   inferredLocalNever = self::inferredOptOutNever;
-  localNever = inferredLocalNever as{TypeError,ForDynamic} Null;
-  self::optOutNever = inferredLocalNever as{TypeError,ForDynamic} Null;
+  localNever = inferredLocalNever as{TypeError,ForDynamic} Never*;
+  self::optOutNever = inferredLocalNever as{TypeError,ForDynamic} Never*;
   nev::optInNever = inferredLocalNever as{TypeError,ForDynamic} Never;
   localNull = inferredLocalNever as{TypeError,ForDynamic} Null;
   self::inferredOptOutNever = inferredLocalNever;
@@ -180,9 +180,8 @@
 static method boundedGenericMethod1<T extends Never = Never>() → nev::boundedGenericMethod1::T
   return throw "Should never return";
 static method boundedGenericMethod2<T extends Never = Never>() → core::List<nev::boundedGenericMethod2::T>
-  return <nev::boundedGenericMethod2::T>[];
+  return core::_GrowableList::•<nev::boundedGenericMethod2::T>(0);
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///never_opt_out.dart:19:20 -> TypeLiteralConstant(Null)
-Extra constant evaluation: evaluated: 136, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(Never*)
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline.expect
index 33f6302..14d2d75 100644
--- a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline.expect
@@ -2,8 +2,17 @@
 class Class {
   Class _field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  Class get field => _field;
+  void set field(Class value) {}
+  Class method() => field;
+  Class operator [](Class key) => field;
+  void operator []=(Class key, Class value) {}
+  Class operator +(int value) => field;
+  Class operator -() => field;
+}
+
 main() {}
 void propertyAccess(Class c) {}
 void indexAccess(Class c) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..027cbbc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+// @dart = 2.6
+class Class {
+  Class _field;
+}
+
+extension Extension on Class {
+  Class get field => _field;
+  Class method() => field;
+  Class operator +(int value) => field;
+  Class operator -() => field;
+  Class operator [](Class key) => field;
+  void operator []=(Class key, Class value) {}
+  void set field(Class value) {}
+}
+
+main() {}
+void ifNull(Class c) {}
+void indexAccess(Class c) {}
+void operatorAccess(Class c) {}
+void propertyAccess(Class c) {}
+void throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline.expect
index 33f6302..14d2d75 100644
--- a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline.expect
@@ -2,8 +2,17 @@
 class Class {
   Class _field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  Class get field => _field;
+  void set field(Class value) {}
+  Class method() => field;
+  Class operator [](Class key) => field;
+  void operator []=(Class key, Class value) {}
+  Class operator +(int value) => field;
+  Class operator -() => field;
+}
+
 main() {}
 void propertyAccess(Class c) {}
 void indexAccess(Class c) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..027cbbc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+// @dart = 2.6
+class Class {
+  Class _field;
+}
+
+extension Extension on Class {
+  Class get field => _field;
+  Class method() => field;
+  Class operator +(int value) => field;
+  Class operator -() => field;
+  Class operator [](Class key) => field;
+  void operator []=(Class key, Class value) {}
+  void set field(Class value) {}
+}
+
+main() {}
+void ifNull(Class c) {}
+void indexAccess(Class c) {}
+void operatorAccess(Class c) {}
+void propertyAccess(Class c) {}
+void throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline.expect
index 72a0f5b..db630d4 100644
--- a/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline.expect
@@ -1,6 +1,8 @@
 import 'nullable_extension_on_opt_out_lib.dart';
-extension on ;
-A;
-? { String get text => "Lily was here"; }
+
+extension on A? {
+  String get text => "Lily was here";
+}
+
 void main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5294531
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+import 'nullable_extension_on_opt_out_lib.dart';
+
+expect(expected, actual) {}
+
+extension on A? {
+  String get text => "Lily was here";
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.expect
index 567675d..964ecb3 100644
--- a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.expect
@@ -34,7 +34,7 @@
 import "dart:core" as core;
 
 class Class1<T extends core::Object? = core::Object?> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class1::redirect, opt::Class1::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class1::redirect, opt::Class1::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class1<opt::Class1::T%>
     : super core::Object::•()
     ;
@@ -46,7 +46,7 @@
     return new opt::Class1::_<opt::Class1::fact::T%>();
 }
 class Class2<T extends core::Object = core::Object> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class2::redirect, opt::Class2::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class2::redirect, opt::Class2::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class2<opt::Class2::T>
     : super core::Object::•()
     ;
@@ -58,7 +58,7 @@
     return new opt::Class2::_<opt::Class2::fact::T>();
 }
 class Class3<T extends core::String = core::String> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class3::redirect, opt::Class3::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class3::redirect, opt::Class3::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class3<opt::Class3::T>
     : super core::Object::•()
     ;
@@ -70,7 +70,7 @@
     return new opt::Class3::_<opt::Class3::fact::T>();
 }
 class Class4<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class4::redirect, opt::Class4::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class4::redirect, opt::Class4::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class4<opt::Class4::T%>
     : super core::Object::•()
     ;
@@ -82,7 +82,7 @@
     return new opt::Class4::_<opt::Class4::fact::T%>();
 }
 class Class5<T extends dynamic = dynamic> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class5::redirect, opt::Class5::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class5::redirect, opt::Class5::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class5<opt::Class5::T%>
     : super core::Object::•()
     ;
@@ -96,7 +96,7 @@
 static method testOptIn() → dynamic {
   new opt::Class1::_<core::Object?>();
   new opt::Class1::_<core::Object?>();
-  #C1;
+  #C6;
   opt::Class1::fact<core::Object?>();
   new opt::Class2::_<core::Object>();
   new opt::Class2::_<core::Object>();
@@ -122,4 +122,22 @@
   #C3 = opt::Class3<core::String*> {}
   #C4 = opt::Class4<dynamic> {}
   #C5 = opt::Class5<dynamic> {}
+  #C6 = opt::Class1<core::Object?> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Class1._ (from org-dartlang-testcase:///opt_in_lib.dart:10:9)
+- Class2._ (from org-dartlang-testcase:///opt_in_lib.dart:18:9)
+- Class3._ (from org-dartlang-testcase:///opt_in_lib.dart:26:9)
+- Class4._ (from org-dartlang-testcase:///opt_in_lib.dart:34:9)
+- Class5._ (from org-dartlang-testcase:///opt_in_lib.dart:42:9)
+
+org-dartlang-testcase:///opt_in_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class1._ (from org-dartlang-testcase:///opt_in_lib.dart:10:9)
+- Class2._ (from org-dartlang-testcase:///opt_in_lib.dart:18:9)
+- Class3._ (from org-dartlang-testcase:///opt_in_lib.dart:26:9)
+- Class4._ (from org-dartlang-testcase:///opt_in_lib.dart:34:9)
+- Class5._ (from org-dartlang-testcase:///opt_in_lib.dart:42:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.transformed.expect
index 789e4fb..46322ee 100644
--- a/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_factory/main.dart.weak.transformed.expect
@@ -34,7 +34,7 @@
 import "dart:core" as core;
 
 class Class1<T extends core::Object? = core::Object?> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class1::redirect, opt::Class1::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class1::redirect, opt::Class1::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class1<opt::Class1::T%>
     : super core::Object::•()
     ;
@@ -46,7 +46,7 @@
     return new opt::Class1::_<opt::Class1::fact::T%>();
 }
 class Class2<T extends core::Object = core::Object> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class2::redirect, opt::Class2::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class2::redirect, opt::Class2::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class2<opt::Class2::T>
     : super core::Object::•()
     ;
@@ -58,7 +58,7 @@
     return new opt::Class2::_<opt::Class2::fact::T>();
 }
 class Class3<T extends core::String = core::String> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class3::redirect, opt::Class3::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class3::redirect, opt::Class3::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class3<opt::Class3::T>
     : super core::Object::•()
     ;
@@ -70,7 +70,7 @@
     return new opt::Class3::_<opt::Class3::fact::T>();
 }
 class Class4<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class4::redirect, opt::Class4::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class4::redirect, opt::Class4::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class4<opt::Class4::T%>
     : super core::Object::•()
     ;
@@ -82,7 +82,7 @@
     return new opt::Class4::_<opt::Class4::fact::T%>();
 }
 class Class5<T extends dynamic = dynamic> extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::Class5::redirect, opt::Class5::constRedirect]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::Class5::redirect, opt::Class5::constRedirect]/*isLegacy*/;
   const constructor _() → opt::Class5<opt::Class5::T%>
     : super core::Object::•()
     ;
@@ -96,7 +96,7 @@
 static method testOptIn() → dynamic {
   new opt::Class1::_<core::Object?>();
   new opt::Class1::_<core::Object?>();
-  #C1;
+  #C6;
   opt::Class1::fact<core::Object?>();
   new opt::Class2::_<core::Object>();
   new opt::Class2::_<core::Object>();
@@ -122,4 +122,22 @@
   #C3 = opt::Class3<core::String*> {}
   #C4 = opt::Class4<dynamic> {}
   #C5 = opt::Class5<dynamic> {}
+  #C6 = opt::Class1<core::Object?> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Class1._ (from org-dartlang-testcase:///opt_in_lib.dart:10:9)
+- Class2._ (from org-dartlang-testcase:///opt_in_lib.dart:18:9)
+- Class3._ (from org-dartlang-testcase:///opt_in_lib.dart:26:9)
+- Class4._ (from org-dartlang-testcase:///opt_in_lib.dart:34:9)
+- Class5._ (from org-dartlang-testcase:///opt_in_lib.dart:42:9)
+
+org-dartlang-testcase:///opt_in_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- Class1._ (from org-dartlang-testcase:///opt_in_lib.dart:10:9)
+- Class2._ (from org-dartlang-testcase:///opt_in_lib.dart:18:9)
+- Class3._ (from org-dartlang-testcase:///opt_in_lib.dart:26:9)
+- Class4._ (from org-dartlang-testcase:///opt_in_lib.dart:34:9)
+- Class5._ (from org-dartlang-testcase:///opt_in_lib.dart:42:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.expect
index 37158e0..f9e81d9 100644
--- a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.expect
@@ -50,7 +50,7 @@
     ;
 }
 class CP<T extends core::Object = core::Object> extends opt::P<opt::CP::T> /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::CP::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::CP::•]/*isLegacy*/;
   const constructor _(core::Object token) → opt::CP<opt::CP::T>
     : super opt::P::_(token)
     ;
@@ -63,7 +63,7 @@
     ;
 }
 class VP<T extends core::Object = core::Object> extends opt::P<opt::VP::T> /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::VP::forToken]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::VP::forToken]/*isLegacy*/;
   const constructor _(core::Object token, opt::VP::T useValue) → opt::VP<opt::VP::T>
     : super opt::P::_(token)
     ;
@@ -86,3 +86,16 @@
   #C6 = opt::M {list:#C5}
   #C7 = <opt::P<core::Object*>*>[]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- CP._ (from org-dartlang-testcase:///opt_in_lib.dart:14:9)
+- XToken. (from org-dartlang-testcase:///main.dart:12:9)
+- Token. (from org-dartlang-testcase:///opt_in_lib.dart:18:9)
+- VP._ (from org-dartlang-testcase:///opt_in_lib.dart:27:9)
+- M. (from org-dartlang-testcase:///opt_in_lib.dart:36:9)
+
+org-dartlang-testcase:///opt_in_lib.dart:
+- P._ (from org-dartlang-testcase:///opt_in_lib.dart:8:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.transformed.expect
index 49ef11a..a8f6383 100644
--- a/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/object_bound_redirecting_factory/main.dart.weak.transformed.expect
@@ -50,7 +50,7 @@
     ;
 }
 class CP<T extends core::Object = core::Object> extends opt::P<opt::CP::T> /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::CP::•]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::CP::•]/*isLegacy*/;
   const constructor _(core::Object token) → opt::CP<opt::CP::T>
     : super opt::P::_(token)
     ;
@@ -63,7 +63,7 @@
     ;
 }
 class VP<T extends core::Object = core::Object> extends opt::P<opt::VP::T> /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[opt::VP::forToken]/*isLegacy*/;
+  static final field dynamic _redirecting# = <dynamic>[opt::VP::forToken]/*isLegacy*/;
   const constructor _(core::Object token, opt::VP::T useValue) → opt::VP<opt::VP::T>
     : super opt::P::_(token)
     ;
@@ -86,3 +86,16 @@
   #C6 = opt::M {list:#C5}
   #C7 = <opt::P<core::Object*>*>[]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- CP._ (from org-dartlang-testcase:///opt_in_lib.dart:14:9)
+- XToken. (from org-dartlang-testcase:///main.dart:12:9)
+- Token. (from org-dartlang-testcase:///opt_in_lib.dart:18:9)
+- VP._ (from org-dartlang-testcase:///opt_in_lib.dart:27:9)
+- M. (from org-dartlang-testcase:///opt_in_lib.dart:36:9)
+
+org-dartlang-testcase:///opt_in_lib.dart:
+- P._ (from org-dartlang-testcase:///opt_in_lib.dart:8:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.textual_outline.expect
index 708b920..be1c56c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.textual_outline.expect
@@ -1,15 +1,16 @@
 import 'opt_out_lib.dart';
+
 class A<T> {
-  late int ;
-  field = 42;
+  late int field = 42;
 }
+
 class B extends A<String?> {}
+
 typedef F = void Function()?;
 List<String?> l = [];
 String? s = null;
 var t = s!;
-late int ;
-field = 42;
+late int field = 42;
 void method(void f()?, {required int a}) {}
 main() {}
 noErrors() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a3c6fff
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+import 'opt_out_lib.dart';
+List<String?> l = [];
+String? s = null;
+class A<T> {
+  ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+  int field = 42;
+}
+class B extends A<String?> {}
+typedef F = void Function()?;
+var t = s!;
+---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+int field = 42;
+main() {}
+noErrors() {}
+void method(void f()?, {required int a}) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.expect
index 3869af1..afc1e53 100644
--- a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.expect
@@ -153,7 +153,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-class B extends self2::A<core::String?> {
+class B extends self2::A<core::String*> {
   synthetic constructor •() → self2::B*
     : super self2::A::•()
     ;
@@ -162,7 +162,7 @@
 static field core::String? s = null;
 static field core::String* t = self2::s!;
 static field core::int* field = 42;
-static method method(() →? void f, {core::int* a = #C1}) → void {}
+static method method(() →* void f, {core::int* a = #C1}) → void {}
 static method errors() → dynamic {
   core::int* local = 42;
   core::List<core::String?>* l = null;
diff --git a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.transformed.expect
index 3869af1..1df514c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.transformed.expect
@@ -23,7 +23,7 @@
     : super self::A::•()
     ;
 }
-static field core::List<core::String?> l = <core::String?>[];
+static field core::List<core::String?> l = core::_GrowableList::•<core::String?>(0);
 static field core::String? s = null;
 static field core::String t = self::s!;
 late static field core::int field = 42;
@@ -153,16 +153,16 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-class B extends self2::A<core::String?> {
+class B extends self2::A<core::String*> {
   synthetic constructor •() → self2::B*
     : super self2::A::•()
     ;
 }
-static field core::List<core::String?>* l = <core::String*>[];
+static field core::List<core::String?>* l = core::_GrowableList::•<core::String*>(0);
 static field core::String? s = null;
 static field core::String* t = self2::s!;
 static field core::int* field = 42;
-static method method(() →? void f, {core::int* a = #C1}) → void {}
+static method method(() →* void f, {core::int* a = #C1}) → void {}
 static method errors() → dynamic {
   core::int* local = 42;
   core::List<core::String?>* l = null;
diff --git a/pkg/front_end/testcases/nnbd_mixed/regress_null_aware.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/regress_null_aware.dart.weak.transformed.expect
index 11de2a4..a873a8e 100644
--- a/pkg/front_end/testcases/nnbd_mixed/regress_null_aware.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/regress_null_aware.dart.weak.transformed.expect
@@ -10,11 +10,11 @@
     ;
   method method(core::String* node, core::Set<core::String*>* set) → core::List<core::String*>*
     return set.{core::Set::add}(node) ?{core::List<core::String*>*} block {
-      final core::List<core::String*>* #t1 = <core::String*>[node];
+      final core::List<core::String*>* #t1 = core::_GrowableList::_literal1<core::String*>(node);
       final core::Iterable<core::String*>* #t2 = let final core::Iterable<core::String*>* #t3 = let final core::Set<core::String*>* #t4 = this.{self::Class::map}.{core::Map::[]}(node) in #t4.{core::Object::==}(null) ?{core::Iterable<core::String*>*} null : #t4.{core::Iterable::expand}<core::String*>((core::String* node) → core::List<core::String*>* => this.{self::Class::method}(node, set)) in #t3.{core::Object::==}(null) ?{core::List<core::String*>*} null : #t3.{core::Iterable::toList}();
       if(!#t2.{core::Object::==}(null))
         #t1.{core::List::addAll}{Invariant}(#t2);
-    } =>#t1 : <core::String*>[];
+    } =>#t1 : core::_GrowableList::•<core::String*>(0);
   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
diff --git a/pkg/front_end/testcases/nnbd_mixed/required_parameter_mixed_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/required_parameter_mixed_from_opt_out.dart.weak.expect
index 4cc02b1..64a13f8 100644
--- a/pkg/front_end/testcases/nnbd_mixed/required_parameter_mixed_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/required_parameter_mixed_from_opt_out.dart.weak.expect
@@ -16,7 +16,7 @@
     : super self::Super::•()
     ;
   forwarding-stub method /*isLegacy*/ method({covariant core::int* named = #C1}) → void
-    return super.{self::Super::method}(named: named);
+    return super.{req::Mixin::method}(named: named);
   abstract member-signature operator /*isLegacy*/ ==(dynamic other) → core::bool*; -> core::Object::==
 }
 class Class extends self::_Class&Super&Mixin {
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart
new file mode 100644
index 0000000..5b167d0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart
@@ -0,0 +1,92 @@
+// 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 'dart:async';
+import 'return_from_async_lib.dart';
+
+abstract class Class {
+  FutureOr<int> throwFutureOrInt();
+
+  int throwInt();
+
+  Future<int> throwFutureInt();
+
+  dynamic throwDynamic();
+
+  Future<num> throwFutureNum();
+}
+
+bool caughtFutureOrInt = false;
+
+Future<int> callFutureOrInt(Class c) async {
+  try {
+    return c.throwFutureOrInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureOrInt = true;
+    return 0;
+  }
+}
+
+bool caughtInt = false;
+
+Future<int> callInt(Class c) async {
+  try {
+    return c.throwInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtInt = true;
+    return 0;
+  }
+}
+
+bool caughtFutureInt = false;
+
+Future<int> callFutureInt(Class c) async {
+  try {
+    return c.throwFutureInt();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureInt = true;
+    return 0;
+  }
+}
+
+bool caughtDynamic = false;
+
+Future<int> callDynamic(Class c) async {
+  try {
+    return c.throwDynamic();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtDynamic = true;
+    return 0;
+  }
+}
+
+bool caughtFutureNum = false;
+
+Future<num> callFutureNum(Class c) async {
+  try {
+    return c.throwFutureNum();
+  } catch (e) {
+    print('Caught "$e"');
+    caughtFutureNum = true;
+    return 0;
+  }
+}
+
+void main() async {
+  Class c = new Subclass();
+  await callFutureOrInt(c);
+  if (!caughtFutureOrInt) throw 'Uncaught async return';
+  await callInt(c);
+  if (!caughtInt) throw 'Uncaught async return';
+  await callFutureInt(c);
+  if (!caughtFutureInt) throw 'Uncaught async return';
+  await callDynamic(c);
+  if (!caughtDynamic) throw 'Uncaught async return';
+  await callFutureNum(c);
+  if (!caughtFutureNum) throw 'Uncaught async return';
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline.expect
new file mode 100644
index 0000000..66339b5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+import 'dart:async';
+import 'return_from_async_lib.dart';
+
+abstract class Class {
+  FutureOr<int> throwFutureOrInt();
+  int throwInt();
+  Future<int> throwFutureInt();
+  dynamic throwDynamic();
+  Future<num> throwFutureNum();
+}
+
+bool caughtFutureOrInt = false;
+Future<int> callFutureOrInt(Class c) async {}
+bool caughtInt = false;
+Future<int> callInt(Class c) async {}
+bool caughtFutureInt = false;
+Future<int> callFutureInt(Class c) async {}
+bool caughtDynamic = false;
+Future<int> callDynamic(Class c) async {}
+bool caughtFutureNum = false;
+Future<num> callFutureNum(Class c) async {}
+void main() async {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c8dcd7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.textual_outline_modelled.expect
@@ -0,0 +1,23 @@
+import 'dart:async';
+import 'return_from_async_lib.dart';
+
+Future<int> callDynamic(Class c) async {}
+Future<int> callFutureInt(Class c) async {}
+Future<int> callFutureOrInt(Class c) async {}
+Future<int> callInt(Class c) async {}
+Future<num> callFutureNum(Class c) async {}
+
+abstract class Class {
+  Future<int> throwFutureInt();
+  Future<num> throwFutureNum();
+  FutureOr<int> throwFutureOrInt();
+  dynamic throwDynamic();
+  int throwInt();
+}
+
+bool caughtDynamic = false;
+bool caughtFutureInt = false;
+bool caughtFutureNum = false;
+bool caughtFutureOrInt = false;
+bool caughtInt = false;
+void main() async {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.expect
new file mode 100644
index 0000000..0a614de
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.expect
@@ -0,0 +1,122 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "return_from_async_lib.dart" as ret;
+
+import "dart:async";
+import "org-dartlang-testcase:///return_from_async_lib.dart";
+
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  abstract method throwFutureOrInt() → FutureOr<core::int>;
+  abstract method throwInt() → core::int;
+  abstract method throwFutureInt() → asy::Future<core::int>;
+  abstract method throwDynamic() → dynamic;
+  abstract method throwFutureNum() → asy::Future<core::num>;
+}
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method callFutureOrInt(self::Class c) → asy::Future<core::int> async {
+  try {
+    return let final FutureOr<core::int>#t1 = c.{self::Class::throwFutureOrInt}() in #t1 is asy::Future<core::int> ?{FutureOr<core::int>} await #t1 : #t1;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureOrInt = true;
+    return let final core::int #t2 = 0 in #t2 is asy::Future<core::int> ?{FutureOr<core::int>} await #t2 : #t2;
+  }
+}
+static method callInt(self::Class c) → asy::Future<core::int> async {
+  try {
+    return let final core::int #t3 = c.{self::Class::throwInt}() in #t3 is asy::Future<core::int> ?{FutureOr<core::int>} await #t3 : #t3;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtInt = true;
+    return let final core::int #t4 = 0 in #t4 is asy::Future<core::int> ?{FutureOr<core::int>} await #t4 : #t4;
+  }
+}
+static method callFutureInt(self::Class c) → asy::Future<core::int> async {
+  try {
+    return let final asy::Future<core::int> #t5 = c.{self::Class::throwFutureInt}() in #t5 is asy::Future<core::int> ?{FutureOr<core::int>} await #t5 : #t5;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureInt = true;
+    return let final core::int #t6 = 0 in #t6 is asy::Future<core::int> ?{FutureOr<core::int>} await #t6 : #t6;
+  }
+}
+static method callDynamic(self::Class c) → asy::Future<core::int> async {
+  try {
+    return let final dynamic #t7 = c.{self::Class::throwDynamic}() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int> in #t7 is asy::Future<core::int> ?{FutureOr<core::int>} await #t7 : #t7;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtDynamic = true;
+    return let final core::int #t8 = 0 in #t8 is asy::Future<core::int> ?{FutureOr<core::int>} await #t8 : #t8;
+  }
+}
+static method callFutureNum(self::Class c) → asy::Future<core::num> async {
+  try {
+    return let final asy::Future<core::num> #t9 = c.{self::Class::throwFutureNum}() in #t9 is asy::Future<core::num> ?{FutureOr<core::num>} await #t9 : #t9;
+  }
+  on core::Object catch(final core::Object e) {
+    core::print("Caught \"${e}\"");
+    self::caughtFutureNum = true;
+    return let final core::int #t10 = 0 in #t10 is asy::Future<core::num> ?{FutureOr<core::num>} await #t10 : #t10;
+  }
+}
+static method main() → void async {
+  self::Class c = new ret::Subclass::•();
+  await self::callFutureOrInt(c);
+  if(!self::caughtFutureOrInt)
+    throw "Uncaught async return";
+  await self::callInt(c);
+  if(!self::caughtInt)
+    throw "Uncaught async return";
+  await self::callFutureInt(c);
+  if(!self::caughtFutureInt)
+    throw "Uncaught async return";
+  await self::callDynamic(c);
+  if(!self::caughtDynamic)
+    throw "Uncaught async return";
+  await self::callFutureNum(c);
+  if(!self::caughtFutureNum)
+    throw "Uncaught async return";
+}
+
+library /*isNonNullableByDefault*/;
+import self as ret;
+import "dart:core" as core;
+import "return_from_async.dart" as self;
+import "dart:async" as asy;
+
+import "dart:async";
+import "org-dartlang-testcase:///return_from_async.dart";
+
+class Subclass extends core::Object implements self::Class {
+  synthetic constructor •() → ret::Subclass
+    : super core::Object::•()
+    ;
+  method throwFutureOrInt() → FutureOr<core::int> async {
+    throw "FutureOr<int>";
+  }
+  method throwInt() → core::int {
+    throw "int";
+  }
+  method throwFutureInt() → asy::Future<core::int> async {
+    throw "Future<int>";
+  }
+  method throwDynamic() → dynamic {
+    throw "dynamic";
+  }
+  method throwFutureNum() → asy::Future<core::num> async {
+    throw "Future<num>";
+  }
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.transformed.expect
new file mode 100644
index 0000000..1924b7e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async.dart.weak.transformed.expect
@@ -0,0 +1,461 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+import "return_from_async_lib.dart" as ret;
+
+import "dart:async";
+import "org-dartlang-testcase:///return_from_async_lib.dart";
+
+abstract class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  abstract method throwFutureOrInt() → FutureOr<core::int>;
+  abstract method throwInt() → core::int;
+  abstract method throwFutureInt() → asy::Future<core::int>;
+  abstract method throwDynamic() → dynamic;
+  abstract method throwFutureNum() → asy::Future<core::num>;
+}
+static field core::bool caughtFutureOrInt = false;
+static field core::bool caughtInt = false;
+static field core::bool caughtFutureInt = false;
+static field core::bool caughtDynamic = false;
+static field core::bool caughtFutureNum = false;
+static method callFutureOrInt(self::Class c) → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        try {
+          final FutureOr<core::int>#t1 = c.{self::Class::throwFutureOrInt}();
+          if(#t1 is asy::Future<core::int>) {
+            [yield] let dynamic #t2 = asy::_awaitHelper(#t1, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t1;
+          }
+          :return_value = :async_temporary_0;
+          break #L1;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureOrInt = true;
+          final core::int #t3 = 0;
+          if(#t3 is asy::Future<core::int>) {
+            [yield] let dynamic #t4 = asy::_awaitHelper(#t3, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t3;
+          }
+          :return_value = :async_temporary_2;
+          break #L1;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callInt(self::Class c) → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        try {
+          final core::int #t5 = c.{self::Class::throwInt}();
+          if(#t5 is asy::Future<core::int>) {
+            [yield] let dynamic #t6 = asy::_awaitHelper(#t5, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t5;
+          }
+          :return_value = :async_temporary_0;
+          break #L2;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtInt = true;
+          final core::int #t7 = 0;
+          if(#t7 is asy::Future<core::int>) {
+            [yield] let dynamic #t8 = asy::_awaitHelper(#t7, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t7;
+          }
+          :return_value = :async_temporary_2;
+          break #L2;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureInt(self::Class c) → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        try {
+          final asy::Future<core::int> #t9 = c.{self::Class::throwFutureInt}();
+          if(#t9 is asy::Future<core::int>) {
+            [yield] let dynamic #t10 = asy::_awaitHelper(#t9, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t9;
+          }
+          :return_value = :async_temporary_0;
+          break #L3;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureInt = true;
+          final core::int #t11 = 0;
+          if(#t11 is asy::Future<core::int>) {
+            [yield] let dynamic #t12 = asy::_awaitHelper(#t11, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t11;
+          }
+          :return_value = :async_temporary_2;
+          break #L3;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callDynamic(self::Class c) → asy::Future<core::int> /* originally async */ {
+  final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+  core::bool* :is_sync = false;
+  FutureOr<core::int>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::int>:async_temporary_0;
+  FutureOr<core::int>:async_temporary_1;
+  FutureOr<core::int>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L4:
+      {
+        try {
+          final FutureOr<core::int>#t13 = c.{self::Class::throwDynamic}() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::int>;
+          if(#t13 is asy::Future<core::int>) {
+            [yield] let dynamic #t14 = asy::_awaitHelper(#t13, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_0 = #t13;
+          }
+          :return_value = :async_temporary_0;
+          break #L4;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtDynamic = true;
+          final core::int #t15 = 0;
+          if(#t15 is asy::Future<core::int>) {
+            [yield] let dynamic #t16 = asy::_awaitHelper(#t15, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t15;
+          }
+          :return_value = :async_temporary_2;
+          break #L4;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method callFutureNum(self::Class c) → asy::Future<core::num> /* originally async */ {
+  final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
+  core::bool* :is_sync = false;
+  FutureOr<core::num>? :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 :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  FutureOr<core::num>:async_temporary_0;
+  FutureOr<core::num>:async_temporary_1;
+  FutureOr<core::num>:async_temporary_2;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        try {
+          final asy::Future<core::num> #t17 = c.{self::Class::throwFutureNum}();
+          if(#t17 is asy::Future<core::num>) {
+            [yield] let dynamic #t18 = asy::_awaitHelper(#t17, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_0 = _in::unsafeCast<core::num>(:result);
+          }
+          else {
+            :async_temporary_0 = #t17;
+          }
+          :return_value = :async_temporary_0;
+          break #L5;
+        }
+        on core::Object catch(final core::Object e) {
+          core::print("Caught \"${e}\"");
+          self::caughtFutureNum = true;
+          final core::int #t19 = 0;
+          if(#t19 is asy::Future<core::num>) {
+            [yield] let dynamic #t20 = asy::_awaitHelper(#t19, :async_op_then, :async_op_error, :async_op) in null;
+            :async_temporary_2 = _in::unsafeCast<core::int>(:result);
+          }
+          else {
+            :async_temporary_2 = #t19;
+          }
+          :return_value = :async_temporary_2;
+          break #L5;
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+static method main() → void /* 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;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L6:
+      {
+        self::Class c = new ret::Subclass::•();
+        [yield] let dynamic #t21 = asy::_awaitHelper(self::callFutureOrInt(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureOrInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t22 = asy::_awaitHelper(self::callInt(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t23 = asy::_awaitHelper(self::callFutureInt(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtFutureInt)
+          throw "Uncaught async return";
+        [yield] let dynamic #t24 = asy::_awaitHelper(self::callDynamic(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::int>(:result);
+        if(!self::caughtDynamic)
+          throw "Uncaught async return";
+        [yield] let dynamic #t25 = asy::_awaitHelper(self::callFutureNum(c), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<core::num>(:result);
+        if(!self::caughtFutureNum)
+          throw "Uncaught async return";
+      }
+      asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+      return;
+    }
+    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.call();
+  :is_sync = true;
+  return :async_future;
+}
+
+library /*isNonNullableByDefault*/;
+import self as ret;
+import "dart:core" as core;
+import "return_from_async.dart" as self;
+import "dart:async" as asy;
+
+import "dart:async";
+import "org-dartlang-testcase:///return_from_async.dart";
+
+class Subclass extends core::Object implements self::Class {
+  synthetic constructor •() → ret::Subclass
+    : super core::Object::•()
+    ;
+  method throwFutureOrInt() → FutureOr<core::int> /* originally async */ {
+    final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+    core::bool* :is_sync = false;
+    FutureOr<core::int>? :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 {
+        #L7:
+        {
+          throw "FutureOr<int>";
+        }
+        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        return;
+      }
+      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.call();
+    :is_sync = true;
+    return :async_future;
+  }
+  method throwInt() → core::int {
+    throw "int";
+  }
+  method throwFutureInt() → asy::Future<core::int> /* originally async */ {
+    final asy::_Future<core::int> :async_future = new asy::_Future::•<core::int>();
+    core::bool* :is_sync = false;
+    FutureOr<core::int>? :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 {
+        #L8:
+        {
+          throw "Future<int>";
+        }
+        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        return;
+      }
+      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.call();
+    :is_sync = true;
+    return :async_future;
+  }
+  method throwDynamic() → dynamic {
+    throw "dynamic";
+  }
+  method throwFutureNum() → asy::Future<core::num> /* originally async */ {
+    final asy::_Future<core::num> :async_future = new asy::_Future::•<core::num>();
+    core::bool* :is_sync = false;
+    FutureOr<core::num>? :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 {
+        #L9:
+        {
+          throw "Future<num>";
+        }
+        asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+        return;
+      }
+      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.call();
+    :is_sync = true;
+    return :async_future;
+  }
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/return_from_async_lib.dart b/pkg/front_end/testcases/nnbd_mixed/return_from_async_lib.dart
new file mode 100644
index 0000000..0e4cbb7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/return_from_async_lib.dart
@@ -0,0 +1,28 @@
+// 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 'dart:async';
+import 'return_from_async.dart';
+
+class Subclass implements Class {
+  FutureOr<int> throwFutureOrInt() async {
+    throw 'FutureOr<int>';
+  }
+
+  int throwInt() {
+    throw 'int';
+  }
+
+  Future<int> throwFutureInt() async {
+    throw 'Future<int>';
+  }
+
+  dynamic throwDynamic() {
+    throw 'dynamic';
+  }
+
+  Future<num> throwFutureNum() async {
+    throw 'Future<num>';
+  }
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_access/main.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/super_access/main.dart.weak.expect
index e157b1f..ca14755 100644
--- a/pkg/front_end/testcases/nnbd_mixed/super_access/main.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/super_access/main.dart.weak.expect
@@ -26,20 +26,24 @@
   synthetic constructor •() → self::_Class&Object&Mixin1&Mixin2<self::_Class&Object&Mixin1&Mixin2::T*>*
     : super self::_Class&Object&Mixin1::•()
     ;
-  abstract member-signature set field((dynamic) →* core::Type* value) → void; -> mai::Mixin2::field
-  abstract member-signature get field() → (dynamic) →* core::Type*; -> mai::Mixin2::field
-  abstract member-signature method method1() → (dynamic) →* core::Type*; -> mai::Mixin2::method1
-  abstract member-signature method method2((dynamic) →* core::Type* t) → void; -> mai::Mixin2::method2
+  mixin-super-stub get field() → (dynamic) →* core::Type*
+    return super.{mai::Mixin2::field};
+  mixin-super-stub set field((dynamic) →* core::Type* value) → void
+    return super.{mai::Mixin2::field} = value;
+  mixin-super-stub method method1() → (dynamic) →* core::Type*
+    return super.{mai::Mixin2::method1}();
+  mixin-super-stub method method2((dynamic) →* core::Type* t) → void
+    return super.{mai::Mixin2::method2}(t);
 }
 class Class<T extends core::Object* = dynamic> extends self::_Class&Object&Mixin1&Mixin2<self::Class::T*> {
   synthetic constructor •() → self::Class<self::Class::T*>*
     : super self::_Class&Object&Mixin1&Mixin2::•()
     ;
-  set field((dynamic) →* core::Type value) → void {
-    super.{mai::Mixin2::field};
+  set field((dynamic) →* core::Type* value) → void {
+    super.{self::_Class&Object&Mixin1&Mixin2::field};
     super.{self::_Class&Object&Mixin1&Mixin2::field} = value;
-    super.{mai::Mixin2::method1}();
-    super.{mai::Mixin2::method2}(null);
+    super.{self::_Class&Object&Mixin1&Mixin2::method1}();
+    super.{self::_Class&Object&Mixin1&Mixin2::method2}(null);
   }
 }
 static method main() → dynamic {}
@@ -55,8 +59,10 @@
   synthetic constructor •() → mai::Mixin1<mai::Mixin1::T*>*
     : super core::Object::•()
     ;
-  abstract member-signature set field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
   abstract member-signature get field() → (core::Object*) →* core::Type*; -> mai2::Interface::field
+  abstract member-signature set field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
+  abstract member-signature method method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
+  abstract member-signature method method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
   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
@@ -67,17 +73,15 @@
   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
-  abstract member-signature method method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
-  abstract member-signature method method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
 }
 abstract class Mixin2<T extends core::Object* = dynamic> extends core::Object implements mai2::Interface<mai2::Value<dynamic>*, core::Object*> {
-  field (dynamic) →* core::Type field = null;
+  field (dynamic) →* core::Type* field = null;
   synthetic constructor •() → mai::Mixin2<mai::Mixin2::T*>*
     : super core::Object::•()
     ;
-  method method1() → (dynamic) →* core::Type
+  method method1() → (dynamic) →* core::Type*
     return null;
-  method method2((dynamic) →* core::Type t) → void {}
+  method method2((dynamic) →* core::Type* t) → void {}
   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
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_access/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/super_access/main.dart.weak.transformed.expect
index cf90354..a0b7a6c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/super_access/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/super_access/main.dart.weak.transformed.expect
@@ -21,19 +21,19 @@
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ toString() → core::String*; -> core::Object::toString
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get /* from org-dartlang-testcase:///main_lib1.dart */ runtimeType() → core::Type*; -> core::Object::runtimeType
-  abstract member-signature set /* from org-dartlang-testcase:///main_lib1.dart */ field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
   abstract member-signature get /* from org-dartlang-testcase:///main_lib1.dart */ field() → (core::Object*) →* core::Type*; -> mai2::Interface::field
+  abstract member-signature set /* from org-dartlang-testcase:///main_lib1.dart */ field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
 }
 abstract class _Class&Object&Mixin1&Mixin2<T extends core::Object* = dynamic> extends self::_Class&Object&Mixin1<self::_Class&Object&Mixin1&Mixin2::T*> implements mai::Mixin2<self::_Class&Object&Mixin1&Mixin2::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
-  field (dynamic) →* core::Type field = null /* from org-dartlang-testcase:///main_lib1.dart */;
+  field (dynamic) →* core::Type* field = null /* from org-dartlang-testcase:///main_lib1.dart */;
   synthetic constructor •() → self::_Class&Object&Mixin1&Mixin2<self::_Class&Object&Mixin1&Mixin2::T*>*
     : super self::_Class&Object&Mixin1::•()
     ;
-  method /* from org-dartlang-testcase:///main_lib1.dart */ method1() → (dynamic) →* core::Type
+  method /* from org-dartlang-testcase:///main_lib1.dart */ method1() → (dynamic) →* core::Type*
     return null;
-  method /* from org-dartlang-testcase:///main_lib1.dart */ method2((dynamic) →* core::Type t) → void {}
+  method /* from org-dartlang-testcase:///main_lib1.dart */ method2((dynamic) →* core::Type* t) → void {}
   abstract member-signature get /* from org-dartlang-testcase:///main_lib1.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -49,11 +49,11 @@
   synthetic constructor •() → self::Class<self::Class::T*>*
     : super self::_Class&Object&Mixin1&Mixin2::•()
     ;
-  set field((dynamic) →* core::Type value) → void {
-    super.{mai::Mixin2::field};
+  set field((dynamic) →* core::Type* value) → void {
+    super.{self::_Class&Object&Mixin1&Mixin2::field};
     super.{self::_Class&Object&Mixin1&Mixin2::field} = value;
-    super.{mai::Mixin2::method1}();
-    super.{mai::Mixin2::method2}(null);
+    super.{self::_Class&Object&Mixin1&Mixin2::method1}();
+    super.{self::_Class&Object&Mixin1&Mixin2::method2}(null);
   }
 }
 static method main() → dynamic {}
@@ -69,8 +69,10 @@
   synthetic constructor •() → mai::Mixin1<mai::Mixin1::T*>*
     : super core::Object::•()
     ;
-  abstract member-signature set field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
   abstract member-signature get field() → (core::Object*) →* core::Type*; -> mai2::Interface::field
+  abstract member-signature set field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
+  abstract member-signature method method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
+  abstract member-signature method method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
   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
@@ -81,17 +83,15 @@
   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
-  abstract member-signature method method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
-  abstract member-signature method method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
 }
 abstract class Mixin2<T extends core::Object* = dynamic> extends core::Object implements mai2::Interface<mai2::Value<dynamic>*, core::Object*> {
-  field (dynamic) →* core::Type field = null;
+  field (dynamic) →* core::Type* field = null;
   synthetic constructor •() → mai::Mixin2<mai::Mixin2::T*>*
     : super core::Object::•()
     ;
-  method method1() → (dynamic) →* core::Type
+  method method1() → (dynamic) →* core::Type*
     return null;
-  method method2((dynamic) →* core::Type t) → void {}
+  method method2((dynamic) →* core::Type* t) → void {}
   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
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_access/main.no_link.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/super_access/main.no_link.dart.weak.expect
index e157b1f..ca14755 100644
--- a/pkg/front_end/testcases/nnbd_mixed/super_access/main.no_link.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/super_access/main.no_link.dart.weak.expect
@@ -26,20 +26,24 @@
   synthetic constructor •() → self::_Class&Object&Mixin1&Mixin2<self::_Class&Object&Mixin1&Mixin2::T*>*
     : super self::_Class&Object&Mixin1::•()
     ;
-  abstract member-signature set field((dynamic) →* core::Type* value) → void; -> mai::Mixin2::field
-  abstract member-signature get field() → (dynamic) →* core::Type*; -> mai::Mixin2::field
-  abstract member-signature method method1() → (dynamic) →* core::Type*; -> mai::Mixin2::method1
-  abstract member-signature method method2((dynamic) →* core::Type* t) → void; -> mai::Mixin2::method2
+  mixin-super-stub get field() → (dynamic) →* core::Type*
+    return super.{mai::Mixin2::field};
+  mixin-super-stub set field((dynamic) →* core::Type* value) → void
+    return super.{mai::Mixin2::field} = value;
+  mixin-super-stub method method1() → (dynamic) →* core::Type*
+    return super.{mai::Mixin2::method1}();
+  mixin-super-stub method method2((dynamic) →* core::Type* t) → void
+    return super.{mai::Mixin2::method2}(t);
 }
 class Class<T extends core::Object* = dynamic> extends self::_Class&Object&Mixin1&Mixin2<self::Class::T*> {
   synthetic constructor •() → self::Class<self::Class::T*>*
     : super self::_Class&Object&Mixin1&Mixin2::•()
     ;
-  set field((dynamic) →* core::Type value) → void {
-    super.{mai::Mixin2::field};
+  set field((dynamic) →* core::Type* value) → void {
+    super.{self::_Class&Object&Mixin1&Mixin2::field};
     super.{self::_Class&Object&Mixin1&Mixin2::field} = value;
-    super.{mai::Mixin2::method1}();
-    super.{mai::Mixin2::method2}(null);
+    super.{self::_Class&Object&Mixin1&Mixin2::method1}();
+    super.{self::_Class&Object&Mixin1&Mixin2::method2}(null);
   }
 }
 static method main() → dynamic {}
@@ -55,8 +59,10 @@
   synthetic constructor •() → mai::Mixin1<mai::Mixin1::T*>*
     : super core::Object::•()
     ;
-  abstract member-signature set field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
   abstract member-signature get field() → (core::Object*) →* core::Type*; -> mai2::Interface::field
+  abstract member-signature set field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
+  abstract member-signature method method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
+  abstract member-signature method method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
   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
@@ -67,17 +73,15 @@
   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
-  abstract member-signature method method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
-  abstract member-signature method method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
 }
 abstract class Mixin2<T extends core::Object* = dynamic> extends core::Object implements mai2::Interface<mai2::Value<dynamic>*, core::Object*> {
-  field (dynamic) →* core::Type field = null;
+  field (dynamic) →* core::Type* field = null;
   synthetic constructor •() → mai::Mixin2<mai::Mixin2::T*>*
     : super core::Object::•()
     ;
-  method method1() → (dynamic) →* core::Type
+  method method1() → (dynamic) →* core::Type*
     return null;
-  method method2((dynamic) →* core::Type t) → void {}
+  method method2((dynamic) →* core::Type* t) → void {}
   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
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_access/main.no_link.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/super_access/main.no_link.dart.weak.transformed.expect
index cf90354..a0b7a6c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/super_access/main.no_link.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/super_access/main.no_link.dart.weak.transformed.expect
@@ -21,19 +21,19 @@
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ toString() → core::String*; -> core::Object::toString
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get /* from org-dartlang-testcase:///main_lib1.dart */ runtimeType() → core::Type*; -> core::Object::runtimeType
-  abstract member-signature set /* from org-dartlang-testcase:///main_lib1.dart */ field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
   abstract member-signature get /* from org-dartlang-testcase:///main_lib1.dart */ field() → (core::Object*) →* core::Type*; -> mai2::Interface::field
+  abstract member-signature set /* from org-dartlang-testcase:///main_lib1.dart */ field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
 }
 abstract class _Class&Object&Mixin1&Mixin2<T extends core::Object* = dynamic> extends self::_Class&Object&Mixin1<self::_Class&Object&Mixin1&Mixin2::T*> implements mai::Mixin2<self::_Class&Object&Mixin1&Mixin2::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
-  field (dynamic) →* core::Type field = null /* from org-dartlang-testcase:///main_lib1.dart */;
+  field (dynamic) →* core::Type* field = null /* from org-dartlang-testcase:///main_lib1.dart */;
   synthetic constructor •() → self::_Class&Object&Mixin1&Mixin2<self::_Class&Object&Mixin1&Mixin2::T*>*
     : super self::_Class&Object&Mixin1::•()
     ;
-  method /* from org-dartlang-testcase:///main_lib1.dart */ method1() → (dynamic) →* core::Type
+  method /* from org-dartlang-testcase:///main_lib1.dart */ method1() → (dynamic) →* core::Type*
     return null;
-  method /* from org-dartlang-testcase:///main_lib1.dart */ method2((dynamic) →* core::Type t) → void {}
+  method /* from org-dartlang-testcase:///main_lib1.dart */ method2((dynamic) →* core::Type* t) → void {}
   abstract member-signature get /* from org-dartlang-testcase:///main_lib1.dart */ _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method /* from org-dartlang-testcase:///main_lib1.dart */ _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -49,11 +49,11 @@
   synthetic constructor •() → self::Class<self::Class::T*>*
     : super self::_Class&Object&Mixin1&Mixin2::•()
     ;
-  set field((dynamic) →* core::Type value) → void {
-    super.{mai::Mixin2::field};
+  set field((dynamic) →* core::Type* value) → void {
+    super.{self::_Class&Object&Mixin1&Mixin2::field};
     super.{self::_Class&Object&Mixin1&Mixin2::field} = value;
-    super.{mai::Mixin2::method1}();
-    super.{mai::Mixin2::method2}(null);
+    super.{self::_Class&Object&Mixin1&Mixin2::method1}();
+    super.{self::_Class&Object&Mixin1&Mixin2::method2}(null);
   }
 }
 static method main() → dynamic {}
@@ -69,8 +69,10 @@
   synthetic constructor •() → mai::Mixin1<mai::Mixin1::T*>*
     : super core::Object::•()
     ;
-  abstract member-signature set field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
   abstract member-signature get field() → (core::Object*) →* core::Type*; -> mai2::Interface::field
+  abstract member-signature set field((core::Object*) →* core::Type* value) → void; -> mai2::Interface::field
+  abstract member-signature method method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
+  abstract member-signature method method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
   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
@@ -81,17 +83,15 @@
   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
-  abstract member-signature method method1() → (core::Object*) →* core::Type*; -> mai2::Interface::method1
-  abstract member-signature method method2((core::Object*) →* core::Type* t) → void; -> mai2::Interface::method2
 }
 abstract class Mixin2<T extends core::Object* = dynamic> extends core::Object implements mai2::Interface<mai2::Value<dynamic>*, core::Object*> {
-  field (dynamic) →* core::Type field = null;
+  field (dynamic) →* core::Type* field = null;
   synthetic constructor •() → mai::Mixin2<mai::Mixin2::T*>*
     : super core::Object::•()
     ;
-  method method1() → (dynamic) →* core::Type
+  method method1() → (dynamic) →* core::Type*
     return null;
-  method method2((dynamic) →* core::Type t) → void {}
+  method method2((dynamic) →* core::Type* t) → void {}
   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
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart
new file mode 100644
index 0000000..8ae24ae
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.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.
+
+// @dart=2.9
+
+import 'super_set_from_opt_in_lib.dart';
+
+abstract class Class extends SuperClass {
+  // This will have a member signature for `property=` that should _not_ be
+  // the target of `super.property = value` below.
+}
+
+class SubClass extends Class {
+  @override
+  set property(Object value) {
+    super.property = value;
+  }
+}
+
+main() {
+  new SubClass().property = null;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.textual_outline.expect
new file mode 100644
index 0000000..22e1969
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+// @dart = 2.9
+import 'super_set_from_opt_in_lib.dart';
+
+abstract class Class extends SuperClass {}
+
+class SubClass extends Class {
+  @override
+  set property(Object value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..22e1969
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+// @dart = 2.9
+import 'super_set_from_opt_in_lib.dart';
+
+abstract class Class extends SuperClass {}
+
+class SubClass extends Class {
+  @override
+  set property(Object value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..c317528
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.weak.expect
@@ -0,0 +1,52 @@
+library;
+import self as self;
+import "super_set_from_opt_in_lib.dart" as sup;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///super_set_from_opt_in_lib.dart";
+
+abstract class Class extends sup::SuperClass<dynamic> {
+  synthetic constructor •() → self::Class*
+    : super sup::SuperClass::•()
+    ;
+  abstract member-signature get property() → core::Object*; -> sup::SuperClass::property
+  abstract member-signature set property(core::Object* value) → void; -> sup::SuperClass::property
+  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
+}
+class SubClass extends self::Class {
+  synthetic constructor •() → self::SubClass*
+    : super self::Class::•()
+    ;
+  @#C1
+  set property(core::Object* value) → void {
+    super.{sup::SuperClass::property} = value;
+  }
+}
+static method main() → dynamic {
+  new self::SubClass::•().{self::SubClass::property} = null;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sup;
+import "dart:core" as core;
+
+abstract class SuperClass<T extends core::Object? = dynamic> extends core::Object {
+  @#C1
+  field core::Object? property = null;
+  synthetic constructor •() → sup::SuperClass<sup::SuperClass::T%>
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = core::_Override {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..c317528
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in.dart.weak.transformed.expect
@@ -0,0 +1,52 @@
+library;
+import self as self;
+import "super_set_from_opt_in_lib.dart" as sup;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///super_set_from_opt_in_lib.dart";
+
+abstract class Class extends sup::SuperClass<dynamic> {
+  synthetic constructor •() → self::Class*
+    : super sup::SuperClass::•()
+    ;
+  abstract member-signature get property() → core::Object*; -> sup::SuperClass::property
+  abstract member-signature set property(core::Object* value) → void; -> sup::SuperClass::property
+  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
+}
+class SubClass extends self::Class {
+  synthetic constructor •() → self::SubClass*
+    : super self::Class::•()
+    ;
+  @#C1
+  set property(core::Object* value) → void {
+    super.{sup::SuperClass::property} = value;
+  }
+}
+static method main() → dynamic {
+  new self::SubClass::•().{self::SubClass::property} = null;
+}
+
+library /*isNonNullableByDefault*/;
+import self as sup;
+import "dart:core" as core;
+
+abstract class SuperClass<T extends core::Object? = dynamic> extends core::Object {
+  @#C1
+  field core::Object? property = null;
+  synthetic constructor •() → sup::SuperClass<sup::SuperClass::T%>
+    : super core::Object::•()
+    ;
+}
+
+constants  {
+  #C1 = core::_Override {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in_lib.dart
new file mode 100644
index 0000000..8e111d9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/super_set_from_opt_in_lib.dart
@@ -0,0 +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.
+
+abstract class SuperClass<T> {
+  @override
+  Object? property;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.expect
index 95d0805..bebc221 100644
--- a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.expect
@@ -6,9 +6,9 @@
 
 import "org-dartlang-testcase:///typedef_from_opt_in_lib.dart";
 
-static method method1() → (typ::Request) →* FutureOr<typ::Response>
+static method method1() → (typ::Request*) →* FutureOr<typ::Response*>*
   return (typ::Request* r) → asy::Future<typ::Response*>* async => new typ::Response::•();
-static method method2() → (core::int?) →* core::int
+static method method2() → (core::int*) →* core::int*
   return (core::int* r) → core::int* => 0;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
index 504f220..db78f69 100644
--- a/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/typedef_from_opt_in.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 
 import "org-dartlang-testcase:///typedef_from_opt_in_lib.dart";
 
-static method method1() → (typ::Request) →* FutureOr<typ::Response>
+static method method1() → (typ::Request*) →* FutureOr<typ::Response*>*
   return (typ::Request* r) → asy::Future<typ::Response*>* /* originally async */ {
     final asy::_Future<typ::Response*>* :async_future = new asy::_Future::•<typ::Response*>();
     core::bool* :is_sync = false;
@@ -34,7 +34,7 @@
     :is_sync = true;
     return :async_future;
   };
-static method method2() → (core::int?) →* core::int
+static method method2() → (core::int*) →* core::int*
   return (core::int* r) → core::int* => 0;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect
index 50ce9f2..7298d03 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect
@@ -1,45 +1,60 @@
 // @dart = 2.8
 import 'unsound_checks_lib.dart';
+
 isNullOptOut1(int i) => i == null;
 isNotNullOptOut1(int i) => i != null;
 isNullOptOut2(int i) => null == i;
 isNotNullOptOut2(int i) => null != i;
 ifNullOptOut(int i) => i ?? 42;
+
 class OptOutClass1 {}
-extension OptOutExtension ;
-on OptOutClass1 (){}
+
+extension OptOutExtension on OptOutClass1 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
 extensionIfNullOptOut1(int i) => OptOutExtension(new OptOutClass1())[i] ??= 42;
 extensionIfNullOptOut1ForEffect(int i) {}
 extensionIfNullOptOut2(int i) => new OptOutClass1()[i] ??= 42;
 extensionIfNullOptOut2ForEffect(int i) {}
+
 class OptOutClass2 {
   int operator [](int index) => index;
   void operator []=(int index, int value) {}
 }
+
 ifNullIndexSetOptOut(int i) => new OptOutClass2()[i] ??= 42;
 ifNullIndexSetOptOutForEffect(int i) {}
+
 class OptOutClass3 {
   int field;
   OptOutClass3(this.field);
 }
+
 ifNullPropertySetOptOut(int i) => new OptOutClass3(i).field ??= 42;
 ifNullPropertySetOptOutForEffect(int i) {}
 ifNullSetOptOut(int i) => i ??= 42;
 ifNullSetOptOutForEffect(int i) {}
+
 class OptOutSuperClass4 {
   int operator [](int index) => index;
   void operator []=(int index, int value) {}
 }
+
 class OptOutClass4 extends OptOutSuperClass4 {
   method(int i) => super[i] ??= 42;
   methodForEffect(int i) {}
 }
+
 ifNullSuperIndexSetOptOut(int i) => new OptOutClass4().method(i);
 ifNullSuperIndexSetOptOutForEffect(int i) {}
+
 class OptOutClass5 {
   int field;
   OptOutClass5(this.field);
 }
+
 nullAwareIfNullSetOptOut(int i) {}
 nullAwareIfNullSetOptOutForEffect(int i) {}
 isTestOptOut(int i) => i is int;
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f86f53b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline_modelled.expect
@@ -0,0 +1,60 @@
+// @dart = 2.8
+import 'unsound_checks_lib.dart';
+
+class OptOutClass1 {}
+
+class OptOutClass2 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+class OptOutClass3 {
+  OptOutClass3(this.field);
+  int field;
+}
+
+class OptOutClass4 extends OptOutSuperClass4 {
+  method(int i) => super[i] ??= 42;
+  methodForEffect(int i) {}
+}
+
+class OptOutClass5 {
+  OptOutClass5(this.field);
+  int field;
+}
+
+class OptOutSuperClass4 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+expect(expected, actual) {}
+
+extension OptOutExtension on OptOutClass1 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+extensionIfNullOptOut1(int i) => OptOutExtension(new OptOutClass1())[i] ??= 42;
+extensionIfNullOptOut1ForEffect(int i) {}
+extensionIfNullOptOut2(int i) => new OptOutClass1()[i] ??= 42;
+extensionIfNullOptOut2ForEffect(int i) {}
+ifNullIndexSetOptOut(int i) => new OptOutClass2()[i] ??= 42;
+ifNullIndexSetOptOutForEffect(int i) {}
+ifNullOptOut(int i) => i ?? 42;
+ifNullPropertySetOptOut(int i) => new OptOutClass3(i).field ??= 42;
+ifNullPropertySetOptOutForEffect(int i) {}
+ifNullSetOptOut(int i) => i ??= 42;
+ifNullSetOptOutForEffect(int i) {}
+ifNullSuperIndexSetOptOut(int i) => new OptOutClass4().method(i);
+ifNullSuperIndexSetOptOutForEffect(int i) {}
+isNotNullOptOut1(int i) => i != null;
+isNotNullOptOut2(int i) => null != i;
+isNotTestOptOut(int i) => i is! int;
+isNullOptOut1(int i) => i == null;
+isNullOptOut2(int i) => null == i;
+isTestOptOut(int i) => i is int;
+main() {}
+nullAwareIfNullSetOptOut(int i) {}
+nullAwareIfNullSetOptOutForEffect(int i) {}
+throws(void f(), [bool Function(Object) testException]) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
index 0f9dd17..a7fa278 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
@@ -619,3 +619,9 @@
   #C7 = null
   #C8 = <uns::E*>[#C3, #C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unsound_checks_lib.dart:
+- E. (from org-dartlang-testcase:///unsound_checks_lib.dart:145:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect
index 54fdabb..7656f90 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect
@@ -250,8 +250,8 @@
   uns::unnecessaryNullCheck(() → Null => null);
   self::expect(0, uns::unnecessaryIfNull(() → core::int* => 0, () → core::int* => 42));
   self::expect(42, uns::unnecessaryIfNull(() → Null => null, () → core::int* => 42));
-  uns::unnecessaryIfNullAssign(<core::int*>[0], () → core::int* => 42);
-  uns::unnecessaryIfNullAssign(<core::int*>[null], () → core::int* => 42);
+  uns::unnecessaryIfNullAssign(core::_GrowableList::_literal1<core::int*>(0), () → core::int* => 42);
+  uns::unnecessaryIfNullAssign(core::_GrowableList::_literal1<core::int*>(null), () → core::int* => 42);
   uns::unnecessaryNullAwareAccess(() → core::int* => 0);
   uns::unnecessaryNullAwareAccess(() → Null => null);
   self::throws(() → dynamic => uns::callReturningNever(() → <BottomType>=> throw "foo"), (core::Object* e) → core::bool* => e.{core::Object::==}("foo"));
@@ -640,3 +640,9 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:134:5 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:134:5 -> IntConstant(0)
 Extra constant evaluation: evaluated: 719, effectively constant: 18
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unsound_checks_lib.dart:
+- E. (from org-dartlang-testcase:///unsound_checks_lib.dart:145:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.strong.transformed.expect
index 99db49e..168474b 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.strong.transformed.expect
@@ -36,7 +36,7 @@
   no-such-method-forwarder get foo() → core::int*
     return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set foo(core::int* value) → void
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 class B extends self::A {
   synthetic constructor •() → self::B*
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
index 26d73b4..7468edb 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
@@ -40,6 +40,8 @@
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::B::noSuchMethod}(i);
   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
@@ -71,4 +73,4 @@
 Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> SymbolConstant(#foo=)
 Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> ListConstant(const <Type*>[])
 Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
-Extra constant evaluation: evaluated: 19, effectively constant: 7
+Extra constant evaluation: evaluated: 21, effectively constant: 7
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
index e3b94fb..ffcf974 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
@@ -44,6 +44,8 @@
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::B::noSuchMethod}(i);
   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
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
index 3433736..4609d1a 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
@@ -38,12 +38,16 @@
   no-such-method-forwarder get foo() → core::int*
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set foo(core::int* value) → void
-    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 abstract class _C&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
+  method noSuchMethod(core::Invocation* i) → dynamic {
+    self::count = self::count.{core::num::+}(1);
+    return null;
+  }
   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
@@ -53,10 +57,6 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-  method noSuchMethod(core::Invocation* i) → dynamic {
-    self::count = self::count.{core::num::+}(1);
-    return null;
-  }
 }
 class C extends self::_C&Object&B {
   synthetic constructor •() → self::C*
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.strong.transformed.expect
index 1d02227..3640888 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.strong.transformed.expect
@@ -41,7 +41,7 @@
     : super self::B::•()
     ;
   no-such-method-forwarder set foo(core::int* value) → void
-    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 abstract class D extends core::Object implements self::A {
   synthetic constructor •() → self::D*
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.strong.transformed.expect
index 94eb66f..ba39cc0 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
     : super core::Object::•()
     ;
   method noSuchMethod(core::Invocation* i) → dynamic
-    return <dynamic>[];
+    return core::_GrowableList::•<dynamic>(0);
   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
@@ -36,7 +36,7 @@
   no-such-method-forwarder get foo() → core::List<core::int*>*
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::List<core::int*>*;
   no-such-method-forwarder set foo(generic-covariant-impl core::List<core::int*>* value) → void
-    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method expectTypeError(() →* dynamic callback) → void {
   try {
@@ -49,7 +49,7 @@
 static method main() → dynamic {
   self::B* b = new self::B::•();
   self::expectTypeError(() → core::List<core::int*>* => b.{self::A::foo});
-  self::expectTypeError(() → core::List<dynamic>* => (b as dynamic).foo = <dynamic>[]);
+  self::expectTypeError(() → core::List<dynamic>* => (b as dynamic).foo = core::_GrowableList::•<dynamic>(0));
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
index 29f7048..ac147ed 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
@@ -21,6 +21,7 @@
   synthetic constructor •() → self::I*
     ;
   abstract method foo() → void;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -29,7 +30,6 @@
   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
 }
 class B extends self::A implements self::I {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect
index cf46444..2182bea 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect
@@ -24,6 +24,7 @@
     : super core::Object::•()
     ;
   abstract method foo() → void;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -32,7 +33,6 @@
   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
 }
 class B extends self::A implements self::I {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect
index cf46444..2182bea 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect
@@ -24,6 +24,7 @@
     : super core::Object::•()
     ;
   abstract method foo() → void;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -32,7 +33,6 @@
   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
 }
 class B extends self::A implements self::I {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.strong.transformed.expect
index 3abbfff..ca335bc 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.strong.transformed.expect
@@ -7,9 +7,9 @@
     : super core::Object::•()
     ;
   no-such-method-forwarder set push(core::int* x) → void
-    return this.{self::Base::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Base::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(x)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder set float(covariant core::int* x) → void
-    return this.{self::Base::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Base::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(x)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   method noSuchMethod(core::Invocation* i) → dynamic
     return core::print("${this.{self::Base::runtimeType}}: ${i.{core::Invocation::positionalArguments}.{core::List::[]}(0)}");
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -32,12 +32,12 @@
     : super self::Base::•()
     ;
   no-such-method-forwarder set push(core::num* x) → void
-    return this.{self::Base::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Base::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(x)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder set float(covariant core::num* x) → void
-    return this.{self::Base::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Base::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(x)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {
-  core::List<self::Base*>* list = <self::Base*>[new self::Me::•(), new self::You::•()];
+  core::List<self::Base*>* list = core::_GrowableList::_literal2<self::Base*>(new self::Me::•(), new self::You::•());
   {
     core::Iterator<self::Base*>* :sync-for-iterator = list.{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.outline.expect
index fd257f0..5a2927f 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.outline.expect
@@ -56,6 +56,7 @@
   synthetic constructor •() → self::HungryCat*
     ;
   abstract method eatFood(core::String* food, {core::double* amount, core::double* yetAnother}) → core::bool*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -64,7 +65,6 @@
   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 method main() → dynamic
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.strong.expect
index 3979bfc..b32f8e5 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.strong.expect
@@ -64,6 +64,7 @@
     : super core::Object::•()
     ;
   abstract method eatFood(core::String* food, {core::double* amount = #C5, core::double* yetAnother = #C5}) → core::bool*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -72,7 +73,6 @@
   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 method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.strong.transformed.expect
index 3979bfc..d5a49ee 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.strong.transformed.expect
@@ -37,7 +37,7 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
   no-such-method-forwarder method eatFood(core::String* food) → core::bool*
-    return this.{self::MockCat::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[food]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
+    return this.{self::MockCat::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(food)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
 }
 class MockCat2 extends self::MockCat {
   synthetic constructor •() → self::MockCat2*
@@ -50,20 +50,21 @@
     : super self::MockCat2::•()
     ;
   no-such-method-forwarder method eatFood(core::String* food, {core::double* amount = #C5}) → core::bool*
-    return this.{self::MockCat2::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[food]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C6: amount}))) as{TypeError,ForDynamic} core::bool*;
+    return this.{self::MockCat2::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(food)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C6: amount}))) as{TypeError,ForDynamic} core::bool*;
 }
 class MockCat4 extends self::MockCat2 implements self::HungryCat {
   synthetic constructor •() → self::MockCat4*
     : super self::MockCat2::•()
     ;
   no-such-method-forwarder method eatFood(core::String* food, {core::double* amount = #C5, core::double* yetAnother = #C5}) → core::bool*
-    return this.{self::MockCat2::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[food]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C6: amount, #C7: yetAnother}))) as{TypeError,ForDynamic} core::bool*;
+    return this.{self::MockCat2::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(food)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C6: amount, #C7: yetAnother}))) as{TypeError,ForDynamic} core::bool*;
 }
 abstract class HungryCat extends core::Object {
   synthetic constructor •() → self::HungryCat*
     : super core::Object::•()
     ;
   abstract method eatFood(core::String* food, {core::double* amount = #C5, core::double* yetAnother = #C5}) → core::bool*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -72,7 +73,6 @@
   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 method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
index be653d9..0ad0983 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
@@ -54,6 +54,8 @@
   synthetic constructor •() → self::_C&A&B*
     : super self::A::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* _) → dynamic
+    return super.{self::B::noSuchMethod}(_);
 }
 class C extends self::_C&A&B {
   synthetic constructor •() → self::C*
@@ -68,4 +70,4 @@
 Evaluated: ListLiteral @ org-dartlang-testcase:///concrete_method_over_forwarder_in_mixin_application.dart:10:3 -> ListConstant(const <Type*>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///concrete_method_over_forwarder_in_mixin_application.dart:10:3 -> ListConstant(const <dynamic>[])
 Evaluated: MapLiteral @ org-dartlang-testcase:///concrete_method_over_forwarder_in_mixin_application.dart:10:3 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
-Extra constant evaluation: evaluated: 9, effectively constant: 4
+Extra constant evaluation: evaluated: 11, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.expect
index ac32c35..c38133a 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.strong.expect
@@ -56,6 +56,8 @@
   synthetic constructor •() → self::_C&A&B*
     : super self::A::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* _) → dynamic
+    return super.{self::B::noSuchMethod}(_);
 }
 class C extends self::_C&A&B {
   synthetic constructor •() → self::C*
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.transformed.expect
index 72909b5..a5a0b39 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.strong.transformed.expect
@@ -35,7 +35,7 @@
   no-such-method-forwarder method foo({core::String* bar = #C4}) → core::String*
     return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C6, #C7, core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C2: bar}))) as{TypeError,ForDynamic} core::String*;
   no-such-method-forwarder method hest([core::int* fisk = #C5]) → core::int*
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C3, 0, #C6, core::List::unmodifiable<dynamic>(<dynamic>[fisk]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C8))) as{TypeError,ForDynamic} core::int*;
+    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C3, 0, #C6, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(fisk)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C8))) as{TypeError,ForDynamic} core::int*;
 }
 static method main() → dynamic {
   self::B* b = new self::B::•();
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation.dart.strong.transformed.expect
index d0e5a4c..410396b 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation.dart.strong.transformed.expect
@@ -40,9 +40,9 @@
   no-such-method-forwarder get bar() → core::int*
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder method baz(core::int* x, {core::String* y = #C1, core::double* z = #C1}) → void
-    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C7: y, #C8: z})));
+    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(x)), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C7: y, #C8: z})));
   no-such-method-forwarder set foo(core::int* value) → void
-    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+    return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
 }
 class C extends self::B {
   synthetic constructor •() → self::C*
@@ -70,9 +70,9 @@
   no-such-method-forwarder method /* from org-dartlang-testcase:///forwarder_propagation_lib.dart */ _privateMethod() → void
     return this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
   no-such-method-forwarder set /* from org-dartlang-testcase:///forwarder_propagation_lib.dart */ _privateSetter(core::int* value) → void
-    return this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+    return this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
   no-such-method-forwarder set /* from org-dartlang-testcase:///forwarder_propagation_lib.dart */ _privateField(core::int* value) → void
-    return this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+    return this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
 }
 class F extends self::E {
   synthetic constructor •() → self::F*
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
index e03bb94..9246c58 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
@@ -38,6 +38,8 @@
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::A::noSuchMethod}(i);
   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
@@ -52,7 +54,7 @@
   synthetic constructor •() → self::B*
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
+    return this.{self::_B&Object&A::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
 static method main() → dynamic
   ;
@@ -67,4 +69,4 @@
 Evaluated: ListLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> ListConstant(const <Type*>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> ListConstant(const <dynamic>[])
 Evaluated: MapLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
-Extra constant evaluation: evaluated: 16, effectively constant: 8
+Extra constant evaluation: evaluated: 18, effectively constant: 8
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
index ef3c7ca..d4f16a5 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
@@ -40,6 +40,8 @@
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::A::noSuchMethod}(i);
   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
@@ -55,7 +57,7 @@
     : super self::_B&Object&A::•()
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::_B&Object&A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
index 248fbe4..3a32356 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
@@ -40,6 +40,8 @@
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
+  method noSuchMethod(core::Invocation* i) → dynamic
+    return null;
   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
@@ -49,15 +51,13 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-  method noSuchMethod(core::Invocation* i) → dynamic
-    return null;
 }
 class B extends self::_B&Object&A {
   synthetic constructor •() → self::B*
     : super self::_B&Object&A::•()
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::_B&Object&A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
index 513d138..6986170 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
@@ -22,6 +22,7 @@
     ;
   method foo() → void
     ;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -30,7 +31,6 @@
   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
 }
 class B extends self::A implements self::I {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect
index 4351d37..acee4b7 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect
@@ -24,6 +24,7 @@
     : super core::Object::•()
     ;
   method foo() → void {}
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -32,7 +33,6 @@
   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
 }
 class B extends self::A implements self::I {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect
index 4351d37..acee4b7 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect
@@ -24,6 +24,7 @@
     : super core::Object::•()
     ;
   method foo() → void {}
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -32,7 +33,6 @@
   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
 }
 class B extends self::A implements self::I {
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
index 6e4c566..c4af234 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
@@ -38,6 +38,8 @@
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::M::noSuchMethod}(i);
   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
@@ -52,12 +54,14 @@
   synthetic constructor •() → self::A*
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
+    return this.{self::_A&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
 abstract class _B&Object&M = core::Object with self::M /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::M::noSuchMethod}(i);
   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
@@ -72,7 +76,7 @@
   synthetic constructor •() → self::B*
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
+    return this.{self::_B&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
 static method main() → dynamic
   ;
@@ -91,4 +95,4 @@
 Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> ListConstant(const <Type*>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> ListConstant(const <dynamic>[])
 Evaluated: MapLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
-Extra constant evaluation: evaluated: 24, effectively constant: 12
+Extra constant evaluation: evaluated: 28, effectively constant: 12
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
index 7c96ad7..0f6e0f1 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
@@ -40,6 +40,8 @@
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::M::noSuchMethod}(i);
   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
@@ -55,12 +57,14 @@
     : super self::_A&Object&M::•()
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::_A&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 abstract class _B&Object&M = core::Object with self::M /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::M::noSuchMethod}(i);
   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
@@ -76,7 +80,7 @@
     : super self::_B&Object&M::•()
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::_B&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
index 80f27c9..a177218 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
@@ -40,6 +40,8 @@
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
+  method noSuchMethod(core::Invocation* i) → dynamic
+    return null;
   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
@@ -49,20 +51,20 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-  method noSuchMethod(core::Invocation* i) → dynamic
-    return null;
 }
 class A extends self::_A&Object&M implements self::I {
   synthetic constructor •() → self::A*
     : super self::_A&Object&M::•()
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::_A&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 abstract class _B&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
+  method noSuchMethod(core::Invocation* i) → dynamic
+    return null;
   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
@@ -72,15 +74,13 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-  method noSuchMethod(core::Invocation* i) → dynamic
-    return null;
 }
 class B extends self::_B&Object&M implements self::I {
   synthetic constructor •() → self::B*
     : super self::_B&Object&M::•()
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::_B&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/multiple_abstract_setters.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/multiple_abstract_setters.dart.strong.transformed.expect
index 297ab3b..d5f3d88 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/multiple_abstract_setters.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/multiple_abstract_setters.dart.strong.transformed.expect
@@ -74,7 +74,7 @@
   no-such-method-forwarder get bar() → Null
     return this.{self::D::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} Null;
   no-such-method-forwarder set foo(core::num* value) → void
-    return this.{self::D::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::D::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect
index 9d5a43e..0428014 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
     : super self::M::•()
     ;
   no-such-method-forwarder method call(core::String* s) → void
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[s]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(s)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
index 69a5847..1a05075 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
@@ -21,6 +21,8 @@
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::A::noSuchMethod}(i);
   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
@@ -35,7 +37,7 @@
   synthetic constructor •() → self::B*
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
+    return this.{self::_B&Object&A::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
 static method main() → dynamic
   ;
@@ -46,4 +48,4 @@
 Evaluated: ListLiteral @ org-dartlang-testcase:///nsm_mixed_in.dart:15:8 -> ListConstant(const <Type*>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///nsm_mixed_in.dart:15:8 -> ListConstant(const <dynamic>[])
 Evaluated: MapLiteral @ org-dartlang-testcase:///nsm_mixed_in.dart:15:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
-Extra constant evaluation: evaluated: 8, effectively constant: 4
+Extra constant evaluation: evaluated: 10, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
index 8a8d728..7c7b366 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
@@ -23,6 +23,8 @@
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::A::noSuchMethod}(i);
   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
@@ -38,7 +40,7 @@
     : super self::_B&Object&A::•()
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::_B&Object&A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
index afcc0f2..a38cf96 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
@@ -23,6 +23,9 @@
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
+  method noSuchMethod(core::Invocation* i) → dynamic {
+    return null;
+  }
   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
@@ -32,16 +35,13 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-  method noSuchMethod(core::Invocation* i) → dynamic {
-    return null;
-  }
 }
 class B extends self::_B&Object&A {
   synthetic constructor •() → self::B*
     : super self::_B&Object&A::•()
     ;
   no-such-method-forwarder method foo() → void
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::_B&Object&A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.outline.expect
index 6b1da0c..2d1038e 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.outline.expect
@@ -45,6 +45,7 @@
   synthetic constructor •() → pri::Fisk*
     ;
   abstract method _hest() → void;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -53,7 +54,6 @@
   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 method main() → dynamic
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.strong.expect
index 6a52850..735122a 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.strong.expect
@@ -48,6 +48,7 @@
     : super core::Object::•()
     ;
   abstract method _hest() → void;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -56,7 +57,6 @@
   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 method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.strong.transformed.expect
index 6a52850..735122a 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.strong.transformed.expect
@@ -48,6 +48,7 @@
     : super core::Object::•()
     ;
   abstract method _hest() → void;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -56,7 +57,6 @@
   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 method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.strong.transformed.expect
index b37c6af5..a110b1a 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.strong.transformed.expect
@@ -18,7 +18,7 @@
     ;
   method foo(core::int* x) → void {}
   no-such-method-forwarder set foo(core::int* x) → void
-    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 2, #C2, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(x)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   method noSuchMethod(core::Invocation* i) → dynamic
     return null;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
index e523dd2..80e949b 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
@@ -6,6 +6,7 @@
   synthetic constructor •() → self::I<self::I::T*>*
     ;
   abstract method foo() → self::I::T*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -14,7 +15,6 @@
   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
 }
 class M extends core::Object {
@@ -36,6 +36,8 @@
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::M::noSuchMethod}(i);
   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
@@ -50,7 +52,7 @@
   synthetic constructor •() → self::A*
     ;
   no-such-method-forwarder method foo() → core::int*
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} core::int*;
+    return this.{self::_A&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} core::int*;
 }
 static method main() → dynamic
   ;
@@ -61,4 +63,4 @@
 Evaluated: ListLiteral @ org-dartlang-testcase:///subst_on_forwarder.dart:10:5 -> ListConstant(const <Type*>[])
 Evaluated: ListLiteral @ org-dartlang-testcase:///subst_on_forwarder.dart:10:5 -> ListConstant(const <dynamic>[])
 Evaluated: MapLiteral @ org-dartlang-testcase:///subst_on_forwarder.dart:10:5 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
-Extra constant evaluation: evaluated: 9, effectively constant: 4
+Extra constant evaluation: evaluated: 11, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
index 353d26c..3676843 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
@@ -7,6 +7,7 @@
     : super core::Object::•()
     ;
   abstract method foo() → self::I::T*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -15,7 +16,6 @@
   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
 }
 class M extends core::Object {
@@ -39,6 +39,8 @@
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
+  mixin-super-stub method noSuchMethod(core::Invocation* i) → dynamic
+    return super.{self::M::noSuchMethod}(i);
   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
@@ -54,7 +56,7 @@
     : super self::_A&Object&M::•()
     ;
   no-such-method-forwarder method foo() → core::int*
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
+    return this.{self::_A&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
index a18e7f88..84fdbfc 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
@@ -7,6 +7,7 @@
     : super core::Object::•()
     ;
   abstract method foo() → self::I::T*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   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
@@ -15,7 +16,6 @@
   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
 }
 class M extends core::Object {
@@ -39,6 +39,9 @@
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
+  method noSuchMethod(core::Invocation* i) → dynamic {
+    return null;
+  }
   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
@@ -48,16 +51,13 @@
   abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-  method noSuchMethod(core::Invocation* i) → dynamic {
-    return null;
-  }
 }
 class A extends self::_A&Object&M implements self::I<core::int*> {
   synthetic constructor •() → self::A*
     : super self::_A&Object&M::•()
     ;
   no-such-method-forwarder method foo() → core::int*
-    return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
+    return this.{self::_A&Object&M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/none/equals.dart b/pkg/front_end/testcases/none/equals.dart
new file mode 100644
index 0000000..8a5100f
--- /dev/null
+++ b/pkg/front_end/testcases/none/equals.dart
@@ -0,0 +1,370 @@
+// 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.md file.
+
+const Object? nullValue = null;
+
+class Class<T> {
+  operator ==(covariant Class<T> other) => true;
+
+  method(o) {}
+}
+
+test<T1 extends Function, T2 extends int Function(int)>(
+    Object o,
+    Object nonNullableObject,
+    Object? nullableObject,
+    Class<String> nonNullableClass,
+    Class<String>? nullableClass,
+    dynamic dyn,
+    Never never,
+    Never? nullableNever,
+    Null nullTypedValue,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function(int) nonNullableFunctionType,
+    int Function(int)? nullableFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2) {
+  print('EqualsNull (literal null)');
+  null == null;
+  null != null;
+
+  nonNullableObject == null;
+  nonNullableObject != null;
+  null == nonNullableObject;
+  null != nonNullableObject;
+
+  nullableObject == null;
+  nullableObject != null;
+  null == nullableObject;
+  null != nullableObject;
+
+  nullableClass == null;
+  nullableClass != null;
+  null == nullableClass;
+  null != nullableClass;
+
+  nonNullableClass == null;
+  nonNullableClass != null;
+  null == nonNullableClass;
+  null != nonNullableClass;
+
+  dyn == null;
+  dyn != null;
+  null == dyn;
+  null != dyn;
+
+  never == null;
+  never != null;
+  null == never;
+  null != never;
+
+  nullableNever == null;
+  nullableNever != null;
+  null == nullableNever;
+  null != nullableNever;
+
+  nullTypedValue == null;
+  nullTypedValue != null;
+  null == nullTypedValue;
+  null != nullTypedValue;
+
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  null == nonNullableFunction;
+  null != nonNullableFunction;
+
+  nullableFunction == null;
+  nullableFunction != null;
+  null == nullableFunction;
+  null != nullableFunction;
+
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  null == nonNullableFunctionType;
+  null != nonNullableFunctionType;
+
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  null == nullableFunctionType;
+  null != nullableFunctionType;
+
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  null == nonNullableTypeVariable1;
+  null != nonNullableTypeVariable1;
+
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  null == nullableTypeVariable1;
+  null != nullableTypeVariable1;
+
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  null == nonNullableTypeVariable2;
+  null != nonNullableTypeVariable2;
+
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  null == nullableTypeVariable2;
+  null != nullableTypeVariable2;
+
+  nonNullableClass.method() == null;
+  nonNullableClass.method() != null;
+  null == nonNullableClass.method();
+  null != nonNullableClass.method();
+
+  print('EqualsNull (constant null)');
+  nullValue == nullValue;
+  nullValue != nullValue;
+
+  nonNullableObject == nullValue;
+  nonNullableObject != nullValue;
+  nullValue == nonNullableObject;
+  nullValue != nonNullableObject;
+
+  nullableObject == nullValue;
+  nullableObject != nullValue;
+  nullValue == nullableObject;
+  nullValue != nullableObject;
+
+  nonNullableClass == nullValue;
+  nonNullableClass != nullValue;
+  nullValue == nonNullableClass;
+  nullValue != nonNullableClass;
+
+  nullableClass == nullValue;
+  nullableClass != nullValue;
+  nullValue == nullableClass;
+  nullValue != nullableClass;
+
+  dyn == nullValue;
+  dyn != nullValue;
+  nullValue == dyn;
+  nullValue != dyn;
+
+  never == nullValue;
+  never != nullValue;
+  nullValue == never;
+  nullValue != never;
+
+  nullableNever == nullValue;
+  nullableNever != nullValue;
+  nullValue == nullableNever;
+  nullValue != nullableNever;
+
+  nullTypedValue == nullValue;
+  nullTypedValue != nullValue;
+  nullValue == nullTypedValue;
+  nullValue != nullTypedValue;
+
+  nonNullableFunction == nullValue;
+  nonNullableFunction != nullValue;
+  nullValue == nonNullableFunction;
+  nullValue != nonNullableFunction;
+
+  nullableFunction == nullValue;
+  nullableFunction != nullValue;
+  nullValue == nullableFunction;
+  nullValue != nullableFunction;
+
+  nonNullableFunctionType == nullValue;
+  nonNullableFunctionType != nullValue;
+  nullValue == nonNullableFunctionType;
+  nullValue != nonNullableFunctionType;
+
+  nullableFunctionType == nullValue;
+  nullableFunctionType != nullValue;
+  nullValue == nullableFunctionType;
+  nullValue != nullableFunctionType;
+
+  nonNullableTypeVariable1 == nullValue;
+  nonNullableTypeVariable1 != nullValue;
+  nullValue == nonNullableTypeVariable1;
+  nullValue != nonNullableTypeVariable1;
+
+  nullableTypeVariable1 == nullValue;
+  nullableTypeVariable1 != nullValue;
+  nullValue == nullableTypeVariable1;
+  nullValue != nullableTypeVariable1;
+
+  nonNullableTypeVariable2 == nullValue;
+  nonNullableTypeVariable2 != nullValue;
+  nullValue == nonNullableTypeVariable2;
+  nullValue != nonNullableTypeVariable2;
+
+  nullableTypeVariable2 == nullValue;
+  nullableTypeVariable2 != nullValue;
+  nullValue == nullableTypeVariable2;
+  nullValue != nullableTypeVariable2;
+
+  nonNullableClass.method() == nullValue;
+  nonNullableClass.method() != nullValue;
+  nullValue == nonNullableClass.method();
+  nullValue != nonNullableClass.method();
+
+  print('EqualsCall');
+
+  nonNullableObject == nullTypedValue;
+  nonNullableObject != nullTypedValue;
+  nullTypedValue == nonNullableObject;
+  nullTypedValue != nonNullableObject;
+  nonNullableObject == o;
+  nonNullableObject != o;
+  o == nonNullableObject;
+  o != nonNullableObject;
+
+  nullableObject == nullTypedValue;
+  nullableObject != nullTypedValue;
+  nullTypedValue == nullableObject;
+  nullTypedValue != nullableObject;
+  nullableObject == o;
+  nullableObject != o;
+  o == nullableObject;
+  o != nullableObject;
+
+  nonNullableClass == nullTypedValue;
+  nonNullableClass != nullTypedValue;
+  nullTypedValue == nonNullableClass;
+  nullTypedValue != nonNullableClass;
+  nonNullableClass == o;
+  nonNullableClass != o;
+  o == nonNullableClass;
+  o != nonNullableClass;
+
+  nullableClass == nullTypedValue;
+  nullableClass != nullTypedValue;
+  nullTypedValue == nullableClass;
+  nullTypedValue != nullableClass;
+  nullableClass == o;
+  nullableClass != o;
+  o == nullableClass;
+  o != nullableClass;
+
+  dyn == nullTypedValue;
+  dyn != nullTypedValue;
+  nullTypedValue == dyn;
+  nullTypedValue != dyn;
+  dyn == o;
+  dyn != o;
+  o == dyn;
+  o != dyn;
+
+  never == nullTypedValue;
+  never != nullTypedValue;
+  nullTypedValue == never;
+  nullTypedValue != never;
+  never == o;
+  never != o;
+  o == never;
+  o != never;
+
+  nullableNever == nullTypedValue;
+  nullableNever != nullTypedValue;
+  nullTypedValue == nullableNever;
+  nullTypedValue != nullableNever;
+  nullableNever == o;
+  nullableNever != o;
+  o == nullableNever;
+  o != nullableNever;
+
+  nullTypedValue == nullTypedValue;
+  nullTypedValue != nullTypedValue;
+  nullTypedValue == nullTypedValue;
+  nullTypedValue != nullTypedValue;
+  nullTypedValue == o;
+  nullTypedValue != o;
+  o == nullTypedValue;
+  o != nullTypedValue;
+
+  nonNullableFunction == nullTypedValue;
+  nonNullableFunction != nullTypedValue;
+  nullTypedValue == nonNullableFunction;
+  nullTypedValue != nonNullableFunction;
+  nonNullableFunction == o;
+  nonNullableFunction != o;
+  o == nonNullableFunction;
+  o != nonNullableFunction;
+
+  nullableFunction == nullTypedValue;
+  nullableFunction != nullTypedValue;
+  nullTypedValue == nullableFunction;
+  nullTypedValue != nullableFunction;
+  nullableFunction == o;
+  nullableFunction != o;
+  o == nullableFunction;
+  o != nullableFunction;
+
+  nonNullableFunctionType == nullTypedValue;
+  nonNullableFunctionType != nullTypedValue;
+  nullTypedValue == nonNullableFunctionType;
+  nullTypedValue != nonNullableFunctionType;
+  nonNullableFunctionType == o;
+  nonNullableFunctionType != o;
+  o == nonNullableFunctionType;
+  o != nonNullableFunctionType;
+
+  nullableFunctionType == nullTypedValue;
+  nullableFunctionType != nullTypedValue;
+  nullTypedValue == nullableFunctionType;
+  nullTypedValue != nullableFunctionType;
+  nullableFunctionType == o;
+  nullableFunctionType != o;
+  o == nullableFunctionType;
+  o != nullableFunctionType;
+
+  nonNullableTypeVariable1 == nullTypedValue;
+  nonNullableTypeVariable1 != nullTypedValue;
+  nullTypedValue == nonNullableTypeVariable1;
+  nullTypedValue != nonNullableTypeVariable1;
+  nonNullableTypeVariable1 == o;
+  nonNullableTypeVariable1 != o;
+  o == nonNullableTypeVariable1;
+  o != nonNullableTypeVariable1;
+
+  nullableTypeVariable1 == nullTypedValue;
+  nullableTypeVariable1 != nullTypedValue;
+  nullTypedValue == nullableTypeVariable1;
+  nullTypedValue != nullableTypeVariable1;
+  nullableTypeVariable1 == o;
+  nullableTypeVariable1 != o;
+  o == nullableTypeVariable1;
+  o != nullableTypeVariable1;
+
+  nonNullableTypeVariable2 == nullTypedValue;
+  nonNullableTypeVariable2 != nullTypedValue;
+  nullTypedValue == nonNullableTypeVariable2;
+  nullTypedValue != nonNullableTypeVariable2;
+  nonNullableTypeVariable2 == o;
+  nonNullableTypeVariable2 != o;
+  o == nonNullableTypeVariable2;
+  o != nonNullableTypeVariable2;
+
+  nullableTypeVariable2 == nullTypedValue;
+  nullableTypeVariable2 != nullTypedValue;
+  nullTypedValue == nullableTypeVariable2;
+  nullTypedValue != nullableTypeVariable2;
+  nullableTypeVariable2 == o;
+  nullableTypeVariable2 != o;
+  o == nullableTypeVariable2;
+  o != nullableTypeVariable2;
+
+  nonNullableClass.method() == nullTypedValue;
+  nonNullableClass.method() != nullTypedValue;
+  nullTypedValue == nonNullableClass.method();
+  nullTypedValue != nonNullableClass.method();
+  nonNullableClass.method() == o;
+  nonNullableClass.method() != o;
+  o == nonNullableClass.method();
+  o != nonNullableClass.method();
+}
+
+nullEqualsIndexGet(Map<int, String> map) {
+  null == map[0];
+  map[0] == null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/none/equals.dart.outline.expect b/pkg/front_end/testcases/none/equals.dart.outline.expect
new file mode 100644
index 0000000..aae3b91
--- /dev/null
+++ b/pkg/front_end/testcases/none/equals.dart.outline.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T%>
+    ;
+  operator ==(covariant generic-covariant-impl self::Class<self::Class::T%> other) → core::bool
+    ;
+  method method(dynamic o) → dynamic
+    ;
+}
+static const field core::Object? nullValue = null;
+static method test<T1 extends core::Function = core::Function, T2 extends (core::int) → core::int = (core::int) → core::int>(core::Object o, core::Object nonNullableObject, core::Object? nullableObject, self::Class<core::String> nonNullableClass, self::Class<core::String>? nullableClass, dynamic dyn, Never never, Never? nullableNever, Null nullTypedValue, core::Function nonNullableFunction, core::Function? nullableFunction, (core::int) → core::int nonNullableFunctionType, (core::int) →? core::int nullableFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2) → dynamic
+  ;
+static method nullEqualsIndexGet(core::Map<core::int, core::String> map) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/none/equals.dart.strong.expect b/pkg/front_end/testcases/none/equals.dart.strong.expect
new file mode 100644
index 0000000..61c94f5
--- /dev/null
+++ b/pkg/front_end/testcases/none/equals.dart.strong.expect
@@ -0,0 +1,482 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/equals.dart:115:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() == null;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:116:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() != null;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:117:34: Error: Too few positional arguments: 1 required, 0 given.
+//   null == nonNullableClass.method();
+//                                  ^
+//
+// pkg/front_end/testcases/none/equals.dart:118:34: Error: Too few positional arguments: 1 required, 0 given.
+//   null != nonNullableClass.method();
+//                                  ^
+//
+// pkg/front_end/testcases/none/equals.dart:134:23: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nonNullableClass == nullValue;
+//                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:135:23: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nonNullableClass != nullValue;
+//                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:139:20: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nullableClass == nullValue;
+//                    ^
+//
+// pkg/front_end/testcases/none/equals.dart:140:20: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nullableClass != nullValue;
+//                    ^
+//
+// pkg/front_end/testcases/none/equals.dart:204:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() == nullValue;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:205:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() != nullValue;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:206:39: Error: Too few positional arguments: 1 required, 0 given.
+//   nullValue == nonNullableClass.method();
+//                                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:207:39: Error: Too few positional arguments: 1 required, 0 given.
+//   nullValue != nonNullableClass.method();
+//                                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:233:23: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nonNullableClass == o;
+//                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:234:23: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nonNullableClass != o;
+//                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:242:20: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nullableClass == o;
+//                    ^
+//
+// pkg/front_end/testcases/none/equals.dart:243:20: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nullableClass != o;
+//                    ^
+//
+// pkg/front_end/testcases/none/equals.dart:355:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() == nullTypedValue;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:356:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() != nullTypedValue;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:357:44: Error: Too few positional arguments: 1 required, 0 given.
+//   nullTypedValue == nonNullableClass.method();
+//                                            ^
+//
+// pkg/front_end/testcases/none/equals.dart:358:44: Error: Too few positional arguments: 1 required, 0 given.
+//   nullTypedValue != nonNullableClass.method();
+//                                            ^
+//
+// pkg/front_end/testcases/none/equals.dart:359:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() == o;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:360:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() != o;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:361:31: Error: Too few positional arguments: 1 required, 0 given.
+//   o == nonNullableClass.method();
+//                               ^
+//
+// pkg/front_end/testcases/none/equals.dart:362:31: Error: Too few positional arguments: 1 required, 0 given.
+//   o != nonNullableClass.method();
+//                               ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T%>
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::Class<self::Class::T%> other) → core::bool
+    return true;
+  method method(dynamic o) → dynamic {}
+}
+static const field core::Object? nullValue = #C1;
+static method test<T1 extends core::Function = core::Function, T2 extends (core::int) → core::int = (core::int) → core::int>(core::Object o, core::Object nonNullableObject, core::Object? nullableObject, self::Class<core::String> nonNullableClass, self::Class<core::String>? nullableClass, dynamic dyn, Never never, Never? nullableNever, Null nullTypedValue, core::Function nonNullableFunction, core::Function? nullableFunction, (core::int) → core::int nonNullableFunctionType, (core::int) →? core::int nullableFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2) → dynamic {
+  core::print("EqualsNull (literal null)");
+  null == null;
+  null != null;
+  nonNullableObject == null;
+  nonNullableObject != null;
+  nonNullableObject == null;
+  nonNullableObject != null;
+  nullableObject == null;
+  nullableObject != null;
+  nullableObject == null;
+  nullableObject != null;
+  nullableClass == null;
+  nullableClass != null;
+  nullableClass == null;
+  nullableClass != null;
+  nonNullableClass == null;
+  nonNullableClass != null;
+  nonNullableClass == null;
+  nonNullableClass != null;
+  dyn == null;
+  dyn != null;
+  dyn == null;
+  dyn != null;
+  never == null;
+  never != null;
+  never == null;
+  never != null;
+  nullableNever == null;
+  nullableNever != null;
+  nullableNever == null;
+  nullableNever != null;
+  nullTypedValue == null;
+  nullTypedValue != null;
+  nullTypedValue == null;
+  nullTypedValue != null;
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  nullableFunction == null;
+  nullableFunction != null;
+  nullableFunction == null;
+  nullableFunction != null;
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/none/equals.dart:115:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() == null;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) == null;
+  (let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/none/equals.dart:116:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() != null;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) != null;
+  (let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/none/equals.dart:117:34: Error: Too few positional arguments: 1 required, 0 given.
+  null == nonNullableClass.method();
+                                 ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) == null;
+  (let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/none/equals.dart:118:34: Error: Too few positional arguments: 1 required, 0 given.
+  null != nonNullableClass.method();
+                                 ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) != null;
+  core::print("EqualsNull (constant null)");
+  (#C1) == null;
+  (#C1) != null;
+  nonNullableObject == null;
+  nonNullableObject != null;
+  nonNullableObject == null;
+  nonNullableObject != null;
+  nullableObject == null;
+  nullableObject != null;
+  nullableObject == null;
+  nullableObject != null;
+  nonNullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/none/equals.dart:134:23: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nonNullableClass == nullValue;
+                      ^" in (#C1) as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nonNullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/none/equals.dart:135:23: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nonNullableClass != nullValue;
+                      ^" in (#C1) as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nonNullableClass == null;
+  nonNullableClass != null;
+  nullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/none/equals.dart:139:20: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nullableClass == nullValue;
+                   ^" in (#C1) as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/none/equals.dart:140:20: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nullableClass != nullValue;
+                   ^" in (#C1) as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nullableClass == null;
+  nullableClass != null;
+  dyn == null;
+  dyn != null;
+  dyn == null;
+  dyn != null;
+  never == null;
+  never != null;
+  never == null;
+  never != null;
+  nullableNever == null;
+  nullableNever != null;
+  nullableNever == null;
+  nullableNever != null;
+  nullTypedValue == null;
+  nullTypedValue != null;
+  nullTypedValue == null;
+  nullTypedValue != null;
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  nullableFunction == null;
+  nullableFunction != null;
+  nullableFunction == null;
+  nullableFunction != null;
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  (let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/none/equals.dart:204:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() == nullValue;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) == null;
+  (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/none/equals.dart:205:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() != nullValue;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) != null;
+  (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/none/equals.dart:206:39: Error: Too few positional arguments: 1 required, 0 given.
+  nullValue == nonNullableClass.method();
+                                      ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) == null;
+  (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/none/equals.dart:207:39: Error: Too few positional arguments: 1 required, 0 given.
+  nullValue != nonNullableClass.method();
+                                      ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) != null;
+  core::print("EqualsCall");
+  nonNullableObject =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableObject !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableObject;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableObject;
+  nonNullableObject =={core::Object::==}{(core::Object) → core::bool} o;
+  nonNullableObject !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableObject;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableObject;
+  nullableObject =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableObject !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableObject;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableObject;
+  nullableObject =={core::Object::==}{(core::Object) → core::bool} o;
+  nullableObject !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableObject;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableObject;
+  nonNullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} nullTypedValue;
+  nonNullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableClass;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableClass;
+  nonNullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/none/equals.dart:233:23: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nonNullableClass == o;
+                      ^" in o as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nonNullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/none/equals.dart:234:23: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nonNullableClass != o;
+                      ^" in o as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableClass;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableClass;
+  nullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} nullTypedValue;
+  nullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableClass;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableClass;
+  nullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/none/equals.dart:242:20: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nullableClass == o;
+                   ^" in o as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/none/equals.dart:243:20: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nullableClass != o;
+                   ^" in o as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  o =={core::Object::==}{(core::Object) → core::bool} nullableClass;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableClass;
+  dyn =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  dyn !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} dyn;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} dyn;
+  dyn =={core::Object::==}{(core::Object) → core::bool} o;
+  dyn !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} dyn;
+  o !={core::Object::==}{(core::Object) → core::bool} dyn;
+  never =={core::Object::==}{(dynamic) → Never} nullTypedValue;
+  never !={core::Object::==}{(dynamic) → Never} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} never;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} never;
+  never =={core::Object::==}{(dynamic) → Never} o;
+  never !={core::Object::==}{(dynamic) → Never} o;
+  o =={core::Object::==}{(core::Object) → core::bool} never;
+  o !={core::Object::==}{(core::Object) → core::bool} never;
+  nullableNever =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableNever !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableNever;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableNever;
+  nullableNever =={core::Object::==}{(core::Object) → core::bool} o;
+  nullableNever !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableNever;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableNever;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} o;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  o !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableFunction =={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableFunction !={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableFunction;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableFunction;
+  nonNullableFunction =={core::Function::==}{(core::Object) → core::bool} o;
+  nonNullableFunction !={core::Function::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableFunction;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableFunction;
+  nullableFunction =={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableFunction !={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableFunction;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableFunction;
+  nullableFunction =={core::Function::==}{(core::Object) → core::bool} o;
+  nullableFunction !={core::Function::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableFunction;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableFunction;
+  nonNullableFunctionType =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableFunctionType !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableFunctionType;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableFunctionType;
+  nonNullableFunctionType =={core::Object::==}{(core::Object) → core::bool} o;
+  nonNullableFunctionType !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableFunctionType;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableFunctionType;
+  nullableFunctionType =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableFunctionType !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableFunctionType;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableFunctionType;
+  nullableFunctionType =={core::Object::==}{(core::Object) → core::bool} o;
+  nullableFunctionType !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableFunctionType;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableFunctionType;
+  nonNullableTypeVariable1 =={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableTypeVariable1 !={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable1;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable1;
+  nonNullableTypeVariable1 =={core::Function::==}{(core::Object) → core::bool} o;
+  nonNullableTypeVariable1 !={core::Function::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable1;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable1;
+  nullableTypeVariable1 =={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableTypeVariable1 !={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable1;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable1;
+  nullableTypeVariable1 =={core::Function::==}{(core::Object) → core::bool} o;
+  nullableTypeVariable1 !={core::Function::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable1;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable1;
+  nonNullableTypeVariable2 =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableTypeVariable2 !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable2;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable2;
+  nonNullableTypeVariable2 =={core::Object::==}{(core::Object) → core::bool} o;
+  nonNullableTypeVariable2 !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable2;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable2;
+  nullableTypeVariable2 =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableTypeVariable2 !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable2;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable2;
+  nullableTypeVariable2 =={core::Object::==}{(core::Object) → core::bool} o;
+  nullableTypeVariable2 !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable2;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable2;
+  (let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/none/equals.dart:355:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() == nullTypedValue;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  (let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/none/equals.dart:356:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() != nullTypedValue;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/none/equals.dart:357:44: Error: Too few positional arguments: 1 required, 0 given.
+  nullTypedValue == nonNullableClass.method();
+                                           ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type});
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} (let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/none/equals.dart:358:44: Error: Too few positional arguments: 1 required, 0 given.
+  nullTypedValue != nonNullableClass.method();
+                                           ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type});
+  (let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/none/equals.dart:359:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() == o;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) =={core::Object::==}{(core::Object) → core::bool} o;
+  (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/none/equals.dart:360:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() != o;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} (let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/none/equals.dart:361:31: Error: Too few positional arguments: 1 required, 0 given.
+  o == nonNullableClass.method();
+                              ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type});
+  o !={core::Object::==}{(core::Object) → core::bool} (let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/none/equals.dart:362:31: Error: Too few positional arguments: 1 required, 0 given.
+  o != nonNullableClass.method();
+                              ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type});
+}
+static method nullEqualsIndexGet(core::Map<core::int, core::String> map) → dynamic {
+  map.{core::Map::[]}(0){(core::Object?) → core::String?} == null;
+  map.{core::Map::[]}(0){(core::Object?) → core::String?} == null;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/none/equals.dart.textual_outline.expect b/pkg/front_end/testcases/none/equals.dart.textual_outline.expect
new file mode 100644
index 0000000..bd43417
--- /dev/null
+++ b/pkg/front_end/testcases/none/equals.dart.textual_outline.expect
@@ -0,0 +1,27 @@
+const Object? nullValue = null;
+
+class Class<T> {
+  operator ==(covariant Class<T> other) => true;
+  method(o) {}
+}
+
+test<T1 extends Function, T2 extends int Function(int)>(
+    Object o,
+    Object nonNullableObject,
+    Object? nullableObject,
+    Class<String> nonNullableClass,
+    Class<String>? nullableClass,
+    dynamic dyn,
+    Never never,
+    Never? nullableNever,
+    Null nullTypedValue,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function(int) nonNullableFunctionType,
+    int Function(int)? nullableFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2) {}
+nullEqualsIndexGet(Map<int, String> map) {}
+main() {}
diff --git a/pkg/front_end/testcases/none/equals.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/none/equals.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..58ef786
--- /dev/null
+++ b/pkg/front_end/testcases/none/equals.dart.textual_outline_modelled.expect
@@ -0,0 +1,26 @@
+class Class<T> {
+  method(o) {}
+  operator ==(covariant Class<T> other) => true;
+}
+
+const Object? nullValue = null;
+main() {}
+nullEqualsIndexGet(Map<int, String> map) {}
+test<T1 extends Function, T2 extends int Function(int)>(
+    Object o,
+    Object nonNullableObject,
+    Object? nullableObject,
+    Class<String> nonNullableClass,
+    Class<String>? nullableClass,
+    dynamic dyn,
+    Never never,
+    Never? nullableNever,
+    Null nullTypedValue,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function(int) nonNullableFunctionType,
+    int Function(int)? nullableFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2) {}
diff --git a/pkg/front_end/testcases/none/equals.dart.weak.expect b/pkg/front_end/testcases/none/equals.dart.weak.expect
new file mode 100644
index 0000000..11bf642
--- /dev/null
+++ b/pkg/front_end/testcases/none/equals.dart.weak.expect
@@ -0,0 +1,483 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/equals.dart:115:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() == null;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:116:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() != null;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:117:34: Error: Too few positional arguments: 1 required, 0 given.
+//   null == nonNullableClass.method();
+//                                  ^
+//
+// pkg/front_end/testcases/none/equals.dart:118:34: Error: Too few positional arguments: 1 required, 0 given.
+//   null != nonNullableClass.method();
+//                                  ^
+//
+// pkg/front_end/testcases/none/equals.dart:134:23: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nonNullableClass == nullValue;
+//                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:135:23: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nonNullableClass != nullValue;
+//                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:139:20: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nullableClass == nullValue;
+//                    ^
+//
+// pkg/front_end/testcases/none/equals.dart:140:20: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nullableClass != nullValue;
+//                    ^
+//
+// pkg/front_end/testcases/none/equals.dart:204:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() == nullValue;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:205:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() != nullValue;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:206:39: Error: Too few positional arguments: 1 required, 0 given.
+//   nullValue == nonNullableClass.method();
+//                                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:207:39: Error: Too few positional arguments: 1 required, 0 given.
+//   nullValue != nonNullableClass.method();
+//                                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:233:23: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nonNullableClass == o;
+//                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:234:23: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nonNullableClass != o;
+//                       ^
+//
+// pkg/front_end/testcases/none/equals.dart:242:20: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nullableClass == o;
+//                    ^
+//
+// pkg/front_end/testcases/none/equals.dart:243:20: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+//  - 'Object' is from 'dart:core'.
+//  - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+//   nullableClass != o;
+//                    ^
+//
+// pkg/front_end/testcases/none/equals.dart:355:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() == nullTypedValue;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:356:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() != nullTypedValue;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:357:44: Error: Too few positional arguments: 1 required, 0 given.
+//   nullTypedValue == nonNullableClass.method();
+//                                            ^
+//
+// pkg/front_end/testcases/none/equals.dart:358:44: Error: Too few positional arguments: 1 required, 0 given.
+//   nullTypedValue != nonNullableClass.method();
+//                                            ^
+//
+// pkg/front_end/testcases/none/equals.dart:359:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() == o;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:360:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass.method() != o;
+//                          ^
+//
+// pkg/front_end/testcases/none/equals.dart:361:31: Error: Too few positional arguments: 1 required, 0 given.
+//   o == nonNullableClass.method();
+//                               ^
+//
+// pkg/front_end/testcases/none/equals.dart:362:31: Error: Too few positional arguments: 1 required, 0 given.
+//   o != nonNullableClass.method();
+//                               ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T%>
+    : super core::Object::•()
+    ;
+  operator ==(covariant generic-covariant-impl self::Class<self::Class::T%> other) → core::bool
+    return true;
+  method method(dynamic o) → dynamic {}
+}
+static const field core::Object? nullValue = #C1;
+static method test<T1 extends core::Function = core::Function, T2 extends (core::int) → core::int = (core::int) → core::int>(core::Object o, core::Object nonNullableObject, core::Object? nullableObject, self::Class<core::String> nonNullableClass, self::Class<core::String>? nullableClass, dynamic dyn, Never never, Never? nullableNever, Null nullTypedValue, core::Function nonNullableFunction, core::Function? nullableFunction, (core::int) → core::int nonNullableFunctionType, (core::int) →? core::int nullableFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2) → dynamic {
+  core::print("EqualsNull (literal null)");
+  null == null;
+  null != null;
+  nonNullableObject == null;
+  nonNullableObject != null;
+  nonNullableObject == null;
+  nonNullableObject != null;
+  nullableObject == null;
+  nullableObject != null;
+  nullableObject == null;
+  nullableObject != null;
+  nullableClass == null;
+  nullableClass != null;
+  nullableClass == null;
+  nullableClass != null;
+  nonNullableClass == null;
+  nonNullableClass != null;
+  nonNullableClass == null;
+  nonNullableClass != null;
+  dyn == null;
+  dyn != null;
+  dyn == null;
+  dyn != null;
+  (let final Never #t1 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) == null;
+  (let final Never #t2 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) != null;
+  (let final Never #t3 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) == null;
+  (let final Never #t4 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) != null;
+  nullableNever == null;
+  nullableNever != null;
+  nullableNever == null;
+  nullableNever != null;
+  nullTypedValue == null;
+  nullTypedValue != null;
+  nullTypedValue == null;
+  nullTypedValue != null;
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  nullableFunction == null;
+  nullableFunction != null;
+  nullableFunction == null;
+  nullableFunction != null;
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  (let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/none/equals.dart:115:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() == null;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) == null;
+  (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/none/equals.dart:116:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() != null;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) != null;
+  (let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/none/equals.dart:117:34: Error: Too few positional arguments: 1 required, 0 given.
+  null == nonNullableClass.method();
+                                 ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) == null;
+  (let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/none/equals.dart:118:34: Error: Too few positional arguments: 1 required, 0 given.
+  null != nonNullableClass.method();
+                                 ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) != null;
+  core::print("EqualsNull (constant null)");
+  (#C1) == null;
+  (#C1) != null;
+  nonNullableObject == null;
+  nonNullableObject != null;
+  nonNullableObject == null;
+  nonNullableObject != null;
+  nullableObject == null;
+  nullableObject != null;
+  nullableObject == null;
+  nullableObject != null;
+  nonNullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/none/equals.dart:134:23: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nonNullableClass == nullValue;
+                      ^" in (#C1) as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nonNullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/none/equals.dart:135:23: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nonNullableClass != nullValue;
+                      ^" in (#C1) as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nonNullableClass == null;
+  nonNullableClass != null;
+  nullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/none/equals.dart:139:20: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nullableClass == nullValue;
+                   ^" in (#C1) as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/none/equals.dart:140:20: Error: The argument type 'Object?' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nullableClass != nullValue;
+                   ^" in (#C1) as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nullableClass == null;
+  nullableClass != null;
+  dyn == null;
+  dyn != null;
+  dyn == null;
+  dyn != null;
+  let final Never #t13 = (let final Never #t14 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) == null in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t15 = (let final Never #t16 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) != null in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  (let final Never #t17 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) == null;
+  (let final Never #t18 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) != null;
+  nullableNever == null;
+  nullableNever != null;
+  nullableNever == null;
+  nullableNever != null;
+  nullTypedValue == null;
+  nullTypedValue != null;
+  nullTypedValue == null;
+  nullTypedValue != null;
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  nonNullableFunction == null;
+  nonNullableFunction != null;
+  nullableFunction == null;
+  nullableFunction != null;
+  nullableFunction == null;
+  nullableFunction != null;
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  nonNullableFunctionType == null;
+  nonNullableFunctionType != null;
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  nullableFunctionType == null;
+  nullableFunctionType != null;
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  nonNullableTypeVariable1 == null;
+  nonNullableTypeVariable1 != null;
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  nullableTypeVariable1 == null;
+  nullableTypeVariable1 != null;
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  nonNullableTypeVariable2 == null;
+  nonNullableTypeVariable2 != null;
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  nullableTypeVariable2 == null;
+  nullableTypeVariable2 != null;
+  (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/none/equals.dart:204:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() == nullValue;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) == null;
+  (let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/none/equals.dart:205:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() != nullValue;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) != null;
+  (let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/none/equals.dart:206:39: Error: Too few positional arguments: 1 required, 0 given.
+  nullValue == nonNullableClass.method();
+                                      ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) == null;
+  (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/none/equals.dart:207:39: Error: Too few positional arguments: 1 required, 0 given.
+  nullValue != nonNullableClass.method();
+                                      ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) != null;
+  core::print("EqualsCall");
+  nonNullableObject =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableObject !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableObject;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableObject;
+  nonNullableObject =={core::Object::==}{(core::Object) → core::bool} o;
+  nonNullableObject !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableObject;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableObject;
+  nullableObject =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableObject !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableObject;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableObject;
+  nullableObject =={core::Object::==}{(core::Object) → core::bool} o;
+  nullableObject !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableObject;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableObject;
+  nonNullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} nullTypedValue;
+  nonNullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableClass;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableClass;
+  nonNullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/none/equals.dart:233:23: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nonNullableClass == o;
+                      ^" in o as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nonNullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/none/equals.dart:234:23: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nonNullableClass != o;
+                      ^" in o as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableClass;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableClass;
+  nullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} nullTypedValue;
+  nullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableClass;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableClass;
+  nullableClass =={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/none/equals.dart:242:20: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nullableClass == o;
+                   ^" in o as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  nullableClass !={self::Class::==}{(self::Class<core::String>) → core::bool} (let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/none/equals.dart:243:20: Error: The argument type 'Object' can't be assigned to the parameter type 'Class<String>?'.
+ - 'Object' is from 'dart:core'.
+ - 'Class' is from 'pkg/front_end/testcases/none/equals.dart'.
+  nullableClass != o;
+                   ^" in o as{TypeError,ForNonNullableByDefault} self::Class<core::String>?);
+  o =={core::Object::==}{(core::Object) → core::bool} nullableClass;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableClass;
+  dyn =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  dyn !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} dyn;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} dyn;
+  dyn =={core::Object::==}{(core::Object) → core::bool} o;
+  dyn !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} dyn;
+  o !={core::Object::==}{(core::Object) → core::bool} dyn;
+  let final Never #t27 = (let final Never #t28 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) =={core::Object::==}{(dynamic) → Never} nullTypedValue in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t29 = (let final Never #t30 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) !={core::Object::==}{(dynamic) → Never} nullTypedValue in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} (let final Never #t31 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} (let final Never #t32 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  let final Never #t33 = (let final Never #t34 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) =={core::Object::==}{(dynamic) → Never} o in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t35 = (let final Never #t36 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) !={core::Object::==}{(dynamic) → Never} o in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  o =={core::Object::==}{(core::Object) → core::bool} (let final Never #t37 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  o !={core::Object::==}{(core::Object) → core::bool} (let final Never #t38 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  nullableNever =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableNever !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableNever;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableNever;
+  nullableNever =={core::Object::==}{(core::Object) → core::bool} o;
+  nullableNever !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableNever;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableNever;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} o;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  o !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableFunction =={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableFunction !={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableFunction;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableFunction;
+  nonNullableFunction =={core::Function::==}{(core::Object) → core::bool} o;
+  nonNullableFunction !={core::Function::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableFunction;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableFunction;
+  nullableFunction =={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableFunction !={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableFunction;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableFunction;
+  nullableFunction =={core::Function::==}{(core::Object) → core::bool} o;
+  nullableFunction !={core::Function::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableFunction;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableFunction;
+  nonNullableFunctionType =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableFunctionType !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableFunctionType;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableFunctionType;
+  nonNullableFunctionType =={core::Object::==}{(core::Object) → core::bool} o;
+  nonNullableFunctionType !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableFunctionType;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableFunctionType;
+  nullableFunctionType =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableFunctionType !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableFunctionType;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableFunctionType;
+  nullableFunctionType =={core::Object::==}{(core::Object) → core::bool} o;
+  nullableFunctionType !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableFunctionType;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableFunctionType;
+  nonNullableTypeVariable1 =={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableTypeVariable1 !={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable1;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable1;
+  nonNullableTypeVariable1 =={core::Function::==}{(core::Object) → core::bool} o;
+  nonNullableTypeVariable1 !={core::Function::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable1;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable1;
+  nullableTypeVariable1 =={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableTypeVariable1 !={core::Function::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable1;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable1;
+  nullableTypeVariable1 =={core::Function::==}{(core::Object) → core::bool} o;
+  nullableTypeVariable1 !={core::Function::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable1;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable1;
+  nonNullableTypeVariable2 =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nonNullableTypeVariable2 !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable2;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable2;
+  nonNullableTypeVariable2 =={core::Object::==}{(core::Object) → core::bool} o;
+  nonNullableTypeVariable2 !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable2;
+  o !={core::Object::==}{(core::Object) → core::bool} nonNullableTypeVariable2;
+  nullableTypeVariable2 =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullableTypeVariable2 !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable2;
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable2;
+  nullableTypeVariable2 =={core::Object::==}{(core::Object) → core::bool} o;
+  nullableTypeVariable2 !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable2;
+  o !={core::Object::==}{(core::Object) → core::bool} nullableTypeVariable2;
+  (let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/none/equals.dart:355:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() == nullTypedValue;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) =={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  (let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/none/equals.dart:356:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() != nullTypedValue;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) !={core::Object::==}{(core::Object) → core::bool} nullTypedValue;
+  nullTypedValue =={core::Object::==}{(core::Object) → core::bool} (let final<BottomType> #t41 = invalid-expression "pkg/front_end/testcases/none/equals.dart:357:44: Error: Too few positional arguments: 1 required, 0 given.
+  nullTypedValue == nonNullableClass.method();
+                                           ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type});
+  nullTypedValue !={core::Object::==}{(core::Object) → core::bool} (let final<BottomType> #t42 = invalid-expression "pkg/front_end/testcases/none/equals.dart:358:44: Error: Too few positional arguments: 1 required, 0 given.
+  nullTypedValue != nonNullableClass.method();
+                                           ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type});
+  (let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/none/equals.dart:359:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() == o;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) =={core::Object::==}{(core::Object) → core::bool} o;
+  (let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/none/equals.dart:360:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass.method() != o;
+                         ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type}) !={core::Object::==}{(core::Object) → core::bool} o;
+  o =={core::Object::==}{(core::Object) → core::bool} (let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/none/equals.dart:361:31: Error: Too few positional arguments: 1 required, 0 given.
+  o == nonNullableClass.method();
+                              ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type});
+  o !={core::Object::==}{(core::Object) → core::bool} (let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/none/equals.dart:362:31: Error: Too few positional arguments: 1 required, 0 given.
+  o != nonNullableClass.method();
+                              ^" in nonNullableClass.{self::Class::method}{<inapplicable>}.(){() → invalid-type});
+}
+static method nullEqualsIndexGet(core::Map<core::int, core::String> map) → dynamic {
+  map.{core::Map::[]}(0){(core::Object?) → core::String?} == null;
+  map.{core::Map::[]}(0){(core::Object?) → core::String?} == null;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/none/method_invocation.dart b/pkg/front_end/testcases/none/method_invocation.dart
new file mode 100644
index 0000000..e354863
--- /dev/null
+++ b/pkg/front_end/testcases/none/method_invocation.dart
@@ -0,0 +1,161 @@
+// 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.md file.
+
+class Class1 {
+  double method(int o) => 0.5;
+}
+
+class Class2<T> {
+  T field;
+
+  Class2(this.field, this.nonNullableFunctionField,
+      this.nonNullableFunctionTypedField);
+
+  T call() => field;
+
+  T method(int o) => field;
+
+  Function nonNullableFunctionField;
+
+  Function get nonNullableFunctionGetter => nonNullableFunctionTypedField;
+
+  Function? nullableFunctionField;
+
+  Function? get nullableFunctionGetter => nonNullableFunctionTypedField;
+
+  void Function() nonNullableFunctionTypedField;
+
+  void Function() get nonNullableFunctionTypedGetter =>
+      nonNullableFunctionTypedField;
+
+  void Function()? nullableFunctionTypedField;
+
+  void Function()? get nullableFunctionTypedGetter =>
+      nonNullableFunctionTypedField;
+}
+
+const int i = 4;
+const int j = 24;
+const int k = i * j;
+
+test<T1 extends Function, T2 extends int Function(int), T3>(
+    Class1 nonNullableClass1,
+    Class1? nullableClass1,
+    dynamic dyn,
+    Never never,
+    Class2<String> nonNullableClass2,
+    Class2<String>? nullableClass2,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function(int) nonNullableFunctionType,
+    int Function(int)? nullableFunctionType,
+    T Function<T>(T) genericFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2,
+    T3 undeterminedTypeVariable) {
+  print('InstanceInvocation');
+  nonNullableClass1.method(0);
+  nullableClass1?.method(0);
+
+  print('InstanceGet calls');
+  nonNullableClass2.nonNullableFunctionField();
+  nonNullableClass2.nonNullableFunctionGetter();
+  nonNullableClass2.nonNullableFunctionTypedField();
+  nonNullableClass2.nonNullableFunctionTypedGetter();
+  nonNullableClass2.nullableFunctionField();
+  nonNullableClass2.nullableFunctionGetter();
+  nonNullableClass2.nullableFunctionTypedField();
+  nonNullableClass2.nullableFunctionTypedGetter();
+  nonNullableClass2.nonNullableFunctionField(0);
+  nonNullableClass2.nonNullableFunctionGetter(0);
+  nonNullableClass2.nonNullableFunctionTypedField(0);
+  nonNullableClass2.nonNullableFunctionTypedGetter(0);
+
+  print('InstanceInvocation (Nullable)');
+  nullableClass1.method(0);
+
+  print('DynamicInvocation');
+  dyn.method(0);
+  dyn?.method(0);
+  dyn.toString(0);
+  const int call_dyn = dyn.toString(0);
+  print(call_dyn);
+
+  print('InstanceInvocation (Object)');
+  dyn.toString();
+  nullableClass1.toString();
+  nullableClass2.toString();
+  nullableFunction.toString();
+  nullableFunctionType.toString();
+  nullableTypeVariable1.toString();
+  nullableTypeVariable2.toString();
+  undeterminedTypeVariable.toString();
+
+  print('DynamicInvocation (Never)');
+  never.method(0);
+  never.toString();
+
+  print('DynamicInvocation (Unresolved)');
+  nonNullableClass1.unresolved();
+
+  print('DynamicInvocation (Inapplicable)');
+  nonNullableClass1.method();
+  nonNullableFunctionType();
+
+  print('InstanceInvocation (generic)');
+  nonNullableClass2.method(0);
+  nullableClass2?.method(0);
+  nonNullableClass2();
+  nonNullableClass2.call();
+
+  print('FunctionInvocation');
+  nonNullableFunction(0);
+  nonNullableFunction.call(0);
+  nullableFunction?.call(0);
+  nonNullableFunctionType(0);
+  nonNullableFunctionType.call(0);
+  nullableFunctionType?.call(0);
+  genericFunctionType(0);
+  genericFunctionType<num>(0);
+  num i = genericFunctionType(0);
+  nonNullableTypeVariable1(0);
+  nonNullableTypeVariable1.call(0);
+  nullableTypeVariable1?.call(0);
+  nonNullableTypeVariable2(0);
+  nonNullableTypeVariable2.call(0);
+  nullableTypeVariable2?.call(0);
+
+  print('FunctionInvocation (Nullable)');
+  nullableFunction(0);
+  nullableFunction.call(0);
+  nullableFunctionType(0);
+  nullableFunctionType.call(0);
+
+  print('DynamicInvocation (Invalid)');
+  nonNullableClass1.method().method(0);
+
+  print('LocalFunctionInvocation');
+  int localFunction() => 42;
+  T genericLocalFunction<T>(T t) => t;
+  localFunction();
+  genericLocalFunction(0);
+  genericLocalFunction<num>(0);
+
+  const int call_localFunction = localFunction();
+  print(call_localFunction);
+
+  int Function() f = () => 42;
+
+  const int call_f = f();
+  print(call_f);
+  const int? nullable = 0;
+  const bool equals_null = nullable == null;
+  print(equals_null);
+  const bool equals = i == j;
+  print(equals);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/none/method_invocation.dart.outline.expect b/pkg/front_end/testcases/none/method_invocation.dart.outline.expect
new file mode 100644
index 0000000..8a7fc69
--- /dev/null
+++ b/pkg/front_end/testcases/none/method_invocation.dart.outline.expect
@@ -0,0 +1,43 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → self::Class1
+    ;
+  method method(core::int o) → core::double
+    ;
+}
+class Class2<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::Class2::T% field;
+  field core::Function nonNullableFunctionField;
+  field core::Function? nullableFunctionField;
+  field () → void nonNullableFunctionTypedField;
+  field () →? void nullableFunctionTypedField;
+  constructor •(self::Class2::T% field, core::Function nonNullableFunctionField, () → void nonNullableFunctionTypedField) → self::Class2<self::Class2::T%>
+    ;
+  method call() → self::Class2::T%
+    ;
+  method method(core::int o) → self::Class2::T%
+    ;
+  get nonNullableFunctionGetter() → core::Function
+    ;
+  get nullableFunctionGetter() → core::Function?
+    ;
+  get nonNullableFunctionTypedGetter() → () → void
+    ;
+  get nullableFunctionTypedGetter() → () →? void
+    ;
+}
+static const field core::int i = 4;
+static const field core::int j = 24;
+static const field core::int k = self::i.{core::num::*}(self::j){(core::num) → core::int};
+static method test<T1 extends core::Function = core::Function, T2 extends (core::int) → core::int = (core::int) → core::int, T3 extends core::Object? = dynamic>(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never, self::Class2<core::String> nonNullableClass2, self::Class2<core::String>? nullableClass2, core::Function nonNullableFunction, core::Function? nullableFunction, (core::int) → core::int nonNullableFunctionType, (core::int) →? core::int nullableFunctionType, <T extends core::Object? = dynamic>(T%) → T% genericFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2, self::test::T3% undeterminedTypeVariable) → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///method_invocation.dart:40:17 -> IntConstant(96)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/none/method_invocation.dart.strong.expect b/pkg/front_end/testcases/none/method_invocation.dart.strong.expect
new file mode 100644
index 0000000..d4e8da9
--- /dev/null
+++ b/pkg/front_end/testcases/none/method_invocation.dart.strong.expect
@@ -0,0 +1,296 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/method_invocation.dart:84:24: Error: Not a constant expression.
+//   const int call_dyn = dyn.toString(0);
+//                        ^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:84:28: Error: Method invocation is not a constant expression.
+//   const int call_dyn = dyn.toString(0);
+//                            ^^^^^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:147:34: Error: Not a constant expression.
+//   const int call_localFunction = localFunction();
+//                                  ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:152:22: Error: Not a constant expression.
+//   const int call_f = f();
+//                      ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:157:23: Error: Not a constant expression.
+//   const bool equals = i == j;
+//                       ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:68:42: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+//  - 'Function' is from 'dart:core'.
+// Try calling using ?.call instead.
+//   nonNullableClass2.nullableFunctionField();
+//                                          ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:69:43: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+//  - 'Function' is from 'dart:core'.
+// Try calling using ?.call instead.
+//   nonNullableClass2.nullableFunctionGetter();
+//                                           ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:70:47: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+// Try calling using ?.call instead.
+//   nonNullableClass2.nullableFunctionTypedField();
+//                                               ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:71:48: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+// Try calling using ?.call instead.
+//   nonNullableClass2.nullableFunctionTypedGetter();
+//                                                ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:74:50: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//   nonNullableClass2.nonNullableFunctionTypedField(0);
+//                                                  ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:75:51: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//   nonNullableClass2.nonNullableFunctionTypedGetter(0);
+//                                                   ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:78:18: Error: Method 'method' cannot be called on 'Class1?' because it is potentially null.
+//  - 'Class1' is from 'pkg/front_end/testcases/none/method_invocation.dart'.
+// Try calling using ?. instead.
+//   nullableClass1.method(0);
+//                  ^^^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:102:21: Error: The method 'unresolved' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/none/method_invocation.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'unresolved'.
+//   nonNullableClass1.unresolved();
+//                     ^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:105:27: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass1.method();
+//                           ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:106:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableFunctionType();
+//                          ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:132:19: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+//  - 'Function' is from 'dart:core'.
+// Try calling using ?.call instead.
+//   nullableFunction(0);
+//                   ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:133:20: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+//  - 'Function' is from 'dart:core'.
+// Try calling using ?. instead.
+//   nullableFunction.call(0);
+//                    ^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:134:23: Error: Can't use an expression of type 'int Function(int)?' as a function because it's potentially null.
+// Try calling using ?.call instead.
+//   nullableFunctionType(0);
+//                       ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:135:24: Error: Method 'call' cannot be called on 'int Function(int)?' because it is potentially null.
+// Try calling using ?. instead.
+//   nullableFunctionType.call(0);
+//                        ^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:138:27: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass1.method().method(0);
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → self::Class1
+    : super core::Object::•()
+    ;
+  method method(core::int o) → core::double
+    return 0.5;
+}
+class Class2<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::Class2::T% field;
+  field core::Function nonNullableFunctionField;
+  field core::Function? nullableFunctionField = null;
+  field () → void nonNullableFunctionTypedField;
+  field () →? void nullableFunctionTypedField = null;
+  constructor •(self::Class2::T% field, core::Function nonNullableFunctionField, () → void nonNullableFunctionTypedField) → self::Class2<self::Class2::T%>
+    : self::Class2::field = field, self::Class2::nonNullableFunctionField = nonNullableFunctionField, self::Class2::nonNullableFunctionTypedField = nonNullableFunctionTypedField, super core::Object::•()
+    ;
+  method call() → self::Class2::T%
+    return this.{self::Class2::field}{self::Class2::T%};
+  method method(core::int o) → self::Class2::T%
+    return this.{self::Class2::field}{self::Class2::T%};
+  get nonNullableFunctionGetter() → core::Function
+    return this.{self::Class2::nonNullableFunctionTypedField}{() → void};
+  get nullableFunctionGetter() → core::Function?
+    return this.{self::Class2::nonNullableFunctionTypedField}{() → void};
+  get nonNullableFunctionTypedGetter() → () → void
+    return this.{self::Class2::nonNullableFunctionTypedField}{() → void};
+  get nullableFunctionTypedGetter() → () →? void
+    return this.{self::Class2::nonNullableFunctionTypedField}{() → void};
+}
+static const field core::int i = #C1;
+static const field core::int j = #C2;
+static const field core::int k = #C3;
+static method test<T1 extends core::Function = core::Function, T2 extends (core::int) → core::int = (core::int) → core::int, T3 extends core::Object? = dynamic>(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never, self::Class2<core::String> nonNullableClass2, self::Class2<core::String>? nullableClass2, core::Function nonNullableFunction, core::Function? nullableFunction, (core::int) → core::int nonNullableFunctionType, (core::int) →? core::int nullableFunctionType, <T extends core::Object? = dynamic>(T%) → T% genericFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2, self::test::T3% undeterminedTypeVariable) → dynamic {
+  core::print("InstanceInvocation");
+  nonNullableClass1.{self::Class1::method}(0){(core::int) → core::double};
+  let final self::Class1? #t1 = nullableClass1 in #t1 == null ?{core::double?} null : #t1{self::Class1}.{self::Class1::method}(0){(core::int) → core::double};
+  core::print("InstanceGet calls");
+  nonNullableClass2.{self::Class2::nonNullableFunctionField}{core::Function}();
+  nonNullableClass2.{self::Class2::nonNullableFunctionGetter}{core::Function}();
+  nonNullableClass2.{self::Class2::nonNullableFunctionTypedField}{() → void}(){() → void};
+  nonNullableClass2.{self::Class2::nonNullableFunctionTypedGetter}{() → void}(){() → void};
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:68:42: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+ - 'Function' is from 'dart:core'.
+Try calling using ?.call instead.
+  nonNullableClass2.nullableFunctionField();
+                                         ^" in nonNullableClass2.{self::Class2::nullableFunctionField}{core::Function?}{<nullable>}.();
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:69:43: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+ - 'Function' is from 'dart:core'.
+Try calling using ?.call instead.
+  nonNullableClass2.nullableFunctionGetter();
+                                          ^" in nonNullableClass2.{self::Class2::nullableFunctionGetter}{core::Function?}{<nullable>}.();
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:70:47: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+Try calling using ?.call instead.
+  nonNullableClass2.nullableFunctionTypedField();
+                                              ^" in nonNullableClass2.{self::Class2::nullableFunctionTypedField}{() →? void}{<nullable>}.(){() →? void};
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:71:48: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+Try calling using ?.call instead.
+  nonNullableClass2.nullableFunctionTypedGetter();
+                                               ^" in nonNullableClass2.{self::Class2::nullableFunctionTypedGetter}{() →? void}{<nullable>}.(){() →? void};
+  let final self::Class2<core::String> #t6 = nonNullableClass2 in let final core::int #t7 = 0 in #t6.{self::Class2::nonNullableFunctionField}{core::Function}(#t7);
+  let final self::Class2<core::String> #t8 = nonNullableClass2 in let final core::int #t9 = 0 in #t8.{self::Class2::nonNullableFunctionGetter}{core::Function}(#t9);
+  let final self::Class2<core::String> #t10 = nonNullableClass2 in let final core::int #t11 = 0 in let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:74:50: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+  nonNullableClass2.nonNullableFunctionTypedField(0);
+                                                 ^" in #t10.{self::Class2::nonNullableFunctionTypedField}{() → void}{<inapplicable>}.(#t11);
+  let final self::Class2<core::String> #t13 = nonNullableClass2 in let final core::int #t14 = 0 in let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:75:51: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+  nonNullableClass2.nonNullableFunctionTypedGetter(0);
+                                                  ^" in #t13.{self::Class2::nonNullableFunctionTypedGetter}{() → void}{<inapplicable>}.(#t14);
+  core::print("InstanceInvocation (Nullable)");
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:78:18: Error: Method 'method' cannot be called on 'Class1?' because it is potentially null.
+ - 'Class1' is from 'pkg/front_end/testcases/none/method_invocation.dart'.
+Try calling using ?. instead.
+  nullableClass1.method(0);
+                 ^^^^^^" in nullableClass1.{self::Class1::method}{<nullable>}.(0){(core::int) → core::double};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.method(0);
+  let final dynamic #t17 = dyn in #t17 == null ?{dynamic} null : #t17{dynamic}.method(0);
+  dyn{dynamic}.toString(0);
+  const core::int call_dyn = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:84:28: Error: Method invocation is not a constant expression.
+  const int call_dyn = dyn.toString(0);
+                           ^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:84:28: Error: Method invocation is not a constant expression.
+  const int call_dyn = dyn.toString(0);
+                           ^^^^^^^^");
+  core::print("InstanceInvocation (Object)");
+  dyn.{core::Object::toString}(){() → core::String};
+  nullableClass1.{core::Object::toString}(){() → core::String};
+  nullableClass2.{core::Object::toString}(){() → core::String};
+  nullableFunction.{core::Object::toString}(){() → core::String};
+  nullableFunctionType.{core::Object::toString}(){() → core::String};
+  nullableTypeVariable1.{core::Object::toString}(){() → core::String};
+  nullableTypeVariable2.{core::Object::toString}(){() → core::String};
+  undeterminedTypeVariable.{core::Object::toString}(){() → core::String};
+  core::print("DynamicInvocation (Never)");
+  never{Never}.method(0);
+  never{Never}.toString();
+  core::print("DynamicInvocation (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:102:21: Error: The method 'unresolved' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/none/method_invocation.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'unresolved'.
+  nonNullableClass1.unresolved();
+                    ^^^^^^^^^^";
+  core::print("DynamicInvocation (Inapplicable)");
+  let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:105:27: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass1.method();
+                          ^" in nonNullableClass1.{self::Class1::method}{<inapplicable>}.(){() → invalid-type};
+  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:106:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableFunctionType();
+                         ^" in nonNullableFunctionType{<inapplicable>}.();
+  core::print("InstanceInvocation (generic)");
+  nonNullableClass2.{self::Class2::method}(0){(core::int) → core::String};
+  let final self::Class2<core::String>? #t20 = nullableClass2 in #t20 == null ?{core::String?} null : #t20{self::Class2<core::String>}.{self::Class2::method}(0){(core::int) → core::String};
+  nonNullableClass2.{self::Class2::call}(){() → core::String};
+  nonNullableClass2.{self::Class2::call}(){() → core::String};
+  core::print("FunctionInvocation");
+  nonNullableFunction(0);
+  nonNullableFunction(0);
+  let final core::Function? #t21 = nullableFunction in #t21 == null ?{dynamic} null : #t21{core::Function}(0);
+  nonNullableFunctionType(0){(core::int) → core::int};
+  nonNullableFunctionType(0){(core::int) → core::int};
+  let final (core::int) →? core::int #t22 = nullableFunctionType in #t22 == null ?{core::int?} null : #t22{(core::int) → core::int}(0){(core::int) → core::int};
+  genericFunctionType<core::int>(0){(core::int) → core::int};
+  genericFunctionType<core::num>(0){(core::num) → core::num};
+  core::num i = genericFunctionType<core::num>(0){(core::num) → core::num};
+  nonNullableTypeVariable1(0);
+  nonNullableTypeVariable1(0);
+  let final self::test::T1? #t23 = nullableTypeVariable1 in #t23 == null ?{dynamic} null : #t23{self::test::T1}(0);
+  nonNullableTypeVariable2(0){(core::int) → core::int};
+  nonNullableTypeVariable2(0){(core::int) → core::int};
+  let final self::test::T2? #t24 = nullableTypeVariable2 in #t24 == null ?{core::int?} null : #t24{self::test::T2}(0){(core::int) → core::int};
+  core::print("FunctionInvocation (Nullable)");
+  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:132:19: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+ - 'Function' is from 'dart:core'.
+Try calling using ?.call instead.
+  nullableFunction(0);
+                  ^" in nullableFunction{<nullable>}.(0);
+  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:133:20: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+ - 'Function' is from 'dart:core'.
+Try calling using ?. instead.
+  nullableFunction.call(0);
+                   ^^^^" in nullableFunction{<nullable>}.(0);
+  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:134:23: Error: Can't use an expression of type 'int Function(int)?' as a function because it's potentially null.
+Try calling using ?.call instead.
+  nullableFunctionType(0);
+                      ^" in nullableFunctionType{<nullable>}.(0){(core::int) →? core::int};
+  let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:135:24: Error: Method 'call' cannot be called on 'int Function(int)?' because it is potentially null.
+Try calling using ?. instead.
+  nullableFunctionType.call(0);
+                       ^^^^" in nullableFunctionType{<nullable>}.(0){(core::int) →? core::int};
+  core::print("DynamicInvocation (Invalid)");
+  (let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:138:27: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass1.method().method(0);
+                          ^" in nonNullableClass1.{self::Class1::method}{<inapplicable>}.(){() → invalid-type}){dynamic}.method(0);
+  core::print("LocalFunctionInvocation");
+  function localFunction() → core::int
+    return 42;
+  function genericLocalFunction<T extends core::Object? = dynamic>(T% t) → T%
+    return t;
+  localFunction(){() → core::int};
+  genericLocalFunction<core::int>(0){(core::int) → core::int};
+  genericLocalFunction<core::num>(0){(core::num) → core::num};
+  const core::int call_localFunction = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:147:34: Error: Not a constant expression.
+  const int call_localFunction = localFunction();
+                                 ^^^^^^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:147:34: Error: Not a constant expression.
+  const int call_localFunction = localFunction();
+                                 ^^^^^^^^^^^^^");
+  () → core::int f = () → core::int => 42;
+  const core::int call_f = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:152:22: Error: Not a constant expression.
+  const int call_f = f();
+                     ^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:152:22: Error: Not a constant expression.
+  const int call_f = f();
+                     ^");
+  core::print(#C4);
+  const core::bool equals = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:157:23: Error: Not a constant expression.
+  const bool equals = i == j;
+                      ^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:157:23: Error: Not a constant expression.
+  const bool equals = i == j;
+                      ^");
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 4
+  #C2 = 24
+  #C3 = 96
+  #C4 = false
+}
diff --git a/pkg/front_end/testcases/none/method_invocation.dart.textual_outline.expect b/pkg/front_end/testcases/none/method_invocation.dart.textual_outline.expect
new file mode 100644
index 0000000..b0ad48c
--- /dev/null
+++ b/pkg/front_end/testcases/none/method_invocation.dart.textual_outline.expect
@@ -0,0 +1,43 @@
+class Class1 {
+  double method(int o) => 0.5;
+}
+
+class Class2<T> {
+  T field;
+  Class2(this.field, this.nonNullableFunctionField,
+      this.nonNullableFunctionTypedField);
+  T call() => field;
+  T method(int o) => field;
+  Function nonNullableFunctionField;
+  Function get nonNullableFunctionGetter => nonNullableFunctionTypedField;
+  Function? nullableFunctionField;
+  Function? get nullableFunctionGetter => nonNullableFunctionTypedField;
+  void Function() nonNullableFunctionTypedField;
+  void Function() get nonNullableFunctionTypedGetter =>
+      nonNullableFunctionTypedField;
+  void Function()? nullableFunctionTypedField;
+  void Function()? get nullableFunctionTypedGetter =>
+      nonNullableFunctionTypedField;
+}
+
+const int i = 4;
+const int j = 24;
+const int k = i * j;
+test<T1 extends Function, T2 extends int Function(int), T3>(
+    Class1 nonNullableClass1,
+    Class1? nullableClass1,
+    dynamic dyn,
+    Never never,
+    Class2<String> nonNullableClass2,
+    Class2<String>? nullableClass2,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function(int) nonNullableFunctionType,
+    int Function(int)? nullableFunctionType,
+    T Function<T>(T) genericFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2,
+    T3 undeterminedTypeVariable) {}
+main() {}
diff --git a/pkg/front_end/testcases/none/method_invocation.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/none/method_invocation.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..05863eb
--- /dev/null
+++ b/pkg/front_end/testcases/none/method_invocation.dart.textual_outline_modelled.expect
@@ -0,0 +1,43 @@
+class Class1 {
+  double method(int o) => 0.5;
+}
+
+class Class2<T> {
+  Class2(this.field, this.nonNullableFunctionField,
+      this.nonNullableFunctionTypedField);
+  Function? get nullableFunctionGetter => nonNullableFunctionTypedField;
+  Function? nullableFunctionField;
+  Function get nonNullableFunctionGetter => nonNullableFunctionTypedField;
+  Function nonNullableFunctionField;
+  T call() => field;
+  T field;
+  T method(int o) => field;
+  void Function()? get nullableFunctionTypedGetter =>
+      nonNullableFunctionTypedField;
+  void Function()? nullableFunctionTypedField;
+  void Function() get nonNullableFunctionTypedGetter =>
+      nonNullableFunctionTypedField;
+  void Function() nonNullableFunctionTypedField;
+}
+
+const int i = 4;
+const int j = 24;
+const int k = i * j;
+main() {}
+test<T1 extends Function, T2 extends int Function(int), T3>(
+    Class1 nonNullableClass1,
+    Class1? nullableClass1,
+    dynamic dyn,
+    Never never,
+    Class2<String> nonNullableClass2,
+    Class2<String>? nullableClass2,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function(int) nonNullableFunctionType,
+    int Function(int)? nullableFunctionType,
+    T Function<T>(T) genericFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2,
+    T3 undeterminedTypeVariable) {}
diff --git a/pkg/front_end/testcases/none/method_invocation.dart.weak.expect b/pkg/front_end/testcases/none/method_invocation.dart.weak.expect
new file mode 100644
index 0000000..0e8d2d1e8
--- /dev/null
+++ b/pkg/front_end/testcases/none/method_invocation.dart.weak.expect
@@ -0,0 +1,297 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/method_invocation.dart:84:24: Error: Not a constant expression.
+//   const int call_dyn = dyn.toString(0);
+//                        ^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:84:28: Error: Method invocation is not a constant expression.
+//   const int call_dyn = dyn.toString(0);
+//                            ^^^^^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:147:34: Error: Not a constant expression.
+//   const int call_localFunction = localFunction();
+//                                  ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:152:22: Error: Not a constant expression.
+//   const int call_f = f();
+//                      ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:157:23: Error: Not a constant expression.
+//   const bool equals = i == j;
+//                       ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:68:42: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+//  - 'Function' is from 'dart:core'.
+// Try calling using ?.call instead.
+//   nonNullableClass2.nullableFunctionField();
+//                                          ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:69:43: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+//  - 'Function' is from 'dart:core'.
+// Try calling using ?.call instead.
+//   nonNullableClass2.nullableFunctionGetter();
+//                                           ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:70:47: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+// Try calling using ?.call instead.
+//   nonNullableClass2.nullableFunctionTypedField();
+//                                               ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:71:48: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+// Try calling using ?.call instead.
+//   nonNullableClass2.nullableFunctionTypedGetter();
+//                                                ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:74:50: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//   nonNullableClass2.nonNullableFunctionTypedField(0);
+//                                                  ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:75:51: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+//   nonNullableClass2.nonNullableFunctionTypedGetter(0);
+//                                                   ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:78:18: Error: Method 'method' cannot be called on 'Class1?' because it is potentially null.
+//  - 'Class1' is from 'pkg/front_end/testcases/none/method_invocation.dart'.
+// Try calling using ?. instead.
+//   nullableClass1.method(0);
+//                  ^^^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:102:21: Error: The method 'unresolved' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/none/method_invocation.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'unresolved'.
+//   nonNullableClass1.unresolved();
+//                     ^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:105:27: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass1.method();
+//                           ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:106:26: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableFunctionType();
+//                          ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:132:19: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+//  - 'Function' is from 'dart:core'.
+// Try calling using ?.call instead.
+//   nullableFunction(0);
+//                   ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:133:20: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+//  - 'Function' is from 'dart:core'.
+// Try calling using ?. instead.
+//   nullableFunction.call(0);
+//                    ^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:134:23: Error: Can't use an expression of type 'int Function(int)?' as a function because it's potentially null.
+// Try calling using ?.call instead.
+//   nullableFunctionType(0);
+//                       ^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:135:24: Error: Method 'call' cannot be called on 'int Function(int)?' because it is potentially null.
+// Try calling using ?. instead.
+//   nullableFunctionType.call(0);
+//                        ^^^^
+//
+// pkg/front_end/testcases/none/method_invocation.dart:138:27: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass1.method().method(0);
+//                           ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class1 extends core::Object {
+  synthetic constructor •() → self::Class1
+    : super core::Object::•()
+    ;
+  method method(core::int o) → core::double
+    return 0.5;
+}
+class Class2<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::Class2::T% field;
+  field core::Function nonNullableFunctionField;
+  field core::Function? nullableFunctionField = null;
+  field () → void nonNullableFunctionTypedField;
+  field () →? void nullableFunctionTypedField = null;
+  constructor •(self::Class2::T% field, core::Function nonNullableFunctionField, () → void nonNullableFunctionTypedField) → self::Class2<self::Class2::T%>
+    : self::Class2::field = field, self::Class2::nonNullableFunctionField = nonNullableFunctionField, self::Class2::nonNullableFunctionTypedField = nonNullableFunctionTypedField, super core::Object::•()
+    ;
+  method call() → self::Class2::T%
+    return this.{self::Class2::field}{self::Class2::T%};
+  method method(core::int o) → self::Class2::T%
+    return this.{self::Class2::field}{self::Class2::T%};
+  get nonNullableFunctionGetter() → core::Function
+    return this.{self::Class2::nonNullableFunctionTypedField}{() → void};
+  get nullableFunctionGetter() → core::Function?
+    return this.{self::Class2::nonNullableFunctionTypedField}{() → void};
+  get nonNullableFunctionTypedGetter() → () → void
+    return this.{self::Class2::nonNullableFunctionTypedField}{() → void};
+  get nullableFunctionTypedGetter() → () →? void
+    return this.{self::Class2::nonNullableFunctionTypedField}{() → void};
+}
+static const field core::int i = #C1;
+static const field core::int j = #C2;
+static const field core::int k = #C3;
+static method test<T1 extends core::Function = core::Function, T2 extends (core::int) → core::int = (core::int) → core::int, T3 extends core::Object? = dynamic>(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never, self::Class2<core::String> nonNullableClass2, self::Class2<core::String>? nullableClass2, core::Function nonNullableFunction, core::Function? nullableFunction, (core::int) → core::int nonNullableFunctionType, (core::int) →? core::int nullableFunctionType, <T extends core::Object? = dynamic>(T%) → T% genericFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2, self::test::T3% undeterminedTypeVariable) → dynamic {
+  core::print("InstanceInvocation");
+  nonNullableClass1.{self::Class1::method}(0){(core::int) → core::double};
+  let final self::Class1? #t1 = nullableClass1 in #t1 == null ?{core::double?} null : #t1{self::Class1}.{self::Class1::method}(0){(core::int) → core::double};
+  core::print("InstanceGet calls");
+  nonNullableClass2.{self::Class2::nonNullableFunctionField}{core::Function}();
+  nonNullableClass2.{self::Class2::nonNullableFunctionGetter}{core::Function}();
+  nonNullableClass2.{self::Class2::nonNullableFunctionTypedField}{() → void}(){() → void};
+  nonNullableClass2.{self::Class2::nonNullableFunctionTypedGetter}{() → void}(){() → void};
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:68:42: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+ - 'Function' is from 'dart:core'.
+Try calling using ?.call instead.
+  nonNullableClass2.nullableFunctionField();
+                                         ^" in nonNullableClass2.{self::Class2::nullableFunctionField}{core::Function?}{<nullable>}.();
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:69:43: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+ - 'Function' is from 'dart:core'.
+Try calling using ?.call instead.
+  nonNullableClass2.nullableFunctionGetter();
+                                          ^" in nonNullableClass2.{self::Class2::nullableFunctionGetter}{core::Function?}{<nullable>}.();
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:70:47: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+Try calling using ?.call instead.
+  nonNullableClass2.nullableFunctionTypedField();
+                                              ^" in nonNullableClass2.{self::Class2::nullableFunctionTypedField}{() →? void}{<nullable>}.(){() →? void};
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:71:48: Error: Can't use an expression of type 'void Function()?' as a function because it's potentially null.
+Try calling using ?.call instead.
+  nonNullableClass2.nullableFunctionTypedGetter();
+                                               ^" in nonNullableClass2.{self::Class2::nullableFunctionTypedGetter}{() →? void}{<nullable>}.(){() →? void};
+  let final self::Class2<core::String> #t6 = nonNullableClass2 in let final core::int #t7 = 0 in #t6.{self::Class2::nonNullableFunctionField}{core::Function}(#t7);
+  let final self::Class2<core::String> #t8 = nonNullableClass2 in let final core::int #t9 = 0 in #t8.{self::Class2::nonNullableFunctionGetter}{core::Function}(#t9);
+  let final self::Class2<core::String> #t10 = nonNullableClass2 in let final core::int #t11 = 0 in let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:74:50: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+  nonNullableClass2.nonNullableFunctionTypedField(0);
+                                                 ^" in #t10.{self::Class2::nonNullableFunctionTypedField}{() → void}{<inapplicable>}.(#t11);
+  let final self::Class2<core::String> #t13 = nonNullableClass2 in let final core::int #t14 = 0 in let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:75:51: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+  nonNullableClass2.nonNullableFunctionTypedGetter(0);
+                                                  ^" in #t13.{self::Class2::nonNullableFunctionTypedGetter}{() → void}{<inapplicable>}.(#t14);
+  core::print("InstanceInvocation (Nullable)");
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:78:18: Error: Method 'method' cannot be called on 'Class1?' because it is potentially null.
+ - 'Class1' is from 'pkg/front_end/testcases/none/method_invocation.dart'.
+Try calling using ?. instead.
+  nullableClass1.method(0);
+                 ^^^^^^" in nullableClass1.{self::Class1::method}{<nullable>}.(0){(core::int) → core::double};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.method(0);
+  let final dynamic #t17 = dyn in #t17 == null ?{dynamic} null : #t17{dynamic}.method(0);
+  dyn{dynamic}.toString(0);
+  const core::int call_dyn = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:84:28: Error: Method invocation is not a constant expression.
+  const int call_dyn = dyn.toString(0);
+                           ^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:84:28: Error: Method invocation is not a constant expression.
+  const int call_dyn = dyn.toString(0);
+                           ^^^^^^^^");
+  core::print("InstanceInvocation (Object)");
+  dyn.{core::Object::toString}(){() → core::String};
+  nullableClass1.{core::Object::toString}(){() → core::String};
+  nullableClass2.{core::Object::toString}(){() → core::String};
+  nullableFunction.{core::Object::toString}(){() → core::String};
+  nullableFunctionType.{core::Object::toString}(){() → core::String};
+  nullableTypeVariable1.{core::Object::toString}(){() → core::String};
+  nullableTypeVariable2.{core::Object::toString}(){() → core::String};
+  undeterminedTypeVariable.{core::Object::toString}(){() → core::String};
+  core::print("DynamicInvocation (Never)");
+  let final Never #t18 = (let final Never #t19 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.method(0) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t20 = (let final Never #t21 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  core::print("DynamicInvocation (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:102:21: Error: The method 'unresolved' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/none/method_invocation.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'unresolved'.
+  nonNullableClass1.unresolved();
+                    ^^^^^^^^^^";
+  core::print("DynamicInvocation (Inapplicable)");
+  let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:105:27: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass1.method();
+                          ^" in nonNullableClass1.{self::Class1::method}{<inapplicable>}.(){() → invalid-type};
+  let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:106:26: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableFunctionType();
+                         ^" in nonNullableFunctionType{<inapplicable>}.();
+  core::print("InstanceInvocation (generic)");
+  nonNullableClass2.{self::Class2::method}(0){(core::int) → core::String};
+  let final self::Class2<core::String>? #t24 = nullableClass2 in #t24 == null ?{core::String?} null : #t24{self::Class2<core::String>}.{self::Class2::method}(0){(core::int) → core::String};
+  nonNullableClass2.{self::Class2::call}(){() → core::String};
+  nonNullableClass2.{self::Class2::call}(){() → core::String};
+  core::print("FunctionInvocation");
+  nonNullableFunction(0);
+  nonNullableFunction(0);
+  let final core::Function? #t25 = nullableFunction in #t25 == null ?{dynamic} null : #t25{core::Function}(0);
+  nonNullableFunctionType(0){(core::int) → core::int};
+  nonNullableFunctionType(0){(core::int) → core::int};
+  let final (core::int) →? core::int #t26 = nullableFunctionType in #t26 == null ?{core::int?} null : #t26{(core::int) → core::int}(0){(core::int) → core::int};
+  genericFunctionType<core::int>(0){(core::int) → core::int};
+  genericFunctionType<core::num>(0){(core::num) → core::num};
+  core::num i = genericFunctionType<core::num>(0){(core::num) → core::num};
+  nonNullableTypeVariable1(0);
+  nonNullableTypeVariable1(0);
+  let final self::test::T1? #t27 = nullableTypeVariable1 in #t27 == null ?{dynamic} null : #t27{self::test::T1}(0);
+  nonNullableTypeVariable2(0){(core::int) → core::int};
+  nonNullableTypeVariable2(0){(core::int) → core::int};
+  let final self::test::T2? #t28 = nullableTypeVariable2 in #t28 == null ?{core::int?} null : #t28{self::test::T2}(0){(core::int) → core::int};
+  core::print("FunctionInvocation (Nullable)");
+  let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:132:19: Error: Can't use an expression of type 'Function?' as a function because it's potentially null.
+ - 'Function' is from 'dart:core'.
+Try calling using ?.call instead.
+  nullableFunction(0);
+                  ^" in nullableFunction{<nullable>}.(0);
+  let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:133:20: Error: Method 'call' cannot be called on 'Function?' because it is potentially null.
+ - 'Function' is from 'dart:core'.
+Try calling using ?. instead.
+  nullableFunction.call(0);
+                   ^^^^" in nullableFunction{<nullable>}.(0);
+  let final<BottomType> #t31 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:134:23: Error: Can't use an expression of type 'int Function(int)?' as a function because it's potentially null.
+Try calling using ?.call instead.
+  nullableFunctionType(0);
+                      ^" in nullableFunctionType{<nullable>}.(0){(core::int) →? core::int};
+  let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:135:24: Error: Method 'call' cannot be called on 'int Function(int)?' because it is potentially null.
+Try calling using ?. instead.
+  nullableFunctionType.call(0);
+                       ^^^^" in nullableFunctionType{<nullable>}.(0){(core::int) →? core::int};
+  core::print("DynamicInvocation (Invalid)");
+  (let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:138:27: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass1.method().method(0);
+                          ^" in nonNullableClass1.{self::Class1::method}{<inapplicable>}.(){() → invalid-type}){dynamic}.method(0);
+  core::print("LocalFunctionInvocation");
+  function localFunction() → core::int
+    return 42;
+  function genericLocalFunction<T extends core::Object? = dynamic>(T% t) → T%
+    return t;
+  localFunction(){() → core::int};
+  genericLocalFunction<core::int>(0){(core::int) → core::int};
+  genericLocalFunction<core::num>(0){(core::num) → core::num};
+  const core::int call_localFunction = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:147:34: Error: Not a constant expression.
+  const int call_localFunction = localFunction();
+                                 ^^^^^^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:147:34: Error: Not a constant expression.
+  const int call_localFunction = localFunction();
+                                 ^^^^^^^^^^^^^");
+  () → core::int f = () → core::int => 42;
+  const core::int call_f = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:152:22: Error: Not a constant expression.
+  const int call_f = f();
+                     ^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:152:22: Error: Not a constant expression.
+  const int call_f = f();
+                     ^");
+  core::print(#C4);
+  const core::bool equals = invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:157:23: Error: Not a constant expression.
+  const bool equals = i == j;
+                      ^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/method_invocation.dart:157:23: Error: Not a constant expression.
+  const bool equals = i == j;
+                      ^");
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = 4
+  #C2 = 24
+  #C3 = 96
+  #C4 = false
+}
diff --git a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.outline.expect b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.outline.expect
index e9e3bdd..b6f679a 100644
--- a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.outline.expect
+++ b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.outline.expect
@@ -32,7 +32,7 @@
     : super mai::SuperClass::•()
     ;
   forwarding-stub method method(covariant core::num i) → void
-    return super.{mai::SuperClass::method}(i);
+    return super.{mai::Mixin::method}(i);
 }
 class Class extends mai::_Class&SuperClass&Mixin {
   synthetic constructor •() → mai::Class
diff --git a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.strong.expect b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.strong.expect
index cd8c81e..940de1e 100644
--- a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.strong.expect
+++ b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.strong.expect
@@ -34,7 +34,7 @@
     : super mai::SuperClass::•()
     ;
   forwarding-stub method method(covariant core::num i) → void
-    return super.{mai::SuperClass::method}(i);
+    return super.{mai::Mixin::method}(i);
 }
 class Class extends mai::_Class&SuperClass&Mixin {
   synthetic constructor •() → mai::Class
diff --git a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.strong.transformed.expect b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.strong.transformed.expect
index cd8c81e..940de1e 100644
--- a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.strong.transformed.expect
@@ -34,7 +34,7 @@
     : super mai::SuperClass::•()
     ;
   forwarding-stub method method(covariant core::num i) → void
-    return super.{mai::SuperClass::method}(i);
+    return super.{mai::Mixin::method}(i);
 }
 class Class extends mai::_Class&SuperClass&Mixin {
   synthetic constructor •() → mai::Class
diff --git a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.weak.expect b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.weak.expect
index cd8c81e..940de1e 100644
--- a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.weak.expect
+++ b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.weak.expect
@@ -34,7 +34,7 @@
     : super mai::SuperClass::•()
     ;
   forwarding-stub method method(covariant core::num i) → void
-    return super.{mai::SuperClass::method}(i);
+    return super.{mai::Mixin::method}(i);
 }
 class Class extends mai::_Class&SuperClass&Mixin {
   synthetic constructor •() → mai::Class
diff --git a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.weak.transformed.expect b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.weak.transformed.expect
index cd8c81e..940de1e 100644
--- a/pkg/front_end/testcases/none/mixin_application_declares/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/none/mixin_application_declares/main.dart.weak.transformed.expect
@@ -34,7 +34,7 @@
     : super mai::SuperClass::•()
     ;
   forwarding-stub method method(covariant core::num i) → void
-    return super.{mai::SuperClass::method}(i);
+    return super.{mai::Mixin::method}(i);
 }
 class Class extends mai::_Class&SuperClass&Mixin {
   synthetic constructor •() → mai::Class
diff --git a/pkg/front_end/testcases/none/mixin_covariant.dart.outline.expect b/pkg/front_end/testcases/none/mixin_covariant.dart.outline.expect
index a0757dd..d858827 100644
--- a/pkg/front_end/testcases/none/mixin_covariant.dart.outline.expect
+++ b/pkg/front_end/testcases/none/mixin_covariant.dart.outline.expect
@@ -30,11 +30,14 @@
   synthetic constructor •() → self::_Class&Superclass&Mixin
     : super self::Superclass::•()
     ;
-  abstract forwarding-stub method method2(covariant core::num argument1, core::num argument2) → core::String;
+  mixin-super-stub method method1(core::num argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method1}(argument1, argument2);
+  mixin-super-stub method method2(covariant core::int argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method2}(argument1, argument2);
   forwarding-stub method method3(core::num argument1, covariant core::num argument2) → core::String
-    return super.{self::Superclass::method3}(argument1, argument2);
-  forwarding-stub method method4(covariant core::num argument1, covariant core::num argument2) → core::String
-    return super.{self::Superclass::method4}(argument1, argument2);
+    return super.{self::Mixin::method3}(argument1, argument2);
+  forwarding-stub method method4(covariant core::int argument1, covariant core::int argument2) → core::String
+    return super.{self::Mixin::method4}(argument1, argument2);
 }
 class Class extends self::_Class&Superclass&Mixin {
   synthetic constructor •() → self::Class
diff --git a/pkg/front_end/testcases/none/mixin_covariant.dart.strong.expect b/pkg/front_end/testcases/none/mixin_covariant.dart.strong.expect
index 412bbf0..be28553 100644
--- a/pkg/front_end/testcases/none/mixin_covariant.dart.strong.expect
+++ b/pkg/front_end/testcases/none/mixin_covariant.dart.strong.expect
@@ -32,11 +32,14 @@
   synthetic constructor •() → self::_Class&Superclass&Mixin
     : super self::Superclass::•()
     ;
-  abstract forwarding-stub method method2(covariant core::num argument1, core::num argument2) → core::String;
+  mixin-super-stub method method1(core::num argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method1}(argument1, argument2);
+  mixin-super-stub method method2(covariant core::int argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method2}(argument1, argument2);
   forwarding-stub method method3(core::num argument1, covariant core::num argument2) → core::String
-    return super.{self::Superclass::method3}(argument1, argument2);
-  forwarding-stub method method4(covariant core::num argument1, covariant core::num argument2) → core::String
-    return super.{self::Superclass::method4}(argument1, argument2);
+    return super.{self::Mixin::method3}(argument1, argument2);
+  forwarding-stub method method4(covariant core::int argument1, covariant core::int argument2) → core::String
+    return super.{self::Mixin::method4}(argument1, argument2);
 }
 class Class extends self::_Class&Superclass&Mixin {
   synthetic constructor •() → self::Class
@@ -45,29 +48,29 @@
 }
 static method main() → dynamic {
   self::Class c = new self::Class::•();
-  self::expect("Mixin", c.{self::Mixin::method1}(0, 1));
-  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method2}(0, 1));
-  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method3}(0, 1));
-  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method4}(0, 1));
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method1}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method2}(0, 1){(core::int, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method3}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method4}(0, 1){(core::int, core::int) → core::String});
   self::Superclass s = c;
-  self::expect("Mixin", s.{self::Superclass::method1}(0.5, 1.5));
-  self::throws(() → void => s.{self::Superclass::method2}(0.5, 1.5));
-  self::expect("Mixin", s.{self::Superclass::method3}(0.5, 1));
-  self::throws(() → void => s.{self::Superclass::method4}(0.5, 1));
-  self::expect("Mixin", s.{self::Superclass::method4}(1, 0.5));
+  self::expect("Mixin", s.{self::Superclass::method1}(0.5, 1.5){(core::num, core::num) → core::String});
+  self::throws(() → void => s.{self::Superclass::method2}(0.5, 1.5){(core::num, core::num) → core::String});
+  self::expect("Mixin", s.{self::Superclass::method3}(0.5, 1){(core::num, core::int) → core::String});
+  self::throws(() → void => s.{self::Superclass::method4}(0.5, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", s.{self::Superclass::method4}(1, 0.5){(core::num, core::num) → core::String});
   self::Mixin m = c;
-  self::expect("Mixin", m.{self::Mixin::method1}(0, 1));
-  self::expect("Mixin", m.{self::Mixin::method2}(0, 1));
-  self::expect("Mixin", m.{self::Mixin::method3}(0, 1));
-  self::expect("Mixin", m.{self::Mixin::method4}(0, 1));
+  self::expect("Mixin", m.{self::Mixin::method1}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method2}(0, 1){(core::int, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method3}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method4}(0, 1){(core::int, core::int) → core::String});
 }
 static method expect(dynamic expected, dynamic actual) → void {
-  if(!expected.{core::Object::==}(actual))
+  if(expected !={core::Object::==}{(core::Object) → core::bool} actual)
     throw "Expected ${expected}, actual ${actual}";
 }
 static method throws(() → void f) → void {
   try {
-    f.call();
+    f(){() → void};
   }
   on core::Object catch(final core::Object _) {
     return;
diff --git a/pkg/front_end/testcases/none/mixin_covariant.dart.strong.transformed.expect b/pkg/front_end/testcases/none/mixin_covariant.dart.strong.transformed.expect
new file mode 100644
index 0000000..be28553
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_covariant.dart.strong.transformed.expect
@@ -0,0 +1,79 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass
+    : super core::Object::•()
+    ;
+  method method1(core::num argument1, core::num argument2) → core::String
+    return "Superclass";
+  method method2(core::num argument1, core::num argument2) → core::String
+    return "Superclass";
+  method method3(core::num argument1, covariant core::int argument2) → core::String
+    return "Superclass";
+  method method4(core::num argument1, covariant core::num argument2) → core::String
+    return "Superclass";
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method method1(core::num argument1, core::num argument2) → core::String
+    return "Mixin";
+  method method2(covariant core::int argument1, core::num argument2) → core::String
+    return "Mixin";
+  method method3(core::num argument1, core::num argument2) → core::String
+    return "Mixin";
+  method method4(covariant core::int argument1, core::int argument2) → core::String
+    return "Mixin";
+}
+abstract class _Class&Superclass&Mixin = self::Superclass with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Class&Superclass&Mixin
+    : super self::Superclass::•()
+    ;
+  mixin-super-stub method method1(core::num argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method1}(argument1, argument2);
+  mixin-super-stub method method2(covariant core::int argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method2}(argument1, argument2);
+  forwarding-stub method method3(core::num argument1, covariant core::num argument2) → core::String
+    return super.{self::Mixin::method3}(argument1, argument2);
+  forwarding-stub method method4(covariant core::int argument1, covariant core::int argument2) → core::String
+    return super.{self::Mixin::method4}(argument1, argument2);
+}
+class Class extends self::_Class&Superclass&Mixin {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Superclass&Mixin::•()
+    ;
+}
+static method main() → dynamic {
+  self::Class c = new self::Class::•();
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method1}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method2}(0, 1){(core::int, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method3}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method4}(0, 1){(core::int, core::int) → core::String});
+  self::Superclass s = c;
+  self::expect("Mixin", s.{self::Superclass::method1}(0.5, 1.5){(core::num, core::num) → core::String});
+  self::throws(() → void => s.{self::Superclass::method2}(0.5, 1.5){(core::num, core::num) → core::String});
+  self::expect("Mixin", s.{self::Superclass::method3}(0.5, 1){(core::num, core::int) → core::String});
+  self::throws(() → void => s.{self::Superclass::method4}(0.5, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", s.{self::Superclass::method4}(1, 0.5){(core::num, core::num) → core::String});
+  self::Mixin m = c;
+  self::expect("Mixin", m.{self::Mixin::method1}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method2}(0, 1){(core::int, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method3}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method4}(0, 1){(core::int, core::int) → core::String});
+}
+static method expect(dynamic expected, dynamic actual) → void {
+  if(expected !={core::Object::==}{(core::Object) → core::bool} actual)
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → void {
+  try {
+    f(){() → void};
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Expected exception";
+}
diff --git a/pkg/front_end/testcases/none/mixin_covariant.dart.weak.expect b/pkg/front_end/testcases/none/mixin_covariant.dart.weak.expect
index 412bbf0..be28553 100644
--- a/pkg/front_end/testcases/none/mixin_covariant.dart.weak.expect
+++ b/pkg/front_end/testcases/none/mixin_covariant.dart.weak.expect
@@ -32,11 +32,14 @@
   synthetic constructor •() → self::_Class&Superclass&Mixin
     : super self::Superclass::•()
     ;
-  abstract forwarding-stub method method2(covariant core::num argument1, core::num argument2) → core::String;
+  mixin-super-stub method method1(core::num argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method1}(argument1, argument2);
+  mixin-super-stub method method2(covariant core::int argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method2}(argument1, argument2);
   forwarding-stub method method3(core::num argument1, covariant core::num argument2) → core::String
-    return super.{self::Superclass::method3}(argument1, argument2);
-  forwarding-stub method method4(covariant core::num argument1, covariant core::num argument2) → core::String
-    return super.{self::Superclass::method4}(argument1, argument2);
+    return super.{self::Mixin::method3}(argument1, argument2);
+  forwarding-stub method method4(covariant core::int argument1, covariant core::int argument2) → core::String
+    return super.{self::Mixin::method4}(argument1, argument2);
 }
 class Class extends self::_Class&Superclass&Mixin {
   synthetic constructor •() → self::Class
@@ -45,29 +48,29 @@
 }
 static method main() → dynamic {
   self::Class c = new self::Class::•();
-  self::expect("Mixin", c.{self::Mixin::method1}(0, 1));
-  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method2}(0, 1));
-  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method3}(0, 1));
-  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method4}(0, 1));
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method1}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method2}(0, 1){(core::int, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method3}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method4}(0, 1){(core::int, core::int) → core::String});
   self::Superclass s = c;
-  self::expect("Mixin", s.{self::Superclass::method1}(0.5, 1.5));
-  self::throws(() → void => s.{self::Superclass::method2}(0.5, 1.5));
-  self::expect("Mixin", s.{self::Superclass::method3}(0.5, 1));
-  self::throws(() → void => s.{self::Superclass::method4}(0.5, 1));
-  self::expect("Mixin", s.{self::Superclass::method4}(1, 0.5));
+  self::expect("Mixin", s.{self::Superclass::method1}(0.5, 1.5){(core::num, core::num) → core::String});
+  self::throws(() → void => s.{self::Superclass::method2}(0.5, 1.5){(core::num, core::num) → core::String});
+  self::expect("Mixin", s.{self::Superclass::method3}(0.5, 1){(core::num, core::int) → core::String});
+  self::throws(() → void => s.{self::Superclass::method4}(0.5, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", s.{self::Superclass::method4}(1, 0.5){(core::num, core::num) → core::String});
   self::Mixin m = c;
-  self::expect("Mixin", m.{self::Mixin::method1}(0, 1));
-  self::expect("Mixin", m.{self::Mixin::method2}(0, 1));
-  self::expect("Mixin", m.{self::Mixin::method3}(0, 1));
-  self::expect("Mixin", m.{self::Mixin::method4}(0, 1));
+  self::expect("Mixin", m.{self::Mixin::method1}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method2}(0, 1){(core::int, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method3}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method4}(0, 1){(core::int, core::int) → core::String});
 }
 static method expect(dynamic expected, dynamic actual) → void {
-  if(!expected.{core::Object::==}(actual))
+  if(expected !={core::Object::==}{(core::Object) → core::bool} actual)
     throw "Expected ${expected}, actual ${actual}";
 }
 static method throws(() → void f) → void {
   try {
-    f.call();
+    f(){() → void};
   }
   on core::Object catch(final core::Object _) {
     return;
diff --git a/pkg/front_end/testcases/none/mixin_covariant.dart.weak.transformed.expect b/pkg/front_end/testcases/none/mixin_covariant.dart.weak.transformed.expect
new file mode 100644
index 0000000..be28553
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_covariant.dart.weak.transformed.expect
@@ -0,0 +1,79 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass
+    : super core::Object::•()
+    ;
+  method method1(core::num argument1, core::num argument2) → core::String
+    return "Superclass";
+  method method2(core::num argument1, core::num argument2) → core::String
+    return "Superclass";
+  method method3(core::num argument1, covariant core::int argument2) → core::String
+    return "Superclass";
+  method method4(core::num argument1, covariant core::num argument2) → core::String
+    return "Superclass";
+}
+class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin
+    : super core::Object::•()
+    ;
+  method method1(core::num argument1, core::num argument2) → core::String
+    return "Mixin";
+  method method2(covariant core::int argument1, core::num argument2) → core::String
+    return "Mixin";
+  method method3(core::num argument1, core::num argument2) → core::String
+    return "Mixin";
+  method method4(covariant core::int argument1, core::int argument2) → core::String
+    return "Mixin";
+}
+abstract class _Class&Superclass&Mixin = self::Superclass with self::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Class&Superclass&Mixin
+    : super self::Superclass::•()
+    ;
+  mixin-super-stub method method1(core::num argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method1}(argument1, argument2);
+  mixin-super-stub method method2(covariant core::int argument1, core::num argument2) → core::String
+    return super.{self::Mixin::method2}(argument1, argument2);
+  forwarding-stub method method3(core::num argument1, covariant core::num argument2) → core::String
+    return super.{self::Mixin::method3}(argument1, argument2);
+  forwarding-stub method method4(covariant core::int argument1, covariant core::int argument2) → core::String
+    return super.{self::Mixin::method4}(argument1, argument2);
+}
+class Class extends self::_Class&Superclass&Mixin {
+  synthetic constructor •() → self::Class
+    : super self::_Class&Superclass&Mixin::•()
+    ;
+}
+static method main() → dynamic {
+  self::Class c = new self::Class::•();
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method1}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method2}(0, 1){(core::int, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method3}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", c.{self::_Class&Superclass&Mixin::method4}(0, 1){(core::int, core::int) → core::String});
+  self::Superclass s = c;
+  self::expect("Mixin", s.{self::Superclass::method1}(0.5, 1.5){(core::num, core::num) → core::String});
+  self::throws(() → void => s.{self::Superclass::method2}(0.5, 1.5){(core::num, core::num) → core::String});
+  self::expect("Mixin", s.{self::Superclass::method3}(0.5, 1){(core::num, core::int) → core::String});
+  self::throws(() → void => s.{self::Superclass::method4}(0.5, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", s.{self::Superclass::method4}(1, 0.5){(core::num, core::num) → core::String});
+  self::Mixin m = c;
+  self::expect("Mixin", m.{self::Mixin::method1}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method2}(0, 1){(core::int, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method3}(0, 1){(core::num, core::num) → core::String});
+  self::expect("Mixin", m.{self::Mixin::method4}(0, 1){(core::int, core::int) → core::String});
+}
+static method expect(dynamic expected, dynamic actual) → void {
+  if(expected !={core::Object::==}{(core::Object) → core::bool} actual)
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → void {
+  try {
+    f(){() → void};
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Expected exception";
+}
diff --git a/pkg/front_end/testcases/none/mixin_super.dart b/pkg/front_end/testcases/none/mixin_super.dart
new file mode 100644
index 0000000..5b90234
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_super.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.md file.
+
+mixin Diagnosticable {
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
+}
+
+class DiagnosticPropertiesBuilder {}
+
+abstract class PointerEvent with Diagnosticable {}
+
+abstract class PointerSignalEvent extends PointerEvent {}
+
+mixin _PointerEventDescription on PointerEvent {
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+  }
+}
+mixin _CopyPointerScrollEvent on PointerEvent {}
+
+class PointerScrollEvent extends PointerSignalEvent
+    with _PointerEventDescription, _CopyPointerScrollEvent {
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+  }
+}
+
+main() {
+  new PointerScrollEvent()
+      .debugFillProperties(new DiagnosticPropertiesBuilder());
+}
diff --git a/pkg/front_end/testcases/none/mixin_super.dart.outline.expect b/pkg/front_end/testcases/none/mixin_super.dart.outline.expect
new file mode 100644
index 0000000..6e052ce
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_super.dart.outline.expect
@@ -0,0 +1,61 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Diagnosticable extends core::Object /*isMixinDeclaration*/  {
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    ;
+}
+class DiagnosticPropertiesBuilder extends core::Object {
+  synthetic constructor •() → self::DiagnosticPropertiesBuilder
+    ;
+}
+abstract class _PointerEvent&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_PointerEvent&Object&Diagnosticable
+    : super core::Object::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::Diagnosticable::debugFillProperties}(properties);
+}
+abstract class PointerEvent extends self::_PointerEvent&Object&Diagnosticable {
+  synthetic constructor •() → self::PointerEvent
+    ;
+}
+abstract class PointerSignalEvent extends self::PointerEvent {
+  synthetic constructor •() → self::PointerSignalEvent
+    ;
+}
+abstract class _PointerEventDescription extends self::PointerEvent /*isMixinDeclaration*/  {
+  @core::override
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    ;
+}
+abstract class _CopyPointerScrollEvent extends self::PointerEvent /*isMixinDeclaration*/  {
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription = self::PointerSignalEvent with self::_PointerEventDescription /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription
+    : super self::PointerSignalEvent::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::_PointerEventDescription::debugFillProperties}(properties);
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent = self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription with self::_CopyPointerScrollEvent /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::•()
+    ;
+}
+class PointerScrollEvent extends self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent {
+  synthetic constructor •() → self::PointerScrollEvent
+    ;
+  @core::override
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    ;
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///mixin_super.dart:16:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///mixin_super.dart:25:4 -> InstanceConstant(const _Override{})
+Extra constant evaluation: evaluated: 6, effectively constant: 2
diff --git a/pkg/front_end/testcases/none/mixin_super.dart.strong.expect b/pkg/front_end/testcases/none/mixin_super.dart.strong.expect
new file mode 100644
index 0000000..9929e69
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_super.dart.strong.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Diagnosticable extends core::Object /*isMixinDeclaration*/  {
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {}
+}
+class DiagnosticPropertiesBuilder extends core::Object {
+  synthetic constructor •() → self::DiagnosticPropertiesBuilder
+    : super core::Object::•()
+    ;
+}
+abstract class _PointerEvent&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_PointerEvent&Object&Diagnosticable
+    : super core::Object::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::Diagnosticable::debugFillProperties}(properties);
+}
+abstract class PointerEvent extends self::_PointerEvent&Object&Diagnosticable {
+  synthetic constructor •() → self::PointerEvent
+    : super self::_PointerEvent&Object&Diagnosticable::•()
+    ;
+}
+abstract class PointerSignalEvent extends self::PointerEvent {
+  synthetic constructor •() → self::PointerSignalEvent
+    : super self::PointerEvent::•()
+    ;
+}
+abstract class _PointerEventDescription extends self::PointerEvent /*isMixinDeclaration*/  {
+  @#C1
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {
+    super.{self::_PointerEvent&Object&Diagnosticable::debugFillProperties}(properties);
+  }
+}
+abstract class _CopyPointerScrollEvent extends self::PointerEvent /*isMixinDeclaration*/  {
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription = self::PointerSignalEvent with self::_PointerEventDescription /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription
+    : super self::PointerSignalEvent::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::_PointerEventDescription::debugFillProperties}(properties);
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent = self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription with self::_CopyPointerScrollEvent /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::•()
+    ;
+}
+class PointerScrollEvent extends self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent {
+  synthetic constructor •() → self::PointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent::•()
+    ;
+  @#C1
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {
+    super.{self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::debugFillProperties}(properties);
+  }
+}
+static method main() → dynamic {
+  new self::PointerScrollEvent::•().{self::PointerScrollEvent::debugFillProperties}(new self::DiagnosticPropertiesBuilder::•()){(self::DiagnosticPropertiesBuilder) → void};
+}
+
+constants  {
+  #C1 = core::_Override {}
+}
diff --git a/pkg/front_end/testcases/none/mixin_super.dart.strong.transformed.expect b/pkg/front_end/testcases/none/mixin_super.dart.strong.transformed.expect
new file mode 100644
index 0000000..9929e69
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_super.dart.strong.transformed.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Diagnosticable extends core::Object /*isMixinDeclaration*/  {
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {}
+}
+class DiagnosticPropertiesBuilder extends core::Object {
+  synthetic constructor •() → self::DiagnosticPropertiesBuilder
+    : super core::Object::•()
+    ;
+}
+abstract class _PointerEvent&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_PointerEvent&Object&Diagnosticable
+    : super core::Object::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::Diagnosticable::debugFillProperties}(properties);
+}
+abstract class PointerEvent extends self::_PointerEvent&Object&Diagnosticable {
+  synthetic constructor •() → self::PointerEvent
+    : super self::_PointerEvent&Object&Diagnosticable::•()
+    ;
+}
+abstract class PointerSignalEvent extends self::PointerEvent {
+  synthetic constructor •() → self::PointerSignalEvent
+    : super self::PointerEvent::•()
+    ;
+}
+abstract class _PointerEventDescription extends self::PointerEvent /*isMixinDeclaration*/  {
+  @#C1
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {
+    super.{self::_PointerEvent&Object&Diagnosticable::debugFillProperties}(properties);
+  }
+}
+abstract class _CopyPointerScrollEvent extends self::PointerEvent /*isMixinDeclaration*/  {
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription = self::PointerSignalEvent with self::_PointerEventDescription /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription
+    : super self::PointerSignalEvent::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::_PointerEventDescription::debugFillProperties}(properties);
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent = self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription with self::_CopyPointerScrollEvent /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::•()
+    ;
+}
+class PointerScrollEvent extends self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent {
+  synthetic constructor •() → self::PointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent::•()
+    ;
+  @#C1
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {
+    super.{self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::debugFillProperties}(properties);
+  }
+}
+static method main() → dynamic {
+  new self::PointerScrollEvent::•().{self::PointerScrollEvent::debugFillProperties}(new self::DiagnosticPropertiesBuilder::•()){(self::DiagnosticPropertiesBuilder) → void};
+}
+
+constants  {
+  #C1 = core::_Override {}
+}
diff --git a/pkg/front_end/testcases/none/mixin_super.dart.textual_outline.expect b/pkg/front_end/testcases/none/mixin_super.dart.textual_outline.expect
new file mode 100644
index 0000000..dd59658
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_super.dart.textual_outline.expect
@@ -0,0 +1,23 @@
+mixin Diagnosticable {
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
+}
+
+class DiagnosticPropertiesBuilder {}
+
+abstract class PointerEvent with Diagnosticable {}
+
+abstract class PointerSignalEvent extends PointerEvent {}
+
+mixin _PointerEventDescription on PointerEvent {
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
+}
+mixin _CopyPointerScrollEvent on PointerEvent {}
+
+class PointerScrollEvent extends PointerSignalEvent
+    with _PointerEventDescription, _CopyPointerScrollEvent {
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/none/mixin_super.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/none/mixin_super.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e011475
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_super.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+abstract class PointerEvent with Diagnosticable {}
+
+abstract class PointerSignalEvent extends PointerEvent {}
+
+class DiagnosticPropertiesBuilder {}
+
+class PointerScrollEvent extends PointerSignalEvent
+    with _PointerEventDescription, _CopyPointerScrollEvent {
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
+}
+
+main() {}
+mixin Diagnosticable {
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
+}
+mixin _CopyPointerScrollEvent on PointerEvent {}
+mixin _PointerEventDescription on PointerEvent {
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
+}
diff --git a/pkg/front_end/testcases/none/mixin_super.dart.weak.expect b/pkg/front_end/testcases/none/mixin_super.dart.weak.expect
new file mode 100644
index 0000000..9929e69
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_super.dart.weak.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Diagnosticable extends core::Object /*isMixinDeclaration*/  {
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {}
+}
+class DiagnosticPropertiesBuilder extends core::Object {
+  synthetic constructor •() → self::DiagnosticPropertiesBuilder
+    : super core::Object::•()
+    ;
+}
+abstract class _PointerEvent&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_PointerEvent&Object&Diagnosticable
+    : super core::Object::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::Diagnosticable::debugFillProperties}(properties);
+}
+abstract class PointerEvent extends self::_PointerEvent&Object&Diagnosticable {
+  synthetic constructor •() → self::PointerEvent
+    : super self::_PointerEvent&Object&Diagnosticable::•()
+    ;
+}
+abstract class PointerSignalEvent extends self::PointerEvent {
+  synthetic constructor •() → self::PointerSignalEvent
+    : super self::PointerEvent::•()
+    ;
+}
+abstract class _PointerEventDescription extends self::PointerEvent /*isMixinDeclaration*/  {
+  @#C1
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {
+    super.{self::_PointerEvent&Object&Diagnosticable::debugFillProperties}(properties);
+  }
+}
+abstract class _CopyPointerScrollEvent extends self::PointerEvent /*isMixinDeclaration*/  {
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription = self::PointerSignalEvent with self::_PointerEventDescription /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription
+    : super self::PointerSignalEvent::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::_PointerEventDescription::debugFillProperties}(properties);
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent = self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription with self::_CopyPointerScrollEvent /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::•()
+    ;
+}
+class PointerScrollEvent extends self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent {
+  synthetic constructor •() → self::PointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent::•()
+    ;
+  @#C1
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {
+    super.{self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::debugFillProperties}(properties);
+  }
+}
+static method main() → dynamic {
+  new self::PointerScrollEvent::•().{self::PointerScrollEvent::debugFillProperties}(new self::DiagnosticPropertiesBuilder::•()){(self::DiagnosticPropertiesBuilder) → void};
+}
+
+constants  {
+  #C1 = core::_Override {}
+}
diff --git a/pkg/front_end/testcases/none/mixin_super.dart.weak.transformed.expect b/pkg/front_end/testcases/none/mixin_super.dart.weak.transformed.expect
new file mode 100644
index 0000000..9929e69
--- /dev/null
+++ b/pkg/front_end/testcases/none/mixin_super.dart.weak.transformed.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Diagnosticable extends core::Object /*isMixinDeclaration*/  {
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {}
+}
+class DiagnosticPropertiesBuilder extends core::Object {
+  synthetic constructor •() → self::DiagnosticPropertiesBuilder
+    : super core::Object::•()
+    ;
+}
+abstract class _PointerEvent&Object&Diagnosticable = core::Object with self::Diagnosticable /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_PointerEvent&Object&Diagnosticable
+    : super core::Object::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::Diagnosticable::debugFillProperties}(properties);
+}
+abstract class PointerEvent extends self::_PointerEvent&Object&Diagnosticable {
+  synthetic constructor •() → self::PointerEvent
+    : super self::_PointerEvent&Object&Diagnosticable::•()
+    ;
+}
+abstract class PointerSignalEvent extends self::PointerEvent {
+  synthetic constructor •() → self::PointerSignalEvent
+    : super self::PointerEvent::•()
+    ;
+}
+abstract class _PointerEventDescription extends self::PointerEvent /*isMixinDeclaration*/  {
+  @#C1
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {
+    super.{self::_PointerEvent&Object&Diagnosticable::debugFillProperties}(properties);
+  }
+}
+abstract class _CopyPointerScrollEvent extends self::PointerEvent /*isMixinDeclaration*/  {
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription = self::PointerSignalEvent with self::_PointerEventDescription /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription
+    : super self::PointerSignalEvent::•()
+    ;
+  mixin-super-stub method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void
+    return super.{self::_PointerEventDescription::debugFillProperties}(properties);
+}
+abstract class _PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent = self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription with self::_CopyPointerScrollEvent /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::•()
+    ;
+}
+class PointerScrollEvent extends self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent {
+  synthetic constructor •() → self::PointerScrollEvent
+    : super self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription&_CopyPointerScrollEvent::•()
+    ;
+  @#C1
+  method debugFillProperties(self::DiagnosticPropertiesBuilder properties) → void {
+    super.{self::_PointerScrollEvent&PointerSignalEvent&_PointerEventDescription::debugFillProperties}(properties);
+  }
+}
+static method main() → dynamic {
+  new self::PointerScrollEvent::•().{self::PointerScrollEvent::debugFillProperties}(new self::DiagnosticPropertiesBuilder::•()){(self::DiagnosticPropertiesBuilder) → void};
+}
+
+constants  {
+  #C1 = core::_Override {}
+}
diff --git a/pkg/front_end/testcases/none/operator.dart b/pkg/front_end/testcases/none/operator.dart
new file mode 100644
index 0000000..624663e
--- /dev/null
+++ b/pkg/front_end/testcases/none/operator.dart
@@ -0,0 +1,132 @@
+// 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.md file.
+
+class Class<T> {
+  Class<T> operator +(Class<T> other) => other;
+
+  Class<T> operator -() => this;
+
+  Class<T> operator [](int index) => this;
+
+  operator []=(int index, Class<T> value) {}
+
+  int method(double o) => 42;
+}
+
+add(num n, int i, double d, Class<String> c, dynamic dyn, Never never,
+    String string) {
+  print('InstanceInvocation');
+  n + n;
+  n + i;
+  n + d;
+  n + dyn;
+
+  print('InstanceInvocation');
+  i + n;
+  i + i;
+  i + d;
+  i + dyn;
+
+  print('InstanceInvocation');
+  d + n;
+  d + i;
+  d + d;
+  i + dyn;
+
+  print('InstanceInvocation');
+  c + c;
+  c + dyn;
+
+  print('DynamicInvocation');
+  dyn + n;
+
+  print('DynamicInvocation (Never)');
+  never + n;
+
+  print('DynamicInvocation (Invalid)');
+  string - 42;
+}
+
+unaryMinus(num n, int i, double d, Class<String> c, dynamic dyn, Never never,
+    String string) {
+  print('InstanceInvocation');
+  -n;
+  -i;
+  -d;
+  -c;
+
+  print('DynamicInvocation');
+  -dyn;
+
+  print('DynamicInvocation (Never)');
+  -never;
+
+  print('DynamicInvocation (Invalid)');
+  -c.method();
+
+  print('DynamicInvocation (Unresolved)');
+  -string;
+}
+
+indexGet(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never, String string) {
+  print('InstanceInvocation');
+  list[0];
+  map['foo'];
+  c[0];
+
+  print('DynamicInvocation');
+  dyn[0];
+
+  print('DynamicInvocation (Never)');
+  never[0];
+
+  print('DynamicInvocation (Invalid)');
+  c.method()[0];
+
+  print('DynamicInvocation (Unresolved)');
+  string[0];
+}
+
+indexSet(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never) {
+  print('InstanceInvocation');
+  list[0] = 42;
+  map['foo'] = 0.5;
+  c[0] = c;
+
+  print('DynamicInvocation');
+  dyn[0] = 42;
+
+  print('DynamicInvocation (Never)');
+  never[0] = 42;
+
+  print('DynamicInvocation (Invalid)');
+  c.method()[0] = 42;
+
+  print('DynamicInvocation (Unresolved)');
+  string[0] = 42;
+}
+
+compound(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never) {
+  print('InstanceInvocation');
+  list[0] += 42;
+  map['foo'] += 0.5;
+  c[0] += c;
+
+  print('DynamicInvocation');
+  dyn[0] += 42;
+
+  print('DynamicInvocation (Never)');
+  never[0] += 42;
+
+  print('DynamicInvocation (Invalid)');
+  c.method()[0] += 42;
+
+  print('DynamicInvocation (Unresolved)');
+  string[0] += 42;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/none/operator.dart.outline.expect b/pkg/front_end/testcases/none/operator.dart.outline.expect
new file mode 100644
index 0000000..b105389
--- /dev/null
+++ b/pkg/front_end/testcases/none/operator.dart.outline.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T%>
+    ;
+  operator +(generic-covariant-impl self::Class<self::Class::T%> other) → self::Class<self::Class::T%>
+    ;
+  operator unary-() → self::Class<self::Class::T%>
+    ;
+  operator [](core::int index) → self::Class<self::Class::T%>
+    ;
+  operator []=(core::int index, generic-covariant-impl self::Class<self::Class::T%> value) → void
+    ;
+  method method(core::double o) → core::int
+    ;
+}
+static method add(core::num n, core::int i, core::double d, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic
+  ;
+static method unaryMinus(core::num n, core::int i, core::double d, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic
+  ;
+static method indexGet(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic
+  ;
+static method indexSet(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never) → dynamic
+  ;
+static method compound(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/none/operator.dart.strong.expect b/pkg/front_end/testcases/none/operator.dart.strong.expect
new file mode 100644
index 0000000..c78387c
--- /dev/null
+++ b/pkg/front_end/testcases/none/operator.dart.strong.expect
@@ -0,0 +1,163 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/operator.dart:48:10: Error: The operator '-' isn't defined for the class 'String'.
+// Try correcting the operator to an existing operator, or defining a '-' operator.
+//   string - 42;
+//          ^
+//
+// pkg/front_end/testcases/none/operator.dart:66:12: Error: Too few positional arguments: 1 required, 0 given.
+//   -c.method();
+//            ^
+//
+// pkg/front_end/testcases/none/operator.dart:69:3: Error: The operator 'unary-' isn't defined for the class 'String'.
+// Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+//   -string;
+//   ^
+//
+// pkg/front_end/testcases/none/operator.dart:86:11: Error: Too few positional arguments: 1 required, 0 given.
+//   c.method()[0];
+//           ^
+//
+// pkg/front_end/testcases/none/operator.dart:109:3: Error: Getter not found: 'string'.
+//   string[0] = 42;
+//   ^^^^^^
+//
+// pkg/front_end/testcases/none/operator.dart:106:11: Error: Too few positional arguments: 1 required, 0 given.
+//   c.method()[0] = 42;
+//           ^
+//
+// pkg/front_end/testcases/none/operator.dart:129:3: Error: Getter not found: 'string'.
+//   string[0] += 42;
+//   ^^^^^^
+//
+// pkg/front_end/testcases/none/operator.dart:116:14: Error: Operator '+' cannot be called on 'double?' because it is potentially null.
+//   map['foo'] += 0.5;
+//              ^
+//
+// pkg/front_end/testcases/none/operator.dart:126:11: Error: Too few positional arguments: 1 required, 0 given.
+//   c.method()[0] += 42;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T%>
+    : super core::Object::•()
+    ;
+  operator +(generic-covariant-impl self::Class<self::Class::T%> other) → self::Class<self::Class::T%>
+    return other;
+  operator unary-() → self::Class<self::Class::T%>
+    return this;
+  operator [](core::int index) → self::Class<self::Class::T%>
+    return this;
+  operator []=(core::int index, generic-covariant-impl self::Class<self::Class::T%> value) → void {}
+  method method(core::double o) → core::int
+    return 42;
+}
+static method add(core::num n, core::int i, core::double d, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic {
+  core::print("InstanceInvocation");
+  n.{core::num::+}(n){(core::num) → core::num};
+  n.{core::num::+}(i){(core::num) → core::num};
+  n.{core::num::+}(d){(core::num) → core::double};
+  n.{core::num::+}(dyn as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+  core::print("InstanceInvocation");
+  i.{core::num::+}(n){(core::num) → core::num};
+  i.{core::num::+}(i){(core::num) → core::int};
+  i.{core::num::+}(d){(core::num) → core::double};
+  i.{core::num::+}(dyn as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+  core::print("InstanceInvocation");
+  d.{core::double::+}(n){(core::num) → core::double};
+  d.{core::double::+}(i){(core::num) → core::double};
+  d.{core::double::+}(d){(core::num) → core::double};
+  i.{core::num::+}(dyn as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+  core::print("InstanceInvocation");
+  c.{self::Class::+}(c){(self::Class<core::String>) → self::Class<core::String>};
+  c.{self::Class::+}(dyn as{TypeError,ForDynamic,ForNonNullableByDefault} self::Class<core::String>){(self::Class<core::String>) → self::Class<core::String>};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.+(n);
+  core::print("DynamicInvocation (Never)");
+  never{Never}.+(n);
+  core::print("DynamicInvocation (Invalid)");
+  invalid-expression "pkg/front_end/testcases/none/operator.dart:48:10: Error: The operator '-' isn't defined for the class 'String'.
+Try correcting the operator to an existing operator, or defining a '-' operator.
+  string - 42;
+         ^";
+}
+static method unaryMinus(core::num n, core::int i, core::double d, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic {
+  core::print("InstanceInvocation");
+  n.{core::num::unary-}(){() → core::num};
+  i.{core::int::unary-}(){() → core::int};
+  d.{core::double::unary-}(){() → core::double};
+  c.{self::Class::unary-}(){() → self::Class<core::String>};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.unary-();
+  core::print("DynamicInvocation (Never)");
+  never{Never}.unary-();
+  core::print("DynamicInvocation (Invalid)");
+  (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/none/operator.dart:66:12: Error: Too few positional arguments: 1 required, 0 given.
+  -c.method();
+           ^" in c.{self::Class::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.unary-();
+  core::print("DynamicInvocation (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/operator.dart:69:3: Error: The operator 'unary-' isn't defined for the class 'String'.
+Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+  -string;
+  ^";
+}
+static method indexGet(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic {
+  core::print("InstanceInvocation");
+  list.{core::List::[]}(0){(core::int) → core::int};
+  map.{core::Map::[]}("foo"){(core::Object?) → core::double?};
+  c.{self::Class::[]}(0){(core::int) → self::Class<core::String>};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.[](0);
+  core::print("DynamicInvocation (Never)");
+  never{Never}.[](0);
+  core::print("DynamicInvocation (Invalid)");
+  (let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/none/operator.dart:86:11: Error: Too few positional arguments: 1 required, 0 given.
+  c.method()[0];
+          ^" in c.{self::Class::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.[](0);
+  core::print("DynamicInvocation (Unresolved)");
+  string.{core::String::[]}(0){(core::int) → core::String};
+}
+static method indexSet(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never) → dynamic {
+  core::print("InstanceInvocation");
+  list.{core::List::[]=}(0, 42){(core::int, core::int) → void};
+  map.{core::Map::[]=}("foo", 0.5){(core::String, core::double) → void};
+  c.{self::Class::[]=}(0, c){(core::int, self::Class<core::String>) → void};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.[]=(0, 42);
+  core::print("DynamicInvocation (Never)");
+  never{Never}.[]=(0, 42);
+  core::print("DynamicInvocation (Invalid)");
+  (let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/none/operator.dart:106:11: Error: Too few positional arguments: 1 required, 0 given.
+  c.method()[0] = 42;
+          ^" in c.{self::Class::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.[]=(0, 42);
+  core::print("DynamicInvocation (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/operator.dart:109:3: Error: Getter not found: 'string'.
+  string[0] = 42;
+  ^^^^^^"{dynamic}.[]=(0, 42);
+}
+static method compound(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never) → dynamic {
+  core::print("InstanceInvocation");
+  let final core::List<core::int> #t4 = list in let final core::int #t5 = 0 in #t4.{core::List::[]=}(#t5, #t4.{core::List::[]}(#t5){(core::int) → core::int}.{core::num::+}(42){(core::num) → core::int}){(core::int, core::int) → void};
+  let final core::Map<core::String, core::double> #t6 = map in let final core::String #t7 = "foo" in #t6.{core::Map::[]=}(#t7, let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/none/operator.dart:116:14: Error: Operator '+' cannot be called on 'double?' because it is potentially null.
+  map['foo'] += 0.5;
+             ^" in #t6.{core::Map::[]}(#t7){(core::Object?) → core::double?}.{core::double::+}(0.5){(core::num) → core::double}){(core::String, core::double) → void};
+  let final self::Class<core::String> #t9 = c in let final core::int #t10 = 0 in #t9.{self::Class::[]=}(#t10, #t9.{self::Class::[]}(#t10){(core::int) → self::Class<core::String>}.{self::Class::+}(c){(self::Class<core::String>) → self::Class<core::String>}){(core::int, self::Class<core::String>) → void};
+  core::print("DynamicInvocation");
+  let final dynamic #t11 = dyn in let final core::int #t12 = 0 in #t11{dynamic}.[]=(#t12, #t11{dynamic}.[](#t12){dynamic}.+(42));
+  core::print("DynamicInvocation (Never)");
+  let final Never #t13 = never in let final core::int #t14 = 0 in #t13{Never}.[]=(#t14, #t13{Never}.[](#t14){Never}.+(42));
+  core::print("DynamicInvocation (Invalid)");
+  let final invalid-type #t15 = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/none/operator.dart:126:11: Error: Too few positional arguments: 1 required, 0 given.
+  c.method()[0] += 42;
+          ^" in c.{self::Class::method}{<inapplicable>}.(){() → invalid-type} in let final core::int #t17 = 0 in #t15{<invalid>}.[]=(#t17, #t15{<invalid>}.[](#t17){<invalid>}.+(42));
+  core::print("DynamicInvocation (Unresolved)");
+  let final dynamic #t18 = invalid-expression "pkg/front_end/testcases/none/operator.dart:129:3: Error: Getter not found: 'string'.
+  string[0] += 42;
+  ^^^^^^" in let final core::int #t19 = 0 in #t18{dynamic}.[]=(#t19, #t18{dynamic}.[](#t19){dynamic}.+(42));
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/none/operator.dart.textual_outline.expect b/pkg/front_end/testcases/none/operator.dart.textual_outline.expect
new file mode 100644
index 0000000..f2e598e
--- /dev/null
+++ b/pkg/front_end/testcases/none/operator.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class Class<T> {
+  Class<T> operator +(Class<T> other) => other;
+  Class<T> operator -() => this;
+  Class<T> operator [](int index) => this;
+  operator []=(int index, Class<T> value) {}
+  int method(double o) => 42;
+}
+
+add(num n, int i, double d, Class<String> c, dynamic dyn, Never never,
+    String string) {}
+unaryMinus(num n, int i, double d, Class<String> c, dynamic dyn, Never never,
+    String string) {}
+indexGet(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never, String string) {}
+indexSet(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never) {}
+compound(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never) {}
+main() {}
diff --git a/pkg/front_end/testcases/none/operator.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/none/operator.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d19339d
--- /dev/null
+++ b/pkg/front_end/testcases/none/operator.dart.textual_outline_modelled.expect
@@ -0,0 +1,20 @@
+add(num n, int i, double d, Class<String> c, dynamic dyn, Never never,
+    String string) {}
+
+class Class<T> {
+  Class<T> operator +(Class<T> other) => other;
+  Class<T> operator -() => this;
+  Class<T> operator [](int index) => this;
+  int method(double o) => 42;
+  operator []=(int index, Class<T> value) {}
+}
+
+compound(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never) {}
+indexGet(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never, String string) {}
+indexSet(List<int> list, Map<String, double> map, Class<String> c, dynamic dyn,
+    Never never) {}
+main() {}
+unaryMinus(num n, int i, double d, Class<String> c, dynamic dyn, Never never,
+    String string) {}
diff --git a/pkg/front_end/testcases/none/operator.dart.weak.expect b/pkg/front_end/testcases/none/operator.dart.weak.expect
new file mode 100644
index 0000000..92c34a3
--- /dev/null
+++ b/pkg/front_end/testcases/none/operator.dart.weak.expect
@@ -0,0 +1,164 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/operator.dart:48:10: Error: The operator '-' isn't defined for the class 'String'.
+// Try correcting the operator to an existing operator, or defining a '-' operator.
+//   string - 42;
+//          ^
+//
+// pkg/front_end/testcases/none/operator.dart:66:12: Error: Too few positional arguments: 1 required, 0 given.
+//   -c.method();
+//            ^
+//
+// pkg/front_end/testcases/none/operator.dart:69:3: Error: The operator 'unary-' isn't defined for the class 'String'.
+// Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+//   -string;
+//   ^
+//
+// pkg/front_end/testcases/none/operator.dart:86:11: Error: Too few positional arguments: 1 required, 0 given.
+//   c.method()[0];
+//           ^
+//
+// pkg/front_end/testcases/none/operator.dart:109:3: Error: Getter not found: 'string'.
+//   string[0] = 42;
+//   ^^^^^^
+//
+// pkg/front_end/testcases/none/operator.dart:106:11: Error: Too few positional arguments: 1 required, 0 given.
+//   c.method()[0] = 42;
+//           ^
+//
+// pkg/front_end/testcases/none/operator.dart:129:3: Error: Getter not found: 'string'.
+//   string[0] += 42;
+//   ^^^^^^
+//
+// pkg/front_end/testcases/none/operator.dart:116:14: Error: Operator '+' cannot be called on 'double?' because it is potentially null.
+//   map['foo'] += 0.5;
+//              ^
+//
+// pkg/front_end/testcases/none/operator.dart:126:11: Error: Too few positional arguments: 1 required, 0 given.
+//   c.method()[0] += 42;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Class<self::Class::T%>
+    : super core::Object::•()
+    ;
+  operator +(generic-covariant-impl self::Class<self::Class::T%> other) → self::Class<self::Class::T%>
+    return other;
+  operator unary-() → self::Class<self::Class::T%>
+    return this;
+  operator [](core::int index) → self::Class<self::Class::T%>
+    return this;
+  operator []=(core::int index, generic-covariant-impl self::Class<self::Class::T%> value) → void {}
+  method method(core::double o) → core::int
+    return 42;
+}
+static method add(core::num n, core::int i, core::double d, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic {
+  core::print("InstanceInvocation");
+  n.{core::num::+}(n){(core::num) → core::num};
+  n.{core::num::+}(i){(core::num) → core::num};
+  n.{core::num::+}(d){(core::num) → core::double};
+  n.{core::num::+}(dyn as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+  core::print("InstanceInvocation");
+  i.{core::num::+}(n){(core::num) → core::num};
+  i.{core::num::+}(i){(core::num) → core::int};
+  i.{core::num::+}(d){(core::num) → core::double};
+  i.{core::num::+}(dyn as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+  core::print("InstanceInvocation");
+  d.{core::double::+}(n){(core::num) → core::double};
+  d.{core::double::+}(i){(core::num) → core::double};
+  d.{core::double::+}(d){(core::num) → core::double};
+  i.{core::num::+}(dyn as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+  core::print("InstanceInvocation");
+  c.{self::Class::+}(c){(self::Class<core::String>) → self::Class<core::String>};
+  c.{self::Class::+}(dyn as{TypeError,ForDynamic,ForNonNullableByDefault} self::Class<core::String>){(self::Class<core::String>) → self::Class<core::String>};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.+(n);
+  core::print("DynamicInvocation (Never)");
+  let final Never #t1 = (let final Never #t2 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.+(n) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  core::print("DynamicInvocation (Invalid)");
+  invalid-expression "pkg/front_end/testcases/none/operator.dart:48:10: Error: The operator '-' isn't defined for the class 'String'.
+Try correcting the operator to an existing operator, or defining a '-' operator.
+  string - 42;
+         ^";
+}
+static method unaryMinus(core::num n, core::int i, core::double d, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic {
+  core::print("InstanceInvocation");
+  n.{core::num::unary-}(){() → core::num};
+  i.{core::int::unary-}(){() → core::int};
+  d.{core::double::unary-}(){() → core::double};
+  c.{self::Class::unary-}(){() → self::Class<core::String>};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.unary-();
+  core::print("DynamicInvocation (Never)");
+  let final Never #t3 = (let final Never #t4 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.unary-() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  core::print("DynamicInvocation (Invalid)");
+  (let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/none/operator.dart:66:12: Error: Too few positional arguments: 1 required, 0 given.
+  -c.method();
+           ^" in c.{self::Class::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.unary-();
+  core::print("DynamicInvocation (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/operator.dart:69:3: Error: The operator 'unary-' isn't defined for the class 'String'.
+Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+  -string;
+  ^";
+}
+static method indexGet(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never, core::String string) → dynamic {
+  core::print("InstanceInvocation");
+  list.{core::List::[]}(0){(core::int) → core::int};
+  map.{core::Map::[]}("foo"){(core::Object?) → core::double?};
+  c.{self::Class::[]}(0){(core::int) → self::Class<core::String>};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.[](0);
+  core::print("DynamicInvocation (Never)");
+  let final Never #t6 = (let final Never #t7 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.[](0) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  core::print("DynamicInvocation (Invalid)");
+  (let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/none/operator.dart:86:11: Error: Too few positional arguments: 1 required, 0 given.
+  c.method()[0];
+          ^" in c.{self::Class::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.[](0);
+  core::print("DynamicInvocation (Unresolved)");
+  string.{core::String::[]}(0){(core::int) → core::String};
+}
+static method indexSet(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never) → dynamic {
+  core::print("InstanceInvocation");
+  list.{core::List::[]=}(0, 42){(core::int, core::int) → void};
+  map.{core::Map::[]=}("foo", 0.5){(core::String, core::double) → void};
+  c.{self::Class::[]=}(0, c){(core::int, self::Class<core::String>) → void};
+  core::print("DynamicInvocation");
+  dyn{dynamic}.[]=(0, 42);
+  core::print("DynamicInvocation (Never)");
+  (let final Never #t9 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.[]=(0, 42);
+  core::print("DynamicInvocation (Invalid)");
+  (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/none/operator.dart:106:11: Error: Too few positional arguments: 1 required, 0 given.
+  c.method()[0] = 42;
+          ^" in c.{self::Class::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.[]=(0, 42);
+  core::print("DynamicInvocation (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/operator.dart:109:3: Error: Getter not found: 'string'.
+  string[0] = 42;
+  ^^^^^^"{dynamic}.[]=(0, 42);
+}
+static method compound(core::List<core::int> list, core::Map<core::String, core::double> map, self::Class<core::String> c, dynamic dyn, Never never) → dynamic {
+  core::print("InstanceInvocation");
+  let final core::List<core::int> #t11 = list in let final core::int #t12 = 0 in #t11.{core::List::[]=}(#t12, #t11.{core::List::[]}(#t12){(core::int) → core::int}.{core::num::+}(42){(core::num) → core::int}){(core::int, core::int) → void};
+  let final core::Map<core::String, core::double> #t13 = map in let final core::String #t14 = "foo" in #t13.{core::Map::[]=}(#t14, let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/none/operator.dart:116:14: Error: Operator '+' cannot be called on 'double?' because it is potentially null.
+  map['foo'] += 0.5;
+             ^" in #t13.{core::Map::[]}(#t14){(core::Object?) → core::double?}.{core::double::+}(0.5){(core::num) → core::double}){(core::String, core::double) → void};
+  let final self::Class<core::String> #t16 = c in let final core::int #t17 = 0 in #t16.{self::Class::[]=}(#t17, #t16.{self::Class::[]}(#t17){(core::int) → self::Class<core::String>}.{self::Class::+}(c){(self::Class<core::String>) → self::Class<core::String>}){(core::int, self::Class<core::String>) → void};
+  core::print("DynamicInvocation");
+  let final dynamic #t18 = dyn in let final core::int #t19 = 0 in #t18{dynamic}.[]=(#t19, #t18{dynamic}.[](#t19){dynamic}.+(42));
+  core::print("DynamicInvocation (Never)");
+  let final Never #t20 = let final Never #t21 = let final Never #t22 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in let final core::int #t23 = 0 in #t21{Never}.[]=(#t23, #t21{Never}.[](#t23){Never}.+(42)) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  core::print("DynamicInvocation (Invalid)");
+  let final invalid-type #t24 = let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/none/operator.dart:126:11: Error: Too few positional arguments: 1 required, 0 given.
+  c.method()[0] += 42;
+          ^" in c.{self::Class::method}{<inapplicable>}.(){() → invalid-type} in let final core::int #t26 = 0 in #t24{<invalid>}.[]=(#t26, #t24{<invalid>}.[](#t26){<invalid>}.+(42));
+  core::print("DynamicInvocation (Unresolved)");
+  let final dynamic #t27 = invalid-expression "pkg/front_end/testcases/none/operator.dart:129:3: Error: Getter not found: 'string'.
+  string[0] += 42;
+  ^^^^^^" in let final core::int #t28 = 0 in #t27{dynamic}.[]=(#t28, #t27{dynamic}.[](#t28){dynamic}.+(42));
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/none/property_get.dart b/pkg/front_end/testcases/none/property_get.dart
new file mode 100644
index 0000000..15baea3
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_get.dart
@@ -0,0 +1,116 @@
+// 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.md file.
+
+class Class1 {
+  int field;
+
+  Class1(this.field);
+
+  int method(double o) => 0;
+
+  static int staticField = 42;
+
+  static int staticMethod(double o) => 0;
+}
+
+int topLevelField = 42;
+
+int topLevelMethod(double o) => 0;
+
+class Class2<T> {
+  T field;
+
+  Class2(this.field);
+
+  int call() => 42;
+}
+
+const String string = 'foo';
+const int stringLength = string.length;
+
+const dynamic dynamicString = 'foo';
+const int dynamicStringLength = dynamicString.length;
+
+test<T1 extends Function, T2 extends int Function()>(
+    Class1 nonNullableClass1,
+    Class1? nullableClass1,
+    dynamic dyn,
+    Never never,
+    Class2<String> nonNullableClass2,
+    Class2<String>? nullableClass2,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function() nonNullableFunctionType,
+    int Function()? nullableFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2) {
+  print('InstanceGet');
+  nonNullableClass1.field;
+  nullableClass1?.field;
+  nonNullableClass2.field;
+  nullableClass2?.field;
+  const dynamic instance_get = nullableClass1.field;
+  print(instance_get);
+
+  print('InstanceTearOff');
+  nonNullableClass1.method;
+  nullableClass1?.method;
+  nonNullableClass2.call;
+  nullableClass2?.call;
+  const dynamic instance_tearOff = nonNullableClass1.method;
+  print(instance_tearOff);
+
+  Function f1 = nonNullableClass2;
+  Function? f2 = nullableClass2;
+
+  print('StaticGet');
+  Class1.staticField;
+  topLevelField;
+
+  print('StaticTearOff');
+  Class1.staticMethod;
+  topLevelMethod;
+  const dynamic static_tearOff = topLevelMethod;
+  print(static_tearOff);
+
+  print('DynamicGet');
+  dyn.field;
+  dyn?.field;
+  const dynamic dyn_get = dyn.field;
+  print(dyn_get);
+
+  print('InstanceGet (Object)');
+  dyn.hashCode;
+  nullableClass1.hashCode;
+
+  print('InstanceGetTearOff (Object)');
+  dyn.toString;
+  nullableClass1.toString;
+
+  print('DynamicGet (Never)');
+  never.field;
+  never.hashCode;
+
+  print('FunctionTearOff');
+  nonNullableFunction.call;
+  nullableFunction?.call;
+  nonNullableFunctionType.call;
+  nullableFunctionType?.call;
+  nonNullableTypeVariable1.call;
+  nullableTypeVariable1?.call;
+  nonNullableTypeVariable2.call;
+  nullableTypeVariable2?.call;
+  const dynamic function_tearOff = nonNullableFunction.call;
+  print(function_tearOff);
+
+  print('DynamicGet (Invalid)');
+  nonNullableClass1.method().field;
+
+  print('DynamicGet (Unresolved)');
+  nonNullableClass1.unresolved;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/none/property_get.dart.outline.expect b/pkg/front_end/testcases/none/property_get.dart.outline.expect
new file mode 100644
index 0000000..06c8396
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_get.dart.outline.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field;
+  static field core::int staticField;
+  constructor •(core::int field) → self::Class1
+    ;
+  method method(core::double o) → core::int
+    ;
+  static method staticMethod(core::double o) → core::int
+    ;
+}
+class Class2<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::Class2::T% field;
+  constructor •(self::Class2::T% field) → self::Class2<self::Class2::T%>
+    ;
+  method call() → core::int
+    ;
+}
+static field core::int topLevelField;
+static const field core::String string = "foo";
+static const field core::int stringLength = self::string.{core::String::length}{core::int};
+static const field dynamic dynamicString = "foo";
+static const field core::int dynamicStringLength = self::dynamicString{dynamic}.length as{TypeError,ForDynamic,ForNonNullableByDefault} core::int;
+static method topLevelMethod(core::double o) → core::int
+  ;
+static method test<T1 extends core::Function = core::Function, T2 extends () → core::int = () → core::int>(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never, self::Class2<core::String> nonNullableClass2, self::Class2<core::String>? nullableClass2, core::Function nonNullableFunction, core::Function? nullableFunction, () → core::int nonNullableFunctionType, () →? core::int nullableFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2) → dynamic
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: InstanceGet @ org-dartlang-testcase:///property_get.dart:30:33 -> IntConstant(3)
+Evaluated: AsExpression @ org-dartlang-testcase:///property_get.dart:33:47 -> IntConstant(3)
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/none/property_get.dart.strong.expect b/pkg/front_end/testcases/none/property_get.dart.strong.expect
new file mode 100644
index 0000000..b1397c7
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_get.dart.strong.expect
@@ -0,0 +1,149 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/property_get.dart:55:32: Error: Not a constant expression.
+//   const dynamic instance_get = nullableClass1.field;
+//                                ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/property_get.dart:63:36: Error: Not a constant expression.
+//   const dynamic instance_tearOff = nonNullableClass1.method;
+//                                    ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/property_get.dart:82:27: Error: Not a constant expression.
+//   const dynamic dyn_get = dyn.field;
+//                           ^^^
+//
+// pkg/front_end/testcases/none/property_get.dart:106:36: Error: Not a constant expression.
+//   const dynamic function_tearOff = nonNullableFunction.call;
+//                                    ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/property_get.dart:67:18: Error: Can't tear off method 'call' from a potentially null value.
+//   Function? f2 = nullableClass2;
+//                  ^
+//
+// pkg/front_end/testcases/none/property_get.dart:110:27: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass1.method().field;
+//                           ^
+//
+// pkg/front_end/testcases/none/property_get.dart:113:21: Error: The getter 'unresolved' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/none/property_get.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'unresolved'.
+//   nonNullableClass1.unresolved;
+//                     ^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+  field core::int field;
+  static field core::int staticField = 42;
+  constructor •(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  method method(core::double o) → core::int
+    return 0;
+  static method staticMethod(core::double o) → core::int
+    return 0;
+}
+class Class2<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::Class2::T% field;
+  constructor •(self::Class2::T% field) → self::Class2<self::Class2::T%>
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  method call() → core::int
+    return 42;
+}
+static field core::int topLevelField = 42;
+static const field core::String string = #C1;
+static const field core::int stringLength = #C2;
+static const field dynamic dynamicString = #C1;
+static const field core::int dynamicStringLength = #C2;
+static method topLevelMethod(core::double o) → core::int
+  return 0;
+static method test<T1 extends core::Function = core::Function, T2 extends () → core::int = () → core::int>(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never, self::Class2<core::String> nonNullableClass2, self::Class2<core::String>? nullableClass2, core::Function nonNullableFunction, core::Function? nullableFunction, () → core::int nonNullableFunctionType, () →? core::int nullableFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2) → dynamic {
+  core::print("InstanceGet");
+  nonNullableClass1.{self::Class1::field}{core::int};
+  let final self::Class1? #t1 = nullableClass1 in #t1 == null ?{core::int?} null : #t1{self::Class1}.{self::Class1::field}{core::int};
+  nonNullableClass2.{self::Class2::field}{core::String};
+  let final self::Class2<core::String>? #t2 = nullableClass2 in #t2 == null ?{core::String?} null : #t2{self::Class2<core::String>}.{self::Class2::field}{core::String};
+  const dynamic instance_get = invalid-expression "pkg/front_end/testcases/none/property_get.dart:55:32: Error: Not a constant expression.
+  const dynamic instance_get = nullableClass1.field;
+                               ^^^^^^^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/property_get.dart:55:32: Error: Not a constant expression.
+  const dynamic instance_get = nullableClass1.field;
+                               ^^^^^^^^^^^^^^");
+  core::print("InstanceTearOff");
+  nonNullableClass1.{self::Class1::method}{(core::double) → core::int};
+  let final self::Class1? #t3 = nullableClass1 in #t3 == null ?{(core::double) →? core::int} null : #t3{self::Class1}.{self::Class1::method}{(core::double) → core::int};
+  nonNullableClass2.{self::Class2::call}{() → core::int};
+  let final self::Class2<core::String>? #t4 = nullableClass2 in #t4 == null ?{() →? core::int} null : #t4{self::Class2<core::String>}.{self::Class2::call}{() → core::int};
+  const dynamic instance_tearOff = invalid-expression "pkg/front_end/testcases/none/property_get.dart:63:36: Error: Not a constant expression.
+  const dynamic instance_tearOff = nonNullableClass1.method;
+                                   ^^^^^^^^^^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/property_get.dart:63:36: Error: Not a constant expression.
+  const dynamic instance_tearOff = nonNullableClass1.method;
+                                   ^^^^^^^^^^^^^^^^^");
+  core::Function f1 = let final self::Class2<core::String> #t5 = nonNullableClass2 in #t5 == null ?{() → core::int} null : #t5.{self::Class2::call};
+  core::Function? f2 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/none/property_get.dart:67:18: Error: Can't tear off method 'call' from a potentially null value.
+  Function? f2 = nullableClass2;
+                 ^" in nullableClass2 as{TypeError} core::Function?;
+  core::print("StaticGet");
+  self::Class1::staticField;
+  self::topLevelField;
+  core::print("StaticTearOff");
+  #C3;
+  #C4;
+  core::print(#C4);
+  core::print("DynamicGet");
+  dyn{dynamic}.field;
+  let final dynamic #t7 = dyn in #t7 == null ?{dynamic} null : #t7{dynamic}.field;
+  const dynamic dyn_get = invalid-expression "pkg/front_end/testcases/none/property_get.dart:82:27: Error: Not a constant expression.
+  const dynamic dyn_get = dyn.field;
+                          ^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/property_get.dart:82:27: Error: Not a constant expression.
+  const dynamic dyn_get = dyn.field;
+                          ^^^");
+  core::print("InstanceGet (Object)");
+  dyn.{core::Object::hashCode}{core::int};
+  nullableClass1.{core::Object::hashCode}{core::int};
+  core::print("InstanceGetTearOff (Object)");
+  dyn.{core::Object::toString}{() → core::String};
+  nullableClass1.{core::Object::toString}{() → core::String};
+  core::print("DynamicGet (Never)");
+  never{Never}.field;
+  never{Never}.hashCode;
+  core::print("FunctionTearOff");
+  nonNullableFunction.call;
+  let final core::Function? #t8 = nullableFunction in #t8 == null ?{core::Function?} null : #t8{core::Function}.call;
+  nonNullableFunctionType.call;
+  let final () →? core::int #t9 = nullableFunctionType in #t9 == null ?{() →? core::int} null : #t9{() → core::int}.call;
+  nonNullableTypeVariable1.call;
+  let final self::test::T1? #t10 = nullableTypeVariable1 in #t10 == null ?{self::test::T1?} null : #t10{self::test::T1}.call;
+  nonNullableTypeVariable2.call;
+  let final self::test::T2? #t11 = nullableTypeVariable2 in #t11 == null ?{self::test::T2?} null : #t11{self::test::T2}.call;
+  const dynamic function_tearOff = invalid-expression "pkg/front_end/testcases/none/property_get.dart:106:36: Error: Not a constant expression.
+  const dynamic function_tearOff = nonNullableFunction.call;
+                                   ^^^^^^^^^^^^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/property_get.dart:106:36: Error: Not a constant expression.
+  const dynamic function_tearOff = nonNullableFunction.call;
+                                   ^^^^^^^^^^^^^^^^^^^");
+  core::print("DynamicGet (Invalid)");
+  (let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/none/property_get.dart:110:27: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass1.method().field;
+                          ^" in nonNullableClass1.{self::Class1::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.field;
+  core::print("DynamicGet (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/property_get.dart:113:21: Error: The getter 'unresolved' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/none/property_get.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'unresolved'.
+  nonNullableClass1.unresolved;
+                    ^^^^^^^^^^";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "foo"
+  #C2 = 3
+  #C3 = tearoff self::Class1::staticMethod
+  #C4 = tearoff self::topLevelMethod
+}
diff --git a/pkg/front_end/testcases/none/property_get.dart.textual_outline.expect b/pkg/front_end/testcases/none/property_get.dart.textual_outline.expect
new file mode 100644
index 0000000..3e3ed79
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_get.dart.textual_outline.expect
@@ -0,0 +1,37 @@
+class Class1 {
+  int field;
+  Class1(this.field);
+  int method(double o) => 0;
+  static int staticField = 42;
+  static int staticMethod(double o) => 0;
+}
+
+int topLevelField = 42;
+int topLevelMethod(double o) => 0;
+
+class Class2<T> {
+  T field;
+  Class2(this.field);
+  int call() => 42;
+}
+
+const String string = 'foo';
+const int stringLength = string.length;
+const dynamic dynamicString = 'foo';
+const int dynamicStringLength = dynamicString.length;
+test<T1 extends Function, T2 extends int Function()>(
+    Class1 nonNullableClass1,
+    Class1? nullableClass1,
+    dynamic dyn,
+    Never never,
+    Class2<String> nonNullableClass2,
+    Class2<String>? nullableClass2,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function() nonNullableFunctionType,
+    int Function()? nullableFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2) {}
+main() {}
diff --git a/pkg/front_end/testcases/none/property_get.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/none/property_get.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cb56e8a
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_get.dart.textual_outline_modelled.expect
@@ -0,0 +1,36 @@
+class Class1 {
+  Class1(this.field);
+  int field;
+  int method(double o) => 0;
+  static int staticField = 42;
+  static int staticMethod(double o) => 0;
+}
+
+class Class2<T> {
+  Class2(this.field);
+  T field;
+  int call() => 42;
+}
+
+const String string = 'foo';
+const dynamic dynamicString = 'foo';
+const int dynamicStringLength = dynamicString.length;
+const int stringLength = string.length;
+int topLevelField = 42;
+int topLevelMethod(double o) => 0;
+main() {}
+test<T1 extends Function, T2 extends int Function()>(
+    Class1 nonNullableClass1,
+    Class1? nullableClass1,
+    dynamic dyn,
+    Never never,
+    Class2<String> nonNullableClass2,
+    Class2<String>? nullableClass2,
+    Function nonNullableFunction,
+    Function? nullableFunction,
+    int Function() nonNullableFunctionType,
+    int Function()? nullableFunctionType,
+    T1 nonNullableTypeVariable1,
+    T1? nullableTypeVariable1,
+    T2 nonNullableTypeVariable2,
+    T2? nullableTypeVariable2) {}
diff --git a/pkg/front_end/testcases/none/property_get.dart.weak.expect b/pkg/front_end/testcases/none/property_get.dart.weak.expect
new file mode 100644
index 0000000..d52d9df
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_get.dart.weak.expect
@@ -0,0 +1,150 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/property_get.dart:55:32: Error: Not a constant expression.
+//   const dynamic instance_get = nullableClass1.field;
+//                                ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/property_get.dart:63:36: Error: Not a constant expression.
+//   const dynamic instance_tearOff = nonNullableClass1.method;
+//                                    ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/property_get.dart:82:27: Error: Not a constant expression.
+//   const dynamic dyn_get = dyn.field;
+//                           ^^^
+//
+// pkg/front_end/testcases/none/property_get.dart:106:36: Error: Not a constant expression.
+//   const dynamic function_tearOff = nonNullableFunction.call;
+//                                    ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/property_get.dart:67:18: Error: Can't tear off method 'call' from a potentially null value.
+//   Function? f2 = nullableClass2;
+//                  ^
+//
+// pkg/front_end/testcases/none/property_get.dart:110:27: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass1.method().field;
+//                           ^
+//
+// pkg/front_end/testcases/none/property_get.dart:113:21: Error: The getter 'unresolved' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/none/property_get.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'unresolved'.
+//   nonNullableClass1.unresolved;
+//                     ^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class1 extends core::Object {
+  field core::int field;
+  static field core::int staticField = 42;
+  constructor •(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  method method(core::double o) → core::int
+    return 0;
+  static method staticMethod(core::double o) → core::int
+    return 0;
+}
+class Class2<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::Class2::T% field;
+  constructor •(self::Class2::T% field) → self::Class2<self::Class2::T%>
+    : self::Class2::field = field, super core::Object::•()
+    ;
+  method call() → core::int
+    return 42;
+}
+static field core::int topLevelField = 42;
+static const field core::String string = #C1;
+static const field core::int stringLength = #C2;
+static const field dynamic dynamicString = #C1;
+static const field core::int dynamicStringLength = #C2;
+static method topLevelMethod(core::double o) → core::int
+  return 0;
+static method test<T1 extends core::Function = core::Function, T2 extends () → core::int = () → core::int>(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never, self::Class2<core::String> nonNullableClass2, self::Class2<core::String>? nullableClass2, core::Function nonNullableFunction, core::Function? nullableFunction, () → core::int nonNullableFunctionType, () →? core::int nullableFunctionType, self::test::T1 nonNullableTypeVariable1, self::test::T1? nullableTypeVariable1, self::test::T2 nonNullableTypeVariable2, self::test::T2? nullableTypeVariable2) → dynamic {
+  core::print("InstanceGet");
+  nonNullableClass1.{self::Class1::field}{core::int};
+  let final self::Class1? #t1 = nullableClass1 in #t1 == null ?{core::int?} null : #t1{self::Class1}.{self::Class1::field}{core::int};
+  nonNullableClass2.{self::Class2::field}{core::String};
+  let final self::Class2<core::String>? #t2 = nullableClass2 in #t2 == null ?{core::String?} null : #t2{self::Class2<core::String>}.{self::Class2::field}{core::String};
+  const dynamic instance_get = invalid-expression "pkg/front_end/testcases/none/property_get.dart:55:32: Error: Not a constant expression.
+  const dynamic instance_get = nullableClass1.field;
+                               ^^^^^^^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/property_get.dart:55:32: Error: Not a constant expression.
+  const dynamic instance_get = nullableClass1.field;
+                               ^^^^^^^^^^^^^^");
+  core::print("InstanceTearOff");
+  nonNullableClass1.{self::Class1::method}{(core::double) → core::int};
+  let final self::Class1? #t3 = nullableClass1 in #t3 == null ?{(core::double) →? core::int} null : #t3{self::Class1}.{self::Class1::method}{(core::double) → core::int};
+  nonNullableClass2.{self::Class2::call}{() → core::int};
+  let final self::Class2<core::String>? #t4 = nullableClass2 in #t4 == null ?{() →? core::int} null : #t4{self::Class2<core::String>}.{self::Class2::call}{() → core::int};
+  const dynamic instance_tearOff = invalid-expression "pkg/front_end/testcases/none/property_get.dart:63:36: Error: Not a constant expression.
+  const dynamic instance_tearOff = nonNullableClass1.method;
+                                   ^^^^^^^^^^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/property_get.dart:63:36: Error: Not a constant expression.
+  const dynamic instance_tearOff = nonNullableClass1.method;
+                                   ^^^^^^^^^^^^^^^^^");
+  core::Function f1 = let final self::Class2<core::String> #t5 = nonNullableClass2 in #t5 == null ?{() → core::int} null : #t5.{self::Class2::call};
+  core::Function? f2 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/none/property_get.dart:67:18: Error: Can't tear off method 'call' from a potentially null value.
+  Function? f2 = nullableClass2;
+                 ^" in nullableClass2 as{TypeError} core::Function?;
+  core::print("StaticGet");
+  self::Class1::staticField;
+  self::topLevelField;
+  core::print("StaticTearOff");
+  #C3;
+  #C4;
+  core::print(#C4);
+  core::print("DynamicGet");
+  dyn{dynamic}.field;
+  let final dynamic #t7 = dyn in #t7 == null ?{dynamic} null : #t7{dynamic}.field;
+  const dynamic dyn_get = invalid-expression "pkg/front_end/testcases/none/property_get.dart:82:27: Error: Not a constant expression.
+  const dynamic dyn_get = dyn.field;
+                          ^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/property_get.dart:82:27: Error: Not a constant expression.
+  const dynamic dyn_get = dyn.field;
+                          ^^^");
+  core::print("InstanceGet (Object)");
+  dyn.{core::Object::hashCode}{core::int};
+  nullableClass1.{core::Object::hashCode}{core::int};
+  core::print("InstanceGetTearOff (Object)");
+  dyn.{core::Object::toString}{() → core::String};
+  nullableClass1.{core::Object::toString}{() → core::String};
+  core::print("DynamicGet (Never)");
+  let final Never #t8 = (let final Never #t9 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.field in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t10 = (let final Never #t11 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.hashCode in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  core::print("FunctionTearOff");
+  nonNullableFunction.call;
+  let final core::Function? #t12 = nullableFunction in #t12 == null ?{core::Function?} null : #t12{core::Function}.call;
+  nonNullableFunctionType.call;
+  let final () →? core::int #t13 = nullableFunctionType in #t13 == null ?{() →? core::int} null : #t13{() → core::int}.call;
+  nonNullableTypeVariable1.call;
+  let final self::test::T1? #t14 = nullableTypeVariable1 in #t14 == null ?{self::test::T1?} null : #t14{self::test::T1}.call;
+  nonNullableTypeVariable2.call;
+  let final self::test::T2? #t15 = nullableTypeVariable2 in #t15 == null ?{self::test::T2?} null : #t15{self::test::T2}.call;
+  const dynamic function_tearOff = invalid-expression "pkg/front_end/testcases/none/property_get.dart:106:36: Error: Not a constant expression.
+  const dynamic function_tearOff = nonNullableFunction.call;
+                                   ^^^^^^^^^^^^^^^^^^^";
+  core::print(invalid-expression "pkg/front_end/testcases/none/property_get.dart:106:36: Error: Not a constant expression.
+  const dynamic function_tearOff = nonNullableFunction.call;
+                                   ^^^^^^^^^^^^^^^^^^^");
+  core::print("DynamicGet (Invalid)");
+  (let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/none/property_get.dart:110:27: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass1.method().field;
+                          ^" in nonNullableClass1.{self::Class1::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.field;
+  core::print("DynamicGet (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/property_get.dart:113:21: Error: The getter 'unresolved' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/none/property_get.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'unresolved'.
+  nonNullableClass1.unresolved;
+                    ^^^^^^^^^^";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = "foo"
+  #C2 = 3
+  #C3 = tearoff self::Class1::staticMethod
+  #C4 = tearoff self::topLevelMethod
+}
diff --git a/pkg/front_end/testcases/none/property_set.dart b/pkg/front_end/testcases/none/property_set.dart
new file mode 100644
index 0000000..3af5cd3
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_set.dart
@@ -0,0 +1,35 @@
+// 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.md file.
+
+class Class1 {
+  int field;
+
+  Class1(this.field);
+
+  method(o) {}
+}
+
+test(Class1 nonNullableClass1, Class1? nullableClass1, dynamic dyn,
+    Never never) {
+  print("InstanceSet");
+  nonNullableClass1.field = 42;
+  nullableClass1?.field = 42;
+  const int set_instance_field = nonNullableClass1.field = 42;
+
+  print("DynamicSet");
+  dyn.field = 42;
+  dyn?.field = 42;
+  const int set_dynamic_field = dyn.field = 42;
+
+  print("DynamicSet (Never)");
+  never.field = 42;
+
+  print("DynamicSet (Invalid)");
+  nonNullableClass1.method().field = 42;
+
+  print("DynamicSet (Unresolved)");
+  nonNullableClass1.unresolved = 42;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/none/property_set.dart.outline.expect b/pkg/front_end/testcases/none/property_set.dart.outline.expect
new file mode 100644
index 0000000..d101c9e
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_set.dart.outline.expect
@@ -0,0 +1,15 @@
+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
+    ;
+  method method(dynamic o) → dynamic
+    ;
+}
+static method test(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/none/property_set.dart.strong.expect b/pkg/front_end/testcases/none/property_set.dart.strong.expect
new file mode 100644
index 0000000..269667d
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_set.dart.strong.expect
@@ -0,0 +1,67 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/property_set.dart:18:34: Error: Not a constant expression.
+//   const int set_instance_field = nonNullableClass1.field = 42;
+//                                  ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/property_set.dart:18:58: Error: Not a constant expression.
+//   const int set_instance_field = nonNullableClass1.field = 42;
+//                                                          ^
+//
+// pkg/front_end/testcases/none/property_set.dart:23:33: Error: Not a constant expression.
+//   const int set_dynamic_field = dyn.field = 42;
+//                                 ^^^
+//
+// pkg/front_end/testcases/none/property_set.dart:23:43: Error: Not a constant expression.
+//   const int set_dynamic_field = dyn.field = 42;
+//                                           ^
+//
+// pkg/front_end/testcases/none/property_set.dart:29:27: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass1.method().field = 42;
+//                           ^
+//
+// pkg/front_end/testcases/none/property_set.dart:32:21: Error: The setter 'unresolved' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/none/property_set.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'unresolved'.
+//   nonNullableClass1.unresolved = 42;
+//                     ^^^^^^^^^^
+//
+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::•()
+    ;
+  method method(dynamic o) → dynamic {}
+}
+static method test(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never) → dynamic {
+  core::print("InstanceSet");
+  nonNullableClass1.{self::Class1::field} = 42;
+  let final self::Class1? #t1 = nullableClass1 in #t1 == null ?{core::int?} null : #t1{self::Class1}.{self::Class1::field} = 42;
+  const core::int set_instance_field = invalid-expression "pkg/front_end/testcases/none/property_set.dart:18:58: Error: Not a constant expression.
+  const int set_instance_field = nonNullableClass1.field = 42;
+                                                         ^";
+  core::print("DynamicSet");
+  dyn{dynamic}.field = 42;
+  let final dynamic #t2 = dyn in #t2 == null ?{core::int?} null : #t2{dynamic}.field = 42;
+  const core::int set_dynamic_field = invalid-expression "pkg/front_end/testcases/none/property_set.dart:23:43: Error: Not a constant expression.
+  const int set_dynamic_field = dyn.field = 42;
+                                          ^";
+  core::print("DynamicSet (Never)");
+  never{Never}.field = 42;
+  core::print("DynamicSet (Invalid)");
+  (let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/none/property_set.dart:29:27: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass1.method().field = 42;
+                          ^" in nonNullableClass1.{self::Class1::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.field = 42;
+  core::print("DynamicSet (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/property_set.dart:32:21: Error: The setter 'unresolved' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/none/property_set.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'unresolved'.
+  nonNullableClass1.unresolved = 42;
+                    ^^^^^^^^^^";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/none/property_set.dart.textual_outline.expect b/pkg/front_end/testcases/none/property_set.dart.textual_outline.expect
new file mode 100644
index 0000000..8c2985d
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_set.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+class Class1 {
+  int field;
+  Class1(this.field);
+  method(o) {}
+}
+
+test(Class1 nonNullableClass1, Class1? nullableClass1, dynamic dyn,
+    Never never) {}
+main() {}
diff --git a/pkg/front_end/testcases/none/property_set.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/none/property_set.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..47012bc
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_set.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class1 {
+  Class1(this.field);
+  int field;
+  method(o) {}
+}
+
+main() {}
+test(Class1 nonNullableClass1, Class1? nullableClass1, dynamic dyn,
+    Never never) {}
diff --git a/pkg/front_end/testcases/none/property_set.dart.weak.expect b/pkg/front_end/testcases/none/property_set.dart.weak.expect
new file mode 100644
index 0000000..e5cbd88
--- /dev/null
+++ b/pkg/front_end/testcases/none/property_set.dart.weak.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/property_set.dart:18:34: Error: Not a constant expression.
+//   const int set_instance_field = nonNullableClass1.field = 42;
+//                                  ^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/none/property_set.dart:18:58: Error: Not a constant expression.
+//   const int set_instance_field = nonNullableClass1.field = 42;
+//                                                          ^
+//
+// pkg/front_end/testcases/none/property_set.dart:23:33: Error: Not a constant expression.
+//   const int set_dynamic_field = dyn.field = 42;
+//                                 ^^^
+//
+// pkg/front_end/testcases/none/property_set.dart:23:43: Error: Not a constant expression.
+//   const int set_dynamic_field = dyn.field = 42;
+//                                           ^
+//
+// pkg/front_end/testcases/none/property_set.dart:29:27: Error: Too few positional arguments: 1 required, 0 given.
+//   nonNullableClass1.method().field = 42;
+//                           ^
+//
+// pkg/front_end/testcases/none/property_set.dart:32:21: Error: The setter 'unresolved' isn't defined for the class 'Class1'.
+//  - 'Class1' is from 'pkg/front_end/testcases/none/property_set.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'unresolved'.
+//   nonNullableClass1.unresolved = 42;
+//                     ^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class1 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → self::Class1
+    : self::Class1::field = field, super core::Object::•()
+    ;
+  method method(dynamic o) → dynamic {}
+}
+static method test(self::Class1 nonNullableClass1, self::Class1? nullableClass1, dynamic dyn, Never never) → dynamic {
+  core::print("InstanceSet");
+  nonNullableClass1.{self::Class1::field} = 42;
+  let final self::Class1? #t1 = nullableClass1 in #t1 == null ?{core::int?} null : #t1{self::Class1}.{self::Class1::field} = 42;
+  const core::int set_instance_field = invalid-expression "pkg/front_end/testcases/none/property_set.dart:18:58: Error: Not a constant expression.
+  const int set_instance_field = nonNullableClass1.field = 42;
+                                                         ^";
+  core::print("DynamicSet");
+  dyn{dynamic}.field = 42;
+  let final dynamic #t2 = dyn in #t2 == null ?{core::int?} null : #t2{dynamic}.field = 42;
+  const core::int set_dynamic_field = invalid-expression "pkg/front_end/testcases/none/property_set.dart:23:43: Error: Not a constant expression.
+  const int set_dynamic_field = dyn.field = 42;
+                                          ^";
+  core::print("DynamicSet (Never)");
+  (let final Never #t3 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")){Never}.field = 42;
+  core::print("DynamicSet (Invalid)");
+  (let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/none/property_set.dart:29:27: Error: Too few positional arguments: 1 required, 0 given.
+  nonNullableClass1.method().field = 42;
+                          ^" in nonNullableClass1.{self::Class1::method}{<inapplicable>}.(){() → invalid-type}){<invalid>}.field = 42;
+  core::print("DynamicSet (Unresolved)");
+  invalid-expression "pkg/front_end/testcases/none/property_set.dart:32:21: Error: The setter 'unresolved' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/none/property_set.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'unresolved'.
+  nonNullableClass1.unresolved = 42;
+                    ^^^^^^^^^^";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/none/tearoff_opt_out.dart b/pkg/front_end/testcases/none/tearoff_opt_out.dart
new file mode 100644
index 0000000..e34a1ab
--- /dev/null
+++ b/pkg/front_end/testcases/none/tearoff_opt_out.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.md file.
+
+// @dart=2.9
+
+class Class {
+  void call() {}
+}
+
+test(Class c) {
+  Function f = c;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/none/tearoff_opt_out.dart.outline.expect b/pkg/front_end/testcases/none/tearoff_opt_out.dart.outline.expect
new file mode 100644
index 0000000..236deb6
--- /dev/null
+++ b/pkg/front_end/testcases/none/tearoff_opt_out.dart.outline.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/tearoff_opt_out.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.9
+// ^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  method call() → void
+    ;
+  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 method test(self::Class* c) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/none/tearoff_opt_out.dart.strong.expect b/pkg/front_end/testcases/none/tearoff_opt_out.dart.strong.expect
new file mode 100644
index 0000000..51270b9
--- /dev/null
+++ b/pkg/front_end/testcases/none/tearoff_opt_out.dart.strong.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/tearoff_opt_out.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.9
+// ^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method call() → void {}
+  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 method test(self::Class* c) → dynamic {
+  core::Function* f = let final self::Class* #t1 = c in #t1 == null ?{() →* void} null : #t1.{self::Class::call};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/none/tearoff_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/none/tearoff_opt_out.dart.strong.transformed.expect
new file mode 100644
index 0000000..51270b9
--- /dev/null
+++ b/pkg/front_end/testcases/none/tearoff_opt_out.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/none/tearoff_opt_out.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.9
+// ^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method call() → void {}
+  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 method test(self::Class* c) → dynamic {
+  core::Function* f = let final self::Class* #t1 = c in #t1 == null ?{() →* void} null : #t1.{self::Class::call};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/none/tearoff_opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/none/tearoff_opt_out.dart.textual_outline.expect
new file mode 100644
index 0000000..ef070bf
--- /dev/null
+++ b/pkg/front_end/testcases/none/tearoff_opt_out.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+// @dart = 2.9
+class Class {
+  void call() {}
+}
+
+test(Class c) {}
+main() {}
diff --git a/pkg/front_end/testcases/none/tearoff_opt_out.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/none/tearoff_opt_out.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e7238f8
--- /dev/null
+++ b/pkg/front_end/testcases/none/tearoff_opt_out.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+// @dart = 2.9
+class Class {
+  void call() {}
+}
+
+main() {}
+test(Class c) {}
diff --git a/pkg/front_end/testcases/none/tearoff_opt_out.dart.weak.expect b/pkg/front_end/testcases/none/tearoff_opt_out.dart.weak.expect
new file mode 100644
index 0000000..7b89feb
--- /dev/null
+++ b/pkg/front_end/testcases/none/tearoff_opt_out.dart.weak.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method call() → void {}
+  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 method test(self::Class* c) → dynamic {
+  core::Function* f = let final self::Class* #t1 = c in #t1 == null ?{() →* void} null : #t1.{self::Class::call};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/none/tearoff_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/none/tearoff_opt_out.dart.weak.transformed.expect
new file mode 100644
index 0000000..7b89feb
--- /dev/null
+++ b/pkg/front_end/testcases/none/tearoff_opt_out.dart.weak.transformed.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method call() → void {}
+  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 method test(self::Class* c) → dynamic {
+  core::Function* f = let final self::Class* #t1 = c in #t1 == null ?{() →* void} null : #t1.{self::Class::call};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 259a2e3..add20b0 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -22,7 +22,6 @@
 general/issue41210a: TypeCheckError
 general/issue41210b/issue41210: TypeCheckError
 general/mixin_application_override: TypeCheckError
-general/mixin_covariant2: TypeCheckError
 general/override_check_accessor_after_inference: TypeCheckError
 general/override_check_accessor_basic: TypeCheckError
 general/override_check_accessor_with_covariant_modifier: TypeCheckError
@@ -47,7 +46,4 @@
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue42603: TypeCheckError
-none/mixin_covariant: TypeCheckError
 rasta/native_is_illegal: Pass # Issue 29763
-runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
-runtime_checks_new/mixin_forwarding_stub_setter: TypeCheckError
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
index 0907c2f..c1d156b 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.expect
@@ -38,3 +38,9 @@
   const C() : this.x(1);
                     ^";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bad_constructor_redirection.dart:
+- C. (from org-dartlang-testcase:///bad_constructor_redirection.dart:6:9)
diff --git a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
index 0907c2f..c1d156b 100644
--- a/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/bad_constructor_redirection.dart.strong.transformed.expect
@@ -38,3 +38,9 @@
   const C() : this.x(1);
                     ^";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bad_constructor_redirection.dart:
+- C. (from org-dartlang-testcase:///bad_constructor_redirection.dart:6:9)
diff --git a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.expect
index e12ad9f..f42bd18 100644
--- a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.expect
@@ -37,3 +37,9 @@
   const B() : super();
                    ^";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bad_explicit_super_constructor.dart:
+- B. (from org-dartlang-testcase:///bad_explicit_super_constructor.dart:10:9)
diff --git a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.transformed.expect
index e12ad9f..f42bd18 100644
--- a/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/bad_explicit_super_constructor.dart.strong.transformed.expect
@@ -37,3 +37,9 @@
   const B() : super();
                    ^";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bad_explicit_super_constructor.dart:
+- B. (from org-dartlang-testcase:///bad_explicit_super_constructor.dart:10:9)
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect
index f3801c3..add2a41 100644
--- a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.expect
@@ -43,3 +43,9 @@
   const B();
         ^";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bad_implicit_super_constructor.dart:
+- B. (from org-dartlang-testcase:///bad_implicit_super_constructor.dart:10:9)
diff --git a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect
index f3801c3..add2a41 100644
--- a/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/bad_implicit_super_constructor.dart.strong.transformed.expect
@@ -43,3 +43,9 @@
   const B();
         ^";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///bad_implicit_super_constructor.dart:
+- B. (from org-dartlang-testcase:///bad_implicit_super_constructor.dart:10:9)
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
index 5d4096c..11d42be 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
@@ -73,7 +73,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class D extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::D::•];
+  static final field dynamic _redirecting# = <dynamic>[self::D::•];
   static factory •() → self::D*
     let dynamic #redirecting_factory = "Missing" in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
index 45530e7..6c4e211 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
@@ -75,7 +75,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class D extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::D::•];
+  static final field dynamic _redirecting# = <dynamic>[self::D::•];
   static factory •() → self::D*
     let dynamic #redirecting_factory = "Missing" in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
index fd64249..3915deb 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
@@ -75,7 +75,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class D extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::D::•];
+  static final field dynamic _redirecting# = <dynamic>[self::D::•];
   static factory •() → self::D*
     let core::String* #redirecting_factory = "Missing" in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.outline.expect b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.outline.expect
index dc7b39d..49d4750 100644
--- a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.outline.expect
@@ -21,6 +21,10 @@
   synthetic constructor •() → self::_A&Object&Mixin*
     : super core::Object::•()
     ;
+  mixin-super-stub get field() → dynamic
+    return super.{self::Mixin::field};
+  mixin-super-stub set field(dynamic value) → void
+    return super.{self::Mixin::field} = value;
   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
@@ -36,6 +40,10 @@
   synthetic constructor •() → self::_A&Object&Mixin&Mixin*
     : super self::_A&Object&Mixin::•()
     ;
+  mixin-super-stub get field() → dynamic
+    return super.{self::Mixin::field};
+  mixin-super-stub set field(dynamic value) → void
+    return super.{self::Mixin::field} = value;
 }
 class A extends self::_A&Object&Mixin&Mixin {
   synthetic constructor •() → self::A*
diff --git a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.expect b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.expect
index d480428..3324351 100644
--- a/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/duplicated_mixin.dart.strong.expect
@@ -22,6 +22,10 @@
   synthetic constructor •() → self::_A&Object&Mixin*
     : super core::Object::•()
     ;
+  mixin-super-stub get field() → dynamic
+    return super.{self::Mixin::field};
+  mixin-super-stub set field(dynamic value) → void
+    return super.{self::Mixin::field} = value;
   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
@@ -37,6 +41,10 @@
   synthetic constructor •() → self::_A&Object&Mixin&Mixin*
     : super self::_A&Object&Mixin::•()
     ;
+  mixin-super-stub get field() → dynamic
+    return super.{self::Mixin::field};
+  mixin-super-stub set field(dynamic value) → void
+    return super.{self::Mixin::field} = value;
 }
 class A extends self::_A&Object&Mixin&Mixin {
   synthetic constructor •() → self::A*
diff --git a/pkg/front_end/testcases/rasta/enum.dart.strong.expect b/pkg/front_end/testcases/rasta/enum.dart.strong.expect
index 7ae9eb8..0a4e983 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.strong.expect
@@ -34,3 +34,9 @@
   #C6 = self::Foo {index:#C4, _name:#C5}
   #C7 = <self::Foo*>[#C3, #C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum.dart:
+- Foo. (from org-dartlang-testcase:///enum.dart:5:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
index 7ae9eb8..0a4e983 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
@@ -34,3 +34,9 @@
   #C6 = self::Foo {index:#C4, _name:#C5}
   #C7 = <self::Foo*>[#C3, #C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum.dart:
+- Foo. (from org-dartlang-testcase:///enum.dart:5:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/generic_factory.dart.outline.expect b/pkg/front_end/testcases/rasta/generic_factory.dart.outline.expect
index 26382b9..7dad5eb 100644
--- a/pkg/front_end/testcases/rasta/generic_factory.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/generic_factory.dart.outline.expect
@@ -70,7 +70,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::a, self::A::b, self::A::c];
+  static final field dynamic _redirecting# = <dynamic>[self::A::a, self::A::b, self::A::c];
   constructor internal() → self::A<self::A::T*>*
     ;
   static factory a<T extends core::Object* = dynamic>() → self::A<self::A::a::T*>*
@@ -91,7 +91,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<S extends core::Object* = dynamic> extends self::A<self::B::S*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::a, self::B::b];
+  static final field dynamic _redirecting# = <dynamic>[self::B::a, self::B::b];
   constructor internal() → self::B<self::B::S*>*
     ;
   static factory a<S extends core::Object* = dynamic>() → self::B<self::B::a::S*>*
diff --git a/pkg/front_end/testcases/rasta/generic_factory.dart.strong.expect b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.expect
index 2b4efa6..e0f9879 100644
--- a/pkg/front_end/testcases/rasta/generic_factory.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.expect
@@ -73,7 +73,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::a, self::A::b, self::A::c];
+  static final field dynamic _redirecting# = <dynamic>[self::A::a, self::A::b, self::A::c];
   constructor internal() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -95,7 +95,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<S extends core::Object* = dynamic> extends self::A<self::B::S*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::a, self::B::b];
+  static final field dynamic _redirecting# = <dynamic>[self::B::a, self::B::b];
   constructor internal() → self::B<self::B::S*>*
     : super self::A::internal()
     ;
diff --git a/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect
index 20f6d97..2f7e9b4 100644
--- a/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/generic_factory.dart.strong.transformed.expect
@@ -73,7 +73,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class A<T extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::a, self::A::b, self::A::c];
+  static final field dynamic _redirecting# = <dynamic>[self::A::a, self::A::b, self::A::c];
   constructor internal() → self::A<self::A::T*>*
     : super core::Object::•()
     ;
@@ -95,7 +95,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class B<S extends core::Object* = dynamic> extends self::A<self::B::S*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::a, self::B::b];
+  static final field dynamic _redirecting# = <dynamic>[self::B::a, self::B::b];
   constructor internal() → self::B<self::B::S*>*
     : super self::A::internal()
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000002.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000002.dart.strong.transformed.expect
index 0b76554..669881c 100644
--- a/pkg/front_end/testcases/rasta/issue_000002.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000002.dart.strong.transformed.expect
@@ -25,7 +25,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field core::List<core::int*>* list = <core::int*>[1, 2, 3];
+static field core::List<core::int*>* list = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
 static method main() → dynamic {
   exp::Expect::isTrue(typ::Uint8List::fromList(self::list).{core::List::[]}(1).{core::num::==}(2));
   exp::Expect::isTrue(self::Foo::fac(10).{self::Foo::value}.{core::Object::==}(10));
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.expect
index 84c890e..f7d1185 100644
--- a/pkg/front_end/testcases/rasta/issue_000004.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.expect
@@ -18,7 +18,7 @@
   dynamic n;
   for (final dynamic #t1 in <dynamic>[1, 2, 3, 4, 5]) {
     n = #t1;
-    f = f.{core::num::*}(n as{TypeError,ForDynamic} core::num) as{TypeError} core::int*;
+    f = f.{core::num::*}(n as{TypeError,ForDynamic} core::num*) as{TypeError} core::int*;
   }
   return f;
 }
@@ -26,7 +26,7 @@
   core::int* f = 1;
   for (final dynamic #t2 in <dynamic>[1, 2, 3, 4, 5, 6]) {
     self::global = #t2;
-    f = f.{core::num::*}(self::global as{TypeError,ForDynamic} core::num) as{TypeError} core::int*;
+    f = f.{core::num::*}(self::global as{TypeError,ForDynamic} core::num*) as{TypeError} core::int*;
   }
   return f;
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect
index fd86b06..9abdbc2 100644
--- a/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000004.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
 static method fact4() → dynamic {
   core::int* f = 1;
   {
-    core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2, 3, 4].{core::Iterable::iterator};
+    core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal4<core::int*>(1, 2, 3, 4).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int* n = :sync-for-iterator.{core::Iterator::current};
       {
@@ -23,12 +23,12 @@
   core::int* f = 1;
   dynamic n;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[1, 2, 3, 4, 5].{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::_literal5<dynamic>(1, 2, 3, 4, 5).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t1 = :sync-for-iterator.{core::Iterator::current};
       {
         n = #t1;
-        f = f.{core::num::*}(n as{TypeError,ForDynamic} core::num) as{TypeError} core::int*;
+        f = f.{core::num::*}(n as{TypeError,ForDynamic} core::num*) as{TypeError} core::int*;
       }
     }
   }
@@ -37,12 +37,12 @@
 static method fact6() → dynamic {
   core::int* f = 1;
   {
-    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[1, 2, 3, 4, 5, 6].{core::Iterable::iterator};
+    core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::_literal6<dynamic>(1, 2, 3, 4, 5, 6).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
       {
         self::global = #t2;
-        f = f.{core::num::*}(self::global as{TypeError,ForDynamic} core::num) as{TypeError} core::int*;
+        f = f.{core::num::*}(self::global as{TypeError,ForDynamic} core::num*) as{TypeError} core::int*;
       }
     }
   }
diff --git a/pkg/front_end/testcases/rasta/issue_000006.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000006.dart.strong.transformed.expect
index a79616d..435535b 100644
--- a/pkg/front_end/testcases/rasta/issue_000006.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000006.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-static field core::List<core::int*>* list = <core::int*>[1, 2, 3];
+static field core::List<core::int*>* list = core::_GrowableList::_literal3<core::int*>(1, 2, 3);
 static method main() → dynamic {
   self::list.{core::List::add}(1);
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000007.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000007.dart.outline.expect
index 0c974c2..f7c2600 100644
--- a/pkg/front_end/testcases/rasta/issue_000007.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000007.dart.outline.expect
@@ -36,6 +36,8 @@
   synthetic constructor •() → self::_Sub&Base&Mixin*
     : super self::Base::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::Mixin::foo}();
 }
 class Sub extends self::_Sub&Base&Mixin {
   synthetic constructor •() → self::Sub*
diff --git a/pkg/front_end/testcases/rasta/issue_000007.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000007.dart.strong.expect
index e5824bc..d37774c 100644
--- a/pkg/front_end/testcases/rasta/issue_000007.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000007.dart.strong.expect
@@ -38,6 +38,8 @@
   synthetic constructor •() → self::_Sub&Base&Mixin*
     : super self::Base::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::Mixin::foo}();
 }
 class Sub extends self::_Sub&Base&Mixin {
   synthetic constructor •() → self::Sub*
@@ -45,5 +47,5 @@
     ;
 }
 static method main() → dynamic {
-  new self::Sub::•().{self::Mixin::foo}();
+  new self::Sub::•().{self::_Sub&Base&Mixin::foo}();
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000007.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000007.dart.strong.transformed.expect
index 232c768..2898d5a 100644
--- a/pkg/front_end/testcases/rasta/issue_000007.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000007.dart.strong.transformed.expect
@@ -57,5 +57,5 @@
     ;
 }
 static method main() → dynamic {
-  new self::Sub::•().{self::Mixin::foo}();
+  new self::Sub::•().{self::_Sub&Base&Mixin::foo}();
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000034.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000034.dart.strong.expect
index 13b1086..58227f9 100644
--- a/pkg/front_end/testcases/rasta/issue_000034.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000034.dart.strong.expect
@@ -36,3 +36,9 @@
   const C() : this.x;
               ^";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_000034.dart:
+- C. (from org-dartlang-testcase:///issue_000034.dart:6:9)
diff --git a/pkg/front_end/testcases/rasta/issue_000034.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000034.dart.strong.transformed.expect
index 13b1086..58227f9 100644
--- a/pkg/front_end/testcases/rasta/issue_000034.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000034.dart.strong.transformed.expect
@@ -36,3 +36,9 @@
   const C() : this.x;
               ^";
 }
+
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_000034.dart:
+- C. (from org-dartlang-testcase:///issue_000034.dart:6:9)
diff --git a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
index 3e7ecfd..5561da6 100644
--- a/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000042.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
   for (var x, y in []) {}
        ^^^";
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t1 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/rasta/issue_000043.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.expect
index 62fa768..dd43e98 100644
--- a/pkg/front_end/testcases/rasta/issue_000043.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   get x() → dynamic
-    return "${self::C*}".{core::String::hashCode};
+    return "${#C1}".{core::String::hashCode};
   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
@@ -19,3 +19,7 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
+
+constants  {
+  #C1 = TypeLiteralConstant(self::C*)
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect
index 9a23794..dd43e98 100644
--- a/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
   get x() → dynamic
-    return "${self::C*}".{core::String::hashCode};
+    return "${#C1}".{core::String::hashCode};
   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
@@ -20,7 +20,6 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///issue_000043.dart:6:14 -> TypeLiteralConstant(C*)
-Extra constant evaluation: evaluated: 3, effectively constant: 1
+constants  {
+  #C1 = TypeLiteralConstant(self::C*)
+}
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.outline.expect
index 2c5c77a..f560daf 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.outline.expect
@@ -29,7 +29,7 @@
 import "dart:core" as core;
 
 class C extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[self::C::good];
+  static final field dynamic _redirecting# = <dynamic>[self::C::good];
   const constructor constant() → self::C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
index 1fa41bd..24463fa 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.expect
@@ -63,7 +63,7 @@
 import "dart:core" as core;
 
 class C extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[self::C::good];
+  static final field dynamic _redirecting# = <dynamic>[self::C::good];
   const constructor constant() → self::C*
     : super core::Object::•()
     ;
@@ -110,3 +110,9 @@
 constants  {
   #C1 = self::C {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_000044.dart:
+- C.constant (from org-dartlang-testcase:///issue_000044.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
index aded6c9..1adf6a4 100644
--- a/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000044.dart.strong.transformed.expect
@@ -63,7 +63,7 @@
 import "dart:core" as core;
 
 class C extends core::Object /*hasConstConstructor*/  {
-  static field dynamic _redirecting# = <dynamic>[self::C::good];
+  static final field dynamic _redirecting# = <dynamic>[self::C::good];
   const constructor constant() → self::C*
     : super core::Object::•()
     ;
@@ -110,3 +110,9 @@
 constants  {
   #C1 = self::C {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_000044.dart:
+- C.constant (from org-dartlang-testcase:///issue_000044.dart:11:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/issue_000048.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000048.dart.outline.expect
index 4cf4cf8..8c6dce3a7 100644
--- a/pkg/front_end/testcases/rasta/issue_000048.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000048.dart.outline.expect
@@ -37,6 +37,10 @@
   synthetic constructor •(core::bool* v1, core::num* v2) → self::C*
     : super self::A::•(v1, v2)
     ;
+  mixin-super-stub get v2() → core::num*
+    return super.{self::M1::v2};
+  mixin-super-stub set v2(core::num* value) → void
+    return super.{self::M1::v2} = value;
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/rasta/issue_000048.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000048.dart.strong.expect
index 17cb090..a297249 100644
--- a/pkg/front_end/testcases/rasta/issue_000048.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000048.dart.strong.expect
@@ -39,6 +39,10 @@
   synthetic constructor •(core::bool* v1, core::num* v2) → self::C*
     : super self::A::•(v1, v2)
     ;
+  mixin-super-stub get v2() → core::num*
+    return super.{self::M1::v2};
+  mixin-super-stub set v2(core::num* value) → void
+    return super.{self::M1::v2} = value;
 }
 static method main() → dynamic {
   self::C* c = new self::C::•(true, 2);
diff --git a/pkg/front_end/testcases/rasta/issue_000067.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000067.dart.outline.expect
index aeefc63..7f34682 100644
--- a/pkg/front_end/testcases/rasta/issue_000067.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000067.dart.outline.expect
@@ -5,7 +5,7 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::foo];
+  static final field dynamic _redirecting# = <dynamic>[self::A::foo];
   constructor •() → self::A*
     ;
   static factory foo() → self::A*
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C extends self::A {
-  static field dynamic _redirecting# = <dynamic>[self::C::bar];
+  static final field dynamic _redirecting# = <dynamic>[self::C::bar];
   constructor •() → self::C*
     ;
   static factory bar() → self::C*
diff --git a/pkg/front_end/testcases/rasta/issue_000067.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000067.dart.strong.expect
index 3cd7551..72b1c0e 100644
--- a/pkg/front_end/testcases/rasta/issue_000067.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000067.dart.strong.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::foo];
+  static final field dynamic _redirecting# = <dynamic>[self::A::foo];
   constructor •() → self::A*
     : super core::Object::•() {}
   static factory foo() → self::A*
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C extends self::A {
-  static field dynamic _redirecting# = <dynamic>[self::C::bar];
+  static final field dynamic _redirecting# = <dynamic>[self::C::bar];
   constructor •() → self::C*
     : super self::A::•() {}
   static factory bar() → self::C*
diff --git a/pkg/front_end/testcases/rasta/issue_000067.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000067.dart.strong.transformed.expect
index e13110b..5286a47 100644
--- a/pkg/front_end/testcases/rasta/issue_000067.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000067.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 import "package:expect/expect.dart";
 
 class A extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::A::foo];
+  static final field dynamic _redirecting# = <dynamic>[self::A::foo];
   constructor •() → self::A*
     : super core::Object::•() {}
   static factory foo() → self::A*
@@ -24,7 +24,7 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C extends self::A {
-  static field dynamic _redirecting# = <dynamic>[self::C::bar];
+  static final field dynamic _redirecting# = <dynamic>[self::C::bar];
   constructor •() → self::C*
     : super self::A::•() {}
   static factory bar() → self::C*
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
index b0b26de..fcbc6d2 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.expect
@@ -69,3 +69,9 @@
   #C2 = <Null>[#C1]
   #C3 = self::A<core::int*, core::int*, core::List<dynamic>*> {field:#C2}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_000070.dart:
+- A.c (from org-dartlang-testcase:///issue_000070.dart:22:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
index b0b26de..41a034d 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.strong.transformed.expect
@@ -8,7 +8,7 @@
 class A<N extends core::Object* = dynamic, S extends core::Object* = dynamic, U extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   final field core::List<self::A::U*>* field;
   constructor •(self::A::N* n, self::A::S* s) → self::A<self::A::N*, self::A::S*, self::A::U*>*
-    : self::A::field = <self::A::U*>[], super core::Object::•() {
+    : self::A::field = core::_GrowableList::•<self::A::U*>(0), super core::Object::•() {
     exp::Expect::isTrue(n is self::A::N*);
     exp::Expect::isTrue(s is self::A::S*);
   }
@@ -69,3 +69,9 @@
   #C2 = <Null>[#C1]
   #C3 = self::A<core::int*, core::int*, core::List<dynamic>*> {field:#C2}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_000070.dart:
+- A.c (from org-dartlang-testcase:///issue_000070.dart:22:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/rasta/issue_000080.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000080.dart.outline.expect
index 1e6e2db..4d151fc 100644
--- a/pkg/front_end/testcases/rasta/issue_000080.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000080.dart.outline.expect
@@ -23,6 +23,12 @@
   synthetic constructor •() → self::_Foo&Object&Mixin*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::Mixin::foo}();
+  mixin-super-stub get field() → dynamic
+    return super.{self::Mixin::field};
+  mixin-super-stub set field(dynamic value) → void
+    return super.{self::Mixin::field} = value;
   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
diff --git a/pkg/front_end/testcases/rasta/issue_000080.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000080.dart.strong.expect
index a1b71ad..102e810 100644
--- a/pkg/front_end/testcases/rasta/issue_000080.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000080.dart.strong.expect
@@ -24,6 +24,12 @@
   synthetic constructor •() → self::_Foo&Object&Mixin*
     : super core::Object::•()
     ;
+  mixin-super-stub method foo() → dynamic
+    return super.{self::Mixin::foo}();
+  mixin-super-stub get field() → dynamic
+    return super.{self::Mixin::field};
+  mixin-super-stub set field(dynamic value) → void
+    return super.{self::Mixin::field} = value;
   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
@@ -40,12 +46,12 @@
     : super self::_Foo&Object&Mixin::•()
     ;
   method foo() → dynamic
-    return super.{self::Mixin::foo}();
+    return super.{self::_Foo&Object&Mixin::foo}();
   method bar() → dynamic
-    return super.{self::Mixin::field};
+    return super.{self::_Foo&Object&Mixin::field};
 }
 static method main() → dynamic {
   self::Foo* f = new self::Foo::•();
-  f.{self::Mixin::field} = 42;
+  f.{self::_Foo&Object&Mixin::field} = 42;
   core::print(f.{self::Foo::bar}());
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000080.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000080.dart.strong.transformed.expect
index 4c078d1..c8a45db 100644
--- a/pkg/front_end/testcases/rasta/issue_000080.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000080.dart.strong.transformed.expect
@@ -25,6 +25,8 @@
   synthetic constructor •() → self::_Foo&Object&Mixin*
     : super core::Object::•()
     ;
+  method foo() → dynamic
+    return 87;
   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
@@ -35,20 +37,18 @@
   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
-  method foo() → dynamic
-    return 87;
 }
 class Foo extends self::_Foo&Object&Mixin {
   synthetic constructor •() → self::Foo*
     : super self::_Foo&Object&Mixin::•()
     ;
   method foo() → dynamic
-    return super.{self::Mixin::foo}();
+    return super.{self::_Foo&Object&Mixin::foo}();
   method bar() → dynamic
-    return super.{self::Mixin::field};
+    return super.{self::_Foo&Object&Mixin::field};
 }
 static method main() → dynamic {
   self::Foo* f = new self::Foo::•();
-  f.{self::Mixin::field} = 42;
+  f.{self::_Foo&Object&Mixin::field} = 42;
   core::print(f.{self::Foo::bar}());
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
index 501253f..b1d4d3f 100644
--- a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
 }
 static method main() → dynamic {
   core::print(new self::Sub::•().{self::Sub::hashCode});
-  core::List<Null>* l = <Null>[null];
+  core::List<Null>* l = core::_GrowableList::_literal1<Null>(null);
   let final core::List<Null>* #t2 = l in let final core::int* #t3 = 0 in #t2.{core::List::[]}(#t3).{core::Object::==}(null) ?{core::String*} #t2.{core::List::[]=}(#t3, "fisk" as{TypeError} Null) : null;
 }
 
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.expect
index c19856d..92274e4 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.expect
@@ -38,3 +38,8 @@
   #C9 = "foo"
   #C10 = _in::ExternalName {name:#C9}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///native_is_illegal.dart:
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
diff --git a/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.transformed.expect
index c19856d..92274e4 100644
--- a/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/native_is_illegal.dart.strong.transformed.expect
@@ -38,3 +38,8 @@
   #C9 = "foo"
   #C10 = _in::ExternalName {name:#C9}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///native_is_illegal.dart:
+- ExternalName. (from org-dartlang-sdk:///sdk/lib/internal/internal.dart:92:9)
diff --git a/pkg/front_end/testcases/rasta/super_mixin.dart.outline.expect b/pkg/front_end/testcases/rasta/super_mixin.dart.outline.expect
index 4929577..81ef6ef 100644
--- a/pkg/front_end/testcases/rasta/super_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/super_mixin.dart.outline.expect
@@ -27,6 +27,34 @@
   synthetic constructor •() → self::_C&Super&Mixin<self::_C&Super&Mixin::V*>*
     : super self::Super::•()
     ;
+  mixin-super-stub get x() → dynamic
+    return super.{mix::Mixin::x};
+  mixin-super-stub set x(dynamic value) → void
+    return super.{mix::Mixin::x} = value;
+  mixin-super-stub get y() → dynamic
+    return super.{mix::Mixin::y};
+  mixin-super-stub set y(dynamic value) → void
+    return super.{mix::Mixin::y} = value;
+  mixin-super-stub get z() → dynamic
+    return super.{mix::Mixin::z};
+  mixin-super-stub set z(dynamic value) → void
+    return super.{mix::Mixin::z} = value;
+  mixin-super-stub get t() → self::_C&Super&Mixin::V*
+    return super.{mix::Mixin::t};
+  mixin-super-stub set t(generic-covariant-impl self::_C&Super&Mixin::V* value) → void
+    return super.{mix::Mixin::t} = value;
+  mixin-super-stub method foo() → dynamic
+    return super.{mix::Mixin::foo}();
+  mixin-super-stub method g(generic-covariant-impl self::_C&Super&Mixin::V* a) → self::_C&Super&Mixin::V*
+    return super.{mix::Mixin::g}(a);
+  mixin-super-stub method h() → dynamic
+    return super.{mix::Mixin::h}();
+  mixin-super-stub method l() → dynamic
+    return super.{mix::Mixin::l}();
+  mixin-super-stub method _privateMethod() → dynamic
+    return super.{mix::Mixin::_privateMethod}();
+  mixin-super-stub method publicMethod() → dynamic
+    return super.{mix::Mixin::publicMethod}();
 }
 class C<V extends core::Object* = dynamic> extends self::_C&Super&Mixin<self::C::V*> {
   synthetic constructor •() → self::C<self::C::V*>*
@@ -36,6 +64,34 @@
   synthetic constructor •() → self::_D&Super&Mixin*
     : super self::Super::•()
     ;
+  mixin-super-stub get x() → dynamic
+    return super.{mix::Mixin::x};
+  mixin-super-stub set x(dynamic value) → void
+    return super.{mix::Mixin::x} = value;
+  mixin-super-stub get y() → dynamic
+    return super.{mix::Mixin::y};
+  mixin-super-stub set y(dynamic value) → void
+    return super.{mix::Mixin::y} = value;
+  mixin-super-stub get z() → dynamic
+    return super.{mix::Mixin::z};
+  mixin-super-stub set z(dynamic value) → void
+    return super.{mix::Mixin::z} = value;
+  mixin-super-stub get t() → dynamic
+    return super.{mix::Mixin::t};
+  mixin-super-stub set t(generic-covariant-impl dynamic value) → void
+    return super.{mix::Mixin::t} = value;
+  mixin-super-stub method foo() → dynamic
+    return super.{mix::Mixin::foo}();
+  mixin-super-stub method g(generic-covariant-impl dynamic a) → dynamic
+    return super.{mix::Mixin::g}(a);
+  mixin-super-stub method h() → dynamic
+    return super.{mix::Mixin::h}();
+  mixin-super-stub method l() → dynamic
+    return super.{mix::Mixin::l}();
+  mixin-super-stub method _privateMethod() → dynamic
+    return super.{mix::Mixin::_privateMethod}();
+  mixin-super-stub method publicMethod() → dynamic
+    return super.{mix::Mixin::publicMethod}();
 }
 class D extends self::_D&Super&Mixin {
   synthetic constructor •() → self::D*
@@ -45,11 +101,67 @@
   synthetic constructor •() → self::C2<self::C2::V*>*
     : super self::Super::•()
     ;
+  mixin-super-stub get x() → dynamic
+    return super.{mix::Mixin::x};
+  mixin-super-stub set x(dynamic value) → void
+    return super.{mix::Mixin::x} = value;
+  mixin-super-stub get y() → dynamic
+    return super.{mix::Mixin::y};
+  mixin-super-stub set y(dynamic value) → void
+    return super.{mix::Mixin::y} = value;
+  mixin-super-stub get z() → dynamic
+    return super.{mix::Mixin::z};
+  mixin-super-stub set z(dynamic value) → void
+    return super.{mix::Mixin::z} = value;
+  mixin-super-stub get t() → self::C2::V*
+    return super.{mix::Mixin::t};
+  mixin-super-stub set t(generic-covariant-impl self::C2::V* value) → void
+    return super.{mix::Mixin::t} = value;
+  mixin-super-stub method foo() → dynamic
+    return super.{mix::Mixin::foo}();
+  mixin-super-stub method g(generic-covariant-impl self::C2::V* a) → self::C2::V*
+    return super.{mix::Mixin::g}(a);
+  mixin-super-stub method h() → dynamic
+    return super.{mix::Mixin::h}();
+  mixin-super-stub method l() → dynamic
+    return super.{mix::Mixin::l}();
+  mixin-super-stub method _privateMethod() → dynamic
+    return super.{mix::Mixin::_privateMethod}();
+  mixin-super-stub method publicMethod() → dynamic
+    return super.{mix::Mixin::publicMethod}();
 }
 class D2 = self::Super<dynamic> with mix::Mixin<dynamic> {
   synthetic constructor •() → self::D2*
     : super self::Super::•()
     ;
+  mixin-super-stub get x() → dynamic
+    return super.{mix::Mixin::x};
+  mixin-super-stub set x(dynamic value) → void
+    return super.{mix::Mixin::x} = value;
+  mixin-super-stub get y() → dynamic
+    return super.{mix::Mixin::y};
+  mixin-super-stub set y(dynamic value) → void
+    return super.{mix::Mixin::y} = value;
+  mixin-super-stub get z() → dynamic
+    return super.{mix::Mixin::z};
+  mixin-super-stub set z(dynamic value) → void
+    return super.{mix::Mixin::z} = value;
+  mixin-super-stub get t() → dynamic
+    return super.{mix::Mixin::t};
+  mixin-super-stub set t(generic-covariant-impl dynamic value) → void
+    return super.{mix::Mixin::t} = value;
+  mixin-super-stub method foo() → dynamic
+    return super.{mix::Mixin::foo}();
+  mixin-super-stub method g(generic-covariant-impl dynamic a) → dynamic
+    return super.{mix::Mixin::g}(a);
+  mixin-super-stub method h() → dynamic
+    return super.{mix::Mixin::h}();
+  mixin-super-stub method l() → dynamic
+    return super.{mix::Mixin::l}();
+  mixin-super-stub method _privateMethod() → dynamic
+    return super.{mix::Mixin::_privateMethod}();
+  mixin-super-stub method publicMethod() → dynamic
+    return super.{mix::Mixin::publicMethod}();
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/rasta/super_mixin.dart.strong.expect b/pkg/front_end/testcases/rasta/super_mixin.dart.strong.expect
index 8042da7..e19cafa 100644
--- a/pkg/front_end/testcases/rasta/super_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/super_mixin.dart.strong.expect
@@ -28,6 +28,34 @@
   synthetic constructor •() → self::_C&Super&Mixin<self::_C&Super&Mixin::V*>*
     : super self::Super::•()
     ;
+  mixin-super-stub get x() → dynamic
+    return super.{mix::Mixin::x};
+  mixin-super-stub set x(dynamic value) → void
+    return super.{mix::Mixin::x} = value;
+  mixin-super-stub get y() → dynamic
+    return super.{mix::Mixin::y};
+  mixin-super-stub set y(dynamic value) → void
+    return super.{mix::Mixin::y} = value;
+  mixin-super-stub get z() → dynamic
+    return super.{mix::Mixin::z};
+  mixin-super-stub set z(dynamic value) → void
+    return super.{mix::Mixin::z} = value;
+  mixin-super-stub get t() → self::_C&Super&Mixin::V*
+    return super.{mix::Mixin::t};
+  mixin-super-stub set t(generic-covariant-impl self::_C&Super&Mixin::V* value) → void
+    return super.{mix::Mixin::t} = value;
+  mixin-super-stub method foo() → dynamic
+    return super.{mix::Mixin::foo}();
+  mixin-super-stub method g(generic-covariant-impl self::_C&Super&Mixin::V* a) → self::_C&Super&Mixin::V*
+    return super.{mix::Mixin::g}(a);
+  mixin-super-stub method h() → dynamic
+    return super.{mix::Mixin::h}();
+  mixin-super-stub method l() → dynamic
+    return super.{mix::Mixin::l}();
+  mixin-super-stub method _privateMethod() → dynamic
+    return super.{mix::Mixin::_privateMethod}();
+  mixin-super-stub method publicMethod() → dynamic
+    return super.{mix::Mixin::publicMethod}();
 }
 class C<V extends core::Object* = dynamic> extends self::_C&Super&Mixin<self::C::V*> {
   synthetic constructor •() → self::C<self::C::V*>*
@@ -38,6 +66,34 @@
   synthetic constructor •() → self::_D&Super&Mixin*
     : super self::Super::•()
     ;
+  mixin-super-stub get x() → dynamic
+    return super.{mix::Mixin::x};
+  mixin-super-stub set x(dynamic value) → void
+    return super.{mix::Mixin::x} = value;
+  mixin-super-stub get y() → dynamic
+    return super.{mix::Mixin::y};
+  mixin-super-stub set y(dynamic value) → void
+    return super.{mix::Mixin::y} = value;
+  mixin-super-stub get z() → dynamic
+    return super.{mix::Mixin::z};
+  mixin-super-stub set z(dynamic value) → void
+    return super.{mix::Mixin::z} = value;
+  mixin-super-stub get t() → dynamic
+    return super.{mix::Mixin::t};
+  mixin-super-stub set t(generic-covariant-impl dynamic value) → void
+    return super.{mix::Mixin::t} = value;
+  mixin-super-stub method foo() → dynamic
+    return super.{mix::Mixin::foo}();
+  mixin-super-stub method g(generic-covariant-impl dynamic a) → dynamic
+    return super.{mix::Mixin::g}(a);
+  mixin-super-stub method h() → dynamic
+    return super.{mix::Mixin::h}();
+  mixin-super-stub method l() → dynamic
+    return super.{mix::Mixin::l}();
+  mixin-super-stub method _privateMethod() → dynamic
+    return super.{mix::Mixin::_privateMethod}();
+  mixin-super-stub method publicMethod() → dynamic
+    return super.{mix::Mixin::publicMethod}();
 }
 class D extends self::_D&Super&Mixin {
   synthetic constructor •() → self::D*
@@ -48,15 +104,71 @@
   synthetic constructor •() → self::C2<self::C2::V*>*
     : super self::Super::•()
     ;
+  mixin-super-stub get x() → dynamic
+    return super.{mix::Mixin::x};
+  mixin-super-stub set x(dynamic value) → void
+    return super.{mix::Mixin::x} = value;
+  mixin-super-stub get y() → dynamic
+    return super.{mix::Mixin::y};
+  mixin-super-stub set y(dynamic value) → void
+    return super.{mix::Mixin::y} = value;
+  mixin-super-stub get z() → dynamic
+    return super.{mix::Mixin::z};
+  mixin-super-stub set z(dynamic value) → void
+    return super.{mix::Mixin::z} = value;
+  mixin-super-stub get t() → self::C2::V*
+    return super.{mix::Mixin::t};
+  mixin-super-stub set t(generic-covariant-impl self::C2::V* value) → void
+    return super.{mix::Mixin::t} = value;
+  mixin-super-stub method foo() → dynamic
+    return super.{mix::Mixin::foo}();
+  mixin-super-stub method g(generic-covariant-impl self::C2::V* a) → self::C2::V*
+    return super.{mix::Mixin::g}(a);
+  mixin-super-stub method h() → dynamic
+    return super.{mix::Mixin::h}();
+  mixin-super-stub method l() → dynamic
+    return super.{mix::Mixin::l}();
+  mixin-super-stub method _privateMethod() → dynamic
+    return super.{mix::Mixin::_privateMethod}();
+  mixin-super-stub method publicMethod() → dynamic
+    return super.{mix::Mixin::publicMethod}();
 }
 class D2 = self::Super<dynamic> with mix::Mixin<dynamic> {
   synthetic constructor •() → self::D2*
     : super self::Super::•()
     ;
+  mixin-super-stub get x() → dynamic
+    return super.{mix::Mixin::x};
+  mixin-super-stub set x(dynamic value) → void
+    return super.{mix::Mixin::x} = value;
+  mixin-super-stub get y() → dynamic
+    return super.{mix::Mixin::y};
+  mixin-super-stub set y(dynamic value) → void
+    return super.{mix::Mixin::y} = value;
+  mixin-super-stub get z() → dynamic
+    return super.{mix::Mixin::z};
+  mixin-super-stub set z(dynamic value) → void
+    return super.{mix::Mixin::z} = value;
+  mixin-super-stub get t() → dynamic
+    return super.{mix::Mixin::t};
+  mixin-super-stub set t(generic-covariant-impl dynamic value) → void
+    return super.{mix::Mixin::t} = value;
+  mixin-super-stub method foo() → dynamic
+    return super.{mix::Mixin::foo}();
+  mixin-super-stub method g(generic-covariant-impl dynamic a) → dynamic
+    return super.{mix::Mixin::g}(a);
+  mixin-super-stub method h() → dynamic
+    return super.{mix::Mixin::h}();
+  mixin-super-stub method l() → dynamic
+    return super.{mix::Mixin::l}();
+  mixin-super-stub method _privateMethod() → dynamic
+    return super.{mix::Mixin::_privateMethod}();
+  mixin-super-stub method publicMethod() → dynamic
+    return super.{mix::Mixin::publicMethod}();
 }
 static method main() → dynamic {
-  core::print(new self::C::•<dynamic>().{mix::Mixin::foo}());
-  core::print(new self::C2::•<dynamic>().{mix::Mixin::foo}());
+  core::print(new self::C::•<dynamic>().{self::_C&Super&Mixin::foo}());
+  core::print(new self::C2::•<dynamic>().{self::C2::foo}());
 }
 
 library test.mixin_library;
diff --git a/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect b/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect
index 46122d2..d9cda9f 100644
--- a/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/type_literals.dart.strong.expect
@@ -291,14 +291,14 @@
     : super core::Object::•()
     ;
   method test() → dynamic {
-    self::C<dynamic>*;
-    self::use(self::C<dynamic>*);
-    dynamic;
-    self::use(dynamic);
+    #C1;
+    self::use(#C1);
+    #C2;
+    self::use(#C2);
     self::C::T*;
     self::use(self::C::T*);
-    () →* void;
-    self::use(() →* void);
+    #C3;
+    self::use(#C3);
     new self::C::•<dynamic>();
     self::use(new self::C::•<dynamic>());
     invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:22:5: Error: Method not found: 'dynamic'.
@@ -439,16 +439,16 @@
     self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:72:11: Error: Can't assign to a type literal.
     use(--Func);
           ^^^^");
-    self::C<dynamic>*.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Can't assign to a type literal.
+    (#C1).{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Can't assign to a type literal.
     C ??= 42;
     ^" : null;
-    self::use(let final core::Type* #t1 = self::C<dynamic>* in #t1.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Can't assign to a type literal.
+    self::use(let final core::Type* #t1 = #C1 in #t1.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Can't assign to a type literal.
     use(C ??= 42);
         ^" : #t1);
-    dynamic.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Can't assign to a type literal.
+    (#C2).{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Can't assign to a type literal.
     dynamic ??= 42;
     ^^^^^^^" : null;
-    self::use(let final core::Type* #t2 = dynamic in #t2.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Can't assign to a type literal.
+    self::use(let final core::Type* #t2 = #C2 in #t2.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Can't assign to a type literal.
     use(dynamic ??= 42);
         ^^^^^^^" : #t2);
     self::C::T*.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:78:5: Error: Can't assign to a type literal.
@@ -457,10 +457,10 @@
     self::use(let final core::Type* #t3 = self::C::T* in #t3.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:79:9: Error: Can't assign to a type literal.
     use(T ??= 42);
         ^" : #t3);
-    () →* void.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Can't assign to a type literal.
+    (#C3).{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Can't assign to a type literal.
     Func ??= 42;
     ^^^^" : null;
-    self::use(let final core::Type* #t4 = () →* void in #t4.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Can't assign to a type literal.
+    self::use(let final core::Type* #t4 = #C3 in #t4.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Can't assign to a type literal.
     use(Func ??= 42);
         ^^^^" : #t4);
     invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:83:5: Error: Can't assign to a type literal.
@@ -530,3 +530,9 @@
 static method main() → dynamic {
   new self::C::•<dynamic>().{self::C::test}();
 }
+
+constants  {
+  #C1 = TypeLiteralConstant(self::C<dynamic>*)
+  #C2 = TypeLiteralConstant(dynamic)
+  #C3 = TypeLiteralConstant(() →* void)
+}
diff --git a/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect
index 31ed6a4..dfb5a65 100644
--- a/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect
@@ -291,14 +291,14 @@
     : super core::Object::•()
     ;
   method test() → dynamic {
-    self::C<dynamic>*;
-    self::use(self::C<dynamic>*);
-    dynamic;
-    self::use(dynamic);
+    #C1;
+    self::use(#C1);
+    #C2;
+    self::use(#C2);
     self::C::T*;
     self::use(self::C::T*);
-    () →* void;
-    self::use(() →* void);
+    #C3;
+    self::use(#C3);
     new self::C::•<dynamic>();
     self::use(new self::C::•<dynamic>());
     invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:22:5: Error: Method not found: 'dynamic'.
@@ -439,16 +439,16 @@
     self::use(invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:72:11: Error: Can't assign to a type literal.
     use(--Func);
           ^^^^");
-    self::C<dynamic>*.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Can't assign to a type literal.
+    (#C1).{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:74:5: Error: Can't assign to a type literal.
     C ??= 42;
     ^" : null;
-    self::use(let final core::Type* #t1 = self::C<dynamic>* in #t1.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Can't assign to a type literal.
+    self::use(let final core::Type* #t1 = #C1 in #t1.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:75:9: Error: Can't assign to a type literal.
     use(C ??= 42);
         ^" : #t1);
-    dynamic.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Can't assign to a type literal.
+    (#C2).{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:76:5: Error: Can't assign to a type literal.
     dynamic ??= 42;
     ^^^^^^^" : null;
-    self::use(let final core::Type* #t2 = dynamic in #t2.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Can't assign to a type literal.
+    self::use(let final core::Type* #t2 = #C2 in #t2.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:77:9: Error: Can't assign to a type literal.
     use(dynamic ??= 42);
         ^^^^^^^" : #t2);
     self::C::T*.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:78:5: Error: Can't assign to a type literal.
@@ -457,10 +457,10 @@
     self::use(let final core::Type* #t3 = self::C::T* in #t3.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:79:9: Error: Can't assign to a type literal.
     use(T ??= 42);
         ^" : #t3);
-    () →* void.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Can't assign to a type literal.
+    (#C3).{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:80:5: Error: Can't assign to a type literal.
     Func ??= 42;
     ^^^^" : null;
-    self::use(let final core::Type* #t4 = () →* void in #t4.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Can't assign to a type literal.
+    self::use(let final core::Type* #t4 = #C3 in #t4.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:81:9: Error: Can't assign to a type literal.
     use(Func ??= 42);
         ^^^^" : #t4);
     invalid-expression "pkg/front_end/testcases/rasta/type_literals.dart:83:5: Error: Can't assign to a type literal.
@@ -531,18 +531,17 @@
   new self::C::•<dynamic>().{self::C::test}();
 }
 
+constants  {
+  #C1 = TypeLiteralConstant(self::C<dynamic>*)
+  #C2 = TypeLiteralConstant(dynamic)
+  #C3 = TypeLiteralConstant(() →* void)
+}
 
 Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:11:5 -> TypeLiteralConstant(C<dynamic>*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:12:9 -> TypeLiteralConstant(C<dynamic>*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:13:5 -> TypeLiteralConstant(dynamic)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:14:9 -> TypeLiteralConstant(dynamic)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:17:5 -> TypeLiteralConstant(void Function()*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:18:9 -> TypeLiteralConstant(void Function()*)
 Evaluated: ConditionalExpression @ org-dartlang-testcase:///type_literals.dart:74:7 -> NullConstant(null)
 Evaluated: Let @ org-dartlang-testcase:///type_literals.dart:75:11 -> TypeLiteralConstant(C<dynamic>*)
 Evaluated: ConditionalExpression @ org-dartlang-testcase:///type_literals.dart:76:13 -> NullConstant(null)
 Evaluated: Let @ org-dartlang-testcase:///type_literals.dart:77:17 -> TypeLiteralConstant(dynamic)
 Evaluated: ConditionalExpression @ org-dartlang-testcase:///type_literals.dart:80:10 -> NullConstant(null)
 Evaluated: Let @ org-dartlang-testcase:///type_literals.dart:81:14 -> TypeLiteralConstant(void Function()*)
-Extra constant evaluation: evaluated: 72, effectively constant: 12
+Extra constant evaluation: evaluated: 66, effectively constant: 6
diff --git a/pkg/front_end/testcases/rasta/typedef.dart.strong.expect b/pkg/front_end/testcases/rasta/typedef.dart.strong.expect
index 777322c..e46b1bf 100644
--- a/pkg/front_end/testcases/rasta/typedef.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/typedef.dart.strong.expect
@@ -19,14 +19,18 @@
 
 typedef Foo = () →* void;
 static method main() → dynamic {
-  core::print(() →* void);
+  core::print(#C1);
   invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:9:3: Error: Can't assign to a type literal.
   Foo = null;
   ^^^";
-  () →* void.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Can't assign to a type literal.
+  (#C1).{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Can't assign to a type literal.
   Foo ??= null;
   ^^^" : null;
   invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:11:3: Error: Method not found: 'Foo'.
   Foo();
   ^^^";
 }
+
+constants  {
+  #C1 = TypeLiteralConstant(() →* void)
+}
diff --git a/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect
index 625cf29..611a358 100644
--- a/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect
@@ -19,11 +19,11 @@
 
 typedef Foo = () →* void;
 static method main() → dynamic {
-  core::print(() →* void);
+  core::print(#C1);
   invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:9:3: Error: Can't assign to a type literal.
   Foo = null;
   ^^^";
-  () →* void.{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Can't assign to a type literal.
+  (#C1).{core::Type::==}(null) ?{dynamic} invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:10:3: Error: Can't assign to a type literal.
   Foo ??= null;
   ^^^" : null;
   invalid-expression "pkg/front_end/testcases/rasta/typedef.dart:11:3: Error: Method not found: 'Foo'.
@@ -31,8 +31,10 @@
   ^^^";
 }
 
+constants  {
+  #C1 = TypeLiteralConstant(() →* void)
+}
 
 Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///typedef.dart:8:9 -> TypeLiteralConstant(void Function()*)
 Evaluated: ConditionalExpression @ org-dartlang-testcase:///typedef.dart:10:7 -> NullConstant(null)
-Extra constant evaluation: evaluated: 3, effectively constant: 2
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
index 8a74c31..eda1e6f 100644
--- a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
@@ -109,7 +109,7 @@
       invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:14:10: Error: Can't assign to a type literal.
     for (Fisk in x) {
          ^^^^";
-      core::print(self::Fisk*);
+      core::print(#C1);
     }
     for (final dynamic #t3 in x as{TypeError,ForDynamic} core::Iterable<dynamic>*) {
       invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:17:10: Error: A prefix can't be used as an expression.
@@ -123,7 +123,7 @@
       invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:20:10: Error: Can't assign to a type literal.
     for (VoidFunction in x) {
          ^^^^^^^^^^^^";
-      core::print(() →* void);
+      core::print(#C2);
     }
     {
       invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Can't assign to this, so it can't be used in a for-in loop.
@@ -167,7 +167,7 @@
     invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:34:8: Error: Can't assign to a type literal.
   for (Fisk in arguments) {
        ^^^^";
-    core::print(self::Fisk*);
+    core::print(#C1);
   }
   for (final dynamic #t8 in arguments as{TypeError,ForDynamic} core::Iterable<dynamic>*) {
     invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:37:8: Error: A prefix can't be used as an expression.
@@ -181,7 +181,7 @@
     invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:40:8: Error: Can't assign to a type literal.
   for (VoidFunction in arguments) {
        ^^^^^^^^^^^^";
-    core::print(() →* void);
+    core::print(#C2);
   }
   {
     invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:43:8: Error: Can't assign to this, so it can't be used in a for-in loop.
@@ -198,3 +198,8 @@
     }
   }
 }
+
+constants  {
+  #C1 = TypeLiteralConstant(self::Fisk*)
+  #C2 = TypeLiteralConstant(() →* void)
+}
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
index 85061fb..c8cfe5a 100644
--- a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
@@ -119,7 +119,7 @@
           invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:14:10: Error: Can't assign to a type literal.
     for (Fisk in x) {
          ^^^^";
-          core::print(self::Fisk*);
+          core::print(#C1);
         }
       }
     }
@@ -145,7 +145,7 @@
           invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:20:10: Error: Can't assign to a type literal.
     for (VoidFunction in x) {
          ^^^^^^^^^^^^";
-          core::print(() →* void);
+          core::print(#C2);
         }
       }
     }
@@ -207,7 +207,7 @@
         invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:34:8: Error: Can't assign to a type literal.
   for (Fisk in arguments) {
        ^^^^";
-        core::print(self::Fisk*);
+        core::print(#C1);
       }
     }
   }
@@ -233,7 +233,7 @@
         invalid-expression "pkg/front_end/testcases/rasta/unresolved_for_in.dart:40:8: Error: Can't assign to a type literal.
   for (VoidFunction in arguments) {
        ^^^^^^^^^^^^";
-        core::print(() →* void);
+        core::print(#C2);
       }
     }
   }
@@ -259,10 +259,7 @@
   }
 }
 
-
-Extra constant evaluation status:
-Evaluated: TypeLiteral @ org-dartlang-testcase:///unresolved_for_in.dart:15:13 -> TypeLiteralConstant(Fisk*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///unresolved_for_in.dart:21:13 -> TypeLiteralConstant(void Function()*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///unresolved_for_in.dart:35:11 -> TypeLiteralConstant(Fisk*)
-Evaluated: TypeLiteral @ org-dartlang-testcase:///unresolved_for_in.dart:41:11 -> TypeLiteralConstant(void Function()*)
-Extra constant evaluation: evaluated: 85, effectively constant: 4
+constants  {
+  #C1 = TypeLiteralConstant(self::Fisk*)
+  #C2 = TypeLiteralConstant(() →* void)
+}
diff --git a/pkg/front_end/testcases/regress/issue_29937.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29937.dart.strong.transformed.expect
index 07a6b9a7..462aa91 100644
--- a/pkg/front_end/testcases/regress/issue_29937.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29937.dart.strong.transformed.expect
@@ -7,7 +7,8 @@
 //    ^
 //
 import self as self;
+import "dart:core" as core;
 
 static method main() → dynamic {
-  <() →* Null>[let final () →* Null f = () → Null {} in f];
+  core::_GrowableList::_literal1<() →* Null>(let final () →* Null f = () → Null {} in f);
 }
diff --git a/pkg/front_end/testcases/regress/issue_29977.dart.outline.expect b/pkg/front_end/testcases/regress/issue_29977.dart.outline.expect
index 7c9a95c..f162b6e 100644
--- a/pkg/front_end/testcases/regress/issue_29977.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_29977.dart.outline.expect
@@ -15,4 +15,11 @@
   ;
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_29977.dart:5:8: Error: Expected a URI.
+// import 'data:async';
+//        ^
+//
 import self as self2;
diff --git a/pkg/front_end/testcases/regress/issue_29977.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29977.dart.strong.expect
index b940300..2709154 100644
--- a/pkg/front_end/testcases/regress/issue_29977.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29977.dart.strong.expect
@@ -14,4 +14,11 @@
 static method main() → dynamic {}
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_29977.dart:5:8: Error: Expected a URI.
+// import 'data:async';
+//        ^
+//
 import self as self2;
diff --git a/pkg/front_end/testcases/regress/issue_29977.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29977.dart.strong.transformed.expect
index b940300..2709154 100644
--- a/pkg/front_end/testcases/regress/issue_29977.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29977.dart.strong.transformed.expect
@@ -14,4 +14,11 @@
 static method main() → dynamic {}
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_29977.dart:5:8: Error: Expected a URI.
+// import 'data:async';
+//        ^
+//
 import self as self2;
diff --git a/pkg/front_end/testcases/regress/issue_29987.dart.outline.expect b/pkg/front_end/testcases/regress/issue_29987.dart.outline.expect
index 31663c2..25fefc3 100644
--- a/pkg/front_end/testcases/regress/issue_29987.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_29987.dart.outline.expect
@@ -15,4 +15,11 @@
   ;
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_29987.dart:5:8: Error: Expected a URI.
+// import "dart_:core";
+//        ^
+//
 import self as self2;
diff --git a/pkg/front_end/testcases/regress/issue_29987.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29987.dart.strong.expect
index 1a60106..4430e45 100644
--- a/pkg/front_end/testcases/regress/issue_29987.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29987.dart.strong.expect
@@ -14,4 +14,11 @@
 static method main() → dynamic {}
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_29987.dart:5:8: Error: Expected a URI.
+// import "dart_:core";
+//        ^
+//
 import self as self2;
diff --git a/pkg/front_end/testcases/regress/issue_29987.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29987.dart.strong.transformed.expect
index 1a60106..4430e45 100644
--- a/pkg/front_end/testcases/regress/issue_29987.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29987.dart.strong.transformed.expect
@@ -14,4 +14,11 @@
 static method main() → dynamic {}
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_29987.dart:5:8: Error: Expected a URI.
+// import "dart_:core";
+//        ^
+//
 import self as self2;
diff --git a/pkg/front_end/testcases/regress/issue_30994.dart.outline.expect b/pkg/front_end/testcases/regress/issue_30994.dart.outline.expect
index 468c487..248fabb 100644
--- a/pkg/front_end/testcases/regress/issue_30994.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_30994.dart.outline.expect
@@ -43,28 +43,77 @@
   ;
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:6:6: Error: Expected a URI.
+// part '$foo';
+//      ^
+//
 import self as self2;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:7:6: Error: Expected a URI.
+// part '$foo/bar';
+//      ^
+//
 import self as self3;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:8:6: Error: Expected a URI.
+// part '$for/bar';
+//      ^
+//
 import self as self4;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:9:6: Error: Expected a URI.
+// part '${true}';
+//      ^
+//
 import self as self5;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:10:6: Error: Expected a URI.
+// part 'the${1}thing';
+//      ^
+//
 import self as self6;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:11:6: Error: Expected a URI.
+// part 'part_$foo${'a'}.dart';
+//      ^
+//
 import self as self7;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:12:6: Error: Expected a URI.
+// part 'part_${'a'}_$foo.dart';
+//      ^
+//
 import self as self8;
diff --git a/pkg/front_end/testcases/regress/issue_30994.dart.strong.expect b/pkg/front_end/testcases/regress/issue_30994.dart.strong.expect
index 99b330c..212f13d 100644
--- a/pkg/front_end/testcases/regress/issue_30994.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_30994.dart.strong.expect
@@ -42,28 +42,77 @@
 static method main() → dynamic {}
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:6:6: Error: Expected a URI.
+// part '$foo';
+//      ^
+//
 import self as self2;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:7:6: Error: Expected a URI.
+// part '$foo/bar';
+//      ^
+//
 import self as self3;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:8:6: Error: Expected a URI.
+// part '$for/bar';
+//      ^
+//
 import self as self4;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:9:6: Error: Expected a URI.
+// part '${true}';
+//      ^
+//
 import self as self5;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:10:6: Error: Expected a URI.
+// part 'the${1}thing';
+//      ^
+//
 import self as self6;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:11:6: Error: Expected a URI.
+// part 'part_$foo${'a'}.dart';
+//      ^
+//
 import self as self7;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:12:6: Error: Expected a URI.
+// part 'part_${'a'}_$foo.dart';
+//      ^
+//
 import self as self8;
diff --git a/pkg/front_end/testcases/regress/issue_30994.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_30994.dart.strong.transformed.expect
index 99b330c..212f13d 100644
--- a/pkg/front_end/testcases/regress/issue_30994.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_30994.dart.strong.transformed.expect
@@ -42,28 +42,77 @@
 static method main() → dynamic {}
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:6:6: Error: Expected a URI.
+// part '$foo';
+//      ^
+//
 import self as self2;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:7:6: Error: Expected a URI.
+// part '$foo/bar';
+//      ^
+//
 import self as self3;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:8:6: Error: Expected a URI.
+// part '$for/bar';
+//      ^
+//
 import self as self4;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:9:6: Error: Expected a URI.
+// part '${true}';
+//      ^
+//
 import self as self5;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:10:6: Error: Expected a URI.
+// part 'the${1}thing';
+//      ^
+//
 import self as self6;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:11:6: Error: Expected a URI.
+// part 'part_$foo${'a'}.dart';
+//      ^
+//
 import self as self7;
 
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_30994.dart:12:6: Error: Expected a URI.
+// part 'part_${'a'}_$foo.dart';
+//      ^
+//
 import self as self8;
diff --git a/pkg/front_end/testcases/regress/issue_32182.dart.outline.expect b/pkg/front_end/testcases/regress/issue_32182.dart.outline.expect
index e38eaf6..2836f3f 100644
--- a/pkg/front_end/testcases/regress/issue_32182.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_32182.dart.outline.expect
@@ -38,6 +38,8 @@
   synthetic constructor •() → self::_C&A&M*
     : super self::A::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M::m}();
 }
 class C extends self::_C&A&M {
   synthetic constructor •() → self::C*
diff --git a/pkg/front_end/testcases/regress/issue_32182.dart.strong.expect b/pkg/front_end/testcases/regress/issue_32182.dart.strong.expect
index c3df437..4714ed4 100644
--- a/pkg/front_end/testcases/regress/issue_32182.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_32182.dart.strong.expect
@@ -40,6 +40,8 @@
   synthetic constructor •() → self::_C&A&M*
     : super self::A::•()
     ;
+  mixin-super-stub method m() → dynamic
+    return super.{self::M::m}();
 }
 class C extends self::_C&A&M {
   synthetic constructor •() → self::C*
@@ -47,5 +49,5 @@
     ;
 }
 static method main() → dynamic {
-  new self::C::•().{self::M::m}().+(1);
+  new self::C::•().{self::_C&A&M::m}().+(1);
 }
diff --git a/pkg/front_end/testcases/regress/issue_32182.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_32182.dart.strong.transformed.expect
index 07cd589..3c0ad85 100644
--- a/pkg/front_end/testcases/regress/issue_32182.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_32182.dart.strong.transformed.expect
@@ -59,5 +59,5 @@
     ;
 }
 static method main() → dynamic {
-  new self::C::•().{self::M::m}().+(1);
+  new self::C::•().{self::_C&A&M::m}().+(1);
 }
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect b/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect
index ad6b170..d282494 100644
--- a/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.outline.expect
@@ -2,16 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
-// class E extends D {
-//       ^
-// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
-//   foo(int x) => x;
-//   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
-//   foo(int x, {int y});
-//   ^
-//
 // pkg/front_end/testcases/regress/issue_32660.dart:13:7: Error: The implementation of 'foo' in the non-abstract class 'C' does not conform to its interface.
 // class C extends A implements B {
 //       ^
@@ -22,6 +12,16 @@
 //   foo(int x, {int y}) => y;
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
+// class E extends D {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
+//   foo(int x) => x;
+//   ^
+// pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
+//   foo(int x, {int y});
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect b/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect
index 32e4786..3493cad 100644
--- a/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.strong.expect
@@ -2,16 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
-// class E extends D {
-//       ^
-// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
-//   foo(int x) => x;
-//   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
-//   foo(int x, {int y});
-//   ^
-//
 // pkg/front_end/testcases/regress/issue_32660.dart:13:7: Error: The implementation of 'foo' in the non-abstract class 'C' does not conform to its interface.
 // class C extends A implements B {
 //       ^
@@ -22,6 +12,16 @@
 //   foo(int x, {int y}) => y;
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
+// class E extends D {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
+//   foo(int x) => x;
+//   ^
+// pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
+//   foo(int x, {int y});
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_32660.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_32660.dart.strong.transformed.expect
index 32e4786..3493cad 100644
--- a/pkg/front_end/testcases/regress/issue_32660.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_32660.dart.strong.transformed.expect
@@ -2,16 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
-// class E extends D {
-//       ^
-// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
-//   foo(int x) => x;
-//   ^
-// pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
-//   foo(int x, {int y});
-//   ^
-//
 // pkg/front_end/testcases/regress/issue_32660.dart:13:7: Error: The implementation of 'foo' in the non-abstract class 'C' does not conform to its interface.
 // class C extends A implements B {
 //       ^
@@ -22,6 +12,16 @@
 //   foo(int x, {int y}) => y;
 //   ^
 //
+// pkg/front_end/testcases/regress/issue_32660.dart:24:7: Error: The implementation of 'foo' in the non-abstract class 'E' does not conform to its interface.
+// class E extends D {
+//       ^
+// pkg/front_end/testcases/regress/issue_32660.dart:21:3: Context: The method 'D.foo' has fewer named arguments than those of overridden method 'E.foo'.
+//   foo(int x) => x;
+//   ^
+// pkg/front_end/testcases/regress/issue_32660.dart:25:3: Context: This is the overridden method ('foo').
+//   foo(int x, {int y});
+//   ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/regress/issue_34403.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34403.dart.strong.expect
index 00208c5..d4c306b 100644
--- a/pkg/front_end/testcases/regress/issue_34403.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_34403.dart.strong.expect
@@ -187,3 +187,13 @@
   #C4 = iss::F<dynamic> {}
   #C5 = iss::F<core::String*> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_34403.dart:
+- D.foo (from org-dartlang-testcase:///issue_34403.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- F.foo (from org-dartlang-testcase:///issue_34403_lib.dart:10:9)
+
+org-dartlang-testcase:///issue_34403_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/regress/issue_34403.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34403.dart.strong.transformed.expect
index 00208c5..d4c306b 100644
--- a/pkg/front_end/testcases/regress/issue_34403.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34403.dart.strong.transformed.expect
@@ -187,3 +187,13 @@
   #C4 = iss::F<dynamic> {}
   #C5 = iss::F<core::String*> {}
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue_34403.dart:
+- D.foo (from org-dartlang-testcase:///issue_34403.dart:12:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
+- F.foo (from org-dartlang-testcase:///issue_34403_lib.dart:10:9)
+
+org-dartlang-testcase:///issue_34403_lib.dart:
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/regress/issue_35259.dart.outline.expect b/pkg/front_end/testcases/regress/issue_35259.dart.outline.expect
index b4d8b6a..3c59d21 100644
--- a/pkg/front_end/testcases/regress/issue_35259.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_35259.dart.outline.expect
@@ -29,7 +29,7 @@
 import "dart:core" as core;
 
 class Supertype extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Supertype::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Supertype::•];
   static factory •() → self::Supertype*
     let dynamic #redirecting_factory = "Unresolved" in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/regress/issue_35259.dart.strong.expect b/pkg/front_end/testcases/regress/issue_35259.dart.strong.expect
index 02e273c..c62b784 100644
--- a/pkg/front_end/testcases/regress/issue_35259.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_35259.dart.strong.expect
@@ -33,7 +33,7 @@
 import "dart:core" as core;
 
 class Supertype extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Supertype::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Supertype::•];
   static factory •() → self::Supertype*
     let dynamic #redirecting_factory = "Unresolved" in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/regress/issue_35259.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_35259.dart.strong.transformed.expect
index 0764eb8..a6ad0e6 100644
--- a/pkg/front_end/testcases/regress/issue_35259.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_35259.dart.strong.transformed.expect
@@ -33,7 +33,7 @@
 import "dart:core" as core;
 
 class Supertype extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Supertype::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Supertype::•];
   static factory •() → self::Supertype*
     let core::String* #redirecting_factory = "Unresolved" in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/regress/issue_35260.dart.outline.expect b/pkg/front_end/testcases/regress/issue_35260.dart.outline.expect
index 093fce3..474004e 100644
--- a/pkg/front_end/testcases/regress/issue_35260.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_35260.dart.outline.expect
@@ -13,7 +13,7 @@
 import "dart:core" as core;
 
 class Supertype extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Supertype::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Supertype::•];
   static factory •() → self::Supertype*
     let dynamic #redirecting_factory = self::X::• in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/regress/issue_35260.dart.strong.expect b/pkg/front_end/testcases/regress/issue_35260.dart.strong.expect
index efed883..3552933 100644
--- a/pkg/front_end/testcases/regress/issue_35260.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_35260.dart.strong.expect
@@ -17,7 +17,7 @@
 import "dart:core" as core;
 
 class Supertype extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Supertype::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Supertype::•];
   static factory •() → self::Supertype*
     let dynamic #redirecting_factory = self::X::• in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/regress/issue_35260.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_35260.dart.strong.transformed.expect
index 4101dff..414ead9ad 100644
--- a/pkg/front_end/testcases/regress/issue_35260.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_35260.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
 import "dart:core" as core;
 
 class Supertype extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::Supertype::•];
+  static final field dynamic _redirecting# = <dynamic>[self::Supertype::•];
   static factory •() → self::Supertype*
     let<BottomType> #redirecting_factory = self::X::• in invalid-expression;
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
diff --git a/pkg/front_end/testcases/regress/issue_35266.dart.outline.expect b/pkg/front_end/testcases/regress/issue_35266.dart.outline.expect
index e10101e..7f77682 100644
--- a/pkg/front_end/testcases/regress/issue_35266.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_35266.dart.outline.expect
@@ -17,14 +17,14 @@
 import "dart:core" as core;
 
 class B<T extends core::Object* = dynamic> extends self::C<self::B::T*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::foo];
+  static final field dynamic _redirecting# = <dynamic>[self::B::foo];
   constructor •() → self::B<self::B::T*>*
     ;
   static factory foo<T extends core::Object* = dynamic>() → self::B<self::B::foo::T*>*
     let dynamic #redirecting_factory = self::B::• in let self::B::foo::T* #typeArg0 = null in invalid-expression;
 }
 class C<K extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::bar];
+  static final field dynamic _redirecting# = <dynamic>[self::C::bar];
   constructor •() → self::C<self::C::K*>*
     ;
   static factory bar<K extends core::Object* = dynamic>() → self::C<self::C::bar::K*>*
diff --git a/pkg/front_end/testcases/regress/issue_35266.dart.strong.expect b/pkg/front_end/testcases/regress/issue_35266.dart.strong.expect
index cf588f4..698e95b 100644
--- a/pkg/front_end/testcases/regress/issue_35266.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_35266.dart.strong.expect
@@ -17,7 +17,7 @@
 import "dart:core" as core;
 
 class B<T extends core::Object* = dynamic> extends self::C<self::B::T*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::foo];
+  static final field dynamic _redirecting# = <dynamic>[self::B::foo];
   constructor •() → self::B<self::B::T*>*
     : super self::C::•()
     ;
@@ -25,7 +25,7 @@
     let dynamic #redirecting_factory = self::B::• in let self::B::foo::T* #typeArg0 = null in invalid-expression;
 }
 class C<K extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::bar];
+  static final field dynamic _redirecting# = <dynamic>[self::C::bar];
   constructor •() → self::C<self::C::K*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_35266.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_35266.dart.strong.transformed.expect
index 3d0f980..fd62e94 100644
--- a/pkg/front_end/testcases/regress/issue_35266.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_35266.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
 import "dart:core" as core;
 
 class B<T extends core::Object* = dynamic> extends self::C<self::B::T*> {
-  static field dynamic _redirecting# = <dynamic>[self::B::foo];
+  static final field dynamic _redirecting# = <dynamic>[self::B::foo];
   constructor •() → self::B<self::B::T*>*
     : super self::C::•()
     ;
@@ -25,7 +25,7 @@
     let<BottomType> #redirecting_factory = self::B::• in let self::B::foo::T* #typeArg0 = null in invalid-expression;
 }
 class C<K extends core::Object* = dynamic> extends core::Object {
-  static field dynamic _redirecting# = <dynamic>[self::C::bar];
+  static final field dynamic _redirecting# = <dynamic>[self::C::bar];
   constructor •() → self::C<self::C::K*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/regress/issue_39040.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_39040.dart.strong.transformed.expect
index ccb6dec..581c2ce 100644
--- a/pkg/front_end/testcases/regress/issue_39040.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_39040.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → void {
-  core::List<core::String*>* whereWasI = <core::String*>[];
+  core::List<core::String*>* whereWasI = core::_GrowableList::•<core::String*>(0);
   core::int* outer = 1;
   core::int* inner = 0;
   #L1:
diff --git a/pkg/front_end/testcases/regress/issue_42423.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_42423.dart.strong.transformed.expect
index 5913720..1ee9e4cd 100644
--- a/pkg/front_end/testcases/regress/issue_42423.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_42423.dart.strong.transformed.expect
@@ -24,7 +24,7 @@
 }
 static method test2(dynamic stringList) → dynamic {
   core::List<core::int*>* intList = block {
-    final core::List<core::int*>* #t5 = <core::int*>[];
+    final core::List<core::int*>* #t5 = core::_GrowableList::•<core::int*>(0);
     final core::Iterable<dynamic>* #t6 = stringList as{TypeError,ForDynamic} core::Iterable<dynamic>*;
     if(!#t6.{core::Object::==}(null)) {
       core::Iterator<dynamic>* :sync-for-iterator = #t6.{core::Iterable::iterator};
@@ -56,7 +56,7 @@
   } =>#t9;
 }
 static method main() → dynamic {
-  dynamic stringList = <core::String*>["string"];
+  dynamic stringList = core::_GrowableList::_literal1<core::String*>("string");
   exp::Expect::throwsTypeError(() → Null {
     self::test1(stringList);
   });
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.transformed.expect
index c696e93..6d29b6e 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
     ;
   method f1() → (self::C::T*) →* void {}
   method f2() → core::List<(self::C::T*) →* void>* {
-    return <(self::C::T*) →* void>[this.{self::C::f1}()];
+    return core::_GrowableList::_literal1<(self::C::T*) →* void>(this.{self::C::f1}());
   }
   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
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.transformed.expect
index ff20fa1..ca43160 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_null_aware.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
     ;
   method f1() → (self::C::T*) →* void {}
   method f2() → core::List<(self::C::T*) →* void>* {
-    return <(self::C::T*) →* void>[this.{self::C::f1}()];
+    return core::_GrowableList::_literal1<(self::C::T*) →* void>(this.{self::C::f1}());
   }
   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
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.transformed.expect
index cfbae18..bf505b2 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
   get f1() → (self::C::T*) →* void
     return null;
   get f2() → core::List<(self::C::T*) →* void>* {
-    return <(self::C::T*) →* void>[this.{self::C::f1}];
+    return core::_GrowableList::_literal1<(self::C::T*) →* void>(this.{self::C::f1});
   }
   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
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.transformed.expect
index b1c9392..441c6fa 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter_return_null_aware.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
   get f1() → (self::C::T*) →* void
     return null;
   get f2() → core::List<(self::C::T*) →* void>* {
-    return <(self::C::T*) →* void>[this.{self::C::f1}];
+    return core::_GrowableList::_literal1<(self::C::T*) →* void>(this.{self::C::f1});
   }
   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
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.outline.expect
index e082c30..6a35bff 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.outline.expect
@@ -54,7 +54,7 @@
     : super self::B::•()
     ;
   forwarding-stub method f(generic-covariant-impl core::int* x) → void
-    return super.{self::B::f}(x);
+    return super.{self::M::f}(x);
 }
 static method g1(self::C* c) → void
   ;
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.strong.expect
index 7e86517..9d84b87 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_in_interface_mixin.dart.strong.expect
@@ -55,7 +55,7 @@
     : super self::B::•()
     ;
   forwarding-stub method f(generic-covariant-impl core::int* x) → void
-    return super.{self::B::f}(x);
+    return super.{self::M::f}(x);
 }
 static method g1(self::C* c) → void {
   c.{self::C::f}(1);
diff --git a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.outline.expect
index 9c97b6c..4b93548 100644
--- a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.outline.expect
@@ -1,4 +1,17 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:16:7: Error: The implementation of 'x' in the non-abstract class 'D' does not conform to its interface.
+// class D extends C implements B {}
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:13:7: Context: The field 'C.x' has type 'int', which does not match the corresponding type, 'num', in the overridden setter, 'D.x'.
+//   int x;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:16:7: Context: This is the overridden method ('x').
+// class D extends C implements B {}
+//       ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.strong.expect
index 92c4e15..ef3d7b6 100644
--- a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.strong.expect
@@ -1,4 +1,17 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:16:7: Error: The implementation of 'x' in the non-abstract class 'D' does not conform to its interface.
+// class D extends C implements B {}
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:13:7: Context: The field 'C.x' has type 'int', which does not match the corresponding type, 'num', in the overridden setter, 'D.x'.
+//   int x;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:16:7: Context: This is the overridden method ('x').
+// class D extends C implements B {}
+//       ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.strong.transformed.expect
index 92c4e15..ef3d7b6 100644
--- a/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart.strong.transformed.expect
@@ -1,4 +1,17 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:16:7: Error: The implementation of 'x' in the non-abstract class 'D' does not conform to its interface.
+// class D extends C implements B {}
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:13:7: Context: The field 'C.x' has type 'int', which does not match the corresponding type, 'num', in the overridden setter, 'D.x'.
+//   int x;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/field_forwarding_stub_explicit_covariant.dart:16:7: Context: This is the overridden method ('x').
+// class D extends C implements B {}
+//       ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.strong.transformed.expect
index a31aa80..3a5d78d 100644
--- a/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/for_in_call_kinds.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
   method test() → void {
     dynamic localVar;
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t1 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -22,7 +22,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t2 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -31,7 +31,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t3 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -40,7 +40,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -49,7 +49,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t5 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -58,7 +58,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t6 = :sync-for-iterator.{core::Iterator::current};
         {
@@ -67,7 +67,7 @@
       }
     }
     {
-      core::Iterator<dynamic>* :sync-for-iterator = <dynamic>[].{core::Iterable::iterator};
+      core::Iterator<dynamic>* :sync-for-iterator = core::_GrowableList::•<dynamic>(0).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
         final dynamic #t7 = :sync-for-iterator.{core::Iterator::current};
         {
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
index d6eb674..b6f1dad 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
@@ -76,10 +76,14 @@
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
+  mixin-super-stub get x() → core::int*
+    return super.{self::M::x};
   forwarding-stub set x(generic-covariant-impl core::int* value) → void
-    return super.{self::B::x} = value;
-  forwarding-stub set y(covariant core::Object* value) → void
-    return super.{self::B::y} = value;
+    return super.{self::M::x} = value;
+  mixin-super-stub get y() → core::int*
+    return super.{self::M::y};
+  forwarding-stub set y(covariant core::int* value) → void
+    return super.{self::M::y} = value;
 }
 static method expectTypeError(() →* void callback) → void
   ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
index 6b59110..2f222f6 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
@@ -83,10 +83,14 @@
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
+  mixin-super-stub get x() → core::int*
+    return super.{self::M::x};
   forwarding-stub set x(generic-covariant-impl core::int* value) → void
-    return super.{self::B::x} = value;
-  forwarding-stub set y(covariant core::Object* value) → void
-    return super.{self::B::y} = value;
+    return super.{self::M::x} = value;
+  mixin-super-stub get y() → core::int*
+    return super.{self::M::y};
+  forwarding-stub set y(covariant core::int* value) → void
+    return super.{self::M::y} = value;
 }
 static method expectTypeError(() →* void callback) → void {
   try {
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.transformed.expect
new file mode 100644
index 0000000..419c073
--- /dev/null
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.transformed.expect
@@ -0,0 +1,126 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:51:7: Error: The mixin application class 'C' introduces an erroneous override of 'y'.
+// class C = B with M implements I<int>;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:48:7: Context: The field 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden setter, 'I.y'.
+//  - 'Object' is from 'dart:core'.
+//   int y;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart:43:12: Context: This is the overridden method ('y').
+//   void set y(covariant Object value);
+//            ^
+//
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  get x() → core::int* {
+    throw "Should not be reached";
+  }
+  set x(core::int* value) → void {
+    throw "Should not be reached";
+  }
+  get y() → core::int* {
+    throw "Should not be reached";
+  }
+  set y(core::int* value) → void {
+    throw "Should not be reached";
+  }
+  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
+}
+abstract class I<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T*>*
+    : super core::Object::•()
+    ;
+  abstract get x() → self::I::T*;
+  abstract set x(generic-covariant-impl self::I::T* value) → void;
+  abstract get y() → core::Object*;
+  abstract set y(covariant core::Object* value) → void;
+  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
+}
+class M extends core::Object {
+  field core::int* x = null;
+  field core::int* y = null;
+  synthetic constructor •() → self::M*
+    : 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
+}
+class C extends self::B implements self::I<core::int*>, self::M /*isEliminatedMixin*/  {
+  generic-covariant-impl field core::int* x = null;
+  covariant field core::int* y = null;
+  synthetic constructor •() → self::C*
+    : super self::B::•()
+    ;
+  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 method expectTypeError(() →* void callback) → void {
+  try {
+    callback.call();
+    throw "Expected TypeError, did not occur";
+  }
+  on core::TypeError* catch(no-exception-var) {
+  }
+}
+static method expect(core::Object* value, core::Object* expected) → void {
+  if(!value.{core::Object::==}(expected)) {
+    throw "Expected ${expected}, got ${value}";
+  }
+}
+static method test(self::I<core::Object*>* i) → void {
+  self::expectTypeError(() → Null {
+    i.{self::I::x} = "hello";
+  });
+  i.{self::I::x} = 1;
+  self::expect(i.{self::I::x}, 1);
+  self::expectTypeError(() → Null {
+    i.{self::I::y} = "hello";
+  });
+  i.{self::I::y} = 2;
+  self::expect(i.{self::I::y}, 2);
+}
+static method main() → void {
+  self::test(new self::C::•());
+}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
index f7e1913..3582fa0 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
@@ -83,10 +83,14 @@
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
+  mixin-super-stub get x() → core::int*
+    return super.{self::M::x};
   forwarding-stub set x(generic-covariant-impl core::int* value) → void
-    return super.{self::B::x} = value;
-  forwarding-stub set y(covariant core::Object* value) → void
-    return super.{self::B::y} = value;
+    return super.{self::M::x} = value;
+  mixin-super-stub get y() → core::int*
+    return super.{self::M::y};
+  forwarding-stub set y(covariant core::int* value) → void
+    return super.{self::M::y} = value;
 }
 static method expectTypeError(() →* void callback) → void
   ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
index 48bd4ce..743d696 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
@@ -92,10 +92,14 @@
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
+  mixin-super-stub get x() → core::int*
+    return super.{self::M::x};
   forwarding-stub set x(generic-covariant-impl core::int* value) → void
-    return super.{self::B::x} = value;
-  forwarding-stub set y(covariant core::Object* value) → void
-    return super.{self::B::y} = value;
+    return super.{self::M::x} = value;
+  mixin-super-stub get y() → core::int*
+    return super.{self::M::y};
+  forwarding-stub set y(covariant core::int* value) → void
+    return super.{self::M::y} = value;
 }
 static method expectTypeError(() →* void callback) → void {
   try {
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.transformed.expect
new file mode 100644
index 0000000..bbb9329
--- /dev/null
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.transformed.expect
@@ -0,0 +1,143 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:58:7: Error: The mixin application class 'C' introduces an erroneous override of 'y'.
+// class C = B with M implements I<int>;
+//       ^
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:53:18: Context: The parameter 'value' of the method 'M.y' has type 'int', which does not match the corresponding type, 'Object', in the overridden method, 'I.y'.
+//  - 'Object' is from 'dart:core'.
+// Change to a supertype of 'Object', or, for a covariant parameter, a subtype.
+//   void set y(int value) {
+//                  ^
+// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart:43:12: Context: This is the overridden method ('y').
+//   void set y(covariant Object value);
+//            ^
+//
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  get x() → core::int* {
+    throw "Should not be reached";
+  }
+  set x(core::int* value) → void {
+    throw "Should not be reached";
+  }
+  get y() → core::int* {
+    throw "Should not be reached";
+  }
+  set y(core::int* value) → void {
+    throw "Should not be reached";
+  }
+  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
+}
+abstract class I<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::I<self::I::T*>*
+    : super core::Object::•()
+    ;
+  abstract get x() → self::I::T*;
+  abstract set x(generic-covariant-impl self::I::T* value) → void;
+  abstract get y() → core::Object*;
+  abstract set y(covariant core::Object* value) → void;
+  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
+}
+class M extends core::Object {
+  synthetic constructor •() → self::M*
+    : super core::Object::•()
+    ;
+  get x() → core::int*
+    return 1;
+  set x(core::int* value) → void {
+    self::expect(value, 2);
+  }
+  get y() → core::int*
+    return 3;
+  set y(core::int* value) → void {
+    self::expect(value, 4);
+  }
+  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
+}
+class C extends self::B implements self::I<core::int*>, self::M /*isEliminatedMixin*/  {
+  synthetic constructor •() → self::C*
+    : super self::B::•()
+    ;
+  get x() → core::int*
+    return 1;
+  set x(generic-covariant-impl core::int* value) → void {
+    self::expect(value, 2);
+  }
+  get y() → core::int*
+    return 3;
+  set y(covariant core::int* value) → void {
+    self::expect(value, 4);
+  }
+  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 method expectTypeError(() →* void callback) → void {
+  try {
+    callback.call();
+    throw "Expected TypeError, did not occur";
+  }
+  on core::TypeError* catch(no-exception-var) {
+  }
+}
+static method expect(core::Object* value, core::Object* expected) → void {
+  if(!value.{core::Object::==}(expected)) {
+    throw "Expected ${expected}, got ${value}";
+  }
+}
+static method test(self::I<core::Object*>* i) → void {
+  self::expectTypeError(() → Null {
+    i.{self::I::x} = "hello";
+  });
+  i.{self::I::x} = 2;
+  self::expect(i.{self::I::x}, 1);
+  self::expectTypeError(() → Null {
+    i.{self::I::y} = "hello";
+  });
+  i.{self::I::y} = 4;
+  self::expect(i.{self::I::y}, 3);
+}
+static method main() → void {
+  self::test(new self::C::•());
+}
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
index aede924..0077a85 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
@@ -25,3 +25,9 @@
   #C6 = self::A {index:#C4, _name:#C5}
   #C7 = <self::A*>[#C3, #C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum.dart:
+- A. (from org-dartlang-testcase:///enum.dart:5:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
index aede924..0077a85 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
@@ -25,3 +25,9 @@
   #C6 = self::A {index:#C4, _name:#C5}
   #C7 = <self::A*>[#C3, #C6]
 }
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///enum.dart:
+- A. (from org-dartlang-testcase:///enum.dart:5:6)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart b/pkg/front_end/testcases/static_field_lowering/opt_in.dart
index c549cad..360ee61 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart
@@ -139,7 +139,7 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
+  } on Error catch (e) {
     print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
index c4ea2b5..b02a477 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
@@ -327,7 +327,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
index c4ea2b5..b02a477 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
@@ -327,7 +327,7 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError catch(final core::LateInitializationError e) {
+  on core::Error catch(final core::Error e) {
     core::print(e);
     return;
   }
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_out.dart b/pkg/front_end/testcases/static_field_lowering/opt_out.dart
index 7ca4c56..a725ecb 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_out.dart
+++ b/pkg/front_end/testcases/static_field_lowering/opt_out.dart
@@ -95,8 +95,6 @@
   dynamic value;
   try {
     value = f();
-  } on LateInitializationError catch (e) {
-    throw '$message: Unexpected LateInitializationError: $e';
   } catch (e) {
     print(e);
     return;
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_out.dart.weak.expect b/pkg/front_end/testcases/static_field_lowering/opt_out.dart.weak.expect
index 7fcf775..fe00cf4 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_out.dart.weak.expect
@@ -74,9 +74,6 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError* catch(final core::LateInitializationError* e) {
-    throw "${message}: Unexpected LateInitializationError: ${e}";
-  }
   on dynamic catch(final dynamic e) {
     core::print(e);
     return;
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/static_field_lowering/opt_out.dart.weak.transformed.expect
index 7fcf775..fe00cf4 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_out.dart.weak.transformed.expect
@@ -74,9 +74,6 @@
   try {
     value = f.call();
   }
-  on core::LateInitializationError* catch(final core::LateInitializationError* e) {
-    throw "${message}: Unexpected LateInitializationError: ${e}";
-  }
   on dynamic catch(final dynamic e) {
     core::print(e);
     return;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 8df4cda..bbb5c64 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -6,6 +6,8 @@
 # Kernel ASTs directly, that is, code in pkg/fasta/lib/src/kernel/ with
 # strong-mode enabled.
 
+# general/platform_invalid_uris/main: SemiFuzzFailure # semi fuzz fails but isn't currently enabled by default.
+
 extensions/call_methods: TypeCheckError
 extensions/extension_setter_error: TypeCheckError
 extensions/instance_access_of_static: RuntimeError
@@ -78,7 +80,7 @@
 general/mixin_application_override: ExpectationFileMismatch # Too many errors.
 general/mixin_application_override: TypeCheckError
 general/mixin_constructors_with_default_values: RuntimeError # Expected
-general/mixin_covariant2: TypeCheckError
+general/mixin_covariant2: RuntimeError
 general/operator_method_not_found: RuntimeError # Expected
 general/optional: TypeCheckError
 general/override_check_accessor_after_inference: TypeCheckError # Issue #31620
@@ -169,13 +171,16 @@
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue41180: RuntimeError # Strong mode runtime checking fails due to mixed strong mode.
-nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
 nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
 nnbd/nullable_object_access: TypeCheckError
 nnbd/nullable_receiver: TypeCheckError
 nnbd/potentially_nullable_access: TypeCheckError
-none/mixin_covariant: TypeCheckError
+none/equals: TypeCheckError
+none/method_invocation: TypeCheckError
+none/operator: TypeCheckError
+none/property_get: TypeCheckError
+none/property_set: TypeCheckError
 rasta/abstract_constructor: RuntimeError
 rasta/bad_constructor_redirection: RuntimeError
 rasta/bad_continue: RuntimeError
@@ -244,9 +249,7 @@
 regress/issue_39091_2: RuntimeError
 regress/utf_16_le_content.crash: RuntimeError
 runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast: RuntimeError
-runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
 runtime_checks_new/mixin_forwarding_stub_getter: TypeCheckError
-runtime_checks_new/mixin_forwarding_stub_setter: TypeCheckError
 set_literals/disambiguation_rule: RuntimeError
 value_class/simple: RuntimeError # Expected
 value_class/value_extends_non_value: RuntimeError # Expected
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index cdc1183..c21c124 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -24,6 +24,8 @@
 general/callable_type_variable: TypeCheckError
 general/candidate_found: TypeCheckError
 general/cascade: RuntimeError
+general/constants/with_unevaluated_agnostic/const_asserts: TextSerializationFailure
+general/constants/with_unevaluated_agnostic/various: TextSerializationFailure
 general/constructor_initializer_invalid: RuntimeError
 general/covariant_field: TypeCheckError
 general/covariant_generic: RuntimeError
@@ -77,7 +79,7 @@
 general/micro: RuntimeError
 general/mixin_application_override: TypeCheckError
 general/mixin_constructors_with_default_values: RuntimeError
-general/mixin_covariant2: TypeCheckError
+general/mixin_covariant2: RuntimeError
 general/operator_method_not_found: RuntimeError
 general/optional: TypeCheckError
 general/override_check_accessor_after_inference: TypeCheckError # Issue #31620
@@ -138,6 +140,8 @@
 general_nnbd_opt_out/type_variable_as_super: RuntimeError
 general_nnbd_opt_out/unsound_promotion: TypeCheckError
 general_nnbd_opt_out/void_methods: RuntimeError
+implicit_getter_calls/getter_call: TextSerializationFailure
+implicit_getter_calls/this_field_call: TextSerializationFailure
 inference/constructors_infer_from_arguments_argument_not_assignable: TypeCheckError
 inference/do_not_infer_overridden_fields_that_explicitly_say_dynamic_infer: TypeCheckError
 inference/downwards_inference_for_each: RuntimeError
@@ -167,13 +171,19 @@
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue41180: RuntimeError
-nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
 nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
 nnbd/nullable_object_access: TypeCheckError
 nnbd/nullable_receiver: TypeCheckError
 nnbd/potentially_nullable_access: TypeCheckError
-none/mixin_covariant: TypeCheckError
+none/equals: TypeCheckError
+none/method_invocation: TypeCheckError
+none/mixin_covariant: TextSerializationFailure
+none/operator: TypeCheckError
+none/property_get: TypeCheckError
+none/property_set: TypeCheckError
+none/mixin_super: TextSerializationFailure
+none/tearoff_opt_out: TextSerializationFailure
 rasta/abstract_constructor: RuntimeError
 rasta/bad_constructor_redirection: RuntimeError
 rasta/bad_continue: RuntimeError
@@ -242,8 +252,6 @@
 regress/issue_39091_2: RuntimeError
 regress/utf_16_le_content.crash: RuntimeError
 runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast: RuntimeError
-runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
-runtime_checks_new/mixin_forwarding_stub_setter: TypeCheckError
 set_literals/disambiguation_rule: RuntimeError
 value_class/simple: RuntimeError # Expected
 value_class/value_extends_non_value: RuntimeError # Expected
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 0553975..add6cbb 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -20,73 +20,11 @@
 regress/issue_39091_2: EmptyOutput
 regress/utf_16_le_content.crash: EmptyOutput
 
-extensions/ambiguous: FormatterCrash
-extensions/annotations: FormatterCrash
-extensions/async_extensions: FormatterCrash
-extensions/bounds: FormatterCrash
-extensions/builtin_identifiers: FormatterCrash
-extensions/call_methods: FormatterCrash
-extensions/check_bounds: FormatterCrash
-extensions/compounds: FormatterCrash
-extensions/conflict_with_object: FormatterCrash
-extensions/conflicts: FormatterCrash
-extensions/default_values: FormatterCrash
-extensions/direct_instance_access: FormatterCrash
-extensions/direct_static_access: FormatterCrash
-extensions/dynamic_invoke: FormatterCrash
-extensions/explicit_extension_access: FormatterCrash
-extensions/explicit_extension_inference: FormatterCrash
-extensions/explicit_generic_extension_access: FormatterCrash
-extensions/explicit_invalid_access: FormatterCrash
-extensions/explicit_this: FormatterCrash
-extensions/extension_call: FormatterCrash
 extensions/extension_constructor: FormatterCrash
 extensions/extension_field_with_type_parameter_usage: FormatterCrash
-extensions/extension_member_conflict: FormatterCrash
-extensions/extension_methods: FormatterCrash
-extensions/extension_setter: FormatterCrash
-extensions/extension_setter_error: FormatterCrash
-extensions/generic_function_in_generic_extension: FormatterCrash
-extensions/getter_setter_conflict: FormatterCrash
-extensions/if_null: FormatterCrash
-extensions/implicit_extension_inference: FormatterCrash
-extensions/implicit_this: FormatterCrash
-extensions/index: FormatterCrash
-extensions/instance_access: FormatterCrash
-extensions/instance_access_of_static: FormatterCrash
-extensions/instance_members: FormatterCrash
-extensions/instance_tearoff: FormatterCrash
-extensions/internal_resolution: FormatterCrash
-extensions/invalid_explicit_access: FormatterCrash
-extensions/invalid_explicit_static_access: FormatterCrash
 extensions/issue38600: FormatterCrash
 extensions/issue38712: FormatterCrash
-extensions/issue38713: FormatterCrash
 extensions/issue38745: FormatterCrash
-extensions/issue38755: FormatterCrash
-extensions/issue38915: FormatterCrash
-extensions/issue39527: FormatterCrash
-extensions/issue39889: FormatterCrash
-extensions/issue40596: FormatterCrash
-extensions/issue40713: FormatterCrash
-extensions/issue40816: FormatterCrash
-extensions/issue43218: FormatterCrash
-extensions/language_issue1182: FormatterCrash
-extensions/missing_toplevel: FormatterCrash
-extensions/nested_on_types: FormatterCrash
-extensions/null_aware: FormatterCrash
-extensions/on_function_type: FormatterCrash
-extensions/on_type_inference: FormatterCrash
-extensions/on_type_variable_inference: FormatterCrash
-extensions/operators: FormatterCrash
-extensions/other_kinds: FormatterCrash
-extensions/static_access: FormatterCrash
-extensions/static_access_of_instance: FormatterCrash
-extensions/tear_offs: FormatterCrash
-extensions/type_variable_bound: FormatterCrash
-extensions/type_variables: FormatterCrash
-extensions/unnamed_extensions: FormatterCrash
-extensions/use_this: FormatterCrash
 general/annotation_eof: FormatterCrash
 general/bad_setter_abstract: FormatterCrash
 general/bug31124: FormatterCrash
@@ -112,19 +50,15 @@
 general/error_recovery/issue_39230.crash: FormatterCrash
 general/error_recovery/issue_39958_01: FormatterCrash
 general/function_type_default_value: FormatterCrash
-general/getter_vs_setter_type: FormatterCrash
 general/incomplete_field_formal_parameter: FormatterCrash
 general/invalid_operator2: FormatterCrash
 general/invalid_operator: FormatterCrash
-general/issue40242: FormatterCrash
 general/issue42997: FormatterCrash
 general/issue43363: FormatterCrash
 general/many_errors: FormatterCrash
 general/null_safety_invalid_experiment_and_language_version: FormatterCrash
-general/type_parameter_usage_in_static_method_in_extension: FormatterCrash
 general/type_parameters_on_void: FormatterCrash
 general/var_as_type_name: FormatterCrash
-general/well_boundness_checks_in_outline: FormatterCrash
 general_nnbd_opt_out/annotation_eof: FormatterCrash
 general_nnbd_opt_out/bad_setter_abstract: FormatterCrash
 general_nnbd_opt_out/bug31124: FormatterCrash
@@ -138,7 +72,6 @@
 inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: FormatterCrash
 inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: FormatterCrash
 late_lowering/covariant_late_field: FormatterCrash
-late_lowering/definitely_unassigned: FormatterCrash
 late_lowering/getter_vs_setter_type: FormatterCrash
 late_lowering/infer_late_field_type: FormatterCrash
 late_lowering/initializer_rewrite: FormatterCrash
@@ -167,60 +100,32 @@
 late_lowering/late_lowering_bitmasks: FormatterCrash
 late_lowering/late_nullable_field_with_initializer: FormatterCrash
 late_lowering/late_nullable_field_without_initializer: FormatterCrash
+late_lowering/late_override: FormatterCrash
 late_lowering/later: FormatterCrash
 late_lowering/override: FormatterCrash
 late_lowering/override_getter_setter: FormatterCrash
 late_lowering/skip_late_final_uninitialized_instance_fields/main: FormatterCrash
 late_lowering/uninitialized_non_nullable_late_fields: FormatterCrash
-late_lowering_sentinel/late_fields: FormatterCrash
 nnbd/abstract_field_errors: FormatterCrash
 nnbd/covariant_late_field: FormatterCrash
-nnbd/definitely_unassigned: FormatterCrash
-nnbd/extension_bounds: FormatterCrash
-nnbd/extension_never: FormatterCrash
-nnbd/extension_type_variable_bound: FormatterCrash
-nnbd/external_field_errors: FormatterCrash
-nnbd/external_fields: FormatterCrash
 nnbd/forbidden_supers: FormatterCrash
-nnbd/getter_vs_setter_type: FormatterCrash
 nnbd/getter_vs_setter_type_late: FormatterCrash
-nnbd/getter_vs_setter_type_nnbd: FormatterCrash
-nnbd/infer_if_null: FormatterCrash
 nnbd/inheritance_from_opt_in: FormatterCrash
 nnbd/issue40805: FormatterCrash
-nnbd/issue41349: FormatterCrash
 nnbd/issue41597: FormatterCrash
 nnbd/issue42967: FormatterCrash
-nnbd/issue43211: FormatterCrash
-nnbd/issue43278: FormatterCrash
 nnbd/issue43354: FormatterCrash
-nnbd/issue43591: FormatterCrash
-nnbd/issue43689: FormatterCrash
-nnbd/language_issue1182: FormatterCrash
 nnbd/late: FormatterCrash
 nnbd/later: FormatterCrash
 nnbd/no_null_shorting_explicit_extension: FormatterCrash
 nnbd/no_null_shorting_extension: FormatterCrash
 nnbd/non_nullable_field_initialization: FormatterCrash
-nnbd/null_shorting_cascade: FormatterCrash
-nnbd/null_shorting_explicit_extension: FormatterCrash
-nnbd/null_shorting_extension: FormatterCrash
-nnbd/null_shorting_index: FormatterCrash
-nnbd/nullable_extension: FormatterCrash
-nnbd/nullable_setter: FormatterCrash
 nnbd/opt_out: FormatterCrash
 nnbd/potentially_non_nullable_field: FormatterCrash
-nnbd/potentially_nullable_access: FormatterCrash
-nnbd/strictly_non_nullable_warnings: FormatterCrash
 nnbd/uninitialized_non_nullable_late_fields: FormatterCrash
 nnbd_mixed/inheritance_from_opt_in: FormatterCrash
 nnbd_mixed/issue41597: FormatterCrash
-nnbd_mixed/no_null_shorting_explicit_extension: FormatterCrash
-nnbd_mixed/no_null_shorting_extension: FormatterCrash
 nnbd_mixed/null_safety_invalid_language_version: FormatterCrash
-nnbd_mixed/nullable_extension_on_opt_out: FormatterCrash
-nnbd_mixed/opt_out: FormatterCrash
-nnbd_mixed/unsound_checks: FormatterCrash
 nonfunction_type_aliases/issue41501: FormatterCrash
 rasta/bad_redirection: FormatterCrash
 rasta/issue_000032: FormatterCrash
diff --git a/pkg/front_end/testcases/unified_collections/fold_initial.dart.weak.transformed.expect b/pkg/front_end/testcases/unified_collections/fold_initial.dart.weak.transformed.expect
index 9108424..09431d2 100644
--- a/pkg/front_end/testcases/unified_collections/fold_initial.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/unified_collections/fold_initial.dart.weak.transformed.expect
@@ -8,7 +8,7 @@
   core::num* element1 = 1;
   core::int* element2 = 2;
   core::List<core::int*>* list = block {
-    final core::List<core::int*>* #t1 = <core::int*>[element0 as{TypeError,ForDynamic} core::int*, element1 as{TypeError} core::int*, element2];
+    final core::List<core::int*>* #t1 = core::_GrowableList::_literal3<core::int*>(element0 as{TypeError,ForDynamic} core::int*, element1 as{TypeError} core::int*, element2);
     if(true)
       #t1.{core::List::add}{Invariant}(3);
     #t1.{core::List::add}{Invariant}(4);
@@ -30,9 +30,9 @@
   self::expect(core::_GrowableList::generate<core::int*>(7, (core::int* i) → core::int* => i), set.{core::Iterable::toList}());
 }
 static method foldInitialSpread1() → void {
-  dynamic initial = <core::int*>[0, 1, 2];
+  dynamic initial = core::_GrowableList::_literal3<core::int*>(0, 1, 2);
   core::List<core::int*>* list = block {
-    final core::List<core::int*>* #t3 = <core::int*>[];
+    final core::List<core::int*>* #t3 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<dynamic>* :sync-for-iterator = (initial as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -71,9 +71,9 @@
   self::expect(core::_GrowableList::generate<core::int*>(7, (core::int* i) → core::int* => i), set.{core::Iterable::toList}());
 }
 static method foldInitialSpread2() → void {
-  core::Iterable<core::num*>* initial = <core::num*>[0, 1, 2];
+  core::Iterable<core::num*>* initial = core::_GrowableList::_literal3<core::num*>(0, 1, 2);
   core::List<core::int*>* list = block {
-    final core::List<core::int*>* #t9 = <core::int*>[];
+    final core::List<core::int*>* #t9 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<core::num*>* :sync-for-iterator = initial.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -112,9 +112,9 @@
   self::expect(core::_GrowableList::generate<core::int*>(7, (core::int* i) → core::int* => i), set.{core::Iterable::toList}());
 }
 static method foldInitialSpread3() → void {
-  core::List<core::num*>* initial = <core::num*>[0, 1, 2];
+  core::List<core::num*>* initial = core::_GrowableList::_literal3<core::num*>(0, 1, 2);
   core::List<core::int*>* list = block {
-    final core::List<core::int*>* #t15 = <core::int*>[];
+    final core::List<core::int*>* #t15 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<core::num*>* :sync-for-iterator = initial.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -153,7 +153,7 @@
   self::expect(core::_GrowableList::generate<core::int*>(7, (core::int* i) → core::int* => i), set.{core::Iterable::toList}());
 }
 static method foldInitialSpread4() → void {
-  core::Iterable<core::int*>* initial = <core::int*>[0, 1, 2];
+  core::Iterable<core::int*>* initial = core::_GrowableList::_literal3<core::int*>(0, 1, 2);
   core::List<core::int*>* list = block {
     final core::List<core::int*>* #t21 = core::List::of<core::int*>(initial);
     if(true)
@@ -174,7 +174,7 @@
   self::expect(core::_GrowableList::generate<core::int*>(7, (core::int* i) → core::int* => i), set.{core::Iterable::toList}());
 }
 static method foldInitialSpread5() → void {
-  core::List<core::int*>* initial = <core::int*>[0, 1, 2];
+  core::List<core::int*>* initial = core::_GrowableList::_literal3<core::int*>(0, 1, 2);
   core::List<core::int*>* list = block {
     final core::List<core::int*>* #t23 = core::List::of<core::int*>(initial);
     if(true)
@@ -195,9 +195,9 @@
   self::expect(core::_GrowableList::generate<core::int*>(7, (core::int* i) → core::int* => i), set.{core::Iterable::toList}());
 }
 static method foldInitialSpread6() → void {
-  core::List<core::int*>* initial = <core::int*>[0, 1, 2];
+  core::List<core::int*>* initial = core::_GrowableList::_literal3<core::int*>(0, 1, 2);
   core::List<core::int*>* list = block {
-    final core::List<core::int*>* #t25 = <core::int*>[];
+    final core::List<core::int*>* #t25 = core::_GrowableList::•<core::int*>(0);
     final core::Iterable<core::int*>* #t26 = initial;
     if(!#t26.{core::Object::==}(null))
       #t25.{core::List::addAll}{Invariant}(#t26);
diff --git a/pkg/front_end/testcases/unified_collections/invariance.dart.weak.transformed.expect b/pkg/front_end/testcases/unified_collections/invariance.dart.weak.transformed.expect
index 8970ba8..5655ae8 100644
--- a/pkg/front_end/testcases/unified_collections/invariance.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/unified_collections/invariance.dart.weak.transformed.expect
@@ -4,11 +4,11 @@
 import "dart:collection" as col;
 
 static method main() → dynamic {
-  core::List<core::int*>* list1 = <core::int*>[0];
-  core::List<core::num*>* list2 = <core::num*>[0];
-  dynamic list3 = <core::int*>[0];
+  core::List<core::int*>* list1 = core::_GrowableList::_literal1<core::int*>(0);
+  core::List<core::num*>* list2 = core::_GrowableList::_literal1<core::num*>(0);
+  dynamic list3 = core::_GrowableList::_literal1<core::int*>(0);
   core::List<core::int*>* list = block {
-    final core::List<core::int*>* #t1 = <core::int*>[0];
+    final core::List<core::int*>* #t1 = core::_GrowableList::_literal1<core::int*>(0);
     #t1.{core::List::addAll}{Invariant}(list1);
     {
       core::Iterator<core::num*>* :sync-for-iterator = list2.{core::Iterable::iterator};
diff --git a/pkg/front_end/testcases/unified_collections/list_add_all.dart.weak.transformed.expect b/pkg/front_end/testcases/unified_collections/list_add_all.dart.weak.transformed.expect
index 5f72074..1f0299e 100644
--- a/pkg/front_end/testcases/unified_collections/list_add_all.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/unified_collections/list_add_all.dart.weak.transformed.expect
@@ -3,16 +3,16 @@
 import "dart:core" as core;
 
 static method useAddAll() → void {
-  dynamic dynamicList1 = <core::int*>[0, 1, 2];
-  dynamic dynamicList2 = <core::num*>[3, 4, 5];
-  core::Iterable<core::int*>* iterableIntList = <core::int*>[6, 7, 8];
-  core::Iterable<core::num*>* iterableNumList1 = <core::int*>[9, 10, 11];
-  core::Iterable<core::num*>* iterableNumList2 = <core::num*>[12, 13, 14];
-  core::List<core::int*>* intList = <core::int*>[15, 16, 17];
-  core::List<core::num*>* numList1 = <core::int*>[18, 19, 20];
-  core::List<core::num*>* numList2 = <core::num*>[21, 22, 23];
+  dynamic dynamicList1 = core::_GrowableList::_literal3<core::int*>(0, 1, 2);
+  dynamic dynamicList2 = core::_GrowableList::_literal3<core::num*>(3, 4, 5);
+  core::Iterable<core::int*>* iterableIntList = core::_GrowableList::_literal3<core::int*>(6, 7, 8);
+  core::Iterable<core::num*>* iterableNumList1 = core::_GrowableList::_literal3<core::int*>(9, 10, 11);
+  core::Iterable<core::num*>* iterableNumList2 = core::_GrowableList::_literal3<core::num*>(12, 13, 14);
+  core::List<core::int*>* intList = core::_GrowableList::_literal3<core::int*>(15, 16, 17);
+  core::List<core::num*>* numList1 = core::_GrowableList::_literal3<core::int*>(18, 19, 20);
+  core::List<core::num*>* numList2 = core::_GrowableList::_literal3<core::num*>(21, 22, 23);
   core::List<core::int*>* list1 = block {
-    final core::List<core::int*>* #t1 = <core::int*>[];
+    final core::List<core::int*>* #t1 = core::_GrowableList::•<core::int*>(0);
     {
       core::Iterator<dynamic>* :sync-for-iterator = (dynamicList1 as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -78,7 +78,7 @@
   } =>#t1;
   self::expect(core::_GrowableList::generate<core::int*>(24, (core::int* i) → core::int* => i), list1);
   core::List<core::num*>* list2 = block {
-    final core::List<core::num*>* #t14 = <core::num*>[];
+    final core::List<core::num*>* #t14 = core::_GrowableList::•<core::num*>(0);
     {
       core::Iterator<dynamic>* :sync-for-iterator = (dynamicList1 as{TypeError,ForDynamic} core::Iterable<dynamic>*).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -108,7 +108,7 @@
   } =>#t14;
   self::expect(core::_GrowableList::generate<core::num*>(24, (core::int* i) → core::int* => i), list2);
   core::List<core::int*>* list3 = block {
-    final core::List<core::int*>* #t19 = <core::int*>[];
+    final core::List<core::int*>* #t19 = core::_GrowableList::•<core::int*>(0);
     final core::Iterable<dynamic>* #t20 = dynamicList1 as{TypeError,ForDynamic} core::Iterable<dynamic>*;
     if(!#t20.{core::Object::==}(null)) {
       core::Iterator<dynamic>* :sync-for-iterator = #t20.{core::Iterable::iterator};
@@ -184,7 +184,7 @@
   } =>#t19;
   self::expect(core::_GrowableList::generate<core::int*>(24, (core::int* i) → core::int* => i), list3);
   core::List<core::num*>* list4 = block {
-    final core::List<core::num*>* #t40 = <core::num*>[];
+    final core::List<core::num*>* #t40 = core::_GrowableList::•<core::num*>(0);
     final core::Iterable<dynamic>* #t41 = dynamicList1 as{TypeError,ForDynamic} core::Iterable<dynamic>*;
     if(!#t41.{core::Object::==}(null)) {
       core::Iterator<dynamic>* :sync-for-iterator = #t41.{core::Iterable::iterator};
diff --git a/pkg/front_end/testcases/unified_collections/list_add_all_nnbd.dart.weak.transformed.expect b/pkg/front_end/testcases/unified_collections/list_add_all_nnbd.dart.weak.transformed.expect
index e9211e8..e94bf35 100644
--- a/pkg/front_end/testcases/unified_collections/list_add_all_nnbd.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/unified_collections/list_add_all_nnbd.dart.weak.transformed.expect
@@ -3,13 +3,13 @@
 import "dart:core" as core;
 
 static method useAddAll() → void {
-  dynamic dynamicList1 = <core::int>[0, 1, 2];
-  dynamic dynamicList2 = <core::num>[3, 4, 5];
-  dynamic dynamicList3 = <core::int?>[6, 7, 8];
-  core::Iterable<core::int> iterableIntList = <core::int>[9, 10, 11];
-  core::List<core::int> intList = <core::int>[12, 13, 14];
+  dynamic dynamicList1 = core::_GrowableList::_literal3<core::int>(0, 1, 2);
+  dynamic dynamicList2 = core::_GrowableList::_literal3<core::num>(3, 4, 5);
+  dynamic dynamicList3 = core::_GrowableList::_literal3<core::int?>(6, 7, 8);
+  core::Iterable<core::int> iterableIntList = core::_GrowableList::_literal3<core::int>(9, 10, 11);
+  core::List<core::int> intList = core::_GrowableList::_literal3<core::int>(12, 13, 14);
   core::List<core::int> list1 = block {
-    final core::List<core::int> #t1 = <core::int>[];
+    final core::List<core::int> #t1 = core::_GrowableList::•<core::int>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (dynamicList1 as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -45,7 +45,7 @@
   } =>#t1;
   self::expect(core::_GrowableList::generate<core::int>(15, (core::int i) → core::int => i), list1);
   core::List<core::num> list2 = block {
-    final core::List<core::num> #t8 = <core::num>[];
+    final core::List<core::num> #t8 = core::_GrowableList::•<core::num>(0);
     {
       core::Iterator<dynamic> :sync-for-iterator = (dynamicList1 as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>).{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -82,13 +82,13 @@
   self::expect(core::_GrowableList::generate<core::num>(15, (core::int i) → core::int => i), list2);
 }
 static method useAddAllNullable() → void {
-  dynamic dynamicList1 = <core::int>[0, 1, 2];
-  dynamic dynamicList2 = <core::num>[3, 4, 5];
-  dynamic dynamicList3 = <core::int?>[6, 7, 8];
-  core::Iterable<core::int>? iterableIntList = true ?{core::List<core::int>?} <core::int>[9, 10, 11] : null;
-  core::List<core::int>? intList = true ?{core::List<core::int>?} <core::int>[12, 13, 14] : null;
+  dynamic dynamicList1 = core::_GrowableList::_literal3<core::int>(0, 1, 2);
+  dynamic dynamicList2 = core::_GrowableList::_literal3<core::num>(3, 4, 5);
+  dynamic dynamicList3 = core::_GrowableList::_literal3<core::int?>(6, 7, 8);
+  core::Iterable<core::int>? iterableIntList = true ?{core::List<core::int>?} core::_GrowableList::_literal3<core::int>(9, 10, 11) : null;
+  core::List<core::int>? intList = true ?{core::List<core::int>?} core::_GrowableList::_literal3<core::int>(12, 13, 14) : null;
   core::List<core::int> list1 = block {
-    final core::List<core::int> #t15 = <core::int>[];
+    final core::List<core::int> #t15 = core::_GrowableList::•<core::int>(0);
     final core::Iterable<dynamic>? #t16 = dynamicList1 as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>?;
     if(!#t16.{core::Object::==}(null)) {
       core::Iterator<dynamic> :sync-for-iterator = #t16{core::Iterable<dynamic>}.{core::Iterable::iterator};
@@ -131,7 +131,7 @@
   } =>#t15;
   self::expect(core::_GrowableList::generate<core::int>(15, (core::int i) → core::int => i), list1);
   core::List<core::num> list2 = block {
-    final core::List<core::num> #t27 = <core::num>[];
+    final core::List<core::num> #t27 = core::_GrowableList::•<core::num>(0);
     final core::Iterable<dynamic>? #t28 = dynamicList1 as{TypeError,ForDynamic,ForNonNullableByDefault} core::Iterable<dynamic>?;
     if(!#t28.{core::Object::==}(null)) {
       core::Iterator<dynamic> :sync-for-iterator = #t28{core::Iterable<dynamic>}.{core::Iterable::iterator};
diff --git a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.weak.transformed.expect b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.weak.transformed.expect
index 691c149..6444381 100644
--- a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.weak.transformed.expect
@@ -42,7 +42,7 @@
 import "dart:core" as core;
 
 static field core::bool* b = false;
-static field core::List<dynamic>* list = <dynamic>[];
+static field core::List<dynamic>* list = core::_GrowableList::•<dynamic>(0);
 static field core::Map<dynamic, dynamic>* map0 = <dynamic, dynamic>{};
 static field core::Map<dynamic, dynamic>* map1 = block {
   final core::Map<dynamic, dynamic>* #t1 = <dynamic, dynamic>{};
diff --git a/pkg/front_end/testcases/unified_collections/string_concatenation.dart.weak.transformed.expect b/pkg/front_end/testcases/unified_collections/string_concatenation.dart.weak.transformed.expect
index b8d8ac8..33e84e4 100644
--- a/pkg/front_end/testcases/unified_collections/string_concatenation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/unified_collections/string_concatenation.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 static method main() → dynamic {
   core::bool* b = false;
   block {
-    final core::List<core::String*>* #t1 = <core::String*>["ab"];
+    final core::List<core::String*>* #t1 = core::_GrowableList::_literal1<core::String*>("ab");
     if(b)
       #t1.{core::List::add}{Invariant}("cd");
   } =>#t1;
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect
index 4b64468..8f2b714 100644
--- a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect
@@ -158,11 +158,11 @@
   no-such-method-forwarder get x() → self::NoSuchMethod::T*
     return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic} self::NoSuchMethod::T*;
   no-such-method-forwarder method method(self::NoSuchMethod::T* x) → self::NoSuchMethod::T*
-    return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic} self::NoSuchMethod::T*;
+    return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(x)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError,ForDynamic} self::NoSuchMethod::T*;
   no-such-method-forwarder set y(self::NoSuchMethod::T* x) → void
-    return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+    return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(x)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
   no-such-method-forwarder set x(self::NoSuchMethod::T* value) → void
-    return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+    return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 2, #C3, core::List::unmodifiable<dynamic>(core::_GrowableList::_literal1<dynamic>(value)), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
 }
 static method main() → dynamic {
   self::A<core::int*, core::num*, core::String*>* a = new self::A::•<core::int*, core::num*, core::String*>();
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 23bbcca..731df3e 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -58,7 +58,6 @@
 late_lowering/covariant_late_field: TypeCheckError
 nnbd/covariant_late_field: TypeCheckError
 nnbd/getter_vs_setter_type: TypeCheckError
-nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
 nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
 nnbd/nullable_object_access: TypeCheckError
@@ -66,13 +65,28 @@
 nnbd/potentially_nullable_access: TypeCheckError
 nnbd_mixed/bad_mixins: TypeCheckError
 nnbd_mixed/covariant_from_opt_in: TypeCheckError
+nnbd_mixed/hierarchy/conflict: TypeCheckError
+nnbd_mixed/hierarchy/duplicates: TypeCheckError
+nnbd_mixed/hierarchy/forwarding_semi_stub_field: TypeCheckError
+nnbd_mixed/hierarchy/forwarding_semi_stub_method: TypeCheckError
+nnbd_mixed/hierarchy/forwarding_semi_stub_setter: TypeCheckError
+nnbd_mixed/hierarchy/getter_setter: TypeCheckError
+nnbd_mixed/hierarchy/in_dill_out_in/in_out_in: TypeCheckError
+nnbd_mixed/hierarchy/in_out_dill_in/in_out_in: TypeCheckError
+nnbd_mixed/hierarchy/in_out_in: TypeCheckError
+nnbd_mixed/hierarchy/mix_in_override: TypeCheckError
+nnbd_mixed/hierarchy/override: TypeCheckError
 nnbd_mixed/inheritance_from_opt_in: TypeCheckError
+nnbd_mixed/issue40512/issue40512: TypeCheckError
+nnbd_mixed/issue41210a/issue41210: TypeCheckError
 nnbd_mixed/issue41567: TypeCheckError
 nnbd_mixed/messages_with_types_opt_in: TypeCheckError
 nnbd_mixed/messages_with_types_opt_out: TypeCheckError
-nnbd_mixed/super_access/main: Crash # Issue 43864
-nnbd_mixed/super_access/main.no_link: Crash # Issue 43864
-none/mixin_covariant: TypeCheckError
+none/equals: TypeCheckError
+none/method_invocation: TypeCheckError
+none/operator: TypeCheckError
+none/property_get: TypeCheckError
+none/property_set: TypeCheckError
 value_class/simple: RuntimeError # Expected
 value_class/value_extends_non_value: RuntimeError # Expected
 value_class/value_implements_non_value: RuntimeError # Expected
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 50bd29e..edd1e75 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -485,6 +485,7 @@
     "exclude": [
       "^pkg/analysis_server/lib/src/analysis_server\\.dart",
       "test/analyser_ignored/",
+      "test/class_hierarchy/data/",
       "test/enable_non_nullable/data/",
       "test/extensions/data/",
       "test/id_testing/data/",
diff --git a/pkg/front_end/tool/_fasta/abcompile.dart b/pkg/front_end/tool/_fasta/abcompile.dart
index 63ea80b..26f815a 100644
--- a/pkg/front_end/tool/_fasta/abcompile.dart
+++ b/pkg/front_end/tool/_fasta/abcompile.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.9
+
 import 'dart:async';
 import 'dart:convert';
 import 'dart:math';
diff --git a/pkg/front_end/tool/_fasta/additional_targets.dart b/pkg/front_end/tool/_fasta/additional_targets.dart
index 6e9399a..098cd0d 100644
--- a/pkg/front_end/tool/_fasta/additional_targets.dart
+++ b/pkg/front_end/tool/_fasta/additional_targets.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.9
+
 library fasta.tool.additional_targets;
 
 import 'package:kernel/target/targets.dart' show TargetFlags, targets;
diff --git a/pkg/front_end/tool/_fasta/additional_targets_test.dart b/pkg/front_end/tool/_fasta/additional_targets_test.dart
index daffd49..d9fea70 100644
--- a/pkg/front_end/tool/_fasta/additional_targets_test.dart
+++ b/pkg/front_end/tool/_fasta/additional_targets_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.
 
+// @dart=2.9
+
 library fasta.tool.additional_targets_test;
 
 import 'package:kernel/target/targets.dart' show targets;
diff --git a/pkg/front_end/tool/_fasta/batch.dart b/pkg/front_end/tool/_fasta/batch.dart
index 968014e..ac34ce6 100644
--- a/pkg/front_end/tool/_fasta/batch.dart
+++ b/pkg/front_end/tool/_fasta/batch.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.9
+
 import 'entry_points.dart' show batchEntryPoint;
 
 main(List<String> arguments) => batchEntryPoint(arguments);
diff --git a/pkg/front_end/tool/_fasta/bench_maker.dart b/pkg/front_end/tool/_fasta/bench_maker.dart
index 6623d7a..dbfbb79 100644
--- a/pkg/front_end/tool/_fasta/bench_maker.dart
+++ b/pkg/front_end/tool/_fasta/bench_maker.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.9
+
 library fasta.tool.entry_points;
 
 import "dart:convert" show JsonEncoder;
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index ed79435..bfa8f4b 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.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.9
+
 library fasta.tool.command_line;
 
 import 'dart:io' show exit;
@@ -193,11 +195,13 @@
   Flags.nnbdAgnosticMode: const BoolValue(false),
   Flags.target: const StringValue(),
   Flags.verbose: const BoolValue(false),
+  Flags.verbosity: const StringValue(),
   Flags.verify: const BoolValue(false),
-  Flags.verifySkipPlatform: const BoolValue(false),
+  Flags.skipPlatformVerification: const BoolValue(false),
   Flags.warnOnReachabilityCheck: const BoolValue(false),
   Flags.linkDependencies: const UriListValue(),
   Flags.noDeps: const BoolValue(false),
+  Flags.invocationModes: const StringValue(),
   "-D": const DefineValue(),
   "-h": const AliasValue(Flags.help),
   "--out": const AliasValue(Flags.output),
@@ -265,7 +269,7 @@
 
   final bool verify = options[Flags.verify];
 
-  final bool verifySkipPlatform = options[Flags.verifySkipPlatform];
+  final bool skipPlatformVerification = options[Flags.skipPlatformVerification];
 
   final bool dumpIr = options[Flags.dumpIr];
 
@@ -303,6 +307,10 @@
 
   final List<Uri> linkDependencies = options[Flags.linkDependencies] ?? [];
 
+  final String invocationModes = options[Flags.invocationModes] ?? '';
+
+  final String verbosity = options[Flags.verbosity] ?? Verbosity.defaultValue;
+
   if (nnbdStrongMode && nnbdWeakMode) {
     return throw new CommandLineProblem.deprecated(
         "Can't specify both '${Flags.nnbdStrongMode}' and "
@@ -347,13 +355,15 @@
     ..omitPlatform = omitPlatform
     ..verbose = verbose
     ..verify = verify
-    ..verifySkipPlatform = verifySkipPlatform
+    ..skipPlatformVerification = skipPlatformVerification
     ..explicitExperimentalFlags = explicitExperimentalFlags
     ..environmentDefines = noDefines ? null : parsedArguments.defines
     ..nnbdMode = nnbdMode
     ..additionalDills = linkDependencies
     ..emitDeps = !noDeps
-    ..warnOnReachabilityCheck = warnOnReachabilityCheck;
+    ..warnOnReachabilityCheck = warnOnReachabilityCheck
+    ..invocationModes = InvocationMode.parseArguments(invocationModes)
+    ..verbosity = Verbosity.parseArgument(verbosity);
 
   if (programName == "compile_platform") {
     if (arguments.length != 5) {
diff --git a/pkg/front_end/tool/_fasta/compile.dart b/pkg/front_end/tool/_fasta/compile.dart
index 2165cf1..0fa58c9 100644
--- a/pkg/front_end/tool/_fasta/compile.dart
+++ b/pkg/front_end/tool/_fasta/compile.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.9
+
 import 'entry_points.dart' show compileEntryPoint;
 
 main(List<String> arguments) => compileEntryPoint(arguments);
diff --git a/pkg/front_end/tool/_fasta/compile_platform.dart b/pkg/front_end/tool/_fasta/compile_platform.dart
index c9791fb..352e1f0 100644
--- a/pkg/front_end/tool/_fasta/compile_platform.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform.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.9
+
 import 'entry_points.dart' show compilePlatformEntryPoint;
 
 main(List<String> arguments) => compilePlatformEntryPoint(arguments);
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 985026c..1f624d3 100644
--- a/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform_legacy_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.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 985026c..1f624d3 100644
--- a/pkg/front_end/tool/_fasta/compile_platform_test.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform_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.md file.
 
+// @dart=2.9
+
 library fasta.test.compile_platform_test;
 
 import 'dart:io';
diff --git a/pkg/front_end/tool/_fasta/deps.dart b/pkg/front_end/tool/_fasta/deps.dart
index 3b83d0f..3e8c7be 100644
--- a/pkg/front_end/tool/_fasta/deps.dart
+++ b/pkg/front_end/tool/_fasta/deps.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.9
+
 import 'entry_points.dart' show depsEntryPoint;
 
 main(List<String> arguments) => depsEntryPoint(arguments);
diff --git a/pkg/front_end/tool/_fasta/direct_parser_ast_helper_creator.dart b/pkg/front_end/tool/_fasta/direct_parser_ast_helper_creator.dart
index 8b7cf18..3fde7d0 100644
--- a/pkg/front_end/tool/_fasta/direct_parser_ast_helper_creator.dart
+++ b/pkg/front_end/tool/_fasta/direct_parser_ast_helper_creator.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.9
+
 import 'dart:io';
 import 'dart:typed_data';
 
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 1aa2265..9733184 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.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.9
+
 library fasta.tool.entry_points;
 
 import 'dart:convert' show LineSplitter, jsonDecode, jsonEncode, utf8;
@@ -357,6 +359,7 @@
 
   Future<Uri> compile(
       {bool omitPlatform: false, bool supportAdditionalDills: true}) async {
+    c.options.reportNullSafetyCompilationModeInfo();
     KernelTarget kernelTarget =
         await buildOutline(supportAdditionalDills: supportAdditionalDills);
     Uri uri = c.options.output;
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
index 8f16842..5911b3a 100644
--- a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags.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.9
+
 import 'dart:io' show File, Platform;
 
 import 'package:_fe_analyzer_shared/src/scanner/characters.dart'
@@ -57,10 +59,12 @@
   StringBuffer sb = new StringBuffer();
 
   sb.write('''
-// 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.
 
+// @dart = 2.9
+
 // NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
 //
 // Instead modify 'tools/experimental_features.yaml' and run
@@ -91,10 +95,12 @@
   StringBuffer sb = new StringBuffer();
 
   sb.write('''
-// 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.
 
+// @dart = 2.9
+
 // NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
 //
 // Instead modify 'tools/experimental_features.yaml' and run
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart
index d826ea5..8320f37 100644
--- a/pkg/front_end/tool/_fasta/generate_experimental_flags_test.dart
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags_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.
 
+// @dart=2.9
+
 import "dart:io" show File, exitCode;
 
 import "generate_experimental_flags.dart"
diff --git a/pkg/front_end/tool/_fasta/generate_messages.dart b/pkg/front_end/tool/_fasta/generate_messages.dart
index cd6b870..23a3487 100644
--- a/pkg/front_end/tool/_fasta/generate_messages.dart
+++ b/pkg/front_end/tool/_fasta/generate_messages.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.9
+
 import 'dart:io';
 
 import 'dart:isolate';
@@ -53,11 +55,15 @@
   StringBuffer sharedMessages = new StringBuffer();
   StringBuffer cfeMessages = new StringBuffer();
 
-  const String preamble = """
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+  const String preamble1 = """
+// 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.
 
+""";
+
+  const String preamble2 = """
+
 // NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
 //
 // Instead modify 'pkg/front_end/messages.yaml' and run
@@ -66,12 +72,19 @@
 // ignore_for_file: lines_longer_than_80_chars
 """;
 
-  sharedMessages.writeln(preamble);
+  sharedMessages.writeln(preamble1);
+  sharedMessages.writeln(preamble2);
   sharedMessages.writeln("""
 part of _fe_analyzer_shared.messages.codes;
 """);
 
-  cfeMessages.writeln(preamble);
+  cfeMessages.writeln(preamble1);
+  cfeMessages.writeln("""
+
+// @dart = 2.9
+
+""");
+  cfeMessages.writeln(preamble2);
   cfeMessages.writeln("""
 part of fasta.codes;
 """);
@@ -167,6 +180,7 @@
   // `|` (verbatim) as they always contain a trailing newline that we don't
   // want.
   template = template.trimRight();
+  const String ignoreNotNull = "// ignore: unnecessary_null_comparison";
   var parameters = new Set<String>();
   var conversions = new Set<String>();
   var conversions2 = new Set<String>();
@@ -209,7 +223,7 @@
         parameters.add("String character");
         conversions.add("if (character.runes.length != 1)"
             "throw \"Not a character '\${character}'\";");
-        arguments.add("'character': character");
+        arguments.add("'$name': character");
         break;
 
       case "unicode":
@@ -219,40 +233,41 @@
         parameters.add("int codePoint");
         conversions.add("String unicode = \"U+\${codePoint.toRadixString(16)"
             ".toUpperCase().padLeft(4, '0')}\";");
-        arguments.add("'codePoint': codePoint");
+        arguments.add("'$name': codePoint");
         break;
 
       case "name":
         parameters.add("String name");
         conversions.add("if (name.isEmpty) throw 'No name provided';");
-        arguments.add("'name': name");
+        arguments.add("'$name': name");
         conversions.add("name = demangleMixinApplicationName(name);");
         break;
 
       case "name2":
         parameters.add("String name2");
         conversions.add("if (name2.isEmpty) throw 'No name provided';");
-        arguments.add("'name2': name2");
+        arguments.add("'$name': name2");
         conversions.add("name2 = demangleMixinApplicationName(name2);");
         break;
 
       case "name3":
         parameters.add("String name3");
         conversions.add("if (name3.isEmpty) throw 'No name provided';");
-        arguments.add("'name3': name3");
+        arguments.add("'$name': name3");
         conversions.add("name3 = demangleMixinApplicationName(name3);");
         break;
 
       case "name4":
         parameters.add("String name4");
         conversions.add("if (name4.isEmpty) throw 'No name provided';");
-        arguments.add("'name4': name4");
+        arguments.add("'$name': name4");
         conversions.add("name4 = demangleMixinApplicationName(name4);");
         break;
 
       case "nameOKEmpty":
         parameters.add("String nameOKEmpty");
-        conversions.add("if (nameOKEmpty == null || nameOKEmpty.isEmpty) "
+        conversions.add("$ignoreNotNull\n"
+            "if (nameOKEmpty == null || nameOKEmpty.isEmpty) "
             "nameOKEmpty = '(unnamed)';");
         arguments.add("'nameOKEmpty': nameOKEmpty");
         break;
@@ -260,45 +275,46 @@
       case "names":
         parameters.add("List<String> _names");
         conversions.add("if (_names.isEmpty) throw 'No names provided';");
-        arguments.add("'names': _names");
+        arguments.add("'$name': _names");
         conversions.add("String names = itemizeNames(_names);");
         break;
 
       case "lexeme":
         parameters.add("Token token");
         conversions.add("String lexeme = token.lexeme;");
-        arguments.add("'token': token");
+        arguments.add("'$name': token");
         break;
 
       case "lexeme2":
         parameters.add("Token token2");
         conversions.add("String lexeme2 = token2.lexeme;");
-        arguments.add("'token2': token2");
+        arguments.add("'$name': token2");
         break;
 
       case "string":
         parameters.add("String string");
         conversions.add("if (string.isEmpty) throw 'No string provided';");
-        arguments.add("'string': string");
+        arguments.add("'$name': string");
         break;
 
       case "string2":
         parameters.add("String string2");
         conversions.add("if (string2.isEmpty) throw 'No string provided';");
-        arguments.add("'string2': string2");
+        arguments.add("'$name': string2");
         break;
 
       case "string3":
         parameters.add("String string3");
         conversions.add("if (string3.isEmpty) throw 'No string provided';");
-        arguments.add("'string3': string3");
+        arguments.add("'$name': string3");
         break;
 
       case "stringOKEmpty":
         parameters.add("String stringOKEmpty");
-        conversions.add("if (stringOKEmpty == null || stringOKEmpty.isEmpty) "
+        conversions.add("$ignoreNotNull\n"
+            "if (stringOKEmpty == null || stringOKEmpty.isEmpty) "
             "stringOKEmpty = '(empty)';");
-        arguments.add("'stringOKEmpty': stringOKEmpty");
+        arguments.add("'$name': stringOKEmpty");
         break;
 
       case "type":
@@ -315,32 +331,34 @@
 
       case "uri":
         parameters.add("Uri uri_");
-        conversions.add("String uri = relativizeUri(uri_);");
-        arguments.add("'uri': uri_");
+        conversions.add("String? uri = relativizeUri(uri_);");
+        arguments.add("'$name': uri_");
         break;
 
       case "uri2":
         parameters.add("Uri uri2_");
-        conversions.add("String uri2 = relativizeUri(uri2_);");
-        arguments.add("'uri2': uri2_");
+        conversions.add("String? uri2 = relativizeUri(uri2_);");
+        arguments.add("'$name': uri2_");
         break;
 
       case "uri3":
         parameters.add("Uri uri3_");
-        conversions.add("String uri3 = relativizeUri(uri3_);");
-        arguments.add("'uri3': uri3_");
+        conversions.add("String? uri3 = relativizeUri(uri3_);");
+        arguments.add("'$name': uri3_");
         break;
 
       case "count":
         parameters.add("int count");
-        conversions.add("if (count == null) throw 'No count provided';");
-        arguments.add("'count': count");
+        conversions.add(
+            "$ignoreNotNull\n" "if (count == null) throw 'No count provided';");
+        arguments.add("'$name': count");
         break;
 
       case "count2":
         parameters.add("int count2");
-        conversions.add("if (count2 == null) throw 'No count provided';");
-        arguments.add("'count2': count2");
+        conversions.add("$ignoreNotNull\n"
+            "if (count2 == null) throw 'No count provided';");
+        arguments.add("'$name': count2");
         break;
 
       case "constant":
@@ -349,28 +367,31 @@
         conversions.add(
             "List<Object> ${name}Parts = labeler.labelConstant(_${name});");
         conversions2.add("String ${name} = ${name}Parts.join();");
-        arguments.add("'constant': _constant");
+        arguments.add("'$name': _constant");
         break;
 
       case "num1":
         parameters.add("num _num1");
-        conversions.add("if (_num1 == null) throw 'No number provided';");
+        conversions.add("$ignoreNotNull\n"
+            "if (_num1 == null) throw 'No number provided';");
         conversions.add("String num1 = ${format('_num1')};");
-        arguments.add("'num1': _num1");
+        arguments.add("'$name': _num1");
         break;
 
       case "num2":
         parameters.add("num _num2");
-        conversions.add("if (_num2 == null) throw 'No number provided';");
+        conversions.add("$ignoreNotNull\n"
+            "if (_num2 == null) throw 'No number provided';");
         conversions.add("String num2 = ${format('_num2')};");
-        arguments.add("'num2': _num2");
+        arguments.add("'$name': _num2");
         break;
 
       case "num3":
         parameters.add("num _num3");
-        conversions.add("if (_num3 == null) throw 'No number provided';");
+        conversions.add("$ignoreNotNull\n"
+            "if (_num3 == null) throw 'No number provided';");
         conversions.add("String num3 = ${format('_num3')};");
-        arguments.add("'num3': _num3");
+        arguments.add("'$name': _num3");
         break;
 
       default:
@@ -459,7 +480,7 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Message Function(${parameters.join(', ')})> code$name =
     const Code<Message Function(${parameters.join(', ')})>(
-        \"$name\", template$name, ${codeArguments.join(', ')});
+        \"$name\", ${codeArguments.join(', ')});
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArguments$name(${parameters.join(', ')}) {
diff --git a/pkg/front_end/tool/_fasta/generate_messages_test.dart b/pkg/front_end/tool/_fasta/generate_messages_test.dart
index 303be61..ccbff6a 100644
--- a/pkg/front_end/tool/_fasta/generate_messages_test.dart
+++ b/pkg/front_end/tool/_fasta/generate_messages_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.
 
+// @dart=2.9
+
 import "dart:io" show File;
 
 import "package:async_helper/async_helper.dart" show asyncTest;
diff --git a/pkg/front_end/tool/_fasta/log_analyzer.dart b/pkg/front_end/tool/_fasta/log_analyzer.dart
index c93e916..1a794a0 100644
--- a/pkg/front_end/tool/_fasta/log_analyzer.dart
+++ b/pkg/front_end/tool/_fasta/log_analyzer.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.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 b35250d..95dc56f 100644
--- a/pkg/front_end/tool/_fasta/log_collector.dart
+++ b/pkg/front_end/tool/_fasta/log_collector.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.9
+
 import 'dart:convert' show jsonDecode, utf8;
 
 import 'dart:isolate' show RawReceivePort;
diff --git a/pkg/front_end/tool/_fasta/outline.dart b/pkg/front_end/tool/_fasta/outline.dart
index dfba5cb..2a4d7f9 100644
--- a/pkg/front_end/tool/_fasta/outline.dart
+++ b/pkg/front_end/tool/_fasta/outline.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.9
+
 import 'entry_points.dart' show outlineEntryPoint;
 
 main(List<String> arguments) => outlineEntryPoint(arguments);
diff --git a/pkg/front_end/tool/compare_dill.dart b/pkg/front_end/tool/compare_dill.dart
index f537a0f..f7e24b3 100644
--- a/pkg/front_end/tool/compare_dill.dart
+++ b/pkg/front_end/tool/compare_dill.dart
@@ -1,3 +1,9 @@
+// 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.
+
+// @dart=2.9
+
 import 'dart:io' show File;
 
 import '../test/binary_md_dill_reader.dart' show DillComparer;
diff --git a/pkg/front_end/tool/fasta.dart b/pkg/front_end/tool/fasta.dart
index f2ecaaf..b2b8d26 100644
--- a/pkg/front_end/tool/fasta.dart
+++ b/pkg/front_end/tool/fasta.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.9
+
 import 'dart:io';
 
 import '../test/utils/io_utils.dart' show computeRepoDir;
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index 385ec39..cd92061 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.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.9
+
 /// An entrypoint used to run portions of fasta and measure its performance.
 library front_end.tool.fasta_perf;
 
diff --git a/pkg/front_end/tool/fasta_perf_test.dart b/pkg/front_end/tool/fasta_perf_test.dart
index f366e73..fb850f0 100644
--- a/pkg/front_end/tool/fasta_perf_test.dart
+++ b/pkg/front_end/tool/fasta_perf_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.
 
+// @dart=2.9
+
 /// The only purpose of this file is to enable analyzer tests on `perf.dart`,
 /// the code here just has a dummy import to the rest of the code.
 library front_end.tool.perf_test;
diff --git a/pkg/front_end/tool/incremental_perf.dart b/pkg/front_end/tool/incremental_perf.dart
index 617e448..50c922c 100644
--- a/pkg/front_end/tool/incremental_perf.dart
+++ b/pkg/front_end/tool/incremental_perf.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.9
+
 /// An entrypoint used to measure performance of the incremental compiler.
 ///
 /// Given an input a program and a .json file describing edits, this script will
diff --git a/pkg/front_end/tool/incremental_perf_test.dart b/pkg/front_end/tool/incremental_perf_test.dart
index 73e0893..72deb00 100644
--- a/pkg/front_end/tool/incremental_perf_test.dart
+++ b/pkg/front_end/tool/incremental_perf_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.
 
+// @dart=2.9
+
 /// Test to ensure that incremental_perf.dart is running without errors.
 
 import 'dart:io';
diff --git a/pkg/front_end/tool/kernel_ast_file_rewriter.dart b/pkg/front_end/tool/kernel_ast_file_rewriter.dart
index bdefeae..64bd396 100644
--- a/pkg/front_end/tool/kernel_ast_file_rewriter.dart
+++ b/pkg/front_end/tool/kernel_ast_file_rewriter.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.9
+
 import "dart:io" show File, Platform, stdout;
 import "dart:typed_data" show Uint8List;
 
diff --git a/pkg/front_end/tool/parser_direct_ast/console_helper.dart b/pkg/front_end/tool/parser_direct_ast/console_helper.dart
index d6a1d34..d758c92 100644
--- a/pkg/front_end/tool/parser_direct_ast/console_helper.dart
+++ b/pkg/front_end/tool/parser_direct_ast/console_helper.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.9
+
 import "dart:async" show StreamSubscription, Timer;
 import "dart:io" show Platform, ProcessSignal, exit, stdin, stdout;
 import "dart:isolate" show RawReceivePort;
diff --git a/pkg/front_end/tool/parser_direct_ast/viewer.dart b/pkg/front_end/tool/parser_direct_ast/viewer.dart
index c516101..276ea23 100644
--- a/pkg/front_end/tool/parser_direct_ast/viewer.dart
+++ b/pkg/front_end/tool/parser_direct_ast/viewer.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.9
+
 import "dart:io" show File, Platform;
 import "dart:typed_data" show Uint8List;
 
diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart
index 95b3ba5..61ee9d3 100644
--- a/pkg/front_end/tool/perf.dart
+++ b/pkg/front_end/tool/perf.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.9
+
 /// An entrypoint used to run portions of analyzer and measure its performance.
 ///
 /// TODO(sigmund): rename to 'analyzer_perf.dart' in sync with changes to the
diff --git a/pkg/front_end/tool/perf_common.dart b/pkg/front_end/tool/perf_common.dart
index 7da7dcb..0ba1365 100644
--- a/pkg/front_end/tool/perf_common.dart
+++ b/pkg/front_end/tool/perf_common.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.9
+
 /// Shared code used by fasta_perf and incremental_perf.
 library front_end.tool.perf_common;
 
diff --git a/pkg/front_end/tool/perf_test.dart b/pkg/front_end/tool/perf_test.dart
index 7b54fb8..b246c05 100644
--- a/pkg/front_end/tool/perf_test.dart
+++ b/pkg/front_end/tool/perf_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.
 
+// @dart=2.9
+
 library front_end.tool.perf_test;
 
 import 'dart:io' show Platform;
diff --git a/pkg/front_end/tool/smoke_test_quick.dart b/pkg/front_end/tool/smoke_test_quick.dart
index 03d3840..7427ee3 100644
--- a/pkg/front_end/tool/smoke_test_quick.dart
+++ b/pkg/front_end/tool/smoke_test_quick.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.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 ead3e7b..c0ac7b4 100644
--- a/pkg/front_end/tool/stat_on_dash_v.dart
+++ b/pkg/front_end/tool/stat_on_dash_v.dart
@@ -1,3 +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
+
 import "dart:io";
 
 import "../test/simple_stats.dart";
diff --git a/pkg/front_end/tool/update_all.dart b/pkg/front_end/tool/update_all.dart
index a4ff797..41ba6a1 100644
--- a/pkg/front_end/tool/update_all.dart
+++ b/pkg/front_end/tool/update_all.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.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 52bcd00..a1cc85c 100644
--- a/pkg/front_end/tool/update_expectations.dart
+++ b/pkg/front_end/tool/update_expectations.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.9
+
 import 'fasta.dart' as fasta;
 
 const List<String> standardSuites = <String>[
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index c1f089f..136b9ab 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -36,6 +36,8 @@
 import 'src/javascript_bundle.dart';
 import 'src/strong_components.dart';
 
+export 'src/to_string_transformer.dart';
+
 ArgParser argParser = ArgParser(allowTrailingOptions: true)
   ..addFlag('train',
       help: 'Run through sample command line to produce snapshot',
@@ -56,9 +58,6 @@
   ..addFlag('tree-shake-write-only-fields',
       help: 'Enable tree shaking of fields which are only written in AOT mode.',
       defaultsTo: true)
-  ..addFlag('protobuf-tree-shaker',
-      help: 'Enable protobuf tree shaker transformation in AOT mode.',
-      defaultsTo: false)
   ..addFlag('protobuf-tree-shaker-v2',
       help: 'Enable protobuf tree shaker v2 in AOT mode.', defaultsTo: false)
   ..addFlag('minimal-kernel',
@@ -114,7 +113,8 @@
       hide: true)
   ..addMultiOption('define',
       abbr: 'D',
-      help: 'The values for the environment constants (e.g. -Dkey=value).')
+      help: 'The values for the environment constants (e.g. -Dkey=value).',
+      splitCommas: false)
   ..addFlag('embed-source-text',
       help: 'Includes sources into generated dill file. Having sources'
           ' allows to effectively use observatory to debug produced'
@@ -361,6 +361,7 @@
         errors.addAll(message.plainTextFormatted);
         break;
       case Severity.warning:
+      case Severity.info:
         printMessage = true;
         break;
       case Severity.context:
@@ -528,7 +529,6 @@
           useGlobalTypeFlowAnalysis: options['tfa'],
           environmentDefines: environmentDefines,
           enableAsserts: options['enable-asserts'],
-          useProtobufTreeShaker: options['protobuf-tree-shaker'],
           useProtobufTreeShakerV2: options['protobuf-tree-shaker-v2'],
           minimalKernel: options['minimal-kernel'],
           treeShakeWriteOnlyFields: options['tree-shake-write-only-fields'],
diff --git a/pkg/js/README.md b/pkg/js/README.md
index e5563a1..7279082 100644
--- a/pkg/js/README.md
+++ b/pkg/js/README.md
@@ -201,3 +201,10 @@
 **Workaround:** Avoid importing `dart:js` and only use the `package:js` provided
 approach. To handle object literals use `@anonymous` on an `@JS()` annotated
 class.
+
+#### `is` checks and `as` casts between JS interop types will always succeed
+
+For any two `@JS()` types, with or without `@anonymous`, a check of whether an
+object of one type `is` another type will always return true, regardless of
+whether those two types are in the same prototype chain. Similarly, an explicit
+cast using `as` will also succeed.
diff --git a/pkg/js_ast/lib/src/equivalence_visitor.dart b/pkg/js_ast/lib/src/equivalence_visitor.dart
index 42801c0..d06f50f 100644
--- a/pkg/js_ast/lib/src/equivalence_visitor.dart
+++ b/pkg/js_ast/lib/src/equivalence_visitor.dart
@@ -341,8 +341,7 @@
   bool visitLiteralExpression(LiteralExpression node, Node arg) {
     if (arg is! LiteralExpression) return failAt(node, arg);
     LiteralExpression other = arg;
-    return testValues(node, node.template, other, other.template) &&
-        testNodeLists(node.inputs, other.inputs);
+    return testValues(node, node.template, other, other.template);
   }
 
   @override
diff --git a/pkg/js_ast/lib/src/nodes.dart b/pkg/js_ast/lib/src/nodes.dart
index 7a9298a..b9cc51f 100644
--- a/pkg/js_ast/lib/src/nodes.dart
+++ b/pkg/js_ast/lib/src/nodes.dart
@@ -1023,34 +1023,21 @@
 
 class LiteralExpression extends Expression {
   final String template;
-  final List<Expression> inputs;
-
-  LiteralExpression(this.template) : inputs = const [];
-
-  LiteralExpression.withData(this.template, this.inputs);
+  LiteralExpression(this.template);
 
   T accept<T>(NodeVisitor<T> visitor) => visitor.visitLiteralExpression(this);
 
   R accept1<R, A>(NodeVisitor1<R, A> visitor, A arg) =>
       visitor.visitLiteralExpression(this, arg);
 
-  void visitChildren<T>(NodeVisitor<T> visitor) {
-    if (inputs != null) {
-      for (Expression expr in inputs) expr.accept(visitor);
-    }
-  }
+  void visitChildren<T>(NodeVisitor<T> visitor) {}
 
-  void visitChildren1<R, A>(NodeVisitor1<R, A> visitor, A arg) {
-    if (inputs != null) {
-      for (Expression expr in inputs) expr.accept1(visitor, arg);
-    }
-  }
+  void visitChildren1<R, A>(NodeVisitor1<R, A> visitor, A arg) {}
 
-  LiteralExpression _clone() =>
-      new LiteralExpression.withData(template, inputs);
+  LiteralExpression _clone() => LiteralExpression(template);
 
-  // Code that uses JS must take care of operator precedences, and
-  // put parenthesis if needed.
+  // Code that uses LiteralExpression must take care of operator precedences,
+  // and put parenthesis if needed.
   int get precedenceLevel => PRIMARY;
 }
 
diff --git a/pkg/js_ast/lib/src/printer.dart b/pkg/js_ast/lib/src/printer.dart
index 400dc42..0d04a21 100644
--- a/pkg/js_ast/lib/src/printer.dart
+++ b/pkg/js_ast/lib/src/printer.dart
@@ -1255,21 +1255,7 @@
 
   @override
   void visitLiteralExpression(LiteralExpression node) {
-    String template = node.template;
-    List<Expression> inputs = node.inputs;
-
-    List<String> parts = template.split('#');
-    int inputsLength = inputs == null ? 0 : inputs.length;
-    if (parts.length != inputsLength + 1) {
-      context.error('Wrong number of arguments for JS: $template');
-    }
-    // Code that uses JS must take care of operator precedences, and
-    // put parenthesis if needed.
-    out(parts[0]);
-    for (int i = 0; i < inputsLength; i++) {
-      visit(inputs[i]);
-      out(parts[i + 1]);
-    }
+    out(node.template);
   }
 
   @override
diff --git a/pkg/js_runtime/README.md b/pkg/js_runtime/README.md
new file mode 100644
index 0000000..5f60952
--- /dev/null
+++ b/pkg/js_runtime/README.md
@@ -0,0 +1,9 @@
+# Package `js_runtime`:
+
+This package contains code that is shared between the dart2js compiler and the
+dart2js runtime libraries.
+
+*Important*: all code under the `lib/shared/` must be kept in sync with the
+runtime at all times (in `sdk/lib/_internal/js_runtime/lib/shared`). The
+`test/in_sync_test.dart` test verifies this.
+
diff --git a/pkg/js_runtime/lib/shared/async_await_error_codes.dart b/pkg/js_runtime/lib/shared/async_await_error_codes.dart
new file mode 100644
index 0000000..f87406b
--- /dev/null
+++ b/pkg/js_runtime/lib/shared/async_await_error_codes.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2015, 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.
+
+/// Contains error codes that transformed async/async* functions use to
+/// communicate with js_helper functions.
+
+const int SUCCESS = 0;
+const int ERROR = 1;
+const int STREAM_WAS_CANCELED = 2;
diff --git a/pkg/js_runtime/lib/shared/embedded_names.dart b/pkg/js_runtime/lib/shared/embedded_names.dart
new file mode 100644
index 0000000..e80fb6a
--- /dev/null
+++ b/pkg/js_runtime/lib/shared/embedded_names.dart
@@ -0,0 +1,281 @@
+// 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.
+
+/// Contains the names of globals that are embedded into the output by the
+/// compiler.
+///
+/// Variables embedded this way should be access with `JS_EMBEDDED_GLOBAL` from
+/// the `_foreign_helper` library.
+///
+/// This library is shared between the compiler and the runtime system.
+library dart2js._embedded_names;
+
+/// The name of the property that is used to find the native superclass of
+/// an extended class.
+///
+/// Every class that extends a native class has this property set on its
+/// native class.
+const NATIVE_SUPERCLASS_TAG_NAME = r"$nativeSuperclassTag";
+
+/// The name of the static-function property name.
+///
+/// This property is set for all tear-offs of static functions, and provides
+/// the static function's unique (potentially minified) name.
+const STATIC_FUNCTION_NAME_PROPERTY_NAME = r'$static_name';
+
+/// The name of a property on the constructor function of Dart Object
+/// and interceptor types, used for caching Rti types.
+const CONSTRUCTOR_RTI_CACHE_PROPERTY_NAME = r'$ccache';
+
+/// The name of the embedded global for metadata.
+///
+/// Use [JsBuiltin.getMetadata] instead of directly accessing this embedded
+/// global.
+const METADATA = 'metadata';
+
+/// A list of types used in the program e.g. for reflection or encoding of
+/// function types.
+///
+/// Use [JsBuiltin.getType] instead of directly accessing this embedded global.
+const TYPES = 'types';
+
+/// Returns a function that maps a name of a class to its type.
+///
+/// This embedded global is used by the runtime when computing the internal
+/// runtime-type-information (rti) object.
+const GET_TYPE_FROM_NAME = 'getTypeFromName';
+
+/// A JS map from mangled global names to their unmangled names.
+///
+/// If the program does not use reflection, this embedded global may be empty
+/// (but not null or undefined).
+const MANGLED_GLOBAL_NAMES = 'mangledGlobalNames';
+
+/// A JS map from mangled instance names to their unmangled names.
+///
+/// This embedded global is mainly used for reflection, but is also used to
+/// map const-symbols (`const Symbol('x')`) to the mangled instance names.
+///
+/// This embedded global may be empty (but not null or undefined).
+const MANGLED_NAMES = 'mangledNames';
+
+/// A JS map from dispatch tags (usually constructor names of DOM classes) to
+/// interceptor class. This map is used to find the correct interceptor for
+/// native classes.
+///
+/// This embedded global is used for natives.
+const INTERCEPTORS_BY_TAG = 'interceptorsByTag';
+
+/// A JS map from dispatch tags (usually constructor names of DOM classes) to
+/// booleans. Every tag entry of [INTERCEPTORS_BY_TAG] has a corresponding
+/// entry in the leaf-tags map.
+///
+/// A tag-entry is true, when a class can be treated as leaf class in the
+/// hierarchy. That is, even though it might have subclasses, all subclasses
+/// have the same code for the used methods.
+///
+/// This embedded global is used for natives.
+const LEAF_TAGS = 'leafTags';
+
+/// A JS function that returns the isolate tag for a given name.
+///
+/// This function uses the [ISOLATE_TAG] (below) to construct a name that is
+/// unique per isolate.
+///
+/// This embedded global is used for natives.
+// TODO(floitsch): should we rename this variable to avoid confusion with
+//    [INTERCEPTORS_BY_TAG] and [LEAF_TAGS].
+const GET_ISOLATE_TAG = 'getIsolateTag';
+
+/// A string that is different for each running isolate.
+///
+/// When this embedded global is initialized a global variable is used to
+/// ensure that no other running isolate uses the same isolate-tag string.
+///
+/// This embedded global is used for natives.
+// TODO(floitsch): should we rename this variable to avoid confusion with
+//    [INTERCEPTORS_BY_TAG] and [LEAF_TAGS].
+const ISOLATE_TAG = 'isolateTag';
+
+/// An embedded global that contains the property used to store type information
+/// on JavaScript Array instances. This is a Symbol (except for IE11, where is
+/// is a String).
+const ARRAY_RTI_PROPERTY = 'arrayRti';
+
+/// This embedded global (a function) returns the isolate-specific dispatch-tag
+/// that is used to accelerate interceptor calls.
+const DISPATCH_PROPERTY_NAME = "dispatchPropertyName";
+
+/// An embedded global that maps a [Type] to the [Interceptor] and constructors
+/// for that type.
+///
+/// More documentation can be found in the interceptors library (close to its
+/// use).
+const TYPE_TO_INTERCEPTOR_MAP = "typeToInterceptorMap";
+
+/// The current script's URI when the program was loaded.
+///
+/// This embedded global is set at startup, just before invoking `main`.
+const CURRENT_SCRIPT = 'currentScript';
+
+/// Contains a map from load-ids to lists of part indexes.
+///
+/// To load the deferred library that is represented by the load-id, the runtime
+/// must load all associated URIs (named in DEFERRED_PART_URIS) and initialize
+/// all the loaded hunks (DEFERRED_PART_HASHES).
+///
+/// This embedded global is only used for deferred loading.
+const DEFERRED_LIBRARY_PARTS = 'deferredLibraryParts';
+
+/// Contains a list of URIs (Strings), indexed by part.
+///
+/// The lists in the DEFERRED_LIBRARY_PARTS map contain indexes into this list.
+///
+/// This embedded global is only used for deferred loading.
+const DEFERRED_PART_URIS = 'deferredPartUris';
+
+/// Contains a list of hashes, indexed by part.
+///
+/// The lists in the DEFERRED_LIBRARY_PARTS map contain indexes into this list.
+///
+/// The hashes are associated with the URIs of the load-ids (see
+/// [DEFERRED_PART_URIS]). They are SHA1 (or similar) hashes of the code that
+/// must be loaded. By using cryptographic hashes we can (1) handle loading in
+/// the same web page the parts from multiple Dart applications (2) avoid
+/// loading similar code multiple times.
+///
+/// This embedded global is only used for deferred loading.
+const DEFERRED_PART_HASHES = 'deferredPartHashes';
+
+/// Initialize a loaded hunk.
+///
+/// Once a hunk (the code from a deferred URI) has been loaded it must be
+/// initialized. Calling this function with the corresponding hash (see
+/// [DEFERRED_LIBRARY_HASHES]) initializes the code.
+///
+/// This embedded global is only used for deferred loading.
+const INITIALIZE_LOADED_HUNK = 'initializeLoadedHunk';
+
+/// Returns, whether a hunk (identified by its hash) has already been loaded.
+///
+/// This embedded global is only used for deferred loading.
+const IS_HUNK_LOADED = 'isHunkLoaded';
+
+/// Returns, whether a hunk (identified by its hash) has already been
+/// initialized.
+///
+/// This embedded global is only used for deferred loading.
+const IS_HUNK_INITIALIZED = 'isHunkInitialized';
+
+/// A set (implemented as map to booleans) of hunks (identified by hashes) that
+/// have already been initialized.
+///
+/// This embedded global is only used for deferred loading.
+///
+/// This global is an emitter-internal embedded global, and not used by the
+/// runtime. The constant remains in this file to make sure that other embedded
+/// globals don't clash with it.
+const DEFERRED_INITIALIZED = 'deferredInitialized';
+
+/// A 'Universe' object used by 'dart:_rti'.
+///
+/// This embedded global is used for --experiment-new-rti.
+const RTI_UNIVERSE = 'typeUniverse';
+
+/// Names that are supported by [JS_GET_NAME].
+// TODO(herhut): Make entries lower case (as in fields) and find a better name.
+enum JsGetName {
+  GETTER_PREFIX,
+  SETTER_PREFIX,
+  CALL_PREFIX,
+  CALL_PREFIX0,
+  CALL_PREFIX1,
+  CALL_PREFIX2,
+  CALL_PREFIX3,
+  CALL_PREFIX4,
+  CALL_PREFIX5,
+  CALL_CATCH_ALL,
+  REQUIRED_PARAMETER_PROPERTY,
+  DEFAULT_VALUES_PROPERTY,
+  CALL_NAME_PROPERTY,
+  DEFERRED_ACTION_PROPERTY,
+
+  /// Prefix used for generated type argument substitutions on classes.
+  OPERATOR_AS_PREFIX,
+
+  /// Prefix used for generated type test property on classes.
+  OPERATOR_IS_PREFIX,
+
+  /// Name used for generated function types on classes and methods.
+  SIGNATURE_NAME,
+
+  /// Name of JavaScript property used to store runtime-type information on
+  /// instances of parameterized classes.
+  RTI_NAME,
+
+  /// String representation of the type of the Future class.
+  FUTURE_CLASS_TYPE_NAME,
+
+  /// Field name used for determining if an object or its interceptor has
+  /// JavaScript indexing behavior.
+  IS_INDEXABLE_FIELD_NAME,
+
+  /// String representation of the type of the null class.
+  NULL_CLASS_TYPE_NAME,
+
+  /// String representation of the type of the object class.
+  OBJECT_CLASS_TYPE_NAME,
+
+  /// Property name for Rti._as field.
+  RTI_FIELD_AS,
+
+  /// Property name for Rti._is field.
+  RTI_FIELD_IS,
+}
+
+enum JsBuiltin {
+  /// Returns the JavaScript constructor function for Dart's Object class.
+  /// This can be used for type tests, as in
+  ///
+  ///     var constructor = JS_BUILTIN('', JsBuiltin.dartObjectConstructor);
+  ///     if (JS('bool', '# instanceof #', obj, constructor))
+  ///       ...
+  dartObjectConstructor,
+
+  /// Returns the JavaScript constructor function for the runtime's Closure
+  /// class, the base class of all closure objects.  This can be used for type
+  /// tests, as in
+  ///
+  ///     var constructor = JS_BUILTIN('', JsBuiltin.dartClosureConstructor);
+  ///     if (JS('bool', '# instanceof #', obj, constructor))
+  ///       ...
+  dartClosureConstructor,
+
+  /// Returns true if the given type is a type argument of a js-interop class
+  /// or a supertype of a js-interop class.
+  ///
+  ///     JS_BUILTIN('bool', JsBuiltin.isJsInteropTypeArgument, o)
+  isJsInteropTypeArgument,
+
+  /// Returns the metadata of the given [index].
+  ///
+  ///     JS_BUILTIN('returns:var;effects:none;depends:none',
+  ///                JsBuiltin.getMetadata, index);
+  getMetadata,
+
+  /// Returns the type of the given [index].
+  ///
+  ///     JS_BUILTIN('returns:var;effects:none;depends:none',
+  ///                JsBuiltin.getType, index);
+  getType,
+}
+
+/// Names of fields of the Rti Universe object.
+class RtiUniverseFieldNames {
+  static String evalCache = 'eC';
+  static String typeRules = 'tR';
+  static String erasedTypes = 'eT';
+  static String typeParameterVariances = 'tPV';
+  static String sharedEmptyArray = 'sEA';
+}
diff --git a/pkg/js_runtime/lib/shared/recipe_syntax.dart b/pkg/js_runtime/lib/shared/recipe_syntax.dart
new file mode 100644
index 0000000..c183861
--- /dev/null
+++ b/pkg/js_runtime/lib/shared/recipe_syntax.dart
@@ -0,0 +1,237 @@
+// 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.
+
+/// Constants and predicates used for encoding and decoding type recipes.
+///
+/// This library is shared between the compiler and the runtime system.
+library dart2js._recipe_syntax;
+
+abstract class Recipe {
+  Recipe._();
+
+  // Operators.
+
+  static const int separator = _comma;
+  static const String separatorString = _commaString;
+
+  static const int toType = _semicolon;
+  static const String toTypeString = _semicolonString;
+
+  static const int pushErased = _hash;
+  static const String pushErasedString = _hashString;
+  static const int pushDynamic = _at;
+  static const String pushDynamicString = _atString;
+  static const int pushVoid = _tilde;
+  static const String pushVoidString = _tildeString;
+
+  static const int wrapStar = _asterisk;
+  static const String wrapStarString = _asteriskString;
+  static const int wrapQuestion = _question;
+  static const String wrapQuestionString = _questionString;
+  static const int wrapFutureOr = _slash;
+  static const String wrapFutureOrString = _slashString;
+
+  static const int startTypeArguments = _lessThan;
+  static const String startTypeArgumentsString = _lessThanString;
+  static const int endTypeArguments = _greaterThan;
+  static const String endTypeArgumentsString = _greaterThanString;
+
+  static const int startFunctionArguments = _leftParen;
+  static const String startFunctionArgumentsString = _leftParenString;
+  static const int endFunctionArguments = _rightParen;
+  static const String endFunctionArgumentsString = _rightParenString;
+  static const int startOptionalGroup = _leftBracket;
+  static const String startOptionalGroupString = _leftBracketString;
+  static const int endOptionalGroup = _rightBracket;
+  static const String endOptionalGroupString = _rightBracketString;
+  static const int startNamedGroup = _leftBrace;
+  static const String startNamedGroupString = _leftBraceString;
+  static const int endNamedGroup = _rightBrace;
+  static const String endNamedGroupString = _rightBraceString;
+  static const int nameSeparator = _colon;
+  static const String nameSeparatorString = _colonString;
+  static const int requiredNameSeparator = _exclamation;
+  static const String requiredNameSeparatorString = _exclamationString;
+
+  static const int genericFunctionTypeParameterIndex = _circumflex;
+  static const String genericFunctionTypeParameterIndexString =
+      _circumflexString;
+
+  static const int extensionOp = _ampersand;
+  static const String extensionOpString = _ampersandString;
+  static const int pushNeverExtension = 0;
+  static const String pushNeverExtensionString = '$pushNeverExtension';
+  static const int pushAnyExtension = 1;
+  static const String pushAnyExtensionString = '$pushAnyExtension';
+
+  // Number and name components.
+
+  static bool isDigit(int code) => code >= _digit0 && code <= _digit9;
+  static int digitValue(int code) => code - _digit0;
+
+  static bool isIdentifierStart(int ch) =>
+      (((ch | 32) - _lowercaseA) & 0xffff) < 26 ||
+      (ch == _underscore) ||
+      (ch == _dollar);
+
+  static const int period = _period;
+
+  // Private names.
+
+  static const int _formfeed = 0x0C;
+  static const String _formfeedString = '\f';
+
+  static const int _space = 0x20;
+  static const String _spaceString = ' ';
+  static const int _exclamation = 0x21;
+  static const String _exclamationString = '!';
+  static const int _hash = 0x23;
+  static const String _hashString = '#';
+  static const int _dollar = 0x24;
+  static const String _dollarString = r'$';
+  static const int _percent = 0x25;
+  static const String _percentString = '%';
+  static const int _ampersand = 0x26;
+  static const String _ampersandString = '&';
+  static const int _apostrophe = 0x27;
+  static const String _apostropheString = "'";
+  static const int _leftParen = 0x28;
+  static const String _leftParenString = '(';
+  static const int _rightParen = 0x29;
+  static const String _rightParenString = ')';
+  static const int _asterisk = 0x2A;
+  static const String _asteriskString = '*';
+  static const int _plus = 0x2B;
+  static const String _plusString = '+';
+  static const int _comma = 0x2C;
+  static const String _commaString = ',';
+  static const int _minus = 0x2D;
+  static const String _minusString = '-';
+  static const int _period = 0x2E;
+  static const String _periodString = '.';
+  static const int _slash = 0x2F;
+  static const String _slashString = '/';
+
+  static const int _digit0 = 0x30;
+  static const int _digit9 = 0x39;
+
+  static const int _colon = 0x3A;
+  static const String _colonString = ':';
+  static const int _semicolon = 0x3B;
+  static const String _semicolonString = ';';
+  static const int _lessThan = 0x3C;
+  static const String _lessThanString = '<';
+  static const int _equals = 0x3D;
+  static const String _equalsString = '=';
+  static const int _greaterThan = 0x3E;
+  static const String _greaterThanString = '>';
+  static const int _question = 0x3F;
+  static const String _questionString = '?';
+  static const int _at = 0x40;
+  static const String _atString = '@';
+
+  static const int _uppercaseA = 0x41;
+  static const int _uppercaseZ = 0x5A;
+
+  static const int _leftBracket = 0x5B;
+  static const String _leftBracketString = '[';
+  static const int _backslash = 0x5C;
+  static const String _backslashString = r'\';
+  static const int _rightBracket = 0x5D;
+  static const String _rightBracketString = ']';
+  static const int _circumflex = 0x5E;
+  static const String _circumflexString = '^';
+  static const int _underscore = 0x5F;
+  static const String _underscoreString = '_';
+  static const int _backtick = 0x60;
+  static const String _backtickString = '`';
+
+  static const int _lowercaseA = 0x61;
+  static const int _lowercaseZ = 0x7A;
+
+  static const int _leftBrace = 0x7B;
+  static const String _leftBraceString = '{';
+  static const int _vertical = 0x7C;
+  static const String _verticalString = '|';
+  static const int _rightBrace = 0x7D;
+  static const String _rightBraceString = '}';
+  static const int _tilde = 0x7E;
+  static const String _tildeString = '~';
+
+  static void testEquivalence() {
+    void test(String label, int charCode, String str) {
+      if (String.fromCharCode(charCode) != str) {
+        throw StateError("$label: String.fromCharCode($charCode) != $str");
+      }
+    }
+
+    void testExtension(String label, int op, String str) {
+      if ('$op' != str) {
+        throw StateError("$label: $op.toString() != $str");
+      }
+    }
+
+    test("separator", separator, separatorString);
+    test("toType", toType, toTypeString);
+    test("pushErased", pushErased, pushErasedString);
+    test("pushDynamic", pushDynamic, pushDynamicString);
+    test("pushVoid", pushVoid, pushVoidString);
+    test("wrapStar", wrapStar, wrapStarString);
+    test("wrapQuestion", wrapQuestion, wrapQuestionString);
+    test("wrapFutureOr", wrapFutureOr, wrapFutureOrString);
+    test("startTypeArguments", startTypeArguments, startTypeArgumentsString);
+    test("endTypeArguments", endTypeArguments, endTypeArgumentsString);
+    test("startFunctionArguments", startFunctionArguments,
+        startFunctionArgumentsString);
+    test("endFunctionArguments", endFunctionArguments,
+        endFunctionArgumentsString);
+    test("startOptionalGroup", startOptionalGroup, startOptionalGroupString);
+    test("endOptionalGroup", endOptionalGroup, endOptionalGroupString);
+    test("startNamedGroup", startNamedGroup, startNamedGroupString);
+    test("endNamedGroup", endNamedGroup, endNamedGroupString);
+    test("nameSeparator", nameSeparator, nameSeparatorString);
+    test("requiredNameSeparator", requiredNameSeparator,
+        requiredNameSeparatorString);
+    test("genericFunctionTypeParameterIndex", genericFunctionTypeParameterIndex,
+        genericFunctionTypeParameterIndexString);
+    test("extensionOp", extensionOp, extensionOpString);
+    testExtension(
+        "pushNeverExtension", pushNeverExtension, pushNeverExtensionString);
+    testExtension("pushAnyExtension", pushAnyExtension, pushAnyExtensionString);
+
+    test("_formfeed", _formfeed, _formfeedString);
+    test("_space", _space, _spaceString);
+    test("_exclamation", _exclamation, _exclamationString);
+    test("_hash", _hash, _hashString);
+    test("_dollar", _dollar, _dollarString);
+    test("_percent", _percent, _percentString);
+    test("_ampersand", _ampersand, _ampersandString);
+    test("_apostrophe", _apostrophe, _apostropheString);
+    test("_leftParen", _leftParen, _leftParenString);
+    test("_rightParen", _rightParen, _rightParenString);
+    test("_asterisk", _asterisk, _asteriskString);
+    test("_plus", _plus, _plusString);
+    test("_comma", _comma, _commaString);
+    test("_minus", _minus, _minusString);
+    test("_period", _period, _periodString);
+    test("_slash", _slash, _slashString);
+    test("_colon", _colon, _colonString);
+    test("_semicolon", _semicolon, _semicolonString);
+    test("_lessThan", _lessThan, _lessThanString);
+    test("_equals", _equals, _equalsString);
+    test("_greaterThan", _greaterThan, _greaterThanString);
+    test("_question", _question, _questionString);
+    test("_at", _at, _atString);
+    test("_leftBracket", _leftBracket, _leftBracketString);
+    test("_backslash", _backslash, _backslashString);
+    test("_rightBracket", _rightBracket, _rightBracketString);
+    test("_circumflex", _circumflex, _circumflexString);
+    test("_underscore", _underscore, _underscoreString);
+    test("_backtick", _backtick, _backtickString);
+    test("_leftBrace", _leftBrace, _leftBraceString);
+    test("_vertical", _vertical, _verticalString);
+    test("_rightBrace", _rightBrace, _rightBraceString);
+    test("_tilde", _tilde, _tildeString);
+  }
+}
diff --git a/pkg/js_runtime/pubspec.yaml b/pkg/js_runtime/pubspec.yaml
new file mode 100644
index 0000000..e707d77
--- /dev/null
+++ b/pkg/js_runtime/pubspec.yaml
@@ -0,0 +1,12 @@
+name: js_runtime
+# This package is not intended for consumption on pub.dev. DO NOT publish.
+publish_to: none
+
+environment:
+  sdk: '>=2.12.0 <3.0.0'
+
+dev_dependencies:
+  expect:
+    path: ../expect
+  _fe_analyzer_shared:
+    path: ../_fe_analyzer_shared
diff --git a/pkg/js_runtime/test/in_sync_test.dart b/pkg/js_runtime/test/in_sync_test.dart
new file mode 100644
index 0000000..4dbef635
--- /dev/null
+++ b/pkg/js_runtime/test/in_sync_test.dart
@@ -0,0 +1,39 @@
+// 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 to verify that this package is in-sync with dart2js runtime libraries.
+import 'dart:io';
+
+import 'package:_fe_analyzer_shared/src/util/relativize.dart';
+import 'package:expect/expect.dart';
+
+void main(List<String> argv) {
+  var packageDir = Platform.script.resolve('../lib/shared/');
+  var sdkDir = Platform.script
+      .resolve('../../../sdk/lib/_internal/js_runtime/lib/shared/');
+  var rPackageDir =
+      relativizeUri(Directory.current.uri, packageDir, Platform.isWindows);
+  var rSdkDir =
+      relativizeUri(Directory.current.uri, sdkDir, Platform.isWindows);
+
+  for (var file in Directory.fromUri(sdkDir).listSync()) {
+    if (file is File) {
+      var filename = file.uri.pathSegments.last;
+      var packageFile = File.fromUri(packageDir.resolve(filename));
+      Expect.isTrue(
+          packageFile.existsSync(),
+          "$filename not in sync. Please update it by running:\n"
+          "  cp $rSdkDir$filename $rPackageDir$filename");
+      var original = file.readAsBytesSync();
+      var copy = packageFile.readAsBytesSync();
+      Expect.listEquals(
+          original,
+          copy,
+          "$filename not in sync. Please update it by running:\n"
+          "  cp $rSdkDir$filename $rPackageDir$filename");
+    }
+  }
+}
diff --git a/pkg/kernel/bin/count_breakdown.dart b/pkg/kernel/bin/count_breakdown.dart
index 43450ff..13dd0737 100755
--- a/pkg/kernel/bin/count_breakdown.dart
+++ b/pkg/kernel/bin/count_breakdown.dart
@@ -3,6 +3,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.9
+
 import 'dart:io';
 import 'package:kernel/kernel.dart';
 import 'package:kernel/src/tool/command_line_util.dart';
diff --git a/pkg/kernel/bin/dump.dart b/pkg/kernel/bin/dump.dart
index 0c3ab47..c95a4e5 100755
--- a/pkg/kernel/bin/dump.dart
+++ b/pkg/kernel/bin/dump.dart
@@ -3,6 +3,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.9
+
 import 'dart:io';
 
 import 'package:kernel/kernel.dart';
diff --git a/pkg/kernel/bin/size_breakdown.dart b/pkg/kernel/bin/size_breakdown.dart
index 01fec0f..979b828 100755
--- a/pkg/kernel/bin/size_breakdown.dart
+++ b/pkg/kernel/bin/size_breakdown.dart
@@ -3,6 +3,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.9
+
 import 'dart:io';
 
 import 'package:kernel/kernel.dart';
@@ -62,9 +64,9 @@
     linkTableSize += byteOffset;
   }
 
-  Map<Uri, Source> readUriToSource() {
+  Map<Uri, Source> readUriToSource(bool readCoverage) {
     uriToSourceSize -= byteOffset;
-    var result = super.readUriToSource();
+    var result = super.readUriToSource(readCoverage);
     uriToSourceSize += byteOffset;
     return result;
   }
diff --git a/pkg/kernel/bin/split.dart b/pkg/kernel/bin/split.dart
index e3c99e8..61d5f0c 100755
--- a/pkg/kernel/bin/split.dart
+++ b/pkg/kernel/bin/split.dart
@@ -3,6 +3,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.9
+
 import 'dart:async';
 import 'dart:io';
 
diff --git a/pkg/kernel/bin/type_check.dart b/pkg/kernel/bin/type_check.dart
index 5c3ef65..5c41244 100755
--- a/pkg/kernel/bin/type_check.dart
+++ b/pkg/kernel/bin/type_check.dart
@@ -3,6 +3,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.9
+
 import 'dart:io';
 
 import 'package:kernel/error_formatter.dart';
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index a93760a..6e71d73 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 52;
+  UInt32 formatVersion = 54;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -363,8 +363,8 @@
   UriReference fileUri;
   FileOffset fileOffset;
   FileOffset fileEndOffset;
-  UInt flags (isFinal, isConst, isStatic, hasImplicitGetter, hasImplicitSetter,
-                isCovariant, isGenericCovariantImpl, isLate, isExtensionMember,
+  UInt flags (isFinal, isConst, isStatic, isCovariant,
+                isGenericCovariantImpl, isLate, isExtensionMember,
                 isNonNullableByDefault, isInternalImplementation);
   Name name;
   List<Expression> annotations;
@@ -399,12 +399,12 @@
 /*
 enum ProcedureStubKind {
   Regular,
-  ForwardingStub,
-  ForwardingSuperStub,
+  AbstractForwardingStub,
+  ConcreteForwardingStub,
   NoSuchMethodForwarder,
   MemberSignature,
-  MixinStub,
-  MixinSuperStub,
+  AbstractMixinStub,
+  ConcreteMixinStub,
 }
 */
 
@@ -615,12 +615,86 @@
   MemberReference interfaceTargetOrigin; // May be NullReference.
 }
 
+/*
+enum InstanceAccessKind {
+  Instance,
+  Object,
+  Inapplicable,
+  Nullable,
+}
+*/
+
+type InstanceGet extends Expression {
+  Byte tag = 118;
+  Byte kind; // Index into InstanceAccessKind above.
+  FileOffset fileOffset;
+  Expression receiver;
+  Name name;
+  DartType resultType;
+  MemberReference interfaceTarget;
+  MemberReference interfaceTargetOrigin; // May be NullReference.
+}
+
+type InstanceSet extends Expression {
+  Byte tag = 119;
+  Byte kind; // Index into InstanceAccessKind above.
+  FileOffset fileOffset;
+  Expression receiver;
+  Name name;
+  Expression value;
+  MemberReference interfaceTarget;
+  MemberReference interfaceTargetOrigin; // May be NullReference.
+}
+
+type InstanceTearOff extends Expression {
+  Byte tag = 121;
+  Byte kind; // Index into InstanceAccessKind above.
+  FileOffset fileOffset;
+  Expression receiver;
+  Name name;
+  DartType resultType;
+  MemberReference interfaceTarget;
+  MemberReference interfaceTargetOrigin; // May be NullReference.
+}
+
+/*
+enum DynamicAccessKind {
+  Dynamic,
+  Never,
+  Invalid,
+  Unresolved,
+}
+*/
+
+type DynamicGet extends Expression {
+  Byte tag = 122;
+  Byte kind; // Index into DynamicAccessKind above.
+  FileOffset fileOffset;
+  Expression receiver;
+  Name name;
+}
+
+type DynamicSet extends Expression {
+  Byte tag = 123;
+  Byte kind; // Index into DynamicAccessKind above.
+  FileOffset fileOffset;
+  Expression receiver;
+  Name name;
+  Expression value;
+}
+
 type StaticGet extends Expression {
   Byte tag = 26;
   FileOffset fileOffset;
   MemberReference target;
 }
 
+type StaticTearOff extends Expression {
+  Byte tag = 17;
+  FileOffset fileOffset;
+  MemberReference target;
+}
+
 type StaticSet extends Expression {
   Byte tag = 27;
   FileOffset fileOffset;
@@ -644,7 +718,7 @@
 
 type MethodInvocation extends Expression {
   Byte tag = 28;
-  Byte flags;
+  Byte flags (isInvariant, isBoundsSafe);
   FileOffset fileOffset;
   Expression receiver;
   Name name;
@@ -653,6 +727,81 @@
   MemberReference interfaceTargetOrigin; // May be NullReference.
 }
 
+type InstanceInvocation extends Expression {
+  Byte tag = 120;
+  Byte kind; // Index into InstanceAccessKind above.
+  Byte flags (isInvariant, isBoundsSafe);
+  FileOffset fileOffset;
+  Expression receiver;
+  Name name;
+  Arguments arguments;
+  DartType functionType;
+  MemberReference interfaceTarget;
+  MemberReference interfaceTargetOrigin; // May be NullReference.
+}
+
+type DynamicInvocation extends Expression {
+  Byte tag = 124;
+  Byte kind; // Index into DynamicAccessKind above.
+  FileOffset fileOffset;
+  Expression receiver;
+  Name name;
+  Arguments arguments;
+}
+
+/*
+enum FunctionAccessKind {
+  Function,
+  FunctionType,
+  Inapplicable,
+  Nullable,
+}
+*/
+
+type FunctionInvocation extends Expression {
+  Byte tag = 125;
+  Byte kind; // Index into FunctionAccessKind above.
+  FileOffset fileOffset;
+  Expression receiver;
+  Arguments arguments;
+  DartType functionType; // Use `const DynamicType()` as `null`.
+}
+
+type FunctionTearOff extends Expression {
+  Byte tag = 126;
+  FileOffset fileOffset;
+  Expression receiver;
+  DartType functionType;
+}
+
+type LocalFunctionInvocation extends Expression {
+  Byte tag = 127;
+  FileOffset fileOffset;
+  // Byte offset in the binary for the variable declaration (without tag).
+  UInt variableDeclarationPosition;
+  VariableReference variable;
+  Arguments arguments;
+  DartType functionType;
+}
+
+type EqualsNull extends Expression {
+  Byte tag = 15;
+  FileOffset fileOffset;
+  Expression expression;
+  Byte isNot;
+}
+
+type EqualsCall extends Expression {
+  Byte tag = 16;
+  FileOffset fileOffset;
+  Expression left;
+  Expression right;
+  Byte isNot;
+  DartType functionType;
+  MemberReference interfaceTarget;
+  MemberReference interfaceTargetOrigin; // May be NullReference.
+}
+
 type SuperMethodInvocation extends Expression {
   Byte tag = 29;
   FileOffset fileOffset;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 41c88aa..65796ed 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.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.9
+
 /// -----------------------------------------------------------------------
 ///                          WHEN CHANGING THIS FILE:
 /// -----------------------------------------------------------------------
@@ -545,9 +547,11 @@
     for (int i = 0; i < fields.length; ++i) {
       Field field = fields[i];
       canonicalName.getChildFromField(field).bindTo(field.getterReference);
-      canonicalName
-          .getChildFromFieldSetter(field)
-          .bindTo(field.setterReference);
+      if (field.hasSetter) {
+        canonicalName
+            .getChildFromFieldSetter(field)
+            .bindTo(field.setterReference);
+      }
     }
     for (int i = 0; i < procedures.length; ++i) {
       Procedure member = procedures[i];
@@ -1192,9 +1196,11 @@
     for (int i = 0; i < fields.length; ++i) {
       Field member = fields[i];
       canonicalName.getChildFromField(member).bindTo(member.getterReference);
-      canonicalName
-          .getChildFromFieldSetter(member)
-          .bindTo(member.setterReference);
+      if (member.hasSetter) {
+        canonicalName
+            .getChildFromFieldSetter(member)
+            .bindTo(member.setterReference);
+      }
     }
     for (int i = 0; i < procedures.length; ++i) {
       Procedure member = procedures[i];
@@ -1462,6 +1468,11 @@
   }
 
   @override
+  Location _getLocationInEnclosingFile(int offset) {
+    return _getLocationInComponent(enclosingComponent, fileUri, offset);
+  }
+
+  @override
   String toString() {
     return "Extension(${toStringInternal()})";
   }
@@ -1683,26 +1694,42 @@
   CanonicalName get getterCanonicalName => getterReference?.canonicalName;
   CanonicalName get setterCanonicalName => setterReference?.canonicalName;
 
-  Field(Name name,
+  Field.mutable(Name name,
+      {this.type: const DynamicType(),
+      this.initializer,
+      bool isCovariant: false,
+      bool isFinal: false,
+      bool isStatic: false,
+      bool isLate: false,
+      int transformerFlags: 0,
+      Uri fileUri,
+      Reference getterReference,
+      Reference setterReference})
+      : this.setterReference = setterReference ?? new Reference(),
+        super(name, fileUri, getterReference) {
+    this.setterReference.node = this;
+    assert(type != null);
+    initializer?.parent = this;
+    this.isCovariant = isCovariant;
+    this.isFinal = isFinal;
+    this.isStatic = isStatic;
+    this.isLate = isLate;
+    this.transformerFlags = transformerFlags;
+  }
+
+  Field.immutable(Name name,
       {this.type: const DynamicType(),
       this.initializer,
       bool isCovariant: false,
       bool isFinal: false,
       bool isConst: false,
       bool isStatic: false,
-      bool hasImplicitGetter,
-      bool hasImplicitSetter,
       bool isLate: false,
       int transformerFlags: 0,
       Uri fileUri,
-      Reference getterReference,
-      Reference setterReference})
-      :
-        // TODO(jensj): Maybe don't create one for final fields?
-        // ('final' is a mutable setting though).
-        this.setterReference = setterReference ?? new Reference(),
+      Reference getterReference})
+      : this.setterReference = null,
         super(name, fileUri, getterReference) {
-    this.setterReference.node = this;
     assert(type != null);
     initializer?.parent = this;
     this.isCovariant = isCovariant;
@@ -1710,31 +1737,26 @@
     this.isConst = isConst;
     this.isStatic = isStatic;
     this.isLate = isLate;
-    this.hasImplicitGetter = hasImplicitGetter ?? !isStatic;
-    this.hasImplicitSetter = hasImplicitSetter ??
-        (!isStatic &&
-            !isConst &&
-            (!isFinal || (isLate && initializer == null)));
     this.transformerFlags = transformerFlags;
   }
 
   @override
   void _relinkNode() {
     super._relinkNode();
-    this.setterReference.node = this;
+    if (hasSetter) {
+      this.setterReference.node = this;
+    }
   }
 
   static const int FlagFinal = 1 << 0; // Must match serialized bit positions.
   static const int FlagConst = 1 << 1;
   static const int FlagStatic = 1 << 2;
-  static const int FlagHasImplicitGetter = 1 << 3;
-  static const int FlagHasImplicitSetter = 1 << 4;
-  static const int FlagCovariant = 1 << 5;
-  static const int FlagGenericCovariantImpl = 1 << 6;
-  static const int FlagLate = 1 << 7;
-  static const int FlagExtensionMember = 1 << 8;
-  static const int FlagNonNullableByDefault = 1 << 9;
-  static const int FlagInternalImplementation = 1 << 10;
+  static const int FlagCovariant = 1 << 3;
+  static const int FlagGenericCovariantImpl = 1 << 4;
+  static const int FlagLate = 1 << 5;
+  static const int FlagExtensionMember = 1 << 6;
+  static const int FlagNonNullableByDefault = 1 << 7;
+  static const int FlagInternalImplementation = 1 << 8;
 
   /// Whether the field is declared with the `covariant` keyword.
   bool get isCovariant => flags & FlagCovariant != 0;
@@ -1746,26 +1768,6 @@
   @override
   bool get isExtensionMember => flags & FlagExtensionMember != 0;
 
-  /// If true, a getter should be generated for this field.
-  ///
-  /// If false, there may or may not exist an explicit getter in the same class
-  /// with the same name as the field.
-  ///
-  /// By default, all non-static fields have implicit getters.
-  bool get hasImplicitGetter => flags & FlagHasImplicitGetter != 0;
-
-  /// If true, a setter should be generated for this field.
-  ///
-  /// If false, there may or may not exist an explicit setter in the same class
-  /// with the same name as the field.
-  ///
-  /// Final fields never have implicit setters, but a field without an implicit
-  /// setter is not necessarily final, as it may be mutated by direct field
-  /// access.
-  ///
-  /// By default, all non-static, non-final fields have implicit setters.
-  bool get hasImplicitSetter => flags & FlagHasImplicitSetter != 0;
-
   /// Indicates whether the implicit setter associated with this field needs to
   /// contain a runtime type check to deal with generic covariance.
   ///
@@ -1804,18 +1806,6 @@
         value ? (flags | FlagExtensionMember) : (flags & ~FlagExtensionMember);
   }
 
-  void set hasImplicitGetter(bool value) {
-    flags = value
-        ? (flags | FlagHasImplicitGetter)
-        : (flags & ~FlagHasImplicitGetter);
-  }
-
-  void set hasImplicitSetter(bool value) {
-    flags = value
-        ? (flags | FlagHasImplicitSetter)
-        : (flags & ~FlagHasImplicitSetter);
-  }
-
   void set isGenericCovariantImpl(bool value) {
     flags = value
         ? (flags | FlagGenericCovariantImpl)
@@ -1832,11 +1822,9 @@
         : (flags & ~FlagInternalImplementation);
   }
 
-  /// True if the field is neither final nor const.
-  bool get isMutable => flags & (FlagFinal | FlagConst) == 0;
   bool get isInstanceMember => !isStatic;
   bool get hasGetter => true;
-  bool get hasSetter => isMutable || isLate && initializer == null;
+  bool get hasSetter => setterReference != null;
 
   bool get isExternal => false;
   void set isExternal(bool value) {
@@ -2163,16 +2151,16 @@
   ///        void method2(int o) {}
   ///     }
   ///     class C implements A<int>, B {
-  ///        // Forwarding stub needed because the parameter is covariant in
-  ///        // `B.method1` but not in `A.method1`.
+  ///        // Abstract forwarding stub needed because the parameter is
+  ///        // covariant in `B.method1` but not in `A.method1`.
   ///        void method1(covariant num o);
-  ///        // Forwarding stub needed because the parameter is a generic
-  ///        // covariant impl in `A.method2` but not in `B.method2`.
+  ///        // Abstract forwarding stub needed because the parameter is a
+  ///        // generic covariant impl in `A.method2` but not in `B.method2`.
   ///        void method2(/*generic-covariant-impl*/ int o);
   ///     }
   ///
   /// The stub target is one of the overridden members.
-  ForwardingStub,
+  AbstractForwardingStub,
 
   /// A concrete procedure inserted to add `isCovariant` and
   /// `isGenericCovariantImpl` checks to parameters before calling the
@@ -2191,15 +2179,15 @@
   ///        void method2(int o) {}
   ///     }
   ///     class C extends A<int> implements B {
-  ///        // Forwarding stub needed because the parameter is covariant in
-  ///        // `B.method1` but not in `A.method1`.
+  ///        // Concrete forwarding stub needed because the parameter is
+  ///        // covariant in `B.method1` but not in `A.method1`.
   ///        void method1(covariant num o) => super.method1(o);
-  ///        // No need for a super stub for `A.method2` because it has the
-  ///        // right covariance flags already.
+  ///        // No need for a concrete forwarding stub for `A.method2` because
+  ///        // it has the right covariance flags already.
   ///     }
   ///
   /// The stub target is the called superclass member.
-  ForwardingSuperStub,
+  ConcreteForwardingStub,
 
   /// A concrete procedure inserted to forward calls to `noSuchMethod` for
   /// an inherited member that it does not implement.
@@ -2274,22 +2262,23 @@
   ///        void method();
   ///     }
   ///     class Class = Super with Mixin
-  ///       // A mixin stub for `A.method` is added to `Class`
+  ///       // An abstract mixin stub for `A.method` is added to `Class`
   ///       void method();
   ///     ;
   ///
   /// This is added to ensure that interface targets are resolved consistently
-  /// in face of cloning. For instance, without the mixin stub, this call:
+  /// in face of cloning. For instance, without the abstract mixin stub, this
+  /// call:
   ///
   ///     method(Class c) => c.method();
   ///
-  /// would use `Mixin.method` as its target, but after load from a VM .dill
+  /// would use `Mixin.method` as its target, but after loading from a VM .dill
   /// (which clones all mixin members) the call would resolve to `Class.method`
   /// instead. By adding the mixin stub to `Class`, all accesses both before
   /// and after .dill will point to `Class.method`.
   ///
   /// The stub target is the mixin member.
-  MixinStub,
+  AbstractMixinStub,
 
   /// A concrete procedure inserted for the application of a concrete mixin
   /// member. The implementation calls the mixin member via a super-call.
@@ -2302,26 +2291,26 @@
   ///        void method() {}
   ///     }
   ///     class Class = Super with Mixin
-  ///       // A mixin stub for `A.method` is added to `Class` which calls
-  ///       // `A.method`.
+  ///       // A concrete mixin stub for `A.method` is added to `Class` which
+  ///       // calls `A.method`.
   ///       void method() => super.method();
   ///     ;
   ///
   /// This is added to ensure that super accesses are resolved correctly, even
-  /// in face of cloning. For instance, without the mixin super stub, this super
-  /// call:
+  /// in face of cloning. For instance, without the concrete mixin stub, this
+  /// super call:
   ///
   ///     class Subclass extends Class {
   ///       method(Class c) => super.method();
   ///     }
   ///
-  /// would use `Mixin.method` as its target, which would to be update to match
-  /// the cloning of mixin member performed for instance by the VM. By adding
-  /// the mixin super stub to `Class`, all accesses both before and after
-  /// cloning will point to `Class.method`.
+  /// would use `Mixin.method` as its target, which would need to be updated to
+  /// match the clone of the mixin member performed for instance by the VM. By
+  /// adding the concrete mixin stub to `Class`, all accesses both before and
+  /// after cloning will point to `Class.method`.
   ///
   /// The stub target is the called mixin member.
-  MixinSuperStub,
+  ConcreteMixinStub,
 }
 
 /// A method, getter, setter, index-getter, index-setter, operator overloader,
@@ -2457,22 +2446,19 @@
 
   /// If set, this flag indicates that this function's implementation exists
   /// solely for the purpose of type checking arguments and forwarding to
-  /// [forwardingStubSuperTarget].
+  /// [concreteForwardingStubTarget].
   ///
   /// Note that just because this bit is set doesn't mean that the function was
   /// not declared in the source; it's possible that this is a forwarding
   /// semi-stub (see isForwardingSemiStub).  To determine whether this function
   /// was present in the source, consult [isSyntheticForwarder].
   bool get isForwardingStub =>
-      stubKind == ProcedureStubKind.ForwardingStub ||
-      stubKind == ProcedureStubKind.ForwardingSuperStub;
+      stubKind == ProcedureStubKind.AbstractForwardingStub ||
+      stubKind == ProcedureStubKind.ConcreteForwardingStub;
 
   /// If set, this flag indicates that although this function is a forwarding
   /// stub, it was present in the original source as an abstract method.
-  bool get isForwardingSemiStub =>
-      !isSynthetic &&
-      (stubKind == ProcedureStubKind.ForwardingStub ||
-          stubKind == ProcedureStubKind.ForwardingSuperStub);
+  bool get isForwardingSemiStub => !isSynthetic && isForwardingStub;
 
   /// If set, this method is a class member added to show the type of an
   /// inherited member.
@@ -2491,7 +2477,7 @@
 
   /// If set, this flag indicates that this function was not present in the
   /// source, and it exists solely for the purpose of type checking arguments
-  /// and forwarding to [forwardingStubSuperTarget].
+  /// and forwarding to [concreteForwardingStubTarget].
   bool get isSyntheticForwarder => isForwardingStub && !isForwardingSemiStub;
   bool get isSynthetic => flags & FlagSynthetic != 0;
 
@@ -2550,13 +2536,13 @@
         : (flags & ~FlagNonNullableByDefault);
   }
 
-  Member get forwardingStubSuperTarget =>
-      stubKind == ProcedureStubKind.ForwardingSuperStub
+  Member get concreteForwardingStubTarget =>
+      stubKind == ProcedureStubKind.ConcreteForwardingStub
           ? stubTargetReference?.asMember
           : null;
 
-  Member get forwardingStubInterfaceTarget =>
-      stubKind == ProcedureStubKind.ForwardingStub
+  Member get abstractForwardingStubTarget =>
+      stubKind == ProcedureStubKind.AbstractForwardingStub
           ? stubTargetReference?.asMember
           : null;
 
@@ -3414,6 +3400,280 @@
   }
 }
 
+enum DynamicAccessKind {
+  /// An access on a receiver of type dynamic.
+  ///
+  /// An access of this kind always results in a value of static type dynamic.
+  ///
+  /// Valid accesses to Object members on receivers of type dynamic are encoded
+  /// as an [InstanceInvocation] of kind [InstanceAccessKind.Object].
+  Dynamic,
+
+  /// An access on a receiver of type Never.
+  ///
+  /// An access of this kind always results in a value of static type Never.
+  ///
+  /// Valid accesses to Object members on receivers of type Never are also
+  /// encoded as [DynamicInvocation] of kind [DynamicAccessKind.Never] and _not_
+  /// as an [InstanceInvocation] of kind [InstanceAccessKind.Object].
+  Never,
+
+  /// An access on a receiver of an invalid type.
+  ///
+  /// An access of this kind always results in a value of an invalid static
+  /// type.
+  Invalid,
+
+  Unresolved,
+}
+
+class DynamicGet extends Expression {
+  final DynamicAccessKind kind;
+  Expression receiver;
+  Name name;
+
+  DynamicGet(this.kind, this.receiver, this.name) {
+    receiver?.parent = this;
+  }
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitDynamicGet(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitDynamicGet(this, arg);
+
+  @override
+  DartType getStaticTypeInternal(StaticTypeContext context) {
+    switch (kind) {
+      case DynamicAccessKind.Dynamic:
+        return const DynamicType();
+      case DynamicAccessKind.Never:
+        return const NeverType(Nullability.nonNullable);
+      case DynamicAccessKind.Invalid:
+      case DynamicAccessKind.Unresolved:
+        return const InvalidType();
+    }
+    return const DynamicType();
+  }
+
+  @override
+  void visitChildren(Visitor v) {
+    receiver?.accept(v);
+    name?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "DynamicGet($kind,${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver,
+        minimumPrecedence: astToText.Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeName(name);
+  }
+}
+
+/// An property read of an instance getter or field with a statically known
+/// interface target.
+class InstanceGet extends Expression {
+  final InstanceAccessKind kind;
+  Expression receiver;
+  Name name;
+
+  /// The static type of result of the property read.
+  ///
+  /// This includes substituted type parameters from the static receiver type.
+  ///
+  /// For instance
+  ///
+  ///    class A<T> {
+  ///      T get t;
+  ///    }
+  ///    m(A<String> a) {
+  ///      a.t; // The result type is `String`.
+  ///    }
+  ///
+  DartType resultType;
+
+  Reference interfaceTargetReference;
+
+  InstanceGet(InstanceAccessKind kind, Expression receiver, Name name,
+      {Member interfaceTarget, DartType resultType})
+      : this.byReference(kind, receiver, name,
+            interfaceTargetReference: getMemberReferenceGetter(interfaceTarget),
+            resultType: resultType);
+
+  InstanceGet.byReference(this.kind, this.receiver, this.name,
+      {this.interfaceTargetReference, this.resultType})
+      : assert(interfaceTargetReference != null),
+        assert(resultType != null) {
+    receiver?.parent = this;
+  }
+
+  Member get interfaceTarget => interfaceTargetReference?.asMember;
+
+  void set interfaceTarget(Member member) {
+    interfaceTargetReference = getMemberReferenceSetter(member);
+  }
+
+  @override
+  DartType getStaticTypeInternal(StaticTypeContext context) => resultType;
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitInstanceGet(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitInstanceGet(this, arg);
+
+  visitChildren(Visitor v) {
+    receiver?.accept(v);
+    interfaceTarget?.acceptReference(v);
+    name?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "InstanceGet($kind,${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver,
+        minimumPrecedence: astToText.Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeInterfaceMemberName(interfaceTargetReference, name);
+  }
+}
+
+/// A tear-off of the 'call' method on an expression whose static type is
+/// a function type or the type 'Function'.
+class FunctionTearOff extends Expression {
+  Expression receiver;
+
+  FunctionTearOff(this.receiver) {
+    receiver?.parent = this;
+  }
+
+  DartType getStaticTypeInternal(StaticTypeContext context) =>
+      receiver.getStaticType(context);
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitFunctionTearOff(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitFunctionTearOff(this, arg);
+
+  visitChildren(Visitor v) {
+    receiver?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "FunctionTearOff(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver,
+        minimumPrecedence: astToText.Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeName(Name.callName);
+  }
+}
+
+/// A tear-off of an instance method with a statically known interface target.
+class InstanceTearOff extends Expression {
+  final InstanceAccessKind kind;
+  Expression receiver;
+  Name name;
+
+  /// The static type of result of the tear-off.
+  ///
+  /// This includes substituted type parameters from the static receiver type.
+  ///
+  /// For instance
+  ///
+  ///    class A<T, S> {
+  ///      T method<U>(S s, U u) { ... }
+  ///    }
+  ///    m(A<String, int> a) {
+  ///      a.method; // The result type is `String Function<U>(int, U)`.
+  ///    }
+  ///
+  DartType resultType;
+
+  Reference interfaceTargetReference;
+
+  InstanceTearOff(InstanceAccessKind kind, Expression receiver, Name name,
+      {Procedure interfaceTarget, DartType resultType})
+      : this.byReference(kind, receiver, name,
+            interfaceTargetReference: getMemberReferenceGetter(interfaceTarget),
+            resultType: resultType);
+
+  InstanceTearOff.byReference(this.kind, this.receiver, this.name,
+      {this.interfaceTargetReference, this.resultType}) {
+    receiver?.parent = this;
+  }
+
+  Procedure get interfaceTarget => interfaceTargetReference?.asMember;
+
+  void set interfaceTarget(Member member) {
+    interfaceTargetReference = getMemberReferenceSetter(member);
+  }
+
+  @override
+  DartType getStaticTypeInternal(StaticTypeContext context) => resultType;
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitInstanceTearOff(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitInstanceTearOff(this, arg);
+
+  visitChildren(Visitor v) {
+    receiver?.accept(v);
+    interfaceTarget?.acceptReference(v);
+    name?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "InstanceTearOff($kind, ${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver,
+        minimumPrecedence: astToText.Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeInterfaceMemberName(interfaceTargetReference, name);
+  }
+}
+
 /// Expression of form `x.field`.
 ///
 /// This may invoke a getter, read a field, or tear off a method.
@@ -3438,7 +3698,6 @@
     interfaceTargetReference = getMemberReferenceGetter(member);
   }
 
-  @override
   DartType getStaticTypeInternal(StaticTypeContext context) {
     Member interfaceTarget = this.interfaceTarget;
     if (interfaceTarget != null) {
@@ -3489,6 +3748,128 @@
   }
 }
 
+class DynamicSet extends Expression {
+  final DynamicAccessKind kind;
+  Expression receiver;
+  Name name;
+  Expression value;
+
+  DynamicSet(this.kind, this.receiver, this.name, this.value) {
+    receiver?.parent = this;
+    value?.parent = this;
+  }
+
+  DartType getStaticTypeInternal(StaticTypeContext context) =>
+      value.getStaticType(context);
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitDynamicSet(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitDynamicSet(this, arg);
+
+  visitChildren(Visitor v) {
+    receiver?.accept(v);
+    name?.accept(v);
+    value?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (value != null) {
+      value = value.accept<TreeNode>(v);
+      value?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "DynamicSet($kind,${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver,
+        minimumPrecedence: astToText.Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeName(name);
+    printer.write(' = ');
+    printer.writeExpression(value);
+  }
+}
+
+/// An property write of an instance setter or field with a statically known
+/// interface target.
+class InstanceSet extends Expression {
+  final InstanceAccessKind kind;
+  Expression receiver;
+  Name name;
+  Expression value;
+
+  Reference interfaceTargetReference;
+
+  InstanceSet(
+      InstanceAccessKind kind, Expression receiver, Name name, Expression value,
+      {Member interfaceTarget})
+      : this.byReference(kind, receiver, name, value,
+            interfaceTargetReference:
+                getMemberReferenceSetter(interfaceTarget));
+
+  InstanceSet.byReference(this.kind, this.receiver, this.name, this.value,
+      {this.interfaceTargetReference})
+      : assert(interfaceTargetReference != null) {
+    receiver?.parent = this;
+    value?.parent = this;
+  }
+
+  Member get interfaceTarget => interfaceTargetReference?.asMember;
+
+  void set interfaceTarget(Member member) {
+    interfaceTargetReference = getMemberReferenceSetter(member);
+  }
+
+  DartType getStaticTypeInternal(StaticTypeContext context) =>
+      value.getStaticType(context);
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitInstanceSet(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitInstanceSet(this, arg);
+
+  visitChildren(Visitor v) {
+    receiver?.accept(v);
+    interfaceTarget?.acceptReference(v);
+    name?.accept(v);
+    value?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (value != null) {
+      value = value.accept<TreeNode>(v);
+      value?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "InstanceSet(${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 `x.field = value`.
 ///
 /// This may invoke a setter or assign a field.
@@ -3518,10 +3899,6 @@
     interfaceTargetReference = getMemberReferenceSetter(member);
   }
 
-  DartType getStaticType(StaticTypeContext context) =>
-      getStaticTypeInternal(context);
-
-  @override
   DartType getStaticTypeInternal(StaticTypeContext context) =>
       value.getStaticType(context);
 
@@ -3648,10 +4025,6 @@
     interfaceTargetReference = getMemberReferenceSetter(member);
   }
 
-  DartType getStaticType(StaticTypeContext context) =>
-      getStaticTypeInternal(context);
-
-  @override
   DartType getStaticTypeInternal(StaticTypeContext context) =>
       value.getStaticType(context);
 
@@ -3701,10 +4074,6 @@
     targetReference = getMemberReferenceGetter(target);
   }
 
-  DartType getStaticType(StaticTypeContext context) =>
-      getStaticTypeInternal(context);
-
-  @override
   DartType getStaticTypeInternal(StaticTypeContext context) =>
       target.getterType;
 
@@ -3729,6 +4098,45 @@
   }
 }
 
+/// Tear-off of a static method.
+class StaticTearOff extends Expression {
+  Reference targetReference;
+
+  StaticTearOff(Procedure target)
+      : this.byReference(getMemberReferenceGetter(target));
+
+  StaticTearOff.byReference(this.targetReference);
+
+  Procedure get target => targetReference?.asProcedure;
+
+  void set target(Procedure target) {
+    targetReference = getMemberReferenceGetter(target);
+  }
+
+  DartType getStaticTypeInternal(StaticTypeContext context) =>
+      target.getterType;
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitStaticTearOff(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitStaticTearOff(this, arg);
+
+  visitChildren(Visitor v) {
+    target?.acceptReference(v);
+  }
+
+  transformChildren(Transformer v) {}
+
+  @override
+  String toString() {
+    return "StaticTearOff(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeMemberName(targetReference);
+  }
+}
+
 /// Assign a static field or call a static setter.
 ///
 /// Evaluates to the value of [value].
@@ -3750,10 +4158,6 @@
     targetReference = getMemberReferenceSetter(target);
   }
 
-  DartType getStaticType(StaticTypeContext context) =>
-      getStaticTypeInternal(context);
-
-  @override
   DartType getStaticTypeInternal(StaticTypeContext context) =>
       value.getStaticType(context);
 
@@ -3916,7 +4320,7 @@
 /// [SuperMethodInvocation], [StaticInvocation], and [ConstructorInvocation].
 abstract class InvocationExpression extends Expression {
   Arguments get arguments;
-  set arguments(Arguments value);
+  void set arguments(Arguments value);
 
   /// Name of the invoked method.
   ///
@@ -3924,6 +4328,566 @@
   Name get name;
 }
 
+class DynamicInvocation extends InvocationExpression {
+  final DynamicAccessKind kind;
+  Expression receiver;
+  Name name;
+  Arguments arguments;
+
+  DynamicInvocation(this.kind, this.receiver, this.name, this.arguments) {
+    receiver?.parent = this;
+    arguments?.parent = this;
+  }
+
+  @override
+  DartType getStaticTypeInternal(StaticTypeContext context) {
+    switch (kind) {
+      case DynamicAccessKind.Dynamic:
+        return const DynamicType();
+      case DynamicAccessKind.Never:
+        return const NeverType(Nullability.nonNullable);
+      case DynamicAccessKind.Invalid:
+      case DynamicAccessKind.Unresolved:
+        return const InvalidType();
+    }
+    return const DynamicType();
+  }
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitDynamicInvocation(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitDynamicInvocation(this, arg);
+
+  visitChildren(Visitor v) {
+    receiver?.accept(v);
+    name?.accept(v);
+    arguments?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (arguments != null) {
+      arguments = arguments.accept<TreeNode>(v);
+      arguments?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "DynamicInvocation($kind,${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver,
+        minimumPrecedence: astToText.Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeName(name);
+    printer.writeArguments(arguments);
+  }
+}
+
+/// Access kind used by [InstanceInvocation], [InstanceGet], [InstanceSet],
+/// and [InstanceTearOff].
+enum InstanceAccessKind {
+  /// An access to a member on a static receiver type which is an interface
+  /// type.
+  ///
+  /// In null safe libraries the static receiver type is non-nullable.
+  ///
+  /// For instance:
+  ///
+  ///     class C { void method() {} }
+  ///     main() => new C().method();
+  ///
+  Instance,
+
+  /// An access to a member defined on Object on a static receiver type that
+  /// is either a non-interface type or a nullable type.
+  ///
+  /// For instance:
+  ///
+  ///     test1(String? s) => s.toString();
+  ///     test1(dynamic s) => s.hashCode;
+  ///
+  Object,
+
+  /// An access to a method on a static receiver type which is an interface
+  /// type which is inapplicable, that is, whose arguments don't match the
+  /// required parameter structure.
+  ///
+  /// This is an error case which is only used on expression nested within
+  /// [InvalidExpression]s.
+  ///
+  /// For instance:
+  ///
+  ///     class C { void method() {} }
+  ///     main() => new C().method(0); // Too many arguments.
+  ///
+  Inapplicable,
+
+  /// An access to a non-Object member on a static receiver type which is a
+  /// nullable interface type.
+  ///
+  /// This is an error case which is only used on expression nested within
+  /// [InvalidExpression]s.
+  ///
+  /// For instance:
+  ///
+  ///     class C { void method() {} }
+  ///     test(C? c) => c.method(0); // 'c' is nullable.
+  ///
+  Nullable,
+}
+
+/// An invocation of an instance method with a statically known interface
+/// target.
+class InstanceInvocation extends InvocationExpression {
+  // Must match serialized bit positions.
+  static const int FlagInvariant = 1 << 0;
+  static const int FlagBoundsSafe = 1 << 1;
+
+  final InstanceAccessKind kind;
+  Expression receiver;
+  Name name;
+  Arguments arguments;
+  int flags = 0;
+
+  /// The static type of the invocation.
+  ///
+  /// This includes substituted type parameters from the static receiver type
+  /// and generic type arguments.
+  ///
+  /// For instance
+  ///
+  ///    class A<T> {
+  ///      Map<T, S> map<S>(S s) { ... }
+  ///    }
+  ///    m(A<String> a) {
+  ///      a.map(0); // The function type is `Map<String, int> Function(int)`.
+  ///    }
+  ///
+  FunctionType functionType;
+
+  Reference interfaceTargetReference;
+
+  InstanceInvocation(InstanceAccessKind kind, Expression receiver, Name name,
+      Arguments arguments, {Member interfaceTarget, FunctionType functionType})
+      : this.byReference(kind, receiver, name, arguments,
+            interfaceTargetReference: getMemberReferenceGetter(interfaceTarget),
+            functionType: functionType);
+
+  InstanceInvocation.byReference(
+      this.kind, this.receiver, this.name, this.arguments,
+      {this.interfaceTargetReference, this.functionType})
+      : assert(interfaceTargetReference != null),
+        assert(functionType != null),
+        assert(functionType.typeParameters.isEmpty) {
+    receiver?.parent = this;
+    arguments?.parent = this;
+  }
+
+  Member get interfaceTarget => interfaceTargetReference?.asMember;
+
+  void set interfaceTarget(Member target) {
+    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);
+  }
+
+  DartType getStaticTypeInternal(StaticTypeContext context) =>
+      functionType.returnType;
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitInstanceInvocation(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitInstanceInvocation(this, arg);
+
+  visitChildren(Visitor v) {
+    receiver?.accept(v);
+    interfaceTarget?.acceptReference(v);
+    name?.accept(v);
+    arguments?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (arguments != null) {
+      arguments = arguments.accept<TreeNode>(v);
+      arguments?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "InstanceInvocation($kind, ${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver,
+        minimumPrecedence: astToText.Precedence.PRIMARY);
+    printer.write('.');
+    printer.writeInterfaceMemberName(interfaceTargetReference, name);
+    printer.writeArguments(arguments);
+  }
+}
+
+/// Access kind used by [FunctionInvocation] and [FunctionTearOff].
+enum FunctionAccessKind {
+  /// An access to the 'call' method on an expression of static type `Function`.
+  ///
+  /// For instance
+  ///
+  ///     method(Function f) => f();
+  ///
+  Function,
+
+  /// An access to the 'call' method on an expression whose static type is a
+  /// function type.
+  ///
+  /// For instance
+  ///
+  ///     method(void Function() f) => f();
+  ///
+  FunctionType,
+
+  /// An access to the 'call' method on an expression whose static type is a
+  /// function type which is inapplicable, that is, whose arguments don't match
+  /// the required parameter structure.
+  ///
+  /// This is an error case which is only used on expression nested within
+  /// [InvalidExpression]s.
+  ///
+  /// For instance:
+  ///
+  ///     test(void Function() f) => f(0); // Too many arguments.
+  ///
+  Inapplicable,
+
+  /// An access to the 'call' method on an expression whose static type is a
+  /// nullable function type or `Function?`.
+  ///
+  /// This is an error case which is only used on expression nested within
+  /// [InvalidExpression]s.
+  ///
+  /// For instance:
+  ///
+  ///     test(void Function()? f) => f(); // 'f' is nullable.
+  ///
+  Nullable,
+}
+
+/// An invocation of the 'call' method on an expression whose static type is
+/// a function type or the type 'Function'.
+class FunctionInvocation extends InvocationExpression {
+  final FunctionAccessKind kind;
+
+  Expression receiver;
+
+  Arguments arguments;
+
+  /// The static type of the invocation.
+  ///
+  /// This is `null` if the static type of the receiver is not a function type
+  /// or is not bounded by a function type.
+  ///
+  /// For instance
+  ///
+  ///    m<T extends Function, S extends int Function()>(T t, S s, Function f) {
+  ///      X local<X>(X t) => t;
+  ///      t(); // The function type is `null`.
+  ///      s(); // The function type is `int Function()`.
+  ///      f(); // The function type is `null`.
+  ///      local(0); // The function type is `int Function(int)`.
+  ///    }
+  ///
+  FunctionType functionType;
+
+  FunctionInvocation(this.kind, this.receiver, this.arguments,
+      {this.functionType}) {
+    receiver?.parent = this;
+    arguments?.parent = this;
+  }
+
+  Name get name => Name.callName;
+
+  DartType getStaticTypeInternal(StaticTypeContext context) =>
+      functionType?.returnType ?? const DynamicType();
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitFunctionInvocation(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitFunctionInvocation(this, arg);
+
+  visitChildren(Visitor v) {
+    receiver?.accept(v);
+    name?.accept(v);
+    arguments?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (arguments != null) {
+      arguments = arguments.accept<TreeNode>(v);
+      arguments?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "FunctionInvocation(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(receiver,
+        minimumPrecedence: astToText.Precedence.PRIMARY);
+    printer.writeArguments(arguments);
+  }
+}
+
+/// An invocation of a local function declaration.
+class LocalFunctionInvocation extends InvocationExpression {
+  /// The variable declaration for the function declaration.
+  VariableDeclaration variable;
+  Arguments arguments;
+
+  /// The static type of the invocation.
+  ///
+  /// This might differ from the static type of [variable] for generic
+  /// functions.
+  ///
+  /// For instance
+  ///
+  ///    m() {
+  ///      T local<T>(T t) => t;
+  ///      local(0); // The static type is `int Function(int)`.
+  ///    }
+  ///
+  FunctionType functionType;
+
+  LocalFunctionInvocation(this.variable, this.arguments, {this.functionType})
+      : assert(functionType != null) {
+    arguments?.parent = this;
+  }
+
+  Name get name => Name.callName;
+
+  @override
+  DartType getStaticTypeInternal(StaticTypeContext context) =>
+      functionType.returnType;
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitLocalFunctionInvocation(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitLocalFunctionInvocation(this, arg);
+
+  visitChildren(Visitor v) {
+    arguments?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (arguments != null) {
+      arguments = arguments.accept<TreeNode>(v);
+      arguments?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "LocalFunctionInvocation(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.write(printer.getVariableName(variable));
+    printer.writeArguments(arguments);
+  }
+}
+
+/// Nullness test of an expression, that is `e == null` or `e != null`.
+///
+/// This is generated for code like `e1 == e2` and `e1 != e2` where `e1` or `e2`
+/// is `null`.
+class EqualsNull extends Expression {
+  /// The expression tested for nullness.
+  Expression expression;
+
+  /// If `true` this is an `e != null` test. Otherwise it is an `e == null`
+  /// test.
+  final bool isNot;
+
+  EqualsNull(this.expression, {this.isNot}) : assert(isNot != null) {
+    expression?.parent = this;
+  }
+
+  @override
+  DartType getStaticTypeInternal(StaticTypeContext context) =>
+      context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitEqualsNull(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitEqualsNull(this, arg);
+
+  visitChildren(Visitor v) {
+    expression?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (expression != null) {
+      expression = expression.accept<TreeNode>(v);
+      expression?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "EqualsNull(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.writeExpression(expression, minimumPrecedence: precedence);
+    if (isNot) {
+      printer.write(' != null');
+    } else {
+      printer.write(' == null');
+    }
+  }
+}
+
+/// A test of equality, that is `e1 == e2` or `e1 != e2`.
+///
+/// This is generated for code like `e1 == e2` and `e1 != e2` where neither `e1`
+/// nor `e2` is `null`.
+class EqualsCall extends Expression {
+  Expression left;
+  Expression right;
+
+  /// The static type of the invocation.
+  ///
+  /// This might differ from the static type of [Object.==] for covariant
+  /// parameters.
+  ///
+  /// For instance
+  ///
+  ///    class C<T> {
+  ///      bool operator(covariant C<T> other) { ... }
+  ///    }
+  ///    // The function type is `bool Function(C<num>)`.
+  ///    method(C<num> a, C<int> b) => a == b;
+  ///
+  FunctionType functionType;
+
+  /// If `true` this is an `e1 != e2` test. Otherwise it is an `e1 == e2` test.
+  final bool isNot;
+
+  Reference interfaceTargetReference;
+
+  EqualsCall(Expression left, Expression right,
+      {bool isNot, FunctionType functionType, Procedure interfaceTarget})
+      : this.byReference(left, right,
+            isNot: isNot,
+            functionType: functionType,
+            interfaceTargetReference:
+                getMemberReferenceGetter(interfaceTarget));
+
+  EqualsCall.byReference(this.left, this.right,
+      {this.isNot, this.functionType, this.interfaceTargetReference})
+      : assert(isNot != null) {
+    left?.parent = this;
+    right?.parent = this;
+  }
+
+  Procedure get interfaceTarget => interfaceTargetReference?.asProcedure;
+
+  void set interfaceTarget(Procedure target) {
+    interfaceTargetReference = getMemberReferenceGetter(target);
+  }
+
+  DartType getStaticTypeInternal(StaticTypeContext context) {
+    return functionType?.returnType ??
+        context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
+  }
+
+  R accept<R>(ExpressionVisitor<R> v) => v.visitEqualsCall(this);
+  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+      v.visitEqualsCall(this, arg);
+
+  visitChildren(Visitor v) {
+    left?.accept(v);
+    interfaceTarget?.acceptReference(v);
+    right?.accept(v);
+  }
+
+  transformChildren(Transformer v) {
+    if (left != null) {
+      left = left.accept<TreeNode>(v);
+      left?.parent = this;
+    }
+    if (right != null) {
+      right = right.accept<TreeNode>(v);
+      right?.parent = this;
+    }
+  }
+
+  @override
+  String toString() {
+    return "EqualsCall(${toStringInternal()})";
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    int minimumPrecedence = precedence;
+    printer.writeExpression(left, minimumPrecedence: minimumPrecedence);
+    if (isNot) {
+      printer.write(' != ');
+    } else {
+      printer.write(' == ');
+    }
+    printer.writeExpression(right, minimumPrecedence: minimumPrecedence + 1);
+  }
+}
+
 /// Expression of form `x.foo(y)`.
 class MethodInvocation extends InvocationExpression {
   // Must match serialized bit positions.
@@ -7429,6 +8393,12 @@
   void toTextInternal(AstPrinter printer) {
     printer.writeName(this);
   }
+
+  /// The name of the `call` method on a function.
+  static final Name callName = new _PublicName('call');
+
+  /// The name of the `==` operator.
+  static final Name equalsName = new _PublicName('==');
 }
 
 class _PrivateName extends Name {
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index e4676d9..e6a4456 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.ast_from_binary;
 
 import 'dart:core' hide MapEntry;
@@ -24,13 +27,19 @@
 }
 
 class InvalidKernelVersionError {
+  final String filename;
   final int version;
 
-  InvalidKernelVersionError(this.version);
+  InvalidKernelVersionError(this.filename, this.version);
 
   String toString() {
-    return 'Unexpected Kernel Format Version ${version} '
-        '(expected ${Tag.BinaryFormatVersion}).';
+    StringBuffer sb = new StringBuffer();
+    sb.write('Unexpected Kernel Format Version ${version} '
+        '(expected ${Tag.BinaryFormatVersion})');
+    if (filename != null) {
+      sb.write(' when reading $filename.');
+    }
+    return '$sb';
   }
 }
 
@@ -57,10 +66,14 @@
   final String message;
 
   CanonicalNameError(this.message);
+
+  String toString() => 'CanonicalNameError: $message';
 }
 
 class CanonicalNameSdkError extends CanonicalNameError {
   CanonicalNameSdkError(String message) : super(message);
+
+  String toString() => 'CanonicalNameSdkError: $message';
 }
 
 class _ComponentIndex {
@@ -131,8 +144,15 @@
       bool disableLazyClassReading = false,
       bool alwaysCreateNewNamedNodes})
       : _disableLazyReading = disableLazyReading,
-        _disableLazyClassReading =
-            disableLazyReading || disableLazyClassReading,
+        _disableLazyClassReading = disableLazyReading ||
+            disableLazyClassReading ||
+            // Disable lazy class reading when forcing the creation of new named
+            // nodes as it is a logical "relink" to the new version (overwriting
+            // the old one) - which doesn't play well with lazy loading class
+            // content as old loaded references will then potentially still
+            // point to the old content until the new class has been lazy
+            // loaded.
+            (alwaysCreateNewNamedNodes == true),
         this.alwaysCreateNewNamedNodes = alwaysCreateNewNamedNodes ?? false;
 
   fail(String message) {
@@ -529,7 +549,7 @@
       }
       int version = readUint32();
       if (version != Tag.BinaryFormatVersion) {
-        throw InvalidKernelVersionError(version);
+        throw InvalidKernelVersionError(filename, version);
       }
 
       _readAndVerifySdkHash();
@@ -563,6 +583,8 @@
   }
 
   /// Deserializes the source and stores it in [component].
+  /// Note that the _coverage_ normally included in the source in the
+  /// uri-to-source mapping is _not_ included.
   ///
   /// The input bytes may contain multiple files concatenated.
   void readComponentSource(Component component) {
@@ -623,11 +645,10 @@
           bool checkReferenceNode = true;
           if (child.reference == null) {
             // OK for "if private: URI of library" part of "Qualified name"...
-            Iterable<CanonicalName> children = child.childrenOrNull;
-            if (parent.parent != null &&
-                children != null &&
-                children.isNotEmpty &&
-                children.first.name.startsWith("_")) {
+            // TODO(johnniwinther): This wrongfully skips checking of variable
+            // synthesized by the VM transformations. The kind of canonical
+            // name types maybe should be directly available.
+            if (parent.parent != null && child.name.contains(':')) {
               // OK then.
               checkReferenceNode = false;
             } else {
@@ -715,7 +736,7 @@
 
     final int formatVersion = readUint32();
     if (formatVersion != Tag.BinaryFormatVersion) {
-      throw InvalidKernelVersionError(formatVersion);
+      throw InvalidKernelVersionError(filename, formatVersion);
     }
 
     _readAndVerifySdkHash();
@@ -724,7 +745,7 @@
     _ComponentIndex index = _readComponentIndex(componentFileSize);
 
     _byteOffset = index.binaryOffsetForSourceTable;
-    Map<Uri, Source> uriToSource = readUriToSource();
+    Map<Uri, Source> uriToSource = readUriToSource(/* readCoverage = */ false);
     _mergeUriToSource(component.uriToSource, uriToSource);
 
     _byteOffset = _componentStartOffset + componentFileSize;
@@ -741,7 +762,7 @@
 
     final int formatVersion = readUint32();
     if (formatVersion != Tag.BinaryFormatVersion) {
-      throw InvalidKernelVersionError(formatVersion);
+      throw InvalidKernelVersionError(filename, formatVersion);
     }
 
     _readAndVerifySdkHash();
@@ -773,7 +794,7 @@
     _associateMetadata(component, _componentStartOffset);
 
     _byteOffset = index.binaryOffsetForSourceTable;
-    Map<Uri, Source> uriToSource = readUriToSource();
+    Map<Uri, Source> uriToSource = readUriToSource(/* readCoverage = */ true);
     _mergeUriToSource(component.uriToSource, uriToSource);
 
     _byteOffset = index.binaryOffsetForConstantTable;
@@ -821,7 +842,14 @@
     return strings;
   }
 
-  Map<Uri, Source> readUriToSource() {
+  /// Read the uri-to-source part of the binary.
+  /// Note that this can include coverage, but that it is only included if
+  /// [readCoverage] is true, otherwise coverage will be skipped. Note also that
+  /// if [readCoverage] is true, references are read and that the link table
+  /// thus has to be read first.
+  Map<Uri, Source> readUriToSource(bool readCoverage) {
+    assert(!readCoverage || (readCoverage && _linkTable != null));
+
     int length = readUint32();
 
     // Read data.
@@ -847,10 +875,16 @@
       Set<Reference> coverageConstructors;
       {
         int constructorCoverageCount = readUInt30();
-        coverageConstructors =
-            constructorCoverageCount == 0 ? null : new Set<Reference>();
-        for (int j = 0; j < constructorCoverageCount; ++j) {
-          coverageConstructors.add(readMemberReference());
+        if (readCoverage) {
+          coverageConstructors =
+              constructorCoverageCount == 0 ? null : new Set<Reference>();
+          for (int j = 0; j < constructorCoverageCount; ++j) {
+            coverageConstructors.add(readMemberReference());
+          }
+        } else {
+          for (int j = 0; j < constructorCoverageCount; ++j) {
+            skipMemberReference();
+          }
         }
       }
 
@@ -906,6 +940,10 @@
     }
   }
 
+  void skipCanonicalNameReference() {
+    readUInt30();
+  }
+
   CanonicalName readCanonicalNameReference() {
     int index = readUInt30();
     if (index == 0) return null;
@@ -937,6 +975,10 @@
     return name?.getReference();
   }
 
+  void skipMemberReference() {
+    skipCanonicalNameReference();
+  }
+
   Reference readMemberReference({bool allowNull: false}) {
     CanonicalName name = readCanonicalNameReference();
     if (name == null && !allowNull) {
@@ -1329,14 +1371,18 @@
     CanonicalName getterCanonicalName = readCanonicalNameReference();
     Reference getterReference = getterCanonicalName.getReference();
     CanonicalName setterCanonicalName = readCanonicalNameReference();
-    Reference setterReference = setterCanonicalName.getReference();
+    Reference setterReference = setterCanonicalName?.getReference();
     Field node = getterReference.node;
     if (alwaysCreateNewNamedNodes) {
       node = null;
     }
     if (node == null) {
-      node = new Field(null,
-          getterReference: getterReference, setterReference: setterReference);
+      if (setterReference != null) {
+        node = new Field.mutable(null,
+            getterReference: getterReference, setterReference: setterReference);
+      } else {
+        node = new Field.immutable(null, getterReference: getterReference);
+      }
     }
     Uri fileUri = readUriReference();
     int fileOffset = readOffset();
@@ -1458,7 +1504,7 @@
     node.stubKind = stubKind;
     node.stubTargetReference = stubTargetReference;
 
-    assert((node.stubKind == ProcedureStubKind.ForwardingSuperStub &&
+    assert((node.stubKind == ProcedureStubKind.ConcreteForwardingStub &&
             node.stubTargetReference != null) ||
         !(node.isForwardingStub && node.function.body != null));
     assert(!(node.isMemberSignature && node.stubTargetReference == null),
@@ -1649,7 +1695,8 @@
   VariableDeclaration readVariableReference() {
     int index = readUInt30();
     if (index >= variableStack.length) {
-      throw fail('unexpected variable index: $index');
+      throw fail('Unexpected variable index: $index. '
+          'Current variable count: ${variableStack.length}.');
     }
     return variableStack[index];
   }
@@ -1719,11 +1766,44 @@
         return new PropertyGet.byReference(readExpression(), readName(),
             readInstanceMemberReference(allowNull: true))
           ..fileOffset = offset;
+      case Tag.InstanceGet:
+        InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
+        int offset = readOffset();
+        return new InstanceGet.byReference(kind, readExpression(), readName(),
+            resultType: readDartType(),
+            interfaceTargetReference: readInstanceMemberReference())
+          ..fileOffset = offset;
+      case Tag.InstanceTearOff:
+        InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
+        int offset = readOffset();
+        return new InstanceTearOff.byReference(
+            kind, readExpression(), readName(),
+            resultType: readDartType(),
+            interfaceTargetReference: readInstanceMemberReference())
+          ..fileOffset = offset;
+      case Tag.DynamicGet:
+        DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
+        int offset = readOffset();
+        return new DynamicGet(kind, readExpression(), readName())
+          ..fileOffset = offset;
       case Tag.PropertySet:
         int offset = readOffset();
         return new PropertySet.byReference(readExpression(), readName(),
             readExpression(), readInstanceMemberReference(allowNull: true))
           ..fileOffset = offset;
+      case Tag.InstanceSet:
+        InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
+        int offset = readOffset();
+        return new InstanceSet.byReference(
+            kind, readExpression(), readName(), readExpression(),
+            interfaceTargetReference: readInstanceMemberReference())
+          ..fileOffset = offset;
+      case Tag.DynamicSet:
+        DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
+        int offset = readOffset();
+        return new DynamicSet(
+            kind, readExpression(), readName(), readExpression())
+          ..fileOffset = offset;
       case Tag.SuperPropertyGet:
         int offset = readOffset();
         addTransformerFlag(TransformerFlag.superCalls);
@@ -1740,6 +1820,10 @@
         int offset = readOffset();
         return new StaticGet.byReference(readMemberReference())
           ..fileOffset = offset;
+      case Tag.StaticTearOff:
+        int offset = readOffset();
+        return new StaticTearOff.byReference(readMemberReference())
+          ..fileOffset = offset;
       case Tag.StaticSet:
         int offset = readOffset();
         return new StaticSet.byReference(
@@ -1752,6 +1836,55 @@
             readArguments(), readInstanceMemberReference(allowNull: true))
           ..fileOffset = offset
           ..flags = flags;
+      case Tag.InstanceInvocation:
+        InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
+        int flags = readByte();
+        int offset = readOffset();
+        return new InstanceInvocation.byReference(
+            kind, readExpression(), readName(), readArguments(),
+            functionType: readDartType(),
+            interfaceTargetReference: readInstanceMemberReference())
+          ..fileOffset = offset
+          ..flags = flags;
+      case Tag.DynamicInvocation:
+        DynamicAccessKind kind = DynamicAccessKind.values[readByte()];
+        int offset = readOffset();
+        return new DynamicInvocation(
+            kind, readExpression(), readName(), readArguments())
+          ..fileOffset = offset;
+      case Tag.FunctionInvocation:
+        FunctionAccessKind kind = FunctionAccessKind.values[readByte()];
+        int offset = readOffset();
+        Expression receiver = readExpression();
+        Arguments arguments = readArguments();
+        DartType functionType = readDartType();
+        // `const DynamicType()` is used to encode a missing function type.
+        assert(functionType is FunctionType || functionType is DynamicType,
+            "Unexpected function type $functionType for FunctionInvocation");
+        return new FunctionInvocation(kind, receiver, arguments,
+            functionType: functionType is FunctionType ? functionType : null)
+          ..fileOffset = offset;
+      case Tag.FunctionTearOff:
+        int offset = readOffset();
+        return new FunctionTearOff(readExpression())..fileOffset = offset;
+      case Tag.LocalFunctionInvocation:
+        int offset = readOffset();
+        readUInt30(); // offset of the variable declaration in the binary.
+        return new LocalFunctionInvocation(
+            readVariableReference(), readArguments(),
+            functionType: readDartType())
+          ..fileOffset = offset;
+      case Tag.EqualsNull:
+        int offset = readOffset();
+        return new EqualsNull(readExpression(), isNot: readByte() == 1)
+          ..fileOffset = offset;
+      case Tag.EqualsCall:
+        int offset = readOffset();
+        return new EqualsCall.byReference(readExpression(), readExpression(),
+            isNot: readByte() == 1,
+            functionType: readDartType(),
+            interfaceTargetReference: readInstanceMemberReference())
+          ..fileOffset = offset;
       case Tag.SuperMethodInvocation:
         int offset = readOffset();
         addTransformerFlag(TransformerFlag.superCalls);
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index ca92ca9..d706a36 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.ast_to_binary;
 
 import 'dart:core' hide MapEntry;
@@ -80,6 +83,13 @@
     _sink.flushAndDestroy();
   }
 
+  int _getVariableIndex(VariableDeclaration variable) {
+    _variableIndexer ??= new VariableIndexer();
+    int index = _variableIndexer[variable];
+    assert(index != null, "No index found for ${variable}");
+    return index;
+  }
+
   void writeByte(int byte) {
     assert((byte & 0xFF) == byte);
     _sink.addByte(byte);
@@ -1207,13 +1217,12 @@
     assert(!(node.isMemberSignature && node.stubTargetReference == null),
         "No member signature origin for member signature $node.");
     assert(
-        !(node.forwardingStubInterfaceTarget is Procedure &&
-            (node.forwardingStubInterfaceTarget as Procedure)
-                .isMemberSignature),
+        !(node.abstractForwardingStubTarget is Procedure &&
+            (node.abstractForwardingStubTarget as Procedure).isMemberSignature),
         "Forwarding stub interface target is member signature: $node.");
     assert(
-        !(node.forwardingStubSuperTarget is Procedure &&
-            (node.forwardingStubSuperTarget as Procedure).isMemberSignature),
+        !(node.concreteForwardingStubTarget is Procedure &&
+            (node.concreteForwardingStubTarget as Procedure).isMemberSignature),
         "Forwarding stub super target is member signature: $node.");
 
     procedureOffsets.add(getBufferOffset());
@@ -1246,20 +1255,27 @@
 
     _currentlyInNonimplementation = currentlyInNonimplementationSaved;
     assert(
-        (node.forwardingStubSuperTarget != null) ||
+        (node.concreteForwardingStubTarget != null) ||
             !(node.isForwardingStub && node.function.body != null),
         "Invalid forwarding stub $node.");
   }
 
   @override
   void visitField(Field node) {
-    if (node.getterCanonicalName == null || node.setterCanonicalName == null) {
+    if (node.getterCanonicalName == null) {
+      throw new ArgumentError('Missing canonical name for $node');
+    }
+    if (node.hasSetter && node.setterCanonicalName == null) {
       throw new ArgumentError('Missing canonical name for $node');
     }
     enterScope(memberScope: true);
     writeByte(Tag.Field);
     writeNonNullCanonicalNameReference(getCanonicalNameOfMemberGetter(node));
-    writeNonNullCanonicalNameReference(getCanonicalNameOfMemberSetter(node));
+    if (node.hasSetter) {
+      writeNonNullCanonicalNameReference(getCanonicalNameOfMemberSetter(node));
+    } else {
+      writeNullAllowedReference(null);
+    }
     writeUriReference(node.fileUri);
     writeOffset(node.fileOffset);
     writeOffset(node.fileEndOffset);
@@ -1383,9 +1399,7 @@
 
   @override
   void visitVariableGet(VariableGet node) {
-    _variableIndexer ??= new VariableIndexer();
-    int index = _variableIndexer[node.variable];
-    assert(index != null, "No index found for ${node.variable}");
+    int index = _getVariableIndex(node.variable);
     if (index & Tag.SpecializedPayloadMask == index &&
         node.promotedType == null) {
       writeByte(Tag.SpecializedVariableGet + index);
@@ -1402,9 +1416,7 @@
 
   @override
   void visitVariableSet(VariableSet node) {
-    _variableIndexer ??= new VariableIndexer();
-    int index = _variableIndexer[node.variable];
-    assert(index != null, "No index found for ${node.variable}");
+    int index = _getVariableIndex(node.variable);
     if (index & Tag.SpecializedPayloadMask == index) {
       writeByte(Tag.SpecializedVariableSet + index);
       writeOffset(node.fileOffset);
@@ -1420,6 +1432,37 @@
   }
 
   @override
+  void visitDynamicGet(DynamicGet node) {
+    writeByte(Tag.DynamicGet);
+    writeByte(node.kind.index);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+    writeName(node.name);
+  }
+
+  @override
+  void visitInstanceGet(InstanceGet node) {
+    writeByte(Tag.InstanceGet);
+    writeByte(node.kind.index);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+    writeName(node.name);
+    writeDartType(node.resultType);
+    writeNonNullInstanceMemberReference(node.interfaceTargetReference);
+  }
+
+  @override
+  void visitInstanceTearOff(InstanceTearOff node) {
+    writeByte(Tag.InstanceTearOff);
+    writeByte(node.kind.index);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+    writeName(node.name);
+    writeDartType(node.resultType);
+    writeNonNullInstanceMemberReference(node.interfaceTargetReference);
+  }
+
+  @override
   void visitPropertyGet(PropertyGet node) {
     writeByte(Tag.PropertyGet);
     writeOffset(node.fileOffset);
@@ -1429,6 +1472,27 @@
   }
 
   @override
+  void visitDynamicSet(DynamicSet node) {
+    writeByte(Tag.DynamicSet);
+    writeByte(node.kind.index);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+    writeName(node.name);
+    writeNode(node.value);
+  }
+
+  @override
+  void visitInstanceSet(InstanceSet node) {
+    writeByte(Tag.InstanceSet);
+    writeByte(node.kind.index);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+    writeName(node.name);
+    writeNode(node.value);
+    writeNonNullInstanceMemberReference(node.interfaceTargetReference);
+  }
+
+  @override
   void visitPropertySet(PropertySet node) {
     writeByte(Tag.PropertySet);
     writeOffset(node.fileOffset);
@@ -1463,6 +1527,13 @@
   }
 
   @override
+  void visitStaticTearOff(StaticTearOff node) {
+    writeByte(Tag.StaticTearOff);
+    writeOffset(node.fileOffset);
+    writeNonNullReference(node.targetReference);
+  }
+
+  @override
   void visitStaticSet(StaticSet node) {
     writeByte(Tag.StaticSet);
     writeOffset(node.fileOffset);
@@ -1471,6 +1542,70 @@
   }
 
   @override
+  void visitDynamicInvocation(DynamicInvocation node) {
+    writeByte(Tag.DynamicInvocation);
+    writeByte(node.kind.index);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+    writeName(node.name);
+    writeArgumentsNode(node.arguments);
+  }
+
+  @override
+  void visitEqualsCall(EqualsCall node) {
+    writeByte(Tag.EqualsCall);
+    writeOffset(node.fileOffset);
+    writeNode(node.left);
+    writeNode(node.right);
+    writeByte(node.isNot ? 1 : 0);
+    writeDartType(node.functionType);
+    writeNonNullInstanceMemberReference(node.interfaceTargetReference);
+  }
+
+  @override
+  void visitEqualsNull(EqualsNull node) {
+    writeByte(Tag.EqualsNull);
+    writeOffset(node.fileOffset);
+    writeNode(node.expression);
+    writeByte(node.isNot ? 1 : 0);
+  }
+
+  @override
+  void visitFunctionInvocation(FunctionInvocation node) {
+    writeByte(Tag.FunctionInvocation);
+    writeByte(node.kind.index);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+    writeArgumentsNode(node.arguments);
+    // `const DynamicType()` is used to encode a missing function type.
+    writeDartType(node.functionType ?? const DynamicType());
+  }
+
+  @override
+  void visitInstanceInvocation(InstanceInvocation node) {
+    writeByte(Tag.InstanceInvocation);
+    writeByte(node.kind.index);
+    writeByte(node.flags);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+    writeName(node.name);
+    writeArgumentsNode(node.arguments);
+    writeDartType(node.functionType);
+    writeNonNullInstanceMemberReference(node.interfaceTargetReference);
+  }
+
+  @override
+  void visitLocalFunctionInvocation(LocalFunctionInvocation node) {
+    writeByte(Tag.LocalFunctionInvocation);
+    writeOffset(node.fileOffset);
+    int index = _getVariableIndex(node.variable);
+    writeUInt30(node.variable.binaryOffsetNoTag);
+    writeUInt30(index);
+    writeArgumentsNode(node.arguments);
+    writeDartType(node.functionType);
+  }
+
+  @override
   void visitMethodInvocation(MethodInvocation node) {
     writeByte(Tag.MethodInvocation);
     writeByte(node.flags);
@@ -2238,6 +2373,13 @@
     }
   }
 
+  @override
+  void visitFunctionTearOff(FunctionTearOff node) {
+    writeByte(Tag.FunctionTearOff);
+    writeOffset(node.fileOffset);
+    writeNode(node.receiver);
+  }
+
   // ================================================================
   // These are nodes that are never serialized directly.  Reaching one
   // during serialization is an error.
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 5fa202a..410617c 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -1,6 +1,7 @@
 // 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 kernel.binary.tag;
 
 class Tag {
@@ -29,6 +30,9 @@
   // Expressions
   static const int CheckLibraryIsLoaded = 13;
   static const int LoadLibrary = 14;
+  static const int EqualsNull = 15;
+  static const int EqualsCall = 16;
+  static const int StaticTearOff = 17;
   static const int ConstStaticInvocation = 18;
   static const int InvalidExpression = 19;
   static const int VariableGet = 20;
@@ -45,14 +49,9 @@
   static const int ConstructorInvocation = 31;
   static const int ConstConstructorInvocation = 32;
   static const int Not = 33;
-  static const int NullCheck = 117;
   static const int LogicalExpression = 34;
   static const int ConditionalExpression = 35;
   static const int StringConcatenation = 36;
-  static const int ListConcatenation = 111;
-  static const int SetConcatenation = 112;
-  static const int MapConcatenation = 113;
-  static const int InstanceCreation = 114;
   static const int IsExpression = 37;
   static const int AsExpression = 38;
   static const int StringLiteral = 39;
@@ -77,10 +76,28 @@
   static const int BigIntLiteral = 57;
   static const int ConstListLiteral = 58;
   static const int ConstMapLiteral = 59;
+
   static const int SetLiteral = 109;
   static const int ConstSetLiteral = 110;
+  static const int ListConcatenation = 111;
+  static const int SetConcatenation = 112;
+  static const int MapConcatenation = 113;
+  static const int InstanceCreation = 114;
   static const int FileUriExpression = 116;
 
+  /// 115 is occupied by [Extension].
+  static const int NullCheck = 117;
+  static const int InstanceGet = 118;
+  static const int InstanceSet = 119;
+  static const int InstanceInvocation = 120;
+  static const int InstanceTearOff = 121;
+  static const int DynamicGet = 122;
+  static const int DynamicSet = 123;
+  static const int DynamicInvocation = 124;
+  static const int FunctionInvocation = 125;
+  static const int FunctionTearOff = 126;
+  static const int LocalFunctionInvocation = 127;
+
   // Statements
   static const int ExpressionStatement = 61;
   static const int Block = 62;
@@ -130,6 +147,16 @@
   /// 115 is occupied by [Extension].
   /// 116 is occupied by [FileUriExpression] (expression).
   /// 117 is occupied by [NullCheck] (expression).
+  /// 118 is occupied by [InstanceGet] (expression).
+  /// 119 is occupied by [InstanceSet] (expression).
+  /// 120 is occupied by [InstanceInvocation] (expression).
+  /// 121 is occupied by [InstanceTearOff] (expression).
+  /// 122 is occupied by [DynamicGet] (expression).
+  /// 123 is occupied by [DynamicSet] (expression).
+  /// 124 is occupied by [DynamicInvocation] (expression).
+  /// 125 is occupied by [FunctionInvocation] (expression).
+  /// 126 is occupied by [FunctionTearOff] (expression).
+  /// 127 is occupied by [LocalFunctionInvocation] (expression).
 
   static const int SpecializedTagHighBit = 0x80; // 10000000
   static const int SpecializedTagMask = 0xF8; // 11111000
@@ -146,7 +173,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 = 52;
+  static const int BinaryFormatVersion = 54;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 6a1a469..70f3004 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.canonical_name;
 
 import 'ast.dart';
@@ -183,10 +186,18 @@
   }
 
   void removeChild(String name) {
-    _children?.remove(name);
+    if (_children != null) {
+      _children.remove(name);
+      if (_children.isEmpty) {
+        _children = null;
+      }
+    }
   }
 
   void bindTo(Reference target) {
+    if (target == null) {
+      throw '$this cannot be bound to null';
+    }
     if (reference == target) return;
     if (reference != null) {
       throw '$this is already bound';
@@ -200,6 +211,16 @@
   }
 
   void unbind() {
+    _unbindInternal();
+    // TODO(johnniwinther): To support replacement of fields with getters and
+    // setters (and the reverse) we need to remove canonical names from the
+    // canonical name tree. We need to establish better invariants about the
+    // state of the canonical name tree, since for instance [unbindAll] doesn't
+    // remove unneeded leaf nodes.
+    _parent.removeChild(name);
+  }
+
+  void _unbindInternal() {
     if (reference == null) return;
     assert(reference.canonicalName == this);
     if (reference.node is Class) {
@@ -213,7 +234,7 @@
   }
 
   void unbindAll() {
-    unbind();
+    _unbindInternal();
     Iterable<CanonicalName> children_ = childrenOrNull;
     if (children_ != null) {
       for (CanonicalName child in children_) {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index dbe15bd..26ef345 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.class_hierarchy;
 
 import 'dart:collection';
@@ -1200,47 +1203,51 @@
         setters ? info.lazyDeclaredSetters : info.lazyDeclaredGettersAndCalls;
     if (members != null) return members;
 
+    // To support that mixin application can declare their own members, for
+    // instance cloned mixin members and concrete forwarding stubs, we first
+    // collect the members in a map before creating the list of members, so that
+    // declared members can replace mixed in members.
+    Map<Name, Member> memberMap = {};
     if (classNode.mixedInType != null) {
       Class mixedInClassNode = classNode.mixedInType.classNode;
       _ClassInfo mixedInInfo = _infoMap[mixedInClassNode];
 
-      members = <Member>[];
       for (Member mixinMember in _buildDeclaredMembers(
           mixedInClassNode, mixedInInfo,
           setters: setters)) {
         if (mixinMember is! Procedure ||
             (mixinMember is Procedure &&
                 !mixinMember.isNoSuchMethodForwarder)) {
-          members.add(mixinMember);
+          memberMap[mixinMember.name] = mixinMember;
         }
       }
-    } else {
-      members = <Member>[];
-      for (Procedure procedure in classNode.procedures) {
-        if (procedure.isStatic) continue;
-        if (procedure.kind == ProcedureKind.Setter) {
-          if (setters) {
-            members.add(procedure);
-          }
-        } else {
-          if (!setters) {
-            members.add(procedure);
-          }
-        }
-      }
-      for (Field field in classNode.fields) {
-        if (field.isStatic) continue;
-        if (!setters && field.hasImplicitGetter) {
-          members.add(field);
-        }
-        if (setters && field.hasImplicitSetter) {
-          members.add(field);
-        }
-      }
-
-      members.sort(ClassHierarchy.compareMembers);
     }
 
+    for (Procedure procedure in classNode.procedures) {
+      if (procedure.isStatic) continue;
+      if (procedure.kind == ProcedureKind.Setter) {
+        if (setters) {
+          memberMap[procedure.name] = procedure;
+        }
+      } else {
+        if (!setters) {
+          memberMap[procedure.name] = procedure;
+        }
+      }
+    }
+    for (Field field in classNode.fields) {
+      if (field.isStatic) continue;
+      if (!setters) {
+        memberMap[field.name] = field;
+      }
+      if (setters && field.hasSetter) {
+        memberMap[field.name] = field;
+      }
+    }
+
+    members = memberMap.values.toList();
+    members.sort(ClassHierarchy.compareMembers);
+
     if (setters) {
       info.lazyDeclaredSetters = members;
     } else {
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 3371d54..83a94a1 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.clone;
 
 import 'dart:core' hide MapEntry;
@@ -615,6 +618,91 @@
   visitTypedef(Typedef node) {
     return defaultTreeNode(node);
   }
+
+  @override
+  TreeNode visitDynamicGet(DynamicGet node) {
+    return new DynamicGet(node.kind, clone(node.receiver), node.name);
+  }
+
+  @override
+  TreeNode visitDynamicInvocation(DynamicInvocation node) {
+    return new DynamicInvocation(
+        node.kind, clone(node.receiver), node.name, clone(node.arguments));
+  }
+
+  @override
+  TreeNode visitDynamicSet(DynamicSet node) {
+    return new DynamicSet(
+        node.kind, clone(node.receiver), node.name, clone(node.value));
+  }
+
+  @override
+  TreeNode visitEqualsCall(EqualsCall node) {
+    return new EqualsCall.byReference(clone(node.left), clone(node.right),
+        isNot: node.isNot,
+        functionType: visitOptionalType(node.functionType),
+        interfaceTargetReference: node.interfaceTargetReference);
+  }
+
+  @override
+  TreeNode visitEqualsNull(EqualsNull node) {
+    return new EqualsNull(clone(node.expression), isNot: node.isNot);
+  }
+
+  @override
+  TreeNode visitFunctionInvocation(FunctionInvocation node) {
+    return new FunctionInvocation(
+        node.kind, clone(node.receiver), clone(node.arguments),
+        functionType: visitOptionalType(node.functionType));
+  }
+
+  @override
+  TreeNode visitInstanceGet(InstanceGet node) {
+    return new InstanceGet.byReference(
+        node.kind, clone(node.receiver), node.name,
+        resultType: visitOptionalType(node.resultType),
+        interfaceTargetReference: node.interfaceTargetReference);
+  }
+
+  @override
+  TreeNode visitInstanceInvocation(InstanceInvocation node) {
+    return new InstanceInvocation.byReference(
+        node.kind, clone(node.receiver), node.name, clone(node.arguments),
+        functionType: visitOptionalType(node.functionType),
+        interfaceTargetReference: node.interfaceTargetReference);
+  }
+
+  @override
+  TreeNode visitInstanceSet(InstanceSet node) {
+    return new InstanceSet.byReference(
+        node.kind, clone(node.receiver), node.name, clone(node.value),
+        interfaceTargetReference: node.interfaceTargetReference);
+  }
+
+  @override
+  TreeNode visitInstanceTearOff(InstanceTearOff node) {
+    return new InstanceTearOff.byReference(
+        node.kind, clone(node.receiver), node.name,
+        resultType: visitOptionalType(node.resultType),
+        interfaceTargetReference: node.interfaceTargetReference);
+  }
+
+  @override
+  TreeNode visitLocalFunctionInvocation(LocalFunctionInvocation node) {
+    return new LocalFunctionInvocation(
+        variables[node.variable], clone(node.arguments),
+        functionType: visitOptionalType(node.functionType));
+  }
+
+  @override
+  TreeNode visitStaticTearOff(StaticTearOff node) {
+    return new StaticTearOff.byReference(node.targetReference);
+  }
+
+  @override
+  TreeNode visitFunctionTearOff(FunctionTearOff node) {
+    return new FunctionTearOff(clone(node.receiver));
+  }
 }
 
 /// Visitor that return a clone of a tree, maintaining references to cloned
@@ -662,12 +750,12 @@
     return result;
   }
 
-  Procedure cloneProcedure(Procedure node, Procedure referenceFrom) {
+  Procedure cloneProcedure(Procedure node, Reference reference) {
     final Uri activeFileUriSaved = _activeFileUri;
     _activeFileUri = node.fileUri ?? _activeFileUri;
     Procedure result = new Procedure(
         node.name, node.kind, super.clone(node.function),
-        reference: referenceFrom?.reference,
+        reference: reference,
         transformerFlags: node.transformerFlags,
         fileUri: _activeFileUri,
         stubKind: node.stubKind,
@@ -684,24 +772,33 @@
     return result;
   }
 
-  Field cloneField(Field node, Field referenceFrom) {
+  Field cloneField(
+      Field node, Reference getterReference, Reference setterReference) {
     final Uri activeFileUriSaved = _activeFileUri;
     _activeFileUri = node.fileUri ?? _activeFileUri;
 
-    Field result = new Field(node.name,
-        type: visitType(node.type),
-        initializer: cloneOptional(node.initializer),
-        isCovariant: node.isCovariant,
-        isFinal: node.isFinal,
-        isConst: node.isConst,
-        isStatic: node.isStatic,
-        isLate: node.isLate,
-        hasImplicitGetter: node.hasImplicitGetter,
-        hasImplicitSetter: node.hasImplicitSetter,
-        transformerFlags: node.transformerFlags,
-        fileUri: _activeFileUri,
-        getterReference: referenceFrom?.getterReference,
-        setterReference: referenceFrom?.setterReference)
+    Field result;
+    if (node.hasSetter) {
+      result = new Field.mutable(node.name,
+          type: visitType(node.type),
+          initializer: cloneOptional(node.initializer),
+          transformerFlags: node.transformerFlags,
+          fileUri: _activeFileUri,
+          getterReference: getterReference,
+          setterReference: setterReference);
+    } else {
+      assert(
+          setterReference == null,
+          "Cannot use setter reference $setterReference "
+          "for clone of an immutable field.");
+      result = new Field.immutable(node.name,
+          type: visitType(node.type),
+          initializer: cloneOptional(node.initializer),
+          transformerFlags: node.transformerFlags,
+          fileUri: _activeFileUri,
+          getterReference: getterReference);
+    }
+    result
       ..annotations = cloneAnnotations && !node.annotations.isEmpty
           ? node.annotations.map(super.clone).toList()
           : const <Expression>[]
@@ -743,6 +840,93 @@
   }
 }
 
+/// Cloner that resolves super calls in mixin declarations.
+class MixinApplicationCloner extends CloneVisitorWithMembers {
+  final Class mixinApplicationClass;
+  Map<Name, Member> _getterMap;
+  Map<Name, Member> _setterMap;
+
+  MixinApplicationCloner(this.mixinApplicationClass,
+      {Map<TypeParameter, DartType> typeSubstitution,
+      Map<TypeParameter, TypeParameter> typeParams,
+      bool cloneAnnotations = true})
+      : super(
+            typeSubstitution: typeSubstitution,
+            typeParams: typeParams,
+            cloneAnnotations: cloneAnnotations);
+
+  Member _findSuperMember(Name name, {bool isSetter}) {
+    assert(isSetter != null);
+    Map<Name, Member> cache;
+    if (isSetter) {
+      cache = _setterMap ??= {};
+    } else {
+      cache = _getterMap ??= {};
+    }
+    Member member = cache[name];
+    if (member != null) {
+      return member;
+    }
+    Class superClass = mixinApplicationClass.superclass;
+    while (superClass != null) {
+      for (Procedure procedure in superClass.procedures) {
+        if (procedure.name == name) {
+          if (isSetter) {
+            if (procedure.kind == ProcedureKind.Setter &&
+                !procedure.isAbstract) {
+              return cache[name] = procedure;
+            }
+          } else {
+            if (procedure.kind != ProcedureKind.Setter &&
+                !procedure.isAbstract) {
+              return cache[name] = procedure;
+            }
+          }
+        }
+      }
+      for (Field field in superClass.fields) {
+        if (field.name == name) {
+          if (isSetter) {
+            if (field.hasSetter) {
+              return cache[name] = field;
+            }
+          } else {
+            return cache[name] = field;
+          }
+        }
+      }
+
+      superClass = superClass.superclass;
+    }
+    // TODO(johnniwinther): Throw instead when the CFE reports missing concrete
+    // super members.
+    // throw new StateError(
+    //     'No super member found for $name in $mixinApplicationClass');
+    return null;
+  }
+
+  @override
+  SuperMethodInvocation visitSuperMethodInvocation(SuperMethodInvocation node) {
+    SuperMethodInvocation cloned = super.visitSuperMethodInvocation(node);
+    cloned.interfaceTarget = _findSuperMember(node.name, isSetter: false);
+    return cloned;
+  }
+
+  @override
+  SuperPropertyGet visitSuperPropertyGet(SuperPropertyGet node) {
+    SuperPropertyGet cloned = super.visitSuperPropertyGet(node);
+    cloned.interfaceTarget = _findSuperMember(node.name, isSetter: false);
+    return cloned;
+  }
+
+  @override
+  SuperPropertySet visitSuperPropertySet(SuperPropertySet node) {
+    SuperPropertySet cloned = super.visitSuperPropertySet(node);
+    cloned.interfaceTarget = _findSuperMember(node.name, isSetter: true);
+    return cloned;
+  }
+}
+
 class CloneProcedureWithoutBody extends CloneVisitorWithMembers {
   CloneProcedureWithoutBody(
       {Map<TypeParameter, DartType> typeSubstitution,
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index e7c5646..7c9a566 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.core_types;
 
 import 'package:kernel/type_algebra.dart';
diff --git a/pkg/kernel/lib/default_language_version.dart b/pkg/kernel/lib/default_language_version.dart
index 465988e..8dbbe5b 100644
--- a/pkg/kernel/lib/default_language_version.dart
+++ b/pkg/kernel/lib/default_language_version.dart
@@ -1,7 +1,9 @@
-// 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.
 
+// @dart = 2.9
+
 // NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
 //
 // Instead modify 'tools/experimental_features.yaml' and run
diff --git a/pkg/kernel/lib/error_formatter.dart b/pkg/kernel/lib/error_formatter.dart
index 42265e7..aab719e 100644
--- a/pkg/kernel/lib/error_formatter.dart
+++ b/pkg/kernel/lib/error_formatter.dart
@@ -3,6 +3,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.9
+
 import 'package:kernel/kernel.dart';
 import 'package:kernel/naive_type_checker.dart';
 import 'package:kernel/text/ast_to_text.dart';
diff --git a/pkg/kernel/lib/external_name.dart b/pkg/kernel/lib/external_name.dart
index 157981d..2531780 100644
--- a/pkg/kernel/lib/external_name.dart
+++ b/pkg/kernel/lib/external_name.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.9
+
 library kernel.external_name;
 
 import 'ast.dart';
diff --git a/pkg/kernel/lib/import_table.dart b/pkg/kernel/lib/import_table.dart
index c85e9f3..c7662b4 100644
--- a/pkg/kernel/lib/import_table.dart
+++ b/pkg/kernel/lib/import_table.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.import_table;
 
 import 'ast.dart';
diff --git a/pkg/kernel/lib/kernel.dart b/pkg/kernel/lib/kernel.dart
index f30a6cd..cae6df9 100644
--- a/pkg/kernel/lib/kernel.dart
+++ b/pkg/kernel/lib/kernel.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.9
+
 /// Conventions for paths:
 ///
 /// - Use the [Uri] class for paths that may have the `file`, `dart` or
@@ -60,6 +62,12 @@
   return future;
 }
 
+List<int> writeComponentToBytes(Component component) {
+  BytesSink sink = new BytesSink();
+  new BinaryPrinter(sink).writeComponentFile(component);
+  return sink.builder.toBytes();
+}
+
 void writeLibraryToText(Library library, {String path}) {
   StringBuffer buffer = new StringBuffer();
   new Printer(buffer).writeLibraryFile(library);
diff --git a/pkg/kernel/lib/library_index.dart b/pkg/kernel/lib/library_index.dart
index d8e36e7..f45aaa5 100644
--- a/pkg/kernel/lib/library_index.dart
+++ b/pkg/kernel/lib/library_index.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.library_index;
 
 import 'ast.dart';
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index 6f8d66d..250dde9 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.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.9
+
 import 'class_hierarchy.dart';
 import 'core_types.dart';
 import 'kernel.dart';
@@ -281,12 +283,18 @@
 
     // Permit any invocation on Function type.
     if (receiver == environment.coreTypes.functionLegacyRawType &&
-        where is MethodInvocation &&
+        where is InvocationExpression &&
         where.name.text == 'call') {
       return;
     }
 
-    fail(where, 'Unresolved method invocation');
+    if (receiver is FunctionType &&
+        where is InvocationExpression &&
+        where.name.text == 'call') {
+      return;
+    }
+
+    fail(where, 'Unresolved method invocation on ${receiver}');
   }
 
   @override
diff --git a/pkg/kernel/lib/reference_from_index.dart b/pkg/kernel/lib/reference_from_index.dart
index 709fbb5..02efc1f 100644
--- a/pkg/kernel/lib/reference_from_index.dart
+++ b/pkg/kernel/lib/reference_from_index.dart
@@ -2,8 +2,21 @@
 // for 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 "ast.dart"
-    show Class, Constructor, Extension, Field, Library, Procedure, Typedef;
+    show
+        Class,
+        Constructor,
+        Extension,
+        Field,
+        Library,
+        Member,
+        Name,
+        Procedure,
+        ProcedureKind,
+        Reference,
+        Typedef;
 
 class ReferenceFromIndex {
   Map<Library, IndexedLibrary> _indexedLibraries =
@@ -19,86 +32,104 @@
   IndexedLibrary lookupLibrary(Library library) => _indexedLibraries[library];
 }
 
-class IndexedLibrary {
+abstract class IndexedContainer {
+  final Map<Name, Reference> _getterReferences = new Map<Name, Reference>();
+  final Map<Name, Reference> _setterReferences = new Map<Name, Reference>();
+
+  Reference lookupGetterReference(Name name) => _getterReferences[name];
+  Reference lookupSetterReference(Name name) => _setterReferences[name];
+
+  Library get library;
+
+  void _addProcedures(List<Procedure> procedures) {
+    for (int i = 0; i < procedures.length; i++) {
+      _addProcedure(procedures[i]);
+    }
+  }
+
+  void _addProcedure(Procedure procedure) {
+    Name name = procedure.name;
+    if (procedure.isSetter) {
+      assert(_setterReferences[name] == null);
+      _setterReferences[name] = procedure.reference;
+    } else {
+      assert(_getterReferences[name] == null);
+      assert(procedure.kind == ProcedureKind.Method ||
+          procedure.kind == ProcedureKind.Getter ||
+          procedure.kind == ProcedureKind.Operator);
+      _getterReferences[name] = procedure.reference;
+    }
+  }
+
+  void _addFields(List<Field> fields) {
+    for (int i = 0; i < fields.length; i++) {
+      Field field = fields[i];
+      Name name = field.name;
+      assert(_getterReferences[name] == null);
+      _getterReferences[name] = field.getterReference;
+      if (field.hasSetter) {
+        assert(_setterReferences[name] == null);
+        _setterReferences[name] = field.setterReference;
+      }
+    }
+  }
+}
+
+class IndexedLibrary extends IndexedContainer {
   final Map<String, Typedef> _typedefs = new Map<String, Typedef>();
   final Map<String, Class> _classes = new Map<String, Class>();
   final Map<String, IndexedClass> _indexedClasses =
       new Map<String, IndexedClass>();
   final Map<String, Extension> _extensions = new Map<String, Extension>();
-  final Map<String, Procedure> _proceduresNotSetters =
-      new Map<String, Procedure>();
-  final Map<String, Procedure> _proceduresSetters =
-      new Map<String, Procedure>();
-  final Map<String, Field> _fields = new Map<String, Field>();
+  final Library library;
 
-  IndexedLibrary(Library library) {
+  IndexedLibrary(this.library) {
     for (int i = 0; i < library.typedefs.length; i++) {
       Typedef typedef = library.typedefs[i];
+      assert(_typedefs[typedef.name] == null);
       _typedefs[typedef.name] = typedef;
     }
     for (int i = 0; i < library.classes.length; i++) {
       Class c = library.classes[i];
+      assert(_classes[c.name] == null);
       _classes[c.name] = c;
-      _indexedClasses[c.name] = new IndexedClass._(c);
+      assert(_indexedClasses[c.name] == null);
+      _indexedClasses[c.name] = new IndexedClass._(c, library);
     }
     for (int i = 0; i < library.extensions.length; i++) {
       Extension extension = library.extensions[i];
+      assert(_extensions[extension.name] == null);
       _extensions[extension.name] = extension;
     }
-    for (int i = 0; i < library.procedures.length; i++) {
-      Procedure procedure = library.procedures[i];
-      if (procedure.isSetter) {
-        _proceduresSetters[procedure.name.text] = procedure;
-      } else {
-        _proceduresNotSetters[procedure.name.text] = procedure;
-      }
-    }
-    for (int i = 0; i < library.fields.length; i++) {
-      Field field = library.fields[i];
-      _fields[field.name.text] = field;
-    }
+    _addProcedures(library.procedures);
+    _addFields(library.fields);
   }
 
   Typedef lookupTypedef(String name) => _typedefs[name];
   Class lookupClass(String name) => _classes[name];
   IndexedClass lookupIndexedClass(String name) => _indexedClasses[name];
   Extension lookupExtension(String name) => _extensions[name];
-  Procedure lookupProcedureNotSetter(String name) =>
-      _proceduresNotSetters[name];
-  Procedure lookupProcedureSetter(String name) => _proceduresSetters[name];
-  Field lookupField(String name) => _fields[name];
 }
 
-class IndexedClass {
-  final Map<String, Constructor> _constructors = new Map<String, Constructor>();
-  final Map<String, Procedure> _proceduresNotSetters =
-      new Map<String, Procedure>();
-  final Map<String, Procedure> _proceduresSetters =
-      new Map<String, Procedure>();
-  final Map<String, Field> _fields = new Map<String, Field>();
+class IndexedClass extends IndexedContainer {
+  final Map<Name, Member> _constructors = new Map<Name, Member>();
+  final Library library;
 
-  IndexedClass._(Class c) {
+  IndexedClass._(Class c, this.library) {
     for (int i = 0; i < c.constructors.length; i++) {
       Constructor constructor = c.constructors[i];
-      _constructors[constructor.name.text] = constructor;
+      _constructors[constructor.name] = constructor;
     }
     for (int i = 0; i < c.procedures.length; i++) {
       Procedure procedure = c.procedures[i];
-      if (procedure.isSetter) {
-        _proceduresSetters[procedure.name.text] = procedure;
+      if (procedure.isFactory) {
+        _constructors[procedure.name] = procedure;
       } else {
-        _proceduresNotSetters[procedure.name.text] = procedure;
+        _addProcedure(procedure);
       }
     }
-    for (int i = 0; i < c.fields.length; i++) {
-      Field field = c.fields[i];
-      _fields[field.name.text] = field;
-    }
+    _addFields(c.fields);
   }
 
-  Constructor lookupConstructor(String name) => _constructors[name];
-  Procedure lookupProcedureNotSetter(String name) =>
-      _proceduresNotSetters[name];
-  Procedure lookupProcedureSetter(String name) => _proceduresSetters[name];
-  Field lookupField(String name) => _fields[name];
+  Member lookupConstructor(Name name) => _constructors[name];
 }
diff --git a/pkg/kernel/lib/src/assumptions.dart b/pkg/kernel/lib/src/assumptions.dart
index 2e131a7..e8c759b 100644
--- a/pkg/kernel/lib/src/assumptions.dart
+++ b/pkg/kernel/lib/src/assumptions.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.9
+
 import '../ast.dart';
 
 /// Pairs of [TypeParameter]s that are currently assumed to be
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index 3e152d2..3862cf5 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.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.9
+
 import '../ast.dart'
     show
         BottomType,
@@ -161,6 +163,15 @@
 /// of the algorithm for details.
 List<DartType> calculateBounds(List<TypeParameter> typeParameters,
     Class objectClass, Library contextLibrary) {
+  return calculateBoundsInternal(typeParameters, objectClass,
+      isNonNullableByDefault: contextLibrary.isNonNullableByDefault);
+}
+
+List<DartType> calculateBoundsInternal(
+    List<TypeParameter> typeParameters, Class objectClass,
+    {bool isNonNullableByDefault}) {
+  assert(isNonNullableByDefault != null);
+
   List<DartType> bounds =
       new List<DartType>.filled(typeParameters.length, null);
   for (int i = 0; i < typeParameters.length; i++) {
@@ -180,7 +191,7 @@
   TypeVariableGraph graph = new TypeVariableGraph(typeParameters, bounds);
   List<List<int>> stronglyConnected = computeStrongComponents(graph);
   final DartType topType = const DynamicType();
-  final DartType bottomType = contextLibrary.isNonNullableByDefault
+  final DartType bottomType = isNonNullableByDefault
       ? const NeverType(Nullability.nonNullable)
       : const BottomType();
   for (List<int> component in stronglyConnected) {
@@ -226,8 +237,20 @@
   /// The enclosing type of the issue, that is, the one with [typeParameter].
   final DartType enclosingType;
 
+  /// The type computed from [enclosingType] for the super-boundness check.
+  ///
+  /// This field can be null.  [invertedType] is supposed to enhance error
+  /// messages, providing the auxiliary type for super-boundness checks for the
+  /// user.  It is set to null if it's not helpful, for example, if
+  /// [enclosingType] is well-bounded or is strictly required to be
+  /// regular-bounded, so the super-boundness check is skipped.  It is set to
+  /// null also if the inversion didn't change the type at all, and it's not
+  /// helpful to show the same type to the user.
+  DartType invertedType;
+
   TypeArgumentIssue(
-      this.index, this.argument, this.typeParameter, this.enclosingType);
+      this.index, this.argument, this.typeParameter, this.enclosingType,
+      {this.invertedType});
 
   int get hashCode {
     int hash = 0x3fffffff & index;
@@ -261,18 +284,12 @@
 // Bound Algorithm.
 // TODO(dmitryas):  Remove [typedefInstantiations] when type arguments passed to
 // typedefs are preserved in the Kernel output.
-List<TypeArgumentIssue> findTypeArgumentIssues(
-    Library library,
-    DartType type,
-    TypeEnvironment typeEnvironment,
-    SubtypeCheckMode subtypeCheckMode,
-    DartType bottomType,
+List<TypeArgumentIssue> findTypeArgumentIssues(Library library, DartType type,
+    TypeEnvironment typeEnvironment, SubtypeCheckMode subtypeCheckMode,
     {bool allowSuperBounded = false}) {
-  assert(bottomType == const NeverType(Nullability.nonNullable) ||
-      bottomType is NullType);
-  List<TypeParameter> variables;
-  List<DartType> arguments;
-  List<TypeArgumentIssue> typedefRhsResult;
+  List<TypeParameter> variables = const <TypeParameter>[];
+  List<DartType> arguments = const <DartType>[];
+  List<TypeArgumentIssue> typedefRhsResult = const <TypeArgumentIssue>[];
 
   if (type is FunctionType && type.typedefType != null) {
     // [type] is a function type that is an application of a parametrized
@@ -287,7 +304,7 @@
         requiredParameterCount: functionType.requiredParameterCount,
         typedefType: null);
     typedefRhsResult = findTypeArgumentIssues(
-        library, cloned, typeEnvironment, subtypeCheckMode, bottomType,
+        library, cloned, typeEnvironment, subtypeCheckMode,
         allowSuperBounded: true);
     type = functionType.typedefType;
   }
@@ -300,48 +317,48 @@
     arguments = type.typeArguments;
   } else if (type is FunctionType) {
     List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
+
     for (TypeParameter parameter in type.typeParameters) {
-      result.addAll(findTypeArgumentIssues(library, parameter.bound,
-              typeEnvironment, subtypeCheckMode, bottomType,
-              allowSuperBounded: true) ??
-          const <TypeArgumentIssue>[]);
+      result.addAll(findTypeArgumentIssues(
+          library, parameter.bound, typeEnvironment, subtypeCheckMode,
+          allowSuperBounded: true));
     }
+
     for (DartType formal in type.positionalParameters) {
       result.addAll(findTypeArgumentIssues(
-              library, formal, typeEnvironment, subtypeCheckMode, bottomType,
-              allowSuperBounded: true) ??
-          const <TypeArgumentIssue>[]);
+          library, formal, typeEnvironment, subtypeCheckMode,
+          allowSuperBounded: true));
     }
+
     for (NamedType named in type.namedParameters) {
-      result.addAll(findTypeArgumentIssues(library, named.type, typeEnvironment,
-              subtypeCheckMode, bottomType,
-              allowSuperBounded: true) ??
-          const <TypeArgumentIssue>[]);
+      result.addAll(findTypeArgumentIssues(
+          library, named.type, typeEnvironment, subtypeCheckMode,
+          allowSuperBounded: true));
     }
-    result.addAll(findTypeArgumentIssues(library, type.returnType,
-            typeEnvironment, subtypeCheckMode, bottomType,
-            allowSuperBounded: true) ??
-        const <TypeArgumentIssue>[]);
-    return result.isEmpty ? null : result;
+
+    result.addAll(findTypeArgumentIssues(
+        library, type.returnType, typeEnvironment, subtypeCheckMode,
+        allowSuperBounded: true));
+
+    return result;
   } else if (type is FutureOrType) {
     variables = typeEnvironment.coreTypes.futureClass.typeParameters;
     arguments = <DartType>[type.typeArgument];
   } else {
-    return null;
+    return const <TypeArgumentIssue>[];
   }
 
-  if (variables == null) return null;
+  if (variables.isEmpty) return const <TypeArgumentIssue>[];
 
-  List<TypeArgumentIssue> result;
-  List<TypeArgumentIssue> argumentsResult;
+  List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
+  List<TypeArgumentIssue> argumentsResult = <TypeArgumentIssue>[];
 
   Map<TypeParameter, DartType> substitutionMap =
       new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
   for (int i = 0; i < arguments.length; ++i) {
     DartType argument = arguments[i];
-    if (argument is FunctionType && argument.typeParameters.length > 0) {
+    if (isGenericFunctionTypeOrAlias(argument)) {
       // Generic function types aren't allowed as type arguments either.
-      result ??= <TypeArgumentIssue>[];
       result.add(new TypeArgumentIssue(i, argument, variables[i], type));
     } else if (variables[i].bound is! InvalidType) {
       DartType bound = substitute(variables[i].bound, substitutionMap);
@@ -349,71 +366,73 @@
         bound = legacyErasure(bound);
       }
       if (!typeEnvironment.isSubtypeOf(argument, bound, subtypeCheckMode)) {
-        // If the bound is InvalidType it's not checked, because an error was
-        // reported already at the time of the creation of InvalidType.
-        result ??= <TypeArgumentIssue>[];
         result.add(new TypeArgumentIssue(i, argument, variables[i], type));
       }
+    } else {
+      // The bound is InvalidType so it's not checked, because an error was
+      // reported already at the time of the creation of InvalidType.
     }
 
-    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
-        library, argument, typeEnvironment, subtypeCheckMode, bottomType,
-        allowSuperBounded: true);
-    if (issues != null) {
-      argumentsResult ??= <TypeArgumentIssue>[];
-      argumentsResult.addAll(issues);
-    }
+    argumentsResult.addAll(findTypeArgumentIssues(
+        library, argument, typeEnvironment, subtypeCheckMode,
+        allowSuperBounded: true));
   }
-  if (argumentsResult != null) {
-    result ??= <TypeArgumentIssue>[];
-    result.addAll(argumentsResult);
-  }
-  if (typedefRhsResult != null) {
-    result ??= <TypeArgumentIssue>[];
-    result.addAll(typedefRhsResult);
-  }
+  result.addAll(argumentsResult);
+  result.addAll(typedefRhsResult);
 
   // [type] is regular-bounded.
-  if (result == null) return null;
+  if (result.isEmpty) return const <TypeArgumentIssue>[];
   if (!allowSuperBounded) return result;
 
-  result = null;
-  type = convertSuperBoundedToRegularBounded(
-      library, typeEnvironment, type, bottomType);
-  List<DartType> argumentsToReport = arguments.toList();
-  if (type is InterfaceType) {
-    variables = type.classNode.typeParameters;
-    arguments = type.typeArguments;
-  } else if (type is TypedefType) {
-    variables = type.typedefNode.typeParameters;
-    arguments = type.typeArguments;
-  } else if (type is FutureOrType) {
+  bool isCorrectSuperBounded = true;
+  DartType invertedType =
+      convertSuperBoundedToRegularBounded(library, typeEnvironment, type);
+
+  // The auxiliary type is the same as [type].  At this point we know that
+  // [type] is not regular-bounded, which means that the inverted type is also
+  // not regular-bounded.  These two judgments together allow us to conclude
+  // that [type] is not well-bounded.
+  if (invertedType == null) return result;
+
+  if (invertedType is InterfaceType) {
+    variables = invertedType.classNode.typeParameters;
+    arguments = invertedType.typeArguments;
+  } else if (invertedType is TypedefType) {
+    variables = invertedType.typedefNode.typeParameters;
+    arguments = invertedType.typeArguments;
+  } else if (invertedType is FutureOrType) {
     variables = typeEnvironment.coreTypes.futureClass.typeParameters;
-    arguments = <DartType>[type.typeArgument];
+    arguments = <DartType>[invertedType.typeArgument];
   }
   substitutionMap =
       new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
   for (int i = 0; i < arguments.length; ++i) {
     DartType argument = arguments[i];
-    if (argument is FunctionType && argument.typeParameters.length > 0) {
+    if (isGenericFunctionTypeOrAlias(argument)) {
       // Generic function types aren't allowed as type arguments either.
-      result ??= <TypeArgumentIssue>[];
-      result.add(
-          new TypeArgumentIssue(i, argumentsToReport[i], variables[i], type));
+      isCorrectSuperBounded = false;
     } else if (!typeEnvironment.isSubtypeOf(argument,
         substitute(variables[i].bound, substitutionMap), subtypeCheckMode)) {
-      result ??= <TypeArgumentIssue>[];
-      result.add(
-          new TypeArgumentIssue(i, argumentsToReport[i], variables[i], type));
+      isCorrectSuperBounded = false;
     }
   }
-  if (argumentsResult != null) {
-    result ??= <TypeArgumentIssue>[];
-    result.addAll(argumentsResult);
+  if (argumentsResult.isNotEmpty) {
+    isCorrectSuperBounded = false;
   }
-  if (typedefRhsResult != null) {
-    result ??= <TypeArgumentIssue>[];
-    result.addAll(typedefRhsResult);
+  if (typedefRhsResult.isNotEmpty) {
+    isCorrectSuperBounded = false;
+  }
+
+  // The inverted type is regular-bounded, which means that [type] is
+  // well-bounded.
+  if (isCorrectSuperBounded) return const <TypeArgumentIssue>[];
+
+  // The inverted type isn't regular-bounded, but it's different from [type].
+  // In this case we'll provide the programmer with the inverted type as a hint,
+  // in case they were going for a super-bounded type and will benefit from that
+  // information correcting the program.
+  for (TypeArgumentIssue issue in result) {
+    issue.invertedType = invertedType;
   }
   return result;
 }
@@ -438,7 +457,7 @@
   assert(arguments.length == parameters.length);
   assert(bottomType == const NeverType(Nullability.nonNullable) ||
       bottomType is NullType);
-  List<TypeArgumentIssue> result;
+  List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
   Map<TypeParameter, DartType> substitutionMap = <TypeParameter, DartType>{};
   for (int i = 0; i < arguments.length; ++i) {
     substitutionMap[parameters[i]] = arguments[i];
@@ -446,11 +465,9 @@
   for (int i = 0; i < arguments.length; ++i) {
     DartType argument = arguments[i];
     if (argument is TypeParameterType && argument.promotedBound != null) {
-      result ??= <TypeArgumentIssue>[];
       result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
-    } else if (argument is FunctionType && argument.typeParameters.length > 0) {
+    } else if (isGenericFunctionTypeOrAlias(argument)) {
       // Generic function types aren't allowed as type arguments either.
-      result ??= <TypeArgumentIssue>[];
       result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
     } else if (parameters[i].bound is! InvalidType) {
       DartType bound = substitute(parameters[i].bound, substitutionMap);
@@ -458,18 +475,13 @@
         bound = legacyErasure(bound);
       }
       if (!typeEnvironment.isSubtypeOf(argument, bound, subtypeCheckMode)) {
-        result ??= <TypeArgumentIssue>[];
         result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
       }
     }
 
-    List<TypeArgumentIssue> issues = findTypeArgumentIssues(
-        library, argument, typeEnvironment, subtypeCheckMode, bottomType,
-        allowSuperBounded: true);
-    if (issues != null) {
-      result ??= <TypeArgumentIssue>[];
-      result.addAll(issues);
-    }
+    result.addAll(findTypeArgumentIssues(
+        library, argument, typeEnvironment, subtypeCheckMode,
+        allowSuperBounded: true));
   }
   return result;
 }
@@ -485,76 +497,199 @@
 
 /// Replaces all covariant occurrences of `dynamic`, `Object`, and `void` with
 /// [BottomType] and all contravariant occurrences of `Null` and [BottomType]
-/// with `Object`.
-DartType convertSuperBoundedToRegularBounded(Library clientLibrary,
-    TypeEnvironment typeEnvironment, DartType type, DartType bottomType,
-    {bool isCovariant = true}) {
-  bool isTop = clientLibrary.isNonNullableByDefault
-      ? typeEnvironment.coreTypes.isTop(type)
-      : type is DynamicType ||
-          type is VoidType ||
-          type is InterfaceType &&
-              type.classNode == typeEnvironment.coreTypes.objectClass;
-  if (isTop && isCovariant) {
+/// with `Object`.  Returns null if the converted type is the same as [type].
+DartType convertSuperBoundedToRegularBounded(
+    Library clientLibrary, TypeEnvironment typeEnvironment, DartType type,
+    {int variance = Variance.covariant}) {
+  bool flipTop;
+  bool flipBottom;
+  DartType topType;
+  DartType bottomType;
+  bool isTop;
+  bool isBottom;
+  if (clientLibrary.isNonNullableByDefault) {
+    flipTop = variance != Variance.contravariant;
+    flipBottom = variance == Variance.contravariant;
+    topType = typeEnvironment.coreTypes.objectNullableRawType;
+    bottomType = const NeverType(Nullability.nonNullable);
+    isTop = typeEnvironment.coreTypes.isTop(type);
+    isBottom = typeEnvironment.coreTypes.isBottom(type);
+  } else {
+    flipTop = variance == Variance.covariant;
+    flipBottom = variance != Variance.covariant;
+    topType = const DynamicType();
+    bottomType = const NullType();
+    isTop = type is DynamicType ||
+        type is VoidType ||
+        type is InterfaceType &&
+            type.classNode == typeEnvironment.coreTypes.objectClass;
+    isBottom = type is NullType || type is BottomType;
+  }
+
+  if (isTop && flipTop) {
     return bottomType;
-  } else if ((type == bottomType || type is BottomType) && !isCovariant) {
-    return typeEnvironment.coreTypes.objectLegacyRawType;
-  } else if (type is InterfaceType && type.classNode.typeParameters != null) {
-    List<DartType> replacedTypeArguments =
-        new List<DartType>.filled(type.typeArguments.length, null);
-    for (int i = 0; i < replacedTypeArguments.length; i++) {
-      replacedTypeArguments[i] = convertSuperBoundedToRegularBounded(
-          clientLibrary, typeEnvironment, type.typeArguments[i], bottomType,
-          isCovariant: isCovariant);
+  } else if (isBottom && flipBottom) {
+    return topType;
+  } else if (type is InterfaceType &&
+      type.classNode.typeParameters.isNotEmpty) {
+    assert(type.classNode.typeParameters.length == type.typeArguments.length);
+
+    List<DartType> convertedTypeArguments = null;
+    for (int i = 0; i < type.typeArguments.length; ++i) {
+      DartType convertedTypeArgument = convertSuperBoundedToRegularBounded(
+          clientLibrary, typeEnvironment, type.typeArguments[i],
+          variance: variance);
+      if (convertedTypeArgument != null) {
+        convertedTypeArguments ??= new List<DartType>.of(type.typeArguments);
+        convertedTypeArguments[i] = convertedTypeArgument;
+      }
     }
+    if (convertedTypeArguments == null) return null;
     return new InterfaceType(
-        type.classNode, type.nullability, replacedTypeArguments);
-  } else if (type is TypedefType && type.typedefNode.typeParameters != null) {
-    List<DartType> replacedTypeArguments =
-        new List<DartType>.filled(type.typeArguments.length, null);
-    for (int i = 0; i < replacedTypeArguments.length; i++) {
-      replacedTypeArguments[i] = convertSuperBoundedToRegularBounded(
-          clientLibrary, typeEnvironment, type.typeArguments[i], bottomType,
-          isCovariant: isCovariant);
+        type.classNode, type.nullability, convertedTypeArguments);
+  } else if (type is TypedefType &&
+      type.typedefNode.typeParameters.isNotEmpty) {
+    assert(type.typedefNode.typeParameters.length == type.typeArguments.length);
+
+    List<DartType> convertedTypeArguments = null;
+    for (int i = 0; i < type.typeArguments.length; i++) {
+      // The implementation of instantiate-to-bound in legacy mode ignored the
+      // variance of type parameters of the typedef.  This behavior is preserved
+      // here in passing the 'variance' parameter unchanged in for legacy
+      // libraries.
+      DartType convertedTypeArgument = convertSuperBoundedToRegularBounded(
+          clientLibrary, typeEnvironment, type.typeArguments[i],
+          variance: clientLibrary.isNonNullableByDefault
+              ? Variance.combine(
+                  variance, type.typedefNode.typeParameters[i].variance)
+              : variance);
+      if (convertedTypeArgument != null) {
+        convertedTypeArguments ??= new List<DartType>.of(type.typeArguments);
+        convertedTypeArguments[i] = convertedTypeArgument;
+      }
     }
+    if (convertedTypeArguments == null) return null;
     return new TypedefType(
-        type.typedefNode, type.nullability, replacedTypeArguments);
+        type.typedefNode, type.nullability, convertedTypeArguments);
   } else if (type is FunctionType) {
-    DartType replacedReturnType = convertSuperBoundedToRegularBounded(
-        clientLibrary, typeEnvironment, type.returnType, bottomType,
-        isCovariant: isCovariant);
-    List<DartType> replacedPositionalParameters =
-        new List<DartType>.filled(type.positionalParameters.length, null);
-    for (int i = 0; i < replacedPositionalParameters.length; i++) {
-      replacedPositionalParameters[i] = convertSuperBoundedToRegularBounded(
-          clientLibrary,
-          typeEnvironment,
-          type.positionalParameters[i],
-          bottomType,
-          isCovariant: !isCovariant);
+    if (clientLibrary.isNonNullableByDefault && type.typedefType != null) {
+      return convertSuperBoundedToRegularBounded(
+          clientLibrary, typeEnvironment, type.typedefType,
+          variance: variance);
     }
-    List<NamedType> replacedNamedParameters =
-        new List<NamedType>.filled(type.namedParameters.length, null);
-    for (int i = 0; i < replacedNamedParameters.length; i++) {
-      replacedNamedParameters[i] = new NamedType(
+
+    DartType convertedReturnType = convertSuperBoundedToRegularBounded(
+        clientLibrary, typeEnvironment, type.returnType,
+        variance: variance);
+
+    List<DartType> convertedPositionalParameters = null;
+    for (int i = 0; i < type.positionalParameters.length; i++) {
+      DartType convertedPositionalParameter =
+          convertSuperBoundedToRegularBounded(
+              clientLibrary, typeEnvironment, type.positionalParameters[i],
+              variance: Variance.combine(variance, Variance.contravariant));
+      if (convertedPositionalParameter != null) {
+        convertedPositionalParameters ??=
+            new List<DartType>.of(type.positionalParameters);
+        convertedPositionalParameters[i] = convertedPositionalParameter;
+      }
+    }
+
+    List<NamedType> convertedNamedParameters = null;
+    for (int i = 0; i < type.namedParameters.length; i++) {
+      NamedType convertedNamedParameter = new NamedType(
           type.namedParameters[i].name,
-          convertSuperBoundedToRegularBounded(clientLibrary, typeEnvironment,
-              type.namedParameters[i].type, bottomType,
-              isCovariant: !isCovariant));
+          convertSuperBoundedToRegularBounded(
+              clientLibrary, typeEnvironment, type.namedParameters[i].type,
+              variance: Variance.combine(variance, Variance.contravariant)),
+          isRequired: type.namedParameters[i].isRequired);
+      if (convertedNamedParameter != null) {
+        convertedNamedParameters ??=
+            new List<NamedType>.of(type.namedParameters);
+        convertedNamedParameters[i] = convertedNamedParameter;
+      }
     }
+
+    List<TypeParameter> convertedTypeParameters = null;
+    if (clientLibrary.isNonNullableByDefault &&
+        type.typeParameters.isNotEmpty) {
+      for (int i = 0; i < type.typeParameters.length; ++i) {
+        DartType convertedBound = convertSuperBoundedToRegularBounded(
+            clientLibrary, typeEnvironment, type.typeParameters[i].bound,
+            variance: Variance.combine(variance, Variance.invariant));
+        if (convertedBound != null) {
+          if (convertedTypeParameters == null) {
+            convertedTypeParameters = <TypeParameter>[];
+            for (TypeParameter parameter in type.typeParameters) {
+              convertedTypeParameters.add(new TypeParameter(parameter.name));
+            }
+          }
+          convertedTypeParameters[i].bound = convertedBound;
+        }
+      }
+
+      Map<TypeParameter, DartType> substitutionMap =
+          <TypeParameter, DartType>{};
+      for (int i = 0; i < type.typeParameters.length; ++i) {
+        substitutionMap[type.typeParameters[i]] =
+            new TypeParameterType.forAlphaRenaming(
+                type.typeParameters[i], convertedTypeParameters[i]);
+      }
+      for (TypeParameter parameter in convertedTypeParameters) {
+        parameter.bound = substitute(parameter.bound, substitutionMap);
+      }
+      List<DartType> defaultTypes = calculateBounds(convertedTypeParameters,
+          typeEnvironment.coreTypes.objectClass, clientLibrary);
+      for (int i = 0; i < convertedTypeParameters.length; ++i) {
+        convertedTypeParameters[i].defaultType = defaultTypes[i];
+      }
+
+      if (convertedReturnType != null) {
+        convertedReturnType = substitute(convertedReturnType, substitutionMap);
+      }
+      if (convertedPositionalParameters != null) {
+        for (int i = 0; i < convertedPositionalParameters.length; ++i) {
+          convertedPositionalParameters[i] =
+              substitute(convertedPositionalParameters[i], substitutionMap);
+        }
+      }
+      if (convertedNamedParameters != null) {
+        for (int i = 0; i < convertedNamedParameters.length; ++i) {
+          convertedNamedParameters[i] = new NamedType(
+              convertedNamedParameters[i].name,
+              substitute(convertedNamedParameters[i].type, substitutionMap),
+              isRequired: convertedNamedParameters[i].isRequired);
+        }
+      }
+    }
+
+    if (convertedReturnType == null &&
+        convertedPositionalParameters == null &&
+        convertedNamedParameters == null &&
+        convertedTypeParameters == null) {
+      return null;
+    }
+
+    convertedReturnType ??= type.returnType;
+    convertedPositionalParameters ??= type.positionalParameters;
+    convertedNamedParameters ??= type.namedParameters;
+    convertedTypeParameters ??= type.typeParameters;
+
     return new FunctionType(
-        replacedPositionalParameters, replacedReturnType, type.nullability,
-        namedParameters: replacedNamedParameters,
+        convertedPositionalParameters, convertedReturnType, type.nullability,
+        namedParameters: convertedNamedParameters,
         typeParameters: type.typeParameters,
         requiredParameterCount: type.requiredParameterCount,
         typedefType: type.typedefType);
   } else if (type is FutureOrType) {
-    return new FutureOrType(
-        convertSuperBoundedToRegularBounded(
-            clientLibrary, typeEnvironment, type.typeArgument, bottomType),
-        type.declaredNullability);
+    DartType convertedTypeArgument = convertSuperBoundedToRegularBounded(
+        clientLibrary, typeEnvironment, type.typeArgument,
+        variance: variance);
+    if (convertedTypeArgument == null) return null;
+    return new FutureOrType(convertedTypeArgument, type.declaredNullability);
   }
-  return type;
+
+  return null;
 }
 
 int computeVariance(TypeParameter typeParameter, DartType type,
@@ -713,3 +848,8 @@
     return Variance.unrelated;
   }
 }
+
+bool isGenericFunctionTypeOrAlias(DartType type) {
+  if (type is TypedefType) type = type.unalias;
+  return type is FunctionType && type.typeParameters.isNotEmpty;
+}
diff --git a/pkg/kernel/lib/src/const_canonical_type.dart b/pkg/kernel/lib/src/const_canonical_type.dart
new file mode 100644
index 0000000..202e731
--- /dev/null
+++ b/pkg/kernel/lib/src/const_canonical_type.dart
@@ -0,0 +1,216 @@
+// 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.
+
+// @dart = 2.9
+
+import 'package:kernel/src/bounds_checks.dart';
+
+import '../ast.dart' hide MapEntry;
+import '../core_types.dart';
+import '../type_algebra.dart';
+
+/// Computes CONST_CANONICAL_TYPE
+///
+/// The algorithm is specified at
+/// https://github.com/dart-lang/language/blob/master/accepted/future-releases/nnbd/feature-specification.md#constant-instances
+DartType computeConstCanonicalType(DartType type, CoreTypes coreTypes,
+    {bool isNonNullableByDefault}) {
+  assert(isNonNullableByDefault != null);
+
+  if (type is InvalidType) {
+    return type;
+  }
+
+  // CONST_CANONICAL_TYPE(T) = T if T is dynamic, void, Null
+  if (type is DynamicType || type is VoidType || type is NullType) {
+    return type;
+  }
+
+  // CONST_CANONICAL_TYPE(T) = T* if T is Never or Object
+  if (type is NeverType &&
+      type.declaredNullability == Nullability.nonNullable) {
+    return const NeverType(Nullability.legacy);
+  }
+  if (type == coreTypes.objectNonNullableRawType) {
+    return coreTypes.objectLegacyRawType;
+  }
+
+  // CONST_CANONICAL_TYPE(FutureOr<T>) = FutureOr<S>*
+  // where S is CONST_CANONICAL_TYPE(T)
+  if (type is FutureOrType &&
+      isTypeWithoutNullabilityMarker(type,
+          isNonNullableByDefault: isNonNullableByDefault)) {
+    return new FutureOrType(
+        computeConstCanonicalType(type.typeArgument, coreTypes,
+            isNonNullableByDefault: isNonNullableByDefault),
+        Nullability.legacy);
+  }
+
+  // CONST_CANONICAL_TYPE(T?) =
+  // let S be CONST_CANONICAL_TYPE(T)
+  // if S is R* then R?
+  // else S?
+  if (isNullableTypeConstructorApplication(type)) {
+    return computeConstCanonicalType(
+            computeTypeWithoutNullabilityMarker(type,
+                isNonNullableByDefault: isNonNullableByDefault),
+            coreTypes,
+            isNonNullableByDefault: isNonNullableByDefault)
+        .withDeclaredNullability(Nullability.nullable);
+  }
+
+  // CONST_CANONICAL_TYPE(T*) = CONST_CANONICAL_TYPE(T)
+  if (isLegacyTypeConstructorApplication(type,
+      isNonNullableByDefault: isNonNullableByDefault)) {
+    return computeConstCanonicalType(
+        computeTypeWithoutNullabilityMarker(type,
+            isNonNullableByDefault: isNonNullableByDefault),
+        coreTypes,
+        isNonNullableByDefault: isNonNullableByDefault);
+  }
+
+  // CONST_CANONICAL_TYPE(X extends T) = X*
+  if (type is TypeParameterType && type.promotedBound == null) {
+    return type.withDeclaredNullability(Nullability.legacy);
+  }
+
+  // CONST_CANONICAL_TYPE(X & T) =
+  // This case should not occur, since intersection types are not permitted as
+  // generic arguments.
+  assert(!(type is TypeParameterType && type.promotedBound != null),
+      "Intersection types are not permitted as generic arguments: '${type}'.");
+
+  // CONST_CANONICAL_TYPE(C<T0, ..., Tn>) = C<R0, ..., Rn>*
+  // where Ri is CONST_CANONICAL_TYPE(Ti)
+  // Note this includes the case of an interface type with no generic parameters
+  // (e.g int).
+  if (type is InterfaceType) {
+    assert(type.declaredNullability == Nullability.nonNullable);
+    List<DartType> typeArguments;
+    if (type.typeArguments.isEmpty) {
+      typeArguments = const <DartType>[];
+    } else {
+      typeArguments =
+          new List<DartType>.of(type.typeArguments, growable: false);
+      for (int i = 0; i < typeArguments.length; ++i) {
+        typeArguments[i] = computeConstCanonicalType(
+            typeArguments[i], coreTypes,
+            isNonNullableByDefault: isNonNullableByDefault);
+      }
+    }
+    return new InterfaceType(type.classNode, Nullability.legacy, typeArguments);
+  }
+
+  // CONST_CANONICAL_TYPE(R Function<X extends B>(S)) = F*
+  // where F = R1 Function<X extends B1>(S1)
+  // and R1 = CONST_CANONICAL_TYPE(R)
+  // and B1 = CONST_CANONICAL_TYPE(B)
+  // and S1 = CONST_CANONICAL_TYPE(S)
+  // Note, this generalizes to arbitrary number of type and term parameters.
+  if (type is FunctionType) {
+    assert(type.declaredNullability == Nullability.nonNullable);
+
+    List<TypeParameter> canonicalizedTypeParameters;
+    Map<TypeParameter, DartType> substitutionMap;
+    if (type.typeParameters.isEmpty) {
+      canonicalizedTypeParameters = const <TypeParameter>[];
+      substitutionMap = const <TypeParameter, DartType>{};
+    } else {
+      substitutionMap = <TypeParameter, DartType>{};
+      canonicalizedTypeParameters =
+          new List<TypeParameter>.of(type.typeParameters, growable: false);
+      for (TypeParameter parameter in canonicalizedTypeParameters) {
+        parameter.bound = computeConstCanonicalType(parameter.bound, coreTypes,
+            isNonNullableByDefault: isNonNullableByDefault);
+      }
+      List<DartType> defaultTypes = calculateBoundsInternal(
+          canonicalizedTypeParameters, coreTypes.objectClass,
+          isNonNullableByDefault: isNonNullableByDefault);
+      for (int i = 0; i < canonicalizedTypeParameters.length; ++i) {
+        canonicalizedTypeParameters[i].defaultType = defaultTypes[i];
+      }
+      for (int i = 0; i < canonicalizedTypeParameters.length; ++i) {
+        substitutionMap[canonicalizedTypeParameters[i]] =
+            new TypeParameterType.forAlphaRenaming(
+                type.typeParameters[i], canonicalizedTypeParameters[i]);
+      }
+    }
+
+    List<DartType> canonicalizedPositionalParameters;
+    if (type.positionalParameters.isEmpty) {
+      canonicalizedPositionalParameters = const <DartType>[];
+    } else {
+      canonicalizedPositionalParameters =
+          new List<DartType>.of(type.positionalParameters, growable: false);
+      for (int i = 0; i < canonicalizedPositionalParameters.length; ++i) {
+        DartType canonicalized = computeConstCanonicalType(
+            canonicalizedPositionalParameters[i], coreTypes,
+            isNonNullableByDefault: isNonNullableByDefault);
+        if (substitutionMap.isNotEmpty) {
+          canonicalized = substitute(canonicalized, substitutionMap);
+        }
+        canonicalizedPositionalParameters[i] = canonicalized;
+      }
+    }
+
+    List<NamedType> canonicalizedNamedParameters;
+    if (type.namedParameters.isEmpty) {
+      canonicalizedNamedParameters = const <NamedType>[];
+    } else {
+      canonicalizedNamedParameters =
+          new List<NamedType>.of(type.namedParameters, growable: false);
+      for (int i = 0; i < canonicalizedNamedParameters.length; ++i) {
+        DartType canonicalized = computeConstCanonicalType(
+            canonicalizedNamedParameters[i].type, coreTypes,
+            isNonNullableByDefault: isNonNullableByDefault);
+        if (substitutionMap.isNotEmpty) {
+          canonicalized = substitute(canonicalized, substitutionMap);
+        }
+        canonicalizedNamedParameters[i] = new NamedType(
+            canonicalizedNamedParameters[i].name, canonicalized,
+            isRequired: canonicalizedNamedParameters[i].isRequired);
+      }
+    }
+
+    DartType canonicalizedReturnType = computeConstCanonicalType(
+        type.returnType, coreTypes,
+        isNonNullableByDefault: isNonNullableByDefault);
+    if (substitutionMap.isNotEmpty) {
+      canonicalizedReturnType =
+          substitute(canonicalizedReturnType, substitutionMap);
+    }
+
+    // Canonicalize typedef type, just in case.
+    TypedefType canonicalizedTypedefType;
+    if (type.typedefType == null) {
+      canonicalizedTypedefType = null;
+    } else {
+      List<DartType> canonicalizedTypeArguments;
+      if (type.typedefType.typeArguments.isEmpty) {
+        canonicalizedTypeArguments = const <DartType>[];
+      } else {
+        canonicalizedTypeArguments = new List<DartType>.of(
+            type.typedefType.typeArguments,
+            growable: false);
+        for (int i = 0; i < canonicalizedTypeArguments.length; ++i) {
+          canonicalizedTypeArguments[i] = computeConstCanonicalType(
+              canonicalizedTypeArguments[i], coreTypes,
+              isNonNullableByDefault: isNonNullableByDefault);
+        }
+      }
+      canonicalizedTypedefType = new TypedefType(type.typedefType.typedefNode,
+          Nullability.legacy, canonicalizedTypeArguments);
+    }
+
+    return new FunctionType(canonicalizedPositionalParameters,
+        canonicalizedReturnType, Nullability.legacy,
+        namedParameters: canonicalizedNamedParameters,
+        typeParameters: canonicalizedTypeParameters,
+        requiredParameterCount: type.requiredParameterCount,
+        typedefType: canonicalizedTypedefType);
+  }
+
+  throw new StateError(
+      "Unhandled '${type.runtimeType}' in 'computeConstCanonicalType'.");
+}
diff --git a/pkg/kernel/lib/src/dart_type_equivalence.dart b/pkg/kernel/lib/src/dart_type_equivalence.dart
index 35eeff4..ee4f758 100644
--- a/pkg/kernel/lib/src/dart_type_equivalence.dart
+++ b/pkg/kernel/lib/src/dart_type_equivalence.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.md file.
 
+// @dart = 2.9
+
 import '../ast.dart';
 import '../core_types.dart';
 import '../visitor.dart';
diff --git a/pkg/kernel/lib/src/future_value_type.dart b/pkg/kernel/lib/src/future_value_type.dart
index e3fd270..a77cef5 100644
--- a/pkg/kernel/lib/src/future_value_type.dart
+++ b/pkg/kernel/lib/src/future_value_type.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.9
+
 import '../ast.dart';
 import '../core_types.dart';
 
diff --git a/pkg/kernel/lib/src/hierarchy_based_type_environment.dart b/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
index 9474496..e259b73 100644
--- a/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
+++ b/pkg/kernel/lib/src/hierarchy_based_type_environment.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.9
+
 library kernel.hierarchy_based_type_environment;
 
 import '../ast.dart' show Class, DartType, InterfaceType, Library, Member, Name;
diff --git a/pkg/kernel/lib/src/legacy_erasure.dart b/pkg/kernel/lib/src/legacy_erasure.dart
index 3628368..3a386bd 100644
--- a/pkg/kernel/lib/src/legacy_erasure.dart
+++ b/pkg/kernel/lib/src/legacy_erasure.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.md file.
 
+// @dart = 2.9
+
 import '../ast.dart' hide MapEntry;
 
 import 'replacement_visitor.dart';
@@ -69,3 +71,47 @@
   @override
   DartType visitNeverType(NeverType node) => const NullType();
 }
+
+/// Returns `true` if a member declared in [declaringClass] inherited or
+/// mixed into [enclosingClass] needs legacy erasure to compute its inherited
+/// type.
+///
+/// For instance:
+///
+///    // Opt in:
+///    class Super {
+///      int extendedMethod(int i, {required int j}) => i;
+///    }
+///    class Mixin {
+///      int mixedInMethod(int i, {required int j}) => i;
+///    }
+///    // Opt out:
+///    class Legacy extends Super with Mixin {}
+///    // Opt in:
+///    class Class extends Legacy {
+///      test() {
+///        // Ok to call `Legacy.extendedMethod` since its type is
+///        // `int* Function(int*, {int* j})`.
+///        super.extendedMethod(null);
+///        // Ok to call `Legacy.mixedInMethod` since its type is
+///        // `int* Function(int*, {int* j})`.
+///        super.mixedInMethod(null);
+///      }
+///    }
+///
+bool needsLegacyErasure(Class enclosingClass, Class declaringClass) {
+  Class cls = enclosingClass;
+  while (cls != null) {
+    if (!cls.enclosingLibrary.isNonNullableByDefault) {
+      return true;
+    }
+    if (cls == declaringClass) {
+      return false;
+    }
+    if (cls.mixedInClass == declaringClass) {
+      return false;
+    }
+    cls = cls.superclass;
+  }
+  return false;
+}
diff --git a/pkg/kernel/lib/src/merge_visitor.dart b/pkg/kernel/lib/src/merge_visitor.dart
index 62eb99a..dc1b77b 100644
--- a/pkg/kernel/lib/src/merge_visitor.dart
+++ b/pkg/kernel/lib/src/merge_visitor.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.md file.
 
+// @dart = 2.9
+
 import '../ast.dart' hide MapEntry;
 import '../type_algebra.dart';
 
diff --git a/pkg/kernel/lib/src/nnbd_top_merge.dart b/pkg/kernel/lib/src/nnbd_top_merge.dart
index 9a56df4..fd5f9eb 100644
--- a/pkg/kernel/lib/src/nnbd_top_merge.dart
+++ b/pkg/kernel/lib/src/nnbd_top_merge.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.md file.
 
+// @dart = 2.9
+
 import '../ast.dart' hide MapEntry;
 import '../core_types.dart';
 
diff --git a/pkg/kernel/lib/src/non_null.dart b/pkg/kernel/lib/src/non_null.dart
index 14e0c01..2a90dad 100644
--- a/pkg/kernel/lib/src/non_null.dart
+++ b/pkg/kernel/lib/src/non_null.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.md file.
 
+// @dart = 2.9
+
 import '../ast.dart';
 
 /// Returns the type defines as `NonNull(type)` in the nnbd specification.
diff --git a/pkg/kernel/lib/src/norm.dart b/pkg/kernel/lib/src/norm.dart
index c8d0f71..1b92f42 100644
--- a/pkg/kernel/lib/src/norm.dart
+++ b/pkg/kernel/lib/src/norm.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.md file.
 
+// @dart = 2.9
+
 import '../ast.dart' hide MapEntry;
 import '../core_types.dart';
 import '../type_algebra.dart';
diff --git a/pkg/kernel/lib/src/printer.dart b/pkg/kernel/lib/src/printer.dart
index 0e9223d..c6a8f57 100644
--- a/pkg/kernel/lib/src/printer.dart
+++ b/pkg/kernel/lib/src/printer.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.9
+
 import '../ast.dart';
 import 'text_util.dart';
 
diff --git a/pkg/kernel/lib/src/replacement_visitor.dart b/pkg/kernel/lib/src/replacement_visitor.dart
index 9550e18..e260919 100644
--- a/pkg/kernel/lib/src/replacement_visitor.dart
+++ b/pkg/kernel/lib/src/replacement_visitor.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.md file.
 
+// @dart = 2.9
+
 import '../ast.dart' hide MapEntry;
 import '../type_algebra.dart';
 
@@ -21,7 +23,11 @@
     List<TypeParameter> newTypeParameters;
     for (int i = 0; i < node.typeParameters.length; i++) {
       TypeParameter typeParameter = node.typeParameters[i];
-      DartType newBound = typeParameter.bound.accept(this);
+      // TODO(johnniwinther): Bounds should not be null, even in case of
+      // cyclic typedefs. Currently
+      //   instantiate_to_bound/non_simple_class_parametrized_typedef_cycle
+      // fails with this.
+      DartType newBound = typeParameter.bound?.accept(this);
       DartType newDefaultType = typeParameter.defaultType?.accept(this);
       if (newBound != null || newDefaultType != null) {
         newTypeParameters ??= node.typeParameters.toList(growable: false);
diff --git a/pkg/kernel/lib/src/standard_bounds.dart b/pkg/kernel/lib/src/standard_bounds.dart
index d622437..de68c1d 100644
--- a/pkg/kernel/lib/src/standard_bounds.dart
+++ b/pkg/kernel/lib/src/standard_bounds.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.md file.
 
+// @dart = 2.9
+
 import 'dart:math' as math;
 
 import '../ast.dart'
@@ -373,8 +375,6 @@
       return const NeverType(Nullability.nonNullable);
     }
 
-    // The effect of the following rules is accounted for in the code below via
-    // the invocations of intersectNullabilities.
     // DOWN(T1*, T2*) = S* where S is DOWN(T1, T2)
     // DOWN(T1*, T2?) = S* where S is DOWN(T1, T2)
     // DOWN(T1?, T2*) = S* where S is DOWN(T1, T2)
@@ -383,6 +383,49 @@
     // DOWN(T1?, T2?) = S? where S is DOWN(T1, T2)
     // DOWN(T1?, T2) = S where S is DOWN(T1, T2)
     // DOWN(T1, T2?) = S where S is DOWN(T1, T2)
+    {
+      bool type1HasNullabilityMarker = !isTypeWithoutNullabilityMarker(type1,
+          isNonNullableByDefault: clientLibrary.isNonNullableByDefault);
+      bool type2HasNullabilityMarker = !isTypeWithoutNullabilityMarker(type2,
+          isNonNullableByDefault: clientLibrary.isNonNullableByDefault);
+      if (type1HasNullabilityMarker && !type2HasNullabilityMarker) {
+        return _getNullabilityAwareStandardLowerBound(
+            computeTypeWithoutNullabilityMarker(type1,
+                isNonNullableByDefault: clientLibrary.isNonNullableByDefault),
+            type2,
+            clientLibrary);
+      } else if (!type1HasNullabilityMarker && type2HasNullabilityMarker) {
+        return _getNullabilityAwareStandardLowerBound(
+            type1,
+            computeTypeWithoutNullabilityMarker(type2,
+                isNonNullableByDefault: clientLibrary.isNonNullableByDefault),
+            clientLibrary);
+      } else if (isLegacyTypeConstructorApplication(type1,
+              isNonNullableByDefault: clientLibrary.isNonNullableByDefault) ||
+          isLegacyTypeConstructorApplication(type2,
+              isNonNullableByDefault: clientLibrary.isNonNullableByDefault)) {
+        return _getNullabilityAwareStandardLowerBound(
+                computeTypeWithoutNullabilityMarker(type1,
+                    isNonNullableByDefault:
+                        clientLibrary.isNonNullableByDefault),
+                computeTypeWithoutNullabilityMarker(type2,
+                    isNonNullableByDefault:
+                        clientLibrary.isNonNullableByDefault),
+                clientLibrary)
+            .withDeclaredNullability(Nullability.legacy);
+      } else if (isNullableTypeConstructorApplication(type1) &&
+          isNullableTypeConstructorApplication(type2)) {
+        return _getNullabilityAwareStandardLowerBound(
+                computeTypeWithoutNullabilityMarker(type1,
+                    isNonNullableByDefault:
+                        clientLibrary.isNonNullableByDefault),
+                computeTypeWithoutNullabilityMarker(type2,
+                    isNonNullableByDefault:
+                        clientLibrary.isNonNullableByDefault),
+                clientLibrary)
+            .withDeclaredNullability(Nullability.nullable);
+      }
+    }
 
     if (type1 is FunctionType && type2 is FunctionType) {
       return _getNullabilityAwareFunctionStandardLowerBound(
@@ -397,9 +440,11 @@
     // [intersectNullabilities] to compute the resulting type if the subtype
     // relation is established.
     DartType typeWithoutNullabilityMarker1 =
-        computeTypeWithoutNullabilityMarker(type1, clientLibrary);
+        computeTypeWithoutNullabilityMarker(type1,
+            isNonNullableByDefault: clientLibrary.isNonNullableByDefault);
     DartType typeWithoutNullabilityMarker2 =
-        computeTypeWithoutNullabilityMarker(type2, clientLibrary);
+        computeTypeWithoutNullabilityMarker(type2,
+            isNonNullableByDefault: clientLibrary.isNonNullableByDefault);
     if (isSubtypeOf(typeWithoutNullabilityMarker1,
         typeWithoutNullabilityMarker2, SubtypeCheckMode.withNullabilities)) {
       return type1.withDeclaredNullability(intersectNullabilities(
@@ -674,8 +719,6 @@
       return type2.withDeclaredNullability(Nullability.nullable);
     }
 
-    // The effect of the following rules is accounted for in the code below via
-    // the invocations of uniteNullabilities.
     // UP(T1*, T2*) = S* where S is UP(T1, T2)
     // UP(T1*, T2?) = S? where S is UP(T1, T2)
     // UP(T1?, T2*) = S? where S is UP(T1, T2)
@@ -684,6 +727,28 @@
     // UP(T1?, T2?) = S? where S is UP(T1, T2)
     // UP(T1?, T2) = S? where S is UP(T1, T2)
     // UP(T1, T2?) = S? where S is UP(T1, T2)
+    if (isNullableTypeConstructorApplication(type1) ||
+        isNullableTypeConstructorApplication(type2)) {
+      return _getNullabilityAwareStandardUpperBound(
+              computeTypeWithoutNullabilityMarker(type1,
+                  isNonNullableByDefault: clientLibrary.isNonNullableByDefault),
+              computeTypeWithoutNullabilityMarker(type2,
+                  isNonNullableByDefault: clientLibrary.isNonNullableByDefault),
+              clientLibrary)
+          .withDeclaredNullability(Nullability.nullable);
+    }
+    if (isLegacyTypeConstructorApplication(type1,
+            isNonNullableByDefault: clientLibrary.isNonNullableByDefault) ||
+        isLegacyTypeConstructorApplication(type2,
+            isNonNullableByDefault: clientLibrary.isNonNullableByDefault)) {
+      return _getNullabilityAwareStandardUpperBound(
+              computeTypeWithoutNullabilityMarker(type1,
+                  isNonNullableByDefault: clientLibrary.isNonNullableByDefault),
+              computeTypeWithoutNullabilityMarker(type2,
+                  isNonNullableByDefault: clientLibrary.isNonNullableByDefault),
+              clientLibrary)
+          .withDeclaredNullability(Nullability.legacy);
+    }
 
     if (type1 is TypeParameterType) {
       return _getNullabilityAwareTypeParameterStandardUpperBound(
@@ -769,9 +834,11 @@
     // uses [uniteNullabilities] to compute the resulting type if the subtype
     // relation is established.
     InterfaceType typeWithoutNullabilityMarker1 =
-        computeTypeWithoutNullabilityMarker(type1, clientLibrary);
+        computeTypeWithoutNullabilityMarker(type1,
+            isNonNullableByDefault: clientLibrary.isNonNullableByDefault);
     InterfaceType typeWithoutNullabilityMarker2 =
-        computeTypeWithoutNullabilityMarker(type2, clientLibrary);
+        computeTypeWithoutNullabilityMarker(type2,
+            isNonNullableByDefault: clientLibrary.isNonNullableByDefault);
 
     if (isSubtypeOf(typeWithoutNullabilityMarker1,
         typeWithoutNullabilityMarker2, SubtypeCheckMode.withNullabilities)) {
diff --git a/pkg/kernel/lib/src/text_util.dart b/pkg/kernel/lib/src/text_util.dart
index 9fe573f..c7634ad 100644
--- a/pkg/kernel/lib/src/text_util.dart
+++ b/pkg/kernel/lib/src/text_util.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.9
+
 import '../ast.dart';
 
 String nullabilityToString(Nullability nullability) {
diff --git a/pkg/kernel/lib/src/tool/batch_util.dart b/pkg/kernel/lib/src/tool/batch_util.dart
index 9412c80..6909087 100644
--- a/pkg/kernel/lib/src/tool/batch_util.dart
+++ b/pkg/kernel/lib/src/tool/batch_util.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.batch_util;
 
 import 'dart:convert';
diff --git a/pkg/kernel/lib/src/tool/command_line_util.dart b/pkg/kernel/lib/src/tool/command_line_util.dart
index 1abadb2..858e1b1 100644
--- a/pkg/kernel/lib/src/tool/command_line_util.dart
+++ b/pkg/kernel/lib/src/tool/command_line_util.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.9
+
 import 'dart:io';
 
 import 'package:kernel/kernel.dart';
diff --git a/pkg/kernel/lib/src/tool/find_referenced_libraries.dart b/pkg/kernel/lib/src/tool/find_referenced_libraries.dart
new file mode 100644
index 0000000..73733ca
--- /dev/null
+++ b/pkg/kernel/lib/src/tool/find_referenced_libraries.dart
@@ -0,0 +1,53 @@
+// 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:kernel/ast.dart';
+import 'package:kernel/visitor.dart';
+
+Set<Library> findAllReferencedLibraries(List<Library> from) {
+  _LibraryCollector collector = new _LibraryCollector();
+  for (Library library in from) {
+    collector.visitLibrary(library);
+  }
+  return collector.allSeenLibraries;
+}
+
+bool duplicateLibrariesReachable(List<Library> from) {
+  Set<Uri> seenUris = {};
+  for (Library lib in findAllReferencedLibraries(from)) {
+    if (!seenUris.add(lib.importUri)) return true;
+  }
+  return false;
+}
+
+class _LibraryCollector extends RecursiveVisitor<Null> {
+  Set<Library> allSeenLibraries = {};
+
+  Null defaultNode(Node node) {
+    if (node is NamedNode) {
+      // Named nodes can be linked to.
+      seen(node);
+    } else if (node is Name) {
+      if (node.library != null) {
+        seen(node.library);
+      }
+    }
+    super.defaultNode(node);
+  }
+
+  Null defaultMemberReference(Member node) {
+    seen(node);
+    super.defaultMemberReference(node);
+  }
+
+  void seen(TreeNode node) {
+    TreeNode parent = node;
+    while (parent != null && parent is! Library) {
+      parent = parent.parent;
+    }
+    allSeenLibraries.add(parent);
+  }
+}
diff --git a/pkg/kernel/lib/src/types.dart b/pkg/kernel/lib/src/types.dart
index 02a4933..4dcec69 100644
--- a/pkg/kernel/lib/src/types.dart
+++ b/pkg/kernel/lib/src/types.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.9
+
 import '../ast.dart'
     show
         BottomType,
diff --git a/pkg/kernel/lib/target/changed_structure_notifier.dart b/pkg/kernel/lib/target/changed_structure_notifier.dart
index e1b2c7f..228a5d2 100644
--- a/pkg/kernel/lib/target/changed_structure_notifier.dart
+++ b/pkg/kernel/lib/target/changed_structure_notifier.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.9
+
 import 'package:kernel/ast.dart' show Class;
 
 /// Meant for notifying the backend (the compiler) that the structure has
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index be01ba0..27f5eba 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.target.targets;
 
 import '../ast.dart';
@@ -367,6 +370,8 @@
   /// 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,
@@ -434,6 +439,9 @@
       !flags.forceNoExplicitGetterCallsForTesting;
 
   @override
+  bool get supportsNewMethodInvocationEncoding => true;
+
+  @override
   String get name => 'none';
 
   @override
diff --git a/pkg/kernel/lib/testing/mock_sdk.dart b/pkg/kernel/lib/testing/mock_sdk.dart
index d4a937b..45a7d0c 100644
--- a/pkg/kernel/lib/testing/mock_sdk.dart
+++ b/pkg/kernel/lib/testing/mock_sdk.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.9
+
 const String mockSdk = """
 class Object;
 class Comparable<T>;
diff --git a/pkg/kernel/lib/testing/mock_sdk_component.dart b/pkg/kernel/lib/testing/mock_sdk_component.dart
index 180ad92..b317b60 100644
--- a/pkg/kernel/lib/testing/mock_sdk_component.dart
+++ b/pkg/kernel/lib/testing/mock_sdk_component.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.9
+
 import 'package:kernel/ast.dart';
 
 /// Returns a [Component] object containing empty definitions of core SDK
diff --git a/pkg/kernel/lib/testing/type_parser.dart b/pkg/kernel/lib/testing/type_parser.dart
index ef288ed..5842eee 100644
--- a/pkg/kernel/lib/testing/type_parser.dart
+++ b/pkg/kernel/lib/testing/type_parser.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.9
+
 import 'package:kernel/ast.dart' show Nullability;
 
 abstract class ParsedType {
diff --git a/pkg/kernel/lib/testing/type_parser_environment.dart b/pkg/kernel/lib/testing/type_parser_environment.dart
index 40484e6..48a843a 100644
--- a/pkg/kernel/lib/testing/type_parser_environment.dart
+++ b/pkg/kernel/lib/testing/type_parser_environment.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.9
+
 import "package:kernel/ast.dart"
     show
         BottomType,
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index b9d95ab..a7faeea 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.ast_to_text;
 
 import 'dart:core' hide MapEntry;
@@ -1077,16 +1080,8 @@
     writeModifier(node.isConst, 'const');
     // Only show implicit getter/setter modifiers in cases where they are
     // out of the ordinary.
-    if (node.isStatic) {
-      writeModifier(node.hasImplicitGetter, '[getter]');
-      writeModifier(node.hasImplicitSetter, '[setter]');
-    } else {
-      writeModifier(!node.hasImplicitGetter, '[no-getter]');
-      if (node.isFinal) {
-        writeModifier(node.hasImplicitSetter, '[setter]');
-      } else {
-        writeModifier(!node.hasImplicitSetter, '[no-setter]');
-      }
+    if (node.isFinal) {
+      writeModifier(node.hasSetter, '[setter]');
     }
     writeWord('field');
     writeSpace();
@@ -1125,8 +1120,24 @@
     writeModifier(node.isAbstract, 'abstract');
     writeModifier(node.isForwardingStub, 'forwarding-stub');
     writeModifier(node.isForwardingSemiStub, 'forwarding-semi-stub');
-    writeModifier(node.isMemberSignature, 'member-signature');
-    writeModifier(node.isNoSuchMethodForwarder, 'no-such-method-forwarder');
+    switch (node.stubKind) {
+      case ProcedureStubKind.Regular:
+      case ProcedureStubKind.AbstractForwardingStub:
+      case ProcedureStubKind.ConcreteForwardingStub:
+        break;
+      case ProcedureStubKind.NoSuchMethodForwarder:
+        writeWord('no-such-method-forwarder');
+        break;
+      case ProcedureStubKind.MemberSignature:
+        writeWord('member-signature');
+        break;
+      case ProcedureStubKind.AbstractMixinStub:
+        writeWord('mixin-stub');
+        break;
+      case ProcedureStubKind.ConcreteMixinStub:
+        writeWord('mixin-super-stub');
+        break;
+    }
     writeWord(procedureKindToString(node.kind));
     List<String> features = <String>[];
     if (node.enclosingLibrary.isNonNullableByDefault !=
@@ -1146,17 +1157,25 @@
     if (features.isNotEmpty) {
       writeWord("/*${features.join(',')}*/");
     }
-    if (node.isMemberSignature) {
-      writeFunction(node.function,
-          name: getMemberName(node), terminateLine: false);
-      if (node.function.body is ReturnStatement) {
-        writeSymbol(';');
-      }
-      writeSymbol(' -> ');
-      writeMemberReferenceFromReference(node.stubTargetReference);
-      endLine();
-    } else {
-      writeFunction(node.function, name: getMemberName(node));
+    switch (node.stubKind) {
+      case ProcedureStubKind.Regular:
+      case ProcedureStubKind.AbstractForwardingStub:
+      case ProcedureStubKind.ConcreteForwardingStub:
+      case ProcedureStubKind.NoSuchMethodForwarder:
+      case ProcedureStubKind.ConcreteMixinStub:
+        writeFunction(node.function, name: getMemberName(node));
+        break;
+      case ProcedureStubKind.MemberSignature:
+      case ProcedureStubKind.AbstractMixinStub:
+        writeFunction(node.function,
+            name: getMemberName(node), terminateLine: false);
+        if (node.function.body is ReturnStatement) {
+          writeSymbol(';');
+        }
+        writeSymbol(' -> ');
+        writeMemberReferenceFromReference(node.stubTargetReference);
+        endLine();
+        break;
     }
   }
 
@@ -1350,6 +1369,120 @@
     }
   }
 
+  void _writeDynamicAccessKind(DynamicAccessKind kind) {
+    switch (kind) {
+      case DynamicAccessKind.Dynamic:
+        writeSymbol('{dynamic}.');
+        break;
+      case DynamicAccessKind.Never:
+        writeSymbol('{Never}.');
+        break;
+      case DynamicAccessKind.Invalid:
+        writeSymbol('{<invalid>}.');
+        break;
+      case DynamicAccessKind.Unresolved:
+        writeSymbol('{<unresolved>}.');
+        break;
+    }
+  }
+
+  visitDynamicInvocation(DynamicInvocation node) {
+    writeExpression(node.receiver, Precedence.PRIMARY);
+    _writeDynamicAccessKind(node.kind);
+    writeName(
+      node.name,
+    );
+    writeNode(node.arguments);
+  }
+
+  void _writeFunctionAccessKind(FunctionAccessKind kind) {
+    switch (kind) {
+      case FunctionAccessKind.Function:
+      case FunctionAccessKind.FunctionType:
+        break;
+      case FunctionAccessKind.Inapplicable:
+        writeSymbol('{<inapplicable>}.');
+        break;
+      case FunctionAccessKind.Nullable:
+        writeSymbol('{<nullable>}.');
+        break;
+    }
+  }
+
+  visitFunctionInvocation(FunctionInvocation node) {
+    writeExpression(node.receiver, Precedence.PRIMARY);
+    _writeFunctionAccessKind(node.kind);
+    writeNode(node.arguments);
+    if (node.functionType != null) {
+      writeSymbol('{');
+      writeType(node.functionType);
+      writeSymbol('}');
+    }
+  }
+
+  @override
+  visitLocalFunctionInvocation(LocalFunctionInvocation node) {
+    writeVariableReference(node.variable);
+    writeNode(node.arguments);
+    writeSymbol('{');
+    writeType(node.functionType);
+    writeSymbol('}');
+  }
+
+  void _writeInstanceAccessKind(InstanceAccessKind kind) {
+    switch (kind) {
+      case InstanceAccessKind.Instance:
+      case InstanceAccessKind.Object:
+        break;
+      case InstanceAccessKind.Inapplicable:
+        writeSymbol('{<inapplicable>}.');
+        break;
+      case InstanceAccessKind.Nullable:
+        writeSymbol('{<nullable>}.');
+        break;
+    }
+  }
+
+  visitInstanceInvocation(InstanceInvocation node) {
+    writeExpression(node.receiver, Precedence.PRIMARY);
+    writeSymbol('.');
+    writeInterfaceTarget(node.name, node.interfaceTargetReference);
+    _writeInstanceAccessKind(node.kind);
+    writeNode(node.arguments);
+    writeSymbol('{');
+    writeType(node.functionType);
+    writeSymbol('}');
+  }
+
+  visitEqualsCall(EqualsCall node) {
+    int precedence = Precedence.EQUALITY;
+    writeExpression(node.left, precedence);
+    writeSpace();
+    if (node.isNot) {
+      writeSymbol('!=');
+    } else {
+      writeSymbol('==');
+    }
+    writeInterfaceTarget(Name.equalsName, node.interfaceTargetReference);
+    writeSymbol('{');
+    writeType(node.functionType);
+    writeSymbol('}');
+    writeSpace();
+    writeExpression(node.right, precedence + 1);
+  }
+
+  visitEqualsNull(EqualsNull node) {
+    writeExpression(node.expression, Precedence.EQUALITY);
+    writeSpace();
+    if (node.isNot) {
+      writeSymbol('!=');
+    } else {
+      writeSymbol('==');
+    }
+    writeSpace();
+    writeSymbol('null');
+  }
+
   visitMethodInvocation(MethodInvocation node) {
     writeExpression(node.receiver, Precedence.PRIMARY);
     writeSymbol('.');
@@ -1758,12 +1891,61 @@
     }
   }
 
+  visitDynamicGet(DynamicGet node) {
+    writeExpression(node.receiver, Precedence.PRIMARY);
+    _writeDynamicAccessKind(node.kind);
+    writeName(node.name);
+  }
+
+  visitFunctionTearOff(FunctionTearOff node) {
+    writeExpression(node.receiver, Precedence.PRIMARY);
+    writeSymbol('.');
+    writeSymbol('call');
+  }
+
+  visitInstanceGet(InstanceGet node) {
+    writeExpression(node.receiver, Precedence.PRIMARY);
+    writeSymbol('.');
+    writeInterfaceTarget(node.name, node.interfaceTargetReference);
+    _writeInstanceAccessKind(node.kind);
+    writeSymbol('{');
+    writeType(node.resultType);
+    writeSymbol('}');
+  }
+
+  visitInstanceTearOff(InstanceTearOff node) {
+    writeExpression(node.receiver, Precedence.PRIMARY);
+    writeSymbol('.');
+    writeInterfaceTarget(node.name, node.interfaceTargetReference);
+    _writeInstanceAccessKind(node.kind);
+    writeSymbol('{');
+    writeType(node.resultType);
+    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);
+    writeName(node.name);
+    writeSpaced('=');
+    writeExpression(node.value);
+  }
+
+  visitInstanceSet(InstanceSet node) {
+    writeExpression(node.receiver, Precedence.PRIMARY);
+    writeSymbol('.');
+    writeInterfaceTarget(node.name, node.interfaceTargetReference);
+    _writeInstanceAccessKind(node.kind);
+    writeSpaced('=');
+    writeExpression(node.value);
+  }
+
   visitPropertySet(PropertySet node) {
     writeExpression(node.receiver, Precedence.PRIMARY);
     writeSymbol('.');
@@ -1786,6 +1968,10 @@
     writeExpression(node.value);
   }
 
+  visitStaticTearOff(StaticTearOff node) {
+    writeMemberReferenceFromReference(node.targetReference);
+  }
+
   visitStaticGet(StaticGet node) {
     writeMemberReferenceFromReference(node.targetReference);
   }
@@ -2426,7 +2612,7 @@
   }
 }
 
-class Precedence extends ExpressionVisitor<int> {
+class Precedence implements ExpressionVisitor<int> {
   static final Precedence instance = new Precedence();
 
   static int of(Expression node) => node.accept(instance);
@@ -2478,44 +2664,189 @@
     return precedence != EQUALITY && precedence != RELATIONAL;
   }
 
+  @override
   int defaultExpression(Expression node) => EXPRESSION;
+
+  @override
   int visitInvalidExpression(InvalidExpression node) => CALLEE;
+
+  @override
   int visitMethodInvocation(MethodInvocation node) => CALLEE;
+
+  @override
+  int visitInstanceInvocation(InstanceInvocation node) => CALLEE;
+
+  @override
+  int visitDynamicInvocation(DynamicInvocation node) => CALLEE;
+
+  @override
+  int visitFunctionInvocation(FunctionInvocation node) => CALLEE;
+
+  @override
+  int visitLocalFunctionInvocation(LocalFunctionInvocation node) => CALLEE;
+
+  @override
+  int visitEqualsCall(EqualsCall node) => EQUALITY;
+
+  @override
+  int visitEqualsNull(EqualsNull node) => EQUALITY;
+
+  @override
   int visitSuperMethodInvocation(SuperMethodInvocation node) => CALLEE;
+
+  @override
   int visitStaticInvocation(StaticInvocation node) => CALLEE;
+
+  @override
   int visitConstructorInvocation(ConstructorInvocation node) => CALLEE;
+
+  @override
   int visitNot(Not node) => PREFIX;
+
+  @override
   int visitNullCheck(NullCheck node) => PRIMARY;
+
+  @override
   int visitLogicalExpression(LogicalExpression node) =>
       binaryPrecedence[logicalExpressionOperatorToString(node.operatorEnum)];
+
+  @override
   int visitConditionalExpression(ConditionalExpression node) => CONDITIONAL;
+
+  @override
   int visitStringConcatenation(StringConcatenation node) => PRIMARY;
+
+  @override
   int visitIsExpression(IsExpression node) => RELATIONAL;
+
+  @override
   int visitAsExpression(AsExpression node) => RELATIONAL;
+
+  @override
   int visitSymbolLiteral(SymbolLiteral node) => PRIMARY;
+
+  @override
   int visitTypeLiteral(TypeLiteral node) => PRIMARY;
+
+  @override
   int visitThisExpression(ThisExpression node) => CALLEE;
+
+  @override
   int visitRethrow(Rethrow node) => PRIMARY;
+
+  @override
   int visitThrow(Throw node) => EXPRESSION;
+
+  @override
   int visitListLiteral(ListLiteral node) => PRIMARY;
+
+  @override
   int visitSetLiteral(SetLiteral node) => PRIMARY;
+
+  @override
   int visitMapLiteral(MapLiteral node) => PRIMARY;
+
+  @override
   int visitAwaitExpression(AwaitExpression node) => PREFIX;
+
+  @override
   int visitFunctionExpression(FunctionExpression node) => EXPRESSION;
+
+  @override
   int visitStringLiteral(StringLiteral node) => CALLEE;
+
+  @override
   int visitIntLiteral(IntLiteral node) => CALLEE;
+
+  @override
   int visitDoubleLiteral(DoubleLiteral node) => CALLEE;
+
+  @override
   int visitBoolLiteral(BoolLiteral node) => CALLEE;
+
+  @override
   int visitNullLiteral(NullLiteral node) => CALLEE;
+
+  @override
   int visitVariableGet(VariableGet node) => PRIMARY;
+
+  @override
   int visitVariableSet(VariableSet node) => EXPRESSION;
+
+  @override
   int visitPropertyGet(PropertyGet node) => PRIMARY;
+
+  @override
+  int visitInstanceGet(InstanceGet node) => PRIMARY;
+
+  @override
+  int visitDynamicGet(DynamicGet node) => PRIMARY;
+
+  @override
+  int visitInstanceTearOff(InstanceTearOff node) => PRIMARY;
+
+  @override
+  int visitFunctionTearOff(FunctionTearOff node) => PRIMARY;
+
+  @override
   int visitPropertySet(PropertySet node) => EXPRESSION;
+
+  @override
   int visitSuperPropertyGet(SuperPropertyGet node) => PRIMARY;
+
+  @override
   int visitSuperPropertySet(SuperPropertySet node) => EXPRESSION;
+
+  @override
   int visitStaticGet(StaticGet node) => PRIMARY;
+
+  @override
+  int visitStaticTearOff(StaticTearOff node) => PRIMARY;
+
+  @override
   int visitStaticSet(StaticSet node) => EXPRESSION;
+
+  @override
   int visitLet(Let node) => EXPRESSION;
+
+  @override
+  int defaultBasicLiteral(BasicLiteral node) => CALLEE;
+
+  @override
+  int visitBlockExpression(BlockExpression node) => EXPRESSION;
+
+  @override
+  int visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) => EXPRESSION;
+
+  @override
+  int visitConstantExpression(ConstantExpression node) => EXPRESSION;
+
+  @override
+  int visitDynamicSet(DynamicSet node) => EXPRESSION;
+
+  @override
+  int visitFileUriExpression(FileUriExpression node) => EXPRESSION;
+
+  @override
+  int visitInstanceCreation(InstanceCreation node) => EXPRESSION;
+
+  @override
+  int visitInstanceSet(InstanceSet node) => EXPRESSION;
+
+  @override
+  int visitInstantiation(Instantiation node) => EXPRESSION;
+
+  @override
+  int visitListConcatenation(ListConcatenation node) => EXPRESSION;
+
+  @override
+  int visitLoadLibrary(LoadLibrary node) => EXPRESSION;
+
+  @override
+  int visitMapConcatenation(MapConcatenation node) => EXPRESSION;
+
+  @override
+  int visitSetConcatenation(SetConcatenation node) => EXPRESSION;
 }
 
 String procedureKindToString(ProcedureKind kind) {
diff --git a/pkg/kernel/lib/text/serializer_combinators.dart b/pkg/kernel/lib/text/serializer_combinators.dart
index dc8fe50..3bd9e1d 100644
--- a/pkg/kernel/lib/text/serializer_combinators.dart
+++ b/pkg/kernel/lib/text/serializer_combinators.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.9
+
 library kernel.serializer_combinators;
 
 import 'dart:convert' show json;
diff --git a/pkg/kernel/lib/text/text_reader.dart b/pkg/kernel/lib/text/text_reader.dart
index a6867e7..21fd497 100644
--- a/pkg/kernel/lib/text/text_reader.dart
+++ b/pkg/kernel/lib/text/text_reader.dart
@@ -17,7 +17,7 @@
 //
 // We use an iterator to read S-expressions.  The iterator produces a stream
 // of atoms (strings) and nested iterators (S-lists).
-class TextIterator implements Iterator<Object /* String | TextIterator */ > {
+class TextIterator implements Iterator<Object? /* String? | TextIterator? */ > {
   static int space = ' '.codeUnitAt(0);
   static int lparen = '('.codeUnitAt(0);
   static int rparen = ')'.codeUnitAt(0);
@@ -39,7 +39,7 @@
   // Consume the rest of a nested S-expression and the closing delimiter.
   void skipToEndOfNested() {
     if (current is TextIterator) {
-      TextIterator it = current;
+      TextIterator it = current as TextIterator;
       while (it.moveNext()) {}
       index = it.index + 1;
     }
@@ -77,7 +77,7 @@
   }
 
   @override
-  Object current = null;
+  Object? current = null;
 
   @override
   bool moveNext() {
diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart
index 0b983c2..0298ad7 100644
--- a/pkg/kernel/lib/text/text_serialization_verifier.dart
+++ b/pkg/kernel/lib/text/text_serialization_verifier.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.9
+
 import 'dart:convert' show json;
 
 import '../ast.dart';
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index a1c93ab..f81886b 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.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.9
+
 library kernel.text_serializer;
 
 import '../ast.dart';
@@ -1460,8 +1462,6 @@
   Field.FlagFinal: "final",
   Field.FlagConst: "const",
   Field.FlagStatic: "static",
-  Field.FlagHasImplicitGetter: "has-implicit-getter",
-  Field.FlagHasImplicitSetter: "has-implicit-setter",
   Field.FlagCovariant: "covariant",
   Field.FlagGenericCovariantImpl: "generic-covariant-impl",
   Field.FlagLate: "late",
@@ -1537,7 +1537,7 @@
 
   String tag(Member node) {
     if (node is Field) {
-      return "field";
+      return node.hasSetter ? "mutable-field" : "immutable-field";
     } else if (node is Constructor) {
       return "constructor";
     } else if (node is RedirectingFactoryConstructor) {
@@ -1563,10 +1563,18 @@
   }
 }
 
-TextSerializer<Field> fieldSerializer =
+TextSerializer<Field> mutableFieldSerializer =
     Wrapped<Tuple4<Name, int, DartType, Expression>, Field>(
         (w) => Tuple4(w.name, w.flags, w.type, w.initializer),
-        (u) => Field(u.first, type: u.third, initializer: u.fourth)
+        (u) => Field.mutable(u.first, type: u.third, initializer: u.fourth)
+          ..flags = u.second,
+        Tuple4Serializer(nameSerializer, fieldFlagsSerializer,
+            dartTypeSerializer, Optional(expressionSerializer)));
+
+TextSerializer<Field> immutableFieldSerializer =
+    Wrapped<Tuple4<Name, int, DartType, Expression>, Field>(
+        (w) => Tuple4(w.name, w.flags, w.type, w.initializer),
+        (u) => Field.immutable(u.first, type: u.third, initializer: u.fourth)
           ..flags = u.second,
         Tuple4Serializer(nameSerializer, fieldFlagsSerializer,
             dartTypeSerializer, Optional(expressionSerializer)));
@@ -2191,7 +2199,8 @@
     "local-fun": functionDeclarationSerializer,
   });
   memberSerializer.registerTags({
-    "field": fieldSerializer,
+    "mutable-field": mutableFieldSerializer,
+    "immutable-field": immutableFieldSerializer,
     "method": methodSerializer,
     "getter": getterSerializer,
     "setter": setterSerializer,
diff --git a/pkg/kernel/lib/transformations/async.dart b/pkg/kernel/lib/transformations/async.dart
index 37c9ea9..e8ac7ba 100644
--- a/pkg/kernel/lib/transformations/async.dart
+++ b/pkg/kernel/lib/transformations/async.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.9
+
 library kernel.transformations.async;
 
 import '../kernel.dart';
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index cf5e16f..0df3e84 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.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.9
+
 library kernel.transformations.continuation;
 
 import 'dart:math' as math;
diff --git a/pkg/kernel/lib/transformations/empty.dart b/pkg/kernel/lib/transformations/empty.dart
index 5a264dd7..c07883b 100644
--- a/pkg/kernel/lib/transformations/empty.dart
+++ b/pkg/kernel/lib/transformations/empty.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.9
+
 library kernel.transformations.empty;
 
 import '../ast.dart';
diff --git a/pkg/kernel/lib/transformations/flags.dart b/pkg/kernel/lib/transformations/flags.dart
index 32cd627..cb6bafd 100644
--- a/pkg/kernel/lib/transformations/flags.dart
+++ b/pkg/kernel/lib/transformations/flags.dart
@@ -1,3 +1,9 @@
+// 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.
+
+// @dart = 2.9
+
 library kernel.transformations.flags;
 
 import '../ast.dart';
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index 345d452..8e17efa 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.transformations.mixin_full_resolution;
 
 import '../ast.dart';
@@ -99,38 +102,53 @@
     var substitution = getSubstitutionMap(class_.mixedInType);
     var cloner = new CloneVisitorWithMembers(typeSubstitution: substitution);
 
-    // When we copy a field from the mixed in class, we remove any
-    // forwarding-stub getters/setters from the superclass, but copy their
-    // covariance-bits onto the new field.
-    var nonSetters = <Name, Procedure>{};
-    var setters = <Name, Procedure>{};
-    for (var procedure in class_.procedures) {
-      if (procedure.isSetter) {
-        setters[procedure.name] = procedure;
-      } else {
-        nonSetters[procedure.name] = procedure;
-      }
-    }
-
     IndexedLibrary indexedLibrary =
         referenceFromIndex?.lookupLibrary(enclosingLibrary);
     IndexedClass indexedClass = indexedLibrary?.lookupIndexedClass(class_.name);
 
-    for (var field in class_.mixin.fields) {
-      Field clone =
-          cloner.cloneField(field, indexedClass?.lookupField(field.name.text));
-      Procedure setter = setters[field.name];
-      if (setter != null) {
-        setters.remove(field.name);
-        VariableDeclaration parameter =
-            setter.function.positionalParameters.first;
-        clone.isGenericCovariantImpl = parameter.isGenericCovariantImpl;
+    if (class_.mixin.fields.isNotEmpty) {
+      // When we copy a field from the mixed in class, we remove any
+      // forwarding-stub getters/setters from the superclass, but copy their
+      // covariance-bits onto the new field.
+      var nonSetters = <Name, Procedure>{};
+      var setters = <Name, Procedure>{};
+      for (var procedure in class_.procedures) {
+        if (procedure.isSetter) {
+          setters[procedure.name] = procedure;
+        } else {
+          nonSetters[procedure.name] = procedure;
+        }
       }
-      nonSetters.remove(field.name);
-      class_.addField(clone);
+
+      for (var field in class_.mixin.fields) {
+        Reference getterReference =
+            indexedClass?.lookupGetterReference(field.name);
+        Reference setterReference =
+            indexedClass?.lookupSetterReference(field.name);
+        if (getterReference == null) {
+          getterReference = nonSetters[field.name]?.reference;
+          getterReference?.canonicalName?.unbind();
+        }
+        if (setterReference == null) {
+          setterReference = setters[field.name]?.reference;
+          setterReference?.canonicalName?.unbind();
+        }
+        Field clone =
+            cloner.cloneField(field, getterReference, setterReference);
+        Procedure setter = setters[field.name];
+        if (setter != null) {
+          setters.remove(field.name);
+          VariableDeclaration parameter =
+              setter.function.positionalParameters.first;
+          clone.isCovariant = parameter.isCovariant;
+          clone.isGenericCovariantImpl = parameter.isGenericCovariantImpl;
+        }
+        nonSetters.remove(field.name);
+        class_.addField(clone);
+      }
+      class_.procedures.clear();
+      class_.procedures..addAll(nonSetters.values)..addAll(setters.values);
     }
-    class_.procedures.clear();
-    class_.procedures..addAll(nonSetters.values)..addAll(setters.values);
 
     // Existing procedures in the class should only be forwarding stubs.
     // Replace them with methods from the mixin class if they have the same
@@ -149,13 +167,11 @@
       // NoSuchMethod forwarders aren't cloned.
       if (procedure.isNoSuchMethodForwarder) continue;
 
-      Procedure referenceFrom;
+      Reference reference;
       if (procedure.isSetter) {
-        referenceFrom =
-            indexedClass?.lookupProcedureSetter(procedure.name.text);
+        reference = indexedClass?.lookupSetterReference(procedure.name);
       } else {
-        referenceFrom =
-            indexedClass?.lookupProcedureNotSetter(procedure.name.text);
+        reference = indexedClass?.lookupGetterReference(procedure.name);
       }
 
       // Linear search for a forwarding stub with the same name.
@@ -179,9 +195,9 @@
         }
       }
       if (originalIndex != null) {
-        referenceFrom ??= class_.procedures[originalIndex];
+        reference ??= class_.procedures[originalIndex]?.reference;
       }
-      Procedure clone = cloner.cloneProcedure(procedure, referenceFrom);
+      Procedure clone = cloner.cloneProcedure(procedure, reference);
       if (originalIndex != null) {
         Procedure originalProcedure = class_.procedures[originalIndex];
         FunctionNode src = originalProcedure.function;
@@ -196,10 +212,14 @@
         // TODO(kernel team): The named parameters are not sorted,
         // this might not be correct.
         for (int j = 0; j < src.namedParameters.length; ++j) {
-          dst.namedParameters[j].flags = src.namedParameters[j].flags;
+          dst.namedParameters[j].isCovariant =
+              src.namedParameters[j].isCovariant;
+          dst.namedParameters[j].isGenericCovariantImpl =
+              src.namedParameters[j].isGenericCovariantImpl;
         }
 
         class_.procedures[originalIndex] = clone;
+        clone.parent = class_;
       } else {
         class_.addProcedure(clone);
       }
diff --git a/pkg/kernel/lib/transformations/scanner.dart b/pkg/kernel/lib/transformations/scanner.dart
index ce4b9fc..5aac0a8 100644
--- a/pkg/kernel/lib/transformations/scanner.dart
+++ b/pkg/kernel/lib/transformations/scanner.dart
@@ -1,3 +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
+
 library kernel.transformations.scanner;
 
 import '../ast.dart';
diff --git a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
index f68a5b6..2eeb952 100644
--- a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
+++ b/pkg/kernel/lib/transformations/track_widget_constructor_locations.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.9
+
 library kernel.transformations.track_widget_constructor_locations;
 
 import 'package:meta/meta.dart';
@@ -375,15 +377,12 @@
       _locationFieldName,
       _hasCreationLocationClass.enclosingLibrary,
     );
-    final Field locationField = new Field(fieldName,
+    final Field locationField = new Field.immutable(fieldName,
         type:
             new InterfaceType(_locationClass, clazz.enclosingLibrary.nullable),
         isFinal: true,
         getterReference: clazz.reference.canonicalName
             ?.getChildFromFieldWithName(fieldName)
-            ?.reference,
-        setterReference: clazz.reference.canonicalName
-            ?.getChildFromFieldSetterWithName(fieldName)
             ?.reference);
     clazz.addField(locationField);
 
diff --git a/pkg/kernel/lib/transformations/type_casts_optimizer.dart b/pkg/kernel/lib/transformations/type_casts_optimizer.dart
index 4df790f..5f901e6 100644
--- a/pkg/kernel/lib/transformations/type_casts_optimizer.dart
+++ b/pkg/kernel/lib/transformations/type_casts_optimizer.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.9
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/type_environment.dart'
     show StaticTypeContext, SubtypeCheckMode, TypeEnvironment;
diff --git a/pkg/kernel/lib/transformations/value_class.dart b/pkg/kernel/lib/transformations/value_class.dart
index 5e21e5c..0264e0a 100644
--- a/pkg/kernel/lib/transformations/value_class.dart
+++ b/pkg/kernel/lib/transformations/value_class.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.9
+
 library kernel.transformations.value_class;
 
 import 'package:kernel/type_environment.dart';
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 4ec2480..03707fb 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.type_algebra;
 
 import 'ast.dart';
@@ -93,6 +96,14 @@
   return new _FreeFunctionTypeVariableVisitor().visit(type);
 }
 
+/// Returns `true` if [type] contains any free type variables
+///
+/// Returns `true` if [type] contains a [TypeParameterType] that doesn't refer
+/// to an enclosing generic [FunctionType] within [type].
+bool containsFreeTypeVariables(DartType type) {
+  return new _FreeTypeVariableVisitor().visit(type);
+}
+
 /// Generates a fresh copy of the given type parameters, with their bounds
 /// substituted to reference the new parameters.
 ///
@@ -749,6 +760,62 @@
   }
 }
 
+class _FreeTypeVariableVisitor implements DartTypeVisitor<bool> {
+  final Set<TypeParameter> variables = new Set<TypeParameter>();
+
+  _FreeTypeVariableVisitor();
+
+  bool visit(DartType node) => node.accept(this);
+
+  bool defaultDartType(DartType node) {
+    throw new UnsupportedError("Unsupported type $node (${node.runtimeType}.");
+  }
+
+  bool visitNamedType(NamedType node) {
+    return visit(node.type);
+  }
+
+  bool visitBottomType(BottomType node) => false;
+  bool visitNeverType(NeverType node) => false;
+  bool visitNullType(NullType node) => false;
+  bool visitInvalidType(InvalidType node) => false;
+  bool visitDynamicType(DynamicType node) => false;
+  bool visitVoidType(VoidType node) => false;
+
+  bool visitInterfaceType(InterfaceType node) {
+    return node.typeArguments.any(visit);
+  }
+
+  bool visitFutureOrType(FutureOrType node) {
+    return visit(node.typeArgument);
+  }
+
+  bool visitTypedefType(TypedefType node) {
+    return node.typeArguments.any(visit);
+  }
+
+  bool visitFunctionType(FunctionType node) {
+    variables.addAll(node.typeParameters);
+    bool result = node.typeParameters.any(handleTypeParameter) ||
+        node.positionalParameters.any(visit) ||
+        node.namedParameters.any(visitNamedType) ||
+        visit(node.returnType);
+    variables.removeAll(node.typeParameters);
+    return result;
+  }
+
+  bool visitTypeParameterType(TypeParameterType node) {
+    return !variables.contains(node.parameter);
+  }
+
+  bool handleTypeParameter(TypeParameter node) {
+    assert(variables.contains(node));
+    if (node.bound.accept(this)) return true;
+    if (node.defaultType == null) return false;
+    return node.defaultType.accept(this);
+  }
+}
+
 Nullability uniteNullabilities(Nullability a, Nullability b) {
   if (a == Nullability.nullable || b == Nullability.nullable) {
     return Nullability.nullable;
@@ -1004,9 +1071,7 @@
   @override
   DartType visitTypeParameterType(TypeParameterType node) {
     if (eliminationTargets.contains(node.parameter)) {
-      return typeParameterReplacement.withDeclaredNullability(
-          uniteNullabilities(
-              typeParameterReplacement.nullability, node.nullability));
+      return typeParameterReplacement;
     }
     return super.visitTypeParameterType(node);
   }
@@ -1020,14 +1085,18 @@
 /// returning the non-nullable version of type int.  In case of
 /// [TypeParameterType]s, the result may be either [Nullability.nonNullable] or
 /// [Nullability.undetermined], depending on the bound.
-DartType computeTypeWithoutNullabilityMarker(
-    DartType type, Library clientLibrary) {
+DartType computeTypeWithoutNullabilityMarker(DartType type,
+    {bool isNonNullableByDefault}) {
+  assert(isNonNullableByDefault != null);
+
   if (type is TypeParameterType) {
     if (type.promotedBound == null) {
       // The default nullability for library is used when there are no
       // nullability markers on the type.
-      return new TypeParameterType.withDefaultNullabilityForLibrary(
-          type.parameter, clientLibrary);
+      return new TypeParameterType(
+          type.parameter,
+          _defaultNullabilityForTypeParameterType(type.parameter,
+              isNonNullableByDefault: isNonNullableByDefault));
     } else {
       // Intersection types can't be arguments to the nullable and the legacy
       // type constructors, so nothing can be peeled off.
@@ -1048,15 +1117,92 @@
 /// type parameter.  Some examples of types declared without nullability markers
 /// are T% and S, where T and S are type parameters such that T extends Object?
 /// and S extends Object.
-bool isTypeParameterTypeWithoutNullabilityMarker(
-    TypeParameterType type, Library clientLibrary) {
+bool isTypeParameterTypeWithoutNullabilityMarker(TypeParameterType type,
+    {bool isNonNullableByDefault}) {
+  assert(isNonNullableByDefault != null);
+
   // The default nullability for library is used when there are no nullability
   // markers on the type.
   return type.promotedBound == null &&
       type.declaredNullability ==
-          new TypeParameterType.withDefaultNullabilityForLibrary(
-                  type.parameter, clientLibrary)
-              .declaredNullability;
+          _defaultNullabilityForTypeParameterType(type.parameter,
+              isNonNullableByDefault: isNonNullableByDefault);
+}
+
+bool isTypeWithoutNullabilityMarker(DartType type,
+    {bool isNonNullableByDefault}) {
+  assert(isNonNullableByDefault != null);
+  return !type.accept(new _NullabilityMarkerDetector(isNonNullableByDefault));
+}
+
+class _NullabilityMarkerDetector implements DartTypeVisitor<bool> {
+  final bool isNonNullableByDefault;
+
+  const _NullabilityMarkerDetector(this.isNonNullableByDefault);
+
+  @override
+  bool defaultDartType(DartType node) {
+    throw new UnsupportedError("Unsupported operation: "
+        "_NullabilityMarkerDetector(${node.runtimeType})");
+  }
+
+  @override
+  bool visitBottomType(BottomType node) => false;
+
+  @override
+  bool visitDynamicType(DynamicType node) => false;
+
+  @override
+  bool visitFunctionType(FunctionType node) {
+    assert(node.declaredNullability != Nullability.undetermined);
+    return node.declaredNullability == Nullability.nullable ||
+        node.declaredNullability == Nullability.legacy;
+  }
+
+  @override
+  bool visitFutureOrType(FutureOrType node) {
+    if (node.declaredNullability == Nullability.nullable ||
+        node.declaredNullability == Nullability.legacy) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  bool visitInterfaceType(InterfaceType node) {
+    assert(node.declaredNullability != Nullability.undetermined);
+    return node.declaredNullability == Nullability.nullable ||
+        node.declaredNullability == Nullability.legacy;
+  }
+
+  @override
+  bool visitInvalidType(InvalidType node) => false;
+
+  @override
+  bool visitNeverType(NeverType node) {
+    assert(node.declaredNullability != Nullability.undetermined);
+    return node.declaredNullability == Nullability.nullable ||
+        node.declaredNullability == Nullability.legacy;
+  }
+
+  @override
+  bool visitNullType(NullType node) => false;
+
+  @override
+  bool visitTypeParameterType(TypeParameterType node) {
+    return !isTypeParameterTypeWithoutNullabilityMarker(node,
+        isNonNullableByDefault: isNonNullableByDefault);
+  }
+
+  @override
+  bool visitTypedefType(TypedefType node) {
+    assert(node.declaredNullability != Nullability.undetermined);
+    return node.declaredNullability == Nullability.nullable ||
+        node.declaredNullability == Nullability.legacy;
+  }
+
+  @override
+  bool visitVoidType(VoidType node) => false;
 }
 
 /// Returns true if [type] is an application of the nullable type constructor.
@@ -1067,6 +1213,10 @@
 /// and Null are nullable, but aren't considered applications of the nullable
 /// type constructor.
 bool isNullableTypeConstructorApplication(DartType type) {
+  if (type is TypeParameterType && type.promotedBound != null) {
+    // Promoted types are never considered applications of ?.
+    return false;
+  }
   return type.declaredNullability == Nullability.nullable &&
       type is! DynamicType &&
       type is! VoidType &&
@@ -1078,23 +1228,28 @@
 /// A type is considered an application of the legacy type constructor if it was
 /// declared within a legacy library and is not one of exempt types, such as
 /// dynamic or void.
-bool isLegacyTypeConstructorApplication(DartType type, Library clientLibrary) {
+bool isLegacyTypeConstructorApplication(DartType type,
+    {bool isNonNullableByDefault}) {
+  assert(isNonNullableByDefault != null);
+
   if (type is TypeParameterType) {
-    if (type.promotedBound == null) {
-      // The legacy nullability is considered an application of the legacy
-      // nullability constructor if it doesn't match the default nullability
-      // of the type-parameter type for the library.
-      return type.declaredNullability == Nullability.legacy &&
-          type.declaredNullability !=
-              new TypeParameterType.withDefaultNullabilityForLibrary(
-                      type.parameter, clientLibrary)
-                  .declaredNullability;
-    } else {
-      return false;
-    }
+    // The legacy nullability is considered an application of the legacy
+    // nullability constructor if it doesn't match the default nullability
+    // of the type-parameter type for the library.
+    return type.declaredNullability == Nullability.legacy &&
+        !isTypeParameterTypeWithoutNullabilityMarker(type,
+            isNonNullableByDefault: isNonNullableByDefault);
   } else if (type is InvalidType) {
     return false;
   } else {
     return type.declaredNullability == Nullability.legacy;
   }
 }
+
+Nullability _defaultNullabilityForTypeParameterType(TypeParameter parameter,
+    {bool isNonNullableByDefault}) {
+  assert(isNonNullableByDefault != null);
+  return isNonNullableByDefault
+      ? TypeParameterType.computeNullabilityFromBound(parameter)
+      : Nullability.legacy;
+}
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 0e24e6f..4748f26 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.type_checker;
 
 import 'ast.dart';
@@ -1076,4 +1079,122 @@
 
   @override
   visitInvalidInitializer(InvalidInitializer node) {}
+
+  @override
+  DartType visitDynamicGet(DynamicGet node) {
+    DartType receiverType = visitExpression(node.receiver);
+    checkUnresolvedInvocation(receiverType, node);
+    return const DynamicType();
+  }
+
+  @override
+  DartType visitDynamicInvocation(DynamicInvocation node) {
+    DartType receiverType = visitExpression(node.receiver);
+    checkUnresolvedInvocation(receiverType, node);
+    node.arguments.positional.forEach(visitExpression);
+    node.arguments.named
+        .forEach((NamedExpression n) => visitExpression(n.value));
+    return const DynamicType();
+  }
+
+  @override
+  DartType visitDynamicSet(DynamicSet node) {
+    DartType value = visitExpression(node.value);
+    final DartType receiver = visitExpression(node.receiver);
+    checkUnresolvedInvocation(receiver, node);
+    return value;
+  }
+
+  @override
+  DartType visitEqualsCall(EqualsCall node) {
+    visitExpression(node.left);
+    visitExpression(node.right);
+    // TODO(johnniwinther): Return Never as type for equals call on Never.
+    return environment.coreTypes.boolLegacyRawType;
+  }
+
+  @override
+  DartType visitEqualsNull(EqualsNull node) {
+    visitExpression(node.expression);
+    return environment.coreTypes.boolLegacyRawType;
+  }
+
+  @override
+  DartType visitFunctionInvocation(FunctionInvocation node) {
+    DartType receiverType = visitExpression(node.receiver);
+    checkUnresolvedInvocation(receiverType, node);
+    node.arguments.positional.forEach(visitExpression);
+    node.arguments.named
+        .forEach((NamedExpression n) => visitExpression(n.value));
+    // TODO(johnniwinther): Return the correct result type.
+    return const DynamicType();
+  }
+
+  @override
+  DartType visitInstanceGet(InstanceGet node) {
+    Substitution receiver =
+        getReceiverType(node, node.receiver, node.interfaceTarget);
+    return receiver.substituteType(node.interfaceTarget.getterType);
+  }
+
+  @override
+  DartType visitInstanceInvocation(InstanceInvocation node) {
+    // TODO(johnniwinther): Use embedded static type.
+    Member target = node.interfaceTarget;
+    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 {
+      visitExpression(node.receiver);
+      return handleCall(node.arguments, target.getterType,
+          receiver: getReceiverType(node, node.receiver, node.interfaceTarget));
+    }
+  }
+
+  @override
+  DartType visitInstanceSet(InstanceSet node) {
+    DartType value = visitExpression(node.value);
+    Substitution receiver =
+        getReceiverType(node, node.receiver, node.interfaceTarget);
+    checkAssignable(
+        node.value,
+        value,
+        receiver.substituteType(node.interfaceTarget.setterType,
+            contravariant: true));
+    return value;
+  }
+
+  @override
+  DartType visitInstanceTearOff(InstanceTearOff node) {
+    Substitution receiver =
+        getReceiverType(node, node.receiver, node.interfaceTarget);
+    return receiver.substituteType(node.interfaceTarget.getterType);
+  }
+
+  @override
+  DartType visitLocalFunctionInvocation(LocalFunctionInvocation node) {
+    checkUnresolvedInvocation(node.functionType, node);
+    node.arguments.positional.forEach(visitExpression);
+    node.arguments.named
+        .forEach((NamedExpression n) => visitExpression(n.value));
+    // TODO(johnniwinther): Return the correct result type.
+    return const DynamicType();
+  }
+
+  @override
+  DartType visitStaticTearOff(StaticTearOff node) {
+    return node.target.getterType;
+  }
+
+  @override
+  DartType visitFunctionTearOff(FunctionTearOff node) {
+    DartType receiverType = visitExpression(node.receiver);
+    checkUnresolvedInvocation(receiverType, node);
+    // TODO(johnniwinther): Return the correct result type.
+    return const DynamicType();
+  }
 }
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 7e0dedc..4b993f5 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.type_environment;
 
 import 'package:kernel/type_algebra.dart';
diff --git a/pkg/kernel/lib/util/graph.dart b/pkg/kernel/lib/util/graph.dart
index f54f8a4..4119f1b 100644
--- a/pkg/kernel/lib/util/graph.dart
+++ b/pkg/kernel/lib/util/graph.dart
@@ -34,7 +34,7 @@
 
     // Step 3: For each edge from [vertex] to a neighboring vertex [neighbor]:
     for (T neighbor in graph.neighborsOf(vertex)) {
-      int neighborPreorderNumber = preorderNumbers[neighbor];
+      int? neighborPreorderNumber = preorderNumbers[neighbor];
       if (neighborPreorderNumber == null) {
         // If the preorder number of [neighbor] has not yet been assigned,
         // recursively search [neighbor];
@@ -46,7 +46,7 @@
         // * Repeatedly pop vertices from [candidates] until the top element of
         //   [candidates] has a preorder number less than or equal to the
         //   preorder number of [neighbor].
-        while (preorderNumbers[candidates.last] > neighborPreorderNumber) {
+        while (preorderNumbers[candidates.last]! > neighborPreorderNumber) {
           candidates.removeLast();
         }
       }
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index 0db1f2b..e40ab133 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.checks;
 
 import 'ast.dart';
@@ -77,9 +80,12 @@
 
   Class currentClass;
 
+  Extension currentExtension;
+
   TreeNode currentParent;
 
-  TreeNode get currentClassOrMember => currentMember ?? currentClass;
+  TreeNode get currentClassOrExtensionOrMember =>
+      currentMember ?? currentClass ?? currentExtension;
 
   static void check(Component component, {bool isOutline, bool afterConst}) {
     component.accept(
@@ -108,7 +114,7 @@
   }
 
   problem(TreeNode node, String details, {TreeNode context}) {
-    context ??= currentClassOrMember;
+    context ??= currentClassOrExtensionOrMember;
     throw new VerificationError(context, node, details);
   }
 
@@ -239,11 +245,13 @@
   }
 
   visitExtension(Extension node) {
+    currentExtension = node;
     declareTypeParameters(node.typeParameters);
     final TreeNode oldParent = enterParent(node);
     node.visitChildren(this);
     exitParent(oldParent);
     undeclareTypeParameters(node.typeParameters);
+    currentExtension = null;
   }
 
   void checkTypedef(Typedef node) {
@@ -284,6 +292,27 @@
       problem(node, "The const field '${node.name.text}' should be static",
           context: node);
     }
+    bool isImmutable = node.isLate
+        ? (node.isFinal && node.initializer != null)
+        : (node.isFinal || node.isConst);
+    if (isImmutable == node.hasSetter) {
+      if (node.hasSetter) {
+        problem(node,
+            "The immutable field '${node.name.text}' has a setter reference",
+            context: node);
+      } else {
+        if (isOutline && node.isLate) {
+          // TODO(johnniwinther): Should we add a flag on Field for having
+          // a declared initializer?
+          // The initializer is not included in the outline so we can't tell
+          // whether it has an initializer or not.
+        } else {
+          problem(node,
+              "The mutable field '${node.name.text}' has no setter reference",
+              context: node);
+        }
+      }
+    }
     classTypeParametersAreInScope = !node.isStatic;
     node.initializer?.accept(this);
     node.type.accept(this);
@@ -322,14 +351,14 @@
       problem(
           node, "Member signature must have a member signature origin $node.");
     }
-    if (node.forwardingStubInterfaceTarget != null &&
+    if (node.abstractForwardingStubTarget != null &&
         !(node.isForwardingStub || node.isForwardingSemiStub)) {
       problem(
           node,
           "Only forwarding stubs can have a forwarding stub interface target "
           "$node.");
     }
-    if (node.forwardingStubSuperTarget != null &&
+    if (node.concreteForwardingStubTarget != null &&
         !(node.isForwardingStub || node.isForwardingSemiStub)) {
       problem(
           node,
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index fdabdc6..fefa970 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.ast.visitor;
 
 import 'dart:core' hide MapEntry;
@@ -17,12 +20,26 @@
   R visitInvalidExpression(InvalidExpression node) => defaultExpression(node);
   R visitVariableGet(VariableGet node) => defaultExpression(node);
   R visitVariableSet(VariableSet node) => defaultExpression(node);
+  R visitDynamicGet(DynamicGet node) => defaultExpression(node);
+  R visitDynamicSet(DynamicSet node) => defaultExpression(node);
+  R visitFunctionTearOff(FunctionTearOff node) => defaultExpression(node);
+  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);
   R visitStaticSet(StaticSet node) => defaultExpression(node);
+  R visitStaticTearOff(StaticTearOff node) => defaultExpression(node);
+  R visitLocalFunctionInvocation(LocalFunctionInvocation node) =>
+      defaultExpression(node);
+  R visitDynamicInvocation(DynamicInvocation node) => defaultExpression(node);
+  R visitFunctionInvocation(FunctionInvocation node) => defaultExpression(node);
+  R visitInstanceInvocation(InstanceInvocation node) => 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);
@@ -142,12 +159,26 @@
   R visitInvalidExpression(InvalidExpression node) => defaultExpression(node);
   R visitVariableGet(VariableGet node) => defaultExpression(node);
   R visitVariableSet(VariableSet node) => defaultExpression(node);
+  R visitDynamicGet(DynamicGet node) => defaultExpression(node);
+  R visitDynamicSet(DynamicSet node) => defaultExpression(node);
+  R visitFunctionTearOff(FunctionTearOff node) => defaultExpression(node);
+  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);
   R visitStaticSet(StaticSet node) => defaultExpression(node);
+  R visitStaticTearOff(StaticTearOff node) => defaultExpression(node);
+  R visitLocalFunctionInvocation(LocalFunctionInvocation node) =>
+      defaultExpression(node);
+  R visitDynamicInvocation(DynamicInvocation node) => defaultExpression(node);
+  R visitFunctionInvocation(FunctionInvocation node) => defaultExpression(node);
+  R visitInstanceInvocation(InstanceInvocation node) => 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);
@@ -661,6 +692,14 @@
       defaultExpression(node, arg);
   R visitVariableGet(VariableGet node, T arg) => defaultExpression(node, arg);
   R visitVariableSet(VariableSet node, T arg) => defaultExpression(node, arg);
+  R visitDynamicGet(DynamicGet node, T arg) => defaultExpression(node, arg);
+  R visitDynamicSet(DynamicSet node, T arg) => defaultExpression(node, arg);
+  R visitFunctionTearOff(FunctionTearOff node, T arg) =>
+      defaultExpression(node, arg);
+  R visitInstanceGet(InstanceGet node, T arg) => defaultExpression(node, arg);
+  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) =>
@@ -669,6 +708,18 @@
       defaultExpression(node, arg);
   R visitStaticGet(StaticGet node, T arg) => defaultExpression(node, arg);
   R visitStaticSet(StaticSet node, T arg) => defaultExpression(node, arg);
+  R visitStaticTearOff(StaticTearOff node, T arg) =>
+      defaultExpression(node, arg);
+  R visitLocalFunctionInvocation(LocalFunctionInvocation node, T arg) =>
+      defaultExpression(node, arg);
+  R visitDynamicInvocation(DynamicInvocation node, T arg) =>
+      defaultExpression(node, arg);
+  R visitFunctionInvocation(FunctionInvocation node, T arg) =>
+      defaultExpression(node, arg);
+  R visitInstanceInvocation(InstanceInvocation node, T arg) =>
+      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) =>
diff --git a/pkg/kernel/lib/vm/constants_native_effects.dart b/pkg/kernel/lib/vm/constants_native_effects.dart
index 8bb1bac..401504a 100644
--- a/pkg/kernel/lib/vm/constants_native_effects.dart
+++ b/pkg/kernel/lib/vm/constants_native_effects.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.9
+
 library vm.constants_native_effects;
 
 import '../ast.dart';
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 3609233..09b5348 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -6,7 +6,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.6.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 dependencies:
   meta:
     path: ../meta
diff --git a/pkg/kernel/test/ast_membench.dart b/pkg/kernel/test/ast_membench.dart
index dc50ccc..baf8245 100644
--- a/pkg/kernel/test/ast_membench.dart
+++ b/pkg/kernel/test/ast_membench.dart
@@ -2,6 +2,9 @@
 // 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.
+
+// @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 4984a0b..2c8d827 100644
--- a/pkg/kernel/test/binary/can_read_platform_test.dart
+++ b/pkg/kernel/test/binary/can_read_platform_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.
 
+// @dart = 2.9
+
 import 'dart:io';
 
 import 'package:kernel/binary/ast_from_binary.dart';
@@ -84,6 +86,9 @@
     int libs = component.libraries.length;
 
     component = new Component();
+    new BinaryBuilderWithMetadata(bytes).readComponentSource(component);
+
+    component = new Component();
     new BinaryBuilder(bytes).readComponent(component);
     if (libs != component.libraries.length) {
       throw "Didn't get the same number of libraries: $libs when reading with "
@@ -91,6 +96,9 @@
           "when reading with BinaryBuilder";
     }
 
+    component = new Component();
+    new BinaryBuilder(bytes).readComponentSource(component);
+
     return true;
   } catch (e, st) {
     print("Error for $dill:");
diff --git a/pkg/kernel/test/binary/component_mode_test.dart b/pkg/kernel/test/binary/component_mode_test.dart
index 982270d..b03ea0a 100644
--- a/pkg/kernel/test/binary/component_mode_test.dart
+++ b/pkg/kernel/test/binary/component_mode_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.
 
+// @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 46f9bc4..454ede6 100644
--- a/pkg/kernel/test/binary/invalid_index_size.dart
+++ b/pkg/kernel/test/binary/invalid_index_size.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.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
new file mode 100644
index 0000000..7edfda9
--- /dev/null
+++ b/pkg/kernel/test/binary/lazy_reading_test.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.
+
+// @dart = 2.9
+
+import 'package:kernel/binary/ast_from_binary.dart';
+import 'package:kernel/src/tool/find_referenced_libraries.dart';
+import 'utils.dart';
+
+main() {
+  Library lib;
+  {
+    /// Create a library with two classes (A and B) where class A - in its
+    /// constructor - invokes the constructor for B.
+    lib = new Library(Uri.parse('org-dartlang:///lib.dart'));
+    final Class classA = new Class(name: "A");
+    lib.addClass(classA);
+    final Class classB = new Class(name: "B");
+    lib.addClass(classB);
+
+    final Constructor classBConstructor = new Constructor(
+        new FunctionNode(new EmptyStatement()),
+        name: new Name(""));
+    classB.addConstructor(classBConstructor);
+
+    final Constructor classAConstructor = new Constructor(
+        new FunctionNode(new ExpressionStatement(new ConstructorInvocation(
+            classBConstructor, new Arguments.empty()))),
+        name: new Name(""));
+    classA.addConstructor(classAConstructor);
+  }
+  Component c = new Component(libraries: [lib]);
+  c.setMainMethodAndMode(null, false, NonNullableByDefaultCompiledMode.Weak);
+  List<int> loadMe = serializeComponent(c);
+
+  // Load and make sure we can get at class B from class A (i.e. that it's
+  // loaded correctly!).
+  Component loadedComponent = new Component();
+  new BinaryBuilder(loadMe,
+          disableLazyReading: false, disableLazyClassReading: false)
+      .readSingleFileComponent(loadedComponent);
+  {
+    final Library loadedLib = loadedComponent.libraries.single;
+    final Class loadedClassA = loadedLib.classes.first;
+    final ExpressionStatement loadedConstructorA =
+        loadedClassA.constructors.single.function.body;
+    final ConstructorInvocation loadedConstructorInvocation =
+        loadedConstructorA.expression;
+    final Class pointedToClass =
+        loadedConstructorInvocation.target.enclosingClass;
+    final Library pointedToLib =
+        loadedConstructorInvocation.target.enclosingLibrary;
+
+    Set<Library> reachable = findAllReferencedLibraries([loadedLib]);
+    if (reachable.length != 1 || reachable.single != loadedLib) {
+      throw "Expected only the single library to be reachable, "
+          "but found $reachable";
+    }
+
+    final Class loadedClassB = loadedLib.classes[1];
+    if (loadedClassB != pointedToClass) {
+      throw "Doesn't point to the right class";
+    }
+    if (pointedToLib != loadedLib) {
+      throw "Doesn't point to the right library";
+    }
+  }
+  // Attempt to load again, overwriting the old stuff. This should logically
+  // "relink" to the newly loaded version.
+  Component loadedComponent2 = new Component(nameRoot: loadedComponent.root);
+  new BinaryBuilder(loadMe,
+          disableLazyReading: false,
+          disableLazyClassReading: false,
+          alwaysCreateNewNamedNodes: true)
+      .readSingleFileComponent(loadedComponent2);
+  {
+    final Library loadedLib = loadedComponent2.libraries.single;
+    final Class loadedClassA = loadedLib.classes.first;
+    final ExpressionStatement loadedConstructorA =
+        loadedClassA.constructors.single.function.body;
+    final ConstructorInvocation loadedConstructorInvocation =
+        loadedConstructorA.expression;
+    final Class pointedToClass =
+        loadedConstructorInvocation.target.enclosingClass;
+    final Library pointedToLib =
+        loadedConstructorInvocation.target.enclosingLibrary;
+
+    Set<Library> reachable = findAllReferencedLibraries([loadedLib]);
+    if (reachable.length != 1 || reachable.single != loadedLib) {
+      throw "Expected only the single library to be reachable, "
+          "but found $reachable";
+    }
+
+    final Class loadedClassB = loadedLib.classes[1];
+    if (loadedClassB != pointedToClass) {
+      throw "Doesn't point to the right class";
+    }
+    if (pointedToLib != loadedLib) {
+      throw "Doesn't point to the right library";
+    }
+  }
+}
diff --git a/pkg/kernel/test/binary/library_flags_test.dart b/pkg/kernel/test/binary/library_flags_test.dart
index 04630d7..0f80d24 100644
--- a/pkg/kernel/test/binary/library_flags_test.dart
+++ b/pkg/kernel/test/binary/library_flags_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.
 
+// @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 1005909..4253db8 100644
--- a/pkg/kernel/test/binary/utils.dart
+++ b/pkg/kernel/test/binary/utils.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.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 a30296a..be0a341 100644
--- a/pkg/kernel/test/binary_bench.dart
+++ b/pkg/kernel/test/binary_bench.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.9
+
 // This files contains methods for benchmarking Kernel binary serialization
 // and deserialization routines.
 
diff --git a/pkg/kernel/test/class_hierarchy_basic.dart b/pkg/kernel/test/class_hierarchy_basic.dart
index b2b9322..1a9b34e 100644
--- a/pkg/kernel/test/class_hierarchy_basic.dart
+++ b/pkg/kernel/test/class_hierarchy_basic.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.9
+
 library kernel.class_hierarchy_basic;
 
 import 'package:kernel/class_hierarchy.dart';
diff --git a/pkg/kernel/test/class_hierarchy_bench.dart b/pkg/kernel/test/class_hierarchy_bench.dart
index 0026781..97d3dcd 100644
--- a/pkg/kernel/test/class_hierarchy_bench.dart
+++ b/pkg/kernel/test/class_hierarchy_bench.dart
@@ -2,6 +2,9 @@
 // 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.
+
+// @dart = 2.9
+
 import 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
diff --git a/pkg/kernel/test/class_hierarchy_membench.dart b/pkg/kernel/test/class_hierarchy_membench.dart
index a8763fb..2c65048 100644
--- a/pkg/kernel/test/class_hierarchy_membench.dart
+++ b/pkg/kernel/test/class_hierarchy_membench.dart
@@ -2,6 +2,9 @@
 // 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.
+
+// @dart = 2.9
+
 import 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
diff --git a/pkg/kernel/test/class_hierarchy_self_check.dart b/pkg/kernel/test/class_hierarchy_self_check.dart
index 7bb0462..182a2b7 100644
--- a/pkg/kernel/test/class_hierarchy_self_check.dart
+++ b/pkg/kernel/test/class_hierarchy_self_check.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.9
+
 import 'package:kernel/kernel.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index bf078f8..841f5b9 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_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.
 
+// @dart = 2.9
+
 import "package:expect/minitest.dart";
 
 import "package:kernel/ast.dart";
@@ -698,8 +700,8 @@
     var abstractMethod = newEmptyMethod('abstractMethod', isAbstract: true);
     var abstractGetter = newEmptyGetter('abstractGetter', isAbstract: true);
     var abstractSetter = newEmptySetter('abstractSetter', isAbstract: true);
-    var nonFinalField = new Field(new Name('nonFinalField'));
-    var finalField = new Field(new Name('finalField'), isFinal: true);
+    var nonFinalField = new Field.mutable(new Name('nonFinalField'));
+    var finalField = new Field.immutable(new Name('finalField'), isFinal: true);
     var a = addClass(new Class(
         isAbstract: true,
         name: 'A',
@@ -929,8 +931,8 @@
     var abstractMethod = newEmptyMethod('abstractMethod', isAbstract: true);
     var abstractGetter = newEmptyGetter('abstractGetter', isAbstract: true);
     var abstractSetter = newEmptySetter('abstractSetter', isAbstract: true);
-    var nonFinalField = new Field(new Name('nonFinalField'));
-    var finalField = new Field(new Name('finalField'), isFinal: true);
+    var nonFinalField = new Field.mutable(new Name('nonFinalField'));
+    var finalField = new Field.immutable(new Name('finalField'), isFinal: true);
     var a = addClass(new Class(
         isAbstract: true,
         name: 'A',
@@ -984,8 +986,8 @@
     var abstractMethod = newEmptyMethod('abstractMethod', isAbstract: true);
     var abstractGetter = newEmptyGetter('abstractGetter', isAbstract: true);
     var abstractSetter = newEmptySetter('abstractSetter', isAbstract: true);
-    var nonFinalField = new Field(new Name('nonFinalField'));
-    var finalField = new Field(new Name('finalField'), isFinal: true);
+    var nonFinalField = new Field.mutable(new Name('nonFinalField'));
+    var finalField = new Field.immutable(new Name('finalField'), isFinal: true);
 
     var a = addClass(new Class(name: 'A', supertype: objectSuper, fields: [
       nonFinalField,
@@ -1049,13 +1051,15 @@
     var method_a = newEmptyMethod('method');
     var getter_a = newEmptyGetter('getter');
     var setter_a = newEmptySetter('setter');
-    var nonFinalField_a = new Field(new Name('nonFinalField'));
-    var finalField_a = new Field(new Name('finalField'), isFinal: true);
+    var nonFinalField_a = new Field.mutable(new Name('nonFinalField'));
+    var finalField_a =
+        new Field.immutable(new Name('finalField'), isFinal: true);
     var method_b = newEmptyMethod('method');
     var getter_b = newEmptyGetter('getter');
     var setter_b = newEmptySetter('setter');
-    var nonFinalField_b = new Field(new Name('nonFinalField'));
-    var finalField_b = new Field(new Name('finalField'), isFinal: true);
+    var nonFinalField_b = new Field.mutable(new Name('nonFinalField'));
+    var finalField_b =
+        new Field.immutable(new Name('finalField'), isFinal: true);
 
     var a = addClass(new Class(
         name: 'A',
@@ -1119,13 +1123,15 @@
     var getter_a = newEmptyGetter('getter');
     var setter_a = newEmptySetter('setter');
     var nonShadowedSetter_a = newEmptySetter('nonShadowedSetter');
-    var nonFinalField_a = new Field(new Name('nonFinalField'));
-    var finalField_a = new Field(new Name('finalField'), isFinal: true);
+    var nonFinalField_a = new Field.mutable(new Name('nonFinalField'));
+    var finalField_a =
+        new Field.immutable(new Name('finalField'), isFinal: true);
     var method_b = newEmptyMethod('method');
     var getter_b = newEmptyGetter('getter');
     var setter_b = newEmptySetter('setter');
-    var nonFinalField_b = new Field(new Name('nonFinalField'));
-    var finalField_b = new Field(new Name('finalField'), isFinal: true);
+    var nonFinalField_b = new Field.mutable(new Name('nonFinalField'));
+    var finalField_b =
+        new Field.immutable(new Name('finalField'), isFinal: true);
 
     var a = addClass(new Class(name: 'A', supertype: objectSuper, fields: [
       nonFinalField_a,
diff --git a/pkg/kernel/test/class_hierarchy_test_disabled.dart b/pkg/kernel/test/class_hierarchy_test_disabled.dart
index d1cd156..5cba5d7 100644
--- a/pkg/kernel/test/class_hierarchy_test_disabled.dart
+++ b/pkg/kernel/test/class_hierarchy_test_disabled.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @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/convert_field_to_setter_getter.dart b/pkg/kernel/test/convert_field_to_setter_getter.dart
index fc45c7b..8cc17a4 100644
--- a/pkg/kernel/test/convert_field_to_setter_getter.dart
+++ b/pkg/kernel/test/convert_field_to_setter_getter.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.
 
-import 'dart:io';
+// @dart = 2.9
 
-import 'package:kernel/ast.dart';
 import 'package:kernel/binary/ast_from_binary.dart';
 import 'package:kernel/binary/ast_to_binary.dart';
+import 'binary/utils.dart';
 
 main() {
   final Library lib1 = new Library(Uri.parse('org-dartlang:///lib.dart'));
-  final Field field = new Field(new Name("f"));
+  final Field field = new Field.mutable(new Name("f"));
   lib1.addField(field);
   final Block libProcedureBody = new Block([
     new ExpressionStatement(new StaticSet(field, new IntLiteral(42))),
@@ -88,7 +88,7 @@
   // Replace getter/setter with field.
   lib1.procedures.remove(getter);
   lib1.procedures.remove(setter);
-  final Field fieldReplacement = new Field(new Name("f"),
+  final Field fieldReplacement = new Field.mutable(new Name("f"),
       getterReference: getter.reference, setterReference: setter.reference);
   // Important: Unbind any old canonical name
   // (nulling out the canonical name is not enough, see above).
@@ -180,14 +180,3 @@
   StaticGet staticGet = setterStatement.expression;
   return staticGet.target;
 }
-
-/// A [Sink] that directly writes data into a byte builder.
-class ByteSink implements Sink<List<int>> {
-  final BytesBuilder builder = new BytesBuilder();
-
-  void add(List<int> data) {
-    builder.add(data);
-  }
-
-  void close() {}
-}
diff --git a/pkg/kernel/test/dart_type_equivalence_test.dart b/pkg/kernel/test/dart_type_equivalence_test.dart
index 462c637..aeb980e 100644
--- a/pkg/kernel/test/dart_type_equivalence_test.dart
+++ b/pkg/kernel/test/dart_type_equivalence_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.
 
+// @dart = 2.9
+
 import "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart' hide MapEntry;
diff --git a/pkg/kernel/test/flatten_test.dart b/pkg/kernel/test/flatten_test.dart
index 6983445..00c707a 100644
--- a/pkg/kernel/test/flatten_test.dart
+++ b/pkg/kernel/test/flatten_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.
 
+// @dart = 2.9
+
 import "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart' hide MapEntry;
diff --git a/pkg/kernel/test/future_value_type_test.dart b/pkg/kernel/test/future_value_type_test.dart
index 8a7bfac..5eed73f 100644
--- a/pkg/kernel/test/future_value_type_test.dart
+++ b/pkg/kernel/test/future_value_type_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.
 
+// @dart = 2.9
+
 import "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart' hide MapEntry;
diff --git a/pkg/kernel/test/graph_test.dart b/pkg/kernel/test/graph_test.dart
index 8a84aaf..28668f6 100644
--- a/pkg/kernel/test/graph_test.dart
+++ b/pkg/kernel/test/graph_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.md file.
 
+// @dart = 2.9
+
 library kernel.test.graph_test;
 
 import 'package:expect/expect.dart' show Expect;
diff --git a/pkg/kernel/test/heap_test.dart b/pkg/kernel/test/heap_test.dart
index 32b294e..95071ef 100644
--- a/pkg/kernel/test/heap_test.dart
+++ b/pkg/kernel/test/heap_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.
 
+// @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 daef20e..62c10f0 100644
--- a/pkg/kernel/test/import_table_test.dart
+++ b/pkg/kernel/test/import_table_test.dart
@@ -1,3 +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
+
 import 'package:kernel/import_table.dart';
 
 main() {
diff --git a/pkg/kernel/test/legacy_erasure_test.dart b/pkg/kernel/test/legacy_erasure_test.dart
index 0a0902b..f62eba0 100644
--- a/pkg/kernel/test/legacy_erasure_test.dart
+++ b/pkg/kernel/test/legacy_erasure_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.
 
+// @dart = 2.9
+
 import "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart' hide MapEntry;
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 a888455..60af31f 100644
--- a/pkg/kernel/test/load_concat_dill_keeps_source_test.dart
+++ b/pkg/kernel/test/load_concat_dill_keeps_source_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.
 
+// @dart = 2.9
+
 // Test that 79cc54e51924cd5a6bdc2bd1771f2d0ee7af8899 works as intended.
 
 import 'dart:convert';
diff --git a/pkg/kernel/test/metadata_test.dart b/pkg/kernel/test/metadata_test.dart
index 5b362f1..377ad22 100644
--- a/pkg/kernel/test/metadata_test.dart
+++ b/pkg/kernel/test/metadata_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.
 
+// @dart = 2.9
+
 import 'dart:convert';
 import 'dart:io';
 
diff --git a/pkg/kernel/test/nnbd_top_merge_test.dart b/pkg/kernel/test/nnbd_top_merge_test.dart
index bd82a7e..1296889 100644
--- a/pkg/kernel/test/nnbd_top_merge_test.dart
+++ b/pkg/kernel/test/nnbd_top_merge_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.
 
+// @dart = 2.9
+
 import "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart' hide MapEntry;
diff --git a/pkg/kernel/test/non_null_test.dart b/pkg/kernel/test/non_null_test.dart
index d9a04aa..c4f2570 100644
--- a/pkg/kernel/test/non_null_test.dart
+++ b/pkg/kernel/test/non_null_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.
 
+// @dart = 2.9
+
 import "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart' hide MapEntry;
diff --git a/pkg/kernel/test/norm_test.dart b/pkg/kernel/test/norm_test.dart
index c287025..5fe8429 100644
--- a/pkg/kernel/test/norm_test.dart
+++ b/pkg/kernel/test/norm_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.
 
+// @dart = 2.9
+
 import "package:expect/expect.dart" show Expect;
 
 import 'package:kernel/ast.dart' hide MapEntry;
diff --git a/pkg/kernel/test/regression_37753_test.dart b/pkg/kernel/test/regression_37753_test.dart
index c5448ac..f653337 100644
--- a/pkg/kernel/test/regression_37753_test.dart
+++ b/pkg/kernel/test/regression_37753_test.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
+
 // Regression test for https://github.com/dart-lang/sdk/issues/37753.
 // A missing piece of transform logic caused nested sync* set to a variable
 // to not get transformed, which would either fail an assert or crash.
diff --git a/pkg/kernel/test/regression_40662_test.dart b/pkg/kernel/test/regression_40662_test.dart
index 140d34c..77eaf47 100644
--- a/pkg/kernel/test/regression_40662_test.dart
+++ b/pkg/kernel/test/regression_40662_test.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
+
 // Regression test for https://github.com/dart-lang/sdk/issues/40662.
 
 import "package:expect/expect.dart" show Expect;
diff --git a/pkg/kernel/test/relink_test.dart b/pkg/kernel/test/relink_test.dart
index ed51ee6..b50be8e 100644
--- a/pkg/kernel/test/relink_test.dart
+++ b/pkg/kernel/test/relink_test.dart
@@ -2,16 +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.
 
-import 'dart:io';
+// @dart = 2.9
 
-import 'package:kernel/ast.dart';
 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';
+import 'binary/utils.dart';
 
 main() {
   Component component1 = createComponent(42);
   Component component2 = createComponent(43);
 
+  expectReachable(
+      findAllReferencedLibraries(component1.libraries), component1.libraries);
+  if (duplicateLibrariesReachable(component1.libraries)) {
+    throw "Didn't expect duplicates libraries!";
+  }
+  expectReachable(
+      findAllReferencedLibraries(component2.libraries), component2.libraries);
+  if (duplicateLibrariesReachable(component2.libraries)) {
+    throw "Didn't expect duplicates libraries!";
+  }
+
   ByteSink sink = new ByteSink();
   new BinaryPrinter(sink).writeComponentFile(component1);
   List<int> writtenBytes1 = sink.builder.takeBytes();
@@ -25,6 +37,11 @@
   Procedure target1 = getMainTarget(component1Prime);
   Procedure procedureLib1 = getLibProcedure(component1Prime);
   if (target1 != procedureLib1) throw "Unexpected target.";
+  expectReachable(findAllReferencedLibraries(component1Prime.libraries),
+      component1Prime.libraries);
+  if (duplicateLibrariesReachable(component1Prime.libraries)) {
+    throw "Didn't expect duplicates libraries!";
+  }
 
   // Loading another one saying it should overwrite works as one would expect
   // for this component: It gives a component that is linked to itself that is
@@ -36,6 +53,11 @@
   Procedure procedureLib2 = getLibProcedure(component2Prime);
   if (procedureLib2 == procedureLib1) throw "Unexpected procedure.";
   if (target2 != procedureLib2) throw "Unexpected target.";
+  expectReachable(findAllReferencedLibraries(component2Prime.libraries),
+      component2Prime.libraries);
+  if (duplicateLibrariesReachable(component2Prime.libraries)) {
+    throw "Didn't expect duplicates libraries!";
+  }
 
   // The old one that was loaded on top of was re-linked so it also points to
   // procedureLib2.
@@ -44,17 +66,48 @@
 
   // Relink back and forth a number of times: It keeps working as expected.
   for (int i = 0; i < 6; i++) {
+    // Before the relink the lib from component2Prime is also reachable!
+    expectReachable(
+        findAllReferencedLibraries(component1Prime.libraries),
+        []
+          ..addAll(component1Prime.libraries)
+          ..add(procedureLib2.enclosingLibrary));
+    if (!duplicateLibrariesReachable(component1Prime.libraries)) {
+      throw "Expected duplicates libraries!";
+    }
+
     // Relinking component1Prime works as one would expected: Both components
     // main now points to procedureLib1.
     component1Prime.relink();
+    // After the relink only the libs from component1Prime are reachable!
+    expectReachable(findAllReferencedLibraries(component1Prime.libraries),
+        component1Prime.libraries);
+    if (duplicateLibrariesReachable(component1Prime.libraries)) {
+      throw "Didn't expect duplicates libraries!";
+    }
     target1 = getMainTarget(component1Prime);
     if (target1 != procedureLib1) throw "Unexpected target.";
     target2 = getMainTarget(component2Prime);
     if (target2 != procedureLib1) throw "Unexpected target.";
 
+    // Before the relink the lib from component1Prime is also reachable!
+    expectReachable(
+        findAllReferencedLibraries(component2Prime.libraries),
+        []
+          ..addAll(component2Prime.libraries)
+          ..add(procedureLib1.enclosingLibrary));
+    if (!duplicateLibrariesReachable(component2Prime.libraries)) {
+      throw "Expected duplicates libraries!";
+    }
     // Relinking component2Prime works as one would expected: Both components
     // main now points to procedureLib2.
     component2Prime.relink();
+    // After the relink only the libs from component1Prime are reachable!
+    expectReachable(findAllReferencedLibraries(component2Prime.libraries),
+        component2Prime.libraries);
+    if (duplicateLibrariesReachable(component2Prime.libraries)) {
+      throw "Didn't expect duplicates libraries!";
+    }
     target1 = getMainTarget(component1Prime);
     if (target1 != procedureLib2) throw "Unexpected target.";
     target2 = getMainTarget(component2Prime);
@@ -62,6 +115,18 @@
   }
 }
 
+void expectReachable(
+    Set<Library> findAllReferencedLibraries, List<Library> libraries) {
+  Set<Library> onlyInReferenced = findAllReferencedLibraries.toSet()
+    ..removeAll(libraries);
+  Set<Library> onlyInLibraries = libraries.toSet()
+    ..removeAll(findAllReferencedLibraries);
+  if (onlyInReferenced.isNotEmpty || onlyInLibraries.isNotEmpty) {
+    throw "Expected to be the same, but ${onlyInReferenced} was only in "
+        "reachable and ${onlyInLibraries} was only in libraries";
+  }
+}
+
 Procedure getLibProcedure(Component component1Prime) {
   if (component1Prime.libraries[1].importUri !=
       Uri.parse('org-dartlang:///lib.dart')) {
@@ -106,14 +171,3 @@
   return new Component(libraries: [main, lib])
     ..setMainMethodAndMode(null, false, NonNullableByDefaultCompiledMode.Weak);
 }
-
-/// A [Sink] that directly writes data into a byte builder.
-class ByteSink implements Sink<List<int>> {
-  final BytesBuilder builder = new BytesBuilder();
-
-  void add(List<int> data) {
-    builder.add(data);
-  }
-
-  void close() {}
-}
diff --git a/pkg/kernel/test/round_trip.dart b/pkg/kernel/test/round_trip.dart
index b94ae42..3766db0 100644
--- a/pkg/kernel/test/round_trip.dart
+++ b/pkg/kernel/test/round_trip.dart
@@ -1,12 +1,15 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.round_trip;
 
 import 'dart:io';
 import 'package:kernel/binary/ast_from_binary.dart';
 import 'package:kernel/binary/ast_to_binary.dart';
-import 'package:kernel/kernel.dart';
+import 'binary/utils.dart';
 
 const String usage = '''
 Usage: round_trip.dart FILE.dill [sdk.dill]
@@ -52,14 +55,3 @@
 String show(int byte) {
   return '$byte (0x${byte.toRadixString(16).padLeft(2, "0")})';
 }
-
-/// A [Sink] that directly writes data into a byte builder.
-class ByteSink implements Sink<List<int>> {
-  final BytesBuilder builder = new BytesBuilder();
-
-  void add(List<int> data) {
-    builder.add(data);
-  }
-
-  void close() {}
-}
diff --git a/pkg/kernel/test/round_trip_self_check.dart b/pkg/kernel/test/round_trip_self_check.dart
index a299f26..da2e0e1 100644
--- a/pkg/kernel/test/round_trip_self_check.dart
+++ b/pkg/kernel/test/round_trip_self_check.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @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 1ebdd39..e742142 100644
--- a/pkg/kernel/test/self_check_util.dart
+++ b/pkg/kernel/test/self_check_util.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.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 3957ddb..0a413f9 100644
--- a/pkg/kernel/test/serialize_bench.dart
+++ b/pkg/kernel/test/serialize_bench.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @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 cd4ae4a..41daa56 100644
--- a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.text_serializer_from_kernel_nodes_test;
 
 import 'package:kernel/ast.dart';
@@ -119,7 +122,8 @@
           serializer: statementSerializer);
     }(),
     () {
-      Field field = new Field(new Name('field'), type: const DynamicType());
+      Field field =
+          new Field.immutable(new Name('field'), type: const DynamicType());
       Library library = new Library(
           new Uri(scheme: 'package', path: 'foo/bar.dart'),
           fields: <Field>[field]);
@@ -136,7 +140,26 @@
           serializer: statementSerializer);
     }(),
     () {
-      Field field = new Field(new Name('field'), type: const DynamicType());
+      Field field =
+          new Field.mutable(new Name('field'), type: const DynamicType());
+      Library library = new Library(
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
+          fields: <Field>[field]);
+      Component component = new Component(libraries: <Library>[library]);
+      component.computeCanonicalNames();
+      return new TestCase<Statement>(
+          name: '/* suppose top-level: dynamic field; */ field;',
+          node: new ExpressionStatement(new StaticGet(field)),
+          expectation: ''
+              '(expr (get-static "package:foo/bar.dart::@fields::field"))',
+          makeSerializationState: () => new SerializationState(null),
+          makeDeserializationState: () =>
+              new DeserializationState(null, component.root),
+          serializer: statementSerializer);
+    }(),
+    () {
+      Field field =
+          new Field.mutable(new Name('field'), type: const DynamicType());
       Library library = new Library(
           new Uri(scheme: 'package', path: 'foo/bar.dart'),
           fields: <Field>[field]);
@@ -208,7 +231,8 @@
           serializer: statementSerializer);
     }(),
     () {
-      Field field = new Field(new Name('field'), type: const DynamicType());
+      Field field =
+          new Field.immutable(new Name('field'), type: const DynamicType());
       Class klass = new Class(name: 'A', fields: <Field>[field]);
       Library library = new Library(
           new Uri(scheme: 'package', path: 'foo/bar.dart'),
@@ -236,7 +260,37 @@
           serializer: statementSerializer);
     }(),
     () {
-      Field field = new Field(new Name('field'), type: const DynamicType());
+      Field field =
+          new Field.mutable(new Name('field'), type: const DynamicType());
+      Class klass = new Class(name: 'A', fields: <Field>[field]);
+      Library library = new Library(
+          new Uri(scheme: 'package', path: 'foo/bar.dart'),
+          classes: <Class>[klass]);
+      Component component = new Component(libraries: <Library>[library]);
+      component.computeCanonicalNames();
+
+      VariableDeclaration x =
+          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)),
+          expectation: ''
+              '(expr (get-prop (get-var "x^0" _) (public "field")))',
+          makeSerializationState: () =>
+              new SerializationState(new SerializationEnvironment(null)
+                ..addBinder(x, nameClue: 'x')
+                ..extend()),
+          makeDeserializationState: () => new DeserializationState(
+              new DeserializationEnvironment(null)
+                ..addBinder(x, "x^0")
+                ..extend(),
+              component.root),
+          serializer: statementSerializer);
+    }(),
+    () {
+      Field field =
+          new Field.mutable(new Name('field'), type: const DynamicType());
       Class klass = new Class(name: 'A', fields: <Field>[field]);
       Library library = new Library(
           new Uri(scheme: 'package', path: 'foo/bar.dart'),
diff --git a/pkg/kernel/test/text_serializer_test.dart b/pkg/kernel/test/text_serializer_test.dart
index 521aca4..e04d07e 100644
--- a/pkg/kernel/test/text_serializer_test.dart
+++ b/pkg/kernel/test/text_serializer_test.dart
@@ -1,6 +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
+
 library kernel.text_serializer_test;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/type_hashcode_quality.dart b/pkg/kernel/test/type_hashcode_quality.dart
index d90183a..f33541e 100644
--- a/pkg/kernel/test/type_hashcode_quality.dart
+++ b/pkg/kernel/test/type_hashcode_quality.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 import 'package:kernel/kernel.dart';
 import 'dart:io';
 
diff --git a/pkg/kernel/test/type_hashcode_test.dart b/pkg/kernel/test/type_hashcode_test.dart
index b988507..9a16a72 100644
--- a/pkg/kernel/test/type_hashcode_test.dart
+++ b/pkg/kernel/test/type_hashcode_test.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 import 'package:kernel/kernel.dart';
 import 'type_parser.dart';
 import 'package:test/test.dart';
diff --git a/pkg/kernel/test/type_parser.dart b/pkg/kernel/test/type_parser.dart
index 62b5a0f..f392821 100644
--- a/pkg/kernel/test/type_parser.dart
+++ b/pkg/kernel/test/type_parser.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 // A very simple parser for a subset of DartTypes for use in testing type
 // algebra.
 library kernel.test.type_parser;
diff --git a/pkg/kernel/test/type_parser_test.dart b/pkg/kernel/test/type_parser_test.dart
index 5a2e651..e015daa 100644
--- a/pkg/kernel/test/type_parser_test.dart
+++ b/pkg/kernel/test/type_parser_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.
 
+// @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 7fb556c..c92d17a 100644
--- a/pkg/kernel/test/type_substitute_bounds_test.dart
+++ b/pkg/kernel/test/type_substitute_bounds_test.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.type_substitute_bounds_test;
 
 import 'package:kernel/kernel.dart';
diff --git a/pkg/kernel/test/type_substitution_identity_test.dart b/pkg/kernel/test/type_substitution_identity_test.dart
index d8fabbd..99d7fe7 100644
--- a/pkg/kernel/test/type_substitution_identity_test.dart
+++ b/pkg/kernel/test/type_substitution_identity_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.
 
+// @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 4f70f04..18be629 100644
--- a/pkg/kernel/test/typedef_unalias_test.dart
+++ b/pkg/kernel/test/typedef_unalias_test.dart
@@ -1,6 +1,9 @@
 // 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.
+
+// @dart = 2.9
+
 library kernel.typedef_unalias_test;
 
 import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/verify_bench.dart b/pkg/kernel/test/verify_bench.dart
index c5fc42e..6326b89 100644
--- a/pkg/kernel/test/verify_bench.dart
+++ b/pkg/kernel/test/verify_bench.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.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 bc9b184..bb2cd02 100644
--- a/pkg/kernel/test/verify_self_check.dart
+++ b/pkg/kernel/test/verify_self_check.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.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 56ccfcf..7b6a238 100644
--- a/pkg/kernel/test/verify_test.dart
+++ b/pkg/kernel/test/verify_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.
 
+// @dart = 2.9
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/text/ast_to_text.dart';
 import 'package:kernel/verifier.dart';
@@ -76,7 +78,7 @@
     'Member redeclared',
     (TestHarness test) {
       Field field =
-          new Field(new Name('field'), initializer: new NullLiteral());
+          new Field.mutable(new Name('field'), initializer: new NullLiteral());
       test.addNode(Class(
           name: 'Test',
           supertype: test.objectClass.asRawSupertype,
@@ -166,7 +168,7 @@
     'Class type parameter in static field',
     (TestHarness test) {
       TypeParameter node = test.classTypeParameter;
-      test.addNode(Field(new Name('field'),
+      test.addNode(Field.mutable(new Name('field'),
           initializer:
               new TypeLiteral(new TypeParameterType(node, Nullability.legacy)),
           isStatic: true));
@@ -235,7 +237,7 @@
   negative1Test(
     'Dangling field get',
     (TestHarness test) {
-      Field orphan = new Field(new Name('foo'));
+      Field orphan = new Field.mutable(new Name('foo'));
       test.addNode(new PropertyGet(new NullLiteral(), orphan.name, orphan));
       return orphan;
     },
@@ -421,7 +423,7 @@
           'Foo',
           new FunctionType(
               [test.otherLegacyRawType], const VoidType(), Nullability.legacy));
-      var field = new Field(new Name('field'),
+      var field = new Field.mutable(new Name('field'),
           type: new TypedefType(typedef_, Nullability.legacy), isStatic: true);
       test.enclosingLibrary.addTypedef(typedef_);
       test.enclosingLibrary.addField(field);
@@ -632,8 +634,8 @@
       var foo =
           new Typedef('Foo', test.otherLegacyRawType, typeParameters: [param]);
       var typedefType = new TypedefType(foo, Nullability.legacy, []);
-      var field =
-          new Field(new Name('field'), type: typedefType, isStatic: true);
+      var field = new Field.mutable(new Name('field'),
+          type: typedefType, isStatic: true);
       test.enclosingLibrary.addTypedef(foo);
       test.enclosingLibrary.addField(field);
       return typedefType;
@@ -646,7 +648,7 @@
     'Dangling typedef reference',
     (TestHarness test) {
       var foo = new Typedef('Foo', test.otherLegacyRawType, typeParameters: []);
-      var field = new Field(new Name('field'),
+      var field = new Field.mutable(new Name('field'),
           type: new TypedefType(foo, Nullability.legacy, []), isStatic: true);
       test.enclosingLibrary.addField(field);
       return foo;
@@ -656,7 +658,7 @@
   negative1Test(
     'Non-static top-level field',
     (TestHarness test) {
-      var field = new Field(new Name('field'));
+      var field = new Field.mutable(new Name('field'));
       test.enclosingLibrary.addField(field);
       return null;
     },
diff --git a/pkg/kernel/tool/smoke_test_quick.dart b/pkg/kernel/tool/smoke_test_quick.dart
index b5a0b9a..6ca6e19 100644
--- a/pkg/kernel/tool/smoke_test_quick.dart
+++ b/pkg/kernel/tool/smoke_test_quick.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.9
+
 import 'dart:io';
 
 final String repoDir = _computeRepoDir();
diff --git a/pkg/modular_test/lib/src/loader.dart b/pkg/modular_test/lib/src/loader.dart
index 65d5558..9050017 100644
--- a/pkg/modular_test/lib/src/loader.dart
+++ b/pkg/modular_test/lib/src/loader.dart
@@ -20,11 +20,12 @@
 ///     The format is described in `test_specification_parser.dart`.
 import 'dart:io';
 import 'dart:convert';
+import 'dart:typed_data';
 import 'suite.dart';
 import 'test_specification_parser.dart';
 import 'find_sdk_root.dart';
 
-import 'package:package_config/packages_file.dart' as package_config;
+import 'package:package_config/src/packages_file.dart' as packages_file;
 
 /// Returns the [ModularTest] associated with a folder under [uri].
 ///
@@ -38,7 +39,7 @@
   var testUri = folder.uri; // normalized in case the trailing '/' was missing.
   Uri root = await findRoot();
   Map<String, Uri> defaultPackages =
-      package_config.parse(_defaultPackagesInput, root);
+      _parseDotPackagesBytesToLibMap(_defaultPackagesInput, root);
   Module sdkModule = await _createSdkModule(root);
   Map<String, Module> modules = {'sdk': sdkModule};
   String specString;
@@ -76,7 +77,7 @@
         modules[moduleName] = module;
       } else if (fileName == '.packages') {
         List<int> packagesBytes = await entry.readAsBytes();
-        packages = package_config.parse(packagesBytes, entryUri);
+        packages = _parseDotPackagesBytesToLibMap(packagesBytes, entryUri);
       } else if (fileName == 'modules.yaml') {
         specString = await entry.readAsString();
       }
@@ -313,3 +314,15 @@
     }
   }
 }
+
+/// Parse [bytes] representing a `.packages` file into the map of package names
+/// to URIs of their `lib` locations.
+Map<String, Uri> _parseDotPackagesBytesToLibMap(Uint8List bytes, Uri baseUri) {
+  var map = <String, Uri>{};
+  var packageConfig =
+      packages_file.parse(bytes, baseUri, (error) => throw error);
+  for (var package in packageConfig.packages) {
+    map[package.name] = package.packageUriRoot;
+  }
+  return map;
+}
diff --git a/pkg/nnbd_migration/bin/migrate.dart b/pkg/nnbd_migration/bin/migrate.dart
index 5401871..ee52742 100644
--- a/pkg/nnbd_migration/bin/migrate.dart
+++ b/pkg/nnbd_migration/bin/migrate.dart
@@ -7,7 +7,7 @@
 import 'package:args/src/arg_results.dart';
 import 'package:nnbd_migration/migration_cli.dart';
 
-main(List<String> args) async {
+void main(List<String> args) async {
   var cli = MigrationCli(binaryName: 'nnbd_migration');
   ArgResults argResults;
   try {
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index 434a003..a5fa5ce 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 
 /// Data structure used by the nullability migration engine to refer to a
 /// specific location in source code.
@@ -273,6 +274,7 @@
   implicitMixinSuperCall,
   implicitNullInitializer,
   implicitNullReturn,
+  implicitThis,
   inferredTypeParameterInstantiation,
   instanceCreation,
   instantiateToBounds,
@@ -303,32 +305,6 @@
 /// about a reason for a modification to the source file.
 abstract class FixReasonInfo {}
 
-/// Enum describing the possible hints that can be performed on an edge or a
-/// node.
-///
-/// Which actions are available can be built by other visitors, and the hint can
-/// be applied by visitors such as EditPlanner when the user requests it from
-/// the front end.
-enum HintActionKind {
-  /// Add a `/*?*/` hint to a type.
-  addNullableHint,
-
-  /// Add a `/*!*/` hint to a type.
-  addNonNullableHint,
-
-  /// Change a `/*!*/` hint to a `/*?*/` hint.
-  changeToNullableHint,
-
-  /// Change a `/*?*/` hint to a `/*!*/` hint.
-  changeToNonNullableHint,
-
-  /// Remove a `/*?*/` hint.
-  removeNullableHint,
-
-  /// Remove a `/*!*/` hint.
-  removeNonNullableHint,
-}
-
 /// Abstract interface for assigning ids numbers to nodes, and performing
 /// lookups afterwards.
 abstract class NodeMapper extends NodeToIdMapper {
@@ -538,27 +514,3 @@
 
   UpstreamPropagationStepInfo get principalCause;
 }
-
-/// Extension methods to make [HintActionKind] act as a smart enum.
-extension HintActionKindBehaviors on HintActionKind {
-  /// Get the text description of a [HintActionKind], for display to users.
-  String get description {
-    switch (this) {
-      case HintActionKind.addNullableHint:
-        return 'Add /*?*/ hint';
-      case HintActionKind.addNonNullableHint:
-        return 'Add /*!*/ hint';
-      case HintActionKind.removeNullableHint:
-        return 'Remove /*?*/ hint';
-      case HintActionKind.removeNonNullableHint:
-        return 'Remove /*!*/ hint';
-      case HintActionKind.changeToNullableHint:
-        return 'Change to /*?*/ hint';
-      case HintActionKind.changeToNonNullableHint:
-        return 'Change to /*!*/ hint';
-    }
-
-    assert(false);
-    return null;
-  }
-}
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
index 4dff755..a727c1c 100644
--- a/pkg/nnbd_migration/lib/migration_cli.dart
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -517,6 +517,12 @@
 
   bool _hasAnalysisErrors = false;
 
+  /// Subscription of interrupt signals (control-C).
+  StreamSubscription<ProcessSignal> _sigIntSubscription;
+
+  /// Completes when an interrupt signal (control-C) is received.
+  Completer<void> sigIntSignalled;
+
   MigrationCliRunner(this.cli, this.options, {Logger logger})
       : logger = logger ?? cli.logger;
 
@@ -549,7 +555,7 @@
 
   @visibleForTesting
   bool get isPreviewServerRunning =>
-      _fixCodeProcessor?.isPreviewServerRunnning ?? false;
+      _fixCodeProcessor?.isPreviewServerRunning ?? false;
 
   Context get pathContext => resourceProvider.pathContext;
 
@@ -559,14 +565,6 @@
   /// derived class.
   void applyHook() {}
 
-  /// Blocks until an interrupt signal (control-C) is received.  Tests may
-  /// override this method to simulate control-C.
-  @visibleForTesting
-  Future<void> blockUntilSignalInterrupt() {
-    Stream<ProcessSignal> stream = ProcessSignal.sigint.watch();
-    return stream.first;
-  }
-
   /// Computes the internet address that should be passed to `HttpServer.bind`
   /// when starting the preview server.  May be overridden in derived classes.
   Object computeBindAddress() {
@@ -593,7 +591,10 @@
   Set<String> computePathsToProcess(DriverBasedAnalysisContext context) =>
       context.contextRoot
           .analyzedFiles()
-          .where((s) => s.endsWith('.dart'))
+          .where((s) =>
+              s.endsWith('.dart') &&
+              // Any file may have been deleted since its initial analysis.
+              resourceProvider.getFile(s).exists)
           .toSet();
 
   NonNullableFix createNonNullableFix(
@@ -605,14 +606,26 @@
       int preferredPort,
       String summaryPath,
       @required String sdkPath}) {
-    return NonNullableFix(
-        listener, resourceProvider, getLineInfo, bindAddress, logger,
+    return NonNullableFix(listener, resourceProvider, getLineInfo, bindAddress,
+        logger, (String path) => shouldBeMigrated(path),
         included: included,
         preferredPort: preferredPort,
         summaryPath: summaryPath,
         sdkPath: sdkPath);
   }
 
+  /// Subscribes to the interrupt signal (control-C).
+  @visibleForTesting
+  void listenForSignalInterrupt() {
+    var stream = ProcessSignal.sigint.watch();
+    sigIntSignalled = Completer();
+    _sigIntSubscription = stream.listen((_) {
+      if (!sigIntSignalled.isCompleted) {
+        sigIntSignalled.complete();
+      }
+    });
+  }
+
   @override
   void onException(String detail) {
     if (_hasExceptions) {
@@ -693,14 +706,12 @@
       logger.stdout('');
     }
 
-    DriverBasedAnalysisContext context = analysisContext;
-
     NonNullableFix nonNullableFix;
 
     logger.stdout(ansi.emphasized('Analyzing project...'));
-    _fixCodeProcessor = _FixCodeProcessor(context, this);
-    _dartFixListener =
-        DartFixListener(DriverProviderImpl(resourceProvider, context), this);
+    _fixCodeProcessor = _FixCodeProcessor(analysisContext, this);
+    _dartFixListener = DartFixListener(
+        DriverProviderImpl(resourceProvider, analysisContext), this);
     nonNullableFix = createNonNullableFix(_dartFixListener, resourceProvider,
         _fixCodeProcessor.getLineInfo, computeBindAddress(),
         included: [options.directory],
@@ -772,8 +783,15 @@
 
 ''');
 
-      // Block until sigint (ctrl-c).
-      await blockUntilSignalInterrupt();
+      listenForSignalInterrupt();
+      await Future.any([
+        sigIntSignalled.future,
+        nonNullableFix.serverIsShutdown.future,
+      ]);
+      // Either the interrupt signal was caught, or the server was shutdown.
+      // Either way, cancel the interrupt signal subscription, and shutdown the
+      // server.
+      _sigIntSubscription?.cancel();
       nonNullableFix.shutdownServer();
     } else {
       logger.stdout(ansi.emphasized('Diff of changes:'));
@@ -798,8 +816,8 @@
   /// return additional paths that aren't inside the user's project, but doesn't
   /// override this method, then those additional paths will be analyzed but not
   /// migrated.
-  bool shouldBeMigrated(DriverBasedAnalysisContext context, String path) {
-    return context.contextRoot.isAnalyzed(path);
+  bool shouldBeMigrated(String path) {
+    return analysisContext.contextRoot.isAnalyzed(path);
   }
 
   /// Perform the indicated source edits to the given source, returning the
@@ -942,6 +960,7 @@
           _dartFixListener,
           _fixCodeProcessor._task.instrumentationListener,
           {},
+          _fixCodeProcessor._task.shouldBeMigratedFunction,
           analysisResult);
     } else if (analysisResult.allSourcesAlreadyMigrated) {
       _logAlreadyMigrated();
@@ -951,6 +970,7 @@
           _dartFixListener,
           _fixCodeProcessor._task.instrumentationListener,
           {},
+          _fixCodeProcessor._task.shouldBeMigratedFunction,
           analysisResult);
     } else {
       logger.stdout(ansi.emphasized('Re-generating migration suggestions...'));
@@ -1029,7 +1049,7 @@
   _FixCodeProcessor(this.context, this._migrationCli)
       : pathsToProcess = _migrationCli.computePathsToProcess(context);
 
-  bool get isPreviewServerRunnning => _task?.isPreviewServerRunning ?? false;
+  bool get isPreviewServerRunning => _task?.isPreviewServerRunning ?? false;
 
   LineInfo getLineInfo(String path) =>
       context.currentSession.getFile(path).lineInfo;
@@ -1135,13 +1155,15 @@
     });
     await processResources((ResolvedUnitResult result) async {
       _progressBar.tick();
-      if (_migrationCli.shouldBeMigrated(context, result.path)) {
+      if (_migrationCli.shouldBeMigrated(result.path)) {
         await _task.finalizeUnit(result);
       }
     });
     _progressBar.complete();
     _migrationCli.logger.stdout(_migrationCli.ansi
         .emphasized('Compiling instrumentation information...'));
+    // Update the tasks paths-to-process, in case of new or deleted files.
+    _task.pathsToProcess = pathsToProcess;
     var state = await _task.finish();
     _task.processPackage(context.contextRoot.root, state.neededPackages);
     if (_migrationCli.options.webPreview) {
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index 25499a8..a05c09f 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -254,13 +254,13 @@
   }
 
   @override
-  operator ==(Object other) =>
+  bool operator ==(Object other) =>
       other is NullabilityFixDescription &&
       appliedMessage == other.appliedMessage &&
       kind == other.kind;
 
   @override
-  toString() =>
+  String toString() =>
       'NullabilityFixDescription(${json.encode(appliedMessage)}, $kind)';
 }
 
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index b348db7..c074a4a 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/dart/element/type_system.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' show TypeSystemImpl;
@@ -190,7 +191,7 @@
   ///
   /// Note that this is not guaranteed to be complete. It is used to make hard
   /// edges on a best-effort basis.
-  final _postDominatedLocals = _ScopedLocalSet();
+  var _postDominatedLocals = _ScopedLocalSet();
 
   /// Map whose keys are expressions of the form `a?.b` on the LHS of
   /// assignments, and whose values are the nullability nodes corresponding to
@@ -231,6 +232,10 @@
   final Map<MethodInvocation, DecoratedType Function(DecoratedType)>
       _deferredMethodInvocationProcessing = {};
 
+  /// If we are visiting a local function or closure, the set of local variables
+  /// assigned to so far inside it.  Otherwise `null`.
+  Set<Element> _elementsWrittenToInLocalFunction;
+
   EdgeBuilder(this.typeProvider, this._typeSystem, this._variables, this._graph,
       this.source, this.listener, this._decoratedClassHierarchy,
       {this.instrumentation})
@@ -470,7 +475,8 @@
       bool isAnd = operatorType == TokenType.AMPERSAND_AMPERSAND;
       _flowAnalysis.logicalBinaryOp_begin();
       _checkExpressionNotNull(leftOperand);
-      _flowAnalysis.logicalBinaryOp_rightBegin(node.leftOperand, isAnd: isAnd);
+      _flowAnalysis.logicalBinaryOp_rightBegin(node.leftOperand, node,
+          isAnd: isAnd);
       _postDominatedLocals.doScoped(
           action: () => _checkExpressionNotNull(rightOperand));
       _flowAnalysis.logicalBinaryOp_end(node, rightOperand, isAnd: isAnd);
@@ -659,7 +665,7 @@
     // Note: we don't have to create a scope for each branch because they can't
     // define variables.
     _postDominatedLocals.doScoped(action: () {
-      _flowAnalysis.conditional_thenBegin(node.condition);
+      _flowAnalysis.conditional_thenBegin(node.condition, node);
       if (trueGuard != null) {
         _guards.add(trueGuard);
       }
@@ -855,9 +861,24 @@
     _dispatch(node.returnType);
     if (_flowAnalysis != null) {
       // This is a local function.
-      _flowAnalysis.functionExpression_begin(node);
-      _dispatch(node.functionExpression);
-      _flowAnalysis.functionExpression_end();
+      var previousPostDominatedLocals = _postDominatedLocals;
+      var previousElementsWrittenToInLocalFunction =
+          _elementsWrittenToInLocalFunction;
+      try {
+        _elementsWrittenToInLocalFunction = {};
+        _postDominatedLocals = _ScopedLocalSet();
+        _flowAnalysis.functionExpression_begin(node);
+        _dispatch(node.functionExpression);
+        _flowAnalysis.functionExpression_end();
+      } finally {
+        for (var element in _elementsWrittenToInLocalFunction) {
+          previousElementsWrittenToInLocalFunction?.add(element);
+          previousPostDominatedLocals.removeFromAllScopes(element);
+        }
+        _elementsWrittenToInLocalFunction =
+            previousElementsWrittenToInLocalFunction;
+        _postDominatedLocals = previousPostDominatedLocals;
+      }
     } else {
       _createFlowAnalysis(node, node.functionExpression.parameters);
       // Initialize a new postDominator scope that contains only the parameters.
@@ -903,7 +924,14 @@
     _currentFunctionExpression = node;
     _currentFunctionType =
         _variables.decoratedElementType(node.declaredElement);
+    var previousPostDominatedLocals = _postDominatedLocals;
+    var previousElementsWrittenToInLocalFunction =
+        _elementsWrittenToInLocalFunction;
     try {
+      if (node.parent is! FunctionDeclaration) {
+        _elementsWrittenToInLocalFunction = {};
+      }
+      _postDominatedLocals = _ScopedLocalSet();
       _postDominatedLocals.doScoped(
           elements: node.declaredElement.parameters,
           action: () => _dispatch(node.body));
@@ -912,9 +940,16 @@
     } finally {
       if (node.parent is! FunctionDeclaration) {
         _flowAnalysis.functionExpression_end();
+        for (var element in _elementsWrittenToInLocalFunction) {
+          previousElementsWrittenToInLocalFunction?.add(element);
+          previousPostDominatedLocals.removeFromAllScopes(element);
+        }
+        _elementsWrittenToInLocalFunction =
+            previousElementsWrittenToInLocalFunction;
       }
       _currentFunctionType = previousFunctionType;
       _currentFunctionExpression = previousFunction;
+      _postDominatedLocals = previousPostDominatedLocals;
     }
   }
 
@@ -940,7 +975,9 @@
 
   @override
   DecoratedType visitIfElement(IfElement node) {
+    _flowAnalysis.ifStatement_conditionBegin();
     _checkExpressionNotNull(node.condition);
+    _flowAnalysis.ifStatement_thenBegin(node.condition, node);
     NullabilityNode trueGuard;
     NullabilityNode falseGuard;
     if (identical(_conditionInfo?.condition, node.condition)) {
@@ -961,6 +998,7 @@
       }
     }
     if (node.elseElement != null) {
+      _flowAnalysis.ifStatement_elseBegin();
       if (falseGuard != null) {
         _guards.add(falseGuard);
       }
@@ -973,6 +1011,7 @@
         }
       }
     }
+    _flowAnalysis.ifStatement_end(node.elseElement != null);
     return null;
   }
 
@@ -992,7 +1031,7 @@
       _guards.add(trueGuard);
     }
     try {
-      _flowAnalysis.ifStatement_thenBegin(node.condition);
+      _flowAnalysis.ifStatement_thenBegin(node.condition, node);
       // We branched, so create a new scope for post-dominators.
       _postDominatedLocals.doScoped(
           action: () => _dispatch(node.thenStatement));
@@ -1230,6 +1269,7 @@
       }
     } else if (target == null && callee.enclosingElement is ClassElement) {
       targetType = _thisOrSuper(node);
+      _checkThisNotNull(targetType, node);
     }
     DecoratedType expressionType;
     DecoratedType calleeType;
@@ -1347,7 +1387,7 @@
       if (operand is SimpleIdentifier) {
         var element = getWriteOrReadElement(operand);
         if (element is PromotableElement) {
-          _flowAnalysis.write(element, writeType);
+          _flowAnalysis.write(element, writeType, null);
         }
       }
       return targetType;
@@ -1398,7 +1438,7 @@
         if (operand is SimpleIdentifier) {
           var element = getWriteOrReadElement(operand);
           if (element is PromotableElement) {
-            _flowAnalysis.write(element, staticType);
+            _flowAnalysis.write(element, staticType, null);
           }
         }
       }
@@ -1537,6 +1577,7 @@
 
   @override
   DecoratedType visitSimpleIdentifier(SimpleIdentifier node) {
+    DecoratedType targetType;
     DecoratedType result;
     var staticElement = getWriteOrReadElement(node);
     if (staticElement is PromotableElement) {
@@ -1556,15 +1597,16 @@
     } else if (staticElement is FunctionElement ||
         staticElement is MethodElement ||
         staticElement is ConstructorElement) {
-      result = getOrComputeElementType(staticElement,
-          targetType: staticElement.enclosingElement is ClassElement
-              ? _thisOrSuper(node)
-              : null);
+      if (staticElement.enclosingElement is ClassElement) {
+        targetType = _thisOrSuper(node);
+      }
+      result = getOrComputeElementType(staticElement, targetType: targetType);
     } else if (staticElement is PropertyAccessorElement) {
-      var elementType = getOrComputeElementType(staticElement,
-          targetType: staticElement.enclosingElement is ClassElement
-              ? _thisOrSuper(node)
-              : null);
+      if (staticElement.enclosingElement is ClassElement) {
+        targetType = _thisOrSuper(node);
+      }
+      var elementType =
+          getOrComputeElementType(staticElement, targetType: targetType);
       result = staticElement.isGetter
           ? elementType.returnType
           : elementType.positionalParameters[0];
@@ -1583,6 +1625,9 @@
       _unimplemented(node,
           'Simple identifier with a static element of type ${staticElement.runtimeType}');
     }
+    if (targetType != null) {
+      _checkThisNotNull(targetType, node);
+    }
     return result;
   }
 
@@ -1742,8 +1787,10 @@
       _typeNameNesting++;
       var typeArguments = typeName.typeArguments?.arguments;
       var element = typeName.name.staticElement;
-      if (element is FunctionTypeAliasElement) {
-        final typedefType = _variables.decoratedElementType(element.function);
+      if (element is TypeAliasElement) {
+        var aliasedElement =
+            element.aliasedElement as GenericFunctionTypeElement;
+        final typedefType = _variables.decoratedElementType(aliasedElement);
         final typeNameType =
             _variables.decoratedTypeAnnotation(source, typeName);
 
@@ -1946,6 +1993,18 @@
     return sourceType;
   }
 
+  /// Generates the appropriate edge to assert that the value of `this` is
+  /// non-null.
+  void _checkThisNotNull(DecoratedType thisType, AstNode node) {
+    // `this` can only be `null` in extensions, so if we're not in an extension,
+    // there's nothing to do.
+    if (_currentExtendedType == null) return;
+    var origin = ImplicitThisOrigin(source, node);
+    var hard =
+        _postDominatedLocals.isInScope(_postDominatedLocals.extensionThis);
+    _graph.makeNonNullable(thisType.node, origin, hard: hard, guards: _guards);
+  }
+
   @override
   void _connect(NullabilityNode source, NullabilityNode destination,
       EdgeOrigin origin, FixReasonTarget edgeTarget,
@@ -2155,8 +2214,12 @@
       }
       return type;
     } catch (exception, stackTrace) {
-      listener.reportException(source, node, exception, stackTrace);
-      return null;
+      if (listener != null) {
+        listener.reportException(source, node, exception, stackTrace);
+        return null;
+      } else {
+        rethrow;
+      }
     }
   }
 
@@ -2340,7 +2403,8 @@
         }
       }
       if (destinationLocalVariable != null) {
-        _flowAnalysis.write(destinationLocalVariable, sourceType);
+        _flowAnalysis.write(destinationLocalVariable, sourceType,
+            compoundOperatorInfo == null ? expression : null);
       }
       if (questionAssignNode != null) {
         _flowAnalysis.ifNullExpression_end();
@@ -2356,7 +2420,12 @@
       }
     }
     if (destinationExpression != null) {
-      _postDominatedLocals.removeReferenceFromAllScopes(destinationExpression);
+      var element =
+          _postDominatedLocals.referencedElement(destinationExpression);
+      if (element != null) {
+        _postDominatedLocals.removeFromAllScopes(element);
+        _elementsWrittenToInLocalFunction?.add(element);
+      }
     }
     return sourceType;
   }
@@ -2406,6 +2475,9 @@
     _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);
+    }
     try {
       _dispatchList(initializers);
       if (declaredElement is ConstructorElement &&
@@ -2970,16 +3042,16 @@
     }
   }
 
-  DecoratedType _handleTarget(Expression target, String name, Element method) {
+  DecoratedType _handleTarget(Expression target, String name, Element callee) {
     if (isDeclaredOnObject(name)) {
       return _dispatch(target);
-    } else if (method is MethodElement &&
-        method.enclosingElement is ExtensionElement) {
+    } else if ((callee is MethodElement || callee is PropertyAccessorElement) &&
+        callee.enclosingElement is ExtensionElement) {
       // Extension methods can be called on a `null` target, when the `on` type
       // of the extension is nullable.
       return _handleAssignment(target,
           destinationType:
-              _variables.decoratedElementType(method.enclosingElement));
+              _variables.decoratedElementType(callee.enclosingElement));
     } else {
       return _checkExpressionNotNull(target);
     }
@@ -3613,20 +3685,25 @@
 ///
 /// 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) {
-    expression = expression.unParenthesized;
-    if (expression is SimpleIdentifier) {
-      var element = expression.staticElement;
-      return isInScope(element);
-    }
-    return false;
+    var element = referencedElement(expression);
+    return element != null && isInScope(element);
   }
 
-  void removeReferenceFromAllScopes(Expression expression) {
+  /// Returns the element referenced directly by [expression], if any; otherwise
+  /// returns `null`.
+  Element referencedElement(Expression expression) {
     expression = expression.unParenthesized;
     if (expression is SimpleIdentifier) {
-      var element = expression.staticElement;
-      removeFromAllScopes(element);
+      return expression.staticElement;
+    } else if (expression is ThisExpression || expression is SuperExpression) {
+      return extensionThis;
+    } else {
+      return null;
     }
   }
 }
diff --git a/pkg/nnbd_migration/lib/src/edge_origin.dart b/pkg/nnbd_migration/lib/src/edge_origin.dart
index 5b42111..cff0b7b 100644
--- a/pkg/nnbd_migration/lib/src/edge_origin.dart
+++ b/pkg/nnbd_migration/lib/src/edge_origin.dart
@@ -85,6 +85,18 @@
   EdgeOriginKind get kind => EdgeOriginKind.argumentErrorCheckNotNull;
 }
 
+/// An edge origin used for edges that originated because of a tear-off of
+/// `call` on a function type.
+class CallTearOffOrigin extends EdgeOrigin {
+  CallTearOffOrigin(Source source, AstNode node) : super(source, node);
+
+  @override
+  String get description => 'tear-off of .call';
+
+  @override
+  EdgeOriginKind get kind => EdgeOriginKind.callTearOff;
+}
+
 /// Edge origin resulting from the use of a value on the LHS of a compound
 /// assignment.
 class CompoundAssignmentOrigin extends EdgeOrigin {
@@ -312,6 +324,18 @@
   ReturnStatement get node => super.node as ReturnStatement;
 }
 
+/// Edge origin used for edges that arise from an implicit use of `this`, e.g.
+/// during a method call from an extension.
+class ImplicitThisOrigin extends EdgeOrigin {
+  ImplicitThisOrigin(Source source, AstNode node) : super(source, node);
+
+  @override
+  String get description => 'implicit use of `this`';
+
+  @override
+  EdgeOriginKind get kind => EdgeOriginKind.implicitThis;
+}
+
 /// Edge origin resulting from the inference of a type parameter, which
 /// can affects the nullability of that type parameter's bound.
 class InferredTypeParameterInstantiationOrigin extends EdgeOrigin {
@@ -397,18 +421,6 @@
   EdgeOriginKind get kind => EdgeOriginKind.listLengthConstructor;
 }
 
-/// An edge origin used for edges that originated because of a tear-off of
-/// `call` on a function type.
-class CallTearOffOrigin extends EdgeOrigin {
-  CallTearOffOrigin(Source source, AstNode node) : super(source, node);
-
-  @override
-  String get description => 'tear-off of .call';
-
-  @override
-  EdgeOriginKind get kind => EdgeOriginKind.callTearOff;
-}
-
 /// An edge origin used for edges that originated because a literal expression
 /// has a known nullability.
 class LiteralOrigin extends EdgeOrigin {
diff --git a/pkg/nnbd_migration/lib/src/fix_aggregator.dart b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
index 2105912..6e57d8d 100644
--- a/pkg/nnbd_migration/lib/src/fix_aggregator.dart
+++ b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
@@ -218,7 +218,7 @@
   Iterable<String> get _toStringParts => const [];
 
   @override
-  toString() => '$runtimeType(${_toStringParts.join(', ')})';
+  String toString() => '$runtimeType(${_toStringParts.join(', ')})';
 
   /// Applies this change to the given [node], producing an [EditPlan].  The
   /// [aggregator] may be used to gather up any edits to the node's descendants
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 1d4748f..687b07b 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -495,6 +495,20 @@
         (_shouldStayNullAware[node] ??= _fixBuilder._shouldStayNullAware(node));
   }
 
+  /// Indicates whether the given [element] is a member of an extension on a
+  /// potentially nullable type (and hence the extension member can be invoked
+  /// on a nullable type without introducing a null check).
+  bool isNullableExtensionMember(Element element) {
+    if (element != null) {
+      var enclosingElement = element.enclosingElement;
+      if (enclosingElement is ExtensionElement) {
+        return _fixBuilder._typeSystem
+            .isPotentiallyNullable(enclosingElement.extendedType);
+      }
+    }
+    return false;
+  }
+
   @override
   bool isPropertyAccessNullAware(PropertyAccess node) {
     return node.isNullAware &&
@@ -705,38 +719,49 @@
             operatorType == TokenType.BANG_EQ) {
           return false;
         } else {
-          return true;
+          return !isNullableExtensionMember(parent.staticElement);
         }
       }
     } else if (parent is PrefixedIdentifier) {
-      if (isDeclaredOnObject(parent.identifier.name)) {
+      if (isDeclaredOnObject(parent.identifier.name) ||
+          isNullableExtensionMember(parent.identifier.staticElement)) {
         return false;
       }
       return identical(node, parent.prefix);
     } else if (parent is PropertyAccess) {
-      if (isDeclaredOnObject(parent.propertyName.name)) {
+      if (isDeclaredOnObject(parent.propertyName.name) ||
+          isNullableExtensionMember(parent.propertyName.staticElement)) {
         return false;
       }
       // TODO(paulberry): what about cascaded?
       return parent.operator.type == TokenType.PERIOD &&
           identical(node, parent.target);
     } else if (parent is MethodInvocation) {
-      if (isDeclaredOnObject(parent.methodName.name)) {
+      if (isDeclaredOnObject(parent.methodName.name) ||
+          isNullableExtensionMember(parent.methodName.staticElement)) {
         return false;
       }
       // TODO(paulberry): what about cascaded?
       return parent.operator.type == TokenType.PERIOD &&
           identical(node, parent.target);
     } else if (parent is IndexExpression) {
-      return identical(node, parent.target);
+      if (identical(node, parent.target)) {
+        return !isNullableExtensionMember(parent.staticElement);
+      } else {
+        return false;
+      }
     } else if (parent is ConditionalExpression) {
       return identical(node, parent.condition);
     } else if (parent is FunctionExpressionInvocation) {
-      return identical(node, parent.function);
+      if (identical(node, parent.function)) {
+        return !isNullableExtensionMember(parent.staticElement);
+      } else {
+        return false;
+      }
     } else if (parent is PrefixExpression) {
       // TODO(paulberry): for prefix increment/decrement, inserting a null check
       // isn't sufficient.
-      return true;
+      return !isNullableExtensionMember(parent.staticElement);
     } else if (parent is ThrowExpression) {
       return true;
     }
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 2b8289c..7852c1d 100644
--- a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
@@ -25,6 +25,7 @@
 import 'package:nnbd_migration/src/front_end/migration_info.dart';
 import 'package:nnbd_migration/src/front_end/offset_mapper.dart';
 import 'package:nnbd_migration/src/front_end/web/navigation_tree.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:nnbd_migration/src/utilities/progress_bar.dart';
 
 /// A builder used to build the migration information for a library.
@@ -54,9 +55,24 @@
   /// unit.
   final Map<String, UnitInfo> unitMap = {};
 
+  /// A function which returns whether a file at a given path should be
+  /// migrated.
+  final bool Function(String) shouldBeMigratedFunction;
+
+  /// The set of files which are being considered for migration.
+  final Iterable<String> _pathsToProcess;
+
   /// Initialize a newly created builder.
-  InfoBuilder(this.provider, this.includedPath, this.info, this.listener,
-      this.migration, this.nodeMapper, this._logger);
+  InfoBuilder(
+      this.provider,
+      this.includedPath,
+      this.info,
+      this.listener,
+      this.migration,
+      this.nodeMapper,
+      this._logger,
+      this.shouldBeMigratedFunction,
+      this._pathsToProcess);
 
   /// The provider used to get information about libraries.
   DriverProviderImpl get driverProvider => listener.server;
@@ -67,11 +83,18 @@
     var sourceInfoMap = info.sourceInformation;
     Set<UnitInfo> units =
         SplayTreeSet<UnitInfo>((u1, u2) => u1.path.compareTo(u2.path));
-    var progressBar = ProgressBar(_logger, sourceInfoMap.length);
 
-    for (var source in sourceInfoMap.keys) {
+    // Collect all of the sources for which we have [SourceInformation], as well
+    // as all files which are being "processed" during this migration, which may
+    // include already migrated files.
+    var sources = {
+      ...sourceInfoMap.keys.map((source) => source.fullName),
+      ..._pathsToProcess,
+    };
+    var progressBar = ProgressBar(_logger, sources.length);
+
+    for (var filePath in sources) {
       progressBar.tick();
-      var filePath = source.fullName;
       var session = driverProvider.getAnalysisSession(filePath);
       if (!session.getFile(filePath).isPart) {
         var result = await session.getResolvedLibrary(filePath);
@@ -90,7 +113,7 @@
           sourceInfo ??= SourceInformation();
           var edit = listener.sourceChange.getFileEdit(unitResult.path);
           var unit = _explainUnit(sourceInfo, unitResult, edit);
-          if (provider.pathContext.isWithin(includedPath, unitResult.path)) {
+          if (_pathsToProcess.contains(unitResult.path)) {
             units.add(unit);
           }
         }
@@ -353,9 +376,16 @@
     var alreadyMigrated =
         result.unit.featureSet.isEnabled(Feature.non_nullable);
     unitInfo.wasExplicitlyOptedOut = result.unit.languageVersionToken != null;
-    unitInfo.migrationStatus = alreadyMigrated
-        ? UnitMigrationStatus.alreadyMigrated
-        : UnitMigrationStatus.migrating;
+    if (alreadyMigrated) {
+      unitInfo.migrationStatus = UnitMigrationStatus.alreadyMigrated;
+      unitInfo.migrationStatusCanBeChanged = false;
+    } else if (shouldBeMigratedFunction(result.path)) {
+      unitInfo.migrationStatus = UnitMigrationStatus.migrating;
+      unitInfo.migrationStatusCanBeChanged = true;
+    } else {
+      unitInfo.migrationStatus = UnitMigrationStatus.optingOut;
+      unitInfo.migrationStatusCanBeChanged = false;
+    }
     var regions = unitInfo.regions;
 
     // There are certain rare conditions involving generated code in a bazel
diff --git a/pkg/nnbd_migration/lib/src/front_end/migration_info.dart b/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
index 42c3804..9f261cd 100644
--- a/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
@@ -6,11 +6,11 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:collection/collection.dart';
 import 'package:crypto/crypto.dart';
-import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/front_end/offset_mapper.dart';
 import 'package:nnbd_migration/src/front_end/unit_link.dart';
 import 'package:nnbd_migration/src/front_end/web/navigation_tree.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:nnbd_migration/src/preview/preview_site.dart';
 import 'package:path/path.dart' as path;
 
@@ -39,24 +39,6 @@
           sourceEdit.replacement);
 }
 
-/// Everything the front end needs to know to tell the server to perform a hint
-/// action.
-class HintAction {
-  final HintActionKind kind;
-  final int nodeId;
-  HintAction(this.kind, this.nodeId);
-
-  HintAction.fromJson(Map<String, Object> json)
-      : nodeId = json['nodeId'] as int,
-        kind = HintActionKind.values
-            .singleWhere((action) => action.index == json['kind']);
-
-  Map<String, Object> toJson() => {
-        'nodeId': nodeId,
-        'kind': kind.index,
-      };
-}
-
 /// A class storing rendering information for an entire migration report.
 ///
 /// This generally provides one [InstrumentationRenderer] (for one library)
@@ -96,17 +78,29 @@
   /// The path of the Roboto Mono font.
   String get robotoMonoFont => PreviewSite.robotoMonoFontPath;
 
+  /// Returns the absolute path of [path], as relative to [includedRoot].
+  String absolutePathFromRoot(String path) =>
+      pathContext.join(includedRoot, path);
+
+  /// Returns the relative path of [path] from [includedRoot].
+  String relativePathFromRoot(String path) =>
+      pathContext.relative(path, from: includedRoot);
+
   /// Return the path to [unit] from [includedRoot], to be used as a display
   /// name for a library.
-  String computeName(UnitInfo unit) =>
-      pathContext.relative(unit.path, from: includedRoot);
+  String computeName(UnitInfo unit) => relativePathFromRoot(unit.path);
 
   List<UnitLink> unitLinks() {
     var links = <UnitLink>[];
     for (var unit in units) {
       var count = unit.fixRegions.length;
-      links.add(UnitLink(unit.path, pathContext.split(computeName(unit)), count,
-          unit.wasExplicitlyOptedOut, unit.migrationStatus));
+      links.add(UnitLink(
+          unit.path,
+          pathContext.split(computeName(unit)),
+          count,
+          unit.wasExplicitlyOptedOut,
+          unit.migrationStatus,
+          unit.migrationStatusCanBeChanged));
     }
     return links;
   }
@@ -152,7 +146,7 @@
   int get hashCode => JenkinsSmiHash.hash3(filePath.hashCode, offset, length);
 
   @override
-  bool operator ==(other) {
+  bool operator ==(Object other) {
     return other is NavigationTarget &&
         other.filePath == filePath &&
         other.offset == offset &&
@@ -283,7 +277,9 @@
 
   /// Whether this compilation unit was explicitly opted out of null safety at
   /// the start of this migration.
-  bool wasExplicitlyOptedOut;
+  /*late*/ bool wasExplicitlyOptedOut;
+
+  /*late*/ bool migrationStatusCanBeChanged;
 
   /// Indicates the migration status of this unit.
   ///
diff --git a/pkg/nnbd_migration/lib/src/front_end/migration_state.dart b/pkg/nnbd_migration/lib/src/front_end/migration_state.dart
index 016c204..d65d0cf 100644
--- a/pkg/nnbd_migration/lib/src/front_end/migration_state.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/migration_state.dart
@@ -50,9 +50,18 @@
   /// required version of each package.
   final Map<String, Version> neededPackages;
 
+  /// A function which returns whether a file at a given path should be
+  /// migrated.
+  final bool Function(String) shouldBeMigratedFunction;
+
   /// Initialize a newly created migration state with the given values.
-  MigrationState(this.migration, this.includedRoot, this.listener,
-      this.instrumentationListener, this.neededPackages,
+  MigrationState(
+      this.migration,
+      this.includedRoot,
+      this.listener,
+      this.instrumentationListener,
+      this.neededPackages,
+      this.shouldBeMigratedFunction,
       [this.analysisResult])
       : assert(neededPackages != null);
 
@@ -68,11 +77,19 @@
   }
 
   /// Refresh the state of the migration after the migration has been updated.
-  Future<void> refresh(Logger logger) async {
+  Future<void> refresh(Logger logger, Iterable<String> pathsToProcess) async {
     assert(!hasBeenApplied);
     var provider = listener.server.resourceProvider;
-    var infoBuilder = InfoBuilder(provider, includedRoot,
-        instrumentationListener.data, listener, migration, nodeMapper, logger);
+    var infoBuilder = InfoBuilder(
+        provider,
+        includedRoot,
+        instrumentationListener.data,
+        listener,
+        migration,
+        nodeMapper,
+        logger,
+        shouldBeMigratedFunction,
+        pathsToProcess);
     var unitInfos = await infoBuilder.explainMigration();
     var pathContext = provider.pathContext;
     migrationInfo = MigrationInfo(
diff --git a/pkg/nnbd_migration/lib/src/front_end/navigation_tree_renderer.dart b/pkg/nnbd_migration/lib/src/front_end/navigation_tree_renderer.dart
index 290f96e..86080eb 100644
--- a/pkg/nnbd_migration/lib/src/front_end/navigation_tree_renderer.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/navigation_tree_renderer.dart
@@ -68,6 +68,7 @@
           editCount: link.editCount,
           wasExplicitlyOptedOut: link.wasExplicitlyOptedOut,
           migrationStatus: link.migrationStatus,
+          migrationStatusCanBeChanged: link.migrationStatusCanBeChanged,
         ),
     ];
   }
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 6ec0a2e..20e8f55 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
@@ -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:async';
 import 'dart:convert' show jsonDecode, JsonEncoder;
 
 import 'package:analyzer/dart/analysis/features.dart';
@@ -74,8 +75,18 @@
   /// A list of the URLs corresponding to the included roots.
   List<String> previewUrls;
 
+  /// A function which returns whether a file at a given path should be
+  /// migrated.
+  final bool Function(String) shouldBeMigratedFunction;
+
+  /// The set of files which are being considered for migration.
+  Iterable<String> pathsToProcess;
+
+  /// Completes when the server has been shutdown.
+  Completer<void> serverIsShutdown;
+
   NonNullableFix(this.listener, this.resourceProvider, this._getLineInfo,
-      this.bindAddress, this._logger,
+      this.bindAddress, this._logger, this.shouldBeMigratedFunction,
       {List<String> included = const [],
       this.preferredPort,
       this.summaryPath,
@@ -107,8 +118,8 @@
   Future<MigrationState> finish() async {
     var neededPackages = migration.finish();
     final state = MigrationState(migration, includedRoot, listener,
-        instrumentationListener, neededPackages);
-    await state.refresh(_logger);
+        instrumentationListener, neededPackages, shouldBeMigratedFunction);
+    await state.refresh(_logger, pathsToProcess);
     return state;
   }
 
@@ -170,8 +181,11 @@
   }
 
   void shutdownServer() {
-    _server?.close();
-    _server = null;
+    if (_server != null) {
+      _server.close();
+      _server = null;
+      serverIsShutdown.complete();
+    }
   }
 
   Future<void> startPreviewServer(
@@ -179,13 +193,18 @@
     // This method may be called multiple times, for example during a re-run.
     // But the preview server should only be started once.
     if (_server == null) {
-      _server = HttpPreviewServer(
-          state, rerun, applyHook, bindAddress, preferredPort);
+      var wrappedApplyHookWithShutdown = () {
+        shutdownServer();
+        applyHook();
+      };
+      _server = HttpPreviewServer(state, rerun, wrappedApplyHookWithShutdown,
+          bindAddress, preferredPort, _logger);
       _server.serveHttp();
       _allServers.add(_server);
       var serverHostname = await _server.boundHostname;
       var serverPort = await _server.boundPort;
       authToken = await _server.authToken;
+      serverIsShutdown = Completer();
 
       previewUrls = [
         // TODO(jcollins-g): Change protocol to only return a single string.
@@ -380,16 +399,34 @@
       VersionConstraint currentConstraint;
       if (node.value is String) {
         currentConstraint = VersionConstraint.parse(node.value as String);
-        if (currentConstraint is VersionRange &&
-            currentConstraint.min >= minimumVersion) {
-          // The current version constraint is already up to date.  Do not edit.
+        var invalidVersionMessage =
+            'The current SDK constraint in pubspec.yaml is invalid. A '
+            'minimum version, such as ">=2.7.0", is required when launching '
+            "'dart migrate'.";
+        if (currentConstraint is Version) {
+          // In this case, the constraint is an exact version, like 2.0.0.
+          _logger.stderr(invalidVersionMessage);
           return false;
+        } else if (currentConstraint is VersionRange) {
+          if (currentConstraint.min == null) {
+            _logger.stderr(invalidVersionMessage);
+            return false;
+          } else if (currentConstraint.min >= minimumVersion) {
+            // The current version constraint is already up to date.  Do not
+            // edit.
+            return false;
+          } else {
+            // TODO(srawlins): This overwrites the current maximum version. In
+            // the uncommon situation that there is a special maximum, it should
+            // not.
+            pubspec._replaceSpan(node.span, fullVersionConstraint, listener);
+            return true;
+          }
         } else {
-          // TODO(srawlins): This overwrites the current maximum version. In
-          // the uncommon situation that there is a special maximum, it should
-          // not.
-          pubspec._replaceSpan(node.span, fullVersionConstraint, listener);
-          return true;
+          // The constraint is something different, like a union, like
+          // '>=1.0.0 <2.0.0 >=3.0.0 <4.0.0', which is not valid.
+          _logger.stderr(invalidVersionMessage);
+          return false;
         }
       } else {
         // Something is odd with the constraint we've found in pubspec.yaml;
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/index.html b/pkg/nnbd_migration/lib/src/front_end/resources/index.html
index f56877d..f24e6a8 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/index.html
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/index.html
@@ -26,7 +26,7 @@
     <h2 class="before-apply">Proposed null safety changes</h2>
     <h2 class="after-apply">&#10003; Null safety migration applied</h2>
     <a target="_blank"
-       href="https://goo.gle/dart-null-safety-migration-tool">
+       href="https://dart.dev/go/null-safety-migration">
       <button class="action-button">
         <i class="material-icons">launch</i>
         <span>Help</span>
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/migration.css b/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
index 257cfef..a715e60 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
@@ -218,6 +218,10 @@
   color: #007a27; /* $light-green */
 }
 
+.status-icon.disabled {
+  cursor: not-allowed;
+}
+
 .status-icon.opted-out {
   color: #676767; /* $secondary-color */
 }
@@ -293,11 +297,12 @@
 }
 
 .file {
+  display: flex;
+  flex-direction: column;
   flex: 4 300px;
   font-family: "Google Sans","Roboto",sans-serif;
   background: #12202f;
-  margin: 6px;
-  overflow: scroll;
+  margin: 0 6px;
 }
 
 .title-bar h3 {
@@ -315,8 +320,7 @@
 }
 
 .title-bar #migrate-unit-status-icon-label.visible {
-  /* Change to 'inline' to enable the incremental migration feature. */
-  display: none;
+  display: inline;
 }
 
 .title-bar #migrate-unit-status-icon {
@@ -324,7 +328,9 @@
 }
 
 .content {
+  flex-grow: 1;
   font-family: "Roboto Mono",monospace;
+  overflow: scroll;
   position: relative;
   white-space: pre;
 }
@@ -424,7 +430,7 @@
   background-color: #263952;
   color: #fff;
   display: inline-block;
-  height: 15px;
+  height: 14px;
   position: relative;
 }
 
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
index b03dfe6..a787415 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
@@ -7422,7 +7422,7 @@
 ''';
 
 String _index_html;
-// index_html md5 is '4dc4d54418f267d0f9189690626e0f2a'
+// index_html md5 is 'c4127573314e7a91769cf9e0bcb489b1'
 String _index_html_base64 = '''
 PGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPk51bGwgU2FmZXR5IFByZXZpZXc8L3RpdGxlPgogICAgPHNj
 cmlwdCBzcmM9Int7IGhpZ2hsaWdodEpzUGF0aCB9fSI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0Pnt7IGRh
@@ -7443,57 +7443,57 @@
 YWx0PSJEYXJ0UGFkIExvZ28iIGNsYXNzPSJsb2dvIi8+CiAgICA8aDE+RGFydDwvaDE+CiAgICA8aDIg
 Y2xhc3M9ImJlZm9yZS1hcHBseSI+UHJvcG9zZWQgbnVsbCBzYWZldHkgY2hhbmdlczwvaDI+CiAgICA8
 aDIgY2xhc3M9ImFmdGVyLWFwcGx5Ij4mIzEwMDAzOyBOdWxsIHNhZmV0eSBtaWdyYXRpb24gYXBwbGll
-ZDwvaDI+CiAgICA8YSB0YXJnZXQ9Il9ibGFuayIKICAgICAgIGhyZWY9Imh0dHBzOi8vZ29vLmdsZS9k
-YXJ0LW51bGwtc2FmZXR5LW1pZ3JhdGlvbi10b29sIj4KICAgICAgPGJ1dHRvbiBjbGFzcz0iYWN0aW9u
-LWJ1dHRvbiI+CiAgICAgICAgPGkgY2xhc3M9Im1hdGVyaWFsLWljb25zIj5sYXVuY2g8L2k+CiAgICAg
-ICAgPHNwYW4+SGVscDwvc3Bhbj4KICAgICAgPC9idXR0b24+CiAgICA8L2E+CiAgICA8YnV0dG9uIGNs
-YXNzPSJhY3Rpb24tYnV0dG9uIGFwcGx5LW1pZ3JhdGlvbiI+CiAgICAgICAgPGkgY2xhc3M9Im1hdGVy
-aWFsLWljb25zIj5lZGl0PC9pPgogICAgICAgIDxzcGFuIGNsYXNzPSJsYWJlbCI+CiAgICAgICAgICBB
-cHBseSBNaWdyYXRpb24KICAgICAgICA8L3NwYW4+CiAgICA8L2J1dHRvbj4KICAgIDxidXR0b24gY2xh
-c3M9ImFjdGlvbi1idXR0b24gYXBwbHktbWlncmF0aW9uIiBkaXNhYmxlZD4KICAgICAgICA8aSBjbGFz
-cz0ibWF0ZXJpYWwtaWNvbnMiPmVkaXQ8L2k+CiAgICAgICAgPHNwYW4gY2xhc3M9ImxhYmVsIj4KICAg
-ICAgICAgIEFwcGx5IE1pZ3JhdGlvbgogICAgICAgIDwvc3Bhbj4KICAgIDwvYnV0dG9uPgogICAgPGJ1
-dHRvbiBjbGFzcz0iYWN0aW9uLWJ1dHRvbiByZXJ1bi1taWdyYXRpb24gYmVmb3JlLWFwcGx5Ij4KICAg
-ICAgPHNwYW4gY2xhc3M9Im9wdGlvbmFsIj4KICAgICAgICA8aSBjbGFzcz0ibWF0ZXJpYWwtaWNvbnMi
-PnJlcGxheTwvaT4KICAgICAgICBSZXJ1biBGcm9tIFNvdXJjZXMKICAgICAgPC9zcGFuPgogICAgICA8
-c3BhbiBjbGFzcz0icmVxdWlyZWQiPgogICAgICAgIDxpIGNsYXNzPSJtYXRlcmlhbC1pY29ucyI+d2Fy
-bmluZzwvaT4KICAgICAgICBSZXJ1biBXaXRoIENoYW5nZXMKICAgICAgPC9zcGFuPgogICAgPC9idXR0
-b24+CjwvaGVhZGVyPgo8ZGl2IGNsYXNzPSJwYW5lbHMgaG9yaXpvbnRhbCI+CiAgICA8ZGl2IGNsYXNz
-PSJuYXYtcGFuZWwiPgogICAgICAgIDxkaXYgY2xhc3M9Im5hdi1pbm5lciI+CiAgICAgICAgICAgIDxk
-aXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPlByb2plY3QgRmlsZXM8L2Rpdj4KICAgICAgICAgICAgPGRp
-diBjbGFzcz0ibmF2LXRyZWUiPjwvZGl2PgogICAgICAgIDwvZGl2PjwhLS0gL25hdi1pbm5lciAtLT4K
-ICAgIDwvZGl2PjwhLS0gL25hdiAtLT4KICAgIDxkaXYgY2xhc3M9ImZpbGUiPgogICAgICAgIDxkaXYg
-Y2xhc3M9InRpdGxlLWJhciI+CiAgICAgICAgICAgIDxoMyBpZD0idW5pdC1uYW1lIj4mbmJzcDs8L2gz
-PgogICAgICAgICAgICA8c3BhbiBpZD0ibWlncmF0ZS11bml0LXN0YXR1cy1pY29uLWxhYmVsIj5NaWdy
-YXRlCiAgICAgICAgICAgICAgICA8c3BhbgogICAgICAgICAgICAgICAgICAgIGNsYXNzPSJtYXRlcmlh
-bC1pY29ucyBzdGF0dXMtaWNvbiBtaWdyYXRpbmciCiAgICAgICAgICAgICAgICAgICAgaWQ9Im1pZ3Jh
-dGUtdW5pdC1zdGF0dXMtaWNvbiI+Y2hlY2tfYm94PC9zcGFuPgogICAgICAgICAgICA8L3NwYW4+CiAg
-ICAgICAgPC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0iY29udGVudCI+CiAgICAgICAgICAgIDxkaXYg
-Y2xhc3M9InJlZ2lvbnMiPgogICAgICAgICAgICAgICAgPCEtLSBUaGUgcmVnaW9ucyBvdmVybGF5IGNv
-ZGUgY29weSBvZiB0aGUgY29udGVudCB0byBwcm92aWRlIC0tPgogICAgICAgICAgICAgICAgPCEtLSB0
-b29sdGlwcyBmb3IgbW9kaWZpZWQgcmVnaW9ucy4gLS0+CiAgICAgICAgICAgIDwvZGl2PjwhLS0gL3Jl
-Z2lvbnMgLS0+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvZGUiPgogICAgICAgICAgICAgICAgPCEt
-LSBDb21waWxhdGlvbiB1bml0IGNvbnRlbnQgaXMgd3JpdHRlbiBoZXJlLiAtLT4KICAgICAgICAgICAg
-ICAgIDxwIGNsYXNzPSJ3ZWxjb21lIj4KICAgICAgICAgICAgICAgICAgICBTZWxlY3QgYSBzb3VyY2Ug
-ZmlsZSBvbiB0aGUgbGVmdCB0byBwcmV2aWV3IHRoZSBwcm9wb3NlZCBlZGl0cy4KICAgICAgICAgICAg
-ICAgIDwvcD4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICA8L2Rpdj48IS0tIC9j
-b250ZW50IC0tPgogICAgPGRpdiBjbGFzcz0iaW5mby1wYW5lbCI+CiAgICAgICAgPGRpdiBjbGFzcz0i
-ZWRpdC1saXN0Ij4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+UHJvcG9zZWQg
-RWRpdHM8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtY29udGVudCI+PC9kaXY+CiAg
-ICAgICAgPC9kaXY+PCEtLSAvZWRpdC1saXN0IC0tPgogICAgICAgIDxkaXYgY2xhc3M9ImVkaXQtcGFu
-ZWwiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkaW5nIj5FZGl0IERldGFpbHM8L2Rp
-dj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtY29udGVudCI+CiAgICAgICAgICAgICAgICA8
-cCBjbGFzcz0icGxhY2Vob2xkZXIiPlNlZSBkZXRhaWxzIGFib3V0IGEgcHJvcG9zZWQgZWRpdC48L3A+
-CiAgICAgICAgICAgIDwvZGl2PjwhLS0gL3BhbmVsLWNvbnRlbnQgLS0+CiAgICAgICAgPC9kaXY+PCEt
-LSAvZWRpdC1wYW5lbCAtLT4KICAgIDwvZGl2PjwhLS0gL2luZm8tcGFuZWwgLS0+CjwvZGl2PjwhLS0g
-L3BhbmVscyAtLT4KPGZvb3Rlcj4KICA8YnV0dG9uIGNsYXNzPSJyZXBvcnQtcHJvYmxlbSI+U2VuZCBG
-ZWVkYmFjazwvYnV0dG9uPgogICAgPHNwYW4gY2xhc3M9IndpZGUiPiA8L3NwYW4+CiAgICA8ZGl2IGNs
-YXNzPSJzZGstdmVyc2lvbiI+QmFzZWQgb24gPHNwYW4gaWQ9InNkay12ZXJzaW9uIj57eyBzZGtWZXJz
-aW9uIH19PC9zcGFuPjwvZGl2Pgo8L2Zvb3Rlcj4KPC9ib2R5Pgo8L2h0bWw+Cg==
+ZDwvaDI+CiAgICA8YSB0YXJnZXQ9Il9ibGFuayIKICAgICAgIGhyZWY9Imh0dHBzOi8vZGFydC5kZXYv
+Z28vbnVsbC1zYWZldHktbWlncmF0aW9uIj4KICAgICAgPGJ1dHRvbiBjbGFzcz0iYWN0aW9uLWJ1dHRv
+biI+CiAgICAgICAgPGkgY2xhc3M9Im1hdGVyaWFsLWljb25zIj5sYXVuY2g8L2k+CiAgICAgICAgPHNw
+YW4+SGVscDwvc3Bhbj4KICAgICAgPC9idXR0b24+CiAgICA8L2E+CiAgICA8YnV0dG9uIGNsYXNzPSJh
+Y3Rpb24tYnV0dG9uIGFwcGx5LW1pZ3JhdGlvbiI+CiAgICAgICAgPGkgY2xhc3M9Im1hdGVyaWFsLWlj
+b25zIj5lZGl0PC9pPgogICAgICAgIDxzcGFuIGNsYXNzPSJsYWJlbCI+CiAgICAgICAgICBBcHBseSBN
+aWdyYXRpb24KICAgICAgICA8L3NwYW4+CiAgICA8L2J1dHRvbj4KICAgIDxidXR0b24gY2xhc3M9ImFj
+dGlvbi1idXR0b24gYXBwbHktbWlncmF0aW9uIiBkaXNhYmxlZD4KICAgICAgICA8aSBjbGFzcz0ibWF0
+ZXJpYWwtaWNvbnMiPmVkaXQ8L2k+CiAgICAgICAgPHNwYW4gY2xhc3M9ImxhYmVsIj4KICAgICAgICAg
+IEFwcGx5IE1pZ3JhdGlvbgogICAgICAgIDwvc3Bhbj4KICAgIDwvYnV0dG9uPgogICAgPGJ1dHRvbiBj
+bGFzcz0iYWN0aW9uLWJ1dHRvbiByZXJ1bi1taWdyYXRpb24gYmVmb3JlLWFwcGx5Ij4KICAgICAgPHNw
+YW4gY2xhc3M9Im9wdGlvbmFsIj4KICAgICAgICA8aSBjbGFzcz0ibWF0ZXJpYWwtaWNvbnMiPnJlcGxh
+eTwvaT4KICAgICAgICBSZXJ1biBGcm9tIFNvdXJjZXMKICAgICAgPC9zcGFuPgogICAgICA8c3BhbiBj
+bGFzcz0icmVxdWlyZWQiPgogICAgICAgIDxpIGNsYXNzPSJtYXRlcmlhbC1pY29ucyI+d2FybmluZzwv
+aT4KICAgICAgICBSZXJ1biBXaXRoIENoYW5nZXMKICAgICAgPC9zcGFuPgogICAgPC9idXR0b24+Cjwv
+aGVhZGVyPgo8ZGl2IGNsYXNzPSJwYW5lbHMgaG9yaXpvbnRhbCI+CiAgICA8ZGl2IGNsYXNzPSJuYXYt
+cGFuZWwiPgogICAgICAgIDxkaXYgY2xhc3M9Im5hdi1pbm5lciI+CiAgICAgICAgICAgIDxkaXYgY2xh
+c3M9InBhbmVsLWhlYWRpbmciPlByb2plY3QgRmlsZXM8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFz
+cz0ibmF2LXRyZWUiPjwvZGl2PgogICAgICAgIDwvZGl2PjwhLS0gL25hdi1pbm5lciAtLT4KICAgIDwv
+ZGl2PjwhLS0gL25hdiAtLT4KICAgIDxkaXYgY2xhc3M9ImZpbGUiPgogICAgICAgIDxkaXYgY2xhc3M9
+InRpdGxlLWJhciI+CiAgICAgICAgICAgIDxoMyBpZD0idW5pdC1uYW1lIj4mbmJzcDs8L2gzPgogICAg
+ICAgICAgICA8c3BhbiBpZD0ibWlncmF0ZS11bml0LXN0YXR1cy1pY29uLWxhYmVsIj5NaWdyYXRlCiAg
+ICAgICAgICAgICAgICA8c3BhbgogICAgICAgICAgICAgICAgICAgIGNsYXNzPSJtYXRlcmlhbC1pY29u
+cyBzdGF0dXMtaWNvbiBtaWdyYXRpbmciCiAgICAgICAgICAgICAgICAgICAgaWQ9Im1pZ3JhdGUtdW5p
+dC1zdGF0dXMtaWNvbiI+Y2hlY2tfYm94PC9zcGFuPgogICAgICAgICAgICA8L3NwYW4+CiAgICAgICAg
+PC9kaXY+CiAgICAgICAgPGRpdiBjbGFzcz0iY29udGVudCI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9
+InJlZ2lvbnMiPgogICAgICAgICAgICAgICAgPCEtLSBUaGUgcmVnaW9ucyBvdmVybGF5IGNvZGUgY29w
+eSBvZiB0aGUgY29udGVudCB0byBwcm92aWRlIC0tPgogICAgICAgICAgICAgICAgPCEtLSB0b29sdGlw
+cyBmb3IgbW9kaWZpZWQgcmVnaW9ucy4gLS0+CiAgICAgICAgICAgIDwvZGl2PjwhLS0gL3JlZ2lvbnMg
+LS0+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNvZGUiPgogICAgICAgICAgICAgICAgPCEtLSBDb21w
+aWxhdGlvbiB1bml0IGNvbnRlbnQgaXMgd3JpdHRlbiBoZXJlLiAtLT4KICAgICAgICAgICAgICAgIDxw
+IGNsYXNzPSJ3ZWxjb21lIj4KICAgICAgICAgICAgICAgICAgICBTZWxlY3QgYSBzb3VyY2UgZmlsZSBv
+biB0aGUgbGVmdCB0byBwcmV2aWV3IHRoZSBwcm9wb3NlZCBlZGl0cy4KICAgICAgICAgICAgICAgIDwv
+cD4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICA8L2Rpdj48IS0tIC9jb250ZW50
+IC0tPgogICAgPGRpdiBjbGFzcz0iaW5mby1wYW5lbCI+CiAgICAgICAgPGRpdiBjbGFzcz0iZWRpdC1s
+aXN0Ij4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+UHJvcG9zZWQgRWRpdHM8
+L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtY29udGVudCI+PC9kaXY+CiAgICAgICAg
+PC9kaXY+PCEtLSAvZWRpdC1saXN0IC0tPgogICAgICAgIDxkaXYgY2xhc3M9ImVkaXQtcGFuZWwiPgog
+ICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkaW5nIj5FZGl0IERldGFpbHM8L2Rpdj4KICAg
+ICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtY29udGVudCI+CiAgICAgICAgICAgICAgICA8cCBjbGFz
+cz0icGxhY2Vob2xkZXIiPlNlZSBkZXRhaWxzIGFib3V0IGEgcHJvcG9zZWQgZWRpdC48L3A+CiAgICAg
+ICAgICAgIDwvZGl2PjwhLS0gL3BhbmVsLWNvbnRlbnQgLS0+CiAgICAgICAgPC9kaXY+PCEtLSAvZWRp
+dC1wYW5lbCAtLT4KICAgIDwvZGl2PjwhLS0gL2luZm8tcGFuZWwgLS0+CjwvZGl2PjwhLS0gL3BhbmVs
+cyAtLT4KPGZvb3Rlcj4KICA8YnV0dG9uIGNsYXNzPSJyZXBvcnQtcHJvYmxlbSI+U2VuZCBGZWVkYmFj
+azwvYnV0dG9uPgogICAgPHNwYW4gY2xhc3M9IndpZGUiPiA8L3NwYW4+CiAgICA8ZGl2IGNsYXNzPSJz
+ZGstdmVyc2lvbiI+QmFzZWQgb24gPHNwYW4gaWQ9InNkay12ZXJzaW9uIj57eyBzZGtWZXJzaW9uIH19
+PC9zcGFuPjwvZGl2Pgo8L2Zvb3Rlcj4KPC9ib2R5Pgo8L2h0bWw+Cg==
 ''';
 
 String _migration_css;
-// migration_css md5 is 'cb4dfc4d6f9dd25370605e3a5e35ace6'
+// migration_css md5 is '46b4cc3c93aac35cd6964bf5b91dee2c'
 String _migration_css_base64 = '''
 LyogQ29weXJpZ2h0IChjKSAyMDE5LCB0aGUgRGFydCBwcm9qZWN0IGF1dGhvcnMuIFBsZWFzZSBzZWUg
 dGhlIEFVVEhPUlMgZmlsZSAgKi8KLyogZm9yIGRldGFpbHMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIFVz
@@ -7556,4227 +7556,4268 @@
 ZXJpYWwtaWNvbnMgewogIGZvbnQtc2l6ZTogMjBweDsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdG9w
 OiA1cHg7CiAgbWFyZ2luLXJpZ2h0OiA4cHg7CiAgY29sb3I6ICM2NzY3Njc7IC8qICRzZWNvbmRhcnkt
 Y29sb3IgKi8KfQoKLnN0YXR1cy1pY29uLmFscmVhZHktbWlncmF0ZWQgewogIGNvbG9yOiAjMDA3YTI3
-OyAvKiAkbGlnaHQtZ3JlZW4gKi8KfQoKLnN0YXR1cy1pY29uLm9wdGVkLW91dCB7CiAgY29sb3I6ICM2
-NzY3Njc7IC8qICRzZWNvbmRhcnktY29sb3IgKi8KfQoKLnN0YXR1cy1pY29uLm9wdGVkLW91dDpob3Zl
-ciB7CiAgY29sb3I6ICNmZmZmZmY7Cn0KCi5zdGF0dXMtaWNvbi5taWdyYXRpbmcgewogIGNvbG9yOiAj
-NTFjNjg2OyAvKiAkZGFyay1ncmVlbiAqLwp9Cgouc3RhdHVzLWljb24ubWlncmF0aW5nOmhvdmVyIHsK
-ICBjb2xvcjogI2ZmZmZmZjsKfQoKLm5hdi1pbm5lciB1bCB7CiAgcGFkZGluZy1sZWZ0OiAxMnB4Owog
-IG1hcmdpbjogMDsKfQoKLm5hdi1pbm5lciBsaSB7CiAgbGlzdC1zdHlsZS10eXBlOiBub25lOwogIHdo
-aXRlLXNwYWNlOiBub3dyYXA7Cn0KCi5uYXYtaW5uZXIgbGk6bm90KC5kaXIpIHsKICBtYXJnaW4tbGVm
-dDogMjBweDsKICBtYXJnaW4tYm90dG9tOiAzcHg7Cn0KCi5uYXYtaW5uZXIgbGkuZGlyIC5hcnJvdyB7
-CiAgY3Vyc29yOiBwb2ludGVyOwogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBmb250LXNpemU6IDEw
-cHg7CiAgbWFyZ2luLXJpZ2h0OiA0cHg7CiAgdHJhbnNpdGlvbjogdHJhbnNmb3JtIDAuNXMgZWFzZS1v
-dXQ7Cn0KCi5uYXYtaW5uZXIgbGkuZGlyIC5hcnJvdy5jb2xsYXBzZWQgewogIHRyYW5zZm9ybTogcm90
-YXRlKC05MGRlZyk7Cn0KCi5uYXYtaW5uZXIgdWwgewogIC8qIGEgbWF4LWhlaWdodCBpcyBhZGRlZCB0
-byBlYWNoIGVsZW1lbnQgYXQgcnVudGltZS4gKi8KICB0cmFuc2l0aW9uOiBtYXgtaGVpZ2h0IDAuNXMg
-ZWFzZS1vdXQ7Cn0KCi5uYXYtaW5uZXIgdWwuY29sbGFwc2VkIHsKICBtYXgtaGVpZ2h0OiAwICFpbXBv
-cnRhbnQ7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKfQoKLm5hdi1pbm5lciAuc2VsZWN0ZWQtZmlsZSB7CiAg
-Y29sb3I6IHdoaXRlOwogIGN1cnNvcjogaW5oZXJpdDsKICBmb250LXdlaWdodDogNjAwOwogIHRleHQt
-ZGVjb3JhdGlvbjogbm9uZTsKfQoKLmVkaXQtY291bnQgewogIGJhY2tncm91bmQtY29sb3I6ICM2NzY3
-Njc7CiAgYm9yZGVyLXJhZGl1czogMTBweDsKICBjb2xvcjogI2ZmZjsKICBkaXNwbGF5OiBpbmxpbmUt
-YmxvY2s7CiAgZm9udC1zaXplOiAxMXB4OwogIGZvbnQtd2VpZ2h0OiA2MDA7CiAgbWFyZ2luLWxlZnQ6
-IDVweDsKICBtaW4td2lkdGg6IDI1cHg7CiAgcGFkZGluZzogNHB4IDAgMnB4IDA7CiAgdGV4dC1hbGln
-bjogY2VudGVyOwogIGxpbmUtaGVpZ2h0OiAxZW07Cn0KCi5maWxlIHsKICBmbGV4OiA0IDMwMHB4Owog
-IGZvbnQtZmFtaWx5OiAiR29vZ2xlIFNhbnMiLCJSb2JvdG8iLHNhbnMtc2VyaWY7CiAgYmFja2dyb3Vu
-ZDogIzEyMjAyZjsKICBtYXJnaW46IDZweDsKICBvdmVyZmxvdzogc2Nyb2xsOwp9CgoudGl0bGUtYmFy
-IGgzIHsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgZm9udC13ZWlnaHQ6IDQwMDsKICAvKiBUaGlz
-IGFsaWducyB0aGUgdGl0bGUgdGV4dCB3aXRoIHRoZSBjb250ZW50IHRleHQsIGFjY291bnRpbmcgZm9y
-IHRoZSB3aWR0aAogICAqIG9mIHRoZSBsaW5lIG51bWJlcnMuCiAgICovCiAgbWFyZ2luOiAwLjVlbSAy
-NHB4IDAuNWVtIDYzcHg7Cn0KCi50aXRsZS1iYXIgI21pZ3JhdGUtdW5pdC1zdGF0dXMtaWNvbi1sYWJl
-bCB7CiAgZGlzcGxheTogbm9uZTsKICB1c2VyLXNlbGVjdDogbm9uZTsKfQoKLnRpdGxlLWJhciAjbWln
-cmF0ZS11bml0LXN0YXR1cy1pY29uLWxhYmVsLnZpc2libGUgewogIC8qIENoYW5nZSB0byAnaW5saW5l
-JyB0byBlbmFibGUgdGhlIGluY3JlbWVudGFsIG1pZ3JhdGlvbiBmZWF0dXJlLiAqLwogIGRpc3BsYXk6
-IG5vbmU7Cn0KCi50aXRsZS1iYXIgI21pZ3JhdGUtdW5pdC1zdGF0dXMtaWNvbiB7CiAgdmVydGljYWwt
-YWxpZ246IHRleHQtYm90dG9tOwp9CgouY29udGVudCB7CiAgZm9udC1mYW1pbHk6ICJSb2JvdG8gTW9u
-byIsbW9ub3NwYWNlOwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB3aGl0ZS1zcGFjZTogcHJlOwp9Cgou
-Y29kZSB7CiAgcGFkZGluZzogMC41ZW07CiAgcG9zaXRpb246IGFic29sdXRlOwogIGxlZnQ6IDA7CiAg
-dG9wOiAwOwogIG1hcmdpbi1sZWZ0OiA1NnB4Owp9CgouY29kZSAud2VsY29tZSB7CiAgZm9udC1mYW1p
-bHk6ICJHb29nbGUgU2FucyIsIlJvYm90byIsc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDE4cHg7CiAg
-bWFyZ2luLXJpZ2h0OiA2MnB4OwogIGNvbG9yOiAjNzc3Owp9CgouY29kZSAubmF2LWxpbmsgewogIGNv
-bG9yOiAjMTZhZGNhOwogIHRleHQtZGVjb3JhdGlvbi1saW5lOiBub25lOwp9CgouY29kZSAubmF2LWxp
-bms6dmlzaXRlZCB7CiAgY29sb3I6ICMxMzliYjU7IC8qICMxNmFkY2EgZGFya2VuZWQgMTAlICovCiAg
-dGV4dC1kZWNvcmF0aW9uLWxpbmU6IG5vbmU7Cn0KCi5jb2RlIC5uYXYtbGluazpob3ZlciB7CiAgdGV4
-dC1kZWNvcmF0aW9uLWxpbmU6IHVuZGVybGluZTsKICBmb250LXdlaWdodDogNjAwOwp9CgoucmVnaW9u
-cyB7CiAgcGFkZGluZzogMC41ZW07CiAgcG9zaXRpb246IGFic29sdXRlOwogIGxlZnQ6IDA7CiAgdG9w
-OiAwOwp9CgoucmVnaW9ucyB0YWJsZSB7CiAgYm9yZGVyLXNwYWNpbmc6IDA7CiAgZm9udC1zaXplOiBp
-bmhlcml0Owp9CgoucmVnaW9ucyB0ZCB7CiAgYm9yZGVyOiBub25lOwogIC8qIFRoZSBjb250ZW50IG9m
-IHRoZSByZWdpb25zIGlzIG5vdCB2aXNpYmxlOyB0aGUgdXNlciBpbnN0ZWFkIHdpbGwgc2VlIHRoZQog
-ICAqIGhpZ2hsaWdodGVkIGNvcHkgb2YgdGhlIGNvbnRlbnQuICovCiAgY29sb3I6IHJnYmEoMjU1LCAy
-NTUsIDI1NSwgMCk7CiAgcGFkZGluZzogMDsKICB3aGl0ZS1zcGFjZTogcHJlOwp9CgoucmVnaW9ucyB0
-ZDplbXB0eTphZnRlciB7CiAgY29udGVudDogIlwwMGEwIjsKfQoKLnJlZ2lvbnMgdHIuaGlnaGxpZ2h0
-IHRkOmxhc3QtY2hpbGQgewogIGJhY2tncm91bmQtY29sb3I6ICM0NDQ0NDQ7CiAgY29sb3I6IHdoaXRl
-Owp9CgoucmVnaW9ucyB0ZC5saW5lLW5vIHsKICBib3JkZXItcmlnaHQ6IHNvbGlkICMxMjIwMmYgMnB4
-OwogIGNvbG9yOiAjOTk5OTk5OwogIHBhZGRpbmctcmlnaHQ6IDRweDsKICB0ZXh0LWFsaWduOiByaWdo
-dDsKICB2aXNpYmlsaXR5OiB2aXNpYmxlOwogIHdpZHRoOiA1MHB4OwogIGRpc3BsYXk6IGlubGluZS1i
-bG9jazsKfQoKLnJlZ2lvbnMgdHIuaGlnaGxpZ2h0IHRkLmxpbmUtbm8gewogIGJvcmRlci1yaWdodDog
-c29saWQgI2NjYyAycHg7Cn0KCi5yZWdpb24gewogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBwb3Np
-dGlvbjogcmVsYXRpdmU7CiAgdmlzaWJpbGl0eTogdmlzaWJsZTsKICB6LWluZGV4OiAyMDA7Cn0KCi5y
-ZWdpb24uYWRkZWQtcmVnaW9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTc4YWZkOwogIGNvbG9yOiAj
-ZmZmOwp9CgoucmVnaW9uLnJlbW92ZWQtcmVnaW9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjRkE1NTdk
-OyAvKiAkZGFyay1waW5rICovCiAgY29sb3I6ICNmZmY7Cn0KCi5yZWdpb24uaW5mb3JtYXRpdmUtcmVn
-aW9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjYzOTUyOwogIGNvbG9yOiAjZmZmOwogIGRpc3BsYXk6
-IGlubGluZS1ibG9jazsKICBoZWlnaHQ6IDE1cHg7CiAgcG9zaXRpb246IHJlbGF0aXZlOwp9CgoudGFy
-Z2V0IHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDQ0OwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB2aXNp
-YmlsaXR5OiB2aXNpYmxlOwogIGZvbnQtd2VpZ2h0OiA2MDA7Cn0KCi5pbmZvLXBhbmVsIHsKICBmbGV4
-OiAxIDIwMHB4OwogIG1hcmdpbjogMDsKICBoZWlnaHQ6IDEwMCU7CiAgZGlzcGxheTogZmxleDsKICBm
-bGV4LWRpcmVjdGlvbjogY29sdW1uOwp9CgouaW5mby1wYW5lbCAuZWRpdC1wYW5lbCB7CiAgYmFja2dy
-b3VuZC1jb2xvcjogIzEyMjAyZjsKICBvdmVyZmxvdzogYXV0bzsKfQoKLmluZm8tcGFuZWwgLnBhbmVs
-LWNvbnRlbnQgewogIHBhZGRpbmc6IDdweDsKfQoKLmluZm8tcGFuZWwgLnBhbmVsLWNvbnRlbnQ+IDpm
-aXJzdC1jaGlsZCB7CiAgbWFyZ2luLXRvcDogMDsKfQoKLmluZm8tcGFuZWwgLm5vd3JhcCB7CiAgd2hp
-dGUtc3BhY2U6IG5vd3JhcDsKfQoKLmluZm8tcGFuZWwgdWwsCi5pbmZvLXBhbmVsIG9sIHsKICBwYWRk
-aW5nLWxlZnQ6IDIwcHg7Cn0KCi5pbmZvLXBhbmVsIGxpIHsKICBtYXJnaW46IDAgMCA1cHggMDsKfQoK
-LmluZm8tcGFuZWwgYSB7CiAgY29sb3I6ICMxMzliYjU7Cn0KCi5pbmZvLXBhbmVsIGE6aG92ZXIgewog
-IGNvbG9yOiAjMWVjN2U3OyAvKiAjMTM5YmI1IGxpZ2h0ZW5lZCAyMCUgKi8KfQoKLmluZm8tcGFuZWwg
-LmVkaXQtbGlzdCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzEyMjAyZjsKICBvdmVyZmxvdzogYXV0bzsK
-fQoKLmVkaXQtcGFuZWwgewogIG1hcmdpbi10b3A6IDZweDsKICBmbGV4OiAxIDEwMHB4Owp9CgouZWRp
-dC1saXN0IHsKICBmbGV4OiAyIDEwMHB4Owp9CgouZWRpdC1saXN0IC5lZGl0IHsKICBtYXJnaW46IDNw
-eCAwOwp9CgouZWRpdC1saXN0IC5lZGl0LWxpbmsgewogIGN1cnNvcjogcG9pbnRlcjsKfQoKLnBvcHVw
-LXBhbmUgewogIGRpc3BsYXk6IG5vbmU7CiAgcG9zaXRpb246IGZpeGVkOwogIHRvcDogMTUwcHg7CiAg
-bGVmdDogMTUwcHg7CiAgcmlnaHQ6IDE1MHB4OwogIGJvdHRvbTogMTUwcHg7CiAgYm9yZGVyOiAxcHgg
-c29saWQgYmxhY2s7CiAgYm9yZGVyLXRvcDogMnB4IHNvbGlkIGJsYWNrOwogIGJvcmRlci1yYWRpdXM6
-IDdweDsKICBib3gtc2hhZG93OiAwcHggMHB4IDIwcHggMnB4ICNiNGJmY2IyMjsKICB6LWluZGV4OiA0
-MDA7CiAgYmFja2dyb3VuZDogIzJiMzAzNjsKICBwYWRkaW5nOiAyMHB4Owp9CgoucG9wdXAtcGFuZSAu
-Y2xvc2UgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICByaWdodDogMTBweDsKICB0b3A6IDEwcHg7CiAg
-Y3Vyc29yOiBwb2ludGVyOwogIHRleHQtc2hhZG93OiAxcHggMXB4IDJweCAjODg4OwogIGJveC1zaGFk
-b3c6IDFweCAxcHggMnB4ICMxMTE7Cn0KCi5wb3B1cC1wYW5lIGgyIHsKICBwYWRkaW5nOiAyMXB4Owog
-IGhlaWdodDogMTAlOwogIG1hcmdpbjogMHB4OwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7Cn0KCi5w
-b3B1cC1wYW5lIHAgewogIGhlaWdodDogMTAlOwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7CiAgcGFk
-ZGluZzogMHB4IDIwcHg7Cn0KCi5wb3B1cC1wYW5lIHByZSB7CiAgYmFja2dyb3VuZDogIzEyMjAyZjsK
-ICBwYWRkaW5nOiAyMHB4OwogIGJvdHRvbTogMHB4OwogIG92ZXJmbG93OiBhdXRvIHNjcm9sbDsKICBo
-ZWlnaHQ6IDY1JTsKICBtYXJnaW46IDBweDsKICBib3gtc2l6aW5nOiBib3JkZXItYm94Owp9CgoucG9w
-dXAtcGFuZSAuYnV0dG9uLmJvdHRvbSB7CiAgbWFyZ2luOiAyMHB4IDBweDsKICBkaXNwbGF5OiBibG9j
-azsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCi5yZXJ1bm5pbmctcGFuZSB7CiAgZGlzcGxheTogbm9u
-ZTsKfQoKYm9keS5yZXJ1bm5pbmcgLnJlcnVubmluZy1wYW5lIHsKICBkaXNwbGF5OiBibG9jazsKICBw
-b3NpdGlvbjogZml4ZWQ7CiAgdG9wOiAwcHg7CiAgYm90dG9tOiAwcHg7CiAgbGVmdDogMHB4OwogIHJp
-Z2h0OiAwcHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMEFBOyAvKiB0cmFuc2x1Y2VudCBibGFj
-ayAqLwogIHotaW5kZXg6IDQwMDsKfQoKLnJlcnVubmluZy1wYW5lIGgxIHsKICBwb3NpdGlvbjogYWJz
-b2x1dGU7CiAgdG9wOiA1MCU7CiAgbGVmdDogNTAlOwogIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUs
-IC01MCUpOwp9CgouZWRpdC1wYW5lbCAudHlwZS1kZXNjcmlwdGlvbiB7CiAgLyogRnJvbSBEYXJ0UGFk
-ICRkYXJrLW9yYW5nZSAqLwogIGNvbG9yOiAjZmY5MTZlOwogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7
-Cn0KCnVsLnRyYWNlIHsKICBmb250LXNpemU6IDEzcHg7CiAgbGlzdC1zdHlsZS10eXBlOiBub25lOwog
-IHBhZGRpbmctbGVmdDogMHB4Owp9Cgp1bC50cmFjZSBsaSB7CiAgY29sb3I6IHdoaXRlOwp9Cgp1bC50
-cmFjZSBsaSAuZnVuY3Rpb24gewogIC8qIGZyb20gLmhsanMtdmFyaWFibGUgKi8KICBjb2xvcjogIzE2
-YWRjYTsKICBmb250LWZhbWlseTogbW9ub3NwYWNlOwogIGZvbnQtd2VpZ2h0OiA2MDA7Cn0KCnVsLnRy
-YWNlIGxpIHAuZHJhd2VyIHsKICBtYXJnaW46IDNweCAwcHg7CiAgcGFkZGluZzogMHB4IDBweCAwcHgg
-MTRweDsKfQoKdWwudHJhY2UgbGkgcC5kcmF3ZXIgYnV0dG9uIHsKICBtYXJnaW4tcmlnaHQ6IDNweDsK
-fQoKLmVsZXZhdGlvbi16NCB7CiAgYm94LXNoYWRvdzogMHB4IDJweCA0cHggLTFweCByZ2JhKDAsIDAs
-IDAsIDAuMiksCiAgICAgIDBweCA0cHggNXB4IDBweCByZ2JhKDAsIDAsIDAsIDAuMTQpLAogICAgICAw
-cHggMXB4IDEwcHggMHB4IHJnYmEoMCwgMCwgMCwgLjEyKTsKfQoKYSB7CiAgY29sb3I6ICNjY2M7CiAg
-ZmlsbDogI2NjYzsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7Cn0KCmE6aG92ZXIgewogIGNvbG9yOiAj
-ZGJkYmRiOyAvKiAjY2NjIGxpZ2h0ZW50ZWQgMzAlKi8KICBmaWxsOiAjZmZmOwp9CgouYWRkLWhpbnQt
-bGluayB7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIG1hcmdpbjogM3B4Owp9CgouYWRkLWhpbnQt
-bGluazpob3ZlciB7CiAgY29sb3I6ICNmZmY7Cn0KCmhlYWRlciBidXR0b24gewogIHRleHQtdHJhbnNm
-b3JtOiB1cHBlcmNhc2U7Cn0KCmhlYWRlciBhIHsKICBtYXJnaW46IDA7Cn0KCi8qIENhcmVmdWwgaGVy
-ZS4gYGEuYnV0dG9uYCBpcyByZXBldGl0aXZlIGJ1dCByZXF1aXJlZCB0byBnZXQgY29ycmVjdAogKiBz
-cGVjaWZpY2l0eSAqLwpidXR0b24sIC5idXR0b24sIGEuYnV0dG9uIHsKICBiYWNrZ3JvdW5kLWNvbG9y
-OiByZ2JhKDIyLCAxMzgsIDI1MywgMC4xNSk7CiAgYm9yZGVyOiBub25lOwogIGJvcmRlci1yYWRpdXM6
-IDNweDsKICBwYWRkaW5nOiAzcHggMTBweDsKICBmb250LXdlaWdodDogNTAwOwogIGZvbnQtZm9udDog
-Um9ib3RvLCBzYW5zLXNlcmlmOwogIGNvbG9yOiAjZmZmOwp9CgpidXR0b246aG92ZXIsIC5idXR0b246
-aG92ZXIgewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjIsIDEzOCwgMjUzLCAwLjI5KTsKICBjdXJz
-b3I6IHBvaW50ZXI7Cn0KCmJ1dHRvbltkaXNhYmxlZF0gewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEo
-MjU1LDI1NSwyNTUsLjEyKTsKICBjb2xvcjogcmdiYSgyNTUsMjU1LDI1NSwuMzcpOwogIGN1cnNvcjog
-bm90LWFsbG93ZWQ7Cn0KCi8qIENoYW5nZSBlZGl0IHBhbmVsIGJ1dHRvbiBjb2xvcnMgKi8KLmVkaXQt
-cGFuZWwgLmJ1dHRvbiwgLmVkaXQtcGFuZWwgYnV0dG9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2Jh
-KDYzLCAxMDQsIDE0OCwgMC42KTsKICBjb2xvcjogd2hpdGU7Cn0KLmVkaXQtcGFuZWwgLmJ1dHRvbjpo
-b3ZlciwgLmVkaXQtcGFuZWwgYnV0dG9uOmhvdmVyIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDEw
-MSwgMTUzLCAyMDgsIDAuNik7CiAgY29sb3I6IHdoaXRlOwp9CgovKgogKiBBZGp1c3RtZW50cyB0byBh
-bGlnbiBtYXRlcmlhbCBpY29ucyBpbiB0aGUgdG9vbGJhciBidXR0b25zLgoqLwouYWN0aW9uLWJ1dHRv
-biA+IHNwYW4gewogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB0b3A6IC0zcHg7Cn0KCi5hY3Rpb24tYnV0
-dG9uIC5tYXRlcmlhbC1pY29ucyB7CiAgdG9wOiA0cHg7Cn0KCi8qIERvbid0IHNoaWZ0IHRoZSBpY29u
-IHdoZW4gaXQncyBhIGRpcmVjdCBjaGlsZCBvZiB0aGUgYnV0dG9uICovCi5hY3Rpb24tYnV0dG9uID4g
-Lm1hdGVyaWFsLWljb25zIHsKICB0b3A6IDFweDsKfQoKLyogU2hpZnQgdGhlIHRleHQgdG8gY2VudGVy
-IHdpdGggdGhlIGljb24uICovCi5hY3Rpb24tYnV0dG9uID4gc3Bhbi5sYWJlbCB7CiAgcG9zaXRpb246
-cmVsYXRpdmU7CiAgdG9wOiAtNHB4Owp9CgouYWN0aW9uLWJ1dHRvbiAubWF0ZXJpYWwtaWNvbnMgewog
-IGZvbnQtc2l6ZTogMjBweDsKICBwb3NpdGlvbjogcmVsYXRpdmU7Cn0KCi5wbGFjZWhvbGRlciB7CiAg
-Y29sb3I6ICM3Nzc7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIG1hcmdpbi10b3A6IDNlbSAhaW1wb3J0
-YW50Owp9CgovKioKICogSExKUyBPdmVycmlkZXMKICovCi5obGpzIHsKICBiYWNrZ3JvdW5kLWNvbG9y
-OiAjMTIyMDJmOyAvKiAkZGFyay1jb2RlLWJhY2tncm91bmQtY29sb3IgKi8KICBjb2xvcjogI2MwYzJj
-NTsgLyogJGRhcmstZWRpdG9yLXRleHQgKi8KICBkaXNwbGF5OiBibG9jazsKICBvdmVyZmxvdy14OiBh
-dXRvOwogIHBhZGRpbmc6IDAuNWVtOwogIC8qKgogICAqIFRoaXMgYWxsb3dzIHRoZSBwZXItbGluZSBo
-aWdobGlnaHRzIHRvIHNob3cuCiAgICovCiAgYmFja2dyb3VuZDogbm9uZTsKfQoKLmhsanMta2V5d29y
-ZCwKLmhsanMtc2VsZWN0b3ItdGFnLAouaGxqcy1kZWxldGlvbiB7CiAgY29sb3I6ICM1MWM2ODY7IC8q
-IGNtLWtleXdvcmQgKi8KfQoKLmhsanMtbnVtYmVyIHsKICBjb2xvcjogIzYyNzk3ODsgLyogY20tbnVt
-YmVyICovCn0KCi5obGpzLWNvbW1lbnQgewogIGNvbG9yOiAjOTE5OGI0OyAvKiBjbS1jb21tZW50ICov
-Cn0KCi5obGpzLWxpdGVyYWwgewogIGNvbG9yOiAjZWU4NjY2OyAvKiBjbS1hdG9tICovCn0KCi5obGpz
-LXN0cmluZyB7CiAgY29sb3I6ICNlNTUwNzQ7IC8qIGNtLXN0cmluZyAqLwp9CgouaGxqcy12YXJpYWJs
-ZSB7CiAgY29sb3I6ICMxNmFkY2E7IC8qIGNtLXZhcmlhYmxlICovCn0KCi5obGpzLWxpbmsgewogIGNv
-bG9yOiAjZTU1MDc0OyAvKiBjbS1zdHJpbmcgKi8KfQouaGxqcy1zZWN0aW9uLAouaGxqcy10eXBlLAou
-aGxqcy1idWlsdF9pbiwKLmhsanMtdGl0bGUgewogIGNvbG9yOiAjZWU4NjY2OyAvKiBjbS12YXJpYWJs
-ZS0yICovCn0KCi5obGpzLWFkZGl0aW9uIHsKICBjb2xvcjogIzI2Mzk1MjsgLyogJGRhcmstc2VsZWN0
-aW9uLWNvbG9yICovCn0KCi5obGpzLW1ldGEgewogIGNvbG9yOiAjNjI3OTc4Owp9Cg==
+OyAvKiAkbGlnaHQtZ3JlZW4gKi8KfQoKLnN0YXR1cy1pY29uLmRpc2FibGVkIHsKICBjdXJzb3I6IG5v
+dC1hbGxvd2VkOwp9Cgouc3RhdHVzLWljb24ub3B0ZWQtb3V0IHsKICBjb2xvcjogIzY3Njc2NzsgLyog
+JHNlY29uZGFyeS1jb2xvciAqLwp9Cgouc3RhdHVzLWljb24ub3B0ZWQtb3V0OmhvdmVyIHsKICBjb2xv
+cjogI2ZmZmZmZjsKfQoKLnN0YXR1cy1pY29uLm1pZ3JhdGluZyB7CiAgY29sb3I6ICM1MWM2ODY7IC8q
+ICRkYXJrLWdyZWVuICovCn0KCi5zdGF0dXMtaWNvbi5taWdyYXRpbmc6aG92ZXIgewogIGNvbG9yOiAj
+ZmZmZmZmOwp9CgoubmF2LWlubmVyIHVsIHsKICBwYWRkaW5nLWxlZnQ6IDEycHg7CiAgbWFyZ2luOiAw
+Owp9CgoubmF2LWlubmVyIGxpIHsKICBsaXN0LXN0eWxlLXR5cGU6IG5vbmU7CiAgd2hpdGUtc3BhY2U6
+IG5vd3JhcDsKfQoKLm5hdi1pbm5lciBsaTpub3QoLmRpcikgewogIG1hcmdpbi1sZWZ0OiAyMHB4Owog
+IG1hcmdpbi1ib3R0b206IDNweDsKfQoKLm5hdi1pbm5lciBsaS5kaXIgLmFycm93IHsKICBjdXJzb3I6
+IHBvaW50ZXI7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIGZvbnQtc2l6ZTogMTBweDsKICBtYXJn
+aW4tcmlnaHQ6IDRweDsKICB0cmFuc2l0aW9uOiB0cmFuc2Zvcm0gMC41cyBlYXNlLW91dDsKfQoKLm5h
+di1pbm5lciBsaS5kaXIgLmFycm93LmNvbGxhcHNlZCB7CiAgdHJhbnNmb3JtOiByb3RhdGUoLTkwZGVn
+KTsKfQoKLm5hdi1pbm5lciB1bCB7CiAgLyogYSBtYXgtaGVpZ2h0IGlzIGFkZGVkIHRvIGVhY2ggZWxl
+bWVudCBhdCBydW50aW1lLiAqLwogIHRyYW5zaXRpb246IG1heC1oZWlnaHQgMC41cyBlYXNlLW91dDsK
+fQoKLm5hdi1pbm5lciB1bC5jb2xsYXBzZWQgewogIG1heC1oZWlnaHQ6IDAgIWltcG9ydGFudDsKICBv
+dmVyZmxvdzogaGlkZGVuOwp9CgoubmF2LWlubmVyIC5zZWxlY3RlZC1maWxlIHsKICBjb2xvcjogd2hp
+dGU7CiAgY3Vyc29yOiBpbmhlcml0OwogIGZvbnQtd2VpZ2h0OiA2MDA7CiAgdGV4dC1kZWNvcmF0aW9u
+OiBub25lOwp9CgouZWRpdC1jb3VudCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzY3Njc2NzsKICBib3Jk
+ZXItcmFkaXVzOiAxMHB4OwogIGNvbG9yOiAjZmZmOwogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBm
+b250LXNpemU6IDExcHg7CiAgZm9udC13ZWlnaHQ6IDYwMDsKICBtYXJnaW4tbGVmdDogNXB4OwogIG1p
+bi13aWR0aDogMjVweDsKICBwYWRkaW5nOiA0cHggMCAycHggMDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7
+CiAgbGluZS1oZWlnaHQ6IDFlbTsKfQoKLmZpbGUgewogIGRpc3BsYXk6IGZsZXg7CiAgZmxleC1kaXJl
+Y3Rpb246IGNvbHVtbjsKICBmbGV4OiA0IDMwMHB4OwogIGZvbnQtZmFtaWx5OiAiR29vZ2xlIFNhbnMi
+LCJSb2JvdG8iLHNhbnMtc2VyaWY7CiAgYmFja2dyb3VuZDogIzEyMjAyZjsKICBtYXJnaW46IDAgNnB4
+Owp9CgoudGl0bGUtYmFyIGgzIHsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgZm9udC13ZWlnaHQ6
+IDQwMDsKICAvKiBUaGlzIGFsaWducyB0aGUgdGl0bGUgdGV4dCB3aXRoIHRoZSBjb250ZW50IHRleHQs
+IGFjY291bnRpbmcgZm9yIHRoZSB3aWR0aAogICAqIG9mIHRoZSBsaW5lIG51bWJlcnMuCiAgICovCiAg
+bWFyZ2luOiAwLjVlbSAyNHB4IDAuNWVtIDYzcHg7Cn0KCi50aXRsZS1iYXIgI21pZ3JhdGUtdW5pdC1z
+dGF0dXMtaWNvbi1sYWJlbCB7CiAgZGlzcGxheTogbm9uZTsKICB1c2VyLXNlbGVjdDogbm9uZTsKfQoK
+LnRpdGxlLWJhciAjbWlncmF0ZS11bml0LXN0YXR1cy1pY29uLWxhYmVsLnZpc2libGUgewogIGRpc3Bs
+YXk6IGlubGluZTsKfQoKLnRpdGxlLWJhciAjbWlncmF0ZS11bml0LXN0YXR1cy1pY29uIHsKICB2ZXJ0
+aWNhbC1hbGlnbjogdGV4dC1ib3R0b207Cn0KCi5jb250ZW50IHsKICBmbGV4LWdyb3c6IDE7CiAgZm9u
+dC1mYW1pbHk6ICJSb2JvdG8gTW9ubyIsbW9ub3NwYWNlOwogIG92ZXJmbG93OiBzY3JvbGw7CiAgcG9z
+aXRpb246IHJlbGF0aXZlOwogIHdoaXRlLXNwYWNlOiBwcmU7Cn0KCi5jb2RlIHsKICBwYWRkaW5nOiAw
+LjVlbTsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgbGVmdDogMDsKICB0b3A6IDA7CiAgbWFyZ2luLWxl
+ZnQ6IDU2cHg7Cn0KCi5jb2RlIC53ZWxjb21lIHsKICBmb250LWZhbWlseTogIkdvb2dsZSBTYW5zIiwi
+Um9ib3RvIixzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tcmlnaHQ6IDYycHg7
+CiAgY29sb3I6ICM3Nzc7Cn0KCi5jb2RlIC5uYXYtbGluayB7CiAgY29sb3I6ICMxNmFkY2E7CiAgdGV4
+dC1kZWNvcmF0aW9uLWxpbmU6IG5vbmU7Cn0KCi5jb2RlIC5uYXYtbGluazp2aXNpdGVkIHsKICBjb2xv
+cjogIzEzOWJiNTsgLyogIzE2YWRjYSBkYXJrZW5lZCAxMCUgKi8KICB0ZXh0LWRlY29yYXRpb24tbGlu
+ZTogbm9uZTsKfQoKLmNvZGUgLm5hdi1saW5rOmhvdmVyIHsKICB0ZXh0LWRlY29yYXRpb24tbGluZTog
+dW5kZXJsaW5lOwogIGZvbnQtd2VpZ2h0OiA2MDA7Cn0KCi5yZWdpb25zIHsKICBwYWRkaW5nOiAwLjVl
+bTsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgbGVmdDogMDsKICB0b3A6IDA7Cn0KCi5yZWdpb25zIHRh
+YmxlIHsKICBib3JkZXItc3BhY2luZzogMDsKICBmb250LXNpemU6IGluaGVyaXQ7Cn0KCi5yZWdpb25z
+IHRkIHsKICBib3JkZXI6IG5vbmU7CiAgLyogVGhlIGNvbnRlbnQgb2YgdGhlIHJlZ2lvbnMgaXMgbm90
+IHZpc2libGU7IHRoZSB1c2VyIGluc3RlYWQgd2lsbCBzZWUgdGhlCiAgICogaGlnaGxpZ2h0ZWQgY29w
+eSBvZiB0aGUgY29udGVudC4gKi8KICBjb2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwKTsKICBwYWRk
+aW5nOiAwOwogIHdoaXRlLXNwYWNlOiBwcmU7Cn0KCi5yZWdpb25zIHRkOmVtcHR5OmFmdGVyIHsKICBj
+b250ZW50OiAiXDAwYTAiOwp9CgoucmVnaW9ucyB0ci5oaWdobGlnaHQgdGQ6bGFzdC1jaGlsZCB7CiAg
+YmFja2dyb3VuZC1jb2xvcjogIzQ0NDQ0NDsKICBjb2xvcjogd2hpdGU7Cn0KCi5yZWdpb25zIHRkLmxp
+bmUtbm8gewogIGJvcmRlci1yaWdodDogc29saWQgIzEyMjAyZiAycHg7CiAgY29sb3I6ICM5OTk5OTk7
+CiAgcGFkZGluZy1yaWdodDogNHB4OwogIHRleHQtYWxpZ246IHJpZ2h0OwogIHZpc2liaWxpdHk6IHZp
+c2libGU7CiAgd2lkdGg6IDUwcHg7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwp9CgoucmVnaW9ucyB0
+ci5oaWdobGlnaHQgdGQubGluZS1ubyB7CiAgYm9yZGVyLXJpZ2h0OiBzb2xpZCAjY2NjIDJweDsKfQoK
+LnJlZ2lvbiB7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB2
+aXNpYmlsaXR5OiB2aXNpYmxlOwogIHotaW5kZXg6IDIwMDsKfQoKLnJlZ2lvbi5hZGRlZC1yZWdpb24g
+ewogIGJhY2tncm91bmQtY29sb3I6ICMxNzhhZmQ7CiAgY29sb3I6ICNmZmY7Cn0KCi5yZWdpb24ucmVt
+b3ZlZC1yZWdpb24gewogIGJhY2tncm91bmQtY29sb3I6ICNGQTU1N2Q7IC8qICRkYXJrLXBpbmsgKi8K
+ICBjb2xvcjogI2ZmZjsKfQoKLnJlZ2lvbi5pbmZvcm1hdGl2ZS1yZWdpb24gewogIGJhY2tncm91bmQt
+Y29sb3I6ICMyNjM5NTI7CiAgY29sb3I6ICNmZmY7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIGhl
+aWdodDogMTRweDsKICBwb3NpdGlvbjogcmVsYXRpdmU7Cn0KCi50YXJnZXQgewogIGJhY2tncm91bmQt
+Y29sb3I6ICM0NDQ7CiAgcG9zaXRpb246IHJlbGF0aXZlOwogIHZpc2liaWxpdHk6IHZpc2libGU7CiAg
+Zm9udC13ZWlnaHQ6IDYwMDsKfQoKLmluZm8tcGFuZWwgewogIGZsZXg6IDEgMjAwcHg7CiAgbWFyZ2lu
+OiAwOwogIGhlaWdodDogMTAwJTsKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1
+bW47Cn0KCi5pbmZvLXBhbmVsIC5lZGl0LXBhbmVsIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTIyMDJm
+OwogIG92ZXJmbG93OiBhdXRvOwp9CgouaW5mby1wYW5lbCAucGFuZWwtY29udGVudCB7CiAgcGFkZGlu
+ZzogN3B4Owp9CgouaW5mby1wYW5lbCAucGFuZWwtY29udGVudD4gOmZpcnN0LWNoaWxkIHsKICBtYXJn
+aW4tdG9wOiAwOwp9CgouaW5mby1wYW5lbCAubm93cmFwIHsKICB3aGl0ZS1zcGFjZTogbm93cmFwOwp9
+CgouaW5mby1wYW5lbCB1bCwKLmluZm8tcGFuZWwgb2wgewogIHBhZGRpbmctbGVmdDogMjBweDsKfQoK
+LmluZm8tcGFuZWwgbGkgewogIG1hcmdpbjogMCAwIDVweCAwOwp9CgouaW5mby1wYW5lbCBhIHsKICBj
+b2xvcjogIzEzOWJiNTsKfQoKLmluZm8tcGFuZWwgYTpob3ZlciB7CiAgY29sb3I6ICMxZWM3ZTc7IC8q
+ICMxMzliYjUgbGlnaHRlbmVkIDIwJSAqLwp9CgouaW5mby1wYW5lbCAuZWRpdC1saXN0IHsKICBiYWNr
+Z3JvdW5kLWNvbG9yOiAjMTIyMDJmOwogIG92ZXJmbG93OiBhdXRvOwp9CgouZWRpdC1wYW5lbCB7CiAg
+bWFyZ2luLXRvcDogNnB4OwogIGZsZXg6IDEgMTAwcHg7Cn0KCi5lZGl0LWxpc3QgewogIGZsZXg6IDIg
+MTAwcHg7Cn0KCi5lZGl0LWxpc3QgLmVkaXQgewogIG1hcmdpbjogM3B4IDA7Cn0KCi5lZGl0LWxpc3Qg
+LmVkaXQtbGluayB7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgoucG9wdXAtcGFuZSB7CiAgZGlzcGxheTog
+bm9uZTsKICBwb3NpdGlvbjogZml4ZWQ7CiAgdG9wOiAxNTBweDsKICBsZWZ0OiAxNTBweDsKICByaWdo
+dDogMTUwcHg7CiAgYm90dG9tOiAxNTBweDsKICBib3JkZXI6IDFweCBzb2xpZCBibGFjazsKICBib3Jk
+ZXItdG9wOiAycHggc29saWQgYmxhY2s7CiAgYm9yZGVyLXJhZGl1czogN3B4OwogIGJveC1zaGFkb3c6
+IDBweCAwcHggMjBweCAycHggI2I0YmZjYjIyOwogIHotaW5kZXg6IDQwMDsKICBiYWNrZ3JvdW5kOiAj
+MmIzMDM2OwogIHBhZGRpbmc6IDIwcHg7Cn0KCi5wb3B1cC1wYW5lIC5jbG9zZSB7CiAgcG9zaXRpb246
+IGFic29sdXRlOwogIHJpZ2h0OiAxMHB4OwogIHRvcDogMTBweDsKICBjdXJzb3I6IHBvaW50ZXI7CiAg
+dGV4dC1zaGFkb3c6IDFweCAxcHggMnB4ICM4ODg7CiAgYm94LXNoYWRvdzogMXB4IDFweCAycHggIzEx
+MTsKfQoKLnBvcHVwLXBhbmUgaDIgewogIHBhZGRpbmc6IDIxcHg7CiAgaGVpZ2h0OiAxMCU7CiAgbWFy
+Z2luOiAwcHg7CiAgYm94LXNpemluZzogYm9yZGVyLWJveDsKfQoKLnBvcHVwLXBhbmUgcCB7CiAgaGVp
+Z2h0OiAxMCU7CiAgYm94LXNpemluZzogYm9yZGVyLWJveDsKICBwYWRkaW5nOiAwcHggMjBweDsKfQoK
+LnBvcHVwLXBhbmUgcHJlIHsKICBiYWNrZ3JvdW5kOiAjMTIyMDJmOwogIHBhZGRpbmc6IDIwcHg7CiAg
+Ym90dG9tOiAwcHg7CiAgb3ZlcmZsb3c6IGF1dG8gc2Nyb2xsOwogIGhlaWdodDogNjUlOwogIG1hcmdp
+bjogMHB4OwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7Cn0KCi5wb3B1cC1wYW5lIC5idXR0b24uYm90
+dG9tIHsKICBtYXJnaW46IDIwcHggMHB4OwogIGRpc3BsYXk6IGJsb2NrOwogIHRleHQtYWxpZ246IGNl
+bnRlcjsKfQoKLnJlcnVubmluZy1wYW5lIHsKICBkaXNwbGF5OiBub25lOwp9Cgpib2R5LnJlcnVubmlu
+ZyAucmVydW5uaW5nLXBhbmUgewogIGRpc3BsYXk6IGJsb2NrOwogIHBvc2l0aW9uOiBmaXhlZDsKICB0
+b3A6IDBweDsKICBib3R0b206IDBweDsKICBsZWZ0OiAwcHg7CiAgcmlnaHQ6IDBweDsKICBiYWNrZ3Jv
+dW5kLWNvbG9yOiAjMDAwMDAwQUE7IC8qIHRyYW5zbHVjZW50IGJsYWNrICovCiAgei1pbmRleDogNDAw
+Owp9CgoucmVydW5uaW5nLXBhbmUgaDEgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICB0b3A6IDUwJTsK
+ICBsZWZ0OiA1MCU7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7Cn0KCi5lZGl0LXBh
+bmVsIC50eXBlLWRlc2NyaXB0aW9uIHsKICAvKiBGcm9tIERhcnRQYWQgJGRhcmstb3JhbmdlICovCiAg
+Y29sb3I6ICNmZjkxNmU7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKfQoKdWwudHJhY2UgewogIGZv
+bnQtc2l6ZTogMTNweDsKICBsaXN0LXN0eWxlLXR5cGU6IG5vbmU7CiAgcGFkZGluZy1sZWZ0OiAwcHg7
+Cn0KCnVsLnRyYWNlIGxpIHsKICBjb2xvcjogd2hpdGU7Cn0KCnVsLnRyYWNlIGxpIC5mdW5jdGlvbiB7
+CiAgLyogZnJvbSAuaGxqcy12YXJpYWJsZSAqLwogIGNvbG9yOiAjMTZhZGNhOwogIGZvbnQtZmFtaWx5
+OiBtb25vc3BhY2U7CiAgZm9udC13ZWlnaHQ6IDYwMDsKfQoKdWwudHJhY2UgbGkgcC5kcmF3ZXIgewog
+IG1hcmdpbjogM3B4IDBweDsKICBwYWRkaW5nOiAwcHggMHB4IDBweCAxNHB4Owp9Cgp1bC50cmFjZSBs
+aSBwLmRyYXdlciBidXR0b24gewogIG1hcmdpbi1yaWdodDogM3B4Owp9CgouZWxldmF0aW9uLXo0IHsK
+ICBib3gtc2hhZG93OiAwcHggMnB4IDRweCAtMXB4IHJnYmEoMCwgMCwgMCwgMC4yKSwKICAgICAgMHB4
+IDRweCA1cHggMHB4IHJnYmEoMCwgMCwgMCwgMC4xNCksCiAgICAgIDBweCAxcHggMTBweCAwcHggcmdi
+YSgwLCAwLCAwLCAuMTIpOwp9CgphIHsKICBjb2xvcjogI2NjYzsKICBmaWxsOiAjY2NjOwogIHRleHQt
+ZGVjb3JhdGlvbjogbm9uZTsKfQoKYTpob3ZlciB7CiAgY29sb3I6ICNkYmRiZGI7IC8qICNjY2MgbGln
+aHRlbnRlZCAzMCUqLwogIGZpbGw6ICNmZmY7Cn0KCi5hZGQtaGludC1saW5rIHsKICBkaXNwbGF5OiBp
+bmxpbmUtYmxvY2s7CiAgbWFyZ2luOiAzcHg7Cn0KCi5hZGQtaGludC1saW5rOmhvdmVyIHsKICBjb2xv
+cjogI2ZmZjsKfQoKaGVhZGVyIGJ1dHRvbiB7CiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTsKfQoK
+aGVhZGVyIGEgewogIG1hcmdpbjogMDsKfQoKLyogQ2FyZWZ1bCBoZXJlLiBgYS5idXR0b25gIGlzIHJl
+cGV0aXRpdmUgYnV0IHJlcXVpcmVkIHRvIGdldCBjb3JyZWN0CiAqIHNwZWNpZmljaXR5ICovCmJ1dHRv
+biwgLmJ1dHRvbiwgYS5idXR0b24gewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjIsIDEzOCwgMjUz
+LCAwLjE1KTsKICBib3JkZXI6IG5vbmU7CiAgYm9yZGVyLXJhZGl1czogM3B4OwogIHBhZGRpbmc6IDNw
+eCAxMHB4OwogIGZvbnQtd2VpZ2h0OiA1MDA7CiAgZm9udC1mb250OiBSb2JvdG8sIHNhbnMtc2VyaWY7
+CiAgY29sb3I6ICNmZmY7Cn0KCmJ1dHRvbjpob3ZlciwgLmJ1dHRvbjpob3ZlciB7CiAgYmFja2dyb3Vu
+ZC1jb2xvcjogcmdiYSgyMiwgMTM4LCAyNTMsIDAuMjkpOwogIGN1cnNvcjogcG9pbnRlcjsKfQoKYnV0
+dG9uW2Rpc2FibGVkXSB7CiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNTUsMjU1LDI1NSwuMTIpOwog
+IGNvbG9yOiByZ2JhKDI1NSwyNTUsMjU1LC4zNyk7CiAgY3Vyc29yOiBub3QtYWxsb3dlZDsKfQoKLyog
+Q2hhbmdlIGVkaXQgcGFuZWwgYnV0dG9uIGNvbG9ycyAqLwouZWRpdC1wYW5lbCAuYnV0dG9uLCAuZWRp
+dC1wYW5lbCBidXR0b24gewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNjMsIDEwNCwgMTQ4LCAwLjYp
+OwogIGNvbG9yOiB3aGl0ZTsKfQouZWRpdC1wYW5lbCAuYnV0dG9uOmhvdmVyLCAuZWRpdC1wYW5lbCBi
+dXR0b246aG92ZXIgewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMTAxLCAxNTMsIDIwOCwgMC42KTsK
+ICBjb2xvcjogd2hpdGU7Cn0KCi8qCiAqIEFkanVzdG1lbnRzIHRvIGFsaWduIG1hdGVyaWFsIGljb25z
+IGluIHRoZSB0b29sYmFyIGJ1dHRvbnMuCiovCi5hY3Rpb24tYnV0dG9uID4gc3BhbiB7CiAgcG9zaXRp
+b246IHJlbGF0aXZlOwogIHRvcDogLTNweDsKfQoKLmFjdGlvbi1idXR0b24gLm1hdGVyaWFsLWljb25z
+IHsKICB0b3A6IDRweDsKfQoKLyogRG9uJ3Qgc2hpZnQgdGhlIGljb24gd2hlbiBpdCdzIGEgZGlyZWN0
+IGNoaWxkIG9mIHRoZSBidXR0b24gKi8KLmFjdGlvbi1idXR0b24gPiAubWF0ZXJpYWwtaWNvbnMgewog
+IHRvcDogMXB4Owp9CgovKiBTaGlmdCB0aGUgdGV4dCB0byBjZW50ZXIgd2l0aCB0aGUgaWNvbi4gKi8K
+LmFjdGlvbi1idXR0b24gPiBzcGFuLmxhYmVsIHsKICBwb3NpdGlvbjpyZWxhdGl2ZTsKICB0b3A6IC00
+cHg7Cn0KCi5hY3Rpb24tYnV0dG9uIC5tYXRlcmlhbC1pY29ucyB7CiAgZm9udC1zaXplOiAyMHB4Owog
+IHBvc2l0aW9uOiByZWxhdGl2ZTsKfQoKLnBsYWNlaG9sZGVyIHsKICBjb2xvcjogIzc3NzsKICB0ZXh0
+LWFsaWduOiBjZW50ZXI7CiAgbWFyZ2luLXRvcDogM2VtICFpbXBvcnRhbnQ7Cn0KCi8qKgogKiBITEpT
+IE92ZXJyaWRlcwogKi8KLmhsanMgewogIGJhY2tncm91bmQtY29sb3I6ICMxMjIwMmY7IC8qICRkYXJr
+LWNvZGUtYmFja2dyb3VuZC1jb2xvciAqLwogIGNvbG9yOiAjYzBjMmM1OyAvKiAkZGFyay1lZGl0b3It
+dGV4dCAqLwogIGRpc3BsYXk6IGJsb2NrOwogIG92ZXJmbG93LXg6IGF1dG87CiAgcGFkZGluZzogMC41
+ZW07CiAgLyoqCiAgICogVGhpcyBhbGxvd3MgdGhlIHBlci1saW5lIGhpZ2hsaWdodHMgdG8gc2hvdy4K
+ICAgKi8KICBiYWNrZ3JvdW5kOiBub25lOwp9CgouaGxqcy1rZXl3b3JkLAouaGxqcy1zZWxlY3Rvci10
+YWcsCi5obGpzLWRlbGV0aW9uIHsKICBjb2xvcjogIzUxYzY4NjsgLyogY20ta2V5d29yZCAqLwp9Cgou
+aGxqcy1udW1iZXIgewogIGNvbG9yOiAjNjI3OTc4OyAvKiBjbS1udW1iZXIgKi8KfQoKLmhsanMtY29t
+bWVudCB7CiAgY29sb3I6ICM5MTk4YjQ7IC8qIGNtLWNvbW1lbnQgKi8KfQoKLmhsanMtbGl0ZXJhbCB7
+CiAgY29sb3I6ICNlZTg2NjY7IC8qIGNtLWF0b20gKi8KfQoKLmhsanMtc3RyaW5nIHsKICBjb2xvcjog
+I2U1NTA3NDsgLyogY20tc3RyaW5nICovCn0KCi5obGpzLXZhcmlhYmxlIHsKICBjb2xvcjogIzE2YWRj
+YTsgLyogY20tdmFyaWFibGUgKi8KfQoKLmhsanMtbGluayB7CiAgY29sb3I6ICNlNTUwNzQ7IC8qIGNt
+LXN0cmluZyAqLwp9Ci5obGpzLXNlY3Rpb24sCi5obGpzLXR5cGUsCi5obGpzLWJ1aWx0X2luLAouaGxq
+cy10aXRsZSB7CiAgY29sb3I6ICNlZTg2NjY7IC8qIGNtLXZhcmlhYmxlLTIgKi8KfQoKLmhsanMtYWRk
+aXRpb24gewogIGNvbG9yOiAjMjYzOTUyOyAvKiAkZGFyay1zZWxlY3Rpb24tY29sb3IgKi8KfQoKLmhs
+anMtbWV0YSB7CiAgY29sb3I6ICM2Mjc5Nzg7Cn0K
 ''';
 
 String _migration_js;
-// migration_dart md5 is 'fd54888536280a9cc3c222ccaf1597fa'
+// migration_dart md5 is 'f0f101e4851eb5288f5fa4074c4246a6'
 String _migration_js_base64 = '''
 KGZ1bmN0aW9uIGRhcnRQcm9ncmFtKCl7ZnVuY3Rpb24gY29weVByb3BlcnRpZXMoYSxiKXt2YXIgcz1P
 YmplY3Qua2V5cyhhKQpmb3IodmFyIHI9MDtyPHMubGVuZ3RoO3IrKyl7dmFyIHE9c1tyXQpiW3FdPWFb
-cV19fXZhciB6PWZ1bmN0aW9uKCl7dmFyIHM9ZnVuY3Rpb24oKXt9CnMucHJvdG90eXBlPXtwOnt9fQp2
-YXIgcj1uZXcgcygpCmlmKCEoci5fX3Byb3RvX18mJnIuX19wcm90b19fLnA9PT1zLnByb3RvdHlwZS5w
-KSlyZXR1cm4gZmFsc2UKdHJ5e2lmKHR5cGVvZiBuYXZpZ2F0b3IhPSJ1bmRlZmluZWQiJiZ0eXBlb2Yg
-bmF2aWdhdG9yLnVzZXJBZ2VudD09InN0cmluZyImJm5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZigi
-Q2hyb21lLyIpPj0wKXJldHVybiB0cnVlCmlmKHR5cGVvZiB2ZXJzaW9uPT0iZnVuY3Rpb24iJiZ2ZXJz
-aW9uLmxlbmd0aD09MCl7dmFyIHE9dmVyc2lvbigpCmlmKC9eXGQrXC5cZCtcLlxkK1wuXGQrJC8udGVz
-dChxKSlyZXR1cm4gdHJ1ZX19Y2F0Y2gocCl7fXJldHVybiBmYWxzZX0oKQpmdW5jdGlvbiBzZXRGdW5j
-dGlvbk5hbWVzSWZOZWNlc3NhcnkoYSl7ZnVuY3Rpb24gdCgpe307aWYodHlwZW9mIHQubmFtZT09InN0
-cmluZyIpcmV0dXJuCmZvcih2YXIgcz0wO3M8YS5sZW5ndGg7cysrKXt2YXIgcj1hW3NdCnZhciBxPU9i
-amVjdC5rZXlzKHIpCmZvcih2YXIgcD0wO3A8cS5sZW5ndGg7cCsrKXt2YXIgbz1xW3BdCnZhciBuPXJb
-b10KaWYodHlwZW9mIG49PSdmdW5jdGlvbicpbi5uYW1lPW99fX1mdW5jdGlvbiBpbmhlcml0KGEsYil7
-YS5wcm90b3R5cGUuY29uc3RydWN0b3I9YQphLnByb3RvdHlwZVsiJGkiK2EubmFtZV09YQppZihiIT1u
-dWxsKXtpZih6KXthLnByb3RvdHlwZS5fX3Byb3RvX189Yi5wcm90b3R5cGUKcmV0dXJufXZhciBzPU9i
-amVjdC5jcmVhdGUoYi5wcm90b3R5cGUpCmNvcHlQcm9wZXJ0aWVzKGEucHJvdG90eXBlLHMpCmEucHJv
-dG90eXBlPXN9fWZ1bmN0aW9uIGluaGVyaXRNYW55KGEsYil7Zm9yKHZhciBzPTA7czxiLmxlbmd0aDtz
-KyspaW5oZXJpdChiW3NdLGEpfWZ1bmN0aW9uIG1peGluKGEsYil7Y29weVByb3BlcnRpZXMoYi5wcm90
-b3R5cGUsYS5wcm90b3R5cGUpCmEucHJvdG90eXBlLmNvbnN0cnVjdG9yPWF9ZnVuY3Rpb24gbGF6eU9s
-ZChhLGIsYyxkKXt2YXIgcz1hCmFbYl09cwphW2NdPWZ1bmN0aW9uKCl7YVtjXT1mdW5jdGlvbigpe0gu
-YWcoYil9CnZhciByCnZhciBxPWQKdHJ5e2lmKGFbYl09PT1zKXtyPWFbYl09cQpyPWFbYl09ZCgpfWVs
-c2Ugcj1hW2JdfWZpbmFsbHl7aWYocj09PXEpYVtiXT1udWxsCmFbY109ZnVuY3Rpb24oKXtyZXR1cm4g
-dGhpc1tiXX19cmV0dXJuIHJ9fWZ1bmN0aW9uIGxhenkoYSxiLGMsZCl7dmFyIHM9YQphW2JdPXMKYVtj
-XT1mdW5jdGlvbigpe2lmKGFbYl09PT1zKWFbYl09ZCgpCmFbY109ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
-c1tiXX0KcmV0dXJuIGFbYl19fWZ1bmN0aW9uIGxhenlGaW5hbChhLGIsYyxkKXt2YXIgcz1hCmFbYl09
-cwphW2NdPWZ1bmN0aW9uKCl7aWYoYVtiXT09PXMpe3ZhciByPWQoKQppZihhW2JdIT09cylILkJvKGIp
-CmFbYl09cn1hW2NdPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXNbYl19CnJldHVybiBhW2JdfX1mdW5jdGlv
-biBtYWtlQ29uc3RMaXN0KGEpe2EuaW1tdXRhYmxlJGxpc3Q9QXJyYXkKYS5maXhlZCRsZW5ndGg9QXJy
-YXkKcmV0dXJuIGF9ZnVuY3Rpb24gY29udmVydFRvRmFzdE9iamVjdChhKXtmdW5jdGlvbiB0KCl7fXQu
-cHJvdG90eXBlPWEKbmV3IHQoKQpyZXR1cm4gYX1mdW5jdGlvbiBjb252ZXJ0QWxsVG9GYXN0T2JqZWN0
-KGEpe2Zvcih2YXIgcz0wO3M8YS5sZW5ndGg7KytzKWNvbnZlcnRUb0Zhc3RPYmplY3QoYVtzXSl9dmFy
-IHk9MApmdW5jdGlvbiB0ZWFyT2ZmR2V0dGVyKGEsYixjLGQsZSl7cmV0dXJuIGU/bmV3IEZ1bmN0aW9u
-KCJmdW5jcyIsImFwcGx5VHJhbXBvbGluZUluZGV4IiwicmVmbGVjdGlvbkluZm8iLCJuYW1lIiwiSCIs
-ImMiLCJyZXR1cm4gZnVuY3Rpb24gdGVhck9mZl8iK2QreSsrKyIocmVjZWl2ZXIpIHsiKyJpZiAoYyA9
-PT0gbnVsbCkgYyA9ICIrIkguS3EiKyIoIisidGhpcywgZnVuY3MsIGFwcGx5VHJhbXBvbGluZUluZGV4
-LCByZWZsZWN0aW9uSW5mbywgZmFsc2UsIHRydWUsIG5hbWUpOyIrInJldHVybiBuZXcgYyh0aGlzLCBm
-dW5jc1swXSwgcmVjZWl2ZXIsIG5hbWUpOyIrIn0iKShhLGIsYyxkLEgsbnVsbCk6bmV3IEZ1bmN0aW9u
-KCJmdW5jcyIsImFwcGx5VHJhbXBvbGluZUluZGV4IiwicmVmbGVjdGlvbkluZm8iLCJuYW1lIiwiSCIs
-ImMiLCJyZXR1cm4gZnVuY3Rpb24gdGVhck9mZl8iK2QreSsrKyIoKSB7IisiaWYgKGMgPT09IG51bGwp
-IGMgPSAiKyJILktxIisiKCIrInRoaXMsIGZ1bmNzLCBhcHBseVRyYW1wb2xpbmVJbmRleCwgcmVmbGVj
-dGlvbkluZm8sIGZhbHNlLCBmYWxzZSwgbmFtZSk7IisicmV0dXJuIG5ldyBjKHRoaXMsIGZ1bmNzWzBd
-LCBudWxsLCBuYW1lKTsiKyJ9IikoYSxiLGMsZCxILG51bGwpfWZ1bmN0aW9uIHRlYXJPZmYoYSxiLGMs
-ZCxlLGYpe3ZhciBzPW51bGwKcmV0dXJuIGQ/ZnVuY3Rpb24oKXtpZihzPT09bnVsbClzPUguS3EodGhp
-cyxhLGIsYyx0cnVlLGZhbHNlLGUpLnByb3RvdHlwZQpyZXR1cm4gc306dGVhck9mZkdldHRlcihhLGIs
-YyxlLGYpfXZhciB4PTAKZnVuY3Rpb24gaW5zdGFsbFRlYXJPZmYoYSxiLGMsZCxlLGYsZyxoLGksail7
-dmFyIHM9W10KZm9yKHZhciByPTA7cjxoLmxlbmd0aDtyKyspe3ZhciBxPWhbcl0KaWYodHlwZW9mIHE9
-PSdzdHJpbmcnKXE9YVtxXQpxLiRjYWxsTmFtZT1nW3JdCnMucHVzaChxKX12YXIgcT1zWzBdCnEuJFI9
-ZQpxLiREPWYKdmFyIHA9aQppZih0eXBlb2YgcD09Im51bWJlciIpcCs9eAp2YXIgbz1oWzBdCnEuJHN0
-dWJOYW1lPW8KdmFyIG49dGVhck9mZihzLGp8fDAscCxjLG8sZCkKYVtiXT1uCmlmKGMpcS4kdGVhck9m
-Zj1ufWZ1bmN0aW9uIGluc3RhbGxTdGF0aWNUZWFyT2ZmKGEsYixjLGQsZSxmLGcsaCl7cmV0dXJuIGlu
-c3RhbGxUZWFyT2ZmKGEsYix0cnVlLGZhbHNlLGMsZCxlLGYsZyxoKX1mdW5jdGlvbiBpbnN0YWxsSW5z
-dGFuY2VUZWFyT2ZmKGEsYixjLGQsZSxmLGcsaCxpKXtyZXR1cm4gaW5zdGFsbFRlYXJPZmYoYSxiLGZh
-bHNlLGMsZCxlLGYsZyxoLGkpfWZ1bmN0aW9uIHNldE9yVXBkYXRlSW50ZXJjZXB0b3JzQnlUYWcoYSl7
-dmFyIHM9di5pbnRlcmNlcHRvcnNCeVRhZwppZighcyl7di5pbnRlcmNlcHRvcnNCeVRhZz1hCnJldHVy
-bn1jb3B5UHJvcGVydGllcyhhLHMpfWZ1bmN0aW9uIHNldE9yVXBkYXRlTGVhZlRhZ3MoYSl7dmFyIHM9
-di5sZWFmVGFncwppZighcyl7di5sZWFmVGFncz1hCnJldHVybn1jb3B5UHJvcGVydGllcyhhLHMpfWZ1
-bmN0aW9uIHVwZGF0ZVR5cGVzKGEpe3ZhciBzPXYudHlwZXMKdmFyIHI9cy5sZW5ndGgKcy5wdXNoLmFw
-cGx5KHMsYSkKcmV0dXJuIHJ9ZnVuY3Rpb24gdXBkYXRlSG9sZGVyKGEsYil7Y29weVByb3BlcnRpZXMo
-YixhKQpyZXR1cm4gYX12YXIgaHVua0hlbHBlcnM9ZnVuY3Rpb24oKXt2YXIgcz1mdW5jdGlvbihhLGIs
-YyxkLGUpe3JldHVybiBmdW5jdGlvbihmLGcsaCxpKXtyZXR1cm4gaW5zdGFsbEluc3RhbmNlVGVhck9m
-ZihmLGcsYSxiLGMsZCxbaF0saSxlKX19LHI9ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGZ1bmN0aW9u
-KGUsZixnLGgpe3JldHVybiBpbnN0YWxsU3RhdGljVGVhck9mZihlLGYsYSxiLGMsW2ddLGgsZCl9fQpy
-ZXR1cm57aW5oZXJpdDppbmhlcml0LGluaGVyaXRNYW55OmluaGVyaXRNYW55LG1peGluOm1peGluLGlu
-c3RhbGxTdGF0aWNUZWFyT2ZmOmluc3RhbGxTdGF0aWNUZWFyT2ZmLGluc3RhbGxJbnN0YW5jZVRlYXJP
-ZmY6aW5zdGFsbEluc3RhbmNlVGVhck9mZixfaW5zdGFuY2VfMHU6cygwLDAsbnVsbCxbIiQwIl0sMCks
-X2luc3RhbmNlXzF1OnMoMCwxLG51bGwsWyIkMSJdLDApLF9pbnN0YW5jZV8ydTpzKDAsMixudWxsLFsi
-JDIiXSwwKSxfaW5zdGFuY2VfMGk6cygxLDAsbnVsbCxbIiQwIl0sMCksX2luc3RhbmNlXzFpOnMoMSwx
-LG51bGwsWyIkMSJdLDApLF9pbnN0YW5jZV8yaTpzKDEsMixudWxsLFsiJDIiXSwwKSxfc3RhdGljXzA6
-cigwLG51bGwsWyIkMCJdLDApLF9zdGF0aWNfMTpyKDEsbnVsbCxbIiQxIl0sMCksX3N0YXRpY18yOnIo
-MixudWxsLFsiJDIiXSwwKSxtYWtlQ29uc3RMaXN0Om1ha2VDb25zdExpc3QsbGF6eTpsYXp5LGxhenlG
-aW5hbDpsYXp5RmluYWwsbGF6eU9sZDpsYXp5T2xkLHVwZGF0ZUhvbGRlcjp1cGRhdGVIb2xkZXIsY29u
-dmVydFRvRmFzdE9iamVjdDpjb252ZXJ0VG9GYXN0T2JqZWN0LHNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vz
-c2FyeTpzZXRGdW5jdGlvbk5hbWVzSWZOZWNlc3NhcnksdXBkYXRlVHlwZXM6dXBkYXRlVHlwZXMsc2V0
-T3JVcGRhdGVJbnRlcmNlcHRvcnNCeVRhZzpzZXRPclVwZGF0ZUludGVyY2VwdG9yc0J5VGFnLHNldE9y
-VXBkYXRlTGVhZlRhZ3M6c2V0T3JVcGRhdGVMZWFmVGFnc319KCkKZnVuY3Rpb24gaW5pdGlhbGl6ZURl
-ZmVycmVkSHVuayhhKXt4PXYudHlwZXMubGVuZ3RoCmEoaHVua0hlbHBlcnMsdix3LCQpfWZ1bmN0aW9u
-IGdldEdsb2JhbEZyb21OYW1lKGEpe2Zvcih2YXIgcz0wO3M8dy5sZW5ndGg7cysrKXtpZih3W3NdPT1D
-KWNvbnRpbnVlCmlmKHdbc11bYV0pcmV0dXJuIHdbc11bYV19fXZhciBDPXt9LEg9e0ZLOmZ1bmN0aW9u
-IEZLKCl7fSwKR0o6ZnVuY3Rpb24oYSxiLGMpe2lmKGIuQygiYlE8MD4iKS5iKGEpKXJldHVybiBuZXcg
-SC5vbChhLGIuQygiQDwwPiIpLktxKGMpLkMoIm9sPDEsMj4iKSkKcmV0dXJuIG5ldyBILlp5KGEsYi5D
-KCJAPDA+IikuS3EoYykuQygiWnk8MSwyPiIpKX0sCkdROmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5u
-KCJGaWVsZCAnIithKyInIGhhcyBiZWVuIGFzc2lnbmVkIGR1cmluZyBpbml0aWFsaXphdGlvbi4iKX0s
-CkJpOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5yMyhhKX0sCm9vOmZ1bmN0aW9uKGEpe3ZhciBzLHI9
-YV40OAppZihyPD05KXJldHVybiByCnM9YXwzMgppZig5Nzw9cyYmczw9MTAyKXJldHVybiBzLTg3CnJl
-dHVybi0xfSwKY2I6ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpdGhyb3cgSC5iKG5ldyBILkdNKGIs
-Yy5DKCJHTTwwPiIpKSkKcmV0dXJuIGF9LApxQzpmdW5jdGlvbihhLGIsYyxkKXtQLmsxKGIsInN0YXJ0
-IikKaWYoYyE9bnVsbCl7UC5rMShjLCJlbmQiKQppZihiPmMpSC52KFAuVEUoYiwwLGMsInN0YXJ0Iixu
-dWxsKSl9cmV0dXJuIG5ldyBILm5IKGEsYixjLGQuQygibkg8MD4iKSl9LApLMTpmdW5jdGlvbihhLGIs
-YyxkKXtpZih0LmIuYihhKSlyZXR1cm4gbmV3IEgueHkoYSxiLGMuQygiQDwwPiIpLktxKGQpLkMoInh5
-PDEsMj4iKSkKcmV0dXJuIG5ldyBILmkxKGEsYixjLkMoIkA8MD4iKS5LcShkKS5DKCJpMTwxLDI+Iikp
-fSwKYks6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPSJjb3VudCIKaWYodC5iLmIoYSkpe1AuTVIoYixzLHQu
-UykKUC5rMShiLHMpCnJldHVybiBuZXcgSC5kNShhLGIsYy5DKCJkNTwwPiIpKX1QLk1SKGIscyx0LlMp
-ClAuazEoYixzKQpyZXR1cm4gbmV3IEguQU0oYSxiLGMuQygiQU08MD4iKSl9LApXcDpmdW5jdGlvbigp
-e3JldHVybiBuZXcgUC5saigiTm8gZWxlbWVudCIpfSwKQW06ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IFAu
-bGooIlRvbyBtYW55IGVsZW1lbnRzIil9LAphcjpmdW5jdGlvbigpe3JldHVybiBuZXcgUC5saigiVG9v
-IGZldyBlbGVtZW50cyIpfSwKQlI6ZnVuY3Rpb24gQlIoKXt9LApFNzpmdW5jdGlvbiBFNyhhLGIpe3Ro
-aXMuYT1hCnRoaXMuJHRpPWJ9LApaeTpmdW5jdGlvbiBaeShhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9
-LApvbDpmdW5jdGlvbiBvbChhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApVcTpmdW5jdGlvbiBVcSgp
-e30sCmpWOmZ1bmN0aW9uIGpWKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCm46ZnVuY3Rpb24gbihh
-KXt0aGlzLmE9YX0sCnIzOmZ1bmN0aW9uIHIzKGEpe3RoaXMuYT1hfSwKcWo6ZnVuY3Rpb24gcWooYSl7
-dGhpcy5hPWF9LApHTTpmdW5jdGlvbiBHTShhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApiUTpmdW5j
-dGlvbiBiUSgpe30sCmFMOmZ1bmN0aW9uIGFMKCl7fSwKbkg6ZnVuY3Rpb24gbkgoYSxiLGMsZCl7dmFy
-IF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKYTc6ZnVuY3Rpb24gYTcoYSxiLGMpe3Zh
-ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCmkxOmZ1bmN0aW9uIGkx
-KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKeHk6ZnVuY3Rpb24geHkoYSxiLGMp
-e3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApNSDpmdW5jdGlvbiBNSChhLGIsYyl7dmFyIF89
-dGhpcwpfLmE9bnVsbApfLmI9YQpfLmM9YgpfLiR0aT1jfSwKbEo6ZnVuY3Rpb24gbEooYSxiLGMpe3Ro
-aXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApVNTpmdW5jdGlvbiBVNShhLGIsYyl7dGhpcy5hPWEK
-dGhpcy5iPWIKdGhpcy4kdGk9Y30sClNPOmZ1bmN0aW9uIFNPKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9
-Ygp0aGlzLiR0aT1jfSwKQU06ZnVuY3Rpb24gQU0oYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMu
-JHRpPWN9LApkNTpmdW5jdGlvbiBkNShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30s
-ClUxOmZ1bmN0aW9uIFUxKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKTUI6ZnVu
-Y3Rpb24gTUIoYSl7dGhpcy4kdGk9YX0sCkZ1OmZ1bmN0aW9uIEZ1KGEpe3RoaXMuJHRpPWF9LAp1Njpm
-dW5jdGlvbiB1NihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApKQjpmdW5jdGlvbiBKQihhLGIpe3Ro
-aXMuYT1hCnRoaXMuJHRpPWJ9LApTVTpmdW5jdGlvbiBTVSgpe30sClJlOmZ1bmN0aW9uIFJlKCl7fSwK
-dzI6ZnVuY3Rpb24gdzIoKXt9LAp3djpmdW5jdGlvbiB3dihhKXt0aGlzLmE9YX0sClFDOmZ1bmN0aW9u
-IFFDKCl7fSwKZGM6ZnVuY3Rpb24oKXt0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlm
-aWFibGUgTWFwIikpfSwKTlE6ZnVuY3Rpb24oYSl7dmFyIHMscj1ILkpnKGEpCmlmKHIhPW51bGwpcmV0
-dXJuIHIKcz0ibWluaWZpZWQ6IithCnJldHVybiBzfSwKd1Y6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihi
-IT1udWxsKXtzPWIueAppZihzIT1udWxsKXJldHVybiBzfXJldHVybiB0LmFVLmIoYSl9LApFajpmdW5j
-dGlvbihhKXt2YXIgcwppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJu
-dW1iZXIiKXtpZihhIT09MClyZXR1cm4iIithfWVsc2UgaWYoITA9PT1hKXJldHVybiJ0cnVlIgplbHNl
-IGlmKCExPT09YSlyZXR1cm4iZmFsc2UiCmVsc2UgaWYoYT09bnVsbClyZXR1cm4ibnVsbCIKcz1KLmoo
-YSkKaWYodHlwZW9mIHMhPSJzdHJpbmciKXRocm93IEguYihILnRMKGEpKQpyZXR1cm4gc30sCmVROmZ1
-bmN0aW9uKGEpe3ZhciBzPWEuJGlkZW50aXR5SGFzaAppZihzPT1udWxsKXtzPU1hdGgucmFuZG9tKCkq
-MHgzZmZmZmZmZnwwCmEuJGlkZW50aXR5SGFzaD1zfXJldHVybiBzfSwKSHA6ZnVuY3Rpb24oYSxiKXt2
-YXIgcyxyLHEscCxvLG4sbT1udWxsCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILnYoSC50TChhKSkKcz0v
-XlxzKlsrLV0/KCgweFthLWYwLTldKyl8KFxkKyl8KFthLXowLTldKykpXHMqJC9pLmV4ZWMoYSkKaWYo
-cz09bnVsbClyZXR1cm4gbQppZigzPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLDMpCnI9c1szXQppZihi
-PT1udWxsKXtpZihyIT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZihzWzJdIT1udWxsKXJldHVy
-biBwYXJzZUludChhLDE2KQpyZXR1cm4gbX1pZihiPDJ8fGI+MzYpdGhyb3cgSC5iKFAuVEUoYiwyLDM2
-LCJyYWRpeCIsbSkpCmlmKGI9PT0xMCYmciE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkKaWYoYjwx
-MHx8cj09bnVsbCl7cT1iPD0xMD80NytiOjg2K2IKcD1zWzFdCmZvcihvPXAubGVuZ3RoLG49MDtuPG87
-KytuKWlmKChDLnhCLlcocCxuKXwzMik+cSlyZXR1cm4gbX1yZXR1cm4gcGFyc2VJbnQoYSxiKX0sCk06
-ZnVuY3Rpb24oYSl7cmV0dXJuIEguSDUoYSl9LApINTpmdW5jdGlvbihhKXt2YXIgcyxyLHEKaWYoYSBp
-bnN0YW5jZW9mIFAuTWgpcmV0dXJuIEguZG0oSC56KGEpLG51bGwpCmlmKEouaWEoYSk9PT1DLk9rfHx0
-LmJKLmIoYSkpe3M9Qy5PNChhKQppZihILkJlKHMpKXJldHVybiBzCnI9YS5jb25zdHJ1Y3RvcgppZih0
-eXBlb2Ygcj09ImZ1bmN0aW9uIil7cT1yLm5hbWUKaWYodHlwZW9mIHE9PSJzdHJpbmciJiZILkJlKHEp
-KXJldHVybiBxfX1yZXR1cm4gSC5kbShILnooYSksbnVsbCl9LApCZTpmdW5jdGlvbihhKXt2YXIgcz1h
-IT09Ik9iamVjdCImJmEhPT0iIgpyZXR1cm4gc30sCk0wOmZ1bmN0aW9uKCl7aWYoISFzZWxmLmxvY2F0
-aW9uKXJldHVybiBzZWxmLmxvY2F0aW9uLmhyZWYKcmV0dXJuIG51bGx9LApWSzpmdW5jdGlvbihhKXt2
-YXIgcyxyLHEscCxvPWEubGVuZ3RoCmlmKG88PTUwMClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5h
-cHBseShudWxsLGEpCmZvcihzPSIiLHI9MDtyPG87cj1xKXtxPXIrNTAwCnA9cTxvP3E6bwpzKz1TdHJp
-bmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYS5zbGljZShyLHApKX1yZXR1cm4gc30sCkNxOmZ1bmN0
-aW9uKGEpe3ZhciBzLHIscSxwPUguVk0oW10sdC5hKQpmb3Iocz1hLmxlbmd0aCxyPTA7cjxhLmxlbmd0
-aDthLmxlbmd0aD09PXN8fCgwLEgubGspKGEpLCsrcil7cT1hW3JdCmlmKCFILm9rKHEpKXRocm93IEgu
-YihILnRMKHEpKQppZihxPD02NTUzNSlDLk5tLmkocCxxKQplbHNlIGlmKHE8PTExMTQxMTEpe0MuTm0u
-aShwLDU1Mjk2KyhDLmpuLndHKHEtNjU1MzYsMTApJjEwMjMpKQpDLk5tLmkocCw1NjMyMCsocSYxMDIz
-KSl9ZWxzZSB0aHJvdyBILmIoSC50TChxKSl9cmV0dXJuIEguVksocCl9LAplVDpmdW5jdGlvbihhKXt2
-YXIgcyxyLHEKZm9yKHM9YS5sZW5ndGgscj0wO3I8czsrK3Ipe3E9YVtyXQppZighSC5vayhxKSl0aHJv
-dyBILmIoSC50TChxKSkKaWYocTwwKXRocm93IEguYihILnRMKHEpKQppZihxPjY1NTM1KXJldHVybiBI
-LkNxKGEpfXJldHVybiBILlZLKGEpfSwKZnc6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwCmlmKGM8
-PTUwMCYmYj09PTAmJmM9PT1hLmxlbmd0aClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShu
-dWxsLGEpCmZvcihzPWIscj0iIjtzPGM7cz1xKXtxPXMrNTAwCnA9cTxjP3E6YwpyKz1TdHJpbmcuZnJv
-bUNoYXJDb2RlLmFwcGx5KG51bGwsYS5zdWJhcnJheShzLHApKX1yZXR1cm4gcn0sCkx3OmZ1bmN0aW9u
-KGEpe3ZhciBzCmlmKDA8PWEpe2lmKGE8PTY1NTM1KXJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGEp
-CmlmKGE8PTExMTQxMTEpe3M9YS02NTUzNgpyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgoQy5qbi53
-RyhzLDEwKXw1NTI5Nik+Pj4wLHMmMTAyM3w1NjMyMCl9fXRocm93IEguYihQLlRFKGEsMCwxMTE0MTEx
-LG51bGwsbnVsbCkpfSwKbzI6ZnVuY3Rpb24oYSl7aWYoYS5kYXRlPT09dm9pZCAwKWEuZGF0ZT1uZXcg
-RGF0ZShhLmEpCnJldHVybiBhLmRhdGV9LAp0SjpmdW5jdGlvbihhKXt2YXIgcz1ILm8yKGEpLmdldEZ1
-bGxZZWFyKCkrMApyZXR1cm4gc30sCk5TOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0TW9udGgo
-KSsxCnJldHVybiBzfSwKakE6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vMihhKS5nZXREYXRlKCkrMApyZXR1
-cm4gc30sCklYOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0SG91cnMoKSswCnJldHVybiBzfSwK
-Y2g6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vMihhKS5nZXRNaW51dGVzKCkrMApyZXR1cm4gc30sCkpkOmZ1
-bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0U2Vjb25kcygpKzAKcmV0dXJuIHN9LApvMTpmdW5jdGlv
-bihhKXt2YXIgcz1ILm8yKGEpLmdldE1pbGxpc2Vjb25kcygpKzAKcmV0dXJuIHN9LAp6bzpmdW5jdGlv
-bihhLGIsYyl7dmFyIHMscixxPXt9CnEuYT0wCnM9W10Kcj1bXQpxLmE9Yi5sZW5ndGgKQy5ObS5GVihz
-LGIpCnEuYj0iIgppZihjIT1udWxsJiZjLmEhPT0wKWMuSygwLG5ldyBILkNqKHEscixzKSkKIiIrcS5h
-CnJldHVybiBKLkp5KGEsbmV3IEguTEkoQy5UZSwwLHMsciwwKSl9LApFazpmdW5jdGlvbihhLGIsYyl7
-dmFyIHMscixxLHAKaWYoYiBpbnN0YW5jZW9mIEFycmF5KXM9Yz09bnVsbHx8Yy5hPT09MAplbHNlIHM9
-ITEKaWYocyl7cj1iCnE9ci5sZW5ndGgKaWYocT09PTApe2lmKCEhYS4kMClyZXR1cm4gYS4kMCgpfWVs
-c2UgaWYocT09PTEpe2lmKCEhYS4kMSlyZXR1cm4gYS4kMShyWzBdKX1lbHNlIGlmKHE9PT0yKXtpZigh
-IWEuJDIpcmV0dXJuIGEuJDIoclswXSxyWzFdKX1lbHNlIGlmKHE9PT0zKXtpZighIWEuJDMpcmV0dXJu
-IGEuJDMoclswXSxyWzFdLHJbMl0pfWVsc2UgaWYocT09PTQpe2lmKCEhYS4kNClyZXR1cm4gYS4kNChy
-WzBdLHJbMV0sclsyXSxyWzNdKX1lbHNlIGlmKHE9PT01KWlmKCEhYS4kNSlyZXR1cm4gYS4kNShyWzBd
-LHJbMV0sclsyXSxyWzNdLHJbNF0pCnA9YVsiIisiJCIrcV0KaWYocCE9bnVsbClyZXR1cm4gcC5hcHBs
-eShhLHIpfXJldHVybiBILmUxKGEsYixjKX0sCmUxOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxv
-LG4sbSxsLGssaixpPWIgaW5zdGFuY2VvZiBBcnJheT9iOlAuQ0goYiwhMCx0LnopLGg9aS5sZW5ndGgs
-Zz1hLiRSCmlmKGg8ZylyZXR1cm4gSC56byhhLGksYykKcz1hLiRECnI9cz09bnVsbApxPSFyP3MoKTpu
-dWxsCnA9Si5pYShhKQpvPXAuJEMKaWYodHlwZW9mIG89PSJzdHJpbmciKW89cFtvXQppZihyKXtpZihj
-IT1udWxsJiZjLmEhPT0wKXJldHVybiBILnpvKGEsaSxjKQppZihoPT09ZylyZXR1cm4gby5hcHBseShh
-LGkpCnJldHVybiBILnpvKGEsaSxjKX1pZihxIGluc3RhbmNlb2YgQXJyYXkpe2lmKGMhPW51bGwmJmMu
-YSE9PTApcmV0dXJuIEguem8oYSxpLGMpCmlmKGg+ZytxLmxlbmd0aClyZXR1cm4gSC56byhhLGksbnVs
-bCkKQy5ObS5GVihpLHEuc2xpY2UoaC1nKSkKcmV0dXJuIG8uYXBwbHkoYSxpKX1lbHNle2lmKGg+Zyly
-ZXR1cm4gSC56byhhLGksYykKbj1PYmplY3Qua2V5cyhxKQppZihjPT1udWxsKWZvcihyPW4ubGVuZ3Ro
-LG09MDttPG4ubGVuZ3RoO24ubGVuZ3RoPT09cnx8KDAsSC5saykobiksKyttKXtsPXFbSC5oKG5bbV0p
-XQppZihDLk52PT09bClyZXR1cm4gSC56byhhLGksYykKQy5ObS5pKGksbCl9ZWxzZXtmb3Iocj1uLmxl
-bmd0aCxrPTAsbT0wO208bi5sZW5ndGg7bi5sZW5ndGg9PT1yfHwoMCxILmxrKShuKSwrK20pe2o9SC5o
-KG5bbV0pCmlmKGMueDQoaikpeysrawpDLk5tLmkoaSxjLnEoMCxqKSl9ZWxzZXtsPXFbal0KaWYoQy5O
-dj09PWwpcmV0dXJuIEguem8oYSxpLGMpCkMuTm0uaShpLGwpfX1pZihrIT09Yy5hKXJldHVybiBILnpv
-KGEsaSxjKX1yZXR1cm4gby5hcHBseShhLGkpfX0sCnBZOmZ1bmN0aW9uKGEpe3Rocm93IEguYihILnRM
-KGEpKX0sCk9IOmZ1bmN0aW9uKGEsYil7aWYoYT09bnVsbClKLkhtKGEpCnRocm93IEguYihILkhZKGEs
-YikpfSwKSFk6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9ImluZGV4IgppZighSC5vayhiKSlyZXR1cm4g
-bmV3IFAudSghMCxiLHEsbnVsbCkKcz1ILnVQKEouSG0oYSkpCmlmKCEoYjwwKSl7aWYodHlwZW9mIHMh
-PT0ibnVtYmVyIilyZXR1cm4gSC5wWShzKQpyPWI+PXN9ZWxzZSByPSEwCmlmKHIpcmV0dXJuIFAuQ2Yo
-YixhLHEsbnVsbCxzKQpyZXR1cm4gUC5PNyhiLHEpfSwKYXU6ZnVuY3Rpb24oYSxiLGMpe2lmKGE+Yyly
-ZXR1cm4gUC5URShhLDAsYywic3RhcnQiLG51bGwpCmlmKGIhPW51bGwpaWYoYjxhfHxiPmMpcmV0dXJu
-IFAuVEUoYixhLGMsImVuZCIsbnVsbCkKcmV0dXJuIG5ldyBQLnUoITAsYiwiZW5kIixudWxsKX0sCnRM
-OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC51KCEwLGEsbnVsbCxudWxsKX0sCmI6ZnVuY3Rpb24oYSl7
-dmFyIHMscgppZihhPT1udWxsKWE9bmV3IFAuRigpCnM9bmV3IEVycm9yKCkKcy5kYXJ0RXhjZXB0aW9u
-PWEKcj1ILngKaWYoImRlZmluZVByb3BlcnR5IiBpbiBPYmplY3Qpe09iamVjdC5kZWZpbmVQcm9wZXJ0
-eShzLCJtZXNzYWdlIix7Z2V0OnJ9KQpzLm5hbWU9IiJ9ZWxzZSBzLnRvU3RyaW5nPXIKcmV0dXJuIHN9
-LAp4OmZ1bmN0aW9uKCl7cmV0dXJuIEouaih0aGlzLmRhcnRFeGNlcHRpb24pfSwKdjpmdW5jdGlvbihh
-KXt0aHJvdyBILmIoYSl9LApsazpmdW5jdGlvbihhKXt0aHJvdyBILmIoUC5hNChhKSl9LApjTTpmdW5j
-dGlvbihhKXt2YXIgcyxyLHEscCxvLG4KYT1ILmVBKGEucmVwbGFjZShTdHJpbmcoe30pLCckcmVjZWl2
-ZXIkJykpCnM9YS5tYXRjaCgvXFxcJFthLXpBLVpdK1xcXCQvZykKaWYocz09bnVsbClzPUguVk0oW10s
-dC5zKQpyPXMuaW5kZXhPZigiXFwkYXJndW1lbnRzXFwkIikKcT1zLmluZGV4T2YoIlxcJGFyZ3VtZW50
-c0V4cHJcXCQiKQpwPXMuaW5kZXhPZigiXFwkZXhwclxcJCIpCm89cy5pbmRleE9mKCJcXCRtZXRob2Rc
-XCQiKQpuPXMuaW5kZXhPZigiXFwkcmVjZWl2ZXJcXCQiKQpyZXR1cm4gbmV3IEguZjkoYS5yZXBsYWNl
-KG5ldyBSZWdFeHAoJ1xcXFxcXCRhcmd1bWVudHNcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJyku
-cmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkYXJndW1lbnRzRXhwclxcXFxcXCQnLCdnJyksJygoPzp4
-fFteeF0pKiknKS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRleHByXFxcXFxcJCcsJ2cnKSwnKCg/
-Onh8W154XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJG1ldGhvZFxcXFxcXCQnLCdnJyks
-JygoPzp4fFteeF0pKiknKS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRyZWNlaXZlclxcXFxcXCQn
-LCdnJyksJygoPzp4fFteeF0pKiknKSxyLHEscCxvLG4pfSwKUzc6ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1
-bmN0aW9uKCRleHByJCl7dmFyICRhcmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXskZXhwciQu
-JG1ldGhvZCQoJGFyZ3VtZW50c0V4cHIkKX1jYXRjaChzKXtyZXR1cm4gcy5tZXNzYWdlfX0oYSl9LApN
-ajpmdW5jdGlvbihhKXtyZXR1cm4gZnVuY3Rpb24oJGV4cHIkKXt0cnl7JGV4cHIkLiRtZXRob2QkfWNh
-dGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fShhKX0sCklqOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBI
-LlcwKGEsYj09bnVsbD9udWxsOmIubWV0aG9kKX0sClQzOmZ1bmN0aW9uKGEsYil7dmFyIHM9Yj09bnVs
-bCxyPXM/bnVsbDpiLm1ldGhvZApyZXR1cm4gbmV3IEguYXooYSxyLHM/bnVsbDpiLnJlY2VpdmVyKX0s
-ClJ1OmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG5ldyBILnRlKGEpCmlmKGEgaW5zdGFuY2Vv
-ZiBILmJxKXJldHVybiBILnRXKGEsYS5hKQppZih0eXBlb2YgYSE9PSJvYmplY3QiKXJldHVybiBhCmlm
-KCJkYXJ0RXhjZXB0aW9uIiBpbiBhKXJldHVybiBILnRXKGEsYS5kYXJ0RXhjZXB0aW9uKQpyZXR1cm4g
-SC50bChhKX0sCnRXOmZ1bmN0aW9uKGEsYil7aWYodC5yLmIoYikpaWYoYi4kdGhyb3duSnNFcnJvcj09
-bnVsbCliLiR0aHJvd25Kc0Vycm9yPWEKcmV0dXJuIGJ9LAp0bDpmdW5jdGlvbihhKXt2YXIgcyxyLHEs
-cCxvLG4sbSxsLGssaixpLGgsZyxmLGU9bnVsbAppZighKCJtZXNzYWdlIiBpbiBhKSlyZXR1cm4gYQpz
-PWEubWVzc2FnZQppZigibnVtYmVyIiBpbiBhJiZ0eXBlb2YgYS5udW1iZXI9PSJudW1iZXIiKXtyPWEu
-bnVtYmVyCnE9ciY2NTUzNQppZigoQy5qbi53RyhyLDE2KSY4MTkxKT09PTEwKXN3aXRjaChxKXtjYXNl
-IDQzODpyZXR1cm4gSC50VyhhLEguVDMoSC5FaihzKSsiIChFcnJvciAiK3ErIikiLGUpKQpjYXNlIDQ0
-NTpjYXNlIDUwMDc6cmV0dXJuIEgudFcoYSxILklqKEguRWoocykrIiAoRXJyb3IgIitxKyIpIixlKSl9
-fWlmKGEgaW5zdGFuY2VvZiBUeXBlRXJyb3Ipe3A9JC5TbigpCm89JC5scSgpCm49JC5OOSgpCm09JC5p
-SSgpCmw9JC5VTigpCms9JC5aaCgpCmo9JC5yTigpCiQuYzMoKQppPSQuSEsoKQpoPSQucjEoKQpnPXAu
-cVMocykKaWYoZyE9bnVsbClyZXR1cm4gSC50VyhhLEguVDMoSC5oKHMpLGcpKQplbHNle2c9by5xUyhz
-KQppZihnIT1udWxsKXtnLm1ldGhvZD0iY2FsbCIKcmV0dXJuIEgudFcoYSxILlQzKEguaChzKSxnKSl9
-ZWxzZXtnPW4ucVMocykKaWYoZz09bnVsbCl7Zz1tLnFTKHMpCmlmKGc9PW51bGwpe2c9bC5xUyhzKQpp
-ZihnPT1udWxsKXtnPWsucVMocykKaWYoZz09bnVsbCl7Zz1qLnFTKHMpCmlmKGc9PW51bGwpe2c9bS5x
-UyhzKQppZihnPT1udWxsKXtnPWkucVMocykKaWYoZz09bnVsbCl7Zz1oLnFTKHMpCmY9ZyE9bnVsbH1l
-bHNlIGY9ITB9ZWxzZSBmPSEwfWVsc2UgZj0hMH1lbHNlIGY9ITB9ZWxzZSBmPSEwfWVsc2UgZj0hMH1l
-bHNlIGY9ITAKaWYoZilyZXR1cm4gSC50VyhhLEguSWooSC5oKHMpLGcpKX19cmV0dXJuIEgudFcoYSxu
-ZXcgSC52Vih0eXBlb2Ygcz09InN0cmluZyI/czoiIikpfWlmKGEgaW5zdGFuY2VvZiBSYW5nZUVycm9y
-KXtpZih0eXBlb2Ygcz09InN0cmluZyImJnMuaW5kZXhPZigiY2FsbCBzdGFjayIpIT09LTEpcmV0dXJu
-IG5ldyBQLktZKCkKcz1mdW5jdGlvbihiKXt0cnl7cmV0dXJuIFN0cmluZyhiKX1jYXRjaChkKXt9cmV0
-dXJuIG51bGx9KGEpCnJldHVybiBILnRXKGEsbmV3IFAudSghMSxlLGUsdHlwZW9mIHM9PSJzdHJpbmci
-P3MucmVwbGFjZSgvXlJhbmdlRXJyb3I6XHMqLywiIik6cykpfWlmKHR5cGVvZiBJbnRlcm5hbEVycm9y
-PT0iZnVuY3Rpb24iJiZhIGluc3RhbmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBlb2Ygcz09InN0cmlu
-ZyImJnM9PT0idG9vIG11Y2ggcmVjdXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4gYX0sCnRz
-OmZ1bmN0aW9uKGEpe3ZhciBzCmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYoYT09bnVs
-bClyZXR1cm4gbmV3IEguWE8oYSkKcz1hLiRjYWNoZWRUcmFjZQppZihzIT1udWxsKXJldHVybiBzCnJl
-dHVybiBhLiRjYWNoZWRUcmFjZT1uZXcgSC5YTyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHMscixx
-LHA9YS5sZW5ndGgKZm9yKHM9MDtzPHA7cz1xKXtyPXMrMQpxPXIrMQpiLlk1KDAsYVtzXSxhW3JdKX1y
-ZXR1cm4gYn0sCmZ0OmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt0LlkuYShhKQpzd2l0Y2goSC51UChiKSl7
-Y2FzZSAwOnJldHVybiBhLiQwKCkKY2FzZSAxOnJldHVybiBhLiQxKGMpCmNhc2UgMjpyZXR1cm4gYS4k
-MihjLGQpCmNhc2UgMzpyZXR1cm4gYS4kMyhjLGQsZSkKY2FzZSA0OnJldHVybiBhLiQ0KGMsZCxlLGYp
-fXRocm93IEguYihuZXcgUC5DRCgiVW5zdXBwb3J0ZWQgbnVtYmVyIG9mIGFyZ3VtZW50cyBmb3Igd3Jh
-cHBlZCBjbG9zdXJlIikpfSwKdFI6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihhPT1udWxsKXJldHVybiBu
-dWxsCnM9YS4kaWRlbnRpdHkKaWYoISFzKXJldHVybiBzCnM9ZnVuY3Rpb24oYyxkLGUpe3JldHVybiBm
-dW5jdGlvbihmLGcsaCxpKXtyZXR1cm4gZShjLGQsZixnLGgsaSl9fShhLGIsSC5mdCkKYS4kaWRlbnRp
-dHk9cwpyZXR1cm4gc30sCmlBOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciBzLHIscSxwLG8sbixt
-LGw9YlswXSxrPWwuJGNhbGxOYW1lLGo9ZT9PYmplY3QuY3JlYXRlKG5ldyBILnp4KCkuY29uc3RydWN0
-b3IucHJvdG90eXBlKTpPYmplY3QuY3JlYXRlKG5ldyBILnJUKG51bGwsbnVsbCxudWxsLCIiKS5jb25z
-dHJ1Y3Rvci5wcm90b3R5cGUpCmouJGluaXRpYWxpemU9ai5jb25zdHJ1Y3RvcgppZihlKXM9ZnVuY3Rp
-b24gc3RhdGljX3RlYXJfb2ZmKCl7dGhpcy4kaW5pdGlhbGl6ZSgpfQplbHNle3I9JC55agppZih0eXBl
-b2YgciE9PSJudW1iZXIiKXJldHVybiByLmgoKQokLnlqPXIrMQpyPW5ldyBGdW5jdGlvbigiYSxiLGMs
-ZCIrciwidGhpcy4kaW5pdGlhbGl6ZShhLGIsYyxkIityKyIpIikKcz1yfWouY29uc3RydWN0b3I9cwpz
-LnByb3RvdHlwZT1qCmlmKCFlKXtxPUguYngoYSxsLGYpCnEuJHJlZmxlY3Rpb25JbmZvPWR9ZWxzZXtq
-LiRzdGF0aWNfbmFtZT1nCnE9bH1qLiRTPUguaW0oZCxlLGYpCmpba109cQpmb3IocD1xLG89MTtvPGIu
-bGVuZ3RoOysrbyl7bj1iW29dCm09bi4kY2FsbE5hbWUKaWYobSE9bnVsbCl7bj1lP246SC5ieChhLG4s
-ZikKalttXT1ufWlmKG89PT1jKXtuLiRyZWZsZWN0aW9uSW5mbz1kCnA9bn19ai4kQz1wCmouJFI9bC4k
-UgpqLiREPWwuJEQKcmV0dXJuIHN9LAppbTpmdW5jdGlvbihhLGIsYyl7dmFyIHMKaWYodHlwZW9mIGE9
-PSJudW1iZXIiKXJldHVybiBmdW5jdGlvbihkLGUpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiBkKGUp
-fX0oSC5CcCxhKQppZih0eXBlb2YgYT09InN0cmluZyIpe2lmKGIpdGhyb3cgSC5iKCJDYW5ub3QgY29t
-cHV0ZSBzaWduYXR1cmUgZm9yIHN0YXRpYyB0ZWFyb2ZmLiIpCnM9Yz9ILlBXOkguVG4KcmV0dXJuIGZ1
-bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGUodGhpcyxkKX19KGEscyl9dGhyb3cg
-SC5iKCJFcnJvciBpbiBmdW5jdGlvblR5cGUgb2YgdGVhcm9mZiIpfSwKdnE6ZnVuY3Rpb24oYSxiLGMs
-ZCl7dmFyIHM9SC5EVgpzd2l0Y2goYj8tMTphKXtjYXNlIDA6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0
-dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYodGhpcylbZV0oKX19KGMscykKY2FzZSAxOnJldHVybiBmdW5j
-dGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnKXtyZXR1cm4gZih0aGlzKVtlXShnKX19KGMscykKY2Fz
-ZSAyOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgpe3JldHVybiBmKHRoaXMp
-W2VdKGcsaCl9fShjLHMpCmNhc2UgMzpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24o
-ZyxoLGkpe3JldHVybiBmKHRoaXMpW2VdKGcsaCxpKX19KGMscykKY2FzZSA0OnJldHVybiBmdW5jdGlv
-bihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSxqKXtyZXR1cm4gZih0aGlzKVtlXShnLGgsaSxqKX19
-KGMscykKY2FzZSA1OnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSxqLGsp
-e3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGosayl9fShjLHMpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9u
-KGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGUuYXBwbHkoZih0aGlzKSxhcmd1bWVudHMpfX0o
-ZCxzKX19LApieDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAsbyxuLG0KaWYoYylyZXR1cm4gSC5I
-ZihhLGIpCnM9Yi4kc3R1Yk5hbWUKcj1iLmxlbmd0aApxPWFbc10KcD1iPT1udWxsP3E9PW51bGw6Yj09
-PXEKbz0hcHx8cj49MjcKaWYobylyZXR1cm4gSC52cShyLCFwLHMsYikKaWYocj09PTApe3A9JC55agpp
-Zih0eXBlb2YgcCE9PSJudW1iZXIiKXJldHVybiBwLmgoKQokLnlqPXArMQpuPSJzZWxmIitwCnJldHVy
-biBuZXcgRnVuY3Rpb24oInJldHVybiBmdW5jdGlvbigpe3ZhciAiK24rIiA9IHRoaXMuIitILkVqKEgu
-b04oKSkrIjtyZXR1cm4gIituKyIuIitILkVqKHMpKyIoKTt9IikoKX1tPSJhYmNkZWZnaGlqa2xtbm9w
-cXJzdHV2d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHIpLmpvaW4oIiwiKQpwPSQueWoKaWYodHlwZW9m
-IHAhPT0ibnVtYmVyIilyZXR1cm4gcC5oKCkKJC55aj1wKzEKbSs9cApyZXR1cm4gbmV3IEZ1bmN0aW9u
-KCJyZXR1cm4gZnVuY3Rpb24oIittKyIpe3JldHVybiB0aGlzLiIrSC5FaihILm9OKCkpKyIuIitILkVq
-KHMpKyIoIittKyIpO30iKSgpfSwKWjQ6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHM9SC5EVixyPUgueVMK
-c3dpdGNoKGI/LTE6YSl7Y2FzZSAwOnRocm93IEguYihuZXcgSC5FcSgiSW50ZXJjZXB0ZWQgZnVuY3Rp
-b24gd2l0aCBubyBhcmd1bWVudHMuIikpCmNhc2UgMTpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVy
-biBmdW5jdGlvbigpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcykpfX0oYyxzLHIpCmNhc2UgMjpyZXR1
-cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoKXtyZXR1cm4gZih0aGlzKVtlXShnKHRo
-aXMpLGgpfX0oYyxzLHIpCmNhc2UgMzpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlv
-bihoLGkpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxpKX19KGMscyxyKQpjYXNlIDQ6cmV0dXJu
-IGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGco
-dGhpcyksaCxpLGopfX0oYyxzLHIpCmNhc2UgNTpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBm
-dW5jdGlvbihoLGksaixrKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSxqLGspfX0oYyxzLHIp
-CmNhc2UgNjpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoLGksaixrLGwpe3Jl
-dHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxpLGosayxsKX19KGMscyxyKQpkZWZhdWx0OnJldHVybiBm
-dW5jdGlvbihlLGYsZyxoKXtyZXR1cm4gZnVuY3Rpb24oKXtoPVtnKHRoaXMpXQpBcnJheS5wcm90b3R5
-cGUucHVzaC5hcHBseShoLGFyZ3VtZW50cykKcmV0dXJuIGUuYXBwbHkoZih0aGlzKSxoKX19KGQscyxy
-KX19LApIZjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtPUgub04oKSxsPSQuUDQKaWYobD09
-bnVsbClsPSQuUDQ9SC5FMigicmVjZWl2ZXIiKQpzPWIuJHN0dWJOYW1lCnI9Yi5sZW5ndGgKcT1hW3Nd
-CnA9Yj09bnVsbD9xPT1udWxsOmI9PT1xCm89IXB8fHI+PTI4CmlmKG8pcmV0dXJuIEguWjQociwhcCxz
-LGIpCmlmKHI9PT0xKXtwPSJyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4iK0guRWoobSkrIi4i
-K0guRWoocykrIih0aGlzLiIrbCsiKTsiCm89JC55agppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVy
-biBvLmgoKQokLnlqPW8rMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKHArbysifSIpKCl9bj0iYWJjZGVmZ2hp
-amtsbW5vcHFyc3R1dnd4eXoiLnNwbGl0KCIiKS5zcGxpY2UoMCxyLTEpLmpvaW4oIiwiKQpwPSJyZXR1
-cm4gZnVuY3Rpb24oIituKyIpe3JldHVybiB0aGlzLiIrSC5FaihtKSsiLiIrSC5FaihzKSsiKHRoaXMu
-IitsKyIsICIrbisiKTsiCm89JC55agppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVybiBvLmgoKQok
-LnlqPW8rMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKHArbysifSIpKCl9LApLcTpmdW5jdGlvbihhLGIsYyxk
-LGUsZixnKXtyZXR1cm4gSC5pQShhLGIsYyxkLCEhZSwhIWYsZyl9LApUbjpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgueihhLmEpLGIpfSwKUFc6ZnVuY3Rpb24oYSxiKXtyZXR1
-cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSxILnooYS5jKSxiKX0sCkRWOmZ1bmN0aW9uKGEpe3JldHVybiBh
-LmF9LAp5UzpmdW5jdGlvbihhKXtyZXR1cm4gYS5jfSwKb046ZnVuY3Rpb24oKXt2YXIgcz0kLm1KCnJl
-dHVybiBzPT1udWxsPyQubUo9SC5FMigic2VsZiIpOnN9LApFMjpmdW5jdGlvbihhKXt2YXIgcyxyLHEs
-cD1uZXcgSC5yVCgic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIpLG89Si5FcChPYmplY3Qu
-Z2V0T3duUHJvcGVydHlOYW1lcyhwKSx0LlcpCmZvcihzPW8ubGVuZ3RoLHI9MDtyPHM7KytyKXtxPW9b
-cl0KaWYocFtxXT09PWEpcmV0dXJuIHF9dGhyb3cgSC5iKFAueFkoIkZpZWxkIG5hbWUgIithKyIgbm90
-IGZvdW5kLiIpKX0sCm9UOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpSC5mTygiYm9vbGVhbiBleHByZXNz
-aW9uIG11c3Qgbm90IGJlIG51bGwiKQpyZXR1cm4gYX0sCmZPOmZ1bmN0aW9uKGEpe3Rocm93IEguYihu
-ZXcgSC5rWShhKSl9LAphZzpmdW5jdGlvbihhKXt0aHJvdyBILmIobmV3IFAuYyhhKSl9LApZZzpmdW5j
-dGlvbihhKXtyZXR1cm4gdi5nZXRJc29sYXRlVGFnKGEpfSwKQm86ZnVuY3Rpb24oYSl7cmV0dXJuIEgu
-dihuZXcgSC5uKGEpKX0sCml3OmZ1bmN0aW9uKGEsYixjKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxi
-LHt2YWx1ZTpjLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0p
-fSwKdzM6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuPUguaCgkLk5GLiQxKGEpKSxtPSQubndbbl0K
-aWYobSE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7
-dmFsdWU6bSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpy
-ZXR1cm4gbS5pfXM9JC52dltuXQppZihzIT1udWxsKXJldHVybiBzCnI9di5pbnRlcmNlcHRvcnNCeVRh
-Z1tuXQppZihyPT1udWxsKXtxPUguaygkLlRYLiQyKGEsbikpCmlmKHEhPW51bGwpe209JC5ud1txXQpp
-ZihtIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2
-YWx1ZTptLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJl
-dHVybiBtLml9cz0kLnZ2W3FdCmlmKHMhPW51bGwpcmV0dXJuIHMKcj12LmludGVyY2VwdG9yc0J5VGFn
-W3FdCm49cX19aWYocj09bnVsbClyZXR1cm4gbnVsbApzPXIucHJvdG90eXBlCnA9blswXQppZihwPT09
-IiEiKXttPUguVmEocykKJC5ud1tuXT1tCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQ
-cm9wZXJ0eU5hbWUse3ZhbHVlOm0sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3Vy
-YWJsZTp0cnVlfSkKcmV0dXJuIG0uaX1pZihwPT09In4iKXskLnZ2W25dPXMKcmV0dXJuIHN9aWYocD09
-PSItIil7bz1ILlZhKHMpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYmplY3QuZ2V0UHJvdG90eXBlT2Yo
+cV19fWZ1bmN0aW9uIG1peGluUHJvcGVydGllcyhhLGIpe3ZhciBzPU9iamVjdC5rZXlzKGEpCmZvcih2
+YXIgcj0wO3I8cy5sZW5ndGg7cisrKXt2YXIgcT1zW3JdCmlmKCFiLmhhc093blByb3BlcnR5KHEpKWJb
+cV09YVtxXX19dmFyIHo9ZnVuY3Rpb24oKXt2YXIgcz1mdW5jdGlvbigpe30Kcy5wcm90b3R5cGU9e3A6
+e319CnZhciByPW5ldyBzKCkKaWYoIShyLl9fcHJvdG9fXyYmci5fX3Byb3RvX18ucD09PXMucHJvdG90
+eXBlLnApKXJldHVybiBmYWxzZQp0cnl7aWYodHlwZW9mIG5hdmlnYXRvciE9InVuZGVmaW5lZCImJnR5
+cGVvZiBuYXZpZ2F0b3IudXNlckFnZW50PT0ic3RyaW5nIiYmbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRl
+eE9mKCJDaHJvbWUvIik+PTApcmV0dXJuIHRydWUKaWYodHlwZW9mIHZlcnNpb249PSJmdW5jdGlvbiIm
+JnZlcnNpb24ubGVuZ3RoPT0wKXt2YXIgcT12ZXJzaW9uKCkKaWYoL15cZCtcLlxkK1wuXGQrXC5cZCsk
+Ly50ZXN0KHEpKXJldHVybiB0cnVlfX1jYXRjaChwKXt9cmV0dXJuIGZhbHNlfSgpCmZ1bmN0aW9uIHNl
+dEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2FyeShhKXtmdW5jdGlvbiB0KCl7fTtpZih0eXBlb2YgdC5uYW1l
+PT0ic3RyaW5nIilyZXR1cm4KZm9yKHZhciBzPTA7czxhLmxlbmd0aDtzKyspe3ZhciByPWFbc10KdmFy
+IHE9T2JqZWN0LmtleXMocikKZm9yKHZhciBwPTA7cDxxLmxlbmd0aDtwKyspe3ZhciBvPXFbcF0KdmFy
+IG49cltvXQppZih0eXBlb2Ygbj09ImZ1bmN0aW9uIiluLm5hbWU9b319fWZ1bmN0aW9uIGluaGVyaXQo
+YSxiKXthLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1hCmEucHJvdG90eXBlWyIkaSIrYS5uYW1lXT1hCmlm
+KGIhPW51bGwpe2lmKHope2EucHJvdG90eXBlLl9fcHJvdG9fXz1iLnByb3RvdHlwZQpyZXR1cm59dmFy
+IHM9T2JqZWN0LmNyZWF0ZShiLnByb3RvdHlwZSkKY29weVByb3BlcnRpZXMoYS5wcm90b3R5cGUscykK
+YS5wcm90b3R5cGU9c319ZnVuY3Rpb24gaW5oZXJpdE1hbnkoYSxiKXtmb3IodmFyIHM9MDtzPGIubGVu
+Z3RoO3MrKylpbmhlcml0KGJbc10sYSl9ZnVuY3Rpb24gbWl4aW4oYSxiKXttaXhpblByb3BlcnRpZXMo
+Yi5wcm90b3R5cGUsYS5wcm90b3R5cGUpCmEucHJvdG90eXBlLmNvbnN0cnVjdG9yPWF9ZnVuY3Rpb24g
+bGF6eU9sZChhLGIsYyxkKXt2YXIgcz1hCmFbYl09cwphW2NdPWZ1bmN0aW9uKCl7YVtjXT1mdW5jdGlv
+bigpe0guYWcoYil9CnZhciByCnZhciBxPWQKdHJ5e2lmKGFbYl09PT1zKXtyPWFbYl09cQpyPWFbYl09
+ZCgpfWVsc2Ugcj1hW2JdfWZpbmFsbHl7aWYocj09PXEpYVtiXT1udWxsCmFbY109ZnVuY3Rpb24oKXty
+ZXR1cm4gdGhpc1tiXX19cmV0dXJuIHJ9fWZ1bmN0aW9uIGxhenkoYSxiLGMsZCl7dmFyIHM9YQphW2Jd
+PXMKYVtjXT1mdW5jdGlvbigpe2lmKGFbYl09PT1zKWFbYl09ZCgpCmFbY109ZnVuY3Rpb24oKXtyZXR1
+cm4gdGhpc1tiXX0KcmV0dXJuIGFbYl19fWZ1bmN0aW9uIGxhenlGaW5hbChhLGIsYyxkKXt2YXIgcz1h
+CmFbYl09cwphW2NdPWZ1bmN0aW9uKCl7aWYoYVtiXT09PXMpe3ZhciByPWQoKQppZihhW2JdIT09cylI
+LkJvKGIpCmFbYl09cn1hW2NdPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXNbYl19CnJldHVybiBhW2JdfX1m
+dW5jdGlvbiBtYWtlQ29uc3RMaXN0KGEpe2EuaW1tdXRhYmxlJGxpc3Q9QXJyYXkKYS5maXhlZCRsZW5n
+dGg9QXJyYXkKcmV0dXJuIGF9ZnVuY3Rpb24gY29udmVydFRvRmFzdE9iamVjdChhKXtmdW5jdGlvbiB0
+KCl7fXQucHJvdG90eXBlPWEKbmV3IHQoKQpyZXR1cm4gYX1mdW5jdGlvbiBjb252ZXJ0QWxsVG9GYXN0
+T2JqZWN0KGEpe2Zvcih2YXIgcz0wO3M8YS5sZW5ndGg7KytzKWNvbnZlcnRUb0Zhc3RPYmplY3QoYVtz
+XSl9dmFyIHk9MApmdW5jdGlvbiB0ZWFyT2ZmR2V0dGVyKGEsYixjLGQsZSl7cmV0dXJuIGU/bmV3IEZ1
+bmN0aW9uKCJmdW5jcyIsImFwcGx5VHJhbXBvbGluZUluZGV4IiwicmVmbGVjdGlvbkluZm8iLCJuYW1l
+IiwiSCIsImMiLCJyZXR1cm4gZnVuY3Rpb24gdGVhck9mZl8iK2QreSsrKyIocmVjZWl2ZXIpIHsiKyJp
+ZiAoYyA9PT0gbnVsbCkgYyA9ICIrIkguS3EiKyIoIisidGhpcywgZnVuY3MsIGFwcGx5VHJhbXBvbGlu
+ZUluZGV4LCByZWZsZWN0aW9uSW5mbywgZmFsc2UsIHRydWUsIG5hbWUpOyIrInJldHVybiBuZXcgYyh0
+aGlzLCBmdW5jc1swXSwgcmVjZWl2ZXIsIG5hbWUpOyIrIn0iKShhLGIsYyxkLEgsbnVsbCk6bmV3IEZ1
+bmN0aW9uKCJmdW5jcyIsImFwcGx5VHJhbXBvbGluZUluZGV4IiwicmVmbGVjdGlvbkluZm8iLCJuYW1l
+IiwiSCIsImMiLCJyZXR1cm4gZnVuY3Rpb24gdGVhck9mZl8iK2QreSsrKyIoKSB7IisiaWYgKGMgPT09
+IG51bGwpIGMgPSAiKyJILktxIisiKCIrInRoaXMsIGZ1bmNzLCBhcHBseVRyYW1wb2xpbmVJbmRleCwg
+cmVmbGVjdGlvbkluZm8sIGZhbHNlLCBmYWxzZSwgbmFtZSk7IisicmV0dXJuIG5ldyBjKHRoaXMsIGZ1
+bmNzWzBdLCBudWxsLCBuYW1lKTsiKyJ9IikoYSxiLGMsZCxILG51bGwpfWZ1bmN0aW9uIHRlYXJPZmYo
+YSxiLGMsZCxlLGYpe3ZhciBzPW51bGwKcmV0dXJuIGQ/ZnVuY3Rpb24oKXtpZihzPT09bnVsbClzPUgu
+S3EodGhpcyxhLGIsYyx0cnVlLGZhbHNlLGUpLnByb3RvdHlwZQpyZXR1cm4gc306dGVhck9mZkdldHRl
+cihhLGIsYyxlLGYpfXZhciB4PTAKZnVuY3Rpb24gaW5zdGFsbFRlYXJPZmYoYSxiLGMsZCxlLGYsZyxo
+LGksail7dmFyIHM9W10KZm9yKHZhciByPTA7cjxoLmxlbmd0aDtyKyspe3ZhciBxPWhbcl0KaWYodHlw
+ZW9mIHE9PSJzdHJpbmciKXE9YVtxXQpxLiRjYWxsTmFtZT1nW3JdCnMucHVzaChxKX12YXIgcT1zWzBd
+CnEuJFI9ZQpxLiREPWYKdmFyIHA9aQppZih0eXBlb2YgcD09Im51bWJlciIpcCs9eAp2YXIgbz1oWzBd
+CnEuJHN0dWJOYW1lPW8KdmFyIG49dGVhck9mZihzLGp8fDAscCxjLG8sZCkKYVtiXT1uCmlmKGMpcS4k
+dGVhck9mZj1ufWZ1bmN0aW9uIGluc3RhbGxTdGF0aWNUZWFyT2ZmKGEsYixjLGQsZSxmLGcsaCl7cmV0
+dXJuIGluc3RhbGxUZWFyT2ZmKGEsYix0cnVlLGZhbHNlLGMsZCxlLGYsZyxoKX1mdW5jdGlvbiBpbnN0
+YWxsSW5zdGFuY2VUZWFyT2ZmKGEsYixjLGQsZSxmLGcsaCxpKXtyZXR1cm4gaW5zdGFsbFRlYXJPZmYo
+YSxiLGZhbHNlLGMsZCxlLGYsZyxoLGkpfWZ1bmN0aW9uIHNldE9yVXBkYXRlSW50ZXJjZXB0b3JzQnlU
+YWcoYSl7dmFyIHM9di5pbnRlcmNlcHRvcnNCeVRhZwppZighcyl7di5pbnRlcmNlcHRvcnNCeVRhZz1h
+CnJldHVybn1jb3B5UHJvcGVydGllcyhhLHMpfWZ1bmN0aW9uIHNldE9yVXBkYXRlTGVhZlRhZ3MoYSl7
+dmFyIHM9di5sZWFmVGFncwppZighcyl7di5sZWFmVGFncz1hCnJldHVybn1jb3B5UHJvcGVydGllcyhh
+LHMpfWZ1bmN0aW9uIHVwZGF0ZVR5cGVzKGEpe3ZhciBzPXYudHlwZXMKdmFyIHI9cy5sZW5ndGgKcy5w
+dXNoLmFwcGx5KHMsYSkKcmV0dXJuIHJ9ZnVuY3Rpb24gdXBkYXRlSG9sZGVyKGEsYil7Y29weVByb3Bl
+cnRpZXMoYixhKQpyZXR1cm4gYX12YXIgaHVua0hlbHBlcnM9ZnVuY3Rpb24oKXt2YXIgcz1mdW5jdGlv
+bihhLGIsYyxkLGUpe3JldHVybiBmdW5jdGlvbihmLGcsaCxpKXtyZXR1cm4gaW5zdGFsbEluc3RhbmNl
+VGVhck9mZihmLGcsYSxiLGMsZCxbaF0saSxlKX19LHI9ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGZ1
+bmN0aW9uKGUsZixnLGgpe3JldHVybiBpbnN0YWxsU3RhdGljVGVhck9mZihlLGYsYSxiLGMsW2ddLGgs
+ZCl9fQpyZXR1cm57aW5oZXJpdDppbmhlcml0LGluaGVyaXRNYW55OmluaGVyaXRNYW55LG1peGluOm1p
+eGluLGluc3RhbGxTdGF0aWNUZWFyT2ZmOmluc3RhbGxTdGF0aWNUZWFyT2ZmLGluc3RhbGxJbnN0YW5j
+ZVRlYXJPZmY6aW5zdGFsbEluc3RhbmNlVGVhck9mZixfaW5zdGFuY2VfMHU6cygwLDAsbnVsbCxbIiQw
+Il0sMCksX2luc3RhbmNlXzF1OnMoMCwxLG51bGwsWyIkMSJdLDApLF9pbnN0YW5jZV8ydTpzKDAsMixu
+dWxsLFsiJDIiXSwwKSxfaW5zdGFuY2VfMGk6cygxLDAsbnVsbCxbIiQwIl0sMCksX2luc3RhbmNlXzFp
+OnMoMSwxLG51bGwsWyIkMSJdLDApLF9pbnN0YW5jZV8yaTpzKDEsMixudWxsLFsiJDIiXSwwKSxfc3Rh
+dGljXzA6cigwLG51bGwsWyIkMCJdLDApLF9zdGF0aWNfMTpyKDEsbnVsbCxbIiQxIl0sMCksX3N0YXRp
+Y18yOnIoMixudWxsLFsiJDIiXSwwKSxtYWtlQ29uc3RMaXN0Om1ha2VDb25zdExpc3QsbGF6eTpsYXp5
+LGxhenlGaW5hbDpsYXp5RmluYWwsbGF6eU9sZDpsYXp5T2xkLHVwZGF0ZUhvbGRlcjp1cGRhdGVIb2xk
+ZXIsY29udmVydFRvRmFzdE9iamVjdDpjb252ZXJ0VG9GYXN0T2JqZWN0LHNldEZ1bmN0aW9uTmFtZXNJ
+Zk5lY2Vzc2FyeTpzZXRGdW5jdGlvbk5hbWVzSWZOZWNlc3NhcnksdXBkYXRlVHlwZXM6dXBkYXRlVHlw
+ZXMsc2V0T3JVcGRhdGVJbnRlcmNlcHRvcnNCeVRhZzpzZXRPclVwZGF0ZUludGVyY2VwdG9yc0J5VGFn
+LHNldE9yVXBkYXRlTGVhZlRhZ3M6c2V0T3JVcGRhdGVMZWFmVGFnc319KCkKZnVuY3Rpb24gaW5pdGlh
+bGl6ZURlZmVycmVkSHVuayhhKXt4PXYudHlwZXMubGVuZ3RoCmEoaHVua0hlbHBlcnMsdix3LCQpfWZ1
+bmN0aW9uIGdldEdsb2JhbEZyb21OYW1lKGEpe2Zvcih2YXIgcz0wO3M8dy5sZW5ndGg7cysrKXtpZih3
+W3NdPT1DKWNvbnRpbnVlCmlmKHdbc11bYV0pcmV0dXJuIHdbc11bYV19fXZhciBDPXt9LEg9e0ZLOmZ1
+bmN0aW9uIEZLKCl7fSwKR0o6ZnVuY3Rpb24oYSxiLGMpe2lmKGIuQygiYlE8MD4iKS5iKGEpKXJldHVy
+biBuZXcgSC5vbChhLGIuQygiQDwwPiIpLktxKGMpLkMoIm9sPDEsMj4iKSkKcmV0dXJuIG5ldyBILlp5
+KGEsYi5DKCJAPDA+IikuS3EoYykuQygiWnk8MSwyPiIpKX0sCkdROmZ1bmN0aW9uKGEpe3JldHVybiBu
+ZXcgSC5uKCJGaWVsZCAnIithKyInIGhhcyBiZWVuIGFzc2lnbmVkIGR1cmluZyBpbml0aWFsaXphdGlv
+bi4iKX0sCkJpOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5yMyhhKX0sCm9vOmZ1bmN0aW9uKGEpe3Zh
+ciBzLHI9YV40OAppZihyPD05KXJldHVybiByCnM9YXwzMgppZig5Nzw9cyYmczw9MTAyKXJldHVybiBz
+LTg3CnJldHVybi0xfSwKY2I6ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpdGhyb3cgSC5iKG5ldyBI
+LkdNKGIsYy5DKCJHTTwwPiIpKSkKcmV0dXJuIGF9LApxQzpmdW5jdGlvbihhLGIsYyxkKXtQLmsxKGIs
+InN0YXJ0IikKaWYoYyE9bnVsbCl7UC5rMShjLCJlbmQiKQppZihiPmMpSC52KFAuVEUoYiwwLGMsInN0
+YXJ0IixudWxsKSl9cmV0dXJuIG5ldyBILm5IKGEsYixjLGQuQygibkg8MD4iKSl9LApLMTpmdW5jdGlv
+bihhLGIsYyxkKXtpZih0LmQuYihhKSlyZXR1cm4gbmV3IEgueHkoYSxiLGMuQygiQDwwPiIpLktxKGQp
+LkMoInh5PDEsMj4iKSkKcmV0dXJuIG5ldyBILmkxKGEsYixjLkMoIkA8MD4iKS5LcShkKS5DKCJpMTwx
+LDI+IikpfSwKYks6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPSJjb3VudCIKaWYodC5kLmIoYSkpe1AuTVIo
+YixzLHQuUykKUC5rMShiLHMpCnJldHVybiBuZXcgSC5kNShhLGIsYy5DKCJkNTwwPiIpKX1QLk1SKGIs
+cyx0LlMpClAuazEoYixzKQpyZXR1cm4gbmV3IEguQU0oYSxiLGMuQygiQU08MD4iKSl9LApXcDpmdW5j
+dGlvbigpe3JldHVybiBuZXcgUC5saigiTm8gZWxlbWVudCIpfSwKQW06ZnVuY3Rpb24oKXtyZXR1cm4g
+bmV3IFAubGooIlRvbyBtYW55IGVsZW1lbnRzIil9LAphcjpmdW5jdGlvbigpe3JldHVybiBuZXcgUC5s
+aigiVG9vIGZldyBlbGVtZW50cyIpfSwKQlI6ZnVuY3Rpb24gQlIoKXt9LApFNzpmdW5jdGlvbiBFNyhh
+LGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApaeTpmdW5jdGlvbiBaeShhLGIpe3RoaXMuYT1hCnRoaXMu
+JHRpPWJ9LApvbDpmdW5jdGlvbiBvbChhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApVcTpmdW5jdGlv
+biBVcSgpe30sCmpWOmZ1bmN0aW9uIGpWKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCm46ZnVuY3Rp
+b24gbihhKXt0aGlzLmE9YX0sCnIzOmZ1bmN0aW9uIHIzKGEpe3RoaXMuYT1hfSwKcWo6ZnVuY3Rpb24g
+cWooYSl7dGhpcy5hPWF9LApHTTpmdW5jdGlvbiBHTShhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApi
+UTpmdW5jdGlvbiBiUSgpe30sCmFMOmZ1bmN0aW9uIGFMKCl7fSwKbkg6ZnVuY3Rpb24gbkgoYSxiLGMs
+ZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKYTc6ZnVuY3Rpb24gYTcoYSxi
+LGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCmkxOmZ1bmN0
+aW9uIGkxKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKeHk6ZnVuY3Rpb24geHko
+YSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApNSDpmdW5jdGlvbiBNSChhLGIsYyl7
+dmFyIF89dGhpcwpfLmE9bnVsbApfLmI9YQpfLmM9YgpfLiR0aT1jfSwKbEo6ZnVuY3Rpb24gbEooYSxi
+LGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApVNTpmdW5jdGlvbiBVNShhLGIsYyl7dGhp
+cy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sClNPOmZ1bmN0aW9uIFNPKGEsYixjKXt0aGlzLmE9YQp0
+aGlzLmI9Ygp0aGlzLiR0aT1jfSwKQU06ZnVuY3Rpb24gQU0oYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1i
+CnRoaXMuJHRpPWN9LApkNTpmdW5jdGlvbiBkNShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4k
+dGk9Y30sClUxOmZ1bmN0aW9uIFUxKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwK
+TUI6ZnVuY3Rpb24gTUIoYSl7dGhpcy4kdGk9YX0sCkZ1OmZ1bmN0aW9uIEZ1KGEpe3RoaXMuJHRpPWF9
+LAp1NjpmdW5jdGlvbiB1NihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApKQjpmdW5jdGlvbiBKQihh
+LGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApTVTpmdW5jdGlvbiBTVSgpe30sClJlOmZ1bmN0aW9uIFJl
+KCl7fSwKdzI6ZnVuY3Rpb24gdzIoKXt9LAp3djpmdW5jdGlvbiB3dihhKXt0aGlzLmE9YX0sClFDOmZ1
+bmN0aW9uIFFDKCl7fSwKZGM6ZnVuY3Rpb24oKXt0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1
+bm1vZGlmaWFibGUgTWFwIikpfSwKTlE6ZnVuY3Rpb24oYSl7dmFyIHMscj1ILkpnKGEpCmlmKHIhPW51
+bGwpcmV0dXJuIHIKcz0ibWluaWZpZWQ6IithCnJldHVybiBzfSwKd1Y6ZnVuY3Rpb24oYSxiKXt2YXIg
+cwppZihiIT1udWxsKXtzPWIueAppZihzIT1udWxsKXJldHVybiBzfXJldHVybiB0LmFVLmIoYSl9LApF
+ajpmdW5jdGlvbihhKXt2YXIgcwppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYodHlwZW9m
+IGE9PSJudW1iZXIiKXtpZihhIT09MClyZXR1cm4iIithfWVsc2UgaWYoITA9PT1hKXJldHVybiJ0cnVl
+IgplbHNlIGlmKCExPT09YSlyZXR1cm4iZmFsc2UiCmVsc2UgaWYoYT09bnVsbClyZXR1cm4ibnVsbCIK
+cz1KLmooYSkKaWYodHlwZW9mIHMhPSJzdHJpbmciKXRocm93IEguYihILnRMKGEpKQpyZXR1cm4gc30s
+CmVROmZ1bmN0aW9uKGEpe3ZhciBzPWEuJGlkZW50aXR5SGFzaAppZihzPT1udWxsKXtzPU1hdGgucmFu
+ZG9tKCkqMHgzZmZmZmZmZnwwCmEuJGlkZW50aXR5SGFzaD1zfXJldHVybiBzfSwKSHA6ZnVuY3Rpb24o
+YSxiKXt2YXIgcyxyLHEscCxvLG4sbT1udWxsCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILnYoSC50TChh
+KSkKcz0vXlxzKlsrLV0/KCgweFthLWYwLTldKyl8KFxkKyl8KFthLXowLTldKykpXHMqJC9pLmV4ZWMo
+YSkKaWYocz09bnVsbClyZXR1cm4gbQppZigzPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLDMpCnI9c1sz
+XQppZihiPT1udWxsKXtpZihyIT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZihzWzJdIT1udWxs
+KXJldHVybiBwYXJzZUludChhLDE2KQpyZXR1cm4gbX1pZihiPDJ8fGI+MzYpdGhyb3cgSC5iKFAuVEUo
+YiwyLDM2LCJyYWRpeCIsbSkpCmlmKGI9PT0xMCYmciE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkK
+aWYoYjwxMHx8cj09bnVsbCl7cT1iPD0xMD80NytiOjg2K2IKcD1zWzFdCmZvcihvPXAubGVuZ3RoLG49
+MDtuPG87KytuKWlmKChDLnhCLlcocCxuKXwzMik+cSlyZXR1cm4gbX1yZXR1cm4gcGFyc2VJbnQoYSxi
+KX0sCk06ZnVuY3Rpb24oYSl7cmV0dXJuIEguSDUoYSl9LApINTpmdW5jdGlvbihhKXt2YXIgcyxyLHEK
+aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIEguZG0oSC56KGEpLG51bGwpCmlmKEouaWEoYSk9PT1D
+Lk9rfHx0LmJKLmIoYSkpe3M9Qy5PNChhKQppZihILkJlKHMpKXJldHVybiBzCnI9YS5jb25zdHJ1Y3Rv
+cgppZih0eXBlb2Ygcj09ImZ1bmN0aW9uIil7cT1yLm5hbWUKaWYodHlwZW9mIHE9PSJzdHJpbmciJiZI
+LkJlKHEpKXJldHVybiBxfX1yZXR1cm4gSC5kbShILnooYSksbnVsbCl9LApCZTpmdW5jdGlvbihhKXt2
+YXIgcz1hIT09Ik9iamVjdCImJmEhPT0iIgpyZXR1cm4gc30sCk0wOmZ1bmN0aW9uKCl7aWYoISFzZWxm
+LmxvY2F0aW9uKXJldHVybiBzZWxmLmxvY2F0aW9uLmhyZWYKcmV0dXJuIG51bGx9LApWSzpmdW5jdGlv
+bihhKXt2YXIgcyxyLHEscCxvPWEubGVuZ3RoCmlmKG88PTUwMClyZXR1cm4gU3RyaW5nLmZyb21DaGFy
+Q29kZS5hcHBseShudWxsLGEpCmZvcihzPSIiLHI9MDtyPG87cj1xKXtxPXIrNTAwCnA9cTxvP3E6bwpz
+Kz1TdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYS5zbGljZShyLHApKX1yZXR1cm4gc30sCkNx
+OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPUguVk0oW10sdC5hKQpmb3Iocz1hLmxlbmd0aCxyPTA7cjxh
+Lmxlbmd0aDthLmxlbmd0aD09PXN8fCgwLEgubGspKGEpLCsrcil7cT1hW3JdCmlmKCFILm9rKHEpKXRo
+cm93IEguYihILnRMKHEpKQppZihxPD02NTUzNSlDLk5tLmkocCxxKQplbHNlIGlmKHE8PTExMTQxMTEp
+e0MuTm0uaShwLDU1Mjk2KyhDLmpuLndHKHEtNjU1MzYsMTApJjEwMjMpKQpDLk5tLmkocCw1NjMyMCso
+cSYxMDIzKSl9ZWxzZSB0aHJvdyBILmIoSC50TChxKSl9cmV0dXJuIEguVksocCl9LAplVDpmdW5jdGlv
+bihhKXt2YXIgcyxyLHEKZm9yKHM9YS5sZW5ndGgscj0wO3I8czsrK3Ipe3E9YVtyXQppZighSC5vayhx
+KSl0aHJvdyBILmIoSC50TChxKSkKaWYocTwwKXRocm93IEguYihILnRMKHEpKQppZihxPjY1NTM1KXJl
+dHVybiBILkNxKGEpfXJldHVybiBILlZLKGEpfSwKZnc6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxw
+CmlmKGM8PTUwMCYmYj09PTAmJmM9PT1hLmxlbmd0aClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5h
+cHBseShudWxsLGEpCmZvcihzPWIscj0iIjtzPGM7cz1xKXtxPXMrNTAwCnA9cTxjP3E6YwpyKz1TdHJp
+bmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYS5zdWJhcnJheShzLHApKX1yZXR1cm4gcn0sCkx3OmZ1
+bmN0aW9uKGEpe3ZhciBzCmlmKDA8PWEpe2lmKGE8PTY1NTM1KXJldHVybiBTdHJpbmcuZnJvbUNoYXJD
+b2RlKGEpCmlmKGE8PTExMTQxMTEpe3M9YS02NTUzNgpyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgo
+Qy5qbi53RyhzLDEwKXw1NTI5Nik+Pj4wLHMmMTAyM3w1NjMyMCl9fXRocm93IEguYihQLlRFKGEsMCwx
+MTE0MTExLG51bGwsbnVsbCkpfSwKbzI6ZnVuY3Rpb24oYSl7aWYoYS5kYXRlPT09dm9pZCAwKWEuZGF0
+ZT1uZXcgRGF0ZShhLmEpCnJldHVybiBhLmRhdGV9LAp0SjpmdW5jdGlvbihhKXt2YXIgcz1ILm8yKGEp
+LmdldEZ1bGxZZWFyKCkrMApyZXR1cm4gc30sCk5TOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0
+TW9udGgoKSsxCnJldHVybiBzfSwKakE6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vMihhKS5nZXREYXRlKCkr
+MApyZXR1cm4gc30sCklYOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0SG91cnMoKSswCnJldHVy
+biBzfSwKY2g6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vMihhKS5nZXRNaW51dGVzKCkrMApyZXR1cm4gc30s
+CkpkOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0U2Vjb25kcygpKzAKcmV0dXJuIHN9LApvMTpm
+dW5jdGlvbihhKXt2YXIgcz1ILm8yKGEpLmdldE1pbGxpc2Vjb25kcygpKzAKcmV0dXJuIHN9LAp6bzpm
+dW5jdGlvbihhLGIsYyl7dmFyIHMscixxPXt9CnEuYT0wCnM9W10Kcj1bXQpxLmE9Yi5sZW5ndGgKQy5O
+bS5GVihzLGIpCnEuYj0iIgppZihjIT1udWxsJiZjLmEhPT0wKWMuSygwLG5ldyBILkNqKHEscixzKSkK
+IiIrcS5hCnJldHVybiBKLkp5KGEsbmV3IEguTEkoQy5UZSwwLHMsciwwKSl9LApFazpmdW5jdGlvbihh
+LGIsYyl7dmFyIHMscixxLHAKaWYoYiBpbnN0YW5jZW9mIEFycmF5KXM9Yz09bnVsbHx8Yy5hPT09MApl
+bHNlIHM9ITEKaWYocyl7cj1iCnE9ci5sZW5ndGgKaWYocT09PTApe2lmKCEhYS4kMClyZXR1cm4gYS4k
+MCgpfWVsc2UgaWYocT09PTEpe2lmKCEhYS4kMSlyZXR1cm4gYS4kMShyWzBdKX1lbHNlIGlmKHE9PT0y
+KXtpZighIWEuJDIpcmV0dXJuIGEuJDIoclswXSxyWzFdKX1lbHNlIGlmKHE9PT0zKXtpZighIWEuJDMp
+cmV0dXJuIGEuJDMoclswXSxyWzFdLHJbMl0pfWVsc2UgaWYocT09PTQpe2lmKCEhYS4kNClyZXR1cm4g
+YS4kNChyWzBdLHJbMV0sclsyXSxyWzNdKX1lbHNlIGlmKHE9PT01KWlmKCEhYS4kNSlyZXR1cm4gYS4k
+NShyWzBdLHJbMV0sclsyXSxyWzNdLHJbNF0pCnA9YVsiIisiJCIrcV0KaWYocCE9bnVsbClyZXR1cm4g
+cC5hcHBseShhLHIpfXJldHVybiBILmUxKGEsYixjKX0sCmUxOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxy
+LHEscCxvLG4sbSxsLGssaixpPWIgaW5zdGFuY2VvZiBBcnJheT9iOlAuQ0goYiwhMCx0LnopLGg9aS5s
+ZW5ndGgsZz1hLiRSCmlmKGg8ZylyZXR1cm4gSC56byhhLGksYykKcz1hLiRECnI9cz09bnVsbApxPSFy
+P3MoKTpudWxsCnA9Si5pYShhKQpvPXAuJEMKaWYodHlwZW9mIG89PSJzdHJpbmciKW89cFtvXQppZihy
+KXtpZihjIT1udWxsJiZjLmEhPT0wKXJldHVybiBILnpvKGEsaSxjKQppZihoPT09ZylyZXR1cm4gby5h
+cHBseShhLGkpCnJldHVybiBILnpvKGEsaSxjKX1pZihxIGluc3RhbmNlb2YgQXJyYXkpe2lmKGMhPW51
+bGwmJmMuYSE9PTApcmV0dXJuIEguem8oYSxpLGMpCmlmKGg+ZytxLmxlbmd0aClyZXR1cm4gSC56byhh
+LGksbnVsbCkKQy5ObS5GVihpLHEuc2xpY2UoaC1nKSkKcmV0dXJuIG8uYXBwbHkoYSxpKX1lbHNle2lm
+KGg+ZylyZXR1cm4gSC56byhhLGksYykKbj1PYmplY3Qua2V5cyhxKQppZihjPT1udWxsKWZvcihyPW4u
+bGVuZ3RoLG09MDttPG4ubGVuZ3RoO24ubGVuZ3RoPT09cnx8KDAsSC5saykobiksKyttKXtsPXFbSC5o
+KG5bbV0pXQppZihDLk52PT09bClyZXR1cm4gSC56byhhLGksYykKQy5ObS5pKGksbCl9ZWxzZXtmb3Io
+cj1uLmxlbmd0aCxrPTAsbT0wO208bi5sZW5ndGg7bi5sZW5ndGg9PT1yfHwoMCxILmxrKShuKSwrK20p
+e2o9SC5oKG5bbV0pCmlmKGMueDQoaikpeysrawpDLk5tLmkoaSxjLnEoMCxqKSl9ZWxzZXtsPXFbal0K
+aWYoQy5Odj09PWwpcmV0dXJuIEguem8oYSxpLGMpCkMuTm0uaShpLGwpfX1pZihrIT09Yy5hKXJldHVy
+biBILnpvKGEsaSxjKX1yZXR1cm4gby5hcHBseShhLGkpfX0sCnBZOmZ1bmN0aW9uKGEpe3Rocm93IEgu
+YihILnRMKGEpKX0sCk9IOmZ1bmN0aW9uKGEsYil7aWYoYT09bnVsbClKLkhtKGEpCnRocm93IEguYihI
+LkhZKGEsYikpfSwKSFk6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9ImluZGV4IgppZighSC5vayhiKSly
+ZXR1cm4gbmV3IFAudSghMCxiLHEsbnVsbCkKcz1ILnVQKEouSG0oYSkpCmlmKCEoYjwwKSl7aWYodHlw
+ZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShzKQpyPWI+PXN9ZWxzZSByPSEwCmlmKHIpcmV0dXJu
+IFAuQ2YoYixhLHEsbnVsbCxzKQpyZXR1cm4gUC5PNyhiLHEpfSwKYXU6ZnVuY3Rpb24oYSxiLGMpe2lm
+KGE+YylyZXR1cm4gUC5URShhLDAsYywic3RhcnQiLG51bGwpCmlmKGIhPW51bGwpaWYoYjxhfHxiPmMp
+cmV0dXJuIFAuVEUoYixhLGMsImVuZCIsbnVsbCkKcmV0dXJuIG5ldyBQLnUoITAsYiwiZW5kIixudWxs
+KX0sCnRMOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC51KCEwLGEsbnVsbCxudWxsKX0sCmI6ZnVuY3Rp
+b24oYSl7dmFyIHMscgppZihhPT1udWxsKWE9bmV3IFAuRigpCnM9bmV3IEVycm9yKCkKcy5kYXJ0RXhj
+ZXB0aW9uPWEKcj1ILngKaWYoImRlZmluZVByb3BlcnR5IiBpbiBPYmplY3Qpe09iamVjdC5kZWZpbmVQ
+cm9wZXJ0eShzLCJtZXNzYWdlIix7Z2V0OnJ9KQpzLm5hbWU9IiJ9ZWxzZSBzLnRvU3RyaW5nPXIKcmV0
+dXJuIHN9LAp4OmZ1bmN0aW9uKCl7cmV0dXJuIEouaih0aGlzLmRhcnRFeGNlcHRpb24pfSwKdjpmdW5j
+dGlvbihhKXt0aHJvdyBILmIoYSl9LApsazpmdW5jdGlvbihhKXt0aHJvdyBILmIoUC5hNChhKSl9LApj
+TTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4KYT1ILmVBKGEucmVwbGFjZShTdHJpbmcoe30pLCIk
+cmVjZWl2ZXIkIikpCnM9YS5tYXRjaCgvXFxcJFthLXpBLVpdK1xcXCQvZykKaWYocz09bnVsbClzPUgu
+Vk0oW10sdC5zKQpyPXMuaW5kZXhPZigiXFwkYXJndW1lbnRzXFwkIikKcT1zLmluZGV4T2YoIlxcJGFy
+Z3VtZW50c0V4cHJcXCQiKQpwPXMuaW5kZXhPZigiXFwkZXhwclxcJCIpCm89cy5pbmRleE9mKCJcXCRt
+ZXRob2RcXCQiKQpuPXMuaW5kZXhPZigiXFwkcmVjZWl2ZXJcXCQiKQpyZXR1cm4gbmV3IEguZjkoYS5y
+ZXBsYWNlKG5ldyBSZWdFeHAoIlxcXFxcXCRhcmd1bWVudHNcXFxcXFwkIiwiZyIpLCIoKD86eHxbXnhd
+KSopIikucmVwbGFjZShuZXcgUmVnRXhwKCJcXFxcXFwkYXJndW1lbnRzRXhwclxcXFxcXCQiLCJnIiks
+IigoPzp4fFteeF0pKikiKS5yZXBsYWNlKG5ldyBSZWdFeHAoIlxcXFxcXCRleHByXFxcXFxcJCIsImci
+KSwiKCg/Onh8W154XSkqKSIpLnJlcGxhY2UobmV3IFJlZ0V4cCgiXFxcXFxcJG1ldGhvZFxcXFxcXCQi
+LCJnIiksIigoPzp4fFteeF0pKikiKS5yZXBsYWNlKG5ldyBSZWdFeHAoIlxcXFxcXCRyZWNlaXZlclxc
+XFxcXCQiLCJnIiksIigoPzp4fFteeF0pKikiKSxyLHEscCxvLG4pfSwKUzc6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGZ1bmN0aW9uKCRleHByJCl7dmFyICRhcmd1bWVudHNFeHByJD0iJGFyZ3VtZW50cyQiCnRyeXsk
+ZXhwciQuJG1ldGhvZCQoJGFyZ3VtZW50c0V4cHIkKX1jYXRjaChzKXtyZXR1cm4gcy5tZXNzYWdlfX0o
+YSl9LApNajpmdW5jdGlvbihhKXtyZXR1cm4gZnVuY3Rpb24oJGV4cHIkKXt0cnl7JGV4cHIkLiRtZXRo
+b2QkfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fShhKX0sCklqOmZ1bmN0aW9uKGEsYil7cmV0dXJu
+IG5ldyBILlcwKGEsYj09bnVsbD9udWxsOmIubWV0aG9kKX0sClQzOmZ1bmN0aW9uKGEsYil7dmFyIHM9
+Yj09bnVsbCxyPXM/bnVsbDpiLm1ldGhvZApyZXR1cm4gbmV3IEguYXooYSxyLHM/bnVsbDpiLnJlY2Vp
+dmVyKX0sClJ1OmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG5ldyBILnRlKGEpCmlmKGEgaW5z
+dGFuY2VvZiBILmJxKXJldHVybiBILnRXKGEsYS5hKQppZih0eXBlb2YgYSE9PSJvYmplY3QiKXJldHVy
+biBhCmlmKCJkYXJ0RXhjZXB0aW9uIiBpbiBhKXJldHVybiBILnRXKGEsYS5kYXJ0RXhjZXB0aW9uKQpy
+ZXR1cm4gSC50bChhKX0sCnRXOmZ1bmN0aW9uKGEsYil7aWYodC5yLmIoYikpaWYoYi4kdGhyb3duSnNF
+cnJvcj09bnVsbCliLiR0aHJvd25Kc0Vycm9yPWEKcmV0dXJuIGJ9LAp0bDpmdW5jdGlvbihhKXt2YXIg
+cyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGU9bnVsbAppZighKCJtZXNzYWdlIiBpbiBhKSlyZXR1
+cm4gYQpzPWEubWVzc2FnZQppZigibnVtYmVyIiBpbiBhJiZ0eXBlb2YgYS5udW1iZXI9PSJudW1iZXIi
+KXtyPWEubnVtYmVyCnE9ciY2NTUzNQppZigoQy5qbi53RyhyLDE2KSY4MTkxKT09PTEwKXN3aXRjaChx
+KXtjYXNlIDQzODpyZXR1cm4gSC50VyhhLEguVDMoSC5FaihzKSsiIChFcnJvciAiK3ErIikiLGUpKQpj
+YXNlIDQ0NTpjYXNlIDUwMDc6cmV0dXJuIEgudFcoYSxILklqKEguRWoocykrIiAoRXJyb3IgIitxKyIp
+IixlKSl9fWlmKGEgaW5zdGFuY2VvZiBUeXBlRXJyb3Ipe3A9JC5TbigpCm89JC5scSgpCm49JC5OOSgp
+Cm09JC5pSSgpCmw9JC5VTigpCms9JC5aaCgpCmo9JC5yTigpCiQuYzMoKQppPSQuSEsoKQpoPSQucjEo
+KQpnPXAucVMocykKaWYoZyE9bnVsbClyZXR1cm4gSC50VyhhLEguVDMoSC5oKHMpLGcpKQplbHNle2c9
+by5xUyhzKQppZihnIT1udWxsKXtnLm1ldGhvZD0iY2FsbCIKcmV0dXJuIEgudFcoYSxILlQzKEguaChz
+KSxnKSl9ZWxzZXtnPW4ucVMocykKaWYoZz09bnVsbCl7Zz1tLnFTKHMpCmlmKGc9PW51bGwpe2c9bC5x
+UyhzKQppZihnPT1udWxsKXtnPWsucVMocykKaWYoZz09bnVsbCl7Zz1qLnFTKHMpCmlmKGc9PW51bGwp
+e2c9bS5xUyhzKQppZihnPT1udWxsKXtnPWkucVMocykKaWYoZz09bnVsbCl7Zz1oLnFTKHMpCmY9ZyE9
+bnVsbH1lbHNlIGY9ITB9ZWxzZSBmPSEwfWVsc2UgZj0hMH1lbHNlIGY9ITB9ZWxzZSBmPSEwfWVsc2Ug
+Zj0hMH1lbHNlIGY9ITAKaWYoZilyZXR1cm4gSC50VyhhLEguSWooSC5oKHMpLGcpKX19cmV0dXJuIEgu
+dFcoYSxuZXcgSC52Vih0eXBlb2Ygcz09InN0cmluZyI/czoiIikpfWlmKGEgaW5zdGFuY2VvZiBSYW5n
+ZUVycm9yKXtpZih0eXBlb2Ygcz09InN0cmluZyImJnMuaW5kZXhPZigiY2FsbCBzdGFjayIpIT09LTEp
+cmV0dXJuIG5ldyBQLktZKCkKcz1mdW5jdGlvbihiKXt0cnl7cmV0dXJuIFN0cmluZyhiKX1jYXRjaChk
+KXt9cmV0dXJuIG51bGx9KGEpCnJldHVybiBILnRXKGEsbmV3IFAudSghMSxlLGUsdHlwZW9mIHM9PSJz
+dHJpbmciP3MucmVwbGFjZSgvXlJhbmdlRXJyb3I6XHMqLywiIik6cykpfWlmKHR5cGVvZiBJbnRlcm5h
+bEVycm9yPT0iZnVuY3Rpb24iJiZhIGluc3RhbmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBlb2Ygcz09
+InN0cmluZyImJnM9PT0idG9vIG11Y2ggcmVjdXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4g
+YX0sCnRzOmZ1bmN0aW9uKGEpe3ZhciBzCmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYo
+YT09bnVsbClyZXR1cm4gbmV3IEguWE8oYSkKcz1hLiRjYWNoZWRUcmFjZQppZihzIT1udWxsKXJldHVy
+biBzCnJldHVybiBhLiRjYWNoZWRUcmFjZT1uZXcgSC5YTyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFy
+IHMscixxLHA9YS5sZW5ndGgKZm9yKHM9MDtzPHA7cz1xKXtyPXMrMQpxPXIrMQpiLlk1KDAsYVtzXSxh
+W3JdKX1yZXR1cm4gYn0sCmZ0OmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt0LlkuYShhKQpzd2l0Y2goSC51
+UChiKSl7Y2FzZSAwOnJldHVybiBhLiQwKCkKY2FzZSAxOnJldHVybiBhLiQxKGMpCmNhc2UgMjpyZXR1
+cm4gYS4kMihjLGQpCmNhc2UgMzpyZXR1cm4gYS4kMyhjLGQsZSkKY2FzZSA0OnJldHVybiBhLiQ0KGMs
+ZCxlLGYpfXRocm93IEguYihuZXcgUC5DRCgiVW5zdXBwb3J0ZWQgbnVtYmVyIG9mIGFyZ3VtZW50cyBm
+b3Igd3JhcHBlZCBjbG9zdXJlIikpfSwKdFI6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihhPT1udWxsKXJl
+dHVybiBudWxsCnM9YS4kaWRlbnRpdHkKaWYoISFzKXJldHVybiBzCnM9ZnVuY3Rpb24oYyxkLGUpe3Jl
+dHVybiBmdW5jdGlvbihmLGcsaCxpKXtyZXR1cm4gZShjLGQsZixnLGgsaSl9fShhLGIsSC5mdCkKYS4k
+aWRlbnRpdHk9cwpyZXR1cm4gc30sCmlBOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciBzLHIscSxw
+LG8sbixtLGw9YlswXSxrPWwuJGNhbGxOYW1lLGo9ZT9PYmplY3QuY3JlYXRlKG5ldyBILnp4KCkuY29u
+c3RydWN0b3IucHJvdG90eXBlKTpPYmplY3QuY3JlYXRlKG5ldyBILnJUKG51bGwsbnVsbCxudWxsLCIi
+KS5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpCmouJGluaXRpYWxpemU9ai5jb25zdHJ1Y3RvcgppZihlKXM9
+ZnVuY3Rpb24gc3RhdGljX3RlYXJfb2ZmKCl7dGhpcy4kaW5pdGlhbGl6ZSgpfQplbHNle3I9JC55agpp
+Zih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLmgoKQokLnlqPXIrMQpyPW5ldyBGdW5jdGlvbigi
+YSxiLGMsZCIrciwidGhpcy4kaW5pdGlhbGl6ZShhLGIsYyxkIityKyIpIikKcz1yfWouY29uc3RydWN0
+b3I9cwpzLnByb3RvdHlwZT1qCmlmKCFlKXtxPUguYngoYSxsLGYpCnEuJHJlZmxlY3Rpb25JbmZvPWR9
+ZWxzZXtqLiRzdGF0aWNfbmFtZT1nCnE9bH1qLiRTPUguaW0oZCxlLGYpCmpba109cQpmb3IocD1xLG89
+MTtvPGIubGVuZ3RoOysrbyl7bj1iW29dCm09bi4kY2FsbE5hbWUKaWYobSE9bnVsbCl7bj1lP246SC5i
+eChhLG4sZikKalttXT1ufWlmKG89PT1jKXtuLiRyZWZsZWN0aW9uSW5mbz1kCnA9bn19ai4kQz1wCmou
+JFI9bC4kUgpqLiREPWwuJEQKcmV0dXJuIHN9LAppbTpmdW5jdGlvbihhLGIsYyl7dmFyIHMKaWYodHlw
+ZW9mIGE9PSJudW1iZXIiKXJldHVybiBmdW5jdGlvbihkLGUpe3JldHVybiBmdW5jdGlvbigpe3JldHVy
+biBkKGUpfX0oSC5CcCxhKQppZih0eXBlb2YgYT09InN0cmluZyIpe2lmKGIpdGhyb3cgSC5iKCJDYW5u
+b3QgY29tcHV0ZSBzaWduYXR1cmUgZm9yIHN0YXRpYyB0ZWFyb2ZmLiIpCnM9Yz9ILlBXOkguVG4KcmV0
+dXJuIGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGUodGhpcyxkKX19KGEscyl9
+dGhyb3cgSC5iKCJFcnJvciBpbiBmdW5jdGlvblR5cGUgb2YgdGVhcm9mZiIpfSwKdnE6ZnVuY3Rpb24o
+YSxiLGMsZCl7dmFyIHM9SC5EVgpzd2l0Y2goYj8tMTphKXtjYXNlIDA6cmV0dXJuIGZ1bmN0aW9uKGUs
+Zil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYodGhpcylbZV0oKX19KGMscykKY2FzZSAxOnJldHVy
+biBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnKXtyZXR1cm4gZih0aGlzKVtlXShnKX19KGMs
+cykKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgpe3JldHVybiBm
+KHRoaXMpW2VdKGcsaCl9fShjLHMpCmNhc2UgMzpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVu
+Y3Rpb24oZyxoLGkpe3JldHVybiBmKHRoaXMpW2VdKGcsaCxpKX19KGMscykKY2FzZSA0OnJldHVybiBm
+dW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSxqKXtyZXR1cm4gZih0aGlzKVtlXShnLGgs
+aSxqKX19KGMscykKY2FzZSA1OnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgs
+aSxqLGspe3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGosayl9fShjLHMpCmRlZmF1bHQ6cmV0dXJuIGZ1
+bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGUuYXBwbHkoZih0aGlzKSxhcmd1bWVu
+dHMpfX0oZCxzKX19LApieDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAsbyxuLG0KaWYoYylyZXR1
+cm4gSC5IZihhLGIpCnM9Yi4kc3R1Yk5hbWUKcj1iLmxlbmd0aApxPWFbc10KcD1iPT1udWxsP3E9PW51
+bGw6Yj09PXEKbz0hcHx8cj49MjcKaWYobylyZXR1cm4gSC52cShyLCFwLHMsYikKaWYocj09PTApe3A9
+JC55agppZih0eXBlb2YgcCE9PSJudW1iZXIiKXJldHVybiBwLmgoKQokLnlqPXArMQpuPSJzZWxmIitw
+CnJldHVybiBuZXcgRnVuY3Rpb24oInJldHVybiBmdW5jdGlvbigpe3ZhciAiK24rIiA9IHRoaXMuIitI
+LkVqKEgub04oKSkrIjtyZXR1cm4gIituKyIuIitILkVqKHMpKyIoKTt9IikoKX1tPSJhYmNkZWZnaGlq
+a2xtbm9wcXJzdHV2d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHIpLmpvaW4oIiwiKQpwPSQueWoKaWYo
+dHlwZW9mIHAhPT0ibnVtYmVyIilyZXR1cm4gcC5oKCkKJC55aj1wKzEKbSs9cApyZXR1cm4gbmV3IEZ1
+bmN0aW9uKCJyZXR1cm4gZnVuY3Rpb24oIittKyIpe3JldHVybiB0aGlzLiIrSC5FaihILm9OKCkpKyIu
+IitILkVqKHMpKyIoIittKyIpO30iKSgpfSwKWjQ6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHM9SC5EVixy
+PUgueVMKc3dpdGNoKGI/LTE6YSl7Y2FzZSAwOnRocm93IEguYihuZXcgSC5FcSgiSW50ZXJjZXB0ZWQg
+ZnVuY3Rpb24gd2l0aCBubyBhcmd1bWVudHMuIikpCmNhc2UgMTpyZXR1cm4gZnVuY3Rpb24oZSxmLGcp
+e3JldHVybiBmdW5jdGlvbigpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcykpfX0oYyxzLHIpCmNhc2Ug
+MjpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoKXtyZXR1cm4gZih0aGlzKVtl
+XShnKHRoaXMpLGgpfX0oYyxzLHIpCmNhc2UgMzpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBm
+dW5jdGlvbihoLGkpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxpKX19KGMscyxyKQpjYXNlIDQ6
+cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGope3JldHVybiBmKHRoaXMp
+W2VdKGcodGhpcyksaCxpLGopfX0oYyxzLHIpCmNhc2UgNTpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3Jl
+dHVybiBmdW5jdGlvbihoLGksaixrKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSxqLGspfX0o
+YyxzLHIpCmNhc2UgNjpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoLGksaixr
+LGwpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxpLGosayxsKX19KGMscyxyKQpkZWZhdWx0OnJl
+dHVybiBmdW5jdGlvbihlLGYsZyxoKXtyZXR1cm4gZnVuY3Rpb24oKXtoPVtnKHRoaXMpXQpBcnJheS5w
+cm90b3R5cGUucHVzaC5hcHBseShoLGFyZ3VtZW50cykKcmV0dXJuIGUuYXBwbHkoZih0aGlzKSxoKX19
+KGQscyxyKX19LApIZjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtPUgub04oKSxsPSQuUDQK
+aWYobD09bnVsbClsPSQuUDQ9SC5FMigicmVjZWl2ZXIiKQpzPWIuJHN0dWJOYW1lCnI9Yi5sZW5ndGgK
+cT1hW3NdCnA9Yj09bnVsbD9xPT1udWxsOmI9PT1xCm89IXB8fHI+PTI4CmlmKG8pcmV0dXJuIEguWjQo
+ciwhcCxzLGIpCmlmKHI9PT0xKXtwPSJyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4iK0guRWoo
+bSkrIi4iK0guRWoocykrIih0aGlzLiIrbCsiKTsiCm89JC55agppZih0eXBlb2YgbyE9PSJudW1iZXIi
+KXJldHVybiBvLmgoKQokLnlqPW8rMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKHArbysifSIpKCl9bj0iYWJj
+ZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoiLnNwbGl0KCIiKS5zcGxpY2UoMCxyLTEpLmpvaW4oIiwiKQpw
+PSJyZXR1cm4gZnVuY3Rpb24oIituKyIpe3JldHVybiB0aGlzLiIrSC5FaihtKSsiLiIrSC5FaihzKSsi
+KHRoaXMuIitsKyIsICIrbisiKTsiCm89JC55agppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVybiBv
+LmgoKQokLnlqPW8rMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKHArbysifSIpKCl9LApLcTpmdW5jdGlvbihh
+LGIsYyxkLGUsZixnKXtyZXR1cm4gSC5pQShhLGIsYyxkLCEhZSwhIWYsZyl9LApUbjpmdW5jdGlvbihh
+LGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgueihhLmEpLGIpfSwKUFc6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSxILnooYS5jKSxiKX0sCkRWOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLmF9LAp5UzpmdW5jdGlvbihhKXtyZXR1cm4gYS5jfSwKb046ZnVuY3Rpb24oKXt2YXIgcz0k
+Lm1KCnJldHVybiBzPT1udWxsPyQubUo9SC5FMigic2VsZiIpOnN9LApFMjpmdW5jdGlvbihhKXt2YXIg
+cyxyLHEscD1uZXcgSC5yVCgic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIpLG89Si5FcChP
+YmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhwKSx0LlcpCmZvcihzPW8ubGVuZ3RoLHI9MDtyPHM7Kyty
+KXtxPW9bcl0KaWYocFtxXT09PWEpcmV0dXJuIHF9dGhyb3cgSC5iKFAueFkoIkZpZWxkIG5hbWUgIith
+KyIgbm90IGZvdW5kLiIpKX0sCm9UOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpSC5mTygiYm9vbGVhbiBl
+eHByZXNzaW9uIG11c3Qgbm90IGJlIG51bGwiKQpyZXR1cm4gYX0sCmZPOmZ1bmN0aW9uKGEpe3Rocm93
+IEguYihuZXcgSC5rWShhKSl9LAphZzpmdW5jdGlvbihhKXt0aHJvdyBILmIobmV3IFAuYyhhKSl9LApZ
+ZzpmdW5jdGlvbihhKXtyZXR1cm4gdi5nZXRJc29sYXRlVGFnKGEpfSwKQm86ZnVuY3Rpb24oYSl7cmV0
+dXJuIEgudihuZXcgSC5uKGEpKX0sCml3OmZ1bmN0aW9uKGEsYixjKXtPYmplY3QuZGVmaW5lUHJvcGVy
+dHkoYSxiLHt2YWx1ZTpjLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6
+dHJ1ZX0pfSwKdzM6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuPUguaCgkLk5GLiQxKGEpKSxtPSQu
+bndbbl0KaWYobSE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsdi5kaXNwYXRjaFByb3BlcnR5
+TmFtZSx7dmFsdWU6bSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRy
+dWV9KQpyZXR1cm4gbS5pfXM9JC52dltuXQppZihzIT1udWxsKXJldHVybiBzCnI9di5pbnRlcmNlcHRv
+cnNCeVRhZ1tuXQppZihyPT1udWxsKXtxPUguaygkLlRYLiQyKGEsbikpCmlmKHEhPW51bGwpe209JC5u
+d1txXQppZihtIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlO
+YW1lLHt2YWx1ZTptLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1
+ZX0pCnJldHVybiBtLml9cz0kLnZ2W3FdCmlmKHMhPW51bGwpcmV0dXJuIHMKcj12LmludGVyY2VwdG9y
+c0J5VGFnW3FdCm49cX19aWYocj09bnVsbClyZXR1cm4gbnVsbApzPXIucHJvdG90eXBlCnA9blswXQpp
+ZihwPT09IiEiKXttPUguVmEocykKJC5ud1tuXT1tCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlz
+cGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm0sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNv
+bmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG0uaX1pZihwPT09In4iKXskLnZ2W25dPXMKcmV0dXJuIHN9
+aWYocD09PSItIil7bz1ILlZhKHMpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYmplY3QuZ2V0UHJvdG90
+eXBlT2YoYSksdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7dmFsdWU6byxlbnVtZXJhYmxlOmZhbHNlLHdy
+aXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gby5pfWlmKHA9PT0iKyIpcmV0dXJu
+IEguTGMoYSxzKQppZihwPT09IioiKXRocm93IEguYihQLlNZKG4pKQppZih2LmxlYWZUYWdzW25dPT09
+dHJ1ZSl7bz1ILlZhKHMpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYmplY3QuZ2V0UHJvdG90eXBlT2Yo
 YSksdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7dmFsdWU6byxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxl
-OnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gby5pfWlmKHA9PT0iKyIpcmV0dXJuIEguTGMo
-YSxzKQppZihwPT09IioiKXRocm93IEguYihQLlNZKG4pKQppZih2LmxlYWZUYWdzW25dPT09dHJ1ZSl7
-bz1ILlZhKHMpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSksdi5k
-aXNwYXRjaFByb3BlcnR5TmFtZSx7dmFsdWU6byxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUs
-Y29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gby5pfWVsc2UgcmV0dXJuIEguTGMoYSxzKX0sCkxjOmZ1
-bmN0aW9uKGEsYil7dmFyIHM9T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpCk9iamVjdC5kZWZpbmVQcm9w
-ZXJ0eShzLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOkouUXUoYixzLG51bGwsbnVsbCksZW51
-bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIGJ9LApW
-YTpmdW5jdGlvbihhKXtyZXR1cm4gSi5RdShhLCExLG51bGwsISFhLiRpWGopfSwKVkY6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciBzPWIucHJvdG90eXBlCmlmKHYubGVhZlRhZ3NbYV09PT10cnVlKXJldHVybiBILlZh
-KHMpCmVsc2UgcmV0dXJuIEouUXUocyxjLG51bGwsbnVsbCl9LApYRDpmdW5jdGlvbigpe2lmKCEwPT09
-JC5CdilyZXR1cm4KJC5Cdj0hMApILloxKCl9LApaMTpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixt
-LGwKJC5udz1PYmplY3QuY3JlYXRlKG51bGwpCiQudnY9T2JqZWN0LmNyZWF0ZShudWxsKQpILmtPKCkK
-cz12LmludGVyY2VwdG9yc0J5VGFnCnI9T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocykKaWYodHlw
-ZW9mIHdpbmRvdyE9InVuZGVmaW5lZCIpe3dpbmRvdwpxPWZ1bmN0aW9uKCl7fQpmb3IocD0wO3A8ci5s
-ZW5ndGg7KytwKXtvPXJbcF0Kbj0kLng3LiQxKG8pCmlmKG4hPW51bGwpe209SC5WRihvLHNbb10sbikK
-aWYobSE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KG4sdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7
-dmFsdWU6bSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpx
-LnByb3RvdHlwZT1ufX19fWZvcihwPTA7cDxyLmxlbmd0aDsrK3Ape289cltwXQppZigvXltBLVphLXpf
-XS8udGVzdChvKSl7bD1zW29dCnNbIiEiK29dPWwKc1sifiIrb109bApzWyItIitvXT1sCnNbIisiK29d
-PWwKc1siKiIrb109bH19fSwKa086ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbT1DLllxKCkKbT1I
-LnVkKEMuS1UsSC51ZChDLmZRLEgudWQoQy5pNyxILnVkKEMuaTcsSC51ZChDLnhpLEgudWQoQy5kayxI
-LnVkKEMud2IoQy5PNCksbSkpKSkpKSkKaWYodHlwZW9mIGRhcnROYXRpdmVEaXNwYXRjaEhvb2tzVHJh
-bnNmb3JtZXIhPSJ1bmRlZmluZWQiKXtzPWRhcnROYXRpdmVEaXNwYXRjaEhvb2tzVHJhbnNmb3JtZXIK
-aWYodHlwZW9mIHM9PSJmdW5jdGlvbiIpcz1bc10KaWYocy5jb25zdHJ1Y3Rvcj09QXJyYXkpZm9yKHI9
-MDtyPHMubGVuZ3RoOysrcil7cT1zW3JdCmlmKHR5cGVvZiBxPT0iZnVuY3Rpb24iKW09cShtKXx8bX19
-cD1tLmdldFRhZwpvPW0uZ2V0VW5rbm93blRhZwpuPW0ucHJvdG90eXBlRm9yVGFnCiQuTkY9bmV3IEgu
-ZEMocCkKJC5UWD1uZXcgSC53TihvKQokLng3PW5ldyBILlZYKG4pfSwKdWQ6ZnVuY3Rpb24oYSxiKXty
-ZXR1cm4gYShiKXx8Yn0sCnY0OmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgcz1iPyJtIjoiIixyPWM/
-IiI6ImkiLHE9ZD8idSI6IiIscD1lPyJzIjoiIixvPWY/ImciOiIiLG49ZnVuY3Rpb24oZyxoKXt0cnl7
-cmV0dXJuIG5ldyBSZWdFeHAoZyxoKX1jYXRjaChtKXtyZXR1cm4gbX19KGEscytyK3ErcCtvKQppZihu
-IGluc3RhbmNlb2YgUmVnRXhwKXJldHVybiBuCnRocm93IEguYihQLnJyKCJJbGxlZ2FsIFJlZ0V4cCBw
-YXR0ZXJuICgiK1N0cmluZyhuKSsiKSIsYSxudWxsKSl9LApTUTpmdW5jdGlvbihhLGIsYyl7dmFyIHMK
-aWYodHlwZW9mIGI9PSJzdHJpbmciKXJldHVybiBhLmluZGV4T2YoYixjKT49MAplbHNlIGlmKGIgaW5z
-dGFuY2VvZiBILlZSKXtzPUMueEIueW4oYSxjKQpyZXR1cm4gYi5iLnRlc3Qocyl9ZWxzZXtzPUouRkwo
-YixDLnhCLnluKGEsYykpCnJldHVybiFzLmdsMChzKX19LApBNDpmdW5jdGlvbihhKXtpZihhLmluZGV4
-T2YoIiQiLDApPj0wKXJldHVybiBhLnJlcGxhY2UoL1wkL2csIiQkJCQiKQpyZXR1cm4gYX0sCmVBOmZ1
-bmN0aW9uKGEpe2lmKC9bW1xde30oKSorPy5cXF4kfF0vLnRlc3QoYSkpcmV0dXJuIGEucmVwbGFjZSgv
-W1tcXXt9KCkqKz8uXFxeJHxdL2csIlxcJCYiKQpyZXR1cm4gYX0sCnlzOmZ1bmN0aW9uKGEsYixjKXt2
-YXIgcz1ILm5NKGEsYixjKQpyZXR1cm4gc30sCm5NOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscApp
-ZihiPT09IiIpe2lmKGE9PT0iIilyZXR1cm4gYwpzPWEubGVuZ3RoCmZvcihyPWMscT0wO3E8czsrK3Ep
-cj1yK2FbcV0rYwpyZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn1wPWEuaW5kZXhPZihiLDApCmlm
-KHA8MClyZXR1cm4gYQppZihhLmxlbmd0aDw1MDB8fGMuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEu
-c3BsaXQoYikuam9pbihjKQpyZXR1cm4gYS5yZXBsYWNlKG5ldyBSZWdFeHAoSC5lQShiKSwnZycpLEgu
-QTQoYykpfSwKUEQ6ZnVuY3Rpb24gUEQoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKV1U6ZnVuY3Rp
-b24gV1UoKXt9LApMUDpmdW5jdGlvbiBMUChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8u
-Yz1jCl8uJHRpPWR9LApYUjpmdW5jdGlvbiBYUihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApMSTpm
-dW5jdGlvbiBMSShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPWEKXy5jPWIKXy5kPWMKXy5lPWQKXy5m
-PWV9LApDajpmdW5jdGlvbiBDaihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApmOTpm
-dW5jdGlvbiBmOShhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApf
-LmU9ZQpfLmY9Zn0sClcwOmZ1bmN0aW9uIFcwKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAphejpmdW5j
-dGlvbiBheihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAp2VjpmdW5jdGlvbiB2Vihh
-KXt0aGlzLmE9YX0sCnRlOmZ1bmN0aW9uIHRlKGEpe3RoaXMuYT1hfSwKYnE6ZnVuY3Rpb24gYnEoYSxi
-KXt0aGlzLmE9YQp0aGlzLmI9Yn0sClhPOmZ1bmN0aW9uIFhPKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxs
-fSwKVHA6ZnVuY3Rpb24gVHAoKXt9LApsYzpmdW5jdGlvbiBsYygpe30sCnp4OmZ1bmN0aW9uIHp4KCl7
-fSwKclQ6ZnVuY3Rpb24gclQoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9
-ZH0sCkVxOmZ1bmN0aW9uIEVxKGEpe3RoaXMuYT1hfSwKa1k6ZnVuY3Rpb24ga1koYSl7dGhpcy5hPWF9
-LAprcjpmdW5jdGlvbiBrcigpe30sCk41OmZ1bmN0aW9uIE41KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5m
-PV8uZT1fLmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LAp2aDpmdW5jdGlvbiB2aChhLGIpe3Zh
-ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKaTU6ZnVuY3Rpb24gaTUoYSxiKXt0aGlz
-LmE9YQp0aGlzLiR0aT1ifSwKTjY6ZnVuY3Rpb24gTjYoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5i
-PWIKXy5kPV8uYz1udWxsCl8uJHRpPWN9LApkQzpmdW5jdGlvbiBkQyhhKXt0aGlzLmE9YX0sCndOOmZ1
-bmN0aW9uIHdOKGEpe3RoaXMuYT1hfSwKVlg6ZnVuY3Rpb24gVlgoYSl7dGhpcy5hPWF9LApWUjpmdW5j
-dGlvbiBWUihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKRUs6ZnVuY3Rp
-b24gRUsoYSl7dGhpcy5iPWF9LApLVzpmdW5jdGlvbiBLVyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIK
-dGhpcy5jPWN9LApQYjpmdW5jdGlvbiBQYihhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9
-YwpfLmQ9bnVsbH0sCnRROmZ1bmN0aW9uIHRRKGEsYil7dGhpcy5hPWEKdGhpcy5jPWJ9LAp1bjpmdW5j
-dGlvbiB1bihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApTZDpmdW5jdGlvbiBTZChh
-LGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9bnVsbH0sClhGOmZ1bmN0aW9uKGEp
-e3JldHVybiBhfSwKb2Q6ZnVuY3Rpb24oYSxiLGMpe2lmKGE+Pj4wIT09YXx8YT49Yyl0aHJvdyBILmIo
-SC5IWShiLGEpKX0sCnJNOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwppZighKGE+Pj4wIT09YSkpcz1iPj4+
-MCE9PWJ8fGE+Ynx8Yj5jCmVsc2Ugcz0hMAppZihzKXRocm93IEguYihILmF1KGEsYixjKSkKcmV0dXJu
-IGJ9LApFVDpmdW5jdGlvbiBFVCgpe30sCkxaOmZ1bmN0aW9uIExaKCl7fSwKRGc6ZnVuY3Rpb24gRGco
-KXt9LApQZzpmdW5jdGlvbiBQZygpe30sCnhqOmZ1bmN0aW9uIHhqKCl7fSwKZEU6ZnVuY3Rpb24gZEUo
-KXt9LApaQTpmdW5jdGlvbiBaQSgpe30sCmRUOmZ1bmN0aW9uIGRUKCl7fSwKUHE6ZnVuY3Rpb24gUHEo
-KXt9LAplRTpmdW5jdGlvbiBlRSgpe30sClY2OmZ1bmN0aW9uIFY2KCl7fSwKUkc6ZnVuY3Rpb24gUkco
-KXt9LApWUDpmdW5jdGlvbiBWUCgpe30sCldCOmZ1bmN0aW9uIFdCKCl7fSwKWkc6ZnVuY3Rpb24gWkco
-KXt9LApjejpmdW5jdGlvbihhLGIpe3ZhciBzPWIuYwpyZXR1cm4gcz09bnVsbD9iLmM9SC5CKGEsYi56
-LCEwKTpzfSwKeFo6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iLmMKcmV0dXJuIHM9PW51bGw/Yi5jPUguSihh
-LCJiOCIsW2Iuel0pOnN9LApRMTpmdW5jdGlvbihhKXt2YXIgcz1hLnkKaWYocz09PTZ8fHM9PT03fHxz
-PT09OClyZXR1cm4gSC5RMShhLnopCnJldHVybiBzPT09MTF8fHM9PT0xMn0sCm1EOmZ1bmN0aW9uKGEp
-e3JldHVybiBhLmN5fSwKTjA6ZnVuY3Rpb24oYSl7cmV0dXJuIEguRSh2LnR5cGVVbml2ZXJzZSxhLCEx
-KX0sClBMOmZ1bmN0aW9uKGEsYixhMCxhMSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixl
-LGQsYz1iLnkKc3dpdGNoKGMpe2Nhc2UgNTpjYXNlIDE6Y2FzZSAyOmNhc2UgMzpjYXNlIDQ6cmV0dXJu
-IGIKY2FzZSA2OnM9Yi56CnI9SC5QTChhLHMsYTAsYTEpCmlmKHI9PT1zKXJldHVybiBiCnJldHVybiBI
-LkMoYSxyLCEwKQpjYXNlIDc6cz1iLnoKcj1ILlBMKGEscyxhMCxhMSkKaWYocj09PXMpcmV0dXJuIGIK
-cmV0dXJuIEguQihhLHIsITApCmNhc2UgODpzPWIuegpyPUguUEwoYSxzLGEwLGExKQppZihyPT09cyly
-ZXR1cm4gYgpyZXR1cm4gSC5mKGEsciwhMCkKY2FzZSA5OnE9Yi5RCnA9SC5iWihhLHEsYTAsYTEpCmlm
-KHA9PT1xKXJldHVybiBiCnJldHVybiBILkooYSxiLnoscCkKY2FzZSAxMDpvPWIuegpuPUguUEwoYSxv
-LGEwLGExKQptPWIuUQpsPUguYlooYSxtLGEwLGExKQppZihuPT09byYmbD09PW0pcmV0dXJuIGIKcmV0
-dXJuIEguYShhLG4sbCkKY2FzZSAxMTprPWIuegpqPUguUEwoYSxrLGEwLGExKQppPWIuUQpoPUgucVQo
-YSxpLGEwLGExKQppZihqPT09ayYmaD09PWkpcmV0dXJuIGIKcmV0dXJuIEguZChhLGosaCkKY2FzZSAx
-MjpnPWIuUQphMSs9Zy5sZW5ndGgKZj1ILmJaKGEsZyxhMCxhMSkKbz1iLnoKbj1ILlBMKGEsbyxhMCxh
-MSkKaWYoZj09PWcmJm49PT1vKXJldHVybiBiCnJldHVybiBILkQoYSxuLGYsITApCmNhc2UgMTM6ZT1i
-LnoKaWYoZTxhMSlyZXR1cm4gYgpkPWEwW2UtYTFdCmlmKGQ9PW51bGwpcmV0dXJuIGIKcmV0dXJuIGQK
-ZGVmYXVsdDp0aHJvdyBILmIoUC5oVigiQXR0ZW1wdGVkIHRvIHN1YnN0aXR1dGUgdW5leHBlY3RlZCBS
-VEkga2luZCAiK2MpKX19LApiWjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEscCxvPWIubGVuZ3Ro
-LG49W10KZm9yKHM9ITEscj0wO3I8bzsrK3Ipe3E9YltyXQpwPUguUEwoYSxxLGMsZCkKaWYocCE9PXEp
-cz0hMApuLnB1c2gocCl9cmV0dXJuIHM/bjpifSwKdk86ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixx
-LHAsbyxuLG09Yi5sZW5ndGgsbD1bXQpmb3Iocz0hMSxyPTA7cjxtO3IrPTMpe3E9YltyXQpwPWJbcisx
-XQpvPWJbcisyXQpuPUguUEwoYSxvLGMsZCkKaWYobiE9PW8pcz0hMApsLnB1c2gocSkKbC5wdXNoKHAp
-CmwucHVzaChuKX1yZXR1cm4gcz9sOmJ9LApxVDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyPWIuYSxx
-PUguYlooYSxyLGMsZCkscD1iLmIsbz1ILmJaKGEscCxjLGQpLG49Yi5jLG09SC52TyhhLG4sYyxkKQpp
-ZihxPT09ciYmbz09PXAmJm09PT1uKXJldHVybiBiCnM9bmV3IEguRygpCnMuYT1xCnMuYj1vCnMuYz1t
-CnJldHVybiBzfSwKVk06ZnVuY3Rpb24oYSxiKXthW3YuYXJyYXlSdGldPWIKcmV0dXJuIGF9LApKUzpm
-dW5jdGlvbihhKXt2YXIgcz1hLiRTCmlmKHMhPW51bGwpe2lmKHR5cGVvZiBzPT0ibnVtYmVyIilyZXR1
-cm4gSC5CcChzKQpyZXR1cm4gYS4kUygpfXJldHVybiBudWxsfSwKVWU6ZnVuY3Rpb24oYSxiKXt2YXIg
-cwppZihILlExKGIpKWlmKGEgaW5zdGFuY2VvZiBILlRwKXtzPUguSlMoYSkKaWYocyE9bnVsbClyZXR1
-cm4gc31yZXR1cm4gSC56KGEpfSwKejpmdW5jdGlvbihhKXt2YXIgcwppZihhIGluc3RhbmNlb2YgUC5N
-aCl7cz1hLiR0aQpyZXR1cm4gcyE9bnVsbD9zOkguVlUoYSl9aWYoQXJyYXkuaXNBcnJheShhKSlyZXR1
-cm4gSC50NihhKQpyZXR1cm4gSC5WVShKLmlhKGEpKX0sCnQ2OmZ1bmN0aW9uKGEpe3ZhciBzPWFbdi5h
-cnJheVJ0aV0scj10LngKaWYocz09bnVsbClyZXR1cm4gcgppZihzLmNvbnN0cnVjdG9yIT09ci5jb25z
-dHJ1Y3RvcilyZXR1cm4gcgpyZXR1cm4gc30sCkxoOmZ1bmN0aW9uKGEpe3ZhciBzPWEuJHRpCnJldHVy
-biBzIT1udWxsP3M6SC5WVShhKX0sClZVOmZ1bmN0aW9uKGEpe3ZhciBzPWEuY29uc3RydWN0b3Iscj1z
-LiRjY2FjaGUKaWYociE9bnVsbClyZXR1cm4gcgpyZXR1cm4gSC5yOShhLHMpfSwKcjk6ZnVuY3Rpb24o
-YSxiKXt2YXIgcz1hIGluc3RhbmNlb2YgSC5UcD9hLl9fcHJvdG9fXy5fX3Byb3RvX18uY29uc3RydWN0
-b3I6YixyPUguYWkodi50eXBlVW5pdmVyc2Uscy5uYW1lKQpiLiRjY2FjaGU9cgpyZXR1cm4gcn0sCkJw
-OmZ1bmN0aW9uKGEpe3ZhciBzLHIscQpILnVQKGEpCnM9di50eXBlcwpyPXNbYV0KaWYodHlwZW9mIHI9
-PSJzdHJpbmciKXtxPUguRSh2LnR5cGVVbml2ZXJzZSxyLCExKQpzW2FdPXEKcmV0dXJuIHF9cmV0dXJu
-IHJ9LApLeDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD1hLngKaWYocCE9bnVsbClyZXR1cm4gcApzPWEu
-Y3kKcj1zLnJlcGxhY2UoL1wqL2csIiIpCmlmKHI9PT1zKXJldHVybiBhLng9bmV3IEgubFkoYSkKcT1I
-LkUodi50eXBlVW5pdmVyc2UsciwhMCkKcD1xLngKcmV0dXJuIGEueD1wPT1udWxsP3EueD1uZXcgSC5s
-WShxKTpwfSwKSko6ZnVuY3Rpb24oYSl7dmFyIHMscixxPXRoaXMscD10LksKaWYocT09PXApcmV0dXJu
-IEguUkUocSxhLEgua2UpCmlmKCFILkE4KHEpKWlmKCEocT09PXQuXykpcD1xPT09cAplbHNlIHA9ITAK
-ZWxzZSBwPSEwCmlmKHApcmV0dXJuIEguUkUocSxhLEguSXcpCnA9cS55CnM9cD09PTY/cS56OnEKaWYo
-cz09PXQuUylyPUgub2sKZWxzZSBpZihzPT09dC5nUnx8cz09PXQuZGkpcj1ILktICmVsc2UgaWYocz09
-PXQuTilyPUguTU0KZWxzZSByPXM9PT10Lnk/SC5sOm51bGwKaWYociE9bnVsbClyZXR1cm4gSC5SRShx
-LGEscikKaWYocy55PT09OSl7cD1zLnoKaWYocy5RLmV2ZXJ5KEguY2MpKXtxLnI9IiRpIitwCnJldHVy
-biBILlJFKHEsYSxILnQ0KX19ZWxzZSBpZihwPT09NylyZXR1cm4gSC5SRShxLGEsSC5BUSkKcmV0dXJu
-IEguUkUocSxhLEguWU8pfSwKUkU6ZnVuY3Rpb24oYSxiLGMpe2EuYj1jCnJldHVybiBhLmIoYil9LApB
-dTpmdW5jdGlvbihhKXt2YXIgcyxyLHE9dGhpcwppZighSC5BOChxKSlpZighKHE9PT10Ll8pKXM9cT09
-PXQuSwplbHNlIHM9ITAKZWxzZSBzPSEwCmlmKHMpcj1ILmhuCmVsc2UgaWYocT09PXQuSylyPUguVGkK
-ZWxzZSByPUgubDQKcS5hPXIKcmV0dXJuIHEuYShhKX0sClFqOmZ1bmN0aW9uKGEpe3ZhciBzLHI9YS55
-CmlmKCFILkE4KGEpKWlmKCEoYT09PXQuXykpaWYoIShhPT09dC5jRikpaWYociE9PTcpcz1yPT09OCYm
-SC5RaihhLnopfHxhPT09dC5QfHxhPT09dC5UCmVsc2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBzPSEwCmVs
-c2Ugcz0hMApyZXR1cm4gc30sCllPOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKaWYoYT09bnVsbClyZXR1
-cm4gSC5RaihzKQpyZXR1cm4gSC5XZSh2LnR5cGVVbml2ZXJzZSxILlVlKGEscyksbnVsbCxzLG51bGwp
-fSwKQVE6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4hMApyZXR1cm4gdGhpcy56LmIoYSl9LAp0
-NDpmdW5jdGlvbihhKXt2YXIgcyxyPXRoaXMKaWYoYT09bnVsbClyZXR1cm4gSC5RaihyKQpzPXIucgpp
-ZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4hIWFbc10KcmV0dXJuISFKLmlhKGEpW3NdfSwKT3o6ZnVu
-Y3Rpb24oYSl7dmFyIHM9dGhpcwppZihhPT1udWxsKXJldHVybiBhCmVsc2UgaWYocy5iKGEpKXJldHVy
-biBhCkgubTQoYSxzKX0sCmw0OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKaWYoYT09bnVsbClyZXR1cm4g
-YQplbHNlIGlmKHMuYihhKSlyZXR1cm4gYQpILm00KGEscyl9LAptNDpmdW5jdGlvbihhLGIpe3Rocm93
-IEguYihILlpjKEguV0soYSxILlVlKGEsYiksSC5kbShiLG51bGwpKSkpfSwKRGg6ZnVuY3Rpb24oYSxi
-LGMsZCl7dmFyIHM9bnVsbAppZihILldlKHYudHlwZVVuaXZlcnNlLGEscyxiLHMpKXJldHVybiBhCnRo
-cm93IEguYihILlpjKCJUaGUgdHlwZSBhcmd1bWVudCAnIitILkVqKEguZG0oYSxzKSkrIicgaXMgbm90
-IGEgc3VidHlwZSBvZiB0aGUgdHlwZSB2YXJpYWJsZSBib3VuZCAnIitILkVqKEguZG0oYixzKSkrIicg
-b2YgdHlwZSB2YXJpYWJsZSAnIitILkVqKGMpKyInIGluICciK0guRWooZCkrIicuIikpfSwKV0s6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciBzPVAucChhKSxyPUguZG0oYj09bnVsbD9ILnooYSk6YixudWxsKQpyZXR1
-cm4gcysiOiB0eXBlICciK0guRWoocikrIicgaXMgbm90IGEgc3VidHlwZSBvZiB0eXBlICciK0guRWoo
-YykrIicifSwKWmM6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILmlNKCJUeXBlRXJyb3I6ICIrYSl9LApx
-OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILmlNKCJUeXBlRXJyb3I6ICIrSC5XSyhhLG51bGwsYikp
-fSwKa2U6ZnVuY3Rpb24oYSl7cmV0dXJuIGEhPW51bGx9LApUaTpmdW5jdGlvbihhKXtyZXR1cm4gYX0s
-Ckl3OmZ1bmN0aW9uKGEpe3JldHVybiEwfSwKaG46ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LApsOmZ1bmN0
-aW9uKGEpe3JldHVybiEwPT09YXx8ITE9PT1hfSwKcDg6ZnVuY3Rpb24oYSl7aWYoITA9PT1hKXJldHVy
-biEwCmlmKCExPT09YSlyZXR1cm4hMQp0aHJvdyBILmIoSC5xKGEsImJvb2wiKSl9LAp5ODpmdW5jdGlv
-bihhKXtpZighMD09PWEpcmV0dXJuITAKaWYoITE9PT1hKXJldHVybiExCmlmKGE9PW51bGwpcmV0dXJu
-IGEKdGhyb3cgSC5iKEgucShhLCJib29sIikpfSwKZHA6ZnVuY3Rpb24oYSl7aWYoITA9PT1hKXJldHVy
-biEwCmlmKCExPT09YSlyZXR1cm4hMQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwi
-Ym9vbD8iKSl9LApGRzpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKdGhy
-b3cgSC5iKEgucShhLCJkb3VibGUiKSl9LApHSDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJl
-ciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImRvdWJsZSIpKX0s
-ClFrOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1udWxsKXJl
-dHVybiBhCnRocm93IEguYihILnEoYSwiZG91YmxlPyIpKX0sCm9rOmZ1bmN0aW9uKGEpe3JldHVybiB0
-eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hfSwKSVo6ZnVuY3Rpb24oYSl7aWYodHlw
-ZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YSlyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEs
-ImludCIpKX0sCnVQOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihh
-KT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImludCIpKX0s
-ClVjOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09PWEpcmV0
-dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImludD8iKSl9LApLSDpmdW5j
-dGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJudW1iZXIifSwKejU6ZnVuY3Rpb24oYSl7aWYodHlwZW9m
-IGE9PSJudW1iZXIiKXJldHVybiBhCnRocm93IEguYihILnEoYSwibnVtIikpfSwKVzE6ZnVuY3Rpb24o
-YSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cg
-SC5iKEgucShhLCJudW0iKSl9LApjVTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0
-dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIm51bT8iKSl9LApNTTpmdW5j
-dGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJzdHJpbmcifSwKQnQ6ZnVuY3Rpb24oYSl7aWYodHlwZW9m
-IGE9PSJzdHJpbmciKXJldHVybiBhCnRocm93IEguYihILnEoYSwiU3RyaW5nIikpfSwKaDpmdW5jdGlv
-bihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJv
-dyBILmIoSC5xKGEsIlN0cmluZyIpKX0sCms6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJzdHJpbmci
-KXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJTdHJpbmc/IikpfSwK
-aW86ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEKZm9yKHM9IiIscj0iIixxPTA7cTxhLmxlbmd0aDsrK3Es
-cj0iLCAiKXMrPUMueEIuaChyLEguZG0oYVtxXSxiKSkKcmV0dXJuIHN9LApiSTpmdW5jdGlvbihhNSxh
-NixhNyl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGEsYTAsYTEsYTIsYTMs
-YTQ9IiwgIgppZihhNyE9bnVsbCl7cz1hNy5sZW5ndGgKaWYoYTY9PW51bGwpe2E2PUguVk0oW10sdC5z
-KQpyPW51bGx9ZWxzZSByPWE2Lmxlbmd0aApxPWE2Lmxlbmd0aApmb3IocD1zO3A+MDstLXApQy5ObS5p
-KGE2LCJUIisocStwKSkKZm9yKG89dC5XLG49dC5fLG09dC5LLGw9IjwiLGs9IiIscD0wO3A8czsrK3As
-az1hNCl7bCs9awpqPWE2Lmxlbmd0aAppPWotMS1wCmlmKGk8MClyZXR1cm4gSC5PSChhNixpKQpsPUMu
-eEIuaChsLGE2W2ldKQpoPWE3W3BdCmc9aC55CmlmKCEoZz09PTJ8fGc9PT0zfHxnPT09NHx8Zz09PTV8
-fGg9PT1vKSlpZighKGg9PT1uKSlqPWg9PT1tCmVsc2Ugaj0hMAplbHNlIGo9ITAKaWYoIWopbCs9Qy54
-Qi5oKCIgZXh0ZW5kcyAiLEguZG0oaCxhNikpfWwrPSI+In1lbHNle2w9IiIKcj1udWxsfW89YTUuegpm
-PWE1LlEKZT1mLmEKZD1lLmxlbmd0aApjPWYuYgpiPWMubGVuZ3RoCmE9Zi5jCmEwPWEubGVuZ3RoCmEx
-PUguZG0obyxhNikKZm9yKGEyPSIiLGEzPSIiLHA9MDtwPGQ7KytwLGEzPWE0KWEyKz1DLnhCLmgoYTMs
-SC5kbShlW3BdLGE2KSkKaWYoYj4wKXthMis9YTMrIlsiCmZvcihhMz0iIixwPTA7cDxiOysrcCxhMz1h
-NClhMis9Qy54Qi5oKGEzLEguZG0oY1twXSxhNikpCmEyKz0iXSJ9aWYoYTA+MCl7YTIrPWEzKyJ7Igpm
-b3IoYTM9IiIscD0wO3A8YTA7cCs9MyxhMz1hNCl7YTIrPWEzCmlmKGFbcCsxXSlhMis9InJlcXVpcmVk
-ICIKYTIrPUouYmIoSC5kbShhW3ArMl0sYTYpLCIgIikrYVtwXX1hMis9In0ifWlmKHIhPW51bGwpe2E2
-LnRvU3RyaW5nCmE2Lmxlbmd0aD1yfXJldHVybiBsKyIoIithMisiKSA9PiAiK0guRWooYTEpfSwKZG06
-ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxsPWEueQppZihsPT09NSlyZXR1cm4iZXJhc2Vk
-IgppZihsPT09MilyZXR1cm4iZHluYW1pYyIKaWYobD09PTMpcmV0dXJuInZvaWQiCmlmKGw9PT0xKXJl
-dHVybiJOZXZlciIKaWYobD09PTQpcmV0dXJuImFueSIKaWYobD09PTYpe3M9SC5kbShhLnosYikKcmV0
-dXJuIHN9aWYobD09PTcpe3I9YS56CnM9SC5kbShyLGIpCnE9ci55CnJldHVybiBKLmJiKHE9PT0xMXx8
-cT09PTEyP0MueEIuaCgiKCIscykrIikiOnMsIj8iKX1pZihsPT09OClyZXR1cm4iRnV0dXJlT3I8IitI
-LkVqKEguZG0oYS56LGIpKSsiPiIKaWYobD09PTkpe3A9SC5vMyhhLnopCm89YS5RCnJldHVybiBvLmxl
-bmd0aCE9PTA/cCsoIjwiK0guaW8obyxiKSsiPiIpOnB9aWYobD09PTExKXJldHVybiBILmJJKGEsYixu
-dWxsKQppZihsPT09MTIpcmV0dXJuIEguYkkoYS56LGIsYS5RKQppZihsPT09MTMpe2IudG9TdHJpbmcK
-bj1hLnoKbT1iLmxlbmd0aApuPW0tMS1uCmlmKG48MHx8bj49bSlyZXR1cm4gSC5PSChiLG4pCnJldHVy
-biBiW25dfXJldHVybiI/In0sCm8zOmZ1bmN0aW9uKGEpe3ZhciBzLHI9SC5KZyhhKQppZihyIT1udWxs
-KXJldHVybiByCnM9Im1pbmlmaWVkOiIrYQpyZXR1cm4gc30sClFvOmZ1bmN0aW9uKGEsYil7dmFyIHM9
-YS50UltiXQpmb3IoO3R5cGVvZiBzPT0ic3RyaW5nIjspcz1hLnRSW3NdCnJldHVybiBzfSwKYWk6ZnVu
-Y3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG49YS5lVCxtPW5bYl0KaWYobT09bnVsbClyZXR1cm4gSC5F
-KGEsYiwhMSkKZWxzZSBpZih0eXBlb2YgbT09Im51bWJlciIpe3M9bQpyPUgubShhLDUsIiMiKQpxPVtd
-CmZvcihwPTA7cDxzOysrcClxLnB1c2gocikKbz1ILkooYSxiLHEpCm5bYl09bwpyZXR1cm4gb31lbHNl
-IHJldHVybiBtfSwKeGI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5JeChhLnRSLGIpfSwKRkY6ZnVuY3Rp
-b24oYSxiKXtyZXR1cm4gSC5JeChhLmVULGIpfSwKRTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1hLmVD
-LHE9ci5nZXQoYikKaWYocSE9bnVsbClyZXR1cm4gcQpzPUguaShILm8oYSxudWxsLGIsYykpCnIuc2V0
-KGIscykKcmV0dXJuIHN9LApjRTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxPWIuY2gKaWYocT09bnVs
-bClxPWIuY2g9bmV3IE1hcCgpCnM9cS5nZXQoYykKaWYocyE9bnVsbClyZXR1cm4gcwpyPUguaShILm8o
-YSxiLGMsITApKQpxLnNldChjLHIpCnJldHVybiByfSwKdjU6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIs
-cSxwPWIuY3gKaWYocD09bnVsbClwPWIuY3g9bmV3IE1hcCgpCnM9Yy5jeQpyPXAuZ2V0KHMpCmlmKHIh
-PW51bGwpcmV0dXJuIHIKcT1ILmEoYSxiLGMueT09PTEwP2MuUTpbY10pCnAuc2V0KHMscSkKcmV0dXJu
-IHF9LApCRDpmdW5jdGlvbihhLGIpe2IuYT1ILkF1CmIuYj1ILkpKCnJldHVybiBifSwKbTpmdW5jdGlv
-bihhLGIsYyl7dmFyIHMscixxPWEuZUMuZ2V0KGMpCmlmKHEhPW51bGwpcmV0dXJuIHEKcz1uZXcgSC5K
-YyhudWxsLG51bGwpCnMueT1iCnMuY3k9YwpyPUguQkQoYSxzKQphLmVDLnNldChjLHIpCnJldHVybiBy
-fSwKQzpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1iLmN5KyIqIixxPWEuZUMuZ2V0KHIpCmlmKHEhPW51
-bGwpcmV0dXJuIHEKcz1ILlo3KGEsYixyLGMpCmEuZUMuc2V0KHIscykKcmV0dXJuIHN9LApaNzpmdW5j
-dGlvbihhLGIsYyxkKXt2YXIgcyxyLHEKaWYoZCl7cz1iLnkKaWYoIUguQTgoYikpcj1iPT09dC5QfHxi
-PT09dC5UfHxzPT09N3x8cz09PTYKZWxzZSByPSEwCmlmKHIpcmV0dXJuIGJ9cT1uZXcgSC5KYyhudWxs
-LG51bGwpCnEueT02CnEuej1iCnEuY3k9YwpyZXR1cm4gSC5CRChhLHEpfSwKQjpmdW5jdGlvbihhLGIs
-Yyl7dmFyIHMscj1iLmN5KyI/IixxPWEuZUMuZ2V0KHIpCmlmKHEhPW51bGwpcmV0dXJuIHEKcz1ILmxs
-KGEsYixyLGMpCmEuZUMuc2V0KHIscykKcmV0dXJuIHN9LApsbDpmdW5jdGlvbihhLGIsYyxkKXt2YXIg
-cyxyLHEscAppZihkKXtzPWIueQppZighSC5BOChiKSlpZighKGI9PT10LlB8fGI9PT10LlQpKWlmKHMh
-PT03KXI9cz09PTgmJkgubFIoYi56KQplbHNlIHI9ITAKZWxzZSByPSEwCmVsc2Ugcj0hMAppZihyKXJl
-dHVybiBiCmVsc2UgaWYocz09PTF8fGI9PT10LmNGKXJldHVybiB0LlAKZWxzZSBpZihzPT09Nil7cT1i
-LnoKaWYocS55PT09OCYmSC5sUihxLnopKXJldHVybiBxCmVsc2UgcmV0dXJuIEguY3ooYSxiKX19cD1u
-ZXcgSC5KYyhudWxsLG51bGwpCnAueT03CnAuej1iCnAuY3k9YwpyZXR1cm4gSC5CRChhLHApfSwKZjpm
-dW5jdGlvbihhLGIsYyl7dmFyIHMscj1iLmN5KyIvIixxPWEuZUMuZ2V0KHIpCmlmKHEhPW51bGwpcmV0
-dXJuIHEKcz1ILmVWKGEsYixyLGMpCmEuZUMuc2V0KHIscykKcmV0dXJuIHN9LAplVjpmdW5jdGlvbihh
-LGIsYyxkKXt2YXIgcyxyLHEKaWYoZCl7cz1iLnkKaWYoIUguQTgoYikpaWYoIShiPT09dC5fKSlyPWI9
-PT10LksKZWxzZSByPSEwCmVsc2Ugcj0hMAppZihyfHxiPT09dC5LKXJldHVybiBiCmVsc2UgaWYocz09
-PTEpcmV0dXJuIEguSihhLCJiOCIsW2JdKQplbHNlIGlmKGI9PT10LlB8fGI9PT10LlQpcmV0dXJuIHQu
-Ykd9cT1uZXcgSC5KYyhudWxsLG51bGwpCnEueT04CnEuej1iCnEuY3k9YwpyZXR1cm4gSC5CRChhLHEp
-fSwKSDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT0iIitiKyJeIixwPWEuZUMuZ2V0KHEpCmlmKHAhPW51
-bGwpcmV0dXJuIHAKcz1uZXcgSC5KYyhudWxsLG51bGwpCnMueT0xMwpzLno9YgpzLmN5PXEKcj1ILkJE
-KGEscykKYS5lQy5zZXQocSxyKQpyZXR1cm4gcn0sClV4OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPWEu
-bGVuZ3RoCmZvcihzPSIiLHI9IiIscT0wO3E8cDsrK3Escj0iLCIpcys9cithW3FdLmN5CnJldHVybiBz
-fSwKUzQ6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG09YS5sZW5ndGgKZm9yKHM9IiIscj0iIixx
-PTA7cTxtO3ErPTMscj0iLCIpe3A9YVtxXQpvPWFbcSsxXT8iISI6IjoiCm49YVtxKzJdLmN5CnMrPXIr
-cCtvK259cmV0dXJuIHN9LApKOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscD1iCmlmKGMubGVuZ3Ro
-IT09MClwKz0iPCIrSC5VeChjKSsiPiIKcz1hLmVDLmdldChwKQppZihzIT1udWxsKXJldHVybiBzCnI9
-bmV3IEguSmMobnVsbCxudWxsKQpyLnk9OQpyLno9YgpyLlE9YwppZihjLmxlbmd0aD4wKXIuYz1jWzBd
-CnIuY3k9cApxPUguQkQoYSxyKQphLmVDLnNldChwLHEpCnJldHVybiBxfSwKYTpmdW5jdGlvbihhLGIs
-Yyl7dmFyIHMscixxLHAsbyxuCmlmKGIueT09PTEwKXtzPWIuegpyPWIuUS5jb25jYXQoYyl9ZWxzZXty
-PWMKcz1ifXE9cy5jeSsoIjs8IitILlV4KHIpKyI+IikKcD1hLmVDLmdldChxKQppZihwIT1udWxsKXJl
-dHVybiBwCm89bmV3IEguSmMobnVsbCxudWxsKQpvLnk9MTAKby56PXMKby5RPXIKby5jeT1xCm49SC5C
-RChhLG8pCmEuZUMuc2V0KHEsbikKcmV0dXJuIG59LApkOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEs
-cCxvLG49Yi5jeSxtPWMuYSxsPW0ubGVuZ3RoLGs9Yy5iLGo9ay5sZW5ndGgsaT1jLmMsaD1pLmxlbmd0
-aCxnPSIoIitILlV4KG0pCmlmKGo+MCl7cz1sPjA/IiwiOiIiCnI9SC5VeChrKQpnKz1zKyJbIityKyJd
-In1pZihoPjApe3M9bD4wPyIsIjoiIgpyPUguUzQoaSkKZys9cysieyIrcisifSJ9cT1uKyhnKyIpIikK
-cD1hLmVDLmdldChxKQppZihwIT1udWxsKXJldHVybiBwCm89bmV3IEguSmMobnVsbCxudWxsKQpvLnk9
-MTEKby56PWIKby5RPWMKby5jeT1xCnI9SC5CRChhLG8pCmEuZUMuc2V0KHEscikKcmV0dXJuIHJ9LApE
-OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHI9Yi5jeSsoIjwiK0guVXgoYykrIj4iKSxxPWEuZUMuZ2V0
-KHIpCmlmKHEhPW51bGwpcmV0dXJuIHEKcz1ILmh3KGEsYixjLHIsZCkKYS5lQy5zZXQocixzKQpyZXR1
-cm4gc30sCmh3OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbyxuLG0sbAppZihlKXtzPWMu
-bGVuZ3RoCnI9bmV3IEFycmF5KHMpCmZvcihxPTAscD0wO3A8czsrK3Ape289Y1twXQppZihvLnk9PT0x
-KXtyW3BdPW87KytxfX1pZihxPjApe249SC5QTChhLGIsciwwKQptPUguYlooYSxjLHIsMCkKcmV0dXJu
-IEguRChhLG4sbSxjIT09bSl9fWw9bmV3IEguSmMobnVsbCxudWxsKQpsLnk9MTIKbC56PWIKbC5RPWMK
-bC5jeT1kCnJldHVybiBILkJEKGEsbCl9LApvOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybnt1OmEsZTpi
-LHI6YyxzOltdLHA6MCxuOmR9fSwKaTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixp
-LGgsZz1hLnIsZj1hLnMKZm9yKHM9Zy5sZW5ndGgscj0wO3I8czspe3E9Zy5jaGFyQ29kZUF0KHIpCmlm
-KHE+PTQ4JiZxPD01NylyPUguQShyKzEscSxnLGYpCmVsc2UgaWYoKCgocXwzMik+Pj4wKS05NyY2NTUz
-NSk8MjZ8fHE9PT05NXx8cT09PTM2KXI9SC50KGEscixnLGYsITEpCmVsc2UgaWYocT09PTQ2KXI9SC50
-KGEscixnLGYsITApCmVsc2V7KytyCnN3aXRjaChxKXtjYXNlIDQ0OmJyZWFrCmNhc2UgNTg6Zi5wdXNo
-KCExKQpicmVhawpjYXNlIDMzOmYucHVzaCghMCkKYnJlYWsKY2FzZSA1OTpmLnB1c2goSC5LKGEudSxh
-LmUsZi5wb3AoKSkpCmJyZWFrCmNhc2UgOTQ6Zi5wdXNoKEguSChhLnUsZi5wb3AoKSkpCmJyZWFrCmNh
-c2UgMzU6Zi5wdXNoKEgubShhLnUsNSwiIyIpKQpicmVhawpjYXNlIDY0OmYucHVzaChILm0oYS51LDIs
-IkAiKSkKYnJlYWsKY2FzZSAxMjY6Zi5wdXNoKEgubShhLnUsMywifiIpKQpicmVhawpjYXNlIDYwOmYu
-cHVzaChhLnApCmEucD1mLmxlbmd0aApicmVhawpjYXNlIDYyOnA9YS51Cm89Zi5zcGxpY2UoYS5wKQpI
-LnIoYS51LGEuZSxvKQphLnA9Zi5wb3AoKQpuPWYucG9wKCkKaWYodHlwZW9mIG49PSJzdHJpbmciKWYu
-cHVzaChILkoocCxuLG8pKQplbHNle209SC5LKHAsYS5lLG4pCnN3aXRjaChtLnkpe2Nhc2UgMTE6Zi5w
-dXNoKEguRChwLG0sbyxhLm4pKQpicmVhawpkZWZhdWx0OmYucHVzaChILmEocCxtLG8pKQpicmVha319
-YnJlYWsKY2FzZSAzODpILkkoYSxmKQpicmVhawpjYXNlIDQyOmw9YS51CmYucHVzaChILkMobCxILkso
-bCxhLmUsZi5wb3AoKSksYS5uKSkKYnJlYWsKY2FzZSA2MzpsPWEudQpmLnB1c2goSC5CKGwsSC5LKGws
-YS5lLGYucG9wKCkpLGEubikpCmJyZWFrCmNhc2UgNDc6bD1hLnUKZi5wdXNoKEguZihsLEguSyhsLGEu
-ZSxmLnBvcCgpKSxhLm4pKQpicmVhawpjYXNlIDQwOmYucHVzaChhLnApCmEucD1mLmxlbmd0aApicmVh
-awpjYXNlIDQxOnA9YS51Cms9bmV3IEguRygpCmo9cC5zRUEKaT1wLnNFQQpuPWYucG9wKCkKaWYodHlw
-ZW9mIG49PSJudW1iZXIiKXN3aXRjaChuKXtjYXNlLTE6aj1mLnBvcCgpCmJyZWFrCmNhc2UtMjppPWYu
-cG9wKCkKYnJlYWsKZGVmYXVsdDpmLnB1c2gobikKYnJlYWt9ZWxzZSBmLnB1c2gobikKbz1mLnNwbGlj
-ZShhLnApCkgucihhLnUsYS5lLG8pCmEucD1mLnBvcCgpCmsuYT1vCmsuYj1qCmsuYz1pCmYucHVzaChI
-LmQocCxILksocCxhLmUsZi5wb3AoKSksaykpCmJyZWFrCmNhc2UgOTE6Zi5wdXNoKGEucCkKYS5wPWYu
-bGVuZ3RoCmJyZWFrCmNhc2UgOTM6bz1mLnNwbGljZShhLnApCkgucihhLnUsYS5lLG8pCmEucD1mLnBv
-cCgpCmYucHVzaChvKQpmLnB1c2goLTEpCmJyZWFrCmNhc2UgMTIzOmYucHVzaChhLnApCmEucD1mLmxl
-bmd0aApicmVhawpjYXNlIDEyNTpvPWYuc3BsaWNlKGEucCkKSC55KGEudSxhLmUsbykKYS5wPWYucG9w
-KCkKZi5wdXNoKG8pCmYucHVzaCgtMikKYnJlYWsKZGVmYXVsdDp0aHJvdyJCYWQgY2hhcmFjdGVyICIr
-cX19fWg9Zi5wb3AoKQpyZXR1cm4gSC5LKGEudSxhLmUsaCl9LApBOmZ1bmN0aW9uKGEsYixjLGQpe3Zh
-ciBzLHIscT1iLTQ4CmZvcihzPWMubGVuZ3RoO2E8czsrK2Epe3I9Yy5jaGFyQ29kZUF0KGEpCmlmKCEo
-cj49NDgmJnI8PTU3KSlicmVhawpxPXEqMTArKHItNDgpfWQucHVzaChxKQpyZXR1cm4gYX0sCnQ6ZnVu
-Y3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvLG4sbT1iKzEKZm9yKHM9Yy5sZW5ndGg7bTxzOysr
-bSl7cj1jLmNoYXJDb2RlQXQobSkKaWYocj09PTQ2KXtpZihlKWJyZWFrCmU9ITB9ZWxzZXtpZighKCgo
-KHJ8MzIpPj4+MCktOTcmNjU1MzUpPDI2fHxyPT09OTV8fHI9PT0zNikpcT1yPj00OCYmcjw9NTcKZWxz
-ZSBxPSEwCmlmKCFxKWJyZWFrfX1wPWMuc3Vic3RyaW5nKGIsbSkKaWYoZSl7cz1hLnUKbz1hLmUKaWYo
-by55PT09MTApbz1vLnoKbj1ILlFvKHMsby56KVtwXQppZihuPT1udWxsKUgudignTm8gIicrcCsnIiBp
-biAiJytILm1EKG8pKyciJykKZC5wdXNoKEguY0UocyxvLG4pKX1lbHNlIGQucHVzaChwKQpyZXR1cm4g
-bX0sCkk6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iLnBvcCgpCmlmKDA9PT1zKXtiLnB1c2goSC5tKGEudSwx
-LCIwJiIpKQpyZXR1cm59aWYoMT09PXMpe2IucHVzaChILm0oYS51LDQsIjEmIikpCnJldHVybn10aHJv
-dyBILmIoUC5oVigiVW5leHBlY3RlZCBleHRlbmRlZCBvcGVyYXRpb24gIitILkVqKHMpKSl9LApLOmZ1
-bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYz09InN0cmluZyIpcmV0dXJuIEguSihhLGMsYS5zRUEpCmVs
-c2UgaWYodHlwZW9mIGM9PSJudW1iZXIiKXJldHVybiBILlRWKGEsYixjKQplbHNlIHJldHVybiBjfSwK
-cjpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1jLmxlbmd0aApmb3Iocz0wO3M8cjsrK3MpY1tzXT1ILkso
-YSxiLGNbc10pfSwKeTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1jLmxlbmd0aApmb3Iocz0yO3M8cjtz
-Kz0zKWNbc109SC5LKGEsYixjW3NdKX0sClRWOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHE9Yi55Cmlm
-KHE9PT0xMCl7aWYoYz09PTApcmV0dXJuIGIuegpzPWIuUQpyPXMubGVuZ3RoCmlmKGM8PXIpcmV0dXJu
-IHNbYy0xXQpjLT1yCmI9Yi56CnE9Yi55fWVsc2UgaWYoYz09PTApcmV0dXJuIGIKaWYocSE9PTkpdGhy
-b3cgSC5iKFAuaFYoIkluZGV4ZWQgYmFzZSBtdXN0IGJlIGFuIGludGVyZmFjZSB0eXBlIikpCnM9Yi5R
-CmlmKGM8PXMubGVuZ3RoKXJldHVybiBzW2MtMV0KdGhyb3cgSC5iKFAuaFYoIkJhZCBpbmRleCAiK2Mr
-IiBmb3IgIitiLncoMCkpKX0sCldlOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbyxuLG0s
-bCxrLGoKaWYoYj09PWQpcmV0dXJuITAKaWYoIUguQTgoZCkpaWYoIShkPT09dC5fKSlzPWQ9PT10LksK
-ZWxzZSBzPSEwCmVsc2Ugcz0hMAppZihzKXJldHVybiEwCnI9Yi55CmlmKHI9PT00KXJldHVybiEwCmlm
-KEguQTgoYikpcmV0dXJuITEKaWYoYi55IT09MSlzPWI9PT10LlB8fGI9PT10LlQKZWxzZSBzPSEwCmlm
-KHMpcmV0dXJuITAKcT1yPT09MTMKaWYocSlpZihILldlKGEsY1tiLnpdLGMsZCxlKSlyZXR1cm4hMApw
-PWQueQppZihyPT09NilyZXR1cm4gSC5XZShhLGIueixjLGQsZSkKaWYocD09PTYpe3M9ZC56CnJldHVy
-biBILldlKGEsYixjLHMsZSl9aWYocj09PTgpe2lmKCFILldlKGEsYi56LGMsZCxlKSlyZXR1cm4hMQpy
-ZXR1cm4gSC5XZShhLEgueFooYSxiKSxjLGQsZSl9aWYocj09PTcpe3M9SC5XZShhLGIueixjLGQsZSkK
-cmV0dXJuIHN9aWYocD09PTgpe2lmKEguV2UoYSxiLGMsZC56LGUpKXJldHVybiEwCnJldHVybiBILldl
-KGEsYixjLEgueFooYSxkKSxlKX1pZihwPT09Nyl7cz1ILldlKGEsYixjLGQueixlKQpyZXR1cm4gc31p
-ZihxKXJldHVybiExCnM9ciE9PTExCmlmKCghc3x8cj09PTEyKSYmZD09PXQuWSlyZXR1cm4hMAppZihw
-PT09MTIpe2lmKGI9PT10LkQpcmV0dXJuITAKaWYociE9PTEyKXJldHVybiExCm89Yi5RCm49ZC5RCm09
-by5sZW5ndGgKaWYobSE9PW4ubGVuZ3RoKXJldHVybiExCmM9Yz09bnVsbD9vOm8uY29uY2F0KGMpCmU9
-ZT09bnVsbD9uOm4uY29uY2F0KGUpCmZvcihsPTA7bDxtOysrbCl7az1vW2xdCmo9bltsXQppZighSC5X
-ZShhLGssYyxqLGUpfHwhSC5XZShhLGosZSxrLGMpKXJldHVybiExfXJldHVybiBILmJPKGEsYi56LGMs
-ZC56LGUpfWlmKHA9PT0xMSl7aWYoYj09PXQuRClyZXR1cm4hMAppZihzKXJldHVybiExCnJldHVybiBI
-LmJPKGEsYixjLGQsZSl9aWYocj09PTkpe2lmKHAhPT05KXJldHVybiExCnJldHVybiBILnBHKGEsYixj
-LGQsZSl9cmV0dXJuITF9LApiTzpmdW5jdGlvbihhMixhMyxhNCxhNSxhNil7dmFyIHMscixxLHAsbyxu
-LG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGEsYTAsYTEKaWYoIUguV2UoYTIsYTMueixhNCxhNS56LGE2
-KSlyZXR1cm4hMQpzPWEzLlEKcj1hNS5RCnE9cy5hCnA9ci5hCm89cS5sZW5ndGgKbj1wLmxlbmd0aApp
-ZihvPm4pcmV0dXJuITEKbT1uLW8KbD1zLmIKaz1yLmIKaj1sLmxlbmd0aAppPWsubGVuZ3RoCmlmKG8r
-ajxuK2kpcmV0dXJuITEKZm9yKGg9MDtoPG87KytoKXtnPXFbaF0KaWYoIUguV2UoYTIscFtoXSxhNixn
-LGE0KSlyZXR1cm4hMX1mb3IoaD0wO2g8bTsrK2gpe2c9bFtoXQppZighSC5XZShhMixwW28raF0sYTYs
-ZyxhNCkpcmV0dXJuITF9Zm9yKGg9MDtoPGk7KytoKXtnPWxbbStoXQppZighSC5XZShhMixrW2hdLGE2
-LGcsYTQpKXJldHVybiExfWY9cy5jCmU9ci5jCmQ9Zi5sZW5ndGgKYz1lLmxlbmd0aApmb3IoYj0wLGE9
-MDthPGM7YSs9Myl7YTA9ZVthXQpmb3IoOyEwOyl7aWYoYj49ZClyZXR1cm4hMQphMT1mW2JdCmIrPTMK
-aWYoYTA8YTEpcmV0dXJuITEKaWYoYTE8YTApY29udGludWUKZz1mW2ItMV0KaWYoIUguV2UoYTIsZVth
-KzJdLGE2LGcsYTQpKXJldHVybiExCmJyZWFrfX1yZXR1cm4hMH0sCnBHOmZ1bmN0aW9uKGEsYixjLGQs
-ZSl7dmFyIHMscixxLHAsbyxuLG0sbCxrPWIueixqPWQuegppZihrPT09ail7cz1iLlEKcj1kLlEKcT1z
-Lmxlbmd0aApmb3IocD0wO3A8cTsrK3Ape289c1twXQpuPXJbcF0KaWYoIUguV2UoYSxvLGMsbixlKSly
-ZXR1cm4hMX1yZXR1cm4hMH1pZihkPT09dC5LKXJldHVybiEwCm09SC5RbyhhLGspCmlmKG09PW51bGwp
-cmV0dXJuITEKbD1tW2pdCmlmKGw9PW51bGwpcmV0dXJuITEKcT1sLmxlbmd0aApyPWQuUQpmb3IocD0w
-O3A8cTsrK3ApaWYoIUguV2UoYSxILmNFKGEsYixsW3BdKSxjLHJbcF0sZSkpcmV0dXJuITEKcmV0dXJu
-ITB9LApsUjpmdW5jdGlvbihhKXt2YXIgcyxyPWEueQppZighKGE9PT10LlB8fGE9PT10LlQpKWlmKCFI
-LkE4KGEpKWlmKHIhPT03KWlmKCEocj09PTYmJkgubFIoYS56KSkpcz1yPT09OCYmSC5sUihhLnopCmVs
-c2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMApyZXR1cm4gc30sCmNjOmZ1bmN0aW9u
-KGEpe3ZhciBzCmlmKCFILkE4KGEpKWlmKCEoYT09PXQuXykpcz1hPT09dC5LCmVsc2Ugcz0hMAplbHNl
-IHM9ITAKcmV0dXJuIHN9LApBODpmdW5jdGlvbihhKXt2YXIgcz1hLnkKcmV0dXJuIHM9PT0yfHxzPT09
-M3x8cz09PTR8fHM9PT01fHxhPT09dC5XfSwKSXg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9T2JqZWN0
-LmtleXMoYikscD1xLmxlbmd0aApmb3Iocz0wO3M8cDsrK3Mpe3I9cVtzXQphW3JdPWJbcl19fSwKSmM6
-ZnVuY3Rpb24gSmMoYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8ueD1fLnI9Xy5jPW51bGwKXy55
-PTAKXy5jeT1fLmN4PV8uY2g9Xy5RPV8uej1udWxsfSwKRzpmdW5jdGlvbiBHKCl7dGhpcy5jPXRoaXMu
-Yj10aGlzLmE9bnVsbH0sCmxZOmZ1bmN0aW9uIGxZKGEpe3RoaXMuYT1hfSwKa1M6ZnVuY3Rpb24ga1Mo
-KXt9LAppTTpmdW5jdGlvbiBpTShhKXt0aGlzLmE9YX0sClI5OmZ1bmN0aW9uKGEpe3JldHVybiB0Lncu
-YihhKXx8dC5CLmIoYSl8fHQuZHouYihhKXx8dC5JLmIoYSl8fHQuQS5iKGEpfHx0Lmc0LmIoYSl8fHQu
-ZzIuYihhKX0sCkpnOmZ1bmN0aW9uKGEpe3JldHVybiB2Lm1hbmdsZWRHbG9iYWxOYW1lc1thXX19LEo9
-ewpRdTpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm57aTphLHA6YixlOmMseDpkfX0sCmtzOmZ1bmN0aW9u
-KGEpe3ZhciBzLHIscSxwLG89YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXQppZihvPT1udWxsKWlmKCQu
-QnY9PW51bGwpe0guWEQoKQpvPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV19aWYobyE9bnVsbCl7cz1v
-LnAKaWYoITE9PT1zKXJldHVybiBvLmkKaWYoITA9PT1zKXJldHVybiBhCnI9T2JqZWN0LmdldFByb3Rv
-dHlwZU9mKGEpCmlmKHM9PT1yKXJldHVybiBvLmkKaWYoby5lPT09cil0aHJvdyBILmIoUC5TWSgiUmV0
-dXJuIGludGVyY2VwdG9yIGZvciAiK0guRWoocyhhLG8pKSkpfXE9YS5jb25zdHJ1Y3RvcgpwPXE9PW51
-bGw/bnVsbDpxW0ouUlAoKV0KaWYocCE9bnVsbClyZXR1cm4gcApwPUgudzMoYSkKaWYocCE9bnVsbCly
-ZXR1cm4gcAppZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gQy5ERwpzPU9iamVjdC5nZXRQcm90
-b3R5cGVPZihhKQppZihzPT1udWxsKXJldHVybiBDLlpRCmlmKHM9PT1PYmplY3QucHJvdG90eXBlKXJl
-dHVybiBDLlpRCmlmKHR5cGVvZiBxPT0iZnVuY3Rpb24iKXtPYmplY3QuZGVmaW5lUHJvcGVydHkocSxK
-LlJQKCkse3ZhbHVlOkMudkIsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJs
-ZTp0cnVlfSkKcmV0dXJuIEMudkJ9cmV0dXJuIEMudkJ9LApSUDpmdW5jdGlvbigpe3ZhciBzPSQuem0K
-cmV0dXJuIHM9PW51bGw/JC56bT12LmdldElzb2xhdGVUYWcoIl8kZGFydF9qcyIpOnN9LApRaTpmdW5j
-dGlvbihhLGIpe2lmKGE8MHx8YT40Mjk0OTY3Mjk1KXRocm93IEguYihQLlRFKGEsMCw0Mjk0OTY3Mjk1
-LCJsZW5ndGgiLG51bGwpKQpyZXR1cm4gSi5weShuZXcgQXJyYXkoYSksYil9LApLaDpmdW5jdGlvbihh
-LGIpe2lmKGE8MCl0aHJvdyBILmIoUC54WSgiTGVuZ3RoIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50
-ZWdlcjogIithKSkKcmV0dXJuIEguVk0obmV3IEFycmF5KGEpLGIuQygiamQ8MD4iKSl9LApweTpmdW5j
-dGlvbihhLGIpe3JldHVybiBKLkVwKEguVk0oYSxiLkMoImpkPDA+IikpLGIpfSwKRXA6ZnVuY3Rpb24o
-YSxiKXthLmZpeGVkJGxlbmd0aD1BcnJheQpyZXR1cm4gYX0sCnpDOmZ1bmN0aW9uKGEpe2EuZml4ZWQk
-bGVuZ3RoPUFycmF5CmEuaW1tdXRhYmxlJGxpc3Q9QXJyYXkKcmV0dXJuIGF9LApHYTpmdW5jdGlvbihh
-KXtpZihhPDI1Nilzd2l0Y2goYSl7Y2FzZSA5OmNhc2UgMTA6Y2FzZSAxMTpjYXNlIDEyOmNhc2UgMTM6
-Y2FzZSAzMjpjYXNlIDEzMzpjYXNlIDE2MDpyZXR1cm4hMApkZWZhdWx0OnJldHVybiExfXN3aXRjaChh
-KXtjYXNlIDU3NjA6Y2FzZSA4MTkyOmNhc2UgODE5MzpjYXNlIDgxOTQ6Y2FzZSA4MTk1OmNhc2UgODE5
-NjpjYXNlIDgxOTc6Y2FzZSA4MTk4OmNhc2UgODE5OTpjYXNlIDgyMDA6Y2FzZSA4MjAxOmNhc2UgODIw
-MjpjYXNlIDgyMzI6Y2FzZSA4MjMzOmNhc2UgODIzOTpjYXNlIDgyODc6Y2FzZSAxMjI4ODpjYXNlIDY1
-Mjc5OnJldHVybiEwCmRlZmF1bHQ6cmV0dXJuITF9fSwKbW06ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmZv
-cihzPWEubGVuZ3RoO2I8czspe3I9Qy54Qi5XKGEsYikKaWYociE9PTMyJiZyIT09MTMmJiFKLkdhKHIp
-KWJyZWFrOysrYn1yZXR1cm4gYn0sCmMxOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpmb3IoO2I+MDtiPXMp
-e3M9Yi0xCnI9Qy54Qi5PMihhLHMpCmlmKHIhPT0zMiYmciE9PTEzJiYhSi5HYShyKSlicmVha31yZXR1
-cm4gYn0sClRKOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gSi5xSS5wcm90
-b3R5cGUKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxs
-KXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLmpkLnByb3RvdHlwZQppZih0
-eXBlb2YgYSE9Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBKLmM1LnByb3Rv
-dHlwZQpyZXR1cm4gYX1pZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0s
-ClU2OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUK
-aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90
-b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4g
-Si5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJu
-IEoua3MoYSl9LApZRTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVybiBhCmlmKHR5cGVvZiBhIT0i
-b2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVy
-biBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJldHVybiBKLmtzKGEpfSwKaWE6ZnVuY3Rp
-b24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXtpZihNYXRoLmZsb29yKGEpPT1hKXJldHVybiBKLmJV
-LnByb3RvdHlwZQpyZXR1cm4gSi5WQS5wcm90b3R5cGV9aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVy
-biBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBKLndlLnByb3RvdHlwZQppZih0eXBlb2Yg
-YT09ImJvb2xlYW4iKXJldHVybiBKLnlFLnByb3RvdHlwZQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSly
-ZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1
-bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgp
-cmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApyWTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmlu
-ZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoIShhIGluc3RhbmNl
-b2YgUC5NaCkpcmV0dXJuIEoua2QucHJvdG90eXBlCnJldHVybiBhfSwKdmQ6ZnVuY3Rpb24oYSl7aWYo
-dHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBKLnFJLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBh
-CmlmKCEoYSBpbnN0YW5jZW9mIFAuTWgpKXJldHVybiBKLmtkLnByb3RvdHlwZQpyZXR1cm4gYX0sCncx
-OmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIGEKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0
-dXJuIEouamQucHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5j
-dGlvbiIpcmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJl
-dHVybiBhCnJldHVybiBKLmtzKGEpfSwKQTU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi53MShhKS5lUihh
-LGIpfSwKRWg6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLllFKGEpLm1LKGEsYixjKX0sCkVsOmZ1bmN0
-aW9uKGEsYil7cmV0dXJuIEoudzEoYSkuZHIoYSxiKX0sCkY3OmZ1bmN0aW9uKGEpe3JldHVybiBKLlU2
-KGEpLmdvcihhKX0sCkZMOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclkoYSkuZGQoYSxiKX0sCkdBOmZ1
-bmN0aW9uKGEsYil7cmV0dXJuIEoudzEoYSkuRShhLGIpfSwKSG06ZnVuY3Rpb24oYSl7cmV0dXJuIEou
-VTYoYSkuZ0EoYSl9LApJVDpmdW5jdGlvbihhKXtyZXR1cm4gSi53MShhKS5nbShhKX0sCkp5OmZ1bmN0
-aW9uKGEsYil7cmV0dXJuIEouaWEoYSkuZTcoYSxiKX0sCktWOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEou
-clkoYSkueW4oYSxiKX0sCkx0OmZ1bmN0aW9uKGEpe3JldHVybiBKLllFKGEpLndnKGEpfSwKTTE6ZnVu
-Y3Rpb24oYSxiLGMpe3JldHVybiBKLncxKGEpLkUyKGEsYixjKX0sCk11OmZ1bmN0aW9uKGEsYil7cmV0
-dXJuIEouWUUoYSkuc24oYSxiKX0sClF6OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclkoYSkuVyhhLGIp
-fSwKUk06ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVybiBiPT1udWxsCmlmKHR5cGVvZiBhIT0i
-b2JqZWN0IilyZXR1cm4gYiE9bnVsbCYmYT09PWIKcmV0dXJuIEouaWEoYSkuRE4oYSxiKX0sClJYOmZ1
-bmN0aW9uKGEpe3JldHVybiBKLncxKGEpLmJyKGEpfSwKVDA6ZnVuY3Rpb24oYSl7cmV0dXJuIEouclko
-YSkuYlMoYSl9LApWdTpmdW5jdGlvbihhKXtyZXR1cm4gSi52ZChhKS56UShhKX0sCmE2OmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIEouclkoYSkuTzIoYSxiKX0sCmJUOmZ1bmN0aW9uKGEpe3JldHVybiBKLllFKGEp
-LkQ0KGEpfSwKYmI6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYT09Im51bWJlciImJnR5cGVvZiBiPT0i
-bnVtYmVyIilyZXR1cm4gYStiCnJldHVybiBKLlRKKGEpLmgoYSxiKX0sCmNIOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBKLnJZKGEpLmhjKGEpfSwKZFI6ZnVuY3Rpb24oYSl7cmV0dXJuIEouWUUoYSkuZ24oYSl9LApk
-WjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5ZRShhKS5PbihhLGIsYyxkKX0sCmRnOmZ1bmN0aW9u
-KGEsYixjLGQpe3JldHVybiBKLnJZKGEpLmk3KGEsYixjLGQpfSwKZGg6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEouWUUoYSkuRkYoYSl9LApkcjpmdW5jdGlvbihhLGIpe3JldHVybiBKLllFKGEpLnNhNChhLGIpfSwK
-aGY6ZnVuY3Rpb24oYSl7cmV0dXJuIEouaWEoYSkuZ2lPKGEpfSwKaWc6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEouWUUoYSkuZ1FnKGEpfSwKajpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS53KGEpfSwKbDU6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gSi5ZRShhKS5zaGYoYSxiKX0sCmxkOmZ1bmN0aW9uKGEsYixjKXtyZXR1
-cm4gSi5yWShhKS5OaihhLGIsYyl9LApwNDpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLlRjKGEs
-Yil9LApxMDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouclkoYSkuUWkoYSxiLGMpfSwKcUY6ZnVuY3Rp
-b24oYSl7cmV0dXJuIEouWUUoYSkuZ1ZsKGEpfSwKdEg6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLllF
-KGEpLnBrKGEsYixjKX0sCnU5OmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi53MShhKS5ZNShhLGIsYyl9
-LAp1VTpmdW5jdGlvbihhKXtyZXR1cm4gSi5VNihhKS5nbDAoYSl9LAp3ZjpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBKLllFKGEpLnNSTihhLGIpfSwKeDk6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYj09PSJudW1i
-ZXIiKWlmKGEuY29uc3RydWN0b3I9PUFycmF5fHx0eXBlb2YgYT09InN0cmluZyJ8fEgud1YoYSxhW3Yu
-ZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdKSlpZihiPj4+MD09PWImJmI8YS5sZW5ndGgpcmV0dXJuIGFbYl0K
-cmV0dXJuIEouVTYoYSkucShhLGIpfSwKemw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5VNihhKS50Zyhh
-LGIpfSwKR3Y6ZnVuY3Rpb24gR3YoKXt9LAp5RTpmdW5jdGlvbiB5RSgpe30sCndlOmZ1bmN0aW9uIHdl
-KCl7fSwKTUY6ZnVuY3Rpb24gTUYoKXt9LAppQzpmdW5jdGlvbiBpQygpe30sCmtkOmZ1bmN0aW9uIGtk
-KCl7fSwKYzU6ZnVuY3Rpb24gYzUoKXt9LApqZDpmdW5jdGlvbiBqZChhKXt0aGlzLiR0aT1hfSwKUG86
-ZnVuY3Rpb24gUG8oYSl7dGhpcy4kdGk9YX0sCm0xOmZ1bmN0aW9uIG0xKGEsYixjKXt2YXIgXz10aGlz
-Cl8uYT1hCl8uYj1iCl8uYz0wCl8uZD1udWxsCl8uJHRpPWN9LApxSTpmdW5jdGlvbiBxSSgpe30sCmJV
-OmZ1bmN0aW9uIGJVKCl7fSwKVkE6ZnVuY3Rpb24gVkEoKXt9LApEcjpmdW5jdGlvbiBEcigpe319LFA9
-ewpPajpmdW5jdGlvbigpe3ZhciBzLHIscT17fQppZihzZWxmLnNjaGVkdWxlSW1tZWRpYXRlIT1udWxs
-KXJldHVybiBQLkVYKCkKaWYoc2VsZi5NdXRhdGlvbk9ic2VydmVyIT1udWxsJiZzZWxmLmRvY3VtZW50
-IT1udWxsKXtzPXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2IikKcj1zZWxmLmRvY3VtZW50
-LmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpxLmE9bnVsbApuZXcgc2VsZi5NdXRhdGlvbk9ic2VydmVyKEgu
-dFIobmV3IFAudGgocSksMSkpLm9ic2VydmUocyx7Y2hpbGRMaXN0OnRydWV9KQpyZXR1cm4gbmV3IFAu
-aGEocSxzLHIpfWVsc2UgaWYoc2VsZi5zZXRJbW1lZGlhdGUhPW51bGwpcmV0dXJuIFAueXQoKQpyZXR1
-cm4gUC5xVygpfSwKWlY6ZnVuY3Rpb24oYSl7c2VsZi5zY2hlZHVsZUltbWVkaWF0ZShILnRSKG5ldyBQ
-LlZzKHQuTS5hKGEpKSwwKSl9LApvQTpmdW5jdGlvbihhKXtzZWxmLnNldEltbWVkaWF0ZShILnRSKG5l
-dyBQLkZ0KHQuTS5hKGEpKSwwKSl9LApCejpmdW5jdGlvbihhKXt0Lk0uYShhKQpQLlFOKDAsYSl9LApR
-TjpmdW5jdGlvbihhLGIpe3ZhciBzPW5ldyBQLlczKCkKcy5DWShhLGIpCnJldHVybiBzfSwKRlg6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIG5ldyBQLmloKG5ldyBQLnZzKCQuWDMsYS5DKCJ2czwwPiIpKSxhLkMoImlo
-PDA+IikpfSwKREk6ZnVuY3Rpb24oYSxiKXthLiQyKDAsbnVsbCkKYi5iPSEwCnJldHVybiBiLmF9LApq
-UTpmdW5jdGlvbihhLGIpe1AuSmUoYSxiKX0sCnlDOmZ1bmN0aW9uKGEsYil7Yi5hTSgwLGEpfSwKZjM6
-ZnVuY3Rpb24oYSxiKXtiLncwKEguUnUoYSksSC50cyhhKSl9LApKZTpmdW5jdGlvbihhLGIpe3ZhciBz
-LHIscT1uZXcgUC5XTShiKSxwPW5ldyBQLlNYKGIpCmlmKGEgaW5zdGFuY2VvZiBQLnZzKWEuUWQocSxw
-LHQueikKZWxzZXtzPXQuegppZih0LmQuYihhKSlhLlNxKHEscCxzKQplbHNle3I9bmV3IFAudnMoJC5Y
-Myx0LmMpCnIuYT00CnIuYz1hCnIuUWQocSxwLHMpfX19LApsejpmdW5jdGlvbihhKXt2YXIgcz1mdW5j
-dGlvbihiLGMpe3JldHVybiBmdW5jdGlvbihkLGUpe3doaWxlKHRydWUpdHJ5e2IoZCxlKQpicmVha31j
-YXRjaChyKXtlPXIKZD1jfX19KGEsMSkKcmV0dXJuICQuWDMuTGoobmV3IFAuR3MocyksdC5ILHQuUyx0
-LnopfSwKSUc6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkZ5KGEsMSl9LApUaDpmdW5jdGlvbigpe3Jl
-dHVybiBDLndRfSwKWW06ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkZ5KGEsMyl9LApsMDpmdW5jdGlv
-bihhLGIpe3JldHVybiBuZXcgUC5xNChhLGIuQygicTQ8MD4iKSl9LAprMzpmdW5jdGlvbihhLGIpe3Zh
-ciBzLHIscQpiLmE9MQp0cnl7YS5TcShuZXcgUC5wVihiKSxuZXcgUC5VNyhiKSx0LlApfWNhdGNoKHEp
-e3M9SC5SdShxKQpyPUgudHMocSkKUC5yYihuZXcgUC52cihiLHMscikpfX0sCkE5OmZ1bmN0aW9uKGEs
-Yil7dmFyIHMscixxCmZvcihzPXQuYztyPWEuYSxyPT09MjspYT1zLmEoYS5jKQppZihyPj00KXtxPWIu
-YWgoKQpiLmE9YS5hCmIuYz1hLmMKUC5IWihiLHEpfWVsc2V7cT10LkYuYShiLmMpCmIuYT0yCmIuYz1h
-CmEualEocSl9fSwKSFo6ZnVuY3Rpb24oYTAsYTEpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxn
-LGYsZSxkLGM9bnVsbCxiPXt9LGE9Yi5hPWEwCmZvcihzPXQubixyPXQuRixxPXQuZDshMDspe3A9e30K
-bz1hLmE9PT04CmlmKGExPT1udWxsKXtpZihvKXtuPXMuYShhLmMpClAuTDIoYyxjLGEuYixuLmEsbi5i
-KX1yZXR1cm59cC5hPWExCm09YTEuYQpmb3IoYT1hMTttIT1udWxsO2E9bSxtPWwpe2EuYT1udWxsClAu
-SFooYi5hLGEpCnAuYT1tCmw9bS5hfWs9Yi5hCmo9ay5jCnAuYj1vCnAuYz1qCmk9IW8KaWYoaSl7aD1h
-LmMKaD0oaCYxKSE9PTB8fChoJjE1KT09PTh9ZWxzZSBoPSEwCmlmKGgpe2c9YS5iLmIKaWYobyl7aD1r
-LmI9PT1nCmg9IShofHxoKX1lbHNlIGg9ITEKaWYoaCl7cy5hKGopClAuTDIoYyxjLGsuYixqLmEsai5i
-KQpyZXR1cm59Zj0kLlgzCmlmKGYhPT1nKSQuWDM9ZwplbHNlIGY9YwphPWEuYwppZigoYSYxNSk9PT04
-KW5ldyBQLlJUKHAsYixvKS4kMCgpCmVsc2UgaWYoaSl7aWYoKGEmMSkhPT0wKW5ldyBQLnJxKHAsaiku
-JDAoKX1lbHNlIGlmKChhJjIpIT09MCluZXcgUC5SVyhiLHApLiQwKCkKaWYoZiE9bnVsbCkkLlgzPWYK
-YT1wLmMKaWYocS5iKGEpKXtlPXAuYS5iCmlmKGEuYT49NCl7ZD1yLmEoZS5jKQplLmM9bnVsbAphMT1l
-Lk44KGQpCmUuYT1hLmEKZS5jPWEuYwpiLmE9YQpjb250aW51ZX1lbHNlIFAuQTkoYSxlKQpyZXR1cm59
-fWU9cC5hLmIKZD1yLmEoZS5jKQplLmM9bnVsbAphMT1lLk44KGQpCmE9cC5iCms9cC5jCmlmKCFhKXtl
-LiR0aS5jLmEoaykKZS5hPTQKZS5jPWt9ZWxzZXtzLmEoaykKZS5hPTgKZS5jPWt9Yi5hPWUKYT1lfX0s
-ClZIOmZ1bmN0aW9uKGEsYil7dmFyIHMKaWYodC5hZy5iKGEpKXJldHVybiBiLkxqKGEsdC56LHQuSyx0
-LmwpCnM9dC5iSQppZihzLmIoYSkpcmV0dXJuIHMuYShhKQp0aHJvdyBILmIoUC5MMyhhLCJvbkVycm9y
-IiwiRXJyb3IgaGFuZGxlciBtdXN0IGFjY2VwdCBvbmUgT2JqZWN0IG9yIG9uZSBPYmplY3QgYW5kIGEg
-U3RhY2tUcmFjZSBhcyBhcmd1bWVudHMsIGFuZCByZXR1cm4gYSBhIHZhbGlkIHJlc3VsdCIpKX0sCnB1
-OmZ1bmN0aW9uKCl7dmFyIHMscgpmb3Iocz0kLlM2O3MhPW51bGw7cz0kLlM2KXskLm1nPW51bGwKcj1z
-LmIKJC5TNj1yCmlmKHI9PW51bGwpJC5rOD1udWxsCnMuYS4kMCgpfX0sCmVOOmZ1bmN0aW9uKCl7JC5V
-RD0hMAp0cnl7UC5wdSgpfWZpbmFsbHl7JC5tZz1udWxsCiQuVUQ9ITEKaWYoJC5TNiE9bnVsbCkkLnV0
-KCkuJDEoUC5VSSgpKX19LAplVzpmdW5jdGlvbihhKXt2YXIgcz1uZXcgUC5PTShhKSxyPSQuazgKaWYo
-cj09bnVsbCl7JC5TNj0kLms4PXMKaWYoISQuVUQpJC51dCgpLiQxKFAuVUkoKSl9ZWxzZSAkLms4PXIu
-Yj1zfSwKclI6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9JC5TNgppZihwPT1udWxsKXtQLmVXKGEpCiQu
-bWc9JC5rOApyZXR1cm59cz1uZXcgUC5PTShhKQpyPSQubWcKaWYocj09bnVsbCl7cy5iPXAKJC5TNj0k
-Lm1nPXN9ZWxzZXtxPXIuYgpzLmI9cQokLm1nPXIuYj1zCmlmKHE9PW51bGwpJC5rOD1zfX0sCnJiOmZ1
-bmN0aW9uKGEpe3ZhciBzPW51bGwscj0kLlgzCmlmKEMuTlU9PT1yKXtQLlRrKHMscyxDLk5VLGEpCnJl
-dHVybn1QLlRrKHMscyxyLHQuTS5hKHIudDgoYSkpKX0sClF3OmZ1bmN0aW9uKGEsYil7SC5jYihhLCJz
-dHJlYW0iLHQuSykKcmV0dXJuIG5ldyBQLnhJKGIuQygieEk8MD4iKSl9LApUbDpmdW5jdGlvbihhLGIp
-e3ZhciBzPUguY2IoYSwiZXJyb3IiLHQuSykKcmV0dXJuIG5ldyBQLkN3KHMsYj09bnVsbD9QLnYwKGEp
-OmIpfSwKdjA6ZnVuY3Rpb24oYSl7dmFyIHMKaWYodC5yLmIoYSkpe3M9YS5nSUkoKQppZihzIT1udWxs
-KXJldHVybiBzfXJldHVybiBDLnBkfSwKTDI6ZnVuY3Rpb24oYSxiLGMsZCxlKXtQLnJSKG5ldyBQLnBL
-KGQsZSkpfSwKVDg6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyPSQuWDMKaWYocj09PWMpcmV0dXJu
-IGQuJDAoKQokLlgzPWMKcz1yCnRyeXtyPWQuJDAoKQpyZXR1cm4gcn1maW5hbGx5eyQuWDM9c319LAp5
-djpmdW5jdGlvbihhLGIsYyxkLGUsZixnKXt2YXIgcyxyPSQuWDMKaWYocj09PWMpcmV0dXJuIGQuJDEo
-ZSkKJC5YMz1jCnM9cgp0cnl7cj1kLiQxKGUpCnJldHVybiByfWZpbmFsbHl7JC5YMz1zfX0sClF4OmZ1
-bmN0aW9uKGEsYixjLGQsZSxmLGcsaCxpKXt2YXIgcyxyPSQuWDMKaWYocj09PWMpcmV0dXJuIGQuJDIo
-ZSxmKQokLlgzPWMKcz1yCnRyeXtyPWQuJDIoZSxmKQpyZXR1cm4gcn1maW5hbGx5eyQuWDM9c319LApU
-azpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcwp0Lk0uYShkKQpzPUMuTlUhPT1jCmlmKHMpZD0hKCFzfHwh
-MSk/Yy50OChkKTpjLlJUKGQsdC5IKQpQLmVXKGQpfSwKdGg6ZnVuY3Rpb24gdGgoYSl7dGhpcy5hPWF9
-LApoYTpmdW5jdGlvbiBoYShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApWczpmdW5j
-dGlvbiBWcyhhKXt0aGlzLmE9YX0sCkZ0OmZ1bmN0aW9uIEZ0KGEpe3RoaXMuYT1hfSwKVzM6ZnVuY3Rp
-b24gVzMoKXt9LAp5SDpmdW5jdGlvbiB5SChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKaWg6ZnVuY3Rp
-b24gaWgoYSxiKXt0aGlzLmE9YQp0aGlzLmI9ITEKdGhpcy4kdGk9Yn0sCldNOmZ1bmN0aW9uIFdNKGEp
-e3RoaXMuYT1hfSwKU1g6ZnVuY3Rpb24gU1goYSl7dGhpcy5hPWF9LApHczpmdW5jdGlvbiBHcyhhKXt0
-aGlzLmE9YX0sCkZ5OmZ1bmN0aW9uIEZ5KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApHVjpmdW5jdGlv
-biBHVihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5kPV8uYz1fLmI9bnVsbApfLiR0aT1ifSwKcTQ6ZnVu
-Y3Rpb24gcTQoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKUGY6ZnVuY3Rpb24gUGYoKXt9LApaZjpm
-dW5jdGlvbiBaZihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApGZTpmdW5jdGlvbiBGZShhLGIsYyxk
-LGUpe3ZhciBfPXRoaXMKXy5hPW51bGwKXy5iPWEKXy5jPWIKXy5kPWMKXy5lPWQKXy4kdGk9ZX0sCnZz
-OmZ1bmN0aW9uIHZzKGEsYil7dmFyIF89dGhpcwpfLmE9MApfLmI9YQpfLmM9bnVsbApfLiR0aT1ifSwK
-ZGE6ZnVuY3Rpb24gZGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCm9ROmZ1bmN0aW9uIG9RKGEsYil7
-dGhpcy5hPWEKdGhpcy5iPWJ9LApwVjpmdW5jdGlvbiBwVihhKXt0aGlzLmE9YX0sClU3OmZ1bmN0aW9u
-IFU3KGEpe3RoaXMuYT1hfSwKdnI6ZnVuY3Rpb24gdnIoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRo
-aXMuYz1jfSwKcnQ6ZnVuY3Rpb24gcnQoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCktGOmZ1bmN0aW9u
-IEtGKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApaTDpmdW5jdGlvbiBaTChhLGIsYyl7dGhpcy5hPWEK
-dGhpcy5iPWIKdGhpcy5jPWN9LApSVDpmdW5jdGlvbiBSVChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIK
-dGhpcy5jPWN9LApqWjpmdW5jdGlvbiBqWihhKXt0aGlzLmE9YX0sCnJxOmZ1bmN0aW9uIHJxKGEsYil7
-dGhpcy5hPWEKdGhpcy5iPWJ9LApSVzpmdW5jdGlvbiBSVyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwK
-T006ZnVuY3Rpb24gT00oYSl7dGhpcy5hPWEKdGhpcy5iPW51bGx9LApxaDpmdW5jdGlvbiBxaCgpe30s
-CkI1OmZ1bmN0aW9uIEI1KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp1TzpmdW5jdGlvbiB1TyhhLGIp
-e3RoaXMuYT1hCnRoaXMuYj1ifSwKTU86ZnVuY3Rpb24gTU8oKXt9LAprVDpmdW5jdGlvbiBrVCgpe30s
-CnhJOmZ1bmN0aW9uIHhJKGEpe3RoaXMuJHRpPWF9LApDdzpmdW5jdGlvbiBDdyhhLGIpe3RoaXMuYT1h
-CnRoaXMuYj1ifSwKbTA6ZnVuY3Rpb24gbTAoKXt9LApwSzpmdW5jdGlvbiBwSyhhLGIpe3RoaXMuYT1h
-CnRoaXMuYj1ifSwKSmk6ZnVuY3Rpb24gSmkoKXt9LApoajpmdW5jdGlvbiBoaihhLGIsYyl7dGhpcy5h
-PWEKdGhpcy5iPWIKdGhpcy5jPWN9LApWcDpmdW5jdGlvbiBWcChhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
-fSwKT1I6ZnVuY3Rpb24gT1IoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKRUY6ZnVu
-Y3Rpb24oYSxiLGMpe3JldHVybiBiLkMoIkA8MD4iKS5LcShjKS5DKCJGbzwxLDI+IikuYShILkI3KGEs
-bmV3IEguTjUoYi5DKCJAPDA+IikuS3EoYykuQygiTjU8MSwyPiIpKSkpfSwKRmw6ZnVuY3Rpb24oYSxi
-KXtyZXR1cm4gbmV3IEguTjUoYS5DKCJAPDA+IikuS3EoYikuQygiTjU8MSwyPiIpKX0sCkxzOmZ1bmN0
-aW9uKGEpe3JldHVybiBuZXcgUC5iNihhLkMoImI2PDA+IikpfSwKVDI6ZnVuY3Rpb24oKXt2YXIgcz1P
-YmplY3QuY3JlYXRlKG51bGwpCnNbIjxub24taWRlbnRpZmllci1rZXk+Il09cwpkZWxldGUgc1siPG5v
-bi1pZGVudGlmaWVyLWtleT4iXQpyZXR1cm4gc30sCnJqOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1uZXcg
-UC5sbShhLGIsYy5DKCJsbTwwPiIpKQpzLmM9YS5lCnJldHVybiBzfSwKRVA6ZnVuY3Rpb24oYSxiLGMp
-e3ZhciBzLHIKaWYoUC5oQihhKSl7aWYoYj09PSIoIiYmYz09PSIpIilyZXR1cm4iKC4uLikiCnJldHVy
-biBiKyIuLi4iK2N9cz1ILlZNKFtdLHQucykKQy5ObS5pKCQueGcsYSkKdHJ5e1AuVnIoYSxzKX1maW5h
-bGx5e2lmKDA+PSQueGcubGVuZ3RoKXJldHVybiBILk9IKCQueGcsLTEpCiQueGcucG9wKCl9cj1QLnZn
-KGIsdC51LmEocyksIiwgIikrYwpyZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn0sCldFOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgcyxyCmlmKFAuaEIoYSkpcmV0dXJuIGIrIi4uLiIrYwpzPW5ldyBQLlJuKGIp
-CkMuTm0uaSgkLnhnLGEpCnRyeXtyPXMKci5hPVAudmcoci5hLGEsIiwgIil9ZmluYWxseXtpZigwPj0k
-LnhnLmxlbmd0aClyZXR1cm4gSC5PSCgkLnhnLC0xKQokLnhnLnBvcCgpfXMuYSs9YwpyPXMuYQpyZXR1
-cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn0sCmhCOmZ1bmN0aW9uKGEpe3ZhciBzLHIKZm9yKHM9JC54
-Zy5sZW5ndGgscj0wO3I8czsrK3IpaWYoYT09PSQueGdbcl0pcmV0dXJuITAKcmV0dXJuITF9LApWcjpm
-dW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtLGw9YS5nbShhKSxrPTAsaj0wCndoaWxlKCEwKXtp
-ZighKGs8ODB8fGo8MykpYnJlYWsKaWYoIWwuRigpKXJldHVybgpzPUguRWoobC5nbCgpKQpDLk5tLmko
-YixzKQprKz1zLmxlbmd0aCsyOysran1pZighbC5GKCkpe2lmKGo8PTUpcmV0dXJuCmlmKDA+PWIubGVu
-Z3RoKXJldHVybiBILk9IKGIsLTEpCnI9Yi5wb3AoKQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChi
-LC0xKQpxPWIucG9wKCl9ZWxzZXtwPWwuZ2woKTsrK2oKaWYoIWwuRigpKXtpZihqPD00KXtDLk5tLmko
-YixILkVqKHApKQpyZXR1cm59cj1ILkVqKHApCmlmKDA+PWIubGVuZ3RoKXJldHVybiBILk9IKGIsLTEp
-CnE9Yi5wb3AoKQprKz1yLmxlbmd0aCsyfWVsc2V7bz1sLmdsKCk7KytqCmZvcig7bC5GKCk7cD1vLG89
-bil7bj1sLmdsKCk7KytqCmlmKGo+MTAwKXt3aGlsZSghMCl7aWYoIShrPjc1JiZqPjMpKWJyZWFrCmlm
-KDA+PWIubGVuZ3RoKXJldHVybiBILk9IKGIsLTEpCmstPWIucG9wKCkubGVuZ3RoKzI7LS1qfUMuTm0u
-aShiLCIuLi4iKQpyZXR1cm59fXE9SC5FaihwKQpyPUguRWoobykKays9ci5sZW5ndGgrcS5sZW5ndGgr
-NH19aWYoaj5iLmxlbmd0aCsyKXtrKz01Cm09Ii4uLiJ9ZWxzZSBtPW51bGwKd2hpbGUoITApe2lmKCEo
-az44MCYmYi5sZW5ndGg+MykpYnJlYWsKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKay09
-Yi5wb3AoKS5sZW5ndGgrMgppZihtPT1udWxsKXtrKz01Cm09Ii4uLiJ9fWlmKG0hPW51bGwpQy5ObS5p
-KGIsbSkKQy5ObS5pKGIscSkKQy5ObS5pKGIscil9LAp0TTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT1Q
-LkxzKGIpCmZvcihzPWEubGVuZ3RoLHI9MDtyPGEubGVuZ3RoO2EubGVuZ3RoPT09c3x8KDAsSC5sayko
-YSksKytyKXEuaSgwLGIuYShhW3JdKSkKcmV0dXJuIHF9LApuTzpmdW5jdGlvbihhKXt2YXIgcyxyPXt9
-CmlmKFAuaEIoYSkpcmV0dXJuInsuLi59IgpzPW5ldyBQLlJuKCIiKQp0cnl7Qy5ObS5pKCQueGcsYSkK
-cy5hKz0ieyIKci5hPSEwCmEuSygwLG5ldyBQLnJhKHIscykpCnMuYSs9In0ifWZpbmFsbHl7aWYoMD49
-JC54Zy5sZW5ndGgpcmV0dXJuIEguT0goJC54ZywtMSkKJC54Zy5wb3AoKX1yPXMuYQpyZXR1cm4gci5j
-aGFyQ29kZUF0KDApPT0wP3I6cn0sCmI2OmZ1bmN0aW9uIGI2KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5m
-PV8uZT1fLmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LApibjpmdW5jdGlvbiBibihhKXt0aGlz
-LmE9YQp0aGlzLmM9dGhpcy5iPW51bGx9LApsbTpmdW5jdGlvbiBsbShhLGIsYyl7dmFyIF89dGhpcwpf
-LmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGwKXy4kdGk9Y30sCm1XOmZ1bmN0aW9uIG1XKCl7fSwKdXk6ZnVu
-Y3Rpb24gdXkoKXt9LApsRDpmdW5jdGlvbiBsRCgpe30sCmlsOmZ1bmN0aW9uIGlsKCl7fSwKcmE6ZnVu
-Y3Rpb24gcmEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCllrOmZ1bmN0aW9uIFlrKCl7fSwKeVE6ZnVu
-Y3Rpb24geVEoYSl7dGhpcy5hPWF9LApLUDpmdW5jdGlvbiBLUCgpe30sClBuOmZ1bmN0aW9uIFBuKCl7
-fSwKR2o6ZnVuY3Rpb24gR2ooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKbGY6ZnVuY3Rpb24gbGYo
-KXt9LApWajpmdW5jdGlvbiBWaigpe30sClh2OmZ1bmN0aW9uIFh2KCl7fSwKblk6ZnVuY3Rpb24gblko
-KXt9LApXWTpmdW5jdGlvbiBXWSgpe30sClJVOmZ1bmN0aW9uIFJVKCl7fSwKcFI6ZnVuY3Rpb24gcFIo
-KXt9LApCUzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwCmlmKHR5cGVvZiBhIT0ic3RyaW5nIil0aHJv
-dyBILmIoSC50TChhKSkKcz1udWxsCnRyeXtzPUpTT04ucGFyc2UoYSl9Y2F0Y2gocSl7cj1ILlJ1KHEp
-CnA9UC5ycihTdHJpbmcociksbnVsbCxudWxsKQp0aHJvdyBILmIocCl9cD1QLlFlKHMpCnJldHVybiBw
-fSwKUWU6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZih0eXBlb2YgYSE9
-Im9iamVjdCIpcmV0dXJuIGEKaWYoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpIT09QXJyYXkucHJvdG90
-eXBlKXJldHVybiBuZXcgUC51dyhhLE9iamVjdC5jcmVhdGUobnVsbCkpCmZvcihzPTA7czxhLmxlbmd0
-aDsrK3MpYVtzXT1QLlFlKGFbc10pCnJldHVybiBhfSwKa3k6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMs
-cgppZihiIGluc3RhbmNlb2YgVWludDhBcnJheSl7cz1iCmQ9cy5sZW5ndGgKaWYoZC1jPDE1KXJldHVy
-biBudWxsCnI9UC5DRyhhLHMsYyxkKQppZihyIT1udWxsJiZhKWlmKHIuaW5kZXhPZigiXHVmZmZkIik+
-PTApcmV0dXJuIG51bGwKcmV0dXJuIHJ9cmV0dXJuIG51bGx9LApDRzpmdW5jdGlvbihhLGIsYyxkKXt2
-YXIgcz1hPyQuSEcoKTokLnJmKCkKaWYocz09bnVsbClyZXR1cm4gbnVsbAppZigwPT09YyYmZD09PWIu
-bGVuZ3RoKXJldHVybiBQLlJiKHMsYikKcmV0dXJuIFAuUmIocyxiLnN1YmFycmF5KGMsUC5qQihjLGQs
-Yi5sZW5ndGgpKSl9LApSYjpmdW5jdGlvbihhLGIpe3ZhciBzLHIKdHJ5e3M9YS5kZWNvZGUoYikKcmV0
-dXJuIHN9Y2F0Y2gocil7SC5SdShyKX1yZXR1cm4gbnVsbH0sCnhNOmZ1bmN0aW9uKGEsYixjLGQsZSxm
-KXtpZihDLmpuLnpZKGYsNCkhPT0wKXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2NCBwYWRkaW5n
-LCBwYWRkZWQgbGVuZ3RoIG11c3QgYmUgbXVsdGlwbGUgb2YgZm91ciwgaXMgIitmLGEsYykpCmlmKGQr
-ZSE9PWYpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsICc9JyBub3QgYXQgdGhl
-IGVuZCIsYSxiKSkKaWYoZT4yKXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2NCBwYWRkaW5nLCBt
-b3JlIHRoYW4gdHdvICc9JyBjaGFyYWN0ZXJzIixhLGIpKX0sCkd5OmZ1bmN0aW9uKGEsYixjKXtyZXR1
-cm4gbmV3IFAuVWQoYSxiKX0sCk5DOmZ1bmN0aW9uKGEpe3JldHVybiBhLkx0KCl9LApVZzpmdW5jdGlv
-bihhLGIpe3JldHVybiBuZXcgUC50dShhLFtdLFAuQ3koKSl9LAp1WDpmdW5jdGlvbihhLGIsYyl7dmFy
-IHMscj1uZXcgUC5SbigiIikscT1QLlVnKHIsYikKcS5pVShhKQpzPXIuYQpyZXR1cm4gcy5jaGFyQ29k
-ZUF0KDApPT0wP3M6c30sCmo0OmZ1bmN0aW9uKGEpe3N3aXRjaChhKXtjYXNlIDY1OnJldHVybiJNaXNz
-aW5nIGV4dGVuc2lvbiBieXRlIgpjYXNlIDY3OnJldHVybiJVbmV4cGVjdGVkIGV4dGVuc2lvbiBieXRl
-IgpjYXNlIDY5OnJldHVybiJJbnZhbGlkIFVURi04IGJ5dGUiCmNhc2UgNzE6cmV0dXJuIk92ZXJsb25n
-IGVuY29kaW5nIgpjYXNlIDczOnJldHVybiJPdXQgb2YgdW5pY29kZSByYW5nZSIKY2FzZSA3NTpyZXR1
-cm4iRW5jb2RlZCBzdXJyb2dhdGUiCmNhc2UgNzc6cmV0dXJuIlVuZmluaXNoZWQgVVRGLTggb2N0ZXQg
-c2VxdWVuY2UiCmRlZmF1bHQ6cmV0dXJuIiJ9fSwKank6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxw
-PWMtYixvPW5ldyBVaW50OEFycmF5KHApCmZvcihzPUouVTYoYSkscj0wO3I8cDsrK3Ipe3E9cy5xKGEs
-YityKQppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLnpNKCkKaWYoKHEmNDI5NDk2NzA0MCk+
-Pj4wIT09MClxPTI1NQppZihyPj1wKXJldHVybiBILk9IKG8scikKb1tyXT1xfXJldHVybiBvfSwKdXc6
-ZnVuY3Rpb24gdXcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9bnVsbH0sCmk4OmZ1bmN0aW9u
-IGk4KGEpe3RoaXMuYT1hfSwKcGc6ZnVuY3Rpb24gcGcoKXt9LApjMjpmdW5jdGlvbiBjMigpe30sCkNW
-OmZ1bmN0aW9uIENWKCl7fSwKVTg6ZnVuY3Rpb24gVTgoKXt9LApVazpmdW5jdGlvbiBVaygpe30sCndJ
-OmZ1bmN0aW9uIHdJKCl7fSwKWmk6ZnVuY3Rpb24gWmkoKXt9LApVZDpmdW5jdGlvbiBVZChhLGIpe3Ro
-aXMuYT1hCnRoaXMuYj1ifSwKSzg6ZnVuY3Rpb24gSzgoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmJ5
-OmZ1bmN0aW9uIGJ5KCl7fSwKb2o6ZnVuY3Rpb24gb2ooYSl7dGhpcy5iPWF9LApNeDpmdW5jdGlvbiBN
-eChhKXt0aGlzLmE9YX0sClNoOmZ1bmN0aW9uIFNoKCl7fSwKdGk6ZnVuY3Rpb24gdGkoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCnR1OmZ1bmN0aW9uIHR1KGEsYixjKXt0aGlzLmM9YQp0aGlzLmE9Ygp0aGlz
-LmI9Y30sCnU1OmZ1bmN0aW9uIHU1KCl7fSwKRTM6ZnVuY3Rpb24gRTMoKXt9LApSdzpmdW5jdGlvbiBS
-dyhhKXt0aGlzLmI9MAp0aGlzLmM9YX0sCkdZOmZ1bmN0aW9uIEdZKGEpe3RoaXMuYT1hfSwKYno6ZnVu
-Y3Rpb24gYnooYSl7dGhpcy5hPWEKdGhpcy5iPTE2CnRoaXMuYz0wfSwKUUE6ZnVuY3Rpb24oYSxiKXt2
-YXIgcz1ILkhwKGEsYikKaWYocyE9bnVsbClyZXR1cm4gcwp0aHJvdyBILmIoUC5ycihhLG51bGwsbnVs
-bCkpfSwKb3M6ZnVuY3Rpb24oYSl7aWYoYSBpbnN0YW5jZW9mIEguVHApcmV0dXJuIGEudygwKQpyZXR1
-cm4iSW5zdGFuY2Ugb2YgJyIrSC5FaihILk0oYSkpKyInIn0sCk84OmZ1bmN0aW9uKGEsYixjLGQpe3Zh
-ciBzLHI9Yz9KLktoKGEsZCk6Si5RaShhLGQpCmlmKGEhPT0wJiZiIT1udWxsKWZvcihzPTA7czxyLmxl
-bmd0aDsrK3MpcltzXT1iCnJldHVybiByfSwKQ0g6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHI9SC5WTShb
-XSxjLkMoImpkPDA+IikpCmZvcihzPUouSVQoYSk7cy5GKCk7KUMuTm0uaShyLGMuYShzLmdsKCkpKQpp
-ZihiKXJldHVybiByCnJldHVybiBKLkVwKHIsYyl9LApZMTpmdW5jdGlvbihhLGIsYyl7dmFyIHMKaWYo
-YilyZXR1cm4gUC5ldihhLGMpCnM9Si5FcChQLmV2KGEsYyksYykKcmV0dXJuIHN9LApldjpmdW5jdGlv
-bihhLGIpe3ZhciBzLHI9SC5WTShbXSxiLkMoImpkPDA+IikpCmZvcihzPUouSVQoYSk7cy5GKCk7KUMu
-Tm0uaShyLHMuZ2woKSkKcmV0dXJuIHJ9LApBRjpmdW5jdGlvbihhLGIpe3JldHVybiBKLnpDKFAuQ0go
-YSwhMSxiKSl9LApITTpmdW5jdGlvbihhLGIsYyl7aWYodC5ibS5iKGEpKXJldHVybiBILmZ3KGEsYixQ
-LmpCKGIsYyxhLmxlbmd0aCkpCnJldHVybiBQLmJ3KGEsYixjKX0sCk9vOmZ1bmN0aW9uKGEpe3JldHVy
-biBILkx3KGEpfSwKYnc6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG89bnVsbAppZihiPDApdGhy
-b3cgSC5iKFAuVEUoYiwwLGEubGVuZ3RoLG8sbykpCnM9Yz09bnVsbAppZighcyYmYzxiKXRocm93IEgu
-YihQLlRFKGMsYixhLmxlbmd0aCxvLG8pKQpyPW5ldyBILmE3KGEsYS5sZW5ndGgsSC56KGEpLkMoImE3
-PGxELkU+IikpCmZvcihxPTA7cTxiOysrcSlpZighci5GKCkpdGhyb3cgSC5iKFAuVEUoYiwwLHEsbyxv
-KSkKcD1bXQppZihzKWZvcig7ci5GKCk7KXAucHVzaChyLmQpCmVsc2UgZm9yKHE9YjtxPGM7KytxKXtp
-Zighci5GKCkpdGhyb3cgSC5iKFAuVEUoYyxiLHEsbyxvKSkKcC5wdXNoKHIuZCl9cmV0dXJuIEguZVQo
-cCl9LApudTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguVlIoYSxILnY0KGEsITEsITAsITEsITEsITEp
-KX0sCnZnOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1KLklUKGIpCmlmKCFzLkYoKSlyZXR1cm4gYQppZihj
-Lmxlbmd0aD09PTApe2RvIGErPUguRWoocy5nbCgpKQp3aGlsZShzLkYoKSl9ZWxzZXthKz1ILkVqKHMu
-Z2woKSkKZm9yKDtzLkYoKTspYT1hK2MrSC5FaihzLmdsKCkpfXJldHVybiBhfSwKbHI6ZnVuY3Rpb24o
-YSxiLGMsZCl7cmV0dXJuIG5ldyBQLm1wKGEsYixjLGQpfSwKdW86ZnVuY3Rpb24oKXt2YXIgcz1ILk0w
-KCkKaWYocyE9bnVsbClyZXR1cm4gUC5oSyhzKQp0aHJvdyBILmIoUC5MNCgiJ1VyaS5iYXNlJyBpcyBu
-b3Qgc3VwcG9ydGVkIikpfSwKZVA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuLG09IjAx
-MjM0NTY3ODlBQkNERUYiCmlmKGM9PT1DLnhNKXtzPSQuejQoKS5iCmlmKHR5cGVvZiBiIT0ic3RyaW5n
-IilILnYoSC50TChiKSkKcz1zLnRlc3QoYil9ZWxzZSBzPSExCmlmKHMpcmV0dXJuIGIKSC5MaChjKS5D
-KCJVay5TIikuYShiKQpyPWMuZ1pFKCkuV0ooYikKZm9yKHM9ci5sZW5ndGgscT0wLHA9IiI7cTxzOysr
-cSl7bz1yW3FdCmlmKG88MTI4KXtuPW8+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goYSxuKQpuPShhW25d
-JjE8PChvJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKXArPUguTHcobykKZWxzZSBwPWQmJm89PT0zMj9w
-KyIrIjpwKyIlIittW28+Pj40JjE1XSttW28mMTVdfXJldHVybiBwLmNoYXJDb2RlQXQoMCk9PTA/cDpw
-fSwKR3E6ZnVuY3Rpb24oYSl7dmFyIHM9TWF0aC5hYnMoYSkscj1hPDA/Ii0iOiIiCmlmKHM+PTEwMDAp
-cmV0dXJuIiIrYQppZihzPj0xMDApcmV0dXJuIHIrIjAiK3MKaWYocz49MTApcmV0dXJuIHIrIjAwIitz
-CnJldHVybiByKyIwMDAiK3N9LApWeDpmdW5jdGlvbihhKXtpZihhPj0xMDApcmV0dXJuIiIrYQppZihh
-Pj0xMClyZXR1cm4iMCIrYQpyZXR1cm4iMDAiK2F9LApoMDpmdW5jdGlvbihhKXtpZihhPj0xMClyZXR1
-cm4iIithCnJldHVybiIwIithfSwKcDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciJ8fEgu
-bChhKXx8bnVsbD09YSlyZXR1cm4gSi5qKGEpCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSlNP
-Ti5zdHJpbmdpZnkoYSkKcmV0dXJuIFAub3MoYSl9LApoVjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAu
-QzYoYSl9LAp4WTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAudSghMSxudWxsLG51bGwsYSl9LApMMzpm
-dW5jdGlvbihhLGIsYyl7cmV0dXJuIG5ldyBQLnUoITAsYSxiLGMpfSwKTVI6ZnVuY3Rpb24oYSxiLGMp
-e3JldHVybiBhfSwKTzc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuYkoobnVsbCxudWxsLCEwLGEs
-YiwiVmFsdWUgbm90IGluIHJhbmdlIil9LApURTpmdW5jdGlvbihhLGIsYyxkLGUpe3JldHVybiBuZXcg
-UC5iSihiLGMsITAsYSxkLCJJbnZhbGlkIHZhbHVlIil9LAp3QTpmdW5jdGlvbihhLGIsYyxkKXtpZihh
-PGJ8fGE+Yyl0aHJvdyBILmIoUC5URShhLGIsYyxkLG51bGwpKQpyZXR1cm4gYX0sCmpCOmZ1bmN0aW9u
-KGEsYixjKXtpZigwPmF8fGE+Yyl0aHJvdyBILmIoUC5URShhLDAsYywic3RhcnQiLG51bGwpKQppZihi
-IT1udWxsKXtpZihhPmJ8fGI+Yyl0aHJvdyBILmIoUC5URShiLGEsYywiZW5kIixudWxsKSkKcmV0dXJu
-IGJ9cmV0dXJuIGN9LAprMTpmdW5jdGlvbihhLGIpe2lmKGE8MCl0aHJvdyBILmIoUC5URShhLDAsbnVs
-bCxiLG51bGwpKQpyZXR1cm4gYX0sCkNmOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHM9SC51UChlPT1u
-dWxsP0ouSG0oYik6ZSkKcmV0dXJuIG5ldyBQLmVZKHMsITAsYSxjLCJJbmRleCBvdXQgb2YgcmFuZ2Ui
-KX0sCkw0OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC51YihhKX0sClNZOmZ1bmN0aW9uKGEpe3JldHVy
-biBuZXcgUC5kcyhhKX0sClBWOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5saihhKX0sCmE0OmZ1bmN0
-aW9uKGEpe3JldHVybiBuZXcgUC5VVihhKX0sCnJyOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbmV3IFAu
-YUUoYSxiLGMpfSwKaEs6ZnVuY3Rpb24oYTUpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYs
-ZSxkLGMsYixhLGEwLGExLGEyLGEzPW51bGwsYTQ9YTUubGVuZ3RoCmlmKGE0Pj01KXtzPSgoSi5Reihh
-NSw0KV41OCkqM3xDLnhCLlcoYTUsMCleMTAwfEMueEIuVyhhNSwxKV45N3xDLnhCLlcoYTUsMileMTE2
-fEMueEIuVyhhNSwzKV45Nyk+Pj4wCmlmKHM9PT0wKXJldHVybiBQLktEKGE0PGE0P0MueEIuTmooYTUs
-MCxhNCk6YTUsNSxhMykuZ2xSKCkKZWxzZSBpZihzPT09MzIpcmV0dXJuIFAuS0QoQy54Qi5OaihhNSw1
-LGE0KSwwLGEzKS5nbFIoKX1yPVAuTzgoOCwwLCExLHQuUykKQy5ObS5ZNShyLDAsMCkKQy5ObS5ZNShy
-LDEsLTEpCkMuTm0uWTUociwyLC0xKQpDLk5tLlk1KHIsNywtMSkKQy5ObS5ZNShyLDMsMCkKQy5ObS5Z
-NShyLDQsMCkKQy5ObS5ZNShyLDUsYTQpCkMuTm0uWTUociw2LGE0KQppZihQLlVCKGE1LDAsYTQsMCxy
-KT49MTQpQy5ObS5ZNShyLDcsYTQpCnE9clsxXQppZihxPj0wKWlmKFAuVUIoYTUsMCxxLDIwLHIpPT09
-MjApcls3XT1xCnA9clsyXSsxCm89clszXQpuPXJbNF0KbT1yWzVdCmw9cls2XQppZihsPG0pbT1sCmlm
-KG48cCluPW0KZWxzZSBpZihuPD1xKW49cSsxCmlmKG88cClvPW4Kaz1yWzddPDAKaWYoaylpZihwPnEr
-Myl7aj1hMwprPSExfWVsc2V7aT1vPjAKaWYoaSYmbysxPT09bil7aj1hMwprPSExfWVsc2V7aWYoISht
-PGE0JiZtPT09bisyJiZKLnEwKGE1LCIuLiIsbikpKWg9bT5uKzImJkoucTAoYTUsIi8uLiIsbS0zKQpl
-bHNlIGg9ITAKaWYoaCl7aj1hMwprPSExfWVsc2V7aWYocT09PTQpaWYoSi5xMChhNSwiZmlsZSIsMCkp
-e2lmKHA8PTApe2lmKCFDLnhCLlFpKGE1LCIvIixuKSl7Zz0iZmlsZTovLy8iCnM9M31lbHNle2c9ImZp
-bGU6Ly8iCnM9Mn1hNT1nK0MueEIuTmooYTUsbixhNCkKcS09MAppPXMtMAptKz1pCmwrPWkKYTQ9YTUu
-bGVuZ3RoCnA9NwpvPTcKbj03fWVsc2UgaWYobj09PW0peysrbApmPW0rMQphNT1DLnhCLmk3KGE1LG4s
-bSwiLyIpOysrYTQKbT1mfWo9ImZpbGUifWVsc2UgaWYoQy54Qi5RaShhNSwiaHR0cCIsMCkpe2lmKGkm
-Jm8rMz09PW4mJkMueEIuUWkoYTUsIjgwIixvKzEpKXtsLT0zCmU9bi0zCm0tPTMKYTU9Qy54Qi5pNyhh
-NSxvLG4sIiIpCmE0LT0zCm49ZX1qPSJodHRwIn1lbHNlIGo9YTMKZWxzZSBpZihxPT09NSYmSi5xMChh
-NSwiaHR0cHMiLDApKXtpZihpJiZvKzQ9PT1uJiZKLnEwKGE1LCI0NDMiLG8rMSkpe2wtPTQKZT1uLTQK
-bS09NAphNT1KLmRnKGE1LG8sbiwiIikKYTQtPTMKbj1lfWo9Imh0dHBzIn1lbHNlIGo9YTMKaz0hMH19
-fWVsc2Ugaj1hMwppZihrKXtpPWE1Lmxlbmd0aAppZihhNDxpKXthNT1KLmxkKGE1LDAsYTQpCnEtPTAK
-cC09MApvLT0wCm4tPTAKbS09MApsLT0wfXJldHVybiBuZXcgUC5VZihhNSxxLHAsbyxuLG0sbCxqKX1p
-ZihqPT1udWxsKWlmKHE+MClqPVAuUGkoYTUsMCxxKQplbHNle2lmKHE9PT0wKXtQLlIzKGE1LDAsIklu
-dmFsaWQgZW1wdHkgc2NoZW1lIikKSC5CaSh1LmcpfWo9IiJ9aWYocD4wKXtkPXErMwpjPWQ8cD9QLnpS
-KGE1LGQscC0xKToiIgpiPVAuT2UoYTUscCxvLCExKQppPW8rMQppZihpPG4pe2E9SC5IcChKLmxkKGE1
-LGksbiksYTMpCmEwPVAud0IoYT09bnVsbD9ILnYoUC5ycigiSW52YWxpZCBwb3J0IixhNSxpKSk6YSxq
-KX1lbHNlIGEwPWEzfWVsc2V7YTA9YTMKYj1hMApjPSIifWExPVAua2EoYTUsbixtLGEzLGosYiE9bnVs
-bCkKYTI9bTxsP1AubGUoYTUsbSsxLGwsYTMpOmEzCnJldHVybiBuZXcgUC5EbihqLGMsYixhMCxhMSxh
-MixsPGE0P1AudEcoYTUsbCsxLGE0KTphMyl9LApNdDpmdW5jdGlvbihhKXtILmgoYSkKcmV0dXJuIFAu
-a3UoYSwwLGEubGVuZ3RoLEMueE0sITEpfSwKV1g6ZnVuY3Rpb24oYSl7dmFyIHM9dC5OCnJldHVybiBD
-Lk5tLk4wKEguVk0oYS5zcGxpdCgiJiIpLHQucyksUC5GbChzLHMpLG5ldyBQLm4xKEMueE0pLHQuSil9
-LApIaDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAsbyxuLG09IklQdjQgYWRkcmVzcyBzaG91bGQg
-Y29udGFpbiBleGFjdGx5IDQgcGFydHMiLGw9ImVhY2ggcGFydCBtdXN0IGJlIGluIHRoZSByYW5nZSAw
-Li4yNTUiLGs9bmV3IFAuY1MoYSksaj1uZXcgVWludDhBcnJheSg0KQpmb3Iocz1iLHI9cyxxPTA7czxj
-Oysrcyl7cD1DLnhCLk8yKGEscykKaWYocCE9PTQ2KXtpZigocF40OCk+OSlrLiQyKCJpbnZhbGlkIGNo
-YXJhY3RlciIscyl9ZWxzZXtpZihxPT09MylrLiQyKG0scykKbz1QLlFBKEMueEIuTmooYSxyLHMpLG51
-bGwpCmlmKG8+MjU1KWsuJDIobCxyKQpuPXErMQppZihxPj00KXJldHVybiBILk9IKGoscSkKaltxXT1v
-CnI9cysxCnE9bn19aWYocSE9PTMpay4kMihtLGMpCm89UC5RQShDLnhCLk5qKGEscixjKSxudWxsKQpp
-ZihvPjI1NSlrLiQyKGwscikKaWYocT49NClyZXR1cm4gSC5PSChqLHEpCmpbcV09bwpyZXR1cm4gan0s
-CmVnOmZ1bmN0aW9uKGEsYixhMCl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQ9bmV3
-IFAuVkMoYSksYz1uZXcgUC5KVChkLGEpCmlmKGEubGVuZ3RoPDIpZC4kMSgiYWRkcmVzcyBpcyB0b28g
-c2hvcnQiKQpzPUguVk0oW10sdC5hKQpmb3Iocj1iLHE9cixwPSExLG89ITE7cjxhMDsrK3Ipe249Qy54
-Qi5PMihhLHIpCmlmKG49PT01OCl7aWYocj09PWIpeysrcgppZihDLnhCLk8yKGEscikhPT01OClkLiQy
-KCJpbnZhbGlkIHN0YXJ0IGNvbG9uLiIscikKcT1yfWlmKHI9PT1xKXtpZihwKWQuJDIoIm9ubHkgb25l
-IHdpbGRjYXJkIGA6OmAgaXMgYWxsb3dlZCIscikKQy5ObS5pKHMsLTEpCnA9ITB9ZWxzZSBDLk5tLmko
-cyxjLiQyKHEscikpCnE9cisxfWVsc2UgaWYobj09PTQ2KW89ITB9aWYocy5sZW5ndGg9PT0wKWQuJDEo
-InRvbyBmZXcgcGFydHMiKQptPXE9PT1hMApsPUMuTm0uZ3JaKHMpCmlmKG0mJmwhPT0tMSlkLiQyKCJl
-eHBlY3RlZCBhIHBhcnQgYWZ0ZXIgbGFzdCBgOmAiLGEwKQppZighbSlpZighbylDLk5tLmkocyxjLiQy
-KHEsYTApKQplbHNle2s9UC5IaChhLHEsYTApCkMuTm0uaShzLChrWzBdPDw4fGtbMV0pPj4+MCkKQy5O
-bS5pKHMsKGtbMl08PDh8a1szXSk+Pj4wKX1pZihwKXtpZihzLmxlbmd0aD43KWQuJDEoImFuIGFkZHJl
-c3Mgd2l0aCBhIHdpbGRjYXJkIG11c3QgaGF2ZSBsZXNzIHRoYW4gNyBwYXJ0cyIpfWVsc2UgaWYocy5s
-ZW5ndGghPT04KWQuJDEoImFuIGFkZHJlc3Mgd2l0aG91dCBhIHdpbGRjYXJkIG11c3QgY29udGFpbiBl
-eGFjdGx5IDggcGFydHMiKQpqPW5ldyBVaW50OEFycmF5KDE2KQpmb3IobD1zLmxlbmd0aCxpPTktbCxy
-PTAsaD0wO3I8bDsrK3Ipe2c9c1tyXQppZihnPT09LTEpZm9yKGY9MDtmPGk7KytmKXtpZihoPDB8fGg+
-PTE2KXJldHVybiBILk9IKGosaCkKaltoXT0wCmU9aCsxCmlmKGU+PTE2KXJldHVybiBILk9IKGosZSkK
-altlXT0wCmgrPTJ9ZWxzZXtlPUMuam4ud0coZyw4KQppZihoPDB8fGg+PTE2KXJldHVybiBILk9IKGos
-aCkKaltoXT1lCmU9aCsxCmlmKGU+PTE2KXJldHVybiBILk9IKGosZSkKaltlXT1nJjI1NQpoKz0yfX1y
-ZXR1cm4gan0sCktMOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciBzLHIscSxwLG8sbgpmPWY9PW51
-bGw/IiI6UC5QaShmLDAsZi5sZW5ndGgpCmc9UC56UihnLDAsZz09bnVsbD8wOmcubGVuZ3RoKQphPVAu
-T2UoYSwwLGE9PW51bGw/MDphLmxlbmd0aCwhMSkKcz1QLmxlKG51bGwsMCwwLGUpCnI9UC50RyhudWxs
-LDAsMCkKZD1QLndCKGQsZikKcT1mPT09ImZpbGUiCmlmKGE9PW51bGwpcD1nLmxlbmd0aCE9PTB8fGQh
-PW51bGx8fHEKZWxzZSBwPSExCmlmKHApYT0iIgpwPWE9PW51bGwKbz0hcApiPVAua2EoYiwwLGI9PW51
-bGw/MDpiLmxlbmd0aCxjLGYsbykKbj1mLmxlbmd0aD09PTAKaWYobiYmcCYmIUMueEIubkMoYiwiLyIp
-KWI9UC53RihiLCFufHxvKQplbHNlIGI9UC54ZShiKQpyZXR1cm4gbmV3IFAuRG4oZixnLHAmJkMueEIu
-bkMoYiwiLy8iKT8iIjphLGQsYixzLHIpfSwKd0s6ZnVuY3Rpb24oYSl7aWYoYT09PSJodHRwIilyZXR1
-cm4gODAKaWYoYT09PSJodHRwcyIpcmV0dXJuIDQ0MwpyZXR1cm4gMH0sClIzOmZ1bmN0aW9uKGEsYixj
-KXt0aHJvdyBILmIoUC5ycihjLGEsYikpfSwKWGQ6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAs
-byxuLG0sbCxrLGosaSxoPW51bGwsZz1iLmxlbmd0aAppZihnIT09MCl7cT0wCndoaWxlKCEwKXtpZigh
-KHE8Zykpe3M9IiIKcj0wCmJyZWFrfWlmKEMueEIuVyhiLHEpPT09NjQpe3M9Qy54Qi5OaihiLDAscSkK
-cj1xKzEKYnJlYWt9KytxfWlmKHI8ZyYmQy54Qi5XKGIscik9PT05MSl7Zm9yKHA9cixvPS0xO3A8Zzsr
-K3Ape249Qy54Qi5XKGIscCkKaWYobj09PTM3JiZvPDApe209Qy54Qi5RaShiLCIyNSIscCsxKT9wKzI6
-cApvPXAKcD1tfWVsc2UgaWYobj09PTkzKWJyZWFrfWlmKHA9PT1nKXRocm93IEguYihQLnJyKCJJbnZh
-bGlkIElQdjYgaG9zdCBlbnRyeS4iLGIscikpCmw9bzwwP3A6bwpQLmVnKGIscisxLGwpOysrcAppZihw
-IT09ZyYmQy54Qi5XKGIscCkhPT01OCl0aHJvdyBILmIoUC5ycigiSW52YWxpZCBlbmQgb2YgYXV0aG9y
-aXR5IixiLHApKX1lbHNlIHA9cgp3aGlsZSghMCl7aWYoIShwPGcpKXtrPWgKYnJlYWt9aWYoQy54Qi5X
-KGIscCk9PT01OCl7aj1DLnhCLnluKGIscCsxKQprPWoubGVuZ3RoIT09MD9QLlFBKGosaCk6aApicmVh
-a30rK3B9aT1DLnhCLk5qKGIscixwKX1lbHNle2s9aAppPWsKcz0iIn1yZXR1cm4gUC5LTChpLGgsSC5W
-TShjLnNwbGl0KCIvIiksdC5zKSxrLGQsYSxzKX0sCmtFOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAs
-bwpmb3Iocz1hLmxlbmd0aCxyPTA7cjxzOysrcil7cT1hW3JdCnEudG9TdHJpbmcKcD1KLlU2KHEpCm89
-cC5nQShxKQppZigwPm8pSC52KFAuVEUoMCwwLHAuZ0EocSksbnVsbCxudWxsKSkKaWYoSC5TUShxLCIv
-IiwwKSl7cz1QLkw0KCJJbGxlZ2FsIHBhdGggY2hhcmFjdGVyICIrSC5FaihxKSkKdGhyb3cgSC5iKHMp
-fX19LApITjpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxCmZvcihzPUgucUMoYSxjLG51bGwsSC50Nihh
-KS5jKSxzPW5ldyBILmE3KHMscy5nQShzKSxzLiR0aS5DKCJhNzxhTC5FPiIpKTtzLkYoKTspe3I9cy5k
-CnE9UC5udSgnWyIqLzo8Pj9cXFxcfF0nKQpyLnRvU3RyaW5nCmlmKEguU1EocixxLDApKXtzPVAuTDQo
-IklsbGVnYWwgY2hhcmFjdGVyIGluIHBhdGg6ICIrcikKdGhyb3cgSC5iKHMpfX19LApyZzpmdW5jdGlv
-bihhLGIpe3ZhciBzCmlmKCEoNjU8PWEmJmE8PTkwKSlzPTk3PD1hJiZhPD0xMjIKZWxzZSBzPSEwCmlm
-KHMpcmV0dXJuCnM9UC5MNCgiSWxsZWdhbCBkcml2ZSBsZXR0ZXIgIitQLk9vKGEpKQp0aHJvdyBILmIo
-cyl9LAp3QjpmdW5jdGlvbihhLGIpe2lmKGEhPW51bGwmJmE9PT1QLndLKGIpKXJldHVybiBudWxsCnJl
-dHVybiBhfSwKT2U6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuCmlmKGE9PW51bGwpcmV0
-dXJuIG51bGwKaWYoYj09PWMpcmV0dXJuIiIKaWYoQy54Qi5PMihhLGIpPT09OTEpe3M9Yy0xCmlmKEMu
-eEIuTzIoYSxzKSE9PTkzKXtQLlIzKGEsYiwiTWlzc2luZyBlbmQgYF1gIHRvIG1hdGNoIGBbYCBpbiBo
-b3N0IikKSC5CaSh1LmcpfXI9YisxCnE9UC50byhhLHIscykKaWYocTxzKXtwPXErMQpvPVAuT0EoYSxD
-LnhCLlFpKGEsIjI1IixwKT9xKzM6cCxzLCIlMjUiKX1lbHNlIG89IiIKUC5lZyhhLHIscSkKcmV0dXJu
-IEMueEIuTmooYSxiLHEpLnRvTG93ZXJDYXNlKCkrbysiXSJ9Zm9yKG49YjtuPGM7KytuKWlmKEMueEIu
-TzIoYSxuKT09PTU4KXtxPUMueEIuWFUoYSwiJSIsYikKcT1xPj1iJiZxPGM/cTpjCmlmKHE8Yyl7cD1x
-KzEKbz1QLk9BKGEsQy54Qi5RaShhLCIyNSIscCk/cSszOnAsYywiJTI1Iil9ZWxzZSBvPSIiClAuZWco
-YSxiLHEpCnJldHVybiJbIitDLnhCLk5qKGEsYixxKStvKyJdIn1yZXR1cm4gUC5PTChhLGIsYyl9LAp0
-bzpmdW5jdGlvbihhLGIsYyl7dmFyIHM9Qy54Qi5YVShhLCIlIixiKQpyZXR1cm4gcz49YiYmczxjP3M6
-Y30sCk9BOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGk9ZCE9PSIiP25l
-dyBQLlJuKGQpOm51bGwKZm9yKHM9YixyPXMscT0hMDtzPGM7KXtwPUMueEIuTzIoYSxzKQppZihwPT09
-Mzcpe289UC5ydihhLHMsITApCm49bz09bnVsbAppZihuJiZxKXtzKz0zCmNvbnRpbnVlfWlmKGk9PW51
-bGwpaT1uZXcgUC5SbigiIikKbT1pLmErPUMueEIuTmooYSxyLHMpCmlmKG4pbz1DLnhCLk5qKGEscyxz
-KzMpCmVsc2UgaWYobz09PSIlIil7UC5SMyhhLHMsIlpvbmVJRCBzaG91bGQgbm90IGNvbnRhaW4gJSBh
-bnltb3JlIikKSC5CaSh1LmcpfWkuYT1tK28Kcys9MwpyPXMKcT0hMH1lbHNle2lmKHA8MTI3KXtuPXA+
-Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5GMyxuKQpuPShDLkYzW25dJjE8PChwJjE1KSkhPT0wfWVs
-c2Ugbj0hMQppZihuKXtpZihxJiY2NTw9cCYmOTA+PXApe2lmKGk9PW51bGwpaT1uZXcgUC5SbigiIikK
-aWYocjxzKXtpLmErPUMueEIuTmooYSxyLHMpCnI9c31xPSExfSsrc31lbHNle2lmKChwJjY0NTEyKT09
-PTU1Mjk2JiZzKzE8Yyl7bD1DLnhCLk8yKGEscysxKQppZigobCY2NDUxMik9PT01NjMyMCl7cD0ocCYx
-MDIzKTw8MTB8bCYxMDIzfDY1NTM2Cms9Mn1lbHNlIGs9MX1lbHNlIGs9MQpqPUMueEIuTmooYSxyLHMp
-CmlmKGk9PW51bGwpe2k9bmV3IFAuUm4oIiIpCm49aX1lbHNlIG49aQpuLmErPWoKbi5hKz1QLnpYKHAp
-CnMrPWsKcj1zfX19aWYoaT09bnVsbClyZXR1cm4gQy54Qi5OaihhLGIsYykKaWYocjxjKWkuYSs9Qy54
-Qi5OaihhLHIsYykKbj1pLmEKcmV0dXJuIG4uY2hhckNvZGVBdCgwKT09MD9uOm59LApPTDpmdW5jdGlv
-bihhLGIsYyl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaQpmb3Iocz1iLHI9cyxxPW51bGwscD0hMDtz
-PGM7KXtvPUMueEIuTzIoYSxzKQppZihvPT09Mzcpe249UC5ydihhLHMsITApCm09bj09bnVsbAppZiht
-JiZwKXtzKz0zCmNvbnRpbnVlfWlmKHE9PW51bGwpcT1uZXcgUC5SbigiIikKbD1DLnhCLk5qKGEscixz
-KQprPXEuYSs9IXA/bC50b0xvd2VyQ2FzZSgpOmwKaWYobSl7bj1DLnhCLk5qKGEscyxzKzMpCmo9M31l
-bHNlIGlmKG49PT0iJSIpe249IiUyNSIKaj0xfWVsc2Ugaj0zCnEuYT1rK24Kcys9agpyPXMKcD0hMH1l
-bHNle2lmKG88MTI3KXttPW8+Pj40CmlmKG0+PTgpcmV0dXJuIEguT0goQy5lYSxtKQptPShDLmVhW21d
-JjE8PChvJjE1KSkhPT0wfWVsc2UgbT0hMQppZihtKXtpZihwJiY2NTw9byYmOTA+PW8pe2lmKHE9PW51
-bGwpcT1uZXcgUC5SbigiIikKaWYocjxzKXtxLmErPUMueEIuTmooYSxyLHMpCnI9c31wPSExfSsrc31l
-bHNle2lmKG88PTkzKXttPW8+Pj40CmlmKG0+PTgpcmV0dXJuIEguT0goQy5hayxtKQptPShDLmFrW21d
-JjE8PChvJjE1KSkhPT0wfWVsc2UgbT0hMQppZihtKXtQLlIzKGEscywiSW52YWxpZCBjaGFyYWN0ZXIi
-KQpILkJpKHUuZyl9ZWxzZXtpZigobyY2NDUxMik9PT01NTI5NiYmcysxPGMpe2k9Qy54Qi5PMihhLHMr
-MSkKaWYoKGkmNjQ1MTIpPT09NTYzMjApe289KG8mMTAyMyk8PDEwfGkmMTAyM3w2NTUzNgpqPTJ9ZWxz
-ZSBqPTF9ZWxzZSBqPTEKbD1DLnhCLk5qKGEscixzKQppZighcClsPWwudG9Mb3dlckNhc2UoKQppZihx
-PT1udWxsKXtxPW5ldyBQLlJuKCIiKQptPXF9ZWxzZSBtPXEKbS5hKz1sCm0uYSs9UC56WChvKQpzKz1q
-CnI9c319fX1pZihxPT1udWxsKXJldHVybiBDLnhCLk5qKGEsYixjKQppZihyPGMpe2w9Qy54Qi5Oaihh
-LHIsYykKcS5hKz0hcD9sLnRvTG93ZXJDYXNlKCk6bH1tPXEuYQpyZXR1cm4gbS5jaGFyQ29kZUF0KDAp
-PT0wP206bX0sClBpOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxvPXUuZwppZihiPT09YylyZXR1
-cm4iIgppZighUC5FdChKLnJZKGEpLlcoYSxiKSkpe1AuUjMoYSxiLCJTY2hlbWUgbm90IHN0YXJ0aW5n
-IHdpdGggYWxwaGFiZXRpYyBjaGFyYWN0ZXIiKQpILkJpKG8pfWZvcihzPWIscj0hMTtzPGM7KytzKXtx
-PUMueEIuVyhhLHMpCmlmKHE8MTI4KXtwPXE+Pj40CmlmKHA+PTgpcmV0dXJuIEguT0goQy5tSyxwKQpw
-PShDLm1LW3BdJjE8PChxJjE1KSkhPT0wfWVsc2UgcD0hMQppZighcCl7UC5SMyhhLHMsIklsbGVnYWwg
-c2NoZW1lIGNoYXJhY3RlciIpCkguQmkobyl9aWYoNjU8PXEmJnE8PTkwKXI9ITB9YT1DLnhCLk5qKGEs
-YixjKQpyZXR1cm4gUC5ZYShyP2EudG9Mb3dlckNhc2UoKTphKX0sCllhOmZ1bmN0aW9uKGEpe2lmKGE9
-PT0iaHR0cCIpcmV0dXJuImh0dHAiCmlmKGE9PT0iZmlsZSIpcmV0dXJuImZpbGUiCmlmKGE9PT0iaHR0
-cHMiKXJldHVybiJodHRwcyIKaWYoYT09PSJwYWNrYWdlIilyZXR1cm4icGFja2FnZSIKcmV0dXJuIGF9
-LAp6UjpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4iIgpyZXR1cm4gUC5QSShhLGIsYyxD
-LnRvLCExKX0sCmthOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgcyxyLHE9ZT09PSJmaWxlIixwPXF8
-fGYKaWYoYT09bnVsbCl7aWYoZD09bnVsbClyZXR1cm4gcT8iLyI6IiIKcz1ILnQ2KGQpCnI9bmV3IEgu
-bEooZCxzLkMoInFVKDEpIikuYShuZXcgUC5SWigpKSxzLkMoImxKPDEscVU+IikpLmsoMCwiLyIpfWVs
-c2UgaWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgiQm90aCBwYXRoIGFuZCBwYXRoU2VnbWVudHMgc3Bl
-Y2lmaWVkIikpCmVsc2Ugcj1QLlBJKGEsYixjLEMuV2QsITApCmlmKHIubGVuZ3RoPT09MCl7aWYocSly
-ZXR1cm4iLyJ9ZWxzZSBpZihwJiYhQy54Qi5uQyhyLCIvIikpcj0iLyIrcgpyZXR1cm4gUC5KcihyLGUs
-Zil9LApKcjpmdW5jdGlvbihhLGIsYyl7dmFyIHM9Yi5sZW5ndGg9PT0wCmlmKHMmJiFjJiYhQy54Qi5u
-QyhhLCIvIikpcmV0dXJuIFAud0YoYSwhc3x8YykKcmV0dXJuIFAueGUoYSl9LApsZTpmdW5jdGlvbihh
-LGIsYyxkKXt2YXIgcyxyPXt9CmlmKGEhPW51bGwpe2lmKGQhPW51bGwpdGhyb3cgSC5iKFAueFkoIkJv
-dGggcXVlcnkgYW5kIHF1ZXJ5UGFyYW1ldGVycyBzcGVjaWZpZWQiKSkKcmV0dXJuIFAuUEkoYSxiLGMs
-Qy5WQywhMCl9aWYoZD09bnVsbClyZXR1cm4gbnVsbApzPW5ldyBQLlJuKCIiKQpyLmE9IiIKZC5LKDAs
-bmV3IFAueTUobmV3IFAuTUUocixzKSkpCnI9cy5hCnJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpy
-fSwKdEc6ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIFAuUEkoYSxi
-LGMsQy5WQywhMCl9LApydjpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAsbyxuPWIrMgppZihuPj1h
-Lmxlbmd0aClyZXR1cm4iJSIKcz1DLnhCLk8yKGEsYisxKQpyPUMueEIuTzIoYSxuKQpxPUgub28ocykK
-cD1ILm9vKHIpCmlmKHE8MHx8cDwwKXJldHVybiIlIgpvPXEqMTYrcAppZihvPDEyNyl7bj1DLmpuLndH
-KG8sNCkKaWYobj49OClyZXR1cm4gSC5PSChDLkYzLG4pCm49KEMuRjNbbl0mMTw8KG8mMTUpKSE9PTB9
-ZWxzZSBuPSExCmlmKG4pcmV0dXJuIEguTHcoYyYmNjU8PW8mJjkwPj1vPyhvfDMyKT4+PjA6bykKaWYo
-cz49OTd8fHI+PTk3KXJldHVybiBDLnhCLk5qKGEsYixiKzMpLnRvVXBwZXJDYXNlKCkKcmV0dXJuIG51
-bGx9LAp6WDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsLGs9IjAxMjM0NTY3ODlBQkNERUYi
-CmlmKGE8MTI4KXtzPW5ldyBVaW50OEFycmF5KDMpCnNbMF09MzcKc1sxXT1DLnhCLlcoayxhPj4+NCkK
-c1syXT1DLnhCLlcoayxhJjE1KX1lbHNle2lmKGE+MjA0NylpZihhPjY1NTM1KXtyPTI0MApxPTR9ZWxz
-ZXtyPTIyNApxPTN9ZWxzZXtyPTE5MgpxPTJ9cD0zKnEKcz1uZXcgVWludDhBcnJheShwKQpmb3Iobz0w
-Oy0tcSxxPj0wO3I9MTI4KXtuPUMuam4uYmYoYSw2KnEpJjYzfHIKaWYobz49cClyZXR1cm4gSC5PSChz
-LG8pCnNbb109MzcKbT1vKzEKbD1DLnhCLlcoayxuPj4+NCkKaWYobT49cClyZXR1cm4gSC5PSChzLG0p
-CnNbbV09bApsPW8rMgptPUMueEIuVyhrLG4mMTUpCmlmKGw+PXApcmV0dXJuIEguT0gocyxsKQpzW2xd
-PW0Kbys9M319cmV0dXJuIFAuSE0ocywwLG51bGwpfSwKUEk6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIg
-cz1QLlVsKGEsYixjLGQsZSkKcmV0dXJuIHM9PW51bGw/Qy54Qi5OaihhLGIsYyk6c30sClVsOmZ1bmN0
-aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGo9bnVsbApmb3Iocz0hZSxyPWIscT1y
-LHA9ajtyPGM7KXtvPUMueEIuTzIoYSxyKQppZihvPDEyNyl7bj1vPj4+NAppZihuPj04KXJldHVybiBI
-Lk9IKGQsbikKbj0oZFtuXSYxPDwobyYxNSkpIT09MH1lbHNlIG49ITEKaWYobikrK3IKZWxzZXtpZihv
-PT09Mzcpe209UC5ydihhLHIsITEpCmlmKG09PW51bGwpe3IrPTMKY29udGludWV9aWYoIiUiPT09bSl7
-bT0iJTI1IgpsPTF9ZWxzZSBsPTN9ZWxzZXtpZihzKWlmKG88PTkzKXtuPW8+Pj40CmlmKG4+PTgpcmV0
-dXJuIEguT0goQy5hayxuKQpuPShDLmFrW25dJjE8PChvJjE1KSkhPT0wfWVsc2Ugbj0hMQplbHNlIG49
-ITEKaWYobil7UC5SMyhhLHIsIkludmFsaWQgY2hhcmFjdGVyIikKSC5CaSh1LmcpCmw9agptPWx9ZWxz
-ZXtpZigobyY2NDUxMik9PT01NTI5Nil7bj1yKzEKaWYobjxjKXtrPUMueEIuTzIoYSxuKQppZigoayY2
-NDUxMik9PT01NjMyMCl7bz0obyYxMDIzKTw8MTB8ayYxMDIzfDY1NTM2Cmw9Mn1lbHNlIGw9MX1lbHNl
-IGw9MX1lbHNlIGw9MQptPVAuelgobyl9fWlmKHA9PW51bGwpe3A9bmV3IFAuUm4oIiIpCm49cH1lbHNl
-IG49cApuLmErPUMueEIuTmooYSxxLHIpCm4uYSs9SC5FaihtKQppZih0eXBlb2YgbCE9PSJudW1iZXIi
-KXJldHVybiBILnBZKGwpCnIrPWwKcT1yfX1pZihwPT1udWxsKXJldHVybiBqCmlmKHE8YylwLmErPUMu
-eEIuTmooYSxxLGMpCnM9cC5hCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKeUI6ZnVuY3Rp
-b24oYSl7aWYoQy54Qi5uQyhhLCIuIikpcmV0dXJuITAKcmV0dXJuIEMueEIuT1koYSwiLy4iKSE9PS0x
-fSwKeGU6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0KaWYoIVAueUIoYSkpcmV0dXJuIGEKcz1I
-LlZNKFtdLHQucykKZm9yKHI9YS5zcGxpdCgiLyIpLHE9ci5sZW5ndGgscD0hMSxvPTA7bzxxOysrbyl7
-bj1yW29dCmlmKEouUk0obiwiLi4iKSl7bT1zLmxlbmd0aAppZihtIT09MCl7aWYoMD49bSlyZXR1cm4g
-SC5PSChzLC0xKQpzLnBvcCgpCmlmKHMubGVuZ3RoPT09MClDLk5tLmkocywiIil9cD0hMH1lbHNlIGlm
-KCIuIj09PW4pcD0hMAplbHNle0MuTm0uaShzLG4pCnA9ITF9fWlmKHApQy5ObS5pKHMsIiIpCnJldHVy
-biBDLk5tLmsocywiLyIpfSwKd0Y6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4KaWYoIVAueUIo
-YSkpcmV0dXJuIWI/UC5DMShhKTphCnM9SC5WTShbXSx0LnMpCmZvcihyPWEuc3BsaXQoIi8iKSxxPXIu
-bGVuZ3RoLHA9ITEsbz0wO288cTsrK28pe249cltvXQppZigiLi4iPT09bilpZihzLmxlbmd0aCE9PTAm
-JkMuTm0uZ3JaKHMpIT09Ii4uIil7aWYoMD49cy5sZW5ndGgpcmV0dXJuIEguT0gocywtMSkKcy5wb3Ao
-KQpwPSEwfWVsc2V7Qy5ObS5pKHMsIi4uIikKcD0hMX1lbHNlIGlmKCIuIj09PW4pcD0hMAplbHNle0Mu
-Tm0uaShzLG4pCnA9ITF9fXI9cy5sZW5ndGgKaWYociE9PTApaWYocj09PTEpe2lmKDA+PXIpcmV0dXJu
-IEguT0gocywwKQpyPXNbMF0ubGVuZ3RoPT09MH1lbHNlIHI9ITEKZWxzZSByPSEwCmlmKHIpcmV0dXJu
-Ii4vIgppZihwfHxDLk5tLmdyWihzKT09PSIuLiIpQy5ObS5pKHMsIiIpCmlmKCFiKXtpZigwPj1zLmxl
-bmd0aClyZXR1cm4gSC5PSChzLDApCkMuTm0uWTUocywwLFAuQzEoc1swXSkpfXJldHVybiBDLk5tLmso
-cywiLyIpfSwKQzE6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9YS5sZW5ndGgKaWYocD49MiYmUC5FdChK
-LlF6KGEsMCkpKWZvcihzPTE7czxwOysrcyl7cj1DLnhCLlcoYSxzKQppZihyPT09NTgpcmV0dXJuIEMu
-eEIuTmooYSwwLHMpKyIlM0EiK0MueEIueW4oYSxzKzEpCmlmKHI8PTEyNyl7cT1yPj4+NAppZihxPj04
-KXJldHVybiBILk9IKEMubUsscSkKcT0oQy5tS1txXSYxPDwociYxNSkpPT09MH1lbHNlIHE9ITAKaWYo
-cSlicmVha31yZXR1cm4gYX0sCm1uOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPWEuZ0ZqKCksbz1wLmxl
-bmd0aAppZihvPjAmJkouSG0ocFswXSk9PT0yJiZKLmE2KHBbMF0sMSk9PT01OCl7aWYoMD49bylyZXR1
-cm4gSC5PSChwLDApClAucmcoSi5hNihwWzBdLDApLCExKQpQLkhOKHAsITEsMSkKcz0hMH1lbHNle1Au
-SE4ocCwhMSwwKQpzPSExfXI9YS5ndFQoKSYmIXM/IlxcIjoiIgppZihhLmdjaigpKXtxPWEuZ0pmKGEp
-CmlmKHEubGVuZ3RoIT09MClyPXIrIlxcIitxKyJcXCJ9cj1QLnZnKHIscCwiXFwiKQpvPXMmJm89PT0x
-P3IrIlxcIjpyCnJldHVybiBvLmNoYXJDb2RlQXQoMCk9PTA/bzpvfSwKSWg6ZnVuY3Rpb24oYSxiKXt2
-YXIgcyxyLHEKZm9yKHM9MCxyPTA7cjwyOysrcil7cT1DLnhCLlcoYSxiK3IpCmlmKDQ4PD1xJiZxPD01
-NylzPXMqMTYrcS00OAplbHNle3F8PTMyCmlmKDk3PD1xJiZxPD0xMDIpcz1zKjE2K3EtODcKZWxzZSB0
-aHJvdyBILmIoUC54WSgiSW52YWxpZCBVUkwgZW5jb2RpbmciKSl9fXJldHVybiBzfSwKa3U6ZnVuY3Rp
-b24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvPUouclkoYSksbj1iCndoaWxlKCEwKXtpZighKG48Yykp
-e3M9ITAKYnJlYWt9cj1vLlcoYSxuKQppZihyPD0xMjcpaWYociE9PTM3KXE9ZSYmcj09PTQzCmVsc2Ug
-cT0hMAplbHNlIHE9ITAKaWYocSl7cz0hMQpicmVha30rK259aWYocyl7aWYoQy54TSE9PWQpcT0hMQpl
-bHNlIHE9ITAKaWYocSlyZXR1cm4gby5OaihhLGIsYykKZWxzZSBwPW5ldyBILnFqKG8uTmooYSxiLGMp
-KX1lbHNle3A9SC5WTShbXSx0LmEpCmZvcihuPWI7bjxjOysrbil7cj1vLlcoYSxuKQppZihyPjEyNyl0
-aHJvdyBILmIoUC54WSgiSWxsZWdhbCBwZXJjZW50IGVuY29kaW5nIGluIFVSSSIpKQppZihyPT09Mzcp
-e2lmKG4rMz5hLmxlbmd0aCl0aHJvdyBILmIoUC54WSgiVHJ1bmNhdGVkIFVSSSIpKQpDLk5tLmkocCxQ
-LkloKGEsbisxKSkKbis9Mn1lbHNlIGlmKGUmJnI9PT00MylDLk5tLmkocCwzMikKZWxzZSBDLk5tLmko
-cCxyKX19dC5MLmEocCkKcmV0dXJuIEMub0UuV0oocCl9LApFdDpmdW5jdGlvbihhKXt2YXIgcz1hfDMy
-CnJldHVybiA5Nzw9cyYmczw9MTIyfSwKS0Q6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbixt
-LGwsaz0iSW52YWxpZCBNSU1FIHR5cGUiLGo9SC5WTShbYi0xXSx0LmEpCmZvcihzPWEubGVuZ3RoLHI9
-YixxPS0xLHA9bnVsbDtyPHM7KytyKXtwPUMueEIuVyhhLHIpCmlmKHA9PT00NHx8cD09PTU5KWJyZWFr
-CmlmKHA9PT00Nyl7aWYocTwwKXtxPXIKY29udGludWV9dGhyb3cgSC5iKFAucnIoayxhLHIpKX19aWYo
-cTwwJiZyPmIpdGhyb3cgSC5iKFAucnIoayxhLHIpKQpmb3IoO3AhPT00NDspe0MuTm0uaShqLHIpOysr
-cgpmb3Iobz0tMTtyPHM7KytyKXtwPUMueEIuVyhhLHIpCmlmKHA9PT02MSl7aWYobzwwKW89cn1lbHNl
-IGlmKHA9PT01OXx8cD09PTQ0KWJyZWFrfWlmKG8+PTApQy5ObS5pKGosbykKZWxzZXtuPUMuTm0uZ3Ja
-KGopCmlmKHAhPT00NHx8ciE9PW4rN3x8IUMueEIuUWkoYSwiYmFzZTY0IixuKzEpKXRocm93IEguYihQ
-LnJyKCJFeHBlY3RpbmcgJz0nIixhLHIpKQpicmVha319Qy5ObS5pKGoscikKbT1yKzEKaWYoKGoubGVu
-Z3RoJjEpPT09MSlhPUMuaDkueXIoYSxtLHMpCmVsc2V7bD1QLlVsKGEsbSxzLEMuVkMsITApCmlmKGwh
-PW51bGwpYT1DLnhCLmk3KGEsbSxzLGwpfXJldHVybiBuZXcgUC5QRShhLGosYyl9LApLTjpmdW5jdGlv
-bigpe3ZhciBzLHIscSxwLG8sbixtPSIwMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVph
-YmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ei0uX34hJCYnKCkqKyw7PSIsbD0iLiIsaz0iOiIsaj0iLyIs
-aT0iPyIsaD0iIyIsZz1ILlZNKG5ldyBBcnJheSgyMiksdC5nTikKZm9yKHM9MDtzPDIyOysrcylnW3Nd
-PW5ldyBVaW50OEFycmF5KDk2KQpyPW5ldyBQLnlJKGcpCnE9bmV3IFAuYzYoKQpwPW5ldyBQLnFkKCkK
-bz10LmdjCm49by5hKHIuJDIoMCwyMjUpKQpxLiQzKG4sbSwxKQpxLiQzKG4sbCwxNCkKcS4kMyhuLGss
-MzQpCnEuJDMobixqLDMpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpuPW8uYShyLiQyKDE0LDIy
-NSkpCnEuJDMobixtLDEpCnEuJDMobixsLDE1KQpxLiQzKG4saywzNCkKcS4kMyhuLGosMjM0KQpxLiQz
-KG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMigxNSwyMjUpKQpxLiQzKG4sbSwxKQpxLiQz
-KG4sIiUiLDIyNSkKcS4kMyhuLGssMzQpCnEuJDMobixqLDkpCnEuJDMobixpLDE3MikKcS4kMyhuLGgs
-MjA1KQpuPW8uYShyLiQyKDEsMjI1KSkKcS4kMyhuLG0sMSkKcS4kMyhuLGssMzQpCnEuJDMobixqLDEw
-KQpxLiQzKG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMigyLDIzNSkpCnEuJDMobixtLDEz
-OSkKcS4kMyhuLGosMTMxKQpxLiQzKG4sbCwxNDYpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpu
-PW8uYShyLiQyKDMsMjM1KSkKcS4kMyhuLG0sMTEpCnEuJDMobixqLDY4KQpxLiQzKG4sbCwxOCkKcS4k
-MyhuLGksMTcyKQpxLiQzKG4saCwyMDUpCm49by5hKHIuJDIoNCwyMjkpKQpxLiQzKG4sbSw1KQpwLiQz
-KG4sIkFaIiwyMjkpCnEuJDMobixrLDEwMikKcS4kMyhuLCJAIiw2OCkKcS4kMyhuLCJbIiwyMzIpCnEu
-JDMobixqLDEzOCkKcS4kMyhuLGksMTcyKQpxLiQzKG4saCwyMDUpCm49by5hKHIuJDIoNSwyMjkpKQpx
-LiQzKG4sbSw1KQpwLiQzKG4sIkFaIiwyMjkpCnEuJDMobixrLDEwMikKcS4kMyhuLCJAIiw2OCkKcS4k
-MyhuLGosMTM4KQpxLiQzKG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMig2LDIzMSkpCnAu
-JDMobiwiMTkiLDcpCnEuJDMobiwiQCIsNjgpCnEuJDMobixqLDEzOCkKcS4kMyhuLGksMTcyKQpxLiQz
-KG4saCwyMDUpCm49by5hKHIuJDIoNywyMzEpKQpwLiQzKG4sIjA5Iiw3KQpxLiQzKG4sIkAiLDY4KQpx
-LiQzKG4saiwxMzgpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpxLiQzKG8uYShyLiQyKDgsOCkp
-LCJdIiw1KQpuPW8uYShyLiQyKDksMjM1KSkKcS4kMyhuLG0sMTEpCnEuJDMobixsLDE2KQpxLiQzKG4s
-aiwyMzQpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpuPW8uYShyLiQyKDE2LDIzNSkpCnEuJDMo
-bixtLDExKQpxLiQzKG4sbCwxNykKcS4kMyhuLGosMjM0KQpxLiQzKG4saSwxNzIpCnEuJDMobixoLDIw
-NSkKbj1vLmEoci4kMigxNywyMzUpKQpxLiQzKG4sbSwxMSkKcS4kMyhuLGosOSkKcS4kMyhuLGksMTcy
-KQpxLiQzKG4saCwyMDUpCm49by5hKHIuJDIoMTAsMjM1KSkKcS4kMyhuLG0sMTEpCnEuJDMobixsLDE4
-KQpxLiQzKG4saiwyMzQpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpuPW8uYShyLiQyKDE4LDIz
-NSkpCnEuJDMobixtLDExKQpxLiQzKG4sbCwxOSkKcS4kMyhuLGosMjM0KQpxLiQzKG4saSwxNzIpCnEu
-JDMobixoLDIwNSkKbj1vLmEoci4kMigxOSwyMzUpKQpxLiQzKG4sbSwxMSkKcS4kMyhuLGosMjM0KQpx
-LiQzKG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMigxMSwyMzUpKQpxLiQzKG4sbSwxMSkK
-cS4kMyhuLGosMTApCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpuPW8uYShyLiQyKDEyLDIzNikp
-CnEuJDMobixtLDEyKQpxLiQzKG4saSwxMikKcS4kMyhuLGgsMjA1KQpuPW8uYShyLiQyKDEzLDIzNykp
-CnEuJDMobixtLDEzKQpxLiQzKG4saSwxMykKcC4kMyhvLmEoci4kMigyMCwyNDUpKSwiYXoiLDIxKQpy
-PW8uYShyLiQyKDIxLDI0NSkpCnAuJDMociwiYXoiLDIxKQpwLiQzKHIsIjA5IiwyMSkKcS4kMyhyLCIr
-LS4iLDIxKQpyZXR1cm4gZ30sClVCOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbyxuPSQu
-dlooKQpmb3Iocz1KLnJZKGEpLHI9YjtyPGM7KytyKXtpZihkPDB8fGQ+PW4ubGVuZ3RoKXJldHVybiBI
-Lk9IKG4sZCkKcT1uW2RdCnA9cy5XKGEscileOTYKbz1xW3A+OTU/MzE6cF0KZD1vJjMxCkMuTm0uWTUo
-ZSxvPj4+NSxyKX1yZXR1cm4gZH0sCldGOmZ1bmN0aW9uIFdGKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9
-LAppUDpmdW5jdGlvbiBpUChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKWFM6ZnVuY3Rpb24gWFMoKXt9
-LApDNjpmdW5jdGlvbiBDNihhKXt0aGlzLmE9YX0sCkV6OmZ1bmN0aW9uIEV6KCl7fSwKRjpmdW5jdGlv
-biBGKCl7fSwKdTpmdW5jdGlvbiB1KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMK
-Xy5kPWR9LApiSjpmdW5jdGlvbiBiSihhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmU9YQpfLmY9Ygpf
-LmE9YwpfLmI9ZApfLmM9ZQpfLmQ9Zn0sCmVZOmZ1bmN0aW9uIGVZKGEsYixjLGQsZSl7dmFyIF89dGhp
-cwpfLmY9YQpfLmE9YgpfLmI9YwpfLmM9ZApfLmQ9ZX0sCm1wOmZ1bmN0aW9uIG1wKGEsYixjLGQpe3Zh
-ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LAp1YjpmdW5jdGlvbiB1YihhKXt0aGlzLmE9
-YX0sCmRzOmZ1bmN0aW9uIGRzKGEpe3RoaXMuYT1hfSwKbGo6ZnVuY3Rpb24gbGooYSl7dGhpcy5hPWF9
-LApVVjpmdW5jdGlvbiBVVihhKXt0aGlzLmE9YX0sCms1OmZ1bmN0aW9uIGs1KCl7fSwKS1k6ZnVuY3Rp
-b24gS1koKXt9LApjOmZ1bmN0aW9uIGMoYSl7dGhpcy5hPWF9LApDRDpmdW5jdGlvbiBDRChhKXt0aGlz
-LmE9YX0sCmFFOmZ1bmN0aW9uIGFFKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCmNY
-OmZ1bmN0aW9uIGNYKCl7fSwKQW46ZnVuY3Rpb24gQW4oKXt9LApOMzpmdW5jdGlvbiBOMyhhLGIsYyl7
-dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCmM4OmZ1bmN0aW9uIGM4KCl7fSwKTWg6ZnVuY3Rp
-b24gTWgoKXt9LApaZDpmdW5jdGlvbiBaZCgpe30sClJuOmZ1bmN0aW9uIFJuKGEpe3RoaXMuYT1hfSwK
-bjE6ZnVuY3Rpb24gbjEoYSl7dGhpcy5hPWF9LApjUzpmdW5jdGlvbiBjUyhhKXt0aGlzLmE9YX0sClZD
-OmZ1bmN0aW9uIFZDKGEpe3RoaXMuYT1hfSwKSlQ6ZnVuY3Rpb24gSlQoYSxiKXt0aGlzLmE9YQp0aGlz
-LmI9Yn0sCkRuOmZ1bmN0aW9uIERuKGEsYixjLGQsZSxmLGcpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIK
-Xy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5yPWcKXy54PW51bGwKXy55PSExCl8uej1udWxsCl8uUT0h
-MQpfLmNoPW51bGwKXy5jeD0hMQpfLmN5PW51bGwKXy5kYj0hMX0sClJaOmZ1bmN0aW9uIFJaKCl7fSwK
-TUU6ZnVuY3Rpb24gTUUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnk1OmZ1bmN0aW9uIHk1KGEpe3Ro
-aXMuYT1hfSwKUEU6ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwK
-eUk6ZnVuY3Rpb24geUkoYSl7dGhpcy5hPWF9LApjNjpmdW5jdGlvbiBjNigpe30sCnFkOmZ1bmN0aW9u
-IHFkKCl7fSwKVWY6ZnVuY3Rpb24gVWYoYSxiLGMsZCxlLGYsZyxoKXt2YXIgXz10aGlzCl8uYT1hCl8u
-Yj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8ueD1oCl8ueT1udWxsfSwKcWU6ZnVuY3Rp
-b24gcWUoYSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9
-ZQpfLmY9ZgpfLnI9ZwpfLng9bnVsbApfLnk9ITEKXy56PW51bGwKXy5RPSExCl8uY2g9bnVsbApfLmN4
-PSExCl8uY3k9bnVsbApfLmRiPSExfSwKaUo6ZnVuY3Rpb24gaUooKXt9LApqZzpmdW5jdGlvbiBqZyhh
-LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVGE6ZnVuY3Rpb24gVGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
-Yn0sCkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBczpmdW5jdGlvbiBBcygp
-e30sCkdFOmZ1bmN0aW9uIEdFKGEpe3RoaXMuYT1hfSwKTjc6ZnVuY3Rpb24gTjcoYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sCnVROmZ1bmN0aW9uIHVRKCl7fSwKaEY6ZnVuY3Rpb24gaEYoKXt9LApSNDpmdW5j
-dGlvbihhLGIsYyxkKXt2YXIgcyxyLHEKSC55OChiKQp0LmouYShkKQppZihILm9UKGIpKXtzPVtjXQpD
-Lk5tLkZWKHMsZCkKZD1zfXI9dC56CnE9UC5DSChKLk0xKGQsUC53MCgpLHIpLCEwLHIpCnQuWS5hKGEp
-CnJldHVybiBQLndZKEguRWsoYSxxLG51bGwpKX0sCkRtOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwp0cnl7
-aWYoT2JqZWN0LmlzRXh0ZW5zaWJsZShhKSYmIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHku
-Y2FsbChhLGIpKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1ZTpjfSkKcmV0dXJuITB9fWNh
-dGNoKHMpe0guUnUocyl9cmV0dXJuITF9LApPbTpmdW5jdGlvbihhLGIpe2lmKE9iamVjdC5wcm90b3R5
-cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXJldHVybiBhW2JdCnJldHVybiBudWxsfSwKd1k6ZnVu
-Y3Rpb24oYSl7aWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8
-fEgubChhKSlyZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5FNClyZXR1cm4gYS5hCmlmKEguUjkoYSkp
-cmV0dXJuIGEKaWYodC5hay5iKGEpKXJldHVybiBhCmlmKGEgaW5zdGFuY2VvZiBQLmlQKXJldHVybiBI
-Lm8yKGEpCmlmKHQuWS5iKGEpKXJldHVybiBQLmhFKGEsIiRkYXJ0X2pzRnVuY3Rpb24iLG5ldyBQLlBD
-KCkpCnJldHVybiBQLmhFKGEsIl8kZGFydF9qc09iamVjdCIsbmV3IFAubXQoJC5rSSgpKSl9LApoRTpm
-dW5jdGlvbihhLGIsYyl7dmFyIHM9UC5PbShhLGIpCmlmKHM9PW51bGwpe3M9Yy4kMShhKQpQLkRtKGEs
-YixzKX1yZXR1cm4gc30sCmRVOmZ1bmN0aW9uKGEpe3ZhciBzLHIKaWYoYT09bnVsbHx8dHlwZW9mIGE9
-PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8fHR5cGVvZiBhPT0iYm9vbGVhbiIpcmV0dXJuIGEK
-ZWxzZSBpZihhIGluc3RhbmNlb2YgT2JqZWN0JiZILlI5KGEpKXJldHVybiBhCmVsc2UgaWYoYSBpbnN0
-YW5jZW9mIE9iamVjdCYmdC5hay5iKGEpKXJldHVybiBhCmVsc2UgaWYoYSBpbnN0YW5jZW9mIERhdGUp
-e3M9SC51UChhLmdldFRpbWUoKSkKaWYoTWF0aC5hYnMocyk8PTg2NGUxMylyPSExCmVsc2Ugcj0hMApp
-ZihyKUgudihQLnhZKCJEYXRlVGltZSBpcyBvdXRzaWRlIHZhbGlkIHJhbmdlOiAiK3MpKQpILmNiKCEx
-LCJpc1V0YyIsdC55KQpyZXR1cm4gbmV3IFAuaVAocywhMSl9ZWxzZSBpZihhLmNvbnN0cnVjdG9yPT09
-JC5rSSgpKXJldHVybiBhLm8KZWxzZSByZXR1cm4gUC5ORChhKX0sCk5EOmZ1bmN0aW9uKGEpe2lmKHR5
-cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBQLmlRKGEsJC53KCksbmV3IFAuTnooKSkKaWYoYSBpbnN0
-YW5jZW9mIEFycmF5KXJldHVybiBQLmlRKGEsJC5SOCgpLG5ldyBQLlFTKCkpCnJldHVybiBQLmlRKGEs
-JC5SOCgpLG5ldyBQLm5wKCkpfSwKaVE6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPVAuT20oYSxiKQppZihz
-PT1udWxsfHwhKGEgaW5zdGFuY2VvZiBPYmplY3QpKXtzPWMuJDEoYSkKUC5EbShhLGIscyl9cmV0dXJu
-IHN9LApQQzpmdW5jdGlvbiBQQygpe30sCm10OmZ1bmN0aW9uIG10KGEpe3RoaXMuYT1hfSwKTno6ZnVu
-Y3Rpb24gTnooKXt9LApRUzpmdW5jdGlvbiBRUygpe30sCm5wOmZ1bmN0aW9uIG5wKCl7fSwKRTQ6ZnVu
-Y3Rpb24gRTQoYSl7dGhpcy5hPWF9LApyNzpmdW5jdGlvbiByNyhhKXt0aGlzLmE9YX0sClR6OmZ1bmN0
-aW9uIFR6KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmNvOmZ1bmN0aW9uIGNvKCl7fSwKbmQ6ZnVu
-Y3Rpb24gbmQoKXt9LApLZTpmdW5jdGlvbiBLZShhKXt0aGlzLmE9YX0sCmhpOmZ1bmN0aW9uIGhpKCl7
-fX0sVz17CngzOmZ1bmN0aW9uKCl7cmV0dXJuIHdpbmRvd30sClpyOmZ1bmN0aW9uKCl7cmV0dXJuIGRv
-Y3VtZW50fSwKSjY6ZnVuY3Rpb24oYSl7dmFyIHM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYSIpCmlm
-KGEhPW51bGwpQy54bi5zTFUocyxhKQpyZXR1cm4gc30sClU5OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxy
-PWRvY3VtZW50LmJvZHkKci50b1N0cmluZwpzPUMuUlkucjYocixhLGIsYykKcy50b1N0cmluZwpyPXQu
-YWMKcj1uZXcgSC5VNShuZXcgVy5lNyhzKSxyLkMoImEyKGxELkUpIikuYShuZXcgVy5DdigpKSxyLkMo
-IlU1PGxELkU+IikpCnJldHVybiB0LmguYShyLmdyOChyKSl9LApyUzpmdW5jdGlvbihhKXt2YXIgcyxy
-LHE9ImVsZW1lbnQgdGFnIHVuYXZhaWxhYmxlIgp0cnl7cz1KLllFKGEpCmlmKHR5cGVvZiBzLmducyhh
-KT09InN0cmluZyIpcT1zLmducyhhKX1jYXRjaChyKXtILlJ1KHIpfXJldHVybiBxfSwKQzA6ZnVuY3Rp
-b24oYSxiKXthPWErYiY1MzY4NzA5MTEKYT1hKygoYSY1MjQyODcpPDwxMCkmNTM2ODcwOTExCnJldHVy
-biBhXmE+Pj42fSwKckU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHM9Vy5DMChXLkMwKFcuQzAoVy5DMCgw
-LGEpLGIpLGMpLGQpLHI9cysoKHMmNjcxMDg4NjMpPDwzKSY1MzY4NzA5MTEKcl49cj4+PjExCnJldHVy
-biByKygociYxNjM4Myk8PDE1KSY1MzY4NzA5MTF9LApUTjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT1h
-LmNsYXNzTGlzdApmb3Iocz1iLmxlbmd0aCxyPTA7cjxiLmxlbmd0aDtiLmxlbmd0aD09PXN8fCgwLEgu
-bGspKGIpLCsrcilxLmFkZChiW3JdKX0sCkpFOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHM9Vy5hRihu
-ZXcgVy52TihjKSx0LkIpCmlmKHMhPW51bGwmJiEwKUouZFooYSxiLHMsITEpCnJldHVybiBuZXcgVy54
-QyhhLGIscywhMSxlLkMoInhDPDA+IikpfSwKVHc6ZnVuY3Rpb24oYSl7dmFyIHM9Vy5KNihudWxsKSxy
-PXdpbmRvdy5sb2NhdGlvbgpzPW5ldyBXLkpRKG5ldyBXLm1rKHMscikpCnMuQ1koYSkKcmV0dXJuIHN9
-LApxRDpmdW5jdGlvbihhLGIsYyxkKXt0LmguYShhKQpILmgoYikKSC5oKGMpCnQuY3IuYShkKQpyZXR1
-cm4hMH0sClFXOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscQp0LmguYShhKQpILmgoYikKSC5oKGMp
-CnM9dC5jci5hKGQpLmEKcj1zLmEKQy54bi5zTFUocixjKQpxPXIuaG9zdG5hbWUKcz1zLmIKaWYoIShx
-PT1zLmhvc3RuYW1lJiZyLnBvcnQ9PXMucG9ydCYmci5wcm90b2NvbD09cy5wcm90b2NvbCkpaWYocT09
-PSIiKWlmKHIucG9ydD09PSIiKXtzPXIucHJvdG9jb2wKcz1zPT09IjoifHxzPT09IiJ9ZWxzZSBzPSEx
-CmVsc2Ugcz0hMQplbHNlIHM9ITAKcmV0dXJuIHN9LApCbDpmdW5jdGlvbigpe3ZhciBzPXQuTixyPVAu
-dE0oQy5ReCxzKSxxPXQuZDAuYShuZXcgVy5JQSgpKSxwPUguVk0oWyJURU1QTEFURSJdLHQucykKcz1u
-ZXcgVy5jdChyLFAuTHMocyksUC5McyhzKSxQLkxzKHMpLG51bGwpCnMuQ1kobnVsbCxuZXcgSC5sSihD
-LlF4LHEsdC5maikscCxudWxsKQpyZXR1cm4gc30sCnFjOmZ1bmN0aW9uKGEpe3ZhciBzCmlmKGE9PW51
-bGwpcmV0dXJuIG51bGwKaWYoInBvc3RNZXNzYWdlIiBpbiBhKXtzPVcuUDEoYSkKaWYodC5hUy5iKHMp
-KXJldHVybiBzCnJldHVybiBudWxsfWVsc2UgcmV0dXJuIHQuY2guYShhKX0sClAxOmZ1bmN0aW9uKGEp
-e2lmKGE9PT13aW5kb3cpcmV0dXJuIHQuY2kuYShhKQplbHNlIHJldHVybiBuZXcgVy5kVygpfSwKYUY6
-ZnVuY3Rpb24oYSxiKXt2YXIgcz0kLlgzCmlmKHM9PT1DLk5VKXJldHVybiBhCnJldHVybiBzLlB5KGEs
-Yil9LApxRTpmdW5jdGlvbiBxRSgpe30sCkdoOmZ1bmN0aW9uIEdoKCl7fSwKZlk6ZnVuY3Rpb24gZlko
-KXt9LApuQjpmdW5jdGlvbiBuQigpe30sCkF6OmZ1bmN0aW9uIEF6KCl7fSwKUVA6ZnVuY3Rpb24gUVAo
-KXt9LApueDpmdW5jdGlvbiBueCgpe30sCm9KOmZ1bmN0aW9uIG9KKCl7fSwKaWQ6ZnVuY3Rpb24gaWQo
-KXt9LApRRjpmdW5jdGlvbiBRRigpe30sCk5oOmZ1bmN0aW9uIE5oKCl7fSwKYWU6ZnVuY3Rpb24gYWUo
-KXt9LApJQjpmdW5jdGlvbiBJQigpe30sCm43OmZ1bmN0aW9uIG43KCl7fSwKd3o6ZnVuY3Rpb24gd3oo
-YSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKY3Y6ZnVuY3Rpb24gY3YoKXt9LApDdjpmdW5jdGlvbiBD
-digpe30sCmVhOmZ1bmN0aW9uIGVhKCl7fSwKRDA6ZnVuY3Rpb24gRDAoKXt9LApoSDpmdW5jdGlvbiBo
-SCgpe30sCmg0OmZ1bmN0aW9uIGg0KCl7fSwKYnI6ZnVuY3Rpb24gYnIoKXt9LApWYjpmdW5jdGlvbiBW
-Yigpe30sCmZKOmZ1bmN0aW9uIGZKKCl7fSwKd2E6ZnVuY3Rpb24gd2EoKXt9LApTZzpmdW5jdGlvbiBT
-Zygpe30sCnc3OmZ1bmN0aW9uIHc3KCl7fSwKQWo6ZnVuY3Rpb24gQWooKXt9LAplNzpmdW5jdGlvbiBl
-NyhhKXt0aGlzLmE9YX0sCnVIOmZ1bmN0aW9uIHVIKCl7fSwKQkg6ZnVuY3Rpb24gQkgoKXt9LApTTjpm
-dW5jdGlvbiBTTigpe30sCmV3OmZ1bmN0aW9uIGV3KCl7fSwKbHA6ZnVuY3Rpb24gbHAoKXt9LApUYjpm
-dW5jdGlvbiBUYigpe30sCkl2OmZ1bmN0aW9uIEl2KCl7fSwKV1A6ZnVuY3Rpb24gV1AoKXt9LAp5WTpm
-dW5jdGlvbiB5WSgpe30sCnc2OmZ1bmN0aW9uIHc2KCl7fSwKSzU6ZnVuY3Rpb24gSzUoKXt9LApDbTpm
-dW5jdGlvbiBDbSgpe30sCkNROmZ1bmN0aW9uIENRKCl7fSwKdzQ6ZnVuY3Rpb24gdzQoKXt9LApyaDpm
-dW5jdGlvbiByaCgpe30sCmNmOmZ1bmN0aW9uIGNmKCl7fSwKaTc6ZnVuY3Rpb24gaTcoYSl7dGhpcy5h
-PWF9LApTeTpmdW5jdGlvbiBTeShhKXt0aGlzLmE9YX0sCktTOmZ1bmN0aW9uIEtTKGEsYil7dGhpcy5h
-PWEKdGhpcy5iPWJ9LApBMzpmdW5jdGlvbiBBMyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSTQ6ZnVu
-Y3Rpb24gSTQoYSl7dGhpcy5hPWF9LApGazpmdW5jdGlvbiBGayhhLGIpe3RoaXMuYT1hCnRoaXMuJHRp
-PWJ9LApSTzpmdW5jdGlvbiBSTyhhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8u
-JHRpPWR9LApldTpmdW5jdGlvbiBldShhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1j
-Cl8uJHRpPWR9LAp4QzpmdW5jdGlvbiB4QyhhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5iPWEKXy5jPWIK
-Xy5kPWMKXy5lPWQKXy4kdGk9ZX0sCnZOOmZ1bmN0aW9uIHZOKGEpe3RoaXMuYT1hfSwKSlE6ZnVuY3Rp
-b24gSlEoYSl7dGhpcy5hPWF9LApHbTpmdW5jdGlvbiBHbSgpe30sCnZEOmZ1bmN0aW9uIHZEKGEpe3Ro
-aXMuYT1hfSwKVXY6ZnVuY3Rpb24gVXYoYSl7dGhpcy5hPWF9LApFZzpmdW5jdGlvbiBFZyhhLGIsYyl7
-dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAptNjpmdW5jdGlvbiBtNigpe30sCkVvOmZ1bmN0aW9u
-IEVvKCl7fSwKV2s6ZnVuY3Rpb24gV2soKXt9LApjdDpmdW5jdGlvbiBjdChhLGIsYyxkLGUpe3ZhciBf
-PXRoaXMKXy5lPWEKXy5hPWIKXy5iPWMKXy5jPWQKXy5kPWV9LApJQTpmdW5jdGlvbiBJQSgpe30sCk93
-OmZ1bmN0aW9uIE93KCl7fSwKVzk6ZnVuY3Rpb24gVzkoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5i
-PWIKXy5jPS0xCl8uZD1udWxsCl8uJHRpPWN9LApkVzpmdW5jdGlvbiBkVygpe30sCm1rOmZ1bmN0aW9u
-IG1rKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApLbzpmdW5jdGlvbiBLbyhhKXt0aGlzLmE9YQp0aGlz
-LmI9ITF9LApmbTpmdW5jdGlvbiBmbShhKXt0aGlzLmE9YX0sCkxlOmZ1bmN0aW9uIExlKCl7fSwKSzc6
-ZnVuY3Rpb24gSzcoKXt9LApyQjpmdW5jdGlvbiByQigpe30sClhXOmZ1bmN0aW9uIFhXKCl7fSwKb2E6
-ZnVuY3Rpb24gb2EoKXt9fSxNPXsKT1g6ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UgQy5BZDpyZXR1
-cm4iQWRkIC8qPyovIGhpbnQiCmNhc2UgQy5uZTpyZXR1cm4iQWRkIC8qISovIGhpbnQiCmNhc2UgQy53
-VjpyZXR1cm4iUmVtb3ZlIC8qPyovIGhpbnQiCmNhc2UgQy5mUjpyZXR1cm4iUmVtb3ZlIC8qISovIGhp
-bnQiCmNhc2UgQy5teTpyZXR1cm4iQ2hhbmdlIHRvIC8qPyovIGhpbnQiCmNhc2UgQy5yeDpyZXR1cm4i
-Q2hhbmdlIHRvIC8qISovIGhpbnQifXJldHVybiBudWxsfSwKSDc6ZnVuY3Rpb24gSDcoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCllGOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuLG0sbApmb3Iocz1i
-Lmxlbmd0aCxyPTE7cjxzOysrcil7aWYoYltyXT09bnVsbHx8YltyLTFdIT1udWxsKWNvbnRpbnVlCmZv
-cig7cz49MTtzPXEpe3E9cy0xCmlmKGJbcV0hPW51bGwpYnJlYWt9cD1uZXcgUC5SbigiIikKbz1hKyIo
-IgpwLmE9bwpuPUgudDYoYikKbT1uLkMoIm5IPDE+IikKbD1uZXcgSC5uSChiLDAscyxtKQpsLkhkKGIs
-MCxzLG4uYykKbT1vK25ldyBILmxKKGwsbS5DKCJxVShhTC5FKSIpLmEobmV3IE0uTm8oKSksbS5DKCJs
-SjxhTC5FLHFVPiIpKS5rKDAsIiwgIikKcC5hPW0KcC5hPW0rKCIpOiBwYXJ0ICIrKHItMSkrIiB3YXMg
-bnVsbCwgYnV0IHBhcnQgIityKyIgd2FzIG5vdC4iKQp0aHJvdyBILmIoUC54WShwLncoMCkpKX19LAps
-STpmdW5jdGlvbiBsSShhKXt0aGlzLmE9YX0sCnE3OmZ1bmN0aW9uIHE3KCl7fSwKTm86ZnVuY3Rpb24g
-Tm8oKXt9fSxVPXsKbno6ZnVuY3Rpb24oYSl7dmFyIHM9SC51UChhLnEoMCwibm9kZUlkIikpCnJldHVy
-biBuZXcgVS5MTChDLk5tLkh0KEMucmssbmV3IFUuTUQoYSkpLHMpfSwKTEw6ZnVuY3Rpb24gTEwoYSxi
-KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1EOmZ1bmN0aW9uIE1EKGEpe3RoaXMuYT1hfSwKamY6ZnVuY3Rp
-b24oYSl7dmFyIHMscixxLHAKaWYoYT09bnVsbClzPW51bGwKZWxzZXtzPUguVk0oW10sdC5kNykKZm9y
-KHI9Si5JVCh0LlUuYShhKSk7ci5GKCk7KXtxPXIuZ2woKQpwPUouVTYocSkKcy5wdXNoKG5ldyBVLlNl
-KEguaChwLnEocSwiZGVzY3JpcHRpb24iKSksSC5oKHAucShxLCJocmVmIikpKSl9fXJldHVybiBzfSwK
-TmQ6ZnVuY3Rpb24oYSl7dmFyIHMscgppZihhPT1udWxsKXM9bnVsbAplbHNle3M9SC5WTShbXSx0LmFB
-KQpmb3Iocj1KLklUKHQuVS5hKGEpKTtyLkYoKTspcy5wdXNoKFUuTmYoci5nbCgpKSl9cmV0dXJuIHN9
-LApOZjpmdW5jdGlvbihhKXt2YXIgcz1KLlU2KGEpLHI9SC5oKHMucShhLCJkZXNjcmlwdGlvbiIpKSxx
-PUguVk0oW10sdC5hSikKZm9yKHM9Si5JVCh0LlUuYShzLnEoYSwiZW50cmllcyIpKSk7cy5GKCk7KXEu
-cHVzaChVLlJqKHMuZ2woKSkpCnJldHVybiBuZXcgVS55RChyLHEpfSwKUmo6ZnVuY3Rpb24oYSl7dmFy
-IHMscj1KLlU2KGEpLHE9SC5oKHIucShhLCJkZXNjcmlwdGlvbiIpKSxwPUguaChyLnEoYSwiZnVuY3Rp
-b24iKSksbz1yLnEoYSwibGluayIpCmlmKG89PW51bGwpbz1udWxsCmVsc2V7cz1KLlU2KG8pCm89bmV3
-IFUuTWwoSC5oKHMucShvLCJocmVmIikpLEgudVAocy5xKG8sImxpbmUiKSksSC5oKHMucShvLCJwYXRo
-IikpKX1yPXQuZksuYShyLnEoYSwiaGludEFjdGlvbnMiKSkKcj1yPT1udWxsP251bGw6Si5NMShyLG5l
-dyBVLmFOKCksdC5hWCkKcj1yPT1udWxsP251bGw6ci5icigwKQpyZXR1cm4gbmV3IFUud2IocSxwLG8s
-cj09bnVsbD9DLmRuOnIpfSwKZDI6ZnVuY3Rpb24gZDIoYSxiLGMsZCxlLGYpe3ZhciBfPXRoaXMKXy5h
-PWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWZ9LApTZTpmdW5jdGlvbiBTZShhLGIpe3RoaXMu
-YT1hCnRoaXMuYj1ifSwKTWw6ZnVuY3Rpb24gTWwoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMu
-Yz1jfSwKeUQ6ZnVuY3Rpb24geUQoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCndiOmZ1bmN0aW9uIHdi
-KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LAphTjpmdW5jdGlvbiBh
-Tigpe30sCmIwOmZ1bmN0aW9uIGIwKCl7fX0sQj17CndSOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBCLnFw
-KCIiLCIiLCIiLEMuRHgpfSwKWWY6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0sbCxrPUguaChh
-LnEoMCwicmVnaW9ucyIpKSxqPUguaChhLnEoMCwibmF2aWdhdGlvbkNvbnRlbnQiKSksaT1ILmgoYS5x
-KDAsInNvdXJjZUNvZGUiKSksaD1QLkZsKHQuWCx0LmRfKQpmb3Iocz10LnQuYShhLnEoMCwiZWRpdHMi
-KSkscz1zLmdQdShzKSxzPXMuZ20ocykscj10LlUscT10Lmg0O3MuRigpOyl7cD1zLmdsKCkKbz1wLmEK
-bj1ILlZNKFtdLHEpCmZvcihwPUouSVQoci5hKHAuYikpO3AuRigpOyl7bT1wLmdsKCkKbD1KLlU2KG0p
-Cm4ucHVzaChuZXcgQi5qOChILnVQKGwucShtLCJsaW5lIikpLEguaChsLnEobSwiZXhwbGFuYXRpb24i
-KSksSC51UChsLnEobSwib2Zmc2V0IikpKSl9aC5ZNSgwLG8sbil9cmV0dXJuIG5ldyBCLnFwKGssaixp
-LGgpfSwKajg6ZnVuY3Rpb24gajgoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcXA6
-ZnVuY3Rpb24gcXAoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmZ2
-OmZ1bmN0aW9uIGZ2KCl7fSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoIShhPj02NSYmYTw9OTApKXM9
-YT49OTcmJmE8PTEyMgplbHNlIHM9ITAKcmV0dXJuIHN9LApZdTpmdW5jdGlvbihhLGIpe3ZhciBzPWEu
-bGVuZ3RoLHI9YisyCmlmKHM8cilyZXR1cm4hMQppZighQi5PUyhDLnhCLk8yKGEsYikpKXJldHVybiEx
-CmlmKEMueEIuTzIoYSxiKzEpIT09NTgpcmV0dXJuITEKaWYocz09PXIpcmV0dXJuITAKcmV0dXJuIEMu
-eEIuTzIoYSxyKT09PTQ3fX0sVD17bVE6ZnVuY3Rpb24gbVEoKXt9fSxMPXsKSXE6ZnVuY3Rpb24oKXtD
-LkJaLkIoZG9jdW1lbnQsIkRPTUNvbnRlbnRMb2FkZWQiLG5ldyBMLmUoKSkKQy5vbC5CKHdpbmRvdywi
-cG9wc3RhdGUiLG5ldyBMLkwoKSl9LAprejpmdW5jdGlvbihhKXt2YXIgcyxyPXQuZy5hKGEucGFyZW50
-Tm9kZSkucXVlcnlTZWxlY3RvcigiOnNjb3BlID4gdWwiKSxxPXIuc3R5bGUscD0iIitDLkNELnpRKHIu
-b2Zmc2V0SGVpZ2h0KSoyKyJweCIKcS5tYXhIZWlnaHQ9cApxPUoucUYoYSkKcD1xLiR0aQpzPXAuQygi
-figxKT8iKS5hKG5ldyBMLld4KHIsYSkpCnQuWi5hKG51bGwpClcuSkUocS5hLHEuYixzLCExLHAuYyl9
-LAp5WDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtPSJxdWVyeVNlbGVjdG9yQWxsIixsPWRv
-Y3VtZW50LnF1ZXJ5U2VsZWN0b3IoYSksaz10LmcKbC50b1N0cmluZwpzPXQuaApILkRoKGsscywiVCIs
-bSkKcj10LlIKcT1uZXcgVy53eihsLnF1ZXJ5U2VsZWN0b3JBbGwoIi5uYXYtbGluayIpLHIpCnEuSyhx
-LG5ldyBMLkFPKGIpKQpILkRoKGsscywiVCIsbSkKcD1uZXcgVy53eihsLnF1ZXJ5U2VsZWN0b3JBbGwo
-Ii5yZWdpb24iKSxyKQppZighcC5nbDAocCkpe289bC5xdWVyeVNlbGVjdG9yKCJ0YWJsZVtkYXRhLXBh
-dGhdIikKby50b1N0cmluZwpwLksocCxuZXcgTC5IbyhvLmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBX
-LlN5KG5ldyBXLmk3KG8pKS5QKCJwYXRoIikpKSl9SC5EaChrLHMsIlQiLG0pCm49bmV3IFcud3oobC5x
-dWVyeVNlbGVjdG9yQWxsKCIuYWRkLWhpbnQtbGluayIpLHIpCm4uSyhuLG5ldyBMLklDKCkpfSwKUTY6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPW5ldyBYTUxIdHRwUmVxdWVzdCgpCkMuRHQuZW8ocywiR0VUIixM
-LlE0KGEsYiksITApCnMuc2V0UmVxdWVzdEhlYWRlcigiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24v
-anNvbjsgY2hhcnNldD1VVEYtOCIpCnJldHVybiBMLkxVKHMsbnVsbCxjLkMoIjAqIikpfSwKdHk6ZnVu
-Y3Rpb24oYSxiKXt2YXIgcz1uZXcgWE1MSHR0cFJlcXVlc3QoKSxyPXQuWApDLkR0LmVvKHMsIlBPU1Qi
-LEwuUTQoYSxQLkZsKHIscikpLCEwKQpzLnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIsImFw
-cGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9VVRGLTgiKQpyZXR1cm4gTC5MVShzLGIsdC50KX0sCkxVOmZ1
-bmN0aW9uKGEsYixjKXtyZXR1cm4gTC5UZyhhLGIsYyxjLkMoIjAqIikpfSwKVGc6ZnVuY3Rpb24oYSxi
-LGMsZCl7dmFyIHM9MCxyPVAuRlgoZCkscSxwPTIsbyxuPVtdLG0sbCxrLGosaSxoLGcsZgp2YXIgJGFz
-eW5jJExVPVAubHooZnVuY3Rpb24oZSxhMCl7aWYoZT09PTEpe289YTAKcz1wfXdoaWxlKHRydWUpc3dp
-dGNoKHMpe2Nhc2UgMDppPW5ldyBQLlpmKG5ldyBQLnZzKCQuWDMsdC5nViksdC5iQykKaD10LmViCmc9
-aC5hKG5ldyBMLmZDKGksYSkpCnQuWi5hKG51bGwpCmw9dC5lUQpXLkpFKGEsImxvYWQiLGcsITEsbCkK
-Vy5KRShhLCJlcnJvciIsaC5hKGkuZ1lKKCkpLCExLGwpCmEuc2VuZChiPT1udWxsP251bGw6Qy5DdC5P
-QihiLG51bGwpKQpwPTQKcz03CnJldHVybiBQLmpRKGkuYSwkYXN5bmMkTFUpCmNhc2UgNzpwPTIKcz02
-CmJyZWFrCmNhc2UgNDpwPTMKZj1vCkguUnUoZikKbT1ILnRzKGYpCmg9UC5UbCgiRXJyb3IgcmVhY2hp
-bmcgbWlncmF0aW9uIHByZXZpZXcgc2VydmVyLiIsbSkKdGhyb3cgSC5iKGgpCnM9NgpicmVhawpjYXNl
-IDM6cz0yCmJyZWFrCmNhc2UgNjpqPUMuQ3QucFcoMCxhLnJlc3BvbnNlVGV4dCxudWxsKQppZihhLnN0
-YXR1cz09PTIwMCl7cT1jLkMoIjAqIikuYShqKQpzPTEKYnJlYWt9ZWxzZSB0aHJvdyBILmIoaikKY2Fz
-ZSAxOnJldHVybiBQLnlDKHEscikKY2FzZSAyOnJldHVybiBQLmYzKG8scil9fSkKcmV0dXJuIFAuREko
-JGFzeW5jJExVLHIpfSwKYUs6ZnVuY3Rpb24oYSl7dmFyIHM9UC5oSyhhKS5naFkoKS5xKDAsImxpbmUi
-KQpyZXR1cm4gcz09bnVsbD9udWxsOkguSHAocyxudWxsKX0sCkc2OmZ1bmN0aW9uKGEpe3ZhciBzPVAu
-aEsoYSkuZ2hZKCkucSgwLCJvZmZzZXQiKQpyZXR1cm4gcz09bnVsbD9udWxsOkguSHAocyxudWxsKX0s
-Cmk2OmZ1bmN0aW9uKGEpe3JldHVybiBMLm5XKHQuTy5hKGEpKX0sCm5XOmZ1bmN0aW9uKGEpe3ZhciBz
-PTAscj1QLkZYKHQueikscT0xLHAsbz1bXSxuLG0sbCxrLGosaSxoCnZhciAkYXN5bmMkaTY9UC5seihm
-dW5jdGlvbihiLGMpe2lmKGI9PT0xKXtwPWMKcz1xfXdoaWxlKHRydWUpc3dpdGNoKHMpe2Nhc2UgMDpp
-PXQuZy5hKFcucWMoYS5jdXJyZW50VGFyZ2V0KSkuZ2V0QXR0cmlidXRlKCJocmVmIikKYS5wcmV2ZW50
-RGVmYXVsdCgpCnE9MwprPWRvY3VtZW50Cm49Qy5DRC56UShrLnF1ZXJ5U2VsZWN0b3IoIi5jb250ZW50
-Iikuc2Nyb2xsVG9wKQpzPTYKcmV0dXJuIFAualEoTC50eShpLG51bGwpLCRhc3luYyRpNikKY2FzZSA2
-OnM9NwpyZXR1cm4gUC5qUShMLkc3KHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSxudWxsLG51bGwsITEs
-bnVsbCksJGFzeW5jJGk2KQpjYXNlIDc6az1rLnF1ZXJ5U2VsZWN0b3IoIi5jb250ZW50IikKay50b1N0
-cmluZwprLnNjcm9sbFRvcD1KLlZ1KG4pCnE9MQpzPTUKYnJlYWsKY2FzZSAzOnE9MgpoPXAKbT1ILlJ1
-KGgpCmw9SC50cyhoKQpMLkMyKCJDb3VsZCBub3QgYWRkL3JlbW92ZSBoaW50IixtLGwpCnM9NQpicmVh
-awpjYXNlIDI6cz0xCmJyZWFrCmNhc2UgNTpyZXR1cm4gUC55QyhudWxsLHIpCmNhc2UgMTpyZXR1cm4g
-UC5mMyhwLHIpfX0pCnJldHVybiBQLkRJKCRhc3luYyRpNixyKX0sCkMyOmZ1bmN0aW9uKGEsYixjKXt2
-YXIgcyxyLHEscD0iZXhjZXB0aW9uIixvPSJzdGFja1RyYWNlIixuPXQudC5iKGIpJiZKLlJNKGIucSgw
-LCJzdWNjZXNzIiksITEpJiZiLng0KHApJiZiLng0KG8pLG09Si5pYShiKQppZihuKXtzPUguaChtLnEo
-YixwKSkKYz1tLnEoYixvKX1lbHNlIHM9bS53KGIpCm49ZG9jdW1lbnQKcj1uLnF1ZXJ5U2VsZWN0b3Io
-Ii5wb3B1cC1wYW5lIikKci5xdWVyeVNlbGVjdG9yKCJoMiIpLmlubmVyVGV4dD1hCnIucXVlcnlTZWxl
-Y3RvcigicCIpLmlubmVyVGV4dD1zCnIucXVlcnlTZWxlY3RvcigicHJlIikuaW5uZXJUZXh0PUouaihj
-KQpxPXQuZGQuYShyLnF1ZXJ5U2VsZWN0b3IoImEuYm90dG9tIikpCm09dC5YOyhxJiZDLnhuKS5zTFUo
-cSxQLlhkKCJodHRwcyIsImdpdGh1Yi5jb20iLCJkYXJ0LWxhbmcvc2RrL2lzc3Vlcy9uZXciLFAuRUYo
-WyJ0aXRsZSIsIkN1c3RvbWVyLXJlcG9ydGVkIGlzc3VlIHdpdGggTk5CRCBtaWdyYXRpb24gdG9vbDog
-IithLCJsYWJlbHMiLHUuZCwiYm9keSIsYSsiXG5cbkVycm9yOiAiK0guRWoocykrIlxuXG5QbGVhc2Ug
-ZmlsbCBpbiB0aGUgZm9sbG93aW5nOlxuXG4qKk5hbWUgb2YgcGFja2FnZSBiZWluZyBtaWdyYXRlZCAo
-aWYgcHVibGljKSoqOlxuKipXaGF0IEkgd2FzIGRvaW5nIHdoZW4gdGhpcyBpc3N1ZSBvY2N1cnJlZCoq
-OlxuKipJcyBpdCBwb3NzaWJsZSB0byB3b3JrIGFyb3VuZCB0aGlzIGlzc3VlKio6XG4qKkhhcyB0aGlz
-IGlzc3VlIGhhcHBlbmVkIGJlZm9yZSwgYW5kIGlmIHNvLCBob3cgb2Z0ZW4qKjpcbioqRGFydCBTREsg
-dmVyc2lvbioqOiAiK0guRWoobi5nZXRFbGVtZW50QnlJZCgic2RrLXZlcnNpb24iKS50ZXh0Q29udGVu
-dCkrIlxuKipBZGRpdGlvbmFsIGRldGFpbHMqKjpcblxuVGhhbmtzIGZvciBmaWxpbmchXG5cblN0YWNr
-dHJhY2U6IF9hdXRvIHBvcHVsYXRlZCBieSBtaWdyYXRpb24gcHJldmlldyB0b29sLl9cblxuYGBgXG4i
-K0guRWooYykrIlxuYGBgXG4iXSxtLG0pKS5nbkQoKSkKbT1xLnN0eWxlCm0uZGlzcGxheT0iaW5pdGlh
-bCIKbj1yLnN0eWxlCm4uZGlzcGxheT0iaW5pdGlhbCIKbj1hKyI6ICIrSC5FaihiKQp3aW5kb3cKaWYo
-dHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLmVycm9yKG4pCndpbmRvdwpu
-PUguRWooYykKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLmVycm9y
-KG4pfSwKdDI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG89dC5nLmEoVy5xYyhhLmN1cnJlbnRU
-YXJnZXQpKQphLnByZXZlbnREZWZhdWx0KCkKcz1vLmdldEF0dHJpYnV0ZSgiaHJlZiIpCnI9TC5Vcyhz
-KQpxPUwuRzYocykKcD1MLmFLKHMpCmlmKHEhPW51bGwpTC5hZihyLHEscCxiLG5ldyBMLm5UKHIscSxw
-KSkKZWxzZSBMLmFmKHIsbnVsbCxudWxsLGIsbmV3IEwuTlkocikpfSwKSzA6ZnVuY3Rpb24oYSl7dmFy
-IHMscixxLHA9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnBvcHVwLXBhbmUiKQpwLnF1ZXJ5U2VsZWN0
-b3IoImgyIikuaW5uZXJUZXh0PSJGYWlsZWQgdG8gcmVydW4gZnJvbSBzb3VyY2VzIgpwLnF1ZXJ5U2Vs
-ZWN0b3IoInAiKS5pbm5lclRleHQ9IlNvdXJjZXMgY29udGFpbiBzdGF0aWMgYW5hbHlzaXMgZXJyb3Jz
-OiIKcz1wLnF1ZXJ5U2VsZWN0b3IoInByZSIpCnI9Si5FbChhLHQuYXcpCnE9SC5MaChyKQpzLmlubmVy
-VGV4dD1uZXcgSC5sSihyLHEuQygicVUqKGxELkUpIikuYShuZXcgTC51ZSgpKSxxLkMoImxKPGxELkUs
-cVUqPiIpKS5rKDAsIlxuIikKcT1wLnF1ZXJ5U2VsZWN0b3IoImEuYm90dG9tIikuc3R5bGUKcS5kaXNw
-bGF5PSJub25lIgpzPXAuc3R5bGUKcy5kaXNwbGF5PSJpbml0aWFsIn0sCnZVOmZ1bmN0aW9uKCl7dmFy
-IHM9ZG9jdW1lbnQKSC5EaCh0LmcsdC5oLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnM9bmV3IFcud3oo
-cy5xdWVyeVNlbGVjdG9yQWxsKCIuY29kZSIpLHQuUikKcy5LKHMsbmV3IEwuZVgoKSl9LApoWDpmdW5j
-dGlvbihhLGIsYyl7cmV0dXJuIEwuWXcoYSxiLGMpfSwKWXc6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPTAs
-cj1QLkZYKHQueikscT0xLHAsbz1bXSxuLG0sbCxrLGosaSxoLGcKdmFyICRhc3luYyRoWD1QLmx6KGZ1
-bmN0aW9uKGQsZSl7aWYoZD09PTEpe3A9ZQpzPXF9d2hpbGUodHJ1ZSlzd2l0Y2gocyl7Y2FzZSAwOnE9
-MwpqPXQuWApzPTYKcmV0dXJuIFAualEoTC5RNihhLFAuRUYoWyJyZWdpb24iLCJyZWdpb24iLCJvZmZz
-ZXQiLEguRWooYildLGosaiksdC50KSwkYXN5bmMkaFgpCmNhc2UgNjpuPWUKaj1uCmk9Si5VNihqKQpt
-PW5ldyBVLmQyKFUuamYoaS5xKGosImVkaXRzIikpLEguaChpLnEoaiwiZXhwbGFuYXRpb24iKSksSC51
-UChpLnEoaiwibGluZSIpKSxILmgoaS5xKGosImRpc3BsYXlQYXRoIikpLEguaChpLnEoaiwidXJpUGF0
-aCIpKSxVLk5kKGkucShqLCJ0cmFjZXMiKSkpCkwuVDEobSkKTC5GcihhLGIsYykKTC55WCgiLmVkaXQt
-cGFuZWwgLnBhbmVsLWNvbnRlbnQiLCExKQpxPTEKcz01CmJyZWFrCmNhc2UgMzpxPTIKZz1wCmw9SC5S
-dShnKQprPUgudHMoZykKTC5DMigiQ291bGQgbm90IGxvYWQgZWRpdCBkZXRhaWxzIixsLGspCnM9NQpi
-cmVhawpjYXNlIDI6cz0xCmJyZWFrCmNhc2UgNTpyZXR1cm4gUC55QyhudWxsLHIpCmNhc2UgMTpyZXR1
-cm4gUC5mMyhwLHIpfX0pCnJldHVybiBQLkRJKCRhc3luYyRoWCxyKX0sCkc3OmZ1bmN0aW9uKGEsYixj
-LGQsZSl7cmV0dXJuIEwuTDUoYSxiLGMsZCxlKX0sCkw1OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHM9
-MCxyPVAuRlgodC5IKSxxLHA9MixvLG49W10sbSxsLGssaixpLGgsZwp2YXIgJGFzeW5jJEc3PVAubHoo
-ZnVuY3Rpb24oZixhMCl7aWYoZj09PTEpe289YTAKcz1wfXdoaWxlKHRydWUpc3dpdGNoKHMpe2Nhc2Ug
-MDppZighSi5wNChhLCIuZGFydCIpKXtMLkJFKGEsQi53UigpLGQpCkwuQlgoYSxudWxsKQppZihlIT1u
-dWxsKWUuJDAoKQpzPTEKYnJlYWt9cD00Cmk9dC5YCnM9NwpyZXR1cm4gUC5qUShMLlE2KGEsUC5FRihb
-ImlubGluZSIsInRydWUiXSxpLGkpLHQudCksJGFzeW5jJEc3KQpjYXNlIDc6bT1hMApMLkJFKGEsQi5Z
-ZihtKSxkKQpMLmZHKGIsYykKbD1MLlVzKGEpCkwuQlgobCxiKQppZihlIT1udWxsKWUuJDAoKQpwPTIK
-cz02CmJyZWFrCmNhc2UgNDpwPTMKZz1vCms9SC5SdShnKQpqPUgudHMoZykKTC5DMigiQ291bGQgbm90
-IGxvYWQgZGFydCBmaWxlICIrYSxrLGopCnM9NgpicmVhawpjYXNlIDM6cz0yCmJyZWFrCmNhc2UgNjpj
-YXNlIDE6cmV0dXJuIFAueUMocSxyKQpjYXNlIDI6cmV0dXJuIFAuZjMobyxyKX19KQpyZXR1cm4gUC5E
-SSgkYXN5bmMkRzcscil9LApHZTpmdW5jdGlvbigpe3ZhciBzPTAscj1QLkZYKHQueikscT0xLHAsbz1b
-XSxuLG0sbCxrLGosaSxoLGcKdmFyICRhc3luYyRHZT1QLmx6KGZ1bmN0aW9uKGEsYil7aWYoYT09PTEp
-e3A9YgpzPXF9d2hpbGUodHJ1ZSlzd2l0Y2gocyl7Y2FzZSAwOmg9Ii9fcHJldmlldy9uYXZpZ2F0aW9u
-VHJlZS5qc29uIgpxPTMKcz02CnJldHVybiBQLmpRKEwuUTYoaCxDLkNNLHQubSksJGFzeW5jJEdlKQpj
-YXNlIDY6bj1iCm09ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLm5hdi10cmVlIikKSi5sNShtLCIiKQpq
-PUwubUsobikKJC5JUj1qCkwudFgobSxqLCExKQpxPTEKcz01CmJyZWFrCmNhc2UgMzpxPTIKZz1wCmw9
-SC5SdShnKQprPUgudHMoZykKTC5DMigiQ291bGQgbm90IGxvYWQgbmF2aWdhdGlvbiB0cmVlIixsLGsp
-CnM9NQpicmVhawpjYXNlIDI6cz0xCmJyZWFrCmNhc2UgNTpyZXR1cm4gUC55QyhudWxsLHIpCmNhc2Ug
-MTpyZXR1cm4gUC5mMyhwLHIpfX0pCnJldHVybiBQLkRJKCRhc3luYyRHZSxyKX0sCnFPOmZ1bmN0aW9u
-KGEpe3ZhciBzLHI9YS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxxPUMuQ0QuelEoJC5maSgpLm9mZnNl
-dEhlaWdodCkscD13aW5kb3cuaW5uZXJIZWlnaHQsbz1DLkNELnpRKCQuRFcoKS5vZmZzZXRIZWlnaHQp
-CmlmKHR5cGVvZiBwIT09Im51bWJlciIpcmV0dXJuIHAuSE4oKQpzPXIuYm90dG9tCnMudG9TdHJpbmcK
-aWYocz5wLShvKzE0KSlKLmRoKGEpCmVsc2V7cD1yLnRvcApwLnRvU3RyaW5nCmlmKHA8cSsxNClKLmRo
-KGEpfX0sCmZHOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbwppZihhIT1udWxsKXtzPWRvY3VtZW50
-CnI9cy5nZXRFbGVtZW50QnlJZCgibyIrSC5FaihhKSkKcT1zLnF1ZXJ5U2VsZWN0b3IoIi5saW5lLSIr
-SC5FaihiKSkKaWYociE9bnVsbCl7TC5xTyhyKQpKLmRSKHIpLmkoMCwidGFyZ2V0Iil9ZWxzZSBpZihx
-IT1udWxsKUwucU8ocS5wYXJlbnRFbGVtZW50KQppZihxIT1udWxsKUouZFIodC5nLmEocS5wYXJlbnRO
-b2RlKSkuaSgwLCJoaWdobGlnaHQiKX1lbHNle3M9ZG9jdW1lbnQKcD10LmcKSC5EaChwLHQuaCwiVCIs
-InF1ZXJ5U2VsZWN0b3JBbGwiKQpzPXMucXVlcnlTZWxlY3RvckFsbCgiLmxpbmUtbm8iKQpvPW5ldyBX
-Lnd6KHMsdC5SKQppZihvLmdBKG8pPT09MClyZXR1cm4KTC5xTyhwLmEoQy50NS5ndEgocykpKX19LAph
-ZjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBzLHIscT1MLkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKSxw
-PUwuYUsod2luZG93LmxvY2F0aW9uLmhyZWYpCmlmKHEhPW51bGwpe3M9ZG9jdW1lbnQuZ2V0RWxlbWVu
-dEJ5SWQoIm8iK0guRWoocSkpCmlmKHMhPW51bGwpSi5kUihzKS5MKDAsInRhcmdldCIpfWlmKHAhPW51
-bGwpe3I9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLmxpbmUtIitILkVqKHApKQppZihyIT1udWxsKUou
-ZFIoci5wYXJlbnRFbGVtZW50KS5MKDAsImhpZ2hsaWdodCIpfWlmKGE9PXdpbmRvdy5sb2NhdGlvbi5w
-YXRobmFtZSl7TC5mRyhiLGMpCmUuJDAoKX1lbHNlIEwuRzcoYSxiLGMsZCxlKX0sClE0OmZ1bmN0aW9u
-KGEsYil7dmFyIHMscixxPVAuaEsoYSkscD10LlgKcD1QLkZsKHAscCkKZm9yKHM9cS5naFkoKSxzPXMu
-Z1B1KHMpLHM9cy5nbShzKTtzLkYoKTspe3I9cy5nbCgpCnAuWTUoMCxyLmEsci5iKX1mb3Iocz1iLmdQ
-dShiKSxzPXMuZ20ocyk7cy5GKCk7KXtyPXMuZ2woKQpwLlk1KDAsci5hLHIuYil9cC5ZNSgwLCJhdXRo
-VG9rZW4iLCQuVUUoKSkKcmV0dXJuIHEubm0oMCxwKS5nbkQoKX0sClQxOmZ1bmN0aW9uKGEpe3ZhciBz
-LHIscSxwLG8sbixtLGwsayxqPSQuaEwoKQpKLmw1KGosIiIpCmlmKGE9PW51bGwpe3M9ZG9jdW1lbnQu
-Y3JlYXRlRWxlbWVudCgicCIpCkMuTHQuc2E0KHMsIlNlZSBkZXRhaWxzIGFib3V0IGEgcHJvcG9zZWQg
-ZWRpdC4iKQpDLkx0LnNuKHMsSC5WTShbInBsYWNlaG9sZGVyIl0sdC5pKSkKai5hcHBlbmRDaGlsZChz
-KQpDLkx0LkZGKHMpCnJldHVybn1yPWEuZApxPSQublUoKQpwPXEuemYocikKbz1hLmIKbj1kb2N1bWVu
-dAptPXEuSFAocixKLlQwKG4ucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpCmw9YS5j
-Cms9bi5jcmVhdGVFbGVtZW50KCJwIikKai5hcHBlbmRDaGlsZChrKQprLmFwcGVuZENoaWxkKG4uY3Jl
-YXRlVGV4dE5vZGUoSC5FaihvKSsiIGF0ICIpKQpxPXQuWApxPVcuSjYoTC5RNChhLmUsUC5FRihbImxp
-bmUiLEouaihsKV0scSxxKSkpCnEuYXBwZW5kQ2hpbGQobi5jcmVhdGVUZXh0Tm9kZShILkVqKG0pKyI6
-IitILkVqKGwpKyIuIikpCmsuYXBwZW5kQ2hpbGQocSkKSi5kaChrKQpMLkNDKGEsaixwKQpMLkZ6KGEs
-ail9LApMSDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlPSQu
-eVAoKQpKLmw1KGUsIiIpCmlmKGIuZ0EoYik9PT0wKXtzPWRvY3VtZW50CnI9cy5jcmVhdGVFbGVtZW50
-KCJwIikKZS5hcHBlbmRDaGlsZChyKQpyLmFwcGVuZENoaWxkKHMuY3JlYXRlVGV4dE5vZGUoIk5vIHBy
-b3Bvc2VkIGVkaXRzIikpfWVsc2UgZm9yKGU9Yi5nUHUoYiksZT1lLmdtKGUpLHM9dC5YLHE9dC5rLHA9
-cS5DKCJ+KDEpPyIpLG89dC5aLHE9cS5jO2UuRigpOyl7bj1lLmdsKCkKbT1kb2N1bWVudApyPW0uY3Jl
-YXRlRWxlbWVudCgicCIpCmw9JC55UCgpCmwuYXBwZW5kQ2hpbGQocikKci5hcHBlbmRDaGlsZChtLmNy
-ZWF0ZVRleHROb2RlKEguRWoobi5hKSsiOiIpKQprPW0uY3JlYXRlRWxlbWVudCgidWwiKQpsLmFwcGVu
-ZENoaWxkKGspCmZvcihuPUouSVQobi5iKTtuLkYoKTspe2w9bi5nbCgpCmo9bS5jcmVhdGVFbGVtZW50
-KCJsaSIpCmsuYXBwZW5kQ2hpbGQoaikKSi5kUihqKS5pKDAsImVkaXQiKQppPW0uY3JlYXRlRWxlbWVu
-dCgiYSIpCmouYXBwZW5kQ2hpbGQoaSkKaS5jbGFzc0xpc3QuYWRkKCJlZGl0LWxpbmsiKQpoPWwuYwpn
-PUguRWooaCkKaS5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhpKSkuUCgib2Zm
-c2V0IiksZykKZj1sLmEKZz1ILkVqKGYpCmkuc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3
-IFcuaTcoaSkpLlAoImxpbmUiKSxnKQppLmFwcGVuZENoaWxkKG0uY3JlYXRlVGV4dE5vZGUoImxpbmUg
-IitILkVqKGYpKSkKaS5zZXRBdHRyaWJ1dGUoImhyZWYiLEwuUTQod2luZG93LmxvY2F0aW9uLnBhdGhu
-YW1lLFAuRUYoWyJsaW5lIixILkVqKGYpLCJvZmZzZXQiLEguRWooaCldLHMscykpKQpnPXAuYShuZXcg
-TC5FRShoLGYsYSkpCm8uYShudWxsKQpXLkpFKGksImNsaWNrIixnLCExLHEpCmouYXBwZW5kQ2hpbGQo
-bS5jcmVhdGVUZXh0Tm9kZSgiOiAiK0guRWoobC5iKSkpfX1pZihjKUwuVDEobnVsbCl9LApGcjpmdW5j
-dGlvbihhLGIsYyl7dmFyIHMscixxPXdpbmRvdy5sb2NhdGlvbixwPVAuaEsoKHEmJkMuRXgpLmdEcihx
-KStILkVqKGEpKQpxPXQuWApxPVAuRmwocSxxKQppZihiIT1udWxsKXEuWTUoMCwib2Zmc2V0IixILkVq
-KGIpKQppZihjIT1udWxsKXEuWTUoMCwibGluZSIsSC5FaihjKSkKcS5ZNSgwLCJhdXRoVG9rZW4iLCQu
-VUUoKSkKcD1wLm5tKDAscSkKcT13aW5kb3cuaGlzdG9yeQpzPXQuegpyPXAuZ25EKCkKcS50b1N0cmlu
-ZwpxLnB1c2hTdGF0ZShuZXcgUC5CZihbXSxbXSkuUHYoUC5GbChzLHMpKSwiIixyKX0sCkVuOmZ1bmN0
-aW9uKGEpe3ZhciBzPUouYmIoZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVu
-dCwiLyIpCmlmKEMueEIubkMoYSxzKSlyZXR1cm4gQy54Qi55bihhLHMubGVuZ3RoKQplbHNlIHJldHVy
-biBhfSwKT3Q6ZnVuY3Rpb24oYSl7c3dpdGNoKGEucil7Y2FzZSBDLmN3OmJyZWFrCmNhc2UgQy5XRDph
-LnI9Qy5YagpicmVhawpjYXNlIEMuWGo6YS5yPUMuV0QKYnJlYWsKY2FzZSBDLmRjOnRocm93IEguYihQ
-LlBWKCJGaWxlICIrSC5FaihhLmMpKyIgc2hvdWxkIG5vdCBoYXZlIGluZGV0ZXJtaW5hdGUgbWlncmF0
-aW9uIHN0YXR1cyIpKX19LAp4bjpmdW5jdGlvbihhLGIpe0wudGEoYSxiLmdkNigpKQppZihiLmM9PSQu
-RDkoKS5pbm5lclRleHQpTC50YSgkLmMwKCksYi5nZDYoKSl9LAp0YTpmdW5jdGlvbihhLGIpe3ZhciBz
-LHI9ImNoZWNrX2JveCIscT0idGl0bGUiLHA9Im9wdGVkLW91dCIsbz0ibWlncmF0aW5nIgpzd2l0Y2go
-Yil7Y2FzZSBDLmN3OmEuaW5uZXJUZXh0PXIKSi5kUihhKS5pKDAsImFscmVhZHktbWlncmF0ZWQiKQph
+OnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gby5pfWVsc2UgcmV0dXJuIEguTGMoYSxzKX0s
+CkxjOmZ1bmN0aW9uKGEsYil7dmFyIHM9T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpCk9iamVjdC5kZWZp
+bmVQcm9wZXJ0eShzLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOkouUXUoYixzLG51bGwsbnVs
+bCksZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJu
+IGJ9LApWYTpmdW5jdGlvbihhKXtyZXR1cm4gSi5RdShhLCExLG51bGwsISFhLiRpWGopfSwKVkY6ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciBzPWIucHJvdG90eXBlCmlmKHYubGVhZlRhZ3NbYV09PT10cnVlKXJldHVy
+biBILlZhKHMpCmVsc2UgcmV0dXJuIEouUXUocyxjLG51bGwsbnVsbCl9LApYRDpmdW5jdGlvbigpe2lm
+KCEwPT09JC5CdilyZXR1cm4KJC5Cdj0hMApILloxKCl9LApaMTpmdW5jdGlvbigpe3ZhciBzLHIscSxw
+LG8sbixtLGwKJC5udz1PYmplY3QuY3JlYXRlKG51bGwpCiQudnY9T2JqZWN0LmNyZWF0ZShudWxsKQpI
+LmtPKCkKcz12LmludGVyY2VwdG9yc0J5VGFnCnI9T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocykK
+aWYodHlwZW9mIHdpbmRvdyE9InVuZGVmaW5lZCIpe3dpbmRvdwpxPWZ1bmN0aW9uKCl7fQpmb3IocD0w
+O3A8ci5sZW5ndGg7KytwKXtvPXJbcF0Kbj0kLng3LiQxKG8pCmlmKG4hPW51bGwpe209SC5WRihvLHNb
+b10sbikKaWYobSE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KG4sdi5kaXNwYXRjaFByb3BlcnR5
+TmFtZSx7dmFsdWU6bSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRy
+dWV9KQpxLnByb3RvdHlwZT1ufX19fWZvcihwPTA7cDxyLmxlbmd0aDsrK3Ape289cltwXQppZigvXltB
+LVphLXpfXS8udGVzdChvKSl7bD1zW29dCnNbIiEiK29dPWwKc1sifiIrb109bApzWyItIitvXT1sCnNb
+IisiK29dPWwKc1siKiIrb109bH19fSwKa086ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbT1DLllx
+KCkKbT1ILnVkKEMuS1UsSC51ZChDLmZRLEgudWQoQy5pNyxILnVkKEMuaTcsSC51ZChDLnhpLEgudWQo
+Qy5kayxILnVkKEMud2IoQy5PNCksbSkpKSkpKSkKaWYodHlwZW9mIGRhcnROYXRpdmVEaXNwYXRjaEhv
+b2tzVHJhbnNmb3JtZXIhPSJ1bmRlZmluZWQiKXtzPWRhcnROYXRpdmVEaXNwYXRjaEhvb2tzVHJhbnNm
+b3JtZXIKaWYodHlwZW9mIHM9PSJmdW5jdGlvbiIpcz1bc10KaWYocy5jb25zdHJ1Y3Rvcj09QXJyYXkp
+Zm9yKHI9MDtyPHMubGVuZ3RoOysrcil7cT1zW3JdCmlmKHR5cGVvZiBxPT0iZnVuY3Rpb24iKW09cSht
+KXx8bX19cD1tLmdldFRhZwpvPW0uZ2V0VW5rbm93blRhZwpuPW0ucHJvdG90eXBlRm9yVGFnCiQuTkY9
+bmV3IEguZEMocCkKJC5UWD1uZXcgSC53TihvKQokLng3PW5ldyBILlZYKG4pfSwKdWQ6ZnVuY3Rpb24o
+YSxiKXtyZXR1cm4gYShiKXx8Yn0sCnY0OmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgcz1iPyJtIjoi
+IixyPWM/IiI6ImkiLHE9ZD8idSI6IiIscD1lPyJzIjoiIixvPWY/ImciOiIiLG49ZnVuY3Rpb24oZyxo
+KXt0cnl7cmV0dXJuIG5ldyBSZWdFeHAoZyxoKX1jYXRjaChtKXtyZXR1cm4gbX19KGEscytyK3ErcCtv
+KQppZihuIGluc3RhbmNlb2YgUmVnRXhwKXJldHVybiBuCnRocm93IEguYihQLnJyKCJJbGxlZ2FsIFJl
+Z0V4cCBwYXR0ZXJuICgiK1N0cmluZyhuKSsiKSIsYSxudWxsKSl9LApTUTpmdW5jdGlvbihhLGIsYyl7
+dmFyIHMKaWYodHlwZW9mIGI9PSJzdHJpbmciKXJldHVybiBhLmluZGV4T2YoYixjKT49MAplbHNlIGlm
+KGIgaW5zdGFuY2VvZiBILlZSKXtzPUMueEIueW4oYSxjKQpyZXR1cm4gYi5iLnRlc3Qocyl9ZWxzZXtz
+PUouRkwoYixDLnhCLnluKGEsYykpCnJldHVybiFzLmdsMChzKX19LApBNDpmdW5jdGlvbihhKXtpZihh
+LmluZGV4T2YoIiQiLDApPj0wKXJldHVybiBhLnJlcGxhY2UoL1wkL2csIiQkJCQiKQpyZXR1cm4gYX0s
+CmVBOmZ1bmN0aW9uKGEpe2lmKC9bW1xde30oKSorPy5cXF4kfF0vLnRlc3QoYSkpcmV0dXJuIGEucmVw
+bGFjZSgvW1tcXXt9KCkqKz8uXFxeJHxdL2csIlxcJCYiKQpyZXR1cm4gYX0sCnlzOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgcz1ILm5NKGEsYixjKQpyZXR1cm4gc30sCm5NOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxy
+LHEscAppZihiPT09IiIpe2lmKGE9PT0iIilyZXR1cm4gYwpzPWEubGVuZ3RoCmZvcihyPWMscT0wO3E8
+czsrK3Epcj1yK2FbcV0rYwpyZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn1wPWEuaW5kZXhPZihi
+LDApCmlmKHA8MClyZXR1cm4gYQppZihhLmxlbmd0aDw1MDB8fGMuaW5kZXhPZigiJCIsMCk+PTApcmV0
+dXJuIGEuc3BsaXQoYikuam9pbihjKQpyZXR1cm4gYS5yZXBsYWNlKG5ldyBSZWdFeHAoSC5lQShiKSwn
+ZycpLEguQTQoYykpfSwKUEQ6ZnVuY3Rpb24gUEQoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKV1U6
+ZnVuY3Rpb24gV1UoKXt9LApMUDpmdW5jdGlvbiBMUChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8u
+Yj1iCl8uYz1jCl8uJHRpPWR9LApYUjpmdW5jdGlvbiBYUihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9
+LApMSTpmdW5jdGlvbiBMSShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPWEKXy5jPWIKXy5kPWMKXy5l
+PWQKXy5mPWV9LApDajpmdW5jdGlvbiBDaihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9
+LApmOTpmdW5jdGlvbiBmOShhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9Ywpf
+LmQ9ZApfLmU9ZQpfLmY9Zn0sClcwOmZ1bmN0aW9uIFcwKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAph
+ejpmdW5jdGlvbiBheihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAp2VjpmdW5jdGlv
+biB2VihhKXt0aGlzLmE9YX0sCnRlOmZ1bmN0aW9uIHRlKGEpe3RoaXMuYT1hfSwKYnE6ZnVuY3Rpb24g
+YnEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sClhPOmZ1bmN0aW9uIFhPKGEpe3RoaXMuYT1hCnRoaXMu
+Yj1udWxsfSwKVHA6ZnVuY3Rpb24gVHAoKXt9LApsYzpmdW5jdGlvbiBsYygpe30sCnp4OmZ1bmN0aW9u
+IHp4KCl7fSwKclQ6ZnVuY3Rpb24gclQoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9
+YwpfLmQ9ZH0sCkVxOmZ1bmN0aW9uIEVxKGEpe3RoaXMuYT1hfSwKa1k6ZnVuY3Rpb24ga1koYSl7dGhp
+cy5hPWF9LAprcjpmdW5jdGlvbiBrcigpe30sCk41OmZ1bmN0aW9uIE41KGEpe3ZhciBfPXRoaXMKXy5h
+PTAKXy5mPV8uZT1fLmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LAp2aDpmdW5jdGlvbiB2aChh
+LGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKaTU6ZnVuY3Rpb24gaTUoYSxi
+KXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKTjY6ZnVuY3Rpb24gTjYoYSxiLGMpe3ZhciBfPXRoaXMKXy5h
+PWEKXy5iPWIKXy5kPV8uYz1udWxsCl8uJHRpPWN9LApkQzpmdW5jdGlvbiBkQyhhKXt0aGlzLmE9YX0s
+CndOOmZ1bmN0aW9uIHdOKGEpe3RoaXMuYT1hfSwKVlg6ZnVuY3Rpb24gVlgoYSl7dGhpcy5hPWF9LApW
+UjpmdW5jdGlvbiBWUihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKRUs6
+ZnVuY3Rpb24gRUsoYSl7dGhpcy5iPWF9LApLVzpmdW5jdGlvbiBLVyhhLGIsYyl7dGhpcy5hPWEKdGhp
+cy5iPWIKdGhpcy5jPWN9LApQYjpmdW5jdGlvbiBQYihhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9
+YgpfLmM9YwpfLmQ9bnVsbH0sCnRROmZ1bmN0aW9uIHRRKGEsYil7dGhpcy5hPWEKdGhpcy5jPWJ9LAp1
+bjpmdW5jdGlvbiB1bihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApTZDpmdW5jdGlv
+biBTZChhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9bnVsbH0sClhGOmZ1bmN0
+aW9uKGEpe3JldHVybiBhfSwKb2Q6ZnVuY3Rpb24oYSxiLGMpe2lmKGE+Pj4wIT09YXx8YT49Yyl0aHJv
+dyBILmIoSC5IWShiLGEpKX0sCnJNOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwppZighKGE+Pj4wIT09YSkp
+cz1iPj4+MCE9PWJ8fGE+Ynx8Yj5jCmVsc2Ugcz0hMAppZihzKXRocm93IEguYihILmF1KGEsYixjKSkK
+cmV0dXJuIGJ9LApFVDpmdW5jdGlvbiBFVCgpe30sCkxaOmZ1bmN0aW9uIExaKCl7fSwKRGc6ZnVuY3Rp
+b24gRGcoKXt9LApQZzpmdW5jdGlvbiBQZygpe30sCnhqOmZ1bmN0aW9uIHhqKCl7fSwKZEU6ZnVuY3Rp
+b24gZEUoKXt9LApaQTpmdW5jdGlvbiBaQSgpe30sCmRUOmZ1bmN0aW9uIGRUKCl7fSwKUHE6ZnVuY3Rp
+b24gUHEoKXt9LAplRTpmdW5jdGlvbiBlRSgpe30sClY2OmZ1bmN0aW9uIFY2KCl7fSwKUkc6ZnVuY3Rp
+b24gUkcoKXt9LApWUDpmdW5jdGlvbiBWUCgpe30sCldCOmZ1bmN0aW9uIFdCKCl7fSwKWkc6ZnVuY3Rp
+b24gWkcoKXt9LApjejpmdW5jdGlvbihhLGIpe3ZhciBzPWIuYwpyZXR1cm4gcz09bnVsbD9iLmM9SC5C
+KGEsYi56LCEwKTpzfSwKeFo6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iLmMKcmV0dXJuIHM9PW51bGw/Yi5j
+PUguSihhLCJiOCIsW2Iuel0pOnN9LApRMTpmdW5jdGlvbihhKXt2YXIgcz1hLnkKaWYocz09PTZ8fHM9
+PT03fHxzPT09OClyZXR1cm4gSC5RMShhLnopCnJldHVybiBzPT09MTF8fHM9PT0xMn0sCm1EOmZ1bmN0
+aW9uKGEpe3JldHVybiBhLmN5fSwKTjA6ZnVuY3Rpb24oYSl7cmV0dXJuIEguRSh2LnR5cGVVbml2ZXJz
+ZSxhLCExKX0sClBMOmZ1bmN0aW9uKGEsYixhMCxhMSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxo
+LGcsZixlLGQsYz1iLnkKc3dpdGNoKGMpe2Nhc2UgNTpjYXNlIDE6Y2FzZSAyOmNhc2UgMzpjYXNlIDQ6
+cmV0dXJuIGIKY2FzZSA2OnM9Yi56CnI9SC5QTChhLHMsYTAsYTEpCmlmKHI9PT1zKXJldHVybiBiCnJl
+dHVybiBILkMoYSxyLCEwKQpjYXNlIDc6cz1iLnoKcj1ILlBMKGEscyxhMCxhMSkKaWYocj09PXMpcmV0
+dXJuIGIKcmV0dXJuIEguQihhLHIsITApCmNhc2UgODpzPWIuegpyPUguUEwoYSxzLGEwLGExKQppZihy
+PT09cylyZXR1cm4gYgpyZXR1cm4gSC5mKGEsciwhMCkKY2FzZSA5OnE9Yi5RCnA9SC5iWihhLHEsYTAs
+YTEpCmlmKHA9PT1xKXJldHVybiBiCnJldHVybiBILkooYSxiLnoscCkKY2FzZSAxMDpvPWIuegpuPUgu
+UEwoYSxvLGEwLGExKQptPWIuUQpsPUguYlooYSxtLGEwLGExKQppZihuPT09byYmbD09PW0pcmV0dXJu
+IGIKcmV0dXJuIEguYShhLG4sbCkKY2FzZSAxMTprPWIuegpqPUguUEwoYSxrLGEwLGExKQppPWIuUQpo
+PUgucVQoYSxpLGEwLGExKQppZihqPT09ayYmaD09PWkpcmV0dXJuIGIKcmV0dXJuIEguZChhLGosaCkK
+Y2FzZSAxMjpnPWIuUQphMSs9Zy5sZW5ndGgKZj1ILmJaKGEsZyxhMCxhMSkKbz1iLnoKbj1ILlBMKGEs
+byxhMCxhMSkKaWYoZj09PWcmJm49PT1vKXJldHVybiBiCnJldHVybiBILkQoYSxuLGYsITApCmNhc2Ug
+MTM6ZT1iLnoKaWYoZTxhMSlyZXR1cm4gYgpkPWEwW2UtYTFdCmlmKGQ9PW51bGwpcmV0dXJuIGIKcmV0
+dXJuIGQKZGVmYXVsdDp0aHJvdyBILmIoUC5oVigiQXR0ZW1wdGVkIHRvIHN1YnN0aXR1dGUgdW5leHBl
+Y3RlZCBSVEkga2luZCAiK2MpKX19LApiWjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEscCxvPWIu
+bGVuZ3RoLG49W10KZm9yKHM9ITEscj0wO3I8bzsrK3Ipe3E9YltyXQpwPUguUEwoYSxxLGMsZCkKaWYo
+cCE9PXEpcz0hMApuLnB1c2gocCl9cmV0dXJuIHM/bjpifSwKdk86ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHMscixxLHAsbyxuLG09Yi5sZW5ndGgsbD1bXQpmb3Iocz0hMSxyPTA7cjxtO3IrPTMpe3E9YltyXQpw
+PWJbcisxXQpvPWJbcisyXQpuPUguUEwoYSxvLGMsZCkKaWYobiE9PW8pcz0hMApsLnB1c2gocSkKbC5w
+dXNoKHApCmwucHVzaChuKX1yZXR1cm4gcz9sOmJ9LApxVDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxy
+PWIuYSxxPUguYlooYSxyLGMsZCkscD1iLmIsbz1ILmJaKGEscCxjLGQpLG49Yi5jLG09SC52TyhhLG4s
+YyxkKQppZihxPT09ciYmbz09PXAmJm09PT1uKXJldHVybiBiCnM9bmV3IEguRygpCnMuYT1xCnMuYj1v
+CnMuYz1tCnJldHVybiBzfSwKVk06ZnVuY3Rpb24oYSxiKXthW3YuYXJyYXlSdGldPWIKcmV0dXJuIGF9
+LApKUzpmdW5jdGlvbihhKXt2YXIgcz1hLiRTCmlmKHMhPW51bGwpe2lmKHR5cGVvZiBzPT0ibnVtYmVy
+IilyZXR1cm4gSC5CcChzKQpyZXR1cm4gYS4kUygpfXJldHVybiBudWxsfSwKVWU6ZnVuY3Rpb24oYSxi
+KXt2YXIgcwppZihILlExKGIpKWlmKGEgaW5zdGFuY2VvZiBILlRwKXtzPUguSlMoYSkKaWYocyE9bnVs
+bClyZXR1cm4gc31yZXR1cm4gSC56KGEpfSwKejpmdW5jdGlvbihhKXt2YXIgcwppZihhIGluc3RhbmNl
+b2YgUC5NaCl7cz1hLiR0aQpyZXR1cm4gcyE9bnVsbD9zOkguVlUoYSl9aWYoQXJyYXkuaXNBcnJheShh
+KSlyZXR1cm4gSC50NihhKQpyZXR1cm4gSC5WVShKLmlhKGEpKX0sCnQ2OmZ1bmN0aW9uKGEpe3ZhciBz
+PWFbdi5hcnJheVJ0aV0scj10LmIKaWYocz09bnVsbClyZXR1cm4gcgppZihzLmNvbnN0cnVjdG9yIT09
+ci5jb25zdHJ1Y3RvcilyZXR1cm4gcgpyZXR1cm4gc30sCkxoOmZ1bmN0aW9uKGEpe3ZhciBzPWEuJHRp
+CnJldHVybiBzIT1udWxsP3M6SC5WVShhKX0sClZVOmZ1bmN0aW9uKGEpe3ZhciBzPWEuY29uc3RydWN0
+b3Iscj1zLiRjY2FjaGUKaWYociE9bnVsbClyZXR1cm4gcgpyZXR1cm4gSC5yOShhLHMpfSwKcjk6ZnVu
+Y3Rpb24oYSxiKXt2YXIgcz1hIGluc3RhbmNlb2YgSC5UcD9hLl9fcHJvdG9fXy5fX3Byb3RvX18uY29u
+c3RydWN0b3I6YixyPUguYWkodi50eXBlVW5pdmVyc2Uscy5uYW1lKQpiLiRjY2FjaGU9cgpyZXR1cm4g
+cn0sCkJwOmZ1bmN0aW9uKGEpe3ZhciBzLHIscQpILnVQKGEpCnM9di50eXBlcwpyPXNbYV0KaWYodHlw
+ZW9mIHI9PSJzdHJpbmciKXtxPUguRSh2LnR5cGVVbml2ZXJzZSxyLCExKQpzW2FdPXEKcmV0dXJuIHF9
+cmV0dXJuIHJ9LApLeDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD1hLngKaWYocCE9bnVsbClyZXR1cm4g
+cApzPWEuY3kKcj1zLnJlcGxhY2UoL1wqL2csIiIpCmlmKHI9PT1zKXJldHVybiBhLng9bmV3IEgubFko
+YSkKcT1ILkUodi50eXBlVW5pdmVyc2UsciwhMCkKcD1xLngKcmV0dXJuIGEueD1wPT1udWxsP3EueD1u
+ZXcgSC5sWShxKTpwfSwKSko6ZnVuY3Rpb24oYSl7dmFyIHMscixxPXRoaXMscD10LksKaWYocT09PXAp
+cmV0dXJuIEguUkUocSxhLEgua2UpCmlmKCFILkE4KHEpKWlmKCEocT09PXQuXykpcD1xPT09cAplbHNl
+IHA9ITAKZWxzZSBwPSEwCmlmKHApcmV0dXJuIEguUkUocSxhLEguSXcpCnA9cS55CnM9cD09PTY/cS56
+OnEKaWYocz09PXQuUylyPUgub2sKZWxzZSBpZihzPT09dC5nUnx8cz09PXQuZGkpcj1ILktICmVsc2Ug
+aWYocz09PXQuTilyPUguTU0KZWxzZSByPXM9PT10Lnk/SC5sOm51bGwKaWYociE9bnVsbClyZXR1cm4g
+SC5SRShxLGEscikKaWYocy55PT09OSl7cD1zLnoKaWYocy5RLmV2ZXJ5KEguY2MpKXtxLnI9IiRpIitw
+CnJldHVybiBILlJFKHEsYSxILnQ0KX19ZWxzZSBpZihwPT09NylyZXR1cm4gSC5SRShxLGEsSC5BUSkK
+cmV0dXJuIEguUkUocSxhLEguWU8pfSwKUkU6ZnVuY3Rpb24oYSxiLGMpe2EuYj1jCnJldHVybiBhLmIo
+Yil9LApBdTpmdW5jdGlvbihhKXt2YXIgcyxyLHE9dGhpcwppZighSC5BOChxKSlpZighKHE9PT10Ll8p
+KXM9cT09PXQuSwplbHNlIHM9ITAKZWxzZSBzPSEwCmlmKHMpcj1ILmhuCmVsc2UgaWYocT09PXQuSyly
+PUguVGkKZWxzZSByPUgubDQKcS5hPXIKcmV0dXJuIHEuYShhKX0sClFqOmZ1bmN0aW9uKGEpe3ZhciBz
+LHI9YS55CmlmKCFILkE4KGEpKWlmKCEoYT09PXQuXykpaWYoIShhPT09dC5jRikpaWYociE9PTcpcz1y
+PT09OCYmSC5RaihhLnopfHxhPT09dC5QfHxhPT09dC5UCmVsc2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBz
+PSEwCmVsc2Ugcz0hMApyZXR1cm4gc30sCllPOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKaWYoYT09bnVs
+bClyZXR1cm4gSC5RaihzKQpyZXR1cm4gSC5XZSh2LnR5cGVVbml2ZXJzZSxILlVlKGEscyksbnVsbCxz
+LG51bGwpfSwKQVE6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4hMApyZXR1cm4gdGhpcy56LmIo
+YSl9LAp0NDpmdW5jdGlvbihhKXt2YXIgcyxyPXRoaXMKaWYoYT09bnVsbClyZXR1cm4gSC5RaihyKQpz
+PXIucgppZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4hIWFbc10KcmV0dXJuISFKLmlhKGEpW3NdfSwK
+T3o6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcwppZihhPT1udWxsKXJldHVybiBhCmVsc2UgaWYocy5iKGEp
+KXJldHVybiBhCkgubTQoYSxzKX0sCmw0OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKaWYoYT09bnVsbCly
+ZXR1cm4gYQplbHNlIGlmKHMuYihhKSlyZXR1cm4gYQpILm00KGEscyl9LAptNDpmdW5jdGlvbihhLGIp
+e3Rocm93IEguYihILlpjKEguV0soYSxILlVlKGEsYiksSC5kbShiLG51bGwpKSkpfSwKRGg6ZnVuY3Rp
+b24oYSxiLGMsZCl7dmFyIHM9bnVsbAppZihILldlKHYudHlwZVVuaXZlcnNlLGEscyxiLHMpKXJldHVy
+biBhCnRocm93IEguYihILlpjKCJUaGUgdHlwZSBhcmd1bWVudCAnIitILkVqKEguZG0oYSxzKSkrIicg
+aXMgbm90IGEgc3VidHlwZSBvZiB0aGUgdHlwZSB2YXJpYWJsZSBib3VuZCAnIitILkVqKEguZG0oYixz
+KSkrIicgb2YgdHlwZSB2YXJpYWJsZSAnIitILkVqKGMpKyInIGluICciK0guRWooZCkrIicuIikpfSwK
+V0s6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPVAucChhKSxyPUguZG0oYj09bnVsbD9ILnooYSk6YixudWxs
+KQpyZXR1cm4gcysiOiB0eXBlICciK0guRWoocikrIicgaXMgbm90IGEgc3VidHlwZSBvZiB0eXBlICci
+K0guRWooYykrIicifSwKWmM6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILmlNKCJUeXBlRXJyb3I6ICIr
+YSl9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILmlNKCJUeXBlRXJyb3I6ICIrSC5XSyhhLG51
+bGwsYikpfSwKa2U6ZnVuY3Rpb24oYSl7cmV0dXJuIGEhPW51bGx9LApUaTpmdW5jdGlvbihhKXtyZXR1
+cm4gYX0sCkl3OmZ1bmN0aW9uKGEpe3JldHVybiEwfSwKaG46ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LAps
+OmZ1bmN0aW9uKGEpe3JldHVybiEwPT09YXx8ITE9PT1hfSwKcDg6ZnVuY3Rpb24oYSl7aWYoITA9PT1h
+KXJldHVybiEwCmlmKCExPT09YSlyZXR1cm4hMQp0aHJvdyBILmIoSC5xKGEsImJvb2wiKSl9LAp5ODpm
+dW5jdGlvbihhKXtpZighMD09PWEpcmV0dXJuITAKaWYoITE9PT1hKXJldHVybiExCmlmKGE9PW51bGwp
+cmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJib29sIikpfSwKZHA6ZnVuY3Rpb24oYSl7aWYoITA9PT1h
+KXJldHVybiEwCmlmKCExPT09YSlyZXR1cm4hMQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihI
+LnEoYSwiYm9vbD8iKSl9LApGRzpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJu
+IGEKdGhyb3cgSC5iKEgucShhLCJkb3VibGUiKSl9LApHSDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09
+Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImRvdWJs
+ZSIpKX0sClFrOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1u
+dWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwiZG91YmxlPyIpKX0sCm9rOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hfSwKSVo6ZnVuY3Rpb24oYSl7
+aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YSlyZXR1cm4gYQp0aHJvdyBILmIo
+SC5xKGEsImludCIpKX0sCnVQOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5m
+bG9vcihhKT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImlu
+dCIpKX0sClVjOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09
+PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImludD8iKSl9LApL
+SDpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJudW1iZXIifSwKejU6ZnVuY3Rpb24oYSl7aWYo
+dHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCnRocm93IEguYihILnEoYSwibnVtIikpfSwKVzE6ZnVu
+Y3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEK
+dGhyb3cgSC5iKEgucShhLCJudW0iKSl9LApjVTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJl
+ciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIm51bT8iKSl9LApN
+TTpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJzdHJpbmcifSwKQnQ6ZnVuY3Rpb24oYSl7aWYo
+dHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCnRocm93IEguYihILnEoYSwiU3RyaW5nIikpfSwKaDpm
+dW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4g
+YQp0aHJvdyBILmIoSC5xKGEsIlN0cmluZyIpKX0sCms6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJz
+dHJpbmciKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJTdHJpbmc/
+IikpfSwKaW86ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEKZm9yKHM9IiIscj0iIixxPTA7cTxhLmxlbmd0
+aDsrK3Escj0iLCAiKXMrPUMueEIuaChyLEguZG0oYVtxXSxiKSkKcmV0dXJuIHN9LApiSTpmdW5jdGlv
+bihhNSxhNixhNyl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGEsYTAsYTEs
+YTIsYTMsYTQ9IiwgIgppZihhNyE9bnVsbCl7cz1hNy5sZW5ndGgKaWYoYTY9PW51bGwpe2E2PUguVk0o
+W10sdC5zKQpyPW51bGx9ZWxzZSByPWE2Lmxlbmd0aApxPWE2Lmxlbmd0aApmb3IocD1zO3A+MDstLXAp
+Qy5ObS5pKGE2LCJUIisocStwKSkKZm9yKG89dC5XLG49dC5fLG09dC5LLGw9IjwiLGs9IiIscD0wO3A8
+czsrK3Asaz1hNCl7bCs9awpqPWE2Lmxlbmd0aAppPWotMS1wCmlmKGk8MClyZXR1cm4gSC5PSChhNixp
+KQpsPUMueEIuaChsLGE2W2ldKQpoPWE3W3BdCmc9aC55CmlmKCEoZz09PTJ8fGc9PT0zfHxnPT09NHx8
+Zz09PTV8fGg9PT1vKSlpZighKGg9PT1uKSlqPWg9PT1tCmVsc2Ugaj0hMAplbHNlIGo9ITAKaWYoIWop
+bCs9Qy54Qi5oKCIgZXh0ZW5kcyAiLEguZG0oaCxhNikpfWwrPSI+In1lbHNle2w9IiIKcj1udWxsfW89
+YTUuegpmPWE1LlEKZT1mLmEKZD1lLmxlbmd0aApjPWYuYgpiPWMubGVuZ3RoCmE9Zi5jCmEwPWEubGVu
+Z3RoCmExPUguZG0obyxhNikKZm9yKGEyPSIiLGEzPSIiLHA9MDtwPGQ7KytwLGEzPWE0KWEyKz1DLnhC
+LmgoYTMsSC5kbShlW3BdLGE2KSkKaWYoYj4wKXthMis9YTMrIlsiCmZvcihhMz0iIixwPTA7cDxiOysr
+cCxhMz1hNClhMis9Qy54Qi5oKGEzLEguZG0oY1twXSxhNikpCmEyKz0iXSJ9aWYoYTA+MCl7YTIrPWEz
+KyJ7Igpmb3IoYTM9IiIscD0wO3A8YTA7cCs9MyxhMz1hNCl7YTIrPWEzCmlmKGFbcCsxXSlhMis9InJl
+cXVpcmVkICIKYTIrPUouYmIoSC5kbShhW3ArMl0sYTYpLCIgIikrYVtwXX1hMis9In0ifWlmKHIhPW51
+bGwpe2E2LnRvU3RyaW5nCmE2Lmxlbmd0aD1yfXJldHVybiBsKyIoIithMisiKSA9PiAiK0guRWooYTEp
+fSwKZG06ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxsPWEueQppZihsPT09NSlyZXR1cm4i
+ZXJhc2VkIgppZihsPT09MilyZXR1cm4iZHluYW1pYyIKaWYobD09PTMpcmV0dXJuInZvaWQiCmlmKGw9
+PT0xKXJldHVybiJOZXZlciIKaWYobD09PTQpcmV0dXJuImFueSIKaWYobD09PTYpe3M9SC5kbShhLnos
+YikKcmV0dXJuIHN9aWYobD09PTcpe3I9YS56CnM9SC5kbShyLGIpCnE9ci55CnJldHVybiBKLmJiKHE9
+PT0xMXx8cT09PTEyP0MueEIuaCgiKCIscykrIikiOnMsIj8iKX1pZihsPT09OClyZXR1cm4iRnV0dXJl
+T3I8IitILkVqKEguZG0oYS56LGIpKSsiPiIKaWYobD09PTkpe3A9SC5vMyhhLnopCm89YS5RCnJldHVy
+biBvLmxlbmd0aCE9PTA/cCsoIjwiK0guaW8obyxiKSsiPiIpOnB9aWYobD09PTExKXJldHVybiBILmJJ
+KGEsYixudWxsKQppZihsPT09MTIpcmV0dXJuIEguYkkoYS56LGIsYS5RKQppZihsPT09MTMpe2IudG9T
+dHJpbmcKbj1hLnoKbT1iLmxlbmd0aApuPW0tMS1uCmlmKG48MHx8bj49bSlyZXR1cm4gSC5PSChiLG4p
+CnJldHVybiBiW25dfXJldHVybiI/In0sCm8zOmZ1bmN0aW9uKGEpe3ZhciBzLHI9SC5KZyhhKQppZihy
+IT1udWxsKXJldHVybiByCnM9Im1pbmlmaWVkOiIrYQpyZXR1cm4gc30sClFvOmZ1bmN0aW9uKGEsYil7
+dmFyIHM9YS50UltiXQpmb3IoO3R5cGVvZiBzPT0ic3RyaW5nIjspcz1hLnRSW3NdCnJldHVybiBzfSwK
+YWk6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG49YS5lVCxtPW5bYl0KaWYobT09bnVsbClyZXR1
+cm4gSC5FKGEsYiwhMSkKZWxzZSBpZih0eXBlb2YgbT09Im51bWJlciIpe3M9bQpyPUgubShhLDUsIiMi
+KQpxPVtdCmZvcihwPTA7cDxzOysrcClxLnB1c2gocikKbz1ILkooYSxiLHEpCm5bYl09bwpyZXR1cm4g
+b31lbHNlIHJldHVybiBtfSwKeGI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5JeChhLnRSLGIpfSwKRkY6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5JeChhLmVULGIpfSwKRTpmdW5jdGlvbihhLGIsYyl7dmFyIHMs
+cj1hLmVDLHE9ci5nZXQoYikKaWYocSE9bnVsbClyZXR1cm4gcQpzPUguaShILm8oYSxudWxsLGIsYykp
+CnIuc2V0KGIscykKcmV0dXJuIHN9LApjRTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxPWIuY2gKaWYo
+cT09bnVsbClxPWIuY2g9bmV3IE1hcCgpCnM9cS5nZXQoYykKaWYocyE9bnVsbClyZXR1cm4gcwpyPUgu
+aShILm8oYSxiLGMsITApKQpxLnNldChjLHIpCnJldHVybiByfSwKdjU6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciBzLHIscSxwPWIuY3gKaWYocD09bnVsbClwPWIuY3g9bmV3IE1hcCgpCnM9Yy5jeQpyPXAuZ2V0KHMp
+CmlmKHIhPW51bGwpcmV0dXJuIHIKcT1ILmEoYSxiLGMueT09PTEwP2MuUTpbY10pCnAuc2V0KHMscSkK
+cmV0dXJuIHF9LApCRDpmdW5jdGlvbihhLGIpe2IuYT1ILkF1CmIuYj1ILkpKCnJldHVybiBifSwKbTpm
+dW5jdGlvbihhLGIsYyl7dmFyIHMscixxPWEuZUMuZ2V0KGMpCmlmKHEhPW51bGwpcmV0dXJuIHEKcz1u
+ZXcgSC5KYyhudWxsLG51bGwpCnMueT1iCnMuY3k9YwpyPUguQkQoYSxzKQphLmVDLnNldChjLHIpCnJl
+dHVybiByfSwKQzpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1iLmN5KyIqIixxPWEuZUMuZ2V0KHIpCmlm
+KHEhPW51bGwpcmV0dXJuIHEKcz1ILlo3KGEsYixyLGMpCmEuZUMuc2V0KHIscykKcmV0dXJuIHN9LApa
+NzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEKaWYoZCl7cz1iLnkKaWYoIUguQTgoYikpcj1iPT09
+dC5QfHxiPT09dC5UfHxzPT09N3x8cz09PTYKZWxzZSByPSEwCmlmKHIpcmV0dXJuIGJ9cT1uZXcgSC5K
+YyhudWxsLG51bGwpCnEueT02CnEuej1iCnEuY3k9YwpyZXR1cm4gSC5CRChhLHEpfSwKQjpmdW5jdGlv
+bihhLGIsYyl7dmFyIHMscj1iLmN5KyI/IixxPWEuZUMuZ2V0KHIpCmlmKHEhPW51bGwpcmV0dXJuIHEK
+cz1ILmxsKGEsYixyLGMpCmEuZUMuc2V0KHIscykKcmV0dXJuIHN9LApsbDpmdW5jdGlvbihhLGIsYyxk
+KXt2YXIgcyxyLHEscAppZihkKXtzPWIueQppZighSC5BOChiKSlpZighKGI9PT10LlB8fGI9PT10LlQp
+KWlmKHMhPT03KXI9cz09PTgmJkgubFIoYi56KQplbHNlIHI9ITAKZWxzZSByPSEwCmVsc2Ugcj0hMApp
+ZihyKXJldHVybiBiCmVsc2UgaWYocz09PTF8fGI9PT10LmNGKXJldHVybiB0LlAKZWxzZSBpZihzPT09
+Nil7cT1iLnoKaWYocS55PT09OCYmSC5sUihxLnopKXJldHVybiBxCmVsc2UgcmV0dXJuIEguY3ooYSxi
+KX19cD1uZXcgSC5KYyhudWxsLG51bGwpCnAueT03CnAuej1iCnAuY3k9YwpyZXR1cm4gSC5CRChhLHAp
+fSwKZjpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1iLmN5KyIvIixxPWEuZUMuZ2V0KHIpCmlmKHEhPW51
+bGwpcmV0dXJuIHEKcz1ILmVWKGEsYixyLGMpCmEuZUMuc2V0KHIscykKcmV0dXJuIHN9LAplVjpmdW5j
+dGlvbihhLGIsYyxkKXt2YXIgcyxyLHEKaWYoZCl7cz1iLnkKaWYoIUguQTgoYikpaWYoIShiPT09dC5f
+KSlyPWI9PT10LksKZWxzZSByPSEwCmVsc2Ugcj0hMAppZihyfHxiPT09dC5LKXJldHVybiBiCmVsc2Ug
+aWYocz09PTEpcmV0dXJuIEguSihhLCJiOCIsW2JdKQplbHNlIGlmKGI9PT10LlB8fGI9PT10LlQpcmV0
+dXJuIHQuYkd9cT1uZXcgSC5KYyhudWxsLG51bGwpCnEueT04CnEuej1iCnEuY3k9YwpyZXR1cm4gSC5C
+RChhLHEpfSwKSDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT0iIitiKyJeIixwPWEuZUMuZ2V0KHEpCmlm
+KHAhPW51bGwpcmV0dXJuIHAKcz1uZXcgSC5KYyhudWxsLG51bGwpCnMueT0xMwpzLno9YgpzLmN5PXEK
+cj1ILkJEKGEscykKYS5lQy5zZXQocSxyKQpyZXR1cm4gcn0sClV4OmZ1bmN0aW9uKGEpe3ZhciBzLHIs
+cSxwPWEubGVuZ3RoCmZvcihzPSIiLHI9IiIscT0wO3E8cDsrK3Escj0iLCIpcys9cithW3FdLmN5CnJl
+dHVybiBzfSwKUzQ6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG09YS5sZW5ndGgKZm9yKHM9IiIs
+cj0iIixxPTA7cTxtO3ErPTMscj0iLCIpe3A9YVtxXQpvPWFbcSsxXT8iISI6IjoiCm49YVtxKzJdLmN5
+CnMrPXIrcCtvK259cmV0dXJuIHN9LApKOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscD1iCmlmKGMu
+bGVuZ3RoIT09MClwKz0iPCIrSC5VeChjKSsiPiIKcz1hLmVDLmdldChwKQppZihzIT1udWxsKXJldHVy
+biBzCnI9bmV3IEguSmMobnVsbCxudWxsKQpyLnk9OQpyLno9YgpyLlE9YwppZihjLmxlbmd0aD4wKXIu
+Yz1jWzBdCnIuY3k9cApxPUguQkQoYSxyKQphLmVDLnNldChwLHEpCnJldHVybiBxfSwKYTpmdW5jdGlv
+bihhLGIsYyl7dmFyIHMscixxLHAsbyxuCmlmKGIueT09PTEwKXtzPWIuegpyPWIuUS5jb25jYXQoYyl9
+ZWxzZXtyPWMKcz1ifXE9cy5jeSsoIjs8IitILlV4KHIpKyI+IikKcD1hLmVDLmdldChxKQppZihwIT1u
+dWxsKXJldHVybiBwCm89bmV3IEguSmMobnVsbCxudWxsKQpvLnk9MTAKby56PXMKby5RPXIKby5jeT1x
+Cm49SC5CRChhLG8pCmEuZUMuc2V0KHEsbikKcmV0dXJuIG59LApkOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+cyxyLHEscCxvLG49Yi5jeSxtPWMuYSxsPW0ubGVuZ3RoLGs9Yy5iLGo9ay5sZW5ndGgsaT1jLmMsaD1p
+Lmxlbmd0aCxnPSIoIitILlV4KG0pCmlmKGo+MCl7cz1sPjA/IiwiOiIiCnI9SC5VeChrKQpnKz1zKyJb
+IityKyJdIn1pZihoPjApe3M9bD4wPyIsIjoiIgpyPUguUzQoaSkKZys9cysieyIrcisifSJ9cT1uKyhn
+KyIpIikKcD1hLmVDLmdldChxKQppZihwIT1udWxsKXJldHVybiBwCm89bmV3IEguSmMobnVsbCxudWxs
+KQpvLnk9MTEKby56PWIKby5RPWMKby5jeT1xCnI9SC5CRChhLG8pCmEuZUMuc2V0KHEscikKcmV0dXJu
+IHJ9LApEOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHI9Yi5jeSsoIjwiK0guVXgoYykrIj4iKSxxPWEu
+ZUMuZ2V0KHIpCmlmKHEhPW51bGwpcmV0dXJuIHEKcz1ILmh3KGEsYixjLHIsZCkKYS5lQy5zZXQocixz
+KQpyZXR1cm4gc30sCmh3OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbyxuLG0sbAppZihl
+KXtzPWMubGVuZ3RoCnI9bmV3IEFycmF5KHMpCmZvcihxPTAscD0wO3A8czsrK3Ape289Y1twXQppZihv
+Lnk9PT0xKXtyW3BdPW87KytxfX1pZihxPjApe249SC5QTChhLGIsciwwKQptPUguYlooYSxjLHIsMCkK
+cmV0dXJuIEguRChhLG4sbSxjIT09bSl9fWw9bmV3IEguSmMobnVsbCxudWxsKQpsLnk9MTIKbC56PWIK
+bC5RPWMKbC5jeT1kCnJldHVybiBILkJEKGEsbCl9LApvOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybnt1
+OmEsZTpiLHI6YyxzOltdLHA6MCxuOmR9fSwKaTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxs
+LGssaixpLGgsZz1hLnIsZj1hLnMKZm9yKHM9Zy5sZW5ndGgscj0wO3I8czspe3E9Zy5jaGFyQ29kZUF0
+KHIpCmlmKHE+PTQ4JiZxPD01NylyPUguQShyKzEscSxnLGYpCmVsc2UgaWYoKCgocXwzMik+Pj4wKS05
+NyY2NTUzNSk8MjZ8fHE9PT05NXx8cT09PTM2KXI9SC50KGEscixnLGYsITEpCmVsc2UgaWYocT09PTQ2
+KXI9SC50KGEscixnLGYsITApCmVsc2V7KytyCnN3aXRjaChxKXtjYXNlIDQ0OmJyZWFrCmNhc2UgNTg6
+Zi5wdXNoKCExKQpicmVhawpjYXNlIDMzOmYucHVzaCghMCkKYnJlYWsKY2FzZSA1OTpmLnB1c2goSC5L
+KGEudSxhLmUsZi5wb3AoKSkpCmJyZWFrCmNhc2UgOTQ6Zi5wdXNoKEguSChhLnUsZi5wb3AoKSkpCmJy
+ZWFrCmNhc2UgMzU6Zi5wdXNoKEgubShhLnUsNSwiIyIpKQpicmVhawpjYXNlIDY0OmYucHVzaChILm0o
+YS51LDIsIkAiKSkKYnJlYWsKY2FzZSAxMjY6Zi5wdXNoKEgubShhLnUsMywifiIpKQpicmVhawpjYXNl
+IDYwOmYucHVzaChhLnApCmEucD1mLmxlbmd0aApicmVhawpjYXNlIDYyOnA9YS51Cm89Zi5zcGxpY2Uo
+YS5wKQpILnIoYS51LGEuZSxvKQphLnA9Zi5wb3AoKQpuPWYucG9wKCkKaWYodHlwZW9mIG49PSJzdHJp
+bmciKWYucHVzaChILkoocCxuLG8pKQplbHNle209SC5LKHAsYS5lLG4pCnN3aXRjaChtLnkpe2Nhc2Ug
+MTE6Zi5wdXNoKEguRChwLG0sbyxhLm4pKQpicmVhawpkZWZhdWx0OmYucHVzaChILmEocCxtLG8pKQpi
+cmVha319YnJlYWsKY2FzZSAzODpILkkoYSxmKQpicmVhawpjYXNlIDQyOmw9YS51CmYucHVzaChILkMo
+bCxILksobCxhLmUsZi5wb3AoKSksYS5uKSkKYnJlYWsKY2FzZSA2MzpsPWEudQpmLnB1c2goSC5CKGws
+SC5LKGwsYS5lLGYucG9wKCkpLGEubikpCmJyZWFrCmNhc2UgNDc6bD1hLnUKZi5wdXNoKEguZihsLEgu
+SyhsLGEuZSxmLnBvcCgpKSxhLm4pKQpicmVhawpjYXNlIDQwOmYucHVzaChhLnApCmEucD1mLmxlbmd0
+aApicmVhawpjYXNlIDQxOnA9YS51Cms9bmV3IEguRygpCmo9cC5zRUEKaT1wLnNFQQpuPWYucG9wKCkK
+aWYodHlwZW9mIG49PSJudW1iZXIiKXN3aXRjaChuKXtjYXNlLTE6aj1mLnBvcCgpCmJyZWFrCmNhc2Ut
+MjppPWYucG9wKCkKYnJlYWsKZGVmYXVsdDpmLnB1c2gobikKYnJlYWt9ZWxzZSBmLnB1c2gobikKbz1m
+LnNwbGljZShhLnApCkgucihhLnUsYS5lLG8pCmEucD1mLnBvcCgpCmsuYT1vCmsuYj1qCmsuYz1pCmYu
+cHVzaChILmQocCxILksocCxhLmUsZi5wb3AoKSksaykpCmJyZWFrCmNhc2UgOTE6Zi5wdXNoKGEucCkK
+YS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgOTM6bz1mLnNwbGljZShhLnApCkgucihhLnUsYS5lLG8pCmEu
+cD1mLnBvcCgpCmYucHVzaChvKQpmLnB1c2goLTEpCmJyZWFrCmNhc2UgMTIzOmYucHVzaChhLnApCmEu
+cD1mLmxlbmd0aApicmVhawpjYXNlIDEyNTpvPWYuc3BsaWNlKGEucCkKSC55KGEudSxhLmUsbykKYS5w
+PWYucG9wKCkKZi5wdXNoKG8pCmYucHVzaCgtMikKYnJlYWsKZGVmYXVsdDp0aHJvdyJCYWQgY2hhcmFj
+dGVyICIrcX19fWg9Zi5wb3AoKQpyZXR1cm4gSC5LKGEudSxhLmUsaCl9LApBOmZ1bmN0aW9uKGEsYixj
+LGQpe3ZhciBzLHIscT1iLTQ4CmZvcihzPWMubGVuZ3RoO2E8czsrK2Epe3I9Yy5jaGFyQ29kZUF0KGEp
+CmlmKCEocj49NDgmJnI8PTU3KSlicmVhawpxPXEqMTArKHItNDgpfWQucHVzaChxKQpyZXR1cm4gYX0s
+CnQ6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvLG4sbT1iKzEKZm9yKHM9Yy5sZW5ndGg7
+bTxzOysrbSl7cj1jLmNoYXJDb2RlQXQobSkKaWYocj09PTQ2KXtpZihlKWJyZWFrCmU9ITB9ZWxzZXtp
+ZighKCgoKHJ8MzIpPj4+MCktOTcmNjU1MzUpPDI2fHxyPT09OTV8fHI9PT0zNikpcT1yPj00OCYmcjw9
+NTcKZWxzZSBxPSEwCmlmKCFxKWJyZWFrfX1wPWMuc3Vic3RyaW5nKGIsbSkKaWYoZSl7cz1hLnUKbz1h
+LmUKaWYoby55PT09MTApbz1vLnoKbj1ILlFvKHMsby56KVtwXQppZihuPT1udWxsKUgudignTm8gIicr
+cCsnIiBpbiAiJytILm1EKG8pKyciJykKZC5wdXNoKEguY0UocyxvLG4pKX1lbHNlIGQucHVzaChwKQpy
+ZXR1cm4gbX0sCkk6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iLnBvcCgpCmlmKDA9PT1zKXtiLnB1c2goSC5t
+KGEudSwxLCIwJiIpKQpyZXR1cm59aWYoMT09PXMpe2IucHVzaChILm0oYS51LDQsIjEmIikpCnJldHVy
+bn10aHJvdyBILmIoUC5oVigiVW5leHBlY3RlZCBleHRlbmRlZCBvcGVyYXRpb24gIitILkVqKHMpKSl9
+LApLOmZ1bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYz09InN0cmluZyIpcmV0dXJuIEguSihhLGMsYS5z
+RUEpCmVsc2UgaWYodHlwZW9mIGM9PSJudW1iZXIiKXJldHVybiBILlRWKGEsYixjKQplbHNlIHJldHVy
+biBjfSwKcjpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1jLmxlbmd0aApmb3Iocz0wO3M8cjsrK3MpY1tz
+XT1ILksoYSxiLGNbc10pfSwKeTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1jLmxlbmd0aApmb3Iocz0y
+O3M8cjtzKz0zKWNbc109SC5LKGEsYixjW3NdKX0sClRWOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHE9
+Yi55CmlmKHE9PT0xMCl7aWYoYz09PTApcmV0dXJuIGIuegpzPWIuUQpyPXMubGVuZ3RoCmlmKGM8PXIp
+cmV0dXJuIHNbYy0xXQpjLT1yCmI9Yi56CnE9Yi55fWVsc2UgaWYoYz09PTApcmV0dXJuIGIKaWYocSE9
+PTkpdGhyb3cgSC5iKFAuaFYoIkluZGV4ZWQgYmFzZSBtdXN0IGJlIGFuIGludGVyZmFjZSB0eXBlIikp
+CnM9Yi5RCmlmKGM8PXMubGVuZ3RoKXJldHVybiBzW2MtMV0KdGhyb3cgSC5iKFAuaFYoIkJhZCBpbmRl
+eCAiK2MrIiBmb3IgIitiLncoMCkpKX0sCldlOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAs
+byxuLG0sbCxrLGoKaWYoYj09PWQpcmV0dXJuITAKaWYoIUguQTgoZCkpaWYoIShkPT09dC5fKSlzPWQ9
+PT10LksKZWxzZSBzPSEwCmVsc2Ugcz0hMAppZihzKXJldHVybiEwCnI9Yi55CmlmKHI9PT00KXJldHVy
+biEwCmlmKEguQTgoYikpcmV0dXJuITEKaWYoYi55IT09MSlzPWI9PT10LlB8fGI9PT10LlQKZWxzZSBz
+PSEwCmlmKHMpcmV0dXJuITAKcT1yPT09MTMKaWYocSlpZihILldlKGEsY1tiLnpdLGMsZCxlKSlyZXR1
+cm4hMApwPWQueQppZihyPT09NilyZXR1cm4gSC5XZShhLGIueixjLGQsZSkKaWYocD09PTYpe3M9ZC56
+CnJldHVybiBILldlKGEsYixjLHMsZSl9aWYocj09PTgpe2lmKCFILldlKGEsYi56LGMsZCxlKSlyZXR1
+cm4hMQpyZXR1cm4gSC5XZShhLEgueFooYSxiKSxjLGQsZSl9aWYocj09PTcpe3M9SC5XZShhLGIueixj
+LGQsZSkKcmV0dXJuIHN9aWYocD09PTgpe2lmKEguV2UoYSxiLGMsZC56LGUpKXJldHVybiEwCnJldHVy
+biBILldlKGEsYixjLEgueFooYSxkKSxlKX1pZihwPT09Nyl7cz1ILldlKGEsYixjLGQueixlKQpyZXR1
+cm4gc31pZihxKXJldHVybiExCnM9ciE9PTExCmlmKCghc3x8cj09PTEyKSYmZD09PXQuWSlyZXR1cm4h
+MAppZihwPT09MTIpe2lmKGI9PT10LngpcmV0dXJuITAKaWYociE9PTEyKXJldHVybiExCm89Yi5RCm49
+ZC5RCm09by5sZW5ndGgKaWYobSE9PW4ubGVuZ3RoKXJldHVybiExCmM9Yz09bnVsbD9vOm8uY29uY2F0
+KGMpCmU9ZT09bnVsbD9uOm4uY29uY2F0KGUpCmZvcihsPTA7bDxtOysrbCl7az1vW2xdCmo9bltsXQpp
+ZighSC5XZShhLGssYyxqLGUpfHwhSC5XZShhLGosZSxrLGMpKXJldHVybiExfXJldHVybiBILmJPKGEs
+Yi56LGMsZC56LGUpfWlmKHA9PT0xMSl7aWYoYj09PXQueClyZXR1cm4hMAppZihzKXJldHVybiExCnJl
+dHVybiBILmJPKGEsYixjLGQsZSl9aWYocj09PTkpe2lmKHAhPT05KXJldHVybiExCnJldHVybiBILnBH
+KGEsYixjLGQsZSl9cmV0dXJuITF9LApiTzpmdW5jdGlvbihhMixhMyxhNCxhNSxhNil7dmFyIHMscixx
+LHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGEsYTAsYTEKaWYoIUguV2UoYTIsYTMueixhNCxh
+NS56LGE2KSlyZXR1cm4hMQpzPWEzLlEKcj1hNS5RCnE9cy5hCnA9ci5hCm89cS5sZW5ndGgKbj1wLmxl
+bmd0aAppZihvPm4pcmV0dXJuITEKbT1uLW8KbD1zLmIKaz1yLmIKaj1sLmxlbmd0aAppPWsubGVuZ3Ro
+CmlmKG8rajxuK2kpcmV0dXJuITEKZm9yKGg9MDtoPG87KytoKXtnPXFbaF0KaWYoIUguV2UoYTIscFto
+XSxhNixnLGE0KSlyZXR1cm4hMX1mb3IoaD0wO2g8bTsrK2gpe2c9bFtoXQppZighSC5XZShhMixwW28r
+aF0sYTYsZyxhNCkpcmV0dXJuITF9Zm9yKGg9MDtoPGk7KytoKXtnPWxbbStoXQppZighSC5XZShhMixr
+W2hdLGE2LGcsYTQpKXJldHVybiExfWY9cy5jCmU9ci5jCmQ9Zi5sZW5ndGgKYz1lLmxlbmd0aApmb3Io
+Yj0wLGE9MDthPGM7YSs9Myl7YTA9ZVthXQpmb3IoOyEwOyl7aWYoYj49ZClyZXR1cm4hMQphMT1mW2Jd
+CmIrPTMKaWYoYTA8YTEpcmV0dXJuITEKaWYoYTE8YTApY29udGludWUKZz1mW2ItMV0KaWYoIUguV2Uo
+YTIsZVthKzJdLGE2LGcsYTQpKXJldHVybiExCmJyZWFrfX1yZXR1cm4hMH0sCnBHOmZ1bmN0aW9uKGEs
+YixjLGQsZSl7dmFyIHMscixxLHAsbyxuLG0sbCxrPWIueixqPWQuegppZihrPT09ail7cz1iLlEKcj1k
+LlEKcT1zLmxlbmd0aApmb3IocD0wO3A8cTsrK3Ape289c1twXQpuPXJbcF0KaWYoIUguV2UoYSxvLGMs
+bixlKSlyZXR1cm4hMX1yZXR1cm4hMH1pZihkPT09dC5LKXJldHVybiEwCm09SC5RbyhhLGspCmlmKG09
+PW51bGwpcmV0dXJuITEKbD1tW2pdCmlmKGw9PW51bGwpcmV0dXJuITEKcT1sLmxlbmd0aApyPWQuUQpm
+b3IocD0wO3A8cTsrK3ApaWYoIUguV2UoYSxILmNFKGEsYixsW3BdKSxjLHJbcF0sZSkpcmV0dXJuITEK
+cmV0dXJuITB9LApsUjpmdW5jdGlvbihhKXt2YXIgcyxyPWEueQppZighKGE9PT10LlB8fGE9PT10LlQp
+KWlmKCFILkE4KGEpKWlmKHIhPT03KWlmKCEocj09PTYmJkgubFIoYS56KSkpcz1yPT09OCYmSC5sUihh
+LnopCmVsc2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMApyZXR1cm4gc30sCmNjOmZ1
+bmN0aW9uKGEpe3ZhciBzCmlmKCFILkE4KGEpKWlmKCEoYT09PXQuXykpcz1hPT09dC5LCmVsc2Ugcz0h
+MAplbHNlIHM9ITAKcmV0dXJuIHN9LApBODpmdW5jdGlvbihhKXt2YXIgcz1hLnkKcmV0dXJuIHM9PT0y
+fHxzPT09M3x8cz09PTR8fHM9PT01fHxhPT09dC5XfSwKSXg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9
+T2JqZWN0LmtleXMoYikscD1xLmxlbmd0aApmb3Iocz0wO3M8cDsrK3Mpe3I9cVtzXQphW3JdPWJbcl19
+fSwKSmM6ZnVuY3Rpb24gSmMoYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8ueD1fLnI9Xy5jPW51
+bGwKXy55PTAKXy5jeT1fLmN4PV8uY2g9Xy5RPV8uej1udWxsfSwKRzpmdW5jdGlvbiBHKCl7dGhpcy5j
+PXRoaXMuYj10aGlzLmE9bnVsbH0sCmxZOmZ1bmN0aW9uIGxZKGEpe3RoaXMuYT1hfSwKa1M6ZnVuY3Rp
+b24ga1MoKXt9LAppTTpmdW5jdGlvbiBpTShhKXt0aGlzLmE9YX0sClI5OmZ1bmN0aW9uKGEpe3JldHVy
+biB0LncuYihhKXx8dC5CLmIoYSl8fHQuZHouYihhKXx8dC5JLmIoYSl8fHQuQS5iKGEpfHx0Lmc0LmIo
+YSl8fHQuZzIuYihhKX0sCkpnOmZ1bmN0aW9uKGEpe3JldHVybiB2Lm1hbmdsZWRHbG9iYWxOYW1lc1th
+XX19LEo9ewpRdTpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm57aTphLHA6YixlOmMseDpkfX0sCmtzOmZ1
+bmN0aW9uKGEpe3ZhciBzLHIscSxwLG89YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXQppZihvPT1udWxs
+KWlmKCQuQnY9PW51bGwpe0guWEQoKQpvPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV19aWYobyE9bnVs
+bCl7cz1vLnAKaWYoITE9PT1zKXJldHVybiBvLmkKaWYoITA9PT1zKXJldHVybiBhCnI9T2JqZWN0Lmdl
+dFByb3RvdHlwZU9mKGEpCmlmKHM9PT1yKXJldHVybiBvLmkKaWYoby5lPT09cil0aHJvdyBILmIoUC5T
+WSgiUmV0dXJuIGludGVyY2VwdG9yIGZvciAiK0guRWoocyhhLG8pKSkpfXE9YS5jb25zdHJ1Y3Rvcgpw
+PXE9PW51bGw/bnVsbDpxW0ouUlAoKV0KaWYocCE9bnVsbClyZXR1cm4gcApwPUgudzMoYSkKaWYocCE9
+bnVsbClyZXR1cm4gcAppZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gQy5ERwpzPU9iamVjdC5n
+ZXRQcm90b3R5cGVPZihhKQppZihzPT1udWxsKXJldHVybiBDLlpRCmlmKHM9PT1PYmplY3QucHJvdG90
+eXBlKXJldHVybiBDLlpRCmlmKHR5cGVvZiBxPT0iZnVuY3Rpb24iKXtPYmplY3QuZGVmaW5lUHJvcGVy
+dHkocSxKLlJQKCkse3ZhbHVlOkMudkIsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZp
+Z3VyYWJsZTp0cnVlfSkKcmV0dXJuIEMudkJ9cmV0dXJuIEMudkJ9LApSUDpmdW5jdGlvbigpe3ZhciBz
+PSQuem0KcmV0dXJuIHM9PW51bGw/JC56bT12LmdldElzb2xhdGVUYWcoIl8kZGFydF9qcyIpOnN9LApR
+aTpmdW5jdGlvbihhLGIpe2lmKGE8MHx8YT40Mjk0OTY3Mjk1KXRocm93IEguYihQLlRFKGEsMCw0Mjk0
+OTY3Mjk1LCJsZW5ndGgiLG51bGwpKQpyZXR1cm4gSi5weShuZXcgQXJyYXkoYSksYil9LApLaDpmdW5j
+dGlvbihhLGIpe2lmKGE8MCl0aHJvdyBILmIoUC54WSgiTGVuZ3RoIG11c3QgYmUgYSBub24tbmVnYXRp
+dmUgaW50ZWdlcjogIithKSkKcmV0dXJuIEguVk0obmV3IEFycmF5KGEpLGIuQygiamQ8MD4iKSl9LApw
+eTpmdW5jdGlvbihhLGIpe3JldHVybiBKLkVwKEguVk0oYSxiLkMoImpkPDA+IikpLGIpfSwKRXA6ZnVu
+Y3Rpb24oYSxiKXthLmZpeGVkJGxlbmd0aD1BcnJheQpyZXR1cm4gYX0sCnpDOmZ1bmN0aW9uKGEpe2Eu
+Zml4ZWQkbGVuZ3RoPUFycmF5CmEuaW1tdXRhYmxlJGxpc3Q9QXJyYXkKcmV0dXJuIGF9LApHYTpmdW5j
+dGlvbihhKXtpZihhPDI1Nilzd2l0Y2goYSl7Y2FzZSA5OmNhc2UgMTA6Y2FzZSAxMTpjYXNlIDEyOmNh
+c2UgMTM6Y2FzZSAzMjpjYXNlIDEzMzpjYXNlIDE2MDpyZXR1cm4hMApkZWZhdWx0OnJldHVybiExfXN3
+aXRjaChhKXtjYXNlIDU3NjA6Y2FzZSA4MTkyOmNhc2UgODE5MzpjYXNlIDgxOTQ6Y2FzZSA4MTk1OmNh
+c2UgODE5NjpjYXNlIDgxOTc6Y2FzZSA4MTk4OmNhc2UgODE5OTpjYXNlIDgyMDA6Y2FzZSA4MjAxOmNh
+c2UgODIwMjpjYXNlIDgyMzI6Y2FzZSA4MjMzOmNhc2UgODIzOTpjYXNlIDgyODc6Y2FzZSAxMjI4ODpj
+YXNlIDY1Mjc5OnJldHVybiEwCmRlZmF1bHQ6cmV0dXJuITF9fSwKbW06ZnVuY3Rpb24oYSxiKXt2YXIg
+cyxyCmZvcihzPWEubGVuZ3RoO2I8czspe3I9Qy54Qi5XKGEsYikKaWYociE9PTMyJiZyIT09MTMmJiFK
+LkdhKHIpKWJyZWFrOysrYn1yZXR1cm4gYn0sCmMxOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpmb3IoO2I+
+MDtiPXMpe3M9Yi0xCnI9Qy54Qi5PKGEscykKaWYociE9PTMyJiZyIT09MTMmJiFKLkdhKHIpKWJyZWFr
+fXJldHVybiBifSwKVEo6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBKLnFJ
+LnByb3RvdHlwZQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9
+PW51bGwpcmV0dXJuIGEKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQucHJvdG90eXBl
+CmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUu
+cHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJldHVybiBKLmtz
+KGEpfSwKVTY6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3Rv
+dHlwZQppZihhPT1udWxsKXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLmpk
+LnByb3RvdHlwZQppZih0eXBlb2YgYSE9Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJl
+dHVybiBKLmM1LnByb3RvdHlwZQpyZXR1cm4gYX1pZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4gYQpy
+ZXR1cm4gSi5rcyhhKX0sCllFOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIGEKaWYodHlwZW9m
+IGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUK
+cmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LAppYTpm
+dW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpe2lmKE1hdGguZmxvb3IoYSk9PWEpcmV0dXJu
+IEouYlUucHJvdG90eXBlCnJldHVybiBKLlZBLnByb3RvdHlwZX1pZih0eXBlb2YgYT09InN0cmluZyIp
+cmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJuIEoud2UucHJvdG90eXBlCmlmKHR5
+cGVvZiBhPT0iYm9vbGVhbiIpcmV0dXJuIEoueUUucHJvdG90eXBlCmlmKGEuY29uc3RydWN0b3I9PUFy
+cmF5KXJldHVybiBKLmpkLnByb3RvdHlwZQppZih0eXBlb2YgYSE9Im9iamVjdCIpe2lmKHR5cGVvZiBh
+PT0iZnVuY3Rpb24iKXJldHVybiBKLmM1LnByb3RvdHlwZQpyZXR1cm4gYX1pZihhIGluc3RhbmNlb2Yg
+UC5NaClyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0sCnJZOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0i
+c3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gYQppZighKGEgaW5z
+dGFuY2VvZiBQLk1oKSlyZXR1cm4gSi5rZC5wcm90b3R5cGUKcmV0dXJuIGF9LAp2ZDpmdW5jdGlvbihh
+KXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEoucUkucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0
+dXJuIGEKaWYoIShhIGluc3RhbmNlb2YgUC5NaCkpcmV0dXJuIEoua2QucHJvdG90eXBlCnJldHVybiBh
+fSwKdzE6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJh
+eSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09
+ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAu
+TWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApBNTpmdW5jdGlvbihhLGIpe3JldHVybiBKLncxKGEp
+LmVSKGEsYil9LApFaDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouWUUoYSkubUsoYSxiLGMpfSwKRWw6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi53MShhKS5kcihhLGIpfSwKRjc6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEouVTYoYSkuZ29yKGEpfSwKRkw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5kZChhLGIpfSwK
+R0E6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi53MShhKS5FKGEsYil9LApIbTpmdW5jdGlvbihhKXtyZXR1
+cm4gSi5VNihhKS5nQShhKX0sCklUOmZ1bmN0aW9uKGEpe3JldHVybiBKLncxKGEpLmdtKGEpfSwKSnk6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5pYShhKS5lNyhhLGIpfSwKS1Y6ZnVuY3Rpb24oYSxiKXtyZXR1
+cm4gSi5yWShhKS55bihhLGIpfSwKTHQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEouWUUoYSkud2coYSl9LApN
+MTpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEoudzEoYSkuRTIoYSxiLGMpfSwKTXU6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gSi5ZRShhKS5zUChhLGIpfSwKUXo6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5X
+KGEsYil9LApSTTpmdW5jdGlvbihhLGIpe2lmKGE9PW51bGwpcmV0dXJuIGI9PW51bGwKaWYodHlwZW9m
+IGEhPSJvYmplY3QiKXJldHVybiBiIT1udWxsJiZhPT09YgpyZXR1cm4gSi5pYShhKS5ETihhLGIpfSwK
+Ulg6ZnVuY3Rpb24oYSl7cmV0dXJuIEoudzEoYSkuYnIoYSl9LApUMDpmdW5jdGlvbihhKXtyZXR1cm4g
+Si5yWShhKS5iUyhhKX0sClZ1OmZ1bmN0aW9uKGEpe3JldHVybiBKLnZkKGEpLnpRKGEpfSwKYTY6ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5PKGEsYil9LApiVDpmdW5jdGlvbihhKXtyZXR1cm4gSi5Z
+RShhKS5ENChhKX0sCmJiOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZ0eXBlb2Yg
+Yj09Im51bWJlciIpcmV0dXJuIGErYgpyZXR1cm4gSi5USihhKS5oKGEsYil9LApjSDpmdW5jdGlvbihh
+KXtyZXR1cm4gSi5yWShhKS5oYyhhKX0sCmRSOmZ1bmN0aW9uKGEpe3JldHVybiBKLllFKGEpLmdQKGEp
+fSwKZFo6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouWUUoYSkuT24oYSxiLGMsZCl9LApkZzpmdW5j
+dGlvbihhLGIsYyxkKXtyZXR1cm4gSi5yWShhKS5pNyhhLGIsYyxkKX0sCmRoOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBKLllFKGEpLkZGKGEpfSwKZHI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5ZRShhKS5zYTQoYSxi
+KX0sCmhmOmZ1bmN0aW9uKGEpe3JldHVybiBKLmlhKGEpLmdpTyhhKX0sCmlnOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBKLllFKGEpLmdRZyhhKX0sCmo6ZnVuY3Rpb24oYSl7cmV0dXJuIEouaWEoYSkudyhhKX0sCmw1
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouWUUoYSkuc2hmKGEsYil9LApsZDpmdW5jdGlvbihhLGIsYyl7
+cmV0dXJuIEouclkoYSkuTmooYSxiLGMpfSwKcDQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5U
+YyhhLGIpfSwKcTA6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnJZKGEpLlFpKGEsYixjKX0sCnFGOmZ1
+bmN0aW9uKGEpe3JldHVybiBKLllFKGEpLmdWbChhKX0sCnRIOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4g
+Si5ZRShhKS5wayhhLGIsYyl9LAp1OTpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEoudzEoYSkuWTUoYSxi
+LGMpfSwKdVU6ZnVuY3Rpb24oYSl7cmV0dXJuIEouVTYoYSkuZ2wwKGEpfSwKd2Y6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gSi5ZRShhKS5zUk4oYSxiKX0sCng5OmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGI9PT0i
+bnVtYmVyIilpZihhLmNvbnN0cnVjdG9yPT1BcnJheXx8dHlwZW9mIGE9PSJzdHJpbmcifHxILndWKGEs
+YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXSkpaWYoYj4+PjA9PT1iJiZiPGEubGVuZ3RoKXJldHVybiBh
+W2JdCnJldHVybiBKLlU2KGEpLnEoYSxiKX0sCnpsOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouVTYoYSku
+dGcoYSxiKX0sCkd2OmZ1bmN0aW9uIEd2KCl7fSwKeUU6ZnVuY3Rpb24geUUoKXt9LAp3ZTpmdW5jdGlv
+biB3ZSgpe30sCk1GOmZ1bmN0aW9uIE1GKCl7fSwKaUM6ZnVuY3Rpb24gaUMoKXt9LAprZDpmdW5jdGlv
+biBrZCgpe30sCmM1OmZ1bmN0aW9uIGM1KCl7fSwKamQ6ZnVuY3Rpb24gamQoYSl7dGhpcy4kdGk9YX0s
+ClBvOmZ1bmN0aW9uIFBvKGEpe3RoaXMuJHRpPWF9LAptMTpmdW5jdGlvbiBtMShhLGIsYyl7dmFyIF89
+dGhpcwpfLmE9YQpfLmI9YgpfLmM9MApfLmQ9bnVsbApfLiR0aT1jfSwKcUk6ZnVuY3Rpb24gcUkoKXt9
+LApiVTpmdW5jdGlvbiBiVSgpe30sClZBOmZ1bmN0aW9uIFZBKCl7fSwKRHI6ZnVuY3Rpb24gRHIoKXt9
+fSxQPXsKT2o6ZnVuY3Rpb24oKXt2YXIgcyxyLHE9e30KaWYoc2VsZi5zY2hlZHVsZUltbWVkaWF0ZSE9
+bnVsbClyZXR1cm4gUC5FWCgpCmlmKHNlbGYuTXV0YXRpb25PYnNlcnZlciE9bnVsbCYmc2VsZi5kb2N1
+bWVudCE9bnVsbCl7cz1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpCnI9c2VsZi5kb2N1
+bWVudC5jcmVhdGVFbGVtZW50KCJzcGFuIikKcS5hPW51bGwKbmV3IHNlbGYuTXV0YXRpb25PYnNlcnZl
+cihILnRSKG5ldyBQLnRoKHEpLDEpKS5vYnNlcnZlKHMse2NoaWxkTGlzdDp0cnVlfSkKcmV0dXJuIG5l
+dyBQLmhhKHEscyxyKX1lbHNlIGlmKHNlbGYuc2V0SW1tZWRpYXRlIT1udWxsKXJldHVybiBQLnl0KCkK
+cmV0dXJuIFAucVcoKX0sClpWOmZ1bmN0aW9uKGEpe3NlbGYuc2NoZWR1bGVJbW1lZGlhdGUoSC50Uihu
+ZXcgUC5Wcyh0Lk0uYShhKSksMCkpfSwKb0E6ZnVuY3Rpb24oYSl7c2VsZi5zZXRJbW1lZGlhdGUoSC50
+UihuZXcgUC5GdCh0Lk0uYShhKSksMCkpfSwKQno6ZnVuY3Rpb24oYSl7dC5NLmEoYSkKUC5RTigwLGEp
+fSwKUU46ZnVuY3Rpb24oYSxiKXt2YXIgcz1uZXcgUC5XMygpCnMuQ1koYSxiKQpyZXR1cm4gc30sCkZY
+OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5paChuZXcgUC52cygkLlgzLGEuQygidnM8MD4iKSksYS5D
+KCJpaDwwPiIpKX0sCkRJOmZ1bmN0aW9uKGEsYil7YS4kMigwLG51bGwpCmIuYj0hMApyZXR1cm4gYi5h
+fSwKalE6ZnVuY3Rpb24oYSxiKXtQLkplKGEsYil9LAp5QzpmdW5jdGlvbihhLGIpe2IuYU0oMCxhKX0s
+CmYzOmZ1bmN0aW9uKGEsYil7Yi53MChILlJ1KGEpLEgudHMoYSkpfSwKSmU6ZnVuY3Rpb24oYSxiKXt2
+YXIgcyxyLHE9bmV3IFAuV00oYikscD1uZXcgUC5TWChiKQppZihhIGluc3RhbmNlb2YgUC52cylhLlFk
+KHEscCx0LnopCmVsc2V7cz10LnoKaWYodC5lLmIoYSkpYS5TcShxLHAscykKZWxzZXtyPW5ldyBQLnZz
+KCQuWDMsdC5jKQpyLmE9NApyLmM9YQpyLlFkKHEscCxzKX19fSwKbHo6ZnVuY3Rpb24oYSl7dmFyIHM9
+ZnVuY3Rpb24oYixjKXtyZXR1cm4gZnVuY3Rpb24oZCxlKXt3aGlsZSh0cnVlKXRyeXtiKGQsZSkKYnJl
+YWt9Y2F0Y2gocil7ZT1yCmQ9Y319fShhLDEpCnJldHVybiAkLlgzLkxqKG5ldyBQLkdzKHMpLHQuSCx0
+LlMsdC56KX0sCklHOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5GeShhLDEpfSwKVGg6ZnVuY3Rpb24o
+KXtyZXR1cm4gQy53UX0sClltOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5GeShhLDMpfSwKbDA6ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAucTQoYSxiLkMoInE0PDA+IikpfSwKVGw6ZnVuY3Rpb24oYSxi
+KXt2YXIgcz1ILmNiKGEsImVycm9yIix0LkspCnJldHVybiBuZXcgUC5DdyhzLGI9PW51bGw/UC52MChh
+KTpiKX0sCnYwOmZ1bmN0aW9uKGEpe3ZhciBzCmlmKHQuci5iKGEpKXtzPWEuZ0lJKCkKaWYocyE9bnVs
+bClyZXR1cm4gc31yZXR1cm4gQy5wZH0sCkE5OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxCmZvcihzPXQu
+YztyPWEuYSxyPT09MjspYT1zLmEoYS5jKQppZihyPj00KXtxPWIuYWgoKQpiLmE9YS5hCmIuYz1hLmMK
+UC5IWihiLHEpfWVsc2V7cT10LkYuYShiLmMpCmIuYT0yCmIuYz1hCmEualEocSl9fSwKSFo6ZnVuY3Rp
+b24oYTAsYTEpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGM9bnVsbCxiPXt9LGE9
+Yi5hPWEwCmZvcihzPXQubixyPXQuRixxPXQuZTshMDspe3A9e30Kbz1hLmE9PT04CmlmKGExPT1udWxs
+KXtpZihvKXtuPXMuYShhLmMpClAuTDIoYyxjLGEuYixuLmEsbi5iKX1yZXR1cm59cC5hPWExCm09YTEu
+YQpmb3IoYT1hMTttIT1udWxsO2E9bSxtPWwpe2EuYT1udWxsClAuSFooYi5hLGEpCnAuYT1tCmw9bS5h
+fWs9Yi5hCmo9ay5jCnAuYj1vCnAuYz1qCmk9IW8KaWYoaSl7aD1hLmMKaD0oaCYxKSE9PTB8fChoJjE1
+KT09PTh9ZWxzZSBoPSEwCmlmKGgpe2c9YS5iLmIKaWYobyl7aD1rLmI9PT1nCmg9IShofHxoKX1lbHNl
+IGg9ITEKaWYoaCl7cy5hKGopClAuTDIoYyxjLGsuYixqLmEsai5iKQpyZXR1cm59Zj0kLlgzCmlmKGYh
+PT1nKSQuWDM9ZwplbHNlIGY9YwphPWEuYwppZigoYSYxNSk9PT04KW5ldyBQLlJUKHAsYixvKS4kMCgp
+CmVsc2UgaWYoaSl7aWYoKGEmMSkhPT0wKW5ldyBQLnJxKHAsaikuJDAoKX1lbHNlIGlmKChhJjIpIT09
+MCluZXcgUC5SVyhiLHApLiQwKCkKaWYoZiE9bnVsbCkkLlgzPWYKYT1wLmMKaWYocS5iKGEpKXtrPXAu
+YS4kdGkKaz1rLkMoImI4PDI+IikuYihhKXx8IWsuUVsxXS5iKGEpfWVsc2Ugaz0hMQppZihrKXtxLmEo
+YSkKZT1wLmEuYgppZihhIGluc3RhbmNlb2YgUC52cylpZihhLmE+PTQpe2Q9ci5hKGUuYykKZS5jPW51
+bGwKYTE9ZS5OOChkKQplLmE9YS5hCmUuYz1hLmMKYi5hPWEKY29udGludWV9ZWxzZSBQLkE5KGEsZSkK
+ZWxzZSBlLmVjKGEpCnJldHVybn19ZT1wLmEuYgpkPXIuYShlLmMpCmUuYz1udWxsCmExPWUuTjgoZCkK
+YT1wLmIKaz1wLmMKaWYoIWEpe2UuJHRpLmMuYShrKQplLmE9NAplLmM9a31lbHNle3MuYShrKQplLmE9
+OAplLmM9a31iLmE9ZQphPWV9fSwKVkg6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZih0LmFnLmIoYSkpcmV0
+dXJuIGIuTGooYSx0LnosdC5LLHQubCkKcz10LmJJCmlmKHMuYihhKSlyZXR1cm4gcy5hKGEpCnRocm93
+IEguYihQLkwzKGEsIm9uRXJyb3IiLCJFcnJvciBoYW5kbGVyIG11c3QgYWNjZXB0IG9uZSBPYmplY3Qg
+b3Igb25lIE9iamVjdCBhbmQgYSBTdGFja1RyYWNlIGFzIGFyZ3VtZW50cywgYW5kIHJldHVybiBhIHZh
+bGlkIHJlc3VsdCIpKX0sCnB1OmZ1bmN0aW9uKCl7dmFyIHMscgpmb3Iocz0kLlM2O3MhPW51bGw7cz0k
+LlM2KXskLm1nPW51bGwKcj1zLmIKJC5TNj1yCmlmKHI9PW51bGwpJC5rOD1udWxsCnMuYS4kMCgpfX0s
+CmVOOmZ1bmN0aW9uKCl7JC5VRD0hMAp0cnl7UC5wdSgpfWZpbmFsbHl7JC5tZz1udWxsCiQuVUQ9ITEK
+aWYoJC5TNiE9bnVsbCkkLnV0KCkuJDEoUC5VSSgpKX19LAplVzpmdW5jdGlvbihhKXt2YXIgcz1uZXcg
+UC5PTShhKSxyPSQuazgKaWYocj09bnVsbCl7JC5TNj0kLms4PXMKaWYoISQuVUQpJC51dCgpLiQxKFAu
+VUkoKSl9ZWxzZSAkLms4PXIuYj1zfSwKclI6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9JC5TNgppZihw
+PT1udWxsKXtQLmVXKGEpCiQubWc9JC5rOApyZXR1cm59cz1uZXcgUC5PTShhKQpyPSQubWcKaWYocj09
+bnVsbCl7cy5iPXAKJC5TNj0kLm1nPXN9ZWxzZXtxPXIuYgpzLmI9cQokLm1nPXIuYj1zCmlmKHE9PW51
+bGwpJC5rOD1zfX0sCnJiOmZ1bmN0aW9uKGEpe3ZhciBzPW51bGwscj0kLlgzCmlmKEMuTlU9PT1yKXtQ
+LlRrKHMscyxDLk5VLGEpCnJldHVybn1QLlRrKHMscyxyLHQuTS5hKHIuR1koYSkpKX0sClF3OmZ1bmN0
+aW9uKGEsYil7SC5jYihhLCJzdHJlYW0iLHQuSykKcmV0dXJuIG5ldyBQLnhJKGIuQygieEk8MD4iKSl9
+LApMMjpmdW5jdGlvbihhLGIsYyxkLGUpe1AuclIobmV3IFAucEsoZCxlKSl9LApUODpmdW5jdGlvbihh
+LGIsYyxkLGUpe3ZhciBzLHI9JC5YMwppZihyPT09YylyZXR1cm4gZC4kMCgpCiQuWDM9YwpzPXIKdHJ5
+e3I9ZC4kMCgpCnJldHVybiByfWZpbmFsbHl7JC5YMz1zfX0sCnl2OmZ1bmN0aW9uKGEsYixjLGQsZSxm
+LGcpe3ZhciBzLHI9JC5YMwppZihyPT09YylyZXR1cm4gZC4kMShlKQokLlgzPWMKcz1yCnRyeXtyPWQu
+JDEoZSkKcmV0dXJuIHJ9ZmluYWxseXskLlgzPXN9fSwKUXg6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyxo
+LGkpe3ZhciBzLHI9JC5YMwppZihyPT09YylyZXR1cm4gZC4kMihlLGYpCiQuWDM9YwpzPXIKdHJ5e3I9
+ZC4kMihlLGYpCnJldHVybiByfWZpbmFsbHl7JC5YMz1zfX0sClRrOmZ1bmN0aW9uKGEsYixjLGQpe3Zh
+ciBzCnQuTS5hKGQpCnM9Qy5OVSE9PWMKaWYocylkPSEoIXN8fCExKT9jLkdZKGQpOmMuUlQoZCx0Lkgp
+ClAuZVcoZCl9LAp0aDpmdW5jdGlvbiB0aChhKXt0aGlzLmE9YX0sCmhhOmZ1bmN0aW9uIGhhKGEsYixj
+KXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClZzOmZ1bmN0aW9uIFZzKGEpe3RoaXMuYT1hfSwK
+RnQ6ZnVuY3Rpb24gRnQoYSl7dGhpcy5hPWF9LApXMzpmdW5jdGlvbiBXMygpe30sCnlIOmZ1bmN0aW9u
+IHlIKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAppaDpmdW5jdGlvbiBpaChhLGIpe3RoaXMuYT1hCnRo
+aXMuYj0hMQp0aGlzLiR0aT1ifSwKV006ZnVuY3Rpb24gV00oYSl7dGhpcy5hPWF9LApTWDpmdW5jdGlv
+biBTWChhKXt0aGlzLmE9YX0sCkdzOmZ1bmN0aW9uIEdzKGEpe3RoaXMuYT1hfSwKRnk6ZnVuY3Rpb24g
+RnkoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkdWOmZ1bmN0aW9uIEdWKGEsYil7dmFyIF89dGhpcwpf
+LmE9YQpfLmQ9Xy5jPV8uYj1udWxsCl8uJHRpPWJ9LApxNDpmdW5jdGlvbiBxNChhLGIpe3RoaXMuYT1h
+CnRoaXMuJHRpPWJ9LApDdzpmdW5jdGlvbiBDdyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKUGY6ZnVu
+Y3Rpb24gUGYoKXt9LApaZjpmdW5jdGlvbiBaZihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApGZTpm
+dW5jdGlvbiBGZShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPW51bGwKXy5iPWEKXy5jPWIKXy5kPWMK
+Xy5lPWQKXy4kdGk9ZX0sCnZzOmZ1bmN0aW9uIHZzKGEsYil7dmFyIF89dGhpcwpfLmE9MApfLmI9YQpf
+LmM9bnVsbApfLiR0aT1ifSwKZGE6ZnVuY3Rpb24gZGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCm9R
+OmZ1bmN0aW9uIG9RKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApwVjpmdW5jdGlvbiBwVihhKXt0aGlz
+LmE9YX0sClU3OmZ1bmN0aW9uIFU3KGEpe3RoaXMuYT1hfSwKdnI6ZnVuY3Rpb24gdnIoYSxiLGMpe3Ro
+aXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcnQ6ZnVuY3Rpb24gcnQoYSxiKXt0aGlzLmE9YQp0aGlz
+LmI9Yn0sCktGOmZ1bmN0aW9uIEtGKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApaTDpmdW5jdGlvbiBa
+TChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApSVDpmdW5jdGlvbiBSVChhLGIsYyl7
+dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApqWjpmdW5jdGlvbiBqWihhKXt0aGlzLmE9YX0sCnJx
+OmZ1bmN0aW9uIHJxKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApSVzpmdW5jdGlvbiBSVyhhLGIpe3Ro
+aXMuYT1hCnRoaXMuYj1ifSwKT006ZnVuY3Rpb24gT00oYSl7dGhpcy5hPWEKdGhpcy5iPW51bGx9LApx
+aDpmdW5jdGlvbiBxaCgpe30sCkI1OmZ1bmN0aW9uIEI1KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp1
+TzpmdW5jdGlvbiB1TyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKTU86ZnVuY3Rpb24gTU8oKXt9LApr
+VDpmdW5jdGlvbiBrVCgpe30sCnhJOmZ1bmN0aW9uIHhJKGEpe3RoaXMuJHRpPWF9LAptMDpmdW5jdGlv
+biBtMCgpe30sCnBLOmZ1bmN0aW9uIHBLKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApKaTpmdW5jdGlv
+biBKaSgpe30sCmhqOmZ1bmN0aW9uIGhqKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30s
+ClZwOmZ1bmN0aW9uIFZwKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApPUjpmdW5jdGlvbiBPUihhLGIs
+Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApFRjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIGIu
+QygiQDwwPiIpLktxKGMpLkMoIkZvPDEsMj4iKS5hKEguQjcoYSxuZXcgSC5ONShiLkMoIkA8MD4iKS5L
+cShjKS5DKCJONTwxLDI+IikpKSl9LApGbDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5ONShhLkMo
+IkA8MD4iKS5LcShiKS5DKCJONTwxLDI+IikpfSwKTHM6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmI2
+KGEuQygiYjY8MD4iKSl9LApUMjpmdW5jdGlvbigpe3ZhciBzPU9iamVjdC5jcmVhdGUobnVsbCkKc1si
+PG5vbi1pZGVudGlmaWVyLWtleT4iXT1zCmRlbGV0ZSBzWyI8bm9uLWlkZW50aWZpZXIta2V5PiJdCnJl
+dHVybiBzfSwKcmo6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPW5ldyBQLmxtKGEsYixjLkMoImxtPDA+Iikp
+CnMuYz1hLmUKcmV0dXJuIHN9LApFUDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscgppZihQLmhCKGEpKXtp
+ZihiPT09IigiJiZjPT09IikiKXJldHVybiIoLi4uKSIKcmV0dXJuIGIrIi4uLiIrY31zPUguVk0oW10s
+dC5zKQpDLk5tLmkoJC54ZyxhKQp0cnl7UC5WcihhLHMpfWZpbmFsbHl7aWYoMD49JC54Zy5sZW5ndGgp
+cmV0dXJuIEguT0goJC54ZywtMSkKJC54Zy5wb3AoKX1yPVAudmcoYix0LnUuYShzKSwiLCAiKStjCnJl
+dHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfSwKV0U6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIKaWYo
+UC5oQihhKSlyZXR1cm4gYisiLi4uIitjCnM9bmV3IFAuUm4oYikKQy5ObS5pKCQueGcsYSkKdHJ5e3I9
+cwpyLmE9UC52ZyhyLmEsYSwiLCAiKX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3RoKXJldHVybiBILk9I
+KCQueGcsLTEpCiQueGcucG9wKCl9cy5hKz1jCnI9cy5hCnJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/
+cjpyfSwKaEI6ZnVuY3Rpb24oYSl7dmFyIHMscgpmb3Iocz0kLnhnLmxlbmd0aCxyPTA7cjxzOysrcilp
+ZihhPT09JC54Z1tyXSlyZXR1cm4hMApyZXR1cm4hMX0sClZyOmZ1bmN0aW9uKGEsYil7dmFyIHMscixx
+LHAsbyxuLG0sbD1hLmdtKGEpLGs9MCxqPTAKd2hpbGUoITApe2lmKCEoazw4MHx8ajwzKSlicmVhawpp
+ZighbC5GKCkpcmV0dXJuCnM9SC5FaihsLmdsKCkpCkMuTm0uaShiLHMpCmsrPXMubGVuZ3RoKzI7Kytq
+fWlmKCFsLkYoKSl7aWYoajw9NSlyZXR1cm4KaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkK
+cj1iLnBvcCgpCmlmKDA+PWIubGVuZ3RoKXJldHVybiBILk9IKGIsLTEpCnE9Yi5wb3AoKX1lbHNle3A9
+bC5nbCgpOysragppZighbC5GKCkpe2lmKGo8PTQpe0MuTm0uaShiLEguRWoocCkpCnJldHVybn1yPUgu
+RWoocCkKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKcT1iLnBvcCgpCmsrPXIubGVuZ3Ro
+KzJ9ZWxzZXtvPWwuZ2woKTsrK2oKZm9yKDtsLkYoKTtwPW8sbz1uKXtuPWwuZ2woKTsrK2oKaWYoaj4x
+MDApe3doaWxlKCEwKXtpZighKGs+NzUmJmo+MykpYnJlYWsKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEgu
+T0goYiwtMSkKay09Yi5wb3AoKS5sZW5ndGgrMjstLWp9Qy5ObS5pKGIsIi4uLiIpCnJldHVybn19cT1I
+LkVqKHApCnI9SC5FaihvKQprKz1yLmxlbmd0aCtxLmxlbmd0aCs0fX1pZihqPmIubGVuZ3RoKzIpe2sr
+PTUKbT0iLi4uIn1lbHNlIG09bnVsbAp3aGlsZSghMCl7aWYoIShrPjgwJiZiLmxlbmd0aD4zKSlicmVh
+awppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQprLT1iLnBvcCgpLmxlbmd0aCsyCmlmKG09
+PW51bGwpe2srPTUKbT0iLi4uIn19aWYobSE9bnVsbClDLk5tLmkoYixtKQpDLk5tLmkoYixxKQpDLk5t
+LmkoYixyKX0sCnRNOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPVAuTHMoYikKZm9yKHM9YS5sZW5ndGgs
+cj0wO3I8YS5sZW5ndGg7YS5sZW5ndGg9PT1zfHwoMCxILmxrKShhKSwrK3IpcS5pKDAsYi5hKGFbcl0p
+KQpyZXR1cm4gcX0sCm5POmZ1bmN0aW9uKGEpe3ZhciBzLHI9e30KaWYoUC5oQihhKSlyZXR1cm4iey4u
+Ln0iCnM9bmV3IFAuUm4oIiIpCnRyeXtDLk5tLmkoJC54ZyxhKQpzLmErPSJ7IgpyLmE9ITAKYS5LKDAs
+bmV3IFAucmEocixzKSkKcy5hKz0ifSJ9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5P
+SCgkLnhnLC0xKQokLnhnLnBvcCgpfXI9cy5hCnJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfSwK
+YjY6ZnVuY3Rpb24gYjYoYSl7dmFyIF89dGhpcwpfLmE9MApfLmY9Xy5lPV8uZD1fLmM9Xy5iPW51bGwK
+Xy5yPTAKXy4kdGk9YX0sCmJuOmZ1bmN0aW9uIGJuKGEpe3RoaXMuYT1hCnRoaXMuYz10aGlzLmI9bnVs
+bH0sCmxtOmZ1bmN0aW9uIGxtKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVs
+bApfLiR0aT1jfSwKbVc6ZnVuY3Rpb24gbVcoKXt9LAp1eTpmdW5jdGlvbiB1eSgpe30sCmxEOmZ1bmN0
+aW9uIGxEKCl7fSwKaWw6ZnVuY3Rpb24gaWwoKXt9LApyYTpmdW5jdGlvbiByYShhLGIpe3RoaXMuYT1h
+CnRoaXMuYj1ifSwKWWs6ZnVuY3Rpb24gWWsoKXt9LAp5UTpmdW5jdGlvbiB5UShhKXt0aGlzLmE9YX0s
+CktQOmZ1bmN0aW9uIEtQKCl7fSwKUG46ZnVuY3Rpb24gUG4oKXt9LApHajpmdW5jdGlvbiBHaihhLGIp
+e3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApsZjpmdW5jdGlvbiBsZigpe30sClZqOmZ1bmN0aW9uIFZqKCl7
+fSwKWHY6ZnVuY3Rpb24gWHYoKXt9LApuWTpmdW5jdGlvbiBuWSgpe30sCldZOmZ1bmN0aW9uIFdZKCl7
+fSwKUlU6ZnVuY3Rpb24gUlUoKXt9LApwUjpmdW5jdGlvbiBwUigpe30sCkJTOmZ1bmN0aW9uKGEsYil7
+dmFyIHMscixxLHAKaWYodHlwZW9mIGEhPSJzdHJpbmciKXRocm93IEguYihILnRMKGEpKQpzPW51bGwK
+dHJ5e3M9SlNPTi5wYXJzZShhKX1jYXRjaChxKXtyPUguUnUocSkKcD1QLnJyKFN0cmluZyhyKSxudWxs
+LG51bGwpCnRocm93IEguYihwKX1wPVAuUWUocykKcmV0dXJuIHB9LApRZTpmdW5jdGlvbihhKXt2YXIg
+cwppZihhPT1udWxsKXJldHVybiBudWxsCmlmKHR5cGVvZiBhIT0ib2JqZWN0IilyZXR1cm4gYQppZihP
+YmplY3QuZ2V0UHJvdG90eXBlT2YoYSkhPT1BcnJheS5wcm90b3R5cGUpcmV0dXJuIG5ldyBQLnV3KGEs
+T2JqZWN0LmNyZWF0ZShudWxsKSkKZm9yKHM9MDtzPGEubGVuZ3RoOysrcylhW3NdPVAuUWUoYVtzXSkK
+cmV0dXJuIGF9LApreTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyCmlmKGIgaW5zdGFuY2VvZiBVaW50
+OEFycmF5KXtzPWIKZD1zLmxlbmd0aAppZihkLWM8MTUpcmV0dXJuIG51bGwKcj1QLkNHKGEscyxjLGQp
+CmlmKHIhPW51bGwmJmEpaWYoci5pbmRleE9mKCJcdWZmZmQiKT49MClyZXR1cm4gbnVsbApyZXR1cm4g
+cn1yZXR1cm4gbnVsbH0sCkNHOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzPWE/JC5IRygpOiQucmYoKQpp
+ZihzPT1udWxsKXJldHVybiBudWxsCmlmKDA9PT1jJiZkPT09Yi5sZW5ndGgpcmV0dXJuIFAuUmIocyxi
+KQpyZXR1cm4gUC5SYihzLGIuc3ViYXJyYXkoYyxQLmpCKGMsZCxiLmxlbmd0aCkpKX0sClJiOmZ1bmN0
+aW9uKGEsYil7dmFyIHMscgp0cnl7cz1hLmRlY29kZShiKQpyZXR1cm4gc31jYXRjaChyKXtILlJ1KHIp
+fXJldHVybiBudWxsfSwKeE06ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe2lmKEMuam4uelkoZiw0KSE9PTAp
+dGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsIHBhZGRlZCBsZW5ndGggbXVzdCBi
+ZSBtdWx0aXBsZSBvZiBmb3VyLCBpcyAiK2YsYSxjKSkKaWYoZCtlIT09Zil0aHJvdyBILmIoUC5ycigi
+SW52YWxpZCBiYXNlNjQgcGFkZGluZywgJz0nIG5vdCBhdCB0aGUgZW5kIixhLGIpKQppZihlPjIpdGhy
+b3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsIG1vcmUgdGhhbiB0d28gJz0nIGNoYXJh
+Y3RlcnMiLGEsYikpfSwKR3k6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBuZXcgUC5VZChhLGIpfSwKTkM6
+ZnVuY3Rpb24oYSl7cmV0dXJuIGEuTHQoKX0sClVnOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQLnR1
+KGEsW10sUC5DeSgpKX0sCnVYOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPW5ldyBQLlJuKCIiKSxxPVAu
+VWcocixiKQpxLmlVKGEpCnM9ci5hCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKajQ6ZnVu
+Y3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UgNjU6cmV0dXJuIk1pc3NpbmcgZXh0ZW5zaW9uIGJ5dGUiCmNh
+c2UgNjc6cmV0dXJuIlVuZXhwZWN0ZWQgZXh0ZW5zaW9uIGJ5dGUiCmNhc2UgNjk6cmV0dXJuIkludmFs
+aWQgVVRGLTggYnl0ZSIKY2FzZSA3MTpyZXR1cm4iT3ZlcmxvbmcgZW5jb2RpbmciCmNhc2UgNzM6cmV0
+dXJuIk91dCBvZiB1bmljb2RlIHJhbmdlIgpjYXNlIDc1OnJldHVybiJFbmNvZGVkIHN1cnJvZ2F0ZSIK
+Y2FzZSA3NzpyZXR1cm4iVW5maW5pc2hlZCBVVEYtOCBvY3RldCBzZXF1ZW5jZSIKZGVmYXVsdDpyZXR1
+cm4iIn19LApqeTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHA9Yy1iLG89bmV3IFVpbnQ4QXJyYXko
+cCkKZm9yKHM9Si5VNihhKSxyPTA7cjxwOysrcil7cT1zLnEoYSxiK3IpCmlmKHR5cGVvZiBxIT09Im51
+bWJlciIpcmV0dXJuIHEuek0oKQppZigocSY0Mjk0OTY3MDQwKT4+PjAhPT0wKXE9MjU1CmlmKHI+PXAp
+cmV0dXJuIEguT0gobyxyKQpvW3JdPXF9cmV0dXJuIG99LAp1dzpmdW5jdGlvbiB1dyhhLGIpe3RoaXMu
+YT1hCnRoaXMuYj1iCnRoaXMuYz1udWxsfSwKaTg6ZnVuY3Rpb24gaTgoYSl7dGhpcy5hPWF9LAp4cjpm
+dW5jdGlvbiB4cigpe30sCk56OmZ1bmN0aW9uIE56KCl7fSwKQ1Y6ZnVuY3Rpb24gQ1YoKXt9LApVODpm
+dW5jdGlvbiBVOCgpe30sClVrOmZ1bmN0aW9uIFVrKCl7fSwKd0k6ZnVuY3Rpb24gd0koKXt9LApaaTpm
+dW5jdGlvbiBaaSgpe30sClVkOmZ1bmN0aW9uIFVkKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApLODpm
+dW5jdGlvbiBLOChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKYnk6ZnVuY3Rpb24gYnkoKXt9LApvajpm
+dW5jdGlvbiBvaihhKXt0aGlzLmI9YX0sCk14OmZ1bmN0aW9uIE14KGEpe3RoaXMuYT1hfSwKU2g6ZnVu
+Y3Rpb24gU2goKXt9LAp0aTpmdW5jdGlvbiB0aShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKdHU6ZnVu
+Y3Rpb24gdHUoYSxiLGMpe3RoaXMuYz1hCnRoaXMuYT1iCnRoaXMuYj1jfSwKdTU6ZnVuY3Rpb24gdTUo
+KXt9LApFMzpmdW5jdGlvbiBFMygpe30sClJ3OmZ1bmN0aW9uIFJ3KGEpe3RoaXMuYj0wCnRoaXMuYz1h
+fSwKR1k6ZnVuY3Rpb24gR1koYSl7dGhpcy5hPWF9LApiejpmdW5jdGlvbiBieihhKXt0aGlzLmE9YQp0
+aGlzLmI9MTYKdGhpcy5jPTB9LApRQTpmdW5jdGlvbihhLGIpe3ZhciBzPUguSHAoYSxiKQppZihzIT1u
+dWxsKXJldHVybiBzCnRocm93IEguYihQLnJyKGEsbnVsbCxudWxsKSl9LApvczpmdW5jdGlvbihhKXtp
+ZihhIGluc3RhbmNlb2YgSC5UcClyZXR1cm4gYS53KDApCnJldHVybiJJbnN0YW5jZSBvZiAnIitILkVq
+KEguTShhKSkrIicifSwKTzg6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscj1jP0ouS2goYSxkKTpKLlFp
+KGEsZCkKaWYoYSE9PTAmJmIhPW51bGwpZm9yKHM9MDtzPHIubGVuZ3RoOysrcylyW3NdPWIKcmV0dXJu
+IHJ9LApDSDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj1ILlZNKFtdLGMuQygiamQ8MD4iKSkKZm9yKHM9
+Si5JVChhKTtzLkYoKTspQy5ObS5pKHIsYy5hKHMuZ2woKSkpCmlmKGIpcmV0dXJuIHIKcmV0dXJuIEou
+RXAocixjKX0sClkxOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwppZihiKXJldHVybiBQLmV2KGEsYykKcz1K
+LkVwKFAuZXYoYSxjKSxjKQpyZXR1cm4gc30sCmV2OmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZihBcnJh
+eS5pc0FycmF5KGEpKXJldHVybiBILlZNKGEuc2xpY2UoMCksYi5DKCJqZDwwPiIpKQpzPUguVk0oW10s
+Yi5DKCJqZDwwPiIpKQpmb3Iocj1KLklUKGEpO3IuRigpOylDLk5tLmkocyxyLmdsKCkpCnJldHVybiBz
+fSwKQUY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi56QyhQLkNIKGEsITEsYikpfSwKSE06ZnVuY3Rpb24o
+YSxiLGMpe2lmKHQuYm0uYihhKSlyZXR1cm4gSC5mdyhhLGIsUC5qQihiLGMsYS5sZW5ndGgpKQpyZXR1
+cm4gUC5idyhhLGIsYyl9LApPbzpmdW5jdGlvbihhKXtyZXR1cm4gSC5MdyhhKX0sCmJ3OmZ1bmN0aW9u
+KGEsYixjKXt2YXIgcyxyLHEscCxvPW51bGwKaWYoYjwwKXRocm93IEguYihQLlRFKGIsMCxhLmxlbmd0
+aCxvLG8pKQpzPWM9PW51bGwKaWYoIXMmJmM8Yil0aHJvdyBILmIoUC5URShjLGIsYS5sZW5ndGgsbyxv
+KSkKcj1uZXcgSC5hNyhhLGEubGVuZ3RoLEgueihhKS5DKCJhNzxsRC5FPiIpKQpmb3IocT0wO3E8Yjsr
+K3EpaWYoIXIuRigpKXRocm93IEguYihQLlRFKGIsMCxxLG8sbykpCnA9W10KaWYocylmb3IoO3IuRigp
+OylwLnB1c2goci5kKQplbHNlIGZvcihxPWI7cTxjOysrcSl7aWYoIXIuRigpKXRocm93IEguYihQLlRF
+KGMsYixxLG8sbykpCnAucHVzaChyLmQpfXJldHVybiBILmVUKHApfSwKbnU6ZnVuY3Rpb24oYSl7cmV0
+dXJuIG5ldyBILlZSKGEsSC52NChhLCExLCEwLCExLCExLCExKSl9LAp2ZzpmdW5jdGlvbihhLGIsYyl7
+dmFyIHM9Si5JVChiKQppZighcy5GKCkpcmV0dXJuIGEKaWYoYy5sZW5ndGg9PT0wKXtkbyBhKz1ILkVq
+KHMuZ2woKSkKd2hpbGUocy5GKCkpfWVsc2V7YSs9SC5FaihzLmdsKCkpCmZvcig7cy5GKCk7KWE9YStj
+K0guRWoocy5nbCgpKX1yZXR1cm4gYX0sCmxyOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBuZXcgUC5t
+cChhLGIsYyxkKX0sCnVvOmZ1bmN0aW9uKCl7dmFyIHM9SC5NMCgpCmlmKHMhPW51bGwpcmV0dXJuIFAu
+aEsocykKdGhyb3cgSC5iKFAuTDQoIidVcmkuYmFzZScgaXMgbm90IHN1cHBvcnRlZCIpKX0sCmVQOmZ1
+bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwLG8sbixtPSIwMTIzNDU2Nzg5QUJDREVGIgppZihjPT09
+Qy54TSl7cz0kLno0KCkuYgppZih0eXBlb2YgYiE9InN0cmluZyIpSC52KEgudEwoYikpCnM9cy50ZXN0
+KGIpfWVsc2Ugcz0hMQppZihzKXJldHVybiBiCkguTGgoYykuQygiVWsuUyIpLmEoYikKcj1jLmdaRSgp
+LldKKGIpCmZvcihzPXIubGVuZ3RoLHE9MCxwPSIiO3E8czsrK3Epe289cltxXQppZihvPDEyOCl7bj1v
+Pj4+NAppZihuPj04KXJldHVybiBILk9IKGEsbikKbj0oYVtuXSYxPDwobyYxNSkpIT09MH1lbHNlIG49
+ITEKaWYobilwKz1ILkx3KG8pCmVsc2UgcD1kJiZvPT09MzI/cCsiKyI6cCsiJSIrbVtvPj4+NCYxNV0r
+bVtvJjE1XX1yZXR1cm4gcC5jaGFyQ29kZUF0KDApPT0wP3A6cH0sCkdxOmZ1bmN0aW9uKGEpe3ZhciBz
+PU1hdGguYWJzKGEpLHI9YTwwPyItIjoiIgppZihzPj0xMDAwKXJldHVybiIiK2EKaWYocz49MTAwKXJl
+dHVybiByKyIwIitzCmlmKHM+PTEwKXJldHVybiByKyIwMCIrcwpyZXR1cm4gcisiMDAwIitzfSwKVng6
+ZnVuY3Rpb24oYSl7aWYoYT49MTAwKXJldHVybiIiK2EKaWYoYT49MTApcmV0dXJuIjAiK2EKcmV0dXJu
+IjAwIithfSwKaDA6ZnVuY3Rpb24oYSl7aWYoYT49MTApcmV0dXJuIiIrYQpyZXR1cm4iMCIrYX0sCnA6
+ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIifHxILmwoYSl8fG51bGw9PWEpcmV0dXJuIEou
+aihhKQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEpTT04uc3RyaW5naWZ5KGEpCnJldHVybiBQ
+Lm9zKGEpfSwKaFY6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkM2KGEpfSwKeFk6ZnVuY3Rpb24oYSl7
+cmV0dXJuIG5ldyBQLnUoITEsbnVsbCxudWxsLGEpfSwKTDM6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBu
+ZXcgUC51KCEwLGEsYixjKX0sCk1SOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gYX0sCk83OmZ1bmN0aW9u
+KGEsYil7cmV0dXJuIG5ldyBQLmJKKG51bGwsbnVsbCwhMCxhLGIsIlZhbHVlIG5vdCBpbiByYW5nZSIp
+fSwKVEU6ZnVuY3Rpb24oYSxiLGMsZCxlKXtyZXR1cm4gbmV3IFAuYkooYixjLCEwLGEsZCwiSW52YWxp
+ZCB2YWx1ZSIpfSwKd0E6ZnVuY3Rpb24oYSxiLGMsZCl7aWYoYTxifHxhPmMpdGhyb3cgSC5iKFAuVEUo
+YSxiLGMsZCxudWxsKSkKcmV0dXJuIGF9LApqQjpmdW5jdGlvbihhLGIsYyl7aWYoMD5hfHxhPmMpdGhy
+b3cgSC5iKFAuVEUoYSwwLGMsInN0YXJ0IixudWxsKSkKaWYoYiE9bnVsbCl7aWYoYT5ifHxiPmMpdGhy
+b3cgSC5iKFAuVEUoYixhLGMsImVuZCIsbnVsbCkpCnJldHVybiBifXJldHVybiBjfSwKazE6ZnVuY3Rp
+b24oYSxiKXtpZihhPDApdGhyb3cgSC5iKFAuVEUoYSwwLG51bGwsYixudWxsKSkKcmV0dXJuIGF9LApD
+ZjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBzPUgudVAoZT09bnVsbD9KLkhtKGIpOmUpCnJldHVybiBu
+ZXcgUC5lWShzLCEwLGEsYywiSW5kZXggb3V0IG9mIHJhbmdlIil9LApMNDpmdW5jdGlvbihhKXtyZXR1
+cm4gbmV3IFAudWIoYSl9LApTWTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuZHMoYSl9LApQVjpmdW5j
+dGlvbihhKXtyZXR1cm4gbmV3IFAubGooYSl9LAphNDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVVYo
+YSl9LApycjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG5ldyBQLmFFKGEsYixjKX0sCmhLOmZ1bmN0aW9u
+KGE1KXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYSxhMCxhMSxhMixhMz1u
+dWxsLGE0PWE1Lmxlbmd0aAppZihhND49NSl7cz0oKEouUXooYTUsNCleNTgpKjN8Qy54Qi5XKGE1LDAp
+XjEwMHxDLnhCLlcoYTUsMSleOTd8Qy54Qi5XKGE1LDIpXjExNnxDLnhCLlcoYTUsMyleOTcpPj4+MApp
+ZihzPT09MClyZXR1cm4gUC5LRChhNDxhND9DLnhCLk5qKGE1LDAsYTQpOmE1LDUsYTMpLmdsUigpCmVs
+c2UgaWYocz09PTMyKXJldHVybiBQLktEKEMueEIuTmooYTUsNSxhNCksMCxhMykuZ2xSKCl9cj1QLk84
+KDgsMCwhMSx0LlMpCkMuTm0uWTUociwwLDApCkMuTm0uWTUociwxLC0xKQpDLk5tLlk1KHIsMiwtMSkK
+Qy5ObS5ZNShyLDcsLTEpCkMuTm0uWTUociwzLDApCkMuTm0uWTUociw0LDApCkMuTm0uWTUociw1LGE0
+KQpDLk5tLlk1KHIsNixhNCkKaWYoUC5VQihhNSwwLGE0LDAscik+PTE0KUMuTm0uWTUociw3LGE0KQpx
+PXJbMV0KaWYocT49MClpZihQLlVCKGE1LDAscSwyMCxyKT09PTIwKXJbN109cQpwPXJbMl0rMQpvPXJb
+M10Kbj1yWzRdCm09cls1XQpsPXJbNl0KaWYobDxtKW09bAppZihuPHApbj1tCmVsc2UgaWYobjw9cSlu
+PXErMQppZihvPHApbz1uCms9cls3XTwwCmlmKGspaWYocD5xKzMpe2o9YTMKaz0hMX1lbHNle2k9bz4w
+CmlmKGkmJm8rMT09PW4pe2o9YTMKaz0hMX1lbHNle2lmKCEobTxhNCYmbT09PW4rMiYmSi5xMChhNSwi
+Li4iLG4pKSloPW0+bisyJiZKLnEwKGE1LCIvLi4iLG0tMykKZWxzZSBoPSEwCmlmKGgpe2o9YTMKaz0h
+MX1lbHNle2lmKHE9PT00KWlmKEoucTAoYTUsImZpbGUiLDApKXtpZihwPD0wKXtpZighQy54Qi5RaShh
+NSwiLyIsbikpe2c9ImZpbGU6Ly8vIgpzPTN9ZWxzZXtnPSJmaWxlOi8vIgpzPTJ9YTU9ZytDLnhCLk5q
+KGE1LG4sYTQpCnEtPTAKaT1zLTAKbSs9aQpsKz1pCmE0PWE1Lmxlbmd0aApwPTcKbz03Cm49N31lbHNl
+IGlmKG49PT1tKXsrK2wKZj1tKzEKYTU9Qy54Qi5pNyhhNSxuLG0sIi8iKTsrK2E0Cm09Zn1qPSJmaWxl
+In1lbHNlIGlmKEMueEIuUWkoYTUsImh0dHAiLDApKXtpZihpJiZvKzM9PT1uJiZDLnhCLlFpKGE1LCI4
+MCIsbysxKSl7bC09MwplPW4tMwptLT0zCmE1PUMueEIuaTcoYTUsbyxuLCIiKQphNC09MwpuPWV9aj0i
+aHR0cCJ9ZWxzZSBqPWEzCmVsc2UgaWYocT09PTUmJkoucTAoYTUsImh0dHBzIiwwKSl7aWYoaSYmbys0
+PT09biYmSi5xMChhNSwiNDQzIixvKzEpKXtsLT00CmU9bi00Cm0tPTQKYTU9Si5kZyhhNSxvLG4sIiIp
+CmE0LT0zCm49ZX1qPSJodHRwcyJ9ZWxzZSBqPWEzCms9ITB9fX1lbHNlIGo9YTMKaWYoayl7aT1hNS5s
+ZW5ndGgKaWYoYTQ8aSl7YTU9Si5sZChhNSwwLGE0KQpxLT0wCnAtPTAKby09MApuLT0wCm0tPTAKbC09
+MH1yZXR1cm4gbmV3IFAuVWYoYTUscSxwLG8sbixtLGwsail9aWYoaj09bnVsbClpZihxPjApaj1QLlBp
+KGE1LDAscSkKZWxzZXtpZihxPT09MCl7UC5SMyhhNSwwLCJJbnZhbGlkIGVtcHR5IHNjaGVtZSIpCkgu
+QmkodS5nKX1qPSIifWlmKHA+MCl7ZD1xKzMKYz1kPHA/UC56UihhNSxkLHAtMSk6IiIKYj1QLk9lKGE1
+LHAsbywhMSkKaT1vKzEKaWYoaTxuKXthPUguSHAoSi5sZChhNSxpLG4pLGEzKQphMD1QLndCKGE9PW51
+bGw/SC52KFAucnIoIkludmFsaWQgcG9ydCIsYTUsaSkpOmEsail9ZWxzZSBhMD1hM31lbHNle2EwPWEz
+CmI9YTAKYz0iIn1hMT1QLmthKGE1LG4sbSxhMyxqLGIhPW51bGwpCmEyPW08bD9QLmxlKGE1LG0rMSxs
+LGEzKTphMwpyZXR1cm4gbmV3IFAuRG4oaixjLGIsYTAsYTEsYTIsbDxhND9QLnRHKGE1LGwrMSxhNCk6
+YTMpfSwKTXQ6ZnVuY3Rpb24oYSl7SC5oKGEpCnJldHVybiBQLmt1KGEsMCxhLmxlbmd0aCxDLnhNLCEx
+KX0sCldYOmZ1bmN0aW9uKGEpe3ZhciBzPXQuTgpyZXR1cm4gQy5ObS5OMChILlZNKGEuc3BsaXQoIiYi
+KSx0LnMpLFAuRmwocyxzKSxuZXcgUC5uMShDLnhNKSx0LkopfSwKSGg6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciBzLHIscSxwLG8sbixtPSJJUHY0IGFkZHJlc3Mgc2hvdWxkIGNvbnRhaW4gZXhhY3RseSA0IHBhcnRz
+IixsPSJlYWNoIHBhcnQgbXVzdCBiZSBpbiB0aGUgcmFuZ2UgMC4uMjU1IixrPW5ldyBQLmNTKGEpLGo9
+bmV3IFVpbnQ4QXJyYXkoNCkKZm9yKHM9YixyPXMscT0wO3M8YzsrK3Mpe3A9Qy54Qi5PKGEscykKaWYo
+cCE9PTQ2KXtpZigocF40OCk+OSlrLiQyKCJpbnZhbGlkIGNoYXJhY3RlciIscyl9ZWxzZXtpZihxPT09
+MylrLiQyKG0scykKbz1QLlFBKEMueEIuTmooYSxyLHMpLG51bGwpCmlmKG8+MjU1KWsuJDIobCxyKQpu
+PXErMQppZihxPj00KXJldHVybiBILk9IKGoscSkKaltxXT1vCnI9cysxCnE9bn19aWYocSE9PTMpay4k
+MihtLGMpCm89UC5RQShDLnhCLk5qKGEscixjKSxudWxsKQppZihvPjI1NSlrLiQyKGwscikKaWYocT49
+NClyZXR1cm4gSC5PSChqLHEpCmpbcV09bwpyZXR1cm4gan0sCmVnOmZ1bmN0aW9uKGEsYixhMCl7dmFy
+IHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQ9bmV3IFAuVkMoYSksYz1uZXcgUC5KVChkLGEp
+CmlmKGEubGVuZ3RoPDIpZC4kMSgiYWRkcmVzcyBpcyB0b28gc2hvcnQiKQpzPUguVk0oW10sdC5hKQpm
+b3Iocj1iLHE9cixwPSExLG89ITE7cjxhMDsrK3Ipe249Qy54Qi5PKGEscikKaWYobj09PTU4KXtpZihy
+PT09Yil7KytyCmlmKEMueEIuTyhhLHIpIT09NTgpZC4kMigiaW52YWxpZCBzdGFydCBjb2xvbi4iLHIp
+CnE9cn1pZihyPT09cSl7aWYocClkLiQyKCJvbmx5IG9uZSB3aWxkY2FyZCBgOjpgIGlzIGFsbG93ZWQi
+LHIpCkMuTm0uaShzLC0xKQpwPSEwfWVsc2UgQy5ObS5pKHMsYy4kMihxLHIpKQpxPXIrMX1lbHNlIGlm
+KG49PT00NilvPSEwfWlmKHMubGVuZ3RoPT09MClkLiQxKCJ0b28gZmV3IHBhcnRzIikKbT1xPT09YTAK
+bD1DLk5tLmdyWihzKQppZihtJiZsIT09LTEpZC4kMigiZXhwZWN0ZWQgYSBwYXJ0IGFmdGVyIGxhc3Qg
+YDpgIixhMCkKaWYoIW0paWYoIW8pQy5ObS5pKHMsYy4kMihxLGEwKSkKZWxzZXtrPVAuSGgoYSxxLGEw
+KQpDLk5tLmkocywoa1swXTw8OHxrWzFdKT4+PjApCkMuTm0uaShzLChrWzJdPDw4fGtbM10pPj4+MCl9
+aWYocCl7aWYocy5sZW5ndGg+NylkLiQxKCJhbiBhZGRyZXNzIHdpdGggYSB3aWxkY2FyZCBtdXN0IGhh
+dmUgbGVzcyB0aGFuIDcgcGFydHMiKX1lbHNlIGlmKHMubGVuZ3RoIT09OClkLiQxKCJhbiBhZGRyZXNz
+IHdpdGhvdXQgYSB3aWxkY2FyZCBtdXN0IGNvbnRhaW4gZXhhY3RseSA4IHBhcnRzIikKaj1uZXcgVWlu
+dDhBcnJheSgxNikKZm9yKGw9cy5sZW5ndGgsaT05LWwscj0wLGg9MDtyPGw7KytyKXtnPXNbcl0KaWYo
+Zz09PS0xKWZvcihmPTA7ZjxpOysrZil7aWYoaDwwfHxoPj0xNilyZXR1cm4gSC5PSChqLGgpCmpbaF09
+MAplPWgrMQppZihlPj0xNilyZXR1cm4gSC5PSChqLGUpCmpbZV09MApoKz0yfWVsc2V7ZT1DLmpuLndH
+KGcsOCkKaWYoaDwwfHxoPj0xNilyZXR1cm4gSC5PSChqLGgpCmpbaF09ZQplPWgrMQppZihlPj0xNily
+ZXR1cm4gSC5PSChqLGUpCmpbZV09ZyYyNTUKaCs9Mn19cmV0dXJuIGp9LApLTDpmdW5jdGlvbihhLGIs
+YyxkLGUsZixnKXt2YXIgcyxyLHEscCxvLG4KZj1mPT1udWxsPyIiOlAuUGkoZiwwLGYubGVuZ3RoKQpn
+PVAuelIoZywwLGc9PW51bGw/MDpnLmxlbmd0aCkKYT1QLk9lKGEsMCxhPT1udWxsPzA6YS5sZW5ndGgs
+ITEpCnM9UC5sZShudWxsLDAsMCxlKQpyPVAudEcobnVsbCwwLDApCmQ9UC53QihkLGYpCnE9Zj09PSJm
+aWxlIgppZihhPT1udWxsKXA9Zy5sZW5ndGghPT0wfHxkIT1udWxsfHxxCmVsc2UgcD0hMQppZihwKWE9
+IiIKcD1hPT1udWxsCm89IXAKYj1QLmthKGIsMCxiPT1udWxsPzA6Yi5sZW5ndGgsYyxmLG8pCm49Zi5s
+ZW5ndGg9PT0wCmlmKG4mJnAmJiFDLnhCLm4oYiwiLyIpKWI9UC53RihiLCFufHxvKQplbHNlIGI9UC54
+ZShiKQpyZXR1cm4gbmV3IFAuRG4oZixnLHAmJkMueEIubihiLCIvLyIpPyIiOmEsZCxiLHMscil9LAp3
+SzpmdW5jdGlvbihhKXtpZihhPT09Imh0dHAiKXJldHVybiA4MAppZihhPT09Imh0dHBzIilyZXR1cm4g
+NDQzCnJldHVybiAwfSwKUjM6ZnVuY3Rpb24oYSxiLGMpe3Rocm93IEguYihQLnJyKGMsYSxiKSl9LApY
+ZDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGg9bnVsbCxnPWIubGVu
+Z3RoCmlmKGchPT0wKXtxPTAKd2hpbGUoITApe2lmKCEocTxnKSl7cz0iIgpyPTAKYnJlYWt9aWYoQy54
+Qi5XKGIscSk9PT02NCl7cz1DLnhCLk5qKGIsMCxxKQpyPXErMQpicmVha30rK3F9aWYocjxnJiZDLnhC
+LlcoYixyKT09PTkxKXtmb3IocD1yLG89LTE7cDxnOysrcCl7bj1DLnhCLlcoYixwKQppZihuPT09Mzcm
+Jm88MCl7bT1DLnhCLlFpKGIsIjI1IixwKzEpP3ArMjpwCm89cApwPW19ZWxzZSBpZihuPT09OTMpYnJl
+YWt9aWYocD09PWcpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgSVB2NiBob3N0IGVudHJ5LiIsYixyKSkK
+bD1vPDA/cDpvClAuZWcoYixyKzEsbCk7KytwCmlmKHAhPT1nJiZDLnhCLlcoYixwKSE9PTU4KXRocm93
+IEguYihQLnJyKCJJbnZhbGlkIGVuZCBvZiBhdXRob3JpdHkiLGIscCkpfWVsc2UgcD1yCndoaWxlKCEw
+KXtpZighKHA8Zykpe2s9aApicmVha31pZihDLnhCLlcoYixwKT09PTU4KXtqPUMueEIueW4oYixwKzEp
+Cms9ai5sZW5ndGghPT0wP1AuUUEoaixoKTpoCmJyZWFrfSsrcH1pPUMueEIuTmooYixyLHApfWVsc2V7
+az1oCmk9awpzPSIifXJldHVybiBQLktMKGksaCxILlZNKGMuc3BsaXQoIi8iKSx0LnMpLGssZCxhLHMp
+fSwKa0U6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvCmZvcihzPWEubGVuZ3RoLHI9MDtyPHM7Kyty
+KXtxPWFbcl0KcS50b1N0cmluZwpwPUouVTYocSkKbz1wLmdBKHEpCmlmKDA+bylILnYoUC5URSgwLDAs
+cC5nQShxKSxudWxsLG51bGwpKQppZihILlNRKHEsIi8iLDApKXtzPVAuTDQoIklsbGVnYWwgcGF0aCBj
+aGFyYWN0ZXIgIitILkVqKHEpKQp0aHJvdyBILmIocyl9fX0sCkhOOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+cyxyLHEKZm9yKHM9SC5xQyhhLGMsbnVsbCxILnQ2KGEpLmMpLHM9bmV3IEguYTcocyxzLmdBKHMpLHMu
+JHRpLkMoImE3PGFMLkU+IikpO3MuRigpOyl7cj1zLmQKcT1QLm51KCdbIiovOjw+P1xcXFx8XScpCnIu
+dG9TdHJpbmcKaWYoSC5TUShyLHEsMCkpe3M9UC5MNCgiSWxsZWdhbCBjaGFyYWN0ZXIgaW4gcGF0aDog
+IityKQp0aHJvdyBILmIocyl9fX0sCnJnOmZ1bmN0aW9uKGEsYil7dmFyIHMKaWYoISg2NTw9YSYmYTw9
+OTApKXM9OTc8PWEmJmE8PTEyMgplbHNlIHM9ITAKaWYocylyZXR1cm4Kcz1QLkw0KCJJbGxlZ2FsIGRy
+aXZlIGxldHRlciAiK1AuT28oYSkpCnRocm93IEguYihzKX0sCndCOmZ1bmN0aW9uKGEsYil7aWYoYSE9
+bnVsbCYmYT09PVAud0soYikpcmV0dXJuIG51bGwKcmV0dXJuIGF9LApPZTpmdW5jdGlvbihhLGIsYyxk
+KXt2YXIgcyxyLHEscCxvLG4KaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZihiPT09YylyZXR1cm4iIgpp
+ZihDLnhCLk8oYSxiKT09PTkxKXtzPWMtMQppZihDLnhCLk8oYSxzKSE9PTkzKXtQLlIzKGEsYiwiTWlz
+c2luZyBlbmQgYF1gIHRvIG1hdGNoIGBbYCBpbiBob3N0IikKSC5CaSh1LmcpfXI9YisxCnE9UC50byhh
+LHIscykKaWYocTxzKXtwPXErMQpvPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixwKT9xKzM6cCxzLCIlMjUi
+KX1lbHNlIG89IiIKUC5lZyhhLHIscSkKcmV0dXJuIEMueEIuTmooYSxiLHEpLnRvTG93ZXJDYXNlKCkr
+bysiXSJ9Zm9yKG49YjtuPGM7KytuKWlmKEMueEIuTyhhLG4pPT09NTgpe3E9Qy54Qi5YVShhLCIlIixi
+KQpxPXE+PWImJnE8Yz9xOmMKaWYocTxjKXtwPXErMQpvPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixwKT9x
+KzM6cCxjLCIlMjUiKX1lbHNlIG89IiIKUC5lZyhhLGIscSkKcmV0dXJuIlsiK0MueEIuTmooYSxiLHEp
+K28rIl0ifXJldHVybiBQLk9MKGEsYixjKX0sCnRvOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1DLnhCLlhV
+KGEsIiUiLGIpCnJldHVybiBzPj1iJiZzPGM/czpjfSwKT0E6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMs
+cixxLHAsbyxuLG0sbCxrLGosaT1kIT09IiI/bmV3IFAuUm4oZCk6bnVsbApmb3Iocz1iLHI9cyxxPSEw
+O3M8Yzspe3A9Qy54Qi5PKGEscykKaWYocD09PTM3KXtvPVAucnYoYSxzLCEwKQpuPW89PW51bGwKaWYo
+biYmcSl7cys9Mwpjb250aW51ZX1pZihpPT1udWxsKWk9bmV3IFAuUm4oIiIpCm09aS5hKz1DLnhCLk5q
+KGEscixzKQppZihuKW89Qy54Qi5OaihhLHMscyszKQplbHNlIGlmKG89PT0iJSIpe1AuUjMoYSxzLCJa
+b25lSUQgc2hvdWxkIG5vdCBjb250YWluICUgYW55bW9yZSIpCkguQmkodS5nKX1pLmE9bStvCnMrPTMK
+cj1zCnE9ITB9ZWxzZXtpZihwPDEyNyl7bj1wPj4+NAppZihuPj04KXJldHVybiBILk9IKEMuRjMsbikK
+bj0oQy5GM1tuXSYxPDwocCYxNSkpIT09MH1lbHNlIG49ITEKaWYobil7aWYocSYmNjU8PXAmJjkwPj1w
+KXtpZihpPT1udWxsKWk9bmV3IFAuUm4oIiIpCmlmKHI8cyl7aS5hKz1DLnhCLk5qKGEscixzKQpyPXN9
+cT0hMX0rK3N9ZWxzZXtpZigocCY2NDUxMik9PT01NTI5NiYmcysxPGMpe2w9Qy54Qi5PKGEscysxKQpp
+ZigobCY2NDUxMik9PT01NjMyMCl7cD0ocCYxMDIzKTw8MTB8bCYxMDIzfDY1NTM2Cms9Mn1lbHNlIGs9
+MX1lbHNlIGs9MQpqPUMueEIuTmooYSxyLHMpCmlmKGk9PW51bGwpe2k9bmV3IFAuUm4oIiIpCm49aX1l
+bHNlIG49aQpuLmErPWoKbi5hKz1QLnpYKHApCnMrPWsKcj1zfX19aWYoaT09bnVsbClyZXR1cm4gQy54
+Qi5OaihhLGIsYykKaWYocjxjKWkuYSs9Qy54Qi5OaihhLHIsYykKbj1pLmEKcmV0dXJuIG4uY2hhckNv
+ZGVBdCgwKT09MD9uOm59LApPTDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGos
+aQpmb3Iocz1iLHI9cyxxPW51bGwscD0hMDtzPGM7KXtvPUMueEIuTyhhLHMpCmlmKG89PT0zNyl7bj1Q
+LnJ2KGEscywhMCkKbT1uPT1udWxsCmlmKG0mJnApe3MrPTMKY29udGludWV9aWYocT09bnVsbClxPW5l
+dyBQLlJuKCIiKQpsPUMueEIuTmooYSxyLHMpCms9cS5hKz0hcD9sLnRvTG93ZXJDYXNlKCk6bAppZiht
+KXtuPUMueEIuTmooYSxzLHMrMykKaj0zfWVsc2UgaWYobj09PSIlIil7bj0iJTI1IgpqPTF9ZWxzZSBq
+PTMKcS5hPWsrbgpzKz1qCnI9cwpwPSEwfWVsc2V7aWYobzwxMjcpe209bz4+PjQKaWYobT49OClyZXR1
+cm4gSC5PSChDLmVhLG0pCm09KEMuZWFbbV0mMTw8KG8mMTUpKSE9PTB9ZWxzZSBtPSExCmlmKG0pe2lm
+KHAmJjY1PD1vJiY5MD49byl7aWYocT09bnVsbClxPW5ldyBQLlJuKCIiKQppZihyPHMpe3EuYSs9Qy54
+Qi5OaihhLHIscykKcj1zfXA9ITF9KytzfWVsc2V7aWYobzw9OTMpe209bz4+PjQKaWYobT49OClyZXR1
+cm4gSC5PSChDLmFrLG0pCm09KEMuYWtbbV0mMTw8KG8mMTUpKSE9PTB9ZWxzZSBtPSExCmlmKG0pe1Au
+UjMoYSxzLCJJbnZhbGlkIGNoYXJhY3RlciIpCkguQmkodS5nKX1lbHNle2lmKChvJjY0NTEyKT09PTU1
+Mjk2JiZzKzE8Yyl7aT1DLnhCLk8oYSxzKzEpCmlmKChpJjY0NTEyKT09PTU2MzIwKXtvPShvJjEwMjMp
+PDwxMHxpJjEwMjN8NjU1MzYKaj0yfWVsc2Ugaj0xfWVsc2Ugaj0xCmw9Qy54Qi5OaihhLHIscykKaWYo
+IXApbD1sLnRvTG93ZXJDYXNlKCkKaWYocT09bnVsbCl7cT1uZXcgUC5SbigiIikKbT1xfWVsc2UgbT1x
+Cm0uYSs9bAptLmErPVAuelgobykKcys9agpyPXN9fX19aWYocT09bnVsbClyZXR1cm4gQy54Qi5Oaihh
+LGIsYykKaWYocjxjKXtsPUMueEIuTmooYSxyLGMpCnEuYSs9IXA/bC50b0xvd2VyQ2FzZSgpOmx9bT1x
+LmEKcmV0dXJuIG0uY2hhckNvZGVBdCgwKT09MD9tOm19LApQaTpmdW5jdGlvbihhLGIsYyl7dmFyIHMs
+cixxLHAsbz11LmcKaWYoYj09PWMpcmV0dXJuIiIKaWYoIVAuRXQoSi5yWShhKS5XKGEsYikpKXtQLlIz
+KGEsYiwiU2NoZW1lIG5vdCBzdGFydGluZyB3aXRoIGFscGhhYmV0aWMgY2hhcmFjdGVyIikKSC5CaShv
+KX1mb3Iocz1iLHI9ITE7czxjOysrcyl7cT1DLnhCLlcoYSxzKQppZihxPDEyOCl7cD1xPj4+NAppZihw
+Pj04KXJldHVybiBILk9IKEMubUsscCkKcD0oQy5tS1twXSYxPDwocSYxNSkpIT09MH1lbHNlIHA9ITEK
+aWYoIXApe1AuUjMoYSxzLCJJbGxlZ2FsIHNjaGVtZSBjaGFyYWN0ZXIiKQpILkJpKG8pfWlmKDY1PD1x
+JiZxPD05MClyPSEwfWE9Qy54Qi5OaihhLGIsYykKcmV0dXJuIFAuWWEocj9hLnRvTG93ZXJDYXNlKCk6
+YSl9LApZYTpmdW5jdGlvbihhKXtpZihhPT09Imh0dHAiKXJldHVybiJodHRwIgppZihhPT09ImZpbGUi
+KXJldHVybiJmaWxlIgppZihhPT09Imh0dHBzIilyZXR1cm4iaHR0cHMiCmlmKGE9PT0icGFja2FnZSIp
+cmV0dXJuInBhY2thZ2UiCnJldHVybiBhfSwKelI6ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpcmV0
+dXJuIiIKcmV0dXJuIFAuUEkoYSxiLGMsQy50bywhMSl9LAprYTpmdW5jdGlvbihhLGIsYyxkLGUsZil7
+dmFyIHMscixxPWU9PT0iZmlsZSIscD1xfHxmCmlmKGE9PW51bGwpe2lmKGQ9PW51bGwpcmV0dXJuIHE/
+Ii8iOiIiCnM9SC50NihkKQpyPW5ldyBILmxKKGQscy5DKCJxVSgxKSIpLmEobmV3IFAuUlooKSkscy5D
+KCJsSjwxLHFVPiIpKS5rKDAsIi8iKX1lbHNlIGlmKGQhPW51bGwpdGhyb3cgSC5iKFAueFkoIkJvdGgg
+cGF0aCBhbmQgcGF0aFNlZ21lbnRzIHNwZWNpZmllZCIpKQplbHNlIHI9UC5QSShhLGIsYyxDLldkLCEw
+KQppZihyLmxlbmd0aD09PTApe2lmKHEpcmV0dXJuIi8ifWVsc2UgaWYocCYmIUMueEIubihyLCIvIikp
+cj0iLyIrcgpyZXR1cm4gUC5KcihyLGUsZil9LApKcjpmdW5jdGlvbihhLGIsYyl7dmFyIHM9Yi5sZW5n
+dGg9PT0wCmlmKHMmJiFjJiYhQy54Qi5uKGEsIi8iKSlyZXR1cm4gUC53RihhLCFzfHxjKQpyZXR1cm4g
+UC54ZShhKX0sCmxlOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHI9e30KaWYoYSE9bnVsbCl7aWYoZCE9
+bnVsbCl0aHJvdyBILmIoUC54WSgiQm90aCBxdWVyeSBhbmQgcXVlcnlQYXJhbWV0ZXJzIHNwZWNpZmll
+ZCIpKQpyZXR1cm4gUC5QSShhLGIsYyxDLlZDLCEwKX1pZihkPT1udWxsKXJldHVybiBudWxsCnM9bmV3
+IFAuUm4oIiIpCnIuYT0iIgpkLksoMCxuZXcgUC55NShuZXcgUC5NRShyLHMpKSkKcj1zLmEKcmV0dXJu
+IHIuY2hhckNvZGVBdCgwKT09MD9yOnJ9LAp0RzpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1
+cm4gbnVsbApyZXR1cm4gUC5QSShhLGIsYyxDLlZDLCEwKX0sCnJ2OmZ1bmN0aW9uKGEsYixjKXt2YXIg
+cyxyLHEscCxvLG49YisyCmlmKG4+PWEubGVuZ3RoKXJldHVybiIlIgpzPUMueEIuTyhhLGIrMSkKcj1D
+LnhCLk8oYSxuKQpxPUgub28ocykKcD1ILm9vKHIpCmlmKHE8MHx8cDwwKXJldHVybiIlIgpvPXEqMTYr
+cAppZihvPDEyNyl7bj1DLmpuLndHKG8sNCkKaWYobj49OClyZXR1cm4gSC5PSChDLkYzLG4pCm49KEMu
+RjNbbl0mMTw8KG8mMTUpKSE9PTB9ZWxzZSBuPSExCmlmKG4pcmV0dXJuIEguTHcoYyYmNjU8PW8mJjkw
+Pj1vPyhvfDMyKT4+PjA6bykKaWYocz49OTd8fHI+PTk3KXJldHVybiBDLnhCLk5qKGEsYixiKzMpLnRv
+VXBwZXJDYXNlKCkKcmV0dXJuIG51bGx9LAp6WDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxs
+LGs9IjAxMjM0NTY3ODlBQkNERUYiCmlmKGE8MTI4KXtzPW5ldyBVaW50OEFycmF5KDMpCnNbMF09MzcK
+c1sxXT1DLnhCLlcoayxhPj4+NCkKc1syXT1DLnhCLlcoayxhJjE1KX1lbHNle2lmKGE+MjA0NylpZihh
+PjY1NTM1KXtyPTI0MApxPTR9ZWxzZXtyPTIyNApxPTN9ZWxzZXtyPTE5MgpxPTJ9cD0zKnEKcz1uZXcg
+VWludDhBcnJheShwKQpmb3Iobz0wOy0tcSxxPj0wO3I9MTI4KXtuPUMuam4uYmYoYSw2KnEpJjYzfHIK
+aWYobz49cClyZXR1cm4gSC5PSChzLG8pCnNbb109MzcKbT1vKzEKbD1DLnhCLlcoayxuPj4+NCkKaWYo
+bT49cClyZXR1cm4gSC5PSChzLG0pCnNbbV09bApsPW8rMgptPUMueEIuVyhrLG4mMTUpCmlmKGw+PXAp
+cmV0dXJuIEguT0gocyxsKQpzW2xdPW0Kbys9M319cmV0dXJuIFAuSE0ocywwLG51bGwpfSwKUEk6ZnVu
+Y3Rpb24oYSxiLGMsZCxlKXt2YXIgcz1QLlVsKGEsYixjLGQsZSkKcmV0dXJuIHM9PW51bGw/Qy54Qi5O
+aihhLGIsYyk6c30sClVsOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGo9
+bnVsbApmb3Iocz0hZSxyPWIscT1yLHA9ajtyPGM7KXtvPUMueEIuTyhhLHIpCmlmKG88MTI3KXtuPW8+
+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goZCxuKQpuPShkW25dJjE8PChvJjE1KSkhPT0wfWVsc2Ugbj0h
+MQppZihuKSsrcgplbHNle2lmKG89PT0zNyl7bT1QLnJ2KGEsciwhMSkKaWYobT09bnVsbCl7cis9Mwpj
+b250aW51ZX1pZigiJSI9PT1tKXttPSIlMjUiCmw9MX1lbHNlIGw9M31lbHNle2lmKHMpaWYobzw9OTMp
+e249bz4+PjQKaWYobj49OClyZXR1cm4gSC5PSChDLmFrLG4pCm49KEMuYWtbbl0mMTw8KG8mMTUpKSE9
+PTB9ZWxzZSBuPSExCmVsc2Ugbj0hMQppZihuKXtQLlIzKGEsciwiSW52YWxpZCBjaGFyYWN0ZXIiKQpI
+LkJpKHUuZykKbD1qCm09bH1lbHNle2lmKChvJjY0NTEyKT09PTU1Mjk2KXtuPXIrMQppZihuPGMpe2s9
+Qy54Qi5PKGEsbikKaWYoKGsmNjQ1MTIpPT09NTYzMjApe289KG8mMTAyMyk8PDEwfGsmMTAyM3w2NTUz
+NgpsPTJ9ZWxzZSBsPTF9ZWxzZSBsPTF9ZWxzZSBsPTEKbT1QLnpYKG8pfX1pZihwPT1udWxsKXtwPW5l
+dyBQLlJuKCIiKQpuPXB9ZWxzZSBuPXAKbi5hKz1DLnhCLk5qKGEscSxyKQpuLmErPUguRWoobSkKaWYo
+dHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShsKQpyKz1sCnE9cn19aWYocD09bnVsbClyZXR1
+cm4gagppZihxPGMpcC5hKz1DLnhCLk5qKGEscSxjKQpzPXAuYQpyZXR1cm4gcy5jaGFyQ29kZUF0KDAp
+PT0wP3M6c30sCnlCOmZ1bmN0aW9uKGEpe2lmKEMueEIubihhLCIuIikpcmV0dXJuITAKcmV0dXJuIEMu
+eEIuT1koYSwiLy4iKSE9PS0xfSwKeGU6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0KaWYoIVAu
+eUIoYSkpcmV0dXJuIGEKcz1ILlZNKFtdLHQucykKZm9yKHI9YS5zcGxpdCgiLyIpLHE9ci5sZW5ndGgs
+cD0hMSxvPTA7bzxxOysrbyl7bj1yW29dCmlmKEouUk0obiwiLi4iKSl7bT1zLmxlbmd0aAppZihtIT09
+MCl7aWYoMD49bSlyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCmlmKHMubGVuZ3RoPT09MClDLk5tLmko
+cywiIil9cD0hMH1lbHNlIGlmKCIuIj09PW4pcD0hMAplbHNle0MuTm0uaShzLG4pCnA9ITF9fWlmKHAp
+Qy5ObS5pKHMsIiIpCnJldHVybiBDLk5tLmsocywiLyIpfSwKd0Y6ZnVuY3Rpb24oYSxiKXt2YXIgcyxy
+LHEscCxvLG4KaWYoIVAueUIoYSkpcmV0dXJuIWI/UC5DMShhKTphCnM9SC5WTShbXSx0LnMpCmZvcihy
+PWEuc3BsaXQoIi8iKSxxPXIubGVuZ3RoLHA9ITEsbz0wO288cTsrK28pe249cltvXQppZigiLi4iPT09
+bilpZihzLmxlbmd0aCE9PTAmJkMuTm0uZ3JaKHMpIT09Ii4uIil7aWYoMD49cy5sZW5ndGgpcmV0dXJu
+IEguT0gocywtMSkKcy5wb3AoKQpwPSEwfWVsc2V7Qy5ObS5pKHMsIi4uIikKcD0hMX1lbHNlIGlmKCIu
+Ij09PW4pcD0hMAplbHNle0MuTm0uaShzLG4pCnA9ITF9fXI9cy5sZW5ndGgKaWYociE9PTApaWYocj09
+PTEpe2lmKDA+PXIpcmV0dXJuIEguT0gocywwKQpyPXNbMF0ubGVuZ3RoPT09MH1lbHNlIHI9ITEKZWxz
+ZSByPSEwCmlmKHIpcmV0dXJuIi4vIgppZihwfHxDLk5tLmdyWihzKT09PSIuLiIpQy5ObS5pKHMsIiIp
+CmlmKCFiKXtpZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLDApCkMuTm0uWTUocywwLFAuQzEoc1sw
+XSkpfXJldHVybiBDLk5tLmsocywiLyIpfSwKQzE6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9YS5sZW5n
+dGgKaWYocD49MiYmUC5FdChKLlF6KGEsMCkpKWZvcihzPTE7czxwOysrcyl7cj1DLnhCLlcoYSxzKQpp
+ZihyPT09NTgpcmV0dXJuIEMueEIuTmooYSwwLHMpKyIlM0EiK0MueEIueW4oYSxzKzEpCmlmKHI8PTEy
+Nyl7cT1yPj4+NAppZihxPj04KXJldHVybiBILk9IKEMubUsscSkKcT0oQy5tS1txXSYxPDwociYxNSkp
+PT09MH1lbHNlIHE9ITAKaWYocSlicmVha31yZXR1cm4gYX0sCm1uOmZ1bmN0aW9uKGEpe3ZhciBzLHIs
+cSxwPWEuZ0ZqKCksbz1wLmxlbmd0aAppZihvPjAmJkouSG0ocFswXSk9PT0yJiZKLmE2KHBbMF0sMSk9
+PT01OCl7aWYoMD49bylyZXR1cm4gSC5PSChwLDApClAucmcoSi5hNihwWzBdLDApLCExKQpQLkhOKHAs
+ITEsMSkKcz0hMH1lbHNle1AuSE4ocCwhMSwwKQpzPSExfXI9YS5ndFQoKSYmIXM/IlxcIjoiIgppZihh
+LmdjaigpKXtxPWEuZ0pmKGEpCmlmKHEubGVuZ3RoIT09MClyPXIrIlxcIitxKyJcXCJ9cj1QLnZnKHIs
+cCwiXFwiKQpvPXMmJm89PT0xP3IrIlxcIjpyCnJldHVybiBvLmNoYXJDb2RlQXQoMCk9PTA/bzpvfSwK
+SWg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEKZm9yKHM9MCxyPTA7cjwyOysrcil7cT1DLnhCLlcoYSxi
+K3IpCmlmKDQ4PD1xJiZxPD01NylzPXMqMTYrcS00OAplbHNle3F8PTMyCmlmKDk3PD1xJiZxPD0xMDIp
+cz1zKjE2K3EtODcKZWxzZSB0aHJvdyBILmIoUC54WSgiSW52YWxpZCBVUkwgZW5jb2RpbmciKSl9fXJl
+dHVybiBzfSwKa3U6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvPUouclkoYSksbj1iCndo
+aWxlKCEwKXtpZighKG48Yykpe3M9ITAKYnJlYWt9cj1vLlcoYSxuKQppZihyPD0xMjcpaWYociE9PTM3
+KXE9ZSYmcj09PTQzCmVsc2UgcT0hMAplbHNlIHE9ITAKaWYocSl7cz0hMQpicmVha30rK259aWYocyl7
+aWYoQy54TSE9PWQpcT0hMQplbHNlIHE9ITAKaWYocSlyZXR1cm4gby5OaihhLGIsYykKZWxzZSBwPW5l
+dyBILnFqKG8uTmooYSxiLGMpKX1lbHNle3A9SC5WTShbXSx0LmEpCmZvcihuPWI7bjxjOysrbil7cj1v
+LlcoYSxuKQppZihyPjEyNyl0aHJvdyBILmIoUC54WSgiSWxsZWdhbCBwZXJjZW50IGVuY29kaW5nIGlu
+IFVSSSIpKQppZihyPT09Mzcpe2lmKG4rMz5hLmxlbmd0aCl0aHJvdyBILmIoUC54WSgiVHJ1bmNhdGVk
+IFVSSSIpKQpDLk5tLmkocCxQLkloKGEsbisxKSkKbis9Mn1lbHNlIGlmKGUmJnI9PT00MylDLk5tLmko
+cCwzMikKZWxzZSBDLk5tLmkocCxyKX19dC5MLmEocCkKcmV0dXJuIEMub0UuV0oocCl9LApFdDpmdW5j
+dGlvbihhKXt2YXIgcz1hfDMyCnJldHVybiA5Nzw9cyYmczw9MTIyfSwKS0Q6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciBzLHIscSxwLG8sbixtLGwsaz0iSW52YWxpZCBNSU1FIHR5cGUiLGo9SC5WTShbYi0xXSx0LmEp
+CmZvcihzPWEubGVuZ3RoLHI9YixxPS0xLHA9bnVsbDtyPHM7KytyKXtwPUMueEIuVyhhLHIpCmlmKHA9
+PT00NHx8cD09PTU5KWJyZWFrCmlmKHA9PT00Nyl7aWYocTwwKXtxPXIKY29udGludWV9dGhyb3cgSC5i
+KFAucnIoayxhLHIpKX19aWYocTwwJiZyPmIpdGhyb3cgSC5iKFAucnIoayxhLHIpKQpmb3IoO3AhPT00
+NDspe0MuTm0uaShqLHIpOysrcgpmb3Iobz0tMTtyPHM7KytyKXtwPUMueEIuVyhhLHIpCmlmKHA9PT02
+MSl7aWYobzwwKW89cn1lbHNlIGlmKHA9PT01OXx8cD09PTQ0KWJyZWFrfWlmKG8+PTApQy5ObS5pKGos
+bykKZWxzZXtuPUMuTm0uZ3JaKGopCmlmKHAhPT00NHx8ciE9PW4rN3x8IUMueEIuUWkoYSwiYmFzZTY0
+IixuKzEpKXRocm93IEguYihQLnJyKCJFeHBlY3RpbmcgJz0nIixhLHIpKQpicmVha319Qy5ObS5pKGos
+cikKbT1yKzEKaWYoKGoubGVuZ3RoJjEpPT09MSlhPUMuaDkueXIoYSxtLHMpCmVsc2V7bD1QLlVsKGEs
+bSxzLEMuVkMsITApCmlmKGwhPW51bGwpYT1DLnhCLmk3KGEsbSxzLGwpfXJldHVybiBuZXcgUC5QRShh
+LGosYyl9LApLTjpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixtPSIwMTIzNDU2Nzg5QUJDREVGR0hJ
+SktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ei0uX34hJCYnKCkqKyw7PSIs
+bD0iLiIsaz0iOiIsaj0iLyIsaT0iPyIsaD0iIyIsZz1ILlZNKG5ldyBBcnJheSgyMiksdC5nTikKZm9y
+KHM9MDtzPDIyOysrcylnW3NdPW5ldyBVaW50OEFycmF5KDk2KQpyPW5ldyBQLnlJKGcpCnE9bmV3IFAu
+YzYoKQpwPW5ldyBQLnFkKCkKbz10LmdjCm49by5hKHIuJDIoMCwyMjUpKQpxLiQzKG4sbSwxKQpxLiQz
+KG4sbCwxNCkKcS4kMyhuLGssMzQpCnEuJDMobixqLDMpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1
+KQpuPW8uYShyLiQyKDE0LDIyNSkpCnEuJDMobixtLDEpCnEuJDMobixsLDE1KQpxLiQzKG4saywzNCkK
+cS4kMyhuLGosMjM0KQpxLiQzKG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMigxNSwyMjUp
+KQpxLiQzKG4sbSwxKQpxLiQzKG4sIiUiLDIyNSkKcS4kMyhuLGssMzQpCnEuJDMobixqLDkpCnEuJDMo
+bixpLDE3MikKcS4kMyhuLGgsMjA1KQpuPW8uYShyLiQyKDEsMjI1KSkKcS4kMyhuLG0sMSkKcS4kMyhu
+LGssMzQpCnEuJDMobixqLDEwKQpxLiQzKG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMigy
+LDIzNSkpCnEuJDMobixtLDEzOSkKcS4kMyhuLGosMTMxKQpxLiQzKG4sbCwxNDYpCnEuJDMobixpLDE3
+MikKcS4kMyhuLGgsMjA1KQpuPW8uYShyLiQyKDMsMjM1KSkKcS4kMyhuLG0sMTEpCnEuJDMobixqLDY4
+KQpxLiQzKG4sbCwxOCkKcS4kMyhuLGksMTcyKQpxLiQzKG4saCwyMDUpCm49by5hKHIuJDIoNCwyMjkp
+KQpxLiQzKG4sbSw1KQpwLiQzKG4sIkFaIiwyMjkpCnEuJDMobixrLDEwMikKcS4kMyhuLCJAIiw2OCkK
+cS4kMyhuLCJbIiwyMzIpCnEuJDMobixqLDEzOCkKcS4kMyhuLGksMTcyKQpxLiQzKG4saCwyMDUpCm49
+by5hKHIuJDIoNSwyMjkpKQpxLiQzKG4sbSw1KQpwLiQzKG4sIkFaIiwyMjkpCnEuJDMobixrLDEwMikK
+cS4kMyhuLCJAIiw2OCkKcS4kMyhuLGosMTM4KQpxLiQzKG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1v
+LmEoci4kMig2LDIzMSkpCnAuJDMobiwiMTkiLDcpCnEuJDMobiwiQCIsNjgpCnEuJDMobixqLDEzOCkK
+cS4kMyhuLGksMTcyKQpxLiQzKG4saCwyMDUpCm49by5hKHIuJDIoNywyMzEpKQpwLiQzKG4sIjA5Iiw3
+KQpxLiQzKG4sIkAiLDY4KQpxLiQzKG4saiwxMzgpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpx
+LiQzKG8uYShyLiQyKDgsOCkpLCJdIiw1KQpuPW8uYShyLiQyKDksMjM1KSkKcS4kMyhuLG0sMTEpCnEu
+JDMobixsLDE2KQpxLiQzKG4saiwyMzQpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpuPW8uYShy
+LiQyKDE2LDIzNSkpCnEuJDMobixtLDExKQpxLiQzKG4sbCwxNykKcS4kMyhuLGosMjM0KQpxLiQzKG4s
+aSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMigxNywyMzUpKQpxLiQzKG4sbSwxMSkKcS4kMyhu
+LGosOSkKcS4kMyhuLGksMTcyKQpxLiQzKG4saCwyMDUpCm49by5hKHIuJDIoMTAsMjM1KSkKcS4kMyhu
+LG0sMTEpCnEuJDMobixsLDE4KQpxLiQzKG4saiwyMzQpCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1
+KQpuPW8uYShyLiQyKDE4LDIzNSkpCnEuJDMobixtLDExKQpxLiQzKG4sbCwxOSkKcS4kMyhuLGosMjM0
+KQpxLiQzKG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMigxOSwyMzUpKQpxLiQzKG4sbSwx
+MSkKcS4kMyhuLGosMjM0KQpxLiQzKG4saSwxNzIpCnEuJDMobixoLDIwNSkKbj1vLmEoci4kMigxMSwy
+MzUpKQpxLiQzKG4sbSwxMSkKcS4kMyhuLGosMTApCnEuJDMobixpLDE3MikKcS4kMyhuLGgsMjA1KQpu
+PW8uYShyLiQyKDEyLDIzNikpCnEuJDMobixtLDEyKQpxLiQzKG4saSwxMikKcS4kMyhuLGgsMjA1KQpu
+PW8uYShyLiQyKDEzLDIzNykpCnEuJDMobixtLDEzKQpxLiQzKG4saSwxMykKcC4kMyhvLmEoci4kMigy
+MCwyNDUpKSwiYXoiLDIxKQpyPW8uYShyLiQyKDIxLDI0NSkpCnAuJDMociwiYXoiLDIxKQpwLiQzKHIs
+IjA5IiwyMSkKcS4kMyhyLCIrLS4iLDIxKQpyZXR1cm4gZ30sClVCOmZ1bmN0aW9uKGEsYixjLGQsZSl7
+dmFyIHMscixxLHAsbyxuPSQudlooKQpmb3Iocz1KLnJZKGEpLHI9YjtyPGM7KytyKXtpZihkPDB8fGQ+
+PW4ubGVuZ3RoKXJldHVybiBILk9IKG4sZCkKcT1uW2RdCnA9cy5XKGEscileOTYKbz1xW3A+OTU/MzE6
+cF0KZD1vJjMxCkMuTm0uWTUoZSxvPj4+NSxyKX1yZXR1cm4gZH0sCldGOmZ1bmN0aW9uIFdGKGEsYil7
+dGhpcy5hPWEKdGhpcy5iPWJ9LAppUDpmdW5jdGlvbiBpUChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwK
+WFM6ZnVuY3Rpb24gWFMoKXt9LApDNjpmdW5jdGlvbiBDNihhKXt0aGlzLmE9YX0sCkV6OmZ1bmN0aW9u
+IEV6KCl7fSwKRjpmdW5jdGlvbiBGKCl7fSwKdTpmdW5jdGlvbiB1KGEsYixjLGQpe3ZhciBfPXRoaXMK
+Xy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LApiSjpmdW5jdGlvbiBiSihhLGIsYyxkLGUsZil7dmFyIF89
+dGhpcwpfLmU9YQpfLmY9YgpfLmE9YwpfLmI9ZApfLmM9ZQpfLmQ9Zn0sCmVZOmZ1bmN0aW9uIGVZKGEs
+YixjLGQsZSl7dmFyIF89dGhpcwpfLmY9YQpfLmE9YgpfLmI9YwpfLmM9ZApfLmQ9ZX0sCm1wOmZ1bmN0
+aW9uIG1wKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LAp1YjpmdW5j
+dGlvbiB1YihhKXt0aGlzLmE9YX0sCmRzOmZ1bmN0aW9uIGRzKGEpe3RoaXMuYT1hfSwKbGo6ZnVuY3Rp
+b24gbGooYSl7dGhpcy5hPWF9LApVVjpmdW5jdGlvbiBVVihhKXt0aGlzLmE9YX0sCms1OmZ1bmN0aW9u
+IGs1KCl7fSwKS1k6ZnVuY3Rpb24gS1koKXt9LApjOmZ1bmN0aW9uIGMoYSl7dGhpcy5hPWF9LApDRDpm
+dW5jdGlvbiBDRChhKXt0aGlzLmE9YX0sCmFFOmZ1bmN0aW9uIGFFKGEsYixjKXt0aGlzLmE9YQp0aGlz
+LmI9Ygp0aGlzLmM9Y30sCmNYOmZ1bmN0aW9uIGNYKCl7fSwKQW46ZnVuY3Rpb24gQW4oKXt9LApOMzpm
+dW5jdGlvbiBOMyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCmM4OmZ1bmN0aW9u
+IGM4KCl7fSwKTWg6ZnVuY3Rpb24gTWgoKXt9LApaZDpmdW5jdGlvbiBaZCgpe30sClJuOmZ1bmN0aW9u
+IFJuKGEpe3RoaXMuYT1hfSwKbjE6ZnVuY3Rpb24gbjEoYSl7dGhpcy5hPWF9LApjUzpmdW5jdGlvbiBj
+UyhhKXt0aGlzLmE9YX0sClZDOmZ1bmN0aW9uIFZDKGEpe3RoaXMuYT1hfSwKSlQ6ZnVuY3Rpb24gSlQo
+YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkRuOmZ1bmN0aW9uIERuKGEsYixjLGQsZSxmLGcpe3ZhciBf
+PXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5yPWcKXy54PW51bGwKXy55
+PSExCl8uej1udWxsCl8uUT0hMQpfLmNoPW51bGwKXy5jeD0hMQpfLmN5PW51bGwKXy5kYj0hMX0sClJa
+OmZ1bmN0aW9uIFJaKCl7fSwKTUU6ZnVuY3Rpb24gTUUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnk1
+OmZ1bmN0aW9uIHk1KGEpe3RoaXMuYT1hfSwKUEU6ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMuYT1hCnRo
+aXMuYj1iCnRoaXMuYz1jfSwKeUk6ZnVuY3Rpb24geUkoYSl7dGhpcy5hPWF9LApjNjpmdW5jdGlvbiBj
+Nigpe30sCnFkOmZ1bmN0aW9uIHFkKCl7fSwKVWY6ZnVuY3Rpb24gVWYoYSxiLGMsZCxlLGYsZyxoKXt2
+YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8ueD1oCl8u
+eT1udWxsfSwKcWU6ZnVuY3Rpb24gcWUoYSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9
+YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9ZgpfLnI9ZwpfLng9bnVsbApfLnk9ITEKXy56PW51bGwKXy5R
+PSExCl8uY2g9bnVsbApfLmN4PSExCl8uY3k9bnVsbApfLmRiPSExfSwKaUo6ZnVuY3Rpb24gaUooKXt9
+LApqZzpmdW5jdGlvbiBqZyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVGE6ZnVuY3Rpb24gVGEoYSxi
+KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9
+LApBczpmdW5jdGlvbiBBcygpe30sCkdFOmZ1bmN0aW9uIEdFKGEpe3RoaXMuYT1hfSwKTjc6ZnVuY3Rp
+b24gTjcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnVROmZ1bmN0aW9uIHVRKCl7fSwKaEY6ZnVuY3Rp
+b24gaEYoKXt9LApSNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEKSC55OChiKQp0LmouYShkKQpp
+ZihILm9UKGIpKXtzPVtjXQpDLk5tLkZWKHMsZCkKZD1zfXI9dC56CnE9UC5DSChKLk0xKGQsUC53MCgp
+LHIpLCEwLHIpCnQuWS5hKGEpCnJldHVybiBQLndZKEguRWsoYSxxLG51bGwpKX0sCkRtOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgcwp0cnl7aWYoT2JqZWN0LmlzRXh0ZW5zaWJsZShhKSYmIU9iamVjdC5wcm90b3R5
+cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1
+ZTpjfSkKcmV0dXJuITB9fWNhdGNoKHMpe0guUnUocyl9cmV0dXJuITF9LApPbTpmdW5jdGlvbihhLGIp
+e2lmKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXJldHVybiBhW2JdCnJl
+dHVybiBudWxsfSwKd1k6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0
+eXBlb2YgYT09Im51bWJlciJ8fEgubChhKSlyZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5FNClyZXR1
+cm4gYS5hCmlmKEguUjkoYSkpcmV0dXJuIGEKaWYodC5hay5iKGEpKXJldHVybiBhCmlmKGEgaW5zdGFu
+Y2VvZiBQLmlQKXJldHVybiBILm8yKGEpCmlmKHQuWS5iKGEpKXJldHVybiBQLmhFKGEsIiRkYXJ0X2pz
+RnVuY3Rpb24iLG5ldyBQLlBDKCkpCnJldHVybiBQLmhFKGEsIl8kZGFydF9qc09iamVjdCIsbmV3IFAu
+bXQoJC5rSSgpKSl9LApoRTpmdW5jdGlvbihhLGIsYyl7dmFyIHM9UC5PbShhLGIpCmlmKHM9PW51bGwp
+e3M9Yy4kMShhKQpQLkRtKGEsYixzKX1yZXR1cm4gc30sCmRVOmZ1bmN0aW9uKGEpe3ZhciBzLHIKaWYo
+YT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8fHR5cGVvZiBhPT0i
+Ym9vbGVhbiIpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2YgT2JqZWN0JiZILlI5KGEpKXJldHVy
+biBhCmVsc2UgaWYoYSBpbnN0YW5jZW9mIE9iamVjdCYmdC5hay5iKGEpKXJldHVybiBhCmVsc2UgaWYo
+YSBpbnN0YW5jZW9mIERhdGUpe3M9SC51UChhLmdldFRpbWUoKSkKaWYoTWF0aC5hYnMocyk8PTg2NGUx
+MylyPSExCmVsc2Ugcj0hMAppZihyKUgudihQLnhZKCJEYXRlVGltZSBpcyBvdXRzaWRlIHZhbGlkIHJh
+bmdlOiAiK3MpKQpILmNiKCExLCJpc1V0YyIsdC55KQpyZXR1cm4gbmV3IFAuaVAocywhMSl9ZWxzZSBp
+ZihhLmNvbnN0cnVjdG9yPT09JC5rSSgpKXJldHVybiBhLm8KZWxzZSByZXR1cm4gUC5ORChhKX0sCk5E
+OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBQLmlRKGEsJC53KCksbmV3
+IFAuUVMoKSkKaWYoYSBpbnN0YW5jZW9mIEFycmF5KXJldHVybiBQLmlRKGEsJC5SOCgpLG5ldyBQLm5w
+KCkpCnJldHVybiBQLmlRKGEsJC5SOCgpLG5ldyBQLlV0KCkpfSwKaVE6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciBzPVAuT20oYSxiKQppZihzPT1udWxsfHwhKGEgaW5zdGFuY2VvZiBPYmplY3QpKXtzPWMuJDEoYSkK
+UC5EbShhLGIscyl9cmV0dXJuIHN9LApQQzpmdW5jdGlvbiBQQygpe30sCm10OmZ1bmN0aW9uIG10KGEp
+e3RoaXMuYT1hfSwKUVM6ZnVuY3Rpb24gUVMoKXt9LApucDpmdW5jdGlvbiBucCgpe30sClV0OmZ1bmN0
+aW9uIFV0KCl7fSwKRTQ6ZnVuY3Rpb24gRTQoYSl7dGhpcy5hPWF9LApyNzpmdW5jdGlvbiByNyhhKXt0
+aGlzLmE9YX0sClR6OmZ1bmN0aW9uIFR6KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmNvOmZ1bmN0
+aW9uIGNvKCl7fSwKbmQ6ZnVuY3Rpb24gbmQoKXt9LApLZTpmdW5jdGlvbiBLZShhKXt0aGlzLmE9YX0s
+CmhpOmZ1bmN0aW9uIGhpKCl7fX0sVz17CngzOmZ1bmN0aW9uKCl7cmV0dXJuIHdpbmRvd30sClpyOmZ1
+bmN0aW9uKCl7cmV0dXJuIGRvY3VtZW50fSwKSjY6ZnVuY3Rpb24oYSl7dmFyIHM9ZG9jdW1lbnQuY3Jl
+YXRlRWxlbWVudCgiYSIpCmlmKGEhPW51bGwpQy54bi5zTFUocyxhKQpyZXR1cm4gc30sClU5OmZ1bmN0
+aW9uKGEsYixjKXt2YXIgcyxyPWRvY3VtZW50LmJvZHkKci50b1N0cmluZwpzPUMuUlkucjYocixhLGIs
+YykKcy50b1N0cmluZwpyPXQuYWMKcj1uZXcgSC5VNShuZXcgVy5lNyhzKSxyLkMoImEyKGxELkUpIiku
+YShuZXcgVy5DdigpKSxyLkMoIlU1PGxELkU+IikpCnJldHVybiB0LmguYShyLmdyOChyKSl9LApyUzpm
+dW5jdGlvbihhKXt2YXIgcyxyLHE9ImVsZW1lbnQgdGFnIHVuYXZhaWxhYmxlIgp0cnl7cz1KLllFKGEp
+CmlmKHR5cGVvZiBzLmducyhhKT09InN0cmluZyIpcT1zLmducyhhKX1jYXRjaChyKXtILlJ1KHIpfXJl
+dHVybiBxfSwKQzA6ZnVuY3Rpb24oYSxiKXthPWErYiY1MzY4NzA5MTEKYT1hKygoYSY1MjQyODcpPDwx
+MCkmNTM2ODcwOTExCnJldHVybiBhXmE+Pj42fSwKckU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHM9Vy5D
+MChXLkMwKFcuQzAoVy5DMCgwLGEpLGIpLGMpLGQpLHI9cysoKHMmNjcxMDg4NjMpPDwzKSY1MzY4NzA5
+MTEKcl49cj4+PjExCnJldHVybiByKygociYxNjM4Myk8PDE1KSY1MzY4NzA5MTF9LApUTjpmdW5jdGlv
+bihhLGIpe3ZhciBzLHIscT1hLmNsYXNzTGlzdApmb3Iocz1iLmxlbmd0aCxyPTA7cjxiLmxlbmd0aDti
+Lmxlbmd0aD09PXN8fCgwLEgubGspKGIpLCsrcilxLmFkZChiW3JdKX0sCkpFOmZ1bmN0aW9uKGEsYixj
+LGQsZSl7dmFyIHM9Vy5hRihuZXcgVy52TihjKSx0LkIpCmlmKHMhPW51bGwmJiEwKUouZFooYSxiLHMs
+ITEpCnJldHVybiBuZXcgVy54QyhhLGIscywhMSxlLkMoInhDPDA+IikpfSwKVHc6ZnVuY3Rpb24oYSl7
+dmFyIHM9Vy5KNihudWxsKSxyPXdpbmRvdy5sb2NhdGlvbgpzPW5ldyBXLkpRKG5ldyBXLm1rKHMscikp
+CnMuQ1koYSkKcmV0dXJuIHN9LApxRDpmdW5jdGlvbihhLGIsYyxkKXt0LmguYShhKQpILmgoYikKSC5o
+KGMpCnQuY3IuYShkKQpyZXR1cm4hMH0sClFXOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscQp0Lmgu
+YShhKQpILmgoYikKSC5oKGMpCnM9dC5jci5hKGQpLmEKcj1zLmEKQy54bi5zTFUocixjKQpxPXIuaG9z
+dG5hbWUKcz1zLmIKaWYoIShxPT1zLmhvc3RuYW1lJiZyLnBvcnQ9PXMucG9ydCYmci5wcm90b2NvbD09
+cy5wcm90b2NvbCkpaWYocT09PSIiKWlmKHIucG9ydD09PSIiKXtzPXIucHJvdG9jb2wKcz1zPT09Ijoi
+fHxzPT09IiJ9ZWxzZSBzPSExCmVsc2Ugcz0hMQplbHNlIHM9ITAKcmV0dXJuIHN9LApCbDpmdW5jdGlv
+bigpe3ZhciBzPXQuTixyPVAudE0oQy5ReCxzKSxxPXQuZDAuYShuZXcgVy5JQSgpKSxwPUguVk0oWyJU
+RU1QTEFURSJdLHQucykKcz1uZXcgVy5jdChyLFAuTHMocyksUC5McyhzKSxQLkxzKHMpLG51bGwpCnMu
+Q1kobnVsbCxuZXcgSC5sSihDLlF4LHEsdC5maikscCxudWxsKQpyZXR1cm4gc30sCnFjOmZ1bmN0aW9u
+KGEpe3ZhciBzCmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYoInBvc3RNZXNzYWdlIiBpbiBhKXtzPVcu
+UDEoYSkKaWYodC5hUy5iKHMpKXJldHVybiBzCnJldHVybiBudWxsfWVsc2UgcmV0dXJuIHQuY2guYShh
+KX0sClAxOmZ1bmN0aW9uKGEpe2lmKGE9PT13aW5kb3cpcmV0dXJuIHQuY2kuYShhKQplbHNlIHJldHVy
+biBuZXcgVy5kVygpfSwKYUY6ZnVuY3Rpb24oYSxiKXt2YXIgcz0kLlgzCmlmKHM9PT1DLk5VKXJldHVy
+biBhCnJldHVybiBzLlB5KGEsYil9LApxRTpmdW5jdGlvbiBxRSgpe30sCkdoOmZ1bmN0aW9uIEdoKCl7
+fSwKZlk6ZnVuY3Rpb24gZlkoKXt9LApuQjpmdW5jdGlvbiBuQigpe30sCkF6OmZ1bmN0aW9uIEF6KCl7
+fSwKUVA6ZnVuY3Rpb24gUVAoKXt9LApueDpmdW5jdGlvbiBueCgpe30sCm9KOmZ1bmN0aW9uIG9KKCl7
+fSwKaWQ6ZnVuY3Rpb24gaWQoKXt9LApRRjpmdW5jdGlvbiBRRigpe30sCk5oOmZ1bmN0aW9uIE5oKCl7
+fSwKYWU6ZnVuY3Rpb24gYWUoKXt9LApJQjpmdW5jdGlvbiBJQigpe30sCm43OmZ1bmN0aW9uIG43KCl7
+fSwKd3o6ZnVuY3Rpb24gd3ooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKY3Y6ZnVuY3Rpb24gY3Yo
+KXt9LApDdjpmdW5jdGlvbiBDdigpe30sCmVhOmZ1bmN0aW9uIGVhKCl7fSwKRDA6ZnVuY3Rpb24gRDAo
+KXt9LApoSDpmdW5jdGlvbiBoSCgpe30sCmg0OmZ1bmN0aW9uIGg0KCl7fSwKYnI6ZnVuY3Rpb24gYnIo
+KXt9LApWYjpmdW5jdGlvbiBWYigpe30sCmZKOmZ1bmN0aW9uIGZKKCl7fSwKd2E6ZnVuY3Rpb24gd2Eo
+KXt9LApTZzpmdW5jdGlvbiBTZygpe30sCnc3OmZ1bmN0aW9uIHc3KCl7fSwKQWo6ZnVuY3Rpb24gQWoo
+KXt9LAplNzpmdW5jdGlvbiBlNyhhKXt0aGlzLmE9YX0sCnVIOmZ1bmN0aW9uIHVIKCl7fSwKQkg6ZnVu
+Y3Rpb24gQkgoKXt9LApTTjpmdW5jdGlvbiBTTigpe30sCmV3OmZ1bmN0aW9uIGV3KCl7fSwKbHA6ZnVu
+Y3Rpb24gbHAoKXt9LApUYjpmdW5jdGlvbiBUYigpe30sCkl2OmZ1bmN0aW9uIEl2KCl7fSwKV1A6ZnVu
+Y3Rpb24gV1AoKXt9LAp5WTpmdW5jdGlvbiB5WSgpe30sCnc2OmZ1bmN0aW9uIHc2KCl7fSwKSzU6ZnVu
+Y3Rpb24gSzUoKXt9LApDbTpmdW5jdGlvbiBDbSgpe30sCkNROmZ1bmN0aW9uIENRKCl7fSwKdzQ6ZnVu
+Y3Rpb24gdzQoKXt9LApyaDpmdW5jdGlvbiByaCgpe30sCmNmOmZ1bmN0aW9uIGNmKCl7fSwKaTc6ZnVu
+Y3Rpb24gaTcoYSl7dGhpcy5hPWF9LApTeTpmdW5jdGlvbiBTeShhKXt0aGlzLmE9YX0sCktTOmZ1bmN0
+aW9uIEtTKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBMzpmdW5jdGlvbiBBMyhhLGIpe3RoaXMuYT1h
+CnRoaXMuYj1ifSwKSTQ6ZnVuY3Rpb24gSTQoYSl7dGhpcy5hPWF9LApGazpmdW5jdGlvbiBGayhhLGIp
+e3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApSTzpmdW5jdGlvbiBSTyhhLGIsYyxkKXt2YXIgXz10aGlzCl8u
+YT1hCl8uYj1iCl8uYz1jCl8uJHRpPWR9LApldTpmdW5jdGlvbiBldShhLGIsYyxkKXt2YXIgXz10aGlz
+Cl8uYT1hCl8uYj1iCl8uYz1jCl8uJHRpPWR9LAp4QzpmdW5jdGlvbiB4QyhhLGIsYyxkLGUpe3ZhciBf
+PXRoaXMKXy5iPWEKXy5jPWIKXy5kPWMKXy5lPWQKXy4kdGk9ZX0sCnZOOmZ1bmN0aW9uIHZOKGEpe3Ro
+aXMuYT1hfSwKSlE6ZnVuY3Rpb24gSlEoYSl7dGhpcy5hPWF9LApHbTpmdW5jdGlvbiBHbSgpe30sCnZE
+OmZ1bmN0aW9uIHZEKGEpe3RoaXMuYT1hfSwKVXY6ZnVuY3Rpb24gVXYoYSl7dGhpcy5hPWF9LApFZzpm
+dW5jdGlvbiBFZyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAptNjpmdW5jdGlvbiBt
+Nigpe30sCkVvOmZ1bmN0aW9uIEVvKCl7fSwKV2s6ZnVuY3Rpb24gV2soKXt9LApjdDpmdW5jdGlvbiBj
+dChhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5lPWEKXy5hPWIKXy5iPWMKXy5jPWQKXy5kPWV9LApJQTpm
+dW5jdGlvbiBJQSgpe30sCk93OmZ1bmN0aW9uIE93KCl7fSwKVzk6ZnVuY3Rpb24gVzkoYSxiLGMpe3Zh
+ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPS0xCl8uZD1udWxsCl8uJHRpPWN9LApkVzpmdW5jdGlvbiBk
+Vygpe30sCm1rOmZ1bmN0aW9uIG1rKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApLbzpmdW5jdGlvbiBL
+byhhKXt0aGlzLmE9YQp0aGlzLmI9ITF9LApmbTpmdW5jdGlvbiBmbShhKXt0aGlzLmE9YX0sCkxlOmZ1
+bmN0aW9uIExlKCl7fSwKSzc6ZnVuY3Rpb24gSzcoKXt9LApyQjpmdW5jdGlvbiByQigpe30sClhXOmZ1
+bmN0aW9uIFhXKCl7fSwKb2E6ZnVuY3Rpb24gb2EoKXt9fSxVPXsKamY6ZnVuY3Rpb24oYSl7dmFyIHMs
+cixxLHAKaWYoYT09bnVsbClzPW51bGwKZWxzZXtzPUguVk0oW10sdC5kNykKZm9yKHI9Si5JVCh0LlUu
+YShhKSk7ci5GKCk7KXtxPXIuZ2woKQpwPUouVTYocSkKcy5wdXNoKG5ldyBVLlNlKEguaChwLnEocSwi
+ZGVzY3JpcHRpb24iKSksSC5oKHAucShxLCJocmVmIikpKSl9fXJldHVybiBzfSwKTmQ6ZnVuY3Rpb24o
+YSl7dmFyIHMscgppZihhPT1udWxsKXM9bnVsbAplbHNle3M9SC5WTShbXSx0LmFBKQpmb3Iocj1KLklU
+KHQuVS5hKGEpKTtyLkYoKTspcy5wdXNoKFUuTmYoci5nbCgpKSl9cmV0dXJuIHN9LApOZjpmdW5jdGlv
+bihhKXt2YXIgcz1KLlU2KGEpLHI9SC5oKHMucShhLCJkZXNjcmlwdGlvbiIpKSxxPUguVk0oW10sdC5h
+SikKZm9yKHM9Si5JVCh0LlUuYShzLnEoYSwiZW50cmllcyIpKSk7cy5GKCk7KXEucHVzaChVLlJqKHMu
+Z2woKSkpCnJldHVybiBuZXcgVS55RChyLHEpfSwKUmo6ZnVuY3Rpb24oYSl7dmFyIHMscj1KLlU2KGEp
+LHE9SC5oKHIucShhLCJkZXNjcmlwdGlvbiIpKSxwPUguaChyLnEoYSwiZnVuY3Rpb24iKSksbz1yLnEo
+YSwibGluayIpCmlmKG89PW51bGwpbz1udWxsCmVsc2V7cz1KLlU2KG8pCm89bmV3IFUuTWwoSC5oKHMu
+cShvLCJocmVmIikpLEgudVAocy5xKG8sImxpbmUiKSksSC5oKHMucShvLCJwYXRoIikpKX1yPXQuZksu
+YShyLnEoYSwiaGludEFjdGlvbnMiKSkKcj1yPT1udWxsP251bGw6Si5NMShyLG5ldyBVLmFOKCksdC5h
+WCkKcj1yPT1udWxsP251bGw6ci5icigwKQpyZXR1cm4gbmV3IFUud2IocSxwLG8scj09bnVsbD9DLmRu
+OnIpfSwKZDI6ZnVuY3Rpb24gZDIoYSxiLGMsZCxlLGYpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5j
+PWMKXy5kPWQKXy5lPWUKXy5mPWZ9LApTZTpmdW5jdGlvbiBTZShhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
+fSwKTWw6ZnVuY3Rpb24gTWwoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKeUQ6ZnVu
+Y3Rpb24geUQoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCndiOmZ1bmN0aW9uIHdiKGEsYixjLGQpe3Zh
+ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LAphTjpmdW5jdGlvbiBhTigpe30sCmIwOmZ1
+bmN0aW9uIGIwKCl7fX0sQj17CndSOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBCLnFwKCIiLCIiLCIiLEMu
+RHgpfSwKWWY6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0sbCxrPUguaChhLnEoMCwicmVnaW9u
+cyIpKSxqPUguaChhLnEoMCwibmF2aWdhdGlvbkNvbnRlbnQiKSksaT1ILmgoYS5xKDAsInNvdXJjZUNv
+ZGUiKSksaD1QLkZsKHQuWCx0LmRfKQpmb3Iocz10LnQuYShhLnEoMCwiZWRpdHMiKSkscz1zLmdQdShz
+KSxzPXMuZ20ocykscj10LlUscT10Lmg0O3MuRigpOyl7cD1zLmdsKCkKbz1wLmEKbj1ILlZNKFtdLHEp
+CmZvcihwPUouSVQoci5hKHAuYikpO3AuRigpOyl7bT1wLmdsKCkKbD1KLlU2KG0pCm4ucHVzaChuZXcg
+Qi5qOChILnVQKGwucShtLCJsaW5lIikpLEguaChsLnEobSwiZXhwbGFuYXRpb24iKSksSC51UChsLnEo
+bSwib2Zmc2V0IikpKSl9aC5ZNSgwLG8sbil9cmV0dXJuIG5ldyBCLnFwKGssaixpLGgpfSwKajg6ZnVu
+Y3Rpb24gajgoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcXA6ZnVuY3Rpb24gcXAo
+YSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmZ2OmZ1bmN0aW9uIGZ2
+KCl7fSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoIShhPj02NSYmYTw9OTApKXM9YT49OTcmJmE8PTEy
+MgplbHNlIHM9ITAKcmV0dXJuIHN9LApZdTpmdW5jdGlvbihhLGIpe3ZhciBzPWEubGVuZ3RoLHI9Yisy
+CmlmKHM8cilyZXR1cm4hMQppZighQi5PUyhDLnhCLk8oYSxiKSkpcmV0dXJuITEKaWYoQy54Qi5PKGEs
+YisxKSE9PTU4KXJldHVybiExCmlmKHM9PT1yKXJldHVybiEwCnJldHVybiBDLnhCLk8oYSxyKT09PTQ3
+fX0sVD17bVE6ZnVuY3Rpb24gbVEoKXt9fSxMPXsKSXE6ZnVuY3Rpb24oKXtDLkJaLkIoZG9jdW1lbnQs
+IkRPTUNvbnRlbnRMb2FkZWQiLG5ldyBMLmUoKSkKQy5vbC5CKHdpbmRvdywicG9wc3RhdGUiLG5ldyBM
+LkwoKSl9LAprejpmdW5jdGlvbihhKXt2YXIgcyxyPXQuZy5hKGEucGFyZW50Tm9kZSkucXVlcnlTZWxl
+Y3RvcigiOnNjb3BlID4gdWwiKSxxPXIuc3R5bGUscD0iIitDLkNELnpRKHIub2Zmc2V0SGVpZ2h0KSoy
+KyJweCIKcS5tYXhIZWlnaHQ9cApxPUoucUYoYSkKcD1xLiR0aQpzPXAuQygifigxKT8iKS5hKG5ldyBM
+Lld4KHIsYSkpCnQuWi5hKG51bGwpClcuSkUocS5hLHEuYixzLCExLHAuYyl9LAp5WDpmdW5jdGlvbihh
+LGIpe3ZhciBzLHIscSxwLG8sbixtPSJxdWVyeVNlbGVjdG9yQWxsIixsPWRvY3VtZW50LnF1ZXJ5U2Vs
+ZWN0b3IoYSksaz10LmcKbC50b1N0cmluZwpzPXQuaApILkRoKGsscywiVCIsbSkKcj10LlIKcT1uZXcg
+Vy53eihsLnF1ZXJ5U2VsZWN0b3JBbGwoIi5uYXYtbGluayIpLHIpCnEuSyhxLG5ldyBMLkFPKGIpKQpI
+LkRoKGsscywiVCIsbSkKcD1uZXcgVy53eihsLnF1ZXJ5U2VsZWN0b3JBbGwoIi5yZWdpb24iKSxyKQpp
+ZighcC5nbDAocCkpe289bC5xdWVyeVNlbGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikKby50b1N0cmlu
+ZwpwLksocCxuZXcgTC5IbyhvLmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KG8p
+KS5PVSgicGF0aCIpKSkpfUguRGgoayxzLCJUIixtKQpuPW5ldyBXLnd6KGwucXVlcnlTZWxlY3RvckFs
+bCgiLmFkZC1oaW50LWxpbmsiKSxyKQpuLksobixuZXcgTC5JQygpKX0sClE2OmZ1bmN0aW9uKGEsYixj
+KXt2YXIgcz1uZXcgWE1MSHR0cFJlcXVlc3QoKQpDLkR0LmVvKHMsIkdFVCIsTC5RNChhLGIpLCEwKQpz
+LnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIsImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9
+VVRGLTgiKQpyZXR1cm4gTC5MVShzLG51bGwsYy5DKCIwKiIpKX0sCnR5OmZ1bmN0aW9uKGEsYil7dmFy
+IHM9bmV3IFhNTEh0dHBSZXF1ZXN0KCkscj10LlgKQy5EdC5lbyhzLCJQT1NUIixMLlE0KGEsUC5GbChy
+LHIpKSwhMCkKcy5zZXRSZXF1ZXN0SGVhZGVyKCJDb250ZW50LVR5cGUiLCJhcHBsaWNhdGlvbi9qc29u
+OyBjaGFyc2V0PVVURi04IikKcmV0dXJuIEwuTFUocyxiLHQudCl9LApMVTpmdW5jdGlvbihhLGIsYyl7
+cmV0dXJuIEwuVGcoYSxiLGMsYy5DKCIwKiIpKX0sClRnOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzPTAs
+cj1QLkZYKGQpLHEscD0yLG8sbj1bXSxtLGwsayxqLGksaCxnLGYKdmFyICRhc3luYyRMVT1QLmx6KGZ1
+bmN0aW9uKGUsYTApe2lmKGU9PT0xKXtvPWEwCnM9cH13aGlsZSh0cnVlKXN3aXRjaChzKXtjYXNlIDA6
+aT1uZXcgUC5aZihuZXcgUC52cygkLlgzLHQuZ1YpLHQuYkMpCmg9dC5lYgpnPWguYShuZXcgTC5mQyhp
+LGEpKQp0LlouYShudWxsKQpsPXQuZVEKVy5KRShhLCJsb2FkIixnLCExLGwpClcuSkUoYSwiZXJyb3Ii
+LGguYShpLmdZSigpKSwhMSxsKQphLnNlbmQoYj09bnVsbD9udWxsOkMuQ3QuT0IoYixudWxsKSkKcD00
+CnM9NwpyZXR1cm4gUC5qUShpLmEsJGFzeW5jJExVKQpjYXNlIDc6cD0yCnM9NgpicmVhawpjYXNlIDQ6
+cD0zCmY9bwpILlJ1KGYpCm09SC50cyhmKQpoPVAuVGwoIkVycm9yIHJlYWNoaW5nIG1pZ3JhdGlvbiBw
+cmV2aWV3IHNlcnZlci4iLG0pCnRocm93IEguYihoKQpzPTYKYnJlYWsKY2FzZSAzOnM9MgpicmVhawpj
+YXNlIDY6aj1DLkN0LnBXKDAsYS5yZXNwb25zZVRleHQsbnVsbCkKaWYoYS5zdGF0dXM9PT0yMDApe3E9
+Yy5DKCIwKiIpLmEoaikKcz0xCmJyZWFrfWVsc2UgdGhyb3cgSC5iKGopCmNhc2UgMTpyZXR1cm4gUC55
+QyhxLHIpCmNhc2UgMjpyZXR1cm4gUC5mMyhvLHIpfX0pCnJldHVybiBQLkRJKCRhc3luYyRMVSxyKX0s
+CmFLOmZ1bmN0aW9uKGEpe3ZhciBzPVAuaEsoYSkuZ2hZKCkucSgwLCJsaW5lIikKcmV0dXJuIHM9PW51
+bGw/bnVsbDpILkhwKHMsbnVsbCl9LApHNjpmdW5jdGlvbihhKXt2YXIgcz1QLmhLKGEpLmdoWSgpLnEo
+MCwib2Zmc2V0IikKcmV0dXJuIHM9PW51bGw/bnVsbDpILkhwKHMsbnVsbCl9LAppNjpmdW5jdGlvbihh
+KXtyZXR1cm4gTC5uVyh0Lk8uYShhKSl9LApuVzpmdW5jdGlvbihhKXt2YXIgcz0wLHI9UC5GWCh0Lnop
+LHE9MSxwLG89W10sbixtLGwsayxqLGksaAp2YXIgJGFzeW5jJGk2PVAubHooZnVuY3Rpb24oYixjKXtp
+ZihiPT09MSl7cD1jCnM9cX13aGlsZSh0cnVlKXN3aXRjaChzKXtjYXNlIDA6aT10LmcuYShXLnFjKGEu
+Y3VycmVudFRhcmdldCkpLmdldEF0dHJpYnV0ZSgiaHJlZiIpCmEucHJldmVudERlZmF1bHQoKQpxPTMK
+az1kb2N1bWVudApuPUMuQ0QuelEoay5xdWVyeVNlbGVjdG9yKCIuY29udGVudCIpLnNjcm9sbFRvcCkK
+cz02CnJldHVybiBQLmpRKEwudHkoaSxudWxsKSwkYXN5bmMkaTYpCmNhc2UgNjpzPTcKcmV0dXJuIFAu
+alEoTC5HNyh3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUsbnVsbCxudWxsLCExLG51bGwpLCRhc3luYyRp
+NikKY2FzZSA3Oms9ay5xdWVyeVNlbGVjdG9yKCIuY29udGVudCIpCmsudG9TdHJpbmcKay5zY3JvbGxU
+b3A9Si5WdShuKQpxPTEKcz01CmJyZWFrCmNhc2UgMzpxPTIKaD1wCm09SC5SdShoKQpsPUgudHMoaCkK
+TC5DMigiQ291bGQgbm90IGFkZC9yZW1vdmUgaGludCIsbSxsKQpzPTUKYnJlYWsKY2FzZSAyOnM9MQpi
+cmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxyKQpjYXNlIDE6cmV0dXJuIFAuZjMocCxyKX19KQpy
+ZXR1cm4gUC5ESSgkYXN5bmMkaTYscil9LApDMjpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHA9ImV4
+Y2VwdGlvbiIsbz0ic3RhY2tUcmFjZSIsbj10LnQuYihiKSYmSi5STShiLnEoMCwic3VjY2VzcyIpLCEx
+KSYmYi54NChwKSYmYi54NChvKSxtPUouaWEoYikKaWYobil7cz1ILmgobS5xKGIscCkpCmM9bS5xKGIs
+byl9ZWxzZSBzPW0udyhiKQpuPWRvY3VtZW50CnI9bi5xdWVyeVNlbGVjdG9yKCIucG9wdXAtcGFuZSIp
+CnIucXVlcnlTZWxlY3RvcigiaDIiKS5pbm5lclRleHQ9YQpyLnF1ZXJ5U2VsZWN0b3IoInAiKS5pbm5l
+clRleHQ9cwpyLnF1ZXJ5U2VsZWN0b3IoInByZSIpLmlubmVyVGV4dD1KLmooYykKcT10LmRkLmEoci5x
+dWVyeVNlbGVjdG9yKCJhLmJvdHRvbSIpKTsocSYmQy54bikuc0xVKHEsUC5YZCgiaHR0cHMiLCJnaXRo
+dWIuY29tIiwiZGFydC1sYW5nL3Nkay9pc3N1ZXMvbmV3IixQLkVGKFsidGl0bGUiLCJDdXN0b21lci1y
+ZXBvcnRlZCBpc3N1ZSB3aXRoIE5OQkQgbWlncmF0aW9uIHRvb2w6ICIrYSwibGFiZWxzIix1LmQsImJv
+ZHkiLGErIlxuXG5FcnJvcjogIitILkVqKHMpKyJcblxuUGxlYXNlIGZpbGwgaW4gdGhlIGZvbGxvd2lu
+ZzpcblxuKipOYW1lIG9mIHBhY2thZ2UgYmVpbmcgbWlncmF0ZWQgKGlmIHB1YmxpYykqKjpcbioqV2hh
+dCBJIHdhcyBkb2luZyB3aGVuIHRoaXMgaXNzdWUgb2NjdXJyZWQqKjpcbioqSXMgaXQgcG9zc2libGUg
+dG8gd29yayBhcm91bmQgdGhpcyBpc3N1ZSoqOlxuKipIYXMgdGhpcyBpc3N1ZSBoYXBwZW5lZCBiZWZv
+cmUsIGFuZCBpZiBzbywgaG93IG9mdGVuKio6XG4qKkRhcnQgU0RLIHZlcnNpb24qKjogIitILkVqKG4u
+Z2V0RWxlbWVudEJ5SWQoInNkay12ZXJzaW9uIikudGV4dENvbnRlbnQpKyJcbioqQWRkaXRpb25hbCBk
+ZXRhaWxzKio6XG5cblRoYW5rcyBmb3IgZmlsaW5nIVxuXG5TdGFja3RyYWNlOiBfYXV0byBwb3B1bGF0
+ZWQgYnkgbWlncmF0aW9uIHByZXZpZXcgdG9vbC5fXG5cbmBgYFxuIitILkVqKGMpKyJcbmBgYFxuIl0s
+dC5YLHQueikpLmduRCgpKQpuPXEuc3R5bGUKbi5kaXNwbGF5PSJpbml0aWFsIgpuPXIuc3R5bGUKbi5k
+aXNwbGF5PSJpbml0aWFsIgpuPWErIjogIitILkVqKGIpCndpbmRvdwppZih0eXBlb2YgY29uc29sZSE9
+InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3IobikKd2luZG93Cm49SC5FaihjKQppZih0eXBl
+b2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3Iobil9LAp0MjpmdW5jdGlv
+bihhLGIpe3ZhciBzLHIscSxwLG89dC5nLmEoVy5xYyhhLmN1cnJlbnRUYXJnZXQpKQphLnByZXZlbnRE
+ZWZhdWx0KCkKcz1vLmdldEF0dHJpYnV0ZSgiaHJlZiIpCnI9TC5VcyhzKQpxPUwuRzYocykKcD1MLmFL
+KHMpCmlmKHEhPW51bGwpTC5hZihyLHEscCxiLG5ldyBMLm5UKHIscSxwKSkKZWxzZSBMLmFmKHIsbnVs
+bCxudWxsLGIsbmV3IEwuTlkocikpfSwKSzA6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9ZG9jdW1lbnQu
+cXVlcnlTZWxlY3RvcigiLnBvcHVwLXBhbmUiKQpwLnF1ZXJ5U2VsZWN0b3IoImgyIikuaW5uZXJUZXh0
+PSJGYWlsZWQgdG8gcmVydW4gZnJvbSBzb3VyY2VzIgpwLnF1ZXJ5U2VsZWN0b3IoInAiKS5pbm5lclRl
+eHQ9IlNvdXJjZXMgY29udGFpbiBzdGF0aWMgYW5hbHlzaXMgZXJyb3JzOiIKcz1wLnF1ZXJ5U2VsZWN0
+b3IoInByZSIpCnI9Si5FbChhLHQuYXcpCnE9SC5MaChyKQpzLmlubmVyVGV4dD1uZXcgSC5sSihyLHEu
+QygicVUqKGxELkUpIikuYShuZXcgTC51ZSgpKSxxLkMoImxKPGxELkUscVUqPiIpKS5rKDAsIlxuIikK
+cT1wLnF1ZXJ5U2VsZWN0b3IoImEuYm90dG9tIikuc3R5bGUKcS5kaXNwbGF5PSJub25lIgpzPXAuc3R5
+bGUKcy5kaXNwbGF5PSJpbml0aWFsIn0sCnZVOmZ1bmN0aW9uKCl7dmFyIHM9ZG9jdW1lbnQKSC5EaCh0
+LmcsdC5oLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnM9bmV3IFcud3oocy5xdWVyeVNlbGVjdG9yQWxs
+KCIuY29kZSIpLHQuUikKcy5LKHMsbmV3IEwuZVgoKSl9LApoWDpmdW5jdGlvbihhLGIsYyl7cmV0dXJu
+IEwuWXcoYSxiLGMpfSwKWXc6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPTAscj1QLkZYKHQueikscT0xLHAs
+bz1bXSxuLG0sbCxrLGosaSxoLGcKdmFyICRhc3luYyRoWD1QLmx6KGZ1bmN0aW9uKGQsZSl7aWYoZD09
+PTEpe3A9ZQpzPXF9d2hpbGUodHJ1ZSlzd2l0Y2gocyl7Y2FzZSAwOnE9MwpqPXQuWApzPTYKcmV0dXJu
+IFAualEoTC5RNihhLFAuRUYoWyJyZWdpb24iLCJyZWdpb24iLCJvZmZzZXQiLEguRWooYildLGosaiks
+dC50KSwkYXN5bmMkaFgpCmNhc2UgNjpuPWUKaj1uCmk9Si5VNihqKQptPW5ldyBVLmQyKFUuamYoaS5x
+KGosImVkaXRzIikpLEguaChpLnEoaiwiZXhwbGFuYXRpb24iKSksSC51UChpLnEoaiwibGluZSIpKSxI
+LmgoaS5xKGosImRpc3BsYXlQYXRoIikpLEguaChpLnEoaiwidXJpUGF0aCIpKSxVLk5kKGkucShqLCJ0
+cmFjZXMiKSkpCkwuVDEobSkKTC5GcihhLGIsYykKTC55WCgiLmVkaXQtcGFuZWwgLnBhbmVsLWNvbnRl
+bnQiLCExKQpxPTEKcz01CmJyZWFrCmNhc2UgMzpxPTIKZz1wCmw9SC5SdShnKQprPUgudHMoZykKTC5D
+MigiQ291bGQgbm90IGxvYWQgZWRpdCBkZXRhaWxzIixsLGspCnM9NQpicmVhawpjYXNlIDI6cz0xCmJy
+ZWFrCmNhc2UgNTpyZXR1cm4gUC55QyhudWxsLHIpCmNhc2UgMTpyZXR1cm4gUC5mMyhwLHIpfX0pCnJl
+dHVybiBQLkRJKCRhc3luYyRoWCxyKX0sCkc3OmZ1bmN0aW9uKGEsYixjLGQsZSl7cmV0dXJuIEwuTDUo
+YSxiLGMsZCxlKX0sCkw1OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHM9MCxyPVAuRlgodC5IKSxxLHA9
+MixvLG49W10sbSxsLGssaixpLGgsZwp2YXIgJGFzeW5jJEc3PVAubHooZnVuY3Rpb24oZixhMCl7aWYo
+Zj09PTEpe289YTAKcz1wfXdoaWxlKHRydWUpc3dpdGNoKHMpe2Nhc2UgMDppZighSi5wNChhLCIuZGFy
+dCIpKXtMLkJFKGEsQi53UigpLGQpCkwuQlgoYSxudWxsKQppZihlIT1udWxsKWUuJDAoKQpzPTEKYnJl
+YWt9cD00Cmk9dC5YCnM9NwpyZXR1cm4gUC5qUShMLlE2KGEsUC5FRihbImlubGluZSIsInRydWUiXSxp
+LGkpLHQudCksJGFzeW5jJEc3KQpjYXNlIDc6bT1hMApMLkJFKGEsQi5ZZihtKSxkKQpMLmZHKGIsYykK
+bD1MLlVzKGEpCkwuQlgobCxiKQppZihlIT1udWxsKWUuJDAoKQpwPTIKcz02CmJyZWFrCmNhc2UgNDpw
+PTMKZz1vCms9SC5SdShnKQpqPUgudHMoZykKTC5DMigiQ291bGQgbm90IGxvYWQgZGFydCBmaWxlICIr
+YSxrLGopCnM9NgpicmVhawpjYXNlIDM6cz0yCmJyZWFrCmNhc2UgNjpjYXNlIDE6cmV0dXJuIFAueUMo
+cSxyKQpjYXNlIDI6cmV0dXJuIFAuZjMobyxyKX19KQpyZXR1cm4gUC5ESSgkYXN5bmMkRzcscil9LApH
+ZTpmdW5jdGlvbigpe3ZhciBzPTAscj1QLkZYKHQueikscT0xLHAsbz1bXSxuLG0sbCxrLGosaSxoLGcK
+dmFyICRhc3luYyRHZT1QLmx6KGZ1bmN0aW9uKGEsYil7aWYoYT09PTEpe3A9YgpzPXF9d2hpbGUodHJ1
+ZSlzd2l0Y2gocyl7Y2FzZSAwOmg9Ii9fcHJldmlldy9uYXZpZ2F0aW9uVHJlZS5qc29uIgpxPTMKcz02
+CnJldHVybiBQLmpRKEwuUTYoaCxDLkNNLHQuZUUpLCRhc3luYyRHZSkKY2FzZSA2Om49YgptPWRvY3Vt
+ZW50LnF1ZXJ5U2VsZWN0b3IoIi5uYXYtdHJlZSIpCkoubDUobSwiIikKaj1MLm1LKG4pCiQuSVI9agpM
+LnRYKG0saiwhMCkKcT0xCnM9NQpicmVhawpjYXNlIDM6cT0yCmc9cApsPUguUnUoZykKaz1ILnRzKGcp
+CkwuQzIoIkNvdWxkIG5vdCBsb2FkIG5hdmlnYXRpb24gdHJlZSIsbCxrKQpzPTUKYnJlYWsKY2FzZSAy
+OnM9MQpicmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxyKQpjYXNlIDE6cmV0dXJuIFAuZjMocCxy
+KX19KQpyZXR1cm4gUC5ESSgkYXN5bmMkR2Uscil9LApxTzpmdW5jdGlvbihhKXt2YXIgcyxyPWEuZ2V0
+Qm91bmRpbmdDbGllbnRSZWN0KCkscT1DLkNELnpRKCQuZmkoKS5vZmZzZXRIZWlnaHQpLHA9d2luZG93
+LmlubmVySGVpZ2h0LG89Qy5DRC56USgkLkRXKCkub2Zmc2V0SGVpZ2h0KQppZih0eXBlb2YgcCE9PSJu
+dW1iZXIiKXJldHVybiBwLkhOKCkKcz1yLmJvdHRvbQpzLnRvU3RyaW5nCmlmKHM+cC0obysxNCkpSi5k
+aChhKQplbHNle3A9ci50b3AKcC50b1N0cmluZwppZihwPHErMTQpSi5kaChhKX19LApmRzpmdW5jdGlv
+bihhLGIpe3ZhciBzLHIscSxwLG8KaWYoYSE9bnVsbCl7cz1kb2N1bWVudApyPXMuZ2V0RWxlbWVudEJ5
+SWQoIm8iK0guRWooYSkpCnE9cy5xdWVyeVNlbGVjdG9yKCIubGluZS0iK0guRWooYikpCmlmKHIhPW51
+bGwpe0wucU8ocikKSi5kUihyKS5pKDAsInRhcmdldCIpfWVsc2UgaWYocSE9bnVsbClMLnFPKHEucGFy
+ZW50RWxlbWVudCkKaWYocSE9bnVsbClKLmRSKHQuZy5hKHEucGFyZW50Tm9kZSkpLmkoMCwiaGlnaGxp
+Z2h0Iil9ZWxzZXtzPWRvY3VtZW50CnA9dC5nCkguRGgocCx0LmgsIlQiLCJxdWVyeVNlbGVjdG9yQWxs
+IikKcz1zLnF1ZXJ5U2VsZWN0b3JBbGwoIi5saW5lLW5vIikKbz1uZXcgVy53eihzLHQuUikKaWYoby5n
+QShvKT09PTApcmV0dXJuCkwucU8ocC5hKEMudDUuZ3RIKHMpKSl9fSwKYWY6ZnVuY3Rpb24oYSxiLGMs
+ZCxlKXt2YXIgcyxyLHE9TC5HNih3aW5kb3cubG9jYXRpb24uaHJlZikscD1MLmFLKHdpbmRvdy5sb2Nh
+dGlvbi5ocmVmKQppZihxIT1udWxsKXtzPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJvIitILkVqKHEp
+KQppZihzIT1udWxsKUouZFIocykuUigwLCJ0YXJnZXQiKX1pZihwIT1udWxsKXtyPWRvY3VtZW50LnF1
+ZXJ5U2VsZWN0b3IoIi5saW5lLSIrSC5FaihwKSkKaWYociE9bnVsbClKLmRSKHIucGFyZW50RWxlbWVu
+dCkuUigwLCJoaWdobGlnaHQiKX1pZihhPT13aW5kb3cubG9jYXRpb24ucGF0aG5hbWUpe0wuZkcoYixj
+KQplLiQwKCl9ZWxzZSBMLkc3KGEsYixjLGQsZSl9LApRNDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT1Q
+LmhLKGEpLHA9dC5YCnA9UC5GbChwLHApCmZvcihzPXEuZ2hZKCkscz1zLmdQdShzKSxzPXMuZ20ocyk7
+cy5GKCk7KXtyPXMuZ2woKQpwLlk1KDAsci5hLHIuYil9Zm9yKHM9Yi5nUHUoYikscz1zLmdtKHMpO3Mu
+RigpOyl7cj1zLmdsKCkKcC5ZNSgwLHIuYSxyLmIpfXAuWTUoMCwiYXV0aFRva2VuIiwkLlVFKCkpCnJl
+dHVybiBxLm5tKDAscCkuZ25EKCl9LApUMTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsLGss
+aj0kLmhMKCkKSi5sNShqLCIiKQppZihhPT1udWxsKXtzPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInAi
+KQpDLkx0LnNhNChzLCJTZWUgZGV0YWlscyBhYm91dCBhIHByb3Bvc2VkIGVkaXQuIikKQy5MdC5zUChz
+LEguVk0oWyJwbGFjZWhvbGRlciJdLHQuaSkpCmouYXBwZW5kQ2hpbGQocykKQy5MdC5GRihzKQpyZXR1
+cm59cj1hLmQKcT0kLm5VKCkKcD1xLnpmKHIpCm89YS5iCm49ZG9jdW1lbnQKbT1xLkhQKHIsSi5UMChu
+LnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQpKQpsPWEuYwprPW4uY3JlYXRlRWxlbWVu
+dCgicCIpCmouYXBwZW5kQ2hpbGQoaykKay5hcHBlbmRDaGlsZChuLmNyZWF0ZVRleHROb2RlKEguRWoo
+bykrIiBhdCAiKSkKcT10LlgKcT1XLko2KEwuUTQoYS5lLFAuRUYoWyJsaW5lIixKLmoobCldLHEscSkp
+KQpxLmFwcGVuZENoaWxkKG4uY3JlYXRlVGV4dE5vZGUoSC5FaihtKSsiOiIrSC5FaihsKSsiLiIpKQpr
+LmFwcGVuZENoaWxkKHEpCkouZGgoaykKTC5DQyhhLGoscCkKTC5GeihhLGopfSwKTEg6ZnVuY3Rpb24o
+YSxiLGMpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT0kLnlQKCkKSi5sNShlLCIiKQpp
+ZihiLmdBKGIpPT09MCl7cz1kb2N1bWVudApyPXMuY3JlYXRlRWxlbWVudCgicCIpCmUuYXBwZW5kQ2hp
+bGQocikKci5hcHBlbmRDaGlsZChzLmNyZWF0ZVRleHROb2RlKCJObyBwcm9wb3NlZCBlZGl0cyIpKX1l
+bHNlIGZvcihlPWIuZ1B1KGIpLGU9ZS5nbShlKSxzPXQuWCxxPXQuayxwPXEuQygifigxKT8iKSxvPXQu
+WixxPXEuYztlLkYoKTspe249ZS5nbCgpCm09ZG9jdW1lbnQKcj1tLmNyZWF0ZUVsZW1lbnQoInAiKQps
+PSQueVAoKQpsLmFwcGVuZENoaWxkKHIpCnIuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZShILkVq
+KG4uYSkrIjoiKSkKaz1tLmNyZWF0ZUVsZW1lbnQoInVsIikKbC5hcHBlbmRDaGlsZChrKQpmb3Iobj1K
+LklUKG4uYik7bi5GKCk7KXtsPW4uZ2woKQpqPW0uY3JlYXRlRWxlbWVudCgibGkiKQprLmFwcGVuZENo
+aWxkKGopCkouZFIoaikuaSgwLCJlZGl0IikKaT1tLmNyZWF0ZUVsZW1lbnQoImEiKQpqLmFwcGVuZENo
+aWxkKGkpCmkuY2xhc3NMaXN0LmFkZCgiZWRpdC1saW5rIikKaD1sLmMKZz1ILkVqKGgpCmkuc2V0QXR0
+cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcoaSkpLk9VKCJvZmZzZXQiKSxnKQpmPWwuYQpn
+PUguRWooZikKaS5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhpKSkuT1UoImxp
+bmUiKSxnKQppLmFwcGVuZENoaWxkKG0uY3JlYXRlVGV4dE5vZGUoImxpbmUgIitILkVqKGYpKSkKaS5z
+ZXRBdHRyaWJ1dGUoImhyZWYiLEwuUTQod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLFAuRUYoWyJsaW5l
+IixILkVqKGYpLCJvZmZzZXQiLEguRWooaCldLHMscykpKQpnPXAuYShuZXcgTC5FRShoLGYsYSkpCm8u
+YShudWxsKQpXLkpFKGksImNsaWNrIixnLCExLHEpCmouYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9k
+ZSgiOiAiK0guRWoobC5iKSkpfX1pZihjKUwuVDEobnVsbCl9LApGcjpmdW5jdGlvbihhLGIsYyl7dmFy
+IHMscixxPXdpbmRvdy5sb2NhdGlvbixwPVAuaEsoKHEmJkMuRXgpLmdEcihxKStILkVqKGEpKQpxPXQu
+WApxPVAuRmwocSxxKQppZihiIT1udWxsKXEuWTUoMCwib2Zmc2V0IixILkVqKGIpKQppZihjIT1udWxs
+KXEuWTUoMCwibGluZSIsSC5FaihjKSkKcS5ZNSgwLCJhdXRoVG9rZW4iLCQuVUUoKSkKcD1wLm5tKDAs
+cSkKcT13aW5kb3cuaGlzdG9yeQpzPXQuegpyPXAuZ25EKCkKcS50b1N0cmluZwpxLnB1c2hTdGF0ZShu
+ZXcgUC5CZihbXSxbXSkuUHYoUC5GbChzLHMpKSwiIixyKX0sCkVuOmZ1bmN0aW9uKGEpe3ZhciBzPUou
+YmIoZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCwiLyIpCmlmKEMueEIu
+bihhLHMpKXJldHVybiBDLnhCLnluKGEscy5sZW5ndGgpCmVsc2UgcmV0dXJuIGF9LApPdDpmdW5jdGlv
+bihhKXtzd2l0Y2goYS5yKXtjYXNlIEMuY3c6YnJlYWsKY2FzZSBDLldEOmEucj1DLlhqCmJyZWFrCmNh
+c2UgQy5YajphLnI9Qy5XRApicmVhawpjYXNlIEMuZGM6dGhyb3cgSC5iKFAuUFYoIkZpbGUgIitILkVq
+KGEuYykrIiBzaG91bGQgbm90IGhhdmUgaW5kZXRlcm1pbmF0ZSBtaWdyYXRpb24gc3RhdHVzIikpfX0s
+CnhuOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPSJkaXNhYmxlZCIscD1iLmdMKCkKTC50YShhLHApCmlm
+KGIuYz09JC5EOSgpLmlubmVyVGV4dCl7cz1iIGluc3RhbmNlb2YgTC5jRCYmIUgub1QoYi54KQpyPUou
+WUUoYSkKaWYocylyLmdQKGEpLmkoMCxxKQplbHNlIHIuZ1AoYSkuUigwLHEpCkwudGEoJC5jMCgpLHAp
+fX0sCnRhOmZ1bmN0aW9uKGEsYil7dmFyIHMscj0iY2hlY2tfYm94IixxPSJ0aXRsZSIscD0ib3B0ZWQt
+b3V0IixvPSJtaWdyYXRpbmciCnN3aXRjaChiKXtjYXNlIEMuY3c6YS5pbm5lclRleHQ9cgpzPUouWUUo
+YSkKcy5nUChhKS5pKDAsImFscmVhZHktbWlncmF0ZWQiKQpzLmdQKGEpLmkoMCwiZGlzYWJsZWQiKQph
 LnNldEF0dHJpYnV0ZShxLCJBbHJlYWR5IG1pZ3JhdGVkIikKYnJlYWsKY2FzZSBDLldEOmEuaW5uZXJU
-ZXh0PXIKcz1KLllFKGEpCnMuZ24oYSkuTCgwLHApCnMuZ24oYSkuaSgwLG8pCmEuc2V0QXR0cmlidXRl
+ZXh0PXIKcz1KLllFKGEpCnMuZ1AoYSkuUigwLHApCnMuZ1AoYSkuaSgwLG8pCmEuc2V0QXR0cmlidXRl
 KHEsIk1pZ3JhdGluZyB0byBudWxsIHNhZmV0eSIpCmJyZWFrCmNhc2UgQy5YajphLmlubmVyVGV4dD0i
-Y2hlY2tfYm94X291dGxpbmVfYmxhbmsiCnM9Si5ZRShhKQpzLmduKGEpLkwoMCxvKQpzLmduKGEpLmko
+Y2hlY2tfYm94X291dGxpbmVfYmxhbmsiCnM9Si5ZRShhKQpzLmdQKGEpLlIoMCxvKQpzLmdQKGEpLmko
 MCxwKQphLnNldEF0dHJpYnV0ZShxLCJPcHRpbmcgb3V0IG9mIG51bGwgc2FmZXR5IikKYnJlYWsKZGVm
-YXVsdDphLmlubmVyVGV4dD0iaW5kZXRlcm1pbmF0ZV9jaGVja19ib3giCnM9Si5ZRShhKQpzLmduKGEp
-LkwoMCxvKQpzLmduKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0ZShxLCJNaXhlZCBzdGF0dXNlcyBvZiAn
+YXVsdDphLmlubmVyVGV4dD0iaW5kZXRlcm1pbmF0ZV9jaGVja19ib3giCnM9Si5ZRShhKQpzLmdQKGEp
+LlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0ZShxLCJNaXhlZCBzdGF0dXNlcyBvZiAn
 bWlncmF0aW5nJyBhbmQgJ29wdGluZyBvdXQnIikKYnJlYWt9fSwKQlg6ZnVuY3Rpb24oYSxiKXt2YXIg
-cyxyPXt9CnIuYT1hCmE9TC5FbihhKQpyLmE9YQpKLmRyKCQuRDkoKSxhKQpzPWRvY3VtZW50CkguRGgo
-dC5nLHQuaCwiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQpzPW5ldyBXLnd6KHMucXVlcnlTZWxlY3RvckFs
-bCgiLm5hdi1wYW5lbCAubmF2LWxpbmsiKSx0LlIpCnMuSyhzLG5ldyBMLlZTKHIpKQpKLmRSKCQuYk4o
-KSkuaSgwLCJ2aXNpYmxlIil9LApBUjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT1iLmIKaWYocSE9bnVs
-bCl7cz10LmcKcj1zLmEocy5hKGEucGFyZW50Tm9kZSkucGFyZW50Tm9kZSkKTC54bihyLnF1ZXJ5U2Vs
-ZWN0b3IoIjpzY29wZSA+IC5zdGF0dXMtaWNvbiIpLHEpCkwuQVIocixxKX19LApCRTpmdW5jdGlvbihh
-LGIsYyl7dmFyIHM9Ii5yZWdpb25zIixyPWRvY3VtZW50LHE9ci5xdWVyeVNlbGVjdG9yKHMpLHA9ci5x
-dWVyeVNlbGVjdG9yKCIuY29kZSIpCkoudEgocSxiLmEsJC5LRygpKQpKLnRIKHAsYi5iLCQuS0coKSkK
-TC5MSChhLGIuZCxjKQppZihiLmMubGVuZ3RoPDJlNSlMLnZVKCkKTC55WCgiLmNvZGUiLCEwKQpMLnlY
-KHMsITApfSwKdFg6ZnVuY3Rpb24oYSxiLGEwKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxm
-LGU9Im1hdGVyaWFsLWljb25zIixkPWRvY3VtZW50LGM9ZC5jcmVhdGVFbGVtZW50KCJ1bCIpCmEuYXBw
-ZW5kQ2hpbGQoYykKZm9yKHM9Yi5sZW5ndGgscj10LlgscT10LloscD0wO3A8Yi5sZW5ndGg7Yi5sZW5n
-dGg9PT1zfHwoMCxILmxrKShiKSwrK3Ape289YltwXQpuPWQuY3JlYXRlRWxlbWVudCgibGkiKQpjLmFw
-cGVuZENoaWxkKG4pCmlmKG8gaW5zdGFuY2VvZiBMLnZ0KXtKLmRSKG4pLmkoMCwiZGlyIikKbi5zZXRB
-dHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhuKSkuUCgibmFtZSIpLG8uYykKbT1kLmNy
-ZWF0ZUVsZW1lbnQoInNwYW4iKQpuLmFwcGVuZENoaWxkKG0pCmw9Si5ZRShtKQpsLmduKG0pLmkoMCwi
-YXJyb3ciKQpsLnNoZihtLCImI3gyNUJDOyIpCms9ZC5jcmVhdGVFbGVtZW50KCJzcGFuIikKSi5kUihr
-KS5pKDAsZSkKay5pbm5lclRleHQ9ImZvbGRlcl9vcGVuIgpuLmFwcGVuZENoaWxkKGspCm4uYXBwZW5k
-Q2hpbGQoZC5jcmVhdGVUZXh0Tm9kZShvLmEpKQpMLnRYKG4sby5kLCExKQpMLmt6KG0pfWVsc2UgaWYo
-byBpbnN0YW5jZW9mIEwuY0Qpe2w9ZC5jcmVhdGVFbGVtZW50KCJzcGFuIikKSi5kUihsKS5pKDAsZSkK
-bC5pbm5lclRleHQ9Imluc2VydF9kcml2ZV9maWxlIgpuLmFwcGVuZENoaWxkKGwpCmo9ZC5jcmVhdGVF
-bGVtZW50KCJhIikKbi5hcHBlbmRDaGlsZChqKQpsPUouWUUoaikKbC5nbihqKS5pKDAsIm5hdi1saW5r
-IikKai5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhqKSkuUCgibmFtZSIpLG8u
-YykKai5zZXRBdHRyaWJ1dGUoImhyZWYiLEwuUTQoby5kLFAuRmwocixyKSkpCmouYXBwZW5kQ2hpbGQo
-ZC5jcmVhdGVUZXh0Tm9kZShvLmEpKQpsPWwuZ1ZsKGopCmk9bC4kdGkKaD1pLkMoIn4oMSk/IikuYShu
-ZXcgTC5URCgpKQpxLmEobnVsbCkKVy5KRShsLmEsbC5iLGgsITEsaS5jKQpnPW8uZQppZih0eXBlb2Yg
-ZyE9PSJudW1iZXIiKXJldHVybiBnLm9zKCkKaWYoZz4wKXtmPWQuY3JlYXRlRWxlbWVudCgic3BhbiIp
-Cm4uYXBwZW5kQ2hpbGQoZikKSi5kUihmKS5pKDAsImVkaXQtY291bnQiKQpsPSIiK2crIiAiCmlmKGc9
-PT0xKWk9InByb3Bvc2VkIGVkaXQiCmVsc2UgaT0icHJvcG9zZWQgZWRpdHMiCmYuc2V0QXR0cmlidXRl
-KCJ0aXRsZSIsbCtpKQpmLmFwcGVuZENoaWxkKGQuY3JlYXRlVGV4dE5vZGUoQy5qbi53KGcpKSl9fX19
-LAp1ejpmdW5jdGlvbihhLGIsYyl7dmFyIHM9ZG9jdW1lbnQscj1zLmNyZWF0ZUVsZW1lbnQoImJ1dHRv
-biIpLHE9dC5rLHA9cS5DKCJ+KDEpPyIpLmEobmV3IEwubTIoYSxjKSkKdC5aLmEobnVsbCkKVy5KRShy
-LCJjbGljayIscCwhMSxxLmMpCnIuYXBwZW5kQ2hpbGQocy5jcmVhdGVUZXh0Tm9kZShNLk9YKGEuYSkp
-KQpiLmFwcGVuZENoaWxkKHIpfSwKRno6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxsLGss
-aixpLGg9YS5hCmlmKGg9PW51bGwpcmV0dXJuCnM9ZG9jdW1lbnQKcj1zLmNyZWF0ZUVsZW1lbnQoInAi
-KQpxPWIuYXBwZW5kQ2hpbGQocikKcj1zLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpwPXQuaQpKLk11KHIs
-SC5WTShbInR5cGUtZGVzY3JpcHRpb24iXSxwKSkKci5hcHBlbmRDaGlsZChzLmNyZWF0ZVRleHROb2Rl
-KCJBY3Rpb25zIikpCnEuYXBwZW5kQ2hpbGQocikKcS5hcHBlbmRDaGlsZChzLmNyZWF0ZVRleHROb2Rl
-KCI6IikpCm89cy5jcmVhdGVFbGVtZW50KCJwIikKYi5hcHBlbmRDaGlsZChvKQpmb3Iocj1oLmxlbmd0
-aCxuPXQuUSxtPTA7bTxoLmxlbmd0aDtoLmxlbmd0aD09PXJ8fCgwLEgubGspKGgpLCsrbSl7bD1oW21d
-Cms9cy5jcmVhdGVFbGVtZW50KCJhIikKby5hcHBlbmRDaGlsZChrKQprLmFwcGVuZENoaWxkKHMuY3Jl
-YXRlVGV4dE5vZGUobC5hKSkKay5zZXRBdHRyaWJ1dGUoImhyZWYiLGwuYikKaj1uLmEoSC5WTShbImFk
-ZC1oaW50LWxpbmsiLCJiZWZvcmUtYXBwbHkiLCJidXR0b24iXSxwKSkKaT1KLmRSKGspCmkuVjEoMCkK
-aS5GVigwLGopfX0sCkNDOmZ1bmN0aW9uKGE0LGE1LGE2KXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixp
-LGgsZyxmLGUsZCxjLGIsYSxhMCxhMSxhMixhMwpmb3Iocz1hNC5mLHI9cy5sZW5ndGgscT10LmkscD10
-LlEsbz0wO288cy5sZW5ndGg7cy5sZW5ndGg9PT1yfHwoMCxILmxrKShzKSwrK28pe249c1tvXQptPWRv
-Y3VtZW50Cmw9bS5jcmVhdGVFbGVtZW50KCJwIikKaz1wLmEoSC5WTShbInRyYWNlIl0scSkpCmo9Si5k
-UihsKQpqLlYxKDApCmouRlYoMCxrKQppPWE1LmFwcGVuZENoaWxkKGwpCmw9bS5jcmVhdGVFbGVtZW50
-KCJzcGFuIikKaz1wLmEoSC5WTShbInR5cGUtZGVzY3JpcHRpb24iXSxxKSkKaj1KLmRSKGwpCmouVjEo
-MCkKai5GVigwLGspCmwuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZShuLmEpKQppLmFwcGVuZENo
-aWxkKGwpCmkuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZSgiOiIpKQpsPW0uY3JlYXRlRWxlbWVu
-dCgidWwiKQprPXAuYShILlZNKFsidHJhY2UiXSxxKSkKaj1KLmRSKGwpCmouVjEoMCkKai5GVigwLGsp
-Cmg9aS5hcHBlbmRDaGlsZChsKQpmb3IobD1uLmIsaz1sLmxlbmd0aCxnPTA7ZzxsLmxlbmd0aDtsLmxl
-bmd0aD09PWt8fCgwLEgubGspKGwpLCsrZyl7Zj1sW2ddCmU9bS5jcmVhdGVFbGVtZW50KCJsaSIpCmgu
-YXBwZW5kQ2hpbGQoZSkKZD1tLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpjPXAuYShILlZNKFsiZnVuY3Rp
-b24iXSxxKSkKaj1KLmRSKGQpCmouVjEoMCkKai5GVigwLGMpCmM9Zi5iCkwua0QoZCxjPT1udWxsPyJ1
-bmtub3duIjpjKQplLmFwcGVuZENoaWxkKGQpCmI9Zi5jCmlmKGIhPW51bGwpe2UuYXBwZW5kQ2hpbGQo
-bS5jcmVhdGVUZXh0Tm9kZSgiICgiKSkKYT1iLmIKYTA9bS5jcmVhdGVFbGVtZW50KCJhIikKYTAuYXBw
-ZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZShILkVqKGIuYykrIjoiK0guRWooYSkpKQphMC5zZXRBdHRy
-aWJ1dGUoImhyZWYiLGIuYSkKYTAuY2xhc3NMaXN0LmFkZCgibmF2LWxpbmsiKQplLmFwcGVuZENoaWxk
-KGEwKQplLmFwcGVuZENoaWxkKG0uY3JlYXRlVGV4dE5vZGUoIikiKSl9ZS5hcHBlbmRDaGlsZChtLmNy
-ZWF0ZVRleHROb2RlKCI6ICIpKQpkPWYuYQpMLmtEKGUsZD09bnVsbD8idW5rbm93biI6ZCkKZD1mLmQK
-aWYoZC5sZW5ndGghPT0wKXtjPW0uY3JlYXRlRWxlbWVudCgicCIpCmExPXAuYShILlZNKFsiZHJhd2Vy
-IiwiYmVmb3JlLWFwcGx5Il0scSkpCmo9Si5kUihjKQpqLlYxKDApCmouRlYoMCxhMSkKYTI9ZS5hcHBl
-bmRDaGlsZChjKQpmb3IoYz1kLmxlbmd0aCxhMz0wO2EzPGQubGVuZ3RoO2QubGVuZ3RoPT09Y3x8KDAs
-SC5saykoZCksKythMylMLnV6KGRbYTNdLGEyLGIpfX19fSwKVXM6ZnVuY3Rpb24oYSl7cmV0dXJuIEou
-VTYoYSkudGcoYSwiPyIpP0MueEIuTmooYSwwLEMueEIuT1koYSwiPyIpKTphfSwKa0Q6ZnVuY3Rpb24o
-YSxiKXt2YXIgcyxyLHE9SC5WTShiLnNwbGl0KCIuIiksdC5zKSxwPUMuTm0uZ3RIKHEpLG89ZG9jdW1l
-bnQKYS5hcHBlbmRDaGlsZChvLmNyZWF0ZVRleHROb2RlKHApKQpmb3IocD1ILnFDKHEsMSxudWxsLHQu
-TikscD1uZXcgSC5hNyhwLHAuZ0EocCkscC4kdGkuQygiYTc8YUwuRT4iKSkscz1KLllFKGEpO3AuRigp
-Oyl7cj1wLmQKcy5ueihhLCJiZWZvcmVlbmQiLCImIzgyMDM7LiIsbnVsbCxudWxsKQphLmFwcGVuZENo
-aWxkKG8uY3JlYXRlVGV4dE5vZGUocikpfX0sCm1IOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAKZm9y
-KHM9YS5sZW5ndGgscj0wO3I8YS5sZW5ndGg7YS5sZW5ndGg9PT1zfHwoMCxILmxrKShhKSwrK3Ipe3E9
-YVtyXQppZihxIGluc3RhbmNlb2YgTC52dCl7cD1MLm1IKHEuZCxiKQppZihwIT1udWxsKXJldHVybiBw
-fWVsc2UgaWYocS5jPT1iKXJldHVybiBxfXJldHVybiBudWxsfSwKZTpmdW5jdGlvbiBlKCl7fSwKVlc6
-ZnVuY3Rpb24gVlcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKb1o6ZnVuY3Rpb24g
-b1ooKXt9LApqcjpmdW5jdGlvbiBqcigpe30sCnFsOmZ1bmN0aW9uIHFsKCl7fSwKSGk6ZnVuY3Rpb24g
-SGkoKXt9LApCVDpmdW5jdGlvbiBCVCgpe30sClBZOmZ1bmN0aW9uIFBZKCl7fSwKdTg6ZnVuY3Rpb24g
-dTgoKXt9LApMOmZ1bmN0aW9uIEwoKXt9LApXeDpmdW5jdGlvbiBXeChhLGIpe3RoaXMuYT1hCnRoaXMu
-Yj1ifSwKQU86ZnVuY3Rpb24gQU8oYSl7dGhpcy5hPWF9LApkTjpmdW5jdGlvbiBkTihhKXt0aGlzLmE9
-YX0sCkhvOmZ1bmN0aW9uIEhvKGEpe3RoaXMuYT1hfSwKeHo6ZnVuY3Rpb24geHooYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sCklDOmZ1bmN0aW9uIElDKCl7fSwKZkM6ZnVuY3Rpb24gZkMoYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sCm5UOmZ1bmN0aW9uIG5UKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
-Y30sCk5ZOmZ1bmN0aW9uIE5ZKGEpe3RoaXMuYT1hfSwKdWU6ZnVuY3Rpb24gdWUoKXt9LAplWDpmdW5j
-dGlvbiBlWCgpe30sCkVFOmZ1bmN0aW9uIEVFKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
-Y30sClFMOmZ1bmN0aW9uIFFMKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApWUzpmdW5jdGlvbiBWUyhh
-KXt0aGlzLmE9YX0sClREOmZ1bmN0aW9uIFREKCl7fSwKbTI6ZnVuY3Rpb24gbTIoYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sClhBOmZ1bmN0aW9uIFhBKCl7fSwKWnM6ZnVuY3Rpb24oYSl7dmFyIHMscixxPUou
-VTYoYSkKaWYoTC5wMihILmgocS5xKGEsInR5cGUiKSkpPT09Qy5ZMil7cz1ILmgocS5xKGEsIm5hbWUi
-KSkKcj1ILmgocS5xKGEsInBhdGgiKSkKcT1xLnEoYSwic3VidHJlZSIpCnE9bmV3IEwudnQocT09bnVs
-bD9udWxsOkwubUsocSkscyxyKQpxLkxWKCkKcmV0dXJuIHF9ZWxzZXtzPUguaChxLnEoYSwibmFtZSIp
-KQpyPUguaChxLnEoYSwicGF0aCIpKQpyZXR1cm4gbmV3IEwuY0QoSC5oKHEucShhLCJocmVmIikpLEgu
-dVAocS5xKGEsImVkaXRDb3VudCIpKSxILnk4KHEucShhLCJ3YXNFeHBsaWNpdGx5T3B0ZWRPdXQiKSks
-TC52QihILnVQKHEucShhLCJtaWdyYXRpb25TdGF0dXMiKSkpLHMscil9fSwKbUs6ZnVuY3Rpb24oYSl7
-dmFyIHMscj1ILlZNKFtdLHQuY1EpCmZvcihzPUouSVQodC5VLmEoYSkpO3MuRigpOylyLnB1c2goTC5a
-cyhzLmdsKCkpKQpyZXR1cm4gcn0sClZEOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT1ILlZNKFtdLHQuRykK
-Zm9yKHM9YS5sZW5ndGgscj0wO3I8YS5sZW5ndGg7YS5sZW5ndGg9PT1zfHwoMCxILmxrKShhKSwrK3Ip
-cS5wdXNoKGFbcl0uTHQoKSkKcmV0dXJuIHF9LAp2QjpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVy
-biBudWxsCmlmKGE+Pj4wIT09YXx8YT49NClyZXR1cm4gSC5PSChDLmwwLGEpCnJldHVybiBDLmwwW2Fd
-fSwKcDI6ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UiZGlyZWN0b3J5IjpyZXR1cm4gQy5ZMgpjYXNl
-ImZpbGUiOnJldHVybiBDLnJmCmRlZmF1bHQ6dGhyb3cgSC5iKFAuUFYoIlVucmVjb2duaXplZCBuYXZp
-Z2F0aW9uIHRyZWUgbm9kZSB0eXBlOiAiK0guRWooYSkpKX19LAp2dDpmdW5jdGlvbiB2dChhLGIsYyl7
-dmFyIF89dGhpcwpfLmQ9YQpfLmE9YgpfLmI9bnVsbApfLmM9Y30sCmNEOmZ1bmN0aW9uIGNEKGEsYixj
-LGQsZSxmKXt2YXIgXz10aGlzCl8uZD1hCl8uZT1iCl8uZj1jCl8ucj1kCl8uYT1lCl8uYj1udWxsCl8u
-Yz1mfSwKRDg6ZnVuY3Rpb24gRDgoKXt9LApPOTpmdW5jdGlvbiBPOShhKXt0aGlzLmI9YX0sCkdiOmZ1
-bmN0aW9uIEdiKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApJVjpmdW5jdGlvbiBJVihhLGIsYyxkKXt2
-YXIgXz10aGlzCl8uZD1hCl8uZT1iCl8uZj1jCl8ucj1kfX0sWD17CkNMOmZ1bmN0aW9uKGEsYil7dmFy
-IHMscixxLHAsbyxuPWIueFooYSkKYi5oSyhhKQppZihuIT1udWxsKWE9Si5LVihhLG4ubGVuZ3RoKQpz
-PXQucwpyPUguVk0oW10scykKcT1ILlZNKFtdLHMpCnM9YS5sZW5ndGgKaWYocyE9PTAmJmIucjQoQy54
-Qi5XKGEsMCkpKXtpZigwPj1zKXJldHVybiBILk9IKGEsMCkKQy5ObS5pKHEsYVswXSkKcD0xfWVsc2V7
-Qy5ObS5pKHEsIiIpCnA9MH1mb3Iobz1wO288czsrK28paWYoYi5yNChDLnhCLlcoYSxvKSkpe0MuTm0u
-aShyLEMueEIuTmooYSxwLG8pKQpDLk5tLmkocSxhW29dKQpwPW8rMX1pZihwPHMpe0MuTm0uaShyLEMu
-eEIueW4oYSxwKSkKQy5ObS5pKHEsIiIpfXJldHVybiBuZXcgWC5XRChiLG4scixxKX0sCldEOmZ1bmN0
-aW9uIFdEKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPWMKXy5lPWR9LApJNzpmdW5j
-dGlvbihhKXtyZXR1cm4gbmV3IFguZHYoYSl9LApkdjpmdW5jdGlvbiBkdihhKXt0aGlzLmE9YX19LE89
-ewpSaDpmdW5jdGlvbigpe3ZhciBzLHI9bnVsbAppZihQLnVvKCkuZ0ZpKCkhPT0iZmlsZSIpcmV0dXJu
-ICQuRWIoKQpzPVAudW8oKQppZighQy54Qi5UYyhzLmdJaShzKSwiLyIpKXJldHVybiAkLkViKCkKaWYo
-UC5LTChyLCJhL2IiLHIscixyLHIscikudDQoKT09PSJhXFxiIilyZXR1cm4gJC5LaygpCnJldHVybiAk
-LmJEKCl9LAp6TDpmdW5jdGlvbiB6TCgpe319LEU9e09GOmZ1bmN0aW9uIE9GKGEsYixjKXt0aGlzLmQ9
-YQp0aGlzLmU9Ygp0aGlzLmY9Y319LEY9e3J1OmZ1bmN0aW9uIHJ1KGEsYixjLGQpe3ZhciBfPXRoaXMK
-Xy5kPWEKXy5lPWIKXy5mPWMKXy5yPWR9fSxEPXsKYWI6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvPW51
-bGwKdHJ5e289UC51bygpfWNhdGNoKHMpe2lmKHQuZzguYihILlJ1KHMpKSl7cj0kLkZmCmlmKHIhPW51
-bGwpcmV0dXJuIHIKdGhyb3cgc31lbHNlIHRocm93IHN9aWYoSi5STShvLCQuSTYpKXtyPSQuRmYKci50
-b1N0cmluZwpyZXR1cm4gcn0kLkk2PW8KaWYoJC5IaygpPT0kLkViKCkpcj0kLkZmPW8uWkkoIi4iKS53
-KDApCmVsc2V7cT1vLnQ0KCkKcD1xLmxlbmd0aC0xCnI9JC5GZj1wPT09MD9xOkMueEIuTmoocSwwLHAp
-fXIudG9TdHJpbmcKcmV0dXJuIHJ9fQp2YXIgdz1bQyxILEosUCxXLE0sVSxCLFQsTCxYLE8sRSxGLERd
-Cmh1bmtIZWxwZXJzLnNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2FyeSh3KQp2YXIgJD17fQpILkZLLnBy
-b3RvdHlwZT17fQpKLkd2LnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PT1ifSwK
-Z2lPOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFu
-Y2Ugb2YgJyIrSC5FaihILk0oYSkpKyInIn0sCmU3OmZ1bmN0aW9uKGEsYil7dC5vLmEoYikKdGhyb3cg
-SC5iKFAubHIoYSxiLmdXYSgpLGIuZ25kKCksYi5nVm0oKSkpfX0KSi55RS5wcm90b3R5cGU9ewp3OmZ1
-bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIGE/NTE5MDE4
-OjIxODE1OX0sCiRpYTI6MX0KSi53ZS5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3JldHVybiBu
-dWxsPT1ifSwKdzpmdW5jdGlvbihhKXtyZXR1cm4ibnVsbCJ9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJu
-IDB9LAplNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNqKGEsdC5vLmEoYikpfSwKJGljODoxfQpK
-Lk1GLnByb3RvdHlwZT17CmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gMH0sCnc6ZnVuY3Rpb24oYSl7cmV0
-dXJuIFN0cmluZyhhKX0sCiRpdm06MX0KSi5pQy5wcm90b3R5cGU9e30KSi5rZC5wcm90b3R5cGU9e30K
-Si5jNS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzPWFbJC53KCldCmlmKHM9PW51bGwpcmV0
-dXJuIHRoaXMudChhKQpyZXR1cm4iSmF2YVNjcmlwdCBmdW5jdGlvbiBmb3IgIitILkVqKEouaihzKSl9
-LAokaUVIOjF9CkouamQucHJvdG90eXBlPXsKZHI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEgualYo
-YSxILnQ2KGEpLkMoIkA8MT4iKS5LcShiKS5DKCJqVjwxLDI+IikpfSwKaTpmdW5jdGlvbihhLGIpe0gu
-dDYoYSkuYy5hKGIpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC52KFAuTDQoImFkZCIpKQphLnB1c2goYil9
-LApXNDpmdW5jdGlvbihhLGIpe3ZhciBzCmlmKCEhYS5maXhlZCRsZW5ndGgpSC52KFAuTDQoInJlbW92
-ZUF0IikpCnM9YS5sZW5ndGgKaWYoYj49cyl0aHJvdyBILmIoUC5PNyhiLG51bGwpKQpyZXR1cm4gYS5z
-cGxpY2UoYiwxKVswXX0sClVHOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyCkgudDYoYSkuQygiY1g8MT4i
-KS5hKGMpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC52KFAuTDQoImluc2VydEFsbCIpKQpQLndBKGIsMCxh
-Lmxlbmd0aCwiaW5kZXgiKQppZighdC5iLmIoYykpYz1KLlJYKGMpCnM9Si5IbShjKQphLmxlbmd0aD1h
-Lmxlbmd0aCtzCnI9YitzCnRoaXMuWVcoYSxyLGEubGVuZ3RoLGEsYikKdGhpcy52ZyhhLGIscixjKX0s
-CkZWOmZ1bmN0aW9uKGEsYil7dmFyIHMKSC50NihhKS5DKCJjWDwxPiIpLmEoYikKaWYoISFhLmZpeGVk
-JGxlbmd0aClILnYoUC5MNCgiYWRkQWxsIikpCmZvcihzPUouSVQoYik7cy5GKCk7KWEucHVzaChzLmds
-KCkpfSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPUgudDYoYSkKcmV0dXJuIG5ldyBILmxKKGEscy5L
-cShjKS5DKCIxKDIpIikuYShiKSxzLkMoIkA8MT4iKS5LcShjKS5DKCJsSjwxLDI+IikpfSwKazpmdW5j
-dGlvbihhLGIpe3ZhciBzLHI9UC5POChhLmxlbmd0aCwiIiwhMSx0Lk4pCmZvcihzPTA7czxhLmxlbmd0
-aDsrK3MpdGhpcy5ZNShyLHMsSC5FaihhW3NdKSkKcmV0dXJuIHIuam9pbihiKX0sCmVSOmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIEgucUMoYSxiLG51bGwsSC50NihhKS5jKX0sCk4wOmZ1bmN0aW9uKGEsYixjLGQp
-e3ZhciBzLHIscQpkLmEoYikKSC50NihhKS5LcShkKS5DKCIxKDEsMikiKS5hKGMpCnM9YS5sZW5ndGgK
-Zm9yKHI9YixxPTA7cTxzOysrcSl7cj1jLiQyKHIsYVtxXSkKaWYoYS5sZW5ndGghPT1zKXRocm93IEgu
-YihQLmE0KGEpKX1yZXR1cm4gcn0sCkh0OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbwpILnQ2KGEp
-LkMoImEyKDEpIikuYShiKQpzPWEubGVuZ3RoCmZvcihyPW51bGwscT0hMSxwPTA7cDxzOysrcCl7bz1h
-W3BdCmlmKEgub1QoYi4kMShvKSkpe2lmKHEpdGhyb3cgSC5iKEguQW0oKSkKcj1vCnE9ITB9aWYocyE9
-PWEubGVuZ3RoKXRocm93IEguYihQLmE0KGEpKX1pZihxKXJldHVybiByCnRocm93IEguYihILldwKCkp
-fSwKRTpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1
-cm4gYVtiXX0sCmd0SDpmdW5jdGlvbihhKXtpZihhLmxlbmd0aD4wKXJldHVybiBhWzBdCnRocm93IEgu
-YihILldwKCkpfSwKZ3JaOmZ1bmN0aW9uKGEpe3ZhciBzPWEubGVuZ3RoCmlmKHM+MClyZXR1cm4gYVtz
-LTFdCnRocm93IEguYihILldwKCkpfSwKWVc6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxv
-CkgudDYoYSkuQygiY1g8MT4iKS5hKGQpCmlmKCEhYS5pbW11dGFibGUkbGlzdClILnYoUC5MNCgic2V0
-UmFuZ2UiKSkKUC5qQihiLGMsYS5sZW5ndGgpCnM9Yy1iCmlmKHM9PT0wKXJldHVybgpQLmsxKGUsInNr
-aXBDb3VudCIpCmlmKHQuai5iKGQpKXtyPWQKcT1lfWVsc2V7cj1KLkE1KGQsZSkudHQoMCwhMSkKcT0w
-fXA9Si5VNihyKQppZihxK3M+cC5nQShyKSl0aHJvdyBILmIoSC5hcigpKQppZihxPGIpZm9yKG89cy0x
-O28+PTA7LS1vKWFbYitvXT1wLnEocixxK28pCmVsc2UgZm9yKG89MDtvPHM7KytvKWFbYitvXT1wLnEo
-cixxK28pfSwKdmc6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIHRoaXMuWVcoYSxiLGMsZCwwKX0sClZy
-OmZ1bmN0aW9uKGEsYil7dmFyIHMscgpILnQ2KGEpLkMoImEyKDEpIikuYShiKQpzPWEubGVuZ3RoCmZv
-cihyPTA7cjxzOysrcil7aWYoSC5vVChiLiQxKGFbcl0pKSlyZXR1cm4hMAppZihhLmxlbmd0aCE9PXMp
-dGhyb3cgSC5iKFAuYTQoYSkpfXJldHVybiExfSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgcwpmb3Iocz0w
-O3M8YS5sZW5ndGg7KytzKWlmKEouUk0oYVtzXSxiKSlyZXR1cm4hMApyZXR1cm4hMX0sCmdsMDpmdW5j
-dGlvbihhKXtyZXR1cm4gYS5sZW5ndGg9PT0wfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0
-aCE9PTB9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKGEsIlsiLCJdIil9LAp0dDpmdW5jdGlvbihh
-LGIpe3ZhciBzPUguVk0oYS5zbGljZSgwKSxILnQ2KGEpKQpyZXR1cm4gc30sCmJyOmZ1bmN0aW9uKGEp
-e3JldHVybiB0aGlzLnR0KGEsITApfSwKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBKLm0xKGEsYS5s
-ZW5ndGgsSC50NihhKS5DKCJtMTwxPiIpKX0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gSC5lUShhKX0s
-CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnNBOmZ1bmN0aW9uKGEsYil7aWYoISFhLmZp
-eGVkJGxlbmd0aClILnYoUC5MNCgic2V0IGxlbmd0aCIpKQppZihiPDApdGhyb3cgSC5iKFAuVEUoYiww
-LG51bGwsIm5ld0xlbmd0aCIsbnVsbCkpCmEubGVuZ3RoPWJ9LApxOmZ1bmN0aW9uKGEsYil7SC51UChi
-KQppZihiPj1hLmxlbmd0aHx8YjwwKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKWTU6
-ZnVuY3Rpb24oYSxiLGMpe0gudDYoYSkuYy5hKGMpCmlmKCEhYS5pbW11dGFibGUkbGlzdClILnYoUC5M
-NCgiaW5kZXhlZCBzZXQiKSkKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQph
-W2JdPWN9LAokaWJROjEsCiRpY1g6MSwKJGl6TToxfQpKLlBvLnByb3RvdHlwZT17fQpKLm0xLnByb3Rv
-dHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVuY3Rpb24oKXt2YXIgcyxyPXRo
-aXMscT1yLmEscD1xLmxlbmd0aAppZihyLmIhPT1wKXRocm93IEguYihILmxrKHEpKQpzPXIuYwppZihz
-Pj1wKXtyLnNNKG51bGwpCnJldHVybiExfXIuc00ocVtzXSk7KytyLmMKcmV0dXJuITB9LApzTTpmdW5j
-dGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuQygiMT8iKS5hKGEpfSwKJGlBbjoxfQpKLnFJLnByb3RvdHlw
-ZT17CnpROmZ1bmN0aW9uKGEpe2lmKGE+MCl7aWYoYSE9PTEvMClyZXR1cm4gTWF0aC5yb3VuZChhKX1l
-bHNlIGlmKGE+LTEvMClyZXR1cm4gMC1NYXRoLnJvdW5kKDAtYSkKdGhyb3cgSC5iKFAuTDQoIiIrYSsi
-LnJvdW5kKCkiKSl9LAp3OmZ1bmN0aW9uKGEpe2lmKGE9PT0wJiYxL2E8MClyZXR1cm4iLTAuMCIKZWxz
-ZSByZXR1cm4iIithfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG89YXwwCmlmKGE9PT1vKXJl
-dHVybiBvJjUzNjg3MDkxMQpzPU1hdGguYWJzKGEpCnI9TWF0aC5sb2cocykvMC42OTMxNDcxODA1NTk5
-NDUzfDAKcT1NYXRoLnBvdygyLHIpCnA9czwxP3MvcTpxL3MKcmV0dXJuKChwKjkwMDcxOTkyNTQ3NDA5
-OTJ8MCkrKHAqMzU0MjI0MzE4MTE3NjUyMXwwKSkqNTk5MTk3K3IqMTI1OSY1MzY4NzA5MTF9LAp6WTpm
-dW5jdGlvbihhLGIpe3ZhciBzPWElYgppZihzPT09MClyZXR1cm4gMAppZihzPjApcmV0dXJuIHMKaWYo
-YjwwKXJldHVybiBzLWIKZWxzZSByZXR1cm4gcytifSwKQlU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4oYXww
-KT09PWE/YS9ifDA6dGhpcy5ESihhLGIpfSwKREo6ZnVuY3Rpb24oYSxiKXt2YXIgcz1hL2IKaWYocz49
-LTIxNDc0ODM2NDgmJnM8PTIxNDc0ODM2NDcpcmV0dXJuIHN8MAppZihzPjApe2lmKHMhPT0xLzApcmV0
-dXJuIE1hdGguZmxvb3Iocyl9ZWxzZSBpZihzPi0xLzApcmV0dXJuIE1hdGguY2VpbChzKQp0aHJvdyBI
-LmIoUC5MNCgiUmVzdWx0IG9mIHRydW5jYXRpbmcgZGl2aXNpb24gaXMgIitILkVqKHMpKyI6ICIrSC5F
-aihhKSsiIH4vICIrYikpfSwKd0c6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihhPjApcz10aGlzLnAzKGEs
-YikKZWxzZXtzPWI+MzE/MzE6YgpzPWE+PnM+Pj4wfXJldHVybiBzfSwKYmY6ZnVuY3Rpb24oYSxiKXtp
-ZihiPDApdGhyb3cgSC5iKEgudEwoYikpCnJldHVybiB0aGlzLnAzKGEsYil9LApwMzpmdW5jdGlvbihh
-LGIpe3JldHVybiBiPjMxPzA6YT4+PmJ9LAokaUNQOjEsCiRpWlo6MX0KSi5iVS5wcm90b3R5cGU9eyRp
-SWY6MX0KSi5WQS5wcm90b3R5cGU9e30KSi5Eci5wcm90b3R5cGU9ewpPMjpmdW5jdGlvbihhLGIpe2lm
-KGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQppZihiPj1hLmxlbmd0aClILnYoSC5IWShhLGIpKQpyZXR1
-cm4gYS5jaGFyQ29kZUF0KGIpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI+PWEubGVuZ3RoKXRocm93IEgu
-YihILkhZKGEsYikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LApkZDpmdW5jdGlvbihhLGIpe3JldHVy
-biBuZXcgSC51bihiLGEsMCl9LApoOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGIhPSJzdHJpbmciKXRo
-cm93IEguYihQLkwzKGIsbnVsbCxudWxsKSkKcmV0dXJuIGErYn0sClRjOmZ1bmN0aW9uKGEsYil7dmFy
-IHM9Yi5sZW5ndGgscj1hLmxlbmd0aAppZihzPnIpcmV0dXJuITEKcmV0dXJuIGI9PT10aGlzLnluKGEs
-ci1zKX0sCmk3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzPVAuakIoYixjLGEubGVuZ3RoKSxyPWEuc3Vi
-c3RyaW5nKDAsYikscT1hLnN1YnN0cmluZyhzKQpyZXR1cm4gcitkK3F9LApRaTpmdW5jdGlvbihhLGIs
-Yyl7dmFyIHMKaWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxudWxs
-LG51bGwpKQpzPWMrYi5sZW5ndGgKaWYocz5hLmxlbmd0aClyZXR1cm4hMQpyZXR1cm4gYj09PWEuc3Vi
-c3RyaW5nKGMscyl9LApuQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlFpKGEsYiwwKX0sCk5qOmZ1
-bmN0aW9uKGEsYixjKXtpZihjPT1udWxsKWM9YS5sZW5ndGgKaWYoYjwwKXRocm93IEguYihQLk83KGIs
-bnVsbCkpCmlmKGI+Yyl0aHJvdyBILmIoUC5PNyhiLG51bGwpKQppZihjPmEubGVuZ3RoKXRocm93IEgu
-YihQLk83KGMsbnVsbCkpCnJldHVybiBhLnN1YnN0cmluZyhiLGMpfSwKeW46ZnVuY3Rpb24oYSxiKXty
-ZXR1cm4gdGhpcy5OaihhLGIsbnVsbCl9LApoYzpmdW5jdGlvbihhKXtyZXR1cm4gYS50b0xvd2VyQ2Fz
-ZSgpfSwKYlM6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9YS50cmltKCksbz1wLmxlbmd0aAppZihvPT09
-MClyZXR1cm4gcAppZih0aGlzLlcocCwwKT09PTEzMyl7cz1KLm1tKHAsMSkKaWYocz09PW8pcmV0dXJu
-IiJ9ZWxzZSBzPTAKcj1vLTEKcT10aGlzLk8yKHAscik9PT0xMzM/Si5jMShwLHIpOm8KaWYocz09PTAm
-JnE9PT1vKXJldHVybiBwCnJldHVybiBwLnN1YnN0cmluZyhzLHEpfSwKVDpmdW5jdGlvbihhLGIpe3Zh
-ciBzLHIKaWYoMD49YilyZXR1cm4iIgppZihiPT09MXx8YS5sZW5ndGg9PT0wKXJldHVybiBhCmlmKGIh
-PT1iPj4+MCl0aHJvdyBILmIoQy5FcSkKZm9yKHM9YSxyPSIiOyEwOyl7aWYoKGImMSk9PT0xKXI9cyty
-CmI9Yj4+PjEKaWYoYj09PTApYnJlYWsKcys9c31yZXR1cm4gcn0sClhVOmZ1bmN0aW9uKGEsYixjKXt2
-YXIgcwppZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYywwLGEubGVuZ3RoLG51bGwsbnVs
-bCkpCnM9YS5pbmRleE9mKGIsYykKcmV0dXJuIHN9LApPWTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlz
-LlhVKGEsYiwwKX0sClBrOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyCmlmKGM9PW51bGwpYz1hLmxlbmd0
-aAplbHNlIGlmKGM8MHx8Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxu
-dWxsKSkKcz1iLmxlbmd0aApyPWEubGVuZ3RoCmlmKGMrcz5yKWM9ci1zCnJldHVybiBhLmxhc3RJbmRl
-eE9mKGIsYyl9LApjbjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlBrKGEsYixudWxsKX0sCklzOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgcz1hLmxlbmd0aAppZihjPnMpdGhyb3cgSC5iKFAuVEUoYywwLHMsbnVs
-bCxudWxsKSkKcmV0dXJuIEguU1EoYSxiLGMpfSwKdGc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5J
-cyhhLGIsMCl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzLHIs
-cQpmb3Iocz1hLmxlbmd0aCxyPTAscT0wO3E8czsrK3Epe3I9cithLmNoYXJDb2RlQXQocSkmNTM2ODcw
-OTExCnI9cisoKHImNTI0Mjg3KTw8MTApJjUzNjg3MDkxMQpyXj1yPj42fXI9cisoKHImNjcxMDg4NjMp
-PDwzKSY1MzY4NzA5MTEKcl49cj4+MTEKcmV0dXJuIHIrKChyJjE2MzgzKTw8MTUpJjUzNjg3MDkxMX0s
-CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCmlm
-KGI+PWEubGVuZ3RofHwhMSl0aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYVtiXX0sCiRpdlg6MSwK
-JGlxVToxfQpILkJSLnByb3RvdHlwZT17CmdtOmZ1bmN0aW9uKGEpe3ZhciBzPUguTGgodGhpcykKcmV0
-dXJuIG5ldyBILkU3KEouSVQodGhpcy5nT04oKSkscy5DKCJAPDE+IikuS3Eocy5RWzFdKS5DKCJFNzwx
-LDI+IikpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIEouSG0odGhpcy5nT04oKSl9LApnbDA6ZnVuY3Rp
-b24oYSl7cmV0dXJuIEoudVUodGhpcy5nT04oKSl9LApnb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIEouRjco
-dGhpcy5nT04oKSl9LAplUjpmdW5jdGlvbihhLGIpe3ZhciBzPUguTGgodGhpcykKcmV0dXJuIEguR0oo
-Si5BNSh0aGlzLmdPTigpLGIpLHMuYyxzLlFbMV0pfSwKRTpmdW5jdGlvbihhLGIpe3JldHVybiBILkxo
-KHRoaXMpLlFbMV0uYShKLkdBKHRoaXMuZ09OKCksYikpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gSi5q
-KHRoaXMuZ09OKCkpfX0KSC5FNy5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5G
-KCl9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLiR0aS5RWzFdLmEodGhpcy5hLmdsKCkpfSwKJGlB
-bjoxfQpILlp5LnByb3RvdHlwZT17CmdPTjpmdW5jdGlvbigpe3JldHVybiB0aGlzLmF9fQpILm9sLnBy
-b3RvdHlwZT17JGliUToxfQpILlVxLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhp
-cy4kdGkuUVsxXS5hKEoueDkodGhpcy5hLEgudVAoYikpKX0sClk1OmZ1bmN0aW9uKGEsYixjKXt2YXIg
-cz10aGlzLiR0aQpKLnU5KHRoaXMuYSxiLHMuYy5hKHMuUVsxXS5hKGMpKSl9LAokaWJROjEsCiRpek06
-MX0KSC5qVi5wcm90b3R5cGU9ewpkcjpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5qVih0aGlzLmEs
-dGhpcy4kdGkuQygiQDwxPiIpLktxKGIpLkMoImpWPDEsMj4iKSl9LApnT046ZnVuY3Rpb24oKXtyZXR1
-cm4gdGhpcy5hfX0KSC5uLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVy
-biBzIT1udWxsPyJMYXRlSW5pdGlhbGl6YXRpb25FcnJvcjogIitzOiJMYXRlSW5pdGlhbGl6YXRpb25F
-cnJvciJ9fQpILnIzLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9IlJlYWNoYWJpbGl0eUVy
-cm9yOiAiK3RoaXMuYQpyZXR1cm4gc319CkgucWoucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0
-dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEMueEIuTzIodGhpcy5hLEgu
-dVAoYikpfX0KSC5HTS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJOdWxsIGlzIG5vdCBh
-IHZhbGlkIHZhbHVlIGZvciB0aGUgcGFyYW1ldGVyICciK3RoaXMuYSsiJyBvZiB0eXBlICciK0guS3go
-dGhpcy4kdGkuYykudygwKSsiJyJ9fQpILmJRLnByb3RvdHlwZT17fQpILmFMLnByb3RvdHlwZT17Cmdt
-OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKcmV0dXJuIG5ldyBILmE3KHMscy5nQShzKSxILkxoKHMpLkMo
-ImE3PGFMLkU+IikpfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdBKHRoaXMpPT09MH0sCms6
-ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscD10aGlzLG89cC5nQShwKQppZihiLmxlbmd0aCE9PTApe2lm
-KG89PT0wKXJldHVybiIiCnM9SC5FaihwLkUoMCwwKSkKaWYobyE9PXAuZ0EocCkpdGhyb3cgSC5iKFAu
-YTQocCkpCmZvcihyPXMscT0xO3E8bzsrK3Epe3I9citiK0guRWoocC5FKDAscSkpCmlmKG8hPT1wLmdB
-KHApKXRocm93IEguYihQLmE0KHApKX1yZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn1lbHNle2Zv
-cihxPTAscj0iIjtxPG87KytxKXtyKz1ILkVqKHAuRSgwLHEpKQppZihvIT09cC5nQShwKSl0aHJvdyBI
-LmIoUC5hNChwKSl9cmV0dXJuIHIuY2hhckNvZGVBdCgwKT09MD9yOnJ9fSwKZXY6ZnVuY3Rpb24oYSxi
-KXtyZXR1cm4gdGhpcy5HRygwLEguTGgodGhpcykuQygiYTIoYUwuRSkiKS5hKGIpKX0sCkUyOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgcz1ILkxoKHRoaXMpCnJldHVybiBuZXcgSC5sSih0aGlzLHMuS3EoYykuQygi
-MShhTC5FKSIpLmEoYikscy5DKCJAPGFMLkU+IikuS3EoYykuQygibEo8MSwyPiIpKX0sCmVSOmZ1bmN0
-aW9uKGEsYil7cmV0dXJuIEgucUModGhpcyxiLG51bGwsSC5MaCh0aGlzKS5DKCJhTC5FIikpfSwKdHQ6
-ZnVuY3Rpb24oYSxiKXtyZXR1cm4gUC5ZMSh0aGlzLCEwLEguTGgodGhpcykuQygiYUwuRSIpKX0sCmJy
-OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnR0KGEsITApfX0KSC5uSC5wcm90b3R5cGU9ewpIZDpmdW5j
-dGlvbihhLGIsYyxkKXt2YXIgcyxyPXRoaXMuYgpQLmsxKHIsInN0YXJ0IikKcz10aGlzLmMKaWYocyE9
-bnVsbCl7UC5rMShzLCJlbmQiKQppZihyPnMpdGhyb3cgSC5iKFAuVEUociwwLHMsInN0YXJ0IixudWxs
-KSl9fSwKZ1VEOmZ1bmN0aW9uKCl7dmFyIHM9Si5IbSh0aGlzLmEpLHI9dGhpcy5jCmlmKHI9PW51bGx8
-fHI+cylyZXR1cm4gcwpyZXR1cm4gcn0sCmdBczpmdW5jdGlvbigpe3ZhciBzPUouSG0odGhpcy5hKSxy
-PXRoaXMuYgppZihyPnMpcmV0dXJuIHMKcmV0dXJuIHJ9LApnQTpmdW5jdGlvbihhKXt2YXIgcyxyPUou
-SG0odGhpcy5hKSxxPXRoaXMuYgppZihxPj1yKXJldHVybiAwCnM9dGhpcy5jCmlmKHM9PW51bGx8fHM+
-PXIpcmV0dXJuIHItcQppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkhOKCkKcmV0dXJuIHMt
-cX0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgcz10aGlzLHI9cy5nQXMoKStiCmlmKGI8MHx8cj49cy5nVUQo
-KSl0aHJvdyBILmIoUC5DZihiLHMsImluZGV4IixudWxsLG51bGwpKQpyZXR1cm4gSi5HQShzLmEscil9
-LAplUjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT10aGlzClAuazEoYiwiY291bnQiKQpzPXEuYitiCnI9
-cS5jCmlmKHIhPW51bGwmJnM+PXIpcmV0dXJuIG5ldyBILk1CKHEuJHRpLkMoIk1CPDE+IikpCnJldHVy
-biBILnFDKHEuYSxzLHIscS4kdGkuYyl9LAp0dDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwPXRoaXMs
-bz1wLmIsbj1wLmEsbT1KLlU2KG4pLGw9bS5nQShuKSxrPXAuYwppZihrIT1udWxsJiZrPGwpbD1rCmlm
-KHR5cGVvZiBsIT09Im51bWJlciIpcmV0dXJuIGwuSE4oKQpzPWwtbwppZihzPD0wKXtuPUouUWkoMCxw
-LiR0aS5jKQpyZXR1cm4gbn1yPVAuTzgocyxtLkUobixvKSwhMSxwLiR0aS5jKQpmb3IocT0xO3E8czsr
-K3Epe0MuTm0uWTUocixxLG0uRShuLG8rcSkpCmlmKG0uZ0Eobik8bCl0aHJvdyBILmIoUC5hNChwKSl9
-cmV0dXJuIHJ9fQpILmE3LnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6
-ZnVuY3Rpb24oKXt2YXIgcyxyPXRoaXMscT1yLmEscD1KLlU2KHEpLG89cC5nQShxKQppZihyLmIhPT1v
-KXRocm93IEguYihQLmE0KHEpKQpzPXIuYwppZihzPj1vKXtyLnNJKG51bGwpCnJldHVybiExfXIuc0ko
-cC5FKHEscykpOysrci5jCnJldHVybiEwfSwKc0k6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLkMo
-IjE/IikuYShhKX0sCiRpQW46MX0KSC5pMS5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXt2YXIgcz1I
-LkxoKHRoaXMpCnJldHVybiBuZXcgSC5NSChKLklUKHRoaXMuYSksdGhpcy5iLHMuQygiQDwxPiIpLktx
-KHMuUVsxXSkuQygiTUg8MSwyPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBKLkhtKHRoaXMuYSl9
-LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIEoudVUodGhpcy5hKX0sCkU6ZnVuY3Rpb24oYSxiKXtyZXR1
-cm4gdGhpcy5iLiQxKEouR0EodGhpcy5hLGIpKX19CkgueHkucHJvdG90eXBlPXskaWJROjF9CkguTUgu
-cHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciBzPXRoaXMscj1zLmIKaWYoci5GKCkpe3Muc0kocy5j
-LiQxKHIuZ2woKSkpCnJldHVybiEwfXMuc0kobnVsbCkKcmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3Jl
-dHVybiB0aGlzLmF9LApzSTpmdW5jdGlvbihhKXt0aGlzLmE9dGhpcy4kdGkuQygiMj8iKS5hKGEpfX0K
-SC5sSi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gSi5IbSh0aGlzLmEpfSwKRTpmdW5j
-dGlvbihhLGIpe3JldHVybiB0aGlzLmIuJDEoSi5HQSh0aGlzLmEsYikpfX0KSC5VNS5wcm90b3R5cGU9
-ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguU08oSi5JVCh0aGlzLmEpLHRoaXMuYix0aGlzLiR0
-aS5DKCJTTzwxPiIpKX19CkguU08ucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciBzLHIKZm9yKHM9
-dGhpcy5hLHI9dGhpcy5iO3MuRigpOylpZihILm9UKHIuJDEocy5nbCgpKSkpcmV0dXJuITAKcmV0dXJu
-ITF9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmEuZ2woKX19CkguQU0ucHJvdG90eXBlPXsKZVI6
-ZnVuY3Rpb24oYSxiKXtQLk1SKGIsImNvdW50Iix0LlMpClAuazEoYiwiY291bnQiKQpyZXR1cm4gbmV3
-IEguQU0odGhpcy5hLHRoaXMuYitiLEguTGgodGhpcykuQygiQU08MT4iKSl9LApnbTpmdW5jdGlvbihh
-KXtyZXR1cm4gbmV3IEguVTEoSi5JVCh0aGlzLmEpLHRoaXMuYixILkxoKHRoaXMpLkMoIlUxPDE+Iikp
-fX0KSC5kNS5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXt2YXIgcz1KLkhtKHRoaXMuYSktdGhpcy5i
-CmlmKHM+PTApcmV0dXJuIHMKcmV0dXJuIDB9LAplUjpmdW5jdGlvbihhLGIpe1AuTVIoYiwiY291bnQi
-LHQuUykKUC5rMShiLCJjb3VudCIpCnJldHVybiBuZXcgSC5kNSh0aGlzLmEsdGhpcy5iK2IsdGhpcy4k
-dGkpfSwKJGliUToxfQpILlUxLnByb3RvdHlwZT17CkY6ZnVuY3Rpb24oKXt2YXIgcyxyCmZvcihzPXRo
-aXMuYSxyPTA7cjx0aGlzLmI7KytyKXMuRigpCnRoaXMuYj0wCnJldHVybiBzLkYoKX0sCmdsOmZ1bmN0
-aW9uKCl7cmV0dXJuIHRoaXMuYS5nbCgpfX0KSC5NQi5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXty
-ZXR1cm4gQy5Hd30sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCmdBOmZ1bmN0aW9uKGEpe3JldHVy
-biAwfSwKRTpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLlRFKGIsMCwwLCJpbmRleCIsbnVsbCkpfSwK
-ZVI6ZnVuY3Rpb24oYSxiKXtQLmsxKGIsImNvdW50IikKcmV0dXJuIHRoaXN9fQpILkZ1LnByb3RvdHlw
-ZT17CkY6ZnVuY3Rpb24oKXtyZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7dGhyb3cgSC5iKEguV3AoKSl9
-LAokaUFuOjF9CkgudTYucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILkpCKEou
-SVQodGhpcy5hKSx0aGlzLiR0aS5DKCJKQjwxPiIpKX19CkguSkIucHJvdG90eXBlPXsKRjpmdW5jdGlv
-bigpe3ZhciBzLHIKZm9yKHM9dGhpcy5hLHI9dGhpcy4kdGkuYztzLkYoKTspaWYoci5iKHMuZ2woKSkp
-cmV0dXJuITAKcmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLiR0aS5jLmEodGhpcy5h
-LmdsKCkpfSwKJGlBbjoxfQpILlNVLnByb3RvdHlwZT17fQpILlJlLnByb3RvdHlwZT17Clk1OmZ1bmN0
-aW9uKGEsYixjKXtILkxoKHRoaXMpLkMoIlJlLkUiKS5hKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3Qg
-bW9kaWZ5IGFuIHVubW9kaWZpYWJsZSBsaXN0IikpfX0KSC53Mi5wcm90b3R5cGU9e30KSC53di5wcm90
-b3R5cGU9ewpnaU86ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5faGFzaENvZGUKaWYocyE9bnVsbClyZXR1
-cm4gcwpzPTY2NDU5NypKLmhmKHRoaXMuYSkmNTM2ODcwOTExCnRoaXMuX2hhc2hDb2RlPXMKcmV0dXJu
-IHN9LAp3OmZ1bmN0aW9uKGEpe3JldHVybidTeW1ib2woIicrSC5Faih0aGlzLmEpKyciKSd9LApETjpm
-dW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBILnd2JiZ0
-aGlzLmE9PWIuYX0sCiRpR0Q6MX0KSC5RQy5wcm90b3R5cGU9e30KSC5QRC5wcm90b3R5cGU9e30KSC5X
-VS5wcm90b3R5cGU9ewpnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ0EodGhpcyk9PT0wfSwKdzpm
-dW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sClk1OmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1ILkxo
-KHRoaXMpCnMuYy5hKGIpCnMuUVsxXS5hKGMpCkguZGMoKQpILkJpKHUuZyl9LApnUHU6ZnVuY3Rpb24o
-YSl7cmV0dXJuIHRoaXMucTQoYSxILkxoKHRoaXMpLkMoIk4zPDEsMj4iKSl9LApxNDpmdW5jdGlvbihh
-LGIpe3ZhciBzPXRoaXMKcmV0dXJuIFAubDAoZnVuY3Rpb24oKXt2YXIgcj1hCnZhciBxPTAscD0xLG8s
-bixtLGwsawpyZXR1cm4gZnVuY3Rpb24gJGFzeW5jJGdQdShjLGQpe2lmKGM9PT0xKXtvPWQKcT1wfXdo
-aWxlKHRydWUpc3dpdGNoKHEpe2Nhc2UgMDpuPXMuZ3ZjKCksbj1uLmdtKG4pLG09SC5MaChzKSxtPW0u
-QygiQDwxPiIpLktxKG0uUVsxXSkuQygiTjM8MSwyPiIpCmNhc2UgMjppZighbi5GKCkpe3E9MwpicmVh
-a31sPW4uZ2woKQprPXMucSgwLGwpCmsudG9TdHJpbmcKcT00CnJldHVybiBuZXcgUC5OMyhsLGssbSkK
-Y2FzZSA0OnE9MgpicmVhawpjYXNlIDM6cmV0dXJuIFAuVGgoKQpjYXNlIDE6cmV0dXJuIFAuWW0obyl9
-fX0sYil9LAokaVowOjF9CkguTFAucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
-YX0sCng0OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhIT0ic3RyaW5nIilyZXR1cm4hMQppZigiX19wcm90
-b19fIj09PWEpcmV0dXJuITEKcmV0dXJuIHRoaXMuYi5oYXNPd25Qcm9wZXJ0eShhKX0sCnE6ZnVuY3Rp
-b24oYSxiKXtpZighdGhpcy54NChiKSlyZXR1cm4gbnVsbApyZXR1cm4gdGhpcy5xUChiKX0sCnFQOmZ1
-bmN0aW9uKGEpe3JldHVybiB0aGlzLmJbSC5oKGEpXX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEs
-cCxvPUguTGgodGhpcykKby5DKCJ+KDEsMikiKS5hKGIpCnM9dGhpcy5jCmZvcihyPXMubGVuZ3RoLG89
-by5RWzFdLHE9MDtxPHI7KytxKXtwPXNbcV0KYi4kMihwLG8uYSh0aGlzLnFQKHApKSl9fSwKZ3ZjOmZ1
-bmN0aW9uKCl7cmV0dXJuIG5ldyBILlhSKHRoaXMsSC5MaCh0aGlzKS5DKCJYUjwxPiIpKX19CkguWFIu
-cHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hLmMKcmV0dXJuIG5ldyBKLm0xKHMs
-cy5sZW5ndGgsSC50NihzKS5DKCJtMTwxPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEu
-Yy5sZW5ndGh9fQpILkxJLnByb3RvdHlwZT17CmdXYTpmdW5jdGlvbigpe3ZhciBzPXRoaXMuYQpyZXR1
-cm4gc30sCmduZDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89dGhpcwppZihvLmM9PT0xKXJldHVybiBD
-LmhVCnM9by5kCnI9cy5sZW5ndGgtby5lLmxlbmd0aC1vLmYKaWYocj09PTApcmV0dXJuIEMuaFUKcT1b
-XQpmb3IocD0wO3A8cjsrK3Ape2lmKHA+PXMubGVuZ3RoKXJldHVybiBILk9IKHMscCkKcS5wdXNoKHNb
-cF0pfXJldHVybiBKLnpDKHEpfSwKZ1ZtOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG0sbCxrPXRo
-aXMKaWYoay5jIT09MClyZXR1cm4gQy5XTwpzPWsuZQpyPXMubGVuZ3RoCnE9ay5kCnA9cS5sZW5ndGgt
-ci1rLmYKaWYocj09PTApcmV0dXJuIEMuV08Kbz1uZXcgSC5ONSh0LmVvKQpmb3Iobj0wO248cjsrK24p
-e2lmKG4+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsbikKbT1zW25dCmw9cCtuCmlmKGw8MHx8bD49cS5s
-ZW5ndGgpcmV0dXJuIEguT0gocSxsKQpvLlk1KDAsbmV3IEgud3YobSkscVtsXSl9cmV0dXJuIG5ldyBI
-LlBEKG8sdC5nRil9LAokaXZROjF9CkguQ2oucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIg
-cwpILmgoYSkKcz10aGlzLmEKcy5iPXMuYisiJCIrSC5FaihhKQpDLk5tLmkodGhpcy5iLGEpCkMuTm0u
-aSh0aGlzLmMsYik7KytzLmF9LAokUzoxMn0KSC5mOS5wcm90b3R5cGU9ewpxUzpmdW5jdGlvbihhKXt2
-YXIgcyxyLHE9dGhpcyxwPW5ldyBSZWdFeHAocS5hKS5leGVjKGEpCmlmKHA9PW51bGwpcmV0dXJuIG51
-bGwKcz1PYmplY3QuY3JlYXRlKG51bGwpCnI9cS5iCmlmKHIhPT0tMSlzLmFyZ3VtZW50cz1wW3IrMV0K
-cj1xLmMKaWYociE9PS0xKXMuYXJndW1lbnRzRXhwcj1wW3IrMV0Kcj1xLmQKaWYociE9PS0xKXMuZXhw
-cj1wW3IrMV0Kcj1xLmUKaWYociE9PS0xKXMubWV0aG9kPXBbcisxXQpyPXEuZgppZihyIT09LTEpcy5y
-ZWNlaXZlcj1wW3IrMV0KcmV0dXJuIHN9fQpILlcwLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFy
-IHM9dGhpcy5iCmlmKHM9PW51bGwpcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiAiK0guRWoodGhpcy5h
-KQpyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciK3MrIicgb24gbnVs
-bCJ9fQpILmF6LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLHE9Ik5vU3VjaE1l
-dGhvZEVycm9yOiBtZXRob2Qgbm90IGZvdW5kOiAnIixwPXIuYgppZihwPT1udWxsKXJldHVybiJOb1N1
-Y2hNZXRob2RFcnJvcjogIitILkVqKHIuYSkKcz1yLmMKaWYocz09bnVsbClyZXR1cm4gcStwKyInICgi
-K0guRWooci5hKSsiKSIKcmV0dXJuIHErcCsiJyBvbiAnIitzKyInICgiK0guRWooci5hKSsiKSJ9fQpI
-LnZWLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVybiBzLmxlbmd0aD09
-PTA/IkVycm9yIjoiRXJyb3I6ICIrc319CkgudGUucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1
-cm4iVGhyb3cgb2YgbnVsbCAoJyIrKHRoaXMuYT09PW51bGw/Im51bGwiOiJ1bmRlZmluZWQiKSsiJyBm
-cm9tIEphdmFTY3JpcHQpIn0sCiRpUno6MX0KSC5icS5wcm90b3R5cGU9e30KSC5YTy5wcm90b3R5cGU9
-ewp3OmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcy5iCmlmKHIhPW51bGwpcmV0dXJuIHIKcj10aGlzLmEK
-cz1yIT09bnVsbCYmdHlwZW9mIHI9PT0ib2JqZWN0Ij9yLnN0YWNrOm51bGwKcmV0dXJuIHRoaXMuYj1z
-PT1udWxsPyIiOnN9LAokaUd6OjF9CkguVHAucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10
-aGlzLmNvbnN0cnVjdG9yLHI9cz09bnVsbD9udWxsOnMubmFtZQpyZXR1cm4iQ2xvc3VyZSAnIitILk5R
-KHI9PW51bGw/InVua25vd24iOnIpKyInIn0sCiRpRUg6MSwKZ0t1OmZ1bmN0aW9uKCl7cmV0dXJuIHRo
-aXN9LAokQzoiJDEiLAokUjoxLAokRDpudWxsfQpILmxjLnByb3RvdHlwZT17fQpILnp4LnByb3RvdHlw
-ZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy4kc3RhdGljX25hbWUKaWYocz09bnVsbClyZXR1cm4i
-Q2xvc3VyZSBvZiB1bmtub3duIHN0YXRpYyBtZXRob2QiCnJldHVybiJDbG9zdXJlICciK0guTlEocykr
-IicifX0KSC5yVC5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMKaWYoYj09bnVs
-bClyZXR1cm4hMQppZihzPT09YilyZXR1cm4hMAppZighKGIgaW5zdGFuY2VvZiBILnJUKSlyZXR1cm4h
-MQpyZXR1cm4gcy5hPT09Yi5hJiZzLmI9PT1iLmImJnMuYz09PWIuY30sCmdpTzpmdW5jdGlvbihhKXt2
-YXIgcyxyPXRoaXMuYwppZihyPT1udWxsKXM9SC5lUSh0aGlzLmEpCmVsc2Ugcz10eXBlb2YgciE9PSJv
-YmplY3QiP0ouaGYocik6SC5lUShyKQpyPUguZVEodGhpcy5iKQppZih0eXBlb2YgcyE9PSJudW1iZXIi
-KXJldHVybiBzLlkoKQpyZXR1cm4oc15yKT4+PjB9LAp3OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYwpp
-ZihzPT1udWxsKXM9dGhpcy5hCnJldHVybiJDbG9zdXJlICciK0guRWoodGhpcy5kKSsiJyBvZiAiKygi
-SW5zdGFuY2Ugb2YgJyIrSC5FaihILk0ocykpKyInIil9fQpILkVxLnByb3RvdHlwZT17Cnc6ZnVuY3Rp
-b24oYSl7cmV0dXJuIlJ1bnRpbWVFcnJvcjogIit0aGlzLmF9fQpILmtZLnByb3RvdHlwZT17Cnc6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIkFzc2VydGlvbiBmYWlsZWQ6ICIrUC5wKHRoaXMuYSl9fQpILmtyLnByb3Rv
-dHlwZT17fQpILk41LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LApnbDA6
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYT09PTB9LApndmM6ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEgu
-aTUodGhpcyxILkxoKHRoaXMpLkMoImk1PDE+IikpfSwKeDQ6ZnVuY3Rpb24oYSl7dmFyIHMscgppZih0
-eXBlb2YgYT09InN0cmluZyIpe3M9dGhpcy5iCmlmKHM9PW51bGwpcmV0dXJuITEKcmV0dXJuIHRoaXMu
-WHUocyxhKX1lbHNle3I9dGhpcy5DWChhKQpyZXR1cm4gcn19LApDWDpmdW5jdGlvbihhKXt2YXIgcz10
-aGlzLmQKaWYocz09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5GaCh0aGlzLkJ0KHMsSi5oZihhKSYw
-eDNmZmZmZmYpLGEpPj0wfSwKcTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG89dGhpcyxuPW51bGwK
-aWYodHlwZW9mIGI9PSJzdHJpbmciKXtzPW8uYgppZihzPT1udWxsKXJldHVybiBuCnI9by5qMihzLGIp
-CnE9cj09bnVsbD9uOnIuYgpyZXR1cm4gcX1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMHgz
-ZmZmZmZmKT09PWIpe3A9by5jCmlmKHA9PW51bGwpcmV0dXJuIG4Kcj1vLmoyKHAsYikKcT1yPT1udWxs
-P246ci5iCnJldHVybiBxfWVsc2UgcmV0dXJuIG8uYWEoYil9LAphYTpmdW5jdGlvbihhKXt2YXIgcyxy
-LHE9dGhpcy5kCmlmKHE9PW51bGwpcmV0dXJuIG51bGwKcz10aGlzLkJ0KHEsSi5oZihhKSYweDNmZmZm
-ZmYpCnI9dGhpcy5GaChzLGEpCmlmKHI8MClyZXR1cm4gbnVsbApyZXR1cm4gc1tyXS5ifSwKWTU6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbixtPXRoaXMsbD1ILkxoKG0pCmwuYy5hKGIpCmwuUVsx
-XS5hKGMpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7cz1tLmIKbS5FSChzPT1udWxsP20uYj1tLnpLKCk6
-cyxiLGMpfWVsc2UgaWYodHlwZW9mIGI9PSJudW1iZXIiJiYoYiYweDNmZmZmZmYpPT09Yil7cj1tLmMK
-bS5FSChyPT1udWxsP20uYz1tLnpLKCk6cixiLGMpfWVsc2V7cT1tLmQKaWYocT09bnVsbClxPW0uZD1t
-LnpLKCkKcD1KLmhmKGIpJjB4M2ZmZmZmZgpvPW0uQnQocSxwKQppZihvPT1udWxsKW0uRUkocSxwLFtt
-LkhuKGIsYyldKQplbHNle249bS5GaChvLGIpCmlmKG4+PTApb1tuXS5iPWMKZWxzZSBvLnB1c2gobS5I
-bihiLGMpKX19fSwKSzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT10aGlzCkguTGgocSkuQygifigxLDIp
-IikuYShiKQpzPXEuZQpyPXEucgpmb3IoO3MhPW51bGw7KXtiLiQyKHMuYSxzLmIpCmlmKHIhPT1xLnIp
-dGhyb3cgSC5iKFAuYTQocSkpCnM9cy5jfX0sCkVIOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPXRoaXMs
-cT1ILkxoKHIpCnEuYy5hKGIpCnEuUVsxXS5hKGMpCnM9ci5qMihhLGIpCmlmKHM9PW51bGwpci5FSShh
-LGIsci5IbihiLGMpKQplbHNlIHMuYj1jfSwKa3M6ZnVuY3Rpb24oKXt0aGlzLnI9dGhpcy5yKzEmNjcx
-MDg4NjN9LApIbjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMscj1ILkxoKHMpLHE9bmV3IEgudmgoci5j
-LmEoYSksci5RWzFdLmEoYikpCmlmKHMuZT09bnVsbClzLmU9cy5mPXEKZWxzZXtyPXMuZgpyLnRvU3Ry
-aW5nCnEuZD1yCnMuZj1yLmM9cX0rK3MuYQpzLmtzKCkKcmV0dXJuIHF9LApGaDpmdW5jdGlvbihhLGIp
-e3ZhciBzLHIKaWYoYT09bnVsbClyZXR1cm4tMQpzPWEubGVuZ3RoCmZvcihyPTA7cjxzOysrcilpZihK
-LlJNKGFbcl0uYSxiKSlyZXR1cm4gcgpyZXR1cm4tMX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAubk8o
-dGhpcyl9LApqMjpmdW5jdGlvbihhLGIpe3JldHVybiBhW2JdfSwKQnQ6ZnVuY3Rpb24oYSxiKXtyZXR1
-cm4gYVtiXX0sCkVJOmZ1bmN0aW9uKGEsYixjKXthW2JdPWN9LApybjpmdW5jdGlvbihhLGIpe2RlbGV0
-ZSBhW2JdfSwKWHU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5qMihhLGIpIT1udWxsfSwKeks6ZnVu
-Y3Rpb24oKXt2YXIgcz0iPG5vbi1pZGVudGlmaWVyLWtleT4iLHI9T2JqZWN0LmNyZWF0ZShudWxsKQp0
-aGlzLkVJKHIscyxyKQp0aGlzLnJuKHIscykKcmV0dXJuIHJ9LAokaUZvOjF9CkgudmgucHJvdG90eXBl
-PXt9CkguaTUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5hfSwKZ2wwOmZ1
-bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYT09PTB9LApnbTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEs
-cj1uZXcgSC5ONihzLHMucix0aGlzLiR0aS5DKCJONjwxPiIpKQpyLmM9cy5lCnJldHVybiByfSwKdGc6
-ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLng0KGIpfX0KSC5ONi5wcm90b3R5cGU9ewpnbDpmdW5j
-dGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHMscj10aGlzLHE9ci5hCmlmKHIu
-YiE9PXEucil0aHJvdyBILmIoUC5hNChxKSkKcz1yLmMKaWYocz09bnVsbCl7ci5zcVkobnVsbCkKcmV0
-dXJuITF9ZWxzZXtyLnNxWShzLmEpCnIuYz1zLmMKcmV0dXJuITB9fSwKc3FZOmZ1bmN0aW9uKGEpe3Ro
-aXMuZD10aGlzLiR0aS5DKCIxPyIpLmEoYSl9LAokaUFuOjF9CkguZEMucHJvdG90eXBlPXsKJDE6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIHRoaXMuYShhKX0sCiRTOjR9Ckgud04ucHJvdG90eXBlPXsKJDI6ZnVuY3Rp
-b24oYSxiKXtyZXR1cm4gdGhpcy5hKGEsYil9LAokUzo0Nn0KSC5WWC5wcm90b3R5cGU9ewokMTpmdW5j
-dGlvbihhKXtyZXR1cm4gdGhpcy5hKEguaChhKSl9LAokUzo0MX0KSC5WUi5wcm90b3R5cGU9ewp3OmZ1
-bmN0aW9uKGEpe3JldHVybiJSZWdFeHAvIit0aGlzLmErIi8iK3RoaXMuYi5mbGFnc30sCmdIYzpmdW5j
-dGlvbigpe3ZhciBzPXRoaXMscj1zLmMKaWYociE9bnVsbClyZXR1cm4gcgpyPXMuYgpyZXR1cm4gcy5j
-PUgudjQocy5hLHIubXVsdGlsaW5lLCFyLmlnbm9yZUNhc2Usci51bmljb2RlLHIuZG90QWxsLCEwKX0s
-CmRkOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILktXKHRoaXMsYiwwKX0sClVaOmZ1bmN0aW9uKGEs
-Yil7dmFyIHMscj10aGlzLmdIYygpCnIubGFzdEluZGV4PWIKcz1yLmV4ZWMoYSkKaWYocz09bnVsbCly
-ZXR1cm4gbnVsbApyZXR1cm4gbmV3IEguRUsocyl9LAokaXZYOjEsCiRpd0w6MX0KSC5FSy5wcm90b3R5
-cGU9ewpxOmZ1bmN0aW9uKGEsYil7dmFyIHMKSC51UChiKQpzPXRoaXMuYgppZihiPj1zLmxlbmd0aCly
-ZXR1cm4gSC5PSChzLGIpCnJldHVybiBzW2JdfSwKJGlPZDoxLAokaWliOjF9CkguS1cucHJvdG90eXBl
-PXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlBiKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19Ckgu
-UGIucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3Zh
-ciBzLHIscSxwLG8sbixtPXRoaXMsbD1tLmIKaWYobD09bnVsbClyZXR1cm4hMQpzPW0uYwpyPWwubGVu
-Z3RoCmlmKHM8PXIpe3E9bS5hCnA9cS5VWihsLHMpCmlmKHAhPW51bGwpe20uZD1wCnM9cC5iCm89cy5p
-bmRleApuPW8rc1swXS5sZW5ndGgKaWYobz09PW4pe2lmKHEuYi51bmljb2RlKXtzPW0uYwpxPXMrMQpp
-ZihxPHIpe3M9Qy54Qi5PMihsLHMpCmlmKHM+PTU1Mjk2JiZzPD01NjMxOSl7cz1DLnhCLk8yKGwscSkK
-cz1zPj01NjMyMCYmczw9NTczNDN9ZWxzZSBzPSExfWVsc2Ugcz0hMX1lbHNlIHM9ITEKbj0ocz9uKzE6
-bikrMX1tLmM9bgpyZXR1cm4hMH19bS5iPW0uZD1udWxsCnJldHVybiExfSwKJGlBbjoxfQpILnRRLnBy
-b3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCmlmKGIhPT0wKUgudihQLk83KGIsbnVsbCkp
-CnJldHVybiB0aGlzLmN9LAokaU9kOjF9CkgudW4ucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0
-dXJuIG5ldyBILlNkKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19CkguU2QucHJvdG90eXBlPXsKRjpmdW5j
-dGlvbigpe3ZhciBzLHIscT10aGlzLHA9cS5jLG89cS5iLG49by5sZW5ndGgsbT1xLmEsbD1tLmxlbmd0
-aAppZihwK24+bCl7cS5kPW51bGwKcmV0dXJuITF9cz1tLmluZGV4T2YobyxwKQppZihzPDApe3EuYz1s
-KzEKcS5kPW51bGwKcmV0dXJuITF9cj1zK24KcS5kPW5ldyBILnRRKHMsbykKcS5jPXI9PT1xLmM/cisx
-OnIKcmV0dXJuITB9LApnbDpmdW5jdGlvbigpe3ZhciBzPXRoaXMuZApzLnRvU3RyaW5nCnJldHVybiBz
-fSwKJGlBbjoxfQpILkVULnByb3RvdHlwZT17JGlFVDoxLCRpQVM6MX0KSC5MWi5wcm90b3R5cGU9ewpn
-QTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LAokaVhqOjF9CkguRGcucHJvdG90eXBlPXsKcTpm
-dW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfSwKWTU6ZnVu
-Y3Rpb24oYSxiLGMpe0guR0goYykKSC5vZChiLGEsYS5sZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGlj
-WDoxLAokaXpNOjF9CkguUGcucHJvdG90eXBlPXsKWTU6ZnVuY3Rpb24oYSxiLGMpe0gudVAoYykKSC5v
-ZChiLGEsYS5sZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9CkgueGoucHJvdG90
-eXBlPXsKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2Jd
-fX0KSC5kRS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpILm9kKGIsYSxhLmxlbmd0
-aCkKcmV0dXJuIGFbYl19fQpILlpBLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgu
-b2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguZFQucHJvdG90eXBlPXsKcTpmdW5jdGlvbihh
-LGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5QcS5wcm90b3R5cGU9
-ewpxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpI
-LmVFLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24o
-YSxiKXtILnVQKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguVjYucHJvdG90eXBl
-PXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikK
-SC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfSwKJGlWNjoxLAokaW42OjF9CkguUkcucHJvdG90
-eXBlPXt9CkguVlAucHJvdG90eXBlPXt9CkguV0IucHJvdG90eXBlPXt9CkguWkcucHJvdG90eXBlPXt9
-CkguSmMucHJvdG90eXBlPXsKQzpmdW5jdGlvbihhKXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSx0
-aGlzLGEpfSwKS3E6ZnVuY3Rpb24oYSl7cmV0dXJuIEgudjUodi50eXBlVW5pdmVyc2UsdGhpcyxhKX19
-CkguRy5wcm90b3R5cGU9e30KSC5sWS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBILmRt
-KHRoaXMuYSxudWxsKX19Ckgua1MucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5h
-fX0KSC5pTS5wcm90b3R5cGU9e30KUC50aC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz10
-aGlzLmEscj1zLmEKcy5hPW51bGwKci4kMCgpfSwKJFM6OX0KUC5oYS5wcm90b3R5cGU9ewokMTpmdW5j
-dGlvbihhKXt2YXIgcyxyCnRoaXMuYS5hPXQuTS5hKGEpCnM9dGhpcy5iCnI9dGhpcy5jCnMuZmlyc3RD
-aGlsZD9zLnJlbW92ZUNoaWxkKHIpOnMuYXBwZW5kQ2hpbGQocil9LAokUzozNH0KUC5Wcy5wcm90b3R5
-cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS4kMCgpfSwKJEM6IiQwIiwKJFI6MCwKJFM6Mn0KUC5GdC5w
-cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS4kMCgpfSwKJEM6IiQwIiwKJFI6MCwKJFM6Mn0K
-UC5XMy5wcm90b3R5cGU9ewpDWTpmdW5jdGlvbihhLGIpe2lmKHNlbGYuc2V0VGltZW91dCE9bnVsbClz
-ZWxmLnNldFRpbWVvdXQoSC50UihuZXcgUC55SCh0aGlzLGIpLDApLGEpCmVsc2UgdGhyb3cgSC5iKFAu
-TDQoImBzZXRUaW1lb3V0KClgIG5vdCBmb3VuZC4iKSl9fQpQLnlILnByb3RvdHlwZT17CiQwOmZ1bmN0
-aW9uKCl7dGhpcy5iLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLmloLnByb3RvdHlwZT17CmFN
-OmZ1bmN0aW9uKGEsYil7dmFyIHMscj10aGlzLHE9ci4kdGkKcS5DKCIxLz8iKS5hKGIpCmlmKCFyLmIp
-ci5hLlhmKGIpCmVsc2V7cz1yLmEKaWYocS5DKCJiODwxPiIpLmIoYikpcy5jVShiKQplbHNlIHMuWDIo
-cS5jLmEoYikpfX0sCncwOmZ1bmN0aW9uKGEsYil7dmFyIHMKaWYoYj09bnVsbCliPVAudjAoYSkKcz10
-aGlzLmEKaWYodGhpcy5iKXMuWkwoYSxiKQplbHNlIHMuTmsoYSxiKX19ClAuV00ucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS4kMigwLGEpfSwKJFM6NTJ9ClAuU1gucHJvdG90eXBl
-PXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuJDIoMSxuZXcgSC5icShhLHQubC5hKGIpKSl9LAokQzoi
-JDIiLAokUjoyLAokUzoyNH0KUC5Hcy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYShI
-LnVQKGEpLGIpfSwKJFM6MjZ9ClAuRnkucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iSXRl
-cmF0aW9uTWFya2VyKCIrdGhpcy5iKyIsICIrSC5Faih0aGlzLmEpKyIpIn19ClAuR1YucHJvdG90eXBl
-PXsKZ2w6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLmMKaWYocz09bnVsbClyZXR1cm4gdGhpcy4kdGkuYy5h
-KHRoaXMuYikKcmV0dXJuIHMuZ2woKX0sCkY6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbT10aGlz
-CmZvcihzPW0uJHRpLkMoIkFuPDE+Iik7ITA7KXtyPW0uYwppZihyIT1udWxsKWlmKHIuRigpKXJldHVy
-biEwCmVsc2UgbS5zWDkobnVsbCkKcT1mdW5jdGlvbihhLGIsYyl7dmFyIGwsaz1iCndoaWxlKHRydWUp
-dHJ5e3JldHVybiBhKGssbCl9Y2F0Y2goail7bD1qCms9Y319KG0uYSwwLDEpCmlmKHEgaW5zdGFuY2Vv
-ZiBQLkZ5KXtwPXEuYgppZihwPT09Mil7bz1tLmQKaWYobz09bnVsbHx8by5sZW5ndGg9PT0wKXttLnNF
-QyhudWxsKQpyZXR1cm4hMX1pZigwPj1vLmxlbmd0aClyZXR1cm4gSC5PSChvLC0xKQptLmE9by5wb3Ao
-KQpjb250aW51ZX1lbHNle3I9cS5hCmlmKHA9PT0zKXRocm93IHIKZWxzZXtuPXMuYShKLklUKHIpKQpp
-ZihuIGluc3RhbmNlb2YgUC5HVil7cj1tLmQKaWYocj09bnVsbClyPW0uZD1bXQpDLk5tLmkocixtLmEp
-Cm0uYT1uLmEKY29udGludWV9ZWxzZXttLnNYOShuKQpjb250aW51ZX19fX1lbHNle20uc0VDKHEpCnJl
-dHVybiEwfX1yZXR1cm4hMX0sCnNFQzpmdW5jdGlvbihhKXt0aGlzLmI9dGhpcy4kdGkuQygiMT8iKS5h
-KGEpfSwKc1g5OmZ1bmN0aW9uKGEpe3RoaXMuYz10aGlzLiR0aS5DKCJBbjwxPj8iKS5hKGEpfSwKJGlB
-bjoxfQpQLnE0LnByb3RvdHlwZT17CmdtOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5HVih0aGlzLmEo
-KSx0aGlzLiR0aS5DKCJHVjwxPiIpKX19ClAuUGYucHJvdG90eXBlPXsKdzA6ZnVuY3Rpb24oYSxiKXt2
-YXIgcwpILmNiKGEsImVycm9yIix0LkspCnM9dGhpcy5hCmlmKHMuYSE9PTApdGhyb3cgSC5iKFAuUFYo
-IkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQppZihiPT1udWxsKWI9UC52MChhKQpzLk5rKGEsYil9
-LApwbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy53MChhLG51bGwpfX0KUC5aZi5wcm90b3R5cGU9ewph
-TTpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcy4kdGkKci5DKCIxLz8iKS5hKGIpCnM9dGhpcy5hCmlm
-KHMuYSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQpzLlhmKHIu
-QygiMS8iKS5hKGIpKX19ClAuRmUucHJvdG90eXBlPXsKSFI6ZnVuY3Rpb24oYSl7aWYoKHRoaXMuYyYx
-NSkhPT02KXJldHVybiEwCnJldHVybiB0aGlzLmIuYi5idih0LmFsLmEodGhpcy5kKSxhLmEsdC55LHQu
-Syl9LApLdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmUscj10LnoscT10LksscD10aGlzLiR0aS5DKCIy
-LyIpLG89dGhpcy5iLmIKaWYodC5hZy5iKHMpKXJldHVybiBwLmEoby5ycChzLGEuYSxhLmIscixxLHQu
-bCkpCmVsc2UgcmV0dXJuIHAuYShvLmJ2KHQuYkkuYShzKSxhLmEscixxKSl9fQpQLnZzLnByb3RvdHlw
-ZT17ClNxOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscD10aGlzLiR0aQpwLktxKGMpLkMoIjEvKDIp
-IikuYShhKQpzPSQuWDMKaWYocyE9PUMuTlUpe2MuQygiQDwwLz4iKS5LcShwLmMpLkMoIjEoMikiKS5h
-KGEpCmlmKGIhPW51bGwpYj1QLlZIKGIscyl9cj1uZXcgUC52cyhzLGMuQygidnM8MD4iKSkKcT1iPT1u
-dWxsPzE6Mwp0aGlzLnhmKG5ldyBQLkZlKHIscSxhLGIscC5DKCJAPDE+IikuS3EoYykuQygiRmU8MSwy
-PiIpKSkKcmV0dXJuIHJ9LApXNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNxKGEsbnVsbCxiKX0s
-ClFkOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPXRoaXMuJHRpCnIuS3EoYykuQygiMS8oMikiKS5hKGEp
-CnM9bmV3IFAudnMoJC5YMyxjLkMoInZzPDA+IikpCnRoaXMueGYobmV3IFAuRmUocywxOSxhLGIsci5D
-KCJAPDE+IikuS3EoYykuQygiRmU8MSwyPiIpKSkKcmV0dXJuIHN9LAp4ZjpmdW5jdGlvbihhKXt2YXIg
-cyxyPXRoaXMscT1yLmEKaWYocTw9MSl7YS5hPXQuRi5hKHIuYykKci5jPWF9ZWxzZXtpZihxPT09Mil7
-cz10LmMuYShyLmMpCnE9cy5hCmlmKHE8NCl7cy54ZihhKQpyZXR1cm59ci5hPXEKci5jPXMuY31QLlRr
-KG51bGwsbnVsbCxyLmIsdC5NLmEobmV3IFAuZGEocixhKSkpfX0sCmpROmZ1bmN0aW9uKGEpe3ZhciBz
-LHIscSxwLG8sbixtPXRoaXMsbD17fQpsLmE9YQppZihhPT1udWxsKXJldHVybgpzPW0uYQppZihzPD0x
-KXtyPXQuRi5hKG0uYykKbS5jPWEKaWYociE9bnVsbCl7cT1hLmEKZm9yKHA9YTtxIT1udWxsO3A9cSxx
-PW8pbz1xLmEKcC5hPXJ9fWVsc2V7aWYocz09PTIpe249dC5jLmEobS5jKQpzPW4uYQppZihzPDQpe24u
-alEoYSkKcmV0dXJufW0uYT1zCm0uYz1uLmN9bC5hPW0uTjgoYSkKUC5UayhudWxsLG51bGwsbS5iLHQu
-TS5hKG5ldyBQLm9RKGwsbSkpKX19LAphaDpmdW5jdGlvbigpe3ZhciBzPXQuRi5hKHRoaXMuYykKdGhp
-cy5jPW51bGwKcmV0dXJuIHRoaXMuTjgocyl9LApOODpmdW5jdGlvbihhKXt2YXIgcyxyLHEKZm9yKHM9
-YSxyPW51bGw7cyE9bnVsbDtyPXMscz1xKXtxPXMuYQpzLmE9cn1yZXR1cm4gcn0sCkhIOmZ1bmN0aW9u
-KGEpe3ZhciBzLHI9dGhpcyxxPXIuJHRpCnEuQygiMS8iKS5hKGEpCmlmKHEuQygiYjg8MT4iKS5iKGEp
-KWlmKHEuYihhKSlQLkE5KGEscikKZWxzZSBQLmszKGEscikKZWxzZXtzPXIuYWgoKQpxLmMuYShhKQpy
-LmE9NApyLmM9YQpQLkhaKHIscyl9fSwKWDI6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzCnIuJHRpLmMu
-YShhKQpzPXIuYWgoKQpyLmE9NApyLmM9YQpQLkhaKHIscyl9LApaTDpmdW5jdGlvbihhLGIpe3ZhciBz
-LHIscT10aGlzCnQubC5hKGIpCnM9cS5haCgpCnI9UC5UbChhLGIpCnEuYT04CnEuYz1yClAuSFoocSxz
-KX0sClhmOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuJHRpCnMuQygiMS8iKS5hKGEpCmlmKHMuQygiYjg8
-MT4iKS5iKGEpKXt0aGlzLmNVKGEpCnJldHVybn10aGlzLndVKHMuYy5hKGEpKX0sCndVOmZ1bmN0aW9u
-KGEpe3ZhciBzPXRoaXMKcy4kdGkuYy5hKGEpCnMuYT0xClAuVGsobnVsbCxudWxsLHMuYix0Lk0uYShu
-ZXcgUC5ydChzLGEpKSl9LApjVTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLHI9cy4kdGkKci5DKCJiODwx
-PiIpLmEoYSkKaWYoci5iKGEpKXtpZihhLmE9PT04KXtzLmE9MQpQLlRrKG51bGwsbnVsbCxzLmIsdC5N
-LmEobmV3IFAuS0YocyxhKSkpfWVsc2UgUC5BOShhLHMpCnJldHVybn1QLmszKGEscyl9LApOazpmdW5j
-dGlvbihhLGIpe3RoaXMuYT0xClAuVGsobnVsbCxudWxsLHRoaXMuYix0Lk0uYShuZXcgUC5aTCh0aGlz
-LGEsYikpKX0sCiRpYjg6MX0KUC5kYS5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe1AuSFoodGhpcy5h
-LHRoaXMuYil9LAokUzowfQpQLm9RLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5IWih0aGlzLmIs
-dGhpcy5hLmEpfSwKJFM6MH0KUC5wVi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz10aGlz
-LmEKcy5hPTAKcy5ISChhKX0sCiRTOjl9ClAuVTcucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0
-aGlzLmEuWkwoYSx0LmwuYShiKSl9LAokQzoiJDIiLAokUjoyLAokUzoyOX0KUC52ci5wcm90b3R5cGU9
-ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0aGlzLmIsdGhpcy5jKX0sCiRTOjB9ClAucnQucHJvdG90
-eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWDIodGhpcy5iKX0sCiRTOjB9ClAuS0YucHJvdG90eXBl
-PXsKJDA6ZnVuY3Rpb24oKXtQLkE5KHRoaXMuYix0aGlzLmEpfSwKJFM6MH0KUC5aTC5wcm90b3R5cGU9
-ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0aGlzLmIsdGhpcy5jKX0sCiRTOjB9ClAuUlQucHJvdG90
-eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbT10aGlzLGw9bnVsbAp0cnl7cT1tLmEu
-YQpsPXEuYi5iLnp6KHQuZk8uYShxLmQpLHQueil9Y2F0Y2gocCl7cz1ILlJ1KHApCnI9SC50cyhwKQpp
-ZihtLmMpe3E9dC5uLmEobS5iLmEuYykuYQpvPXMKbz1xPT1udWxsP289PW51bGw6cT09PW8KcT1vfWVs
-c2UgcT0hMQpvPW0uYQppZihxKW8uYz10Lm4uYShtLmIuYS5jKQplbHNlIG8uYz1QLlRsKHMscikKby5i
-PSEwCnJldHVybn1pZihsIGluc3RhbmNlb2YgUC52cyYmbC5hPj00KXtpZihsLmE9PT04KXtxPW0uYQpx
-LmM9dC5uLmEobC5jKQpxLmI9ITB9cmV0dXJufWlmKHQuZC5iKGwpKXtuPW0uYi5hCnE9bS5hCnEuYz1s
-Llc3KG5ldyBQLmpaKG4pLHQueikKcS5iPSExfX0sCiRTOjB9ClAualoucHJvdG90eXBlPXsKJDE6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCiRTOjMyfQpQLnJxLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
-KCl7dmFyIHMscixxLHAsbyxuLG0sbAp0cnl7cT10aGlzLmEKcD1xLmEKbz1wLiR0aQpuPW8uYwptPW4u
-YSh0aGlzLmIpCnEuYz1wLmIuYi5idihvLkMoIjIvKDEpIikuYShwLmQpLG0sby5DKCIyLyIpLG4pfWNh
-dGNoKGwpe3M9SC5SdShsKQpyPUgudHMobCkKcT10aGlzLmEKcS5jPVAuVGwocyxyKQpxLmI9ITB9fSwK
-JFM6MH0KUC5SVy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixtLGwsaz10
-aGlzCnRyeXtzPXQubi5hKGsuYS5hLmMpCnA9ay5iCmlmKEgub1QocC5hLkhSKHMpKSYmcC5hLmUhPW51
-bGwpe3AuYz1wLmEuS3cocykKcC5iPSExfX1jYXRjaChvKXtyPUguUnUobykKcT1ILnRzKG8pCnA9dC5u
-LmEoay5hLmEuYykKbj1wLmEKbT1yCmw9ay5iCmlmKG49PW51bGw/bT09bnVsbDpuPT09bSlsLmM9cApl
-bHNlIGwuYz1QLlRsKHIscSkKbC5iPSEwfX0sCiRTOjB9ClAuT00ucHJvdG90eXBlPXt9ClAucWgucHJv
-dG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7dmFyIHMscixxPXRoaXMscD17fSxvPW5ldyBQLnZzKCQuWDMs
-dC5mSikKcC5hPTAKcz1ILkxoKHEpCnI9cy5DKCJ+KDEpPyIpLmEobmV3IFAuQjUocCxxKSkKdC5aLmEo
-bmV3IFAudU8ocCxvKSkKVy5KRShxLmEscS5iLHIsITEscy5jKQpyZXR1cm4gb319ClAuQjUucHJvdG90
-eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC5MaCh0aGlzLmIpLmMuYShhKTsrK3RoaXMuYS5hfSwKJFM6ZnVu
-Y3Rpb24oKXtyZXR1cm4gSC5MaCh0aGlzLmIpLkMoIn4oMSkiKX19ClAudU8ucHJvdG90eXBlPXsKJDA6
-ZnVuY3Rpb24oKXt0aGlzLmIuSEgodGhpcy5hLmEpfSwKJFM6MH0KUC5NTy5wcm90b3R5cGU9e30KUC5r
-VC5wcm90b3R5cGU9e30KUC54SS5wcm90b3R5cGU9e30KUC5Ddy5wcm90b3R5cGU9ewp3OmZ1bmN0aW9u
-KGEpe3JldHVybiBILkVqKHRoaXMuYSl9LAokaVhTOjEsCmdJSTpmdW5jdGlvbigpe3JldHVybiB0aGlz
-LmJ9fQpQLm0wLnByb3RvdHlwZT17JGlRbToxfQpQLnBLLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7
-dmFyIHM9SC5iKHRoaXMuYSkKcy5zdGFjaz1KLmoodGhpcy5iKQp0aHJvdyBzfSwKJFM6MH0KUC5KaS5w
-cm90b3R5cGU9ewpiSDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD1udWxsCnQuTS5hKGEpCnRyeXtpZihD
-Lk5VPT09JC5YMyl7YS4kMCgpCnJldHVybn1QLlQ4KHAscCx0aGlzLGEsdC5IKX1jYXRjaChxKXtzPUgu
-UnUocSkKcj1ILnRzKHEpClAuTDIocCxwLHRoaXMscyx0LmwuYShyKSl9fSwKRGw6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciBzLHIscSxwPW51bGwKYy5DKCJ+KDApIikuYShhKQpjLmEoYikKdHJ5e2lmKEMuTlU9PT0k
-LlgzKXthLiQxKGIpCnJldHVybn1QLnl2KHAscCx0aGlzLGEsYix0LkgsYyl9Y2F0Y2gocSl7cz1ILlJ1
-KHEpCnI9SC50cyhxKQpQLkwyKHAscCx0aGlzLHMsdC5sLmEocikpfX0sClJUOmZ1bmN0aW9uKGEsYil7
-cmV0dXJuIG5ldyBQLmhqKHRoaXMsYi5DKCIwKCkiKS5hKGEpLGIpfSwKdDg6ZnVuY3Rpb24oYSl7cmV0
-dXJuIG5ldyBQLlZwKHRoaXMsdC5NLmEoYSkpfSwKUHk6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAu
-T1IodGhpcyxiLkMoIn4oMCkiKS5hKGEpLGIpfSwKcTpmdW5jdGlvbihhLGIpe3JldHVybiBudWxsfSwK
-eno6ZnVuY3Rpb24oYSxiKXtiLkMoIjAoKSIpLmEoYSkKaWYoJC5YMz09PUMuTlUpcmV0dXJuIGEuJDAo
-KQpyZXR1cm4gUC5UOChudWxsLG51bGwsdGhpcyxhLGIpfSwKYnY6ZnVuY3Rpb24oYSxiLGMsZCl7Yy5D
-KCJAPDA+IikuS3EoZCkuQygiMSgyKSIpLmEoYSkKZC5hKGIpCmlmKCQuWDM9PT1DLk5VKXJldHVybiBh
-LiQxKGIpCnJldHVybiBQLnl2KG51bGwsbnVsbCx0aGlzLGEsYixjLGQpfSwKcnA6ZnVuY3Rpb24oYSxi
-LGMsZCxlLGYpe2QuQygiQDwwPiIpLktxKGUpLktxKGYpLkMoIjEoMiwzKSIpLmEoYSkKZS5hKGIpCmYu
-YShjKQppZigkLlgzPT09Qy5OVSlyZXR1cm4gYS4kMihiLGMpCnJldHVybiBQLlF4KG51bGwsbnVsbCx0
-aGlzLGEsYixjLGQsZSxmKX0sCkxqOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBiLkMoIkA8MD4iKS5L
-cShjKS5LcShkKS5DKCIxKDIsMykiKS5hKGEpfX0KUC5oai5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigp
-e3JldHVybiB0aGlzLmEuenoodGhpcy5iLHRoaXMuYyl9LAokUzpmdW5jdGlvbigpe3JldHVybiB0aGlz
-LmMuQygiMCgpIil9fQpQLlZwLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5i
-SCh0aGlzLmIpfSwKJFM6MH0KUC5PUi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz10aGlz
-LmMKcmV0dXJuIHRoaXMuYS5EbCh0aGlzLmIscy5hKGEpLHMpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4g
-dGhpcy5jLkMoIn4oMCkiKX19ClAuYjYucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7dmFyIHM9dGhp
-cyxyPW5ldyBQLmxtKHMscy5yLEguTGgocykuQygibG08MT4iKSkKci5jPXMuZQpyZXR1cm4gcn0sCmdB
-OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYT09
-PTB9LApnb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYSE9PTB9LAp0ZzpmdW5jdGlvbihhLGIpe3Zh
-ciBzLHIKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpe3M9dGhpcy5iCmlmKHM9
-PW51bGwpcmV0dXJuITEKcmV0dXJuIHQuZS5hKHNbYl0pIT1udWxsfWVsc2V7cj10aGlzLlBSKGIpCnJl
-dHVybiByfX0sClBSOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuZAppZihzPT1udWxsKXJldHVybiExCnJl
-dHVybiB0aGlzLlIoc1t0aGlzLk4oYSldLGEpPj0wfSwKaTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT10
-aGlzCkguTGgocSkuYy5hKGIpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXtz
-PXEuYgpyZXR1cm4gcS5TKHM9PW51bGw/cS5iPVAuVDIoKTpzLGIpfWVsc2UgaWYodHlwZW9mIGI9PSJu
-dW1iZXIiJiYoYiYxMDczNzQxODIzKT09PWIpe3I9cS5jCnJldHVybiBxLlMocj09bnVsbD9xLmM9UC5U
-MigpOnIsYil9ZWxzZSByZXR1cm4gcS5HKGIpfSwKRzpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD10aGlz
-CkguTGgocCkuYy5hKGEpCnM9cC5kCmlmKHM9PW51bGwpcz1wLmQ9UC5UMigpCnI9cC5OKGEpCnE9c1ty
-XQppZihxPT1udWxsKXNbcl09W3AuSChhKV0KZWxzZXtpZihwLlIocSxhKT49MClyZXR1cm4hMQpxLnB1
-c2gocC5IKGEpKX1yZXR1cm4hMH0sCkw6ZnVuY3Rpb24oYSxiKXt2YXIgcz10aGlzCmlmKHR5cGVvZiBi
-PT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXJldHVybiBzLkg0KHMuYixiKQplbHNlIGlmKHR5cGVv
-ZiBiPT0ibnVtYmVyIiYmKGImMTA3Mzc0MTgyMyk9PT1iKXJldHVybiBzLkg0KHMuYyxiKQplbHNlIHJl
-dHVybiBzLnFnKGIpfSwKcWc6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbz10aGlzLG49by5kCmlmKG49
-PW51bGwpcmV0dXJuITEKcz1vLk4oYSkKcj1uW3NdCnE9by5SKHIsYSkKaWYocTwwKXJldHVybiExCnA9
-ci5zcGxpY2UocSwxKVswXQppZigwPT09ci5sZW5ndGgpZGVsZXRlIG5bc10Kby5HUyhwKQpyZXR1cm4h
-MH0sClM6ZnVuY3Rpb24oYSxiKXtILkxoKHRoaXMpLmMuYShiKQppZih0LmUuYShhW2JdKSE9bnVsbCly
-ZXR1cm4hMQphW2JdPXRoaXMuSChiKQpyZXR1cm4hMH0sCkg0OmZ1bmN0aW9uKGEsYil7dmFyIHMKaWYo
-YT09bnVsbClyZXR1cm4hMQpzPXQuZS5hKGFbYl0pCmlmKHM9PW51bGwpcmV0dXJuITEKdGhpcy5HUyhz
-KQpkZWxldGUgYVtiXQpyZXR1cm4hMH0sCkdZOmZ1bmN0aW9uKCl7dGhpcy5yPXRoaXMucisxJjEwNzM3
-NDE4MjN9LApIOmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcyxxPW5ldyBQLmJuKEguTGgocikuYy5hKGEp
-KQppZihyLmU9PW51bGwpci5lPXIuZj1xCmVsc2V7cz1yLmYKcy50b1N0cmluZwpxLmM9cwpyLmY9cy5i
-PXF9KytyLmEKci5HWSgpCnJldHVybiBxfSwKR1M6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcyxyPWEuYyxx
-PWEuYgppZihyPT1udWxsKXMuZT1xCmVsc2Ugci5iPXEKaWYocT09bnVsbClzLmY9cgplbHNlIHEuYz1y
-Oy0tcy5hCnMuR1koKX0sCk46ZnVuY3Rpb24oYSl7cmV0dXJuIEouaGYoYSkmMTA3Mzc0MTgyM30sClI6
-ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlmKGE9PW51bGwpcmV0dXJuLTEKcz1hLmxlbmd0aApmb3Iocj0w
-O3I8czsrK3IpaWYoSi5STShhW3JdLmEsYikpcmV0dXJuIHIKcmV0dXJuLTF9fQpQLmJuLnByb3RvdHlw
-ZT17fQpQLmxtLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVuY3Rp
-b24oKXt2YXIgcz10aGlzLHI9cy5jLHE9cy5hCmlmKHMuYiE9PXEucil0aHJvdyBILmIoUC5hNChxKSkK
-ZWxzZSBpZihyPT1udWxsKXtzLnNqKG51bGwpCnJldHVybiExfWVsc2V7cy5zaihzLiR0aS5DKCIxPyIp
-LmEoci5hKSkKcy5jPXIuYgpyZXR1cm4hMH19LApzajpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGku
-QygiMT8iKS5hKGEpfSwKJGlBbjoxfQpQLm1XLnByb3RvdHlwZT17fQpQLnV5LnByb3RvdHlwZT17JGli
-UToxLCRpY1g6MSwkaXpNOjF9ClAubEQucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIG5l
-dyBILmE3KGEsdGhpcy5nQShhKSxILnooYSkuQygiYTc8bEQuRT4iKSl9LApFOmZ1bmN0aW9uKGEsYil7
-cmV0dXJuIHRoaXMucShhLGIpfSwKSzpmdW5jdGlvbihhLGIpe3ZhciBzLHIKSC56KGEpLkMoIn4obEQu
-RSkiKS5hKGIpCnM9dGhpcy5nQShhKQpmb3Iocj0wO3I8czsrK3Ipe2IuJDEodGhpcy5xKGEscikpCmlm
-KHMhPT10aGlzLmdBKGEpKXRocm93IEguYihQLmE0KGEpKX19LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJu
-IHRoaXMuZ0EoYSk9PT0wfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiF0aGlzLmdsMChhKX0sCkUyOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgcz1ILnooYSkKcmV0dXJuIG5ldyBILmxKKGEscy5LcShjKS5DKCIxKGxE
-LkUpIikuYShiKSxzLkMoIkA8bEQuRT4iKS5LcShjKS5DKCJsSjwxLDI+IikpfSwKZVI6ZnVuY3Rpb24o
-YSxiKXtyZXR1cm4gSC5xQyhhLGIsbnVsbCxILnooYSkuQygibEQuRSIpKX0sCmRyOmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIG5ldyBILmpWKGEsSC56KGEpLkMoIkA8bEQuRT4iKS5LcShiKS5DKCJqVjwxLDI+Iikp
-fSwKZHU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMKSC56KGEpLkMoImxELkU/IikuYShkKQpQLmpCKGIs
-Yyx0aGlzLmdBKGEpKQpmb3Iocz1iO3M8YzsrK3MpdGhpcy5ZNShhLHMsZCl9LAp3OmZ1bmN0aW9uKGEp
-e3JldHVybiBQLldFKGEsIlsiLCJdIil9fQpQLmlsLnByb3RvdHlwZT17fQpQLnJhLnByb3RvdHlwZT17
-CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHMscj10aGlzLmEKaWYoIXIuYSl0aGlzLmIuYSs9IiwgIgpyLmE9
-ITEKcj10aGlzLmIKcz1yLmErPUguRWooYSkKci5hPXMrIjogIgpyLmErPUguRWooYil9LAokUzoxMH0K
-UC5Zay5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpILkxoKHRoaXMpLkMoIn4oWWsu
-SyxZay5WKSIpLmEoYikKZm9yKHM9Si5JVCh0aGlzLmd2YygpKTtzLkYoKTspe3I9cy5nbCgpCmIuJDIo
-cix0aGlzLnEoMCxyKSl9fSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVybiBKLk0xKHRoaXMuZ3ZjKCksbmV3
-IFAueVEodGhpcyksSC5MaCh0aGlzKS5DKCJOMzxZay5LLFlrLlY+IikpfSwKeDQ6ZnVuY3Rpb24oYSl7
-cmV0dXJuIEouemwodGhpcy5ndmMoKSxhKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBKLkhtKHRoaXMu
-Z3ZjKCkpfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiBKLnVVKHRoaXMuZ3ZjKCkpfSwKdzpmdW5jdGlv
-bihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sCiRpWjA6MX0KUC55US5wcm90b3R5cGU9ewokMTpmdW5jdGlv
-bihhKXt2YXIgcz10aGlzLmEscj1ILkxoKHMpCnIuQygiWWsuSyIpLmEoYSkKcmV0dXJuIG5ldyBQLk4z
-KGEscy5xKDAsYSksci5DKCJAPFlrLks+IikuS3Eoci5DKCJZay5WIikpLkMoIk4zPDEsMj4iKSl9LAok
-UzpmdW5jdGlvbigpe3JldHVybiBILkxoKHRoaXMuYSkuQygiTjM8WWsuSyxZay5WPihZay5LKSIpfX0K
-UC5LUC5wcm90b3R5cGU9ewpZNTpmdW5jdGlvbihhLGIsYyl7dmFyIHM9SC5MaCh0aGlzKQpzLmMuYShi
-KQpzLlFbMV0uYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlmaWFibGUgbWFw
-IikpfX0KUC5Qbi5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5xKDAsYil9
-LApZNTpmdW5jdGlvbihhLGIsYyl7dmFyIHM9SC5MaCh0aGlzKQp0aGlzLmEuWTUoMCxzLmMuYShiKSxz
-LlFbMV0uYShjKSl9LAp4NDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLng0KGEpfSwKSzpmdW5jdGlv
-bihhLGIpe3RoaXMuYS5LKDAsSC5MaCh0aGlzKS5DKCJ+KDEsMikiKS5hKGIpKX0sCmdsMDpmdW5jdGlv
-bihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMuZ2wwKHMpfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHM9dGhp
-cy5hCnJldHVybiBzLmdBKHMpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gSi5qKHRoaXMuYSl9LApnUHU6
-ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVybiBzLmdQdShzKX0sCiRpWjA6MX0KUC5Hai5wcm90
-b3R5cGU9e30KUC5sZi5wcm90b3R5cGU9ewpnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ0EodGhp
-cyk9PT0wfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdBKHRoaXMpIT09MH0sCkZWOmZ1bmN0
-aW9uKGEsYil7dmFyIHMKZm9yKHM9Si5JVChILkxoKHRoaXMpLkMoImNYPGxmLkU+IikuYShiKSk7cy5G
-KCk7KXRoaXMuaSgwLHMuZ2woKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKHRoaXMsInsiLCJ9
-Iil9LAprOmZ1bmN0aW9uKGEsYil7dmFyIHMscj10aGlzLmdtKHRoaXMpCmlmKCFyLkYoKSlyZXR1cm4i
-IgppZihiPT09IiIpe3M9IiIKZG8gcys9SC5FaihyLmQpCndoaWxlKHIuRigpKX1lbHNle3M9SC5Faihy
-LmQpCmZvcig7ci5GKCk7KXM9cytiK0guRWooci5kKX1yZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6
-c30sCmVSOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguYksodGhpcyxiLEguTGgodGhpcykuQygibGYuRSIp
-KX0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscD0iaW5kZXgiCkguY2IoYixwLHQuUykKUC5rMShi
-LHApCmZvcihzPXRoaXMuZ20odGhpcykscj0wO3MuRigpOyl7cT1zLmQKaWYoYj09PXIpcmV0dXJuIHE7
-KytyfXRocm93IEguYihQLkNmKGIsdGhpcyxwLG51bGwscikpfX0KUC5Wai5wcm90b3R5cGU9eyRpYlE6
-MSwkaWNYOjEsJGl4dToxfQpQLlh2LnByb3RvdHlwZT17JGliUToxLCRpY1g6MSwkaXh1OjF9ClAublku
-cHJvdG90eXBlPXt9ClAuV1kucHJvdG90eXBlPXt9ClAuUlUucHJvdG90eXBlPXt9ClAucFIucHJvdG90
-eXBlPXt9ClAudXcucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcy5iCmlmKHI9
-PW51bGwpcmV0dXJuIHRoaXMuYy5xKDAsYikKZWxzZSBpZih0eXBlb2YgYiE9InN0cmluZyIpcmV0dXJu
-IG51bGwKZWxzZXtzPXJbYl0KcmV0dXJuIHR5cGVvZiBzPT0idW5kZWZpbmVkIj90aGlzLmZiKGIpOnN9
-fSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYj09bnVsbD90aGlzLmMuYTp0aGlzLkNmKCkubGVu
-Z3RofSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdBKHRoaXMpPT09MH0sCmd2YzpmdW5jdGlv
-bigpe2lmKHRoaXMuYj09bnVsbCl7dmFyIHM9dGhpcy5jCnJldHVybiBuZXcgSC5pNShzLEguTGgocyku
-QygiaTU8MT4iKSl9cmV0dXJuIG5ldyBQLmk4KHRoaXMpfSwKWTU6ZnVuY3Rpb24oYSxiLGMpe3ZhciBz
-LHIscT10aGlzCmlmKHEuYj09bnVsbClxLmMuWTUoMCxiLGMpCmVsc2UgaWYocS54NChiKSl7cz1xLmIK
-c1tiXT1jCnI9cS5hCmlmKHI9PW51bGw/cyE9bnVsbDpyIT09cylyW2JdPW51bGx9ZWxzZSBxLlhLKCku
-WTUoMCxiLGMpfSwKeDQ6ZnVuY3Rpb24oYSl7aWYodGhpcy5iPT1udWxsKXJldHVybiB0aGlzLmMueDQo
-YSkKcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSl9LApL
-OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbz10aGlzCnQuY0EuYShiKQppZihvLmI9PW51bGwpcmV0
-dXJuIG8uYy5LKDAsYikKcz1vLkNmKCkKZm9yKHI9MDtyPHMubGVuZ3RoOysrcil7cT1zW3JdCnA9by5i
-W3FdCmlmKHR5cGVvZiBwPT0idW5kZWZpbmVkIil7cD1QLlFlKG8uYVtxXSkKby5iW3FdPXB9Yi4kMihx
-LHApCmlmKHMhPT1vLmMpdGhyb3cgSC5iKFAuYTQobykpfX0sCkNmOmZ1bmN0aW9uKCl7dmFyIHM9dC5i
-TS5hKHRoaXMuYykKaWYocz09bnVsbClzPXRoaXMuYz1ILlZNKE9iamVjdC5rZXlzKHRoaXMuYSksdC5z
-KQpyZXR1cm4gc30sClhLOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuPXRoaXMKaWYobi5iPT1udWxs
-KXJldHVybiBuLmMKcz1QLkZsKHQuTix0LnopCnI9bi5DZigpCmZvcihxPTA7cD1yLmxlbmd0aCxxPHA7
-KytxKXtvPXJbcV0Kcy5ZNSgwLG8sbi5xKDAsbykpfWlmKHA9PT0wKUMuTm0uaShyLCIiKQplbHNlIEMu
-Tm0uc0EociwwKQpuLmE9bi5iPW51bGwKcmV0dXJuIG4uYz1zfSwKZmI6ZnVuY3Rpb24oYSl7dmFyIHMK
-aWYoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSkpcmV0dXJuIG51
-bGwKcz1QLlFlKHRoaXMuYVthXSkKcmV0dXJuIHRoaXMuYlthXT1zfX0KUC5pOC5wcm90b3R5cGU9ewpn
-QTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMuZ0Eocyl9LApFOmZ1bmN0aW9uKGEsYil7
-dmFyIHM9dGhpcy5hCmlmKHMuYj09bnVsbClzPXMuZ3ZjKCkuRSgwLGIpCmVsc2V7cz1zLkNmKCkKaWYo
-YjwwfHxiPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLGIpCnM9c1tiXX1yZXR1cm4gc30sCmdtOmZ1bmN0
-aW9uKGEpe3ZhciBzPXRoaXMuYQppZihzLmI9PW51bGwpe3M9cy5ndmMoKQpzPXMuZ20ocyl9ZWxzZXtz
-PXMuQ2YoKQpzPW5ldyBKLm0xKHMscy5sZW5ndGgsSC50NihzKS5DKCJtMTwxPiIpKX1yZXR1cm4gc30s
-CnRnOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS54NChiKX19ClAucGcucHJvdG90eXBlPXsKJDA6
-ZnVuY3Rpb24oKXt2YXIgcyxyCnRyeXtzPW5ldyBUZXh0RGVjb2RlcigidXRmLTgiLHtmYXRhbDp0cnVl
-fSkKcmV0dXJuIHN9Y2F0Y2gocil7SC5SdShyKX1yZXR1cm4gbnVsbH0sCiRTOjExfQpQLmMyLnByb3Rv
-dHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHMscgp0cnl7cz1uZXcgVGV4dERlY29kZXIoInV0Zi04Iix7
-ZmF0YWw6ZmFsc2V9KQpyZXR1cm4gc31jYXRjaChyKXtILlJ1KHIpfXJldHVybiBudWxsfSwKJFM6MTF9
-ClAuQ1YucHJvdG90eXBlPXsKeXI6ZnVuY3Rpb24oYTAsYTEsYTIpe3ZhciBzLHIscSxwLG8sbixtLGws
-ayxqLGksaCxnLGYsZSxkLGMsYixhPSJJbnZhbGlkIGJhc2U2NCBlbmNvZGluZyBsZW5ndGggIgphMj1Q
-LmpCKGExLGEyLGEwLmxlbmd0aCkKcz0kLlY3KCkKZm9yKHI9YTEscT1yLHA9bnVsbCxvPS0xLG49LTEs
-bT0wO3I8YTI7cj1sKXtsPXIrMQprPUMueEIuVyhhMCxyKQppZihrPT09Mzcpe2o9bCsyCmlmKGo8PWEy
-KXtpPUgub28oQy54Qi5XKGEwLGwpKQpoPUgub28oQy54Qi5XKGEwLGwrMSkpCmc9aSoxNitoLShoJjI1
-NikKaWYoZz09PTM3KWc9LTEKbD1qfWVsc2UgZz0tMX1lbHNlIGc9awppZigwPD1nJiZnPD0xMjcpe2lm
-KGc8MHx8Zz49cy5sZW5ndGgpcmV0dXJuIEguT0gocyxnKQpmPXNbZ10KaWYoZj49MCl7Zz1DLnhCLk8y
-KCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1
-Njc4OSsvIixmKQppZihnPT09ayljb250aW51ZQprPWd9ZWxzZXtpZihmPT09LTEpe2lmKG88MCl7ZT1w
-PT1udWxsP251bGw6cC5hLmxlbmd0aAppZihlPT1udWxsKWU9MApvPWUrKHItcSkKbj1yfSsrbQppZihr
-PT09NjEpY29udGludWV9az1nfWlmKGYhPT0tMil7aWYocD09bnVsbCl7cD1uZXcgUC5SbigiIikKZT1w
-fWVsc2UgZT1wCmUuYSs9Qy54Qi5OaihhMCxxLHIpCmUuYSs9SC5MdyhrKQpxPWwKY29udGludWV9fXRo
-cm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2NCBkYXRhIixhMCxyKSl9aWYocCE9bnVsbCl7ZT1wLmEr
-PUMueEIuTmooYTAscSxhMikKZD1lLmxlbmd0aAppZihvPj0wKVAueE0oYTAsbixhMixvLG0sZCkKZWxz
-ZXtjPUMuam4uelkoZC0xLDQpKzEKaWYoYz09PTEpdGhyb3cgSC5iKFAucnIoYSxhMCxhMikpCmZvcig7
-Yzw0Oyl7ZSs9Ij0iCnAuYT1lOysrY319ZT1wLmEKcmV0dXJuIEMueEIuaTcoYTAsYTEsYTIsZS5jaGFy
-Q29kZUF0KDApPT0wP2U6ZSl9Yj1hMi1hMQppZihvPj0wKVAueE0oYTAsbixhMixvLG0sYikKZWxzZXtj
-PUMuam4uelkoYiw0KQppZihjPT09MSl0aHJvdyBILmIoUC5ycihhLGEwLGEyKSkKaWYoYz4xKWEwPUMu
-eEIuaTcoYTAsYTIsYTIsYz09PTI/Ij09IjoiPSIpfXJldHVybiBhMH19ClAuVTgucHJvdG90eXBlPXt9
-ClAuVWsucHJvdG90eXBlPXt9ClAud0kucHJvdG90eXBlPXt9ClAuWmkucHJvdG90eXBlPXt9ClAuVWQu
-cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz1QLnAodGhpcy5hKQpyZXR1cm4odGhpcy5iIT1u
-dWxsPyJDb252ZXJ0aW5nIG9iamVjdCB0byBhbiBlbmNvZGFibGUgb2JqZWN0IGZhaWxlZDoiOiJDb252
-ZXJ0aW5nIG9iamVjdCBkaWQgbm90IHJldHVybiBhbiBlbmNvZGFibGUgb2JqZWN0OiIpKyIgIitzfX0K
-UC5LOC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJDeWNsaWMgZXJyb3IgaW4gSlNPTiBz
-dHJpbmdpZnkifX0KUC5ieS5wcm90b3R5cGU9ewpwVzpmdW5jdGlvbihhLGIsYyl7dmFyIHMKdC5mVi5h
-KGMpCnM9UC5CUyhiLHRoaXMuZ0hlKCkuYSkKcmV0dXJuIHN9LApPQjpmdW5jdGlvbihhLGIpe3ZhciBz
-CnQuZEEuYShiKQpzPVAudVgoYSx0aGlzLmdaRSgpLmIsbnVsbCkKcmV0dXJuIHN9LApnWkU6ZnVuY3Rp
-b24oKXtyZXR1cm4gQy5uWH0sCmdIZTpmdW5jdGlvbigpe3JldHVybiBDLkEzfX0KUC5vai5wcm90b3R5
-cGU9e30KUC5NeC5wcm90b3R5cGU9e30KUC5TaC5wcm90b3R5cGU9ewp2cDpmdW5jdGlvbihhKXt2YXIg
-cyxyLHEscCxvLG4sbSxsPWEubGVuZ3RoCmZvcihzPUouclkoYSkscj10aGlzLmMscT0wLHA9MDtwPGw7
-KytwKXtvPXMuVyhhLHApCmlmKG8+OTIpe2lmKG8+PTU1Mjk2KXtuPW8mNjQ1MTIKaWYobj09PTU1Mjk2
-KXttPXArMQptPSEobTxsJiYoQy54Qi5XKGEsbSkmNjQ1MTIpPT09NTYzMjApfWVsc2UgbT0hMQppZigh
-bSlpZihuPT09NTYzMjApe249cC0xCm49IShuPj0wJiYoQy54Qi5PMihhLG4pJjY0NTEyKT09PTU1Mjk2
-KX1lbHNlIG49ITEKZWxzZSBuPSEwCmlmKG4pe2lmKHA+cSlyLmErPUMueEIuTmooYSxxLHApCnE9cCsx
-CnIuYSs9SC5Mdyg5MikKci5hKz1ILkx3KDExNykKci5hKz1ILkx3KDEwMCkKbj1vPj4+OCYxNQpyLmEr
-PUguTHcobjwxMD80OCtuOjg3K24pCm49bz4+PjQmMTUKci5hKz1ILkx3KG48MTA/NDgrbjo4NytuKQpu
-PW8mMTUKci5hKz1ILkx3KG48MTA/NDgrbjo4NytuKX19Y29udGludWV9aWYobzwzMil7aWYocD5xKXIu
-YSs9Qy54Qi5OaihhLHEscCkKcT1wKzEKci5hKz1ILkx3KDkyKQpzd2l0Y2gobyl7Y2FzZSA4OnIuYSs9
-SC5Mdyg5OCkKYnJlYWsKY2FzZSA5OnIuYSs9SC5MdygxMTYpCmJyZWFrCmNhc2UgMTA6ci5hKz1ILkx3
-KDExMCkKYnJlYWsKY2FzZSAxMjpyLmErPUguTHcoMTAyKQpicmVhawpjYXNlIDEzOnIuYSs9SC5Mdygx
-MTQpCmJyZWFrCmRlZmF1bHQ6ci5hKz1ILkx3KDExNykKci5hKz1ILkx3KDQ4KQpyLmErPUguTHcoNDgp
-Cm49bz4+PjQmMTUKci5hKz1ILkx3KG48MTA/NDgrbjo4NytuKQpuPW8mMTUKci5hKz1ILkx3KG48MTA/
-NDgrbjo4NytuKQpicmVha319ZWxzZSBpZihvPT09MzR8fG89PT05Mil7aWYocD5xKXIuYSs9Qy54Qi5O
-aihhLHEscCkKcT1wKzEKci5hKz1ILkx3KDkyKQpyLmErPUguTHcobyl9fWlmKHE9PT0wKXIuYSs9SC5F
-aihhKQplbHNlIGlmKHE8bClyLmErPXMuTmooYSxxLGwpfSwKSm46ZnVuY3Rpb24oYSl7dmFyIHMscixx
-LHAKZm9yKHM9dGhpcy5hLHI9cy5sZW5ndGgscT0wO3E8cjsrK3Epe3A9c1txXQppZihhPT1udWxsP3A9
-PW51bGw6YT09PXApdGhyb3cgSC5iKG5ldyBQLks4KGEsbnVsbCkpfUMuTm0uaShzLGEpfSwKaVU6ZnVu
-Y3Rpb24oYSl7dmFyIHMscixxLHAsbz10aGlzCmlmKG8udE0oYSkpcmV0dXJuCm8uSm4oYSkKdHJ5e3M9
-by5iLiQxKGEpCmlmKCFvLnRNKHMpKXtxPVAuR3koYSxudWxsLG8uZ1ZLKCkpCnRocm93IEguYihxKX1x
-PW8uYQppZigwPj1xLmxlbmd0aClyZXR1cm4gSC5PSChxLC0xKQpxLnBvcCgpfWNhdGNoKHApe3I9SC5S
-dShwKQpxPVAuR3koYSxyLG8uZ1ZLKCkpCnRocm93IEguYihxKX19LAp0TTpmdW5jdGlvbihhKXt2YXIg
-cyxyLHE9dGhpcwppZih0eXBlb2YgYT09Im51bWJlciIpe2lmKCFpc0Zpbml0ZShhKSlyZXR1cm4hMQpx
-LmMuYSs9Qy5DRC53KGEpCnJldHVybiEwfWVsc2UgaWYoYT09PSEwKXtxLmMuYSs9InRydWUiCnJldHVy
-biEwfWVsc2UgaWYoYT09PSExKXtxLmMuYSs9ImZhbHNlIgpyZXR1cm4hMH1lbHNlIGlmKGE9PW51bGwp
-e3EuYy5hKz0ibnVsbCIKcmV0dXJuITB9ZWxzZSBpZih0eXBlb2YgYT09InN0cmluZyIpe3M9cS5jCnMu
-YSs9JyInCnEudnAoYSkKcy5hKz0nIicKcmV0dXJuITB9ZWxzZSBpZih0LmouYihhKSl7cS5KbihhKQpx
-LmxLKGEpCnM9cS5hCmlmKDA+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9wKCkKcmV0dXJu
-ITB9ZWxzZSBpZih0LmYuYihhKSl7cS5KbihhKQpyPXEuancoYSkKcz1xLmEKaWYoMD49cy5sZW5ndGgp
-cmV0dXJuIEguT0gocywtMSkKcy5wb3AoKQpyZXR1cm4gcn1lbHNlIHJldHVybiExfSwKbEs6ZnVuY3Rp
-b24oYSl7dmFyIHMscixxPXRoaXMuYwpxLmErPSJbIgpzPUouVTYoYSkKaWYocy5nb3IoYSkpe3RoaXMu
-aVUocy5xKGEsMCkpCmZvcihyPTE7cjxzLmdBKGEpOysrcil7cS5hKz0iLCIKdGhpcy5pVShzLnEoYSxy
-KSl9fXEuYSs9Il0ifSwKanc6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG09dGhpcyxsPXt9Cmlm
-KGEuZ2wwKGEpKXttLmMuYSs9Int9IgpyZXR1cm4hMH1zPWEuZ0EoYSkqMgpyPVAuTzgocyxudWxsLCEx
-LHQuVykKcT1sLmE9MApsLmI9ITAKYS5LKDAsbmV3IFAudGkobCxyKSkKaWYoIWwuYilyZXR1cm4hMQpw
-PW0uYwpwLmErPSJ7Igpmb3Iobz0nIic7cTxzO3ErPTIsbz0nLCInKXtwLmErPW8KbS52cChILmgocltx
-XSkpCnAuYSs9JyI6JwpuPXErMQppZihuPj1zKXJldHVybiBILk9IKHIsbikKbS5pVShyW25dKX1wLmEr
-PSJ9IgpyZXR1cm4hMH19ClAudGkucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlm
-KHR5cGVvZiBhIT0ic3RyaW5nIil0aGlzLmEuYj0hMQpzPXRoaXMuYgpyPXRoaXMuYQpDLk5tLlk1KHMs
-ci5hKyssYSkKQy5ObS5ZNShzLHIuYSsrLGIpfSwKJFM6MTB9ClAudHUucHJvdG90eXBlPXsKZ1ZLOmZ1
-bmN0aW9uKCl7dmFyIHM9dGhpcy5jLmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9fQpQLnU1
-LnByb3RvdHlwZT17CmdaRTpmdW5jdGlvbigpe3JldHVybiBDLlFrfX0KUC5FMy5wcm90b3R5cGU9ewpX
-SjpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD1QLmpCKDAsbnVsbCxhLmxlbmd0aCksbz1wLTAKaWYobz09
-PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApCnM9byozCnI9bmV3IFVpbnQ4QXJyYXkocykKcT1uZXcg
-UC5SdyhyKQppZihxLkd4KGEsMCxwKSE9PXApe0ouYTYoYSxwLTEpCnEuUk8oKX1yZXR1cm4gbmV3IFVp
-bnQ4QXJyYXkoci5zdWJhcnJheSgwLEguck0oMCxxLmIscykpKX19ClAuUncucHJvdG90eXBlPXsKUk86
-ZnVuY3Rpb24oKXt2YXIgcz10aGlzLHI9cy5jLHE9cy5iLHA9cy5iPXErMSxvPXIubGVuZ3RoCmlmKHE+
-PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPTIzOQpxPXMuYj1wKzEKaWYocD49bylyZXR1cm4gSC5PSChy
-LHApCnJbcF09MTkxCnMuYj1xKzEKaWYocT49bylyZXR1cm4gSC5PSChyLHEpCnJbcV09MTg5fSwKTzY6
-ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG49dGhpcwppZigoYiY2NDUxMik9PT01NjMyMCl7cz02
-NTUzNisoKGEmMTAyMyk8PDEwKXxiJjEwMjMKcj1uLmMKcT1uLmIKcD1uLmI9cSsxCm89ci5sZW5ndGgK
-aWYocT49bylyZXR1cm4gSC5PSChyLHEpCnJbcV09cz4+PjE4fDI0MApxPW4uYj1wKzEKaWYocD49byly
-ZXR1cm4gSC5PSChyLHApCnJbcF09cz4+PjEyJjYzfDEyOApwPW4uYj1xKzEKaWYocT49bylyZXR1cm4g
-SC5PSChyLHEpCnJbcV09cz4+PjYmNjN8MTI4Cm4uYj1wKzEKaWYocD49bylyZXR1cm4gSC5PSChyLHAp
-CnJbcF09cyY2M3wxMjgKcmV0dXJuITB9ZWxzZXtuLlJPKCkKcmV0dXJuITF9fSwKR3g6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciBzLHIscSxwLG8sbixtLGw9dGhpcwppZihiIT09YyYmKEMueEIuTzIoYSxjLTEpJjY0
-NTEyKT09PTU1Mjk2KS0tYwpmb3Iocz1sLmMscj1zLmxlbmd0aCxxPWI7cTxjOysrcSl7cD1DLnhCLlco
-YSxxKQppZihwPD0xMjcpe289bC5iCmlmKG8+PXIpYnJlYWsKbC5iPW8rMQpzW29dPXB9ZWxzZXtvPXAm
-NjQ1MTIKaWYobz09PTU1Mjk2KXtpZihsLmIrND5yKWJyZWFrCm49cSsxCmlmKGwuTzYocCxDLnhCLlco
-YSxuKSkpcT1ufWVsc2UgaWYobz09PTU2MzIwKXtpZihsLmIrMz5yKWJyZWFrCmwuUk8oKX1lbHNlIGlm
-KHA8PTIwNDcpe289bC5iCm09bysxCmlmKG0+PXIpYnJlYWsKbC5iPW0KaWYobz49cilyZXR1cm4gSC5P
-SChzLG8pCnNbb109cD4+PjZ8MTkyCmwuYj1tKzEKc1ttXT1wJjYzfDEyOH1lbHNle289bC5iCmlmKG8r
-Mj49cilicmVhawptPWwuYj1vKzEKaWYobz49cilyZXR1cm4gSC5PSChzLG8pCnNbb109cD4+PjEyfDIy
-NApvPWwuYj1tKzEKaWYobT49cilyZXR1cm4gSC5PSChzLG0pCnNbbV09cD4+PjYmNjN8MTI4CmwuYj1v
-KzEKaWYobz49cilyZXR1cm4gSC5PSChzLG8pCnNbb109cCY2M3wxMjh9fX1yZXR1cm4gcX19ClAuR1ku
-cHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFyIHMscgp0LkwuYShhKQpzPXRoaXMuYQpyPVAua3ko
-cyxhLDAsbnVsbCkKaWYociE9bnVsbClyZXR1cm4gcgpyZXR1cm4gbmV3IFAuYnoocykuTmUoYSwwLG51
-bGwsITApfX0KUC5iei5wcm90b3R5cGU9ewpOZTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEscCxv
-LG49dGhpcwp0LkwuYShhKQpzPVAuakIoYixjLEouSG0oYSkpCmlmKGI9PT1zKXJldHVybiIiCnI9UC5q
-eShhLGIscykKcT1uLmhPKHIsMCxzLWIsITApCnA9bi5iCmlmKChwJjEpIT09MCl7bz1QLmo0KHApCm4u
-Yj0wCnRocm93IEguYihQLnJyKG8sYSxiK24uYykpfXJldHVybiBxfSwKaE86ZnVuY3Rpb24oYSxiLGMs
-ZCl7dmFyIHMscixxPXRoaXMKaWYoYy1iPjEwMDApe3M9Qy5qbi5CVShiK2MsMikKcj1xLmhPKGEsYixz
-LCExKQppZigocS5iJjEpIT09MClyZXR1cm4gcgpyZXR1cm4gcitxLmhPKGEscyxjLGQpfXJldHVybiBx
-LkVoKGEsYixjLGQpfSwKRWg6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuLG0sbCxrPXRo
-aXMsaj02NTUzMyxpPWsuYixoPWsuYyxnPW5ldyBQLlJuKCIiKSxmPWIrMSxlPWEubGVuZ3RoCmlmKGI8
-MHx8Yj49ZSlyZXR1cm4gSC5PSChhLGIpCnM9YVtiXQokbGFiZWwwJDA6Zm9yKHI9ay5hOyEwOyl7Zm9y
-KDshMDtmPW8pe3E9Qy54Qi5XKCJBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
+cyxyLHE9e30KcS5hPWEKYT1MLkVuKGEpCnEuYT1hCkouZHIoJC5EOSgpLGEpCnM9ZG9jdW1lbnQKSC5E
+aCh0LmcsdC5oLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnM9bmV3IFcud3oocy5xdWVyeVNlbGVjdG9y
+QWxsKCIubmF2LXBhbmVsIC5uYXYtbGluayIpLHQuUikKcy5LKHMsbmV3IEwuVlMocSkpCnI9TC5tSCgk
+LklSLHEuYSkKaWYocj09bnVsbClKLmRSKCQuYk4oKSkuUigwLCJ2aXNpYmxlIikKZWxzZXtKLmRSKCQu
+Yk4oKSkuaSgwLCJ2aXNpYmxlIikKTC50YSgkLmMwKCksci5nTCgpKX19LApBUjpmdW5jdGlvbihhLGIp
+e3ZhciBzLHIscT1iLmIKaWYocSE9bnVsbCl7cz10LmcKcj1zLmEocy5hKGEucGFyZW50Tm9kZSkucGFy
+ZW50Tm9kZSkKTC54bihyLnF1ZXJ5U2VsZWN0b3IoIjpzY29wZSA+IC5zdGF0dXMtaWNvbiIpLHEpCkwu
+QVIocixxKX19LApobDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtPSI6c2NvcGUgPiAuc3Rh
+dHVzLWljb24iCmZvcihzPWIuZCxyPXMubGVuZ3RoLHE9dC5nLHA9MDtwPHMubGVuZ3RoO3MubGVuZ3Ro
+PT09cnx8KDAsSC5saykocyksKytwKXtvPXNbcF0Kbj1hLnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLW5hbWUq
+PSInK0guRWooby5jKSsnIl0nKQppZihvIGluc3RhbmNlb2YgTC52dCl7TC5obChuLG8pCkwueG4obi5x
+dWVyeVNlbGVjdG9yKG0pLGIpfWVsc2UgTC54bihxLmEobi5wYXJlbnROb2RlKS5xdWVyeVNlbGVjdG9y
+KG0pLG8pfX0sCkJFOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz0iLnJlZ2lvbnMiLHI9ZG9jdW1lbnQscT1y
+LnF1ZXJ5U2VsZWN0b3IocykscD1yLnF1ZXJ5U2VsZWN0b3IoIi5jb2RlIikKSi50SChxLGIuYSwkLktH
+KCkpCkoudEgocCxiLmIsJC5LRygpKQpMLkxIKGEsYi5kLGMpCmlmKGIuYy5sZW5ndGg8MmU1KUwudlUo
+KQpMLnlYKCIuY29kZSIsITApCkwueVgocywhMCl9LAp0WDpmdW5jdGlvbihhMSxhMixhMyl7dmFyIHMs
+cixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYz0ibWF0ZXJpYWwtaWNvbnMiLGI9InN0YXR1cy1p
+Y29uIixhPWRvY3VtZW50LGEwPWEuY3JlYXRlRWxlbWVudCgidWwiKQphMS5hcHBlbmRDaGlsZChhMCkK
+Zm9yKHM9YTIubGVuZ3RoLHI9dC5YLHE9dC5aLHA9MDtwPGEyLmxlbmd0aDthMi5sZW5ndGg9PT1zfHwo
+MCxILmxrKShhMiksKytwKXtvPWEyW3BdCm49YS5jcmVhdGVFbGVtZW50KCJsaSIpCmEwLmFwcGVuZENo
+aWxkKG4pCmlmKG8gaW5zdGFuY2VvZiBMLnZ0KXttPUouWUUobikKbS5nUChuKS5pKDAsImRpciIpCm4u
+c2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcobikpLk9VKCJuYW1lIiksby5jKQps
+PWEuY3JlYXRlRWxlbWVudCgic3BhbiIpCm4uYXBwZW5kQ2hpbGQobCkKaz1KLllFKGwpCmsuZ1AobCku
+aSgwLCJhcnJvdyIpCmsuc2hmKGwsIiYjeDI1QkM7IikKaj1hLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpK
+LmRSKGopLmkoMCxjKQpqLmlubmVyVGV4dD0iZm9sZGVyX29wZW4iCm4uYXBwZW5kQ2hpbGQoaikKbi5h
+cHBlbmRDaGlsZChhLmNyZWF0ZVRleHROb2RlKG8uYSkpCkwudFgobixvLmQsITApCmk9YS5jcmVhdGVF
+bGVtZW50KCJzcGFuIikKaz1KLllFKGkpCmsuZ1AoaSkuaSgwLGMpCmkuaW5uZXJUZXh0PSJpbmRldGVy
+bWluYXRlX2NoZWNrX2JveCIKay5nUChpKS5pKDAsYikKTC54bihpLG8pCms9ay5nVmwoaSkKaD1rLiR0
+aQpnPWguQygifigxKT8iKS5hKG5ldyBMLlREKG8sbixpKSkKcS5hKG51bGwpClcuSkUoay5hLGsuYixn
+LCExLGguYykKbS5tSyhuLGksaikKTC5reihsKX1lbHNlIGlmKG8gaW5zdGFuY2VvZiBMLmNEKXtpPWEu
+Y3JlYXRlRWxlbWVudCgic3BhbiIpCm09Si5ZRShpKQptLmdQKGkpLmkoMCxjKQppLmlubmVyVGV4dD0i
+IgptLmdQKGkpLmkoMCxiKQprPUgub1Qoby54KQppZighayltLmdQKGkpLmkoMCwiZGlzYWJsZWQiKQpM
+LnhuKGksbykKaWYoayl7bT1tLmdWbChpKQprPW0uJHRpCmg9ay5DKCJ+KDEpPyIpLmEobmV3IEwuSWYo
+byxpLG4pKQpxLmEobnVsbCkKVy5KRShtLmEsbS5iLGgsITEsay5jKX1uLmFwcGVuZENoaWxkKGkpCm09
+YS5jcmVhdGVFbGVtZW50KCJzcGFuIikKSi5kUihtKS5pKDAsYykKbS5pbm5lclRleHQ9Imluc2VydF9k
+cml2ZV9maWxlIgpuLmFwcGVuZENoaWxkKG0pCmY9YS5jcmVhdGVFbGVtZW50KCJhIikKbi5hcHBlbmRD
+aGlsZChmKQptPUouWUUoZikKbS5nUChmKS5pKDAsIm5hdi1saW5rIikKZi5zZXRBdHRyaWJ1dGUoImRh
+dGEtIituZXcgVy5TeShuZXcgVy5pNyhmKSkuT1UoIm5hbWUiKSxvLmMpCmYuc2V0QXR0cmlidXRlKCJo
+cmVmIixMLlE0KG8uZCxQLkZsKHIscikpKQpmLmFwcGVuZENoaWxkKGEuY3JlYXRlVGV4dE5vZGUoby5h
+KSkKbT1tLmdWbChmKQprPW0uJHRpCmg9ay5DKCJ+KDEpPyIpLmEobmV3IEwudEIoKSkKcS5hKG51bGwp
+ClcuSkUobS5hLG0uYixoLCExLGsuYykKZT1vLmUKaWYodHlwZW9mIGUhPT0ibnVtYmVyIilyZXR1cm4g
+ZS5vcygpCmlmKGU+MCl7ZD1hLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpuLmFwcGVuZENoaWxkKGQpCkou
+ZFIoZCkuaSgwLCJlZGl0LWNvdW50IikKbT0iIitlKyIgIgppZihlPT09MSlrPSJwcm9wb3NlZCBlZGl0
+IgplbHNlIGs9InByb3Bvc2VkIGVkaXRzIgpkLnNldEF0dHJpYnV0ZSgidGl0bGUiLG0raykKZC5hcHBl
+bmRDaGlsZChhLmNyZWF0ZVRleHROb2RlKEMuam4udyhlKSkpfX19fSwKdXo6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciBzPWRvY3VtZW50LHI9cy5jcmVhdGVFbGVtZW50KCJidXR0b24iKSxxPXQuayxwPXEuQygifigx
+KT8iKS5hKG5ldyBMLm0yKGEsYykpCnQuWi5hKG51bGwpClcuSkUociwiY2xpY2siLHAsITEscS5jKQpy
+LmFwcGVuZENoaWxkKHMuY3JlYXRlVGV4dE5vZGUoUi5PWChhLmEpKSkKYi5hcHBlbmRDaGlsZChyKX0s
+CkZ6OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoPWEuYQppZihoPT1udWxs
+KXJldHVybgpzPWRvY3VtZW50CnI9cy5jcmVhdGVFbGVtZW50KCJwIikKcT1iLmFwcGVuZENoaWxkKHIp
+CnI9cy5jcmVhdGVFbGVtZW50KCJzcGFuIikKcD10LmkKSi5NdShyLEguVk0oWyJ0eXBlLWRlc2NyaXB0
+aW9uIl0scCkpCnIuYXBwZW5kQ2hpbGQocy5jcmVhdGVUZXh0Tm9kZSgiQWN0aW9ucyIpKQpxLmFwcGVu
+ZENoaWxkKHIpCnEuYXBwZW5kQ2hpbGQocy5jcmVhdGVUZXh0Tm9kZSgiOiIpKQpvPXMuY3JlYXRlRWxl
+bWVudCgicCIpCmIuYXBwZW5kQ2hpbGQobykKZm9yKHI9aC5sZW5ndGgsbj10LlEsbT0wO208aC5sZW5n
+dGg7aC5sZW5ndGg9PT1yfHwoMCxILmxrKShoKSwrK20pe2w9aFttXQprPXMuY3JlYXRlRWxlbWVudCgi
+YSIpCm8uYXBwZW5kQ2hpbGQoaykKay5hcHBlbmRDaGlsZChzLmNyZWF0ZVRleHROb2RlKGwuYSkpCmsu
+c2V0QXR0cmlidXRlKCJocmVmIixsLmIpCmo9bi5hKEguVk0oWyJhZGQtaGludC1saW5rIiwiYmVmb3Jl
+LWFwcGx5IiwiYnV0dG9uIl0scCkpCmk9Si5kUihrKQppLlYxKDApCmkuRlYoMCxqKX19LApDQzpmdW5j
+dGlvbihhNCxhNSxhNil7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGEsYTAs
+YTEsYTIsYTMKZm9yKHM9YTQuZixyPXMubGVuZ3RoLHE9dC5pLHA9dC5RLG89MDtvPHMubGVuZ3RoO3Mu
+bGVuZ3RoPT09cnx8KDAsSC5saykocyksKytvKXtuPXNbb10KbT1kb2N1bWVudApsPW0uY3JlYXRlRWxl
+bWVudCgicCIpCms9cC5hKEguVk0oWyJ0cmFjZSJdLHEpKQpqPUouZFIobCkKai5WMSgwKQpqLkZWKDAs
+aykKaT1hNS5hcHBlbmRDaGlsZChsKQpsPW0uY3JlYXRlRWxlbWVudCgic3BhbiIpCms9cC5hKEguVk0o
+WyJ0eXBlLWRlc2NyaXB0aW9uIl0scSkpCmo9Si5kUihsKQpqLlYxKDApCmouRlYoMCxrKQpsLmFwcGVu
+ZENoaWxkKG0uY3JlYXRlVGV4dE5vZGUobi5hKSkKaS5hcHBlbmRDaGlsZChsKQppLmFwcGVuZENoaWxk
+KG0uY3JlYXRlVGV4dE5vZGUoIjoiKSkKbD1tLmNyZWF0ZUVsZW1lbnQoInVsIikKaz1wLmEoSC5WTShb
+InRyYWNlIl0scSkpCmo9Si5kUihsKQpqLlYxKDApCmouRlYoMCxrKQpoPWkuYXBwZW5kQ2hpbGQobCkK
+Zm9yKGw9bi5iLGs9bC5sZW5ndGgsZz0wO2c8bC5sZW5ndGg7bC5sZW5ndGg9PT1rfHwoMCxILmxrKShs
+KSwrK2cpe2Y9bFtnXQplPW0uY3JlYXRlRWxlbWVudCgibGkiKQpoLmFwcGVuZENoaWxkKGUpCmQ9bS5j
+cmVhdGVFbGVtZW50KCJzcGFuIikKYz1wLmEoSC5WTShbImZ1bmN0aW9uIl0scSkpCmo9Si5kUihkKQpq
+LlYxKDApCmouRlYoMCxjKQpjPWYuYgpMLmtEKGQsYz09bnVsbD8idW5rbm93biI6YykKZS5hcHBlbmRD
+aGlsZChkKQpiPWYuYwppZihiIT1udWxsKXtlLmFwcGVuZENoaWxkKG0uY3JlYXRlVGV4dE5vZGUoIiAo
+IikpCmE9Yi5iCmEwPW0uY3JlYXRlRWxlbWVudCgiYSIpCmEwLmFwcGVuZENoaWxkKG0uY3JlYXRlVGV4
+dE5vZGUoSC5FaihiLmMpKyI6IitILkVqKGEpKSkKYTAuc2V0QXR0cmlidXRlKCJocmVmIixiLmEpCmEw
+LmNsYXNzTGlzdC5hZGQoIm5hdi1saW5rIikKZS5hcHBlbmRDaGlsZChhMCkKZS5hcHBlbmRDaGlsZCht
+LmNyZWF0ZVRleHROb2RlKCIpIikpfWUuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZSgiOiAiKSkK
+ZD1mLmEKTC5rRChlLGQ9PW51bGw/InVua25vd24iOmQpCmQ9Zi5kCmlmKGQubGVuZ3RoIT09MCl7Yz1t
+LmNyZWF0ZUVsZW1lbnQoInAiKQphMT1wLmEoSC5WTShbImRyYXdlciIsImJlZm9yZS1hcHBseSJdLHEp
+KQpqPUouZFIoYykKai5WMSgwKQpqLkZWKDAsYTEpCmEyPWUuYXBwZW5kQ2hpbGQoYykKZm9yKGM9ZC5s
+ZW5ndGgsYTM9MDthMzxkLmxlbmd0aDtkLmxlbmd0aD09PWN8fCgwLEgubGspKGQpLCsrYTMpTC51eihk
+W2EzXSxhMixiKX19fX0sClVzOmZ1bmN0aW9uKGEpe3JldHVybiBKLlU2KGEpLnRnKGEsIj8iKT9DLnhC
+Lk5qKGEsMCxDLnhCLk9ZKGEsIj8iKSk6YX0sCmtEOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPUguVk0o
+Yi5zcGxpdCgiLiIpLHQucykscD1DLk5tLmd0SChxKSxvPWRvY3VtZW50CmEuYXBwZW5kQ2hpbGQoby5j
+cmVhdGVUZXh0Tm9kZShwKSkKZm9yKHA9SC5xQyhxLDEsbnVsbCx0Lk4pLHA9bmV3IEguYTcocCxwLmdB
+KHApLHAuJHRpLkMoImE3PGFMLkU+IikpLHM9Si5ZRShhKTtwLkYoKTspe3I9cC5kCnMubnooYSwiYmVm
+b3JlZW5kIiwiJiM4MjAzOy4iLG51bGwsbnVsbCkKYS5hcHBlbmRDaGlsZChvLmNyZWF0ZVRleHROb2Rl
+KHIpKX19LAptSDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwCmZvcihzPWEubGVuZ3RoLHI9MDtyPGEu
+bGVuZ3RoO2EubGVuZ3RoPT09c3x8KDAsSC5saykoYSksKytyKXtxPWFbcl0KaWYocSBpbnN0YW5jZW9m
+IEwudnQpe3A9TC5tSChxLmQsYikKaWYocCE9bnVsbClyZXR1cm4gcH1lbHNlIGlmKHEuYz09YilyZXR1
+cm4gcX1yZXR1cm4gbnVsbH0sCmU6ZnVuY3Rpb24gZSgpe30sClZXOmZ1bmN0aW9uIFZXKGEsYixjKXt0
+aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCm9aOmZ1bmN0aW9uIG9aKCl7fSwKanI6ZnVuY3Rpb24g
+anIoKXt9LApxbDpmdW5jdGlvbiBxbCgpe30sCkhpOmZ1bmN0aW9uIEhpKCl7fSwKQlQ6ZnVuY3Rpb24g
+QlQoKXt9LApQWTpmdW5jdGlvbiBQWSgpe30sCnU4OmZ1bmN0aW9uIHU4KCl7fSwKTDpmdW5jdGlvbiBM
+KCl7fSwKV3g6ZnVuY3Rpb24gV3goYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkFPOmZ1bmN0aW9uIEFP
+KGEpe3RoaXMuYT1hfSwKZE46ZnVuY3Rpb24gZE4oYSl7dGhpcy5hPWF9LApIbzpmdW5jdGlvbiBIbyhh
+KXt0aGlzLmE9YX0sCnh6OmZ1bmN0aW9uIHh6KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApJQzpmdW5j
+dGlvbiBJQygpe30sCmZDOmZ1bmN0aW9uIGZDKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApuVDpmdW5j
+dGlvbiBuVChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApOWTpmdW5jdGlvbiBOWShh
+KXt0aGlzLmE9YX0sCnVlOmZ1bmN0aW9uIHVlKCl7fSwKZVg6ZnVuY3Rpb24gZVgoKXt9LApFRTpmdW5j
+dGlvbiBFRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApRTDpmdW5jdGlvbiBRTChh
+LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVlM6ZnVuY3Rpb24gVlMoYSl7dGhpcy5hPWF9LApURDpmdW5j
+dGlvbiBURChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApJZjpmdW5jdGlvbiBJZihh
+LGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAp0QjpmdW5jdGlvbiB0Qigpe30sCm0yOmZ1
+bmN0aW9uIG0yKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApYQTpmdW5jdGlvbiBYQSgpe30sClpzOmZ1
+bmN0aW9uKGEpe3ZhciBzLHIscT1KLlU2KGEpCmlmKEwucDIoSC5oKHEucShhLCJ0eXBlIikpKT09PUMu
+WTIpe3M9SC5oKHEucShhLCJuYW1lIikpCnI9SC5oKHEucShhLCJwYXRoIikpCnE9cS5xKGEsInN1YnRy
+ZWUiKQpxPW5ldyBMLnZ0KHE9PW51bGw/bnVsbDpMLm1LKHEpLHMscikKcS5MVigpCnJldHVybiBxfWVs
+c2V7cz1ILmgocS5xKGEsIm5hbWUiKSkKcj1ILmgocS5xKGEsInBhdGgiKSkKcmV0dXJuIG5ldyBMLmNE
+KEguaChxLnEoYSwiaHJlZiIpKSxILnVQKHEucShhLCJlZGl0Q291bnQiKSksSC55OChxLnEoYSwid2Fz
+RXhwbGljaXRseU9wdGVkT3V0IikpLEwudkIoSC51UChxLnEoYSwibWlncmF0aW9uU3RhdHVzIikpKSxI
+Lnk4KHEucShhLCJtaWdyYXRpb25TdGF0dXNDYW5CZUNoYW5nZWQiKSkscyxyKX19LAptSzpmdW5jdGlv
+bihhKXt2YXIgcyxyPUguVk0oW10sdC5jUSkKZm9yKHM9Si5JVCh0LlUuYShhKSk7cy5GKCk7KXIucHVz
+aChMLlpzKHMuZ2woKSkpCnJldHVybiByfSwKVkQ6ZnVuY3Rpb24oYSl7dmFyIHMscixxPUguVk0oW10s
+dC5HKQpmb3Iocz1hLmxlbmd0aCxyPTA7cjxhLmxlbmd0aDthLmxlbmd0aD09PXN8fCgwLEgubGspKGEp
+LCsrcilxLnB1c2goYVtyXS5MdCgpKQpyZXR1cm4gcX0sCnZCOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwp
+cmV0dXJuIG51bGwKaWYoYT4+PjAhPT1hfHxhPj00KXJldHVybiBILk9IKEMubDAsYSkKcmV0dXJuIEMu
+bDBbYV19LApwMjpmdW5jdGlvbihhKXtzd2l0Y2goYSl7Y2FzZSJkaXJlY3RvcnkiOnJldHVybiBDLlky
+CmNhc2UiZmlsZSI6cmV0dXJuIEMucmYKZGVmYXVsdDp0aHJvdyBILmIoUC5QVigiVW5yZWNvZ25pemVk
+IG5hdmlnYXRpb24gdHJlZSBub2RlIHR5cGU6ICIrSC5FaihhKSkpfX0sCnZ0OmZ1bmN0aW9uIHZ0KGEs
+YixjKXt2YXIgXz10aGlzCl8uZD1hCl8uYT1iCl8uYj1udWxsCl8uYz1jfSwKY0Q6ZnVuY3Rpb24gY0Qo
+YSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9YgpfLmY9YwpfLnI9ZApfLng9ZQpfLmE9
+ZgpfLmI9bnVsbApfLmM9Z30sCkQ4OmZ1bmN0aW9uIEQ4KCl7fSwKTzk6ZnVuY3Rpb24gTzkoYSl7dGhp
+cy5iPWF9LApHYjpmdW5jdGlvbiBHYihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSVY6ZnVuY3Rpb24g
+SVYoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9YgpfLmY9YwpfLnI9ZH19LFI9ewpuejpmdW5j
+dGlvbihhKXt2YXIgcz1ILnVQKGEucSgwLCJub2RlSWQiKSkKcmV0dXJuIG5ldyBSLkxMKEMuTm0uSHQo
+Qy5yayxuZXcgUi5NRChhKSkscyl9LApPWDpmdW5jdGlvbihhKXtzd2l0Y2goYSl7Y2FzZSBDLkFkOnJl
+dHVybiJBZGQgLyo/Ki8gaGludCIKY2FzZSBDLm5lOnJldHVybiJBZGQgLyohKi8gaGludCIKY2FzZSBD
+LndWOnJldHVybiJSZW1vdmUgLyo/Ki8gaGludCIKY2FzZSBDLmZSOnJldHVybiJSZW1vdmUgLyohKi8g
+aGludCIKY2FzZSBDLm15OnJldHVybiJDaGFuZ2UgdG8gLyo/Ki8gaGludCIKY2FzZSBDLnJ4OnJldHVy
+biJDaGFuZ2UgdG8gLyohKi8gaGludCJ9cmV0dXJuIG51bGx9LApMTDpmdW5jdGlvbiBMTChhLGIpe3Ro
+aXMuYT1hCnRoaXMuYj1ifSwKTUQ6ZnVuY3Rpb24gTUQoYSl7dGhpcy5hPWF9LApINzpmdW5jdGlvbiBI
+NyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifX0sTT17CllGOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAs
+byxuLG0sbApmb3Iocz1iLmxlbmd0aCxyPTE7cjxzOysrcil7aWYoYltyXT09bnVsbHx8YltyLTFdIT1u
+dWxsKWNvbnRpbnVlCmZvcig7cz49MTtzPXEpe3E9cy0xCmlmKGJbcV0hPW51bGwpYnJlYWt9cD1uZXcg
+UC5SbigiIikKbz1hKyIoIgpwLmE9bwpuPUgudDYoYikKbT1uLkMoIm5IPDE+IikKbD1uZXcgSC5uSChi
+LDAscyxtKQpsLkhkKGIsMCxzLG4uYykKbT1vK25ldyBILmxKKGwsbS5DKCJxVShhTC5FKSIpLmEobmV3
+IE0uTm8oKSksbS5DKCJsSjxhTC5FLHFVPiIpKS5rKDAsIiwgIikKcC5hPW0KcC5hPW0rKCIpOiBwYXJ0
+ICIrKHItMSkrIiB3YXMgbnVsbCwgYnV0IHBhcnQgIityKyIgd2FzIG5vdC4iKQp0aHJvdyBILmIoUC54
+WShwLncoMCkpKX19LApsSTpmdW5jdGlvbiBsSShhKXt0aGlzLmE9YX0sCnE3OmZ1bmN0aW9uIHE3KCl7
+fSwKTm86ZnVuY3Rpb24gTm8oKXt9fSxYPXsKQ0w6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG49
+Yi54WihhKQpiLmhLKGEpCmlmKG4hPW51bGwpYT1KLktWKGEsbi5sZW5ndGgpCnM9dC5zCnI9SC5WTShb
+XSxzKQpxPUguVk0oW10scykKcz1hLmxlbmd0aAppZihzIT09MCYmYi5yNChDLnhCLlcoYSwwKSkpe2lm
+KDA+PXMpcmV0dXJuIEguT0goYSwwKQpDLk5tLmkocSxhWzBdKQpwPTF9ZWxzZXtDLk5tLmkocSwiIikK
+cD0wfWZvcihvPXA7bzxzOysrbylpZihiLnI0KEMueEIuVyhhLG8pKSl7Qy5ObS5pKHIsQy54Qi5Oaihh
+LHAsbykpCkMuTm0uaShxLGFbb10pCnA9bysxfWlmKHA8cyl7Qy5ObS5pKHIsQy54Qi55bihhLHApKQpD
+Lk5tLmkocSwiIil9cmV0dXJuIG5ldyBYLldEKGIsbixyLHEpfSwKV0Q6ZnVuY3Rpb24gV0QoYSxiLGMs
+ZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9YwpfLmU9ZH0sCkk3OmZ1bmN0aW9uKGEpe3JldHVy
+biBuZXcgWC5kdihhKX0sCmR2OmZ1bmN0aW9uIGR2KGEpe3RoaXMuYT1hfX0sTz17ClJoOmZ1bmN0aW9u
+KCl7dmFyIHMscj1udWxsCmlmKFAudW8oKS5nRmkoKSE9PSJmaWxlIilyZXR1cm4gJC5FYigpCnM9UC51
+bygpCmlmKCFDLnhCLlRjKHMuZ0lpKHMpLCIvIikpcmV0dXJuICQuRWIoKQppZihQLktMKHIsImEvYiIs
+cixyLHIscixyKS50NCgpPT09ImFcXGIiKXJldHVybiAkLktrKCkKcmV0dXJuICQuYkQoKX0sCnpMOmZ1
+bmN0aW9uIHpMKCl7fX0sRT17T0Y6ZnVuY3Rpb24gT0YoYSxiLGMpe3RoaXMuZD1hCnRoaXMuZT1iCnRo
+aXMuZj1jfX0sRj17cnU6ZnVuY3Rpb24gcnUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9Ygpf
+LmY9YwpfLnI9ZH19LEQ9ewphYjpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89bnVsbAp0cnl7bz1QLnVv
+KCl9Y2F0Y2gocyl7aWYodC5nOC5iKEguUnUocykpKXtyPSQuRmYKaWYociE9bnVsbClyZXR1cm4gcgp0
+aHJvdyBzfWVsc2UgdGhyb3cgc31pZihKLlJNKG8sJC5JNikpe3I9JC5GZgpyLnRvU3RyaW5nCnJldHVy
+biByfSQuSTY9bwppZigkLkhrKCk9PSQuRWIoKSlyPSQuRmY9by5aSSgiLiIpLncoMCkKZWxzZXtxPW8u
+dDQoKQpwPXEubGVuZ3RoLTEKcj0kLkZmPXA9PT0wP3E6Qy54Qi5OaihxLDAscCl9ci50b1N0cmluZwpy
+ZXR1cm4gcn19CnZhciB3PVtDLEgsSixQLFcsVSxCLFQsTCxSLE0sWCxPLEUsRixEXQpodW5rSGVscGVy
+cy5zZXRGdW5jdGlvbk5hbWVzSWZOZWNlc3NhcnkodykKdmFyICQ9e30KSC5GSy5wcm90b3R5cGU9e30K
+Si5Hdi5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3JldHVybiBhPT09Yn0sCmdpTzpmdW5jdGlv
+bihhKXtyZXR1cm4gSC5lUShhKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIkluc3RhbmNlIG9mICciK0gu
+RWooSC5NKGEpKSsiJyJ9LAplNzpmdW5jdGlvbihhLGIpe3Quby5hKGIpCnRocm93IEguYihQLmxyKGEs
+Yi5nV2EoKSxiLmduZCgpLGIuZ1ZtKCkpKX19CkoueUUucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXty
+ZXR1cm4gU3RyaW5nKGEpfSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBhPzUxOTAxODoyMTgxNTl9LAok
+aWEyOjF9Ckoud2UucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbnVsbD09Yn0sCnc6
+ZnVuY3Rpb24oYSl7cmV0dXJuIm51bGwifSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiAwfSwKZTc6ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5TaihhLHQuby5hKGIpKX0sCiRpYzg6MX0KSi5NRi5wcm90b3R5
+cGU9ewpnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIDB9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmco
+YSl9LAokaXZtOjF9CkouaUMucHJvdG90eXBlPXt9Ckoua2QucHJvdG90eXBlPXt9CkouYzUucHJvdG90
+eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz1hWyQudygpXQppZihzPT1udWxsKXJldHVybiB0aGlzLnQo
+YSkKcmV0dXJuIkphdmFTY3JpcHQgZnVuY3Rpb24gZm9yICIrSC5FaihKLmoocykpfSwKJGlFSDoxfQpK
+LmpkLnByb3RvdHlwZT17CmRyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILmpWKGEsSC50NihhKS5D
+KCJAPDE+IikuS3EoYikuQygialY8MSwyPiIpKX0sCmk6ZnVuY3Rpb24oYSxiKXtILnQ2KGEpLmMuYShi
+KQppZighIWEuZml4ZWQkbGVuZ3RoKUgudihQLkw0KCJhZGQiKSkKYS5wdXNoKGIpfSwKVzQ6ZnVuY3Rp
+b24oYSxiKXt2YXIgcwppZighIWEuZml4ZWQkbGVuZ3RoKUgudihQLkw0KCJyZW1vdmVBdCIpKQpzPWEu
+bGVuZ3RoCmlmKGI+PXMpdGhyb3cgSC5iKFAuTzcoYixudWxsKSkKcmV0dXJuIGEuc3BsaWNlKGIsMSlb
+MF19LApVRzpmdW5jdGlvbihhLGIsYyl7dmFyIHMscgpILnQ2KGEpLkMoImNYPDE+IikuYShjKQppZigh
+IWEuZml4ZWQkbGVuZ3RoKUgudihQLkw0KCJpbnNlcnRBbGwiKSkKUC53QShiLDAsYS5sZW5ndGgsImlu
+ZGV4IikKaWYoIXQuZC5iKGMpKWM9Si5SWChjKQpzPUouSG0oYykKYS5sZW5ndGg9YS5sZW5ndGgrcwpy
+PWIrcwp0aGlzLllXKGEscixhLmxlbmd0aCxhLGIpCnRoaXMudmcoYSxiLHIsYyl9LApGVjpmdW5jdGlv
+bihhLGIpe3ZhciBzCkgudDYoYSkuQygiY1g8MT4iKS5hKGIpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC52
+KFAuTDQoImFkZEFsbCIpKQppZihBcnJheS5pc0FycmF5KGIpKXt0aGlzLktoKGEsYikKcmV0dXJufWZv
+cihzPUouSVQoYik7cy5GKCk7KWEucHVzaChzLmdsKCkpfSwKS2g6ZnVuY3Rpb24oYSxiKXt2YXIgcyxy
+CnQuYi5hKGIpCnM9Yi5sZW5ndGgKaWYocz09PTApcmV0dXJuCmlmKGE9PT1iKXRocm93IEguYihQLmE0
+KGEpKQpmb3Iocj0wO3I8czsrK3IpYS5wdXNoKGJbcl0pfSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBz
+PUgudDYoYSkKcmV0dXJuIG5ldyBILmxKKGEscy5LcShjKS5DKCIxKDIpIikuYShiKSxzLkMoIkA8MT4i
+KS5LcShjKS5DKCJsSjwxLDI+IikpfSwKazpmdW5jdGlvbihhLGIpe3ZhciBzLHI9UC5POChhLmxlbmd0
+aCwiIiwhMSx0Lk4pCmZvcihzPTA7czxhLmxlbmd0aDsrK3MpdGhpcy5ZNShyLHMsSC5FaihhW3NdKSkK
+cmV0dXJuIHIuam9pbihiKX0sCmVSOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEgucUMoYSxiLG51bGwsSC50
+NihhKS5jKX0sCk4wOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscQpkLmEoYikKSC50NihhKS5LcShk
+KS5DKCIxKDEsMikiKS5hKGMpCnM9YS5sZW5ndGgKZm9yKHI9YixxPTA7cTxzOysrcSl7cj1jLiQyKHIs
+YVtxXSkKaWYoYS5sZW5ndGghPT1zKXRocm93IEguYihQLmE0KGEpKX1yZXR1cm4gcn0sCkh0OmZ1bmN0
+aW9uKGEsYil7dmFyIHMscixxLHAsbwpILnQ2KGEpLkMoImEyKDEpIikuYShiKQpzPWEubGVuZ3RoCmZv
+cihyPW51bGwscT0hMSxwPTA7cDxzOysrcCl7bz1hW3BdCmlmKEgub1QoYi4kMShvKSkpe2lmKHEpdGhy
+b3cgSC5iKEguQW0oKSkKcj1vCnE9ITB9aWYocyE9PWEubGVuZ3RoKXRocm93IEguYihQLmE0KGEpKX1p
+ZihxKXJldHVybiByCnRocm93IEguYihILldwKCkpfSwKRTpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49
+YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCmd0SDpmdW5jdGlvbihhKXtpZihh
+Lmxlbmd0aD4wKXJldHVybiBhWzBdCnRocm93IEguYihILldwKCkpfSwKZ3JaOmZ1bmN0aW9uKGEpe3Zh
+ciBzPWEubGVuZ3RoCmlmKHM+MClyZXR1cm4gYVtzLTFdCnRocm93IEguYihILldwKCkpfSwKWVc6ZnVu
+Y3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvCkgudDYoYSkuQygiY1g8MT4iKS5hKGQpCmlmKCEh
+YS5pbW11dGFibGUkbGlzdClILnYoUC5MNCgic2V0UmFuZ2UiKSkKUC5qQihiLGMsYS5sZW5ndGgpCnM9
+Yy1iCmlmKHM9PT0wKXJldHVybgpQLmsxKGUsInNraXBDb3VudCIpCmlmKHQuai5iKGQpKXtyPWQKcT1l
+fWVsc2V7cj1KLkE1KGQsZSkudHQoMCwhMSkKcT0wfXA9Si5VNihyKQppZihxK3M+cC5nQShyKSl0aHJv
+dyBILmIoSC5hcigpKQppZihxPGIpZm9yKG89cy0xO28+PTA7LS1vKWFbYitvXT1wLnEocixxK28pCmVs
+c2UgZm9yKG89MDtvPHM7KytvKWFbYitvXT1wLnEocixxK28pfSwKdmc6ZnVuY3Rpb24oYSxiLGMsZCl7
+cmV0dXJuIHRoaXMuWVcoYSxiLGMsZCwwKX0sClZyOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpILnQ2KGEp
+LkMoImEyKDEpIikuYShiKQpzPWEubGVuZ3RoCmZvcihyPTA7cjxzOysrcil7aWYoSC5vVChiLiQxKGFb
+cl0pKSlyZXR1cm4hMAppZihhLmxlbmd0aCE9PXMpdGhyb3cgSC5iKFAuYTQoYSkpfXJldHVybiExfSwK
+dGc6ZnVuY3Rpb24oYSxiKXt2YXIgcwpmb3Iocz0wO3M8YS5sZW5ndGg7KytzKWlmKEouUk0oYVtzXSxi
+KSlyZXR1cm4hMApyZXR1cm4hMX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGg9PT0wfSwK
+Z29yOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aCE9PTB9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQ
+LldFKGEsIlsiLCJdIil9LAp0dDpmdW5jdGlvbihhLGIpe3ZhciBzPUguVk0oYS5zbGljZSgwKSxILnQ2
+KGEpKQpyZXR1cm4gc30sCmJyOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnR0KGEsITApfSwKZ206ZnVu
+Y3Rpb24oYSl7cmV0dXJuIG5ldyBKLm0xKGEsYS5sZW5ndGgsSC50NihhKS5DKCJtMTwxPiIpKX0sCmdp
+TzpmdW5jdGlvbihhKXtyZXR1cm4gSC5lUShhKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0
+aH0sCnNBOmZ1bmN0aW9uKGEsYil7aWYoISFhLmZpeGVkJGxlbmd0aClILnYoUC5MNCgic2V0IGxlbmd0
+aCIpKQppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLG51bGwsIm5ld0xlbmd0aCIsbnVsbCkpCmEubGVu
+Z3RoPWJ9LApxOmZ1bmN0aW9uKGEsYil7SC51UChiKQppZihiPj1hLmxlbmd0aHx8YjwwKXRocm93IEgu
+YihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKWTU6ZnVuY3Rpb24oYSxiLGMpe0gudDYoYSkuYy5hKGMp
+CmlmKCEhYS5pbW11dGFibGUkbGlzdClILnYoUC5MNCgiaW5kZXhlZCBzZXQiKSkKaWYoYj49YS5sZW5n
+dGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQphW2JdPWN9LAokaWJROjEsCiRpY1g6MSwKJGl6TTox
+fQpKLlBvLnByb3RvdHlwZT17fQpKLm0xLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRo
+aXMuZH0sCkY6ZnVuY3Rpb24oKXt2YXIgcyxyPXRoaXMscT1yLmEscD1xLmxlbmd0aAppZihyLmIhPT1w
+KXRocm93IEguYihILmxrKHEpKQpzPXIuYwppZihzPj1wKXtyLnNNKG51bGwpCnJldHVybiExfXIuc00o
+cVtzXSk7KytyLmMKcmV0dXJuITB9LApzTTpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuQygiMT8i
+KS5hKGEpfSwKJGlBbjoxfQpKLnFJLnByb3RvdHlwZT17CnpROmZ1bmN0aW9uKGEpe2lmKGE+MCl7aWYo
+YSE9PTEvMClyZXR1cm4gTWF0aC5yb3VuZChhKX1lbHNlIGlmKGE+LTEvMClyZXR1cm4gMC1NYXRoLnJv
+dW5kKDAtYSkKdGhyb3cgSC5iKFAuTDQoIiIrYSsiLnJvdW5kKCkiKSl9LAp3OmZ1bmN0aW9uKGEpe2lm
+KGE9PT0wJiYxL2E8MClyZXR1cm4iLTAuMCIKZWxzZSByZXR1cm4iIithfSwKZ2lPOmZ1bmN0aW9uKGEp
+e3ZhciBzLHIscSxwLG89YXwwCmlmKGE9PT1vKXJldHVybiBvJjUzNjg3MDkxMQpzPU1hdGguYWJzKGEp
+CnI9TWF0aC5sb2cocykvMC42OTMxNDcxODA1NTk5NDUzfDAKcT1NYXRoLnBvdygyLHIpCnA9czwxP3Mv
+cTpxL3MKcmV0dXJuKChwKjkwMDcxOTkyNTQ3NDA5OTJ8MCkrKHAqMzU0MjI0MzE4MTE3NjUyMXwwKSkq
+NTk5MTk3K3IqMTI1OSY1MzY4NzA5MTF9LAp6WTpmdW5jdGlvbihhLGIpe3ZhciBzPWElYgppZihzPT09
+MClyZXR1cm4gMAppZihzPjApcmV0dXJuIHMKaWYoYjwwKXJldHVybiBzLWIKZWxzZSByZXR1cm4gcyti
+fSwKQlU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4oYXwwKT09PWE/YS9ifDA6dGhpcy5ESihhLGIpfSwKREo6
+ZnVuY3Rpb24oYSxiKXt2YXIgcz1hL2IKaWYocz49LTIxNDc0ODM2NDgmJnM8PTIxNDc0ODM2NDcpcmV0
+dXJuIHN8MAppZihzPjApe2lmKHMhPT0xLzApcmV0dXJuIE1hdGguZmxvb3Iocyl9ZWxzZSBpZihzPi0x
+LzApcmV0dXJuIE1hdGguY2VpbChzKQp0aHJvdyBILmIoUC5MNCgiUmVzdWx0IG9mIHRydW5jYXRpbmcg
+ZGl2aXNpb24gaXMgIitILkVqKHMpKyI6ICIrSC5FaihhKSsiIH4vICIrYikpfSwKd0c6ZnVuY3Rpb24o
+YSxiKXt2YXIgcwppZihhPjApcz10aGlzLnAzKGEsYikKZWxzZXtzPWI+MzE/MzE6YgpzPWE+PnM+Pj4w
+fXJldHVybiBzfSwKYmY6ZnVuY3Rpb24oYSxiKXtpZihiPDApdGhyb3cgSC5iKEgudEwoYikpCnJldHVy
+biB0aGlzLnAzKGEsYil9LApwMzpmdW5jdGlvbihhLGIpe3JldHVybiBiPjMxPzA6YT4+PmJ9LAokaUNQ
+OjEsCiRpWlo6MX0KSi5iVS5wcm90b3R5cGU9eyRpQjI6MX0KSi5WQS5wcm90b3R5cGU9e30KSi5Eci5w
+cm90b3R5cGU9ewpPOmZ1bmN0aW9uKGEsYil7aWYoYjwwKXRocm93IEguYihILkhZKGEsYikpCmlmKGI+
+PWEubGVuZ3RoKUgudihILkhZKGEsYikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LApXOmZ1bmN0aW9u
+KGEsYil7aWYoYj49YS5sZW5ndGgpdGhyb3cgSC5iKEguSFkoYSxiKSkKcmV0dXJuIGEuY2hhckNvZGVB
+dChiKX0sCmRkOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILnVuKGIsYSwwKX0sCmg6ZnVuY3Rpb24o
+YSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyIpdGhyb3cgSC5iKFAuTDMoYixudWxsLG51bGwpKQpyZXR1
+cm4gYStifSwKVGM6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iLmxlbmd0aCxyPWEubGVuZ3RoCmlmKHM+cily
+ZXR1cm4hMQpyZXR1cm4gYj09PXRoaXMueW4oYSxyLXMpfSwKaTc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHM9UC5qQihiLGMsYS5sZW5ndGgpLHI9YS5zdWJzdHJpbmcoMCxiKSxxPWEuc3Vic3RyaW5nKHMpCnJl
+dHVybiByK2QrcX0sClFpOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwppZihjPDB8fGM+YS5sZW5ndGgpdGhy
+b3cgSC5iKFAuVEUoYywwLGEubGVuZ3RoLG51bGwsbnVsbCkpCnM9YytiLmxlbmd0aAppZihzPmEubGVu
+Z3RoKXJldHVybiExCnJldHVybiBiPT09YS5zdWJzdHJpbmcoYyxzKX0sCm46ZnVuY3Rpb24oYSxiKXty
+ZXR1cm4gdGhpcy5RaShhLGIsMCl9LApOajpmdW5jdGlvbihhLGIsYyl7aWYoYz09bnVsbCljPWEubGVu
+Z3RoCmlmKGI8MCl0aHJvdyBILmIoUC5PNyhiLG51bGwpKQppZihiPmMpdGhyb3cgSC5iKFAuTzcoYixu
+dWxsKSkKaWYoYz5hLmxlbmd0aCl0aHJvdyBILmIoUC5PNyhjLG51bGwpKQpyZXR1cm4gYS5zdWJzdHJp
+bmcoYixjKX0sCnluOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuTmooYSxiLG51bGwpfSwKaGM6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIGEudG9Mb3dlckNhc2UoKX0sCmJTOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxw
+PWEudHJpbSgpLG89cC5sZW5ndGgKaWYobz09PTApcmV0dXJuIHAKaWYodGhpcy5XKHAsMCk9PT0xMzMp
+e3M9Si5tbShwLDEpCmlmKHM9PT1vKXJldHVybiIifWVsc2Ugcz0wCnI9by0xCnE9dGhpcy5PKHAscik9
+PT0xMzM/Si5jMShwLHIpOm8KaWYocz09PTAmJnE9PT1vKXJldHVybiBwCnJldHVybiBwLnN1YnN0cmlu
+ZyhzLHEpfSwKVDpmdW5jdGlvbihhLGIpe3ZhciBzLHIKaWYoMD49YilyZXR1cm4iIgppZihiPT09MXx8
+YS5sZW5ndGg9PT0wKXJldHVybiBhCmlmKGIhPT1iPj4+MCl0aHJvdyBILmIoQy5FcSkKZm9yKHM9YSxy
+PSIiOyEwOyl7aWYoKGImMSk9PT0xKXI9cytyCmI9Yj4+PjEKaWYoYj09PTApYnJlYWsKcys9c31yZXR1
+cm4gcn0sClhVOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwppZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5i
+KFAuVEUoYywwLGEubGVuZ3RoLG51bGwsbnVsbCkpCnM9YS5pbmRleE9mKGIsYykKcmV0dXJuIHN9LApP
+WTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlhVKGEsYiwwKX0sClBrOmZ1bmN0aW9uKGEsYixjKXt2
+YXIgcyxyCmlmKGM9PW51bGwpYz1hLmxlbmd0aAplbHNlIGlmKGM8MHx8Yz5hLmxlbmd0aCl0aHJvdyBI
+LmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKcz1iLmxlbmd0aApyPWEubGVuZ3RoCmlmKGMr
+cz5yKWM9ci1zCnJldHVybiBhLmxhc3RJbmRleE9mKGIsYyl9LApjbjpmdW5jdGlvbihhLGIpe3JldHVy
+biB0aGlzLlBrKGEsYixudWxsKX0sCklzOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1hLmxlbmd0aAppZihj
+PnMpdGhyb3cgSC5iKFAuVEUoYywwLHMsbnVsbCxudWxsKSkKcmV0dXJuIEguU1EoYSxiLGMpfSwKdGc6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5JcyhhLGIsMCl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBh
+fSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzLHIscQpmb3Iocz1hLmxlbmd0aCxyPTAscT0wO3E8czsrK3Ep
+e3I9cithLmNoYXJDb2RlQXQocSkmNTM2ODcwOTExCnI9cisoKHImNTI0Mjg3KTw8MTApJjUzNjg3MDkx
+MQpyXj1yPj42fXI9cisoKHImNjcxMDg4NjMpPDwzKSY1MzY4NzA5MTEKcl49cj4+MTEKcmV0dXJuIHIr
+KChyJjE2MzgzKTw8MTUpJjUzNjg3MDkxMX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0s
+CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCmlmKGI+PWEubGVuZ3RofHwhMSl0aHJvdyBILmIoSC5IWShh
+LGIpKQpyZXR1cm4gYVtiXX0sCiRpdlg6MSwKJGlxVToxfQpILkJSLnByb3RvdHlwZT17CmdtOmZ1bmN0
+aW9uKGEpe3ZhciBzPUguTGgodGhpcykKcmV0dXJuIG5ldyBILkU3KEouSVQodGhpcy5nT04oKSkscy5D
+KCJAPDE+IikuS3Eocy5RWzFdKS5DKCJFNzwxLDI+IikpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIEou
+SG0odGhpcy5nT04oKSl9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIEoudVUodGhpcy5nT04oKSl9LApn
+b3I6ZnVuY3Rpb24oYSl7cmV0dXJuIEouRjcodGhpcy5nT04oKSl9LAplUjpmdW5jdGlvbihhLGIpe3Zh
+ciBzPUguTGgodGhpcykKcmV0dXJuIEguR0ooSi5BNSh0aGlzLmdPTigpLGIpLHMuYyxzLlFbMV0pfSwK
+RTpmdW5jdGlvbihhLGIpe3JldHVybiBILkxoKHRoaXMpLlFbMV0uYShKLkdBKHRoaXMuZ09OKCksYikp
+fSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gSi5qKHRoaXMuZ09OKCkpfX0KSC5FNy5wcm90b3R5cGU9ewpG
+OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5GKCl9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLiR0
+aS5RWzFdLmEodGhpcy5hLmdsKCkpfSwKJGlBbjoxfQpILlp5LnByb3RvdHlwZT17CmdPTjpmdW5jdGlv
+bigpe3JldHVybiB0aGlzLmF9fQpILm9sLnByb3RvdHlwZT17JGliUToxfQpILlVxLnByb3RvdHlwZT17
+CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy4kdGkuUVsxXS5hKEoueDkodGhpcy5hLEgudVAoYikp
+KX0sClk1OmZ1bmN0aW9uKGEsYixjKXt2YXIgcz10aGlzLiR0aQpKLnU5KHRoaXMuYSxiLHMuYy5hKHMu
+UVsxXS5hKGMpKSl9LAokaWJROjEsCiRpek06MX0KSC5qVi5wcm90b3R5cGU9ewpkcjpmdW5jdGlvbihh
+LGIpe3JldHVybiBuZXcgSC5qVih0aGlzLmEsdGhpcy4kdGkuQygiQDwxPiIpLktxKGIpLkMoImpWPDEs
+Mj4iKSl9LApnT046ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hfX0KSC5uLnByb3RvdHlwZT17Cnc6ZnVu
+Y3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVybiBzIT1udWxsPyJMYXRlSW5pdGlhbGl6YXRpb25FcnJv
+cjogIitzOiJMYXRlSW5pdGlhbGl6YXRpb25FcnJvciJ9fQpILnIzLnByb3RvdHlwZT17Cnc6ZnVuY3Rp
+b24oYSl7dmFyIHM9IlJlYWNoYWJpbGl0eUVycm9yOiAiK3RoaXMuYQpyZXR1cm4gc319CkgucWoucHJv
+dG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEs
+Yil7cmV0dXJuIEMueEIuTyh0aGlzLmEsSC51UChiKSl9fQpILkdNLnByb3RvdHlwZT17Cnc6ZnVuY3Rp
+b24oYSl7cmV0dXJuIk51bGwgaXMgbm90IGEgdmFsaWQgdmFsdWUgZm9yIHRoZSBwYXJhbWV0ZXIgJyIr
+dGhpcy5hKyInIG9mIHR5cGUgJyIrSC5LeCh0aGlzLiR0aS5jKS53KDApKyInIn19CkguYlEucHJvdG90
+eXBlPXt9CkguYUwucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcwpyZXR1cm4gbmV3
+IEguYTcocyxzLmdBKHMpLEguTGgocykuQygiYTc8YUwuRT4iKSl9LApnbDA6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHRoaXMuZ0EodGhpcyk9PT0wfSwKazpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwPXRoaXMsbz1w
+LmdBKHApCmlmKGIubGVuZ3RoIT09MCl7aWYobz09PTApcmV0dXJuIiIKcz1ILkVqKHAuRSgwLDApKQpp
+ZihvIT09cC5nQShwKSl0aHJvdyBILmIoUC5hNChwKSkKZm9yKHI9cyxxPTE7cTxvOysrcSl7cj1yK2Ir
+SC5FaihwLkUoMCxxKSkKaWYobyE9PXAuZ0EocCkpdGhyb3cgSC5iKFAuYTQocCkpfXJldHVybiByLmNo
+YXJDb2RlQXQoMCk9PTA/cjpyfWVsc2V7Zm9yKHE9MCxyPSIiO3E8bzsrK3Epe3IrPUguRWoocC5FKDAs
+cSkpCmlmKG8hPT1wLmdBKHApKXRocm93IEguYihQLmE0KHApKX1yZXR1cm4gci5jaGFyQ29kZUF0KDAp
+PT0wP3I6cn19LApldjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLkdHKDAsSC5MaCh0aGlzKS5DKCJh
+MihhTC5FKSIpLmEoYikpfSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPUguTGgodGhpcykKcmV0dXJu
+IG5ldyBILmxKKHRoaXMscy5LcShjKS5DKCIxKGFMLkUpIikuYShiKSxzLkMoIkA8YUwuRT4iKS5LcShj
+KS5DKCJsSjwxLDI+IikpfSwKZVI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5xQyh0aGlzLGIsbnVsbCxI
+LkxoKHRoaXMpLkMoImFMLkUiKSl9LAp0dDpmdW5jdGlvbihhLGIpe3JldHVybiBQLlkxKHRoaXMsITAs
+SC5MaCh0aGlzKS5DKCJhTC5FIikpfSwKYnI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMudHQoYSwhMCl9
+fQpILm5ILnByb3RvdHlwZT17CkhkOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHI9dGhpcy5iClAuazEo
+ciwic3RhcnQiKQpzPXRoaXMuYwppZihzIT1udWxsKXtQLmsxKHMsImVuZCIpCmlmKHI+cyl0aHJvdyBI
+LmIoUC5URShyLDAscywic3RhcnQiLG51bGwpKX19LApnVUQ6ZnVuY3Rpb24oKXt2YXIgcz1KLkhtKHRo
+aXMuYSkscj10aGlzLmMKaWYocj09bnVsbHx8cj5zKXJldHVybiBzCnJldHVybiByfSwKZ0FzOmZ1bmN0
+aW9uKCl7dmFyIHM9Si5IbSh0aGlzLmEpLHI9dGhpcy5iCmlmKHI+cylyZXR1cm4gcwpyZXR1cm4gcn0s
+CmdBOmZ1bmN0aW9uKGEpe3ZhciBzLHI9Si5IbSh0aGlzLmEpLHE9dGhpcy5iCmlmKHE+PXIpcmV0dXJu
+IDAKcz10aGlzLmMKaWYocz09bnVsbHx8cz49cilyZXR1cm4gci1xCmlmKHR5cGVvZiBzIT09Im51bWJl
+ciIpcmV0dXJuIHMuSE4oKQpyZXR1cm4gcy1xfSwKRTpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMscj1z
+LmdBcygpK2IKaWYoYjwwfHxyPj1zLmdVRCgpKXRocm93IEguYihQLkNmKGIscywiaW5kZXgiLG51bGws
+bnVsbCkpCnJldHVybiBKLkdBKHMuYSxyKX0sCmVSOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPXRoaXMK
+UC5rMShiLCJjb3VudCIpCnM9cS5iK2IKcj1xLmMKaWYociE9bnVsbCYmcz49cilyZXR1cm4gbmV3IEgu
+TUIocS4kdGkuQygiTUI8MT4iKSkKcmV0dXJuIEgucUMocS5hLHMscixxLiR0aS5jKX0sCnR0OmZ1bmN0
+aW9uKGEsYil7dmFyIHMscixxLHA9dGhpcyxvPXAuYixuPXAuYSxtPUouVTYobiksbD1tLmdBKG4pLGs9
+cC5jCmlmKGshPW51bGwmJms8bClsPWsKaWYodHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4gbC5ITigp
+CnM9bC1vCmlmKHM8PTApe249Si5RaSgwLHAuJHRpLmMpCnJldHVybiBufXI9UC5POChzLG0uRShuLG8p
+LCExLHAuJHRpLmMpCmZvcihxPTE7cTxzOysrcSl7Qy5ObS5ZNShyLHEsbS5FKG4sbytxKSkKaWYobS5n
+QShuKTxsKXRocm93IEguYihQLmE0KHApKX1yZXR1cm4gcn19CkguYTcucHJvdG90eXBlPXsKZ2w6ZnVu
+Y3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3ZhciBzLHI9dGhpcyxxPXIuYSxwPUou
+VTYocSksbz1wLmdBKHEpCmlmKHIuYiE9PW8pdGhyb3cgSC5iKFAuYTQocSkpCnM9ci5jCmlmKHM+PW8p
+e3Iuc0kobnVsbCkKcmV0dXJuITF9ci5zSShwLkUocSxzKSk7KytyLmMKcmV0dXJuITB9LApzSTpmdW5j
+dGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuQygiMT8iKS5hKGEpfSwKJGlBbjoxfQpILmkxLnByb3RvdHlw
+ZT17CmdtOmZ1bmN0aW9uKGEpe3ZhciBzPUguTGgodGhpcykKcmV0dXJuIG5ldyBILk1IKEouSVQodGhp
+cy5hKSx0aGlzLmIscy5DKCJAPDE+IikuS3Eocy5RWzFdKS5DKCJNSDwxLDI+IikpfSwKZ0E6ZnVuY3Rp
+b24oYSl7cmV0dXJuIEouSG0odGhpcy5hKX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gSi51VSh0aGlz
+LmEpfSwKRTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmIuJDEoSi5HQSh0aGlzLmEsYikpfX0KSC54
+eS5wcm90b3R5cGU9eyRpYlE6MX0KSC5NSC5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHM9dGhp
+cyxyPXMuYgppZihyLkYoKSl7cy5zSShzLmMuJDEoci5nbCgpKSkKcmV0dXJuITB9cy5zSShudWxsKQpy
+ZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYX0sCnNJOmZ1bmN0aW9uKGEpe3RoaXMu
+YT10aGlzLiR0aS5DKCIyPyIpLmEoYSl9fQpILmxKLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBKLkhtKHRoaXMuYSl9LApFOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYi4kMShKLkdBKHRo
+aXMuYSxiKSl9fQpILlU1LnByb3RvdHlwZT17CmdtOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5TTyhK
+LklUKHRoaXMuYSksdGhpcy5iLHRoaXMuJHRpLkMoIlNPPDE+IikpfX0KSC5TTy5wcm90b3R5cGU9ewpG
+OmZ1bmN0aW9uKCl7dmFyIHMscgpmb3Iocz10aGlzLmEscj10aGlzLmI7cy5GKCk7KWlmKEgub1Qoci4k
+MShzLmdsKCkpKSlyZXR1cm4hMApyZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5n
+bCgpfX0KSC5BTS5wcm90b3R5cGU9ewplUjpmdW5jdGlvbihhLGIpe1AuTVIoYiwiY291bnQiLHQuUykK
+UC5rMShiLCJjb3VudCIpCnJldHVybiBuZXcgSC5BTSh0aGlzLmEsdGhpcy5iK2IsSC5MaCh0aGlzKS5D
+KCJBTTwxPiIpKX0sCmdtOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5VMShKLklUKHRoaXMuYSksdGhp
+cy5iLEguTGgodGhpcykuQygiVTE8MT4iKSl9fQpILmQ1LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEp
+e3ZhciBzPUouSG0odGhpcy5hKS10aGlzLmIKaWYocz49MClyZXR1cm4gcwpyZXR1cm4gMH0sCmVSOmZ1
+bmN0aW9uKGEsYil7UC5NUihiLCJjb3VudCIsdC5TKQpQLmsxKGIsImNvdW50IikKcmV0dXJuIG5ldyBI
+LmQ1KHRoaXMuYSx0aGlzLmIrYix0aGlzLiR0aSl9LAokaWJROjF9CkguVTEucHJvdG90eXBlPXsKRjpm
+dW5jdGlvbigpe3ZhciBzLHIKZm9yKHM9dGhpcy5hLHI9MDtyPHRoaXMuYjsrK3Ipcy5GKCkKdGhpcy5i
+PTAKcmV0dXJuIHMuRigpfSwKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hLmdsKCl9fQpILk1CLnBy
+b3RvdHlwZT17CmdtOmZ1bmN0aW9uKGEpe3JldHVybiBDLkd3fSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVy
+biEwfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIDB9LApFOmZ1bmN0aW9uKGEsYil7dGhyb3cgSC5iKFAu
+VEUoYiwwLDAsImluZGV4IixudWxsKSl9LAplUjpmdW5jdGlvbihhLGIpe1AuazEoYiwiY291bnQiKQpy
+ZXR1cm4gdGhpc319CkguRnUucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3JldHVybiExfSwKZ2w6ZnVu
+Y3Rpb24oKXt0aHJvdyBILmIoSC5XcCgpKX0sCiRpQW46MX0KSC51Ni5wcm90b3R5cGU9ewpnbTpmdW5j
+dGlvbihhKXtyZXR1cm4gbmV3IEguSkIoSi5JVCh0aGlzLmEpLHRoaXMuJHRpLkMoIkpCPDE+IikpfX0K
+SC5KQi5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHMscgpmb3Iocz10aGlzLmEscj10aGlzLiR0
+aS5jO3MuRigpOylpZihyLmIocy5nbCgpKSlyZXR1cm4hMApyZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7
+cmV0dXJuIHRoaXMuJHRpLmMuYSh0aGlzLmEuZ2woKSl9LAokaUFuOjF9CkguU1UucHJvdG90eXBlPXt9
+CkguUmUucHJvdG90eXBlPXsKWTU6ZnVuY3Rpb24oYSxiLGMpe0guTGgodGhpcykuQygiUmUuRSIpLmEo
+YykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgYW4gdW5tb2RpZmlhYmxlIGxpc3QiKSl9fQpI
+LncyLnByb3RvdHlwZT17fQpILnd2LnByb3RvdHlwZT17CmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlz
+Ll9oYXNoQ29kZQppZihzIT1udWxsKXJldHVybiBzCnM9NjY0NTk3KkouaGYodGhpcy5hKSY1MzY4NzA5
+MTEKdGhpcy5faGFzaENvZGU9cwpyZXR1cm4gc30sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuJ1N5bWJvbCgi
+JytILkVqKHRoaXMuYSkrJyIpJ30sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpy
+ZXR1cm4gYiBpbnN0YW5jZW9mIEgud3YmJnRoaXMuYT09Yi5hfSwKJGlHRDoxfQpILlFDLnByb3RvdHlw
+ZT17fQpILlBELnByb3RvdHlwZT17fQpILldVLnByb3RvdHlwZT17CmdsMDpmdW5jdGlvbihhKXtyZXR1
+cm4gdGhpcy5nQSh0aGlzKT09PTB9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKHRoaXMpfSwKWTU6
+ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPUguTGgodGhpcykKcy5jLmEoYikKcy5RWzFdLmEoYykKSC5kYygp
+CkguQmkodS5nKX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5xNChhLEguTGgodGhpcykuQygi
+TjM8MSwyPiIpKX0sCnE0OmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhpcwpyZXR1cm4gUC5sMChmdW5jdGlv
+bigpe3ZhciByPWEKdmFyIHE9MCxwPTEsbyxuLG0sbCxrCnJldHVybiBmdW5jdGlvbiAkYXN5bmMkZ1B1
+KGMsZCl7aWYoYz09PTEpe289ZApxPXB9d2hpbGUodHJ1ZSlzd2l0Y2gocSl7Y2FzZSAwOm49cy5ndmMo
+KSxuPW4uZ20obiksbT1ILkxoKHMpLG09bS5DKCJAPDE+IikuS3EobS5RWzFdKS5DKCJOMzwxLDI+IikK
+Y2FzZSAyOmlmKCFuLkYoKSl7cT0zCmJyZWFrfWw9bi5nbCgpCms9cy5xKDAsbCkKay50b1N0cmluZwpx
+PTQKcmV0dXJuIG5ldyBQLk4zKGwsayxtKQpjYXNlIDQ6cT0yCmJyZWFrCmNhc2UgMzpyZXR1cm4gUC5U
+aCgpCmNhc2UgMTpyZXR1cm4gUC5ZbShvKX19fSxiKX0sCiRpWjA6MX0KSC5MUC5wcm90b3R5cGU9ewpn
+QTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKeDQ6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGEhPSJz
+dHJpbmciKXJldHVybiExCmlmKCJfX3Byb3RvX18iPT09YSlyZXR1cm4hMQpyZXR1cm4gdGhpcy5iLmhh
+c093blByb3BlcnR5KGEpfSwKcTpmdW5jdGlvbihhLGIpe2lmKCF0aGlzLng0KGIpKXJldHVybiBudWxs
+CnJldHVybiB0aGlzLnFQKGIpfSwKcVA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYltILmgoYSldfSwK
+SzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG89SC5MaCh0aGlzKQpvLkMoIn4oMSwyKSIpLmEoYikK
+cz10aGlzLmMKZm9yKHI9cy5sZW5ndGgsbz1vLlFbMV0scT0wO3E8cjsrK3Epe3A9c1txXQpiLiQyKHAs
+by5hKHRoaXMucVAocCkpKX19LApndmM6ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEguWFIodGhpcyxILkxo
+KHRoaXMpLkMoIlhSPDE+IikpfX0KSC5YUi5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXt2YXIgcz10
+aGlzLmEuYwpyZXR1cm4gbmV3IEoubTEocyxzLmxlbmd0aCxILnQ2KHMpLkMoIm0xPDE+IikpfSwKZ0E6
+ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5jLmxlbmd0aH19CkguTEkucHJvdG90eXBlPXsKZ1dhOmZ1
+bmN0aW9uKCl7dmFyIHM9dGhpcy5hCnJldHVybiBzfSwKZ25kOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAs
+bz10aGlzCmlmKG8uYz09PTEpcmV0dXJuIEMuaFUKcz1vLmQKcj1zLmxlbmd0aC1vLmUubGVuZ3RoLW8u
+ZgppZihyPT09MClyZXR1cm4gQy5oVQpxPVtdCmZvcihwPTA7cDxyOysrcCl7aWYocD49cy5sZW5ndGgp
+cmV0dXJuIEguT0gocyxwKQpxLnB1c2goc1twXSl9cmV0dXJuIEouekMocSl9LApnVm06ZnVuY3Rpb24o
+KXt2YXIgcyxyLHEscCxvLG4sbSxsLGs9dGhpcwppZihrLmMhPT0wKXJldHVybiBDLldPCnM9ay5lCnI9
+cy5sZW5ndGgKcT1rLmQKcD1xLmxlbmd0aC1yLWsuZgppZihyPT09MClyZXR1cm4gQy5XTwpvPW5ldyBI
+Lk41KHQuZW8pCmZvcihuPTA7bjxyOysrbil7aWYobj49cy5sZW5ndGgpcmV0dXJuIEguT0gocyxuKQpt
+PXNbbl0KbD1wK24KaWYobDwwfHxsPj1xLmxlbmd0aClyZXR1cm4gSC5PSChxLGwpCm8uWTUoMCxuZXcg
+SC53dihtKSxxW2xdKX1yZXR1cm4gbmV3IEguUEQobyx0LmdGKX0sCiRpdlE6MX0KSC5Dai5wcm90b3R5
+cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzCkguaChhKQpzPXRoaXMuYQpzLmI9cy5iKyIkIitILkVq
+KGEpCkMuTm0uaSh0aGlzLmIsYSkKQy5ObS5pKHRoaXMuYyxiKTsrK3MuYX0sCiRTOjEzfQpILmY5LnBy
+b3RvdHlwZT17CnFTOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzLHA9bmV3IFJlZ0V4cChxLmEpLmV4
+ZWMoYSkKaWYocD09bnVsbClyZXR1cm4gbnVsbApzPU9iamVjdC5jcmVhdGUobnVsbCkKcj1xLmIKaWYo
+ciE9PS0xKXMuYXJndW1lbnRzPXBbcisxXQpyPXEuYwppZihyIT09LTEpcy5hcmd1bWVudHNFeHByPXBb
+cisxXQpyPXEuZAppZihyIT09LTEpcy5leHByPXBbcisxXQpyPXEuZQppZihyIT09LTEpcy5tZXRob2Q9
+cFtyKzFdCnI9cS5mCmlmKHIhPT0tMSlzLnJlY2VpdmVyPXBbcisxXQpyZXR1cm4gc319CkguVzAucHJv
+dG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4iTm9TdWNo
+TWV0aG9kRXJyb3I6ICIrSC5Faih0aGlzLmEpCnJldHVybiJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9k
+IG5vdCBmb3VuZDogJyIrcysiJyBvbiBudWxsIn19CkguYXoucHJvdG90eXBlPXsKdzpmdW5jdGlvbihh
+KXt2YXIgcyxyPXRoaXMscT0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciLHA9
+ci5iCmlmKHA9PW51bGwpcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiAiK0guRWooci5hKQpzPXIuYwpp
+ZihzPT1udWxsKXJldHVybiBxK3ArIicgKCIrSC5FaihyLmEpKyIpIgpyZXR1cm4gcStwKyInIG9uICci
+K3MrIicgKCIrSC5FaihyLmEpKyIpIn19CkgudlYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIg
+cz10aGlzLmEKcmV0dXJuIHMubGVuZ3RoPT09MD8iRXJyb3IiOiJFcnJvcjogIitzfX0KSC50ZS5wcm90
+b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJUaHJvdyBvZiBudWxsICgnIisodGhpcy5hPT09bnVs
+bD8ibnVsbCI6InVuZGVmaW5lZCIpKyInIGZyb20gSmF2YVNjcmlwdCkifSwKJGlSejoxfQpILmJxLnBy
+b3RvdHlwZT17fQpILlhPLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLmIKaWYo
+ciE9bnVsbClyZXR1cm4gcgpyPXRoaXMuYQpzPXIhPT1udWxsJiZ0eXBlb2Ygcj09PSJvYmplY3QiP3Iu
+c3RhY2s6bnVsbApyZXR1cm4gdGhpcy5iPXM9PW51bGw/IiI6c30sCiRpR3o6MX0KSC5UcC5wcm90b3R5
+cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuY29uc3RydWN0b3Iscj1zPT1udWxsP251bGw6cy5u
+YW1lCnJldHVybiJDbG9zdXJlICciK0guTlEocj09bnVsbD8idW5rbm93biI6cikrIicifSwKJGlFSDox
+LApnS3U6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30sCiRDOiIkMSIsCiRSOjEsCiREOm51bGx9CkgubGMu
+cHJvdG90eXBlPXt9CkguengucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLiRzdGF0
+aWNfbmFtZQppZihzPT1udWxsKXJldHVybiJDbG9zdXJlIG9mIHVua25vd24gc3RhdGljIG1ldGhvZCIK
+cmV0dXJuIkNsb3N1cmUgJyIrSC5OUShzKSsiJyJ9fQpILnJULnByb3RvdHlwZT17CkROOmZ1bmN0aW9u
+KGEsYil7dmFyIHM9dGhpcwppZihiPT1udWxsKXJldHVybiExCmlmKHM9PT1iKXJldHVybiEwCmlmKCEo
+YiBpbnN0YW5jZW9mIEguclQpKXJldHVybiExCnJldHVybiBzLmE9PT1iLmEmJnMuYj09PWIuYiYmcy5j
+PT09Yi5jfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcy5jCmlmKHI9PW51bGwpcz1ILmVRKHRo
+aXMuYSkKZWxzZSBzPXR5cGVvZiByIT09Im9iamVjdCI/Si5oZihyKTpILmVRKHIpCnI9SC5lUSh0aGlz
+LmIpCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuWSgpCnJldHVybihzXnIpPj4+MH0sCnc6
+ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5jCmlmKHM9PW51bGwpcz10aGlzLmEKcmV0dXJuIkNsb3N1cmUg
+JyIrSC5Faih0aGlzLmQpKyInIG9mICIrKCJJbnN0YW5jZSBvZiAnIitILkVqKEguTShzKSkrIiciKX19
+CkguRXEucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iUnVudGltZUVycm9yOiAiK3RoaXMu
+YX19Ckgua1kucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDog
+IitQLnAodGhpcy5hKX19Ckgua3IucHJvdG90eXBlPXt9CkguTjUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHRoaXMuYX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hPT09MH0sCmd2
+YzpmdW5jdGlvbigpe3JldHVybiBuZXcgSC5pNSh0aGlzLEguTGgodGhpcykuQygiaTU8MT4iKSl9LAp4
+NDpmdW5jdGlvbihhKXt2YXIgcyxyCmlmKHR5cGVvZiBhPT0ic3RyaW5nIil7cz10aGlzLmIKaWYocz09
+bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5YdShzLGEpfWVsc2V7cj10aGlzLkNYKGEpCnJldHVybiBy
+fX0sCkNYOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuZAppZihzPT1udWxsKXJldHVybiExCnJldHVybiB0
+aGlzLkZoKHRoaXMuQnQocyxKLmhmKGEpJjB4M2ZmZmZmZiksYSk+PTB9LApxOmZ1bmN0aW9uKGEsYil7
+dmFyIHMscixxLHAsbz10aGlzLG49bnVsbAppZih0eXBlb2YgYj09InN0cmluZyIpe3M9by5iCmlmKHM9
+PW51bGwpcmV0dXJuIG4Kcj1vLmoyKHMsYikKcT1yPT1udWxsP246ci5iCnJldHVybiBxfWVsc2UgaWYo
+dHlwZW9mIGI9PSJudW1iZXIiJiYoYiYweDNmZmZmZmYpPT09Yil7cD1vLmMKaWYocD09bnVsbClyZXR1
+cm4gbgpyPW8uajIocCxiKQpxPXI9PW51bGw/bjpyLmIKcmV0dXJuIHF9ZWxzZSByZXR1cm4gby5hYShi
+KX0sCmFhOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzLmQKaWYocT09bnVsbClyZXR1cm4gbnVsbApz
+PXRoaXMuQnQocSxKLmhmKGEpJjB4M2ZmZmZmZikKcj10aGlzLkZoKHMsYSkKaWYocjwwKXJldHVybiBu
+dWxsCnJldHVybiBzW3JdLmJ9LApZNTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAsbyxuLG09dGhp
+cyxsPUguTGgobSkKbC5jLmEoYikKbC5RWzFdLmEoYykKaWYodHlwZW9mIGI9PSJzdHJpbmciKXtzPW0u
+YgptLkVIKHM9PW51bGw/bS5iPW0ueksoKTpzLGIsYyl9ZWxzZSBpZih0eXBlb2YgYj09Im51bWJlciIm
+JihiJjB4M2ZmZmZmZik9PT1iKXtyPW0uYwptLkVIKHI9PW51bGw/bS5jPW0ueksoKTpyLGIsYyl9ZWxz
+ZXtxPW0uZAppZihxPT1udWxsKXE9bS5kPW0ueksoKQpwPUouaGYoYikmMHgzZmZmZmZmCm89bS5CdChx
+LHApCmlmKG89PW51bGwpbS5FSShxLHAsW20uSG4oYixjKV0pCmVsc2V7bj1tLkZoKG8sYikKaWYobj49
+MClvW25dLmI9YwplbHNlIG8ucHVzaChtLkhuKGIsYykpfX19LApLOmZ1bmN0aW9uKGEsYil7dmFyIHMs
+cixxPXRoaXMKSC5MaChxKS5DKCJ+KDEsMikiKS5hKGIpCnM9cS5lCnI9cS5yCmZvcig7cyE9bnVsbDsp
+e2IuJDIocy5hLHMuYikKaWYociE9PXEucil0aHJvdyBILmIoUC5hNChxKSkKcz1zLmN9fSwKRUg6ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciBzLHI9dGhpcyxxPUguTGgocikKcS5jLmEoYikKcS5RWzFdLmEoYykKcz1y
+LmoyKGEsYikKaWYocz09bnVsbClyLkVJKGEsYixyLkhuKGIsYykpCmVsc2Ugcy5iPWN9LAprczpmdW5j
+dGlvbigpe3RoaXMucj10aGlzLnIrMSY2NzEwODg2M30sCkhuOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhp
+cyxyPUguTGgocykscT1uZXcgSC52aChyLmMuYShhKSxyLlFbMV0uYShiKSkKaWYocy5lPT1udWxsKXMu
+ZT1zLmY9cQplbHNle3I9cy5mCnIudG9TdHJpbmcKcS5kPXIKcy5mPXIuYz1xfSsrcy5hCnMua3MoKQpy
+ZXR1cm4gcX0sCkZoOmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZihhPT1udWxsKXJldHVybi0xCnM9YS5s
+ZW5ndGgKZm9yKHI9MDtyPHM7KytyKWlmKEouUk0oYVtyXS5hLGIpKXJldHVybiByCnJldHVybi0xfSwK
+dzpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sCmoyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGFb
+Yl19LApCdDpmdW5jdGlvbihhLGIpe3JldHVybiBhW2JdfSwKRUk6ZnVuY3Rpb24oYSxiLGMpe2FbYl09
+Y30sCnJuOmZ1bmN0aW9uKGEsYil7ZGVsZXRlIGFbYl19LApYdTpmdW5jdGlvbihhLGIpe3JldHVybiB0
+aGlzLmoyKGEsYikhPW51bGx9LAp6SzpmdW5jdGlvbigpe3ZhciBzPSI8bm9uLWlkZW50aWZpZXIta2V5
+PiIscj1PYmplY3QuY3JlYXRlKG51bGwpCnRoaXMuRUkocixzLHIpCnRoaXMucm4ocixzKQpyZXR1cm4g
+cn0sCiRpRm86MX0KSC52aC5wcm90b3R5cGU9e30KSC5pNS5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihh
+KXtyZXR1cm4gdGhpcy5hLmF9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5hPT09MH0sCmdt
+OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYSxyPW5ldyBILk42KHMscy5yLHRoaXMuJHRpLkMoIk42PDE+
+IikpCnIuYz1zLmUKcmV0dXJuIHJ9LAp0ZzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmEueDQoYil9
+fQpILk42LnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVuY3Rpb24o
+KXt2YXIgcyxyPXRoaXMscT1yLmEKaWYoci5iIT09cS5yKXRocm93IEguYihQLmE0KHEpKQpzPXIuYwpp
+ZihzPT1udWxsKXtyLnNxWShudWxsKQpyZXR1cm4hMX1lbHNle3Iuc3FZKHMuYSkKci5jPXMuYwpyZXR1
+cm4hMH19LApzcVk6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLkMoIjE/IikuYShhKX0sCiRpQW46
+MX0KSC5kQy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hKGEpfSwKJFM6NH0K
+SC53Ti5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmEoYSxiKX0sCiRTOjM0
+fQpILlZYLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEoSC5oKGEpKX0sCiRT
+OjMyfQpILlZSLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlJlZ0V4cC8iK3RoaXMuYSsi
+LyIrdGhpcy5iLmZsYWdzfSwKZ0hjOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcyxyPXMuYwppZihyIT1udWxs
+KXJldHVybiByCnI9cy5iCnJldHVybiBzLmM9SC52NChzLmEsci5tdWx0aWxpbmUsIXIuaWdub3JlQ2Fz
+ZSxyLnVuaWNvZGUsci5kb3RBbGwsITApfSwKZGQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguS1co
+dGhpcyxiLDApfSwKVVo6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyPXRoaXMuZ0hjKCkKci5sYXN0SW5kZXg9
+YgpzPXIuZXhlYyhhKQppZihzPT1udWxsKXJldHVybiBudWxsCnJldHVybiBuZXcgSC5FSyhzKX0sCiRp
+dlg6MSwKJGl3TDoxfQpILkVLLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXt2YXIgcwpILnVQKGIp
+CnM9dGhpcy5iCmlmKGI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsYikKcmV0dXJuIHNbYl19LAokaU9k
+OjEsCiRpaWI6MX0KSC5LVy5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguUGIo
+dGhpcy5hLHRoaXMuYix0aGlzLmMpfX0KSC5QYi5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3JldHVy
+biB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG09dGhpcyxsPW0uYgppZihsPT1u
+dWxsKXJldHVybiExCnM9bS5jCnI9bC5sZW5ndGgKaWYoczw9cil7cT1tLmEKcD1xLlVaKGwscykKaWYo
+cCE9bnVsbCl7bS5kPXAKcz1wLmIKbz1zLmluZGV4Cm49bytzWzBdLmxlbmd0aAppZihvPT09bil7aWYo
+cS5iLnVuaWNvZGUpe3M9bS5jCnE9cysxCmlmKHE8cil7cz1DLnhCLk8obCxzKQppZihzPj01NTI5NiYm
+czw9NTYzMTkpe3M9Qy54Qi5PKGwscSkKcz1zPj01NjMyMCYmczw9NTczNDN9ZWxzZSBzPSExfWVsc2Ug
+cz0hMX1lbHNlIHM9ITEKbj0ocz9uKzE6bikrMX1tLmM9bgpyZXR1cm4hMH19bS5iPW0uZD1udWxsCnJl
+dHVybiExfSwKJGlBbjoxfQpILnRRLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCmlm
+KGIhPT0wKUgudihQLk83KGIsbnVsbCkpCnJldHVybiB0aGlzLmN9LAokaU9kOjF9CkgudW4ucHJvdG90
+eXBlPXsKZ206ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlNkKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19
+CkguU2QucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciBzLHIscT10aGlzLHA9cS5jLG89cS5iLG49
+by5sZW5ndGgsbT1xLmEsbD1tLmxlbmd0aAppZihwK24+bCl7cS5kPW51bGwKcmV0dXJuITF9cz1tLmlu
+ZGV4T2YobyxwKQppZihzPDApe3EuYz1sKzEKcS5kPW51bGwKcmV0dXJuITF9cj1zK24KcS5kPW5ldyBI
+LnRRKHMsbykKcS5jPXI9PT1xLmM/cisxOnIKcmV0dXJuITB9LApnbDpmdW5jdGlvbigpe3ZhciBzPXRo
+aXMuZApzLnRvU3RyaW5nCnJldHVybiBzfSwKJGlBbjoxfQpILkVULnByb3RvdHlwZT17JGlFVDoxLCRp
+QVM6MX0KSC5MWi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LAokaVhq
+OjF9CkguRGcucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5n
+dGgpCnJldHVybiBhW2JdfSwKWTU6ZnVuY3Rpb24oYSxiLGMpe0guR0goYykKSC5vZChiLGEsYS5sZW5n
+dGgpCmFbYl09Y30sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9CkguUGcucHJvdG90eXBlPXsKWTU6ZnVu
+Y3Rpb24oYSxiLGMpe0gudVAoYykKSC5vZChiLGEsYS5sZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGlj
+WDoxLAokaXpNOjF9CkgueGoucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChi
+LGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5kRS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7
+SC51UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILlpBLnByb3RvdHlwZT17CnE6
+ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguZFQu
+cHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVy
+biBhW2JdfX0KSC5QcS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpILm9kKGIsYSxh
+Lmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmVFLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVy
+biBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1
+cm4gYVtiXX19CkguVjYucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwK
+cTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfSwKJGlW
+NjoxLAokaW42OjF9CkguUkcucHJvdG90eXBlPXt9CkguVlAucHJvdG90eXBlPXt9CkguV0IucHJvdG90
+eXBlPXt9CkguWkcucHJvdG90eXBlPXt9CkguSmMucHJvdG90eXBlPXsKQzpmdW5jdGlvbihhKXtyZXR1
+cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfSwKS3E6ZnVuY3Rpb24oYSl7cmV0dXJuIEgudjUo
+di50eXBlVW5pdmVyc2UsdGhpcyxhKX19CkguRy5wcm90b3R5cGU9e30KSC5sWS5wcm90b3R5cGU9ewp3
+OmZ1bmN0aW9uKGEpe3JldHVybiBILmRtKHRoaXMuYSxudWxsKX19Ckgua1MucHJvdG90eXBlPXsKdzpm
+dW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfX0KSC5pTS5wcm90b3R5cGU9e30KUC50aC5wcm90b3R5cGU9
+ewokMTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEscj1zLmEKcy5hPW51bGwKci4kMCgpfSwKJFM6MTB9
+ClAuaGEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscgp0aGlzLmEuYT10Lk0uYShhKQpz
+PXRoaXMuYgpyPXRoaXMuYwpzLmZpcnN0Q2hpbGQ/cy5yZW1vdmVDaGlsZChyKTpzLmFwcGVuZENoaWxk
+KHIpfSwKJFM6NTJ9ClAuVnMucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuJDAoKX0sCiRD
+OiIkMCIsCiRSOjAsCiRTOjJ9ClAuRnQucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuJDAo
+KX0sCiRDOiIkMCIsCiRSOjAsCiRTOjJ9ClAuVzMucHJvdG90eXBlPXsKQ1k6ZnVuY3Rpb24oYSxiKXtp
+ZihzZWxmLnNldFRpbWVvdXQhPW51bGwpc2VsZi5zZXRUaW1lb3V0KEgudFIobmV3IFAueUgodGhpcyxi
+KSwwKSxhKQplbHNlIHRocm93IEguYihQLkw0KCJgc2V0VGltZW91dCgpYCBub3QgZm91bmQuIikpfX0K
+UC55SC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYi4kMCgpfSwKJEM6IiQwIiwKJFI6MCwK
+JFM6MH0KUC5paC5wcm90b3R5cGU9ewphTTpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcyxxPXIuJHRp
+CnEuQygiMS8/IikuYShiKQppZighci5iKXIuYS5YZihiKQplbHNle3M9ci5hCmlmKHEuQygiYjg8MT4i
+KS5iKGIpKXMuY1UoYikKZWxzZSBzLlgyKHEuYy5hKGIpKX19LAp3MDpmdW5jdGlvbihhLGIpe3ZhciBz
+CmlmKGI9PW51bGwpYj1QLnYwKGEpCnM9dGhpcy5hCmlmKHRoaXMuYilzLlpMKGEsYikKZWxzZSBzLk5r
+KGEsYil9fQpQLldNLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuJDIoMCxh
+KX0sCiRTOjQzfQpQLlNYLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLiQyKDEsbmV3
+IEguYnEoYSx0LmwuYShiKSkpfSwKJEM6IiQyIiwKJFI6MiwKJFM6NTR9ClAuR3MucHJvdG90eXBlPXsK
+JDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEoSC51UChhKSxiKX0sCiRTOjI0fQpQLkZ5LnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIkl0ZXJhdGlvbk1hcmtlcigiK3RoaXMuYisiLCAiK0guRWoodGhp
+cy5hKSsiKSJ9fQpQLkdWLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy5jCmlmKHM9
+PW51bGwpcmV0dXJuIHRoaXMuJHRpLmMuYSh0aGlzLmIpCnJldHVybiBzLmdsKCl9LApGOmZ1bmN0aW9u
+KCl7dmFyIHMscixxLHAsbyxuLG09dGhpcwpmb3Iocz1tLiR0aS5DKCJBbjwxPiIpOyEwOyl7cj1tLmMK
+aWYociE9bnVsbClpZihyLkYoKSlyZXR1cm4hMAplbHNlIG0uc1g5KG51bGwpCnE9ZnVuY3Rpb24oYSxi
+LGMpe3ZhciBsLGs9Ygp3aGlsZSh0cnVlKXRyeXtyZXR1cm4gYShrLGwpfWNhdGNoKGope2w9agprPWN9
+fShtLmEsMCwxKQppZihxIGluc3RhbmNlb2YgUC5GeSl7cD1xLmIKaWYocD09PTIpe289bS5kCmlmKG89
+PW51bGx8fG8ubGVuZ3RoPT09MCl7bS5zRUMobnVsbCkKcmV0dXJuITF9aWYoMD49by5sZW5ndGgpcmV0
+dXJuIEguT0gobywtMSkKbS5hPW8ucG9wKCkKY29udGludWV9ZWxzZXtyPXEuYQppZihwPT09Myl0aHJv
+dyByCmVsc2V7bj1zLmEoSi5JVChyKSkKaWYobiBpbnN0YW5jZW9mIFAuR1Ype3I9bS5kCmlmKHI9PW51
+bGwpcj1tLmQ9W10KQy5ObS5pKHIsbS5hKQptLmE9bi5hCmNvbnRpbnVlfWVsc2V7bS5zWDkobikKY29u
+dGludWV9fX19ZWxzZXttLnNFQyhxKQpyZXR1cm4hMH19cmV0dXJuITF9LApzRUM6ZnVuY3Rpb24oYSl7
+dGhpcy5iPXRoaXMuJHRpLkMoIjE/IikuYShhKX0sCnNYOTpmdW5jdGlvbihhKXt0aGlzLmM9dGhpcy4k
+dGkuQygiQW48MT4/IikuYShhKX0sCiRpQW46MX0KUC5xNC5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihh
+KXtyZXR1cm4gbmV3IFAuR1YodGhpcy5hKCksdGhpcy4kdGkuQygiR1Y8MT4iKSl9fQpQLkN3LnByb3Rv
+dHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIEguRWoodGhpcy5hKX0sCiRpWFM6MSwKZ0lJOmZ1bmN0
+aW9uKCl7cmV0dXJuIHRoaXMuYn19ClAuUGYucHJvdG90eXBlPXsKdzA6ZnVuY3Rpb24oYSxiKXt2YXIg
+cwpILmNiKGEsImVycm9yIix0LkspCnM9dGhpcy5hCmlmKHMuYSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1
+dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQppZihiPT1udWxsKWI9UC52MChhKQpzLk5rKGEsYil9LApw
+bTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy53MChhLG51bGwpfX0KUC5aZi5wcm90b3R5cGU9ewphTTpm
+dW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcy4kdGkKci5DKCIxLz8iKS5hKGIpCnM9dGhpcy5hCmlmKHMu
+YSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQpzLlhmKHIuQygi
+MS8iKS5hKGIpKX19ClAuRmUucHJvdG90eXBlPXsKSFI6ZnVuY3Rpb24oYSl7aWYoKHRoaXMuYyYxNSkh
+PT02KXJldHVybiEwCnJldHVybiB0aGlzLmIuYi5idih0LmFsLmEodGhpcy5kKSxhLmEsdC55LHQuSyl9
+LApLdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmUscj10LnoscT10LksscD10aGlzLiR0aS5DKCIyLyIp
+LG89dGhpcy5iLmIKaWYodC5hZy5iKHMpKXJldHVybiBwLmEoby5ycChzLGEuYSxhLmIscixxLHQubCkp
+CmVsc2UgcmV0dXJuIHAuYShvLmJ2KHQuYkkuYShzKSxhLmEscixxKSl9fQpQLnZzLnByb3RvdHlwZT17
+ClNxOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscD10aGlzLiR0aQpwLktxKGMpLkMoIjEvKDIpIiku
+YShhKQpzPSQuWDMKaWYocyE9PUMuTlUpe2MuQygiQDwwLz4iKS5LcShwLmMpLkMoIjEoMikiKS5hKGEp
+CmlmKGIhPW51bGwpYj1QLlZIKGIscyl9cj1uZXcgUC52cyhzLGMuQygidnM8MD4iKSkKcT1iPT1udWxs
+PzE6Mwp0aGlzLnhmKG5ldyBQLkZlKHIscSxhLGIscC5DKCJAPDE+IikuS3EoYykuQygiRmU8MSwyPiIp
+KSkKcmV0dXJuIHJ9LApXNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNxKGEsbnVsbCxiKX0sClFk
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPXRoaXMuJHRpCnIuS3EoYykuQygiMS8oMikiKS5hKGEpCnM9
+bmV3IFAudnMoJC5YMyxjLkMoInZzPDA+IikpCnRoaXMueGYobmV3IFAuRmUocywxOSxhLGIsci5DKCJA
+PDE+IikuS3EoYykuQygiRmU8MSwyPiIpKSkKcmV0dXJuIHN9LAp4ZjpmdW5jdGlvbihhKXt2YXIgcyxy
+PXRoaXMscT1yLmEKaWYocTw9MSl7YS5hPXQuRi5hKHIuYykKci5jPWF9ZWxzZXtpZihxPT09Mil7cz10
+LmMuYShyLmMpCnE9cy5hCmlmKHE8NCl7cy54ZihhKQpyZXR1cm59ci5hPXEKci5jPXMuY31QLlRrKG51
+bGwsbnVsbCxyLmIsdC5NLmEobmV3IFAuZGEocixhKSkpfX0sCmpROmZ1bmN0aW9uKGEpe3ZhciBzLHIs
+cSxwLG8sbixtPXRoaXMsbD17fQpsLmE9YQppZihhPT1udWxsKXJldHVybgpzPW0uYQppZihzPD0xKXty
+PXQuRi5hKG0uYykKbS5jPWEKaWYociE9bnVsbCl7cT1hLmEKZm9yKHA9YTtxIT1udWxsO3A9cSxxPW8p
+bz1xLmEKcC5hPXJ9fWVsc2V7aWYocz09PTIpe249dC5jLmEobS5jKQpzPW4uYQppZihzPDQpe24ualEo
+YSkKcmV0dXJufW0uYT1zCm0uYz1uLmN9bC5hPW0uTjgoYSkKUC5UayhudWxsLG51bGwsbS5iLHQuTS5h
+KG5ldyBQLm9RKGwsbSkpKX19LAphaDpmdW5jdGlvbigpe3ZhciBzPXQuRi5hKHRoaXMuYykKdGhpcy5j
+PW51bGwKcmV0dXJuIHRoaXMuTjgocyl9LApOODpmdW5jdGlvbihhKXt2YXIgcyxyLHEKZm9yKHM9YSxy
+PW51bGw7cyE9bnVsbDtyPXMscz1xKXtxPXMuYQpzLmE9cn1yZXR1cm4gcn0sCmVjOmZ1bmN0aW9uKGEp
+e3ZhciBzLHIscSxwPXRoaXMKcC5hPTEKdHJ5e2EuU3EobmV3IFAucFYocCksbmV3IFAuVTcocCksdC5Q
+KX1jYXRjaChxKXtzPUguUnUocSkKcj1ILnRzKHEpClAucmIobmV3IFAudnIocCxzLHIpKX19LApYMjpm
+dW5jdGlvbihhKXt2YXIgcyxyPXRoaXMKci4kdGkuYy5hKGEpCnM9ci5haCgpCnIuYT00CnIuYz1hClAu
+SFoocixzKX0sClpMOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPXRoaXMKdC5sLmEoYikKcz1xLmFoKCkK
+cj1QLlRsKGEsYikKcS5hPTgKcS5jPXIKUC5IWihxLHMpfSwKWGY6ZnVuY3Rpb24oYSl7dmFyIHM9dGhp
+cy4kdGkKcy5DKCIxLyIpLmEoYSkKaWYocy5DKCJiODwxPiIpLmIoYSkpe3RoaXMuY1UoYSkKcmV0dXJu
+fXRoaXMud1Uocy5jLmEoYSkpfSwKd1U6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcwpzLiR0aS5jLmEoYSkK
+cy5hPTEKUC5UayhudWxsLG51bGwscy5iLHQuTS5hKG5ldyBQLnJ0KHMsYSkpKX0sCmNVOmZ1bmN0aW9u
+KGEpe3ZhciBzPXRoaXMscj1zLiR0aQpyLkMoImI4PDE+IikuYShhKQppZihyLmIoYSkpe2lmKGEuYT09
+PTgpe3MuYT0xClAuVGsobnVsbCxudWxsLHMuYix0Lk0uYShuZXcgUC5LRihzLGEpKSl9ZWxzZSBQLkE5
+KGEscykKcmV0dXJufXMuZWMoYSl9LApOazpmdW5jdGlvbihhLGIpe3RoaXMuYT0xClAuVGsobnVsbCxu
+dWxsLHRoaXMuYix0Lk0uYShuZXcgUC5aTCh0aGlzLGEsYikpKX0sCiRpYjg6MX0KUC5kYS5wcm90b3R5
+cGU9ewokMDpmdW5jdGlvbigpe1AuSFoodGhpcy5hLHRoaXMuYil9LAokUzowfQpQLm9RLnByb3RvdHlw
+ZT17CiQwOmZ1bmN0aW9uKCl7UC5IWih0aGlzLmIsdGhpcy5hLmEpfSwKJFM6MH0KUC5wVi5wcm90b3R5
+cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD10aGlzLmEKcC5hPTAKdHJ5e3AuWDIocC4kdGku
+Yy5hKGEpKX1jYXRjaChxKXtzPUguUnUocSkKcj1ILnRzKHEpCnAuWkwocyxyKX19LAokUzoxMH0KUC5V
+Ny5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS5aTChhLHQubC5hKGIpKX0sCiRDOiIk
+MiIsCiRSOjIsCiRTOjI4fQpQLnZyLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLlpMKHRo
+aXMuYix0aGlzLmMpfSwKJFM6MH0KUC5ydC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5Y
+Mih0aGlzLmIpfSwKJFM6MH0KUC5LRi5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe1AuQTkodGhpcy5i
+LHRoaXMuYSl9LAokUzowfQpQLlpMLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLlpMKHRo
+aXMuYix0aGlzLmMpfSwKJFM6MH0KUC5SVC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciBzLHIs
+cSxwLG8sbixtPXRoaXMsbD1udWxsCnRyeXtxPW0uYS5hCmw9cS5iLmIuenoodC5mTy5hKHEuZCksdC56
+KX1jYXRjaChwKXtzPUguUnUocCkKcj1ILnRzKHApCmlmKG0uYyl7cT10Lm4uYShtLmIuYS5jKS5hCm89
+cwpvPXE9PW51bGw/bz09bnVsbDpxPT09bwpxPW99ZWxzZSBxPSExCm89bS5hCmlmKHEpby5jPXQubi5h
+KG0uYi5hLmMpCmVsc2Ugby5jPVAuVGwocyxyKQpvLmI9ITAKcmV0dXJufWlmKGwgaW5zdGFuY2VvZiBQ
+LnZzJiZsLmE+PTQpe2lmKGwuYT09PTgpe3E9bS5hCnEuYz10Lm4uYShsLmMpCnEuYj0hMH1yZXR1cm59
+aWYodC5lLmIobCkpe249bS5iLmEKcT1tLmEKcS5jPWwuVzcobmV3IFAualoobiksdC56KQpxLmI9ITF9
+fSwKJFM6MH0KUC5qWi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKJFM6
+Mjl9ClAucnEucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbSxsCnRyeXtx
+PXRoaXMuYQpwPXEuYQpvPXAuJHRpCm49by5jCm09bi5hKHRoaXMuYikKcS5jPXAuYi5iLmJ2KG8uQygi
+Mi8oMSkiKS5hKHAuZCksbSxvLkMoIjIvIiksbil9Y2F0Y2gobCl7cz1ILlJ1KGwpCnI9SC50cyhsKQpx
+PXRoaXMuYQpxLmM9UC5UbChzLHIpCnEuYj0hMH19LAokUzowfQpQLlJXLnByb3RvdHlwZT17CiQwOmZ1
+bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG0sbCxrPXRoaXMKdHJ5e3M9dC5uLmEoay5hLmEuYykKcD1r
+LmIKaWYoSC5vVChwLmEuSFIocykpJiZwLmEuZSE9bnVsbCl7cC5jPXAuYS5LdyhzKQpwLmI9ITF9fWNh
+dGNoKG8pe3I9SC5SdShvKQpxPUgudHMobykKcD10Lm4uYShrLmEuYS5jKQpuPXAuYQptPXIKbD1rLmIK
+aWYobj09bnVsbD9tPT1udWxsOm49PT1tKWwuYz1wCmVsc2UgbC5jPVAuVGwocixxKQpsLmI9ITB9fSwK
+JFM6MH0KUC5PTS5wcm90b3R5cGU9e30KUC5xaC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXt2YXIg
+cyxyLHE9dGhpcyxwPXt9LG89bmV3IFAudnMoJC5YMyx0LmZKKQpwLmE9MApzPUguTGgocSkKcj1zLkMo
+In4oMSk/IikuYShuZXcgUC5CNShwLHEpKQp0LlouYShuZXcgUC51TyhwLG8pKQpXLkpFKHEuYSxxLmIs
+ciwhMSxzLmMpCnJldHVybiBvfX0KUC5CNS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtILkxoKHRo
+aXMuYikuYy5hKGEpOysrdGhpcy5hLmF9LAokUzpmdW5jdGlvbigpe3JldHVybiBILkxoKHRoaXMuYiku
+QygifigxKSIpfX0KUC51Ty5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciBzPXRoaXMuYixyPXMu
+JHRpLHE9ci5DKCIxLyIpLmEodGhpcy5hLmEpLHA9cy5haCgpCnIuYy5hKHEpCnMuYT00CnMuYz1xClAu
+SFoocyxwKX0sCiRTOjB9ClAuTU8ucHJvdG90eXBlPXt9ClAua1QucHJvdG90eXBlPXt9ClAueEkucHJv
+dG90eXBlPXt9ClAubTAucHJvdG90eXBlPXskaVFtOjF9ClAucEsucHJvdG90eXBlPXsKJDA6ZnVuY3Rp
+b24oKXt2YXIgcz1ILmIodGhpcy5hKQpzLnN0YWNrPUouaih0aGlzLmIpCnRocm93IHN9LAokUzowfQpQ
+LkppLnByb3RvdHlwZT17CmJIOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPW51bGwKdC5NLmEoYSkKdHJ5
+e2lmKEMuTlU9PT0kLlgzKXthLiQwKCkKcmV0dXJufVAuVDgocCxwLHRoaXMsYSx0LkgpfWNhdGNoKHEp
+e3M9SC5SdShxKQpyPUgudHMocSkKUC5MMihwLHAsdGhpcyxzLHQubC5hKHIpKX19LApEbDpmdW5jdGlv
+bihhLGIsYyl7dmFyIHMscixxLHA9bnVsbApjLkMoIn4oMCkiKS5hKGEpCmMuYShiKQp0cnl7aWYoQy5O
+VT09PSQuWDMpe2EuJDEoYikKcmV0dXJufVAueXYocCxwLHRoaXMsYSxiLHQuSCxjKX1jYXRjaChxKXtz
+PUguUnUocSkKcj1ILnRzKHEpClAuTDIocCxwLHRoaXMscyx0LmwuYShyKSl9fSwKUlQ6ZnVuY3Rpb24o
+YSxiKXtyZXR1cm4gbmV3IFAuaGoodGhpcyxiLkMoIjAoKSIpLmEoYSksYil9LApHWTpmdW5jdGlvbihh
+KXtyZXR1cm4gbmV3IFAuVnAodGhpcyx0Lk0uYShhKSl9LApQeTpmdW5jdGlvbihhLGIpe3JldHVybiBu
+ZXcgUC5PUih0aGlzLGIuQygifigwKSIpLmEoYSksYil9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG51
+bGx9LAp6ejpmdW5jdGlvbihhLGIpe2IuQygiMCgpIikuYShhKQppZigkLlgzPT09Qy5OVSlyZXR1cm4g
+YS4kMCgpCnJldHVybiBQLlQ4KG51bGwsbnVsbCx0aGlzLGEsYil9LApidjpmdW5jdGlvbihhLGIsYyxk
+KXtjLkMoIkA8MD4iKS5LcShkKS5DKCIxKDIpIikuYShhKQpkLmEoYikKaWYoJC5YMz09PUMuTlUpcmV0
+dXJuIGEuJDEoYikKcmV0dXJuIFAueXYobnVsbCxudWxsLHRoaXMsYSxiLGMsZCl9LApycDpmdW5jdGlv
+bihhLGIsYyxkLGUsZil7ZC5DKCJAPDA+IikuS3EoZSkuS3EoZikuQygiMSgyLDMpIikuYShhKQplLmEo
+YikKZi5hKGMpCmlmKCQuWDM9PT1DLk5VKXJldHVybiBhLiQyKGIsYykKcmV0dXJuIFAuUXgobnVsbCxu
+dWxsLHRoaXMsYSxiLGMsZCxlLGYpfSwKTGo6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGIuQygiQDww
+PiIpLktxKGMpLktxKGQpLkMoIjEoMiwzKSIpLmEoYSl9fQpQLmhqLnByb3RvdHlwZT17CiQwOmZ1bmN0
+aW9uKCl7cmV0dXJuIHRoaXMuYS56eih0aGlzLmIsdGhpcy5jKX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJu
+IHRoaXMuYy5DKCIwKCkiKX19ClAuVnAucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
+cy5hLmJIKHRoaXMuYil9LAokUzowfQpQLk9SLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBz
+PXRoaXMuYwpyZXR1cm4gdGhpcy5hLkRsKHRoaXMuYixzLmEoYSkscyl9LAokUzpmdW5jdGlvbigpe3Jl
+dHVybiB0aGlzLmMuQygifigwKSIpfX0KUC5iNi5wcm90b3R5cGU9ewpnbTpmdW5jdGlvbihhKXt2YXIg
+cz10aGlzLHI9bmV3IFAubG0ocyxzLnIsSC5MaChzKS5DKCJsbTwxPiIpKQpyLmM9cy5lCnJldHVybiBy
+fSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
+cy5hPT09MH0sCmdvcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hIT09MH0sCnRnOmZ1bmN0aW9uKGEs
+Yil7dmFyIHMscgppZih0eXBlb2YgYj09InN0cmluZyImJmIhPT0iX19wcm90b19fIil7cz10aGlzLmIK
+aWYocz09bnVsbClyZXR1cm4hMQpyZXR1cm4gdC5tLmEoc1tiXSkhPW51bGx9ZWxzZXtyPXRoaXMuUFIo
+YikKcmV0dXJuIHJ9fSwKUFI6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5kCmlmKHM9PW51bGwpcmV0dXJu
+ITEKcmV0dXJuIHRoaXMuREYoc1t0aGlzLk4oYSldLGEpPj0wfSwKaTpmdW5jdGlvbihhLGIpe3ZhciBz
+LHIscT10aGlzCkguTGgocSkuYy5hKGIpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3Rv
+X18iKXtzPXEuYgpyZXR1cm4gcS5iUShzPT1udWxsP3EuYj1QLlQyKCk6cyxiKX1lbHNlIGlmKHR5cGVv
+ZiBiPT0ibnVtYmVyIiYmKGImMTA3Mzc0MTgyMyk9PT1iKXtyPXEuYwpyZXR1cm4gcS5iUShyPT1udWxs
+P3EuYz1QLlQyKCk6cixiKX1lbHNlIHJldHVybiBxLkI3KGIpfSwKQjc6ZnVuY3Rpb24oYSl7dmFyIHMs
+cixxLHA9dGhpcwpILkxoKHApLmMuYShhKQpzPXAuZAppZihzPT1udWxsKXM9cC5kPVAuVDIoKQpyPXAu
+TihhKQpxPXNbcl0KaWYocT09bnVsbClzW3JdPVtwLnlvKGEpXQplbHNle2lmKHAuREYocSxhKT49MCly
+ZXR1cm4hMQpxLnB1c2gocC55byhhKSl9cmV0dXJuITB9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhp
+cwppZih0eXBlb2YgYj09InN0cmluZyImJmIhPT0iX19wcm90b19fIilyZXR1cm4gcy5IKHMuYixiKQpl
+bHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMTA3Mzc0MTgyMyk9PT1iKXJldHVybiBzLkgocy5j
+LGIpCmVsc2UgcmV0dXJuIHMucWcoYil9LApxZzpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvPXRoaXMs
+bj1vLmQKaWYobj09bnVsbClyZXR1cm4hMQpzPW8uTihhKQpyPW5bc10KcT1vLkRGKHIsYSkKaWYocTww
+KXJldHVybiExCnA9ci5zcGxpY2UocSwxKVswXQppZigwPT09ci5sZW5ndGgpZGVsZXRlIG5bc10Kby5H
+KHApCnJldHVybiEwfSwKYlE6ZnVuY3Rpb24oYSxiKXtILkxoKHRoaXMpLmMuYShiKQppZih0Lm0uYShh
+W2JdKSE9bnVsbClyZXR1cm4hMQphW2JdPXRoaXMueW8oYikKcmV0dXJuITB9LApIOmZ1bmN0aW9uKGEs
+Yil7dmFyIHMKaWYoYT09bnVsbClyZXR1cm4hMQpzPXQubS5hKGFbYl0pCmlmKHM9PW51bGwpcmV0dXJu
+ITEKdGhpcy5HKHMpCmRlbGV0ZSBhW2JdCnJldHVybiEwfSwKUzpmdW5jdGlvbigpe3RoaXMucj10aGlz
+LnIrMSYxMDczNzQxODIzfSwKeW86ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLHE9bmV3IFAuYm4oSC5M
+aChyKS5jLmEoYSkpCmlmKHIuZT09bnVsbClyLmU9ci5mPXEKZWxzZXtzPXIuZgpzLnRvU3RyaW5nCnEu
+Yz1zCnIuZj1zLmI9cX0rK3IuYQpyLlMoKQpyZXR1cm4gcX0sCkc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhp
+cyxyPWEuYyxxPWEuYgppZihyPT1udWxsKXMuZT1xCmVsc2Ugci5iPXEKaWYocT09bnVsbClzLmY9cgpl
+bHNlIHEuYz1yOy0tcy5hCnMuUygpfSwKTjpmdW5jdGlvbihhKXtyZXR1cm4gSi5oZihhKSYxMDczNzQx
+ODIzfSwKREY6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlmKGE9PW51bGwpcmV0dXJuLTEKcz1hLmxlbmd0
+aApmb3Iocj0wO3I8czsrK3IpaWYoSi5STShhW3JdLmEsYikpcmV0dXJuIHIKcmV0dXJuLTF9fQpQLmJu
+LnByb3RvdHlwZT17fQpQLmxtLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0s
+CkY6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLHI9cy5jLHE9cy5hCmlmKHMuYiE9PXEucil0aHJvdyBILmIo
+UC5hNChxKSkKZWxzZSBpZihyPT1udWxsKXtzLnNqKG51bGwpCnJldHVybiExfWVsc2V7cy5zaihzLiR0
+aS5DKCIxPyIpLmEoci5hKSkKcy5jPXIuYgpyZXR1cm4hMH19LApzajpmdW5jdGlvbihhKXt0aGlzLmQ9
+dGhpcy4kdGkuQygiMT8iKS5hKGEpfSwKJGlBbjoxfQpQLm1XLnByb3RvdHlwZT17fQpQLnV5LnByb3Rv
+dHlwZT17JGliUToxLCRpY1g6MSwkaXpNOjF9ClAubEQucHJvdG90eXBlPXsKZ206ZnVuY3Rpb24oYSl7
+cmV0dXJuIG5ldyBILmE3KGEsdGhpcy5nQShhKSxILnooYSkuQygiYTc8bEQuRT4iKSl9LApFOmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIHRoaXMucShhLGIpfSwKSzpmdW5jdGlvbihhLGIpe3ZhciBzLHIKSC56KGEp
+LkMoIn4obEQuRSkiKS5hKGIpCnM9dGhpcy5nQShhKQpmb3Iocj0wO3I8czsrK3Ipe2IuJDEodGhpcy5x
+KGEscikpCmlmKHMhPT10aGlzLmdBKGEpKXRocm93IEguYihQLmE0KGEpKX19LApnbDA6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuZ0EoYSk9PT0wfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiF0aGlzLmdsMChh
+KX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1ILnooYSkKcmV0dXJuIG5ldyBILmxKKGEscy5LcShj
+KS5DKCIxKGxELkUpIikuYShiKSxzLkMoIkA8bEQuRT4iKS5LcShjKS5DKCJsSjwxLDI+IikpfSwKZVI6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5xQyhhLGIsbnVsbCxILnooYSkuQygibEQuRSIpKX0sCmRyOmZ1
+bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILmpWKGEsSC56KGEpLkMoIkA8bEQuRT4iKS5LcShiKS5DKCJq
+VjwxLDI+IikpfSwKZHU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMKSC56KGEpLkMoImxELkU/IikuYShk
+KQpQLmpCKGIsYyx0aGlzLmdBKGEpKQpmb3Iocz1iO3M8YzsrK3MpdGhpcy5ZNShhLHMsZCl9LAp3OmZ1
+bmN0aW9uKGEpe3JldHVybiBQLldFKGEsIlsiLCJdIil9fQpQLmlsLnByb3RvdHlwZT17fQpQLnJhLnBy
+b3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHMscj10aGlzLmEKaWYoIXIuYSl0aGlzLmIuYSs9
+IiwgIgpyLmE9ITEKcj10aGlzLmIKcz1yLmErPUguRWooYSkKci5hPXMrIjogIgpyLmErPUguRWooYil9
+LAokUzoxMX0KUC5Zay5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpILkxoKHRoaXMp
+LkMoIn4oWWsuSyxZay5WKSIpLmEoYikKZm9yKHM9Si5JVCh0aGlzLmd2YygpKTtzLkYoKTspe3I9cy5n
+bCgpCmIuJDIocix0aGlzLnEoMCxyKSl9fSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVybiBKLk0xKHRoaXMu
+Z3ZjKCksbmV3IFAueVEodGhpcyksSC5MaCh0aGlzKS5DKCJOMzxZay5LLFlrLlY+IikpfSwKeDQ6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIEouemwodGhpcy5ndmMoKSxhKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBK
+LkhtKHRoaXMuZ3ZjKCkpfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiBKLnVVKHRoaXMuZ3ZjKCkpfSwK
+dzpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sCiRpWjA6MX0KUC55US5wcm90b3R5cGU9ewok
+MTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEscj1ILkxoKHMpCnIuQygiWWsuSyIpLmEoYSkKcmV0dXJu
+IG5ldyBQLk4zKGEscy5xKDAsYSksci5DKCJAPFlrLks+IikuS3Eoci5DKCJZay5WIikpLkMoIk4zPDEs
+Mj4iKSl9LAokUzpmdW5jdGlvbigpe3JldHVybiBILkxoKHRoaXMuYSkuQygiTjM8WWsuSyxZay5WPihZ
+ay5LKSIpfX0KUC5LUC5wcm90b3R5cGU9ewpZNTpmdW5jdGlvbihhLGIsYyl7dmFyIHM9SC5MaCh0aGlz
+KQpzLmMuYShiKQpzLlFbMV0uYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlm
+aWFibGUgbWFwIikpfX0KUC5Qbi5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMu
+YS5xKDAsYil9LApZNTpmdW5jdGlvbihhLGIsYyl7dmFyIHM9SC5MaCh0aGlzKQp0aGlzLmEuWTUoMCxz
+LmMuYShiKSxzLlFbMV0uYShjKSl9LAp4NDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLng0KGEpfSwK
+SzpmdW5jdGlvbihhLGIpe3RoaXMuYS5LKDAsSC5MaCh0aGlzKS5DKCJ+KDEsMikiKS5hKGIpKX0sCmds
+MDpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMuZ2wwKHMpfSwKZ0E6ZnVuY3Rpb24oYSl7
+dmFyIHM9dGhpcy5hCnJldHVybiBzLmdBKHMpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gSi5qKHRoaXMu
+YSl9LApnUHU6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVybiBzLmdQdShzKX0sCiRpWjA6MX0K
+UC5Hai5wcm90b3R5cGU9e30KUC5sZi5wcm90b3R5cGU9ewpnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
+aXMuZ0EodGhpcyk9PT0wfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdBKHRoaXMpIT09MH0s
+CkZWOmZ1bmN0aW9uKGEsYil7dmFyIHMKZm9yKHM9Si5JVChILkxoKHRoaXMpLkMoImNYPGxmLkU+Iiku
+YShiKSk7cy5GKCk7KXRoaXMuaSgwLHMuZ2woKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKHRo
+aXMsInsiLCJ9Iil9LAprOmZ1bmN0aW9uKGEsYil7dmFyIHMscj10aGlzLmdtKHRoaXMpCmlmKCFyLkYo
+KSlyZXR1cm4iIgppZihiPT09IiIpe3M9IiIKZG8gcys9SC5FaihyLmQpCndoaWxlKHIuRigpKX1lbHNl
+e3M9SC5FaihyLmQpCmZvcig7ci5GKCk7KXM9cytiK0guRWooci5kKX1yZXR1cm4gcy5jaGFyQ29kZUF0
+KDApPT0wP3M6c30sCmVSOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguYksodGhpcyxiLEguTGgodGhpcyku
+QygibGYuRSIpKX0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscD0iaW5kZXgiCkguY2IoYixwLHQu
+UykKUC5rMShiLHApCmZvcihzPXRoaXMuZ20odGhpcykscj0wO3MuRigpOyl7cT1zLmQKaWYoYj09PXIp
+cmV0dXJuIHE7KytyfXRocm93IEguYihQLkNmKGIsdGhpcyxwLG51bGwscikpfX0KUC5Wai5wcm90b3R5
+cGU9eyRpYlE6MSwkaWNYOjEsJGl4dToxfQpQLlh2LnByb3RvdHlwZT17JGliUToxLCRpY1g6MSwkaXh1
+OjF9ClAublkucHJvdG90eXBlPXt9ClAuV1kucHJvdG90eXBlPXt9ClAuUlUucHJvdG90eXBlPXt9ClAu
+cFIucHJvdG90eXBlPXt9ClAudXcucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhp
+cy5iCmlmKHI9PW51bGwpcmV0dXJuIHRoaXMuYy5xKDAsYikKZWxzZSBpZih0eXBlb2YgYiE9InN0cmlu
+ZyIpcmV0dXJuIG51bGwKZWxzZXtzPXJbYl0KcmV0dXJuIHR5cGVvZiBzPT0idW5kZWZpbmVkIj90aGlz
+LmZiKGIpOnN9fSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYj09bnVsbD90aGlzLmMuYTp0aGlz
+LkNmKCkubGVuZ3RofSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdBKHRoaXMpPT09MH0sCmd2
+YzpmdW5jdGlvbigpe2lmKHRoaXMuYj09bnVsbCl7dmFyIHM9dGhpcy5jCnJldHVybiBuZXcgSC5pNShz
+LEguTGgocykuQygiaTU8MT4iKSl9cmV0dXJuIG5ldyBQLmk4KHRoaXMpfSwKWTU6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciBzLHIscT10aGlzCmlmKHEuYj09bnVsbClxLmMuWTUoMCxiLGMpCmVsc2UgaWYocS54NChi
+KSl7cz1xLmIKc1tiXT1jCnI9cS5hCmlmKHI9PW51bGw/cyE9bnVsbDpyIT09cylyW2JdPW51bGx9ZWxz
+ZSBxLlhLKCkuWTUoMCxiLGMpfSwKeDQ6ZnVuY3Rpb24oYSl7aWYodGhpcy5iPT1udWxsKXJldHVybiB0
+aGlzLmMueDQoYSkKcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlz
+LmEsYSl9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbz10aGlzCnQuY0EuYShiKQppZihvLmI9
+PW51bGwpcmV0dXJuIG8uYy5LKDAsYikKcz1vLkNmKCkKZm9yKHI9MDtyPHMubGVuZ3RoOysrcil7cT1z
+W3JdCnA9by5iW3FdCmlmKHR5cGVvZiBwPT0idW5kZWZpbmVkIil7cD1QLlFlKG8uYVtxXSkKby5iW3Fd
+PXB9Yi4kMihxLHApCmlmKHMhPT1vLmMpdGhyb3cgSC5iKFAuYTQobykpfX0sCkNmOmZ1bmN0aW9uKCl7
+dmFyIHM9dC5iTS5hKHRoaXMuYykKaWYocz09bnVsbClzPXRoaXMuYz1ILlZNKE9iamVjdC5rZXlzKHRo
+aXMuYSksdC5zKQpyZXR1cm4gc30sClhLOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuPXRoaXMKaWYo
+bi5iPT1udWxsKXJldHVybiBuLmMKcz1QLkZsKHQuTix0LnopCnI9bi5DZigpCmZvcihxPTA7cD1yLmxl
+bmd0aCxxPHA7KytxKXtvPXJbcV0Kcy5ZNSgwLG8sbi5xKDAsbykpfWlmKHA9PT0wKUMuTm0uaShyLCIi
+KQplbHNlIEMuTm0uc0EociwwKQpuLmE9bi5iPW51bGwKcmV0dXJuIG4uYz1zfSwKZmI6ZnVuY3Rpb24o
+YSl7dmFyIHMKaWYoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSkp
+cmV0dXJuIG51bGwKcz1QLlFlKHRoaXMuYVthXSkKcmV0dXJuIHRoaXMuYlthXT1zfX0KUC5pOC5wcm90
+b3R5cGU9ewpnQTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMuZ0Eocyl9LApFOmZ1bmN0
+aW9uKGEsYil7dmFyIHM9dGhpcy5hCmlmKHMuYj09bnVsbClzPXMuZ3ZjKCkuRSgwLGIpCmVsc2V7cz1z
+LkNmKCkKaWYoYjwwfHxiPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLGIpCnM9c1tiXX1yZXR1cm4gc30s
+CmdtOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYQppZihzLmI9PW51bGwpe3M9cy5ndmMoKQpzPXMuZ20o
+cyl9ZWxzZXtzPXMuQ2YoKQpzPW5ldyBKLm0xKHMscy5sZW5ndGgsSC50NihzKS5DKCJtMTwxPiIpKX1y
+ZXR1cm4gc30sCnRnOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS54NChiKX19ClAueHIucHJvdG90
+eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgcyxyCnRyeXtzPW5ldyBUZXh0RGVjb2RlcigidXRmLTgiLHtm
+YXRhbDp0cnVlfSkKcmV0dXJuIHN9Y2F0Y2gocil7SC5SdShyKX1yZXR1cm4gbnVsbH0sCiRTOjEyfQpQ
+Lk56LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHMscgp0cnl7cz1uZXcgVGV4dERlY29kZXIo
+InV0Zi04Iix7ZmF0YWw6ZmFsc2V9KQpyZXR1cm4gc31jYXRjaChyKXtILlJ1KHIpfXJldHVybiBudWxs
+fSwKJFM6MTJ9ClAuQ1YucHJvdG90eXBlPXsKeXI6ZnVuY3Rpb24oYTAsYTEsYTIpe3ZhciBzLHIscSxw
+LG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhPSJJbnZhbGlkIGJhc2U2NCBlbmNvZGluZyBsZW5n
+dGggIgphMj1QLmpCKGExLGEyLGEwLmxlbmd0aCkKcz0kLlY3KCkKZm9yKHI9YTEscT1yLHA9bnVsbCxv
+PS0xLG49LTEsbT0wO3I8YTI7cj1sKXtsPXIrMQprPUMueEIuVyhhMCxyKQppZihrPT09Mzcpe2o9bCsy
+CmlmKGo8PWEyKXtpPUgub28oQy54Qi5XKGEwLGwpKQpoPUgub28oQy54Qi5XKGEwLGwrMSkpCmc9aSox
+NitoLShoJjI1NikKaWYoZz09PTM3KWc9LTEKbD1qfWVsc2UgZz0tMX1lbHNlIGc9awppZigwPD1nJiZn
+PD0xMjcpe2lmKGc8MHx8Zz49cy5sZW5ndGgpcmV0dXJuIEguT0gocyxnKQpmPXNbZ10KaWYoZj49MCl7
+Zz1DLnhCLk8oIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4
+eXowMTIzNDU2Nzg5Ky8iLGYpCmlmKGc9PT1rKWNvbnRpbnVlCms9Z31lbHNle2lmKGY9PT0tMSl7aWYo
+bzwwKXtlPXA9PW51bGw/bnVsbDpwLmEubGVuZ3RoCmlmKGU9PW51bGwpZT0wCm89ZSsoci1xKQpuPXJ9
+KyttCmlmKGs9PT02MSljb250aW51ZX1rPWd9aWYoZiE9PS0yKXtpZihwPT1udWxsKXtwPW5ldyBQLlJu
+KCIiKQplPXB9ZWxzZSBlPXAKZS5hKz1DLnhCLk5qKGEwLHEscikKZS5hKz1ILkx3KGspCnE9bApjb250
+aW51ZX19dGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IGRhdGEiLGEwLHIpKX1pZihwIT1udWxs
+KXtlPXAuYSs9Qy54Qi5OaihhMCxxLGEyKQpkPWUubGVuZ3RoCmlmKG8+PTApUC54TShhMCxuLGEyLG8s
+bSxkKQplbHNle2M9Qy5qbi56WShkLTEsNCkrMQppZihjPT09MSl0aHJvdyBILmIoUC5ycihhLGEwLGEy
+KSkKZm9yKDtjPDQ7KXtlKz0iPSIKcC5hPWU7KytjfX1lPXAuYQpyZXR1cm4gQy54Qi5pNyhhMCxhMSxh
+MixlLmNoYXJDb2RlQXQoMCk9PTA/ZTplKX1iPWEyLWExCmlmKG8+PTApUC54TShhMCxuLGEyLG8sbSxi
+KQplbHNle2M9Qy5qbi56WShiLDQpCmlmKGM9PT0xKXRocm93IEguYihQLnJyKGEsYTAsYTIpKQppZihj
+PjEpYTA9Qy54Qi5pNyhhMCxhMixhMixjPT09Mj8iPT0iOiI9Iil9cmV0dXJuIGEwfX0KUC5VOC5wcm90
+b3R5cGU9e30KUC5Vay5wcm90b3R5cGU9e30KUC53SS5wcm90b3R5cGU9e30KUC5aaS5wcm90b3R5cGU9
+e30KUC5VZC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzPVAucCh0aGlzLmEpCnJldHVybih0
+aGlzLmIhPW51bGw/IkNvbnZlcnRpbmcgb2JqZWN0IHRvIGFuIGVuY29kYWJsZSBvYmplY3QgZmFpbGVk
+OiI6IkNvbnZlcnRpbmcgb2JqZWN0IGRpZCBub3QgcmV0dXJuIGFuIGVuY29kYWJsZSBvYmplY3Q6Iikr
+IiAiK3N9fQpQLks4LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIkN5Y2xpYyBlcnJvciBp
+biBKU09OIHN0cmluZ2lmeSJ9fQpQLmJ5LnByb3RvdHlwZT17CnBXOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+cwp0LmZWLmEoYykKcz1QLkJTKGIsdGhpcy5nSGUoKS5hKQpyZXR1cm4gc30sCk9COmZ1bmN0aW9uKGEs
+Yil7dmFyIHMKdC5kQS5hKGIpCnM9UC51WChhLHRoaXMuZ1pFKCkuYixudWxsKQpyZXR1cm4gc30sCmda
+RTpmdW5jdGlvbigpe3JldHVybiBDLm5YfSwKZ0hlOmZ1bmN0aW9uKCl7cmV0dXJuIEMuQTN9fQpQLm9q
+LnByb3RvdHlwZT17fQpQLk14LnByb3RvdHlwZT17fQpQLlNoLnByb3RvdHlwZT17CnZwOmZ1bmN0aW9u
+KGEpe3ZhciBzLHIscSxwLG8sbixtLGw9YS5sZW5ndGgKZm9yKHM9Si5yWShhKSxyPXRoaXMuYyxxPTAs
+cD0wO3A8bDsrK3Ape289cy5XKGEscCkKaWYobz45Mil7aWYobz49NTUyOTYpe249byY2NDUxMgppZihu
+PT09NTUyOTYpe209cCsxCm09IShtPGwmJihDLnhCLlcoYSxtKSY2NDUxMik9PT01NjMyMCl9ZWxzZSBt
+PSExCmlmKCFtKWlmKG49PT01NjMyMCl7bj1wLTEKbj0hKG4+PTAmJihDLnhCLk8oYSxuKSY2NDUxMik9
+PT01NTI5Nil9ZWxzZSBuPSExCmVsc2Ugbj0hMAppZihuKXtpZihwPnEpci5hKz1DLnhCLk5qKGEscSxw
+KQpxPXArMQpyLmErPUguTHcoOTIpCnIuYSs9SC5MdygxMTcpCnIuYSs9SC5MdygxMDApCm49bz4+Pjgm
+MTUKci5hKz1ILkx3KG48MTA/NDgrbjo4NytuKQpuPW8+Pj40JjE1CnIuYSs9SC5MdyhuPDEwPzQ4K246
+ODcrbikKbj1vJjE1CnIuYSs9SC5MdyhuPDEwPzQ4K246ODcrbil9fWNvbnRpbnVlfWlmKG88MzIpe2lm
+KHA+cSlyLmErPUMueEIuTmooYSxxLHApCnE9cCsxCnIuYSs9SC5Mdyg5MikKc3dpdGNoKG8pe2Nhc2Ug
+ODpyLmErPUguTHcoOTgpCmJyZWFrCmNhc2UgOTpyLmErPUguTHcoMTE2KQpicmVhawpjYXNlIDEwOnIu
+YSs9SC5MdygxMTApCmJyZWFrCmNhc2UgMTI6ci5hKz1ILkx3KDEwMikKYnJlYWsKY2FzZSAxMzpyLmEr
+PUguTHcoMTE0KQpicmVhawpkZWZhdWx0OnIuYSs9SC5MdygxMTcpCnIuYSs9SC5Mdyg0OCkKci5hKz1I
+Lkx3KDQ4KQpuPW8+Pj40JjE1CnIuYSs9SC5MdyhuPDEwPzQ4K246ODcrbikKbj1vJjE1CnIuYSs9SC5M
+dyhuPDEwPzQ4K246ODcrbikKYnJlYWt9fWVsc2UgaWYobz09PTM0fHxvPT09OTIpe2lmKHA+cSlyLmEr
+PUMueEIuTmooYSxxLHApCnE9cCsxCnIuYSs9SC5Mdyg5MikKci5hKz1ILkx3KG8pfX1pZihxPT09MCly
+LmErPUguRWooYSkKZWxzZSBpZihxPGwpci5hKz1zLk5qKGEscSxsKX0sCkpuOmZ1bmN0aW9uKGEpe3Zh
+ciBzLHIscSxwCmZvcihzPXRoaXMuYSxyPXMubGVuZ3RoLHE9MDtxPHI7KytxKXtwPXNbcV0KaWYoYT09
+bnVsbD9wPT1udWxsOmE9PT1wKXRocm93IEguYihuZXcgUC5LOChhLG51bGwpKX1DLk5tLmkocyxhKX0s
+CmlVOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG89dGhpcwppZihvLnRNKGEpKXJldHVybgpvLkpuKGEp
+CnRyeXtzPW8uYi4kMShhKQppZighby50TShzKSl7cT1QLkd5KGEsbnVsbCxvLmdWSygpKQp0aHJvdyBI
+LmIocSl9cT1vLmEKaWYoMD49cS5sZW5ndGgpcmV0dXJuIEguT0gocSwtMSkKcS5wb3AoKX1jYXRjaChw
+KXtyPUguUnUocCkKcT1QLkd5KGEscixvLmdWSygpKQp0aHJvdyBILmIocSl9fSwKdE06ZnVuY3Rpb24o
+YSl7dmFyIHMscixxPXRoaXMKaWYodHlwZW9mIGE9PSJudW1iZXIiKXtpZighaXNGaW5pdGUoYSkpcmV0
+dXJuITEKcS5jLmErPUMuQ0QudyhhKQpyZXR1cm4hMH1lbHNlIGlmKGE9PT0hMCl7cS5jLmErPSJ0cnVl
+IgpyZXR1cm4hMH1lbHNlIGlmKGE9PT0hMSl7cS5jLmErPSJmYWxzZSIKcmV0dXJuITB9ZWxzZSBpZihh
+PT1udWxsKXtxLmMuYSs9Im51bGwiCnJldHVybiEwfWVsc2UgaWYodHlwZW9mIGE9PSJzdHJpbmciKXtz
+PXEuYwpzLmErPSciJwpxLnZwKGEpCnMuYSs9JyInCnJldHVybiEwfWVsc2UgaWYodC5qLmIoYSkpe3Eu
+Sm4oYSkKcS5sSyhhKQpzPXEuYQppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgp
+CnJldHVybiEwfWVsc2UgaWYodC5mLmIoYSkpe3EuSm4oYSkKcj1xLmp3KGEpCnM9cS5hCmlmKDA+PXMu
+bGVuZ3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9wKCkKcmV0dXJuIHJ9ZWxzZSByZXR1cm4hMX0sCmxL
+OmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzLmMKcS5hKz0iWyIKcz1KLlU2KGEpCmlmKHMuZ29yKGEp
+KXt0aGlzLmlVKHMucShhLDApKQpmb3Iocj0xO3I8cy5nQShhKTsrK3Ipe3EuYSs9IiwiCnRoaXMuaVUo
+cy5xKGEscikpfX1xLmErPSJdIn0sCmp3OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtPXRoaXMs
+bD17fQppZihhLmdsMChhKSl7bS5jLmErPSJ7fSIKcmV0dXJuITB9cz1hLmdBKGEpKjIKcj1QLk84KHMs
+bnVsbCwhMSx0LlcpCnE9bC5hPTAKbC5iPSEwCmEuSygwLG5ldyBQLnRpKGwscikpCmlmKCFsLmIpcmV0
+dXJuITEKcD1tLmMKcC5hKz0ieyIKZm9yKG89JyInO3E8cztxKz0yLG89JywiJyl7cC5hKz1vCm0udnAo
+SC5oKHJbcV0pKQpwLmErPSciOicKbj1xKzEKaWYobj49cylyZXR1cm4gSC5PSChyLG4pCm0uaVUocltu
+XSl9cC5hKz0ifSIKcmV0dXJuITB9fQpQLnRpLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFy
+IHMscgppZih0eXBlb2YgYSE9InN0cmluZyIpdGhpcy5hLmI9ITEKcz10aGlzLmIKcj10aGlzLmEKQy5O
+bS5ZNShzLHIuYSsrLGEpCkMuTm0uWTUocyxyLmErKyxiKX0sCiRTOjExfQpQLnR1LnByb3RvdHlwZT17
+CmdWSzpmdW5jdGlvbigpe3ZhciBzPXRoaXMuYy5hCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpz
+fX0KUC51NS5wcm90b3R5cGU9ewpnWkU6ZnVuY3Rpb24oKXtyZXR1cm4gQy5Ra319ClAuRTMucHJvdG90
+eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9UC5qQigwLG51bGwsYS5sZW5ndGgpLG89cC0w
+CmlmKG89PT0wKXJldHVybiBuZXcgVWludDhBcnJheSgwKQpzPW8qMwpyPW5ldyBVaW50OEFycmF5KHMp
+CnE9bmV3IFAuUncocikKaWYocS5HeChhLDAscCkhPT1wKXtKLmE2KGEscC0xKQpxLlJPKCl9cmV0dXJu
+IG5ldyBVaW50OEFycmF5KHIuc3ViYXJyYXkoMCxILnJNKDAscS5iLHMpKSl9fQpQLlJ3LnByb3RvdHlw
+ZT17ClJPOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcyxyPXMuYyxxPXMuYixwPXMuYj1xKzEsbz1yLmxlbmd0
+aAppZihxPj1vKXJldHVybiBILk9IKHIscSkKcltxXT0yMzkKcT1zLmI9cCsxCmlmKHA+PW8pcmV0dXJu
+IEguT0gocixwKQpyW3BdPTE5MQpzLmI9cSsxCmlmKHE+PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPTE4
+OX0sCk82OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuPXRoaXMKaWYoKGImNjQ1MTIpPT09NTYz
+MjApe3M9NjU1MzYrKChhJjEwMjMpPDwxMCl8YiYxMDIzCnI9bi5jCnE9bi5iCnA9bi5iPXErMQpvPXIu
+bGVuZ3RoCmlmKHE+PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPXM+Pj4xOHwyNDAKcT1uLmI9cCsxCmlm
+KHA+PW8pcmV0dXJuIEguT0gocixwKQpyW3BdPXM+Pj4xMiY2M3wxMjgKcD1uLmI9cSsxCmlmKHE+PW8p
+cmV0dXJuIEguT0gocixxKQpyW3FdPXM+Pj42JjYzfDEyOApuLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEgu
+T0gocixwKQpyW3BdPXMmNjN8MTI4CnJldHVybiEwfWVsc2V7bi5STygpCnJldHVybiExfX0sCkd4OmZ1
+bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxvLG4sbSxsPXRoaXMKaWYoYiE9PWMmJihDLnhCLk8oYSxj
+LTEpJjY0NTEyKT09PTU1Mjk2KS0tYwpmb3Iocz1sLmMscj1zLmxlbmd0aCxxPWI7cTxjOysrcSl7cD1D
+LnhCLlcoYSxxKQppZihwPD0xMjcpe289bC5iCmlmKG8+PXIpYnJlYWsKbC5iPW8rMQpzW29dPXB9ZWxz
+ZXtvPXAmNjQ1MTIKaWYobz09PTU1Mjk2KXtpZihsLmIrND5yKWJyZWFrCm49cSsxCmlmKGwuTzYocCxD
+LnhCLlcoYSxuKSkpcT1ufWVsc2UgaWYobz09PTU2MzIwKXtpZihsLmIrMz5yKWJyZWFrCmwuUk8oKX1l
+bHNlIGlmKHA8PTIwNDcpe289bC5iCm09bysxCmlmKG0+PXIpYnJlYWsKbC5iPW0KaWYobz49cilyZXR1
+cm4gSC5PSChzLG8pCnNbb109cD4+PjZ8MTkyCmwuYj1tKzEKc1ttXT1wJjYzfDEyOH1lbHNle289bC5i
+CmlmKG8rMj49cilicmVhawptPWwuYj1vKzEKaWYobz49cilyZXR1cm4gSC5PSChzLG8pCnNbb109cD4+
+PjEyfDIyNApvPWwuYj1tKzEKaWYobT49cilyZXR1cm4gSC5PSChzLG0pCnNbbV09cD4+PjYmNjN8MTI4
+CmwuYj1vKzEKaWYobz49cilyZXR1cm4gSC5PSChzLG8pCnNbb109cCY2M3wxMjh9fX1yZXR1cm4gcX19
+ClAuR1kucHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFyIHMscgp0LkwuYShhKQpzPXRoaXMuYQpy
+PVAua3kocyxhLDAsbnVsbCkKaWYociE9bnVsbClyZXR1cm4gcgpyZXR1cm4gbmV3IFAuYnoocykuTmUo
+YSwwLG51bGwsITApfX0KUC5iei5wcm90b3R5cGU9ewpOZTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxy
+LHEscCxvLG49dGhpcwp0LkwuYShhKQpzPVAuakIoYixjLEouSG0oYSkpCmlmKGI9PT1zKXJldHVybiIi
+CnI9UC5qeShhLGIscykKcT1uLmhPKHIsMCxzLWIsITApCnA9bi5iCmlmKChwJjEpIT09MCl7bz1QLmo0
+KHApCm4uYj0wCnRocm93IEguYihQLnJyKG8sYSxiK24uYykpfXJldHVybiBxfSwKaE86ZnVuY3Rpb24o
+YSxiLGMsZCl7dmFyIHMscixxPXRoaXMKaWYoYy1iPjEwMDApe3M9Qy5qbi5CVShiK2MsMikKcj1xLmhP
+KGEsYixzLCExKQppZigocS5iJjEpIT09MClyZXR1cm4gcgpyZXR1cm4gcitxLmhPKGEscyxjLGQpfXJl
+dHVybiBxLkVoKGEsYixjLGQpfSwKRWg6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuLG0s
+bCxrPXRoaXMsaj02NTUzMyxpPWsuYixoPWsuYyxnPW5ldyBQLlJuKCIiKSxmPWIrMSxlPWEubGVuZ3Ro
+CmlmKGI8MHx8Yj49ZSlyZXR1cm4gSC5PSChhLGIpCnM9YVtiXQokbGFiZWwwJDA6Zm9yKHI9ay5hOyEw
+Oyl7Zm9yKDshMDtmPW8pe3E9Qy54Qi5XKCJBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
 QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
-QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUZGRkZGRkZGRkZGRkZGRkZHR0dHR0dHR0dHR0dHR0dH
-SEhISEhISEhISEhISEhISEhISEhISEhISEhISUhISEpFRUJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJC
-QkJCQktDQ0NDQ0NDQ0NDQ0NEQ0xPTk5OTUVFRUVFRUVFRUVFIixzKSYzMQpoPWk8PTMyP3MmNjE2OTQ+
-Pj5xOihzJjYzfGg8PDYpPj4+MAppPUMueEIuVygiIFx4MDAwOlhFQ0NDQ0NOOmxEYiBceDAwMDpYRUND
-Q0NDTnZsRGIgXHgwMDA6WEVDQ0NDQ046bERiIEFBQUFBXHgwMFx4MDBceDAwXHgwMFx4MDBBQUFBQTAw
-MDAwQUFBQUE6Ojo6OkFBQUFBR0cwMDBBQUFBQTAwS0tLQUFBQUFHOjo6OkFBQUFBOklJSUlBQUFBQTAw
-MFx4ODAwQUFBQUFceDAwXHgwMFx4MDBceDAwIEFBQUFBIixpK3EpCmlmKGk9PT0wKXtnLmErPUguTHco
-aCkKaWYoZj09PWMpYnJlYWsgJGxhYmVsMCQwCmJyZWFrfWVsc2UgaWYoKGkmMSkhPT0wKXtpZihyKXN3
-aXRjaChpKXtjYXNlIDY5OmNhc2UgNjc6Zy5hKz1ILkx3KGopCmJyZWFrCmNhc2UgNjU6Zy5hKz1ILkx3
-KGopOy0tZgpicmVhawpkZWZhdWx0OnA9Zy5hKz1ILkx3KGopCmcuYT1wK0guTHcoaikKYnJlYWt9ZWxz
-ZXtrLmI9aQprLmM9Zi0xCnJldHVybiIifWk9MH1pZihmPT09YylicmVhayAkbGFiZWwwJDAKbz1mKzEK
-aWYoZjwwfHxmPj1lKXJldHVybiBILk9IKGEsZikKcz1hW2ZdfW89ZisxCmlmKGY8MHx8Zj49ZSlyZXR1
-cm4gSC5PSChhLGYpCnM9YVtmXQppZihzPDEyOCl7d2hpbGUoITApe2lmKCEobzxjKSl7bj1jCmJyZWFr
-fW09bysxCmlmKG88MHx8bz49ZSlyZXR1cm4gSC5PSChhLG8pCnM9YVtvXQppZihzPj0xMjgpe249bS0x
-Cm89bQpicmVha31vPW19aWYobi1mPDIwKWZvcihsPWY7bDxuOysrbCl7aWYobD49ZSlyZXR1cm4gSC5P
-SChhLGwpCmcuYSs9SC5MdyhhW2xdKX1lbHNlIGcuYSs9UC5ITShhLGYsbikKaWYobj09PWMpYnJlYWsg
-JGxhYmVsMCQwCmY9b31lbHNlIGY9b31pZihkJiZpPjMyKWlmKHIpZy5hKz1ILkx3KGopCmVsc2V7ay5i
-PTc3CmsuYz1jCnJldHVybiIifWsuYj1pCmsuYz1oCmU9Zy5hCnJldHVybiBlLmNoYXJDb2RlQXQoMCk9
-PTA/ZTplfX0KUC5XRi5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscQp0LmZvLmEo
-YSkKcz10aGlzLmIKcj10aGlzLmEKcy5hKz1yLmEKcT1zLmErPUguRWooYS5hKQpzLmE9cSsiOiAiCnMu
-YSs9UC5wKGIpCnIuYT0iLCAifSwKJFM6NDJ9ClAuaVAucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxi
-KXtpZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2YgUC5pUCYmdGhpcy5hPT09Yi5h
-JiYhMH0sCmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuKHNeQy5qbi53RyhzLDMwKSkm
-MTA3Mzc0MTgyM30sCnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcyxyPVAuR3EoSC50SihzKSkscT1QLmgw
-KEguTlMocykpLHA9UC5oMChILmpBKHMpKSxvPVAuaDAoSC5JWChzKSksbj1QLmgwKEguY2gocykpLG09
-UC5oMChILkpkKHMpKSxsPVAuVngoSC5vMShzKSksaz1yKyItIitxKyItIitwKyIgIitvKyI6IituKyI6
-IittKyIuIitsCnJldHVybiBrfX0KUC5YUy5wcm90b3R5cGU9ewpnSUk6ZnVuY3Rpb24oKXtyZXR1cm4g
-SC50cyh0aGlzLiR0aHJvd25Kc0Vycm9yKX19ClAuQzYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2
-YXIgcz10aGlzLmEKaWYocyE9bnVsbClyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLnAocykKcmV0
-dXJuIkFzc2VydGlvbiBmYWlsZWQifX0KUC5Fei5wcm90b3R5cGU9e30KUC5GLnByb3RvdHlwZT17Cnc6
-ZnVuY3Rpb24oYSl7cmV0dXJuIlRocm93IG9mIG51bGwuIn19ClAudS5wcm90b3R5cGU9ewpnWjpmdW5j
-dGlvbigpe3JldHVybiJJbnZhbGlkIGFyZ3VtZW50IisoIXRoaXMuYT8iKHMpIjoiIil9LApndTpmdW5j
-dGlvbigpe3JldHVybiIifSwKdzpmdW5jdGlvbihhKXt2YXIgcyxyLHE9dGhpcyxwPXEuYyxvPXA9PW51
-bGw/IiI6IiAoIitwKyIpIixuPXEuZCxtPW49PW51bGw/IiI6IjogIitILkVqKG4pLGw9cS5nWigpK28r
-bQppZighcS5hKXJldHVybiBsCnM9cS5ndSgpCnI9UC5wKHEuYikKcmV0dXJuIGwrcysiOiAiK3J9fQpQ
-LmJKLnByb3RvdHlwZT17CmdaOmZ1bmN0aW9uKCl7cmV0dXJuIlJhbmdlRXJyb3IifSwKZ3U6ZnVuY3Rp
-b24oKXt2YXIgcyxyPXRoaXMuZSxxPXRoaXMuZgppZihyPT1udWxsKXM9cSE9bnVsbD8iOiBOb3QgbGVz
-cyB0aGFuIG9yIGVxdWFsIHRvICIrSC5FaihxKToiIgplbHNlIGlmKHE9PW51bGwpcz0iOiBOb3QgZ3Jl
-YXRlciB0aGFuIG9yIGVxdWFsIHRvICIrSC5FaihyKQplbHNlIGlmKHE+cilzPSI6IE5vdCBpbiBpbmNs
-dXNpdmUgcmFuZ2UgIitILkVqKHIpKyIuLiIrSC5FaihxKQplbHNlIHM9cTxyPyI6IFZhbGlkIHZhbHVl
-IHJhbmdlIGlzIGVtcHR5IjoiOiBPbmx5IHZhbGlkIHZhbHVlIGlzICIrSC5FaihyKQpyZXR1cm4gc319
-ClAuZVkucHJvdG90eXBlPXsKZ1o6ZnVuY3Rpb24oKXtyZXR1cm4iUmFuZ2VFcnJvciJ9LApndTpmdW5j
-dGlvbigpe3ZhciBzLHI9SC51UCh0aGlzLmIpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJuIHIu
-SigpCmlmKHI8MClyZXR1cm4iOiBpbmRleCBtdXN0IG5vdCBiZSBuZWdhdGl2ZSIKcz10aGlzLmYKaWYo
-cz09PTApcmV0dXJuIjogbm8gaW5kaWNlcyBhcmUgdmFsaWQiCnJldHVybiI6IGluZGV4IHNob3VsZCBi
-ZSBsZXNzIHRoYW4gIitILkVqKHMpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZn19ClAubXAu
-cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsLGs9dGhpcyxqPXt9LGk9
-bmV3IFAuUm4oIiIpCmouYT0iIgpzPWsuYwpmb3Iocj1zLmxlbmd0aCxxPTAscD0iIixvPSIiO3E8cjsr
-K3Esbz0iLCAiKXtuPXNbcV0KaS5hPXArbwpwPWkuYSs9UC5wKG4pCmouYT0iLCAifWsuZC5LKDAsbmV3
-IFAuV0YoaixpKSkKbT1QLnAoay5hKQpsPWkudygwKQpyPSJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9k
-IG5vdCBmb3VuZDogJyIrSC5FaihrLmIuYSkrIidcblJlY2VpdmVyOiAiK20rIlxuQXJndW1lbnRzOiBb
-IitsKyJdIgpyZXR1cm4gcn19ClAudWIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iVW5z
-dXBwb3J0ZWQgb3BlcmF0aW9uOiAiK3RoaXMuYX19ClAuZHMucHJvdG90eXBlPXsKdzpmdW5jdGlvbihh
-KXt2YXIgcz10aGlzLmEKcmV0dXJuIHMhPW51bGw/IlVuaW1wbGVtZW50ZWRFcnJvcjogIitzOiJVbmlt
-cGxlbWVudGVkRXJyb3IifX0KUC5sai5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJCYWQg
-c3RhdGU6ICIrdGhpcy5hfX0KUC5VVi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMu
-YQppZihzPT1udWxsKXJldHVybiJDb25jdXJyZW50IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9u
-LiIKcmV0dXJuIkNvbmN1cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb246ICIrUC5wKHMp
-KyIuIn19ClAuazUucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iT3V0IG9mIE1lbW9yeSJ9
-LApnSUk6ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sCiRpWFM6MX0KUC5LWS5wcm90b3R5cGU9ewp3OmZ1
-bmN0aW9uKGEpe3JldHVybiJTdGFjayBPdmVyZmxvdyJ9LApnSUk6ZnVuY3Rpb24oKXtyZXR1cm4gbnVs
-bH0sCiRpWFM6MX0KUC5jLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVy
-biBzPT1udWxsPyJSZWFkaW5nIHN0YXRpYyB2YXJpYWJsZSBkdXJpbmcgaXRzIGluaXRpYWxpemF0aW9u
-IjoiUmVhZGluZyBzdGF0aWMgdmFyaWFibGUgJyIrcysiJyBkdXJpbmcgaXRzIGluaXRpYWxpemF0aW9u
-In19ClAuQ0QucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iRXhjZXB0aW9uOiAiK3RoaXMu
-YX0sCiRpUno6MX0KUC5hRS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixt
-LGwsayxqLGksaCxnPXRoaXMuYSxmPWchPW51bGwmJiIiIT09Zz8iRm9ybWF0RXhjZXB0aW9uOiAiK0gu
-RWooZyk6IkZvcm1hdEV4Y2VwdGlvbiIsZT10aGlzLmMsZD10aGlzLmIKaWYodHlwZW9mIGQ9PSJzdHJp
-bmciKXtpZihlIT1udWxsKXM9ZTwwfHxlPmQubGVuZ3RoCmVsc2Ugcz0hMQppZihzKWU9bnVsbAppZihl
-PT1udWxsKXtpZihkLmxlbmd0aD43OClkPUMueEIuTmooZCwwLDc1KSsiLi4uIgpyZXR1cm4gZisiXG4i
-K2R9Zm9yKHI9MSxxPTAscD0hMSxvPTA7bzxlOysrbyl7bj1DLnhCLlcoZCxvKQppZihuPT09MTApe2lm
-KHEhPT1vfHwhcCkrK3IKcT1vKzEKcD0hMX1lbHNlIGlmKG49PT0xMyl7KytyCnE9bysxCnA9ITB9fWY9
-cj4xP2YrKCIgKGF0IGxpbmUgIityKyIsIGNoYXJhY3RlciAiKyhlLXErMSkrIilcbiIpOmYrKCIgKGF0
-IGNoYXJhY3RlciAiKyhlKzEpKyIpXG4iKQptPWQubGVuZ3RoCmZvcihvPWU7bzxtOysrbyl7bj1DLnhC
-Lk8yKGQsbykKaWYobj09PTEwfHxuPT09MTMpe209bwpicmVha319aWYobS1xPjc4KWlmKGUtcTw3NSl7
-bD1xKzc1Cms9cQpqPSIiCmk9Ii4uLiJ9ZWxzZXtpZihtLWU8NzUpe2s9bS03NQpsPW0KaT0iIn1lbHNl
-e2s9ZS0zNgpsPWUrMzYKaT0iLi4uIn1qPSIuLi4ifWVsc2V7bD1tCms9cQpqPSIiCmk9IiJ9aD1DLnhC
-Lk5qKGQsayxsKQpyZXR1cm4gZitqK2graSsiXG4iK0MueEIuVCgiICIsZS1rK2oubGVuZ3RoKSsiXlxu
-In1lbHNlIHJldHVybiBlIT1udWxsP2YrKCIgKGF0IG9mZnNldCAiK0guRWooZSkrIikiKTpmfSwKJGlS
-ejoxfQpQLmNYLnByb3RvdHlwZT17CmRyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguR0oodGhpcyxILkxo
-KHRoaXMpLkMoImNYLkUiKSxiKX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1ILkxoKHRoaXMpCnJl
-dHVybiBILksxKHRoaXMscy5LcShjKS5DKCIxKGNYLkUpIikuYShiKSxzLkMoImNYLkUiKSxjKX0sCmV2
-OmZ1bmN0aW9uKGEsYil7dmFyIHM9SC5MaCh0aGlzKQpyZXR1cm4gbmV3IEguVTUodGhpcyxzLkMoImEy
-KGNYLkUpIikuYShiKSxzLkMoIlU1PGNYLkU+IikpfSwKdHQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gUC5Z
-MSh0aGlzLGIsSC5MaCh0aGlzKS5DKCJjWC5FIikpfSwKYnI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
-dHQoYSwhMCl9LApnQTpmdW5jdGlvbihhKXt2YXIgcyxyPXRoaXMuZ20odGhpcykKZm9yKHM9MDtyLkYo
-KTspKytzCnJldHVybiBzfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiF0aGlzLmdtKHRoaXMpLkYoKX0s
-CmdvcjpmdW5jdGlvbihhKXtyZXR1cm4hdGhpcy5nbDAodGhpcyl9LAplUjpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBILmJLKHRoaXMsYixILkxoKHRoaXMpLkMoImNYLkUiKSl9LApncjg6ZnVuY3Rpb24oYSl7dmFy
-IHMscj10aGlzLmdtKHRoaXMpCmlmKCFyLkYoKSl0aHJvdyBILmIoSC5XcCgpKQpzPXIuZ2woKQppZihy
-LkYoKSl0aHJvdyBILmIoSC5BbSgpKQpyZXR1cm4gc30sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEK
-UC5rMShiLCJpbmRleCIpCmZvcihzPXRoaXMuZ20odGhpcykscj0wO3MuRigpOyl7cT1zLmdsKCkKaWYo
-Yj09PXIpcmV0dXJuIHE7KytyfXRocm93IEguYihQLkNmKGIsdGhpcywiaW5kZXgiLG51bGwscikpfSwK
-dzpmdW5jdGlvbihhKXtyZXR1cm4gUC5FUCh0aGlzLCIoIiwiKSIpfX0KUC5Bbi5wcm90b3R5cGU9e30K
-UC5OMy5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJNYXBFbnRyeSgiK0guRWooSi5qKHRo
-aXMuYSkpKyI6ICIrSC5FaihKLmoodGhpcy5iKSkrIikifX0KUC5jOC5wcm90b3R5cGU9ewpnaU86ZnVu
-Y3Rpb24oYSl7cmV0dXJuIFAuTWgucHJvdG90eXBlLmdpTy5jYWxsKEMuak4sdGhpcyl9LAp3OmZ1bmN0
-aW9uKGEpe3JldHVybiJudWxsIn19ClAuTWgucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpQLk1oLCRpTWg6
-MSwKRE46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcz09PWJ9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJu
-IEguZVEodGhpcyl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiJJbnN0YW5jZSBvZiAnIitILkVqKEguTSh0
-aGlzKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt0Lm8uYShiKQp0aHJvdyBILmIoUC5scih0aGlzLGIu
-Z1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9LAp0b1N0cmluZzpmdW5jdGlvbigpe3JldHVybiB0aGlzLnco
-dGhpcyl9fQpQLlpkLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIiJ9LAokaUd6OjF9ClAu
-Um4ucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LAp3OmZ1bmN0
-aW9uKGEpe3ZhciBzPXRoaXMuYQpyZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c30sCiRpQkw6MX0K
-UC5uMS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwCnQuSi5hKGEpCkguaChi
-KQpzPUouclkoYikuT1koYiwiPSIpCmlmKHM9PT0tMSl7aWYoYiE9PSIiKWEuWTUoMCxQLmt1KGIsMCxi
-Lmxlbmd0aCx0aGlzLmEsITApLCIiKX1lbHNlIGlmKHMhPT0wKXtyPUMueEIuTmooYiwwLHMpCnE9Qy54
-Qi55bihiLHMrMSkKcD10aGlzLmEKYS5ZNSgwLFAua3UociwwLHIubGVuZ3RoLHAsITApLFAua3UocSww
-LHEubGVuZ3RoLHAsITApKX1yZXR1cm4gYX0sCiRTOjQ0fQpQLmNTLnByb3RvdHlwZT17CiQyOmZ1bmN0
-aW9uKGEsYil7dGhyb3cgSC5iKFAucnIoIklsbGVnYWwgSVB2NCBhZGRyZXNzLCAiK2EsdGhpcy5hLGIp
-KX0sCiRTOjIxfQpQLlZDLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhyb3cgSC5iKFAucnIo
-IklsbGVnYWwgSVB2NiBhZGRyZXNzLCAiK2EsdGhpcy5hLGIpKX0sCiQxOmZ1bmN0aW9uKGEpe3JldHVy
-biB0aGlzLiQyKGEsbnVsbCl9LAokUzo0OX0KUC5KVC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIp
-e3ZhciBzCmlmKGItYT40KXRoaXMuYS4kMigiYW4gSVB2NiBwYXJ0IGNhbiBvbmx5IGNvbnRhaW4gYSBt
-YXhpbXVtIG9mIDQgaGV4IGRpZ2l0cyIsYSkKcz1QLlFBKEMueEIuTmoodGhpcy5iLGEsYiksMTYpCmlm
-KHM8MHx8cz42NTUzNSl0aGlzLmEuJDIoImVhY2ggcGFydCBtdXN0IGJlIGluIHRoZSByYW5nZSBvZiBg
-MHgwLi4weEZGRkZgIixhKQpyZXR1cm4gc30sCiRTOjUxfQpQLkRuLnByb3RvdHlwZT17CmduRDpmdW5j
-dGlvbigpe3ZhciBzLHIscSxwLG89dGhpcwppZighby55KXtzPW8uYQpyPXMubGVuZ3RoIT09MD9zKyI6
-IjoiIgpxPW8uYwpwPXE9PW51bGwKaWYoIXB8fHM9PT0iZmlsZSIpe3M9cisiLy8iCnI9by5iCmlmKHIu
-bGVuZ3RoIT09MClzPXMrcisiQCIKaWYoIXApcys9cQpyPW8uZAppZihyIT1udWxsKXM9cysiOiIrSC5F
-aihyKX1lbHNlIHM9cgpzKz1vLmUKcj1vLmYKaWYociE9bnVsbClzPXMrIj8iK3IKcj1vLnIKaWYociE9
-bnVsbClzPXMrIiMiK3IKaWYoby55KXRocm93IEguYihILkdRKCJfdGV4dCIpKQpvLng9cy5jaGFyQ29k
-ZUF0KDApPT0wP3M6cwpvLnk9ITB9cmV0dXJuIG8ueH0sCmdGajpmdW5jdGlvbigpe3ZhciBzLHIscT10
-aGlzCmlmKCFxLlEpe3M9cS5lCmlmKHMubGVuZ3RoIT09MCYmQy54Qi5XKHMsMCk9PT00NylzPUMueEIu
-eW4ocywxKQpyPXMubGVuZ3RoPT09MD9DLnhEOlAuQUYobmV3IEgubEooSC5WTShzLnNwbGl0KCIvIiks
-dC5zKSx0LmRPLmEoUC5QSCgpKSx0LmRvKSx0Lk4pCmlmKHEuUSl0aHJvdyBILmIoSC5HUSgicGF0aFNl
-Z21lbnRzIikpCnEuc0twKHIpCnEuUT0hMH1yZXR1cm4gcS56fSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBz
-LHI9dGhpcwppZighci5jeCl7cz1KLmhmKHIuZ25EKCkpCmlmKHIuY3gpdGhyb3cgSC5iKEguR1EoImhh
-c2hDb2RlIikpCnIuY2g9cwpyLmN4PSEwfXJldHVybiByLmNofSwKZ2hZOmZ1bmN0aW9uKCl7dmFyIHMs
-cj10aGlzCmlmKCFyLmRiKXtzPVAuV1goci5ndFAoKSkKaWYoci5kYil0aHJvdyBILmIoSC5HUSgicXVl
-cnlQYXJhbWV0ZXJzIikpCnIuc05NKG5ldyBQLkdqKHMsdC5kdykpCnIuZGI9ITB9cmV0dXJuIHIuY3l9
-LApna3U6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5ifSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMu
-YwppZihzPT1udWxsKXJldHVybiIiCmlmKEMueEIubkMocywiWyIpKXJldHVybiBDLnhCLk5qKHMsMSxz
-Lmxlbmd0aC0xKQpyZXR1cm4gc30sCmd0cDpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmQKcmV0dXJuIHM9
-PW51bGw/UC53Syh0aGlzLmEpOnN9LApndFA6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLmYKcmV0dXJuIHM9
-PW51bGw/IiI6c30sCmdLYTpmdW5jdGlvbigpe3ZhciBzPXRoaXMucgpyZXR1cm4gcz09bnVsbD8iIjpz
-fSwKbm06ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaj10aGlzCnQuYzkuYShiKQpz
-PWouYQpyPXM9PT0iZmlsZSIKcT1qLmIKcD1qLmQKbz1qLmMKaWYoIShvIT1udWxsKSlvPXEubGVuZ3Ro
-IT09MHx8cCE9bnVsbHx8cj8iIjpudWxsCm49ai5lCmlmKCFyKW09byE9bnVsbCYmbi5sZW5ndGghPT0w
-CmVsc2UgbT0hMAppZihtJiYhQy54Qi5uQyhuLCIvIikpbj0iLyIrbgpsPW4Kaz1QLmxlKG51bGwsMCww
-LGIpCnJldHVybiBuZXcgUC5EbihzLHEsbyxwLGwsayxqLnIpfSwKSmg6ZnVuY3Rpb24oYSxiKXt2YXIg
-cyxyLHEscCxvLG4KZm9yKHM9MCxyPTA7Qy54Qi5RaShiLCIuLi8iLHIpOyl7cis9MzsrK3N9cT1DLnhC
-LmNuKGEsIi8iKQp3aGlsZSghMCl7aWYoIShxPjAmJnM+MCkpYnJlYWsKcD1DLnhCLlBrKGEsIi8iLHEt
-MSkKaWYocDwwKWJyZWFrCm89cS1wCm49byE9PTIKaWYoIW58fG89PT0zKWlmKEMueEIuTzIoYSxwKzEp
-PT09NDYpbj0hbnx8Qy54Qi5PMihhLHArMik9PT00NgplbHNlIG49ITEKZWxzZSBuPSExCmlmKG4pYnJl
-YWs7LS1zCnE9cH1yZXR1cm4gQy54Qi5pNyhhLHErMSxudWxsLEMueEIueW4oYixyLTMqcykpfSwKWkk6
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMubVMoUC5oSyhhKSl9LAptUzpmdW5jdGlvbihhKXt2YXIgcyxy
-LHEscCxvLG4sbSxsLGssaj10aGlzLGk9bnVsbAppZihhLmdGaSgpLmxlbmd0aCE9PTApe3M9YS5nRmko
-KQppZihhLmdjaigpKXtyPWEuZ2t1KCkKcT1hLmdKZihhKQpwPWEuZ3hBKCk/YS5ndHAoYSk6aX1lbHNl
-e3A9aQpxPXAKcj0iIn1vPVAueGUoYS5nSWkoYSkpCm49YS5nUUQoKT9hLmd0UCgpOml9ZWxzZXtzPWou
-YQppZihhLmdjaigpKXtyPWEuZ2t1KCkKcT1hLmdKZihhKQpwPVAud0IoYS5neEEoKT9hLmd0cChhKTpp
-LHMpCm89UC54ZShhLmdJaShhKSkKbj1hLmdRRCgpP2EuZ3RQKCk6aX1lbHNle3I9ai5iCnE9ai5jCnA9
-ai5kCmlmKGEuZ0lpKGEpPT09IiIpe289ai5lCm49YS5nUUQoKT9hLmd0UCgpOmouZn1lbHNle2lmKGEu
-Z3RUKCkpbz1QLnhlKGEuZ0lpKGEpKQplbHNle209ai5lCmlmKG0ubGVuZ3RoPT09MClpZihxPT1udWxs
-KW89cy5sZW5ndGg9PT0wP2EuZ0lpKGEpOlAueGUoYS5nSWkoYSkpCmVsc2Ugbz1QLnhlKCIvIithLmdJ
-aShhKSkKZWxzZXtsPWouSmgobSxhLmdJaShhKSkKaz1zLmxlbmd0aD09PTAKaWYoIWt8fHEhPW51bGx8
-fEMueEIubkMobSwiLyIpKW89UC54ZShsKQplbHNlIG89UC53RihsLCFrfHxxIT1udWxsKX19bj1hLmdR
+QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUZGRkZGRkZGRkZGRkZGRkZHR0dHR0dHR0dH
+R0dHR0dHSEhISEhISEhISEhISEhISEhISEhISEhISEhISUhISEpFRUJCQkJCQkJCQkJCQkJCQkJCQkJC
+QkJCQkJCQkJCQktDQ0NDQ0NDQ0NDQ0NEQ0xPTk5OTUVFRUVFRUVFRUVFIixzKSYzMQpoPWk8PTMyP3Mm
+NjE2OTQ+Pj5xOihzJjYzfGg8PDYpPj4+MAppPUMueEIuVygiIFx4MDAwOlhFQ0NDQ0NOOmxEYiBceDAw
+MDpYRUNDQ0NDTnZsRGIgXHgwMDA6WEVDQ0NDQ046bERiIEFBQUFBXHgwMFx4MDBceDAwXHgwMFx4MDBB
+QUFBQTAwMDAwQUFBQUE6Ojo6OkFBQUFBR0cwMDBBQUFBQTAwS0tLQUFBQUFHOjo6OkFBQUFBOklJSUlB
+QUFBQTAwMFx4ODAwQUFBQUFceDAwXHgwMFx4MDBceDAwIEFBQUFBIixpK3EpCmlmKGk9PT0wKXtnLmEr
+PUguTHcoaCkKaWYoZj09PWMpYnJlYWsgJGxhYmVsMCQwCmJyZWFrfWVsc2UgaWYoKGkmMSkhPT0wKXtp
+ZihyKXN3aXRjaChpKXtjYXNlIDY5OmNhc2UgNjc6Zy5hKz1ILkx3KGopCmJyZWFrCmNhc2UgNjU6Zy5h
+Kz1ILkx3KGopOy0tZgpicmVhawpkZWZhdWx0OnA9Zy5hKz1ILkx3KGopCmcuYT1wK0guTHcoaikKYnJl
+YWt9ZWxzZXtrLmI9aQprLmM9Zi0xCnJldHVybiIifWk9MH1pZihmPT09YylicmVhayAkbGFiZWwwJDAK
+bz1mKzEKaWYoZjwwfHxmPj1lKXJldHVybiBILk9IKGEsZikKcz1hW2ZdfW89ZisxCmlmKGY8MHx8Zj49
+ZSlyZXR1cm4gSC5PSChhLGYpCnM9YVtmXQppZihzPDEyOCl7d2hpbGUoITApe2lmKCEobzxjKSl7bj1j
+CmJyZWFrfW09bysxCmlmKG88MHx8bz49ZSlyZXR1cm4gSC5PSChhLG8pCnM9YVtvXQppZihzPj0xMjgp
+e249bS0xCm89bQpicmVha31vPW19aWYobi1mPDIwKWZvcihsPWY7bDxuOysrbCl7aWYobD49ZSlyZXR1
+cm4gSC5PSChhLGwpCmcuYSs9SC5MdyhhW2xdKX1lbHNlIGcuYSs9UC5ITShhLGYsbikKaWYobj09PWMp
+YnJlYWsgJGxhYmVsMCQwCmY9b31lbHNlIGY9b31pZihkJiZpPjMyKWlmKHIpZy5hKz1ILkx3KGopCmVs
+c2V7ay5iPTc3CmsuYz1jCnJldHVybiIifWsuYj1pCmsuYz1oCmU9Zy5hCnJldHVybiBlLmNoYXJDb2Rl
+QXQoMCk9PTA/ZTplfX0KUC5XRi5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscQp0
+LmZvLmEoYSkKcz10aGlzLmIKcj10aGlzLmEKcy5hKz1yLmEKcT1zLmErPUguRWooYS5hKQpzLmE9cSsi
+OiAiCnMuYSs9UC5wKGIpCnIuYT0iLCAifSwKJFM6NDB9ClAuaVAucHJvdG90eXBlPXsKRE46ZnVuY3Rp
+b24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2YgUC5pUCYmdGhpcy5h
+PT09Yi5hJiYhMH0sCmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuKHNeQy5qbi53Ryhz
+LDMwKSkmMTA3Mzc0MTgyM30sCnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcyxyPVAuR3EoSC50SihzKSks
+cT1QLmgwKEguTlMocykpLHA9UC5oMChILmpBKHMpKSxvPVAuaDAoSC5JWChzKSksbj1QLmgwKEguY2go
+cykpLG09UC5oMChILkpkKHMpKSxsPVAuVngoSC5vMShzKSksaz1yKyItIitxKyItIitwKyIgIitvKyI6
+IituKyI6IittKyIuIitsCnJldHVybiBrfX0KUC5YUy5wcm90b3R5cGU9ewpnSUk6ZnVuY3Rpb24oKXty
+ZXR1cm4gSC50cyh0aGlzLiR0aHJvd25Kc0Vycm9yKX19ClAuQzYucHJvdG90eXBlPXsKdzpmdW5jdGlv
+bihhKXt2YXIgcz10aGlzLmEKaWYocyE9bnVsbClyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLnAo
+cykKcmV0dXJuIkFzc2VydGlvbiBmYWlsZWQifX0KUC5Fei5wcm90b3R5cGU9e30KUC5GLnByb3RvdHlw
+ZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlRocm93IG9mIG51bGwuIn19ClAudS5wcm90b3R5cGU9ewpn
+WjpmdW5jdGlvbigpe3JldHVybiJJbnZhbGlkIGFyZ3VtZW50IisoIXRoaXMuYT8iKHMpIjoiIil9LApn
+dTpmdW5jdGlvbigpe3JldHVybiIifSwKdzpmdW5jdGlvbihhKXt2YXIgcyxyLHE9dGhpcyxwPXEuYyxv
+PXA9PW51bGw/IiI6IiAoIitwKyIpIixuPXEuZCxtPW49PW51bGw/IiI6IjogIitILkVqKG4pLGw9cS5n
+WigpK28rbQppZighcS5hKXJldHVybiBsCnM9cS5ndSgpCnI9UC5wKHEuYikKcmV0dXJuIGwrcysiOiAi
+K3J9fQpQLmJKLnByb3RvdHlwZT17CmdaOmZ1bmN0aW9uKCl7cmV0dXJuIlJhbmdlRXJyb3IifSwKZ3U6
+ZnVuY3Rpb24oKXt2YXIgcyxyPXRoaXMuZSxxPXRoaXMuZgppZihyPT1udWxsKXM9cSE9bnVsbD8iOiBO
+b3QgbGVzcyB0aGFuIG9yIGVxdWFsIHRvICIrSC5FaihxKToiIgplbHNlIGlmKHE9PW51bGwpcz0iOiBO
+b3QgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvICIrSC5FaihyKQplbHNlIGlmKHE+cilzPSI6IE5vdCBp
+biBpbmNsdXNpdmUgcmFuZ2UgIitILkVqKHIpKyIuLiIrSC5FaihxKQplbHNlIHM9cTxyPyI6IFZhbGlk
+IHZhbHVlIHJhbmdlIGlzIGVtcHR5IjoiOiBPbmx5IHZhbGlkIHZhbHVlIGlzICIrSC5FaihyKQpyZXR1
+cm4gc319ClAuZVkucHJvdG90eXBlPXsKZ1o6ZnVuY3Rpb24oKXtyZXR1cm4iUmFuZ2VFcnJvciJ9LApn
+dTpmdW5jdGlvbigpe3ZhciBzLHI9SC51UCh0aGlzLmIpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0
+dXJuIHIuSigpCmlmKHI8MClyZXR1cm4iOiBpbmRleCBtdXN0IG5vdCBiZSBuZWdhdGl2ZSIKcz10aGlz
+LmYKaWYocz09PTApcmV0dXJuIjogbm8gaW5kaWNlcyBhcmUgdmFsaWQiCnJldHVybiI6IGluZGV4IHNo
+b3VsZCBiZSBsZXNzIHRoYW4gIitILkVqKHMpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZn19
+ClAubXAucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsLGs9dGhpcyxq
+PXt9LGk9bmV3IFAuUm4oIiIpCmouYT0iIgpzPWsuYwpmb3Iocj1zLmxlbmd0aCxxPTAscD0iIixvPSIi
+O3E8cjsrK3Esbz0iLCAiKXtuPXNbcV0KaS5hPXArbwpwPWkuYSs9UC5wKG4pCmouYT0iLCAifWsuZC5L
+KDAsbmV3IFAuV0YoaixpKSkKbT1QLnAoay5hKQpsPWkudygwKQpyPSJOb1N1Y2hNZXRob2RFcnJvcjog
+bWV0aG9kIG5vdCBmb3VuZDogJyIrSC5FaihrLmIuYSkrIidcblJlY2VpdmVyOiAiK20rIlxuQXJndW1l
+bnRzOiBbIitsKyJdIgpyZXR1cm4gcn19ClAudWIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1
+cm4iVW5zdXBwb3J0ZWQgb3BlcmF0aW9uOiAiK3RoaXMuYX19ClAuZHMucHJvdG90eXBlPXsKdzpmdW5j
+dGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMhPW51bGw/IlVuaW1wbGVtZW50ZWRFcnJvcjogIitz
+OiJVbmltcGxlbWVudGVkRXJyb3IifX0KUC5sai5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVy
+biJCYWQgc3RhdGU6ICIrdGhpcy5hfX0KUC5VVi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBz
+PXRoaXMuYQppZihzPT1udWxsKXJldHVybiJDb25jdXJyZW50IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRl
+cmF0aW9uLiIKcmV0dXJuIkNvbmN1cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb246ICIr
+UC5wKHMpKyIuIn19ClAuazUucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iT3V0IG9mIE1l
+bW9yeSJ9LApnSUk6ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sCiRpWFM6MX0KUC5LWS5wcm90b3R5cGU9
+ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJTdGFjayBPdmVyZmxvdyJ9LApnSUk6ZnVuY3Rpb24oKXtyZXR1
+cm4gbnVsbH0sCiRpWFM6MX0KUC5jLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5h
+CnJldHVybiBzPT1udWxsPyJSZWFkaW5nIHN0YXRpYyB2YXJpYWJsZSBkdXJpbmcgaXRzIGluaXRpYWxp
+emF0aW9uIjoiUmVhZGluZyBzdGF0aWMgdmFyaWFibGUgJyIrcysiJyBkdXJpbmcgaXRzIGluaXRpYWxp
+emF0aW9uIn19ClAuQ0QucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iRXhjZXB0aW9uOiAi
+K3RoaXMuYX0sCiRpUno6MX0KUC5hRS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxw
+LG8sbixtLGwsayxqLGksaCxnPXRoaXMuYSxmPWchPW51bGwmJiIiIT09Zz8iRm9ybWF0RXhjZXB0aW9u
+OiAiK0guRWooZyk6IkZvcm1hdEV4Y2VwdGlvbiIsZT10aGlzLmMsZD10aGlzLmIKaWYodHlwZW9mIGQ9
+PSJzdHJpbmciKXtpZihlIT1udWxsKXM9ZTwwfHxlPmQubGVuZ3RoCmVsc2Ugcz0hMQppZihzKWU9bnVs
+bAppZihlPT1udWxsKXtpZihkLmxlbmd0aD43OClkPUMueEIuTmooZCwwLDc1KSsiLi4uIgpyZXR1cm4g
+ZisiXG4iK2R9Zm9yKHI9MSxxPTAscD0hMSxvPTA7bzxlOysrbyl7bj1DLnhCLlcoZCxvKQppZihuPT09
+MTApe2lmKHEhPT1vfHwhcCkrK3IKcT1vKzEKcD0hMX1lbHNlIGlmKG49PT0xMyl7KytyCnE9bysxCnA9
+ITB9fWY9cj4xP2YrKCIgKGF0IGxpbmUgIityKyIsIGNoYXJhY3RlciAiKyhlLXErMSkrIilcbiIpOmYr
+KCIgKGF0IGNoYXJhY3RlciAiKyhlKzEpKyIpXG4iKQptPWQubGVuZ3RoCmZvcihvPWU7bzxtOysrbyl7
+bj1DLnhCLk8oZCxvKQppZihuPT09MTB8fG49PT0xMyl7bT1vCmJyZWFrfX1pZihtLXE+NzgpaWYoZS1x
+PDc1KXtsPXErNzUKaz1xCmo9IiIKaT0iLi4uIn1lbHNle2lmKG0tZTw3NSl7az1tLTc1Cmw9bQppPSIi
+fWVsc2V7az1lLTM2Cmw9ZSszNgppPSIuLi4ifWo9Ii4uLiJ9ZWxzZXtsPW0Kaz1xCmo9IiIKaT0iIn1o
+PUMueEIuTmooZCxrLGwpCnJldHVybiBmK2oraCtpKyJcbiIrQy54Qi5UKCIgIixlLWsrai5sZW5ndGgp
+KyJeXG4ifWVsc2UgcmV0dXJuIGUhPW51bGw/ZisoIiAoYXQgb2Zmc2V0ICIrSC5FaihlKSsiKSIpOmZ9
+LAokaVJ6OjF9ClAuY1gucHJvdG90eXBlPXsKZHI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5HSih0aGlz
+LEguTGgodGhpcykuQygiY1guRSIpLGIpfSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPUguTGgodGhp
+cykKcmV0dXJuIEguSzEodGhpcyxzLktxKGMpLkMoIjEoY1guRSkiKS5hKGIpLHMuQygiY1guRSIpLGMp
+fSwKZXY6ZnVuY3Rpb24oYSxiKXt2YXIgcz1ILkxoKHRoaXMpCnJldHVybiBuZXcgSC5VNSh0aGlzLHMu
+QygiYTIoY1guRSkiKS5hKGIpLHMuQygiVTU8Y1guRT4iKSl9LAp0dDpmdW5jdGlvbihhLGIpe3JldHVy
+biBQLlkxKHRoaXMsYixILkxoKHRoaXMpLkMoImNYLkUiKSl9LApicjpmdW5jdGlvbihhKXtyZXR1cm4g
+dGhpcy50dChhLCEwKX0sCmdBOmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcy5nbSh0aGlzKQpmb3Iocz0w
+O3IuRigpOykrK3MKcmV0dXJuIHN9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIXRoaXMuZ20odGhpcyku
+RigpfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiF0aGlzLmdsMCh0aGlzKX0sCmVSOmZ1bmN0aW9uKGEs
+Yil7cmV0dXJuIEguYksodGhpcyxiLEguTGgodGhpcykuQygiY1guRSIpKX0sCmdyODpmdW5jdGlvbihh
+KXt2YXIgcyxyPXRoaXMuZ20odGhpcykKaWYoIXIuRigpKXRocm93IEguYihILldwKCkpCnM9ci5nbCgp
+CmlmKHIuRigpKXRocm93IEguYihILkFtKCkpCnJldHVybiBzfSwKRTpmdW5jdGlvbihhLGIpe3ZhciBz
+LHIscQpQLmsxKGIsImluZGV4IikKZm9yKHM9dGhpcy5nbSh0aGlzKSxyPTA7cy5GKCk7KXtxPXMuZ2wo
+KQppZihiPT09cilyZXR1cm4gcTsrK3J9dGhyb3cgSC5iKFAuQ2YoYix0aGlzLCJpbmRleCIsbnVsbCxy
+KSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLkVQKHRoaXMsIigiLCIpIil9fQpQLkFuLnByb3RvdHlw
+ZT17fQpQLk4zLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIk1hcEVudHJ5KCIrSC5FaihK
+LmoodGhpcy5hKSkrIjogIitILkVqKEouaih0aGlzLmIpKSsiKSJ9fQpQLmM4LnByb3RvdHlwZT17Cmdp
+TzpmdW5jdGlvbihhKXtyZXR1cm4gUC5NaC5wcm90b3R5cGUuZ2lPLmNhbGwoQy5qTix0aGlzKX0sCnc6
+ZnVuY3Rpb24oYSl7cmV0dXJuIm51bGwifX0KUC5NaC5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOlAuTWgs
+JGlNaDoxLApETjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzPT09Yn0sCmdpTzpmdW5jdGlvbihhKXty
+ZXR1cm4gSC5lUSh0aGlzKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIkluc3RhbmNlIG9mICciK0guRWoo
+SC5NKHRoaXMpKSsiJyJ9LAplNzpmdW5jdGlvbihhLGIpe3Quby5hKGIpCnRocm93IEguYihQLmxyKHRo
+aXMsYi5nV2EoKSxiLmduZCgpLGIuZ1ZtKCkpKX0sCnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIHRo
+aXMudyh0aGlzKX19ClAuWmQucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iIn0sCiRpR3o6
+MX0KUC5Sbi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmxlbmd0aH0sCnc6
+ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKJGlC
+TDoxfQpQLm4xLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAKdC5KLmEoYSkK
+SC5oKGIpCnM9Si5yWShiKS5PWShiLCI9IikKaWYocz09PS0xKXtpZihiIT09IiIpYS5ZNSgwLFAua3Uo
+YiwwLGIubGVuZ3RoLHRoaXMuYSwhMCksIiIpfWVsc2UgaWYocyE9PTApe3I9Qy54Qi5OaihiLDAscykK
+cT1DLnhCLnluKGIscysxKQpwPXRoaXMuYQphLlk1KDAsUC5rdShyLDAsci5sZW5ndGgscCwhMCksUC5r
+dShxLDAscS5sZW5ndGgscCwhMCkpfXJldHVybiBhfSwKJFM6NDF9ClAuY1MucHJvdG90eXBlPXsKJDI6
+ZnVuY3Rpb24oYSxiKXt0aHJvdyBILmIoUC5ycigiSWxsZWdhbCBJUHY0IGFkZHJlc3MsICIrYSx0aGlz
+LmEsYikpfSwKJFM6MjF9ClAuVkMucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aHJvdyBILmIo
+UC5ycigiSWxsZWdhbCBJUHY2IGFkZHJlc3MsICIrYSx0aGlzLmEsYikpfSwKJDE6ZnVuY3Rpb24oYSl7
+cmV0dXJuIHRoaXMuJDIoYSxudWxsKX0sCiRTOjQ2fQpQLkpULnByb3RvdHlwZT17CiQyOmZ1bmN0aW9u
+KGEsYil7dmFyIHMKaWYoYi1hPjQpdGhpcy5hLiQyKCJhbiBJUHY2IHBhcnQgY2FuIG9ubHkgY29udGFp
+biBhIG1heGltdW0gb2YgNCBoZXggZGlnaXRzIixhKQpzPVAuUUEoQy54Qi5Oaih0aGlzLmIsYSxiKSwx
+NikKaWYoczwwfHxzPjY1NTM1KXRoaXMuYS4kMigiZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJhbmdl
+IG9mIGAweDAuLjB4RkZGRmAiLGEpCnJldHVybiBzfSwKJFM6NTF9ClAuRG4ucHJvdG90eXBlPXsKZ25E
+OmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbz10aGlzCmlmKCFvLnkpe3M9by5hCnI9cy5sZW5ndGghPT0w
+P3MrIjoiOiIiCnE9by5jCnA9cT09bnVsbAppZighcHx8cz09PSJmaWxlIil7cz1yKyIvLyIKcj1vLmIK
+aWYoci5sZW5ndGghPT0wKXM9cytyKyJAIgppZighcClzKz1xCnI9by5kCmlmKHIhPW51bGwpcz1zKyI6
+IitILkVqKHIpfWVsc2Ugcz1yCnMrPW8uZQpyPW8uZgppZihyIT1udWxsKXM9cysiPyIrcgpyPW8ucgpp
+ZihyIT1udWxsKXM9cysiIyIrcgppZihvLnkpdGhyb3cgSC5iKEguR1EoIl90ZXh0IikpCm8ueD1zLmNo
+YXJDb2RlQXQoMCk9PTA/czpzCm8ueT0hMH1yZXR1cm4gby54fSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHMs
+cixxPXRoaXMKaWYoIXEuUSl7cz1xLmUKaWYocy5sZW5ndGghPT0wJiZDLnhCLlcocywwKT09PTQ3KXM9
+Qy54Qi55bihzLDEpCnI9cy5sZW5ndGg9PT0wP0MueEQ6UC5BRihuZXcgSC5sSihILlZNKHMuc3BsaXQo
+Ii8iKSx0LnMpLHQuZE8uYShQLlBIKCkpLHQuZG8pLHQuTikKaWYocS5RKXRocm93IEguYihILkdRKCJw
+YXRoU2VnbWVudHMiKSkKcS5zS3AocikKcS5RPSEwfXJldHVybiBxLnp9LApnaU86ZnVuY3Rpb24oYSl7
+dmFyIHMscj10aGlzCmlmKCFyLmN4KXtzPUouaGYoci5nbkQoKSkKaWYoci5jeCl0aHJvdyBILmIoSC5H
+USgiaGFzaENvZGUiKSkKci5jaD1zCnIuY3g9ITB9cmV0dXJuIHIuY2h9LApnaFk6ZnVuY3Rpb24oKXt2
+YXIgcyxyPXRoaXMKaWYoIXIuZGIpe3M9UC5XWChyLmd0UCgpKQppZihyLmRiKXRocm93IEguYihILkdR
+KCJxdWVyeVBhcmFtZXRlcnMiKSkKci5zTk0obmV3IFAuR2oocyx0LmR3KSkKci5kYj0hMH1yZXR1cm4g
+ci5jeX0sCmdrdTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFyIHM9
+dGhpcy5jCmlmKHM9PW51bGwpcmV0dXJuIiIKaWYoQy54Qi5uKHMsIlsiKSlyZXR1cm4gQy54Qi5Oaihz
+LDEscy5sZW5ndGgtMSkKcmV0dXJuIHN9LApndHA6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5kCnJldHVy
+biBzPT1udWxsP1Aud0sodGhpcy5hKTpzfSwKZ3RQOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy5mCnJldHVy
+biBzPT1udWxsPyIiOnN9LApnS2E6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLnIKcmV0dXJuIHM9PW51bGw/
+IiI6c30sCm5tOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuLG0sbCxrLGo9dGhpcwp0LmM5LmEo
+YikKcz1qLmEKcj1zPT09ImZpbGUiCnE9ai5iCnA9ai5kCm89ai5jCmlmKCEobyE9bnVsbCkpbz1xLmxl
+bmd0aCE9PTB8fHAhPW51bGx8fHI/IiI6bnVsbApuPWouZQppZighciltPW8hPW51bGwmJm4ubGVuZ3Ro
+IT09MAplbHNlIG09ITAKaWYobSYmIUMueEIubihuLCIvIikpbj0iLyIrbgpsPW4Kaz1QLmxlKG51bGws
+MCwwLGIpCnJldHVybiBuZXcgUC5EbihzLHEsbyxwLGwsayxqLnIpfSwKSmg6ZnVuY3Rpb24oYSxiKXt2
+YXIgcyxyLHEscCxvLG4KZm9yKHM9MCxyPTA7Qy54Qi5RaShiLCIuLi8iLHIpOyl7cis9MzsrK3N9cT1D
+LnhCLmNuKGEsIi8iKQp3aGlsZSghMCl7aWYoIShxPjAmJnM+MCkpYnJlYWsKcD1DLnhCLlBrKGEsIi8i
+LHEtMSkKaWYocDwwKWJyZWFrCm89cS1wCm49byE9PTIKaWYoIW58fG89PT0zKWlmKEMueEIuTyhhLHAr
+MSk9PT00NiluPSFufHxDLnhCLk8oYSxwKzIpPT09NDYKZWxzZSBuPSExCmVsc2Ugbj0hMQppZihuKWJy
+ZWFrOy0tcwpxPXB9cmV0dXJuIEMueEIuaTcoYSxxKzEsbnVsbCxDLnhCLnluKGIsci0zKnMpKX0sClpJ
+OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLm1TKFAuaEsoYSkpfSwKbVM6ZnVuY3Rpb24oYSl7dmFyIHMs
+cixxLHAsbyxuLG0sbCxrLGo9dGhpcyxpPW51bGwKaWYoYS5nRmkoKS5sZW5ndGghPT0wKXtzPWEuZ0Zp
+KCkKaWYoYS5nY2ooKSl7cj1hLmdrdSgpCnE9YS5nSmYoYSkKcD1hLmd4QSgpP2EuZ3RwKGEpOml9ZWxz
+ZXtwPWkKcT1wCnI9IiJ9bz1QLnhlKGEuZ0lpKGEpKQpuPWEuZ1FEKCk/YS5ndFAoKTppfWVsc2V7cz1q
+LmEKaWYoYS5nY2ooKSl7cj1hLmdrdSgpCnE9YS5nSmYoYSkKcD1QLndCKGEuZ3hBKCk/YS5ndHAoYSk6
+aSxzKQpvPVAueGUoYS5nSWkoYSkpCm49YS5nUUQoKT9hLmd0UCgpOml9ZWxzZXtyPWouYgpxPWouYwpw
+PWouZAppZihhLmdJaShhKT09PSIiKXtvPWouZQpuPWEuZ1FEKCk/YS5ndFAoKTpqLmZ9ZWxzZXtpZihh
+Lmd0VCgpKW89UC54ZShhLmdJaShhKSkKZWxzZXttPWouZQppZihtLmxlbmd0aD09PTApaWYocT09bnVs
+bClvPXMubGVuZ3RoPT09MD9hLmdJaShhKTpQLnhlKGEuZ0lpKGEpKQplbHNlIG89UC54ZSgiLyIrYS5n
+SWkoYSkpCmVsc2V7bD1qLkpoKG0sYS5nSWkoYSkpCms9cy5sZW5ndGg9PT0wCmlmKCFrfHxxIT1udWxs
+fHxDLnhCLm4obSwiLyIpKW89UC54ZShsKQplbHNlIG89UC53RihsLCFrfHxxIT1udWxsKX19bj1hLmdR
 RCgpP2EuZ3RQKCk6aX19fXJldHVybiBuZXcgUC5EbihzLHIscSxwLG8sbixhLmdaOCgpP2EuZ0thKCk6
 aSl9LApnY2o6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jIT1udWxsfSwKZ3hBOmZ1bmN0aW9uKCl7cmV0
 dXJuIHRoaXMuZCE9bnVsbH0sCmdRRDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmYhPW51bGx9LApnWjg6
 ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5yIT1udWxsfSwKZ3RUOmZ1bmN0aW9uKCl7cmV0dXJuIEMueEIu
-bkModGhpcy5lLCIvIil9LAp0NDpmdW5jdGlvbigpe3ZhciBzLHI9dGhpcyxxPXIuYQppZihxIT09IiIm
-JnEhPT0iZmlsZSIpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20g
-YSAiK3ErIiBVUkkiKSkKaWYoci5ndFAoKSE9PSIiKXRocm93IEguYihQLkw0KHUuaSkpCmlmKHIuZ0th
-KCkhPT0iIil0aHJvdyBILmIoUC5MNCh1LmwpKQpxPSQud1EoKQppZihILm9UKHEpKXE9UC5tbihyKQpl
-bHNle2lmKHIuYyE9bnVsbCYmci5nSmYocikhPT0iIilILnYoUC5MNCh1LmopKQpzPXIuZ0ZqKCkKUC5r
-RShzLCExKQpxPVAudmcoQy54Qi5uQyhyLmUsIi8iKT8iLyI6IiIscywiLyIpCnE9cS5jaGFyQ29kZUF0
-KDApPT0wP3E6cX1yZXR1cm4gcX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ25EKCl9LApETjpm
-dW5jdGlvbihhLGIpe3ZhciBzPXRoaXMKaWYoYj09bnVsbClyZXR1cm4hMQppZihzPT09YilyZXR1cm4h
-MApyZXR1cm4gdC5kRC5iKGIpJiZzLmE9PT1iLmdGaSgpJiZzLmMhPW51bGw9PT1iLmdjaigpJiZzLmI9
-PT1iLmdrdSgpJiZzLmdKZihzKT09PWIuZ0pmKGIpJiZzLmd0cChzKT09PWIuZ3RwKGIpJiZzLmU9PT1i
-LmdJaShiKSYmcy5mIT1udWxsPT09Yi5nUUQoKSYmcy5ndFAoKT09PWIuZ3RQKCkmJnMuciE9bnVsbD09
-PWIuZ1o4KCkmJnMuZ0thKCk9PT1iLmdLYSgpfSwKc0twOmZ1bmN0aW9uKGEpe3RoaXMuej10LmJrLmEo
-YSl9LApzTk06ZnVuY3Rpb24oYSl7dGhpcy5jeT10LmNaLmEoYSl9LAokaWlEOjEsCmdGaTpmdW5jdGlv
-bigpe3JldHVybiB0aGlzLmF9LApnSWk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZX19ClAuUloucHJv
-dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuZVAoQy5aSixILmgoYSksQy54TSwhMSl9LAok
-Uzo1fQpQLk1FLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhpcy5iLHI9dGhpcy5h
-CnMuYSs9ci5hCnIuYT0iJiIKcj1zLmErPUguRWooUC5lUChDLkYzLGEsQy54TSwhMCkpCmlmKGIhPW51
-bGwmJmIubGVuZ3RoIT09MCl7cy5hPXIrIj0iCnMuYSs9SC5FaihQLmVQKEMuRjMsYixDLnhNLCEwKSl9
-fSwKJFM6MjJ9ClAueTUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCkguaChhKQpp
-ZihiPT1udWxsfHx0eXBlb2YgYj09InN0cmluZyIpdGhpcy5hLiQyKGEsSC5rKGIpKQplbHNlIGZvcihz
-PUouSVQodC51LmEoYikpLHI9dGhpcy5hO3MuRigpOylyLiQyKGEsSC5oKHMuZ2woKSkpfSwKJFM6MTJ9
-ClAuUEUucHJvdG90eXBlPXsKZ2xSOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbz10aGlzLG49bnVsbCxt
-PW8uYwppZihtPT1udWxsKXttPW8uYgppZigwPj1tLmxlbmd0aClyZXR1cm4gSC5PSChtLDApCnM9by5h
-Cm09bVswXSsxCnI9Qy54Qi5YVShzLCI/IixtKQpxPXMubGVuZ3RoCmlmKHI+PTApe3A9UC5QSShzLHIr
-MSxxLEMuVkMsITEpCnE9cn1lbHNlIHA9bgptPW8uYz1uZXcgUC5xZSgiZGF0YSIsIiIsbixuLFAuUEko
-cyxtLHEsQy5XZCwhMSkscCxuKX1yZXR1cm4gbX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLmIK
-aWYoMD49ci5sZW5ndGgpcmV0dXJuIEguT0gociwwKQpzPXRoaXMuYQpyZXR1cm4gclswXT09PS0xPyJk
-YXRhOiIrczpzfX0KUC55SS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMuYQpp
-ZihhPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLGEpCnM9c1thXQpDLk5BLmR1KHMsMCw5NixiKQpyZXR1
-cm4gc30sCiRTOjIzfQpQLmM2LnByb3RvdHlwZT17CiQzOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEK
-Zm9yKHM9Yi5sZW5ndGgscj0wO3I8czsrK3Ipe3E9Qy54Qi5XKGIscileOTYKaWYocT49OTYpcmV0dXJu
-IEguT0goYSxxKQphW3FdPWN9fSwKJFM6MTN9ClAucWQucHJvdG90eXBlPXsKJDM6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciBzLHIscQpmb3Iocz1DLnhCLlcoYiwwKSxyPUMueEIuVyhiLDEpO3M8PXI7KytzKXtxPShz
-Xjk2KT4+PjAKaWYocT49OTYpcmV0dXJuIEguT0goYSxxKQphW3FdPWN9fSwKJFM6MTN9ClAuVWYucHJv
-dG90eXBlPXsKZ2NqOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYz4wfSwKZ3hBOmZ1bmN0aW9uKCl7cmV0
-dXJuIHRoaXMuYz4wJiZ0aGlzLmQrMTx0aGlzLmV9LApnUUQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5m
-PHRoaXMucn0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnI8dGhpcy5hLmxlbmd0aH0sCmdOdzpm
-dW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT00JiZDLnhCLm5DKHRoaXMuYSwiZmlsZSIpfSwKZ1daOmZ1
-bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTQmJkMueEIubkModGhpcy5hLCJodHRwIil9LApnUmU6ZnVu
-Y3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NSYmQy54Qi5uQyh0aGlzLmEsImh0dHBzIil9LApndFQ6ZnVu
-Y3Rpb24oKXtyZXR1cm4gQy54Qi5RaSh0aGlzLmEsIi8iLHRoaXMuZSl9LApnRmk6ZnVuY3Rpb24oKXt2
-YXIgcz10aGlzLngKcmV0dXJuIHM9PW51bGw/dGhpcy54PXRoaXMuVTIoKTpzfSwKVTI6ZnVuY3Rpb24o
-KXt2YXIgcz10aGlzLHI9cy5iCmlmKHI8PTApcmV0dXJuIiIKaWYocy5nV1ooKSlyZXR1cm4iaHR0cCIK
-aWYocy5nUmUoKSlyZXR1cm4iaHR0cHMiCmlmKHMuZ053KCkpcmV0dXJuImZpbGUiCmlmKHI9PT03JiZD
-LnhCLm5DKHMuYSwicGFja2FnZSIpKXJldHVybiJwYWNrYWdlIgpyZXR1cm4gQy54Qi5OaihzLmEsMCxy
-KX0sCmdrdTpmdW5jdGlvbigpe3ZhciBzPXRoaXMuYyxyPXRoaXMuYiszCnJldHVybiBzPnI/Qy54Qi5O
-aih0aGlzLmEscixzLTEpOiIifSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYwpyZXR1cm4gcz4w
-P0MueEIuTmoodGhpcy5hLHMsdGhpcy5kKToiIn0sCmd0cDpmdW5jdGlvbihhKXt2YXIgcz10aGlzCmlm
-KHMuZ3hBKCkpcmV0dXJuIFAuUUEoQy54Qi5OaihzLmEscy5kKzEscy5lKSxudWxsKQppZihzLmdXWigp
-KXJldHVybiA4MAppZihzLmdSZSgpKXJldHVybiA0NDMKcmV0dXJuIDB9LApnSWk6ZnVuY3Rpb24oYSl7
-cmV0dXJuIEMueEIuTmoodGhpcy5hLHRoaXMuZSx0aGlzLmYpfSwKZ3RQOmZ1bmN0aW9uKCl7dmFyIHM9
-dGhpcy5mLHI9dGhpcy5yCnJldHVybiBzPHI/Qy54Qi5Oaih0aGlzLmEscysxLHIpOiIifSwKZ0thOmZ1
-bmN0aW9uKCl7dmFyIHM9dGhpcy5yLHI9dGhpcy5hCnJldHVybiBzPHIubGVuZ3RoP0MueEIueW4ocixz
-KzEpOiIifSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHMscixxPXRoaXMuZSxwPXRoaXMuZixvPXRoaXMuYQpp
-ZihDLnhCLlFpKG8sIi8iLHEpKSsrcQppZihxPT09cClyZXR1cm4gQy54RApzPUguVk0oW10sdC5zKQpm
-b3Iocj1xO3I8cDsrK3IpaWYoQy54Qi5PMihvLHIpPT09NDcpe0MuTm0uaShzLEMueEIuTmoobyxxLHIp
-KQpxPXIrMX1DLk5tLmkocyxDLnhCLk5qKG8scSxwKSkKcmV0dXJuIFAuQUYocyx0Lk4pfSwKZ2hZOmZ1
-bmN0aW9uKCl7aWYodGhpcy5mPj10aGlzLnIpcmV0dXJuIEMuQ00KcmV0dXJuIG5ldyBQLkdqKFAuV1go
-dGhpcy5ndFAoKSksdC5kdyl9LAprWDpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmQrMQpyZXR1cm4gcyth
-Lmxlbmd0aD09PXRoaXMuZSYmQy54Qi5RaSh0aGlzLmEsYSxzKX0sCk45OmZ1bmN0aW9uKCl7dmFyIHM9
-dGhpcyxyPXMucixxPXMuYQppZihyPj1xLmxlbmd0aClyZXR1cm4gcwpyZXR1cm4gbmV3IFAuVWYoQy54
-Qi5OaihxLDAscikscy5iLHMuYyxzLmQscy5lLHMuZixyLHMueCl9LApubTpmdW5jdGlvbihhLGIpe3Zh
-ciBzLHIscSxwLG8sbixtLGwsayxqLGk9dGhpcyxoPW51bGwKdC5jOS5hKGIpCnM9aS5nRmkoKQpyPXM9
-PT0iZmlsZSIKcT1pLmMKcD1xPjA/Qy54Qi5OaihpLmEsaS5iKzMscSk6IiIKbz1pLmd4QSgpP2kuZ3Rw
-KGkpOmgKcT1pLmMKaWYocT4wKW49Qy54Qi5OaihpLmEscSxpLmQpCmVsc2Ugbj1wLmxlbmd0aCE9PTB8
-fG8hPW51bGx8fHI/IiI6aApxPWkuYQptPUMueEIuTmoocSxpLmUsaS5mKQppZighcilsPW4hPW51bGwm
-Jm0ubGVuZ3RoIT09MAplbHNlIGw9ITAKaWYobCYmIUMueEIubkMobSwiLyIpKW09Ii8iK20Kaz1QLmxl
-KGgsMCwwLGIpCmw9aS5yCmo9bDxxLmxlbmd0aD9DLnhCLnluKHEsbCsxKTpoCnJldHVybiBuZXcgUC5E
-bihzLHAsbixvLG0sayxqKX0sClpJOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLm1TKFAuaEsoYSkpfSwK
-bVM6ZnVuY3Rpb24oYSl7aWYoYSBpbnN0YW5jZW9mIFAuVWYpcmV0dXJuIHRoaXMudTEodGhpcyxhKQpy
-ZXR1cm4gdGhpcy52cygpLm1TKGEpfSwKdTE6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxs
-LGssaixpLGgsZz1iLmIKaWYoZz4wKXJldHVybiBiCnM9Yi5jCmlmKHM+MCl7cj1hLmIKaWYocjw9MCly
-ZXR1cm4gYgppZihhLmdOdygpKXE9Yi5lIT09Yi5mCmVsc2UgaWYoYS5nV1ooKSlxPSFiLmtYKCI4MCIp
-CmVsc2UgcT0hYS5nUmUoKXx8IWIua1goIjQ0MyIpCmlmKHEpe3A9cisxCnJldHVybiBuZXcgUC5VZihD
-LnhCLk5qKGEuYSwwLHApK0MueEIueW4oYi5hLGcrMSkscixzK3AsYi5kK3AsYi5lK3AsYi5mK3AsYi5y
-K3AsYS54KX1lbHNlIHJldHVybiB0aGlzLnZzKCkubVMoYil9bz1iLmUKZz1iLmYKaWYobz09PWcpe3M9
-Yi5yCmlmKGc8cyl7cj1hLmYKcD1yLWcKcmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAscikrQy54
-Qi55bihiLmEsZyksYS5iLGEuYyxhLmQsYS5lLGcrcCxzK3AsYS54KX1nPWIuYQppZihzPGcubGVuZ3Ro
-KXtyPWEucgpyZXR1cm4gbmV3IFAuVWYoQy54Qi5OaihhLmEsMCxyKStDLnhCLnluKGcscyksYS5iLGEu
-YyxhLmQsYS5lLGEuZixzKyhyLXMpLGEueCl9cmV0dXJuIGEuTjkoKX1zPWIuYQppZihDLnhCLlFpKHMs
-Ii8iLG8pKXtyPWEuZQpwPXItbwpyZXR1cm4gbmV3IFAuVWYoQy54Qi5OaihhLmEsMCxyKStDLnhCLnlu
-KHMsbyksYS5iLGEuYyxhLmQscixnK3AsYi5yK3AsYS54KX1uPWEuZQptPWEuZgppZihuPT09bSYmYS5j
-PjApe2Zvcig7Qy54Qi5RaShzLCIuLi8iLG8pOylvKz0zCnA9bi1vKzEKcmV0dXJuIG5ldyBQLlVmKEMu
-eEIuTmooYS5hLDAsbikrIi8iK0MueEIueW4ocyxvKSxhLmIsYS5jLGEuZCxuLGcrcCxiLnIrcCxhLngp
-fWw9YS5hCmZvcihrPW47Qy54Qi5RaShsLCIuLi8iLGspOylrKz0zCmo9MAp3aGlsZSghMCl7aT1vKzMK
-aWYoIShpPD1nJiZDLnhCLlFpKHMsIi4uLyIsbykpKWJyZWFrOysragpvPWl9Zm9yKGg9IiI7bT5rOyl7
-LS1tCmlmKEMueEIuTzIobCxtKT09PTQ3KXtpZihqPT09MCl7aD0iLyIKYnJlYWt9LS1qCmg9Ii8ifX1p
-ZihtPT09ayYmYS5iPD0wJiYhQy54Qi5RaShsLCIvIixuKSl7by09aiozCmg9IiJ9cD1tLW8raC5sZW5n
-dGgKcmV0dXJuIG5ldyBQLlVmKEMueEIuTmoobCwwLG0pK2grQy54Qi55bihzLG8pLGEuYixhLmMsYS5k
-LG4sZytwLGIucitwLGEueCl9LAp0NDpmdW5jdGlvbigpe3ZhciBzLHIscSxwPXRoaXMKaWYocC5iPj0w
-JiYhcC5nTncoKSl0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBh
-ICIrcC5nRmkoKSsiIFVSSSIpKQpzPXAuZgpyPXAuYQppZihzPHIubGVuZ3RoKXtpZihzPHAucil0aHJv
-dyBILmIoUC5MNCh1LmkpKQp0aHJvdyBILmIoUC5MNCh1LmwpKX1xPSQud1EoKQppZihILm9UKHEpKXM9
-UC5tbihwKQplbHNle2lmKHAuYzxwLmQpSC52KFAuTDQodS5qKSkKcz1DLnhCLk5qKHIscC5lLHMpfXJl
-dHVybiBzfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMueQpyZXR1cm4gcz09bnVsbD90aGlzLnk9
-Qy54Qi5naU8odGhpcy5hKTpzfSwKRE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCmlm
-KHRoaXM9PT1iKXJldHVybiEwCnJldHVybiB0LmRELmIoYikmJnRoaXMuYT09PWIudygwKX0sCnZzOmZ1
-bmN0aW9uKCl7dmFyIHM9dGhpcyxyPW51bGwscT1zLmdGaSgpLHA9cy5na3UoKSxvPXMuYz4wP3MuZ0pm
-KHMpOnIsbj1zLmd4QSgpP3MuZ3RwKHMpOnIsbT1zLmEsbD1zLmYsaz1DLnhCLk5qKG0scy5lLGwpLGo9
-cy5yCmw9bDxqP3MuZ3RQKCk6cgpyZXR1cm4gbmV3IFAuRG4ocSxwLG8sbixrLGwsajxtLmxlbmd0aD9z
-LmdLYSgpOnIpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKJGlpRDoxfQpQLnFlLnByb3Rv
-dHlwZT17fQpXLnFFLnByb3RvdHlwZT17fQpXLkdoLnByb3RvdHlwZT17CnNMVTpmdW5jdGlvbihhLGIp
-e2EuaHJlZj1ifSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGlHaDoxfQpXLmZZLnBy
-b3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX19ClcubkIucHJvdG90eXBlPXsk
-aW5COjF9ClcuQXoucHJvdG90eXBlPXskaUF6OjF9ClcuUVAucHJvdG90eXBlPXskaVFQOjF9Clcubngu
-cHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5vSi5wcm90b3R5cGU9
-ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmlkLnByb3RvdHlwZT17fQpXLlFGLnBy
-b3RvdHlwZT17fQpXLk5oLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX19
-ClcuYWUucHJvdG90eXBlPXsKRGM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYS5jcmVhdGVIVE1MRG9jdW1l
-bnQoYil9fQpXLklCLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHMscj1hLmxlZnQKci50b1N0
-cmluZwpyPSJSZWN0YW5nbGUgKCIrSC5FaihyKSsiLCAiCnM9YS50b3AKcy50b1N0cmluZwpzPXIrSC5F
-aihzKSsiKSAiCnI9YS53aWR0aApyLnRvU3RyaW5nCnI9cytILkVqKHIpKyIgeCAiCnM9YS5oZWlnaHQK
-cy50b1N0cmluZwpyZXR1cm4gcitILkVqKHMpfSwKRE46ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlmKGI9
-PW51bGwpcmV0dXJuITEKaWYodC5xLmIoYikpe3M9YS5sZWZ0CnMudG9TdHJpbmcKcj1iLmxlZnQKci50
-b1N0cmluZwppZihzPT09cil7cz1hLnRvcApzLnRvU3RyaW5nCnI9Yi50b3AKci50b1N0cmluZwppZihz
-PT09cil7cz1hLndpZHRoCnMudG9TdHJpbmcKcj1iLndpZHRoCnIudG9TdHJpbmcKaWYocz09PXIpe3M9
-YS5oZWlnaHQKcy50b1N0cmluZwpyPWIuaGVpZ2h0CnIudG9TdHJpbmcKcj1zPT09cgpzPXJ9ZWxzZSBz
-PSExfWVsc2Ugcz0hMX1lbHNlIHM9ITF9ZWxzZSBzPSExCnJldHVybiBzfSwKZ2lPOmZ1bmN0aW9uKGEp
-e3ZhciBzLHIscSxwPWEubGVmdApwLnRvU3RyaW5nCnA9Qy5DRC5naU8ocCkKcz1hLnRvcApzLnRvU3Ry
-aW5nCnM9Qy5DRC5naU8ocykKcj1hLndpZHRoCnIudG9TdHJpbmcKcj1DLkNELmdpTyhyKQpxPWEuaGVp
-Z2h0CnEudG9TdHJpbmcKcmV0dXJuIFcuckUocCxzLHIsQy5DRC5naU8ocSkpfSwKJGl0bjoxfQpXLm43
-LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19Clcud3oucHJvdG90eXBl
-PXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7dmFy
-IHMKSC51UChiKQpzPXRoaXMuYQppZihiPDB8fGI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsYikKcmV0
-dXJuIHRoaXMuJHRpLmMuYShzW2JdKX0sClk1OmZ1bmN0aW9uKGEsYixjKXt0aGlzLiR0aS5jLmEoYykK
-dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgbGlzdCIpKX19ClcuY3YucHJvdG90eXBlPXsKZ1Fn
-OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5pNyhhKX0sCmduOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcg
-Vy5JNChhKX0sCnNuOmZ1bmN0aW9uKGEsYil7dmFyIHMKdC5RLmEoYikKcz10aGlzLmduKGEpCnMuVjEo
-MCkKcy5GVigwLGIpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhbE5hbWV9LApGRjpmdW5jdGlv
-bihhKXt2YXIgcz0hIWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZAppZihzKWEuc2Nyb2xsSW50b1ZpZXdJ
-Zk5lZWRlZCgpCmVsc2UgYS5zY3JvbGxJbnRvVmlldygpfSwKbno6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2
-YXIgcyxyPXRoaXMucjYoYSxjLGQsZSkKc3dpdGNoKGIudG9Mb3dlckNhc2UoKSl7Y2FzZSJiZWZvcmVi
-ZWdpbiI6cz1hLnBhcmVudE5vZGUKcy50b1N0cmluZwpKLkVoKHMscixhKQpicmVhawpjYXNlImFmdGVy
-YmVnaW4iOnM9YS5jaGlsZE5vZGVzCnRoaXMubUsoYSxyLHMubGVuZ3RoPjA/c1swXTpudWxsKQpicmVh
-awpjYXNlImJlZm9yZWVuZCI6YS5hcHBlbmRDaGlsZChyKQpicmVhawpjYXNlImFmdGVyZW5kIjpzPWEu
-cGFyZW50Tm9kZQpzLnRvU3RyaW5nCkouRWgocyxyLGEubmV4dFNpYmxpbmcpCmJyZWFrCmRlZmF1bHQ6
-SC52KFAueFkoIkludmFsaWQgcG9zaXRpb24gIitiKSl9fSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
-IHMscixxLHAKaWYoYz09bnVsbCl7aWYoZD09bnVsbCl7cz0kLmx0CmlmKHM9PW51bGwpe3M9SC5WTShb
-XSx0LnYpCnI9bmV3IFcudkQocykKQy5ObS5pKHMsVy5UdyhudWxsKSkKQy5ObS5pKHMsVy5CbCgpKQok
-Lmx0PXIKZD1yfWVsc2UgZD1zfXM9JC5FVQppZihzPT1udWxsKXtzPW5ldyBXLktvKGQpCiQuRVU9cwpj
-PXN9ZWxzZXtzLmE9ZApjPXN9fWVsc2UgaWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgidmFsaWRhdG9y
-IGNhbiBvbmx5IGJlIHBhc3NlZCBpZiB0cmVlU2FuaXRpemVyIGlzIG51bGwiKSkKaWYoJC54bz09bnVs
-bCl7cz1kb2N1bWVudApyPXMuaW1wbGVtZW50YXRpb24Kci50b1N0cmluZwpyPUMubUguRGMociwiIikK
-JC54bz1yCiQuQk89ci5jcmVhdGVSYW5nZSgpCnI9JC54by5jcmVhdGVFbGVtZW50KCJiYXNlIikKdC5j
-Ui5hKHIpCnM9cy5iYXNlVVJJCnMudG9TdHJpbmcKci5ocmVmPXMKJC54by5oZWFkLmFwcGVuZENoaWxk
-KHIpfXM9JC54bwppZihzLmJvZHk9PW51bGwpe3I9cy5jcmVhdGVFbGVtZW50KCJib2R5IikKQy5CWi5z
-WEcocyx0LnAuYShyKSl9cz0kLnhvCmlmKHQucC5iKGEpKXtzPXMuYm9keQpzLnRvU3RyaW5nCnE9c31l
-bHNle3MudG9TdHJpbmcKcT1zLmNyZWF0ZUVsZW1lbnQoYS50YWdOYW1lKQokLnhvLmJvZHkuYXBwZW5k
-Q2hpbGQocSl9aWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3Rv
-dHlwZSYmIUMuTm0udGcoQy5TcSxhLnRhZ05hbWUpKXskLkJPLnNlbGVjdE5vZGVDb250ZW50cyhxKQpz
-PSQuQk8Kcy50b1N0cmluZwpwPXMuY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KGI9PW51bGw/Im51bGwi
-OmIpfWVsc2V7Si53ZihxLGIpCnA9JC54by5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKZm9yKDtzPXEu
-Zmlyc3RDaGlsZCxzIT1udWxsOylwLmFwcGVuZENoaWxkKHMpfWlmKHEhPT0kLnhvLmJvZHkpSi5MdChx
-KQpjLlBuKHApCmRvY3VtZW50LmFkb3B0Tm9kZShwKQpyZXR1cm4gcH0sCkFIOmZ1bmN0aW9uKGEsYixj
-KXtyZXR1cm4gdGhpcy5yNihhLGIsYyxudWxsKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxi
-KX0sCnBrOmZ1bmN0aW9uKGEsYixjKXt0aGlzLnNhNChhLG51bGwpCmEuYXBwZW5kQ2hpbGQodGhpcy5y
-NihhLGIsbnVsbCxjKSl9LApZQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEsYixudWxsKX0s
-CnNSTjpmdW5jdGlvbihhLGIpe2EuaW5uZXJIVE1MPWJ9LApnbnM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
-dGFnTmFtZX0sCmdWbDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuZXUoYSwiY2xpY2siLCExLHQuayl9
-LAokaWN2OjF9ClcuQ3YucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHQuaC5iKHQuQS5h
-KGEpKX0sCiRTOjI1fQpXLmVhLnByb3RvdHlwZT17JGllYToxfQpXLkQwLnByb3RvdHlwZT17Ck9uOmZ1
-bmN0aW9uKGEsYixjLGQpe3QuYncuYShjKQppZihjIT1udWxsKXRoaXMudihhLGIsYyxkKX0sCkI6ZnVu
-Y3Rpb24oYSxiLGMpe3JldHVybiB0aGlzLk9uKGEsYixjLG51bGwpfSwKdjpmdW5jdGlvbihhLGIsYyxk
-KXtyZXR1cm4gYS5hZGRFdmVudExpc3RlbmVyKGIsSC50Uih0LmJ3LmEoYyksMSksZCl9LAokaUQwOjF9
-ClcuaEgucHJvdG90eXBlPXskaWhIOjF9ClcuaDQucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0
-dXJuIGEubGVuZ3RofX0KVy5ici5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5n
-dGh9fQpXLlZiLnByb3RvdHlwZT17CnNYRzpmdW5jdGlvbihhLGIpe2EuYm9keT1ifX0KVy5mSi5wcm90
-b3R5cGU9ewplbzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYS5vcGVuKGIsYywhMCl9LAokaWZKOjF9
-Clcud2EucHJvdG90eXBlPXt9ClcuU2cucHJvdG90eXBlPXskaVNnOjF9ClcudzcucHJvdG90eXBlPXsK
-Z0RyOmZ1bmN0aW9uKGEpe2lmKCJvcmlnaW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILkVq
-KGEucHJvdG9jb2wpKyIvLyIrSC5FaihhLmhvc3QpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5n
-KGEpfSwKJGl3NzoxfQpXLkFqLnByb3RvdHlwZT17JGlBajoxfQpXLmU3LnByb3RvdHlwZT17CmdyODpm
-dW5jdGlvbihhKXt2YXIgcz10aGlzLmEscj1zLmNoaWxkTm9kZXMubGVuZ3RoCmlmKHI9PT0wKXRocm93
-IEguYihQLlBWKCJObyBlbGVtZW50cyIpKQppZihyPjEpdGhyb3cgSC5iKFAuUFYoIk1vcmUgdGhhbiBv
-bmUgZWxlbWVudCIpKQpzPXMuZmlyc3RDaGlsZApzLnRvU3RyaW5nCnJldHVybiBzfSwKRlY6ZnVuY3Rp
-b24oYSxiKXt2YXIgcyxyLHEscCxvCnQuZWguYShiKQppZihiIGluc3RhbmNlb2YgVy5lNyl7cz1iLmEK
-cj10aGlzLmEKaWYocyE9PXIpZm9yKHE9cy5jaGlsZE5vZGVzLmxlbmd0aCxwPTA7cDxxOysrcCl7bz1z
-LmZpcnN0Q2hpbGQKby50b1N0cmluZwpyLmFwcGVuZENoaWxkKG8pfXJldHVybn1mb3Iocz1iLmdtKGIp
-LHI9dGhpcy5hO3MuRigpOylyLmFwcGVuZENoaWxkKHMuZ2woKSl9LApZNTpmdW5jdGlvbihhLGIsYyl7
-dmFyIHMscgp0LkEuYShjKQpzPXRoaXMuYQpyPXMuY2hpbGROb2RlcwppZihiPDB8fGI+PXIubGVuZ3Ro
-KXJldHVybiBILk9IKHIsYikKcy5yZXBsYWNlQ2hpbGQoYyxyW2JdKX0sCmdtOmZ1bmN0aW9uKGEpe3Zh
-ciBzPXRoaXMuYS5jaGlsZE5vZGVzCnJldHVybiBuZXcgVy5XOShzLHMubGVuZ3RoLEgueihzKS5DKCJX
-OTxHbS5FPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2hpbGROb2Rlcy5sZW5ndGh9
-LApxOmZ1bmN0aW9uKGEsYil7dmFyIHMKSC51UChiKQpzPXRoaXMuYS5jaGlsZE5vZGVzCmlmKGI8MHx8
-Yj49cy5sZW5ndGgpcmV0dXJuIEguT0gocyxiKQpyZXR1cm4gc1tiXX19ClcudUgucHJvdG90eXBlPXsK
-d2c6ZnVuY3Rpb24oYSl7dmFyIHM9YS5wYXJlbnROb2RlCmlmKHMhPW51bGwpcy5yZW1vdmVDaGlsZChh
-KX0sCkQ0OmZ1bmN0aW9uKGEpe3ZhciBzCmZvcig7cz1hLmZpcnN0Q2hpbGQscyE9bnVsbDspYS5yZW1v
-dmVDaGlsZChzKX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHM9YS5ub2RlVmFsdWUKcmV0dXJuIHM9PW51bGw/
-dGhpcy5VKGEpOnN9LApzYTQ6ZnVuY3Rpb24oYSxiKXthLnRleHRDb250ZW50PWJ9LAptSzpmdW5jdGlv
-bihhLGIsYyl7cmV0dXJuIGEuaW5zZXJ0QmVmb3JlKGIsYyl9LAokaXVIOjF9ClcuQkgucHJvdG90eXBl
-PXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikK
-aWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihiLGEsbnVsbCxudWxsLG51bGwp
-KQpyZXR1cm4gYVtiXX0sClk1OmZ1bmN0aW9uKGEsYixjKXt0LkEuYShjKQp0aHJvdyBILmIoUC5MNCgi
-Q2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sCmd0SDpmdW5jdGlvbihh
-KXtpZihhLmxlbmd0aD4wKXJldHVybiBhWzBdCnRocm93IEguYihQLlBWKCJObyBlbGVtZW50cyIpKX0s
-CkU6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBILk9IKGEsYikKcmV0dXJu
-IGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAokaXpNOjF9ClcuU04ucHJvdG90eXBlPXt9Clcu
-ZXcucHJvdG90eXBlPXskaWV3OjF9ClcubHAucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJu
-IGEubGVuZ3RofX0KVy5UYi5wcm90b3R5cGU9ewpyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyCmlm
-KCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJu
-IHRoaXMuRFcoYSxiLGMsZCkKcz1XLlU5KCI8dGFibGU+IitILkVqKGIpKyI8L3RhYmxlPiIsYyxkKQpy
-PWRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpyLnRvU3RyaW5nCnMudG9TdHJpbmcKbmV3
-IFcuZTcocikuRlYoMCxuZXcgVy5lNyhzKSkKcmV0dXJuIHJ9fQpXLkl2LnByb3RvdHlwZT17CnI2OmZ1
-bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGlu
-IHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKcz1kb2N1bWVudApy
-PXMuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnM9Qy5JZS5yNihzLmNyZWF0ZUVsZW1lbnQoInRhYmxl
-IiksYixjLGQpCnMudG9TdHJpbmcKcz1uZXcgVy5lNyhzKQpxPXMuZ3I4KHMpCnEudG9TdHJpbmcKcz1u
-ZXcgVy5lNyhxKQpwPXMuZ3I4KHMpCnIudG9TdHJpbmcKcC50b1N0cmluZwpuZXcgVy5lNyhyKS5GVigw
-LG5ldyBXLmU3KHApKQpyZXR1cm4gcn19ClcuV1AucHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxiLGMs
-ZCl7dmFyIHMscixxCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5w
-cm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKcz1kb2N1bWVudApyPXMuY3JlYXRlRG9jdW1l
-bnRGcmFnbWVudCgpCnM9Qy5JZS5yNihzLmNyZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnMudG9T
-dHJpbmcKcz1uZXcgVy5lNyhzKQpxPXMuZ3I4KHMpCnIudG9TdHJpbmcKcS50b1N0cmluZwpuZXcgVy5l
-NyhyKS5GVigwLG5ldyBXLmU3KHEpKQpyZXR1cm4gcn19ClcueVkucHJvdG90eXBlPXsKcGs6ZnVuY3Rp
-b24oYSxiLGMpe3ZhciBzLHIKdGhpcy5zYTQoYSxudWxsKQpzPWEuY29udGVudApzLnRvU3RyaW5nCkou
-YlQocykKcj10aGlzLnI2KGEsYixudWxsLGMpCmEuY29udGVudC5hcHBlbmRDaGlsZChyKX0sCllDOmZ1
-bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucGsoYSxiLG51bGwpfSwKJGl5WToxfQpXLnc2LnByb3RvdHlw
-ZT17fQpXLks1LnByb3RvdHlwZT17ClBvOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1XLlAxKGEub3Blbihi
-LGMpKQpyZXR1cm4gc30sCmdtVzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhdGlvbn0sCnVzOmZ1bmN0
-aW9uKGEsYil7cmV0dXJuIGEuY29uZmlybShiKX0sCiRpSzU6MSwKJGl2NjoxfQpXLkNtLnByb3RvdHlw
-ZT17JGlDbToxfQpXLkNRLnByb3RvdHlwZT17JGlDUToxfQpXLnc0LnByb3RvdHlwZT17Cnc6ZnVuY3Rp
-b24oYSl7dmFyIHMscj1hLmxlZnQKci50b1N0cmluZwpyPSJSZWN0YW5nbGUgKCIrSC5FaihyKSsiLCAi
-CnM9YS50b3AKcy50b1N0cmluZwpzPXIrSC5FaihzKSsiKSAiCnI9YS53aWR0aApyLnRvU3RyaW5nCnI9
-cytILkVqKHIpKyIgeCAiCnM9YS5oZWlnaHQKcy50b1N0cmluZwpyZXR1cm4gcitILkVqKHMpfSwKRE46
-ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlmKGI9PW51bGwpcmV0dXJuITEKaWYodC5xLmIoYikpe3M9YS5s
-ZWZ0CnMudG9TdHJpbmcKcj1iLmxlZnQKci50b1N0cmluZwppZihzPT09cil7cz1hLnRvcApzLnRvU3Ry
-aW5nCnI9Yi50b3AKci50b1N0cmluZwppZihzPT09cil7cz1hLndpZHRoCnMudG9TdHJpbmcKcj1iLndp
-ZHRoCnIudG9TdHJpbmcKaWYocz09PXIpe3M9YS5oZWlnaHQKcy50b1N0cmluZwpyPWIuaGVpZ2h0CnIu
-dG9TdHJpbmcKcj1zPT09cgpzPXJ9ZWxzZSBzPSExfWVsc2Ugcz0hMX1lbHNlIHM9ITF9ZWxzZSBzPSEx
-CnJldHVybiBzfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPWEubGVmdApwLnRvU3RyaW5nCnA9
-Qy5DRC5naU8ocCkKcz1hLnRvcApzLnRvU3RyaW5nCnM9Qy5DRC5naU8ocykKcj1hLndpZHRoCnIudG9T
-dHJpbmcKcj1DLkNELmdpTyhyKQpxPWEuaGVpZ2h0CnEudG9TdHJpbmcKcmV0dXJuIFcuckUocCxzLHIs
-Qy5DRC5naU8ocSkpfX0KVy5yaC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5n
-dGh9LApxOmZ1bmN0aW9uKGEsYil7SC51UChiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93
-IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTU6ZnVuY3Rpb24oYSxi
-LGMpe3QuQS5hKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRh
-YmxlIExpc3QuIikpfSwKRTpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEgu
-T0goYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5jZi5w
-cm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbwp0LmVBLmEoYikKZm9yKHM9dGhp
-cy5ndmMoKSxyPXMubGVuZ3RoLHE9dGhpcy5hLHA9MDtwPHMubGVuZ3RoO3MubGVuZ3RoPT09cnx8KDAs
-SC5saykocyksKytwKXtvPXNbcF0KYi4kMihvLHEuZ2V0QXR0cmlidXRlKG8pKX19LApndmM6ZnVuY3Rp
-b24oKXt2YXIgcyxyLHEscCxvLG4sbT10aGlzLmEuYXR0cmlidXRlcwptLnRvU3RyaW5nCnM9SC5WTShb
-XSx0LnMpCmZvcihyPW0ubGVuZ3RoLHE9dC5oOSxwPTA7cDxyOysrcCl7aWYocD49bS5sZW5ndGgpcmV0
-dXJuIEguT0gobSxwKQpvPXEuYShtW3BdKQppZihvLm5hbWVzcGFjZVVSST09bnVsbCl7bj1vLm5hbWUK
-bi50b1N0cmluZwpDLk5tLmkocyxuKX19cmV0dXJuIHN9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
-aXMuZ3ZjKCkubGVuZ3RoPT09MH19ClcuaTcucHJvdG90eXBlPXsKeDQ6ZnVuY3Rpb24oYSl7dmFyIHM9
-SC5vVCh0aGlzLmEuaGFzQXR0cmlidXRlKGEpKQpyZXR1cm4gc30sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1
-cm4gdGhpcy5hLmdldEF0dHJpYnV0ZShILmgoYikpfSwKWTU6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5z
-ZXRBdHRyaWJ1dGUoYixjKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmd2YygpLmxlbmd0aH19
-ClcuU3kucHJvdG90eXBlPXsKeDQ6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vVCh0aGlzLmEuYS5oYXNBdHRy
-aWJ1dGUoImRhdGEtIit0aGlzLlAoYSkpKQpyZXR1cm4gc30sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
-dGhpcy5hLmEuZ2V0QXR0cmlidXRlKCJkYXRhLSIrdGhpcy5QKEguaChiKSkpfSwKWTU6ZnVuY3Rpb24o
-YSxiLGMpe3RoaXMuYS5hLnNldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuUChiKSxjKX0sCks6ZnVuY3Rp
-b24oYSxiKXt0aGlzLmEuSygwLG5ldyBXLktTKHRoaXMsdC5lQS5hKGIpKSl9LApndmM6ZnVuY3Rpb24o
-KXt2YXIgcz1ILlZNKFtdLHQucykKdGhpcy5hLksoMCxuZXcgVy5BMyh0aGlzLHMpKQpyZXR1cm4gc30s
-CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmd2YygpLmxlbmd0aH0sCmdsMDpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5ndmMoKS5sZW5ndGg9PT0wfSwKeHE6ZnVuY3Rpb24oYSl7dmFyIHMscixxPUguVk0o
-YS5zcGxpdCgiLSIpLHQucykKZm9yKHM9MTtzPHEubGVuZ3RoOysrcyl7cj1xW3NdCmlmKHIubGVuZ3Ro
-PjApQy5ObS5ZNShxLHMsclswXS50b1VwcGVyQ2FzZSgpK0ouS1YociwxKSl9cmV0dXJuIEMuTm0uayhx
-LCIiKX0sClA6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbwpmb3Iocz1hLmxlbmd0aCxyPTAscT0iIjty
-PHM7KytyKXtwPWFbcl0Kbz1wLnRvTG93ZXJDYXNlKCkKcT0ocCE9PW8mJnI+MD9xKyItIjpxKStvfXJl
-dHVybiBxLmNoYXJDb2RlQXQoMCk9PTA/cTpxfX0KVy5LUy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihh
-LGIpe2lmKEouclkoYSkubkMoYSwiZGF0YS0iKSl0aGlzLmIuJDIodGhpcy5hLnhxKEMueEIueW4oYSw1
-KSksYil9LAokUzoxNH0KVy5BMy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe2lmKEouclkoYSku
-bkMoYSwiZGF0YS0iKSlDLk5tLmkodGhpcy5iLHRoaXMuYS54cShDLnhCLnluKGEsNSkpKX0sCiRTOjE0
-fQpXLkk0LnByb3RvdHlwZT17CkQ6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvPVAuTHModC5OKQpmb3Io
-cz10aGlzLmEuY2xhc3NOYW1lLnNwbGl0KCIgIikscj1zLmxlbmd0aCxxPTA7cTxyOysrcSl7cD1KLlQw
-KHNbcV0pCmlmKHAubGVuZ3RoIT09MClvLmkoMCxwKX1yZXR1cm4gb30sClg6ZnVuY3Rpb24oYSl7dGhp
-cy5hLmNsYXNzTmFtZT10LkMuYShhKS5rKDAsIiAiKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
-LmEuY2xhc3NMaXN0Lmxlbmd0aH0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNsYXNzTGlz
-dC5sZW5ndGg9PT0wfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2xhc3NMaXN0Lmxlbmd0
-aCE9PTB9LApWMTpmdW5jdGlvbihhKXt0aGlzLmEuY2xhc3NOYW1lPSIifSwKdGc6ZnVuY3Rpb24oYSxi
-KXt2YXIgcz10aGlzLmEuY2xhc3NMaXN0LmNvbnRhaW5zKGIpCnJldHVybiBzfSwKaTpmdW5jdGlvbihh
-LGIpe3ZhciBzLHIKSC5oKGIpCnM9dGhpcy5hLmNsYXNzTGlzdApyPXMuY29udGFpbnMoYikKcy5hZGQo
-YikKcmV0dXJuIXJ9LApMOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxCmlmKHR5cGVvZiBiPT0ic3RyaW5n
-Iil7cz10aGlzLmEuY2xhc3NMaXN0CnI9cy5jb250YWlucyhiKQpzLnJlbW92ZShiKQpxPXJ9ZWxzZSBx
-PSExCnJldHVybiBxfSwKRlY6ZnVuY3Rpb24oYSxiKXtXLlROKHRoaXMuYSx0LlEuYShiKSl9fQpXLkZr
-LnByb3RvdHlwZT17fQpXLlJPLnByb3RvdHlwZT17fQpXLmV1LnByb3RvdHlwZT17fQpXLnhDLnByb3Rv
-dHlwZT17fQpXLnZOLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuJDEodC5C
-LmEoYSkpfSwKJFM6Mjd9ClcuSlEucHJvdG90eXBlPXsKQ1k6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoJC5v
-ci5hPT09MCl7Zm9yKHM9MDtzPDI2MjsrK3MpJC5vci5ZNSgwLEMuY21bc10sVy5wUygpKQpmb3Iocz0w
-O3M8MTI7KytzKSQub3IuWTUoMCxDLkJJW3NdLFcuVjQoKSl9fSwKaTA6ZnVuY3Rpb24oYSl7cmV0dXJu
-ICQuQU4oKS50ZygwLFcuclMoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPSQub3IucSgwLEgu
-RWooVy5yUyhhKSkrIjo6IitiKQppZihzPT1udWxsKXM9JC5vci5xKDAsIio6OiIrYikKaWYocz09bnVs
-bClyZXR1cm4hMQpyZXR1cm4gSC55OChzLiQ0KGEsYixjLHRoaXMpKX0sCiRpa0Y6MX0KVy5HbS5wcm90
-b3R5cGU9ewpnbTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuVzkoYSx0aGlzLmdBKGEpLEgueihhKS5D
-KCJXOTxHbS5FPiIpKX19ClcudkQucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIEMuTm0u
-VnIodGhpcy5hLG5ldyBXLlV2KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gQy5ObS5Wcih0
-aGlzLmEsbmV3IFcuRWcoYSxiLGMpKX0sCiRpa0Y6MX0KVy5Vdi5wcm90b3R5cGU9ewokMTpmdW5jdGlv
-bihhKXtyZXR1cm4gdC5mNi5hKGEpLmkwKHRoaXMuYSl9LAokUzoxNX0KVy5FZy5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4gdC5mNi5hKGEpLkViKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRT
-OjE1fQpXLm02LnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscQp0aGlzLmEu
-RlYoMCxjKQpzPWIuZXYoMCxuZXcgVy5FbygpKQpyPWIuZXYoMCxuZXcgVy5XaygpKQp0aGlzLmIuRlYo
-MCxzKQpxPXRoaXMuYwpxLkZWKDAsQy54RCkKcS5GVigwLHIpfSwKaTA6ZnVuY3Rpb24oYSl7cmV0dXJu
-IHRoaXMuYS50ZygwLFcuclMoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPXRoaXMscj1XLnJT
-KGEpLHE9cy5jCmlmKHEudGcoMCxILkVqKHIpKyI6OiIrYikpcmV0dXJuIHMuZC5EdChjKQplbHNlIGlm
-KHEudGcoMCwiKjo6IitiKSlyZXR1cm4gcy5kLkR0KGMpCmVsc2V7cT1zLmIKaWYocS50ZygwLEguRWoo
-cikrIjo6IitiKSlyZXR1cm4hMAplbHNlIGlmKHEudGcoMCwiKjo6IitiKSlyZXR1cm4hMAplbHNlIGlm
-KHEudGcoMCxILkVqKHIpKyI6OioiKSlyZXR1cm4hMAplbHNlIGlmKHEudGcoMCwiKjo6KiIpKXJldHVy
-biEwfXJldHVybiExfSwKJGlrRjoxfQpXLkVvLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVy
-biFDLk5tLnRnKEMuQkksSC5oKGEpKX0sCiRTOjZ9ClcuV2sucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24o
-YSl7cmV0dXJuIEMuTm0udGcoQy5CSSxILmgoYSkpfSwKJFM6Nn0KVy5jdC5wcm90b3R5cGU9ewpFYjpm
-dW5jdGlvbihhLGIsYyl7aWYodGhpcy5qRihhLGIsYykpcmV0dXJuITAKaWYoYj09PSJ0ZW1wbGF0ZSIm
-JmM9PT0iIilyZXR1cm4hMAppZihhLmdldEF0dHJpYnV0ZSgidGVtcGxhdGUiKT09PSIiKXJldHVybiB0
-aGlzLmUudGcoMCxiKQpyZXR1cm4hMX19ClcuSUEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0
-dXJuIlRFTVBMQVRFOjoiK0guRWooSC5oKGEpKX0sCiRTOjV9ClcuT3cucHJvdG90eXBlPXsKaTA6ZnVu
-Y3Rpb24oYSl7dmFyIHMKaWYodC5ldy5iKGEpKXJldHVybiExCnM9dC5nNy5iKGEpCmlmKHMmJlcuclMo
-YSk9PT0iZm9yZWlnbk9iamVjdCIpcmV0dXJuITEKaWYocylyZXR1cm4hMApyZXR1cm4hMX0sCkViOmZ1
-bmN0aW9uKGEsYixjKXtpZihiPT09ImlzInx8Qy54Qi5uQyhiLCJvbiIpKXJldHVybiExCnJldHVybiB0
-aGlzLmkwKGEpfSwKJGlrRjoxfQpXLlc5LnByb3RvdHlwZT17CkY6ZnVuY3Rpb24oKXt2YXIgcz10aGlz
-LHI9cy5jKzEscT1zLmIKaWYocjxxKXtzLnNwKEoueDkocy5hLHIpKQpzLmM9cgpyZXR1cm4hMH1zLnNw
-KG51bGwpCnMuYz1xCnJldHVybiExfSwKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKc3A6ZnVu
-Y3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLkMoIjE/IikuYShhKX0sCiRpQW46MX0KVy5kVy5wcm90b3R5
-cGU9eyRpRDA6MSwkaXY2OjF9ClcubWsucHJvdG90eXBlPXskaXkwOjF9ClcuS28ucHJvdG90eXBlPXsK
-UG46ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcyxyPW5ldyBXLmZtKHMpCnMuYj0hMQpyLiQyKGEsbnVsbCkK
-Zm9yKDtzLmI7KXtzLmI9ITEKci4kMihhLG51bGwpfX0sCkVQOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhp
-cy5iPSEwCmlmKGIhPW51bGw/YiE9PWEucGFyZW50Tm9kZTpzKUouTHQoYSkKZWxzZSBiLnJlbW92ZUNo
-aWxkKGEpfSwKSTQ6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG49ITAsbT1udWxsLGw9bnVsbAp0
-cnl7bT1KLmlnKGEpCmw9bS5hLmdldEF0dHJpYnV0ZSgiaXMiKQp0LmguYShhKQpzPWZ1bmN0aW9uKGMp
-e2lmKCEoYy5hdHRyaWJ1dGVzIGluc3RhbmNlb2YgTmFtZWROb2RlTWFwKSlyZXR1cm4gdHJ1ZQppZihj
-LmlkPT0nbGFzdENoaWxkJ3x8Yy5uYW1lPT0nbGFzdENoaWxkJ3x8Yy5pZD09J3ByZXZpb3VzU2libGlu
-Zyd8fGMubmFtZT09J3ByZXZpb3VzU2libGluZyd8fGMuaWQ9PSdjaGlsZHJlbid8fGMubmFtZT09J2No
-aWxkcmVuJylyZXR1cm4gdHJ1ZQp2YXIgaz1jLmNoaWxkTm9kZXMKaWYoYy5sYXN0Q2hpbGQmJmMubGFz
-dENoaWxkIT09a1trLmxlbmd0aC0xXSlyZXR1cm4gdHJ1ZQppZihjLmNoaWxkcmVuKWlmKCEoYy5jaGls
-ZHJlbiBpbnN0YW5jZW9mIEhUTUxDb2xsZWN0aW9ufHxjLmNoaWxkcmVuIGluc3RhbmNlb2YgTm9kZUxp
-c3QpKXJldHVybiB0cnVlCnZhciBqPTAKaWYoYy5jaGlsZHJlbilqPWMuY2hpbGRyZW4ubGVuZ3RoCmZv
-cih2YXIgaT0wO2k8ajtpKyspe3ZhciBoPWMuY2hpbGRyZW5baV0KaWYoaC5pZD09J2F0dHJpYnV0ZXMn
-fHxoLm5hbWU9PSdhdHRyaWJ1dGVzJ3x8aC5pZD09J2xhc3RDaGlsZCd8fGgubmFtZT09J2xhc3RDaGls
-ZCd8fGguaWQ9PSdwcmV2aW91c1NpYmxpbmcnfHxoLm5hbWU9PSdwcmV2aW91c1NpYmxpbmcnfHxoLmlk
-PT0nY2hpbGRyZW4nfHxoLm5hbWU9PSdjaGlsZHJlbicpcmV0dXJuIHRydWV9cmV0dXJuIGZhbHNlfShh
-KQpuPUgub1Qocyk/ITA6IShhLmF0dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApfWNhdGNo
-KHApe0guUnUocCl9cj0iZWxlbWVudCB1bnByaW50YWJsZSIKdHJ5e3I9Si5qKGEpfWNhdGNoKHApe0gu
-UnUocCl9dHJ5e3E9Vy5yUyhhKQp0aGlzLmtSKHQuaC5hKGEpLGIsbixyLHEsdC5mLmEobSksSC5rKGwp
-KX1jYXRjaChwKXtpZihILlJ1KHApIGluc3RhbmNlb2YgUC51KXRocm93IHAKZWxzZXt0aGlzLkVQKGEs
-YikKd2luZG93Cm89IlJlbW92aW5nIGNvcnJ1cHRlZCBlbGVtZW50ICIrSC5FaihyKQppZih0eXBlb2Yg
-Y29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihvKX19fSwKa1I6ZnVuY3Rpb24o
-YSxiLGMsZCxlLGYsZyl7dmFyIHMscixxLHAsbyxuLG09dGhpcwppZihjKXttLkVQKGEsYikKd2luZG93
-CnM9IlJlbW92aW5nIGVsZW1lbnQgZHVlIHRvIGNvcnJ1cHRlZCBhdHRyaWJ1dGVzIG9uIDwiK2QrIj4i
-CmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKHMpCnJldHVy
-bn1pZighbS5hLmkwKGEpKXttLkVQKGEsYikKd2luZG93CnM9IlJlbW92aW5nIGRpc2FsbG93ZWQgZWxl
-bWVudCA8IitILkVqKGUpKyI+IGZyb20gIitILkVqKGIpCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZp
-bmVkIil3aW5kb3cuY29uc29sZS53YXJuKHMpCnJldHVybn1pZihnIT1udWxsKWlmKCFtLmEuRWIoYSwi
-aXMiLGcpKXttLkVQKGEsYikKd2luZG93CnM9IlJlbW92aW5nIGRpc2FsbG93ZWQgdHlwZSBleHRlbnNp
-b24gPCIrSC5FaihlKSsnIGlzPSInK2crJyI+JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIp
-d2luZG93LmNvbnNvbGUud2FybihzKQpyZXR1cm59cz1mLmd2YygpCnI9SC5WTShzLnNsaWNlKDApLEgu
-dDYocykpCmZvcihxPWYuZ3ZjKCkubGVuZ3RoLTEscz1mLmE7cT49MDstLXEpe2lmKHE+PXIubGVuZ3Ro
-KXJldHVybiBILk9IKHIscSkKcD1yW3FdCm89bS5hCm49Si5jSChwKQpILmgocCkKaWYoIW8uRWIoYSxu
-LHMuZ2V0QXR0cmlidXRlKHApKSl7d2luZG93Cm89IlJlbW92aW5nIGRpc2FsbG93ZWQgYXR0cmlidXRl
-IDwiK0guRWooZSkrIiAiK3ArJz0iJytILkVqKHMuZ2V0QXR0cmlidXRlKHApKSsnIj4nCmlmKHR5cGVv
-ZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKG8pCnMucmVtb3ZlQXR0cmli
-dXRlKHApfX1pZih0LmFXLmIoYSkpe3M9YS5jb250ZW50CnMudG9TdHJpbmcKbS5QbihzKX19LAokaW9u
-OjF9ClcuZm0ucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbT10aGlz
-LmEKc3dpdGNoKGEubm9kZVR5cGUpe2Nhc2UgMTptLkk0KGEsYikKYnJlYWsKY2FzZSA4OmNhc2UgMTE6
-Y2FzZSAzOmNhc2UgNDpicmVhawpkZWZhdWx0Om0uRVAoYSxiKX1zPWEubGFzdENoaWxkCmZvcihxPXQu
-QTtudWxsIT1zOyl7cj1udWxsCnRyeXtyPXMucHJldmlvdXNTaWJsaW5nCmlmKHIhPW51bGwpe3A9ci5u
-ZXh0U2libGluZwpvPXMKbz1wPT1udWxsP28hPW51bGw6cCE9PW8KcD1vfWVsc2UgcD0hMQppZihwKXtw
-PVAuUFYoIkNvcnJ1cHQgSFRNTCIpCnRocm93IEguYihwKX19Y2F0Y2gobil7SC5SdShuKQpwPXEuYShz
-KQptLmI9ITAKbz1wLnBhcmVudE5vZGUKbz1hPT1udWxsP28hPW51bGw6YSE9PW8KaWYobyl7bz1wLnBh
-cmVudE5vZGUKaWYobyE9bnVsbClvLnJlbW92ZUNoaWxkKHApfWVsc2UgYS5yZW1vdmVDaGlsZChwKQpz
-PW51bGwKcj1hLmxhc3RDaGlsZH1pZihzIT1udWxsKXRoaXMuJDIocyxhKQpzPXJ9fSwKJFM6MzB9Clcu
-TGUucHJvdG90eXBlPXt9ClcuSzcucHJvdG90eXBlPXt9ClcuckIucHJvdG90eXBlPXt9ClcuWFcucHJv
-dG90eXBlPXt9Clcub2EucHJvdG90eXBlPXt9ClAuaUoucHJvdG90eXBlPXsKVkg6ZnVuY3Rpb24oYSl7
-dmFyIHMscj10aGlzLmEscT1yLmxlbmd0aApmb3Iocz0wO3M8cTsrK3MpaWYocltzXT09PWEpcmV0dXJu
-IHMKQy5ObS5pKHIsYSkKQy5ObS5pKHRoaXMuYixudWxsKQpyZXR1cm4gcX0sClB2OmZ1bmN0aW9uKGEp
-e3ZhciBzLHIscSxwPXRoaXMsbz17fQppZihhPT1udWxsKXJldHVybiBhCmlmKEgubChhKSlyZXR1cm4g
-YQppZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVy
-biBhCmlmKGEgaW5zdGFuY2VvZiBQLmlQKXJldHVybiBuZXcgRGF0ZShhLmEpCmlmKHQuZnYuYihhKSl0
-aHJvdyBILmIoUC5TWSgic3RydWN0dXJlZCBjbG9uZSBvZiBSZWdFeHAiKSkKaWYodC5jOC5iKGEpKXJl
-dHVybiBhCmlmKHQudy5iKGEpKXJldHVybiBhCmlmKHQuSS5iKGEpKXJldHVybiBhCnM9dC5kRS5iKGEp
-fHwhMQppZihzKXJldHVybiBhCmlmKHQuZi5iKGEpKXtyPXAuVkgoYSkKcz1wLmIKaWYocj49cy5sZW5n
-dGgpcmV0dXJuIEguT0gocyxyKQpxPW8uYT1zW3JdCmlmKHEhPW51bGwpcmV0dXJuIHEKcT17fQpvLmE9
-cQpDLk5tLlk1KHMscixxKQphLksoMCxuZXcgUC5qZyhvLHApKQpyZXR1cm4gby5hfWlmKHQuai5iKGEp
-KXtyPXAuVkgoYSkKbz1wLmIKaWYocj49by5sZW5ndGgpcmV0dXJuIEguT0gobyxyKQpxPW9bcl0KaWYo
-cSE9bnVsbClyZXR1cm4gcQpyZXR1cm4gcC5layhhLHIpfWlmKHQuZUguYihhKSl7cj1wLlZIKGEpCnM9
-cC5iCmlmKHI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMscikKcT1vLmI9c1tyXQppZihxIT1udWxsKXJl
-dHVybiBxCnE9e30Kby5iPXEKQy5ObS5ZNShzLHIscSkKcC5pbShhLG5ldyBQLlRhKG8scCkpCnJldHVy
-biBvLmJ9dGhyb3cgSC5iKFAuU1koInN0cnVjdHVyZWQgY2xvbmUgb2Ygb3RoZXIgdHlwZSIpKX0sCmVr
-OmZ1bmN0aW9uKGEsYil7dmFyIHMscj1KLlU2KGEpLHE9ci5nQShhKSxwPW5ldyBBcnJheShxKQpDLk5t
-Llk1KHRoaXMuYixiLHApCmZvcihzPTA7czxxOysrcylDLk5tLlk1KHAscyx0aGlzLlB2KHIucShhLHMp
-KSkKcmV0dXJuIHB9fQpQLmpnLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLmFbYV09
-dGhpcy5iLlB2KGIpfSwKJFM6MzF9ClAuVGEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlz
-LmEuYlthXT10aGlzLmIuUHYoYil9LAokUzoxNn0KUC5CZi5wcm90b3R5cGU9ewppbTpmdW5jdGlvbihh
-LGIpe3ZhciBzLHIscSxwCnQuYjguYShiKQpmb3Iocz1PYmplY3Qua2V5cyhhKSxyPXMubGVuZ3RoLHE9
-MDtxPHI7KytxKXtwPXNbcV0KYi4kMihwLGFbcF0pfX19ClAuQXMucHJvdG90eXBlPXsKVjpmdW5jdGlv
-bihhKXt2YXIgcwpILmgoYSkKcz0kLmhHKCkuYgppZih0eXBlb2YgYSE9InN0cmluZyIpSC52KEgudEwo
-YSkpCmlmKHMudGVzdChhKSlyZXR1cm4gYQp0aHJvdyBILmIoUC5MMyhhLCJ2YWx1ZSIsIk5vdCBhIHZh
-bGlkIGNsYXNzIHRva2VuIikpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5EKCkuaygwLCIgIil9
-LApnbTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLkQoKQpyZXR1cm4gUC5yaihzLHMucixILkxoKHMpLmMp
-fSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLkQoKS5hPT09MH0sCmdvcjpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5EKCkuYSE9PTB9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5EKCkuYX0sCnRn
-OmZ1bmN0aW9uKGEsYil7dGhpcy5WKGIpCnJldHVybiB0aGlzLkQoKS50ZygwLGIpfSwKaTpmdW5jdGlv
-bihhLGIpe3ZhciBzCkguaChiKQp0aGlzLlYoYikKcz10aGlzLk8obmV3IFAuR0UoYikpCnJldHVybiBI
-Lnk4KHM9PW51bGw/ITE6cyl9LApMOmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZih0eXBlb2YgYiE9InN0
-cmluZyIpcmV0dXJuITEKdGhpcy5WKGIpCnM9dGhpcy5EKCkKcj1zLkwoMCxiKQp0aGlzLlgocykKcmV0
-dXJuIHJ9LApGVjpmdW5jdGlvbihhLGIpe3RoaXMuTyhuZXcgUC5ONyh0aGlzLHQuUS5hKGIpKSl9LApl
-UjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMuRCgpCnJldHVybiBILmJLKHMsYixILkxoKHMpLkMoImxm
-LkUiKSl9LApFOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuRCgpLkUoMCxiKX0sClYxOmZ1bmN0aW9u
-KGEpe3RoaXMuTyhuZXcgUC51USgpKX0sCk86ZnVuY3Rpb24oYSl7dmFyIHMscgp0LmJVLmEoYSkKcz10
-aGlzLkQoKQpyPWEuJDEocykKdGhpcy5YKHMpCnJldHVybiByfX0KUC5HRS5wcm90b3R5cGU9ewokMTpm
-dW5jdGlvbihhKXtyZXR1cm4gdC5DLmEoYSkuaSgwLHRoaXMuYSl9LAokUzozM30KUC5ONy5wcm90b3R5
-cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmIscj1ILnQ2KHMpCnJldHVybiB0LkMuYShhKS5G
-VigwLG5ldyBILmxKKHMsci5DKCJxVSgxKSIpLmEodGhpcy5hLmd1TSgpKSxyLkMoImxKPDEscVU+Iikp
-KX0sCiRTOjE3fQpQLnVRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3QuQy5hKGEpCmlmKGEuYT4w
-KXthLmI9YS5jPWEuZD1hLmU9YS5mPW51bGwKYS5hPTAKYS5HWSgpfXJldHVybiBudWxsfSwKJFM6MTd9
-ClAuaEYucHJvdG90eXBlPXskaWhGOjF9ClAuUEMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFy
-IHMKdC5ZLmEoYSkKcz1mdW5jdGlvbihiLGMsZCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGIoYyxk
-LHRoaXMsQXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KGFyZ3VtZW50cykpfX0oUC5SNCxhLCExKQpQ
-LkRtKHMsJC53KCksYSkKcmV0dXJuIHN9LAokUzo0fQpQLm10LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9u
-KGEpe3JldHVybiBuZXcgdGhpcy5hKGEpfSwKJFM6NH0KUC5Oei5wcm90b3R5cGU9ewokMTpmdW5jdGlv
-bihhKXtyZXR1cm4gbmV3IFAucjcoYSl9LAokUzozNX0KUC5RUy5wcm90b3R5cGU9ewokMTpmdW5jdGlv
-bihhKXtyZXR1cm4gbmV3IFAuVHooYSx0LmFtKX0sCiRTOjU0fQpQLm5wLnByb3RvdHlwZT17CiQxOmZ1
-bmN0aW9uKGEpe3JldHVybiBuZXcgUC5FNChhKX0sCiRTOjM3fQpQLkU0LnByb3RvdHlwZT17CnE6ZnVu
-Y3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBiIT0ibnVtYmVyIil0aHJvdyBI
-LmIoUC54WSgicHJvcGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIpKQpyZXR1cm4gUC5kVSh0aGlz
-LmFbYl0pfSwKWTU6ZnVuY3Rpb24oYSxiLGMpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIiYmdHlwZW9mIGIh
-PSJudW1iZXIiKXRocm93IEguYihQLnhZKCJwcm9wZXJ0eSBpcyBub3QgYSBTdHJpbmcgb3IgbnVtIikp
-CnRoaXMuYVtiXT1QLndZKGMpfSwKRE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJl
-dHVybiBiIGluc3RhbmNlb2YgUC5FNCYmdGhpcy5hPT09Yi5hfSwKdzpmdW5jdGlvbihhKXt2YXIgcyxy
-CnRyeXtzPVN0cmluZyh0aGlzLmEpCnJldHVybiBzfWNhdGNoKHIpe0guUnUocikKcz10aGlzLnhiKDAp
-CnJldHVybiBzfX0sClY3OmZ1bmN0aW9uKGEsYil7dmFyIHMscj10aGlzLmEKaWYoYj09bnVsbClzPW51
-bGwKZWxzZXtzPUgudDYoYikKcz1QLkNIKG5ldyBILmxKKGIscy5DKCJAKDEpIikuYShQLmlHKCkpLHMu
-QygibEo8MSxAPiIpKSwhMCx0LnopfXJldHVybiBQLmRVKHJbYV0uYXBwbHkocixzKSl9LApnaU86ZnVu
-Y3Rpb24oYSl7cmV0dXJuIDB9fQpQLnI3LnByb3RvdHlwZT17fQpQLlR6LnByb3RvdHlwZT17CmNQOmZ1
-bmN0aW9uKGEpe3ZhciBzPXRoaXMscj1hPDB8fGE+PXMuZ0EocykKaWYocil0aHJvdyBILmIoUC5URShh
-LDAscy5nQShzKSxudWxsLG51bGwpKX0sCnE6ZnVuY3Rpb24oYSxiKXtpZihILm9rKGIpKXRoaXMuY1Ao
-YikKcmV0dXJuIHRoaXMuJHRpLmMuYSh0aGlzLlVyKDAsYikpfSwKWTU6ZnVuY3Rpb24oYSxiLGMpe3Ro
-aXMuY1AoYikKdGhpcy5lNCgwLGIsYyl9LApnQTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEubGVuZ3Ro
-CmlmKHR5cGVvZiBzPT09Im51bWJlciImJnM+Pj4wPT09cylyZXR1cm4gcwp0aHJvdyBILmIoUC5QVigi
-QmFkIEpzQXJyYXkgbGVuZ3RoIikpfSwKJGliUToxLAokaWNYOjEsCiRpek06MX0KUC5jby5wcm90b3R5
-cGU9e30KUC5uZC5wcm90b3R5cGU9eyRpbmQ6MX0KUC5LZS5wcm90b3R5cGU9ewpEOmZ1bmN0aW9uKCl7
-dmFyIHMscixxLHAsbz10aGlzLmEuZ2V0QXR0cmlidXRlKCJjbGFzcyIpLG49UC5Mcyh0Lk4pCmlmKG89
-PW51bGwpcmV0dXJuIG4KZm9yKHM9by5zcGxpdCgiICIpLHI9cy5sZW5ndGgscT0wO3E8cjsrK3Epe3A9
-Si5UMChzW3FdKQppZihwLmxlbmd0aCE9PTApbi5pKDAscCl9cmV0dXJuIG59LApYOmZ1bmN0aW9uKGEp
-e3RoaXMuYS5zZXRBdHRyaWJ1dGUoImNsYXNzIixhLmsoMCwiICIpKX19ClAuaGkucHJvdG90eXBlPXsK
-Z246ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLktlKGEpfSwKc2hmOmZ1bmN0aW9uKGEsYil7dGhpcy5Z
-QyhhLGIpfSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuCmlmKGQ9PW51bGwpe3M9
-SC5WTShbXSx0LnYpCmQ9bmV3IFcudkQocykKQy5ObS5pKHMsVy5UdyhudWxsKSkKQy5ObS5pKHMsVy5C
-bCgpKQpDLk5tLmkocyxuZXcgVy5PdygpKX1jPW5ldyBXLktvKGQpCnI9JzxzdmcgdmVyc2lvbj0iMS4x
-Ij4nK0guRWooYikrIjwvc3ZnPiIKcz1kb2N1bWVudApxPXMuYm9keQpxLnRvU3RyaW5nCnA9Qy5SWS5B
-SChxLHIsYykKbz1zLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpwLnRvU3RyaW5nCnM9bmV3IFcuZTco
-cCkKbj1zLmdyOChzKQpmb3IoO3M9bi5maXJzdENoaWxkLHMhPW51bGw7KW8uYXBwZW5kQ2hpbGQocykK
-cmV0dXJuIG99LApuejpmdW5jdGlvbihhLGIsYyxkLGUpe3Rocm93IEguYihQLkw0KCJDYW5ub3QgaW52
-b2tlIGluc2VydEFkamFjZW50SHRtbCBvbiBTVkcuIikpfSwKZ1ZsOmZ1bmN0aW9uKGEpe3JldHVybiBu
-ZXcgVy5ldShhLCJjbGljayIsITEsdC5rKX0sCiRpaGk6MX0KTS5INy5wcm90b3R5cGU9ewp3OmZ1bmN0
-aW9uKGEpe3JldHVybiB0aGlzLmJ9fQpVLkxMLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7cmV0dXJu
-IFAuRUYoWyJub2RlSWQiLHRoaXMuYiwia2luZCIsdGhpcy5hLmFdLHQuWCx0Ll8pfX0KVS5NRC5wcm90
+bih0aGlzLmUsIi8iKX0sCnQ0OmZ1bmN0aW9uKCl7dmFyIHMscj10aGlzLHE9ci5hCmlmKHEhPT0iIiYm
+cSE9PSJmaWxlIil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBh
+ICIrcSsiIFVSSSIpKQppZihyLmd0UCgpIT09IiIpdGhyb3cgSC5iKFAuTDQodS5pKSkKaWYoci5nS2Eo
+KSE9PSIiKXRocm93IEguYihQLkw0KHUubCkpCnE9JC53USgpCmlmKEgub1QocSkpcT1QLm1uKHIpCmVs
+c2V7aWYoci5jIT1udWxsJiZyLmdKZihyKSE9PSIiKUgudihQLkw0KHUuaikpCnM9ci5nRmooKQpQLmtF
+KHMsITEpCnE9UC52ZyhDLnhCLm4oci5lLCIvIik/Ii8iOiIiLHMsIi8iKQpxPXEuY2hhckNvZGVBdCgw
+KT09MD9xOnF9cmV0dXJuIHF9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmduRCgpfSwKRE46ZnVu
+Y3Rpb24oYSxiKXt2YXIgcz10aGlzCmlmKGI9PW51bGwpcmV0dXJuITEKaWYocz09PWIpcmV0dXJuITAK
+cmV0dXJuIHQuZEQuYihiKSYmcy5hPT09Yi5nRmkoKSYmcy5jIT1udWxsPT09Yi5nY2ooKSYmcy5iPT09
+Yi5na3UoKSYmcy5nSmYocyk9PT1iLmdKZihiKSYmcy5ndHAocyk9PT1iLmd0cChiKSYmcy5lPT09Yi5n
+SWkoYikmJnMuZiE9bnVsbD09PWIuZ1FEKCkmJnMuZ3RQKCk9PT1iLmd0UCgpJiZzLnIhPW51bGw9PT1i
+LmdaOCgpJiZzLmdLYSgpPT09Yi5nS2EoKX0sCnNLcDpmdW5jdGlvbihhKXt0aGlzLno9dC5iay5hKGEp
+fSwKc05NOmZ1bmN0aW9uKGEpe3RoaXMuY3k9dC5jWi5hKGEpfSwKJGlpRDoxLApnRmk6ZnVuY3Rpb24o
+KXtyZXR1cm4gdGhpcy5hfSwKZ0lpOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmV9fQpQLlJaLnByb3Rv
+dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBQLmVQKEMuWkosSC5oKGEpLEMueE0sITEpfSwKJFM6
+NX0KUC5NRS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMuYixyPXRoaXMuYQpz
+LmErPXIuYQpyLmE9IiYiCnI9cy5hKz1ILkVqKFAuZVAoQy5GMyxhLEMueE0sITApKQppZihiIT1udWxs
+JiZiLmxlbmd0aCE9PTApe3MuYT1yKyI9IgpzLmErPUguRWooUC5lUChDLkYzLGIsQy54TSwhMCkpfX0s
+CiRTOjIyfQpQLnk1LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpILmgoYSkKaWYo
+Yj09bnVsbHx8dHlwZW9mIGI9PSJzdHJpbmciKXRoaXMuYS4kMihhLEguayhiKSkKZWxzZSBmb3Iocz1K
+LklUKHQudS5hKGIpKSxyPXRoaXMuYTtzLkYoKTspci4kMihhLEguaChzLmdsKCkpKX0sCiRTOjEzfQpQ
+LlBFLnByb3RvdHlwZT17CmdsUjpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89dGhpcyxuPW51bGwsbT1v
+LmMKaWYobT09bnVsbCl7bT1vLmIKaWYoMD49bS5sZW5ndGgpcmV0dXJuIEguT0gobSwwKQpzPW8uYQpt
+PW1bMF0rMQpyPUMueEIuWFUocywiPyIsbSkKcT1zLmxlbmd0aAppZihyPj0wKXtwPVAuUEkocyxyKzEs
+cSxDLlZDLCExKQpxPXJ9ZWxzZSBwPW4KbT1vLmM9bmV3IFAucWUoImRhdGEiLCIiLG4sbixQLlBJKHMs
+bSxxLEMuV2QsITEpLHAsbil9cmV0dXJuIG19LAp3OmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcy5iCmlm
+KDA+PXIubGVuZ3RoKXJldHVybiBILk9IKHIsMCkKcz10aGlzLmEKcmV0dXJuIHJbMF09PT0tMT8iZGF0
+YToiK3M6c319ClAueUkucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcz10aGlzLmEKaWYo
+YT49cy5sZW5ndGgpcmV0dXJuIEguT0gocyxhKQpzPXNbYV0KQy5OQS5kdShzLDAsOTYsYikKcmV0dXJu
+IHN9LAokUzoyM30KUC5jNi5wcm90b3R5cGU9ewokMzpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxCmZv
+cihzPWIubGVuZ3RoLHI9MDtyPHM7KytyKXtxPUMueEIuVyhiLHIpXjk2CmlmKHE+PTk2KXJldHVybiBI
+Lk9IKGEscSkKYVtxXT1jfX0sCiRTOjE0fQpQLnFkLnByb3RvdHlwZT17CiQzOmZ1bmN0aW9uKGEsYixj
+KXt2YXIgcyxyLHEKZm9yKHM9Qy54Qi5XKGIsMCkscj1DLnhCLlcoYiwxKTtzPD1yOysrcyl7cT0oc145
+Nik+Pj4wCmlmKHE+PTk2KXJldHVybiBILk9IKGEscSkKYVtxXT1jfX0sCiRTOjE0fQpQLlVmLnByb3Rv
+dHlwZT17CmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlzLmM+MH0sCmd4QTpmdW5jdGlvbigpe3JldHVy
+biB0aGlzLmM+MCYmdGhpcy5kKzE8dGhpcy5lfSwKZ1FEOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZjx0
+aGlzLnJ9LApnWjg6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5yPHRoaXMuYS5sZW5ndGh9LApnTnc6ZnVu
+Y3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NCYmQy54Qi5uKHRoaXMuYSwiZmlsZSIpfSwKZ1daOmZ1bmN0
+aW9uKCl7cmV0dXJuIHRoaXMuYj09PTQmJkMueEIubih0aGlzLmEsImh0dHAiKX0sCmdSZTpmdW5jdGlv
+bigpe3JldHVybiB0aGlzLmI9PT01JiZDLnhCLm4odGhpcy5hLCJodHRwcyIpfSwKZ3RUOmZ1bmN0aW9u
+KCl7cmV0dXJuIEMueEIuUWkodGhpcy5hLCIvIix0aGlzLmUpfSwKZ0ZpOmZ1bmN0aW9uKCl7dmFyIHM9
+dGhpcy54CnJldHVybiBzPT1udWxsP3RoaXMueD10aGlzLlUyKCk6c30sClUyOmZ1bmN0aW9uKCl7dmFy
+IHM9dGhpcyxyPXMuYgppZihyPD0wKXJldHVybiIiCmlmKHMuZ1daKCkpcmV0dXJuImh0dHAiCmlmKHMu
+Z1JlKCkpcmV0dXJuImh0dHBzIgppZihzLmdOdygpKXJldHVybiJmaWxlIgppZihyPT09NyYmQy54Qi5u
+KHMuYSwicGFja2FnZSIpKXJldHVybiJwYWNrYWdlIgpyZXR1cm4gQy54Qi5OaihzLmEsMCxyKX0sCmdr
+dTpmdW5jdGlvbigpe3ZhciBzPXRoaXMuYyxyPXRoaXMuYiszCnJldHVybiBzPnI/Qy54Qi5Oaih0aGlz
+LmEscixzLTEpOiIifSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYwpyZXR1cm4gcz4wP0MueEIu
+TmoodGhpcy5hLHMsdGhpcy5kKToiIn0sCmd0cDpmdW5jdGlvbihhKXt2YXIgcz10aGlzCmlmKHMuZ3hB
+KCkpcmV0dXJuIFAuUUEoQy54Qi5OaihzLmEscy5kKzEscy5lKSxudWxsKQppZihzLmdXWigpKXJldHVy
+biA4MAppZihzLmdSZSgpKXJldHVybiA0NDMKcmV0dXJuIDB9LApnSWk6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEMueEIuTmoodGhpcy5hLHRoaXMuZSx0aGlzLmYpfSwKZ3RQOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy5m
+LHI9dGhpcy5yCnJldHVybiBzPHI/Qy54Qi5Oaih0aGlzLmEscysxLHIpOiIifSwKZ0thOmZ1bmN0aW9u
+KCl7dmFyIHM9dGhpcy5yLHI9dGhpcy5hCnJldHVybiBzPHIubGVuZ3RoP0MueEIueW4ocixzKzEpOiIi
+fSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHMscixxPXRoaXMuZSxwPXRoaXMuZixvPXRoaXMuYQppZihDLnhC
+LlFpKG8sIi8iLHEpKSsrcQppZihxPT09cClyZXR1cm4gQy54RApzPUguVk0oW10sdC5zKQpmb3Iocj1x
+O3I8cDsrK3IpaWYoQy54Qi5PKG8scik9PT00Nyl7Qy5ObS5pKHMsQy54Qi5OaihvLHEscikpCnE9cisx
+fUMuTm0uaShzLEMueEIuTmoobyxxLHApKQpyZXR1cm4gUC5BRihzLHQuTil9LApnaFk6ZnVuY3Rpb24o
+KXtpZih0aGlzLmY+PXRoaXMucilyZXR1cm4gQy5DTQpyZXR1cm4gbmV3IFAuR2ooUC5XWCh0aGlzLmd0
+UCgpKSx0LmR3KX0sCmtYOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuZCsxCnJldHVybiBzK2EubGVuZ3Ro
+PT09dGhpcy5lJiZDLnhCLlFpKHRoaXMuYSxhLHMpfSwKTjk6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLHI9
+cy5yLHE9cy5hCmlmKHI+PXEubGVuZ3RoKXJldHVybiBzCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKHEs
+MCxyKSxzLmIscy5jLHMuZCxzLmUscy5mLHIscy54KX0sCm5tOmZ1bmN0aW9uKGEsYil7dmFyIHMscixx
+LHAsbyxuLG0sbCxrLGosaT10aGlzLGg9bnVsbAp0LmM5LmEoYikKcz1pLmdGaSgpCnI9cz09PSJmaWxl
+IgpxPWkuYwpwPXE+MD9DLnhCLk5qKGkuYSxpLmIrMyxxKToiIgpvPWkuZ3hBKCk/aS5ndHAoaSk6aApx
+PWkuYwppZihxPjApbj1DLnhCLk5qKGkuYSxxLGkuZCkKZWxzZSBuPXAubGVuZ3RoIT09MHx8byE9bnVs
+bHx8cj8iIjpoCnE9aS5hCm09Qy54Qi5OaihxLGkuZSxpLmYpCmlmKCFyKWw9biE9bnVsbCYmbS5sZW5n
+dGghPT0wCmVsc2UgbD0hMAppZihsJiYhQy54Qi5uKG0sIi8iKSltPSIvIittCms9UC5sZShoLDAsMCxi
+KQpsPWkucgpqPWw8cS5sZW5ndGg/Qy54Qi55bihxLGwrMSk6aApyZXR1cm4gbmV3IFAuRG4ocyxwLG4s
+byxtLGssail9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5tUyhQLmhLKGEpKX0sCm1TOmZ1bmN0
+aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBQLlVmKXJldHVybiB0aGlzLnUxKHRoaXMsYSkKcmV0dXJuIHRo
+aXMudnMoKS5tUyhhKX0sCnUxOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxo
+LGc9Yi5iCmlmKGc+MClyZXR1cm4gYgpzPWIuYwppZihzPjApe3I9YS5iCmlmKHI8PTApcmV0dXJuIGIK
+aWYoYS5nTncoKSlxPWIuZSE9PWIuZgplbHNlIGlmKGEuZ1daKCkpcT0hYi5rWCgiODAiKQplbHNlIHE9
+IWEuZ1JlKCl8fCFiLmtYKCI0NDMiKQppZihxKXtwPXIrMQpyZXR1cm4gbmV3IFAuVWYoQy54Qi5Oaihh
+LmEsMCxwKStDLnhCLnluKGIuYSxnKzEpLHIscytwLGIuZCtwLGIuZStwLGIuZitwLGIucitwLGEueCl9
+ZWxzZSByZXR1cm4gdGhpcy52cygpLm1TKGIpfW89Yi5lCmc9Yi5mCmlmKG89PT1nKXtzPWIucgppZihn
+PHMpe3I9YS5mCnA9ci1nCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGEuYSwwLHIpK0MueEIueW4oYi5h
+LGcpLGEuYixhLmMsYS5kLGEuZSxnK3AscytwLGEueCl9Zz1iLmEKaWYoczxnLmxlbmd0aCl7cj1hLnIK
+cmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAscikrQy54Qi55bihnLHMpLGEuYixhLmMsYS5kLGEu
+ZSxhLmYscysoci1zKSxhLngpfXJldHVybiBhLk45KCl9cz1iLmEKaWYoQy54Qi5RaShzLCIvIixvKSl7
+cj1hLmUKcD1yLW8KcmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAscikrQy54Qi55bihzLG8pLGEu
+YixhLmMsYS5kLHIsZytwLGIucitwLGEueCl9bj1hLmUKbT1hLmYKaWYobj09PW0mJmEuYz4wKXtmb3Io
+O0MueEIuUWkocywiLi4vIixvKTspbys9MwpwPW4tbysxCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGEu
+YSwwLG4pKyIvIitDLnhCLnluKHMsbyksYS5iLGEuYyxhLmQsbixnK3AsYi5yK3AsYS54KX1sPWEuYQpm
+b3Ioaz1uO0MueEIuUWkobCwiLi4vIixrKTspays9MwpqPTAKd2hpbGUoITApe2k9byszCmlmKCEoaTw9
+ZyYmQy54Qi5RaShzLCIuLi8iLG8pKSlicmVhazsrK2oKbz1pfWZvcihoPSIiO20+azspey0tbQppZihD
+LnhCLk8obCxtKT09PTQ3KXtpZihqPT09MCl7aD0iLyIKYnJlYWt9LS1qCmg9Ii8ifX1pZihtPT09ayYm
+YS5iPD0wJiYhQy54Qi5RaShsLCIvIixuKSl7by09aiozCmg9IiJ9cD1tLW8raC5sZW5ndGgKcmV0dXJu
+IG5ldyBQLlVmKEMueEIuTmoobCwwLG0pK2grQy54Qi55bihzLG8pLGEuYixhLmMsYS5kLG4sZytwLGIu
+citwLGEueCl9LAp0NDpmdW5jdGlvbigpe3ZhciBzLHIscSxwPXRoaXMKaWYocC5iPj0wJiYhcC5nTnco
+KSl0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhICIrcC5nRmko
+KSsiIFVSSSIpKQpzPXAuZgpyPXAuYQppZihzPHIubGVuZ3RoKXtpZihzPHAucil0aHJvdyBILmIoUC5M
+NCh1LmkpKQp0aHJvdyBILmIoUC5MNCh1LmwpKX1xPSQud1EoKQppZihILm9UKHEpKXM9UC5tbihwKQpl
+bHNle2lmKHAuYzxwLmQpSC52KFAuTDQodS5qKSkKcz1DLnhCLk5qKHIscC5lLHMpfXJldHVybiBzfSwK
+Z2lPOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMueQpyZXR1cm4gcz09bnVsbD90aGlzLnk9Qy54Qi5naU8o
+dGhpcy5hKTpzfSwKRE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCmlmKHRoaXM9PT1i
+KXJldHVybiEwCnJldHVybiB0LmRELmIoYikmJnRoaXMuYT09PWIudygwKX0sCnZzOmZ1bmN0aW9uKCl7
+dmFyIHM9dGhpcyxyPW51bGwscT1zLmdGaSgpLHA9cy5na3UoKSxvPXMuYz4wP3MuZ0pmKHMpOnIsbj1z
+Lmd4QSgpP3MuZ3RwKHMpOnIsbT1zLmEsbD1zLmYsaz1DLnhCLk5qKG0scy5lLGwpLGo9cy5yCmw9bDxq
+P3MuZ3RQKCk6cgpyZXR1cm4gbmV3IFAuRG4ocSxwLG8sbixrLGwsajxtLmxlbmd0aD9zLmdLYSgpOnIp
+fSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKJGlpRDoxfQpQLnFlLnByb3RvdHlwZT17fQpX
+LnFFLnByb3RvdHlwZT17fQpXLkdoLnByb3RvdHlwZT17CnNMVTpmdW5jdGlvbihhLGIpe2EuaHJlZj1i
+fSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGlHaDoxfQpXLmZZLnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX19ClcubkIucHJvdG90eXBlPXskaW5COjF9Clcu
+QXoucHJvdG90eXBlPXskaUF6OjF9ClcuUVAucHJvdG90eXBlPXskaVFQOjF9ClcubngucHJvdG90eXBl
+PXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5vSi5wcm90b3R5cGU9ewpnQTpmdW5j
+dGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmlkLnByb3RvdHlwZT17fQpXLlFGLnByb3RvdHlwZT17
+fQpXLk5oLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX19ClcuYWUucHJv
+dG90eXBlPXsKRGM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYS5jcmVhdGVIVE1MRG9jdW1lbnQoYil9fQpX
+LklCLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHMscj1hLmxlZnQKci50b1N0cmluZwpyPSJS
+ZWN0YW5nbGUgKCIrSC5FaihyKSsiLCAiCnM9YS50b3AKcy50b1N0cmluZwpzPXIrSC5FaihzKSsiKSAi
+CnI9YS53aWR0aApyLnRvU3RyaW5nCnI9cytILkVqKHIpKyIgeCAiCnM9YS5oZWlnaHQKcy50b1N0cmlu
+ZwpyZXR1cm4gcitILkVqKHMpfSwKRE46ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlmKGI9PW51bGwpcmV0
+dXJuITEKaWYodC5xLmIoYikpe3M9YS5sZWZ0CnMudG9TdHJpbmcKcj1iLmxlZnQKci50b1N0cmluZwpp
+ZihzPT09cil7cz1hLnRvcApzLnRvU3RyaW5nCnI9Yi50b3AKci50b1N0cmluZwppZihzPT09cil7cz1h
+LndpZHRoCnMudG9TdHJpbmcKcj1iLndpZHRoCnIudG9TdHJpbmcKaWYocz09PXIpe3M9YS5oZWlnaHQK
+cy50b1N0cmluZwpyPWIuaGVpZ2h0CnIudG9TdHJpbmcKcj1zPT09cgpzPXJ9ZWxzZSBzPSExfWVsc2Ug
+cz0hMX1lbHNlIHM9ITF9ZWxzZSBzPSExCnJldHVybiBzfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzLHIs
+cSxwPWEubGVmdApwLnRvU3RyaW5nCnA9Qy5DRC5naU8ocCkKcz1hLnRvcApzLnRvU3RyaW5nCnM9Qy5D
+RC5naU8ocykKcj1hLndpZHRoCnIudG9TdHJpbmcKcj1DLkNELmdpTyhyKQpxPWEuaGVpZ2h0CnEudG9T
+dHJpbmcKcmV0dXJuIFcuckUocCxzLHIsQy5DRC5naU8ocSkpfSwKJGl0bjoxfQpXLm43LnByb3RvdHlw
+ZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19Clcud3oucHJvdG90eXBlPXsKZ0E6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7dmFyIHMKSC51UChi
+KQpzPXRoaXMuYQppZihiPDB8fGI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsYikKcmV0dXJuIHRoaXMu
+JHRpLmMuYShzW2JdKX0sClk1OmZ1bmN0aW9uKGEsYixjKXt0aGlzLiR0aS5jLmEoYykKdGhyb3cgSC5i
+KFAuTDQoIkNhbm5vdCBtb2RpZnkgbGlzdCIpKX19ClcuY3YucHJvdG90eXBlPXsKZ1FnOmZ1bmN0aW9u
+KGEpe3JldHVybiBuZXcgVy5pNyhhKX0sCmdQOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5JNChhKX0s
+CnNQOmZ1bmN0aW9uKGEsYil7dmFyIHMKdC5RLmEoYikKcz10aGlzLmdQKGEpCnMuVjEoMCkKcy5GVigw
+LGIpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhbE5hbWV9LApGRjpmdW5jdGlvbihhKXt2YXIg
+cz0hIWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZAppZihzKWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZCgp
+CmVsc2UgYS5zY3JvbGxJbnRvVmlldygpfSwKbno6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyPXRo
+aXMucjYoYSxjLGQsZSkKc3dpdGNoKGIudG9Mb3dlckNhc2UoKSl7Y2FzZSJiZWZvcmViZWdpbiI6cz1h
+LnBhcmVudE5vZGUKcy50b1N0cmluZwpKLkVoKHMscixhKQpicmVhawpjYXNlImFmdGVyYmVnaW4iOnM9
+YS5jaGlsZE5vZGVzCnRoaXMubUsoYSxyLHMubGVuZ3RoPjA/c1swXTpudWxsKQpicmVhawpjYXNlImJl
+Zm9yZWVuZCI6YS5hcHBlbmRDaGlsZChyKQpicmVhawpjYXNlImFmdGVyZW5kIjpzPWEucGFyZW50Tm9k
+ZQpzLnRvU3RyaW5nCkouRWgocyxyLGEubmV4dFNpYmxpbmcpCmJyZWFrCmRlZmF1bHQ6SC52KFAueFko
+IkludmFsaWQgcG9zaXRpb24gIitiKSl9fSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAK
+aWYoYz09bnVsbCl7aWYoZD09bnVsbCl7cz0kLmx0CmlmKHM9PW51bGwpe3M9SC5WTShbXSx0LnYpCnI9
+bmV3IFcudkQocykKQy5ObS5pKHMsVy5UdyhudWxsKSkKQy5ObS5pKHMsVy5CbCgpKQokLmx0PXIKZD1y
+fWVsc2UgZD1zfXM9JC5FVQppZihzPT1udWxsKXtzPW5ldyBXLktvKGQpCiQuRVU9cwpjPXN9ZWxzZXtz
+LmE9ZApjPXN9fWVsc2UgaWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgidmFsaWRhdG9yIGNhbiBvbmx5
+IGJlIHBhc3NlZCBpZiB0cmVlU2FuaXRpemVyIGlzIG51bGwiKSkKaWYoJC54bz09bnVsbCl7cz1kb2N1
+bWVudApyPXMuaW1wbGVtZW50YXRpb24Kci50b1N0cmluZwpyPUMubUguRGMociwiIikKJC54bz1yCiQu
+Qk89ci5jcmVhdGVSYW5nZSgpCnI9JC54by5jcmVhdGVFbGVtZW50KCJiYXNlIikKdC5jUi5hKHIpCnM9
+cy5iYXNlVVJJCnMudG9TdHJpbmcKci5ocmVmPXMKJC54by5oZWFkLmFwcGVuZENoaWxkKHIpfXM9JC54
+bwppZihzLmJvZHk9PW51bGwpe3I9cy5jcmVhdGVFbGVtZW50KCJib2R5IikKQy5CWi5zR1Mocyx0LnAu
+YShyKSl9cz0kLnhvCmlmKHQucC5iKGEpKXtzPXMuYm9keQpzLnRvU3RyaW5nCnE9c31lbHNle3MudG9T
+dHJpbmcKcT1zLmNyZWF0ZUVsZW1lbnQoYS50YWdOYW1lKQokLnhvLmJvZHkuYXBwZW5kQ2hpbGQocSl9
+aWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSYmIUMu
+Tm0udGcoQy5TcSxhLnRhZ05hbWUpKXskLkJPLnNlbGVjdE5vZGVDb250ZW50cyhxKQpzPSQuQk8Kcy50
+b1N0cmluZwpwPXMuY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KGI9PW51bGw/Im51bGwiOmIpfWVsc2V7
+Si53ZihxLGIpCnA9JC54by5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKZm9yKDtzPXEuZmlyc3RDaGls
+ZCxzIT1udWxsOylwLmFwcGVuZENoaWxkKHMpfWlmKHEhPT0kLnhvLmJvZHkpSi5MdChxKQpjLlBuKHAp
+CmRvY3VtZW50LmFkb3B0Tm9kZShwKQpyZXR1cm4gcH0sCkFIOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4g
+dGhpcy5yNihhLGIsYyxudWxsKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxiKX0sCnBrOmZ1
+bmN0aW9uKGEsYixjKXt0aGlzLnNhNChhLG51bGwpCmEuYXBwZW5kQ2hpbGQodGhpcy5yNihhLGIsbnVs
+bCxjKSl9LApZQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEsYixudWxsKX0sCnNSTjpmdW5j
+dGlvbihhLGIpe2EuaW5uZXJIVE1MPWJ9LApnbnM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudGFnTmFtZX0s
+CmdWbDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuZXUoYSwiY2xpY2siLCExLHQuayl9LAokaWN2OjF9
+ClcuQ3YucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHQuaC5iKHQuQS5hKGEpKX0sCiRT
+OjI1fQpXLmVhLnByb3RvdHlwZT17JGllYToxfQpXLkQwLnByb3RvdHlwZT17Ck9uOmZ1bmN0aW9uKGEs
+YixjLGQpe3QuYncuYShjKQppZihjIT1udWxsKXRoaXMudihhLGIsYyxkKX0sCkI6ZnVuY3Rpb24oYSxi
+LGMpe3JldHVybiB0aGlzLk9uKGEsYixjLG51bGwpfSwKdjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4g
+YS5hZGRFdmVudExpc3RlbmVyKGIsSC50Uih0LmJ3LmEoYyksMSksZCl9LAokaUQwOjF9ClcuaEgucHJv
+dG90eXBlPXskaWhIOjF9ClcuaDQucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVu
+Z3RofX0KVy5ici5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLlZi
+LnByb3RvdHlwZT17CnNHUzpmdW5jdGlvbihhLGIpe2EuYm9keT1ifX0KVy5mSi5wcm90b3R5cGU9ewpl
+bzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYS5vcGVuKGIsYywhMCl9LAokaWZKOjF9Clcud2EucHJv
+dG90eXBlPXt9ClcuU2cucHJvdG90eXBlPXskaVNnOjF9ClcudzcucHJvdG90eXBlPXsKZ0RyOmZ1bmN0
+aW9uKGEpe2lmKCJvcmlnaW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILkVqKGEucHJvdG9j
+b2wpKyIvLyIrSC5FaihhLmhvc3QpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGl3
+NzoxfQpXLkFqLnByb3RvdHlwZT17JGlBajoxfQpXLmU3LnByb3RvdHlwZT17CmdyODpmdW5jdGlvbihh
+KXt2YXIgcz10aGlzLmEscj1zLmNoaWxkTm9kZXMubGVuZ3RoCmlmKHI9PT0wKXRocm93IEguYihQLlBW
+KCJObyBlbGVtZW50cyIpKQppZihyPjEpdGhyb3cgSC5iKFAuUFYoIk1vcmUgdGhhbiBvbmUgZWxlbWVu
+dCIpKQpzPXMuZmlyc3RDaGlsZApzLnRvU3RyaW5nCnJldHVybiBzfSwKRlY6ZnVuY3Rpb24oYSxiKXt2
+YXIgcyxyLHEscCxvCnQuZWguYShiKQppZihiIGluc3RhbmNlb2YgVy5lNyl7cz1iLmEKcj10aGlzLmEK
+aWYocyE9PXIpZm9yKHE9cy5jaGlsZE5vZGVzLmxlbmd0aCxwPTA7cDxxOysrcCl7bz1zLmZpcnN0Q2hp
+bGQKby50b1N0cmluZwpyLmFwcGVuZENoaWxkKG8pfXJldHVybn1mb3Iocz1iLmdtKGIpLHI9dGhpcy5h
+O3MuRigpOylyLmFwcGVuZENoaWxkKHMuZ2woKSl9LApZNTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscgp0
+LkEuYShjKQpzPXRoaXMuYQpyPXMuY2hpbGROb2RlcwppZihiPDB8fGI+PXIubGVuZ3RoKXJldHVybiBI
+Lk9IKHIsYikKcy5yZXBsYWNlQ2hpbGQoYyxyW2JdKX0sCmdtOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMu
+YS5jaGlsZE5vZGVzCnJldHVybiBuZXcgVy5XOShzLHMubGVuZ3RoLEgueihzKS5DKCJXOTxHbS5FPiIp
+KX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2hpbGROb2Rlcy5sZW5ndGh9LApxOmZ1bmN0
+aW9uKGEsYil7dmFyIHMKSC51UChiKQpzPXRoaXMuYS5jaGlsZE5vZGVzCmlmKGI8MHx8Yj49cy5sZW5n
+dGgpcmV0dXJuIEguT0gocyxiKQpyZXR1cm4gc1tiXX19ClcudUgucHJvdG90eXBlPXsKd2c6ZnVuY3Rp
+b24oYSl7dmFyIHM9YS5wYXJlbnROb2RlCmlmKHMhPW51bGwpcy5yZW1vdmVDaGlsZChhKX0sCkQ0OmZ1
+bmN0aW9uKGEpe3ZhciBzCmZvcig7cz1hLmZpcnN0Q2hpbGQscyE9bnVsbDspYS5yZW1vdmVDaGlsZChz
+KX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHM9YS5ub2RlVmFsdWUKcmV0dXJuIHM9PW51bGw/dGhpcy5VKGEp
+OnN9LApzYTQ6ZnVuY3Rpb24oYSxiKXthLnRleHRDb250ZW50PWJ9LAptSzpmdW5jdGlvbihhLGIsYyl7
+cmV0dXJuIGEuaW5zZXJ0QmVmb3JlKGIsYyl9LAokaXVIOjF9ClcuQkgucHJvdG90eXBlPXsKZ0E6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKaWYoYj4+PjAh
+PT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4g
+YVtiXX0sClk1OmZ1bmN0aW9uKGEsYixjKXt0LkEuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFz
+c2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sCmd0SDpmdW5jdGlvbihhKXtpZihhLmxl
+bmd0aD4wKXJldHVybiBhWzBdCnRocm93IEguYihQLlBWKCJObyBlbGVtZW50cyIpKX0sCkU6ZnVuY3Rp
+b24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBILk9IKGEsYikKcmV0dXJuIGFbYl19LAok
+aWJROjEsCiRpWGo6MSwKJGljWDoxLAokaXpNOjF9ClcuU04ucHJvdG90eXBlPXt9ClcuZXcucHJvdG90
+eXBlPXskaWV3OjF9ClcubHAucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3Ro
+fX0KVy5UYi5wcm90b3R5cGU9ewpyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyCmlmKCJjcmVhdGVD
+b250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFco
+YSxiLGMsZCkKcz1XLlU5KCI8dGFibGU+IitILkVqKGIpKyI8L3RhYmxlPiIsYyxkKQpyPWRvY3VtZW50
+LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpyLnRvU3RyaW5nCnMudG9TdHJpbmcKbmV3IFcuZTcociku
+RlYoMCxuZXcgVy5lNyhzKSkKcmV0dXJuIHJ9fQpXLkl2LnByb3RvdHlwZT17CnI2OmZ1bmN0aW9uKGEs
+YixjLGQpe3ZhciBzLHIscSxwCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5S
+YW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKcz1kb2N1bWVudApyPXMuY3JlYXRl
+RG9jdW1lbnRGcmFnbWVudCgpCnM9Qy5JZS5yNihzLmNyZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQp
+CnMudG9TdHJpbmcKcz1uZXcgVy5lNyhzKQpxPXMuZ3I4KHMpCnEudG9TdHJpbmcKcz1uZXcgVy5lNyhx
+KQpwPXMuZ3I4KHMpCnIudG9TdHJpbmcKcC50b1N0cmluZwpuZXcgVy5lNyhyKS5GVigwLG5ldyBXLmU3
+KHApKQpyZXR1cm4gcn19ClcuV1AucHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMs
+cixxCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUp
+cmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKcz1kb2N1bWVudApyPXMuY3JlYXRlRG9jdW1lbnRGcmFnbWVu
+dCgpCnM9Qy5JZS5yNihzLmNyZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnMudG9TdHJpbmcKcz1u
+ZXcgVy5lNyhzKQpxPXMuZ3I4KHMpCnIudG9TdHJpbmcKcS50b1N0cmluZwpuZXcgVy5lNyhyKS5GVigw
+LG5ldyBXLmU3KHEpKQpyZXR1cm4gcn19ClcueVkucHJvdG90eXBlPXsKcGs6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciBzLHIKdGhpcy5zYTQoYSxudWxsKQpzPWEuY29udGVudApzLnRvU3RyaW5nCkouYlQocykKcj10
+aGlzLnI2KGEsYixudWxsLGMpCmEuY29udGVudC5hcHBlbmRDaGlsZChyKX0sCllDOmZ1bmN0aW9uKGEs
+Yil7cmV0dXJuIHRoaXMucGsoYSxiLG51bGwpfSwKJGl5WToxfQpXLnc2LnByb3RvdHlwZT17fQpXLks1
+LnByb3RvdHlwZT17ClBvOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1XLlAxKGEub3BlbihiLGMpKQpyZXR1
+cm4gc30sCmdtVzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhdGlvbn0sCnVzOmZ1bmN0aW9uKGEsYil7
+cmV0dXJuIGEuY29uZmlybShiKX0sCiRpSzU6MSwKJGl2NjoxfQpXLkNtLnByb3RvdHlwZT17JGlDbTox
+fQpXLkNRLnByb3RvdHlwZT17JGlDUToxfQpXLnc0LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFy
+IHMscj1hLmxlZnQKci50b1N0cmluZwpyPSJSZWN0YW5nbGUgKCIrSC5FaihyKSsiLCAiCnM9YS50b3AK
+cy50b1N0cmluZwpzPXIrSC5FaihzKSsiKSAiCnI9YS53aWR0aApyLnRvU3RyaW5nCnI9cytILkVqKHIp
+KyIgeCAiCnM9YS5oZWlnaHQKcy50b1N0cmluZwpyZXR1cm4gcitILkVqKHMpfSwKRE46ZnVuY3Rpb24o
+YSxiKXt2YXIgcyxyCmlmKGI9PW51bGwpcmV0dXJuITEKaWYodC5xLmIoYikpe3M9YS5sZWZ0CnMudG9T
+dHJpbmcKcj1iLmxlZnQKci50b1N0cmluZwppZihzPT09cil7cz1hLnRvcApzLnRvU3RyaW5nCnI9Yi50
+b3AKci50b1N0cmluZwppZihzPT09cil7cz1hLndpZHRoCnMudG9TdHJpbmcKcj1iLndpZHRoCnIudG9T
+dHJpbmcKaWYocz09PXIpe3M9YS5oZWlnaHQKcy50b1N0cmluZwpyPWIuaGVpZ2h0CnIudG9TdHJpbmcK
+cj1zPT09cgpzPXJ9ZWxzZSBzPSExfWVsc2Ugcz0hMX1lbHNlIHM9ITF9ZWxzZSBzPSExCnJldHVybiBz
+fSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPWEubGVmdApwLnRvU3RyaW5nCnA9Qy5DRC5naU8o
+cCkKcz1hLnRvcApzLnRvU3RyaW5nCnM9Qy5DRC5naU8ocykKcj1hLndpZHRoCnIudG9TdHJpbmcKcj1D
+LkNELmdpTyhyKQpxPWEuaGVpZ2h0CnEudG9TdHJpbmcKcmV0dXJuIFcuckUocCxzLHIsQy5DRC5naU8o
+cSkpfX0KVy5yaC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1
+bmN0aW9uKGEsYil7SC51UChiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLkNm
+KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTU6ZnVuY3Rpb24oYSxiLGMpe3QuQS5h
+KGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3Qu
+IikpfSwKRTpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpy
+ZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5jZi5wcm90b3R5cGU9
+ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbwp0LmVBLmEoYikKZm9yKHM9dGhpcy5ndmMoKSxy
+PXMubGVuZ3RoLHE9dGhpcy5hLHA9MDtwPHMubGVuZ3RoO3MubGVuZ3RoPT09cnx8KDAsSC5saykocyks
+KytwKXtvPXNbcF0KYi4kMihvLHEuZ2V0QXR0cmlidXRlKG8pKX19LApndmM6ZnVuY3Rpb24oKXt2YXIg
+cyxyLHEscCxvLG4sbT10aGlzLmEuYXR0cmlidXRlcwptLnRvU3RyaW5nCnM9SC5WTShbXSx0LnMpCmZv
+cihyPW0ubGVuZ3RoLHE9dC5oOSxwPTA7cDxyOysrcCl7aWYocD49bS5sZW5ndGgpcmV0dXJuIEguT0go
+bSxwKQpvPXEuYShtW3BdKQppZihvLm5hbWVzcGFjZVVSST09bnVsbCl7bj1vLm5hbWUKbi50b1N0cmlu
+ZwpDLk5tLmkocyxuKX19cmV0dXJuIHN9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ3ZjKCku
+bGVuZ3RoPT09MH19ClcuaTcucHJvdG90eXBlPXsKeDQ6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vVCh0aGlz
+LmEuaGFzQXR0cmlidXRlKGEpKQpyZXR1cm4gc30sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5h
+LmdldEF0dHJpYnV0ZShILmgoYikpfSwKWTU6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5zZXRBdHRyaWJ1
+dGUoYixjKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmd2YygpLmxlbmd0aH19ClcuU3kucHJv
+dG90eXBlPXsKeDQ6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vVCh0aGlzLmEuYS5oYXNBdHRyaWJ1dGUoImRh
+dGEtIit0aGlzLk9VKGEpKSkKcmV0dXJuIHN9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5h
+LmdldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuT1UoSC5oKGIpKSl9LApZNTpmdW5jdGlvbihhLGIsYyl7
+dGhpcy5hLmEuc2V0QXR0cmlidXRlKCJkYXRhLSIrdGhpcy5PVShiKSxjKX0sCks6ZnVuY3Rpb24oYSxi
+KXt0aGlzLmEuSygwLG5ldyBXLktTKHRoaXMsdC5lQS5hKGIpKSl9LApndmM6ZnVuY3Rpb24oKXt2YXIg
+cz1ILlZNKFtdLHQucykKdGhpcy5hLksoMCxuZXcgVy5BMyh0aGlzLHMpKQpyZXR1cm4gc30sCmdBOmZ1
+bmN0aW9uKGEpe3JldHVybiB0aGlzLmd2YygpLmxlbmd0aH0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4g
+dGhpcy5ndmMoKS5sZW5ndGg9PT0wfSwKeHE6ZnVuY3Rpb24oYSl7dmFyIHMscixxPUguVk0oYS5zcGxp
+dCgiLSIpLHQucykKZm9yKHM9MTtzPHEubGVuZ3RoOysrcyl7cj1xW3NdCmlmKHIubGVuZ3RoPjApQy5O
+bS5ZNShxLHMsclswXS50b1VwcGVyQ2FzZSgpK0ouS1YociwxKSl9cmV0dXJuIEMuTm0uayhxLCIiKX0s
+Ck9VOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8KZm9yKHM9YS5sZW5ndGgscj0wLHE9IiI7cjxzOysr
+cil7cD1hW3JdCm89cC50b0xvd2VyQ2FzZSgpCnE9KHAhPT1vJiZyPjA/cSsiLSI6cSkrb31yZXR1cm4g
+cS5jaGFyQ29kZUF0KDApPT0wP3E6cX19ClcuS1MucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtp
+ZihKLnJZKGEpLm4oYSwiZGF0YS0iKSl0aGlzLmIuJDIodGhpcy5hLnhxKEMueEIueW4oYSw1KSksYil9
+LAokUzoxNX0KVy5BMy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe2lmKEouclkoYSkubihhLCJk
+YXRhLSIpKUMuTm0uaSh0aGlzLmIsdGhpcy5hLnhxKEMueEIueW4oYSw1KSkpfSwKJFM6MTV9ClcuSTQu
+cHJvdG90eXBlPXsKRDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89UC5Mcyh0Lk4pCmZvcihzPXRoaXMu
+YS5jbGFzc05hbWUuc3BsaXQoIiAiKSxyPXMubGVuZ3RoLHE9MDtxPHI7KytxKXtwPUouVDAoc1txXSkK
+aWYocC5sZW5ndGghPT0wKW8uaSgwLHApfXJldHVybiBvfSwKWDpmdW5jdGlvbihhKXt0aGlzLmEuY2xh
+c3NOYW1lPXQuQy5hKGEpLmsoMCwiICIpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5jbGFz
+c0xpc3QubGVuZ3RofSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2xhc3NMaXN0Lmxlbmd0
+aD09PTB9LApnb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5jbGFzc0xpc3QubGVuZ3RoIT09MH0s
+ClYxOmZ1bmN0aW9uKGEpe3RoaXMuYS5jbGFzc05hbWU9IiJ9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciBz
+PXRoaXMuYS5jbGFzc0xpc3QuY29udGFpbnMoYikKcmV0dXJuIHN9LAppOmZ1bmN0aW9uKGEsYil7dmFy
+IHMscgpILmgoYikKcz10aGlzLmEuY2xhc3NMaXN0CnI9cy5jb250YWlucyhiKQpzLmFkZChiKQpyZXR1
+cm4hcn0sClI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEKaWYodHlwZW9mIGI9PSJzdHJpbmciKXtzPXRo
+aXMuYS5jbGFzc0xpc3QKcj1zLmNvbnRhaW5zKGIpCnMucmVtb3ZlKGIpCnE9cn1lbHNlIHE9ITEKcmV0
+dXJuIHF9LApGVjpmdW5jdGlvbihhLGIpe1cuVE4odGhpcy5hLHQuUS5hKGIpKX19ClcuRmsucHJvdG90
+eXBlPXt9ClcuUk8ucHJvdG90eXBlPXt9ClcuZXUucHJvdG90eXBlPXt9ClcueEMucHJvdG90eXBlPXt9
+Clcudk4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS4kMSh0LkIuYShhKSl9
+LAokUzoyN30KVy5KUS5wcm90b3R5cGU9ewpDWTpmdW5jdGlvbihhKXt2YXIgcwppZigkLm9yLmE9PT0w
+KXtmb3Iocz0wO3M8MjYyOysrcykkLm9yLlk1KDAsQy5jbVtzXSxXLnBTKCkpCmZvcihzPTA7czwxMjsr
+K3MpJC5vci5ZNSgwLEMuQklbc10sVy5WNCgpKX19LAppMDpmdW5jdGlvbihhKXtyZXR1cm4gJC5BTigp
+LnRnKDAsVy5yUyhhKSl9LApFYjpmdW5jdGlvbihhLGIsYyl7dmFyIHM9JC5vci5xKDAsSC5FaihXLnJT
+KGEpKSsiOjoiK2IpCmlmKHM9PW51bGwpcz0kLm9yLnEoMCwiKjo6IitiKQppZihzPT1udWxsKXJldHVy
+biExCnJldHVybiBILnk4KHMuJDQoYSxiLGMsdGhpcykpfSwKJGlrRjoxfQpXLkdtLnByb3RvdHlwZT17
+CmdtOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5XOShhLHRoaXMuZ0EoYSksSC56KGEpLkMoIlc5PEdt
+LkU+IikpfX0KVy52RC5wcm90b3R5cGU9ewppMDpmdW5jdGlvbihhKXtyZXR1cm4gQy5ObS5Wcih0aGlz
+LmEsbmV3IFcuVXYoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBDLk5tLlZyKHRoaXMuYSxu
+ZXcgVy5FZyhhLGIsYykpfSwKJGlrRjoxfQpXLlV2LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0LkUuYShhKS5pMCh0aGlzLmEpfSwKJFM6MTZ9ClcuRWcucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHQuRS5hKGEpLkViKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjE2fQpXLm02
+LnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscQp0aGlzLmEuRlYoMCxjKQpz
+PWIuZXYoMCxuZXcgVy5FbygpKQpyPWIuZXYoMCxuZXcgVy5XaygpKQp0aGlzLmIuRlYoMCxzKQpxPXRo
+aXMuYwpxLkZWKDAsQy54RCkKcS5GVigwLHIpfSwKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS50
+ZygwLFcuclMoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPXRoaXMscj1XLnJTKGEpLHE9cy5j
+CmlmKHEudGcoMCxILkVqKHIpKyI6OiIrYikpcmV0dXJuIHMuZC5EdChjKQplbHNlIGlmKHEudGcoMCwi
+Kjo6IitiKSlyZXR1cm4gcy5kLkR0KGMpCmVsc2V7cT1zLmIKaWYocS50ZygwLEguRWoocikrIjo6Iiti
+KSlyZXR1cm4hMAplbHNlIGlmKHEudGcoMCwiKjo6IitiKSlyZXR1cm4hMAplbHNlIGlmKHEudGcoMCxI
+LkVqKHIpKyI6OioiKSlyZXR1cm4hMAplbHNlIGlmKHEudGcoMCwiKjo6KiIpKXJldHVybiEwfXJldHVy
+biExfSwKJGlrRjoxfQpXLkVvLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiFDLk5tLnRn
+KEMuQkksSC5oKGEpKX0sCiRTOjZ9ClcuV2sucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEMuTm0udGcoQy5CSSxILmgoYSkpfSwKJFM6Nn0KVy5jdC5wcm90b3R5cGU9ewpFYjpmdW5jdGlvbihh
+LGIsYyl7aWYodGhpcy5qRihhLGIsYykpcmV0dXJuITAKaWYoYj09PSJ0ZW1wbGF0ZSImJmM9PT0iIily
+ZXR1cm4hMAppZihhLmdldEF0dHJpYnV0ZSgidGVtcGxhdGUiKT09PSIiKXJldHVybiB0aGlzLmUudGco
+MCxiKQpyZXR1cm4hMX19ClcuSUEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIlRFTVBM
+QVRFOjoiK0guRWooSC5oKGEpKX0sCiRTOjV9ClcuT3cucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7
+dmFyIHMKaWYodC5ldy5iKGEpKXJldHVybiExCnM9dC5nNy5iKGEpCmlmKHMmJlcuclMoYSk9PT0iZm9y
+ZWlnbk9iamVjdCIpcmV0dXJuITEKaWYocylyZXR1cm4hMApyZXR1cm4hMX0sCkViOmZ1bmN0aW9uKGEs
+YixjKXtpZihiPT09ImlzInx8Qy54Qi5uKGIsIm9uIikpcmV0dXJuITEKcmV0dXJuIHRoaXMuaTAoYSl9
+LAokaWtGOjF9ClcuVzkucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciBzPXRoaXMscj1zLmMrMSxx
+PXMuYgppZihyPHEpe3Muc3AoSi54OShzLmEscikpCnMuYz1yCnJldHVybiEwfXMuc3AobnVsbCkKcy5j
+PXEKcmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApzcDpmdW5jdGlvbihhKXt0
+aGlzLmQ9dGhpcy4kdGkuQygiMT8iKS5hKGEpfSwKJGlBbjoxfQpXLmRXLnByb3RvdHlwZT17JGlEMDox
+LCRpdjY6MX0KVy5tay5wcm90b3R5cGU9eyRpeTA6MX0KVy5Lby5wcm90b3R5cGU9ewpQbjpmdW5jdGlv
+bihhKXt2YXIgcz10aGlzLHI9bmV3IFcuZm0ocykKcy5iPSExCnIuJDIoYSxudWxsKQpmb3IoO3MuYjsp
+e3MuYj0hMQpyLiQyKGEsbnVsbCl9fSwKRVA6ZnVuY3Rpb24oYSxiKXt2YXIgcz10aGlzLmI9ITAKaWYo
+YiE9bnVsbD9iIT09YS5wYXJlbnROb2RlOnMpSi5MdChhKQplbHNlIGIucmVtb3ZlQ2hpbGQoYSl9LApJ
+NDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbj0hMCxtPW51bGwsbD1udWxsCnRyeXttPUouaWco
+YSkKbD1tLmEuZ2V0QXR0cmlidXRlKCJpcyIpCnQuaC5hKGEpCnM9ZnVuY3Rpb24oYyl7aWYoIShjLmF0
+dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApKXJldHVybiB0cnVlCmlmKGMuaWQ9PSdsYXN0
+Q2hpbGQnfHxjLm5hbWU9PSdsYXN0Q2hpbGQnfHxjLmlkPT0ncHJldmlvdXNTaWJsaW5nJ3x8Yy5uYW1l
+PT0ncHJldmlvdXNTaWJsaW5nJ3x8Yy5pZD09J2NoaWxkcmVuJ3x8Yy5uYW1lPT0nY2hpbGRyZW4nKXJl
+dHVybiB0cnVlCnZhciBrPWMuY2hpbGROb2RlcwppZihjLmxhc3RDaGlsZCYmYy5sYXN0Q2hpbGQhPT1r
+W2subGVuZ3RoLTFdKXJldHVybiB0cnVlCmlmKGMuY2hpbGRyZW4paWYoIShjLmNoaWxkcmVuIGluc3Rh
+bmNlb2YgSFRNTENvbGxlY3Rpb258fGMuY2hpbGRyZW4gaW5zdGFuY2VvZiBOb2RlTGlzdCkpcmV0dXJu
+IHRydWUKdmFyIGo9MAppZihjLmNoaWxkcmVuKWo9Yy5jaGlsZHJlbi5sZW5ndGgKZm9yKHZhciBpPTA7
+aTxqO2krKyl7dmFyIGg9Yy5jaGlsZHJlbltpXQppZihoLmlkPT0nYXR0cmlidXRlcyd8fGgubmFtZT09
+J2F0dHJpYnV0ZXMnfHxoLmlkPT0nbGFzdENoaWxkJ3x8aC5uYW1lPT0nbGFzdENoaWxkJ3x8aC5pZD09
+J3ByZXZpb3VzU2libGluZyd8fGgubmFtZT09J3ByZXZpb3VzU2libGluZyd8fGguaWQ9PSdjaGlsZHJl
+bid8fGgubmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZX1yZXR1cm4gZmFsc2V9KGEpCm49SC5vVChz
+KT8hMDohKGEuYXR0cmlidXRlcyBpbnN0YW5jZW9mIE5hbWVkTm9kZU1hcCl9Y2F0Y2gocCl7SC5SdShw
+KX1yPSJlbGVtZW50IHVucHJpbnRhYmxlIgp0cnl7cj1KLmooYSl9Y2F0Y2gocCl7SC5SdShwKX10cnl7
+cT1XLnJTKGEpCnRoaXMua1IodC5oLmEoYSksYixuLHIscSx0LmYuYShtKSxILmsobCkpfWNhdGNoKHAp
+e2lmKEguUnUocCkgaW5zdGFuY2VvZiBQLnUpdGhyb3cgcAplbHNle3RoaXMuRVAoYSxiKQp3aW5kb3cK
+bz0iUmVtb3ZpbmcgY29ycnVwdGVkIGVsZW1lbnQgIitILkVqKHIpCmlmKHR5cGVvZiBjb25zb2xlIT0i
+dW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKG8pfX19LAprUjpmdW5jdGlvbihhLGIsYyxkLGUs
+ZixnKXt2YXIgcyxyLHEscCxvLG4sbT10aGlzCmlmKGMpe20uRVAoYSxiKQp3aW5kb3cKcz0iUmVtb3Zp
+bmcgZWxlbWVudCBkdWUgdG8gY29ycnVwdGVkIGF0dHJpYnV0ZXMgb24gPCIrZCsiPiIKaWYodHlwZW9m
+IGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocykKcmV0dXJufWlmKCFtLmEu
+aTAoYSkpe20uRVAoYSxiKQp3aW5kb3cKcz0iUmVtb3ZpbmcgZGlzYWxsb3dlZCBlbGVtZW50IDwiK0gu
+RWooZSkrIj4gZnJvbSAiK0guRWooYikKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRv
+dy5jb25zb2xlLndhcm4ocykKcmV0dXJufWlmKGchPW51bGwpaWYoIW0uYS5FYihhLCJpcyIsZykpe20u
+RVAoYSxiKQp3aW5kb3cKcz0iUmVtb3ZpbmcgZGlzYWxsb3dlZCB0eXBlIGV4dGVuc2lvbiA8IitILkVq
+KGUpKycgaXM9IicrZysnIj4nCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29u
+c29sZS53YXJuKHMpCnJldHVybn1zPWYuZ3ZjKCkKcj1ILlZNKHMuc2xpY2UoMCksSC50NihzKSkKZm9y
+KHE9Zi5ndmMoKS5sZW5ndGgtMSxzPWYuYTtxPj0wOy0tcSl7aWYocT49ci5sZW5ndGgpcmV0dXJuIEgu
+T0gocixxKQpwPXJbcV0Kbz1tLmEKbj1KLmNIKHApCkguaChwKQppZighby5FYihhLG4scy5nZXRBdHRy
+aWJ1dGUocCkpKXt3aW5kb3cKbz0iUmVtb3ZpbmcgZGlzYWxsb3dlZCBhdHRyaWJ1dGUgPCIrSC5Faihl
+KSsiICIrcCsnPSInK0guRWoocy5nZXRBdHRyaWJ1dGUocCkpKyciPicKaWYodHlwZW9mIGNvbnNvbGUh
+PSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4obykKcy5yZW1vdmVBdHRyaWJ1dGUocCl9fWlm
+KHQuYVcuYihhKSl7cz1hLmNvbnRlbnQKcy50b1N0cmluZwptLlBuKHMpfX0sCiRpb246MX0KVy5mbS5w
+cm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtPXRoaXMuYQpzd2l0Y2go
+YS5ub2RlVHlwZSl7Y2FzZSAxOm0uSTQoYSxiKQpicmVhawpjYXNlIDg6Y2FzZSAxMTpjYXNlIDM6Y2Fz
+ZSA0OmJyZWFrCmRlZmF1bHQ6bS5FUChhLGIpfXM9YS5sYXN0Q2hpbGQKZm9yKHE9dC5BO251bGwhPXM7
+KXtyPW51bGwKdHJ5e3I9cy5wcmV2aW91c1NpYmxpbmcKaWYociE9bnVsbCl7cD1yLm5leHRTaWJsaW5n
+Cm89cwpvPXA9PW51bGw/byE9bnVsbDpwIT09bwpwPW99ZWxzZSBwPSExCmlmKHApe3A9UC5QVigiQ29y
+cnVwdCBIVE1MIikKdGhyb3cgSC5iKHApfX1jYXRjaChuKXtILlJ1KG4pCnA9cS5hKHMpCm0uYj0hMApv
+PXAucGFyZW50Tm9kZQpvPWE9PW51bGw/byE9bnVsbDphIT09bwppZihvKXtvPXAucGFyZW50Tm9kZQpp
+ZihvIT1udWxsKW8ucmVtb3ZlQ2hpbGQocCl9ZWxzZSBhLnJlbW92ZUNoaWxkKHApCnM9bnVsbApyPWEu
+bGFzdENoaWxkfWlmKHMhPW51bGwpdGhpcy4kMihzLGEpCnM9cn19LAokUzozMH0KVy5MZS5wcm90b3R5
+cGU9e30KVy5LNy5wcm90b3R5cGU9e30KVy5yQi5wcm90b3R5cGU9e30KVy5YVy5wcm90b3R5cGU9e30K
+Vy5vYS5wcm90b3R5cGU9e30KUC5pSi5wcm90b3R5cGU9ewpWSDpmdW5jdGlvbihhKXt2YXIgcyxyPXRo
+aXMuYSxxPXIubGVuZ3RoCmZvcihzPTA7czxxOysrcylpZihyW3NdPT09YSlyZXR1cm4gcwpDLk5tLmko
+cixhKQpDLk5tLmkodGhpcy5iLG51bGwpCnJldHVybiBxfSwKUHY6ZnVuY3Rpb24oYSl7dmFyIHMscixx
+LHA9dGhpcyxvPXt9CmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoSC5sKGEpKXJldHVybiBhCmlmKHR5cGVv
+ZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYSBp
+bnN0YW5jZW9mIFAuaVApcmV0dXJuIG5ldyBEYXRlKGEuYSkKaWYodC5mdi5iKGEpKXRocm93IEguYihQ
+LlNZKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIFJlZ0V4cCIpKQppZih0LmM4LmIoYSkpcmV0dXJuIGEKaWYo
+dC53LmIoYSkpcmV0dXJuIGEKaWYodC5JLmIoYSkpcmV0dXJuIGEKcz10LmRFLmIoYSl8fCExCmlmKHMp
+cmV0dXJuIGEKaWYodC5mLmIoYSkpe3I9cC5WSChhKQpzPXAuYgppZihyPj1zLmxlbmd0aClyZXR1cm4g
+SC5PSChzLHIpCnE9by5hPXNbcl0KaWYocSE9bnVsbClyZXR1cm4gcQpxPXt9Cm8uYT1xCkMuTm0uWTUo
+cyxyLHEpCmEuSygwLG5ldyBQLmpnKG8scCkpCnJldHVybiBvLmF9aWYodC5qLmIoYSkpe3I9cC5WSChh
+KQpvPXAuYgppZihyPj1vLmxlbmd0aClyZXR1cm4gSC5PSChvLHIpCnE9b1tyXQppZihxIT1udWxsKXJl
+dHVybiBxCnJldHVybiBwLmVrKGEscil9aWYodC5lSC5iKGEpKXtyPXAuVkgoYSkKcz1wLmIKaWYocj49
+cy5sZW5ndGgpcmV0dXJuIEguT0gocyxyKQpxPW8uYj1zW3JdCmlmKHEhPW51bGwpcmV0dXJuIHEKcT17
+fQpvLmI9cQpDLk5tLlk1KHMscixxKQpwLmltKGEsbmV3IFAuVGEobyxwKSkKcmV0dXJuIG8uYn10aHJv
+dyBILmIoUC5TWSgic3RydWN0dXJlZCBjbG9uZSBvZiBvdGhlciB0eXBlIikpfSwKZWs6ZnVuY3Rpb24o
+YSxiKXt2YXIgcyxyPUouVTYoYSkscT1yLmdBKGEpLHA9bmV3IEFycmF5KHEpCkMuTm0uWTUodGhpcy5i
+LGIscCkKZm9yKHM9MDtzPHE7KytzKUMuTm0uWTUocCxzLHRoaXMuUHYoci5xKGEscykpKQpyZXR1cm4g
+cH19ClAuamcucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuYVthXT10aGlzLmIuUHYo
+Yil9LAokUzozMX0KUC5UYS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS5iW2FdPXRo
+aXMuYi5QdihiKX0sCiRTOjE3fQpQLkJmLnByb3RvdHlwZT17CmltOmZ1bmN0aW9uKGEsYil7dmFyIHMs
+cixxLHAKdC5iOC5hKGIpCmZvcihzPU9iamVjdC5rZXlzKGEpLHI9cy5sZW5ndGgscT0wO3E8cjsrK3Ep
+e3A9c1txXQpiLiQyKHAsYVtwXSl9fX0KUC5Bcy5wcm90b3R5cGU9ewpWOmZ1bmN0aW9uKGEpe3ZhciBz
+CkguaChhKQpzPSQuaEcoKS5iCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILnYoSC50TChhKSkKaWYocy50
+ZXN0KGEpKXJldHVybiBhCnRocm93IEguYihQLkwzKGEsInZhbHVlIiwiTm90IGEgdmFsaWQgY2xhc3Mg
+dG9rZW4iKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLkQoKS5rKDAsIiAiKX0sCmdtOmZ1bmN0
+aW9uKGEpe3ZhciBzPXRoaXMuRCgpCnJldHVybiBQLnJqKHMscy5yLEguTGgocykuYyl9LApnbDA6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIHRoaXMuRCgpLmE9PT0wfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
+LkQoKS5hIT09MH0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLkQoKS5hfSwKdGc6ZnVuY3Rpb24o
+YSxiKXt0aGlzLlYoYikKcmV0dXJuIHRoaXMuRCgpLnRnKDAsYil9LAppOmZ1bmN0aW9uKGEsYil7dmFy
+IHMKSC5oKGIpCnRoaXMuVihiKQpzPXRoaXMuT1MobmV3IFAuR0UoYikpCnJldHVybiBILnk4KHM9PW51
+bGw/ITE6cyl9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZih0eXBlb2YgYiE9InN0cmluZyIpcmV0
+dXJuITEKdGhpcy5WKGIpCnM9dGhpcy5EKCkKcj1zLlIoMCxiKQp0aGlzLlgocykKcmV0dXJuIHJ9LApG
+VjpmdW5jdGlvbihhLGIpe3RoaXMuT1MobmV3IFAuTjcodGhpcyx0LlEuYShiKSkpfSwKZVI6ZnVuY3Rp
+b24oYSxiKXt2YXIgcz10aGlzLkQoKQpyZXR1cm4gSC5iSyhzLGIsSC5MaChzKS5DKCJsZi5FIikpfSwK
+RTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLkQoKS5FKDAsYil9LApWMTpmdW5jdGlvbihhKXt0aGlz
+Lk9TKG5ldyBQLnVRKCkpfSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHMscgp0LmJVLmEoYSkKcz10aGlzLkQo
+KQpyPWEuJDEocykKdGhpcy5YKHMpCnJldHVybiByfX0KUC5HRS5wcm90b3R5cGU9ewokMTpmdW5jdGlv
+bihhKXtyZXR1cm4gdC5DLmEoYSkuaSgwLHRoaXMuYSl9LAokUzozM30KUC5ONy5wcm90b3R5cGU9ewok
+MTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmIscj1ILnQ2KHMpCnJldHVybiB0LkMuYShhKS5GVigwLG5l
+dyBILmxKKHMsci5DKCJxVSgxKSIpLmEodGhpcy5hLmd1TSgpKSxyLkMoImxKPDEscVU+IikpKX0sCiRT
+OjE4fQpQLnVRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3QuQy5hKGEpCmlmKGEuYT4wKXthLmI9
+YS5jPWEuZD1hLmU9YS5mPW51bGwKYS5hPTAKYS5TKCl9cmV0dXJuIG51bGx9LAokUzoxOH0KUC5oRi5w
+cm90b3R5cGU9eyRpaEY6MX0KUC5QQy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcwp0Llku
+YShhKQpzPWZ1bmN0aW9uKGIsYyxkKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gYihjLGQsdGhpcyxB
+cnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkoYXJndW1lbnRzKSl9fShQLlI0LGEsITEpClAuRG0ocywk
+LncoKSxhKQpyZXR1cm4gc30sCiRTOjR9ClAubXQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0
+dXJuIG5ldyB0aGlzLmEoYSl9LAokUzo0fQpQLlFTLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBuZXcgUC5yNyhhKX0sCiRTOjM1fQpQLm5wLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBuZXcgUC5UeihhLHQuYW0pfSwKJFM6NDV9ClAuVXQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24o
+YSl7cmV0dXJuIG5ldyBQLkU0KGEpfSwKJFM6Mzd9ClAuRTQucHJvdG90eXBlPXsKcTpmdW5jdGlvbihh
+LGIpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIiYmdHlwZW9mIGIhPSJudW1iZXIiKXRocm93IEguYihQLnhZ
+KCJwcm9wZXJ0eSBpcyBub3QgYSBTdHJpbmcgb3IgbnVtIikpCnJldHVybiBQLmRVKHRoaXMuYVtiXSl9
+LApZNTpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGIhPSJzdHJpbmciJiZ0eXBlb2YgYiE9Im51bWJl
+ciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5IGlzIG5vdCBhIFN0cmluZyBvciBudW0iKSkKdGhpcy5h
+W2JdPVAud1koYyl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIGIg
+aW5zdGFuY2VvZiBQLkU0JiZ0aGlzLmE9PT1iLmF9LAp3OmZ1bmN0aW9uKGEpe3ZhciBzLHIKdHJ5e3M9
+U3RyaW5nKHRoaXMuYSkKcmV0dXJuIHN9Y2F0Y2gocil7SC5SdShyKQpzPXRoaXMueGIoMCkKcmV0dXJu
+IHN9fSwKVjc6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyPXRoaXMuYQppZihiPT1udWxsKXM9bnVsbAplbHNl
+e3M9SC50NihiKQpzPVAuQ0gobmV3IEgubEooYixzLkMoIkAoMSkiKS5hKFAuaUcoKSkscy5DKCJsSjwx
+LEA+IikpLCEwLHQueil9cmV0dXJuIFAuZFUoclthXS5hcHBseShyLHMpKX0sCmdpTzpmdW5jdGlvbihh
+KXtyZXR1cm4gMH19ClAucjcucHJvdG90eXBlPXt9ClAuVHoucHJvdG90eXBlPXsKY1A6ZnVuY3Rpb24o
+YSl7dmFyIHM9dGhpcyxyPWE8MHx8YT49cy5nQShzKQppZihyKXRocm93IEguYihQLlRFKGEsMCxzLmdB
+KHMpLG51bGwsbnVsbCkpfSwKcTpmdW5jdGlvbihhLGIpe2lmKEgub2soYikpdGhpcy5jUChiKQpyZXR1
+cm4gdGhpcy4kdGkuYy5hKHRoaXMuVXIoMCxiKSl9LApZNTpmdW5jdGlvbihhLGIsYyl7dGhpcy5jUChi
+KQp0aGlzLmJoKDAsYixjKX0sCmdBOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYS5sZW5ndGgKaWYodHlw
+ZW9mIHM9PT0ibnVtYmVyIiYmcz4+PjA9PT1zKXJldHVybiBzCnRocm93IEguYihQLlBWKCJCYWQgSnNB
+cnJheSBsZW5ndGgiKSl9LAokaWJROjEsCiRpY1g6MSwKJGl6TToxfQpQLmNvLnByb3RvdHlwZT17Clk1
+OmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gdGhpcy5lNCgwLGIsYyl9fQpQLm5kLnByb3RvdHlwZT17JGlu
+ZDoxfQpQLktlLnByb3RvdHlwZT17CkQ6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvPXRoaXMuYS5nZXRB
+dHRyaWJ1dGUoImNsYXNzIiksbj1QLkxzKHQuTikKaWYobz09bnVsbClyZXR1cm4gbgpmb3Iocz1vLnNw
+bGl0KCIgIikscj1zLmxlbmd0aCxxPTA7cTxyOysrcSl7cD1KLlQwKHNbcV0pCmlmKHAubGVuZ3RoIT09
+MCluLmkoMCxwKX1yZXR1cm4gbn0sClg6ZnVuY3Rpb24oYSl7dGhpcy5hLnNldEF0dHJpYnV0ZSgiY2xh
+c3MiLGEuaygwLCIgIikpfX0KUC5oaS5wcm90b3R5cGU9ewpnUDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3
+IFAuS2UoYSl9LApzaGY6ZnVuY3Rpb24oYSxiKXt0aGlzLllDKGEsYil9LApyNjpmdW5jdGlvbihhLGIs
+YyxkKXt2YXIgcyxyLHEscCxvLG4KaWYoZD09bnVsbCl7cz1ILlZNKFtdLHQudikKZD1uZXcgVy52RChz
+KQpDLk5tLmkocyxXLlR3KG51bGwpKQpDLk5tLmkocyxXLkJsKCkpCkMuTm0uaShzLG5ldyBXLk93KCkp
+fWM9bmV3IFcuS28oZCkKcj0nPHN2ZyB2ZXJzaW9uPSIxLjEiPicrSC5FaihiKSsiPC9zdmc+IgpzPWRv
+Y3VtZW50CnE9cy5ib2R5CnEudG9TdHJpbmcKcD1DLlJZLkFIKHEscixjKQpvPXMuY3JlYXRlRG9jdW1l
+bnRGcmFnbWVudCgpCnAudG9TdHJpbmcKcz1uZXcgVy5lNyhwKQpuPXMuZ3I4KHMpCmZvcig7cz1uLmZp
+cnN0Q2hpbGQscyE9bnVsbDspby5hcHBlbmRDaGlsZChzKQpyZXR1cm4gb30sCm56OmZ1bmN0aW9uKGEs
+YixjLGQsZSl7dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBpbnZva2UgaW5zZXJ0QWRqYWNlbnRIdG1sIG9u
+IFNWRy4iKSl9LApnVmw6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLmV1KGEsImNsaWNrIiwhMSx0Lmsp
+fSwKJGloaToxfQpVLmQyLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbz10aGlz
+LG49dC5YLG09dC5fLGw9UC5GbChuLG0pLGs9by5hCmlmKGshPW51bGwpe3M9SC5WTShbXSx0LkcpCmZv
+cihyPWsubGVuZ3RoLHE9MDtxPGsubGVuZ3RoO2subGVuZ3RoPT09cnx8KDAsSC5saykoayksKytxKXtw
+PWtbcV0Kcy5wdXNoKFAuRUYoWyJkZXNjcmlwdGlvbiIscC5hLCJocmVmIixwLmJdLG4sbSkpfWwuWTUo
+MCwiZWRpdHMiLHMpfWwuWTUoMCwiZXhwbGFuYXRpb24iLG8uYikKbC5ZNSgwLCJsaW5lIixvLmMpCmwu
+WTUoMCwiZGlzcGxheVBhdGgiLG8uZCkKbC5ZNSgwLCJ1cmlQYXRoIixvLmUpCm49by5mCmlmKG4hPW51
+bGwpe209SC5WTShbXSx0LkcpCmZvcihrPW4ubGVuZ3RoLHE9MDtxPG4ubGVuZ3RoO24ubGVuZ3RoPT09
+a3x8KDAsSC5saykobiksKytxKW0ucHVzaChuW3FdLkx0KCkpCmwuWTUoMCwidHJhY2VzIixtKX1yZXR1
+cm4gbH19ClUuU2UucHJvdG90eXBlPXsKTHQ6ZnVuY3Rpb24oKXtyZXR1cm4gUC5FRihbImRlc2NyaXB0
+aW9uIix0aGlzLmEsImhyZWYiLHRoaXMuYl0sdC5YLHQuXyl9fQpVLk1sLnByb3RvdHlwZT17Ckx0OmZ1
+bmN0aW9uKCl7cmV0dXJuIFAuRUYoWyJocmVmIix0aGlzLmEsImxpbmUiLHRoaXMuYiwicGF0aCIsdGhp
+cy5jXSx0LlgsdC5fKX19ClUueUQucHJvdG90eXBlPXsKTHQ6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscD1I
+LlZNKFtdLHQuRykKZm9yKHM9dGhpcy5iLHI9cy5sZW5ndGgscT0wO3E8cy5sZW5ndGg7cy5sZW5ndGg9
+PT1yfHwoMCxILmxrKShzKSwrK3EpcC5wdXNoKHNbcV0uTHQoKSkKcmV0dXJuIFAuRUYoWyJkZXNjcmlw
+dGlvbiIsdGhpcy5hLCJlbnRyaWVzIixwXSx0LlgsdC5fKX19ClUud2IucHJvdG90eXBlPXsKTHQ6ZnVu
+Y3Rpb24oKXt2YXIgcyxyLHEscD10aGlzLG89UC5GbCh0LlgsdC5fKQpvLlk1KDAsImRlc2NyaXB0aW9u
+IixwLmEpCnM9cC5iCmlmKHMhPW51bGwpby5ZNSgwLCJmdW5jdGlvbiIscykKcz1wLmMKaWYocyE9bnVs
+bClvLlk1KDAsImxpbmsiLHMuTHQoKSkKcz1wLmQKaWYocy5sZW5ndGghPT0wKXtyPUgudDYocykKcT1y
+LkMoImxKPDEsWjA8cVUqLE1oKj4qPiIpCm8uWTUoMCwiaGludEFjdGlvbnMiLFAuWTEobmV3IEgubEoo
+cyxyLkMoIlowPHFVKixNaCo+KigxKSIpLmEobmV3IFUuYjAoKSkscSksITAscS5DKCJhTC5FIikpKX1y
+ZXR1cm4gb319ClUuYU4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIFIubnoodC50LmEo
+YSkpfSwKJFM6Mzh9ClUuYjAucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHQuYVguYShh
+KS5MdCgpfSwKJFM6Mzl9CkIuajgucHJvdG90eXBlPXsKTHQ6ZnVuY3Rpb24oKXtyZXR1cm4gUC5FRihb
+ImxpbmUiLHRoaXMuYSwiZXhwbGFuYXRpb24iLHRoaXMuYiwib2Zmc2V0Iix0aGlzLmNdLHQuWCx0Ll8p
+fX0KQi5xcC5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixtLGw9dGhpcyxr
+PXQuWCxqPVAuRmwoayx0LmRwKQpmb3Iocz1sLmQscz1zLmdQdShzKSxzPXMuZ20ocykscj10Ll8scT10
+Lkc7cy5GKCk7KXtwPXMuZ2woKQpvPXAuYQpuPUguVk0oW10scSkKZm9yKHA9Si5JVChwLmIpO3AuRigp
+Oyl7bT1wLmdsKCkKbi5wdXNoKFAuRUYoWyJsaW5lIixtLmEsImV4cGxhbmF0aW9uIixtLmIsIm9mZnNl
+dCIsbS5jXSxrLHIpKX1qLlk1KDAsbyxuKX1yZXR1cm4gUC5FRihbInJlZ2lvbnMiLGwuYSwibmF2aWdh
+dGlvbkNvbnRlbnQiLGwuYiwic291cmNlQ29kZSIsbC5jLCJlZGl0cyIsal0sayxyKX19ClQubVEucHJv
+dG90eXBlPXt9CkwuZS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbQp0
+LmFMLmEoYSkKcz13aW5kb3cubG9jYXRpb24ucGF0aG5hbWUKcj1MLkc2KHdpbmRvdy5sb2NhdGlvbi5o
+cmVmKQpxPUwuYUsod2luZG93LmxvY2F0aW9uLmhyZWYpCkwuR2UoKQppZihzIT09Ii8iJiZzIT09Si5U
+MChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50KSlMLkc3KHMscixxLCEw
+LG5ldyBMLlZXKHMscixxKSkKcD1kb2N1bWVudApvPUoucUYocC5xdWVyeVNlbGVjdG9yKCIuYXBwbHkt
+bWlncmF0aW9uIikpCm49by4kdGkKbT1uLkMoIn4oMSk/IikuYShuZXcgTC5vWigpKQp0LlouYShudWxs
+KQpXLkpFKG8uYSxvLmIsbSwhMSxuLmMpCm49Si5xRihwLnF1ZXJ5U2VsZWN0b3IoIi5yZXJ1bi1taWdy
+YXRpb24iKSkKbT1uLiR0aQpXLkpFKG4uYSxuLmIsbS5DKCJ+KDEpPyIpLmEobmV3IEwuSGkoKSksITEs
+bS5jKQptPUoucUYocC5xdWVyeVNlbGVjdG9yKCIucmVwb3J0LXByb2JsZW0iKSkKbj1tLiR0aQpXLkpF
+KG0uYSxtLmIsbi5DKCJ+KDEpPyIpLmEobmV3IEwuQlQoKSksITEsbi5jKQpwPUoucUYocC5xdWVyeVNl
+bGVjdG9yKCIucG9wdXAtcGFuZSAuY2xvc2UiKSkKbj1wLiR0aQpXLkpFKHAuYSxwLmIsbi5DKCJ+KDEp
+PyIpLmEobmV3IEwuUFkoKSksITEsbi5jKQpuPUoucUYoJC5jMCgpKQpwPW4uJHRpClcuSkUobi5hLG4u
+YixwLkMoIn4oMSk/IikuYShuZXcgTC51OCgpKSwhMSxwLmMpfSwKJFM6MTl9CkwuVlcucHJvdG90eXBl
+PXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjJ9Ckwub1oucHJv
+dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbwp0Lk8uYShhKQppZihILm9UKEMub2wu
+dXMod2luZG93LCJUaGlzIHdpbGwgYXBwbHkgdGhlIGNoYW5nZXMgeW91J3ZlIHByZXZpZXdlZCB0byB5
+b3VyIHdvcmtpbmcgZGlyZWN0b3J5LiBJdCBpcyByZWNvbW1lbmRlZCB5b3UgY29tbWl0IGFueSBjaGFu
+Z2VzIHlvdSBtYWRlIGJlZm9yZSBkb2luZyB0aGlzLiIpKSl7cz1ILlZNKFtdLHQuRykKZm9yKHI9JC5J
+UixxPXIubGVuZ3RoLHA9MDtwPHIubGVuZ3RoO3IubGVuZ3RoPT09cXx8KDAsSC5saykociksKytwKXMu
+cHVzaChyW3BdLkx0KCkpCnM9TC50eSgiL2FwcGx5LW1pZ3JhdGlvbiIsUC5FRihbIm5hdmlnYXRpb25U
+cmVlIixzXSx0LlgsdC5kcCkpLlc3KG5ldyBMLmpyKCksdC5QKQpvPW5ldyBMLnFsKCkKdC5iNy5hKG51
+bGwpCnI9cy4kdGkKcT0kLlgzCmlmKHEhPT1DLk5VKW89UC5WSChvLHEpCnMueGYobmV3IFAuRmUobmV3
+IFAudnMocSxyKSwyLG51bGwsbyxyLkMoIkA8MT4iKS5LcShyLmMpLkMoIkZlPDEsMj4iKSkpfX0sCiRT
+OjF9CkwuanIucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMKdC50LmEoYSkKcz1kb2N1bWVu
+dC5ib2R5CnMuY2xhc3NMaXN0LnJlbW92ZSgicHJvcG9zZWQiKQpzLmNsYXNzTGlzdC5hZGQoImFwcGxp
+ZWQiKX0sCiRTOjQyfQpMLnFsLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5DMigiQ291bGQg
+bm90IGFwcGx5IG1pZ3JhdGlvbiIsYSxiKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjE3fQpMLkhpLnByb3Rv
+dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnhuKHQuTy5hKGEpKX0sCnhuOmZ1bmN0aW9u
+KGEpe3ZhciBzPTAscj1QLkZYKHQuUCkscT0xLHAsbz1bXSxuLG0sbCxrLGoKdmFyICRhc3luYyQkMT1Q
+Lmx6KGZ1bmN0aW9uKGIsYyl7aWYoYj09PTEpe3A9YwpzPXF9d2hpbGUodHJ1ZSlzd2l0Y2gocyl7Y2Fz
+ZSAwOnE9Mwpkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoInJlcnVubmluZyIpCnM9NgpyZXR1cm4g
+UC5qUShMLnR5KCIvcmVydW4tbWlncmF0aW9uIixudWxsKSwkYXN5bmMkJDEpCmNhc2UgNjpuPWMKaWYo
+SC5vVChILnk4KEoueDkobiwic3VjY2VzcyIpKSkpd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpCmVsc2Ug
+TC5LMCh0LmVFLmEoSi54OShuLCJlcnJvcnMiKSkpCm8ucHVzaCg1KQpzPTQKYnJlYWsKY2FzZSAzOnE9
+MgpqPXAKbT1ILlJ1KGopCmw9SC50cyhqKQpMLkMyKCJGYWlsZWQgdG8gcmVydW4gbWlncmF0aW9uIixt
+LGwpCm8ucHVzaCg1KQpzPTQKYnJlYWsKY2FzZSAyOm89WzFdCmNhc2UgNDpxPTEKZG9jdW1lbnQuYm9k
+eS5jbGFzc0xpc3QucmVtb3ZlKCJyZXJ1bm5pbmciKQpzPW8ucG9wKCkKYnJlYWsKY2FzZSA1OnJldHVy
+biBQLnlDKG51bGwscikKY2FzZSAxOnJldHVybiBQLmYzKHAscil9fSkKcmV0dXJuIFAuREkoJGFzeW5j
+JCQxLHIpfSwKJFM6MjB9CkwuQlQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dC5PLmEoYSkKQy5v
+bC5Qbyh3aW5kb3csUC5YZCgiaHR0cHMiLCJnaXRodWIuY29tIiwiZGFydC1sYW5nL3Nkay9pc3N1ZXMv
+bmV3IixQLkVGKFsidGl0bGUiLCJDdXN0b21lci1yZXBvcnRlZCBpc3N1ZSB3aXRoIE5OQkQgbWlncmF0
+aW9uIHRvb2wiLCJsYWJlbHMiLHUuZCwiYm9keSIsIiMjIyMgU3RlcHMgdG8gcmVwcm9kdWNlXG5cbiMj
+IyMgV2hhdCBkaWQgeW91IGV4cGVjdCB0byBoYXBwZW4/XG5cbiMjIyMgV2hhdCBhY3R1YWxseSBoYXBw
+ZW5lZD9cblxuX1NjcmVlbnNob3RzIGFyZSBhcHByZWNpYXRlZF9cblxuKipEYXJ0IFNESyB2ZXJzaW9u
+Kio6ICIrSC5Faihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic2RrLXZlcnNpb24iKS50ZXh0Q29udGVu
+dCkrIlxuXG5UaGFua3MgZm9yIGZpbGluZyFcbiJdLHQuWCx0LnopKS5nbkQoKSwicmVwb3J0LXByb2Js
+ZW0iKX0sCiRTOjF9CkwuUFkucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMKdC5PLmEoYSkK
+cz1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucG9wdXAtcGFuZSIpLnN0eWxlCnMuZGlzcGxheT0ibm9u
+ZSIKcmV0dXJuIm5vbmUifSwKJFM6NDR9CkwudTgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFy
+IHMscixxLHAKdC5PLmEoYSkKcz0kLkQ5KCkuaW5uZXJUZXh0CnI9dC5nLmEoZG9jdW1lbnQucXVlcnlT
+ZWxlY3RvcignLm5hdi1wYW5lbCBbZGF0YS1uYW1lKj0iJytILkVqKHMpKyciXScpLnBhcmVudE5vZGUp
+CnE9ci5xdWVyeVNlbGVjdG9yKCIuc3RhdHVzLWljb24iKQpwPUwubUgoJC5JUixzKQppZihwIGluc3Rh
+bmNlb2YgTC5jRCYmSC5vVChwLngpKXtMLk90KHApCkwueG4ocSxwKQpMLkFSKHIscCl9fSwKJFM6MX0K
+TC5MLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIscQp0LmFMLmEoYSkKcz13aW5kb3cu
+bG9jYXRpb24ucGF0aG5hbWUKcj1MLkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpxPUwuYUsod2luZG93
+LmxvY2F0aW9uLmhyZWYpCmlmKHMubGVuZ3RoPjEpTC5HNyhzLHIscSwhMSxudWxsKQplbHNle0wuQkUo
+cyxCLndSKCksITApCkwuQlgoIiZuYnNwOyIsbnVsbCl9fSwKJFM6MTl9CkwuV3gucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9ImNvbGxhcHNlZCIKdC5PLmEoYSkKcz10aGlzLmEKcj1K
+LllFKHMpCnE9dGhpcy5iCmlmKCFyLmdQKHMpLnRnKDAscCkpe3IuZ1AocykuaSgwLHApCkouZFIocSku
+aSgwLHApfWVsc2V7ci5nUChzKS5SKDAscCkKSi5kUihxKS5SKDAscCl9fSwKJFM6MX0KTC5BTy5wcm90
+b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz1KLnFGKHQuZy5hKGEpKSxyPXMuJHRpLHE9ci5DKCJ+
+KDEpPyIpLmEobmV3IEwuZE4odGhpcy5hKSkKdC5aLmEobnVsbCkKVy5KRShzLmEscy5iLHEsITEsci5j
+KX0sCiRTOjN9CkwuZE4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEwudDIodC5PLmEo
+YSksdGhpcy5hKX0sCiRTOjd9CkwuSG8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscixx
+CnQuZy5hKGEpCnM9Si5xRihhKQpyPXMuJHRpCnE9ci5DKCJ+KDEpPyIpLmEobmV3IEwueHooYSx0aGlz
+LmEpKQp0LlouYShudWxsKQpXLkpFKHMuYSxzLmIscSwhMSxyLmMpfSwKJFM6M30KTC54ei5wcm90b3R5
+cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcwp0Lk8uYShhKQpzPXRoaXMuYQpMLmhYKHRoaXMuYixQLlFB
+KHMuZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcocykpLk9VKCJvZmZzZXQiKSks
+bnVsbCksUC5RQShzLmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHMpKS5PVSgi
+bGluZSIpKSxudWxsKSl9LAokUzoxfQpMLklDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBz
+PUoucUYodC5nLmEoYSkpLHI9cy4kdGkKci5DKCJ+KDEpPyIpLmEoTC5pUygpKQp0LlouYShudWxsKQpX
+LkpFKHMuYSxzLmIsTC5pUygpLCExLHIuYyl9LAokUzozfQpMLmZDLnByb3RvdHlwZT17CiQxOmZ1bmN0
+aW9uKGEpe3QuZVEuYShhKQp0aGlzLmEuYU0oMCx0aGlzLmIpfSwKJFM6NDd9CkwublQucHJvdG90eXBl
+PXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjJ9CkwuTlkucHJv
+dG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYSxudWxsLG51bGwpfSwKJFM6Mn0KTC51ZS5w
+cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt0LmF3LmEoYSkKcmV0dXJuIEguRWooYS5xKDAsInNldmVy
+aXR5IikpKyIgLSAiK0guRWooYS5xKDAsIm1lc3NhZ2UiKSkrIiBhdCAiK0guRWooYS5xKDAsImxvY2F0
+aW9uIikpKyIgLSAoIitILkVqKGEucSgwLCJjb2RlIikpKyIpIn0sCiRTOjQ4fQpMLmVYLnByb3RvdHlw
+ZT17CiQxOmZ1bmN0aW9uKGEpe3QuZy5hKGEpCiQuekIoKS50b1N0cmluZwp0LmRILmEoJC5vdygpLnEo
+MCwiaGxqcyIpKS5WNygiaGlnaGxpZ2h0QmxvY2siLFthXSl9LAokUzozfQpMLkVFLnByb3RvdHlwZT17
+CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIKdC5PLmEoYSkucHJldmVudERlZmF1bHQoKQpzPXRoaXMuYQpy
+PXRoaXMuYgpMLmFmKHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSxzLHIsITAsbmV3IEwuUUwocyxyKSkK
+TC5oWCh0aGlzLmMscyxyKX0sCiRTOjF9CkwuUUwucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtMLkZy
+KHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSx0aGlzLmEsdGhpcy5iKX0sCiRTOjJ9CkwuVlMucHJvdG90
+eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscj0ic2VsZWN0ZWQtZmlsZSIKdC5nLmEoYSkKYS50b1N0
+cmluZwpzPUouWUUoYSkKaWYoYS5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhh
+KSkuT1UoIm5hbWUiKSk9PT10aGlzLmEuYSlzLmdQKGEpLmkoMCxyKQplbHNlIHMuZ1AoYSkuUigwLHIp
+fSwKJFM6M30KTC5URC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcyxyCnQuTy5hKGEpCnM9
+dGhpcy5hCnN3aXRjaChzLmdMKCkpe2Nhc2UgQy5jdzpicmVhawpjYXNlIEMuV0Q6cy5uRygpCmJyZWFr
+CmNhc2UgQy5YajpzLmMyKCkKYnJlYWsKY2FzZSBDLmRjOnMuYzIoKQpicmVha31yPXRoaXMuYgpMLmhs
+KHIscykKTC54bih0aGlzLmMscykKTC5BUihyLHMpfSwKJFM6MX0KTC5JZi5wcm90b3R5cGU9ewokMTpm
+dW5jdGlvbihhKXt2YXIgcwp0Lk8uYShhKQpzPXRoaXMuYQpMLk90KHMpCkwueG4odGhpcy5iLHMpCkwu
+QVIodGhpcy5jLHMpfSwKJFM6MX0KTC50Qi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4g
+TC50Mih0Lk8uYShhKSwhMCl9LAokUzo3fQpMLm0yLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0aGlzLlJJKHQuTy5hKGEpKX0sClJJOmZ1bmN0aW9uKGEpe3ZhciBzPTAscj1QLkZYKHQuUCks
+cT0xLHAsbz1bXSxuPXRoaXMsbSxsLGssaixpLGgsZyxmCnZhciAkYXN5bmMkJDE9UC5seihmdW5jdGlv
+bihiLGMpe2lmKGI9PT0xKXtwPWMKcz1xfXdoaWxlKHRydWUpc3dpdGNoKHMpe2Nhc2UgMDpxPTMKaT1k
+b2N1bWVudAptPUMuQ0QuelEoaS5xdWVyeVNlbGVjdG9yKCIuY29udGVudCIpLnNjcm9sbFRvcCkKaD10
+LlgKcz02CnJldHVybiBQLmpRKEwudHkoTC5RNCgiL2FwcGx5LWhpbnQiLFAuRmwoaCxoKSksbi5hLkx0
+KCkpLCRhc3luYyQkMSkKY2FzZSA2Omg9bi5iCmw9TC5VcyhoLmEpCnM9NwpyZXR1cm4gUC5qUShMLkc3
+KGwsbnVsbCxoLmIsITEsbnVsbCksJGFzeW5jJCQxKQpjYXNlIDc6aS5ib2R5LmNsYXNzTGlzdC5hZGQo
+Im5lZWRzLXJlcnVuIikKaT1pLnF1ZXJ5U2VsZWN0b3IoIi5jb250ZW50IikKaS50b1N0cmluZwppLnNj
+cm9sbFRvcD1KLlZ1KG0pCnE9MQpzPTUKYnJlYWsKY2FzZSAzOnE9MgpmPXAKaz1ILlJ1KGYpCmo9SC50
+cyhmKQpMLkMyKCJDb3VsZCBub3QgYXBwbHkgaGludCIsayxqKQpzPTUKYnJlYWsKY2FzZSAyOnM9MQpi
+cmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxyKQpjYXNlIDE6cmV0dXJuIFAuZjMocCxyKX19KQpy
+ZXR1cm4gUC5ESSgkYXN5bmMkJDEscil9LAokUzoyMH0KTC5YQS5wcm90b3R5cGU9ewpFYjpmdW5jdGlv
+bihhLGIsYyl7cmV0dXJuITB9LAppMDpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCiRpa0Y6MX0KTC52dC5w
+cm90b3R5cGU9ewpnTDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixtLGw9dGhpcy5kCmlmKGwubGVu
+Z3RoPT09MClyZXR1cm4gQy5jdwpzPUMuTm0uZ3RIKGwpLmdMKCkKZm9yKHI9bC5sZW5ndGgscT0hMCxw
+PSEwLG89MDtvPGwubGVuZ3RoO2wubGVuZ3RoPT09cnx8KDAsSC5saykobCksKytvKXtuPWxbb10uZ0wo
+KQppZihuIT1zKXM9bnVsbAptPW4hPT1DLmN3CmlmKG0mJm4hPT1DLldEKXE9ITEKaWYobSYmbiE9PUMu
+WGopcD0hMX1pZihzIT1udWxsKXJldHVybiBzCmlmKHEpcmV0dXJuIEMuV0QKaWYocClyZXR1cm4gQy5Y
+agpyZXR1cm4gQy5kY30sCkxWOmZ1bmN0aW9uKCl7dmFyIHMscixxPXRoaXMuZAppZihxIT1udWxsKWZv
+cihzPXEubGVuZ3RoLHI9MDtyPHM7KytyKXFbcl0uYj10aGlzfSwKYzI6ZnVuY3Rpb24oKXt2YXIgcyxy
+LHEscApmb3Iocz10aGlzLmQscj1zLmxlbmd0aCxxPTA7cTxzLmxlbmd0aDtzLmxlbmd0aD09PXJ8fCgw
+LEgubGspKHMpLCsrcSl7cD1zW3FdCmlmKHAgaW5zdGFuY2VvZiBMLnZ0KXAuYzIoKQplbHNlIGlmKHAg
+aW5zdGFuY2VvZiBMLmNEJiZILm9UKHAueCkmJnAucj09PUMuWGopcC5yPUMuV0R9fSwKbkc6ZnVuY3Rp
+b24oKXt2YXIgcyxyLHEscApmb3Iocz10aGlzLmQscj1zLmxlbmd0aCxxPTA7cTxzLmxlbmd0aDtzLmxl
+bmd0aD09PXJ8fCgwLEgubGspKHMpLCsrcSl7cD1zW3FdCmlmKHAgaW5zdGFuY2VvZiBMLnZ0KXAubkco
+KQplbHNlIGlmKHAgaW5zdGFuY2VvZiBMLmNEJiZILm9UKHAueCkmJnAucj09PUMuV0QpcC5yPUMuWGp9
+fSwKTHQ6ZnVuY3Rpb24oKXt2YXIgcyxyPVAuRmwodC5YLHQuXykKci5ZNSgwLCJ0eXBlIiwiZGlyZWN0
+b3J5IikKci5ZNSgwLCJuYW1lIix0aGlzLmEpCnIuWTUoMCwic3VidHJlZSIsTC5WRCh0aGlzLmQpKQpz
+PXRoaXMuYwppZihzIT1udWxsKXIuWTUoMCwicGF0aCIscykKcmV0dXJuIHJ9fQpMLmNELnByb3RvdHlw
+ZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHMscj10aGlzLHE9UC5GbCh0LlgsdC5fKQpxLlk1KDAsInR5cGUi
+LCJmaWxlIikKcS5ZNSgwLCJuYW1lIixyLmEpCnM9ci5jCmlmKHMhPW51bGwpcS5ZNSgwLCJwYXRoIixz
+KQpzPXIuZAppZihzIT1udWxsKXEuWTUoMCwiaHJlZiIscykKcz1yLmUKaWYocyE9bnVsbClxLlk1KDAs
+ImVkaXRDb3VudCIscykKcz1yLmYKaWYocyE9bnVsbClxLlk1KDAsIndhc0V4cGxpY2l0bHlPcHRlZE91
+dCIscykKcz1yLnIKaWYocyE9bnVsbClxLlk1KDAsIm1pZ3JhdGlvblN0YXR1cyIscy5hKQpzPXIueApp
+ZihzIT1udWxsKXEuWTUoMCwibWlncmF0aW9uU3RhdHVzQ2FuQmVDaGFuZ2VkIixzKQpyZXR1cm4gcX0s
+CmdMOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucn19CkwuRDgucHJvdG90eXBlPXt9CkwuTzkucHJvdG90
+eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ifX0KTC5HYi5wcm90b3R5cGU9ewp3OmZ1bmN0
+aW9uKGEpe3JldHVybiB0aGlzLmJ9fQpSLkxMLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7cmV0dXJu
+IFAuRUYoWyJub2RlSWQiLHRoaXMuYiwia2luZCIsdGhpcy5hLmFdLHQuWCx0Ll8pfX0KUi5NRC5wcm90
 b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdC5mRS5hKGEpLmE9PT10aGlzLmEucSgwLCJraW5k
-Iil9LAokUzozOH0KVS5kMi5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89dGhp
-cyxuPXQuWCxtPXQuXyxsPVAuRmwobixtKSxrPW8uYQppZihrIT1udWxsKXtzPUguVk0oW10sdC5HKQpm
-b3Iocj1rLmxlbmd0aCxxPTA7cTxrLmxlbmd0aDtrLmxlbmd0aD09PXJ8fCgwLEgubGspKGspLCsrcSl7
-cD1rW3FdCnMucHVzaChQLkVGKFsiZGVzY3JpcHRpb24iLHAuYSwiaHJlZiIscC5iXSxuLG0pKX1sLlk1
-KDAsImVkaXRzIixzKX1sLlk1KDAsImV4cGxhbmF0aW9uIixvLmIpCmwuWTUoMCwibGluZSIsby5jKQps
-Llk1KDAsImRpc3BsYXlQYXRoIixvLmQpCmwuWTUoMCwidXJpUGF0aCIsby5lKQpuPW8uZgppZihuIT1u
-dWxsKXttPUguVk0oW10sdC5HKQpmb3Ioaz1uLmxlbmd0aCxxPTA7cTxuLmxlbmd0aDtuLmxlbmd0aD09
-PWt8fCgwLEgubGspKG4pLCsrcSltLnB1c2gobltxXS5MdCgpKQpsLlk1KDAsInRyYWNlcyIsbSl9cmV0
-dXJuIGx9fQpVLlNlLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7cmV0dXJuIFAuRUYoWyJkZXNjcmlw
-dGlvbiIsdGhpcy5hLCJocmVmIix0aGlzLmJdLHQuWCx0Ll8pfX0KVS5NbC5wcm90b3R5cGU9ewpMdDpm
-dW5jdGlvbigpe3JldHVybiBQLkVGKFsiaHJlZiIsdGhpcy5hLCJsaW5lIix0aGlzLmIsInBhdGgiLHRo
-aXMuY10sdC5YLHQuXyl9fQpVLnlELnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHMscixxLHA9
-SC5WTShbXSx0LkcpCmZvcihzPXRoaXMuYixyPXMubGVuZ3RoLHE9MDtxPHMubGVuZ3RoO3MubGVuZ3Ro
-PT09cnx8KDAsSC5saykocyksKytxKXAucHVzaChzW3FdLkx0KCkpCnJldHVybiBQLkVGKFsiZGVzY3Jp
-cHRpb24iLHRoaXMuYSwiZW50cmllcyIscF0sdC5YLHQuXyl9fQpVLndiLnByb3RvdHlwZT17Ckx0OmZ1
-bmN0aW9uKCl7dmFyIHMscixxLHA9dGhpcyxvPVAuRmwodC5YLHQuXykKby5ZNSgwLCJkZXNjcmlwdGlv
-biIscC5hKQpzPXAuYgppZihzIT1udWxsKW8uWTUoMCwiZnVuY3Rpb24iLHMpCnM9cC5jCmlmKHMhPW51
-bGwpby5ZNSgwLCJsaW5rIixzLkx0KCkpCnM9cC5kCmlmKHMubGVuZ3RoIT09MCl7cj1ILnQ2KHMpCnE9
-ci5DKCJsSjwxLFowPHFVKixNaCo+Kj4iKQpvLlk1KDAsImhpbnRBY3Rpb25zIixQLlkxKG5ldyBILmxK
-KHMsci5DKCJaMDxxVSosTWgqPiooMSkiKS5hKG5ldyBVLmIwKCkpLHEpLCEwLHEuQygiYUwuRSIpKSl9
-cmV0dXJuIG99fQpVLmFOLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBVLm56KHQudC5h
-KGEpKX0sCiRTOjM5fQpVLmIwLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0LmFYLmEo
-YSkuTHQoKX0sCiRTOjQwfQpCLmo4LnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7cmV0dXJuIFAuRUYo
-WyJsaW5lIix0aGlzLmEsImV4cGxhbmF0aW9uIix0aGlzLmIsIm9mZnNldCIsdGhpcy5jXSx0LlgsdC5f
-KX19CkIucXAucHJvdG90eXBlPXsKTHQ6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbSxsPXRoaXMs
-az10Llgsaj1QLkZsKGssdC5kcCkKZm9yKHM9bC5kLHM9cy5nUHUocykscz1zLmdtKHMpLHI9dC5fLHE9
-dC5HO3MuRigpOyl7cD1zLmdsKCkKbz1wLmEKbj1ILlZNKFtdLHEpCmZvcihwPUouSVQocC5iKTtwLkYo
-KTspe209cC5nbCgpCm4ucHVzaChQLkVGKFsibGluZSIsbS5hLCJleHBsYW5hdGlvbiIsbS5iLCJvZmZz
-ZXQiLG0uY10sayxyKSl9ai5ZNSgwLG8sbil9cmV0dXJuIFAuRUYoWyJyZWdpb25zIixsLmEsIm5hdmln
-YXRpb25Db250ZW50IixsLmIsInNvdXJjZUNvZGUiLGwuYywiZWRpdHMiLGpdLGsscil9fQpULm1RLnBy
-b3RvdHlwZT17fQpMLmUucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0K
-dC5hTC5hKGEpCnM9d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lCnI9TC5HNih3aW5kb3cubG9jYXRpb24u
-aHJlZikKcT1MLmFLKHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpMLkdlKCkKaWYocyE9PSIvIiYmcyE9PUou
-VDAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpTC5HNyhzLHIscSwh
-MCxuZXcgTC5WVyhzLHIscSkpCnA9ZG9jdW1lbnQKbz1KLnFGKHAucXVlcnlTZWxlY3RvcigiLmFwcGx5
-LW1pZ3JhdGlvbiIpKQpuPW8uJHRpCm09bi5DKCJ+KDEpPyIpLmEobmV3IEwub1ooKSkKdC5aLmEobnVs
-bCkKVy5KRShvLmEsby5iLG0sITEsbi5jKQpuPUoucUYocC5xdWVyeVNlbGVjdG9yKCIucmVydW4tbWln
-cmF0aW9uIikpCm09bi4kdGkKVy5KRShuLmEsbi5iLG0uQygifigxKT8iKS5hKG5ldyBMLkhpKCkpLCEx
-LG0uYykKbT1KLnFGKHAucXVlcnlTZWxlY3RvcigiLnJlcG9ydC1wcm9ibGVtIikpCm49bS4kdGkKVy5K
-RShtLmEsbS5iLG4uQygifigxKT8iKS5hKG5ldyBMLkJUKCkpLCExLG4uYykKcD1KLnFGKHAucXVlcnlT
-ZWxlY3RvcigiLnBvcHVwLXBhbmUgLmNsb3NlIikpCm49cC4kdGkKVy5KRShwLmEscC5iLG4uQygifigx
-KT8iKS5hKG5ldyBMLlBZKCkpLCExLG4uYykKbj1KLnFGKCQuYzAoKSkKcD1uLiR0aQpXLkpFKG4uYSxu
-LmIscC5DKCJ+KDEpPyIpLmEobmV3IEwudTgoKSksITEscC5jKX0sCiRTOjE4fQpMLlZXLnByb3RvdHlw
-ZT17CiQwOmZ1bmN0aW9uKCl7TC5Gcih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzoyfQpMLm9aLnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwCnQuTy5hKGEpCmlmKEgub1QoQy5vbC51
-cyh3aW5kb3csIlRoaXMgd2lsbCBhcHBseSB0aGUgY2hhbmdlcyB5b3UndmUgcHJldmlld2VkIHRvIHlv
-dXIgd29ya2luZyBkaXJlY3RvcnkuIEl0IGlzIHJlY29tbWVuZGVkIHlvdSBjb21taXQgYW55IGNoYW5n
-ZXMgeW91IG1hZGUgYmVmb3JlIGRvaW5nIHRoaXMuIikpKXtzPUwudHkoIi9hcHBseS1taWdyYXRpb24i
-LG51bGwpLlc3KG5ldyBMLmpyKCksdC5QKQpyPW5ldyBMLnFsKCkKdC5iNy5hKG51bGwpCnE9cy4kdGkK
-cD0kLlgzCmlmKHAhPT1DLk5VKXI9UC5WSChyLHApCnMueGYobmV3IFAuRmUobmV3IFAudnMocCxxKSwy
-LG51bGwscixxLkMoIkA8MT4iKS5LcShxLmMpLkMoIkZlPDEsMj4iKSkpfX0sCiRTOjF9CkwuanIucHJv
-dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMKdC50LmEoYSkKcz1kb2N1bWVudC5ib2R5CnMuY2xh
-c3NMaXN0LnJlbW92ZSgicHJvcG9zZWQiKQpzLmNsYXNzTGlzdC5hZGQoImFwcGxpZWQiKX0sCiRTOjQz
-fQpMLnFsLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5DMigiQ291bGQgbm90IGFwcGx5IG1p
-Z3JhdGlvbiIsYSxiKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjE2fQpMLkhpLnByb3RvdHlwZT17CiQxOmZ1
-bmN0aW9uKGEpe3JldHVybiB0aGlzLnhuKHQuTy5hKGEpKX0sCnhuOmZ1bmN0aW9uKGEpe3ZhciBzPTAs
-cj1QLkZYKHQuUCkscT0xLHAsbz1bXSxuLG0sbCxrLGoKdmFyICRhc3luYyQkMT1QLmx6KGZ1bmN0aW9u
-KGIsYyl7aWYoYj09PTEpe3A9YwpzPXF9d2hpbGUodHJ1ZSlzd2l0Y2gocyl7Y2FzZSAwOnE9Mwpkb2N1
-bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoInJlcnVubmluZyIpCnM9NgpyZXR1cm4gUC5qUShMLnR5KCIv
-cmVydW4tbWlncmF0aW9uIixudWxsKSwkYXN5bmMkJDEpCmNhc2UgNjpuPWMKaWYoSC5vVChILnk4KEou
-eDkobiwic3VjY2VzcyIpKSkpd2luZG93LmxvY2F0aW9uLnJlbG9hZCgpCmVsc2UgTC5LMCh0Lm0uYShK
-Lng5KG4sImVycm9ycyIpKSkKby5wdXNoKDUpCnM9NApicmVhawpjYXNlIDM6cT0yCmo9cAptPUguUnUo
-aikKbD1ILnRzKGopCkwuQzIoIkZhaWxlZCB0byByZXJ1biBtaWdyYXRpb24iLG0sbCkKby5wdXNoKDUp
-CnM9NApicmVhawpjYXNlIDI6bz1bMV0KY2FzZSA0OnE9MQpkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5y
-ZW1vdmUoInJlcnVubmluZyIpCnM9by5wb3AoKQpicmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxy
-KQpjYXNlIDE6cmV0dXJuIFAuZjMocCxyKX19KQpyZXR1cm4gUC5ESSgkYXN5bmMkJDEscil9LAokUzox
-OX0KTC5CVC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcwp0Lk8uYShhKQpzPXQuWApDLm9s
-LlBvKHdpbmRvdyxQLlhkKCJodHRwcyIsImdpdGh1Yi5jb20iLCJkYXJ0LWxhbmcvc2RrL2lzc3Vlcy9u
-ZXciLFAuRUYoWyJ0aXRsZSIsIkN1c3RvbWVyLXJlcG9ydGVkIGlzc3VlIHdpdGggTk5CRCBtaWdyYXRp
-b24gdG9vbCIsImxhYmVscyIsdS5kLCJib2R5IiwiIyMjIyBTdGVwcyB0byByZXByb2R1Y2VcblxuIyMj
-IyBXaGF0IGRpZCB5b3UgZXhwZWN0IHRvIGhhcHBlbj9cblxuIyMjIyBXaGF0IGFjdHVhbGx5IGhhcHBl
-bmVkP1xuXG5fU2NyZWVuc2hvdHMgYXJlIGFwcHJlY2lhdGVkX1xuXG4qKkRhcnQgU0RLIHZlcnNpb24q
-KjogIitILkVqKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJzZGstdmVyc2lvbiIpLnRleHRDb250ZW50
-KSsiXG5cblRoYW5rcyBmb3IgZmlsaW5nIVxuIl0scyxzKSkuZ25EKCksInJlcG9ydC1wcm9ibGVtIil9
-LAokUzoxfQpMLlBZLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzCnQuTy5hKGEpCnM9ZG9j
-dW1lbnQucXVlcnlTZWxlY3RvcigiLnBvcHVwLXBhbmUiKS5zdHlsZQpzLmRpc3BsYXk9Im5vbmUiCnJl
-dHVybiJub25lIn0sCiRTOjQ1fQpMLnU4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIs
-cSxwCnQuTy5hKGEpCnM9JC5EOSgpLmlubmVyVGV4dApyPXQuZy5hKGRvY3VtZW50LnF1ZXJ5U2VsZWN0
-b3IoJy5uYXYtcGFuZWwgW2RhdGEtbmFtZSo9IicrSC5FaihzKSsnIl0nKS5wYXJlbnROb2RlKQpxPXIu
-cXVlcnlTZWxlY3RvcigiLnN0YXR1cy1pY29uIikKcD1MLm1IKCQuSVIscykKaWYocCBpbnN0YW5jZW9m
-IEwuY0Qpe0wuT3QocCkKTC54bihxLHApCkwuQVIocixwKX19LAokUzoxfQpMLkwucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7dmFyIHMscixxCnQuYUwuYShhKQpzPXdpbmRvdy5sb2NhdGlvbi5wYXRobmFt
-ZQpyPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpCnE9TC5hSyh3aW5kb3cubG9jYXRpb24uaHJlZikK
-aWYocy5sZW5ndGg+MSlMLkc3KHMscixxLCExLG51bGwpCmVsc2V7TC5CRShzLEIud1IoKSwhMCkKTC5C
-WCgiJm5ic3A7IixudWxsKX19LAokUzoxOH0KTC5XeC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2
-YXIgcyxyLHEscD0iY29sbGFwc2VkIgp0Lk8uYShhKQpzPXRoaXMuYQpyPUouWUUocykKcT10aGlzLmIK
-aWYoIXIuZ24ocykudGcoMCxwKSl7ci5nbihzKS5pKDAscCkKSi5kUihxKS5pKDAscCl9ZWxzZXtyLmdu
-KHMpLkwoMCxwKQpKLmRSKHEpLkwoMCxwKX19LAokUzoxfQpMLkFPLnByb3RvdHlwZT17CiQxOmZ1bmN0
-aW9uKGEpe3ZhciBzPUoucUYodC5nLmEoYSkpLHI9cy4kdGkscT1yLkMoIn4oMSk/IikuYShuZXcgTC5k
-Tih0aGlzLmEpKQp0LlouYShudWxsKQpXLkpFKHMuYSxzLmIscSwhMSxyLmMpfSwKJFM6M30KTC5kTi5w
-cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcwp0Lk8uYShhKQpzPWRvY3VtZW50LnF1ZXJ5U2Vs
-ZWN0b3IoInRhYmxlW2RhdGEtcGF0aF0iKQpzLnRvU3RyaW5nCkwudDIoYSx0aGlzLmEscy5nZXRBdHRy
-aWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhzKSkuUCgicGF0aCIpKSl9LAokUzoxfQpMLkhv
-LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIscQp0LmcuYShhKQpzPUoucUYoYSkKcj1z
-LiR0aQpxPXIuQygifigxKT8iKS5hKG5ldyBMLnh6KGEsdGhpcy5hKSkKdC5aLmEobnVsbCkKVy5KRShz
-LmEscy5iLHEsITEsci5jKX0sCiRTOjN9CkwueHoucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFy
-IHMKdC5PLmEoYSkKcz10aGlzLmEKTC5oWCh0aGlzLmIsUC5RQShzLmdldEF0dHJpYnV0ZSgiZGF0YS0i
-K25ldyBXLlN5KG5ldyBXLmk3KHMpKS5QKCJvZmZzZXQiKSksbnVsbCksUC5RQShzLmdldEF0dHJpYnV0
-ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHMpKS5QKCJsaW5lIikpLG51bGwpKX0sCiRTOjF9Ckwu
-SUMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHM9Si5xRih0LmcuYShhKSkscj1zLiR0aQpy
-LkMoIn4oMSk/IikuYShMLmlTKCkpCnQuWi5hKG51bGwpClcuSkUocy5hLHMuYixMLmlTKCksITEsci5j
-KX0sCiRTOjN9CkwuZkMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dC5lUS5hKGEpCnRoaXMuYS5h
-TSgwLHRoaXMuYil9LAokUzo0N30KTC5uVC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhp
-cy5hLHRoaXMuYix0aGlzLmMpfSwKJFM6Mn0KTC5OWS5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wu
-RnIodGhpcy5hLG51bGwsbnVsbCl9LAokUzoyfQpMLnVlLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
-e3QuYXcuYShhKQpyZXR1cm4gSC5FaihhLnEoMCwic2V2ZXJpdHkiKSkrIiAtICIrSC5FaihhLnEoMCwi
-bWVzc2FnZSIpKSsiIGF0ICIrSC5FaihhLnEoMCwibG9jYXRpb24iKSkrIiAtICgiK0guRWooYS5xKDAs
-ImNvZGUiKSkrIikifSwKJFM6NDh9CkwuZVgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dC5nLmEo
-YSkKJC56QigpLnRvU3RyaW5nCnQuZEguYSgkLm93KCkucSgwLCJobGpzIikpLlY3KCJoaWdobGlnaHRC
-bG9jayIsW2FdKX0sCiRTOjN9CkwuRUUucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscgp0
-Lk8uYShhKS5wcmV2ZW50RGVmYXVsdCgpCnM9dGhpcy5hCnI9dGhpcy5iCkwuYWYod2luZG93LmxvY2F0
-aW9uLnBhdGhuYW1lLHMsciwhMCxuZXcgTC5RTChzLHIpKQpMLmhYKHRoaXMuYyxzLHIpfSwKJFM6MX0K
-TC5RTC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIod2luZG93LmxvY2F0aW9uLnBhdGhuYW1l
-LHRoaXMuYSx0aGlzLmIpfSwKJFM6Mn0KTC5WUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
-cyxyPSJzZWxlY3RlZC1maWxlIgp0LmcuYShhKQphLnRvU3RyaW5nCnM9Si5ZRShhKQppZihhLmdldEF0
-dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGEpKS5QKCJuYW1lIikpPT09dGhpcy5hLmEp
-cy5nbihhKS5pKDAscikKZWxzZSBzLmduKGEpLkwoMCxyKX0sCiRTOjN9CkwuVEQucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEwudDIodC5PLmEoYSksITAsbnVsbCl9LAokUzoyMH0KTC5tMi5w
-cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5SSSh0Lk8uYShhKSl9LApSSTpmdW5j
-dGlvbihhKXt2YXIgcz0wLHI9UC5GWCh0LlApLHE9MSxwLG89W10sbj10aGlzLG0sbCxrLGosaSxoLGcs
-Zgp2YXIgJGFzeW5jJCQxPVAubHooZnVuY3Rpb24oYixjKXtpZihiPT09MSl7cD1jCnM9cX13aGlsZSh0
-cnVlKXN3aXRjaChzKXtjYXNlIDA6cT0zCmk9ZG9jdW1lbnQKbT1DLkNELnpRKGkucXVlcnlTZWxlY3Rv
-cigiLmNvbnRlbnQiKS5zY3JvbGxUb3ApCmg9dC5YCnM9NgpyZXR1cm4gUC5qUShMLnR5KEwuUTQoIi9h
-cHBseS1oaW50IixQLkZsKGgsaCkpLG4uYS5MdCgpKSwkYXN5bmMkJDEpCmNhc2UgNjpoPW4uYgpsPUwu
-VXMoaC5hKQpzPTcKcmV0dXJuIFAualEoTC5HNyhsLG51bGwsaC5iLCExLG51bGwpLCRhc3luYyQkMSkK
-Y2FzZSA3OmkuYm9keS5jbGFzc0xpc3QuYWRkKCJuZWVkcy1yZXJ1biIpCmk9aS5xdWVyeVNlbGVjdG9y
-KCIuY29udGVudCIpCmkudG9TdHJpbmcKaS5zY3JvbGxUb3A9Si5WdShtKQpxPTEKcz01CmJyZWFrCmNh
-c2UgMzpxPTIKZj1wCms9SC5SdShmKQpqPUgudHMoZikKTC5DMigiQ291bGQgbm90IGFwcGx5IGhpbnQi
-LGssaikKcz01CmJyZWFrCmNhc2UgMjpzPTEKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscikK
-Y2FzZSAxOnJldHVybiBQLmYzKHAscil9fSkKcmV0dXJuIFAuREkoJGFzeW5jJCQxLHIpfSwKJFM6MTl9
-CkwuWEEucHJvdG90eXBlPXsKRWI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiEwfSwKaTA6ZnVuY3Rpb24o
-YSl7cmV0dXJuITB9LAokaWtGOjF9CkwudnQucHJvdG90eXBlPXsKZ2Q2OmZ1bmN0aW9uKCl7dmFyIHMs
-cixxLHAsbyxuLG0sbD10aGlzLmQKaWYobC5sZW5ndGg9PT0wKXJldHVybiBDLmN3CnM9Qy5ObS5ndEgo
-bCkuZ2Q2KCkKZm9yKHI9bC5sZW5ndGgscT0hMCxwPSEwLG89MDtvPGwubGVuZ3RoO2wubGVuZ3RoPT09
-cnx8KDAsSC5saykobCksKytvKXtuPWxbb10uZ2Q2KCkKaWYobiE9cylzPW51bGwKbT1uIT09Qy5jdwpp
-ZihtJiZuIT09Qy5XRClxPSExCmlmKG0mJm4hPT1DLlhqKXA9ITF9aWYocyE9bnVsbClyZXR1cm4gcwpp
-ZihxKXJldHVybiBDLldECmlmKHApcmV0dXJuIEMuWGoKcmV0dXJuIEMuZGN9LApMVjpmdW5jdGlvbigp
-e3ZhciBzLHIscT10aGlzLmQKaWYocSE9bnVsbClmb3Iocz1xLmxlbmd0aCxyPTA7cjxzOysrcilxW3Jd
-LmI9dGhpc30sCkx0OmZ1bmN0aW9uKCl7dmFyIHMscj1QLkZsKHQuWCx0Ll8pCnIuWTUoMCwidHlwZSIs
-ImRpcmVjdG9yeSIpCnIuWTUoMCwibmFtZSIsdGhpcy5hKQpyLlk1KDAsInN1YnRyZWUiLEwuVkQodGhp
-cy5kKSkKcz10aGlzLmMKaWYocyE9bnVsbClyLlk1KDAsInBhdGgiLHMpCnJldHVybiByfX0KTC5jRC5w
-cm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBzLHI9dGhpcyxxPVAuRmwodC5YLHQuXykKcS5ZNSgw
-LCJ0eXBlIiwiZmlsZSIpCnEuWTUoMCwibmFtZSIsci5hKQpzPXIuYwppZihzIT1udWxsKXEuWTUoMCwi
-cGF0aCIscykKcz1yLmQKaWYocyE9bnVsbClxLlk1KDAsImhyZWYiLHMpCnM9ci5lCmlmKHMhPW51bGwp
-cS5ZNSgwLCJlZGl0Q291bnQiLHMpCnM9ci5mCmlmKHMhPW51bGwpcS5ZNSgwLCJ3YXNFeHBsaWNpdGx5
-T3B0ZWRPdXQiLHMpCnM9ci5yCmlmKHMhPW51bGwpcS5ZNSgwLCJtaWdyYXRpb25TdGF0dXMiLHMuYSkK
-cmV0dXJuIHF9LApnZDY6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5yfX0KTC5EOC5wcm90b3R5cGU9e30K
-TC5POS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJ9fQpMLkdiLnByb3RvdHlw
-ZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYn19Ck0ubEkucHJvdG90eXBlPXsKZ2w6ZnVuY3Rp
-b24oKXt2YXIgcz1ELmFiKCkKcmV0dXJuIHN9LApXTzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT10LmQ0
-Ck0uWUYoImFic29sdXRlIixILlZNKFtiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsXSxxKSkK
-cz10aGlzLmEKcz1zLllyKGIpPjAmJiFzLmhLKGIpCmlmKHMpcmV0dXJuIGIKcj1ILlZNKFt0aGlzLmds
-KCksYixudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbF0scSkKTS5ZRigiam9pbiIscikKcmV0dXJu
-IHRoaXMuSVAobmV3IEgudTYocix0LmVKKSl9LAp6ZjpmdW5jdGlvbihhKXt2YXIgcyxyLHE9WC5DTChh
-LHRoaXMuYSkKcS5JeCgpCnM9cS5kCnI9cy5sZW5ndGgKaWYocj09PTApe3M9cS5iCnJldHVybiBzPT1u
-dWxsPyIuIjpzfWlmKHI9PT0xKXtzPXEuYgpyZXR1cm4gcz09bnVsbD8iLiI6c31pZigwPj1yKXJldHVy
-biBILk9IKHMsLTEpCnMucG9wKCkKcz1xLmUKaWYoMD49cy5sZW5ndGgpcmV0dXJuIEguT0gocywtMSkK
-cy5wb3AoKQpxLkl4KCkKcmV0dXJuIHEudygwKX0sCklQOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8s
-bixtLGwsayxqCnQuUS5hKGEpCmZvcihzPWEuJHRpLHI9cy5DKCJhMihjWC5FKSIpLmEobmV3IE0ucTco
-KSkscT1hLmdtKGEpLHM9bmV3IEguU08ocSxyLHMuQygiU088Y1guRT4iKSkscj10aGlzLmEscD0hMSxv
-PSExLG49IiI7cy5GKCk7KXttPXEuZ2woKQppZihyLmhLKG0pJiZvKXtsPVguQ0wobSxyKQprPW4uY2hh
-ckNvZGVBdCgwKT09MD9uOm4Kbj1DLnhCLk5qKGssMCxyLlNwKGssITApKQpsLmI9bgppZihyLmRzKG4p
-KUMuTm0uWTUobC5lLDAsci5nbUkoKSkKbj1sLncoMCl9ZWxzZSBpZihyLllyKG0pPjApe289IXIuaEso
-bSkKbj1ILkVqKG0pfWVsc2V7aj1tLmxlbmd0aAppZihqIT09MCl7aWYoMD49ailyZXR1cm4gSC5PSCht
-LDApCmo9ci5VZChtWzBdKX1lbHNlIGo9ITEKaWYoIWopaWYocCluKz1yLmdtSSgpCm4rPW19cD1yLmRz
-KG0pfXJldHVybiBuLmNoYXJDb2RlQXQoMCk9PTA/bjpufSwKbzU6ZnVuY3Rpb24oYSl7dmFyIHMKaWYo
-IXRoaXMueTMoYSkpcmV0dXJuIGEKcz1YLkNMKGEsdGhpcy5hKQpzLnJSKCkKcmV0dXJuIHMudygwKX0s
-CnkzOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqCmEudG9TdHJpbmcKcz10aGlzLmEK
-cj1zLllyKGEpCmlmKHIhPT0wKXtpZihzPT09JC5LaygpKWZvcihxPTA7cTxyOysrcSlpZihDLnhCLlco
-YSxxKT09PTQ3KXJldHVybiEwCnA9cgpvPTQ3fWVsc2V7cD0wCm89bnVsbH1mb3Iobj1uZXcgSC5xaihh
-KS5hLG09bi5sZW5ndGgscT1wLGw9bnVsbDtxPG07KytxLGw9byxvPWspe2s9Qy54Qi5PMihuLHEpCmlm
-KHMucjQoaykpe2lmKHM9PT0kLktrKCkmJms9PT00NylyZXR1cm4hMAppZihvIT1udWxsJiZzLnI0KG8p
-KXJldHVybiEwCmlmKG89PT00NilqPWw9PW51bGx8fGw9PT00Nnx8cy5yNChsKQplbHNlIGo9ITEKaWYo
-ailyZXR1cm4hMH19aWYobz09bnVsbClyZXR1cm4hMAppZihzLnI0KG8pKXJldHVybiEwCmlmKG89PT00
-NilzPWw9PW51bGx8fHMucjQobCl8fGw9PT00NgplbHNlIHM9ITEKaWYocylyZXR1cm4hMApyZXR1cm4h
-MX0sCkhQOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuLG0sbD10aGlzLGs9J1VuYWJsZSB0byBm
-aW5kIGEgcGF0aCB0byAiJwpiPWwuV08oMCxiKQpzPWwuYQppZihzLllyKGIpPD0wJiZzLllyKGEpPjAp
-cmV0dXJuIGwubzUoYSkKaWYocy5ZcihhKTw9MHx8cy5oSyhhKSlhPWwuV08oMCxhKQppZihzLllyKGEp
-PD0wJiZzLllyKGIpPjApdGhyb3cgSC5iKFguSTcoaytILkVqKGEpKyciIGZyb20gIicrSC5FaihiKSsn
-Ii4nKSkKcj1YLkNMKGIscykKci5yUigpCnE9WC5DTChhLHMpCnEuclIoKQpwPXIuZApvPXAubGVuZ3Ro
-CmlmKG8hPT0wKXtpZigwPj1vKXJldHVybiBILk9IKHAsMCkKcD1KLlJNKHBbMF0sIi4iKX1lbHNlIHA9
-ITEKaWYocClyZXR1cm4gcS53KDApCnA9ci5iCm89cS5iCmlmKHAhPW8pcD1wPT1udWxsfHxvPT1udWxs
-fHwhcy5OYyhwLG8pCmVsc2UgcD0hMQppZihwKXJldHVybiBxLncoMCkKd2hpbGUoITApe3A9ci5kCm89
-cC5sZW5ndGgKaWYobyE9PTApe249cS5kCm09bi5sZW5ndGgKaWYobSE9PTApe2lmKDA+PW8pcmV0dXJu
-IEguT0gocCwwKQpwPXBbMF0KaWYoMD49bSlyZXR1cm4gSC5PSChuLDApCm49cy5OYyhwLG5bMF0pCnA9
-bn1lbHNlIHA9ITF9ZWxzZSBwPSExCmlmKCFwKWJyZWFrCkMuTm0uVzQoci5kLDApCkMuTm0uVzQoci5l
-LDEpCkMuTm0uVzQocS5kLDApCkMuTm0uVzQocS5lLDEpfXA9ci5kCm89cC5sZW5ndGgKaWYobyE9PTAp
-e2lmKDA+PW8pcmV0dXJuIEguT0gocCwwKQpwPUouUk0ocFswXSwiLi4iKX1lbHNlIHA9ITEKaWYocCl0
-aHJvdyBILmIoWC5JNyhrK0guRWooYSkrJyIgZnJvbSAiJytILkVqKGIpKyciLicpKQpwPXQuTgpDLk5t
-LlVHKHEuZCwwLFAuTzgoci5kLmxlbmd0aCwiLi4iLCExLHApKQpDLk5tLlk1KHEuZSwwLCIiKQpDLk5t
-LlVHKHEuZSwxLFAuTzgoci5kLmxlbmd0aCxzLmdtSSgpLCExLHApKQpzPXEuZApwPXMubGVuZ3RoCmlm
-KHA9PT0wKXJldHVybiIuIgppZihwPjEmJkouUk0oQy5ObS5ncloocyksIi4iKSl7cz1xLmQKaWYoMD49
-cy5sZW5ndGgpcmV0dXJuIEguT0gocywtMSkKcy5wb3AoKQpzPXEuZQppZigwPj1zLmxlbmd0aClyZXR1
-cm4gSC5PSChzLC0xKQpzLnBvcCgpCmlmKDA+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9w
-KCkKQy5ObS5pKHMsIiIpfXEuYj0iIgpxLkl4KCkKcmV0dXJuIHEudygwKX19Ck0ucTcucHJvdG90eXBl
-PXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEguaChhKSE9PSIifSwKJFM6Nn0KTS5Oby5wcm90b3R5cGU9
-ewokMTpmdW5jdGlvbihhKXtILmsoYSkKcmV0dXJuIGE9PW51bGw/Im51bGwiOiciJythKyciJ30sCiRT
-OjUwfQpCLmZ2LnByb3RvdHlwZT17CnhaOmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcy5ZcihhKQppZihy
-PjApcmV0dXJuIEoubGQoYSwwLHIpCmlmKHRoaXMuaEsoYSkpe2lmKDA+PWEubGVuZ3RoKXJldHVybiBI
-Lk9IKGEsMCkKcz1hWzBdfWVsc2Ugcz1udWxsCnJldHVybiBzfSwKTmM6ZnVuY3Rpb24oYSxiKXtyZXR1
-cm4gYT09Yn19ClguV0QucHJvdG90eXBlPXsKSXg6ZnVuY3Rpb24oKXt2YXIgcyxyLHE9dGhpcwp3aGls
-ZSghMCl7cz1xLmQKaWYoIShzLmxlbmd0aCE9PTAmJkouUk0oQy5ObS5ncloocyksIiIpKSlicmVhawpz
-PXEuZAppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCnM9cS5lCmlmKDA+PXMu
-bGVuZ3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9wKCl9cz1xLmUKcj1zLmxlbmd0aAppZihyIT09MClD
-Lk5tLlk1KHMsci0xLCIiKX0sCnJSOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG09dGhpcyxsPUgu
-Vk0oW10sdC5zKQpmb3Iocz1tLmQscj1zLmxlbmd0aCxxPTAscD0wO3A8cy5sZW5ndGg7cy5sZW5ndGg9
-PT1yfHwoMCxILmxrKShzKSwrK3Ape289c1twXQpuPUouaWEobykKaWYoIShuLkROKG8sIi4iKXx8bi5E
-TihvLCIiKSkpaWYobi5ETihvLCIuLiIpKXtuPWwubGVuZ3RoCmlmKG4hPT0wKXtpZigwPj1uKXJldHVy
-biBILk9IKGwsLTEpCmwucG9wKCl9ZWxzZSArK3F9ZWxzZSBDLk5tLmkobCxvKX1pZihtLmI9PW51bGwp
-Qy5ObS5VRyhsLDAsUC5POChxLCIuLiIsITEsdC5OKSkKaWYobC5sZW5ndGg9PT0wJiZtLmI9PW51bGwp
-Qy5ObS5pKGwsIi4iKQptLnNuSihsKQpzPW0uYQptLnNQaChQLk84KGwubGVuZ3RoKzEscy5nbUkoKSwh
-MCx0Lk4pKQpyPW0uYgppZihyPT1udWxsfHxsLmxlbmd0aD09PTB8fCFzLmRzKHIpKUMuTm0uWTUobS5l
-LDAsIiIpCnI9bS5iCmlmKHIhPW51bGwmJnM9PT0kLktrKCkpe3IudG9TdHJpbmcKbS5iPUgueXMociwi
-LyIsIlxcIil9bS5JeCgpfSwKdzpmdW5jdGlvbihhKXt2YXIgcyxyLHE9dGhpcyxwPXEuYgpwPXAhPW51
-bGw/cDoiIgpmb3Iocz0wO3M8cS5kLmxlbmd0aDsrK3Mpe3I9cS5lCmlmKHM+PXIubGVuZ3RoKXJldHVy
-biBILk9IKHIscykKcj1wK0guRWoocltzXSkKcD1xLmQKaWYocz49cC5sZW5ndGgpcmV0dXJuIEguT0go
-cCxzKQpwPXIrSC5FaihwW3NdKX1wKz1ILkVqKEMuTm0uZ3JaKHEuZSkpCnJldHVybiBwLmNoYXJDb2Rl
-QXQoMCk9PTA/cDpwfSwKc25KOmZ1bmN0aW9uKGEpe3RoaXMuZD10LkUuYShhKX0sCnNQaDpmdW5jdGlv
-bihhKXt0aGlzLmU9dC5FLmEoYSl9fQpYLmR2LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJu
-IlBhdGhFeGNlcHRpb246ICIrdGhpcy5hfSwKJGlSejoxfQpPLnpMLnByb3RvdHlwZT17Cnc6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMuZ29jKHRoaXMpfX0KRS5PRi5wcm90b3R5cGU9ewpVZDpmdW5jdGlvbihh
-KXtyZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3fSwKZHM6
-ZnVuY3Rpb24oYSl7dmFyIHM9YS5sZW5ndGgKcmV0dXJuIHMhPT0wJiZDLnhCLk8yKGEscy0xKSE9PTQ3
-fSwKU3A6ZnVuY3Rpb24oYSxiKXtpZihhLmxlbmd0aCE9PTAmJkMueEIuVyhhLDApPT09NDcpcmV0dXJu
-IDEKcmV0dXJuIDB9LApZcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0
-aW9uKGEpe3JldHVybiExfSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJuInBvc2l4In0sCmdtSTpmdW5jdGlv
-bigpe3JldHVybiIvIn19CkYucnUucHJvdG90eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIu
-dGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGE9PT00N30sCmRzOmZ1bmN0aW9uKGEpe3Zh
-ciBzPWEubGVuZ3RoCmlmKHM9PT0wKXJldHVybiExCmlmKEMueEIuTzIoYSxzLTEpIT09NDcpcmV0dXJu
-ITAKcmV0dXJuIEMueEIuVGMoYSwiOi8vIikmJnRoaXMuWXIoYSk9PT1zfSwKU3A6ZnVuY3Rpb24oYSxi
-KXt2YXIgcyxyLHEscCxvPWEubGVuZ3RoCmlmKG89PT0wKXJldHVybiAwCmlmKEMueEIuVyhhLDApPT09
-NDcpcmV0dXJuIDEKZm9yKHM9MDtzPG87KytzKXtyPUMueEIuVyhhLHMpCmlmKHI9PT00NylyZXR1cm4g
-MAppZihyPT09NTgpe2lmKHM9PT0wKXJldHVybiAwCnE9Qy54Qi5YVShhLCIvIixDLnhCLlFpKGEsIi8v
-IixzKzEpP3MrMzpzKQppZihxPD0wKXJldHVybiBvCmlmKCFifHxvPHErMylyZXR1cm4gcQppZighQy54
-Qi5uQyhhLCJmaWxlOi8vIikpcmV0dXJuIHEKaWYoIUIuWXUoYSxxKzEpKXJldHVybiBxCnA9cSszCnJl
-dHVybiBvPT09cD9wOnErNH19cmV0dXJuIDB9LApZcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChh
-LCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aCE9PTAmJkMueEIuVyhhLDApPT09NDd9
-LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4idXJsIn0sCmdtSTpmdW5jdGlvbigpe3JldHVybiIvIn19Ckwu
-SVYucHJvdG90eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIudGcoYSwiLyIpfSwKcjQ6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGE9PT00N3x8YT09PTkyfSwKZHM6ZnVuY3Rpb24oYSl7dmFyIHM9YS5sZW5n
-dGgKaWYocz09PTApcmV0dXJuITEKcz1DLnhCLk8yKGEscy0xKQpyZXR1cm4hKHM9PT00N3x8cz09PTky
-KX0sClNwOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPWEubGVuZ3RoCmlmKHE9PT0wKXJldHVybiAwCnM9
-Qy54Qi5XKGEsMCkKaWYocz09PTQ3KXJldHVybiAxCmlmKHM9PT05Mil7aWYocTwyfHxDLnhCLlcoYSwx
-KSE9PTkyKXJldHVybiAxCnI9Qy54Qi5YVShhLCJcXCIsMikKaWYocj4wKXtyPUMueEIuWFUoYSwiXFwi
-LHIrMSkKaWYocj4wKXJldHVybiByfXJldHVybiBxfWlmKHE8MylyZXR1cm4gMAppZighQi5PUyhzKSly
-ZXR1cm4gMAppZihDLnhCLlcoYSwxKSE9PTU4KXJldHVybiAwCnE9Qy54Qi5XKGEsMikKaWYoIShxPT09
-NDd8fHE9PT05MikpcmV0dXJuIDAKcmV0dXJuIDN9LApZcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5T
-cChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLllyKGEpPT09MX0sCk90OmZ1bmN0aW9u
-KGEsYil7dmFyIHMKaWYoYT09PWIpcmV0dXJuITAKaWYoYT09PTQ3KXJldHVybiBiPT09OTIKaWYoYT09
-PTkyKXJldHVybiBiPT09NDcKaWYoKGFeYikhPT0zMilyZXR1cm4hMQpzPWF8MzIKcmV0dXJuIHM+PTk3
-JiZzPD0xMjJ9LApOYzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscQppZihhPT1iKXJldHVybiEwCnM9YS5s
-ZW5ndGgKaWYocyE9PWIubGVuZ3RoKXJldHVybiExCmZvcihyPUouclkoYikscT0wO3E8czsrK3EpaWYo
-IXRoaXMuT3QoQy54Qi5XKGEscSksci5XKGIscSkpKXJldHVybiExCnJldHVybiEwfSwKZ29jOmZ1bmN0
-aW9uKCl7cmV0dXJuIndpbmRvd3MifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJuIlxcIn19OyhmdW5jdGlv
-biBhbGlhc2VzKCl7dmFyIHM9Si5Hdi5wcm90b3R5cGUKcy5VPXMudwpzLlNqPXMuZTcKcz1KLk1GLnBy
-b3RvdHlwZQpzLnQ9cy53CnM9UC5jWC5wcm90b3R5cGUKcy5HRz1zLmV2CnM9UC5NaC5wcm90b3R5cGUK
-cy54Yj1zLncKcz1XLmN2LnByb3RvdHlwZQpzLkRXPXMucjYKcz1XLm02LnByb3RvdHlwZQpzLmpGPXMu
-RWIKcz1QLkU0LnByb3RvdHlwZQpzLlVyPXMucQpzLmU0PXMuWTV9KSgpOyhmdW5jdGlvbiBpbnN0YWxs
-VGVhck9mZnMoKXt2YXIgcz1odW5rSGVscGVycy5fc3RhdGljXzEscj1odW5rSGVscGVycy5fc3RhdGlj
-XzAscT1odW5rSGVscGVycy5pbnN0YWxsSW5zdGFuY2VUZWFyT2ZmLHA9aHVua0hlbHBlcnMuaW5zdGFs
-bFN0YXRpY1RlYXJPZmYsbz1odW5rSGVscGVycy5faW5zdGFuY2VfMXUKcyhQLCJFWCIsIlpWIiw3KQpz
-KFAsInl0Iiwib0EiLDcpCnMoUCwicVciLCJCeiIsNykKcihQLCJVSSIsImVOIiwwKQpxKFAuUGYucHJv
-dG90eXBlLCJnWUoiLDAsMSxudWxsLFsiJDIiLCIkMSJdLFsidzAiLCJwbSJdLDI4LDApCnMoUCwiQ3ki
-LCJOQyIsNCkKcyhQLCJQSCIsIk10Iiw1KQpwKFcsInBTIiw0LG51bGwsWyIkNCJdLFsicUQiXSw4LDAp
-CnAoVywiVjQiLDQsbnVsbCxbIiQ0Il0sWyJRVyJdLDgsMCkKbyhQLkFzLnByb3RvdHlwZSwiZ3VNIiwi
-ViIsNSkKcyhQLCJpRyIsIndZIiw1MykKcyhQLCJ3MCIsImRVIiwzNikKcyhMLCJpUyIsImk2IiwyMCl9
-KSgpOyhmdW5jdGlvbiBpbmhlcml0YW5jZSgpe3ZhciBzPWh1bmtIZWxwZXJzLm1peGluLHI9aHVua0hl
-bHBlcnMuaW5oZXJpdCxxPWh1bmtIZWxwZXJzLmluaGVyaXRNYW55CnIoUC5NaCxudWxsKQpxKFAuTWgs
-W0guRkssSi5HdixKLm0xLFAuY1gsSC5FNyxQLlhTLFAublksSC5hNyxQLkFuLEguRnUsSC5KQixILlNV
-LEguUmUsSC53dixQLlBuLEguV1UsSC5MSSxILlRwLEguZjksSC50ZSxILmJxLEguWE8sSC5rcixQLllr
-LEgudmgsSC5ONixILlZSLEguRUssSC5QYixILnRRLEguU2QsSC5KYyxILkcsSC5sWSxQLlczLFAuaWgs
-UC5GeSxQLkdWLFAuUGYsUC5GZSxQLnZzLFAuT00sUC5xaCxQLk1PLFAua1QsUC54SSxQLkN3LFAubTAs
-UC5wUixQLmJuLFAubG0sUC5sRCxQLktQLFAubGYsUC5XWSxQLlVrLFAuU2gsUC5SdyxQLmJ6LFAuaVAs
-UC5rNSxQLktZLFAuQ0QsUC5hRSxQLk4zLFAuYzgsUC5aZCxQLlJuLFAuRG4sUC5QRSxQLlVmLFcuaWQs
-Vy5GayxXLkpRLFcuR20sVy52RCxXLm02LFcuT3csVy5XOSxXLmRXLFcubWssVy5LbyxQLmlKLFAuRTQs
-TS5INyxVLkxMLFUuZDIsVS5TZSxVLk1sLFUueUQsVS53YixCLmo4LEIucXAsVC5tUSxMLlhBLEwuRDgs
-TC5POSxMLkdiLE0ubEksTy56TCxYLldELFguZHZdKQpxKEouR3YsW0oueUUsSi53ZSxKLk1GLEouamQs
-Si5xSSxKLkRyLEguRVQsVy5EMCxXLkF6LFcuTGUsVy5OaCxXLmFlLFcuSUIsVy5uNyxXLmVhLFcuYnIs
-Vy5TZyxXLnc3LFcuSzcsVy5YVyxQLmhGXSkKcShKLk1GLFtKLmlDLEoua2QsSi5jNV0pCnIoSi5QbyxK
-LmpkKQpxKEoucUksW0ouYlUsSi5WQV0pCnEoUC5jWCxbSC5CUixILmJRLEguaTEsSC5VNSxILkFNLEgu
-dTYsSC5YUixQLm1XLEgudW5dKQpxKEguQlIsW0guWnksSC5RQ10pCnIoSC5vbCxILlp5KQpyKEguVXEs
-SC5RQykKcihILmpWLEguVXEpCnEoUC5YUyxbSC5uLEgucjMsSC5HTSxQLkV6LEguYXosSC52VixILkVx
-LFAuQzYsSC5rUyxQLlVkLFAuRixQLnUsUC5tcCxQLnViLFAuZHMsUC5saixQLlVWLFAuY10pCnIoUC51
-eSxQLm5ZKQpxKFAudXksW0gudzIsVy53eixXLmU3XSkKcihILnFqLEgudzIpCnEoSC5iUSxbSC5hTCxI
-Lk1CLEguaTVdKQpxKEguYUwsW0gubkgsSC5sSixQLmk4XSkKcihILnh5LEguaTEpCnEoUC5BbixbSC5N
-SCxILlNPLEguVTFdKQpyKEguZDUsSC5BTSkKcihQLlJVLFAuUG4pCnIoUC5HaixQLlJVKQpyKEguUEQs
-UC5HaikKcihILkxQLEguV1UpCnEoSC5UcCxbSC5DaixILmxjLEguZEMsSC53TixILlZYLFAudGgsUC5o
-YSxQLlZzLFAuRnQsUC55SCxQLldNLFAuU1gsUC5HcyxQLmRhLFAub1EsUC5wVixQLlU3LFAudnIsUC5y
-dCxQLktGLFAuWkwsUC5SVCxQLmpaLFAucnEsUC5SVyxQLkI1LFAudU8sUC5wSyxQLmhqLFAuVnAsUC5P
-UixQLnJhLFAueVEsUC5wZyxQLmMyLFAudGksUC5XRixQLm4xLFAuY1MsUC5WQyxQLkpULFAuUlosUC5N
-RSxQLnk1LFAueUksUC5jNixQLnFkLFcuQ3YsVy5LUyxXLkEzLFcudk4sVy5VdixXLkVnLFcuRW8sVy5X
-ayxXLklBLFcuZm0sUC5qZyxQLlRhLFAuR0UsUC5ONyxQLnVRLFAuUEMsUC5tdCxQLk56LFAuUVMsUC5u
-cCxVLk1ELFUuYU4sVS5iMCxMLmUsTC5WVyxMLm9aLEwuanIsTC5xbCxMLkhpLEwuQlQsTC5QWSxMLnU4
-LEwuTCxMLld4LEwuQU8sTC5kTixMLkhvLEwueHosTC5JQyxMLmZDLEwublQsTC5OWSxMLnVlLEwuZVgs
-TC5FRSxMLlFMLEwuVlMsTC5URCxMLm0yLE0ucTcsTS5Ob10pCnIoSC5XMCxQLkV6KQpxKEgubGMsW0gu
-engsSC5yVF0pCnIoSC5rWSxQLkM2KQpyKFAuaWwsUC5ZaykKcShQLmlsLFtILk41LFAudXcsVy5jZixX
-LlN5XSkKcShQLm1XLFtILktXLFAucTRdKQpyKEguTFosSC5FVCkKcShILkxaLFtILlJHLEguV0JdKQpy
-KEguVlAsSC5SRykKcihILkRnLEguVlApCnIoSC5aRyxILldCKQpyKEguUGcsSC5aRykKcShILlBnLFtI
-LnhqLEguZEUsSC5aQSxILmRULEguUHEsSC5lRSxILlY2XSkKcihILmlNLEgua1MpCnIoUC5aZixQLlBm
-KQpyKFAuSmksUC5tMCkKcihQLlh2LFAucFIpCnIoUC5iNixQLlh2KQpyKFAuVmosUC5XWSkKcShQLlVr
-LFtQLkNWLFAuWmksUC5ieV0pCnIoUC53SSxQLmtUKQpxKFAud0ksW1AuVTgsUC5vaixQLk14LFAuRTMs
-UC5HWV0pCnIoUC5LOCxQLlVkKQpyKFAudHUsUC5TaCkKcihQLnU1LFAuWmkpCnEoUC51LFtQLmJKLFAu
-ZVldKQpyKFAucWUsUC5EbikKcShXLkQwLFtXLnVILFcud2EsVy5LNSxXLkNtXSkKcShXLnVILFtXLmN2
-LFcubngsVy5RRixXLkNRXSkKcShXLmN2LFtXLnFFLFAuaGldKQpxKFcucUUsW1cuR2gsVy5mWSxXLm5C
-LFcuUVAsVy5oNCxXLlNOLFcubHAsVy5UYixXLkl2LFcuV1AsVy55WV0pCnIoVy5vSixXLkxlKQpyKFcu
-aEgsVy5BeikKcihXLlZiLFcuUUYpCnIoVy5mSixXLndhKQpxKFcuZWEsW1cudzYsVy5ld10pCnIoVy5B
-aixXLnc2KQpyKFcuckIsVy5LNykKcihXLkJILFcuckIpCnIoVy53NCxXLklCKQpyKFcub2EsVy5YVykK
-cihXLnJoLFcub2EpCnIoVy5pNyxXLmNmKQpyKFAuQXMsUC5WaikKcShQLkFzLFtXLkk0LFAuS2VdKQpy
-KFcuUk8sUC5xaCkKcihXLmV1LFcuUk8pCnIoVy54QyxQLk1PKQpyKFcuY3QsVy5tNikKcihQLkJmLFAu
-aUopCnEoUC5FNCxbUC5yNyxQLmNvXSkKcihQLlR6LFAuY28pCnIoUC5uZCxQLmhpKQpxKEwuRDgsW0wu
-dnQsTC5jRF0pCnIoQi5mdixPLnpMKQpxKEIuZnYsW0UuT0YsRi5ydSxMLklWXSkKcyhILncyLEguUmUp
-CnMoSC5RQyxQLmxEKQpzKEguUkcsUC5sRCkKcyhILlZQLEguU1UpCnMoSC5XQixQLmxEKQpzKEguWkcs
-SC5TVSkKcyhQLm5ZLFAubEQpCnMoUC5XWSxQLmxmKQpzKFAuUlUsUC5LUCkKcyhQLnBSLFAubGYpCnMo
-Vy5MZSxXLmlkKQpzKFcuSzcsUC5sRCkKcyhXLnJCLFcuR20pCnMoVy5YVyxQLmxEKQpzKFcub2EsVy5H
-bSkKcyhQLmNvLFAubEQpfSkoKQp2YXIgdj17dHlwZVVuaXZlcnNlOntlQzpuZXcgTWFwKCksdFI6e30s
-ZVQ6e30sdFBWOnt9LHNFQTpbXX0sbWFuZ2xlZEdsb2JhbE5hbWVzOntJZjoiaW50IixDUDoiZG91Ymxl
-IixaWjoibnVtIixxVToiU3RyaW5nIixhMjoiYm9vbCIsYzg6Ik51bGwiLHpNOiJMaXN0In0sbWFuZ2xl
-ZE5hbWVzOnt9LGdldFR5cGVGcm9tTmFtZTpnZXRHbG9iYWxGcm9tTmFtZSxtZXRhZGF0YTpbXSx0eXBl
-czpbIn4oKSIsImM4KEFqKikiLCJjOCgpIiwiYzgoY3YqKSIsIkAoQCkiLCJxVShxVSkiLCJhMihxVSki
-LCJ+KH4oKSkiLCJhMihjdixxVSxxVSxKUSkiLCJjOChAKSIsIn4oTWg/LE1oPykiLCJAKCkiLCJ+KHFV
-LEApIiwifihuNixxVSxJZikiLCJ+KHFVLHFVKSIsImEyKGtGKSIsImM4KEAsQCkiLCJ+KHh1PHFVPiki
-LCJjOChlYSopIiwiYjg8Yzg+KihBaiopIiwifihBaiopIiwifihxVSxJZikiLCJ+KHFVLHFVPykiLCJu
-NihALEApIiwiYzgoQCxHeikiLCJhMih1SCkiLCJ+KElmLEApIiwifihlYSkiLCJ+KE1oW0d6P10pIiwi
-YzgoTWgsR3opIiwifih1SCx1SD8pIiwifihALEApIiwidnM8QD4oQCkiLCJhMih4dTxxVT4pIiwiYzgo
-figpKSIsInI3KEApIiwiTWg/KEApIiwiRTQoQCkiLCJhMiooSDcqKSIsIkxMKihAKSIsIlowPHFVKixN
-aCo+KihMTCopIiwiQChxVSkiLCJ+KEdELEApIiwiYzgoWjA8cVUqLE1oKj4qKSIsIlowPHFVLHFVPiha
-MDxxVSxxVT4scVUpIiwicVUqKEFqKikiLCJAKEAscVUpIiwiYzgoZXcqKSIsInFVKihaMDxALEA+Kiki
-LCJ+KHFVW0BdKSIsInFVKHFVPykiLCJJZihJZixJZikiLCJ+KEApIiwiTWg/KE1oPykiLCJUejxAPihA
-KSJdLGludGVyY2VwdG9yc0J5VGFnOm51bGwsbGVhZlRhZ3M6bnVsbCxhcnJheVJ0aTp0eXBlb2YgU3lt
-Ym9sPT0iZnVuY3Rpb24iJiZ0eXBlb2YgU3ltYm9sKCk9PSJzeW1ib2wiP1N5bWJvbCgiJHRpIik6IiR0
-aSJ9CkgueGIodi50eXBlVW5pdmVyc2UsSlNPTi5wYXJzZSgneyJjNSI6Ik1GIiwiaUMiOiJNRiIsImtk
-IjoiTUYiLCJyeCI6ImVhIiwiZTUiOiJlYSIsIlkwIjoiaGkiLCJ0cCI6ImhpIiwiRzgiOiJldyIsIk1y
-IjoicUUiLCJlTCI6InFFIiwiSTAiOiJ1SCIsImhzIjoidUgiLCJYZyI6IlFGIiwibnIiOiJBaiIsInk0
-IjoidzYiLCJhUCI6IkNtIiwieGMiOiJueCIsImtKIjoibngiLCJ6VSI6IkRnIiwiZGYiOiJFVCIsInlF
-Ijp7ImEyIjpbXX0sIndlIjp7ImM4IjpbXX0sIk1GIjp7InZtIjpbXSwiRUgiOltdfSwiamQiOnsiek0i
-OlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXX0sIlBvIjp7ImpkIjpbIjEiXSwiek0iOlsiMSJdLCJi
-USI6WyIxIl0sImNYIjpbIjEiXX0sIm0xIjp7IkFuIjpbIjEiXX0sInFJIjp7IkNQIjpbXSwiWloiOltd
-fSwiYlUiOnsiQ1AiOltdLCJJZiI6W10sIlpaIjpbXX0sIlZBIjp7IkNQIjpbXSwiWloiOltdfSwiRHIi
-OnsicVUiOltdLCJ2WCI6W119LCJCUiI6eyJjWCI6WyIyIl19LCJFNyI6eyJBbiI6WyIyIl19LCJaeSI6
-eyJCUiI6WyIxIiwiMiJdLCJjWCI6WyIyIl0sImNYLkUiOiIyIn0sIm9sIjp7Ilp5IjpbIjEiLCIyIl0s
-IkJSIjpbIjEiLCIyIl0sImJRIjpbIjIiXSwiY1giOlsiMiJdLCJjWC5FIjoiMiJ9LCJVcSI6eyJsRCI6
-WyIyIl0sInpNIjpbIjIiXSwiQlIiOlsiMSIsIjIiXSwiYlEiOlsiMiJdLCJjWCI6WyIyIl19LCJqViI6
-eyJVcSI6WyIxIiwiMiJdLCJsRCI6WyIyIl0sInpNIjpbIjIiXSwiQlIiOlsiMSIsIjIiXSwiYlEiOlsi
-MiJdLCJjWCI6WyIyIl0sImxELkUiOiIyIiwiY1guRSI6IjIifSwibiI6eyJYUyI6W119LCJyMyI6eyJY
-UyI6W119LCJxaiI6eyJsRCI6WyJJZiJdLCJSZSI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJiUSI6WyJJZiJd
-LCJjWCI6WyJJZiJdLCJsRC5FIjoiSWYiLCJSZS5FIjoiSWYifSwiR00iOnsiWFMiOltdfSwiYlEiOnsi
-Y1giOlsiMSJdfSwiYUwiOnsiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJuSCI6eyJhTCI6WyIxIl0sImJR
-IjpbIjEiXSwiY1giOlsiMSJdLCJhTC5FIjoiMSIsImNYLkUiOiIxIn0sImE3Ijp7IkFuIjpbIjEiXX0s
-ImkxIjp7ImNYIjpbIjIiXSwiY1guRSI6IjIifSwieHkiOnsiaTEiOlsiMSIsIjIiXSwiYlEiOlsiMiJd
-LCJjWCI6WyIyIl0sImNYLkUiOiIyIn0sIk1IIjp7IkFuIjpbIjIiXX0sImxKIjp7ImFMIjpbIjIiXSwi
-YlEiOlsiMiJdLCJjWCI6WyIyIl0sImFMLkUiOiIyIiwiY1guRSI6IjIifSwiVTUiOnsiY1giOlsiMSJd
-LCJjWC5FIjoiMSJ9LCJTTyI6eyJBbiI6WyIxIl19LCJBTSI6eyJjWCI6WyIxIl0sImNYLkUiOiIxIn0s
-ImQ1Ijp7IkFNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIlUxIjp7IkFu
-IjpbIjEiXX0sIk1CIjp7ImJRIjpbIjEiXSwiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJGdSI6eyJBbiI6
-WyIxIl19LCJ1NiI6eyJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIkpCIjp7IkFuIjpbIjEiXX0sIncyIjp7
-ImxEIjpbIjEiXSwiUmUiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwid3Yi
-OnsiR0QiOltdfSwiUEQiOnsiR2oiOlsiMSIsIjIiXSwiUlUiOlsiMSIsIjIiXSwiUG4iOlsiMSIsIjIi
-XSwiS1AiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIldVIjp7IlowIjpbIjEiLCIyIl19LCJMUCI6
-eyJXVSI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiWFIiOnsiY1giOlsiMSJdLCJjWC5FIjoiMSJ9
-LCJMSSI6eyJ2USI6W119LCJXMCI6eyJYUyI6W119LCJheiI6eyJYUyI6W119LCJ2ViI6eyJYUyI6W119
-LCJ0ZSI6eyJSeiI6W119LCJYTyI6eyJHeiI6W119LCJUcCI6eyJFSCI6W119LCJsYyI6eyJFSCI6W119
-LCJ6eCI6eyJFSCI6W119LCJyVCI6eyJFSCI6W119LCJFcSI6eyJYUyI6W119LCJrWSI6eyJYUyI6W119
-LCJONSI6eyJZayI6WyIxIiwiMiJdLCJGbyI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdLCJZay5LIjoi
-MSIsIllrLlYiOiIyIn0sImk1Ijp7ImJRIjpbIjEiXSwiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJONiI6
-eyJBbiI6WyIxIl19LCJWUiI6eyJ3TCI6W10sInZYIjpbXX0sIkVLIjp7ImliIjpbXSwiT2QiOltdfSwi
-S1ciOnsiY1giOlsiaWIiXSwiY1guRSI6ImliIn0sIlBiIjp7IkFuIjpbImliIl19LCJ0USI6eyJPZCI6
-W119LCJ1biI6eyJjWCI6WyJPZCJdLCJjWC5FIjoiT2QifSwiU2QiOnsiQW4iOlsiT2QiXX0sIkVUIjp7
-IkFTIjpbXX0sIkxaIjp7IlhqIjpbIjEiXSwiRVQiOltdLCJBUyI6W119LCJEZyI6eyJsRCI6WyJDUCJd
-LCJYaiI6WyJDUCJdLCJ6TSI6WyJDUCJdLCJFVCI6W10sImJRIjpbIkNQIl0sIkFTIjpbXSwiY1giOlsi
-Q1AiXSwiU1UiOlsiQ1AiXSwibEQuRSI6IkNQIn0sIlBnIjp7ImxEIjpbIklmIl0sIlhqIjpbIklmIl0s
-InpNIjpbIklmIl0sIkVUIjpbXSwiYlEiOlsiSWYiXSwiQVMiOltdLCJjWCI6WyJJZiJdLCJTVSI6WyJJ
-ZiJdfSwieGoiOnsibEQiOlsiSWYiXSwiWGoiOlsiSWYiXSwiek0iOlsiSWYiXSwiRVQiOltdLCJiUSI6
-WyJJZiJdLCJBUyI6W10sImNYIjpbIklmIl0sIlNVIjpbIklmIl0sImxELkUiOiJJZiJ9LCJkRSI6eyJs
-RCI6WyJJZiJdLCJYaiI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJFVCI6W10sImJRIjpbIklmIl0sIkFTIjpb
-XSwiY1giOlsiSWYiXSwiU1UiOlsiSWYiXSwibEQuRSI6IklmIn0sIlpBIjp7ImxEIjpbIklmIl0sIlhq
-IjpbIklmIl0sInpNIjpbIklmIl0sIkVUIjpbXSwiYlEiOlsiSWYiXSwiQVMiOltdLCJjWCI6WyJJZiJd
-LCJTVSI6WyJJZiJdLCJsRC5FIjoiSWYifSwiZFQiOnsibEQiOlsiSWYiXSwiWGoiOlsiSWYiXSwiek0i
-OlsiSWYiXSwiRVQiOltdLCJiUSI6WyJJZiJdLCJBUyI6W10sImNYIjpbIklmIl0sIlNVIjpbIklmIl0s
-ImxELkUiOiJJZiJ9LCJQcSI6eyJsRCI6WyJJZiJdLCJYaiI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJFVCI6
-W10sImJRIjpbIklmIl0sIkFTIjpbXSwiY1giOlsiSWYiXSwiU1UiOlsiSWYiXSwibEQuRSI6IklmIn0s
-ImVFIjp7ImxEIjpbIklmIl0sIlhqIjpbIklmIl0sInpNIjpbIklmIl0sIkVUIjpbXSwiYlEiOlsiSWYi
-XSwiQVMiOltdLCJjWCI6WyJJZiJdLCJTVSI6WyJJZiJdLCJsRC5FIjoiSWYifSwiVjYiOnsibEQiOlsi
-SWYiXSwibjYiOltdLCJYaiI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJFVCI6W10sImJRIjpbIklmIl0sIkFT
-IjpbXSwiY1giOlsiSWYiXSwiU1UiOlsiSWYiXSwibEQuRSI6IklmIn0sImtTIjp7IlhTIjpbXX0sImlN
-Ijp7IlhTIjpbXX0sIkdWIjp7IkFuIjpbIjEiXX0sInE0Ijp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwi
-WmYiOnsiUGYiOlsiMSJdfSwidnMiOnsiYjgiOlsiMSJdfSwiQ3ciOnsiWFMiOltdfSwibTAiOnsiUW0i
-OltdfSwiSmkiOnsibTAiOltdLCJRbSI6W119LCJiNiI6eyJsZiI6WyIxIl0sInh1IjpbIjEiXSwiYlEi
-OlsiMSJdLCJjWCI6WyIxIl0sImxmLkUiOiIxIn0sImxtIjp7IkFuIjpbIjEiXX0sIm1XIjp7ImNYIjpb
-IjEiXX0sInV5Ijp7ImxEIjpbIjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXX0sImls
-Ijp7IllrIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJZayI6eyJaMCI6WyIxIiwiMiJdfSwiUG4i
-OnsiWjAiOlsiMSIsIjIiXX0sIkdqIjp7IlJVIjpbIjEiLCIyIl0sIlBuIjpbIjEiLCIyIl0sIktQIjpb
-IjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJWaiI6eyJsZiI6WyIxIl0sInh1IjpbIjEiXSwiYlEiOlsi
-MSJdLCJjWCI6WyIxIl19LCJYdiI6eyJsZiI6WyIxIl0sInh1IjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6
-WyIxIl19LCJ1dyI6eyJZayI6WyJxVSIsIkAiXSwiWjAiOlsicVUiLCJAIl0sIllrLksiOiJxVSIsIllr
-LlYiOiJAIn0sImk4Ijp7ImFMIjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl0sImFMLkUiOiJx
-VSIsImNYLkUiOiJxVSJ9LCJDViI6eyJVayI6WyJ6TTxJZj4iLCJxVSJdLCJVay5TIjoiek08SWY+In0s
-IlU4Ijp7IndJIjpbInpNPElmPiIsInFVIl19LCJaaSI6eyJVayI6WyJxVSIsInpNPElmPiJdfSwiVWQi
-OnsiWFMiOltdfSwiSzgiOnsiWFMiOltdfSwiYnkiOnsiVWsiOlsiTWg/IiwicVUiXSwiVWsuUyI6Ik1o
-PyJ9LCJvaiI6eyJ3SSI6WyJNaD8iLCJxVSJdfSwiTXgiOnsid0kiOlsicVUiLCJNaD8iXX0sInU1Ijp7
-IlVrIjpbInFVIiwiek08SWY+Il0sIlVrLlMiOiJxVSJ9LCJFMyI6eyJ3SSI6WyJxVSIsInpNPElmPiJd
-fSwiR1kiOnsid0kiOlsiek08SWY+IiwicVUiXX0sIkNQIjp7IlpaIjpbXX0sIklmIjp7IlpaIjpbXX0s
-InpNIjp7ImJRIjpbIjEiXSwiY1giOlsiMSJdfSwiaWIiOnsiT2QiOltdfSwieHUiOnsiYlEiOlsiMSJd
-LCJjWCI6WyIxIl19LCJxVSI6eyJ2WCI6W119LCJDNiI6eyJYUyI6W119LCJFeiI6eyJYUyI6W119LCJG
-Ijp7IlhTIjpbXX0sInUiOnsiWFMiOltdfSwiYkoiOnsiWFMiOltdfSwiZVkiOnsiWFMiOltdfSwibXAi
-OnsiWFMiOltdfSwidWIiOnsiWFMiOltdfSwiZHMiOnsiWFMiOltdfSwibGoiOnsiWFMiOltdfSwiVVYi
-OnsiWFMiOltdfSwiazUiOnsiWFMiOltdfSwiS1kiOnsiWFMiOltdfSwiYyI6eyJYUyI6W119LCJDRCI6
-eyJSeiI6W119LCJhRSI6eyJSeiI6W119LCJaZCI6eyJHeiI6W119LCJSbiI6eyJCTCI6W119LCJEbiI6
-eyJpRCI6W119LCJVZiI6eyJpRCI6W119LCJxZSI6eyJpRCI6W119LCJxRSI6eyJjdiI6W10sInVIIjpb
-XSwiRDAiOltdfSwiR2giOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sImZZIjp7ImN2IjpbXSwidUgi
-OltdLCJEMCI6W119LCJuQiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiUVAiOnsiY3YiOltdLCJ1
-SCI6W10sIkQwIjpbXX0sIm54Ijp7InVIIjpbXSwiRDAiOltdfSwiUUYiOnsidUgiOltdLCJEMCI6W119
-LCJJQiI6eyJ0biI6WyJaWiJdfSwid3oiOnsibEQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwi
-Y1giOlsiMSJdLCJsRC5FIjoiMSJ9LCJjdiI6eyJ1SCI6W10sIkQwIjpbXX0sImhIIjp7IkF6IjpbXX0s
-Img0Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJWYiI6eyJ1SCI6W10sIkQwIjpbXX0sImZKIjp7
-IkQwIjpbXX0sIndhIjp7IkQwIjpbXX0sIkFqIjp7ImVhIjpbXX0sImU3Ijp7ImxEIjpbInVIIl0sInpN
-IjpbInVIIl0sImJRIjpbInVIIl0sImNYIjpbInVIIl0sImxELkUiOiJ1SCJ9LCJ1SCI6eyJEMCI6W119
-LCJCSCI6eyJsRCI6WyJ1SCJdLCJHbSI6WyJ1SCJdLCJ6TSI6WyJ1SCJdLCJYaiI6WyJ1SCJdLCJiUSI6
-WyJ1SCJdLCJjWCI6WyJ1SCJdLCJsRC5FIjoidUgiLCJHbS5FIjoidUgifSwiU04iOnsiY3YiOltdLCJ1
-SCI6W10sIkQwIjpbXX0sImV3Ijp7ImVhIjpbXX0sImxwIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119
-LCJUYiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiSXYiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpb
-XX0sIldQIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJ5WSI6eyJjdiI6W10sInVIIjpbXSwiRDAi
-OltdfSwidzYiOnsiZWEiOltdfSwiSzUiOnsidjYiOltdLCJEMCI6W119LCJDbSI6eyJEMCI6W119LCJD
-USI6eyJ1SCI6W10sIkQwIjpbXX0sInc0Ijp7InRuIjpbIlpaIl19LCJyaCI6eyJsRCI6WyJ1SCJdLCJH
-bSI6WyJ1SCJdLCJ6TSI6WyJ1SCJdLCJYaiI6WyJ1SCJdLCJiUSI6WyJ1SCJdLCJjWCI6WyJ1SCJdLCJs
-RC5FIjoidUgiLCJHbS5FIjoidUgifSwiY2YiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFV
-Il19LCJpNyI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXSwiWWsuSyI6InFVIiwiWWsu
-ViI6InFVIn0sIlN5Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUi
-LCJZay5WIjoicVUifSwiSTQiOnsibGYiOlsicVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUiXSwiY1gi
-OlsicVUiXSwibGYuRSI6InFVIn0sIlJPIjp7InFoIjpbIjEiXX0sImV1Ijp7IlJPIjpbIjEiXSwicWgi
-OlsiMSJdfSwieEMiOnsiTU8iOlsiMSJdfSwiSlEiOnsia0YiOltdfSwidkQiOnsia0YiOltdfSwibTYi
-Onsia0YiOltdfSwiY3QiOnsia0YiOltdfSwiT3ciOnsia0YiOltdfSwiVzkiOnsiQW4iOlsiMSJdfSwi
-ZFciOnsidjYiOltdLCJEMCI6W119LCJtayI6eyJ5MCI6W119LCJLbyI6eyJvbiI6W119LCJBcyI6eyJs
-ZiI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJiUSI6WyJxVSJdLCJjWCI6WyJxVSJdfSwicjciOnsiRTQiOltd
-fSwiVHoiOnsibEQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiRTQiOltdLCJjWCI6WyIxIl0s
-ImxELkUiOiIxIn0sIm5kIjp7ImhpIjpbXSwiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIktlIjp7Imxm
-IjpbInFVIl0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl0sImxmLkUiOiJxVSJ9LCJo
-aSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiWEEiOnsia0YiOltdfSwidnQiOnsiRDgiOltdfSwi
-Y0QiOnsiRDgiOltdfSwiZHYiOnsiUnoiOltdfSwiT0YiOnsiZnYiOltdfSwicnUiOnsiZnYiOltdfSwi
-SVYiOnsiZnYiOltdfSwibjYiOnsiek0iOlsiSWYiXSwiYlEiOlsiSWYiXSwiY1giOlsiSWYiXSwiQVMi
-OltdfX0nKSkKSC5GRih2LnR5cGVVbml2ZXJzZSxKU09OLnBhcnNlKCd7IncyIjoxLCJRQyI6MiwiTFoi
-OjEsImtUIjoyLCJtVyI6MSwidXkiOjEsImlsIjoyLCJWaiI6MSwiWHYiOjEsIm5ZIjoxLCJXWSI6MSwi
-cFIiOjEsImNvIjoxfScpKQp2YXIgdT17bDoiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBh
-IFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IixpOiJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0
-aCBmcm9tIGEgVVJJIHdpdGggYSBxdWVyeSBjb21wb25lbnQiLGo6IkNhbm5vdCBleHRyYWN0IGEgbm9u
-LVdpbmRvd3MgZmlsZSBwYXRoIGZyb20gYSBmaWxlIFVSSSB3aXRoIGFuIGF1dGhvcml0eSIsZzoiYG51
-bGxgIGVuY291bnRlcmVkIGFzIHRoZSByZXN1bHQgZnJvbSBleHByZXNzaW9uIHdpdGggdHlwZSBgTmV2
-ZXJgLiIsZDoiYXJlYS1hbmFseXplcixhbmFseXplci1ubmJkLW1pZ3JhdGlvbix0eXBlLWJ1ZyJ9CnZh
-ciB0PShmdW5jdGlvbiBydGlpKCl7dmFyIHM9SC5OMApyZXR1cm57bjpzKCJDdyIpLGNSOnMoIm5CIiks
-dzpzKCJBeiIpLHA6cygiUVAiKSxnRjpzKCJQRDxHRCxAPiIpLGI6cygiYlE8QD4iKSxoOnMoImN2Iiks
-cjpzKCJYUyIpLEI6cygiZWEiKSxhUzpzKCJEMCIpLGc4OnMoIlJ6IiksYzg6cygiaEgiKSxZOnMoIkVI
-IiksZDpzKCJiODxAPiIpLEk6cygiU2ciKSxvOnMoInZRIiksZWg6cygiY1g8dUg+IiksUTpzKCJjWDxx
-VT4iKSx1OnMoImNYPEA+IiksdjpzKCJqZDxrRj4iKSxzOnMoImpkPHFVPiIpLGdOOnMoImpkPG42PiIp
-LHg6cygiamQ8QD4iKSxhOnMoImpkPElmPiIpLGQ3OnMoImpkPFNlKj4iKSxoNDpzKCJqZDxqOCo+Iiks
-RzpzKCJqZDxaMDxxVSosTWgqPio+IiksY1E6cygiamQ8RDgqPiIpLGk6cygiamQ8cVUqPiIpLGFBOnMo
-ImpkPHlEKj4iKSxhSjpzKCJqZDx3Yio+IiksVjpzKCJqZDxJZio+IiksZDQ6cygiamQ8cVU/PiIpLFQ6
-cygid2UiKSxlSDpzKCJ2bSIpLEQ6cygiYzUiKSxhVTpzKCJYajxAPiIpLGFtOnMoIlR6PEA+IiksZW86
-cygiTjU8R0QsQD4iKSxkejpzKCJoRiIpLEU6cygiek08cVU+IiksajpzKCJ6TTxAPiIpLEw6cygiek08
-SWY+IiksSjpzKCJaMDxxVSxxVT4iKSxmOnMoIlowPEAsQD4iKSxkbzpzKCJsSjxxVSxAPiIpLGZqOnMo
-ImxKPHFVKixxVT4iKSxkRTpzKCJFVCIpLGJtOnMoIlY2IiksQTpzKCJ1SCIpLGY2OnMoImtGIiksUDpz
-KCJjOCIpLEs6cygiTWgiKSxxOnMoInRuPFpaPiIpLGZ2OnMoIndMIiksZXc6cygibmQiKSxDOnMoInh1
-PHFVPiIpLGw6cygiR3oiKSxOOnMoInFVIiksZDA6cygicVUocVUqKSIpLGc3OnMoImhpIiksZm86cygi
-R0QiKSxhVzpzKCJ5WSIpLGFrOnMoIkFTIiksZ2M6cygibjYiKSxiSjpzKCJrZCIpLGR3OnMoIkdqPHFV
-LHFVPiIpLGREOnMoImlEIiksZUo6cygidTY8cVU+IiksZzQ6cygiSzUiKSxjaTpzKCJ2NiIpLGcyOnMo
-IkNtIiksYkM6cygiWmY8ZkoqPiIpLGg5OnMoIkNRIiksYWM6cygiZTciKSxrOnMoImV1PEFqKj4iKSxS
-OnMoInd6PGN2Kj4iKSxjOnMoInZzPEA+IiksZko6cygidnM8SWY+IiksZ1Y6cygidnM8ZkoqPiIpLGNy
-OnMoIkpRIikseTpzKCJhMiIpLGFsOnMoImEyKE1oKSIpLGdSOnMoIkNQIiksejpzKCJAIiksZk86cygi
-QCgpIiksYkk6cygiQChNaCkiKSxhZzpzKCJAKE1oLEd6KSIpLGJVOnMoIkAoeHU8cVU+KSIpLGRPOnMo
-IkAocVUpIiksYjg6cygiQChALEApIiksUzpzKCJJZiIpLGRkOnMoIkdoKiIpLGc6cygiY3YqIiksYUw6
-cygiZWEqIiksYVg6cygiTEwqIiksZkU6cygiSDcqIiksVTpzKCJjWDxAPioiKSxkSDpzKCJFNCoiKSxm
-SzpzKCJ6TTxAPioiKSxkXzpzKCJ6TTxqOCo+KiIpLGRwOnMoInpNPFowPHFVKixNaCo+Kj4qIiksbTpz
-KCJ6TTxNaCo+KiIpLGF3OnMoIlowPEAsQD4qIiksdDpzKCJaMDxxVSosTWgqPioiKSxPOnMoIkFqKiIp
-LGNGOnMoIjAmKiIpLF86cygiTWgqIiksZVE6cygiZXcqIiksWDpzKCJxVSoiKSxjaDpzKCJEMD8iKSxi
-RzpzKCJiODxjOD4/IiksYms6cygiek08cVU+PyIpLGJNOnMoInpNPEA+PyIpLGNaOnMoIlowPHFVLHFV
-Pj8iKSxjOTpzKCJaMDxxVSxAPj8iKSxXOnMoIk1oPyIpLEY6cygiRmU8QCxAPj8iKSxlOnMoImJuPyIp
-LGI3OnMoImEyKE1oKT8iKSxidzpzKCJAKGVhKT8iKSxmVjpzKCJNaD8oTWg/LE1oPyk/IiksZEE6cygi
-TWg/KEApPyIpLFo6cygifigpPyIpLGViOnMoIn4oZXcqKT8iKSxkaTpzKCJaWiIpLEg6cygifiIpLE06
-cygifigpIiksZUE6cygifihxVSxxVSkiKSxjQTpzKCJ+KHFVLEApIil9fSkoKTsoZnVuY3Rpb24gY29u
-c3RhbnRzKCl7dmFyIHM9aHVua0hlbHBlcnMubWFrZUNvbnN0TGlzdApDLnhuPVcuR2gucHJvdG90eXBl
-CkMuUlk9Vy5RUC5wcm90b3R5cGUKQy5tSD1XLmFlLnByb3RvdHlwZQpDLkJaPVcuVmIucHJvdG90eXBl
-CkMuRHQ9Vy5mSi5wcm90b3R5cGUKQy5Paz1KLkd2LnByb3RvdHlwZQpDLk5tPUouamQucHJvdG90eXBl
-CkMuam49Si5iVS5wcm90b3R5cGUKQy5qTj1KLndlLnByb3RvdHlwZQpDLkNEPUoucUkucHJvdG90eXBl
-CkMueEI9Si5Eci5wcm90b3R5cGUKQy5ERz1KLmM1LnByb3RvdHlwZQpDLkV4PVcudzcucHJvdG90eXBl
-CkMuTkE9SC5WNi5wcm90b3R5cGUKQy50NT1XLkJILnByb3RvdHlwZQpDLkx0PVcuU04ucHJvdG90eXBl
-CkMuWlE9Si5pQy5wcm90b3R5cGUKQy5JZT1XLlRiLnByb3RvdHlwZQpDLnZCPUoua2QucHJvdG90eXBl
-CkMub2w9Vy5LNS5wcm90b3R5cGUKQy55OD1uZXcgUC5VOCgpCkMuaDk9bmV3IFAuQ1YoKQpDLkd3PW5l
-dyBILkZ1KEguTjAoIkZ1PGM4PiIpKQpDLk80PWZ1bmN0aW9uIGdldFRhZ0ZhbGxiYWNrKG8pIHsKICB2
-YXIgcyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTsKICByZXR1cm4gcy5zdWJzdHJp
-bmcoOCwgcy5sZW5ndGggLSAxKTsKfQpDLllxPWZ1bmN0aW9uKCkgewogIHZhciB0b1N0cmluZ0Z1bmN0
-aW9uID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKICBmdW5jdGlvbiBnZXRUYWcobykgewogICAg
-dmFyIHMgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwobyk7CiAgICByZXR1cm4gcy5zdWJzdHJpbmcoOCwg
-cy5sZW5ndGggLSAxKTsKICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRhZykgewog
-ICAgaWYgKC9eSFRNTFtBLVpdLipFbGVtZW50JC8udGVzdCh0YWcpKSB7CiAgICAgIHZhciBuYW1lID0g
-dG9TdHJpbmdGdW5jdGlvbi5jYWxsKG9iamVjdCk7CiAgICAgIGlmIChuYW1lID09ICJbb2JqZWN0IE9i
-amVjdF0iKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAgICB9CiAgfQog
-IGZ1bmN0aW9uIGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlcihvYmplY3QsIHRhZykgewogICAgaWYg
-KHNlbGYuSFRNTEVsZW1lbnQgJiYgb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHJldHVybiAi
-SFRNTEVsZW1lbnQiOwogICAgcmV0dXJuIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcpOwogIH0KICBm
-dW5jdGlvbiBwcm90b3R5cGVGb3JUYWcodGFnKSB7CiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PSAidW5k
-ZWZpbmVkIikgcmV0dXJuIG51bGw7CiAgICBpZiAodHlwZW9mIHdpbmRvd1t0YWddID09ICJ1bmRlZmlu
-ZWQiKSByZXR1cm4gbnVsbDsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYg
-KHR5cGVvZiBjb25zdHJ1Y3RvciAhPSAiZnVuY3Rpb24iKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBj
-b25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGZ1bmN0aW9uIGRpc2NyaW1pbmF0b3IodGFnKSB7IHJl
-dHVybiBudWxsOyB9CiAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9iamVjdCI7
-CiAgcmV0dXJuIHsKICAgIGdldFRhZzogZ2V0VGFnLAogICAgZ2V0VW5rbm93blRhZzogaXNCcm93c2Vy
-ID8gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyIDogZ2V0VW5rbm93blRhZywKICAgIHByb3RvdHlw
-ZUZvclRhZzogcHJvdG90eXBlRm9yVGFnLAogICAgZGlzY3JpbWluYXRvcjogZGlzY3JpbWluYXRvciB9
-Owp9CkMud2I9ZnVuY3Rpb24oZ2V0VGFnRmFsbGJhY2spIHsKICByZXR1cm4gZnVuY3Rpb24oaG9va3Mp
-IHsKICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9ICJvYmplY3QiKSByZXR1cm4gaG9va3M7CiAgICB2
-YXIgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50OwogICAgaWYgKHVhLmluZGV4T2YoIkR1bXBSZW5kZXJU
-cmVlIikgPj0gMCkgcmV0dXJuIGhvb2tzOwogICAgaWYgKHVhLmluZGV4T2YoIkNocm9tZSIpID49IDAp
-IHsKICAgICAgZnVuY3Rpb24gY29uZmlybShwKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiB3aW5kb3cg
-PT0gIm9iamVjdCIgJiYgd2luZG93W3BdICYmIHdpbmRvd1twXS5uYW1lID09IHA7CiAgICAgIH0KICAg
-ICAgaWYgKGNvbmZpcm0oIldpbmRvdyIpICYmIGNvbmZpcm0oIkhUTUxFbGVtZW50IikpIHJldHVybiBo
-b29rczsKICAgIH0KICAgIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZhbGxiYWNrOwogIH07Cn0KQy5LVT1m
-dW5jdGlvbihob29rcykgewogIGlmICh0eXBlb2YgZGFydEV4cGVyaW1lbnRhbEZpeHVwR2V0VGFnICE9
-ICJmdW5jdGlvbiIpIHJldHVybiBob29rczsKICBob29rcy5nZXRUYWcgPSBkYXJ0RXhwZXJpbWVudGFs
-Rml4dXBHZXRUYWcoaG9va3MuZ2V0VGFnKTsKfQpDLmZRPWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFyIGdl
-dFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcHJvdG90eXBlRm9yVGFnID0gaG9va3MucHJvdG90eXBl
-Rm9yVGFnOwogIGZ1bmN0aW9uIGdldFRhZ0ZpeGVkKG8pIHsKICAgIHZhciB0YWcgPSBnZXRUYWcobyk7
-CiAgICBpZiAodGFnID09ICJEb2N1bWVudCIpIHsKICAgICAgaWYgKCEhby54bWxWZXJzaW9uKSByZXR1
-cm4gIiFEb2N1bWVudCI7CiAgICAgIHJldHVybiAiIUhUTUxEb2N1bWVudCI7CiAgICB9CiAgICByZXR1
-cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdGaXhlZCh0YWcpIHsKICAgIGlmICh0
-YWcgPT0gIkRvY3VtZW50IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gcHJvdG90eXBlRm9yVGFnKHRh
-Zyk7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpeGVkOwogIGhvb2tzLnByb3RvdHlwZUZvclRh
-ZyA9IHByb3RvdHlwZUZvclRhZ0ZpeGVkOwp9CkMuZGs9ZnVuY3Rpb24oaG9va3MpIHsKICB2YXIgdXNl
-ckFnZW50ID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51c2VyQWdlbnQg
-OiAiIjsKICBpZiAodXNlckFnZW50LmluZGV4T2YoIkZpcmVmb3giKSA9PSAtMSkgcmV0dXJuIGhvb2tz
-OwogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAgIkJlZm9y
-ZVVubG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJkIiwKICAg
-ICJHZW9HZW9sb2NhdGlvbiI6ICJHZW9sb2NhdGlvbiIsCiAgICAiTG9jYXRpb24iOiAiIUxvY2F0aW9u
-IiwKICAgICJXb3JrZXJNZXNzYWdlRXZlbnQiOiAiTWVzc2FnZUV2ZW50IiwKICAgICJYTUxEb2N1bWVu
-dCI6ICIhRG9jdW1lbnQifTsKICBmdW5jdGlvbiBnZXRUYWdGaXJlZm94KG8pIHsKICAgIHZhciB0YWcg
-PSBnZXRUYWcobyk7CiAgICByZXR1cm4gcXVpY2tNYXBbdGFnXSB8fCB0YWc7CiAgfQogIGhvb2tzLmdl
-dFRhZyA9IGdldFRhZ0ZpcmVmb3g7Cn0KQy54aT1mdW5jdGlvbihob29rcykgewogIHZhciB1c2VyQWdl
+Iil9LAokUzo0OX0KUi5INy5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJ9fQpN
+LmxJLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7dmFyIHM9RC5hYigpCnJldHVybiBzfSwKV086ZnVu
+Y3Rpb24oYSxiKXt2YXIgcyxyLHE9dC5kNApNLllGKCJhYnNvbHV0ZSIsSC5WTShbYixudWxsLG51bGws
+bnVsbCxudWxsLG51bGwsbnVsbF0scSkpCnM9dGhpcy5hCnM9cy5ZcihiKT4wJiYhcy5oSyhiKQppZihz
+KXJldHVybiBiCnI9SC5WTShbdGhpcy5nbCgpLGIsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGxd
+LHEpCk0uWUYoImpvaW4iLHIpCnJldHVybiB0aGlzLklQKG5ldyBILnU2KHIsdC5lSikpfSwKemY6ZnVu
+Y3Rpb24oYSl7dmFyIHMscixxPVguQ0woYSx0aGlzLmEpCnEuSXgoKQpzPXEuZApyPXMubGVuZ3RoCmlm
+KHI9PT0wKXtzPXEuYgpyZXR1cm4gcz09bnVsbD8iLiI6c31pZihyPT09MSl7cz1xLmIKcmV0dXJuIHM9
+PW51bGw/Ii4iOnN9aWYoMD49cilyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCnM9cS5lCmlmKDA+PXMu
+bGVuZ3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9wKCkKcS5JeCgpCnJldHVybiBxLncoMCl9LApJUDpm
+dW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssagp0LlEuYShhKQpmb3Iocz1hLiR0aSxyPXMu
+QygiYTIoY1guRSkiKS5hKG5ldyBNLnE3KCkpLHE9YS5nbShhKSxzPW5ldyBILlNPKHEscixzLkMoIlNP
+PGNYLkU+IikpLHI9dGhpcy5hLHA9ITEsbz0hMSxuPSIiO3MuRigpOyl7bT1xLmdsKCkKaWYoci5oSyht
+KSYmbyl7bD1YLkNMKG0scikKaz1uLmNoYXJDb2RlQXQoMCk9PTA/bjpuCm49Qy54Qi5OaihrLDAsci5T
+cChrLCEwKSkKbC5iPW4KaWYoci5kcyhuKSlDLk5tLlk1KGwuZSwwLHIuZ21JKCkpCm49bC53KDApfWVs
+c2UgaWYoci5ZcihtKT4wKXtvPSFyLmhLKG0pCm49SC5FaihtKX1lbHNle2o9bS5sZW5ndGgKaWYoaiE9
+PTApe2lmKDA+PWopcmV0dXJuIEguT0gobSwwKQpqPXIuVWQobVswXSl9ZWxzZSBqPSExCmlmKCFqKWlm
+KHApbis9ci5nbUkoKQpuKz1tfXA9ci5kcyhtKX1yZXR1cm4gbi5jaGFyQ29kZUF0KDApPT0wP246bn0s
+Cm81OmZ1bmN0aW9uKGEpe3ZhciBzCmlmKCF0aGlzLnkzKGEpKXJldHVybiBhCnM9WC5DTChhLHRoaXMu
+YSkKcy5yUigpCnJldHVybiBzLncoMCl9LAp5MzpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxs
+LGssagphLnRvU3RyaW5nCnM9dGhpcy5hCnI9cy5ZcihhKQppZihyIT09MCl7aWYocz09PSQuS2soKSlm
+b3IocT0wO3E8cjsrK3EpaWYoQy54Qi5XKGEscSk9PT00NylyZXR1cm4hMApwPXIKbz00N31lbHNle3A9
+MApvPW51bGx9Zm9yKG49bmV3IEgucWooYSkuYSxtPW4ubGVuZ3RoLHE9cCxsPW51bGw7cTxtOysrcSxs
+PW8sbz1rKXtrPUMueEIuTyhuLHEpCmlmKHMucjQoaykpe2lmKHM9PT0kLktrKCkmJms9PT00NylyZXR1
+cm4hMAppZihvIT1udWxsJiZzLnI0KG8pKXJldHVybiEwCmlmKG89PT00NilqPWw9PW51bGx8fGw9PT00
+Nnx8cy5yNChsKQplbHNlIGo9ITEKaWYoailyZXR1cm4hMH19aWYobz09bnVsbClyZXR1cm4hMAppZihz
+LnI0KG8pKXJldHVybiEwCmlmKG89PT00NilzPWw9PW51bGx8fHMucjQobCl8fGw9PT00NgplbHNlIHM9
+ITEKaWYocylyZXR1cm4hMApyZXR1cm4hMX0sCkhQOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxu
+LG0sbD10aGlzLGs9J1VuYWJsZSB0byBmaW5kIGEgcGF0aCB0byAiJwpiPWwuV08oMCxiKQpzPWwuYQpp
+ZihzLllyKGIpPD0wJiZzLllyKGEpPjApcmV0dXJuIGwubzUoYSkKaWYocy5ZcihhKTw9MHx8cy5oSyhh
+KSlhPWwuV08oMCxhKQppZihzLllyKGEpPD0wJiZzLllyKGIpPjApdGhyb3cgSC5iKFguSTcoaytILkVq
+KGEpKyciIGZyb20gIicrSC5FaihiKSsnIi4nKSkKcj1YLkNMKGIscykKci5yUigpCnE9WC5DTChhLHMp
+CnEuclIoKQpwPXIuZApvPXAubGVuZ3RoCmlmKG8hPT0wKXtpZigwPj1vKXJldHVybiBILk9IKHAsMCkK
+cD1KLlJNKHBbMF0sIi4iKX1lbHNlIHA9ITEKaWYocClyZXR1cm4gcS53KDApCnA9ci5iCm89cS5iCmlm
+KHAhPW8pcD1wPT1udWxsfHxvPT1udWxsfHwhcy5OYyhwLG8pCmVsc2UgcD0hMQppZihwKXJldHVybiBx
+LncoMCkKd2hpbGUoITApe3A9ci5kCm89cC5sZW5ndGgKaWYobyE9PTApe249cS5kCm09bi5sZW5ndGgK
+aWYobSE9PTApe2lmKDA+PW8pcmV0dXJuIEguT0gocCwwKQpwPXBbMF0KaWYoMD49bSlyZXR1cm4gSC5P
+SChuLDApCm49cy5OYyhwLG5bMF0pCnA9bn1lbHNlIHA9ITF9ZWxzZSBwPSExCmlmKCFwKWJyZWFrCkMu
+Tm0uVzQoci5kLDApCkMuTm0uVzQoci5lLDEpCkMuTm0uVzQocS5kLDApCkMuTm0uVzQocS5lLDEpfXA9
+ci5kCm89cC5sZW5ndGgKaWYobyE9PTApe2lmKDA+PW8pcmV0dXJuIEguT0gocCwwKQpwPUouUk0ocFsw
+XSwiLi4iKX1lbHNlIHA9ITEKaWYocCl0aHJvdyBILmIoWC5JNyhrK0guRWooYSkrJyIgZnJvbSAiJytI
+LkVqKGIpKyciLicpKQpwPXQuTgpDLk5tLlVHKHEuZCwwLFAuTzgoci5kLmxlbmd0aCwiLi4iLCExLHAp
+KQpDLk5tLlk1KHEuZSwwLCIiKQpDLk5tLlVHKHEuZSwxLFAuTzgoci5kLmxlbmd0aCxzLmdtSSgpLCEx
+LHApKQpzPXEuZApwPXMubGVuZ3RoCmlmKHA9PT0wKXJldHVybiIuIgppZihwPjEmJkouUk0oQy5ObS5n
+cloocyksIi4iKSl7cz1xLmQKaWYoMD49cy5sZW5ndGgpcmV0dXJuIEguT0gocywtMSkKcy5wb3AoKQpz
+PXEuZQppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCmlmKDA+PXMubGVuZ3Ro
+KXJldHVybiBILk9IKHMsLTEpCnMucG9wKCkKQy5ObS5pKHMsIiIpfXEuYj0iIgpxLkl4KCkKcmV0dXJu
+IHEudygwKX19Ck0ucTcucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEguaChhKSE9PSIi
+fSwKJFM6Nn0KTS5Oby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtILmsoYSkKcmV0dXJuIGE9PW51
+bGw/Im51bGwiOiciJythKyciJ30sCiRTOjUwfQpCLmZ2LnByb3RvdHlwZT17CnhaOmZ1bmN0aW9uKGEp
+e3ZhciBzLHI9dGhpcy5ZcihhKQppZihyPjApcmV0dXJuIEoubGQoYSwwLHIpCmlmKHRoaXMuaEsoYSkp
+e2lmKDA+PWEubGVuZ3RoKXJldHVybiBILk9IKGEsMCkKcz1hWzBdfWVsc2Ugcz1udWxsCnJldHVybiBz
+fSwKTmM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT09Yn19ClguV0QucHJvdG90eXBlPXsKSXg6ZnVuY3Rp
+b24oKXt2YXIgcyxyLHE9dGhpcwp3aGlsZSghMCl7cz1xLmQKaWYoIShzLmxlbmd0aCE9PTAmJkouUk0o
+Qy5ObS5ncloocyksIiIpKSlicmVhawpzPXEuZAppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLC0x
+KQpzLnBvcCgpCnM9cS5lCmlmKDA+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9wKCl9cz1x
+LmUKcj1zLmxlbmd0aAppZihyIT09MClDLk5tLlk1KHMsci0xLCIiKX0sCnJSOmZ1bmN0aW9uKCl7dmFy
+IHMscixxLHAsbyxuLG09dGhpcyxsPUguVk0oW10sdC5zKQpmb3Iocz1tLmQscj1zLmxlbmd0aCxxPTAs
+cD0wO3A8cy5sZW5ndGg7cy5sZW5ndGg9PT1yfHwoMCxILmxrKShzKSwrK3Ape289c1twXQpuPUouaWEo
+bykKaWYoIShuLkROKG8sIi4iKXx8bi5ETihvLCIiKSkpaWYobi5ETihvLCIuLiIpKXtuPWwubGVuZ3Ro
+CmlmKG4hPT0wKXtpZigwPj1uKXJldHVybiBILk9IKGwsLTEpCmwucG9wKCl9ZWxzZSArK3F9ZWxzZSBD
+Lk5tLmkobCxvKX1pZihtLmI9PW51bGwpQy5ObS5VRyhsLDAsUC5POChxLCIuLiIsITEsdC5OKSkKaWYo
+bC5sZW5ndGg9PT0wJiZtLmI9PW51bGwpQy5ObS5pKGwsIi4iKQptLnNuSihsKQpzPW0uYQptLnNQaChQ
+Lk84KGwubGVuZ3RoKzEscy5nbUkoKSwhMCx0Lk4pKQpyPW0uYgppZihyPT1udWxsfHxsLmxlbmd0aD09
+PTB8fCFzLmRzKHIpKUMuTm0uWTUobS5lLDAsIiIpCnI9bS5iCmlmKHIhPW51bGwmJnM9PT0kLktrKCkp
+e3IudG9TdHJpbmcKbS5iPUgueXMociwiLyIsIlxcIil9bS5JeCgpfSwKdzpmdW5jdGlvbihhKXt2YXIg
+cyxyLHE9dGhpcyxwPXEuYgpwPXAhPW51bGw/cDoiIgpmb3Iocz0wO3M8cS5kLmxlbmd0aDsrK3Mpe3I9
+cS5lCmlmKHM+PXIubGVuZ3RoKXJldHVybiBILk9IKHIscykKcj1wK0guRWoocltzXSkKcD1xLmQKaWYo
+cz49cC5sZW5ndGgpcmV0dXJuIEguT0gocCxzKQpwPXIrSC5FaihwW3NdKX1wKz1ILkVqKEMuTm0uZ3Ja
+KHEuZSkpCnJldHVybiBwLmNoYXJDb2RlQXQoMCk9PTA/cDpwfSwKc25KOmZ1bmN0aW9uKGEpe3RoaXMu
+ZD10LkQuYShhKX0sCnNQaDpmdW5jdGlvbihhKXt0aGlzLmU9dC5ELmEoYSl9fQpYLmR2LnByb3RvdHlw
+ZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlBhdGhFeGNlcHRpb246ICIrdGhpcy5hfSwKJGlSejoxfQpP
+LnpMLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ29jKHRoaXMpfX0KRS5PRi5w
+cm90b3R5cGU9ewpVZDpmdW5jdGlvbihhKXtyZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlv
+bihhKXtyZXR1cm4gYT09PTQ3fSwKZHM6ZnVuY3Rpb24oYSl7dmFyIHM9YS5sZW5ndGgKcmV0dXJuIHMh
+PT0wJiZDLnhCLk8oYSxzLTEpIT09NDd9LApTcDpmdW5jdGlvbihhLGIpe2lmKGEubGVuZ3RoIT09MCYm
+Qy54Qi5XKGEsMCk9PT00NylyZXR1cm4gMQpyZXR1cm4gMH0sCllyOmZ1bmN0aW9uKGEpe3JldHVybiB0
+aGlzLlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuITF9LApnb2M6ZnVuY3Rpb24oKXtyZXR1
+cm4icG9zaXgifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJuIi8ifX0KRi5ydS5wcm90b3R5cGU9ewpVZDpm
+dW5jdGlvbihhKXtyZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09
+PTQ3fSwKZHM6ZnVuY3Rpb24oYSl7dmFyIHM9YS5sZW5ndGgKaWYocz09PTApcmV0dXJuITEKaWYoQy54
+Qi5PKGEscy0xKSE9PTQ3KXJldHVybiEwCnJldHVybiBDLnhCLlRjKGEsIjovLyIpJiZ0aGlzLllyKGEp
+PT09c30sClNwOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbz1hLmxlbmd0aAppZihvPT09MClyZXR1
+cm4gMAppZihDLnhCLlcoYSwwKT09PTQ3KXJldHVybiAxCmZvcihzPTA7czxvOysrcyl7cj1DLnhCLlco
+YSxzKQppZihyPT09NDcpcmV0dXJuIDAKaWYocj09PTU4KXtpZihzPT09MClyZXR1cm4gMApxPUMueEIu
+WFUoYSwiLyIsQy54Qi5RaShhLCIvLyIscysxKT9zKzM6cykKaWYocTw9MClyZXR1cm4gbwppZighYnx8
+bzxxKzMpcmV0dXJuIHEKaWYoIUMueEIubihhLCJmaWxlOi8vIikpcmV0dXJuIHEKaWYoIUIuWXUoYSxx
+KzEpKXJldHVybiBxCnA9cSszCnJldHVybiBvPT09cD9wOnErNH19cmV0dXJuIDB9LApZcjpmdW5jdGlv
+bihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aCE9
+PTAmJkMueEIuVyhhLDApPT09NDd9LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4idXJsIn0sCmdtSTpmdW5j
+dGlvbigpe3JldHVybiIvIn19CkwuSVYucHJvdG90eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMu
+eEIudGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGE9PT00N3x8YT09PTkyfSwKZHM6ZnVu
+Y3Rpb24oYSl7dmFyIHM9YS5sZW5ndGgKaWYocz09PTApcmV0dXJuITEKcz1DLnhCLk8oYSxzLTEpCnJl
+dHVybiEocz09PTQ3fHxzPT09OTIpfSwKU3A6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9YS5sZW5ndGgK
+aWYocT09PTApcmV0dXJuIDAKcz1DLnhCLlcoYSwwKQppZihzPT09NDcpcmV0dXJuIDEKaWYocz09PTky
+KXtpZihxPDJ8fEMueEIuVyhhLDEpIT09OTIpcmV0dXJuIDEKcj1DLnhCLlhVKGEsIlxcIiwyKQppZihy
+PjApe3I9Qy54Qi5YVShhLCJcXCIscisxKQppZihyPjApcmV0dXJuIHJ9cmV0dXJuIHF9aWYocTwzKXJl
+dHVybiAwCmlmKCFCLk9TKHMpKXJldHVybiAwCmlmKEMueEIuVyhhLDEpIT09NTgpcmV0dXJuIDAKcT1D
+LnhCLlcoYSwyKQppZighKHE9PT00N3x8cT09PTkyKSlyZXR1cm4gMApyZXR1cm4gM30sCllyOmZ1bmN0
+aW9uKGEpe3JldHVybiB0aGlzLlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuWXIo
+YSk9PT0xfSwKT3Q6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihhPT09YilyZXR1cm4hMAppZihhPT09NDcp
+cmV0dXJuIGI9PT05MgppZihhPT09OTIpcmV0dXJuIGI9PT00NwppZigoYV5iKSE9PTMyKXJldHVybiEx
+CnM9YXwzMgpyZXR1cm4gcz49OTcmJnM8PTEyMn0sCk5jOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxCmlm
+KGE9PWIpcmV0dXJuITAKcz1hLmxlbmd0aAppZihzIT09Yi5sZW5ndGgpcmV0dXJuITEKZm9yKHI9Si5y
+WShiKSxxPTA7cTxzOysrcSlpZighdGhpcy5PdChDLnhCLlcoYSxxKSxyLlcoYixxKSkpcmV0dXJuITEK
+cmV0dXJuITB9LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4id2luZG93cyJ9LApnbUk6ZnVuY3Rpb24oKXty
+ZXR1cm4iXFwifX07KGZ1bmN0aW9uIGFsaWFzZXMoKXt2YXIgcz1KLkd2LnByb3RvdHlwZQpzLlU9cy53
+CnMuU2o9cy5lNwpzPUouTUYucHJvdG90eXBlCnMudD1zLncKcz1QLmNYLnByb3RvdHlwZQpzLkdHPXMu
+ZXYKcz1QLk1oLnByb3RvdHlwZQpzLnhiPXMudwpzPVcuY3YucHJvdG90eXBlCnMuRFc9cy5yNgpzPVcu
+bTYucHJvdG90eXBlCnMuakY9cy5FYgpzPVAuRTQucHJvdG90eXBlCnMuVXI9cy5xCnMuZTQ9cy5ZNQpz
+PVAuY28ucHJvdG90eXBlCnMuYmg9cy5ZNX0pKCk7KGZ1bmN0aW9uIGluc3RhbGxUZWFyT2Zmcygpe3Zh
+ciBzPWh1bmtIZWxwZXJzLl9zdGF0aWNfMSxyPWh1bmtIZWxwZXJzLl9zdGF0aWNfMCxxPWh1bmtIZWxw
+ZXJzLmluc3RhbGxJbnN0YW5jZVRlYXJPZmYscD1odW5rSGVscGVycy5pbnN0YWxsU3RhdGljVGVhck9m
+ZixvPWh1bmtIZWxwZXJzLl9pbnN0YW5jZV8xdQpzKFAsIkVYIiwiWlYiLDgpCnMoUCwieXQiLCJvQSIs
+OCkKcyhQLCJxVyIsIkJ6Iiw4KQpyKFAsIlVJIiwiZU4iLDApCnEoUC5QZi5wcm90b3R5cGUsImdZSiIs
+MCwxLG51bGwsWyIkMiIsIiQxIl0sWyJ3MCIsInBtIl0sMjYsMCkKcyhQLCJDeSIsIk5DIiw0KQpzKFAs
+IlBIIiwiTXQiLDUpCnAoVywicFMiLDQsbnVsbCxbIiQ0Il0sWyJxRCJdLDksMCkKcChXLCJWNCIsNCxu
+dWxsLFsiJDQiXSxbIlFXIl0sOSwwKQpvKFAuQXMucHJvdG90eXBlLCJndU0iLCJWIiw1KQpzKFAsImlH
+Iiwid1kiLDUzKQpzKFAsIncwIiwiZFUiLDM2KQpzKEwsImlTIiwiaTYiLDcpfSkoKTsoZnVuY3Rpb24g
+aW5oZXJpdGFuY2UoKXt2YXIgcz1odW5rSGVscGVycy5taXhpbixyPWh1bmtIZWxwZXJzLmluaGVyaXQs
+cT1odW5rSGVscGVycy5pbmhlcml0TWFueQpyKFAuTWgsbnVsbCkKcShQLk1oLFtILkZLLEouR3YsSi5t
+MSxQLmNYLEguRTcsUC5YUyxQLm5ZLEguYTcsUC5BbixILkZ1LEguSkIsSC5TVSxILlJlLEgud3YsUC5Q
+bixILldVLEguTEksSC5UcCxILmY5LEgudGUsSC5icSxILlhPLEgua3IsUC5ZayxILnZoLEguTjYsSC5W
+UixILkVLLEguUGIsSC50USxILlNkLEguSmMsSC5HLEgubFksUC5XMyxQLmloLFAuRnksUC5HVixQLkN3
+LFAuUGYsUC5GZSxQLnZzLFAuT00sUC5xaCxQLk1PLFAua1QsUC54SSxQLm0wLFAucFIsUC5ibixQLmxt
+LFAubEQsUC5LUCxQLmxmLFAuV1ksUC5VayxQLlNoLFAuUncsUC5ieixQLmlQLFAuazUsUC5LWSxQLkNE
+LFAuYUUsUC5OMyxQLmM4LFAuWmQsUC5SbixQLkRuLFAuUEUsUC5VZixXLmlkLFcuRmssVy5KUSxXLkdt
+LFcudkQsVy5tNixXLk93LFcuVzksVy5kVyxXLm1rLFcuS28sUC5pSixQLkU0LFUuZDIsVS5TZSxVLk1s
+LFUueUQsVS53YixCLmo4LEIucXAsVC5tUSxMLlhBLEwuRDgsTC5POSxMLkdiLFIuTEwsUi5INyxNLmxJ
+LE8uekwsWC5XRCxYLmR2XSkKcShKLkd2LFtKLnlFLEoud2UsSi5NRixKLmpkLEoucUksSi5EcixILkVU
+LFcuRDAsVy5BeixXLkxlLFcuTmgsVy5hZSxXLklCLFcubjcsVy5lYSxXLmJyLFcuU2csVy53NyxXLks3
+LFcuWFcsUC5oRl0pCnEoSi5NRixbSi5pQyxKLmtkLEouYzVdKQpyKEouUG8sSi5qZCkKcShKLnFJLFtK
+LmJVLEouVkFdKQpxKFAuY1gsW0guQlIsSC5iUSxILmkxLEguVTUsSC5BTSxILnU2LEguWFIsUC5tVyxI
+LnVuXSkKcShILkJSLFtILlp5LEguUUNdKQpyKEgub2wsSC5aeSkKcihILlVxLEguUUMpCnIoSC5qVixI
+LlVxKQpxKFAuWFMsW0gubixILnIzLEguR00sUC5FeixILmF6LEgudlYsSC5FcSxQLkM2LEgua1MsUC5V
+ZCxQLkYsUC51LFAubXAsUC51YixQLmRzLFAubGosUC5VVixQLmNdKQpyKFAudXksUC5uWSkKcShQLnV5
+LFtILncyLFcud3osVy5lN10pCnIoSC5xaixILncyKQpxKEguYlEsW0guYUwsSC5NQixILmk1XSkKcShI
+LmFMLFtILm5ILEgubEosUC5pOF0pCnIoSC54eSxILmkxKQpxKFAuQW4sW0guTUgsSC5TTyxILlUxXSkK
+cihILmQ1LEguQU0pCnIoUC5SVSxQLlBuKQpyKFAuR2osUC5SVSkKcihILlBELFAuR2opCnIoSC5MUCxI
+LldVKQpxKEguVHAsW0guQ2osSC5sYyxILmRDLEgud04sSC5WWCxQLnRoLFAuaGEsUC5WcyxQLkZ0LFAu
+eUgsUC5XTSxQLlNYLFAuR3MsUC5kYSxQLm9RLFAucFYsUC5VNyxQLnZyLFAucnQsUC5LRixQLlpMLFAu
+UlQsUC5qWixQLnJxLFAuUlcsUC5CNSxQLnVPLFAucEssUC5oaixQLlZwLFAuT1IsUC5yYSxQLnlRLFAu
+eHIsUC5OeixQLnRpLFAuV0YsUC5uMSxQLmNTLFAuVkMsUC5KVCxQLlJaLFAuTUUsUC55NSxQLnlJLFAu
+YzYsUC5xZCxXLkN2LFcuS1MsVy5BMyxXLnZOLFcuVXYsVy5FZyxXLkVvLFcuV2ssVy5JQSxXLmZtLFAu
+amcsUC5UYSxQLkdFLFAuTjcsUC51USxQLlBDLFAubXQsUC5RUyxQLm5wLFAuVXQsVS5hTixVLmIwLEwu
+ZSxMLlZXLEwub1osTC5qcixMLnFsLEwuSGksTC5CVCxMLlBZLEwudTgsTC5MLEwuV3gsTC5BTyxMLmRO
+LEwuSG8sTC54eixMLklDLEwuZkMsTC5uVCxMLk5ZLEwudWUsTC5lWCxMLkVFLEwuUUwsTC5WUyxMLlRE
+LEwuSWYsTC50QixMLm0yLFIuTUQsTS5xNyxNLk5vXSkKcihILlcwLFAuRXopCnEoSC5sYyxbSC56eCxI
+LnJUXSkKcihILmtZLFAuQzYpCnIoUC5pbCxQLllrKQpxKFAuaWwsW0guTjUsUC51dyxXLmNmLFcuU3ld
+KQpxKFAubVcsW0guS1csUC5xNF0pCnIoSC5MWixILkVUKQpxKEguTFosW0guUkcsSC5XQl0pCnIoSC5W
+UCxILlJHKQpyKEguRGcsSC5WUCkKcihILlpHLEguV0IpCnIoSC5QZyxILlpHKQpxKEguUGcsW0gueGos
+SC5kRSxILlpBLEguZFQsSC5QcSxILmVFLEguVjZdKQpyKEguaU0sSC5rUykKcihQLlpmLFAuUGYpCnIo
+UC5KaSxQLm0wKQpyKFAuWHYsUC5wUikKcihQLmI2LFAuWHYpCnIoUC5WaixQLldZKQpxKFAuVWssW1Au
+Q1YsUC5aaSxQLmJ5XSkKcihQLndJLFAua1QpCnEoUC53SSxbUC5VOCxQLm9qLFAuTXgsUC5FMyxQLkdZ
+XSkKcihQLks4LFAuVWQpCnIoUC50dSxQLlNoKQpyKFAudTUsUC5aaSkKcShQLnUsW1AuYkosUC5lWV0p
+CnIoUC5xZSxQLkRuKQpxKFcuRDAsW1cudUgsVy53YSxXLks1LFcuQ21dKQpxKFcudUgsW1cuY3YsVy5u
+eCxXLlFGLFcuQ1FdKQpxKFcuY3YsW1cucUUsUC5oaV0pCnEoVy5xRSxbVy5HaCxXLmZZLFcubkIsVy5R
+UCxXLmg0LFcuU04sVy5scCxXLlRiLFcuSXYsVy5XUCxXLnlZXSkKcihXLm9KLFcuTGUpCnIoVy5oSCxX
+LkF6KQpyKFcuVmIsVy5RRikKcihXLmZKLFcud2EpCnEoVy5lYSxbVy53NixXLmV3XSkKcihXLkFqLFcu
+dzYpCnIoVy5yQixXLks3KQpyKFcuQkgsVy5yQikKcihXLnc0LFcuSUIpCnIoVy5vYSxXLlhXKQpyKFcu
+cmgsVy5vYSkKcihXLmk3LFcuY2YpCnIoUC5BcyxQLlZqKQpxKFAuQXMsW1cuSTQsUC5LZV0pCnIoVy5S
+TyxQLnFoKQpyKFcuZXUsVy5STykKcihXLnhDLFAuTU8pCnIoVy5jdCxXLm02KQpyKFAuQmYsUC5pSikK
+cShQLkU0LFtQLnI3LFAuY29dKQpyKFAuVHosUC5jbykKcihQLm5kLFAuaGkpCnEoTC5EOCxbTC52dCxM
+LmNEXSkKcihCLmZ2LE8uekwpCnEoQi5mdixbRS5PRixGLnJ1LEwuSVZdKQpzKEgudzIsSC5SZSkKcyhI
+LlFDLFAubEQpCnMoSC5SRyxQLmxEKQpzKEguVlAsSC5TVSkKcyhILldCLFAubEQpCnMoSC5aRyxILlNV
+KQpzKFAublksUC5sRCkKcyhQLldZLFAubGYpCnMoUC5SVSxQLktQKQpzKFAucFIsUC5sZikKcyhXLkxl
+LFcuaWQpCnMoVy5LNyxQLmxEKQpzKFcuckIsVy5HbSkKcyhXLlhXLFAubEQpCnMoVy5vYSxXLkdtKQpz
+KFAuY28sUC5sRCl9KSgpCnZhciB2PXt0eXBlVW5pdmVyc2U6e2VDOm5ldyBNYXAoKSx0Ujp7fSxlVDp7
+fSx0UFY6e30sc0VBOltdfSxtYW5nbGVkR2xvYmFsTmFtZXM6e0IyOiJpbnQiLENQOiJkb3VibGUiLFpa
+OiJudW0iLHFVOiJTdHJpbmciLGEyOiJib29sIixjODoiTnVsbCIsek06Ikxpc3QifSxtYW5nbGVkTmFt
+ZXM6e30sZ2V0VHlwZUZyb21OYW1lOmdldEdsb2JhbEZyb21OYW1lLG1ldGFkYXRhOltdLHR5cGVzOlsi
+figpIiwiYzgoQWoqKSIsImM4KCkiLCJjOChjdiopIiwiQChAKSIsInFVKHFVKSIsImEyKHFVKSIsIn4o
+QWoqKSIsIn4ofigpKSIsImEyKGN2LHFVLHFVLEpRKSIsImM4KEApIiwifihNaD8sTWg/KSIsIkAoKSIs
+In4ocVUsQCkiLCJ+KG42LHFVLEIyKSIsIn4ocVUscVUpIiwiYTIoa0YpIiwiYzgoQCxAKSIsIn4oeHU8
+cVU+KSIsImM4KGVhKikiLCJiODxjOD4qKEFqKikiLCJ+KHFVLEIyKSIsIn4ocVUscVU/KSIsIm42KEAs
+QCkiLCJ+KEIyLEApIiwiYTIodUgpIiwifihNaFtHej9dKSIsIn4oZWEpIiwiYzgoTWgsR3opIiwidnM8
+QD4oQCkiLCJ+KHVILHVIPykiLCJ+KEAsQCkiLCJAKHFVKSIsImEyKHh1PHFVPikiLCJAKEAscVUpIiwi
+cjcoQCkiLCJNaD8oQCkiLCJFNChAKSIsIkxMKihAKSIsIlowPHFVKixNaCo+KihMTCopIiwifihHRCxA
+KSIsIlowPHFVLHFVPihaMDxxVSxxVT4scVUpIiwiYzgoWjA8cVUqLE1oKj4qKSIsIn4oQCkiLCJxVSoo
+QWoqKSIsIlR6PEA+KEApIiwifihxVVtAXSkiLCJjOChldyopIiwicVUqKFowPEAsQD4qKSIsImEyKihI
+NyopIiwicVUocVU/KSIsIkIyKEIyLEIyKSIsImM4KH4oKSkiLCJNaD8oTWg/KSIsImM4KEAsR3opIl0s
+aW50ZXJjZXB0b3JzQnlUYWc6bnVsbCxsZWFmVGFnczpudWxsLGFycmF5UnRpOnR5cGVvZiBTeW1ib2w9
+PSJmdW5jdGlvbiImJnR5cGVvZiBTeW1ib2woKT09InN5bWJvbCI/U3ltYm9sKCIkdGkiKToiJHRpIn0K
+SC54Yih2LnR5cGVVbml2ZXJzZSxKU09OLnBhcnNlKCd7ImM1IjoiTUYiLCJpQyI6Ik1GIiwia2QiOiJN
+RiIsInJ4IjoiZWEiLCJlNSI6ImVhIiwiWTAiOiJoaSIsInRwIjoiaGkiLCJHOCI6ImV3IiwiTXIiOiJx
+RSIsImVMIjoicUUiLCJJMCI6InVIIiwiaHMiOiJ1SCIsIlhnIjoiUUYiLCJuciI6IkFqIiwieTQiOiJ3
+NiIsImFQIjoiQ20iLCJ4YyI6Im54Iiwia0oiOiJueCIsInpVIjoiRGciLCJkZiI6IkVUIiwieUUiOnsi
+YTIiOltdfSwid2UiOnsiYzgiOltdfSwiTUYiOnsidm0iOltdLCJFSCI6W119LCJqZCI6eyJ6TSI6WyIx
+Il0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwiUG8iOnsiamQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpb
+IjEiXSwiY1giOlsiMSJdfSwibTEiOnsiQW4iOlsiMSJdfSwicUkiOnsiQ1AiOltdLCJaWiI6W119LCJi
+VSI6eyJDUCI6W10sIkIyIjpbXSwiWloiOltdfSwiVkEiOnsiQ1AiOltdLCJaWiI6W119LCJEciI6eyJx
+VSI6W10sInZYIjpbXX0sIkJSIjp7ImNYIjpbIjIiXX0sIkU3Ijp7IkFuIjpbIjIiXX0sIlp5Ijp7IkJS
+IjpbIjEiLCIyIl0sImNYIjpbIjIiXSwiY1guRSI6IjIifSwib2wiOnsiWnkiOlsiMSIsIjIiXSwiQlIi
+OlsiMSIsIjIiXSwiYlEiOlsiMiJdLCJjWCI6WyIyIl0sImNYLkUiOiIyIn0sIlVxIjp7ImxEIjpbIjIi
+XSwiek0iOlsiMiJdLCJCUiI6WyIxIiwiMiJdLCJiUSI6WyIyIl0sImNYIjpbIjIiXX0sImpWIjp7IlVx
+IjpbIjEiLCIyIl0sImxEIjpbIjIiXSwiek0iOlsiMiJdLCJCUiI6WyIxIiwiMiJdLCJiUSI6WyIyIl0s
+ImNYIjpbIjIiXSwibEQuRSI6IjIiLCJjWC5FIjoiMiJ9LCJuIjp7IlhTIjpbXX0sInIzIjp7IlhTIjpb
+XX0sInFqIjp7ImxEIjpbIkIyIl0sIlJlIjpbIkIyIl0sInpNIjpbIkIyIl0sImJRIjpbIkIyIl0sImNY
+IjpbIkIyIl0sImxELkUiOiJCMiIsIlJlLkUiOiJCMiJ9LCJHTSI6eyJYUyI6W119LCJiUSI6eyJjWCI6
+WyIxIl19LCJhTCI6eyJiUSI6WyIxIl0sImNYIjpbIjEiXX0sIm5IIjp7ImFMIjpbIjEiXSwiYlEiOlsi
+MSJdLCJjWCI6WyIxIl0sImFMLkUiOiIxIiwiY1guRSI6IjEifSwiYTciOnsiQW4iOlsiMSJdfSwiaTEi
+OnsiY1giOlsiMiJdLCJjWC5FIjoiMiJ9LCJ4eSI6eyJpMSI6WyIxIiwiMiJdLCJiUSI6WyIyIl0sImNY
+IjpbIjIiXSwiY1guRSI6IjIifSwiTUgiOnsiQW4iOlsiMiJdfSwibEoiOnsiYUwiOlsiMiJdLCJiUSI6
+WyIyIl0sImNYIjpbIjIiXSwiYUwuRSI6IjIiLCJjWC5FIjoiMiJ9LCJVNSI6eyJjWCI6WyIxIl0sImNY
+LkUiOiIxIn0sIlNPIjp7IkFuIjpbIjEiXX0sIkFNIjp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiZDUi
+OnsiQU0iOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXSwiY1guRSI6IjEifSwiVTEiOnsiQW4iOlsi
+MSJdfSwiTUIiOnsiYlEiOlsiMSJdLCJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIkZ1Ijp7IkFuIjpbIjEi
+XX0sInU2Ijp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiSkIiOnsiQW4iOlsiMSJdfSwidzIiOnsibEQi
+OlsiMSJdLCJSZSI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJ3diI6eyJH
+RCI6W119LCJQRCI6eyJHaiI6WyIxIiwiMiJdLCJSVSI6WyIxIiwiMiJdLCJQbiI6WyIxIiwiMiJdLCJL
+UCI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiV1UiOnsiWjAiOlsiMSIsIjIiXX0sIkxQIjp7IldV
+IjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJYUiI6eyJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIkxJ
+Ijp7InZRIjpbXX0sIlcwIjp7IlhTIjpbXX0sImF6Ijp7IlhTIjpbXX0sInZWIjp7IlhTIjpbXX0sInRl
+Ijp7IlJ6IjpbXX0sIlhPIjp7Ikd6IjpbXX0sIlRwIjp7IkVIIjpbXX0sImxjIjp7IkVIIjpbXX0sInp4
+Ijp7IkVIIjpbXX0sInJUIjp7IkVIIjpbXX0sIkVxIjp7IlhTIjpbXX0sImtZIjp7IlhTIjpbXX0sIk41
+Ijp7IllrIjpbIjEiLCIyIl0sIkZvIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl0sIllrLksiOiIxIiwi
+WWsuViI6IjIifSwiaTUiOnsiYlEiOlsiMSJdLCJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIk42Ijp7IkFu
+IjpbIjEiXX0sIlZSIjp7IndMIjpbXSwidlgiOltdfSwiRUsiOnsiaWIiOltdLCJPZCI6W119LCJLVyI6
+eyJjWCI6WyJpYiJdLCJjWC5FIjoiaWIifSwiUGIiOnsiQW4iOlsiaWIiXX0sInRRIjp7Ik9kIjpbXX0s
+InVuIjp7ImNYIjpbIk9kIl0sImNYLkUiOiJPZCJ9LCJTZCI6eyJBbiI6WyJPZCJdfSwiRVQiOnsiQVMi
+OltdfSwiTFoiOnsiWGoiOlsiMSJdLCJFVCI6W10sIkFTIjpbXX0sIkRnIjp7ImxEIjpbIkNQIl0sIlhq
+IjpbIkNQIl0sInpNIjpbIkNQIl0sIkVUIjpbXSwiYlEiOlsiQ1AiXSwiQVMiOltdLCJjWCI6WyJDUCJd
+LCJTVSI6WyJDUCJdLCJsRC5FIjoiQ1AifSwiUGciOnsibEQiOlsiQjIiXSwiWGoiOlsiQjIiXSwiek0i
+OlsiQjIiXSwiRVQiOltdLCJiUSI6WyJCMiJdLCJBUyI6W10sImNYIjpbIkIyIl0sIlNVIjpbIkIyIl19
+LCJ4aiI6eyJsRCI6WyJCMiJdLCJYaiI6WyJCMiJdLCJ6TSI6WyJCMiJdLCJFVCI6W10sImJRIjpbIkIy
+Il0sIkFTIjpbXSwiY1giOlsiQjIiXSwiU1UiOlsiQjIiXSwibEQuRSI6IkIyIn0sImRFIjp7ImxEIjpb
+IkIyIl0sIlhqIjpbIkIyIl0sInpNIjpbIkIyIl0sIkVUIjpbXSwiYlEiOlsiQjIiXSwiQVMiOltdLCJj
+WCI6WyJCMiJdLCJTVSI6WyJCMiJdLCJsRC5FIjoiQjIifSwiWkEiOnsibEQiOlsiQjIiXSwiWGoiOlsi
+QjIiXSwiek0iOlsiQjIiXSwiRVQiOltdLCJiUSI6WyJCMiJdLCJBUyI6W10sImNYIjpbIkIyIl0sIlNV
+IjpbIkIyIl0sImxELkUiOiJCMiJ9LCJkVCI6eyJsRCI6WyJCMiJdLCJYaiI6WyJCMiJdLCJ6TSI6WyJC
+MiJdLCJFVCI6W10sImJRIjpbIkIyIl0sIkFTIjpbXSwiY1giOlsiQjIiXSwiU1UiOlsiQjIiXSwibEQu
+RSI6IkIyIn0sIlBxIjp7ImxEIjpbIkIyIl0sIlhqIjpbIkIyIl0sInpNIjpbIkIyIl0sIkVUIjpbXSwi
+YlEiOlsiQjIiXSwiQVMiOltdLCJjWCI6WyJCMiJdLCJTVSI6WyJCMiJdLCJsRC5FIjoiQjIifSwiZUUi
+OnsibEQiOlsiQjIiXSwiWGoiOlsiQjIiXSwiek0iOlsiQjIiXSwiRVQiOltdLCJiUSI6WyJCMiJdLCJB
+UyI6W10sImNYIjpbIkIyIl0sIlNVIjpbIkIyIl0sImxELkUiOiJCMiJ9LCJWNiI6eyJsRCI6WyJCMiJd
+LCJuNiI6W10sIlhqIjpbIkIyIl0sInpNIjpbIkIyIl0sIkVUIjpbXSwiYlEiOlsiQjIiXSwiQVMiOltd
+LCJjWCI6WyJCMiJdLCJTVSI6WyJCMiJdLCJsRC5FIjoiQjIifSwia1MiOnsiWFMiOltdfSwiaU0iOnsi
+WFMiOltdfSwiR1YiOnsiQW4iOlsiMSJdfSwicTQiOnsiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJDdyI6
+eyJYUyI6W119LCJaZiI6eyJQZiI6WyIxIl19LCJ2cyI6eyJiOCI6WyIxIl19LCJtMCI6eyJRbSI6W119
+LCJKaSI6eyJtMCI6W10sIlFtIjpbXX0sImI2Ijp7ImxmIjpbIjEiXSwieHUiOlsiMSJdLCJiUSI6WyIx
+Il0sImNYIjpbIjEiXSwibGYuRSI6IjEifSwibG0iOnsiQW4iOlsiMSJdfSwibVciOnsiY1giOlsiMSJd
+fSwidXkiOnsibEQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwiaWwiOnsi
+WWsiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIllrIjp7IlowIjpbIjEiLCIyIl19LCJQbiI6eyJa
+MCI6WyIxIiwiMiJdfSwiR2oiOnsiUlUiOlsiMSIsIjIiXSwiUG4iOlsiMSIsIjIiXSwiS1AiOlsiMSIs
+IjIiXSwiWjAiOlsiMSIsIjIiXX0sIlZqIjp7ImxmIjpbIjEiXSwieHUiOlsiMSJdLCJiUSI6WyIxIl0s
+ImNYIjpbIjEiXX0sIlh2Ijp7ImxmIjpbIjEiXSwieHUiOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEi
+XX0sInV3Ijp7IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwiWWsuSyI6InFVIiwiWWsuViI6
+IkAifSwiaTgiOnsiYUwiOlsicVUiXSwiYlEiOlsicVUiXSwiY1giOlsicVUiXSwiYUwuRSI6InFVIiwi
+Y1guRSI6InFVIn0sIkNWIjp7IlVrIjpbInpNPEIyPiIsInFVIl0sIlVrLlMiOiJ6TTxCMj4ifSwiVTgi
+Onsid0kiOlsiek08QjI+IiwicVUiXX0sIlppIjp7IlVrIjpbInFVIiwiek08QjI+Il19LCJVZCI6eyJY
+UyI6W119LCJLOCI6eyJYUyI6W119LCJieSI6eyJVayI6WyJNaD8iLCJxVSJdLCJVay5TIjoiTWg/In0s
+Im9qIjp7IndJIjpbIk1oPyIsInFVIl19LCJNeCI6eyJ3SSI6WyJxVSIsIk1oPyJdfSwidTUiOnsiVWsi
+OlsicVUiLCJ6TTxCMj4iXSwiVWsuUyI6InFVIn0sIkUzIjp7IndJIjpbInFVIiwiek08QjI+Il19LCJH
+WSI6eyJ3SSI6WyJ6TTxCMj4iLCJxVSJdfSwiQ1AiOnsiWloiOltdfSwiQjIiOnsiWloiOltdfSwiek0i
+OnsiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJpYiI6eyJPZCI6W119LCJ4dSI6eyJiUSI6WyIxIl0sImNY
+IjpbIjEiXX0sInFVIjp7InZYIjpbXX0sIkM2Ijp7IlhTIjpbXX0sIkV6Ijp7IlhTIjpbXX0sIkYiOnsi
+WFMiOltdfSwidSI6eyJYUyI6W119LCJiSiI6eyJYUyI6W119LCJlWSI6eyJYUyI6W119LCJtcCI6eyJY
+UyI6W119LCJ1YiI6eyJYUyI6W119LCJkcyI6eyJYUyI6W119LCJsaiI6eyJYUyI6W119LCJVViI6eyJY
+UyI6W119LCJrNSI6eyJYUyI6W119LCJLWSI6eyJYUyI6W119LCJjIjp7IlhTIjpbXX0sIkNEIjp7IlJ6
+IjpbXX0sImFFIjp7IlJ6IjpbXX0sIlpkIjp7Ikd6IjpbXX0sIlJuIjp7IkJMIjpbXX0sIkRuIjp7ImlE
+IjpbXX0sIlVmIjp7ImlEIjpbXX0sInFlIjp7ImlEIjpbXX0sInFFIjp7ImN2IjpbXSwidUgiOltdLCJE
+MCI6W119LCJHaCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiZlkiOnsiY3YiOltdLCJ1SCI6W10s
+IkQwIjpbXX0sIm5CIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJRUCI6eyJjdiI6W10sInVIIjpb
+XSwiRDAiOltdfSwibngiOnsidUgiOltdLCJEMCI6W119LCJRRiI6eyJ1SCI6W10sIkQwIjpbXX0sIklC
+Ijp7InRuIjpbIlpaIl19LCJ3eiI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6
+WyIxIl0sImxELkUiOiIxIn0sImN2Ijp7InVIIjpbXSwiRDAiOltdfSwiaEgiOnsiQXoiOltdfSwiaDQi
+OnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlZiIjp7InVIIjpbXSwiRDAiOltdfSwiZkoiOnsiRDAi
+OltdfSwid2EiOnsiRDAiOltdfSwiQWoiOnsiZWEiOltdfSwiZTciOnsibEQiOlsidUgiXSwiek0iOlsi
+dUgiXSwiYlEiOlsidUgiXSwiY1giOlsidUgiXSwibEQuRSI6InVIIn0sInVIIjp7IkQwIjpbXX0sIkJI
+Ijp7ImxEIjpbInVIIl0sIkdtIjpbInVIIl0sInpNIjpbInVIIl0sIlhqIjpbInVIIl0sImJRIjpbInVI
+Il0sImNYIjpbInVIIl0sImxELkUiOiJ1SCIsIkdtLkUiOiJ1SCJ9LCJTTiI6eyJjdiI6W10sInVIIjpb
+XSwiRDAiOltdfSwiZXciOnsiZWEiOltdfSwibHAiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlRi
+Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJJdiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwi
+V1AiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sInlZIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119
+LCJ3NiI6eyJlYSI6W119LCJLNSI6eyJ2NiI6W10sIkQwIjpbXX0sIkNtIjp7IkQwIjpbXX0sIkNRIjp7
+InVIIjpbXSwiRDAiOltdfSwidzQiOnsidG4iOlsiWloiXX0sInJoIjp7ImxEIjpbInVIIl0sIkdtIjpb
+InVIIl0sInpNIjpbInVIIl0sIlhqIjpbInVIIl0sImJRIjpbInVIIl0sImNYIjpbInVIIl0sImxELkUi
+OiJ1SCIsIkdtLkUiOiJ1SCJ9LCJjZiI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXX0s
+Imk3Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUiLCJZay5WIjoi
+cVUifSwiU3kiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFVIl0sIllrLksiOiJxVSIsIllr
+LlYiOiJxVSJ9LCJJNCI6eyJsZiI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJiUSI6WyJxVSJdLCJjWCI6WyJx
+VSJdLCJsZi5FIjoicVUifSwiUk8iOnsicWgiOlsiMSJdfSwiZXUiOnsiUk8iOlsiMSJdLCJxaCI6WyIx
+Il19LCJ4QyI6eyJNTyI6WyIxIl19LCJKUSI6eyJrRiI6W119LCJ2RCI6eyJrRiI6W119LCJtNiI6eyJr
+RiI6W119LCJjdCI6eyJrRiI6W119LCJPdyI6eyJrRiI6W119LCJXOSI6eyJBbiI6WyIxIl19LCJkVyI6
+eyJ2NiI6W10sIkQwIjpbXX0sIm1rIjp7InkwIjpbXX0sIktvIjp7Im9uIjpbXX0sIkFzIjp7ImxmIjpb
+InFVIl0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl19LCJyNyI6eyJFNCI6W119LCJU
+eiI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJFNCI6W10sImNYIjpbIjEiXSwibEQu
+RSI6IjEifSwibmQiOnsiaGkiOltdLCJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiS2UiOnsibGYiOlsi
+cVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUiXSwiY1giOlsicVUiXSwibGYuRSI6InFVIn0sImhpIjp7
+ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJYQSI6eyJrRiI6W119LCJ2dCI6eyJEOCI6W119LCJjRCI6
+eyJEOCI6W119LCJkdiI6eyJSeiI6W119LCJPRiI6eyJmdiI6W119LCJydSI6eyJmdiI6W119LCJJViI6
+eyJmdiI6W119LCJuNiI6eyJ6TSI6WyJCMiJdLCJiUSI6WyJCMiJdLCJjWCI6WyJCMiJdLCJBUyI6W119
+fScpKQpILkZGKHYudHlwZVVuaXZlcnNlLEpTT04ucGFyc2UoJ3sidzIiOjEsIlFDIjoyLCJMWiI6MSwi
+a1QiOjIsIm1XIjoxLCJ1eSI6MSwiaWwiOjIsIlZqIjoxLCJYdiI6MSwiblkiOjEsIldZIjoxLCJwUiI6
+MSwiY28iOjF9JykpCnZhciB1PXtsOiJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJ
+IHdpdGggYSBmcmFnbWVudCBjb21wb25lbnQiLGk6IkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZy
+b20gYSBVUkkgd2l0aCBhIHF1ZXJ5IGNvbXBvbmVudCIsajoiQ2Fubm90IGV4dHJhY3QgYSBub24tV2lu
+ZG93cyBmaWxlIHBhdGggZnJvbSBhIGZpbGUgVVJJIHdpdGggYW4gYXV0aG9yaXR5IixnOiJgbnVsbGAg
+ZW5jb3VudGVyZWQgYXMgdGhlIHJlc3VsdCBmcm9tIGV4cHJlc3Npb24gd2l0aCB0eXBlIGBOZXZlcmAu
+IixkOiJhcmVhLWFuYWx5emVyLGFuYWx5emVyLW5uYmQtbWlncmF0aW9uLHR5cGUtYnVnIn0KdmFyIHQ9
+KGZ1bmN0aW9uIHJ0aWkoKXt2YXIgcz1ILk4wCnJldHVybntuOnMoIkN3IiksY1I6cygibkIiKSx3OnMo
+IkF6IikscDpzKCJRUCIpLGdGOnMoIlBEPEdELEA+IiksZDpzKCJiUTxAPiIpLGg6cygiY3YiKSxyOnMo
+IlhTIiksQjpzKCJlYSIpLGFTOnMoIkQwIiksZzg6cygiUnoiKSxjODpzKCJoSCIpLFk6cygiRUgiKSxl
+OnMoImI4PEA+IiksSTpzKCJTZyIpLG86cygidlEiKSxlaDpzKCJjWDx1SD4iKSxROnMoImNYPHFVPiIp
+LHU6cygiY1g8QD4iKSx2OnMoImpkPGtGPiIpLHM6cygiamQ8cVU+IiksZ046cygiamQ8bjY+IiksYjpz
+KCJqZDxAPiIpLGE6cygiamQ8QjI+IiksZDc6cygiamQ8U2UqPiIpLGg0OnMoImpkPGo4Kj4iKSxHOnMo
+ImpkPFowPHFVKixNaCo+Kj4iKSxjUTpzKCJqZDxEOCo+IiksaTpzKCJqZDxxVSo+IiksYUE6cygiamQ8
+eUQqPiIpLGFKOnMoImpkPHdiKj4iKSxWOnMoImpkPEIyKj4iKSxkNDpzKCJqZDxxVT8+IiksVDpzKCJ3
+ZSIpLGVIOnMoInZtIikseDpzKCJjNSIpLGFVOnMoIlhqPEA+IiksYW06cygiVHo8QD4iKSxlbzpzKCJO
+NTxHRCxAPiIpLGR6OnMoImhGIiksRDpzKCJ6TTxxVT4iKSxqOnMoInpNPEA+IiksTDpzKCJ6TTxCMj4i
+KSxKOnMoIlowPHFVLHFVPiIpLGY6cygiWjA8QCxAPiIpLGRvOnMoImxKPHFVLEA+IiksZmo6cygibEo8
+cVUqLHFVPiIpLGRFOnMoIkVUIiksYm06cygiVjYiKSxBOnMoInVIIiksRTpzKCJrRiIpLFA6cygiYzgi
+KSxLOnMoIk1oIikscTpzKCJ0bjxaWj4iKSxmdjpzKCJ3TCIpLGV3OnMoIm5kIiksQzpzKCJ4dTxxVT4i
+KSxsOnMoIkd6IiksTjpzKCJxVSIpLGQwOnMoInFVKHFVKikiKSxnNzpzKCJoaSIpLGZvOnMoIkdEIiks
+YVc6cygieVkiKSxhazpzKCJBUyIpLGdjOnMoIm42IiksYko6cygia2QiKSxkdzpzKCJHajxxVSxxVT4i
+KSxkRDpzKCJpRCIpLGVKOnMoInU2PHFVPiIpLGc0OnMoIks1IiksY2k6cygidjYiKSxnMjpzKCJDbSIp
+LGJDOnMoIlpmPGZKKj4iKSxoOTpzKCJDUSIpLGFjOnMoImU3IiksazpzKCJldTxBaio+IiksUjpzKCJ3
+ejxjdio+IiksYzpzKCJ2czxAPiIpLGZKOnMoInZzPEIyPiIpLGdWOnMoInZzPGZKKj4iKSxjcjpzKCJK
+USIpLHk6cygiYTIiKSxhbDpzKCJhMihNaCkiKSxnUjpzKCJDUCIpLHo6cygiQCIpLGZPOnMoIkAoKSIp
+LGJJOnMoIkAoTWgpIiksYWc6cygiQChNaCxHeikiKSxiVTpzKCJAKHh1PHFVPikiKSxkTzpzKCJAKHFV
+KSIpLGI4OnMoIkAoQCxAKSIpLFM6cygiQjIiKSxkZDpzKCJHaCoiKSxnOnMoImN2KiIpLGFMOnMoImVh
+KiIpLGFYOnMoIkxMKiIpLGZFOnMoIkg3KiIpLFU6cygiY1g8QD4qIiksZEg6cygiRTQqIiksZks6cygi
+ek08QD4qIiksZF86cygiek08ajgqPioiKSxkcDpzKCJ6TTxaMDxxVSosTWgqPio+KiIpLGVFOnMoInpN
+PE1oKj4qIiksYXc6cygiWjA8QCxAPioiKSx0OnMoIlowPHFVKixNaCo+KiIpLE86cygiQWoqIiksY0Y6
+cygiMCYqIiksXzpzKCJNaCoiKSxlUTpzKCJldyoiKSxYOnMoInFVKiIpLGNoOnMoIkQwPyIpLGJHOnMo
+ImI4PGM4Pj8iKSxiazpzKCJ6TTxxVT4/IiksYk06cygiek08QD4/IiksY1o6cygiWjA8cVUscVU+PyIp
+LGM5OnMoIlowPHFVLEA+PyIpLFc6cygiTWg/IiksRjpzKCJGZTxALEA+PyIpLG06cygiYm4/IiksYjc6
+cygiYTIoTWgpPyIpLGJ3OnMoIkAoZWEpPyIpLGZWOnMoIk1oPyhNaD8sTWg/KT8iKSxkQTpzKCJNaD8o
+QCk/IiksWjpzKCJ+KCk/IiksZWI6cygifihldyopPyIpLGRpOnMoIlpaIiksSDpzKCJ+IiksTTpzKCJ+
+KCkiKSxlQTpzKCJ+KHFVLHFVKSIpLGNBOnMoIn4ocVUsQCkiKX19KSgpOyhmdW5jdGlvbiBjb25zdGFu
+dHMoKXt2YXIgcz1odW5rSGVscGVycy5tYWtlQ29uc3RMaXN0CkMueG49Vy5HaC5wcm90b3R5cGUKQy5S
+WT1XLlFQLnByb3RvdHlwZQpDLm1IPVcuYWUucHJvdG90eXBlCkMuQlo9Vy5WYi5wcm90b3R5cGUKQy5E
+dD1XLmZKLnByb3RvdHlwZQpDLk9rPUouR3YucHJvdG90eXBlCkMuTm09Si5qZC5wcm90b3R5cGUKQy5q
+bj1KLmJVLnByb3RvdHlwZQpDLmpOPUoud2UucHJvdG90eXBlCkMuQ0Q9Si5xSS5wcm90b3R5cGUKQy54
+Qj1KLkRyLnByb3RvdHlwZQpDLkRHPUouYzUucHJvdG90eXBlCkMuRXg9Vy53Ny5wcm90b3R5cGUKQy5O
+QT1ILlY2LnByb3RvdHlwZQpDLnQ1PVcuQkgucHJvdG90eXBlCkMuTHQ9Vy5TTi5wcm90b3R5cGUKQy5a
+UT1KLmlDLnByb3RvdHlwZQpDLkllPVcuVGIucHJvdG90eXBlCkMudkI9Si5rZC5wcm90b3R5cGUKQy5v
+bD1XLks1LnByb3RvdHlwZQpDLnk4PW5ldyBQLlU4KCkKQy5oOT1uZXcgUC5DVigpCkMuR3c9bmV3IEgu
+RnUoSC5OMCgiRnU8Yzg+IikpCkMuTzQ9ZnVuY3Rpb24gZ2V0VGFnRmFsbGJhY2sobykgewogIHZhciBz
+ID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pOwogIHJldHVybiBzLnN1YnN0cmluZyg4
+LCBzLmxlbmd0aCAtIDEpOwp9CkMuWXE9ZnVuY3Rpb24oKSB7CiAgdmFyIHRvU3RyaW5nRnVuY3Rpb24g
+PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwogIGZ1bmN0aW9uIGdldFRhZyhvKSB7CiAgICB2YXIg
+cyA9IHRvU3RyaW5nRnVuY3Rpb24uY2FsbChvKTsKICAgIHJldHVybiBzLnN1YnN0cmluZyg4LCBzLmxl
+bmd0aCAtIDEpOwogIH0KICBmdW5jdGlvbiBnZXRVbmtub3duVGFnKG9iamVjdCwgdGFnKSB7CiAgICBp
+ZiAoL15IVE1MW0EtWl0uKkVsZW1lbnQkLy50ZXN0KHRhZykpIHsKICAgICAgdmFyIG5hbWUgPSB0b1N0
+cmluZ0Z1bmN0aW9uLmNhbGwob2JqZWN0KTsKICAgICAgaWYgKG5hbWUgPT0gIltvYmplY3QgT2JqZWN0
+XSIpIHJldHVybiBudWxsOwogICAgICByZXR1cm4gIkhUTUxFbGVtZW50IjsKICAgIH0KICB9CiAgZnVu
+Y3Rpb24gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyKG9iamVjdCwgdGFnKSB7CiAgICBpZiAoc2Vs
+Zi5IVE1MRWxlbWVudCAmJiBvYmplY3QgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkgcmV0dXJuICJIVE1M
+RWxlbWVudCI7CiAgICByZXR1cm4gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRhZyk7CiAgfQogIGZ1bmN0
+aW9uIHByb3RvdHlwZUZvclRhZyh0YWcpIHsKICAgIGlmICh0eXBlb2Ygd2luZG93ID09ICJ1bmRlZmlu
+ZWQiKSByZXR1cm4gbnVsbDsKICAgIGlmICh0eXBlb2Ygd2luZG93W3RhZ10gPT0gInVuZGVmaW5lZCIp
+IHJldHVybiBudWxsOwogICAgdmFyIGNvbnN0cnVjdG9yID0gd2luZG93W3RhZ107CiAgICBpZiAodHlw
+ZW9mIGNvbnN0cnVjdG9yICE9ICJmdW5jdGlvbiIpIHJldHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0
+cnVjdG9yLnByb3RvdHlwZTsKICB9CiAgZnVuY3Rpb24gZGlzY3JpbWluYXRvcih0YWcpIHsgcmV0dXJu
+IG51bGw7IH0KICB2YXIgaXNCcm93c2VyID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IjsKICBy
+ZXR1cm4gewogICAgZ2V0VGFnOiBnZXRUYWcsCiAgICBnZXRVbmtub3duVGFnOiBpc0Jyb3dzZXIgPyBn
+ZXRVbmtub3duVGFnR2VuZXJpY0Jyb3dzZXIgOiBnZXRVbmtub3duVGFnLAogICAgcHJvdG90eXBlRm9y
+VGFnOiBwcm90b3R5cGVGb3JUYWcsCiAgICBkaXNjcmltaW5hdG9yOiBkaXNjcmltaW5hdG9yIH07Cn0K
+Qy53Yj1mdW5jdGlvbihnZXRUYWdGYWxsYmFjaykgewogIHJldHVybiBmdW5jdGlvbihob29rcykgewog
+ICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT0gIm9iamVjdCIpIHJldHVybiBob29rczsKICAgIHZhciB1
+YSA9IG5hdmlnYXRvci51c2VyQWdlbnQ7CiAgICBpZiAodWEuaW5kZXhPZigiRHVtcFJlbmRlclRyZWUi
+KSA+PSAwKSByZXR1cm4gaG9va3M7CiAgICBpZiAodWEuaW5kZXhPZigiQ2hyb21lIikgPj0gMCkgewog
+ICAgICBmdW5jdGlvbiBjb25maXJtKHApIHsKICAgICAgICByZXR1cm4gdHlwZW9mIHdpbmRvdyA9PSAi
+b2JqZWN0IiAmJiB3aW5kb3dbcF0gJiYgd2luZG93W3BdLm5hbWUgPT0gcDsKICAgICAgfQogICAgICBp
+ZiAoY29uZmlybSgiV2luZG93IikgJiYgY29uZmlybSgiSFRNTEVsZW1lbnQiKSkgcmV0dXJuIGhvb2tz
+OwogICAgfQogICAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnRmFsbGJhY2s7CiAgfTsKfQpDLktVPWZ1bmN0
+aW9uKGhvb2tzKSB7CiAgaWYgKHR5cGVvZiBkYXJ0RXhwZXJpbWVudGFsRml4dXBHZXRUYWcgIT0gImZ1
+bmN0aW9uIikgcmV0dXJuIGhvb2tzOwogIGhvb2tzLmdldFRhZyA9IGRhcnRFeHBlcmltZW50YWxGaXh1
+cEdldFRhZyhob29rcy5nZXRUYWcpOwp9CkMuZlE9ZnVuY3Rpb24oaG9va3MpIHsKICB2YXIgZ2V0VGFn
+ID0gaG9va3MuZ2V0VGFnOwogIHZhciBwcm90b3R5cGVGb3JUYWcgPSBob29rcy5wcm90b3R5cGVGb3JU
+YWc7CiAgZnVuY3Rpb24gZ2V0VGFnRml4ZWQobykgewogICAgdmFyIHRhZyA9IGdldFRhZyhvKTsKICAg
+IGlmICh0YWcgPT0gIkRvY3VtZW50IikgewogICAgICBpZiAoISFvLnhtbFZlcnNpb24pIHJldHVybiAi
+IURvY3VtZW50IjsKICAgICAgcmV0dXJuICIhSFRNTERvY3VtZW50IjsKICAgIH0KICAgIHJldHVybiB0
+YWc7CiAgfQogIGZ1bmN0aW9uIHByb3RvdHlwZUZvclRhZ0ZpeGVkKHRhZykgewogICAgaWYgKHRhZyA9
+PSAiRG9jdW1lbnQiKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBwcm90b3R5cGVGb3JUYWcodGFnKTsK
+ICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnRml4ZWQ7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0g
+cHJvdG90eXBlRm9yVGFnRml4ZWQ7Cn0KQy5kaz1mdW5jdGlvbihob29rcykgewogIHZhciB1c2VyQWdl
 bnQgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJBZ2VudCA6ICIi
-OwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiVHJpZGVudC8iKSA9PSAtMSkgcmV0dXJuIGhvb2tzOwog
-IHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAgIkJlZm9yZVVu
-bG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJkIiwKICAgICJI
-VE1MRERFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJIVE1MRFRFbGVtZW50IjogIkhUTUxFbGVt
-ZW50IiwKICAgICJIVE1MUGhyYXNlRWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAiUG9zaXRpb24i
-OiAiR2VvcG9zaXRpb24iCiAgfTsKICBmdW5jdGlvbiBnZXRUYWdJRShvKSB7CiAgICB2YXIgdGFnID0g
-Z2V0VGFnKG8pOwogICAgdmFyIG5ld1RhZyA9IHF1aWNrTWFwW3RhZ107CiAgICBpZiAobmV3VGFnKSBy
-ZXR1cm4gbmV3VGFnOwogICAgaWYgKHRhZyA9PSAiT2JqZWN0IikgewogICAgICBpZiAod2luZG93LkRh
-dGFWaWV3ICYmIChvIGluc3RhbmNlb2Ygd2luZG93LkRhdGFWaWV3KSkgcmV0dXJuICJEYXRhVmlldyI7
-CiAgICB9CiAgICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdJRSh0YWcp
-IHsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKGNvbnN0cnVjdG9yID09
-IG51bGwpIHJldHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsKICB9CiAg
-aG9va3MuZ2V0VGFnID0gZ2V0VGFnSUU7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0gcHJvdG90eXBl
-Rm9yVGFnSUU7Cn0KQy5pNz1mdW5jdGlvbihob29rcykgeyByZXR1cm4gaG9va3M7IH0KCkMuQ3Q9bmV3
-IFAuYnkoKQpDLkVxPW5ldyBQLms1KCkKQy54TT1uZXcgUC51NSgpCkMuUWs9bmV3IFAuRTMoKQpDLk52
-PW5ldyBILmtyKCkKQy5OVT1uZXcgUC5KaSgpCkMucGQ9bmV3IFAuWmQoKQpDLkFkPW5ldyBNLkg3KDAs
-IkhpbnRBY3Rpb25LaW5kLmFkZE51bGxhYmxlSGludCIpCkMubmU9bmV3IE0uSDcoMSwiSGludEFjdGlv
-bktpbmQuYWRkTm9uTnVsbGFibGVIaW50IikKQy5teT1uZXcgTS5INygyLCJIaW50QWN0aW9uS2luZC5j
-aGFuZ2VUb051bGxhYmxlSGludCIpCkMucng9bmV3IE0uSDcoMywiSGludEFjdGlvbktpbmQuY2hhbmdl
-VG9Ob25OdWxsYWJsZUhpbnQiKQpDLndWPW5ldyBNLkg3KDQsIkhpbnRBY3Rpb25LaW5kLnJlbW92ZU51
-bGxhYmxlSGludCIpCkMuZlI9bmV3IE0uSDcoNSwiSGludEFjdGlvbktpbmQucmVtb3ZlTm9uTnVsbGFi
-bGVIaW50IikKQy5BMz1uZXcgUC5NeChudWxsKQpDLm5YPW5ldyBQLm9qKG51bGwpCkMuY3c9bmV3IEwu
-R2IoMCwiVW5pdE1pZ3JhdGlvblN0YXR1cy5hbHJlYWR5TWlncmF0ZWQiKQpDLmRjPW5ldyBMLkdiKDEs
-IlVuaXRNaWdyYXRpb25TdGF0dXMuaW5kZXRlcm1pbmF0ZSIpCkMuV0Q9bmV3IEwuR2IoMiwiVW5pdE1p
-Z3JhdGlvblN0YXR1cy5taWdyYXRpbmciKQpDLlhqPW5ldyBMLkdiKDMsIlVuaXRNaWdyYXRpb25TdGF0
-dXMub3B0aW5nT3V0IikKQy5sMD1ILlZNKHMoW0MuY3csQy5kYyxDLldELEMuWGpdKSxILk4wKCJqZDxH
-Yio+IikpCkMuYWs9SC5WTShzKFswLDAsMzI3NzYsMzM3OTIsMSwxMDI0MCwwLDBdKSx0LlYpCkMuY209
-SC5WTShzKFsiKjo6Y2xhc3MiLCIqOjpkaXIiLCIqOjpkcmFnZ2FibGUiLCIqOjpoaWRkZW4iLCIqOjpp
-ZCIsIio6OmluZXJ0IiwiKjo6aXRlbXByb3AiLCIqOjppdGVtcmVmIiwiKjo6aXRlbXNjb3BlIiwiKjo6
-bGFuZyIsIio6OnNwZWxsY2hlY2siLCIqOjp0aXRsZSIsIio6OnRyYW5zbGF0ZSIsIkE6OmFjY2Vzc2tl
-eSIsIkE6OmNvb3JkcyIsIkE6OmhyZWZsYW5nIiwiQTo6bmFtZSIsIkE6OnNoYXBlIiwiQTo6dGFiaW5k
-ZXgiLCJBOjp0YXJnZXQiLCJBOjp0eXBlIiwiQVJFQTo6YWNjZXNza2V5IiwiQVJFQTo6YWx0IiwiQVJF
-QTo6Y29vcmRzIiwiQVJFQTo6bm9ocmVmIiwiQVJFQTo6c2hhcGUiLCJBUkVBOjp0YWJpbmRleCIsIkFS
-RUE6OnRhcmdldCIsIkFVRElPOjpjb250cm9scyIsIkFVRElPOjpsb29wIiwiQVVESU86Om1lZGlhZ3Jv
-dXAiLCJBVURJTzo6bXV0ZWQiLCJBVURJTzo6cHJlbG9hZCIsIkJETzo6ZGlyIiwiQk9EWTo6YWxpbmsi
-LCJCT0RZOjpiZ2NvbG9yIiwiQk9EWTo6bGluayIsIkJPRFk6OnRleHQiLCJCT0RZOjp2bGluayIsIkJS
-OjpjbGVhciIsIkJVVFRPTjo6YWNjZXNza2V5IiwiQlVUVE9OOjpkaXNhYmxlZCIsIkJVVFRPTjo6bmFt
-ZSIsIkJVVFRPTjo6dGFiaW5kZXgiLCJCVVRUT046OnR5cGUiLCJCVVRUT046OnZhbHVlIiwiQ0FOVkFT
-OjpoZWlnaHQiLCJDQU5WQVM6OndpZHRoIiwiQ0FQVElPTjo6YWxpZ24iLCJDT0w6OmFsaWduIiwiQ09M
-OjpjaGFyIiwiQ09MOjpjaGFyb2ZmIiwiQ09MOjpzcGFuIiwiQ09MOjp2YWxpZ24iLCJDT0w6OndpZHRo
-IiwiQ09MR1JPVVA6OmFsaWduIiwiQ09MR1JPVVA6OmNoYXIiLCJDT0xHUk9VUDo6Y2hhcm9mZiIsIkNP
-TEdST1VQOjpzcGFuIiwiQ09MR1JPVVA6OnZhbGlnbiIsIkNPTEdST1VQOjp3aWR0aCIsIkNPTU1BTkQ6
-OmNoZWNrZWQiLCJDT01NQU5EOjpjb21tYW5kIiwiQ09NTUFORDo6ZGlzYWJsZWQiLCJDT01NQU5EOjps
-YWJlbCIsIkNPTU1BTkQ6OnJhZGlvZ3JvdXAiLCJDT01NQU5EOjp0eXBlIiwiREFUQTo6dmFsdWUiLCJE
-RUw6OmRhdGV0aW1lIiwiREVUQUlMUzo6b3BlbiIsIkRJUjo6Y29tcGFjdCIsIkRJVjo6YWxpZ24iLCJE
-TDo6Y29tcGFjdCIsIkZJRUxEU0VUOjpkaXNhYmxlZCIsIkZPTlQ6OmNvbG9yIiwiRk9OVDo6ZmFjZSIs
-IkZPTlQ6OnNpemUiLCJGT1JNOjphY2NlcHQiLCJGT1JNOjphdXRvY29tcGxldGUiLCJGT1JNOjplbmN0
-eXBlIiwiRk9STTo6bWV0aG9kIiwiRk9STTo6bmFtZSIsIkZPUk06Om5vdmFsaWRhdGUiLCJGT1JNOjp0
-YXJnZXQiLCJGUkFNRTo6bmFtZSIsIkgxOjphbGlnbiIsIkgyOjphbGlnbiIsIkgzOjphbGlnbiIsIkg0
-OjphbGlnbiIsIkg1OjphbGlnbiIsIkg2OjphbGlnbiIsIkhSOjphbGlnbiIsIkhSOjpub3NoYWRlIiwi
-SFI6OnNpemUiLCJIUjo6d2lkdGgiLCJIVE1MOjp2ZXJzaW9uIiwiSUZSQU1FOjphbGlnbiIsIklGUkFN
-RTo6ZnJhbWVib3JkZXIiLCJJRlJBTUU6OmhlaWdodCIsIklGUkFNRTo6bWFyZ2luaGVpZ2h0IiwiSUZS
-QU1FOjptYXJnaW53aWR0aCIsIklGUkFNRTo6d2lkdGgiLCJJTUc6OmFsaWduIiwiSU1HOjphbHQiLCJJ
-TUc6OmJvcmRlciIsIklNRzo6aGVpZ2h0IiwiSU1HOjpoc3BhY2UiLCJJTUc6OmlzbWFwIiwiSU1HOjpu
-YW1lIiwiSU1HOjp1c2VtYXAiLCJJTUc6OnZzcGFjZSIsIklNRzo6d2lkdGgiLCJJTlBVVDo6YWNjZXB0
-IiwiSU5QVVQ6OmFjY2Vzc2tleSIsIklOUFVUOjphbGlnbiIsIklOUFVUOjphbHQiLCJJTlBVVDo6YXV0
-b2NvbXBsZXRlIiwiSU5QVVQ6OmF1dG9mb2N1cyIsIklOUFVUOjpjaGVja2VkIiwiSU5QVVQ6OmRpc2Fi
-bGVkIiwiSU5QVVQ6OmlucHV0bW9kZSIsIklOUFVUOjppc21hcCIsIklOUFVUOjpsaXN0IiwiSU5QVVQ6
-Om1heCIsIklOUFVUOjptYXhsZW5ndGgiLCJJTlBVVDo6bWluIiwiSU5QVVQ6Om11bHRpcGxlIiwiSU5Q
-VVQ6Om5hbWUiLCJJTlBVVDo6cGxhY2Vob2xkZXIiLCJJTlBVVDo6cmVhZG9ubHkiLCJJTlBVVDo6cmVx
-dWlyZWQiLCJJTlBVVDo6c2l6ZSIsIklOUFVUOjpzdGVwIiwiSU5QVVQ6OnRhYmluZGV4IiwiSU5QVVQ6
-OnR5cGUiLCJJTlBVVDo6dXNlbWFwIiwiSU5QVVQ6OnZhbHVlIiwiSU5TOjpkYXRldGltZSIsIktFWUdF
-Tjo6ZGlzYWJsZWQiLCJLRVlHRU46OmtleXR5cGUiLCJLRVlHRU46Om5hbWUiLCJMQUJFTDo6YWNjZXNz
-a2V5IiwiTEFCRUw6OmZvciIsIkxFR0VORDo6YWNjZXNza2V5IiwiTEVHRU5EOjphbGlnbiIsIkxJOjp0
-eXBlIiwiTEk6OnZhbHVlIiwiTElOSzo6c2l6ZXMiLCJNQVA6Om5hbWUiLCJNRU5VOjpjb21wYWN0Iiwi
-TUVOVTo6bGFiZWwiLCJNRU5VOjp0eXBlIiwiTUVURVI6OmhpZ2giLCJNRVRFUjo6bG93IiwiTUVURVI6
-Om1heCIsIk1FVEVSOjptaW4iLCJNRVRFUjo6dmFsdWUiLCJPQkpFQ1Q6OnR5cGVtdXN0bWF0Y2giLCJP
-TDo6Y29tcGFjdCIsIk9MOjpyZXZlcnNlZCIsIk9MOjpzdGFydCIsIk9MOjp0eXBlIiwiT1BUR1JPVVA6
-OmRpc2FibGVkIiwiT1BUR1JPVVA6OmxhYmVsIiwiT1BUSU9OOjpkaXNhYmxlZCIsIk9QVElPTjo6bGFi
-ZWwiLCJPUFRJT046OnNlbGVjdGVkIiwiT1BUSU9OOjp2YWx1ZSIsIk9VVFBVVDo6Zm9yIiwiT1VUUFVU
-OjpuYW1lIiwiUDo6YWxpZ24iLCJQUkU6OndpZHRoIiwiUFJPR1JFU1M6Om1heCIsIlBST0dSRVNTOjpt
-aW4iLCJQUk9HUkVTUzo6dmFsdWUiLCJTRUxFQ1Q6OmF1dG9jb21wbGV0ZSIsIlNFTEVDVDo6ZGlzYWJs
-ZWQiLCJTRUxFQ1Q6Om11bHRpcGxlIiwiU0VMRUNUOjpuYW1lIiwiU0VMRUNUOjpyZXF1aXJlZCIsIlNF
-TEVDVDo6c2l6ZSIsIlNFTEVDVDo6dGFiaW5kZXgiLCJTT1VSQ0U6OnR5cGUiLCJUQUJMRTo6YWxpZ24i
-LCJUQUJMRTo6Ymdjb2xvciIsIlRBQkxFOjpib3JkZXIiLCJUQUJMRTo6Y2VsbHBhZGRpbmciLCJUQUJM
-RTo6Y2VsbHNwYWNpbmciLCJUQUJMRTo6ZnJhbWUiLCJUQUJMRTo6cnVsZXMiLCJUQUJMRTo6c3VtbWFy
-eSIsIlRBQkxFOjp3aWR0aCIsIlRCT0RZOjphbGlnbiIsIlRCT0RZOjpjaGFyIiwiVEJPRFk6OmNoYXJv
-ZmYiLCJUQk9EWTo6dmFsaWduIiwiVEQ6OmFiYnIiLCJURDo6YWxpZ24iLCJURDo6YXhpcyIsIlREOjpi
-Z2NvbG9yIiwiVEQ6OmNoYXIiLCJURDo6Y2hhcm9mZiIsIlREOjpjb2xzcGFuIiwiVEQ6OmhlYWRlcnMi
-LCJURDo6aGVpZ2h0IiwiVEQ6Om5vd3JhcCIsIlREOjpyb3dzcGFuIiwiVEQ6OnNjb3BlIiwiVEQ6OnZh
-bGlnbiIsIlREOjp3aWR0aCIsIlRFWFRBUkVBOjphY2Nlc3NrZXkiLCJURVhUQVJFQTo6YXV0b2NvbXBs
-ZXRlIiwiVEVYVEFSRUE6OmNvbHMiLCJURVhUQVJFQTo6ZGlzYWJsZWQiLCJURVhUQVJFQTo6aW5wdXRt
-b2RlIiwiVEVYVEFSRUE6Om5hbWUiLCJURVhUQVJFQTo6cGxhY2Vob2xkZXIiLCJURVhUQVJFQTo6cmVh
-ZG9ubHkiLCJURVhUQVJFQTo6cmVxdWlyZWQiLCJURVhUQVJFQTo6cm93cyIsIlRFWFRBUkVBOjp0YWJp
-bmRleCIsIlRFWFRBUkVBOjp3cmFwIiwiVEZPT1Q6OmFsaWduIiwiVEZPT1Q6OmNoYXIiLCJURk9PVDo6
-Y2hhcm9mZiIsIlRGT09UOjp2YWxpZ24iLCJUSDo6YWJiciIsIlRIOjphbGlnbiIsIlRIOjpheGlzIiwi
-VEg6OmJnY29sb3IiLCJUSDo6Y2hhciIsIlRIOjpjaGFyb2ZmIiwiVEg6OmNvbHNwYW4iLCJUSDo6aGVh
-ZGVycyIsIlRIOjpoZWlnaHQiLCJUSDo6bm93cmFwIiwiVEg6OnJvd3NwYW4iLCJUSDo6c2NvcGUiLCJU
-SDo6dmFsaWduIiwiVEg6OndpZHRoIiwiVEhFQUQ6OmFsaWduIiwiVEhFQUQ6OmNoYXIiLCJUSEVBRDo6
-Y2hhcm9mZiIsIlRIRUFEOjp2YWxpZ24iLCJUUjo6YWxpZ24iLCJUUjo6Ymdjb2xvciIsIlRSOjpjaGFy
-IiwiVFI6OmNoYXJvZmYiLCJUUjo6dmFsaWduIiwiVFJBQ0s6OmRlZmF1bHQiLCJUUkFDSzo6a2luZCIs
-IlRSQUNLOjpsYWJlbCIsIlRSQUNLOjpzcmNsYW5nIiwiVUw6OmNvbXBhY3QiLCJVTDo6dHlwZSIsIlZJ
-REVPOjpjb250cm9scyIsIlZJREVPOjpoZWlnaHQiLCJWSURFTzo6bG9vcCIsIlZJREVPOjptZWRpYWdy
-b3VwIiwiVklERU86Om11dGVkIiwiVklERU86OnByZWxvYWQiLCJWSURFTzo6d2lkdGgiXSksdC5pKQpD
-LlZDPUguVk0ocyhbMCwwLDY1NDkwLDQ1MDU1LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdC5WKQpD
-Lm1LPUguVk0ocyhbMCwwLDI2NjI0LDEwMjMsNjU1MzQsMjA0Nyw2NTUzNCwyMDQ3XSksdC5WKQpDLlNx
-PUguVk0ocyhbIkhFQUQiLCJBUkVBIiwiQkFTRSIsIkJBU0VGT05UIiwiQlIiLCJDT0wiLCJDT0xHUk9V
-UCIsIkVNQkVEIiwiRlJBTUUiLCJGUkFNRVNFVCIsIkhSIiwiSU1BR0UiLCJJTUciLCJJTlBVVCIsIklT
-SU5ERVgiLCJMSU5LIiwiTUVUQSIsIlBBUkFNIiwiU09VUkNFIiwiU1RZTEUiLCJUSVRMRSIsIldCUiJd
-KSx0LmkpCkMuaFU9SC5WTShzKFtdKSx0LngpCkMuZG49SC5WTShzKFtdKSxILk4wKCJqZDxMTCo+Iikp
-CkMueEQ9SC5WTShzKFtdKSx0LmkpCkMudG89SC5WTShzKFswLDAsMzI3MjIsMTIyODcsNjU1MzQsMzQ4
-MTUsNjU1MzQsMTg0MzFdKSx0LlYpCkMucms9SC5WTShzKFtDLkFkLEMubmUsQy5teSxDLnJ4LEMud1Ys
-Qy5mUl0pLEguTjAoImpkPEg3Kj4iKSkKQy5GMz1ILlZNKHMoWzAsMCwyNDU3NiwxMDIzLDY1NTM0LDM0
-ODE1LDY1NTM0LDE4NDMxXSksdC5WKQpDLmVhPUguVk0ocyhbMCwwLDMyNzU0LDExMjYzLDY1NTM0LDM0
-ODE1LDY1NTM0LDE4NDMxXSksdC5WKQpDLlpKPUguVk0ocyhbMCwwLDMyNzIyLDEyMjg3LDY1NTM1LDM0
-ODE1LDY1NTM0LDE4NDMxXSksdC5WKQpDLldkPUguVk0ocyhbMCwwLDY1NDkwLDEyMjg3LDY1NTM1LDM0
-ODE1LDY1NTM0LDE4NDMxXSksdC5WKQpDLlF4PUguVk0ocyhbImJpbmQiLCJpZiIsInJlZiIsInJlcGVh
-dCIsInN5bnRheCJdKSx0LmkpCkMuQkk9SC5WTShzKFsiQTo6aHJlZiIsIkFSRUE6OmhyZWYiLCJCTE9D
-S1FVT1RFOjpjaXRlIiwiQk9EWTo6YmFja2dyb3VuZCIsIkNPTU1BTkQ6Omljb24iLCJERUw6OmNpdGUi
-LCJGT1JNOjphY3Rpb24iLCJJTUc6OnNyYyIsIklOUFVUOjpzcmMiLCJJTlM6OmNpdGUiLCJROjpjaXRl
-IiwiVklERU86OnBvc3RlciJdKSx0LmkpCkMuRHg9bmV3IEguTFAoMCx7fSxDLnhELEguTjAoIkxQPHFV
-Kix6TTxqOCo+Kj4iKSkKQy5DTT1uZXcgSC5MUCgwLHt9LEMueEQsSC5OMCgiTFA8cVUqLHFVKj4iKSkK
-Qy5pSD1ILlZNKHMoW10pLEguTjAoImpkPEdEKj4iKSkKQy5XTz1uZXcgSC5MUCgwLHt9LEMuaUgsSC5O
-MCgiTFA8R0QqLEA+IikpCkMuWTI9bmV3IEwuTzkoIk5hdmlnYXRpb25UcmVlTm9kZVR5cGUuZGlyZWN0
-b3J5IikKQy5yZj1uZXcgTC5POSgiTmF2aWdhdGlvblRyZWVOb2RlVHlwZS5maWxlIikKQy5UZT1uZXcg
-SC53digiY2FsbCIpCkMub0U9bmV3IFAuR1koITEpCkMud1E9bmV3IFAuRnkobnVsbCwyKX0pKCk7KGZ1
-bmN0aW9uIHN0YXRpY0ZpZWxkcygpeyQuem09bnVsbAokLnlqPTAKJC5tSj1udWxsCiQuUDQ9bnVsbAok
-Lk5GPW51bGwKJC5UWD1udWxsCiQueDc9bnVsbAokLm53PW51bGwKJC52dj1udWxsCiQuQnY9bnVsbAok
-LlM2PW51bGwKJC5rOD1udWxsCiQubWc9bnVsbAokLlVEPSExCiQuWDM9Qy5OVQokLnhnPUguVk0oW10s
-SC5OMCgiamQ8TWg+IikpCiQueG89bnVsbAokLkJPPW51bGwKJC5sdD1udWxsCiQuRVU9bnVsbAokLm9y
-PVAuRmwodC5OLHQuWSkKJC5JUj1udWxsCiQuSTY9bnVsbAokLkZmPW51bGx9KSgpOyhmdW5jdGlvbiBs
-YXp5SW5pdGlhbGl6ZXJzKCl7dmFyIHM9aHVua0hlbHBlcnMubGF6eUZpbmFsLHI9aHVua0hlbHBlcnMu
-bGF6eU9sZApzKCQsImZhIiwidyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5ZZygiXyRkYXJ0X2RhcnRDbG9z
-dXJlIil9KQpzKCQsIlUyIiwiU24iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5TNyh7CnRvU3RyaW5n
-OmZ1bmN0aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0pKX0pCnMoJCwieHEiLCJscSIsZnVuY3Rpb24o
-KXtyZXR1cm4gSC5jTShILlM3KHskbWV0aG9kJDpudWxsLAp0b1N0cmluZzpmdW5jdGlvbigpe3JldHVy
-biIkcmVjZWl2ZXIkIn19KSl9KQpzKCQsIlIxIiwiTjkiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5T
-NyhudWxsKSl9KQpzKCQsImZOIiwiaUkiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVuY3Rpb24oKXt2
-YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJndW1lbnRzJCcKdHJ5e251bGwuJG1ldGhvZCQoJGFyZ3VtZW50
-c0V4cHIkKX1jYXRjaChxKXtyZXR1cm4gcS5tZXNzYWdlfX0oKSl9KQpzKCQsInFpIiwiVU4iLGZ1bmN0
-aW9uKCl7cmV0dXJuIEguY00oSC5TNyh2b2lkIDApKX0pCnMoJCwicloiLCJaaCIsZnVuY3Rpb24oKXty
-ZXR1cm4gSC5jTShmdW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7
-KHZvaWQgMCkuJG1ldGhvZCQoJGFyZ3VtZW50c0V4cHIkKX1jYXRjaChxKXtyZXR1cm4gcS5tZXNzYWdl
-fX0oKSl9KQpzKCQsImtxIiwick4iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5NaihudWxsKSl9KQpz
-KCQsInR0IiwiYzMiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVuY3Rpb24oKXt0cnl7bnVsbC4kbWV0
-aG9kJH1jYXRjaChxKXtyZXR1cm4gcS5tZXNzYWdlfX0oKSl9KQpzKCQsImR0IiwiSEsiLGZ1bmN0aW9u
-KCl7cmV0dXJuIEguY00oSC5Naih2b2lkIDApKX0pCnMoJCwiQTciLCJyMSIsZnVuY3Rpb24oKXtyZXR1
-cm4gSC5jTShmdW5jdGlvbigpe3RyeXsodm9pZCAwKS4kbWV0aG9kJH1jYXRjaChxKXtyZXR1cm4gcS5t
-ZXNzYWdlfX0oKSl9KQpzKCQsIldjIiwidXQiLGZ1bmN0aW9uKCl7cmV0dXJuIFAuT2ooKX0pCnMoJCwi
-a2giLCJyZiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IFAucGcoKS4kMCgpfSkKcygkLCJkSCIsIkhHIixm
-dW5jdGlvbigpe3JldHVybiBuZXcgUC5jMigpLiQwKCl9KQpzKCQsImJ0IiwiVjciLGZ1bmN0aW9uKCl7
-cmV0dXJuIG5ldyBJbnQ4QXJyYXkoSC5YRihILlZNKFstMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwt
-MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwt
-MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMSwtMiwtMiwtMiwtMiwtMiw2MiwtMiw2MiwtMiw2Myw1Miw1
-Myw1NCw1NSw1Niw1Nyw1OCw1OSw2MCw2MSwtMiwtMiwtMiwtMSwtMiwtMiwtMiwwLDEsMiwzLDQsNSw2
-LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5LDIwLDIxLDIyLDIzLDI0LDI1LC0yLC0y
-LC0yLC0yLDYzLC0yLDI2LDI3LDI4LDI5LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3LDM4LDM5LDQwLDQx
-LDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLC0yLC0yLC0yLC0yLC0yXSx0LmEpKSl9KQpzKCQs
-Ik01Iiwid1EiLGZ1bmN0aW9uKCl7cmV0dXJuIHR5cGVvZiBwcm9jZXNzIT0idW5kZWZpbmVkIiYmT2Jq
-ZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHByb2Nlc3MpPT0iW29iamVjdCBwcm9jZXNzXSImJnBy
-b2Nlc3MucGxhdGZvcm09PSJ3aW4zMiJ9KQpzKCQsIm1mIiwiejQiLGZ1bmN0aW9uKCl7cmV0dXJuIFAu
-bnUoIl5bXFwtXFwuMC05QS1aX2Eten5dKiQiKX0pCnMoJCwiT1EiLCJ2WiIsZnVuY3Rpb24oKXtyZXR1
-cm4gUC5LTigpfSkKcygkLCJTQyIsIkFOIixmdW5jdGlvbigpe3JldHVybiBQLnRNKFsiQSIsIkFCQlIi
-LCJBQ1JPTllNIiwiQUREUkVTUyIsIkFSRUEiLCJBUlRJQ0xFIiwiQVNJREUiLCJBVURJTyIsIkIiLCJC
-REkiLCJCRE8iLCJCSUciLCJCTE9DS1FVT1RFIiwiQlIiLCJCVVRUT04iLCJDQU5WQVMiLCJDQVBUSU9O
-IiwiQ0VOVEVSIiwiQ0lURSIsIkNPREUiLCJDT0wiLCJDT0xHUk9VUCIsIkNPTU1BTkQiLCJEQVRBIiwi
-REFUQUxJU1QiLCJERCIsIkRFTCIsIkRFVEFJTFMiLCJERk4iLCJESVIiLCJESVYiLCJETCIsIkRUIiwi
-RU0iLCJGSUVMRFNFVCIsIkZJR0NBUFRJT04iLCJGSUdVUkUiLCJGT05UIiwiRk9PVEVSIiwiRk9STSIs
-IkgxIiwiSDIiLCJIMyIsIkg0IiwiSDUiLCJINiIsIkhFQURFUiIsIkhHUk9VUCIsIkhSIiwiSSIsIklG
-UkFNRSIsIklNRyIsIklOUFVUIiwiSU5TIiwiS0JEIiwiTEFCRUwiLCJMRUdFTkQiLCJMSSIsIk1BUCIs
-Ik1BUksiLCJNRU5VIiwiTUVURVIiLCJOQVYiLCJOT0JSIiwiT0wiLCJPUFRHUk9VUCIsIk9QVElPTiIs
-Ik9VVFBVVCIsIlAiLCJQUkUiLCJQUk9HUkVTUyIsIlEiLCJTIiwiU0FNUCIsIlNFQ1RJT04iLCJTRUxF
-Q1QiLCJTTUFMTCIsIlNPVVJDRSIsIlNQQU4iLCJTVFJJS0UiLCJTVFJPTkciLCJTVUIiLCJTVU1NQVJZ
-IiwiU1VQIiwiVEFCTEUiLCJUQk9EWSIsIlREIiwiVEVYVEFSRUEiLCJURk9PVCIsIlRIIiwiVEhFQUQi
-LCJUSU1FIiwiVFIiLCJUUkFDSyIsIlRUIiwiVSIsIlVMIiwiVkFSIiwiVklERU8iLCJXQlIiXSx0Lk4p
-fSkKcygkLCJYNCIsImhHIixmdW5jdGlvbigpe3JldHVybiBQLm51KCJeXFxTKyQiKX0pCnMoJCwid08i
-LCJvdyIsZnVuY3Rpb24oKXtyZXR1cm4gUC5ORChzZWxmKX0pCnMoJCwia3QiLCJSOCIsZnVuY3Rpb24o
-KXtyZXR1cm4gSC5ZZygiXyRkYXJ0X2RhcnRPYmplY3QiKX0pCnMoJCwiZksiLCJrSSIsZnVuY3Rpb24o
-KXtyZXR1cm4gZnVuY3Rpb24gRGFydE9iamVjdChhKXt0aGlzLm89YX19KQpyKCQsInF0IiwiekIiLGZ1
-bmN0aW9uKCl7cmV0dXJuIG5ldyBULm1RKCl9KQpyKCQsIk9sIiwiVUUiLGZ1bmN0aW9uKCl7cmV0dXJu
-IFAuaEsoQy5vbC5nbVcoVy54MygpKS5ocmVmKS5naFkoKS5xKDAsImF1dGhUb2tlbiIpfSkKcigkLCJo
-VCIsInlQIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiLmVkaXQtbGlzdCAu
-cGFuZWwtY29udGVudCIpfSkKcigkLCJXNiIsImhMIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVl
-cnlTZWxlY3RvcigiLmVkaXQtcGFuZWwgLnBhbmVsLWNvbnRlbnQiKX0pCnIoJCwiVFIiLCJEVyIsZnVu
-Y3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoImZvb3RlciIpfSkKcigkLCJFWSIsImZp
-IixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiaGVhZGVyIil9KQpyKCQsImF2
-IiwiRDkiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIjdW5pdC1uYW1lIil9
-KQpyKCQsInQwIiwiYk4iLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIjbWln
-cmF0ZS11bml0LXN0YXR1cy1pY29uLWxhYmVsIil9KQpyKCQsImJBIiwiYzAiLGZ1bmN0aW9uKCl7cmV0
-dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIjbWlncmF0ZS11bml0LXN0YXR1cy1pY29uIil9KQpyKCQs
-ImZlIiwiS0ciLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLlhBKCl9KQpzKCQsImVvIiwiblUiLGZ1bmN0
-aW9uKCl7cmV0dXJuIG5ldyBNLmxJKCQuSGsoKSl9KQpzKCQsInlyIiwiYkQiLGZ1bmN0aW9uKCl7cmV0
-dXJuIG5ldyBFLk9GKFAubnUoIi8iKSxQLm51KCJbXi9dJCIpLFAubnUoIl4vIikpfSkKcygkLCJNayIs
-IktrIixmdW5jdGlvbigpe3JldHVybiBuZXcgTC5JVihQLm51KCJbL1xcXFxdIiksUC5udSgiW14vXFxc
-XF0kIiksUC5udSgiXihcXFxcXFxcXFteXFxcXF0rXFxcXFteXFxcXC9dK3xbYS16QS1aXTpbL1xcXFxd
-KSIpLFAubnUoIl5bL1xcXFxdKD8hWy9cXFxcXSkiKSl9KQpzKCQsImFrIiwiRWIiLGZ1bmN0aW9uKCl7
-cmV0dXJuIG5ldyBGLnJ1KFAubnUoIi8iKSxQLm51KCIoXlthLXpBLVpdWy0rLmEtekEtWlxcZF0qOi8v
-fFteL10pJCIpLFAubnUoIlthLXpBLVpdWy0rLmEtekEtWlxcZF0qOi8vW14vXSoiKSxQLm51KCJeLyIp
-KX0pCnMoJCwibHMiLCJIayIsZnVuY3Rpb24oKXtyZXR1cm4gTy5SaCgpfSl9KSgpOyhmdW5jdGlvbiBu
-YXRpdmVTdXBwb3J0KCl7IWZ1bmN0aW9uKCl7dmFyIHM9ZnVuY3Rpb24oYSl7dmFyIG09e30KbVthXT0x
-CnJldHVybiBPYmplY3Qua2V5cyhodW5rSGVscGVycy5jb252ZXJ0VG9GYXN0T2JqZWN0KG0pKVswXX0K
-di5nZXRJc29sYXRlVGFnPWZ1bmN0aW9uKGEpe3JldHVybiBzKCJfX19kYXJ0XyIrYSt2Lmlzb2xhdGVU
-YWcpfQp2YXIgcj0iX19fZGFydF9pc29sYXRlX3RhZ3NfIgp2YXIgcT1PYmplY3Rbcl18fChPYmplY3Rb
-cl09T2JqZWN0LmNyZWF0ZShudWxsKSkKdmFyIHA9Il9aeFl4WCIKZm9yKHZhciBvPTA7O28rKyl7dmFy
-IG49cyhwKyJfIitvKyJfIikKaWYoIShuIGluIHEpKXtxW25dPTEKdi5pc29sYXRlVGFnPW4KYnJlYWt9
-fXYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWU9di5nZXRJc29sYXRlVGFnKCJkaXNwYXRjaF9yZWNvcmQiKX0o
-KQpodW5rSGVscGVycy5zZXRPclVwZGF0ZUludGVyY2VwdG9yc0J5VGFnKHtET01FcnJvcjpKLkd2LE1l
-ZGlhRXJyb3I6Si5HdixOYXZpZ2F0b3I6Si5HdixOYXZpZ2F0b3JDb25jdXJyZW50SGFyZHdhcmU6Si5H
-dixOYXZpZ2F0b3JVc2VyTWVkaWFFcnJvcjpKLkd2LE92ZXJjb25zdHJhaW5lZEVycm9yOkouR3YsUG9z
-aXRpb25FcnJvcjpKLkd2LFJhbmdlOkouR3YsU1FMRXJyb3I6Si5HdixEYXRhVmlldzpILkVULEFycmF5
-QnVmZmVyVmlldzpILkVULEZsb2F0MzJBcnJheTpILkRnLEZsb2F0NjRBcnJheTpILkRnLEludDE2QXJy
-YXk6SC54aixJbnQzMkFycmF5OkguZEUsSW50OEFycmF5OkguWkEsVWludDE2QXJyYXk6SC5kVCxVaW50
-MzJBcnJheTpILlBxLFVpbnQ4Q2xhbXBlZEFycmF5OkguZUUsQ2FudmFzUGl4ZWxBcnJheTpILmVFLFVp
-bnQ4QXJyYXk6SC5WNixIVE1MQXVkaW9FbGVtZW50OlcucUUsSFRNTEJSRWxlbWVudDpXLnFFLEhUTUxC
-dXR0b25FbGVtZW50OlcucUUsSFRNTENhbnZhc0VsZW1lbnQ6Vy5xRSxIVE1MQ29udGVudEVsZW1lbnQ6
-Vy5xRSxIVE1MRExpc3RFbGVtZW50OlcucUUsSFRNTERhdGFFbGVtZW50OlcucUUsSFRNTERhdGFMaXN0
-RWxlbWVudDpXLnFFLEhUTUxEZXRhaWxzRWxlbWVudDpXLnFFLEhUTUxEaWFsb2dFbGVtZW50OlcucUUs
-SFRNTERpdkVsZW1lbnQ6Vy5xRSxIVE1MRW1iZWRFbGVtZW50OlcucUUsSFRNTEZpZWxkU2V0RWxlbWVu
-dDpXLnFFLEhUTUxIUkVsZW1lbnQ6Vy5xRSxIVE1MSGVhZEVsZW1lbnQ6Vy5xRSxIVE1MSGVhZGluZ0Vs
-ZW1lbnQ6Vy5xRSxIVE1MSHRtbEVsZW1lbnQ6Vy5xRSxIVE1MSUZyYW1lRWxlbWVudDpXLnFFLEhUTUxJ
-bWFnZUVsZW1lbnQ6Vy5xRSxIVE1MSW5wdXRFbGVtZW50OlcucUUsSFRNTExJRWxlbWVudDpXLnFFLEhU
-TUxMYWJlbEVsZW1lbnQ6Vy5xRSxIVE1MTGVnZW5kRWxlbWVudDpXLnFFLEhUTUxMaW5rRWxlbWVudDpX
-LnFFLEhUTUxNYXBFbGVtZW50OlcucUUsSFRNTE1lZGlhRWxlbWVudDpXLnFFLEhUTUxNZW51RWxlbWVu
-dDpXLnFFLEhUTUxNZXRhRWxlbWVudDpXLnFFLEhUTUxNZXRlckVsZW1lbnQ6Vy5xRSxIVE1MTW9kRWxl
-bWVudDpXLnFFLEhUTUxPTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MT2JqZWN0RWxlbWVudDpXLnFFLEhUTUxP
-cHRHcm91cEVsZW1lbnQ6Vy5xRSxIVE1MT3B0aW9uRWxlbWVudDpXLnFFLEhUTUxPdXRwdXRFbGVtZW50
-OlcucUUsSFRNTFBhcmFtRWxlbWVudDpXLnFFLEhUTUxQaWN0dXJlRWxlbWVudDpXLnFFLEhUTUxQcmVF
-bGVtZW50OlcucUUsSFRNTFByb2dyZXNzRWxlbWVudDpXLnFFLEhUTUxRdW90ZUVsZW1lbnQ6Vy5xRSxI
-VE1MU2NyaXB0RWxlbWVudDpXLnFFLEhUTUxTaGFkb3dFbGVtZW50OlcucUUsSFRNTFNsb3RFbGVtZW50
-OlcucUUsSFRNTFNvdXJjZUVsZW1lbnQ6Vy5xRSxIVE1MU3BhbkVsZW1lbnQ6Vy5xRSxIVE1MU3R5bGVF
-bGVtZW50OlcucUUsSFRNTFRhYmxlQ2FwdGlvbkVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDZWxsRWxlbWVu
-dDpXLnFFLEhUTUxUYWJsZURhdGFDZWxsRWxlbWVudDpXLnFFLEhUTUxUYWJsZUhlYWRlckNlbGxFbGVt
-ZW50OlcucUUsSFRNTFRhYmxlQ29sRWxlbWVudDpXLnFFLEhUTUxUZXh0QXJlYUVsZW1lbnQ6Vy5xRSxI
-VE1MVGltZUVsZW1lbnQ6Vy5xRSxIVE1MVGl0bGVFbGVtZW50OlcucUUsSFRNTFRyYWNrRWxlbWVudDpX
-LnFFLEhUTUxVTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MVW5rbm93bkVsZW1lbnQ6Vy5xRSxIVE1MVmlkZW9F
-bGVtZW50OlcucUUsSFRNTERpcmVjdG9yeUVsZW1lbnQ6Vy5xRSxIVE1MRm9udEVsZW1lbnQ6Vy5xRSxI
-VE1MRnJhbWVFbGVtZW50OlcucUUsSFRNTEZyYW1lU2V0RWxlbWVudDpXLnFFLEhUTUxNYXJxdWVlRWxl
-bWVudDpXLnFFLEhUTUxFbGVtZW50OlcucUUsSFRNTEFuY2hvckVsZW1lbnQ6Vy5HaCxIVE1MQXJlYUVs
-ZW1lbnQ6Vy5mWSxIVE1MQmFzZUVsZW1lbnQ6Vy5uQixCbG9iOlcuQXosSFRNTEJvZHlFbGVtZW50Olcu
-UVAsQ0RBVEFTZWN0aW9uOlcubngsQ2hhcmFjdGVyRGF0YTpXLm54LENvbW1lbnQ6Vy5ueCxQcm9jZXNz
-aW5nSW5zdHJ1Y3Rpb246Vy5ueCxUZXh0OlcubngsQ1NTU3R5bGVEZWNsYXJhdGlvbjpXLm9KLE1TU3R5
-bGVDU1NQcm9wZXJ0aWVzOlcub0osQ1NTMlByb3BlcnRpZXM6Vy5vSixYTUxEb2N1bWVudDpXLlFGLERv
-Y3VtZW50OlcuUUYsRE9NRXhjZXB0aW9uOlcuTmgsRE9NSW1wbGVtZW50YXRpb246Vy5hZSxET01SZWN0
-UmVhZE9ubHk6Vy5JQixET01Ub2tlbkxpc3Q6Vy5uNyxFbGVtZW50OlcuY3YsQWJvcnRQYXltZW50RXZl
-bnQ6Vy5lYSxBbmltYXRpb25FdmVudDpXLmVhLEFuaW1hdGlvblBsYXliYWNrRXZlbnQ6Vy5lYSxBcHBs
-aWNhdGlvbkNhY2hlRXJyb3JFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaENsaWNrRXZlbnQ6Vy5lYSxC
-YWNrZ3JvdW5kRmV0Y2hFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaEZhaWxFdmVudDpXLmVhLEJhY2tn
-cm91bmRGZXRjaGVkRXZlbnQ6Vy5lYSxCZWZvcmVJbnN0YWxsUHJvbXB0RXZlbnQ6Vy5lYSxCZWZvcmVV
-bmxvYWRFdmVudDpXLmVhLEJsb2JFdmVudDpXLmVhLENhbk1ha2VQYXltZW50RXZlbnQ6Vy5lYSxDbGlw
-Ym9hcmRFdmVudDpXLmVhLENsb3NlRXZlbnQ6Vy5lYSxDdXN0b21FdmVudDpXLmVhLERldmljZU1vdGlv
-bkV2ZW50OlcuZWEsRGV2aWNlT3JpZW50YXRpb25FdmVudDpXLmVhLEVycm9yRXZlbnQ6Vy5lYSxFeHRl
-bmRhYmxlRXZlbnQ6Vy5lYSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50OlcuZWEsRmV0Y2hFdmVudDpXLmVh
-LEZvbnRGYWNlU2V0TG9hZEV2ZW50OlcuZWEsRm9yZWlnbkZldGNoRXZlbnQ6Vy5lYSxHYW1lcGFkRXZl
-bnQ6Vy5lYSxIYXNoQ2hhbmdlRXZlbnQ6Vy5lYSxJbnN0YWxsRXZlbnQ6Vy5lYSxNZWRpYUVuY3J5cHRl
-ZEV2ZW50OlcuZWEsTWVkaWFLZXlNZXNzYWdlRXZlbnQ6Vy5lYSxNZWRpYVF1ZXJ5TGlzdEV2ZW50Olcu
-ZWEsTWVkaWFTdHJlYW1FdmVudDpXLmVhLE1lZGlhU3RyZWFtVHJhY2tFdmVudDpXLmVhLE1lc3NhZ2VF
-dmVudDpXLmVhLE1JRElDb25uZWN0aW9uRXZlbnQ6Vy5lYSxNSURJTWVzc2FnZUV2ZW50OlcuZWEsTXV0
-YXRpb25FdmVudDpXLmVhLE5vdGlmaWNhdGlvbkV2ZW50OlcuZWEsUGFnZVRyYW5zaXRpb25FdmVudDpX
-LmVhLFBheW1lbnRSZXF1ZXN0RXZlbnQ6Vy5lYSxQYXltZW50UmVxdWVzdFVwZGF0ZUV2ZW50OlcuZWEs
-UG9wU3RhdGVFdmVudDpXLmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25BdmFpbGFibGVFdmVudDpXLmVh
-LFByZXNlbnRhdGlvbkNvbm5lY3Rpb25DbG9zZUV2ZW50OlcuZWEsUHJvbWlzZVJlamVjdGlvbkV2ZW50
-OlcuZWEsUHVzaEV2ZW50OlcuZWEsUlRDRGF0YUNoYW5uZWxFdmVudDpXLmVhLFJUQ0RUTUZUb25lQ2hh
-bmdlRXZlbnQ6Vy5lYSxSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50OlcuZWEsUlRDVHJhY2tFdmVudDpX
-LmVhLFNlY3VyaXR5UG9saWN5VmlvbGF0aW9uRXZlbnQ6Vy5lYSxTZW5zb3JFcnJvckV2ZW50OlcuZWEs
-U3BlZWNoUmVjb2duaXRpb25FcnJvcjpXLmVhLFNwZWVjaFJlY29nbml0aW9uRXZlbnQ6Vy5lYSxTcGVl
-Y2hTeW50aGVzaXNFdmVudDpXLmVhLFN0b3JhZ2VFdmVudDpXLmVhLFN5bmNFdmVudDpXLmVhLFRyYWNr
-RXZlbnQ6Vy5lYSxUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxXZWJLaXRUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxW
-UkRldmljZUV2ZW50OlcuZWEsVlJEaXNwbGF5RXZlbnQ6Vy5lYSxWUlNlc3Npb25FdmVudDpXLmVhLE1v
-am9JbnRlcmZhY2VSZXF1ZXN0RXZlbnQ6Vy5lYSxVU0JDb25uZWN0aW9uRXZlbnQ6Vy5lYSxJREJWZXJz
-aW9uQ2hhbmdlRXZlbnQ6Vy5lYSxBdWRpb1Byb2Nlc3NpbmdFdmVudDpXLmVhLE9mZmxpbmVBdWRpb0Nv
-bXBsZXRpb25FdmVudDpXLmVhLFdlYkdMQ29udGV4dEV2ZW50OlcuZWEsRXZlbnQ6Vy5lYSxJbnB1dEV2
-ZW50OlcuZWEsU3VibWl0RXZlbnQ6Vy5lYSxFdmVudFRhcmdldDpXLkQwLEZpbGU6Vy5oSCxIVE1MRm9y
-bUVsZW1lbnQ6Vy5oNCxIaXN0b3J5OlcuYnIsSFRNTERvY3VtZW50OlcuVmIsWE1MSHR0cFJlcXVlc3Q6
-Vy5mSixYTUxIdHRwUmVxdWVzdEV2ZW50VGFyZ2V0Olcud2EsSW1hZ2VEYXRhOlcuU2csTG9jYXRpb246
-Vy53NyxNb3VzZUV2ZW50OlcuQWosRHJhZ0V2ZW50OlcuQWosUG9pbnRlckV2ZW50OlcuQWosV2hlZWxF
-dmVudDpXLkFqLERvY3VtZW50RnJhZ21lbnQ6Vy51SCxTaGFkb3dSb290OlcudUgsRG9jdW1lbnRUeXBl
-OlcudUgsTm9kZTpXLnVILE5vZGVMaXN0OlcuQkgsUmFkaW9Ob2RlTGlzdDpXLkJILEhUTUxQYXJhZ3Jh
-cGhFbGVtZW50OlcuU04sUHJvZ3Jlc3NFdmVudDpXLmV3LFJlc291cmNlUHJvZ3Jlc3NFdmVudDpXLmV3
-LEhUTUxTZWxlY3RFbGVtZW50OlcubHAsSFRNTFRhYmxlRWxlbWVudDpXLlRiLEhUTUxUYWJsZVJvd0Vs
-ZW1lbnQ6Vy5JdixIVE1MVGFibGVTZWN0aW9uRWxlbWVudDpXLldQLEhUTUxUZW1wbGF0ZUVsZW1lbnQ6
-Vy55WSxDb21wb3NpdGlvbkV2ZW50OlcudzYsRm9jdXNFdmVudDpXLnc2LEtleWJvYXJkRXZlbnQ6Vy53
-NixUZXh0RXZlbnQ6Vy53NixUb3VjaEV2ZW50OlcudzYsVUlFdmVudDpXLnc2LFdpbmRvdzpXLks1LERP
-TVdpbmRvdzpXLks1LERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOlcuQ20sU2VydmljZVdvcmtlckds
-b2JhbFNjb3BlOlcuQ20sU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxXb3JrZXJHbG9iYWxTY29w
-ZTpXLkNtLEF0dHI6Vy5DUSxDbGllbnRSZWN0OlcudzQsRE9NUmVjdDpXLnc0LE5hbWVkTm9kZU1hcDpX
-LnJoLE1vek5hbWVkQXR0ck1hcDpXLnJoLElEQktleVJhbmdlOlAuaEYsU1ZHU2NyaXB0RWxlbWVudDpQ
-Lm5kLFNWR0FFbGVtZW50OlAuaGksU1ZHQW5pbWF0ZUVsZW1lbnQ6UC5oaSxTVkdBbmltYXRlTW90aW9u
-RWxlbWVudDpQLmhpLFNWR0FuaW1hdGVUcmFuc2Zvcm1FbGVtZW50OlAuaGksU1ZHQW5pbWF0aW9uRWxl
-bWVudDpQLmhpLFNWR0NpcmNsZUVsZW1lbnQ6UC5oaSxTVkdDbGlwUGF0aEVsZW1lbnQ6UC5oaSxTVkdE
-ZWZzRWxlbWVudDpQLmhpLFNWR0Rlc2NFbGVtZW50OlAuaGksU1ZHRGlzY2FyZEVsZW1lbnQ6UC5oaSxT
-VkdFbGxpcHNlRWxlbWVudDpQLmhpLFNWR0ZFQmxlbmRFbGVtZW50OlAuaGksU1ZHRkVDb2xvck1hdHJp
-eEVsZW1lbnQ6UC5oaSxTVkdGRUNvbXBvbmVudFRyYW5zZmVyRWxlbWVudDpQLmhpLFNWR0ZFQ29tcG9z
-aXRlRWxlbWVudDpQLmhpLFNWR0ZFQ29udm9sdmVNYXRyaXhFbGVtZW50OlAuaGksU1ZHRkVEaWZmdXNl
-TGlnaHRpbmdFbGVtZW50OlAuaGksU1ZHRkVEaXNwbGFjZW1lbnRNYXBFbGVtZW50OlAuaGksU1ZHRkVE
-aXN0YW50TGlnaHRFbGVtZW50OlAuaGksU1ZHRkVGbG9vZEVsZW1lbnQ6UC5oaSxTVkdGRUZ1bmNBRWxl
-bWVudDpQLmhpLFNWR0ZFRnVuY0JFbGVtZW50OlAuaGksU1ZHRkVGdW5jR0VsZW1lbnQ6UC5oaSxTVkdG
-RUZ1bmNSRWxlbWVudDpQLmhpLFNWR0ZFR2F1c3NpYW5CbHVyRWxlbWVudDpQLmhpLFNWR0ZFSW1hZ2VF
-bGVtZW50OlAuaGksU1ZHRkVNZXJnZUVsZW1lbnQ6UC5oaSxTVkdGRU1lcmdlTm9kZUVsZW1lbnQ6UC5o
-aSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OlAuaGksU1ZHRkVPZmZzZXRFbGVtZW50OlAuaGksU1ZHRkVQ
-b2ludExpZ2h0RWxlbWVudDpQLmhpLFNWR0ZFU3BlY3VsYXJMaWdodGluZ0VsZW1lbnQ6UC5oaSxTVkdG
-RVNwb3RMaWdodEVsZW1lbnQ6UC5oaSxTVkdGRVRpbGVFbGVtZW50OlAuaGksU1ZHRkVUdXJidWxlbmNl
-RWxlbWVudDpQLmhpLFNWR0ZpbHRlckVsZW1lbnQ6UC5oaSxTVkdGb3JlaWduT2JqZWN0RWxlbWVudDpQ
-LmhpLFNWR0dFbGVtZW50OlAuaGksU1ZHR2VvbWV0cnlFbGVtZW50OlAuaGksU1ZHR3JhcGhpY3NFbGVt
-ZW50OlAuaGksU1ZHSW1hZ2VFbGVtZW50OlAuaGksU1ZHTGluZUVsZW1lbnQ6UC5oaSxTVkdMaW5lYXJH
-cmFkaWVudEVsZW1lbnQ6UC5oaSxTVkdNYXJrZXJFbGVtZW50OlAuaGksU1ZHTWFza0VsZW1lbnQ6UC5o
-aSxTVkdNZXRhZGF0YUVsZW1lbnQ6UC5oaSxTVkdQYXRoRWxlbWVudDpQLmhpLFNWR1BhdHRlcm5FbGVt
-ZW50OlAuaGksU1ZHUG9seWdvbkVsZW1lbnQ6UC5oaSxTVkdQb2x5bGluZUVsZW1lbnQ6UC5oaSxTVkdS
-YWRpYWxHcmFkaWVudEVsZW1lbnQ6UC5oaSxTVkdSZWN0RWxlbWVudDpQLmhpLFNWR1NldEVsZW1lbnQ6
-UC5oaSxTVkdTdG9wRWxlbWVudDpQLmhpLFNWR1N0eWxlRWxlbWVudDpQLmhpLFNWR1NWR0VsZW1lbnQ6
-UC5oaSxTVkdTd2l0Y2hFbGVtZW50OlAuaGksU1ZHU3ltYm9sRWxlbWVudDpQLmhpLFNWR1RTcGFuRWxl
-bWVudDpQLmhpLFNWR1RleHRDb250ZW50RWxlbWVudDpQLmhpLFNWR1RleHRFbGVtZW50OlAuaGksU1ZH
-VGV4dFBhdGhFbGVtZW50OlAuaGksU1ZHVGV4dFBvc2l0aW9uaW5nRWxlbWVudDpQLmhpLFNWR1RpdGxl
-RWxlbWVudDpQLmhpLFNWR1VzZUVsZW1lbnQ6UC5oaSxTVkdWaWV3RWxlbWVudDpQLmhpLFNWR0dyYWRp
-ZW50RWxlbWVudDpQLmhpLFNWR0NvbXBvbmVudFRyYW5zZmVyRnVuY3Rpb25FbGVtZW50OlAuaGksU1ZH
-RkVEcm9wU2hhZG93RWxlbWVudDpQLmhpLFNWR01QYXRoRWxlbWVudDpQLmhpLFNWR0VsZW1lbnQ6UC5o
-aX0pCmh1bmtIZWxwZXJzLnNldE9yVXBkYXRlTGVhZlRhZ3Moe0RPTUVycm9yOnRydWUsTWVkaWFFcnJv
-cjp0cnVlLE5hdmlnYXRvcjp0cnVlLE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2FyZTp0cnVlLE5hdmln
-YXRvclVzZXJNZWRpYUVycm9yOnRydWUsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6dHJ1ZSxQb3NpdGlvbkVy
-cm9yOnRydWUsUmFuZ2U6dHJ1ZSxTUUxFcnJvcjp0cnVlLERhdGFWaWV3OnRydWUsQXJyYXlCdWZmZXJW
-aWV3OmZhbHNlLEZsb2F0MzJBcnJheTp0cnVlLEZsb2F0NjRBcnJheTp0cnVlLEludDE2QXJyYXk6dHJ1
-ZSxJbnQzMkFycmF5OnRydWUsSW50OEFycmF5OnRydWUsVWludDE2QXJyYXk6dHJ1ZSxVaW50MzJBcnJh
-eTp0cnVlLFVpbnQ4Q2xhbXBlZEFycmF5OnRydWUsQ2FudmFzUGl4ZWxBcnJheTp0cnVlLFVpbnQ4QXJy
-YXk6ZmFsc2UsSFRNTEF1ZGlvRWxlbWVudDp0cnVlLEhUTUxCUkVsZW1lbnQ6dHJ1ZSxIVE1MQnV0dG9u
-RWxlbWVudDp0cnVlLEhUTUxDYW52YXNFbGVtZW50OnRydWUsSFRNTENvbnRlbnRFbGVtZW50OnRydWUs
-SFRNTERMaXN0RWxlbWVudDp0cnVlLEhUTUxEYXRhRWxlbWVudDp0cnVlLEhUTUxEYXRhTGlzdEVsZW1l
-bnQ6dHJ1ZSxIVE1MRGV0YWlsc0VsZW1lbnQ6dHJ1ZSxIVE1MRGlhbG9nRWxlbWVudDp0cnVlLEhUTUxE
-aXZFbGVtZW50OnRydWUsSFRNTEVtYmVkRWxlbWVudDp0cnVlLEhUTUxGaWVsZFNldEVsZW1lbnQ6dHJ1
-ZSxIVE1MSFJFbGVtZW50OnRydWUsSFRNTEhlYWRFbGVtZW50OnRydWUsSFRNTEhlYWRpbmdFbGVtZW50
-OnRydWUsSFRNTEh0bWxFbGVtZW50OnRydWUsSFRNTElGcmFtZUVsZW1lbnQ6dHJ1ZSxIVE1MSW1hZ2VF
-bGVtZW50OnRydWUsSFRNTElucHV0RWxlbWVudDp0cnVlLEhUTUxMSUVsZW1lbnQ6dHJ1ZSxIVE1MTGFi
-ZWxFbGVtZW50OnRydWUsSFRNTExlZ2VuZEVsZW1lbnQ6dHJ1ZSxIVE1MTGlua0VsZW1lbnQ6dHJ1ZSxI
-VE1MTWFwRWxlbWVudDp0cnVlLEhUTUxNZWRpYUVsZW1lbnQ6dHJ1ZSxIVE1MTWVudUVsZW1lbnQ6dHJ1
-ZSxIVE1MTWV0YUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0ZXJFbGVtZW50OnRydWUsSFRNTE1vZEVsZW1lbnQ6
-dHJ1ZSxIVE1MT0xpc3RFbGVtZW50OnRydWUsSFRNTE9iamVjdEVsZW1lbnQ6dHJ1ZSxIVE1MT3B0R3Jv
-dXBFbGVtZW50OnRydWUsSFRNTE9wdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MT3V0cHV0RWxlbWVudDp0cnVl
-LEhUTUxQYXJhbUVsZW1lbnQ6dHJ1ZSxIVE1MUGljdHVyZUVsZW1lbnQ6dHJ1ZSxIVE1MUHJlRWxlbWVu
-dDp0cnVlLEhUTUxQcm9ncmVzc0VsZW1lbnQ6dHJ1ZSxIVE1MUXVvdGVFbGVtZW50OnRydWUsSFRNTFNj
-cmlwdEVsZW1lbnQ6dHJ1ZSxIVE1MU2hhZG93RWxlbWVudDp0cnVlLEhUTUxTbG90RWxlbWVudDp0cnVl
-LEhUTUxTb3VyY2VFbGVtZW50OnRydWUsSFRNTFNwYW5FbGVtZW50OnRydWUsSFRNTFN0eWxlRWxlbWVu
-dDp0cnVlLEhUTUxUYWJsZUNhcHRpb25FbGVtZW50OnRydWUsSFRNTFRhYmxlQ2VsbEVsZW1lbnQ6dHJ1
-ZSxIVE1MVGFibGVEYXRhQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVIZWFkZXJDZWxsRWxlbWVudDp0
-cnVlLEhUTUxUYWJsZUNvbEVsZW1lbnQ6dHJ1ZSxIVE1MVGV4dEFyZWFFbGVtZW50OnRydWUsSFRNTFRp
-bWVFbGVtZW50OnRydWUsSFRNTFRpdGxlRWxlbWVudDp0cnVlLEhUTUxUcmFja0VsZW1lbnQ6dHJ1ZSxI
-VE1MVUxpc3RFbGVtZW50OnRydWUsSFRNTFVua25vd25FbGVtZW50OnRydWUsSFRNTFZpZGVvRWxlbWVu
-dDp0cnVlLEhUTUxEaXJlY3RvcnlFbGVtZW50OnRydWUsSFRNTEZvbnRFbGVtZW50OnRydWUsSFRNTEZy
-YW1lRWxlbWVudDp0cnVlLEhUTUxGcmFtZVNldEVsZW1lbnQ6dHJ1ZSxIVE1MTWFycXVlZUVsZW1lbnQ6
-dHJ1ZSxIVE1MRWxlbWVudDpmYWxzZSxIVE1MQW5jaG9yRWxlbWVudDp0cnVlLEhUTUxBcmVhRWxlbWVu
-dDp0cnVlLEhUTUxCYXNlRWxlbWVudDp0cnVlLEJsb2I6ZmFsc2UsSFRNTEJvZHlFbGVtZW50OnRydWUs
-Q0RBVEFTZWN0aW9uOnRydWUsQ2hhcmFjdGVyRGF0YTp0cnVlLENvbW1lbnQ6dHJ1ZSxQcm9jZXNzaW5n
-SW5zdHJ1Y3Rpb246dHJ1ZSxUZXh0OnRydWUsQ1NTU3R5bGVEZWNsYXJhdGlvbjp0cnVlLE1TU3R5bGVD
-U1NQcm9wZXJ0aWVzOnRydWUsQ1NTMlByb3BlcnRpZXM6dHJ1ZSxYTUxEb2N1bWVudDp0cnVlLERvY3Vt
-ZW50OmZhbHNlLERPTUV4Y2VwdGlvbjp0cnVlLERPTUltcGxlbWVudGF0aW9uOnRydWUsRE9NUmVjdFJl
-YWRPbmx5OmZhbHNlLERPTVRva2VuTGlzdDp0cnVlLEVsZW1lbnQ6ZmFsc2UsQWJvcnRQYXltZW50RXZl
-bnQ6dHJ1ZSxBbmltYXRpb25FdmVudDp0cnVlLEFuaW1hdGlvblBsYXliYWNrRXZlbnQ6dHJ1ZSxBcHBs
-aWNhdGlvbkNhY2hlRXJyb3JFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaENsaWNrRXZlbnQ6dHJ1ZSxC
-YWNrZ3JvdW5kRmV0Y2hFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaEZhaWxFdmVudDp0cnVlLEJhY2tn
-cm91bmRGZXRjaGVkRXZlbnQ6dHJ1ZSxCZWZvcmVJbnN0YWxsUHJvbXB0RXZlbnQ6dHJ1ZSxCZWZvcmVV
-bmxvYWRFdmVudDp0cnVlLEJsb2JFdmVudDp0cnVlLENhbk1ha2VQYXltZW50RXZlbnQ6dHJ1ZSxDbGlw
-Ym9hcmRFdmVudDp0cnVlLENsb3NlRXZlbnQ6dHJ1ZSxDdXN0b21FdmVudDp0cnVlLERldmljZU1vdGlv
-bkV2ZW50OnRydWUsRGV2aWNlT3JpZW50YXRpb25FdmVudDp0cnVlLEVycm9yRXZlbnQ6dHJ1ZSxFeHRl
-bmRhYmxlRXZlbnQ6dHJ1ZSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50OnRydWUsRmV0Y2hFdmVudDp0cnVl
-LEZvbnRGYWNlU2V0TG9hZEV2ZW50OnRydWUsRm9yZWlnbkZldGNoRXZlbnQ6dHJ1ZSxHYW1lcGFkRXZl
-bnQ6dHJ1ZSxIYXNoQ2hhbmdlRXZlbnQ6dHJ1ZSxJbnN0YWxsRXZlbnQ6dHJ1ZSxNZWRpYUVuY3J5cHRl
-ZEV2ZW50OnRydWUsTWVkaWFLZXlNZXNzYWdlRXZlbnQ6dHJ1ZSxNZWRpYVF1ZXJ5TGlzdEV2ZW50OnRy
-dWUsTWVkaWFTdHJlYW1FdmVudDp0cnVlLE1lZGlhU3RyZWFtVHJhY2tFdmVudDp0cnVlLE1lc3NhZ2VF
-dmVudDp0cnVlLE1JRElDb25uZWN0aW9uRXZlbnQ6dHJ1ZSxNSURJTWVzc2FnZUV2ZW50OnRydWUsTXV0
-YXRpb25FdmVudDp0cnVlLE5vdGlmaWNhdGlvbkV2ZW50OnRydWUsUGFnZVRyYW5zaXRpb25FdmVudDp0
-cnVlLFBheW1lbnRSZXF1ZXN0RXZlbnQ6dHJ1ZSxQYXltZW50UmVxdWVzdFVwZGF0ZUV2ZW50OnRydWUs
-UG9wU3RhdGVFdmVudDp0cnVlLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25BdmFpbGFibGVFdmVudDp0cnVl
-LFByZXNlbnRhdGlvbkNvbm5lY3Rpb25DbG9zZUV2ZW50OnRydWUsUHJvbWlzZVJlamVjdGlvbkV2ZW50
-OnRydWUsUHVzaEV2ZW50OnRydWUsUlRDRGF0YUNoYW5uZWxFdmVudDp0cnVlLFJUQ0RUTUZUb25lQ2hh
-bmdlRXZlbnQ6dHJ1ZSxSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50OnRydWUsUlRDVHJhY2tFdmVudDp0
-cnVlLFNlY3VyaXR5UG9saWN5VmlvbGF0aW9uRXZlbnQ6dHJ1ZSxTZW5zb3JFcnJvckV2ZW50OnRydWUs
-U3BlZWNoUmVjb2duaXRpb25FcnJvcjp0cnVlLFNwZWVjaFJlY29nbml0aW9uRXZlbnQ6dHJ1ZSxTcGVl
-Y2hTeW50aGVzaXNFdmVudDp0cnVlLFN0b3JhZ2VFdmVudDp0cnVlLFN5bmNFdmVudDp0cnVlLFRyYWNr
-RXZlbnQ6dHJ1ZSxUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxXZWJLaXRUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxW
-UkRldmljZUV2ZW50OnRydWUsVlJEaXNwbGF5RXZlbnQ6dHJ1ZSxWUlNlc3Npb25FdmVudDp0cnVlLE1v
-am9JbnRlcmZhY2VSZXF1ZXN0RXZlbnQ6dHJ1ZSxVU0JDb25uZWN0aW9uRXZlbnQ6dHJ1ZSxJREJWZXJz
-aW9uQ2hhbmdlRXZlbnQ6dHJ1ZSxBdWRpb1Byb2Nlc3NpbmdFdmVudDp0cnVlLE9mZmxpbmVBdWRpb0Nv
-bXBsZXRpb25FdmVudDp0cnVlLFdlYkdMQ29udGV4dEV2ZW50OnRydWUsRXZlbnQ6ZmFsc2UsSW5wdXRF
-dmVudDpmYWxzZSxTdWJtaXRFdmVudDpmYWxzZSxFdmVudFRhcmdldDpmYWxzZSxGaWxlOnRydWUsSFRN
-TEZvcm1FbGVtZW50OnRydWUsSGlzdG9yeTp0cnVlLEhUTUxEb2N1bWVudDp0cnVlLFhNTEh0dHBSZXF1
-ZXN0OnRydWUsWE1MSHR0cFJlcXVlc3RFdmVudFRhcmdldDpmYWxzZSxJbWFnZURhdGE6dHJ1ZSxMb2Nh
-dGlvbjp0cnVlLE1vdXNlRXZlbnQ6dHJ1ZSxEcmFnRXZlbnQ6dHJ1ZSxQb2ludGVyRXZlbnQ6dHJ1ZSxX
-aGVlbEV2ZW50OnRydWUsRG9jdW1lbnRGcmFnbWVudDp0cnVlLFNoYWRvd1Jvb3Q6dHJ1ZSxEb2N1bWVu
-dFR5cGU6dHJ1ZSxOb2RlOmZhbHNlLE5vZGVMaXN0OnRydWUsUmFkaW9Ob2RlTGlzdDp0cnVlLEhUTUxQ
-YXJhZ3JhcGhFbGVtZW50OnRydWUsUHJvZ3Jlc3NFdmVudDp0cnVlLFJlc291cmNlUHJvZ3Jlc3NFdmVu
-dDp0cnVlLEhUTUxTZWxlY3RFbGVtZW50OnRydWUsSFRNTFRhYmxlRWxlbWVudDp0cnVlLEhUTUxUYWJs
-ZVJvd0VsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVTZWN0aW9uRWxlbWVudDp0cnVlLEhUTUxUZW1wbGF0ZUVs
-ZW1lbnQ6dHJ1ZSxDb21wb3NpdGlvbkV2ZW50OnRydWUsRm9jdXNFdmVudDp0cnVlLEtleWJvYXJkRXZl
-bnQ6dHJ1ZSxUZXh0RXZlbnQ6dHJ1ZSxUb3VjaEV2ZW50OnRydWUsVUlFdmVudDpmYWxzZSxXaW5kb3c6
-dHJ1ZSxET01XaW5kb3c6dHJ1ZSxEZWRpY2F0ZWRXb3JrZXJHbG9iYWxTY29wZTp0cnVlLFNlcnZpY2VX
-b3JrZXJHbG9iYWxTY29wZTp0cnVlLFNoYXJlZFdvcmtlckdsb2JhbFNjb3BlOnRydWUsV29ya2VyR2xv
-YmFsU2NvcGU6dHJ1ZSxBdHRyOnRydWUsQ2xpZW50UmVjdDp0cnVlLERPTVJlY3Q6dHJ1ZSxOYW1lZE5v
-ZGVNYXA6dHJ1ZSxNb3pOYW1lZEF0dHJNYXA6dHJ1ZSxJREJLZXlSYW5nZTp0cnVlLFNWR1NjcmlwdEVs
-ZW1lbnQ6dHJ1ZSxTVkdBRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVFbGVtZW50OnRydWUsU1ZHQW5pbWF0
-ZU1vdGlvbkVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlVHJhbnNmb3JtRWxlbWVudDp0cnVlLFNWR0FuaW1h
-dGlvbkVsZW1lbnQ6dHJ1ZSxTVkdDaXJjbGVFbGVtZW50OnRydWUsU1ZHQ2xpcFBhdGhFbGVtZW50OnRy
-dWUsU1ZHRGVmc0VsZW1lbnQ6dHJ1ZSxTVkdEZXNjRWxlbWVudDp0cnVlLFNWR0Rpc2NhcmRFbGVtZW50
-OnRydWUsU1ZHRWxsaXBzZUVsZW1lbnQ6dHJ1ZSxTVkdGRUJsZW5kRWxlbWVudDp0cnVlLFNWR0ZFQ29s
-b3JNYXRyaXhFbGVtZW50OnRydWUsU1ZHRkVDb21wb25lbnRUcmFuc2ZlckVsZW1lbnQ6dHJ1ZSxTVkdG
-RUNvbXBvc2l0ZUVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbnZvbHZlTWF0cml4RWxlbWVudDp0cnVlLFNWR0ZF
-RGlmZnVzZUxpZ2h0aW5nRWxlbWVudDp0cnVlLFNWR0ZFRGlzcGxhY2VtZW50TWFwRWxlbWVudDp0cnVl
-LFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFRmxvb2RFbGVtZW50OnRydWUsU1ZHRkVG
-dW5jQUVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNCRWxlbWVudDp0cnVlLFNWR0ZFRnVuY0dFbGVtZW50OnRy
-dWUsU1ZHRkVGdW5jUkVsZW1lbnQ6dHJ1ZSxTVkdGRUdhdXNzaWFuQmx1ckVsZW1lbnQ6dHJ1ZSxTVkdG
-RUltYWdlRWxlbWVudDp0cnVlLFNWR0ZFTWVyZ2VFbGVtZW50OnRydWUsU1ZHRkVNZXJnZU5vZGVFbGVt
-ZW50OnRydWUsU1ZHRkVNb3JwaG9sb2d5RWxlbWVudDp0cnVlLFNWR0ZFT2Zmc2V0RWxlbWVudDp0cnVl
-LFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRVNwZWN1bGFyTGlnaHRpbmdFbGVtZW50OnRy
-dWUsU1ZHRkVTcG90TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVUaWxlRWxlbWVudDp0cnVlLFNWR0ZFVHVy
-YnVsZW5jZUVsZW1lbnQ6dHJ1ZSxTVkdGaWx0ZXJFbGVtZW50OnRydWUsU1ZHRm9yZWlnbk9iamVjdEVs
-ZW1lbnQ6dHJ1ZSxTVkdHRWxlbWVudDp0cnVlLFNWR0dlb21ldHJ5RWxlbWVudDp0cnVlLFNWR0dyYXBo
-aWNzRWxlbWVudDp0cnVlLFNWR0ltYWdlRWxlbWVudDp0cnVlLFNWR0xpbmVFbGVtZW50OnRydWUsU1ZH
-TGluZWFyR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHTWFya2VyRWxlbWVudDp0cnVlLFNWR01hc2tFbGVt
-ZW50OnRydWUsU1ZHTWV0YWRhdGFFbGVtZW50OnRydWUsU1ZHUGF0aEVsZW1lbnQ6dHJ1ZSxTVkdQYXR0
-ZXJuRWxlbWVudDp0cnVlLFNWR1BvbHlnb25FbGVtZW50OnRydWUsU1ZHUG9seWxpbmVFbGVtZW50OnRy
-dWUsU1ZHUmFkaWFsR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHUmVjdEVsZW1lbnQ6dHJ1ZSxTVkdTZXRF
-bGVtZW50OnRydWUsU1ZHU3RvcEVsZW1lbnQ6dHJ1ZSxTVkdTdHlsZUVsZW1lbnQ6dHJ1ZSxTVkdTVkdF
-bGVtZW50OnRydWUsU1ZHU3dpdGNoRWxlbWVudDp0cnVlLFNWR1N5bWJvbEVsZW1lbnQ6dHJ1ZSxTVkdU
-U3BhbkVsZW1lbnQ6dHJ1ZSxTVkdUZXh0Q29udGVudEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0RWxlbWVudDp0
-cnVlLFNWR1RleHRQYXRoRWxlbWVudDp0cnVlLFNWR1RleHRQb3NpdGlvbmluZ0VsZW1lbnQ6dHJ1ZSxT
-VkdUaXRsZUVsZW1lbnQ6dHJ1ZSxTVkdVc2VFbGVtZW50OnRydWUsU1ZHVmlld0VsZW1lbnQ6dHJ1ZSxT
-VkdHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdDb21wb25lbnRUcmFuc2ZlckZ1bmN0aW9uRWxlbWVudDp0
-cnVlLFNWR0ZFRHJvcFNoYWRvd0VsZW1lbnQ6dHJ1ZSxTVkdNUGF0aEVsZW1lbnQ6dHJ1ZSxTVkdFbGVt
-ZW50OmZhbHNlfSkKSC5MWi4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlJH
-LiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguVlAuJG5hdGl2ZVN1cGVyY2xh
-c3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5EZy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZm
-ZXJWaWV3IgpILldCLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguWkcuJG5h
-dGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5QZy4kbmF0aXZlU3VwZXJjbGFzc1Rh
-Zz0iQXJyYXlCdWZmZXJWaWV3In0pKCkKY29udmVydEFsbFRvRmFzdE9iamVjdCh3KQpjb252ZXJ0VG9G
-YXN0T2JqZWN0KCQpOyhmdW5jdGlvbihhKXtpZih0eXBlb2YgZG9jdW1lbnQ9PT0idW5kZWZpbmVkIil7
-YShudWxsKQpyZXR1cm59aWYodHlwZW9mIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQhPSd1bmRlZmluZWQn
-KXthKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpCnJldHVybn12YXIgcz1kb2N1bWVudC5zY3JpcHRzCmZ1
-bmN0aW9uIG9uTG9hZChiKXtmb3IodmFyIHE9MDtxPHMubGVuZ3RoOysrcSlzW3FdLnJlbW92ZUV2ZW50
-TGlzdGVuZXIoImxvYWQiLG9uTG9hZCxmYWxzZSkKYShiLnRhcmdldCl9Zm9yKHZhciByPTA7cjxzLmxl
-bmd0aDsrK3Ipc1tyXS5hZGRFdmVudExpc3RlbmVyKCJsb2FkIixvbkxvYWQsZmFsc2UpfSkoZnVuY3Rp
-b24oYSl7di5jdXJyZW50U2NyaXB0PWEKaWYodHlwZW9mIGRhcnRNYWluUnVubmVyPT09ImZ1bmN0aW9u
-IilkYXJ0TWFpblJ1bm5lcihMLklxLFtdKQplbHNlIEwuSXEoW10pfSl9KSgpCi8vIyBzb3VyY2VNYXBw
-aW5nVVJMPW1pZ3JhdGlvbi5qcy5tYXAK
+OwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiRmlyZWZveCIpID09IC0xKSByZXR1cm4gaG9va3M7CiAg
+dmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcXVpY2tNYXAgPSB7CiAgICAiQmVmb3JlVW5s
+b2FkRXZlbnQiOiAiRXZlbnQiLAogICAgIkRhdGFUcmFuc2ZlciI6ICJDbGlwYm9hcmQiLAogICAgIkdl
+b0dlb2xvY2F0aW9uIjogIkdlb2xvY2F0aW9uIiwKICAgICJMb2NhdGlvbiI6ICIhTG9jYXRpb24iLAog
+ICAgIldvcmtlck1lc3NhZ2VFdmVudCI6ICJNZXNzYWdlRXZlbnQiLAogICAgIlhNTERvY3VtZW50Ijog
+IiFEb2N1bWVudCJ9OwogIGZ1bmN0aW9uIGdldFRhZ0ZpcmVmb3gobykgewogICAgdmFyIHRhZyA9IGdl
+dFRhZyhvKTsKICAgIHJldHVybiBxdWlja01hcFt0YWddIHx8IHRhZzsKICB9CiAgaG9va3MuZ2V0VGFn
+ID0gZ2V0VGFnRmlyZWZveDsKfQpDLnhpPWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFyIHVzZXJBZ2VudCA9
+IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9iamVjdCIgPyBuYXZpZ2F0b3IudXNlckFnZW50IDogIiI7CiAg
+aWYgKHVzZXJBZ2VudC5pbmRleE9mKCJUcmlkZW50LyIpID09IC0xKSByZXR1cm4gaG9va3M7CiAgdmFy
+IGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcXVpY2tNYXAgPSB7CiAgICAiQmVmb3JlVW5sb2Fk
+RXZlbnQiOiAiRXZlbnQiLAogICAgIkRhdGFUcmFuc2ZlciI6ICJDbGlwYm9hcmQiLAogICAgIkhUTUxE
+REVsZW1lbnQiOiAiSFRNTEVsZW1lbnQiLAogICAgIkhUTUxEVEVsZW1lbnQiOiAiSFRNTEVsZW1lbnQi
+LAogICAgIkhUTUxQaHJhc2VFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJQb3NpdGlvbiI6ICJH
+ZW9wb3NpdGlvbiIKICB9OwogIGZ1bmN0aW9uIGdldFRhZ0lFKG8pIHsKICAgIHZhciB0YWcgPSBnZXRU
+YWcobyk7CiAgICB2YXIgbmV3VGFnID0gcXVpY2tNYXBbdGFnXTsKICAgIGlmIChuZXdUYWcpIHJldHVy
+biBuZXdUYWc7CiAgICBpZiAodGFnID09ICJPYmplY3QiKSB7CiAgICAgIGlmICh3aW5kb3cuRGF0YVZp
+ZXcgJiYgKG8gaW5zdGFuY2VvZiB3aW5kb3cuRGF0YVZpZXcpKSByZXR1cm4gIkRhdGFWaWV3IjsKICAg
+IH0KICAgIHJldHVybiB0YWc7CiAgfQogIGZ1bmN0aW9uIHByb3RvdHlwZUZvclRhZ0lFKHRhZykgewog
+ICAgdmFyIGNvbnN0cnVjdG9yID0gd2luZG93W3RhZ107CiAgICBpZiAoY29uc3RydWN0b3IgPT0gbnVs
+bCkgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gY29uc3RydWN0b3IucHJvdG90eXBlOwogIH0KICBob29r
+cy5nZXRUYWcgPSBnZXRUYWdJRTsKICBob29rcy5wcm90b3R5cGVGb3JUYWcgPSBwcm90b3R5cGVGb3JU
+YWdJRTsKfQpDLmk3PWZ1bmN0aW9uKGhvb2tzKSB7IHJldHVybiBob29rczsgfQoKQy5DdD1uZXcgUC5i
+eSgpCkMuRXE9bmV3IFAuazUoKQpDLnhNPW5ldyBQLnU1KCkKQy5Raz1uZXcgUC5FMygpCkMuTnY9bmV3
+IEgua3IoKQpDLk5VPW5ldyBQLkppKCkKQy5wZD1uZXcgUC5aZCgpCkMuQWQ9bmV3IFIuSDcoMCwiSGlu
+dEFjdGlvbktpbmQuYWRkTnVsbGFibGVIaW50IikKQy5uZT1uZXcgUi5INygxLCJIaW50QWN0aW9uS2lu
+ZC5hZGROb25OdWxsYWJsZUhpbnQiKQpDLm15PW5ldyBSLkg3KDIsIkhpbnRBY3Rpb25LaW5kLmNoYW5n
+ZVRvTnVsbGFibGVIaW50IikKQy5yeD1uZXcgUi5INygzLCJIaW50QWN0aW9uS2luZC5jaGFuZ2VUb05v
+bk51bGxhYmxlSGludCIpCkMud1Y9bmV3IFIuSDcoNCwiSGludEFjdGlvbktpbmQucmVtb3ZlTnVsbGFi
+bGVIaW50IikKQy5mUj1uZXcgUi5INyg1LCJIaW50QWN0aW9uS2luZC5yZW1vdmVOb25OdWxsYWJsZUhp
+bnQiKQpDLkEzPW5ldyBQLk14KG51bGwpCkMublg9bmV3IFAub2oobnVsbCkKQy5jdz1uZXcgTC5HYigw
+LCJVbml0TWlncmF0aW9uU3RhdHVzLmFscmVhZHlNaWdyYXRlZCIpCkMuZGM9bmV3IEwuR2IoMSwiVW5p
+dE1pZ3JhdGlvblN0YXR1cy5pbmRldGVybWluYXRlIikKQy5XRD1uZXcgTC5HYigyLCJVbml0TWlncmF0
+aW9uU3RhdHVzLm1pZ3JhdGluZyIpCkMuWGo9bmV3IEwuR2IoMywiVW5pdE1pZ3JhdGlvblN0YXR1cy5v
+cHRpbmdPdXQiKQpDLmwwPUguVk0ocyhbQy5jdyxDLmRjLEMuV0QsQy5Yal0pLEguTjAoImpkPEdiKj4i
+KSkKQy5haz1ILlZNKHMoWzAsMCwzMjc3NiwzMzc5MiwxLDEwMjQwLDAsMF0pLHQuVikKQy5jbT1ILlZN
+KHMoWyIqOjpjbGFzcyIsIio6OmRpciIsIio6OmRyYWdnYWJsZSIsIio6OmhpZGRlbiIsIio6OmlkIiwi
+Kjo6aW5lcnQiLCIqOjppdGVtcHJvcCIsIio6Oml0ZW1yZWYiLCIqOjppdGVtc2NvcGUiLCIqOjpsYW5n
+IiwiKjo6c3BlbGxjaGVjayIsIio6OnRpdGxlIiwiKjo6dHJhbnNsYXRlIiwiQTo6YWNjZXNza2V5Iiwi
+QTo6Y29vcmRzIiwiQTo6aHJlZmxhbmciLCJBOjpuYW1lIiwiQTo6c2hhcGUiLCJBOjp0YWJpbmRleCIs
+IkE6OnRhcmdldCIsIkE6OnR5cGUiLCJBUkVBOjphY2Nlc3NrZXkiLCJBUkVBOjphbHQiLCJBUkVBOjpj
+b29yZHMiLCJBUkVBOjpub2hyZWYiLCJBUkVBOjpzaGFwZSIsIkFSRUE6OnRhYmluZGV4IiwiQVJFQTo6
+dGFyZ2V0IiwiQVVESU86OmNvbnRyb2xzIiwiQVVESU86Omxvb3AiLCJBVURJTzo6bWVkaWFncm91cCIs
+IkFVRElPOjptdXRlZCIsIkFVRElPOjpwcmVsb2FkIiwiQkRPOjpkaXIiLCJCT0RZOjphbGluayIsIkJP
+RFk6OmJnY29sb3IiLCJCT0RZOjpsaW5rIiwiQk9EWTo6dGV4dCIsIkJPRFk6OnZsaW5rIiwiQlI6OmNs
+ZWFyIiwiQlVUVE9OOjphY2Nlc3NrZXkiLCJCVVRUT046OmRpc2FibGVkIiwiQlVUVE9OOjpuYW1lIiwi
+QlVUVE9OOjp0YWJpbmRleCIsIkJVVFRPTjo6dHlwZSIsIkJVVFRPTjo6dmFsdWUiLCJDQU5WQVM6Omhl
+aWdodCIsIkNBTlZBUzo6d2lkdGgiLCJDQVBUSU9OOjphbGlnbiIsIkNPTDo6YWxpZ24iLCJDT0w6OmNo
+YXIiLCJDT0w6OmNoYXJvZmYiLCJDT0w6OnNwYW4iLCJDT0w6OnZhbGlnbiIsIkNPTDo6d2lkdGgiLCJD
+T0xHUk9VUDo6YWxpZ24iLCJDT0xHUk9VUDo6Y2hhciIsIkNPTEdST1VQOjpjaGFyb2ZmIiwiQ09MR1JP
+VVA6OnNwYW4iLCJDT0xHUk9VUDo6dmFsaWduIiwiQ09MR1JPVVA6OndpZHRoIiwiQ09NTUFORDo6Y2hl
+Y2tlZCIsIkNPTU1BTkQ6OmNvbW1hbmQiLCJDT01NQU5EOjpkaXNhYmxlZCIsIkNPTU1BTkQ6OmxhYmVs
+IiwiQ09NTUFORDo6cmFkaW9ncm91cCIsIkNPTU1BTkQ6OnR5cGUiLCJEQVRBOjp2YWx1ZSIsIkRFTDo6
+ZGF0ZXRpbWUiLCJERVRBSUxTOjpvcGVuIiwiRElSOjpjb21wYWN0IiwiRElWOjphbGlnbiIsIkRMOjpj
+b21wYWN0IiwiRklFTERTRVQ6OmRpc2FibGVkIiwiRk9OVDo6Y29sb3IiLCJGT05UOjpmYWNlIiwiRk9O
+VDo6c2l6ZSIsIkZPUk06OmFjY2VwdCIsIkZPUk06OmF1dG9jb21wbGV0ZSIsIkZPUk06OmVuY3R5cGUi
+LCJGT1JNOjptZXRob2QiLCJGT1JNOjpuYW1lIiwiRk9STTo6bm92YWxpZGF0ZSIsIkZPUk06OnRhcmdl
+dCIsIkZSQU1FOjpuYW1lIiwiSDE6OmFsaWduIiwiSDI6OmFsaWduIiwiSDM6OmFsaWduIiwiSDQ6OmFs
+aWduIiwiSDU6OmFsaWduIiwiSDY6OmFsaWduIiwiSFI6OmFsaWduIiwiSFI6Om5vc2hhZGUiLCJIUjo6
+c2l6ZSIsIkhSOjp3aWR0aCIsIkhUTUw6OnZlcnNpb24iLCJJRlJBTUU6OmFsaWduIiwiSUZSQU1FOjpm
+cmFtZWJvcmRlciIsIklGUkFNRTo6aGVpZ2h0IiwiSUZSQU1FOjptYXJnaW5oZWlnaHQiLCJJRlJBTUU6
+Om1hcmdpbndpZHRoIiwiSUZSQU1FOjp3aWR0aCIsIklNRzo6YWxpZ24iLCJJTUc6OmFsdCIsIklNRzo6
+Ym9yZGVyIiwiSU1HOjpoZWlnaHQiLCJJTUc6OmhzcGFjZSIsIklNRzo6aXNtYXAiLCJJTUc6Om5hbWUi
+LCJJTUc6OnVzZW1hcCIsIklNRzo6dnNwYWNlIiwiSU1HOjp3aWR0aCIsIklOUFVUOjphY2NlcHQiLCJJ
+TlBVVDo6YWNjZXNza2V5IiwiSU5QVVQ6OmFsaWduIiwiSU5QVVQ6OmFsdCIsIklOUFVUOjphdXRvY29t
+cGxldGUiLCJJTlBVVDo6YXV0b2ZvY3VzIiwiSU5QVVQ6OmNoZWNrZWQiLCJJTlBVVDo6ZGlzYWJsZWQi
+LCJJTlBVVDo6aW5wdXRtb2RlIiwiSU5QVVQ6OmlzbWFwIiwiSU5QVVQ6Omxpc3QiLCJJTlBVVDo6bWF4
+IiwiSU5QVVQ6Om1heGxlbmd0aCIsIklOUFVUOjptaW4iLCJJTlBVVDo6bXVsdGlwbGUiLCJJTlBVVDo6
+bmFtZSIsIklOUFVUOjpwbGFjZWhvbGRlciIsIklOUFVUOjpyZWFkb25seSIsIklOUFVUOjpyZXF1aXJl
+ZCIsIklOUFVUOjpzaXplIiwiSU5QVVQ6OnN0ZXAiLCJJTlBVVDo6dGFiaW5kZXgiLCJJTlBVVDo6dHlw
+ZSIsIklOUFVUOjp1c2VtYXAiLCJJTlBVVDo6dmFsdWUiLCJJTlM6OmRhdGV0aW1lIiwiS0VZR0VOOjpk
+aXNhYmxlZCIsIktFWUdFTjo6a2V5dHlwZSIsIktFWUdFTjo6bmFtZSIsIkxBQkVMOjphY2Nlc3NrZXki
+LCJMQUJFTDo6Zm9yIiwiTEVHRU5EOjphY2Nlc3NrZXkiLCJMRUdFTkQ6OmFsaWduIiwiTEk6OnR5cGUi
+LCJMSTo6dmFsdWUiLCJMSU5LOjpzaXplcyIsIk1BUDo6bmFtZSIsIk1FTlU6OmNvbXBhY3QiLCJNRU5V
+OjpsYWJlbCIsIk1FTlU6OnR5cGUiLCJNRVRFUjo6aGlnaCIsIk1FVEVSOjpsb3ciLCJNRVRFUjo6bWF4
+IiwiTUVURVI6Om1pbiIsIk1FVEVSOjp2YWx1ZSIsIk9CSkVDVDo6dHlwZW11c3RtYXRjaCIsIk9MOjpj
+b21wYWN0IiwiT0w6OnJldmVyc2VkIiwiT0w6OnN0YXJ0IiwiT0w6OnR5cGUiLCJPUFRHUk9VUDo6ZGlz
+YWJsZWQiLCJPUFRHUk9VUDo6bGFiZWwiLCJPUFRJT046OmRpc2FibGVkIiwiT1BUSU9OOjpsYWJlbCIs
+Ik9QVElPTjo6c2VsZWN0ZWQiLCJPUFRJT046OnZhbHVlIiwiT1VUUFVUOjpmb3IiLCJPVVRQVVQ6Om5h
+bWUiLCJQOjphbGlnbiIsIlBSRTo6d2lkdGgiLCJQUk9HUkVTUzo6bWF4IiwiUFJPR1JFU1M6Om1pbiIs
+IlBST0dSRVNTOjp2YWx1ZSIsIlNFTEVDVDo6YXV0b2NvbXBsZXRlIiwiU0VMRUNUOjpkaXNhYmxlZCIs
+IlNFTEVDVDo6bXVsdGlwbGUiLCJTRUxFQ1Q6Om5hbWUiLCJTRUxFQ1Q6OnJlcXVpcmVkIiwiU0VMRUNU
+OjpzaXplIiwiU0VMRUNUOjp0YWJpbmRleCIsIlNPVVJDRTo6dHlwZSIsIlRBQkxFOjphbGlnbiIsIlRB
+QkxFOjpiZ2NvbG9yIiwiVEFCTEU6OmJvcmRlciIsIlRBQkxFOjpjZWxscGFkZGluZyIsIlRBQkxFOjpj
+ZWxsc3BhY2luZyIsIlRBQkxFOjpmcmFtZSIsIlRBQkxFOjpydWxlcyIsIlRBQkxFOjpzdW1tYXJ5Iiwi
+VEFCTEU6OndpZHRoIiwiVEJPRFk6OmFsaWduIiwiVEJPRFk6OmNoYXIiLCJUQk9EWTo6Y2hhcm9mZiIs
+IlRCT0RZOjp2YWxpZ24iLCJURDo6YWJiciIsIlREOjphbGlnbiIsIlREOjpheGlzIiwiVEQ6OmJnY29s
+b3IiLCJURDo6Y2hhciIsIlREOjpjaGFyb2ZmIiwiVEQ6OmNvbHNwYW4iLCJURDo6aGVhZGVycyIsIlRE
+OjpoZWlnaHQiLCJURDo6bm93cmFwIiwiVEQ6OnJvd3NwYW4iLCJURDo6c2NvcGUiLCJURDo6dmFsaWdu
+IiwiVEQ6OndpZHRoIiwiVEVYVEFSRUE6OmFjY2Vzc2tleSIsIlRFWFRBUkVBOjphdXRvY29tcGxldGUi
+LCJURVhUQVJFQTo6Y29scyIsIlRFWFRBUkVBOjpkaXNhYmxlZCIsIlRFWFRBUkVBOjppbnB1dG1vZGUi
+LCJURVhUQVJFQTo6bmFtZSIsIlRFWFRBUkVBOjpwbGFjZWhvbGRlciIsIlRFWFRBUkVBOjpyZWFkb25s
+eSIsIlRFWFRBUkVBOjpyZXF1aXJlZCIsIlRFWFRBUkVBOjpyb3dzIiwiVEVYVEFSRUE6OnRhYmluZGV4
+IiwiVEVYVEFSRUE6OndyYXAiLCJURk9PVDo6YWxpZ24iLCJURk9PVDo6Y2hhciIsIlRGT09UOjpjaGFy
+b2ZmIiwiVEZPT1Q6OnZhbGlnbiIsIlRIOjphYmJyIiwiVEg6OmFsaWduIiwiVEg6OmF4aXMiLCJUSDo6
+Ymdjb2xvciIsIlRIOjpjaGFyIiwiVEg6OmNoYXJvZmYiLCJUSDo6Y29sc3BhbiIsIlRIOjpoZWFkZXJz
+IiwiVEg6OmhlaWdodCIsIlRIOjpub3dyYXAiLCJUSDo6cm93c3BhbiIsIlRIOjpzY29wZSIsIlRIOjp2
+YWxpZ24iLCJUSDo6d2lkdGgiLCJUSEVBRDo6YWxpZ24iLCJUSEVBRDo6Y2hhciIsIlRIRUFEOjpjaGFy
+b2ZmIiwiVEhFQUQ6OnZhbGlnbiIsIlRSOjphbGlnbiIsIlRSOjpiZ2NvbG9yIiwiVFI6OmNoYXIiLCJU
+Ujo6Y2hhcm9mZiIsIlRSOjp2YWxpZ24iLCJUUkFDSzo6ZGVmYXVsdCIsIlRSQUNLOjpraW5kIiwiVFJB
+Q0s6OmxhYmVsIiwiVFJBQ0s6OnNyY2xhbmciLCJVTDo6Y29tcGFjdCIsIlVMOjp0eXBlIiwiVklERU86
+OmNvbnRyb2xzIiwiVklERU86OmhlaWdodCIsIlZJREVPOjpsb29wIiwiVklERU86Om1lZGlhZ3JvdXAi
+LCJWSURFTzo6bXV0ZWQiLCJWSURFTzo6cHJlbG9hZCIsIlZJREVPOjp3aWR0aCJdKSx0LmkpCkMuVkM9
+SC5WTShzKFswLDAsNjU0OTAsNDUwNTUsNjU1MzUsMzQ4MTUsNjU1MzQsMTg0MzFdKSx0LlYpCkMubUs9
+SC5WTShzKFswLDAsMjY2MjQsMTAyMyw2NTUzNCwyMDQ3LDY1NTM0LDIwNDddKSx0LlYpCkMuU3E9SC5W
+TShzKFsiSEVBRCIsIkFSRUEiLCJCQVNFIiwiQkFTRUZPTlQiLCJCUiIsIkNPTCIsIkNPTEdST1VQIiwi
+RU1CRUQiLCJGUkFNRSIsIkZSQU1FU0VUIiwiSFIiLCJJTUFHRSIsIklNRyIsIklOUFVUIiwiSVNJTkRF
+WCIsIkxJTksiLCJNRVRBIiwiUEFSQU0iLCJTT1VSQ0UiLCJTVFlMRSIsIlRJVExFIiwiV0JSIl0pLHQu
+aSkKQy5oVT1ILlZNKHMoW10pLHQuYikKQy5kbj1ILlZNKHMoW10pLEguTjAoImpkPExMKj4iKSkKQy54
+RD1ILlZNKHMoW10pLHQuaSkKQy50bz1ILlZNKHMoWzAsMCwzMjcyMiwxMjI4Nyw2NTUzNCwzNDgxNSw2
+NTUzNCwxODQzMV0pLHQuVikKQy5yaz1ILlZNKHMoW0MuQWQsQy5uZSxDLm15LEMucngsQy53VixDLmZS
+XSksSC5OMCgiamQ8SDcqPiIpKQpDLkYzPUguVk0ocyhbMCwwLDI0NTc2LDEwMjMsNjU1MzQsMzQ4MTUs
+NjU1MzQsMTg0MzFdKSx0LlYpCkMuZWE9SC5WTShzKFswLDAsMzI3NTQsMTEyNjMsNjU1MzQsMzQ4MTUs
+NjU1MzQsMTg0MzFdKSx0LlYpCkMuWko9SC5WTShzKFswLDAsMzI3MjIsMTIyODcsNjU1MzUsMzQ4MTUs
+NjU1MzQsMTg0MzFdKSx0LlYpCkMuV2Q9SC5WTShzKFswLDAsNjU0OTAsMTIyODcsNjU1MzUsMzQ4MTUs
+NjU1MzQsMTg0MzFdKSx0LlYpCkMuUXg9SC5WTShzKFsiYmluZCIsImlmIiwicmVmIiwicmVwZWF0Iiwi
+c3ludGF4Il0pLHQuaSkKQy5CST1ILlZNKHMoWyJBOjpocmVmIiwiQVJFQTo6aHJlZiIsIkJMT0NLUVVP
+VEU6OmNpdGUiLCJCT0RZOjpiYWNrZ3JvdW5kIiwiQ09NTUFORDo6aWNvbiIsIkRFTDo6Y2l0ZSIsIkZP
+Uk06OmFjdGlvbiIsIklNRzo6c3JjIiwiSU5QVVQ6OnNyYyIsIklOUzo6Y2l0ZSIsIlE6OmNpdGUiLCJW
+SURFTzo6cG9zdGVyIl0pLHQuaSkKQy5EeD1uZXcgSC5MUCgwLHt9LEMueEQsSC5OMCgiTFA8cVUqLHpN
+PGo4Kj4qPiIpKQpDLkNNPW5ldyBILkxQKDAse30sQy54RCxILk4wKCJMUDxxVSoscVUqPiIpKQpDLmlI
+PUguVk0ocyhbXSksSC5OMCgiamQ8R0QqPiIpKQpDLldPPW5ldyBILkxQKDAse30sQy5pSCxILk4wKCJM
+UDxHRCosQD4iKSkKQy5ZMj1uZXcgTC5POSgiTmF2aWdhdGlvblRyZWVOb2RlVHlwZS5kaXJlY3Rvcnki
+KQpDLnJmPW5ldyBMLk85KCJOYXZpZ2F0aW9uVHJlZU5vZGVUeXBlLmZpbGUiKQpDLlRlPW5ldyBILnd2
+KCJjYWxsIikKQy5vRT1uZXcgUC5HWSghMSkKQy53UT1uZXcgUC5GeShudWxsLDIpfSkoKTsoZnVuY3Rp
+b24gc3RhdGljRmllbGRzKCl7JC56bT1udWxsCiQueWo9MAokLm1KPW51bGwKJC5QND1udWxsCiQuTkY9
+bnVsbAokLlRYPW51bGwKJC54Nz1udWxsCiQubnc9bnVsbAokLnZ2PW51bGwKJC5Cdj1udWxsCiQuUzY9
+bnVsbAokLms4PW51bGwKJC5tZz1udWxsCiQuVUQ9ITEKJC5YMz1DLk5VCiQueGc9SC5WTShbXSxILk4w
+KCJqZDxNaD4iKSkKJC54bz1udWxsCiQuQk89bnVsbAokLmx0PW51bGwKJC5FVT1udWxsCiQub3I9UC5G
+bCh0Lk4sdC5ZKQokLklSPW51bGwKJC5JNj1udWxsCiQuRmY9bnVsbH0pKCk7KGZ1bmN0aW9uIGxhenlJ
+bml0aWFsaXplcnMoKXt2YXIgcz1odW5rSGVscGVycy5sYXp5RmluYWwscj1odW5rSGVscGVycy5sYXp5
+T2xkCnMoJCwiZmEiLCJ3IixmdW5jdGlvbigpe3JldHVybiBILllnKCJfJGRhcnRfZGFydENsb3N1cmUi
+KX0pCnMoJCwiVTIiLCJTbiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHsKdG9TdHJpbmc6ZnVu
+Y3Rpb24oKXtyZXR1cm4iJHJlY2VpdmVyJCJ9fSkpfSkKcygkLCJ4cSIsImxxIixmdW5jdGlvbigpe3Jl
+dHVybiBILmNNKEguUzcoeyRtZXRob2QkOm51bGwsCnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIiRy
+ZWNlaXZlciQifX0pKX0pCnMoJCwiUjEiLCJOOSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KG51
+bGwpKX0pCnMoJCwiZk4iLCJpSSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3ZhciAk
+YXJndW1lbnRzRXhwciQ9IiRhcmd1bWVudHMkIgp0cnl7bnVsbC4kbWV0aG9kJCgkYXJndW1lbnRzRXhw
+ciQpfWNhdGNoKHEpe3JldHVybiBxLm1lc3NhZ2V9fSgpKX0pCnMoJCwicWkiLCJVTiIsZnVuY3Rpb24o
+KXtyZXR1cm4gSC5jTShILlM3KHZvaWQgMCkpfSkKcygkLCJyWiIsIlpoIixmdW5jdGlvbigpe3JldHVy
+biBILmNNKGZ1bmN0aW9uKCl7dmFyICRhcmd1bWVudHNFeHByJD0iJGFyZ3VtZW50cyQiCnRyeXsodm9p
+ZCAwKS4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHEpe3JldHVybiBxLm1lc3NhZ2V9fSgp
+KX0pCnMoJCwia3EiLCJyTiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILk1qKG51bGwpKX0pCnMoJCwi
+dHQiLCJjMyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3RyeXtudWxsLiRtZXRob2Qk
+fWNhdGNoKHEpe3JldHVybiBxLm1lc3NhZ2V9fSgpKX0pCnMoJCwiZHQiLCJISyIsZnVuY3Rpb24oKXty
+ZXR1cm4gSC5jTShILk1qKHZvaWQgMCkpfSkKcygkLCJBNyIsInIxIixmdW5jdGlvbigpe3JldHVybiBI
+LmNNKGZ1bmN0aW9uKCl7dHJ5eyh2b2lkIDApLiRtZXRob2QkfWNhdGNoKHEpe3JldHVybiBxLm1lc3Nh
+Z2V9fSgpKX0pCnMoJCwiV2MiLCJ1dCIsZnVuY3Rpb24oKXtyZXR1cm4gUC5PaigpfSkKcygkLCJraCIs
+InJmIixmdW5jdGlvbigpe3JldHVybiBuZXcgUC54cigpLiQwKCl9KQpzKCQsImRIIiwiSEciLGZ1bmN0
+aW9uKCl7cmV0dXJuIG5ldyBQLk56KCkuJDAoKX0pCnMoJCwiYnQiLCJWNyIsZnVuY3Rpb24oKXtyZXR1
+cm4gbmV3IEludDhBcnJheShILlhGKEguVk0oWy0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
+LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
+LC0yLC0yLC0yLC0yLC0yLC0yLC0xLC0yLC0yLC0yLC0yLC0yLDYyLC0yLDYyLC0yLDYzLDUyLDUzLDU0
+LDU1LDU2LDU3LDU4LDU5LDYwLDYxLC0yLC0yLC0yLC0xLC0yLC0yLC0yLDAsMSwyLDMsNCw1LDYsNyw4
+LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUsLTIsLTIsLTIs
+LTIsNjMsLTIsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIs
+NDMsNDQsNDUsNDYsNDcsNDgsNDksNTAsNTEsLTIsLTIsLTIsLTIsLTJdLHQuYSkpKX0pCnMoJCwiTTUi
+LCJ3USIsZnVuY3Rpb24oKXtyZXR1cm4gdHlwZW9mIHByb2Nlc3MhPSJ1bmRlZmluZWQiJiZPYmplY3Qu
+cHJvdG90eXBlLnRvU3RyaW5nLmNhbGwocHJvY2Vzcyk9PSJbb2JqZWN0IHByb2Nlc3NdIiYmcHJvY2Vz
+cy5wbGF0Zm9ybT09IndpbjMyIn0pCnMoJCwibWYiLCJ6NCIsZnVuY3Rpb24oKXtyZXR1cm4gUC5udSgi
+XltcXC1cXC4wLTlBLVpfYS16fl0qJCIpfSkKcygkLCJPUSIsInZaIixmdW5jdGlvbigpe3JldHVybiBQ
+LktOKCl9KQpzKCQsIlNDIiwiQU4iLGZ1bmN0aW9uKCl7cmV0dXJuIFAudE0oWyJBIiwiQUJCUiIsIkFD
+Uk9OWU0iLCJBRERSRVNTIiwiQVJFQSIsIkFSVElDTEUiLCJBU0lERSIsIkFVRElPIiwiQiIsIkJESSIs
+IkJETyIsIkJJRyIsIkJMT0NLUVVPVEUiLCJCUiIsIkJVVFRPTiIsIkNBTlZBUyIsIkNBUFRJT04iLCJD
+RU5URVIiLCJDSVRFIiwiQ09ERSIsIkNPTCIsIkNPTEdST1VQIiwiQ09NTUFORCIsIkRBVEEiLCJEQVRB
+TElTVCIsIkREIiwiREVMIiwiREVUQUlMUyIsIkRGTiIsIkRJUiIsIkRJViIsIkRMIiwiRFQiLCJFTSIs
+IkZJRUxEU0VUIiwiRklHQ0FQVElPTiIsIkZJR1VSRSIsIkZPTlQiLCJGT09URVIiLCJGT1JNIiwiSDEi
+LCJIMiIsIkgzIiwiSDQiLCJINSIsIkg2IiwiSEVBREVSIiwiSEdST1VQIiwiSFIiLCJJIiwiSUZSQU1F
+IiwiSU1HIiwiSU5QVVQiLCJJTlMiLCJLQkQiLCJMQUJFTCIsIkxFR0VORCIsIkxJIiwiTUFQIiwiTUFS
+SyIsIk1FTlUiLCJNRVRFUiIsIk5BViIsIk5PQlIiLCJPTCIsIk9QVEdST1VQIiwiT1BUSU9OIiwiT1VU
+UFVUIiwiUCIsIlBSRSIsIlBST0dSRVNTIiwiUSIsIlMiLCJTQU1QIiwiU0VDVElPTiIsIlNFTEVDVCIs
+IlNNQUxMIiwiU09VUkNFIiwiU1BBTiIsIlNUUklLRSIsIlNUUk9ORyIsIlNVQiIsIlNVTU1BUlkiLCJT
+VVAiLCJUQUJMRSIsIlRCT0RZIiwiVEQiLCJURVhUQVJFQSIsIlRGT09UIiwiVEgiLCJUSEVBRCIsIlRJ
+TUUiLCJUUiIsIlRSQUNLIiwiVFQiLCJVIiwiVUwiLCJWQVIiLCJWSURFTyIsIldCUiJdLHQuTil9KQpz
+KCQsIlg0IiwiaEciLGZ1bmN0aW9uKCl7cmV0dXJuIFAubnUoIl5cXFMrJCIpfSkKcygkLCJ3TyIsIm93
+IixmdW5jdGlvbigpe3JldHVybiBQLk5EKHNlbGYpfSkKcygkLCJrdCIsIlI4IixmdW5jdGlvbigpe3Jl
+dHVybiBILllnKCJfJGRhcnRfZGFydE9iamVjdCIpfSkKcygkLCJmSyIsImtJIixmdW5jdGlvbigpe3Jl
+dHVybiBmdW5jdGlvbiBEYXJ0T2JqZWN0KGEpe3RoaXMubz1hfX0pCnIoJCwicXQiLCJ6QiIsZnVuY3Rp
+b24oKXtyZXR1cm4gbmV3IFQubVEoKX0pCnIoJCwiT2wiLCJVRSIsZnVuY3Rpb24oKXtyZXR1cm4gUC5o
+SyhDLm9sLmdtVyhXLngzKCkpLmhyZWYpLmdoWSgpLnEoMCwiYXV0aFRva2VuIil9KQpyKCQsImhUIiwi
+eVAiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRpdC1saXN0IC5wYW5l
+bC1jb250ZW50Iil9KQpyKCQsIlc2IiwiaEwiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNl
+bGVjdG9yKCIuZWRpdC1wYW5lbCAucGFuZWwtY29udGVudCIpfSkKcigkLCJUUiIsIkRXIixmdW5jdGlv
+bigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiZm9vdGVyIil9KQpyKCQsIkVZIiwiZmkiLGZ1
+bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCJoZWFkZXIiKX0pCnIoJCwiYXYiLCJE
+OSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiN1bml0LW5hbWUiKX0pCnIo
+JCwidDAiLCJiTiIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiNtaWdyYXRl
+LXVuaXQtc3RhdHVzLWljb24tbGFiZWwiKX0pCnIoJCwiYkEiLCJjMCIsZnVuY3Rpb24oKXtyZXR1cm4g
+Vy5acigpLnF1ZXJ5U2VsZWN0b3IoIiNtaWdyYXRlLXVuaXQtc3RhdHVzLWljb24iKX0pCnIoJCwiZmUi
+LCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnMoJCwiZW8iLCJuVSIsZnVuY3Rpb24o
+KXtyZXR1cm4gbmV3IE0ubEkoJC5IaygpKX0pCnMoJCwieXIiLCJiRCIsZnVuY3Rpb24oKXtyZXR1cm4g
+bmV3IEUuT0YoUC5udSgiLyIpLFAubnUoIlteL10kIiksUC5udSgiXi8iKSl9KQpzKCQsIk1rIiwiS2si
+LGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLklWKFAubnUoIlsvXFxcXF0iKSxQLm51KCJbXi9cXFxcXSQi
+KSxQLm51KCJeKFxcXFxcXFxcW15cXFxcXStcXFxcW15cXFxcL10rfFthLXpBLVpdOlsvXFxcXF0pIiks
+UC5udSgiXlsvXFxcXF0oPyFbL1xcXFxdKSIpKX0pCnMoJCwiYWsiLCJFYiIsZnVuY3Rpb24oKXtyZXR1
+cm4gbmV3IEYucnUoUC5udSgiLyIpLFAubnUoIiheW2EtekEtWl1bLSsuYS16QS1aXFxkXSo6Ly98W14v
+XSkkIiksUC5udSgiW2EtekEtWl1bLSsuYS16QS1aXFxkXSo6Ly9bXi9dKiIpLFAubnUoIl4vIikpfSkK
+cygkLCJscyIsIkhrIixmdW5jdGlvbigpe3JldHVybiBPLlJoKCl9KX0pKCk7KGZ1bmN0aW9uIG5hdGl2
+ZVN1cHBvcnQoKXshZnVuY3Rpb24oKXt2YXIgcz1mdW5jdGlvbihhKXt2YXIgbT17fQptW2FdPTEKcmV0
+dXJuIE9iamVjdC5rZXlzKGh1bmtIZWxwZXJzLmNvbnZlcnRUb0Zhc3RPYmplY3QobSkpWzBdfQp2Lmdl
+dElzb2xhdGVUYWc9ZnVuY3Rpb24oYSl7cmV0dXJuIHMoIl9fX2RhcnRfIithK3YuaXNvbGF0ZVRhZyl9
+CnZhciByPSJfX19kYXJ0X2lzb2xhdGVfdGFnc18iCnZhciBxPU9iamVjdFtyXXx8KE9iamVjdFtyXT1P
+YmplY3QuY3JlYXRlKG51bGwpKQp2YXIgcD0iX1p4WXhYIgpmb3IodmFyIG89MDs7bysrKXt2YXIgbj1z
+KHArIl8iK28rIl8iKQppZighKG4gaW4gcSkpe3Fbbl09MQp2Lmlzb2xhdGVUYWc9bgpicmVha319di5k
+aXNwYXRjaFByb3BlcnR5TmFtZT12LmdldElzb2xhdGVUYWcoImRpc3BhdGNoX3JlY29yZCIpfSgpCmh1
+bmtIZWxwZXJzLnNldE9yVXBkYXRlSW50ZXJjZXB0b3JzQnlUYWcoe0RPTUVycm9yOkouR3YsTWVkaWFF
+cnJvcjpKLkd2LE5hdmlnYXRvcjpKLkd2LE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2FyZTpKLkd2LE5h
+dmlnYXRvclVzZXJNZWRpYUVycm9yOkouR3YsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6Si5HdixQb3NpdGlv
+bkVycm9yOkouR3YsUmFuZ2U6Si5HdixTUUxFcnJvcjpKLkd2LERhdGFWaWV3OkguRVQsQXJyYXlCdWZm
+ZXJWaWV3OkguRVQsRmxvYXQzMkFycmF5OkguRGcsRmxvYXQ2NEFycmF5OkguRGcsSW50MTZBcnJheTpI
+LnhqLEludDMyQXJyYXk6SC5kRSxJbnQ4QXJyYXk6SC5aQSxVaW50MTZBcnJheTpILmRULFVpbnQzMkFy
+cmF5OkguUHEsVWludDhDbGFtcGVkQXJyYXk6SC5lRSxDYW52YXNQaXhlbEFycmF5OkguZUUsVWludDhB
+cnJheTpILlY2LEhUTUxBdWRpb0VsZW1lbnQ6Vy5xRSxIVE1MQlJFbGVtZW50OlcucUUsSFRNTEJ1dHRv
+bkVsZW1lbnQ6Vy5xRSxIVE1MQ2FudmFzRWxlbWVudDpXLnFFLEhUTUxDb250ZW50RWxlbWVudDpXLnFF
+LEhUTUxETGlzdEVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUxpc3RFbGVt
+ZW50OlcucUUsSFRNTERldGFpbHNFbGVtZW50OlcucUUsSFRNTERpYWxvZ0VsZW1lbnQ6Vy5xRSxIVE1M
+RGl2RWxlbWVudDpXLnFFLEhUTUxFbWJlZEVsZW1lbnQ6Vy5xRSxIVE1MRmllbGRTZXRFbGVtZW50Olcu
+cUUsSFRNTEhSRWxlbWVudDpXLnFFLEhUTUxIZWFkRWxlbWVudDpXLnFFLEhUTUxIZWFkaW5nRWxlbWVu
+dDpXLnFFLEhUTUxIdG1sRWxlbWVudDpXLnFFLEhUTUxJRnJhbWVFbGVtZW50OlcucUUsSFRNTEltYWdl
+RWxlbWVudDpXLnFFLEhUTUxJbnB1dEVsZW1lbnQ6Vy5xRSxIVE1MTElFbGVtZW50OlcucUUsSFRNTExh
+YmVsRWxlbWVudDpXLnFFLEhUTUxMZWdlbmRFbGVtZW50OlcucUUsSFRNTExpbmtFbGVtZW50OlcucUUs
+SFRNTE1hcEVsZW1lbnQ6Vy5xRSxIVE1MTWVkaWFFbGVtZW50OlcucUUsSFRNTE1lbnVFbGVtZW50Olcu
+cUUsSFRNTE1ldGFFbGVtZW50OlcucUUsSFRNTE1ldGVyRWxlbWVudDpXLnFFLEhUTUxNb2RFbGVtZW50
+OlcucUUsSFRNTE9MaXN0RWxlbWVudDpXLnFFLEhUTUxPYmplY3RFbGVtZW50OlcucUUsSFRNTE9wdEdy
+b3VwRWxlbWVudDpXLnFFLEhUTUxPcHRpb25FbGVtZW50OlcucUUsSFRNTE91dHB1dEVsZW1lbnQ6Vy5x
+RSxIVE1MUGFyYW1FbGVtZW50OlcucUUsSFRNTFBpY3R1cmVFbGVtZW50OlcucUUsSFRNTFByZUVsZW1l
+bnQ6Vy5xRSxIVE1MUHJvZ3Jlc3NFbGVtZW50OlcucUUsSFRNTFF1b3RlRWxlbWVudDpXLnFFLEhUTUxT
+Y3JpcHRFbGVtZW50OlcucUUsSFRNTFNoYWRvd0VsZW1lbnQ6Vy5xRSxIVE1MU2xvdEVsZW1lbnQ6Vy5x
+RSxIVE1MU291cmNlRWxlbWVudDpXLnFFLEhUTUxTcGFuRWxlbWVudDpXLnFFLEhUTUxTdHlsZUVsZW1l
+bnQ6Vy5xRSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNlbGxFbGVtZW50Olcu
+cUUsSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlSGVhZGVyQ2VsbEVsZW1lbnQ6
+Vy5xRSxIVE1MVGFibGVDb2xFbGVtZW50OlcucUUsSFRNTFRleHRBcmVhRWxlbWVudDpXLnFFLEhUTUxU
+aW1lRWxlbWVudDpXLnFFLEhUTUxUaXRsZUVsZW1lbnQ6Vy5xRSxIVE1MVHJhY2tFbGVtZW50OlcucUUs
+SFRNTFVMaXN0RWxlbWVudDpXLnFFLEhUTUxVbmtub3duRWxlbWVudDpXLnFFLEhUTUxWaWRlb0VsZW1l
+bnQ6Vy5xRSxIVE1MRGlyZWN0b3J5RWxlbWVudDpXLnFFLEhUTUxGb250RWxlbWVudDpXLnFFLEhUTUxG
+cmFtZUVsZW1lbnQ6Vy5xRSxIVE1MRnJhbWVTZXRFbGVtZW50OlcucUUsSFRNTE1hcnF1ZWVFbGVtZW50
+OlcucUUsSFRNTEVsZW1lbnQ6Vy5xRSxIVE1MQW5jaG9yRWxlbWVudDpXLkdoLEhUTUxBcmVhRWxlbWVu
+dDpXLmZZLEhUTUxCYXNlRWxlbWVudDpXLm5CLEJsb2I6Vy5BeixIVE1MQm9keUVsZW1lbnQ6Vy5RUCxD
+REFUQVNlY3Rpb246Vy5ueCxDaGFyYWN0ZXJEYXRhOlcubngsQ29tbWVudDpXLm54LFByb2Nlc3NpbmdJ
+bnN0cnVjdGlvbjpXLm54LFRleHQ6Vy5ueCxDU1NTdHlsZURlY2xhcmF0aW9uOlcub0osTVNTdHlsZUNT
+U1Byb3BlcnRpZXM6Vy5vSixDU1MyUHJvcGVydGllczpXLm9KLFhNTERvY3VtZW50OlcuUUYsRG9jdW1l
+bnQ6Vy5RRixET01FeGNlcHRpb246Vy5OaCxET01JbXBsZW1lbnRhdGlvbjpXLmFlLERPTVJlY3RSZWFk
+T25seTpXLklCLERPTVRva2VuTGlzdDpXLm43LEVsZW1lbnQ6Vy5jdixBYm9ydFBheW1lbnRFdmVudDpX
+LmVhLEFuaW1hdGlvbkV2ZW50OlcuZWEsQW5pbWF0aW9uUGxheWJhY2tFdmVudDpXLmVhLEFwcGxpY2F0
+aW9uQ2FjaGVFcnJvckV2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNoQ2xpY2tFdmVudDpXLmVhLEJhY2tn
+cm91bmRGZXRjaEV2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNoRmFpbEV2ZW50OlcuZWEsQmFja2dyb3Vu
+ZEZldGNoZWRFdmVudDpXLmVhLEJlZm9yZUluc3RhbGxQcm9tcHRFdmVudDpXLmVhLEJlZm9yZVVubG9h
+ZEV2ZW50OlcuZWEsQmxvYkV2ZW50OlcuZWEsQ2FuTWFrZVBheW1lbnRFdmVudDpXLmVhLENsaXBib2Fy
+ZEV2ZW50OlcuZWEsQ2xvc2VFdmVudDpXLmVhLEN1c3RvbUV2ZW50OlcuZWEsRGV2aWNlTW90aW9uRXZl
+bnQ6Vy5lYSxEZXZpY2VPcmllbnRhdGlvbkV2ZW50OlcuZWEsRXJyb3JFdmVudDpXLmVhLEV4dGVuZGFi
+bGVFdmVudDpXLmVhLEV4dGVuZGFibGVNZXNzYWdlRXZlbnQ6Vy5lYSxGZXRjaEV2ZW50OlcuZWEsRm9u
+dEZhY2VTZXRMb2FkRXZlbnQ6Vy5lYSxGb3JlaWduRmV0Y2hFdmVudDpXLmVhLEdhbWVwYWRFdmVudDpX
+LmVhLEhhc2hDaGFuZ2VFdmVudDpXLmVhLEluc3RhbGxFdmVudDpXLmVhLE1lZGlhRW5jcnlwdGVkRXZl
+bnQ6Vy5lYSxNZWRpYUtleU1lc3NhZ2VFdmVudDpXLmVhLE1lZGlhUXVlcnlMaXN0RXZlbnQ6Vy5lYSxN
+ZWRpYVN0cmVhbUV2ZW50OlcuZWEsTWVkaWFTdHJlYW1UcmFja0V2ZW50OlcuZWEsTWVzc2FnZUV2ZW50
+OlcuZWEsTUlESUNvbm5lY3Rpb25FdmVudDpXLmVhLE1JRElNZXNzYWdlRXZlbnQ6Vy5lYSxNdXRhdGlv
+bkV2ZW50OlcuZWEsTm90aWZpY2F0aW9uRXZlbnQ6Vy5lYSxQYWdlVHJhbnNpdGlvbkV2ZW50OlcuZWEs
+UGF5bWVudFJlcXVlc3RFdmVudDpXLmVhLFBheW1lbnRSZXF1ZXN0VXBkYXRlRXZlbnQ6Vy5lYSxQb3BT
+dGF0ZUV2ZW50OlcuZWEsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkF2YWlsYWJsZUV2ZW50OlcuZWEsUHJl
+c2VudGF0aW9uQ29ubmVjdGlvbkNsb3NlRXZlbnQ6Vy5lYSxQcm9taXNlUmVqZWN0aW9uRXZlbnQ6Vy5l
+YSxQdXNoRXZlbnQ6Vy5lYSxSVENEYXRhQ2hhbm5lbEV2ZW50OlcuZWEsUlRDRFRNRlRvbmVDaGFuZ2VF
+dmVudDpXLmVhLFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQ6Vy5lYSxSVENUcmFja0V2ZW50OlcuZWEs
+U2VjdXJpdHlQb2xpY3lWaW9sYXRpb25FdmVudDpXLmVhLFNlbnNvckVycm9yRXZlbnQ6Vy5lYSxTcGVl
+Y2hSZWNvZ25pdGlvbkVycm9yOlcuZWEsU3BlZWNoUmVjb2duaXRpb25FdmVudDpXLmVhLFNwZWVjaFN5
+bnRoZXNpc0V2ZW50OlcuZWEsU3RvcmFnZUV2ZW50OlcuZWEsU3luY0V2ZW50OlcuZWEsVHJhY2tFdmVu
+dDpXLmVhLFRyYW5zaXRpb25FdmVudDpXLmVhLFdlYktpdFRyYW5zaXRpb25FdmVudDpXLmVhLFZSRGV2
+aWNlRXZlbnQ6Vy5lYSxWUkRpc3BsYXlFdmVudDpXLmVhLFZSU2Vzc2lvbkV2ZW50OlcuZWEsTW9qb0lu
+dGVyZmFjZVJlcXVlc3RFdmVudDpXLmVhLFVTQkNvbm5lY3Rpb25FdmVudDpXLmVhLElEQlZlcnNpb25D
+aGFuZ2VFdmVudDpXLmVhLEF1ZGlvUHJvY2Vzc2luZ0V2ZW50OlcuZWEsT2ZmbGluZUF1ZGlvQ29tcGxl
+dGlvbkV2ZW50OlcuZWEsV2ViR0xDb250ZXh0RXZlbnQ6Vy5lYSxFdmVudDpXLmVhLElucHV0RXZlbnQ6
+Vy5lYSxTdWJtaXRFdmVudDpXLmVhLEV2ZW50VGFyZ2V0OlcuRDAsRmlsZTpXLmhILEhUTUxGb3JtRWxl
+bWVudDpXLmg0LEhpc3Rvcnk6Vy5icixIVE1MRG9jdW1lbnQ6Vy5WYixYTUxIdHRwUmVxdWVzdDpXLmZK
+LFhNTEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6Vy53YSxJbWFnZURhdGE6Vy5TZyxMb2NhdGlvbjpXLnc3
+LE1vdXNlRXZlbnQ6Vy5BaixEcmFnRXZlbnQ6Vy5BaixQb2ludGVyRXZlbnQ6Vy5BaixXaGVlbEV2ZW50
+OlcuQWosRG9jdW1lbnRGcmFnbWVudDpXLnVILFNoYWRvd1Jvb3Q6Vy51SCxEb2N1bWVudFR5cGU6Vy51
+SCxOb2RlOlcudUgsTm9kZUxpc3Q6Vy5CSCxSYWRpb05vZGVMaXN0OlcuQkgsSFRNTFBhcmFncmFwaEVs
+ZW1lbnQ6Vy5TTixQcm9ncmVzc0V2ZW50OlcuZXcsUmVzb3VyY2VQcm9ncmVzc0V2ZW50OlcuZXcsSFRN
+TFNlbGVjdEVsZW1lbnQ6Vy5scCxIVE1MVGFibGVFbGVtZW50OlcuVGIsSFRNTFRhYmxlUm93RWxlbWVu
+dDpXLkl2LEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OlcuV1AsSFRNTFRlbXBsYXRlRWxlbWVudDpXLnlZ
+LENvbXBvc2l0aW9uRXZlbnQ6Vy53NixGb2N1c0V2ZW50OlcudzYsS2V5Ym9hcmRFdmVudDpXLnc2LFRl
+eHRFdmVudDpXLnc2LFRvdWNoRXZlbnQ6Vy53NixVSUV2ZW50OlcudzYsV2luZG93OlcuSzUsRE9NV2lu
+ZG93OlcuSzUsRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxTZXJ2aWNlV29ya2VyR2xvYmFs
+U2NvcGU6Vy5DbSxTaGFyZWRXb3JrZXJHbG9iYWxTY29wZTpXLkNtLFdvcmtlckdsb2JhbFNjb3BlOlcu
+Q20sQXR0cjpXLkNRLENsaWVudFJlY3Q6Vy53NCxET01SZWN0OlcudzQsTmFtZWROb2RlTWFwOlcucmgs
+TW96TmFtZWRBdHRyTWFwOlcucmgsSURCS2V5UmFuZ2U6UC5oRixTVkdTY3JpcHRFbGVtZW50OlAubmQs
+U1ZHQUVsZW1lbnQ6UC5oaSxTVkdBbmltYXRlRWxlbWVudDpQLmhpLFNWR0FuaW1hdGVNb3Rpb25FbGVt
+ZW50OlAuaGksU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1lbnQ6UC5oaSxTVkdBbmltYXRpb25FbGVtZW50
+OlAuaGksU1ZHQ2lyY2xlRWxlbWVudDpQLmhpLFNWR0NsaXBQYXRoRWxlbWVudDpQLmhpLFNWR0RlZnNF
+bGVtZW50OlAuaGksU1ZHRGVzY0VsZW1lbnQ6UC5oaSxTVkdEaXNjYXJkRWxlbWVudDpQLmhpLFNWR0Vs
+bGlwc2VFbGVtZW50OlAuaGksU1ZHRkVCbGVuZEVsZW1lbnQ6UC5oaSxTVkdGRUNvbG9yTWF0cml4RWxl
+bWVudDpQLmhpLFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJFbGVtZW50OlAuaGksU1ZHRkVDb21wb3NpdGVF
+bGVtZW50OlAuaGksU1ZHRkVDb252b2x2ZU1hdHJpeEVsZW1lbnQ6UC5oaSxTVkdGRURpZmZ1c2VMaWdo
+dGluZ0VsZW1lbnQ6UC5oaSxTVkdGRURpc3BsYWNlbWVudE1hcEVsZW1lbnQ6UC5oaSxTVkdGRURpc3Rh
+bnRMaWdodEVsZW1lbnQ6UC5oaSxTVkdGRUZsb29kRWxlbWVudDpQLmhpLFNWR0ZFRnVuY0FFbGVtZW50
+OlAuaGksU1ZHRkVGdW5jQkVsZW1lbnQ6UC5oaSxTVkdGRUZ1bmNHRWxlbWVudDpQLmhpLFNWR0ZFRnVu
+Y1JFbGVtZW50OlAuaGksU1ZHRkVHYXVzc2lhbkJsdXJFbGVtZW50OlAuaGksU1ZHRkVJbWFnZUVsZW1l
+bnQ6UC5oaSxTVkdGRU1lcmdlRWxlbWVudDpQLmhpLFNWR0ZFTWVyZ2VOb2RlRWxlbWVudDpQLmhpLFNW
+R0ZFTW9ycGhvbG9neUVsZW1lbnQ6UC5oaSxTVkdGRU9mZnNldEVsZW1lbnQ6UC5oaSxTVkdGRVBvaW50
+TGlnaHRFbGVtZW50OlAuaGksU1ZHRkVTcGVjdWxhckxpZ2h0aW5nRWxlbWVudDpQLmhpLFNWR0ZFU3Bv
+dExpZ2h0RWxlbWVudDpQLmhpLFNWR0ZFVGlsZUVsZW1lbnQ6UC5oaSxTVkdGRVR1cmJ1bGVuY2VFbGVt
+ZW50OlAuaGksU1ZHRmlsdGVyRWxlbWVudDpQLmhpLFNWR0ZvcmVpZ25PYmplY3RFbGVtZW50OlAuaGks
+U1ZHR0VsZW1lbnQ6UC5oaSxTVkdHZW9tZXRyeUVsZW1lbnQ6UC5oaSxTVkdHcmFwaGljc0VsZW1lbnQ6
+UC5oaSxTVkdJbWFnZUVsZW1lbnQ6UC5oaSxTVkdMaW5lRWxlbWVudDpQLmhpLFNWR0xpbmVhckdyYWRp
+ZW50RWxlbWVudDpQLmhpLFNWR01hcmtlckVsZW1lbnQ6UC5oaSxTVkdNYXNrRWxlbWVudDpQLmhpLFNW
+R01ldGFkYXRhRWxlbWVudDpQLmhpLFNWR1BhdGhFbGVtZW50OlAuaGksU1ZHUGF0dGVybkVsZW1lbnQ6
+UC5oaSxTVkdQb2x5Z29uRWxlbWVudDpQLmhpLFNWR1BvbHlsaW5lRWxlbWVudDpQLmhpLFNWR1JhZGlh
+bEdyYWRpZW50RWxlbWVudDpQLmhpLFNWR1JlY3RFbGVtZW50OlAuaGksU1ZHU2V0RWxlbWVudDpQLmhp
+LFNWR1N0b3BFbGVtZW50OlAuaGksU1ZHU3R5bGVFbGVtZW50OlAuaGksU1ZHU1ZHRWxlbWVudDpQLmhp
+LFNWR1N3aXRjaEVsZW1lbnQ6UC5oaSxTVkdTeW1ib2xFbGVtZW50OlAuaGksU1ZHVFNwYW5FbGVtZW50
+OlAuaGksU1ZHVGV4dENvbnRlbnRFbGVtZW50OlAuaGksU1ZHVGV4dEVsZW1lbnQ6UC5oaSxTVkdUZXh0
+UGF0aEVsZW1lbnQ6UC5oaSxTVkdUZXh0UG9zaXRpb25pbmdFbGVtZW50OlAuaGksU1ZHVGl0bGVFbGVt
+ZW50OlAuaGksU1ZHVXNlRWxlbWVudDpQLmhpLFNWR1ZpZXdFbGVtZW50OlAuaGksU1ZHR3JhZGllbnRF
+bGVtZW50OlAuaGksU1ZHQ29tcG9uZW50VHJhbnNmZXJGdW5jdGlvbkVsZW1lbnQ6UC5oaSxTVkdGRURy
+b3BTaGFkb3dFbGVtZW50OlAuaGksU1ZHTVBhdGhFbGVtZW50OlAuaGksU1ZHRWxlbWVudDpQLmhpfSkK
+aHVua0hlbHBlcnMuc2V0T3JVcGRhdGVMZWFmVGFncyh7RE9NRXJyb3I6dHJ1ZSxNZWRpYUVycm9yOnRy
+dWUsTmF2aWdhdG9yOnRydWUsTmF2aWdhdG9yQ29uY3VycmVudEhhcmR3YXJlOnRydWUsTmF2aWdhdG9y
+VXNlck1lZGlhRXJyb3I6dHJ1ZSxPdmVyY29uc3RyYWluZWRFcnJvcjp0cnVlLFBvc2l0aW9uRXJyb3I6
+dHJ1ZSxSYW5nZTp0cnVlLFNRTEVycm9yOnRydWUsRGF0YVZpZXc6dHJ1ZSxBcnJheUJ1ZmZlclZpZXc6
+ZmFsc2UsRmxvYXQzMkFycmF5OnRydWUsRmxvYXQ2NEFycmF5OnRydWUsSW50MTZBcnJheTp0cnVlLElu
+dDMyQXJyYXk6dHJ1ZSxJbnQ4QXJyYXk6dHJ1ZSxVaW50MTZBcnJheTp0cnVlLFVpbnQzMkFycmF5OnRy
+dWUsVWludDhDbGFtcGVkQXJyYXk6dHJ1ZSxDYW52YXNQaXhlbEFycmF5OnRydWUsVWludDhBcnJheTpm
+YWxzZSxIVE1MQXVkaW9FbGVtZW50OnRydWUsSFRNTEJSRWxlbWVudDp0cnVlLEhUTUxCdXR0b25FbGVt
+ZW50OnRydWUsSFRNTENhbnZhc0VsZW1lbnQ6dHJ1ZSxIVE1MQ29udGVudEVsZW1lbnQ6dHJ1ZSxIVE1M
+RExpc3RFbGVtZW50OnRydWUsSFRNTERhdGFFbGVtZW50OnRydWUsSFRNTERhdGFMaXN0RWxlbWVudDp0
+cnVlLEhUTUxEZXRhaWxzRWxlbWVudDp0cnVlLEhUTUxEaWFsb2dFbGVtZW50OnRydWUsSFRNTERpdkVs
+ZW1lbnQ6dHJ1ZSxIVE1MRW1iZWRFbGVtZW50OnRydWUsSFRNTEZpZWxkU2V0RWxlbWVudDp0cnVlLEhU
+TUxIUkVsZW1lbnQ6dHJ1ZSxIVE1MSGVhZEVsZW1lbnQ6dHJ1ZSxIVE1MSGVhZGluZ0VsZW1lbnQ6dHJ1
+ZSxIVE1MSHRtbEVsZW1lbnQ6dHJ1ZSxIVE1MSUZyYW1lRWxlbWVudDp0cnVlLEhUTUxJbWFnZUVsZW1l
+bnQ6dHJ1ZSxIVE1MSW5wdXRFbGVtZW50OnRydWUsSFRNTExJRWxlbWVudDp0cnVlLEhUTUxMYWJlbEVs
+ZW1lbnQ6dHJ1ZSxIVE1MTGVnZW5kRWxlbWVudDp0cnVlLEhUTUxMaW5rRWxlbWVudDp0cnVlLEhUTUxN
+YXBFbGVtZW50OnRydWUsSFRNTE1lZGlhRWxlbWVudDp0cnVlLEhUTUxNZW51RWxlbWVudDp0cnVlLEhU
+TUxNZXRhRWxlbWVudDp0cnVlLEhUTUxNZXRlckVsZW1lbnQ6dHJ1ZSxIVE1MTW9kRWxlbWVudDp0cnVl
+LEhUTUxPTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MT2JqZWN0RWxlbWVudDp0cnVlLEhUTUxPcHRHcm91cEVs
+ZW1lbnQ6dHJ1ZSxIVE1MT3B0aW9uRWxlbWVudDp0cnVlLEhUTUxPdXRwdXRFbGVtZW50OnRydWUsSFRN
+TFBhcmFtRWxlbWVudDp0cnVlLEhUTUxQaWN0dXJlRWxlbWVudDp0cnVlLEhUTUxQcmVFbGVtZW50OnRy
+dWUsSFRNTFByb2dyZXNzRWxlbWVudDp0cnVlLEhUTUxRdW90ZUVsZW1lbnQ6dHJ1ZSxIVE1MU2NyaXB0
+RWxlbWVudDp0cnVlLEhUTUxTaGFkb3dFbGVtZW50OnRydWUsSFRNTFNsb3RFbGVtZW50OnRydWUsSFRN
+TFNvdXJjZUVsZW1lbnQ6dHJ1ZSxIVE1MU3BhbkVsZW1lbnQ6dHJ1ZSxIVE1MU3R5bGVFbGVtZW50OnRy
+dWUsSFRNTFRhYmxlQ2FwdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVDZWxsRWxlbWVudDp0cnVlLEhU
+TUxUYWJsZURhdGFDZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZUhlYWRlckNlbGxFbGVtZW50OnRydWUs
+SFRNTFRhYmxlQ29sRWxlbWVudDp0cnVlLEhUTUxUZXh0QXJlYUVsZW1lbnQ6dHJ1ZSxIVE1MVGltZUVs
+ZW1lbnQ6dHJ1ZSxIVE1MVGl0bGVFbGVtZW50OnRydWUsSFRNTFRyYWNrRWxlbWVudDp0cnVlLEhUTUxV
+TGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MVW5rbm93bkVsZW1lbnQ6dHJ1ZSxIVE1MVmlkZW9FbGVtZW50OnRy
+dWUsSFRNTERpcmVjdG9yeUVsZW1lbnQ6dHJ1ZSxIVE1MRm9udEVsZW1lbnQ6dHJ1ZSxIVE1MRnJhbWVF
+bGVtZW50OnRydWUsSFRNTEZyYW1lU2V0RWxlbWVudDp0cnVlLEhUTUxNYXJxdWVlRWxlbWVudDp0cnVl
+LEhUTUxFbGVtZW50OmZhbHNlLEhUTUxBbmNob3JFbGVtZW50OnRydWUsSFRNTEFyZWFFbGVtZW50OnRy
+dWUsSFRNTEJhc2VFbGVtZW50OnRydWUsQmxvYjpmYWxzZSxIVE1MQm9keUVsZW1lbnQ6dHJ1ZSxDREFU
+QVNlY3Rpb246dHJ1ZSxDaGFyYWN0ZXJEYXRhOnRydWUsQ29tbWVudDp0cnVlLFByb2Nlc3NpbmdJbnN0
+cnVjdGlvbjp0cnVlLFRleHQ6dHJ1ZSxDU1NTdHlsZURlY2xhcmF0aW9uOnRydWUsTVNTdHlsZUNTU1By
+b3BlcnRpZXM6dHJ1ZSxDU1MyUHJvcGVydGllczp0cnVlLFhNTERvY3VtZW50OnRydWUsRG9jdW1lbnQ6
+ZmFsc2UsRE9NRXhjZXB0aW9uOnRydWUsRE9NSW1wbGVtZW50YXRpb246dHJ1ZSxET01SZWN0UmVhZE9u
+bHk6ZmFsc2UsRE9NVG9rZW5MaXN0OnRydWUsRWxlbWVudDpmYWxzZSxBYm9ydFBheW1lbnRFdmVudDp0
+cnVlLEFuaW1hdGlvbkV2ZW50OnRydWUsQW5pbWF0aW9uUGxheWJhY2tFdmVudDp0cnVlLEFwcGxpY2F0
+aW9uQ2FjaGVFcnJvckV2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoQ2xpY2tFdmVudDp0cnVlLEJhY2tn
+cm91bmRGZXRjaEV2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoRmFpbEV2ZW50OnRydWUsQmFja2dyb3Vu
+ZEZldGNoZWRFdmVudDp0cnVlLEJlZm9yZUluc3RhbGxQcm9tcHRFdmVudDp0cnVlLEJlZm9yZVVubG9h
+ZEV2ZW50OnRydWUsQmxvYkV2ZW50OnRydWUsQ2FuTWFrZVBheW1lbnRFdmVudDp0cnVlLENsaXBib2Fy
+ZEV2ZW50OnRydWUsQ2xvc2VFdmVudDp0cnVlLEN1c3RvbUV2ZW50OnRydWUsRGV2aWNlTW90aW9uRXZl
+bnQ6dHJ1ZSxEZXZpY2VPcmllbnRhdGlvbkV2ZW50OnRydWUsRXJyb3JFdmVudDp0cnVlLEV4dGVuZGFi
+bGVFdmVudDp0cnVlLEV4dGVuZGFibGVNZXNzYWdlRXZlbnQ6dHJ1ZSxGZXRjaEV2ZW50OnRydWUsRm9u
+dEZhY2VTZXRMb2FkRXZlbnQ6dHJ1ZSxGb3JlaWduRmV0Y2hFdmVudDp0cnVlLEdhbWVwYWRFdmVudDp0
+cnVlLEhhc2hDaGFuZ2VFdmVudDp0cnVlLEluc3RhbGxFdmVudDp0cnVlLE1lZGlhRW5jcnlwdGVkRXZl
+bnQ6dHJ1ZSxNZWRpYUtleU1lc3NhZ2VFdmVudDp0cnVlLE1lZGlhUXVlcnlMaXN0RXZlbnQ6dHJ1ZSxN
+ZWRpYVN0cmVhbUV2ZW50OnRydWUsTWVkaWFTdHJlYW1UcmFja0V2ZW50OnRydWUsTWVzc2FnZUV2ZW50
+OnRydWUsTUlESUNvbm5lY3Rpb25FdmVudDp0cnVlLE1JRElNZXNzYWdlRXZlbnQ6dHJ1ZSxNdXRhdGlv
+bkV2ZW50OnRydWUsTm90aWZpY2F0aW9uRXZlbnQ6dHJ1ZSxQYWdlVHJhbnNpdGlvbkV2ZW50OnRydWUs
+UGF5bWVudFJlcXVlc3RFdmVudDp0cnVlLFBheW1lbnRSZXF1ZXN0VXBkYXRlRXZlbnQ6dHJ1ZSxQb3BT
+dGF0ZUV2ZW50OnRydWUsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkF2YWlsYWJsZUV2ZW50OnRydWUsUHJl
+c2VudGF0aW9uQ29ubmVjdGlvbkNsb3NlRXZlbnQ6dHJ1ZSxQcm9taXNlUmVqZWN0aW9uRXZlbnQ6dHJ1
+ZSxQdXNoRXZlbnQ6dHJ1ZSxSVENEYXRhQ2hhbm5lbEV2ZW50OnRydWUsUlRDRFRNRlRvbmVDaGFuZ2VF
+dmVudDp0cnVlLFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQ6dHJ1ZSxSVENUcmFja0V2ZW50OnRydWUs
+U2VjdXJpdHlQb2xpY3lWaW9sYXRpb25FdmVudDp0cnVlLFNlbnNvckVycm9yRXZlbnQ6dHJ1ZSxTcGVl
+Y2hSZWNvZ25pdGlvbkVycm9yOnRydWUsU3BlZWNoUmVjb2duaXRpb25FdmVudDp0cnVlLFNwZWVjaFN5
+bnRoZXNpc0V2ZW50OnRydWUsU3RvcmFnZUV2ZW50OnRydWUsU3luY0V2ZW50OnRydWUsVHJhY2tFdmVu
+dDp0cnVlLFRyYW5zaXRpb25FdmVudDp0cnVlLFdlYktpdFRyYW5zaXRpb25FdmVudDp0cnVlLFZSRGV2
+aWNlRXZlbnQ6dHJ1ZSxWUkRpc3BsYXlFdmVudDp0cnVlLFZSU2Vzc2lvbkV2ZW50OnRydWUsTW9qb0lu
+dGVyZmFjZVJlcXVlc3RFdmVudDp0cnVlLFVTQkNvbm5lY3Rpb25FdmVudDp0cnVlLElEQlZlcnNpb25D
+aGFuZ2VFdmVudDp0cnVlLEF1ZGlvUHJvY2Vzc2luZ0V2ZW50OnRydWUsT2ZmbGluZUF1ZGlvQ29tcGxl
+dGlvbkV2ZW50OnRydWUsV2ViR0xDb250ZXh0RXZlbnQ6dHJ1ZSxFdmVudDpmYWxzZSxJbnB1dEV2ZW50
+OmZhbHNlLFN1Ym1pdEV2ZW50OmZhbHNlLEV2ZW50VGFyZ2V0OmZhbHNlLEZpbGU6dHJ1ZSxIVE1MRm9y
+bUVsZW1lbnQ6dHJ1ZSxIaXN0b3J5OnRydWUsSFRNTERvY3VtZW50OnRydWUsWE1MSHR0cFJlcXVlc3Q6
+dHJ1ZSxYTUxIdHRwUmVxdWVzdEV2ZW50VGFyZ2V0OmZhbHNlLEltYWdlRGF0YTp0cnVlLExvY2F0aW9u
+OnRydWUsTW91c2VFdmVudDp0cnVlLERyYWdFdmVudDp0cnVlLFBvaW50ZXJFdmVudDp0cnVlLFdoZWVs
+RXZlbnQ6dHJ1ZSxEb2N1bWVudEZyYWdtZW50OnRydWUsU2hhZG93Um9vdDp0cnVlLERvY3VtZW50VHlw
+ZTp0cnVlLE5vZGU6ZmFsc2UsTm9kZUxpc3Q6dHJ1ZSxSYWRpb05vZGVMaXN0OnRydWUsSFRNTFBhcmFn
+cmFwaEVsZW1lbnQ6dHJ1ZSxQcm9ncmVzc0V2ZW50OnRydWUsUmVzb3VyY2VQcm9ncmVzc0V2ZW50OnRy
+dWUsSFRNTFNlbGVjdEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVFbGVtZW50OnRydWUsSFRNTFRhYmxlUm93
+RWxlbWVudDp0cnVlLEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OnRydWUsSFRNTFRlbXBsYXRlRWxlbWVu
+dDp0cnVlLENvbXBvc2l0aW9uRXZlbnQ6dHJ1ZSxGb2N1c0V2ZW50OnRydWUsS2V5Ym9hcmRFdmVudDp0
+cnVlLFRleHRFdmVudDp0cnVlLFRvdWNoRXZlbnQ6dHJ1ZSxVSUV2ZW50OmZhbHNlLFdpbmRvdzp0cnVl
+LERPTVdpbmRvdzp0cnVlLERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOnRydWUsU2VydmljZVdvcmtl
+ckdsb2JhbFNjb3BlOnRydWUsU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxXb3JrZXJHbG9iYWxT
+Y29wZTp0cnVlLEF0dHI6dHJ1ZSxDbGllbnRSZWN0OnRydWUsRE9NUmVjdDp0cnVlLE5hbWVkTm9kZU1h
+cDp0cnVlLE1vek5hbWVkQXR0ck1hcDp0cnVlLElEQktleVJhbmdlOnRydWUsU1ZHU2NyaXB0RWxlbWVu
+dDp0cnVlLFNWR0FFbGVtZW50OnRydWUsU1ZHQW5pbWF0ZUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlTW90
+aW9uRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVUcmFuc2Zvcm1FbGVtZW50OnRydWUsU1ZHQW5pbWF0aW9u
+RWxlbWVudDp0cnVlLFNWR0NpcmNsZUVsZW1lbnQ6dHJ1ZSxTVkdDbGlwUGF0aEVsZW1lbnQ6dHJ1ZSxT
+VkdEZWZzRWxlbWVudDp0cnVlLFNWR0Rlc2NFbGVtZW50OnRydWUsU1ZHRGlzY2FyZEVsZW1lbnQ6dHJ1
+ZSxTVkdFbGxpcHNlRWxlbWVudDp0cnVlLFNWR0ZFQmxlbmRFbGVtZW50OnRydWUsU1ZHRkVDb2xvck1h
+dHJpeEVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbXBvbmVudFRyYW5zZmVyRWxlbWVudDp0cnVlLFNWR0ZFQ29t
+cG9zaXRlRWxlbWVudDp0cnVlLFNWR0ZFQ29udm9sdmVNYXRyaXhFbGVtZW50OnRydWUsU1ZHRkVEaWZm
+dXNlTGlnaHRpbmdFbGVtZW50OnRydWUsU1ZHRkVEaXNwbGFjZW1lbnRNYXBFbGVtZW50OnRydWUsU1ZH
+RkVEaXN0YW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVGbG9vZEVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNB
+RWxlbWVudDp0cnVlLFNWR0ZFRnVuY0JFbGVtZW50OnRydWUsU1ZHRkVGdW5jR0VsZW1lbnQ6dHJ1ZSxT
+VkdGRUZ1bmNSRWxlbWVudDp0cnVlLFNWR0ZFR2F1c3NpYW5CbHVyRWxlbWVudDp0cnVlLFNWR0ZFSW1h
+Z2VFbGVtZW50OnRydWUsU1ZHRkVNZXJnZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1lcmdlTm9kZUVsZW1lbnQ6
+dHJ1ZSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OnRydWUsU1ZHRkVPZmZzZXRFbGVtZW50OnRydWUsU1ZH
+RkVQb2ludExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFU3BlY3VsYXJMaWdodGluZ0VsZW1lbnQ6dHJ1ZSxT
+VkdGRVNwb3RMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRVRpbGVFbGVtZW50OnRydWUsU1ZHRkVUdXJidWxl
+bmNlRWxlbWVudDp0cnVlLFNWR0ZpbHRlckVsZW1lbnQ6dHJ1ZSxTVkdGb3JlaWduT2JqZWN0RWxlbWVu
+dDp0cnVlLFNWR0dFbGVtZW50OnRydWUsU1ZHR2VvbWV0cnlFbGVtZW50OnRydWUsU1ZHR3JhcGhpY3NF
+bGVtZW50OnRydWUsU1ZHSW1hZ2VFbGVtZW50OnRydWUsU1ZHTGluZUVsZW1lbnQ6dHJ1ZSxTVkdMaW5l
+YXJHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdNYXJrZXJFbGVtZW50OnRydWUsU1ZHTWFza0VsZW1lbnQ6
+dHJ1ZSxTVkdNZXRhZGF0YUVsZW1lbnQ6dHJ1ZSxTVkdQYXRoRWxlbWVudDp0cnVlLFNWR1BhdHRlcm5F
+bGVtZW50OnRydWUsU1ZHUG9seWdvbkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5bGluZUVsZW1lbnQ6dHJ1ZSxT
+VkdSYWRpYWxHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdSZWN0RWxlbWVudDp0cnVlLFNWR1NldEVsZW1l
+bnQ6dHJ1ZSxTVkdTdG9wRWxlbWVudDp0cnVlLFNWR1N0eWxlRWxlbWVudDp0cnVlLFNWR1NWR0VsZW1l
+bnQ6dHJ1ZSxTVkdTd2l0Y2hFbGVtZW50OnRydWUsU1ZHU3ltYm9sRWxlbWVudDp0cnVlLFNWR1RTcGFu
+RWxlbWVudDp0cnVlLFNWR1RleHRDb250ZW50RWxlbWVudDp0cnVlLFNWR1RleHRFbGVtZW50OnRydWUs
+U1ZHVGV4dFBhdGhFbGVtZW50OnRydWUsU1ZHVGV4dFBvc2l0aW9uaW5nRWxlbWVudDp0cnVlLFNWR1Rp
+dGxlRWxlbWVudDp0cnVlLFNWR1VzZUVsZW1lbnQ6dHJ1ZSxTVkdWaWV3RWxlbWVudDp0cnVlLFNWR0dy
+YWRpZW50RWxlbWVudDp0cnVlLFNWR0NvbXBvbmVudFRyYW5zZmVyRnVuY3Rpb25FbGVtZW50OnRydWUs
+U1ZHRkVEcm9wU2hhZG93RWxlbWVudDp0cnVlLFNWR01QYXRoRWxlbWVudDp0cnVlLFNWR0VsZW1lbnQ6
+ZmFsc2V9KQpILkxaLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguUkcuJG5h
+dGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5WUC4kbmF0aXZlU3VwZXJjbGFzc1Rh
+Zz0iQXJyYXlCdWZmZXJWaWV3IgpILkRnLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZp
+ZXciCkguV0IuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5aRy4kbmF0aXZl
+U3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlBnLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJB
+cnJheUJ1ZmZlclZpZXcifSkoKQpjb252ZXJ0QWxsVG9GYXN0T2JqZWN0KHcpCmNvbnZlcnRUb0Zhc3RP
+YmplY3QoJCk7KGZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBkb2N1bWVudD09PSJ1bmRlZmluZWQiKXthKG51
+bGwpCnJldHVybn1pZih0eXBlb2YgZG9jdW1lbnQuY3VycmVudFNjcmlwdCE9InVuZGVmaW5lZCIpe2Eo
+ZG9jdW1lbnQuY3VycmVudFNjcmlwdCkKcmV0dXJufXZhciBzPWRvY3VtZW50LnNjcmlwdHMKZnVuY3Rp
+b24gb25Mb2FkKGIpe2Zvcih2YXIgcT0wO3E8cy5sZW5ndGg7KytxKXNbcV0ucmVtb3ZlRXZlbnRMaXN0
+ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKQphKGIudGFyZ2V0KX1mb3IodmFyIHI9MDtyPHMubGVuZ3Ro
+OysrcilzW3JdLmFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLG9uTG9hZCxmYWxzZSl9KShmdW5jdGlvbihh
+KXt2LmN1cnJlbnRTY3JpcHQ9YQp2YXIgcz1MLklxCmlmKHR5cGVvZiBkYXJ0TWFpblJ1bm5lcj09PSJm
+dW5jdGlvbiIpZGFydE1haW5SdW5uZXIocyxbXSkKZWxzZSBzKFtdKX0pfSkoKQovLyMgc291cmNlTWFw
+cGluZ1VSTD1taWdyYXRpb24uanMubWFwCg==
 ''';
diff --git a/pkg/nnbd_migration/lib/src/front_end/unit_link.dart b/pkg/nnbd_migration/lib/src/front_end/unit_link.dart
index c345775..bbf031b 100644
--- a/pkg/nnbd_migration/lib/src/front_end/unit_link.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/unit_link.dart
@@ -19,10 +19,19 @@
   /// the start of this migration.
   final bool wasExplicitlyOptedOut;
 
-  UnitMigrationStatus migrationStatus;
+  final UnitMigrationStatus migrationStatus;
 
-  UnitLink(this.fullPath, this.pathParts, this.editCount,
-      this.wasExplicitlyOptedOut, this.migrationStatus)
+  /// Whether the migration status of this compilation unit can be changed in
+  /// the web interface.
+  final bool migrationStatusCanBeChanged;
+
+  UnitLink(
+      this.fullPath,
+      this.pathParts,
+      this.editCount,
+      this.wasExplicitlyOptedOut,
+      this.migrationStatus,
+      this.migrationStatusCanBeChanged)
       : depth = pathParts.length - 1;
 
   String get fileName => pathParts.last;
diff --git a/pkg/nnbd_migration/lib/src/front_end/web/edit_details.dart b/pkg/nnbd_migration/lib/src/front_end/web/edit_details.dart
index b416b03..f5ad437 100644
--- a/pkg/nnbd_migration/lib/src/front_end/web/edit_details.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/web/edit_details.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:meta/meta.dart';
-import 'package:nnbd_migration/src/front_end/migration_info.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 
 /// Information about what should be populated into the "Edit Details" view of
 /// the migration preview tool.
diff --git a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
index e98bbea..7a5de1c 100644
--- a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
@@ -2,15 +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.
 
+// Explicitly opt out this file from null safety, for build reasons, inside
+// Google.
+// @dart=2.9
+
 import 'dart:async';
 import 'dart:convert';
 import 'dart:html';
 
-import 'package:nnbd_migration/instrumentation.dart';
-import 'package:nnbd_migration/src/front_end/migration_info.dart';
 import 'package:nnbd_migration/src/front_end/web/edit_details.dart';
 import 'package:nnbd_migration/src/front_end/web/file_details.dart';
 import 'package:nnbd_migration/src/front_end/web/navigation_tree.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:path/path.dart' as _p;
 
 import 'highlight_js.dart';
@@ -38,7 +41,11 @@
           "This will apply the changes you've previewed to your working "
           'directory. It is recommended you commit any changes you made before '
           'doing this.')) {
-        doPost('/apply-migration').then((xhr) {
+        var navigationTreeJson = [
+          for (var entity in navigationTree) entity.toJson()
+        ];
+        doPost('/apply-migration', {'navigationTree': navigationTreeJson})
+            .then((xhr) {
           document.body.classes
             ..remove('proposed')
             ..add('applied');
@@ -80,7 +87,8 @@
           .parentNode as Element;
       var statusIcon = unitNavItem.querySelector('.status-icon');
       var entity = navigationTree.find(unitPath);
-      if (entity is NavigationTreeFileNode) {
+      if (entity is NavigationTreeFileNode &&
+          entity.migrationStatusCanBeChanged) {
         toggleFileMigrationStatus(entity);
         updateIconsForNode(statusIcon, entity);
         updateParentIcons(unitNavItem, entity);
@@ -159,11 +167,7 @@
   // Add navigation handlers for navigation links in the source code.
   List<Element> navLinks = parentElement.querySelectorAll('.nav-link');
   navLinks.forEach((link) {
-    link.onClick.listen((event) {
-      var tableElement = document.querySelector('table[data-path]');
-      var parentPath = tableElement.dataset['path'];
-      handleNavLinkClick(event, clearEditDetails, relativeTo: parentPath);
-    });
+    link.onClick.listen((event) => handleNavLinkClick(event, clearEditDetails));
   });
 
   List<Element> regions = parentElement.querySelectorAll('.region');
@@ -346,11 +350,7 @@
   logError('$header: $exception', stackTrace);
 }
 
-void handleNavLinkClick(
-  MouseEvent event,
-  bool clearEditDetails, {
-  String relativeTo,
-}) {
+void handleNavLinkClick(MouseEvent event, bool clearEditDetails) {
   Element target = event.currentTarget as Element;
   event.preventDefault();
 
@@ -454,13 +454,13 @@
     navTree.innerHtml = '';
     navigationTree = NavigationTreeNode.listFromJson(response);
     writeNavigationSubtree(navTree, navigationTree,
-        enablePartialMigration: false);
+        enablePartialMigration: true);
   } catch (e, st) {
     handleError('Could not load navigation tree', e, st);
   }
 }
 
-void logError(e, st) {
+void logError(Object e, Object st) {
   window.console.error('$e');
   window.console.error('$st');
 }
@@ -733,12 +733,19 @@
 /// Updates the navigation [icon] and current file icon according to the current
 /// migration status of [entity].
 void updateIconsForNode(Element icon, NavigationTreeNode entity) {
-  updateIconForStatus(icon, entity.migrationStatus);
+  var status = entity.migrationStatus;
+  updateIconForStatus(icon, status);
   // Update the status at the top of the file view if [entity] represents the
   // current file.
   var unitPath = unitName.innerText;
   if (entity.path == unitPath) {
-    updateIconForStatus(migrateUnitStatusIcon, entity.migrationStatus);
+    if (entity is NavigationTreeFileNode &&
+        !entity.migrationStatusCanBeChanged) {
+      icon.classes.add('disabled');
+    } else {
+      icon.classes.remove('disabled');
+    }
+    updateIconForStatus(migrateUnitStatusIcon, status);
   }
 }
 
@@ -748,6 +755,7 @@
     case UnitMigrationStatus.alreadyMigrated:
       icon.innerText = 'check_box';
       icon.classes.add('already-migrated');
+      icon.classes.add('disabled');
       icon.setAttribute('title', 'Already migrated');
       break;
     case UnitMigrationStatus.migrating:
@@ -789,7 +797,14 @@
       link.classes.remove('selected-file');
     }
   });
-  migrateUnitStatusIconLabel.classes.add('visible');
+  var entity = navigationTree.find(path);
+  // Update migration status for files in current migration.
+  if (entity == null) {
+    migrateUnitStatusIconLabel.classes.remove('visible');
+  } else {
+    migrateUnitStatusIconLabel.classes.add('visible');
+    updateIconForStatus(migrateUnitStatusIcon, entity.migrationStatus);
+  }
 }
 
 /// Updates the parent icons of [entity] with list item [element] in the
@@ -874,12 +889,18 @@
     } else if (entity is NavigationTreeFileNode) {
       if (enablePartialMigration) {
         var statusIcon = createIcon()..classes.add('status-icon');
+        if (entity is NavigationTreeFileNode &&
+            !entity.migrationStatusCanBeChanged) {
+          statusIcon.classes.add('disabled');
+        }
         updateIconsForNode(statusIcon, entity);
-        statusIcon.onClick.listen((MouseEvent event) {
-          toggleFileMigrationStatus(entity);
-          updateIconsForNode(statusIcon, entity);
-          updateParentIcons(li, entity);
-        });
+        if (entity.migrationStatusCanBeChanged) {
+          statusIcon.onClick.listen((MouseEvent event) {
+            toggleFileMigrationStatus(entity);
+            updateIconsForNode(statusIcon, entity);
+            updateParentIcons(li, entity);
+          });
+        }
         li.append(statusIcon);
       }
       li.append(createIcon('insert_drive_file'));
diff --git a/pkg/nnbd_migration/lib/src/front_end/web/navigation_tree.dart b/pkg/nnbd_migration/lib/src/front_end/web/navigation_tree.dart
index ca96d0b..f322e41 100644
--- a/pkg/nnbd_migration/lib/src/front_end/web/navigation_tree.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/web/navigation_tree.dart
@@ -76,6 +76,7 @@
       if (child is NavigationTreeDirectoryNode) {
         child.toggleChildrenToMigrate();
       } else if (child is NavigationTreeFileNode &&
+          child.migrationStatusCanBeChanged &&
           child.migrationStatus == UnitMigrationStatus.optingOut) {
         child.migrationStatus = UnitMigrationStatus.migrating;
       }
@@ -90,6 +91,7 @@
       if (child is NavigationTreeDirectoryNode) {
         child.toggleChildrenToOptOut();
       } else if (child is NavigationTreeFileNode &&
+          child.migrationStatusCanBeChanged &&
           child.migrationStatus == UnitMigrationStatus.migrating) {
         child.migrationStatus = UnitMigrationStatus.optingOut;
       }
@@ -117,6 +119,8 @@
 
   UnitMigrationStatus migrationStatus;
 
+  final bool migrationStatusCanBeChanged;
+
   /// Creates a navigation tree node representing a file.
   NavigationTreeFileNode(
       {@required String name,
@@ -124,7 +128,8 @@
       @required this.href,
       @required this.editCount,
       @required this.wasExplicitlyOptedOut,
-      @required this.migrationStatus})
+      @required this.migrationStatus,
+      @required this.migrationStatusCanBeChanged})
       : super._(name: name, path: path);
 
   NavigationTreeNodeType get type => NavigationTreeNodeType.file;
@@ -138,6 +143,8 @@
         if (wasExplicitlyOptedOut != null)
           'wasExplicitlyOptedOut': wasExplicitlyOptedOut,
         if (migrationStatus != null) 'migrationStatus': migrationStatus.index,
+        if (migrationStatusCanBeChanged != null)
+          'migrationStatusCanBeChanged': migrationStatusCanBeChanged,
       };
 }
 
@@ -162,13 +169,15 @@
         ..setSubtreeParents();
     } else {
       return NavigationTreeFileNode(
-          name: json['name'] as String,
-          path: json['path'] as String,
-          href: json['href'] as String,
-          editCount: json['editCount'] as int,
-          wasExplicitlyOptedOut: json['wasExplicitlyOptedOut'] as bool,
-          migrationStatus:
-              _decodeMigrationStatus(json['migrationStatus'] as int));
+        name: json['name'] as String,
+        path: json['path'] as String,
+        href: json['href'] as String,
+        editCount: json['editCount'] as int,
+        wasExplicitlyOptedOut: json['wasExplicitlyOptedOut'] as bool,
+        migrationStatus: _decodeMigrationStatus(json['migrationStatus'] as int),
+        migrationStatusCanBeChanged:
+            json['migrationStatusCanBeChanged'] as bool,
+      );
     }
   }
 
diff --git a/pkg/nnbd_migration/lib/src/hint_action.dart b/pkg/nnbd_migration/lib/src/hint_action.dart
new file mode 100644
index 0000000..3d2103f
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/hint_action.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.
+
+/// Everything the front end needs to know to tell the server to perform a hint
+/// action.
+class HintAction {
+  final HintActionKind kind;
+  final int nodeId;
+  HintAction(this.kind, this.nodeId);
+
+  HintAction.fromJson(Map<String, Object> json)
+      : nodeId = json['nodeId'] as int,
+        kind = HintActionKind.values
+            .singleWhere((action) => action.index == json['kind']);
+
+  Map<String, Object> toJson() => {
+        'nodeId': nodeId,
+        'kind': kind.index,
+      };
+}
+
+/// Enum describing the possible hints that can be performed on an edge or a
+/// node.
+///
+/// Which actions are available can be built by other visitors, and the hint can
+/// be applied by visitors such as EditPlanner when the user requests it from
+/// the front end.
+enum HintActionKind {
+  /// Add a `/*?*/` hint to a type.
+  addNullableHint,
+
+  /// Add a `/*!*/` hint to a type.
+  addNonNullableHint,
+
+  /// Change a `/*!*/` hint to a `/*?*/` hint.
+  changeToNullableHint,
+
+  /// Change a `/*?*/` hint to a `/*!*/` hint.
+  changeToNonNullableHint,
+
+  /// Remove a `/*?*/` hint.
+  removeNullableHint,
+
+  /// Remove a `/*!*/` hint.
+  removeNonNullableHint,
+}
+
+/// Extension methods to make [HintActionKind] act as a smart enum.
+extension HintActionKindBehaviors on HintActionKind {
+  /// Get the text description of a [HintActionKind], for display to users.
+  String get description {
+    switch (this) {
+      case HintActionKind.addNullableHint:
+        return 'Add /*?*/ hint';
+      case HintActionKind.addNonNullableHint:
+        return 'Add /*!*/ hint';
+      case HintActionKind.removeNullableHint:
+        return 'Remove /*?*/ hint';
+      case HintActionKind.removeNonNullableHint:
+        return 'Remove /*!*/ hint';
+      case HintActionKind.changeToNullableHint:
+        return 'Change to /*?*/ hint';
+      case HintActionKind.changeToNonNullableHint:
+        return 'Change to /*!*/ hint';
+    }
+
+    assert(false);
+    return null;
+  }
+}
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 25a697c..3c5e862 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -15,6 +15,7 @@
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:nnbd_migration/src/utilities/completeness_tracker.dart';
@@ -366,7 +367,9 @@
   DecoratedType visitFunctionTypeAlias(FunctionTypeAlias node) {
     node.metadata.accept(this);
     var declaredElement = node.declaredElement;
-    var functionType = declaredElement.function.type;
+    var functionElement =
+        declaredElement.aliasedElement as GenericFunctionTypeElement;
+    var functionType = functionElement.type;
     var returnType = node.returnType;
     DecoratedType decoratedReturnType;
     var target = NullabilityNodeTarget.element(declaredElement, _getLineInfo);
@@ -400,7 +403,7 @@
       _namedParameters = previousNamedParameters;
     }
     _variables.recordDecoratedElementType(
-        declaredElement.function, decoratedFunctionType);
+        functionElement, decoratedFunctionType);
     return null;
   }
 
@@ -422,7 +425,7 @@
       decoratedFunctionType = node.functionType.accept(this);
     });
     _variables.recordDecoratedElementType(
-        (node.declaredElement as FunctionTypeAliasElement).function,
+        (node.declaredElement as TypeAliasElement).aliasedElement,
         decoratedFunctionType);
     return null;
   }
@@ -469,7 +472,7 @@
   }
 
   @override
-  visitMixinDeclaration(MixinDeclaration node) {
+  DecoratedType visitMixinDeclaration(MixinDeclaration node) {
     node.metadata.accept(this);
     node.name?.accept(this);
     node.typeParameters?.accept(this);
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index e1bda51..85fa200 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -11,6 +11,7 @@
 import 'package:nnbd_migration/nullability_state.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
 import 'package:nnbd_migration/src/expression_checks.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:nnbd_migration/src/nullability_node_target.dart';
 import 'package:nnbd_migration/src/postmortem_file.dart';
 
@@ -1434,22 +1435,6 @@
         var edge = step.edge;
         if (!edge.isTriggered) continue;
         var node = edge.destinationNode;
-        var nonNullIntent = node.nonNullIntent;
-        if (nonNullIntent.isPresent) {
-          if (edge.isCheckable) {
-            // The node has already been marked as having non-null intent, and
-            // the edge can be addressed by adding a null check, so we prefer to
-            // leave the edge unsatisfied and let the null check happen.
-            result.unsatisfiedEdges.add(edge);
-            continue;
-          }
-          if (nonNullIntent.isDirect) {
-            // The node has direct non-null intent so we aren't in a position to
-            // mark it as nullable.
-            result.unsatisfiedEdges.add(edge);
-            continue;
-          }
-        }
         if (edge.isUninit && !node.isNullable) {
           // [edge] is an edge from always to an uninitialized variable
           // declaration.
@@ -1473,6 +1458,22 @@
             continue;
           }
         }
+        var nonNullIntent = node.nonNullIntent;
+        if (nonNullIntent.isPresent) {
+          if (edge.isCheckable) {
+            // The node has already been marked as having non-null intent, and
+            // the edge can be addressed by adding a null check, so we prefer to
+            // leave the edge unsatisfied and let the null check happen.
+            result.unsatisfiedEdges.add(edge);
+            continue;
+          }
+          if (nonNullIntent.isDirect) {
+            // The node has direct non-null intent so we aren't in a position to
+            // mark it as nullable.
+            result.unsatisfiedEdges.add(edge);
+            continue;
+          }
+        }
         if (node is NullabilityNodeMutable && !node.isNullable) {
           assert(step.targetNode == null);
           step.targetNode = node;
diff --git a/pkg/nnbd_migration/lib/src/preview/http_preview_server.dart b/pkg/nnbd_migration/lib/src/preview/http_preview_server.dart
index 105b9f6..c817e97 100644
--- a/pkg/nnbd_migration/lib/src/preview/http_preview_server.dart
+++ b/pkg/nnbd_migration/lib/src/preview/http_preview_server.dart
@@ -4,6 +4,7 @@
 
 import 'dart:io';
 
+import 'package:cli_util/cli_logging.dart';
 import 'package:nnbd_migration/src/front_end/migration_state.dart';
 import 'package:nnbd_migration/src/preview/preview_site.dart';
 
@@ -26,7 +27,7 @@
   final MigrationState migrationState;
 
   /// The [PreviewSite] that can handle GET and POST requests.
-  PreviewSite previewSite;
+  PreviewSite _previewSite;
 
   /// Future that is completed with the HTTP server once it is running.
   Future<HttpServer> _serverFuture;
@@ -47,14 +48,15 @@
   /// [HttpServer.bind] to pick one.
   final int preferredPort;
 
+  final Logger _logger;
+
   /// Initialize a newly created HTTP server.
   HttpPreviewServer(this.migrationState, this.rerunFunction, this.applyHook,
-      this.bindAddress, this.preferredPort)
+      this.bindAddress, this.preferredPort, this._logger)
       : assert(bindAddress is String || bindAddress is InternetAddress);
 
   Future<String> get authToken async {
     await _serverFuture;
-    previewSite ??= PreviewSite(migrationState, rerunFunction, applyHook);
     return previewSite.serviceAuthToken;
   }
 
@@ -68,6 +70,9 @@
     return (await _serverFuture)?.port;
   }
 
+  PreviewSite get previewSite => _previewSite ??=
+      PreviewSite(migrationState, rerunFunction, applyHook, _logger);
+
   void close() {
     _serverFuture?.then((HttpServer server) {
       server.close();
@@ -96,13 +101,11 @@
 
   /// Handle a GET request received by the HTTP server.
   Future<void> _handleGetRequest(HttpRequest request) async {
-    previewSite ??= PreviewSite(migrationState, rerunFunction, applyHook);
     await previewSite.handleGetRequest(request);
   }
 
   /// Handle a POST request received by the HTTP server.
   Future<void> _handlePostRequest(HttpRequest request) async {
-    previewSite ??= PreviewSite(migrationState, rerunFunction, applyHook);
     await previewSite.handlePostRequest(request);
   }
 
diff --git a/pkg/nnbd_migration/lib/src/preview/preview_site.dart b/pkg/nnbd_migration/lib/src/preview/preview_site.dart
index 4fabe98..bd690a9 100644
--- a/pkg/nnbd_migration/lib/src/preview/preview_site.dart
+++ b/pkg/nnbd_migration/lib/src/preview/preview_site.dart
@@ -8,10 +8,15 @@
 import 'dart:typed_data';
 
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:charcode/charcode.dart';
+import 'package:cli_util/cli_logging.dart';
+import 'package:meta/meta.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
 import 'package:nnbd_migration/src/front_end/migration_info.dart';
 import 'package:nnbd_migration/src/front_end/migration_state.dart';
 import 'package:nnbd_migration/src/front_end/path_mapper.dart';
+import 'package:nnbd_migration/src/front_end/web/navigation_tree.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:nnbd_migration/src/preview/dart_file_page.dart';
 import 'package:nnbd_migration/src/preview/dart_logo_page.dart';
 import 'package:nnbd_migration/src/preview/exception_page.dart';
@@ -40,6 +45,229 @@
   return base64Url.encode(bytes);
 }
 
+/// A plan for an incremental migration.
+///
+/// This plan uses [UnitMigrationStatus]es from [NavigationTreeNode]s to apply
+/// different edits to different files:
+///
+/// * migrating files will be edited according to a [SourceFileEdit],
+/// * newly opted out files will be prepended with a Dart Language Version
+///   comment specifying "2.9",
+/// * already opted out files will remain unchanged.
+class IncrementalPlan {
+  static final _nonWhitespaceChar = RegExp(r'\S');
+  final MigrationInfo migrationInfo;
+  final Map<String, UnitInfo> unitInfoMap;
+  final PathMapper pathMapper;
+  final List<SourceFileEdit> edits;
+  final Logger logger;
+
+  /// The set of units which are to be opted out in this migration.
+  final Set<String> optOutUnitPaths;
+
+  /// Creates a new [IncrementalPlan], extracting all of the paths which are
+  /// "opting out" from [navigationTree].
+  factory IncrementalPlan(
+      MigrationInfo migrationInfo,
+      Map<String, UnitInfo> unitInfoMap,
+      PathMapper pathMapper,
+      List<SourceFileEdit> edits,
+      Iterable<NavigationTreeNode> navigationTree,
+      Logger logger) {
+    var optOutUnitPaths = <String>{};
+    void addUnitsToOptOut(NavigationTreeNode entity) {
+      if (entity is NavigationTreeDirectoryNode) {
+        for (var child in entity.subtree) {
+          addUnitsToOptOut(child);
+        }
+      } else {
+        if (entity.migrationStatus == UnitMigrationStatus.optingOut) {
+          optOutUnitPaths.add(entity.path);
+        }
+      }
+    }
+
+    for (var entity in navigationTree) {
+      addUnitsToOptOut(entity);
+    }
+
+    return IncrementalPlan._(
+        migrationInfo, unitInfoMap, pathMapper, edits, optOutUnitPaths, logger);
+  }
+
+  IncrementalPlan._(this.migrationInfo, this.unitInfoMap, this.pathMapper,
+      this.edits, this.optOutUnitPaths, this.logger);
+
+  /// Applies this migration to disk.
+  void apply() {
+    logger.stdout('Applying migration suggestions to disk...');
+    var migratedFiles = <String>[];
+    for (final fileEdit in edits) {
+      var unit = unitInfoMap[fileEdit.file];
+      // Decide whether to opt out; default to `false` files not included in
+      // [edits], like [pubspec.yaml].
+      var unitIsOptOut = unit != null
+          ? optOutUnitPaths.contains(migrationInfo.computeName(unit))
+          : false;
+      if (!unitIsOptOut) {
+        final file = pathMapper.provider.getFile(fileEdit.file);
+        var code = file.exists ? file.readAsStringSync() : '';
+        code = SourceEdit.applySequence(code, fileEdit.edits);
+        file.writeAsStringSync(code);
+        migratedFiles.add(migrationInfo.relativePathFromRoot(fileEdit.file));
+      }
+    }
+
+    // A file which is to be opted out may not be found in [edits], if all types
+    // were to be made non-nullable, etc. Iterate over [optOutUnitPaths] instead
+    // of [edits] to opt files out.
+    var newlyOptedOutFiles = <String>[];
+    var keptOptedOutFiles = <String>[];
+    for (var optOutUnitPath in optOutUnitPaths) {
+      var absolutePath = migrationInfo.absolutePathFromRoot(optOutUnitPath);
+      var unit = unitInfoMap[absolutePath];
+      if (unit.wasExplicitlyOptedOut) {
+        // This unit was explicitly opted out of null safety with a Dart
+        // Language version comment. Leave the unit be.
+        keptOptedOutFiles.add(optOutUnitPath);
+      } else {
+        // This unit was not yet migrated at the start, was not explicitly
+        // opted out at the start, and is being opted out now. Add a Dart
+        // Language version comment.
+        final file = pathMapper.provider.getFile(absolutePath);
+        var code = file.exists ? file.readAsStringSync() : '';
+        file.writeAsStringSync(optCodeOutOfNullSafety(code));
+        newlyOptedOutFiles.add(optOutUnitPath);
+      }
+    }
+
+    _logFileStatus(migratedFiles, (text) => 'Migrated $text');
+    _logFileStatus(
+        newlyOptedOutFiles,
+        (text) =>
+            'Opted $text out of null safety with a new Dart language version '
+            'comment');
+    _logFileStatus(
+        keptOptedOutFiles, (text) => 'Kept $text opted out of null safety');
+  }
+
+  void _logFileStatus(
+      List<String> files, String Function(String text) template) {
+    if (files.isNotEmpty) {
+      var count = files.length;
+      if (count <= 20) {
+        var s = count > 1 ? 's' : '';
+        var text = '$count file$s';
+        logger.stdout('${template(text)}:');
+        for (var path in files) {
+          logger.stdout('    $path');
+        }
+      } else {
+        var text = '$count files';
+        logger.stdout('${template(text)}.');
+      }
+    }
+  }
+
+  @visibleForTesting
+  static String optCodeOutOfNullSafety(String code) {
+    var newline = '\n';
+    var length = code.length;
+
+    if (length == 0) {
+      return '// @dart=2.9';
+    }
+
+    var index = 0;
+
+    // Returns the next line and updates [index].
+    //
+    // After this function returns, [index] points to the character after the
+    // end of the line which was returned.
+    String getLine() {
+      var nextIndex = code.indexOf('\n', index);
+      if (nextIndex < 0) {
+        // Last line.
+        var line = code.substring(index);
+        index = length;
+        return line;
+      }
+      var line = code.substring(index, nextIndex);
+      index = nextIndex + 1;
+      return line;
+    }
+
+    // Skip past blank lines.
+    var line = getLine();
+    if (code.codeUnitAt(index - 1) == $lf) {
+      if (index - 2 >= 0 && code.codeUnitAt(index - 2) == $cr) {
+        // Looks like Windows-style line endings ("\r\n"). Use "\r\n" for all
+        // inserted line endings.
+        newline = '\r\n';
+      }
+    }
+    var lineStart = line.indexOf(_nonWhitespaceChar);
+    while (lineStart < 0) {
+      line = getLine();
+      if (index == length) {
+        // [code] consists _only_ of blank lines.
+        return '// @dart=2.9$newline$newline$code';
+      }
+      lineStart = line.indexOf(_nonWhitespaceChar);
+    }
+
+    // [line] is the first non-blank line.
+    if (line.length > lineStart + 1 &&
+        line.codeUnitAt(lineStart) == $slash &&
+        line.codeUnitAt(lineStart + 1) == $slash) {
+      // [line] is a comment.
+
+      if (index == length) {
+        // [code] consists _only_ of one comment line.
+        return '$code$newline$newline// @dart=2.9$newline';
+      }
+      var previousLineIndex = index;
+      String newlinesAfterDlvc;
+      while (true) {
+        previousLineIndex = index;
+        line = getLine();
+        lineStart = line.indexOf(_nonWhitespaceChar);
+        if (lineStart < 0) {
+          // Line of zero-or-more whitespace; end of block comment.
+          newlinesAfterDlvc = newline;
+          break;
+        }
+        if (line.length <= lineStart + 1) {
+          // Only one character; not a comment; end of block comment.
+          newlinesAfterDlvc = '$newline$newline';
+          break;
+        }
+        if (line.codeUnitAt(lineStart) == $slash &&
+            line.codeUnitAt(lineStart + 1) == $slash) {
+          // Comment line.
+          if (index == length) {
+            // [code] consists _only_ of this block comment.
+            return '$code$newline$newline// @dart=2.9$newline';
+          }
+          continue;
+        } else {
+          // Non-blank, non-comment line.
+          newlinesAfterDlvc = '$newline$newline';
+          break;
+        }
+      }
+      // [previousLineIndex] points to the start of [line], which is the first
+      // non-comment line following the first comment.
+      return '${code.substring(0, previousLineIndex)}$newline'
+          '// @dart=2.9$newlinesAfterDlvc'
+          '${code.substring(previousLineIndex)}';
+    } else {
+      // [code] does not start with a block comment.
+      return '// @dart=2.9$newline$newline$code';
+    }
+  }
+}
+
 /// The site used to serve pages for the preview tool.
 class PreviewSite extends Site
     implements AbstractGetHandler, AbstractPostHandler {
@@ -84,11 +312,14 @@
   /// migration.
   final void Function() applyHook;
 
+  final Logger logger;
+
   final String serviceAuthToken = _makeAuthToken();
 
   /// Initialize a newly created site to serve a preview of the results of an
   /// NNBD migration.
-  PreviewSite(this.migrationState, this.rerunFunction, this.applyHook)
+  PreviewSite(
+      this.migrationState, this.rerunFunction, this.applyHook, this.logger)
       : super('NNBD Migration Preview') {
     reset();
   }
@@ -212,7 +443,10 @@
         return _respondUnauthorized(request);
       }
       if (path == applyMigrationPath) {
-        performApply();
+        var navigationTree =
+            ((await requestBodyJson(request))['navigationTree'] as List)
+                .map((encoded) => NavigationTreeNode.fromJson(encoded));
+        performApply(navigationTree);
 
         respondOk(request);
         return;
@@ -248,7 +482,7 @@
   }
 
   /// Perform the migration.
-  void performApply() {
+  void performApply(Iterable<NavigationTreeNode> navigationTree) {
     if (migrationState.hasBeenApplied) {
       throw StateError(
           'It looks like this migration has already been applied. Try'
@@ -273,12 +507,9 @@
 
     // Eagerly mark the migration applied. If this throws, we cannot go back.
     migrationState.markApplied();
-    for (final fileEdit in edits) {
-      final file = pathMapper.provider.getFile(fileEdit.file);
-      var code = file.exists ? file.readAsStringSync() : '';
-      code = SourceEdit.applySequence(code, fileEdit.edits);
-      file.writeAsStringSync(code);
-    }
+    IncrementalPlan(migrationInfo, unitInfoMap, pathMapper, edits,
+            navigationTree, logger)
+        .apply();
     applyHook();
   }
 
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index a3ddc70..84e0ea0 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -390,12 +390,12 @@
       element = element.declaration;
     }
 
-    if (element is FunctionTypeAliasElement) {
+    if (element is TypeAliasElement) {
       // For `typedef F<T> = Function(T)`, get the `function` which is (in this
       // case) `Function(T)`. Without this we would get `Function<T>(T)` which
       // is incorrect. This is a known issue with `.type` on typedefs in the
       // analyzer.
-      element = (element as FunctionTypeAliasElement).function;
+      element = (element as FunctionTypeAliasElement).aliasedElement;
     }
 
     var target = NullabilityNodeTarget.element(element, _getLineInfo);
diff --git a/pkg/nnbd_migration/pubspec.yaml b/pkg/nnbd_migration/pubspec.yaml
index 0a382de..10777c5 100644
--- a/pkg/nnbd_migration/pubspec.yaml
+++ b/pkg/nnbd_migration/pubspec.yaml
@@ -14,6 +14,7 @@
   analyzer_plugin:
     path: ../analyzer_plugin
   args: ^1.4.4
+  charcode: ^1.1.0
   cli_util: ^0.2.0
   collection: ^1.14.11
   crypto: ^2.0.6
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 8e1285fa..97bac6d 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -1918,8 +1918,8 @@
 class C<T> {
   int Function(T) f;
 }
-void main() {
-  C<String> c;
+void main(dynamic d) {
+  C<String> c = d;
   int Function(String) f1 = c.f; // should not have a nullable arg
   c.f(null); // exact nullability induced here
 }
@@ -1928,8 +1928,8 @@
 class C<T> {
   int Function(T)? f;
 }
-void main() {
-  C<String?> c;
+void main(dynamic d) {
+  C<String?> c = d;
   int Function(String)? f1 = c.f; // should not have a nullable arg
   c.f!(null); // exact nullability induced here
 }
@@ -1945,8 +1945,8 @@
   T Function(String) f;
 }
 int Function(String) f1; // should not have a nullable return
-void main() {
-  C<int> c;
+void main(dynamic d) {
+  C<int> c = d;
   c.f = f1;
   c.f = (_) => null; // exact nullability induced here
 }
@@ -1956,8 +1956,8 @@
   T Function(String)? f;
 }
 int Function(String)? f1; // should not have a nullable return
-void main() {
-  C<int?> c;
+void main(dynamic d) {
+  C<int?> c = d;
   c.f = f1;
   c.f = (_) => null; // exact nullability induced here
 }
@@ -2116,6 +2116,163 @@
     await _checkSingleFileChanges(content, expected, removeViaComments: true);
   }
 
+  Future<void> test_extension_extended_type_nullability_intent() async {
+    var content = '''
+extension E on C {
+  String foo() => this.bar();
+}
+
+class C {
+  String bar() => null;
+}
+
+void test(C c, bool b) {
+  if (b) {
+    c.foo();
+  }
+}
+
+main() {
+  test(null, false);
+}
+''';
+    // The call to `bar` from `foo` should be taken as a demonstration that the
+    // extension E is not intended to apply to nullable types, so the call to
+    // `foo` should be null checked.
+    var expected = '''
+extension E on C {
+  String? foo() => this.bar();
+}
+
+class C {
+  String? bar() => null;
+}
+
+void test(C? c, bool b) {
+  if (b) {
+    c!.foo();
+  }
+}
+
+main() {
+  test(null, false);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_extension_null_check_non_nullable() async {
+    var content = '''
+class C {}
+extension E on C/*!*/ {
+  void m() {}
+}
+void f(C c, bool b) {
+  if (b) {
+    c.m();
+  }
+}
+void g() => f(null, false);
+''';
+    var expected = '''
+class C {}
+extension E on C {
+  void m() {}
+}
+void f(C? c, bool b) {
+  if (b) {
+    c!.m();
+  }
+}
+void g() => f(null, false);
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_extension_null_check_non_nullable_generic() async {
+    var content = '''
+class C {}
+extension E<T extends Object/*!*/> on T/*!*/ {
+  void m() {}
+}
+void f(C c, bool b) {
+  if (b) {
+    c.m();
+  }
+}
+void g() => f(null, false);
+''';
+    var expected = '''
+class C {}
+extension E<T extends Object> on T {
+  void m() {}
+}
+void f(C? c, bool b) {
+  if (b) {
+    c!.m();
+  }
+}
+void g() => f(null, false);
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_extension_null_check_nullable() async {
+    var content = '''
+class C {}
+extension E on C/*?*/ {
+  void m() {}
+}
+void f(C c, bool b) {
+  if (b) {
+    c.m();
+  }
+}
+void g() => f(null, false);
+''';
+    var expected = '''
+class C {}
+extension E on C? {
+  void m() {}
+}
+void f(C? c, bool b) {
+  if (b) {
+    c.m();
+  }
+}
+void g() => f(null, false);
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_extension_null_check_nullable_generic() async {
+    var content = '''
+class C {}
+extension E<T extends Object/*?*/> on T/*!*/ {
+  void m() {}
+}
+void f(C c, bool b) {
+  if (b) {
+    c.m();
+  }
+}
+void g() => f(null, false);
+''';
+    var expected = '''
+class C {}
+extension E<T extends Object?> on T {
+  void m() {}
+}
+void f(C? c, bool b) {
+  if (b) {
+    c.m();
+  }
+}
+void g() => f(null, false);
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_extension_null_check_target() async {
     var content = '''
 extension E on int/*!*/ {
@@ -2132,7 +2289,6 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/42529')
   Future<void> test_extension_nullable_target() async {
     var content = '''
 extension E on int {
@@ -2218,7 +2374,6 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/40023')
   Future<void> test_extension_nullableOnType_viaImplicitInvocation() async {
     var content = '''
 class C {}
@@ -2351,7 +2506,6 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/42529')
   Future<void> test_extension_override_nullable_target() async {
     var content = '''
 extension E on int {
@@ -3071,6 +3225,28 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_function_expression_return() async {
+    var content = '''
+void test({String foo}) async {
+  var f = () {
+    return "hello";
+  }
+
+  foo.length;
+}
+''';
+    var expected = '''
+void test({required String foo}) async {
+  var f = () {
+    return "hello";
+  }
+
+  foo.length;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_function_typed_field_formal_param() async {
     var content = '''
 class C {
@@ -4458,6 +4634,24 @@
         {path2: file2, path1: file1}, {path1: expected1, path2: expected2});
   }
 
+  Future<void> test_list_conditional_element() async {
+    var content = '''
+void bar(List<String> l) {}
+
+void test({String foo}) {
+    bar([if (foo != null) foo]);
+}
+''';
+    var expected = '''
+void bar(List<String> l) {}
+
+void test({String? foo}) {
+    bar([if (foo != null) foo]);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_literal_null_without_valid_migration() async {
     var content = '''
 void f(int/*!*/ x) {}
@@ -4551,6 +4745,102 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_local_function_expression_inhibits_non_null_intent() async {
+    var content = '''
+void call(void Function() callback) {
+  callback();
+}
+test(int i, int j) {
+  call(() {
+    i = j;
+  });
+  print(i + 1);
+}
+main() {
+  test(null, 0);
+}
+''';
+    // `print(i + 1)` does *not* demonstrate non-null intent for `i` because it
+    // is write captured by the local function expression, so it's not
+    // guaranteed that a null value of `i` on entry to the function will lead to
+    // an exception.
+    var expected = '''
+void call(void Function() callback) {
+  callback();
+}
+test(int? i, int j) {
+  call(() {
+    i = j;
+  });
+  print(i! + 1);
+}
+main() {
+  test(null, 0);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_local_function_inhibits_non_null_intent() async {
+    var content = '''
+void call(void Function() callback) {
+  callback();
+}
+test(int i, int j) {
+  void f() {
+    i = j;
+  }
+  call(f);
+  print(i + 1);
+}
+main() {
+  test(null, 0);
+}
+''';
+    // `print(i + 1)` does *not* demonstrate non-null intent for `i` because it
+    // is write captured by the local function expression, so it's not
+    // guaranteed that a null value of `i` on entry to the function will lead to
+    // an exception.
+    var expected = '''
+void call(void Function() callback) {
+  callback();
+}
+test(int? i, int j) {
+  void f() {
+    i = j;
+  }
+  call(f);
+  print(i! + 1);
+}
+main() {
+  test(null, 0);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void> test_local_function_return() async {
+    var content = '''
+void test({String foo}) async {
+  String f() {
+    return "hello";
+  }
+
+  foo.length;
+}
+''';
+    var expected = '''
+void test({required String foo}) async {
+  String f() {
+    return "hello";
+  }
+
+  foo.length;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_localVariable_type_inferred() async {
     var content = '''
 int f() => null;
@@ -6800,7 +7090,7 @@
     var expected = '''
 typedef F = Function(int?);
 
-F _f;
+late F _f;
 
 f() {
   _f(null);
@@ -6865,7 +7155,7 @@
     var expected = '''
 typedef F = Function<T>(T);
 
-F _f;
+late F _f;
 
 f() {
   _f<int?>(null);
@@ -6887,7 +7177,7 @@
     var expected = '''
 typedef F<R> = Function<T>(T);
 
-F<Object> _f;
+late F<Object> _f;
 
 f() {
   _f<int?>(null);
@@ -6909,7 +7199,7 @@
     var expected = '''
 typedef F<T> = Function(T);
 
-F<int?> _f;
+late F<int?> _f;
 
 f() {
   _f(null);
@@ -6931,7 +7221,7 @@
     var expected = '''
 typedef F<T> = Function(T);
 
-F<int?> _f;
+late F<int?> _f;
 
 f() {
   _f(null);
@@ -6967,7 +7257,7 @@
     var expected = '''
 typedef F(int? x);
 
-F _f;
+late F _f;
 
 f() {
   _f(null);
@@ -7017,7 +7307,7 @@
     var expected = '''
 typedef F<T>(T t);
 
-F<int?> _f;
+late F<int?> _f;
 
 f() {
   _f(null);
@@ -7039,7 +7329,7 @@
     var expected = '''
 typedef F<T>(T t);
 
-F<int?> _f;
+late F<int?> _f;
 
 f() {
   _f(null);
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 1885167..e50b091 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -2952,6 +2952,87 @@
     // adding assertion(s).
   }
 
+  Future<void> test_extension_this_non_null_intent_explicit_direct() async {
+    await analyze('''
+extension on int {
+  f() => g(this);
+}
+void g(int i) {}
+''');
+    assertEdge(decoratedTypeAnnotation('int {').node,
+        decoratedTypeAnnotation('int i').node,
+        hard: true);
+  }
+
+  Future<void> test_extension_this_non_null_intent_explicit_method() async {
+    await analyze('''
+extension on int {
+  f() => this.abs();
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int').node, never, hard: true);
+  }
+
+  Future<void>
+      test_extension_this_non_null_intent_explicit_property_get() async {
+    await analyze('''
+extension on int {
+  f() => this.isEven;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int').node, never, hard: true);
+  }
+
+  Future<void>
+      test_extension_this_non_null_intent_explicit_property_set() async {
+    await analyze('''
+class C {
+  int x;
+}
+extension on C /*reference*/ {
+  f() {
+    this.x = 0;
+  }
+}
+''');
+    assertEdge(decoratedTypeAnnotation('C /*reference*/').node, never,
+        hard: true);
+  }
+
+  Future<void> test_extension_this_non_null_intent_implicit_method() async {
+    await analyze('''
+extension on int {
+  f() => abs();
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int').node, never, hard: true);
+  }
+
+  Future<void> test_extension_this_non_null_intent_implicit_property() async {
+    await analyze('''
+extension on int {
+  f() => isEven;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('int').node, never, hard: true);
+  }
+
+  Future<void>
+      test_extension_this_non_null_intent_implicit_property_set() async {
+    await analyze('''
+class C {
+  int x;
+}
+extension on C /*reference*/ {
+  f() {
+    x = 0;
+  }
+}
+''');
+    assertEdge(decoratedTypeAnnotation('C /*reference*/').node, never,
+        hard: true);
+  }
+
   Future<void> test_field_final_does_not_override_setter() async {
     await analyze('''
 abstract class A {
@@ -6197,6 +6278,58 @@
         assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true));
   }
 
+  Future<void> test_postDominators_subFunction_nested() async {
+    await analyze('''
+f1(int a, int b, int c, int d) {
+  f2() {
+    a = 0;
+    f3() {
+      b = 0;
+    }
+    c = 0;
+  }
+  a + 1;
+  b + 1;
+  c + 1;
+  d + 1;
+}
+''');
+    // a, b, and c may all be written to prior to their use, so their use sites
+    // don't demonstrate non-null intent.
+    assertEdge(decoratedTypeAnnotation('int a').node, never, hard: false);
+    assertEdge(decoratedTypeAnnotation('int b').node, never, hard: false);
+    assertEdge(decoratedTypeAnnotation('int c').node, never, hard: false);
+    // However, the use of `d` does demonstrate non-null intent because there's
+    // no write to `d`.
+    assertEdge(decoratedTypeAnnotation('int d').node, never, hard: true);
+  }
+
+  Future<void> test_postDominators_subFunction_nested_closure() async {
+    await analyze('''
+f1(int a, int b, int c, int d) {
+  var f2 = () {
+    a = 0;
+    var f3 = () {
+      b = 0;
+    };
+    c = 0;
+  };
+  a + 1;
+  b + 1;
+  c + 1;
+  d + 1;
+}
+''');
+    // a, b, and c may all be written to prior to their use, so their use sites
+    // don't demonstrate non-null intent.
+    assertEdge(decoratedTypeAnnotation('int a').node, never, hard: false);
+    assertEdge(decoratedTypeAnnotation('int b').node, never, hard: false);
+    assertEdge(decoratedTypeAnnotation('int c').node, never, hard: false);
+    // However, the use of `d` does demonstrate non-null intent because there's
+    // no write to `d`.
+    assertEdge(decoratedTypeAnnotation('int d').node, never, hard: true);
+  }
+
   Future<void> test_postDominators_ternaryOperator() async {
     await analyze('''
 class C {
@@ -6340,6 +6473,38 @@
     expect(hasNullCheckHint(findNode.prefixed('m.pi/*!*/')), isTrue);
   }
 
+  Future<void> test_prefixedIdentifier_extension_nullTarget_get() async {
+    await analyze('''
+class C {}
+extension on C /*1*/ {
+  int get x => 0;
+}
+void f() {
+  C c = null;
+  c.x;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('C c').node,
+        decoratedTypeAnnotation('C /*1*/').node,
+        hard: true);
+  }
+
+  Future<void> test_prefixedIdentifier_extension_nullTarget_set() async {
+    await analyze('''
+class C {}
+extension on C /*1*/ {
+  set x(int value) {}
+}
+void f() {
+  C c = null;
+  c.x = 0;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('C c').node,
+        decoratedTypeAnnotation('C /*1*/').node,
+        hard: true);
+  }
+
   Future<void> test_prefixedIdentifier_field_type() async {
     await analyze('''
 class C {
@@ -6669,6 +6834,70 @@
         hard: false);
   }
 
+  Future<void> test_propertyAccess_extension_nullTarget_get() async {
+    await analyze('''
+class C {}
+extension on C /*1*/ {
+  int get x => 0;
+}
+void f() {
+  C g() => null;
+  g().x;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('C g()').node,
+        decoratedTypeAnnotation('C /*1*/').node,
+        hard: false);
+  }
+
+  Future<void> test_propertyAccess_extension_nullTarget_get_explicit() async {
+    await analyze('''
+class C {}
+extension E on C /*1*/ {
+  int get x => 0;
+}
+void f() {
+  C g() => null;
+  E(g()).x;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('C g()').node,
+        decoratedTypeAnnotation('C /*1*/').node,
+        hard: false);
+  }
+
+  Future<void> test_propertyAccess_extension_nullTarget_set() async {
+    await analyze('''
+class C {}
+extension on C /*1*/ {
+  set x(int value) {}
+}
+void f() {
+  C g() => null;
+  g().x = 0;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('C g()').node,
+        decoratedTypeAnnotation('C /*1*/').node,
+        hard: false);
+  }
+
+  Future<void> test_propertyAccess_extension_nullTarget_set_explicit() async {
+    await analyze('''
+class C {}
+extension E on C /*1*/ {
+  set x(int value) {}
+}
+void f() {
+  C g() => null;
+  E(g()).x = 0;
+}
+''');
+    assertEdge(decoratedTypeAnnotation('C g()').node,
+        decoratedTypeAnnotation('C /*1*/').node,
+        hard: false);
+  }
+
   Future<void> test_propertyAccess_object_property() async {
     await analyze('''
 int f(int i) => i.hashCode;
@@ -7660,11 +7889,11 @@
 }
 ''');
     expect(
-        assertEdge(anyNode, decoratedTypeAnnotation('int f1').node, hard: false)
+        assertEdge(anyNode, decoratedTypeAnnotation('int f1').node, hard: true)
             .sourceNode,
         isNot(never));
     expect(
-        assertEdge(anyNode, decoratedTypeAnnotation('int f2').node, hard: false)
+        assertEdge(anyNode, decoratedTypeAnnotation('int f2').node, hard: true)
             .sourceNode,
         never);
     expect(hasNullCheckHint(findNode.this_('this/*!*/')), isTrue);
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 7989905..e292a6f 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -946,6 +946,60 @@
     visitSubexpression(findNode.binary('=='), 'bool');
   }
 
+  Future<void> test_binaryExpression_extensionMember_allowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  void operator+(C/*!*/ other) {}
+}
+f(C/*?*/ c) => c + c;
+''');
+    var binaryExpression = findNode.binary('c + c');
+    visitSubexpression(binaryExpression, 'void',
+        changes: {binaryExpression.rightOperand: isNullCheck});
+  }
+
+  Future<void>
+      test_binaryExpression_extensionMember_allowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  void operator+(C/*!*/ other) {}
+}
+f(C/*?*/ c) => E(c) + c;
+''');
+    var binaryExpression = findNode.binary('E(c) + c');
+    visitSubexpression(binaryExpression, 'void',
+        changes: {binaryExpression.rightOperand: isNullCheck});
+  }
+
+  Future<void> test_binaryExpression_extensionMember_disallowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  void operator+(C/*!*/ other) {}
+}
+f(C/*?*/ c) => c + c;
+''');
+    var binaryExpression = findNode.binary('c + c');
+    visitSubexpression(binaryExpression, 'void',
+        changes: {binaryExpression.leftOperand: isNullCheck});
+  }
+
+  Future<void>
+      test_binaryExpression_extensionMember_disallowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  void operator+(C/*!*/ other) {}
+}
+f(C/*?*/ c) => E(c) + c;
+''');
+    var binaryExpression = findNode.binary('E(c) + c');
+    visitSubexpression(binaryExpression, 'void',
+        changes: {findNode.simple('c) +'): isNullCheck});
+  }
+
   Future<void> test_binaryExpression_question_question() async {
     await analyze('''
 _f(int/*?*/ x, double/*?*/ y) {
@@ -1390,6 +1444,64 @@
     visitSubexpression(findNode.functionExpressionInvocation('d('), 'dynamic');
   }
 
+  Future<void>
+      test_functionExpressionInvocation_extensionMember_allowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  void call() {}
+}
+f(C/*?*/ c) => c();
+''');
+    var functoinExpressionInvocation =
+        findNode.functionExpressionInvocation('c()');
+    visitSubexpression(functoinExpressionInvocation, 'void');
+  }
+
+  Future<void>
+      test_functionExpressionInvocation_extensionMember_allowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  void call() {}
+}
+f(C/*?*/ c) => E(c)();
+''');
+    var functoinExpressionInvocation =
+        findNode.functionExpressionInvocation('E(c)()');
+    visitSubexpression(functoinExpressionInvocation, 'void');
+  }
+
+  Future<void>
+      test_functionExpressionInvocation_extensionMember_disallowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  void call() {}
+}
+f(C/*?*/ c) => c();
+''');
+    var functionExpressionInvocation =
+        findNode.functionExpressionInvocation('c()');
+    visitSubexpression(functionExpressionInvocation, 'void',
+        changes: {functionExpressionInvocation.function: isNullCheck});
+  }
+
+  Future<void>
+      test_functionExpressionInvocation_extensionMember_disallowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  void call() {}
+}
+f(C/*?*/ c) => E(c)();
+''');
+    var functionExpressionInvocation =
+        findNode.functionExpressionInvocation('E(c)()');
+    visitSubexpression(functionExpressionInvocation, 'void',
+        changes: {findNode.simple('c)()'): isNullCheck});
+  }
+
   Future<void> test_functionExpressionInvocation_function_checked() async {
     await analyze('''
 _f(Function/*?*/ func) => func();
@@ -1660,6 +1772,58 @@
     visitSubexpression(findNode.index('d[i]'), 'dynamic');
   }
 
+  Future<void> test_indexExpression_extensionMember_allowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  int operator[](int index) => 0;
+}
+f(C/*?*/ c) => c[0];
+''');
+    var indexExpression = findNode.index('c[0]');
+    visitSubexpression(indexExpression, 'int');
+  }
+
+  Future<void>
+      test_indexExpression_extensionMember_allowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  int operator[](int index) => 0;
+}
+f(C/*?*/ c) => E(c)[0];
+''');
+    var indexExpression = findNode.index('E(c)[0]');
+    visitSubexpression(indexExpression, 'int');
+  }
+
+  Future<void> test_indexExpression_extensionMember_disallowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  int operator[](int index) => 0;
+}
+f(C/*?*/ c) => c[0];
+''');
+    var indexExpression = findNode.index('c[0]');
+    visitSubexpression(indexExpression, 'int',
+        changes: {indexExpression.target: isNullCheck});
+  }
+
+  Future<void>
+      test_indexExpression_extensionMember_disallowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  int operator[](int index) => 0;
+}
+f(C/*?*/ c) => E(c)[0];
+''');
+    var indexExpression = findNode.index('E(c)[0]');
+    visitSubexpression(indexExpression, 'int',
+        changes: {findNode.simple('c)[0]'): isNullCheck});
+  }
+
   Future<void> test_indexExpression_simple() async {
     await analyze('''
 class _C {
@@ -1931,6 +2095,67 @@
     visitSubexpression(findNode.methodInvocation('d.f'), 'dynamic');
   }
 
+  Future<void> test_methodInvocation_extensionMember_allowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  void foo() {}
+}
+f(C/*?*/ c) => c.foo();
+''');
+    var methodInvocation = findNode.methodInvocation('c.foo');
+    visitSubexpression(methodInvocation, 'void');
+  }
+
+  Future<void>
+      test_methodInvocation_extensionMember_allowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  void foo() {}
+}
+f(C/*?*/ c) => E(c).foo();
+''');
+    var methodInvocation = findNode.methodInvocation('E(c).foo');
+    visitSubexpression(methodInvocation, 'void');
+  }
+
+  Future<void> test_methodInvocation_extensionMember_disallowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  void foo() {}
+}
+f(C/*?*/ c) => c.foo();
+''');
+    var methodInvocation = findNode.methodInvocation('c.foo');
+    visitSubexpression(methodInvocation, 'void',
+        changes: {methodInvocation.target: isNullCheck});
+  }
+
+  Future<void>
+      test_methodInvocation_extensionMember_disallowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  void foo() {}
+}
+f(C/*?*/ c) => E(c).foo();
+''');
+    var methodInvocation = findNode.methodInvocation('E(c).foo');
+    visitSubexpression(methodInvocation, 'void',
+        changes: {findNode.simple('c).foo'): isNullCheck});
+  }
+
+  Future<void> test_methodInvocation_function_call_nullCheck() async {
+    await analyze('''
+f(void Function()/*?*/ x) => x.call();
+''');
+    var methodInvocation = findNode.methodInvocation('x.call');
+    visitSubexpression(methodInvocation, 'void',
+        changes: {methodInvocation.target: isNullCheck});
+  }
+
   Future<void> test_methodInvocation_namedParameter() async {
     await analyze('''
 abstract class _C {
@@ -2474,6 +2699,31 @@
     visitSubexpression(findNode.prefixed('d.x'), 'dynamic');
   }
 
+  Future<void> test_prefixedIdentifier_extensionMember_allowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  int get foo => 0;
+}
+f(C/*?*/ c) => c.foo;
+''');
+    var prefixedIdentifier = findNode.prefixed('c.foo');
+    visitSubexpression(prefixedIdentifier, 'int');
+  }
+
+  Future<void> test_prefixedIdentifier_extensionMember_disallowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  int get foo => 0;
+}
+f(C/*?*/ c) => c.foo;
+''');
+    var prefixedIdentifier = findNode.prefixed('c.foo');
+    visitSubexpression(prefixedIdentifier, 'int',
+        changes: {prefixedIdentifier.prefix: isNullCheck});
+  }
+
   Future<void> test_prefixedIdentifier_field_nonNullable() async {
     await analyze('''
 class _C {
@@ -2643,6 +2893,58 @@
         changes: {findNode.simple('c);'): isNullCheck});
   }
 
+  Future<void> test_prefixExpression_extensionMember_allowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  C operator-() => C();
+}
+f(C/*?*/ c) => -c;
+''');
+    var prefixExpression = findNode.prefix('-c');
+    visitSubexpression(prefixExpression, 'C');
+  }
+
+  Future<void>
+      test_prefixExpression_extensionMember_allowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  C operator-() => C();
+}
+f(C/*?*/ c) => -E(c);
+''');
+    var prefixExpression = findNode.prefix('-E(c)');
+    visitSubexpression(prefixExpression, 'C');
+  }
+
+  Future<void> test_prefixExpression_extensionMember_disallowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  C operator-() => C();
+}
+f(C/*?*/ c) => -c;
+''');
+    var prefixExpression = findNode.prefix('-c');
+    visitSubexpression(prefixExpression, 'C',
+        changes: {prefixExpression.operand: isNullCheck});
+  }
+
+  Future<void>
+      test_prefixExpression_extensionMember_disallowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  C operator-() => C();
+}
+f(C/*?*/ c) => -E(c);
+''');
+    var prefixExpression = findNode.prefix('-E(c)');
+    visitSubexpression(prefixExpression, 'C',
+        changes: {findNode.simple('c);'): isNullCheck});
+  }
+
   Future<void> test_prefixExpression_increment_undoes_promotion() async {
     await analyze('''
 abstract class _C {
@@ -2768,6 +3070,58 @@
     visitSubexpression(findNode.propertyAccess('(d).x'), 'dynamic');
   }
 
+  Future<void> test_propertyAccess_extensionMember_allowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  int get foo => 0;
+}
+f(C/*?*/ Function() g) => g().foo;
+''');
+    var propertyAccess = findNode.propertyAccess('g().foo');
+    visitSubexpression(propertyAccess, 'int');
+  }
+
+  Future<void> test_propertyAccess_extensionMember_allowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*?*/ {
+  int get foo => 0;
+}
+f(C/*?*/ Function() g) => E(g()).foo;
+''');
+    var propertyAccess = findNode.propertyAccess('E(g()).foo');
+    visitSubexpression(propertyAccess, 'int');
+  }
+
+  Future<void> test_propertyAccess_extensionMember_disallowsNull() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  int get foo => 0;
+}
+f(C/*?*/ Function() g) => g().foo;
+''');
+    var propertyAccess = findNode.propertyAccess('g().foo');
+    visitSubexpression(propertyAccess, 'int',
+        changes: {propertyAccess.target: isNullCheck});
+  }
+
+  Future<void>
+      test_propertyAccess_extensionMember_disallowsNull_explicit() async {
+    await analyze('''
+class C {}
+extension E on C/*!*/ {
+  int get foo => 0;
+}
+f(C/*?*/ Function() g) => E(g()).foo;
+''');
+    var propertyAccess = findNode.propertyAccess('E(g()).foo');
+    visitSubexpression(propertyAccess, 'int', changes: {
+      findNode.functionExpressionInvocation('g()).foo'): isNullCheck
+    });
+  }
+
   Future<void> test_propertyAccess_field_nonNullable() async {
     await analyze('''
 class _C {
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 b4f76ed..45292fd 100644
--- a/pkg/nnbd_migration/test/front_end/info_builder_test.dart
+++ b/pkg/nnbd_migration/test/front_end/info_builder_test.dart
@@ -5,10 +5,10 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:meta/meta.dart';
-import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/front_end/info_builder.dart';
 import 'package:nnbd_migration/src/front_end/migration_info.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
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 b941ca3..2622ed5 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
@@ -14,6 +14,7 @@
 import 'package:nnbd_migration/src/front_end/migration_info.dart';
 import 'package:nnbd_migration/src/front_end/non_nullable_fix.dart';
 import 'package:nnbd_migration/src/front_end/offset_mapper.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -158,6 +159,8 @@
     var includedRoot = resourceProvider.pathContext.dirname(testFile);
     await _buildMigrationInfo([testFile],
         includedRoot: includedRoot,
+        shouldBeMigratedFunction: (String path) => true,
+        pathsToProcess: [testFile],
         removeViaComments: removeViaComments,
         warnOnWeakCode: warnOnWeakCode);
   }
@@ -189,13 +192,20 @@
   ///
   /// Returns the singular [UnitInfo] which was built.
   Future<List<UnitInfo>> buildInfoForTestFiles(Map<String, String> files,
-      {String includedRoot}) async {
+      {@required String includedRoot,
+      bool Function(String) shouldBeMigratedFunction,
+      Iterable<String> pathsToProcess}) async {
+    shouldBeMigratedFunction ??= (String path) => true;
     var testPaths = <String>[];
     files.forEach((String path, String content) {
       newFile(path, content: content);
       testPaths.add(path);
     });
-    await _buildMigrationInfo(testPaths, includedRoot: includedRoot);
+    pathsToProcess ??= testPaths;
+    await _buildMigrationInfo(testPaths,
+        includedRoot: includedRoot,
+        shouldBeMigratedFunction: shouldBeMigratedFunction,
+        pathsToProcess: pathsToProcess);
     // Ignore info for dart:core.
     var filteredInfos = [
       for (var info in infos)
@@ -211,8 +221,10 @@
 
   /// Uses the InfoBuilder to build information for files at [testPaths], which
   /// should all share a common parent directory, [includedRoot].
-  Future<void> _buildMigrationInfo(List<String> testPaths,
-      {String includedRoot,
+  Future<void> _buildMigrationInfo(Iterable<String> testPaths,
+      {@required String includedRoot,
+      @required bool Function(String) shouldBeMigratedFunction,
+      @required Iterable<String> pathsToProcess,
       bool removeViaComments = true,
       bool warnOnWeakCode = false}) async {
     // Compute the analysis results.
@@ -242,8 +254,16 @@
     // Build the migration info.
     var info = instrumentationListener.data;
     var logger = TestLogger(false);
-    var builder = InfoBuilder(resourceProvider, includedRoot, info, listener,
-        migration, nodeMapper, logger);
+    var builder = InfoBuilder(
+        resourceProvider,
+        includedRoot,
+        info,
+        listener,
+        migration,
+        nodeMapper,
+        logger,
+        shouldBeMigratedFunction,
+        pathsToProcess);
     infos = await builder.explainMigration();
   }
 }
diff --git a/pkg/nnbd_migration/test/migration_cli_test.dart b/pkg/nnbd_migration/test/migration_cli_test.dart
index d746ac6..f065da9 100644
--- a/pkg/nnbd_migration/test/migration_cli_test.dart
+++ b/pkg/nnbd_migration/test/migration_cli_test.dart
@@ -73,6 +73,7 @@
       String summaryPath,
       @required String sdkPath})
       : super(listener, resourceProvider, getLineInfo, bindAddress, logger,
+            (String path) => true,
             included: included,
             preferredPort: preferredPort,
             summaryPath: summaryPath,
@@ -124,11 +125,12 @@
   }
 
   @override
-  Future<void> blockUntilSignalInterrupt() async {
+  void listenForSignalInterrupt() {
     if (_runWhilePreviewServerActive == null) {
       fail('Preview server not expected to have been started');
     }
-    await _runWhilePreviewServerActive.call();
+    sigIntSignalled = Completer();
+    _runWhilePreviewServerActive.call().then((_) => sigIntSignalled.complete());
     _runWhilePreviewServerActive = null;
   }
 
@@ -183,9 +185,9 @@
   }
 
   @override
-  bool shouldBeMigrated(DriverBasedAnalysisContext context, String path) =>
+  bool shouldBeMigrated(String path) =>
       cli._test.overrideShouldBeMigrated?.call(path) ??
-      super.shouldBeMigrated(context, path);
+      super.shouldBeMigrated(path);
 
   /// Sorts the paths in [paths] for repeatability of migration tests.
   Set<String> _sortPaths(Set<String> paths) {
@@ -295,7 +297,7 @@
   }
 
   Future assertPreviewServerResponsive(String url) async {
-    var response = await httpGet(url);
+    var response = await httpGet(Uri.parse(url));
     assertHttpSuccess(response);
   }
 
@@ -370,13 +372,13 @@
 
   /// Performs an HTTP get, verifying that the response received (if any) is
   /// reasonable.
-  Future<http.Response> httpGet(dynamic url, {Map<String, String> headers}) {
+  Future<http.Response> httpGet(Uri url, {Map<String, String> headers}) {
     return checkHttpResponse(http.get(url, headers: headers));
   }
 
   /// Performs an HTTP post, verifying that the response received (if any) is
   /// reasonable.
-  Future<http.Response> httpPost(dynamic url,
+  Future<http.Response> httpPost(Uri url,
       {Map<String, String> headers, dynamic body, Encoding encoding}) {
     return checkHttpResponse(
         http.post(url, headers: headers, body: body, encoding: encoding));
@@ -397,7 +399,7 @@
         await callback(url);
       });
       // Server should be stopped now
-      expect(httpGet(url), throwsA(anything));
+      expect(httpGet(Uri.parse(url)), throwsA(anything));
       assertNormalExit(cliRunner);
     }
   }
@@ -1861,6 +1863,48 @@
         projectDir, simpleProject(migrated: true, pubspecText: pubspecText));
   }
 
+  test_pubspec_environment_sdk_is_exact_version() async {
+    var pubspecText = '''
+name: test
+environment:
+  sdk: '2.0.0'
+''';
+    var projectContents = simpleProject(pubspecText: pubspecText);
+    var projectDir = createProjectDir(projectContents);
+    var cliRunner = _createCli()
+        .decodeCommandLineArgs(_parseArgs(['--apply-changes', projectDir]));
+    await cliRunner.run();
+    // The Dart source code should still be migrated.
+    assertProjectContents(
+        projectDir,
+        simpleProject(
+            migrated: true,
+            pubspecText: pubspecText,
+            // The package config file should not have been touched.
+            packageConfigText: _getPackageConfigText(migrated: false)));
+  }
+
+  test_pubspec_environment_sdk_is_missing_min() async {
+    var pubspecText = '''
+name: test
+environment:
+  sdk: '<3.0.0'
+''';
+    var projectContents = simpleProject(pubspecText: pubspecText);
+    var projectDir = createProjectDir(projectContents);
+    var cliRunner = _createCli()
+        .decodeCommandLineArgs(_parseArgs(['--apply-changes', projectDir]));
+    await cliRunner.run();
+    // The Dart source code should still be migrated.
+    assertProjectContents(
+        projectDir,
+        simpleProject(
+            migrated: true,
+            pubspecText: pubspecText,
+            // The package config file should not have been touched.
+            packageConfigText: _getPackageConfigText(migrated: false)));
+  }
+
   test_pubspec_environment_sdk_is_not_string() async {
     var pubspecText = '''
 name: test
@@ -1882,6 +1926,27 @@
             packageConfigText: _getPackageConfigText(migrated: false)));
   }
 
+  test_pubspec_environment_sdk_is_union() async {
+    var pubspecText = '''
+name: test
+environment:
+  sdk: '>=2.0.0 <2.1.0 >=2.2.0 <3.0.0'
+''';
+    var projectContents = simpleProject(pubspecText: pubspecText);
+    var projectDir = createProjectDir(projectContents);
+    var cliRunner = _createCli()
+        .decodeCommandLineArgs(_parseArgs(['--apply-changes', projectDir]));
+    await cliRunner.run();
+    // The Dart source code should still be migrated.
+    assertProjectContents(
+        projectDir,
+        simpleProject(
+            migrated: true,
+            pubspecText: pubspecText,
+            // The package config file should not have been touched.
+            packageConfigText: _getPackageConfigText(migrated: false)));
+  }
+
   test_pubspec_has_unusual_max_sdk_constraint() async {
     // No one should be using a weird max SDK constraint like this.  If they are
     // doing so, we'll fix it to 3.0.0.
@@ -2078,8 +2143,8 @@
     expect(errorOutput, contains('1 analysis issue found:'));
     expect(
         errorOutput,
-        contains("A value of type 'Null' can't be returned from function 'f' "
-            "because it has a return type of 'int'"));
+        contains("A value of type 'Null' can't be returned from the function "
+            "'f' because it has a return type of 'int'"));
     expect(errorOutput, contains('Set the lower SDK constraint'));
   }
 
@@ -2127,7 +2192,8 @@
         uri.replace(
             path: PreviewSite.applyMigrationPath,
             queryParameters: {'authToken': authToken}),
-        headers: {'Content-Type': 'application/json; charset=UTF-8'});
+        headers: {'Content-Type': 'application/json; charset=UTF-8'},
+        body: json.encode({'navigationTree': []}));
     assertHttpSuccess(response);
   }
 }
diff --git a/pkg/nnbd_migration/test/node_builder_test.dart b/pkg/nnbd_migration/test/node_builder_test.dart
index f729846..54d4aa1 100644
--- a/pkg/nnbd_migration/test/node_builder_test.dart
+++ b/pkg/nnbd_migration/test/node_builder_test.dart
@@ -3,9 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/type.dart';
-import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
+import 'package:nnbd_migration/src/hint_action.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -1053,8 +1053,8 @@
     await analyze('''
 typedef T F<T, U>(U u);
 ''');
-    var element = findElement.functionTypeAlias('F');
-    var decoratedType = variables.decoratedElementType(element.function);
+    var element = findElement.typeAlias('F');
+    var decoratedType = variables.decoratedElementType(element.aliasedElement);
     var t = element.typeParameters[0];
     var u = element.typeParameters[1];
     // typeFormals should be empty because this is not a generic function type,
@@ -1079,7 +1079,7 @@
 typedef F();
 ''');
     var decoratedType = variables
-        .decoratedElementType(findElement.functionTypeAlias('F').function);
+        .decoratedElementType(findElement.typeAlias('F').aliasedElement);
     expect(decoratedType.returnType.type.isDynamic, isTrue);
     expect(decoratedType.returnType.node.isImmutable, false);
     expect(decoratedType.typeFormals, isEmpty);
@@ -1090,7 +1090,7 @@
 typedef int F(String s);
 ''');
     var decoratedType = variables
-        .decoratedElementType(findElement.functionTypeAlias('F').function);
+        .decoratedElementType(findElement.typeAlias('F').aliasedElement);
     expect(decoratedType.returnType, same(decoratedTypeAnnotation('int')));
     expect(decoratedType.typeFormals, isEmpty);
     expect(decoratedType.positionalParameters[0],
@@ -1287,8 +1287,8 @@
     await analyze('''
 typedef F = T Function<T, U>(U u);
 ''');
-    var element = findElement.functionTypeAlias('F');
-    var decoratedType = variables.decoratedElementType(element.function);
+    var element = findElement.typeAlias('F');
+    var decoratedType = variables.decoratedElementType(element.aliasedElement);
     expect(decoratedType,
         same(decoratedGenericFunctionTypeAnnotation('T Function')));
     expect(decoratedType.typeFormals, hasLength(2));
@@ -1311,8 +1311,8 @@
     await analyze('''
 typedef F<T, U> = T Function(U u);
 ''');
-    var element = findElement.functionTypeAlias('F');
-    var decoratedType = variables.decoratedElementType(element.function);
+    var element = findElement.typeAlias('F');
+    var decoratedType = variables.decoratedElementType(element.aliasedElement);
     expect(decoratedType,
         same(decoratedGenericFunctionTypeAnnotation('T Function')));
     var t = element.typeParameters[0];
@@ -1339,7 +1339,7 @@
 typedef F = Function();
 ''');
     var decoratedType = variables
-        .decoratedElementType(findElement.functionTypeAlias('F').function);
+        .decoratedElementType(findElement.typeAlias('F').aliasedElement);
     expect(decoratedType,
         same(decoratedGenericFunctionTypeAnnotation('Function')));
     expect(decoratedType.returnType.type.isDynamic, isTrue);
@@ -1352,7 +1352,7 @@
 typedef F = int Function(String s);
 ''');
     var decoratedType = variables
-        .decoratedElementType(findElement.functionTypeAlias('F').function);
+        .decoratedElementType(findElement.typeAlias('F').aliasedElement);
     expect(decoratedType,
         same(decoratedGenericFunctionTypeAnnotation('int Function')));
     expect(decoratedType.returnType, same(decoratedTypeAnnotation('int')));
@@ -2071,7 +2071,7 @@
     // This is necessary because there is no guarantee of whether the typedef or
     // its usage will be visited first.
     var typedefDecoratedType = variables
-        .decoratedElementType(findElement.functionTypeAlias('F').function);
+        .decoratedElementType(findElement.typeAlias('F').aliasedElement);
     var decoratedType = decoratedTypeAnnotation('F<int>');
     expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
     expect(decoratedType.node, isNot(same(typedefDecoratedType.node)));
@@ -2092,7 +2092,7 @@
     // This is necessary because there is no guarantee of whether the typedef or
     // its usage will be visited first.
     var typedefDecoratedType = variables
-        .decoratedElementType(findElement.functionTypeAlias('F').function);
+        .decoratedElementType(findElement.typeAlias('F').aliasedElement);
     var decoratedType = decoratedTypeAnnotation('F f');
     expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
     expect(decoratedType.node, isNot(same(typedefDecoratedType.node)));
@@ -2122,7 +2122,7 @@
     // This is necessary because there is no guarantee of whether the typedef or
     // its usage will be visited first.
     var typedefDecoratedType = variables
-        .decoratedElementType(findElement.functionTypeAlias('F').function);
+        .decoratedElementType(findElement.typeAlias('F').aliasedElement);
     var decoratedType = decoratedTypeAnnotation('F f');
     expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
     expect(decoratedType.node, isNot(same(typedefDecoratedType.node)));
diff --git a/pkg/nnbd_migration/test/preview/preview_site_test.dart b/pkg/nnbd_migration/test/preview/preview_site_test.dart
index 3f9ce89..550cd92 100644
--- a/pkg/nnbd_migration/test/preview/preview_site_test.dart
+++ b/pkg/nnbd_migration/test/preview/preview_site_test.dart
@@ -10,13 +10,16 @@
 import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
 import 'package:nnbd_migration/src/front_end/migration_info.dart';
 import 'package:nnbd_migration/src/front_end/migration_state.dart';
+import 'package:nnbd_migration/src/front_end/navigation_tree_renderer.dart';
 import 'package:nnbd_migration/src/front_end/offset_mapper.dart';
 import 'package:nnbd_migration/src/front_end/path_mapper.dart';
+import 'package:nnbd_migration/src/front_end/web/navigation_tree.dart';
 import 'package:nnbd_migration/src/preview/preview_site.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../front_end/nnbd_migration_test_base.dart';
+import '../utilities/test_logger.dart';
 
 void main() {
   defineReflectiveSuite(() {
@@ -38,13 +41,16 @@
   void setUp() {
     dartfixListener = DartFixListener(null, ListenerClient());
     resourceProvider = MemoryResourceProvider();
-    final migrationInfo = MigrationInfo({}, {}, null, null);
-    state = MigrationState(null, null, dartfixListener, null, {});
+    final migrationInfo =
+        MigrationInfo({}, {}, resourceProvider.pathContext, null);
+    state = MigrationState(
+        null, null, dartfixListener, null, {}, (String path) => true);
     state.pathMapper = PathMapper(resourceProvider);
     state.migrationInfo = migrationInfo;
+    logger = TestLogger(false /*isVerbose*/);
     site = PreviewSite(state, () async {
       return state;
-    }, () {});
+    }, () {}, logger);
   }
 
   void test_apply_regress41391() async {
@@ -64,7 +70,7 @@
           SourceEdit(9, 0, '\n  enable-experiment:\n  - non-nullable')
         ]));
     // This should not crash.
-    site.performApply();
+    site.performApply([]);
     expect(analysisOptions.readAsStringSync(), '''
 analyzer:
   enable-experiment:
@@ -75,14 +81,14 @@
   void test_applyChangesEmpty() {
     final file = getFile('/test.dart');
     file.writeAsStringSync('void main() {}');
-    site.performApply();
+    site.performApply([]);
     expect(file.readAsStringSync(), 'void main() {}');
     expect(state.hasBeenApplied, true);
   }
 
   void test_applyChangesTwiceThrows() {
-    site.performApply();
-    expect(site.performApply, throwsA(isA<StateError>()));
+    site.performApply([]);
+    expect(() => site.performApply([]), throwsA(isA<StateError>()));
   }
 
   void test_applyMigration_sanityCheck_dontApply() async {
@@ -96,7 +102,7 @@
         'test change',
         Location(path, 10, 0, 1, 10),
         SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
-    expect(() => site.performApply(), throwsA(isA<StateError>()));
+    expect(() => site.performApply([]), throwsA(isA<StateError>()));
     expect(file.readAsStringSync(), currentContent);
     expect(state.hasBeenApplied, false);
   }
@@ -114,7 +120,7 @@
           SourceEdit(10, 0, 'List args'),
           SourceEdit(13, 0, '\n  print(args);\n')
         ]));
-    site.performApply();
+    site.performApply([]);
     expect(file.readAsStringSync(), '''
 void main(List args) {
   print(args);
@@ -132,11 +138,94 @@
         'test change',
         Location(path, 10, 0, 1, 10),
         SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
-    site.performApply();
+    site.performApply([]);
     expect(file.readAsStringSync(), 'void main(List args) {}');
     expect(state.hasBeenApplied, true);
   }
 
+  void test_optOutOfNullSafety_blankLines() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('  \n  \n'),
+        equals('// @dart=2.9\n\n  \n  \n'));
+  }
+
+  void test_optOutOfNullSafety_blankLines_windows() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('  \r\n  \r\n'),
+        equals('// @dart=2.9\r\n\r\n  \r\n  \r\n'));
+  }
+
+  void test_optOutOfNullSafety_commentThenCode() {
+    expect(
+        IncrementalPlan.optCodeOutOfNullSafety('// comment\n\nvoid main() {}'),
+        equals('// comment\n\n// @dart=2.9\n\nvoid main() {}'));
+  }
+
+  void test_optOutOfNullSafety_commentThenSemicolon() {
+    expect(
+        IncrementalPlan.optCodeOutOfNullSafety('// comment\n;\nvoid main() {}'),
+        equals('// comment\n\n// @dart=2.9\n\n;\nvoid main() {}'));
+  }
+
+  void test_optOutOfNullSafety_commentThenCode_windows() {
+    expect(
+        IncrementalPlan.optCodeOutOfNullSafety(
+            '// comment\r\n\r\nvoid main() {}'),
+        equals('// comment\r\n\r\n// @dart=2.9\r\n\r\nvoid main() {}'));
+  }
+
+  void test_optOutOfNullSafety_commentThenDirective() {
+    expect(
+        IncrementalPlan.optCodeOutOfNullSafety(
+            '// comment\nimport "dart:core";'),
+        equals('// comment\n\n// @dart=2.9\n\nimport "dart:core";'));
+  }
+
+  void test_optOutOfNullSafety_commentThenDirective_multiLine() {
+    expect(
+        IncrementalPlan.optCodeOutOfNullSafety(
+            '// comment\n// comment\nimport "dart:core";'),
+        equals(
+            '// comment\n// comment\n\n// @dart=2.9\n\nimport "dart:core";'));
+  }
+
+  void test_optOutOfNullSafety_empty() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety(''), equals('// @dart=2.9'));
+  }
+
+  void test_optOutOfNullSafety_singleComment_multiLine() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('// line 1\n// line 2'),
+        equals('// line 1\n// line 2\n\n// @dart=2.9\n'));
+  }
+
+  void test_optOutOfNullSafety_singleComment_multiLine_indented() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('  // line 1\n  // line 2'),
+        equals('  // line 1\n  // line 2\n\n// @dart=2.9\n'));
+  }
+
+  void test_optOutOfNullSafety_singleComment_singleLine() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('// comment'),
+        equals('// comment\n\n// @dart=2.9\n'));
+  }
+
+  void test_optOutOfNullSafety_singleComment_singleLine_trailingNewline() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('// comment\n'),
+        equals('// comment\n\n\n// @dart=2.9\n'));
+  }
+
+  void test_optOutOfNullSafety_singleLine() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('void main() {}'),
+        equals('// @dart=2.9\n\nvoid main() {}'));
+  }
+
+  void test_optOutOfNullSafety_singleLine_afterBlankLines() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('\n\nvoid main() {}'),
+        equals('// @dart=2.9\n\n\n\nvoid main() {}'));
+  }
+
+  void test_optOutOfNullSafety_singleLine_windows() {
+    expect(IncrementalPlan.optCodeOutOfNullSafety('void main() {}\r\n'),
+        equals('// @dart=2.9\r\n\r\nvoid main() {}\r\n'));
+  }
+
   void test_performEdit() {
     final path = convertPath('/test.dart');
     final file = getFile(path);
@@ -171,6 +260,7 @@
   PreviewSite site;
   DartFixListener dartfixListener;
   MigrationState state;
+  TestLogger logger;
 
   Future<void> performEdit(String path, int offset, String replacement) {
     final pathUri = Uri.file(path).path;
@@ -183,22 +273,34 @@
 @reflectiveTest
 class PreviewSiteWithEngineTest extends NnbdMigrationTestBase
     with ResourceProviderMixin, PreviewSiteTestMixin {
-  @override
-  void setUp() {
-    super.setUp();
+  MigrationInfo migrationInfo;
+
+  Future<void> setUpMigrationInfo(Map<String, String> files,
+      {bool Function(String) shouldBeMigratedFunction,
+      Iterable<String> pathsToProcess}) async {
+    shouldBeMigratedFunction ??= (String path) => true;
+    pathsToProcess ??= files.keys;
+    await buildInfoForTestFiles(files,
+        includedRoot: projectPath,
+        shouldBeMigratedFunction: shouldBeMigratedFunction,
+        pathsToProcess: pathsToProcess);
     dartfixListener = DartFixListener(null, ListenerClient());
-    final migrationInfo = MigrationInfo({}, {}, null, null);
-    state = MigrationState(null, null, dartfixListener, null, {});
+    migrationInfo =
+        MigrationInfo(infos, {}, resourceProvider.pathContext, projectPath);
+    state = MigrationState(
+        null, null, dartfixListener, null, {}, shouldBeMigratedFunction);
     nodeMapper = state.nodeMapper;
     state.pathMapper = PathMapper(resourceProvider);
     state.migrationInfo = migrationInfo;
+    logger = TestLogger(false /*isVerbose*/);
     site = PreviewSite(state, () async {
       return state;
-    }, () {});
+    }, () {}, logger);
   }
 
   void test_applyHintAction() async {
-    final path = convertPath('/home/tests/bin/test.dart');
+    await setUpMigrationInfo({});
+    final path = convertPath('$projectPath/bin/test.dart');
     final file = getFile(path);
     final content = r'''
 int x;
@@ -247,7 +349,8 @@
   }
 
   void test_applyHintAction_removeHint() async {
-    final path = convertPath('/home/tests/bin/test.dart');
+    await setUpMigrationInfo({});
+    final path = convertPath('$projectPath/bin/test.dart');
     final file = getFile(path);
     final content = r'''
 int/*!*/ x;
@@ -285,7 +388,194 @@
     expect(state.needsRerun, true);
   }
 
+  void test_applyMigration_migratePreviouslyOptedOutFile() async {
+    final path = convertPath('$projectPath/lib/a.dart');
+    final content = '''
+// @dart=2.9
+
+void main() {}''';
+    await setUpMigrationInfo({path: content});
+    site.unitInfoMap[path] = UnitInfo(path)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = true;
+    dartfixListener.addSourceFileEdit(
+        'remove DLV comment',
+        Location(path, 0, 14, 1, 1),
+        SourceFileEdit(path, 0, edits: [SourceEdit(0, 14, '')]));
+    var navigationTree =
+        NavigationTreeRenderer(migrationInfo, state.pathMapper).render();
+    site.performApply(navigationTree);
+    expect(getFile(path).readAsStringSync(), 'void main() {}');
+    expect(logger.stdoutBuffer.toString(), contains('''
+Migrated 1 file:
+    ${convertPath('lib/a.dart')}
+'''));
+  }
+
+  void test_applyMigration_optOutEmptyFile() async {
+    final path = convertPath('$projectPath/lib/a.dart');
+    final content = '';
+    await setUpMigrationInfo({path: content});
+    site.unitInfoMap[path] = UnitInfo(path)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = false;
+    var navigationTree =
+        NavigationTreeRenderer(migrationInfo, state.pathMapper).render();
+    var libDir = navigationTree.single as NavigationTreeDirectoryNode;
+    (libDir.subtree.single as NavigationTreeFileNode).migrationStatus =
+        UnitMigrationStatus.optingOut;
+    site.performApply(navigationTree);
+    expect(getFile(path).readAsStringSync(), '// @dart=2.9');
+    expect(logger.stdoutBuffer.toString(), contains('''
+Opted 1 file out of null safety with a new Dart language version comment:
+    ${convertPath('lib/a.dart')}
+'''));
+  }
+
+  void test_applyMigration_optOutFileWithEdits() async {
+    final path = convertPath('$projectPath/lib/a.dart');
+    final content = 'void main() {}';
+    await setUpMigrationInfo({path: content});
+    site.unitInfoMap[path] = UnitInfo(path)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = false;
+    dartfixListener.addSourceFileEdit(
+        'test change',
+        Location(path, 10, 0, 1, 10),
+        SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
+    var navigationTree =
+        NavigationTreeRenderer(migrationInfo, state.pathMapper).render();
+    var libDir = navigationTree.single as NavigationTreeDirectoryNode;
+    (libDir.subtree.single as NavigationTreeFileNode).migrationStatus =
+        UnitMigrationStatus.optingOut;
+    site.performApply(navigationTree);
+    expect(getFile(path).readAsStringSync(), '''
+// @dart=2.9
+
+void main() {}''');
+    expect(logger.stdoutBuffer.toString(), contains('''
+Opted 1 file out of null safety with a new Dart language version comment:
+    ${convertPath('lib/a.dart')}
+'''));
+  }
+
+  void test_applyMigration_optOutFileWithoutEdits() async {
+    final path = convertPath('$projectPath/lib/a.dart');
+    final content = 'void main() {}';
+    await setUpMigrationInfo({path: content});
+    site.unitInfoMap[path] = UnitInfo(path)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = false;
+    var navigationTree =
+        NavigationTreeRenderer(migrationInfo, state.pathMapper).render();
+    var libDir = navigationTree.single as NavigationTreeDirectoryNode;
+    (libDir.subtree.single as NavigationTreeFileNode).migrationStatus =
+        UnitMigrationStatus.optingOut;
+    site.performApply(navigationTree);
+    expect(getFile(path).readAsStringSync(), '''
+// @dart=2.9
+
+void main() {}''');
+    expect(logger.stdoutBuffer.toString(), contains('''
+Opted 1 file out of null safety with a new Dart language version comment:
+    ${convertPath('lib/a.dart')}
+'''));
+  }
+
+  void test_applyMigration_doNotOptOutFileNotInPathsToProcess() async {
+    final pathA = convertPath('$projectPath/lib/a.dart');
+    final pathB = convertPath('$projectPath/lib/b.dart');
+    final content = 'void main() {}';
+    await setUpMigrationInfo({pathA: content, pathB: content},
+        // Neither [pathA] nor [[pathB] should be migrated.
+        shouldBeMigratedFunction: (String path) => false,
+        pathsToProcess: [pathA]);
+    site.unitInfoMap[pathA] = UnitInfo(pathA)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = false
+      ..migrationStatus = UnitMigrationStatus.optingOut;
+    site.unitInfoMap[pathB] = UnitInfo(pathB)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = false
+      ..migrationStatus = UnitMigrationStatus.optingOut;
+    var navigationTree =
+        NavigationTreeRenderer(migrationInfo, state.pathMapper).render();
+    site.performApply(navigationTree);
+    expect(getFile(pathA).readAsStringSync(), '''
+// @dart=2.9
+
+void main() {}''');
+    expect(getFile(pathB).readAsStringSync(), 'void main() {}');
+  }
+
+  void test_applyMigration_optOutOne_migrateAnother() async {
+    final pathA = convertPath('$projectPath/lib/a.dart');
+    final pathB = convertPath('$projectPath/lib/b.dart');
+    final content = 'void main() {}';
+    await setUpMigrationInfo({pathA: content, pathB: content});
+    site.unitInfoMap[pathA] = UnitInfo(pathA)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = false;
+    site.unitInfoMap[pathB] = UnitInfo(pathB)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = false;
+    dartfixListener.addSourceFileEdit(
+        'test change',
+        Location(pathA, 10, 0, 1, 10),
+        SourceFileEdit(pathA, 0, edits: [SourceEdit(10, 0, 'List args')]));
+    dartfixListener.addSourceFileEdit(
+        'test change',
+        Location(pathB, 10, 0, 1, 10),
+        SourceFileEdit(pathB, 0, edits: [SourceEdit(10, 0, 'List args')]));
+    var navigationTree =
+        NavigationTreeRenderer(migrationInfo, state.pathMapper).render();
+    var libDir = navigationTree.single as NavigationTreeDirectoryNode;
+    (libDir.subtree[0] as NavigationTreeFileNode).migrationStatus =
+        UnitMigrationStatus.optingOut;
+    site.performApply(navigationTree);
+    expect(getFile(pathA).readAsStringSync(), '''
+// @dart=2.9
+
+void main() {}''');
+    expect(getFile(pathB).readAsStringSync(), '''
+void main(List args) {}''');
+    expect(logger.stdoutBuffer.toString(), contains('''
+Migrated 1 file:
+    ${convertPath('lib/b.dart')}
+Opted 1 file out of null safety with a new Dart language version comment:
+    ${convertPath('lib/a.dart')}
+'''));
+  }
+
+  void test_applyMigration_optOutPreviouslyOptedOutFile() async {
+    final path = convertPath('$projectPath/lib/a.dart');
+    final content = '''
+// @dart=2.9
+
+int a;''';
+    await setUpMigrationInfo({path: content});
+    site.unitInfoMap[path] = UnitInfo(path)
+      ..diskContent = content
+      ..wasExplicitlyOptedOut = true;
+    dartfixListener.addSourceFileEdit(
+        'remove DLV comment',
+        Location(path, 0, 14, 1, 1),
+        SourceFileEdit(path, 0, edits: [SourceEdit(0, 14, '')]));
+    var navigationTree =
+        NavigationTreeRenderer(migrationInfo, state.pathMapper).render();
+    var libDir = navigationTree.single as NavigationTreeDirectoryNode;
+    (libDir.subtree.single as NavigationTreeFileNode).migrationStatus =
+        UnitMigrationStatus.optingOut;
+    site.performApply(navigationTree);
+    expect(getFile(path).readAsStringSync(), content);
+    expect(logger.stdoutBuffer.toString(), contains('''
+Kept 1 file opted out of null safety:
+    ${convertPath('lib/a.dart')}
+'''));
+  }
+
   void test_performEdit_multiple() async {
+    await setUpMigrationInfo({});
     final path = convertPath('/test.dart');
     final file = getFile(path);
     final content = r'''
diff --git a/pkg/nnbd_migration/tool/codegen/generate_resources.dart b/pkg/nnbd_migration/tool/codegen/generate_resources.dart
index 43c9356..8de7d12 100644
--- a/pkg/nnbd_migration/tool/codegen/generate_resources.dart
+++ b/pkg/nnbd_migration/tool/codegen/generate_resources.dart
@@ -12,12 +12,14 @@
 
 import 'package:args/args.dart';
 import 'package:crypto/crypto.dart';
+import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 
 void main(List<String> args) async {
   var argParser = ArgParser()
     ..addFlag('verify', negatable: false)
     ..addFlag('dev', negatable: false)
+    ..addOption('dart2js_path')
     ..addFlag('help', negatable: false);
   var argResults = argParser.parse(args);
   if (argResults['help'] == true) {
@@ -44,7 +46,8 @@
   if (verify) {
     verifyResourcesGDartGenerated();
   } else {
-    await compileWebFrontEnd(devMode: dev);
+    await compileWebFrontEnd(
+        devMode: dev, dart2jsPath: dart2jsPath(argResults));
 
     print('');
 
@@ -52,6 +55,17 @@
   }
 }
 
+/// Returns the dart2jsPath, either from [argResults] or the Platform.
+String dart2jsPath(ArgResults argResults) {
+  if (argResults.wasParsed('dart2js_path')) {
+    return argResults['dart2js_path'] as String;
+  } else {
+    var sdkBinDir = path.dirname(Platform.resolvedExecutable);
+    var dart2jsBinary = Platform.isWindows ? 'dart2js.bat' : 'dart2js';
+    return path.join(sdkBinDir, dart2jsBinary);
+  }
+}
+
 final File dartSources = File(path.join('pkg', 'nnbd_migration', 'lib', 'src',
     'front_end', 'web', 'migration.dart'));
 
@@ -88,11 +102,8 @@
   return lines.join('\n');
 }
 
-Future<void> compileWebFrontEnd({bool devMode = false}) async {
-  var sdkBinDir = path.dirname(Platform.resolvedExecutable);
-  var dart2jsBinary = Platform.isWindows ? 'dart2js.bat' : 'dart2js';
-  var dart2jsPath = path.join(sdkBinDir, dart2jsBinary);
-
+Future<void> compileWebFrontEnd(
+    {@required bool devMode, @required String dart2jsPath}) async {
   // dart2js -m -o output source
   var process = await Process.start(dart2jsPath, [
     devMode ? '-O1' : '-m',
diff --git a/pkg/nnbd_migration/tool/postmortem.dart b/pkg/nnbd_migration/tool/postmortem.dart
index 2e7a38f..0584991 100644
--- a/pkg/nnbd_migration/tool/postmortem.dart
+++ b/pkg/nnbd_migration/tool/postmortem.dart
@@ -11,7 +11,7 @@
 import 'package:nnbd_migration/src/postmortem_file.dart';
 import 'package:nnbd_migration/src/variables.dart';
 
-main(List<String> args) {
+void main(List<String> args) {
   ArgParser argParser = ArgParser();
   ArgResults parsedArgs;
 
diff --git a/pkg/nnbd_migration/tool/trial_migration.dart b/pkg/nnbd_migration/tool/trial_migration.dart
index 616a5c2..2d0769d 100644
--- a/pkg/nnbd_migration/tool/trial_migration.dart
+++ b/pkg/nnbd_migration/tool/trial_migration.dart
@@ -21,7 +21,7 @@
 
 import 'src/package.dart';
 
-main(List<String> args) async {
+void main(List<String> args) async {
   ArgResults parsedArgs = parseArguments(args);
 
   Sdk sdk = Sdk(parsedArgs['sdk'] as String);
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 6b93319..da7fa09 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -173,6 +173,7 @@
 dev_compiler/test/options/*: SkipByDesign
 front_end/test/hot_reload_e2e_test: Skip
 frontend_server/test/*: SkipByDesign # Only meant to run on vm
+js_runtime/test/*: SkipByDesign # Only meant to run on vm
 vm/test/*: SkipByDesign # Only meant to run on vm
 vm_service/test/*: SkipByDesign # Uses dart:io
 vm_snapshot_analysis/test/*: SkipByDesign # Only meant to run on vm
diff --git a/pkg/scrape/example/strings.dart b/pkg/scrape/example/strings.dart
new file mode 100644
index 0000000..a89fcef
--- /dev/null
+++ b/pkg/scrape/example/strings.dart
@@ -0,0 +1,96 @@
+// 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:analyzer/dart/ast/ast.dart';
+import 'package:scrape/scrape.dart';
+
+final quoteRegExp = RegExp('\\\\?[\'"]');
+
+void main(List<String> arguments) {
+  Scrape()
+    ..addHistogram('Directive')
+    ..addHistogram('Expression')
+    ..addHistogram('Escapes')
+    ..addVisitor(() => StringVisitor())
+    ..runCommandLine(arguments);
+}
+
+class StringVisitor extends ScrapeVisitor {
+  @override
+  void visitSimpleStringLiteral(SimpleStringLiteral node) {
+    _record('Expression', node);
+    _recordEscapes(node);
+    super.visitSimpleStringLiteral(node);
+  }
+
+  @override
+  void visitStringInterpolation(StringInterpolation node) {
+    // Entire expression containing interpolation elements.
+    _record('Expression', node);
+
+    // TODO: Analyze escaped quotes inside strings.
+
+    // TODO: Analyze string literals nested inside interpolation.
+    super.visitStringInterpolation(node);
+  }
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    _record('Directive', node.uri);
+    // Don't recurse so that we don't treat the URI as a string expression.
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    _record('Directive', node.uri);
+    // Don't recurse so that we don't treat the URI as a string expression.
+  }
+
+  @override
+  void visitPartDirective(PartDirective node) {
+    _record('Directive', node.uri);
+    // Don't recurse so that we don't treat the URI as a string expression.
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {
+    if (node.uri != null) _record('Directive', node.uri);
+    // Don't recurse so that we don't treat the URI as a string expression.
+  }
+
+  void _record(String histogram, StringLiteral string) {
+    record(histogram, _quoteType(string.beginToken.lexeme));
+  }
+
+  void _recordEscapes(StringLiteral string) {
+    var quote = _quoteType(string.beginToken.lexeme);
+
+    // Ignore the rarer quote styles.
+    if (quote != "'" && quote != '"') return;
+
+    var contents = string.toSource();
+    contents = contents.substring(1, contents.length - 1);
+
+    var quotes = quoteRegExp
+        .allMatches(contents)
+        .map((match) => match[0])
+        .toSet()
+        .toList();
+    quotes.sort();
+
+    if (quotes.isNotEmpty) {
+      record('Escapes', '$quote containing ${quotes.join(" ")}');
+    }
+  }
+
+  String _quoteType(String lexeme) {
+    const types = ['"""', "'''", 'r"""', "r'''", '"', "'", 'r"', "r'"];
+
+    for (var type in types) {
+      if (lexeme.startsWith(type)) return type;
+    }
+
+    log('Unknown string quote in $lexeme');
+    return '';
+  }
+}
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index 846d39d..370e772 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -663,10 +663,9 @@
 
       case Compiler.dartdevc:
       case Compiler.dartdevk:
-        // TODO(rnystrom): Expand to support other JS execution environments
-        // (other browsers, d8) when tested and working.
         return const [
           Runtime.none,
+          Runtime.d8,
           Runtime.chrome,
           Runtime.edge,
           Runtime.firefox,
diff --git a/pkg/telemetry/test/telemetry_test.dart b/pkg/telemetry/test/telemetry_test.dart
index 7a9b70a..8cd4ca3 100644
--- a/pkg/telemetry/test/telemetry_test.dart
+++ b/pkg/telemetry/test/telemetry_test.dart
@@ -6,7 +6,6 @@
 
 import 'package:telemetry/telemetry.dart';
 import 'package:test/test.dart';
-import 'package:usage/usage.dart';
 
 void main() {
   group('telemetry', () {
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index d92797d..0ec7acd 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -557,29 +557,36 @@
     args.addAll(options);
     args.addAll(_configuration.sharedOptions);
 
+    bool d8Runtime = _configuration.runtime == Runtime.d8;
+
     args.addAll([
       "--ignore-unrecognized-flags",
       "--no-summarize",
+      if (d8Runtime) "--modules=legacy",
       "-o",
       outputFile,
       inputFile,
     ]);
 
-    // Link to the summaries for the available packages, so that they don't
-    // get recompiled into the test's own module.
-    var packageSummaryDir =
-        _configuration.nnbdMode == NnbdMode.strong ? 'pkg_sound' : 'pkg_kernel';
-    for (var package in testPackages) {
-      args.add("-s");
+    if (!d8Runtime) {
+      // TODO(sigmund): allow caching of shared packages in legacy mode too.
+      // Link to the summaries for the available packages, so that they don't
+      // get recompiled into the test's own module.
+      var packageSummaryDir = _configuration.nnbdMode == NnbdMode.strong
+          ? 'pkg_sound'
+          : 'pkg_kernel';
+      for (var package in testPackages) {
+        args.add("-s");
 
-      // Since the summaries for the packages are not near the tests, we give
-      // dartdevc explicit module paths for each one. When the test is run, we
-      // will tell require.js where to find each package's compiled JS.
-      var summary = Path(_configuration.buildDirectory)
-          .append("/gen/utils/dartdevc/$packageSummaryDir/$package.dill")
-          .absolute
-          .toNativePath();
-      args.add("$summary=$package");
+        // Since the summaries for the packages are not near the tests, we give
+        // dartdevc explicit module paths for each one. When the test is run, we
+        // will tell require.js where to find each package's compiled JS.
+        var summary = Path(_configuration.buildDirectory)
+            .append("/gen/utils/dartdevc/$packageSummaryDir/$package.dill")
+            .absolute
+            .toNativePath();
+        args.add("$summary=$package");
+      }
     }
 
     var inputDir = Path(inputFile).append("..").canonicalize().toNativePath();
@@ -598,12 +605,80 @@
     // computeCompilerArguments() to here seems hacky. Is there a cleaner way?
     var sharedOptions = arguments.sublist(0, arguments.length - 1);
     var inputFile = arguments.last;
-    var inputFilename = Uri.file(inputFile).pathSegments.last;
-    var outputFile = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
+    var inputUri = Uri.file(inputFile);
+    var inputFilename = inputUri.pathSegments.last;
+    var moduleName =
+        inputFilename.substring(0, inputFilename.length - ".dart".length);
+    var outputFile = "$tempDir/$moduleName.js";
+    var runFile = outputFile;
+
+    if (_configuration.runtime == Runtime.d8) {
+      // TODO(sigmund): ddc should have a flag to emit an entrypoint file like
+      // the one below, otherwise it is succeptible to break, for example, if
+      // library naming conventions were to change in the future.
+      runFile = "$tempDir/$moduleName.d8.js";
+      var nonNullAsserts = arguments.contains('--null-assertions');
+      var nativeNonNullAsserts = arguments.contains('--native-null-assertions');
+      var weakNullSafetyErrors =
+          arguments.contains('--weak-null-safety-errors');
+      var soundNullSafety = _configuration.nnbdMode == NnbdMode.strong;
+      var weakNullSafetyWarnings = !(weakNullSafetyErrors || soundNullSafety);
+      var repositoryUri = Uri.directory(Repository.dir.toNativePath());
+      var dartLibraryPath = repositoryUri
+          .resolve('pkg/dev_compiler/lib/js/legacy/dart_library.js')
+          .path;
+      var sdkJsDir = Uri.directory(_configuration.buildDirectory)
+          .resolve('gen/utils/dartdevc/');
+      var sdkJsPath = soundNullSafety
+          ? 'sound/legacy/dart_sdk.js'
+          : 'kernel/legacy/dart_sdk.js';
+      var libraryName = inputUri.path
+          .substring(repositoryUri.path.length)
+          .replaceAll("/", "__")
+          .replaceAll("-", "_")
+          .replaceAll(".dart", "");
+
+      // Note: this assumes that d8 is invoked with the dart2js d8.js preamble.
+      // TODO(sigmund): to support other runtimes like js-shell, we may want to
+      // remove the `load` statements here and instead provide those files
+      // through the runtime command-line arguments.
+      File(runFile).writeAsStringSync('''
+        load("$dartLibraryPath");
+        load("$sdkJsDir/$sdkJsPath");
+        load("$outputFile");
+
+        let sdk = dart_library.import("dart_sdk");
+        sdk.dart.weakNullSafetyWarnings($weakNullSafetyWarnings);
+        sdk.dart.weakNullSafetyErrors($weakNullSafetyErrors);
+        sdk.dart.nonNullAsserts($nonNullAsserts);
+        sdk.dart.nativeNonNullAsserts($nativeNonNullAsserts);
+
+        // Invoke main through the d8 preamble to ensure the code is running
+        // within the fake event loop.
+        self.dartMainRunner(function () {
+          dart_library.start("$moduleName", "$libraryName");
+        });
+      '''
+          .replaceAll("\n        ", "\n"));
+    }
 
     return CommandArtifact([
       _createCommand(inputFile, outputFile, sharedOptions, environmentOverrides)
-    ], outputFile, "application/javascript");
+    ], runFile, "application/javascript");
+  }
+
+  List<String> computeRuntimeArguments(
+      RuntimeConfiguration runtimeConfiguration,
+      TestFile testFile,
+      List<String> vmOptions,
+      List<String> originalArguments,
+      CommandArtifact artifact) {
+    var sdkDir = _useSdk
+        ? Uri.directory(_configuration.buildDirectory).resolve('dart-sdk/')
+        : Uri.directory(Repository.dir.toNativePath()).resolve('sdk/');
+    var preambleDir = sdkDir.resolve('lib/_internal/js_runtime/lib/preambles/');
+    return runtimeConfiguration.dart2jsPreambles(preambleDir)
+      ..add(artifact.filename);
   }
 }
 
@@ -1183,7 +1258,7 @@
 
     var compilerArguments = [
       '--verify',
-      '--verify-skip-platform',
+      '--skip-platform-verification',
       "-o",
       outputFileName,
       "--platform",
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 6d682de..7c51016 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -828,6 +828,7 @@
     }
 
     // Expand runtimes.
+    var configurationNumber = 1;
     for (var runtime in runtimes) {
       // Expand architectures.
       var architectures = data["arch"] as String;
@@ -852,8 +853,13 @@
             }
             for (var sanitizerName in sanitizers.split(",")) {
               var sanitizer = Sanitizer.find(sanitizerName);
-              var configuration = Configuration("custom configuration",
-                  architecture, compiler, mode, runtime, system,
+              var configuration = Configuration(
+                  "custom configuration_${configurationNumber++}",
+                  architecture,
+                  compiler,
+                  mode,
+                  runtime,
+                  system,
                   nnbdMode: nnbdMode,
                   sanitizer: sanitizer,
                   timeout: data["timeout"] as int,
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index 6f5d5f2..96f273a 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -221,23 +221,13 @@
   /// Create a directories for generated assets (tests, html files,
   /// pubspec checkouts ...).
   String createOutputDirectory(Path testPath) {
-    var checked = configuration.isChecked ? '-checked' : '';
-    var minified = configuration.isMinified ? '-minified' : '';
-    var sdk = configuration.useSdk ? '-sdk' : '';
-    var dirName = "${configuration.compiler.name}-${configuration.runtime.name}"
-        "$checked$minified$sdk";
-    return createGeneratedTestDirectoryHelper("tests", dirName, testPath);
+    return createGeneratedTestDirectoryHelper(
+        "tests", configuration.configuration.name, testPath);
   }
 
   String createCompilationOutputDirectory(Path testPath) {
-    var checked = configuration.isChecked ? '-checked' : '';
-    var minified = configuration.isMinified ? '-minified' : '';
-    var csp = configuration.isCsp ? '-csp' : '';
-    var sdk = configuration.useSdk ? '-sdk' : '';
-    var dirName = "${configuration.compiler.name}"
-        "$checked$minified$csp$sdk";
     return createGeneratedTestDirectoryHelper(
-        "compilations", dirName, testPath);
+        "compilations", configuration.configuration.name, testPath);
   }
 
   String createPubspecCheckoutDirectory(Path directoryOfPubspecYaml) {
diff --git a/pkg/test_runner/lib/src/utils.dart b/pkg/test_runner/lib/src/utils.dart
index b1c41171..fc27e18 100644
--- a/pkg/test_runner/lib/src/utils.dart
+++ b/pkg/test_runner/lib/src/utils.dart
@@ -414,13 +414,11 @@
   static void deleteTempSnapshotDirectory(TestConfiguration configuration) {
     if (configuration.compiler == Compiler.dartk ||
         configuration.compiler == Compiler.dartkp) {
-      var checked = configuration.isChecked ? '-checked' : '';
-      var minified = configuration.isMinified ? '-minified' : '';
-      var csp = configuration.isCsp ? '-csp' : '';
-      var sdk = configuration.useSdk ? '-sdk' : '';
-      var dirName = "${configuration.compiler.name}$checked$minified$csp$sdk";
-      var generatedPath =
-          configuration.buildDirectory + "/generated_compilations/$dirName";
+      var generatedPath = [
+        configuration.buildDirectory,
+        "generated_compilations",
+        configuration.configuration.name
+      ].join('/');
       if (FileSystemEntity.isDirectorySync(generatedPath)) {
         TestUtils.deleteDirectory(generatedPath);
       }
diff --git a/pkg/test_runner/tool/convert_multitest.dart b/pkg/test_runner/tool/convert_multitest.dart
index dbf146c..c44394e 100644
--- a/pkg/test_runner/tool/convert_multitest.dart
+++ b/pkg/test_runner/tool/convert_multitest.dart
@@ -22,10 +22,15 @@
 
 Future<List<StaticError>> getErrors(
     List<String> options, String filePath) async {
-  return [
-    ...await runAnalyzer(filePath, options),
-    ...await runCfe(filePath, options)
-  ];
+  var analyzerErrors = await runAnalyzer(filePath, options);
+  if (analyzerErrors == null) {
+    exit(1);
+  }
+  var cfeErrors = await runCfe(filePath, options);
+  if (cfeErrors == null) {
+    exit(1);
+  }
+  return [...analyzerErrors, ...cfeErrors];
 }
 
 bool areSameErrors(List<StaticError> first, List<StaticError> second) {
@@ -142,18 +147,8 @@
   }
 }
 
-Future<void> main(List<String> arguments) async {
-  var parser = ArgParser();
-  parser.addFlag("verbose", abbr: "v", help: "print additional information");
-  parser.addFlag("write", abbr: "w", help: "write output to input file");
-  var results = parser.parse(arguments);
-  if (results.rest.length != 1) {
-    print("Usage: convert_multi_test.dart [-v] [-w] <input file>");
-    exitCode = 1;
-    return;
-  }
-  var verbose = results["verbose"] as bool;
-  var testFilePath = Uri.base.resolve(results.rest.single).toFilePath();
+Future<void> convertFile(String testFilePath, bool writeToFile, bool verbose,
+    List<String> experiments) async {
   var testFile = File(testFilePath);
   if (!await testFile.exists()) {
     print("File '${testFile.uri.toFilePath()}' not found");
@@ -190,6 +185,9 @@
     // Get the reported errors for the multi-test and all generated sub-tests
     // from the analyser and the common front-end.
     var options = test.sharedOptions;
+    if (experiments.isNotEmpty) {
+      options.add("--enable-experiment=${experiments.join(',')}");
+    }
     var errors = <List<StaticError>>[];
     for (var test in tests) {
       if (verbose) {
@@ -198,7 +196,7 @@
       errors.add(await getErrors(options, test.path.toNativePath()));
     }
     if (errors[1].isNotEmpty) {
-      throw "internal error: errors in '/none' test";
+      throw UnableToConvertException("internal error: errors in '/none' test");
     }
     // Check that the multi-test generates the same errors as all sub-tests
     // together - otherwise converting the test would be unsound.
@@ -217,7 +215,6 @@
     // and output the result.
     var annotatedContent =
         updateErrorExpectations(contentWithoutMarkers, errors[0]);
-    var writeToFile = results["write"] as bool;
     if (writeToFile) {
       await testFile.writeAsString(annotatedContent);
       print("Converted test '${test.path.toNativePath()}'.");
@@ -245,3 +242,27 @@
     outputDirectory.delete(recursive: true);
   }
 }
+
+Future<void> main(List<String> arguments) async {
+  var parser = ArgParser();
+  parser.addFlag("verbose", abbr: "v", help: "print additional information");
+  parser.addFlag("write", abbr: "w", help: "write output to input file");
+  parser.addOption("enable-experiment",
+      help: "Enable one or more experimental features", allowMultiple: true);
+
+  var results = parser.parse(arguments);
+  if (results.rest.isEmpty) {
+    print("Usage: convert_multi_test.dart [-v] [-w] <input files>");
+    print(parser.getUsage());
+    exitCode = 1;
+    return;
+  }
+  var verbose = results["verbose"] as bool;
+  var filePaths =
+      results.rest.map((path) => Uri.base.resolve(path).toFilePath());
+  var writeToFile = results["write"] as bool;
+  for (var testFilePath in filePaths) {
+    await convertFile(testFilePath, writeToFile, verbose,
+        (results["enable-experiment"] as List).cast<String>());
+  }
+}
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index c6f6c16..1f7fc84 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -358,8 +358,16 @@
   /// update the test to match new expectations.
   final String autoFixCommand;
 
+  /// If set, the test can be fixed by running
+  ///
+  ///     dart pkg/front_end/tool/update_expectations.dart
+  ///
+  final bool canBeFixWithUpdateExpectations;
+
   Result(this.output, this.outcome, this.error,
-      {this.trace, this.autoFixCommand});
+      {this.trace,
+      this.autoFixCommand,
+      this.canBeFixWithUpdateExpectations: false});
 
   Result.pass(O output) : this(output, Expectation.Pass, null);
 
@@ -384,7 +392,9 @@
 
   Result<O2> copyWithOutput<O2>(O2 output) {
     return new Result<O2>(output, outcome, error,
-        trace: trace, autoFixCommand: autoFixCommand)
+        trace: trace,
+        autoFixCommand: autoFixCommand,
+        canBeFixWithUpdateExpectations: canBeFixWithUpdateExpectations)
       ..logs.addAll(logs);
   }
 }
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 13aa646..a558085 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -23,7 +23,9 @@
 import 'dart:async' show Future, ZoneSpecification, runZoned;
 import 'dart:collection' show UnmodifiableMapBase;
 import 'dart:convert' show utf8;
-import 'dart:io' show Directory, File, Platform, stderr hide FileSystemEntity;
+import 'dart:io'
+    show Directory, File, Platform, stderr, stdout
+    hide FileSystemEntity;
 import 'dart:isolate';
 import 'dart:typed_data' show Uint8List;
 
@@ -44,8 +46,6 @@
     show autoDetectNullSafetyMode, createLoadedLibrariesSet;
 import 'package:vm/http_filesystem.dart';
 import 'package:vm/target/vm.dart' show VmTarget;
-import 'package:front_end/src/api_prototype/compiler_options.dart'
-    show CompilerOptions, parseExperimentalFlags;
 
 final bool verbose = new bool.fromEnvironment('DFE_VERBOSE');
 final bool dumpKernel = new bool.fromEnvironment('DFE_DUMP_KERNEL');
@@ -89,12 +89,13 @@
 CompilerOptions setupCompilerOptions(
     FileSystem fileSystem,
     Uri platformKernelPath,
-    bool suppressWarnings,
     bool enableAsserts,
     int nullSafety,
     List<String> experimentalFlags,
     Uri packagesUri,
-    List<String> errors) {
+    List<String> errors,
+    String invocationModes,
+    String verbosityLevel) {
   final expFlags = <String>[];
   if (experimentalFlags != null) {
     for (String flag in experimentalFlags) {
@@ -102,6 +103,7 @@
     }
   }
 
+  Verbosity verbosity = Verbosity.parseArgument(verbosityLevel);
   return new CompilerOptions()
     ..fileSystem = fileSystem
     ..target = new VmTarget(new TargetFlags(
@@ -118,37 +120,48 @@
         ? NnbdMode.Strong
         : NnbdMode.Weak
     ..onDiagnostic = (DiagnosticMessage message) {
-      bool printMessage;
+      bool printToStdErr = false;
+      bool printToStdOut = false;
       switch (message.severity) {
         case Severity.error:
         case Severity.internalProblem:
           // TODO(sigmund): support emitting code with errors as long as they
           // are handled in the generated code.
-          printMessage = false; // errors are printed by VM
+          printToStdErr = false; // errors are printed by VM
           errors.addAll(message.plainTextFormatted);
           break;
         case Severity.warning:
-          printMessage = !suppressWarnings;
+          printToStdErr = true;
+          break;
+        case Severity.info:
+          printToStdOut = true;
           break;
         case Severity.context:
         case Severity.ignored:
           throw "Unexpected severity: ${message.severity}";
       }
-      if (printMessage) {
-        printDiagnosticMessage(message, stderr.writeln);
+      if (Verbosity.shouldPrint(verbosity, message)) {
+        if (printToStdErr) {
+          printDiagnosticMessage(message, stderr.writeln);
+        } else if (printToStdOut) {
+          printDiagnosticMessage(message, stdout.writeln);
+        }
       }
-    };
+    }
+    ..invocationModes = InvocationMode.parseArguments(invocationModes)
+    ..verbosity = verbosity;
 }
 
 abstract class Compiler {
   final int isolateId;
   final FileSystem fileSystem;
   final Uri platformKernelPath;
-  final bool suppressWarnings;
   final bool enableAsserts;
   final int nullSafety;
   final List<String> experimentalFlags;
   final String packageConfig;
+  final String invocationModes;
+  final String verbosityLevel;
 
   // Code coverage and hot reload are only supported by incremental compiler,
   // which is used if vm-service is enabled.
@@ -160,13 +173,14 @@
   CompilerOptions options;
 
   Compiler(this.isolateId, this.fileSystem, this.platformKernelPath,
-      {this.suppressWarnings: false,
-      this.enableAsserts: false,
+      {this.enableAsserts: false,
       this.nullSafety: kNullSafetyOptionUnspecified,
       this.experimentalFlags: null,
       this.supportCodeCoverage: false,
       this.supportHotReload: false,
-      this.packageConfig: null}) {
+      this.packageConfig: null,
+      this.invocationModes: '',
+      this.verbosityLevel: Verbosity.defaultValue}) {
     Uri packagesUri = null;
     if (packageConfig != null) {
       packagesUri = Uri.parse(packageConfig);
@@ -184,12 +198,13 @@
     options = setupCompilerOptions(
         fileSystem,
         platformKernelPath,
-        suppressWarnings,
         enableAsserts,
         nullSafety,
         experimentalFlags,
         packagesUri,
-        errors);
+        errors,
+        invocationModes,
+        verbosityLevel);
   }
 
   Future<CompilerResult> compile(Uri script) {
@@ -275,35 +290,37 @@
 
   IncrementalCompilerWrapper(
       int isolateId, FileSystem fileSystem, Uri platformKernelPath,
-      {bool suppressWarnings: false,
-      bool enableAsserts: false,
+      {bool enableAsserts: false,
       int nullSafety: kNullSafetyOptionUnspecified,
       List<String> experimentalFlags: null,
-      String packageConfig: null})
+      String packageConfig: null,
+      String invocationModes: '',
+      String verbosityLevel: Verbosity.defaultValue})
       : super(isolateId, fileSystem, platformKernelPath,
-            suppressWarnings: suppressWarnings,
             enableAsserts: enableAsserts,
             nullSafety: nullSafety,
             experimentalFlags: experimentalFlags,
             supportHotReload: true,
             supportCodeCoverage: true,
-            packageConfig: packageConfig);
+            packageConfig: packageConfig,
+            invocationModes: invocationModes,
+            verbosityLevel: verbosityLevel);
 
   factory IncrementalCompilerWrapper.forExpressionCompilationOnly(
       Component component,
       int isolateId,
       FileSystem fileSystem,
       Uri platformKernelPath,
-      {bool suppressWarnings: false,
-      bool enableAsserts: false,
+      {bool enableAsserts: false,
       List<String> experimentalFlags: null,
-      String packageConfig: null}) {
+      String packageConfig: null,
+      String invocationModes: ''}) {
     IncrementalCompilerWrapper result = IncrementalCompilerWrapper(
         isolateId, fileSystem, platformKernelPath,
-        suppressWarnings: suppressWarnings,
         enableAsserts: enableAsserts,
         experimentalFlags: experimentalFlags,
-        packageConfig: packageConfig);
+        packageConfig: packageConfig,
+        invocationModes: invocationModes);
     result.generator = new IncrementalCompiler.forExpressionCompilationOnly(
         component,
         result.options,
@@ -328,11 +345,11 @@
   Future<IncrementalCompilerWrapper> clone(int isolateId) async {
     IncrementalCompilerWrapper clone = IncrementalCompilerWrapper(
         isolateId, fileSystem, platformKernelPath,
-        suppressWarnings: suppressWarnings,
         enableAsserts: enableAsserts,
         nullSafety: nullSafety,
         experimentalFlags: experimentalFlags,
-        packageConfig: packageConfig);
+        packageConfig: packageConfig,
+        invocationModes: invocationModes);
 
     generator.resetDeltaState();
     Component fullComponent = await generator.compile();
@@ -358,17 +375,19 @@
   SingleShotCompilerWrapper(
       int isolateId, FileSystem fileSystem, Uri platformKernelPath,
       {this.requireMain: false,
-      bool suppressWarnings: false,
       bool enableAsserts: false,
       int nullSafety: kNullSafetyOptionUnspecified,
       List<String> experimentalFlags: null,
-      String packageConfig: null})
+      String packageConfig: null,
+      String invocationModes: '',
+      String verbosityLevel: Verbosity.defaultValue})
       : super(isolateId, fileSystem, platformKernelPath,
-            suppressWarnings: suppressWarnings,
             enableAsserts: enableAsserts,
             nullSafety: nullSafety,
             experimentalFlags: experimentalFlags,
-            packageConfig: packageConfig);
+            packageConfig: packageConfig,
+            invocationModes: invocationModes,
+            verbosityLevel: verbosityLevel);
 
   @override
   Future<CompilerResult> compileInternal(Uri script) async {
@@ -398,13 +417,14 @@
 
 Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateId,
     List sourceFiles, Uri platformKernelPath, List<int> platformKernel,
-    {bool suppressWarnings: false,
-    bool enableAsserts: false,
+    {bool enableAsserts: false,
     int nullSafety: kNullSafetyOptionUnspecified,
     List<String> experimentalFlags: null,
     String packageConfig: null,
     String multirootFilepaths,
-    String multirootScheme}) async {
+    String multirootScheme,
+    String invocationModes: '',
+    String verbosityLevel: Verbosity.defaultValue}) async {
   IncrementalCompilerWrapper compiler = lookupIncrementalCompiler(isolateId);
   if (compiler != null) {
     updateSources(compiler, sourceFiles);
@@ -429,11 +449,12 @@
       // isolate was shut down. Message should be handled here in this script.
       compiler = new IncrementalCompilerWrapper(
           isolateId, fileSystem, platformKernelPath,
-          suppressWarnings: suppressWarnings,
           enableAsserts: enableAsserts,
           nullSafety: nullSafety,
           experimentalFlags: experimentalFlags,
-          packageConfig: packageConfig);
+          packageConfig: packageConfig,
+          invocationModes: invocationModes,
+          verbosityLevel: verbosityLevel);
     }
     isolateCompilers[isolateId] = compiler;
   }
@@ -482,10 +503,9 @@
   final bool isStatic = request[9];
   final List dillData = request[10];
   final int blobLoadCount = request[11];
-  final bool suppressWarnings = request[12];
-  final bool enableAsserts = request[13];
+  final bool enableAsserts = request[12];
   final List<String> experimentalFlags =
-      request[14] != null ? request[14].cast<String>() : null;
+      request[13] != null ? request[13].cast<String>() : null;
 
   IncrementalCompilerWrapper compiler = isolateCompilers[isolateId];
 
@@ -565,7 +585,6 @@
       try {
         compiler = new IncrementalCompilerWrapper.forExpressionCompilationOnly(
             component, isolateId, fileSystem, null,
-            suppressWarnings: suppressWarnings,
             enableAsserts: enableAsserts,
             experimentalFlags: experimentalFlags,
             packageConfig: dotPackagesFile);
@@ -653,10 +672,7 @@
   return utf8.encode(uris.map(_escapeDependency).join(" "));
 }
 
-Future _processListDependenciesRequest(request) async {
-  final SendPort port = request[1];
-  final int isolateId = request[6];
-
+Future _processListDependenciesRequest(SendPort port, int isolateId) async {
   final List<Uri> dependencies = isolateDependencies[isolateId] ?? <Uri>[];
 
   CompilationResult result;
@@ -710,25 +726,26 @@
     return;
   }
 
-  if (tag == kListDependenciesTag) {
-    await _processListDependenciesRequest(request);
-    return;
-  }
-
   if (tag == kNotifyIsolateShutdownTag) {
     await _processIsolateShutdownNotification(request);
     return;
   }
 
   final SendPort port = request[1];
+  final int isolateId = request[7];
+
+  if (tag == kListDependenciesTag) {
+    await _processListDependenciesRequest(port, isolateId);
+    return;
+  }
+
   final String inputFileUri = request[2];
   final Uri script =
       inputFileUri != null ? Uri.base.resolve(inputFileUri) : null;
   final bool incremental = request[4];
-  final int nullSafety = request[5];
-  final int isolateId = request[6];
-  final List sourceFiles = request[7];
-  final bool suppressWarnings = request[8];
+  final bool snapshot = request[5];
+  final int nullSafety = request[6];
+  final List sourceFiles = request[8];
   final bool enableAsserts = request[9];
   final List<String> experimentalFlags =
       request[10] != null ? request[10].cast<String>() : null;
@@ -736,7 +753,7 @@
   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;
   if (request[3] is String) {
@@ -749,6 +766,8 @@
         computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
   }
 
+  final String invocationModes = snapshot ? 'compile' : '';
+
   Compiler compiler;
 
   // Update the in-memory file system with the provided sources. Currently, only
@@ -793,8 +812,16 @@
       packagesUri = Uri.directory(workingDirectory).resolveUri(packagesUri);
     }
     final List<String> errors = <String>[];
-    var options = setupCompilerOptions(fileSystem, platformKernelPath, false,
-        false, nullSafety, experimentalFlags, packagesUri, errors);
+    var options = setupCompilerOptions(
+        fileSystem,
+        platformKernelPath,
+        false,
+        nullSafety,
+        experimentalFlags,
+        packagesUri,
+        errors,
+        invocationModes,
+        verbosityLevel);
 
     // script should only be null for kUpdateSourcesTag.
     assert(script != null);
@@ -814,24 +841,26 @@
   if (incremental) {
     compiler = await lookupOrBuildNewIncrementalCompiler(
         isolateId, sourceFiles, platformKernelPath, platformKernel,
-        suppressWarnings: suppressWarnings,
         enableAsserts: enableAsserts,
         nullSafety: nullSafety,
         experimentalFlags: experimentalFlags,
         packageConfig: packageConfig,
         multirootFilepaths: multirootFilepaths,
-        multirootScheme: multirootScheme);
+        multirootScheme: multirootScheme,
+        invocationModes: invocationModes,
+        verbosityLevel: verbosityLevel);
   } else {
     FileSystem fileSystem = _buildFileSystem(
         sourceFiles, platformKernel, multirootFilepaths, multirootScheme);
     compiler = new SingleShotCompilerWrapper(
         isolateId, fileSystem, platformKernelPath,
         requireMain: false,
-        suppressWarnings: suppressWarnings,
         enableAsserts: enableAsserts,
         nullSafety: nullSafety,
         experimentalFlags: experimentalFlags,
-        packageConfig: packageConfig);
+        packageConfig: packageConfig,
+        invocationModes: invocationModes,
+        verbosityLevel: verbosityLevel);
   }
 
   CompilationResult result;
@@ -975,16 +1004,17 @@
     scriptUri,
     platformKernelPath,
     false /* incremental */,
+    false /* snapshot */,
     kNullSafetyOptionUnspecified /* null safety */,
     1 /* isolateId chosen randomly */,
     [] /* source files */,
-    false /* suppress warnings */,
     false /* enable asserts */,
     null /* experimental_flags */,
     null /* package_config */,
     null /* multirootFilepaths */,
     null /* multirootScheme */,
     null /* original working directory */,
+    'all' /* CFE logging mode */,
   ];
   await _processLoadRequest(request);
 }
diff --git a/pkg/vm/bin/protobuf_aware_treeshaker.dart b/pkg/vm/bin/protobuf_aware_treeshaker.dart
index d1fa2d1..69aa466 100644
--- a/pkg/vm/bin/protobuf_aware_treeshaker.dart
+++ b/pkg/vm/bin/protobuf_aware_treeshaker.dart
@@ -30,13 +30,14 @@
 import 'package:args/args.dart';
 import 'package:kernel/kernel.dart';
 import 'package:kernel/binary/ast_to_binary.dart';
+import 'package:kernel/core_types.dart' show CoreTypes;
 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/protobuf_aware_treeshaker/transformer.dart'
-    as treeshaker;
+import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
+    show transformComponent;
 
 ArgResults parseArgs(List<String> args) {
   ArgParser argParser = ArgParser()
@@ -99,11 +100,6 @@
   final input = argResults.rest[0];
   final output = argResults.rest[1];
 
-  final Map<String, String> environment = Map.fromIterable(
-      argResults['define'].map((x) => x.split('=')),
-      key: (x) => x[0],
-      value: (x) => x[1]);
-
   var bytes = File(input).readAsBytesSync();
   final platformFile = argResults['platform'];
   if (platformFile != null) {
@@ -119,31 +115,19 @@
   if (argResults['aot']) {
     const bool useGlobalTypeFlowAnalysis = true;
     const bool enableAsserts = false;
-    const bool useProtobufAwareTreeShaker = true;
-    const bool useProtobufAwareTreeShakerV2 = false;
+    const bool useProtobufAwareTreeShakerV2 = true;
     final nopErrorDetector = ErrorDetector();
     runGlobalTransformations(
       target,
       component,
       useGlobalTypeFlowAnalysis,
       enableAsserts,
-      useProtobufAwareTreeShaker,
       useProtobufAwareTreeShakerV2,
       nopErrorDetector,
     );
   } else {
-    treeshaker.TransformationInfo info = treeshaker.transformComponent(
-        component, environment, target,
-        collectInfo: argResults['verbose']);
-
-    if (argResults['verbose']) {
-      for (String fieldName in info.removedMessageFields) {
-        print('Removed $fieldName');
-      }
-      for (Class removedClass in info.removedMessageClasses) {
-        print('Removed $removedClass');
-      }
-    }
+    globalTypeFlow.transformComponent(target, CoreTypes(component), component,
+        treeShakeProtobufs: true, treeShakeSignatures: false);
   }
 
   if (argResults['aot']) {
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index eb8f045..e0368f7 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -23,6 +23,7 @@
         CompilerContext,
         CompilerOptions,
         CompilerResult,
+        InvocationMode,
         DiagnosticMessage,
         DiagnosticMessageHandler,
         ExperimentalFlag,
@@ -32,6 +33,7 @@
         ProcessedOptions,
         Severity,
         StandardFileSystem,
+        Verbosity,
         getMessageUri,
         kernelForProgram,
         parseExperimentalArguments,
@@ -55,8 +57,6 @@
     show transformComponent;
 import 'transformations/no_dynamic_invocations_annotator.dart'
     as no_dynamic_invocations_annotator show transformComponent;
-import 'transformations/protobuf_aware_treeshaker/transformer.dart'
-    as protobuf_tree_shaker;
 import 'transformations/type_flow/transformer.dart' as globalTypeFlow
     show transformComponent;
 import 'transformations/obfuscation_prohibitions_annotator.dart'
@@ -104,9 +104,6 @@
   args.addFlag('tree-shake-write-only-fields',
       help: 'Enable tree shaking of fields which are only written in AOT mode.',
       defaultsTo: true);
-  args.addFlag('protobuf-tree-shaker',
-      help: 'Enable protobuf tree shaker transformation in AOT mode.',
-      defaultsTo: false);
   args.addFlag('protobuf-tree-shaker-v2',
       help: 'Enable protobuf tree shaker v2 in AOT mode.', defaultsTo: false);
   args.addMultiOption('define',
@@ -132,6 +129,13 @@
   args.addFlag('track-widget-creation',
       help: 'Run a kernel transformer to track creation locations for widgets.',
       defaultsTo: false);
+  args.addOption('invocation-modes',
+      help: 'Provides information to the front end about how it is invoked.',
+      defaultsTo: '');
+  args.addOption('verbosity',
+      help: 'Sets the verbosity level used for filtering messages during '
+          'compilation.',
+      defaultsTo: Verbosity.defaultValue);
 }
 
 /// Create ArgParser and populate it with options consumed by [runCompiler].
@@ -174,7 +178,6 @@
   final bool embedSources = options['embed-sources'];
   final bool enableAsserts = options['enable-asserts'];
   final bool nullSafety = options['sound-null-safety'];
-  final bool useProtobufTreeShaker = options['protobuf-tree-shaker'];
   final bool useProtobufTreeShakerV2 = options['protobuf-tree-shaker-v2'];
   final bool splitOutputByPackages = options['split-output-by-packages'];
   final String manifestFilename = options['manifest'];
@@ -217,7 +220,8 @@
     mainUri = await convertToPackageUri(fileSystem, mainUri, packagesUri);
   }
 
-  final errorPrinter = new ErrorPrinter();
+  final verbosity = Verbosity.parseArgument(options['verbosity']);
+  final errorPrinter = new ErrorPrinter(verbosity);
   final errorDetector = new ErrorDetector(previousErrorHandler: errorPrinter);
 
   final CompilerOptions compilerOptions = new CompilerOptions()
@@ -232,7 +236,10 @@
     ..onDiagnostic = (DiagnosticMessage m) {
       errorDetector(m);
     }
-    ..embedSourceText = embedSources;
+    ..embedSourceText = embedSources
+    ..invocationModes =
+        InvocationMode.parseArguments(options['invocation-modes'])
+    ..verbosity = verbosity;
 
   if (nullSafety == null &&
       compilerOptions.isExperimentEnabled(ExperimentalFlag.nonNullable)) {
@@ -255,7 +262,6 @@
       useGlobalTypeFlowAnalysis: tfa,
       environmentDefines: environmentDefines,
       enableAsserts: enableAsserts,
-      useProtobufTreeShaker: useProtobufTreeShaker,
       useProtobufTreeShakerV2: useProtobufTreeShakerV2,
       minimalKernel: minimalKernel,
       treeShakeWriteOnlyFields: treeShakeWriteOnlyFields,
@@ -322,7 +328,6 @@
     bool useGlobalTypeFlowAnalysis: false,
     Map<String, String> environmentDefines,
     bool enableAsserts: true,
-    bool useProtobufTreeShaker: false,
     bool useProtobufTreeShakerV2: false,
     bool minimalKernel: false,
     bool treeShakeWriteOnlyFields: false,
@@ -356,7 +361,6 @@
         component,
         useGlobalTypeFlowAnalysis,
         enableAsserts,
-        useProtobufTreeShaker,
         useProtobufTreeShakerV2,
         errorDetector,
         minimalKernel: minimalKernel,
@@ -414,7 +418,6 @@
     Component component,
     bool useGlobalTypeFlowAnalysis,
     bool enableAsserts,
-    bool useProtobufTreeShaker,
     bool useProtobufTreeShakerV2,
     ErrorDetector errorDetector,
     {bool minimalKernel: false,
@@ -435,10 +438,6 @@
   // before type flow analysis so TFA won't take unreachable code into account.
   unreachable_code_elimination.transformComponent(component, enableAsserts);
 
-  if (useProtobufTreeShaker && useProtobufTreeShakerV2) {
-    throw 'Cannot use both versions of protobuf tree shaker';
-  }
-
   if (useGlobalTypeFlowAnalysis) {
     globalTypeFlow.transformComponent(target, coreTypes, component,
         treeShakeSignatures: !minimalKernel,
@@ -449,19 +448,6 @@
     no_dynamic_invocations_annotator.transformComponent(component);
   }
 
-  if (useProtobufTreeShaker) {
-    if (!useGlobalTypeFlowAnalysis) {
-      throw 'Protobuf tree shaker requires type flow analysis (--tfa)';
-    }
-
-    protobuf_tree_shaker.removeUnusedProtoReferences(
-        component, coreTypes, null);
-
-    globalTypeFlow.transformComponent(target, coreTypes, component,
-        treeShakeSignatures: !minimalKernel,
-        treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
-  }
-
   // TODO(35069): avoid recomputing CSA by reading it from the platform files.
   void ignoreAmbiguousSupertypes(cls, a, b) {}
   final hierarchy = new ClassHierarchy(component, coreTypes,
@@ -510,10 +496,11 @@
 }
 
 class ErrorPrinter {
+  final Verbosity verbosity;
   final DiagnosticMessageHandler previousErrorHandler;
   final compilationMessages = <Uri, List<DiagnosticMessage>>{};
 
-  ErrorPrinter({this.previousErrorHandler});
+  ErrorPrinter(this.verbosity, {this.previousErrorHandler});
 
   void call(DiagnosticMessage message) {
     final sourceUri = getMessageUri(message);
@@ -523,10 +510,23 @@
 
   void printCompilationMessages() {
     final sortedUris = compilationMessages.keys.toList()
-      ..sort((a, b) => '$a'.compareTo('$b'));
+      ..sort((a, b) {
+        // Sort messages without a corresponding uri before the location based
+        // messages, since these related to the whole compilation.
+        if (a != null && b != null) {
+          return '$a'.compareTo('$b');
+        } else if (a != null) {
+          return 1;
+        } else if (b != null) {
+          return -1;
+        }
+        return 0;
+      });
     for (final Uri sourceUri in sortedUris) {
       for (final DiagnosticMessage message in compilationMessages[sourceUri]) {
-        printDiagnosticMessage(message, print);
+        if (Verbosity.shouldPrint(verbosity, message)) {
+          printDiagnosticMessage(message, print);
+        }
       }
     }
   }
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index c117efa..e08f278 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -21,8 +21,8 @@
     show VmConstantsBackend;
 
 import '../transformations/call_site_annotator.dart' as callSiteAnnotator;
-import '../transformations/lowering.dart' as lowering show transformLibraries;
-import '../transformations/ffi.dart' as transformFfi show ReplacedMembers;
+import '../transformations/lowering.dart' as lowering
+    show transformLibraries, transformProcedure;
 import '../transformations/ffi_definitions.dart' as transformFfiDefinitions
     show transformLibraries;
 import '../transformations/ffi_use_sites.dart' as transformFfiUseSites
@@ -64,6 +64,9 @@
       !flags.forceNoExplicitGetterCallsForTesting;
 
   @override
+  bool get supportsNewMethodInvocationEncoding => false;
+
+  @override
   String get name => 'vm';
 
   // This is the order that bootstrap libraries are loaded according to
@@ -152,17 +155,16 @@
         this, coreTypes, hierarchy, libraries, referenceFromIndex);
     logger?.call("Transformed mixin applications");
 
-    transformFfi.ReplacedMembers replacedFields =
-        transformFfiDefinitions.transformLibraries(
-            component,
-            coreTypes,
-            hierarchy,
-            libraries,
-            diagnosticReporter,
-            referenceFromIndex,
-            changedStructureNotifier);
+    final ffiTransformerData = transformFfiDefinitions.transformLibraries(
+        component,
+        coreTypes,
+        hierarchy,
+        libraries,
+        diagnosticReporter,
+        referenceFromIndex,
+        changedStructureNotifier);
     transformFfiUseSites.transformLibraries(component, coreTypes, hierarchy,
-        libraries, diagnosticReporter, replacedFields, referenceFromIndex);
+        libraries, diagnosticReporter, ffiTransformerData, referenceFromIndex);
     logger?.call("Transformed ffi annotations");
 
     // TODO(kmillikin): Make this run on a per-method basis.
@@ -188,6 +190,10 @@
     transformAsync.transformProcedure(
         new TypeEnvironment(coreTypes, hierarchy), procedure);
     logger?.call("Transformed async functions");
+
+    lowering.transformProcedure(
+        procedure, coreTypes, hierarchy, flags.enableNullSafety);
+    logger?.call("Lowering transformations performed");
   }
 
   Expression _instantiateInvocationMirrorWithType(
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index 2752c23..e27e3f3 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -34,6 +34,7 @@
   kFloat,
   kDouble,
   kVoid,
+  kOpaque,
   kStruct,
   kHandle,
 }
@@ -60,6 +61,7 @@
   'Float',
   'Double',
   'Void',
+  'Opaque',
   'Struct',
   'Handle'
 ];
@@ -86,6 +88,7 @@
   4, // Float
   8, // Double
   UNKNOWN, // Void
+  UNKNOWN, // Opaque
   UNKNOWN, // Struct
   WORD_SIZE, // Handle
 ];
@@ -193,21 +196,34 @@
   final Class doubleClass;
   final Class listClass;
   final Class typeClass;
+  final Procedure unsafeCastMethod;
+  final Class typedDataClass;
+  final Procedure typedDataBufferGetter;
+  final Procedure typedDataOffsetInBytesGetter;
+  final Procedure byteBufferAsUint8List;
   final Class pragmaClass;
   final Field pragmaName;
   final Field pragmaOptions;
   final Procedure listElementAt;
+  final Procedure numAddition;
 
   final Library ffiLibrary;
+  final Class allocatorClass;
   final Class nativeFunctionClass;
+  final Class opaqueClass;
   final Class pointerClass;
   final Class structClass;
+  final Procedure allocateMethod;
+  final Procedure allocatorAllocateMethod;
   final Procedure castMethod;
   final Procedure offsetByMethod;
   final Procedure elementAtMethod;
   final Procedure addressGetter;
+  final Procedure structPointerRef;
+  final Procedure structPointerElemAt;
   final Procedure asFunctionMethod;
   final Procedure asFunctionInternal;
+  final Procedure sizeOfMethod;
   final Procedure lookupFunctionMethod;
   final Procedure fromFunctionMethod;
   final Field addressOfField;
@@ -221,6 +237,8 @@
   final Map<NativeType, Procedure> storeMethods;
   final Map<NativeType, Procedure> elementAtMethods;
   final Procedure loadStructMethod;
+  final Procedure memCopy;
+  final Procedure allocationTearoff;
   final Procedure asFunctionTearoff;
   final Procedure lookupFunctionTearoff;
 
@@ -235,14 +253,29 @@
         doubleClass = coreTypes.doubleClass,
         listClass = coreTypes.listClass,
         typeClass = coreTypes.typeClass,
+        unsafeCastMethod =
+            index.getTopLevelMember('dart:_internal', 'unsafeCast'),
+        typedDataClass = index.getClass('dart:typed_data', 'TypedData'),
+        typedDataBufferGetter =
+            index.getMember('dart:typed_data', 'TypedData', 'get:buffer'),
+        typedDataOffsetInBytesGetter = index.getMember(
+            'dart:typed_data', 'TypedData', 'get:offsetInBytes'),
+        byteBufferAsUint8List =
+            index.getMember('dart:typed_data', 'ByteBuffer', 'asUint8List'),
         pragmaClass = coreTypes.pragmaClass,
         pragmaName = coreTypes.pragmaName,
         pragmaOptions = coreTypes.pragmaOptions,
         listElementAt = coreTypes.index.getMember('dart:core', 'List', '[]'),
+        numAddition = coreTypes.index.getMember('dart:core', 'num', '+'),
         ffiLibrary = index.getLibrary('dart:ffi'),
+        allocatorClass = index.getClass('dart:ffi', 'Allocator'),
         nativeFunctionClass = index.getClass('dart:ffi', 'NativeFunction'),
+        opaqueClass = index.getClass('dart:ffi', 'Opaque'),
         pointerClass = index.getClass('dart:ffi', 'Pointer'),
         structClass = index.getClass('dart:ffi', 'Struct'),
+        allocateMethod = index.getMember('dart:ffi', 'AllocatorAlloc', 'call'),
+        allocatorAllocateMethod =
+            index.getMember('dart:ffi', 'Allocator', 'allocate'),
         castMethod = index.getMember('dart:ffi', 'Pointer', 'cast'),
         offsetByMethod = index.getMember('dart:ffi', 'Pointer', '_offsetBy'),
         elementAtMethod = index.getMember('dart:ffi', 'Pointer', 'elementAt'),
@@ -252,10 +285,15 @@
             index.getMember('dart:ffi', 'Struct', '_fromPointer'),
         fromAddressInternal =
             index.getTopLevelMember('dart:ffi', '_fromAddress'),
+        structPointerRef =
+            index.getMember('dart:ffi', 'StructPointer', 'get:ref'),
+        structPointerElemAt =
+            index.getMember('dart:ffi', 'StructPointer', '[]'),
         asFunctionMethod =
             index.getMember('dart:ffi', 'NativeFunctionPointer', 'asFunction'),
         asFunctionInternal =
             index.getTopLevelMember('dart:ffi', '_asFunctionInternal'),
+        sizeOfMethod = index.getTopLevelMember('dart:ffi', 'sizeOf'),
         lookupFunctionMethod = index.getMember(
             'dart:ffi', 'DynamicLibraryExtension', 'lookupFunction'),
         fromFunctionMethod =
@@ -283,6 +321,9 @@
           return index.getTopLevelMember('dart:ffi', "_elementAt$name");
         }),
         loadStructMethod = index.getTopLevelMember('dart:ffi', '_loadStruct'),
+        memCopy = index.getTopLevelMember('dart:ffi', '_memCopy'),
+        allocationTearoff = index.getMember(
+            'dart:ffi', 'AllocatorAlloc', LibraryIndex.tearoffPrefix + 'call'),
         asFunctionTearoff = index.getMember('dart:ffi', 'NativeFunctionPointer',
             LibraryIndex.tearoffPrefix + 'asFunction'),
         lookupFunctionTearoff = index.getMember(
@@ -310,8 +351,10 @@
   /// [Handle]                             -> [Object]
   /// [NativeFunction]<T1 Function(T2, T3) -> S1 Function(S2, S3)
   ///    where DartRepresentationOf(Tn) -> Sn
-  DartType convertNativeTypeToDartType(
-      DartType nativeType, bool allowStructs, bool allowHandle) {
+  DartType convertNativeTypeToDartType(DartType nativeType,
+      {bool allowStructs = false,
+      bool allowStructItself = false,
+      bool allowHandle = false}) {
     if (nativeType is! InterfaceType) {
       return null;
     }
@@ -320,6 +363,9 @@
     final NativeType nativeType_ = getType(nativeClass);
 
     if (hierarchy.isSubclassOf(nativeClass, structClass)) {
+      if (structClass == nativeClass) {
+        return allowStructItself ? nativeType : null;
+      }
       return allowStructs ? nativeType : null;
     }
     if (nativeType_ == null) {
@@ -352,13 +398,13 @@
       return null;
     }
     if (fun.typeParameters.length != 0) return null;
-    // TODO(36730): Structs cannot appear in native function signatures.
-    final DartType returnType = convertNativeTypeToDartType(
-        fun.returnType, /*allowStructs=*/ false, /*allowHandle=*/ true);
+
+    final DartType returnType = convertNativeTypeToDartType(fun.returnType,
+        allowStructs: allowStructs, allowHandle: true);
     if (returnType == null) return null;
     final List<DartType> argumentTypes = fun.positionalParameters
-        .map((t) => convertNativeTypeToDartType(
-            t, /*allowStructs=*/ false, /*allowHandle=*/ true))
+        .map((t) => convertNativeTypeToDartType(t,
+            allowStructs: allowStructs, allowHandle: true))
         .toList();
     if (argumentTypes.contains(null)) return null;
     return FunctionType(argumentTypes, returnType, Nullability.legacy);
@@ -373,12 +419,12 @@
   }
 }
 
-/// Contains replaced members, of which all the call sites need to be replaced.
-///
-/// [ReplacedMembers] is populated by _FfiDefinitionTransformer and consumed by
-/// _FfiUseSiteTransformer.
-class ReplacedMembers {
+/// Contains all information collected by _FfiDefinitionTransformer that is
+/// needed in _FfiUseSiteTransformer.
+class FfiTransformerData {
   final Map<Field, Procedure> replacedGetters;
   final Map<Field, Procedure> replacedSetters;
-  ReplacedMembers(this.replacedGetters, this.replacedSetters);
+  final Set<Class> emptyStructs;
+  FfiTransformerData(
+      this.replacedGetters, this.replacedSetters, this.emptyStructs);
 }
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 4f96426..853087e 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -8,7 +8,10 @@
 
 import 'package:front_end/src/api_unstable/vm.dart'
     show
+        templateFfiEmptyStruct,
+        templateFfiEmptyStructWarning,
         templateFfiFieldAnnotation,
+        templateFfiFieldCyclic,
         templateFfiFieldNoAnnotation,
         templateFfiTypeMismatch,
         templateFfiFieldInitializer,
@@ -22,6 +25,7 @@
 import 'package:kernel/target/changed_structure_notifier.dart';
 import 'package:kernel/target/targets.dart' show DiagnosticReporter;
 import 'package:kernel/type_environment.dart' show SubtypeCheckMode;
+import 'package:kernel/util/graph.dart';
 
 import 'ffi.dart';
 
@@ -40,7 +44,7 @@
 ///
 /// Output:
 /// class Coord extends Struct {
-///   Coord.#fromPointer(Pointer<Coord> coord) : super._(coord);
+///   Coord.#fromTypedDataBase(Pointer<Coord> coord) : super._(coord);
 ///
 ///   Pointer<Double> get _xPtr => addressOf.cast();
 ///   set x(double v) => _xPtr.store(v);
@@ -56,7 +60,7 @@
 ///
 ///   static final int #sizeOf = 24;
 /// }
-ReplacedMembers transformLibraries(
+FfiTransformerData transformLibraries(
     Component component,
     CoreTypes coreTypes,
     ClassHierarchy hierarchy,
@@ -64,31 +68,47 @@
     DiagnosticReporter diagnosticReporter,
     ReferenceFromIndex referenceFromIndex,
     ChangedStructureNotifier changedStructureNotifier) {
-  final LibraryIndex index =
-      LibraryIndex(component, const ["dart:ffi", "dart:core"]);
+  final LibraryIndex index = LibraryIndex(component,
+      const ["dart:core", "dart:ffi", "dart:_internal", "dart:typed_data"]);
   if (!index.containsLibrary("dart:ffi")) {
     // TODO: This check doesn't make sense: "dart:ffi" is always loaded/created
     // for the VM target.
     // If dart:ffi is not loaded, do not do the transformation.
-    return ReplacedMembers({}, {});
+    return FfiTransformerData({}, {}, {});
   }
   if (index.tryGetClass('dart:ffi', 'NativeFunction') == null) {
     // If dart:ffi is not loaded (for real): do not do the transformation.
-    return ReplacedMembers({}, {});
+    return FfiTransformerData({}, {}, {});
   }
   final transformer = new _FfiDefinitionTransformer(index, coreTypes, hierarchy,
       diagnosticReporter, referenceFromIndex, changedStructureNotifier);
   libraries.forEach(transformer.visitLibrary);
-  return ReplacedMembers(
-      transformer.replacedGetters, transformer.replacedSetters);
+  transformer.manualVisitInTopologicalOrder();
+  return FfiTransformerData(transformer.replacedGetters,
+      transformer.replacedSetters, transformer.emptyStructs);
+}
+
+class StructDependencyGraph<T> implements Graph<T> {
+  final Map<T, Iterable<T>> map;
+  StructDependencyGraph(this.map);
+
+  Iterable<T> get vertices => map.keys;
+  Iterable<T> neighborsOf(T vertex) => map[vertex];
 }
 
 /// Checks and elaborates the dart:ffi structs and fields.
 class _FfiDefinitionTransformer extends FfiTransformer {
   final LibraryIndex index;
 
+  // Data structures for topological navigation.
+  Map<Class, IndexedClass> indexedStructClasses = {};
+  Map<Class, Set<Class>> structClassDependencies = {};
+  Map<Class, bool> fieldsValid = {};
+  Map<Class, Map<Abi, StructLayout>> structLayouts = {};
+
   Map<Field, Procedure> replacedGetters = {};
   Map<Field, Procedure> replacedSetters = {};
+  Set<Class> emptyStructs = {};
 
   ChangedStructureNotifier changedStructureNotifier;
 
@@ -104,6 +124,40 @@
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex) {}
 
+  void manualVisitInTopologicalOrder() {
+    final connectedComponents =
+        computeStrongComponents(StructDependencyGraph(structClassDependencies));
+
+    connectedComponents.forEach((List<Class> component) {
+      bool report = false;
+      if (component.length > 1) {
+        // Indirect cycle.
+        report = true;
+      }
+      if (component.length == 1) {
+        if (structClassDependencies[component.single]
+            .contains(component.single)) {
+          // Direct cycle.
+          report = true;
+        }
+      }
+      if (report) {
+        component.forEach((Class e) {
+          diagnosticReporter.report(
+              templateFfiFieldCyclic.withArguments(
+                  e.name, component.map((e) => e.name).toList()),
+              e.fileOffset,
+              e.name.length,
+              e.fileUri);
+        });
+      }
+    });
+
+    final structClassesSorted = connectedComponents.expand((i) => i).toList();
+
+    structClassesSorted.forEach(visitClassInTopologicalOrder);
+  }
+
   @override
   visitLibrary(Library node) {
     currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
@@ -127,17 +181,22 @@
     // Struct objects are manufactured in the VM by 'allocate' and 'load'.
     _makeEntryPoint(node);
 
-    var indexedClass = currentLibraryIndex?.lookupIndexedClass(node.name);
+    final indexedClass = currentLibraryIndex?.lookupIndexedClass(node.name);
     _checkConstructors(node, indexedClass);
-    final bool fieldsValid = _checkFieldAnnotations(node);
+    indexedStructClasses[node] = indexedClass;
 
-    if (fieldsValid) {
+    fieldsValid[node] = _checkFieldAnnotations(node);
+
+    return node;
+  }
+
+  void visitClassInTopologicalOrder(Class node) {
+    final indexedClass = indexedStructClasses[node];
+    if (fieldsValid[node]) {
       final structSize = _replaceFields(node, indexedClass);
       _replaceSizeOfMethod(node, structSize, indexedClass);
       changedStructureNotifier?.registerClassMemberChange(node);
     }
-
-    return node;
   }
 
   void _checkStructClass(Class node) {
@@ -166,6 +225,11 @@
         SubtypeCheckMode.ignoringNullabilities);
   }
 
+  bool _isStructSubtype(DartType type) {
+    return env.isSubtypeOf(type, InterfaceType(structClass, Nullability.legacy),
+        SubtypeCheckMode.ignoringNullabilities);
+  }
+
   /// Returns members of [node] that correspond to struct fields.
   ///
   /// Note that getters and setters that originate from an external field have
@@ -197,6 +261,7 @@
 
   bool _checkFieldAnnotations(Class node) {
     bool success = true;
+    structClassDependencies[node] = {};
     final membersWithAnnotations = _structFieldMembers(node)
       ..retainWhere((m) => (m is Field) || (m is Procedure && m.isGetter));
     for (final Member f in membersWithAnnotations) {
@@ -211,7 +276,7 @@
       }
       final nativeTypeAnnos = _getNativeTypeAnnotations(f).toList();
       final type = _structFieldMemberType(f);
-      if (_isPointerType(type)) {
+      if (_isPointerType(type) || _isStructSubtype(type)) {
         if (nativeTypeAnnos.length != 0) {
           diagnosticReporter.report(
               templateFfiFieldNoAnnotation.withArguments(f.name.text),
@@ -219,6 +284,10 @@
               f.name.text.length,
               f.fileUri);
         }
+        if (_isStructSubtype(type)) {
+          final clazz = (type as InterfaceType).classNode;
+          structClassDependencies[node].add(clazz);
+        }
       } else if (nativeTypeAnnos.length != 1) {
         diagnosticReporter.report(
             templateFfiFieldAnnotation.withArguments(f.name.text),
@@ -229,9 +298,10 @@
         final DartType nativeType = InterfaceType(
             nativeTypesClasses[_getFieldType(nativeTypeAnnos.first).index],
             Nullability.legacy);
-        // TODO(dartbug.com/37271): Support structs inside structs.
         final DartType shouldBeDartType = convertNativeTypeToDartType(
-            nativeType, /*allowStructs=*/ false, /*allowHandle=*/ false);
+            nativeType,
+            allowStructs: true,
+            allowHandle: false);
         if (shouldBeDartType == null ||
             !env.isSubtypeOf(type, shouldBeDartType,
                 SubtypeCheckMode.ignoringNullabilities)) {
@@ -271,10 +341,10 @@
     }
 
     // Add a constructor which 'load' can use.
-    // C.#fromPointer(Pointer<Void> address) : super.fromPointer(address);
+    // C.#fromTypedDataBase(Object address) : super.fromPointer(address);
     final VariableDeclaration pointer = new VariableDeclaration("#pointer");
-    final name = Name("#fromPointer");
-    final referenceFrom = indexedClass?.lookupConstructor(name.text);
+    final name = Name("#fromTypedDataBase");
+    final referenceFrom = indexedClass?.lookupConstructor(name);
     final Constructor ctor = Constructor(
         FunctionNode(EmptyStatement(), positionalParameters: [pointer]),
         name: name,
@@ -309,6 +379,16 @@
       if (_isPointerType(dartType)) {
         nativeType = NativeType.kPointer;
         clazz = pointerClass;
+      } else if (_isStructSubtype(dartType)) {
+        nativeType = NativeType.kStruct;
+        clazz = (dartType as InterfaceType).classNode;
+        if (emptyStructs.contains(clazz)) {
+          diagnosticReporter.report(
+              templateFfiEmptyStruct.withArguments(clazz.name),
+              m.fileOffset,
+              1,
+              m.location.file);
+        }
       } else {
         final nativeTypeAnnos = _getNativeTypeAnnotations(m).toList();
         if (nativeTypeAnnos.length == 1) {
@@ -338,15 +418,24 @@
     }
 
     _annoteStructWithFields(node, classes);
-
-    final sizeAndOffsets = <Abi, SizeAndOffsets>{};
-    for (final Abi abi in Abi.values) {
-      sizeAndOffsets[abi] = _calculateSizeAndOffsets(types, abi);
+    if (classes.isEmpty) {
+      diagnosticReporter.report(
+          templateFfiEmptyStructWarning.withArguments(node.name),
+          node.fileOffset,
+          node.name.length,
+          node.location.file);
+      emptyStructs.add(node);
     }
 
+    final structLayout = <Abi, StructLayout>{};
+    for (final Abi abi in Abi.values) {
+      structLayout[abi] = _calculateStructLayout(types, classes, abi);
+    }
+    structLayouts[node] = structLayout;
+
     for (final i in fields.keys) {
-      final fieldOffsets = sizeAndOffsets
-          .map((Abi abi, SizeAndOffsets v) => MapEntry(abi, v.offsets[i]));
+      final fieldOffsets = structLayout
+          .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i]));
       final methods = _generateMethodsForField(
           fields[i], types[i], fieldOffsets, indexedClass);
       methods.forEach((p) => node.addProcedure(p));
@@ -357,8 +446,8 @@
     }
 
     for (final i in getters.keys) {
-      final fieldOffsets = sizeAndOffsets
-          .map((Abi abi, SizeAndOffsets v) => MapEntry(abi, v.offsets[i]));
+      final fieldOffsets = structLayout
+          .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i]));
       Procedure getter = getters[i];
       getter.function.body = _generateGetterStatement(
           getter.function.returnType,
@@ -369,8 +458,8 @@
     }
 
     for (final i in setters.keys) {
-      final fieldOffsets = sizeAndOffsets
-          .map((Abi abi, SizeAndOffsets v) => MapEntry(abi, v.offsets[i]));
+      final fieldOffsets = structLayout
+          .map((Abi abi, StructLayout v) => MapEntry(abi, v.offsets[i]));
       Procedure setter = setters[i];
       setter.function.body = _generateSetterStatement(
           setter.function.positionalParameters.single.type,
@@ -381,7 +470,7 @@
       setter.isExternal = false;
     }
 
-    return sizeAndOffsets.map((k, v) => MapEntry(k, v.size));
+    return structLayout.map((k, v) => MapEntry(k, v.size));
   }
 
   void _annoteStructWithFields(Class node, List<Class> fieldTypes) {
@@ -427,6 +516,7 @@
   Statement _generateGetterStatement(DartType dartType, NativeType type,
       int fileOffset, Map<Abi, int> offsets) {
     final bool isPointer = type == NativeType.kPointer;
+    final bool isStruct = type == NativeType.kStruct;
 
     // Sample output:
     // int get x => _loadInt8(pointer, offset);
@@ -434,11 +524,87 @@
     // Treat Pointer fields different to get correct behavior without casts:
     // Pointer<Int8> get x =>
     //   _fromAddress<Int8>(_loadIntPtr(pointer, offset));
-    final loadMethod = isPointer
-        ? loadMethods[NativeType.kIntptr]
-        : optimizedTypes.contains(type)
-            ? loadMethods[type]
-            : loadStructMethod;
+    //
+    // Nested structs:
+    // MyStruct get x =>
+    //   MyStruct.#fromTypedDataBase(
+    //     _addressOf is Pointer ?
+    //       _fromAddress<MyStruct>((_addressOf as Pointer).address + offset) :
+    //       (_addressOf as TypedData).buffer.asInt8List(
+    //         (_addressOf as TypedData).offsetInBytes + offset,
+    //         size
+    //       )
+    //   );
+    if (isStruct) {
+      final clazz = (dartType as InterfaceType).classNode;
+      final constructor = clazz.constructors
+          .firstWhere((c) => c.name == Name("#fromTypedDataBase"));
+      final lengths =
+          structLayouts[clazz].map((key, value) => MapEntry(key, value.size));
+      Expression thisDotAddressOf() =>
+          PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
+            ..fileOffset = fileOffset;
+      return ReturnStatement(ConstructorInvocation(
+          constructor,
+          Arguments([
+            ConditionalExpression(
+                IsExpression(thisDotAddressOf(),
+                    InterfaceType(pointerClass, Nullability.legacy)),
+                StaticInvocation(
+                    fromAddressInternal,
+                    Arguments([
+                      MethodInvocation(
+                          PropertyGet(thisDotAddressOf(), addressGetter.name,
+                              addressGetter)
+                            ..fileOffset = fileOffset,
+                          numAddition.name,
+                          Arguments([_runtimeBranchOnLayout(offsets)]),
+                          numAddition)
+                    ], types: [
+                      dartType
+                    ]))
+                  ..fileOffset = fileOffset,
+                MethodInvocation(
+                    PropertyGet(
+                        StaticInvocation(
+                            unsafeCastMethod,
+                            Arguments([
+                              thisDotAddressOf()
+                            ], types: [
+                              InterfaceType(typedDataClass, Nullability.legacy)
+                            ]))
+                          ..fileOffset = fileOffset,
+                        typedDataBufferGetter.name,
+                        typedDataBufferGetter)
+                      ..fileOffset = fileOffset,
+                    byteBufferAsUint8List.name,
+                    Arguments([
+                      MethodInvocation(
+                          PropertyGet(
+                              StaticInvocation(
+                                  unsafeCastMethod,
+                                  Arguments([
+                                    thisDotAddressOf()
+                                  ], types: [
+                                    InterfaceType(
+                                        typedDataClass, Nullability.legacy)
+                                  ]))
+                                ..fileOffset = fileOffset,
+                              typedDataOffsetInBytesGetter.name,
+                              typedDataOffsetInBytesGetter)
+                            ..fileOffset = fileOffset,
+                          numAddition.name,
+                          Arguments([_runtimeBranchOnLayout(offsets)]),
+                          numAddition),
+                      _runtimeBranchOnLayout(lengths)
+                    ]),
+                    byteBufferAsUint8List),
+                InterfaceType(objectClass, Nullability.nonNullable))
+          ]))
+        ..fileOffset = fileOffset);
+    }
+    final loadMethod =
+        isPointer ? loadMethods[NativeType.kIntptr] : loadMethods[type];
     Expression getterReturnValue = StaticInvocation(
         loadMethod,
         Arguments([
@@ -459,6 +625,7 @@
   Statement _generateSetterStatement(DartType dartType, NativeType type,
       int fileOffset, Map<Abi, int> offsets, VariableDeclaration argument) {
     final bool isPointer = type == NativeType.kPointer;
+    final bool isStruct = type == NativeType.kStruct;
 
     // Sample output:
     // set x(int v) => _storeInt8(pointer, offset, v);
@@ -466,6 +633,28 @@
     // Treat Pointer fields different to get correct behavior without casts:
     // set x(Pointer<Int8> v) =>
     //   _storeIntPtr(pointer, offset, (v as Pointer<Int8>).address);
+    //
+    // Nested structs:
+    // set x(MyStruct v) =>
+    //   _memCopy(this._address, offset, v._address, 0, size);
+    if (isStruct) {
+      final clazz = (dartType as InterfaceType).classNode;
+      final lengths =
+          structLayouts[clazz].map((key, value) => MapEntry(key, value.size));
+      return ReturnStatement(StaticInvocation(
+          memCopy,
+          Arguments([
+            PropertyGet(ThisExpression(), addressOfField.name, addressOfField)
+              ..fileOffset = fileOffset,
+            _runtimeBranchOnLayout(offsets),
+            PropertyGet(
+                VariableGet(argument), addressOfField.name, addressOfField)
+              ..fileOffset = fileOffset,
+            ConstantExpression(IntConstant(0)),
+            _runtimeBranchOnLayout(lengths),
+          ]))
+        ..fileOffset = fileOffset);
+    }
     final storeMethod =
         isPointer ? storeMethods[NativeType.kIntptr] : storeMethods[type];
     Expression argumentExpression = VariableGet(argument)
@@ -493,8 +682,7 @@
     final Procedure getter = Procedure(field.name, ProcedureKind.Getter,
         FunctionNode(getterStatement, returnType: field.type),
         fileUri: field.fileUri,
-        reference:
-            indexedClass?.lookupProcedureNotSetter(field.name.text)?.reference)
+        reference: indexedClass?.lookupGetterReference(field.name))
       ..fileOffset = field.fileOffset
       ..isNonNullableByDefault = field.isNonNullableByDefault;
 
@@ -511,8 +699,7 @@
           FunctionNode(setterStatement,
               returnType: VoidType(), positionalParameters: [argument]),
           fileUri: field.fileUri,
-          reference:
-              indexedClass?.lookupProcedureSetter(field.name.text)?.reference)
+          reference: indexedClass?.lookupSetterReference(field.name))
         ..fileOffset = field.fileOffset
         ..isNonNullableByDefault = field.isNonNullableByDefault;
     }
@@ -524,25 +711,32 @@
   }
 
   /// Sample output:
-  /// static int #sizeOf() => 24;
+  /// int #sizeOf => [24,24,16][_abi()];
   void _replaceSizeOfMethod(
       Class struct, Map<Abi, int> sizes, IndexedClass indexedClass) {
     var name = Name("#sizeOf");
-    var lookupField = indexedClass?.lookupField(name.text);
-    final Field sizeOf = Field(name,
+    var getterReference = indexedClass?.lookupGetterReference(name);
+    final Field sizeOf = Field.immutable(name,
         isStatic: true,
         isFinal: true,
         initializer: _runtimeBranchOnLayout(sizes),
         type: InterfaceType(intClass, Nullability.legacy),
         fileUri: struct.fileUri,
-        getterReference: lookupField?.getterReference,
-        setterReference: lookupField?.setterReference)
+        getterReference: getterReference)
       ..fileOffset = struct.fileOffset;
     _makeEntryPoint(sizeOf);
     struct.addField(sizeOf);
   }
 
-  int _sizeInBytes(NativeType type, Abi abi) {
+  int _sizeInBytes(NativeType type, Class clazz, Abi abi) {
+    if (type == NativeType.kStruct) {
+      final structLayout = structLayouts[clazz];
+      if (structLayout == null) {
+        // We have a cycle, so we don't know the size.
+        return 0;
+      }
+      return structLayout[abi].size;
+    }
     final int size = nativeTypeSizes[type.index];
     if (size == WORD_SIZE) {
       return wordSize[abi];
@@ -550,10 +744,18 @@
     return size;
   }
 
-  int _alignmentOf(NativeType type, Abi abi) {
+  int _alignmentOf(NativeType type, Class clazz, Abi abi) {
+    if (type == NativeType.kStruct) {
+      final structLayout = structLayouts[clazz];
+      if (structLayout == null) {
+        // We have a cycle, so we don't know the size.
+        return 0;
+      }
+      return structLayout[abi].alignment;
+    }
     final int alignment = nonSizeAlignment[abi][type];
     if (alignment != null) return alignment;
-    return _sizeInBytes(type, abi);
+    return _sizeInBytes(type, clazz, abi);
   }
 
   int _alignOffset(int offset, int alignment) {
@@ -565,23 +767,23 @@
     return offset;
   }
 
-  // TODO(37271): Support nested structs.
-  SizeAndOffsets _calculateSizeAndOffsets(List<NativeType> types, Abi abi) {
+  // Keep consistent with runtime/vm/compiler/ffi/native_type.cc
+  // NativeCompoundType::FromNativeTypes.
+  StructLayout _calculateStructLayout(
+      List<NativeType> types, List<Class> classes, Abi abi) {
     int offset = 0;
     final offsets = <int>[];
-    for (final NativeType t in types) {
-      final int size = _sizeInBytes(t, abi);
-      final int alignment = _alignmentOf(t, abi);
+    int structAlignment = 1;
+    for (int i = 0; i < types.length; i++) {
+      final int size = _sizeInBytes(types[i], classes[i], abi);
+      final int alignment = _alignmentOf(types[i], classes[i], abi);
       offset = _alignOffset(offset, alignment);
       offsets.add(offset);
       offset += size;
+      structAlignment = math.max(structAlignment, alignment);
     }
-    final int minimumAlignment = 1;
-    final sizeAlignment = types
-        .map((t) => _alignmentOf(t, abi))
-        .followedBy([minimumAlignment]).reduce(math.max);
-    final int size = _alignOffset(offset, sizeAlignment);
-    return SizeAndOffsets(size, offsets);
+    final int size = _alignOffset(offset, structAlignment);
+    return StructLayout(size, structAlignment, offsets);
   }
 
   void _makeEntryPoint(Annotatable node) {
@@ -613,12 +815,16 @@
   }
 }
 
-class SizeAndOffsets {
+/// The layout of a `Struct` in one [Abi].
+class StructLayout {
   /// Size of the entire struct.
   final int size;
 
+  /// Alignment of struct when nested in other struct.
+  final int alignment;
+
   /// Offset in bytes for each field, indexed by field number.
   final List<int> offsets;
 
-  SizeAndOffsets(this.size, this.offsets);
+  StructLayout(this.size, this.alignment, this.offsets);
 }
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 16e31c7..e963078 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -9,9 +9,11 @@
         messageFfiExceptionalReturnNull,
         messageFfiExpectedConstant,
         templateFfiDartTypeMismatch,
+        templateFfiEmptyStruct,
         templateFfiExpectedExceptionalReturn,
         templateFfiExpectedNoExceptionalReturn,
         templateFfiExtendsOrImplementsSealedClass,
+        templateFfiNonConstantTypeArgumentWarning,
         templateFfiNotStatic,
         templateFfiTypeInvalid,
         templateFfiTypeMismatch;
@@ -25,7 +27,7 @@
 import 'package:kernel/type_environment.dart';
 
 import 'ffi.dart'
-    show ReplacedMembers, NativeType, FfiTransformer, optimizedTypes;
+    show FfiTransformerData, NativeType, FfiTransformer, optimizedTypes;
 
 /// Checks and replaces calls to dart:ffi struct fields and methods.
 void transformLibraries(
@@ -34,9 +36,10 @@
     ClassHierarchy hierarchy,
     List<Library> libraries,
     DiagnosticReporter diagnosticReporter,
-    ReplacedMembers replacedFields,
+    FfiTransformerData ffiTransformerData,
     ReferenceFromIndex referenceFromIndex) {
-  final index = new LibraryIndex(component, ["dart:ffi"]);
+  final index = new LibraryIndex(
+      component, ["dart:ffi", "dart:_internal", "dart:typed_data"]);
   if (!index.containsLibrary("dart:ffi")) {
     // TODO: This check doesn't make sense: "dart:ffi" is always loaded/created
     // for the VM target.
@@ -53,8 +56,9 @@
       hierarchy,
       diagnosticReporter,
       referenceFromIndex,
-      replacedFields.replacedGetters,
-      replacedFields.replacedSetters);
+      ffiTransformerData.replacedGetters,
+      ffiTransformerData.replacedSetters,
+      ffiTransformerData.emptyStructs);
   libraries.forEach(transformer.visitLibrary);
 }
 
@@ -62,6 +66,7 @@
 class _FfiUseSiteTransformer extends FfiTransformer {
   final Map<Field, Procedure> replacedGetters;
   final Map<Field, Procedure> replacedSetters;
+  final Set<Class> emptyStructs;
   StaticTypeContext _staticTypeContext;
 
   Library currentLibrary;
@@ -79,7 +84,8 @@
       DiagnosticReporter diagnosticReporter,
       ReferenceFromIndex referenceFromIndex,
       this.replacedGetters,
-      this.replacedSetters)
+      this.replacedSetters,
+      this.emptyStructs)
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex) {}
 
@@ -123,7 +129,9 @@
   @override
   visitProcedure(Procedure node) {
     if (isFfiLibrary && node.isExtensionMember) {
-      if (node == asFunctionTearoff || node == lookupFunctionTearoff) {
+      if (node == allocationTearoff ||
+          node == asFunctionTearoff ||
+          node == lookupFunctionTearoff) {
         // Skip static checks and transformation for the tearoffs.
         return node;
       }
@@ -166,23 +174,39 @@
 
     final Member target = node.target;
     try {
-      if (target == lookupFunctionMethod) {
+      if (target == structPointerRef || target == structPointerElemAt) {
+        final DartType nativeType = node.arguments.types[0];
+
+        _warningNativeTypeValid(nativeType, node, allowStructItself: false);
+
+        // TODO(http://dartbug.com/38721): Replace calls with direct
+        // constructor invocations.
+      } else if (target == sizeOfMethod) {
+        final DartType nativeType = node.arguments.types[0];
+
+        if (!isFfiLibrary) {
+          _warningNativeTypeValid(nativeType, node);
+        }
+
+        // TODO(http://dartbug.com/38721): Replace calls with constant
+        // expressions.
+      } else if (target == lookupFunctionMethod) {
         final DartType nativeType = InterfaceType(
             nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
         final DartType dartType = node.arguments.types[1];
 
-        _ensureNativeTypeValid(nativeType, node, allowStructs: false);
-        _ensureNativeTypeToDartType(nativeType, dartType, node,
-            allowStructs: false);
+        _ensureNativeTypeValid(nativeType, node);
+        _ensureNativeTypeToDartType(nativeType, dartType, node);
+        _ensureNoEmptyStructs(dartType, node);
         return _replaceLookupFunction(node);
       } else if (target == asFunctionMethod) {
         final DartType dartType = node.arguments.types[1];
         final DartType nativeType = InterfaceType(
             nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
 
-        _ensureNativeTypeValid(nativeType, node, allowStructs: false);
-        _ensureNativeTypeToDartType(nativeType, dartType, node,
-            allowStructs: false);
+        _ensureNativeTypeValid(nativeType, node);
+        _ensureNativeTypeToDartType(nativeType, dartType, node);
+        _ensureNoEmptyStructs(dartType, node);
 
         final DartType nativeSignature =
             (nativeType as InterfaceType).typeArguments[0];
@@ -199,9 +223,9 @@
 
         _ensureIsStaticFunction(func);
 
-        _ensureNativeTypeValid(nativeType, node, allowStructs: false);
-        _ensureNativeTypeToDartType(nativeType, dartType, node,
-            allowStructs: false);
+        _ensureNativeTypeValid(nativeType, node);
+        _ensureNativeTypeToDartType(nativeType, dartType, node);
+        _ensureNoEmptyStructs(dartType, node);
 
         // Check `exceptionalReturn`'s type.
         final FunctionType funcType = dartType;
@@ -274,6 +298,13 @@
           }
         }
         return _replaceFromFunction(node);
+      } else if (target == allocateMethod) {
+        final DartType nativeType = node.arguments.types[0];
+
+        _ensureNativeTypeValid(nativeType, node);
+
+        // TODO(http://dartbug.com/38721): Inline the body to get rid of a
+        // generic invocation of sizeOf.
       }
     } on _FfiStaticTypeError {
       // It's OK to swallow the exception because the diagnostics issued will
@@ -332,8 +363,8 @@
     final nativeFunctionType = InterfaceType(
         nativeFunctionClass, Nullability.legacy, node.arguments.types);
     var name = Name("_#ffiCallback${callbackCount++}", currentLibrary);
-    var lookupField = currentLibraryIndex?.lookupField(name.text);
-    final Field field = Field(name,
+    var getterReference = currentLibraryIndex?.lookupGetterReference(name);
+    final Field field = Field.immutable(name,
         type: InterfaceType(
             pointerClass, Nullability.legacy, [nativeFunctionType]),
         initializer: StaticInvocation(
@@ -346,8 +377,7 @@
         isStatic: true,
         isFinal: true,
         fileUri: currentLibrary.fileUri,
-        getterReference: lookupField?.getterReference,
-        setterReference: lookupField?.setterReference)
+        getterReference: getterReference)
       ..fileOffset = node.fileOffset;
     currentLibrary.addField(field);
     return StaticGet(field);
@@ -363,6 +393,9 @@
         final DartType pointerType =
             node.receiver.getStaticType(_staticTypeContext);
         final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+
+        _warningNativeTypeValid(nativeType, node);
+
         if (nativeType is TypeParameterType) {
           // Do not rewire generic invocations.
           return node;
@@ -394,9 +427,11 @@
 
   void _ensureNativeTypeToDartType(
       DartType nativeType, DartType dartType, Expression node,
-      {bool allowStructs: false, bool allowHandle: false}) {
-    final DartType correspondingDartType =
-        convertNativeTypeToDartType(nativeType, allowStructs, allowHandle);
+      {bool allowHandle: false}) {
+    final DartType correspondingDartType = convertNativeTypeToDartType(
+        nativeType,
+        allowStructs: true,
+        allowHandle: allowHandle);
     if (dartType == correspondingDartType) return;
     if (env.isSubtypeOf(correspondingDartType, dartType,
         SubtypeCheckMode.ignoringNullabilities)) {
@@ -412,9 +447,11 @@
   }
 
   void _ensureNativeTypeValid(DartType nativeType, Expression node,
-      {bool allowStructs: false, bool allowHandle: false}) {
+      {bool allowHandle: false, bool allowStructItself = true}) {
     if (!_nativeTypeValid(nativeType,
-        allowStructs: allowStructs, allowHandle: allowHandle)) {
+        allowStructs: true,
+        allowStructItself: allowStructItself,
+        allowHandle: allowHandle)) {
       diagnosticReporter.report(
           templateFfiTypeInvalid.withArguments(
               nativeType, currentLibrary.isNonNullableByDefault),
@@ -425,11 +462,55 @@
     }
   }
 
+  void _warningNativeTypeValid(DartType nativeType, Expression node,
+      {bool allowHandle: false, bool allowStructItself = true}) {
+    if (!_nativeTypeValid(nativeType,
+        allowStructs: true,
+        allowStructItself: allowStructItself,
+        allowHandle: allowHandle)) {
+      diagnosticReporter.report(
+          templateFfiNonConstantTypeArgumentWarning.withArguments(
+              nativeType, currentLibrary.isNonNullableByDefault),
+          node.fileOffset,
+          1,
+          node.location.file);
+      throw _FfiStaticTypeError();
+    }
+  }
+
+  void _ensureNoEmptyStructs(DartType nativeType, Expression node) {
+    // Error on structs with no fields.
+    if (nativeType is InterfaceType) {
+      final Class nativeClass = nativeType.classNode;
+      if (hierarchy.isSubclassOf(nativeClass, structClass)) {
+        if (emptyStructs.contains(nativeClass)) {
+          diagnosticReporter.report(
+              templateFfiEmptyStruct.withArguments(nativeClass.name),
+              node.fileOffset,
+              1,
+              node.location.file);
+        }
+      }
+    }
+
+    // Recurse when seeing a function type.
+    if (nativeType is FunctionType) {
+      nativeType.positionalParameters
+          .forEach((e) => _ensureNoEmptyStructs(e, node));
+      _ensureNoEmptyStructs(nativeType.returnType, node);
+    }
+  }
+
   /// The Dart type system does not enforce that NativeFunction return and
   /// parameter types are only NativeTypes, so we need to check this.
   bool _nativeTypeValid(DartType nativeType,
-      {bool allowStructs: false, allowHandle: false}) {
-    return convertNativeTypeToDartType(nativeType, allowStructs, allowHandle) !=
+      {bool allowStructs: false,
+      bool allowStructItself = false,
+      bool allowHandle = false}) {
+    return convertNativeTypeToDartType(nativeType,
+            allowStructs: allowStructs,
+            allowStructItself: allowStructItself,
+            allowHandle: allowHandle) !=
         null;
   }
 
@@ -449,10 +530,15 @@
   Class _extendsOrImplementsSealedClass(Class klass) {
     final Class superClass = klass.supertype?.classNode;
 
-    // The Struct class can be extended, but subclasses of Struct cannot be (nor
-    // implemented).
-    if (klass != structClass && hierarchy.isSubtypeOf(klass, structClass)) {
-      return superClass != structClass ? superClass : null;
+    // The Opaque and Struct classes can be extended, but subclasses
+    // cannot be (nor implemented).
+    if (klass != opaqueClass &&
+        klass != structClass &&
+        (hierarchy.isSubtypeOf(klass, opaqueClass) ||
+            hierarchy.isSubtypeOf(klass, structClass))) {
+      return superClass != opaqueClass && superClass != structClass
+          ? superClass
+          : null;
     }
 
     if (!nativeTypesClasses.contains(klass)) {
diff --git a/pkg/vm/lib/transformations/list_literals_lowering.dart b/pkg/vm/lib/transformations/list_literals_lowering.dart
new file mode 100644
index 0000000..e6b5e13
--- /dev/null
+++ b/pkg/vm/lib/transformations/list_literals_lowering.dart
@@ -0,0 +1,59 @@
+// 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:front_end/src/api_unstable/vm.dart'
+    show isRedirectingFactoryField;
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart' show CoreTypes;
+
+/// VM-specific specialization of list literals.
+///
+/// Transforms list literals of small length into calls to specialized
+/// list constructors.
+class ListLiteralsLowering {
+  // Number of specialized factories for list literals.
+  static const numSpecializedFactories = 8;
+
+  final CoreTypes coreTypes;
+
+  // Default _GrowableList(int length) factory. Used to generate empty list
+  // literals.
+  final Procedure _defaultFactory;
+
+  // Specialized _GrowableList._literalN(e1, ..., eN) factories.
+  final List<Procedure> _specializedFactories =
+      List<Procedure>.filled(numSpecializedFactories, null);
+
+  ListLiteralsLowering(this.coreTypes)
+      : _defaultFactory =
+            coreTypes.index.getMember('dart:core', '_GrowableList', '');
+
+  Procedure getSpecializedFactory(int length) =>
+      (_specializedFactories[length - 1] ??= coreTypes.index
+          .getMember('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)) {
+      // Do not transform list literals which are used to represent
+      // redirecting factories.
+      return node;
+    }
+    final int length = node.expressions.length;
+    if (length == 0) {
+      return StaticInvocation(_defaultFactory,
+          Arguments([IntLiteral(0)], types: [node.typeArgument]))
+        ..fileOffset = node.fileOffset;
+    } else if (length <= numSpecializedFactories) {
+      final factory = getSpecializedFactory(length);
+      return StaticInvocation(
+          factory, Arguments(node.expressions, types: [node.typeArgument]))
+        ..fileOffset = node.fileOffset;
+    }
+    return node;
+  }
+}
diff --git a/pkg/vm/lib/transformations/lowering.dart b/pkg/vm/lib/transformations/lowering.dart
index 19fee1a..4b320ad 100644
--- a/pkg/vm/lib/transformations/lowering.dart
+++ b/pkg/vm/lib/transformations/lowering.dart
@@ -11,6 +11,7 @@
     show StaticTypeContext, TypeEnvironment;
 import 'package:vm/transformations/specializer/factory_specializer.dart';
 import 'late_var_init_transformer.dart' show LateVarInitTransformer;
+import 'list_literals_lowering.dart' show ListLiteralsLowering;
 
 /// VM-specific lowering transformations and optimizations combined into a
 /// single transformation pass.
@@ -23,11 +24,18 @@
   libraries.forEach(transformer.visitLibrary);
 }
 
+void transformProcedure(Procedure procedure, CoreTypes coreTypes,
+    ClassHierarchy hierarchy, bool nullSafety) {
+  final transformer = _Lowering(coreTypes, hierarchy, nullSafety);
+  procedure.accept(transformer);
+}
+
 class _Lowering extends Transformer {
   final TypeEnvironment env;
   final bool nullSafety;
   final LateVarInitTransformer lateVarInitTransformer;
   final FactorySpecializer factorySpecializer;
+  final ListLiteralsLowering listLiteralsLowering;
 
   Member _currentMember;
   StaticTypeContext _cachedStaticTypeContext;
@@ -35,7 +43,8 @@
   _Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy, this.nullSafety)
       : env = TypeEnvironment(coreTypes, hierarchy),
         lateVarInitTransformer = LateVarInitTransformer(),
-        factorySpecializer = FactorySpecializer(coreTypes);
+        factorySpecializer = FactorySpecializer(coreTypes),
+        listLiteralsLowering = ListLiteralsLowering(coreTypes);
 
   StaticTypeContext get _staticTypeContext =>
       _cachedStaticTypeContext ??= StaticTypeContext(_currentMember, env);
@@ -76,4 +85,10 @@
     node.transformChildren(this);
     return lateVarInitTransformer.transformAssertBlock(node);
   }
+
+  @override
+  visitListLiteral(ListLiteral node) {
+    node.transformChildren(this);
+    return listLiteralsLowering.transformListLiteral(node);
+  }
 }
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index 42e74cd..7f76626 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -167,6 +167,12 @@
   }
 
   @override
+  void visitProcedure(Procedure node) {
+    super.visitProcedure(node);
+    node.stubTarget = _resolveNewInterfaceTarget(node.stubTarget);
+  }
+
+  @override
   visitPropertyGet(PropertyGet node) {
     node.interfaceTarget = _resolveNewInterfaceTarget(node.interfaceTarget);
     super.visitPropertyGet(node);
diff --git a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
deleted file mode 100644
index e216685..0000000
--- a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
+++ /dev/null
@@ -1,341 +0,0 @@
-// 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/kernel.dart';
-import 'package:kernel/target/targets.dart';
-import 'package:kernel/core_types.dart';
-import 'package:meta/meta.dart';
-import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
-    show transformComponent;
-import 'package:vm/transformations/no_dynamic_invocations_annotator.dart'
-    show Selector;
-
-class TransformationInfo {
-  final List<String> removedMessageFields = <String>[];
-  final List<Class> removedMessageClasses = <Class>[];
-}
-
-TransformationInfo transformComponent(
-    Component component, Map<String, String> environment, Target target,
-    {@required bool collectInfo}) {
-  final coreTypes = new CoreTypes(component);
-
-  TransformationInfo info = collectInfo ? TransformationInfo() : null;
-
-  _treeshakeProtos(target, component, coreTypes, info);
-  return info;
-}
-
-void _treeshakeProtos(Target target, Component component, CoreTypes coreTypes,
-    TransformationInfo info) {
-  globalTypeFlow.transformComponent(target, coreTypes, component,
-      treeShakeSignatures: false);
-
-  final collector = removeUnusedProtoReferences(component, coreTypes, info);
-  if (collector != null) {
-    globalTypeFlow.transformComponent(target, coreTypes, component,
-        treeShakeSignatures: false);
-    if (info != null) {
-      for (Class gmSubclass in collector.gmSubclasses) {
-        if (!gmSubclass.enclosingLibrary.classes.contains(gmSubclass)) {
-          info.removedMessageClasses.add(gmSubclass);
-        }
-      }
-    }
-  }
-
-  // Remove metadata added by the typeflow analysis (even if the code doesn't
-  // use any protos).
-  component.metadata.clear();
-}
-
-/// Called by the signature shaker to exclude the positional parameters of
-/// certain members whose first few parameters are depended upon by the
-/// protobuf-aware tree shaker.
-bool excludePositionalParametersFromSignatureShaking(Member member) {
-  return member.enclosingClass?.name == 'BuilderInfo' &&
-      member.enclosingLibrary.importUri ==
-          Uri.parse('package:protobuf/protobuf.dart') &&
-      _UnusedFieldMetadataPruner.fieldAddingMethods.contains(member.name.name);
-}
-
-InfoCollector removeUnusedProtoReferences(
-    Component component, CoreTypes coreTypes, TransformationInfo info) {
-  final protobufUri = Uri.parse('package:protobuf/protobuf.dart');
-  final protobufLibs =
-      component.libraries.where((lib) => lib.importUri == protobufUri);
-  if (protobufLibs.isEmpty) {
-    return null;
-  }
-  final protobufLib = protobufLibs.single;
-
-  final gmClass = protobufLib.classes
-      .where((klass) => klass.name == 'GeneratedMessage')
-      .single;
-  final tagNumberClass =
-      protobufLib.classes.where((klass) => klass.name == 'TagNumber').single;
-
-  final collector = InfoCollector(gmClass);
-
-  final biClass =
-      protobufLib.classes.where((klass) => klass.name == 'BuilderInfo').single;
-  final addMethod =
-      biClass.members.singleWhere((Member member) => member.name.text == 'add');
-
-  component.accept(collector);
-
-  _UnusedFieldMetadataPruner(tagNumberClass, biClass, addMethod,
-          collector.dynamicSelectors, coreTypes, info)
-      .removeMetadataForUnusedFields(
-    collector.gmSubclasses,
-    collector.gmSubclassesInvokedMethods,
-    coreTypes,
-    info,
-  );
-
-  return collector;
-}
-
-/// For protobuf fields which are not accessed, prune away its metadata.
-class _UnusedFieldMetadataPruner extends TreeVisitor<void> {
-  final Class tagNumberClass;
-  final Reference tagNumberField;
-  // All of those methods have the dart field name as second positional
-  // parameter.
-  // Method names are defined in:
-  // https://github.com/dart-lang/protobuf/blob/master/protobuf/lib/src/protobuf/builder_info.dart
-  // The code is generated by:
-  // https://github.com/dart-lang/protobuf/blob/master/protoc_plugin/lib/protobuf_field.dart.
-  static final fieldAddingMethods = Set<String>.from(const <String>[
-    'a',
-    'aOM',
-    'aOS',
-    'aQM',
-    'pPS',
-    'aQS',
-    'aInt64',
-    'aOB',
-    'e',
-    'p',
-    'pc',
-    'm',
-  ]);
-
-  final Class builderInfoClass;
-  Class visitedClass;
-  final names = Set<String>();
-  final usedTagNumbers = Set<int>();
-
-  final dynamicNames = Set<String>();
-  final CoreTypes coreTypes;
-  final TransformationInfo info;
-  final Member addMethod;
-
-  _UnusedFieldMetadataPruner(this.tagNumberClass, this.builderInfoClass,
-      this.addMethod, Set<Selector> dynamicSelectors, this.coreTypes, this.info)
-      : tagNumberField = tagNumberClass.fields
-            .firstWhere((f) => f.name.text == 'tagNumber')
-            .getterReference {
-    dynamicNames.addAll(dynamicSelectors.map((sel) => sel.target.text));
-  }
-
-  /// If a proto message field is never accessed (neither read nor written to),
-  /// remove its corresponding metadata in the construction of the Message._i
-  /// field (i.e. the BuilderInfo metadata).
-  void removeMetadataForUnusedFields(
-      Set<Class> gmSubclasses,
-      Map<Class, Set<Selector>> invokedMethods,
-      CoreTypes coreTypes,
-      TransformationInfo info) {
-    for (final klass in gmSubclasses) {
-      final selectors = invokedMethods[klass] ?? Set<Selector>();
-      final builderInfoFields = klass.fields.where((f) => f.name.text == '_i');
-      if (builderInfoFields.isEmpty) {
-        continue;
-      }
-      final builderInfoField = builderInfoFields.single;
-      _pruneBuilderInfoField(builderInfoField, selectors, klass);
-    }
-  }
-
-  void _pruneBuilderInfoField(
-      Field field, Set<Selector> selectors, Class gmSubclass) {
-    names.clear();
-    names.addAll(selectors.map((sel) => sel.target.text));
-    visitedClass = gmSubclass;
-    _computeUsedTagNumbers(gmSubclass);
-    field.initializer.accept(this);
-  }
-
-  void _computeUsedTagNumbers(Class gmSubclass) {
-    usedTagNumbers.clear();
-    for (final procedure in gmSubclass.procedures) {
-      for (final annotation in procedure.annotations) {
-        if (annotation is ConstantExpression) {
-          final constant = annotation.constant;
-          if (constant is InstanceConstant &&
-              constant.classReference == tagNumberClass.reference) {
-            final name = procedure.name.text;
-            if (dynamicNames.contains(name) || names.contains(name)) {
-              usedTagNumbers.add(
-                  (constant.fieldValues[tagNumberField] as IntConstant).value);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  @override
-  visitBlockExpression(BlockExpression node) {
-    // The BuilderInfo field `_i` is set up with a row of cascaded calls.
-    // ```
-    // static final BuilderInfo _i = BuilderInfo('MessageName')
-    //     ..a(1, 'foo', PbFieldType.OM)
-    //     ..a(2, 'bar', PbFieldType.OM)
-    // ```
-    // Each cascaded call will be represented in kernel as an entry in a
-    // BlockExpression (but starts out in a Let), where each statement in block
-    // is an ExpressionStatement, and where each statement will be a call to a
-    // method of `builderInfo`.
-    // For example:
-    // ```
-    // {protobuf::BuilderInfo::a}<dart.core::int*>(1, "foo", #C10)
-    // ```
-    // The methods enumerated in `fieldAddingMethods` are the ones that set up
-    // fields (other methods do other things).
-    //
-    // First argument is the tag-number of the added field.
-    // Second argument is the field-name.
-    // Further arguments are specific to the method.
-    for (Statement statement in node.body.statements) {
-      if (statement is ExpressionStatement) {
-        _changeCascadeEntry(statement.expression);
-      }
-    }
-    node.body.accept(this);
-  }
-
-  @override
-  visitLet(Let node) {
-    // See comment in visitBlockExpression.
-    node.body.accept(this);
-  }
-
-  String _extractFieldName(Expression expression) {
-    if (expression is StringLiteral) {
-      return expression.value;
-    }
-    if (expression is ConditionalExpression) {
-      return _extractFieldName(expression.otherwise);
-    }
-    throw ArgumentError.value(
-        expression, 'expression', 'Unsupported  expression');
-  }
-
-  void _changeCascadeEntry(Expression initializer) {
-    if (initializer is MethodInvocation &&
-        initializer.interfaceTarget?.enclosingClass == builderInfoClass &&
-        fieldAddingMethods.contains(initializer.name.text)) {
-      final tagNumber =
-          (initializer.arguments.positional[0] as IntLiteral).value;
-      if (!usedTagNumbers.contains(tagNumber)) {
-        if (info != null) {
-          final fieldName =
-              _extractFieldName(initializer.arguments.positional[1]);
-          info.removedMessageFields.add("${visitedClass.name}.$fieldName");
-        }
-
-        // Replace the field metadata method with a dummy call to
-        // `BuilderInfo.add`. This is to preserve the index calculations when
-        // removing a field.
-        // Change the tag-number to 0. Otherwise the decoder will get confused.
-        initializer.interfaceTarget = addMethod;
-        initializer.name = addMethod.name;
-        initializer.arguments.replaceWith(
-          Arguments(
-            <Expression>[
-              IntLiteral(0), // tagNumber
-              NullLiteral(), // name
-              NullLiteral(), // fieldType
-              NullLiteral(), // defaultOrMaker
-              NullLiteral(), // subBuilder
-              NullLiteral(), // valueOf
-              NullLiteral(), // enumValues
-            ],
-            types: <DartType>[const NullType()],
-          ),
-        );
-      }
-    }
-  }
-}
-
-/// Finds all subclasses of [GeneratedMessage] and all methods invoked on them
-/// (potentially in a dynamic call).
-class InfoCollector extends RecursiveVisitor<void> {
-  final dynamicSelectors = Set<Selector>();
-  final Class generatedMessageClass;
-  final gmSubclasses = Set<Class>();
-  final gmSubclassesInvokedMethods = Map<Class, Set<Selector>>();
-
-  InfoCollector(this.generatedMessageClass);
-
-  @override
-  visitClass(Class klass) {
-    if (isGeneratedMethodSubclass(klass)) {
-      gmSubclasses.add(klass);
-    }
-    return super.visitClass(klass);
-  }
-
-  @override
-  visitMethodInvocation(MethodInvocation node) {
-    if (node.interfaceTarget == null) {
-      dynamicSelectors.add(Selector.doInvoke(node.name));
-    }
-
-    final targetClass = node.interfaceTarget?.enclosingClass;
-    if (isGeneratedMethodSubclass(targetClass)) {
-      addInvokedMethod(targetClass, Selector.doInvoke(node.name));
-    }
-    super.visitMethodInvocation(node);
-  }
-
-  @override
-  visitPropertyGet(PropertyGet node) {
-    if (node.interfaceTarget == null) {
-      dynamicSelectors.add(Selector.doGet(node.name));
-    }
-
-    final targetClass = node.interfaceTarget?.enclosingClass;
-    if (isGeneratedMethodSubclass(targetClass)) {
-      addInvokedMethod(targetClass, Selector.doGet(node.name));
-    }
-    super.visitPropertyGet(node);
-  }
-
-  @override
-  visitPropertySet(PropertySet node) {
-    if (node.interfaceTarget == null) {
-      dynamicSelectors.add(Selector.doSet(node.name));
-    }
-
-    final targetClass = node.interfaceTarget?.enclosingClass;
-    if (isGeneratedMethodSubclass(targetClass)) {
-      addInvokedMethod(targetClass, Selector.doSet(node.name));
-    }
-    super.visitPropertySet(node);
-  }
-
-  bool isGeneratedMethodSubclass(Class klass) {
-    return klass?.superclass == generatedMessageClass;
-  }
-
-  void addInvokedMethod(Class klass, Selector selector) {
-    final selectors =
-        gmSubclassesInvokedMethods.putIfAbsent(klass, () => Set<Selector>());
-    selectors.add(selector);
-  }
-}
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index b5c33f7..45d05d8 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -504,7 +504,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);
+          .specializeTypeCone((receiver as ConeType).cls, allowWideCone: false);
     }
 
     assert(targets.isEmpty);
@@ -936,6 +936,11 @@
 }
 
 class _TFClassImpl extends TFClass {
+  /// Maximum number of concrete types to use when calculating
+  /// subtype cone specialization. If number of allocated types
+  /// exceeds this constant, then WideConeType approximation is used.
+  static const int maxAllocatedTypesInSetSpecializations = 128;
+
   final Set<_TFClassImpl> supertypes; // List of super-types including this.
   final Set<_TFClassImpl> _allocatedSubtypes = new Set<_TFClassImpl>();
   final Map<Selector, Member> _dispatchTargets = <Selector, Member>{};
@@ -959,6 +964,15 @@
   Type get specializedConeType =>
       _specializedConeType ??= _calculateConeTypeSpecialization();
 
+  bool get hasWideCone =>
+      _allocatedSubtypes.length > maxAllocatedTypesInSetSpecializations;
+
+  WideConeType _wideConeType;
+  WideConeType get wideConeType {
+    assert(hasWideCone);
+    return _wideConeType ??= new WideConeType(this);
+  }
+
   Type _calculateConeTypeSpecialization() {
     final int numSubTypes = _allocatedSubtypes.length;
     if (numSubTypes == 0) {
@@ -1154,21 +1168,23 @@
   }
 
   @override
-  Type specializeTypeCone(TFClass baseClass) {
+  Type specializeTypeCone(TFClass baseClass, {bool allowWideCone = false}) {
     if (kPrintTrace) {
       tracePrint("specializeTypeCone for $baseClass");
     }
     Statistics.typeConeSpecializations++;
 
-    // TODO(alexmarkov): consider approximating type if number of allocated
-    // subtypes is too large
-
     if (baseClass.classNode == coreTypes.objectClass) {
       return const AnyType();
     }
 
     final _TFClassImpl cls = baseClass as _TFClassImpl;
 
+    if (allowWideCone && cls.hasWideCone) {
+      Statistics.typeSpecializationsUsedWideCone++;
+      return cls.wideConeType;
+    }
+
     if (!_sealed) {
       cls.dependencyTracker
           .addDependentInvocation(_typeFlowAnalysis.currentInvocation);
diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
index 8be7d86..4adf6c6 100644
--- a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
+++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
@@ -10,8 +10,6 @@
 import 'table_selector_assigner.dart';
 import 'types.dart';
 import 'utils.dart';
-import '../protobuf_aware_treeshaker/transformer.dart'
-    show excludePositionalParametersFromSignatureShaking;
 import '../../metadata/procedure_attributes.dart';
 
 /// Transform parameters from optional to required when they are always passed,
@@ -125,11 +123,6 @@
   int callCount = 0;
   bool eligible = true;
 
-  /// Whether positional parameters can be eliminated from this member. Some
-  /// protobuf methods require these parameters to be preserved for the
-  /// protobuf-aware tree shaker to function.
-  bool canEliminatePositional = true;
-
   _ParameterInfo ensurePositional(int i) {
     if (positional.length <= i) {
       assert(positional.length == i);
@@ -178,8 +171,7 @@
   bool get isNeverPassed => passCount == 0;
 
   bool get canBeEliminated =>
-      (!isUsed || (isNeverPassed || isConstant && !isChecked) && !isWritten) &&
-      (isNamed || info.canEliminatePositional);
+      (!isUsed || (isNeverPassed || isConstant && !isChecked) && !isWritten);
 
   void observeParameter(
       Member member, VariableDeclaration param, SignatureShaker shaker) {
@@ -244,10 +236,6 @@
         getExternalName(member) != null) {
       info.eligible = false;
     }
-
-    if (excludePositionalParametersFromSignatureShaking(member)) {
-      info.canEliminatePositional = false;
-    }
   }
 
   @override
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index b009b27..20ad897 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -23,6 +23,7 @@
 abstract class Statement extends TypeExpr {
   /// Index of this statement in the [Summary].
   int index = -1;
+  Summary summary;
 
   @override
   Type getComputedType(List<Type> types) {
@@ -258,9 +259,11 @@
     if (selector is! DirectSelector) {
       _observeReceiverType(argTypes[0], typeHierarchy);
     }
+    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) {
       if (staticResultType != null) {
         result = result.intersection(staticResultType, typeHierarchy);
@@ -586,6 +589,7 @@
 /// Summary is a linear sequence of statements representing a type flow in
 /// one member, function or initializer.
 class Summary {
+  final String name;
   int parameterCount;
   int positionalParameterCount;
   int requiredParameterCount;
@@ -594,7 +598,10 @@
   TypeExpr result = null;
   Type resultType = EmptyType();
 
-  Summary(
+  // Analysis time of callees. Populated only if kPrintTimings.
+  int calleeTime;
+
+  Summary(this.name,
       {this.parameterCount: 0,
       this.positionalParameterCount: 0,
       this.requiredParameterCount: 0});
@@ -603,6 +610,7 @@
 
   Statement add(Statement op) {
     op.index = _statements.length;
+    op.summary = this;
     _statements.add(op);
     return op;
   }
@@ -621,6 +629,9 @@
   /// 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 int oldCalleeTime = calleeTime;
+    calleeTime = 0;
     final args = arguments.values;
     final positionalArgCount = arguments.positionalCount;
     final namedArgCount = arguments.namedCount;
@@ -699,6 +710,16 @@
 
     Type computedType = result.getComputedType(types);
     resultType = resultType.union(computedType, typeHierarchy);
+
+    if (kPrintTimings) {
+      final dirtyTime = timer.elapsedMicroseconds;
+      final pureTime = dirtyTime < calleeTime ? 0 : (dirtyTime - calleeTime);
+      Statistics.numSummaryApplications.add(name);
+      Statistics.dirtySummaryAnalysisTime.add(name, dirtyTime);
+      Statistics.pureSummaryAnalysisTime.add(name, pureTime);
+    }
+    calleeTime = oldCalleeTime;
+
     return computedType;
   }
 
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 51daa89..789d1e1 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -596,8 +596,9 @@
 
   Summary createSummary(Member member,
       {fieldSummaryType: FieldSummaryType.kInitializer}) {
-    debugPrint(
-        "===== ${member}${fieldSummaryType == FieldSummaryType.kFieldGuard ? " (guard)" : ""} =====");
+    final String summaryName =
+        "${member}${fieldSummaryType == FieldSummaryType.kFieldGuard ? " (guard)" : ""}";
+    debugPrint("===== $summaryName =====");
     assert(!member.isAbstract);
     assert(!(member is Procedure && member.isRedirectingFactoryConstructor));
 
@@ -620,14 +621,14 @@
       if (hasReceiver) {
         final int numArgs =
             fieldSummaryType == FieldSummaryType.kInitializer ? 1 : 2;
-        _summary = new Summary(
+        _summary = new Summary(summaryName,
             parameterCount: numArgs, positionalParameterCount: numArgs);
         // TODO(alexmarkov): subclass cone
         _receiver = _declareParameter("this",
             _environment.coreTypes.legacyRawType(member.enclosingClass), null,
             isReceiver: true);
       } else {
-        _summary = new Summary();
+        _summary = new Summary(summaryName);
       }
 
       _translator = new RuntimeTypeTranslatorImpl(
@@ -647,7 +648,7 @@
       final numTypeParameters = numTypeParams(member);
       final firstParamIndex = (hasReceiver ? 1 : 0) + numTypeParameters;
 
-      _summary = new Summary(
+      _summary = new Summary(summaryName,
           parameterCount: firstParamIndex +
               function.positionalParameters.length +
               function.namedParameters.length,
@@ -675,18 +676,18 @@
           this, _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo);
 
       // Handle forwarding stubs. We need to check types against the types of
-      // the forwarding stub's target, [member.forwardingStubSuperTarget].
+      // the forwarding stub's target, [member.concreteForwardingStubTarget].
       FunctionNode useTypesFrom = member.function;
       if (member is Procedure &&
           member.isForwardingStub &&
-          member.forwardingStubSuperTarget != null) {
-        final target = member.forwardingStubSuperTarget;
+          member.concreteForwardingStubTarget != null) {
+        final target = member.concreteForwardingStubTarget;
         if (target is Field) {
           useTypesFrom = FunctionNode(null, positionalParameters: [
             VariableDeclaration("value", type: target.type)
           ]);
         } else {
-          useTypesFrom = member.forwardingStubSuperTarget.function;
+          useTypesFrom = member.concreteForwardingStubTarget.function;
         }
       }
 
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 02ffe47..b8b187c 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -590,17 +590,17 @@
         m.type.accept(typeVisitor);
       } else if (m is Procedure) {
         func = m.function;
-        if (m.forwardingStubSuperTarget != null) {
+        if (m.concreteForwardingStubTarget != null) {
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
-              m.forwardingStubSuperTarget,
+              m.concreteForwardingStubTarget,
               isSetter: m.isSetter);
-          addUsedMember(m.forwardingStubSuperTarget);
+          addUsedMember(m.concreteForwardingStubTarget);
         }
-        if (m.forwardingStubInterfaceTarget != null) {
+        if (m.abstractForwardingStubTarget != null) {
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
-              m.forwardingStubInterfaceTarget,
+              m.abstractForwardingStubTarget,
               isSetter: m.isSetter);
-          addUsedMember(m.forwardingStubInterfaceTarget);
+          addUsedMember(m.abstractForwardingStubTarget);
         }
         if (m.memberSignatureOrigin != null) {
           m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
@@ -1326,9 +1326,20 @@
           _makeUnreachableBody(node.function);
         }
         node.function.asyncMarker = AsyncMarker.Sync;
-        if (node.forwardingStubSuperTarget != null ||
-            node.forwardingStubInterfaceTarget != null) {
-          node.stubTarget = null;
+        switch (node.stubKind) {
+          case ProcedureStubKind.Regular:
+          case ProcedureStubKind.NoSuchMethodForwarder:
+            break;
+          case ProcedureStubKind.MemberSignature:
+          case ProcedureStubKind.AbstractForwardingStub:
+          case ProcedureStubKind.ConcreteForwardingStub:
+          case ProcedureStubKind.AbstractMixinStub:
+          case ProcedureStubKind.ConcreteMixinStub:
+            // Make the stub look like a regular procedure so the stub target
+            // isn't expected to be non-null, for instance by the verifier.
+            node.stubKind = ProcedureStubKind.Regular;
+            node.stubTarget = null;
+            break;
         }
         Statistics.methodBodiesDropped++;
       } else if (node is Field) {
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 4392865..c871bd0 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -129,8 +129,14 @@
   bool isSubtype(Class sub, Class sup);
 
   /// Return a more specific type for the type cone with [base] root.
-  /// May return EmptyType, AnyType, ConcreteType or a SetType.
-  Type specializeTypeCone(TFClass base);
+  /// May return EmptyType, AnyType, WideConeType, ConcreteType or a SetType.
+  /// WideConeType can be returned only if [allowWideCone].
+  ///
+  /// This method is used when calculating type flow throughout the program.
+  /// It is correct (although less accurate) for [specializeTypeCone] to return
+  /// a larger set. In such case analysis would admit that a larger set of
+  /// values can flow through the program.
+  Type specializeTypeCone(TFClass base, {bool allowWideCone = false});
 
   Type _cachedIntType;
   Type get intType {
@@ -184,9 +190,19 @@
   Type specialize(TypeHierarchy typeHierarchy) => this;
 
   /// Calculate union of this and [other] types.
+  ///
+  /// This method is used when calculating type flow throughout the program.
+  /// It is correct (although less accurate) for [union] to return
+  /// a larger set. In such case analysis would admit that a larger set of
+  /// values can flow through the program.
   Type union(Type other, TypeHierarchy typeHierarchy);
 
   /// Calculate intersection of this and [other] types.
+  ///
+  /// This method is used when calculating type flow throughout the program.
+  /// It is correct (although less accurate) for [intersection] to return
+  /// a larger set. In such case analysis would admit that a larger set of
+  /// values can flow through the program.
   Type intersection(Type other, TypeHierarchy typeHierarchy);
 }
 
@@ -197,6 +213,7 @@
   Empty,
   Nullable,
   Any,
+  WideCone,
   Set,
   Cone,
   Concrete,
@@ -502,7 +519,7 @@
           : new SetType(_unionLists(types, <ConcreteType>[other]));
     } else if (other is ConeType) {
       return typeHierarchy
-          .specializeTypeCone(other.cls)
+          .specializeTypeCone(other.cls, allowWideCone: true)
           .union(this, typeHierarchy);
     } else {
       throw 'Unexpected type $other';
@@ -535,7 +552,7 @@
       return EmptyType();
     } else if (other is ConeType) {
       return typeHierarchy
-          .specializeTypeCone(other.cls)
+          .specializeTypeCone(other.cls, allowWideCone: true)
           .intersection(this, typeHierarchy);
     } else {
       throw 'Unexpected type $other';
@@ -552,8 +569,9 @@
   ConeType(this.cls);
 
   @override
-  Class getConcreteClass(TypeHierarchy typeHierarchy) =>
-      typeHierarchy.specializeTypeCone(cls).getConcreteClass(typeHierarchy);
+  Class getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
+      .specializeTypeCone(cls, allowWideCone: true)
+      .getConcreteClass(typeHierarchy);
 
   @override
   bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
@@ -588,7 +606,7 @@
 
   @override
   Type specialize(TypeHierarchy typeHierarchy) =>
-      typeHierarchy.specializeTypeCone(cls);
+      typeHierarchy.specializeTypeCone(cls, allowWideCone: true);
 
   @override
   Type union(Type other, TypeHierarchy typeHierarchy) {
@@ -611,7 +629,9 @@
         return this;
       }
     }
-    return typeHierarchy.specializeTypeCone(cls).union(other, typeHierarchy);
+    return typeHierarchy
+        .specializeTypeCone(cls, allowWideCone: true)
+        .union(other, typeHierarchy);
   }
 
   @override
@@ -638,11 +658,101 @@
       }
     }
     return typeHierarchy
-        .specializeTypeCone(cls)
+        .specializeTypeCone(cls, allowWideCone: true)
         .intersection(other, typeHierarchy);
   }
 }
 
+/// Type representing a subtype cone which has too many concrete classes.
+/// It contains instances of all Dart types which extend, mix-in or implement
+/// certain class.
+class WideConeType extends ConeType {
+  WideConeType(TFClass cls) : super(cls);
+
+  @override
+  Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
+
+  @override
+  int get hashCode => (cls.id + 41) & kHashMask;
+
+  @override
+  bool operator ==(other) =>
+      identical(this, other) ||
+      (other is WideConeType) && identical(this.cls, other.cls);
+
+  @override
+  int get order => TypeOrder.WideCone.index;
+
+  @override
+  bool get isSpecialized => true;
+
+  @override
+  Type specialize(TypeHierarchy typeHierarchy) => this;
+
+  @override
+  Type union(Type other, TypeHierarchy typeHierarchy) {
+    if (identical(this, other)) return this;
+    if (other.order < this.order) {
+      return other.union(this, typeHierarchy);
+    }
+    if (other is ConeType) {
+      if (typeHierarchy.isSubtype(other.cls.classNode, this.cls.classNode)) {
+        return this;
+      }
+      if (typeHierarchy.isSubtype(this.cls.classNode, other.cls.classNode)) {
+        return other;
+      }
+    } else if (other is ConcreteType) {
+      if (typeHierarchy.isSubtype(other.cls.classNode, this.cls.classNode)) {
+        return this;
+      }
+      if (typeHierarchy.isSubtype(this.cls.classNode, other.cls.classNode)) {
+        return ConeType(other.cls);
+      }
+    } else if (other is SetType) {
+      bool subtypes = true;
+      for (ConcreteType t in other.types) {
+        if (!typeHierarchy.isSubtype(t.cls.classNode, this.cls.classNode)) {
+          subtypes = false;
+          break;
+        }
+      }
+      if (subtypes) {
+        return this;
+      }
+    } else {
+      throw 'Unexpected type $other';
+    }
+    // Wider approximation.
+    return const AnyType();
+  }
+
+  @override
+  Type intersection(Type other, TypeHierarchy typeHierarchy) {
+    if (identical(this, other)) return this;
+    if (other.order < this.order) {
+      return other.intersection(this, typeHierarchy);
+    }
+    if (other is ConeType) {
+      if (typeHierarchy.isSubtype(other.cls.classNode, this.cls.classNode)) {
+        return other;
+      }
+    } else if (other is ConcreteType) {
+      if (typeHierarchy.isSubtype(other.cls.classNode, this.cls.classNode)) {
+        return other;
+      } else {
+        return const EmptyType();
+      }
+    } else if (other is SetType) {
+      return other;
+    } else {
+      throw 'Unexpected type $other';
+    }
+    // Wider approximation.
+    return this;
+  }
+}
+
 /// Type representing a set of instances of a specific Dart class (no subtypes
 /// or `null` object).
 class ConcreteType extends Type implements Comparable<ConcreteType> {
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index 2502904..2762bd8 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -17,6 +17,9 @@
 const bool kPrintDebug =
     const bool.fromEnvironment('global.type.flow.print.debug');
 
+const bool kPrintTimings =
+    const bool.fromEnvironment('global.type.flow.print.timings');
+
 const bool kPrintStats =
     const bool.fromEnvironment('global.type.flow.print.stats');
 
@@ -123,6 +126,51 @@
       .firstWhere((p) => p.name == name, orElse: () => null);
 }
 
+class Histogram<K> {
+  final Map<K, int> values = <K, int>{};
+
+  void add(K key, [int addition = 1]) {
+    final v = values[key];
+    values[key] = (v ?? 0) + addition;
+  }
+
+  void printTop(String title, int n) {
+    print(
+        '-------------------------------------------------------------------');
+    print(title);
+    print(
+        '-------------------------------------------------------------------');
+    List<K> keys = values.keys.toList();
+    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];
+      print("${values[k].toString().padLeft(9)}   $k");
+    }
+    print(
+        '-------------------------------------------------------------------');
+  }
+}
+
+class CommutativePair {
+  final dynamic v1;
+  final dynamic v2;
+
+  CommutativePair(this.v1, this.v2);
+
+  @override
+  bool operator ==(other) =>
+      other is CommutativePair &&
+      ((v1 == other.v1 && v2 == other.v2) ||
+          (v1 == other.v2 && v2 == other.v1));
+
+  @override
+  int get hashCode => v1.hashCode ^ v2.hashCode;
+
+  @override
+  String toString() => "<$v1, $v2>";
+}
+
 /// Holds various statistic counters for type flow analysis.
 class Statistics {
   static int summariesCreated = 0;
@@ -134,6 +182,7 @@
   static int maxInvalidationsPerInvocation = 0;
   static int recursiveInvocationsApproximated = 0;
   static int typeConeSpecializations = 0;
+  static int typeSpecializationsUsedWideCone = 0;
   static int iterationsOverInvocationsWorkList = 0;
   static int invocationsInvalidatedDuringProcessing = 0;
   static int invocationsQueriedInCache = 0;
@@ -152,6 +201,9 @@
   static int protobufMessagesUsed = 0;
   static int protobufMetadataInitializersUpdated = 0;
   static int protobufMetadataFieldsPruned = 0;
+  static Histogram<String> numSummaryApplications = Histogram<String>();
+  static Histogram<String> dirtySummaryAnalysisTime = Histogram<String>();
+  static Histogram<String> pureSummaryAnalysisTime = Histogram<String>();
 
   /// Resets statistic counters.
   static void reset() {
@@ -164,6 +216,7 @@
     maxInvalidationsPerInvocation = 0;
     recursiveInvocationsApproximated = 0;
     typeConeSpecializations = 0;
+    typeSpecializationsUsedWideCone = 0;
     iterationsOverInvocationsWorkList = 0;
     invocationsInvalidatedDuringProcessing = 0;
     invocationsQueriedInCache = 0;
@@ -182,9 +235,22 @@
     protobufMessagesUsed = 0;
     protobufMetadataInitializersUpdated = 0;
     protobufMetadataFieldsPruned = 0;
+    numSummaryApplications = Histogram<String>();
+    dirtySummaryAnalysisTime = Histogram<String>();
+    pureSummaryAnalysisTime = Histogram<String>();
   }
 
   static void print(String caption) {
+    if (kPrintTimings) {
+      numSummaryApplications.printTop(
+          "Top summaries by number of times analyzed", 1000);
+      dirtySummaryAnalysisTime.printTop(
+          "Top summaries by dirty analysis time (including callees), in microseconds",
+          1000);
+      pureSummaryAnalysisTime.printTop(
+          "Top summaries by pure analysis time (excluding callees), in microseconds",
+          1000);
+    }
     statPrint("""${caption}:
     ${summariesCreated} summaries created
     ${summariesAnalyzed} summaries analyzed
@@ -195,6 +261,7 @@
     ${maxInvalidationsPerInvocation} maximum invalidations per invocation
     ${recursiveInvocationsApproximated} recursive invocations approximated
     ${typeConeSpecializations} type cones specialized
+    ${typeSpecializationsUsedWideCone} type specializations used wide cone
     ${iterationsOverInvocationsWorkList} iterations over invocations work list
     ${invocationsInvalidatedDuringProcessing} invocations invalidated during processing
     ${invocationsQueriedInCache} invocations queried in cache
diff --git a/pkg/vm/test/modular_kernel_plus_aot_test.dart b/pkg/vm/test/modular_kernel_plus_aot_test.dart
index 6d0dc45..8b950bd 100644
--- a/pkg/vm/test/modular_kernel_plus_aot_test.dart
+++ b/pkg/vm/test/modular_kernel_plus_aot_test.dart
@@ -56,19 +56,22 @@
 
     const useGlobalTypeFlowAnalysis = true;
     const enableAsserts = false;
-    const useProtobufTreeShaker = false;
     const useProtobufTreeShakerV2 = false;
     await runGlobalTransformations(
         vmTarget,
         component,
         useGlobalTypeFlowAnalysis,
         enableAsserts,
-        useProtobufTreeShaker,
         useProtobufTreeShakerV2,
         ErrorDetector());
 
     // Verify after running global transformations.
     verifyComponent(component, isOutline: false, afterConst: true);
+
+    // Verify that we can reserialize the component to ensure that all
+    // references are contained within the component.
+    writeComponentToBytes(
+        loadComponentFromBytes(writeComponentToBytes(component)));
   });
 }
 
@@ -90,7 +93,7 @@
       StandardFileSystem.instance, const <String>[], const <String, String>{});
 
   void onDiagnostic(fe.DiagnosticMessage message) {
-    print(message);
+    message.plainTextFormatted.forEach(print);
   }
 
   final Component component =
@@ -119,11 +122,16 @@
 Uri sdkRootFile(name) => Directory.current.uri.resolveUri(Uri.file(name));
 
 const String mainFile = r'''
+// @dart=2.9
+// This library is opt-out to provoke the creation of member signatures in
+// R that point to members of A2.
+
 import 'mixin.dart';
+
 class R extends A2 {
   void bar() {
     mixinProperty = '';
-    mixinProperty .foo();
+    mixinProperty.foo();
     mixinMethod('').foo();
     super.mixinProperty= '';
     super.mixinProperty.foo();
@@ -139,6 +147,7 @@
   a2.mixinProperty= '';
   a2.mixinProperty.foo();
   a2.mixinMethod('').foo();
+  R().bar();
 }
 ''';
 
@@ -148,8 +157,8 @@
 }
 class Mixin {
   void set mixinProperty(v) {}
-  Foo get mixinProperty{}
-  Foo mixinMethod(v) {}
+  Foo get mixinProperty => new Foo();
+  Foo mixinMethod(v) => new Foo();
 }
 class A1 extends Object with Mixin { }
 class A2 extends Object with Mixin { }
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 4a29089..023c93e 100644
--- a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
+++ b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
@@ -8,14 +8,15 @@
 import 'package:kernel/ast.dart';
 import 'package:kernel/kernel.dart';
 import 'package:kernel/binary/ast_to_binary.dart';
+import 'package:kernel/core_types.dart' show CoreTypes;
 import 'package:kernel/src/printer.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
 import 'package:vm/kernel_front_end.dart'
     show runGlobalTransformations, ErrorDetector;
-import 'package:vm/transformations/protobuf_aware_treeshaker/transformer.dart'
-    as treeshaker;
+import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
+    show transformComponent;
 
 import '../../common_test_utils.dart';
 
@@ -39,8 +40,9 @@
       )
       .toList();
 
-  treeshaker.transformComponent(component, {}, TestingVmTarget(TargetFlags()),
-      collectInfo: true);
+  globalTypeFlow.transformComponent(
+      TestingVmTarget(TargetFlags()), CoreTypes(component), component,
+      treeShakeProtobufs: true, treeShakeSignatures: false);
 
   for (Class messageClass in messageClasses) {
     expect(messageClass.enclosingLibrary.classes.contains(messageClass),
@@ -54,6 +56,7 @@
     final sink = file.openWrite();
     final printer = BinaryPrinter(sink, includeSources: false);
 
+    component.metadata.clear();
     printer.writeComponentFile(component);
     await sink.close();
 
@@ -77,15 +80,13 @@
   // Copied verbatim from pkg/vm/bin/protobuf_aware_treeshaker.dart.
   const bool useGlobalTypeFlowAnalysis = true;
   const bool enableAsserts = false;
-  const bool useProtobufAwareTreeShaker = true;
-  const bool useProtobufAwareTreeShakerV2 = false;
+  const bool useProtobufAwareTreeShakerV2 = true;
   final nopErrorDetector = ErrorDetector();
   runGlobalTransformations(
     target,
     component,
     useGlobalTypeFlowAnalysis,
     enableAsserts,
-    useProtobufAwareTreeShaker,
     useProtobufAwareTreeShakerV2,
     nopErrorDetector,
   );
@@ -96,7 +97,9 @@
     pkgVmDir,
     'testcases',
     'transformations',
-    'protobuf_aware_treeshaker',
+    'type_flow',
+    'transformer',
+    'protobuf_handler',
     'lib',
   )).listSync().where((f) => f.path.endsWith('_test.dart'));
   for (final entry in testCases) {
diff --git a/pkg/vm/test/transformations/type_flow/types_test.dart b/pkg/vm/test/transformations/type_flow/types_test.dart
index 326ce81..dbdf093 100644
--- a/pkg/vm/test/transformations/type_flow/types_test.dart
+++ b/pkg/vm/test/transformations/type_flow/types_test.dart
@@ -25,7 +25,7 @@
   }
 
   @override
-  Type specializeTypeCone(TFClass base) {
+  Type specializeTypeCone(TFClass base, {bool allowWideCone = false}) {
     Type result = specializations[base.classNode];
     expect(result, isNotNull,
         reason: "specializeTypeCone($base) is not defined");
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
deleted file mode 100755
index 8031891..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-# 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.
-
-# Running this script requires having protoc_plugin installed in your path.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-
-rm -rf $DIR/lib/generated
-mkdir $DIR/lib/generated
-
-# Directory of the script
-GENERATED_DIR=$DIR/lib/generated
-
-protoc --dart_out=$GENERATED_DIR -I$DIR/protos $DIR/protos/*.proto
-rm $GENERATED_DIR/*.pbenum.dart $GENERATED_DIR/*.pbjson.dart $GENERATED_DIR/*.pbserver.dart
-
-dartfmt -w $DIR/lib/generated
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart
deleted file mode 100644
index 1912459..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/create_test.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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:test/test.dart';
-
-import 'generated/foo.pb.dart';
-
-main() {
-  FooKeep foo = FooKeep()
-    ..barKeep = (BarKeep()..aKeep = 5)
-    ..mapKeep['foo'] = (BarKeep()..aKeep = 2)
-    ..aKeep = 43;
-  test('retrieving values', () {
-    expect(foo.barKeep.aKeep, 5);
-    expect(foo.mapKeep['foo'].aKeep, 2);
-    expect(foo.hasHasKeep(), false);
-    expect(foo.aKeep, 43);
-    foo.clearClearKeep();
-  });
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart
deleted file mode 100644
index d33289f..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/decode_test.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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:test/test.dart';
-
-import 'generated/foo.pb.dart';
-
-List<int> buffer = <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,
-];
-
-main() {
-  FooKeep foo = FooKeep.fromBuffer(buffer);
-  test('Kept values are restored correctly', () {
-    expect(foo.mapKeep['foo'].aKeep, 42);
-    expect(foo.barKeep.aKeep, 5);
-    expect(foo.aKeep, 43);
-    expect(foo.hasHasKeep(), true);
-    foo.clearClearKeep();
-  });
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart
deleted file mode 100644
index de756cc..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/encode_all_fields.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 'dart:math';
-
-import 'generated/foo.pb.dart';
-
-main() {
-  FooKeep foo = FooKeep()
-    ..barKeep = (BarKeep()
-      ..aKeep = 5
-      ..bDrop = 4)
-    ..mapKeep['foo'] = (BarKeep()..aKeep = 42)
-    ..mapDrop['zop'] = (ZopDrop()..aDrop = 3)
-    ..aKeep = 43
-    ..hasKeep = HasKeep()
-    ..clearKeep = ClearKeep();
-  final buffer = foo.writeToBuffer();
-  print('List<int> buffer = <int>[');
-  for (int i = 0; i < buffer.length; i += 5) {
-    final numbers = buffer.sublist(i, min(buffer.length, i + 5)).join(', ');
-    print('  $numbers,${i == 0 ? ' //' : ''}');
-  }
-  print('];');
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/freeze_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/freeze_test.dart
deleted file mode 100644
index 0529e4a..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/freeze_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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:test/test.dart';
-
-import 'generated/foo.pb.dart';
-
-main() {
-  FooKeep foo = FooKeep()
-    ..barKeep = (BarKeep()..aKeep = 5)
-    ..mapKeep['foo'] = (BarKeep()..aKeep = 2)
-    ..aKeep = 43;
-  test('Freezing a message works', () {
-    foo.freeze();
-    expect(foo.barKeep.aKeep, 5);
-    expect(foo.mapKeep['foo'].aKeep, 2);
-    expect(foo.hasHasKeep(), false);
-    expect(foo.aKeep, 43);
-    expect(() => foo.clearClearKeep(),
-        throwsA(const TypeMatcher<UnsupportedError>()));
-  });
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart
deleted file mode 100644
index 19c9bac5..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/foo.pb.dart
+++ /dev/null
@@ -1,440 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: foo.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
-
-import 'dart:core' as $core;
-
-import 'package:protobuf/protobuf.dart' as $pb;
-
-class FooKeep extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FooKeep',
-      createEmptyInstance: create)
-    ..aOM<BarKeep>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'barKeep',
-        protoName: 'barKeep', subBuilder: BarKeep.create)
-    ..aOM<BarKeep>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'barDrop',
-        protoName: 'barDrop', subBuilder: BarKeep.create)
-    ..m<$core.String, BarKeep>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mapKeep',
-        protoName: 'mapKeep',
-        entryClassName: 'FooKeep.MapKeepEntry',
-        keyFieldType: $pb.PbFieldType.OS,
-        valueFieldType: $pb.PbFieldType.OM,
-        valueCreator: BarKeep.create)
-    ..m<$core.String, ZopDrop>(
-        4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'mapDrop',
-        protoName: 'mapDrop',
-        entryClassName: 'FooKeep.MapDropEntry',
-        keyFieldType: $pb.PbFieldType.OS,
-        valueFieldType: $pb.PbFieldType.OM,
-        valueCreator: ZopDrop.create)
-    ..a<$core.int>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'aKeep', $pb.PbFieldType.O3,
-        protoName: 'aKeep')
-    ..aOM<HasKeep>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'hasKeep',
-        protoName: 'hasKeep', subBuilder: HasKeep.create)
-    ..aOM<ClearKeep>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'clearKeep',
-        protoName: 'clearKeep', subBuilder: ClearKeep.create)
-    ..hasRequiredFields = false;
-
-  FooKeep._() : super();
-  factory FooKeep() => create();
-  factory FooKeep.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory FooKeep.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  FooKeep clone() => FooKeep()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  FooKeep copyWith(void Function(FooKeep) updates) =>
-      super.copyWith((message) => updates(message as FooKeep))
-          as FooKeep; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static FooKeep create() => FooKeep._();
-  FooKeep createEmptyInstance() => create();
-  static $pb.PbList<FooKeep> createRepeated() => $pb.PbList<FooKeep>();
-  @$core.pragma('dart2js:noInline')
-  static FooKeep getDefault() =>
-      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FooKeep>(create);
-  static FooKeep? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  BarKeep get barKeep => $_getN(0);
-  @$pb.TagNumber(1)
-  set barKeep(BarKeep v) {
-    setField(1, v);
-  }
-
-  @$pb.TagNumber(1)
-  $core.bool hasBarKeep() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearBarKeep() => clearField(1);
-  @$pb.TagNumber(1)
-  BarKeep ensureBarKeep() => $_ensure(0);
-
-  @$pb.TagNumber(2)
-  BarKeep get barDrop => $_getN(1);
-  @$pb.TagNumber(2)
-  set barDrop(BarKeep v) {
-    setField(2, v);
-  }
-
-  @$pb.TagNumber(2)
-  $core.bool hasBarDrop() => $_has(1);
-  @$pb.TagNumber(2)
-  void clearBarDrop() => clearField(2);
-  @$pb.TagNumber(2)
-  BarKeep ensureBarDrop() => $_ensure(1);
-
-  @$pb.TagNumber(3)
-  $core.Map<$core.String, BarKeep> get mapKeep => $_getMap(2);
-
-  @$pb.TagNumber(4)
-  $core.Map<$core.String, ZopDrop> get mapDrop => $_getMap(3);
-
-  @$pb.TagNumber(5)
-  $core.int get aKeep => $_getIZ(4);
-  @$pb.TagNumber(5)
-  set aKeep($core.int v) {
-    $_setSignedInt32(4, v);
-  }
-
-  @$pb.TagNumber(5)
-  $core.bool hasAKeep() => $_has(4);
-  @$pb.TagNumber(5)
-  void clearAKeep() => clearField(5);
-
-  @$pb.TagNumber(6)
-  HasKeep get hasKeep => $_getN(5);
-  @$pb.TagNumber(6)
-  set hasKeep(HasKeep v) {
-    setField(6, v);
-  }
-
-  @$pb.TagNumber(6)
-  $core.bool hasHasKeep() => $_has(5);
-  @$pb.TagNumber(6)
-  void clearHasKeep() => clearField(6);
-  @$pb.TagNumber(6)
-  HasKeep ensureHasKeep() => $_ensure(5);
-
-  @$pb.TagNumber(7)
-  ClearKeep get clearKeep => $_getN(6);
-  @$pb.TagNumber(7)
-  set clearKeep(ClearKeep v) {
-    setField(7, v);
-  }
-
-  @$pb.TagNumber(7)
-  $core.bool hasClearKeep() => $_has(6);
-  @$pb.TagNumber(7)
-  void clearClearKeep() => clearField(7);
-  @$pb.TagNumber(7)
-  ClearKeep ensureClearKeep() => $_ensure(6);
-}
-
-class BarKeep extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(
-      const $core.bool.fromEnvironment('protobuf.omit_message_names')
-          ? ''
-          : 'BarKeep',
-      createEmptyInstance: create)
-    ..a<$core.int>(
-        1,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'aKeep',
-        $pb.PbFieldType.O3,
-        protoName: 'aKeep')
-    ..a<$core.int>(
-        2,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'bDrop',
-        $pb.PbFieldType.O3,
-        protoName: 'bDrop')
-    ..hasRequiredFields = false;
-
-  BarKeep._() : super();
-  factory BarKeep() => create();
-  factory BarKeep.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory BarKeep.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  BarKeep clone() => BarKeep()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  BarKeep copyWith(void Function(BarKeep) updates) =>
-      super.copyWith((message) => updates(message as BarKeep))
-          as BarKeep; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static BarKeep create() => BarKeep._();
-  BarKeep createEmptyInstance() => create();
-  static $pb.PbList<BarKeep> createRepeated() => $pb.PbList<BarKeep>();
-  @$core.pragma('dart2js:noInline')
-  static BarKeep getDefault() =>
-      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BarKeep>(create);
-  static BarKeep? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.int get aKeep => $_getIZ(0);
-  @$pb.TagNumber(1)
-  set aKeep($core.int v) {
-    $_setSignedInt32(0, v);
-  }
-
-  @$pb.TagNumber(1)
-  $core.bool hasAKeep() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearAKeep() => clearField(1);
-
-  @$pb.TagNumber(2)
-  $core.int get bDrop => $_getIZ(1);
-  @$pb.TagNumber(2)
-  set bDrop($core.int v) {
-    $_setSignedInt32(1, v);
-  }
-
-  @$pb.TagNumber(2)
-  $core.bool hasBDrop() => $_has(1);
-  @$pb.TagNumber(2)
-  void clearBDrop() => clearField(2);
-}
-
-class HasKeep extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(
-      const $core.bool.fromEnvironment('protobuf.omit_message_names')
-          ? ''
-          : 'HasKeep',
-      createEmptyInstance: create)
-    ..a<$core.int>(
-        1,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'aDrop',
-        $pb.PbFieldType.O3,
-        protoName: 'aDrop')
-    ..hasRequiredFields = false;
-
-  HasKeep._() : super();
-  factory HasKeep() => create();
-  factory HasKeep.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory HasKeep.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  HasKeep clone() => HasKeep()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  HasKeep copyWith(void Function(HasKeep) updates) =>
-      super.copyWith((message) => updates(message as HasKeep))
-          as HasKeep; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static HasKeep create() => HasKeep._();
-  HasKeep createEmptyInstance() => create();
-  static $pb.PbList<HasKeep> createRepeated() => $pb.PbList<HasKeep>();
-  @$core.pragma('dart2js:noInline')
-  static HasKeep getDefault() =>
-      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<HasKeep>(create);
-  static HasKeep? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.int get aDrop => $_getIZ(0);
-  @$pb.TagNumber(1)
-  set aDrop($core.int v) {
-    $_setSignedInt32(0, v);
-  }
-
-  @$pb.TagNumber(1)
-  $core.bool hasADrop() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearADrop() => clearField(1);
-}
-
-class ClearKeep extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(
-      const $core.bool.fromEnvironment('protobuf.omit_message_names')
-          ? ''
-          : 'ClearKeep',
-      createEmptyInstance: create)
-    ..a<$core.int>(
-        1,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'aDrop',
-        $pb.PbFieldType.O3,
-        protoName: 'aDrop')
-    ..hasRequiredFields = false;
-
-  ClearKeep._() : super();
-  factory ClearKeep() => create();
-  factory ClearKeep.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory ClearKeep.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  ClearKeep clone() => ClearKeep()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  ClearKeep copyWith(void Function(ClearKeep) updates) =>
-      super.copyWith((message) => updates(message as ClearKeep))
-          as ClearKeep; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static ClearKeep create() => ClearKeep._();
-  ClearKeep createEmptyInstance() => create();
-  static $pb.PbList<ClearKeep> createRepeated() => $pb.PbList<ClearKeep>();
-  @$core.pragma('dart2js:noInline')
-  static ClearKeep getDefault() =>
-      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ClearKeep>(create);
-  static ClearKeep? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.int get aDrop => $_getIZ(0);
-  @$pb.TagNumber(1)
-  set aDrop($core.int v) {
-    $_setSignedInt32(0, v);
-  }
-
-  @$pb.TagNumber(1)
-  $core.bool hasADrop() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearADrop() => clearField(1);
-}
-
-class ZopDrop extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(
-      const $core.bool.fromEnvironment('protobuf.omit_message_names')
-          ? ''
-          : 'ZopDrop',
-      createEmptyInstance: create)
-    ..a<$core.int>(
-        1,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'aDrop',
-        $pb.PbFieldType.O3,
-        protoName: 'aDrop')
-    ..hasRequiredFields = false;
-
-  ZopDrop._() : super();
-  factory ZopDrop() => create();
-  factory ZopDrop.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory ZopDrop.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  ZopDrop clone() => ZopDrop()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  ZopDrop copyWith(void Function(ZopDrop) updates) =>
-      super.copyWith((message) => updates(message as ZopDrop))
-          as ZopDrop; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static ZopDrop create() => ZopDrop._();
-  ZopDrop createEmptyInstance() => create();
-  static $pb.PbList<ZopDrop> createRepeated() => $pb.PbList<ZopDrop>();
-  @$core.pragma('dart2js:noInline')
-  static ZopDrop getDefault() =>
-      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ZopDrop>(create);
-  static ZopDrop? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.int get aDrop => $_getIZ(0);
-  @$pb.TagNumber(1)
-  set aDrop($core.int v) {
-    $_setSignedInt32(0, v);
-  }
-
-  @$pb.TagNumber(1)
-  $core.bool hasADrop() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearADrop() => clearField(1);
-}
-
-class MobDrop extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(
-      const $core.bool.fromEnvironment('protobuf.omit_message_names')
-          ? ''
-          : 'MobDrop',
-      createEmptyInstance: create)
-    ..a<$core.int>(
-        1,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'aDrop',
-        $pb.PbFieldType.O3,
-        protoName: 'aDrop')
-    ..hasRequiredFields = false;
-
-  MobDrop._() : super();
-  factory MobDrop() => create();
-  factory MobDrop.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory MobDrop.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  MobDrop clone() => MobDrop()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  MobDrop copyWith(void Function(MobDrop) updates) =>
-      super.copyWith((message) => updates(message as MobDrop))
-          as MobDrop; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static MobDrop create() => MobDrop._();
-  MobDrop createEmptyInstance() => create();
-  static $pb.PbList<MobDrop> createRepeated() => $pb.PbList<MobDrop>();
-  @$core.pragma('dart2js:noInline')
-  static MobDrop getDefault() =>
-      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MobDrop>(create);
-  static MobDrop? _defaultInstance;
-
-  @$pb.TagNumber(1)
-  $core.int get aDrop => $_getIZ(0);
-  @$pb.TagNumber(1)
-  set aDrop($core.int v) {
-    $_setSignedInt32(0, v);
-  }
-
-  @$pb.TagNumber(1)
-  $core.bool hasADrop() => $_has(0);
-  @$pb.TagNumber(1)
-  void clearADrop() => clearField(1);
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/name_mangling.pb.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/name_mangling.pb.dart
deleted file mode 100644
index c42141a..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/name_mangling.pb.dart
+++ /dev/null
@@ -1,105 +0,0 @@
-///
-//  Generated code. Do not modify.
-//  source: name_mangling.proto
-//
-// @dart = 2.12
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
-
-import 'dart:core' as $core;
-
-import 'package:protobuf/protobuf.dart' as $pb;
-
-class AKeep extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(
-      const $core.bool.fromEnvironment('protobuf.omit_message_names')
-          ? ''
-          : 'AKeep',
-      createEmptyInstance: create)
-    ..hasRequiredFields = false;
-
-  AKeep._() : super();
-  factory AKeep() => create();
-  factory AKeep.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory AKeep.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  AKeep clone() => AKeep()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  AKeep copyWith(void Function(AKeep) updates) =>
-      super.copyWith((message) => updates(message as AKeep))
-          as AKeep; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static AKeep create() => AKeep._();
-  AKeep createEmptyInstance() => create();
-  static $pb.PbList<AKeep> createRepeated() => $pb.PbList<AKeep>();
-  @$core.pragma('dart2js:noInline')
-  static AKeep getDefault() =>
-      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AKeep>(create);
-  static AKeep? _defaultInstance;
-}
-
-class NameManglingKeep extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(
-      const $core.bool.fromEnvironment('protobuf.omit_message_names')
-          ? ''
-          : 'NameManglingKeep',
-      createEmptyInstance: create)
-    ..aOM<AKeep>(
-        10,
-        const $core.bool.fromEnvironment('protobuf.omit_field_names')
-            ? ''
-            : 'clone',
-        subBuilder: AKeep.create)
-    ..hasRequiredFields = false;
-
-  NameManglingKeep._() : super();
-  factory NameManglingKeep() => create();
-  factory NameManglingKeep.fromBuffer($core.List<$core.int> i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromBuffer(i, r);
-  factory NameManglingKeep.fromJson($core.String i,
-          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
-      create()..mergeFromJson(i, r);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
-      'Will be removed in next major version')
-  NameManglingKeep clone() => NameManglingKeep()..mergeFromMessage(this);
-  @$core.Deprecated('Using this can add significant overhead to your binary. '
-      'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
-      'Will be removed in next major version')
-  NameManglingKeep copyWith(void Function(NameManglingKeep) updates) =>
-      super.copyWith((message) => updates(message as NameManglingKeep))
-          as NameManglingKeep; // ignore: deprecated_member_use
-  $pb.BuilderInfo get info_ => _i;
-  @$core.pragma('dart2js:noInline')
-  static NameManglingKeep create() => NameManglingKeep._();
-  NameManglingKeep createEmptyInstance() => create();
-  static $pb.PbList<NameManglingKeep> createRepeated() =>
-      $pb.PbList<NameManglingKeep>();
-  @$core.pragma('dart2js:noInline')
-  static NameManglingKeep getDefault() => _defaultInstance ??=
-      $pb.GeneratedMessage.$_defaultFor<NameManglingKeep>(create);
-  static NameManglingKeep? _defaultInstance;
-
-  @$pb.TagNumber(10)
-  AKeep get clone_10 => $_getN(0);
-  @$pb.TagNumber(10)
-  set clone_10(AKeep v) {
-    setField(10, v);
-  }
-
-  @$pb.TagNumber(10)
-  $core.bool hasClone_10() => $_has(0);
-  @$pb.TagNumber(10)
-  void clearClone_10() => clearField(10);
-  @$pb.TagNumber(10)
-  AKeep ensureClone_10() => $_ensure(0);
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/name_mangling_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/name_mangling_test.dart
deleted file mode 100644
index b52c5dc..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/name_mangling_test.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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:test/test.dart';
-
-import 'generated/name_mangling.pb.dart';
-
-main() {
-  NameManglingKeep n = NameManglingKeep.fromBuffer([]);
-  if (n.hasClone_10()) {
-    print("Has clone field");
-  }
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/nop_test.dart b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/nop_test.dart
deleted file mode 100644
index 60997dc..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/nop_test.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// 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.
-
-main() {
-  // Ensures the protobuf-aware tree shaker can also transform non-protobuf
-  // using code.
-  print("hello world");
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
deleted file mode 100644
index 1f10872..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-syntax = "proto3";
-
-message FooKeep {
-  BarKeep barKeep = 1;
-  BarKeep barDrop = 2;
-  map<string, BarKeep> mapKeep = 3;
-  map<string, ZopDrop> mapDrop = 4;
-  int32 aKeep = 5;
-  HasKeep hasKeep = 6;
-  ClearKeep clearKeep = 7;
-}
-
-message BarKeep {
-  int32 aKeep = 1;
-  int32 bDrop = 2;
-}
-
-message HasKeep {
-  int32 aDrop = 1;
-}
-
-message ClearKeep {
-  int32 aDrop = 1;
-}
-
-message ZopDrop {
-  int32 aDrop = 1;
-}
-
-message MobDrop {
-  int32 aDrop = 1;
-}
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/name_mangling.proto b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/name_mangling.proto
deleted file mode 100644
index f25b2f4..0000000
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/name_mangling.proto
+++ /dev/null
@@ -1,10 +0,0 @@
-syntax = "proto3";
-
-message AKeep {}
-
-message NameManglingKeep {
-  // the name `clone` is mangled by the protoc_plugin to not conflict with
-  // `GeneratedMessage.clone`.
-  // Still we should be able to detect usages of this field.
-  AKeep clone = 10;
-}
\ No newline at end of file
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 250bacb..d0227dd 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
@@ -156,10 +156,11 @@
 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 [#lib::foo] (_T (dart.core::_GrowableList<#lib::C4*>))
-t9 = _Call direct [#lib::foo] (_T (#lib::C3))
-t10 = _Join [dynamic] (_T (#lib::C3), t8)
-t11 = _Call direct [#lib::bar] (t10)
+t8* = _Call direct [dart.core::_GrowableList._literal2] (#lib::C4*, _T (#lib::C4), _T {})
+t9* = _Call direct [#lib::foo] (t8)
+t10 = _Call direct [#lib::foo] (_T (#lib::C3))
+t11 = _Join [dynamic] (_T (#lib::C3), t9)
+t12 = _Call direct [#lib::bar] (t11)
 RESULT: _T {}?
 ------------ loop1 ------------
 t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
@@ -190,14 +191,15 @@
 ------------ 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))
-t3* = _Call get [dart.core::Iterable.iterator] (_T (dart.core::_GrowableList<dynamic?>))
-t4* = _Call [dart.core::Iterator.moveNext] (t3)
-t5 = _Narrow (t3 to _T ANY)
-t6 = _Call get [dart.core::Iterator.current] (t5)
+t2* = _Call direct [#lib::foo] (_T (#lib::C2))
+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))
-t8 = _Call direct [#lib::foo] (x_0)
-t9 = _Call direct [#lib::C3.] (_T (#lib::C3))
+t9 = _Call direct [#lib::foo] (x_0)
+t10 = _Call direct [#lib::C3.] (_T (#lib::C3))
 RESULT: x_0
 ------------ loop5 ------------
 t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
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 173e18b..5f90ab8 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
@@ -6,7 +6,7 @@
 [@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.<(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::<=}(_in::unsafeCast<core::num>(n)); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
+  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::<=}(_in::unsafeCast<core::num*>(n)); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
     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.%(i).{core::Object::==}(0))
       return false;
   }
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 59e2b69..6fce119 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
@@ -22,7 +22,7 @@
     : 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 member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3]  abstract operator ==(dynamic other) → core::bool*;
 }
 abstract class _StreamImpl extends self::Stream {
   synthetic constructor •() → self::_StreamImpl*
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 b4f873e..63fc423 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
@@ -37,7 +37,7 @@
   new self::T1::•();
 }
 static method main(core::List<core::String*>* args) → dynamic {
-  self::foo1(<self::T1*>[]);
+  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/lists.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
index c02e36d..7bb6dcf 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
@@ -4,8 +4,8 @@
 import "dart:_internal" as _in;
 
 class A extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::List<core::int*>* literal1 = <core::int*>[];
-[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  final field core::List<core::int*>* literal2 = <core::int*>[1, 2, 3];
+[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::List<core::int*>* literal1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::•<core::int*>(0);
+[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  final field core::List<core::int*>* literal2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::_literal3<core::int*>(1, 2, 3);
 [@vm.inferred-type.metadata=dart.core::_ImmutableList (value: const <dart.core::int*>[])] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  final field core::List<core::int*>* constLiteral1 = #C1;
 [@vm.inferred-type.metadata=dart.core::_ImmutableList (value: const <dart.core::int*>[1, 2])] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  final field core::List<core::int*>* constLiteral2 = #C4;
 [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field core::List<core::int*>* defaultConstructor1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::•<core::int*>(0);
@@ -22,7 +22,7 @@
 [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:16]  final field core::List<core::int*>* generateFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::generate<core::int*>(2, (core::int* i) → core::int* => i);
 [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:17]  final field core::List<core::int*>* generateFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::generate<core::int*>((core::int* i) → core::int* => i);
 [@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:18]  final field core::List<core::int*>* generateFactory4 = let final (core::int*) →* core::int* #t3 = (core::int* i) → core::int* => i in let final core::bool #t4 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::generate<core::int*>(#t3, #t4);
-[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int*>*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:19]  final field core::List<core::List<core::int*>*>* generateFactory5 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int*>*>] core::_GrowableList::generate<core::List<core::int*>*>(2, (core::int* _) → core::List<core::int*>* => <core::int*>[]);
+[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int*>*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:19]  final field core::List<core::List<core::int*>*>* generateFactory5 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int*>*>] core::_GrowableList::generate<core::List<core::int*>*>(2, (core::int* _) → core::List<core::int*>* => core::_GrowableList::•<core::int*>(0));
   synthetic constructor •() → self::A*
     : super core::Object::•()
     ;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart.expect
index 8d53437..2f2f5db 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart.expect
@@ -4,8 +4,8 @@
 import "dart:_internal" as _in;
 
 class A extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::List<core::int> literal1 = <core::int>[];
-[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  final field core::List<core::int> literal2 = <core::int>[1, 2, 3];
+[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::List<core::int> literal1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::•<core::int>(0);
+[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  final field core::List<core::int> literal2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::_literal3<core::int>(1, 2, 3);
 [@vm.inferred-type.metadata=dart.core::_ImmutableList (value: const <dart.core::int*>[])] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  final field core::List<core::int> constLiteral1 = #C1;
 [@vm.inferred-type.metadata=dart.core::_ImmutableList (value: const <dart.core::int*>[1, 2])] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  final field core::List<core::int> constLiteral2 = #C4;
 [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field core::List<core::int> filledFactory1 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::filled<core::int>(2, 0);
@@ -20,7 +20,7 @@
 [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:14]  final field core::List<core::int> generateFactory2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::generate<core::int>(2, (core::int i) → core::int => i);
 [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:15]  final field core::List<core::int> generateFactory3 = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int>] core::_List::generate<core::int>((core::int i) → core::int => i);
 [@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:16]  final field core::List<core::int> generateFactory4 = let final (core::int) → core::int #t3 = (core::int i) → core::int => i in let final core::bool #t4 = _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::nonConstant()) in [@vm.inferred-type.metadata=!] core::List::generate<core::int>(#t3, #t4);
-[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int>>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:17]  final field core::List<core::List<core::int>> generateFactory5 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int>>] core::_GrowableList::generate<core::List<core::int>>(2, (core::int _) → core::List<core::int> => <core::int>[]);
+[@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int>>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:17]  final field core::List<core::List<core::int>> generateFactory5 = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::List<dart.core::int>>] core::_GrowableList::generate<core::List<core::int>>(2, (core::int _) → core::List<core::int> => core::_GrowableList::•<core::int>(0));
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
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 5b69347..6aeb4eb 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
@@ -53,7 +53,7 @@
 [@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))));
 [@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>(<dynamic>[a1, a2, a3, a4, #C7]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
+    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))));
 }
 abstract class C extends core::Object {
   synthetic constructor •() → self::C*
@@ -72,7 +72,7 @@
 [@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))));
 [@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>(<dynamic>[a1, a2, a3, a4, #C7]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))));
+    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))));
 }
 class E extends core::Object implements self::A {
   synthetic constructor •() → self::E*
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart.expect
index 1b24ebc..90d79cb 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart.expect
@@ -19,7 +19,7 @@
 static method testAlwaysNull([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
   return [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}!;
 static method main() → void {
-  final core::List<self::A> list = <self::A>[new self::A::•("foo", null), self::staticField];
+  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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
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 17ed46c..2c04a27 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
@@ -51,7 +51,7 @@
 static method someCondition() → dynamic
   return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1);
 static method main() → void {
-  final core::List<self::A*>* list = <self::A*>[new self::A::•("foo", null), self::staticField];
+  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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
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 a697cdd..ec70e94 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
@@ -38,11 +38,11 @@
 [@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);
     [@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);
-    [@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", #C2);
+    [@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);
     [@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);
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep", #C3);
-    [@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);
-    [@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);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep");
+    [@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);
+    [@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", #C4);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t1;
   constructor _() → self::FooKeep
@@ -52,36 +52,36 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
-  @#C8
+  @#C7
   static method create() → self::FooKeep
     return new self::FooKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  @#C10
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  @#C9
   get barKeep() → self::BarKeep
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep>();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  @#C10
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  @#C9
   set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(v);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C11
   get mapKeep() → core::Map<core::String, self::BarKeep>
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String, self::BarKeep>();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i]  @#C14
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i]  @#C13
   get aKeep() → core::int
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b]  @#C14
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b]  @#C13
   set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  @#C16
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  @#C15
   method hasHasKeep() → core::bool
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  @#C18
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  @#C17
   method clearClearKeep() → void
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}();
 }
 class BarKeep extends pro::GeneratedMessage {
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t2 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "BarKeep") in block {
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aKeep", #C3);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aKeep");
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t2;
@@ -92,13 +92,13 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
-  @#C8
+  @#C7
   static method create() → self::BarKeep
     return new self::BarKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i]  @#C10
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i]  @#C9
   get aKeep() → core::int
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(i)->b]  @#C10
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(i)->b]  @#C9
   set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
   }
@@ -113,7 +113,7 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
-  @#C8
+  @#C7
   static method create() → self::HasKeep
     return new self::HasKeep::_();
 }
@@ -127,7 +127,7 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
-  @#C8
+  @#C7
   static method create() → self::ClearKeep
     return new self::ClearKeep::_();
 }
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 14a4689..71dc247 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
@@ -31,11 +31,11 @@
 [@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);
     [@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);
-    [@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", #C3);
+    [@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);
     [@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);
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep", #C4);
-    [@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", #C5);
-    [@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", #C6);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep");
+    [@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);
+    [@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);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t1;
   constructor _() → self::FooKeep
@@ -47,28 +47,28 @@
     } =>#t2;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
-  @#C9
+  @#C8
   static method create() → self::FooKeep
     return new self::FooKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  @#C11
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  @#C10
   get barKeep() → self::BarKeep
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep>();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  @#C13
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  @#C12
   get mapKeep() → core::Map<core::String, self::BarKeep>
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String, self::BarKeep>();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  @#C15
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  @#C14
   get aKeep() → core::int
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  @#C17
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  @#C16
   method hasHasKeep() → core::bool
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  @#C19
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  @#C18
   method clearClearKeep() → void
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}();
 }
 class BarKeep extends pro::GeneratedMessage {
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t3 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "BarKeep", createEmptyInstance: #C3) in block {
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aKeep", #C4);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aKeep");
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t3;
@@ -77,15 +77,15 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
-  @#C9
+  @#C8
   static method create() → self::BarKeep
     return new self::BarKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:9] [@vm.unboxing-info.metadata=()->i]  @#C11
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:9] [@vm.unboxing-info.metadata=()->i]  @#C10
   get aKeep() → core::int
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
 }
 class HasKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t4 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "HasKeep", createEmptyInstance: #C5) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t4 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "HasKeep", createEmptyInstance: #C4) in block {
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t4;
@@ -94,12 +94,12 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
-  @#C9
+  @#C8
   static method create() → self::HasKeep
     return new self::HasKeep::_();
 }
 class ClearKeep extends pro::GeneratedMessage {
-[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t5 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "ClearKeep", createEmptyInstance: #C6) in block {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t5 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "ClearKeep", createEmptyInstance: #C5) in block {
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t5;
@@ -108,7 +108,7 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
-  @#C9
+  @#C8
   static method create() → self::ClearKeep
     return new self::ClearKeep::_();
 }
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 4980123..e99a0c0 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
@@ -47,9 +47,9 @@
     [@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);
     [@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);
     [@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);
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep", #C4, "aKeep");
-    [@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", #C5);
-    [@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", #C6);
+    [@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");
+    [@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);
+    [@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);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t1;
   constructor _() → self::FooKeep
@@ -59,36 +59,36 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
-  @#C9
+  @#C8
   static method create() → self::FooKeep
     return new self::FooKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2]  @#C11
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2]  @#C10
   set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  @#C13
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  @#C12
   get mapKeep() → core::Map<core::String, self::BarKeep>
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String, self::BarKeep>(2);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C15
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C14
   get mapDrop() → core::Map<core::String, self::ZopDrop>
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String, self::ZopDrop>(3);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] [@vm.unboxing-info.metadata=(i)->b]  @#C17
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] [@vm.unboxing-info.metadata=(i)->b]  @#C16
   set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6]  @#C19
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6]  @#C18
   set hasKeep([@vm.inferred-type.metadata=foo.pb.dart::HasKeep] self::HasKeep v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(6, v);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7]  @#C21
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7]  @#C20
   set clearKeep([@vm.inferred-type.metadata=foo.pb.dart::ClearKeep] self::ClearKeep v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(7, v);
   }
 }
 class BarKeep extends pro::GeneratedMessage {
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t2 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "BarKeep") in block {
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aKeep", #C4, "aKeep");
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int>(2, (#C1) ?{core::String} "" : "bDrop", #C4, "bDrop");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aKeep", "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int>(2, (#C1) ?{core::String} "" : "bDrop", "bDrop");
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t2;
   constructor _() → self::BarKeep
@@ -98,14 +98,14 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
-  @#C9
+  @#C8
   static method create() → self::BarKeep
     return new self::BarKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8] [@vm.unboxing-info.metadata=(i)->b]  @#C11
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8] [@vm.unboxing-info.metadata=(i)->b]  @#C10
   set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9] [@vm.unboxing-info.metadata=(i)->b]  @#C23
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9] [@vm.unboxing-info.metadata=(i)->b]  @#C22
   set bDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] core::int v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(1, v);
   }
@@ -122,7 +122,7 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::HasKeep] self::HasKeep::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
-  @#C9
+  @#C8
   static method create() → self::HasKeep
     return new self::HasKeep::_();
 }
@@ -138,13 +138,13 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::ClearKeep] self::ClearKeep::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
-  @#C9
+  @#C8
   static method create() → self::ClearKeep
     return new self::ClearKeep::_();
 }
 class ZopDrop extends pro::GeneratedMessage {
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t5 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "ZopDrop") in block {
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aDrop", #C4, "aDrop");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aDrop", "aDrop");
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t5;
   constructor _() → self::ZopDrop
@@ -154,10 +154,10 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::ZopDrop] self::ZopDrop::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ZopDrop::_i;
-  @#C9
+  @#C8
   static method create() → self::ZopDrop
     return new self::ZopDrop::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10] [@vm.unboxing-info.metadata=(i)->b]  @#C11
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10] [@vm.unboxing-info.metadata=(i)->b]  @#C10
   set aDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] core::int v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
   }
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 15a7ebf..b750159 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
@@ -41,11 +41,11 @@
 [@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);
     [@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);
-    [@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", #C2);
+    [@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);
     [@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);
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep", #C3);
-    [@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);
-    [@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);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep");
+    [@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);
+    [@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", #C4);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t1;
   constructor _() → self::FooKeep
@@ -55,36 +55,36 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
-  @#C8
+  @#C7
   static method create() → self::FooKeep
     return new self::FooKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  @#C10
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  @#C9
   get barKeep() → self::BarKeep
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep>();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  @#C10
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  @#C9
   set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(v);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C12
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C11
   get mapKeep() → core::Map<core::String, self::BarKeep>
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String, self::BarKeep>();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i]  @#C14
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i]  @#C13
   get aKeep() → core::int
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b]  @#C14
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b]  @#C13
   set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
   }
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  @#C16
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8]  @#C15
   method hasHasKeep() → core::bool
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  @#C18
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  @#C17
   method clearClearKeep() → void
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}();
 }
 class BarKeep extends pro::GeneratedMessage {
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t2 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "BarKeep") in block {
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aKeep", #C3);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int>(1, (#C1) ?{core::String} "" : "aKeep");
     [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t2;
@@ -95,13 +95,13 @@
     return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
-  @#C8
+  @#C7
   static method create() → self::BarKeep
     return new self::BarKeep::_();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i]  @#C10
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i]  @#C9
   get aKeep() → core::int
     return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(i)->b]  @#C10
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(i)->b]  @#C9
   set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int v) → void {
     [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
   }
@@ -116,7 +116,7 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
-  @#C8
+  @#C7
   static method create() → self::HasKeep
     return new self::HasKeep::_();
 }
@@ -130,7 +130,7 @@
     ;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  get info_() → pro::BuilderInfo
     return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
-  @#C8
+  @#C7
   static method create() → self::ClearKeep
     return new self::ClearKeep::_();
 }
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 6f760ed..f3b8f42 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
@@ -7,7 +7,7 @@
 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(<core::int*>[]);
+  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::print("Has clone field");
   }
@@ -35,7 +35,7 @@
 }
 class NameManglingKeep extends pro::GeneratedMessage {
 [@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t2 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "NameManglingKeep", #C6) in block {
-    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::aOM}<self::AKeep>(10, (#C1) ?{core::String} "" : "clone", #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::aOM}<self::AKeep>((#C1) ?{core::String} "" : "clone", #C2);
     [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
   } =>#t2;
   constructor _() → self::NameManglingKeep
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 416164b..b142142 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
@@ -3,29 +3,29 @@
 import "dart:core" as core;
 
 class A extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1]  final field core::List<dynamic>* afield;
-  constructor •([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] 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.direct-call.metadata=dart.core::_GrowableList.toString] [@vm.inferred-type.metadata=!? (skip check) (receiver not int)] [@vm.direct-call.metadata=#lib::A.afield] [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] this.{self::A::afield}.{core::Object::toString}();
+    return [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A.afield] this.{self::A::afield}.{core::Object::toString}();
 }
 class B extends core::Object {
   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 = <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}()) {
       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::num::<}(0)) {
         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=dart.core::_GrowableList<dynamic> (skip check)] this.{self::B::_foo}(iter)));
+      [@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)));
     }
     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*>]<core::int*>[1, 2, 3].{core::Iterable::iterator});
+  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::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 662b365..3798fa8 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
@@ -5,4 +5,4 @@
 [@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));
 static method main() → dynamic
-  return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print([@vm.inferred-type.metadata=int] self::foo(<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_42413.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect
index 81b5d0b..187070f 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
@@ -14,7 +14,7 @@
 [@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} = <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 {
@@ -28,7 +28,7 @@
   }
 [@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}.length)); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
+    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}.length)); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
       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}.[](i);
       core::print([@vm.direct-call.metadata=#lib::B.x??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0) (receiver not int)] e.x);
     }
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 5df0c21..3162618 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
@@ -36,7 +36,7 @@
     [@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));
     [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}(null);
   }
-  final core::List<self::B*>* l = <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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
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 11a9912..a700bd1 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
@@ -36,7 +36,7 @@
     [@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));
     [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}(null);
   }
-  final core::List<self::B*>* l = <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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
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 7b4579e..53f54b7 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
@@ -101,7 +101,7 @@
     ;
 }
 static method main() → dynamic {
-  core::List<self::A1*>* x1 = <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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -109,7 +109,7 @@
       o.{self::A1::foo}();
     }
   }
-  core::List<self::A2*>* x2 = <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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -117,7 +117,7 @@
       o.{self::A2::foo}();
     }
   }
-  core::List<self::A3*>* x3 = <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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -125,7 +125,7 @@
       o.{self::A3::foo}();
     }
   }
-  core::List<self::A4*>* x4 = <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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -133,7 +133,7 @@
       o.{self::A4::foo}();
     }
   }
-  core::List<self::B4*>* y4 = <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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
@@ -141,7 +141,7 @@
       o.{self::B4::foo}();
     }
   }
-  core::List<self::C4*>* z4 = <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};
     for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
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 3b1f57e..b9d738c 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
@@ -12,7 +12,7 @@
     : 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().foo() as{TypeError,ForDynamic} core::num) as{TypeError} 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().foo() as{TypeError,ForDynamic} core::num*) as{TypeError} 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;
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 dde5bb5..8558915 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
@@ -14,7 +14,7 @@
     : 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().bar())));
+    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().bar())));
 [@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;
 }
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 6090bf0..2b87ac1 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
@@ -14,14 +14,14 @@
     : 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().foo())));
+    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().foo())));
 }
 abstract class Base extends core::Object {
   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().foo())));
+    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().foo())));
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6]  method doCall(dynamic x) → core::int*
     return [@vm.call-site-attributes.metadata=receiverType:dynamic] x.call() as{TypeError,ForDynamic} core::int*;
 }
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 34bb4b0..b66946e 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
@@ -125,7 +125,7 @@
   [@vm.inferred-type.metadata=!? (receiver not int)] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final core::List<core::Object*>* values = <core::Object*>[new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•()];
+  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")) 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")) 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")) as self::SubImpl3*;
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 0b24d0e..2411b2f 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
@@ -125,7 +125,7 @@
   [@vm.inferred-type.metadata=!? (receiver not int)] self::usedObject.{core::Object::==}(null) ?{dynamic} self::usedObject = object : null;
 }
 static method main() → dynamic {
-  final core::List<core::Object*>* values = <core::Object*>[new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•()];
+  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")) 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")) 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")) as self::SubImpl3*;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart.expect
index 001ee63..1431eb6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart.expect
@@ -20,7 +20,7 @@
     [@vm.direct-call.metadata=#lib::B.x] [@vm.inferred-type.metadata=!? (skip check)] this.{self::B::x} = 3;
   }
 }
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] [@vm.unboxing-info.metadata=(i)->i]late static final field core::int staticLateB;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] [@vm.unboxing-info.metadata=(i)->i]late static final [setter] field core::int staticLateB;
 static method main() → void {
   [@vm.direct-call.metadata=#lib::A.use] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::use}();
   [@vm.direct-call.metadata=#lib::B.use] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::use}();
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 c1d8144..d27c9fc 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
@@ -67,7 +67,7 @@
   for (; ; ) {
   }
   {
-    core::Iterator<core::int*>* :sync-for-iterator = <core::int*>[1, 2].{core::Iterable::iterator};
+    core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(1, 2).{core::Iterable::iterator};
     for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
       core::int* i = :sync-for-iterator.{core::Iterator::current};
     }
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index 6010ee8..192cac3 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -34,7 +34,6 @@
     ;;
     --tfa | \
     --no-tfa | \
-    --protobuf-tree-shaker | \
     --protobuf-tree-shaker-v2 | \
     --minimal-kernel | \
     --no-embed-sources | \
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 4b6ac4a..4bd758c 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,29 @@
 # Changelog
 
+## 6.0.1-nullsafety.0
+- Fix versioning for pub.
+
+## 6.0.0-nullsafety.4
+- Fixed issue where response parsing could fail for `SourceReportRange.coverage`
+  if no coverage information was provided.
+## 6.0.0-nullsafety.3
+- Fixed issue where `Response.type` and classes which override `Response.type` were
+  returning the name of the `package:vm_service` reference object (e.g., InstanceRef) instead of
+  the type specified in the specification (e.g., @Instance).
+
+## 6.0.0-nullsafety.2
+- *breaking* Updated signature of `Field.staticValue` to `dynamic` in order to
+  properly allow for uninitialized sentinel values.
+
+## 6.0.0-nullsafety.1
+- *breaking* Null safety migration, take two. Assume all object fields are nullable.
+
+## 6.0.0-nullsafety-dev
+- *breaking* Migrate to use null safety.
+
+## 5.5.1
+- Fix issue where `VmService.onDone` could complete before the provided `DisposeHandler` had finished executing.
+
 ## 5.5.0
 - Update to version `3.42.0` of the spec.
 - Added optional `limit` parameter to `getStack` RPC.
diff --git a/pkg/vm_service/example/vm_service_assert.dart b/pkg/vm_service/example/vm_service_assert.dart
index 0243d12..a0938bf 100644
--- a/pkg/vm_service/example/vm_service_assert.dart
+++ b/pkg/vm_service/example/vm_service_assert.dart
@@ -14,17 +14,14 @@
 }
 
 bool assertBool(bool obj) {
-  assertNotNull(obj);
   return obj;
 }
 
 int assertInt(int obj) {
-  assertNotNull(obj);
   return obj;
 }
 
 double assertDouble(double obj) {
-  assertNotNull(obj);
   return obj;
 }
 
@@ -55,13 +52,11 @@
 }
 
 String assertString(String obj) {
-  assertNotNull(obj);
   if (obj.isEmpty) throw 'expected non-zero length string';
   return obj;
 }
 
 vms.Success assertSuccess(vms.Success obj) {
-  assertNotNull(obj);
   if (obj.type != 'Success') throw 'expected Success';
   return obj;
 }
@@ -75,10 +70,10 @@
       event.kind == vms.EventKind.kBreakpointAdded ||
       event.kind == vms.EventKind.kBreakpointRemoved ||
       event.kind == vms.EventKind.kBreakpointResolved) {
-    assertBreakpoint(event.breakpoint);
+    assertBreakpoint(event.breakpoint!);
   }
   if (event.kind == vms.EventKind.kPauseBreakpoint) {
-    for (vms.Breakpoint elem in event.pauseBreakpoints) {
+    for (vms.Breakpoint elem in event.pauseBreakpoints!) {
       assertBreakpoint(elem);
     }
   }
@@ -94,18 +89,18 @@
     if (event.topFrame != null ||
         (event.kind != vms.EventKind.kPauseInterrupted &&
             event.kind != vms.EventKind.kResume)) {
-      assertFrame(event.topFrame);
+      assertFrame(event.topFrame!);
     }
   }
   if (event.kind == vms.EventKind.kPauseException) {
-    assertInstanceRef(event.exception);
+    assertInstanceRef(event.exception!);
   }
   if (event.kind == vms.EventKind.kPauseBreakpoint ||
       event.kind == vms.EventKind.kPauseInterrupted) {
-    assertBool(event.atAsyncSuspension);
+    assertBool(event.atAsyncSuspension!);
   }
   if (event.kind == vms.EventKind.kInspect) {
-    assertInstanceRef(event.inspectee);
+    assertInstanceRef(event.inspectee!);
   }
   return event;
 }
@@ -115,7 +110,7 @@
 vms.Event assertIsolateEvent(vms.Event event) {
   assertEvent(event);
   if (event.kind == vms.EventKind.kServiceExtensionAdded) {
-    assertString(event.extensionRPC);
+    assertString(event.extensionRPC!);
   }
   return event;
 }
@@ -250,19 +245,18 @@
 
 vms.AllocationProfile assertAllocationProfile(vms.AllocationProfile obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfClassHeapStats(obj.members);
-  assertMemoryUsage(obj.memoryUsage);
+  assertListOfClassHeapStats(obj.members!);
+  assertMemoryUsage(obj.memoryUsage!);
   return obj;
 }
 
 vms.BoundField assertBoundField(vms.BoundField obj) {
   assertNotNull(obj);
-  assertFieldRef(obj.decl);
+  assertFieldRef(obj.decl!);
   if (obj.value is vms.InstanceRef) {
-    assertInstanceRef(obj.value);
+    assertInstanceRef(obj.value!);
   } else if (obj.value is vms.Sentinel) {
-    assertSentinel(obj.value);
+    assertSentinel(obj.value!);
   } else {
     throw "Unexpected value: ${obj.value}";
   }
@@ -271,20 +265,19 @@
 
 vms.BoundVariable assertBoundVariable(vms.BoundVariable obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.name);
+  assertString(obj.name!);
   if (obj.value is vms.InstanceRef) {
-    assertInstanceRef(obj.value);
+    assertInstanceRef(obj.value!);
   } else if (obj.value is vms.TypeArgumentsRef) {
-    assertTypeArgumentsRef(obj.value);
+    assertTypeArgumentsRef(obj.value!);
   } else if (obj.value is vms.Sentinel) {
-    assertSentinel(obj.value);
+    assertSentinel(obj.value!);
   } else {
     throw "Unexpected value: ${obj.value}";
   }
-  assertInt(obj.declarationTokenPos);
-  assertInt(obj.scopeStartTokenPos);
-  assertInt(obj.scopeEndTokenPos);
+  assertInt(obj.declarationTokenPos!);
+  assertInt(obj.scopeStartTokenPos!);
+  assertInt(obj.scopeEndTokenPos!);
   return obj;
 }
 
@@ -298,14 +291,13 @@
 
 vms.Breakpoint assertBreakpoint(vms.Breakpoint obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertInt(obj.breakpointNumber);
-  assertBool(obj.resolved);
+  assertString(obj.id!);
+  assertInt(obj.breakpointNumber!);
+  assertBool(obj.resolved!);
   if (obj.location is vms.SourceLocation) {
-    assertSourceLocation(obj.location);
+    assertSourceLocation(obj.location!);
   } else if (obj.location is vms.UnresolvedSourceLocation) {
-    assertUnresolvedSourceLocation(obj.location);
+    assertUnresolvedSourceLocation(obj.location!);
   } else {
     throw "Unexpected value: ${obj.location}";
   }
@@ -321,9 +313,8 @@
 
 vms.ClassRef assertClassRef(vms.ClassRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
+  assertString(obj.id!);
+  assertString(obj.name!);
   return obj;
 }
 
@@ -336,27 +327,25 @@
 
 vms.Class assertClass(vms.Class obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
-  assertBool(obj.isAbstract);
-  assertBool(obj.isConst);
-  assertLibraryRef(obj.library);
-  assertListOfInstanceRef(obj.interfaces);
-  assertListOfFieldRef(obj.fields);
-  assertListOfFuncRef(obj.functions);
-  assertListOfClassRef(obj.subclasses);
+  assertString(obj.id!);
+  assertString(obj.name!);
+  assertBool(obj.isAbstract!);
+  assertBool(obj.isConst!);
+  assertLibraryRef(obj.library!);
+  assertListOfInstanceRef(obj.interfaces!);
+  assertListOfFieldRef(obj.fields!);
+  assertListOfFuncRef(obj.functions!);
+  assertListOfClassRef(obj.subclasses!);
   return obj;
 }
 
 vms.ClassHeapStats assertClassHeapStats(vms.ClassHeapStats obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertClassRef(obj.classRef);
-  assertInt(obj.accumulatedSize);
-  assertInt(obj.bytesCurrent);
-  assertInt(obj.instancesAccumulated);
-  assertInt(obj.instancesCurrent);
+  assertClassRef(obj.classRef!);
+  assertInt(obj.accumulatedSize!);
+  assertInt(obj.bytesCurrent!);
+  assertInt(obj.instancesAccumulated!);
+  assertInt(obj.instancesCurrent!);
   return obj;
 }
 
@@ -370,17 +359,15 @@
 
 vms.ClassList assertClassList(vms.ClassList obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfClassRef(obj.classes);
+  assertListOfClassRef(obj.classes!);
   return obj;
 }
 
 vms.CodeRef assertCodeRef(vms.CodeRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
-  assertCodeKind(obj.kind);
+  assertString(obj.id!);
+  assertString(obj.name!);
+  assertCodeKind(obj.kind!);
   return obj;
 }
 
@@ -393,18 +380,16 @@
 
 vms.Code assertCode(vms.Code obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
-  assertCodeKind(obj.kind);
+  assertString(obj.id!);
+  assertString(obj.name!);
+  assertCodeKind(obj.kind!);
   return obj;
 }
 
 vms.ContextRef assertContextRef(vms.ContextRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertInt(obj.length);
+  assertString(obj.id!);
+  assertInt(obj.length!);
   return obj;
 }
 
@@ -417,19 +402,18 @@
 
 vms.Context assertContext(vms.Context obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertInt(obj.length);
-  assertListOfContextElement(obj.variables);
+  assertString(obj.id!);
+  assertInt(obj.length!);
+  assertListOfContextElement(obj.variables!);
   return obj;
 }
 
 vms.ContextElement assertContextElement(vms.ContextElement obj) {
   assertNotNull(obj);
   if (obj.value is vms.InstanceRef) {
-    assertInstanceRef(obj.value);
+    assertInstanceRef(obj.value!);
   } else if (obj.value is vms.Sentinel) {
-    assertSentinel(obj.value);
+    assertSentinel(obj.value!);
   } else {
     throw "Unexpected value: ${obj.value}";
   }
@@ -446,24 +430,23 @@
 
 vms.CpuSamples assertCpuSamples(vms.CpuSamples obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInt(obj.samplePeriod);
-  assertInt(obj.maxStackDepth);
-  assertInt(obj.sampleCount);
-  assertInt(obj.timeSpan);
-  assertInt(obj.timeOriginMicros);
-  assertInt(obj.timeExtentMicros);
-  assertInt(obj.pid);
-  assertListOfProfileFunction(obj.functions);
-  assertListOfCpuSample(obj.samples);
+  assertInt(obj.samplePeriod!);
+  assertInt(obj.maxStackDepth!);
+  assertInt(obj.sampleCount!);
+  assertInt(obj.timeSpan!);
+  assertInt(obj.timeOriginMicros!);
+  assertInt(obj.timeExtentMicros!);
+  assertInt(obj.pid!);
+  assertListOfProfileFunction(obj.functions!);
+  assertListOfCpuSample(obj.samples!);
   return obj;
 }
 
 vms.CpuSample assertCpuSample(vms.CpuSample obj) {
   assertNotNull(obj);
-  assertInt(obj.tid);
-  assertInt(obj.timestamp);
-  assertListOfInt(obj.stack);
+  assertInt(obj.tid!);
+  assertInt(obj.timestamp!);
+  assertListOfInt(obj.stack!);
   return obj;
 }
 
@@ -476,10 +459,9 @@
 
 vms.ErrorRef assertErrorRef(vms.ErrorRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertErrorKind(obj.kind);
-  assertString(obj.message);
+  assertString(obj.id!);
+  assertErrorKind(obj.kind!);
+  assertString(obj.message!);
   return obj;
 }
 
@@ -492,18 +474,16 @@
 
 vms.Error assertError(vms.Error obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertErrorKind(obj.kind);
-  assertString(obj.message);
+  assertString(obj.id!);
+  assertErrorKind(obj.kind!);
+  assertString(obj.message!);
   return obj;
 }
 
 vms.Event assertEvent(vms.Event obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertEventKind(obj.kind);
-  assertInt(obj.timestamp);
+  assertEventKind(obj.kind!);
+  assertInt(obj.timestamp!);
   return obj;
 }
 
@@ -514,14 +494,13 @@
 
 vms.FieldRef assertFieldRef(vms.FieldRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
-  assertObjRef(obj.owner);
-  assertInstanceRef(obj.declaredType);
-  assertBool(obj.isConst);
-  assertBool(obj.isFinal);
-  assertBool(obj.isStatic);
+  assertString(obj.id!);
+  assertString(obj.name!);
+  assertObjRef(obj.owner!);
+  assertInstanceRef(obj.declaredType!);
+  assertBool(obj.isConst!);
+  assertBool(obj.isFinal!);
+  assertBool(obj.isStatic!);
   return obj;
 }
 
@@ -534,22 +513,21 @@
 
 vms.Field assertField(vms.Field obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
-  assertObjRef(obj.owner);
-  assertInstanceRef(obj.declaredType);
-  assertBool(obj.isConst);
-  assertBool(obj.isFinal);
-  assertBool(obj.isStatic);
+  assertString(obj.id!);
+  assertString(obj.name!);
+  assertObjRef(obj.owner!);
+  assertInstanceRef(obj.declaredType!);
+  assertBool(obj.isConst!);
+  assertBool(obj.isFinal!);
+  assertBool(obj.isStatic!);
   return obj;
 }
 
 vms.Flag assertFlag(vms.Flag obj) {
   assertNotNull(obj);
-  assertString(obj.name);
-  assertString(obj.comment);
-  assertBool(obj.modified);
+  assertString(obj.name!);
+  assertString(obj.comment!);
+  assertBool(obj.modified!);
   return obj;
 }
 
@@ -562,15 +540,13 @@
 
 vms.FlagList assertFlagList(vms.FlagList obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfFlag(obj.flags);
+  assertListOfFlag(obj.flags!);
   return obj;
 }
 
 vms.Frame assertFrame(vms.Frame obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInt(obj.index);
+  assertInt(obj.index!);
   return obj;
 }
 
@@ -583,20 +559,19 @@
 
 vms.FuncRef assertFuncRef(vms.FuncRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
+  assertString(obj.id!);
+  assertString(obj.name!);
   if (obj.owner is vms.LibraryRef) {
-    assertLibraryRef(obj.owner);
+    assertLibraryRef(obj.owner!);
   } else if (obj.owner is vms.ClassRef) {
-    assertClassRef(obj.owner);
+    assertClassRef(obj.owner!);
   } else if (obj.owner is vms.FuncRef) {
-    assertFuncRef(obj.owner);
+    assertFuncRef(obj.owner!);
   } else {
     throw "Unexpected value: ${obj.owner}";
   }
-  assertBool(obj.isStatic);
-  assertBool(obj.isConst);
+  assertBool(obj.isStatic!);
+  assertBool(obj.isConst!);
   return obj;
 }
 
@@ -609,29 +584,27 @@
 
 vms.Func assertFunc(vms.Func obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
+  assertString(obj.id!);
+  assertString(obj.name!);
   if (obj.owner is vms.LibraryRef) {
-    assertLibraryRef(obj.owner);
+    assertLibraryRef(obj.owner!);
   } else if (obj.owner is vms.ClassRef) {
-    assertClassRef(obj.owner);
+    assertClassRef(obj.owner!);
   } else if (obj.owner is vms.FuncRef) {
-    assertFuncRef(obj.owner);
+    assertFuncRef(obj.owner!);
   } else {
     throw "Unexpected value: ${obj.owner}";
   }
-  assertBool(obj.isStatic);
-  assertBool(obj.isConst);
+  assertBool(obj.isStatic!);
+  assertBool(obj.isConst!);
   return obj;
 }
 
 vms.InstanceRef assertInstanceRef(vms.InstanceRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertInstanceKind(obj.kind);
-  assertClassRef(obj.classRef);
+  assertString(obj.id!);
+  assertInstanceKind(obj.kind!);
+  assertClassRef(obj.classRef!);
   return obj;
 }
 
@@ -644,20 +617,18 @@
 
 vms.Instance assertInstance(vms.Instance obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertInstanceKind(obj.kind);
-  assertClassRef(obj.classRef);
+  assertString(obj.id!);
+  assertInstanceKind(obj.kind!);
+  assertClassRef(obj.classRef!);
   return obj;
 }
 
 vms.IsolateRef assertIsolateRef(vms.IsolateRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.number);
-  assertString(obj.name);
-  assertBool(obj.isSystemIsolate);
+  assertString(obj.id!);
+  assertString(obj.number!);
+  assertString(obj.name!);
+  assertBool(obj.isSystemIsolate!);
   return obj;
 }
 
@@ -670,37 +641,35 @@
 
 vms.Isolate assertIsolate(vms.Isolate obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.number);
-  assertString(obj.name);
-  assertBool(obj.isSystemIsolate);
-  assertListOfIsolateFlag(obj.isolateFlags);
-  assertInt(obj.startTime);
-  assertBool(obj.runnable);
-  assertInt(obj.livePorts);
-  assertBool(obj.pauseOnExit);
-  assertEvent(obj.pauseEvent);
-  assertListOfLibraryRef(obj.libraries);
-  assertListOfBreakpoint(obj.breakpoints);
-  assertExceptionPauseMode(obj.exceptionPauseMode);
+  assertString(obj.id!);
+  assertString(obj.number!);
+  assertString(obj.name!);
+  assertBool(obj.isSystemIsolate!);
+  assertListOfIsolateFlag(obj.isolateFlags!);
+  assertInt(obj.startTime!);
+  assertBool(obj.runnable!);
+  assertInt(obj.livePorts!);
+  assertBool(obj.pauseOnExit!);
+  assertEvent(obj.pauseEvent!);
+  assertListOfLibraryRef(obj.libraries!);
+  assertListOfBreakpoint(obj.breakpoints!);
+  assertExceptionPauseMode(obj.exceptionPauseMode!);
   return obj;
 }
 
 vms.IsolateFlag assertIsolateFlag(vms.IsolateFlag obj) {
   assertNotNull(obj);
-  assertString(obj.name);
-  assertString(obj.valueAsString);
+  assertString(obj.name!);
+  assertString(obj.valueAsString!);
   return obj;
 }
 
 vms.IsolateGroupRef assertIsolateGroupRef(vms.IsolateGroupRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.number);
-  assertString(obj.name);
-  assertBool(obj.isSystemIsolateGroup);
+  assertString(obj.id!);
+  assertString(obj.number!);
+  assertString(obj.name!);
+  assertBool(obj.isSystemIsolateGroup!);
   return obj;
 }
 
@@ -714,25 +683,23 @@
 
 vms.IsolateGroup assertIsolateGroup(vms.IsolateGroup obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.number);
-  assertString(obj.name);
-  assertBool(obj.isSystemIsolateGroup);
-  assertListOfIsolateRef(obj.isolates);
+  assertString(obj.id!);
+  assertString(obj.number!);
+  assertString(obj.name!);
+  assertBool(obj.isSystemIsolateGroup!);
+  assertListOfIsolateRef(obj.isolates!);
   return obj;
 }
 
 vms.InboundReferences assertInboundReferences(vms.InboundReferences obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfInboundReference(obj.references);
+  assertListOfInboundReference(obj.references!);
   return obj;
 }
 
 vms.InboundReference assertInboundReference(vms.InboundReference obj) {
   assertNotNull(obj);
-  assertObjRef(obj.source);
+  assertObjRef(obj.source!);
   return obj;
 }
 
@@ -746,18 +713,16 @@
 
 vms.InstanceSet assertInstanceSet(vms.InstanceSet obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInt(obj.totalCount);
-  assertListOfObjRef(obj.instances);
+  assertInt(obj.totalCount!);
+  assertListOfObjRef(obj.instances!);
   return obj;
 }
 
 vms.LibraryRef assertLibraryRef(vms.LibraryRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
-  assertString(obj.uri);
+  assertString(obj.id!);
+  assertString(obj.name!);
+  assertString(obj.uri!);
   return obj;
 }
 
@@ -770,25 +735,24 @@
 
 vms.Library assertLibrary(vms.Library obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
-  assertString(obj.uri);
-  assertBool(obj.debuggable);
-  assertListOfLibraryDependency(obj.dependencies);
-  assertListOfScriptRef(obj.scripts);
-  assertListOfFieldRef(obj.variables);
-  assertListOfFuncRef(obj.functions);
-  assertListOfClassRef(obj.classes);
+  assertString(obj.id!);
+  assertString(obj.name!);
+  assertString(obj.uri!);
+  assertBool(obj.debuggable!);
+  assertListOfLibraryDependency(obj.dependencies!);
+  assertListOfScriptRef(obj.scripts!);
+  assertListOfFieldRef(obj.variables!);
+  assertListOfFuncRef(obj.functions!);
+  assertListOfClassRef(obj.classes!);
   return obj;
 }
 
 vms.LibraryDependency assertLibraryDependency(vms.LibraryDependency obj) {
   assertNotNull(obj);
-  assertBool(obj.isImport);
-  assertBool(obj.isDeferred);
-  assertString(obj.prefix);
-  assertLibraryRef(obj.target);
+  assertBool(obj.isImport!);
+  assertBool(obj.isDeferred!);
+  assertString(obj.prefix!);
+  assertLibraryRef(obj.target!);
   return obj;
 }
 
@@ -802,31 +766,30 @@
 
 vms.LogRecord assertLogRecord(vms.LogRecord obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInstanceRef(obj.message);
-  assertInt(obj.time);
-  assertInt(obj.level);
-  assertInt(obj.sequenceNumber);
-  assertInstanceRef(obj.loggerName);
-  assertInstanceRef(obj.zone);
-  assertInstanceRef(obj.error);
-  assertInstanceRef(obj.stackTrace);
+  assertInstanceRef(obj.message!);
+  assertInt(obj.time!);
+  assertInt(obj.level!);
+  assertInt(obj.sequenceNumber!);
+  assertInstanceRef(obj.loggerName!);
+  assertInstanceRef(obj.zone!);
+  assertInstanceRef(obj.error!);
+  assertInstanceRef(obj.stackTrace!);
   return obj;
 }
 
 vms.MapAssociation assertMapAssociation(vms.MapAssociation obj) {
   assertNotNull(obj);
   if (obj.key is vms.InstanceRef) {
-    assertInstanceRef(obj.key);
+    assertInstanceRef(obj.key!);
   } else if (obj.key is vms.Sentinel) {
-    assertSentinel(obj.key);
+    assertSentinel(obj.key!);
   } else {
     throw "Unexpected value: ${obj.key}";
   }
   if (obj.value is vms.InstanceRef) {
-    assertInstanceRef(obj.value);
+    assertInstanceRef(obj.value!);
   } else if (obj.value is vms.Sentinel) {
-    assertSentinel(obj.value);
+    assertSentinel(obj.value!);
   } else {
     throw "Unexpected value: ${obj.value}";
   }
@@ -835,20 +798,18 @@
 
 vms.MemoryUsage assertMemoryUsage(vms.MemoryUsage obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInt(obj.externalUsage);
-  assertInt(obj.heapCapacity);
-  assertInt(obj.heapUsage);
+  assertInt(obj.externalUsage!);
+  assertInt(obj.heapCapacity!);
+  assertInt(obj.heapUsage!);
   return obj;
 }
 
 vms.Message assertMessage(vms.Message obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInt(obj.index);
-  assertString(obj.name);
-  assertString(obj.messageObjectId);
-  assertInt(obj.size);
+  assertInt(obj.index!);
+  assertString(obj.name!);
+  assertString(obj.messageObjectId!);
+  assertInt(obj.size!);
   return obj;
 }
 
@@ -861,17 +822,16 @@
 
 vms.NativeFunction assertNativeFunction(vms.NativeFunction obj) {
   assertNotNull(obj);
-  assertString(obj.name);
+  assertString(obj.name!);
   return obj;
 }
 
 vms.NullValRef assertNullValRef(vms.NullValRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertInstanceKind(obj.kind);
-  assertClassRef(obj.classRef);
-  assertString(obj.valueAsString);
+  assertString(obj.id!);
+  assertInstanceKind(obj.kind!);
+  assertClassRef(obj.classRef!);
+  assertString(obj.valueAsString!);
   return obj;
 }
 
@@ -884,18 +844,16 @@
 
 vms.NullVal assertNullVal(vms.NullVal obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertInstanceKind(obj.kind);
-  assertClassRef(obj.classRef);
-  assertString(obj.valueAsString);
+  assertString(obj.id!);
+  assertInstanceKind(obj.kind!);
+  assertClassRef(obj.classRef!);
+  assertString(obj.valueAsString!);
   return obj;
 }
 
 vms.ObjRef assertObjRef(vms.ObjRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
+  assertString(obj.id!);
   return obj;
 }
 
@@ -908,25 +866,23 @@
 
 vms.Obj assertObj(vms.Obj obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
+  assertString(obj.id!);
   return obj;
 }
 
 vms.PortList assertPortList(vms.PortList obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfInstanceRef(obj.ports);
+  assertListOfInstanceRef(obj.ports!);
   return obj;
 }
 
 vms.ProfileFunction assertProfileFunction(vms.ProfileFunction obj) {
   assertNotNull(obj);
-  assertString(obj.kind);
-  assertInt(obj.inclusiveTicks);
-  assertInt(obj.exclusiveTicks);
-  assertString(obj.resolvedUrl);
-  assertDynamic(obj.function);
+  assertString(obj.kind!);
+  assertInt(obj.inclusiveTicks!);
+  assertInt(obj.exclusiveTicks!);
+  assertString(obj.resolvedUrl!);
+  assertDynamic(obj.function!);
   return obj;
 }
 
@@ -940,16 +896,15 @@
 
 vms.ProtocolList assertProtocolList(vms.ProtocolList obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfProtocol(obj.protocols);
+  assertListOfProtocol(obj.protocols!);
   return obj;
 }
 
 vms.Protocol assertProtocol(vms.Protocol obj) {
   assertNotNull(obj);
-  assertString(obj.protocolName);
-  assertInt(obj.major);
-  assertInt(obj.minor);
+  assertString(obj.protocolName!);
+  assertInt(obj.major!);
+  assertInt(obj.minor!);
   return obj;
 }
 
@@ -962,17 +917,16 @@
 
 vms.ProcessMemoryUsage assertProcessMemoryUsage(vms.ProcessMemoryUsage obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertProcessMemoryItem(obj.root);
+  assertProcessMemoryItem(obj.root!);
   return obj;
 }
 
 vms.ProcessMemoryItem assertProcessMemoryItem(vms.ProcessMemoryItem obj) {
   assertNotNull(obj);
-  assertString(obj.name);
-  assertString(obj.description);
-  assertInt(obj.size);
-  assertListOfProcessMemoryItem(obj.children);
+  assertString(obj.name!);
+  assertString(obj.description!);
+  assertInt(obj.size!);
+  assertListOfProcessMemoryItem(obj.children!);
   return obj;
 }
 
@@ -986,14 +940,13 @@
 
 vms.ReloadReport assertReloadReport(vms.ReloadReport obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertBool(obj.success);
+  assertBool(obj.success!);
   return obj;
 }
 
 vms.RetainingObject assertRetainingObject(vms.RetainingObject obj) {
   assertNotNull(obj);
-  assertObjRef(obj.value);
+  assertObjRef(obj.value!);
   return obj;
 }
 
@@ -1007,32 +960,28 @@
 
 vms.RetainingPath assertRetainingPath(vms.RetainingPath obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInt(obj.length);
-  assertString(obj.gcRootType);
-  assertListOfRetainingObject(obj.elements);
+  assertInt(obj.length!);
+  assertString(obj.gcRootType!);
+  assertListOfRetainingObject(obj.elements!);
   return obj;
 }
 
 vms.Response assertResponse(vms.Response obj) {
   assertNotNull(obj);
-  assertString(obj.type);
   return obj;
 }
 
 vms.Sentinel assertSentinel(vms.Sentinel obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertSentinelKind(obj.kind);
-  assertString(obj.valueAsString);
+  assertSentinelKind(obj.kind!);
+  assertString(obj.valueAsString!);
   return obj;
 }
 
 vms.ScriptRef assertScriptRef(vms.ScriptRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.uri);
+  assertString(obj.id!);
+  assertString(obj.uri!);
   return obj;
 }
 
@@ -1045,50 +994,46 @@
 
 vms.Script assertScript(vms.Script obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.uri);
-  assertLibraryRef(obj.library);
+  assertString(obj.id!);
+  assertString(obj.uri!);
+  assertLibraryRef(obj.library!);
   return obj;
 }
 
 vms.ScriptList assertScriptList(vms.ScriptList obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfScriptRef(obj.scripts);
+  assertListOfScriptRef(obj.scripts!);
   return obj;
 }
 
 vms.SourceLocation assertSourceLocation(vms.SourceLocation obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertScriptRef(obj.script);
-  assertInt(obj.tokenPos);
+  assertScriptRef(obj.script!);
+  assertInt(obj.tokenPos!);
   return obj;
 }
 
 vms.SourceReport assertSourceReport(vms.SourceReport obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfSourceReportRange(obj.ranges);
-  assertListOfScriptRef(obj.scripts);
+  assertListOfSourceReportRange(obj.ranges!);
+  assertListOfScriptRef(obj.scripts!);
   return obj;
 }
 
 vms.SourceReportCoverage assertSourceReportCoverage(
     vms.SourceReportCoverage obj) {
   assertNotNull(obj);
-  assertListOfInt(obj.hits);
-  assertListOfInt(obj.misses);
+  assertListOfInt(obj.hits!);
+  assertListOfInt(obj.misses!);
   return obj;
 }
 
 vms.SourceReportRange assertSourceReportRange(vms.SourceReportRange obj) {
   assertNotNull(obj);
-  assertInt(obj.scriptIndex);
-  assertInt(obj.startPos);
-  assertInt(obj.endPos);
-  assertBool(obj.compiled);
+  assertInt(obj.scriptIndex!);
+  assertInt(obj.startPos!);
+  assertInt(obj.endPos!);
+  assertBool(obj.compiled!);
   return obj;
 }
 
@@ -1102,19 +1047,17 @@
 
 vms.Stack assertStack(vms.Stack obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfFrame(obj.frames);
-  assertListOfMessage(obj.messages);
-  assertBool(obj.truncated);
+  assertListOfFrame(obj.frames!);
+  assertListOfMessage(obj.messages!);
+  assertBool(obj.truncated!);
   return obj;
 }
 
 vms.Timeline assertTimeline(vms.Timeline obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertListOfTimelineEvent(obj.traceEvents);
-  assertInt(obj.timeOriginMicros);
-  assertInt(obj.timeExtentMicros);
+  assertListOfTimelineEvent(obj.traceEvents!);
+  assertInt(obj.timeOriginMicros!);
+  assertInt(obj.timeExtentMicros!);
   return obj;
 }
 
@@ -1133,25 +1076,22 @@
 
 vms.TimelineFlags assertTimelineFlags(vms.TimelineFlags obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.recorderName);
-  assertListOfString(obj.availableStreams);
-  assertListOfString(obj.recordedStreams);
+  assertString(obj.recorderName!);
+  assertListOfString(obj.availableStreams!);
+  assertListOfString(obj.recordedStreams!);
   return obj;
 }
 
 vms.Timestamp assertTimestamp(vms.Timestamp obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInt(obj.timestamp);
+  assertInt(obj.timestamp!);
   return obj;
 }
 
 vms.TypeArgumentsRef assertTypeArgumentsRef(vms.TypeArgumentsRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
+  assertString(obj.id!);
+  assertString(obj.name!);
   return obj;
 }
 
@@ -1165,32 +1105,28 @@
 
 vms.TypeArguments assertTypeArguments(vms.TypeArguments obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.id);
-  assertString(obj.name);
-  assertListOfInstanceRef(obj.types);
+  assertString(obj.id!);
+  assertString(obj.name!);
+  assertListOfInstanceRef(obj.types!);
   return obj;
 }
 
 vms.UnresolvedSourceLocation assertUnresolvedSourceLocation(
     vms.UnresolvedSourceLocation obj) {
   assertNotNull(obj);
-  assertString(obj.type);
   return obj;
 }
 
 vms.Version assertVersion(vms.Version obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertInt(obj.major);
-  assertInt(obj.minor);
+  assertInt(obj.major!);
+  assertInt(obj.minor!);
   return obj;
 }
 
 vms.VMRef assertVMRef(vms.VMRef obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.name);
+  assertString(obj.name!);
   return obj;
 }
 
@@ -1203,18 +1139,17 @@
 
 vms.VM assertVM(vms.VM obj) {
   assertNotNull(obj);
-  assertString(obj.type);
-  assertString(obj.name);
-  assertInt(obj.architectureBits);
-  assertString(obj.hostCPU);
-  assertString(obj.operatingSystem);
-  assertString(obj.targetCPU);
-  assertString(obj.version);
-  assertInt(obj.pid);
-  assertInt(obj.startTime);
-  assertListOfIsolateRef(obj.isolates);
-  assertListOfIsolateGroupRef(obj.isolateGroups);
-  assertListOfIsolateRef(obj.systemIsolates);
-  assertListOfIsolateGroupRef(obj.systemIsolateGroups);
+  assertString(obj.name!);
+  assertInt(obj.architectureBits!);
+  assertString(obj.hostCPU!);
+  assertString(obj.operatingSystem!);
+  assertString(obj.targetCPU!);
+  assertString(obj.version!);
+  assertInt(obj.pid!);
+  assertInt(obj.startTime!);
+  assertListOfIsolateRef(obj.isolates!);
+  assertListOfIsolateGroupRef(obj.isolateGroups!);
+  assertListOfIsolateRef(obj.systemIsolates!);
+  assertListOfIsolateGroupRef(obj.systemIsolateGroups!);
   return obj;
 }
diff --git a/pkg/vm_service/example/vm_service_tester.dart b/pkg/vm_service/example/vm_service_tester.dart
index 8038c98..2406111 100644
--- a/pkg/vm_service/example/vm_service_tester.dart
+++ b/pkg/vm_service/example/vm_service_tester.dart
@@ -18,10 +18,10 @@
 final String host = 'localhost';
 final int port = 7575;
 
-VmService serviceClient;
+late VmService serviceClient;
 
 void main() {
-  Process process;
+  Process? process;
 
   tearDown(() {
     process?.kill();
@@ -43,11 +43,11 @@
     print('dart process started');
 
     // ignore: unawaited_futures
-    process.exitCode.then((code) => print('vm exited: ${code}'));
+    process!.exitCode.then((code) => print('vm exited: ${code}'));
     // ignore: strong_mode_down_cast_composite
-    process.stdout.transform(utf8.decoder).listen(print);
+    process!.stdout.transform(utf8.decoder).listen(print);
     // ignore: strong_mode_down_cast_composite
-    process.stderr.transform(utf8.decoder).listen(print);
+    process!.stderr.transform(utf8.decoder).listen(print);
 
     await Future.delayed(Duration(milliseconds: 500));
 
@@ -70,7 +70,7 @@
       // reserialize it back to the same exact representation (minus private
       // fields).
       var json = jsonDecode(str);
-      var originalJson = json['result'] as Map<String, dynamic>;
+      var originalJson = json['result'] as Map<String, dynamic>?;
       if (originalJson == null && json['method'] == 'streamNotify') {
         originalJson = json['params']['event'];
       }
@@ -84,7 +84,7 @@
 
       var reserializedJson = (instance as dynamic).toJson();
 
-      forEachNestedMap(originalJson, (obj) {
+      forEachNestedMap(originalJson!, (obj) {
         // Private fields that we don't reproduce
         obj.removeWhere((k, v) => k.startsWith('_'));
         // Extra fields that aren't specified and we don't reproduce
@@ -112,7 +112,7 @@
     VM vm = await serviceClient.getVM();
     print('hostCPU=${vm.hostCPU}');
     print(await serviceClient.getVersion());
-    List<IsolateRef> isolates = await vm.isolates;
+    List<IsolateRef> isolates = await vm.isolates!;
     print(isolates);
 
     // Disable the json reserialization checks since custom services are not
@@ -121,14 +121,14 @@
     await testServiceRegistration();
     checkResponseJsonCompatibility = true;
 
-    await testScriptParse(vm.isolates.first);
-    await testSourceReport(vm.isolates.first);
+    await testScriptParse(vm.isolates!.first);
+    await testSourceReport(vm.isolates!.first);
 
     IsolateRef isolateRef = isolates.first;
-    print(await serviceClient.resume(isolateRef.id));
+    print(await serviceClient.resume(isolateRef.id!));
 
     print('waiting for client to shut down...');
-    serviceClient.dispose();
+    await serviceClient.dispose();
 
     await serviceClient.onDone;
     print('service client shut down');
@@ -169,48 +169,50 @@
   otherClient.onEvent('Service').listen((e) async {
     if (e.service == serviceName && e.kind == EventKind.kServiceRegistered) {
       assert(e.alias == serviceAlias);
-      Response response = await serviceClient.callMethod(
-        e.method,
+      Response? response = await serviceClient.callMethod(
+        e.method!,
         args: <String, dynamic>{'input': movedValue},
       );
-      assert(response.json['output'] == movedValue);
+      assert(response.json!['output'] == movedValue);
       completer.complete();
     }
   });
   await otherClient.streamListen('Service');
   await completer.future;
-  otherClient.dispose();
+  await otherClient.dispose();
 }
 
 Future testScriptParse(IsolateRef isolateRef) async {
-  final Isolate isolate = await serviceClient.getIsolate(isolateRef.id);
+  final isolateId = isolateRef.id!;
+  final Isolate isolate = await serviceClient.getIsolate(isolateId);
   final Library rootLibrary =
-      await serviceClient.getObject(isolateRef.id, isolate.rootLib.id);
-  final ScriptRef scriptRef = rootLibrary.scripts.first;
+      await serviceClient.getObject(isolateId, isolate.rootLib!.id!) as Library;
+  final ScriptRef scriptRef = rootLibrary.scripts!.first;
 
   final Script script =
-      await serviceClient.getObject(isolateRef.id, scriptRef.id);
+      await serviceClient.getObject(isolateId, scriptRef.id!) as Script;
   print(script);
   print(script.uri);
   print(script.library);
-  print(script.source.length);
-  print(script.tokenPosTable.length);
+  print(script.source!.length);
+  print(script.tokenPosTable!.length);
 }
 
 Future testSourceReport(IsolateRef isolateRef) async {
-  final Isolate isolate = await serviceClient.getIsolate(isolateRef.id);
+  final isolateId = isolateRef.id!;
+  final Isolate isolate = await serviceClient.getIsolate(isolateId);
   final Library rootLibrary =
-      await serviceClient.getObject(isolateRef.id, isolate.rootLib.id);
-  final ScriptRef scriptRef = rootLibrary.scripts.first;
+      await serviceClient.getObject(isolateId, isolate.rootLib!.id!) as Library;
+  final ScriptRef scriptRef = rootLibrary.scripts!.first;
 
   // make sure some code has run
-  await serviceClient.resume(isolateRef.id);
+  await serviceClient.resume(isolateId);
   await Future.delayed(const Duration(milliseconds: 25));
 
   final SourceReport sourceReport = await serviceClient.getSourceReport(
-      isolateRef.id, [SourceReportKind.kCoverage],
+      isolateId, [SourceReportKind.kCoverage],
       scriptId: scriptRef.id);
-  for (SourceReportRange range in sourceReport.ranges) {
+  for (SourceReportRange range in sourceReport.ranges!) {
     print('  $range');
     if (range.coverage != null) {
       print('  ${range.coverage}');
diff --git a/pkg/vm_service/lib/src/dart_io_extensions.dart b/pkg/vm_service/lib/src/dart_io_extensions.dart
index c184d3c..7ab74eb 100644
--- a/pkg/vm_service/lib/src/dart_io_extensions.dart
+++ b/pkg/vm_service/lib/src/dart_io_extensions.dart
@@ -6,7 +6,6 @@
 
 import 'dart:collection';
 
-import 'package:meta/meta.dart';
 import 'package:vm_service/vm_service.dart';
 
 import 'vm_service.dart';
@@ -16,10 +15,12 @@
   static Map<String, Version> _isolateVersion = {};
 
   Future<Version> _version(String isolateId) async {
-    if (_isolateVersion[isolateId] == null) {
-      _isolateVersion[isolateId] = await getDartIOVersion(isolateId);
+    Version? version = _isolateVersion[isolateId];
+    if (version == null) {
+      version = await getDartIOVersion(isolateId);
+      _isolateVersion[isolateId] = version;
     }
-    return _isolateVersion[isolateId];
+    return version;
   }
 
   /// The `getDartIOVersion` RPC returns the available version of the dart:io
@@ -46,7 +47,7 @@
   /// If the state of the socket profiler is changed, a `SocketProfilingStateChange`
   /// event will be sent on the `Extension` stream.
   Future<SocketProfilingState> socketProfilingEnabled(String isolateId,
-      [bool enabled]) async {
+      [bool? enabled]) async {
     return _callHelper('ext.dart.io.socketProfilingEnabled', isolateId, args: {
       if (enabled != null) 'enabled': enabled,
     });
@@ -90,11 +91,11 @@
   /// If the value of `HttpClient.enableTimelineLogging` is changed, a
   /// `HttpTimelineLoggingStateChange` event will be sent on the `Extension` stream.
   Future<HttpTimelineLoggingState> httpEnableTimelineLogging(String isolateId,
-      [bool enabled]) async {
+      [bool? enabled]) async {
     final version = await _version(isolateId);
     // Parameter name changed in version 1.4.
     final enableKey =
-        ((version.major == 1 && version.minor > 3) || version.major >= 2)
+        ((version.major! == 1 && version.minor! > 3) || version.major! >= 2)
             ? 'enabled'
             : 'enable';
     return _callHelper('ext.dart.io.httpEnableTimelineLogging', isolateId,
@@ -139,7 +140,7 @@
         },
       );
 
-  Future<T> _callHelper<T>(String method, String isolateId,
+  Future<T> _callHelper<T>(String method, String? isolateId,
       {Map args = const {}}) {
     if (!_factoriesRegistered) {
       _registerFactories();
@@ -170,7 +171,7 @@
 }
 
 class SocketStatistic {
-  static SocketStatistic parse(Map json) =>
+  static SocketStatistic? parse(Map<String, dynamic>? json) =>
       json == null ? null : SocketStatistic._fromJson(json);
 
   /// The unique ID associated with this socket.
@@ -219,43 +220,54 @@
 
 /// A [SocketProfile] provides information about statistics of sockets.
 class SocketProfile extends Response {
-  static SocketProfile parse(Map json) =>
+  static SocketProfile? parse(Map<String, dynamic>? json) =>
       json == null ? null : SocketProfile._fromJson(json);
 
-  /// List of socket statistics.
-  List<SocketStatistic> sockets;
+  @override
+  String get type => 'SocketProfile';
 
-  SocketProfile({@required this.sockets});
+  /// List of socket statistics.
+  late final List<SocketStatistic> sockets;
+
+  SocketProfile({required this.sockets});
 
   SocketProfile._fromJson(Map<String, dynamic> json) {
     // TODO(bkonyi): make this part of the vm_service.dart library so we can
     // call super._fromJson.
-    type = json['type'];
     sockets = List<SocketStatistic>.from(
-        createServiceObject(json['sockets'], const ['SocketStatistic']) ?? []);
+        createServiceObject(json['sockets'], const ['SocketStatistic'])
+                as List? ??
+            []);
   }
 }
 
 /// A [Response] containing the enabled state of a service extension.
 abstract class _State extends Response {
-  _State({@required this.enabled});
+  _State({required this.enabled}) : _type = 'State';
 
   // TODO(bkonyi): make this part of the vm_service.dart library so we can
   // call super._fromJson.
-  _State._fromJson(Map<String, dynamic> json) : enabled = json['enabled'] {
-    type = json['type'];
-  }
+  _State._fromJson(Map<String, dynamic> json)
+      : enabled = json['enabled'],
+        _type = json['type'];
+
+  @override
+  String get type => _type;
 
   final bool enabled;
+  final String _type;
 }
 
 /// A [HttpTimelineLoggingState] provides information about the current state of HTTP
 /// request logging for a given isolate.
 class HttpTimelineLoggingState extends _State {
-  static HttpTimelineLoggingState parse(Map json) =>
+  static HttpTimelineLoggingState? parse(Map<String, dynamic>? json) =>
       json == null ? null : HttpTimelineLoggingState._fromJson(json);
 
-  HttpTimelineLoggingState({@required bool enabled}) : super(enabled: enabled);
+  @override
+  String get type => 'HttpTimelineLoggingState';
+
+  HttpTimelineLoggingState({required bool enabled}) : super(enabled: enabled);
 
   HttpTimelineLoggingState._fromJson(Map<String, dynamic> json)
       : super._fromJson(json);
@@ -264,10 +276,10 @@
 /// A [SocketProfilingState] provides information about the current state of
 /// socket profiling for a given isolate.
 class SocketProfilingState extends _State {
-  static SocketProfilingState parse(Map json) =>
+  static SocketProfilingState? parse(Map<String, dynamic>? json) =>
       json == null ? null : SocketProfilingState._fromJson(json);
 
-  SocketProfilingState({@required bool enabled}) : super(enabled: enabled);
+  SocketProfilingState({required bool enabled}) : super(enabled: enabled);
 
   SocketProfilingState._fromJson(Map<String, dynamic> json)
       : super._fromJson(json);
@@ -275,12 +287,12 @@
 
 /// A [SpawnedProcessRef] contains identifying information about a spawned process.
 class SpawnedProcessRef {
-  static SpawnedProcessRef parse(Map json) =>
+  static SpawnedProcessRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : SpawnedProcessRef._fromJson(json);
 
   SpawnedProcessRef({
-    @required this.id,
-    @required this.name,
+    required this.id,
+    required this.name,
   });
 
   SpawnedProcessRef._fromJson(Map<String, dynamic> json)
@@ -301,16 +313,16 @@
 
 /// A [SpawnedProcess] contains startup information of a spawned process.
 class SpawnedProcess extends Response implements SpawnedProcessRef {
-  static SpawnedProcess parse(Map json) =>
+  static SpawnedProcess? parse(Map<String, dynamic>? json) =>
       json == null ? null : SpawnedProcess._fromJson(json);
 
   SpawnedProcess({
-    @required this.id,
-    @required this.name,
-    @required this.pid,
-    @required this.startedAt,
-    @required List<String> arguments,
-    @required this.workingDirectory,
+    required this.id,
+    required this.name,
+    required this.pid,
+    required this.startedAt,
+    required List<String> arguments,
+    required this.workingDirectory,
   }) : _arguments = arguments;
 
   SpawnedProcess._fromJson(Map<String, dynamic> json)
@@ -322,11 +334,11 @@
         pid = json['pid'],
         startedAt = json['startedAt'],
         _arguments = List<String>.from(
-            createServiceObject(json['arguments'], const ['String']) as List ??
-                []),
-        workingDirectory = json['workingDirectory'] {
-    type = json['type'];
-  }
+            createServiceObject(json['arguments'], const ['String']) as List),
+        workingDirectory = json['workingDirectory'];
+
+  @override
+  String get type => 'SpawnedProcess';
 
   /// The unique ID associated with this process.
   final int id;
@@ -349,10 +361,10 @@
 }
 
 class SpawnedProcessList extends Response {
-  static SpawnedProcessList parse(Map json) =>
+  static SpawnedProcessList? parse(Map<String, dynamic>? json) =>
       json == null ? null : SpawnedProcessList._fromJson(json);
 
-  SpawnedProcessList({@required List<SpawnedProcessRef> processes})
+  SpawnedProcessList({required List<SpawnedProcessRef> processes})
       : _processes = processes;
 
   SpawnedProcessList._fromJson(Map<String, dynamic> json)
@@ -361,10 +373,10 @@
         // call super._fromJson.
         _processes = List<SpawnedProcessRef>.from(
             createServiceObject(json['processes'], const ['SpawnedProcessRef'])
-                    as List ??
-                []) {
-    type = json['type'];
-  }
+                as List);
+
+  @override
+  String get type => 'SpawnedProcessList';
 
   /// A list of processes spawned through dart:io on a given isolate.
   List<SpawnedProcessRef> get processes => UnmodifiableListView(_processes);
@@ -373,12 +385,12 @@
 
 /// A [OpenFileRef] contains identifying information about a currently opened file.
 class OpenFileRef {
-  static OpenFileRef parse(Map json) =>
+  static OpenFileRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : OpenFileRef._fromJson(json);
 
   OpenFileRef({
-    @required this.id,
-    @required this.name,
+    required this.id,
+    required this.name,
   });
 
   OpenFileRef._fromJson(Map<String, dynamic> json)
@@ -399,18 +411,18 @@
 
 /// A [File] contains information about reads and writes to a currently opened file.
 class OpenFile extends Response implements OpenFileRef {
-  static OpenFile parse(Map json) =>
+  static OpenFile? parse(Map<String, dynamic>? json) =>
       json == null ? null : OpenFile._fromJson(json);
 
   OpenFile({
-    @required this.id,
-    @required this.name,
-    @required this.readBytes,
-    @required this.writeBytes,
-    @required this.readCount,
-    @required this.writeCount,
-    @required this.lastReadTime,
-    @required this.lastWriteTime,
+    required this.id,
+    required this.name,
+    required this.readBytes,
+    required this.writeBytes,
+    required this.readCount,
+    required this.writeCount,
+    required this.lastReadTime,
+    required this.lastWriteTime,
   });
 
   OpenFile._fromJson(Map<String, dynamic> json)
@@ -426,9 +438,10 @@
         lastReadTime =
             DateTime.fromMillisecondsSinceEpoch(json['lastReadTime']),
         lastWriteTime =
-            DateTime.fromMillisecondsSinceEpoch(json['lastWriteTime']) {
-    type = json['type'];
-  }
+            DateTime.fromMillisecondsSinceEpoch(json['lastWriteTime']);
+
+  @override
+  String get type => 'OpenFile';
 
   /// The unique ID associated with this file.
   final int id;
@@ -456,20 +469,20 @@
 }
 
 class OpenFileList extends Response {
-  static OpenFileList parse(Map json) =>
+  static OpenFileList? parse(Map<String, dynamic>? json) =>
       json == null ? null : OpenFileList._fromJson(json);
 
-  OpenFileList({@required List<OpenFileRef> files}) : _files = files;
+  OpenFileList({required List<OpenFileRef> files}) : _files = files;
 
   OpenFileList._fromJson(Map<String, dynamic> json)
       :
         // TODO(bkonyi): make this part of the vm_service.dart library so we can
         // call super._fromJson.
         _files = List<OpenFileRef>.from(
-            createServiceObject(json['files'], const ['OpenFileRef']) as List ??
-                []) {
-    type = json['type'];
-  }
+            createServiceObject(json['files'], const ['OpenFileRef']) as List);
+
+  @override
+  String get type => 'OpenFileList';
 
   /// A list of all files opened through dart:io on a given isolate.
   List<OpenFileRef> get files => UnmodifiableListView(_files);
diff --git a/pkg/vm_service/lib/src/helpers.dart b/pkg/vm_service/lib/src/helpers.dart
index 0d14c16..a92c70b 100644
--- a/pkg/vm_service/lib/src/helpers.dart
+++ b/pkg/vm_service/lib/src/helpers.dart
@@ -6,7 +6,7 @@
 
 class IsolateHelper {
   static List<TagCounter> getTagCounters(Isolate isolate) {
-    Map m = isolate.json['_tagCounters'];
+    Map m = isolate.json!['_tagCounters']!;
     List<String> names = m['names'];
     List<int> counters = m['counters'];
 
diff --git a/pkg/vm_service/lib/src/service_extension_registry.dart b/pkg/vm_service/lib/src/service_extension_registry.dart
index 9ec1514..6de71cd 100644
--- a/pkg/vm_service/lib/src/service_extension_registry.dart
+++ b/pkg/vm_service/lib/src/service_extension_registry.dart
@@ -44,7 +44,7 @@
   ///
   /// The result of this function should not be stored, because clients may
   /// shut down at any time.
-  VmServerConnection clientFor(String extension) =>
+  VmServerConnection? clientFor(String extension) =>
       _extensionToConnection[extension];
 
   /// All of the currently registered extensions
diff --git a/pkg/vm_service/lib/src/snapshot_graph.dart b/pkg/vm_service/lib/src/snapshot_graph.dart
index bad549e..7e93eed 100644
--- a/pkg/vm_service/lib/src/snapshot_graph.dart
+++ b/pkg/vm_service/lib/src/snapshot_graph.dart
@@ -100,8 +100,8 @@
   /// The name of the field.
   String get name => _name;
 
-  int _index;
-  String _name;
+  int _index = -1;
+  String _name = '';
 
   HeapSnapshotField._read(_ReadStream reader) {
     // flags (reserved)
@@ -129,10 +129,10 @@
   /// The list of fields in the class.
   List<HeapSnapshotField> get fields => _fields;
 
-  String _name;
-  String _libraryName;
-  Uri _libraryUri;
-  List<HeapSnapshotField> _fields = <HeapSnapshotField>[];
+  String _name = '';
+  String _libraryName = '';
+  late final Uri _libraryUri;
+  final List<HeapSnapshotField> _fields = <HeapSnapshotField>[];
 
   HeapSnapshotClass._read(_ReadStream reader) {
     // flags (reserved).
@@ -170,10 +170,10 @@
   /// A list of 1-origin indicies into [HeapSnapshotGraph.objects].
   List<int> get references => _references;
 
-  int _classId;
-  int _shallowSize;
-  dynamic _data;
-  List<int> _references = <int>[];
+  int _classId = -1;
+  int _shallowSize = -1;
+  late final dynamic _data;
+  final List<int> _references = <int>[];
 
   HeapSnapshotObject._read(_ReadStream reader) {
     _classId = reader.readUnsigned();
@@ -238,15 +238,15 @@
   List<HeapSnapshotExternalProperty> get externalProperties =>
       _externalProperties;
 
-  String _name;
-  int _flags;
-  int _shallowSize;
-  int _capacity;
-  int _externalSize;
-  List<HeapSnapshotClass> _classes = <HeapSnapshotClass>[];
-  int _referenceCount;
-  List<HeapSnapshotObject> _objects = <HeapSnapshotObject>[];
-  List<HeapSnapshotExternalProperty> _externalProperties =
+  String _name = '';
+  int _flags = -1;
+  int _shallowSize = -1;
+  int _capacity = -1;
+  int _externalSize = -1;
+  final List<HeapSnapshotClass> _classes = <HeapSnapshotClass>[];
+  int _referenceCount = -1;
+  final List<HeapSnapshotObject> _objects = <HeapSnapshotObject>[];
+  final List<HeapSnapshotExternalProperty> _externalProperties =
       <HeapSnapshotExternalProperty>[];
 
   /// Requests a heap snapshot for a given isolate and builds a
@@ -260,17 +260,17 @@
 
     final completer = Completer<HeapSnapshotGraph>();
     final chunks = <ByteData>[];
-    StreamSubscription streamSubscription;
+    late StreamSubscription streamSubscription;
     streamSubscription = service.onHeapSnapshotEvent.listen((e) async {
-      chunks.add(e.data);
-      if (e.last) {
+      chunks.add(e.data!);
+      if (e.last!) {
         await service.streamCancel(EventStreams.kHeapSnapshot);
         await streamSubscription.cancel();
         completer.complete(HeapSnapshotGraph.fromChunks(chunks));
       }
     });
 
-    await service.requestHeapSnapshot(isolate.id);
+    await service.requestHeapSnapshot(isolate.id!);
     return completer.future;
   }
 
diff --git a/pkg/vm_service/lib/src/stream_helpers.dart b/pkg/vm_service/lib/src/stream_helpers.dart
index 474c417..b7b5515 100644
--- a/pkg/vm_service/lib/src/stream_helpers.dart
+++ b/pkg/vm_service/lib/src/stream_helpers.dart
@@ -35,12 +35,12 @@
         ? _next.asBroadcastStream()
         : _next;
 
-    StreamSubscription<T> subscription;
+    StreamSubscription<T>? subscription;
     var currentStream = first;
     var firstDone = false;
     var secondDone = false;
 
-    Function currentDoneHandler;
+    late Function currentDoneHandler;
 
     listen() {
       subscription = currentStream.listen(controller.add,
@@ -64,21 +64,22 @@
     controller.onListen = () {
       assert(subscription == null);
       listen();
+      final sub = subscription!;
       if (!first.isBroadcast) {
         controller
           ..onPause = () {
-            if (!firstDone || !next.isBroadcast) return subscription.pause();
-            subscription.cancel();
+            if (!firstDone || !next.isBroadcast) return sub.pause();
+            sub.cancel();
             subscription = null;
           }
           ..onResume = () {
-            if (!firstDone || !next.isBroadcast) return subscription.resume();
+            if (!firstDone || !next.isBroadcast) return sub.resume();
             listen();
           };
       }
       controller.onCancel = () {
         if (secondDone) return null;
-        var toCancel = subscription;
+        var toCancel = subscription!;
         subscription = null;
         return toCancel.cancel();
       };
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 6bb049a..d7d9d48 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -12,8 +12,6 @@
 import 'dart:convert' show base64, jsonDecode, jsonEncode, utf8;
 import 'dart:typed_data';
 
-import 'package:meta/meta.dart';
-
 import 'service_extension_registry.dart';
 
 export 'service_extension_registry.dart' show ServiceExtensionRegistry;
@@ -41,13 +39,13 @@
 bool _isNullInstance(Map json) =>
     ((json['type'] == '@Instance') && (json['kind'] == 'Null'));
 
-Object createServiceObject(dynamic json, List<String> expectedTypes) {
+Object? createServiceObject(dynamic json, List<String> expectedTypes) {
   if (json == null) return null;
 
   if (json is List) {
     return json.map((e) => createServiceObject(e, expectedTypes)).toList();
   } else if (json is Map) {
-    String type = json['type'];
+    String? type = json['type'];
 
     // Not a Response type.
     if (type == null) {
@@ -62,10 +60,11 @@
       // be returned.
       return null;
     }
-    if (_typeFactories[type] == null) {
+    final typeFactory = _typeFactories[type];
+    if (typeFactory == null) {
       return null;
     } else {
-      return _typeFactories[type](json);
+      return typeFactory(json);
     }
   } else {
     // Handle simple types.
@@ -89,7 +88,7 @@
   }
 }
 
-void _setIfNotNull(Map<String, Object> json, String key, Object value) {
+void _setIfNotNull(Map<String, dynamic> json, String key, Object? value) {
   if (value == null) return;
   json[key] = value;
 }
@@ -250,7 +249,7 @@
 
   /// Handler for calling extra service extensions.
   Future<Response> callServiceExtension(String method,
-      {String isolateId, Map args});
+      {String? isolateId, Map<String, dynamic>? args});
 
   /// The `addBreakpoint` RPC is used to add a breakpoint at a specific line of
   /// some script.
@@ -284,7 +283,7 @@
     String isolateId,
     String scriptId,
     int line, {
-    int column,
+    int? column,
   });
 
   /// The `addBreakpoint` RPC is used to add a breakpoint at a specific line of
@@ -321,7 +320,7 @@
     String isolateId,
     String scriptUri,
     int line, {
-    int column,
+    int? column,
   });
 
   /// The `addBreakpointAtEntry` RPC is used to add a breakpoint at the
@@ -398,7 +397,7 @@
     String targetId,
     String selector,
     List<String> argumentIds, {
-    bool disableBreakpoints,
+    bool? disableBreakpoints,
   });
 
   /// The `evaluate` RPC is used to evaluate an expression in the context of
@@ -443,8 +442,8 @@
     String isolateId,
     String targetId,
     String expression, {
-    Map<String, String> scope,
-    bool disableBreakpoints,
+    Map<String, String>? scope,
+    bool? disableBreakpoints,
   });
 
   /// The `evaluateInFrame` RPC is used to evaluate an expression in the context
@@ -481,8 +480,8 @@
     String isolateId,
     int frameIndex,
     String expression, {
-    Map<String, String> scope,
-    bool disableBreakpoints,
+    Map<String, String>? scope,
+    bool? disableBreakpoints,
   });
 
   /// The `getAllocationProfile` RPC is used to retrieve allocation information
@@ -501,7 +500,7 @@
   /// This method will throw a [SentinelException] in the case a [Sentinel] is
   /// returned.
   Future<AllocationProfile> getAllocationProfile(String isolateId,
-      {bool reset, bool gc});
+      {bool? reset, bool? gc});
 
   /// The `getClassList` RPC is used to retrieve a `ClassList` containing all
   /// classes for an isolate based on the isolate's `isolateId`.
@@ -686,8 +685,8 @@
   Future<Obj> getObject(
     String isolateId,
     String objectId, {
-    int offset,
-    int count,
+    int? offset,
+    int? count,
   });
 
   /// The `getPorts` RPC is used to retrieve the list of `ReceivePort` instances
@@ -746,7 +745,7 @@
   ///
   /// This method will throw a [SentinelException] in the case a [Sentinel] is
   /// returned.
-  Future<Stack> getStack(String isolateId, {int limit});
+  Future<Stack> getStack(String isolateId, {int? limit});
 
   /// The `getSupportedProtocols` RPC is used to determine which protocols are
   /// supported by the current server.
@@ -801,10 +800,10 @@
     String isolateId,
     /*List<SourceReportKind>*/
     List<String> reports, {
-    String scriptId,
-    int tokenPos,
-    int endTokenPos,
-    bool forceCompile,
+    String? scriptId,
+    int? tokenPos,
+    int? endTokenPos,
+    bool? forceCompile,
   });
 
   /// The `getVersion` RPC is used to determine what version of the Service
@@ -838,7 +837,8 @@
   /// or Macos or Systrace, an [RPC error] with error code `114`, `invalid
   /// timeline request`, will be returned as timeline events are handled by the
   /// OS in these modes.
-  Future<Timeline> getVMTimeline({int timeOriginMicros, int timeExtentMicros});
+  Future<Timeline> getVMTimeline(
+      {int? timeOriginMicros, int? timeExtentMicros});
 
   /// The `getVMTimelineFlags` RPC returns information about the current VM
   /// timeline configuration.
@@ -917,10 +917,10 @@
   /// returned.
   Future<ReloadReport> reloadSources(
     String isolateId, {
-    bool force,
-    bool pause,
-    String rootLibUri,
-    String packagesUri,
+    bool? force,
+    bool? pause,
+    String? rootLibUri,
+    String? packagesUri,
   });
 
   /// The `removeBreakpoint` RPC is used to remove a breakpoint by its `id`.
@@ -981,7 +981,7 @@
   /// This method will throw a [SentinelException] in the case a [Sentinel] is
   /// returned.
   Future<Success> resume(String isolateId,
-      {/*StepOption*/ String step, int frameIndex});
+      {/*StepOption*/ String? step, int? frameIndex});
 
   /// The `setExceptionPauseMode` RPC is used to control if an isolate pauses
   /// when an exception is thrown.
@@ -1120,14 +1120,14 @@
 }
 
 class _PendingServiceRequest {
-  Future<Map<String, Object>> get future => _completer.future;
-  final _completer = Completer<Map<String, Object>>();
+  Future<Map<String, Object?>> get future => _completer.future;
+  final _completer = Completer<Map<String, Object?>>();
 
   final dynamic originalId;
 
   _PendingServiceRequest(this.originalId);
 
-  void complete(Map<String, Object> response) {
+  void complete(Map<String, Object?> response) {
     response['id'] = originalId;
     _completer.complete(response);
   }
@@ -1141,7 +1141,7 @@
 /// instances.
 class VmServerConnection {
   final Stream<Map<String, Object>> _requestStream;
-  final StreamSink<Map<String, Object>> _responseSink;
+  final StreamSink<Map<String, Object?>> _responseSink;
   final ServiceExtensionRegistry _serviceExtensionRegistry;
   final VmServiceInterface _serviceImplementation;
 
@@ -1152,8 +1152,8 @@
   final _streamSubscriptions = <String, StreamSubscription>{};
 
   /// Completes when [_requestStream] is done.
-  Future get done => _doneCompleter.future;
-  final _doneCompleter = Completer<Null>();
+  Future<void> get done => _doneCompleter.future;
+  final _doneCompleter = Completer<void>();
 
   /// Pending service extension requests to this client by id.
   final _pendingServiceExtensionRequests = <dynamic, _PendingServiceRequest>{};
@@ -1170,13 +1170,13 @@
   ///
   /// We don't attempt to do any serialization or deserialization of the
   /// request or response in this case
-  Future<Map<String, Object>> _forwardServiceExtensionRequest(
-      Map<String, Object> request) {
-    var originalId = request['id'];
-    request = Map.of(request);
+  Future<Map<String, Object?>> _forwardServiceExtensionRequest(
+      Map<String, Object?> request) {
+    final originalId = request['id'];
+    request = Map<String, Object?>.of(request);
     // Modify the request ID to ensure we don't have conflicts between
     // multiple clients ids.
-    var newId = '${_nextServiceRequestId++}:$originalId';
+    final newId = '${_nextServiceRequestId++}:$originalId';
     request['id'] = newId;
     var pendingRequest = _PendingServiceRequest(originalId);
     _pendingServiceExtensionRequests[newId] = pendingRequest;
@@ -1184,31 +1184,31 @@
     return pendingRequest.future;
   }
 
-  void _delegateRequest(Map<String, Object> request) async {
+  void _delegateRequest(Map<String, Object?> request) async {
     try {
       var id = request['id'];
       // Check if this is actually a response to a pending request.
       if (_pendingServiceExtensionRequests.containsKey(id)) {
-        final pending = _pendingServiceExtensionRequests[id];
-        pending.complete(Map.of(request));
+        final pending = _pendingServiceExtensionRequests[id]!;
+        pending.complete(Map<String, Object?>.of(request));
         return;
       }
-      var method = request['method'] as String;
+      final method = request['method'] as String?;
       if (method == null) {
         throw RPCError(
             null, RPCError.kInvalidRequest, 'Invalid Request', request);
       }
-      var params = request['params'] as Map;
-      Response response;
+      final params = request['params'] as Map<String, dynamic>?;
+      late Response response;
 
       switch (method) {
         case 'registerService':
-          _serviceExtensionRegistry.registerExtension(params['service'], this);
+          _serviceExtensionRegistry.registerExtension(params!['service'], this);
           response = Success();
           break;
         case 'addBreakpoint':
           response = await _serviceImplementation.addBreakpoint(
-            params['isolateId'],
+            params!['isolateId'],
             params['scriptId'],
             params['line'],
             column: params['column'],
@@ -1216,7 +1216,7 @@
           break;
         case 'addBreakpointWithScriptUri':
           response = await _serviceImplementation.addBreakpointWithScriptUri(
-            params['isolateId'],
+            params!['isolateId'],
             params['scriptUri'],
             params['line'],
             column: params['column'],
@@ -1224,13 +1224,13 @@
           break;
         case 'addBreakpointAtEntry':
           response = await _serviceImplementation.addBreakpointAtEntry(
-            params['isolateId'],
+            params!['isolateId'],
             params['functionId'],
           );
           break;
         case 'clearCpuSamples':
           response = await _serviceImplementation.clearCpuSamples(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'clearVMTimeline':
@@ -1238,7 +1238,7 @@
           break;
         case 'invoke':
           response = await _serviceImplementation.invoke(
-            params['isolateId'],
+            params!['isolateId'],
             params['targetId'],
             params['selector'],
             List<String>.from(params['argumentIds'] ?? []),
@@ -1247,7 +1247,7 @@
           break;
         case 'evaluate':
           response = await _serviceImplementation.evaluate(
-            params['isolateId'],
+            params!['isolateId'],
             params['targetId'],
             params['expression'],
             scope: params['scope']?.cast<String, String>(),
@@ -1256,7 +1256,7 @@
           break;
         case 'evaluateInFrame':
           response = await _serviceImplementation.evaluateInFrame(
-            params['isolateId'],
+            params!['isolateId'],
             params['frameIndex'],
             params['expression'],
             scope: params['scope']?.cast<String, String>(),
@@ -1265,19 +1265,19 @@
           break;
         case 'getAllocationProfile':
           response = await _serviceImplementation.getAllocationProfile(
-            params['isolateId'],
+            params!['isolateId'],
             reset: params['reset'],
             gc: params['gc'],
           );
           break;
         case 'getClassList':
           response = await _serviceImplementation.getClassList(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'getCpuSamples':
           response = await _serviceImplementation.getCpuSamples(
-            params['isolateId'],
+            params!['isolateId'],
             params['timeOriginMicros'],
             params['timeExtentMicros'],
           );
@@ -1287,46 +1287,46 @@
           break;
         case 'getInboundReferences':
           response = await _serviceImplementation.getInboundReferences(
-            params['isolateId'],
+            params!['isolateId'],
             params['targetId'],
             params['limit'],
           );
           break;
         case 'getInstances':
           response = await _serviceImplementation.getInstances(
-            params['isolateId'],
+            params!['isolateId'],
             params['objectId'],
             params['limit'],
           );
           break;
         case 'getIsolate':
           response = await _serviceImplementation.getIsolate(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'getIsolateGroup':
           response = await _serviceImplementation.getIsolateGroup(
-            params['isolateGroupId'],
+            params!['isolateGroupId'],
           );
           break;
         case 'getMemoryUsage':
           response = await _serviceImplementation.getMemoryUsage(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'getIsolateGroupMemoryUsage':
           response = await _serviceImplementation.getIsolateGroupMemoryUsage(
-            params['isolateGroupId'],
+            params!['isolateGroupId'],
           );
           break;
         case 'getScripts':
           response = await _serviceImplementation.getScripts(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'getObject':
           response = await _serviceImplementation.getObject(
-            params['isolateId'],
+            params!['isolateId'],
             params['objectId'],
             offset: params['offset'],
             count: params['count'],
@@ -1334,12 +1334,12 @@
           break;
         case 'getPorts':
           response = await _serviceImplementation.getPorts(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'getRetainingPath':
           response = await _serviceImplementation.getRetainingPath(
-            params['isolateId'],
+            params!['isolateId'],
             params['targetId'],
             params['limit'],
           );
@@ -1349,7 +1349,7 @@
           break;
         case 'getStack':
           response = await _serviceImplementation.getStack(
-            params['isolateId'],
+            params!['isolateId'],
             limit: params['limit'],
           );
           break;
@@ -1358,7 +1358,7 @@
           break;
         case 'getSourceReport':
           response = await _serviceImplementation.getSourceReport(
-            params['isolateId'],
+            params!['isolateId'],
             List<String>.from(params['reports'] ?? []),
             scriptId: params['scriptId'],
             tokenPos: params['tokenPos'],
@@ -1374,7 +1374,7 @@
           break;
         case 'getVMTimeline':
           response = await _serviceImplementation.getVMTimeline(
-            timeOriginMicros: params['timeOriginMicros'],
+            timeOriginMicros: params!['timeOriginMicros'],
             timeExtentMicros: params['timeExtentMicros'],
           );
           break;
@@ -1386,17 +1386,17 @@
           break;
         case 'pause':
           response = await _serviceImplementation.pause(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'kill':
           response = await _serviceImplementation.kill(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'reloadSources':
           response = await _serviceImplementation.reloadSources(
-            params['isolateId'],
+            params!['isolateId'],
             force: params['force'],
             pause: params['pause'],
             rootLibUri: params['rootLibUri'],
@@ -1405,59 +1405,59 @@
           break;
         case 'removeBreakpoint':
           response = await _serviceImplementation.removeBreakpoint(
-            params['isolateId'],
+            params!['isolateId'],
             params['breakpointId'],
           );
           break;
         case 'requestHeapSnapshot':
           response = await _serviceImplementation.requestHeapSnapshot(
-            params['isolateId'],
+            params!['isolateId'],
           );
           break;
         case 'resume':
           response = await _serviceImplementation.resume(
-            params['isolateId'],
+            params!['isolateId'],
             step: params['step'],
             frameIndex: params['frameIndex'],
           );
           break;
         case 'setExceptionPauseMode':
           response = await _serviceImplementation.setExceptionPauseMode(
-            params['isolateId'],
+            params!['isolateId'],
             params['mode'],
           );
           break;
         case 'setFlag':
           response = await _serviceImplementation.setFlag(
-            params['name'],
+            params!['name'],
             params['value'],
           );
           break;
         case 'setLibraryDebuggable':
           response = await _serviceImplementation.setLibraryDebuggable(
-            params['isolateId'],
+            params!['isolateId'],
             params['libraryId'],
             params['isDebuggable'],
           );
           break;
         case 'setName':
           response = await _serviceImplementation.setName(
-            params['isolateId'],
+            params!['isolateId'],
             params['name'],
           );
           break;
         case 'setVMName':
           response = await _serviceImplementation.setVMName(
-            params['name'],
+            params!['name'],
           );
           break;
         case 'setVMTimelineFlags':
           response = await _serviceImplementation.setVMTimelineFlags(
-            List<String>.from(params['recordedStreams'] ?? []),
+            List<String>.from(params!['recordedStreams'] ?? []),
           );
           break;
         case 'streamCancel':
-          var id = params['streamId'];
+          var id = params!['streamId'];
           var existing = _streamSubscriptions.remove(id);
           if (existing == null) {
             throw RPCError.withDetails(
@@ -1471,7 +1471,7 @@
           response = Success();
           break;
         case 'streamListen':
-          var id = params['streamId'];
+          var id = params!['streamId'];
           if (_streamSubscriptions.containsKey(id)) {
             throw RPCError.withDetails(
               'streamListen',
@@ -1497,7 +1497,7 @@
           response = Success();
           break;
         default:
-          var registeredClient = _serviceExtensionRegistry.clientFor(method);
+          final registeredClient = _serviceExtensionRegistry.clientFor(method);
           if (registeredClient != null) {
             // Check for any client which has registered this extension, if we
             // have one then delegate the request to that client.
@@ -1509,8 +1509,9 @@
           } else if (method.startsWith('ext.')) {
             // Remaining methods with `ext.` are assumed to be registered via
             // dart:developer, which the service implementation handles.
-            var args = params == null ? null : Map.of(params);
-            var isolateId = args?.remove('isolateId');
+            final args =
+                params == null ? null : Map<String, dynamic>.of(params);
+            final isolateId = args?.remove('isolateId');
             response = await _serviceImplementation.callServiceExtension(method,
                 isolateId: isolateId, args: args);
           } else {
@@ -1518,16 +1519,13 @@
                 method, RPCError.kMethodNotFound, 'Method not found', request);
           }
       }
-      if (response == null) {
-        throw StateError('Invalid null response from service');
-      }
       _responseSink.add({
         'jsonrpc': '2.0',
         'id': id,
         'result': response.toJson(),
       });
     } catch (e, st) {
-      var error = e is RPCError
+      final error = e is RPCError
           ? e.toMap()
           : {
               'code': RPCError.kInternalError,
@@ -1544,13 +1542,13 @@
 }
 
 class VmService implements VmServiceInterface {
-  StreamSubscription _streamSub;
-  Function _writeMessage;
+  late final StreamSubscription _streamSub;
+  late final Function _writeMessage;
   int _id = 0;
   Map<String, Completer> _completers = {};
   Map<String, String> _methodCalls = {};
   Map<String, ServiceCallback> _services = {};
-  Log _log;
+  late final Log _log;
 
   StreamController<String> _onSend = StreamController.broadcast(sync: true);
   StreamController<String> _onReceive = StreamController.broadcast(sync: true);
@@ -1560,7 +1558,7 @@
   Map<String, StreamController<Event>> _eventControllers = {};
 
   StreamController<Event> _getEventController(String eventName) {
-    StreamController<Event> controller = _eventControllers[eventName];
+    StreamController<Event>? controller = _eventControllers[eventName];
     if (controller == null) {
       controller = StreamController.broadcast();
       _eventControllers[eventName] = controller;
@@ -1568,14 +1566,14 @@
     return controller;
   }
 
-  DisposeHandler _disposeHandler;
+  late final DisposeHandler? _disposeHandler;
 
   VmService(
     Stream<dynamic> /*String|List<int>*/ inStream,
     void writeMessage(String message), {
-    Log log,
-    DisposeHandler disposeHandler,
-    Future streamClosed,
+    Log? log,
+    DisposeHandler? disposeHandler,
+    Future? streamClosed,
   }) {
     _streamSub = inStream.listen(_processMessage,
         onDone: () => _onDoneCompleter.complete());
@@ -1632,7 +1630,7 @@
     String isolateId,
     String scriptId,
     int line, {
-    int column,
+    int? column,
   }) =>
       _call('addBreakpoint', {
         'isolateId': isolateId,
@@ -1646,7 +1644,7 @@
     String isolateId,
     String scriptUri,
     int line, {
-    int column,
+    int? column,
   }) =>
       _call('addBreakpointWithScriptUri', {
         'isolateId': isolateId,
@@ -1674,7 +1672,7 @@
     String targetId,
     String selector,
     List<String> argumentIds, {
-    bool disableBreakpoints,
+    bool? disableBreakpoints,
   }) =>
       _call('invoke', {
         'isolateId': isolateId,
@@ -1690,8 +1688,8 @@
     String isolateId,
     String targetId,
     String expression, {
-    Map<String, String> scope,
-    bool disableBreakpoints,
+    Map<String, String>? scope,
+    bool? disableBreakpoints,
   }) =>
       _call('evaluate', {
         'isolateId': isolateId,
@@ -1707,8 +1705,8 @@
     String isolateId,
     int frameIndex,
     String expression, {
-    Map<String, String> scope,
-    bool disableBreakpoints,
+    Map<String, String>? scope,
+    bool? disableBreakpoints,
   }) =>
       _call('evaluateInFrame', {
         'isolateId': isolateId,
@@ -1721,7 +1719,7 @@
 
   @override
   Future<AllocationProfile> getAllocationProfile(String isolateId,
-          {bool reset, bool gc}) =>
+          {bool? reset, bool? gc}) =>
       _call('getAllocationProfile', {
         'isolateId': isolateId,
         if (reset != null && reset) 'reset': reset,
@@ -1780,8 +1778,8 @@
   Future<Obj> getObject(
     String isolateId,
     String objectId, {
-    int offset,
-    int count,
+    int? offset,
+    int? count,
   }) =>
       _call('getObject', {
         'isolateId': isolateId,
@@ -1805,7 +1803,7 @@
       _call('getProcessMemoryUsage');
 
   @override
-  Future<Stack> getStack(String isolateId, {int limit}) => _call('getStack', {
+  Future<Stack> getStack(String isolateId, {int? limit}) => _call('getStack', {
         'isolateId': isolateId,
         if (limit != null) 'limit': limit,
       });
@@ -1819,10 +1817,10 @@
     String isolateId,
     /*List<SourceReportKind>*/
     List<String> reports, {
-    String scriptId,
-    int tokenPos,
-    int endTokenPos,
-    bool forceCompile,
+    String? scriptId,
+    int? tokenPos,
+    int? endTokenPos,
+    bool? forceCompile,
   }) =>
       _call('getSourceReport', {
         'isolateId': isolateId,
@@ -1841,7 +1839,7 @@
 
   @override
   Future<Timeline> getVMTimeline(
-          {int timeOriginMicros, int timeExtentMicros}) =>
+          {int? timeOriginMicros, int? timeExtentMicros}) =>
       _call('getVMTimeline', {
         if (timeOriginMicros != null) 'timeOriginMicros': timeOriginMicros,
         if (timeExtentMicros != null) 'timeExtentMicros': timeExtentMicros,
@@ -1868,10 +1866,10 @@
   @override
   Future<ReloadReport> reloadSources(
     String isolateId, {
-    bool force,
-    bool pause,
-    String rootLibUri,
-    String packagesUri,
+    bool? force,
+    bool? pause,
+    String? rootLibUri,
+    String? packagesUri,
   }) =>
       _call('reloadSources', {
         'isolateId': isolateId,
@@ -1892,7 +1890,7 @@
 
   @override
   Future<Success> resume(String isolateId,
-          {/*StepOption*/ String step, int frameIndex}) =>
+          {/*StepOption*/ String? step, int? frameIndex}) =>
       _call('resume', {
         'isolateId': isolateId,
         if (step != null) 'step': step,
@@ -1938,7 +1936,8 @@
 
   /// Call an arbitrary service protocol method. This allows clients to call
   /// methods not explicitly exposed by this library.
-  Future<Response> callMethod(String method, {String isolateId, Map args}) {
+  Future<Response> callMethod(String method,
+      {String? isolateId, Map<String, dynamic>? args}) {
     return callServiceExtension(method, isolateId: isolateId, args: args);
   }
 
@@ -1947,11 +1946,11 @@
   /// See https://api.dart.dev/stable/dart-developer/dart-developer-library.html.
   @override
   Future<Response> callServiceExtension(String method,
-      {String isolateId, Map args}) {
+      {String? isolateId, Map<String, dynamic>? args}) {
     if (args == null && isolateId == null) {
       return _call(method);
     } else if (args == null) {
-      return _call(method, {'isolateId': isolateId});
+      return _call(method, {'isolateId': isolateId!});
     } else {
       args = Map.from(args);
       if (isolateId != null) {
@@ -1965,8 +1964,8 @@
 
   Stream<String> get onReceive => _onReceive.stream;
 
-  void dispose() {
-    _streamSub.cancel();
+  Future<void> dispose() async {
+    await _streamSub.cancel();
     _completers.forEach((id, c) {
       final method = _methodCalls[id];
       return c.completeError(RPCError(
@@ -1974,7 +1973,7 @@
     });
     _completers.clear();
     if (_disposeHandler != null) {
-      _disposeHandler();
+      await _disposeHandler!();
     }
     if (!_onDoneCompleter.isCompleted) {
       _onDoneCompleter.complete();
@@ -2032,22 +2031,21 @@
         bytes.buffer, bytes.offsetInBytes + metaOffset, metaLength));
     final data = ByteData.view(
         bytes.buffer, bytes.offsetInBytes + dataOffset, dataLength);
-    dynamic map = jsonDecode(meta);
-    if (map != null && map['method'] == 'streamNotify') {
+    dynamic map = jsonDecode(meta)!;
+    if (map['method'] == 'streamNotify') {
       String streamId = map['params']['streamId'];
       Map event = map['params']['event'];
       event['data'] = data;
       _getEventController(streamId)
-          .add(createServiceObject(event, const ['Event']));
+          .add(createServiceObject(event, const ['Event'])! as Event);
     }
   }
 
   void _processMessageStr(String message) {
-    var json;
+    late Map<String, dynamic> json;
     try {
       _onReceive.add(message);
-
-      json = jsonDecode(message);
+      json = jsonDecode(message)!;
     } catch (e, s) {
       _log.severe('unable to decode message: ${message}, ${e}\n${s}');
       return;
@@ -2068,9 +2066,9 @@
   }
 
   void _processResponse(Map<String, dynamic> json) {
-    Completer completer = _completers.remove(json['id']);
-    String methodName = _methodCalls.remove(json['id']);
-    List<String> returnTypes = _methodReturnTypes[methodName];
+    Completer? completer = _completers.remove(json['id']);
+    String methodName = _methodCalls.remove(json['id'])!;
+    List<String> returnTypes = _methodReturnTypes[methodName] ?? [];
     if (completer == null) {
       _log.severe('unmatched request response: ${jsonEncode(json)}');
     } else if (json['error'] != null) {
@@ -2100,25 +2098,26 @@
 
   Future _processNotification(Map<String, dynamic> json) async {
     final String method = json['method'];
-    final Map params = json['params'] ?? <String, dynamic>{};
+    final Map<String, dynamic> params = json['params'] ?? <String, dynamic>{};
     if (method == 'streamNotify') {
       String streamId = params['streamId'];
       _getEventController(streamId)
-          .add(createServiceObject(params['event'], const ['Event']));
+          .add(createServiceObject(params['event'], const ['Event'])! as Event);
     } else {
       await _routeRequest(method, params);
     }
   }
 
   Future<Map> _routeRequest(String method, Map<String, dynamic> params) async {
-    if (!_services.containsKey(method)) {
+    final service = _services[method];
+    if (service == null) {
       RPCError error = RPCError(
           method, RPCError.kMethodNotFound, 'method not found \'$method\'');
       return {'error': error.toMap()};
     }
 
     try {
-      return await _services[method](params);
+      return await service(params);
     } catch (e, st) {
       RPCError error = RPCError.withDetails(
         method,
@@ -2153,22 +2152,22 @@
     return RPCError(callingMethod, json['code'], json['message'], json['data']);
   }
 
-  final String callingMethod;
+  final String? callingMethod;
   final int code;
   final String message;
-  final Map data;
+  final Map? data;
 
   RPCError(this.callingMethod, this.code, this.message, [this.data]);
 
   RPCError.withDetails(this.callingMethod, this.code, this.message,
-      {Object details})
+      {Object? details})
       : data = details == null ? null : <String, dynamic>{} {
     if (details != null) {
-      data['details'] = details;
+      data!['details'] = details;
     }
   }
 
-  String get details => data == null ? null : data['details'];
+  String? get details => data == null ? null : data!['details'];
 
   /// Return a map representation of this error suitable for converstion to
   /// json.
@@ -2198,17 +2197,17 @@
   final Sentinel sentinel;
 
   SentinelException.parse(this.callingMethod, Map<String, dynamic> data)
-      : sentinel = Sentinel.parse(data);
+      : sentinel = Sentinel.parse(data)!;
 
   String toString() => '$sentinel from ${callingMethod}()';
 }
 
 /// An `ExtensionData` is an arbitrary map that can have any contents.
 class ExtensionData {
-  static ExtensionData parse(Map json) =>
+  static ExtensionData? parse(Map<String, dynamic>? json) =>
       json == null ? null : ExtensionData._fromJson(json);
 
-  final Map data;
+  final Map<String, dynamic> data;
 
   ExtensionData() : data = {};
 
@@ -2535,30 +2534,30 @@
 // types
 
 class AllocationProfile extends Response {
-  static AllocationProfile parse(Map<String, dynamic> json) =>
+  static AllocationProfile? parse(Map<String, dynamic>? json) =>
       json == null ? null : AllocationProfile._fromJson(json);
 
   /// Allocation information for all class types.
-  List<ClassHeapStats> members;
+  List<ClassHeapStats>? members;
 
   /// Information about memory usage for the isolate.
-  MemoryUsage memoryUsage;
+  MemoryUsage? memoryUsage;
 
   /// The timestamp of the last accumulator reset.
   ///
   /// If the accumulators have not been reset, this field is not present.
   @optional
-  int dateLastAccumulatorReset;
+  int? dateLastAccumulatorReset;
 
   /// The timestamp of the last manually triggered GC.
   ///
   /// If a GC has not been triggered manually, this field is not present.
   @optional
-  int dateLastServiceGC;
+  int? dateLastServiceGC;
 
   AllocationProfile({
-    @required this.members,
-    @required this.memoryUsage,
+    required this.members,
+    required this.memoryUsage,
     this.dateLastAccumulatorReset,
     this.dateLastServiceGC,
   });
@@ -2566,9 +2565,12 @@
   AllocationProfile._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
     members = List<ClassHeapStats>.from(
-        createServiceObject(json['members'], const ['ClassHeapStats']) ?? []);
+        createServiceObject(json['members'], const ['ClassHeapStats'])
+                as List? ??
+            []);
     memoryUsage =
-        createServiceObject(json['memoryUsage'], const ['MemoryUsage']);
+        createServiceObject(json['memoryUsage']!, const ['MemoryUsage'])
+            as MemoryUsage;
     dateLastAccumulatorReset = json['dateLastAccumulatorReset'] is String
         ? int.parse(json['dateLastAccumulatorReset'])
         : json['dateLastAccumulatorReset'];
@@ -2578,20 +2580,23 @@
   }
 
   @override
+  String get type => 'AllocationProfile';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'AllocationProfile';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'members': members.map((f) => f.toJson()).toList(),
-      'memoryUsage': memoryUsage.toJson(),
+      'members': members?.map((f) => f.toJson()).toList(),
+      'memoryUsage': memoryUsage?.toJson(),
     });
     _setIfNotNull(json, 'dateLastAccumulatorReset', dateLastAccumulatorReset);
     _setIfNotNull(json, 'dateLastServiceGC', dateLastServiceGC);
     return json;
   }
 
-  String toString() => '[AllocationProfile ' //
-      'type: ${type}, members: ${members}, memoryUsage: ${memoryUsage}]';
+  String toString() =>
+      '[AllocationProfile members: ${members}, memoryUsage: ${memoryUsage}]';
 }
 
 /// A `BoundField` represents a field bound to a particular value in an
@@ -2603,30 +2608,31 @@
 /// If the field is being initialized, the `value` will be the
 /// `BeingInitialized` [Sentinel].
 class BoundField {
-  static BoundField parse(Map<String, dynamic> json) =>
+  static BoundField? parse(Map<String, dynamic>? json) =>
       json == null ? null : BoundField._fromJson(json);
 
-  FieldRef decl;
+  FieldRef? decl;
 
   /// [value] can be one of [InstanceRef] or [Sentinel].
-  dynamic value;
+  dynamic? value;
 
   BoundField({
-    @required this.decl,
-    @required this.value,
+    required this.decl,
+    required this.value,
   });
 
   BoundField._fromJson(Map<String, dynamic> json) {
-    decl = createServiceObject(json['decl'], const ['FieldRef']);
+    decl = createServiceObject(json['decl']!, const ['FieldRef']) as FieldRef;
     value =
-        createServiceObject(json['value'], const ['InstanceRef', 'Sentinel']);
+        createServiceObject(json['value']!, const ['InstanceRef', 'Sentinel'])
+            as dynamic;
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
-      'decl': decl.toJson(),
-      'value': value.toJson(),
+      'decl': decl?.toJson(),
+      'value': value?.toJson(),
     });
     return json;
   }
@@ -2646,47 +2652,50 @@
 /// If the variable has been optimized out by the compiler, the `value` will be
 /// the `OptimizedOut` [Sentinel].
 class BoundVariable extends Response {
-  static BoundVariable parse(Map<String, dynamic> json) =>
+  static BoundVariable? parse(Map<String, dynamic>? json) =>
       json == null ? null : BoundVariable._fromJson(json);
 
-  String name;
+  String? name;
 
   /// [value] can be one of [InstanceRef], [TypeArgumentsRef] or [Sentinel].
-  dynamic value;
+  dynamic? value;
 
   /// The token position where this variable was declared.
-  int declarationTokenPos;
+  int? declarationTokenPos;
 
   /// The first token position where this variable is visible to the scope.
-  int scopeStartTokenPos;
+  int? scopeStartTokenPos;
 
   /// The last token position where this variable is visible to the scope.
-  int scopeEndTokenPos;
+  int? scopeEndTokenPos;
 
   BoundVariable({
-    @required this.name,
-    @required this.value,
-    @required this.declarationTokenPos,
-    @required this.scopeStartTokenPos,
-    @required this.scopeEndTokenPos,
+    required this.name,
+    required this.value,
+    required this.declarationTokenPos,
+    required this.scopeStartTokenPos,
+    required this.scopeEndTokenPos,
   });
 
   BoundVariable._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    value = createServiceObject(
-        json['value'], const ['InstanceRef', 'TypeArgumentsRef', 'Sentinel']);
-    declarationTokenPos = json['declarationTokenPos'];
-    scopeStartTokenPos = json['scopeStartTokenPos'];
-    scopeEndTokenPos = json['scopeEndTokenPos'];
+    name = json['name'] ?? '';
+    value = createServiceObject(json['value']!,
+        const ['InstanceRef', 'TypeArgumentsRef', 'Sentinel']) as dynamic;
+    declarationTokenPos = json['declarationTokenPos'] ?? -1;
+    scopeStartTokenPos = json['scopeStartTokenPos'] ?? -1;
+    scopeEndTokenPos = json['scopeEndTokenPos'] ?? -1;
   }
 
   @override
+  String get type => 'BoundVariable';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'BoundVariable';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'name': name,
-      'value': value.toJson(),
+      'value': value?.toJson(),
       'declarationTokenPos': declarationTokenPos,
       'scopeStartTokenPos': scopeStartTokenPos,
       'scopeEndTokenPos': scopeEndTokenPos,
@@ -2695,7 +2704,7 @@
   }
 
   String toString() => '[BoundVariable ' //
-      'type: ${type}, name: ${name}, value: ${value}, declarationTokenPos: ${declarationTokenPos}, ' //
+      'name: ${name}, value: ${value}, declarationTokenPos: ${declarationTokenPos}, ' //
       'scopeStartTokenPos: ${scopeStartTokenPos}, scopeEndTokenPos: ${scopeEndTokenPos}]';
 }
 
@@ -2706,50 +2715,55 @@
 /// yet been compiled or in a library which has not been loaded (i.e. a deferred
 /// library).
 class Breakpoint extends Obj {
-  static Breakpoint parse(Map<String, dynamic> json) =>
+  static Breakpoint? parse(Map<String, dynamic>? json) =>
       json == null ? null : Breakpoint._fromJson(json);
 
   /// A number identifying this breakpoint to the user.
-  int breakpointNumber;
+  int? breakpointNumber;
 
   /// Has this breakpoint been assigned to a specific program location?
-  bool resolved;
+  bool? resolved;
 
   /// Is this a breakpoint that was added synthetically as part of a step
   /// OverAsyncSuspension resume command?
   @optional
-  bool isSyntheticAsyncContinuation;
+  bool? isSyntheticAsyncContinuation;
 
   /// SourceLocation when breakpoint is resolved, UnresolvedSourceLocation when
   /// a breakpoint is not resolved.
   ///
   /// [location] can be one of [SourceLocation] or [UnresolvedSourceLocation].
-  dynamic location;
+  dynamic? location;
 
   Breakpoint({
-    @required this.breakpointNumber,
-    @required this.resolved,
-    @required this.location,
-    @required String id,
+    required this.breakpointNumber,
+    required this.resolved,
+    required this.location,
+    required String id,
     this.isSyntheticAsyncContinuation,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+        );
 
   Breakpoint._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    breakpointNumber = json['breakpointNumber'];
-    resolved = json['resolved'];
+    breakpointNumber = json['breakpointNumber'] ?? -1;
+    resolved = json['resolved'] ?? false;
     isSyntheticAsyncContinuation = json['isSyntheticAsyncContinuation'];
-    location = createServiceObject(
-        json['location'], const ['SourceLocation', 'UnresolvedSourceLocation']);
+    location = createServiceObject(json['location']!,
+        const ['SourceLocation', 'UnresolvedSourceLocation']) as dynamic;
   }
 
   @override
+  String get type => 'Breakpoint';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Breakpoint';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'breakpointNumber': breakpointNumber,
       'resolved': resolved,
-      'location': location.toJson(),
+      'location': location?.toJson(),
     });
     _setIfNotNull(
         json, 'isSyntheticAsyncContinuation', isSyntheticAsyncContinuation);
@@ -2761,31 +2775,36 @@
   operator ==(other) => other is Breakpoint && id == other.id;
 
   String toString() => '[Breakpoint ' //
-      'type: ${type}, id: ${id}, breakpointNumber: ${breakpointNumber}, ' //
-      'resolved: ${resolved}, location: ${location}]';
+      'id: ${id}, breakpointNumber: ${breakpointNumber}, resolved: ${resolved}, ' //
+      'location: ${location}]';
 }
 
 /// `ClassRef` is a reference to a `Class`.
 class ClassRef extends ObjRef {
-  static ClassRef parse(Map<String, dynamic> json) =>
+  static ClassRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : ClassRef._fromJson(json);
 
   /// The name of this class.
-  String name;
+  String? name;
 
   ClassRef({
-    @required this.name,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   ClassRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
+    name = json['name'] ?? '';
   }
 
   @override
+  String get type => '@Class';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Class';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
     });
@@ -2796,115 +2815,129 @@
 
   operator ==(other) => other is ClassRef && id == other.id;
 
-  String toString() => '[ClassRef type: ${type}, id: ${id}, name: ${name}]';
+  String toString() => '[ClassRef id: ${id}, name: ${name}]';
 }
 
 /// A `Class` provides information about a Dart language class.
 class Class extends Obj implements ClassRef {
-  static Class parse(Map<String, dynamic> json) =>
+  static Class? parse(Map<String, dynamic>? json) =>
       json == null ? null : Class._fromJson(json);
 
   /// The name of this class.
-  String name;
+  String? name;
 
   /// The error which occurred during class finalization, if it exists.
   @optional
-  ErrorRef error;
+  ErrorRef? error;
 
   /// Is this an abstract class?
-  bool isAbstract;
+  bool? isAbstract;
 
   /// Is this a const class?
-  bool isConst;
+  bool? isConst;
 
   /// The library which contains this class.
-  LibraryRef library;
+  LibraryRef? library;
 
   /// The location of this class in the source code.
   @optional
-  SourceLocation location;
+  SourceLocation? location;
 
   /// The superclass of this class, if any.
   @optional
-  ClassRef superClass;
+  ClassRef? superClass;
 
   /// The supertype for this class, if any.
   ///
   /// The value will be of the kind: Type.
   @optional
-  InstanceRef superType;
+  InstanceRef? superType;
 
   /// A list of interface types for this class.
   ///
   /// The values will be of the kind: Type.
-  List<InstanceRef> interfaces;
+  List<InstanceRef>? interfaces;
 
   /// The mixin type for this class, if any.
   ///
   /// The value will be of the kind: Type.
   @optional
-  InstanceRef mixin;
+  InstanceRef? mixin;
 
   /// A list of fields in this class. Does not include fields from superclasses.
-  List<FieldRef> fields;
+  List<FieldRef>? fields;
 
   /// A list of functions in this class. Does not include functions from
   /// superclasses.
-  List<FuncRef> functions;
+  List<FuncRef>? functions;
 
   /// A list of subclasses of this class.
-  List<ClassRef> subclasses;
+  List<ClassRef>? subclasses;
 
   Class({
-    @required this.name,
-    @required this.isAbstract,
-    @required this.isConst,
-    @required this.library,
-    @required this.interfaces,
-    @required this.fields,
-    @required this.functions,
-    @required this.subclasses,
-    @required String id,
+    required this.name,
+    required this.isAbstract,
+    required this.isConst,
+    required this.library,
+    required this.interfaces,
+    required this.fields,
+    required this.functions,
+    required this.subclasses,
+    required String id,
     this.error,
     this.location,
     this.superClass,
     this.superType,
     this.mixin,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+        );
 
   Class._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    error = createServiceObject(json['error'], const ['ErrorRef']);
-    isAbstract = json['abstract'];
-    isConst = json['const'];
-    library = createServiceObject(json['library'], const ['LibraryRef']);
-    location = createServiceObject(json['location'], const ['SourceLocation']);
-    superClass = createServiceObject(json['super'], const ['ClassRef']);
-    superType = createServiceObject(json['superType'], const ['InstanceRef']);
+    name = json['name'] ?? '';
+    error = createServiceObject(json['error'], const ['ErrorRef']) as ErrorRef?;
+    isAbstract = json['abstract'] ?? false;
+    isConst = json['const'] ?? false;
+    library = createServiceObject(json['library']!, const ['LibraryRef'])
+        as LibraryRef;
+    location = createServiceObject(json['location'], const ['SourceLocation'])
+        as SourceLocation?;
+    superClass =
+        createServiceObject(json['super'], const ['ClassRef']) as ClassRef?;
+    superType = createServiceObject(json['superType'], const ['InstanceRef'])
+        as InstanceRef?;
     interfaces = List<InstanceRef>.from(
-        createServiceObject(json['interfaces'], const ['InstanceRef']) ?? []);
-    mixin = createServiceObject(json['mixin'], const ['InstanceRef']);
+        createServiceObject(json['interfaces'], const ['InstanceRef'])
+                as List? ??
+            []);
+    mixin = createServiceObject(json['mixin'], const ['InstanceRef'])
+        as InstanceRef?;
     fields = List<FieldRef>.from(
-        createServiceObject(json['fields'], const ['FieldRef']) ?? []);
+        createServiceObject(json['fields'], const ['FieldRef']) as List? ?? []);
     functions = List<FuncRef>.from(
-        createServiceObject(json['functions'], const ['FuncRef']) ?? []);
+        createServiceObject(json['functions'], const ['FuncRef']) as List? ??
+            []);
     subclasses = List<ClassRef>.from(
-        createServiceObject(json['subclasses'], const ['ClassRef']) ?? []);
+        createServiceObject(json['subclasses'], const ['ClassRef']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'Class';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Class';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
       'abstract': isAbstract,
       'const': isConst,
-      'library': library.toJson(),
-      'interfaces': interfaces.map((f) => f.toJson()).toList(),
-      'fields': fields.map((f) => f.toJson()).toList(),
-      'functions': functions.map((f) => f.toJson()).toList(),
-      'subclasses': subclasses.map((f) => f.toJson()).toList(),
+      'library': library?.toJson(),
+      'interfaces': interfaces?.map((f) => f.toJson()).toList(),
+      'fields': fields?.map((f) => f.toJson()).toList(),
+      'functions': functions?.map((f) => f.toJson()).toList(),
+      'subclasses': subclasses?.map((f) => f.toJson()).toList(),
     });
     _setIfNotNull(json, 'error', error?.toJson());
     _setIfNotNull(json, 'location', location?.toJson());
@@ -2922,48 +2955,52 @@
 }
 
 class ClassHeapStats extends Response {
-  static ClassHeapStats parse(Map<String, dynamic> json) =>
+  static ClassHeapStats? parse(Map<String, dynamic>? json) =>
       json == null ? null : ClassHeapStats._fromJson(json);
 
   /// The class for which this memory information is associated.
-  ClassRef classRef;
+  ClassRef? classRef;
 
   /// The number of bytes allocated for instances of class since the accumulator
   /// was last reset.
-  int accumulatedSize;
+  int? accumulatedSize;
 
   /// The number of bytes currently allocated for instances of class.
-  int bytesCurrent;
+  int? bytesCurrent;
 
   /// The number of instances of class which have been allocated since the
   /// accumulator was last reset.
-  int instancesAccumulated;
+  int? instancesAccumulated;
 
   /// The number of instances of class which are currently alive.
-  int instancesCurrent;
+  int? instancesCurrent;
 
   ClassHeapStats({
-    @required this.classRef,
-    @required this.accumulatedSize,
-    @required this.bytesCurrent,
-    @required this.instancesAccumulated,
-    @required this.instancesCurrent,
+    required this.classRef,
+    required this.accumulatedSize,
+    required this.bytesCurrent,
+    required this.instancesAccumulated,
+    required this.instancesCurrent,
   });
 
   ClassHeapStats._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    classRef = createServiceObject(json['class'], const ['ClassRef']);
-    accumulatedSize = json['accumulatedSize'];
-    bytesCurrent = json['bytesCurrent'];
-    instancesAccumulated = json['instancesAccumulated'];
-    instancesCurrent = json['instancesCurrent'];
+    classRef =
+        createServiceObject(json['class']!, const ['ClassRef']) as ClassRef;
+    accumulatedSize = json['accumulatedSize'] ?? -1;
+    bytesCurrent = json['bytesCurrent'] ?? -1;
+    instancesAccumulated = json['instancesAccumulated'] ?? -1;
+    instancesCurrent = json['instancesCurrent'] ?? -1;
   }
 
   @override
+  String get type => 'ClassHeapStats';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'ClassHeapStats';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'class': classRef.toJson(),
+      'class': classRef?.toJson(),
       'accumulatedSize': accumulatedSize,
       'bytesCurrent': bytesCurrent,
       'instancesAccumulated': instancesAccumulated,
@@ -2973,64 +3010,73 @@
   }
 
   String toString() => '[ClassHeapStats ' //
-      'type: ${type}, classRef: ${classRef}, accumulatedSize: ${accumulatedSize}, ' //
+      'classRef: ${classRef}, accumulatedSize: ${accumulatedSize}, ' //
       'bytesCurrent: ${bytesCurrent}, instancesAccumulated: ${instancesAccumulated}, instancesCurrent: ${instancesCurrent}]';
 }
 
 class ClassList extends Response {
-  static ClassList parse(Map<String, dynamic> json) =>
+  static ClassList? parse(Map<String, dynamic>? json) =>
       json == null ? null : ClassList._fromJson(json);
 
-  List<ClassRef> classes;
+  List<ClassRef>? classes;
 
   ClassList({
-    @required this.classes,
+    required this.classes,
   });
 
   ClassList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     classes = List<ClassRef>.from(
-        createServiceObject(json['classes'], const ['ClassRef']) ?? []);
+        createServiceObject(json['classes'], const ['ClassRef']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'ClassList';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'ClassList';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'classes': classes.map((f) => f.toJson()).toList(),
+      'classes': classes?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
-  String toString() => '[ClassList type: ${type}, classes: ${classes}]';
+  String toString() => '[ClassList classes: ${classes}]';
 }
 
 /// `CodeRef` is a reference to a `Code` object.
 class CodeRef extends ObjRef {
-  static CodeRef parse(Map<String, dynamic> json) =>
+  static CodeRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : CodeRef._fromJson(json);
 
   /// A name for this code object.
-  String name;
+  String? name;
 
   /// What kind of code object is this?
-  /*CodeKind*/ String kind;
+  /*CodeKind*/ String? kind;
 
   CodeRef({
-    @required this.name,
-    @required this.kind,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required this.kind,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   CodeRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    kind = json['kind'];
+    name = json['name'] ?? '';
+    kind = json['kind'] ?? '';
   }
 
   @override
+  String get type => '@Code';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Code';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
       'kind': kind,
@@ -3042,36 +3088,40 @@
 
   operator ==(other) => other is CodeRef && id == other.id;
 
-  String toString() =>
-      '[CodeRef type: ${type}, id: ${id}, name: ${name}, kind: ${kind}]';
+  String toString() => '[CodeRef id: ${id}, name: ${name}, kind: ${kind}]';
 }
 
 /// A `Code` object represents compiled code in the Dart VM.
 class Code extends ObjRef implements CodeRef {
-  static Code parse(Map<String, dynamic> json) =>
+  static Code? parse(Map<String, dynamic>? json) =>
       json == null ? null : Code._fromJson(json);
 
   /// A name for this code object.
-  String name;
+  String? name;
 
   /// What kind of code object is this?
-  /*CodeKind*/ String kind;
+  /*CodeKind*/ String? kind;
 
   Code({
-    @required this.name,
-    @required this.kind,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required this.kind,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   Code._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    kind = json['kind'];
+    name = json['name'] ?? '';
+    kind = json['kind'] ?? '';
   }
 
   @override
+  String get type => 'Code';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Code';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
       'kind': kind,
@@ -3083,30 +3133,34 @@
 
   operator ==(other) => other is Code && id == other.id;
 
-  String toString() =>
-      '[Code type: ${type}, id: ${id}, name: ${name}, kind: ${kind}]';
+  String toString() => '[Code id: ${id}, name: ${name}, kind: ${kind}]';
 }
 
 class ContextRef extends ObjRef {
-  static ContextRef parse(Map<String, dynamic> json) =>
+  static ContextRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : ContextRef._fromJson(json);
 
   /// The number of variables in this context.
-  int length;
+  int? length;
 
   ContextRef({
-    @required this.length,
-    @required String id,
-  }) : super(id: id);
+    required this.length,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   ContextRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    length = json['length'];
+    length = json['length'] ?? -1;
   }
 
   @override
+  String get type => '@Context';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Context';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'length': length,
     });
@@ -3117,47 +3171,53 @@
 
   operator ==(other) => other is ContextRef && id == other.id;
 
-  String toString() =>
-      '[ContextRef type: ${type}, id: ${id}, length: ${length}]';
+  String toString() => '[ContextRef id: ${id}, length: ${length}]';
 }
 
 /// A `Context` is a data structure which holds the captured variables for some
 /// closure.
 class Context extends Obj implements ContextRef {
-  static Context parse(Map<String, dynamic> json) =>
+  static Context? parse(Map<String, dynamic>? json) =>
       json == null ? null : Context._fromJson(json);
 
   /// The number of variables in this context.
-  int length;
+  int? length;
 
   /// The enclosing context for this context.
   @optional
-  Context parent;
+  Context? parent;
 
   /// The variables in this context object.
-  List<ContextElement> variables;
+  List<ContextElement>? variables;
 
   Context({
-    @required this.length,
-    @required this.variables,
-    @required String id,
+    required this.length,
+    required this.variables,
+    required String id,
     this.parent,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+        );
 
   Context._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    length = json['length'];
-    parent = createServiceObject(json['parent'], const ['Context']);
+    length = json['length'] ?? -1;
+    parent = createServiceObject(json['parent'], const ['Context']) as Context?;
     variables = List<ContextElement>.from(
-        createServiceObject(json['variables'], const ['ContextElement']) ?? []);
+        createServiceObject(json['variables'], const ['ContextElement'])
+                as List? ??
+            []);
   }
 
   @override
+  String get type => 'Context';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Context';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'length': length,
-      'variables': variables.map((f) => f.toJson()).toList(),
+      'variables': variables?.map((f) => f.toJson()).toList(),
     });
     _setIfNotNull(json, 'parent', parent?.toJson());
     return json;
@@ -3167,30 +3227,31 @@
 
   operator ==(other) => other is Context && id == other.id;
 
-  String toString() => '[Context ' //
-      'type: ${type}, id: ${id}, length: ${length}, variables: ${variables}]';
+  String toString() =>
+      '[Context id: ${id}, length: ${length}, variables: ${variables}]';
 }
 
 class ContextElement {
-  static ContextElement parse(Map<String, dynamic> json) =>
+  static ContextElement? parse(Map<String, dynamic>? json) =>
       json == null ? null : ContextElement._fromJson(json);
 
   /// [value] can be one of [InstanceRef] or [Sentinel].
-  dynamic value;
+  dynamic? value;
 
   ContextElement({
-    @required this.value,
+    required this.value,
   });
 
   ContextElement._fromJson(Map<String, dynamic> json) {
     value =
-        createServiceObject(json['value'], const ['InstanceRef', 'Sentinel']);
+        createServiceObject(json['value']!, const ['InstanceRef', 'Sentinel'])
+            as dynamic;
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
-      'value': value.toJson(),
+      'value': value?.toJson(),
     });
     return json;
   }
@@ -3200,71 +3261,76 @@
 
 /// See [getCpuSamples] and [CpuSample].
 class CpuSamples extends Response {
-  static CpuSamples parse(Map<String, dynamic> json) =>
+  static CpuSamples? parse(Map<String, dynamic>? json) =>
       json == null ? null : CpuSamples._fromJson(json);
 
   /// The sampling rate for the profiler in microseconds.
-  int samplePeriod;
+  int? samplePeriod;
 
   /// The maximum possible stack depth for samples.
-  int maxStackDepth;
+  int? maxStackDepth;
 
   /// The number of samples returned.
-  int sampleCount;
+  int? sampleCount;
 
   /// The timespan the set of returned samples covers, in microseconds.
-  int timeSpan;
+  int? timeSpan;
 
   /// The start of the period of time in which the returned samples were
   /// collected.
-  int timeOriginMicros;
+  int? timeOriginMicros;
 
   /// The duration of time covered by the returned samples.
-  int timeExtentMicros;
+  int? timeExtentMicros;
 
   /// The process ID for the VM.
-  int pid;
+  int? pid;
 
   /// A list of functions seen in the relevant samples. These references can be
   /// looked up using the indicies provided in a `CpuSample` `stack` to
   /// determine which function was on the stack.
-  List<ProfileFunction> functions;
+  List<ProfileFunction>? functions;
 
   /// A list of samples collected in the range `[timeOriginMicros,
   /// timeOriginMicros + timeExtentMicros]`
-  List<CpuSample> samples;
+  List<CpuSample>? samples;
 
   CpuSamples({
-    @required this.samplePeriod,
-    @required this.maxStackDepth,
-    @required this.sampleCount,
-    @required this.timeSpan,
-    @required this.timeOriginMicros,
-    @required this.timeExtentMicros,
-    @required this.pid,
-    @required this.functions,
-    @required this.samples,
+    required this.samplePeriod,
+    required this.maxStackDepth,
+    required this.sampleCount,
+    required this.timeSpan,
+    required this.timeOriginMicros,
+    required this.timeExtentMicros,
+    required this.pid,
+    required this.functions,
+    required this.samples,
   });
 
   CpuSamples._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    samplePeriod = json['samplePeriod'];
-    maxStackDepth = json['maxStackDepth'];
-    sampleCount = json['sampleCount'];
-    timeSpan = json['timeSpan'];
-    timeOriginMicros = json['timeOriginMicros'];
-    timeExtentMicros = json['timeExtentMicros'];
-    pid = json['pid'];
+    samplePeriod = json['samplePeriod'] ?? -1;
+    maxStackDepth = json['maxStackDepth'] ?? -1;
+    sampleCount = json['sampleCount'] ?? -1;
+    timeSpan = json['timeSpan'] ?? -1;
+    timeOriginMicros = json['timeOriginMicros'] ?? -1;
+    timeExtentMicros = json['timeExtentMicros'] ?? -1;
+    pid = json['pid'] ?? -1;
     functions = List<ProfileFunction>.from(
-        createServiceObject(json['functions'], const ['ProfileFunction']) ??
+        createServiceObject(json['functions'], const ['ProfileFunction'])
+                as List? ??
             []);
     samples = List<CpuSample>.from(
-        createServiceObject(json['samples'], const ['CpuSample']) ?? []);
+        createServiceObject(json['samples'], const ['CpuSample']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'CpuSamples';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'CpuSamples';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'samplePeriod': samplePeriod,
       'maxStackDepth': maxStackDepth,
@@ -3273,8 +3339,8 @@
       'timeOriginMicros': timeOriginMicros,
       'timeExtentMicros': timeExtentMicros,
       'pid': pid,
-      'functions': functions.map((f) => f.toJson()).toList(),
-      'samples': samples.map((f) => f.toJson()).toList(),
+      'functions': functions?.map((f) => f.toJson()).toList(),
+      'samples': samples?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
@@ -3284,30 +3350,30 @@
 
 /// See [getCpuSamples] and [CpuSamples].
 class CpuSample {
-  static CpuSample parse(Map<String, dynamic> json) =>
+  static CpuSample? parse(Map<String, dynamic>? json) =>
       json == null ? null : CpuSample._fromJson(json);
 
   /// The thread ID representing the thread on which this sample was collected.
-  int tid;
+  int? tid;
 
   /// The time this sample was collected in microseconds.
-  int timestamp;
+  int? timestamp;
 
   /// The name of VM tag set when this sample was collected. Omitted if the VM
   /// tag for the sample is not considered valid.
   @optional
-  String vmTag;
+  String? vmTag;
 
   /// The name of the User tag set when this sample was collected. Omitted if no
   /// User tag was set when this sample was collected.
   @optional
-  String userTag;
+  String? userTag;
 
   /// Provided and set to true if the sample's stack was truncated. This can
   /// happen if the stack is deeper than the `stackDepth` in the `CpuSamples`
   /// response.
   @optional
-  bool truncated;
+  bool? truncated;
 
   /// The call stack at the time this sample was collected. The stack is to be
   /// interpreted as top to bottom. Each element in this array is a key into the
@@ -3317,20 +3383,20 @@
   ///
   /// `functions[stack[0]] = @Function(bar())` `functions[stack[1]] =
   /// @Function(foo())` `functions[stack[2]] = @Function(main())`
-  List<int> stack;
+  List<int>? stack;
 
   CpuSample({
-    @required this.tid,
-    @required this.timestamp,
-    @required this.stack,
+    required this.tid,
+    required this.timestamp,
+    required this.stack,
     this.vmTag,
     this.userTag,
     this.truncated,
   });
 
   CpuSample._fromJson(Map<String, dynamic> json) {
-    tid = json['tid'];
-    timestamp = json['timestamp'];
+    tid = json['tid'] ?? -1;
+    timestamp = json['timestamp'] ?? -1;
     vmTag = json['vmTag'];
     userTag = json['userTag'];
     truncated = json['truncated'];
@@ -3338,11 +3404,11 @@
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'tid': tid,
       'timestamp': timestamp,
-      'stack': stack.map((f) => f).toList(),
+      'stack': stack?.map((f) => f).toList(),
     });
     _setIfNotNull(json, 'vmTag', vmTag);
     _setIfNotNull(json, 'userTag', userTag);
@@ -3356,30 +3422,35 @@
 
 /// `ErrorRef` is a reference to an `Error`.
 class ErrorRef extends ObjRef {
-  static ErrorRef parse(Map<String, dynamic> json) =>
+  static ErrorRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : ErrorRef._fromJson(json);
 
   /// What kind of error is this?
-  /*ErrorKind*/ String kind;
+  /*ErrorKind*/ String? kind;
 
   /// A description of the error.
-  String message;
+  String? message;
 
   ErrorRef({
-    @required this.kind,
-    @required this.message,
-    @required String id,
-  }) : super(id: id);
+    required this.kind,
+    required this.message,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   ErrorRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    kind = json['kind'];
-    message = json['message'];
+    kind = json['kind'] ?? '';
+    message = json['message'] ?? '';
   }
 
   @override
+  String get type => '@Error';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Error';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'kind': kind,
       'message': message,
@@ -3392,50 +3463,57 @@
   operator ==(other) => other is ErrorRef && id == other.id;
 
   String toString() =>
-      '[ErrorRef type: ${type}, id: ${id}, kind: ${kind}, message: ${message}]';
+      '[ErrorRef id: ${id}, kind: ${kind}, message: ${message}]';
 }
 
 /// An `Error` represents a Dart language level error. This is distinct from an
 /// [RPC error].
 class Error extends Obj implements ErrorRef {
-  static Error parse(Map<String, dynamic> json) =>
+  static Error? parse(Map<String, dynamic>? json) =>
       json == null ? null : Error._fromJson(json);
 
   /// What kind of error is this?
-  /*ErrorKind*/ String kind;
+  /*ErrorKind*/ String? kind;
 
   /// A description of the error.
-  String message;
+  String? message;
 
   /// If this error is due to an unhandled exception, this is the exception
   /// thrown.
   @optional
-  InstanceRef exception;
+  InstanceRef? exception;
 
   /// If this error is due to an unhandled exception, this is the stacktrace
   /// object.
   @optional
-  InstanceRef stacktrace;
+  InstanceRef? stacktrace;
 
   Error({
-    @required this.kind,
-    @required this.message,
-    @required String id,
+    required this.kind,
+    required this.message,
+    required String id,
     this.exception,
     this.stacktrace,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+        );
 
   Error._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    kind = json['kind'];
-    message = json['message'];
-    exception = createServiceObject(json['exception'], const ['InstanceRef']);
-    stacktrace = createServiceObject(json['stacktrace'], const ['InstanceRef']);
+    kind = json['kind'] ?? '';
+    message = json['message'] ?? '';
+    exception = createServiceObject(json['exception'], const ['InstanceRef'])
+        as InstanceRef?;
+    stacktrace = createServiceObject(json['stacktrace'], const ['InstanceRef'])
+        as InstanceRef?;
   }
 
   @override
+  String get type => 'Error';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Error';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'kind': kind,
       'message': message,
@@ -3449,8 +3527,7 @@
 
   operator ==(other) => other is Error && id == other.id;
 
-  String toString() =>
-      '[Error type: ${type}, id: ${id}, kind: ${kind}, message: ${message}]';
+  String toString() => '[Error id: ${id}, kind: ${kind}, message: ${message}]';
 }
 
 /// An `Event` is an asynchronous notification from the VM. It is delivered only
@@ -3459,31 +3536,31 @@
 ///
 /// For more information, see [events].
 class Event extends Response {
-  static Event parse(Map<String, dynamic> json) =>
+  static Event? parse(Map<String, dynamic>? json) =>
       json == null ? null : Event._fromJson(json);
 
   /// What kind of event is this?
-  /*EventKind*/ String kind;
+  /*EventKind*/ String? kind;
 
   /// The isolate with which this event is associated.
   ///
   /// This is provided for all event kinds except for:
   ///  - VMUpdate, VMFlagUpdate
   @optional
-  IsolateRef isolate;
+  IsolateRef? isolate;
 
   /// The vm with which this event is associated.
   ///
   /// This is provided for the event kind:
   ///  - VMUpdate, VMFlagUpdate
   @optional
-  VMRef vm;
+  VMRef? vm;
 
   /// The timestamp (in milliseconds since the epoch) associated with this
   /// event. For some isolate pause events, the timestamp is from when the
   /// isolate was paused. For other events, the timestamp is from when the event
   /// was created.
-  int timestamp;
+  int? timestamp;
 
   /// The breakpoint which was added, removed, or resolved.
   ///
@@ -3493,7 +3570,7 @@
   ///  - BreakpointRemoved
   ///  - BreakpointResolved
   @optional
-  Breakpoint breakpoint;
+  Breakpoint? breakpoint;
 
   /// The list of breakpoints at which we are currently paused for a
   /// PauseBreakpoint event.
@@ -3507,7 +3584,7 @@
   /// This is provided for the event kinds:
   ///  - PauseBreakpoint
   @optional
-  List<Breakpoint> pauseBreakpoints;
+  List<Breakpoint>? pauseBreakpoints;
 
   /// The top stack frame associated with this event, if applicable.
   ///
@@ -3523,54 +3600,54 @@
   /// the initial resume event that is delivered when an isolate begins
   /// execution.
   @optional
-  Frame topFrame;
+  Frame? topFrame;
 
   /// The exception associated with this event, if this is a PauseException
   /// event.
   @optional
-  InstanceRef exception;
+  InstanceRef? exception;
 
   /// An array of bytes, encoded as a base64 string.
   ///
   /// This is provided for the WriteEvent event.
   @optional
-  String bytes;
+  String? bytes;
 
   /// The argument passed to dart:developer.inspect.
   ///
   /// This is provided for the Inspect event.
   @optional
-  InstanceRef inspectee;
+  InstanceRef? inspectee;
 
   /// The RPC name of the extension that was added.
   ///
   /// This is provided for the ServiceExtensionAdded event.
   @optional
-  String extensionRPC;
+  String? extensionRPC;
 
   /// The extension event kind.
   ///
   /// This is provided for the Extension event.
   @optional
-  String extensionKind;
+  String? extensionKind;
 
   /// The extension event data.
   ///
   /// This is provided for the Extension event.
   @optional
-  ExtensionData extensionData;
+  ExtensionData? extensionData;
 
   /// An array of TimelineEvents
   ///
   /// This is provided for the TimelineEvents event.
   @optional
-  List<TimelineEvent> timelineEvents;
+  List<TimelineEvent>? timelineEvents;
 
   /// The new set of recorded timeline streams.
   ///
   /// This is provided for the TimelineStreamSubscriptionsUpdate event.
   @optional
-  List<String> updatedStreams;
+  List<String>? updatedStreams;
 
   /// Is the isolate paused at an await, yield, or yield* statement?
   ///
@@ -3578,19 +3655,19 @@
   ///  - PauseBreakpoint
   ///  - PauseInterrupted
   @optional
-  bool atAsyncSuspension;
+  bool? atAsyncSuspension;
 
   /// The status (success or failure) related to the event. This is provided for
   /// the event kinds:
   ///  - IsolateReloaded
   @optional
-  String status;
+  String? status;
 
   /// LogRecord data.
   ///
   /// This is provided for the Logging event.
   @optional
-  LogRecord logRecord;
+  LogRecord? logRecord;
 
   /// The service identifier.
   ///
@@ -3598,7 +3675,7 @@
   ///  - ServiceRegistered
   ///  - ServiceUnregistered
   @optional
-  String service;
+  String? service;
 
   /// The RPC method that should be used to invoke the service.
   ///
@@ -3606,46 +3683,46 @@
   ///  - ServiceRegistered
   ///  - ServiceUnregistered
   @optional
-  String method;
+  String? method;
 
   /// The alias of the registered service.
   ///
   /// This is provided for the event kinds:
   ///  - ServiceRegistered
   @optional
-  String alias;
+  String? alias;
 
   /// The name of the changed flag.
   ///
   /// This is provided for the event kinds:
   ///  - VMFlagUpdate
   @optional
-  String flag;
+  String? flag;
 
   /// The new value of the changed flag.
   ///
   /// This is provided for the event kinds:
   ///  - VMFlagUpdate
   @optional
-  String newValue;
+  String? newValue;
 
   /// Specifies whether this event is the last of a group of events.
   ///
   /// This is provided for the event kinds:
   ///  - HeapSnapshot
   @optional
-  bool last;
+  bool? last;
 
   /// Binary data associated with the event.
   ///
   /// This is provided for the event kinds:
   ///   - HeapSnapshot
   @optional
-  ByteData data;
+  ByteData? data;
 
   Event({
-    @required this.kind,
-    @required this.timestamp,
+    required this.kind,
+    required this.timestamp,
     this.isolate,
     this.vm,
     this.breakpoint,
@@ -3672,32 +3749,38 @@
   });
 
   Event._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    kind = json['kind'];
-    isolate = createServiceObject(json['isolate'], const ['IsolateRef']);
-    vm = createServiceObject(json['vm'], const ['VMRef']);
-    timestamp = json['timestamp'];
-    breakpoint = createServiceObject(json['breakpoint'], const ['Breakpoint']);
+    kind = json['kind'] ?? '';
+    isolate = createServiceObject(json['isolate'], const ['IsolateRef'])
+        as IsolateRef?;
+    vm = createServiceObject(json['vm'], const ['VMRef']) as VMRef?;
+    timestamp = json['timestamp'] ?? -1;
+    breakpoint = createServiceObject(json['breakpoint'], const ['Breakpoint'])
+        as Breakpoint?;
     pauseBreakpoints = json['pauseBreakpoints'] == null
         ? null
-        : List<Breakpoint>.from(createServiceObject(
-            json['pauseBreakpoints'], const ['Breakpoint']));
-    topFrame = createServiceObject(json['topFrame'], const ['Frame']);
-    exception = createServiceObject(json['exception'], const ['InstanceRef']);
+        : List<Breakpoint>.from(
+            createServiceObject(json['pauseBreakpoints'], const ['Breakpoint'])!
+                as List);
+    topFrame = createServiceObject(json['topFrame'], const ['Frame']) as Frame?;
+    exception = createServiceObject(json['exception'], const ['InstanceRef'])
+        as InstanceRef?;
     bytes = json['bytes'];
-    inspectee = createServiceObject(json['inspectee'], const ['InstanceRef']);
+    inspectee = createServiceObject(json['inspectee'], const ['InstanceRef'])
+        as InstanceRef?;
     extensionRPC = json['extensionRPC'];
     extensionKind = json['extensionKind'];
     extensionData = ExtensionData.parse(json['extensionData']);
     timelineEvents = json['timelineEvents'] == null
         ? null
         : List<TimelineEvent>.from(createServiceObject(
-            json['timelineEvents'], const ['TimelineEvent']));
+            json['timelineEvents'], const ['TimelineEvent'])! as List);
     updatedStreams = json['updatedStreams'] == null
         ? null
         : List<String>.from(json['updatedStreams']);
     atAsyncSuspension = json['atAsyncSuspension'];
     status = json['status'];
-    logRecord = createServiceObject(json['logRecord'], const ['LogRecord']);
+    logRecord = createServiceObject(json['logRecord'], const ['LogRecord'])
+        as LogRecord?;
     service = json['service'];
     method = json['method'];
     alias = json['alias'];
@@ -3708,9 +3791,12 @@
   }
 
   @override
+  String get type => 'Event';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Event';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'kind': kind,
       'timestamp': timestamp,
@@ -3719,7 +3805,7 @@
     _setIfNotNull(json, 'vm', vm?.toJson());
     _setIfNotNull(json, 'breakpoint', breakpoint?.toJson());
     _setIfNotNull(json, 'pauseBreakpoints',
-        pauseBreakpoints?.map((f) => f?.toJson())?.toList());
+        pauseBreakpoints?.map((f) => f.toJson()).toList());
     _setIfNotNull(json, 'topFrame', topFrame?.toJson());
     _setIfNotNull(json, 'exception', exception?.toJson());
     _setIfNotNull(json, 'bytes', bytes);
@@ -3728,9 +3814,9 @@
     _setIfNotNull(json, 'extensionKind', extensionKind);
     _setIfNotNull(json, 'extensionData', extensionData?.data);
     _setIfNotNull(json, 'timelineEvents',
-        timelineEvents?.map((f) => f?.toJson())?.toList());
+        timelineEvents?.map((f) => f.toJson()).toList());
     _setIfNotNull(
-        json, 'updatedStreams', updatedStreams?.map((f) => f)?.toList());
+        json, 'updatedStreams', updatedStreams?.map((f) => f).toList());
     _setIfNotNull(json, 'atAsyncSuspension', atAsyncSuspension);
     _setIfNotNull(json, 'status', status);
     _setIfNotNull(json, 'logRecord', logRecord?.toJson());
@@ -3744,64 +3830,69 @@
     return json;
   }
 
-  String toString() =>
-      '[Event type: ${type}, kind: ${kind}, timestamp: ${timestamp}]';
+  String toString() => '[Event kind: ${kind}, timestamp: ${timestamp}]';
 }
 
 /// An `FieldRef` is a reference to a `Field`.
 class FieldRef extends ObjRef {
-  static FieldRef parse(Map<String, dynamic> json) =>
+  static FieldRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : FieldRef._fromJson(json);
 
   /// The name of this field.
-  String name;
+  String? name;
 
   /// The owner of this field, which can be either a Library or a Class.
-  ObjRef owner;
+  ObjRef? owner;
 
   /// The declared type of this field.
   ///
   /// The value will always be of one of the kinds: Type, TypeRef,
   /// TypeParameter, BoundedType.
-  InstanceRef declaredType;
+  InstanceRef? declaredType;
 
   /// Is this field const?
-  bool isConst;
+  bool? isConst;
 
   /// Is this field final?
-  bool isFinal;
+  bool? isFinal;
 
   /// Is this field static?
-  bool isStatic;
+  bool? isStatic;
 
   FieldRef({
-    @required this.name,
-    @required this.owner,
-    @required this.declaredType,
-    @required this.isConst,
-    @required this.isFinal,
-    @required this.isStatic,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required this.owner,
+    required this.declaredType,
+    required this.isConst,
+    required this.isFinal,
+    required this.isStatic,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   FieldRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    owner = createServiceObject(json['owner'], const ['ObjRef']);
+    name = json['name'] ?? '';
+    owner = createServiceObject(json['owner']!, const ['ObjRef']) as ObjRef;
     declaredType =
-        createServiceObject(json['declaredType'], const ['InstanceRef']);
-    isConst = json['const'];
-    isFinal = json['final'];
-    isStatic = json['static'];
+        createServiceObject(json['declaredType']!, const ['InstanceRef'])
+            as InstanceRef;
+    isConst = json['const'] ?? false;
+    isFinal = json['final'] ?? false;
+    isStatic = json['static'] ?? false;
   }
 
   @override
+  String get type => '@Field';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Field';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
-      'owner': owner.toJson(),
-      'declaredType': declaredType.toJson(),
+      'owner': owner?.toJson(),
+      'declaredType': declaredType?.toJson(),
       'const': isConst,
       'final': isFinal,
       'static': isStatic,
@@ -3813,76 +3904,88 @@
 
   operator ==(other) => other is FieldRef && id == other.id;
 
-  String toString() => '[FieldRef]';
+  String toString() => '[FieldRef ' //
+      'id: ${id}, name: ${name}, owner: ${owner}, declaredType: ${declaredType}, ' //
+      'isConst: ${isConst}, isFinal: ${isFinal}, isStatic: ${isStatic}]';
 }
 
 /// A `Field` provides information about a Dart language field or variable.
 class Field extends Obj implements FieldRef {
-  static Field parse(Map<String, dynamic> json) =>
+  static Field? parse(Map<String, dynamic>? json) =>
       json == null ? null : Field._fromJson(json);
 
   /// The name of this field.
-  String name;
+  String? name;
 
   /// The owner of this field, which can be either a Library or a Class.
-  ObjRef owner;
+  ObjRef? owner;
 
   /// The declared type of this field.
   ///
   /// The value will always be of one of the kinds: Type, TypeRef,
   /// TypeParameter, BoundedType.
-  InstanceRef declaredType;
+  InstanceRef? declaredType;
 
   /// Is this field const?
-  bool isConst;
+  bool? isConst;
 
   /// Is this field final?
-  bool isFinal;
+  bool? isFinal;
 
   /// Is this field static?
-  bool isStatic;
+  bool? isStatic;
 
-  /// The value of this field, if the field is static.
+  /// The value of this field, if the field is static. If uninitialized, this
+  /// will take the value of an uninitialized Sentinel.
+  ///
+  /// [staticValue] can be one of [InstanceRef] or [Sentinel].
   @optional
-  InstanceRef staticValue;
+  dynamic? staticValue;
 
   /// The location of this field in the source code.
   @optional
-  SourceLocation location;
+  SourceLocation? location;
 
   Field({
-    @required this.name,
-    @required this.owner,
-    @required this.declaredType,
-    @required this.isConst,
-    @required this.isFinal,
-    @required this.isStatic,
-    @required String id,
+    required this.name,
+    required this.owner,
+    required this.declaredType,
+    required this.isConst,
+    required this.isFinal,
+    required this.isStatic,
+    required String id,
     this.staticValue,
     this.location,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+        );
 
   Field._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    owner = createServiceObject(json['owner'], const ['ObjRef']);
+    name = json['name'] ?? '';
+    owner = createServiceObject(json['owner']!, const ['ObjRef']) as ObjRef;
     declaredType =
-        createServiceObject(json['declaredType'], const ['InstanceRef']);
-    isConst = json['const'];
-    isFinal = json['final'];
-    isStatic = json['static'];
-    staticValue =
-        createServiceObject(json['staticValue'], const ['InstanceRef']);
-    location = createServiceObject(json['location'], const ['SourceLocation']);
+        createServiceObject(json['declaredType']!, const ['InstanceRef'])
+            as InstanceRef;
+    isConst = json['const'] ?? false;
+    isFinal = json['final'] ?? false;
+    isStatic = json['static'] ?? false;
+    staticValue = createServiceObject(
+        json['staticValue'], const ['InstanceRef', 'Sentinel']) as dynamic?;
+    location = createServiceObject(json['location'], const ['SourceLocation'])
+        as SourceLocation?;
   }
 
   @override
+  String get type => 'Field';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Field';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
-      'owner': owner.toJson(),
-      'declaredType': declaredType.toJson(),
+      'owner': owner?.toJson(),
+      'declaredType': declaredType?.toJson(),
       'const': isConst,
       'final': isFinal,
       'static': isStatic,
@@ -3896,45 +3999,47 @@
 
   operator ==(other) => other is Field && id == other.id;
 
-  String toString() => '[Field]';
+  String toString() => '[Field ' //
+      'id: ${id}, name: ${name}, owner: ${owner}, declaredType: ${declaredType}, ' //
+      'isConst: ${isConst}, isFinal: ${isFinal}, isStatic: ${isStatic}]';
 }
 
 /// A `Flag` represents a single VM command line flag.
 class Flag {
-  static Flag parse(Map<String, dynamic> json) =>
+  static Flag? parse(Map<String, dynamic>? json) =>
       json == null ? null : Flag._fromJson(json);
 
   /// The name of the flag.
-  String name;
+  String? name;
 
   /// A description of the flag.
-  String comment;
+  String? comment;
 
   /// Has this flag been modified from its default setting?
-  bool modified;
+  bool? modified;
 
   /// The value of this flag as a string.
   ///
   /// If this property is absent, then the value of the flag was NULL.
   @optional
-  String valueAsString;
+  String? valueAsString;
 
   Flag({
-    @required this.name,
-    @required this.comment,
-    @required this.modified,
+    required this.name,
+    required this.comment,
+    required this.modified,
     this.valueAsString,
   });
 
   Flag._fromJson(Map<String, dynamic> json) {
-    name = json['name'];
-    comment = json['comment'];
-    modified = json['modified'];
+    name = json['name'] ?? '';
+    comment = json['comment'] ?? '';
+    modified = json['modified'] ?? false;
     valueAsString = json['valueAsString'];
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'name': name,
       'comment': comment,
@@ -3950,58 +4055,61 @@
 
 /// A `FlagList` represents the complete set of VM command line flags.
 class FlagList extends Response {
-  static FlagList parse(Map<String, dynamic> json) =>
+  static FlagList? parse(Map<String, dynamic>? json) =>
       json == null ? null : FlagList._fromJson(json);
 
   /// A list of all flags in the VM.
-  List<Flag> flags;
+  List<Flag>? flags;
 
   FlagList({
-    @required this.flags,
+    required this.flags,
   });
 
   FlagList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     flags = List<Flag>.from(
-        createServiceObject(json['flags'], const ['Flag']) ?? []);
+        createServiceObject(json['flags'], const ['Flag']) as List? ?? []);
   }
 
   @override
+  String get type => 'FlagList';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'FlagList';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'flags': flags.map((f) => f.toJson()).toList(),
+      'flags': flags?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
-  String toString() => '[FlagList type: ${type}, flags: ${flags}]';
+  String toString() => '[FlagList flags: ${flags}]';
 }
 
 class Frame extends Response {
-  static Frame parse(Map<String, dynamic> json) =>
+  static Frame? parse(Map<String, dynamic>? json) =>
       json == null ? null : Frame._fromJson(json);
 
-  int index;
+  int? index;
 
   @optional
-  FuncRef function;
+  FuncRef? function;
 
   @optional
-  CodeRef code;
+  CodeRef? code;
 
   @optional
-  SourceLocation location;
+  SourceLocation? location;
 
   @optional
-  List<BoundVariable> vars;
+  List<BoundVariable>? vars;
 
   @optional
   /*FrameKind*/
-  String kind;
+  String? kind;
 
   Frame({
-    @required this.index,
+    required this.index,
     this.function,
     this.code,
     this.location,
@@ -4010,77 +4118,88 @@
   });
 
   Frame._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    index = json['index'];
-    function = createServiceObject(json['function'], const ['FuncRef']);
-    code = createServiceObject(json['code'], const ['CodeRef']);
-    location = createServiceObject(json['location'], const ['SourceLocation']);
+    index = json['index'] ?? -1;
+    function =
+        createServiceObject(json['function'], const ['FuncRef']) as FuncRef?;
+    code = createServiceObject(json['code'], const ['CodeRef']) as CodeRef?;
+    location = createServiceObject(json['location'], const ['SourceLocation'])
+        as SourceLocation?;
     vars = json['vars'] == null
         ? null
         : List<BoundVariable>.from(
-            createServiceObject(json['vars'], const ['BoundVariable']));
+            createServiceObject(json['vars'], const ['BoundVariable'])!
+                as List);
     kind = json['kind'];
   }
 
   @override
+  String get type => 'Frame';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Frame';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'index': index,
     });
     _setIfNotNull(json, 'function', function?.toJson());
     _setIfNotNull(json, 'code', code?.toJson());
     _setIfNotNull(json, 'location', location?.toJson());
-    _setIfNotNull(json, 'vars', vars?.map((f) => f?.toJson())?.toList());
+    _setIfNotNull(json, 'vars', vars?.map((f) => f.toJson()).toList());
     _setIfNotNull(json, 'kind', kind);
     return json;
   }
 
-  String toString() => '[Frame type: ${type}, index: ${index}]';
+  String toString() => '[Frame index: ${index}]';
 }
 
 /// An `FuncRef` is a reference to a `Func`.
 class FuncRef extends ObjRef {
-  static FuncRef parse(Map<String, dynamic> json) =>
+  static FuncRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : FuncRef._fromJson(json);
 
   /// The name of this function.
-  String name;
+  String? name;
 
   /// The owner of this function, which can be a Library, Class, or a Function.
   ///
   /// [owner] can be one of [LibraryRef], [ClassRef] or [FuncRef].
-  dynamic owner;
+  dynamic? owner;
 
   /// Is this function static?
-  bool isStatic;
+  bool? isStatic;
 
   /// Is this function const?
-  bool isConst;
+  bool? isConst;
 
   FuncRef({
-    @required this.name,
-    @required this.owner,
-    @required this.isStatic,
-    @required this.isConst,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required this.owner,
+    required this.isStatic,
+    required this.isConst,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   FuncRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
+    name = json['name'] ?? '';
     owner = createServiceObject(
-        json['owner'], const ['LibraryRef', 'ClassRef', 'FuncRef']);
-    isStatic = json['static'];
-    isConst = json['const'];
+        json['owner']!, const ['LibraryRef', 'ClassRef', 'FuncRef']) as dynamic;
+    isStatic = json['static'] ?? false;
+    isConst = json['const'] ?? false;
   }
 
   @override
+  String get type => '@Function';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Function';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
-      'owner': owner.toJson(),
+      'owner': owner?.toJson(),
       'static': isStatic,
       'const': isConst,
     });
@@ -4092,64 +4211,70 @@
   operator ==(other) => other is FuncRef && id == other.id;
 
   String toString() => '[FuncRef ' //
-      'type: ${type}, id: ${id}, name: ${name}, owner: ${owner}, ' //
-      'isStatic: ${isStatic}, isConst: ${isConst}]';
+      'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
+      'isConst: ${isConst}]';
 }
 
 /// A `Func` represents a Dart language function.
 class Func extends Obj implements FuncRef {
-  static Func parse(Map<String, dynamic> json) =>
+  static Func? parse(Map<String, dynamic>? json) =>
       json == null ? null : Func._fromJson(json);
 
   /// The name of this function.
-  String name;
+  String? name;
 
   /// The owner of this function, which can be a Library, Class, or a Function.
   ///
   /// [owner] can be one of [LibraryRef], [ClassRef] or [FuncRef].
-  dynamic owner;
+  dynamic? owner;
 
   /// Is this function static?
-  bool isStatic;
+  bool? isStatic;
 
   /// Is this function const?
-  bool isConst;
+  bool? isConst;
 
   /// The location of this function in the source code.
   @optional
-  SourceLocation location;
+  SourceLocation? location;
 
   /// The compiled code associated with this function.
   @optional
-  CodeRef code;
+  CodeRef? code;
 
   Func({
-    @required this.name,
-    @required this.owner,
-    @required this.isStatic,
-    @required this.isConst,
-    @required String id,
+    required this.name,
+    required this.owner,
+    required this.isStatic,
+    required this.isConst,
+    required String id,
     this.location,
     this.code,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+        );
 
   Func._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
+    name = json['name'] ?? '';
     owner = createServiceObject(
-        json['owner'], const ['LibraryRef', 'ClassRef', 'FuncRef']);
-    isStatic = json['static'];
-    isConst = json['const'];
-    location = createServiceObject(json['location'], const ['SourceLocation']);
-    code = createServiceObject(json['code'], const ['CodeRef']);
+        json['owner']!, const ['LibraryRef', 'ClassRef', 'FuncRef']) as dynamic;
+    isStatic = json['static'] ?? false;
+    isConst = json['const'] ?? false;
+    location = createServiceObject(json['location'], const ['SourceLocation'])
+        as SourceLocation?;
+    code = createServiceObject(json['code'], const ['CodeRef']) as CodeRef?;
   }
 
   @override
+  String get type => 'Function';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Function';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
-      'owner': owner.toJson(),
+      'owner': owner?.toJson(),
       'static': isStatic,
       'const': isConst,
     });
@@ -4163,20 +4288,20 @@
   operator ==(other) => other is Func && id == other.id;
 
   String toString() => '[Func ' //
-      'type: ${type}, id: ${id}, name: ${name}, owner: ${owner}, ' //
-      'isStatic: ${isStatic}, isConst: ${isConst}]';
+      'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
+      'isConst: ${isConst}]';
 }
 
 /// `InstanceRef` is a reference to an `Instance`.
 class InstanceRef extends ObjRef {
-  static InstanceRef parse(Map<String, dynamic> json) =>
+  static InstanceRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : InstanceRef._fromJson(json);
 
   /// What kind of instance is this?
-  /*InstanceKind*/ String kind;
+  /*InstanceKind*/ String? kind;
 
   /// Instance references always include their class.
-  ClassRef classRef;
+  ClassRef? classRef;
 
   /// The value of this instance as a string.
   ///
@@ -4191,14 +4316,14 @@
   ///  - Int32x4
   ///  - StackTrace
   @optional
-  String valueAsString;
+  String? valueAsString;
 
   /// The valueAsString for String references may be truncated. If so, this
   /// property is added with the value 'true'.
   ///
   /// New code should use 'length' and 'count' instead.
   @optional
-  bool valueAsStringIsTruncated;
+  bool? valueAsStringIsTruncated;
 
   /// The length of a List or the number of associations in a Map or the number
   /// of codeunits in a String.
@@ -4222,28 +4347,28 @@
   ///  - Float32x4List
   ///  - Float64x2List
   @optional
-  int length;
+  int? length;
 
   /// The name of a Type instance.
   ///
   /// Provided for instance kinds:
   ///  - Type
   @optional
-  String name;
+  String? name;
 
   /// The corresponding Class if this Type has a resolved typeClass.
   ///
   /// Provided for instance kinds:
   ///  - Type
   @optional
-  ClassRef typeClass;
+  ClassRef? typeClass;
 
   /// The parameterized class of a type parameter:
   ///
   /// Provided for instance kinds:
   ///  - TypeParameter
   @optional
-  ClassRef parameterizedClass;
+  ClassRef? parameterizedClass;
 
   /// The pattern of a RegExp instance.
   ///
@@ -4252,47 +4377,47 @@
   /// Provided for instance kinds:
   ///  - RegExp
   @optional
-  InstanceRef pattern;
+  InstanceRef? pattern;
 
   /// The function associated with a Closure instance.
   ///
   /// Provided for instance kinds:
   ///  - Closure
   @optional
-  FuncRef closureFunction;
+  FuncRef? closureFunction;
 
   /// The context associated with a Closure instance.
   ///
   /// Provided for instance kinds:
   ///  - Closure
   @optional
-  ContextRef closureContext;
+  ContextRef? closureContext;
 
   /// The port ID for a ReceivePort.
   ///
   /// Provided for instance kinds:
   ///  - ReceivePort
   @optional
-  int portId;
+  int? portId;
 
   /// The stack trace associated with the allocation of a ReceivePort.
   ///
   /// Provided for instance kinds:
   ///  - ReceivePort
   @optional
-  InstanceRef allocationLocation;
+  InstanceRef? allocationLocation;
 
   /// A name associated with a ReceivePort used for debugging purposes.
   ///
   /// Provided for instance kinds:
   ///  - ReceivePort
   @optional
-  String debugName;
+  String? debugName;
 
   InstanceRef({
-    @required this.kind,
-    @required this.classRef,
-    @required String id,
+    required this.kind,
+    required this.classRef,
+    required String id,
     this.valueAsString,
     this.valueAsStringIsTruncated,
     this.length,
@@ -4305,36 +4430,48 @@
     this.portId,
     this.allocationLocation,
     this.debugName,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+        );
 
   InstanceRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    kind = json['kind'];
-    classRef = createServiceObject(json['class'], const ['ClassRef']);
+    kind = json['kind'] ?? '';
+    classRef =
+        createServiceObject(json['class']!, const ['ClassRef']) as ClassRef;
     valueAsString = json['valueAsString'];
     valueAsStringIsTruncated = json['valueAsStringIsTruncated'];
     length = json['length'];
     name = json['name'];
-    typeClass = createServiceObject(json['typeClass'], const ['ClassRef']);
+    typeClass =
+        createServiceObject(json['typeClass'], const ['ClassRef']) as ClassRef?;
     parameterizedClass =
-        createServiceObject(json['parameterizedClass'], const ['ClassRef']);
-    pattern = createServiceObject(json['pattern'], const ['InstanceRef']);
+        createServiceObject(json['parameterizedClass'], const ['ClassRef'])
+            as ClassRef?;
+    pattern = createServiceObject(json['pattern'], const ['InstanceRef'])
+        as InstanceRef?;
     closureFunction =
-        createServiceObject(json['closureFunction'], const ['FuncRef']);
+        createServiceObject(json['closureFunction'], const ['FuncRef'])
+            as FuncRef?;
     closureContext =
-        createServiceObject(json['closureContext'], const ['ContextRef']);
+        createServiceObject(json['closureContext'], const ['ContextRef'])
+            as ContextRef?;
     portId = json['portId'];
     allocationLocation =
-        createServiceObject(json['allocationLocation'], const ['InstanceRef']);
+        createServiceObject(json['allocationLocation'], const ['InstanceRef'])
+            as InstanceRef?;
     debugName = json['debugName'];
   }
 
   @override
+  String get type => '@Instance';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Instance';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'kind': kind,
-      'class': classRef.toJson(),
+      'class': classRef?.toJson(),
     });
     _setIfNotNull(json, 'valueAsString', valueAsString);
     _setIfNotNull(json, 'valueAsStringIsTruncated', valueAsStringIsTruncated);
@@ -4355,21 +4492,21 @@
 
   operator ==(other) => other is InstanceRef && id == other.id;
 
-  String toString() => '[InstanceRef ' //
-      'type: ${type}, id: ${id}, kind: ${kind}, classRef: ${classRef}]';
+  String toString() =>
+      '[InstanceRef id: ${id}, kind: ${kind}, classRef: ${classRef}]';
 }
 
 /// An `Instance` represents an instance of the Dart language class `Obj`.
 class Instance extends Obj implements InstanceRef {
-  static Instance parse(Map<String, dynamic> json) =>
+  static Instance? parse(Map<String, dynamic>? json) =>
       json == null ? null : Instance._fromJson(json);
 
   /// What kind of instance is this?
-  /*InstanceKind*/ String kind;
+  /*InstanceKind*/ String? kind;
 
   /// Instance references always include their class.
   @override
-  ClassRef classRef;
+  ClassRef? classRef;
 
   /// The value of this instance as a string.
   ///
@@ -4380,14 +4517,14 @@
   ///  - String (value may be truncated)
   ///  - StackTrace
   @optional
-  String valueAsString;
+  String? valueAsString;
 
   /// The valueAsString for String references may be truncated. If so, this
   /// property is added with the value 'true'.
   ///
   /// New code should use 'length' and 'count' instead.
   @optional
-  bool valueAsStringIsTruncated;
+  bool? valueAsStringIsTruncated;
 
   /// The length of a List or the number of associations in a Map or the number
   /// of codeunits in a String.
@@ -4411,7 +4548,7 @@
   ///  - Float32x4List
   ///  - Float64x2List
   @optional
-  int length;
+  int? length;
 
   /// The index of the first element or association or codeunit returned. This
   /// is only provided when it is non-zero.
@@ -4435,7 +4572,7 @@
   ///  - Float32x4List
   ///  - Float64x2List
   @optional
-  int offset;
+  int? offset;
 
   /// The number of elements or associations or codeunits returned. This is only
   /// provided when it is less than length.
@@ -4459,46 +4596,46 @@
   ///  - Float32x4List
   ///  - Float64x2List
   @optional
-  int count;
+  int? count;
 
   /// The name of a Type instance.
   ///
   /// Provided for instance kinds:
   ///  - Type
   @optional
-  String name;
+  String? name;
 
   /// The corresponding Class if this Type is canonical.
   ///
   /// Provided for instance kinds:
   ///  - Type
   @optional
-  ClassRef typeClass;
+  ClassRef? typeClass;
 
   /// The parameterized class of a type parameter:
   ///
   /// Provided for instance kinds:
   ///  - TypeParameter
   @optional
-  ClassRef parameterizedClass;
+  ClassRef? parameterizedClass;
 
   /// The fields of this Instance.
   @optional
-  List<BoundField> fields;
+  List<BoundField>? fields;
 
   /// The elements of a List instance.
   ///
   /// Provided for instance kinds:
   ///  - List
   @optional
-  List<dynamic> elements;
+  List<dynamic>? elements;
 
   /// The elements of a Map instance.
   ///
   /// Provided for instance kinds:
   ///  - Map
   @optional
-  List<MapAssociation> associations;
+  List<MapAssociation>? associations;
 
   /// The bytes of a TypedData instance.
   ///
@@ -4520,77 +4657,77 @@
   ///  - Float32x4List
   ///  - Float64x2List
   @optional
-  String bytes;
+  String? bytes;
 
   /// The referent of a MirrorReference instance.
   ///
   /// Provided for instance kinds:
   ///  - MirrorReference
   @optional
-  InstanceRef mirrorReferent;
+  InstanceRef? mirrorReferent;
 
   /// The pattern of a RegExp instance.
   ///
   /// Provided for instance kinds:
   ///  - RegExp
   @optional
-  InstanceRef pattern;
+  InstanceRef? pattern;
 
   /// The function associated with a Closure instance.
   ///
   /// Provided for instance kinds:
   ///  - Closure
   @optional
-  FuncRef closureFunction;
+  FuncRef? closureFunction;
 
   /// The context associated with a Closure instance.
   ///
   /// Provided for instance kinds:
   ///  - Closure
   @optional
-  ContextRef closureContext;
+  ContextRef? closureContext;
 
   /// Whether this regular expression is case sensitive.
   ///
   /// Provided for instance kinds:
   ///  - RegExp
   @optional
-  bool isCaseSensitive;
+  bool? isCaseSensitive;
 
   /// Whether this regular expression matches multiple lines.
   ///
   /// Provided for instance kinds:
   ///  - RegExp
   @optional
-  bool isMultiLine;
+  bool? isMultiLine;
 
   /// The key for a WeakProperty instance.
   ///
   /// Provided for instance kinds:
   ///  - WeakProperty
   @optional
-  InstanceRef propertyKey;
+  InstanceRef? propertyKey;
 
   /// The key for a WeakProperty instance.
   ///
   /// Provided for instance kinds:
   ///  - WeakProperty
   @optional
-  InstanceRef propertyValue;
+  InstanceRef? propertyValue;
 
   /// The type arguments for this type.
   ///
   /// Provided for instance kinds:
   ///  - Type
   @optional
-  TypeArgumentsRef typeArguments;
+  TypeArgumentsRef? typeArguments;
 
   /// The index of a TypeParameter instance.
   ///
   /// Provided for instance kinds:
   ///  - TypeParameter
   @optional
-  int parameterIndex;
+  int? parameterIndex;
 
   /// The type bounded by a BoundedType instance - or - the referent of a
   /// TypeRef instance.
@@ -4602,7 +4739,7 @@
   ///  - BoundedType
   ///  - TypeRef
   @optional
-  InstanceRef targetType;
+  InstanceRef? targetType;
 
   /// The bound of a TypeParameter or BoundedType.
   ///
@@ -4613,33 +4750,33 @@
   ///  - BoundedType
   ///  - TypeParameter
   @optional
-  InstanceRef bound;
+  InstanceRef? bound;
 
   /// The port ID for a ReceivePort.
   ///
   /// Provided for instance kinds:
   ///  - ReceivePort
   @optional
-  int portId;
+  int? portId;
 
   /// The stack trace associated with the allocation of a ReceivePort.
   ///
   /// Provided for instance kinds:
   ///  - ReceivePort
   @optional
-  InstanceRef allocationLocation;
+  InstanceRef? allocationLocation;
 
   /// A name associated with a ReceivePort used for debugging purposes.
   ///
   /// Provided for instance kinds:
   ///  - ReceivePort
   @optional
-  String debugName;
+  String? debugName;
 
   Instance({
-    @required this.kind,
-    @required this.classRef,
-    @required String id,
+    required this.kind,
+    required this.classRef,
+    required String id,
     this.valueAsString,
     this.valueAsStringIsTruncated,
     this.length,
@@ -4667,64 +4804,41 @@
     this.portId,
     this.allocationLocation,
     this.debugName,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+          classRef: classRef,
+        );
 
   Instance._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    kind = json['kind'];
-    classRef = createServiceObject(json['class'], const ['ClassRef']);
+    kind = json['kind'] ?? '';
     valueAsString = json['valueAsString'];
     valueAsStringIsTruncated = json['valueAsStringIsTruncated'];
     length = json['length'];
     offset = json['offset'];
     count = json['count'];
     name = json['name'];
-    typeClass = createServiceObject(json['typeClass'], const ['ClassRef']);
-    parameterizedClass =
-        createServiceObject(json['parameterizedClass'], const ['ClassRef']);
-    fields = json['fields'] == null
-        ? null
-        : List<BoundField>.from(
-            createServiceObject(json['fields'], const ['BoundField']));
-    elements = json['elements'] == null
-        ? null
-        : List<dynamic>.from(
-            createServiceObject(json['elements'], const ['dynamic']));
     associations = json['associations'] == null
         ? null
         : List<MapAssociation>.from(
             _createSpecificObject(json['associations'], MapAssociation.parse));
     bytes = json['bytes'];
-    mirrorReferent =
-        createServiceObject(json['mirrorReferent'], const ['InstanceRef']);
-    pattern = createServiceObject(json['pattern'], const ['InstanceRef']);
-    closureFunction =
-        createServiceObject(json['closureFunction'], const ['FuncRef']);
-    closureContext =
-        createServiceObject(json['closureContext'], const ['ContextRef']);
     isCaseSensitive = json['isCaseSensitive'];
     isMultiLine = json['isMultiLine'];
-    propertyKey =
-        createServiceObject(json['propertyKey'], const ['InstanceRef']);
-    propertyValue =
-        createServiceObject(json['propertyValue'], const ['InstanceRef']);
-    typeArguments =
-        createServiceObject(json['typeArguments'], const ['TypeArgumentsRef']);
     parameterIndex = json['parameterIndex'];
-    targetType = createServiceObject(json['targetType'], const ['InstanceRef']);
-    bound = createServiceObject(json['bound'], const ['InstanceRef']);
     portId = json['portId'];
-    allocationLocation =
-        createServiceObject(json['allocationLocation'], const ['InstanceRef']);
     debugName = json['debugName'];
   }
 
   @override
+  String get type => 'Instance';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Instance';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'kind': kind,
-      'class': classRef.toJson(),
+      'class': classRef?.toJson(),
     });
     _setIfNotNull(json, 'valueAsString', valueAsString);
     _setIfNotNull(json, 'valueAsStringIsTruncated', valueAsStringIsTruncated);
@@ -4734,11 +4848,10 @@
     _setIfNotNull(json, 'name', name);
     _setIfNotNull(json, 'typeClass', typeClass?.toJson());
     _setIfNotNull(json, 'parameterizedClass', parameterizedClass?.toJson());
-    _setIfNotNull(json, 'fields', fields?.map((f) => f?.toJson())?.toList());
+    _setIfNotNull(json, 'fields', fields?.map((f) => f.toJson()).toList());
+    _setIfNotNull(json, 'elements', elements?.map((f) => f.toJson()).toList());
     _setIfNotNull(
-        json, 'elements', elements?.map((f) => f?.toJson())?.toList());
-    _setIfNotNull(
-        json, 'associations', associations?.map((f) => f?.toJson())?.toList());
+        json, 'associations', associations?.map((f) => f.toJson()).toList());
     _setIfNotNull(json, 'bytes', bytes);
     _setIfNotNull(json, 'mirrorReferent', mirrorReferent?.toJson());
     _setIfNotNull(json, 'pattern', pattern?.toJson());
@@ -4762,46 +4875,49 @@
 
   operator ==(other) => other is Instance && id == other.id;
 
-  String toString() => '[Instance ' //
-      'type: ${type}, id: ${id}, kind: ${kind}, classRef: ${classRef}]';
+  String toString() =>
+      '[Instance id: ${id}, kind: ${kind}, classRef: ${classRef}]';
 }
 
 /// `IsolateRef` is a reference to an `Isolate` object.
 class IsolateRef extends Response {
-  static IsolateRef parse(Map<String, dynamic> json) =>
+  static IsolateRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : IsolateRef._fromJson(json);
 
   /// The id which is passed to the getIsolate RPC to load this isolate.
-  String id;
+  String? id;
 
   /// A numeric id for this isolate, represented as a string. Unique.
-  String number;
+  String? number;
 
   /// A name identifying this isolate. Not guaranteed to be unique.
-  String name;
+  String? name;
 
   /// Specifies whether the isolate was spawned by the VM or embedder for
   /// internal use. If `false`, this isolate is likely running user code.
-  bool isSystemIsolate;
+  bool? isSystemIsolate;
 
   IsolateRef({
-    @required this.id,
-    @required this.number,
-    @required this.name,
-    @required this.isSystemIsolate,
+    required this.id,
+    required this.number,
+    required this.name,
+    required this.isSystemIsolate,
   });
 
   IsolateRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    id = json['id'];
-    number = json['number'];
-    name = json['name'];
-    isSystemIsolate = json['isSystemIsolate'];
+    id = json['id'] ?? '';
+    number = json['number'] ?? '';
+    name = json['name'] ?? '';
+    isSystemIsolate = json['isSystemIsolate'] ?? false;
   }
 
   @override
+  String get type => '@Isolate';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = '@Isolate';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'id': id,
       'number': number,
@@ -4816,142 +4932,150 @@
   operator ==(other) => other is IsolateRef && id == other.id;
 
   String toString() => '[IsolateRef ' //
-      'type: ${type}, id: ${id}, number: ${number}, name: ${name}, ' //
-      'isSystemIsolate: ${isSystemIsolate}]';
+      'id: ${id}, number: ${number}, name: ${name}, isSystemIsolate: ${isSystemIsolate}]';
 }
 
 /// An `Isolate` object provides information about one isolate in the VM.
 class Isolate extends Response implements IsolateRef {
-  static Isolate parse(Map<String, dynamic> json) =>
+  static Isolate? parse(Map<String, dynamic>? json) =>
       json == null ? null : Isolate._fromJson(json);
 
   /// The id which is passed to the getIsolate RPC to reload this isolate.
-  String id;
+  String? id;
 
   /// A numeric id for this isolate, represented as a string. Unique.
-  String number;
+  String? number;
 
   /// A name identifying this isolate. Not guaranteed to be unique.
-  String name;
+  String? name;
 
   /// Specifies whether the isolate was spawned by the VM or embedder for
   /// internal use. If `false`, this isolate is likely running user code.
-  bool isSystemIsolate;
+  bool? isSystemIsolate;
 
   /// The list of isolate flags provided to this isolate. See Dart_IsolateFlags
   /// in dart_api.h for the list of accepted isolate flags.
-  List<IsolateFlag> isolateFlags;
+  List<IsolateFlag>? isolateFlags;
 
   /// The time that the VM started in milliseconds since the epoch.
   ///
   /// Suitable to pass to DateTime.fromMillisecondsSinceEpoch.
-  int startTime;
+  int? startTime;
 
   /// Is the isolate in a runnable state?
-  bool runnable;
+  bool? runnable;
 
   /// The number of live ports for this isolate.
-  int livePorts;
+  int? livePorts;
 
   /// Will this isolate pause when exiting?
-  bool pauseOnExit;
+  bool? pauseOnExit;
 
   /// The last pause event delivered to the isolate. If the isolate is running,
   /// this will be a resume event.
-  Event pauseEvent;
+  Event? pauseEvent;
 
   /// The root library for this isolate.
   ///
   /// Guaranteed to be initialized when the IsolateRunnable event fires.
   @optional
-  LibraryRef rootLib;
+  LibraryRef? rootLib;
 
   /// A list of all libraries for this isolate.
   ///
   /// Guaranteed to be initialized when the IsolateRunnable event fires.
-  List<LibraryRef> libraries;
+  List<LibraryRef>? libraries;
 
   /// A list of all breakpoints for this isolate.
-  List<Breakpoint> breakpoints;
+  List<Breakpoint>? breakpoints;
 
   /// The error that is causing this isolate to exit, if applicable.
   @optional
-  Error error;
+  Error? error;
 
   /// The current pause on exception mode for this isolate.
-  /*ExceptionPauseMode*/ String exceptionPauseMode;
+  /*ExceptionPauseMode*/ String? exceptionPauseMode;
 
   /// The list of service extension RPCs that are registered for this isolate,
   /// if any.
   @optional
-  List<String> extensionRPCs;
+  List<String>? extensionRPCs;
 
   Isolate({
-    @required this.id,
-    @required this.number,
-    @required this.name,
-    @required this.isSystemIsolate,
-    @required this.isolateFlags,
-    @required this.startTime,
-    @required this.runnable,
-    @required this.livePorts,
-    @required this.pauseOnExit,
-    @required this.pauseEvent,
-    @required this.libraries,
-    @required this.breakpoints,
-    @required this.exceptionPauseMode,
+    required this.id,
+    required this.number,
+    required this.name,
+    required this.isSystemIsolate,
+    required this.isolateFlags,
+    required this.startTime,
+    required this.runnable,
+    required this.livePorts,
+    required this.pauseOnExit,
+    required this.pauseEvent,
+    required this.libraries,
+    required this.breakpoints,
+    required this.exceptionPauseMode,
     this.rootLib,
     this.error,
     this.extensionRPCs,
   });
 
   Isolate._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    id = json['id'];
-    number = json['number'];
-    name = json['name'];
-    isSystemIsolate = json['isSystemIsolate'];
+    id = json['id'] ?? '';
+    number = json['number'] ?? '';
+    name = json['name'] ?? '';
+    isSystemIsolate = json['isSystemIsolate'] ?? false;
     isolateFlags = List<IsolateFlag>.from(
-        createServiceObject(json['isolateFlags'], const ['IsolateFlag']) ?? []);
-    startTime = json['startTime'];
-    runnable = json['runnable'];
-    livePorts = json['livePorts'];
-    pauseOnExit = json['pauseOnExit'];
-    pauseEvent = createServiceObject(json['pauseEvent'], const ['Event']);
-    rootLib = createServiceObject(json['rootLib'], const ['LibraryRef']);
+        createServiceObject(json['isolateFlags'], const ['IsolateFlag'])
+                as List? ??
+            []);
+    startTime = json['startTime'] ?? -1;
+    runnable = json['runnable'] ?? false;
+    livePorts = json['livePorts'] ?? -1;
+    pauseOnExit = json['pauseOnExit'] ?? false;
+    pauseEvent =
+        createServiceObject(json['pauseEvent']!, const ['Event']) as Event;
+    rootLib = createServiceObject(json['rootLib'], const ['LibraryRef'])
+        as LibraryRef?;
     libraries = List<LibraryRef>.from(
-        createServiceObject(json['libraries'], const ['LibraryRef']) ?? []);
+        createServiceObject(json['libraries'], const ['LibraryRef']) as List? ??
+            []);
     breakpoints = List<Breakpoint>.from(
-        createServiceObject(json['breakpoints'], const ['Breakpoint']) ?? []);
-    error = createServiceObject(json['error'], const ['Error']);
-    exceptionPauseMode = json['exceptionPauseMode'];
+        createServiceObject(json['breakpoints'], const ['Breakpoint'])
+                as List? ??
+            []);
+    error = createServiceObject(json['error'], const ['Error']) as Error?;
+    exceptionPauseMode = json['exceptionPauseMode'] ?? '';
     extensionRPCs = json['extensionRPCs'] == null
         ? null
         : List<String>.from(json['extensionRPCs']);
   }
 
   @override
+  String get type => 'Isolate';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Isolate';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'id': id,
       'number': number,
       'name': name,
       'isSystemIsolate': isSystemIsolate,
-      'isolateFlags': isolateFlags.map((f) => f.toJson()).toList(),
+      'isolateFlags': isolateFlags?.map((f) => f.toJson()).toList(),
       'startTime': startTime,
       'runnable': runnable,
       'livePorts': livePorts,
       'pauseOnExit': pauseOnExit,
-      'pauseEvent': pauseEvent.toJson(),
-      'libraries': libraries.map((f) => f.toJson()).toList(),
-      'breakpoints': breakpoints.map((f) => f.toJson()).toList(),
+      'pauseEvent': pauseEvent?.toJson(),
+      'libraries': libraries?.map((f) => f.toJson()).toList(),
+      'breakpoints': breakpoints?.map((f) => f.toJson()).toList(),
       'exceptionPauseMode': exceptionPauseMode,
     });
     _setIfNotNull(json, 'rootLib', rootLib?.toJson());
     _setIfNotNull(json, 'error', error?.toJson());
-    _setIfNotNull(
-        json, 'extensionRPCs', extensionRPCs?.map((f) => f)?.toList());
+    _setIfNotNull(json, 'extensionRPCs', extensionRPCs?.map((f) => f).toList());
     return json;
   }
 
@@ -4964,27 +5088,27 @@
 
 /// Represents the value of a single isolate flag. See [Isolate].
 class IsolateFlag {
-  static IsolateFlag parse(Map<String, dynamic> json) =>
+  static IsolateFlag? parse(Map<String, dynamic>? json) =>
       json == null ? null : IsolateFlag._fromJson(json);
 
   /// The name of the flag.
-  String name;
+  String? name;
 
   /// The value of this flag as a string.
-  String valueAsString;
+  String? valueAsString;
 
   IsolateFlag({
-    @required this.name,
-    @required this.valueAsString,
+    required this.name,
+    required this.valueAsString,
   });
 
   IsolateFlag._fromJson(Map<String, dynamic> json) {
-    name = json['name'];
-    valueAsString = json['valueAsString'];
+    name = json['name'] ?? '';
+    valueAsString = json['valueAsString'] ?? '';
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'name': name,
       'valueAsString': valueAsString,
@@ -4998,41 +5122,44 @@
 
 /// `IsolateGroupRef` is a reference to an `IsolateGroup` object.
 class IsolateGroupRef extends Response {
-  static IsolateGroupRef parse(Map<String, dynamic> json) =>
+  static IsolateGroupRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : IsolateGroupRef._fromJson(json);
 
   /// The id which is passed to the getIsolateGroup RPC to load this isolate
   /// group.
-  String id;
+  String? id;
 
   /// A numeric id for this isolate group, represented as a string. Unique.
-  String number;
+  String? number;
 
   /// A name identifying this isolate group. Not guaranteed to be unique.
-  String name;
+  String? name;
 
   /// Specifies whether the isolate group was spawned by the VM or embedder for
   /// internal use. If `false`, this isolate group is likely running user code.
-  bool isSystemIsolateGroup;
+  bool? isSystemIsolateGroup;
 
   IsolateGroupRef({
-    @required this.id,
-    @required this.number,
-    @required this.name,
-    @required this.isSystemIsolateGroup,
+    required this.id,
+    required this.number,
+    required this.name,
+    required this.isSystemIsolateGroup,
   });
 
   IsolateGroupRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    id = json['id'];
-    number = json['number'];
-    name = json['name'];
-    isSystemIsolateGroup = json['isSystemIsolateGroup'];
+    id = json['id'] ?? '';
+    number = json['number'] ?? '';
+    name = json['name'] ?? '';
+    isSystemIsolateGroup = json['isSystemIsolateGroup'] ?? false;
   }
 
   @override
+  String get type => '@IsolateGroup';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = '@IsolateGroup';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'id': id,
       'number': number,
@@ -5047,58 +5174,61 @@
   operator ==(other) => other is IsolateGroupRef && id == other.id;
 
   String toString() => '[IsolateGroupRef ' //
-      'type: ${type}, id: ${id}, number: ${number}, name: ${name}, ' //
-      'isSystemIsolateGroup: ${isSystemIsolateGroup}]';
+      'id: ${id}, number: ${number}, name: ${name}, isSystemIsolateGroup: ${isSystemIsolateGroup}]';
 }
 
 /// An `Isolate` object provides information about one isolate in the VM.
 class IsolateGroup extends Response implements IsolateGroupRef {
-  static IsolateGroup parse(Map<String, dynamic> json) =>
+  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.
-  String id;
+  String? id;
 
   /// A numeric id for this isolate, represented as a string. Unique.
-  String number;
+  String? number;
 
   /// A name identifying this isolate. Not guaranteed to be unique.
-  String name;
+  String? name;
 
   /// Specifies whether the isolate group was spawned by the VM or embedder for
   /// internal use. If `false`, this isolate group is likely running user code.
-  bool isSystemIsolateGroup;
+  bool? isSystemIsolateGroup;
 
   /// A list of all isolates in this isolate group.
-  List<IsolateRef> isolates;
+  List<IsolateRef>? isolates;
 
   IsolateGroup({
-    @required this.id,
-    @required this.number,
-    @required this.name,
-    @required this.isSystemIsolateGroup,
-    @required this.isolates,
+    required this.id,
+    required this.number,
+    required this.name,
+    required this.isSystemIsolateGroup,
+    required this.isolates,
   });
 
   IsolateGroup._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    id = json['id'];
-    number = json['number'];
-    name = json['name'];
-    isSystemIsolateGroup = json['isSystemIsolateGroup'];
+    id = json['id'] ?? '';
+    number = json['number'] ?? '';
+    name = json['name'] ?? '';
+    isSystemIsolateGroup = json['isSystemIsolateGroup'] ?? false;
     isolates = List<IsolateRef>.from(
-        createServiceObject(json['isolates'], const ['IsolateRef']) ?? []);
+        createServiceObject(json['isolates'], const ['IsolateRef']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'IsolateGroup';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'IsolateGroup';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'id': id,
       'number': number,
       'name': name,
       'isSystemIsolateGroup': isSystemIsolateGroup,
-      'isolates': isolates.map((f) => f.toJson()).toList(),
+      'isolates': isolates?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
@@ -5108,77 +5238,81 @@
   operator ==(other) => other is IsolateGroup && id == other.id;
 
   String toString() => '[IsolateGroup ' //
-      'type: ${type}, id: ${id}, number: ${number}, name: ${name}, ' //
-      'isSystemIsolateGroup: ${isSystemIsolateGroup}, isolates: ${isolates}]';
+      'id: ${id}, number: ${number}, name: ${name}, isSystemIsolateGroup: ${isSystemIsolateGroup}, ' //
+      'isolates: ${isolates}]';
 }
 
 /// See [getInboundReferences].
 class InboundReferences extends Response {
-  static InboundReferences parse(Map<String, dynamic> json) =>
+  static InboundReferences? parse(Map<String, dynamic>? json) =>
       json == null ? null : InboundReferences._fromJson(json);
 
   /// An array of inbound references to an object.
-  List<InboundReference> references;
+  List<InboundReference>? references;
 
   InboundReferences({
-    @required this.references,
+    required this.references,
   });
 
   InboundReferences._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
     references = List<InboundReference>.from(
-        createServiceObject(json['references'], const ['InboundReference']) ??
+        createServiceObject(json['references'], const ['InboundReference'])
+                as List? ??
             []);
   }
 
   @override
+  String get type => 'InboundReferences';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'InboundReferences';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'references': references.map((f) => f.toJson()).toList(),
+      'references': references?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
-  String toString() =>
-      '[InboundReferences type: ${type}, references: ${references}]';
+  String toString() => '[InboundReferences references: ${references}]';
 }
 
 /// See [getInboundReferences].
 class InboundReference {
-  static InboundReference parse(Map<String, dynamic> json) =>
+  static InboundReference? parse(Map<String, dynamic>? json) =>
       json == null ? null : InboundReference._fromJson(json);
 
   /// The object holding the inbound reference.
-  ObjRef source;
+  ObjRef? source;
 
   /// If source is a List, parentListIndex is the index of the inbound
   /// reference.
   @optional
-  int parentListIndex;
+  int? parentListIndex;
 
   /// If source is a field of an object, parentField is the field containing the
   /// inbound reference.
   @optional
-  FieldRef parentField;
+  FieldRef? parentField;
 
   InboundReference({
-    @required this.source,
+    required this.source,
     this.parentListIndex,
     this.parentField,
   });
 
   InboundReference._fromJson(Map<String, dynamic> json) {
-    source = createServiceObject(json['source'], const ['ObjRef']);
+    source = createServiceObject(json['source']!, const ['ObjRef']) as ObjRef;
     parentListIndex = json['parentListIndex'];
-    parentField = createServiceObject(json['parentField'], const ['FieldRef']);
+    parentField = createServiceObject(json['parentField'], const ['FieldRef'])
+        as FieldRef?;
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
-      'source': source.toJson(),
+      'source': source?.toJson(),
     });
     _setIfNotNull(json, 'parentListIndex', parentListIndex);
     _setIfNotNull(json, 'parentField', parentField?.toJson());
@@ -5190,67 +5324,76 @@
 
 /// See [getInstances].
 class InstanceSet extends Response {
-  static InstanceSet parse(Map<String, dynamic> json) =>
+  static InstanceSet? parse(Map<String, dynamic>? json) =>
       json == null ? null : InstanceSet._fromJson(json);
 
   /// The number of instances of the requested type currently allocated.
-  int totalCount;
+  int? totalCount;
 
   /// An array of instances of the requested type.
-  List<ObjRef> instances;
+  List<ObjRef>? instances;
 
   InstanceSet({
-    @required this.totalCount,
-    @required this.instances,
+    required this.totalCount,
+    required this.instances,
   });
 
   InstanceSet._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    totalCount = json['totalCount'];
+    totalCount = json['totalCount'] ?? -1;
     instances = List<ObjRef>.from(createServiceObject(
-        json['instances'] ?? json['samples'], const ['ObjRef']));
+            (json['instances'] ?? json['samples']!) as List, const ['ObjRef'])!
+        as List);
   }
 
   @override
+  String get type => 'InstanceSet';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'InstanceSet';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'totalCount': totalCount,
-      'instances': instances.map((f) => f.toJson()).toList(),
+      'instances': instances?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
-  String toString() => '[InstanceSet ' //
-      'type: ${type}, totalCount: ${totalCount}, instances: ${instances}]';
+  String toString() =>
+      '[InstanceSet totalCount: ${totalCount}, instances: ${instances}]';
 }
 
 /// `LibraryRef` is a reference to a `Library`.
 class LibraryRef extends ObjRef {
-  static LibraryRef parse(Map<String, dynamic> json) =>
+  static LibraryRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : LibraryRef._fromJson(json);
 
   /// The name of this library.
-  String name;
+  String? name;
 
   /// The uri of this library.
-  String uri;
+  String? uri;
 
   LibraryRef({
-    @required this.name,
-    @required this.uri,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required this.uri,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   LibraryRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    uri = json['uri'];
+    name = json['name'] ?? '';
+    uri = json['uri'] ?? '';
   }
 
   @override
+  String get type => '@Library';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Library';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
       'uri': uri,
@@ -5262,82 +5405,90 @@
 
   operator ==(other) => other is LibraryRef && id == other.id;
 
-  String toString() =>
-      '[LibraryRef type: ${type}, id: ${id}, name: ${name}, uri: ${uri}]';
+  String toString() => '[LibraryRef id: ${id}, name: ${name}, uri: ${uri}]';
 }
 
 /// A `Library` provides information about a Dart language library.
 ///
 /// See [setLibraryDebuggable].
 class Library extends Obj implements LibraryRef {
-  static Library parse(Map<String, dynamic> json) =>
+  static Library? parse(Map<String, dynamic>? json) =>
       json == null ? null : Library._fromJson(json);
 
   /// The name of this library.
-  String name;
+  String? name;
 
   /// The uri of this library.
-  String uri;
+  String? uri;
 
   /// Is this library debuggable? Default true.
-  bool debuggable;
+  bool? debuggable;
 
   /// A list of the imports for this library.
-  List<LibraryDependency> dependencies;
+  List<LibraryDependency>? dependencies;
 
   /// A list of the scripts which constitute this library.
-  List<ScriptRef> scripts;
+  List<ScriptRef>? scripts;
 
   /// A list of the top-level variables in this library.
-  List<FieldRef> variables;
+  List<FieldRef>? variables;
 
   /// A list of the top-level functions in this library.
-  List<FuncRef> functions;
+  List<FuncRef>? functions;
 
   /// A list of all classes in this library.
-  List<ClassRef> classes;
+  List<ClassRef>? classes;
 
   Library({
-    @required this.name,
-    @required this.uri,
-    @required this.debuggable,
-    @required this.dependencies,
-    @required this.scripts,
-    @required this.variables,
-    @required this.functions,
-    @required this.classes,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required this.uri,
+    required this.debuggable,
+    required this.dependencies,
+    required this.scripts,
+    required this.variables,
+    required this.functions,
+    required this.classes,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   Library._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    uri = json['uri'];
-    debuggable = json['debuggable'];
+    name = json['name'] ?? '';
+    uri = json['uri'] ?? '';
+    debuggable = json['debuggable'] ?? false;
     dependencies = List<LibraryDependency>.from(
-        _createSpecificObject(json['dependencies'], LibraryDependency.parse));
+        _createSpecificObject(json['dependencies']!, LibraryDependency.parse));
     scripts = List<ScriptRef>.from(
-        createServiceObject(json['scripts'], const ['ScriptRef']) ?? []);
+        createServiceObject(json['scripts'], const ['ScriptRef']) as List? ??
+            []);
     variables = List<FieldRef>.from(
-        createServiceObject(json['variables'], const ['FieldRef']) ?? []);
+        createServiceObject(json['variables'], const ['FieldRef']) as List? ??
+            []);
     functions = List<FuncRef>.from(
-        createServiceObject(json['functions'], const ['FuncRef']) ?? []);
+        createServiceObject(json['functions'], const ['FuncRef']) as List? ??
+            []);
     classes = List<ClassRef>.from(
-        createServiceObject(json['classes'], const ['ClassRef']) ?? []);
+        createServiceObject(json['classes'], const ['ClassRef']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'Library';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Library';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
       'uri': uri,
       'debuggable': debuggable,
-      'dependencies': dependencies.map((f) => f.toJson()).toList(),
-      'scripts': scripts.map((f) => f.toJson()).toList(),
-      'variables': variables.map((f) => f.toJson()).toList(),
-      'functions': functions.map((f) => f.toJson()).toList(),
-      'classes': classes.map((f) => f.toJson()).toList(),
+      'dependencies': dependencies?.map((f) => f.toJson()).toList(),
+      'scripts': scripts?.map((f) => f.toJson()).toList(),
+      'variables': variables?.map((f) => f.toJson()).toList(),
+      'functions': functions?.map((f) => f.toJson()).toList(),
+      'classes': classes?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
@@ -5351,42 +5502,43 @@
 
 /// A `LibraryDependency` provides information about an import or export.
 class LibraryDependency {
-  static LibraryDependency parse(Map<String, dynamic> json) =>
+  static LibraryDependency? parse(Map<String, dynamic>? json) =>
       json == null ? null : LibraryDependency._fromJson(json);
 
   /// Is this dependency an import (rather than an export)?
-  bool isImport;
+  bool? isImport;
 
   /// Is this dependency deferred?
-  bool isDeferred;
+  bool? isDeferred;
 
   /// The prefix of an 'as' import, or null.
-  String prefix;
+  String? prefix;
 
   /// The library being imported or exported.
-  LibraryRef target;
+  LibraryRef? target;
 
   LibraryDependency({
-    @required this.isImport,
-    @required this.isDeferred,
-    @required this.prefix,
-    @required this.target,
+    required this.isImport,
+    required this.isDeferred,
+    required this.prefix,
+    required this.target,
   });
 
   LibraryDependency._fromJson(Map<String, dynamic> json) {
-    isImport = json['isImport'];
-    isDeferred = json['isDeferred'];
-    prefix = json['prefix'];
-    target = createServiceObject(json['target'], const ['LibraryRef']);
+    isImport = json['isImport'] ?? false;
+    isDeferred = json['isDeferred'] ?? false;
+    prefix = json['prefix'] ?? '';
+    target = createServiceObject(json['target']!, const ['LibraryRef'])
+        as LibraryRef;
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'isImport': isImport,
       'isDeferred': isDeferred,
       'prefix': prefix,
-      'target': target.toJson(),
+      'target': target?.toJson(),
     });
     return json;
   }
@@ -5397,71 +5549,79 @@
 }
 
 class LogRecord extends Response {
-  static LogRecord parse(Map<String, dynamic> json) =>
+  static LogRecord? parse(Map<String, dynamic>? json) =>
       json == null ? null : LogRecord._fromJson(json);
 
   /// The log message.
-  InstanceRef message;
+  InstanceRef? message;
 
   /// The timestamp.
-  int time;
+  int? time;
 
   /// The severity level (a value between 0 and 2000).
   ///
   /// See the package:logging `Level` class for an overview of the possible
   /// values.
-  int level;
+  int? level;
 
   /// A monotonically increasing sequence number.
-  int sequenceNumber;
+  int? sequenceNumber;
 
   /// The name of the source of the log message.
-  InstanceRef loggerName;
+  InstanceRef? loggerName;
 
   /// The zone where the log was emitted.
-  InstanceRef zone;
+  InstanceRef? zone;
 
   /// An error object associated with this log event.
-  InstanceRef error;
+  InstanceRef? error;
 
   /// A stack trace associated with this log event.
-  InstanceRef stackTrace;
+  InstanceRef? stackTrace;
 
   LogRecord({
-    @required this.message,
-    @required this.time,
-    @required this.level,
-    @required this.sequenceNumber,
-    @required this.loggerName,
-    @required this.zone,
-    @required this.error,
-    @required this.stackTrace,
+    required this.message,
+    required this.time,
+    required this.level,
+    required this.sequenceNumber,
+    required this.loggerName,
+    required this.zone,
+    required this.error,
+    required this.stackTrace,
   });
 
   LogRecord._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    message = createServiceObject(json['message'], const ['InstanceRef']);
-    time = json['time'];
-    level = json['level'];
-    sequenceNumber = json['sequenceNumber'];
-    loggerName = createServiceObject(json['loggerName'], const ['InstanceRef']);
-    zone = createServiceObject(json['zone'], const ['InstanceRef']);
-    error = createServiceObject(json['error'], const ['InstanceRef']);
-    stackTrace = createServiceObject(json['stackTrace'], const ['InstanceRef']);
+    message = createServiceObject(json['message']!, const ['InstanceRef'])
+        as InstanceRef;
+    time = json['time'] ?? -1;
+    level = json['level'] ?? -1;
+    sequenceNumber = json['sequenceNumber'] ?? -1;
+    loggerName = createServiceObject(json['loggerName']!, const ['InstanceRef'])
+        as InstanceRef;
+    zone = createServiceObject(json['zone']!, const ['InstanceRef'])
+        as InstanceRef;
+    error = createServiceObject(json['error']!, const ['InstanceRef'])
+        as InstanceRef;
+    stackTrace = createServiceObject(json['stackTrace']!, const ['InstanceRef'])
+        as InstanceRef;
   }
 
   @override
+  String get type => 'LogRecord';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'LogRecord';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'message': message.toJson(),
+      'message': message?.toJson(),
       'time': time,
       'level': level,
       'sequenceNumber': sequenceNumber,
-      'loggerName': loggerName.toJson(),
-      'zone': zone.toJson(),
-      'error': error.toJson(),
-      'stackTrace': stackTrace.toJson(),
+      'loggerName': loggerName?.toJson(),
+      'zone': zone?.toJson(),
+      'error': error?.toJson(),
+      'stackTrace': stackTrace?.toJson(),
     });
     return json;
   }
@@ -5470,31 +5630,33 @@
 }
 
 class MapAssociation {
-  static MapAssociation parse(Map<String, dynamic> json) =>
+  static MapAssociation? parse(Map<String, dynamic>? json) =>
       json == null ? null : MapAssociation._fromJson(json);
 
   /// [key] can be one of [InstanceRef] or [Sentinel].
-  dynamic key;
+  dynamic? key;
 
   /// [value] can be one of [InstanceRef] or [Sentinel].
-  dynamic value;
+  dynamic? value;
 
   MapAssociation({
-    @required this.key,
-    @required this.value,
+    required this.key,
+    required this.value,
   });
 
   MapAssociation._fromJson(Map<String, dynamic> json) {
-    key = createServiceObject(json['key'], const ['InstanceRef', 'Sentinel']);
+    key = createServiceObject(json['key']!, const ['InstanceRef', 'Sentinel'])
+        as dynamic;
     value =
-        createServiceObject(json['value'], const ['InstanceRef', 'Sentinel']);
+        createServiceObject(json['value']!, const ['InstanceRef', 'Sentinel'])
+            as dynamic;
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
-      'key': key.toJson(),
-      'value': value.toJson(),
+      'key': key?.toJson(),
+      'value': value?.toJson(),
     });
     return json;
   }
@@ -5505,7 +5667,7 @@
 /// A `MemoryUsage` object provides heap usage information for a specific
 /// isolate at a given point in time.
 class MemoryUsage extends Response {
-  static MemoryUsage parse(Map<String, dynamic> json) =>
+  static MemoryUsage? parse(Map<String, dynamic>? json) =>
       json == null ? null : MemoryUsage._fromJson(json);
 
   /// The amount of non-Dart memory that is retained by Dart objects. For
@@ -5515,32 +5677,35 @@
   /// supplied to these APIs from the VM embedder or native extensions. This
   /// external memory applies GC pressure, but is separate from heapUsage and
   /// heapCapacity.
-  int externalUsage;
+  int? externalUsage;
 
   /// The total capacity of the heap in bytes. This is the amount of memory used
   /// by the Dart heap from the perspective of the operating system.
-  int heapCapacity;
+  int? heapCapacity;
 
   /// The current heap memory usage in bytes. Heap usage is always less than or
   /// equal to the heap capacity.
-  int heapUsage;
+  int? heapUsage;
 
   MemoryUsage({
-    @required this.externalUsage,
-    @required this.heapCapacity,
-    @required this.heapUsage,
+    required this.externalUsage,
+    required this.heapCapacity,
+    required this.heapUsage,
   });
 
   MemoryUsage._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    externalUsage = json['externalUsage'];
-    heapCapacity = json['heapCapacity'];
-    heapUsage = json['heapUsage'];
+    externalUsage = json['externalUsage'] ?? -1;
+    heapCapacity = json['heapCapacity'] ?? -1;
+    heapUsage = json['heapUsage'] ?? -1;
   }
 
   @override
+  String get type => 'MemoryUsage';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'MemoryUsage';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'externalUsage': externalUsage,
       'heapCapacity': heapCapacity,
@@ -5550,60 +5715,65 @@
   }
 
   String toString() => '[MemoryUsage ' //
-      'type: ${type}, externalUsage: ${externalUsage}, heapCapacity: ${heapCapacity}, ' //
+      'externalUsage: ${externalUsage}, heapCapacity: ${heapCapacity}, ' //
       'heapUsage: ${heapUsage}]';
 }
 
 /// A `Message` provides information about a pending isolate message and the
 /// function that will be invoked to handle it.
 class Message extends Response {
-  static Message parse(Map<String, dynamic> json) =>
+  static Message? parse(Map<String, dynamic>? json) =>
       json == null ? null : Message._fromJson(json);
 
   /// The index in the isolate's message queue. The 0th message being the next
   /// message to be processed.
-  int index;
+  int? index;
 
   /// An advisory name describing this message.
-  String name;
+  String? name;
 
   /// An instance id for the decoded message. This id can be passed to other
   /// RPCs, for example, getObject or evaluate.
-  String messageObjectId;
+  String? messageObjectId;
 
   /// The size (bytes) of the encoded message.
-  int size;
+  int? size;
 
   /// A reference to the function that will be invoked to handle this message.
   @optional
-  FuncRef handler;
+  FuncRef? handler;
 
   /// The source location of handler.
   @optional
-  SourceLocation location;
+  SourceLocation? location;
 
   Message({
-    @required this.index,
-    @required this.name,
-    @required this.messageObjectId,
-    @required this.size,
+    required this.index,
+    required this.name,
+    required this.messageObjectId,
+    required this.size,
     this.handler,
     this.location,
   });
 
   Message._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    index = json['index'];
-    name = json['name'];
-    messageObjectId = json['messageObjectId'];
-    size = json['size'];
-    handler = createServiceObject(json['handler'], const ['FuncRef']);
-    location = createServiceObject(json['location'], const ['SourceLocation']);
+    index = json['index'] ?? -1;
+    name = json['name'] ?? '';
+    messageObjectId = json['messageObjectId'] ?? '';
+    size = json['size'] ?? -1;
+    handler =
+        createServiceObject(json['handler'], const ['FuncRef']) as FuncRef?;
+    location = createServiceObject(json['location'], const ['SourceLocation'])
+        as SourceLocation?;
   }
 
   @override
+  String get type => 'Message';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Message';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'index': index,
       'name': name,
@@ -5616,29 +5786,29 @@
   }
 
   String toString() => '[Message ' //
-      'type: ${type}, index: ${index}, name: ${name}, messageObjectId: ${messageObjectId}, ' //
+      'index: ${index}, name: ${name}, messageObjectId: ${messageObjectId}, ' //
       'size: ${size}]';
 }
 
 /// A `NativeFunction` object is used to represent native functions in profiler
 /// samples. See [CpuSamples];
 class NativeFunction {
-  static NativeFunction parse(Map<String, dynamic> json) =>
+  static NativeFunction? parse(Map<String, dynamic>? json) =>
       json == null ? null : NativeFunction._fromJson(json);
 
   /// The name of the native function this object represents.
-  String name;
+  String? name;
 
   NativeFunction({
-    @required this.name,
+    required this.name,
   });
 
   NativeFunction._fromJson(Map<String, dynamic> json) {
-    name = json['name'];
+    name = json['name'] ?? '';
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'name': name,
     });
@@ -5650,25 +5820,35 @@
 
 /// `NullValRef` is a reference to an a `NullVal`.
 class NullValRef extends InstanceRef {
-  static NullValRef parse(Map<String, dynamic> json) =>
+  static NullValRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : NullValRef._fromJson(json);
 
   /// Always 'null'.
   @override
-  String valueAsString;
+  String? valueAsString;
 
   NullValRef({
-    @required this.valueAsString,
-  });
+    required this.valueAsString,
+  }) : super(
+          id: 'instance/null',
+          kind: InstanceKind.kNull,
+          classRef: ClassRef(
+            id: 'class/null',
+            name: 'Null',
+          ),
+        );
 
   NullValRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    valueAsString = json['valueAsString'];
+    valueAsString = json['valueAsString'] ?? '';
   }
 
   @override
+  String get type => '@Null';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Null';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'valueAsString': valueAsString,
     });
@@ -5680,31 +5860,40 @@
   operator ==(other) => other is NullValRef && id == other.id;
 
   String toString() => '[NullValRef ' //
-      'type: ${type}, id: ${id}, kind: ${kind}, classRef: ${classRef}, ' //
-      'valueAsString: ${valueAsString}]';
+      'id: ${id}, kind: ${kind}, classRef: ${classRef}, valueAsString: ${valueAsString}]';
 }
 
 /// A `NullVal` object represents the Dart language value null.
 class NullVal extends Instance implements NullValRef {
-  static NullVal parse(Map<String, dynamic> json) =>
+  static NullVal? parse(Map<String, dynamic>? json) =>
       json == null ? null : NullVal._fromJson(json);
 
   /// Always 'null'.
   @override
-  String valueAsString;
+  String? valueAsString;
 
   NullVal({
-    @required this.valueAsString,
-  });
+    required this.valueAsString,
+  }) : super(
+          id: 'instance/null',
+          kind: InstanceKind.kNull,
+          classRef: ClassRef(
+            id: 'class/null',
+            name: 'Null',
+          ),
+        );
 
   NullVal._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    valueAsString = json['valueAsString'];
+    valueAsString = json['valueAsString'] ?? '';
   }
 
   @override
+  String get type => 'Null';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Null';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'valueAsString': valueAsString,
     });
@@ -5716,39 +5905,41 @@
   operator ==(other) => other is NullVal && id == other.id;
 
   String toString() => '[NullVal ' //
-      'type: ${type}, id: ${id}, kind: ${kind}, classRef: ${classRef}, ' //
-      'valueAsString: ${valueAsString}]';
+      'id: ${id}, kind: ${kind}, classRef: ${classRef}, valueAsString: ${valueAsString}]';
 }
 
 /// `ObjRef` is a reference to a `Obj`.
 class ObjRef extends Response {
-  static ObjRef parse(Map<String, dynamic> json) =>
+  static ObjRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : ObjRef._fromJson(json);
 
   /// A unique identifier for an Object. Passed to the getObject RPC to load
   /// this Object.
-  String id;
+  String? id;
 
   /// Provided and set to true if the id of an Object is fixed. If true, the id
   /// of an Object is guaranteed not to change or expire. The object may,
   /// however, still be _Collected_.
   @optional
-  bool fixedId;
+  bool? fixedId;
 
   ObjRef({
-    @required this.id,
+    required this.id,
     this.fixedId,
   });
 
   ObjRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    id = json['id'];
+    id = json['id'] ?? '';
     fixedId = json['fixedId'];
   }
 
   @override
+  String get type => '@Object';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = '@Object';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'id': id,
     });
@@ -5760,25 +5951,25 @@
 
   operator ==(other) => other is ObjRef && id == other.id;
 
-  String toString() => '[ObjRef type: ${type}, id: ${id}]';
+  String toString() => '[ObjRef id: ${id}]';
 }
 
 /// An `Obj` is a persistent object that is owned by some isolate.
 class Obj extends Response implements ObjRef {
-  static Obj parse(Map<String, dynamic> json) =>
+  static Obj? parse(Map<String, dynamic>? json) =>
       json == null ? null : Obj._fromJson(json);
 
   /// A unique identifier for an Object. Passed to the getObject RPC to reload
   /// this Object.
   ///
   /// Some objects may get a new id when they are reloaded.
-  String id;
+  String? id;
 
   /// Provided and set to true if the id of an Object is fixed. If true, the id
   /// of an Object is guaranteed not to change or expire. The object may,
   /// however, still be _Collected_.
   @optional
-  bool fixedId;
+  bool? fixedId;
 
   /// If an object is allocated in the Dart heap, it will have a corresponding
   /// class object.
@@ -5789,7 +5980,7 @@
   /// Moving an Object into or out of the heap is considered a backwards
   /// compatible change for types other than Instance.
   @optional
-  ClassRef classRef;
+  ClassRef? classRef;
 
   /// The size of this object in the heap.
   ///
@@ -5799,26 +5990,30 @@
   /// implementation, this occurs for small integers, which are stored entirely
   /// within their object pointers.
   @optional
-  int size;
+  int? size;
 
   Obj({
-    @required this.id,
+    required this.id,
     this.fixedId,
     this.classRef,
     this.size,
   });
 
   Obj._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    id = json['id'];
+    id = json['id'] ?? '';
     fixedId = json['fixedId'];
-    classRef = createServiceObject(json['class'], const ['ClassRef']);
+    classRef =
+        createServiceObject(json['class'], const ['ClassRef']) as ClassRef?;
     size = json['size'];
   }
 
   @override
+  String get type => 'Object';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Object';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'id': id,
     });
@@ -5832,38 +6027,42 @@
 
   operator ==(other) => other is Obj && id == other.id;
 
-  String toString() => '[Obj type: ${type}, id: ${id}]';
+  String toString() => '[Obj id: ${id}]';
 }
 
 /// A `PortList` contains a list of ports associated with some isolate.
 ///
 /// See [getPort].
 class PortList extends Response {
-  static PortList parse(Map<String, dynamic> json) =>
+  static PortList? parse(Map<String, dynamic>? json) =>
       json == null ? null : PortList._fromJson(json);
 
-  List<InstanceRef> ports;
+  List<InstanceRef>? ports;
 
   PortList({
-    @required this.ports,
+    required this.ports,
   });
 
   PortList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     ports = List<InstanceRef>.from(
-        createServiceObject(json['ports'], const ['InstanceRef']) ?? []);
+        createServiceObject(json['ports'], const ['InstanceRef']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'PortList';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'PortList';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'ports': ports.map((f) => f.toJson()).toList(),
+      'ports': ports?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
-  String toString() => '[PortList type: ${type}, ports: ${ports}]';
+  String toString() => '[PortList ports: ${ports}]';
 }
 
 /// A `ProfileFunction` contains profiling information about a Dart or native
@@ -5871,49 +6070,50 @@
 ///
 /// See [CpuSamples].
 class ProfileFunction {
-  static ProfileFunction parse(Map<String, dynamic> json) =>
+  static ProfileFunction? parse(Map<String, dynamic>? json) =>
       json == null ? null : ProfileFunction._fromJson(json);
 
   /// The kind of function this object represents.
-  String kind;
+  String? kind;
 
   /// The number of times function appeared on the stack during sampling events.
-  int inclusiveTicks;
+  int? inclusiveTicks;
 
   /// The number of times function appeared on the top of the stack during
   /// sampling events.
-  int exclusiveTicks;
+  int? exclusiveTicks;
 
   /// The resolved URL for the script containing function.
-  String resolvedUrl;
+  String? resolvedUrl;
 
   /// The function captured during profiling.
-  dynamic function;
+  dynamic? function;
 
   ProfileFunction({
-    @required this.kind,
-    @required this.inclusiveTicks,
-    @required this.exclusiveTicks,
-    @required this.resolvedUrl,
-    @required this.function,
+    required this.kind,
+    required this.inclusiveTicks,
+    required this.exclusiveTicks,
+    required this.resolvedUrl,
+    required this.function,
   });
 
   ProfileFunction._fromJson(Map<String, dynamic> json) {
-    kind = json['kind'];
-    inclusiveTicks = json['inclusiveTicks'];
-    exclusiveTicks = json['exclusiveTicks'];
-    resolvedUrl = json['resolvedUrl'];
-    function = createServiceObject(json['function'], const ['dynamic']);
+    kind = json['kind'] ?? '';
+    inclusiveTicks = json['inclusiveTicks'] ?? -1;
+    exclusiveTicks = json['exclusiveTicks'] ?? -1;
+    resolvedUrl = json['resolvedUrl'] ?? '';
+    function =
+        createServiceObject(json['function']!, const ['dynamic']) as dynamic;
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'kind': kind,
       'inclusiveTicks': inclusiveTicks,
       'exclusiveTicks': exclusiveTicks,
       'resolvedUrl': resolvedUrl,
-      'function': function.toJson(),
+      'function': function?.toJson(),
     });
     return json;
   }
@@ -5928,62 +6128,66 @@
 ///
 /// See [Protocol] and [getSupportedProtocols].
 class ProtocolList extends Response {
-  static ProtocolList parse(Map<String, dynamic> json) =>
+  static ProtocolList? parse(Map<String, dynamic>? json) =>
       json == null ? null : ProtocolList._fromJson(json);
 
   /// A list of supported protocols provided by this service.
-  List<Protocol> protocols;
+  List<Protocol>? protocols;
 
   ProtocolList({
-    @required this.protocols,
+    required this.protocols,
   });
 
   ProtocolList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     protocols = List<Protocol>.from(
-        createServiceObject(json['protocols'], const ['Protocol']) ?? []);
+        createServiceObject(json['protocols'], const ['Protocol']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'ProtocolList';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'ProtocolList';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'protocols': protocols.map((f) => f.toJson()).toList(),
+      'protocols': protocols?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
-  String toString() => '[ProtocolList type: ${type}, protocols: ${protocols}]';
+  String toString() => '[ProtocolList protocols: ${protocols}]';
 }
 
 /// See [getSupportedProtocols].
 class Protocol {
-  static Protocol parse(Map<String, dynamic> json) =>
+  static Protocol? parse(Map<String, dynamic>? json) =>
       json == null ? null : Protocol._fromJson(json);
 
   /// The name of the supported protocol.
-  String protocolName;
+  String? protocolName;
 
   /// The major revision of the protocol.
-  int major;
+  int? major;
 
   /// The minor revision of the protocol.
-  int minor;
+  int? minor;
 
   Protocol({
-    @required this.protocolName,
-    @required this.major,
-    @required this.minor,
+    required this.protocolName,
+    required this.major,
+    required this.minor,
   });
 
   Protocol._fromJson(Map<String, dynamic> json) {
-    protocolName = json['protocolName'];
-    major = json['major'];
-    minor = json['minor'];
+    protocolName = json['protocolName'] ?? '';
+    major = json['major'] ?? -1;
+    minor = json['minor'] ?? -1;
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'protocolName': protocolName,
       'major': major,
@@ -5998,73 +6202,78 @@
 
 /// Set [getProcessMemoryUsage].
 class ProcessMemoryUsage extends Response {
-  static ProcessMemoryUsage parse(Map<String, dynamic> json) =>
+  static ProcessMemoryUsage? parse(Map<String, dynamic>? json) =>
       json == null ? null : ProcessMemoryUsage._fromJson(json);
 
-  ProcessMemoryItem root;
+  ProcessMemoryItem? root;
 
   ProcessMemoryUsage({
-    @required this.root,
+    required this.root,
   });
 
   ProcessMemoryUsage._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
-    root = createServiceObject(json['root'], const ['ProcessMemoryItem']);
+    root = createServiceObject(json['root']!, const ['ProcessMemoryItem'])
+        as ProcessMemoryItem;
   }
 
   @override
+  String get type => 'ProcessMemoryUsage';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'ProcessMemoryUsage';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'root': root.toJson(),
+      'root': root?.toJson(),
     });
     return json;
   }
 
-  String toString() => '[ProcessMemoryUsage type: ${type}, root: ${root}]';
+  String toString() => '[ProcessMemoryUsage root: ${root}]';
 }
 
 class ProcessMemoryItem {
-  static ProcessMemoryItem parse(Map<String, dynamic> json) =>
+  static ProcessMemoryItem? parse(Map<String, dynamic>? json) =>
       json == null ? null : ProcessMemoryItem._fromJson(json);
 
   /// A short name for this bucket of memory.
-  String name;
+  String? name;
 
   /// A longer description for this item.
-  String description;
+  String? description;
 
   /// The amount of memory in bytes. This is a retained size, not a shallow
   /// size. That is, it includes the size of children.
-  int size;
+  int? size;
 
   /// Subdivisons of this bucket of memory.
-  List<ProcessMemoryItem> children;
+  List<ProcessMemoryItem>? children;
 
   ProcessMemoryItem({
-    @required this.name,
-    @required this.description,
-    @required this.size,
-    @required this.children,
+    required this.name,
+    required this.description,
+    required this.size,
+    required this.children,
   });
 
   ProcessMemoryItem._fromJson(Map<String, dynamic> json) {
-    name = json['name'];
-    description = json['description'];
-    size = json['size'];
+    name = json['name'] ?? '';
+    description = json['description'] ?? '';
+    size = json['size'] ?? -1;
     children = List<ProcessMemoryItem>.from(
-        createServiceObject(json['children'], const ['ProcessMemoryItem']) ??
+        createServiceObject(json['children'], const ['ProcessMemoryItem'])
+                as List? ??
             []);
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'name': name,
       'description': description,
       'size': size,
-      'children': children.map((f) => f.toJson()).toList(),
+      'children': children?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
@@ -6075,71 +6284,75 @@
 }
 
 class ReloadReport extends Response {
-  static ReloadReport parse(Map<String, dynamic> json) =>
+  static ReloadReport? parse(Map<String, dynamic>? json) =>
       json == null ? null : ReloadReport._fromJson(json);
 
   /// Did the reload succeed or fail?
-  bool success;
+  bool? success;
 
   ReloadReport({
-    @required this.success,
+    required this.success,
   });
 
   ReloadReport._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    success = json['success'];
+    success = json['success'] ?? false;
   }
 
   @override
+  String get type => 'ReloadReport';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'ReloadReport';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'success': success,
     });
     return json;
   }
 
-  String toString() => '[ReloadReport type: ${type}, success: ${success}]';
+  String toString() => '[ReloadReport success: ${success}]';
 }
 
 /// See [RetainingPath].
 class RetainingObject {
-  static RetainingObject parse(Map<String, dynamic> json) =>
+  static RetainingObject? parse(Map<String, dynamic>? json) =>
       json == null ? null : RetainingObject._fromJson(json);
 
   /// An object that is part of a retaining path.
-  ObjRef value;
+  ObjRef? value;
 
   /// The offset of the retaining object in a containing list.
   @optional
-  int parentListIndex;
+  int? parentListIndex;
 
   /// The key mapping to the retaining object in a containing map.
   @optional
-  ObjRef parentMapKey;
+  ObjRef? parentMapKey;
 
   /// The name of the field containing the retaining object within an object.
   @optional
-  String parentField;
+  String? parentField;
 
   RetainingObject({
-    @required this.value,
+    required this.value,
     this.parentListIndex,
     this.parentMapKey,
     this.parentField,
   });
 
   RetainingObject._fromJson(Map<String, dynamic> json) {
-    value = createServiceObject(json['value'], const ['ObjRef']);
+    value = createServiceObject(json['value']!, const ['ObjRef']) as ObjRef;
     parentListIndex = json['parentListIndex'];
-    parentMapKey = createServiceObject(json['parentMapKey'], const ['ObjRef']);
+    parentMapKey =
+        createServiceObject(json['parentMapKey'], const ['ObjRef']) as ObjRef?;
     parentField = json['parentField'];
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
-      'value': value.toJson(),
+      'value': value?.toJson(),
     });
     _setIfNotNull(json, 'parentListIndex', parentListIndex);
     _setIfNotNull(json, 'parentMapKey', parentMapKey?.toJson());
@@ -6152,78 +6365,79 @@
 
 /// See [getRetainingPath].
 class RetainingPath extends Response {
-  static RetainingPath parse(Map<String, dynamic> json) =>
+  static RetainingPath? parse(Map<String, dynamic>? json) =>
       json == null ? null : RetainingPath._fromJson(json);
 
   /// The length of the retaining path.
-  int length;
+  int? length;
 
   /// The type of GC root which is holding a reference to the specified object.
   /// Possible values include:  * class table  * local handle  * persistent
   /// handle  * stack  * user global  * weak persistent handle  * unknown
-  String gcRootType;
+  String? gcRootType;
 
   /// The chain of objects which make up the retaining path.
-  List<RetainingObject> elements;
+  List<RetainingObject>? elements;
 
   RetainingPath({
-    @required this.length,
-    @required this.gcRootType,
-    @required this.elements,
+    required this.length,
+    required this.gcRootType,
+    required this.elements,
   });
 
   RetainingPath._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    length = json['length'];
-    gcRootType = json['gcRootType'];
+    length = json['length'] ?? -1;
+    gcRootType = json['gcRootType'] ?? '';
     elements = List<RetainingObject>.from(
-        createServiceObject(json['elements'], const ['RetainingObject']) ?? []);
+        createServiceObject(json['elements'], const ['RetainingObject'])
+                as List? ??
+            []);
   }
 
   @override
+  String get type => 'RetainingPath';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'RetainingPath';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'length': length,
       'gcRootType': gcRootType,
-      'elements': elements.map((f) => f.toJson()).toList(),
+      'elements': elements?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
   String toString() => '[RetainingPath ' //
-      'type: ${type}, length: ${length}, gcRootType: ${gcRootType}, ' //
-      'elements: ${elements}]';
+      'length: ${length}, gcRootType: ${gcRootType}, elements: ${elements}]';
 }
 
 /// Every non-error response returned by the Service Protocol extends
 /// `Response`. By using the `type` property, the client can determine which
 /// [type] of response has been provided.
 class Response {
-  static Response parse(Map<String, dynamic> json) =>
+  static Response? parse(Map<String, dynamic>? json) =>
       json == null ? null : Response._fromJson(json);
 
-  Map<String, dynamic> json;
+  Map<String, dynamic>? json;
 
-  /// Every response returned by the VM Service has the type property. This
-  /// allows the client distinguish between different kinds of responses.
-  String type;
+  Response();
 
-  Response({
-    @required this.type,
-  });
+  Response._fromJson(this.json);
 
-  Response._fromJson(this.json) {
-    type = json['type'];
-  }
+  String get type => 'Response';
 
   Map<String, dynamic> toJson() {
-    var result = json == null ? <String, dynamic>{} : Map.of(json);
-    result['type'] = type ?? 'Response';
+    final localJson = json;
+    final result = localJson == null
+        ? <String, dynamic>{}
+        : Map<String, dynamic>.of(localJson);
+    result['type'] = type;
     return result;
   }
 
-  String toString() => '[Response type: ${type}]';
+  String toString() => '[Response]';
 }
 
 /// A `Sentinel` is used to indicate that the normal response is not available.
@@ -6231,29 +6445,32 @@
 /// We use a `Sentinel` instead of an [error] for these cases because they do
 /// not represent a problematic condition. They are normal.
 class Sentinel extends Response {
-  static Sentinel parse(Map<String, dynamic> json) =>
+  static Sentinel? parse(Map<String, dynamic>? json) =>
       json == null ? null : Sentinel._fromJson(json);
 
   /// What kind of sentinel is this?
-  /*SentinelKind*/ String kind;
+  /*SentinelKind*/ String? kind;
 
   /// A reasonable string representation of this sentinel.
-  String valueAsString;
+  String? valueAsString;
 
   Sentinel({
-    @required this.kind,
-    @required this.valueAsString,
+    required this.kind,
+    required this.valueAsString,
   });
 
   Sentinel._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    kind = json['kind'];
-    valueAsString = json['valueAsString'];
+    kind = json['kind'] ?? '';
+    valueAsString = json['valueAsString'] ?? '';
   }
 
   @override
+  String get type => 'Sentinel';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Sentinel';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'kind': kind,
       'valueAsString': valueAsString,
@@ -6261,31 +6478,36 @@
     return json;
   }
 
-  String toString() => '[Sentinel ' //
-      'type: ${type}, kind: ${kind}, valueAsString: ${valueAsString}]';
+  String toString() =>
+      '[Sentinel kind: ${kind}, valueAsString: ${valueAsString}]';
 }
 
 /// `ScriptRef` is a reference to a `Script`.
 class ScriptRef extends ObjRef {
-  static ScriptRef parse(Map<String, dynamic> json) =>
+  static ScriptRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : ScriptRef._fromJson(json);
 
   /// The uri from which this script was loaded.
-  String uri;
+  String? uri;
 
   ScriptRef({
-    @required this.uri,
-    @required String id,
-  }) : super(id: id);
+    required this.uri,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   ScriptRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    uri = json['uri'];
+    uri = json['uri'] ?? '';
   }
 
   @override
+  String get type => '@Script';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@Script';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'uri': uri,
     });
@@ -6296,7 +6518,7 @@
 
   operator ==(other) => other is ScriptRef && id == other.id;
 
-  String toString() => '[ScriptRef type: ${type}, id: ${id}, uri: ${uri}]';
+  String toString() => '[ScriptRef id: ${id}, uri: ${uri}]';
 }
 
 /// A `Script` provides information about a Dart language script.
@@ -6330,71 +6552,75 @@
 /// 101 | 1 | 8
 /// 102 | 2 | 7
 class Script extends Obj implements ScriptRef {
-  static Script parse(Map<String, dynamic> json) =>
+  static Script? parse(Map<String, dynamic>? json) =>
       json == null ? null : Script._fromJson(json);
 
   final _tokenToLine = <int, int>{};
   final _tokenToColumn = <int, int>{};
 
   /// The uri from which this script was loaded.
-  String uri;
+  String? uri;
 
   /// The library which owns this script.
-  LibraryRef library;
+  LibraryRef? library;
 
   @optional
-  int lineOffset;
+  int? lineOffset;
 
   @optional
-  int columnOffset;
+  int? columnOffset;
 
   /// The source code for this script. This can be null for certain built-in
   /// scripts.
   @optional
-  String source;
+  String? source;
 
   /// A table encoding a mapping from token position to line and column. This
   /// field is null if sources aren't available.
   @optional
-  List<List<int>> tokenPosTable;
+  List<List<int>>? tokenPosTable;
 
   Script({
-    @required this.uri,
-    @required this.library,
-    @required String id,
+    required this.uri,
+    required this.library,
+    required String id,
     this.lineOffset,
     this.columnOffset,
     this.source,
     this.tokenPosTable,
-  }) : super(id: id);
+  }) : super(
+          id: id,
+        );
 
   Script._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    uri = json['uri'];
-    library = createServiceObject(json['library'], const ['LibraryRef']);
+    uri = json['uri'] ?? '';
+    library = createServiceObject(json['library']!, const ['LibraryRef'])
+        as LibraryRef;
     lineOffset = json['lineOffset'];
     columnOffset = json['columnOffset'];
     source = json['source'];
     tokenPosTable = json['tokenPosTable'] == null
         ? null
         : List<List<int>>.from(
-            json['tokenPosTable'].map((dynamic list) => List<int>.from(list)));
+            json['tokenPosTable']!.map((dynamic list) => List<int>.from(list)));
     _parseTokenPosTable();
   }
 
   /// This function maps a token position to a line number.
   /// The VM considers the first line to be line 1.
-  int getLineNumberFromTokenPos(int tokenPos) => _tokenToLine[tokenPos];
+  int? getLineNumberFromTokenPos(int tokenPos) => _tokenToLine[tokenPos];
 
   /// This function maps a token position to a column number.
   /// The VM considers the first column to be column 1.
-  int getColumnNumberFromTokenPos(int tokenPos) => _tokenToColumn[tokenPos];
+  int? getColumnNumberFromTokenPos(int tokenPos) => _tokenToColumn[tokenPos];
 
   void _parseTokenPosTable() {
-    if (tokenPosTable == null) {
+    final tokenPositionTable = tokenPosTable;
+    if (tokenPositionTable == null) {
       return;
     }
-    final lineSet = Set<int>();
-    for (List line in tokenPosTable) {
+    final lineSet = <int>{};
+    for (List line in tokenPositionTable) {
       // Each entry begins with a line number...
       int lineNumber = line[0];
       lineSet.add(lineNumber);
@@ -6409,18 +6635,21 @@
   }
 
   @override
+  String get type => 'Script';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'Script';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'uri': uri,
-      'library': library.toJson(),
+      'library': library?.toJson(),
     });
     _setIfNotNull(json, 'lineOffset', lineOffset);
     _setIfNotNull(json, 'columnOffset', columnOffset);
     _setIfNotNull(json, 'source', source);
-    _setIfNotNull(json, 'tokenPosTable',
-        tokenPosTable?.map((f) => f?.toList())?.toList());
+    _setIfNotNull(
+        json, 'tokenPosTable', tokenPosTable?.map((f) => f.toList()).toList());
     return json;
   }
 
@@ -6428,72 +6657,79 @@
 
   operator ==(other) => other is Script && id == other.id;
 
-  String toString() =>
-      '[Script type: ${type}, id: ${id}, uri: ${uri}, library: ${library}]';
+  String toString() => '[Script id: ${id}, uri: ${uri}, library: ${library}]';
 }
 
 class ScriptList extends Response {
-  static ScriptList parse(Map<String, dynamic> json) =>
+  static ScriptList? parse(Map<String, dynamic>? json) =>
       json == null ? null : ScriptList._fromJson(json);
 
-  List<ScriptRef> scripts;
+  List<ScriptRef>? scripts;
 
   ScriptList({
-    @required this.scripts,
+    required this.scripts,
   });
 
   ScriptList._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     scripts = List<ScriptRef>.from(
-        createServiceObject(json['scripts'], const ['ScriptRef']) ?? []);
+        createServiceObject(json['scripts'], const ['ScriptRef']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'ScriptList';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'ScriptList';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'scripts': scripts.map((f) => f.toJson()).toList(),
+      'scripts': scripts?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
-  String toString() => '[ScriptList type: ${type}, scripts: ${scripts}]';
+  String toString() => '[ScriptList scripts: ${scripts}]';
 }
 
 /// The `SourceLocation` class is used to designate a position or range in some
 /// script.
 class SourceLocation extends Response {
-  static SourceLocation parse(Map<String, dynamic> json) =>
+  static SourceLocation? parse(Map<String, dynamic>? json) =>
       json == null ? null : SourceLocation._fromJson(json);
 
   /// The script containing the source location.
-  ScriptRef script;
+  ScriptRef? script;
 
   /// The first token of the location.
-  int tokenPos;
+  int? tokenPos;
 
   /// The last token of the location if this is a range.
   @optional
-  int endTokenPos;
+  int? endTokenPos;
 
   SourceLocation({
-    @required this.script,
-    @required this.tokenPos,
+    required this.script,
+    required this.tokenPos,
     this.endTokenPos,
   });
 
   SourceLocation._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    script = createServiceObject(json['script'], const ['ScriptRef']);
-    tokenPos = json['tokenPos'];
+    script =
+        createServiceObject(json['script']!, const ['ScriptRef']) as ScriptRef;
+    tokenPos = json['tokenPos'] ?? -1;
     endTokenPos = json['endTokenPos'];
   }
 
   @override
+  String get type => 'SourceLocation';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'SourceLocation';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'script': script.toJson(),
+      'script': script?.toJson(),
       'tokenPos': tokenPos,
     });
     _setIfNotNull(json, 'endTokenPos', endTokenPos);
@@ -6501,13 +6737,13 @@
   }
 
   String toString() =>
-      '[SourceLocation type: ${type}, script: ${script}, tokenPos: ${tokenPos}]';
+      '[SourceLocation script: ${script}, tokenPos: ${tokenPos}]';
 }
 
 /// The `SourceReport` class represents a set of reports tied to source
 /// locations in an isolate.
 class SourceReport extends Response {
-  static SourceReport parse(Map<String, dynamic> json) =>
+  static SourceReport? parse(Map<String, dynamic>? json) =>
       json == null ? null : SourceReport._fromJson(json);
 
   /// A list of ranges in the program source.  These ranges correspond to ranges
@@ -6518,36 +6754,39 @@
   /// functions.
   ///
   /// Note that ranges may be duplicated, in the case of mixins.
-  List<SourceReportRange> ranges;
+  List<SourceReportRange>? ranges;
 
   /// A list of scripts, referenced by index in the report's ranges.
-  List<ScriptRef> scripts;
+  List<ScriptRef>? scripts;
 
   SourceReport({
-    @required this.ranges,
-    @required this.scripts,
+    required this.ranges,
+    required this.scripts,
   });
 
   SourceReport._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     ranges = List<SourceReportRange>.from(
-        _createSpecificObject(json['ranges'], SourceReportRange.parse));
+        _createSpecificObject(json['ranges']!, SourceReportRange.parse));
     scripts = List<ScriptRef>.from(
-        createServiceObject(json['scripts'], const ['ScriptRef']) ?? []);
+        createServiceObject(json['scripts'], const ['ScriptRef']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'SourceReport';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'SourceReport';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'ranges': ranges.map((f) => f.toJson()).toList(),
-      'scripts': scripts.map((f) => f.toJson()).toList(),
+      'ranges': ranges?.map((f) => f.toJson()).toList(),
+      'scripts': scripts?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
 
-  String toString() =>
-      '[SourceReport type: ${type}, ranges: ${ranges}, scripts: ${scripts}]';
+  String toString() => '[SourceReport ranges: ${ranges}, scripts: ${scripts}]';
 }
 
 /// The `SourceReportCoverage` class represents coverage information for one
@@ -6556,20 +6795,20 @@
 /// Note that `SourceReportCoverage` does not extend [Response] and therefore
 /// will not contain a `type` property.
 class SourceReportCoverage {
-  static SourceReportCoverage parse(Map<String, dynamic> json) =>
+  static SourceReportCoverage? parse(Map<String, dynamic>? json) =>
       json == null ? null : SourceReportCoverage._fromJson(json);
 
   /// A list of token positions in a SourceReportRange which have been executed.
   /// The list is sorted.
-  List<int> hits;
+  List<int>? hits;
 
   /// A list of token positions in a SourceReportRange which have not been
   /// executed.  The list is sorted.
-  List<int> misses;
+  List<int>? misses;
 
   SourceReportCoverage({
-    @required this.hits,
-    @required this.misses,
+    required this.hits,
+    required this.misses,
   });
 
   SourceReportCoverage._fromJson(Map<String, dynamic> json) {
@@ -6578,10 +6817,10 @@
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
-      'hits': hits.map((f) => f).toList(),
-      'misses': misses.map((f) => f).toList(),
+      'hits': hits?.map((f) => f).toList(),
+      'misses': misses?.map((f) => f).toList(),
     });
     return json;
   }
@@ -6597,55 +6836,55 @@
 /// Note that `SourceReportRange` does not extend [Response] and therefore will
 /// not contain a `type` property.
 class SourceReportRange {
-  static SourceReportRange parse(Map<String, dynamic> json) =>
+  static SourceReportRange? parse(Map<String, dynamic>? json) =>
       json == null ? null : SourceReportRange._fromJson(json);
 
   /// An index into the script table of the SourceReport, indicating which
   /// script contains this range of code.
-  int scriptIndex;
+  int? scriptIndex;
 
   /// The token position at which this range begins.
-  int startPos;
+  int? startPos;
 
   /// The token position at which this range ends.  Inclusive.
-  int endPos;
+  int? endPos;
 
   /// Has this range been compiled by the Dart VM?
-  bool compiled;
+  bool? compiled;
 
   /// The error while attempting to compile this range, if this report was
   /// generated with forceCompile=true.
   @optional
-  ErrorRef error;
+  ErrorRef? error;
 
   /// Code coverage information for this range.  Provided only when the Coverage
   /// report has been requested and the range has been compiled.
   @optional
-  SourceReportCoverage coverage;
+  SourceReportCoverage? coverage;
 
   /// Possible breakpoint information for this range, represented as a sorted
   /// list of token positions.  Provided only when the when the
   /// PossibleBreakpoint report has been requested and the range has been
   /// compiled.
   @optional
-  List<int> possibleBreakpoints;
+  List<int>? possibleBreakpoints;
 
   SourceReportRange({
-    @required this.scriptIndex,
-    @required this.startPos,
-    @required this.endPos,
-    @required this.compiled,
+    required this.scriptIndex,
+    required this.startPos,
+    required this.endPos,
+    required this.compiled,
     this.error,
     this.coverage,
     this.possibleBreakpoints,
   });
 
   SourceReportRange._fromJson(Map<String, dynamic> json) {
-    scriptIndex = json['scriptIndex'];
-    startPos = json['startPos'];
-    endPos = json['endPos'];
-    compiled = json['compiled'];
-    error = createServiceObject(json['error'], const ['ErrorRef']);
+    scriptIndex = json['scriptIndex'] ?? -1;
+    startPos = json['startPos'] ?? -1;
+    endPos = json['endPos'] ?? -1;
+    compiled = json['compiled'] ?? false;
+    error = createServiceObject(json['error'], const ['ErrorRef']) as ErrorRef?;
     coverage =
         _createSpecificObject(json['coverage'], SourceReportCoverage.parse);
     possibleBreakpoints = json['possibleBreakpoints'] == null
@@ -6654,7 +6893,7 @@
   }
 
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
+    final json = <String, dynamic>{};
     json.addAll({
       'scriptIndex': scriptIndex,
       'startPos': startPos,
@@ -6664,7 +6903,7 @@
     _setIfNotNull(json, 'error', error?.toJson());
     _setIfNotNull(json, 'coverage', coverage?.toJson());
     _setIfNotNull(json, 'possibleBreakpoints',
-        possibleBreakpoints?.map((f) => f)?.toList());
+        possibleBreakpoints?.map((f) => f).toList());
     return json;
   }
 
@@ -6678,80 +6917,85 @@
 ///
 /// See [getStack].
 class Stack extends Response {
-  static Stack parse(Map<String, dynamic> json) =>
+  static Stack? parse(Map<String, dynamic>? json) =>
       json == null ? null : Stack._fromJson(json);
 
   /// A list of frames that make up the synchronous stack, rooted at the message
   /// loop (i.e., the frames since the last asynchronous gap or the isolate's
   /// entrypoint).
-  List<Frame> frames;
+  List<Frame>? frames;
 
   /// A list of frames representing the asynchronous path. Comparable to
   /// `awaiterFrames`, if provided, although some frames may be different.
   @optional
-  List<Frame> asyncCausalFrames;
+  List<Frame>? asyncCausalFrames;
 
   /// A list of frames representing the asynchronous path. Comparable to
   /// `asyncCausalFrames`, if provided, although some frames may be different.
   @optional
-  List<Frame> awaiterFrames;
+  List<Frame>? awaiterFrames;
 
   /// A list of messages in the isolate's message queue.
-  List<Message> messages;
+  List<Message>? messages;
 
   /// Specifies whether or not this stack is complete or has been artificially
   /// truncated.
-  bool truncated;
+  bool? truncated;
 
   Stack({
-    @required this.frames,
-    @required this.messages,
-    @required this.truncated,
+    required this.frames,
+    required this.messages,
+    required this.truncated,
     this.asyncCausalFrames,
     this.awaiterFrames,
   });
 
   Stack._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     frames = List<Frame>.from(
-        createServiceObject(json['frames'], const ['Frame']) ?? []);
+        createServiceObject(json['frames'], const ['Frame']) as List? ?? []);
     asyncCausalFrames = json['asyncCausalFrames'] == null
         ? null
         : List<Frame>.from(
-            createServiceObject(json['asyncCausalFrames'], const ['Frame']));
+            createServiceObject(json['asyncCausalFrames'], const ['Frame'])!
+                as List);
     awaiterFrames = json['awaiterFrames'] == null
         ? null
         : List<Frame>.from(
-            createServiceObject(json['awaiterFrames'], const ['Frame']));
+            createServiceObject(json['awaiterFrames'], const ['Frame'])!
+                as List);
     messages = List<Message>.from(
-        createServiceObject(json['messages'], const ['Message']) ?? []);
-    truncated = json['truncated'];
+        createServiceObject(json['messages'], const ['Message']) as List? ??
+            []);
+    truncated = json['truncated'] ?? false;
   }
 
   @override
+  String get type => 'Stack';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Stack';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'frames': frames.map((f) => f.toJson()).toList(),
-      'messages': messages.map((f) => f.toJson()).toList(),
+      'frames': frames?.map((f) => f.toJson()).toList(),
+      'messages': messages?.map((f) => f.toJson()).toList(),
       'truncated': truncated,
     });
     _setIfNotNull(json, 'asyncCausalFrames',
-        asyncCausalFrames?.map((f) => f?.toJson())?.toList());
-    _setIfNotNull(json, 'awaiterFrames',
-        awaiterFrames?.map((f) => f?.toJson())?.toList());
+        asyncCausalFrames?.map((f) => f.toJson()).toList());
+    _setIfNotNull(
+        json, 'awaiterFrames', awaiterFrames?.map((f) => f.toJson()).toList());
     return json;
   }
 
   String toString() => '[Stack ' //
-      'type: ${type}, frames: ${frames}, messages: ${messages}, ' //
-      'truncated: ${truncated}]';
+      'frames: ${frames}, messages: ${messages}, truncated: ${truncated}]';
 }
 
 /// The `Success` type is used to indicate that an operation completed
 /// successfully.
 class Success extends Response {
-  static Success parse(Map<String, dynamic> json) =>
+  static Success? parse(Map<String, dynamic>? json) =>
       json == null ? null : Success._fromJson(json);
 
   Success();
@@ -6759,50 +7003,57 @@
   Success._fromJson(Map<String, dynamic> json) : super._fromJson(json);
 
   @override
+  String get type => 'Success';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Success';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     return json;
   }
 
-  String toString() => '[Success type: ${type}]';
+  String toString() => '[Success]';
 }
 
 class Timeline extends Response {
-  static Timeline parse(Map<String, dynamic> json) =>
+  static Timeline? parse(Map<String, dynamic>? json) =>
       json == null ? null : Timeline._fromJson(json);
 
-  /// A list of timeline events. No order is guaranteed for these events; in
+  /// A list of timeline events. No order is guarenteed for these events; in
   /// particular, these events may be unordered with respect to their
   /// timestamps.
-  List<TimelineEvent> traceEvents;
+  List<TimelineEvent>? traceEvents;
 
   /// The start of the period of time in which traceEvents were collected.
-  int timeOriginMicros;
+  int? timeOriginMicros;
 
   /// The duration of time covered by the timeline.
-  int timeExtentMicros;
+  int? timeExtentMicros;
 
   Timeline({
-    @required this.traceEvents,
-    @required this.timeOriginMicros,
-    @required this.timeExtentMicros,
+    required this.traceEvents,
+    required this.timeOriginMicros,
+    required this.timeExtentMicros,
   });
 
   Timeline._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     traceEvents = List<TimelineEvent>.from(
-        createServiceObject(json['traceEvents'], const ['TimelineEvent']) ??
+        createServiceObject(json['traceEvents'], const ['TimelineEvent'])
+                as List? ??
             []);
-    timeOriginMicros = json['timeOriginMicros'];
-    timeExtentMicros = json['timeExtentMicros'];
+    timeOriginMicros = json['timeOriginMicros'] ?? -1;
+    timeExtentMicros = json['timeExtentMicros'] ?? -1;
   }
 
   @override
+  String get type => 'Timeline';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Timeline';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
-      'traceEvents': traceEvents.map((f) => f.toJson()).toList(),
+      'traceEvents': traceEvents?.map((f) => f.toJson()).toList(),
       'timeOriginMicros': timeOriginMicros,
       'timeExtentMicros': timeExtentMicros,
     });
@@ -6810,125 +7061,139 @@
   }
 
   String toString() => '[Timeline ' //
-      'type: ${type}, traceEvents: ${traceEvents}, timeOriginMicros: ${timeOriginMicros}, ' //
+      'traceEvents: ${traceEvents}, timeOriginMicros: ${timeOriginMicros}, ' //
       'timeExtentMicros: ${timeExtentMicros}]';
 }
 
 /// An `TimelineEvent` is an arbitrary map that contains a [Trace Event Format]
 /// event.
 class TimelineEvent {
-  static TimelineEvent parse(Map<String, dynamic> json) =>
+  static TimelineEvent? parse(Map<String, dynamic>? json) =>
       json == null ? null : TimelineEvent._fromJson(json);
 
-  Map<String, dynamic> json;
+  Map<String, dynamic>? json;
 
   TimelineEvent();
 
   TimelineEvent._fromJson(this.json);
 
   Map<String, dynamic> toJson() {
-    var result = json == null ? <String, dynamic>{} : Map.of(json);
+    final localJson = json;
+    final result = localJson == null
+        ? <String, dynamic>{}
+        : Map<String, dynamic>.of(localJson);
     result['type'] = 'TimelineEvent';
     return result;
   }
 
-  String toString() => '[TimelineEvent ]';
+  String toString() => '[TimelineEvent]';
 }
 
 class TimelineFlags extends Response {
-  static TimelineFlags parse(Map<String, dynamic> json) =>
+  static TimelineFlags? parse(Map<String, dynamic>? json) =>
       json == null ? null : TimelineFlags._fromJson(json);
 
   /// The name of the recorder currently in use. Recorder types include, but are
   /// not limited to: Callback, Endless, Fuchsia, Macos, Ring, Startup, and
   /// Systrace. Set to "null" if no recorder is currently set.
-  String recorderName;
+  String? recorderName;
 
   /// The list of all available timeline streams.
-  List<String> availableStreams;
+  List<String>? availableStreams;
 
   /// The list of timeline streams that are currently enabled.
-  List<String> recordedStreams;
+  List<String>? recordedStreams;
 
   TimelineFlags({
-    @required this.recorderName,
-    @required this.availableStreams,
-    @required this.recordedStreams,
+    required this.recorderName,
+    required this.availableStreams,
+    required this.recordedStreams,
   });
 
   TimelineFlags._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    recorderName = json['recorderName'];
+    recorderName = json['recorderName'] ?? '';
     availableStreams = List<String>.from(json['availableStreams']);
     recordedStreams = List<String>.from(json['recordedStreams']);
   }
 
   @override
+  String get type => 'TimelineFlags';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'TimelineFlags';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'recorderName': recorderName,
-      'availableStreams': availableStreams.map((f) => f).toList(),
-      'recordedStreams': recordedStreams.map((f) => f).toList(),
+      'availableStreams': availableStreams?.map((f) => f).toList(),
+      'recordedStreams': recordedStreams?.map((f) => f).toList(),
     });
     return json;
   }
 
   String toString() => '[TimelineFlags ' //
-      'type: ${type}, recorderName: ${recorderName}, availableStreams: ${availableStreams}, ' //
+      'recorderName: ${recorderName}, availableStreams: ${availableStreams}, ' //
       'recordedStreams: ${recordedStreams}]';
 }
 
 class Timestamp extends Response {
-  static Timestamp parse(Map<String, dynamic> json) =>
+  static Timestamp? parse(Map<String, dynamic>? json) =>
       json == null ? null : Timestamp._fromJson(json);
 
   /// A timestamp in microseconds since epoch.
-  int timestamp;
+  int? timestamp;
 
   Timestamp({
-    @required this.timestamp,
+    required this.timestamp,
   });
 
   Timestamp._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    timestamp = json['timestamp'];
+    timestamp = json['timestamp'] ?? -1;
   }
 
   @override
+  String get type => 'Timestamp';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Timestamp';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'timestamp': timestamp,
     });
     return json;
   }
 
-  String toString() => '[Timestamp type: ${type}, timestamp: ${timestamp}]';
+  String toString() => '[Timestamp timestamp: ${timestamp}]';
 }
 
 /// `TypeArgumentsRef` is a reference to a `TypeArguments` object.
 class TypeArgumentsRef extends ObjRef {
-  static TypeArgumentsRef parse(Map<String, dynamic> json) =>
+  static TypeArgumentsRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : TypeArgumentsRef._fromJson(json);
 
   /// A name for this type argument list.
-  String name;
+  String? name;
 
   TypeArgumentsRef({
-    @required this.name,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   TypeArgumentsRef._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
-    name = json['name'];
+    name = json['name'] ?? '';
   }
 
   @override
+  String get type => '@TypeArguments';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = '@TypeArguments';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
     });
@@ -6939,44 +7204,49 @@
 
   operator ==(other) => other is TypeArgumentsRef && id == other.id;
 
-  String toString() =>
-      '[TypeArgumentsRef type: ${type}, id: ${id}, name: ${name}]';
+  String toString() => '[TypeArgumentsRef id: ${id}, name: ${name}]';
 }
 
 /// A `TypeArguments` object represents the type argument vector for some
 /// instantiated generic type.
 class TypeArguments extends Obj implements TypeArgumentsRef {
-  static TypeArguments parse(Map<String, dynamic> json) =>
+  static TypeArguments? parse(Map<String, dynamic>? json) =>
       json == null ? null : TypeArguments._fromJson(json);
 
   /// A name for this type argument list.
-  String name;
+  String? name;
 
   /// A list of types.
   ///
   /// The value will always be one of the kinds: Type, TypeRef, TypeParameter,
   /// BoundedType.
-  List<InstanceRef> types;
+  List<InstanceRef>? types;
 
   TypeArguments({
-    @required this.name,
-    @required this.types,
-    @required String id,
-  }) : super(id: id);
+    required this.name,
+    required this.types,
+    required String id,
+  }) : super(
+          id: id,
+        );
 
   TypeArguments._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
+    name = json['name'] ?? '';
     types = List<InstanceRef>.from(
-        createServiceObject(json['types'], const ['InstanceRef']) ?? []);
+        createServiceObject(json['types'], const ['InstanceRef']) as List? ??
+            []);
   }
 
   @override
+  String get type => 'TypeArguments';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = super.toJson();
-    json['type'] = 'TypeArguments';
+    final json = super.toJson();
+    json['type'] = type;
     json.addAll({
       'name': name,
-      'types': types.map((f) => f.toJson()).toList(),
+      'types': types?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
@@ -6986,7 +7256,7 @@
   operator ==(other) => other is TypeArguments && id == other.id;
 
   String toString() =>
-      '[TypeArguments type: ${type}, id: ${id}, name: ${name}, types: ${types}]';
+      '[TypeArguments id: ${id}, name: ${name}, types: ${types}]';
 }
 
 /// The `UnresolvedSourceLocation` class is used to refer to an unresolved
@@ -7000,32 +7270,32 @@
 /// The `column` field will only be present when the breakpoint was specified
 /// with a specific column number.
 class UnresolvedSourceLocation extends Response {
-  static UnresolvedSourceLocation parse(Map<String, dynamic> json) =>
+  static UnresolvedSourceLocation? parse(Map<String, dynamic>? json) =>
       json == null ? null : UnresolvedSourceLocation._fromJson(json);
 
   /// The script containing the source location if the script has been loaded.
   @optional
-  ScriptRef script;
+  ScriptRef? script;
 
   /// The uri of the script containing the source location if the script has yet
   /// to be loaded.
   @optional
-  String scriptUri;
+  String? scriptUri;
 
   /// An approximate token position for the source location. This may change
   /// when the location is resolved.
   @optional
-  int tokenPos;
+  int? tokenPos;
 
   /// An approximate line number for the source location. This may change when
   /// the location is resolved.
   @optional
-  int line;
+  int? line;
 
   /// An approximate column number for the source location. This may change when
   /// the location is resolved.
   @optional
-  int column;
+  int? column;
 
   UnresolvedSourceLocation({
     this.script,
@@ -7037,7 +7307,8 @@
 
   UnresolvedSourceLocation._fromJson(Map<String, dynamic> json)
       : super._fromJson(json) {
-    script = createServiceObject(json['script'], const ['ScriptRef']);
+    script =
+        createServiceObject(json['script'], const ['ScriptRef']) as ScriptRef?;
     scriptUri = json['scriptUri'];
     tokenPos = json['tokenPos'];
     line = json['line'];
@@ -7045,9 +7316,12 @@
   }
 
   @override
+  String get type => 'UnresolvedSourceLocation';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'UnresolvedSourceLocation';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     _setIfNotNull(json, 'script', script?.toJson());
     _setIfNotNull(json, 'scriptUri', scriptUri);
     _setIfNotNull(json, 'tokenPos', tokenPos);
@@ -7056,36 +7330,39 @@
     return json;
   }
 
-  String toString() => '[UnresolvedSourceLocation type: ${type}]';
+  String toString() => '[UnresolvedSourceLocation]';
 }
 
 /// See [Versioning].
 class Version extends Response {
-  static Version parse(Map<String, dynamic> json) =>
+  static Version? parse(Map<String, dynamic>? json) =>
       json == null ? null : Version._fromJson(json);
 
   /// The major version number is incremented when the protocol is changed in a
   /// potentially incompatible way.
-  int major;
+  int? major;
 
   /// The minor version number is incremented when the protocol is changed in a
   /// backwards compatible way.
-  int minor;
+  int? minor;
 
   Version({
-    @required this.major,
-    @required this.minor,
+    required this.major,
+    required this.minor,
   });
 
   Version._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    major = json['major'];
-    minor = json['minor'];
+    major = json['major'] ?? -1;
+    minor = json['minor'] ?? -1;
   }
 
   @override
+  String get type => 'Version';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'Version';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'major': major,
       'minor': minor,
@@ -7093,122 +7370,130 @@
     return json;
   }
 
-  String toString() =>
-      '[Version type: ${type}, major: ${major}, minor: ${minor}]';
+  String toString() => '[Version major: ${major}, minor: ${minor}]';
 }
 
 /// `VMRef` is a reference to a `VM` object.
 class VMRef extends Response {
-  static VMRef parse(Map<String, dynamic> json) =>
+  static VMRef? parse(Map<String, dynamic>? json) =>
       json == null ? null : VMRef._fromJson(json);
 
   /// A name identifying this vm. Not guaranteed to be unique.
-  String name;
+  String? name;
 
   VMRef({
-    @required this.name,
+    required this.name,
   });
 
   VMRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
+    name = json['name'] ?? '';
   }
 
   @override
+  String get type => '@VM';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = '@VM';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'name': name,
     });
     return json;
   }
 
-  String toString() => '[VMRef type: ${type}, name: ${name}]';
+  String toString() => '[VMRef name: ${name}]';
 }
 
 class VM extends Response implements VMRef {
-  static VM parse(Map<String, dynamic> json) =>
+  static VM? parse(Map<String, dynamic>? json) =>
       json == null ? null : VM._fromJson(json);
 
   /// A name identifying this vm. Not guaranteed to be unique.
-  String name;
+  String? name;
 
   /// Word length on target architecture (e.g. 32, 64).
-  int architectureBits;
+  int? architectureBits;
 
   /// The CPU we are actually running on.
-  String hostCPU;
+  String? hostCPU;
 
   /// The operating system we are running on.
-  String operatingSystem;
+  String? operatingSystem;
 
   /// The CPU we are generating code for.
-  String targetCPU;
+  String? targetCPU;
 
   /// The Dart VM version string.
-  String version;
+  String? version;
 
   /// The process id for the VM.
-  int pid;
+  int? pid;
 
   /// The time that the VM started in milliseconds since the epoch.
   ///
   /// Suitable to pass to DateTime.fromMillisecondsSinceEpoch.
-  int startTime;
+  int? startTime;
 
   /// A list of isolates running in the VM.
-  List<IsolateRef> isolates;
+  List<IsolateRef>? isolates;
 
   /// A list of isolate groups running in the VM.
-  List<IsolateGroupRef> isolateGroups;
+  List<IsolateGroupRef>? isolateGroups;
 
   /// A list of system isolates running in the VM.
-  List<IsolateRef> systemIsolates;
+  List<IsolateRef>? systemIsolates;
 
   /// A list of isolate groups which contain system isolates running in the VM.
-  List<IsolateGroupRef> systemIsolateGroups;
+  List<IsolateGroupRef>? systemIsolateGroups;
 
   VM({
-    @required this.name,
-    @required this.architectureBits,
-    @required this.hostCPU,
-    @required this.operatingSystem,
-    @required this.targetCPU,
-    @required this.version,
-    @required this.pid,
-    @required this.startTime,
-    @required this.isolates,
-    @required this.isolateGroups,
-    @required this.systemIsolates,
-    @required this.systemIsolateGroups,
+    required this.name,
+    required this.architectureBits,
+    required this.hostCPU,
+    required this.operatingSystem,
+    required this.targetCPU,
+    required this.version,
+    required this.pid,
+    required this.startTime,
+    required this.isolates,
+    required this.isolateGroups,
+    required this.systemIsolates,
+    required this.systemIsolateGroups,
   });
 
   VM._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
-    name = json['name'];
-    architectureBits = json['architectureBits'];
-    hostCPU = json['hostCPU'];
-    operatingSystem = json['operatingSystem'];
-    targetCPU = json['targetCPU'];
-    version = json['version'];
-    pid = json['pid'];
-    startTime = json['startTime'];
+    name = json['name'] ?? '';
+    architectureBits = json['architectureBits'] ?? -1;
+    hostCPU = json['hostCPU'] ?? '';
+    operatingSystem = json['operatingSystem'] ?? '';
+    targetCPU = json['targetCPU'] ?? '';
+    version = json['version'] ?? '';
+    pid = json['pid'] ?? -1;
+    startTime = json['startTime'] ?? -1;
     isolates = List<IsolateRef>.from(
-        createServiceObject(json['isolates'], const ['IsolateRef']) ?? []);
+        createServiceObject(json['isolates'], const ['IsolateRef']) as List? ??
+            []);
     isolateGroups = List<IsolateGroupRef>.from(
-        createServiceObject(json['isolateGroups'], const ['IsolateGroupRef']) ??
+        createServiceObject(json['isolateGroups'], const ['IsolateGroupRef'])
+                as List? ??
             []);
     systemIsolates = List<IsolateRef>.from(
-        createServiceObject(json['systemIsolates'], const ['IsolateRef']) ??
+        createServiceObject(json['systemIsolates'], const ['IsolateRef'])
+                as List? ??
             []);
     systemIsolateGroups = List<IsolateGroupRef>.from(createServiceObject(
-            json['systemIsolateGroups'], const ['IsolateGroupRef']) ??
+            json['systemIsolateGroups'], const ['IsolateGroupRef']) as List? ??
         []);
   }
 
   @override
+  String get type => 'VM';
+
+  @override
   Map<String, dynamic> toJson() {
-    var json = <String, dynamic>{};
-    json['type'] = 'VM';
+    final json = <String, dynamic>{};
+    json['type'] = type;
     json.addAll({
       'name': name,
       'architectureBits': architectureBits,
@@ -7218,11 +7503,11 @@
       'version': version,
       'pid': pid,
       'startTime': startTime,
-      'isolates': isolates.map((f) => f.toJson()).toList(),
-      'isolateGroups': isolateGroups.map((f) => f.toJson()).toList(),
-      'systemIsolates': systemIsolates.map((f) => f.toJson()).toList(),
+      'isolates': isolates?.map((f) => f.toJson()).toList(),
+      'isolateGroups': isolateGroups?.map((f) => f.toJson()).toList(),
+      'systemIsolates': systemIsolates?.map((f) => f.toJson()).toList(),
       'systemIsolateGroups':
-          systemIsolateGroups.map((f) => f.toJson()).toList(),
+          systemIsolateGroups?.map((f) => f.toJson()).toList(),
     });
     return json;
   }
diff --git a/pkg/vm_service/lib/utils.dart b/pkg/vm_service/lib/utils.dart
index dd6ffbc..9f65a66 100644
--- a/pkg/vm_service/lib/utils.dart
+++ b/pkg/vm_service/lib/utils.dart
@@ -2,12 +2,10 @@
 // for 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:meta/meta.dart';
-
 /// Map the URI to a WebSocket URI for the VM service protocol.
 ///
 /// If the URI is already a VM Service WebSocket URI it will not be modified.
-Uri convertToWebSocketUrl({@required Uri serviceProtocolUrl}) {
+Uri convertToWebSocketUrl({required Uri serviceProtocolUrl}) {
   final isSecure = serviceProtocolUrl.isScheme('wss') ||
       serviceProtocolUrl.isScheme('https');
   final scheme = isSecure ? 'wss' : 'ws';
diff --git a/pkg/vm_service/lib/vm_service_io.dart b/pkg/vm_service/lib/vm_service_io.dart
index 00597af..0db488b 100644
--- a/pkg/vm_service/lib/vm_service_io.dart
+++ b/pkg/vm_service/lib/vm_service_io.dart
@@ -8,7 +8,7 @@
 import 'vm_service.dart';
 
 @Deprecated('Prefer vmServiceConnectUri')
-Future<VmService> vmServiceConnect(String host, int port, {Log log}) async {
+Future<VmService> vmServiceConnect(String host, int port, {Log? log}) async {
   final WebSocket socket = await WebSocket.connect('ws://$host:$port/ws');
   final StreamController<dynamic> controller = StreamController();
   final Completer streamClosedCompleter = Completer();
@@ -28,7 +28,7 @@
 }
 
 /// Connect to the given uri and return a new [VmService] instance.
-Future<VmService> vmServiceConnectUri(String wsUri, {Log log}) async {
+Future<VmService> vmServiceConnectUri(String wsUri, {Log? log}) async {
   final WebSocket socket = await WebSocket.connect(wsUri);
   final StreamController<dynamic> controller = StreamController();
   final Completer streamClosedCompleter = Completer();
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 3b14073..fc44e80 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -2,21 +2,21 @@
 description: >-
   A library to communicate with a service implementing the Dart VM
   service protocol.
-version: 5.5.0
+
+version: 6.0.1-nullsafety.0
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
 
 environment:
-  sdk: '>=2.6.0 <3.0.0'
+  sdk: '>=2.12.0-0 <3.0.0'
 
 dependencies:
-  meta: ^1.0.2
 
 dev_dependencies:
-  async: ^2.0.0
-  markdown: ^2.0.0
-  mockito: ^4.0.0
-  path: ^1.0.0
-  pedantic: ^1.7.0
-  pub_semver: ^1.0.0
-  test: ^1.0.0
+  async: ^2.5.0-nullsafety.3
+  markdown: ^4.0.0-nullsafety.0
+  mockito: ^5.0.0-nullsafety.1
+  path: ^1.8.0-nullsafety.3
+  pedantic: ^1.10.0-nullsafety.3
+  pub_semver: ^2.0.0-nullsafety.0
+  test: ^1.16.0-nullsafety.13
diff --git a/pkg/vm_service/test/async_generator_breakpoint_test.dart b/pkg/vm_service/test/async_generator_breakpoint_test.dart
index e709594..d4c20a7 100644
--- a/pkg/vm_service/test/async_generator_breakpoint_test.dart
+++ b/pkg/vm_service/test/async_generator_breakpoint_test.dart
@@ -46,27 +46,30 @@
 }
 
 Future testAsync(VmService service, IsolateRef isolateRef) async {
-  final isolate = await service.getIsolate(isolateRef.id);
-  final Library lib = await service.getObject(isolate.id, isolate.rootLib.id);
-  final script = lib.scripts[0];
+  final isolateId = isolateRef.id!;
+  final isolate = await service.getIsolate(isolateId);
+  final Library lib =
+      (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library;
+  final script = lib.scripts![0];
+  final scriptId = script.id!;
 
-  final bp1 = await service.addBreakpoint(isolate.id, script.id, 11);
+  final bp1 = await service.addBreakpoint(isolateId, scriptId, 11);
   expect(bp1, isNotNull);
   expect(bp1 is Breakpoint, isTrue);
 
-  final bp2 = await service.addBreakpoint(isolate.id, script.id, 16);
+  final bp2 = await service.addBreakpoint(isolateId, scriptId, 16);
   expect(bp2, isNotNull);
   expect(bp2 is Breakpoint, isTrue);
 
-  final bp3 = await service.addBreakpoint(isolate.id, script.id, 21);
+  final bp3 = await service.addBreakpoint(isolateId, scriptId, 21);
   expect(bp3, isNotNull);
   expect(bp3 is Breakpoint, isTrue);
 
-  final bp4 = await service.addBreakpoint(isolate.id, script.id, 25);
+  final bp4 = await service.addBreakpoint(isolateId, scriptId, 25);
   expect(bp4, isNotNull);
   expect(bp4 is Breakpoint, isTrue);
 
-  final bp5 = await service.addBreakpoint(isolate.id, script.id, 42);
+  final bp5 = await service.addBreakpoint(isolateId, scriptId, 42);
   expect(bp5, isNotNull);
   expect(bp5 is Breakpoint, isTrue);
 
@@ -75,9 +78,9 @@
 
   // ignore: unawaited_futures
   service
-      .evaluate(isolate.id, lib.id, 'testerReady = true')
+      .evaluate(isolateId, lib.id!, 'testerReady = true')
       .then((Response result) async {
-    Obj res = await service.getObject(isolate.id, (result as InstanceRef).id);
+    Obj res = await service.getObject(isolateId, (result as InstanceRef).id!);
     print(res);
     expect((res as Instance).valueAsString, equals('true'));
   });
@@ -85,10 +88,10 @@
   final stream = service.onDebugEvent;
   await for (Event event in stream) {
     if (event.kind == EventKind.kPauseBreakpoint) {
-      assert(event.pauseBreakpoints.isNotEmpty);
-      final bp = event.pauseBreakpoints.first;
+      assert(event.pauseBreakpoints!.isNotEmpty);
+      final bp = event.pauseBreakpoints!.first;
       hits.add(bp);
-      await service.resume(isolate.id);
+      await service.resume(isolateId);
 
       if (hits.length == 5) break;
     }
diff --git a/pkg/vm_service/test/async_scope_test.dart b/pkg/vm_service/test/async_scope_test.dart
index 9573e69..5b8d262 100644
--- a/pkg/vm_service/test/async_scope_test.dart
+++ b/pkg/vm_service/test/async_scope_test.dart
@@ -34,20 +34,22 @@
 }
 
 Future<void> checkAsyncVarDescriptors(
-    VmService service, IsolateRef isolateRef) async {
-  final stack = await service.getStack(isolateRef.id);
-  expect(stack.frames.length, greaterThanOrEqualTo(1));
-  final frame = stack.frames[0];
-  final vars = frame.vars.map((v) => v.name).join(' ');
+    VmService? service, IsolateRef? isolateRef) async {
+  final isolateId = isolateRef!.id!;
+  final stack = await service!.getStack(isolateId);
+  expect(stack.frames!.length, greaterThanOrEqualTo(1));
+  final frame = stack.frames![0];
+  final vars = frame.vars!.map((v) => v.name).join(' ');
   expect(vars, 'param1 local1'); // no :async_op et al
 }
 
 Future checkAsyncStarVarDescriptors(
-    VmService service, IsolateRef isolateRef) async {
-  final stack = await service.getStack(isolateRef.id);
-  expect(stack.frames.length, greaterThanOrEqualTo(1));
-  final frame = stack.frames[0];
-  final vars = frame.vars.map((v) => v.name).join(' ');
+    VmService? service, IsolateRef? isolateRef) async {
+  final isolateId = isolateRef!.id!;
+  final stack = await service!.getStack(isolateId);
+  expect(stack.frames!.length, greaterThanOrEqualTo(1));
+  final frame = stack.frames![0];
+  final vars = frame.vars!.map((v) => v.name).join(' ');
   expect(vars, 'param2 local2'); // no :async_op et al
 }
 
diff --git a/pkg/vm_service/test/async_single_step_out_test.dart b/pkg/vm_service/test/async_single_step_out_test.dart
index a0a3d83..7e5f200 100644
--- a/pkg/vm_service/test/async_single_step_out_test.dart
+++ b/pkg/vm_service/test/async_single_step_out_test.dart
@@ -44,6 +44,10 @@
   stepInto, // exit helper via a single step.
 
   hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B), // await helper
+  stepInto,
+
+  hasStoppedAtBreakpoint,
   stoppedAtLine(20), // return null (weird dispatching)
   stepInto, // exit helper via a single step.
 
diff --git a/pkg/vm_service/test/common/service_test_common.dart b/pkg/vm_service/test/common/service_test_common.dart
index 56a6304..8277753 100644
--- a/pkg/vm_service/test/common/service_test_common.dart
+++ b/pkg/vm_service/test/common/service_test_common.dart
@@ -14,12 +14,11 @@
 
 Future<void> smartNext(VmService service, IsolateRef isolateRef) async {
   print('smartNext');
-  final isolate = await service.getIsolate(isolateRef.id);
-  if ((isolate.pauseEvent != null) &&
-      (isolate.pauseEvent.kind == EventKind.kPauseBreakpoint)) {
-    Event event = isolate.pauseEvent;
+  final isolate = await service.getIsolate(isolateRef.id!);
+  Event event = isolate.pauseEvent!;
+  if ((event.kind == EventKind.kPauseBreakpoint)) {
     // TODO(bkonyi): remove needless refetching of isolate object.
-    if (event?.atAsyncSuspension ?? false) {
+    if (event.atAsyncSuspension ?? false) {
       return asyncNext(service, isolateRef);
     } else {
       return syncNext(service, isolateRef);
@@ -31,14 +30,15 @@
 
 Future<void> asyncNext(VmService service, IsolateRef isolateRef) async {
   print('asyncNext');
-  final isolate = await service.getIsolate(isolateRef.id);
-  if ((isolate.pauseEvent != null) &&
-      (isolate.pauseEvent.kind == EventKind.kPauseBreakpoint)) {
+  final id = isolateRef.id!;
+  final isolate = await service.getIsolate(id);
+  final event = isolate.pauseEvent!;
+  if ((event.kind == EventKind.kPauseBreakpoint)) {
     dynamic event = isolate.pauseEvent;
     if (!event.atAsyncSuspension) {
       throw 'No async continuation at this location';
     } else {
-      return service.resume(isolateRef.id, step: 'OverAsyncSuspension');
+      await service.resume(id, step: 'OverAsyncSuspension');
     }
   } else {
     throw 'The program is already running';
@@ -47,10 +47,11 @@
 
 Future<void> syncNext(VmService service, IsolateRef isolateRef) async {
   print('syncNext');
-  final isolate = await service.getIsolate(isolateRef.id);
-  if ((isolate.pauseEvent != null) &&
-      (isolate.pauseEvent.kind == EventKind.kPauseBreakpoint)) {
-    return service.resume(isolate.id, step: 'Over');
+  final id = isolateRef.id!;
+  final isolate = await service.getIsolate(id);
+  final event = isolate.pauseEvent!;
+  if ((event.kind == EventKind.kPauseBreakpoint)) {
+    await service.resume(id, step: 'Over');
   } else {
     throw 'The program is already running';
   }
@@ -58,10 +59,10 @@
 
 Future<void> hasPausedFor(
     VmService service, IsolateRef isolateRef, String kind) async {
-  var completer = Completer();
-  var subscription;
+  Completer<dynamic>? completer = Completer();
+  late var subscription;
   subscription = service.onDebugEvent.listen((event) async {
-    if ((isolateRef.id == event.isolate.id) && (event.kind == kind)) {
+    if ((isolateRef.id == event.isolate!.id) && (event.kind == kind)) {
       if (completer != null) {
         try {
           await service.streamCancel(EventStreams.kDebug);
@@ -77,8 +78,10 @@
   await _subscribeDebugStream(service);
 
   // Pause may have happened before we subscribed.
-  final isolate = await service.getIsolate(isolateRef.id);
-  if ((isolate.pauseEvent != null) && (isolate.pauseEvent.kind == kind)) {
+  final id = isolateRef.id!;
+  final isolate = await service.getIsolate(id);
+  final event = isolate.pauseEvent!;
+  if ((event.kind == kind)) {
     if (completer != null) {
       try {
         await service.streamCancel(EventStreams.kDebug);
@@ -116,11 +119,13 @@
 IsolateTest setBreakpointAtLine(int line) {
   return (VmService service, IsolateRef isolateRef) async {
     print("Setting breakpoint for line $line");
-    final isolate = await service.getIsolate(isolateRef.id);
-    final Library lib = await service.getObject(isolate.id, isolate.rootLib.id);
-    final script = lib.scripts.first;
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final Library lib =
+        (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library;
+    final script = lib.scripts!.first;
 
-    Breakpoint bpt = await service.addBreakpoint(isolate.id, script.id, line);
+    Breakpoint bpt = await service.addBreakpoint(isolateId, script.id!, line);
     print("Breakpoint is $bpt");
   };
 }
@@ -130,26 +135,28 @@
     print("Checking we are at line $line");
 
     // Make sure that the isolate has stopped.
-    final isolate = await service.getIsolate(isolateRef.id);
-    expect(isolate.pauseEvent.kind != EventKind.kResume, isTrue);
+    final id = isolateRef.id!;
+    final isolate = await service.getIsolate(id);
+    final event = isolate.pauseEvent!;
+    expect(event.kind != EventKind.kResume, isTrue);
 
-    final stack = await service.getStack(isolateRef.id);
+    final stack = await service.getStack(id);
 
-    final frames = stack.frames;
+    final frames = stack.frames!;
     expect(frames.length, greaterThanOrEqualTo(1));
 
     final top = frames[0];
     final Script script =
-        await service.getObject(isolate.id, top.location.script.id);
-    int actualLine = script.getLineNumberFromTokenPos(top.location.tokenPos);
+        (await service.getObject(id, top.location!.script!.id!)) as Script;
+    int actualLine = script.getLineNumberFromTokenPos(top.location!.tokenPos!)!;
     if (actualLine != line) {
       print("Actual: $actualLine Line: $line");
       final sb = StringBuffer();
       sb.write("Expected to be at line $line but actually at line $actualLine");
       sb.write("\nFull stack trace:\n");
-      for (Frame f in stack.frames) {
+      for (Frame f in frames) {
         sb.write(
-            " $f [${script.getLineNumberFromTokenPos(f.location.tokenPos)}]\n");
+            " $f [${script.getLineNumberFromTokenPos(f.location!.tokenPos!)}]\n");
       }
       throw sb.toString();
     } else {
@@ -160,7 +167,7 @@
 
 Future<void> resumeIsolate(VmService service, IsolateRef isolate) async {
   Completer completer = Completer();
-  var subscription;
+  late var subscription;
   subscription = service.onDebugEvent.listen((event) async {
     if (event.kind == EventKind.kResume) {
       try {
@@ -172,7 +179,7 @@
     }
   });
   await service.streamListen(EventStreams.kDebug);
-  await service.resume(isolate.id);
+  await service.resume(isolate.id!);
   return completer.future;
 }
 
@@ -195,21 +202,21 @@
 Future<void> stepOver(VmService service, IsolateRef isolateRef) async {
   await service.streamListen(EventStreams.kDebug);
   await _subscribeDebugStream(service);
-  await service.resume(isolateRef.id, step: 'Over');
+  await service.resume(isolateRef.id!, step: 'Over');
   await hasStoppedAtBreakpoint(service, isolateRef);
   await _unsubscribeDebugStream(service);
 }
 
 Future<void> stepInto(VmService service, IsolateRef isolateRef) async {
   await _subscribeDebugStream(service);
-  await service.resume(isolateRef.id, step: 'Into');
+  await service.resume(isolateRef.id!, step: 'Into');
   await hasStoppedAtBreakpoint(service, isolateRef);
   await _unsubscribeDebugStream(service);
 }
 
 Future<void> stepOut(VmService service, IsolateRef isolateRef) async {
   await _subscribeDebugStream(service);
-  await service.resume(isolateRef.id, step: 'Out');
+  await service.resume(isolateRef.id!, step: 'Out');
   await hasStoppedAtBreakpoint(service, isolateRef);
   await _unsubscribeDebugStream(service);
 }
diff --git a/pkg/vm_service/test/common/test_helper.dart b/pkg/vm_service/test/common/test_helper.dart
index 48d5941..634ec64 100644
--- a/pkg/vm_service/test/common/test_helper.dart
+++ b/pkg/vm_service/test/common/test_helper.dart
@@ -18,8 +18,8 @@
 
 /// Will be set to the http address of the VM's service protocol before
 /// any tests are invoked.
-String serviceHttpAddress;
-String serviceWebsocketAddress;
+late String serviceHttpAddress;
+late String serviceWebsocketAddress;
 
 const String _TESTEE_ENV_KEY = 'SERVICE_TEST_TESTEE';
 const Map<String, String> _TESTEE_SPAWN_ENV = {_TESTEE_ENV_KEY: 'true'};
@@ -33,7 +33,7 @@
     // We'll need to parse the actual URI out...
     final fileRegExp = RegExp(r'file:\/\/\/.*\.dart');
     final path =
-        fileRegExp.stringMatch(io.Platform.script.data.contentAsString());
+        fileRegExp.stringMatch(io.Platform.script.data!.contentAsString());
     if (path == null) {
       throw 'Unable to determine file path for script!';
     }
@@ -45,8 +45,8 @@
 
 class _ServiceTesteeRunner {
   Future run(
-      {Function() testeeBefore,
-      Function() testeeConcurrent,
+      {Function()? testeeBefore,
+      Function()? testeeConcurrent,
       bool pause_on_start = false,
       bool pause_on_exit = false}) async {
     if (!pause_on_start) {
@@ -72,8 +72,8 @@
   }
 
   void runSync(
-      {void Function() testeeBeforeSync,
-      void Function() testeeConcurrentSync,
+      {void Function()? testeeBeforeSync,
+      void Function()? testeeConcurrentSync,
       bool pause_on_start = false,
       bool pause_on_exit = false}) {
     if (!pause_on_start) {
@@ -93,7 +93,7 @@
 }
 
 class _ServiceTesteeLauncher {
-  io.Process process;
+  io.Process? process;
   List<String> args;
   bool killedByTester = false;
 
@@ -106,13 +106,8 @@
     bool pause_on_unhandled_exceptions,
     bool testeeControlsServer,
     bool useAuthToken,
-    List<String> extraArgs,
+    List<String>? extraArgs,
   ) {
-    assert(pause_on_start != null);
-    assert(pause_on_exit != null);
-    assert(pause_on_unhandled_exceptions != null);
-    assert(testeeControlsServer != null);
-    assert(useAuthToken != null);
     return _spawnDartProcess(
         pause_on_start,
         pause_on_exit,
@@ -128,7 +123,7 @@
       bool pause_on_unhandled_exceptions,
       bool testeeControlsServer,
       bool useAuthToken,
-      List<String> extraArgs) {
+      List<String>? extraArgs) {
     String dartExecutable = io.Platform.executable;
 
     var fullArgs = <String>[
@@ -160,16 +155,14 @@
     return _spawnCommon(dartExecutable, fullArgs, <String, String>{});
   }
 
-  Future<io.Process> _spawnCommon(String executable, List<String> arguments,
-      Map<String, String> dartEnvironment) {
+  Future<io.Process> _spawnCommon(String executable,
+      List<String> /*!*/ arguments, Map<String, String> dartEnvironment) {
     var environment = _TESTEE_SPAWN_ENV;
     var bashEnvironment = StringBuffer();
     environment.forEach((k, v) => bashEnvironment.write("$k=$v "));
-    if (dartEnvironment != null) {
-      dartEnvironment.forEach((k, v) {
-        arguments.insert(0, '-D$k=$v');
-      });
-    }
+    dartEnvironment.forEach((k, v) {
+      arguments.insert(0, '-D$k=$v');
+    });
     print('** Launching $bashEnvironment$executable ${arguments.join(' ')}');
     return io.Process.start(executable, arguments, environment: environment);
   }
@@ -180,7 +173,7 @@
       bool pause_on_unhandled_exceptions,
       bool testeeControlsServer,
       bool useAuthToken,
-      List<String> extraArgs) {
+      List<String>? extraArgs) {
     return _spawnProcess(
             pause_on_start,
             pause_on_exit,
@@ -191,10 +184,10 @@
         .then((p) {
       Completer<Uri> completer = Completer<Uri>();
       process = p;
-      Uri uri;
+      Uri? uri;
       var blank;
       var first = true;
-      process.stdout
+      process!.stdout
           .transform(utf8.decoder)
           .transform(LineSplitter())
           .listen((line) {
@@ -214,15 +207,15 @@
         }
         io.stdout.write('>testee>out> ${line}\n');
       });
-      process.stderr
+      process!.stderr
           .transform(utf8.decoder)
           .transform(LineSplitter())
           .listen((line) {
         io.stdout.write('>testee>err> ${line}\n');
       });
-      process.exitCode.then((exitCode) {
+      process!.exitCode.then((exitCode) {
         if ((io.exitCode != 0) && !killedByTester) {
-          throw "Testee io.exited with $exitCode";
+          throw "Testee exited with $exitCode";
         }
         print("** Process exited");
       });
@@ -233,14 +226,14 @@
   void requestExit() {
     if (process != null) {
       print('** Killing script');
-      if (process.kill()) {
+      if (process!.kill()) {
         killedByTester = true;
       }
     }
   }
 }
 
-void setupAddresses(Uri serverAddress) {
+void setupAddresses(Uri /*!*/ serverAddress) {
   serviceWebsocketAddress =
       'ws://${serverAddress.authority}${serverAddress.path}ws';
   serviceHttpAddress = 'http://${serverAddress.authority}${serverAddress.path}';
@@ -248,10 +241,10 @@
 
 class _ServiceTesterRunner {
   Future run(
-      {List<String> mainArgs,
-      List<String> extraArgs,
-      List<VMTest> vmTests,
-      List<IsolateTest> isolateTests,
+      {List<String>? mainArgs,
+      List<String>? extraArgs,
+      List<VMTest>? vmTests,
+      List<IsolateTest>? isolateTests,
       bool pause_on_start = false,
       bool pause_on_exit = false,
       bool verbose_vm = false,
@@ -259,15 +252,15 @@
       bool testeeControlsServer = false,
       bool useAuthToken = false}) async {
     var process = _ServiceTesteeLauncher();
-    VmService vm;
-    IsolateRef isolate;
+    late VmService vm;
+    late IsolateRef isolate;
     setUp(() async {
       await process
           .launch(pause_on_start, pause_on_exit, pause_on_unhandled_exceptions,
               testeeControlsServer, useAuthToken, extraArgs)
           .then((Uri serverAddress) async {
-        if (mainArgs.contains("--gdb")) {
-          var pid = process.process.pid;
+        if (mainArgs!.contains("--gdb")) {
+          var pid = process.process!.pid;
           var wait = Duration(seconds: 10);
           print("Testee has pid $pid, waiting $wait before continuing");
           io.sleep(wait);
@@ -318,12 +311,12 @@
 
   Future<IsolateRef> getFirstIsolate(VmService service) async {
     var vm = await service.getVM();
-
-    if (vm.isolates.isNotEmpty) {
-      return vm.isolates.first;
+    final vmIsolates = vm.isolates!;
+    if (vmIsolates.isNotEmpty) {
+      return vmIsolates.first;
     }
-    var completer = Completer();
-    StreamSubscription subscription;
+    Completer<dynamic>? completer = Completer();
+    late StreamSubscription subscription;
     subscription = service.onIsolateEvent.listen((Event event) async {
       if (completer == null) {
         await subscription.cancel();
@@ -331,21 +324,21 @@
       }
       if (event.kind == EventKind.kIsolateRunnable) {
         vm = await service.getVM();
-        assert(vm.isolates.isNotEmpty);
+        assert(vmIsolates.isNotEmpty);
         await subscription.cancel();
-        completer.complete(vm.isolates.first);
+        completer!.complete(vmIsolates.first);
         completer = null;
       }
     });
 
     // The isolate may have started before we subscribed.
     vm = await service.getVM();
-    if (vm.isolates.isNotEmpty) {
+    if (vmIsolates.isNotEmpty) {
       await subscription.cancel();
-      completer.complete(vm.isolates.first);
+      completer!.complete(vmIsolates.first);
       completer = null;
     }
-    return await completer.future;
+    return await (completer!.future as FutureOr<IsolateRef>);
   }
 }
 
@@ -356,15 +349,15 @@
 Future<void> runIsolateTests(
   List<String> mainArgs,
   List<IsolateTest> tests, {
-  testeeBefore(),
-  testeeConcurrent(),
+  testeeBefore()?,
+  testeeConcurrent()?,
   bool pause_on_start = false,
   bool pause_on_exit = false,
   bool verbose_vm = false,
   bool pause_on_unhandled_exceptions = false,
   bool testeeControlsServer = false,
   bool useAuthToken = false,
-  List<String> extraArgs,
+  List<String>? extraArgs,
 }) async {
   assert(!pause_on_start || testeeBefore == null);
   if (_isTestee()) {
@@ -399,13 +392,13 @@
 void runIsolateTestsSynchronous(
   List<String> mainArgs,
   List<IsolateTest> tests, {
-  void testeeBefore(),
-  void testeeConcurrent(),
+  void testeeBefore()?,
+  void testeeConcurrent()?,
   bool pause_on_start = false,
   bool pause_on_exit = false,
   bool verbose_vm = false,
   bool pause_on_unhandled_exceptions = false,
-  List<String> extraArgs,
+  List<String>? extraArgs,
 }) {
   assert(!pause_on_start || testeeBefore == null);
   if (_isTestee()) {
@@ -433,13 +426,13 @@
 Future<void> runVMTests(
   List<String> mainArgs,
   List<VMTest> tests, {
-  testeeBefore(),
-  testeeConcurrent(),
+  testeeBefore()?,
+  testeeConcurrent()?,
   bool pause_on_start = false,
   bool pause_on_exit = false,
   bool verbose_vm = false,
   bool pause_on_unhandled_exceptions = false,
-  List<String> extraArgs,
+  List<String>? extraArgs,
 }) async {
   if (_isTestee()) {
     await _ServiceTesteeRunner().run(
diff --git a/pkg/vm_service/test/coverage_leaf_function_test.dart b/pkg/vm_service/test/coverage_leaf_function_test.dart
index eac959f..1e5146f 100644
--- a/pkg/vm_service/test/coverage_leaf_function_test.dart
+++ b/pkg/vm_service/test/coverage_leaf_function_test.dart
@@ -30,18 +30,19 @@
 var tests = <IsolateTest>[
   hasStoppedAtBreakpoint,
   (VmService service, IsolateRef isolateRef) async {
-    final isolate = await service.getIsolate(isolateRef.id);
-    final stack = await service.getStack(isolate.id);
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final stack = await service.getStack(isolateId);
 
     // Make sure we are in the right place.
-    expect(stack.frames.length, greaterThanOrEqualTo(1));
-    expect(stack.frames[0].function.name, 'testFunction');
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
+    expect(stack.frames![0].function!.name, 'testFunction');
 
     final Library root =
-        await service.getObject(isolate.id, isolate.rootLib.id);
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
     FuncRef funcRef =
-        root.functions.singleWhere((f) => f.name == 'leafFunction');
-    Func func = await service.getObject(isolate.id, funcRef.id) as Func;
+        root.functions!.singleWhere((f) => f.name == 'leafFunction');
+    Func func = await service.getObject(isolateId, funcRef.id!) as Func;
 
     final expectedRange = {
       'scriptIndex': 0,
@@ -53,33 +54,36 @@
         'misses': [397]
       }
     };
+    final location = func.location!;
 
     final report = await service.getSourceReport(
-        isolate.id, [SourceReportKind.kCoverage],
-        scriptId: func.location.script.id,
-        tokenPos: func.location.tokenPos,
-        endTokenPos: func.location.endTokenPos,
+        isolateId, [SourceReportKind.kCoverage],
+        scriptId: location.script!.id,
+        tokenPos: location.tokenPos,
+        endTokenPos: location.endTokenPos,
         forceCompile: true);
-    expect(report.ranges.length, 1);
-    expect(report.ranges[0].toJson(), expectedRange);
-    expect(report.scripts.length, 1);
-    expect(report.scripts[0].uri, endsWith('coverage_leaf_function_test.dart'));
+    expect(report.ranges!.length, 1);
+    expect(report.ranges![0].toJson(), expectedRange);
+    expect(report.scripts!.length, 1);
+    expect(
+        report.scripts![0].uri, endsWith('coverage_leaf_function_test.dart'));
   },
   resumeIsolate,
   hasStoppedAtBreakpoint,
   (VmService service, IsolateRef isolateRef) async {
-    final isolate = await service.getIsolate(isolateRef.id);
-    final stack = await service.getStack(isolate.id);
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final stack = await service.getStack(isolateId);
 
     // Make sure we are in the right place.
-    expect(stack.frames.length, greaterThanOrEqualTo(1));
-    expect(stack.frames[0].function.name, 'testFunction');
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
+    expect(stack.frames![0].function!.name, 'testFunction');
 
     final Library root =
-        await service.getObject(isolate.id, isolate.rootLib.id);
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
     FuncRef funcRef =
-        root.functions.singleWhere((f) => f.name == 'leafFunction');
-    Func func = await service.getObject(isolate.id, funcRef.id) as Func;
+        root.functions!.singleWhere((f) => f.name == 'leafFunction');
+    Func func = await service.getObject(isolateId, funcRef.id!) as Func;
 
     var expectedRange = {
       'scriptIndex': 0,
@@ -92,16 +96,18 @@
       }
     };
 
+    final location = func.location!;
     final report = await service.getSourceReport(
-        isolate.id, [SourceReportKind.kCoverage],
-        scriptId: func.location.script.id,
-        tokenPos: func.location.tokenPos,
-        endTokenPos: func.location.endTokenPos,
+        isolateId, [SourceReportKind.kCoverage],
+        scriptId: location.script!.id,
+        tokenPos: location.tokenPos,
+        endTokenPos: location.endTokenPos,
         forceCompile: true);
-    expect(report.ranges.length, 1);
-    expect(report.ranges[0].toJson(), expectedRange);
-    expect(report.scripts.length, 1);
-    expect(report.scripts[0].uri, endsWith('coverage_leaf_function_test.dart'));
+    expect(report.ranges!.length, 1);
+    expect(report.ranges![0].toJson(), expectedRange);
+    expect(report.scripts!.length, 1);
+    expect(
+        report.scripts![0].uri, endsWith('coverage_leaf_function_test.dart'));
   },
 ];
 
diff --git a/pkg/vm_service/test/debugging_test.dart b/pkg/vm_service/test/debugging_test.dart
index d5c1b9e..615dfc2 100644
--- a/pkg/vm_service/test/debugging_test.dart
+++ b/pkg/vm_service/test/debugging_test.dart
@@ -25,14 +25,15 @@
 }
 
 int getLineNumberFromTokenPos(Script s, int token) =>
-    s.tokenPosTable[token].first;
+    s.tokenPosTable![token].first;
 
 var tests = <IsolateTest>[
 // Pause
-  (VmService service, IsolateRef isolateRef) async {
+  (VmService? service, IsolateRef? isolateRef) async {
+    final isolateId = isolateRef!.id!;
     Completer completer = Completer();
-    var stream = service.onDebugEvent;
-    var subscription;
+    var stream = service!.onDebugEvent;
+    late var subscription;
     subscription = stream.listen((Event event) {
       if (event.kind == EventKind.kPauseInterrupted) {
         subscription.cancel();
@@ -40,16 +41,17 @@
       }
     });
     await service.streamListen(EventStreams.kDebug);
-    await service.pause(isolateRef.id);
+    await service.pause(isolateId);
     await completer.future;
     await service.streamCancel(EventStreams.kDebug);
   },
 
 // Resume
   (VmService service, IsolateRef isolate) async {
+    final isolateId = isolate.id!;
     Completer completer = Completer();
     var stream = service.onDebugEvent;
-    var subscription;
+    late var subscription;
     subscription = stream.listen((Event event) {
       if (event.kind == EventKind.kResume) {
         subscription.cancel();
@@ -57,21 +59,22 @@
       }
     });
     await service.streamListen(EventStreams.kDebug);
-    await service.resume(isolate.id);
+    await service.resume(isolateId);
     await completer.future;
     await service.streamCancel(EventStreams.kDebug);
   },
 
 // Add breakpoint
   (VmService service, IsolateRef isolateRef) async {
-    Isolate isolate = await service.getIsolate(isolateRef.id);
+    final isolateId = isolateRef.id!;
+    Isolate isolate = await service.getIsolate(isolateId);
     final Library rootLib =
-        await service.getObject(isolate.id, isolate.rootLib.id);
+        (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library;
 
     // Set up a listener to wait for breakpoint events.
     Completer completer = Completer();
     var stream = service.onDebugEvent;
-    var subscription;
+    late var subscription;
     subscription = stream.listen((Event event) {
       if (event.kind == EventKind.kPauseBreakpoint) {
         print('Breakpoint reached');
@@ -80,30 +83,32 @@
       }
     });
     await service.streamListen(EventStreams.kDebug);
-    final Script script =
-        await service.getObject(isolate.id, rootLib.scripts.first.id);
+    final Script script = (await service.getObject(
+        isolateId, rootLib.scripts!.first.id!)) as Script;
     // Add the breakpoint.
     final Breakpoint bpt =
-        await service.addBreakpoint(isolate.id, script.id, 16);
+        await service.addBreakpoint(isolateId, script.id!, 16);
     final SourceLocation location = bpt.location;
-    expect(location.script.id, script.id);
-    expect(script.getLineNumberFromTokenPos(location.tokenPos), 16);
+    expect(location.script!.id, script.id);
+    expect(script.getLineNumberFromTokenPos(location.tokenPos!), 16);
 
-    isolate = await service.getIsolate(isolate.id);
-    expect(isolate.breakpoints.length, 1);
+    isolate = await service.getIsolate(isolateId);
+    expect(isolate.breakpoints!.length, 1);
 
     await completer.future; // Wait for breakpoint events.
     await service.streamCancel(EventStreams.kDebug);
   },
 // We are at the breakpoint on line 16.
   (VmService service, IsolateRef isolateRef) async {
-    final stack = await service.getStack(isolateRef.id);
-    expect(stack.frames.length, greaterThanOrEqualTo(1));
+    final isolateId = isolateRef.id!;
+    final stack = await service.getStack(isolateId);
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
 
-    Script script = await service.getObject(
-        isolateRef.id, stack.frames[0].location.script.id);
+    Script script = (await service.getObject(
+        isolateId, stack.frames![0].location!.script!.id!)) as Script;
     expect(script.uri, endsWith('debugging_test.dart'));
-    expect(script.getLineNumberFromTokenPos(stack.frames[0].location.tokenPos),
+    expect(
+        script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
         16);
   },
 
@@ -112,7 +117,7 @@
     // Set up a listener to wait for breakpoint events.
     final completer = Completer();
     var stream = service.onDebugEvent;
-    var subscription;
+    late var subscription;
     subscription = stream.listen((Event event) {
       if (event.kind == EventKind.kPauseBreakpoint) {
         print('Breakpoint reached');
@@ -128,36 +133,39 @@
   },
 // We are now at line 17.
   (VmService service, IsolateRef isolateRef) async {
-    final stack = await service.getStack(isolateRef.id);
-    expect(stack.frames.length, greaterThanOrEqualTo(1));
+    final isolateId = isolateRef.id!;
+    final stack = await service.getStack(isolateId);
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
 
-    final Script script = await service.getObject(
-        isolateRef.id, stack.frames[0].location.script.id);
+    final Script script = (await service.getObject(
+        isolateId, stack.frames![0].location!.script!.id!)) as Script;
     expect(script.uri, endsWith('debugging_test.dart'));
-    expect(script.getLineNumberFromTokenPos(stack.frames[0].location.tokenPos),
+    expect(
+        script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
         17);
   },
 // Remove breakpoint
   (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id!;
     // Set up a listener to wait for breakpoint events.
     final completer = Completer();
     var stream = service.onDebugEvent;
-    var subscription;
+    late var subscription;
     subscription = stream.listen((Event event) async {
       if (event.kind == EventKind.kBreakpointRemoved) {
         print('Breakpoint removed');
-        final isolate = await service.getIsolate(isolateRef.id);
-        expect(isolate.breakpoints.length, 0);
+        final isolate = await service.getIsolate(isolateId);
+        expect(isolate.breakpoints!.length, 0);
         subscription.cancel();
         completer.complete();
       }
     });
 
-    final Isolate isolate = await service.getIsolate(isolateRef.id);
-    expect(isolate.breakpoints.length, 1);
-    final bpt = isolate.breakpoints.first;
+    final Isolate isolate = await service.getIsolate(isolateId);
+    expect(isolate.breakpoints!.length, 1);
+    final bpt = isolate.breakpoints!.first;
     await service.streamListen(EventStreams.kDebug);
-    await service.removeBreakpoint(isolate.id, bpt.id);
+    await service.removeBreakpoint(isolateId, bpt.id!);
     await completer.future;
     await service.streamCancel(EventStreams.kDebug);
   },
@@ -165,7 +173,7 @@
   (VmService service, IsolateRef isolate) async {
     final completer = Completer();
     var stream = service.onDebugEvent;
-    var subscription;
+    late var subscription;
     subscription = stream.listen((Event event) {
       if (event.kind == EventKind.kResume) {
         subscription.cancel();
@@ -177,11 +185,12 @@
   },
 // Add breakpoint at function entry
   (VmService service, IsolateRef isolateRef) async {
-    Isolate isolate = await service.getIsolate(isolateRef.id);
+    final isolateId = isolateRef.id!;
+    Isolate isolate = await service.getIsolate(isolateId);
     // Set up a listener to wait for breakpoint events.
     final completer = Completer();
     var stream = service.onDebugEvent;
-    var subscription;
+    late var subscription;
     subscription = stream.listen((Event event) {
       if (event.kind == EventKind.kPauseBreakpoint) {
         print('Breakpoint reached');
@@ -192,35 +201,37 @@
 
     await service.streamListen(EventStreams.kDebug);
     final Library rootLib =
-        await service.getObject(isolate.id, isolate.rootLib.id);
+        (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library;
 
     // Find a specific function.
     final FuncRef function =
-        rootLib.functions.firstWhere((f) => f.name == 'periodicTask');
+        rootLib.functions!.firstWhere((f) => f.name == 'periodicTask');
     expect(function, isNotNull);
 
     // Add the breakpoint at function entry
-    final bpt = await service.addBreakpointAtEntry(isolate.id, function.id);
+    final bpt = await service.addBreakpointAtEntry(isolateId, function.id!);
     final Script script =
-        await service.getObject(isolate.id, bpt.location.script.id);
+        (await service.getObject(isolateId, bpt.location.script.id)) as Script;
     expect(script.uri, endsWith('debugging_test.dart'));
     expect(script.getLineNumberFromTokenPos(bpt.location.tokenPos), 14);
 
     // Refresh isolate state.
-    isolate = await service.getIsolate(isolate.id);
-    expect(isolate.breakpoints.length, 1);
+    isolate = await service.getIsolate(isolateId);
+    expect(isolate.breakpoints!.length, 1);
 
     await completer.future; // Wait for breakpoint events.
   },
 // We are now at line 14.
   (VmService service, IsolateRef isolateRef) async {
-    final stack = await service.getStack(isolateRef.id);
-    expect(stack.frames.length, greaterThanOrEqualTo(1));
+    final isolateId = isolateRef.id!;
+    final stack = await service.getStack(isolateId);
+    expect(stack.frames!.length, greaterThanOrEqualTo(1));
 
-    final Script script = await service.getObject(
-        isolateRef.id, stack.frames[0].location.script.id);
+    final Script script = (await service.getObject(
+        isolateId, stack.frames![0].location!.script!.id!)) as Script;
     expect(script.uri, endsWith('debugging_test.dart'));
-    expect(script.getLineNumberFromTokenPos(stack.frames[0].location.tokenPos),
+    expect(
+        script.getLineNumberFromTokenPos(stack.frames![0].location!.tokenPos!),
         14);
   },
 ];
diff --git a/pkg/vm_service/test/eval_test.dart b/pkg/vm_service/test/eval_test.dart
index ba30330..5be029f 100644
--- a/pkg/vm_service/test/eval_test.dart
+++ b/pkg/vm_service/test/eval_test.dart
@@ -39,54 +39,56 @@
 
 // Evaluate against library, class, and instance.
   (VmService service, IsolateRef isolateRef) async {
-    final isolate = await service.getIsolate(isolateRef.id);
-    final stack = await service.getStack(isolateRef.id);
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final stack = await service.getStack(isolateId);
 
     // Make sure we are in the right place.
-    expect(stack.frames.length, greaterThanOrEqualTo(2));
-    expect(stack.frames[0].function.name, 'method');
-    expect((stack.frames[0].function.owner as ClassRef).name, 'MyClass');
+    expect(stack.frames!.length, greaterThanOrEqualTo(2));
+    expect(stack.frames![0].function!.name, 'method');
+    expect((stack.frames![0].function!.owner as ClassRef).name, 'MyClass');
 
-    final LibraryRef lib = isolate.rootLib;
-    final ClassRef cls = stack.frames[0].function.owner;
-    final InstanceRef instance = stack.frames[0].vars[0].value;
+    final LibraryRef lib = isolate.rootLib!;
+    final ClassRef cls = stack.frames![0].function!.owner;
+    final InstanceRef instance = stack.frames![0].vars![0].value;
 
     dynamic result =
-        await service.evaluate(isolate.id, lib.id, 'globalVar + 5');
+        await service.evaluate(isolateId, lib.id!, 'globalVar + 5');
     print(result);
     expect(result.valueAsString, '105');
 
     await expectError(() =>
-        service.evaluate(isolate.id, lib.id, 'globalVar + staticVar + 5'));
+        service.evaluate(isolateId, lib.id!, 'globalVar + staticVar + 5'));
 
     result =
-        await service.evaluate(isolate.id, cls.id, 'globalVar + staticVar + 5');
+        await service.evaluate(isolateId, cls.id!, 'globalVar + staticVar + 5');
     print(result);
     expect(result.valueAsString, '1105');
 
-    await expectError(() => service.evaluate(isolate.id, cls.id, 'this + 5'));
+    await expectError(() => service.evaluate(isolateId, cls.id!, 'this + 5'));
 
-    result = await service.evaluate(isolate.id, instance.id, 'this + 5');
+    result = await service.evaluate(isolateId, instance.id!, 'this + 5');
     print(result);
     expect(result.valueAsString, '10005');
 
     await expectError(
-        () => service.evaluate(isolate.id, instance.id, 'this + frog'));
+        () => service.evaluate(isolateId, instance.id!, 'this + frog'));
   },
   resumeIsolate,
   hasStoppedAtBreakpoint,
   (VmService service, IsolateRef isolate) async {
-    final stack = await service.getStack(isolate.id);
+    final isolateId = isolate.id!;
+    final stack = await service.getStack(isolateId);
 
     // Make sure we are in the right place.
-    expect(stack.frames.length, greaterThanOrEqualTo(2));
-    expect(stack.frames[0].function.name, 'foo');
-    expect((stack.frames[0].function.owner as ClassRef).name, '_MyClass');
+    expect(stack.frames!.length, greaterThanOrEqualTo(2));
+    expect(stack.frames![0].function!.name, 'foo');
+    expect((stack.frames![0].function!.owner as ClassRef).name, '_MyClass');
 
-    final ClassRef cls = stack.frames[0].function.owner;
+    final ClassRef cls = stack.frames![0].function!.owner;
 
     final InstanceRef result =
-        await service.evaluate(isolate.id, cls.id, "1+1");
+        await service.evaluate(isolateId, cls.id!, "1+1") as InstanceRef;
     print(result);
     expect(result.valueAsString, "2");
   }
diff --git a/pkg/vm_service/test/evaluate_with_scope_test.dart b/pkg/vm_service/test/evaluate_with_scope_test.dart
index 8dfd4d4..54e8979 100644
--- a/pkg/vm_service/test/evaluate_with_scope_test.dart
+++ b/pkg/vm_service/test/evaluate_with_scope_test.dart
@@ -6,29 +6,34 @@
 import 'package:test/test.dart';
 import 'common/test_helper.dart';
 
-int thing1;
-int thing2;
+int? thing1;
+int? thing2;
 
 testeeMain() {
   thing1 = 3;
   thing2 = 4;
 }
 
-Future evaluate(VmService service, isolate, target, x, y) async => await service
-    .evaluate(isolate.id, target.id, 'x + y', scope: {'x': x.id, 'y': y.id});
+Future evaluate(VmService service, isolate, target, x, y) async =>
+    await service.evaluate(isolate!.id!!, target.id!, 'x + y',
+        scope: {'x': x.id!, 'y': y.id!});
 
 final tests = <IsolateTest>[
   (VmService service, IsolateRef isolateRef) async {
-    final isolate = await service.getIsolate(isolateRef.id);
-    final Library lib = await service.getObject(isolate.id, isolate.rootLib.id);
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final Library lib =
+        (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library;
 
-    final Field field1 = await service.getObject(
-        isolate.id, lib.variables.singleWhere((v) => v.name == 'thing1').id);
-    final thing1 = (await service.getObject(isolate.id, field1.staticValue.id));
+    final Field field1 = (await service.getObject(isolateId,
+        lib.variables!.singleWhere((v) => v.name == 'thing1').id!)) as Field;
+    final thing1 =
+        (await service.getObject(isolateId, field1.staticValue!.id!));
 
-    final Field field2 = await service.getObject(
-        isolate.id, lib.variables.singleWhere((v) => v.name == 'thing2').id);
-    final thing2 = (await service.getObject(isolate.id, field2.staticValue.id));
+    final Field field2 = (await service.getObject(isolateId,
+        lib.variables!.singleWhere((v) => v.name == 'thing2').id!)) as Field;
+    final thing2 =
+        (await service.getObject(isolateId, field2.staticValue!.id!));
 
     var result = await evaluate(service, isolate, lib, thing1, thing2);
     expect(result.valueAsString, equals('7'));
@@ -46,8 +51,8 @@
 
     didThrow = false;
     try {
-      result = await service.evaluate(isolate.id, lib.id, "x + y",
-          scope: <String, String>{"not&an&identifier": thing1.id});
+      result = await service.evaluate(isolateId, lib.id!, "x + y",
+          scope: <String, String>{"not&an&id!entifier": thing1.id!});
       print(result);
     } catch (e) {
       didThrow = true;
diff --git a/pkg/vm_service/test/file_service_test.dart b/pkg/vm_service/test/file_service_test.dart
index c74fdae..045ba1e 100644
--- a/pkg/vm_service/test/file_service_test.dart
+++ b/pkg/vm_service/test/file_service_test.dart
@@ -71,16 +71,17 @@
 
 var fileTests = <IsolateTest>[
   (VmService service, IsolateRef isolate) async {
+    final isolateId = isolate.id!;
     await service.callServiceExtension(
       'ext.dart.io.setup',
       isolateId: isolate.id,
     );
     try {
-      final result = await service.getOpenFiles(isolate.id);
+      final result = await service.getOpenFiles(isolateId);
       expect(result, isA<OpenFileList>());
       expect(result.files.length, equals(2));
       final writing = await service.getOpenFileById(
-        isolate.id,
+        isolateId,
         result.files[0].id,
       );
 
@@ -92,7 +93,7 @@
       expect(writing.lastReadTime.millisecondsSinceEpoch, 0);
 
       final reading = await service.getOpenFileById(
-        isolate.id,
+        isolateId,
         result.files[1].id,
       );
       expect(reading.readBytes, 5);
diff --git a/pkg/vm_service/test/get_allocation_profile_rpc_test.dart b/pkg/vm_service/test/get_allocation_profile_rpc_test.dart
index c4540e5..4ce9675 100644
--- a/pkg/vm_service/test/get_allocation_profile_rpc_test.dart
+++ b/pkg/vm_service/test/get_allocation_profile_rpc_test.dart
@@ -12,25 +12,27 @@
 
 var tests = <IsolateTest>[
   (VmService service, IsolateRef isolate) async {
-    AllocationProfile result = await service.getAllocationProfile(isolate.id);
+    final isolateId = isolate.id!;
+
+    AllocationProfile result = await service.getAllocationProfile(isolateId);
     expect(result.dateLastAccumulatorReset, isNull);
     expect(result.dateLastServiceGC, isNull);
-    expect(result.members.length, isPositive);
+    expect(result.members!.length, isPositive);
 
-    ClassHeapStats member = result.members[0];
+    ClassHeapStats member = result.members![0];
     expect(member.instancesAccumulated, isNotNull);
     expect(member.instancesCurrent, isNotNull);
     expect(member.bytesCurrent, isNotNull);
     expect(member.accumulatedSize, isNotNull);
 
     // reset.
-    result = await service.getAllocationProfile(isolate.id, reset: true);
+    result = await service.getAllocationProfile(isolateId, reset: true);
     final firstReset = result.dateLastAccumulatorReset;
     expect(firstReset, isNotNull);
     expect(result.dateLastServiceGC, isNull);
-    expect(result.members.length, isPositive);
+    expect(result.members!.length, isPositive);
 
-    member = result.members[0];
+    member = result.members![0];
     expect(member.instancesAccumulated, isNotNull);
     expect(member.instancesCurrent, isNotNull);
     expect(member.bytesCurrent, isNotNull);
@@ -38,18 +40,18 @@
 
     await sleep(1000);
 
-    result = await service.getAllocationProfile(isolate.id, reset: true);
+    result = await service.getAllocationProfile(isolateId, reset: true);
     final secondReset = result.dateLastAccumulatorReset;
     expect(secondReset, isNot(firstReset));
 
     // gc.
-    result = await service.getAllocationProfile(isolate.id, gc: true);
+    result = await service.getAllocationProfile(isolateId, gc: true);
     expect(result.dateLastAccumulatorReset, secondReset);
     final firstGC = result.dateLastServiceGC;
     expect(firstGC, isNotNull);
-    expect(result.members.length, isPositive);
+    expect(result.members!.length, isPositive);
 
-    member = result.members[0];
+    member = result.members![0];
     expect(member.instancesAccumulated, isNotNull);
     expect(member.instancesCurrent, isNotNull);
     expect(member.bytesCurrent, isNotNull);
@@ -57,7 +59,7 @@
 
     await sleep(1000);
 
-    result = await service.getAllocationProfile(isolate.id, gc: true);
+    result = await service.getAllocationProfile(isolateId, gc: true);
     final secondGC = result.dateLastAccumulatorReset;
     expect(secondGC, isNot(firstGC));
   },
diff --git a/pkg/vm_service/test/get_cpu_samples_rpc_test.dart b/pkg/vm_service/test/get_cpu_samples_rpc_test.dart
index 8b9b143..95d8c85 100644
--- a/pkg/vm_service/test/get_cpu_samples_rpc_test.dart
+++ b/pkg/vm_service/test/get_cpu_samples_rpc_test.dart
@@ -22,15 +22,16 @@
 
 Future checkSamples(VmService service, IsolateRef isolate) async {
   // Grab all the samples.
-  final result = await service.getCpuSamples(isolate.id, 0, ~0);
+  final isolateId = isolate.id!;
+  final result = await service.getCpuSamples(isolateId, 0, ~0);
 
   final isString = TypeMatcher<String>();
   final isInt = TypeMatcher<int>();
   final isList = TypeMatcher<List>();
-  expect(result.functions.length, greaterThan(10),
-      reason: "Should have many functions");
+  expect(result.functions!.length, greaterThan(10),
+      reason: "Should have many functions!");
 
-  final samples = result.samples;
+  final samples = result.samples!;
   expect(samples.length, greaterThan(10), reason: "Should have many samples");
   expect(samples.length, result.sampleCount);
 
@@ -47,7 +48,7 @@
 }
 
 var tests = <IsolateTest>[
-  (VmService service, IsolateRef i) => checkSamples(service, i),
+  ((VmService service, IsolateRef i) => checkSamples(service, i)),
 ];
 
 var vmArgs = [
diff --git a/pkg/vm_service/test/get_flag_list_rpc_test.dart b/pkg/vm_service/test/get_flag_list_rpc_test.dart
index 8b6c337..1fba955 100644
--- a/pkg/vm_service/test/get_flag_list_rpc_test.dart
+++ b/pkg/vm_service/test/get_flag_list_rpc_test.dart
@@ -11,7 +11,7 @@
 
 Future getFlagValue(VmService service, String flagName) async {
   final result = await service.getFlagList();
-  final flags = result.flags;
+  final flags = result.flags!;
   for (final flag in flags) {
     if (flag.name == flagName) {
       return flag.valueAsString;
@@ -22,14 +22,15 @@
 var tests = <VMTest>[
   // Modify a flag which does not exist.
   (VmService service) async {
-    final Error result = await service.setFlag('does_not_exist', 'true');
+    final Error result =
+        (await service.setFlag('does_not_exist', 'true')) as Error;
     expect(result.message, 'Cannot set flag: flag not found');
   },
 
   // Modify a flag with the wrong value type.
   (VmService service) async {
-    final Error result =
-        await service.setFlag('pause_isolates_on_start', 'not-boolean');
+    final Error result = (await service.setFlag(
+        'pause_isolates_on_start', 'not-boolean')) as Error;
     expect(result.message, equals('Cannot set flag: invalid value'));
   },
 
@@ -41,7 +42,7 @@
 
   // Modify a flag which cannot be set at runtime.
   (VmService service) async {
-    final Error result = await service.setFlag('random_seed', '42');
+    final Error result = (await service.setFlag('random_seed', '42')) as Error;
     expect(result.message, 'Cannot set flag: cannot change at runtime');
   },
 
@@ -52,7 +53,7 @@
     expect(await getFlagValue(service, kProfilePeriod), '1000');
     final completer = Completer();
     final stream = await service.onVMEvent;
-    var subscription;
+    late var subscription;
     subscription = stream.listen((Event event) {
       print(event);
       if (event.kind == EventKind.kVMFlagUpdate) {
diff --git a/pkg/vm_service/test/get_isolate_group_memory_usage.dart b/pkg/vm_service/test/get_isolate_group_memory_usage.dart
index e6323a1..6ab44e5 100644
--- a/pkg/vm_service/test/get_isolate_group_memory_usage.dart
+++ b/pkg/vm_service/test/get_isolate_group_memory_usage.dart
@@ -11,13 +11,13 @@
   (VmService service) async {
     final vm = await service.getVM();
     final result =
-        await service.getIsolateGroupMemoryUsage(vm.isolateGroups.first.id);
+        await service.getIsolateGroupMemoryUsage(vm.isolateGroups!.first.id!);
     expect(result.heapUsage, isPositive);
     expect(result.heapCapacity, isPositive);
     expect(result.externalUsage, isNonNegative);
   },
   (VmService service) async {
-    bool caughtException;
+    bool? caughtException;
     try {
       await service.getMemoryUsage('badid');
       fail('Unreachable');
diff --git a/pkg/vm_service/test/get_isolate_rpc_test.dart b/pkg/vm_service/test/get_isolate_rpc_test.dart
index 6df4ec0..29e3d7a 100644
--- a/pkg/vm_service/test/get_isolate_rpc_test.dart
+++ b/pkg/vm_service/test/get_isolate_rpc_test.dart
@@ -10,28 +10,28 @@
 var tests = <VMTest>[
   (VmService service) async {
     final vm = await service.getVM();
-    final result = await service.getIsolate(vm.isolates.first.id);
+    final result = await service.getIsolate(vm.isolates!.first.id!);
     expect(result.id, startsWith('isolates/'));
     expect(result.number, isNotNull);
     expect(result.isolateFlags, isNotNull);
-    expect(result.isolateFlags.length, isPositive);
+    expect(result.isolateFlags!.length, isPositive);
     expect(result.isSystemIsolate, isFalse);
-    expect(result.json['_originNumber'], result.number);
+    expect(result.json!['_originNumber'], result.number);
     expect(result.startTime, isPositive);
     expect(result.livePorts, isPositive);
     expect(result.pauseOnExit, isFalse);
-    expect(result.pauseEvent.type, 'Event');
+    expect(result.pauseEvent!.type, 'Event');
     expect(result.error, isNull);
     expect(result.rootLib, isNotNull);
-    expect(result.libraries.length, isPositive);
-    expect(result.libraries[0], isNotNull);
-    expect(result.breakpoints.length, isZero);
-    expect(result.json['_heaps']['new']['type'], 'HeapSpace');
-    expect(result.json['_heaps']['old']['type'], 'HeapSpace');
+    expect(result.libraries!.length, isPositive);
+    expect(result.libraries![0], isNotNull);
+    expect(result.breakpoints!.length, isZero);
+    expect(result.json!['_heaps']['new']['type'], 'HeapSpace');
+    expect(result.json!['_heaps']['old']['type'], 'HeapSpace');
   },
 
   (VmService service) async {
-    bool caughtException;
+    bool caughtException = false;
     try {
       await service.getIsolate('badid');
       expect(false, isTrue, reason: 'Unreachable');
diff --git a/pkg/vm_service/test/get_memory_usage.dart b/pkg/vm_service/test/get_memory_usage.dart
index 76cac44..9325f59 100644
--- a/pkg/vm_service/test/get_memory_usage.dart
+++ b/pkg/vm_service/test/get_memory_usage.dart
@@ -10,13 +10,13 @@
 var tests = <VMTest>[
   (VmService service) async {
     final vm = await service.getVM();
-    final result = await service.getMemoryUsage(vm.isolates.first.id);
+    final result = await service.getMemoryUsage(vm.isolates!.first.id!);
     expect(result.heapUsage, isPositive);
     expect(result.heapCapacity, isPositive);
     expect(result.externalUsage, isPositive);
   },
   (VmService service) async {
-    bool caughtException;
+    bool? caughtException;
     try {
       await service.getMemoryUsage('badid');
       fail('Unreachable');
diff --git a/pkg/vm_service/test/get_stack_test.dart b/pkg/vm_service/test/get_stack_test.dart
index 5889996..f1ba6f1 100644
--- a/pkg/vm_service/test/get_stack_test.dart
+++ b/pkg/vm_service/test/get_stack_test.dart
@@ -53,7 +53,7 @@
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_A),
   (VmService service, IsolateRef isolateRef) async {
-    final result = await service.getStack(isolateRef.id);
+    final result = await service.getStack(isolateRef.id!);
 
     expect(result.frames, hasLength(16));
     expect(result.asyncCausalFrames, hasLength(16));
@@ -106,13 +106,13 @@
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_B),
   (VmService service, IsolateRef isolateRef) async {
-    final result = await service.getStack(isolateRef.id);
+    final result = await service.getStack(isolateRef.id!);
 
     expect(result.frames, hasLength(10));
     expect(result.asyncCausalFrames, hasLength(26));
     expect(result.awaiterFrames, hasLength(2));
 
-    expectFrames(result.frames, [
+    expectFrames(result.frames!, [
       [equals('Regular'), endsWith(' func10')],
       [equals('Regular'), endsWith(' _RootZone.runUnary')],
       [equals('Regular'), anything], // Internal mech. ..
diff --git a/pkg/vm_service/test/get_version_rpc_test.dart b/pkg/vm_service/test/get_version_rpc_test.dart
index 130bf21..3cfedda 100644
--- a/pkg/vm_service/test/get_version_rpc_test.dart
+++ b/pkg/vm_service/test/get_version_rpc_test.dart
@@ -10,8 +10,8 @@
 var tests = <VMTest>[
   (VmService vm) async {
     final result = await vm.getVersion();
-    expect(result.major > 0, isTrue);
-    expect(result.minor >= 0, isTrue);
+    expect(result.major! > 0, isTrue);
+    expect(result.minor! >= 0, isTrue);
   },
 ];
 
diff --git a/pkg/vm_service/test/heap_snapshot_graph_test.dart b/pkg/vm_service/test/heap_snapshot_graph_test.dart
index 7b035cc..b9fbe10 100644
--- a/pkg/vm_service/test/heap_snapshot_graph_test.dart
+++ b/pkg/vm_service/test/heap_snapshot_graph_test.dart
@@ -13,9 +13,9 @@
   dynamic right;
 }
 
-Foo r;
+late Foo r;
 
-List lst;
+late List lst;
 
 void script() {
   // Create 3 instances of Foo, with out-degrees
diff --git a/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart b/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
index 10157d5..2bbc902 100644
--- a/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
+++ b/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
@@ -24,12 +24,12 @@
     VmService service, IsolateRef isolateRef, bool state,
     {bool useSetter = true}) async {
   final completer = Completer<void>();
-  final isolateId = isolateRef.id;
-  StreamSubscription sub;
+  final isolateId = isolateRef.id!;
+  late StreamSubscription sub;
   sub = service.onExtensionEvent.listen((event) {
     expect(event.extensionKind, 'HttpTimelineLoggingStateChange');
-    expect(event.extensionData.data['isolateId'], isolateRef.id);
-    expect(event.extensionData.data['enabled'], state);
+    expect(event.extensionData!.data['isolateId'], isolateRef.id);
+    expect(event.extensionData!.data['enabled'], state);
     sub.cancel();
     completer.complete();
   });
@@ -47,17 +47,17 @@
 
 var tests = <IsolateTest>[
   (VmService service, IsolateRef isolateRef) async {
-    final isolate = await service.getIsolate(isolateRef.id);
+    final isolate = await service.getIsolate(isolateRef.id!);
     // Ensure all HTTP service extensions are registered.
-    expect(isolate.extensionRPCs.length, greaterThanOrEqualTo(2));
+    expect(isolate.extensionRPCs!.length, greaterThanOrEqualTo(2));
     expect(
-        isolate.extensionRPCs.contains(kGetHttpEnableTimelineLogging), isTrue);
+        isolate.extensionRPCs!.contains(kGetHttpEnableTimelineLogging), isTrue);
     expect(
-        isolate.extensionRPCs.contains(kSetHttpEnableTimelineLogging), isTrue);
-    expect(isolate.extensionRPCs.contains(kHttpEnableTimelineLogging), isTrue);
+        isolate.extensionRPCs!.contains(kSetHttpEnableTimelineLogging), isTrue);
+    expect(isolate.extensionRPCs!.contains(kHttpEnableTimelineLogging), isTrue);
   },
   (VmService service, IsolateRef isolateRef) async {
-    final isolateId = isolateRef.id;
+    final isolateId = isolateRef.id!;
     // ignore: deprecated_member_use_from_same_package
     dynamic response = await service.getHttpEnableTimelineLogging(isolateId);
     expect(response.enabled, false);
@@ -73,7 +73,7 @@
     expect(response.enabled, false);
   },
   (VmService service, IsolateRef isolateRef) async {
-    final isolateId = isolateRef.id;
+    final isolateId = isolateRef.id!;
     dynamic response = await service.httpEnableTimelineLogging(isolateId, null);
     expect(response.enabled, false);
 
diff --git a/pkg/vm_service/test/invoke_test.dart b/pkg/vm_service/test/invoke_test.dart
index 651e39e..6458f97d 100644
--- a/pkg/vm_service/test/invoke_test.dart
+++ b/pkg/vm_service/test/invoke_test.dart
@@ -30,39 +30,42 @@
 var tests = <IsolateTest>[
   hasStoppedAtBreakpoint,
   (VmService service, IsolateRef isolateRef) async {
-    final isolate = await service.getIsolate(isolateRef.id);
-    final Library lib = await service.getObject(isolate.id, isolate.rootLib.id);
-    final cls = lib.classes.singleWhere((cls) => cls.name == "Klass");
+    final isolateId = isolateRef.id!;
+    final isolate = await service.getIsolate(isolateId);
+    final Library lib =
+        await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+    final cls = lib.classes!.singleWhere((cls) => cls.name == "Klass");
     FieldRef fieldRef =
-        lib.variables.singleWhere((field) => field.name == "instance");
-    Field field = await service.getObject(isolate.id, fieldRef.id);
-    final instance = await service.getObject(isolate.id, field.staticValue.id);
+        lib.variables!.singleWhere((field) => field.name == "instance");
+    Field field = await service.getObject(isolateId, fieldRef.id!) as Field;
+    final instance = await service.getObject(isolateId, field.staticValue!.id!);
 
-    fieldRef = lib.variables.singleWhere((field) => field.name == "apple");
-    field = await service.getObject(isolate.id, fieldRef.id);
-    final apple = await service.getObject(isolate.id, field.staticValue.id);
-    fieldRef = lib.variables.singleWhere((field) => field.name == "banana");
-    field = await service.getObject(isolate.id, fieldRef.id);
-    Instance banana = await service.getObject(isolate.id, field.staticValue.id);
+    fieldRef = lib.variables!.singleWhere((field) => field.name == "apple");
+    field = await service.getObject(isolateId, fieldRef.id!) as Field;
+    final apple = await service.getObject(isolateId, field.staticValue!.id!);
+    fieldRef = lib.variables!.singleWhere((field) => field.name == "banana");
+    field = await service.getObject(isolateId, fieldRef.id!) as Field;
+    Instance banana =
+        await service.getObject(isolateId, field.staticValue!.id!) as Instance;
 
     dynamic result =
-        await service.invoke(isolate.id, lib.id, 'libraryFunction', []);
+        await service.invoke(isolateId, lib.id!, 'libraryFunction', []);
     expect(result.valueAsString, equals('foobar1'));
 
     result =
-        await service.invoke(isolate.id, cls.id, "classFunction", [apple.id]);
+        await service.invoke(isolateId, cls.id!, "classFunction", [apple.id!]);
     expect(result.valueAsString, equals('foobar2apple'));
 
     result = await service.invoke(
-        isolate.id, instance.id, "instanceFunction", [apple.id, banana.id]);
+        isolateId, instance.id!, "instanceFunction", [apple.id!, banana.id!]);
     expect(result.valueAsString, equals('foobar3applebanana'));
 
     // Wrong arity.
     await expectError(() => service
-        .invoke(isolate.id, instance.id, "instanceFunction", [apple.id]));
+        .invoke(isolateId, instance.id!, "instanceFunction", [apple.id!]));
     // No such target.
     await expectError(() => service
-        .invoke(isolate.id, instance.id, "functionDoesNotExist", [apple.id]));
+        .invoke(isolateId, instance.id!, "functionDoesNotExist", [apple.id!]));
   },
   resumeIsolate,
 ];
diff --git a/pkg/vm_service/test/network_profiling_test.dart b/pkg/vm_service/test/network_profiling_test.dart
index d554d81..b993389 100644
--- a/pkg/vm_service/test/network_profiling_test.dart
+++ b/pkg/vm_service/test/network_profiling_test.dart
@@ -28,12 +28,12 @@
     VmService service, IsolateRef isolateRef, bool state,
     {bool useSetter = true}) async {
   final completer = Completer<void>();
-  final isolateId = isolateRef.id;
-  StreamSubscription sub;
+  final isolateId = isolateRef.id!;
+  late StreamSubscription sub;
   sub = service.onExtensionEvent.listen((event) {
     expect(event.extensionKind, 'SocketProfilingStateChange');
-    expect(event.extensionData.data['isolateId'], isolateRef.id);
-    expect(event.extensionData.data['enabled'], state);
+    expect(event.extensionData!.data['isolateId'], isolateRef.id);
+    expect(event.extensionData!.data['enabled'], state);
     sub.cancel();
     completer.complete();
   });
@@ -60,7 +60,7 @@
   var socket = await io.Socket.connect(localhost, serverSocket.port);
   socket.write(content);
   await socket.flush();
-  await socket.destroy();
+  socket.destroy();
 
   // rawDatagram
   final doneCompleter = Completer<void>();
@@ -86,49 +86,46 @@
 
 var tests = <IsolateTest>[
   (VmService service, IsolateRef isolateRef) async {
-    final isolate = await service.getIsolate(isolateRef.id);
+    final isolate = await service.getIsolate(isolateRef.id!);
     // Ensure all network profiling service extensions are registered.
-    expect(isolate.extensionRPCs.length, greaterThanOrEqualTo(5));
-    expect(isolate.extensionRPCs.contains(kClearSocketProfileRPC), isTrue);
-    expect(isolate.extensionRPCs.contains(kGetVersionRPC), isTrue);
-    expect(isolate.extensionRPCs.contains(kPauseSocketProfilingRPC), isTrue);
-    expect(isolate.extensionRPCs.contains(kStartSocketProfilingRPC), isTrue);
-    expect(isolate.extensionRPCs.contains(kPauseSocketProfilingRPC), isTrue);
-    expect(isolate.extensionRPCs.contains(kSocketProfilingEnabledRPC), isTrue);
+    expect(isolate.extensionRPCs!.length, greaterThanOrEqualTo(5));
+    expect(isolate.extensionRPCs!.contains(kClearSocketProfileRPC), isTrue);
+    expect(isolate.extensionRPCs!.contains(kGetVersionRPC), isTrue);
+    expect(isolate.extensionRPCs!.contains(kPauseSocketProfilingRPC), isTrue);
+    expect(isolate.extensionRPCs!.contains(kStartSocketProfilingRPC), isTrue);
+    expect(isolate.extensionRPCs!.contains(kPauseSocketProfilingRPC), isTrue);
+    expect(isolate.extensionRPCs!.contains(kSocketProfilingEnabledRPC), isTrue);
   },
 
   // Test getSocketProfiler
   (VmService service, IsolateRef isolateRef) async {
-    final socketProfile = await service.getSocketProfile(isolateRef.id);
+    final socketProfile = await service.getSocketProfile(isolateRef.id!);
     expect(socketProfile.sockets.isEmpty, isTrue);
   },
   // Exercise methods naively
   (VmService service, IsolateRef isolateRef) async {
-    final version = await service.getDartIOVersion(isolateRef.id);
-    expect(version.major >= 1, true);
-    expect(version.minor >= 0, true);
-    await service.clearSocketProfile(isolateRef.id);
-    await service.getSocketProfile(isolateRef.id);
+    final isolateId = isolateRef.id!;
+    final version = await service.getDartIOVersion(isolateId);
+    expect(version.major! >= 1, true);
+    expect(version.minor! >= 0, true);
+    await service.clearSocketProfile(isolateId);
+    await service.getSocketProfile(isolateId);
   },
   (VmService service, IsolateRef isolateRef) async {
-    final initial =
-        (await service.socketProfilingEnabled(isolateRef.id)).enabled;
+    final isolateId = isolateRef.id!;
+    final initial = (await service.socketProfilingEnabled(isolateId)).enabled;
     await waitForStreamEvent(service, isolateRef, !initial);
-    expect((await service.socketProfilingEnabled(isolateRef.id)).enabled,
-        !initial);
+    expect((await service.socketProfilingEnabled(isolateId)).enabled, !initial);
     await waitForStreamEvent(service, isolateRef, initial);
-    expect(
-        (await service.socketProfilingEnabled(isolateRef.id)).enabled, initial);
+    expect((await service.socketProfilingEnabled(isolateId)).enabled, initial);
   },
   (VmService service, IsolateRef isolateRef) async {
-    final initial =
-        (await service.socketProfilingEnabled(isolateRef.id)).enabled;
+    final isolateId = isolateRef.id!;
+    final initial = (await service.socketProfilingEnabled(isolateId)).enabled;
     await waitForStreamEvent(service, isolateRef, !initial, useSetter: false);
-    expect((await service.socketProfilingEnabled(isolateRef.id)).enabled,
-        !initial);
+    expect((await service.socketProfilingEnabled(isolateId)).enabled, !initial);
     await waitForStreamEvent(service, isolateRef, initial, useSetter: false);
-    expect(
-        (await service.socketProfilingEnabled(isolateRef.id)).enabled, initial);
+    expect((await service.socketProfilingEnabled(isolateId)).enabled, initial);
   }
   // TODO(bkonyi): fully port observatory test for socket profiling.
 ];
diff --git a/pkg/vm_service/test/process_service_test.dart b/pkg/vm_service/test/process_service_test.dart
index a47359a..b1c269a 100644
--- a/pkg/vm_service/test/process_service_test.dart
+++ b/pkg/vm_service/test/process_service_test.dart
@@ -24,19 +24,19 @@
     '--pause_isolates_on_start',
     io.Platform.script.toFilePath(),
   ];
-  io.Process process1;
-  io.Process process2;
-  io.Process process3;
+  io.Process? process1;
+  io.Process? process2;
+  io.Process? process3;
 
   void closeDown() {
     if (process1 != null) {
-      process1.kill();
+      process1!.kill();
     }
     if (process2 != null) {
-      process2.kill();
+      process2!.kill();
     }
     if (process3 != null) {
-      process3.kill();
+      process3!.kill();
     }
     dir.deleteSync(recursive: true);
   }
@@ -70,14 +70,14 @@
 
     final result = jsonEncode({
       'type': 'foobar',
-      'pids': [process1.pid, process2.pid, process3.pid]
+      'pids': [process1!.pid, process2!.pid, process3!.pid]
     });
     return Future.value(ServiceExtensionResponse.result(result));
   }
 
   Future<ServiceExtensionResponse> closeStdin(ignored_a, ignored_b) {
-    process3.stdin.close();
-    return process3.exitCode.then<ServiceExtensionResponse>((int exit) {
+    process3!.stdin.close();
+    return process3!.exitCode.then<ServiceExtensionResponse>((int exit) {
       final result = jsonEncode({'type': 'foobar'});
       return ServiceExtensionResponse.result(result);
     });
@@ -91,57 +91,58 @@
 final processTests = <IsolateTest>[
   // Initial.
   (VmService service, IsolateRef isolate) async {
+    final isolateId = isolate.id!;
     final setup = await service.callServiceExtension(
       'ext.dart.io.setup',
-      isolateId: isolate.id,
+      isolateId: isolateId,
     );
     try {
-      SpawnedProcessList all = await service.getSpawnedProcesses(isolate.id);
+      SpawnedProcessList all = await service.getSpawnedProcesses(isolateId);
       expect(all.processes.length, equals(3));
 
       final first = await service.getSpawnedProcessById(
-        isolate.id,
+        isolateId,
         all.processes[0].id,
       );
 
       expect(first.name, io.Platform.executable);
-      expect(first.pid, equals(setup.json['pids'][0]));
+      expect(first.pid, equals(setup.json!['pids']![0]));
       expect(first.arguments.contains('foobar'), isFalse);
       expect(first.startedAt, greaterThan(0));
 
       final second = await service.getSpawnedProcessById(
-        isolate.id,
+        isolateId,
         all.processes[1].id,
       );
 
       expect(second.name, io.Platform.executable);
-      expect(second.pid, equals(setup.json['pids'][1]));
+      expect(second.pid, equals(setup.json!['pids']![1]));
       expect(second.arguments.contains('foobar'), isTrue);
       expect(second.pid != first.pid, isTrue);
       expect(second.startedAt, greaterThan(0));
       expect(second.startedAt, greaterThanOrEqualTo(first.startedAt));
 
       final third = await service.getSpawnedProcessById(
-        isolate.id,
+        isolateId,
         all.processes[2].id,
       );
 
       expect(third.name, dartJITBinary);
-      expect(third.pid, equals(setup.json['pids'][2]));
+      expect(third.pid, equals(setup.json!['pids']![2]));
       expect(third.pid != first.pid, isTrue);
       expect(third.pid != second.pid, isTrue);
       expect(third.startedAt, greaterThanOrEqualTo(second.startedAt));
 
       await service.callServiceExtension(
         'ext.dart.io.closeStdin',
-        isolateId: isolate.id,
+        isolateId: isolateId,
       );
-      all = await service.getSpawnedProcesses(isolate.id);
+      all = await service.getSpawnedProcesses(isolateId);
       expect(all.processes.length, equals(2));
     } finally {
       await service.callServiceExtension(
         'ext.dart.io.cleanup',
-        isolateId: isolate.id,
+        isolateId: isolateId,
       );
     }
   },
diff --git a/pkg/vm_service/test/regress_43940_test.dart b/pkg/vm_service/test/regress_43940_test.dart
new file mode 100644
index 0000000..3a490f3
--- /dev/null
+++ b/pkg/vm_service/test/regress_43940_test.dart
@@ -0,0 +1,29 @@
+// 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 'dart:async';
+
+import 'package:pedantic/pedantic.dart';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+void main() {
+  test('Call dispose handler before onDone completion', () async {
+    final controller = StreamController<String>(onCancel: () async {
+      await Future.delayed(const Duration(seconds: 1));
+    });
+    bool completed = false;
+    final fakeService = VmService(
+      controller.stream,
+      controller.sink.add,
+      disposeHandler: () async {
+        completed = true;
+      },
+    );
+
+    unawaited(fakeService.dispose());
+    await fakeService.onDone;
+    expect(completed, true);
+  });
+}
diff --git a/pkg/vm_service/test/regress_44588_test.dart b/pkg/vm_service/test/regress_44588_test.dart
new file mode 100644
index 0000000..3469305
--- /dev/null
+++ b/pkg/vm_service/test/regress_44588_test.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.
+
+import 'package:vm_service/vm_service.dart';
+import 'package:test/test.dart';
+
+import 'common/test_helper.dart';
+
+class Foo {
+  static Bar b = Bar();
+}
+
+class Bar {}
+
+var tests = <IsolateTest>[
+  (VmService service, IsolateRef isolate) async {
+    final classes = (await service.getClassList(isolate.id!)).classes!;
+    final fooRef = classes.firstWhere((element) => element.name == 'Foo');
+    final foo = (await service.getObject(isolate.id!, fooRef.id!)) as Class;
+    final field =
+        (await service.getObject(isolate.id!, foo.fields!.first.id!)) as Field;
+    expect(field.staticValue!.valueAsString, '<not initialized>');
+  }
+];
+
+main([args = const <String>[]]) => runIsolateTests(args, tests);
diff --git a/pkg/vm_service/test/server_test.dart b/pkg/vm_service/test/server_test.dart
index 739af84..97b0aed 100644
--- a/pkg/vm_service/test/server_test.dart
+++ b/pkg/vm_service/test/server_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.
 
+// @dart = 2.10
+
 @TestOn('vm')
 import 'dart:async';
 import 'dart:convert';
@@ -110,7 +112,7 @@
       test('with no params or isolateId', () {
         var extension = 'ext.cool';
         var request = rpcRequest(extension, params: null);
-        var response = Response(type: '')..json = {"hello": "world"};
+        var response = Response()..json = {"hello": "world"};
         when(serviceMock.callServiceExtension(
           extension,
           isolateId: argThat(isNull, named: 'isolateId'),
@@ -127,7 +129,7 @@
       test('with isolateId and no other params', () {
         var extension = 'ext.cool';
         var request = rpcRequest(extension, params: {'isolateId': '1'});
-        var response = Response(type: '')..json = {"hello": "world"};
+        var response = Response()..json = {"hello": "world"};
         when(serviceMock.callServiceExtension(
           extension,
           isolateId: argThat(equals('1'), named: 'isolateId'),
@@ -145,7 +147,7 @@
         var extension = 'ext.cool';
         var params = {'cool': 'option'};
         var request = rpcRequest(extension, params: params);
-        var response = Response(type: '')..json = {"hello": "world"};
+        var response = Response()..json = {"hello": "world"};
         when(serviceMock.callServiceExtension(
           extension,
           isolateId: argThat(isNull, named: 'isolateId'),
@@ -164,7 +166,7 @@
         var params = {'cool': 'option'};
         var request =
             rpcRequest(extension, params: Map.of(params)..['isolateId'] = '1');
-        var response = Response(type: '')..json = {"hello": "world"};
+        var response = Response()..json = {"hello": "world"};
         when(serviceMock.callServiceExtension(
           extension,
           isolateId: argThat(equals("1"), named: 'isolateId'),
@@ -214,7 +216,7 @@
         when(serviceMock.streamListen(streamId))
             .thenAnswer((_) => Future.value(response));
         requestsController.add(request);
-        await expect(responseQueue, emitsThrough(rpcResponse(response)));
+        await expectLater(responseQueue, emitsThrough(rpcResponse(response)));
 
         eventController = serviceMock.streamControllers[streamId];
 
@@ -229,7 +231,7 @@
           )
         ];
         events.forEach(eventController.add);
-        await expect(
+        await expectLater(
             responseQueue,
             emitsInOrder(
                 events.map((event) => streamNotifyResponse(streamId, event))));
@@ -241,7 +243,7 @@
         when(serviceMock.streamListen(streamId))
             .thenAnswer((_) => Future.value(response));
         requestsController.add(request);
-        await expect(responseQueue, emitsThrough(rpcResponse(response)));
+        await expectLater(responseQueue, emitsThrough(rpcResponse(response)));
 
         var nextEvent = Event(
           kind: EventKind.kIsolateReload,
@@ -329,7 +331,7 @@
             rpcRequest('streamListen', params: {'streamId': serviceStream}));
         requestsController
             .add(rpcRequest('registerService', params: {'service': serviceId}));
-        await expect(
+        await expectLater(
             responsesController.stream
                 .map((Map response) => stripEventTimestamp(response)),
             emitsThrough(serviceRegisteredEvent));
@@ -343,8 +345,12 @@
           responsesController2.close();
         });
 
-        VmServerConnection(requestsController2.stream,
-            responsesController2.sink, serviceRegistry, null);
+        VmServerConnection(
+          requestsController2.stream,
+          responsesController2.sink,
+          serviceRegistry,
+          VmService(Stream.empty(), (String _) => null),
+        );
 
         expect(
             responsesController2.stream
@@ -367,8 +373,12 @@
         var requestsController3 = StreamController<Map<String, Object>>();
         var responsesController3 = StreamController<Map<String, Object>>();
 
-        VmServerConnection(requestsController3.stream,
-            responsesController3.sink, serviceRegistry, null);
+        VmServerConnection(
+          requestsController3.stream,
+          responsesController3.sink,
+          serviceRegistry,
+          VmService(Stream.empty(), (String _) => null),
+        );
         expect(
             responsesController3.stream,
             neverEmits(
@@ -402,13 +412,13 @@
           clientInputController.sink, serviceRegistry, serviceMock);
 
       var requestParams = {'foo': 'bar'};
-      var expectedResponse = Response(type: '')..json = {'zap': 'zip'};
-      await client.registerService(serviceId, null);
+      var expectedResponse = Response()..json = {'zap': 'zip'};
+      await client.registerService(serviceId, 'service');
       // Duplicate registrations should fail.
-      expect(client.registerService(serviceId, null),
+      expect(client.registerService(serviceId, 'service'),
           throwsA(const TypeMatcher<RPCError>()));
 
-      await client.registerServiceCallback(serviceId, (request) async {
+      client.registerServiceCallback(serviceId, (request) async {
         expect(request, equals(requestParams));
         return {'result': expectedResponse.toJson()};
       });
@@ -420,11 +430,11 @@
 
       // Kill the client that registered the handler, it should now fall back
       // on `callServiceExtension`.
-      client.dispose();
+      await client.dispose();
       // This should complete as well.
       await clientConnection.done;
 
-      var mockResponse = Response(type: '')..json = {'mock': 'response'};
+      var mockResponse = Response()..json = {'mock': 'response'};
       when(serviceMock.callServiceExtension(serviceId,
               args: argThat(equals(requestParams), named: 'args'),
               isolateId: argThat(isNull, named: 'isolateId')))
@@ -490,7 +500,7 @@
       response['params'].containsKey('event')) {
     response['params']['event']['timestamp'] = 0;
   }
-  return response;
+  return response as Map<String, Object>;
 }
 
 class MockVmService extends Mock implements VmServiceInterface {
diff --git a/pkg/vm_service/tool/common/generate_common.dart b/pkg/vm_service/tool/common/generate_common.dart
index f250c55..d91e730 100644
--- a/pkg/vm_service/tool/common/generate_common.dart
+++ b/pkg/vm_service/tool/common/generate_common.dart
@@ -4,6 +4,9 @@
 
 library generate_vm_service_common;
 
+// TODO(bkonyi): remove once markdown and pub_semver deps are updated to null
+// safety for the SDK.
+// ignore_for_file: import_of_legacy_library_into_null_safe
 import 'package:markdown/markdown.dart';
 import 'package:pub_semver/pub_semver.dart';
 
@@ -19,9 +22,9 @@
     final RegExp regex = RegExp(r'[\d.]+');
 
     // Extract version from header: `# Dart VM Service Protocol 2.0`.
-    Element node = nodes.firstWhere((n) => isH1(n));
-    Text text = node.children[0];
-    Match match = regex.firstMatch(text.text);
+    Element node = nodes.firstWhere((n) => isH1(n)) as Element;
+    Text text = node.children[0] as Text;
+    Match? match = regex.firstMatch(text.text);
     if (match == null) throw 'Unable to locate service protocol version';
 
     // Append a `.0`.
diff --git a/pkg/vm_service/tool/common/parser.dart b/pkg/vm_service/tool/common/parser.dart
index 3a58340..08d3709 100644
--- a/pkg/vm_service/tool/common/parser.dart
+++ b/pkg/vm_service/tool/common/parser.dart
@@ -7,21 +7,21 @@
 class Token {
   static final RegExp _alpha = RegExp(r'^[0-9a-zA-Z_\-@]+$');
 
-  final String text;
-  Token next;
+  final String? text;
+  Token? next;
 
   Token(this.text);
 
   bool get eof => text == null;
 
   bool get isName {
-    if (text == null || text.isEmpty) return false;
-    return _alpha.hasMatch(text);
+    if (text == null || text!.isEmpty) return false;
+    return _alpha.hasMatch(text!);
   }
 
-  bool get isComment => text != null && text.startsWith('//');
+  bool get isComment => text != null && text!.startsWith('//');
 
-  String toString() => text == null ? 'EOF' : text;
+  String toString() => text == null ? 'EOF' : text!;
 }
 
 class Tokenizer {
@@ -30,12 +30,12 @@
   static final whitespace = ' \n\t\r';
 
   String text;
-  Token _head;
-  Token _last;
+  Token? _head;
+  Token? _last;
 
   Tokenizer(this.text);
 
-  Token tokenize() {
+  Token? tokenize() {
     _emit(null);
 
     for (int i = 0; i < text.length; i++) {
@@ -63,15 +63,15 @@
 
     _emit(null);
 
-    _head = _head.next;
+    _head = _head!.next;
 
     return _head;
   }
 
-  void _emit(String value) {
+  void _emit(String? value) {
     Token token = Token(value);
     if (_head == null) _head = token;
-    if (_last != null) _last.next = token;
+    if (_last != null) _last!.next = token;
     _last = token;
   }
 
@@ -83,12 +83,12 @@
   String toString() {
     StringBuffer buf = StringBuffer();
 
-    Token t = _head;
+    Token t = _head!;
 
     buf.write('[${t}]\n');
 
     while (!t.eof) {
-      t = t.next;
+      t = t.next!;
       buf.write('[${t}]\n');
     }
 
@@ -97,20 +97,20 @@
 }
 
 abstract class Parser {
-  final Token startToken;
+  final Token? startToken;
 
-  Token current;
+  Token? current;
 
   Parser(this.startToken);
 
   Token expect(String text) {
-    Token t = advance();
+    Token t = advance()!;
     if (text != t.text) fail('expected ${text}, got ${t}');
     return t;
   }
 
   bool consume(String text) {
-    if (peek().text == text) {
+    if (peek()!.text == text) {
       advance();
       return true;
     } else {
@@ -118,31 +118,34 @@
     }
   }
 
-  Token peek() =>
-      current == null ? startToken : current.eof ? current : current.next;
+  Token? peek() => current == null
+      ? startToken
+      : current!.eof
+          ? current
+          : current!.next;
 
   Token expectName() {
-    Token t = advance();
+    Token t = advance()!;
     if (!t.isName) fail('expected name token, got ${t}');
     return t;
   }
 
-  Token advance() {
+  Token? advance() {
     if (current == null) {
       current = startToken;
-    } else if (!current.eof) {
-      current = current.next;
+    } else if (!current!.eof) {
+      current = current!.next;
     }
 
     return current;
   }
 
-  String collectComments() {
+  String? collectComments() {
     StringBuffer buf = StringBuffer();
 
-    while (peek().isComment) {
-      Token t = advance();
-      String str = t.text.substring(2);
+    while (peek()!.isComment) {
+      Token t = advance()!;
+      String str = t.text!.substring(2);
 
       if (str.startsWith(' ')) str = str.substring(1);
 
diff --git a/pkg/vm_service/tool/common/src_gen_common.dart b/pkg/vm_service/tool/common/src_gen_common.dart
index cb5a9fd..4fd8313 100644
--- a/pkg/vm_service/tool/common/src_gen_common.dart
+++ b/pkg/vm_service/tool/common/src_gen_common.dart
@@ -4,6 +4,9 @@
 
 library src_gen_common;
 
+// TODO(bkonyi): remove once markdown and pub_semver deps are updated to null
+// safety for the SDK.
+// ignore_for_file: import_of_legacy_library_into_null_safe
 import 'package:markdown/markdown.dart';
 
 const int RUNE_SPACE = 32;
@@ -36,7 +39,7 @@
 String lowerTitleCase(String str) =>
     str.substring(0, 1).toLowerCase() + str.substring(1);
 
-String joinLast(Iterable<String> strs, String join, [String last]) {
+String joinLast(Iterable<String> strs, String join, [String? last]) {
   if (strs.isEmpty) return '';
   List list = strs.toList();
   if (list.length == 1) return list.first;
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 49fb41a..b41d7ab 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -4,6 +4,9 @@
 
 library generate_vm_service_dart;
 
+// TODO(bkonyi): remove once markdown and pub_semver deps are updated to null
+// safety for the SDK.
+// ignore_for_file: import_of_legacy_library_into_null_safe
 import 'package:markdown/markdown.dart';
 
 import '../common/generate_common.dart';
@@ -13,9 +16,9 @@
 
 export 'src_gen_dart.dart' show DartGenerator;
 
-Api api;
+late Api api;
 
-String _coerceRefType(String typeName) {
+String? _coerceRefType(String? typeName) {
   if (typeName == 'Object') typeName = 'Obj';
   if (typeName == '@Object') typeName = 'ObjRef';
   if (typeName == 'Null') typeName = 'NullVal';
@@ -23,7 +26,7 @@
   if (typeName == 'Function') typeName = 'Func';
   if (typeName == '@Function') typeName = 'FuncRef';
 
-  if (typeName.startsWith('@')) typeName = typeName.substring(1) + 'Ref';
+  if (typeName!.startsWith('@')) typeName = typeName.substring(1) + 'Ref';
 
   if (typeName == 'string') typeName = 'String';
   if (typeName == 'map') typeName = 'Map';
@@ -32,7 +35,7 @@
 }
 
 String _typeRefListToString(List<TypeRef> types) =>
-    'const [' + types.map((e) => "'" + e.name + "'").join(',') + ']';
+    'const [' + types.map((e) => "'" + e.name! + "'").join(',') + ']';
 
 final String _headerCode = r'''
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
@@ -49,8 +52,6 @@
 import 'dart:convert' show base64, jsonDecode, jsonEncode, utf8;
 import 'dart:typed_data';
 
-import 'package:meta/meta.dart';
-
 import 'service_extension_registry.dart';
 
 export 'service_extension_registry.dart' show ServiceExtensionRegistry;
@@ -69,8 +70,8 @@
   /// Call an arbitrary service protocol method. This allows clients to call
   /// methods not explicitly exposed by this library.
   Future<Response> callMethod(String method, {
-    String isolateId,
-    Map args
+    String? isolateId,
+    Map<String, dynamic>? args
   }) {
     return callServiceExtension(method, isolateId: isolateId, args: args);
   }
@@ -80,13 +81,13 @@
   /// See https://api.dart.dev/stable/dart-developer/dart-developer-library.html.
   @override
   Future<Response> callServiceExtension(String method, {
-    String isolateId,
-    Map args
+    String? isolateId,
+    Map<String, dynamic>? args
   }) {
     if (args == null && isolateId == null) {
       return _call(method);
     } else if (args == null) {
-      return _call(method, {'isolateId': isolateId});
+      return _call(method, {'isolateId': isolateId!});
     } else {
       args = Map.from(args);
       if (isolateId != null) {
@@ -100,8 +101,8 @@
 
   Stream<String> get onReceive => _onReceive.stream;
 
-  void dispose() {
-    _streamSub.cancel();
+  Future<void> dispose() async {
+    await _streamSub.cancel();
     _completers.forEach((id, c) {
       final method = _methodCalls[id];
       return c.completeError(RPCError(
@@ -109,7 +110,7 @@
     });
     _completers.clear();
     if (_disposeHandler != null) {
-      _disposeHandler();
+      await _disposeHandler!();
     }
     if (!_onDoneCompleter.isCompleted) {
       _onDoneCompleter.complete();
@@ -162,22 +163,21 @@
         bytes.buffer, bytes.offsetInBytes + metaOffset, metaLength));
     final data = ByteData.view(
         bytes.buffer, bytes.offsetInBytes + dataOffset, dataLength);
-    dynamic map = jsonDecode(meta);
-    if (map != null && map['method'] == 'streamNotify') {
+    dynamic map = jsonDecode(meta)!;
+    if (map['method'] == 'streamNotify') {
       String streamId = map['params']['streamId'];
       Map event = map['params']['event'];
       event['data'] = data;
       _getEventController(streamId)
-          .add(createServiceObject(event, const ['Event']));
+          .add(createServiceObject(event, const ['Event'])! as Event);
     }
   }
 
   void _processMessageStr(String message) {
-    var json;
+    late Map<String, dynamic> json;
     try {
       _onReceive.add(message);
-
-      json = jsonDecode(message);
+      json = jsonDecode(message)!;
     } catch (e, s) {
       _log.severe('unable to decode message: ${message}, ${e}\n${s}');
       return;
@@ -199,9 +199,9 @@
   }
 
   void _processResponse(Map<String, dynamic> json) {
-    Completer completer = _completers.remove(json['id']);
-    String methodName = _methodCalls.remove(json['id']);
-    List<String> returnTypes = _methodReturnTypes[methodName];
+    Completer? completer = _completers.remove(json['id']);
+    String methodName = _methodCalls.remove(json['id'])!;
+    List<String> returnTypes = _methodReturnTypes[methodName] ?? [];
     if (completer == null) {
       _log.severe('unmatched request response: ${jsonEncode(json)}');
     } else if (json['error'] != null) {
@@ -230,24 +230,25 @@
 
   Future _processNotification(Map<String, dynamic> json) async {
     final String method = json['method'];
-    final Map params = json['params'] ?? <String, dynamic>{};
+    final Map<String, dynamic> params = json['params'] ?? <String, dynamic>{};
     if (method == 'streamNotify') {
       String streamId = params['streamId'];
-      _getEventController(streamId).add(createServiceObject(params['event'], const ['Event']));
+      _getEventController(streamId).add(createServiceObject(params['event'], const ['Event'])! as Event);
     } else {
       await _routeRequest(method, params);
     }
   }
 
   Future<Map> _routeRequest(String method, Map<String, dynamic> params) async{
-    if (!_services.containsKey(method)) {
+    final service = _services[method];
+    if (service == null) {
       RPCError error = RPCError(
           method, RPCError.kMethodNotFound, 'method not found \'$method\'');
       return {'error': error.toMap()};
     }
 
     try {
-      return await _services[method](params);
+      return await service(params);
     } catch (e, st) {
       RPCError error = RPCError.withDetails(
         method, RPCError.kServerError, '$e', details: '$st',);
@@ -281,22 +282,22 @@
     return RPCError(callingMethod, json['code'], json['message'], json['data']);
   }
 
-  final String callingMethod;
+  final String? callingMethod;
   final int code;
   final String message;
-  final Map data;
+  final Map? data;
 
   RPCError(this.callingMethod, this.code, this.message, [this.data]);
 
   RPCError.withDetails(this.callingMethod, this.code, this.message,
-      {Object details})
+      {Object? details})
       : data = details == null ? null : <String, dynamic>{} {
     if (details != null) {
-      data['details'] = details;
+      data!['details'] = details;
     }
   }
 
-  String get details => data == null ? null : data['details'];
+  String? get details => data == null ? null : data!['details'];
 
   /// Return a map representation of this error suitable for converstion to
   /// json.
@@ -326,17 +327,17 @@
   final Sentinel sentinel;
 
   SentinelException.parse(this.callingMethod, Map<String, dynamic> data) :
-    sentinel = Sentinel.parse(data);
+    sentinel = Sentinel.parse(data)!;
 
   String toString() => '$sentinel from ${callingMethod}()';
 }
 
 /// An `ExtensionData` is an arbitrary map that can have any contents.
 class ExtensionData {
-  static ExtensionData parse(Map json) =>
+  static ExtensionData? parse(Map<String, dynamic>? json) =>
       json == null ? null : ExtensionData._fromJson(json);
 
-  final Map data;
+  final Map<String, dynamic> data;
 
   ExtensionData() : data = {};
 
@@ -362,11 +363,11 @@
 ''';
 
 final _registerServiceImpl = '''
-_serviceExtensionRegistry.registerExtension(params['service'], this);
+_serviceExtensionRegistry.registerExtension(params!['service'], this);
 response =  Success();''';
 
 final _streamListenCaseImpl = '''
-var id = params['streamId'];
+var id = params!['streamId'];
 if (_streamSubscriptions.containsKey(id)) {
   throw RPCError.withDetails(
     'streamListen', 103, 'Stream already subscribed',
@@ -390,7 +391,7 @@
 response = Success();''';
 
 final _streamCancelCaseImpl = '''
-var id = params['streamId'];
+var id = params!['streamId'];
 var existing = _streamSubscriptions.remove(id);
 if (existing == null) {
   throw RPCError.withDetails(
@@ -402,22 +403,22 @@
 response = Success();''';
 
 abstract class Member {
-  String get name;
+  String? get name;
 
-  String get docs => null;
+  String? get docs => null;
 
   void generate(DartGenerator gen);
 
   bool get hasDocs => docs != null;
 
-  String toString() => name;
+  String toString() => name!;
 }
 
 class Api extends Member with ApiParseUtil {
-  String serviceVersion;
+  String? serviceVersion;
   List<Method> methods = [];
   List<Enum> enums = [];
-  List<Type> types = [];
+  List<Type?> types = [];
   List<StreamCategory> streamCategories = [];
 
   void parse(List<Node> nodes) {
@@ -427,19 +428,19 @@
     // the pre following it is the definition
     // the optional p following that is the documentation
 
-    String h3Name;
+    String? h3Name;
 
     for (int i = 0; i < nodes.length; i++) {
       Node node = nodes[i];
 
       if (isPre(node) && h3Name != null) {
         String definition = textForCode(node);
-        String docs = '';
+        String? docs = '';
 
         while (i + 1 < nodes.length &&
                 (isPara(nodes[i + 1]) || isBlockquote(nodes[i + 1])) ||
             isList(nodes[i + 1])) {
-          Element p = nodes[++i];
+          Element p = nodes[++i] as Element;
           String str = TextOutputVisitor.printText(p);
           if (!str.contains('|') &&
               !str.contains('``') &&
@@ -449,7 +450,7 @@
           docs = '${docs}\n\n${str}';
         }
 
-        docs = docs.trim();
+        docs = docs!.trim();
         if (docs.isEmpty) docs = null;
 
         _parse(h3Name, definition, docs);
@@ -460,20 +461,20 @@
       }
     }
 
-    for (Type type in types) {
-      type.calculateFieldOverrides();
+    for (Type? type in types) {
+      type!.calculateFieldOverrides();
     }
 
     Method streamListenMethod =
         methods.singleWhere((method) => method.name == 'streamListen');
-    _parseStreamListenDocs(streamListenMethod.docs);
+    _parseStreamListenDocs(streamListenMethod.docs!);
   }
 
   String get name => 'api';
 
-  String get docs => null;
+  String? get docs => null;
 
-  void _parse(String name, String definition, [String docs]) {
+  void _parse(String name, String definition, [String? docs]) {
     name = name.trim();
     definition = definition.trim();
     // clean markdown introduced changes
@@ -518,13 +519,13 @@
 bool _isNullInstance(Map json) => ((json['type'] == '@Instance') &&
                                   (json['kind'] == 'Null'));
 
-Object createServiceObject(dynamic json, List<String> expectedTypes) {
+Object? createServiceObject(dynamic json, List<String> expectedTypes) {
   if (json == null) return null;
 
   if (json is List) {
     return json.map((e) => createServiceObject(e, expectedTypes)).toList();
   } else if (json is Map) {
-    String type = json['type'];
+    String? type = json['type'];
 
     // Not a Response type.
     if (type == null) {
@@ -539,10 +540,11 @@
       // be returned.
       return null;
     }
-    if (_typeFactories[type] == null) {
+    final typeFactory = _typeFactories[type];
+    if (typeFactory == null) {
       return null;
     } else {
-      return _typeFactories[type](json);
+      return typeFactory(json);
     }
   } else {
     // Handle simple types.
@@ -566,7 +568,7 @@
   }
 }
 
-void _setIfNotNull(Map<String, Object> json, String key, Object value) {
+void _setIfNotNull(Map<String, dynamic> json, String key, Object? value) {
   if (value == null) return;
   json[key] = value;
 }
@@ -588,8 +590,8 @@
 ''');
     gen.writeln();
     gen.writeln('Map<String, Function> _typeFactories = {');
-    types.forEach((Type type) {
-      gen.writeln("'${type.rawName}': ${type.name}.parse,");
+    types.forEach((Type? type) {
+      gen.writeln("'${type!.rawName}': ${type.name}.parse,");
     });
     gen.writeln('};');
     gen.writeln();
@@ -615,7 +617,7 @@
   Stream<Event> onEvent(String streamId);
 
   /// Handler for calling extra service extensions.
-  Future<Response> callServiceExtension(String method, {String isolateId, Map args});
+  Future<Response> callServiceExtension(String method, {String? isolateId, Map<String, dynamic>? args});
 ''');
     methods.forEach((m) {
       m.generateDefinition(gen);
@@ -628,14 +630,14 @@
     // automatically.
     gen.write('''
   class _PendingServiceRequest {
-    Future<Map<String, Object>> get future => _completer.future;
-    final _completer = Completer<Map<String, Object>>();
+    Future<Map<String, Object?>> get future => _completer.future;
+    final _completer = Completer<Map<String, Object?>>();
 
     final dynamic originalId;
 
     _PendingServiceRequest(this.originalId);
 
-    void complete(Map<String, Object> response) {
+    void complete(Map<String, Object?> response) {
       response['id'] = originalId;
       _completer.complete(response);
     }
@@ -649,7 +651,7 @@
   /// instances.
   class VmServerConnection {
     final Stream<Map<String, Object>> _requestStream;
-    final StreamSink<Map<String, Object>> _responseSink;
+    final StreamSink<Map<String, Object?>> _responseSink;
     final ServiceExtensionRegistry _serviceExtensionRegistry;
     final VmServiceInterface _serviceImplementation;
     /// Used to create unique ids when acting as a proxy between clients.
@@ -659,8 +661,8 @@
     final _streamSubscriptions = <String, StreamSubscription>{};
 
     /// Completes when [_requestStream] is done.
-    Future get done => _doneCompleter.future;
-    final _doneCompleter = Completer<Null>();
+    Future<void> get done => _doneCompleter.future;
+    final _doneCompleter = Completer<void>();
 
     /// Pending service extension requests to this client by id.
     final _pendingServiceExtensionRequests = <dynamic, _PendingServiceRequest>{};
@@ -678,13 +680,13 @@
     ///
     /// We don't attempt to do any serialization or deserialization of the
     /// request or response in this case
-    Future<Map<String, Object>> _forwardServiceExtensionRequest(
-        Map<String, Object> request) {
-      var originalId = request['id'];
-      request = Map.of(request);
+    Future<Map<String, Object?>> _forwardServiceExtensionRequest(
+        Map<String, Object?> request) {
+      final originalId = request['id'];
+      request = Map<String, Object?>.of(request);
       // Modify the request ID to ensure we don't have conflicts between
       // multiple clients ids.
-      var newId = '\${_nextServiceRequestId++}:\$originalId';
+      final newId = '\${_nextServiceRequestId++}:\$originalId';
       request['id'] = newId;
       var pendingRequest = _PendingServiceRequest(originalId);
       _pendingServiceExtensionRequests[newId] = pendingRequest;
@@ -692,22 +694,22 @@
       return pendingRequest.future;
     }
 
-    void _delegateRequest(Map<String, Object> request) async {
+    void _delegateRequest(Map<String, Object?> request) async {
       try {
         var id = request['id'];
         // Check if this is actually a response to a pending request.
         if (_pendingServiceExtensionRequests.containsKey(id)) {
-          final pending = _pendingServiceExtensionRequests[id];
-          pending.complete(Map.of(request));
+          final pending = _pendingServiceExtensionRequests[id]!;
+          pending.complete(Map<String, Object?>.of(request));
           return;
         }
-        var method = request['method'] as String;
+        final method = request['method'] as String?;
         if (method == null) {
           throw RPCError(
             null, RPCError.kInvalidRequest, 'Invalid Request', request);
         }
-        var params = request['params'] as Map;
-        Response response;
+        final params = request['params'] as Map<String, dynamic>?;
+        late Response response;
 
         switch(method) {
           case 'registerService':
@@ -722,14 +724,22 @@
         } else if (m.name == 'streamCancel') {
           gen.writeln(_streamCancelCaseImpl);
         } else {
+          bool firstParam = true;
+          final nullCheck = () {
+            final result = firstParam ? '!' : '';
+            if (firstParam) {
+              firstParam = false;
+            }
+            return result;
+          };
           gen.write("response = await _serviceImplementation.${m.name}(");
           // Positional args
           m.args.where((arg) => !arg.optional).forEach((MethodArg arg) {
             if (arg.type.isArray) {
               gen.write(
-                  "${arg.type.listCreationRef}.from(params['${arg.name}'] ?? []), ");
+                  "${arg.type.listCreationRef}.from(params${nullCheck()}['${arg.name}'] ?? []), ");
             } else {
-              gen.write("params['${arg.name}'], ");
+              gen.write("params${nullCheck()}['${arg.name}'], ");
             }
           });
           // Optional named args
@@ -738,9 +748,10 @@
             namedArgs.forEach((arg) {
               if (arg.name == 'scope') {
                 gen.writeln(
-                    "${arg.name}: params['${arg.name}']?.cast<String, String>(), ");
+                    "${arg.name}: params${nullCheck()}['${arg.name}']?.cast<String, String>(), ");
               } else {
-                gen.writeln("${arg.name}: params['${arg.name}'], ");
+                gen.writeln(
+                    "${arg.name}: params${nullCheck()}['${arg.name}'], ");
               }
             });
           }
@@ -752,7 +763,7 @@
     // Handle service extensions
     gen.writeln('default:');
     gen.writeln('''
-        var registeredClient = _serviceExtensionRegistry.clientFor(method);
+        final registeredClient = _serviceExtensionRegistry.clientFor(method);
         if (registeredClient != null) {
           // Check for any client which has registered this extension, if we
           // have one then delegate the request to that client.
@@ -764,8 +775,8 @@
         } else if (method.startsWith('ext.')) {
           // Remaining methods with `ext.` are assumed to be registered via
           // dart:developer, which the service implementation handles.
-          var args = params == null ? null : Map.of(params);
-          var isolateId = args?.remove('isolateId');
+          final args = params == null ? null : Map<String, dynamic>.of(params);
+          final isolateId = args?.remove('isolateId');
           response = await _serviceImplementation.callServiceExtension(method,
               isolateId: isolateId, args: args);
         } else {
@@ -775,13 +786,6 @@
     // Terminate the switch
     gen.writeln('}');
 
-    // Handle null responses
-    gen.write('''
-      if (response == null) {
-        throw StateError('Invalid null response from service');
-      }
-    ''');
-
     // Generate the json success response
     gen.write("""_responseSink.add({
   'jsonrpc': '2.0',
@@ -793,7 +797,7 @@
     // Close the try block, handle errors
     gen.write(r'''
       } catch (e, st) {
-        var error = e is RPCError
+        final error = e is RPCError
             ? e.toMap()
             : {
                 'code': RPCError.kInternalError,
@@ -817,13 +821,13 @@
 
     // The client side service implementation.
     gen.writeStatement('class VmService implements VmServiceInterface {');
-    gen.writeStatement('StreamSubscription _streamSub;');
-    gen.writeStatement('Function _writeMessage;');
+    gen.writeStatement('late final StreamSubscription _streamSub;');
+    gen.writeStatement('late final Function _writeMessage;');
     gen.writeStatement('int _id = 0;');
     gen.writeStatement('Map<String, Completer> _completers = {};');
     gen.writeStatement('Map<String, String> _methodCalls = {};');
     gen.writeStatement('Map<String, ServiceCallback> _services = {};');
-    gen.writeStatement('Log _log;');
+    gen.writeStatement('late final Log _log;');
     gen.write('''
 
 StreamController<String> _onSend = StreamController.broadcast(sync: true);
@@ -834,7 +838,7 @@
 Map<String, StreamController<Event>> _eventControllers = {};
 
 StreamController<Event> _getEventController(String eventName) {
-  StreamController<Event> controller = _eventControllers[eventName];
+  StreamController<Event>? controller = _eventControllers[eventName];
   if (controller == null) {
     controller = StreamController.broadcast();
     _eventControllers[eventName] = controller;
@@ -842,12 +846,12 @@
   return controller;
 }
 
-DisposeHandler _disposeHandler;
+late final DisposeHandler? _disposeHandler;
 
 VmService(Stream<dynamic> /*String|List<int>*/ inStream, void writeMessage(String message), {
-  Log log,
-  DisposeHandler disposeHandler,
-  Future streamClosed,
+  Log? log,
+  DisposeHandler? disposeHandler,
+  Future? streamClosed,
 }) {
   _streamSub = inStream.listen(_processMessage, onDone: ()=> _onDoneCompleter.complete());
   _writeMessage = writeMessage;
@@ -882,7 +886,7 @@
     });
     gen.writeln();
     gen.writeln('// types');
-    types.where((t) => !t.skip).forEach((t) => t.generate(gen));
+    types.where((t) => !t!.skip).forEach((t) => t!.generate(gen));
   }
 
   void generateAsserts(DartGenerator gen) {
@@ -903,17 +907,14 @@
 }
 
 bool assertBool(bool obj) {
-  assertNotNull(obj);
   return obj;
 }
 
 int assertInt(int obj) {
-  assertNotNull(obj);
   return obj;
 }
 
 double assertDouble(double obj) {
-  assertNotNull(obj);
   return obj;
 }
 
@@ -944,13 +945,11 @@
 }
 
 String assertString(String obj) {
-  assertNotNull(obj);
   if (obj.isEmpty) throw 'expected non-zero length string';
   return obj;
 }
 
 vms.Success assertSuccess(vms.Success obj) {
-  assertNotNull(obj);
   if (obj.type != 'Success') throw 'expected Success';
   return obj;
 }
@@ -964,10 +963,10 @@
       event.kind == vms.EventKind.kBreakpointAdded ||
       event.kind == vms.EventKind.kBreakpointRemoved ||
       event.kind == vms.EventKind.kBreakpointResolved) {
-    assertBreakpoint(event.breakpoint);
+    assertBreakpoint(event.breakpoint!);
   }
   if (event.kind == vms.EventKind.kPauseBreakpoint) {
-    for (vms.Breakpoint elem in event.pauseBreakpoints) {
+    for (vms.Breakpoint elem in event.pauseBreakpoints!) {
       assertBreakpoint(elem);
     }
   }
@@ -983,18 +982,18 @@
     if (event.topFrame != null ||
         (event.kind != vms.EventKind.kPauseInterrupted &&
             event.kind != vms.EventKind.kResume)) {
-      assertFrame(event.topFrame);
+      assertFrame(event.topFrame!);
     }
   }
   if (event.kind == vms.EventKind.kPauseException) {
-    assertInstanceRef(event.exception);
+    assertInstanceRef(event.exception!);
   }
   if (event.kind == vms.EventKind.kPauseBreakpoint ||
       event.kind == vms.EventKind.kPauseInterrupted) {
-    assertBool(event.atAsyncSuspension);
+    assertBool(event.atAsyncSuspension!);
   }
   if (event.kind == vms.EventKind.kInspect) {
-    assertInstanceRef(event.inspectee);
+    assertInstanceRef(event.inspectee!);
   }
   return event;
 }
@@ -1004,7 +1003,7 @@
 vms.Event assertIsolateEvent(vms.Event event) {
   assertEvent(event);
   if (event.kind == vms.EventKind.kServiceExtensionAdded) {
-    assertString(event.extensionRPC);
+    assertString(event.extensionRPC!);
   }
   return event;
 }
@@ -1013,10 +1012,10 @@
     for (Enum e in enums) {
       e.generateAssert(gen);
     }
-    for (Type type in types) {
-      if (type.name == 'Success') continue;
+    for (Type? type in types) {
+      if (type!.name == 'Success') continue;
       type.generateAssert(gen);
-      if (type.name.endsWith('Ref') ||
+      if (type.name!.endsWith('Ref') ||
           [
             'BoundVariable',
             'Breakpoint',
@@ -1029,6 +1028,7 @@
             'InboundReference',
             'LibraryDependency',
             'Message',
+            'ProcessMemoryItem',
             'ProfileFunction',
             'ProcessMemoryItem',
             'Protocol',
@@ -1043,16 +1043,17 @@
 
   void setDefaultValue(String typeName, String fieldName, String defaultValue) {
     types
-        .firstWhere((t) => t.name == typeName)
+        .firstWhere((t) => t!.name == typeName)!
         .fields
         .firstWhere((f) => f.name == fieldName)
         .defaultValue = defaultValue;
   }
 
-  bool isEnumName(String typeName) => enums.any((Enum e) => e.name == typeName);
+  bool isEnumName(String? typeName) =>
+      enums.any((Enum e) => e.name == typeName);
 
-  Type getType(String name) =>
-      types.firstWhere((t) => t.name == name, orElse: () => null);
+  Type? getType(String? name) =>
+      types.firstWhere((t) => t!.name == name, orElse: () => null);
 
   void _parseStreamListenDocs(String docs) {
     Iterator<String> lines = docs.split('\n').map((l) => l.trim()).iterator;
@@ -1090,8 +1091,8 @@
 }
 
 class StreamCategory {
-  String _name;
-  List<String> _events;
+  String? _name;
+  List<String>? _events;
 
   StreamCategory(String line) {
     // Debug | PauseStart, PauseExit, ...
@@ -1101,13 +1102,13 @@
     _events = line.split(',').map((w) => w.trim()).toList();
   }
 
-  String get name => _name;
+  String? get name => _name;
 
-  List<String> get events => _events;
+  List<String>? get events => _events;
 
   void generate(DartGenerator gen) {
     gen.writeln();
-    gen.writeln('// ${events.join(', ')}');
+    gen.writeln('// ${events!.join(', ')}');
     gen.writeln(
         "Stream<Event> get on${name}Event => _getEventController('$name').stream;");
   }
@@ -1117,7 +1118,7 @@
 
 class Method extends Member {
   final String name;
-  final String docs;
+  final String? docs;
 
   MemberType returnType = MemberType();
   List<MethodArg> args = [];
@@ -1142,7 +1143,7 @@
           .join());
 
       args.where((MethodArg a) => a.optional).forEach((MethodArg arg) {
-        String valueRef = arg.name;
+        String? valueRef = arg.name;
         // Special case for `getAllocationProfile`. We do not want to add these
         // params if they are false.
         if (name == 'getAllocationProfile') {
@@ -1173,7 +1174,7 @@
       {bool withDocs = true, bool withOverrides = false}) {
     gen.writeln();
     if (withDocs && docs != null) {
-      String _docs = docs == null ? '' : docs;
+      String _docs = docs == null ? '' : docs!;
       if (returnType.isMultipleReturns) {
         _docs += '\n\nThe return value can be one of '
             '${joinLast(returnType.types.map((t) => '[${t}]'), ', ', ' or ')}.';
@@ -1190,7 +1191,7 @@
     gen.write('Future<${returnType.name}> ${name}(');
     bool startedOptional = false;
     gen.write(args.map((MethodArg arg) {
-      String typeName;
+      String? typeName;
       if (api.isEnumName(arg.type.name)) {
         if (arg.type.isArray) {
           typeName = typeName = '/*${arg.type}*/ List<String>';
@@ -1200,12 +1201,12 @@
       } else {
         typeName = arg.type.ref;
       }
-
+      final nullable = arg.optional ? '?' : '';
       if (arg.optional && !startedOptional) {
         startedOptional = true;
-        return '{${typeName} ${arg.name}';
+        return '{${typeName}$nullable ${arg.name}';
       } else {
-        return '${typeName} ${arg.name}';
+        return '${typeName}$nullable ${arg.name}';
       }
     }).join(', '));
     if (args.length >= 4) gen.write(',');
@@ -1213,7 +1214,7 @@
     gen.write(') ');
   }
 
-  void _parse(Token token) => MethodParser(token).parseInto(this);
+  void _parse(Token? token) => MethodParser(token).parseInto(this);
 }
 
 class MemberType extends Member {
@@ -1229,7 +1230,7 @@
 
     while (loop) {
       if (parser.consume('(')) {
-        while (parser.peek().text != ')') {
+        while (parser.peek()!.text != ')') {
           // @Instance | Sentinel
           parser.advance();
         }
@@ -1258,7 +1259,7 @@
     }
   }
 
-  String get name {
+  String? get name {
     if (types.isEmpty) return '';
     if (types.length == 1) return types.first.ref;
     if (isReturnType) return 'Response';
@@ -1276,25 +1277,25 @@
 
   bool get isArray => types.length == 1 && types.first.isArray;
 
-  void generate(DartGenerator gen) => gen.write(name);
+  void generate(DartGenerator gen) => gen.write(name!);
 }
 
 class TypeRef {
-  String name;
+  String? name;
   int arrayDepth = 0;
-  List<TypeRef> genericTypes;
+  List<TypeRef>? genericTypes;
 
   TypeRef(this.name);
 
-  String get ref {
+  String? get ref {
     if (arrayDepth == 2) {
       return 'List<List<${name}>>';
     } else if (arrayDepth == 1) {
       return 'List<${name}>';
     } else if (genericTypes != null) {
-      return '$name<${genericTypes.join(', ')}>';
+      return '$name<${genericTypes!.join(', ')}>';
     } else {
-      return name.startsWith('_') ? name.substring(1) : name;
+      return name!.startsWith('_') ? name!.substring(1) : name;
     }
   }
 
@@ -1308,7 +1309,7 @@
     }
   }
 
-  String get listTypeArg => arrayDepth == 2 ? 'List<$name>' : name;
+  String? get listTypeArg => arrayDepth == 2 ? 'List<$name>' : name;
 
   bool get isArray => arrayDepth > 0;
 
@@ -1330,13 +1331,13 @@
           name == 'double' ||
           name == 'ByteData');
 
-  String toString() => ref;
+  String toString() => ref!;
 }
 
 class MethodArg extends Member {
   final Method parent;
   TypeRef type;
-  String name;
+  String? name;
   bool optional = false;
 
   MethodArg(this.parent, this.type, this.name);
@@ -1350,10 +1351,10 @@
 
 class Type extends Member {
   final Api parent;
-  String rawName;
-  String name;
-  String superName;
-  final String docs;
+  String? rawName;
+  String? name;
+  String? superName;
+  final String? docs;
   List<TypeField> fields = [];
 
   Type(this.parent, String categoryName, String definition, [this.docs]) {
@@ -1364,11 +1365,11 @@
 
   factory Type.merge(Type t1, Type t2) {
     final Api parent = t1.parent;
-    final String rawName = t1.rawName;
-    final String name = t1.name;
-    final String superName = t1.superName;
+    final String? rawName = t1.rawName;
+    final String? name = t1.name;
+    final String? superName = t1.superName;
     final String docs = [t1.docs, t2.docs].where((e) => e != null).join('\n');
-    final Map<String, TypeField> map = <String, TypeField>{};
+    final Map<String?, TypeField> map = <String?, TypeField>{};
     for (TypeField f in t2.fields.reversed) {
       map[f.name] = f;
     }
@@ -1385,17 +1386,17 @@
   bool get isResponse {
     if (superName == null) return false;
     if (name == 'Response' || superName == 'Response') return true;
-    return parent.getType(superName).isResponse;
+    return parent.getType(superName)!.isResponse;
   }
 
-  bool get isRef => name.endsWith('Ref');
+  bool get isRef => name!.endsWith('Ref');
 
   bool get supportsIdentity {
     if (fields.any((f) => f.name == 'id')) return true;
-    return superName == null ? false : getSuper().supportsIdentity;
+    return superName == null ? false : getSuper()!.supportsIdentity;
   }
 
-  Type getSuper() => superName == null ? null : api.getType(superName);
+  Type? getSuper() => superName == null ? null : api.getType(superName);
 
   List<TypeField> getAllFields() {
     if (superName == null) return fields;
@@ -1403,7 +1404,7 @@
     List<TypeField> all = [];
     all.insertAll(0, fields);
 
-    Type s = getSuper();
+    Type? s = getSuper();
     while (s != null) {
       all.insertAll(0, s.fields);
       s = s.getSuper();
@@ -1418,7 +1419,7 @@
     gen.writeln();
     if (docs != null) gen.writeDocs(docs);
     gen.write('class ${name} ');
-    Type superType;
+    Type? superType;
     if (superName != null) {
       superType = parent.getType(superName);
       gen.write('extends ${superName} ');
@@ -1427,12 +1428,12 @@
       gen.write('implements ${name}Ref ');
     }
     gen.writeln('{');
-    gen.writeln('static ${name} parse(Map<String, dynamic> json) => '
+    gen.writeln('static ${name}? parse(Map<String, dynamic>? json) => '
         'json == null ? null : ${name}._fromJson(json);');
     gen.writeln();
 
     if (name == 'Response' || name == 'TimelineEvent') {
-      gen.writeln('Map<String, dynamic> json;');
+      gen.writeln('Map<String, dynamic>? json;');
     }
     if (name == 'Script') {
       gen.writeln('final _tokenToLine = <int, int>{};');
@@ -1451,9 +1452,10 @@
     gen.write('${name}(');
     if (fields.isNotEmpty) {
       gen.write('{');
-      fields
-          .where((field) => !field.optional)
-          .forEach((field) => field.generateNamedParameter(gen));
+      fields.where((field) => !field.optional).forEach((field) {
+        final fromParent = (name == 'Instance' && field.name == 'classRef');
+        field.generateNamedParameter(gen, fromParent: fromParent);
+      });
       if (hasRequiredParentFields) {
         superType.fields.where((field) => !field.optional).forEach(
             (field) => field.generateNamedParameter(gen, fromParent: true));
@@ -1467,11 +1469,22 @@
     if (hasRequiredParentFields) {
       gen.write(' : super(');
       superType.fields.where((field) => !field.optional).forEach((field) {
-        String name = field.generatableName;
-        gen.write('$name: $name');
+        String? name = field.generatableName;
+        gen.writeln('$name: $name,');
       });
+      if (name == 'Instance') {
+        gen.writeln('classRef: classRef,');
+      }
       gen.write(')');
+    } else if (name!.contains('NullVal')) {
+      gen.writeln(' : super(');
+      gen.writeln("id: 'instance/null',");
+      gen.writeln('kind: InstanceKind.kNull,');
+      gen.writeln("classRef: ClassRef(id: 'class/null',");
+      gen.writeln("name: 'Null',),");
+      gen.writeln(')');
     }
+
     gen.writeln(';');
 
     // Build from JSON.
@@ -1501,6 +1514,37 @@
         }
         if (field.defaultValue != null) {
           gen.write(' ?? ${field.defaultValue}');
+        } else if (!field.optional) {
+          // If a default isn't provided and the field is required, generate a
+          // sane default initializer to avoid TypeErrors at runtime when
+          // running in a null-safe context.
+          dynamic defaultValue;
+          switch (field.type.name) {
+            case 'int':
+            case 'num':
+            case 'double':
+              defaultValue = -1;
+              break;
+            case 'bool':
+              defaultValue = false;
+              break;
+            case 'String':
+              defaultValue = "''";
+              break;
+            case 'ByteData':
+              defaultValue = "ByteData(0)";
+              break;
+            default:
+              {
+                if (field.type.isEnum) {
+                  // TODO(bkonyi): Figure out if there's a more correct way to
+                  // determine a default value for enums.
+                  defaultValue = "''";
+                }
+                break;
+              }
+          }
+          gen.write(' ?? $defaultValue');
         }
         gen.writeln(';');
         // } else if (field.type.isEnum) {
@@ -1512,23 +1556,27 @@
         // Special case `Event.extensionData`.
         gen.writeln(
             "extensionData = ExtensionData.parse(json['extensionData']);");
-      } else if (name == 'Instance' && field.name == 'associations') {
-        // Special case `Instance.associations`.
-        gen.writeln("associations = json['associations'] == null "
-            "? null : List<MapAssociation>.from("
-            "_createSpecificObject(json['associations'], MapAssociation.parse));");
+      } else if (name == 'Instance') {
+        if (field.name == 'associations') {
+          // Special case `Instance.associations`.
+          gen.writeln("associations = json['associations'] == null "
+              "? null : List<MapAssociation>.from("
+              "_createSpecificObject(json['associations'], MapAssociation.parse));");
+        } else if (field.name == 'classRef') {
+          // This is populated by `Obj`
+        }
       } else if (name == '_CpuProfile' && field.name == 'codes') {
         // Special case `_CpuProfile.codes`.
         gen.writeln("codes = List<CodeRegion>.from("
-            "_createSpecificObject(json['codes'], CodeRegion.parse));");
+            "_createSpecificObject(json['codes']!, CodeRegion.parse));");
       } else if (name == '_CpuProfile' && field.name == 'functions') {
         // Special case `_CpuProfile.functions`.
         gen.writeln("functions = List<ProfileFunction>.from("
-            "_createSpecificObject(json['functions'], ProfileFunction.parse));");
+            "_createSpecificObject(json['functions']!, ProfileFunction.parse));");
       } else if (name == 'SourceReport' && field.name == 'ranges') {
         // Special case `SourceReport.ranges`.
         gen.writeln("ranges = List<SourceReportRange>.from("
-            "_createSpecificObject(json['ranges'], SourceReportRange.parse));");
+            "_createSpecificObject(json['ranges']!, SourceReportRange.parse));");
       } else if (name == 'SourceReportRange' && field.name == 'coverage') {
         // Special case `SourceReportRange.coverage`.
         gen.writeln("coverage = _createSpecificObject("
@@ -1536,7 +1584,7 @@
       } else if (name == 'Library' && field.name == 'dependencies') {
         // Special case `Library.dependencies`.
         gen.writeln("dependencies = List<LibraryDependency>.from("
-            "_createSpecificObject(json['dependencies'], "
+            "_createSpecificObject(json['dependencies']!, "
             "LibraryDependency.parse));");
       } else if (name == 'Script' && field.name == 'tokenPosTable') {
         // Special case `Script.tokenPosTable`.
@@ -1544,7 +1592,7 @@
         if (field.optional) {
           gen.write("json['tokenPosTable'] == null ? null : ");
         }
-        gen.writeln("List<List<int>>.from(json['tokenPosTable'].map"
+        gen.writeln("List<List<int>>.from(json['tokenPosTable']!.map"
             "((dynamic list) => List<int>.from(list)));");
         gen.writeln('_parseTokenPosTable();');
       } else if (field.type.isArray) {
@@ -1557,7 +1605,7 @@
                 "List<${fieldType.listTypeArg}>.from($ref);");
           } else {
             gen.writeln("${field.generatableName} = $ref == null ? null : "
-                "List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList));");
+                "List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList)! as List);");
           }
         } else {
           if (fieldType.isListTypeSimple) {
@@ -1575,17 +1623,18 @@
             // field named 'samples' instead of 'instances'.
             if (name == 'InstanceSet') {
               gen.writeln("${field.generatableName} = "
-                  "List<${fieldType.listTypeArg}>.from(createServiceObject($ref ?? json['samples'], $typesList));");
+                  "List<${fieldType.listTypeArg}>.from(createServiceObject(($ref ?? json['samples']!) as List, $typesList)! as List);");
             } else {
               gen.writeln("${field.generatableName} = "
-                  "List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList) ?? []);");
+                  "List<${fieldType.listTypeArg}>.from(createServiceObject($ref, $typesList) as List? ?? []);");
             }
           }
         }
       } else {
         String typesList = _typeRefListToString(field.type.types);
         gen.writeln("${field.generatableName} = "
-            "createServiceObject(json['${field.name}'], $typesList);");
+            "createServiceObject(json['${field.name}']${field.optional ? '' : '!'}, "
+            "$typesList) as ${field.type.name}${field.optional ? '?' : ''};");
       }
     });
     if (fields.isNotEmpty) {
@@ -1599,10 +1648,13 @@
 
     // toJson support, the base Response type is not supported
     if (name == 'Response') {
+      gen.writeln("String get type => 'Response';");
+      gen.writeln();
       gen.writeln('''
 Map<String, dynamic> toJson() {
-  var result = json == null ? <String, dynamic>{} : Map.of(json);
-  result['type'] = type ?? 'Response';
+  final localJson = json;
+  final result = localJson == null ? <String, dynamic>{} : Map<String, dynamic>.of(localJson);
+  result['type'] = type;
   return result;
 }''');
     } else if (name == 'TimelineEvent') {
@@ -1610,7 +1662,8 @@
       // fairly dynamic. Return the json directly.
       gen.writeln('''
           Map<String, dynamic> toJson() {
-            var result = json == null ? <String, dynamic>{} : Map.of(json);
+            final localJson = json;
+            final result = localJson == null ? <String, dynamic>{} : Map<String, dynamic>.of(localJson);
             result['type'] = 'TimelineEvent';
             return result;
           }
@@ -1618,19 +1671,25 @@
     } else {
       if (isResponse) {
         gen.writeln('@override');
+        gen.writeln("String get type => '$rawName';");
+        gen.writeln();
+      }
+
+      if (isResponse) {
+        gen.writeln('@override');
       }
       gen.writeln('Map<String, dynamic> toJson() {');
       if (superName == null || superName == 'Response') {
         // The base Response type doesn't have a toJson
-        gen.writeln('var json = <String, dynamic>{};');
+        gen.writeln('final json = <String, dynamic>{};');
       } else {
-        gen.writeln('var json = super.toJson();');
+        gen.writeln('final json = super.toJson();');
       }
 
       // Only Response objects have a `type` field, as defined by protocol.
       if (isResponse) {
         // Overwrites "type" from the super class if we had one.
-        gen.writeln("json['type'] = '$rawName';");
+        gen.writeln("json['type'] = type;");
       }
 
       var requiredFields = fields.where((f) => !f.optional);
@@ -1682,7 +1741,8 @@
         }
         gen.writeln("String toString() => '[${name} ' //\n'${properties}]';");
       } else {
-        gen.writeln("String toString() => '[${name} ${properties}]';");
+        final formattedProperties = (properties.isEmpty) ? '' : ' $properties';
+        gen.writeln("String toString() => '[$name$formattedProperties]';");
       }
     } else {
       gen.writeln("String toString() => '[${name}]';");
@@ -1696,20 +1756,21 @@
     gen.writeDocs('''This function maps a token position to a line number.
 The VM considers the first line to be line 1.''');
     gen.writeln(
-        'int getLineNumberFromTokenPos(int tokenPos) => _tokenToLine[tokenPos];');
+        'int? getLineNumberFromTokenPos(int tokenPos) => _tokenToLine[tokenPos];');
     gen.writeln();
     gen.writeDocs('''This function maps a token position to a column number.
 The VM considers the first column to be column 1.''');
     gen.writeln(
-        'int getColumnNumberFromTokenPos(int tokenPos) => _tokenToColumn[tokenPos];');
+        'int? getColumnNumberFromTokenPos(int tokenPos) => _tokenToColumn[tokenPos];');
     gen.writeln();
     gen.writeln('''
 void _parseTokenPosTable() {
-  if (tokenPosTable == null) {
+  final tokenPositionTable = tokenPosTable;
+  if (tokenPositionTable == null) {
     return;
   }
-  final lineSet = Set<int>();
-  for (List line in tokenPosTable) {
+  final lineSet = <int>{};
+  for (List line in tokenPositionTable) {
     // Each entry begins with a line number...
     int lineNumber = line[0];
     lineSet.add(lineNumber);
@@ -1726,7 +1787,6 @@
 
   // Writes the code to retrieve the serialized value of a field.
   void generateSerializedFieldAccess(TypeField field, DartGenerator gen) {
-    var nullAware = field.optional ? '?' : '';
     if (field.type.isSimple || field.type.isEnum) {
       gen.write('${field.generatableName}');
       if (field.defaultValue != null) {
@@ -1734,18 +1794,18 @@
       }
     } else if (name == 'Event' && field.name == 'extensionData') {
       // Special case `Event.extensionData`.
-      gen.writeln('extensionData$nullAware.data');
+      gen.writeln('extensionData?.data');
     } else if (field.type.isArray) {
-      gen.write('${field.generatableName}$nullAware.map((f) => f');
+      gen.write('${field.generatableName}?.map((f) => f');
       // Special case `tokenPosTable` which is a List<List<int>>.
       if (field.name == 'tokenPosTable') {
-        gen.write('$nullAware.toList()');
+        gen.write('.toList()');
       } else if (!field.type.types.first.isListTypeSimple) {
-        gen.write('$nullAware.toJson()');
+        gen.write('.toJson()');
       }
-      gen.write(')$nullAware.toList()');
+      gen.write(').toList()');
     } else {
-      gen.write('${field.generatableName}$nullAware.toJson()');
+      gen.write('${field.generatableName}?.toJson()');
     }
   }
 
@@ -1759,9 +1819,9 @@
           TypeRef arrayType = type.types.first;
           if (arrayType.arrayDepth == 1) {
             String assertMethodName = 'assertListOf' +
-                arrayType.name.substring(0, 1).toUpperCase() +
-                arrayType.name.substring(1);
-            gen.writeln('$assertMethodName(obj.${field.generatableName});');
+                arrayType.name!.substring(0, 1).toUpperCase() +
+                arrayType.name!.substring(1);
+            gen.writeln('$assertMethodName(obj.${field.generatableName}!);');
           } else {
             gen.writeln(
                 '// assert obj.${field.generatableName} is ${type.name}');
@@ -1774,9 +1834,9 @@
             gen.writeln(
                 'if (obj.${field.generatableName} is vms.${typeRef.name}) {');
             String assertMethodName = 'assert' +
-                typeRef.name.substring(0, 1).toUpperCase() +
-                typeRef.name.substring(1);
-            gen.writeln('$assertMethodName(obj.${field.generatableName});');
+                typeRef.name!.substring(0, 1).toUpperCase() +
+                typeRef.name!.substring(1);
+            gen.writeln('$assertMethodName(obj.${field.generatableName}!);');
           }
           gen.writeln('} else {');
           gen.writeln(
@@ -1784,9 +1844,9 @@
           gen.writeln('}');
         } else {
           String assertMethodName = 'assert' +
-              type.name.substring(0, 1).toUpperCase() +
-              type.name.substring(1);
-          gen.writeln('$assertMethodName(obj.${field.generatableName});');
+              type.name!.substring(0, 1).toUpperCase() +
+              type.name!.substring(1);
+          gen.writeln('$assertMethodName(obj.${field.generatableName}!);');
         }
       }
     }
@@ -1806,19 +1866,19 @@
     gen.writeln('');
   }
 
-  void _parse(Token token) => TypeParser(token).parseInto(this);
+  void _parse(Token? token) => TypeParser(token).parseInto(this);
 
   void calculateFieldOverrides() {
     for (TypeField field in fields.toList()) {
       if (superName == null) continue;
 
-      if (getSuper().hasField(field.name)) {
+      if (getSuper()!.hasField(field.name)) {
         field.setOverrides();
       }
     }
   }
 
-  bool hasField(String name) {
+  bool hasField(String? name) {
     if (fields.any((field) => field.name == name)) return true;
     return getSuper()?.hasField(name) ?? false;
   }
@@ -1836,19 +1896,19 @@
   };
 
   final Type parent;
-  final String _docs;
+  final String? _docs;
   MemberType type = MemberType();
-  String name;
+  String? name;
   bool optional = false;
-  String defaultValue;
+  String? defaultValue;
   bool overrides = false;
 
   TypeField(this.parent, this._docs);
 
   void setOverrides() => overrides = true;
 
-  String get docs {
-    String str = _docs == null ? '' : _docs;
+  String? get docs {
+    String str = _docs == null ? '' : _docs!;
     if (type.isMultipleReturns) {
       str += '\n\n[${generatableName}] can be one of '
           '${joinLast(type.types.map((t) => '[${t}]'), ', ', ' or ')}.';
@@ -1857,26 +1917,37 @@
     return str;
   }
 
-  String get generatableName {
+  String? get generatableName {
     return _nameRemap[name] != null ? _nameRemap[name] : name;
   }
 
   void generate(DartGenerator gen) {
-    if (docs.isNotEmpty) gen.writeDocs(docs);
+    if (docs!.isNotEmpty) gen.writeDocs(docs);
     if (optional) gen.write('@optional ');
     if (overrides) gen.write('@override ');
-    String typeName =
-        api.isEnumName(type.name) ? '/*${type.name}*/ String' : type.name;
-    gen.writeStatement('${typeName} ${generatableName};');
-    if (parent.fields.any((field) => field.hasDocs)) gen.writeln();
+    // Special case where Instance extends Obj, but 'classRef' is not optional
+    // for Instance although it is for Obj.
+    /*if (parent.name == 'Instance' && generatableName == 'classRef') {
+      gen.writeStatement('covariant late final ClassRef classRef;');
+    } else if (parent.name!.contains('NullVal') &&
+        generatableName == 'valueAsString') {
+      gen.writeStatement('covariant late final String valueAsString;');
+    } else */
+    {
+      String? typeName =
+          api.isEnumName(type.name) ? '/*${type.name}*/ String' : type.name;
+      typeName = '$typeName?';
+      gen.writeStatement('${typeName} ${generatableName};');
+      if (parent.fields.any((field) => field.hasDocs)) gen.writeln();
+    }
   }
 
   void generateNamedParameter(DartGenerator gen, {bool fromParent = false}) {
     if (!optional) {
-      gen.write('@required ');
+      gen.write('required ');
     }
     if (fromParent) {
-      String typeName =
+      String? typeName =
           api.isEnumName(type.name) ? '/*${type.name}*/ String' : type.name;
       gen.writeStatement('$typeName ${generatableName},');
     } else {
@@ -1887,7 +1958,7 @@
 
 class Enum extends Member {
   final String name;
-  final String docs;
+  final String? docs;
 
   List<EnumValue> enums = [];
 
@@ -1900,7 +1971,7 @@
   factory Enum.merge(Enum e1, Enum e2) {
     final String name = e1.name;
     final String docs = [e1.docs, e2.docs].where((e) => e != null).join('\n');
-    final Map<String, EnumValue> map = <String, EnumValue>{};
+    final Map<String?, EnumValue> map = <String?, EnumValue>{};
     for (EnumValue e in e2.enums.reversed) {
       map[e.name] = e;
     }
@@ -1930,7 +2001,7 @@
   void generateAssert(DartGenerator gen) {
     gen.writeln('String assert${name}(String obj) {');
     List<EnumValue> sorted = enums.toList()
-      ..sort((EnumValue e1, EnumValue e2) => e1.name.compareTo(e2.name));
+      ..sort((EnumValue e1, EnumValue e2) => e1.name!.compareTo(e2.name!));
     for (EnumValue value in sorted) {
       gen.writeln('  if (obj == "${value.name}") return obj;');
     }
@@ -1939,13 +2010,13 @@
     gen.writeln('');
   }
 
-  void _parse(Token token) => EnumParser(token).parseInto(this);
+  void _parse(Token? token) => EnumParser(token).parseInto(this);
 }
 
 class EnumValue extends Member {
   final Enum parent;
-  final String name;
-  final String docs;
+  final String? name;
+  final String? docs;
 
   EnumValue(this.parent, this.name, [this.docs]);
 
@@ -1996,7 +2067,7 @@
   }
 
   void visitText(Text text) {
-    String t = text.text;
+    String? t = text.text;
     if (_em) {
       t = _coerceRefType(t);
     } else if (_href) {
@@ -2039,7 +2110,7 @@
 //     string targetId [optional],
 //     string expression)
 class MethodParser extends Parser {
-  MethodParser(Token startToken) : super(startToken);
+  MethodParser(Token? startToken) : super(startToken);
 
   void parseInto(Method method) {
     // method is return type, name, (, args )
@@ -2053,21 +2124,21 @@
 
     expect('(');
 
-    while (peek().text != ')') {
+    while (peek()!.text != ')') {
       Token type = expectName();
       TypeRef ref = TypeRef(_coerceRefType(type.text));
-      if (peek().text == '[') {
+      if (peek()!.text == '[') {
         while (consume('[')) {
           expect(']');
           ref.arrayDepth++;
         }
-      } else if (peek().text == '<') {
+      } else if (peek()!.text == '<') {
         // handle generics
         expect('<');
         ref.genericTypes = [];
-        while (peek().text != '>') {
+        while (peek()!.text != '>') {
           Token genericTypeName = expectName();
-          ref.genericTypes.add(TypeRef(_coerceRefType(genericTypeName.text)));
+          ref.genericTypes!.add(TypeRef(_coerceRefType(genericTypeName.text)));
           consume(',');
         }
         expect('>');
@@ -2095,7 +2166,7 @@
 }
 
 class TypeParser extends Parser {
-  TypeParser(Token startToken) : super(startToken);
+  TypeParser(Token? startToken) : super(startToken);
 
   void parseInto(Type type) {
     // class ClassList extends Response {
@@ -2114,7 +2185,7 @@
 
     expect('{');
 
-    while (peek().text != '}') {
+    while (peek()!.text != '}') {
       TypeField field = TypeField(type, collectComments());
       field.type.parse(this);
       field.name = expectName().text;
@@ -2137,6 +2208,8 @@
       dataField.name = 'data';
       dataField.optional = true;
       type.fields.add(dataField);
+    } else if (type.rawName == 'Response') {
+      type.fields.removeWhere((field) => field.name == 'type');
     }
 
     expect('}');
@@ -2144,7 +2217,7 @@
 }
 
 class EnumParser extends Parser {
-  EnumParser(Token startToken) : super(startToken);
+  EnumParser(Token? startToken) : super(startToken);
 
   void parseInto(Enum e) {
     // enum ErrorKind { UnhandledException, Foo, Bar }
@@ -2157,7 +2230,7 @@
 
     while (!t.eof) {
       if (consume('}')) break;
-      String docs = collectComments();
+      String? docs = collectComments();
       t = expectName();
       consume(',');
 
diff --git a/pkg/vm_service/tool/dart/src_gen_dart.dart b/pkg/vm_service/tool/dart/src_gen_dart.dart
index 15cf723..e343e37 100644
--- a/pkg/vm_service/tool/dart/src_gen_dart.dart
+++ b/pkg/vm_service/tool/dart/src_gen_dart.dart
@@ -25,7 +25,7 @@
   /// Write out the given dartdoc text, wrapping lines as necessary to flow
   /// along the column boundary. If [preferSingle] is true, and the docs would
   /// fit on a single line, use `///` dartdoc style.
-  void writeDocs(String docs) {
+  void writeDocs(String? docs) {
     if (docs == null) return;
 
     docs = wrap(docs.trim(), colBoundary - _indent.length - 4);
diff --git a/pkg/vm_service/tool/generate.dart b/pkg/vm_service/tool/generate.dart
index 28dc548..bea71f8 100644
--- a/pkg/vm_service/tool/generate.dart
+++ b/pkg/vm_service/tool/generate.dart
@@ -4,6 +4,9 @@
 
 import 'dart:io';
 
+// TODO(bkonyi): remove once markdown and pub_semver deps are updated to null
+// safety for the SDK.
+// ignore_for_file: import_of_legacy_library_into_null_safe
 import 'package:markdown/markdown.dart';
 import 'package:path/path.dart';
 import 'package:pub_semver/pub_semver.dart';
@@ -132,8 +135,8 @@
     if (line.startsWith(pattern)) {
       found = true;
       Version v = Version.parse(line.substring(pattern.length));
-      String pre = v.preRelease.isEmpty ? null : v.preRelease.join('-');
-      String build = v.build.isEmpty ? null : v.build.join('+');
+      String? pre = v.preRelease.isEmpty ? null : v.preRelease.join('-');
+      String? build = v.build.isEmpty ? null : v.build.join('+');
       v = Version(version.major, version.minor, v.patch,
           pre: pre, build: build);
       return '${pattern}${v.toString()}';
diff --git a/pkg/vm_service/tool/java/generate_java.dart b/pkg/vm_service/tool/java/generate_java.dart
index 675ce5b..3a3567a 100644
--- a/pkg/vm_service/tool/java/generate_java.dart
+++ b/pkg/vm_service/tool/java/generate_java.dart
@@ -4,6 +4,9 @@
 
 library generate_vm_service_java;
 
+// TODO(bkonyi): remove once markdown and pub_semver deps are updated to null
+// safety for the SDK.
+// ignore_for_file: import_of_legacy_library_into_null_safe
 import 'package:markdown/markdown.dart';
 import 'package:pub_semver/pub_semver.dart';
 
@@ -50,11 +53,11 @@
 from within any {@link Consumer} method.
 ''';
 
-Api api;
+late Api api;
 
 /// Convert documentation references
 /// from spec style of [className] to javadoc style {@link className}
-String convertDocLinks(String doc) {
+String? convertDocLinks(String? doc) {
   if (doc == null) return null;
   var sb = StringBuffer();
   int start = 0;
@@ -78,14 +81,14 @@
   return sb.toString();
 }
 
-String _coerceRefType(String typeName) {
+String? _coerceRefType(String? typeName) {
   if (typeName == 'Class') typeName = 'ClassObj';
   if (typeName == 'Error') typeName = 'ErrorObj';
   if (typeName == 'Object') typeName = 'Obj';
   if (typeName == '@Object') typeName = 'ObjRef';
   if (typeName == 'Function') typeName = 'Func';
   if (typeName == '@Function') typeName = 'FuncRef';
-  if (typeName.startsWith('@')) typeName = typeName.substring(1) + 'Ref';
+  if (typeName!.startsWith('@')) typeName = typeName.substring(1) + 'Ref';
   if (typeName == 'string') typeName = 'String';
   if (typeName == 'bool') typeName = 'boolean';
   if (typeName == 'num') typeName = 'BigDecimal';
@@ -94,20 +97,20 @@
 }
 
 class Api extends Member with ApiParseUtil {
-  int serviceMajor;
-  int serviceMinor;
-  String serviceVersion;
+  int? serviceMajor;
+  int? serviceMinor;
+  String? serviceVersion;
   List<Method> methods = [];
-  List<Enum> enums = [];
-  List<Type> types = [];
+  List<Enum?> enums = [];
+  List<Type?> types = [];
   Map<String, List<String>> streamIdMap = {};
 
-  String get docs => null;
+  String? get docs => null;
 
   String get name => 'api';
 
-  void addProperty(String typeName, String propertyName, {String javadoc}) {
-    var t = types.firstWhere((t) => t.name == typeName);
+  void addProperty(String typeName, String propertyName, {String? javadoc}) {
+    var t = types.firstWhere((t) => t!.name == typeName)!;
     for (var f in t.fields) {
       if (f.name == propertyName) {
         print('$typeName already has $propertyName field');
@@ -133,13 +136,13 @@
     for (var m in methods) {
       for (var a in m.args) {
         if (a.hasDocs) continue;
-        var t = types.firstWhere((Type t) => t.name == a.type.name,
+        var t = types.firstWhere((Type? t) => t!.name == a.type.name,
             orElse: () => null);
         if (t != null) {
           a.docs = t.docs;
           continue;
         }
-        var e = enums.firstWhere((Enum e) => e.name == a.type.name,
+        var e = enums.firstWhere((Enum? e) => e!.name == a.type.name,
             orElse: () => null);
         if (e != null) {
           a.docs = e.docs;
@@ -234,17 +237,18 @@
       m.generateConsumerInterface(gen);
     }
     for (var t in types) {
-      t.generateElement(gen);
+      t!.generateElement(gen);
     }
     for (var e in enums) {
-      e.generateEnum(gen);
+      e!.generateEnum(gen);
     }
   }
 
-  Type getType(String name) =>
-      types.firstWhere((t) => t.name == name, orElse: () => null);
+  Type? getType(String? name) =>
+      types.firstWhere((t) => t!.name == name, orElse: () => null);
 
-  bool isEnumName(String typeName) => enums.any((Enum e) => e.name == typeName);
+  bool isEnumName(String? typeName) =>
+      enums.any((Enum? e) => e!.name == typeName);
 
   void parse(List<Node> nodes) {
     Version version = ApiParseUtil.parseVersionSemVer(nodes);
@@ -256,17 +260,17 @@
     // the pre following it is the definition
     // the optional p following that is the documentation
 
-    String h3Name;
+    String? h3Name;
 
     for (int i = 0; i < nodes.length; i++) {
       Node node = nodes[i];
 
       if (isPre(node) && h3Name != null) {
         String definition = textForCode(node);
-        String docs;
+        String? docs;
 
         if (i + 1 < nodes.length && isPara(nodes[i + 1])) {
-          Element p = nodes[++i];
+          Element p = nodes[++i] as Element;
           docs = collapseWhitespace(TextOutputVisitor.printText(p));
         }
 
@@ -288,18 +292,18 @@
         }
       }
     }
-    for (Type type in types) {
-      type.calculateFieldOverrides();
+    for (Type? type in types) {
+      type!.calculateFieldOverrides();
     }
   }
 
   void setDefaultValue(String typeName, String propertyName) {
-    var type = types.firstWhere((t) => t.name == typeName);
+    var type = types.firstWhere((t) => t!.name == typeName)!;
     var field = type.fields.firstWhere((f) => f.name == propertyName);
     field.defaultValue = 'false';
   }
 
-  void _parse(String name, String definition, [String docs]) {
+  void _parse(String name, String definition, [String? docs]) {
     name = name.trim();
     definition = definition.trim();
     // clean markdown introduced changes
@@ -361,7 +365,7 @@
 
 class Enum extends Member {
   final String name;
-  final String docs;
+  final String? docs;
 
   List<EnumValue> enums = [];
 
@@ -375,7 +379,7 @@
     gen.writeType(elementTypeName, (TypeWriter writer) {
       writer.javadoc = convertDocLinks(docs);
       writer.isEnum = true;
-      enums.sort((v1, v2) => v1.name.compareTo(v2.name));
+      enums.sort((v1, v2) => v1.name!.compareTo(v2.name!));
       for (var value in enums) {
         writer.addEnumValue(value.name, javadoc: value.docs);
       }
@@ -386,13 +390,13 @@
     });
   }
 
-  void _parse(Token token) {
+  void _parse(Token? token) {
     EnumParser(token).parseInto(this);
   }
 }
 
 class EnumParser extends Parser {
-  EnumParser(Token startToken) : super(startToken);
+  EnumParser(Token? startToken) : super(startToken);
 
   void parseInto(Enum e) {
     // enum ErrorKind { UnhandledException, Foo, Bar }
@@ -405,7 +409,7 @@
 
     while (!t.eof) {
       if (consume('}')) break;
-      String docs = collectComments();
+      String? docs = collectComments();
       t = expectName();
       consume(',');
 
@@ -416,8 +420,8 @@
 
 class EnumValue extends Member {
   final Enum parent;
-  final String name;
-  final String docs;
+  final String? name;
+  final String? docs;
 
   EnumValue(this.parent, this.name, [this.docs]);
 
@@ -425,13 +429,13 @@
 }
 
 abstract class Member {
-  String get docs => null;
+  String? get docs => null;
 
   bool get hasDocs => docs != null;
 
-  String get name;
+  String? get name;
 
-  String toString() => name;
+  String toString() => name!;
 }
 
 class MemberType extends Member {
@@ -449,13 +453,13 @@
 
   bool get isValueAndSentinel => types.length == 2 && hasSentinel;
 
-  String get name {
+  String? get name {
     if (types.isEmpty) return '';
     if (types.length == 1) return types.first.ref;
     return 'dynamic';
   }
 
-  TypeRef get valueType {
+  TypeRef? get valueType {
     if (types.length == 1) return types.first;
     if (isValueAndSentinel) {
       return types.firstWhere((t) => t.name != 'Sentinel');
@@ -492,7 +496,7 @@
 
 class Method extends Member {
   final String name;
-  final String docs;
+  final String? docs;
 
   MemberType returnType = MemberType();
   List<MethodArg> args = [];
@@ -502,7 +506,7 @@
   }
 
   String get consumerTypeName {
-    String prefix;
+    String? prefix;
     if (returnType.isMultipleReturns) {
       prefix = titleCase(name);
     } else {
@@ -531,13 +535,13 @@
   void generateVmServiceForward(StatementWriter writer) {
     var consumerName = classNameFor(consumerTypeName);
     writer.addLine('if (consumer instanceof $consumerName) {');
-    List<Type> types = List.from(returnType.types.map((ref) => ref.type));
+    List<Type?> types = List.from(returnType.types.map((ref) => ref.type));
     for (int index = 0; index < types.length; ++index) {
-      types.addAll(types[index].subtypes);
+      types.addAll(types[index]!.subtypes);
     }
-    types.sort((t1, t2) => t1.name.compareTo(t2.name));
+    types.sort((t1, t2) => t1!.name!.compareTo(t2!.name!));
     for (var t in types) {
-      var responseName = classNameFor(t.elementTypeName);
+      var responseName = classNameFor(t!.elementTypeName!);
       writer.addLine('  if (responseType.equals("${t.rawName}")) {');
       writer.addLine(
           '    (($consumerName) consumer).received(new $responseName(json));');
@@ -557,7 +561,7 @@
 //    }
 
     // Update method docs
-    var javadoc = StringBuffer(docs == null ? '' : docs);
+    var javadoc = StringBuffer(docs == null ? '' : docs!);
     bool firstParamDoc = true;
     for (var a in args) {
       if (!includeOptional && a.optional) continue;
@@ -611,7 +615,7 @@
     }, javadoc: javadoc.toString());
   }
 
-  void _parse(Token token) {
+  void _parse(Token? token) {
     MethodParser(token).parseInto(this);
   }
 }
@@ -619,8 +623,8 @@
 class MethodArg extends Member {
   final Method parent;
   final TypeRef type;
-  String name;
-  String docs;
+  String? name;
+  String? docs;
   bool optional = false;
 
   MethodArg(this.parent, this.type, this.name);
@@ -643,7 +647,7 @@
 }
 
 class MethodParser extends Parser {
-  MethodParser(Token startToken) : super(startToken);
+  MethodParser(Token? startToken) : super(startToken);
 
   void parseInto(Method method) {
     // method is return type, name, (, args )
@@ -657,21 +661,21 @@
 
     expect('(');
 
-    while (peek().text != ')') {
+    while (peek()!.text != ')') {
       Token type = expectName();
       TypeRef ref = TypeRef(_coerceRefType(type.text));
-      if (peek().text == '[') {
+      if (peek()!.text == '[') {
         while (consume('[')) {
           expect(']');
           ref.arrayDepth++;
         }
-      } else if (peek().text == '<') {
+      } else if (peek()!.text == '<') {
         // handle generics
         expect('<');
         ref.genericTypes = [];
-        while (peek().text != '>') {
+        while (peek()!.text != '>') {
           Token genericTypeName = expectName();
-          ref.genericTypes.add(TypeRef(_coerceRefType(genericTypeName.text)));
+          ref.genericTypes!.add(TypeRef(_coerceRefType(genericTypeName.text)));
           consume(',');
         }
         expect('>');
@@ -719,7 +723,7 @@
   }
 
   void visitText(Text text) {
-    String t = text.text;
+    String? t = text.text;
     if (_inRef) t = _coerceRefType(t);
     buf.write(t);
   }
@@ -742,27 +746,27 @@
 
 class Type extends Member {
   final Api parent;
-  String rawName;
-  String name;
-  String superName;
-  final String docs;
+  String? rawName;
+  String? name;
+  String? superName;
+  final String? docs;
   List<TypeField> fields = [];
 
   Type(this.parent, String categoryName, String definition, [this.docs]) {
     _parse(Tokenizer(definition).tokenize());
   }
 
-  String get elementTypeName {
+  String? get elementTypeName {
     if (isSimple) return null;
     return '$servicePackage.element.$name';
   }
 
-  bool get isRef => name.endsWith('Ref');
+  bool get isRef => name!.endsWith('Ref');
 
   bool get isResponse {
     if (superName == null) return false;
     if (name == 'Response' || superName == 'Response') return true;
-    return parent.getType(superName).isResponse;
+    return parent.getType(superName)!.isResponse;
   }
 
   bool get isSimple => simpleTypes.contains(name);
@@ -773,8 +777,8 @@
     return name;
   }
 
-  Iterable<Type> get subtypes =>
-      api.types.toList()..retainWhere((t) => t.superName == name);
+  Iterable<Type?> get subtypes =>
+      api.types.toList()..retainWhere((t) => t!.superName == name);
 
   void generateElement(JavaGenerator gen) {
     gen.writeType('$servicePackage.element.$name', (TypeWriter writer) {
@@ -814,7 +818,7 @@
     List<TypeField> all = [];
     all.insertAll(0, fields);
 
-    Type s = getSuper();
+    Type? s = getSuper();
     while (s != null) {
       all.insertAll(0, s.fields);
       s = s.getSuper();
@@ -823,14 +827,14 @@
     return all;
   }
 
-  Type getSuper() => superName == null ? null : api.getType(superName);
+  Type? getSuper() => superName == null ? null : api.getType(superName);
 
-  bool hasField(String name) {
+  bool hasField(String? name) {
     if (fields.any((field) => field.name == name)) return true;
     return getSuper()?.hasField(name) ?? false;
   }
 
-  void _parse(Token token) {
+  void _parse(Token? token) {
     TypeParser(token).parseInto(this);
   }
 
@@ -838,7 +842,7 @@
     for (TypeField field in fields.toList()) {
       if (superName == null) continue;
 
-      if (getSuper().hasField(field.name)) {
+      if (getSuper()!.hasField(field.name)) {
         field.setOverrides();
       }
     }
@@ -860,11 +864,11 @@
   };
 
   final Type parent;
-  final String _docs;
+  final String? _docs;
   MemberType type = MemberType();
-  String name;
+  String? name;
   bool optional = false;
-  String defaultValue;
+  String? defaultValue;
   bool overrides = false;
 
   TypeField(this.parent, this._docs);
@@ -880,11 +884,11 @@
     } else {
       remappedName = name;
     }
-    return 'get${titleCase(remappedName)}';
+    return 'get${titleCase(remappedName!)}';
   }
 
-  String get docs {
-    String str = _docs == null ? '' : _docs;
+  String? get docs {
+    String str = _docs == null ? '' : _docs!;
     if (type.isMultipleReturns) {
       str += '\n\n@return one of '
           '${joinLast(type.types.map((t) => '<code>${t}</code>'), ', ', ' or ')}';
@@ -904,7 +908,7 @@
         w.addLine('final JsonObject elem = (JsonObject)json.get("$name");');
         w.addLine('if (elem == null) return null;\n');
         for (TypeRef t in type.types) {
-          String refName = t.name;
+          String refName = t.name!;
           if (refName.endsWith('Ref')) {
             refName = "@" + refName.substring(0, refName.length - 3);
           }
@@ -914,7 +918,7 @@
         w.addLine('return null;');
       }, javadoc: docs, returnType: 'Object');
     } else {
-      String returnType = type.valueType.ref;
+      String? returnType = type.valueType!.ref;
       if (name == 'timestamp') {
         returnType = 'long';
       }
@@ -923,7 +927,7 @@
         accessorName,
         [],
         (StatementWriter writer) {
-          type.valueType.generateAccessStatements(
+          type.valueType!.generateAccessStatements(
             writer,
             name,
             canBeSentinel: type.isValueAndSentinel,
@@ -940,7 +944,7 @@
 }
 
 class TypeParser extends Parser {
-  TypeParser(Token startToken) : super(startToken);
+  TypeParser(Token? startToken) : super(startToken);
 
   void parseInto(Type type) {
     // class ClassList extends Response {
@@ -959,7 +963,7 @@
 
     expect('{');
 
-    while (peek().text != '}') {
+    while (peek()!.text != '}') {
       TypeField field = TypeField(type, collectComments());
       field.type.parse(this);
       field.name = expectName().text;
@@ -977,13 +981,13 @@
 }
 
 class TypeRef {
-  String name;
+  String? name;
   int arrayDepth = 0;
-  List<TypeRef> genericTypes;
+  List<TypeRef>? genericTypes;
 
   TypeRef(this.name);
 
-  String get elementTypeName {
+  String? get elementTypeName {
     if (isSimple) return null;
     return '$servicePackage.element.$name';
   }
@@ -991,20 +995,20 @@
   bool get isArray => arrayDepth > 0;
 
   /// Hacked enum determination
-  bool get isEnum => name.endsWith('Kind') || name.endsWith('Mode');
+  bool get isEnum => name!.endsWith('Kind') || name!.endsWith('Mode');
 
   bool get isSimple => simpleTypes.contains(name);
 
-  String get javaBoxedName {
+  String? get javaBoxedName {
     if (name == 'boolean') return 'Boolean';
     if (name == 'int') return 'Integer';
     if (name == 'double') return 'Double';
     return name;
   }
 
-  String get ref {
+  String? get ref {
     if (genericTypes != null) {
-      return '$name<${genericTypes.join(', ')}>';
+      return '$name<${genericTypes!.join(', ')}>';
     } else if (isSimple) {
       if (arrayDepth == 2) return 'List<List<${javaBoxedName}>>';
       if (arrayDepth == 1) return 'List<${javaBoxedName}>';
@@ -1015,13 +1019,13 @@
     return name;
   }
 
-  Type get type => api.types.firstWhere((t) => t.name == name);
+  Type? get type => api.types.firstWhere((t) => t!.name == name);
 
   void generateAccessStatements(
     StatementWriter writer,
-    String propertyName, {
+    String? propertyName, {
     bool canBeSentinel = false,
-    String defaultValue,
+    String? defaultValue,
     bool optional = false,
   }) {
     if (name == 'boolean') {
@@ -1144,5 +1148,5 @@
     }
   }
 
-  String toString() => ref;
+  String toString() => ref!;
 }
diff --git a/pkg/vm_service/tool/java/src_gen_java.dart b/pkg/vm_service/tool/java/src_gen_java.dart
index 91b71e2..b67c203 100644
--- a/pkg/vm_service/tool/java/src_gen_java.dart
+++ b/pkg/vm_service/tool/java/src_gen_java.dart
@@ -15,7 +15,7 @@
 int colBoundary = 100;
 
 /// The header for every generated file.
-String fileHeader;
+String? fileHeader;
 
 String classNameFor(String typeName) {
   // Convert ElementList<Foo> param declarations to List<Foo> declarations.
@@ -71,8 +71,8 @@
 }
 
 class JavaMethodArg {
-  final String name;
-  final String typeName;
+  final String? name;
+  final String? typeName;
 
   JavaMethodArg(this.name, this.typeName);
 }
@@ -115,10 +115,10 @@
   final String className;
   bool isInterface = false;
   bool isEnum = false;
-  String javadoc;
+  String? javadoc;
   String modifiers = 'public';
   final Set<String> _imports = Set<String>();
-  String superclassName;
+  String? superclassName;
   List<String> interfaceNames = <String>[];
   final StringBuffer _content = StringBuffer();
   final List<String> _fields = <String>[];
@@ -135,7 +135,7 @@
   }
 
   void addConstructor(Iterable<JavaMethodArg> args, WriteStatements write,
-      {String javadoc, String modifiers = 'public'}) {
+      {String? javadoc, String modifiers = 'public'}) {
     _content.writeln();
     if (javadoc != null && javadoc.isNotEmpty) {
       _content.writeln('  /**');
@@ -146,22 +146,18 @@
     }
     _content.write('  $modifiers $className(');
     _content.write(
-        args.map((a) => '${classNameFor(a.typeName)} ${a.name}').join(', '));
+        args.map((a) => '${classNameFor(a.typeName!)} ${a.name}').join(', '));
     _content.write(')');
-    if (write != null) {
-      _content.writeln(' {');
-      StatementWriter writer = StatementWriter(this);
-      write(writer);
-      _content.write(writer.toSource());
-      _content.writeln('  }');
-    } else {
-      _content.writeln(';');
-    }
+    _content.writeln(' {');
+    StatementWriter writer = StatementWriter(this);
+    write(writer);
+    _content.write(writer.toSource());
+    _content.writeln('  }');
   }
 
   void addEnumValue(
-    String name, {
-    String javadoc,
+    String? name, {
+    String? javadoc,
     bool isLast = false,
   }) {
     _content.writeln();
@@ -181,7 +177,7 @@
   }
 
   void addField(String name, String typeName,
-      {String modifiers = 'public', String value, String javadoc}) {
+      {String modifiers = 'public', String? value, String? javadoc}) {
     var fieldDecl = StringBuffer();
     if (javadoc != null && javadoc.isNotEmpty) {
       fieldDecl.writeln('  /**');
@@ -191,7 +187,7 @@
       fieldDecl.writeln('   */');
     }
     fieldDecl.write('  ');
-    if (modifiers != null && modifiers.isNotEmpty) {
+    if (modifiers.isNotEmpty) {
       fieldDecl.write('$modifiers ');
     }
     fieldDecl.write('$typeName $name');
@@ -202,7 +198,7 @@
     _fields.add(fieldDecl.toString());
   }
 
-  void addImport(String typeName) {
+  void addImport(String? typeName) {
     if (typeName == null || typeName.isEmpty) return;
     var pkgName = pkgNameFor(typeName);
     if (pkgName.isNotEmpty && pkgName != this.pkgName) {
@@ -213,10 +209,10 @@
   void addMethod(
     String name,
     Iterable<JavaMethodArg> args,
-    WriteStatements write, {
-    String javadoc,
-    String modifiers = 'public',
-    String returnType = 'void',
+    WriteStatements? write, {
+    String? javadoc,
+    String? modifiers = 'public',
+    String? returnType = 'void',
     bool isOverride = false,
   }) {
     var methodDecl = StringBuffer();
@@ -238,7 +234,8 @@
     }
     methodDecl.write('$returnType $name(');
     methodDecl.write(args
-        .map((JavaMethodArg arg) => '${classNameFor(arg.typeName)} ${arg.name}')
+        .map(
+            (JavaMethodArg arg) => '${classNameFor(arg.typeName!)} ${arg.name}')
         .join(', '));
     methodDecl.write(')');
     if (write != null) {
@@ -260,10 +257,8 @@
   String toSource() {
     var buffer = StringBuffer();
     if (fileHeader != null) buffer.write(fileHeader);
-    if (pkgName != null) {
-      buffer.writeln('package $pkgName;');
-      buffer.writeln();
-    }
+    buffer.writeln('package $pkgName;');
+    buffer.writeln();
     buffer.writeln('// This is a generated file.');
     buffer.writeln();
     addImport(superclassName);
@@ -275,9 +270,9 @@
       }
       buffer.writeln();
     }
-    if (javadoc != null && javadoc.isNotEmpty) {
+    if (javadoc != null && javadoc!.isNotEmpty) {
       buffer.writeln('/**');
-      wrap(javadoc.trim(), colBoundary - 4)
+      wrap(javadoc!.trim(), colBoundary - 4)
           .split('\n')
           .forEach((line) => buffer.writeln(' * $line'));
       buffer.writeln(' */');
@@ -287,7 +282,7 @@
 
     buffer.write('$modifiers $kind $className');
     if (superclassName != null) {
-      buffer.write(' extends ${classNameFor(superclassName)}');
+      buffer.write(' extends ${classNameFor(superclassName!)}');
     }
     if (interfaceNames.isNotEmpty) {
       var classNames = interfaceNames.map((t) => classNameFor(t));
diff --git a/pkg/wasm/README.md b/pkg/wasm/README.md
index 8bf6c4b..ce842cd 100644
--- a/pkg/wasm/README.md
+++ b/pkg/wasm/README.md
@@ -2,3 +2,7 @@
 
 This package provides utilities for loading and running WASM modules. It is
 built on top of the [Wasmer](https://github.com/wasmerio/wasmer) runtime.
+
+## Setup
+
+Run `dart bin/setup.dart` to build the Wasmer runtime.
diff --git a/pkg/wasm/bin/.gitignore b/pkg/wasm/bin/.gitignore
new file mode 100644
index 0000000..8b44e90
--- /dev/null
+++ b/pkg/wasm/bin/.gitignore
@@ -0,0 +1,2 @@
+Cargo.lock
+/out
diff --git a/pkg/wasm/bin/Cargo.toml b/pkg/wasm/bin/Cargo.toml
new file mode 100644
index 0000000..a476549
--- /dev/null
+++ b/pkg/wasm/bin/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "wasmer"
+version = "1.0.0-alpha5"
+
+[lib]
+name = "wasmer"
+crate-type = ["staticlib"]
+path = "wasmer.rs"
+
+[dependencies.wasmer-c-api]
+version = "1.0.0-alpha5"
+default-features = false
+features = ["jit", "cranelift", "wasi"]
diff --git a/pkg/wasm/bin/finalizers.cc b/pkg/wasm/bin/finalizers.cc
new file mode 100644
index 0000000..192277e
--- /dev/null
+++ b/pkg/wasm/bin/finalizers.cc
@@ -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.
+
+#include "include/dart_api.h"
+#include "include/dart_api_dl.h"
+
+#define FINALIZER(type)                                                        \
+  extern "C" void wasm_##type##_delete(void*);                                 \
+  extern "C" void wasm_##type##_finalizer(void*, void* native_object) {        \
+    wasm_##type##_delete(native_object);                                       \
+  }                                                                            \
+  DART_EXPORT void set_finalizer_for_##type(Dart_Handle dart_object,           \
+                                            void* native_object) {             \
+    Dart_NewFinalizableHandle_DL(dart_object, native_object, 0,                \
+                                 wasm_##type##_finalizer);                     \
+  }
+
+FINALIZER(engine);
+FINALIZER(store);
+FINALIZER(module);
+FINALIZER(instance);
+FINALIZER(trap);
+FINALIZER(memorytype);
+FINALIZER(memory);
+FINALIZER(func);
diff --git a/pkg/wasm/bin/setup.dart b/pkg/wasm/bin/setup.dart
new file mode 100644
index 0000000..2e8fcad
--- /dev/null
+++ b/pkg/wasm/bin/setup.dart
@@ -0,0 +1,165 @@
+// 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.
+
+// Builds the wasmer runtime library, to by used by package:wasm. Requires
+// rustc, cargo, clang, and clang++. If a target triple is not specified, it
+// will default to the host target.
+// Usage: dart setup.dart [target-triple]
+
+import 'dart:convert';
+import 'dart:io';
+
+Uri getSdkDir() {
+  // The common case, and how cli_util.dart computes the Dart SDK directory,
+  // path.dirname called twice on Platform.resolvedExecutable.
+  final exe = Uri.file(Platform.resolvedExecutable);
+  final commonSdkDir = exe.resolve('../..');
+  if (Directory(commonSdkDir.path).existsSync()) {
+    return commonSdkDir;
+  }
+
+  // This is the less common case where the user is in the checked out Dart
+  // SDK, and is executing dart via:
+  // ./out/ReleaseX64/dart ...
+  final checkedOutSdkDir = exe.resolve('../dart-sdk');
+  if (Directory(checkedOutSdkDir.path).existsSync()) {
+    return checkedOutSdkDir;
+  }
+
+  // If neither returned above, we return the common case:
+  return commonSdkDir;
+}
+
+String getOutLib(String target) {
+  final os = RegExp(r'^.*-.*-(.*)').firstMatch(target)?.group(1) ?? '';
+  if (os == 'darwin' || os == 'ios') {
+    return 'libwasmer.dylib';
+  } else if (os == 'windows') {
+    return 'wasmer.dll';
+  }
+  return 'libwasmer.so';
+}
+
+getTargetTriple() async {
+  final process = await Process.start('rustc', ['--print', 'cfg']);
+  process.stderr
+      .transform(utf8.decoder)
+      .transform(const LineSplitter())
+      .listen((line) => stderr.writeln(line));
+  final cfg = {};
+  await process.stdout
+      .transform(utf8.decoder)
+      .transform(const LineSplitter())
+      .listen((line) {
+    final match = RegExp(r'^([^=]+)="(.*)"$').firstMatch(line);
+    if (match != null) cfg[match.group(1)] = match.group(2);
+  }).asFuture();
+  String arch = cfg['target_arch'] ?? 'unknown';
+  String vendor = cfg['target_vendor'] ?? 'unknown';
+  String os = cfg['target_os'] ?? 'unknown';
+  String env = cfg['target_env'] ?? 'unknown';
+  return '$arch-$vendor-$os-$env';
+}
+
+run(String exe, List<String> args) async {
+  print('\n$exe ${args.join(' ')}\n');
+  final process = await Process.start(exe, args);
+  process.stdout
+      .transform(utf8.decoder)
+      .transform(const LineSplitter())
+      .listen((line) => print(line));
+  process.stderr
+      .transform(utf8.decoder)
+      .transform(const LineSplitter())
+      .listen((line) => stderr.writeln(line));
+  final exitCode = await process.exitCode;
+  if (exitCode != 0) {
+    print('Command failed with exit code ${exitCode}');
+    exit(exitCode);
+  }
+}
+
+main(List<String> args) async {
+  if (args.length > 1) {
+    print('Usage: dart setup.dart [target-triple]');
+    exit(1);
+  }
+
+  final target = args.length >= 1 ? args[0] : await getTargetTriple();
+  final sdkDir = getSdkDir();
+  final binDir = Platform.script;
+  final outLib = binDir.resolve('out/' + getOutLib(target)).path;
+
+  print('Dart SDK directory: ${sdkDir.path}');
+  print('Script directory: ${binDir.path}');
+  print('Target: $target');
+  print('Output library: $outLib');
+
+  // Build wasmer crate.
+  await run('cargo', [
+    'build',
+    '--target',
+    target,
+    '--target-dir',
+    binDir.resolve('out').path,
+    '--manifest-path',
+    binDir.resolve('Cargo.toml').path,
+    '--release'
+  ]);
+
+  // Build dart_api_dl.o.
+  await run('clang', [
+    '-DDART_SHARED_LIB',
+    '-DNDEBUG',
+    '-fno-exceptions',
+    '-fPIC',
+    '-O3',
+    '-target',
+    target,
+    '-c',
+    sdkDir.resolve('runtime/include/dart_api_dl.c').path,
+    '-o',
+    binDir.resolve('out/dart_api_dl.o').path
+  ]);
+
+  // Build finalizers.o.
+  await run('clang++', [
+    '-DDART_SHARED_LIB',
+    '-DNDEBUG',
+    '-fno-exceptions',
+    '-fno-rtti',
+    '-fPIC',
+    '-O3',
+    '-std=c++11',
+    '-target',
+    target,
+    '-I',
+    sdkDir.resolve('runtime').path,
+    '-c',
+    binDir.resolve('finalizers.cc').path,
+    '-o',
+    binDir.resolve('out/finalizers.o').path
+  ]);
+
+  // Link wasmer, dart_api_dl, and finalizers to create the output library.
+  await run('clang++', [
+    '-shared',
+    '-Wl,--no-as-needed',
+    '-Wl,--fatal-warnings',
+    '-Wl,-z,now',
+    '-Wl,-z,noexecstack',
+    '-Wl,-z,relro',
+    '-Wl,--build-id=none',
+    '-fPIC',
+    '-Wl,-O1',
+    '-Wl,--gc-sections',
+    '-target',
+    target,
+    binDir.resolve('out/dart_api_dl.o').path,
+    binDir.resolve('out/finalizers.o').path,
+    binDir.resolve('out/' + target + '/release/libwasmer.a').path,
+    '-o',
+    outLib
+  ]);
+}
diff --git a/pkg/wasm/bin/wasmer.rs b/pkg/wasm/bin/wasmer.rs
new file mode 100644
index 0000000..c4bd6e5
--- /dev/null
+++ b/pkg/wasm/bin/wasmer.rs
@@ -0,0 +1 @@
+pub extern crate wasmer_c_api;
diff --git a/pkg/wasm/example/README.md b/pkg/wasm/example/README.md
new file mode 100644
index 0000000..c809dc66
--- /dev/null
+++ b/pkg/wasm/example/README.md
@@ -0,0 +1,29 @@
+# Example usage of package:wasm
+
+This example demonstrates how to use package:wasm to run a wasm build of the [Brotli compression library](https://github.com/google/brotli).
+
+### Running the example
+
+`dart brotli.dart lipsum.txt`
+
+This will compress lipsum.txt, report the compression ratio, then decompress it and verify that the result matches the input.
+
+### Generating wasm code
+
+libbrotli.wasm was built by cloning the [Brotli repo](https://github.com/google/brotli), and compiling it using [wasienv](https://github.com/wasienv/wasienv).
+
+There are several ways of building wasm code. The most important difference between the tool sets is how the wasm code they generate interacts with the OS. For very simple code this difference doesn't matter. But if the library does any sort of OS interaction, such as file IO, or even using malloc, it will need to use either Emscripten or WASI for that interaction. package:wasm only supports WASI at the moment.
+
+To target WASI, one option is to use [wasi-libc](https://github.com/WebAssembly/wasi-libc) and a recent version of clang. Set the target to `--target=wasm32-unknown-wasi` and the `--sysroot` to wasi-libc.
+
+Another option is to build using [wasienv](https://github.com/wasienv/wasienv), which is a set of tools that are essentially just an ergonomic wrapper around the clang + wasi-libc approach. This is how libbrotli.wasm was built:
+
+1. Install [wasienv](https://github.com/wasienv/wasienv) and clone the [Brotli repo](https://github.com/google/brotli).
+2. Compile every .c file in brotli/c/common/, dec/, and enc/, using wasicc:
+`wasicc -c foo.c -o out/foo.o -I c/include`
+3. Link all the .o files together using wasild:
+`wasild --no-entry --export=bar out/foo.o $wasienv_sysroot/lib/wasm32-wasi/libc.a`
+The `--no-entry` flag tells the linker to ignore the fact that there's no `main()` function, which is important for libraries.
+`--export=bar` will export the `bar()` function from the library, so that it can be found by package:wasm. For libbrotli.wasm, every function in c/include/brotli/encode.h and decode.h was exported.
+Brotli used functions from libc, so the wasm version of libc that comes with wasienv was also linked in.
+If there are still undefined symbols after linking in the wasi libraries, the `--allow-undefined` flag tells the linker to treat undefined symbols as function imports. These functions can then be supplied from Dart code.
diff --git a/pkg/wasm/example/brotli.dart b/pkg/wasm/example/brotli.dart
new file mode 100644
index 0000000..e9520e3
--- /dev/null
+++ b/pkg/wasm/example/brotli.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.
+
+// Example of using package:wasm to run a wasm build of the Brotli compression
+// library. Usage:
+// dart brotli.dart input.txt
+
+import 'dart:convert';
+import "dart:io";
+import "dart:typed_data";
+import "package:wasm/wasm.dart";
+
+// Brotli compression parameters.
+const int kDefaultQuality = 11;
+const int kDefaultWindow = 22;
+const int kDefaultMode = 0;
+
+main(List<String> args) {
+  var brotliPath = Platform.script.resolve('libbrotli.wasm');
+  var moduleData = File(brotliPath.path).readAsBytesSync();
+  var module = WasmModule(moduleData);
+  print(module.describe());
+
+  var instance = module.instantiate().enableWasi().build();
+  var memory = instance.memory;
+  var compress = instance.lookupFunction("BrotliEncoderCompress");
+  var decompress = instance.lookupFunction("BrotliDecoderDecompress");
+
+  print("Loading ${args[0]}");
+  var inputData = File(args[0]).readAsBytesSync();
+  print("Input size: ${inputData.length} bytes");
+
+  // Grow the module's memory to get unused space to put our data.
+  // [initial memory][input data][output data][size][decoded data][size]
+  var inputPtr = memory.lengthInBytes;
+  memory.grow((3 * inputData.length / WasmMemory.kPageSizeInBytes).ceil());
+  var memoryView = memory.view;
+  var outputPtr = inputPtr + inputData.length;
+  var outSizePtr = outputPtr + inputData.length;
+  var decodedPtr = outSizePtr + 4;
+  var decSizePtr = decodedPtr + inputData.length;
+
+  memoryView.setRange(inputPtr, inputPtr + inputData.length, inputData);
+
+  var sizeBytes = ByteData(4);
+  sizeBytes.setUint32(0, inputData.length, Endian.host);
+  memoryView.setRange(
+      outSizePtr, outSizePtr + 4, sizeBytes.buffer.asUint8List());
+
+  print("\nCompressing...");
+  var status = compress(kDefaultQuality, kDefaultWindow, kDefaultMode,
+      inputData.length, inputPtr, outSizePtr, outputPtr);
+  print("Compression status: $status");
+
+  var compressedSize =
+      ByteData.sublistView(memoryView, outSizePtr, outSizePtr + 4)
+          .getUint32(0, Endian.host);
+  print("Compressed size: $compressedSize bytes");
+  var spaceSaving = 100 * (1 - compressedSize / inputData.length);
+  print("Space saving: ${spaceSaving.toStringAsFixed(2)}%");
+
+  var decSizeBytes = ByteData(4);
+  decSizeBytes.setUint32(0, inputData.length, Endian.host);
+  memoryView.setRange(
+      decSizePtr, decSizePtr + 4, decSizeBytes.buffer.asUint8List());
+
+  print("\nDecompressing...");
+  status = decompress(compressedSize, outputPtr, decSizePtr, decodedPtr);
+  print("Decompression status: $status");
+
+  var decompressedSize =
+      ByteData.sublistView(memoryView, decSizePtr, decSizePtr + 4)
+          .getUint32(0, Endian.host);
+  print("Decompressed size: $decompressedSize bytes");
+
+  print("\nVerifying decompression...");
+  assert(inputData.length == decompressedSize);
+  for (var i = 0; i < inputData.length; ++i) {
+    assert(inputData[i] == memoryView[decodedPtr + i]);
+  }
+  print("Decompression succeeded :)");
+}
diff --git a/pkg/wasm/example/libbrotli.wasm b/pkg/wasm/example/libbrotli.wasm
new file mode 100755
index 0000000..0f8ddb3
--- /dev/null
+++ b/pkg/wasm/example/libbrotli.wasm
Binary files differ
diff --git a/pkg/wasm/example/lipsum.txt b/pkg/wasm/example/lipsum.txt
new file mode 100644
index 0000000..f3b5ee0
--- /dev/null
+++ b/pkg/wasm/example/lipsum.txt
@@ -0,0 +1,10 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam feugiat efficitur est a sodales. Ut et odio at nunc fermentum ullamcorper nec in libero. Mauris et interdum elit. Integer in diam nec felis venenatis consectetur. Curabitur elementum egestas augue ac sollicitudin. Cras vulputate efficitur nulla. In blandit sapien ultrices maximus posuere.
+
+Suspendisse in mi at arcu scelerisque tincidunt. Nullam venenatis ex nunc, ut efficitur nulla vehicula eget. Fusce sagittis facilisis ligula nec semper. Nullam et semper ligula. Curabitur sollicitudin ultrices elit et sodales. In iaculis erat scelerisque ipsum scelerisque rutrum. Quisque sollicitudin dolor eu venenatis venenatis. Donec non varius lacus. Phasellus fermentum id mauris nec consequat. Curabitur ultrices, mauris ut scelerisque aliquam, neque augue elementum mi, at accumsan est massa vitae metus. Donec sit amet accumsan dolor, sed vehicula augue. Nunc augue ligula, faucibus tincidunt lorem sed, efficitur ullamcorper erat. Curabitur pellentesque auctor nisi. Cras placerat, massa quis scelerisque commodo, augue leo aliquam elit, sed tempor turpis neque sed nulla. Proin vulputate malesuada augue, quis finibus felis rutrum nec.
+
+Phasellus molestie, tellus eget hendrerit accumsan, diam nunc scelerisque nisi, quis aliquet augue lacus non diam. Nulla facilisi. Nulla est urna, egestas vel luctus nec, sagittis in risus. Mauris aliquam viverra massa vitae efficitur. Integer fringilla sollicitudin ex, et maximus sem gravida ultrices. Vestibulum nec sodales nulla. Cras dapibus maximus venenatis. Vivamus condimentum porttitor mollis. Aliquam congue eleifend condimentum. Donec sagittis bibendum gravida. Nulla condimentum viverra sapien, quis congue libero aliquet nec. Fusce et interdum nisi. Suspendisse at commodo eros. Mauris malesuada nisi in tortor accumsan iaculis. Nam hendrerit interdum magna, eu aliquam est varius eu. Nullam auctor ornare erat, sit amet maximus orci fringilla eu.
+
+Vivamus ullamcorper enim eget tellus lobortis mattis. Vivamus nec tincidunt ipsum. Quisque pharetra non neque non sagittis. Morbi ultrices massa nulla, ac eleifend nulla bibendum mollis. Donec in sodales massa, id luctus dolor. Pellentesque vel auctor tortor, eu imperdiet felis. Pellentesque eleifend eros ipsum, sagittis feugiat enim placerat at. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aliquam lacinia pharetra est.
+
+Duis elit arcu, faucibus ac libero ut, auctor volutpat elit. Duis blandit quis felis at ultricies. Duis ac eros id velit pretium sagittis. Praesent eget orci porttitor, posuere purus ac, interdum eros. Nam augue velit, euismod nec lobortis vitae, rutrum ut libero. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean porttitor sem ante. Integer elit purus, sollicitudin sit amet est in, accumsan suscipit libero. Donec finibus metus scelerisque, mattis dui quis, suscipit turpis. Aliquam rhoncus leo ipsum, vel hendrerit ante porta sit amet. Donec dui nisi, bibendum non rutrum vel, ornare nec diam. Proin tristique ipsum eu pulvinar finibus. Duis pellentesque massa a condimentum elementum. Maecenas efficitur ac est in eleifend. Mauris sit amet lacus blandit, pulvinar ex in, commodo eros.
+
diff --git a/pkg/wasm/lib/src/module.dart b/pkg/wasm/lib/src/module.dart
index 62723d5..b06abb8 100644
--- a/pkg/wasm/lib/src/module.dart
+++ b/pkg/wasm/lib/src/module.dart
@@ -314,6 +314,9 @@
     _view[index] = value;
   }
 
+  /// Returns a Uint8List view into the memory.
+  Uint8List get view => _view;
+
   /// Grow the memory by deltaPages.
   void grow(int deltaPages) {
     var runtime = WasmRuntime();
diff --git a/runtime/bin/builtin_impl_sources.gni b/runtime/bin/builtin_impl_sources.gni
index 58323d0..1045fdc 100644
--- a/runtime/bin/builtin_impl_sources.gni
+++ b/runtime/bin/builtin_impl_sources.gni
@@ -77,4 +77,5 @@
   "eventhandler_test.cc",
   "file_test.cc",
   "hashmap_test.cc",
+  "priority_heap_test.cc",
 ]
diff --git a/runtime/bin/dartdev_isolate.cc b/runtime/bin/dartdev_isolate.cc
index df01614..468ef64 100644
--- a/runtime/bin/dartdev_isolate.cc
+++ b/runtime/bin/dartdev_isolate.cc
@@ -57,13 +57,14 @@
           (strncmp(script_uri, "google3://", 10) != 0));
 }
 
-Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
+Utils::CStringUniquePtr DartDevIsolate::TryResolveArtifactPath(
+    const char* filename) {
   // |dir_prefix| includes the last path seperator.
   auto dir_prefix = EXEUtils::GetDirectoryPrefixFromExeName();
 
   // First assume we're in dart-sdk/bin.
   char* snapshot_path =
-      Utils::SCreate("%ssnapshots/dartdev.dill", dir_prefix.get());
+      Utils::SCreate("%ssnapshots/%s", dir_prefix.get(), filename);
   if (File::Exists(nullptr, snapshot_path)) {
     return Utils::CreateCStringUniquePtr(snapshot_path);
   }
@@ -71,7 +72,7 @@
 
   // If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
   // directories. Try to use a snapshot from a previously built SDK.
-  snapshot_path = Utils::SCreate("%sdartdev.dill", dir_prefix.get());
+  snapshot_path = Utils::SCreate("%s%s", dir_prefix.get(), filename);
   if (File::Exists(nullptr, snapshot_path)) {
     return Utils::CreateCStringUniquePtr(snapshot_path);
   }
@@ -79,6 +80,14 @@
   return Utils::CreateCStringUniquePtr(nullptr);
 }
 
+Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevSnapshotPath() {
+  return TryResolveArtifactPath("dartdev.dart.snapshot");
+}
+
+Utils::CStringUniquePtr DartDevIsolate::TryResolveDartDevKernelPath() {
+  return TryResolveArtifactPath("dartdev.dill");
+}
+
 void DartDevIsolate::DartDevRunner::Run(
     Dart_IsolateGroupCreateCallback create_isolate,
     char** packages_file,
diff --git a/runtime/bin/dartdev_isolate.h b/runtime/bin/dartdev_isolate.h
index 8fd0bd9..a25664c 100644
--- a/runtime/bin/dartdev_isolate.h
+++ b/runtime/bin/dartdev_isolate.h
@@ -41,8 +41,10 @@
 
   static bool should_run_dart_dev() { return should_run_dart_dev_; }
 
-  // Attempts to find the DartDev snapshot. If the snapshot cannot be found,
-  // the VM will shutdown.
+  // Attempts to find the path of the DartDev kernel file.
+  static Utils::CStringUniquePtr TryResolveDartDevKernelPath();
+
+  // Attempts to find the path of the DartDev snapshot.
   static Utils::CStringUniquePtr TryResolveDartDevSnapshotPath();
 
   // Starts a DartDev instance in a new isolate and runs it to completion.
@@ -89,6 +91,8 @@
   };
 
  private:
+  static Utils::CStringUniquePtr TryResolveArtifactPath(const char* filename);
+
   static DartDevRunner runner_;
   static bool should_run_dart_dev_;
 
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index f0aa87a..6935447 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -182,15 +182,16 @@
 
 Dart_KernelCompilationResult DFE::CompileScript(const char* script_uri,
                                                 bool incremental,
-                                                const char* package_config) {
+                                                const char* package_config,
+                                                bool snapshot) {
   // TODO(aam): When Frontend is ready, VM should be passing vm_outline.dill
   // instead of vm_platform.dill to Frontend for compilation.
   PathSanitizer path_sanitizer(script_uri);
   const char* sanitized_uri = path_sanitizer.sanitized_uri();
 
   return Dart_CompileToKernel(sanitized_uri, platform_strong_dill,
-                              platform_strong_dill_size, incremental,
-                              package_config);
+                              platform_strong_dill_size, incremental, snapshot,
+                              package_config, verbosity());
 }
 
 void DFE::CompileAndReadScript(const char* script_uri,
@@ -198,9 +199,10 @@
                                intptr_t* kernel_buffer_size,
                                char** error,
                                int* exit_code,
-                               const char* package_config) {
-  Dart_KernelCompilationResult result =
-      CompileScript(script_uri, use_incremental_compiler(), package_config);
+                               const char* package_config,
+                               bool snapshot) {
+  Dart_KernelCompilationResult result = CompileScript(
+      script_uri, use_incremental_compiler(), package_config, snapshot);
   switch (result.status) {
     case Dart_KernelCompilationStatus_Ok:
       *kernel_buffer = result.kernel;
diff --git a/runtime/bin/dfe.h b/runtime/bin/dfe.h
index eb475bf..b381f9c 100644
--- a/runtime/bin/dfe.h
+++ b/runtime/bin/dfe.h
@@ -42,6 +42,11 @@
   }
   bool use_incremental_compiler() const { return use_incremental_compiler_; }
 
+  void set_verbosity(Dart_KernelCompilationVerbosityLevel verbosity) {
+    verbosity_ = verbosity;
+  }
+  Dart_KernelCompilationVerbosityLevel verbosity() const { return verbosity_; }
+
   // Returns the platform binary file name if the path to
   // kernel binaries was set using SetKernelBinaries.
   const char* GetPlatformBinaryFilename();
@@ -59,20 +64,28 @@
 
   // Compiles specified script.
   // Returns result from compiling the script.
+  //
+  // `snapshot` is used by the frontend to determine if compilation
+  // related information should be printed to console (e.g., null safety mode).
   Dart_KernelCompilationResult CompileScript(const char* script_uri,
                                              bool incremental,
-                                             const char* package_config);
+                                             const char* package_config,
+                                             bool snapshot);
 
   // Compiles specified script and reads the resulting kernel file.
   // If the compilation is successful, returns a valid in memory kernel
   // representation of the script, NULL otherwise
   // 'error' and 'exit_code' have the error values in case of errors.
+  //
+  // `snapshot` is used by the frontend to determine if compilation
+  // related information should be printed to console (e.g., null safety mode).
   void CompileAndReadScript(const char* script_uri,
                             uint8_t** kernel_buffer,
                             intptr_t* kernel_buffer_size,
                             char** error,
                             int* exit_code,
-                            const char* package_config);
+                            const char* package_config,
+                            bool snapshot);
 
   // Reads the script kernel file if specified 'script_uri' is a kernel file.
   // Returns an in memory kernel representation of the specified script is a
@@ -107,6 +120,8 @@
   bool use_dfe_;
   bool use_incremental_compiler_;
   char* frontend_filename_;
+  Dart_KernelCompilationVerbosityLevel verbosity_ =
+      Dart_KernelCompilationVerbosityLevel_All;
 
   // Kernel binary specified on the cmd line.
   uint8_t* application_kernel_buffer_;
diff --git a/runtime/bin/eventhandler.cc b/runtime/bin/eventhandler.cc
index 6a02a0f..83e93a0 100644
--- a/runtime/bin/eventhandler.cc
+++ b/runtime/bin/eventhandler.cc
@@ -15,46 +15,6 @@
 namespace dart {
 namespace bin {
 
-void TimeoutQueue::UpdateTimeout(Dart_Port port, int64_t timeout) {
-  // Find port if present.
-  Timeout* last = NULL;
-  Timeout* current = timeouts_;
-  while (current != NULL) {
-    if (current->port() == port) {
-      // Found.
-      if (timeout < 0) {
-        // Remove from list and delete existing.
-        if (last != NULL) {
-          last->set_next(current->next());
-        } else {
-          timeouts_ = current->next();
-        }
-        delete current;
-      } else {
-        // Update timeout.
-        current->set_timeout(timeout);
-      }
-      break;
-    }
-    last = current;
-    current = current->next();
-  }
-  if (current == NULL && timeout >= 0) {
-    // Not found, create a new.
-    timeouts_ = new Timeout(port, timeout, timeouts_);
-  }
-  // Clear and find next timeout.
-  next_timeout_ = NULL;
-  current = timeouts_;
-  while (current != NULL) {
-    if ((next_timeout_ == NULL) ||
-        (current->timeout() < next_timeout_->timeout())) {
-      next_timeout_ = current;
-    }
-    current = current->next();
-  }
-}
-
 static EventHandler* event_handler = NULL;
 static Monitor* shutdown_monitor = NULL;
 
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index a305f65..69a8e3a 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -10,6 +10,7 @@
 #include "bin/isolate_data.h"
 
 #include "platform/hashmap.h"
+#include "platform/priority_queue.h"
 
 namespace dart {
 namespace bin {
@@ -57,56 +58,39 @@
 // clang-format on
 
 class TimeoutQueue {
- private:
-  class Timeout {
-   public:
-    Timeout(Dart_Port port, int64_t timeout, Timeout* next)
-        : port_(port), timeout_(timeout), next_(next) {}
-
-    Dart_Port port() const { return port_; }
-
-    int64_t timeout() const { return timeout_; }
-    void set_timeout(int64_t timeout) {
-      ASSERT(timeout >= 0);
-      timeout_ = timeout;
-    }
-
-    Timeout* next() const { return next_; }
-    void set_next(Timeout* next) { next_ = next; }
-
-   private:
-    Dart_Port port_;
-    int64_t timeout_;
-    Timeout* next_;
-  };
-
  public:
-  TimeoutQueue() : next_timeout_(NULL), timeouts_(NULL) {}
+  TimeoutQueue() {}
 
   ~TimeoutQueue() {
     while (HasTimeout())
       RemoveCurrent();
   }
 
-  bool HasTimeout() const { return next_timeout_ != NULL; }
+  bool HasTimeout() const { return !timeouts_.IsEmpty(); }
 
   int64_t CurrentTimeout() const {
-    ASSERT(next_timeout_ != NULL);
-    return next_timeout_->timeout();
+    ASSERT(!timeouts_.IsEmpty());
+    return timeouts_.Minimum().priority;
   }
 
   Dart_Port CurrentPort() const {
-    ASSERT(next_timeout_ != NULL);
-    return next_timeout_->port();
+    ASSERT(!timeouts_.IsEmpty());
+    return timeouts_.Minimum().value;
   }
 
-  void RemoveCurrent() { UpdateTimeout(CurrentPort(), -1); }
+  void RemoveCurrent() { timeouts_.RemoveMinimum(); }
 
-  void UpdateTimeout(Dart_Port port, int64_t timeout);
+  void UpdateTimeout(Dart_Port port, int64_t timeout) {
+    if (timeout < 0) {
+      timeouts_.RemoveByValue(port);
+    } else {
+      timeouts_.InsertOrChangePriority(timeout, port);
+    }
+  }
 
  private:
-  Timeout* next_timeout_;
-  Timeout* timeouts_;
+  PriorityQueue<int64_t, Dart_Port> timeouts_;
+  int64_t next_timeout_;
 
   DISALLOW_COPY_AND_ASSIGN(TimeoutQueue);
 };
@@ -399,7 +383,7 @@
     intptr_t is_reading;
     intptr_t token_count;
 
-    bool IsReady() { return token_count > 0 && is_reading; }
+    bool IsReady() { return token_count > 0 && is_reading != 0; }
   };
 
  public:
diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc
index 57d6a01..69a0e51 100644
--- a/runtime/bin/ffi_test/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions.cc
@@ -612,7 +612,6 @@
 // A struct designed to exercise all kinds of alignment rules.
 // Note that offset32A (System V ia32, iOS arm) aligns doubles on 4 bytes while
 // offset32B (Arm 32 bit and MSVC ia32) aligns on 8 bytes.
-// TODO(37271): Support nested structs.
 // TODO(37470): Add uncommon primitive data types when we want to support them.
 struct VeryLargeStruct {
   //                             size32 size64 offset32A offset32B offset64
@@ -784,6 +783,31 @@
   return result;
 }
 
+// Can't easily share this with the generated file.
+struct Struct4BytesHomogeneousInt16Copy {
+  int16_t a0;
+  int16_t a1;
+};
+
+// Can't easily share this with the generated file.
+struct Struct8BytesNestedIntCopy {
+  Struct4BytesHomogeneousInt16Copy a0;
+  Struct4BytesHomogeneousInt16Copy a1;
+};
+
+DART_EXPORT void CallbackWithStruct(void (*f)(Struct8BytesNestedIntCopy)) {
+  std::cout << "CallbackWithStruct"
+            << "(" << reinterpret_cast<void*>(f) << ")\n";
+
+  Struct8BytesNestedIntCopy arg;
+  arg.a0.a0 = 10;
+  arg.a0.a1 = 11;
+  arg.a1.a0 = 12;
+  arg.a1.a1 = 13;
+
+  f(arg);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Tests for callbacks.
 
diff --git a/runtime/bin/ffi_test/ffi_test_functions_generated.cc b/runtime/bin/ffi_test/ffi_test_functions_generated.cc
index 74f27e4..65d06a5 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_generated.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_generated.cc
@@ -34,8 +34,6 @@
   CHECK(((EXPECTED * 0.99) <= (ACTUAL) && (EXPECTED * 1.01) >= (ACTUAL)) ||    \
         ((EXPECTED * 0.99) >= (ACTUAL) && (EXPECTED * 1.01) <= (ACTUAL)))
 
-struct Struct0Bytes {};
-
 struct Struct1ByteInt {
   int8_t a0;
 };
@@ -56,6 +54,10 @@
   int16_t a1;
 };
 
+struct Struct4BytesFloat {
+  float a0;
+};
+
 struct Struct7BytesHomogeneousUint8 {
   uint8_t a0;
   uint8_t a1;
@@ -339,6 +341,75 @@
   int8_t a2;
 };
 
+struct Struct8BytesNestedInt {
+  Struct4BytesHomogeneousInt16 a0;
+  Struct4BytesHomogeneousInt16 a1;
+};
+
+struct Struct8BytesNestedFloat {
+  Struct4BytesFloat a0;
+  Struct4BytesFloat a1;
+};
+
+struct Struct8BytesNestedFloat2 {
+  Struct4BytesFloat a0;
+  float a1;
+};
+
+struct Struct8BytesNestedMixed {
+  Struct4BytesHomogeneousInt16 a0;
+  Struct4BytesFloat a1;
+};
+
+struct Struct16BytesNestedInt {
+  Struct8BytesNestedInt a0;
+  Struct8BytesNestedInt a1;
+};
+
+struct Struct32BytesNestedInt {
+  Struct16BytesNestedInt a0;
+  Struct16BytesNestedInt a1;
+};
+
+struct StructNestedIntStructAlignmentInt16 {
+  StructAlignmentInt16 a0;
+  StructAlignmentInt16 a1;
+};
+
+struct StructNestedIntStructAlignmentInt32 {
+  StructAlignmentInt32 a0;
+  StructAlignmentInt32 a1;
+};
+
+struct StructNestedIntStructAlignmentInt64 {
+  StructAlignmentInt64 a0;
+  StructAlignmentInt64 a1;
+};
+
+struct StructNestedIrregularBig {
+  uint16_t a0;
+  Struct8BytesNestedMixed a1;
+  uint16_t a2;
+  Struct8BytesNestedFloat2 a3;
+  uint16_t a4;
+  Struct8BytesNestedFloat a5;
+  uint16_t a6;
+};
+
+struct StructNestedIrregularBigger {
+  StructNestedIrregularBig a0;
+  Struct8BytesNestedMixed a1;
+  float a2;
+  double a3;
+};
+
+struct StructNestedIrregularEvenBigger {
+  uint64_t a0;
+  StructNestedIrregularBigger a1;
+  StructNestedIrregularBigger a2;
+  double a3;
+};
+
 // Used for testing structs by value.
 // Smallest struct with data.
 // 10 struct arguments will exhaust available registers.
@@ -2569,6 +2640,639 @@
 }
 
 // Used for testing structs by value.
+// Simple nested struct. No alignment gaps on any architectures.
+// 10 arguments exhaust registers on all platforms.
+DART_EXPORT int64_t PassStruct8BytesNestedIntx10(Struct8BytesNestedInt a0,
+                                                 Struct8BytesNestedInt a1,
+                                                 Struct8BytesNestedInt a2,
+                                                 Struct8BytesNestedInt a3,
+                                                 Struct8BytesNestedInt a4,
+                                                 Struct8BytesNestedInt a5,
+                                                 Struct8BytesNestedInt a6,
+                                                 Struct8BytesNestedInt a7,
+                                                 Struct8BytesNestedInt a8,
+                                                 Struct8BytesNestedInt a9) {
+  std::cout << "PassStruct8BytesNestedIntx10"
+            << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0
+            << ", " << a0.a1.a1 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1
+            << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ")), ((" << a2.a0.a0
+            << ", " << a2.a0.a1 << "), (" << a2.a1.a0 << ", " << a2.a1.a1
+            << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0
+            << ", " << a3.a1.a1 << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1
+            << "), (" << a4.a1.a0 << ", " << a4.a1.a1 << ")), ((" << a5.a0.a0
+            << ", " << a5.a0.a1 << "), (" << a5.a1.a0 << ", " << a5.a1.a1
+            << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0
+            << ", " << a6.a1.a1 << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1
+            << "), (" << a7.a1.a0 << ", " << a7.a1.a1 << ")), ((" << a8.a0.a0
+            << ", " << a8.a0.a1 << "), (" << a8.a1.a0 << ", " << a8.a1.a1
+            << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0
+            << ", " << a9.a1.a1 << ")))"
+            << "\n";
+
+  int64_t result = 0;
+
+  result += a0.a0.a0;
+  result += a0.a0.a1;
+  result += a0.a1.a0;
+  result += a0.a1.a1;
+  result += a1.a0.a0;
+  result += a1.a0.a1;
+  result += a1.a1.a0;
+  result += a1.a1.a1;
+  result += a2.a0.a0;
+  result += a2.a0.a1;
+  result += a2.a1.a0;
+  result += a2.a1.a1;
+  result += a3.a0.a0;
+  result += a3.a0.a1;
+  result += a3.a1.a0;
+  result += a3.a1.a1;
+  result += a4.a0.a0;
+  result += a4.a0.a1;
+  result += a4.a1.a0;
+  result += a4.a1.a1;
+  result += a5.a0.a0;
+  result += a5.a0.a1;
+  result += a5.a1.a0;
+  result += a5.a1.a1;
+  result += a6.a0.a0;
+  result += a6.a0.a1;
+  result += a6.a1.a0;
+  result += a6.a1.a1;
+  result += a7.a0.a0;
+  result += a7.a0.a1;
+  result += a7.a1.a0;
+  result += a7.a1.a1;
+  result += a8.a0.a0;
+  result += a8.a0.a1;
+  result += a8.a1.a0;
+  result += a8.a1.a1;
+  result += a9.a0.a0;
+  result += a9.a0.a1;
+  result += a9.a1.a0;
+  result += a9.a1.a1;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Simple nested struct. No alignment gaps on any architectures.
+// 10 arguments exhaust fpu registers on all platforms.
+DART_EXPORT float PassStruct8BytesNestedFloatx10(Struct8BytesNestedFloat a0,
+                                                 Struct8BytesNestedFloat a1,
+                                                 Struct8BytesNestedFloat a2,
+                                                 Struct8BytesNestedFloat a3,
+                                                 Struct8BytesNestedFloat a4,
+                                                 Struct8BytesNestedFloat a5,
+                                                 Struct8BytesNestedFloat a6,
+                                                 Struct8BytesNestedFloat a7,
+                                                 Struct8BytesNestedFloat a8,
+                                                 Struct8BytesNestedFloat a9) {
+  std::cout << "PassStruct8BytesNestedFloatx10"
+            << "(((" << a0.a0.a0 << "), (" << a0.a1.a0 << ")), ((" << a1.a0.a0
+            << "), (" << a1.a1.a0 << ")), ((" << a2.a0.a0 << "), (" << a2.a1.a0
+            << ")), ((" << a3.a0.a0 << "), (" << a3.a1.a0 << ")), (("
+            << a4.a0.a0 << "), (" << a4.a1.a0 << ")), ((" << a5.a0.a0 << "), ("
+            << a5.a1.a0 << ")), ((" << a6.a0.a0 << "), (" << a6.a1.a0
+            << ")), ((" << a7.a0.a0 << "), (" << a7.a1.a0 << ")), (("
+            << a8.a0.a0 << "), (" << a8.a1.a0 << ")), ((" << a9.a0.a0 << "), ("
+            << a9.a1.a0 << ")))"
+            << "\n";
+
+  float result = 0;
+
+  result += a0.a0.a0;
+  result += a0.a1.a0;
+  result += a1.a0.a0;
+  result += a1.a1.a0;
+  result += a2.a0.a0;
+  result += a2.a1.a0;
+  result += a3.a0.a0;
+  result += a3.a1.a0;
+  result += a4.a0.a0;
+  result += a4.a1.a0;
+  result += a5.a0.a0;
+  result += a5.a1.a0;
+  result += a6.a0.a0;
+  result += a6.a1.a0;
+  result += a7.a0.a0;
+  result += a7.a1.a0;
+  result += a8.a0.a0;
+  result += a8.a1.a0;
+  result += a9.a0.a0;
+  result += a9.a1.a0;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Simple nested struct. No alignment gaps on any architectures.
+// 10 arguments exhaust fpu registers on all platforms.
+// The nesting is irregular, testing homogenous float rules on arm and arm64,
+// and the fpu register usage on x64.
+DART_EXPORT float PassStruct8BytesNestedFloat2x10(Struct8BytesNestedFloat2 a0,
+                                                  Struct8BytesNestedFloat2 a1,
+                                                  Struct8BytesNestedFloat2 a2,
+                                                  Struct8BytesNestedFloat2 a3,
+                                                  Struct8BytesNestedFloat2 a4,
+                                                  Struct8BytesNestedFloat2 a5,
+                                                  Struct8BytesNestedFloat2 a6,
+                                                  Struct8BytesNestedFloat2 a7,
+                                                  Struct8BytesNestedFloat2 a8,
+                                                  Struct8BytesNestedFloat2 a9) {
+  std::cout << "PassStruct8BytesNestedFloat2x10"
+            << "(((" << a0.a0.a0 << "), " << a0.a1 << "), ((" << a1.a0.a0
+            << "), " << a1.a1 << "), ((" << a2.a0.a0 << "), " << a2.a1
+            << "), ((" << a3.a0.a0 << "), " << a3.a1 << "), ((" << a4.a0.a0
+            << "), " << a4.a1 << "), ((" << a5.a0.a0 << "), " << a5.a1
+            << "), ((" << a6.a0.a0 << "), " << a6.a1 << "), ((" << a7.a0.a0
+            << "), " << a7.a1 << "), ((" << a8.a0.a0 << "), " << a8.a1
+            << "), ((" << a9.a0.a0 << "), " << a9.a1 << "))"
+            << "\n";
+
+  float result = 0;
+
+  result += a0.a0.a0;
+  result += a0.a1;
+  result += a1.a0.a0;
+  result += a1.a1;
+  result += a2.a0.a0;
+  result += a2.a1;
+  result += a3.a0.a0;
+  result += a3.a1;
+  result += a4.a0.a0;
+  result += a4.a1;
+  result += a5.a0.a0;
+  result += a5.a1;
+  result += a6.a0.a0;
+  result += a6.a1;
+  result += a7.a0.a0;
+  result += a7.a1;
+  result += a8.a0.a0;
+  result += a8.a1;
+  result += a9.a0.a0;
+  result += a9.a1;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Simple nested struct. No alignment gaps on any architectures.
+// 10 arguments exhaust all registers on all platforms.
+DART_EXPORT double PassStruct8BytesNestedMixedx10(Struct8BytesNestedMixed a0,
+                                                  Struct8BytesNestedMixed a1,
+                                                  Struct8BytesNestedMixed a2,
+                                                  Struct8BytesNestedMixed a3,
+                                                  Struct8BytesNestedMixed a4,
+                                                  Struct8BytesNestedMixed a5,
+                                                  Struct8BytesNestedMixed a6,
+                                                  Struct8BytesNestedMixed a7,
+                                                  Struct8BytesNestedMixed a8,
+                                                  Struct8BytesNestedMixed a9) {
+  std::cout << "PassStruct8BytesNestedMixedx10"
+            << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0
+            << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0
+            << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << "), (" << a2.a1.a0
+            << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0
+            << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << "), (" << a4.a1.a0
+            << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << "), (" << a5.a1.a0
+            << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0
+            << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << "), (" << a7.a1.a0
+            << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << "), (" << a8.a1.a0
+            << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0
+            << ")))"
+            << "\n";
+
+  double result = 0;
+
+  result += a0.a0.a0;
+  result += a0.a0.a1;
+  result += a0.a1.a0;
+  result += a1.a0.a0;
+  result += a1.a0.a1;
+  result += a1.a1.a0;
+  result += a2.a0.a0;
+  result += a2.a0.a1;
+  result += a2.a1.a0;
+  result += a3.a0.a0;
+  result += a3.a0.a1;
+  result += a3.a1.a0;
+  result += a4.a0.a0;
+  result += a4.a0.a1;
+  result += a4.a1.a0;
+  result += a5.a0.a0;
+  result += a5.a0.a1;
+  result += a5.a1.a0;
+  result += a6.a0.a0;
+  result += a6.a0.a1;
+  result += a6.a1.a0;
+  result += a7.a0.a0;
+  result += a7.a0.a1;
+  result += a7.a1.a0;
+  result += a8.a0.a0;
+  result += a8.a0.a1;
+  result += a8.a1.a0;
+  result += a9.a0.a0;
+  result += a9.a0.a1;
+  result += a9.a1.a0;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Deeper nested struct to test recursive member access.
+DART_EXPORT int64_t PassStruct16BytesNestedIntx2(Struct16BytesNestedInt a0,
+                                                 Struct16BytesNestedInt a1) {
+  std::cout << "PassStruct16BytesNestedIntx2"
+            << "((((" << a0.a0.a0.a0 << ", " << a0.a0.a0.a1 << "), ("
+            << a0.a0.a1.a0 << ", " << a0.a0.a1.a1 << ")), ((" << a0.a1.a0.a0
+            << ", " << a0.a1.a0.a1 << "), (" << a0.a1.a1.a0 << ", "
+            << a0.a1.a1.a1 << "))), (((" << a1.a0.a0.a0 << ", " << a1.a0.a0.a1
+            << "), (" << a1.a0.a1.a0 << ", " << a1.a0.a1.a1 << ")), (("
+            << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0
+            << ", " << a1.a1.a1.a1 << "))))"
+            << "\n";
+
+  int64_t result = 0;
+
+  result += a0.a0.a0.a0;
+  result += a0.a0.a0.a1;
+  result += a0.a0.a1.a0;
+  result += a0.a0.a1.a1;
+  result += a0.a1.a0.a0;
+  result += a0.a1.a0.a1;
+  result += a0.a1.a1.a0;
+  result += a0.a1.a1.a1;
+  result += a1.a0.a0.a0;
+  result += a1.a0.a0.a1;
+  result += a1.a0.a1.a0;
+  result += a1.a0.a1.a1;
+  result += a1.a1.a0.a0;
+  result += a1.a1.a0.a1;
+  result += a1.a1.a1.a0;
+  result += a1.a1.a1.a1;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Even deeper nested struct to test recursive member access.
+DART_EXPORT int64_t PassStruct32BytesNestedIntx2(Struct32BytesNestedInt a0,
+                                                 Struct32BytesNestedInt a1) {
+  std::cout << "PassStruct32BytesNestedIntx2"
+            << "(((((" << a0.a0.a0.a0.a0 << ", " << a0.a0.a0.a0.a1 << "), ("
+            << a0.a0.a0.a1.a0 << ", " << a0.a0.a0.a1.a1 << ")), (("
+            << a0.a0.a1.a0.a0 << ", " << a0.a0.a1.a0.a1 << "), ("
+            << a0.a0.a1.a1.a0 << ", " << a0.a0.a1.a1.a1 << "))), ((("
+            << a0.a1.a0.a0.a0 << ", " << a0.a1.a0.a0.a1 << "), ("
+            << a0.a1.a0.a1.a0 << ", " << a0.a1.a0.a1.a1 << ")), (("
+            << a0.a1.a1.a0.a0 << ", " << a0.a1.a1.a0.a1 << "), ("
+            << a0.a1.a1.a1.a0 << ", " << a0.a1.a1.a1.a1 << ")))), (((("
+            << a1.a0.a0.a0.a0 << ", " << a1.a0.a0.a0.a1 << "), ("
+            << a1.a0.a0.a1.a0 << ", " << a1.a0.a0.a1.a1 << ")), (("
+            << a1.a0.a1.a0.a0 << ", " << a1.a0.a1.a0.a1 << "), ("
+            << a1.a0.a1.a1.a0 << ", " << a1.a0.a1.a1.a1 << "))), ((("
+            << a1.a1.a0.a0.a0 << ", " << a1.a1.a0.a0.a1 << "), ("
+            << a1.a1.a0.a1.a0 << ", " << a1.a1.a0.a1.a1 << ")), (("
+            << a1.a1.a1.a0.a0 << ", " << a1.a1.a1.a0.a1 << "), ("
+            << a1.a1.a1.a1.a0 << ", " << a1.a1.a1.a1.a1 << ")))))"
+            << "\n";
+
+  int64_t result = 0;
+
+  result += a0.a0.a0.a0.a0;
+  result += a0.a0.a0.a0.a1;
+  result += a0.a0.a0.a1.a0;
+  result += a0.a0.a0.a1.a1;
+  result += a0.a0.a1.a0.a0;
+  result += a0.a0.a1.a0.a1;
+  result += a0.a0.a1.a1.a0;
+  result += a0.a0.a1.a1.a1;
+  result += a0.a1.a0.a0.a0;
+  result += a0.a1.a0.a0.a1;
+  result += a0.a1.a0.a1.a0;
+  result += a0.a1.a0.a1.a1;
+  result += a0.a1.a1.a0.a0;
+  result += a0.a1.a1.a0.a1;
+  result += a0.a1.a1.a1.a0;
+  result += a0.a1.a1.a1.a1;
+  result += a1.a0.a0.a0.a0;
+  result += a1.a0.a0.a0.a1;
+  result += a1.a0.a0.a1.a0;
+  result += a1.a0.a0.a1.a1;
+  result += a1.a0.a1.a0.a0;
+  result += a1.a0.a1.a0.a1;
+  result += a1.a0.a1.a1.a0;
+  result += a1.a0.a1.a1.a1;
+  result += a1.a1.a0.a0.a0;
+  result += a1.a1.a0.a0.a1;
+  result += a1.a1.a0.a1.a0;
+  result += a1.a1.a0.a1.a1;
+  result += a1.a1.a1.a0.a0;
+  result += a1.a1.a1.a0.a1;
+  result += a1.a1.a1.a1.a0;
+  result += a1.a1.a1.a1.a1;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 16 byte int.
+DART_EXPORT int64_t PassStructNestedIntStructAlignmentInt16(
+    StructNestedIntStructAlignmentInt16 a0) {
+  std::cout << "PassStructNestedIntStructAlignmentInt16"
+            << "(((" << static_cast<int>(a0.a0.a0) << ", " << a0.a0.a1 << ", "
+            << static_cast<int>(a0.a0.a2) << "), ("
+            << static_cast<int>(a0.a1.a0) << ", " << a0.a1.a1 << ", "
+            << static_cast<int>(a0.a1.a2) << ")))"
+            << "\n";
+
+  int64_t result = 0;
+
+  result += a0.a0.a0;
+  result += a0.a0.a1;
+  result += a0.a0.a2;
+  result += a0.a1.a0;
+  result += a0.a1.a1;
+  result += a0.a1.a2;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 32 byte int.
+DART_EXPORT int64_t PassStructNestedIntStructAlignmentInt32(
+    StructNestedIntStructAlignmentInt32 a0) {
+  std::cout << "PassStructNestedIntStructAlignmentInt32"
+            << "(((" << static_cast<int>(a0.a0.a0) << ", " << a0.a0.a1 << ", "
+            << static_cast<int>(a0.a0.a2) << "), ("
+            << static_cast<int>(a0.a1.a0) << ", " << a0.a1.a1 << ", "
+            << static_cast<int>(a0.a1.a2) << ")))"
+            << "\n";
+
+  int64_t result = 0;
+
+  result += a0.a0.a0;
+  result += a0.a0.a1;
+  result += a0.a0.a2;
+  result += a0.a1.a0;
+  result += a0.a1.a1;
+  result += a0.a1.a2;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 64 byte int.
+DART_EXPORT int64_t PassStructNestedIntStructAlignmentInt64(
+    StructNestedIntStructAlignmentInt64 a0) {
+  std::cout << "PassStructNestedIntStructAlignmentInt64"
+            << "(((" << static_cast<int>(a0.a0.a0) << ", " << a0.a0.a1 << ", "
+            << static_cast<int>(a0.a0.a2) << "), ("
+            << static_cast<int>(a0.a1.a0) << ", " << a0.a1.a1 << ", "
+            << static_cast<int>(a0.a1.a2) << ")))"
+            << "\n";
+
+  int64_t result = 0;
+
+  result += a0.a0.a0;
+  result += a0.a0.a1;
+  result += a0.a0.a2;
+  result += a0.a1.a0;
+  result += a0.a1.a1;
+  result += a0.a1.a2;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Return big irregular struct as smoke test.
+DART_EXPORT double PassStructNestedIrregularEvenBiggerx4(
+    StructNestedIrregularEvenBigger a0,
+    StructNestedIrregularEvenBigger a1,
+    StructNestedIrregularEvenBigger a2,
+    StructNestedIrregularEvenBigger a3) {
+  std::cout
+      << "PassStructNestedIrregularEvenBiggerx4"
+      << "((" << a0.a0 << ", ((" << a0.a1.a0.a0 << ", ((" << a0.a1.a0.a1.a0.a0
+      << ", " << a0.a1.a0.a1.a0.a1 << "), (" << a0.a1.a0.a1.a1.a0 << ")), "
+      << a0.a1.a0.a2 << ", ((" << a0.a1.a0.a3.a0.a0 << "), " << a0.a1.a0.a3.a1
+      << "), " << a0.a1.a0.a4 << ", ((" << a0.a1.a0.a5.a0.a0 << "), ("
+      << a0.a1.a0.a5.a1.a0 << ")), " << a0.a1.a0.a6 << "), ((" << a0.a1.a1.a0.a0
+      << ", " << a0.a1.a1.a0.a1 << "), (" << a0.a1.a1.a1.a0 << ")), "
+      << a0.a1.a2 << ", " << a0.a1.a3 << "), ((" << a0.a2.a0.a0 << ", (("
+      << a0.a2.a0.a1.a0.a0 << ", " << a0.a2.a0.a1.a0.a1 << "), ("
+      << a0.a2.a0.a1.a1.a0 << ")), " << a0.a2.a0.a2 << ", (("
+      << a0.a2.a0.a3.a0.a0 << "), " << a0.a2.a0.a3.a1 << "), " << a0.a2.a0.a4
+      << ", ((" << a0.a2.a0.a5.a0.a0 << "), (" << a0.a2.a0.a5.a1.a0 << ")), "
+      << a0.a2.a0.a6 << "), ((" << a0.a2.a1.a0.a0 << ", " << a0.a2.a1.a0.a1
+      << "), (" << a0.a2.a1.a1.a0 << ")), " << a0.a2.a2 << ", " << a0.a2.a3
+      << "), " << a0.a3 << "), (" << a1.a0 << ", ((" << a1.a1.a0.a0 << ", (("
+      << a1.a1.a0.a1.a0.a0 << ", " << a1.a1.a0.a1.a0.a1 << "), ("
+      << a1.a1.a0.a1.a1.a0 << ")), " << a1.a1.a0.a2 << ", (("
+      << a1.a1.a0.a3.a0.a0 << "), " << a1.a1.a0.a3.a1 << "), " << a1.a1.a0.a4
+      << ", ((" << a1.a1.a0.a5.a0.a0 << "), (" << a1.a1.a0.a5.a1.a0 << ")), "
+      << a1.a1.a0.a6 << "), ((" << a1.a1.a1.a0.a0 << ", " << a1.a1.a1.a0.a1
+      << "), (" << a1.a1.a1.a1.a0 << ")), " << a1.a1.a2 << ", " << a1.a1.a3
+      << "), ((" << a1.a2.a0.a0 << ", ((" << a1.a2.a0.a1.a0.a0 << ", "
+      << a1.a2.a0.a1.a0.a1 << "), (" << a1.a2.a0.a1.a1.a0 << ")), "
+      << a1.a2.a0.a2 << ", ((" << a1.a2.a0.a3.a0.a0 << "), " << a1.a2.a0.a3.a1
+      << "), " << a1.a2.a0.a4 << ", ((" << a1.a2.a0.a5.a0.a0 << "), ("
+      << a1.a2.a0.a5.a1.a0 << ")), " << a1.a2.a0.a6 << "), ((" << a1.a2.a1.a0.a0
+      << ", " << a1.a2.a1.a0.a1 << "), (" << a1.a2.a1.a1.a0 << ")), "
+      << a1.a2.a2 << ", " << a1.a2.a3 << "), " << a1.a3 << "), (" << a2.a0
+      << ", ((" << a2.a1.a0.a0 << ", ((" << a2.a1.a0.a1.a0.a0 << ", "
+      << a2.a1.a0.a1.a0.a1 << "), (" << a2.a1.a0.a1.a1.a0 << ")), "
+      << a2.a1.a0.a2 << ", ((" << a2.a1.a0.a3.a0.a0 << "), " << a2.a1.a0.a3.a1
+      << "), " << a2.a1.a0.a4 << ", ((" << a2.a1.a0.a5.a0.a0 << "), ("
+      << a2.a1.a0.a5.a1.a0 << ")), " << a2.a1.a0.a6 << "), ((" << a2.a1.a1.a0.a0
+      << ", " << a2.a1.a1.a0.a1 << "), (" << a2.a1.a1.a1.a0 << ")), "
+      << a2.a1.a2 << ", " << a2.a1.a3 << "), ((" << a2.a2.a0.a0 << ", (("
+      << a2.a2.a0.a1.a0.a0 << ", " << a2.a2.a0.a1.a0.a1 << "), ("
+      << a2.a2.a0.a1.a1.a0 << ")), " << a2.a2.a0.a2 << ", (("
+      << a2.a2.a0.a3.a0.a0 << "), " << a2.a2.a0.a3.a1 << "), " << a2.a2.a0.a4
+      << ", ((" << a2.a2.a0.a5.a0.a0 << "), (" << a2.a2.a0.a5.a1.a0 << ")), "
+      << a2.a2.a0.a6 << "), ((" << a2.a2.a1.a0.a0 << ", " << a2.a2.a1.a0.a1
+      << "), (" << a2.a2.a1.a1.a0 << ")), " << a2.a2.a2 << ", " << a2.a2.a3
+      << "), " << a2.a3 << "), (" << a3.a0 << ", ((" << a3.a1.a0.a0 << ", (("
+      << a3.a1.a0.a1.a0.a0 << ", " << a3.a1.a0.a1.a0.a1 << "), ("
+      << a3.a1.a0.a1.a1.a0 << ")), " << a3.a1.a0.a2 << ", (("
+      << a3.a1.a0.a3.a0.a0 << "), " << a3.a1.a0.a3.a1 << "), " << a3.a1.a0.a4
+      << ", ((" << a3.a1.a0.a5.a0.a0 << "), (" << a3.a1.a0.a5.a1.a0 << ")), "
+      << a3.a1.a0.a6 << "), ((" << a3.a1.a1.a0.a0 << ", " << a3.a1.a1.a0.a1
+      << "), (" << a3.a1.a1.a1.a0 << ")), " << a3.a1.a2 << ", " << a3.a1.a3
+      << "), ((" << a3.a2.a0.a0 << ", ((" << a3.a2.a0.a1.a0.a0 << ", "
+      << a3.a2.a0.a1.a0.a1 << "), (" << a3.a2.a0.a1.a1.a0 << ")), "
+      << a3.a2.a0.a2 << ", ((" << a3.a2.a0.a3.a0.a0 << "), " << a3.a2.a0.a3.a1
+      << "), " << a3.a2.a0.a4 << ", ((" << a3.a2.a0.a5.a0.a0 << "), ("
+      << a3.a2.a0.a5.a1.a0 << ")), " << a3.a2.a0.a6 << "), ((" << a3.a2.a1.a0.a0
+      << ", " << a3.a2.a1.a0.a1 << "), (" << a3.a2.a1.a1.a0 << ")), "
+      << a3.a2.a2 << ", " << a3.a2.a3 << "), " << a3.a3 << "))"
+      << "\n";
+
+  double result = 0;
+
+  result += a0.a0;
+  result += a0.a1.a0.a0;
+  result += a0.a1.a0.a1.a0.a0;
+  result += a0.a1.a0.a1.a0.a1;
+  result += a0.a1.a0.a1.a1.a0;
+  result += a0.a1.a0.a2;
+  result += a0.a1.a0.a3.a0.a0;
+  result += a0.a1.a0.a3.a1;
+  result += a0.a1.a0.a4;
+  result += a0.a1.a0.a5.a0.a0;
+  result += a0.a1.a0.a5.a1.a0;
+  result += a0.a1.a0.a6;
+  result += a0.a1.a1.a0.a0;
+  result += a0.a1.a1.a0.a1;
+  result += a0.a1.a1.a1.a0;
+  result += a0.a1.a2;
+  result += a0.a1.a3;
+  result += a0.a2.a0.a0;
+  result += a0.a2.a0.a1.a0.a0;
+  result += a0.a2.a0.a1.a0.a1;
+  result += a0.a2.a0.a1.a1.a0;
+  result += a0.a2.a0.a2;
+  result += a0.a2.a0.a3.a0.a0;
+  result += a0.a2.a0.a3.a1;
+  result += a0.a2.a0.a4;
+  result += a0.a2.a0.a5.a0.a0;
+  result += a0.a2.a0.a5.a1.a0;
+  result += a0.a2.a0.a6;
+  result += a0.a2.a1.a0.a0;
+  result += a0.a2.a1.a0.a1;
+  result += a0.a2.a1.a1.a0;
+  result += a0.a2.a2;
+  result += a0.a2.a3;
+  result += a0.a3;
+  result += a1.a0;
+  result += a1.a1.a0.a0;
+  result += a1.a1.a0.a1.a0.a0;
+  result += a1.a1.a0.a1.a0.a1;
+  result += a1.a1.a0.a1.a1.a0;
+  result += a1.a1.a0.a2;
+  result += a1.a1.a0.a3.a0.a0;
+  result += a1.a1.a0.a3.a1;
+  result += a1.a1.a0.a4;
+  result += a1.a1.a0.a5.a0.a0;
+  result += a1.a1.a0.a5.a1.a0;
+  result += a1.a1.a0.a6;
+  result += a1.a1.a1.a0.a0;
+  result += a1.a1.a1.a0.a1;
+  result += a1.a1.a1.a1.a0;
+  result += a1.a1.a2;
+  result += a1.a1.a3;
+  result += a1.a2.a0.a0;
+  result += a1.a2.a0.a1.a0.a0;
+  result += a1.a2.a0.a1.a0.a1;
+  result += a1.a2.a0.a1.a1.a0;
+  result += a1.a2.a0.a2;
+  result += a1.a2.a0.a3.a0.a0;
+  result += a1.a2.a0.a3.a1;
+  result += a1.a2.a0.a4;
+  result += a1.a2.a0.a5.a0.a0;
+  result += a1.a2.a0.a5.a1.a0;
+  result += a1.a2.a0.a6;
+  result += a1.a2.a1.a0.a0;
+  result += a1.a2.a1.a0.a1;
+  result += a1.a2.a1.a1.a0;
+  result += a1.a2.a2;
+  result += a1.a2.a3;
+  result += a1.a3;
+  result += a2.a0;
+  result += a2.a1.a0.a0;
+  result += a2.a1.a0.a1.a0.a0;
+  result += a2.a1.a0.a1.a0.a1;
+  result += a2.a1.a0.a1.a1.a0;
+  result += a2.a1.a0.a2;
+  result += a2.a1.a0.a3.a0.a0;
+  result += a2.a1.a0.a3.a1;
+  result += a2.a1.a0.a4;
+  result += a2.a1.a0.a5.a0.a0;
+  result += a2.a1.a0.a5.a1.a0;
+  result += a2.a1.a0.a6;
+  result += a2.a1.a1.a0.a0;
+  result += a2.a1.a1.a0.a1;
+  result += a2.a1.a1.a1.a0;
+  result += a2.a1.a2;
+  result += a2.a1.a3;
+  result += a2.a2.a0.a0;
+  result += a2.a2.a0.a1.a0.a0;
+  result += a2.a2.a0.a1.a0.a1;
+  result += a2.a2.a0.a1.a1.a0;
+  result += a2.a2.a0.a2;
+  result += a2.a2.a0.a3.a0.a0;
+  result += a2.a2.a0.a3.a1;
+  result += a2.a2.a0.a4;
+  result += a2.a2.a0.a5.a0.a0;
+  result += a2.a2.a0.a5.a1.a0;
+  result += a2.a2.a0.a6;
+  result += a2.a2.a1.a0.a0;
+  result += a2.a2.a1.a0.a1;
+  result += a2.a2.a1.a1.a0;
+  result += a2.a2.a2;
+  result += a2.a2.a3;
+  result += a2.a3;
+  result += a3.a0;
+  result += a3.a1.a0.a0;
+  result += a3.a1.a0.a1.a0.a0;
+  result += a3.a1.a0.a1.a0.a1;
+  result += a3.a1.a0.a1.a1.a0;
+  result += a3.a1.a0.a2;
+  result += a3.a1.a0.a3.a0.a0;
+  result += a3.a1.a0.a3.a1;
+  result += a3.a1.a0.a4;
+  result += a3.a1.a0.a5.a0.a0;
+  result += a3.a1.a0.a5.a1.a0;
+  result += a3.a1.a0.a6;
+  result += a3.a1.a1.a0.a0;
+  result += a3.a1.a1.a0.a1;
+  result += a3.a1.a1.a1.a0;
+  result += a3.a1.a2;
+  result += a3.a1.a3;
+  result += a3.a2.a0.a0;
+  result += a3.a2.a0.a1.a0.a0;
+  result += a3.a2.a0.a1.a0.a1;
+  result += a3.a2.a0.a1.a1.a0;
+  result += a3.a2.a0.a2;
+  result += a3.a2.a0.a3.a0.a0;
+  result += a3.a2.a0.a3.a1;
+  result += a3.a2.a0.a4;
+  result += a3.a2.a0.a5.a0.a0;
+  result += a3.a2.a0.a5.a1.a0;
+  result += a3.a2.a0.a6;
+  result += a3.a2.a1.a0.a0;
+  result += a3.a2.a1.a0.a1;
+  result += a3.a2.a1.a1.a0;
+  result += a3.a2.a2;
+  result += a3.a2.a3;
+  result += a3.a3;
+
+  std::cout << "result = " << result << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
 // Smallest struct with data.
 DART_EXPORT Struct1ByteInt ReturnStruct1ByteInt(int8_t a0) {
   std::cout << "ReturnStruct1ByteInt"
@@ -3695,6 +4399,349 @@
 }
 
 // Used for testing structs by value.
+// Simple nested struct.
+DART_EXPORT Struct8BytesNestedInt
+ReturnStruct8BytesNestedInt(Struct4BytesHomogeneousInt16 a0,
+                            Struct4BytesHomogeneousInt16 a1) {
+  std::cout << "ReturnStruct8BytesNestedInt"
+            << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", "
+            << a1.a1 << "))"
+            << "\n";
+
+  Struct8BytesNestedInt result;
+
+  result.a0.a0 = a0.a0;
+  result.a0.a1 = a0.a1;
+  result.a1.a0 = a1.a0;
+  result.a1.a1 = a1.a1;
+
+  std::cout << "result = "
+            << "((" << result.a0.a0 << ", " << result.a0.a1 << "), ("
+            << result.a1.a0 << ", " << result.a1.a1 << "))"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Simple nested struct with floats.
+DART_EXPORT Struct8BytesNestedFloat
+ReturnStruct8BytesNestedFloat(Struct4BytesFloat a0, Struct4BytesFloat a1) {
+  std::cout << "ReturnStruct8BytesNestedFloat"
+            << "((" << a0.a0 << "), (" << a1.a0 << "))"
+            << "\n";
+
+  Struct8BytesNestedFloat result;
+
+  result.a0.a0 = a0.a0;
+  result.a1.a0 = a1.a0;
+
+  std::cout << "result = "
+            << "((" << result.a0.a0 << "), (" << result.a1.a0 << "))"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// The nesting is irregular, testing homogenous float rules on arm and arm64,
+// and the fpu register usage on x64.
+DART_EXPORT Struct8BytesNestedFloat2
+ReturnStruct8BytesNestedFloat2(Struct4BytesFloat a0, float a1) {
+  std::cout << "ReturnStruct8BytesNestedFloat2"
+            << "((" << a0.a0 << "), " << a1 << ")"
+            << "\n";
+
+  Struct8BytesNestedFloat2 result;
+
+  result.a0.a0 = a0.a0;
+  result.a1 = a1;
+
+  std::cout << "result = "
+            << "((" << result.a0.a0 << "), " << result.a1 << ")"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Simple nested struct with mixed members.
+DART_EXPORT Struct8BytesNestedMixed
+ReturnStruct8BytesNestedMixed(Struct4BytesHomogeneousInt16 a0,
+                              Struct4BytesFloat a1) {
+  std::cout << "ReturnStruct8BytesNestedMixed"
+            << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << "))"
+            << "\n";
+
+  Struct8BytesNestedMixed result;
+
+  result.a0.a0 = a0.a0;
+  result.a0.a1 = a0.a1;
+  result.a1.a0 = a1.a0;
+
+  std::cout << "result = "
+            << "((" << result.a0.a0 << ", " << result.a0.a1 << "), ("
+            << result.a1.a0 << "))"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Deeper nested struct to test recursive member access.
+DART_EXPORT Struct16BytesNestedInt
+ReturnStruct16BytesNestedInt(Struct8BytesNestedInt a0,
+                             Struct8BytesNestedInt a1) {
+  std::cout << "ReturnStruct16BytesNestedInt"
+            << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0
+            << ", " << a0.a1.a1 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1
+            << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ")))"
+            << "\n";
+
+  Struct16BytesNestedInt result;
+
+  result.a0.a0.a0 = a0.a0.a0;
+  result.a0.a0.a1 = a0.a0.a1;
+  result.a0.a1.a0 = a0.a1.a0;
+  result.a0.a1.a1 = a0.a1.a1;
+  result.a1.a0.a0 = a1.a0.a0;
+  result.a1.a0.a1 = a1.a0.a1;
+  result.a1.a1.a0 = a1.a1.a0;
+  result.a1.a1.a1 = a1.a1.a1;
+
+  std::cout << "result = "
+            << "(((" << result.a0.a0.a0 << ", " << result.a0.a0.a1 << "), ("
+            << result.a0.a1.a0 << ", " << result.a0.a1.a1 << ")), (("
+            << result.a1.a0.a0 << ", " << result.a1.a0.a1 << "), ("
+            << result.a1.a1.a0 << ", " << result.a1.a1.a1 << ")))"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Even deeper nested struct to test recursive member access.
+DART_EXPORT Struct32BytesNestedInt
+ReturnStruct32BytesNestedInt(Struct16BytesNestedInt a0,
+                             Struct16BytesNestedInt a1) {
+  std::cout << "ReturnStruct32BytesNestedInt"
+            << "((((" << a0.a0.a0.a0 << ", " << a0.a0.a0.a1 << "), ("
+            << a0.a0.a1.a0 << ", " << a0.a0.a1.a1 << ")), ((" << a0.a1.a0.a0
+            << ", " << a0.a1.a0.a1 << "), (" << a0.a1.a1.a0 << ", "
+            << a0.a1.a1.a1 << "))), (((" << a1.a0.a0.a0 << ", " << a1.a0.a0.a1
+            << "), (" << a1.a0.a1.a0 << ", " << a1.a0.a1.a1 << ")), (("
+            << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0
+            << ", " << a1.a1.a1.a1 << "))))"
+            << "\n";
+
+  Struct32BytesNestedInt result;
+
+  result.a0.a0.a0.a0 = a0.a0.a0.a0;
+  result.a0.a0.a0.a1 = a0.a0.a0.a1;
+  result.a0.a0.a1.a0 = a0.a0.a1.a0;
+  result.a0.a0.a1.a1 = a0.a0.a1.a1;
+  result.a0.a1.a0.a0 = a0.a1.a0.a0;
+  result.a0.a1.a0.a1 = a0.a1.a0.a1;
+  result.a0.a1.a1.a0 = a0.a1.a1.a0;
+  result.a0.a1.a1.a1 = a0.a1.a1.a1;
+  result.a1.a0.a0.a0 = a1.a0.a0.a0;
+  result.a1.a0.a0.a1 = a1.a0.a0.a1;
+  result.a1.a0.a1.a0 = a1.a0.a1.a0;
+  result.a1.a0.a1.a1 = a1.a0.a1.a1;
+  result.a1.a1.a0.a0 = a1.a1.a0.a0;
+  result.a1.a1.a0.a1 = a1.a1.a0.a1;
+  result.a1.a1.a1.a0 = a1.a1.a1.a0;
+  result.a1.a1.a1.a1 = a1.a1.a1.a1;
+
+  std::cout << "result = "
+            << "((((" << result.a0.a0.a0.a0 << ", " << result.a0.a0.a0.a1
+            << "), (" << result.a0.a0.a1.a0 << ", " << result.a0.a0.a1.a1
+            << ")), ((" << result.a0.a1.a0.a0 << ", " << result.a0.a1.a0.a1
+            << "), (" << result.a0.a1.a1.a0 << ", " << result.a0.a1.a1.a1
+            << "))), (((" << result.a1.a0.a0.a0 << ", " << result.a1.a0.a0.a1
+            << "), (" << result.a1.a0.a1.a0 << ", " << result.a1.a0.a1.a1
+            << ")), ((" << result.a1.a1.a0.a0 << ", " << result.a1.a1.a0.a1
+            << "), (" << result.a1.a1.a1.a0 << ", " << result.a1.a1.a1.a1
+            << "))))"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 16 byte int.
+DART_EXPORT StructNestedIntStructAlignmentInt16
+ReturnStructNestedIntStructAlignmentInt16(StructAlignmentInt16 a0,
+                                          StructAlignmentInt16 a1) {
+  std::cout << "ReturnStructNestedIntStructAlignmentInt16"
+            << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+            << static_cast<int>(a0.a2) << "), (" << static_cast<int>(a1.a0)
+            << ", " << a1.a1 << ", " << static_cast<int>(a1.a2) << "))"
+            << "\n";
+
+  StructNestedIntStructAlignmentInt16 result;
+
+  result.a0.a0 = a0.a0;
+  result.a0.a1 = a0.a1;
+  result.a0.a2 = a0.a2;
+  result.a1.a0 = a1.a0;
+  result.a1.a1 = a1.a1;
+  result.a1.a2 = a1.a2;
+
+  std::cout << "result = "
+            << "((" << static_cast<int>(result.a0.a0) << ", " << result.a0.a1
+            << ", " << static_cast<int>(result.a0.a2) << "), ("
+            << static_cast<int>(result.a1.a0) << ", " << result.a1.a1 << ", "
+            << static_cast<int>(result.a1.a2) << "))"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 32 byte int.
+DART_EXPORT StructNestedIntStructAlignmentInt32
+ReturnStructNestedIntStructAlignmentInt32(StructAlignmentInt32 a0,
+                                          StructAlignmentInt32 a1) {
+  std::cout << "ReturnStructNestedIntStructAlignmentInt32"
+            << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+            << static_cast<int>(a0.a2) << "), (" << static_cast<int>(a1.a0)
+            << ", " << a1.a1 << ", " << static_cast<int>(a1.a2) << "))"
+            << "\n";
+
+  StructNestedIntStructAlignmentInt32 result;
+
+  result.a0.a0 = a0.a0;
+  result.a0.a1 = a0.a1;
+  result.a0.a2 = a0.a2;
+  result.a1.a0 = a1.a0;
+  result.a1.a1 = a1.a1;
+  result.a1.a2 = a1.a2;
+
+  std::cout << "result = "
+            << "((" << static_cast<int>(result.a0.a0) << ", " << result.a0.a1
+            << ", " << static_cast<int>(result.a0.a2) << "), ("
+            << static_cast<int>(result.a1.a0) << ", " << result.a1.a1 << ", "
+            << static_cast<int>(result.a1.a2) << "))"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 64 byte int.
+DART_EXPORT StructNestedIntStructAlignmentInt64
+ReturnStructNestedIntStructAlignmentInt64(StructAlignmentInt64 a0,
+                                          StructAlignmentInt64 a1) {
+  std::cout << "ReturnStructNestedIntStructAlignmentInt64"
+            << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+            << static_cast<int>(a0.a2) << "), (" << static_cast<int>(a1.a0)
+            << ", " << a1.a1 << ", " << static_cast<int>(a1.a2) << "))"
+            << "\n";
+
+  StructNestedIntStructAlignmentInt64 result;
+
+  result.a0.a0 = a0.a0;
+  result.a0.a1 = a0.a1;
+  result.a0.a2 = a0.a2;
+  result.a1.a0 = a1.a0;
+  result.a1.a1 = a1.a1;
+  result.a1.a2 = a1.a2;
+
+  std::cout << "result = "
+            << "((" << static_cast<int>(result.a0.a0) << ", " << result.a0.a1
+            << ", " << static_cast<int>(result.a0.a2) << "), ("
+            << static_cast<int>(result.a1.a0) << ", " << result.a1.a1 << ", "
+            << static_cast<int>(result.a1.a2) << "))"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
+// Return big irregular struct as smoke test.
+DART_EXPORT StructNestedIrregularEvenBigger
+ReturnStructNestedIrregularEvenBigger(uint64_t a0,
+                                      StructNestedIrregularBigger a1,
+                                      StructNestedIrregularBigger a2,
+                                      double a3) {
+  std::cout << "ReturnStructNestedIrregularEvenBigger"
+            << "(" << a0 << ", ((" << a1.a0.a0 << ", ((" << a1.a0.a1.a0.a0
+            << ", " << a1.a0.a1.a0.a1 << "), (" << a1.a0.a1.a1.a0 << ")), "
+            << a1.a0.a2 << ", ((" << a1.a0.a3.a0.a0 << "), " << a1.a0.a3.a1
+            << "), " << a1.a0.a4 << ", ((" << a1.a0.a5.a0.a0 << "), ("
+            << a1.a0.a5.a1.a0 << ")), " << a1.a0.a6 << "), ((" << a1.a1.a0.a0
+            << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0 << ")), " << a1.a2
+            << ", " << a1.a3 << "), ((" << a2.a0.a0 << ", ((" << a2.a0.a1.a0.a0
+            << ", " << a2.a0.a1.a0.a1 << "), (" << a2.a0.a1.a1.a0 << ")), "
+            << a2.a0.a2 << ", ((" << a2.a0.a3.a0.a0 << "), " << a2.a0.a3.a1
+            << "), " << a2.a0.a4 << ", ((" << a2.a0.a5.a0.a0 << "), ("
+            << a2.a0.a5.a1.a0 << ")), " << a2.a0.a6 << "), ((" << a2.a1.a0.a0
+            << ", " << a2.a1.a0.a1 << "), (" << a2.a1.a1.a0 << ")), " << a2.a2
+            << ", " << a2.a3 << "), " << a3 << ")"
+            << "\n";
+
+  StructNestedIrregularEvenBigger result;
+
+  result.a0 = a0;
+  result.a1.a0.a0 = a1.a0.a0;
+  result.a1.a0.a1.a0.a0 = a1.a0.a1.a0.a0;
+  result.a1.a0.a1.a0.a1 = a1.a0.a1.a0.a1;
+  result.a1.a0.a1.a1.a0 = a1.a0.a1.a1.a0;
+  result.a1.a0.a2 = a1.a0.a2;
+  result.a1.a0.a3.a0.a0 = a1.a0.a3.a0.a0;
+  result.a1.a0.a3.a1 = a1.a0.a3.a1;
+  result.a1.a0.a4 = a1.a0.a4;
+  result.a1.a0.a5.a0.a0 = a1.a0.a5.a0.a0;
+  result.a1.a0.a5.a1.a0 = a1.a0.a5.a1.a0;
+  result.a1.a0.a6 = a1.a0.a6;
+  result.a1.a1.a0.a0 = a1.a1.a0.a0;
+  result.a1.a1.a0.a1 = a1.a1.a0.a1;
+  result.a1.a1.a1.a0 = a1.a1.a1.a0;
+  result.a1.a2 = a1.a2;
+  result.a1.a3 = a1.a3;
+  result.a2.a0.a0 = a2.a0.a0;
+  result.a2.a0.a1.a0.a0 = a2.a0.a1.a0.a0;
+  result.a2.a0.a1.a0.a1 = a2.a0.a1.a0.a1;
+  result.a2.a0.a1.a1.a0 = a2.a0.a1.a1.a0;
+  result.a2.a0.a2 = a2.a0.a2;
+  result.a2.a0.a3.a0.a0 = a2.a0.a3.a0.a0;
+  result.a2.a0.a3.a1 = a2.a0.a3.a1;
+  result.a2.a0.a4 = a2.a0.a4;
+  result.a2.a0.a5.a0.a0 = a2.a0.a5.a0.a0;
+  result.a2.a0.a5.a1.a0 = a2.a0.a5.a1.a0;
+  result.a2.a0.a6 = a2.a0.a6;
+  result.a2.a1.a0.a0 = a2.a1.a0.a0;
+  result.a2.a1.a0.a1 = a2.a1.a0.a1;
+  result.a2.a1.a1.a0 = a2.a1.a1.a0;
+  result.a2.a2 = a2.a2;
+  result.a2.a3 = a2.a3;
+  result.a3 = a3;
+
+  std::cout << "result = "
+            << "(" << result.a0 << ", ((" << result.a1.a0.a0 << ", (("
+            << result.a1.a0.a1.a0.a0 << ", " << result.a1.a0.a1.a0.a1 << "), ("
+            << result.a1.a0.a1.a1.a0 << ")), " << result.a1.a0.a2 << ", (("
+            << result.a1.a0.a3.a0.a0 << "), " << result.a1.a0.a3.a1 << "), "
+            << result.a1.a0.a4 << ", ((" << result.a1.a0.a5.a0.a0 << "), ("
+            << result.a1.a0.a5.a1.a0 << ")), " << result.a1.a0.a6 << "), (("
+            << result.a1.a1.a0.a0 << ", " << result.a1.a1.a0.a1 << "), ("
+            << result.a1.a1.a1.a0 << ")), " << result.a1.a2 << ", "
+            << result.a1.a3 << "), ((" << result.a2.a0.a0 << ", (("
+            << result.a2.a0.a1.a0.a0 << ", " << result.a2.a0.a1.a0.a1 << "), ("
+            << result.a2.a0.a1.a1.a0 << ")), " << result.a2.a0.a2 << ", (("
+            << result.a2.a0.a3.a0.a0 << "), " << result.a2.a0.a3.a1 << "), "
+            << result.a2.a0.a4 << ", ((" << result.a2.a0.a5.a0.a0 << "), ("
+            << result.a2.a0.a5.a1.a0 << ")), " << result.a2.a0.a6 << "), (("
+            << result.a2.a1.a0.a0 << ", " << result.a2.a1.a0.a1 << "), ("
+            << result.a2.a1.a1.a0 << ")), " << result.a2.a2 << ", "
+            << result.a2.a3 << "), " << result.a3 << ")"
+            << "\n";
+
+  return result;
+}
+
+// Used for testing structs by value.
 // Smallest struct with data.
 // 10 struct arguments will exhaust available registers.
 DART_EXPORT intptr_t TestPassStruct1ByteIntx10(
@@ -6790,6 +7837,874 @@
 }
 
 // Used for testing structs by value.
+// Simple nested struct. No alignment gaps on any architectures.
+// 10 arguments exhaust registers on all platforms.
+DART_EXPORT intptr_t TestPassStruct8BytesNestedIntx10(
+    // NOLINTNEXTLINE(whitespace/parens)
+    int64_t (*f)(Struct8BytesNestedInt a0,
+                 Struct8BytesNestedInt a1,
+                 Struct8BytesNestedInt a2,
+                 Struct8BytesNestedInt a3,
+                 Struct8BytesNestedInt a4,
+                 Struct8BytesNestedInt a5,
+                 Struct8BytesNestedInt a6,
+                 Struct8BytesNestedInt a7,
+                 Struct8BytesNestedInt a8,
+                 Struct8BytesNestedInt a9)) {
+  Struct8BytesNestedInt a0;
+  Struct8BytesNestedInt a1;
+  Struct8BytesNestedInt a2;
+  Struct8BytesNestedInt a3;
+  Struct8BytesNestedInt a4;
+  Struct8BytesNestedInt a5;
+  Struct8BytesNestedInt a6;
+  Struct8BytesNestedInt a7;
+  Struct8BytesNestedInt a8;
+  Struct8BytesNestedInt a9;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3;
+  a0.a1.a1 = 4;
+  a1.a0.a0 = -5;
+  a1.a0.a1 = 6;
+  a1.a1.a0 = -7;
+  a1.a1.a1 = 8;
+  a2.a0.a0 = -9;
+  a2.a0.a1 = 10;
+  a2.a1.a0 = -11;
+  a2.a1.a1 = 12;
+  a3.a0.a0 = -13;
+  a3.a0.a1 = 14;
+  a3.a1.a0 = -15;
+  a3.a1.a1 = 16;
+  a4.a0.a0 = -17;
+  a4.a0.a1 = 18;
+  a4.a1.a0 = -19;
+  a4.a1.a1 = 20;
+  a5.a0.a0 = -21;
+  a5.a0.a1 = 22;
+  a5.a1.a0 = -23;
+  a5.a1.a1 = 24;
+  a6.a0.a0 = -25;
+  a6.a0.a1 = 26;
+  a6.a1.a0 = -27;
+  a6.a1.a1 = 28;
+  a7.a0.a0 = -29;
+  a7.a0.a1 = 30;
+  a7.a1.a0 = -31;
+  a7.a1.a1 = 32;
+  a8.a0.a0 = -33;
+  a8.a0.a1 = 34;
+  a8.a1.a0 = -35;
+  a8.a1.a1 = 36;
+  a9.a0.a0 = -37;
+  a9.a0.a1 = 38;
+  a9.a1.a0 = -39;
+  a9.a1.a1 = 40;
+
+  std::cout << "Calling TestPassStruct8BytesNestedIntx10("
+            << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0
+            << ", " << a0.a1.a1 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1
+            << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ")), ((" << a2.a0.a0
+            << ", " << a2.a0.a1 << "), (" << a2.a1.a0 << ", " << a2.a1.a1
+            << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0
+            << ", " << a3.a1.a1 << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1
+            << "), (" << a4.a1.a0 << ", " << a4.a1.a1 << ")), ((" << a5.a0.a0
+            << ", " << a5.a0.a1 << "), (" << a5.a1.a0 << ", " << a5.a1.a1
+            << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0
+            << ", " << a6.a1.a1 << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1
+            << "), (" << a7.a1.a0 << ", " << a7.a1.a1 << ")), ((" << a8.a0.a0
+            << ", " << a8.a0.a1 << "), (" << a8.a1.a0 << ", " << a8.a1.a1
+            << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0
+            << ", " << a9.a1.a1 << ")))"
+            << ")\n";
+
+  int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_EQ(20, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0 = 42;
+
+  result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  CHECK_EQ(0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0 = 84;
+
+  result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  CHECK_EQ(0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Simple nested struct. No alignment gaps on any architectures.
+// 10 arguments exhaust fpu registers on all platforms.
+DART_EXPORT intptr_t TestPassStruct8BytesNestedFloatx10(
+    // NOLINTNEXTLINE(whitespace/parens)
+    float (*f)(Struct8BytesNestedFloat a0,
+               Struct8BytesNestedFloat a1,
+               Struct8BytesNestedFloat a2,
+               Struct8BytesNestedFloat a3,
+               Struct8BytesNestedFloat a4,
+               Struct8BytesNestedFloat a5,
+               Struct8BytesNestedFloat a6,
+               Struct8BytesNestedFloat a7,
+               Struct8BytesNestedFloat a8,
+               Struct8BytesNestedFloat a9)) {
+  Struct8BytesNestedFloat a0;
+  Struct8BytesNestedFloat a1;
+  Struct8BytesNestedFloat a2;
+  Struct8BytesNestedFloat a3;
+  Struct8BytesNestedFloat a4;
+  Struct8BytesNestedFloat a5;
+  Struct8BytesNestedFloat a6;
+  Struct8BytesNestedFloat a7;
+  Struct8BytesNestedFloat a8;
+  Struct8BytesNestedFloat a9;
+
+  a0.a0.a0 = -1.0;
+  a0.a1.a0 = 2.0;
+  a1.a0.a0 = -3.0;
+  a1.a1.a0 = 4.0;
+  a2.a0.a0 = -5.0;
+  a2.a1.a0 = 6.0;
+  a3.a0.a0 = -7.0;
+  a3.a1.a0 = 8.0;
+  a4.a0.a0 = -9.0;
+  a4.a1.a0 = 10.0;
+  a5.a0.a0 = -11.0;
+  a5.a1.a0 = 12.0;
+  a6.a0.a0 = -13.0;
+  a6.a1.a0 = 14.0;
+  a7.a0.a0 = -15.0;
+  a7.a1.a0 = 16.0;
+  a8.a0.a0 = -17.0;
+  a8.a1.a0 = 18.0;
+  a9.a0.a0 = -19.0;
+  a9.a1.a0 = 20.0;
+
+  std::cout << "Calling TestPassStruct8BytesNestedFloatx10("
+            << "(((" << a0.a0.a0 << "), (" << a0.a1.a0 << ")), ((" << a1.a0.a0
+            << "), (" << a1.a1.a0 << ")), ((" << a2.a0.a0 << "), (" << a2.a1.a0
+            << ")), ((" << a3.a0.a0 << "), (" << a3.a1.a0 << ")), (("
+            << a4.a0.a0 << "), (" << a4.a1.a0 << ")), ((" << a5.a0.a0 << "), ("
+            << a5.a1.a0 << ")), ((" << a6.a0.a0 << "), (" << a6.a1.a0
+            << ")), ((" << a7.a0.a0 << "), (" << a7.a1.a0 << ")), (("
+            << a8.a0.a0 << "), (" << a8.a1.a0 << ")), ((" << a9.a0.a0 << "), ("
+            << a9.a1.a0 << ")))"
+            << ")\n";
+
+  float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_APPROX(10.0, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0 = 42;
+
+  result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  CHECK_APPROX(0.0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0 = 84;
+
+  result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  CHECK_APPROX(0.0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Simple nested struct. No alignment gaps on any architectures.
+// 10 arguments exhaust fpu registers on all platforms.
+// The nesting is irregular, testing homogenous float rules on arm and arm64,
+// and the fpu register usage on x64.
+DART_EXPORT intptr_t TestPassStruct8BytesNestedFloat2x10(
+    // NOLINTNEXTLINE(whitespace/parens)
+    float (*f)(Struct8BytesNestedFloat2 a0,
+               Struct8BytesNestedFloat2 a1,
+               Struct8BytesNestedFloat2 a2,
+               Struct8BytesNestedFloat2 a3,
+               Struct8BytesNestedFloat2 a4,
+               Struct8BytesNestedFloat2 a5,
+               Struct8BytesNestedFloat2 a6,
+               Struct8BytesNestedFloat2 a7,
+               Struct8BytesNestedFloat2 a8,
+               Struct8BytesNestedFloat2 a9)) {
+  Struct8BytesNestedFloat2 a0;
+  Struct8BytesNestedFloat2 a1;
+  Struct8BytesNestedFloat2 a2;
+  Struct8BytesNestedFloat2 a3;
+  Struct8BytesNestedFloat2 a4;
+  Struct8BytesNestedFloat2 a5;
+  Struct8BytesNestedFloat2 a6;
+  Struct8BytesNestedFloat2 a7;
+  Struct8BytesNestedFloat2 a8;
+  Struct8BytesNestedFloat2 a9;
+
+  a0.a0.a0 = -1.0;
+  a0.a1 = 2.0;
+  a1.a0.a0 = -3.0;
+  a1.a1 = 4.0;
+  a2.a0.a0 = -5.0;
+  a2.a1 = 6.0;
+  a3.a0.a0 = -7.0;
+  a3.a1 = 8.0;
+  a4.a0.a0 = -9.0;
+  a4.a1 = 10.0;
+  a5.a0.a0 = -11.0;
+  a5.a1 = 12.0;
+  a6.a0.a0 = -13.0;
+  a6.a1 = 14.0;
+  a7.a0.a0 = -15.0;
+  a7.a1 = 16.0;
+  a8.a0.a0 = -17.0;
+  a8.a1 = 18.0;
+  a9.a0.a0 = -19.0;
+  a9.a1 = 20.0;
+
+  std::cout << "Calling TestPassStruct8BytesNestedFloat2x10("
+            << "(((" << a0.a0.a0 << "), " << a0.a1 << "), ((" << a1.a0.a0
+            << "), " << a1.a1 << "), ((" << a2.a0.a0 << "), " << a2.a1
+            << "), ((" << a3.a0.a0 << "), " << a3.a1 << "), ((" << a4.a0.a0
+            << "), " << a4.a1 << "), ((" << a5.a0.a0 << "), " << a5.a1
+            << "), ((" << a6.a0.a0 << "), " << a6.a1 << "), ((" << a7.a0.a0
+            << "), " << a7.a1 << "), ((" << a8.a0.a0 << "), " << a8.a1
+            << "), ((" << a9.a0.a0 << "), " << a9.a1 << "))"
+            << ")\n";
+
+  float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_APPROX(10.0, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0 = 42;
+
+  result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  CHECK_APPROX(0.0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0 = 84;
+
+  result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  CHECK_APPROX(0.0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Simple nested struct. No alignment gaps on any architectures.
+// 10 arguments exhaust all registers on all platforms.
+DART_EXPORT intptr_t TestPassStruct8BytesNestedMixedx10(
+    // NOLINTNEXTLINE(whitespace/parens)
+    double (*f)(Struct8BytesNestedMixed a0,
+                Struct8BytesNestedMixed a1,
+                Struct8BytesNestedMixed a2,
+                Struct8BytesNestedMixed a3,
+                Struct8BytesNestedMixed a4,
+                Struct8BytesNestedMixed a5,
+                Struct8BytesNestedMixed a6,
+                Struct8BytesNestedMixed a7,
+                Struct8BytesNestedMixed a8,
+                Struct8BytesNestedMixed a9)) {
+  Struct8BytesNestedMixed a0;
+  Struct8BytesNestedMixed a1;
+  Struct8BytesNestedMixed a2;
+  Struct8BytesNestedMixed a3;
+  Struct8BytesNestedMixed a4;
+  Struct8BytesNestedMixed a5;
+  Struct8BytesNestedMixed a6;
+  Struct8BytesNestedMixed a7;
+  Struct8BytesNestedMixed a8;
+  Struct8BytesNestedMixed a9;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3.0;
+  a1.a0.a0 = 4;
+  a1.a0.a1 = -5;
+  a1.a1.a0 = 6.0;
+  a2.a0.a0 = -7;
+  a2.a0.a1 = 8;
+  a2.a1.a0 = -9.0;
+  a3.a0.a0 = 10;
+  a3.a0.a1 = -11;
+  a3.a1.a0 = 12.0;
+  a4.a0.a0 = -13;
+  a4.a0.a1 = 14;
+  a4.a1.a0 = -15.0;
+  a5.a0.a0 = 16;
+  a5.a0.a1 = -17;
+  a5.a1.a0 = 18.0;
+  a6.a0.a0 = -19;
+  a6.a0.a1 = 20;
+  a6.a1.a0 = -21.0;
+  a7.a0.a0 = 22;
+  a7.a0.a1 = -23;
+  a7.a1.a0 = 24.0;
+  a8.a0.a0 = -25;
+  a8.a0.a1 = 26;
+  a8.a1.a0 = -27.0;
+  a9.a0.a0 = 28;
+  a9.a0.a1 = -29;
+  a9.a1.a0 = 30.0;
+
+  std::cout << "Calling TestPassStruct8BytesNestedMixedx10("
+            << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0
+            << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0
+            << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << "), (" << a2.a1.a0
+            << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0
+            << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << "), (" << a4.a1.a0
+            << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << "), (" << a5.a1.a0
+            << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0
+            << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << "), (" << a7.a1.a0
+            << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << "), (" << a8.a1.a0
+            << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0
+            << ")))"
+            << ")\n";
+
+  double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_APPROX(15.0, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0 = 42;
+
+  result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  CHECK_APPROX(0.0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0 = 84;
+
+  result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  CHECK_APPROX(0.0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Deeper nested struct to test recursive member access.
+DART_EXPORT intptr_t TestPassStruct16BytesNestedIntx2(
+    // NOLINTNEXTLINE(whitespace/parens)
+    int64_t (*f)(Struct16BytesNestedInt a0, Struct16BytesNestedInt a1)) {
+  Struct16BytesNestedInt a0;
+  Struct16BytesNestedInt a1;
+
+  a0.a0.a0.a0 = -1;
+  a0.a0.a0.a1 = 2;
+  a0.a0.a1.a0 = -3;
+  a0.a0.a1.a1 = 4;
+  a0.a1.a0.a0 = -5;
+  a0.a1.a0.a1 = 6;
+  a0.a1.a1.a0 = -7;
+  a0.a1.a1.a1 = 8;
+  a1.a0.a0.a0 = -9;
+  a1.a0.a0.a1 = 10;
+  a1.a0.a1.a0 = -11;
+  a1.a0.a1.a1 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15;
+  a1.a1.a1.a1 = 16;
+
+  std::cout << "Calling TestPassStruct16BytesNestedIntx2("
+            << "((((" << a0.a0.a0.a0 << ", " << a0.a0.a0.a1 << "), ("
+            << a0.a0.a1.a0 << ", " << a0.a0.a1.a1 << ")), ((" << a0.a1.a0.a0
+            << ", " << a0.a1.a0.a1 << "), (" << a0.a1.a1.a0 << ", "
+            << a0.a1.a1.a1 << "))), (((" << a1.a0.a0.a0 << ", " << a1.a0.a0.a1
+            << "), (" << a1.a0.a1.a0 << ", " << a1.a0.a1.a1 << ")), (("
+            << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0
+            << ", " << a1.a1.a1.a1 << "))))"
+            << ")\n";
+
+  int64_t result = f(a0, a1);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_EQ(8, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Even deeper nested struct to test recursive member access.
+DART_EXPORT intptr_t TestPassStruct32BytesNestedIntx2(
+    // NOLINTNEXTLINE(whitespace/parens)
+    int64_t (*f)(Struct32BytesNestedInt a0, Struct32BytesNestedInt a1)) {
+  Struct32BytesNestedInt a0;
+  Struct32BytesNestedInt a1;
+
+  a0.a0.a0.a0.a0 = -1;
+  a0.a0.a0.a0.a1 = 2;
+  a0.a0.a0.a1.a0 = -3;
+  a0.a0.a0.a1.a1 = 4;
+  a0.a0.a1.a0.a0 = -5;
+  a0.a0.a1.a0.a1 = 6;
+  a0.a0.a1.a1.a0 = -7;
+  a0.a0.a1.a1.a1 = 8;
+  a0.a1.a0.a0.a0 = -9;
+  a0.a1.a0.a0.a1 = 10;
+  a0.a1.a0.a1.a0 = -11;
+  a0.a1.a0.a1.a1 = 12;
+  a0.a1.a1.a0.a0 = -13;
+  a0.a1.a1.a0.a1 = 14;
+  a0.a1.a1.a1.a0 = -15;
+  a0.a1.a1.a1.a1 = 16;
+  a1.a0.a0.a0.a0 = -17;
+  a1.a0.a0.a0.a1 = 18;
+  a1.a0.a0.a1.a0 = -19;
+  a1.a0.a0.a1.a1 = 20;
+  a1.a0.a1.a0.a0 = -21;
+  a1.a0.a1.a0.a1 = 22;
+  a1.a0.a1.a1.a0 = -23;
+  a1.a0.a1.a1.a1 = 24;
+  a1.a1.a0.a0.a0 = -25;
+  a1.a1.a0.a0.a1 = 26;
+  a1.a1.a0.a1.a0 = -27;
+  a1.a1.a0.a1.a1 = 28;
+  a1.a1.a1.a0.a0 = -29;
+  a1.a1.a1.a0.a1 = 30;
+  a1.a1.a1.a1.a0 = -31;
+  a1.a1.a1.a1.a1 = 32;
+
+  std::cout << "Calling TestPassStruct32BytesNestedIntx2("
+            << "(((((" << a0.a0.a0.a0.a0 << ", " << a0.a0.a0.a0.a1 << "), ("
+            << a0.a0.a0.a1.a0 << ", " << a0.a0.a0.a1.a1 << ")), (("
+            << a0.a0.a1.a0.a0 << ", " << a0.a0.a1.a0.a1 << "), ("
+            << a0.a0.a1.a1.a0 << ", " << a0.a0.a1.a1.a1 << "))), ((("
+            << a0.a1.a0.a0.a0 << ", " << a0.a1.a0.a0.a1 << "), ("
+            << a0.a1.a0.a1.a0 << ", " << a0.a1.a0.a1.a1 << ")), (("
+            << a0.a1.a1.a0.a0 << ", " << a0.a1.a1.a0.a1 << "), ("
+            << a0.a1.a1.a1.a0 << ", " << a0.a1.a1.a1.a1 << ")))), (((("
+            << a1.a0.a0.a0.a0 << ", " << a1.a0.a0.a0.a1 << "), ("
+            << a1.a0.a0.a1.a0 << ", " << a1.a0.a0.a1.a1 << ")), (("
+            << a1.a0.a1.a0.a0 << ", " << a1.a0.a1.a0.a1 << "), ("
+            << a1.a0.a1.a1.a0 << ", " << a1.a0.a1.a1.a1 << "))), ((("
+            << a1.a1.a0.a0.a0 << ", " << a1.a1.a0.a0.a1 << "), ("
+            << a1.a1.a0.a1.a0 << ", " << a1.a1.a0.a1.a1 << ")), (("
+            << a1.a1.a1.a0.a0 << ", " << a1.a1.a1.a0.a1 << "), ("
+            << a1.a1.a1.a1.a0 << ", " << a1.a1.a1.a1.a1 << ")))))"
+            << ")\n";
+
+  int64_t result = f(a0, a1);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_EQ(16, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0.a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0.a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 16 byte int.
+DART_EXPORT intptr_t TestPassStructNestedIntStructAlignmentInt16(
+    // NOLINTNEXTLINE(whitespace/parens)
+    int64_t (*f)(StructNestedIntStructAlignmentInt16 a0)) {
+  StructNestedIntStructAlignmentInt16 a0;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  std::cout << "Calling TestPassStructNestedIntStructAlignmentInt16("
+            << "(((" << static_cast<int>(a0.a0.a0) << ", " << a0.a0.a1 << ", "
+            << static_cast<int>(a0.a0.a2) << "), ("
+            << static_cast<int>(a0.a1.a0) << ", " << a0.a1.a1 << ", "
+            << static_cast<int>(a0.a1.a2) << ")))"
+            << ")\n";
+
+  int64_t result = f(a0);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_EQ(3, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0 = 42;
+
+  result = f(a0);
+
+  CHECK_EQ(0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0 = 84;
+
+  result = f(a0);
+
+  CHECK_EQ(0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 32 byte int.
+DART_EXPORT intptr_t TestPassStructNestedIntStructAlignmentInt32(
+    // NOLINTNEXTLINE(whitespace/parens)
+    int64_t (*f)(StructNestedIntStructAlignmentInt32 a0)) {
+  StructNestedIntStructAlignmentInt32 a0;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  std::cout << "Calling TestPassStructNestedIntStructAlignmentInt32("
+            << "(((" << static_cast<int>(a0.a0.a0) << ", " << a0.a0.a1 << ", "
+            << static_cast<int>(a0.a0.a2) << "), ("
+            << static_cast<int>(a0.a1.a0) << ", " << a0.a1.a1 << ", "
+            << static_cast<int>(a0.a1.a2) << ")))"
+            << ")\n";
+
+  int64_t result = f(a0);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_EQ(3, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0 = 42;
+
+  result = f(a0);
+
+  CHECK_EQ(0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0 = 84;
+
+  result = f(a0);
+
+  CHECK_EQ(0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 64 byte int.
+DART_EXPORT intptr_t TestPassStructNestedIntStructAlignmentInt64(
+    // NOLINTNEXTLINE(whitespace/parens)
+    int64_t (*f)(StructNestedIntStructAlignmentInt64 a0)) {
+  StructNestedIntStructAlignmentInt64 a0;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  std::cout << "Calling TestPassStructNestedIntStructAlignmentInt64("
+            << "(((" << static_cast<int>(a0.a0.a0) << ", " << a0.a0.a1 << ", "
+            << static_cast<int>(a0.a0.a2) << "), ("
+            << static_cast<int>(a0.a1.a0) << ", " << a0.a1.a1 << ", "
+            << static_cast<int>(a0.a1.a2) << ")))"
+            << ")\n";
+
+  int64_t result = f(a0);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_EQ(3, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0 = 42;
+
+  result = f(a0);
+
+  CHECK_EQ(0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0 = 84;
+
+  result = f(a0);
+
+  CHECK_EQ(0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Return big irregular struct as smoke test.
+DART_EXPORT intptr_t TestPassStructNestedIrregularEvenBiggerx4(
+    // NOLINTNEXTLINE(whitespace/parens)
+    double (*f)(StructNestedIrregularEvenBigger a0,
+                StructNestedIrregularEvenBigger a1,
+                StructNestedIrregularEvenBigger a2,
+                StructNestedIrregularEvenBigger a3)) {
+  StructNestedIrregularEvenBigger a0;
+  StructNestedIrregularEvenBigger a1;
+  StructNestedIrregularEvenBigger a2;
+  StructNestedIrregularEvenBigger a3;
+
+  a0.a0 = 1;
+  a0.a1.a0.a0 = 2;
+  a0.a1.a0.a1.a0.a0 = -3;
+  a0.a1.a0.a1.a0.a1 = 4;
+  a0.a1.a0.a1.a1.a0 = -5.0;
+  a0.a1.a0.a2 = 6;
+  a0.a1.a0.a3.a0.a0 = -7.0;
+  a0.a1.a0.a3.a1 = 8.0;
+  a0.a1.a0.a4 = 9;
+  a0.a1.a0.a5.a0.a0 = 10.0;
+  a0.a1.a0.a5.a1.a0 = -11.0;
+  a0.a1.a0.a6 = 12;
+  a0.a1.a1.a0.a0 = -13;
+  a0.a1.a1.a0.a1 = 14;
+  a0.a1.a1.a1.a0 = -15.0;
+  a0.a1.a2 = 16.0;
+  a0.a1.a3 = -17.0;
+  a0.a2.a0.a0 = 18;
+  a0.a2.a0.a1.a0.a0 = -19;
+  a0.a2.a0.a1.a0.a1 = 20;
+  a0.a2.a0.a1.a1.a0 = -21.0;
+  a0.a2.a0.a2 = 22;
+  a0.a2.a0.a3.a0.a0 = -23.0;
+  a0.a2.a0.a3.a1 = 24.0;
+  a0.a2.a0.a4 = 25;
+  a0.a2.a0.a5.a0.a0 = 26.0;
+  a0.a2.a0.a5.a1.a0 = -27.0;
+  a0.a2.a0.a6 = 28;
+  a0.a2.a1.a0.a0 = -29;
+  a0.a2.a1.a0.a1 = 30;
+  a0.a2.a1.a1.a0 = -31.0;
+  a0.a2.a2 = 32.0;
+  a0.a2.a3 = -33.0;
+  a0.a3 = 34.0;
+  a1.a0 = 35;
+  a1.a1.a0.a0 = 36;
+  a1.a1.a0.a1.a0.a0 = -37;
+  a1.a1.a0.a1.a0.a1 = 38;
+  a1.a1.a0.a1.a1.a0 = -39.0;
+  a1.a1.a0.a2 = 40;
+  a1.a1.a0.a3.a0.a0 = -41.0;
+  a1.a1.a0.a3.a1 = 42.0;
+  a1.a1.a0.a4 = 43;
+  a1.a1.a0.a5.a0.a0 = 44.0;
+  a1.a1.a0.a5.a1.a0 = -45.0;
+  a1.a1.a0.a6 = 46;
+  a1.a1.a1.a0.a0 = -47;
+  a1.a1.a1.a0.a1 = 48;
+  a1.a1.a1.a1.a0 = -49.0;
+  a1.a1.a2 = 50.0;
+  a1.a1.a3 = -51.0;
+  a1.a2.a0.a0 = 52;
+  a1.a2.a0.a1.a0.a0 = -53;
+  a1.a2.a0.a1.a0.a1 = 54;
+  a1.a2.a0.a1.a1.a0 = -55.0;
+  a1.a2.a0.a2 = 56;
+  a1.a2.a0.a3.a0.a0 = -57.0;
+  a1.a2.a0.a3.a1 = 58.0;
+  a1.a2.a0.a4 = 59;
+  a1.a2.a0.a5.a0.a0 = 60.0;
+  a1.a2.a0.a5.a1.a0 = -61.0;
+  a1.a2.a0.a6 = 62;
+  a1.a2.a1.a0.a0 = -63;
+  a1.a2.a1.a0.a1 = 64;
+  a1.a2.a1.a1.a0 = -65.0;
+  a1.a2.a2 = 66.0;
+  a1.a2.a3 = -67.0;
+  a1.a3 = 68.0;
+  a2.a0 = 69;
+  a2.a1.a0.a0 = 70;
+  a2.a1.a0.a1.a0.a0 = -71;
+  a2.a1.a0.a1.a0.a1 = 72;
+  a2.a1.a0.a1.a1.a0 = -73.0;
+  a2.a1.a0.a2 = 74;
+  a2.a1.a0.a3.a0.a0 = -75.0;
+  a2.a1.a0.a3.a1 = 76.0;
+  a2.a1.a0.a4 = 77;
+  a2.a1.a0.a5.a0.a0 = 78.0;
+  a2.a1.a0.a5.a1.a0 = -79.0;
+  a2.a1.a0.a6 = 80;
+  a2.a1.a1.a0.a0 = -81;
+  a2.a1.a1.a0.a1 = 82;
+  a2.a1.a1.a1.a0 = -83.0;
+  a2.a1.a2 = 84.0;
+  a2.a1.a3 = -85.0;
+  a2.a2.a0.a0 = 86;
+  a2.a2.a0.a1.a0.a0 = -87;
+  a2.a2.a0.a1.a0.a1 = 88;
+  a2.a2.a0.a1.a1.a0 = -89.0;
+  a2.a2.a0.a2 = 90;
+  a2.a2.a0.a3.a0.a0 = -91.0;
+  a2.a2.a0.a3.a1 = 92.0;
+  a2.a2.a0.a4 = 93;
+  a2.a2.a0.a5.a0.a0 = 94.0;
+  a2.a2.a0.a5.a1.a0 = -95.0;
+  a2.a2.a0.a6 = 96;
+  a2.a2.a1.a0.a0 = -97;
+  a2.a2.a1.a0.a1 = 98;
+  a2.a2.a1.a1.a0 = -99.0;
+  a2.a2.a2 = 100.0;
+  a2.a2.a3 = -101.0;
+  a2.a3 = 102.0;
+  a3.a0 = 103;
+  a3.a1.a0.a0 = 104;
+  a3.a1.a0.a1.a0.a0 = -105;
+  a3.a1.a0.a1.a0.a1 = 106;
+  a3.a1.a0.a1.a1.a0 = -107.0;
+  a3.a1.a0.a2 = 108;
+  a3.a1.a0.a3.a0.a0 = -109.0;
+  a3.a1.a0.a3.a1 = 110.0;
+  a3.a1.a0.a4 = 111;
+  a3.a1.a0.a5.a0.a0 = 112.0;
+  a3.a1.a0.a5.a1.a0 = -113.0;
+  a3.a1.a0.a6 = 114;
+  a3.a1.a1.a0.a0 = -115;
+  a3.a1.a1.a0.a1 = 116;
+  a3.a1.a1.a1.a0 = -117.0;
+  a3.a1.a2 = 118.0;
+  a3.a1.a3 = -119.0;
+  a3.a2.a0.a0 = 120;
+  a3.a2.a0.a1.a0.a0 = -121;
+  a3.a2.a0.a1.a0.a1 = 122;
+  a3.a2.a0.a1.a1.a0 = -123.0;
+  a3.a2.a0.a2 = 124;
+  a3.a2.a0.a3.a0.a0 = -125.0;
+  a3.a2.a0.a3.a1 = 126.0;
+  a3.a2.a0.a4 = 127;
+  a3.a2.a0.a5.a0.a0 = 128.0;
+  a3.a2.a0.a5.a1.a0 = -129.0;
+  a3.a2.a0.a6 = 130;
+  a3.a2.a1.a0.a0 = -131;
+  a3.a2.a1.a0.a1 = 132;
+  a3.a2.a1.a1.a0 = -133.0;
+  a3.a2.a2 = 134.0;
+  a3.a2.a3 = -135.0;
+  a3.a3 = 136.0;
+
+  std::cout
+      << "Calling TestPassStructNestedIrregularEvenBiggerx4("
+      << "((" << a0.a0 << ", ((" << a0.a1.a0.a0 << ", ((" << a0.a1.a0.a1.a0.a0
+      << ", " << a0.a1.a0.a1.a0.a1 << "), (" << a0.a1.a0.a1.a1.a0 << ")), "
+      << a0.a1.a0.a2 << ", ((" << a0.a1.a0.a3.a0.a0 << "), " << a0.a1.a0.a3.a1
+      << "), " << a0.a1.a0.a4 << ", ((" << a0.a1.a0.a5.a0.a0 << "), ("
+      << a0.a1.a0.a5.a1.a0 << ")), " << a0.a1.a0.a6 << "), ((" << a0.a1.a1.a0.a0
+      << ", " << a0.a1.a1.a0.a1 << "), (" << a0.a1.a1.a1.a0 << ")), "
+      << a0.a1.a2 << ", " << a0.a1.a3 << "), ((" << a0.a2.a0.a0 << ", (("
+      << a0.a2.a0.a1.a0.a0 << ", " << a0.a2.a0.a1.a0.a1 << "), ("
+      << a0.a2.a0.a1.a1.a0 << ")), " << a0.a2.a0.a2 << ", (("
+      << a0.a2.a0.a3.a0.a0 << "), " << a0.a2.a0.a3.a1 << "), " << a0.a2.a0.a4
+      << ", ((" << a0.a2.a0.a5.a0.a0 << "), (" << a0.a2.a0.a5.a1.a0 << ")), "
+      << a0.a2.a0.a6 << "), ((" << a0.a2.a1.a0.a0 << ", " << a0.a2.a1.a0.a1
+      << "), (" << a0.a2.a1.a1.a0 << ")), " << a0.a2.a2 << ", " << a0.a2.a3
+      << "), " << a0.a3 << "), (" << a1.a0 << ", ((" << a1.a1.a0.a0 << ", (("
+      << a1.a1.a0.a1.a0.a0 << ", " << a1.a1.a0.a1.a0.a1 << "), ("
+      << a1.a1.a0.a1.a1.a0 << ")), " << a1.a1.a0.a2 << ", (("
+      << a1.a1.a0.a3.a0.a0 << "), " << a1.a1.a0.a3.a1 << "), " << a1.a1.a0.a4
+      << ", ((" << a1.a1.a0.a5.a0.a0 << "), (" << a1.a1.a0.a5.a1.a0 << ")), "
+      << a1.a1.a0.a6 << "), ((" << a1.a1.a1.a0.a0 << ", " << a1.a1.a1.a0.a1
+      << "), (" << a1.a1.a1.a1.a0 << ")), " << a1.a1.a2 << ", " << a1.a1.a3
+      << "), ((" << a1.a2.a0.a0 << ", ((" << a1.a2.a0.a1.a0.a0 << ", "
+      << a1.a2.a0.a1.a0.a1 << "), (" << a1.a2.a0.a1.a1.a0 << ")), "
+      << a1.a2.a0.a2 << ", ((" << a1.a2.a0.a3.a0.a0 << "), " << a1.a2.a0.a3.a1
+      << "), " << a1.a2.a0.a4 << ", ((" << a1.a2.a0.a5.a0.a0 << "), ("
+      << a1.a2.a0.a5.a1.a0 << ")), " << a1.a2.a0.a6 << "), ((" << a1.a2.a1.a0.a0
+      << ", " << a1.a2.a1.a0.a1 << "), (" << a1.a2.a1.a1.a0 << ")), "
+      << a1.a2.a2 << ", " << a1.a2.a3 << "), " << a1.a3 << "), (" << a2.a0
+      << ", ((" << a2.a1.a0.a0 << ", ((" << a2.a1.a0.a1.a0.a0 << ", "
+      << a2.a1.a0.a1.a0.a1 << "), (" << a2.a1.a0.a1.a1.a0 << ")), "
+      << a2.a1.a0.a2 << ", ((" << a2.a1.a0.a3.a0.a0 << "), " << a2.a1.a0.a3.a1
+      << "), " << a2.a1.a0.a4 << ", ((" << a2.a1.a0.a5.a0.a0 << "), ("
+      << a2.a1.a0.a5.a1.a0 << ")), " << a2.a1.a0.a6 << "), ((" << a2.a1.a1.a0.a0
+      << ", " << a2.a1.a1.a0.a1 << "), (" << a2.a1.a1.a1.a0 << ")), "
+      << a2.a1.a2 << ", " << a2.a1.a3 << "), ((" << a2.a2.a0.a0 << ", (("
+      << a2.a2.a0.a1.a0.a0 << ", " << a2.a2.a0.a1.a0.a1 << "), ("
+      << a2.a2.a0.a1.a1.a0 << ")), " << a2.a2.a0.a2 << ", (("
+      << a2.a2.a0.a3.a0.a0 << "), " << a2.a2.a0.a3.a1 << "), " << a2.a2.a0.a4
+      << ", ((" << a2.a2.a0.a5.a0.a0 << "), (" << a2.a2.a0.a5.a1.a0 << ")), "
+      << a2.a2.a0.a6 << "), ((" << a2.a2.a1.a0.a0 << ", " << a2.a2.a1.a0.a1
+      << "), (" << a2.a2.a1.a1.a0 << ")), " << a2.a2.a2 << ", " << a2.a2.a3
+      << "), " << a2.a3 << "), (" << a3.a0 << ", ((" << a3.a1.a0.a0 << ", (("
+      << a3.a1.a0.a1.a0.a0 << ", " << a3.a1.a0.a1.a0.a1 << "), ("
+      << a3.a1.a0.a1.a1.a0 << ")), " << a3.a1.a0.a2 << ", (("
+      << a3.a1.a0.a3.a0.a0 << "), " << a3.a1.a0.a3.a1 << "), " << a3.a1.a0.a4
+      << ", ((" << a3.a1.a0.a5.a0.a0 << "), (" << a3.a1.a0.a5.a1.a0 << ")), "
+      << a3.a1.a0.a6 << "), ((" << a3.a1.a1.a0.a0 << ", " << a3.a1.a1.a0.a1
+      << "), (" << a3.a1.a1.a1.a0 << ")), " << a3.a1.a2 << ", " << a3.a1.a3
+      << "), ((" << a3.a2.a0.a0 << ", ((" << a3.a2.a0.a1.a0.a0 << ", "
+      << a3.a2.a0.a1.a0.a1 << "), (" << a3.a2.a0.a1.a1.a0 << ")), "
+      << a3.a2.a0.a2 << ", ((" << a3.a2.a0.a3.a0.a0 << "), " << a3.a2.a0.a3.a1
+      << "), " << a3.a2.a0.a4 << ", ((" << a3.a2.a0.a5.a0.a0 << "), ("
+      << a3.a2.a0.a5.a1.a0 << ")), " << a3.a2.a0.a6 << "), ((" << a3.a2.a1.a0.a0
+      << ", " << a3.a2.a1.a0.a1 << "), (" << a3.a2.a1.a1.a0 << ")), "
+      << a3.a2.a2 << ", " << a3.a2.a3 << "), " << a3.a3 << "))"
+      << ")\n";
+
+  double result = f(a0, a1, a2, a3);
+
+  std::cout << "result = " << result << "\n";
+
+  CHECK_APPROX(1572.0, result);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0 = 42;
+
+  result = f(a0, a1, a2, a3);
+
+  CHECK_APPROX(0.0, result);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0 = 84;
+
+  result = f(a0, a1, a2, a3);
+
+  CHECK_APPROX(0.0, result);
+
+  return 0;
+}
+
+// Used for testing structs by value.
 // Smallest struct with data.
 DART_EXPORT intptr_t TestReturnStruct1ByteInt(
     // NOLINTNEXTLINE(whitespace/parens)
@@ -9387,4 +11302,780 @@
   return 0;
 }
 
+// Used for testing structs by value.
+// Simple nested struct.
+DART_EXPORT intptr_t TestReturnStruct8BytesNestedInt(
+    // NOLINTNEXTLINE(whitespace/parens)
+    Struct8BytesNestedInt (*f)(Struct4BytesHomogeneousInt16 a0,
+                               Struct4BytesHomogeneousInt16 a1)) {
+  Struct4BytesHomogeneousInt16 a0;
+  Struct4BytesHomogeneousInt16 a1;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a1.a0 = -3;
+  a1.a1 = 4;
+
+  std::cout << "Calling TestReturnStruct8BytesNestedInt("
+            << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", "
+            << a1.a1 << "))"
+            << ")\n";
+
+  Struct8BytesNestedInt result = f(a0, a1);
+
+  std::cout << "result = "
+            << "((" << result.a0.a0 << ", " << result.a0.a1 << "), ("
+            << result.a1.a0 << ", " << result.a1.a1 << "))"
+            << "\n";
+
+  CHECK_EQ(a0.a0, result.a0.a0);
+  CHECK_EQ(a0.a1, result.a0.a1);
+  CHECK_EQ(a1.a0, result.a1.a0);
+  CHECK_EQ(a1.a1, result.a1.a1);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_EQ(0, result.a1.a0);
+  CHECK_EQ(0, result.a1.a1);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_EQ(0, result.a1.a0);
+  CHECK_EQ(0, result.a1.a1);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Simple nested struct with floats.
+DART_EXPORT intptr_t TestReturnStruct8BytesNestedFloat(
+    // NOLINTNEXTLINE(whitespace/parens)
+    Struct8BytesNestedFloat (*f)(Struct4BytesFloat a0, Struct4BytesFloat a1)) {
+  Struct4BytesFloat a0;
+  Struct4BytesFloat a1;
+
+  a0.a0 = -1.0;
+  a1.a0 = 2.0;
+
+  std::cout << "Calling TestReturnStruct8BytesNestedFloat("
+            << "((" << a0.a0 << "), (" << a1.a0 << "))"
+            << ")\n";
+
+  Struct8BytesNestedFloat result = f(a0, a1);
+
+  std::cout << "result = "
+            << "((" << result.a0.a0 << "), (" << result.a1.a0 << "))"
+            << "\n";
+
+  CHECK_APPROX(a0.a0, result.a0.a0);
+  CHECK_APPROX(a1.a0, result.a1.a0);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_APPROX(0.0, result.a0.a0);
+  CHECK_APPROX(0.0, result.a1.a0);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_APPROX(0.0, result.a0.a0);
+  CHECK_APPROX(0.0, result.a1.a0);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// The nesting is irregular, testing homogenous float rules on arm and arm64,
+// and the fpu register usage on x64.
+DART_EXPORT intptr_t TestReturnStruct8BytesNestedFloat2(
+    // NOLINTNEXTLINE(whitespace/parens)
+    Struct8BytesNestedFloat2 (*f)(Struct4BytesFloat a0, float a1)) {
+  Struct4BytesFloat a0;
+  float a1;
+
+  a0.a0 = -1.0;
+  a1 = 2.0;
+
+  std::cout << "Calling TestReturnStruct8BytesNestedFloat2("
+            << "((" << a0.a0 << "), " << a1 << ")"
+            << ")\n";
+
+  Struct8BytesNestedFloat2 result = f(a0, a1);
+
+  std::cout << "result = "
+            << "((" << result.a0.a0 << "), " << result.a1 << ")"
+            << "\n";
+
+  CHECK_APPROX(a0.a0, result.a0.a0);
+  CHECK_APPROX(a1, result.a1);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_APPROX(0.0, result.a0.a0);
+  CHECK_APPROX(0.0, result.a1);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_APPROX(0.0, result.a0.a0);
+  CHECK_APPROX(0.0, result.a1);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Simple nested struct with mixed members.
+DART_EXPORT intptr_t TestReturnStruct8BytesNestedMixed(
+    // NOLINTNEXTLINE(whitespace/parens)
+    Struct8BytesNestedMixed (*f)(Struct4BytesHomogeneousInt16 a0,
+                                 Struct4BytesFloat a1)) {
+  Struct4BytesHomogeneousInt16 a0;
+  Struct4BytesFloat a1;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a1.a0 = -3.0;
+
+  std::cout << "Calling TestReturnStruct8BytesNestedMixed("
+            << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << "))"
+            << ")\n";
+
+  Struct8BytesNestedMixed result = f(a0, a1);
+
+  std::cout << "result = "
+            << "((" << result.a0.a0 << ", " << result.a0.a1 << "), ("
+            << result.a1.a0 << "))"
+            << "\n";
+
+  CHECK_EQ(a0.a0, result.a0.a0);
+  CHECK_EQ(a0.a1, result.a0.a1);
+  CHECK_APPROX(a1.a0, result.a1.a0);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_APPROX(0.0, result.a1.a0);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_APPROX(0.0, result.a1.a0);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Deeper nested struct to test recursive member access.
+DART_EXPORT intptr_t TestReturnStruct16BytesNestedInt(
+    // NOLINTNEXTLINE(whitespace/parens)
+    Struct16BytesNestedInt (*f)(Struct8BytesNestedInt a0,
+                                Struct8BytesNestedInt a1)) {
+  Struct8BytesNestedInt a0;
+  Struct8BytesNestedInt a1;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3;
+  a0.a1.a1 = 4;
+  a1.a0.a0 = -5;
+  a1.a0.a1 = 6;
+  a1.a1.a0 = -7;
+  a1.a1.a1 = 8;
+
+  std::cout << "Calling TestReturnStruct16BytesNestedInt("
+            << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0
+            << ", " << a0.a1.a1 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1
+            << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ")))"
+            << ")\n";
+
+  Struct16BytesNestedInt result = f(a0, a1);
+
+  std::cout << "result = "
+            << "(((" << result.a0.a0.a0 << ", " << result.a0.a0.a1 << "), ("
+            << result.a0.a1.a0 << ", " << result.a0.a1.a1 << ")), (("
+            << result.a1.a0.a0 << ", " << result.a1.a0.a1 << "), ("
+            << result.a1.a1.a0 << ", " << result.a1.a1.a1 << ")))"
+            << "\n";
+
+  CHECK_EQ(a0.a0.a0, result.a0.a0.a0);
+  CHECK_EQ(a0.a0.a1, result.a0.a0.a1);
+  CHECK_EQ(a0.a1.a0, result.a0.a1.a0);
+  CHECK_EQ(a0.a1.a1, result.a0.a1.a1);
+  CHECK_EQ(a1.a0.a0, result.a1.a0.a0);
+  CHECK_EQ(a1.a0.a1, result.a1.a0.a1);
+  CHECK_EQ(a1.a1.a0, result.a1.a1.a0);
+  CHECK_EQ(a1.a1.a1, result.a1.a1.a1);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0.a0);
+  CHECK_EQ(0, result.a0.a0.a1);
+  CHECK_EQ(0, result.a0.a1.a0);
+  CHECK_EQ(0, result.a0.a1.a1);
+  CHECK_EQ(0, result.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a0.a1);
+  CHECK_EQ(0, result.a1.a1.a0);
+  CHECK_EQ(0, result.a1.a1.a1);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0.a0);
+  CHECK_EQ(0, result.a0.a0.a1);
+  CHECK_EQ(0, result.a0.a1.a0);
+  CHECK_EQ(0, result.a0.a1.a1);
+  CHECK_EQ(0, result.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a0.a1);
+  CHECK_EQ(0, result.a1.a1.a0);
+  CHECK_EQ(0, result.a1.a1.a1);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Even deeper nested struct to test recursive member access.
+DART_EXPORT intptr_t TestReturnStruct32BytesNestedInt(
+    // NOLINTNEXTLINE(whitespace/parens)
+    Struct32BytesNestedInt (*f)(Struct16BytesNestedInt a0,
+                                Struct16BytesNestedInt a1)) {
+  Struct16BytesNestedInt a0;
+  Struct16BytesNestedInt a1;
+
+  a0.a0.a0.a0 = -1;
+  a0.a0.a0.a1 = 2;
+  a0.a0.a1.a0 = -3;
+  a0.a0.a1.a1 = 4;
+  a0.a1.a0.a0 = -5;
+  a0.a1.a0.a1 = 6;
+  a0.a1.a1.a0 = -7;
+  a0.a1.a1.a1 = 8;
+  a1.a0.a0.a0 = -9;
+  a1.a0.a0.a1 = 10;
+  a1.a0.a1.a0 = -11;
+  a1.a0.a1.a1 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15;
+  a1.a1.a1.a1 = 16;
+
+  std::cout << "Calling TestReturnStruct32BytesNestedInt("
+            << "((((" << a0.a0.a0.a0 << ", " << a0.a0.a0.a1 << "), ("
+            << a0.a0.a1.a0 << ", " << a0.a0.a1.a1 << ")), ((" << a0.a1.a0.a0
+            << ", " << a0.a1.a0.a1 << "), (" << a0.a1.a1.a0 << ", "
+            << a0.a1.a1.a1 << "))), (((" << a1.a0.a0.a0 << ", " << a1.a0.a0.a1
+            << "), (" << a1.a0.a1.a0 << ", " << a1.a0.a1.a1 << ")), (("
+            << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0
+            << ", " << a1.a1.a1.a1 << "))))"
+            << ")\n";
+
+  Struct32BytesNestedInt result = f(a0, a1);
+
+  std::cout << "result = "
+            << "((((" << result.a0.a0.a0.a0 << ", " << result.a0.a0.a0.a1
+            << "), (" << result.a0.a0.a1.a0 << ", " << result.a0.a0.a1.a1
+            << ")), ((" << result.a0.a1.a0.a0 << ", " << result.a0.a1.a0.a1
+            << "), (" << result.a0.a1.a1.a0 << ", " << result.a0.a1.a1.a1
+            << "))), (((" << result.a1.a0.a0.a0 << ", " << result.a1.a0.a0.a1
+            << "), (" << result.a1.a0.a1.a0 << ", " << result.a1.a0.a1.a1
+            << ")), ((" << result.a1.a1.a0.a0 << ", " << result.a1.a1.a0.a1
+            << "), (" << result.a1.a1.a1.a0 << ", " << result.a1.a1.a1.a1
+            << "))))"
+            << "\n";
+
+  CHECK_EQ(a0.a0.a0.a0, result.a0.a0.a0.a0);
+  CHECK_EQ(a0.a0.a0.a1, result.a0.a0.a0.a1);
+  CHECK_EQ(a0.a0.a1.a0, result.a0.a0.a1.a0);
+  CHECK_EQ(a0.a0.a1.a1, result.a0.a0.a1.a1);
+  CHECK_EQ(a0.a1.a0.a0, result.a0.a1.a0.a0);
+  CHECK_EQ(a0.a1.a0.a1, result.a0.a1.a0.a1);
+  CHECK_EQ(a0.a1.a1.a0, result.a0.a1.a1.a0);
+  CHECK_EQ(a0.a1.a1.a1, result.a0.a1.a1.a1);
+  CHECK_EQ(a1.a0.a0.a0, result.a1.a0.a0.a0);
+  CHECK_EQ(a1.a0.a0.a1, result.a1.a0.a0.a1);
+  CHECK_EQ(a1.a0.a1.a0, result.a1.a0.a1.a0);
+  CHECK_EQ(a1.a0.a1.a1, result.a1.a0.a1.a1);
+  CHECK_EQ(a1.a1.a0.a0, result.a1.a1.a0.a0);
+  CHECK_EQ(a1.a1.a0.a1, result.a1.a1.a0.a1);
+  CHECK_EQ(a1.a1.a1.a0, result.a1.a1.a1.a0);
+  CHECK_EQ(a1.a1.a1.a1, result.a1.a1.a1.a1);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0.a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0.a0.a0);
+  CHECK_EQ(0, result.a0.a0.a0.a1);
+  CHECK_EQ(0, result.a0.a0.a1.a0);
+  CHECK_EQ(0, result.a0.a0.a1.a1);
+  CHECK_EQ(0, result.a0.a1.a0.a0);
+  CHECK_EQ(0, result.a0.a1.a0.a1);
+  CHECK_EQ(0, result.a0.a1.a1.a0);
+  CHECK_EQ(0, result.a0.a1.a1.a1);
+  CHECK_EQ(0, result.a1.a0.a0.a0);
+  CHECK_EQ(0, result.a1.a0.a0.a1);
+  CHECK_EQ(0, result.a1.a0.a1.a0);
+  CHECK_EQ(0, result.a1.a0.a1.a1);
+  CHECK_EQ(0, result.a1.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a1.a0.a1);
+  CHECK_EQ(0, result.a1.a1.a1.a0);
+  CHECK_EQ(0, result.a1.a1.a1.a1);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0.a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0.a0.a0);
+  CHECK_EQ(0, result.a0.a0.a0.a1);
+  CHECK_EQ(0, result.a0.a0.a1.a0);
+  CHECK_EQ(0, result.a0.a0.a1.a1);
+  CHECK_EQ(0, result.a0.a1.a0.a0);
+  CHECK_EQ(0, result.a0.a1.a0.a1);
+  CHECK_EQ(0, result.a0.a1.a1.a0);
+  CHECK_EQ(0, result.a0.a1.a1.a1);
+  CHECK_EQ(0, result.a1.a0.a0.a0);
+  CHECK_EQ(0, result.a1.a0.a0.a1);
+  CHECK_EQ(0, result.a1.a0.a1.a0);
+  CHECK_EQ(0, result.a1.a0.a1.a1);
+  CHECK_EQ(0, result.a1.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a1.a0.a1);
+  CHECK_EQ(0, result.a1.a1.a1.a0);
+  CHECK_EQ(0, result.a1.a1.a1.a1);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 16 byte int.
+DART_EXPORT intptr_t TestReturnStructNestedIntStructAlignmentInt16(
+    // NOLINTNEXTLINE(whitespace/parens)
+    StructNestedIntStructAlignmentInt16 (*f)(StructAlignmentInt16 a0,
+                                             StructAlignmentInt16 a1)) {
+  StructAlignmentInt16 a0;
+  StructAlignmentInt16 a1;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  std::cout << "Calling TestReturnStructNestedIntStructAlignmentInt16("
+            << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+            << static_cast<int>(a0.a2) << "), (" << static_cast<int>(a1.a0)
+            << ", " << a1.a1 << ", " << static_cast<int>(a1.a2) << "))"
+            << ")\n";
+
+  StructNestedIntStructAlignmentInt16 result = f(a0, a1);
+
+  std::cout << "result = "
+            << "((" << static_cast<int>(result.a0.a0) << ", " << result.a0.a1
+            << ", " << static_cast<int>(result.a0.a2) << "), ("
+            << static_cast<int>(result.a1.a0) << ", " << result.a1.a1 << ", "
+            << static_cast<int>(result.a1.a2) << "))"
+            << "\n";
+
+  CHECK_EQ(a0.a0, result.a0.a0);
+  CHECK_EQ(a0.a1, result.a0.a1);
+  CHECK_EQ(a0.a2, result.a0.a2);
+  CHECK_EQ(a1.a0, result.a1.a0);
+  CHECK_EQ(a1.a1, result.a1.a1);
+  CHECK_EQ(a1.a2, result.a1.a2);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_EQ(0, result.a0.a2);
+  CHECK_EQ(0, result.a1.a0);
+  CHECK_EQ(0, result.a1.a1);
+  CHECK_EQ(0, result.a1.a2);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_EQ(0, result.a0.a2);
+  CHECK_EQ(0, result.a1.a0);
+  CHECK_EQ(0, result.a1.a1);
+  CHECK_EQ(0, result.a1.a2);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 32 byte int.
+DART_EXPORT intptr_t TestReturnStructNestedIntStructAlignmentInt32(
+    // NOLINTNEXTLINE(whitespace/parens)
+    StructNestedIntStructAlignmentInt32 (*f)(StructAlignmentInt32 a0,
+                                             StructAlignmentInt32 a1)) {
+  StructAlignmentInt32 a0;
+  StructAlignmentInt32 a1;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  std::cout << "Calling TestReturnStructNestedIntStructAlignmentInt32("
+            << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+            << static_cast<int>(a0.a2) << "), (" << static_cast<int>(a1.a0)
+            << ", " << a1.a1 << ", " << static_cast<int>(a1.a2) << "))"
+            << ")\n";
+
+  StructNestedIntStructAlignmentInt32 result = f(a0, a1);
+
+  std::cout << "result = "
+            << "((" << static_cast<int>(result.a0.a0) << ", " << result.a0.a1
+            << ", " << static_cast<int>(result.a0.a2) << "), ("
+            << static_cast<int>(result.a1.a0) << ", " << result.a1.a1 << ", "
+            << static_cast<int>(result.a1.a2) << "))"
+            << "\n";
+
+  CHECK_EQ(a0.a0, result.a0.a0);
+  CHECK_EQ(a0.a1, result.a0.a1);
+  CHECK_EQ(a0.a2, result.a0.a2);
+  CHECK_EQ(a1.a0, result.a1.a0);
+  CHECK_EQ(a1.a1, result.a1.a1);
+  CHECK_EQ(a1.a2, result.a1.a2);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_EQ(0, result.a0.a2);
+  CHECK_EQ(0, result.a1.a0);
+  CHECK_EQ(0, result.a1.a1);
+  CHECK_EQ(0, result.a1.a2);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_EQ(0, result.a0.a2);
+  CHECK_EQ(0, result.a1.a0);
+  CHECK_EQ(0, result.a1.a1);
+  CHECK_EQ(0, result.a1.a2);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Test alignment and padding of nested struct with 64 byte int.
+DART_EXPORT intptr_t TestReturnStructNestedIntStructAlignmentInt64(
+    // NOLINTNEXTLINE(whitespace/parens)
+    StructNestedIntStructAlignmentInt64 (*f)(StructAlignmentInt64 a0,
+                                             StructAlignmentInt64 a1)) {
+  StructAlignmentInt64 a0;
+  StructAlignmentInt64 a1;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  std::cout << "Calling TestReturnStructNestedIntStructAlignmentInt64("
+            << "((" << static_cast<int>(a0.a0) << ", " << a0.a1 << ", "
+            << static_cast<int>(a0.a2) << "), (" << static_cast<int>(a1.a0)
+            << ", " << a1.a1 << ", " << static_cast<int>(a1.a2) << "))"
+            << ")\n";
+
+  StructNestedIntStructAlignmentInt64 result = f(a0, a1);
+
+  std::cout << "result = "
+            << "((" << static_cast<int>(result.a0.a0) << ", " << result.a0.a1
+            << ", " << static_cast<int>(result.a0.a2) << "), ("
+            << static_cast<int>(result.a1.a0) << ", " << result.a1.a1 << ", "
+            << static_cast<int>(result.a1.a2) << "))"
+            << "\n";
+
+  CHECK_EQ(a0.a0, result.a0.a0);
+  CHECK_EQ(a0.a1, result.a0.a1);
+  CHECK_EQ(a0.a2, result.a0.a2);
+  CHECK_EQ(a1.a0, result.a1.a0);
+  CHECK_EQ(a1.a1, result.a1.a1);
+  CHECK_EQ(a1.a2, result.a1.a2);
+
+  // Pass argument that will make the Dart callback throw.
+  a0.a0 = 42;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_EQ(0, result.a0.a2);
+  CHECK_EQ(0, result.a1.a0);
+  CHECK_EQ(0, result.a1.a1);
+  CHECK_EQ(0, result.a1.a2);
+
+  // Pass argument that will make the Dart callback return null.
+  a0.a0 = 84;
+
+  result = f(a0, a1);
+
+  CHECK_EQ(0, result.a0.a0);
+  CHECK_EQ(0, result.a0.a1);
+  CHECK_EQ(0, result.a0.a2);
+  CHECK_EQ(0, result.a1.a0);
+  CHECK_EQ(0, result.a1.a1);
+  CHECK_EQ(0, result.a1.a2);
+
+  return 0;
+}
+
+// Used for testing structs by value.
+// Return big irregular struct as smoke test.
+DART_EXPORT intptr_t TestReturnStructNestedIrregularEvenBigger(
+    // NOLINTNEXTLINE(whitespace/parens)
+    StructNestedIrregularEvenBigger (*f)(uint64_t a0,
+                                         StructNestedIrregularBigger a1,
+                                         StructNestedIrregularBigger a2,
+                                         double a3)) {
+  uint64_t a0;
+  StructNestedIrregularBigger a1;
+  StructNestedIrregularBigger a2;
+  double a3;
+
+  a0 = 1;
+  a1.a0.a0 = 2;
+  a1.a0.a1.a0.a0 = -3;
+  a1.a0.a1.a0.a1 = 4;
+  a1.a0.a1.a1.a0 = -5.0;
+  a1.a0.a2 = 6;
+  a1.a0.a3.a0.a0 = -7.0;
+  a1.a0.a3.a1 = 8.0;
+  a1.a0.a4 = 9;
+  a1.a0.a5.a0.a0 = 10.0;
+  a1.a0.a5.a1.a0 = -11.0;
+  a1.a0.a6 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15.0;
+  a1.a2 = 16.0;
+  a1.a3 = -17.0;
+  a2.a0.a0 = 18;
+  a2.a0.a1.a0.a0 = -19;
+  a2.a0.a1.a0.a1 = 20;
+  a2.a0.a1.a1.a0 = -21.0;
+  a2.a0.a2 = 22;
+  a2.a0.a3.a0.a0 = -23.0;
+  a2.a0.a3.a1 = 24.0;
+  a2.a0.a4 = 25;
+  a2.a0.a5.a0.a0 = 26.0;
+  a2.a0.a5.a1.a0 = -27.0;
+  a2.a0.a6 = 28;
+  a2.a1.a0.a0 = -29;
+  a2.a1.a0.a1 = 30;
+  a2.a1.a1.a0 = -31.0;
+  a2.a2 = 32.0;
+  a2.a3 = -33.0;
+  a3 = 34.0;
+
+  std::cout << "Calling TestReturnStructNestedIrregularEvenBigger("
+            << "(" << a0 << ", ((" << a1.a0.a0 << ", ((" << a1.a0.a1.a0.a0
+            << ", " << a1.a0.a1.a0.a1 << "), (" << a1.a0.a1.a1.a0 << ")), "
+            << a1.a0.a2 << ", ((" << a1.a0.a3.a0.a0 << "), " << a1.a0.a3.a1
+            << "), " << a1.a0.a4 << ", ((" << a1.a0.a5.a0.a0 << "), ("
+            << a1.a0.a5.a1.a0 << ")), " << a1.a0.a6 << "), ((" << a1.a1.a0.a0
+            << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0 << ")), " << a1.a2
+            << ", " << a1.a3 << "), ((" << a2.a0.a0 << ", ((" << a2.a0.a1.a0.a0
+            << ", " << a2.a0.a1.a0.a1 << "), (" << a2.a0.a1.a1.a0 << ")), "
+            << a2.a0.a2 << ", ((" << a2.a0.a3.a0.a0 << "), " << a2.a0.a3.a1
+            << "), " << a2.a0.a4 << ", ((" << a2.a0.a5.a0.a0 << "), ("
+            << a2.a0.a5.a1.a0 << ")), " << a2.a0.a6 << "), ((" << a2.a1.a0.a0
+            << ", " << a2.a1.a0.a1 << "), (" << a2.a1.a1.a0 << ")), " << a2.a2
+            << ", " << a2.a3 << "), " << a3 << ")"
+            << ")\n";
+
+  StructNestedIrregularEvenBigger result = f(a0, a1, a2, a3);
+
+  std::cout << "result = "
+            << "(" << result.a0 << ", ((" << result.a1.a0.a0 << ", (("
+            << result.a1.a0.a1.a0.a0 << ", " << result.a1.a0.a1.a0.a1 << "), ("
+            << result.a1.a0.a1.a1.a0 << ")), " << result.a1.a0.a2 << ", (("
+            << result.a1.a0.a3.a0.a0 << "), " << result.a1.a0.a3.a1 << "), "
+            << result.a1.a0.a4 << ", ((" << result.a1.a0.a5.a0.a0 << "), ("
+            << result.a1.a0.a5.a1.a0 << ")), " << result.a1.a0.a6 << "), (("
+            << result.a1.a1.a0.a0 << ", " << result.a1.a1.a0.a1 << "), ("
+            << result.a1.a1.a1.a0 << ")), " << result.a1.a2 << ", "
+            << result.a1.a3 << "), ((" << result.a2.a0.a0 << ", (("
+            << result.a2.a0.a1.a0.a0 << ", " << result.a2.a0.a1.a0.a1 << "), ("
+            << result.a2.a0.a1.a1.a0 << ")), " << result.a2.a0.a2 << ", (("
+            << result.a2.a0.a3.a0.a0 << "), " << result.a2.a0.a3.a1 << "), "
+            << result.a2.a0.a4 << ", ((" << result.a2.a0.a5.a0.a0 << "), ("
+            << result.a2.a0.a5.a1.a0 << ")), " << result.a2.a0.a6 << "), (("
+            << result.a2.a1.a0.a0 << ", " << result.a2.a1.a0.a1 << "), ("
+            << result.a2.a1.a1.a0 << ")), " << result.a2.a2 << ", "
+            << result.a2.a3 << "), " << result.a3 << ")"
+            << "\n";
+
+  CHECK_EQ(a0, result.a0);
+  CHECK_EQ(a1.a0.a0, result.a1.a0.a0);
+  CHECK_EQ(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0);
+  CHECK_EQ(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1);
+  CHECK_APPROX(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0);
+  CHECK_EQ(a1.a0.a2, result.a1.a0.a2);
+  CHECK_APPROX(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0);
+  CHECK_APPROX(a1.a0.a3.a1, result.a1.a0.a3.a1);
+  CHECK_EQ(a1.a0.a4, result.a1.a0.a4);
+  CHECK_APPROX(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0);
+  CHECK_APPROX(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0);
+  CHECK_EQ(a1.a0.a6, result.a1.a0.a6);
+  CHECK_EQ(a1.a1.a0.a0, result.a1.a1.a0.a0);
+  CHECK_EQ(a1.a1.a0.a1, result.a1.a1.a0.a1);
+  CHECK_APPROX(a1.a1.a1.a0, result.a1.a1.a1.a0);
+  CHECK_APPROX(a1.a2, result.a1.a2);
+  CHECK_APPROX(a1.a3, result.a1.a3);
+  CHECK_EQ(a2.a0.a0, result.a2.a0.a0);
+  CHECK_EQ(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0);
+  CHECK_EQ(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1);
+  CHECK_APPROX(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0);
+  CHECK_EQ(a2.a0.a2, result.a2.a0.a2);
+  CHECK_APPROX(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0);
+  CHECK_APPROX(a2.a0.a3.a1, result.a2.a0.a3.a1);
+  CHECK_EQ(a2.a0.a4, result.a2.a0.a4);
+  CHECK_APPROX(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0);
+  CHECK_APPROX(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0);
+  CHECK_EQ(a2.a0.a6, result.a2.a0.a6);
+  CHECK_EQ(a2.a1.a0.a0, result.a2.a1.a0.a0);
+  CHECK_EQ(a2.a1.a0.a1, result.a2.a1.a0.a1);
+  CHECK_APPROX(a2.a1.a1.a0, result.a2.a1.a1.a0);
+  CHECK_APPROX(a2.a2, result.a2.a2);
+  CHECK_APPROX(a2.a3, result.a2.a3);
+  CHECK_APPROX(a3, result.a3);
+
+  // Pass argument that will make the Dart callback throw.
+  a0 = 42;
+
+  result = f(a0, a1, a2, a3);
+
+  CHECK_EQ(0, result.a0);
+  CHECK_EQ(0, result.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a0.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a0.a1.a0.a1);
+  CHECK_APPROX(0.0, result.a1.a0.a1.a1.a0);
+  CHECK_EQ(0, result.a1.a0.a2);
+  CHECK_APPROX(0.0, result.a1.a0.a3.a0.a0);
+  CHECK_APPROX(0.0, result.a1.a0.a3.a1);
+  CHECK_EQ(0, result.a1.a0.a4);
+  CHECK_APPROX(0.0, result.a1.a0.a5.a0.a0);
+  CHECK_APPROX(0.0, result.a1.a0.a5.a1.a0);
+  CHECK_EQ(0, result.a1.a0.a6);
+  CHECK_EQ(0, result.a1.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a1.a0.a1);
+  CHECK_APPROX(0.0, result.a1.a1.a1.a0);
+  CHECK_APPROX(0.0, result.a1.a2);
+  CHECK_APPROX(0.0, result.a1.a3);
+  CHECK_EQ(0, result.a2.a0.a0);
+  CHECK_EQ(0, result.a2.a0.a1.a0.a0);
+  CHECK_EQ(0, result.a2.a0.a1.a0.a1);
+  CHECK_APPROX(0.0, result.a2.a0.a1.a1.a0);
+  CHECK_EQ(0, result.a2.a0.a2);
+  CHECK_APPROX(0.0, result.a2.a0.a3.a0.a0);
+  CHECK_APPROX(0.0, result.a2.a0.a3.a1);
+  CHECK_EQ(0, result.a2.a0.a4);
+  CHECK_APPROX(0.0, result.a2.a0.a5.a0.a0);
+  CHECK_APPROX(0.0, result.a2.a0.a5.a1.a0);
+  CHECK_EQ(0, result.a2.a0.a6);
+  CHECK_EQ(0, result.a2.a1.a0.a0);
+  CHECK_EQ(0, result.a2.a1.a0.a1);
+  CHECK_APPROX(0.0, result.a2.a1.a1.a0);
+  CHECK_APPROX(0.0, result.a2.a2);
+  CHECK_APPROX(0.0, result.a2.a3);
+  CHECK_APPROX(0.0, result.a3);
+
+  // Pass argument that will make the Dart callback return null.
+  a0 = 84;
+
+  result = f(a0, a1, a2, a3);
+
+  CHECK_EQ(0, result.a0);
+  CHECK_EQ(0, result.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a0.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a0.a1.a0.a1);
+  CHECK_APPROX(0.0, result.a1.a0.a1.a1.a0);
+  CHECK_EQ(0, result.a1.a0.a2);
+  CHECK_APPROX(0.0, result.a1.a0.a3.a0.a0);
+  CHECK_APPROX(0.0, result.a1.a0.a3.a1);
+  CHECK_EQ(0, result.a1.a0.a4);
+  CHECK_APPROX(0.0, result.a1.a0.a5.a0.a0);
+  CHECK_APPROX(0.0, result.a1.a0.a5.a1.a0);
+  CHECK_EQ(0, result.a1.a0.a6);
+  CHECK_EQ(0, result.a1.a1.a0.a0);
+  CHECK_EQ(0, result.a1.a1.a0.a1);
+  CHECK_APPROX(0.0, result.a1.a1.a1.a0);
+  CHECK_APPROX(0.0, result.a1.a2);
+  CHECK_APPROX(0.0, result.a1.a3);
+  CHECK_EQ(0, result.a2.a0.a0);
+  CHECK_EQ(0, result.a2.a0.a1.a0.a0);
+  CHECK_EQ(0, result.a2.a0.a1.a0.a1);
+  CHECK_APPROX(0.0, result.a2.a0.a1.a1.a0);
+  CHECK_EQ(0, result.a2.a0.a2);
+  CHECK_APPROX(0.0, result.a2.a0.a3.a0.a0);
+  CHECK_APPROX(0.0, result.a2.a0.a3.a1);
+  CHECK_EQ(0, result.a2.a0.a4);
+  CHECK_APPROX(0.0, result.a2.a0.a5.a0.a0);
+  CHECK_APPROX(0.0, result.a2.a0.a5.a1.a0);
+  CHECK_EQ(0, result.a2.a0.a6);
+  CHECK_EQ(0, result.a2.a1.a0.a0);
+  CHECK_EQ(0, result.a2.a1.a0.a1);
+  CHECK_APPROX(0.0, result.a2.a1.a1.a0);
+  CHECK_APPROX(0.0, result.a2.a2);
+  CHECK_APPROX(0.0, result.a2.a3);
+  CHECK_APPROX(0.0, result.a3);
+
+  return 0;
+}
+
 }  // namespace dart
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index cb53b76..3da8be8 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -759,10 +759,6 @@
   }
 }
 
-static Dart_QualifiedFunctionName no_entry_points[] = {
-    {NULL, NULL, NULL}  // Must be terminated with NULL entries.
-};
-
 static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) {
   uint8_t* kernel_buffer = NULL;
   intptr_t kernel_buffer_size = 0;
@@ -775,7 +771,6 @@
                             kernel_buffer, kernel_buffer_size);
   if (IsSnapshottingForPrecompilation()) {
     isolate_flags.obfuscate = obfuscate;
-    isolate_flags.entry_points = no_entry_points;
   }
 
   auto isolate_group_data = std::unique_ptr<IsolateGroupData>(
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 9f62982..e855baf 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -198,7 +198,7 @@
     uint8_t* kernel_buffer = NULL;
     intptr_t kernel_buffer_size = -1;
     dfe.CompileAndReadScript(url_string, &kernel_buffer, &kernel_buffer_size,
-                             &error, &exit_code, NULL);
+                             &error, &exit_code, NULL, false);
     if (exit_code == 0) {
       return Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
     } else if (exit_code == kCompilationErrorExitCode) {
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 7299ade..cddacb8 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -298,9 +298,14 @@
     }
     uint8_t* application_kernel_buffer = NULL;
     intptr_t application_kernel_buffer_size = 0;
+    // Only pass snapshot = true when generating an AppJIT snapshot to avoid
+    // duplicate null-safety info messages from the frontend when generating
+    // a kernel snapshot (this flag is instead set in
+    // Snapshot::GenerateKernel()).
+    const bool snapshot = Options::gen_snapshot_kind() == kAppJIT;
     dfe.CompileAndReadScript(script_uri, &application_kernel_buffer,
                              &application_kernel_buffer_size, error, exit_code,
-                             resolved_packages_config);
+                             resolved_packages_config, snapshot);
     if (application_kernel_buffer == NULL) {
       Dart_ExitScope();
       Dart_ShutdownIsolate();
@@ -584,40 +589,81 @@
   int64_t start = Dart_TimelineGetMicros();
 
   auto dartdev_path = DartDevIsolate::TryResolveDartDevSnapshotPath();
-  if (dartdev_path == nullptr) {
-    *error = Utils::StrDup("Unable to find DartDev snapshot");
-    return nullptr;
-  }
 
+  Dart_Isolate isolate = nullptr;
   const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
   const uint8_t* isolate_snapshot_instructions =
       core_isolate_snapshot_instructions;
+  IsolateGroupData* isolate_group_data = nullptr;
+  IsolateData* isolate_data = nullptr;
 
-  auto isolate_group_data =
-      new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config, nullptr,
-                           /*isolate_run_app_snapshot*/ false);
-  uint8_t* application_kernel_buffer = NULL;
-  intptr_t application_kernel_buffer_size = 0;
-  dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
-                 &application_kernel_buffer_size);
-  isolate_group_data->SetKernelBufferNewlyOwned(application_kernel_buffer,
-                                                application_kernel_buffer_size);
+  if (error != nullptr) {
+    *error = nullptr;
+  }
+  AppSnapshot* app_snapshot = nullptr;
+  bool isolate_run_app_snapshot = true;
+  if (dartdev_path.get() != nullptr &&
+      (app_snapshot = Snapshot::TryReadAppSnapshot(dartdev_path.get())) !=
+          nullptr) {
+    const uint8_t* isolate_snapshot_data = NULL;
+    const uint8_t* isolate_snapshot_instructions = NULL;
+    const uint8_t* ignore_vm_snapshot_data;
+    const uint8_t* ignore_vm_snapshot_instructions;
+    app_snapshot->SetBuffers(
+        &ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
+        &isolate_snapshot_data, &isolate_snapshot_instructions);
+    isolate_group_data =
+        new IsolateGroupData(dartdev_path.get(), packages_config, app_snapshot,
+                             isolate_run_app_snapshot);
+    isolate_data = new IsolateData(isolate_group_data);
+    isolate = Dart_CreateIsolateGroup(
+        DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
+        isolate_snapshot_instructions, flags, isolate_group_data, isolate_data,
+        error);
+  }
 
-  auto isolate_data = new IsolateData(isolate_group_data);
-  Dart_Isolate isolate = nullptr;
-  isolate = Dart_CreateIsolateGroup(
-      DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
-      isolate_snapshot_instructions, flags, isolate_group_data, isolate_data,
-      error);
+  if (isolate == nullptr) {
+    isolate_run_app_snapshot = false;
+    dartdev_path = DartDevIsolate::TryResolveDartDevKernelPath();
+    // Clear error from app snapshot and retry from kernel.
+    if (error != nullptr && *error != nullptr) {
+      free(*error);
+      *error = nullptr;
+    }
+
+    if (app_snapshot != nullptr) {
+      delete app_snapshot;
+    }
+
+    if (dartdev_path.get() != nullptr) {
+      isolate_group_data =
+          new IsolateGroupData(DART_DEV_ISOLATE_NAME, packages_config, nullptr,
+                               isolate_run_app_snapshot);
+      uint8_t* application_kernel_buffer = NULL;
+      intptr_t application_kernel_buffer_size = 0;
+      dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
+                     &application_kernel_buffer_size);
+      isolate_group_data->SetKernelBufferNewlyOwned(
+          application_kernel_buffer, application_kernel_buffer_size);
+
+      isolate_data = new IsolateData(isolate_group_data);
+      isolate = Dart_CreateIsolateGroup(
+          DART_DEV_ISOLATE_NAME, DART_DEV_ISOLATE_NAME, isolate_snapshot_data,
+          isolate_snapshot_instructions, flags, isolate_group_data,
+          isolate_data, error);
+    }
+  }
 
   Dart_Isolate created_isolate = nullptr;
   if (isolate == nullptr) {
+    Syslog::PrintErr("Failed to start the Dart CLI isolate\n");
     delete isolate_data;
     delete isolate_group_data;
+    return nullptr;
   } else {
     created_isolate = IsolateSetupHelper(
         isolate, false, DART_DEV_ISOLATE_NAME, packages_config,
-        /*isolate_run_app_snapshot*/ false, flags, error, exit_code);
+        isolate_run_app_snapshot, flags, error, exit_code);
   }
   int64_t end = Dart_TimelineGetMicros();
   Dart_TimelineEvent("CreateAndSetupDartDevIsolate", start, end,
@@ -1237,6 +1283,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
   // Load vm_platform_strong.dill for dart:* source support.
   dfe.Init();
+  dfe.set_verbosity(Options::verbosity_level());
   if (script_name != nullptr) {
     uint8_t* application_kernel_buffer = NULL;
     intptr_t application_kernel_buffer_size = 0;
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index d019ce4..517029d 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -34,7 +34,13 @@
     NULL,
 };
 
+// These strings must match the enum VerbosityLevel in main_options.h.
+static const char* kVerbosityLevelNames[] = {
+    "error", "warning", "info", "all", nullptr,
+};
+
 SnapshotKind Options::gen_snapshot_kind_ = kNone;
+VerbosityLevel Options::verbosity_ = kAll;
 bool Options::enable_vm_service_ = false;
 
 #define OPTION_FIELD(variable) Options::variable##_
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 2ab8598..adec23c 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -63,7 +63,9 @@
 // In main_options.cc there must be a list of strings that matches the enum
 // called k{enum_type}Names. The field is not automatically declared in
 // main_options.cc. It must be explicitly declared.
-#define ENUM_OPTIONS_LIST(V) V(snapshot_kind, SnapshotKind, gen_snapshot_kind)
+#define ENUM_OPTIONS_LIST(V)                                                   \
+  V(snapshot_kind, SnapshotKind, gen_snapshot_kind)                            \
+  V(verbosity, VerbosityLevel, verbosity)
 
 // Callbacks passed to DEFINE_CB_OPTION().
 #define CB_OPTIONS_LIST(V)                                                     \
@@ -79,6 +81,14 @@
   kAppJIT,
 };
 
+// This enum must match the strings in kVerbosityLevelNames in main_options.cc.
+enum VerbosityLevel {
+  kError,
+  kWarning,
+  kInfo,
+  kAll,
+};
+
 static constexpr const char* DEFAULT_VM_SERVICE_SERVER_IP = "localhost";
 static constexpr int DEFAULT_VM_SERVICE_SERVER_PORT = 8181;
 static constexpr int INVALID_VM_SERVICE_SERVER_PORT = -1;
@@ -131,6 +141,9 @@
   static const char* vm_service_server_ip() { return vm_service_server_ip_; }
   static int vm_service_server_port() { return vm_service_server_port_; }
 
+  static Dart_KernelCompilationVerbosityLevel verbosity_level() {
+    return VerbosityLevelToDartAPI(verbosity_);
+  }
 #if !defined(DART_PRECOMPILED_RUNTIME)
   static DFE* dfe() { return dfe_; }
   static void set_dfe(DFE* dfe) { dfe_ = dfe; }
@@ -169,6 +182,22 @@
   static DFE* dfe_;
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
+  static Dart_KernelCompilationVerbosityLevel VerbosityLevelToDartAPI(
+      VerbosityLevel level) {
+    switch (level) {
+      case kError:
+        return Dart_KernelCompilationVerbosityLevel_Error;
+      case kWarning:
+        return Dart_KernelCompilationVerbosityLevel_Warning;
+      case kInfo:
+        return Dart_KernelCompilationVerbosityLevel_Info;
+      case kAll:
+        return Dart_KernelCompilationVerbosityLevel_All;
+      default:
+        UNREACHABLE();
+    }
+  }
+
   // VM Service argument processing.
   static const char* vm_service_server_ip_;
   static bool enable_vm_service_;
diff --git a/runtime/bin/priority_heap_test.cc b/runtime/bin/priority_heap_test.cc
new file mode 100644
index 0000000..b0fdb5b
--- /dev/null
+++ b/runtime/bin/priority_heap_test.cc
@@ -0,0 +1,167 @@
+// 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.
+
+#include "vm/unit_test.h"
+
+#include "platform/priority_queue.h"
+
+namespace dart {
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__INCREASING) {
+  const word kSize = PriorityQueue<word, word>::kMinimumSize;
+
+  PriorityQueue<word, word> heap;
+  for (word i = 0; i < kSize; i++) {
+    heap.Insert(i, 10 + i);
+  }
+  ASSERT(heap.min_heap_size() == kSize);
+  for (word i = 0; i < kSize; i++) {
+    EXPECT(!heap.IsEmpty());
+    EXPECT_EQ(i, heap.Minimum().priority);
+    EXPECT_EQ(10 + i, heap.Minimum().value);
+    EXPECT(heap.ContainsValue(10 + i));
+    heap.RemoveMinimum();
+    EXPECT(!heap.ContainsValue(10 + i));
+  }
+  EXPECT(heap.IsEmpty());
+}
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__DECREASING) {
+  const word kSize = PriorityQueue<word, word>::kMinimumSize;
+
+  PriorityQueue<word, word> heap;
+  for (word i = kSize - 1; i >= 0; i--) {
+    heap.Insert(i, 10 + i);
+  }
+  ASSERT(heap.min_heap_size() == kSize);
+  for (word i = 0; i < kSize; i++) {
+    EXPECT(!heap.IsEmpty());
+    EXPECT_EQ(i, heap.Minimum().priority);
+    EXPECT_EQ(10 + i, heap.Minimum().value);
+    EXPECT(heap.ContainsValue(10 + i));
+    heap.RemoveMinimum();
+    EXPECT(!heap.ContainsValue(10 + i));
+  }
+  EXPECT(heap.IsEmpty());
+}
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__DELETE_BY_VALUES) {
+  const word kSize = PriorityQueue<word, word>::kMinimumSize;
+
+  PriorityQueue<word, word> heap;
+  for (word i = kSize - 1; i >= 0; i--) {
+    heap.Insert(i, 10 + i);
+  }
+
+  ASSERT(heap.min_heap_size() == kSize);
+
+  EXPECT(heap.RemoveByValue(10 + 0));
+  EXPECT(!heap.RemoveByValue(10 + 0));
+
+  EXPECT(heap.RemoveByValue(10 + 5));
+  EXPECT(!heap.RemoveByValue(10 + 5));
+
+  EXPECT(heap.RemoveByValue(10 + kSize - 1));
+  EXPECT(!heap.RemoveByValue(10 + kSize - 1));
+
+  for (word i = 0; i < kSize; i++) {
+    // Jump over the removed [i]s in the loop.
+    if (i != 0 && i != 5 && i != (kSize - 1)) {
+      EXPECT(!heap.IsEmpty());
+      EXPECT_EQ(i, heap.Minimum().priority);
+      EXPECT_EQ(10 + i, heap.Minimum().value);
+      EXPECT(heap.ContainsValue(10 + i));
+      heap.RemoveMinimum();
+      EXPECT(!heap.ContainsValue(10 + i));
+    }
+  }
+  EXPECT(heap.IsEmpty());
+}
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__GROW_SHRINK) {
+  const word kSize = 1024;
+  const word kMinimumSize = PriorityQueue<word, word>::kMinimumSize;
+
+  PriorityQueue<word, word> heap;
+  for (word i = 0; i < kSize; i++) {
+    heap.Insert(i, 10 + i);
+  }
+
+  ASSERT(heap.min_heap_size() == kSize);
+
+  for (word i = 0; i < kSize; i++) {
+    EXPECT(!heap.IsEmpty());
+    EXPECT_EQ(i, heap.Minimum().priority);
+    EXPECT_EQ(10 + i, heap.Minimum().value);
+    EXPECT(heap.ContainsValue(10 + i));
+    heap.RemoveMinimum();
+    EXPECT(!heap.ContainsValue(10 + i));
+  }
+
+  EXPECT(heap.IsEmpty());
+  ASSERT(heap.min_heap_size() == kMinimumSize);
+
+  for (word i = 0; i < kSize; i++) {
+    heap.Insert(i, 10 + i);
+  }
+
+  for (word i = 0; i < kSize; i++) {
+    EXPECT(!heap.IsEmpty());
+    EXPECT_EQ(i, heap.Minimum().priority);
+    EXPECT_EQ(10 + i, heap.Minimum().value);
+    EXPECT(heap.ContainsValue(10 + i));
+    heap.RemoveMinimum();
+    EXPECT(!heap.ContainsValue(10 + i));
+  }
+
+  EXPECT(heap.IsEmpty());
+  ASSERT(heap.min_heap_size() == kMinimumSize);
+}
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__CHANGE_PRIORITY) {
+  const word kSize = PriorityQueue<word, word>::kMinimumSize;
+
+  PriorityQueue<word, word> heap;
+  for (word i = 0; i < kSize; i++) {
+    if (i % 2 == 0) {
+      heap.Insert(i, 10 + i);
+    }
+  }
+  ASSERT(heap.min_heap_size() == kSize);
+  for (word i = 0; i < kSize; i++) {
+    bool was_inserted = i % 2 == 0;
+    bool increase = i % 3 == 0;
+    word new_priority = i + (increase ? 100 : -100);
+
+    EXPECT(was_inserted != heap.InsertOrChangePriority(new_priority, 10 + i));
+  }
+
+  for (word i = 0; i < kSize; i++) {
+    bool increase = i % 3 == 0;
+    if (!increase) {
+      word expected_priority = i + (increase ? 100 : -100);
+      EXPECT(!heap.IsEmpty());
+      EXPECT_EQ(expected_priority, heap.Minimum().priority);
+      EXPECT_EQ(10 + i, heap.Minimum().value);
+      EXPECT(heap.ContainsValue(10 + i));
+      heap.RemoveMinimum();
+      EXPECT(!heap.ContainsValue(10 + i));
+    }
+  }
+  for (word i = 0; i < kSize; i++) {
+    bool increase = i % 3 == 0;
+    if (increase) {
+      word expected_priority = i + (increase ? 100 : -100);
+      EXPECT(!heap.IsEmpty());
+      EXPECT_EQ(expected_priority, heap.Minimum().priority);
+      EXPECT_EQ(10 + i, heap.Minimum().value);
+      EXPECT(heap.ContainsValue(10 + i));
+      heap.RemoveMinimum();
+      EXPECT(!heap.ContainsValue(10 + i));
+    }
+  }
+  EXPECT(heap.IsEmpty());
+}
+
+}  // namespace dart.
diff --git a/runtime/bin/secure_socket_filter.cc b/runtime/bin/secure_socket_filter.cc
index c7a89a5..f515b92 100644
--- a/runtime/bin/secure_socket_filter.cc
+++ b/runtime/bin/secure_socket_filter.cc
@@ -159,10 +159,14 @@
 
 void FUNCTION_NAME(SecureSocket_NewX509CertificateWrapper)(
     Dart_NativeArguments args) {
+// This is to be used only in conjunction with certificate trust evaluator
+// running asynchronously, which is only used on mac/ios at the moment.
+#if !defined(HOST_OS_MACOS)
+  FATAL("This is to be used only on mac/ios platforms");
+#endif
   intptr_t x509_pointer = DartUtils::GetNativeIntptrArgument(args, 0);
   ASSERT(x509_pointer != 0);
   X509* x509 = reinterpret_cast<X509*>(x509_pointer);
-  X509_up_ref(x509);
   Dart_SetReturnValue(args, X509Helper::WrappedX509Certificate(x509));
 }
 
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
index 927e139..c56487d 100644
--- a/runtime/bin/security_context_macos.cc
+++ b/runtime/bin/security_context_macos.cc
@@ -136,6 +136,7 @@
   int current_cert = 0;
   cert_chain.set(CFArrayCreateMutable(NULL, num_certs, NULL));
   X509* ca;
+  // Look for the last certificate in the chain - it's a root certificate.
   while ((ca = sk_X509_shift(unverified)) != NULL) {
     ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
     if (cert == NULL) {
@@ -145,9 +146,12 @@
     ++current_cert;
 
     if (current_cert == num_certs) {
-      root_cert = ca;
+      break;
     }
   }
+  ASSERT(current_cert == num_certs);
+  root_cert = ca;
+  X509_up_ref(ca);
 
   SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
   X509_STORE* store = SSL_CTX_get_cert_store(ssl_ctx);
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 4a19ba2..5168ac5 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -471,7 +471,7 @@
     free(kernel_buffer);
   } else {
     Dart_KernelCompilationResult result =
-        dfe.CompileScript(script_name, false, package_config);
+        dfe.CompileScript(script_name, false, package_config, true);
     if (result.status != Dart_KernelCompilationStatus_Ok) {
       ErrorExit(kErrorExitCode, "%s\n", result.error);
     }
diff --git a/runtime/docs/pragmas.md b/runtime/docs/pragmas.md
index 3f7d23b..3895806 100644
--- a/runtime/docs/pragmas.md
+++ b/runtime/docs/pragmas.md
@@ -7,8 +7,9 @@
 | Pragma | Meaning |
 | --- | --- |
 | `vm:entry-point` | [Defining entry-points into Dart code for an embedder or native methods](compiler/aot/entry_point_pragma.md) |
-| `vm:never-inline` | [Never inline a function or method](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-never-be-inlined)  |
-| `vm:prefer-inline` | [Inline a function or method when possible](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-be-inlined)  |
+| `vm:never-inline` | [Never inline a function or method](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-never-be-inlined) |
+| `vm:prefer-inline` | [Inline a function or method when possible](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-be-inlined) |
+| `vm:notify-debugger-on-exception` | Marks a function that catches exceptions, making the VM treat any caught exception as if they were uncaught. This can be used to notify an attached debugger during debugging, without pausing the app during regular execution. |
 
 ## Pragmas for internal use
 
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 189a6b7..b4415cf 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -588,12 +588,6 @@
  */
 DART_EXPORT const char* Dart_VersionString();
 
-typedef struct {
-  const char* library_uri;
-  const char* class_name;
-  const char* function_name;
-} Dart_QualifiedFunctionName;
-
 /**
  * Isolate specific flags are set when creating a new isolate using the
  * Dart_IsolateFlags structure.
@@ -610,7 +604,6 @@
   bool use_field_guards;
   bool use_osr;
   bool obfuscate;
-  Dart_QualifiedFunctionName* entry_points;
   bool load_vmservice_library;
   bool copy_parent_code;
   bool null_safety;
@@ -3532,6 +3525,13 @@
   intptr_t kernel_size;
 } Dart_KernelCompilationResult;
 
+typedef enum {
+  Dart_KernelCompilationVerbosityLevel_Error = 0,
+  Dart_KernelCompilationVerbosityLevel_Warning,
+  Dart_KernelCompilationVerbosityLevel_Info,
+  Dart_KernelCompilationVerbosityLevel_All,
+} Dart_KernelCompilationVerbosityLevel;
+
 DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate);
 DART_EXPORT bool Dart_KernelIsolateIsRunning();
 DART_EXPORT Dart_Port Dart_KernelPort();
@@ -3544,6 +3544,13 @@
  *
  * \param platform_kernel_size The length of the platform_kernel buffer.
  *
+ * \param snapshot_compile Set to `true` when the compilation is for a snapshot.
+ * This is used by the frontend to determine if compilation related information
+ * should be printed to console (e.g., null safety mode).
+ *
+ * \param verbosity Specifies the logging behavior of the kernel compilation
+ * service.
+ *
  * \return Returns the result of the compilation.
  *
  * On a successful compilation the returned [Dart_KernelCompilationResult] has
@@ -3561,7 +3568,9 @@
                      const uint8_t* platform_kernel,
                      const intptr_t platform_kernel_size,
                      bool incremental_compile,
-                     const char* package_config);
+                     bool snapshot_compile,
+                     const char* package_config,
+                     Dart_KernelCompilationVerbosityLevel verbosity);
 
 typedef struct {
   const char* uri;
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc
index d143a98..ec94448 100644
--- a/runtime/lib/array.cc
+++ b/runtime/lib/array.cc
@@ -85,7 +85,7 @@
     result.SetAt(i, temp);
   }
   result.MakeImmutable();
-  return result.raw();
+  return result.ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/lib/bool.cc b/runtime/lib/bool.cc
index 7a4e416..c18a8c3 100644
--- a/runtime/lib/bool.cc
+++ b/runtime/lib/bool.cc
@@ -24,13 +24,13 @@
       String::Handle(Api::GetEnvironmentValue(thread, name));
   if (!env_value.IsNull()) {
     if (Symbols::True().Equals(env_value)) {
-      return Bool::True().raw();
+      return Bool::True().ptr();
     }
     if (Symbols::False().Equals(env_value)) {
-      return Bool::False().raw();
+      return Bool::False().ptr();
     }
   }
-  return default_value.raw();
+  return default_value.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Bool_hasEnvironment, 0, 2) {
@@ -39,9 +39,9 @@
   const String& env_value =
       String::Handle(Api::GetEnvironmentValue(thread, name));
   if (!env_value.IsNull()) {
-    return Bool::True().raw();
+    return Bool::True().ptr();
   }
-  return Bool::False().raw();
+  return Bool::False().ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/lib/developer.cc b/runtime/lib/developer.cc
index fafd0ca..d45cecd 100644
--- a/runtime/lib/developer.cc
+++ b/runtime/lib/developer.cc
@@ -25,13 +25,13 @@
   GET_NATIVE_ARGUMENT(String, msg, arguments->NativeArgAt(1));
   Debugger* debugger = isolate->debugger();
   if (debugger == nullptr) {
-    return when.raw();
+    return when.ptr();
   }
   if (when.value()) {
     debugger->PauseDeveloper(msg);
   }
 #endif
-  return when.raw();
+  return when.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Developer_inspect, 0, 1) {
@@ -39,7 +39,7 @@
 #ifndef PRODUCT
   Service::SendInspectEvent(isolate, inspectee);
 #endif  // !PRODUCT
-  return inspectee.raw();
+  return inspectee.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Developer_log, 0, 8) {
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 61b76a3..09136b7 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -134,13 +134,13 @@
     OS::PrintErr("Double_greaterThan %s > %s\n", left.ToCString(),
                  right.ToCString());
   }
-  return Bool::Get(result).raw();
+  return Bool::Get(result).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Double_greaterThanFromInteger, 0, 2) {
   const Double& right = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, left, arguments->NativeArgAt(1));
-  return Bool::Get(left.AsDoubleValue() > right.value()).raw();
+  return Bool::Get(left.AsDoubleValue() > right.value()).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Double_equal, 0, 2) {
@@ -151,13 +151,13 @@
     OS::PrintErr("Double_equal %s == %s\n", left.ToCString(),
                  right.ToCString());
   }
-  return Bool::Get(result).raw();
+  return Bool::Get(result).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Double_equalToInteger, 0, 2) {
   const Double& left = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, right, arguments->NativeArgAt(1));
-  return Bool::Get(left.value() == right.AsDoubleValue()).raw();
+  return Bool::Get(left.value() == right.AsDoubleValue()).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Double_round, 0, 1) {
@@ -264,19 +264,19 @@
 
 DEFINE_NATIVE_ENTRY(Double_getIsInfinite, 0, 1) {
   const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
-  return Bool::Get(isinf(arg.value())).raw();
+  return Bool::Get(isinf(arg.value())).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Double_getIsNaN, 0, 1) {
   const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
-  return Bool::Get(isnan(arg.value())).raw();
+  return Bool::Get(isnan(arg.value())).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Double_getIsNegative, 0, 1) {
   const Double& arg = Double::CheckedHandle(zone, arguments->NativeArgAt(0));
   // Include negative zero, infinity.
   double dval = arg.value();
-  return Bool::Get(signbit(dval) && !isnan(dval)).raw();
+  return Bool::Get(signbit(dval) && !isnan(dval)).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Double_flipSignBit, 0, 1) {
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index cce88cf..42c0acc 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -40,7 +40,7 @@
           return func.script();
         }
         ASSERT(!hit_assertion_error);
-        hit_assertion_error = (func.Owner() == assert_error_class.raw());
+        hit_assertion_error = (func.Owner() == assert_error_class.ptr());
         inlined_iterator.Advance();
       }
       continue;
@@ -52,7 +52,7 @@
       return func.script();
     }
     ASSERT(!hit_assertion_error);
-    hit_assertion_error = (func.Owner() == assert_error_class.raw());
+    hit_assertion_error = (func.Owner() == assert_error_class.ptr());
   }
   UNREACHABLE();
   return Script::null();
@@ -67,9 +67,9 @@
 DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 0, 3) {
   // No need to type check the arguments. This function can only be called
   // internally from the VM.
-  const TokenPosition assertion_start = TokenPosition(
+  const TokenPosition assertion_start = TokenPosition::Deserialize(
       Smi::CheckedHandle(zone, arguments->NativeArgAt(0)).Value());
-  const TokenPosition assertion_end = TokenPosition(
+  const TokenPosition assertion_end = TokenPosition::Deserialize(
       Smi::CheckedHandle(zone, arguments->NativeArgAt(1)).Value());
 
   const Instance& message =
@@ -82,23 +82,25 @@
   const Script& script = Script::Handle(FindScript(&iterator));
 
   // Initialize argument 'failed_assertion' with source snippet.
-  intptr_t from_line, from_column;
-  script.GetTokenLocation(assertion_start, &from_line, &from_column);
-  intptr_t to_line, to_column;
-  script.GetTokenLocation(assertion_end, &to_line, &to_column);
+  auto& condition_text = String::Handle();
   // Extract the assertion condition text (if source is available).
-  auto& condition_text = String::Handle(
-      script.GetSnippet(from_line, from_column, to_line, to_column));
+  intptr_t from_line = -1, from_column = -1;
+  if (script.GetTokenLocation(assertion_start, &from_line, &from_column)) {
+    // Extract the assertion condition text (if source is available).
+    intptr_t to_line, to_column;
+    script.GetTokenLocation(assertion_end, &to_line, &to_column);
+    condition_text =
+        script.GetSnippet(from_line, from_column, to_line, to_column);
+  }
   if (condition_text.IsNull()) {
-    condition_text = Symbols::OptimizedOut().raw();
+    condition_text = Symbols::OptimizedOut().ptr();
   }
   args.SetAt(0, condition_text);
 
   // Initialize location arguments starting at position 1.
-  // Do not set a column if the source has been generated as it will be wrong.
   args.SetAt(1, String::Handle(script.url()));
   args.SetAt(2, Smi::Handle(Smi::New(from_line)));
-  args.SetAt(3, Smi::Handle(Smi::New(script.HasSource() ? from_column : -1)));
+  args.SetAt(3, Smi::Handle(Smi::New(from_column)));
   args.SetAt(4, message);
 
   Exceptions::ThrowByType(Exceptions::kAssertion, args);
@@ -151,7 +153,7 @@
 DEFINE_NATIVE_ENTRY(TypeError_throwNew, 0, 4) {
   // No need to type check the arguments. This function can only be called
   // internally from the VM.
-  const TokenPosition location = TokenPosition(
+  const TokenPosition location = TokenPosition::Deserialize(
       Smi::CheckedHandle(zone, arguments->NativeArgAt(0)).Value());
   const Instance& src_value =
       Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
@@ -171,7 +173,7 @@
 // Return value: none, throws an exception.
 DEFINE_NATIVE_ENTRY(FallThroughError_throwNew, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
-  TokenPosition fallthrough_pos = TokenPosition(smi_pos.Value());
+  TokenPosition fallthrough_pos = TokenPosition::Deserialize(smi_pos.Value());
 
   const Array& args = Array::Handle(Array::New(2));
 
@@ -181,8 +183,8 @@
   iterator.NextFrame();  // Skip native call.
   const Script& script = Script::Handle(Exceptions::GetCallerScript(&iterator));
   args.SetAt(0, String::Handle(script.url()));
-  intptr_t line;
-  script.GetTokenLocation(fallthrough_pos, &line, NULL);
+  intptr_t line = -1;
+  script.GetTokenLocation(fallthrough_pos, &line);
   args.SetAt(1, Smi::Handle(Smi::New(line)));
 
   Exceptions::ThrowByType(Exceptions::kFallThrough, args);
@@ -197,7 +199,7 @@
 DEFINE_NATIVE_ENTRY(AbstractClassInstantiationError_throwNew, 0, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(String, class_name, arguments->NativeArgAt(1));
-  TokenPosition error_pos = TokenPosition(smi_pos.Value());
+  TokenPosition error_pos = TokenPosition::Deserialize(smi_pos.Value());
 
   const Array& args = Array::Handle(Array::New(3));
 
@@ -208,8 +210,8 @@
   const Script& script = Script::Handle(Exceptions::GetCallerScript(&iterator));
   args.SetAt(0, class_name);
   args.SetAt(1, String::Handle(script.url()));
-  intptr_t line;
-  script.GetTokenLocation(error_pos, &line, NULL);
+  intptr_t line = -1;
+  script.GetTokenLocation(error_pos, &line);
   args.SetAt(2, Smi::Handle(Smi::New(line)));
 
   Exceptions::ThrowByType(Exceptions::kAbstractClassInstantiation, args);
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 2144be8..d703d0b 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -91,14 +91,14 @@
 static ObjectPtr LoadValueStruct(Zone* zone,
                                  const Pointer& target,
                                  const AbstractType& instance_type_arg) {
-  // Result is a struct class -- find <class name>.#fromPointer
+  // Result is a struct class -- find <class name>.#fromTypedDataBase
   // constructor and call it.
   const Class& cls = Class::Handle(zone, instance_type_arg.type_class());
   const Function& constructor =
       Function::Handle(cls.LookupFunctionAllowPrivate(String::Handle(
           String::Concat(String::Handle(String::Concat(
                              String::Handle(cls.Name()), Symbols::Dot())),
-                         Symbols::StructFromPointer()))));
+                         Symbols::StructFromTypedDataBase()))));
   ASSERT(!constructor.IsNull());
   ASSERT(constructor.IsGenerativeConstructor());
   ASSERT(!Object::Handle(constructor.VerifyCallEntryPoint()).IsError());
@@ -110,7 +110,7 @@
   const Object& constructorResult =
       Object::Handle(DartEntry::InvokeFunction(constructor, args));
   ASSERT(!constructorResult.IsError());
-  return new_object.raw();
+  return new_object.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Ffi_loadStruct, 0, 2) {
@@ -222,7 +222,7 @@
   }
 
   const auto& typed_data_class =
-      Class::Handle(zone, isolate->class_table()->At(cid));
+      Class::Handle(zone, isolate->group()->class_table()->At(cid));
   const auto& error =
       Error::Handle(zone, typed_data_class.EnsureIsAllocateFinalized(thread));
   if (!error.IsNull()) {
@@ -248,8 +248,7 @@
                                arguments->NativeArgAt(1));
 
   ASSERT(type_arg.IsInstantiated() && type_arg.IsFunctionType());
-  const Function& native_signature =
-      Function::Handle(zone, Type::Cast(type_arg).signature());
+  const FunctionType& native_signature = FunctionType::Cast(type_arg);
   Function& func = Function::Handle(zone, closure.function());
 
   // The FE verifies that the target of a 'fromFunction' is a static method, so
@@ -270,7 +269,7 @@
                                  native_signature, func, exceptional_return)));
 
   // Because we have already set the return value.
-  return Object::sentinel().raw();
+  return Object::sentinel().ptr();
 #endif
 }
 
@@ -293,12 +292,22 @@
     Exceptions::PropagateError(Error::Cast(result));
   }
   ASSERT(result.IsCode());
-  code ^= result.raw();
+  code ^= result.ptr();
 #endif
 
   ASSERT(!code.IsNull());
   thread->SetFfiCallbackCode(function.FfiCallbackId(), code);
 
+#ifdef TARGET_ARCH_IA32
+  // On ia32, store the stack delta that we need to use when returning.
+  const intptr_t stack_return_delta =
+      function.FfiCSignatureReturnsStruct() && CallingConventions::kUsesRet4
+          ? compiler::target::kWordSize
+          : 0;
+  thread->SetFfiCallbackStackReturn(function.FfiCallbackId(),
+                                    stack_return_delta);
+#endif
+
   uword entry_point = code.EntryPoint();
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (NativeCallbackTrampolines::Enabled()) {
diff --git a/runtime/lib/ffi_dynamic_library.cc b/runtime/lib/ffi_dynamic_library.cc
index ac11bd9..c95e972 100644
--- a/runtime/lib/ffi_dynamic_library.cc
+++ b/runtime/lib/ffi_dynamic_library.cc
@@ -9,7 +9,7 @@
 #include "vm/native_entry.h"
 
 #if !defined(HOST_OS_LINUX) && !defined(HOST_OS_MACOS) &&                      \
-    !defined(HOST_OS_ANDROID)
+    !defined(HOST_OS_ANDROID) && !defined(HOST_OS_FUCHSIA)
 // TODO(dacoharkes): Implement dynamic libraries for other targets & merge the
 // implementation with:
 // - runtime/bin/extensions.h
@@ -23,7 +23,8 @@
 namespace dart {
 
 static void* LoadExtensionLibrary(const char* library_file) {
-#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
+#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) ||                        \
+    defined(HOST_OS_ANDROID) || defined(HOST_OS_FUCHSIA)
   void* handle = dlopen(library_file, RTLD_LAZY);
   if (handle == nullptr) {
     char* error = dlerror();
@@ -77,7 +78,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(Ffi_dl_processLibrary, 0, 0) {
-#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
+#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) ||                        \
+    defined(HOST_OS_ANDROID) || defined(HOST_OS_FUCHSIA)
   return DynamicLibrary::New(RTLD_DEFAULT);
 #else
   const Array& args = Array::Handle(Array::New(1));
@@ -93,7 +95,8 @@
 }
 
 static void* ResolveSymbol(void* handle, const char* symbol) {
-#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
+#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) ||                        \
+    defined(HOST_OS_ANDROID) || defined(HOST_OS_FUCHSIA)
   dlerror();  // Clear any errors.
   void* pointer = dlsym(handle, symbol);
   if (pointer == nullptr) {
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index 1ea506c..07e839f 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -27,7 +27,7 @@
   if (result.IsError()) {
     Exceptions::PropagateError(Error::Cast(result));
   }
-  return result.raw();
+  return result.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Closure_equals, 0, 2) {
@@ -39,8 +39,8 @@
   // 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.raw() == other.raw()) {
-    return Bool::True().raw();
+  if (receiver.ptr() == other.ptr()) {
+    return Bool::True().ptr();
   }
   if (other.IsClosure()) {
     const Function& func_a = Function::Handle(zone, receiver.function());
@@ -54,15 +54,15 @@
         ObjectPtr receiver_a = context_a.At(0);
         ObjectPtr receiver_b = context_b.At(0);
         if ((receiver_a == receiver_b) &&
-            ((func_a.raw() == func_b.raw()) ||
+            ((func_a.ptr() == func_b.ptr()) ||
              ((func_a.name() == func_b.name()) &&
               (func_a.Owner() == func_b.Owner())))) {
-          return Bool::True().raw();
+          return Bool::True().ptr();
         }
       }
     }
   }
-  return Bool::False().raw();
+  return Bool::False().ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Closure_computeHash, 0, 1) {
diff --git a/runtime/lib/growable_array.cc b/runtime/lib/growable_array.cc
index 71d9f2a..1f8bd54 100644
--- a/runtime/lib/growable_array.cc
+++ b/runtime/lib/growable_array.cc
@@ -24,7 +24,7 @@
   const GrowableObjectArray& new_array =
       GrowableObjectArray::Handle(GrowableObjectArray::New(data));
   new_array.SetTypeArguments(type_arguments);
-  return new_array.raw();
+  return new_array.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(GrowableList_getIndexed, 0, 2) {
@@ -35,7 +35,7 @@
     Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
   }
   const Instance& obj = Instance::CheckedHandle(zone, array.At(index.Value()));
-  return obj.raw();
+  return obj.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(GrowableList_setIndexed, 0, 3) {
@@ -89,7 +89,7 @@
 DEFINE_NATIVE_ENTRY(Internal_makeFixedListUnmodifiable, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Array, array, arguments->NativeArgAt(0));
   array.MakeImmutable();
-  return array.raw();
+  return array.ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/lib/identical.cc b/runtime/lib/identical.cc
index c0d2b96..832ded4 100644
--- a/runtime/lib/identical.cc
+++ b/runtime/lib/identical.cc
@@ -12,7 +12,7 @@
   GET_NATIVE_ARGUMENT(Instance, a, arguments->NativeArgAt(0));
   GET_NATIVE_ARGUMENT(Instance, b, arguments->NativeArgAt(1));
   const bool is_identical = a.IsIdenticalTo(b);
-  return Bool::Get(is_identical).raw();
+  return Bool::Get(is_identical).ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index 1c89c6d..af4a2a7 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -143,7 +143,7 @@
     OS::PrintErr("Integer_greaterThanFromInteger %s > %s\n", left.ToCString(),
                  right.ToCString());
   }
-  return Bool::Get(left.CompareWith(right) == 1).raw();
+  return Bool::Get(left.CompareWith(right) == 1).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Integer_equalToInteger, 0, 2) {
@@ -155,7 +155,7 @@
     OS::PrintErr("Integer_equalToInteger %s == %s\n", left.ToCString(),
                  right.ToCString());
   }
-  return Bool::Get(left.CompareWith(right) == 0).raw();
+  return Bool::Get(left.CompareWith(right) == 0).ptr();
 }
 
 static IntegerPtr ParseInteger(const String& value) {
@@ -194,12 +194,12 @@
     const Integer& result = Integer::Handle(ParseInteger(env_value));
     if (!result.IsNull()) {
       if (result.IsSmi()) {
-        return result.raw();
+        return result.ptr();
       }
       return result.Canonicalize(thread);
     }
   }
-  return default_value.raw();
+  return default_value.ptr();
 }
 
 static IntegerPtr ShiftOperationHelper(Token::Kind kind,
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 3a41006..b5d898e 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -39,7 +39,7 @@
 DEFINE_NATIVE_ENTRY(CapabilityImpl_equals, 0, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(Capability, recv, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Capability, other, arguments->NativeArgAt(1));
-  return (recv.Id() == other.Id()) ? Bool::True().raw() : Bool::False().raw();
+  return (recv.Id() == other.Id()) ? Bool::True().ptr() : Bool::False().ptr();
 }
 
 DEFINE_NATIVE_ENTRY(CapabilityImpl_get_hashcode, 0, 1) {
@@ -107,9 +107,9 @@
   const Dart_Port destination_port_id = port.Id();
   const bool can_send_any_object = isolate->origin_id() == port.origin_id();
 
-  if (ApiObjectConverter::CanConvert(obj.raw())) {
+  if (ApiObjectConverter::CanConvert(obj.ptr())) {
     PortMap::PostMessage(
-        Message::New(destination_port_id, obj.raw(), Message::kNormalPriority));
+        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?
@@ -119,7 +119,7 @@
   return Object::null();
 }
 
-class ObjectPtrSetTraitsLayout {
+class UntaggedObjectPtrSetTraits {
  public:
   static bool ReportStats() { return false; }
   static const char* Name() { return "RawObjectPtrSetTraits"; }
@@ -146,7 +146,7 @@
    private:
     void VisitPointers(ObjectPtr* from, ObjectPtr* to) {
       for (ObjectPtr* raw = from; raw <= to; raw++) {
-        if (!(*raw)->IsHeapObject() || (*raw)->ptr()->IsCanonical()) {
+        if (!(*raw)->IsHeapObject() || (*raw)->untag()->IsCanonical()) {
           continue;
         }
         if (visited_->GetValueExclusive(*raw) == 1) {
@@ -160,10 +160,10 @@
     WeakTable* visited_;
     MallocGrowableArray<ObjectPtr>* const working_set_;
   };
-  if (!obj.raw()->IsHeapObject() || obj.raw()->ptr()->IsCanonical()) {
-    return obj.raw();
+  if (!obj.ptr()->IsHeapObject() || obj.ptr()->untag()->IsCanonical()) {
+    return obj.ptr();
   }
-  ClassTable* class_table = isolate->class_table();
+  ClassTable* class_table = isolate->group()->class_table();
 
   Class& klass = Class::Handle(zone);
   Closure& closure = Closure::Handle(zone);
@@ -184,8 +184,8 @@
 
     SendMessageValidator visitor(isolate->group(), visited.get(), &working_set);
 
-    visited->SetValueExclusive(obj.raw(), 1);
-    working_set.Add(obj.raw());
+    visited->SetValueExclusive(obj.ptr(), 1);
+    working_set.Add(obj.ptr());
 
     while (!working_set.is_empty() && !error_found) {
       ObjectPtr raw = working_set.RemoveLast();
@@ -225,13 +225,13 @@
           if (cid >= kNumPredefinedCids) {
             klass = class_table->At(cid);
             if (klass.num_native_fields() != 0) {
-              erroneous_nativewrapper_class = klass.raw();
+              erroneous_nativewrapper_class = klass.ptr();
               error_found = true;
               break;
             }
           }
       }
-      raw->ptr()->VisitPointers(&visitor);
+      raw->untag()->VisitPointers(&visitor);
     }
   }
   if (error_found) {
@@ -255,7 +255,7 @@
         zone, Exceptions::kArgumentValue, exception_message);
   }
   isolate->set_forward_table_new(nullptr);
-  return obj.raw();
+  return obj.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(SendPortImpl_sendAndExitInternal_, 0, 2) {
@@ -271,7 +271,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, obj, arguments->NativeArgAt(1));
 
   Object& validated_result = Object::Handle(zone);
-  Object& msg_obj = Object::Handle(zone, obj.raw());
+  Object& msg_obj = Object::Handle(zone, obj.ptr());
   validated_result = ValidateMessageObject(zone, isolate, msg_obj);
   if (validated_result.IsUnhandledException()) {
     Exceptions::PropagateError(Error::Cast(validated_result));
@@ -279,7 +279,7 @@
   }
   PersistentHandle* handle =
       isolate->group()->api_state()->AllocatePersistentHandle();
-  handle->set_raw(msg_obj);
+  handle->set_ptr(msg_obj);
   isolate->bequeath(std::unique_ptr<Bequest>(new Bequest(handle, port.Id())));
   // TODO(aam): Ensure there are no dart api calls after this point as we want
   // to ensure that validated message won't get tampered with.
@@ -457,7 +457,7 @@
 
 ObjectPtr IsolateSpawnState::ResolveFunction() {
   Thread* thread = Thread::Current();
-  Isolate* I = thread->isolate();
+  auto IG = thread->isolate_group();
   Zone* zone = thread->zone();
 
   const String& func_name = String::Handle(zone, String::New(function_name()));
@@ -466,13 +466,13 @@
     // Handle spawnUri lookup rules.
     // Check whether the root library defines a main function.
     const Library& lib =
-        Library::Handle(zone, I->object_store()->root_library());
+        Library::Handle(zone, IG->object_store()->root_library());
     Function& func = Function::Handle(zone, lib.LookupLocalFunction(func_name));
     if (func.IsNull()) {
       // Check whether main is reexported from the root library.
       const Object& obj = Object::Handle(zone, lib.LookupReExport(func_name));
       if (obj.IsFunction()) {
-        func ^= obj.raw();
+        func ^= obj.ptr();
       }
     }
     if (func.IsNull()) {
@@ -482,7 +482,7 @@
                     function_name(), script_url()));
       return LanguageError::New(msg);
     }
-    return func.raw();
+    return func.ptr();
   }
 
   // Lookup the to be spawned function for the Isolate.spawn implementation.
@@ -508,7 +508,7 @@
                     function_name(), library_url()));
       return LanguageError::New(msg);
     }
-    return func.raw();
+    return func.ptr();
   }
 
   const String& cls_name = String::Handle(zone, String::New(class_name()));
@@ -533,7 +533,7 @@
                   (library_url() != nullptr ? library_url() : script_url())));
     return LanguageError::New(msg);
   }
-  return func.raw();
+  return func.ptr();
 }
 
 static InstancePtr DeserializeMessage(Thread* thread, Message* message) {
@@ -547,7 +547,7 @@
     MessageSnapshotReader reader(message, thread);
     const Object& obj = Object::Handle(zone, reader.ReadObject());
     ASSERT(!obj.IsError());
-    return Instance::RawCast(obj.raw());
+    return Instance::RawCast(obj.ptr());
   }
 }
 
@@ -634,11 +634,7 @@
     char* error = nullptr;
 
     auto group = state_->isolate_group();
-#if defined(DART_PRECOMPILED_RUNTIME)
-    Isolate* isolate = CreateWithinExistingIsolateGroupAOT(group, name, &error);
-#else
     Isolate* isolate = CreateWithinExistingIsolateGroup(group, name, &error);
-#endif
     parent_isolate_->DecrementSpawnCount();
     parent_isolate_ = nullptr;
 
@@ -724,7 +720,7 @@
       return false;
     }
     ASSERT(result.IsFunction());
-    auto& func = Function::Handle(zone, Function::Cast(result).raw());
+    auto& func = Function::Handle(zone, Function::Cast(result).ptr());
     func = func.ImplicitClosureFunction();
     const auto& entrypoint_closure =
         Object::Handle(zone, func.ImplicitStaticClosure());
@@ -886,7 +882,7 @@
       result = String2UTF8(String::Cast(obj));
     } else if (obj.IsError()) {
       Error& error_obj = Error::Handle();
-      error_obj ^= obj.raw();
+      error_obj ^= obj.ptr();
       *error = zone->PrintToString("Unable to canonicalize uri '%s': %s",
                                    uri.ToCString(), error_obj.ToErrorCString());
     } else {
@@ -938,7 +934,7 @@
 
   // Canonicalize the uri with respect to the current isolate.
   const Library& root_lib =
-      Library::Handle(isolate->object_store()->root_library());
+      Library::Handle(isolate->group()->object_store()->root_library());
   char* error = NULL;
   const char* canonical_uri = CanonicalizeUri(thread, root_lib, uri, &error);
   if (canonical_uri == NULL) {
@@ -987,12 +983,12 @@
       1, Capability::Handle(Capability::New(isolate->pause_capability())));
   result.SetAt(
       2, Capability::Handle(Capability::New(isolate->terminate_capability())));
-  return result.raw();
+  return result.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Isolate_getCurrentRootUriStr, 0, 0) {
   const Library& root_lib =
-      Library::Handle(zone, isolate->object_store()->root_library());
+      Library::Handle(zone, isolate->group()->object_store()->root_library());
   return root_lib.url();
 }
 
@@ -1049,7 +1045,7 @@
     array ^= growable_array.data();
     array_length = growable_array.Length();
   } else if (array_instance.IsArray()) {
-    array ^= Array::Cast(array_instance).raw();
+    array ^= Array::Cast(array_instance).ptr();
     array_length = array.Length();
   } else {
     Exceptions::ThrowArgumentError(array_instance);
@@ -1075,8 +1071,8 @@
 
   uint8_t* data = reinterpret_cast<uint8_t*>(::malloc(total_bytes));
   if (data == nullptr) {
-    const Instance& exception =
-        Instance::Handle(thread->isolate()->object_store()->out_of_memory());
+    const Instance& exception = Instance::Handle(
+        thread->isolate_group()->object_store()->out_of_memory());
     Exceptions::Throw(thread, exception);
     UNREACHABLE();
   }
@@ -1106,7 +1102,7 @@
   void* peer;
   {
     NoSafepointScope no_safepoint;
-    peer = thread->heap()->GetPeer(t.raw());
+    peer = thread->heap()->GetPeer(t.ptr());
     // Assume that object's Peer is only used to track transferrability state.
     ASSERT(peer != nullptr);
   }
@@ -1126,11 +1122,11 @@
   const ExternalTypedData& typed_data = ExternalTypedData::Handle(
       ExternalTypedData::New(kExternalTypedDataUint8ArrayCid, data, length,
                              thread->heap()->SpaceForExternal(length)));
-  FinalizablePersistentHandle::New(thread->isolate(), typed_data,
+  FinalizablePersistentHandle::New(thread->isolate_group(), typed_data,
                                    /* peer= */ data,
                                    &ExternalTypedDataFinalizer, length,
                                    /*auto_delete=*/true);
-  return typed_data.raw();
+  return typed_data.ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/lib/math.cc b/runtime/lib/math.cc
index b1e7513..9346d1e 100644
--- a/runtime/lib/math.cc
+++ b/runtime/lib/math.cc
@@ -86,7 +86,7 @@
   const TypedData& array = TypedData::Cast(state_field_value);
   ASSERT(array.Length() == 2);
   ASSERT(array.ElementType() == kUint32ArrayElement);
-  return array.raw();
+  return array.ptr();
 }
 
 // Implements:
@@ -113,7 +113,7 @@
   result.SetUint32(0, static_cast<uint32_t>(seed));
   result.SetUint32(result.ElementSizeInBytes(),
                    static_cast<uint32_t>(seed >> 32));
-  return result.raw();
+  return result.ptr();
 }
 
 uint64_t mix64(uint64_t n) {
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index eddf299..d2d9a4f 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -38,7 +38,7 @@
   if (result.IsError()) {
     Exceptions::PropagateError(Error::Cast(result));
   }
-  return Instance::Cast(result).raw();
+  return Instance::Cast(result).ptr();
 }
 
 // Conventions:
@@ -94,15 +94,16 @@
 }
 
 static InstancePtr CreateParameterMirrorList(const Function& func,
+                                             const FunctionType& signature,
                                              const Instance& owner_mirror) {
   HANDLESCOPE(Thread::Current());
-  const intptr_t implicit_param_count = func.NumImplicitParameters();
+  const intptr_t implicit_param_count = signature.num_implicit_parameters();
   const intptr_t non_implicit_param_count =
-      func.NumParameters() - implicit_param_count;
+      signature.NumParameters() - implicit_param_count;
   const intptr_t index_of_first_optional_param =
-      non_implicit_param_count - func.NumOptionalParameters();
+      non_implicit_param_count - signature.NumOptionalParameters();
   const intptr_t index_of_first_named_param =
-      non_implicit_param_count - func.NumOptionalNamedParameters();
+      non_implicit_param_count - signature.NumOptionalNamedParameters();
   const Array& results = Array::Handle(Array::New(non_implicit_param_count));
   const Array& args = Array::Handle(Array::New(9));
 
@@ -116,23 +117,18 @@
   // We force compilation of constructors to ensure the types of initializing
   // formals have been corrected. We do not force the compilation of all types
   // of functions because some have no body, e.g. signature functions.
-  EnsureConstructorsAreCompiled(func);
+  if (!func.IsNull()) {
+    EnsureConstructorsAreCompiled(func);
+  }
 
   bool has_extra_parameter_info = true;
   if (non_implicit_param_count == 0) {
     has_extra_parameter_info = false;
   }
-  if (func.IsImplicitConstructor()) {
+  if (func.IsNull() || func.IsImplicitConstructor()) {
     // This covers the default constructor and forwarding constructors.
     has_extra_parameter_info = false;
   }
-  if (func.IsSignatureFunction() &&
-      (func.token_pos() == TokenPosition::kNoSource)) {
-    // Signature functions (except those describing typedefs) get canonicalized,
-    // hence do not have a token position, and therefore cannot be reparsed.
-    has_extra_parameter_info = false;
-  }
-
   Array& param_descriptor = Array::Handle();
   if (has_extra_parameter_info) {
     // Reparse the function for the following information:
@@ -144,23 +140,27 @@
       Exceptions::PropagateError(Error::Cast(result));
       UNREACHABLE();
     }
-    param_descriptor ^= result.raw();
+    param_descriptor ^= result.ptr();
     ASSERT(param_descriptor.Length() ==
            (Parser::kParameterEntrySize * non_implicit_param_count));
   }
 
-  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func)));
+  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(signature)));
   args.SetAt(2, owner_mirror);
 
   if (!has_extra_parameter_info) {
-    is_final = Bool::True().raw();
+    is_final = Bool::True().ptr();
     default_value = Object::null();
     metadata = Object::null();
   }
 
   for (intptr_t i = 0; i < non_implicit_param_count; i++) {
     pos = Smi::New(i);
-    name = func.ParameterNameAt(implicit_param_count + i);
+    if (!func.IsNull()) {
+      name = func.ParameterNameAt(implicit_param_count + i);
+    } else {
+      name = signature.ParameterNameAt(implicit_param_count + i);
+    }
     if (has_extra_parameter_info) {
       is_final ^= param_descriptor.At(i * Parser::kParameterEntrySize +
                                       Parser::kParameterIsFinalOffset);
@@ -184,7 +184,7 @@
     results.SetAt(i, param);
   }
   results.MakeImmutable();
-  return results.raw();
+  return results.ptr();
 }
 
 static InstancePtr CreateTypeVariableMirror(const TypeParameter& param,
@@ -201,7 +201,7 @@
 static InstancePtr CreateTypeVariableList(const Class& cls) {
   const TypeArguments& args = TypeArguments::Handle(cls.type_parameters());
   if (args.IsNull()) {
-    return Object::empty_array().raw();
+    return Object::empty_array().ptr();
   }
   const Array& result = Array::Handle(Array::New(args.Length() * 2));
   TypeParameter& type = TypeParameter::Handle();
@@ -214,30 +214,17 @@
     result.SetAt(2 * i, name);
     result.SetAt(2 * i + 1, type);
   }
-  return result.raw();
-}
-
-static InstancePtr CreateTypedefMirror(const Class& cls,
-                                       const AbstractType& type,
-                                       const Bool& is_declaration,
-                                       const Instance& owner_mirror) {
-  const Array& args = Array::Handle(Array::New(6));
-  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
-  args.SetAt(1, type);
-  args.SetAt(2, String::Handle(cls.Name()));
-  args.SetAt(3, Bool::Get(cls.IsGeneric()));
-  args.SetAt(4, cls.IsGeneric() ? is_declaration : Bool::False());
-  args.SetAt(5, owner_mirror);
-  return CreateMirror(Symbols::_TypedefMirror(), args);
+  return result.ptr();
 }
 
 static InstancePtr CreateFunctionTypeMirror(const AbstractType& type) {
   ASSERT(type.IsFunctionType());
-  const Class& cls = Class::Handle(Type::Cast(type).type_class());
-  const Function& func = Function::Handle(Type::Cast(type).signature());
+  const Class& closure_class =
+      Class::Handle(IsolateGroup::Current()->object_store()->closure_class());
+  const FunctionType& sig = FunctionType::Cast(type);
   const Array& args = Array::Handle(Array::New(3));
-  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
-  args.SetAt(1, MirrorReference::Handle(MirrorReference::New(func)));
+  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(closure_class)));
+  args.SetAt(1, MirrorReference::Handle(MirrorReference::New(sig)));
   args.SetAt(2, type);
   return CreateMirror(Symbols::_FunctionTypeMirror(), args);
 }
@@ -262,7 +249,7 @@
       (static_cast<intptr_t>(func.IsGetterFunction()) << Mirrors::kGetter);
   kind_flags |=
       (static_cast<intptr_t>(func.IsSetterFunction()) << Mirrors::kSetter);
-  bool is_ctor = (func.kind() == FunctionLayout::kConstructor);
+  bool is_ctor = (func.kind() == UntaggedFunction::kConstructor);
   kind_flags |= (static_cast<intptr_t>(is_ctor) << Mirrors::kConstructor);
   kind_flags |= (static_cast<intptr_t>(is_ctor && func.is_const())
                  << Mirrors::kConstCtor);
@@ -318,11 +305,7 @@
   ASSERT(!cls.IsNeverClass());
   ASSERT(!type.IsNull());
   ASSERT(type.IsFinalized());
-
-  if (cls.IsTypedefClass()) {
-    return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
-  }
-
+  ASSERT(type.IsCanonical());
   const Array& args = Array::Handle(Array::New(9));
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
   args.SetAt(1, type);
@@ -508,7 +491,7 @@
   while (entries.HasNext()) {
     entry = entries.GetNext();
     if (entry.IsLibraryPrefix()) {
-      prefix ^= entry.raw();
+      prefix ^= entry.ptr();
       ports = prefix.imports();
       for (intptr_t i = 0; i < ports.Length(); i++) {
         ns ^= ports.At(i);
@@ -523,7 +506,7 @@
     }
   }
 
-  return deps.raw();
+  return deps.ptr();
 }
 
 static InstancePtr CreateTypeMirror(const AbstractType& type) {
@@ -534,16 +517,10 @@
     return CreateTypeMirror(ref_type);
   }
   ASSERT(type.IsFinalized());
-  ASSERT(type.IsCanonical() || type.IsTypeParameter());
+  ASSERT(type.IsCanonical());
 
   if (type.IsFunctionType()) {
-    const Class& scope_class = Class::Handle(Type::Cast(type).type_class());
-    if (scope_class.IsTypedefClass()) {
-      return CreateTypedefMirror(scope_class, type, Bool::False(),
-                                 Object::null_instance());
-    } else {
-      return CreateFunctionTypeMirror(type);
-    }
+    return CreateFunctionTypeMirror(type);
   }
   if (type.HasTypeClass()) {
     const Class& cls = Class::Handle(type.type_class());
@@ -564,17 +541,19 @@
     // TODO(regis): Until mirrors reflect nullability, force kLegacy, except for
     // Null type, which should remain nullable.
     if (!type.IsNullType()) {
-      const Type& legacy_type = Type::Handle(
+      Type& legacy_type = Type::Handle(
           Type::Cast(type).ToNullability(Nullability::kLegacy, Heap::kOld));
+      legacy_type ^= legacy_type.Canonicalize(Thread::Current(), nullptr);
       return CreateClassMirror(cls, legacy_type, Bool::False(),
                                Object::null_instance());
     }
     return CreateClassMirror(cls, type, Bool::False(), Object::null_instance());
   } else if (type.IsTypeParameter()) {
     // TODO(regis): Until mirrors reflect nullability, force kLegacy.
-    const TypeParameter& legacy_type =
+    TypeParameter& legacy_type =
         TypeParameter::Handle(TypeParameter::Cast(type).ToNullability(
             Nullability::kLegacy, Heap::kOld));
+    legacy_type ^= legacy_type.Canonicalize(Thread::Current(), nullptr);
     return CreateTypeVariableMirror(legacy_type, Object::null_instance());
   }
   UNREACHABLE();
@@ -585,8 +564,8 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   const String& debug_name = String::Handle(String::New(isolate->name()));
-  const Library& root_library =
-      Library::Handle(thread->zone(), isolate->object_store()->root_library());
+  const Library& root_library = Library::Handle(
+      thread->zone(), isolate->group()->object_store()->root_library());
   const Instance& root_library_mirror =
       Instance::Handle(CreateLibraryMirror(thread, root_library));
 
@@ -631,13 +610,13 @@
   // Generic function type parameters are not reified, but mapped to dynamic,
   // i.e. all function type parameters are free with a null vector.
   ASSERT(type.IsFinalized());
-  ASSERT(type.IsCanonical() || type.IsTypeParameter());
+  ASSERT(type.IsCanonical());
 
   if (type.IsInstantiated()) {
     return type.Canonicalize(Thread::Current(), nullptr);
   }
   TypeArguments& instantiator_type_args = TypeArguments::Handle();
-  if (!instantiator.IsNull()) {
+  if (!instantiator.IsNull() && instantiator.IsType()) {
     ASSERT(instantiator.IsFinalized());
     instantiator_type_args = instantiator.arguments();
   }
@@ -649,8 +628,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(MirrorSystem_libraries, 0, 0) {
-  const GrowableObjectArray& libraries =
-      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  const GrowableObjectArray& libraries = GrowableObjectArray::Handle(
+      zone, isolate->group()->object_store()->libraries());
 
   const intptr_t num_libraries = libraries.Length();
   const GrowableObjectArray& library_mirrors = GrowableObjectArray::Handle(
@@ -665,7 +644,7 @@
       library_mirrors.Add(library_mirror);
     }
   }
-  return library_mirrors.raw();
+  return library_mirrors.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(MirrorSystem_isolate, 0, 0) {
@@ -692,15 +671,15 @@
   // Canonicalize library URI.
   String& canonical_uri = String::Handle(zone);
   if (uri.StartsWith(Symbols::DartScheme())) {
-    canonical_uri = uri.raw();
+    canonical_uri = uri.ptr();
   } else {
     isolate->BlockClassFinalization();
     const Object& result = Object::Handle(
-        zone,
-        isolate->CallTagHandler(
-            Dart_kCanonicalizeUrl,
-            Library::Handle(zone, isolate->object_store()->root_library()),
-            uri));
+        zone, isolate->CallTagHandler(
+                  Dart_kCanonicalizeUrl,
+                  Library::Handle(
+                      zone, isolate->group()->object_store()->root_library()),
+                  uri));
     isolate->UnblockClassFinalization();
     if (result.IsError()) {
       if (result.IsLanguageError()) {
@@ -711,7 +690,7 @@
       ThrowLanguageError("library handler failed URI canonicalization");
     }
 
-    canonical_uri ^= result.raw();
+    canonical_uri ^= result.ptr();
   }
 
   // Return the existing library if it has already been loaded.
@@ -726,7 +705,8 @@
   Object& result = Object::Handle(
       zone, isolate->CallTagHandler(
                 Dart_kImportTag,
-                Library::Handle(zone, isolate->object_store()->root_library()),
+                Library::Handle(
+                    zone, isolate->group()->object_store()->root_library()),
                 canonical_uri));
   isolate->UnblockClassFinalization();
   if (result.IsError()) {
@@ -762,11 +742,12 @@
 DEFINE_NATIVE_ENTRY(Mirrors_makeLocalClassMirror, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(type.IsFinalized());
-  ASSERT(type.HasTypeClass());
-  const Class& cls = Class::Handle(type.type_class());
+  const Class& cls = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   ASSERT(!cls.IsNull());
-  if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsNeverClass() ||
-      cls.IsTypedefClass()) {
+  if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsNeverClass()) {
     Exceptions::ThrowArgumentError(type);
     UNREACHABLE();
   }
@@ -784,8 +765,10 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Array, args, arguments->NativeArgAt(1));
 
-  ASSERT(type.HasTypeClass());
-  const Class& clz = Class::Handle(type.type_class());
+  const Class& clz = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   if (!clz.IsGeneric()) {
     const Array& error_args = Array::Handle(Array::New(3));
     error_args.SetAt(0, type);
@@ -825,23 +808,22 @@
     type_args_obj.SetTypeAt(i, type_arg);
   }
 
-  Type& instantiated_type =
-      Type::Handle(Type::New(clz, type_args_obj, TokenPosition::kNoSource));
+  Type& instantiated_type = Type::Handle(Type::New(clz, type_args_obj));
   instantiated_type ^= ClassFinalizer::FinalizeType(instantiated_type);
-  return instantiated_type.raw();
+  return instantiated_type.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Mirrors_mangleName, 0, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
   const Library& lib = Library::Handle(ref.GetLibraryReferent());
-  return lib.IsPrivate(name) ? lib.PrivateName(name) : name.raw();
+  return lib.IsPrivate(name) ? lib.PrivateName(name) : name.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(MirrorReference_equals, 0, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, a, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, b, arguments->NativeArgAt(1));
-  return Bool::Get(a.referent() == b.referent()).raw();
+  return Bool::Get(a.referent() == b.referent()).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 0, 1) {
@@ -851,7 +833,7 @@
     const MirrorReference& decl_ref = MirrorReference::Cast(reflectee);
     decl = decl_ref.referent();
   } else if (reflectee.IsTypeParameter()) {
-    decl = reflectee.raw();
+    decl = reflectee.ptr();
   } else {
     UNREACHABLE();
   }
@@ -860,57 +842,56 @@
   Library& library = Library::Handle();
 
   if (decl.IsClass()) {
-    klass ^= decl.raw();
+    klass ^= decl.ptr();
     library = klass.library();
-  } else if (decl.IsFunction() && !Function::Cast(decl).IsSignatureFunction()) {
+  } else if (decl.IsFunction()) {
     klass = Function::Cast(decl).origin();
     library = klass.library();
   } else if (decl.IsField()) {
     klass = Field::Cast(decl).Origin();
     library = klass.library();
   } else if (decl.IsLibrary()) {
-    library ^= decl.raw();
+    library ^= decl.ptr();
   } else if (decl.IsTypeParameter()) {
-    if (TypeParameter::Cast(decl).IsFunctionTypeParameter()) {
-      // TODO(regis): Fully support generic functions.
-      return Object::empty_array().raw();
-    }
-    klass = TypeParameter::Cast(decl).parameterized_class();
-    library = klass.library();
+    // There is no reference from a canonical type parameter to its declaration.
+    return Object::empty_array().ptr();
   } else {
-    return Object::empty_array().raw();
+    return Object::empty_array().ptr();
   }
 
   const Object& metadata = Object::Handle(library.GetMetadata(decl));
   if (metadata.IsError()) {
     Exceptions::PropagateError(Error::Cast(metadata));
   }
-  return metadata.raw();
+  return metadata.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(FunctionTypeMirror_call_method, 0, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner_mirror,
                                arguments->NativeArgAt(0));
-  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
-  // TODO(rmacnak): Return get:call() method on class _Closure instead?
-  // This now returns the result of invoking that call getter.
-  const Function& func = Function::Handle(ref.GetFunctionReferent());
-  ASSERT(!func.IsNull());
-  return CreateMethodMirror(func, owner_mirror, AbstractType::Handle());
+  // Return get:call() method on class _Closure.
+  const auto& getter_name = Symbols::GetCall();
+  const Class& closure_class =
+      Class::Handle(IsolateGroup::Current()->object_store()->closure_class());
+  const Function& get_call = Function::Handle(
+      Resolver::ResolveDynamicAnyArgs(zone, closure_class, getter_name,
+                                      /*allow_add=*/false));
+  ASSERT(!get_call.IsNull());
+  return CreateMethodMirror(get_call, owner_mirror, AbstractType::Handle());
 }
 
 DEFINE_NATIVE_ENTRY(FunctionTypeMirror_parameters, 0, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
-  const Function& func = Function::Handle(ref.GetFunctionReferent());
-  return CreateParameterMirrorList(func, owner);
+  const FunctionType& sig = FunctionType::Handle(ref.GetFunctionTypeReferent());
+  return CreateParameterMirrorList(Object::null_function(), sig, owner);
 }
 
 DEFINE_NATIVE_ENTRY(FunctionTypeMirror_return_type, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
-  const Function& func = Function::Handle(ref.GetFunctionReferent());
-  ASSERT(!func.IsNull());
-  AbstractType& type = AbstractType::Handle(func.result_type());
+  const FunctionType& sig = FunctionType::Handle(ref.GetFunctionTypeReferent());
+  ASSERT(!sig.IsNull());
+  AbstractType& type = AbstractType::Handle(sig.result_type());
   // Signatures of function types are instantiated, but not canonical.
   return type.Canonicalize(thread, nullptr);
 }
@@ -926,16 +907,22 @@
 DEFINE_NATIVE_ENTRY(ClassMirror_supertype, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(type.IsFinalized());
-  const Class& cls = Class::Handle(type.type_class());
+  const Class& cls = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   const AbstractType& super_type = AbstractType::Handle(cls.super_type());
   ASSERT(super_type.IsNull() || super_type.IsFinalized());
-  return super_type.raw();
+  return super_type.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(ClassMirror_supertype_instantiated, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(type.IsFinalized());
-  const Class& cls = Class::Handle(type.type_class());
+  const Class& cls = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   const AbstractType& super_type = AbstractType::Handle(cls.super_type());
   return InstantiateType(super_type, type);
 }
@@ -943,7 +930,10 @@
 DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(type.IsFinalized());
-  const Class& cls = Class::Handle(type.type_class());
+  const Class& cls = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
   if (!error.IsNull()) {
     Exceptions::PropagateError(error);
@@ -955,7 +945,10 @@
 DEFINE_NATIVE_ENTRY(ClassMirror_interfaces_instantiated, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(type.IsFinalized());
-  const Class& cls = Class::Handle(type.type_class());
+  const Class& cls = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   const Error& error = Error::Handle(cls.EnsureIsFinalized(thread));
   if (!error.IsNull()) {
     Exceptions::PropagateError(error);
@@ -971,20 +964,23 @@
     interfaces_inst.SetAt(i, interface);
   }
 
-  return interfaces_inst.raw();
+  return interfaces_inst.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(ClassMirror_mixin, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
   ASSERT(type.IsFinalized());
-  const Class& cls = Class::Handle(type.type_class());
+  const Class& cls = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   AbstractType& mixin_type = AbstractType::Handle();
   if (cls.is_transformed_mixin_application()) {
     const Array& interfaces = Array::Handle(cls.interfaces());
     mixin_type ^= interfaces.At(interfaces.Length() - 1);
   }
   ASSERT(mixin_type.IsNull() || mixin_type.IsFinalized());
-  return mixin_type.raw();
+  return mixin_type.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(ClassMirror_mixin_instantiated, 0, 2) {
@@ -992,14 +988,17 @@
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, instantiator,
                                arguments->NativeArgAt(1));
   ASSERT(type.IsFinalized());
-  const Class& cls = Class::Handle(type.type_class());
+  const Class& cls = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   AbstractType& mixin_type = AbstractType::Handle();
   if (cls.is_transformed_mixin_application()) {
     const Array& interfaces = Array::Handle(cls.interfaces());
     mixin_type ^= interfaces.At(interfaces.Length() - 1);
   }
   if (mixin_type.IsNull()) {
-    return mixin_type.raw();
+    return mixin_type.ptr();
   }
 
   return InstantiateType(mixin_type, instantiator);
@@ -1041,16 +1040,16 @@
   for (intptr_t i = 0; i < num_functions; i++) {
     func ^= functions.At(i);
     if (func.is_reflectable() &&
-        (func.kind() == FunctionLayout::kRegularFunction ||
-         func.kind() == FunctionLayout::kGetterFunction ||
-         func.kind() == FunctionLayout::kSetterFunction)) {
+        (func.kind() == UntaggedFunction::kRegularFunction ||
+         func.kind() == UntaggedFunction::kGetterFunction ||
+         func.kind() == UntaggedFunction::kSetterFunction)) {
       member_mirror =
           CreateMethodMirror(func, owner_mirror, owner_instantiator);
       member_mirrors.Add(member_mirror);
     }
   }
 
-  return member_mirrors.raw();
+  return member_mirrors.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(ClassMirror_constructors, 0, 3) {
@@ -1076,14 +1075,15 @@
   Function& func = Function::Handle();
   for (intptr_t i = 0; i < num_functions; i++) {
     func ^= functions.At(i);
-    if (func.is_reflectable() && func.kind() == FunctionLayout::kConstructor) {
+    if (func.is_reflectable() &&
+        func.kind() == UntaggedFunction::kConstructor) {
       constructor_mirror =
           CreateMethodMirror(func, owner_mirror, owner_instantiator);
       constructor_mirrors.Add(constructor_mirror);
     }
   }
 
-  return constructor_mirrors.raw();
+  return constructor_mirrors.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(LibraryMirror_members, 0, 2) {
@@ -1129,9 +1129,9 @@
     } else if (entry.IsFunction()) {
       const Function& func = Function::Cast(entry);
       if (func.is_reflectable() &&
-          (func.kind() == FunctionLayout::kRegularFunction ||
-           func.kind() == FunctionLayout::kGetterFunction ||
-           func.kind() == FunctionLayout::kSetterFunction)) {
+          (func.kind() == UntaggedFunction::kRegularFunction ||
+           func.kind() == UntaggedFunction::kGetterFunction ||
+           func.kind() == UntaggedFunction::kSetterFunction)) {
         member_mirror =
             CreateMethodMirror(func, owner_mirror, AbstractType::Handle());
         member_mirrors.Add(member_mirror);
@@ -1139,7 +1139,7 @@
     }
   }
 
-  return member_mirrors.raw();
+  return member_mirrors.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(ClassMirror_type_variables, 0, 1) {
@@ -1156,11 +1156,14 @@
 DEFINE_NATIVE_ENTRY(ClassMirror_type_arguments, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
 
-  const Class& cls = Class::Handle(type.type_class());
+  const Class& cls = Class::Handle(
+      type.IsFunctionType()
+          ? IsolateGroup::Current()->object_store()->closure_class()
+          : type.type_class());
   const intptr_t num_params = cls.NumTypeParameters();
 
   if (num_params == 0) {
-    return Object::empty_array().raw();
+    return Object::empty_array().ptr();
   }
 
   const Array& result = Array::Handle(Array::New(num_params));
@@ -1172,12 +1175,12 @@
   // arguments have been provided, or all arguments are dynamic. Return a list
   // of typemirrors on dynamic in this case.
   if (args.IsNull()) {
-    arg_type = Object::dynamic_type().raw();
+    arg_type = Object::dynamic_type().ptr();
     type_mirror = CreateTypeMirror(arg_type);
     for (intptr_t i = 0; i < num_params; i++) {
       result.SetAt(i, type_mirror);
     }
-    return result.raw();
+    return result.ptr();
   }
 
   ASSERT(args.Length() >= num_params);
@@ -1187,22 +1190,13 @@
     type_mirror = CreateTypeMirror(arg_type);
     result.SetAt(i, type_mirror);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(TypeVariableMirror_owner, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
-  Class& owner = Class::Handle(param.parameterized_class());
-  AbstractType& type = AbstractType::Handle();
-  if (owner.IsNull()) {
-    // TODO(regis): Fully support generic functions. For now, reify function
-    // type parameters to dynamic and map their function owner to Null class.
-    ASSERT(param.IsFunctionTypeParameter());
-    type = Type::NullType();
-    owner = type.type_class();
-  } else {
-    type = owner.DeclarationType();
-  }
+  // Type parameters do not have a reference to their owner anymore.
+  const AbstractType& type = AbstractType::Handle(Type::NullType());
+  Class& owner = Class::Handle(type.type_class());
   return CreateClassMirror(owner, type,
                            Bool::True(),  // is_declaration
                            Instance::null_instance());
@@ -1213,16 +1207,6 @@
   return param.bound();
 }
 
-DEFINE_NATIVE_ENTRY(TypedefMirror_declaration, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
-  ASSERT(type.IsFunctionType());
-  const Class& cls = Class::Handle(type.type_class());
-  ASSERT(cls.IsTypedefClass());
-  return CreateTypedefMirror(cls, AbstractType::Handle(cls.DeclarationType()),
-                             Bool::True(),  // is_declaration
-                             Object::null_instance());
-}
-
 DEFINE_NATIVE_ENTRY(InstanceMirror_invoke, 0, 5) {
   // Argument 0 is the mirror, which is unused by the native. It exists
   // because this native is an instance method in order to be polymorphic
@@ -1278,7 +1262,7 @@
       // In the case of extension methods also we avoid handing out a reference
       // to the tear-off and instead get the parent function of the
       // anonymous closure.
-      function = parent.raw();
+      function = parent.ptr();
     }
 
     Type& instantiator = Type::Handle();
@@ -1289,9 +1273,9 @@
       // The 'instantiator' created below should not be a type, but two type
       // argument vectors: instantiator_type_arguments and
       // function_type_arguments.
-      const Class& cls =
-          Class::Handle(Isolate::Current()->object_store()->object_class());
-      instantiator = Type::New(cls, arguments, TokenPosition::kNoSource);
+      const Class& cls = Class::Handle(
+          IsolateGroup::Current()->object_store()->object_class());
+      instantiator = Type::New(cls, arguments);
       instantiator.SetIsFinalized();
     }
     return CreateMethodMirror(function, Instance::null_instance(),
@@ -1360,20 +1344,20 @@
   // unnamed constructor for class 'A' is labeled 'A.'.
   // This convention prevents users from explicitly calling constructors.
   const String& klass_name = String::Handle(klass.Name());
-  String& external_constructor_name = String::Handle(klass_name.raw());
+  String& external_constructor_name = String::Handle(klass_name.ptr());
   String& internal_constructor_name =
       String::Handle(String::Concat(klass_name, Symbols::Dot()));
   if (!constructor_name.IsNull() && constructor_name.Length() > 0) {
     internal_constructor_name =
         String::Concat(internal_constructor_name, constructor_name);
-    external_constructor_name = internal_constructor_name.raw();
+    external_constructor_name = internal_constructor_name.ptr();
   }
 
   Function& lookup_constructor = Function::Handle(
       Resolver::ResolveFunction(zone, klass, internal_constructor_name));
 
   if (lookup_constructor.IsNull() ||
-      (lookup_constructor.kind() != FunctionLayout::kConstructor) ||
+      (lookup_constructor.kind() != UntaggedFunction::kConstructor) ||
       !lookup_constructor.is_reflectable()) {
     ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
                       external_constructor_name, explicit_args, arg_names,
@@ -1401,7 +1385,7 @@
     type_arguments = rare_type.arguments();
   }
 
-  Class& redirected_klass = Class::Handle(klass.raw());
+  Class& redirected_klass = Class::Handle(klass.ptr());
   const intptr_t num_explicit_args = explicit_args.Length();
   const intptr_t num_implicit_args = 1;
   const Array& args =
@@ -1471,9 +1455,9 @@
   ASSERT(result.IsInstance() || result.IsNull());
 
   if (lookup_constructor.IsGenerativeConstructor()) {
-    return new_object.raw();
+    return new_object.ptr();
   } else {
-    return result.raw();
+    return result.ptr();
   }
 }
 
@@ -1532,7 +1516,8 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, owner, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
   const Function& func = Function::Handle(ref.GetFunctionReferent());
-  return CreateParameterMirrorList(func, owner);
+  const FunctionType& sig = FunctionType::Handle(func.signature());
+  return CreateParameterMirrorList(func, sig, owner);
 }
 
 DEFINE_NATIVE_ENTRY(MethodMirror_return_type, 0, 2) {
@@ -1570,7 +1555,7 @@
     const MirrorReference& decl_ref = MirrorReference::Cast(reflectee);
     decl = decl_ref.referent();
   } else if (reflectee.IsTypeParameter()) {
-    decl = reflectee.raw();
+    decl = reflectee.ptr();
   } else {
     UNREACHABLE();
   }
@@ -1580,7 +1565,7 @@
 
   if (decl.IsFunction()) {
     const Function& func = Function::Cast(decl);
-    if (func.IsImplicitConstructor() || func.IsSignatureFunction()) {
+    if (func.IsImplicitConstructor()) {
       // These are synthetic methods; they have no source.
       return Instance::null();
     }
@@ -1588,8 +1573,7 @@
     token_pos = func.token_pos();
   } else if (decl.IsClass()) {
     const Class& cls = Class::Cast(decl);
-    const bool is_typedef = cls.IsTypedefClass();
-    if (cls.is_synthesized_class() && !is_typedef && !cls.is_enum_class()) {
+    if (cls.is_synthesized_class() && !cls.is_enum_class()) {
       return Instance::null();  // Synthetic.
     }
     script = cls.script();
@@ -1599,17 +1583,10 @@
     script = field.Script();
     token_pos = field.token_pos();
   } else if (decl.IsTypeParameter()) {
-    const TypeParameter& type_var = TypeParameter::Cast(decl);
-    if (type_var.IsFunctionTypeParameter()) {
-      // TODO(regis): Support generic functions.
-      return Instance::null();
-    }
-    const Class& owner = Class::Handle(zone, type_var.parameterized_class());
-    script = owner.script();
-    token_pos = type_var.token_pos();
+    return Instance::null();
   } else if (decl.IsLibrary()) {
     const Library& lib = Library::Cast(decl);
-    if (lib.raw() == Library::NativeWrappersLibrary()) {
+    if (lib.ptr() == Library::NativeWrappersLibrary()) {
       return Instance::null();  // No source.
     }
     const Array& scripts = Array::Handle(zone, lib.LoadedScripts());
@@ -1628,39 +1605,19 @@
   }
 
   const String& uri = String::Handle(zone, script.url());
-  intptr_t from_line = 0;
-  intptr_t from_col = 0;
-  if (script.HasSource()) {
-    script.GetTokenLocation(token_pos, &from_line, &from_col);
-  } else {
-    // Avoid the slow path of printing the token stream when precise source
-    // information is not available.
-    script.GetTokenLocation(token_pos, &from_line, NULL);
-  }
-  // We should always have at least the line number.
-  ASSERT(from_line != 0);
+  intptr_t from_line = 0, from_col = 0;
+  script.GetTokenLocation(token_pos, &from_line, &from_col);
   return CreateSourceLocation(uri, from_line, from_col);
 }
 
-DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 0, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
-  ASSERT(type.IsFunctionType());
-  const Class& cls = Class::Handle(type.type_class());
-  ASSERT(cls.IsTypedefClass());
-  const Function& sig_func = Function::Handle(cls.signature_function());
-  Type& referent_type = Type::Handle(sig_func.SignatureType());
-  ASSERT(cls.raw() == referent_type.type_class());
-  referent_type ^= InstantiateType(referent_type, type);
-  return CreateFunctionTypeMirror(referent_type);
-}
-
 DEFINE_NATIVE_ENTRY(ParameterMirror_type, 0, 3) {
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, pos, arguments->NativeArgAt(1));
   GET_NATIVE_ARGUMENT(AbstractType, instantiator, arguments->NativeArgAt(2));
-  const Function& func = Function::Handle(ref.GetFunctionReferent());
-  AbstractType& type = AbstractType::Handle(
-      func.ParameterTypeAt(func.NumImplicitParameters() + pos.Value()));
+  const FunctionType& signature =
+      FunctionType::Handle(ref.GetFunctionTypeReferent());
+  AbstractType& type = AbstractType::Handle(signature.ParameterTypeAt(
+      signature.num_implicit_parameters() + pos.Value()));
   type = type.Canonicalize(
       thread, nullptr);  // Instantiated signatures are not canonical.
   return InstantiateType(type, instantiator);
@@ -1677,7 +1634,7 @@
 DEFINE_NATIVE_ENTRY(TypeMirror_subtypeTest, 0, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
-  return Bool::Get(a.IsSubtypeOf(b, Heap::kNew)).raw();
+  return Bool::Get(a.IsSubtypeOf(b, Heap::kNew)).ptr();
 }
 
 #endif  // !DART_PRECOMPILED_RUNTIME
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index cf1e6ff..103983e 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -40,7 +40,7 @@
 #if defined(HASH_IN_OBJECT_HEADER)
   return Smi::New(Object::GetCachedHash(arguments->NativeArgAt(0)));
 #else
-  Heap* heap = isolate->heap();
+  Heap* heap = isolate->group()->heap();
   ASSERT(arguments->NativeArgAt(0)->IsDartInstance());
   return Smi::New(heap->GetHash(arguments->NativeArgAt(0)));
 #endif
@@ -53,8 +53,8 @@
 #else
   const Instance& instance =
       Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
-  Heap* heap = isolate->heap();
-  heap->SetHash(instance.raw(), hash.Value());
+  Heap* heap = isolate->group()->heap();
+  heap->SetHash(instance.ptr(), hash.Value());
 #endif
   return Object::null();
 }
@@ -63,7 +63,7 @@
   const Instance& instance =
       Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
   if (instance.IsString()) {
-    return instance.raw();
+    return instance.ptr();
   }
   if (instance.IsAbstractType()) {
     return AbstractType::Cast(instance).UserVisibleName();
@@ -81,6 +81,8 @@
     return Type::IntType();
   } else if (instance.IsDouble()) {
     return Type::Double();
+  } else if (instance.IsType() || instance.IsFunctionType()) {
+    return Type::DartTypeType();
   }
   return instance.GetType(Heap::kNew);
 }
@@ -96,11 +98,13 @@
 
   if (left_cid != right_cid) {
     if (IsIntegerClassId(left_cid)) {
-      return Bool::Get(IsIntegerClassId(right_cid)).raw();
-    } else if (IsStringClassId(right_cid)) {
-      return Bool::Get(IsStringClassId(right_cid)).raw();
+      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().raw();
+      return Bool::False().ptr();
     }
   }
 
@@ -113,15 +117,15 @@
         AbstractType::Handle(right.GetType(Heap::kNew));
     return Bool::Get(
                left_type.IsEquivalent(right_type, TypeEquality::kSyntactical))
-        .raw();
+        .ptr();
   }
 
   if (!cls.IsGeneric()) {
-    return Bool::True().raw();
+    return Bool::True().ptr();
   }
 
   if (left.GetTypeArguments() == right.GetTypeArguments()) {
-    return Bool::True().raw();
+    return Bool::True().ptr();
   }
   const TypeArguments& left_type_arguments =
       TypeArguments::Handle(left.GetTypeArguments());
@@ -132,7 +136,7 @@
   return Bool::Get(left_type_arguments.IsSubvectorEquivalent(
                        right_type_arguments, num_type_args - num_type_params,
                        num_type_params, TypeEquality::kSyntactical))
-      .raw();
+      .ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Object_instanceOf, 0, 4) {
@@ -157,7 +161,7 @@
     OS::PrintErr("  test type: %s\n",
                  String::Handle(zone, type.Name()).ToCString());
   }
-  return Bool::Get(is_instance_of).raw();
+  return Bool::Get(is_instance_of).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Object_simpleInstanceOf, 0, 2) {
@@ -171,7 +175,7 @@
   ASSERT(type.IsInstantiated());
   const bool is_instance_of = instance.IsInstanceOf(
       type, Object::null_type_arguments(), Object::null_type_arguments());
-  return Bool::Get(is_instance_of).raw();
+  return Bool::Get(is_instance_of).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(AbstractType_toString, 0, 1) {
@@ -192,16 +196,36 @@
   const Type& type = Type::CheckedHandle(zone, arguments->NativeArgAt(0));
   const Instance& other =
       Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
-  if (type.raw() == other.raw()) {
-    return Bool::True().raw();
+  if (type.ptr() == other.ptr()) {
+    return Bool::True().ptr();
   }
-  return Bool::Get(type.IsEquivalent(other, TypeEquality::kSyntactical)).raw();
+  return Bool::Get(type.IsEquivalent(other, TypeEquality::kSyntactical)).ptr();
+}
+
+DEFINE_NATIVE_ENTRY(FunctionType_getHashCode, 0, 1) {
+  const FunctionType& type =
+      FunctionType::CheckedHandle(zone, arguments->NativeArgAt(0));
+  intptr_t hash_val = type.Hash();
+  ASSERT(hash_val > 0);
+  ASSERT(Smi::IsValid(hash_val));
+  return Smi::New(hash_val);
+}
+
+DEFINE_NATIVE_ENTRY(FunctionType_equality, 0, 2) {
+  const FunctionType& type =
+      FunctionType::CheckedHandle(zone, arguments->NativeArgAt(0));
+  const Instance& other =
+      Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
+  if (type.ptr() == other.ptr()) {
+    return Bool::True().ptr();
+  }
+  return Bool::Get(type.IsEquivalent(other, TypeEquality::kSyntactical)).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(LibraryPrefix_isLoaded, 0, 1) {
   const LibraryPrefix& prefix =
       LibraryPrefix::CheckedHandle(zone, arguments->NativeArgAt(0));
-  return Bool::Get(prefix.is_loaded()).raw();
+  return Bool::Get(prefix.is_loaded()).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(LibraryPrefix_setLoaded, 0, 1) {
@@ -221,7 +245,8 @@
 
 DEFINE_NATIVE_ENTRY(LibraryPrefix_issueLoad, 0, 1) {
   const Smi& id = Smi::CheckedHandle(zone, arguments->NativeArgAt(0));
-  Array& units = Array::Handle(zone, isolate->object_store()->loading_units());
+  Array& units =
+      Array::Handle(zone, isolate->group()->object_store()->loading_units());
   if (units.IsNull()) {
     // Not actually split.
     const Library& lib = Library::Handle(zone, Library::CoreLibrary());
@@ -243,9 +268,9 @@
 
 DEFINE_NATIVE_ENTRY(Internal_inquireIs64Bit, 0, 0) {
 #if defined(ARCH_IS_64_BIT)
-  return Bool::True().raw();
+  return Bool::True().ptr();
 #else
-  return Bool::False().raw();
+  return Bool::False().ptr();
 #endif  // defined(ARCH_IS_64_BIT)
 }
 
@@ -259,7 +284,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Internal_collectAllGarbage, 0, 0) {
-  isolate->heap()->CollectAllGarbage();
+  isolate->group()->heap()->CollectAllGarbage();
   return Object::null();
 }
 
@@ -268,7 +293,7 @@
                                      const TypeArguments& instance_type_args,
                                      const Class& interface_cls,
                                      TypeArguments* interface_type_args) {
-  Class& cur_cls = Class::Handle(zone, instance_cls.raw());
+  Class& cur_cls = Class::Handle(zone, instance_cls.ptr());
   // The following code is a specialization of Class::IsSubtypeOf().
   Array& interfaces = Array::Handle(zone);
   AbstractType& interface = AbstractType::Handle(zone);
@@ -276,8 +301,8 @@
   TypeArguments& cur_interface_type_args = TypeArguments::Handle(zone);
   while (true) {
     // Additional subtyping rules related to 'FutureOr' are not applied.
-    if (cur_cls.raw() == interface_cls.raw()) {
-      *interface_type_args = instance_type_args.raw();
+    if (cur_cls.ptr() == interface_cls.ptr()) {
+      *interface_type_args = instance_type_args.ptr();
       return true;
     }
     interfaces = cur_cls.interfaces();
@@ -390,7 +415,7 @@
     Exceptions::PropagateError(Error::Cast(result));
     UNREACHABLE();
   }
-  return result.raw();
+  return result.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Internal_prependTypeArguments, 0, 4) {
@@ -437,7 +462,7 @@
   for (intptr_t i = 0; i < bounds.Length(); ++i) {
     parameter ^= bounds.TypeAt(i);
     supertype = parameter.bound();
-    subtype = type_args_to_check.IsNull() ? Object::dynamic_type().raw()
+    subtype = type_args_to_check.IsNull() ? Object::dynamic_type().ptr()
                                           : type_args_to_check.TypeAt(i);
 
     ASSERT(!subtype.IsNull());
@@ -447,7 +472,7 @@
     if (!AbstractType::InstantiateAndTestSubtype(
             &subtype, &supertype, instantiator_type_args, function_type_args)) {
       // Throw a dynamic type error.
-      TokenPosition location;
+      TokenPosition location = TokenPosition::kNoSource;
       {
         DartFrameIterator iterator(Thread::Current(),
                                    StackFrameIterator::kNoCrossThreadIteration);
@@ -485,7 +510,7 @@
     }
   }
   type_list.MakeImmutable();
-  return type_list.raw();
+  return type_list.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(NoSuchMethodError_existingMethodSignature, 0, 3) {
diff --git a/runtime/lib/profiler.cc b/runtime/lib/profiler.cc
index 3d6d84e..956597a 100644
--- a/runtime/lib/profiler.cc
+++ b/runtime/lib/profiler.cc
@@ -34,7 +34,7 @@
   }
   const UserTag& old = UserTag::Handle(zone, isolate->current_tag());
   self.MakeActive();
-  return old.raw();
+  return old.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(UserTag_defaultTag, 0, 0) {
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 57aa72a..3e0e337 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -29,10 +29,10 @@
                                arguments->NativeArgAt(4));
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, handle_dot_all,
                                arguments->NativeArgAt(5));
-  bool ignore_case = handle_case_sensitive.raw() != Bool::True().raw();
-  bool multi_line = handle_multi_line.raw() == Bool::True().raw();
-  bool unicode = handle_unicode.raw() == Bool::True().raw();
-  bool dot_all = handle_dot_all.raw() == Bool::True().raw();
+  bool ignore_case = handle_case_sensitive.ptr() != Bool::True().ptr();
+  bool multi_line = handle_multi_line.ptr() == Bool::True().ptr();
+  bool unicode = handle_unicode.ptr() == Bool::True().ptr();
+  bool dot_all = handle_dot_all.ptr() == Bool::True().ptr();
 
   RegExpFlags flags;
 
@@ -60,25 +60,25 @@
 DEFINE_NATIVE_ENTRY(RegExp_getIsMultiLine, 0, 1) {
   const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
-  return Bool::Get(regexp.flags().IsMultiLine()).raw();
+  return Bool::Get(regexp.flags().IsMultiLine()).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getIsUnicode, 0, 1) {
   const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
-  return Bool::Get(regexp.flags().IsUnicode()).raw();
+  return Bool::Get(regexp.flags().IsUnicode()).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getIsDotAll, 0, 1) {
   const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
-  return Bool::Get(regexp.flags().IsDotAll()).raw();
+  return Bool::Get(regexp.flags().IsDotAll()).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getIsCaseSensitive, 0, 1) {
   const RegExp& regexp = RegExp::CheckedHandle(zone, arguments->NativeArgAt(0));
   ASSERT(!regexp.IsNull());
-  return Bool::Get(!regexp.flags().IgnoreCase()).raw();
+  return Bool::Get(!regexp.flags().IgnoreCase()).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(RegExp_getGroupCount, 0, 1) {
diff --git a/runtime/lib/simd128.cc b/runtime/lib/simd128.cc
index e5983b3..9adf5c3 100644
--- a/runtime/lib/simd128.cc
+++ b/runtime/lib/simd128.cc
@@ -550,25 +550,25 @@
 DEFINE_NATIVE_ENTRY(Int32x4_getFlagX, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, self, arguments->NativeArgAt(0));
   int32_t value = self.x();
-  return Bool::Get(value != 0).raw();
+  return Bool::Get(value != 0).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Int32x4_getFlagY, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, self, arguments->NativeArgAt(0));
   int32_t value = self.y();
-  return Bool::Get(value != 0).raw();
+  return Bool::Get(value != 0).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Int32x4_getFlagZ, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, self, arguments->NativeArgAt(0));
   int32_t value = self.z();
-  return Bool::Get(value != 0).raw();
+  return Bool::Get(value != 0).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Int32x4_getFlagW, 0, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, self, arguments->NativeArgAt(0));
   int32_t value = self.w();
-  return Bool::Get(value != 0).raw();
+  return Bool::Get(value != 0).ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Int32x4_setFlagX, 0, 2) {
@@ -578,7 +578,7 @@
   int32_t _y = self.y();
   int32_t _z = self.z();
   int32_t _w = self.w();
-  _x = flagX.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+  _x = flagX.ptr() == Bool::True().ptr() ? 0xFFFFFFFF : 0x0;
   return Int32x4::New(_x, _y, _z, _w);
 }
 
@@ -589,7 +589,7 @@
   int32_t _y = self.y();
   int32_t _z = self.z();
   int32_t _w = self.w();
-  _y = flagY.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+  _y = flagY.ptr() == Bool::True().ptr() ? 0xFFFFFFFF : 0x0;
   return Int32x4::New(_x, _y, _z, _w);
 }
 
@@ -600,7 +600,7 @@
   int32_t _y = self.y();
   int32_t _z = self.z();
   int32_t _w = self.w();
-  _z = flagZ.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+  _z = flagZ.ptr() == Bool::True().ptr() ? 0xFFFFFFFF : 0x0;
   return Int32x4::New(_x, _y, _z, _w);
 }
 
@@ -611,7 +611,7 @@
   int32_t _y = self.y();
   int32_t _z = self.z();
   int32_t _w = self.w();
-  _w = flagW.raw() == Bool::True().raw() ? 0xFFFFFFFF : 0x0;
+  _w = flagW.ptr() == Bool::True().ptr() ? 0xFFFFFFFF : 0x0;
   return Int32x4::New(_x, _y, _z, _w);
 }
 
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 170bc96..4e1fc80 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -25,7 +25,7 @@
   if (!env_value.IsNull()) {
     return Symbols::New(thread, env_value);
   }
-  return default_value.raw();
+  return default_value.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 0, 3) {
@@ -40,7 +40,7 @@
     a = growableArray.data();
     length = growableArray.Length();
   } else if (list.IsArray()) {
-    a = Array::Cast(list).raw();
+    a = Array::Cast(list).ptr();
     length = a.Length();
   } else {
     Exceptions::ThrowArgumentError(list);
@@ -242,7 +242,7 @@
   if (write_index < length) {
     Exceptions::ThrowArgumentError(matches_growable);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(OneByteString_substringUnchecked, 0, 3) {
@@ -282,8 +282,8 @@
                                           Heap::kNew);
   result.Add(str);
   result.SetTypeArguments(TypeArguments::Handle(
-      zone, isolate->object_store()->type_argument_string()));
-  return result.raw();
+      zone, isolate->group()->object_store()->type_argument_string()));
+  return result.ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Internal_allocateOneByteString, 0, 1) {
@@ -292,8 +292,8 @@
   if ((length < 0) || (length > OneByteString::kMaxElements)) {
     // Assume that negative lengths are the result of wrapping in code in
     // string_patch.dart.
-    const Instance& exception =
-        Instance::Handle(thread->isolate()->object_store()->out_of_memory());
+    const Instance& exception = Instance::Handle(
+        thread->isolate_group()->object_store()->out_of_memory());
     Exceptions::Throw(thread, exception);
     UNREACHABLE();
   }
@@ -306,8 +306,8 @@
   if ((length < 0) || (length > TwoByteString::kMaxElements)) {
     // Assume that negative lengths are the result of wrapping in code in
     // string_patch.dart.
-    const Instance& exception =
-        Instance::Handle(thread->isolate()->object_store()->out_of_memory());
+    const Instance& exception = Instance::Handle(
+        thread->isolate_group()->object_store()->out_of_memory());
     Exceptions::Throw(thread, exception);
     UNREACHABLE();
   }
@@ -379,7 +379,7 @@
       intptr_t value = Smi::Value(static_cast<SmiPtr>(array.At(start + i)));
       OneByteString::SetCharAt(string, i, value);
     }
-    return string.raw();
+    return string.ptr();
   } else if (list.IsGrowableObjectArray()) {
     const GrowableObjectArray& array = GrowableObjectArray::Cast(list);
     if (end > array.Length()) {
@@ -392,7 +392,7 @@
       intptr_t value = Smi::Value(static_cast<SmiPtr>(array.At(start + i)));
       OneByteString::SetCharAt(string, i, value);
     }
-    return string.raw();
+    return string.ptr();
   }
   UNREACHABLE();
   return Object::null();
@@ -483,7 +483,7 @@
       intptr_t value = Smi::Value(static_cast<SmiPtr>(array.At(start + i)));
       TwoByteString::SetCharAt(string, i, value);
     }
-    return string.raw();
+    return string.ptr();
   } else if (list.IsGrowableObjectArray()) {
     const GrowableObjectArray& array = GrowableObjectArray::Cast(list);
     if (end > array.Length()) {
@@ -495,7 +495,7 @@
       intptr_t value = Smi::Value(static_cast<SmiPtr>(array.At(start + i)));
       TwoByteString::SetCharAt(string, i, value);
     }
-    return string.raw();
+    return string.ptr();
   }
   UNREACHABLE();
   return Object::null();
@@ -579,7 +579,7 @@
   Array& strings = Array::Handle();
   intptr_t length = -1;
   if (argument.IsArray()) {
-    strings ^= argument.raw();
+    strings ^= argument.ptr();
     length = strings.Length();
   } else if (argument.IsGrowableObjectArray()) {
     const GrowableObjectArray& g_array = GrowableObjectArray::Cast(argument);
@@ -619,7 +619,7 @@
 
   uint16_t* data_position = reinterpret_cast<uint16_t*>(codeUnits.DataAddr(0));
   String::Copy(result, 0, data_position, length_value);
-  return result.raw();
+  return result.ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/lib/timeline.cc b/runtime/lib/timeline.cc
index 12c0c68..0b3816c 100644
--- a/runtime/lib/timeline.cc
+++ b/runtime/lib/timeline.cc
@@ -18,10 +18,10 @@
 DEFINE_NATIVE_ENTRY(Timeline_isDartStreamEnabled, 0, 0) {
 #if defined(SUPPORT_TIMELINE)
   if (Timeline::GetDartStream()->enabled()) {
-    return Bool::True().raw();
+    return Bool::True().ptr();
   }
 #endif
-  return Bool::False().raw();
+  return Bool::False().ptr();
 }
 
 DEFINE_NATIVE_ENTRY(Timeline_getNextAsyncId, 0, 0) {
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index d71d08e..28d9331 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -108,7 +108,7 @@
     TypedData::Copy<DstType, SrcType>(dst_array, dst_offset_in_bytes, src_array,
                                       src_offset_in_bytes, length_in_bytes);
   }
-  return Bool::True().raw();
+  return Bool::True().ptr();
 }
 
 static bool IsClamped(intptr_t cid) {
@@ -174,7 +174,7 @@
     }
   }
   UNREACHABLE();
-  return Bool::False().raw();
+  return Bool::False().ptr();
 }
 
 // Native methods for typed data allocation are recognized and implemented
diff --git a/runtime/lib/uri.cc b/runtime/lib/uri.cc
index 4f1ef81..af4c65d 100644
--- a/runtime/lib/uri.cc
+++ b/runtime/lib/uri.cc
@@ -10,9 +10,9 @@
 
 DEFINE_NATIVE_ENTRY(Uri_isWindowsPlatform, 0, 0) {
 #if defined(HOST_OS_WINDOWS)
-  return Bool::True().raw();
+  return Bool::True().ptr();
 #else
-  return Bool::False().raw();
+  return Bool::False().ptr();
 #endif
 }
 
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 8ffecd6..c42fa15 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -55,7 +55,7 @@
   // TODO(turnidge): Throw an exception when the return value is false?
   bool result = PortMap::PostMessage(
       writer.WriteMessage(message, sp.Id(), Message::kOOBPriority));
-  return Bool::Get(result).raw();
+  return Bool::Get(result).ptr();
 #else
   return Object::null();
 #endif
@@ -122,7 +122,7 @@
 #ifndef PRODUCT
   GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
   bool result = Service::ListenStream(stream_id.ToCString());
-  return Bool::Get(result).raw();
+  return Bool::Get(result).ptr();
 #else
   return Object::null();
 #endif
@@ -323,7 +323,7 @@
 #ifndef PRODUCT
   GET_NON_NULL_NATIVE_ARGUMENT(TypedData, data, arguments->NativeArgAt(0));
   Api::Scope scope(thread);
-  Dart_Handle data_handle = Api::NewHandle(thread, data.raw());
+  Dart_Handle data_handle = Api::NewHandle(thread, data.ptr());
   Dart_Handle result_list;
   {
     TransitionVMToNative transition(thread);
@@ -368,7 +368,7 @@
       idx += 2;
     }
   }
-  return Api::UnwrapArrayHandle(thread->zone(), result_list).raw();
+  return Api::UnwrapArrayHandle(thread->zone(), result_list).ptr();
 #else
   return Object::null();
 #endif
diff --git a/runtime/observatory/BUILD.gn b/runtime/observatory/BUILD.gn
index 360863c..022498e 100644
--- a/runtime/observatory/BUILD.gn
+++ b/runtime/observatory/BUILD.gn
@@ -37,7 +37,6 @@
     "-o",
     rebase_path(output),
     "--packages=" + rebase_path("../../.packages"),
-    "--enable-experiment=non-nullable",
     "--no-sound-null-safety",
   ]
   if (is_debug) {
diff --git a/runtime/observatory/analysis_options.yaml b/runtime/observatory/analysis_options.yaml
index f9cf4b3..e579874 100644
--- a/runtime/observatory/analysis_options.yaml
+++ b/runtime/observatory/analysis_options.yaml
@@ -1,7 +1,4 @@
 analyzer:
-  enable-experiment:
-    - non-nullable
-
   errors:
     dead_code: info
     getter_not_subtype_setter_types: info
diff --git a/runtime/observatory/lib/app.dart b/runtime/observatory/lib/app.dart
index ee1640b..8b3742f 100644
--- a/runtime/observatory/lib/app.dart
+++ b/runtime/observatory/lib/app.dart
@@ -18,7 +18,6 @@
 import 'package:observatory/tracer.dart';
 import 'package:observatory/utils.dart';
 import 'package:stack_trace/stack_trace.dart';
-import 'package:usage/usage_html.dart';
 
 export 'package:observatory/utils.dart';
 
diff --git a/runtime/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart
index b1b3654..f4ecbfc 100644
--- a/runtime/observatory/lib/src/elements/function_view.dart
+++ b/runtime/observatory/lib/src/elements/function_view.dart
@@ -424,8 +424,6 @@
         return 'stub';
       case M.FunctionKind.tag:
         return 'tag';
-      case M.FunctionKind.signatureFunction:
-        return 'signature function';
       case M.FunctionKind.dynamicInvocationForwarder:
         return 'dynamic invocation forwarder';
     }
diff --git a/runtime/observatory/lib/src/elements/instance_ref.dart b/runtime/observatory/lib/src/elements/instance_ref.dart
index d92d2b9..389350a 100644
--- a/runtime/observatory/lib/src/elements/instance_ref.dart
+++ b/runtime/observatory/lib/src/elements/instance_ref.dart
@@ -125,6 +125,7 @@
                 _instance.valueAsString!, _instance.valueAsStringIsTruncated!)
         ];
       case M.InstanceKind.type:
+      case M.InstanceKind.functionType:
       case M.InstanceKind.typeRef:
       case M.InstanceKind.typeParameter:
         return [
diff --git a/runtime/observatory/lib/src/models/objects/field.dart b/runtime/observatory/lib/src/models/objects/field.dart
index c063238..91c4a05 100644
--- a/runtime/observatory/lib/src/models/objects/field.dart
+++ b/runtime/observatory/lib/src/models/objects/field.dart
@@ -15,7 +15,7 @@
   /// The declared type of this field.
   ///
   /// The value will always be of one of the kinds:
-  /// Type, TypeRef, TypeParameter.
+  /// Type, FunctionType, TypeRef, TypeParameter.
   InstanceRef? get declaredType;
 
   /// Is this field const?
diff --git a/runtime/observatory/lib/src/models/objects/function.dart b/runtime/observatory/lib/src/models/objects/function.dart
index e63ef40..4637d27 100644
--- a/runtime/observatory/lib/src/models/objects/function.dart
+++ b/runtime/observatory/lib/src/models/objects/function.dart
@@ -24,7 +24,6 @@
   ffiTrampoline,
   stub,
   tag,
-  signatureFunction,
   dynamicInvocationForwarder
 }
 
diff --git a/runtime/observatory/lib/src/models/objects/instance.dart b/runtime/observatory/lib/src/models/objects/instance.dart
index a0400c5..8102095 100644
--- a/runtime/observatory/lib/src/models/objects/instance.dart
+++ b/runtime/observatory/lib/src/models/objects/instance.dart
@@ -115,6 +115,9 @@
   /// An instance of the Dart class Type.
   type,
 
+  /// An instance of the Dart class FunctionType.
+  functionType,
+
   /// An instance of the Dart class TypeParameter.
   typeParameter,
 
@@ -170,6 +173,7 @@
   }
   switch (kind) {
     case InstanceKind.type:
+    case InstanceKind.functionType:
     case InstanceKind.typeRef:
     case InstanceKind.typeParameter:
       return true;
@@ -387,7 +391,7 @@
   /// [optional] The referent of a TypeRef instance.
   ///
   /// The value will always be of one of the kinds:
-  /// Type, TypeRef, TypeParameter.
+  /// Type, FunctionType, TypeRef, TypeParameter.
   ///
   /// Provided for instance kinds:
   ///   TypeRef
@@ -396,7 +400,7 @@
   /// [optional] The bound of a TypeParameter.
   ///
   /// The value will always be of one of the kinds:
-  /// Type, TypeRef, TypeParameter.
+  /// Type, FunctionType, TypeRef, TypeParameter.
   ///
   /// Provided for instance kinds:
   ///   TypeParameter
diff --git a/runtime/observatory/lib/src/models/objects/type_arguments.dart b/runtime/observatory/lib/src/models/objects/type_arguments.dart
index ffe2186..a8dc134 100644
--- a/runtime/observatory/lib/src/models/objects/type_arguments.dart
+++ b/runtime/observatory/lib/src/models/objects/type_arguments.dart
@@ -13,6 +13,6 @@
   /// A list of types.
   ///
   /// The value will always be one of the kinds:
-  /// Type, TypeRef, TypeParameter.
+  /// Type, FunctionType, TypeRef, TypeParameter.
   Iterable<InstanceRef>? get types;
 }
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 63ec9c4..759d854 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -2747,6 +2747,8 @@
       return M.InstanceKind.weakProperty;
     case 'Type':
       return M.InstanceKind.type;
+    case 'FunctionType':
+      return M.InstanceKind.functionType;
     case 'TypeParameter':
       return M.InstanceKind.typeParameter;
     case 'TypeRef':
@@ -3118,8 +3120,6 @@
       return M.FunctionKind.stub;
     case 'Tag':
       return M.FunctionKind.tag;
-    case 'SignatureFunction':
-      return M.FunctionKind.signatureFunction;
     case 'DynamicInvocationForwarder':
       return M.FunctionKind.dynamicInvocationForwarder;
   }
diff --git a/runtime/observatory/lib/utils.dart b/runtime/observatory/lib/utils.dart
index 940a6e1..a23dc64 100644
--- a/runtime/observatory/lib/utils.dart
+++ b/runtime/observatory/lib/utils.dart
@@ -98,24 +98,25 @@
 
   static String formatSize(bytesDynamic) {
     int bytes = bytesDynamic.toInt();
-    int absBytes = bytes >= 0 ? bytes : -bytes;
-    const int digits = 1;
+
+    String finish(int scale, String prefix) {
+      double scaled = bytes / scale;
+      int digits = 1;
+      if (scaled < 10) digits = 2;
+      return "${scaled.toStringAsFixed(digits)}${prefix}B";
+    }
+
     const int bytesPerKB = 1024;
     const int bytesPerMB = 1024 * bytesPerKB;
     const int bytesPerGB = 1024 * bytesPerMB;
     const int bytesPerTB = 1024 * bytesPerGB;
 
-    if (absBytes < bytesPerKB) {
-      return "${bytes}B";
-    } else if (absBytes < bytesPerMB) {
-      return "${(bytes / bytesPerKB).toStringAsFixed(digits)}KB";
-    } else if (absBytes < bytesPerGB) {
-      return "${(bytes / bytesPerMB).toStringAsFixed(digits)}MB";
-    } else if (absBytes < bytesPerTB) {
-      return "${(bytes / bytesPerGB).toStringAsFixed(digits)}GB";
-    } else {
-      return "${(bytes / bytesPerTB).toStringAsFixed(digits)}TB";
-    }
+    int absBytes = bytes >= 0 ? bytes : -bytes;
+    if (absBytes < bytesPerKB) return "${bytes}B";
+    if (absBytes < bytesPerMB) return finish(bytesPerKB, "K");
+    if (absBytes < bytesPerGB) return finish(bytesPerMB, "M");
+    if (absBytes < bytesPerTB) return finish(bytesPerGB, "G");
+    return finish(bytesPerTB, "TB");
   }
 
   static String formatTime(double time) {
diff --git a/runtime/observatory/pubspec.yaml b/runtime/observatory/pubspec.yaml
index ba282ab..ddf5b9c 100644
--- a/runtime/observatory/pubspec.yaml
+++ b/runtime/observatory/pubspec.yaml
@@ -1,6 +1,6 @@
 name: observatory
 environment:
-  sdk: '>=2.10.0 <3.0.0'
+  sdk: '>=2.12.0-0 <3.0.0'
 
 dependencies:
   usage: 'any'
diff --git a/runtime/observatory/tests/service/async_generator_breakpoint_test.dart b/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
index 44f5c2a..b607ea8 100644
--- a/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
+++ b/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
@@ -53,15 +53,19 @@
   var script = isolate.rootLibrary.scripts[0];
 
   var bp1 = await isolate.addBreakpoint(script, 13);
+  print("BP1 - $bp1");
   expect(bp1, isNotNull);
   expect(bp1 is Breakpoint, isTrue);
   var bp2 = await isolate.addBreakpoint(script, 18);
+  print("BP2 - $bp2");
   expect(bp2, isNotNull);
   expect(bp2 is Breakpoint, isTrue);
   var bp3 = await isolate.addBreakpoint(script, 23);
+  print("BP3 - $bp3");
   expect(bp3, isNotNull);
   expect(bp3 is Breakpoint, isTrue);
   var bp4 = await isolate.addBreakpoint(script, 27);
+  print("BP4 - $bp4");
   expect(bp4, isNotNull);
   expect(bp4 is Breakpoint, isTrue);
   var bp5 = await isolate.addBreakpoint(script, 44);
diff --git a/runtime/observatory/tests/service/async_single_step_out_test.dart b/runtime/observatory/tests/service/async_single_step_out_test.dart
index cfeac6c..3c6de1b 100644
--- a/runtime/observatory/tests/service/async_single_step_out_test.dart
+++ b/runtime/observatory/tests/service/async_single_step_out_test.dart
@@ -44,6 +44,10 @@
   stepInto, // exit helper via a single step.
 
   hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B), // await helper
+  stepInto,
+
+  hasStoppedAtBreakpoint,
   stoppedAtLine(20), // return null (weird dispatching)
   stepInto, // exit helper via a single step.
 
diff --git a/runtime/observatory/tests/service/dds_disconnects_existing_clients_test.dart b/runtime/observatory/tests/service/dds_disconnects_existing_clients_test.dart
new file mode 100644
index 0000000..584b1cc
--- /dev/null
+++ b/runtime/observatory/tests/service/dds_disconnects_existing_clients_test.dart
@@ -0,0 +1,61 @@
+// 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:observatory/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+final tests = <VMTest>[
+  (VM vm) async {
+    late DartDevelopmentService dds;
+    final waitForDDS = Completer<void>();
+    final serviceMessageCompleter = Completer<void>();
+
+    // The original VM service client is connected.
+    expect(vm.isConnected, true);
+
+    // A service event is sent to all existing clients when DDS connects before
+    // their connection is closed.
+    await vm.listenEventStream('Service', (ServiceEvent event) async {
+      // Wait for dds to be set before checking the server's URI.
+      await waitForDDS.future;
+      final message =
+          'A Dart Developer Service instance has connected and this direct '
+          'connection to the VM service will now be closed. Please reconnect to '
+          'the Dart Development Service at ${dds.uri}.';
+      expect(event.kind, ServiceEvent.kDartDevelopmentServiceConnected);
+      expect(event.message, message);
+      expect(event.uri, dds.uri);
+      serviceMessageCompleter.complete();
+    });
+
+    // Start DDS, which should result in the original VM service client being
+    // disconnected from the VM service.
+    final remote = Uri.parse(vm.target.networkAddress);
+    dds = await DartDevelopmentService.startDartDevelopmentService(
+      remote.replace(
+        scheme: 'http',
+        pathSegments: remote.pathSegments.sublist(
+          0,
+          remote.pathSegments.length - 1,
+        ),
+      ),
+    );
+    waitForDDS.complete();
+    expect(dds.isRunning, true);
+    await serviceMessageCompleter.future;
+    await vm.onDisconnect;
+    await dds.shutdown();
+  }
+];
+
+main(args) async => runVMTests(
+      args,
+      tests,
+      enableDds: false,
+    );
diff --git a/runtime/observatory/tests/service/deferred_import_reload/v1/deferred.dart b/runtime/observatory/tests/service/deferred_import_reload/v1/deferred.dart
new file mode 100644
index 0000000..0cdf678
--- /dev/null
+++ b/runtime/observatory/tests/service/deferred_import_reload/v1/deferred.dart
@@ -0,0 +1,5 @@
+// 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.
+
+foo() => 'apple';
diff --git a/runtime/observatory/tests/service/deferred_import_reload/v1/main.dart b/runtime/observatory/tests/service/deferred_import_reload/v1/main.dart
new file mode 100644
index 0000000..3f1912e
--- /dev/null
+++ b/runtime/observatory/tests/service/deferred_import_reload/v1/main.dart
@@ -0,0 +1,38 @@
+// 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 'dart:isolate';
+
+import 'deferred.dart' deferred as prefix1;
+import 'deferred.dart' deferred as prefix2;
+
+main() {
+  prefix1.loadLibrary();
+  RawReceivePort keepAlive = new RawReceivePort();
+  print('spawned isolate running');
+}
+
+test() {
+  var x = "";
+
+  try {
+    x += prefix1.foo(); // Should retain loaded=true state across reload.
+  } catch (e, st) {
+    print(e);
+    print(st);
+    x += "error";
+  }
+
+  x += ",";
+
+  try {
+    x += prefix2.foo(); // Should retain loaded=false state across reload.
+  } catch (e, st) {
+    print(e);
+    print(st);
+    x += "error";
+  }
+
+  return x;
+}
diff --git a/runtime/observatory/tests/service/deferred_import_reload/v2/deferred.dart b/runtime/observatory/tests/service/deferred_import_reload/v2/deferred.dart
new file mode 100644
index 0000000..7a58941
--- /dev/null
+++ b/runtime/observatory/tests/service/deferred_import_reload/v2/deferred.dart
@@ -0,0 +1,5 @@
+// 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.
+
+foo() => 'orange';
diff --git a/runtime/observatory/tests/service/deferred_import_reload/v2/main.dart b/runtime/observatory/tests/service/deferred_import_reload/v2/main.dart
new file mode 100644
index 0000000..2710f32
--- /dev/null
+++ b/runtime/observatory/tests/service/deferred_import_reload/v2/main.dart
@@ -0,0 +1,36 @@
+// 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 'dart:isolate';
+
+import 'deferred.dart' deferred as prefix1;
+import 'deferred.dart' deferred as prefix2;
+
+main() {
+  throw "Not executed";
+}
+
+test() {
+  var x = "";
+
+  try {
+    x += prefix1.foo(); // Should retain loaded=true state across reload.
+  } catch (e, st) {
+    print(e);
+    print(st);
+    x += "error";
+  }
+
+  x += ",";
+
+  try {
+    x += prefix2.foo(); // Should retain loaded=false state across reload.
+  } catch (e, st) {
+    print(e);
+    print(st);
+    x += "error";
+  }
+
+  return x;
+}
diff --git a/runtime/observatory/tests/service/deferred_import_reload_test.dart b/runtime/observatory/tests/service/deferred_import_reload_test.dart
new file mode 100644
index 0000000..dccac4e
--- /dev/null
+++ b/runtime/observatory/tests/service/deferred_import_reload_test.dart
@@ -0,0 +1,78 @@
+// 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.
+//
+// OtherResources=deferred_import_reload/v1/main.dart deferred_import_reload/v1/deferred.dart deferred_import_reload/v2/main.dart deferred_import_reload/v2/deferred.dart
+
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate' as I;
+import 'dart:io';
+import 'service_test_common.dart';
+import 'package:observatory/service.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+// Chop off the file name.
+String baseDirectory = path.dirname(Platform.script.path) + '/';
+
+Uri baseUri = Platform.script.replace(path: baseDirectory);
+Uri spawnUri =
+    baseUri.resolveUri(Uri.parse('deferred_import_reload/v1/main.dart'));
+Uri v2Uri =
+    baseUri.resolveUri(Uri.parse('deferred_import_reload/v2/main.dart'));
+
+testMain() async {
+  print(baseUri);
+  debugger(); // Stop here.
+  // Spawn the child isolate.
+  I.Isolate isolate = await I.Isolate.spawnUri(spawnUri, [], null);
+  print(isolate);
+  debugger();
+}
+
+Future<String> invokeTest(Isolate isolate) async {
+  await isolate.reload();
+  Library lib = isolate.rootLibrary;
+  await lib.load();
+  Instance result = await lib.evaluate('test()') as Instance;
+  expect(result.isString, isTrue);
+  return result.valueAsString as String;
+}
+
+var tests = <IsolateTest>[
+  // Stopped at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  // Resume the isolate into the while loop.
+  resumeIsolate,
+  // Stop at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  (Isolate mainIsolate) async {
+    // Grab the VM.
+    VM vm = mainIsolate.vm;
+    await vm.reloadIsolates();
+    expect(vm.isolates.length, 2);
+
+    // Find the spawned isolate.
+    Isolate spawnedIsolate =
+        vm.isolates.firstWhere((Isolate i) => i != mainIsolate);
+    expect(spawnedIsolate, isNotNull);
+
+    // Invoke test in v1.
+    String v1 = await invokeTest(spawnedIsolate);
+    expect(v1, 'apple,error');
+
+    // Reload to v2.
+    var response = await spawnedIsolate.reloadSources(
+      rootLibUri: v2Uri.toString(),
+    );
+    // Observe that it succeed.
+    expect(response['success'], isTrue);
+
+    String v2 = await invokeTest(spawnedIsolate);
+    expect(v2, 'orange,error');
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/notify_debugger_on_exception_test.dart b/runtime/observatory/tests/service/notify_debugger_on_exception_test.dart
new file mode 100644
index 0000000..1d03341
--- /dev/null
+++ b/runtime/observatory/tests/service/notify_debugger_on_exception_test.dart
@@ -0,0 +1,37 @@
+// 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.
+//
+// VMOptions=--verbose_debug
+
+// See: https://github.com/flutter/flutter/issues/17007
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 24;
+
+@pragma('vm:notify-debugger-on-exception')
+void catchNotifyDebugger(Function() code) {
+  try {
+    code();
+  } catch (e) {
+    // Ignore. Internals will notify debugger.
+  }
+}
+
+syncThrow() {
+  throw 'Hello from syncThrow!'; // Line A.
+}
+
+testMain() {
+  catchNotifyDebugger(syncThrow);
+}
+
+final tests = <IsolateTest>[
+  hasStoppedWithUnhandledException,
+  stoppedAtLine(LINE_A),
+];
+
+main([args = const <String>[]]) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_unhandled_exceptions: true);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index bc2bb42..5896d37 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -23,6 +23,10 @@
 developer_extension_test: SkipByDesign
 get_isolate_after_language_error_test: SkipByDesign
 
+# The _1 versions of this test can be slow due to stress testing flags.
+[ $mode == debug ]
+async_generator_breakpoint_test: Pass, Slow
+
 # Service protocol is not supported in product mode.
 [ $mode == product ]
 *: SkipByDesign
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 59145d2..4fc37a9 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -9,7 +9,7 @@
 break_on_activation_test: SkipByDesign # No incremental compiler available.
 complex_reload_test: RuntimeError
 debugger_inspect_test: SkipByDesign # No incremental compiler available.
-debugger_location_second_test: RuntimeError
+debugger_location_second_test: SkipByDesign # No script sources available.
 eval_internal_class_test: SkipByDesign # No incremental compiler available.
 eval_regression_flutter20255_test: SkipByDesign # No incremental compiler available.
 eval_test: SkipByDesign # No incremental compiler available.
@@ -25,6 +25,7 @@
 evaluate_in_sync_star_activation_test: SkipByDesign # No incremental compiler available.
 evaluate_with_escaping_closure_test: SkipByDesign # No incremental compiler available.
 evaluate_with_scope_test: SkipByDesign # No incremental compiler available.
+get_object_rpc_test: SkipByDesign # App-JIT snapshots don't contain script sources.
 pause_on_exceptions_test: SkipByDesign # No incremental compiler available.
 rewind_optimized_out_test: SkipByDesign # No incremental compiler available.
 rewind_test: SkipByDesign # No incremental compiler available.
@@ -87,6 +88,7 @@
 debugger_location_test: SkipByDesign # Debugger is disabled in AOT mode.
 debugging_inlined_finally_test: SkipByDesign # Debugger is disabled in AOT mode.
 debugging_test: SkipByDesign # Debugger is disabled in AOT mode.
+deferred_import_reload_test: SkipByDesign # Hot reload is disabled in AOT mode.
 dev_fs_spawn_test: SkipByDesign # Debugger is disabled in AOT mode.
 developer_extension_test: SkipByDesign # Debugger is disabled in AOT mode.
 developer_service_get_isolate_id_test: SkipByDesign # Debugger is disabled in AOT mode.
@@ -152,6 +154,7 @@
 next_through_simple_async_with_returns_test: SkipByDesign # Debugger is disabled in AOT mode.
 next_through_simple_linear_2_test: SkipByDesign # Debugger is disabled in AOT mode.
 next_through_simple_linear_test: SkipByDesign # Debugger is disabled in AOT mode.
+notify_debugger_on_exception_test: SkipByDesign # Debugger is disabled in AOT mode.
 parameters_in_scope_at_entry_test: SkipByDesign # Debugger is disabled in AOT mode.
 pause_idle_isolate_test: SkipByDesign # Debugger is disabled in AOT mode.
 pause_on_exception_from_slow_path_test: SkipByDesign # Debugger is disabled in AOT mode.
@@ -165,7 +168,7 @@
 regress_28443_test: SkipByDesign # Debugger is disabled in AOT mode.
 regress_28980_test: SkipByDesign # Debugger is disabled in AOT mode.
 regress_34841_test: SkipByDesign # Debugger is disabled in AOT mode.
-reload_sources_test: SkipByDesign # Debugger is disabled in AOT mode.
+reload_sources_test: SkipByDesign #  Hot reload is disabled in AOT mode.
 rewind_optimized_out_test: SkipByDesign # Debugger is disabled in AOT mode.
 rewind_test: SkipByDesign # Debugger is disabled in AOT mode.
 set_library_debuggable_test: SkipByDesign # Debugger is disabled in AOT mode.
diff --git a/runtime/observatory/web/third_party/trace_viewer_full.html b/runtime/observatory/web/third_party/trace_viewer_full.html
index d815ec5..daa87d0 100644
--- a/runtime/observatory/web/third_party/trace_viewer_full.html
+++ b/runtime/observatory/web/third_party/trace_viewer_full.html
@@ -2908,8 +2908,6 @@
       <div id="collapsing_controls"></div>
       <tr-ui-b-info-bar-group id="import-warnings">
       </tr-ui-b-info-bar-group>
-      <tr-ui-b-info-bar-group id="polyfill-warning">
-      </tr-ui-b-info-bar-group>
     </div>
     <middle-container>
       <slot></slot>
@@ -3120,10 +3118,6 @@
       margin-right: 20px;
     }
 
-    #show_visualization {
-      margin-right: 20px;
-    }
-
     #export {
       margin-right: 20px;
     }
@@ -3169,8 +3163,6 @@
       <select id="statistic" value="{{displayStatisticName::change}}">
       </select>
 
-      <button id="show_visualization" on-tap="loadVisualization_">Visualize</button>
-
       <tr-ui-b-dropdown label="Export">
         <tr-v-ui-histogram-set-controls-export>
         </tr-v-ui-histogram-set-controls-export>
@@ -3396,221 +3388,6 @@
 
     <tr-ui-b-table id="table">
   </tr-ui-b-table></template>
-</dom-module><dom-module id="tr-v-ui-metrics-visualization">
-  <template>
-    <style>
-      button {
-        padding: 5px;
-        font-size: 14px;
-      }
-
-      .text_input {
-        width: 50px;
-        padding: 4px;
-        font-size: 14px;
-      }
-
-      .error {
-        color: red;
-        display: none;
-      }
-
-      .container {
-        position: relative;
-        display: inline-block;
-        margin-left: 15px;
-      }
-
-      #title {
-        font-size: 20px;
-        font-weight: bold;
-        padding-bottom: 5px;
-      }
-
-      #selectors {
-        display: block;
-        padding-bottom: 10px;
-      }
-
-      #search_page {
-        width: 200px;
-        margin-left: 30px;
-      }
-
-      #close {
-        display: none;
-        vertical-align: top;
-      }
-
-      #close svg{
-        height: 1em;
-      }
-
-      #close svg line {
-        stroke-width: 18;
-        stroke: black;
-      }
-
-      #close:hover svg {
-        background: black;
-      }
-
-      #close:hover svg line {
-        stroke: white;
-      }
-    </style>
-      <span class="container" id="aggregateContainer">
-      </span>
-      <span class="container" id="pageByPageContainer">
-        <span id="selectors">
-          <span id="percentile_label">Percentile Range:</span>
-          <input class="text_input" id="start" placeholder="0"/>
-          <input class="text_input" id="end" placeholder="100"/>
-          <button id="filter" on-tap="filterByPercentile_">Filter</button>
-          <input class="text_input" id="search_page" placeholder="Page Name"/>
-          <button id="search" on-tap="searchByPage_">Search</button>
-          <span class="error" id="search_error">Sorry, could not find that page!</span>
-        </span>
-      </span>
-      <div display="block" id="submetricsContainer">
-        <span id="close">
-          <svg viewBox="0 0 128 128">
-            <line x1="28" x2="100" y1="28" y2="100"></line>
-            <line x1="28" x2="100" y1="100" y2="28"></line>
-          </svg>
-        </span>
-      </div>
-  </template>
-</dom-module><dom-module id="tr-v-ui-raster-visualization">
-  <template>
-    <style>
-      button {
-        padding: 5px;
-        font-size: 14px;
-      }
-      .error {
-        color: red;
-        display: none;
-      }
-
-      .text_input {
-        width: 200px;
-        padding: 4px;
-        font-size: 14px;
-      }
-
-      .selector_container{
-        padding: 5px;
-      }
-
-      #search {
-        display: inline-block;
-        padding-bottom: 10px;
-      }
-
-      #search_page {
-        width: 200px;
-      }
-
-      #pageSelector {
-        display: inline-block;
-        font-size: 12pt;
-      }
-
-      #close {
-        display: none;
-        vertical-align: top;
-      }
-
-      #close svg{
-        height: 1em;
-      }
-
-      #close svg line {
-        stroke-width: 18;
-        stroke: black;
-      }
-
-      #close:hover svg {
-        background: black;
-      }
-
-      #close:hover svg line {
-        stroke: white;
-      }
-    </style>
-    <span id="aggregateContainer">
-      <div>
-        <div class="selector_container">
-          <span id="select_page_label">Individual Page Results:</span>
-          <select id="pageSelector">
-            <option id="select_page" value="">Select a page</option>
-          </select>
-        </div>
-        <div class="selector_container">
-          <div id="search_page_label">Search for a page:</div>
-          <input class="text_input" id="search_page" placeholder="Page Name"/>
-          <button id="search_button">Search</button>
-          <div class="error" id="search_error">Sorry, could not find that page!</div>
-        </div>
-      </div>
-    </span>
-    <span id="pageContainer">
-      <span id="close">
-          <svg viewBox="0 0 128 128">
-            <line x1="28" x2="100" y1="28" y2="100"></line>
-            <line x1="28" x2="100" y1="100" y2="28"></line>
-          </svg>
-        </span>
-      </span>
-  </template>
-</dom-module><meta charset="utf-8"/><dom-module id="tr-v-ui-visualizations-data-container">
-  <template>
-    <style>
-      .error {
-        color: red;
-        display: none;
-      }
-
-      .sample{
-        display: none;
-      }
-
-      .subtitle{
-        font-size: 20px;
-        font-weight: bold;
-        padding-bottom: 5px;
-      }
-
-      .description{
-        font-size: 15px;
-        padding-bottom: 5px;
-      }
-
-      #title {
-        font-size: 30px;
-        font-weight: bold;
-        padding-bottom: 5px;
-      }
-    </style>
-    <div id="title">Visualizations</div>
-    <div class="error" id="data_error">Invalid data provided.</div>
-    <div id="pipeline_per_frame_container">
-      <div class="subtitle">Graphics Pipeline and Raster Tasks</div>
-      <div class="description">
-        When raster tasks are completed in comparison to the rest of the graphics pipeline.<br/>
-        Only pages where raster tasks are completed after beginFrame is issued are included.
-      </div>
-      <tr-v-ui-raster-visualization id="rasterVisualization">
-      </tr-v-ui-raster-visualization>
-    </div>
-    <div id="metrics_container">
-      <div class="subtitle">Metrics</div>
-      <div class="description">Total amount of time taken for the indicated metrics.</div>
-      <tr-v-ui-metrics-visualization class="sample" id="metricsVisualization">
-      </tr-v-ui-metrics-visualization>
-    </div>
-  </template>
 </dom-module><dom-module id="tr-v-ui-histogram-set-view">
   <template>
     <style>
@@ -3632,9 +3409,6 @@
       display: none;
     }
 
-    #visualizations{
-      display: none;
-    }
     </style>
 
     <div id="zero">zero Histograms</div>
@@ -3643,9 +3417,6 @@
       <tr-v-ui-histogram-set-controls id="controls">
       </tr-v-ui-histogram-set-controls>
 
-      <tr-v-ui-visualizations-data-container id="visualizations">
-      </tr-v-ui-visualizations-data-container>
-
       <tr-v-ui-histogram-set-table id="table"></tr-v-ui-histogram-set-table>
     </div>
   </template>
@@ -3702,7 +3473,22 @@
  * Do not edit directly.
  */
 
-'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(window.Polymer){throw new Error('Cannot proceed. Polymer already present.');}
+'use strict';const global=this.window||this.global;this.tr=(function(){if(global.tr)return global.tr;function exportPath(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{cur=cur[part]={};}}
+return cur;}
+function isExported(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{return false;}}
+return true;}
+function isDefined(name){const parts=name.split('.');let curObject=global;for(let i=0;i<parts.length;i++){const partName=parts[i];const nextObject=curObject[partName];if(nextObject===undefined)return false;curObject=nextObject;}
+return true;}
+let panicElement=undefined;const rawPanicMessages=[];function showPanicElementIfNeeded(){if(panicElement)return;const panicOverlay=document.createElement('div');panicOverlay.style.backgroundColor='white';panicOverlay.style.border='3px solid red';panicOverlay.style.boxSizing='border-box';panicOverlay.style.color='black';panicOverlay.style.display='flex';panicOverlay.style.height='100%';panicOverlay.style.left=0;panicOverlay.style.padding='8px';panicOverlay.style.position='fixed';panicOverlay.style.top=0;panicOverlay.style.webkitFlexDirection='column';panicOverlay.style.width='100%';panicElement=document.createElement('div');panicElement.style.webkitFlex='1 1 auto';panicElement.style.overflow='auto';panicOverlay.appendChild(panicElement);if(!document.body){setTimeout(function(){document.body.appendChild(panicOverlay);},150);}else{document.body.appendChild(panicOverlay);}}
+function showPanic(panicTitle,panicDetails){if(tr.isHeadless){if(panicDetails instanceof Error)throw panicDetails;throw new Error('Panic: '+panicTitle+':\n'+panicDetails);}
+if(panicDetails instanceof Error){panicDetails=panicDetails.stack;}
+showPanicElementIfNeeded();const panicMessageEl=document.createElement('div');panicMessageEl.innerHTML='<h2 id="message"></h2>'+'<pre id="details"></pre>';panicMessageEl.querySelector('#message').textContent=panicTitle;panicMessageEl.querySelector('#details').textContent=panicDetails;panicElement.appendChild(panicMessageEl);rawPanicMessages.push({title:panicTitle,details:panicDetails});}
+function hasPanic(){return rawPanicMessages.length!==0;}
+function getPanicText(){return rawPanicMessages.map(function(msg){return msg.title;}).join(', ');}
+function exportTo(namespace,fn){const obj=exportPath(namespace);const exports=fn();for(const propertyName in exports){const propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor){Object.defineProperty(obj,propertyName,propertyDescriptor);}}}
+function initialize(){if(global.isVinn){tr.isVinn=true;}else if(global.process&&global.process.versions.node){tr.isNode=true;}else{tr.isVinn=false;tr.isNode=false;tr.doc=document;tr.isMac=/Mac/.test(navigator.platform);tr.isWindows=/Win/.test(navigator.platform);tr.isChromeOS=/CrOS/.test(navigator.userAgent);tr.isLinux=/Linux/.test(navigator.userAgent);}
+tr.isHeadless=tr.isVinn||tr.isNode;}
+return{initialize,exportTo,isExported,isDefined,showPanic,hasPanic,getPanicText,};})();tr.initialize();'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(window.Polymer){throw new Error('Cannot proceed. Polymer already present.');}
 window.Polymer={};window.Polymer.dom='shadow';}
 (function(){function resolve(){document.body.removeAttribute('unresolved');}
 if(window.WebComponents){addEventListener('WebComponentsReady',resolve);}else{if(document.readyState==='interactive'||document.readyState==='complete'){resolve();}else{addEventListener('DOMContentLoaded',resolve);}}}());window.Polymer={Settings:function(){var settings=window.Polymer||{};if(!settings.noUrlSettings){var parts=location.search.slice(1).split('&');for(var i=0,o;i<parts.length&&(o=parts[i]);i++){o=o.split('=');o[0]&&(settings[o[0]]=o[1]||true);}}
@@ -4296,22 +4082,7 @@
 this._instance=null;}},_showHideChildren:function(){var hidden=this.__hideTemplateChildren__||!this.if;if(this._instance){this._instance._showHideChildren(hidden);}},_forwardParentProp:function(prop,value){if(this._instance){this._instance.__setProperty(prop,value,true);}},_forwardParentPath:function(path,value){if(this._instance){this._instance._notifyPath(path,value,true);}}});Polymer({is:'dom-bind',properties:{notifyDomChange:{type:Boolean}},extends:'template',_template:null,created:function(){var self=this;Polymer.RenderStatus.whenReady(function(){if(document.readyState=='loading'){document.addEventListener('DOMContentLoaded',function(){self._markImportsReady();});}else{self._markImportsReady();}});},_ensureReady:function(){if(!this._readied){this._readySelf();}},_markImportsReady:function(){this._importsReady=true;this._ensureReady();},_registerFeatures:function(){this._prepConstructor();},_insertChildren:function(){var refNode;var parentNode=Polymer.dom(this).parentNode;if(parentNode.localName==this.is){refNode=parentNode;parentNode=Polymer.dom(parentNode).parentNode;}else{refNode=this;}
 Polymer.dom(parentNode).insertBefore(this.root,refNode);},_removeChildren:function(){if(this._children){for(var i=0;i<this._children.length;i++){this.root.appendChild(this._children[i]);}}},_initFeatures:function(){},_scopeElementClass:function(element,selector){if(this.dataHost){return this.dataHost._scopeElementClass(element,selector);}else{return selector;}},_configureInstanceProperties:function(){},_prepConfigure:function(){var config={};for(var prop in this._propertyEffects){config[prop]=this[prop];}
 var setupConfigure=this._setupConfigure;this._setupConfigure=function(){setupConfigure.call(this,config);};},attached:function(){if(this._importsReady){this.render();}},detached:function(){this._removeChildren();},render:function(){this._ensureReady();if(!this._children){this._template=this;this._prepAnnotations();this._prepEffects();this._prepBehaviors();this._prepConfigure();this._prepBindings();this._prepPropertyInfo();Polymer.Base._initFeatures.call(this);this._children=Polymer.TreeApi.arrayCopyChildNodes(this.root);}
-this._insertChildren();if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}}});'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(!Polymer.Settings.useNativeShadow){tr.showPanic('Polymer error','base should use native shadow when possible.');}}'use strict';const global=this.window||this.global;this.tr=(function(){if(global.tr)return global.tr;function exportPath(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{cur=cur[part]={};}}
-return cur;}
-function isExported(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{return false;}}
-return true;}
-function isDefined(name){const parts=name.split('.');let curObject=global;for(let i=0;i<parts.length;i++){const partName=parts[i];const nextObject=curObject[partName];if(nextObject===undefined)return false;curObject=nextObject;}
-return true;}
-let panicElement=undefined;const rawPanicMessages=[];function showPanicElementIfNeeded(){if(panicElement)return;const panicOverlay=document.createElement('div');panicOverlay.style.backgroundColor='white';panicOverlay.style.border='3px solid red';panicOverlay.style.boxSizing='border-box';panicOverlay.style.color='black';panicOverlay.style.display='flex';panicOverlay.style.height='100%';panicOverlay.style.left=0;panicOverlay.style.padding='8px';panicOverlay.style.position='fixed';panicOverlay.style.top=0;panicOverlay.style.webkitFlexDirection='column';panicOverlay.style.width='100%';panicElement=document.createElement('div');panicElement.style.webkitFlex='1 1 auto';panicElement.style.overflow='auto';panicOverlay.appendChild(panicElement);if(!document.body){setTimeout(function(){document.body.appendChild(panicOverlay);},150);}else{document.body.appendChild(panicOverlay);}}
-function showPanic(panicTitle,panicDetails){if(tr.isHeadless){if(panicDetails instanceof Error)throw panicDetails;throw new Error('Panic: '+panicTitle+':\n'+panicDetails);}
-if(panicDetails instanceof Error){panicDetails=panicDetails.stack;}
-showPanicElementIfNeeded();const panicMessageEl=document.createElement('div');panicMessageEl.innerHTML='<h2 id="message"></h2>'+'<pre id="details"></pre>';panicMessageEl.querySelector('#message').textContent=panicTitle;panicMessageEl.querySelector('#details').textContent=panicDetails;panicElement.appendChild(panicMessageEl);rawPanicMessages.push({title:panicTitle,details:panicDetails});}
-function hasPanic(){return rawPanicMessages.length!==0;}
-function getPanicText(){return rawPanicMessages.map(function(msg){return msg.title;}).join(', ');}
-function exportTo(namespace,fn){const obj=exportPath(namespace);const exports=fn();for(const propertyName in exports){const propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor){Object.defineProperty(obj,propertyName,propertyDescriptor);}}}
-function initialize(){if(global.isVinn){tr.isVinn=true;}else if(global.process&&global.process.versions.node){tr.isNode=true;}else{tr.isVinn=false;tr.isNode=false;tr.doc=document;tr.isMac=/Mac/.test(navigator.platform);tr.isWindows=/Win/.test(navigator.platform);tr.isChromeOS=/CrOS/.test(navigator.userAgent);tr.isLinux=/Linux/.test(navigator.userAgent);}
-tr.isHeadless=tr.isVinn||tr.isNode;}
-return{initialize,exportTo,isExported,isDefined,showPanic,hasPanic,getPanicText,};})();tr.initialize();'use strict';tr.exportTo('tr.b',function(){function EventTarget(){}
+this._insertChildren();if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}}});'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(!Polymer.Settings.useNativeShadow){tr.showPanic('Polymer error','base should use native shadow when possible.');}}'use strict';tr.exportTo('tr.b',function(){function EventTarget(){}
 EventTarget.decorate=function(target){for(const k in EventTarget.prototype){if(k==='decorate')continue;const v=EventTarget.prototype[k];if(typeof v!=='function')continue;target[k]=v;}};EventTarget.prototype={addEventListener(type,handler){if(!this.listeners_){this.listeners_=Object.create(null);}
 if(!(type in this.listeners_)){this.listeners_[type]=[handler];}else{const handlers=this.listeners_[type];if(handlers.indexOf(handler)<0){handlers.push(handler);}}},removeEventListener(type,handler){if(!this.listeners_)return;if(type in this.listeners_){const handlers=this.listeners_[type];const index=handlers.indexOf(handler);if(index>=0){if(handlers.length===1){delete this.listeners_[type];}else{handlers.splice(index,1);}}}},dispatchEvent(event){if(!this.listeners_)return true;event.__defineGetter__('target',()=>this);const realPreventDefault=event.preventDefault;event.preventDefault=function(){realPreventDefault.call(this);this.rawReturnValue=false;};const type=event.type;let prevented=0;if(type in this.listeners_){const handlers=this.listeners_[type].concat();for(let i=0,handler;handler=handlers[i];i++){if(handler.handleEvent){prevented|=handler.handleEvent.call(handler,event)===false;}else{prevented|=handler.call(this,event)===false;}}}
 return!prevented&&event.rawReturnValue;},async dispatchAsync(event){if(!this.listeners_)return true;const listeners=this.listeners_[event.type];if(listeners===undefined)return;await Promise.all(listeners.slice().map(listener=>{if(listener.handleEvent){return listener.handleEvent.call(listener,event);}
@@ -4573,7 +4344,7 @@
 const baseUnit=Unit.byName[params.baseUnitName];definedUnits.forEach(u=>u.baseUnit=baseUnit);};Unit.nameSuffixForImprovementDirection=function(improvementDirection){switch(improvementDirection){case ImprovementDirection.DONT_CARE:return'';case ImprovementDirection.BIGGER_IS_BETTER:return'_biggerIsBetter';case ImprovementDirection.SMALLER_IS_BETTER:return'_smallerIsBetter';default:throw new Error('Unknown improvement direction: '+improvementDirection);}};Unit.defineUnitVariant_=function(params,isDelta,improvementDirection){let nameSuffix=isDelta?'Delta':'';nameSuffix+=Unit.nameSuffixForImprovementDirection(improvementDirection);const unitName=params.baseUnitName+nameSuffix;const jsonName=params.baseJsonName+nameSuffix;if(Unit.byName[unitName]!==undefined){throw new Error('Unit \''+unitName+'\' already exists');}
 if(Unit.byJSONName[jsonName]!==undefined){throw new Error('JSON unit \''+jsonName+'\' alread exists');}
 let scaleBaseUnit=params.scaleBaseUnit;if(!scaleBaseUnit){let formatSpec=params.formatSpec;if(typeof formatSpec==='function')formatSpec=formatSpec();const baseSymbol=formatSpec.unitScale?formatSpec.unitScale[0].baseSymbol:(formatSpec.baseSymbol||'');scaleBaseUnit={value:1,symbol:baseSymbol,baseSymbol};}
-const unit=new Unit(unitName,jsonName,scaleBaseUnit,isDelta,improvementDirection,params.formatSpec);Unit.byName[unitName]=unit;Unit.byJSONName[jsonName]=unit;return unit;};tr.b.EventTarget.decorate(Unit);Unit.reset();Unit.define({baseUnitName:'timeInMsAutoFormat',baseJsonName:'msBestFitFormat',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec:{unitScale:tr.b.UnitScale.TIME.AUTO,minimumFractionDigits:0,maximumFractionDigits:3}});Unit.define({baseUnitName:'timeDurationInMs',baseJsonName:'ms',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'timeStampInMs',baseJsonName:'tsMs',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'normalizedPercentage',baseJsonName:'n%',formatSpec:{unitScale:[{value:0.01,symbol:'%'}],avoidSpacePrecedingUnit:true,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'sizeInBytes',baseJsonName:'sizeInBytes',formatSpec:{unitScale:tr.b.UnitScale.MEMORY.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'bandwidthInBytesPerSecond',baseJsonName:'bytesPerSecond',formatSpec:{unitScale:tr.b.UnitScale.BANDWIDTH_BYTES.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'energyInJoules',baseJsonName:'J',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('J','JOULE',tr.b.UnitPrefixScale.METRIC,'JOULE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'powerInWatts',baseJsonName:'W',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('W','WATT',tr.b.UnitPrefixScale.METRIC,'WATT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricCurrentInAmperes',baseJsonName:'A',formatSpec:{baseSymbol:'A',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('A','AMPERE',tr.b.UnitPrefixScale.METRIC,'AMPERE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricPotentialInVolts',baseJsonName:'V',formatSpec:{baseSymbol:'V',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('V','VOLT',tr.b.UnitPrefixScale.METRIC,'VOLT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'frequencyInHertz',baseJsonName:'Hz',formatSpec:{baseSymbol:'Hz',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('Hz','HERTZ',tr.b.UnitPrefixScale.METRIC,'HERTZ').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'unitlessNumber',baseJsonName:'unitless',formatSpec:{minimumFractionDigits:3,maximumFractionDigits:3}});Unit.define({baseUnitName:'count',baseJsonName:'count',formatSpec:{minimumFractionDigits:0,maximumFractionDigits:0}});Unit.define({baseUnitName:'sigma',baseJsonName:'sigma',formatSpec:{baseSymbol:String.fromCharCode(963),minimumFractionDigits:1,maximumFractionDigits:1}});return{ImprovementDirection,Unit,};});'use strict';tr.exportTo('tr.b',function(){class Scalar{constructor(unit,value){if(!(unit instanceof tr.b.Unit)){throw new Error('Expected Unit');}
+const unit=new Unit(unitName,jsonName,scaleBaseUnit,isDelta,improvementDirection,params.formatSpec);Unit.byName[unitName]=unit;Unit.byJSONName[jsonName]=unit;return unit;};tr.b.EventTarget.decorate(Unit);Unit.reset();Unit.define({baseUnitName:'timeInMsAutoFormat',baseJsonName:'msBestFitFormat',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec:{unitScale:tr.b.UnitScale.TIME.AUTO,minimumFractionDigits:0,maximumFractionDigits:3}});Unit.define({baseUnitName:'timeDurationInMs',baseJsonName:'ms',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'timeStampInMs',baseJsonName:'tsMs',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'normalizedPercentage',baseJsonName:'n%',formatSpec:{unitScale:[{value:0.01,symbol:'%'}],avoidSpacePrecedingUnit:true,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'sizeInBytes',baseJsonName:'sizeInBytes',formatSpec:{unitScale:tr.b.UnitScale.MEMORY.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'bandwidthInBytesPerSecond',baseJsonName:'bytesPerSecond',formatSpec:{unitScale:tr.b.UnitScale.BANDWIDTH_BYTES.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'energyInJoules',baseJsonName:'J',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('J','JOULE',tr.b.UnitPrefixScale.METRIC,'JOULE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'powerInWatts',baseJsonName:'W',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('W','WATT',tr.b.UnitPrefixScale.METRIC,'WATT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricCurrentInAmperes',baseJsonName:'A',formatSpec:{baseSymbol:'A',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('A','AMPERE',tr.b.UnitPrefixScale.METRIC,'AMPERE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'batteryChargeInAmpereHours',baseJsonName:'Ah',formatSpec:{baseSymbol:'Ah',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('Ah','AMPEREHOUR',tr.b.UnitPrefixScale.METRIC,'AMPEREHOUR').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricPotentialInVolts',baseJsonName:'V',formatSpec:{baseSymbol:'V',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('V','VOLT',tr.b.UnitPrefixScale.METRIC,'VOLT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'frequencyInHertz',baseJsonName:'Hz',formatSpec:{baseSymbol:'Hz',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('Hz','HERTZ',tr.b.UnitPrefixScale.METRIC,'HERTZ').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'unitlessNumber',baseJsonName:'unitless',formatSpec:{minimumFractionDigits:3,maximumFractionDigits:3}});Unit.define({baseUnitName:'count',baseJsonName:'count',formatSpec:{minimumFractionDigits:0,maximumFractionDigits:0}});Unit.define({baseUnitName:'sigma',baseJsonName:'sigma',formatSpec:{baseSymbol:String.fromCharCode(963),minimumFractionDigits:1,maximumFractionDigits:1}});return{ImprovementDirection,Unit,};});'use strict';tr.exportTo('tr.b',function(){class Scalar{constructor(unit,value){if(!(unit instanceof tr.b.Unit)){throw new Error('Expected Unit');}
 if(!(typeof(value)==='number')){throw new Error('Expected value to be number');}
 this.unit=unit;this.value=value;}
 asDict(){return{unit:this.unit.asJSON(),value:tr.b.numberToJson(this.value),};}
@@ -4725,8 +4496,8 @@
 DocLinkBuilder.prototype={addAppVideo(name,videoId){this.docLinks.push({label:'Video Link',textContent:('Android Performance Patterns: '+name),href:'https://www.youtube.com/watch?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE&v='+videoId});return this;},addDacRef(name,link){this.docLinks.push({label:'Doc Link',textContent:(name+' documentation'),href:'https://developer.android.com/reference/'+link});return this;},build(){return this.docLinks;}};function AndroidAuditor(model){Auditor.call(this,model);const helper=model.getOrCreateHelper(AndroidModelHelper);if(helper.apps.length||helper.surfaceFlinger){this.helper=helper;}}
 AndroidAuditor.viewAlphaAlertInfo_=new EventInfo('Inefficient View alpha usage','Setting an alpha between 0 and 1 has significant performance costs, if one of the fast alpha paths is not used.',new DocLinkBuilder().addAppVideo('Hidden Cost of Transparency','wIy8g8yNhNk').addDacRef('View#setAlpha()','android/view/View.html#setAlpha(float)').build());AndroidAuditor.saveLayerAlertInfo_=new EventInfo('Expensive rendering with Canvas#saveLayer()','Canvas#saveLayer() incurs extremely high rendering cost. They disrupt the rendering pipeline when drawn, forcing a flush of drawing content. Instead use View hardware layers, or static Bitmaps. This enables the offscreen buffers to be reused in between frames, and avoids the disruptive render target switch.',new DocLinkBuilder().addAppVideo('Hidden Cost of Transparency','wIy8g8yNhNk').addDacRef('Canvas#saveLayerAlpha()','android/graphics/Canvas.html#saveLayerAlpha(android.graphics.RectF, int, int)').build());AndroidAuditor.getSaveLayerAlerts_=function(frame){const badAlphaRegEx=/^(.+) alpha caused (unclipped )?saveLayer (\d+)x(\d+)$/;const saveLayerRegEx=/^(unclipped )?saveLayer (\d+)x(\d+)$/;const ret=[];const events=[];frame.associatedEvents.forEach(function(slice){const match=badAlphaRegEx.exec(slice.title);if(match){const args={'view name':match[1],'width':parseInt(match[3]),'height':parseInt(match[4])};ret.push(new Alert(AndroidAuditor.viewAlphaAlertInfo_,slice.start,[slice],args));}else if(saveLayerRegEx.test(slice.title)){events.push(slice);}},this);if(events.length>ret.length){const unclippedSeen=Statistics.sum(events,function(slice){return saveLayerRegEx.exec(slice.title)[1]?1:0;});const clippedSeen=events.length-unclippedSeen;const earliestStart=Statistics.min(events,function(slice){return slice.start;});const args={'Unclipped saveLayer count (especially bad!)':unclippedSeen,'Clipped saveLayer count':clippedSeen};events.push(frame);ret.push(new Alert(AndroidAuditor.saveLayerAlertInfo_,earliestStart,events,args));}
 return ret;};AndroidAuditor.pathAlertInfo_=new EventInfo('Path texture churn','Paths are drawn with a mask texture, so when a path is modified / newly drawn, that texture must be generated and uploaded to the GPU. Ensure that you cache paths between frames and do not unnecessarily call Path#reset(). You can cut down on this cost by sharing Path object instances between drawables/views.');AndroidAuditor.getPathAlert_=function(frame){const uploadRegEx=/^Generate Path Texture$/;const events=frame.associatedEvents.filter(function(event){return event.title==='Generate Path Texture';});const start=Statistics.min(events,getStart);const duration=Statistics.sum(events,getDuration);if(duration<3)return undefined;events.push(frame);return new Alert(AndroidAuditor.pathAlertInfo_,start,events,{'Time spent':new Scalar(timeDurationInMs,duration)});};AndroidAuditor.uploadAlertInfo_=new EventInfo('Expensive Bitmap uploads','Bitmaps that have been modified / newly drawn must be uploaded to the GPU. Since this is expensive if the total number of pixels uploaded is large, reduce the amount of Bitmap churn in this animation/context, per frame.');AndroidAuditor.getUploadAlert_=function(frame){const uploadRegEx=/^Upload (\d+)x(\d+) Texture$/;const events=[];let start=Number.POSITIVE_INFINITY;let duration=0;let pixelsUploaded=0;frame.associatedEvents.forEach(function(event){const match=uploadRegEx.exec(event.title);if(match){events.push(event);start=Math.min(start,event.start);duration+=event.duration;pixelsUploaded+=parseInt(match[1])*parseInt(match[2]);}});if(events.length===0||duration<3)return undefined;const mPixels=(pixelsUploaded/1000000).toFixed(2)+' million';const args={'Pixels uploaded':mPixels,'Time spent':new Scalar(timeDurationInMs,duration)};events.push(frame);return new Alert(AndroidAuditor.uploadAlertInfo_,start,events,args);};AndroidAuditor.ListViewInflateAlertInfo_=new EventInfo('Inflation during ListView recycling','ListView item recycling involved inflating views. Ensure your Adapter#getView() recycles the incoming View, instead of constructing a new one.');AndroidAuditor.ListViewBindAlertInfo_=new EventInfo('Inefficient ListView recycling/rebinding','ListView recycling taking too much time per frame. Ensure your Adapter#getView() binds data efficiently.');AndroidAuditor.getListViewAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='obtainView'||event.title==='setupListItem';});const duration=Statistics.sum(events,getCpuDuration);if(events.length===0||duration<3)return undefined;let hasInflation=false;for(const event of events){if(event.findDescendentSlice('inflate')){hasInflation=true;}}
-const start=Statistics.min(events,getStart);const args={'Time spent':new Scalar(timeDurationInMs,duration)};args['ListView items '+(hasInflation?'inflated':'rebound')]=events.length/2;const eventInfo=hasInflation?AndroidAuditor.ListViewInflateAlertInfo_:AndroidAuditor.ListViewBindAlertInfo_;events.push(frame);return new Alert(eventInfo,start,events,args);};AndroidAuditor.measureLayoutAlertInfo_=new EventInfo('Expensive measure/layout pass','Measure/Layout took a significant time, contributing to jank. Avoid triggering layout during animations.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').build());AndroidAuditor.getMeasureLayoutAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='measure'||event.title==='layout';});const duration=Statistics.sum(events,getCpuDuration);if(events.length===0||duration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.measureLayoutAlertInfo_,start,events,{'Time spent':new Scalar(timeDurationInMs,duration)});};AndroidAuditor.viewDrawAlertInfo_=new EventInfo('Long View#draw()','Recording the drawing commands of invalidated Views took a long time. Avoid significant work in View or Drawable custom drawing, especially allocations or drawing to Bitmaps.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').addAppVideo('Avoiding Allocations in onDraw()','HAK5acHQ53E').build());AndroidAuditor.getViewDrawAlert_=function(frame){let slice=undefined;for(const event of frame.associatedEvents){if(event.title==='getDisplayList'||event.title==='Record View#draw()'){slice=event;break;}}
-if(!slice||getCpuDuration(slice)<3)return undefined;return new Alert(AndroidAuditor.viewDrawAlertInfo_,slice.start,[slice,frame],{'Time spent':new Scalar(timeDurationInMs,getCpuDuration(slice))});};AndroidAuditor.blockingGcAlertInfo_=new EventInfo('Blocking Garbage Collection','Blocking GCs are caused by object churn, and made worse by having large numbers of objects in the heap. Avoid allocating objects during animations/scrolling, and recycle Bitmaps to avoid triggering garbage collection.',new DocLinkBuilder().addAppVideo('Garbage Collection in Android','pzfzz50W5Uo').addAppVideo('Avoiding Allocations in onDraw()','HAK5acHQ53E').build());AndroidAuditor.getBlockingGcAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='DVM Suspend'||event.title==='GC: Wait For Concurrent';});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.blockingGcAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.lockContentionAlertInfo_=new EventInfo('Lock contention','UI thread lock contention is caused when another thread holds a lock that the UI thread is trying to use. UI thread progress is blocked until the lock is released. Inspect locking done within the UI thread, and ensure critical sections are short.');AndroidAuditor.getLockContentionAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return/^Lock Contention on /.test(event.title);});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<1)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.lockContentionAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.schedulingAlertInfo_=new EventInfo('Scheduling delay','Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.');AndroidAuditor.getSchedulingAlert_=function(frame){let totalDuration=0;const totalStats={};for(const ttr of frame.threadTimeRanges){const stats=ttr.thread.getSchedulingStatsForRange(ttr.start,ttr.end);for(const[key,value]of Object.entries(stats)){if(!(key in totalStats)){totalStats[key]=0;}
+const start=Statistics.min(events,getStart);const args={'Time spent':new Scalar(timeDurationInMs,duration)};args['ListView items '+(hasInflation?'inflated':'rebound')]=events.length/2;const eventInfo=hasInflation?AndroidAuditor.ListViewInflateAlertInfo_:AndroidAuditor.ListViewBindAlertInfo_;events.push(frame);return new Alert(eventInfo,start,events,args);};AndroidAuditor.measureLayoutAlertInfo_=new EventInfo('Expensive measure/layout pass','Measure/Layout took a significant time, contributing to jank. Avoid triggering layout during animations.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').build());AndroidAuditor.getMeasureLayoutAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='measure'||event.title==='layout';});const duration=Statistics.sum(events,getCpuDuration);if(events.length===0||duration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.measureLayoutAlertInfo_,start,events,{'Time spent':new Scalar(timeDurationInMs,duration)});};AndroidAuditor.viewDrawAlertInfo_=new EventInfo('Long View#dptr()','Recording the drawing commands of invalidated Views took a long time. Avoid significant work in View or Drawable custom drawing, especially allocations or drawing to Bitmaps.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').addAppVideo('Avoiding Allocations in onDptr()','HAK5acHQ53E').build());AndroidAuditor.getViewDrawAlert_=function(frame){let slice=undefined;for(const event of frame.associatedEvents){if(event.title==='getDisplayList'||event.title==='Record View#dptr()'){slice=event;break;}}
+if(!slice||getCpuDuration(slice)<3)return undefined;return new Alert(AndroidAuditor.viewDrawAlertInfo_,slice.start,[slice,frame],{'Time spent':new Scalar(timeDurationInMs,getCpuDuration(slice))});};AndroidAuditor.blockingGcAlertInfo_=new EventInfo('Blocking Garbage Collection','Blocking GCs are caused by object churn, and made worse by having large numbers of objects in the heap. Avoid allocating objects during animations/scrolling, and recycle Bitmaps to avoid triggering garbage collection.',new DocLinkBuilder().addAppVideo('Garbage Collection in Android','pzfzz50W5Uo').addAppVideo('Avoiding Allocations in onDptr()','HAK5acHQ53E').build());AndroidAuditor.getBlockingGcAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='DVM Suspend'||event.title==='GC: Wait For Concurrent';});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.blockingGcAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.lockContentionAlertInfo_=new EventInfo('Lock contention','UI thread lock contention is caused when another thread holds a lock that the UI thread is trying to use. UI thread progress is blocked until the lock is released. Inspect locking done within the UI thread, and ensure critical sections are short.');AndroidAuditor.getLockContentionAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return/^Lock Contention on /.test(event.title);});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<1)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.lockContentionAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.schedulingAlertInfo_=new EventInfo('Scheduling delay','Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.');AndroidAuditor.getSchedulingAlert_=function(frame){let totalDuration=0;const totalStats={};for(const ttr of frame.threadTimeRanges){const stats=ttr.thread.getSchedulingStatsForRange(ttr.start,ttr.end);for(const[key,value]of Object.entries(stats)){if(!(key in totalStats)){totalStats[key]=0;}
 totalStats[key]+=value;totalDuration+=value;}}
 if(!(SCHEDULING_STATE.RUNNING in totalStats)||totalDuration===0||totalDuration-totalStats[SCHEDULING_STATE.RUNNING]<3){return;}
 const args={};for(const[key,value]of Object.entries(totalStats)){let newKey=key;if(key===SCHEDULING_STATE.RUNNABLE){newKey='Not scheduled, but runnable';}else if(key===SCHEDULING_STATE.UNINTR_SLEEP){newKey='Blocking I/O delay';}
@@ -4740,7 +4511,7 @@
 if(/^hwuiTask/.test(thread.name)){thread.sortIndex=-1;}});},pushFramesAndJudgeJank_(){let badFramesObserved=0;let framesObserved=0;const surfaceFlinger=this.helper.surfaceFlinger;this.helper.apps.forEach(function(app){app.process.frames=app.getFrames();app.process.frames.forEach(function(frame){if(frame.totalDuration>EXPECTED_FRAME_TIME_MS*2){badFramesObserved+=2;frame.perfClass=FRAME_PERF_CLASS.TERRIBLE;}else if(frame.totalDuration>EXPECTED_FRAME_TIME_MS||frameMissedDeadline(frame)){badFramesObserved++;frame.perfClass=FRAME_PERF_CLASS.BAD;}else{frame.perfClass=FRAME_PERF_CLASS.GOOD;}});framesObserved+=app.process.frames.length;});if(framesObserved){const portionBad=badFramesObserved/framesObserved;if(portionBad>0.3){this.model.faviconHue='red';}else if(portionBad>0.05){this.model.faviconHue='yellow';}else{this.model.faviconHue='green';}}},pushEventInfo_(){const appAnnotator=new AppAnnotator();this.helper.apps.forEach(function(app){if(app.uiThread){appAnnotator.applyEventInfos(app.uiThread.sliceGroup);}
 if(app.renderThread){appAnnotator.applyEventInfos(app.renderThread.sliceGroup);}});},runAnnotate(){if(!this.helper)return;this.renameAndSort_();this.pushFramesAndJudgeJank_();this.pushEventInfo_();this.helper.iterateImportantSlices(function(slice){slice.important=true;});},runAudit(){if(!this.helper)return;const alerts=this.model.alerts;this.helper.apps.forEach(function(app){app.getFrames().forEach(function(frame){alerts.push.apply(alerts,AndroidAuditor.getSaveLayerAlerts_(frame));if(frame.perfClass===FRAME_PERF_CLASS.NEUTRAL||frame.perfClass===FRAME_PERF_CLASS.GOOD){return;}
 let alert=AndroidAuditor.getPathAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getUploadAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getListViewAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getMeasureLayoutAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getViewDrawAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getBlockingGcAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getLockContentionAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getSchedulingAlert_(frame);if(alert)alerts.push(alert);});},this);this.addRenderingInteractionRecords();this.addInputInteractionRecords();},addRenderingInteractionRecords(){const events=[];this.helper.apps.forEach(function(app){events.push.apply(events,app.getAnimationAsyncSlices());events.push.apply(events,app.getFrames());});const mergerFunction=function(events){const ir=new tr.model.um.ResponseExpectation(this.model,'Rendering',events[0].min,events[events.length-1].max-events[0].min);this.model.userModel.expectations.push(ir);}.bind(this);tr.b.math.mergeRanges(tr.b.math.convertEventsToRanges(events),30,mergerFunction);},addInputInteractionRecords(){const inputSamples=[];this.helper.apps.forEach(function(app){inputSamples.push.apply(inputSamples,app.getInputSamples());});const mergerFunction=function(events){const ir=new tr.model.um.ResponseExpectation(this.model,'Input',events[0].min,events[events.length-1].max-events[0].min);this.model.userModel.expectations.push(ir);}.bind(this);const inputRanges=inputSamples.map(function(sample){return tr.b.math.Range.fromExplicitRange(sample.timestamp,sample.timestamp);});tr.b.math.mergeRanges(inputRanges,30,mergerFunction);}};Auditor.register(AndroidAuditor);function AppAnnotator(){this.titleInfoLookup=new Map();this.titleParentLookup=new Map();this.build_();}
-AppAnnotator.prototype={build_(){const registerEventInfo=function(dict){this.titleInfoLookup.set(dict.title,new EventInfo(dict.title,dict.description,dict.docLinks));if(dict.parents){this.titleParentLookup.set(dict.title,dict.parents);}}.bind(this);registerEventInfo({title:'inflate',description:'Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes.'});registerEventInfo({title:'obtainView',description:'Adapter#getView() called to bind content to a recycled View that is being presented.'});registerEventInfo({title:'setupListItem',description:'Attached a newly-bound, recycled View to its parent ListView.'});registerEventInfo({title:'setupGridItem',description:'Attached a newly-bound, recycled View to its parent GridView.'});const choreographerLinks=new DocLinkBuilder().addDacRef('Choreographer','android/view/Choreographer.html').build();registerEventInfo({title:'Choreographer#doFrame',docLinks:choreographerLinks,description:'Choreographer executes frame callbacks for inputs, animations, and rendering traversals. When this work is done, a frame will be presented to the user.'});registerEventInfo({title:'input',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Input callbacks are processed. This generally encompasses dispatching input to Views, as well as any work the Views do to process this input/gesture.'});registerEventInfo({title:'animation',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Animation callbacks are processed. This is generally minimal work, as animations determine progress for the frame, and push new state to animated objects (such as setting View properties).'});registerEventInfo({title:'traversals',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Primary draw traversals. This is the primary traversal of the View hierarchy, including layout and draw passes.'});const traversalParents=['Choreographer#doFrame','performTraversals'];const layoutLinks=new DocLinkBuilder().addDacRef('View#Layout','android/view/View.html#Layout').build();registerEventInfo({title:'performTraversals',description:'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'});registerEventInfo({title:'measure',parents:traversalParents,docLinks:layoutLinks,description:'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'});registerEventInfo({title:'layout',parents:traversalParents,docLinks:layoutLinks,description:'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'});const drawString='Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.';registerEventInfo({title:'draw',parents:traversalParents,description:drawString});const recordString='Every invalidated View\'s drawing commands are recorded. Each will have View#draw() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.';registerEventInfo({title:'getDisplayList',parents:['draw'],description:recordString});registerEventInfo({title:'Record View#draw()',parents:['draw'],description:recordString});registerEventInfo({title:'drawDisplayList',parents:['draw'],description:'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU. On Android L and higher devices, this work is done on a dedicated RenderThread, instead of on the UI Thread.'});registerEventInfo({title:'DrawFrame',description:'RenderThread portion of the standard UI/RenderThread split frame. This represents the actual formation and issuing of drawing commands to the GPU.'});registerEventInfo({title:'doFrame',description:'RenderThread animation frame. Represents drawing work done by the RenderThread on a frame where the UI thread did not produce new drawing content.'});registerEventInfo({title:'syncFrameState',description:'Sync stage between the UI thread and the RenderThread, where the UI thread hands off a frame (including information about modified Views). Time in this method primarily consists of uploading modified Bitmaps to the GPU. After this sync is completed, the UI thread is unblocked, and the RenderThread starts to render the frame.'});registerEventInfo({title:'flush drawing commands',description:'Issuing the now complete drawing commands to the GPU.'});registerEventInfo({title:'eglSwapBuffers',description:'Complete GPU rendering of the frame.'});registerEventInfo({title:'RV Scroll',description:'RecyclerView is calculating a scroll. If there are too many of these in Systrace, some Views inside RecyclerView might be causing it. Try to avoid using EditText, focusable views or handle them with care.'});registerEventInfo({title:'RV OnLayout',description:'OnLayout has been called by the View system. If this shows up too many times in Systrace, make sure the children of RecyclerView do not update themselves directly. This will cause a full re-layout but when it happens via the Adapter notifyItemChanged, RecyclerView can avoid full layout calculation.'});registerEventInfo({title:'RV FullInvalidate',description:'NotifyDataSetChanged or equal has been called. If this is taking a long time, try sending granular notify adapter changes instead of just calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter might help.'});registerEventInfo({title:'RV PartialInvalidate',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV OnBindView',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV CreateView',description:'RecyclerView is creating a new View. If too many of these are present: 1) There might be a problem in Recycling (e.g. custom Animations that set transient state and prevent recycling or ItemAnimator not implementing the contract properly. See Adapter#onFailedToRecycleView(ViewHolder). 2) There may be too many item view types. Try merging them. 3) There might be too many itemChange animations and not enough space in RecyclerPool. Try increasing your pool size and item cache size.'});registerEventInfo({title:'eglSwapBuffers',description:'The CPU has finished producing drawing commands, and is flushing drawing work to the GPU, and posting that buffer to the consumer (which is often SurfaceFlinger window composition). Once this is completed, the GPU can produce the frame content without any involvement from the CPU.'});},applyEventInfosRecursive_(parentNames,slice){const checkExpectedParentNames=function(expectedParentNames){if(!expectedParentNames)return true;return expectedParentNames.some(function(name){return parentNames.has(name);});};if(this.titleInfoLookup.has(slice.title)){if(checkExpectedParentNames(this.titleParentLookup.get(slice.title))){slice.info=this.titleInfoLookup.get(slice.title);}}
+AppAnnotator.prototype={build_(){const registerEventInfo=function(dict){this.titleInfoLookup.set(dict.title,new EventInfo(dict.title,dict.description,dict.docLinks));if(dict.parents){this.titleParentLookup.set(dict.title,dict.parents);}}.bind(this);registerEventInfo({title:'inflate',description:'Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes.'});registerEventInfo({title:'obtainView',description:'Adapter#getView() called to bind content to a recycled View that is being presented.'});registerEventInfo({title:'setupListItem',description:'Attached a newly-bound, recycled View to its parent ListView.'});registerEventInfo({title:'setupGridItem',description:'Attached a newly-bound, recycled View to its parent GridView.'});const choreographerLinks=new DocLinkBuilder().addDacRef('Choreographer','android/view/Choreographer.html').build();registerEventInfo({title:'Choreographer#doFrame',docLinks:choreographerLinks,description:'Choreographer executes frame callbacks for inputs, animations, and rendering traversals. When this work is done, a frame will be presented to the user.'});registerEventInfo({title:'input',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Input callbacks are processed. This generally encompasses dispatching input to Views, as well as any work the Views do to process this input/gesture.'});registerEventInfo({title:'animation',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Animation callbacks are processed. This is generally minimal work, as animations determine progress for the frame, and push new state to animated objects (such as setting View properties).'});registerEventInfo({title:'traversals',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Primary draw traversals. This is the primary traversal of the View hierarchy, including layout and draw passes.'});const traversalParents=['Choreographer#doFrame','performTraversals'];const layoutLinks=new DocLinkBuilder().addDacRef('View#Layout','android/view/View.html#Layout').build();registerEventInfo({title:'performTraversals',description:'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'});registerEventInfo({title:'measure',parents:traversalParents,docLinks:layoutLinks,description:'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'});registerEventInfo({title:'layout',parents:traversalParents,docLinks:layoutLinks,description:'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'});const drawString='Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.';registerEventInfo({title:'draw',parents:traversalParents,description:drawString});const recordString='Every invalidated View\'s drawing commands are recorded. Each will have View#dptr() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.';registerEventInfo({title:'getDisplayList',parents:['draw'],description:recordString});registerEventInfo({title:'Record View#dptr()',parents:['draw'],description:recordString});registerEventInfo({title:'drawDisplayList',parents:['draw'],description:'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU. On Android L and higher devices, this work is done on a dedicated RenderThread, instead of on the UI Thread.'});registerEventInfo({title:'DrawFrame',description:'RenderThread portion of the standard UI/RenderThread split frame. This represents the actual formation and issuing of drawing commands to the GPU.'});registerEventInfo({title:'doFrame',description:'RenderThread animation frame. Represents drawing work done by the RenderThread on a frame where the UI thread did not produce new drawing content.'});registerEventInfo({title:'syncFrameState',description:'Sync stage between the UI thread and the RenderThread, where the UI thread hands off a frame (including information about modified Views). Time in this method primarily consists of uploading modified Bitmaps to the GPU. After this sync is completed, the UI thread is unblocked, and the RenderThread starts to render the frame.'});registerEventInfo({title:'flush drawing commands',description:'Issuing the now complete drawing commands to the GPU.'});registerEventInfo({title:'eglSwapBuffers',description:'Complete GPU rendering of the frame.'});registerEventInfo({title:'RV Scroll',description:'RecyclerView is calculating a scroll. If there are too many of these in Systrace, some Views inside RecyclerView might be causing it. Try to avoid using EditText, focusable views or handle them with care.'});registerEventInfo({title:'RV OnLayout',description:'OnLayout has been called by the View system. If this shows up too many times in Systrace, make sure the children of RecyclerView do not update themselves directly. This will cause a full re-layout but when it happens via the Adapter notifyItemChanged, RecyclerView can avoid full layout calculation.'});registerEventInfo({title:'RV FullInvalidate',description:'NotifyDataSetChanged or equal has been called. If this is taking a long time, try sending granular notify adapter changes instead of just calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter might help.'});registerEventInfo({title:'RV PartialInvalidate',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV OnBindView',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV CreateView',description:'RecyclerView is creating a new View. If too many of these are present: 1) There might be a problem in Recycling (e.g. custom Animations that set transient state and prevent recycling or ItemAnimator not implementing the contract properly. See Adapter#onFailedToRecycleView(ViewHolder). 2) There may be too many item view types. Try merging them. 3) There might be too many itemChange animations and not enough space in RecyclerPool. Try increasing your pool size and item cache size.'});registerEventInfo({title:'eglSwapBuffers',description:'The CPU has finished producing drawing commands, and is flushing drawing work to the GPU, and posting that buffer to the consumer (which is often SurfaceFlinger window composition). Once this is completed, the GPU can produce the frame content without any involvement from the CPU.'});},applyEventInfosRecursive_(parentNames,slice){const checkExpectedParentNames=function(expectedParentNames){if(!expectedParentNames)return true;return expectedParentNames.some(function(name){return parentNames.has(name);});};if(this.titleInfoLookup.has(slice.title)){if(checkExpectedParentNames(this.titleParentLookup.get(slice.title))){slice.info=this.titleInfoLookup.get(slice.title);}}
 if(slice.subSlices.length>0){if(!parentNames.has(slice.title)){parentNames.set(slice.title,0);}
 parentNames.set(slice.title,parentNames.get(slice.title)+1);slice.subSlices.forEach(function(subSlice){this.applyEventInfosRecursive_(parentNames,subSlice);},this);parentNames.set(slice.title,parentNames.get(slice.title)-1);if(parentNames.get(slice.title)===0){delete parentNames[slice.title];}}},applyEventInfos(sliceGroup){sliceGroup.topLevelSlices.forEach(function(slice){this.applyEventInfosRecursive_(new Map(),slice);},this);}};return{AndroidAuditor,};});'use strict';tr.exportTo('tr.model',function(){function ObjectSnapshot(objectInstance,ts,args){tr.model.Event.call(this);this.objectInstance=objectInstance;this.ts=ts;this.args=args;}
 ObjectSnapshot.prototype={__proto__:tr.model.Event.prototype,preInitialize(){},initialize(){},referencedAt(item,object,field){},addBoundsToRange(range){range.addValue(this.ts);},get userFriendlyName(){return'Snapshot of '+this.objectInstance.userFriendlyName+' @ '+
@@ -4808,8 +4579,8 @@
 return process.findAllThreadsNamed('CrGpuMain').length>0;};ChromeGpuHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype};return{ChromeGpuHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const NET_CATEGORIES=new Set(['net','netlog','disabled-by-default-netlog','disabled-by-default-network']);class ChromeThreadHelper{constructor(thread){this.thread=thread;}
 getNetworkEvents(){const networkEvents=[];for(const slice of this.thread.asyncSliceGroup.slices){const categories=tr.b.getCategoryParts(slice.category);const isNetEvent=category=>NET_CATEGORIES.has(category);if(categories.filter(isNetEvent).length===0)continue;networkEvents.push(slice);}
 return networkEvents;}}
-return{ChromeThreadHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const ChromeThreadHelper=tr.model.helpers.ChromeThreadHelper;function ChromeRendererHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain')||process.findAtMostOneThreadNamed('Chrome_InProcRendererThread');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)return false;if(t.name.startsWith('CompositorTileWorker'))return true;if(t.name.startsWith('CompositorRasterWorker'))return true;return false;});this.dedicatedWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('DedicatedWorker');});this.foregroundWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ThreadPoolForegroundWorker');});if(!process.name){process.name=ChromeRendererHelper.PROCESS_NAME;}}
-ChromeRendererHelper.PROCESS_NAME='Renderer';ChromeRendererHelper.isRenderProcess=function(process){if(process.findAtMostOneThreadNamed('CrRendererMain'))return true;if(process.findAtMostOneThreadNamed('Compositor'))return true;return false;};ChromeRendererHelper.isTracingProcess=function(process){return process.labels!==undefined&&process.labels.length===1&&process.labels[0]==='chrome://tracing';};ChromeRendererHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;},get dedicatedWorkerThreads(){return this.dedicatedWorkerThreads_;},get foregroundWorkerThreads(){return this.foregroundWorkerThreads_;},get isChromeTracingUI(){return ChromeRendererHelper.isTracingProcess(this.process);},};return{ChromeRendererHelper,};});'use strict';tr.exportTo('tr.model.um',function(){class Segment extends tr.model.TimedEvent{constructor(start,duration){super(start);this.duration=duration;this.expectations_=[];}
+return{ChromeThreadHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const ChromeThreadHelper=tr.model.helpers.ChromeThreadHelper;function ChromeRendererHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain')||process.findAtMostOneThreadNamed('Chrome_InProcRendererThread');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)return false;if(t.name.startsWith('CompositorTileWorker'))return true;if(t.name.startsWith('CompositorRasterWorker'))return true;return false;});this.dedicatedWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('DedicatedWorker');});this.serviceWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ServiceWorker');});this.foregroundWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ThreadPoolForegroundWorker');});if(!process.name){process.name=ChromeRendererHelper.PROCESS_NAME;}}
+ChromeRendererHelper.PROCESS_NAME='Renderer';ChromeRendererHelper.isRenderProcess=function(process){if(process.findAtMostOneThreadNamed('CrRendererMain'))return true;if(process.findAtMostOneThreadNamed('Compositor'))return true;return false;};ChromeRendererHelper.isTracingProcess=function(process){return process.labels!==undefined&&process.labels.length===1&&process.labels[0]==='chrome://tracing';};ChromeRendererHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;},get dedicatedWorkerThreads(){return this.dedicatedWorkerThreads_;},get serviceWorkerThreads(){return this.serviceWorkerThreads_;},get foregroundWorkerThreads(){return this.foregroundWorkerThreads_;},get isChromeTracingUI(){return ChromeRendererHelper.isTracingProcess(this.process);},};return{ChromeRendererHelper,};});'use strict';tr.exportTo('tr.model.um',function(){class Segment extends tr.model.TimedEvent{constructor(start,duration){super(start);this.duration=duration;this.expectations_=[];}
 get expectations(){return this.expectations_;}
 clone(){const clone=new Segment(this.start,this.duration);clone.expectations.push(...this.expectations);return clone;}
 addSegment(other){this.duration+=other.duration;this.expectations.push(...other.expectations);}}
@@ -4869,7 +4640,7 @@
 for(const category of Object.values(USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY)){ChromeUserFriendlyCategoryDriver.ALL_TITLES.push(category);}
 ChromeUserFriendlyCategoryDriver.ALL_TITLES.sort();for(const category of ChromeUserFriendlyCategoryDriver.ALL_TITLES){ChromeUserFriendlyCategoryDriver.getColor(category);}
 return{ChromeUserFriendlyCategoryDriver,};});'use strict';tr.exportTo('tr.model',function(){return{BROWSER_PROCESS_PID_REF:-1,OBJECT_DEFAULT_SCOPE:'ptr',LOCAL_ID_PHASES:new Set(['N','D','O','(',')'])};});'use strict';tr.exportTo('tr.e.audits',function(){const Auditor=tr.c.Auditor;const Alert=tr.model.Alert;const EventInfo=tr.model.EventInfo;function ChromeAuditor(model){Auditor.call(this,model);const modelHelper=this.model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper&&modelHelper.browserHelper){this.modelHelper=modelHelper;}else{this.modelHelper=undefined;}}
-function getMissedFrameAlerts(rendererHelpers){const alerts=[];for(const rendererHelper of rendererHelpers){if(!rendererHelper.compositorThread)continue;const thread=rendererHelper.compositorThread;const asyncSlices=Object.values(thread.asyncSliceGroup.slices);for(const slice of asyncSlices){if(slice.title!=='PipelineReporter'||!slice.args.termination_status||slice.args.termination_status!=='missed_frame')continue;const alertSlices=[slice].concat(slice.subSlices);alerts.push(new Alert(new EventInfo('Missed Frame','Frame was not submitted before deadline.'),slice.start,alertSlices));}}
+function getMissedFrameAlerts(rendererHelpers){const alerts=[];for(const rendererHelper of rendererHelpers){if(!rendererHelper.compositorThread)continue;const thread=rendererHelper.compositorThread;const asyncSlices=Object.values(thread.asyncSliceGroup.slices);for(const slice of asyncSlices){if(slice.title==='PipelineReporter'&&slice.args.chrome_frame_reporter&&slice.args.chrome_frame_reporter.state==='STATE_DROPPED'){const alertSlices=[slice].concat(slice.subSlices);alerts.push(new Alert(new EventInfo('Dropped Frame','Frame was dropped (i.e. not produced/presented).'),slice.start,alertSlices));}}}
 return alerts;}
 ChromeAuditor.prototype={__proto__:Auditor.prototype,runAnnotate(){if(!this.modelHelper)return;for(const pid in this.modelHelper.rendererHelpers){const rendererHelper=this.modelHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI){rendererHelper.process.important=false;}}},installUserFriendlyCategoryDriverIfNeeded(){this.model.addUserFriendlyCategoryDriver(tr.e.chrome.ChromeUserFriendlyCategoryDriver);},runAudit(){if(!this.modelHelper)return;this.model.replacePIDRefsInPatchups(tr.model.BROWSER_PROCESS_PID_REF,this.modelHelper.browserProcess.pid);this.model.applyObjectRefPatchups();const alerts=getMissedFrameAlerts(Object.values(this.modelHelper.rendererHelpers));this.model.alerts=this.model.alerts.concat(alerts);}};Auditor.register(ChromeAuditor);return{ChromeAuditor,};});'use strict';tr.exportTo('tr.e.chrome',function(){const KNOWN_PROPERTIES={absX:1,absY:1,address:1,anonymous:1,childNeeds:1,children:1,classNames:1,col:1,colSpan:1,float:1,height:1,htmlId:1,name:1,posChildNeeds:1,positioned:1,positionedMovement:1,relX:1,relY:1,relativePositioned:1,row:1,rowSpan:1,selfNeeds:1,stickyPositioned:1,tag:1,width:1};function LayoutObject(snapshot,args){this.snapshot_=snapshot;this.id_=args.address;this.name_=args.name;this.childLayoutObjects_=[];this.otherProperties_={};this.tag_=args.tag;this.relativeRect_=tr.b.math.Rect.fromXYWH(args.relX,args.relY,args.width,args.height);this.absoluteRect_=tr.b.math.Rect.fromXYWH(args.absX,args.absY,args.width,args.height);this.isFloat_=args.float;this.isStickyPositioned_=args.stickyPositioned;this.isPositioned_=args.positioned;this.isRelativePositioned_=args.relativePositioned;this.isAnonymous_=args.anonymous;this.htmlId_=args.htmlId;this.classNames_=args.classNames;this.needsLayoutReasons_=[];if(args.selfNeeds){this.needsLayoutReasons_.push('self');}
 if(args.childNeeds){this.needsLayoutReasons_.push('child');}
@@ -5033,7 +4804,8 @@
 if(markers[0].domainId===domainId){throw new Error('A clock domain cannot sync with itself.');}
 markers.push(marker);this.onSyncCompleted_(markers[0],marker);},get completeSyncIds(){const completeSyncIds=[];for(const[syncId,markers]of this.markersBySyncId){if(markers.length===2)completeSyncIds.push(syncId);}
 return completeSyncIds;},get markersBySyncId(){return this.markersBySyncId_;},get domainsSeen(){return this.domainsSeen_;},getModelTimeTransformer(domainId){this.onDomainSeen_(domainId);if(!this.modelDomainId_){this.selectModelDomainId_();}
-return this.getTimeTransformerRaw_(domainId,this.modelDomainId_).fn;},getTimeTransformerError(fromDomainId,toDomainId){this.onDomainSeen_(fromDomainId);this.onDomainSeen_(toDomainId);return this.getTimeTransformerRaw_(fromDomainId,toDomainId).error;},getTimeTransformerRaw_(fromDomainId,toDomainId){const transformer=this.getTransformerBetween_(fromDomainId,toDomainId);if(!transformer){throw new Error('No clock sync markers exist pairing clock domain "'+
+return this.getTimeTransformerRaw_(domainId,this.modelDomainId_).fn;},getModelTimeTransformerInverse(domainId){this.onDomainSeen_(domainId);if(!this.modelDomainId_){this.selectModelDomainId_();}
+return this.getTimeTransformerRaw_(this.modelDomainId_,domainId).fn;},getTimeTransformerError(fromDomainId,toDomainId){this.onDomainSeen_(fromDomainId);this.onDomainSeen_(toDomainId);return this.getTimeTransformerRaw_(fromDomainId,toDomainId).error;},getTimeTransformerRaw_(fromDomainId,toDomainId){const transformer=this.getTransformerBetween_(fromDomainId,toDomainId);if(!transformer){throw new Error('No clock sync markers exist pairing clock domain "'+
 fromDomainId+'" '+'with target clock domain "'+
 toDomainId+'".');}
 return transformer;},getTransformerBetween_(fromDomainId,toDomainId){const visitedDomainIds=new Set();const queue=[{domainId:fromDomainId,transformer:Transformer.IDENTITY}];while(queue.length>0){queue.sort((domain1,domain2)=>domain1.transformer.error-domain2.transformer.error);const current=queue.shift();if(current.domainId===toDomainId){return current.transformer;}
@@ -5388,7 +5160,8 @@
 for(const event of this.childEvents()){event.start+=shiftAmount;}
 this.updateBounds();},convertTimestampToModelTime(sourceClockDomainName,ts){if(sourceClockDomainName!=='traceEventClock'){throw new Error('Only traceEventClock is supported.');}
 return tr.b.Unit.timestampFromUs(ts)+
-this.timestampShiftToZeroAmount_;},get numProcesses(){let n=0;for(const p in this.processes){n++;}
+this.timestampShiftToZeroAmount_;},convertTimestampFromModelTime(targetClockDomainName,ts){if(targetClockDomainName!=='traceEventClock'){throw new Error('Only traceEventClock is supported.');}
+const convertFn=this.clockSyncManager.getModelTimeTransformerInverse(tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL);return convertFn(ts)-this.timestampShiftToZeroAmount_;},get numProcesses(){let n=0;for(const p in this.processes){n++;}
 return n;},getProcess(pid){return this.processes[pid];},getOrCreateProcess(pid){if(!this.processes[pid]){this.processes[pid]=new Process(this,pid);}
 return this.processes[pid];},addStackFrame(stackFrame){if(this.stackFrames[stackFrame.id]){throw new Error('Stack frame already exists');}
 this.stackFrames[stackFrame.id]=stackFrame;return stackFrame;},updateCategories_(){const categoriesDict={};this.userModel.addCategoriesToDict(categoriesDict);this.device.addCategoriesToDict(categoriesDict);this.kernel.addCategoriesToDict(categoriesDict);for(const pid in this.processes){this.processes[pid].addCategoriesToDict(categoriesDict);}
@@ -5800,7 +5573,7 @@
 class ProfilingDictionaryReader{constructor(opt_metadata,opt_maps,opt_groups,opt_parent){this.metadata=opt_metadata||new Map();this.maps=opt_maps||new Map();this.groups=opt_groups||new Map();this.parent_=opt_parent||undefined;this.inflated_=undefined;this.raw_=undefined;this.boundGetString_=this.getString.bind(this);this.deferenceStrings_=o=>deferenceStrings(this.boundGetString_,o);}
 static empty(){return new ProfilingDictionaryReader();}
 get parent(){return this.parent_;}
-get raw(){if(this.raw_)return this.raw_;this.raw_={};for(const[name,group]of this.groups.entries()){this.raw_[name]=group;}
+get ptr(){if(this.raw_)return this.raw_;this.raw_={};for(const[name,group]of this.groups.entries()){this.raw_[name]=group;}
 return this.raw_;}
 get inflated(){if(this.inflated_)return this.inflated_;this.inflated_={};for(const[name,group]of this.groups.entries()){this.inflated_[name]=this.inflateGroup(group);}
 return this.inflated_;}
@@ -5878,7 +5651,7 @@
 XMarkerAnnotationView.prototype={__proto__:tr.ui.annotations.AnnotationView.prototype,draw(ctx){const dt=this.viewport_.currentDisplayTransform;const viewX=dt.xWorldToView(this.annotation_.timestamp);ctx.beginPath();tr.ui.b.drawLine(ctx,viewX,0,viewX,ctx.canvas.height);ctx.strokeStyle=this.annotation_.strokeStyle;ctx.stroke();}};return{XMarkerAnnotationView,};});'use strict';tr.exportTo('tr.model',function(){function XMarkerAnnotation(timestamp){tr.model.Annotation.apply(this,arguments);this.timestamp=timestamp;this.strokeStyle='rgba(0, 0, 255, 0.5)';}
 XMarkerAnnotation.fromDict=function(dict){return new XMarkerAnnotation(dict.args.timestamp);};XMarkerAnnotation.prototype={__proto__:tr.model.Annotation.prototype,toDict(){return{typeName:'xmarker',args:{timestamp:this.timestamp}};},createView_(viewport){return new tr.ui.annotations.XMarkerAnnotationView(viewport,this);}};tr.model.Annotation.register(XMarkerAnnotation,{typeName:'xmarker'});return{XMarkerAnnotation,};});'use strict';tr.exportTo('tr.e.importer',function(){const Base64=tr.b.Base64;const deepCopy=tr.b.deepCopy;const ColorScheme=tr.b.ColorScheme;const HeapDumpTraceEventImporter=tr.e.importer.HeapDumpTraceEventImporter;const LegacyHeapDumpTraceEventImporter=tr.e.importer.LegacyHeapDumpTraceEventImporter;const StreamingEventExpander=tr.e.importer.StreamingEventExpander;const ProfilingDictionaryReader=tr.e.importer.ProfilingDictionaryReader;const MEASURE_NAME_REGEX=tr.e.measure.MEASURE_NAME_REGEX;function getEventColor(event,opt_customName){if(event.cname){return ColorScheme.getColorIdForReservedName(event.cname);}else if(opt_customName||event.name){return ColorScheme.getColorIdForGeneralPurposeString(opt_customName||event.name);}}
 function isLegacyChromeClockSyncEvent(event){return event.name!==undefined&&event.name.startsWith(LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX)&&((event.ph==='S')||(event.ph==='F'));}
-const PRODUCER='producer';const CONSUMER='consumer';const STEP='step';const BACKGROUND=tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;const LIGHT=tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;const DETAILED=tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;const MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER=[undefined,BACKGROUND,LIGHT,DETAILED];const GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX='global/';const LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX='ClockSyncEvent.';const BYTE_STAT_NAME_MAP={'pc':'privateCleanResident','pd':'privateDirtyResident','sc':'sharedCleanResident','sd':'sharedDirtyResident','pss':'proportionalResident','sw':'swapped'};const WEAK_MEMORY_ALLOCATOR_DUMP_FLAG=1<<0;const OBJECT_TYPE_NAME_PATTERNS=[{prefix:'const char *WTF::getStringWithTypeName() [T = ',suffix:']'},{prefix:'const char* WTF::getStringWithTypeName() [with T = ',suffix:']'},{prefix:'const char *__cdecl WTF::getStringWithTypeName<',suffix:'>(void)'}];const SUBTRACE_FIELDS=new Set(['powerTraceAsString','systemTraceEvents','androidProcessDump',]);const NON_METADATA_FIELDS=new Set(['displayTimeUnit','samples','stackFrames','traceAnnotations','traceEvents',...SUBTRACE_FIELDS]);function TraceEventImporter(model,eventData){this.hasEvents_=undefined;this.importPriority=1;this.model_=model;this.events_=undefined;this.sampleEvents_=undefined;this.stackFrameEvents_=undefined;this.stackFrameTree_=new tr.model.ProfileTree();this.subtraces_=[];this.eventsWereFromString_=false;this.softwareMeasuredCpuCount_=undefined;this.allAsyncEvents_=[];this.allFlowEvents_=[];this.allObjectEvents_=[];this.contextProcessorPerThread={};this.traceEventSampleStackFramesByName_={};this.v8ProcessCodeMaps_={};this.v8ProcessRootStackFrame_={};this.v8SamplingData_=[];this.profileTrees_=new Map();this.profileInfo_=new Map();this.legacyChromeClockSyncStartEvent_=undefined;this.legacyChromeClockSyncFinishEvent_=undefined;this.allMemoryDumpEvents_={};this.heapProfileExpander=new ProfilingDictionaryReader();this.objectTypeNameMap_={};this.clockDomainId_=tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;this.toModelTime_=undefined;if(typeof(eventData)==='string'||eventData instanceof String){eventData=eventData.trim();if(eventData[0]==='['){eventData=eventData.replace(/\s*,\s*$/,'');if(eventData[eventData.length-1]!==']'){eventData=eventData+']';}}
+const PRODUCER='producer';const CONSUMER='consumer';const STEP='step';const BACKGROUND=tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;const LIGHT=tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;const DETAILED=tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;const MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER=[undefined,BACKGROUND,LIGHT,DETAILED];const GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX='global/';const LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX='ClockSyncEvent.';const BYTE_STAT_NAME_MAP={'pc':'privateCleanResident','pd':'privateDirtyResident','sc':'sharedCleanResident','sd':'sharedDirtyResident','pss':'proportionalResident','sw':'swapped'};const WEAK_MEMORY_ALLOCATOR_DUMP_FLAG=1<<0;const OBJECT_TYPE_NAME_PATTERNS=[{prefix:'const char *WTF::getStringWithTypeName() [T = ',suffix:']'},{prefix:'const char* WTF::getStringWithTypeName() [with T = ',suffix:']'},{prefix:'const char *__cdecl WTF::getStringWithTypeName<',suffix:'>(void)'}];const SUBTRACE_FIELDS=new Set(['powerTraceAsString','systemTraceEvents','androidProcessDump','cgroupDump',]);const NON_METADATA_FIELDS=new Set(['displayTimeUnit','samples','stackFrames','traceAnnotations','traceEvents',...SUBTRACE_FIELDS]);function TraceEventImporter(model,eventData){this.hasEvents_=undefined;this.importPriority=1;this.model_=model;this.events_=undefined;this.sampleEvents_=undefined;this.stackFrameEvents_=undefined;this.stackFrameTree_=new tr.model.ProfileTree();this.subtraces_=[];this.eventsWereFromString_=false;this.softwareMeasuredCpuCount_=undefined;this.allAsyncEvents_=[];this.allFlowEvents_=[];this.allObjectEvents_=[];this.contextProcessorPerThread={};this.traceEventSampleStackFramesByName_={};this.v8ProcessCodeMaps_={};this.v8ProcessRootStackFrame_={};this.v8SamplingData_=[];this.profileTrees_=new Map();this.profileInfo_=new Map();this.legacyChromeClockSyncStartEvent_=undefined;this.legacyChromeClockSyncFinishEvent_=undefined;this.allMemoryDumpEvents_={};this.heapProfileExpander=new ProfilingDictionaryReader();this.objectTypeNameMap_={};this.clockDomainId_=tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;this.toModelTime_=undefined;if(typeof(eventData)==='string'||eventData instanceof String){eventData=eventData.trim();if(eventData[0]==='['){eventData=eventData.replace(/\s*,\s*$/,'');if(eventData[eventData.length-1]!==']'){eventData=eventData+']';}}
 this.events_=JSON.parse(eventData);this.eventsWereFromString_=true;}else{this.events_=eventData;}
 if(this.events_.traceEvents){const container=this.events_;this.events_=this.events_.traceEvents;for(const subtraceField of SUBTRACE_FIELDS){if(container[subtraceField]){this.storeSubtrace_(container[subtraceField]);}}
 this.storeSamples_(container.samples);this.storeStackFrames_(container.stackFrames);this.storeDisplayTimeUnit_(container.displayTimeUnit);this.storeTraceAnnotations_(container.traceAnnotations);this.storeMetadata_(container);}else if(this.events_ instanceof tr.b.TraceStream){const parser=oboe().node('{cat ph}',function(e){return oboe.drop;}).node('!.powerTraceAsString',this.storeSubtrace_.bind(this)).node('!.systemTraceEvents',this.storeSubtrace_.bind(this)).node('!.samples',this.storeSamples_.bind(this)).node('!.stackFrames',this.storeStackFrames_.bind(this)).node('!.displayTimeUnit',this.storeDisplayTimeUnit_.bind(this)).node('!.traceAnnotations',this.storeTraceAnnotations_.bind(this)).done(this.storeMetadata_.bind(this));this.events_.rewind();while(this.events_.hasData){parser.write(this.events_.readNumBytes());}
@@ -5917,10 +5690,10 @@
 const profileTree=new tr.model.ProfileTree();profileTreeMap.set(id,profileTree);const info=this.profileInfo_.get(id);if(info!==undefined){profileTree.startTime=info.startTime;profileTree.pid=info.pid;profileTree.tid=info.tid;}
 return profileTree;},processSample(event){if(event.args===undefined||event.args.data===undefined){return;}
 if(event.id===undefined){throw new Error('No event ID in sample');}
-const data=event.args.data;if(data.startTime!==undefined){this.profileInfo_.set(event.id,{startTime:data.startTime,pid:event.pid,tid:event.tid});}
+const data=event.args.data;if(data.startTime!==undefined){this.profileInfo_.set(`${event.pid} ${event.id}`,{startTime:data.startTime,pid:event.pid,tid:event.tid});}
 const timeDeltas=data.timeDeltas;for(const sampleType in data){if(sampleType==='timeDeltas'||sampleType==='startTime'){continue;}
 if(data[sampleType].samples&&timeDeltas&&data[sampleType].samples.length!==timeDeltas.length){throw new Error('samples and timeDeltas array should have same length');}
-const profileTree=this.getOrCreateProfileTree_(sampleType,event.id);const nodes=data[sampleType].nodes;const samples=data[sampleType].samples;if(nodes!==undefined){for(const node of nodes){const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);const profileNode=ProfileNodeType.constructFromObject(profileTree,node);if(profileNode===undefined){continue;}
+const profileTree=this.getOrCreateProfileTree_(sampleType,`${event.pid} ${event.id}`);const nodes=data[sampleType].nodes;const samples=data[sampleType].samples;if(nodes!==undefined){for(const node of nodes){const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);const profileNode=ProfileNodeType.constructFromObject(profileTree,node);if(profileNode===undefined){continue;}
 profileTree.add(profileNode);}}
 if(samples!==undefined){const thread=this.model_.getOrCreateProcess(profileTree.pid).getOrCreateThread(profileTree.tid);for(let i=0,len=samples.length;i<len;++i){const node=profileTree.getNode(samples[i]);profileTree.endTime+=timeDeltas[i];if(node===undefined)continue;const start=this.toModelTimeFromUs_(profileTree.endTime);this.model_.samples.push(new tr.model.Sample(start,node.sampleTitle,node,thread));}}}},processLegacyV8Sample(event){const data=event.args.data;const sampleType='legacySample';const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);if(data.vm_state==='js'&&!data.stack.length)return;const profileTree=this.getOrCreateProfileTree_(sampleType,event.pid);if(profileTree.getNode(-1)===undefined){profileTree.add(new ProfileNodeType(-1,{url:'',scriptId:-1,functionName:'unknown'},undefined));}
 let node=undefined;if(data.stack.length>0&&this.v8ProcessCodeMaps_[event.pid]){const map=this.v8ProcessCodeMaps_[event.pid];data.stack.reverse();let parentNode=undefined;for(let i=0;i<data.stack.length;i++){const entry=map.lookupEntry(data.stack[i]);if(entry===undefined){node=profileTree.getNode(-1);}else{node=profileTree.getNode(entry.id);if(node===undefined){const sourceInfo=entry.sourceInfo;node=new ProfileNodeType(entry.id,{functionName:entry.name,url:entry.sourceInfo.file,lineNumber:sourceInfo.line!==-1?sourceInfo.line:undefined,columnNumber:sourceInfo.column!==-1?sourceInfo.column:undefined,scriptid:entry.sourceInfo.scriptId},parentNode);profileTree.add(node);}}
@@ -6298,9 +6071,12 @@
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addL2Cycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.l2Sample(hwcTitle,'cycles',ts,eventBase);}
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));}};Parser.register(MaliParser);return{MaliParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function MemReclaimParser(importer){Parser.call(this,importer);importer.registerEventHandler('mm_vmscan_kswapd_wake',MemReclaimParser.prototype.kswapdWake.bind(this));importer.registerEventHandler('mm_vmscan_kswapd_sleep',MemReclaimParser.prototype.kswapdSleep.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_begin',MemReclaimParser.prototype.reclaimBegin.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_end',MemReclaimParser.prototype.reclaimEnd.bind(this));importer.registerEventHandler('lowmemory_kill',MemReclaimParser.prototype.lowmemoryKill.bind(this));}
 const kswapdWakeRE=/nid=(\d+) order=(\d+)/;const kswapdSleepRE=/nid=(\d+)/;const reclaimBeginRE=/order=(\d+) may_writepage=\d+ gfp_flags=(.+)/;const reclaimEndRE=/nr_reclaimed=(\d+)/;const lowmemoryRE=/([^ ]+) \((\d+)\), page cache (\d+)kB \(limit (\d+)kB\), free (-?\d+)Kb/;MemReclaimParser.prototype={__proto__:Parser.prototype,kswapdWake(eventName,cpuNumber,pid,ts,eventBase){const event=kswapdWakeRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const nid=parseInt(event[1]);const order=parseInt(event[2]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS){if(order>kthread.order){kthread.order=order;}}else{kthread.openSliceTS=ts;kthread.order=order;}
-return true;},kswapdSleep(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim',eventBase.threadName,kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order});}
-kthread.openSliceTS=undefined;kthread.order=undefined;return true;},reclaimBegin(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimBeginRE.exec(eventBase.details);if(!event)return false;const order=parseInt(event[1]);const gfp=event[2];const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.openSliceTS=ts;kthread.order=order;kthread.gfp=gfp;return true;},reclaimEnd(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimEndRE.exec(eventBase.details);if(!event)return false;const nrReclaimed=parseInt(event[1]);const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS!==undefined){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim','direct reclaim',kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order,gfp:kthread.gfp,nr_reclaimed:nrReclaimed});}
-kthread.openSliceTS=undefined;kthread.order=undefined;kthread.gfp=undefined;return true;},lowmemoryKill(eventName,cpuNumber,pid,ts,eventBase){const event=lowmemoryRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const killedName=event[1];const killedPid=parseInt(event[2]);const cache=parseInt(event[3]);const free=parseInt(event[5]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.thread.sliceGroup.pushCompleteSlice('lowmemory','low memory kill',ts,0,0,0,{killed_name:killedName,killed_pid:killedPid,cache,free});return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency_limits',PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));}
+kthread.waitingFor='kswapSleep';return true;},kswapdSleep(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.waitingFor!=='kswapSleep')return false;kthread.waitingFor=undefined;if(kthread.openSliceTS){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim',eventBase.threadName,kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order});}
+kthread.openSliceTS=undefined;kthread.order=undefined;return true;},reclaimBegin(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimBeginRE.exec(eventBase.details);if(!event)return false;const order=parseInt(event[1]);const gfp=event[2];const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.openMemReclaimSliceTS=ts;kthread.order=order;kthread.gfp=gfp;kthread.waitingFor='reclaimEnd';return true;},reclaimEnd(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimEndRE.exec(eventBase.details);if(!event)return false;const nrReclaimed=parseInt(event[1]);const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.waitingFor!=='reclaimEnd')return false;kthread.waitingFor=undefined;if(kthread.openMemReclaimSliceTS!==undefined){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim','direct reclaim',kthread.openMemReclaimSliceTS,ts-kthread.openMemReclaimSliceTS,0,0,{order:kthread.order,gfp:kthread.gfp,nr_reclaimed:nrReclaimed});kthread.openMemReclaimSliceTS=undefined;kthread.order=undefined;kthread.gfp=undefined;return true;}
+return false;},lowmemoryKill(eventName,cpuNumber,pid,ts,eventBase){const event=lowmemoryRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const killedName=event[1];const killedPid=parseInt(event[2]);const cache=parseInt(event[3]);const free=parseInt(event[5]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.thread.sliceGroup.pushCompleteSlice('lowmemory','low memory kill',ts,0,0,0,{killed_name:killedName,killed_pid:killedPid,cache,free});return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function MSMParser(importer){Parser.call(this,importer);importer.registerEventHandler('msm_gpu_freq_change',MSMParser.prototype.gpuFrequency.bind(this));importer.registerEventHandler('msm_gpu_submit_flush',MSMParser.prototype.gpuSubmitFlush.bind(this));importer.registerEventHandler('msm_gpu_submit_retired',MSMParser.prototype.gpuSubmitRetired.bind(this));this.model_=importer.model_;this.submits={};this.num_submits=0;}
+MSMParser.prototype={__proto__:Parser.prototype,gpuFrequency(eventName,cpuNumber,pid,ts,eventBase){const event=/new_freq=(\d+)/.exec(eventBase.details);if(!event)return false;const freq=parseInt(event[1]);const counter=this.model_.kernel.getOrCreateCounter('GPU','GPU Frequency');if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries('frequency',ColorScheme.getColorIdForGeneralPurposeString(counter.name)));}
+counter.series.forEach(function(series){series.addCounterSample(ts,freq);});return true;},gpuSubmitFlush(eventName,cpuNumber,pid,ts,eventBase){const event=/id=(\d+) pid=(\d+) ring=(\d+):(\d+) ticks=(\d+)/.exec(eventBase.details);if(!event)return false;const id=parseInt(event[1]);const submit={};submit.flushTS=ts;submit.flushTicks=parseInt(event[5]);submit.pid=parseInt(event[2]);this.submits[id]=submit;this.num_submits++;return true;},gpuSubmitRetired(eventName,cpuNumber,pid,ts,eventBase){const event=/id=(\d+) pid=(\d+) ring=(\d+):(\d+) elapsed=(\d+) ns mhz=(\d+) start=(\d+) end=(\d+)/.exec(eventBase.details);if(!event)return false;const id=parseInt(event[1]);if(!(id in this.submits))return true;const submit=this.submits[id];delete this.submits[id];this.num_submits--;const gpuThread=this.importer.getOrCreatePseudoThread('GPU');submit.elapsedNs=parseInt(event[5]);submit.mhz=parseInt(event[6]);submit.startTicks=parseInt(event[7]);submit.endTicks=parseInt(event[8]);function ticks2ms(ticks){return ticks/19200;}
+const queuedDuration=ticks2ms(submit.startTicks-submit.flushTicks);const runningDuration=ticks2ms(submit.endTicks-submit.startTicks);submit.queuedDuration=queuedDuration;submit.runningDuration=runningDuration;const queued=new tr.model.AsyncSlice('',event[1]+' queued',tr.b.ColorScheme.getColorIdForReservedName('thread_state_runnable'),submit.flushTS,submit,queuedDuration);const running=new tr.model.AsyncSlice('',event[1]+' running',tr.b.ColorScheme.getColorIdForReservedName('thread_state_running'),submit.flushTS+queuedDuration,submit,runningDuration);const async=new tr.model.AsyncSlice('','pipeline',ColorScheme.getColorIdForGeneralPurposeString('ongpu:'+submit.pid),submit.flushTS,submit,queuedDuration+runningDuration);async.hidden=true;async.subSlices.push(queued);async.subSlices.push(running);gpuThread.thread.asyncSliceGroup.push(async);const onGpu=new tr.model.ThreadSlice('',event[1],ColorScheme.getColorIdForGeneralPurposeString('ongpu:'+submit.pid),submit.flushTS+queuedDuration,submit,runningDuration);gpuThread.thread.sliceGroup.pushSlice(onGpu);return true;}};Parser.register(MSMParser);return{MSMParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency_limits',PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));}
 PowerParser.prototype={__proto__:Parser.prototype,cpuStateSlice(ts,targetCpuNumber,eventType,cpuState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);if(eventType!=='1'){this.importer.model.importWarning({type:'parse_error',message:'Don\'t understand power_start events of '+'type '+eventType});return;}
 const powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));}
 powerCounter.series.forEach(function(series){series.addCounterSample(ts,cpuState);});},cpuIdleSlice(ts,targetCpuNumber,cpuState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);const powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name)));}
@@ -6322,7 +6098,9 @@
 thread.lastActiveTs=ts;thread.lastActiveValue=event[2];return true;},syncWaitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=syncWaitRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
 const tgid=parseInt(eventBase.tgid);const thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;const slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
 const name='fence_wait("'+event[2]+'")';if(event[1]==='begin'){const slice=slices.beginSlice(null,name,ts,{'Start state':event[3]});}else if(event[1]==='end'){if(slices.openSliceCount>0){slices.endSlice(ts);}}else{return false;}
-return true;},syncPtEvent(eventName,cpuNumber,pid,ts,eventBase){return!!syncPtRE.exec(eventBase.details);}};Parser.register(SyncParser);return{SyncParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function WorkqueueParser(importer){Parser.call(this,importer);importer.registerEventHandler('workqueue_execute_start',WorkqueueParser.prototype.executeStartEvent.bind(this));importer.registerEventHandler('workqueue_execute_end',WorkqueueParser.prototype.executeEndEvent.bind(this));importer.registerEventHandler('workqueue_queue_work',WorkqueueParser.prototype.executeQueueWork.bind(this));importer.registerEventHandler('workqueue_activate_work',WorkqueueParser.prototype.executeActivateWork.bind(this));}
+return true;},syncPtEvent(eventName,cpuNumber,pid,ts,eventBase){return!!syncPtRE.exec(eventBase.details);}};Parser.register(SyncParser);return{SyncParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function ThermalParser(importer){Parser.call(this,importer);importer.registerEventHandler('thermal_temperature',ThermalParser.prototype.traceMarkWriteTemperatureEvent.bind(this));importer.registerEventHandler('cdev_update',ThermalParser.prototype.traceMarkWriteCdevEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+ThermalParser.prototype={__proto__:Parser.prototype,thermalMark(name,subName,value,ts){const ctr=this.model_.kernel.getOrCreateCounter(null,name+' '+subName);if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,value);});},traceMarkWriteTemperatureEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/thermal_zone=(\S+) id=(\d+) temp_prev=(\d+) temp=(\d+)/.exec(eventBase.details);const name=event[1];const temp=parseInt(event[4]);this.thermalMark(name,'Temperature',temp,ts);return true;},traceMarkWriteCdevEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/type=(\S+) target=(\d+)/.exec(eventBase.details);const name=event[1];const rate=parseInt(event[2]);this.thermalMark(name,'CoolingDevice',rate,ts);return true;}};Parser.register(ThermalParser);return{ThermalParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function WorkqueueParser(importer){Parser.call(this,importer);importer.registerEventHandler('workqueue_execute_start',WorkqueueParser.prototype.executeStartEvent.bind(this));importer.registerEventHandler('workqueue_execute_end',WorkqueueParser.prototype.executeEndEvent.bind(this));importer.registerEventHandler('workqueue_queue_work',WorkqueueParser.prototype.executeQueueWork.bind(this));importer.registerEventHandler('workqueue_activate_work',WorkqueueParser.prototype.executeActivateWork.bind(this));}
 const workqueueExecuteStartRE=/work struct (.+): function (\S+)/;const workqueueExecuteEndRE=/work struct (.+)/;WorkqueueParser.prototype={__proto__:Parser.prototype,executeStartEvent(eventName,cpuNumber,pid,ts,eventBase){const event=workqueueExecuteStartRE.exec(eventBase.details);if(!event)return false;const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);kthread.openSliceTS=ts;kthread.openSlice=event[2];return true;},executeEndEvent(eventName,cpuNumber,pid,ts,eventBase){const event=workqueueExecuteEndRE.exec(eventBase.details);if(!event)return false;const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);if(kthread.openSlice){const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,{},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
 kthread.openSlice=undefined;return true;},executeQueueWork(eventName,cpuNumber,pid,ts,eventBase){return true;},executeActivateWork(eventName,cpuNumber,pid,ts,eventBase){return true;}};Parser.register(WorkqueueParser);return{WorkqueueParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID='linux_clock_monotonic_to_ftrace_global';const IMPORT_PRIORITY=2;function FTraceImporter(model,events){this.importPriority=IMPORT_PRIORITY;this.model_=model;this.events_=events;this.wakeups_=[];this.blockedReasons_=[];this.kernelThreadStates_={};this.buildMapFromLinuxPidsToThreads_();this.lines_=[];this.pseudoThreadCounter=1;this.parsers_=[];this.eventHandlers_={};this.haveClockSyncedMonotonicToGlobal_=false;this.clockDomainId_=tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL;}
 const TestExports={};const lineREWithTGID=new RegExp('^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]'+'\\s+[dX.][Nnp.][Hhs.][0-9a-f.]'+'\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');const lineParserWithTGID=function(line){const groups=lineREWithTGID.exec(line);if(!groups)return groups;let tgid=groups[3];if(tgid[0]==='-')tgid=undefined;return{threadName:groups[1],pid:groups[2],tgid,cpuNumber:groups[4],timestamp:groups[5],eventName:groups[6],details:groups[7]};};TestExports.lineParserWithTGID=lineParserWithTGID;const lineREWithIRQInfo=new RegExp('^\\s*(.+)-(\\d+)\\s+\\[(\\d+)\\]'+'\\s+[dX.][Nnp.][Hhs.][0-9a-f.]'+'\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');const lineParserWithIRQInfo=function(line){const groups=lineREWithIRQInfo.exec(line);if(!groups)return groups;return{threadName:groups[1],pid:groups[2],cpuNumber:groups[3],timestamp:groups[4],eventName:groups[5],details:groups[6]};};TestExports.lineParserWithIRQInfo=lineParserWithIRQInfo;const lineREWithLegacyFmt=/^\s*(.+)-(\d+)\s+\[(\d+)\]\s*(\d+\.\d+):\s+(\S+):\s(.*)$/;const lineParserWithLegacyFmt=function(line){const groups=lineREWithLegacyFmt.exec(line);if(!groups){return groups;}
@@ -6623,20 +6401,22 @@
 if(fiCandidate===undefined){if(reachedFCIQuiescence_(searchEnd,quietWindowBegin,searchBegin)){fiCandidate=quietWindowBegin;}else{return undefined;}}
 return Math.max(fiCandidate,domContentLoadedEnd);}
 return{findInteractiveTime,findFirstCpuIdleTime,requiredFCIWindowSizeMs,findFCITaskClusters,};});'use strict';tr.exportTo('tr.model.um',function(){const LOAD_SUBTYPE_NAMES={SUCCESSFUL:'Successful',FAILED:'Failed',};const DOES_LOAD_SUBTYPE_NAME_EXIST={};for(const key in LOAD_SUBTYPE_NAMES){DOES_LOAD_SUBTYPE_NAME_EXIST[LOAD_SUBTYPE_NAMES[key]]=true;}
-function LoadExpectation(parentModel,initiatorTitle,start,duration,renderer,navigationStart,fmpEvent,dclEndEvent,cpuIdleTime,timeToInteractive,url,frameId){if(!DOES_LOAD_SUBTYPE_NAME_EXIST[initiatorTitle]){throw new Error(initiatorTitle+' is not in LOAD_SUBTYPE_NAMES');}
-tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);this.renderProcess=renderer;this.renderMainThread=undefined;this.routingId=undefined;this.parentRoutingId=undefined;this.loadFinishedEvent=undefined;this.navigationStart=navigationStart;this.fmpEvent=fmpEvent;this.domContentLoadedEndEvent=dclEndEvent;this.firstCpuIdleTime=cpuIdleTime;this.timeToInteractive=timeToInteractive;this.url=url;this.frameId=frameId;}
+function LoadExpectation(parentModel,initiatorTitle,start,duration,renderer,navigationStart,fmpEvent,fcpEvent,dclEndEvent,cpuIdleTime,timeToInteractive,totalBlockingTime,url,frameId){if(!DOES_LOAD_SUBTYPE_NAME_EXIST[initiatorTitle]){throw new Error(initiatorTitle+' is not in LOAD_SUBTYPE_NAMES');}
+tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);this.renderProcess=renderer;this.renderMainThread=undefined;this.routingId=undefined;this.parentRoutingId=undefined;this.loadFinishedEvent=undefined;this.navigationStart=navigationStart;this.fmpEvent=fmpEvent;this.fcpEvent=fcpEvent;this.domContentLoadedEndEvent=dclEndEvent;this.firstCpuIdleTime=cpuIdleTime;this.timeToInteractive=timeToInteractive;this.totalBlockingTime=totalBlockingTime;this.url=url;this.frameId=frameId;}
 LoadExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:LoadExpectation};tr.model.um.UserExpectation.subTypes.register(LoadExpectation,{stageTitle:'Load',colorId:tr.b.ColorScheme.getColorIdForReservedName('rail_load')});return{LOAD_SUBTYPE_NAMES,LoadExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const LONG_TASK_THRESHOLD_MS=50;const IGNORE_URLS=['','about:blank',];function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
 return snapshot;}
 function findFirstMeaningfulPaintCandidates(rendererHelper){const candidatesForFrameId={};for(const ev of rendererHelper.process.getDescendantEvents()){if(!tr.e.chrome.EventFinderUtils.hasCategoryAndName(ev,'loading','firstMeaningfulPaintCandidate')){continue;}
 if(rendererHelper.isTelemetryInternalEvent(ev))continue;const frameIdRef=ev.args.frame;if(frameIdRef===undefined)continue;let list=candidatesForFrameId[frameIdRef];if(list===undefined){candidatesForFrameId[frameIdRef]=list=[];}
 list.push(ev);}
 return candidatesForFrameId;}
-function computeInteractivityMetricSample_(rendererHelper,navigationStart,fmpEvent,domContentLoadedEndEvent,searchWindowEnd){if(domContentLoadedEndEvent===undefined||fmpEvent===undefined){return{interactiveTime:undefined,firstCpuIdleTime:undefined};}
-const firstMeaningfulPaintTime=fmpEvent.start;const mainThreadTasks=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const longTasks=mainThreadTasks.filter(task=>task.duration>=LONG_TASK_THRESHOLD_MS);const longTasksInWindow=longTasks.filter(task=>task.range.intersectsExplicitRangeInclusive(firstMeaningfulPaintTime,searchWindowEnd));const resourceLoadEvents=tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd));const firstCpuIdleTime=tr.e.chrome.findFirstCpuIdleTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow);const interactiveTime=resourceLoadEvents.length>0?tr.e.chrome.findInteractiveTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow,resourceLoadEvents):undefined;return{interactiveTime,firstCpuIdleTime};}
-function constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,navigationStart,fmpEvent,searchWindowEnd,url,frameId){const dclTimesForFrame=frameToDomContentLoadedEndEvents.get(frameId)||[];const dclSearchRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd);const dclTimesInWindow=dclSearchRange.filterArray(dclTimesForFrame,event=>event.start);let domContentLoadedEndEvent=undefined;if(dclTimesInWindow.length!==0){domContentLoadedEndEvent=dclTimesInWindow[dclTimesInWindow.length-1];}
-const{interactiveTime,firstCpuIdleTime}=computeInteractivityMetricSample_(rendererHelper,navigationStart,fmpEvent,domContentLoadedEndEvent,searchWindowEnd);const duration=(interactiveTime===undefined)?searchWindowEnd-navigationStart.start:interactiveTime-navigationStart.start;return new tr.model.um.LoadExpectation(rendererHelper.modelHelper.model,tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL,navigationStart.start,duration,rendererHelper.process,navigationStart,fmpEvent,domContentLoadedEndEvent,firstCpuIdleTime,interactiveTime,url,frameId);}
-function collectLoadExpectationsForRenderer(rendererHelper){const samples=[];const frameToNavStartEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const frameToDomContentLoadedEndEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'domContentLoadedEventEnd','blink.user_timing');function addSamples(frameIdRef,navigationStart,fmpCandidateEvents,searchWindowEnd,url){let fmpMarkerEvent=tr.e.chrome.EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(fmpCandidateEvents,searchWindowEnd);if(fmpMarkerEvent!==undefined&&navigationStart.start>fmpMarkerEvent.start){fmpMarkerEvent=undefined;}
-samples.push(constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,navigationStart,fmpMarkerEvent,searchWindowEnd,url,frameIdRef));}
+function computeTotalBlockingTime_(fcpTime,interactiveTime,topLevelTasks){let sumBlockingTime=0;for(const event of topLevelTasks){if(event.duration<LONG_TASK_THRESHOLD_MS)continue;if(event.end<fcpTime)continue;if(event.start>interactiveTime)continue;const clippedStart=Math.max(event.start,fcpTime);const clippedEnd=Math.min(event.end,interactiveTime);const clippedDuration=clippedEnd-clippedStart;if(clippedDuration<LONG_TASK_THRESHOLD_MS)continue;sumBlockingTime+=(clippedDuration-LONG_TASK_THRESHOLD_MS);}
+return sumBlockingTime;}
+function computeInteractivityMetricSample_(rendererHelper,navigationStart,fcpEvent,domContentLoadedEndEvent,searchWindowEnd){if(domContentLoadedEndEvent===undefined||fcpEvent===undefined){return{interactiveTime:undefined,firstCpuIdleTime:undefined,totalBlockingTime:undefined};}
+const firstContentfulPaintTime=fcpEvent.start;const mainThreadTasks=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const longTasks=mainThreadTasks.filter(task=>task.duration>=LONG_TASK_THRESHOLD_MS);const longTasksInWindow=longTasks.filter(task=>task.range.intersectsExplicitRangeInclusive(firstContentfulPaintTime,searchWindowEnd));const resourceLoadEvents=tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd));const firstCpuIdleTime=tr.e.chrome.findFirstCpuIdleTime(firstContentfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow);const interactiveTime=resourceLoadEvents.length>0?tr.e.chrome.findInteractiveTime(firstContentfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow,resourceLoadEvents):undefined;const totalBlockingTime=interactiveTime?computeTotalBlockingTime_(fcpEvent.start,interactiveTime,longTasks):undefined;return{interactiveTime,firstCpuIdleTime,totalBlockingTime};}
+function constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,frameToFcpEvents,navigationStart,fmpEvent,searchWindowEnd,url,frameId){const searchRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd);const dclTimesForFrame=frameToDomContentLoadedEndEvents.get(frameId)||[];const dclTimesInWindow=searchRange.filterArray(dclTimesForFrame,event=>event.start);let domContentLoadedEndEvent=undefined;if(dclTimesInWindow.length!==0){domContentLoadedEndEvent=dclTimesInWindow[dclTimesInWindow.length-1];}
+const fcpForFrame=frameToFcpEvents.get(frameId)||[];const fcpInWindow=searchRange.filterArray(fcpForFrame,event=>event.start);const fcpEvent=fcpInWindow[0];const{interactiveTime,firstCpuIdleTime,totalBlockingTime}=computeInteractivityMetricSample_(rendererHelper,navigationStart,fcpEvent,domContentLoadedEndEvent,searchWindowEnd);const duration=(interactiveTime===undefined)?searchWindowEnd-navigationStart.start:interactiveTime-navigationStart.start;return new tr.model.um.LoadExpectation(rendererHelper.modelHelper.model,tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL,navigationStart.start,duration,rendererHelper.process,navigationStart,fmpEvent,fcpEvent,domContentLoadedEndEvent,firstCpuIdleTime,interactiveTime,totalBlockingTime,url,frameId);}
+function collectLoadExpectationsForRenderer(rendererHelper){const samples=[];const frameToNavStartEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const frameToDomContentLoadedEndEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'domContentLoadedEventEnd','blink.user_timing');const frameToFcpEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'firstContentfulPaint','loading');function addSamples(frameIdRef,navigationStart,fmpCandidateEvents,searchWindowEnd,url){let fmpMarkerEvent=tr.e.chrome.EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(fmpCandidateEvents,searchWindowEnd);if(fmpMarkerEvent!==undefined&&navigationStart.start>fmpMarkerEvent.start){fmpMarkerEvent=undefined;}
+samples.push(constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,frameToFcpEvents,navigationStart,fmpMarkerEvent,searchWindowEnd,url,frameIdRef));}
 const candidatesForFrameId=findFirstMeaningfulPaintCandidates(rendererHelper);for(const[frameIdRef,navStartEvents]of frameToNavStartEvents){const fmpCandidateEvents=candidatesForFrameId[frameIdRef]||[];let prevNavigation={navigationEvent:undefined,url:undefined};for(let index=0;index<navStartEvents.length;index++){const currNavigation=navStartEvents[index];let url;let isLoadingMainFrame=false;if(currNavigation.args.data){url=currNavigation.args.data.documentLoaderURL;isLoadingMainFrame=currNavigation.args.data.isLoadingMainFrame;}else{const snapshot=findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,currNavigation.start);if(snapshot){url=snapshot.args.documentLoaderURL;isLoadingMainFrame=snapshot.args.isLoadingMainFrame;}}
 if(!isLoadingMainFrame)continue;if(url===undefined||IGNORE_URLS.includes(url))continue;if(prevNavigation.navigationEvent!==undefined){addSamples(frameIdRef,prevNavigation.navigationEvent,fmpCandidateEvents,currNavigation.start,prevNavigation.url);}
 prevNavigation={navigationEvent:currNavigation,url};}
@@ -6918,7 +6698,8 @@
 if(opt_dictionary.color){spanEl.style.color=opt_dictionary.color;}}
 return spanEl;}
 function createLink(opt_args){let ownerDocument=document;if(opt_args&&opt_args.ownerDocument){ownerDocument=opt_args.ownerDocument;}
-const linkEl=ownerDocument.createElement('a');if(opt_args){if(opt_args.href)linkEl.href=opt_args.href;if(opt_args.tooltip)linkEl.title=opt_args.tooltip;if(opt_args.color)linkEl.style.color=opt_args.color;if(opt_args.bold)linkEl.style.fontWeight='bold';if(opt_args.italic)linkEl.style.fontStyle='italic';if(opt_args.className)linkEl.className=opt_args.className;if(opt_args.parent)Polymer.dom(opt_args.parent).appendChild(linkEl);if(opt_args.marginLeft)linkEl.style.marginLeft=opt_args.marginLeft;if(opt_args.marginRight)linkEl.style.marginRight=opt_args.marginRight;if(opt_args.backgroundColor){linkEl.style.backgroundColor=opt_args.backgroundColor;}
+const linkEl=ownerDocument.createElement('a');if(opt_args){if(opt_args.href){linkEl.href=opt_args.href;linkEl.target='_blank';}
+if(opt_args.tooltip)linkEl.title=opt_args.tooltip;if(opt_args.color)linkEl.style.color=opt_args.color;if(opt_args.bold)linkEl.style.fontWeight='bold';if(opt_args.italic)linkEl.style.fontStyle='italic';if(opt_args.className)linkEl.className=opt_args.className;if(opt_args.parent)Polymer.dom(opt_args.parent).appendChild(linkEl);if(opt_args.marginLeft)linkEl.style.marginLeft=opt_args.marginLeft;if(opt_args.marginRight)linkEl.style.marginRight=opt_args.marginRight;if(opt_args.backgroundColor){linkEl.style.backgroundColor=opt_args.backgroundColor;}
 if(opt_args.textContent){Polymer.dom(linkEl).textContent=opt_args.textContent;}}
 return linkEl;}
 function createDiv(opt_dictionary){const divEl=document.createElement('div');if(opt_dictionary){if(opt_dictionary.className){divEl.className=opt_dictionary.className;}
@@ -7319,7 +7100,7 @@
 static deserialize(data,deserializer){return new UnmergeableDiagnosticSet(d.map(i=>deserializer.getDiagnostic(i).diagnostic));}
 serialize(serializer){return this._diagnostics.map(d=>serializer.getOrAllocateDiagnosticId('',d));}
 static fromDict(d){return new UnmergeableDiagnosticSet(d.diagnostics.map(d=>((typeof d==='string')?new tr.v.d.DiagnosticRef(d):tr.v.d.Diagnostic.fromDict(d))));}}
-tr.v.d.Diagnostic.register(UnmergeableDiagnosticSet,{elementName:'tr-v-ui-unmergeable-diagnostic-set-span'});return{UnmergeableDiagnosticSet,};});'use strict';tr.exportTo('tr.v.d',function(){const RESERVED_INFOS={ANGLE_REVISIONS:{name:'angleRevisions',type:tr.v.d.GenericSet},ARCHITECTURES:{name:'architectures',type:tr.v.d.GenericSet},BENCHMARKS:{name:'benchmarks',type:tr.v.d.GenericSet},BENCHMARK_START:{name:'benchmarkStart',type:tr.v.d.DateRange},BENCHMARK_DESCRIPTIONS:{name:'benchmarkDescriptions',type:tr.v.d.GenericSet},BOTS:{name:'bots',type:tr.v.d.GenericSet},BUG_COMPONENTS:{name:'bugComponents',type:tr.v.d.GenericSet},BUILDS:{name:'builds',type:tr.v.d.GenericSet},CATAPULT_REVISIONS:{name:'catapultRevisions',type:tr.v.d.GenericSet},CHROMIUM_COMMIT_POSITIONS:{name:'chromiumCommitPositions',type:tr.v.d.GenericSet},CHROMIUM_REVISIONS:{name:'chromiumRevisions',type:tr.v.d.GenericSet},DESCRIPTION:{name:'description',type:tr.v.d.GenericSet},DEVICE_IDS:{name:'deviceIds',type:tr.v.d.GenericSet},DOCUMENTATION_URLS:{name:'documentationUrls',type:tr.v.d.GenericSet},FUCHSIA_GARNET_REVISIONS:{name:'fuchsiaGarnetRevisions',type:tr.v.d.GenericSet},FUCHSIA_PERIDOT_REVISIONS:{name:'fuchsiaPeridotRevisions',type:tr.v.d.GenericSet},FUCHSIA_TOPAZ_REVISIONS:{name:'fuchsiaTopazRevisions',type:tr.v.d.GenericSet},FUCHSIA_ZIRCON_REVISIONS:{name:'fuchsiaZirconRevisions',type:tr.v.d.GenericSet},GPUS:{name:'gpus',type:tr.v.d.GenericSet},IS_REFERENCE_BUILD:{name:'isReferenceBuild',type:tr.v.d.GenericSet},LABELS:{name:'labels',type:tr.v.d.GenericSet},LOG_URLS:{name:'logUrls',type:tr.v.d.GenericSet},MASTERS:{name:'masters',type:tr.v.d.GenericSet},MEMORY_AMOUNTS:{name:'memoryAmounts',type:tr.v.d.GenericSet},OS_NAMES:{name:'osNames',type:tr.v.d.GenericSet},OS_VERSIONS:{name:'osVersions',type:tr.v.d.GenericSet},OWNERS:{name:'owners',type:tr.v.d.GenericSet},POINT_ID:{name:'pointId',type:tr.v.d.GenericSet},PRODUCT_VERSIONS:{name:'productVersions',type:tr.v.d.GenericSet},REVISION_TIMESTAMPS:{name:'revisionTimestamps',type:tr.v.d.DateRange},SKIA_REVISIONS:{name:'skiaRevisions',type:tr.v.d.GenericSet},STATISTICS_NAMES:{name:'statisticsNames',type:tr.v.d.GenericSet},STORIES:{name:'stories',type:tr.v.d.GenericSet},STORYSET_REPEATS:{name:'storysetRepeats',type:tr.v.d.GenericSet},STORY_TAGS:{name:'storyTags',type:tr.v.d.GenericSet},SUMMARY_KEYS:{name:'summaryKeys',type:tr.v.d.GenericSet},TEST_PATH:{name:'testPath',type:tr.v.d.GenericSet},TRACE_START:{name:'traceStart',type:tr.v.d.DateRange},TRACE_URLS:{name:'traceUrls',type:tr.v.d.GenericSet},V8_COMMIT_POSITIONS:{name:'v8CommitPositions',type:tr.v.d.DateRange},V8_REVISIONS:{name:'v8Revisions',type:tr.v.d.GenericSet},WEBRTC_REVISIONS:{name:'webrtcRevisions',type:tr.v.d.GenericSet},WEBRTC_INTERNAL_REVISIONS:{name:'webrtcInternalRevisions',type:tr.v.d.GenericSet},};const RESERVED_NAMES={};const RESERVED_NAMES_TO_TYPES=new Map();for(const[codename,info]of Object.entries(RESERVED_INFOS)){RESERVED_NAMES[codename]=info.name;if(RESERVED_NAMES_TO_TYPES.has(info.name)){throw new Error(`Duplicate reserved name "${info.name}"`);}
+tr.v.d.Diagnostic.register(UnmergeableDiagnosticSet,{elementName:'tr-v-ui-unmergeable-diagnostic-set-span'});return{UnmergeableDiagnosticSet,};});'use strict';tr.exportTo('tr.v.d',function(){const RESERVED_INFOS={ALERT_GROUPING:{name:'alertGrouping',type:tr.v.d.GenericSet},ANGLE_REVISIONS:{name:'angleRevisions',type:tr.v.d.GenericSet},ARCHITECTURES:{name:'architectures',type:tr.v.d.GenericSet},BENCHMARKS:{name:'benchmarks',type:tr.v.d.GenericSet},BENCHMARK_START:{name:'benchmarkStart',type:tr.v.d.DateRange},BENCHMARK_DESCRIPTIONS:{name:'benchmarkDescriptions',type:tr.v.d.GenericSet},BOTS:{name:'bots',type:tr.v.d.GenericSet},BUG_COMPONENTS:{name:'bugComponents',type:tr.v.d.GenericSet},BUILDS:{name:'builds',type:tr.v.d.GenericSet},CATAPULT_REVISIONS:{name:'catapultRevisions',type:tr.v.d.GenericSet},CHROMIUM_COMMIT_POSITIONS:{name:'chromiumCommitPositions',type:tr.v.d.GenericSet},CHROMIUM_REVISIONS:{name:'chromiumRevisions',type:tr.v.d.GenericSet},DESCRIPTION:{name:'description',type:tr.v.d.GenericSet},DEVICE_IDS:{name:'deviceIds',type:tr.v.d.GenericSet},DOCUMENTATION_URLS:{name:'documentationUrls',type:tr.v.d.GenericSet},INFO_BLURB:{name:'infoBlurb',type:tr.v.d.GenericSet},FUCHSIA_GARNET_REVISIONS:{name:'fuchsiaGarnetRevisions',type:tr.v.d.GenericSet},FUCHSIA_PERIDOT_REVISIONS:{name:'fuchsiaPeridotRevisions',type:tr.v.d.GenericSet},FUCHSIA_TOPAZ_REVISIONS:{name:'fuchsiaTopazRevisions',type:tr.v.d.GenericSet},FUCHSIA_ZIRCON_REVISIONS:{name:'fuchsiaZirconRevisions',type:tr.v.d.GenericSet},GPUS:{name:'gpus',type:tr.v.d.GenericSet},IS_REFERENCE_BUILD:{name:'isReferenceBuild',type:tr.v.d.GenericSet},LABELS:{name:'labels',type:tr.v.d.GenericSet},LOG_URLS:{name:'logUrls',type:tr.v.d.GenericSet},MASTERS:{name:'masters',type:tr.v.d.GenericSet},MEMORY_AMOUNTS:{name:'memoryAmounts',type:tr.v.d.GenericSet},OS_NAMES:{name:'osNames',type:tr.v.d.GenericSet},OS_VERSIONS:{name:'osVersions',type:tr.v.d.GenericSet},OWNERS:{name:'owners',type:tr.v.d.GenericSet},POINT_ID:{name:'pointId',type:tr.v.d.GenericSet},PRODUCT_VERSIONS:{name:'productVersions',type:tr.v.d.GenericSet},REVISION_TIMESTAMPS:{name:'revisionTimestamps',type:tr.v.d.DateRange},SKIA_REVISIONS:{name:'skiaRevisions',type:tr.v.d.GenericSet},STATISTICS_NAMES:{name:'statisticsNames',type:tr.v.d.GenericSet},STORIES:{name:'stories',type:tr.v.d.GenericSet},STORYSET_REPEATS:{name:'storysetRepeats',type:tr.v.d.GenericSet},STORY_TAGS:{name:'storyTags',type:tr.v.d.GenericSet},SUMMARY_KEYS:{name:'summaryKeys',type:tr.v.d.GenericSet},TEST_PATH:{name:'testPath',type:tr.v.d.GenericSet},TRACE_START:{name:'traceStart',type:tr.v.d.DateRange},TRACE_URLS:{name:'traceUrls',type:tr.v.d.GenericSet},V8_COMMIT_POSITIONS:{name:'v8CommitPositions',type:tr.v.d.DateRange},V8_REVISIONS:{name:'v8Revisions',type:tr.v.d.GenericSet},WEBRTC_REVISIONS:{name:'webrtcRevisions',type:tr.v.d.GenericSet},WEBRTC_INTERNAL_REVISIONS:{name:'webrtcInternalRevisions',type:tr.v.d.GenericSet},};const RESERVED_NAMES={};const RESERVED_NAMES_TO_TYPES=new Map();for(const[codename,info]of Object.entries(RESERVED_INFOS)){RESERVED_NAMES[codename]=info.name;if(RESERVED_NAMES_TO_TYPES.has(info.name)){throw new Error(`Duplicate reserved name "${info.name}"`);}
 RESERVED_NAMES_TO_TYPES.set(info.name,info.type);}
 const RESERVED_NAMES_SET=new Set(Object.values(RESERVED_NAMES));return{RESERVED_INFOS,RESERVED_NAMES,RESERVED_NAMES_SET,RESERVED_NAMES_TO_TYPES,};});'use strict';tr.exportTo('tr.v.d',function(){class DiagnosticMap extends Map{constructor(opt_allowReservedNames){super();if(opt_allowReservedNames===undefined){opt_allowReservedNames=true;}
 this.allowReservedNames_=opt_allowReservedNames;}
@@ -7363,13 +7144,17 @@
 const DEFAULT_SUMMARY_OPTIONS=new Map([['avg',true],['count',true],['geometricMean',false],['max',true],['min',true],['nans',false],['std',true],['sum',true],]);class Histogram{constructor(name,unit,opt_binBoundaries){if(!(unit instanceof tr.b.Unit)){throw new Error('unit must be a Unit: '+unit);}
 let binBoundaries=opt_binBoundaries;if(!binBoundaries){const baseUnit=unit.baseUnit?unit.baseUnit:unit;binBoundaries=DEFAULT_BOUNDARIES_FOR_UNIT.get(baseUnit.unitName);}
 this.binBoundariesDict_=binBoundaries.asDict();this.allBins=binBoundaries.bins.slice();this.description='';const allowReservedNames=false;this.diagnostics_=new tr.v.d.DiagnosticMap(allowReservedNames);this.maxNumSampleValues_=this.defaultMaxNumSampleValues_;this.name_=name;this.nanDiagnosticMaps=[];this.numNans=0;this.running_=undefined;this.sampleValues_=[];this.sampleMeans_=[];this.summaryOptions=new Map(DEFAULT_SUMMARY_OPTIONS);this.summaryOptions.set('percentile',[]);this.summaryOptions.set('iprs',[]);this.summaryOptions.set('ci',[]);this.unit=unit;}
-static create(name,unit,samples,opt_options){const options=opt_options||{};const hist=new Histogram(name,unit,options.binBoundaries);if(options.description)hist.description=options.description;if(options.summaryOptions){let summaryOptions=options.summaryOptions;if(!(summaryOptions instanceof Map)){summaryOptions=Object.entries(summaryOptions);}
+static create(name,unit,samples,opt_options){const options=opt_options||{};const hist=new Histogram(name,unit,options.binBoundaries);if(options.alertGrouping!==undefined){hist.setAlertGrouping(options.alertGrouping);}
+if(options.description)hist.description=options.description;if(options.summaryOptions){let summaryOptions=options.summaryOptions;if(!(summaryOptions instanceof Map)){summaryOptions=Object.entries(summaryOptions);}
 for(const[name,value]of summaryOptions){hist.summaryOptions.set(name,value);}}
 if(options.diagnostics!==undefined){let diagnostics=options.diagnostics;if(!(diagnostics instanceof Map)){diagnostics=Object.entries(diagnostics);}
 for(const[name,diagnostic]of diagnostics){if(!diagnostic)continue;hist.diagnostics.set(name,diagnostic);}}
 if(!(samples instanceof Array))samples=[samples];for(const sample of samples){if(typeof sample==='object'){hist.addSample(sample.value,sample.diagnostics);}else{hist.addSample(sample);}}
 return hist;}
 get diagnostics(){return this.diagnostics_;}
+setAlertGrouping(alertGrouping){if(alertGrouping===undefined||alertGrouping===null||alertGrouping.length===undefined){throw Error('alertGrouping must be an array');}
+for(const alertGroup of alertGrouping){if(!Object.values(tr.v.d.ALERT_GROUPS).includes(alertGroup)){throw Error(`Alert group ${alertGroup} must be added to `+'/tracing/value/diagnostics/alert_groups.html');}}
+this.diagnostics.set(tr.v.d.RESERVED_NAMES.ALERT_GROUPING,new tr.v.d.GenericSet(alertGrouping));}
 get running(){return this.running_;}
 get maxNumSampleValues(){return this.maxNumSampleValues_;}
 set maxNumSampleValues(n){this.maxNumSampleValues_=n;tr.b.math.Statistics.uniformlySampleArray(this.sampleValues_,this.maxNumSampleValues_);}
@@ -7591,7 +7376,7 @@
 Polymer({is:'tr-ui-a-generic-object-view',ready(){this.object_=undefined;},get object(){return this.object_;},set object(object){this.object_=object;this.updateContents_();},updateContents_(){Polymer.dom(this.$.content).textContent='';this.appendElementsForType_('',this.object_,0,0,5,'');},appendElementsForType_(label,object,indent,depth,maxDepth,suffix){if(depth>maxDepth){this.appendSimpleText_(label,indent,'<recursion limit reached>',suffix);return;}
 if(object===undefined){this.appendSimpleText_(label,indent,'undefined',suffix);return;}
 if(object===null){this.appendSimpleText_(label,indent,'null',suffix);return;}
-if(!(object instanceof Object)){const type=typeof object;if(type!=='string'){return this.appendSimpleText_(label,indent,object,suffix);}
+if(!(object instanceof Object)){const type=typeof object;if(type!=='string'){return this.appendSimpleText_(label,indent,String(object),suffix);}
 let objectReplaced=false;if((object[0]==='{'&&object[object.length-1]==='}')||(object[0]==='['&&object[object.length-1]===']')){try{object=JSON.parse(object);objectReplaced=true;}catch(e){}}
 if(!objectReplaced){if(object.includes('\n')){const lines=object.split('\n');lines.forEach(function(line,i){let text;let ioff;let ll;let ss;if(i===0){text='"'+line;ioff=0;ll=label;ss='';}else if(i<lines.length-1){text=line;ioff=1;ll='';ss='';}else{text=line+'"';ioff=1;ll='';ss=suffix;}
 const el=this.appendSimpleText_(ll,indent+ioff*label.length+ioff,text,ss);el.style.whiteSpace='pre';return el;},this);return;}
@@ -7774,11 +7559,11 @@
 function drawProjectedQuadToContext(passNumber,quad,p1,p2,p3,p4,ctx,quadCanvas){if(passNumber===0){drawProjectedQuadBackgroundToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else if(passNumber===1){drawProjectedQuadOutlineToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else if(passNumber===2){drawProjectedQuadSelectionOutlineToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else{throw new Error('Invalid pass number');}}
 const tmpP1=vec3.create();const tmpP2=vec3.create();const tmpP3=vec3.create();const tmpP4=vec3.create();function transformAndProcessQuads(matrix,viewport,quads,numPasses,handleQuadFunc,opt_arg1,opt_arg2){for(let passNumber=0;passNumber<numPasses;passNumber++){for(let i=0;i<quads.length;i++){const quad=quads[i];transform(tmpP1,quad.p1,matrix,viewport);transform(tmpP2,quad.p2,matrix,viewport);transform(tmpP3,quad.p3,matrix,viewport);transform(tmpP4,quad.p4,matrix,viewport);handleQuadFunc(passNumber,quad,tmpP1,tmpP2,tmpP3,tmpP4,opt_arg1,opt_arg2);}}}
 const QuadStackView=tr.ui.b.define('quad-stack-view');QuadStackView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.className='quad-stack-view';this.style.display='flex';this.style.position='relative';const node=tr.ui.b.instantiateTemplate('#quad-stack-view-template',THIS_DOC);Polymer.dom(this).appendChild(node);this.updateHeaderVisibility_();const header=Polymer.dom(this).querySelector('#header');header.style.position='absolute';header.style.fontSize='70%';header.style.top='10px';header.style.left='10px';header.style.right='150px';const scroller=Polymer.dom(this).querySelector('#canvas-scroller');scroller.style.flexGrow=1;scroller.style.flexShrink=1;scroller.style.flexBasis='auto';scroller.style.minWidth=0;scroller.style.minHeight=0;scroller.style.overflow='auto';this.canvas_=Polymer.dom(this).querySelector('#canvas');this.chromeImages_={left:Polymer.dom(this).querySelector('#chrome-left'),mid:Polymer.dom(this).querySelector('#chrome-mid'),right:Polymer.dom(this).querySelector('#chrome-right')};const stackingDistanceSlider=Polymer.dom(this).querySelector('#stacking-distance-slider');stackingDistanceSlider.style.position='absolute';stackingDistanceSlider.style.fontSize='70%';stackingDistanceSlider.style.top='10px';stackingDistanceSlider.style.right='10px';stackingDistanceSlider.value=tr.b.Settings.get('quadStackView.stackingDistance',45);stackingDistanceSlider.addEventListener('change',this.onStackingDistanceChange_.bind(this));stackingDistanceSlider.addEventListener('input',this.onStackingDistanceChange_.bind(this));this.trackMouse_();this.camera_=new tr.ui.b.Camera(this.mouseModeSelector_);this.camera_.addEventListener('renderrequired',this.onRenderRequired_.bind(this));this.cameraWasReset_=false;this.camera_.canvas=this.canvas_;this.viewportRect_=tr.b.math.Rect.fromXYWH(0,0,0,0);this.pixelRatio_=window.devicePixelRatio||1;},updateHeaderVisibility_(){if(this.headerText){Polymer.dom(this).querySelector('#header').style.display='';}else{Polymer.dom(this).querySelector('#header').style.display='none';}},get headerText(){return Polymer.dom(this).querySelector('#header').textContent;},set headerText(headerText){Polymer.dom(this).querySelector('#header').textContent=headerText;this.updateHeaderVisibility_();},onStackingDistanceChange_(e){tr.b.Settings.set('quadStackView.stackingDistance',this.stackingDistance);this.scheduleRender();e.stopPropagation();},get stackingDistance(){return Polymer.dom(this).querySelector('#stacking-distance-slider').value;},get mouseModeSelector(){return this.mouseModeSelector_;},get camera(){return this.camera_;},set quads(q){this.quads_=q;this.scheduleRender();},set deviceRect(rect){if(!rect||rect.equalTo(this.deviceRect_))return;this.deviceRect_=rect;this.camera_.deviceRect=rect;this.chromeQuad_=undefined;},resize(){if(!this.offsetParent)return true;const width=parseInt(window.getComputedStyle(this.offsetParent).width);const height=parseInt(window.getComputedStyle(this.offsetParent).height);const rect=tr.b.math.Rect.fromXYWH(0,0,width,height);if(rect.equalTo(this.viewportRect_))return false;this.viewportRect_=rect;this.canvas_.style.width=width+'px';this.canvas_.style.height=height+'px';this.canvas_.width=this.pixelRatio_*width;this.canvas_.height=this.pixelRatio_*height;if(!this.cameraWasReset_){this.camera_.resetCamera();this.cameraWasReset_=true;}
-return true;},readyToDraw(){if(!this.chromeImages_.left.src){let leftContent=window.getComputedStyle(this.chromeImages_.left).backgroundImage;leftContent=tr.ui.b.extractUrlString(leftContent);let midContent=window.getComputedStyle(this.chromeImages_.mid).backgroundImage;midContent=tr.ui.b.extractUrlString(midContent);let rightContent=window.getComputedStyle(this.chromeImages_.right).backgroundImage;rightContent=tr.ui.b.extractUrlString(rightContent);this.chromeImages_.left.src=leftContent;this.chromeImages_.mid.src=midContent;this.chromeImages_.right.src=rightContent;}
+return true;},readyToDptr(){if(!this.chromeImages_.left.src){let leftContent=window.getComputedStyle(this.chromeImages_.left).backgroundImage;leftContent=tr.ui.b.extractUrlString(leftContent);let midContent=window.getComputedStyle(this.chromeImages_.mid).backgroundImage;midContent=tr.ui.b.extractUrlString(midContent);let rightContent=window.getComputedStyle(this.chromeImages_.right).backgroundImage;rightContent=tr.ui.b.extractUrlString(rightContent);this.chromeImages_.left.src=leftContent;this.chromeImages_.mid.src=midContent;this.chromeImages_.right.src=rightContent;}
 return(this.chromeImages_.left.height>0)&&(this.chromeImages_.mid.height>0)&&(this.chromeImages_.right.height>0);},get chromeQuad(){if(this.chromeQuad_)return this.chromeQuad_;const chromeCanvas=document.createElement('canvas');const offsetY=this.chromeImages_.left.height;chromeCanvas.width=this.deviceRect_.width;chromeCanvas.height=this.deviceRect_.height+offsetY;const leftWidth=this.chromeImages_.left.width;const midWidth=this.chromeImages_.mid.width;const rightWidth=this.chromeImages_.right.width;const chromeCtx=chromeCanvas.getContext('2d');chromeCtx.drawImage(this.chromeImages_.left,0,0);chromeCtx.save();chromeCtx.translate(leftWidth,0);const s=(this.deviceRect_.width-leftWidth-rightWidth)/midWidth;chromeCtx.scale(s,1);chromeCtx.drawImage(this.chromeImages_.mid,0,0);chromeCtx.restore();chromeCtx.drawImage(this.chromeImages_.right,leftWidth+s*midWidth,0);const chromeRect=tr.b.math.Rect.fromXYWH(this.deviceRect_.x,this.deviceRect_.y-offsetY,this.deviceRect_.width,this.deviceRect_.height+offsetY);const chromeQuad=tr.b.math.Quad.fromRect(chromeRect);chromeQuad.stackingGroupId=this.maxStackingGroupId_+1;chromeQuad.imageData=chromeCtx.getImageData(0,0,chromeCanvas.width,chromeCanvas.height);chromeQuad.shadowOffset=[0,0];chromeQuad.shadowBlur=5;chromeQuad.borderWidth=3;this.chromeQuad_=chromeQuad;return this.chromeQuad_;},scheduleRender(){if(this.redrawScheduled_)return false;this.redrawScheduled_=true;tr.b.requestAnimationFrame(this.render,this);},onRenderRequired_(e){this.scheduleRender();},stackTransformAndProcessQuads_(numPasses,handleQuadFunc,includeChromeQuad,opt_arg1,opt_arg2){const mv=this.camera_.modelViewMatrix;const p=this.camera_.projectionMatrix;const viewport=tr.b.math.Rect.fromXYWH(0,0,this.canvas_.width,this.canvas_.height);const quadStacks=[];for(let i=0;i<this.quads_.length;++i){const quad=this.quads_[i];const stackingId=quad.stackingGroupId||0;while(stackingId>=quadStacks.length){quadStacks.push([]);}
 quadStacks[stackingId].push(quad);}
 const mvp=mat4.create();this.maxStackingGroupId_=quadStacks.length;const effectiveStackingDistance=this.stackingDistance*this.camera_.stackingDistanceDampening;mat4.multiply(mvp,p,mv);for(let i=0;i<quadStacks.length;++i){transformAndProcessQuads(mvp,viewport,quadStacks[i],numPasses,handleQuadFunc,opt_arg1,opt_arg2);mat4.translate(mv,mv,[0,0,effectiveStackingDistance]);mat4.multiply(mvp,p,mv);}
-if(includeChromeQuad&&this.deviceRect_){transformAndProcessQuads(mvp,viewport,[this.chromeQuad],numPasses,drawProjectedQuadToContext,opt_arg1,opt_arg2);}},render(){this.redrawScheduled_=false;if(!this.readyToDraw()){setTimeout(this.scheduleRender.bind(this),constants.IMAGE_LOAD_RETRY_TIME_MS);return;}
+if(includeChromeQuad&&this.deviceRect_){transformAndProcessQuads(mvp,viewport,[this.chromeQuad],numPasses,drawProjectedQuadToContext,opt_arg1,opt_arg2);}},render(){this.redrawScheduled_=false;if(!this.readyToDptr()){setTimeout(this.scheduleRender.bind(this),constants.IMAGE_LOAD_RETRY_TIME_MS);return;}
 if(!this.quads_)return;const canvasCtx=this.canvas_.getContext('2d');if(!this.resize()){canvasCtx.clearRect(0,0,this.canvas_.width,this.canvas_.height);}
 const quadCanvas=document.createElement('canvas');this.stackTransformAndProcessQuads_(3,drawProjectedQuadToContext,true,canvasCtx,quadCanvas);quadCanvas.width=0;},trackMouse_(){this.mouseModeSelector_=document.createElement('tr-ui-b-mouse-mode-selector');this.mouseModeSelector_.targetElement=this.canvas_;this.mouseModeSelector_.supportedModeMask=tr.ui.b.MOUSE_SELECTOR_MODE.SELECTION|tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN|tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM|tr.ui.b.MOUSE_SELECTOR_MODE.ROTATE;this.mouseModeSelector_.mode=tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN;this.mouseModeSelector_.pos={x:0,y:100};Polymer.dom(this).appendChild(this.mouseModeSelector_);this.mouseModeSelector_.settingsKey='quadStackView.mouseModeSelector';this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.ROTATE,tr.ui.b.MODIFIER.SHIFT);this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN,tr.ui.b.MODIFIER.SPACE);this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM,tr.ui.b.MODIFIER.CMD_OR_CTRL);this.mouseModeSelector_.addEventListener('updateselection',this.onSelectionUpdate_.bind(this));this.mouseModeSelector_.addEventListener('endselection',this.onSelectionUpdate_.bind(this));},extractRelativeMousePosition_(e){const br=this.canvas_.getBoundingClientRect();return[this.pixelRatio_*(e.clientX-this.canvas_.offsetLeft-br.left),this.pixelRatio_*(e.clientY-this.canvas_.offsetTop-br.top)];},onSelectionUpdate_(e){const mousePos=this.extractRelativeMousePosition_(e);const res=[];function handleQuad(passNumber,quad,p1,p2,p3,p4){if(tr.b.math.pointInImplicitQuad(mousePos,p1,p2,p3,p4)){res.push(quad);}}
 this.stackTransformAndProcessQuads_(1,handleQuad,false);e=new tr.b.Event('selectionchange');e.quads=res;this.dispatchEvent(e);}};return{QuadStackView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const ColorScheme=tr.b.ColorScheme;const THIS_DOC=document.currentScript.ownerDocument;const TILE_HEATMAP_TYPE={};TILE_HEATMAP_TYPE.NONE='none';TILE_HEATMAP_TYPE.SCHEDULED_PRIORITY='scheduledPriority';TILE_HEATMAP_TYPE.USING_GPU_MEMORY='usingGpuMemory';const cc=tr.ui.e.chrome.cc;function createTileRectsSelectorBaseOptions(){return[{label:'None',value:'none'},{label:'Coverage Rects',value:'coverage'}];}
@@ -7851,7 +7636,7 @@
 tr.b.dispatchSimpleEvent(this,'selection-change');},createPictureBtn_(pictures){if(!(pictures instanceof Array)){pictures=[pictures];}
 const link=document.createElement('tr-ui-a-analysis-link');link.selection=function(){const layeredPicture=new tr.e.cc.LayeredPicture(pictures);const snapshot=new tr.e.cc.PictureSnapshot(layeredPicture);snapshot.picture=layeredPicture;const selection=new tr.model.EventSet();selection.push(snapshot);return selection;};Polymer.dom(link).textContent='View in Picture Debugger';return link;},onRequestSelectionChangeFromAnalysisEl_(e){if(!(e.selection instanceof tr.ui.e.chrome.cc.Selection)){return;}
 e.stopPropagation();this.selection=e.selection;},get extraHighlightsByLayerId(){return this.layerTreeQuadStackView_.extraHighlightsByLayerId;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.layerTreeQuadStackView_.extraHighlightsByLayerId=extraHighlightsByLayerId;}};return{LayerView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const LayerTreeHostImplSnapshotView=tr.ui.b.define('tr-ui-e-chrome-cc-layer-tree-host-impl-snapshot-view',tr.ui.analysis.ObjectSnapshotView);LayerTreeHostImplSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){Polymer.dom(this).classList.add('tr-ui-e-chrome-cc-lthi-s-view');this.style.display='flex';this.style.flexDirection='row';this.style.flexGrow=1;this.style.flexShrink=1;this.style.flexBasis='auto';this.style.minWidth=0;this.selection_=undefined;this.layerPicker_=new tr.ui.e.chrome.cc.LayerPicker();this.layerPicker_.style.flexGrow=0;this.layerPicker_.style.flexShrink=0;this.layerPicker_.style.flexBasis='auto';this.layerPicker_.style.minWidth='200px';this.layerPicker_.addEventListener('selection-change',this.onLayerPickerSelectionChanged_.bind(this));this.layerView_=new tr.ui.e.chrome.cc.LayerView();this.layerView_.addEventListener('selection-change',this.onLayerViewSelectionChanged_.bind(this));this.layerView_.style.flexGrow=1;this.layerView_.style.flexShrink=1;this.layerView_.style.flexBasis='auto';this.layerView_.style.minWidth=0;this.dragHandle_=document.createElement('tr-ui-b-drag-handle');this.dragHandle_.style.flexGrow=0;this.dragHandle_.style.flexShrink=0;this.dragHandle_.style.flexBasis='auto';this.dragHandle_.horizontal=false;this.dragHandle_.target=this.layerPicker_;Polymer.dom(this).appendChild(this.layerPicker_);Polymer.dom(this).appendChild(this.dragHandle_);Polymer.dom(this).appendChild(this.layerView_);this.onLayerViewSelectionChanged_();this.onLayerPickerSelectionChanged_();},get objectSnapshot(){return this.objectSnapshot_;},set objectSnapshot(objectSnapshot){this.objectSnapshot_=objectSnapshot;const lthi=this.objectSnapshot;let layerTreeImpl;if(lthi){layerTreeImpl=lthi.getTree(this.layerPicker_.whichTree);}
-this.layerPicker_.lthiSnapshot=lthi;this.layerView_.layerTreeImpl=layerTreeImpl;this.layerView_.regenerateContent();if(!this.selection_)return;this.selection=this.selection_.findEquivalent(lthi);},get selection(){return this.selection_;},set selection(selection){if(this.selection_===selection)return;this.selection_=selection;this.layerPicker_.selection=selection;this.layerView_.selection=selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerPickerSelectionChanged_(){this.selection_=this.layerPicker_.selection;this.layerView_.selection=this.selection;this.layerView_.layerTreeImpl=this.layerPicker_.layerTreeImpl;this.layerView_.isRenderPassQuads=this.layerPicker_.isRenderPassQuads;this.layerView_.regenerateContent();tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerViewSelectionChanged_(){this.selection_=this.layerView_.selection;this.layerPicker_.selection=this.selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},get extraHighlightsByLayerId(){return this.layerView_.extraHighlightsByLayerId;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.layerView_.extraHighlightsByLayerId=extraHighlightsByLayerId;}};tr.ui.analysis.ObjectSnapshotView.register(LayerTreeHostImplSnapshotView,{typeName:'cc::LayerTreeHostImpl'});return{LayerTreeHostImplSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const OPS_TIMING_ITERATIONS=3;const CHART_PADDING_LEFT=65;const CHART_PADDING_RIGHT=40;const AXIS_PADDING_LEFT=60;const AXIS_PADDING_RIGHT=35;const AXIS_PADDING_TOP=25;const AXIS_PADDING_BOTTOM=45;const AXIS_LABEL_PADDING=5;const AXIS_TICK_SIZE=10;const LABEL_PADDING=5;const LABEL_INTERLEAVE_OFFSET=15;const BAR_PADDING=5;const VERTICAL_TICKS=5;const HUE_CHAR_CODE_ADJUSTMENT=5.7;const PictureOpsChartSummaryView=tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-chart-summary-view');PictureOpsChartSummaryView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.flexGrow=0;this.style.flexShrink=0;this.style.flexBasis='auto';this.style.fontSize=0;this.style.margin=0;this.style.minHeight='200px';this.style.minWidth='200px';this.style.overflow='hidden';this.style.padding=0;this.picture_=undefined;this.pictureDataProcessed_=false;this.chartScale_=window.devicePixelRatio;this.chart_=document.createElement('canvas');this.chartCtx_=this.chart_.getContext('2d');Polymer.dom(this).appendChild(this.chart_);this.opsTimingData_=[];this.chartWidth_=0;this.chartHeight_=0;this.requiresRedraw_=true;this.currentBarMouseOverTarget_=null;this.chart_.addEventListener('mousemove',this.onMouseMove_.bind(this));try{new ResizeObserver(this.onResize_.bind(this)).observe(this);}catch(e){}},get requiresRedraw(){return this.requiresRedraw_;},set requiresRedraw(requiresRedraw){this.requiresRedraw_=requiresRedraw;},get picture(){return this.picture_;},set picture(picture){this.picture_=picture;this.pictureDataProcessed_=false;if(Polymer.dom(this).classList.contains('hidden'))return;this.processPictureData_();this.requiresRedraw=true;this.updateChartContents();},hide(){Polymer.dom(this).classList.add('hidden');this.style.display='none';},show(){Polymer.dom(this).classList.remove('hidden');this.style.display='';if(!this.pictureDataProcessed_){this.processPictureData_();}
+this.layerPicker_.lthiSnapshot=lthi;this.layerView_.layerTreeImpl=layerTreeImpl;this.layerView_.regenerateContent();if(!this.selection_)return;this.selection=this.selection_.findEquivalent(lthi);},get selection(){return this.selection_;},set selection(selection){if(this.selection_===selection)return;this.selection_=selection;this.layerPicker_.selection=selection;this.layerView_.selection=selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerPickerSelectionChanged_(){this.selection_=this.layerPicker_.selection;this.layerView_.selection=this.selection;this.layerView_.layerTreeImpl=this.layerPicker_.layerTreeImpl;this.layerView_.isRenderPassQuads=this.layerPicker_.isRenderPassQuads;this.layerView_.regenerateContent();tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerViewSelectionChanged_(){this.selection_=this.layerView_.selection;this.layerPicker_.selection=this.selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},get extraHighlightsByLayerId(){return this.layerView_.extraHighlightsByLayerId;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.layerView_.extraHighlightsByLayerId=extraHighlightsByLayerId;}};tr.ui.analysis.ObjectSnapshotView.register(LayerTreeHostImplSnapshotView,{typeName:'cc::LayerTreeHostImpl'});return{LayerTreeHostImplSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const OPS_TIMING_ITERATIONS=3;const CHART_PADDING_LEFT=65;const CHART_PADDING_RIGHT=40;const AXIS_PADDING_LEFT=60;const AXIS_PADDING_RIGHT=35;const AXIS_PADDING_TOP=25;const AXIS_PADDING_BOTTOM=45;const AXIS_LABEL_PADDING=5;const AXIS_TICK_SIZE=10;const LABEL_PADDING=5;const LABEL_INTERLEAVE_OFFSET=15;const BAR_PADDING=5;const VERTICAL_TICKS=5;const HUE_CHAR_CODE_ADJUSTMENT=5.7;const PictureOpsChartSummaryView=tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-chart-summary-view');PictureOpsChartSummaryView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.flexGrow=0;this.style.flexShrink=0;this.style.flexBasis='auto';this.style.fontSize=0;this.style.margin=0;this.style.minHeight='200px';this.style.minWidth='200px';this.style.overflow='hidden';this.style.padding=0;this.picture_=undefined;this.pictureDataProcessed_=false;this.chartScale_=window.devicePixelRatio;this.chart_=document.createElement('canvas');this.chartCtx_=this.chart_.getContext('2d');Polymer.dom(this).appendChild(this.chart_);this.opsTimingData_=[];this.chartWidth_=0;this.chartHeight_=0;this.requiresRedraw_=true;this.currentBarMouseOverTarget_=null;this.chart_.addEventListener('mousemove',this.onMouseMove_.bind(this));try{new ResizeObserver(this.onResize_.bind(this)).observe(this);}catch(e){}},get requiresRedptr(){return this.requiresRedraw_;},set requiresRedraw(requiresRedraw){this.requiresRedraw_=requiresRedraw;},get picture(){return this.picture_;},set picture(picture){this.picture_=picture;this.pictureDataProcessed_=false;if(Polymer.dom(this).classList.contains('hidden'))return;this.processPictureData_();this.requiresRedraw=true;this.updateChartContents();},hide(){Polymer.dom(this).classList.add('hidden');this.style.display='none';},show(){Polymer.dom(this).classList.remove('hidden');this.style.display='';if(!this.pictureDataProcessed_){this.processPictureData_();}
 this.requiresRedraw=true;this.updateChartContents();},onMouseMove_(e){const lastBarMouseOverTarget=this.currentBarMouseOverTarget_;this.currentBarMouseOverTarget_=null;const x=e.offsetX;const y=e.offsetY;const chartLeft=CHART_PADDING_LEFT;const chartRight=this.chartWidth_-CHART_PADDING_RIGHT;const chartTop=AXIS_PADDING_TOP;const chartBottom=this.chartHeight_-AXIS_PADDING_BOTTOM;const chartInnerWidth=chartRight-chartLeft;if(x>chartLeft&&x<chartRight&&y>chartTop&&y<chartBottom){this.currentBarMouseOverTarget_=Math.floor((x-chartLeft)/chartInnerWidth*this.opsTimingData_.length);this.currentBarMouseOverTarget_=tr.b.math.clamp(this.currentBarMouseOverTarget_,0,this.opsTimingData_.length-1);}
 if(this.currentBarMouseOverTarget_===lastBarMouseOverTarget)return;this.drawChartContents_();},onResize_(){this.requiresRedraw=true;this.updateChartContents();},updateChartContents(){if(this.requiresRedraw){this.updateChartDimensions_();}
 this.drawChartContents_();},updateChartDimensions_(){this.chartWidth_=this.offsetWidth;this.chartHeight_=this.offsetHeight;this.chart_.width=this.chartWidth_*this.chartScale_;this.chart_.height=this.chartHeight_*this.chartScale_;this.chart_.style.width=this.chartWidth_+'px';this.chart_.style.height=this.chartHeight_+'px';this.chartCtx_.scale(this.chartScale_,this.chartScale_);},processPictureData_(){this.resetOpsTimingData_();this.pictureDataProcessed_=true;if(!this.picture_)return;let ops=this.picture_.getOps();if(!ops)return;ops=this.picture_.tagOpsWithTimings(ops);if(ops[0].cmd_time===undefined)return;this.collapseOpsToTimingBuckets_(ops);},drawChartContents_(){this.clearChartContents_();if(this.opsTimingData_.length===0){this.showNoTimingDataMessage_();return;}
@@ -7929,7 +7714,8 @@
 if(event.category){rows.push({name:'Category',value:event.category});}
 if(event.model!==undefined){const ufc=event.model.getUserFriendlyCategoryFromEvent(event);if(ufc!==undefined){rows.push({name:'User Friendly Category',value:ufc});}}
 if(event.name){rows.push({name:'Name',value:event.name});}
-rows.push({name:'Start',value:tr.v.ui.createScalarSpan(event.start,{unit:tr.b.Unit.byName.timeStampInMs})});if(event.duration){rows.push({name:'Wall Duration',value:tr.v.ui.createScalarSpan(event.duration,{unit:tr.b.Unit.byName.timeDurationInMs})});}
+rows.push({name:'Start',value:tr.v.ui.createScalarSpan(event.start,{unit:tr.b.Unit.byName.timeStampInMs})});if(event.category==='android'&&event.model!==undefined){rows.push({name:'Start (Absolute time)',value:tr.v.ui.createScalarSpan(event.model.convertTimestampFromModelTime('traceEventClock',event.start),{unit:tr.b.Unit.byName.timeStampInMs})});}
+if(event.duration){rows.push({name:'Wall Duration',value:tr.v.ui.createScalarSpan(event.duration,{unit:tr.b.Unit.byName.timeDurationInMs})});}
 if(event.cpuDuration){rows.push({name:'CPU Duration',value:tr.v.ui.createScalarSpan(event.cpuDuration,{unit:tr.b.Unit.byName.timeDurationInMs})});}
 if(event.subSlices!==undefined&&event.subSlices.length!==0){if(event.selfTime){rows.push({name:'Self Time',value:tr.v.ui.createScalarSpan(event.selfTime,{unit:tr.b.Unit.byName.timeDurationInMs})});}
 if(event.cpuSelfTime){const cpuSelfTimeEl=tr.v.ui.createScalarSpan(event.cpuSelfTime,{unit:tr.b.Unit.byName.timeDurationInMs});if(event.cpuSelfTime>event.selfTime){cpuSelfTimeEl.warning=' Note that CPU Self Time is larger than Self Time. '+'This is a known limitation of this system, which occurs '+'due to several subslices, rounding issues, and imprecise '+'time at which we get cpu- and real-time.';}
@@ -8293,21 +8079,21 @@
 if(slice.title==='RenderAccessibilityImpl::SendLocationChanges'){renderAccessibilityLocationsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}}}
 for(const browserHelper of Object.values(chromeHelper.browserHelpers)){const mainThread=browserHelper.mainThread;if(mainThread===undefined)continue;for(const slice of mainThread.getDescendantEvents()){if(slice.title==='BrowserAccessibilityManager::OnAccessibilityEvents'){browserAccessibilityEventsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}}}
 histograms.addHistogram(browserAccessibilityEventsHist);histograms.addHistogram(renderAccessibilityEventsHist);histograms.addHistogram(renderAccessibilityLocationsHist);}
-tr.metrics.MetricRegistry.register(accessibilityMetric);return{accessibilityMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MESSAGE_LOOP_EVENT_NAME='Startup.BrowserMessageLoopStartTime';const CONTENT_START_EVENT_NAME='content::Start';const NAVIGATION_EVENT_NAME='Navigation StartToCommit';const FIRST_CONTENTFUL_PAINT_EVENT_NAME='firstContentfulPaint';function androidStartupMetric(histograms,model){let messageLoopStartEvents=[];let navigationEvents=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;for(const helper of chromeHelper.browserHelpers){for(const ev of helper.mainThread.asyncSliceGroup.childEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}}}
+tr.metrics.MetricRegistry.register(accessibilityMetric);return{accessibilityMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MESSAGE_LOOP_EVENT_NAME='Startup.BrowserMessageLoopStartTime';const CONTENT_START_EVENT_NAME='content::Start';const NAVIGATION_EVENT_NAME='Navigation StartToCommit';const FIRST_CONTENTFUL_PAINT_EVENT_NAME='firstContentfulPaint';const APPLICATION_START_EVENT_NAME='Startup.LoadTime.ProcessCreateToApplicationStart';function androidStartupMetric(histograms,model){let messageLoopStartEvents=[];let applicationStartEvents=[];let navigationEvents=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;for(const helper of chromeHelper.browserHelpers){for(const ev of helper.mainThread.asyncSliceGroup.childEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===APPLICATION_START_EVENT_NAME){applicationStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}}}
 let contentStartEvents=[];let firstContentfulPaintEvents=[];const rendererHelpers=chromeHelper.rendererHelpers;const pids=Object.keys(rendererHelpers);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(!rendererHelper.mainThread)continue;for(const ev of rendererHelper.mainThread.sliceGroup.childEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}}
-let totalBrowserStarts=messageLoopStartEvents.length;let totalContentStartEvents=contentStartEvents.length;let totalFcpEvents=firstContentfulPaintEvents.length;let totalNavigations=navigationEvents.length;if(totalFcpEvents!==totalBrowserStarts||totalNavigations!==totalBrowserStarts||totalContentStartEvents!==totalBrowserStarts||totalBrowserStarts===0){messageLoopStartEvents=[];contentStartEvents=[];navigationEvents=[];firstContentfulPaintEvents=[];for(const proc of Object.values(model.processes)){for(const ev of proc.getDescendantEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}
+let totalBrowserStarts=messageLoopStartEvents.length;let totalContentStartEvents=contentStartEvents.length;let totalFcpEvents=firstContentfulPaintEvents.length;let totalNavigations=navigationEvents.length;let totalApplicationStartEvents=applicationStartEvents.length;if(totalFcpEvents!==totalBrowserStarts||totalNavigations!==totalBrowserStarts||totalContentStartEvents!==totalBrowserStarts||totalApplicationStartEvents!==totalBrowserStarts||totalBrowserStarts===0){messageLoopStartEvents=[];contentStartEvents=[];navigationEvents=[];firstContentfulPaintEvents=[];applicationStartEvents=[];for(const proc of Object.values(model.processes)){for(const ev of proc.getDescendantEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===APPLICATION_START_EVENT_NAME){applicationStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}
 for(const ev of proc.getDescendantEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}}}
-totalBrowserStarts=messageLoopStartEvents.length;totalContentStartEvents=contentStartEvents.length;totalNavigations=navigationEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;}
+totalBrowserStarts=messageLoopStartEvents.length;totalContentStartEvents=contentStartEvents.length;totalNavigations=navigationEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;totalApplicationStartEvents=applicationStartEvents.length;}
 function orderEvents(event1,event2){return event1.start-event2.start;}
-messageLoopStartEvents.sort(orderEvents);contentStartEvents.sort(orderEvents);navigationEvents.sort(orderEvents);firstContentfulPaintEvents.sort(orderEvents);if(totalFcpEvents<totalBrowserStarts){throw new Error('Found fewer FCP events ('+totalFcpEvents+') than browser starts ('+totalBrowserStarts+')');}
-const messageLoopStartHistogram=histograms.createHistogram('messageloop_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const contentStartHistogram=histograms.createHistogram('experimental_content_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationStartHistogram=histograms.createHistogram('experimental_navigation_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationCommitHistogram=histograms.createHistogram('navigation_commit_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const firstContentfulPaintHistogram=histograms.createHistogram('first_contentful_paint_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);let contentIndex=0;let navIndex=0;let fcpIndex=0;for(let loopStartIndex=0;loopStartIndex<totalBrowserStarts;){const startEvent=messageLoopStartEvents[loopStartIndex];if(fcpIndex===totalFcpEvents){break;}
-const contentStartEvent=contentIndex<contentStartEvents.length?contentStartEvents[contentIndex]:null;if(contentStartEvent&&contentStartEvent.start<startEvent.start){contentIndex++;continue;}
-const navEvent=navIndex<navigationEvents.length?navigationEvents[navIndex]:null;if(navEvent&&navEvent.start<startEvent.start){navIndex++;continue;}
-const fcpEvent=firstContentfulPaintEvents[fcpIndex];if(fcpEvent.start<startEvent.start){fcpIndex++;continue;}
+messageLoopStartEvents.sort(orderEvents);applicationStartEvents.sort(orderEvents);contentStartEvents.sort(orderEvents);navigationEvents.sort(orderEvents);firstContentfulPaintEvents.sort(orderEvents);if(totalFcpEvents<totalBrowserStarts){throw new Error('Found fewer FCP events ('+totalFcpEvents+') than browser starts ('+totalBrowserStarts+')');}
+const messageLoopStartHistogram=histograms.createHistogram('messageloop_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const contentStartHistogram=histograms.createHistogram('experimental_content_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationStartHistogram=histograms.createHistogram('experimental_navigation_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationCommitHistogram=histograms.createHistogram('navigation_commit_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const firstContentfulPaintHistogram=histograms.createHistogram('first_contentful_paint_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const applicationStartHistogram=histograms.createHistogram('process_create_to_app_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);let contentIndex=0;let navIndex=0;let fcpIndex=0;for(let loopStartIndex=0;loopStartIndex<totalBrowserStarts;){const loopStartEvent=messageLoopStartEvents[loopStartIndex];const applicationStartEvent=applicationStartEvents[loopStartIndex];if(fcpIndex===totalFcpEvents){break;}
+const contentStartEvent=contentIndex<contentStartEvents.length?contentStartEvents[contentIndex]:null;if(contentStartEvent&&contentStartEvent.start<loopStartEvent.start){contentIndex++;continue;}
+const navEvent=navIndex<navigationEvents.length?navigationEvents[navIndex]:null;if(navEvent&&navEvent.start<loopStartEvent.start){navIndex++;continue;}
+const fcpEvent=firstContentfulPaintEvents[fcpIndex];if(fcpEvent.start<loopStartEvent.start){fcpIndex++;continue;}
 loopStartIndex++;if(fcpIndex<2){continue;}
-messageLoopStartHistogram.addSample(startEvent.duration,{events:new tr.v.d.RelatedEventSet([startEvent])});if(contentStartEvent){contentStartHistogram.addSample(contentStartEvent.start-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,contentStartEvent])});}
-if(navEvent){navigationStartHistogram.addSample(navEvent.start-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,navEvent])});navigationCommitHistogram.addSample(navEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,navEvent])});}
-firstContentfulPaintHistogram.addSample(fcpEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,fcpEvent])});}}
+messageLoopStartHistogram.addSample(loopStartEvent.duration,{events:new tr.v.d.RelatedEventSet([loopStartEvent])});if(contentStartEvent){contentStartHistogram.addSample(contentStartEvent.start-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,contentStartEvent])});}
+if(navEvent){navigationStartHistogram.addSample(navEvent.start-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,navEvent])});navigationCommitHistogram.addSample(navEvent.end-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,navEvent])});}
+firstContentfulPaintHistogram.addSample(fcpEvent.end-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,fcpEvent])});if(applicationStartEvent){applicationStartHistogram.addSample(applicationStartEvent.duration,{events:new tr.v.d.RelatedEventSet([applicationStartEvent])});}}}
 tr.metrics.MetricRegistry.register(androidStartupMetric);return{androidStartupMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MAX_INPUT_EVENT_TO_STARTUP_DELAY_IN_MS=2000;const MIN_DRAW_DELAY_IN_MS=80;const MAX_DRAW_DELAY_IN_MS=2000;function findProcess(processName,model){for(const pid in model.processes){const process=model.processes[pid];if(process.name===processName){return process;}}
 return undefined;}
 function findThreads(process,threadPrefix){if(process===undefined)return undefined;const threads=[];for(const tid in process.threads){const thread=process.threads[tid];if(thread.name.startsWith(threadPrefix)){threads.push(thread);}}
@@ -8351,6 +8137,7 @@
 function isFullMarkCompactorEvent(event){return event.title==='V8.GCCompactor';}
 function isMarkCompactorSummaryEvent(event){return event.title==='V8.GCMarkCompactorSummary';}
 function isMarkCompactorMarkingSummaryEvent(event){return event.title==='V8.GCMarkCompactorMarkingSummary';}
+function isScavengerStackScanningEvent(event){return event.title==='V8.GCScavengerStackScanning';}
 function isIncrementalMarkingEvent(event){return event.title.startsWith('V8.GCIncrementalMarking');}
 function isLatencyMarkCompactorEvent(event){return event.title==='V8.GCFinalizeMC';}
 function isMemoryMarkCompactorEvent(event){return event.title==='V8.GCFinalizeMCReduceMemory';}
@@ -8367,7 +8154,7 @@
 return TOP_GC_EVENTS[event.title];}
 function topGarbageCollectionEventNames(){return Object.values(TOP_GC_EVENTS);}
 function subGarbageCollectionEventName(event){const topEvent=findParent(event,isTopGarbageCollectionEvent);const prefix=topEvent?topGarbageCollectionEventName(topEvent):'unknown';const name=event.title.replace('V8.GC_MC_','').replace('V8.GC_SCAVENGER_','').replace('V8.GC_','').replace(/_/g,'-').toLowerCase();return prefix+'-'+name;}
-function jsExecutionThreads(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let threads=[];for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;threads.push(rendererHelper.mainThread);threads=threads.concat(rendererHelper.dedicatedWorkerThreads);threads=threads.concat(rendererHelper.foregroundWorkerThreads);}
+function jsExecutionThreads(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let threads=[];for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;threads.push(rendererHelper.mainThread);threads=threads.concat(rendererHelper.dedicatedWorkerThreads);threads=threads.concat(rendererHelper.serviceWorkerThreads);threads=threads.concat(rendererHelper.foregroundWorkerThreads);}
 return threads;}
 function groupAndProcessEvents(model,filterCallback,groupCallback,processCallback,groups){const groupToEvents={};if(groups){for(const group of groups){groupToEvents[group]=[];}}
 const threads=jsExecutionThreads(model);for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;const group=groupCallback(event);if(groups&&!(group in groupToEvents)){continue;}
@@ -8375,6 +8162,8 @@
 for(const[group,events]of Object.entries(groupToEvents)){processCallback(group,events);}}
 function filterEvents(model,filterCallback){const threads=jsExecutionThreads(model);const events=[];for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;events.push(event);}}
 return events;}
+function filterAndOrderEvents(model,filterCallback,keyCallback){const threads=jsExecutionThreads(model);const events={};for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;const key=keyCallback(event);if(events[key]){events[key].push(event);}else{events[key]=[event];}}}
+return events;}
 function unionOfIntervals(intervals){if(intervals.length===0)return[];return tr.b.math.mergeRanges(intervals.map(x=>{return{min:x.start,max:x.end};}),1e-6,function(ranges){return{start:ranges.reduce((acc,x)=>Math.min(acc,x.min),ranges[0].min),end:ranges.reduce((acc,x)=>Math.max(acc,x.max),ranges[0].max)};});}
 function hasV8Stats(globalMemoryDump){let v8stats=undefined;globalMemoryDump.iterateContainerDumps(function(dump){v8stats=v8stats||dump.getMemoryAllocatorDumpByFullName('v8');});return!!v8stats;}
 function rangeForMemoryDumps(model){const startOfFirstDumpWithV8=model.globalMemoryDumps.filter(hasV8Stats).reduce((start,dump)=>Math.min(start,dump.start),Infinity);if(startOfFirstDumpWithV8===Infinity)return new tr.b.math.Range();return tr.b.math.Range.fromExplicitRange(startOfFirstDumpWithV8,Infinity);}
@@ -8389,8 +8178,10 @@
 function addMutatorUtilization(metricName,eventFilter,timeWindows,rendererHelpers,histograms){const histogramMap=new Map();for(const timeWindow of timeWindows){const summaryOptions={avg:false,count:false,max:false,min:true,std:false,sum:false};const description=`The minimum mutator utilization in ${timeWindow}ms time window`;const histogram=histograms.createHistogram(`${metricName}-${timeWindow}ms_window`,tr.b.Unit.byName.normalizedPercentage_biggerIsBetter,[],{summaryOptions,description});histogramMap.set(timeWindow,histogram);}
 for(const rendererHelper of rendererHelpers){if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread===undefined)continue;const pauses=[];for(const event of rendererHelper.mainThread.sliceGroup.childEvents()){if(eventFilter(event)&&event.end>event.start){pauses.push({start:event.start,end:event.end});}}
 pauses.sort((a,b)=>a.start-b.start);const start=rendererHelper.mainThread.bounds.min;const end=rendererHelper.mainThread.bounds.max;for(const timeWindow of timeWindows){const mu=mutatorUtilization(start,end,timeWindow,pauses);histogramMap.get(timeWindow).addSample(mu.min);}}}
-return{addMutatorUtilization,findParent,forcedGCEventName,filterEvents,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,topGarbageCollectionEventNames,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP={'BlinkGC.AtomicPauseMarkEpilogue':'blink-gc-atomic-pause-mark-epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink-gc-atomic-pause-mark-prologue','BlinkGC.AtomicPauseMarkRoots':'blink-gc-atomic-pause-mark-roots','BlinkGC.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step','BlinkGC.UnifiedMarkingStep':'blink-gc-unified-marking-by-v8','BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact'};const BLINK_TOP_GC_ROOTS_MARKING_EVENTS=['BlinkGC.VisitRoots'];const BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure'];const BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.IncrementalMarkingStep','BlinkGC.UnifiedMarkingStep'];const BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking',].concat(BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS);const BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS=['BlinkGC.ConcurrentMarkingStep'];const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation'];const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS=['BlinkGC.ConcurrentSweepingStep'];const BLINK_TOP_GC_EVENTS=Object.keys(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP).concat(BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP[event.title];}
+return{addMutatorUtilization,findParent,forcedGCEventName,filterEvents,filterAndOrderEvents,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isScavengerStackScanningEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,topGarbageCollectionEventNames,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP={'BlinkGC.AtomicPauseMarkEpilogue':'blink-gc-atomic-pause-mark-epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink-gc-atomic-pause-mark-prologue','BlinkGC.AtomicPauseMarkRoots':'blink-gc-atomic-pause-mark-roots','BlinkGC.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step','BlinkGC.UnifiedMarkingStep':'blink-gc-unified-marking-by-v8','BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact'};const BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP={'BlinkGC.AtomicPauseMarkEpilogue':'blink:gc:main_thread:cycle:full:atomic:mark:epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink:gc:main_thread:cycle:full:atomic:mark:prologue','BlinkGC.AtomicPauseMarkRoots':'blink:gc:main_thread:cycle:full:atomic:mark:roots','BlinkGC.IncrementalMarkingStartMarking':'blink:gc:main_thread:cycle:full:incremental:mark:start','BlinkGC.IncrementalMarkingStep':'blink:gc:main_thread:cycle:full:incremental:mark:step','BlinkGC.UnifiedMarkingStep':'unified:gc:main_thread:cycle:full:mark:step','BlinkGC.CompleteSweep':'blink:gc:main_thread:cycle:full:sweep:complete','BlinkGC.LazySweepInIdle':'blink:gc:main_thread:cycle:full:sweep:idle','BlinkGC.LazySweepOnAllocation':'blink:gc:main_thread:cycle:full:sweep:on_allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink:gc:main_thread:cycle:full:atomic:sweep:compact'};const BLINK_TOP_GC_ROOTS_MARKING_EVENTS=['BlinkGC.VisitRoots'];const BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure'];const BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.IncrementalMarkingStep','BlinkGC.UnifiedMarkingStep'];const BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking',].concat(BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS);const BLINK_GC_FORCED_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking','BlinkGC.MarkBailOutObjects','BlinkGC.MarkFlushV8References','BlinkGC.MarkFlushEphemeronPairs',];const BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS=['BlinkGC.ConcurrentMarkingStep'];const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation'];const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS=['BlinkGC.ConcurrentSweepingStep'];const BLINK_TOP_GC_EVENTS=Object.keys(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP).concat(BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP[event.title];}
 function blinkGarbageCollectionEventNames(){return Object.values(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP);}
+function blinkGarbageCollectionEventNewName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP[event.title];}
+function blinkGarbageCollectionEventNewNames(){return Object.values(BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP);}
 function isNonForcedEvent(event){return(!event.args||!event.args.forced)&&!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);}
 function isNonForcedBlinkGarbageCollectionEvent(event){return BLINK_TOP_GC_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedNonAggregatedBlinkGarbageCollectionEvent(event){return event.title in BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP&&isNonForcedEvent(event);}
@@ -8401,35 +8192,33 @@
 function
 isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent(event){return BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedBlinkGarbageCollectionForegroundMarkingEvent(event){return BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent(event){return BLINK_GC_FORCED_FOREGROUND_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent(event){return BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedBlinkGarbageCollectionForegroundSweepingEvent(event){return BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent(event){return BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonNestedNonForcedBlinkGarbageCollectionEvent(event){return isNonForcedBlinkGarbageCollectionEvent(event)&&!tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isGarbageCollectionEvent);}
-function blinkGcMetric(histograms,model){addDurationOfTopEvents(histograms,model);addDurationOfAtomicPause(histograms,model);addDurationOfAtomicPauseTransitiveClosure(histograms,model);addTotalDurationOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);addTotalDurationOfRootsMarking(histograms,model);addTotalDurationOfMarkingTransitiveClosure(histograms,model);addTotalDurationOfForegroundMarking(histograms,model);addTotalDurationOfBackgroundMarking(histograms,model);addTotalDurationOfForegroundSweeping(histograms,model);addTotalDurationOfBackgroundSweeping(histograms,model);}
-tr.metrics.MetricRegistry.register(blinkGcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
-function createNumericForTotalEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:true,max:false,min:false,std:false,sum:true,percentile:[0.90]});return n;}
-function createNumericForUnifiedEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:true,max:true,min:false,std:false,sum:true,percentile:[0.90]});return n;}
-function addDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedNonAggregatedBlinkGarbageCollectionEvent,blinkGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForTopEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},blinkGarbageCollectionEventNames());}
-function addDurationOfAtomicPause(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionAtomicPauseEvent,event=>event.args.epoch,function(group,events){const cpuDuration=createNumericForTopEventTime('blink-gc-atomic-pause');cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));histograms.addHistogram(cpuDuration);});}
-function addDurationOfAtomicPauseTransitiveClosure(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent,event=>event.args.epoch,function(group,events){const cpuDuration=createNumericForTopEventTime('blink-gc-atomic-pause-mark-transitive-closure');cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));histograms.addHistogram(cpuDuration);});}
-function addTotalDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionEvent,event=>'blink-gc-total',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-total']);}
-function addTotalDurationOfRootsMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionRootsMarkingEvent,event=>'blink-gc-mark-roots',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-mark-roots']);}
-function addTotalDurationOfMarkingTransitiveClosure(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent,event=>'blink-gc-mark-transitive-closure',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-mark-transitive-closure']);}
-function addTotalDurationOfForegroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForegroundMarkingEvent,event=>'blink-gc-mark-foreground',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-mark-foreground']);}
-function addTotalDurationOfBackgroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent,event=>'blink-gc-mark-background',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-mark-background']);}
-function addTotalDurationOfForegroundSweeping(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForegroundSweepingEvent,event=>'blink-gc-sweep-foreground',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-sweep-foreground']);}
-function addTotalDurationOfBackgroundSweeping(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent,event=>'blink-gc-sweep-background',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-sweep-background']);}
+function blinkGcMetric(histograms,model){addDurationOfTopEvents(histograms,model);addDurationOfAtomicPause(histograms,model);addDurationOfAtomicPauseTransitiveClosure(histograms,model);addTotalDurationOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);addTotalDurationOfRootsMarking(histograms,model);addTotalDurationOfMarkingTransitiveClosure(histograms,model);addTotalDurationOfForegroundMarking(histograms,model);addTotalDurationOfForcedForegroundMarking(histograms,model);addTotalDurationOfBackgroundMarking(histograms,model);addTotalDurationOfForegroundSweeping(histograms,model);addTotalDurationOfBackgroundSweeping(histograms,model);}
+function getEventEpochUniqueId(event){return event.parentContainer.parent.stableId+':'+event.args.epoch;}
+tr.metrics.MetricRegistry.register(blinkGcMetric);const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForEventTime(name){const n=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:true,std:true,sum:true,percentile:[0.90]});return n;}
+function addDurationOfTopEvents(histograms,model){const nameToNumeric={};const nameToEpochNumeric={};for(const name of blinkGarbageCollectionEventNames()){nameToNumeric[name]=createNumericForEventTime(name);}
+for(const name of blinkGarbageCollectionEventNewNames()){nameToEpochNumeric[name]=createNumericForEventTime(name);}
+tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedNonAggregatedBlinkGarbageCollectionEvent,getEventEpochUniqueId,function(epoch,events){const namesToPerEpochDurations={};for(const event of events){nameToNumeric[blinkGarbageCollectionEventName(event)].addSample(event.cpuDuration);const name=blinkGarbageCollectionEventNewName(event);namesToPerEpochDurations[name]=(namesToPerEpochDurations[name]||0)+event.cpuDuration;}
+for(const name in namesToPerEpochDurations){nameToEpochNumeric[name].addSample(namesToPerEpochDurations[name]);}});for(const name of blinkGarbageCollectionEventNames()){histograms.addHistogram(nameToNumeric[name]);}
+for(const name of blinkGarbageCollectionEventNewNames()){histograms.addHistogram(nameToEpochNumeric[name]);}}
+function addIndividualDurationsOfEvents(histograms,model,name,filter){const cpuDuration=createNumericForEventTime(name);tr.metrics.v8.utils.groupAndProcessEvents(model,filter,event=>name,function(group,events){for(const event of events){cpuDuration.addSample(event.cpuDuration);}},[name]);histograms.addHistogram(cpuDuration);}
+function addPerEpochDurationsOfEvents(histograms,model,name,filter){const cpuDuration=createNumericForEventTime(name);tr.metrics.v8.utils.groupAndProcessEvents(model,filter,getEventEpochUniqueId,function(epoch,events){cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));});histograms.addHistogram(cpuDuration);}
+function addDurationOfAtomicPause(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-atomic-pause',isNonForcedBlinkGarbageCollectionAtomicPauseEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:atomic',isNonForcedBlinkGarbageCollectionAtomicPauseEvent);}
+function addDurationOfAtomicPauseTransitiveClosure(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-atomic-pause-mark-transitive-closure',isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:atomic:mark:transitive_closure',isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent);}
+function addTotalDurationOfTopEvents(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-total',isNonForcedBlinkGarbageCollectionEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full',isNonForcedBlinkGarbageCollectionEvent);}
+function addTotalDurationOfRootsMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-roots',isNonForcedBlinkGarbageCollectionRootsMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:roots',isNonForcedBlinkGarbageCollectionRootsMarkingEvent);}
+function addTotalDurationOfMarkingTransitiveClosure(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-transitive-closure',isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:transitive_closure',isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent);}
+function addTotalDurationOfForegroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-foreground',isNonForcedBlinkGarbageCollectionForegroundMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark',isNonForcedBlinkGarbageCollectionForegroundMarkingEvent);}
+function addTotalDurationOfForcedForegroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-foreground-forced',isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:forced',isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent);}
+function addTotalDurationOfBackgroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-background',isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:concurrent_thread:cycle:full:mark',isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent);}
+function addTotalDurationOfForegroundSweeping(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-sweep-foreground',isNonForcedBlinkGarbageCollectionForegroundSweepingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:sweep',isNonForcedBlinkGarbageCollectionForegroundSweepingEvent);}
+function addTotalDurationOfBackgroundSweeping(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-sweep-background',isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:concurrent_thread:cycle:full:sweep',isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent);}
 function isV8OrBlinkTopLevelGarbageCollectionEvent(event){return tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent(event)||isNonNestedNonForcedBlinkGarbageCollectionEvent(event);}
-function addTotalDurationOfBlinkAndV8TopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8OrBlinkTopLevelGarbageCollectionEvent,event=>'unified-gc-total',function(name,events){const cpuDuration=createNumericForUnifiedEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['unified-gc-total']);}
+function addTotalDurationOfBlinkAndV8TopEvents(histograms,model){addIndividualDurationsOfEvents(histograms,model,'unified-gc-total',isV8OrBlinkTopLevelGarbageCollectionEvent);}
 return{blinkGcMetric,};});'use strict';tr.exportTo('tr.metrics.blink',function(){function leakDetectionMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper===undefined){throw new Error('Chrome is not present.');}
 const rendererHelpers=modelHelper.rendererHelpers;if(Object.keys(rendererHelpers).length===0){throw new Error('Renderer process is not present.');}
 const pids=Object.keys(rendererHelpers);const chromeDumps=tr.metrics.sh.splitGlobalDumpsByBrowserName(model,undefined).get('chrome');const sumCounter=new Map();for(const pid of pids){for(const[key,count]of countLeakedBlinkObjects(chromeDumps,pid)){sumCounter.set(key,(sumCounter.get(key)||0)+count);}}
@@ -8440,10 +8229,11 @@
 return diffCounter;}
 function countBlinkObjects(dump,pid){const counter=new Map();const processesMemoryDumps=dump.processMemoryDumps;if(processesMemoryDumps[pid]===undefined)return counter;const blinkObjectsDump=processesMemoryDumps[pid].memoryAllocatorDumps.find(dump=>dump.fullName==='blink_objects');for(const v of blinkObjectsDump.children){counter.set(v.name,v.numerics.object_count.value);}
 return counter;}
-return{leakDetectionMetric,};});'use strict';tr.exportTo('tr.metrics.console',function(){const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e4,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;const SOURCES=['all','js','network'];function consoleErrorMetric(histograms,model){const counts={};for(const source of SOURCES){counts[source]=0;}
-for(const slice of model.getDescendantEvents()){if(slice.category==='blink.console'&&slice.title==='ConsoleMessage::Error'){const source=slice.args.source.toLowerCase();counts.all++;if(source in counts){counts[source]++;}}
-if(slice.category==='v8.console'&&(slice.title==='V8ConsoleMessage::Exception'||slice.title==='V8ConsoleMessage::Error'||slice.title==='V8ConsoleMessage::Assert')){counts.all++;counts.js++;}}
-for(const source of SOURCES){histograms.createHistogram(`console:error:${source}`,tr.b.Unit.byName.count_smallerIsBetter,counts[source],{description:`Number of ${source} console error messages`,summaryOptions:SUMMARY_OPTIONS});}}
+return{leakDetectionMetric,};});'use strict';tr.exportTo('tr.metrics.console',function(){const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e4,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;const SOURCES=['all','js','network'];function consoleErrorMetric(histograms,model){const counts={};for(const source of SOURCES){counts[source]={count:0,details:[]};}
+for(const slice of model.getDescendantEvents()){if(slice.category==='blink.console'&&slice.title==='ConsoleMessage::Error'){const source=slice.args.source.toLowerCase();counts.all.count++;if(slice.args.message){counts.all.details.push({pid:slice.getProcess().pid,...slice.args.message});}
+if(source in counts){counts[source].count++;if(slice.args.message){counts[source].details.push({pid:slice.getProcess().pid,...slice.args.message});}}}
+if(slice.category==='v8.console'&&(slice.title==='V8ConsoleMessage::Exception'||slice.title==='V8ConsoleMessage::Error'||slice.title==='V8ConsoleMessage::Assert')){counts.all.count++;counts.js.count++;}}
+for(const source of SOURCES){const hist=histograms.createHistogram(`console:error:${source}`,tr.b.Unit.byName.count_smallerIsBetter,{value:counts[source].count,diagnostics:{details:new tr.v.d.GenericSet(counts[source].details)}},{description:`Number of ${source} console error messages`,summaryOptions:SUMMARY_OPTIONS,});}}
 tr.metrics.MetricRegistry.register(consoleErrorMetric);return{consoleErrorMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function getCpuSnapshotsFromModel(model){const snapshots=[];for(const pid in model.processes){const snapshotInstances=model.processes[pid].objects.getAllInstancesNamed('CPUSnapshots');if(!snapshotInstances)continue;for(const object of snapshotInstances[0].snapshots){snapshots.push(object.args.processes);}}
 return snapshots;}
 function getProcessSumsFromSnapshot(snapshot){const processSums=new Map();for(const processData of snapshot){const processName=processData.name;if(!(processSums.has(processName))){processSums.set(processName,{sum:0.0,paths:new Set()});}
@@ -8458,7 +8248,7 @@
 tr.metrics.MetricRegistry.register(cpuProcessMetric);return{cpuProcessMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function mediaMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(chromeHelper===undefined)return;for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){const mainThread=rendererHelper.mainThread;if(mainThread===undefined)continue;const videoThreads=rendererHelper.process.findAllThreadsMatching(thread=>(thread.name?thread.name.startsWith('ThreadPoolSingleThreadSharedForegroundBlocking'):false));const compositorThread=rendererHelper.compositorThread;if(compositorThread!==undefined){videoThreads.push(compositorThread);}
 const audioThreads=rendererHelper.process.findAllThreadsNamed('AudioOutputDevice');if(audioThreads.length===0&&videoThreads.length===0)continue;const processData=new PerProcessData();processData.recordPlayStarts(mainThread);if(!processData.hasPlaybacks)continue;if(videoThreads.length!==0){processData.calculateTimeToVideoPlays(videoThreads);processData.calculateDroppedFrameCounts(videoThreads);}
 if(audioThreads.length!==0){processData.calculateTimeToAudioPlays(audioThreads);}
-processData.calculateSeekTimes(mainThread);processData.calculateBufferingTimes(mainThread);processData.addMetricToHistograms(histograms);}}
+processData.calculateSeekTimes(mainThread);processData.calculateBufferingTimes(mainThread);const allThreads=rendererHelper.process.findAllThreadsMatching(function(){return true;});processData.calculateVideoPlaybackQuality(allThreads);processData.addMetricToHistograms(histograms);}}
 class PerProcessData{constructor(){this.playbackIdToDataMap_=new Map();}
 recordPlayStarts(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::DoLoad'){const id=event.args.id;if(this.playbackIdToDataMap_.has(id)){throw new Error('Unexpected multiple initialization of a media playback');}
 this.playbackIdToDataMap_.set(id,new PerPlaybackData(event.start));}}}
@@ -8468,15 +8258,18 @@
 calculateSeekTimes(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::DoSeek'){this.getPerPlaybackObject_(event.args.id).processDoSeek(event.args.target,event.start);}else if(event.title==='WebMediaPlayerImpl::OnPipelineSeeked'){this.getPerPlaybackObject_(event.args.id).processOnPipelineSeeked(event.args.target,event.start);}else if(event.title==='WebMediaPlayerImpl::BufferingHaveEnough'){this.getPerPlaybackObject_(event.args.id).processBufferingHaveEnough(event.start);}}}
 calculateBufferingTimes(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::OnEnded'){this.getPerPlaybackObject_(event.args.id).processOnEnded(event.start,event.args.duration);}}}
 calculateDroppedFrameCounts(videoThreads){for(const thread of videoThreads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoFramesDropped'){this.getPerPlaybackObject_(event.args.id).processVideoFramesDropped(event.args.count);}}}}
+calculateVideoPlaybackQuality(threads){for(const thread of threads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoPlaybackRoughness'){this.getPerPlaybackObject_(event.args.id).processVideoRoughness(event.args.roughness);}else if(event.title==='VideoPlaybackFreezing'){this.getPerPlaybackObject_(event.args.id).processVideoFreezing(event.args.freezing);}}}}
 addMetricToHistograms(histograms){for(const[id,playbackData]of this.playbackIdToDataMap_){playbackData.addMetricToHistograms(histograms);}}
 getPerPlaybackObject_(playbackId){let perPlaybackObject=this.playbackIdToDataMap_.get(playbackId);if(perPlaybackObject===undefined){perPlaybackObject=new PerPlaybackData(undefined);this.playbackIdToDataMap_.set(playbackId,perPlaybackObject);}
 return perPlaybackObject;}}
-class PerPlaybackData{constructor(playStartTime){this.playStart_=playStartTime;this.timeToVideoPlay_=undefined;this.timeToAudioPlay_=undefined;this.bufferingTime_=undefined;this.droppedFrameCount_=0;this.seekError_=false;this.seekTimes_=new Map();this.currentSeek_=undefined;}
+class PerPlaybackData{constructor(playStartTime){this.playStart_=playStartTime;this.timeToVideoPlay_=undefined;this.timeToAudioPlay_=undefined;this.bufferingTime_=undefined;this.droppedFrameCount_=0;this.seekError_=false;this.seekTimes_=new Map();this.currentSeek_=undefined;this.roughness_=undefined;this.freezing_=undefined;}
 get timeToVideoPlay(){return this.timeToVideoPlay_;}
 get timeToAudioPlay(){return this.timeToAudioPlay_;}
 get bufferingTime(){return this.bufferingTime_;}
 get droppedFrameCount(){return(this.timeToVideoPlay_!==undefined)?this.droppedFrameCount_:undefined;}
 get seekTimes(){if(this.seekError_||this.currentSeek_!==undefined)return new Map();return this.seekTimes_;}
+get roughness(){return this.roughness_;}
+get freezing(){return this.freezing_;}
 processVideoRenderTime(videoRenderTime){if(this.playStart_!==undefined&&this.timeToVideoPlay_===undefined){this.timeToVideoPlay_=videoRenderTime-this.playStart_;}}
 processAudioRenderTime(audioRenderTime){if(this.playStart_!==undefined&&this.timeToAudioPlay_===undefined){this.timeToAudioPlay_=audioRenderTime-this.playStart_;}}
 processVideoFramesDropped(count){this.droppedFrameCount_+=count;}
@@ -8490,22 +8283,26 @@
 if(currentSeek.pipelineSeekTime===undefined){return;}
 currentSeek.seekTime=time-currentSeek.startTime;this.currentSeek_=undefined;}
 processOnEnded(playEndTime,duration){if(this.playStart_===undefined)return;if(this.seekTimes_.size!==0||this.seekError_)return;if(this.bufferingTime_!==undefined)return;duration=tr.b.convertUnit(duration,tr.b.UnitPrefixScale.METRIC.NONE,tr.b.UnitPrefixScale.METRIC.MILLI);const playTime=playEndTime-this.playStart_;if(this.timeToVideoPlay_!==undefined){this.bufferingTime_=playTime-duration-this.timeToVideoPlay_;}else if(this.timeToAudioPlay!==undefined){this.bufferingTime_=playTime-duration-this.timeToAudioPlay_;}}
+processVideoRoughness(roughness){if(this.roughness_===undefined||this.roughness_>roughness){this.roughness_=roughness;}}
+processVideoFreezing(freezing){if(this.freezing_===undefined||this.freezing_>freezing){this.freezing_=freezing;}}
 addMetricToHistograms(histograms){this.addSample_(histograms,'time_to_video_play',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.timeToVideoPlay);this.addSample_(histograms,'time_to_audio_play',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.timeToAudioPlay);this.addSample_(histograms,'dropped_frame_count',tr.b.Unit.byName.count_smallerIsBetter,this.droppedFrameCount);for(const[key,value]of this.seekTimes.entries()){const keyString=key.toString().replace('.','_');this.addSample_(histograms,'pipeline_seek_time_'+keyString,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value.pipelineSeekTime);this.addSample_(histograms,'seek_time_'+keyString,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value.seekTime);}
-this.addSample_(histograms,'buffering_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.bufferingTime);}
+this.addSample_(histograms,'buffering_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.bufferingTime);this.addSample_(histograms,'roughness',tr.b.Unit.byName.count_smallerIsBetter,this.roughness);this.addSample_(histograms,'freezing',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.freezing);}
 addSample_(histograms,name,unit,sample){if(sample===undefined)return;const histogram=histograms.getHistogramNamed(name);if(histogram===undefined){histograms.createHistogram(name,unit,sample);}else{histogram.addSample(sample);}}}
-tr.metrics.MetricRegistry.register(mediaMetric);return{mediaMetric,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const UNKNOWN_THREAD_NAME='Unknown';const CATEGORY_THREAD_MAP=new Map();CATEGORY_THREAD_MAP.set('total_all',[/.*/]);CATEGORY_THREAD_MAP.set('browser',[/^Browser Compositor$/,/^CrBrowserMain$/]);CATEGORY_THREAD_MAP.set('display_compositor',[/^VizCompositorThread$/]);CATEGORY_THREAD_MAP.set('GPU',[/^Chrome_InProcGpuThread$/,/^CrGpuMain$/]);CATEGORY_THREAD_MAP.set('IO',[/IOThread/]);CATEGORY_THREAD_MAP.set('raster',[/CompositorTileWorker/]);CATEGORY_THREAD_MAP.set('renderer_compositor',[/^Compositor$/]);CATEGORY_THREAD_MAP.set('renderer_main',[/^CrRendererMain$/]);CATEGORY_THREAD_MAP.set('total_rendering',[/^Browser Compositor$/,/^Chrome_InProcGpuThread$/,/^Compositor$/,/CompositorTileWorker/,/^CrBrowserMain$/,/^CrGpuMain$/,/^CrRendererMain$/,/IOThread/,/^VizCompositorThread$/]);const ALL_CATEGORIES=[...CATEGORY_THREAD_MAP.keys(),'other'];function addValueToMap_(map,key,value){const oldValue=map.get(key)||0;map.set(key,oldValue+value);}
-function categoryShouldHaveBreakdown(category){return category==='total_all'||category==='total_rendering';}
+tr.metrics.MetricRegistry.register(mediaMetric);return{mediaMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function memoryAblationMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper.gpuHelper)return;const gpuProcess=modelHelper.gpuHelper.process;const events=[...gpuProcess.findTopmostSlicesNamed('Memory.GPU.PeakMemoryUsage.AblationTimes')];const allocHistogram=histograms.createHistogram('Ablation Alloc',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,10000,20),description:'The amount of time spent allocating the ablation '+'memory',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const deallocHistogram=histograms.createHistogram('Ablation Dealloc',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,10000,20),description:'The amount of time spent deallocating the ablation '+'memory',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});for(let i=0;i<events.length;i++){allocHistogram.addSample(events[i].args.alloc);deallocHistogram.addSample(events[i].args.dealloc);}}
+tr.metrics.MetricRegistry.register(memoryAblationMetric,{requiredCategories:['gpu.memory'],});return{memoryAblationMetric,};});'use strict';tr.exportTo('tr.metrics.pa',function(){function pcscanMetric(histograms,model){function createNumericForProcess(name,processName,desc){function createNumericForEventTime(name,desc){const n=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);n.description=desc;n.customizeSummaryOptions({avg:true,count:true,max:true,min:true,std:true,sum:true});return n;}
+const scheme=['pa','pcscan',processName];if(name)scheme.push(name);return createNumericForEventTime(scheme.join(':'),desc);}
+function createHistsForProcess(processName){return{scan:createNumericForProcess('scan',processName,'Time for scanning heap for quarantine pointers'),sweep:createNumericForProcess('sweep',processName,'Time for sweeping quarantine'),clear:createNumericForProcess('clear',processName,'Time for clearing quarantine entries'),total:createNumericForProcess('',processName,'Total time for PCScan execution')};}
+function addSample(hists,slice){if(!(slice instanceof tr.model.ThreadSlice))return;if(slice.category!=='partition_alloc')return;if(slice.title==='PCScan.Scan'){hists.scan.addSample(slice.duration);}else if(slice.title==='PCScan.Sweep'){hists.sweep.addSample(slice.duration);}else if(slice.title==='PCScan.Clear'){hists.clear.addSample(slice.duration);}else if(slice.title==='PCScan'){hists.total.addSample(slice.duration);}}
+function addHistsForProcess(processHists,processHelpers){for(const helper of Object.values(processHelpers)){const processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(helper.process.name);if(!processHists.has(processName)){processHists.set(processName,createHistsForProcess(processName));}
+for(const slice of helper.process.getDescendantEvents()){addSample(processHists.get(processName),slice);}}}
+const helper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const processHists=new Map();addHistsForProcess(processHists,helper.browserHelpers);addHistsForProcess(processHists,helper.rendererHelpers);for(const hists of processHists.values()){for(const hist of Object.values(hists)){histograms.addHistogram(hist);}}}
+tr.metrics.MetricRegistry.register(pcscanMetric);return{pcscanMetric,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const UNKNOWN_THREAD_NAME='Unknown';const CATEGORY_THREAD_MAP=new Map();CATEGORY_THREAD_MAP.set('total_all',[/.*/]);CATEGORY_THREAD_MAP.set('browser',[/^Browser Compositor$/,/^CrBrowserMain$/]);CATEGORY_THREAD_MAP.set('display_compositor',[/^VizCompositorThread$/]);CATEGORY_THREAD_MAP.set('GPU',[/^Chrome_InProcGpuThread$/,/^CrGpuMain$/]);CATEGORY_THREAD_MAP.set('IO',[/IOThread/]);CATEGORY_THREAD_MAP.set('raster',[/CompositorTileWorker/]);CATEGORY_THREAD_MAP.set('renderer_compositor',[/^Compositor$/]);CATEGORY_THREAD_MAP.set('renderer_main',[/^CrRendererMain$/]);CATEGORY_THREAD_MAP.set('total_rendering',[/^Browser Compositor$/,/^Chrome_InProcGpuThread$/,/^Compositor$/,/CompositorTileWorker/,/^CrBrowserMain$/,/^CrGpuMain$/,/^CrRendererMain$/,/IOThread/,/^VizCompositorThread$/]);const ALL_CATEGORIES=[...CATEGORY_THREAD_MAP.keys(),'other'];function addValueToMap_(map,key,value){const oldValue=map.get(key)||0;map.set(key,oldValue+value);}
+function addToArrayInMap_(map,key,value){const arr=map.get(key)||[];arr.push(value);map.set(key,arr);}
 function*getCategories_(threadName){let isOther=true;for(const[category,regexps]of CATEGORY_THREAD_MAP){for(const regexp of regexps){if(regexp.test(threadName)){if(category!=='total_all')isOther=false;yield category;break;}}}
 if(isOther)yield'other';}
-function isSubset_(regexps1,regexps2){for(const r1 of regexps1){if(regexps2.find(r2=>r2.toString()===r1.toString())===undefined){return false;}}
-return true;}
-function addCpuUtilizationHistograms(histograms,model,segments,segmentCostFunc,histogramNameFunc,description,unit){if(!unit)unit=tr.b.Unit.byName.unitlessNumber;const histogramMap=new Map();for(const category of ALL_CATEGORIES){const histogram=histograms.createHistogram(histogramNameFunc(category),unit,[],{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(1,50,20),description,summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histogramMap.set(category,histogram);}
-for(const[category,regexps]of CATEGORY_THREAD_MAP){const relatedCategories=new tr.v.d.RelatedNameMap();const histogram=histogramMap.get(category);for(const[otherCategory,otherRegexps]of CATEGORY_THREAD_MAP){if(otherCategory===category)continue;if(category!=='all'&&!isSubset_(otherRegexps,regexps))continue;const otherHistogram=histogramMap.get(otherCategory);relatedCategories.set(otherCategory,otherHistogram.name);}
-if([...relatedCategories.values()].length>0){histogram.diagnostics.set('breakdown',relatedCategories);}}
-for(const segment of segments){const threadValues=new Map();for(const thread of model.getAllThreads()){addValueToMap_(threadValues,thread.name||UNKNOWN_THREAD_NAME,segmentCostFunc(thread,segment));}
-const categoryValues=new Map();const breakdowns=new Map();for(const[threadName,coresPerSec]of threadValues){for(const category of getCategories_(threadName)){addValueToMap_(categoryValues,category,coresPerSec);if(!categoryShouldHaveBreakdown(category))continue;if(!breakdowns.has(category)){breakdowns.set(category,new tr.v.d.Breakdown());}
-breakdowns.get(category).set(threadName,coresPerSec);}}
-for(const category of ALL_CATEGORIES){const value=categoryValues.get(category)||0;const diagnostics=new tr.v.d.DiagnosticMap();const breakdown=breakdowns.get(category);if(breakdown)diagnostics.set('breakdown',breakdown);const histogram=histogramMap.get(category);histogram.addSample(value,diagnostics);}}}
+function addCpuUtilizationHistograms(histograms,model,segments,segmentCostFunc,histogramNameFunc,description){const categoryValues=new Map();for(const segment of segments){const threadValues=new Map();for(const thread of model.getAllThreads()){addValueToMap_(threadValues,thread.name||UNKNOWN_THREAD_NAME,segmentCostFunc(thread,segment));}
+for(const[threadName,coresPerSec]of threadValues){for(const category of getCategories_(threadName)){addToArrayInMap_(categoryValues,category,coresPerSec);}}}
+const unit=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;for(const category of ALL_CATEGORIES){const values=categoryValues.get(category)||0;if(!values)continue;const avg=values.reduce((sum,e)=>sum+e,0)/segments.length;histograms.createHistogram(histogramNameFunc(category),unit,avg,{description,summaryOptions:{},});}}
 const SUMMARY_OPTIONS={percentile:[0.90,0.95],ci:[0.95],};return{addCpuUtilizationHistograms,SUMMARY_OPTIONS,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const PRESENT_EVENT='Display::FrameDisplayed';const DISPLAY_EVENT='BenchmarkInstrumentation::DisplayRenderingStats';const DRM_EVENT='DrmEventFlipComplete';const SURFACE_FLINGER_EVENT='vsync_before';const COMPOSITOR_FRAME_PRESENTED_EVENT='FramePresented';const MIN_FRAME_LENGTH=0.5;const MIN_FRAME_COUNT=10;const PAUSE_THRESHOLD=20;const ASH_ENVIRONMENT='ash';const BROWSER_ENVIRONMENT='browser';class FrameEvent{constructor(event){this.event_=event;}
 get eventStart(){return this.event_.start;}
 get frameStart(){if(this.event_.title!==DRM_EVENT)return this.event_.start;const data=this.event_.args.data;const TIME=tr.b.UnitScale.TIME;return tr.b.convertUnit(data['vblank.tv_sec'],TIME.SEC,TIME.MILLI_SEC)+
@@ -8531,11 +8328,11 @@
 return legacyEvents;}
 function computeFrameSegments_(events,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const frameEvents=events.map(e=>new FrameEvent(e));const frameSegments=[];for(const segment of segments){const filtered=segment.boundsRange.filterArray(frameEvents,x=>x.eventStart);if(filtered.length<minFrameCount)continue;for(let i=1;i<filtered.length;i++){const duration=filtered[i].frameStart-filtered[i-1].frameStart;frameSegments.push(new FrameSegment(filtered[i-1],duration));}}
 return frameSegments;}
-function addBasicFrameTimeHistograms_(histograms,frameSegments,prefix){const frameTimes=(frameSegments.length===0)?[0]:frameSegments.map(x=>x.duration);histograms.createHistogram(`${prefix}frame_times`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,frameTimes,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),description:'Raw frame times.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram(`${prefix}percentage_smooth`,tr.b.Unit.byName.unitlessNumber_biggerIsBetter,100*tr.b.math.Statistics.sum(frameTimes,(x=>(x<17?1:0)))/frameTimes.length,{description:'Percentage of frames that were hitting 60 FPS.',summaryOptions:{},});}
+function addBasicFrameTimeHistograms_(histograms,frameSegments,prefix){const frameTimes=(frameSegments.length===0)?[0]:frameSegments.map(x=>x.duration);histograms.createHistogram(`${prefix}frame_times`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,frameTimes,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),description:'Raw frame times.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
 function addFrameTimeHistograms(histograms,model,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const events=getDisplayCompositorPresentationEvents_(modelHelper);if(!events)return;addFrameTimeHistogramsHelper(histograms,model,segments,events,'',true,minFrameCount);const eventsExp=getDisplayCompositorPresentationEventsExp_(modelHelper);if(eventsExp&&eventsExp.length>0){addFrameTimeHistogramsHelper(histograms,model,segments,eventsExp,'exp_',false,minFrameCount);}}
-function addFrameTimeHistogramsHelper(histograms,model,segments,events,prefix,addCpuMetrics,minFrameCount){const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,prefix+'');if(addCpuMetrics){tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getCpuTimeForRange(segment.boundsRange),category=>`thread_${category}_cpu_time_per_frame`,'CPU cores of a thread group per frame',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getNumToplevelSlicesForRange(segment.boundsRange),category=>`tasks_per_frame_${category}`,'Number of tasks of a thread group per frame',tr.b.Unit.byName.unitlessNumber_smallerIsBetter);let totalWallTime=0;let totalCpuTime=0;for(const segment of frameSegments){for(const thread of model.getAllThreads()){totalCpuTime+=thread.getCpuTimeForRange(segment.boundsRange);totalWallTime+=thread.getWallTimeForRange(segment.boundsRange);}}
+function addFrameTimeHistogramsHelper(histograms,model,segments,events,prefix,addCpuMetrics,minFrameCount){const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,prefix+'');if(addCpuMetrics){tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getCpuTimeForRange(segment.boundsRange),category=>`thread_${category}_cpu_time_per_frame`,'CPU cores of a thread group per frame');tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getNumToplevelSlicesForRange(segment.boundsRange),category=>`tasks_per_frame_${category}`,'Number of tasks of a thread group per frame');let totalWallTime=0;let totalCpuTime=0;for(const segment of frameSegments){for(const thread of model.getAllThreads()){totalCpuTime+=thread.getCpuTimeForRange(segment.boundsRange);totalWallTime+=thread.getWallTimeForRange(segment.boundsRange);}}
 histograms.createHistogram('cpu_wall_time_ratio',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,totalCpuTime/totalWallTime,{description:'Ratio of total cpu-time vs. wall-time.',summaryOptions:{},});}
-const refreshPeriod=getRefreshPeriod(model,frameSegments.map(fs=>fs.boundsRange));frameSegments.forEach(fs=>fs.updateLength(refreshPeriod));const validFrames=frameSegments.filter(fs=>fs.length>=MIN_FRAME_LENGTH);const totalFrameDuration=tr.b.math.Statistics.sum(frameSegments,fs=>fs.duration);addJankCountHistograms(histograms,validFrames,prefix);const frameLengths=validFrames.map(frame=>frame.length);histograms.createHistogram(prefix+'frame_lengths',tr.b.Unit.byName.unitlessNumber_smallerIsBetter,frameLengths,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,5,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Frame times in vsyncs.'});histograms.createHistogram(prefix+'avg_surface_fps',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,frameLengths.length/tr.b.convertUnit(totalFrameDuration,tr.b.UnitScale.TIME.MILLI_SEC,tr.b.UnitScale.TIME.SEC),{description:'Average frames per second.',summaryOptions:{},});}
+const refreshPeriod=getRefreshPeriod(model,frameSegments.map(fs=>fs.boundsRange));frameSegments.forEach(fs=>fs.updateLength(refreshPeriod));const validFrames=frameSegments.filter(fs=>fs.length>=MIN_FRAME_LENGTH);const totalFrameDuration=tr.b.math.Statistics.sum(frameSegments,fs=>fs.duration);addJankCountHistograms(histograms,validFrames,prefix);const frameLengths=validFrames.map(frame=>frame.length);histograms.createHistogram(prefix+'avg_surface_fps',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,frameLengths.length/tr.b.convertUnit(totalFrameDuration,tr.b.UnitScale.TIME.MILLI_SEC,tr.b.UnitScale.TIME.SEC),{description:'Average frames per second.',summaryOptions:{},});}
 function addUIFrameTimeHistograms(histograms,model,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const events=getUIPresentationEvents_(model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper));if(events.length===0)return;const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,'ui_');}
 function addJankCountHistograms(histograms,validFrames,prefix){const jankEvents=[];for(let i=1;i<validFrames.length;i++){const change=Math.round((validFrames[i].length-validFrames[i-1].length));if(change>0&&change<PAUSE_THRESHOLD){jankEvents.push(validFrames[i].event);}}
 const jankCount=jankEvents.length;const diagnostics=new tr.v.d.DiagnosticMap();diagnostics.set('events',new tr.v.d.RelatedEventSet(jankEvents));diagnostics.set('timestamps',new tr.v.d.GenericSet(jankEvents.map(e=>e.start)));const histogram=histograms.createHistogram(prefix+'jank_count',tr.b.Unit.byName.count_smallerIsBetter,{value:jankCount,diagnostics},{description:'Number of changes in frame rate.',summaryOptions:{},});}
@@ -8546,30 +8343,7 @@
 return{addFrameTimeHistograms,addUIFrameTimeHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const RGB_DECODE_EVENT='ImageFrameGenerator::decode';const YUV_DECODE_EVENT='ImageFrameGenerator::decodeToYUV';const BLINK_GPU_RASTER_DECODE_EVENT='GpuImageDecodeCache::DecodeImage';const BLINK_SOFTWARE_RASTER_DECODE_EVENT='SoftwareImageDecodeCache::'+'DecodeImageInTask';function getImageDecodingEvents_(modelHelper,ranges){if(!modelHelper||!modelHelper.rendererHelpers)return[];const events=[];for(const renderer of Object.values(modelHelper.rendererHelpers)){for(const thread of renderer.rasterWorkerThreads){const slices=thread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title===RGB_DECODE_EVENT||slice.title===YUV_DECODE_EVENT||slice.title===BLINK_GPU_RASTER_DECODE_EVENT||slice.title===BLINK_SOFTWARE_RASTER_DECODE_EVENT){events.push(slice);}}}}
 return events;}
 function addImageDecodeTimeHistograms(histograms,model,segments){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const decodeEvents=getImageDecodingEvents_(modelHelper,segments.map(s=>s.boundsRange));if(!decodeEvents)return;histograms.createHistogram('rgb_decode_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===RGB_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of the Blink RGB decoding path for a chunk '+'of image data (possibly the whole image).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('yuv_decode_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===YUV_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of the Blink YUV decoding path for a '+'chunk of image data (possibly the whole image).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('blink_decode_time_gpu_rasterization',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===BLINK_GPU_RASTER_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of decoding and scaling within the '+'GpuImageDecodeCache for a chunk of image data '+'(possibly the whole image)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('blink_decode_time_software_rasterization',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===BLINK_SOFTWARE_RASTER_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of decoding and scaling within the '+'SoftwareImageDecodeCache for a chunk of image data '+'(possibly the whole image)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
-return{addImageDecodeTimeHistograms};});'use strict';tr.exportTo('tr.metrics.rendering',function(){function eventIsValidGraphicsEvent_(event,eventMap){if(event.title!=='Graphics.Pipeline'||!event.bindId||!event.args||!event.args.step){return false;}
-const bindId=event.bindId;if(eventMap.has(bindId)&&event.args.step in eventMap.get(bindId)){if(event.args.step==='IssueBeginFrame'||event.args.step==='ReceiveBeginFrame'){throw new Error('Unexpected duplicate step: '+event.args.step);}
-return false;}
-return true;}
-function generateBreakdownForCompositorPipelineInClient_(flow){const breakdown=new tr.v.d.Breakdown();breakdown.set('time before GenerateRenderPass',flow.GenerateRenderPass.start-flow.ReceiveBeginFrame.start);breakdown.set('GenerateRenderPass duration',flow.GenerateRenderPass.duration);breakdown.set('GenerateCompositorFrame duration',flow.GenerateCompositorFrame.duration);breakdown.set('SubmitCompositorFrame duration',flow.SubmitCompositorFrame.duration);return breakdown;}
-function generateBreakdownForCompositorPipelineInService_(flow){const breakdown=new tr.v.d.Breakdown();breakdown.set('Processing CompositorFrame on reception',flow.ReceiveCompositorFrame.duration);breakdown.set('Delay before SurfaceAggregation',flow.SurfaceAggregation.start-flow.ReceiveCompositorFrame.end);breakdown.set('SurfaceAggregation duration',flow.SurfaceAggregation.duration);return breakdown;}
-function generateBreakdownForDraw_(drawEvent){const breakdown=new tr.v.d.Breakdown();for(const slice of drawEvent.subSlices){breakdown.set(slice.title,slice.duration);}
-return breakdown;}
-function getDisplayCompositorThread_(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const gpuHelper=chromeHelper.gpuHelper;if(gpuHelper){const thread=gpuHelper.process.findAtMostOneThreadNamed('VizCompositorThread');if(thread){return thread;}}
-if(!chromeHelper.browserProcess)return null;return chromeHelper.browserProcess.findAtMostOneThreadNamed('CrBrowserMain');}
-function getRasterTaskTimes(sourceFrameNumber,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const renderers=modelHelper.telemetryHelper.renderersWithIR;if(renderers.length===0)return;const rasterThreads=renderers[0].rasterWorkerThreads;let earliestStart=undefined;let lastEnd=undefined;for(const rasterThread of rasterThreads){for(const slice of[...rasterThread.findTopmostSlicesNamed('TaskGraphRunner::RunTask')]){if(slice.args&&slice.args.source_frame_number_&&slice.args.source_frame_number_===sourceFrameNumber){if(earliestStart===undefined||slice.start<earliestStart){earliestStart=slice.start;}
-if(lastEnd===undefined||slice.end>lastEnd){lastEnd=slice.end;}}}}
-return{start:earliestStart,end:lastEnd};}
-function addPipelineHistograms(histograms,model,segments){const ranges=segments.map(s=>s.boundsRange);const bindEvents=new Map();for(const thread of model.getAllThreads()){for(const event of thread.sliceGroup.childEvents()){if(!eventIsValidGraphicsEvent_(event,bindEvents))continue;for(const range of ranges){if(range.containsExplicitRangeInclusive(event.start,event.end)){if(!bindEvents.has(event.bindId))bindEvents.set(event.bindId,{});break;}}
-if(bindEvents.has(event.bindId)){bindEvents.get(event.bindId)[event.args.step]=event;}}}
-const dcThread=getDisplayCompositorThread_(model);const drawEvents={};if(dcThread){const events=[...dcThread.findTopmostSlicesNamed('Graphics.Pipeline.DrawAndSwap')];for(const segment of segments){const filteredEvents=segment.boundsRange.filterArray(events,evt=>evt.start);for(const event of filteredEvents){if((event.args&&event.args.status==='canceled')||!event.id.startsWith(':ptr:')){continue;}
-const id=parseInt(event.id.substring(5),16);if(id in drawEvents){throw new Error('Duplicate draw events: '+id);}
-drawEvents[id]=event;}}}
-const issueToReceipt=histograms.createHistogram('pipeline:begin_frame_transport',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency of begin-frame message from the display '+'compositor to the client, including the IPC latency and task-'+'queue time in the client.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const issueToRasterStart=histograms.createHistogram('pipeline:begin_frame_to_raster_start',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame message and '+'the beginning of the first CompositorTask run in the compositor.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const issueToRasterEnd=histograms.createHistogram('pipeline:begin_frame_to_raster_end',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame message and '+'the end of the last CompositorTask run in the compositor.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const receiptToSubmit=histograms.createHistogram('pipeline:begin_frame_to_frame_submission',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame reception and '+'CompositorFrame submission in the renderer.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const submitToAggregate=histograms.createHistogram('pipeline:frame_submission_to_display',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between CompositorFrame submission in the '+'renderer to display in the display-compositor, including IPC '+'latency, task-queue time in the display-compositor, and '+'additional processing (e.g. surface-sync etc.)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const aggregateToDraw=histograms.createHistogram('pipeline:draw',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'How long it takes for the gpu-swap step.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});for(const flow of bindEvents.values()){if(!flow.IssueBeginFrame||!flow.ReceiveBeginFrame||!flow.SubmitCompositorFrame||!flow.SurfaceAggregation){continue;}
-issueToReceipt.addSample(flow.ReceiveBeginFrame.start-
-flow.IssueBeginFrame.start);receiptToSubmit.addSample(flow.SubmitCompositorFrame.end-flow.ReceiveBeginFrame.start,{breakdown:generateBreakdownForCompositorPipelineInClient_(flow)});submitToAggregate.addSample(flow.SurfaceAggregation.end-flow.SubmitCompositorFrame.end,{breakdown:generateBreakdownForCompositorPipelineInService_(flow)});if(flow.SubmitCompositorFrame.parentSlice){const sourceFrameNumber=flow.SubmitCompositorFrame.parentSlice.args.source_frame_number_;const rasterDuration=getRasterTaskTimes(sourceFrameNumber,model);if(rasterDuration&&rasterDuration.start&&rasterDuration.end){const receiveToStart=rasterDuration.start-
-flow.ReceiveBeginFrame.start;const receiveToEnd=rasterDuration.end-flow.ReceiveBeginFrame.end;if(receiveToEnd>0){issueToRasterStart.addSample(receiveToStart>0?receiveToStart:0);issueToRasterEnd.addSample(receiveToEnd);}}}
-if(flow.SurfaceAggregation.args&&flow.SurfaceAggregation.args.display_trace){const displayTrace=flow.SurfaceAggregation.args.display_trace;if(!(displayTrace in drawEvents))continue;const drawEvent=drawEvents[displayTrace];aggregateToDraw.addSample(drawEvent.duration,{breakdown:generateBreakdownForDraw_(drawEvent)});}}}
-return{addPipelineHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const IMPL_THREAD_RENDERING_STATS_EVENT='BenchmarkInstrumentation::ImplThreadRenderingStats';const VISIBLE_CONTENT_DATA='visible_content_area';const APPROXIMATED_VISIBLE_CONTENT_DATA='approximated_visible_content_area';const CHECKERBOARDED_VISIBLE_CONTENT_DATA='checkerboarded_visible_content_area';function addPixelsHistograms(histograms,model,segments){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;const approximatedPixelPercentages=[];const checkerboardedPixelPercentages=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.compositorThread===undefined)continue;const slices=rendererHelper.compositorThread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==IMPL_THREAD_RENDERING_STATS_EVENT)continue;const data=slice.args.data;if(!(VISIBLE_CONTENT_DATA in data)){throw new Error(`${VISIBLE_CONTENT_DATA} is missing`);}
+return{addImageDecodeTimeHistograms};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const IMPL_THREAD_RENDERING_STATS_EVENT='BenchmarkInstrumentation::ImplThreadRenderingStats';const VISIBLE_CONTENT_DATA='visible_content_area';const APPROXIMATED_VISIBLE_CONTENT_DATA='approximated_visible_content_area';const CHECKERBOARDED_VISIBLE_CONTENT_DATA='checkerboarded_visible_content_area';function addPixelsHistograms(histograms,model,segments){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;const approximatedPixelPercentages=[];const checkerboardedPixelPercentages=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.compositorThread===undefined)continue;const slices=rendererHelper.compositorThread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==IMPL_THREAD_RENDERING_STATS_EVENT)continue;const data=slice.args.data;if(!(VISIBLE_CONTENT_DATA in data)){throw new Error(`${VISIBLE_CONTENT_DATA} is missing`);}
 const visibleContentArea=data[VISIBLE_CONTENT_DATA];if(visibleContentArea===0){continue;}
 if(APPROXIMATED_VISIBLE_CONTENT_DATA in data){approximatedPixelPercentages.push(data[APPROXIMATED_VISIBLE_CONTENT_DATA]/visibleContentArea);}
 if(CHECKERBOARDED_VISIBLE_CONTENT_DATA in data){checkerboardedPixelPercentages.push(data[CHECKERBOARDED_VISIBLE_CONTENT_DATA]/visibleContentArea);}}}
@@ -8580,7 +8354,7 @@
 const queueingDurations=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of targetRenderers){const mainThread=rendererHelper.mainThread;const compositorThread=rendererHelper.compositorThread;if(mainThread===undefined||compositorThread===undefined)continue;const beginMainFrameTimes=getEventTimesByBeginFrameId_(mainThread,BEGIN_MAIN_FRAME_EVENT,ranges);const sendBeginFrameTimes=getEventTimesByBeginFrameId_(compositorThread,SEND_BEGIN_FRAME_EVENT,ranges);for(const[id,time]of sendBeginFrameTimes){queueingDurations.push(beginMainFrameTimes.get(id)-time);}}
 histograms.createHistogram('queueing_durations',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,queueingDurations,{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(0.01,2,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Time between ScheduledActionSendBeginMainFrame in '+'the compositor thread and the corresponding '+'BeginMainFrame in the main thread.'});}
 return{addQueueingDurationHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const GESTURE_EVENT='SyntheticGestureController::running';function renderingMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;let segments=chromeHelper.telemetryHelper.irSegments;if(segments.length===0){segments=chromeHelper.telemetryHelper.animationSegments;}
-if(segments.length>0){tr.metrics.rendering.addFrameTimeHistograms(histograms,model,segments);tr.metrics.rendering.addImageDecodeTimeHistograms(histograms,model,segments);tr.metrics.rendering.addPipelineHistograms(histograms,model,segments);tr.metrics.rendering.addPixelsHistograms(histograms,model,segments);tr.metrics.rendering.addQueueingDurationHistograms(histograms,model,segments);}
+if(segments.length>0){tr.metrics.rendering.addFrameTimeHistograms(histograms,model,segments);tr.metrics.rendering.addImageDecodeTimeHistograms(histograms,model,segments);tr.metrics.rendering.addPixelsHistograms(histograms,model,segments);tr.metrics.rendering.addQueueingDurationHistograms(histograms,model,segments);}
 const uiSegments=chromeHelper.telemetryHelper.uiSegments;if(uiSegments.length>0){tr.metrics.rendering.addUIFrameTimeHistograms(histograms,model,chromeHelper.telemetryHelper.uiSegments);}}
 tr.metrics.MetricRegistry.register(renderingMetric,{requiredCategories:['benchmark','toplevel'],});return{renderingMetric,};});'use strict';tr.exportTo('tr.metrics',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const EventFinderUtils=tr.e.chrome.EventFinderUtils;const METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(80e3,30);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function reportedByPageMetric(histograms,model){const timeToViewable=histograms.createHistogram('reported_by_page:time_to_viewable',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from navigation start'+'to telemetry:reported_by_page:viewable',summaryOptions:SUMMARY_OPTIONS,});const timeToInteractive=histograms.createHistogram('reported_by_page:time_to_interactive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from navigation start '+'to telemetry:reported_by_page:interactive',summaryOptions:SUMMARY_OPTIONS,});const benchmarkTime=histograms.createHistogram('reported_by_page:benchmark_time',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from telemetry:reported_by_page:benchmark_begin '+'to telemetry:reported_by_page:benchmark_end',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread===undefined)continue;measureUserTime(rendererHelper,'navigationStart','telemetry:reported_by_page:viewable',timeToViewable);measureUserTime(rendererHelper,'navigationStart','telemetry:reported_by_page:interactive',timeToInteractive);measureUserTime(rendererHelper,'telemetry:reported_by_page:benchmark_begin','telemetry:reported_by_page:benchmark_end',benchmarkTime);}}
 function measureUserTime(rendererHelper,startName,endName,histogram){const startEventByNavId=new Map();for(const event of rendererHelper.mainThread.sliceGroup.childEvents()){const navId=getNavigationId(event);if(!navId)continue;if(EventFinderUtils.hasCategoryAndName(event,'blink.user_timing',startName)){startEventByNavId.set(navId,event);}
@@ -8682,7 +8456,7 @@
 const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addRectsBasedSpeedIndexSample(rectsBasedSpeedIndexSamples,rendererHelper,expectation.navigationStart.start,expectation.duration,expectation.navigationStart.args.frame);}
 return rectsBasedSpeedIndexSamples;}
 function rectsBasedSpeedIndexMetric(histograms,model){const rectsBasedSpeedIndexHistogram=histograms.createHistogram('rectsBasedSpeedIndex',timeDurationInMs_smallerIsBetter,[],{binBoundaries:BIN_BOUNDARIES,description:' the average time at which visible parts of the'+' page are displayed (in ms).',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const samples=collectRectsBasedSpeedIndexSamplesFromLoadExpectations(model,chromeHelper);for(const sample of samples){rectsBasedSpeedIndexHistogram.addSample(sample.value);}}
-tr.metrics.MetricRegistry.register(rectsBasedSpeedIndexMetric);return{rectsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LONG_TASK_THRESHOLD_MS=50;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const RelatedEventSet=tr.v.d.RelatedEventSet;const hasCategoryAndName=tr.metrics.sh.hasCategoryAndName;const EventFinderUtils=tr.e.chrome.EventFinderUtils;function createBreakdownDiagnostic(breakdownTree){const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownTree){breakdownDiagnostic.set(label,breakdownTree[label].total);}
+tr.metrics.MetricRegistry.register(rectsBasedSpeedIndexMetric);return{rectsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.v.d',function(){const ALERT_GROUPS={CPU_USAGE:'cpu_usage',LOADING_PAINT:'loading_paint',LOADING_INTERACTIVITY:'loading_interactivity',LOADING_LAYOUT:'loading_layout',};return{ALERT_GROUPS,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LONG_TASK_THRESHOLD_MS=50;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const RelatedEventSet=tr.v.d.RelatedEventSet;const hasCategoryAndName=tr.metrics.sh.hasCategoryAndName;const EventFinderUtils=tr.e.chrome.EventFinderUtils;function createBreakdownDiagnostic(breakdownTree){const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownTree){breakdownDiagnostic.set(label,breakdownTree[label].total);}
 return breakdownDiagnostic;}
 const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const TIME_TO_INTERACTIVE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,40e3,35).addExponentialBins(80e3,15);const LAYOUT_SHIFT_SCORE_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,50,25);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
 return snapshot;}
@@ -8703,7 +8477,7 @@
 function findLayoutShiftSamples(rendererHelper){let sample;EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'LayoutShift','loading').forEach((events)=>{const evData=events.pop().args.data;if(evData.is_main_frame){sample={value:evData.cumulative_score};}});return sample?[sample]:[];}
 function addFirstMeaningfulPaintSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToFMPRange);const timeToFirstMeaningfulPaint=navStartToFMPRange.duration;const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToFMPRange);samples.push({value:timeToFirstMeaningfulPaint,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
 function addFirstMeaningfulPaintCpuTimeSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const mainThreadCpuTime=rendererHelper.mainThread.getCpuTimeForRange(navStartToFMPRange);const breakdownTree=tr.metrics.sh.generateCpuTimeBreakdownTree(rendererHelper.mainThread,navStartToFMPRange);samples.push({value:mainThreadCpuTime,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
-function decorateInteractivitySampleWithDiagnostics_(rendererHelper,eventTimestamp,navigationStartEvent,firstMeaningfulPaintTime,domContentLoadedEndTime,url){if(eventTimestamp===undefined)return undefined;const navigationStartTime=navigationStartEvent.start;const navStartToEventTimeRange=tr.b.math.Range.fromExplicitRange(navigationStartTime,eventTimestamp);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventTimeRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventTimeRange);const breakdownDiagnostic=createBreakdownDiagnostic(breakdownTree);return{value:navStartToEventTimeRange.duration,diagnostics:tr.v.d.DiagnosticMap.fromObject({'Start':new RelatedEventSet(navigationStartEvent),'Navigation infos':new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,navigationStartTime,firstMeaningfulPaintTime,domContentLoadedEndTime,eventTimestamp,}]),'Breakdown of [navStart, eventTimestamp]':breakdownDiagnostic,}),};}
+function decorateInteractivitySampleWithDiagnostics_(rendererHelper,eventTimestamp,navigationStartEvent,firstContentfulPaintTime,domContentLoadedEndTime,url){if(eventTimestamp===undefined)return undefined;const navigationStartTime=navigationStartEvent.start;const navStartToEventTimeRange=tr.b.math.Range.fromExplicitRange(navigationStartTime,eventTimestamp);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventTimeRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventTimeRange);const breakdownDiagnostic=createBreakdownDiagnostic(breakdownTree);return{value:navStartToEventTimeRange.duration,diagnostics:tr.v.d.DiagnosticMap.fromObject({'Start':new RelatedEventSet(navigationStartEvent),'Navigation infos':new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,navigationStartTime,firstContentfulPaintTime,domContentLoadedEndTime,eventTimestamp,}]),'Breakdown of [navStart, eventTimestamp]':breakdownDiagnostic,}),};}
 function getCandidateIndex(entry){return entry.targetEvent.args.data.candidateIndex;}
 function findLastCandidateForEachNavigation(timeToXEntries){const entryMap=new Map();for(const e of timeToXEntries){const navStartEvent=e.navigationStartEvent;if(!entryMap.has(navStartEvent)){entryMap.set(navStartEvent,[]);}
 entryMap.get(navStartEvent).push(e);}
@@ -8714,16 +8488,17 @@
 function findLargestImagePaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents){const timeToPaintEntries=findTimeToXEntries('loading','LargestImagePaint::Candidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const timeToPaintBlockingEntries=findTimeToXEntries('loading','LargestImagePaint::NoCandidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const lastCandidateEvents=findLastCandidateForEachNavigation(timeToPaintEntries.concat(timeToPaintBlockingEntries)).filter(event=>event.targetEvent.title!=='LargestImagePaint::NoCandidate');return collectTimeToEvent(rendererHelper,lastCandidateEvents);}
 function findLargestContentfulPaintHistogramSamples(allBrowserEvents){const lcp=new tr.e.chrome.LargestContentfulPaint(allBrowserEvents);const lcpSamples=lcp.findCandidates().map(candidate=>{const{durationInMilliseconds,size,type,inMainFrame,mainFrameTreeNodeId}=candidate;return{value:durationInMilliseconds,diagnostics:{size:new tr.v.d.GenericSet([size]),type:new tr.v.d.GenericSet([type]),inMainFrame:new tr.v.d.GenericSet([inMainFrame]),mainFrameTreeNodeId:new tr.v.d.GenericSet([mainFrameTreeNodeId]),},};});return lcpSamples;}
 function collectLoadingMetricsForRenderer(rendererHelper){const frameToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const navIdToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByNavId(rendererHelper,'navigationStart','blink.user_timing');const firstPaintSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('loading','firstPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const timeToFCPEntries=findTimeToXEntries('loading','firstContentfulPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const firstContentfulPaintSamples=collectTimeToEvent(rendererHelper,timeToFCPEntries);const firstContentfulPaintCpuTimeSamples=collectTimeToEventInCpuTime(rendererHelper,timeToFCPEntries);const onLoadSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('blink.user_timing','loadEventStart',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const aboveTheFoldLoadedToVisibleSamples=getAboveTheFoldLoadedToVisibleSamples(rendererHelper);const firstViewportReadySamples=getFirstViewportReadySamples(rendererHelper,navIdToNavStartEvents);const largestImagePaintSamples=findLargestImagePaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const largestTextPaintSamples=findLargestTextPaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const layoutShiftSamples=findLayoutShiftSamples(rendererHelper);const navigationStartSamples=timeToFCPEntries.map(entry=>{return{value:entry.navigationStartEvent.start};});return{frameToNavStartEvents,firstPaintSamples,firstContentfulPaintSamples,firstContentfulPaintCpuTimeSamples,onLoadSamples,aboveTheFoldLoadedToVisibleSamples,firstViewportReadySamples,largestImagePaintSamples,largestTextPaintSamples,layoutShiftSamples,navigationStartSamples,};}
-function collectMetricsFromLoadExpectations(model,chromeHelper){const interactiveSamples=[];const firstCpuIdleSamples=[];const firstMeaningfulPaintSamples=[];const firstMeaningfulPaintCpuTimeSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+function collectMetricsFromLoadExpectations(model,chromeHelper){const interactiveSamples=[];const firstCpuIdleSamples=[];const firstMeaningfulPaintSamples=[];const firstMeaningfulPaintCpuTimeSamples=[];const totalBlockingTimeSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
 const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];if(expectation.fmpEvent!==undefined){addFirstMeaningfulPaintSample(firstMeaningfulPaintSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);addFirstMeaningfulPaintCpuTimeSample(firstMeaningfulPaintCpuTimeSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);}
-if(expectation.firstCpuIdleTime!==undefined){firstCpuIdleSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.firstCpuIdleTime,expectation.navigationStart,expectation.fmpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}
-if(expectation.timeToInteractive!==undefined){interactiveSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.timeToInteractive,expectation.navigationStart,expectation.fmpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}}
-return{firstMeaningfulPaintSamples,firstMeaningfulPaintCpuTimeSamples,firstCpuIdleSamples,interactiveSamples,};}
+if(expectation.firstCpuIdleTime!==undefined){firstCpuIdleSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.firstCpuIdleTime,expectation.navigationStart,expectation.fcpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}
+if(expectation.timeToInteractive!==undefined){interactiveSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.timeToInteractive,expectation.navigationStart,expectation.fcpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}
+if(expectation.totalBlockingTime!==undefined){totalBlockingTimeSamples.push({value:expectation.totalBlockingTime,diagnostics:{url:new tr.v.d.GenericSet([expectation.url]),navigationStart:new RelatedEventSet(expectation.navigationStart),firstContentfulPaint:new RelatedEventSet(expectation.fcpEvent),interactiveTime:new tr.v.d.GenericSet([expectation.timeToInteractive]),}});}}
+return{firstMeaningfulPaintSamples,firstMeaningfulPaintCpuTimeSamples,firstCpuIdleSamples,interactiveSamples,totalBlockingTimeSamples,};}
 function addSamplesToHistogram(samples,histogram,histograms){for(const sample of samples){histogram.addSample(sample.value,sample.diagnostics);if(histogram.name!=='timeToFirstContentfulPaint')continue;if(!sample.breakdownTree)continue;for(const[category,breakdown]of Object.entries(sample.breakdownTree)){const relatedName=`${histogram.name}:${category}`;let relatedHist=histograms.getHistogramsNamed(relatedName)[0];if(!relatedHist){relatedHist=histograms.createHistogram(relatedName,histogram.unit,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,summaryOptions:{count:false,max:false,min:false,sum:false,},});let relatedNames=histogram.diagnostics.get('breakdown');if(!relatedNames){relatedNames=new tr.v.d.RelatedNameMap();histogram.diagnostics.set('breakdown',relatedNames);}
 relatedNames.set(category,relatedName);}
 relatedHist.addSample(breakdown.total,{breakdown:tr.v.d.Breakdown.fromEntries(Object.entries(breakdown.events)),});}}}
-function loadingMetric(histograms,model){const firstPaintHistogram=histograms.createHistogram('timeToFirstPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintHistogram=histograms.createHistogram('timeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const onLoadHistogram=histograms.createHistogram('timeToOnload',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to onload. '+'This is temporary metric used for PCv1/v2 sanity checking',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintHistogram=histograms.createHistogram('timeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const timeToInteractiveHistogram=histograms.createHistogram('timeToInteractive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to Interactive',summaryOptions:SUMMARY_OPTIONS,});const timeToFirstCpuIdleHistogram=histograms.createHistogram('timeToFirstCpuIdle',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to First CPU Idle',summaryOptions:SUMMARY_OPTIONS,});const aboveTheFoldLoadedToVisibleHistogram=histograms.createHistogram('aboveTheFoldLoadedToVisible',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from first visible to load for AMP pages only.',summaryOptions:SUMMARY_OPTIONS,});const firstViewportReadyHistogram=histograms.createHistogram('timeToFirstViewportReady',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from navigation to load for AMP pages only. ',summaryOptions:SUMMARY_OPTIONS,});const largestImagePaintHistogram=histograms.createHistogram('largestImagePaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Image Paint',summaryOptions:SUMMARY_OPTIONS,});const largestTextPaintHistogram=histograms.createHistogram('largestTextPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Text Paint',summaryOptions:SUMMARY_OPTIONS,});const largestContentfulPaintHistogram=histograms.createHistogram('largestContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Contentful Paint',summaryOptions:SUMMARY_OPTIONS,});const layoutShiftHistogram=histograms.createHistogram('mainFrameCumulativeLayoutShift',unitlessNumber_smallerIsBetter,[],{binBoundaries:LAYOUT_SHIFT_SCORE_BOUNDARIES,description:'Main Frame Document Cumulative Layout Shift Score',summaryOptions:SUMMARY_OPTIONS,});const navigationStartHistogram=histograms.createHistogram('navigationStart',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'navigationStart',summaryOptions:SUMMARY_OPTIONS,});tr.metrics.sh.rectsBasedSpeedIndexMetric(histograms,model);const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;const samplesSet=collectLoadingMetricsForRenderer(rendererHelper);const lcpSamples=findLargestContentfulPaintHistogramSamples(chromeHelper.browserHelper.mainThread.sliceGroup.slices);addSamplesToHistogram(lcpSamples,largestContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstPaintSamples,firstPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintSamples,firstContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintCpuTimeSamples,firstContentfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.onLoadSamples,onLoadHistogram,histograms);addSamplesToHistogram(samplesSet.aboveTheFoldLoadedToVisibleSamples,aboveTheFoldLoadedToVisibleHistogram,histograms);addSamplesToHistogram(samplesSet.firstViewportReadySamples,firstViewportReadyHistogram,histograms);addSamplesToHistogram(samplesSet.largestImagePaintSamples,largestImagePaintHistogram,histograms);addSamplesToHistogram(samplesSet.largestTextPaintSamples,largestTextPaintHistogram,histograms);addSamplesToHistogram(samplesSet.layoutShiftSamples,layoutShiftHistogram,histograms);addSamplesToHistogram(samplesSet.navigationStartSamples,navigationStartHistogram,histograms);}
-const samplesSet=collectMetricsFromLoadExpectations(model,chromeHelper);addSamplesToHistogram(samplesSet.firstMeaningfulPaintSamples,firstMeaningfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstMeaningfulPaintCpuTimeSamples,firstMeaningfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.interactiveSamples,timeToInteractiveHistogram,histograms);addSamplesToHistogram(samplesSet.firstCpuIdleSamples,timeToFirstCpuIdleHistogram,histograms);}
+function loadingMetric(histograms,model){const firstPaintHistogram=histograms.createHistogram('timeToFirstPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstContentfulPaintHistogram=histograms.createHistogram('timeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstContentfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const onLoadHistogram=histograms.createHistogram('timeToOnload',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to onload. '+'This is temporary metric used for PCv1/v2 sanity checking',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintHistogram=histograms.createHistogram('timeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstMeaningfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const timeToInteractiveHistogram=histograms.createHistogram('timeToInteractive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to Interactive',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});const totalBlockingTimeHistogram=histograms.createHistogram('totalBlockingTime',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Total Blocking Time',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});const timeToFirstCpuIdleHistogram=histograms.createHistogram('timeToFirstCpuIdle',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to First CPU Idle',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});const aboveTheFoldLoadedToVisibleHistogram=histograms.createHistogram('aboveTheFoldLoadedToVisible',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from first visible to load for AMP pages only.',summaryOptions:SUMMARY_OPTIONS,});const firstViewportReadyHistogram=histograms.createHistogram('timeToFirstViewportReady',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from navigation to load for AMP pages only. ',summaryOptions:SUMMARY_OPTIONS,});const largestImagePaintHistogram=histograms.createHistogram('largestImagePaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Image Paint',summaryOptions:SUMMARY_OPTIONS,});const largestTextPaintHistogram=histograms.createHistogram('largestTextPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Text Paint',summaryOptions:SUMMARY_OPTIONS,});const largestContentfulPaintHistogram=histograms.createHistogram('largestContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Contentful Paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const layoutShiftHistogram=histograms.createHistogram('mainFrameCumulativeLayoutShift',unitlessNumber_smallerIsBetter,[],{binBoundaries:LAYOUT_SHIFT_SCORE_BOUNDARIES,description:'Main Frame Document Cumulative Layout Shift Score',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_LAYOUT],});const navigationStartHistogram=histograms.createHistogram('navigationStart',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'navigationStart',summaryOptions:SUMMARY_OPTIONS,});tr.metrics.sh.rectsBasedSpeedIndexMetric(histograms,model);const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;const samplesSet=collectLoadingMetricsForRenderer(rendererHelper);const lcpSamples=findLargestContentfulPaintHistogramSamples(chromeHelper.browserHelper.mainThread.sliceGroup.slices);addSamplesToHistogram(lcpSamples,largestContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstPaintSamples,firstPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintSamples,firstContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintCpuTimeSamples,firstContentfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.onLoadSamples,onLoadHistogram,histograms);addSamplesToHistogram(samplesSet.aboveTheFoldLoadedToVisibleSamples,aboveTheFoldLoadedToVisibleHistogram,histograms);addSamplesToHistogram(samplesSet.firstViewportReadySamples,firstViewportReadyHistogram,histograms);addSamplesToHistogram(samplesSet.largestImagePaintSamples,largestImagePaintHistogram,histograms);addSamplesToHistogram(samplesSet.largestTextPaintSamples,largestTextPaintHistogram,histograms);addSamplesToHistogram(samplesSet.layoutShiftSamples,layoutShiftHistogram,histograms);addSamplesToHistogram(samplesSet.navigationStartSamples,navigationStartHistogram,histograms);}
+const samplesSet=collectMetricsFromLoadExpectations(model,chromeHelper);addSamplesToHistogram(samplesSet.firstMeaningfulPaintSamples,firstMeaningfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstMeaningfulPaintCpuTimeSamples,firstMeaningfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.interactiveSamples,timeToInteractiveHistogram,histograms);addSamplesToHistogram(samplesSet.firstCpuIdleSamples,timeToFirstCpuIdleHistogram,histograms);addSamplesToHistogram(samplesSet.totalBlockingTimeSamples,totalBlockingTimeHistogram,histograms);}
 tr.metrics.MetricRegistry.register(loadingMetric);return{loadingMetric,createBreakdownDiagnostic};});'use strict';tr.exportTo('tr.metrics',function(){const SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY=tr.v.HistogramBinBoundaries.createExponential(1,1000,50);function spaNavigationMetric(histograms,model){const histogram=new tr.v.Histogram('spaNavigationStartToFpDuration',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY);histogram.description='Latency between the input event causing'+' a SPA navigation and the first paint event after it';histogram.customizeSummaryOptions({count:false,sum:false,});const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper){return;}
 const rendererHelpers=modelHelper.rendererHelpers;if(!rendererHelpers){return;}
 const browserHelper=modelHelper.browserHelper;for(const rendererHelper of Object.values(rendererHelpers)){const spaNavigations=tr.metrics.findSpaNavigationsOnRenderer(rendererHelper,browserHelper);for(const spaNav of spaNavigations){let beginTs=0;if(spaNav.navStartCandidates.inputLatencyAsyncSlice){const beginData=spaNav.navStartCandidates.inputLatencyAsyncSlice.args.data;beginTs=model.convertTimestampToModelTime('traceEventClock',beginData.INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT.time);}else{beginTs=spaNav.navStartCandidates.goToIndexSlice.start;}
@@ -8737,7 +8512,7 @@
 let processCpuTime=0;for(const tid in process.threads){const thread=process.threads[tid];processCpuTime+=thread.getCpuTimeForRange(rangeOfInterest);}
 allProcessCpuTime+=processCpuTime;}
 let normalizedAllProcessCpuTime=0;if(rangeOfInterest.duration>0){normalizedAllProcessCpuTime=allProcessCpuTime/rangeOfInterest.duration;}
-const unit=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const cpuTimeHist=new tr.v.Histogram('cpu_time_percentage',unit,CPU_TIME_PERCENTAGE_BOUNDARIES);cpuTimeHist.description='Percent CPU utilization, normalized against a single core. Can be '+'greater than 100% if machine has multiple cores.';cpuTimeHist.customizeSummaryOptions({avg:true,count:false,max:false,min:false,std:false,sum:false});cpuTimeHist.addSample(normalizedAllProcessCpuTime);histograms.addHistogram(cpuTimeHist);}
+const unit=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const cpuTimeHist=new tr.v.Histogram('cpu_time_percentage',unit,CPU_TIME_PERCENTAGE_BOUNDARIES);cpuTimeHist.description='Percent CPU utilization, normalized against a single core. Can be '+'greater than 100% if machine has multiple cores.';cpuTimeHist.setAlertGrouping([tr.v.d.ALERT_GROUPS.CPU_USAGE]);cpuTimeHist.customizeSummaryOptions({avg:true,count:false,max:false,min:false,std:false,sum:false});cpuTimeHist.addSample(normalizedAllProcessCpuTime);histograms.addHistogram(cpuTimeHist);}
 tr.metrics.MetricRegistry.register(cpuTimeMetric,{supportsRangeOfInterest:true});return{cpuTimeMetric,};});'use strict';tr.exportTo('tr.v',function(){class HistogramDeserializer{static deserialize(data){const deserializer=new HistogramDeserializer(data[0],data[1]);return data.slice(2).map(datum=>tr.v.Histogram.deserialize(datum,deserializer));}
 constructor(objects,diagnostics){this.objects_=objects;this.diagnostics_=[];for(const[type,diagnosticsByName]of Object.entries(diagnostics||{})){for(const[name,diagnosticsById]of Object.entries(diagnosticsByName)){for(const[id,data]of Object.entries(diagnosticsById)){const diagnostic=tr.v.d.Diagnostic.deserialize(type,data,this);this.diagnostics_[parseInt(id)]={name,diagnostic};}}}}
 getObject(id){return this.objects_[id];}
@@ -9173,13 +8948,16 @@
 const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addSpeedIndexScreenshotsBasedSample(speedIndexScreenshotsBasedSamples,expectation.navigationStart,expectation.duration,chromeHelper.browserHelper);}
 return speedIndexScreenshotsBasedSamples;}
 function screenshotsBasedSpeedIndexMetric(histograms,model){const speedIndexScreenshotsBasedHistogram=histograms.createHistogram('speedIndexScreenshotsBased',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'The average time at which visible parts of the'+' page are displayed.',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const samples=collectSpeedIndexSamplesFromLoadExpectations(model,chromeHelper);for(const sample of samples){speedIndexScreenshotsBasedHistogram.addSample(sample.value);}}
-tr.metrics.MetricRegistry.register(screenshotsBasedSpeedIndexMetric);return{screenshotsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function webviewStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('webview_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebView startup wall time';const startupCPUHist=new tr.v.Histogram('webview_startup_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupCPUHist.description='WebView startup CPU time';const loadWallHist=new tr.v.Histogram('webview_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebView blank URL load wall time';const loadCPUHist=new tr.v.Histogram('webview_url_load_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadCPUHist.description='WebView blank URL load CPU time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebViewStartupInterval'){startupWallHist.addSample(slice.duration);startupCPUHist.addSample(slice.cpuDuration);}
+tr.metrics.MetricRegistry.register(screenshotsBasedSpeedIndexMetric);return{screenshotsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function weblayerStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('weblayer_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebLayer startup wall time';const loadWallHist=new tr.v.Histogram('weblayer_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebLayer blank URL load wall time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebLayerStartupInterval'){startupWallHist.addSample(slice.duration);}
+if(slice.title==='WebLayerBlankUrlLoadInterval'){loadWallHist.addSample(slice.duration);}}
+histograms.addHistogram(startupWallHist);histograms.addHistogram(loadWallHist);}
+tr.metrics.MetricRegistry.register(weblayerStartupMetric);return{weblayerStartupMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function webviewStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('webview_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebView startup wall time';const startupCPUHist=new tr.v.Histogram('webview_startup_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupCPUHist.description='WebView startup CPU time';const loadWallHist=new tr.v.Histogram('webview_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebView blank URL load wall time';const loadCPUHist=new tr.v.Histogram('webview_url_load_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadCPUHist.description='WebView blank URL load CPU time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebViewStartupInterval'){startupWallHist.addSample(slice.duration);startupCPUHist.addSample(slice.cpuDuration);}
 if(slice.title==='WebViewBlankUrlLoadInterval'){loadWallHist.addSample(slice.duration);loadCPUHist.addSample(slice.cpuDuration);}}
 histograms.addHistogram(startupWallHist);histograms.addHistogram(startupCPUHist);histograms.addHistogram(loadWallHist);histograms.addHistogram(loadCPUHist);}
 tr.metrics.MetricRegistry.register(webviewStartupMetric);return{webviewStartupMetric,};});'use strict';tr.exportTo('tr.metrics.tabs',function(){function tabsMetric(histograms,model,opt_options){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper){return;}
 const tabSwitchRequestDelays=[];const TAB_SWITCHING_REQUEST_TITLE='TabSwitchVisibilityRequest';let startTabSwitchVisibilityRequest=Number.MAX_SAFE_INTEGER;for(const helper of chromeHelper.browserHelpers){if(!helper.mainThread)continue;for(const slice of helper.mainThread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_REQUEST_TITLE&&!slice.error){tabSwitchRequestDelays.push(slice.duration);if(slice.start<startTabSwitchVisibilityRequest){startTabSwitchVisibilityRequest=slice.start;}}}}
 histograms.createHistogram('tab_switching_request_delay',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchRequestDelays,{description:'Delay before tab-request is made',summaryOptions:{sum:false}});const tabSwitchLatencies=[];const TAB_SWITCHING_SLICE_TITLE='TabSwitching::Latency';function extractLatencyFromHelpers(helpers,legacy){for(const helper of helpers){if(!helper.mainThread){continue;}
-const thread=helper.mainThread;for(const slice of thread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_SLICE_TITLE&&(legacy||slice.args.latency)&&slice.start>startTabSwitchVisibilityRequest){tabSwitchLatencies.push(legacy?slice.duration:slice.args.latency);}}}}
+const thread=helper.mainThread;for(const slice of thread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_SLICE_TITLE&&(legacy||slice.args.latency)&&slice.start>startTabSwitchVisibilityRequest-1){tabSwitchLatencies.push(legacy?slice.duration:slice.args.latency);}}}}
 extractLatencyFromHelpers(chromeHelper.browserHelpers);extractLatencyFromHelpers(Object.values(chromeHelper.rendererHelpers));if(tabSwitchLatencies.length===0){extractLatencyFromHelpers(chromeHelper.browserHelpers,true);}
 histograms.createHistogram('tab_switching_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchLatencies,{description:'Tab switching time in ms',summaryOptions:{sum:false}});}
 tr.metrics.MetricRegistry.register(tabsMetric,{supportsRangeOfInterest:false,});return{tabsMetric,};});'use strict';tr.exportTo('tr.metrics',function(){const MEMORY_INFRA_TRACING_CATEGORY='disabled-by-default-memory-infra';const TIME_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1e-3,1e5,30);const BYTE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e9,30);const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e5,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;function addMemoryInfraHistograms(histograms,model,categoryNamesToTotalEventSizes){const memoryDumpCount=model.globalMemoryDumps.length;if(memoryDumpCount===0)return;let totalOverhead=0;let nonMemoryInfraThreadOverhead=0;const overheadByProvider={};for(const process of Object.values(model.processes)){for(const thread of Object.values(process.threads)){for(const slice of Object.values(thread.sliceGroup.slices)){if(slice.category!==MEMORY_INFRA_TRACING_CATEGORY)continue;totalOverhead+=slice.duration;if(thread.name!=='MemoryInfra'){nonMemoryInfraThreadOverhead+=slice.duration;}
@@ -9197,20 +8975,17 @@
 function mergeBins_(x,y){x.sum+=y.sum;const allBins=[...x.bins,...y.bins];allBins.sort((a,b)=>a.min-b.min);x.bins=[];let last=undefined;for(const bin of allBins){if(last!==undefined&&bin.min===last.min){if(last.max!==bin.max)throw new Error('Incompatible bins');if(bin.count===0)continue;last.count+=bin.count;for(const event of bin.events){last.events.add(event);}
 last.processes.addDiagnostic(bin.processes);}else{if(last!==undefined&&bin.min<last.max){throw new Error('Incompatible bins');}
 x.bins.push(bin);last=bin;}}}
-function subtractBins_(x,y){x.sum-=y.sum;let p1=0;let p2=0;while(p2<y.bins.length){while(p1<x.bins.length&&x.bins[p1].min!==y.bins[p2].min){p1++;}
-if(p1===x.bins.length)throw new Error('Cannot subtract');if(x.bins[p1].max!==y.bins[p2].max){throw new Error('Incompatible bins');}
-if(x.bins[p1].count<y.bins[p2].count){throw new Error('Cannot subtract');}
-x.bins[p1].count-=y.bins[p2].count;for(const event of y.bins[p2].events){x.bins[p1].events.add(event);}
-const processName=tr.b.getOnlyElement(x.bins[p1].processes)[0];x.bins[p1].processes.set(processName,x.bins[p1].count);p2++;}}
 function getHistogramUnit_(name){return tr.b.Unit.byName.unitlessNumber_smallerIsBetter;}
+function getIsHistogramBinsLinear_(histogramName){return histogramName.startsWith('Graphics.Smoothness.Throughput')||histogramName.startsWith('Memory.Memory.GPU.PeakMemoryUsage');}
 function getHistogramBoundaries_(name){if(name.startsWith('Event.Latency.Scroll')){return tr.v.HistogramBinBoundaries.createExponential(1e3,1e5,50);}
 if(name.startsWith('Graphics.Smoothness.Throughput')){return tr.v.HistogramBinBoundaries.createLinear(0,100,101);}
 if(name.startsWith('Memory.Memory.GPU.PeakMemoryUsage')){return tr.v.HistogramBinBoundaries.createLinear(0,1e6,100);}
 return tr.v.HistogramBinBoundaries.createExponential(1e-3,1e3,50);}
 function umaMetric(histograms,model){const histogramValues=new Map();const nameCounts=new Map();for(const process of model.getAllProcesses()){const histogramEvents=new Map();for(const event of process.instantEvents){if(event.title!=='UMAHistogramSamples')continue;const name=event.args.name;const events=histogramEvents.get(name)||[];if(!histogramEvents.has(name))histogramEvents.set(name,events);events.push(event);}
-let processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(process.name);nameCounts.set(processName,(nameCounts.get(processName)||0)+1);processName=`${processName}_${nameCounts.get(processName)}`;for(const[name,events]of histogramEvents){const values=histogramValues.get(name)||{sum:0,bins:[]};if(!histogramValues.has(name))histogramValues.set(name,values);const endValues=parseBuckets_(events[events.length-1],processName);if(events.length===1){mergeBins_(values,endValues);}else if(events.length===2){subtractBins_(endValues,parseBuckets_(events[0],processName));mergeBins_(values,endValues);}else{throw new Error('There should be at most two snapshots of an UMA '+'histogram in each process');}}}
-for(const[name,values]of histogramValues){const histogram=new tr.v.Histogram(name,getHistogramUnit_(name),getHistogramBoundaries_(name));let sumOfMiddles=0;let sumOfBinLengths=0;for(const bin of values.bins){sumOfMiddles+=bin.count*(bin.min+bin.max)/2;sumOfBinLengths+=bin.count*(bin.max-bin.min);}
-const shift=(values.sum-sumOfMiddles)/sumOfBinLengths;if(Math.abs(shift)>0.5)throw new Error('Samples sum is wrong');for(const bin of values.bins){if(bin.count===0)continue;const shiftedValue=(bin.min+bin.max)/2+shift*(bin.max-bin.min);for(const[processName,count]of bin.processes){bin.processes.set(processName,shiftedValue*count/bin.count);}
+let processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(process.name);nameCounts.set(processName,(nameCounts.get(processName)||0)+1);processName=`${processName}_${nameCounts.get(processName)}`;for(const[name,events]of histogramEvents){const values=histogramValues.get(name)||{sum:0,bins:[]};if(!histogramValues.has(name))histogramValues.set(name,values);const endValues=parseBuckets_(events[events.length-1],processName);if(events.length===1){mergeBins_(values,endValues,name);}else{throw new Error('There should be at most one snapshot of UMA '+`histogram for ${name} in each process.`);}}}
+for(const[name,values]of histogramValues){const histogram=new tr.v.Histogram(name,getHistogramUnit_(name),getHistogramBoundaries_(name));const isLinear=getIsHistogramBinsLinear_(name);let sumOfMiddles=0;let sumOfBinLengths=0;for(const bin of values.bins){sumOfMiddles+=bin.count*(bin.min+bin.max)/2;sumOfBinLengths+=bin.count*(bin.max-bin.min);}
+const shift=(values.sum-sumOfMiddles)/sumOfBinLengths;if(isLinear&&Math.abs(shift)>0.5){throw new Error(`Samples sum is wrong for ${name}.`);}
+for(const bin of values.bins){if(bin.count===0)continue;const shiftedValue=(bin.min+bin.max)/2+shift*(bin.max-bin.min);for(const[processName,count]of bin.processes){bin.processes.set(processName,shiftedValue*count/bin.count);}
 for(let i=0;i<bin.count;i++){histogram.addSample(shiftedValue,{processes:bin.processes,events:bin.events});}}
 histograms.addHistogram(histogram);}}
 tr.metrics.MetricRegistry.register(umaMetric,{requiredCategories:['benchmark'],});return{umaMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(4,200,100);function computeExecuteMetrics(histograms,model){const cpuTotalExecution=new tr.v.Histogram('v8_execution_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalExecution.description='cpu total time spent in script execution';const wallTotalExecution=new tr.v.Histogram('v8_execution_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalExecution.description='wall total time spent in script execution';const cpuSelfExecution=new tr.v.Histogram('v8_execution_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfExecution.description='cpu self time spent in script execution';const wallSelfExecution=new tr.v.Histogram('v8_execution_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfExecution.description='wall self time spent in script execution';for(const e of model.findTopmostSlicesNamed('V8.Execute')){cpuTotalExecution.addSample(e.cpuDuration);wallTotalExecution.addSample(e.duration);cpuSelfExecution.addSample(e.cpuSelfTime);wallSelfExecution.addSample(e.selfTime);}
@@ -9230,9 +9005,54 @@
 function computeDeoptimizeCodeMetrics(histograms,model){const cpuTotalDeoptimizeCode=new tr.v.Histogram('v8_deoptimize_code_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalDeoptimizeCode.description='cpu total time spent in code deoptimization';const wallTotalDeoptimizeCode=new tr.v.Histogram('v8_deoptimize_code_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalDeoptimizeCode.description='wall total time spent in code deoptimization';for(const e of model.findTopmostSlicesNamed('V8.DeoptimizeCode')){cpuTotalDeoptimizeCode.addSample(e.cpuDuration);wallTotalDeoptimizeCode.addSample(e.duration);}
 histograms.addHistogram(cpuTotalDeoptimizeCode);histograms.addHistogram(wallTotalDeoptimizeCode);}
 function executionMetric(histograms,model){computeExecuteMetrics(histograms,model);computeParseLazyMetrics(histograms,model);computeCompileIgnitionMetrics(histograms,model);computeCompileFullCodeMetrics(histograms,model);computeRecompileMetrics(histograms,model);computeOptimizeCodeMetrics(histograms,model);computeDeoptimizeCodeMetrics(histograms,model);}
-tr.metrics.MetricRegistry.register(executionMetric);return{executionMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const TARGET_FPS=60;const MS_PER_SECOND=1000;const WINDOW_SIZE_MS=MS_PER_SECOND/TARGET_FPS;function gcMetric(histograms,model,options){options=options||{};addDurationOfTopEvents(histograms,model);addTotalDurationOfTopEvents(histograms,model);if(options.include_sub_events){addDurationOfSubEvents(histograms,model);}
-addPercentageInV8ExecuteOfTopEvents(histograms,model);addTotalPercentageInV8Execute(histograms,model);addMarkCompactorMutatorUtilization(histograms,model);addTotalMarkCompactorTime(histograms,model);addTotalMarkCompactorMarkingTime(histograms,model);}
-tr.metrics.MetricRegistry.register(gcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
+tr.metrics.MetricRegistry.register(executionMetric);return{executionMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const TARGET_FPS=60;const MS_PER_SECOND=1000;const WINDOW_SIZE_MS=MS_PER_SECOND/TARGET_FPS;const EPSILON=1e-6;const METRICS=['v8:gc:cycle:full','v8:gc:cycle:full:cpp','v8:gc:cycle:full:mark','v8:gc:cycle:full:mark:cpp','v8:gc:cycle:full:weak','v8:gc:cycle:full:weak:cpp','v8:gc:cycle:full:sweep','v8:gc:cycle:full:sweep:cpp','v8:gc:cycle:full:compact','v8:gc:cycle:full:compact:cpp','v8:gc:cycle:main_thread:full','v8:gc:cycle:main_thread:full:cpp','v8:gc:cycle:main_thread:full:mark','v8:gc:cycle:main_thread:full:mark:cpp','v8:gc:cycle:main_thread:full:weak','v8:gc:cycle:main_thread:full:weak:cpp','v8:gc:cycle:main_thread:full:sweep','v8:gc:cycle:main_thread:full:sweep:cpp','v8:gc:cycle:main_thread:full:compact','v8:gc:cycle:main_thread:full:compact:cpp','v8:gc:event:main_thread:full:atomic','v8:gc:event:main_thread:full:atomic:cpp','v8:gc:event:main_thread:full:atomic:mark','v8:gc:event:main_thread:full:atomic:mark:cpp','v8:gc:event:main_thread:full:atomic:weak','v8:gc:event:main_thread:full:atomic:weak:cpp','v8:gc:event:main_thread:full:atomic:sweep','v8:gc:event:main_thread:full:atomic:sweep:cpp','v8:gc:event:main_thread:full:atomic:compact','v8:gc:event:main_thread:full:atomic:compact:cpp','v8:gc:event:main_thread:full:incremental','v8:gc:event:main_thread:full:incremental:cpp','v8:gc:event:main_thread:full:incremental:mark','v8:gc:event:main_thread:full:incremental:mark:cpp','v8:gc:event:main_thread:full:incremental:sweep','v8:gc:event:main_thread:full:incremental:sweep:cpp','v8:gc:cycle:young','v8:gc:cycle:main_thread:young',];const V8_FULL_ATOMIC_EVENTS=['V8.GCCompactor','V8.GCFinalizeMC','V8.GCFinalizeMCReduceMemory',];const V8_FULL_MARK_EVENTS=['V8.GC_MC_BACKGROUND_MARKING','V8.GC_MC_MARK','V8.GCIncrementalMarking','V8.GCIncrementalMarkingFinalize','V8.GCIncrementalMarkingStart',];const V8_FULL_COMPACT_EVENTS=['V8.GC_MC_BACKGROUND_EVACUATE_COPY','V8.GC_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS','V8.GC_MC_EVACUATE',];const V8_FULL_SWEEP_EVENTS=['V8.GC_MC_BACKGROUND_SWEEPING','V8.GC_MC_SWEEP',];const V8_FULL_WEAK_EVENTS=['V8.GC_MC_CLEAR',];const V8_YOUNG_EVENTS=['V8.GC_SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL','V8.GCScavenger',];const CPP_GC_FULL_MARK_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.ConcurrentMarkingStep','BlinkGC.IncrementalMarkingStartMarking','BlinkGC.IncrementalMarkingStep','BlinkGC.MarkBailOutObjects','BlinkGC.MarkFlushEphemeronPairs','BlinkGC.MarkFlushV8References','BlinkGC.UnifiedMarkingStep',];const CPP_GC_FULL_COMPACT_EVENTS=['BlinkGC.AtomicPauseSweepAndCompact',];const CPP_GC_FULL_SWEEP_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.ConcurrentSweepingStep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation',];const RULES=[{events:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic',},{events:V8_FULL_MARK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:mark',},{events:CPP_GC_FULL_MARK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:mark:cpp',},{events:V8_FULL_MARK_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:mark',},{events:CPP_GC_FULL_MARK_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:mark:cpp',},{events:V8_FULL_COMPACT_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:compact',},{events:CPP_GC_FULL_COMPACT_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:compact:cpp',},{events:V8_FULL_SWEEP_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:sweep',},{events:CPP_GC_FULL_SWEEP_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:sweep:cpp',},{events:V8_FULL_WEAK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:weak',},{events:V8_FULL_SWEEP_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:sweep',},{events:CPP_GC_FULL_SWEEP_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:sweep:cpp',},{events:V8_YOUNG_EVENTS,contribute_to:'young:atomic',},];const Granularity={CYCLE:'cycle',EVENT:'event',};const ThreadType={MAIN:'main',BACKGROUND:'background',ALL_THREADS:'all_threads',};class Metric{constructor(name){const parts=name.split(':');this.granularity_=parts[2];assert(this.granularity_===Granularity.CYCLE||this.granularity_===Granularity.EVENT);this.thread_=ThreadType.ALL_THREADS;let phasesIndex=3;if(parts[3]==='main_thread'){this.thread_=ThreadType.MAIN;phasesIndex=4;}
+if(parts[3]==='background_threads'){this.thread_=ThreadType.BACKGROUND;phasesIndex=4;}
+this.phases_=parts.slice(phasesIndex);const maxValue=this.isPerCycleMetric()?10000:1000;const boundaries=tr.v.HistogramBinBoundaries.createExponential(0.1,maxValue,100);this.histogram=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,boundaries);this.histogram.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:false,sum:this.isPerCycleMetric(),});}
+isPerCycleMetric(){return this.granularity_===Granularity.CYCLE;}
+isMoreGeneralThanOrEqualTo(phases){const phasesSet=new Set(phases.split(':'));return this.phases_.every(phase=>phasesSet.has(phase));}
+contributingEvents(rules,events){const eventsByName=groupBy(events,e=>e.title);function matches(rule,event){function isEnclosing(name){if(!eventsByName.has(name))return false;return eventsByName.get(name).some(e=>encloses(e,event));}
+if(!rule.events.includes(event.title)){return false;}
+if(rule.inside&&!rule.inside.some(isEnclosing)){return false;}
+if(rule.outside&&rule.outside.some(isEnclosing)){return false;}
+return true;}
+const result=[];for(const event of events){const matching=rules.filter(r=>matches(r,event));if(matching.length===0){continue;}
+assert(matching.length===1,`${event.userFriendlyName} matches more than one rule: `+
+JSON.stringify(matching));if(this.isMoreGeneralThanOrEqualTo(matching[0].contribute_to)){result.push(event);}}
+return result;}
+apply(rules,events,threadTypes){const filtered=this.contributingEvents(rules,events);const eventsByThread=groupBy(filtered,e=>e.parentContainer.tid);let flattened=[];for(const[tid,threadEvents]of eventsByThread){if(this.thread_===ThreadType.ALL_THREADS||this.thread_===threadTypes.get(tid)){flattened=flattened.concat(flatten(threadEvents));}}
+if(this.isPerCycleMetric()){let sum=0;for(const event of flattened){sum+=event.cpuDuration;}
+if(flattened.length>0){this.histogram.addSample(sum);}}else{for(const event of flattened){this.histogram.addSample(event.cpuDuration);}}}}
+function assert(condition,message){if(!condition){throw new Error(message);}}
+function groupBy(objects,keyCallback){const result=new Map();for(const object of objects){const group=keyCallback(object);if(result.has(group)){result.get(group).push(object);}else{result.set(group,[object]);}}
+return result;}
+function eventsMentionedIn(rules){let result=[];for(const rule of rules){result=result.concat(rule.events);if(rule.inside){result=result.concat(rule.inside);}
+if(rule.outside){result=result.concat(rule.outside);}}
+return result;}
+function encloses(event1,event2){return(event1.start-EPSILON<=event2.start&&event2.end<=event1.end+EPSILON);}
+function jsExecutionThreadsWithTypes(rendererHelper){const mainThreads=([rendererHelper.mainThread].concat(rendererHelper.dedicatedWorkerThreads).concat(rendererHelper.serviceWorkerThreads));const backgroundThreads=rendererHelper.foregroundWorkerThreads;const threadTypes=new Map();for(const thread of mainThreads){threadTypes.set(thread.tid,ThreadType.MAIN);}
+for(const thread of backgroundThreads){threadTypes.set(thread.tid,ThreadType.BACKGROUND);}
+return[mainThreads.concat(backgroundThreads),threadTypes];}
+function flatten(events){function compareWithEpsilon(a,b){if(a.start<b.start-EPSILON)return-1;if(a.start>b.start+EPSILON)return 1;return b.end-a.end;}
+events.sort(compareWithEpsilon);let last=events[0];const result=[last];for(const e of events){if(e.end>last.end+EPSILON){assert(e.start>=last.end-EPSILON,'Overlapping events: '+
+e.userFriendlyName+' '+
+last.userFriendlyName);result.push(e);last=e;}}
+return result;}
+function groupByEpoch(events){function isV8Event(event){return event.category&&event.category.includes('v8');}
+function getEpoch(event){function checkEpochConsistency(epoch,event){if(epoch===null)return;assert(epoch===event.args.epoch,`${event.userFriendlyName} has epoch ${event.args.epoch} `+`which contradicts the epoch of nested events ${epoch}`);}
+const result={v8:null,cpp:null};while(event){if('epoch'in event.args){if(isV8Event(event)){checkEpochConsistency(result.v8,event);result.v8=event.args.epoch;}else{checkEpochConsistency(result.cpp,event);result.cpp=event.args.epoch;}}
+event=event.parentSlice;}
+return result;}
+const cppToV8=new Map();for(const event of events){const epoch=getEpoch(event);if(epoch.cpp!==null&&epoch.v8!==null){assert(!cppToV8.has(epoch.cpp)||cppToV8.get(epoch.cpp)===epoch.v8,`CppGC epoch ${epoch.cpp} corresponds to two v8 epochs `+`${cppToV8.get(epoch.cpp)} and ${epoch.v8}. `+`Detected at ${event.userFriendlyName}.`);cppToV8.set(epoch.cpp,epoch.v8);}}
+const result=new Map();for(const event of events){const epoch=getEpoch(event);if(epoch.cpp===null&&epoch.v8===null){continue;}
+assert(epoch.cpp===null||cppToV8.has(epoch.cpp),`CppGC epoch ${epoch.cpp} doesn't have the corresponding V8 epoch. `+`Detected at ${event.userFriendlyName}`);const key=epoch.v8===null?cppToV8.get(epoch.cpp):epoch.v8;if(result.has(key)){result.get(key).push(event);}else{result.set(key,[event]);}}
+return result;}
+function addGarbageCollectionMetrics(metricNames,histograms,model){const metrics=metricNames.map(name=>new Metric(name));const gcEventNames=new Set(eventsMentionedIn(RULES));const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;const[threads,threadTypes]=jsExecutionThreadsWithTypes(rendererHelper);const events=[];for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(gcEventNames.has(event.title)){events.push(event);}}}
+for(const cycleEvents of groupByEpoch(events).values()){if(cycleEvents.some(tr.metrics.v8.utils.isForcedGarbageCollectionEvent)){continue;}
+for(const metric of metrics){metric.apply(RULES,cycleEvents,threadTypes);}}}
+for(const metric of metrics){histograms.addHistogram(metric.histogram);}}
+function gcMetric(histograms,model,options){options=options||{};addDurationOfTopEvents(histograms,model);addTotalDurationOfTopEvents(histograms,model);if(options.include_sub_events){addDurationOfSubEvents(histograms,model);}
+addPercentageInV8ExecuteOfTopEvents(histograms,model);addTotalPercentageInV8Execute(histograms,model);addMarkCompactorMutatorUtilization(histograms,model);addTotalMarkCompactorTime(histograms,model);addTotalMarkCompactorMarkingTime(histograms,model);addScavengerSurvivedFromStackEvents(histograms,model);}
+tr.metrics.MetricRegistry.register(gcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const bytes_smallerIsBetter=tr.b.Unit.byName.sizeInBytes_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
 function createNumericForSubEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:false,std:false,sum:false,percentile:[0.90]});return n;}
 function createNumericForIdleTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:false,std:false,sum:true,percentile:[]});return n;}
 function createPercentage(name,numerator,denominator,unit){const hist=new tr.v.Histogram(name,unit);if(denominator===0){hist.addSample(0);}else{hist.addSample(numerator/denominator);}
@@ -9245,13 +9065,16 @@
 histograms.addHistogram(foregroundDuration);histograms.addHistogram(backgroundDuration);histograms.addHistogram(totalDuration,{breakdown:relatedNames});}
 function addTotalMarkCompactorTime(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8MarkCompactorSummary,event=>'v8-gc-mark-compactor',(name,events)=>createHistogramFromSummary(histograms,name,events),['v8-gc-mark-compactor']);}
 function addTotalMarkCompactorMarkingTime(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8MarkCompactorMarkingSummary,event=>'v8-gc-mark-compactor-marking',(name,events)=>createHistogramFromSummary(histograms,name,events),['v8-gc-mark-compactor-marking']);}
+function createNumericForTotalBytes(name){const n=new tr.v.Histogram(name,bytes_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:false,max:false,min:false,std:false,sum:true,percentile:[]});return n;}
+function createNumericForSampledPercent(name){const n=new tr.v.Histogram(name,percentage_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:true,std:true,sum:false,percentile:[]});return n;}
+function addScavengerSurvivedFromStackEvents(histograms,model){const baseName='v8-gc-scavenger-survived';tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isScavengerStackScanningEvent,event=>baseName,function(name,events){const sampledPercentage=createNumericForSampledPercent(baseName+'-percentage-from-stack');let survivedWithoutStack=0;let survivedWithStack=0;events.forEach(function(event){const bytesBefore=event.args.survived_bytes_before;const bytesAfter=event.args.survived_bytes_after;sampledPercentage.addSample((bytesAfter>0)?(bytesAfter-bytesBefore)/bytesAfter:0);survivedWithoutStack+=bytesBefore;survivedWithStack+=bytesAfter;});histograms.addHistogram(sampledPercentage);const totalBytesSurvivedWithoutStack=createNumericForTotalBytes(baseName+'-total-bytes-without-stack');totalBytesSurvivedWithoutStack.addSample(survivedWithoutStack);histograms.addHistogram(totalBytesSurvivedWithoutStack);const totalBytesSurvivedWithStack=createNumericForTotalBytes(baseName+'-total-bytes-with-stack');totalBytesSurvivedWithStack.addSample(survivedWithStack);histograms.addHistogram(totalBytesSurvivedWithStack);const overallPercentage=createPercentage(baseName+'-total-percentage-from-stack',survivedWithStack-survivedWithoutStack,survivedWithStack,percentage_smallerIsBetter);histograms.addHistogram(overallPercentage);},[baseName]);}
 function addDurationOfSubEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedSubGarbageCollectionEvent,tr.metrics.v8.utils.subGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForSubEventTime(name);events.forEach(function(event){cpuDuration.addSample(event.cpuDuration);});histograms.addHistogram(cpuDuration);});}
 function addPercentageInV8ExecuteOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,tr.metrics.v8.utils.topGarbageCollectionEventName,function(name,events){addPercentageInV8Execute(histograms,model,name,events);},tr.metrics.v8.utils.topGarbageCollectionEventNames());}
 function addTotalPercentageInV8Execute(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,event=>'v8-gc-total',function(name,events){addPercentageInV8Execute(histograms,model,name,events);},['v8-gc-total']);}
 function addPercentageInV8Execute(histograms,model,name,events){let cpuDurationInV8Execute=0;let cpuDurationTotal=0;events.forEach(function(event){const v8Execute=tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isV8ExecuteEvent);if(v8Execute){cpuDurationInV8Execute+=event.cpuDuration;}
 cpuDurationTotal+=event.cpuDuration;});const percentage=createPercentage(name+'_percentage_in_v8_execute',cpuDurationInV8Execute,cpuDurationTotal,percentage_smallerIsBetter);histograms.addHistogram(percentage);}
 function addMarkCompactorMutatorUtilization(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=Object.values(chromeHelper.rendererHelpers);tr.metrics.v8.utils.addMutatorUtilization('v8-gc-mark-compactor-mmu',tr.metrics.v8.utils.isNotForcedMarkCompactorEvent,[100],rendererHelpers,histograms);}
-return{gcMetric,WINDOW_SIZE_MS,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const COUNT_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1000000,50);const DURATION_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.1,10000,50);const SUMMARY_OPTIONS={std:false,count:false,sum:false,min:false,max:false,};function convertMicroToMilli_(time){return tr.b.convertUnit(time,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);}
+return{gcMetric,WINDOW_SIZE_MS,addGarbageCollectionMetrics,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const COUNT_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1000000,50);const DURATION_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.1,10000,50);const SUMMARY_OPTIONS={std:false,count:false,sum:false,min:false,max:false,};function convertMicroToMilli_(time){return tr.b.convertUnit(time,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);}
 function addDurationHistogram(histogramName,time,histograms){const value=convertMicroToMilli_(time);histograms.createHistogram(`${histogramName}:duration`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,{value},{binBoundaries:DURATION_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});}
 function addCountHistogram(histogramName,value,histograms){histograms.createHistogram(`${histogramName}:count`,tr.b.Unit.byName.count_smallerIsBetter,{value},{binBoundaries:COUNT_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS});}
 function runtimeStatsTotalMetric(histograms,model){const v8Slices=tr.metrics.v8.utils.filterEvents(model,ev=>ev instanceof tr.e.v8.V8ThreadSlice);const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(v8Slices);let overallV8Time=runtimeGroupCollection.totalTime;let overallV8Count=runtimeGroupCollection.totalCount;let mainThreadTime=runtimeGroupCollection.totalTime;let mainThreadCount=runtimeGroupCollection.totalCount;let mainThreadV8Time=runtimeGroupCollection.totalTime;let mainThreadV8Count=runtimeGroupCollection.totalCount;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addDurationHistogram(runtimeGroup.name,runtimeGroup.time,histograms);if(runtimeGroup.name==='Blink C++'){overallV8Time-=runtimeGroup.time;mainThreadV8Time-=runtimeGroup.time;}else if(runtimeGroup.name.includes('Background')){mainThreadTime-=runtimeGroup.time;mainThreadV8Time-=runtimeGroup.time;}
@@ -9259,7 +9082,15 @@
 if(runtimeGroupCollection.blinkRCSGroupCollection.totalTime>0){const blinkRCSGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;for(const group of blinkRCSGroupCollection.runtimeGroups){addDurationHistogram(group.name,group.time,histograms);addCountHistogram(group.name,group.count,histograms);}}
 addDurationHistogram('V8-Only',overallV8Time,histograms);addCountHistogram('V8-Only',overallV8Count,histograms);addDurationHistogram('Total-Main-Thread',mainThreadTime,histograms);addCountHistogram('Total-Main-Thread',mainThreadCount,histograms);addDurationHistogram('V8-Only-Main-Thread',mainThreadV8Time,histograms);addCountHistogram('V8-Only-Main-Thread',mainThreadV8Count,histograms);}
 tr.metrics.MetricRegistry.register(runtimeStatsTotalMetric);return{runtimeStatsTotalMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){function v8AndMemoryMetrics(histograms,model){tr.metrics.v8.executionMetric(histograms,model);tr.metrics.v8.gcMetric(histograms,model);tr.metrics.sh.memoryMetric(histograms,model,{rangeOfInterest:tr.metrics.v8.utils.rangeForMemoryDumps(model)});}
-tr.metrics.MetricRegistry.register(v8AndMemoryMetrics);return{v8AndMemoryMetrics,};});'use strict';tr.exportTo('tr.metrics.vr',function(){const VR_GL_THREAD_NAME='VrShellGL';function createHistograms(histograms,name,options,hasCpuTime){const createdHistograms={wall:histograms.createHistogram(name+'_wall',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options)};if(hasCpuTime){createdHistograms.cpu=histograms.createHistogram(name+'_cpu',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options);}
+tr.metrics.MetricRegistry.register(v8AndMemoryMetrics);return{v8AndMemoryMetrics,};});'use strict';tr.exportTo('tr.metrics.v8',function(){function computeSyncInstantiationTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.SyncInstantiate'))return;const wasmSyncInstantiationTimeCPU=new tr.v.Histogram('v8:wasm:sync_instantiate:cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);wasmSyncInstantiationTimeCPU.description='cpu time spent instantiating a WebAssembly module';const wasmSyncInstantiationTimeWall=new tr.v.Histogram('v8:wasm:sync_instantiate:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);wasmSyncInstantiationTimeWall.description='wall time spent instantiating a WebAssembly module';for(const e of wasmEvents['wasm.SyncInstantiate']){wasmSyncInstantiationTimeCPU.addSample(e.cpuDuration);wasmSyncInstantiationTimeWall.addSample(e.duration);}
+histograms.addHistogram(wasmSyncInstantiationTimeCPU);histograms.addHistogram(wasmSyncInstantiationTimeWall);}
+function computeStreamingBaselineCompileTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.StartStreamingCompilation')||!wasmEvents.hasOwnProperty('wasm.BaselineFinished')){return;}
+const histogram=new tr.v.Histogram('v8:wasm:streaming_baseline_compilation:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);const compilationStart=wasmEvents['wasm.StartStreamingCompilation'][0].start;const compilationEnd=wasmEvents['wasm.BaselineFinished'][0].end;histogram.addSample(compilationEnd-compilationStart);histograms.addHistogram(histogram);}
+function computeCompilationTierupWallTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.BaselineFinished')||!wasmEvents.hasOwnProperty('wasm.TopTierFinished')){return;}
+const histogram=new tr.v.Histogram('v8:wasm:compilation_tierup:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);const tierupStart=wasmEvents['wasm.BaselineFinished'][0].start;const tierupEnd=wasmEvents['wasm.TopTierFinished'][0].end;histogram.addSample(tierupEnd-tierupStart);histograms.addHistogram(histogram);}
+function collectWasmEvents(model){const wasmEvents=tr.metrics.v8.utils.filterAndOrderEvents(model,event=>event.title.startsWith('wasm.'),event=>event.title);return wasmEvents;}
+function wasmMetric(histograms,model){const wasmEvents=collectWasmEvents(model);computeSyncInstantiationTimeMetric(histograms,wasmEvents);computeStreamingBaselineCompileTimeMetric(histograms,wasmEvents);computeCompilationTierupWallTimeMetric(histograms,wasmEvents);}
+tr.metrics.MetricRegistry.register(wasmMetric);return{wasmMetric,};});'use strict';tr.exportTo('tr.metrics.vr',function(){const VR_GL_THREAD_NAME='VrShellGL';function createHistograms(histograms,name,options,hasCpuTime){const createdHistograms={wall:histograms.createHistogram(name+'_wall',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options)};if(hasCpuTime){createdHistograms.cpu=histograms.createHistogram(name+'_cpu',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options);}
 return createdHistograms;}
 function frameCycleDurationMetric(histograms,model,opt_options){const histogramsByEventTitle=new Map();const expectationEvents=tr.importer.VR_EXPECTATION_EVENTS;for(const eventName in expectationEvents){const extraInfo=expectationEvents[eventName];histogramsByEventTitle.set(eventName,createHistograms(histograms,extraInfo.histogramName,{description:extraInfo.description},extraInfo.hasCpuTime));}
 histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateAnimationsAndOpacity',createHistograms(histograms,'update_animations_and_opacity',{description:'Duration to apply animation and opacity changes'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateBindings',createHistograms(histograms,'update_bindings',{description:'Duration to push binding values'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateLayout',createHistograms(histograms,'update_layout',{description:'Duration to compute element sizes, layout and textures'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateWorldSpaceTransform',createHistograms(histograms,'update_world_space_transforms',{description:'Duration to calculate element transforms in world space'},true));histogramsByEventTitle.set('UiRenderer::DrawUiView',createHistograms(histograms,'draw_ui',{description:'Duration to draw the UI'},true));histogramsByEventTitle.set('UiElementRenderer::DrawTexturedQuad',createHistograms(histograms,'draw_textured_quad',{description:'Duration to draw a textured element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientQuad',createHistograms(histograms,'draw_gradient_quad',{description:'Duration to draw a gradient element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientGridQuad',createHistograms(histograms,'draw_gradient_grid_quad',{description:'Duration to draw a gradient grid element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawController',createHistograms(histograms,'draw_controller',{description:'Duration to draw the controller'},true));histogramsByEventTitle.set('UiElementRenderer::DrawLaser',createHistograms(histograms,'draw_laser',{description:'Duration to draw the laser'},true));histogramsByEventTitle.set('UiElementRenderer::DrawReticle',createHistograms(histograms,'draw_reticle',{description:'Duration to draw the reticle'},true));histogramsByEventTitle.set('UiElementRenderer::DrawShadow',createHistograms(histograms,'draw_shadow',{description:'Duration to draw a shadow element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawStars',createHistograms(histograms,'draw_stars',{description:'Duration to draw the stars'},true));histogramsByEventTitle.set('UiElementRenderer::DrawBackground',createHistograms(histograms,'draw_background',{description:'Duration to draw the textured background'},true));histogramsByEventTitle.set('UiElementRenderer::DrawKeyboard',createHistograms(histograms,'draw_keyboard',{description:'Duration to draw the keyboard'},true));const drawUiSubSlicesMap=new Map();const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let rangeOfInterest=model.bounds;const userExpectationsOfInterest=[tr.model.um.AnimationExpectation];if(opt_options&&opt_options.rangeOfInterest){rangeOfInterest=opt_options.rangeOfInterest;userExpectationsOfInterest.push(tr.model.um.ResponseExpectation);}
@@ -9315,7 +9146,18 @@
 function getSmoothnessStats(driftTimes){const meanDriftTime=tr.b.math.Statistics.mean(driftTimes);const normDriftTimes=driftTimes.map(driftTime=>Math.abs(driftTime-meanDriftTime));const framesSeverelyOutOfSync=normDriftTimes.filter(driftTime=>driftTime>2*VSYNC_DURATION_US).length;const framesOutOfSync=normDriftTimes.filter(driftTime=>driftTime>VSYNC_DURATION_US).length;const percentBadlyOutOfSync=framesSeverelyOutOfSync/driftTimes.length;const percentOutOfSync=framesOutOfSync/driftTimes.length;const framesOutOfSyncOnlyOnce=framesOutOfSync-framesSeverelyOutOfSync;let smoothnessScore=1-(framesOutOfSyncOnlyOnce+
 SEVERITY*framesSeverelyOutOfSync)/driftTimes.length;if(smoothnessScore<0){smoothnessScore=0;}
 return{framesOutOfSync,framesSeverelyOutOfSync,percentBadlyOutOfSync,percentOutOfSync,smoothnessScore};}
-return{webrtcRenderingMetric,};});'use strict';Polymer({is:'tr-ui-a-alert-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},getRowsForSingleAlert_(alert){const rows=[];for(const argName in alert.args){const argView=document.createElement('tr-ui-a-generic-object-view');argView.object=alert.args[argName];rows.push({name:argName,value:argView});}
+return{webrtcRenderingMetric,};});'use strict';tr.exportTo('tr.metrics.webui',function(){function webuiMetric(histograms,model,opt_options){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper){return;}
+const WEBUI_TITLE_PREFIX='webui_metric:';const traces=new Map();const benchmarkValues=new Map();for(const helper of chromeHelper.browserHelpers){if(!helper.mainThread)continue;for(const slice of helper.mainThread.sliceGroup.slices.concat(helper.mainThread.asyncSliceGroup.slices)){if(!slice.error&&slice.title.startsWith(WEBUI_TITLE_PREFIX)){if(!traces.has(slice.title)){traces.set(slice.title,[]);}
+traces.get(slice.title).push(slice.duration);}}}
+const BENCHMARK_BEGIN='benchmark_begin';const BENCHMARK_END='benchmark_end';const BENCHMARK_VALUE='benchmark_value';const marks=new Map();for(const helper of Object.values(chromeHelper.rendererHelpers)){for(const event of helper.mainThread.sliceGroup.childEvents()){const navId=getNavigationId(event);if(!navId||!event.category.includes('blink.user_timing'))continue;const{title}=event;const index=title.lastIndexOf(':');if(index===-1){continue;}
+const name=title.substring(0,index);const lastPart=title.substring(index+1);if(lastPart===BENCHMARK_BEGIN){marks.set(name,event);}else if(lastPart===BENCHMARK_END){if(!marks.has(name)){continue;}
+const range=tr.b.math.Range.fromExplicitRange(marks.get(name).start,event.start);if(!traces.has(name)){traces.set(name,[]);}
+traces.get(name).push(range.duration);marks.delete(name);}else if(lastPart===BENCHMARK_VALUE){const index2=name.lastIndexOf(':');if(index2===-1){continue;}
+const key=name.substring(0,index2);const value=Number(name.substring(index2+1));if(key&&!isNaN(value)){if(!benchmarkValues.has(key)){benchmarkValues.set(key,[]);}
+benchmarkValues.get(key).push(value);}}}}
+traces.forEach((value,key)=>{histograms.createHistogram(key,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value);});benchmarkValues.forEach((value,key)=>{histograms.createHistogram(key,tr.b.Unit.byName.unitlessNumber_smallerIsBetter,value);});}
+function getNavigationId(event){return event.args.data&&event.args.data.navigationId;}
+tr.metrics.MetricRegistry.register(webuiMetric,{supportsRangeOfInterest:false,});return{webuiMetric,};});'use strict';Polymer({is:'tr-ui-a-alert-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},getRowsForSingleAlert_(alert){const rows=[];for(const argName in alert.args){const argView=document.createElement('tr-ui-a-generic-object-view');argView.object=alert.args[argName];rows.push({name:argName,value:argView});}
 if(alert.associatedEvents.length){alert.associatedEvents.forEach(function(event,i){const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(new tr.model.EventSet(event),event.title);let valueString='';if(event instanceof tr.model.TimedEvent){valueString='took '+event.duration.toFixed(2)+'ms';}
 rows.push({name:linkEl,value:valueString});});}
 const descriptionEl=tr.ui.b.createDiv({textContent:alert.info.description,maxWidth:'300px'});rows.push({name:'Description',value:descriptionEl});if(alert.info.docLinks){alert.info.docLinks.forEach(function(linkObject){const linkEl=document.createElement('a');linkEl.target='_blank';linkEl.href=linkObject.href;Polymer.dom(linkEl).textContent=Polymer.dom(linkObject).textContent;rows.push({name:linkObject.label,value:linkEl});});}
@@ -9968,7 +9810,8 @@
 for(let i=0;i<subGroupRows.length;i++){rowsWithHeadings.push({row:subGroupRows[i],heading:(i===0?subGroup.title:'')});}}
 this.setPrebuiltSubRows(this.group_,rowsWithHeadings);}};function stripSlice_(slice){if(slice.subSlices!==undefined&&slice.subSlices.length===1){const subSlice=slice.subSlices[0];if(tr.b.math.approximately(subSlice.start,slice.start,1)&&tr.b.math.approximately(subSlice.duration,slice.duration,1)){return subSlice;}}
 return slice;}
-function makeLevelSubRows_(slices){const rows=[];const putSlice=(slice,level)=>{while(rows.length<=level){rows.push([]);}
+function makeLevelSubRows_(slices){const rows=[];const putSlice=(slice,level)=>{if(slice.hidden){return;}
+while(rows.length<=level){rows.push([]);}
 rows[level].push(slice);};const putSliceRecursively=(slice,level)=>{putSlice(slice,level);if(slice.subSlices!==undefined){for(const subSlice of slice.subSlices){putSliceRecursively(subSlice,level+1);}}};for(const slice of slices){putSliceRecursively(stripSlice_(slice),0);}
 return rows;}
 function groupAsyncSlicesIntoSubRows(slices,opt_skipSort){if(!opt_skipSort){slices.sort((x,y)=>x.start-y.start);}
@@ -10111,9 +9954,9 @@
 for(const labelEl of unsupportedLabelEls){Polymer.dom(this.tabStrip_).appendChild(labelEl);}
 if(previouslyActivePanelType&&supportedPanelTypes.includes(previouslyActivePanelType)){this.activePanelType=previouslyActivePanelType;Polymer.dom(this).setAttribute('expanded',true);}else{if(this.activePanel){Polymer.dom(this.activePanelContainer_).removeChild(this.activePanel);}
 Polymer.dom(this).removeAttribute('expanded');}},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){if(range===undefined){throw new Error('Must not be undefined');}
-this.rangeOfInterest_=range;if(this.activePanel){this.activePanel.rangeOfInterest=range;}}});'use strict';Polymer({is:'tr-ui-timeline-view-help-overlay',ready(){const mod=tr.isMac?'cmd ':'ctrl';const spans=Polymer.dom(this.root).querySelectorAll('span.mod');for(let i=0;i<spans.length;i++){Polymer.dom(spans[i]).textContent=mod;}}});'use strict';Polymer({is:'tr-ui-timeline-view-metadata-overlay',created(){this.metadata_=undefined;},ready(){this.$.table.tableColumns=[{title:'name',value:d=>d.name,},{title:'value',value:d=>{const gov=document.createElement('tr-ui-a-generic-object-view');gov.object=d.value;return gov;},}];},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.table.tableRows=this.metadata_;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-v-ui-preferred-display-unit',ready(){this.preferredTimeDisplayMode_=undefined;},attached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},detached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},get preferredTimeDisplayMode(){return this.preferredTimeDisplayMode_;},set preferredTimeDisplayMode(v){if(this.preferredTimeDisplayMode_===v)return;this.preferredTimeDisplayMode_=v;tr.b.Unit.didPreferredTimeDisplayUnitChange();}});'use strict';const POLYFILL_WARNING_MESSAGE='Trace Viewer is running with WebComponentsV0 polyfill, and some '+'features may be broken. As a workaround, you may try running chrome '+'with "--enable-blink-features=ShadowDOMV0,CustomElementsV0,HTMLImports" '+'flag. See crbug.com/1036492.';Polymer({is:'tr-ui-timeline-view',created(){this.trackViewContainer_=undefined;this.queuedModel_=undefined;this.builtPromise_=undefined;this.doneBuilding_=undefined;},attached(){this.async(function(){this.trackViewContainer_=Polymer.dom(this).querySelector('#track_view_container');if(!this.trackViewContainer_){throw new Error('missing trackviewContainer');}
+this.rangeOfInterest_=range;if(this.activePanel){this.activePanel.rangeOfInterest=range;}}});'use strict';Polymer({is:'tr-ui-timeline-view-help-overlay',ready(){const mod=tr.isMac?'cmd ':'ctrl';const spans=Polymer.dom(this.root).querySelectorAll('span.mod');for(let i=0;i<spans.length;i++){Polymer.dom(spans[i]).textContent=mod;}}});'use strict';Polymer({is:'tr-ui-timeline-view-metadata-overlay',created(){this.metadata_=undefined;},ready(){this.$.table.tableColumns=[{title:'name',value:d=>d.name,},{title:'value',value:d=>{const gov=document.createElement('tr-ui-a-generic-object-view');gov.object=d.value;return gov;},}];},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.table.tableRows=this.metadata_;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-v-ui-preferred-display-unit',ready(){this.preferredTimeDisplayMode_=undefined;},attached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},detached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},get preferredTimeDisplayMode(){return this.preferredTimeDisplayMode_;},set preferredTimeDisplayMode(v){if(this.preferredTimeDisplayMode_===v)return;this.preferredTimeDisplayMode_=v;tr.b.Unit.didPreferredTimeDisplayUnitChange();}});'use strict';const POLYFILL_WARNING_MESSAGE='Trace Viewer is running with WebComponentsV0 polyfill, and some '+'features may be broken. See crbug.com/1036492.';Polymer({is:'tr-ui-timeline-view',created(){this.trackViewContainer_=undefined;this.queuedModel_=undefined;this.builtPromise_=undefined;this.doneBuilding_=undefined;},attached(){this.async(function(){this.trackViewContainer_=Polymer.dom(this).querySelector('#track_view_container');if(!this.trackViewContainer_){throw new Error('missing trackviewContainer');}
 if(this.queuedModel_)this.updateContents_();});},ready(){this.tabIndex=0;this.polyfillWarnedOnce_=false;this.titleEl_=this.$.title;this.leftControlsEl_=this.$.left_controls;this.rightControlsEl_=this.$.right_controls;this.collapsingControlsEl_=this.$.collapsing_controls;this.sidePanelContainer_=this.$.side_panel_container;this.brushingStateController_=new tr.c.BrushingStateController(this);this.findCtl_=this.$.view_find_control;this.findCtl_.controller=new tr.ui.FindController(this.brushingStateController_);this.scriptingCtl_=document.createElement('tr-ui-scripting-control');this.scriptingCtl_.controller=new tr.c.ScriptingController(this.brushingStateController_);this.sidePanelContainer_.brushingStateController=this.brushingStateController_;if(window.tr.metrics&&window.tr.metrics.sh&&window.tr.metrics.sh.SystemHealthMetric){this.railScoreSpan_=document.createElement('tr-metrics-ui-sh-system-health-span');Polymer.dom(this.rightControls).appendChild(this.railScoreSpan_);}else{this.railScoreSpan_=undefined;}
-this.flowEventFilter_=this.$.flow_event_filter_dropdown;this.processFilter_=this.$.process_filter_dropdown;this.optionsDropdown_=this.$.view_options_dropdown;this.selectedFlowEvents_=new Set();this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.ui.b.createCheckBox(this,'highlightVSync','tr.ui.TimelineView.highlightVSync',false,'Highlight VSync');Polymer.dom(this.optionsDropdown_).appendChild(this.highlightVSyncCheckbox_);this.initMetadataButton_();this.initConsoleButton_();this.initHelpButton_();Polymer.dom(this.collapsingControls).appendChild(this.scriptingCtl_);this.dragEl_=this.$.drag_handle;this.analysisEl_=this.$.analysis;this.analysisEl_.brushingStateController=this.brushingStateController_;this.addEventListener('requestSelectionChange',function(e){const sc=this.brushingStateController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);this.bindKeyListeners_();this.dragEl_.target=this.analysisEl_;},get globalMode(){return this.hotkeyController.globalMode;},set globalMode(globalMode){globalMode=!!globalMode;this.brushingStateController_.historyEnabled=globalMode;this.hotkeyController.globalMode=globalMode;},get hotkeyController(){return this.$.hkc;},warnPolyfill(){if(this.polyfillWarnedOnce_)return;console.warn(POLYFILL_WARNING_MESSAGE);this.polyfillWarnedOnce_=true;if(!window.__hideTraceViewerPolyfillWarning){const polyfillWarningsEl=Polymer.dom(this.root).querySelector('#polyfill-warning');polyfillWarningsEl.addMessage(POLYFILL_WARNING_MESSAGE,[{buttonText:'Hide',onClick:()=>polyfillWarningsEl.clearMessages()}]);}},updateDocumentFavicon(){let hue;if(!this.model){hue='blue';}else{hue=this.model.faviconHue;}
+this.flowEventFilter_=this.$.flow_event_filter_dropdown;this.processFilter_=this.$.process_filter_dropdown;this.optionsDropdown_=this.$.view_options_dropdown;this.selectedFlowEvents_=new Set();this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.ui.b.createCheckBox(this,'highlightVSync','tr.ui.TimelineView.highlightVSync',false,'Highlight VSync');Polymer.dom(this.optionsDropdown_).appendChild(this.highlightVSyncCheckbox_);this.initMetadataButton_();this.initConsoleButton_();this.initHelpButton_();Polymer.dom(this.collapsingControls).appendChild(this.scriptingCtl_);this.dragEl_=this.$.drag_handle;this.analysisEl_=this.$.analysis;this.analysisEl_.brushingStateController=this.brushingStateController_;this.addEventListener('requestSelectionChange',function(e){const sc=this.brushingStateController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);this.bindKeyListeners_();this.dragEl_.target=this.analysisEl_;},get globalMode(){return this.hotkeyController.globalMode;},set globalMode(globalMode){globalMode=!!globalMode;this.brushingStateController_.historyEnabled=globalMode;this.hotkeyController.globalMode=globalMode;},get hotkeyController(){return this.$.hkc;},warnPolyfill(){if(this.polyfillWarnedOnce_)return;console.warn(POLYFILL_WARNING_MESSAGE);this.polyfillWarnedOnce_=true;},updateDocumentFavicon(){let hue;if(!this.model){hue='blue';}else{hue=this.model.faviconHue;}
 let faviconData=tr.ui.b.FaviconsByHue[hue];if(faviconData===undefined){faviconData=tr.ui.b.FaviconsByHue.blue;}
 let link=Polymer.dom(document.head).querySelector('link[rel="shortcut icon"]');if(!link){link=document.createElement('link');link.rel='shortcut icon';Polymer.dom(document.head).appendChild(link);}
 link.href=faviconData;},get selectedFlowEvents(){return this.selectedFlowEvents_;},set selectedFlowEvents(selectedFlowEvents){this.selectedFlowEvents_=selectedFlowEvents;},get highlightVSync(){return this.highlightVSync_;},set highlightVSync(highlightVSync){this.highlightVSync_=highlightVSync;if(!this.trackView_)return;this.trackView_.viewport.highlightVSync=highlightVSync;},initHelpButton_(){const helpButtonEl=this.$.view_help_button;const dlg=new tr.ui.b.Overlay();dlg.title='Chrome Tracing Help';dlg.visible=false;dlg.appendChild(document.createElement('tr-ui-timeline-view-help-overlay'));function onClick(e){dlg.visible=!dlg.visible;e.stopPropagation();}
@@ -10192,7 +10035,8 @@
 if(config){return{excluded:config.excluded_categories||[],included:config.included_categories||[],};}}}
 function validateTraceCategories(requiredCategories,categories){if(!requiredCategories)return;if(!categories)throw new Error('Missing trace config metadata');for(const cat of requiredCategories){const isDisabledByDefault=(cat.indexOf('disabled-by-default')===0);let missing=false;if(isDisabledByDefault){if(!categories.included.includes(cat)){missing=true;}}else if(categories.excluded.includes(cat)){missing=true;}
 if(missing){throw new Error(`Trace is missing required category "${cat}"`);}}}
-function validateDiagnosticNames(histograms){for(const hist of histograms){for(const name of hist.diagnostics.keys()){if(tr.v.d.RESERVED_NAMES_SET.has(name)){throw new Error(`Illegal diagnostic name "${name}" on Histogram "${hist.name}"`);}}}}
+function validateDiagnosticNames(histograms){for(const hist of histograms){for(const name of hist.diagnostics.keys()){if(name===tr.v.d.RESERVED_NAMES.ALERT_GROUPING){continue;}
+if(tr.v.d.RESERVED_NAMES_SET.has(name)){throw new Error(`Illegal diagnostic name "${name}" on Histogram "${hist.name}"`);}}}}
 function addTelemetryInfo(histograms,model){for(const metadata of model.metadata){if(!metadata.value||!metadata.value.telemetry)continue;for(const[name,value]of Object.entries(metadata.value.telemetry)){const type=tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);if(type===undefined){throw new Error(`Unexpected telemetry.${name}`);}
 histograms.addSharedDiagnosticToAllHistograms(name,new type(value));}}}
 function metricMapFunction(result,model,options){const histograms=runMetrics(model,options,result.addFailure.bind(result));addTelemetryInfo(histograms,model);if(model.canonicalUrl!==undefined){const info=tr.v.d.RESERVED_INFOS.TRACE_URLS;histograms.addSharedDiagnosticToAllHistograms(info.name,new info.type([model.canonicalUrl]));}
@@ -10291,7 +10135,7 @@
 if(names.includes(this.viewState.displayStatisticName)){this.displayStatisticName=this.viewState.displayStatisticName;this.$.statistic.value=this.displayStatisticName;}else{this.viewState.displayStatisticName=names[0]||'';}},get anyOverviewCharts_(){for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){if(row.isOverviewed)return true;}
 return false;},async toggleOverviewLineCharts_(){const showOverviews=!this.anyOverviewCharts_;const mark=tr.b.Timing.mark('histogram-set-controls',(showOverviews?'show':'hide')+'OverviewCharts');for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){await row.update({isOverviewed:showOverviews});}
 this.$.hide_overview.style.display=showOverviews?'inline':'none';this.$.show_overview.style.display=showOverviews?'none':'inline';await tr.b.animationFrame();mark.end();},set helpHref(href){this.$.help.href=href;this.$.help.style.display='inline';},set feedbackHref(href){this.$.feedback.href=href;this.$.feedback.style.display='inline';},clearSearch_(){this.set('searchQuery','');this.$.search.focus();},getAlphaString_(alphaIndex){return(''+ALPHA_OPTIONS[alphaIndex]).substr(0,5);},openAlphaSlider_(){const alphaButtonRect=this.$.alpha.getBoundingClientRect();this.$.alpha_slider_container.style.display='flex';this.$.alpha_slider_container.style.top=alphaButtonRect.bottom+'px';this.$.alpha_slider_container.style.left=alphaButtonRect.left+'px';this.$.alpha_slider.focus();},closeAlphaSlider_(){this.$.alpha_slider_container.style.display='';},updateAlpha_(){this.alphaIndex=this.$.alpha_slider.value;},getAlphaIndexFromViewState_(){for(let i=0;i<ALPHA_OPTIONS.length;++i){if(ALPHA_OPTIONS[i]>=this.viewState.alpha)return i;}
-return ALPHA_OPTIONS.length-1;},set enableVisualization(enable){this.$.show_visualization.style.display=enable?'inline':'none';},loadVisualization_(){tr.b.dispatchSimpleEvent(this,'loadVisualization',true,true,{});},});return{};});'use strict';tr.exportTo('tr.v',function(){class HistogramSetHierarchy{constructor(name){this.name=name;this.description='';this.depth=0;this.subRows=[];this.columns=new Map();}*walk(){yield this;for(const row of this.subRows)yield*row.walk();}
+return ALPHA_OPTIONS.length-1;},});return{};});'use strict';tr.exportTo('tr.v',function(){class HistogramSetHierarchy{constructor(name){this.name=name;this.description='';this.depth=0;this.subRows=[];this.columns=new Map();}*walk(){yield this;for(const row of this.subRows)yield*row.walk();}
 static*walkAll(rootRows){for(const rootRow of rootRows)yield*rootRow.walk();}
 static build(histogramArrayMap){const rootRows=[];HistogramSetHierarchy.buildInternal_(histogramArrayMap,[],rootRows);const histograms=new tr.v.HistogramSet();for(const row of HistogramSetHierarchy.walkAll(rootRows)){for(const hist of row.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;histograms.addHistogram(hist);}}
 histograms.deduplicateDiagnostics();for(const row of HistogramSetHierarchy.walkAll(rootRows)){row.maybeRebin_();}
@@ -10387,48 +10231,11 @@
 return;}
 await this.updateContents_();},onSortColumnChanged_(event){tr.b.Timing.instant('histogram-set-table','sortColumn');this.viewState.update({sortColumnIndex:event.sortColumnIndex,sortDescending:event.sortDescending,});},onRequestSelectionChange_(event){if(event.selection instanceof tr.model.EventSet)return;event.stopPropagation();tr.b.Timing.instant('histogram-set-table','selectHistogramNames');let histogramNames=event.selection;histogramNames.sort();histogramNames=histogramNames.map(escapeRegExp).join('|');this.viewState.update({showAll:true,searchQuery:`^(${histogramNames})$`,});},get leafHistograms(){const histograms=new tr.v.HistogramSet();for(const row of
 tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows)){if(row.subRows.length)continue;for(const hist of row.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;histograms.addHistogram(hist);}}
-return histograms;}});return{MIDLINE_HORIZONTAL_ELLIPSIS,};});'use strict';tr.exportTo('tr.v.ui',function(){const PAGE_BREAKDOWN_KEY='pageBreakdown';Polymer({is:'tr-v-ui-metrics-visualization',created(){this.charts_=new Map();},ready(){this.$.start.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_();});this.$.end.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_();});this.$.search_page.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_();});},build(chartData){this.title_=chartData.title;this.aggregateData_=chartData.aggregate;this.data_=chartData.page;this.submetricsData_=chartData.submetrics;this.benchmarkCount_=chartData.aggregate.length;const aggregateChart=this.initializeColumnChart(this.title_);Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);this.charts_.set(tr.v.ui.AGGREGATE_KEY,aggregateChart);this.setChartColors_(tr.v.ui.AGGREGATE_KEY);aggregateChart.data=chartData.aggregate;this.setChartSize_(tr.v.ui.AGGREGATE_KEY);const newChart=this.initializeColumnChart(this.title_+' Breakdown');newChart.enableToolTip=true;newChart.toolTipCallBack=(rect)=>this.openChildChart_(rect);Polymer.dom(this.$.pageByPageContainer).appendChild(newChart);this.charts_.set(PAGE_BREAKDOWN_KEY,newChart);this.setChartColors_(PAGE_BREAKDOWN_KEY);newChart.data=this.data_;this.setChartSize_(PAGE_BREAKDOWN_KEY);},setChartSize_(page){const chart=this.charts_.get(page);const pageCount=chart.data.length;chart.graphHeight=tr.b.math.clamp(pageCount*20,400,600);chart.graphWidth=tr.b.math.clamp(pageCount*30,200,1000);},setChartColors_(page){const chart=this.charts_.get(page);const metrics=tr.v.ui.METRICS.get(this.title_);for(let i=0;i<this.benchmarkCount_;++i){for(let j=0;j<metrics.length;++j){const mainColorIndex=j%tr.v.ui.COLORS.length;const subColorIndex=i%tr.v.ui.COLORS[mainColorIndex].length;const color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];const series=metrics[j]+'-'+this.aggregateData_[i].x;chart.getDataSeries(series).color=color;if(i===0){chart.getDataSeries(series).title=metrics[j];}else{chart.getDataSeries(series).title='';}}}},initializeColumnChart(title){const newChart=new tr.ui.b.NameColumnChart();newChart.hideLegend=false;newChart.isStacked=true;newChart.yAxisLabel='ms';newChart.hideXAxis=true;newChart.displayXInHover=true;newChart.isGrouped=true;newChart.showTitleInLegend=true;newChart.chartTitle=title;newChart.titleHeight='14pt';return newChart;},initializeChildChart_(title,height,width){const div=document.createElement('div');div.classList.add('container');Polymer.dom(this.$.submetricsContainer).insertBefore(div,this.$.submetricsContainer.firstChild);const childChart=new tr.ui.b.NameBarChart();childChart.xAxisLabel='ms';childChart.chartTitle=title;childChart.graphHeight=height;childChart.graphWidth=width;childChart.titleHeight='14pt';childChart.isStacked=true;childChart.hideLegend=true;childChart.isGrouped=true;childChart.isWaterfall=true;div.appendChild(childChart);const button=this.initializeCloseButton_(div,this.$.submetricsContainer);div.appendChild(button);return childChart;},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},openChildChart_(rect){const metrics=tr.v.ui.METRICS.get(this.title_);let metric;let metricIndex;for(let i=0;i<metrics.length;++i){if(rect.key.startsWith(metrics[i])){metric=metrics[i];metricIndex=i;break;}}
-const page=rect.datum.group;const title=this.title_+' '+metric+': '+page;const submetrics=this.submetricsData_.get(page).get(metric);const width=tr.b.math.clamp(submetrics.size*150,300,700);const height=tr.b.math.clamp(submetrics.size*this.benchmarkCount_*50,300,700);const childChart=this.initializeChildChart_(title,height,width);childChart.data=this.processSubmetrics_(childChart,submetrics,0,metricIndex).data;},processSubmetrics_(chart,submetrics,hideValue,metricIndex){const finalData=[];let submetricIndex=0;for(const submetric of submetrics.values()){let benchmarkIndex=0;for(const benchmark of submetric.values()){benchmark.hide=!hideValue?0:hideValue;const series=benchmark.x+'-'+benchmark.group;const mainColorIndex=metricIndex%tr.v.ui.COLORS.length;const subColorIndex=benchmarkIndex%tr.v.ui.COLORS[mainColorIndex].length;chart.getDataSeries(series).color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];if(benchmarkIndex===(this.benchmarkCount_-1)){hideValue+=benchmark[series];}
-finalData.push(benchmark);benchmarkIndex++;}
-submetricIndex++;}
-return{data:finalData,hide:hideValue};},filterByPercentile_(){const startPercentile=this.$.start.value;const endPercentile=this.$.end.value;if(startPercentile===''||endPercentile==='')return;const length=this.data_.length/(this.benchmarkCount_+1);const startIndex=this.getPercentileIndex_(startPercentile,length);const endIndex=this.getPercentileIndex_(endPercentile,length);this.charts_.get(PAGE_BREAKDOWN_KEY).data=this.data_.slice(startIndex,endIndex);},getPercentileIndex_(percentile,arrayLength){const index=Math.ceil(arrayLength*(percentile/100.0));if(index===-1)return 0;if(index>=arrayLength)return arrayLength;return index*this.benchmarkCount_;},searchByPage_(){const criteria=this.$.search_page.value;if(criteria==='')return;const query=new RegExp(criteria);const filteredData=[...this.data_].filter(group=>{if(group.group)return group.group.match(query);return false;});if(filteredData.length<1){this.$.search_error.style.display='block';return;}
-const page=filteredData[0].group;const title=this.title_+' Breakdown: '+page;const metricToSubmetricMap=this.submetricsData_.get(page);let totalSubmetrics=0;for(const submetrics of metricToSubmetricMap.values()){for(const benchmark of submetrics.values()){totalSubmetrics+=benchmark.length;}}
-const width=tr.b.math.clamp(totalSubmetrics*150,300,700);const height=tr.b.math.clamp(totalSubmetrics*this.benchmarkCount_*30,300,700);const childChart=this.initializeChildChart_(title,height,width);const childData=[];let hide=0;let metricIndex=0;for(const submetrics of metricToSubmetricMap.values()){const submetricsData=this.processSubmetrics_(childChart,submetrics,hide,metricIndex);childData.push(...submetricsData.data);hide=submetricsData.hide;metricIndex++;}
-childChart.data=childData;},});});'use strict';Polymer({is:'tr-v-ui-raster-visualization',ready(){this.$.pageSelector.addEventListener('click',()=>{this.selectPage_();});this.$.search_page.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_();});this.$.search_button.addEventListener('click',()=>{this.searchByPage_();});},build(chartData){this.data_=chartData;const aggregateChart=this.createChart_('Aggregate Data by Run');Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);aggregateChart.enableToolTip=true;aggregateChart.toolTipCallBack=(rect)=>this.openBenchmarkChart_(rect);this.setChartColors_(aggregateChart,this.data_.get(tr.v.ui.AGGREGATE_KEY));aggregateChart.data=this.data_.get(tr.v.ui.AGGREGATE_KEY);this.setChartSize_(aggregateChart,this.data_.get(tr.v.ui.AGGREGATE_KEY).length);for(const page of this.data_.keys()){if(page===tr.v.ui.AGGREGATE_KEY)continue;const option=document.createElement('option');option.textContent=page;option.value=page;this.$.pageSelector.appendChild(option);}},setChartSize_(chart,pageCount,dataLength){chart.graphHeight=tr.b.math.clamp(pageCount*25,175,1000);chart.graphWidth=tr.b.math.clamp(pageCount*25,500,1000);},setChartColors_(chart,data){const metrics=new Map();let count=0;for(const thread of tr.v.ui.FRAME.values()){for(const metric of thread.keys()){metrics.set(metric,count);count++;}}
-for(let i=0;i<Math.floor(data.length/tr.v.ui.FRAME.length);++i){let j=0;for(const[threadName,thread]of tr.v.ui.FRAME.entries()){for(const metric of thread.keys()){let color='transparent';if(thread.get(metric)){const mainColorIndex=metrics.get(metric)%tr.v.ui.COLORS.length;const subColorIndex=i%tr.v.ui.COLORS[mainColorIndex].length;color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];}
-const series=metric+'-'+data[i*2+j].x+'-'+threadName;chart.getDataSeries(series).color=color;chart.getDataSeries(series).title=!i?metric:'';}
-j++;}}},createChart_(title){const newChart=new tr.ui.b.NameBarChart();newChart.chartTitle=title;newChart.xAxisLabel='ms';newChart.hideLegend=false;newChart.showTitleInLegend=true;newChart.hideYAxis=true;newChart.isStacked=true;newChart.displayXInHover=true;newChart.isGrouped=true;return newChart;},openBenchmarkChart_(rect){const benchmarkIndex=Math.floor(rect.index/tr.v.ui.FRAME.length);const title=rect.datum.x;const div=document.createElement('div');Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const chart=this.createChart_(title);div.appendChild(chart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const newDataSet=[];for(const page of this.data_.keys()){if(page===tr.v.ui.AGGREGATE_KEY)continue;for(let i=0;i<tr.v.ui.FRAME.length;i++){newDataSet.push(this.data_.get(page)[benchmarkIndex*tr.v.ui.FRAME.length+i]);}}
-this.setChartColors_(chart,newDataSet);chart.data=newDataSet;this.setChartSize_(chart,newDataSet.length);},selectPage_(){const div=document.createElement('div');const page=this.$.pageSelector.value;if(page==='')return;Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const pageChart=this.createChart_(page);div.appendChild(pageChart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const pageData=this.data_.get(page);this.setChartColors_(pageChart,pageData);pageChart.data=pageData;this.setChartSize_(pageChart,pageData.length);},searchByPage_(){const criteria=this.$.search_page.value;if(criteria==='')return;const query=new RegExp(criteria);const filteredData=[...this.data_.keys()].filter(page=>page.match(query));if(filteredData.length<1){this.$.search_error.style.display='block';return;}
-const page=filteredData[0];const div=document.createElement('div');Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const pageChart=this.createChart_(page);div.appendChild(pageChart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const pageData=this.data_.get(page);this.setChartColors_(pageChart,pageData);pageChart.data=pageData;this.setChartSize_(pageChart,pageData.length);},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},});'use strict';tr.exportTo('tr.v.ui',function(){const STATISTICS_KEY='statistics';const SUBMETRICS_KEY='submetrics';const AGGREGATE_KEY='aggregate';const RASTER_START_METRIC_KEY='pipeline:begin_frame_to_raster_start';const COLORS=[['#FFD740','#FFC400','#FFAB00','#E29800'],['#FF6E40','#FF3D00','#DD2C00','#A32000'],['#40C4FF','#00B0FF','#0091EA','#006DAF'],['#89C641','#54B503','#4AA510','#377A0D'],['#B388FF','#7C4DFF','#651FFF','#6200EA'],['#FF80AB','#FF4081','#F50057','#C51162'],['#FFAB40','#FF9100','#FF6D00','#D65C02'],['#8C9EFF','#536DFE','#3D5AFE','#304FFE']];const FRAME=[new Map([['pipeline:begin_frame_to_raster_start',false],['pipeline:begin_frame_to_raster_end',true]]),new Map([['pipeline:begin_frame_transport',true],['pipeline:begin_frame_to_frame_submission',true],['pipeline:frame_submission_to_display',true],['pipeline:draw',true]])];const METRICS=new Map([['Pipeline',['pipeline:begin_frame_transport','pipeline:begin_frame_to_frame_submission','pipeline:frame_submission_to_display','pipeline:draw']],['Thread',['thread_browser_cpu_time_per_frame','thread_display_compositor_cpu_time_per_frame','thread_GPU_cpu_time_per_frame','thread_IO_cpu_time_per_frame','thread_other_cpu_time_per_frame','thread_raster_cpu_time_per_frame','thread_renderer_compositor_cpu_time_per_frame','thread_renderer_main_cpu_time_per_frame']]]);function getValueFromMap(key,map){let retrievedValue=map.get(key);if(!retrievedValue){retrievedValue=new Map();map.set(key,retrievedValue);}
-return retrievedValue;}
-Polymer({is:'tr-v-ui-visualizations-data-container',created(){this.orderedBenchmarks_=[];this.groupedData_=new Map();},build(leafHistograms,histograms){if(!leafHistograms||leafHistograms.length<1||!histograms||histograms.length<1){this.$.data_error.style.display='block';return;}
-this.processHistograms_(this.groupHistograms_(histograms),this.groupHistograms_(leafHistograms));this.buildCharts_();},processHistograms_(histograms,leafHistograms){const benchmarkStartGrouping=tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START);const benchmarkToStartTime=new Map();for(const[metric,benchmarks]of histograms.entries()){for(const[benchmark,pages]of leafHistograms.get(metric).entries()){for(const[page,histograms]of pages.entries()){for(const histogram of histograms){const aggregateToBenchmarkMap=getValueFromMap(AGGREGATE_KEY,this.groupedData_);const benchmarkToMetricMap=getValueFromMap(benchmark,aggregateToBenchmarkMap);benchmarkToMetricMap.set(metric,new Map([[STATISTICS_KEY,histogram.running]]));}}}
-for(const[benchmark,pages]of benchmarks.entries()){for(const[page,histograms]of pages.entries()){for(const histogram of histograms){if(!benchmarkToStartTime.get(benchmark)){benchmarkToStartTime.set(benchmark,benchmarkStartGrouping.callback(histogram));}
-const pageToBenchmarkMap=getValueFromMap(page,this.groupedData_);const benchmarkToMetricMap=getValueFromMap(benchmark,pageToBenchmarkMap);const mergedSubmetrics=new tr.v.d.DiagnosticMap();for(const bin of histogram.allBins){for(const map of bin.diagnosticMaps){mergedSubmetrics.addDiagnostics(map);}}
-if(benchmarkToMetricMap.get(metric))continue;benchmarkToMetricMap.set(metric,new Map([[STATISTICS_KEY,histogram.running],[SUBMETRICS_KEY,mergedSubmetrics.get('breakdown')]]));}}}}
-this.orderedBenchmarks_=this.sortBenchmarks_(benchmarkToStartTime);},groupHistograms_(histograms){const groupings=[tr.v.HistogramGrouping.HISTOGRAM_NAME,tr.v.HistogramGrouping.DISPLAY_LABEL,tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES)];return histograms.groupHistogramsRecursively(groupings);},sortBenchmarks_(benchmarks){return Array.from(benchmarks.keys()).sort((a,b)=>{Date.parse(benchmarks.get(a))-Date.parse(benchmarks.get(b));});},getSeriesKey_(metric,benchmark){return metric+'-'+benchmark;},buildCharts_(){const rasterDataToBePassed=this.buildRasterChart_();this.$.rasterVisualization.build(rasterDataToBePassed);for(const chartName of METRICS.keys()){const metricsDataToBePassed=this.buildMetricsData_(chartName);const newChart=this.$.metricsVisualization.cloneNode(true);newChart.style.display='block';Polymer.dom(this.$.metrics_container).appendChild(newChart);newChart.build(metricsDataToBePassed);}},buildRasterChart_(){const orderedPages=[...this.groupedData_.keys()].filter((page)=>this.filterPagesWithoutRasterMetric_(page)).sort((a,b)=>this.sortByRasterStart_(a,b));const allChartData=new Map();for(const page of orderedPages){const pageMap=this.groupedData_.get(page);let chartData=[];for(const benchmark of this.orderedBenchmarks_){if(!pageMap.has(benchmark))continue;const benchmarkMap=pageMap.get(benchmark);const benchmarkData=[];if(benchmarkMap.get(RASTER_START_METRIC_KEY)===undefined){continue;}
-for(const[threadName,thread]of FRAME.entries()){const data={x:benchmark,hide:0};if(page!==AGGREGATE_KEY)data.group=page;let rasterBegin=0;for(const metric of thread.keys()){const metricMap=benchmarkMap.get(metric);const key=this.getSeriesKey_(metric,data.x+'-'+threadName);const stats=metricMap.get(STATISTICS_KEY);const mean=stats?stats.mean:0;let roundedMean=Math.round(mean*100)/100;if(metric===RASTER_START_METRIC_KEY){rasterBegin=roundedMean;}else if(metric==='pipeline:begin_frame_to_raster_end'){roundedMean-=rasterBegin;}
-data[key]=roundedMean;}
-benchmarkData.push(data);}
-chartData=chartData.concat(benchmarkData);}
-allChartData.set(page,chartData);}
-return allChartData;},buildMetricsData_(chartName){const orderedPages=[...this.groupedData_.keys()].sort((a,b)=>this.sortByTotal_(a,b,chartName));const chartData=[];const aggregateChart=[];for(const page of orderedPages){const pageMap=this.groupedData_.get(page);for(const benchmark of this.orderedBenchmarks_){if(!pageMap.has(benchmark))continue;const data={x:benchmark,group:page};const benchmarkMap=pageMap.get(benchmark);for(const metric of METRICS.get(chartName)){const metricMap=benchmarkMap.get(metric);const key=this.getSeriesKey_(metric,benchmark);const stats=metricMap.get(STATISTICS_KEY);const mean=stats?stats.mean:0;data[key]=Math.round(mean*100)/100;}
-if(page===AGGREGATE_KEY){aggregateChart.push(data);}else{chartData.push(data);}}
-chartData.push({});}
-chartData.shift();return{title:chartName,aggregate:aggregateChart,page:chartData,submetrics:this.processSubmetricsData_(chartName)};},submetricsHelper_(submetric,value,benchmark,metricToSubmetricMap){let submetricToBenchmarkMap=metricToSubmetricMap.get(submetric);if(!submetricToBenchmarkMap){submetricToBenchmarkMap=[];metricToSubmetricMap.set(submetric,submetricToBenchmarkMap);}
-const data={x:submetric,hide:0,group:benchmark};const mean=value;const roundedMean=Math.round(mean*100)/100;if(!roundedMean)return;data[this.getSeriesKey_(submetric,benchmark)]=roundedMean;submetricToBenchmarkMap.push(data);},processSubmetricsData_(chartName){const submetrics=new Map();for(const[page,pageMap]of this.groupedData_.entries()){if(page===AGGREGATE_KEY)continue;const pageToMetricMap=getValueFromMap(page,submetrics);for(const benchmark of this.orderedBenchmarks_){const benchmarkMap=pageMap.get(benchmark);if(!benchmarkMap)continue;for(const metric of METRICS.get(chartName)){const metricMap=benchmarkMap.get(metric);const metricToSubmetricMap=getValueFromMap(metric,pageToMetricMap);const submetrics=metricMap.get(SUBMETRICS_KEY);if(!submetrics){this.submetricsHelper_(metric,metricMap.get(STATISTICS_KEY),benchmark,metricToSubmetricMap);continue;}
-for(const[submetric,value]of[...submetrics]){this.submetricsHelper_(submetric,value,benchmark,metricToSubmetricMap);}}}}
-return submetrics;},sortByTotal_(a,b,chartName){if(a===AGGREGATE_KEY)return-1;if(b===AGGREGATE_KEY)return 1;let aValue=0;const aMap=this.groupedData_.get(a);if(aMap.get(this.orderedBenchmarks_[0])!==undefined){for(const metric of METRICS.get(chartName)){const aMetricMap=aMap.get(this.orderedBenchmarks_[0]).get(metric);const aStats=aMetricMap.get(STATISTICS_KEY);aValue+=aStats?aStats.mean:0;}}
-let bValue=0;const bMap=this.groupedData_.get(b);if(bMap.get(this.orderedBenchmarks_[0])!==undefined){for(const metric of METRICS.get(chartName)){const bMetricMap=bMap.get(this.orderedBenchmarks_[0]).get(metric);const bStats=bMetricMap.get(STATISTICS_KEY);bValue+=bStats?bStats.mean:0;}}
-return aValue-bValue;},filterPagesWithoutRasterMetric_(page){const pageMap=this.groupedData_.get(page);for(const benchmark of this.orderedBenchmarks_){const pageMetricMap=pageMap.get(benchmark);if(!pageMetricMap)continue;const wantedMetric=pageMetricMap.get(RASTER_START_METRIC_KEY);if(wantedMetric!==undefined)return true;}
-return false;},sortByRasterStart_(a,b){if(a===AGGREGATE_KEY)return 1;if(b===AGGREGATE_KEY)return-1;let aValue=0;const aMap=this.groupedData_.get(a);if(aMap.get(this.orderedBenchmarks_[0])!==undefined){const aMetricMap=aMap.get(this.orderedBenchmarks_[0]).get(RASTER_START_METRIC_KEY);const aStats=aMetricMap.get(STATISTICS_KEY);aValue=aStats?aStats.mean:0;}
-let bValue=0;const bMap=this.groupedData_.get(b);if(bMap.get(this.orderedBenchmarks_[0])!==undefined){const bMetricMap=bMap.get(this.orderedBenchmarks_[0]).get(RASTER_START_METRIC_KEY);const bStats=bMetricMap.get(STATISTICS_KEY);bValue=bStats?bStats.mean:0;}
-return bValue-aValue;},});return{STATISTICS_KEY,SUBMETRICS_KEY,AGGREGATE_KEY,COLORS,FRAME,METRICS,getValueFromMap,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-view',listeners:{export:'onExport_',loadVisualization:'onLoadVisualization_'},created(){this.brushingStateController_=new tr.ui.NullBrushingStateController();this.viewState_=new tr.v.ui.HistogramSetViewState();this.visualizationLoaded_=false;},ready(){this.$.table.viewState=this.viewState;this.$.controls.viewState=this.viewState;},attached(){this.brushingStateController.parentController=tr.c.BrushingStateController.getControllerForElement(this.parentNode);},get brushingStateController(){return this.brushingStateController_;},get viewState(){return this.viewState_;},get histograms(){return this.$.table.histograms;},async build(histograms,opt_options){const options=opt_options||{};const progress=options.progress||(()=>Promise.resolve());if(options.helpHref)this.$.controls.helpHref=options.helpHref;if(options.feedbackHref){this.$.controls.feedbackHref=options.feedbackHref;}
+return histograms;}});return{MIDLINE_HORIZONTAL_ELLIPSIS,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-view',listeners:{export:'onExport_',},created(){this.brushingStateController_=new tr.ui.NullBrushingStateController();this.viewState_=new tr.v.ui.HistogramSetViewState();},ready(){this.$.table.viewState=this.viewState;this.$.controls.viewState=this.viewState;},attached(){this.brushingStateController.parentController=tr.c.BrushingStateController.getControllerForElement(this.parentNode);},get brushingStateController(){return this.brushingStateController_;},get viewState(){return this.viewState_;},get histograms(){return this.$.table.histograms;},async build(histograms,opt_options){const options=opt_options||{};const progress=options.progress||(()=>Promise.resolve());if(options.helpHref)this.$.controls.helpHref=options.helpHref;if(options.feedbackHref){this.$.controls.feedbackHref=options.feedbackHref;}
 if(histograms===undefined||histograms.length===0){this.$.container.style.display='none';this.$.zero.style.display='block';this.style.display='block';return;}
-this.$.zero.style.display='none';this.$.container.style.display='block';this.$.container.style.maxHeight=(window.innerHeight-16)+'px';const buildMark=tr.b.Timing.mark('histogram-set-view','build');await progress('Finding important Histograms...');const sourceHistogramsMark=tr.b.Timing.mark('histogram-set-view','sourceHistograms');const sourceHistograms=histograms.sourceHistograms;sourceHistogramsMark.end();this.$.controls.showAllEnabled=(sourceHistograms.length!==histograms.length);await progress('Collecting parameters...');const collectParametersMark=tr.b.Timing.mark('histogram-set-view','collectParameters');const parameterCollector=new tr.v.HistogramParameterCollector();parameterCollector.process(histograms);this.$.controls.baseStatisticNames=parameterCollector.statisticNames;this.$.controls.possibleGroupings=parameterCollector.possibleGroupings;const displayLabels=parameterCollector.labels;this.$.controls.displayLabels=displayLabels;collectParametersMark.end();const hist=[...histograms][0];const benchmarks=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARKS);let enable=false;if(benchmarks!==undefined&&benchmarks.length>0){for(const benchmark of benchmarks){if(benchmark.includes('rendering')){enable=true;break;}}}
-this.$.controls.enableVisualization=enable;await this.$.table.build(histograms,sourceHistograms,displayLabels,progress);buildMark.end();},onExport_(event){const mark=tr.b.Timing.mark('histogram-set-view','export'+
+this.$.zero.style.display='none';this.$.container.style.display='block';this.$.container.style.maxHeight=(window.innerHeight-16)+'px';const buildMark=tr.b.Timing.mark('histogram-set-view','build');await progress('Finding important Histograms...');const sourceHistogramsMark=tr.b.Timing.mark('histogram-set-view','sourceHistograms');const sourceHistograms=histograms.sourceHistograms;sourceHistogramsMark.end();this.$.controls.showAllEnabled=(sourceHistograms.length!==histograms.length);await progress('Collecting parameters...');const collectParametersMark=tr.b.Timing.mark('histogram-set-view','collectParameters');const parameterCollector=new tr.v.HistogramParameterCollector();parameterCollector.process(histograms);this.$.controls.baseStatisticNames=parameterCollector.statisticNames;this.$.controls.possibleGroupings=parameterCollector.possibleGroupings;const displayLabels=parameterCollector.labels;this.$.controls.displayLabels=displayLabels;collectParametersMark.end();await this.$.table.build(histograms,sourceHistograms,displayLabels,progress);buildMark.end();},onExport_(event){const mark=tr.b.Timing.mark('histogram-set-view','export'+
 (event.merged?'Merged':'Raw')+event.format.toUpperCase());const histograms=event.merged?this.$.table.leafHistograms:this.histograms;let blob;if(event.format==='csv'){const csv=new tr.v.CSVBuilder(histograms);csv.build();blob=new window.Blob([csv.toString()],{type:'text/csv'});}else if(event.format==='json'){blob=new window.Blob([JSON.stringify(histograms.asDicts())],{type:'text/json'});}else{throw new Error(`Unable to export format "${event.format}"`);}
-const path=window.location.pathname.split('/');const basename=path[path.length-1].split('.')[0]||'histograms';const anchor=document.createElement('a');anchor.download=`${basename}.${event.format}`;anchor.href=window.URL.createObjectURL(blob);anchor.click();mark.end();},onLoadVisualization_(event){if(!this.visualizationLoaded_){this.$.visualizations.style.display='block';this.$.visualizations.build(this.$.table.leafHistograms,this.histograms);this.visualizationLoaded_=true;}else if(this.$.visualizations.style.display==='none'){this.$.visualizations.style.display='block';}else{this.$.visualizations.style.display='none';}},});return{};});'use strict';tr.exportTo('tr.ui',function(){Polymer({is:'tr-ui-sp-metrics-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.rangeOfInterest_=undefined;this.metricLatenciesMs_=[];this.metrics_=[];tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(function(m){if(m.constructor.name==='sampleMetric')return;this.metrics_.push({label:m.constructor.name,value:m.constructor.name});},this);this.metrics_.sort((x,y)=>x.label.localeCompare(y.label));this.settingsKey_='metrics-side-panel-metric-name';this.currentMetricName_='responsivenessMetric';const metricSelector=tr.ui.b.createSelector(this,'currentMetricName_',this.settingsKey_,this.currentMetricName_,this.metrics_);Polymer.dom(this.$.top_left_controls).appendChild(metricSelector);metricSelector.addEventListener('change',this.onMetricChange_.bind(this));this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.recomputeButton_=tr.ui.b.createButton('Recompute',this.onRecompute_,this);Polymer.dom(this.$.top_left_controls).appendChild(this.recomputeButton_);this.$.results.addEventListener('display-ready',()=>{this.$.results.style.display='';});},async build(model){this.model_=model;await this.updateContents_();},get metricLatencyMs(){return tr.b.math.Statistics.mean(this.metricLatenciesMs_);},onMetricChange_(){this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.metricLatenciesMs_=[];this.updateContents_();},onRecompute_(){this.updateContents_();},get textLabel(){return'Metrics';},supportsModel(m){if(!m){return{supported:false,reason:'No model available'};}
+const path=window.location.pathname.split('/');const basename=path[path.length-1].split('.')[0]||'histograms';const anchor=document.createElement('a');anchor.download=`${basename}.${event.format}`;anchor.href=window.URL.createObjectURL(blob);anchor.click();mark.end();},});return{};});'use strict';tr.exportTo('tr.ui',function(){Polymer({is:'tr-ui-sp-metrics-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.rangeOfInterest_=undefined;this.metricLatenciesMs_=[];this.metrics_=[];tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(function(m){if(m.constructor.name==='sampleMetric')return;this.metrics_.push({label:m.constructor.name,value:m.constructor.name});},this);this.metrics_.sort((x,y)=>x.label.localeCompare(y.label));this.settingsKey_='metrics-side-panel-metric-name';this.currentMetricName_='responsivenessMetric';const metricSelector=tr.ui.b.createSelector(this,'currentMetricName_',this.settingsKey_,this.currentMetricName_,this.metrics_);Polymer.dom(this.$.top_left_controls).appendChild(metricSelector);metricSelector.addEventListener('change',this.onMetricChange_.bind(this));this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.recomputeButton_=tr.ui.b.createButton('Recompute',this.onRecompute_,this);Polymer.dom(this.$.top_left_controls).appendChild(this.recomputeButton_);this.$.results.addEventListener('display-ready',()=>{this.$.results.style.display='';});},async build(model){this.model_=model;await this.updateContents_();},get metricLatencyMs(){return tr.b.math.Statistics.mean(this.metricLatenciesMs_);},onMetricChange_(){this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.metricLatenciesMs_=[];this.updateContents_();},onRecompute_(){this.updateContents_();},get textLabel(){return'Metrics';},supportsModel(m){if(!m){return{supported:false,reason:'No model available'};}
 return{supported:true};},get model(){return this.model_;},set model(model){this.build(model);},get selection(){},set selection(_){},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){this.rangeOfInterest_=range;if(this.currentMetricTypeInfo_&&this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest){if((this.metricLatencyMs===undefined)||(this.metricLatencyMs<100)){this.updateContents_();}else{this.recomputeButton_.style.background='red';}}},async updateContents_(){Polymer.dom(this.$.error).textContent='';this.$.results.style.display='none';if(!this.model_){Polymer.dom(this.$.error).textContent='Missing model';return;}
 const options={metrics:[this.currentMetricName_]};if(this.currentMetricTypeInfo_&&this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest&&this.rangeOfInterest&&!this.rangeOfInterest.isEmpty){options.rangeOfInterest=this.rangeOfInterest;}
 const startDate=new Date();const addFailureCb=failure=>{Polymer.dom(this.$.error).textContent=failure.description;};const histograms=tr.metrics.runMetrics(this.model_,options,addFailureCb);this.metricLatenciesMs_.push(new Date()-startDate);while(this.metricLatenciesMs_.length>20){this.metricLatenciesMs_.shift();}
diff --git a/runtime/observatory_2/lib/app.dart b/runtime/observatory_2/lib/app.dart
index 86de2ed..1c9849c 100644
--- a/runtime/observatory_2/lib/app.dart
+++ b/runtime/observatory_2/lib/app.dart
@@ -18,7 +18,6 @@
 import 'package:observatory_2/tracer.dart';
 import 'package:observatory_2/utils.dart';
 import 'package:stack_trace/stack_trace.dart';
-import 'package:usage/usage_html.dart';
 
 export 'package:observatory_2/utils.dart';
 
diff --git a/runtime/observatory_2/lib/src/elements/function_view.dart b/runtime/observatory_2/lib/src/elements/function_view.dart
index cad9250..963ecc4 100644
--- a/runtime/observatory_2/lib/src/elements/function_view.dart
+++ b/runtime/observatory_2/lib/src/elements/function_view.dart
@@ -422,8 +422,6 @@
         return 'stub';
       case M.FunctionKind.tag:
         return 'tag';
-      case M.FunctionKind.signatureFunction:
-        return 'signature function';
       case M.FunctionKind.dynamicInvocationForwarder:
         return 'dynamic invocation forwarder';
     }
diff --git a/runtime/observatory_2/lib/src/elements/instance_ref.dart b/runtime/observatory_2/lib/src/elements/instance_ref.dart
index 51f3616..1895783 100644
--- a/runtime/observatory_2/lib/src/elements/instance_ref.dart
+++ b/runtime/observatory_2/lib/src/elements/instance_ref.dart
@@ -124,6 +124,7 @@
                 _instance.valueAsString, _instance.valueAsStringIsTruncated)
         ];
       case M.InstanceKind.type:
+      case M.InstanceKind.functionType:
       case M.InstanceKind.typeRef:
       case M.InstanceKind.typeParameter:
         return [
diff --git a/runtime/observatory_2/lib/src/models/objects/field.dart b/runtime/observatory_2/lib/src/models/objects/field.dart
index ca59328c..53bc59d 100644
--- a/runtime/observatory_2/lib/src/models/objects/field.dart
+++ b/runtime/observatory_2/lib/src/models/objects/field.dart
@@ -15,7 +15,7 @@
   /// The declared type of this field.
   ///
   /// The value will always be of one of the kinds:
-  /// Type, TypeRef, TypeParameter.
+  /// Type, FunctionType, TypeRef, TypeParameter.
   InstanceRef get declaredType;
 
   /// Is this field const?
diff --git a/runtime/observatory_2/lib/src/models/objects/function.dart b/runtime/observatory_2/lib/src/models/objects/function.dart
index 7de7ad6..0d31983 100644
--- a/runtime/observatory_2/lib/src/models/objects/function.dart
+++ b/runtime/observatory_2/lib/src/models/objects/function.dart
@@ -24,7 +24,6 @@
   ffiTrampoline,
   stub,
   tag,
-  signatureFunction,
   dynamicInvocationForwarder
 }
 
diff --git a/runtime/observatory_2/lib/src/models/objects/instance.dart b/runtime/observatory_2/lib/src/models/objects/instance.dart
index e52cdd7..b21c572 100644
--- a/runtime/observatory_2/lib/src/models/objects/instance.dart
+++ b/runtime/observatory_2/lib/src/models/objects/instance.dart
@@ -115,6 +115,9 @@
   /// An instance of the Dart class Type.
   type,
 
+  /// An instance of the Dart class FunctionType.
+  functionType,
+
   /// An instance of the Dart class TypeParameter.
   typeParameter,
 
@@ -161,6 +164,7 @@
 bool isAbstractType(InstanceKind kind) {
   switch (kind) {
     case InstanceKind.type:
+    case InstanceKind.functionType:
     case InstanceKind.typeRef:
     case InstanceKind.typeParameter:
       return true;
@@ -378,7 +382,7 @@
   /// [optional] The referent of a TypeRef instance.
   ///
   /// The value will always be of one of the kinds:
-  /// Type, TypeRef, TypeParameter.
+  /// Type, FunctionType, TypeRef, TypeParameter.
   ///
   /// Provided for instance kinds:
   ///   TypeRef
@@ -387,7 +391,7 @@
   /// [optional] The bound of a TypeParameter.
   ///
   /// The value will always be of one of the kinds:
-  /// Type, TypeRef, TypeParameter.
+  /// Type, FunctionType, TypeRef, TypeParameter.
   ///
   /// Provided for instance kinds:
   ///   TypeParameter
diff --git a/runtime/observatory_2/lib/src/models/objects/type_arguments.dart b/runtime/observatory_2/lib/src/models/objects/type_arguments.dart
index a3614dd..a6469df 100644
--- a/runtime/observatory_2/lib/src/models/objects/type_arguments.dart
+++ b/runtime/observatory_2/lib/src/models/objects/type_arguments.dart
@@ -13,6 +13,6 @@
   /// A list of types.
   ///
   /// The value will always be one of the kinds:
-  /// Type, TypeRef, TypeParameter.
+  /// Type, FunctionType, TypeRef, TypeParameter.
   Iterable<InstanceRef> get types;
 }
diff --git a/runtime/observatory_2/lib/src/service/object.dart b/runtime/observatory_2/lib/src/service/object.dart
index 981215d..da5b60f 100644
--- a/runtime/observatory_2/lib/src/service/object.dart
+++ b/runtime/observatory_2/lib/src/service/object.dart
@@ -2756,6 +2756,8 @@
       return M.InstanceKind.weakProperty;
     case 'Type':
       return M.InstanceKind.type;
+    case 'FunctionType':
+      return M.InstanceKind.functionType;
     case 'TypeParameter':
       return M.InstanceKind.typeParameter;
     case 'TypeRef':
@@ -3131,8 +3133,6 @@
       return M.FunctionKind.stub;
     case 'Tag':
       return M.FunctionKind.tag;
-    case 'SignatureFunction':
-      return M.FunctionKind.signatureFunction;
     case 'DynamicInvocationForwarder':
       return M.FunctionKind.dynamicInvocationForwarder;
   }
diff --git a/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart b/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart
index 1abcb9f..4f91673 100644
--- a/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart
+++ b/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart
@@ -53,15 +53,19 @@
   var script = isolate.rootLibrary.scripts[0];
 
   var bp1 = await isolate.addBreakpoint(script, 13);
+  print("BP1 - $bp1");
   expect(bp1, isNotNull);
   expect(bp1 is Breakpoint, isTrue);
   var bp2 = await isolate.addBreakpoint(script, 18);
+  print("BP2 - $bp2");
   expect(bp2, isNotNull);
   expect(bp2 is Breakpoint, isTrue);
   var bp3 = await isolate.addBreakpoint(script, 23);
+  print("BP3 - $bp3");
   expect(bp3, isNotNull);
   expect(bp3 is Breakpoint, isTrue);
   var bp4 = await isolate.addBreakpoint(script, 27);
+  print("BP4 - $bp4");
   expect(bp4, isNotNull);
   expect(bp4 is Breakpoint, isTrue);
   var bp5 = await isolate.addBreakpoint(script, 44);
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_file_uri_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_file_uri_test.dart
index 03a57f6..da48c7d 100644
--- a/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_file_uri_test.dart
+++ b/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_file_uri_test.dart
@@ -14,7 +14,8 @@
 // Chop off the file name.
 String baseDirectory = path.dirname(Platform.script.path) + '/';
 Uri baseUri = Platform.script.replace(path: baseDirectory);
-Uri breakpointFile = baseUri.resolve('observatory_test_package/the_part.dart');
+Uri breakpointFile =
+    baseUri.resolve('observatory_test_package_2/the_part.dart');
 const String shortFile = "the_part.dart";
 
 const int LINE = 87;
diff --git a/runtime/observatory_2/tests/service_2/dds_disconnects_existing_clients_test.dart b/runtime/observatory_2/tests/service_2/dds_disconnects_existing_clients_test.dart
new file mode 100644
index 0000000..a8b529e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dds_disconnects_existing_clients_test.dart
@@ -0,0 +1,61 @@
+// 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:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+final tests = <VMTest>[
+  (VM vm) async {
+    DartDevelopmentService dds;
+    final waitForDDS = Completer<void>();
+    final serviceMessageCompleter = Completer<void>();
+
+    // The original VM service client is connected.
+    expect(vm.isConnected, true);
+
+    // A service event is sent to all existing clients when DDS connects before
+    // their connection is closed.
+    await vm.listenEventStream('Service', (ServiceEvent event) async {
+      // Wait for dds to be set before checking the server's URI.
+      await waitForDDS.future;
+      final message =
+          'A Dart Developer Service instance has connected and this direct '
+          'connection to the VM service will now be closed. Please reconnect to '
+          'the Dart Development Service at ${dds.uri}.';
+      expect(event.kind, ServiceEvent.kDartDevelopmentServiceConnected);
+      expect(event.message, message);
+      expect(event.uri, dds.uri);
+      serviceMessageCompleter.complete();
+    });
+
+    // Start DDS, which should result in the original VM service client being
+    // disconnected from the VM service.
+    final remote = Uri.parse(vm.target.networkAddress);
+    dds = await DartDevelopmentService.startDartDevelopmentService(
+      remote.replace(
+        scheme: 'http',
+        pathSegments: remote.pathSegments.sublist(
+          0,
+          remote.pathSegments.length - 1,
+        ),
+      ),
+    );
+    waitForDDS.complete();
+    expect(dds.isRunning, true);
+    await serviceMessageCompleter.future;
+    await vm.onDisconnect;
+    await dds.shutdown();
+  }
+];
+
+main(args) async => runVMTests(
+      args,
+      tests,
+      enableDds: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/deferred_import_reload/v1/deferred.dart b/runtime/observatory_2/tests/service_2/deferred_import_reload/v1/deferred.dart
new file mode 100644
index 0000000..0cdf678
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/deferred_import_reload/v1/deferred.dart
@@ -0,0 +1,5 @@
+// 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.
+
+foo() => 'apple';
diff --git a/runtime/observatory_2/tests/service_2/deferred_import_reload/v1/main.dart b/runtime/observatory_2/tests/service_2/deferred_import_reload/v1/main.dart
new file mode 100644
index 0000000..3f1912e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/deferred_import_reload/v1/main.dart
@@ -0,0 +1,38 @@
+// 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 'dart:isolate';
+
+import 'deferred.dart' deferred as prefix1;
+import 'deferred.dart' deferred as prefix2;
+
+main() {
+  prefix1.loadLibrary();
+  RawReceivePort keepAlive = new RawReceivePort();
+  print('spawned isolate running');
+}
+
+test() {
+  var x = "";
+
+  try {
+    x += prefix1.foo(); // Should retain loaded=true state across reload.
+  } catch (e, st) {
+    print(e);
+    print(st);
+    x += "error";
+  }
+
+  x += ",";
+
+  try {
+    x += prefix2.foo(); // Should retain loaded=false state across reload.
+  } catch (e, st) {
+    print(e);
+    print(st);
+    x += "error";
+  }
+
+  return x;
+}
diff --git a/runtime/observatory_2/tests/service_2/deferred_import_reload/v2/deferred.dart b/runtime/observatory_2/tests/service_2/deferred_import_reload/v2/deferred.dart
new file mode 100644
index 0000000..7a58941
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/deferred_import_reload/v2/deferred.dart
@@ -0,0 +1,5 @@
+// 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.
+
+foo() => 'orange';
diff --git a/runtime/observatory_2/tests/service_2/deferred_import_reload/v2/main.dart b/runtime/observatory_2/tests/service_2/deferred_import_reload/v2/main.dart
new file mode 100644
index 0000000..2710f32
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/deferred_import_reload/v2/main.dart
@@ -0,0 +1,36 @@
+// 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 'dart:isolate';
+
+import 'deferred.dart' deferred as prefix1;
+import 'deferred.dart' deferred as prefix2;
+
+main() {
+  throw "Not executed";
+}
+
+test() {
+  var x = "";
+
+  try {
+    x += prefix1.foo(); // Should retain loaded=true state across reload.
+  } catch (e, st) {
+    print(e);
+    print(st);
+    x += "error";
+  }
+
+  x += ",";
+
+  try {
+    x += prefix2.foo(); // Should retain loaded=false state across reload.
+  } catch (e, st) {
+    print(e);
+    print(st);
+    x += "error";
+  }
+
+  return x;
+}
diff --git a/runtime/observatory_2/tests/service_2/deferred_import_reload_test.dart b/runtime/observatory_2/tests/service_2/deferred_import_reload_test.dart
new file mode 100644
index 0000000..fe3bff9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/deferred_import_reload_test.dart
@@ -0,0 +1,78 @@
+// 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.
+//
+// OtherResources=deferred_import_reload/v1/main.dart deferred_import_reload/v1/deferred.dart deferred_import_reload/v2/main.dart deferred_import_reload/v2/deferred.dart
+
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate' as I;
+import 'dart:io';
+import 'service_test_common.dart';
+import 'package:observatory_2/service.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+// Chop off the file name.
+String baseDirectory = path.dirname(Platform.script.path) + '/';
+
+Uri baseUri = Platform.script.replace(path: baseDirectory);
+Uri spawnUri =
+    baseUri.resolveUri(Uri.parse('deferred_import_reload/v1/main.dart'));
+Uri v2Uri =
+    baseUri.resolveUri(Uri.parse('deferred_import_reload/v2/main.dart'));
+
+testMain() async {
+  print(baseUri);
+  debugger(); // Stop here.
+  // Spawn the child isolate.
+  I.Isolate isolate = await I.Isolate.spawnUri(spawnUri, [], null);
+  print(isolate);
+  debugger();
+}
+
+Future<String> invokeTest(Isolate isolate) async {
+  await isolate.reload();
+  Library lib = isolate.rootLibrary;
+  await lib.load();
+  Instance result = await lib.evaluate('test()');
+  expect(result.isString, isTrue);
+  return result.valueAsString;
+}
+
+var tests = <IsolateTest>[
+  // Stopped at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  // Resume the isolate into the while loop.
+  resumeIsolate,
+  // Stop at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  (Isolate mainIsolate) async {
+    // Grab the VM.
+    VM vm = mainIsolate.vm;
+    await vm.reloadIsolates();
+    expect(vm.isolates.length, 2);
+
+    // Find the spawned isolate.
+    Isolate spawnedIsolate =
+        vm.isolates.firstWhere((Isolate i) => i != mainIsolate);
+    expect(spawnedIsolate, isNotNull);
+
+    // Invoke test in v1.
+    String v1 = await invokeTest(spawnedIsolate);
+    expect(v1, 'apple,error');
+
+    // Reload to v2.
+    var response = await spawnedIsolate.reloadSources(
+      rootLibUri: v2Uri.toString(),
+    );
+    // Observe that it succeed.
+    expect(response['success'], isTrue);
+
+    String v2 = await invokeTest(spawnedIsolate);
+    expect(v2, 'orange,error');
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/notify_debugger_on_exception_test.dart b/runtime/observatory_2/tests/service_2/notify_debugger_on_exception_test.dart
new file mode 100644
index 0000000..1d03341
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/notify_debugger_on_exception_test.dart
@@ -0,0 +1,37 @@
+// 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.
+//
+// VMOptions=--verbose_debug
+
+// See: https://github.com/flutter/flutter/issues/17007
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 24;
+
+@pragma('vm:notify-debugger-on-exception')
+void catchNotifyDebugger(Function() code) {
+  try {
+    code();
+  } catch (e) {
+    // Ignore. Internals will notify debugger.
+  }
+}
+
+syncThrow() {
+  throw 'Hello from syncThrow!'; // Line A.
+}
+
+testMain() {
+  catchNotifyDebugger(syncThrow);
+}
+
+final tests = <IsolateTest>[
+  hasStoppedWithUnhandledException,
+  stoppedAtLine(LINE_A),
+];
+
+main([args = const <String>[]]) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_unhandled_exceptions: true);
diff --git a/runtime/observatory_2/tests/service_2/service_2.status b/runtime/observatory_2/tests/service_2/service_2.status
index c16feab..874b3f4 100644
--- a/runtime/observatory_2/tests/service_2/service_2.status
+++ b/runtime/observatory_2/tests/service_2/service_2.status
@@ -25,6 +25,10 @@
 developer_extension_test: SkipByDesign
 get_isolate_after_language_error_test: SkipByDesign
 
+# The _1 versions of this test can be slow due to stress testing flags.
+[ $mode == debug ]
+async_generator_breakpoint_test: Pass, Slow
+
 # Service protocol is not supported in product mode.
 [ $mode == product ]
 *: SkipByDesign
diff --git a/runtime/observatory_2/tests/service_2/service_2_kernel.status b/runtime/observatory_2/tests/service_2/service_2_kernel.status
index 5522831..aea3d74 100644
--- a/runtime/observatory_2/tests/service_2/service_2_kernel.status
+++ b/runtime/observatory_2/tests/service_2/service_2_kernel.status
@@ -9,7 +9,7 @@
 break_on_activation_test: SkipByDesign # No incremental compiler available.
 complex_reload_test: RuntimeError
 debugger_inspect_test: SkipByDesign # No incremental compiler available.
-debugger_location_second_test: RuntimeError
+debugger_location_second_test: SkipByDesign # No script sources available.
 eval_internal_class_test: SkipByDesign # No incremental compiler available.
 eval_regression_flutter20255_test: SkipByDesign # No incremental compiler available.
 eval_test: SkipByDesign # No incremental compiler available.
@@ -25,6 +25,7 @@
 evaluate_in_sync_star_activation_test: SkipByDesign # No incremental compiler available.
 evaluate_with_escaping_closure_test: SkipByDesign # No incremental compiler available.
 evaluate_with_scope_test: SkipByDesign # No incremental compiler available.
+get_object_rpc_test: SkipByDesign # App-JIT snapshots don't contain script sources.
 pause_on_exceptions_test: SkipByDesign # No incremental compiler available.
 rewind_optimized_out_test: SkipByDesign # No incremental compiler available.
 rewind_test: SkipByDesign # No incremental compiler available.
@@ -87,6 +88,7 @@
 debugger_location_test: SkipByDesign # Debugger is disabled in AOT mode.
 debugging_inlined_finally_test: SkipByDesign # Debugger is disabled in AOT mode.
 debugging_test: SkipByDesign # Debugger is disabled in AOT mode.
+deferred_import_reload_test: SkipByDesign # Hot reload is disabled in AOT mode.
 dev_fs_spawn_test: SkipByDesign # Debugger is disabled in AOT mode.
 developer_extension_test: SkipByDesign # Debugger is disabled in AOT mode.
 developer_service_get_isolate_id_test: SkipByDesign # Debugger is disabled in AOT mode.
@@ -152,6 +154,7 @@
 next_through_simple_async_with_returns_test: SkipByDesign # Debugger is disabled in AOT mode.
 next_through_simple_linear_2_test: SkipByDesign # Debugger is disabled in AOT mode.
 next_through_simple_linear_test: SkipByDesign # Debugger is disabled in AOT mode.
+notify_debugger_on_exception_test: SkipByDesign # Debugger is disabled in AOT mode.
 parameters_in_scope_at_entry_test: SkipByDesign # Debugger is disabled in AOT mode.
 pause_idle_isolate_test: SkipByDesign # Debugger is disabled in AOT mode.
 pause_on_exceptions_test: SkipByDesign # Debugger is disabled in AOT mode.
@@ -164,7 +167,7 @@
 regress_28443_test: SkipByDesign # Debugger is disabled in AOT mode.
 regress_28980_test: SkipByDesign # Debugger is disabled in AOT mode.
 regress_34841_test: SkipByDesign # Debugger is disabled in AOT mode.
-reload_sources_test: SkipByDesign # Debugger is disabled in AOT mode.
+reload_sources_test: SkipByDesign # Hot reload is disabled in AOT mode.
 rewind_optimized_out_test: SkipByDesign # Debugger is disabled in AOT mode.
 rewind_test: SkipByDesign # Debugger is disabled in AOT mode.
 set_library_debuggable_test: SkipByDesign # Debugger is disabled in AOT mode.
diff --git a/runtime/observatory_2/web/third_party/trace_viewer_full.html b/runtime/observatory_2/web/third_party/trace_viewer_full.html
index d815ec5..daa87d0 100644
--- a/runtime/observatory_2/web/third_party/trace_viewer_full.html
+++ b/runtime/observatory_2/web/third_party/trace_viewer_full.html
@@ -2908,8 +2908,6 @@
       <div id="collapsing_controls"></div>
       <tr-ui-b-info-bar-group id="import-warnings">
       </tr-ui-b-info-bar-group>
-      <tr-ui-b-info-bar-group id="polyfill-warning">
-      </tr-ui-b-info-bar-group>
     </div>
     <middle-container>
       <slot></slot>
@@ -3120,10 +3118,6 @@
       margin-right: 20px;
     }
 
-    #show_visualization {
-      margin-right: 20px;
-    }
-
     #export {
       margin-right: 20px;
     }
@@ -3169,8 +3163,6 @@
       <select id="statistic" value="{{displayStatisticName::change}}">
       </select>
 
-      <button id="show_visualization" on-tap="loadVisualization_">Visualize</button>
-
       <tr-ui-b-dropdown label="Export">
         <tr-v-ui-histogram-set-controls-export>
         </tr-v-ui-histogram-set-controls-export>
@@ -3396,221 +3388,6 @@
 
     <tr-ui-b-table id="table">
   </tr-ui-b-table></template>
-</dom-module><dom-module id="tr-v-ui-metrics-visualization">
-  <template>
-    <style>
-      button {
-        padding: 5px;
-        font-size: 14px;
-      }
-
-      .text_input {
-        width: 50px;
-        padding: 4px;
-        font-size: 14px;
-      }
-
-      .error {
-        color: red;
-        display: none;
-      }
-
-      .container {
-        position: relative;
-        display: inline-block;
-        margin-left: 15px;
-      }
-
-      #title {
-        font-size: 20px;
-        font-weight: bold;
-        padding-bottom: 5px;
-      }
-
-      #selectors {
-        display: block;
-        padding-bottom: 10px;
-      }
-
-      #search_page {
-        width: 200px;
-        margin-left: 30px;
-      }
-
-      #close {
-        display: none;
-        vertical-align: top;
-      }
-
-      #close svg{
-        height: 1em;
-      }
-
-      #close svg line {
-        stroke-width: 18;
-        stroke: black;
-      }
-
-      #close:hover svg {
-        background: black;
-      }
-
-      #close:hover svg line {
-        stroke: white;
-      }
-    </style>
-      <span class="container" id="aggregateContainer">
-      </span>
-      <span class="container" id="pageByPageContainer">
-        <span id="selectors">
-          <span id="percentile_label">Percentile Range:</span>
-          <input class="text_input" id="start" placeholder="0"/>
-          <input class="text_input" id="end" placeholder="100"/>
-          <button id="filter" on-tap="filterByPercentile_">Filter</button>
-          <input class="text_input" id="search_page" placeholder="Page Name"/>
-          <button id="search" on-tap="searchByPage_">Search</button>
-          <span class="error" id="search_error">Sorry, could not find that page!</span>
-        </span>
-      </span>
-      <div display="block" id="submetricsContainer">
-        <span id="close">
-          <svg viewBox="0 0 128 128">
-            <line x1="28" x2="100" y1="28" y2="100"></line>
-            <line x1="28" x2="100" y1="100" y2="28"></line>
-          </svg>
-        </span>
-      </div>
-  </template>
-</dom-module><dom-module id="tr-v-ui-raster-visualization">
-  <template>
-    <style>
-      button {
-        padding: 5px;
-        font-size: 14px;
-      }
-      .error {
-        color: red;
-        display: none;
-      }
-
-      .text_input {
-        width: 200px;
-        padding: 4px;
-        font-size: 14px;
-      }
-
-      .selector_container{
-        padding: 5px;
-      }
-
-      #search {
-        display: inline-block;
-        padding-bottom: 10px;
-      }
-
-      #search_page {
-        width: 200px;
-      }
-
-      #pageSelector {
-        display: inline-block;
-        font-size: 12pt;
-      }
-
-      #close {
-        display: none;
-        vertical-align: top;
-      }
-
-      #close svg{
-        height: 1em;
-      }
-
-      #close svg line {
-        stroke-width: 18;
-        stroke: black;
-      }
-
-      #close:hover svg {
-        background: black;
-      }
-
-      #close:hover svg line {
-        stroke: white;
-      }
-    </style>
-    <span id="aggregateContainer">
-      <div>
-        <div class="selector_container">
-          <span id="select_page_label">Individual Page Results:</span>
-          <select id="pageSelector">
-            <option id="select_page" value="">Select a page</option>
-          </select>
-        </div>
-        <div class="selector_container">
-          <div id="search_page_label">Search for a page:</div>
-          <input class="text_input" id="search_page" placeholder="Page Name"/>
-          <button id="search_button">Search</button>
-          <div class="error" id="search_error">Sorry, could not find that page!</div>
-        </div>
-      </div>
-    </span>
-    <span id="pageContainer">
-      <span id="close">
-          <svg viewBox="0 0 128 128">
-            <line x1="28" x2="100" y1="28" y2="100"></line>
-            <line x1="28" x2="100" y1="100" y2="28"></line>
-          </svg>
-        </span>
-      </span>
-  </template>
-</dom-module><meta charset="utf-8"/><dom-module id="tr-v-ui-visualizations-data-container">
-  <template>
-    <style>
-      .error {
-        color: red;
-        display: none;
-      }
-
-      .sample{
-        display: none;
-      }
-
-      .subtitle{
-        font-size: 20px;
-        font-weight: bold;
-        padding-bottom: 5px;
-      }
-
-      .description{
-        font-size: 15px;
-        padding-bottom: 5px;
-      }
-
-      #title {
-        font-size: 30px;
-        font-weight: bold;
-        padding-bottom: 5px;
-      }
-    </style>
-    <div id="title">Visualizations</div>
-    <div class="error" id="data_error">Invalid data provided.</div>
-    <div id="pipeline_per_frame_container">
-      <div class="subtitle">Graphics Pipeline and Raster Tasks</div>
-      <div class="description">
-        When raster tasks are completed in comparison to the rest of the graphics pipeline.<br/>
-        Only pages where raster tasks are completed after beginFrame is issued are included.
-      </div>
-      <tr-v-ui-raster-visualization id="rasterVisualization">
-      </tr-v-ui-raster-visualization>
-    </div>
-    <div id="metrics_container">
-      <div class="subtitle">Metrics</div>
-      <div class="description">Total amount of time taken for the indicated metrics.</div>
-      <tr-v-ui-metrics-visualization class="sample" id="metricsVisualization">
-      </tr-v-ui-metrics-visualization>
-    </div>
-  </template>
 </dom-module><dom-module id="tr-v-ui-histogram-set-view">
   <template>
     <style>
@@ -3632,9 +3409,6 @@
       display: none;
     }
 
-    #visualizations{
-      display: none;
-    }
     </style>
 
     <div id="zero">zero Histograms</div>
@@ -3643,9 +3417,6 @@
       <tr-v-ui-histogram-set-controls id="controls">
       </tr-v-ui-histogram-set-controls>
 
-      <tr-v-ui-visualizations-data-container id="visualizations">
-      </tr-v-ui-visualizations-data-container>
-
       <tr-v-ui-histogram-set-table id="table"></tr-v-ui-histogram-set-table>
     </div>
   </template>
@@ -3702,7 +3473,22 @@
  * Do not edit directly.
  */
 
-'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(window.Polymer){throw new Error('Cannot proceed. Polymer already present.');}
+'use strict';const global=this.window||this.global;this.tr=(function(){if(global.tr)return global.tr;function exportPath(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{cur=cur[part]={};}}
+return cur;}
+function isExported(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{return false;}}
+return true;}
+function isDefined(name){const parts=name.split('.');let curObject=global;for(let i=0;i<parts.length;i++){const partName=parts[i];const nextObject=curObject[partName];if(nextObject===undefined)return false;curObject=nextObject;}
+return true;}
+let panicElement=undefined;const rawPanicMessages=[];function showPanicElementIfNeeded(){if(panicElement)return;const panicOverlay=document.createElement('div');panicOverlay.style.backgroundColor='white';panicOverlay.style.border='3px solid red';panicOverlay.style.boxSizing='border-box';panicOverlay.style.color='black';panicOverlay.style.display='flex';panicOverlay.style.height='100%';panicOverlay.style.left=0;panicOverlay.style.padding='8px';panicOverlay.style.position='fixed';panicOverlay.style.top=0;panicOverlay.style.webkitFlexDirection='column';panicOverlay.style.width='100%';panicElement=document.createElement('div');panicElement.style.webkitFlex='1 1 auto';panicElement.style.overflow='auto';panicOverlay.appendChild(panicElement);if(!document.body){setTimeout(function(){document.body.appendChild(panicOverlay);},150);}else{document.body.appendChild(panicOverlay);}}
+function showPanic(panicTitle,panicDetails){if(tr.isHeadless){if(panicDetails instanceof Error)throw panicDetails;throw new Error('Panic: '+panicTitle+':\n'+panicDetails);}
+if(panicDetails instanceof Error){panicDetails=panicDetails.stack;}
+showPanicElementIfNeeded();const panicMessageEl=document.createElement('div');panicMessageEl.innerHTML='<h2 id="message"></h2>'+'<pre id="details"></pre>';panicMessageEl.querySelector('#message').textContent=panicTitle;panicMessageEl.querySelector('#details').textContent=panicDetails;panicElement.appendChild(panicMessageEl);rawPanicMessages.push({title:panicTitle,details:panicDetails});}
+function hasPanic(){return rawPanicMessages.length!==0;}
+function getPanicText(){return rawPanicMessages.map(function(msg){return msg.title;}).join(', ');}
+function exportTo(namespace,fn){const obj=exportPath(namespace);const exports=fn();for(const propertyName in exports){const propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor){Object.defineProperty(obj,propertyName,propertyDescriptor);}}}
+function initialize(){if(global.isVinn){tr.isVinn=true;}else if(global.process&&global.process.versions.node){tr.isNode=true;}else{tr.isVinn=false;tr.isNode=false;tr.doc=document;tr.isMac=/Mac/.test(navigator.platform);tr.isWindows=/Win/.test(navigator.platform);tr.isChromeOS=/CrOS/.test(navigator.userAgent);tr.isLinux=/Linux/.test(navigator.userAgent);}
+tr.isHeadless=tr.isVinn||tr.isNode;}
+return{initialize,exportTo,isExported,isDefined,showPanic,hasPanic,getPanicText,};})();tr.initialize();'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(window.Polymer){throw new Error('Cannot proceed. Polymer already present.');}
 window.Polymer={};window.Polymer.dom='shadow';}
 (function(){function resolve(){document.body.removeAttribute('unresolved');}
 if(window.WebComponents){addEventListener('WebComponentsReady',resolve);}else{if(document.readyState==='interactive'||document.readyState==='complete'){resolve();}else{addEventListener('DOMContentLoaded',resolve);}}}());window.Polymer={Settings:function(){var settings=window.Polymer||{};if(!settings.noUrlSettings){var parts=location.search.slice(1).split('&');for(var i=0,o;i<parts.length&&(o=parts[i]);i++){o=o.split('=');o[0]&&(settings[o[0]]=o[1]||true);}}
@@ -4296,22 +4082,7 @@
 this._instance=null;}},_showHideChildren:function(){var hidden=this.__hideTemplateChildren__||!this.if;if(this._instance){this._instance._showHideChildren(hidden);}},_forwardParentProp:function(prop,value){if(this._instance){this._instance.__setProperty(prop,value,true);}},_forwardParentPath:function(path,value){if(this._instance){this._instance._notifyPath(path,value,true);}}});Polymer({is:'dom-bind',properties:{notifyDomChange:{type:Boolean}},extends:'template',_template:null,created:function(){var self=this;Polymer.RenderStatus.whenReady(function(){if(document.readyState=='loading'){document.addEventListener('DOMContentLoaded',function(){self._markImportsReady();});}else{self._markImportsReady();}});},_ensureReady:function(){if(!this._readied){this._readySelf();}},_markImportsReady:function(){this._importsReady=true;this._ensureReady();},_registerFeatures:function(){this._prepConstructor();},_insertChildren:function(){var refNode;var parentNode=Polymer.dom(this).parentNode;if(parentNode.localName==this.is){refNode=parentNode;parentNode=Polymer.dom(parentNode).parentNode;}else{refNode=this;}
 Polymer.dom(parentNode).insertBefore(this.root,refNode);},_removeChildren:function(){if(this._children){for(var i=0;i<this._children.length;i++){this.root.appendChild(this._children[i]);}}},_initFeatures:function(){},_scopeElementClass:function(element,selector){if(this.dataHost){return this.dataHost._scopeElementClass(element,selector);}else{return selector;}},_configureInstanceProperties:function(){},_prepConfigure:function(){var config={};for(var prop in this._propertyEffects){config[prop]=this[prop];}
 var setupConfigure=this._setupConfigure;this._setupConfigure=function(){setupConfigure.call(this,config);};},attached:function(){if(this._importsReady){this.render();}},detached:function(){this._removeChildren();},render:function(){this._ensureReady();if(!this._children){this._template=this;this._prepAnnotations();this._prepEffects();this._prepBehaviors();this._prepConfigure();this._prepBindings();this._prepPropertyInfo();Polymer.Base._initFeatures.call(this);this._children=Polymer.TreeApi.arrayCopyChildNodes(this.root);}
-this._insertChildren();if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}}});'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(!Polymer.Settings.useNativeShadow){tr.showPanic('Polymer error','base should use native shadow when possible.');}}'use strict';const global=this.window||this.global;this.tr=(function(){if(global.tr)return global.tr;function exportPath(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{cur=cur[part]={};}}
-return cur;}
-function isExported(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{return false;}}
-return true;}
-function isDefined(name){const parts=name.split('.');let curObject=global;for(let i=0;i<parts.length;i++){const partName=parts[i];const nextObject=curObject[partName];if(nextObject===undefined)return false;curObject=nextObject;}
-return true;}
-let panicElement=undefined;const rawPanicMessages=[];function showPanicElementIfNeeded(){if(panicElement)return;const panicOverlay=document.createElement('div');panicOverlay.style.backgroundColor='white';panicOverlay.style.border='3px solid red';panicOverlay.style.boxSizing='border-box';panicOverlay.style.color='black';panicOverlay.style.display='flex';panicOverlay.style.height='100%';panicOverlay.style.left=0;panicOverlay.style.padding='8px';panicOverlay.style.position='fixed';panicOverlay.style.top=0;panicOverlay.style.webkitFlexDirection='column';panicOverlay.style.width='100%';panicElement=document.createElement('div');panicElement.style.webkitFlex='1 1 auto';panicElement.style.overflow='auto';panicOverlay.appendChild(panicElement);if(!document.body){setTimeout(function(){document.body.appendChild(panicOverlay);},150);}else{document.body.appendChild(panicOverlay);}}
-function showPanic(panicTitle,panicDetails){if(tr.isHeadless){if(panicDetails instanceof Error)throw panicDetails;throw new Error('Panic: '+panicTitle+':\n'+panicDetails);}
-if(panicDetails instanceof Error){panicDetails=panicDetails.stack;}
-showPanicElementIfNeeded();const panicMessageEl=document.createElement('div');panicMessageEl.innerHTML='<h2 id="message"></h2>'+'<pre id="details"></pre>';panicMessageEl.querySelector('#message').textContent=panicTitle;panicMessageEl.querySelector('#details').textContent=panicDetails;panicElement.appendChild(panicMessageEl);rawPanicMessages.push({title:panicTitle,details:panicDetails});}
-function hasPanic(){return rawPanicMessages.length!==0;}
-function getPanicText(){return rawPanicMessages.map(function(msg){return msg.title;}).join(', ');}
-function exportTo(namespace,fn){const obj=exportPath(namespace);const exports=fn();for(const propertyName in exports){const propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor){Object.defineProperty(obj,propertyName,propertyDescriptor);}}}
-function initialize(){if(global.isVinn){tr.isVinn=true;}else if(global.process&&global.process.versions.node){tr.isNode=true;}else{tr.isVinn=false;tr.isNode=false;tr.doc=document;tr.isMac=/Mac/.test(navigator.platform);tr.isWindows=/Win/.test(navigator.platform);tr.isChromeOS=/CrOS/.test(navigator.userAgent);tr.isLinux=/Linux/.test(navigator.userAgent);}
-tr.isHeadless=tr.isVinn||tr.isNode;}
-return{initialize,exportTo,isExported,isDefined,showPanic,hasPanic,getPanicText,};})();tr.initialize();'use strict';tr.exportTo('tr.b',function(){function EventTarget(){}
+this._insertChildren();if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}}});'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(!Polymer.Settings.useNativeShadow){tr.showPanic('Polymer error','base should use native shadow when possible.');}}'use strict';tr.exportTo('tr.b',function(){function EventTarget(){}
 EventTarget.decorate=function(target){for(const k in EventTarget.prototype){if(k==='decorate')continue;const v=EventTarget.prototype[k];if(typeof v!=='function')continue;target[k]=v;}};EventTarget.prototype={addEventListener(type,handler){if(!this.listeners_){this.listeners_=Object.create(null);}
 if(!(type in this.listeners_)){this.listeners_[type]=[handler];}else{const handlers=this.listeners_[type];if(handlers.indexOf(handler)<0){handlers.push(handler);}}},removeEventListener(type,handler){if(!this.listeners_)return;if(type in this.listeners_){const handlers=this.listeners_[type];const index=handlers.indexOf(handler);if(index>=0){if(handlers.length===1){delete this.listeners_[type];}else{handlers.splice(index,1);}}}},dispatchEvent(event){if(!this.listeners_)return true;event.__defineGetter__('target',()=>this);const realPreventDefault=event.preventDefault;event.preventDefault=function(){realPreventDefault.call(this);this.rawReturnValue=false;};const type=event.type;let prevented=0;if(type in this.listeners_){const handlers=this.listeners_[type].concat();for(let i=0,handler;handler=handlers[i];i++){if(handler.handleEvent){prevented|=handler.handleEvent.call(handler,event)===false;}else{prevented|=handler.call(this,event)===false;}}}
 return!prevented&&event.rawReturnValue;},async dispatchAsync(event){if(!this.listeners_)return true;const listeners=this.listeners_[event.type];if(listeners===undefined)return;await Promise.all(listeners.slice().map(listener=>{if(listener.handleEvent){return listener.handleEvent.call(listener,event);}
@@ -4573,7 +4344,7 @@
 const baseUnit=Unit.byName[params.baseUnitName];definedUnits.forEach(u=>u.baseUnit=baseUnit);};Unit.nameSuffixForImprovementDirection=function(improvementDirection){switch(improvementDirection){case ImprovementDirection.DONT_CARE:return'';case ImprovementDirection.BIGGER_IS_BETTER:return'_biggerIsBetter';case ImprovementDirection.SMALLER_IS_BETTER:return'_smallerIsBetter';default:throw new Error('Unknown improvement direction: '+improvementDirection);}};Unit.defineUnitVariant_=function(params,isDelta,improvementDirection){let nameSuffix=isDelta?'Delta':'';nameSuffix+=Unit.nameSuffixForImprovementDirection(improvementDirection);const unitName=params.baseUnitName+nameSuffix;const jsonName=params.baseJsonName+nameSuffix;if(Unit.byName[unitName]!==undefined){throw new Error('Unit \''+unitName+'\' already exists');}
 if(Unit.byJSONName[jsonName]!==undefined){throw new Error('JSON unit \''+jsonName+'\' alread exists');}
 let scaleBaseUnit=params.scaleBaseUnit;if(!scaleBaseUnit){let formatSpec=params.formatSpec;if(typeof formatSpec==='function')formatSpec=formatSpec();const baseSymbol=formatSpec.unitScale?formatSpec.unitScale[0].baseSymbol:(formatSpec.baseSymbol||'');scaleBaseUnit={value:1,symbol:baseSymbol,baseSymbol};}
-const unit=new Unit(unitName,jsonName,scaleBaseUnit,isDelta,improvementDirection,params.formatSpec);Unit.byName[unitName]=unit;Unit.byJSONName[jsonName]=unit;return unit;};tr.b.EventTarget.decorate(Unit);Unit.reset();Unit.define({baseUnitName:'timeInMsAutoFormat',baseJsonName:'msBestFitFormat',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec:{unitScale:tr.b.UnitScale.TIME.AUTO,minimumFractionDigits:0,maximumFractionDigits:3}});Unit.define({baseUnitName:'timeDurationInMs',baseJsonName:'ms',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'timeStampInMs',baseJsonName:'tsMs',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'normalizedPercentage',baseJsonName:'n%',formatSpec:{unitScale:[{value:0.01,symbol:'%'}],avoidSpacePrecedingUnit:true,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'sizeInBytes',baseJsonName:'sizeInBytes',formatSpec:{unitScale:tr.b.UnitScale.MEMORY.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'bandwidthInBytesPerSecond',baseJsonName:'bytesPerSecond',formatSpec:{unitScale:tr.b.UnitScale.BANDWIDTH_BYTES.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'energyInJoules',baseJsonName:'J',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('J','JOULE',tr.b.UnitPrefixScale.METRIC,'JOULE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'powerInWatts',baseJsonName:'W',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('W','WATT',tr.b.UnitPrefixScale.METRIC,'WATT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricCurrentInAmperes',baseJsonName:'A',formatSpec:{baseSymbol:'A',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('A','AMPERE',tr.b.UnitPrefixScale.METRIC,'AMPERE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricPotentialInVolts',baseJsonName:'V',formatSpec:{baseSymbol:'V',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('V','VOLT',tr.b.UnitPrefixScale.METRIC,'VOLT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'frequencyInHertz',baseJsonName:'Hz',formatSpec:{baseSymbol:'Hz',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('Hz','HERTZ',tr.b.UnitPrefixScale.METRIC,'HERTZ').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'unitlessNumber',baseJsonName:'unitless',formatSpec:{minimumFractionDigits:3,maximumFractionDigits:3}});Unit.define({baseUnitName:'count',baseJsonName:'count',formatSpec:{minimumFractionDigits:0,maximumFractionDigits:0}});Unit.define({baseUnitName:'sigma',baseJsonName:'sigma',formatSpec:{baseSymbol:String.fromCharCode(963),minimumFractionDigits:1,maximumFractionDigits:1}});return{ImprovementDirection,Unit,};});'use strict';tr.exportTo('tr.b',function(){class Scalar{constructor(unit,value){if(!(unit instanceof tr.b.Unit)){throw new Error('Expected Unit');}
+const unit=new Unit(unitName,jsonName,scaleBaseUnit,isDelta,improvementDirection,params.formatSpec);Unit.byName[unitName]=unit;Unit.byJSONName[jsonName]=unit;return unit;};tr.b.EventTarget.decorate(Unit);Unit.reset();Unit.define({baseUnitName:'timeInMsAutoFormat',baseJsonName:'msBestFitFormat',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec:{unitScale:tr.b.UnitScale.TIME.AUTO,minimumFractionDigits:0,maximumFractionDigits:3}});Unit.define({baseUnitName:'timeDurationInMs',baseJsonName:'ms',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'timeStampInMs',baseJsonName:'tsMs',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'normalizedPercentage',baseJsonName:'n%',formatSpec:{unitScale:[{value:0.01,symbol:'%'}],avoidSpacePrecedingUnit:true,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'sizeInBytes',baseJsonName:'sizeInBytes',formatSpec:{unitScale:tr.b.UnitScale.MEMORY.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'bandwidthInBytesPerSecond',baseJsonName:'bytesPerSecond',formatSpec:{unitScale:tr.b.UnitScale.BANDWIDTH_BYTES.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'energyInJoules',baseJsonName:'J',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('J','JOULE',tr.b.UnitPrefixScale.METRIC,'JOULE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'powerInWatts',baseJsonName:'W',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('W','WATT',tr.b.UnitPrefixScale.METRIC,'WATT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricCurrentInAmperes',baseJsonName:'A',formatSpec:{baseSymbol:'A',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('A','AMPERE',tr.b.UnitPrefixScale.METRIC,'AMPERE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'batteryChargeInAmpereHours',baseJsonName:'Ah',formatSpec:{baseSymbol:'Ah',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('Ah','AMPEREHOUR',tr.b.UnitPrefixScale.METRIC,'AMPEREHOUR').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricPotentialInVolts',baseJsonName:'V',formatSpec:{baseSymbol:'V',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('V','VOLT',tr.b.UnitPrefixScale.METRIC,'VOLT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'frequencyInHertz',baseJsonName:'Hz',formatSpec:{baseSymbol:'Hz',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('Hz','HERTZ',tr.b.UnitPrefixScale.METRIC,'HERTZ').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'unitlessNumber',baseJsonName:'unitless',formatSpec:{minimumFractionDigits:3,maximumFractionDigits:3}});Unit.define({baseUnitName:'count',baseJsonName:'count',formatSpec:{minimumFractionDigits:0,maximumFractionDigits:0}});Unit.define({baseUnitName:'sigma',baseJsonName:'sigma',formatSpec:{baseSymbol:String.fromCharCode(963),minimumFractionDigits:1,maximumFractionDigits:1}});return{ImprovementDirection,Unit,};});'use strict';tr.exportTo('tr.b',function(){class Scalar{constructor(unit,value){if(!(unit instanceof tr.b.Unit)){throw new Error('Expected Unit');}
 if(!(typeof(value)==='number')){throw new Error('Expected value to be number');}
 this.unit=unit;this.value=value;}
 asDict(){return{unit:this.unit.asJSON(),value:tr.b.numberToJson(this.value),};}
@@ -4725,8 +4496,8 @@
 DocLinkBuilder.prototype={addAppVideo(name,videoId){this.docLinks.push({label:'Video Link',textContent:('Android Performance Patterns: '+name),href:'https://www.youtube.com/watch?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE&v='+videoId});return this;},addDacRef(name,link){this.docLinks.push({label:'Doc Link',textContent:(name+' documentation'),href:'https://developer.android.com/reference/'+link});return this;},build(){return this.docLinks;}};function AndroidAuditor(model){Auditor.call(this,model);const helper=model.getOrCreateHelper(AndroidModelHelper);if(helper.apps.length||helper.surfaceFlinger){this.helper=helper;}}
 AndroidAuditor.viewAlphaAlertInfo_=new EventInfo('Inefficient View alpha usage','Setting an alpha between 0 and 1 has significant performance costs, if one of the fast alpha paths is not used.',new DocLinkBuilder().addAppVideo('Hidden Cost of Transparency','wIy8g8yNhNk').addDacRef('View#setAlpha()','android/view/View.html#setAlpha(float)').build());AndroidAuditor.saveLayerAlertInfo_=new EventInfo('Expensive rendering with Canvas#saveLayer()','Canvas#saveLayer() incurs extremely high rendering cost. They disrupt the rendering pipeline when drawn, forcing a flush of drawing content. Instead use View hardware layers, or static Bitmaps. This enables the offscreen buffers to be reused in between frames, and avoids the disruptive render target switch.',new DocLinkBuilder().addAppVideo('Hidden Cost of Transparency','wIy8g8yNhNk').addDacRef('Canvas#saveLayerAlpha()','android/graphics/Canvas.html#saveLayerAlpha(android.graphics.RectF, int, int)').build());AndroidAuditor.getSaveLayerAlerts_=function(frame){const badAlphaRegEx=/^(.+) alpha caused (unclipped )?saveLayer (\d+)x(\d+)$/;const saveLayerRegEx=/^(unclipped )?saveLayer (\d+)x(\d+)$/;const ret=[];const events=[];frame.associatedEvents.forEach(function(slice){const match=badAlphaRegEx.exec(slice.title);if(match){const args={'view name':match[1],'width':parseInt(match[3]),'height':parseInt(match[4])};ret.push(new Alert(AndroidAuditor.viewAlphaAlertInfo_,slice.start,[slice],args));}else if(saveLayerRegEx.test(slice.title)){events.push(slice);}},this);if(events.length>ret.length){const unclippedSeen=Statistics.sum(events,function(slice){return saveLayerRegEx.exec(slice.title)[1]?1:0;});const clippedSeen=events.length-unclippedSeen;const earliestStart=Statistics.min(events,function(slice){return slice.start;});const args={'Unclipped saveLayer count (especially bad!)':unclippedSeen,'Clipped saveLayer count':clippedSeen};events.push(frame);ret.push(new Alert(AndroidAuditor.saveLayerAlertInfo_,earliestStart,events,args));}
 return ret;};AndroidAuditor.pathAlertInfo_=new EventInfo('Path texture churn','Paths are drawn with a mask texture, so when a path is modified / newly drawn, that texture must be generated and uploaded to the GPU. Ensure that you cache paths between frames and do not unnecessarily call Path#reset(). You can cut down on this cost by sharing Path object instances between drawables/views.');AndroidAuditor.getPathAlert_=function(frame){const uploadRegEx=/^Generate Path Texture$/;const events=frame.associatedEvents.filter(function(event){return event.title==='Generate Path Texture';});const start=Statistics.min(events,getStart);const duration=Statistics.sum(events,getDuration);if(duration<3)return undefined;events.push(frame);return new Alert(AndroidAuditor.pathAlertInfo_,start,events,{'Time spent':new Scalar(timeDurationInMs,duration)});};AndroidAuditor.uploadAlertInfo_=new EventInfo('Expensive Bitmap uploads','Bitmaps that have been modified / newly drawn must be uploaded to the GPU. Since this is expensive if the total number of pixels uploaded is large, reduce the amount of Bitmap churn in this animation/context, per frame.');AndroidAuditor.getUploadAlert_=function(frame){const uploadRegEx=/^Upload (\d+)x(\d+) Texture$/;const events=[];let start=Number.POSITIVE_INFINITY;let duration=0;let pixelsUploaded=0;frame.associatedEvents.forEach(function(event){const match=uploadRegEx.exec(event.title);if(match){events.push(event);start=Math.min(start,event.start);duration+=event.duration;pixelsUploaded+=parseInt(match[1])*parseInt(match[2]);}});if(events.length===0||duration<3)return undefined;const mPixels=(pixelsUploaded/1000000).toFixed(2)+' million';const args={'Pixels uploaded':mPixels,'Time spent':new Scalar(timeDurationInMs,duration)};events.push(frame);return new Alert(AndroidAuditor.uploadAlertInfo_,start,events,args);};AndroidAuditor.ListViewInflateAlertInfo_=new EventInfo('Inflation during ListView recycling','ListView item recycling involved inflating views. Ensure your Adapter#getView() recycles the incoming View, instead of constructing a new one.');AndroidAuditor.ListViewBindAlertInfo_=new EventInfo('Inefficient ListView recycling/rebinding','ListView recycling taking too much time per frame. Ensure your Adapter#getView() binds data efficiently.');AndroidAuditor.getListViewAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='obtainView'||event.title==='setupListItem';});const duration=Statistics.sum(events,getCpuDuration);if(events.length===0||duration<3)return undefined;let hasInflation=false;for(const event of events){if(event.findDescendentSlice('inflate')){hasInflation=true;}}
-const start=Statistics.min(events,getStart);const args={'Time spent':new Scalar(timeDurationInMs,duration)};args['ListView items '+(hasInflation?'inflated':'rebound')]=events.length/2;const eventInfo=hasInflation?AndroidAuditor.ListViewInflateAlertInfo_:AndroidAuditor.ListViewBindAlertInfo_;events.push(frame);return new Alert(eventInfo,start,events,args);};AndroidAuditor.measureLayoutAlertInfo_=new EventInfo('Expensive measure/layout pass','Measure/Layout took a significant time, contributing to jank. Avoid triggering layout during animations.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').build());AndroidAuditor.getMeasureLayoutAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='measure'||event.title==='layout';});const duration=Statistics.sum(events,getCpuDuration);if(events.length===0||duration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.measureLayoutAlertInfo_,start,events,{'Time spent':new Scalar(timeDurationInMs,duration)});};AndroidAuditor.viewDrawAlertInfo_=new EventInfo('Long View#draw()','Recording the drawing commands of invalidated Views took a long time. Avoid significant work in View or Drawable custom drawing, especially allocations or drawing to Bitmaps.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').addAppVideo('Avoiding Allocations in onDraw()','HAK5acHQ53E').build());AndroidAuditor.getViewDrawAlert_=function(frame){let slice=undefined;for(const event of frame.associatedEvents){if(event.title==='getDisplayList'||event.title==='Record View#draw()'){slice=event;break;}}
-if(!slice||getCpuDuration(slice)<3)return undefined;return new Alert(AndroidAuditor.viewDrawAlertInfo_,slice.start,[slice,frame],{'Time spent':new Scalar(timeDurationInMs,getCpuDuration(slice))});};AndroidAuditor.blockingGcAlertInfo_=new EventInfo('Blocking Garbage Collection','Blocking GCs are caused by object churn, and made worse by having large numbers of objects in the heap. Avoid allocating objects during animations/scrolling, and recycle Bitmaps to avoid triggering garbage collection.',new DocLinkBuilder().addAppVideo('Garbage Collection in Android','pzfzz50W5Uo').addAppVideo('Avoiding Allocations in onDraw()','HAK5acHQ53E').build());AndroidAuditor.getBlockingGcAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='DVM Suspend'||event.title==='GC: Wait For Concurrent';});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.blockingGcAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.lockContentionAlertInfo_=new EventInfo('Lock contention','UI thread lock contention is caused when another thread holds a lock that the UI thread is trying to use. UI thread progress is blocked until the lock is released. Inspect locking done within the UI thread, and ensure critical sections are short.');AndroidAuditor.getLockContentionAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return/^Lock Contention on /.test(event.title);});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<1)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.lockContentionAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.schedulingAlertInfo_=new EventInfo('Scheduling delay','Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.');AndroidAuditor.getSchedulingAlert_=function(frame){let totalDuration=0;const totalStats={};for(const ttr of frame.threadTimeRanges){const stats=ttr.thread.getSchedulingStatsForRange(ttr.start,ttr.end);for(const[key,value]of Object.entries(stats)){if(!(key in totalStats)){totalStats[key]=0;}
+const start=Statistics.min(events,getStart);const args={'Time spent':new Scalar(timeDurationInMs,duration)};args['ListView items '+(hasInflation?'inflated':'rebound')]=events.length/2;const eventInfo=hasInflation?AndroidAuditor.ListViewInflateAlertInfo_:AndroidAuditor.ListViewBindAlertInfo_;events.push(frame);return new Alert(eventInfo,start,events,args);};AndroidAuditor.measureLayoutAlertInfo_=new EventInfo('Expensive measure/layout pass','Measure/Layout took a significant time, contributing to jank. Avoid triggering layout during animations.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').build());AndroidAuditor.getMeasureLayoutAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='measure'||event.title==='layout';});const duration=Statistics.sum(events,getCpuDuration);if(events.length===0||duration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.measureLayoutAlertInfo_,start,events,{'Time spent':new Scalar(timeDurationInMs,duration)});};AndroidAuditor.viewDrawAlertInfo_=new EventInfo('Long View#dptr()','Recording the drawing commands of invalidated Views took a long time. Avoid significant work in View or Drawable custom drawing, especially allocations or drawing to Bitmaps.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').addAppVideo('Avoiding Allocations in onDptr()','HAK5acHQ53E').build());AndroidAuditor.getViewDrawAlert_=function(frame){let slice=undefined;for(const event of frame.associatedEvents){if(event.title==='getDisplayList'||event.title==='Record View#dptr()'){slice=event;break;}}
+if(!slice||getCpuDuration(slice)<3)return undefined;return new Alert(AndroidAuditor.viewDrawAlertInfo_,slice.start,[slice,frame],{'Time spent':new Scalar(timeDurationInMs,getCpuDuration(slice))});};AndroidAuditor.blockingGcAlertInfo_=new EventInfo('Blocking Garbage Collection','Blocking GCs are caused by object churn, and made worse by having large numbers of objects in the heap. Avoid allocating objects during animations/scrolling, and recycle Bitmaps to avoid triggering garbage collection.',new DocLinkBuilder().addAppVideo('Garbage Collection in Android','pzfzz50W5Uo').addAppVideo('Avoiding Allocations in onDptr()','HAK5acHQ53E').build());AndroidAuditor.getBlockingGcAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='DVM Suspend'||event.title==='GC: Wait For Concurrent';});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.blockingGcAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.lockContentionAlertInfo_=new EventInfo('Lock contention','UI thread lock contention is caused when another thread holds a lock that the UI thread is trying to use. UI thread progress is blocked until the lock is released. Inspect locking done within the UI thread, and ensure critical sections are short.');AndroidAuditor.getLockContentionAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return/^Lock Contention on /.test(event.title);});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<1)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.lockContentionAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.schedulingAlertInfo_=new EventInfo('Scheduling delay','Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.');AndroidAuditor.getSchedulingAlert_=function(frame){let totalDuration=0;const totalStats={};for(const ttr of frame.threadTimeRanges){const stats=ttr.thread.getSchedulingStatsForRange(ttr.start,ttr.end);for(const[key,value]of Object.entries(stats)){if(!(key in totalStats)){totalStats[key]=0;}
 totalStats[key]+=value;totalDuration+=value;}}
 if(!(SCHEDULING_STATE.RUNNING in totalStats)||totalDuration===0||totalDuration-totalStats[SCHEDULING_STATE.RUNNING]<3){return;}
 const args={};for(const[key,value]of Object.entries(totalStats)){let newKey=key;if(key===SCHEDULING_STATE.RUNNABLE){newKey='Not scheduled, but runnable';}else if(key===SCHEDULING_STATE.UNINTR_SLEEP){newKey='Blocking I/O delay';}
@@ -4740,7 +4511,7 @@
 if(/^hwuiTask/.test(thread.name)){thread.sortIndex=-1;}});},pushFramesAndJudgeJank_(){let badFramesObserved=0;let framesObserved=0;const surfaceFlinger=this.helper.surfaceFlinger;this.helper.apps.forEach(function(app){app.process.frames=app.getFrames();app.process.frames.forEach(function(frame){if(frame.totalDuration>EXPECTED_FRAME_TIME_MS*2){badFramesObserved+=2;frame.perfClass=FRAME_PERF_CLASS.TERRIBLE;}else if(frame.totalDuration>EXPECTED_FRAME_TIME_MS||frameMissedDeadline(frame)){badFramesObserved++;frame.perfClass=FRAME_PERF_CLASS.BAD;}else{frame.perfClass=FRAME_PERF_CLASS.GOOD;}});framesObserved+=app.process.frames.length;});if(framesObserved){const portionBad=badFramesObserved/framesObserved;if(portionBad>0.3){this.model.faviconHue='red';}else if(portionBad>0.05){this.model.faviconHue='yellow';}else{this.model.faviconHue='green';}}},pushEventInfo_(){const appAnnotator=new AppAnnotator();this.helper.apps.forEach(function(app){if(app.uiThread){appAnnotator.applyEventInfos(app.uiThread.sliceGroup);}
 if(app.renderThread){appAnnotator.applyEventInfos(app.renderThread.sliceGroup);}});},runAnnotate(){if(!this.helper)return;this.renameAndSort_();this.pushFramesAndJudgeJank_();this.pushEventInfo_();this.helper.iterateImportantSlices(function(slice){slice.important=true;});},runAudit(){if(!this.helper)return;const alerts=this.model.alerts;this.helper.apps.forEach(function(app){app.getFrames().forEach(function(frame){alerts.push.apply(alerts,AndroidAuditor.getSaveLayerAlerts_(frame));if(frame.perfClass===FRAME_PERF_CLASS.NEUTRAL||frame.perfClass===FRAME_PERF_CLASS.GOOD){return;}
 let alert=AndroidAuditor.getPathAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getUploadAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getListViewAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getMeasureLayoutAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getViewDrawAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getBlockingGcAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getLockContentionAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getSchedulingAlert_(frame);if(alert)alerts.push(alert);});},this);this.addRenderingInteractionRecords();this.addInputInteractionRecords();},addRenderingInteractionRecords(){const events=[];this.helper.apps.forEach(function(app){events.push.apply(events,app.getAnimationAsyncSlices());events.push.apply(events,app.getFrames());});const mergerFunction=function(events){const ir=new tr.model.um.ResponseExpectation(this.model,'Rendering',events[0].min,events[events.length-1].max-events[0].min);this.model.userModel.expectations.push(ir);}.bind(this);tr.b.math.mergeRanges(tr.b.math.convertEventsToRanges(events),30,mergerFunction);},addInputInteractionRecords(){const inputSamples=[];this.helper.apps.forEach(function(app){inputSamples.push.apply(inputSamples,app.getInputSamples());});const mergerFunction=function(events){const ir=new tr.model.um.ResponseExpectation(this.model,'Input',events[0].min,events[events.length-1].max-events[0].min);this.model.userModel.expectations.push(ir);}.bind(this);const inputRanges=inputSamples.map(function(sample){return tr.b.math.Range.fromExplicitRange(sample.timestamp,sample.timestamp);});tr.b.math.mergeRanges(inputRanges,30,mergerFunction);}};Auditor.register(AndroidAuditor);function AppAnnotator(){this.titleInfoLookup=new Map();this.titleParentLookup=new Map();this.build_();}
-AppAnnotator.prototype={build_(){const registerEventInfo=function(dict){this.titleInfoLookup.set(dict.title,new EventInfo(dict.title,dict.description,dict.docLinks));if(dict.parents){this.titleParentLookup.set(dict.title,dict.parents);}}.bind(this);registerEventInfo({title:'inflate',description:'Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes.'});registerEventInfo({title:'obtainView',description:'Adapter#getView() called to bind content to a recycled View that is being presented.'});registerEventInfo({title:'setupListItem',description:'Attached a newly-bound, recycled View to its parent ListView.'});registerEventInfo({title:'setupGridItem',description:'Attached a newly-bound, recycled View to its parent GridView.'});const choreographerLinks=new DocLinkBuilder().addDacRef('Choreographer','android/view/Choreographer.html').build();registerEventInfo({title:'Choreographer#doFrame',docLinks:choreographerLinks,description:'Choreographer executes frame callbacks for inputs, animations, and rendering traversals. When this work is done, a frame will be presented to the user.'});registerEventInfo({title:'input',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Input callbacks are processed. This generally encompasses dispatching input to Views, as well as any work the Views do to process this input/gesture.'});registerEventInfo({title:'animation',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Animation callbacks are processed. This is generally minimal work, as animations determine progress for the frame, and push new state to animated objects (such as setting View properties).'});registerEventInfo({title:'traversals',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Primary draw traversals. This is the primary traversal of the View hierarchy, including layout and draw passes.'});const traversalParents=['Choreographer#doFrame','performTraversals'];const layoutLinks=new DocLinkBuilder().addDacRef('View#Layout','android/view/View.html#Layout').build();registerEventInfo({title:'performTraversals',description:'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'});registerEventInfo({title:'measure',parents:traversalParents,docLinks:layoutLinks,description:'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'});registerEventInfo({title:'layout',parents:traversalParents,docLinks:layoutLinks,description:'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'});const drawString='Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.';registerEventInfo({title:'draw',parents:traversalParents,description:drawString});const recordString='Every invalidated View\'s drawing commands are recorded. Each will have View#draw() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.';registerEventInfo({title:'getDisplayList',parents:['draw'],description:recordString});registerEventInfo({title:'Record View#draw()',parents:['draw'],description:recordString});registerEventInfo({title:'drawDisplayList',parents:['draw'],description:'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU. On Android L and higher devices, this work is done on a dedicated RenderThread, instead of on the UI Thread.'});registerEventInfo({title:'DrawFrame',description:'RenderThread portion of the standard UI/RenderThread split frame. This represents the actual formation and issuing of drawing commands to the GPU.'});registerEventInfo({title:'doFrame',description:'RenderThread animation frame. Represents drawing work done by the RenderThread on a frame where the UI thread did not produce new drawing content.'});registerEventInfo({title:'syncFrameState',description:'Sync stage between the UI thread and the RenderThread, where the UI thread hands off a frame (including information about modified Views). Time in this method primarily consists of uploading modified Bitmaps to the GPU. After this sync is completed, the UI thread is unblocked, and the RenderThread starts to render the frame.'});registerEventInfo({title:'flush drawing commands',description:'Issuing the now complete drawing commands to the GPU.'});registerEventInfo({title:'eglSwapBuffers',description:'Complete GPU rendering of the frame.'});registerEventInfo({title:'RV Scroll',description:'RecyclerView is calculating a scroll. If there are too many of these in Systrace, some Views inside RecyclerView might be causing it. Try to avoid using EditText, focusable views or handle them with care.'});registerEventInfo({title:'RV OnLayout',description:'OnLayout has been called by the View system. If this shows up too many times in Systrace, make sure the children of RecyclerView do not update themselves directly. This will cause a full re-layout but when it happens via the Adapter notifyItemChanged, RecyclerView can avoid full layout calculation.'});registerEventInfo({title:'RV FullInvalidate',description:'NotifyDataSetChanged or equal has been called. If this is taking a long time, try sending granular notify adapter changes instead of just calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter might help.'});registerEventInfo({title:'RV PartialInvalidate',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV OnBindView',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV CreateView',description:'RecyclerView is creating a new View. If too many of these are present: 1) There might be a problem in Recycling (e.g. custom Animations that set transient state and prevent recycling or ItemAnimator not implementing the contract properly. See Adapter#onFailedToRecycleView(ViewHolder). 2) There may be too many item view types. Try merging them. 3) There might be too many itemChange animations and not enough space in RecyclerPool. Try increasing your pool size and item cache size.'});registerEventInfo({title:'eglSwapBuffers',description:'The CPU has finished producing drawing commands, and is flushing drawing work to the GPU, and posting that buffer to the consumer (which is often SurfaceFlinger window composition). Once this is completed, the GPU can produce the frame content without any involvement from the CPU.'});},applyEventInfosRecursive_(parentNames,slice){const checkExpectedParentNames=function(expectedParentNames){if(!expectedParentNames)return true;return expectedParentNames.some(function(name){return parentNames.has(name);});};if(this.titleInfoLookup.has(slice.title)){if(checkExpectedParentNames(this.titleParentLookup.get(slice.title))){slice.info=this.titleInfoLookup.get(slice.title);}}
+AppAnnotator.prototype={build_(){const registerEventInfo=function(dict){this.titleInfoLookup.set(dict.title,new EventInfo(dict.title,dict.description,dict.docLinks));if(dict.parents){this.titleParentLookup.set(dict.title,dict.parents);}}.bind(this);registerEventInfo({title:'inflate',description:'Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes.'});registerEventInfo({title:'obtainView',description:'Adapter#getView() called to bind content to a recycled View that is being presented.'});registerEventInfo({title:'setupListItem',description:'Attached a newly-bound, recycled View to its parent ListView.'});registerEventInfo({title:'setupGridItem',description:'Attached a newly-bound, recycled View to its parent GridView.'});const choreographerLinks=new DocLinkBuilder().addDacRef('Choreographer','android/view/Choreographer.html').build();registerEventInfo({title:'Choreographer#doFrame',docLinks:choreographerLinks,description:'Choreographer executes frame callbacks for inputs, animations, and rendering traversals. When this work is done, a frame will be presented to the user.'});registerEventInfo({title:'input',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Input callbacks are processed. This generally encompasses dispatching input to Views, as well as any work the Views do to process this input/gesture.'});registerEventInfo({title:'animation',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Animation callbacks are processed. This is generally minimal work, as animations determine progress for the frame, and push new state to animated objects (such as setting View properties).'});registerEventInfo({title:'traversals',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Primary draw traversals. This is the primary traversal of the View hierarchy, including layout and draw passes.'});const traversalParents=['Choreographer#doFrame','performTraversals'];const layoutLinks=new DocLinkBuilder().addDacRef('View#Layout','android/view/View.html#Layout').build();registerEventInfo({title:'performTraversals',description:'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'});registerEventInfo({title:'measure',parents:traversalParents,docLinks:layoutLinks,description:'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'});registerEventInfo({title:'layout',parents:traversalParents,docLinks:layoutLinks,description:'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'});const drawString='Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.';registerEventInfo({title:'draw',parents:traversalParents,description:drawString});const recordString='Every invalidated View\'s drawing commands are recorded. Each will have View#dptr() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.';registerEventInfo({title:'getDisplayList',parents:['draw'],description:recordString});registerEventInfo({title:'Record View#dptr()',parents:['draw'],description:recordString});registerEventInfo({title:'drawDisplayList',parents:['draw'],description:'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU. On Android L and higher devices, this work is done on a dedicated RenderThread, instead of on the UI Thread.'});registerEventInfo({title:'DrawFrame',description:'RenderThread portion of the standard UI/RenderThread split frame. This represents the actual formation and issuing of drawing commands to the GPU.'});registerEventInfo({title:'doFrame',description:'RenderThread animation frame. Represents drawing work done by the RenderThread on a frame where the UI thread did not produce new drawing content.'});registerEventInfo({title:'syncFrameState',description:'Sync stage between the UI thread and the RenderThread, where the UI thread hands off a frame (including information about modified Views). Time in this method primarily consists of uploading modified Bitmaps to the GPU. After this sync is completed, the UI thread is unblocked, and the RenderThread starts to render the frame.'});registerEventInfo({title:'flush drawing commands',description:'Issuing the now complete drawing commands to the GPU.'});registerEventInfo({title:'eglSwapBuffers',description:'Complete GPU rendering of the frame.'});registerEventInfo({title:'RV Scroll',description:'RecyclerView is calculating a scroll. If there are too many of these in Systrace, some Views inside RecyclerView might be causing it. Try to avoid using EditText, focusable views or handle them with care.'});registerEventInfo({title:'RV OnLayout',description:'OnLayout has been called by the View system. If this shows up too many times in Systrace, make sure the children of RecyclerView do not update themselves directly. This will cause a full re-layout but when it happens via the Adapter notifyItemChanged, RecyclerView can avoid full layout calculation.'});registerEventInfo({title:'RV FullInvalidate',description:'NotifyDataSetChanged or equal has been called. If this is taking a long time, try sending granular notify adapter changes instead of just calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter might help.'});registerEventInfo({title:'RV PartialInvalidate',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV OnBindView',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV CreateView',description:'RecyclerView is creating a new View. If too many of these are present: 1) There might be a problem in Recycling (e.g. custom Animations that set transient state and prevent recycling or ItemAnimator not implementing the contract properly. See Adapter#onFailedToRecycleView(ViewHolder). 2) There may be too many item view types. Try merging them. 3) There might be too many itemChange animations and not enough space in RecyclerPool. Try increasing your pool size and item cache size.'});registerEventInfo({title:'eglSwapBuffers',description:'The CPU has finished producing drawing commands, and is flushing drawing work to the GPU, and posting that buffer to the consumer (which is often SurfaceFlinger window composition). Once this is completed, the GPU can produce the frame content without any involvement from the CPU.'});},applyEventInfosRecursive_(parentNames,slice){const checkExpectedParentNames=function(expectedParentNames){if(!expectedParentNames)return true;return expectedParentNames.some(function(name){return parentNames.has(name);});};if(this.titleInfoLookup.has(slice.title)){if(checkExpectedParentNames(this.titleParentLookup.get(slice.title))){slice.info=this.titleInfoLookup.get(slice.title);}}
 if(slice.subSlices.length>0){if(!parentNames.has(slice.title)){parentNames.set(slice.title,0);}
 parentNames.set(slice.title,parentNames.get(slice.title)+1);slice.subSlices.forEach(function(subSlice){this.applyEventInfosRecursive_(parentNames,subSlice);},this);parentNames.set(slice.title,parentNames.get(slice.title)-1);if(parentNames.get(slice.title)===0){delete parentNames[slice.title];}}},applyEventInfos(sliceGroup){sliceGroup.topLevelSlices.forEach(function(slice){this.applyEventInfosRecursive_(new Map(),slice);},this);}};return{AndroidAuditor,};});'use strict';tr.exportTo('tr.model',function(){function ObjectSnapshot(objectInstance,ts,args){tr.model.Event.call(this);this.objectInstance=objectInstance;this.ts=ts;this.args=args;}
 ObjectSnapshot.prototype={__proto__:tr.model.Event.prototype,preInitialize(){},initialize(){},referencedAt(item,object,field){},addBoundsToRange(range){range.addValue(this.ts);},get userFriendlyName(){return'Snapshot of '+this.objectInstance.userFriendlyName+' @ '+
@@ -4808,8 +4579,8 @@
 return process.findAllThreadsNamed('CrGpuMain').length>0;};ChromeGpuHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype};return{ChromeGpuHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const NET_CATEGORIES=new Set(['net','netlog','disabled-by-default-netlog','disabled-by-default-network']);class ChromeThreadHelper{constructor(thread){this.thread=thread;}
 getNetworkEvents(){const networkEvents=[];for(const slice of this.thread.asyncSliceGroup.slices){const categories=tr.b.getCategoryParts(slice.category);const isNetEvent=category=>NET_CATEGORIES.has(category);if(categories.filter(isNetEvent).length===0)continue;networkEvents.push(slice);}
 return networkEvents;}}
-return{ChromeThreadHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const ChromeThreadHelper=tr.model.helpers.ChromeThreadHelper;function ChromeRendererHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain')||process.findAtMostOneThreadNamed('Chrome_InProcRendererThread');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)return false;if(t.name.startsWith('CompositorTileWorker'))return true;if(t.name.startsWith('CompositorRasterWorker'))return true;return false;});this.dedicatedWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('DedicatedWorker');});this.foregroundWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ThreadPoolForegroundWorker');});if(!process.name){process.name=ChromeRendererHelper.PROCESS_NAME;}}
-ChromeRendererHelper.PROCESS_NAME='Renderer';ChromeRendererHelper.isRenderProcess=function(process){if(process.findAtMostOneThreadNamed('CrRendererMain'))return true;if(process.findAtMostOneThreadNamed('Compositor'))return true;return false;};ChromeRendererHelper.isTracingProcess=function(process){return process.labels!==undefined&&process.labels.length===1&&process.labels[0]==='chrome://tracing';};ChromeRendererHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;},get dedicatedWorkerThreads(){return this.dedicatedWorkerThreads_;},get foregroundWorkerThreads(){return this.foregroundWorkerThreads_;},get isChromeTracingUI(){return ChromeRendererHelper.isTracingProcess(this.process);},};return{ChromeRendererHelper,};});'use strict';tr.exportTo('tr.model.um',function(){class Segment extends tr.model.TimedEvent{constructor(start,duration){super(start);this.duration=duration;this.expectations_=[];}
+return{ChromeThreadHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const ChromeThreadHelper=tr.model.helpers.ChromeThreadHelper;function ChromeRendererHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain')||process.findAtMostOneThreadNamed('Chrome_InProcRendererThread');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)return false;if(t.name.startsWith('CompositorTileWorker'))return true;if(t.name.startsWith('CompositorRasterWorker'))return true;return false;});this.dedicatedWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('DedicatedWorker');});this.serviceWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ServiceWorker');});this.foregroundWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ThreadPoolForegroundWorker');});if(!process.name){process.name=ChromeRendererHelper.PROCESS_NAME;}}
+ChromeRendererHelper.PROCESS_NAME='Renderer';ChromeRendererHelper.isRenderProcess=function(process){if(process.findAtMostOneThreadNamed('CrRendererMain'))return true;if(process.findAtMostOneThreadNamed('Compositor'))return true;return false;};ChromeRendererHelper.isTracingProcess=function(process){return process.labels!==undefined&&process.labels.length===1&&process.labels[0]==='chrome://tracing';};ChromeRendererHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;},get dedicatedWorkerThreads(){return this.dedicatedWorkerThreads_;},get serviceWorkerThreads(){return this.serviceWorkerThreads_;},get foregroundWorkerThreads(){return this.foregroundWorkerThreads_;},get isChromeTracingUI(){return ChromeRendererHelper.isTracingProcess(this.process);},};return{ChromeRendererHelper,};});'use strict';tr.exportTo('tr.model.um',function(){class Segment extends tr.model.TimedEvent{constructor(start,duration){super(start);this.duration=duration;this.expectations_=[];}
 get expectations(){return this.expectations_;}
 clone(){const clone=new Segment(this.start,this.duration);clone.expectations.push(...this.expectations);return clone;}
 addSegment(other){this.duration+=other.duration;this.expectations.push(...other.expectations);}}
@@ -4869,7 +4640,7 @@
 for(const category of Object.values(USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY)){ChromeUserFriendlyCategoryDriver.ALL_TITLES.push(category);}
 ChromeUserFriendlyCategoryDriver.ALL_TITLES.sort();for(const category of ChromeUserFriendlyCategoryDriver.ALL_TITLES){ChromeUserFriendlyCategoryDriver.getColor(category);}
 return{ChromeUserFriendlyCategoryDriver,};});'use strict';tr.exportTo('tr.model',function(){return{BROWSER_PROCESS_PID_REF:-1,OBJECT_DEFAULT_SCOPE:'ptr',LOCAL_ID_PHASES:new Set(['N','D','O','(',')'])};});'use strict';tr.exportTo('tr.e.audits',function(){const Auditor=tr.c.Auditor;const Alert=tr.model.Alert;const EventInfo=tr.model.EventInfo;function ChromeAuditor(model){Auditor.call(this,model);const modelHelper=this.model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper&&modelHelper.browserHelper){this.modelHelper=modelHelper;}else{this.modelHelper=undefined;}}
-function getMissedFrameAlerts(rendererHelpers){const alerts=[];for(const rendererHelper of rendererHelpers){if(!rendererHelper.compositorThread)continue;const thread=rendererHelper.compositorThread;const asyncSlices=Object.values(thread.asyncSliceGroup.slices);for(const slice of asyncSlices){if(slice.title!=='PipelineReporter'||!slice.args.termination_status||slice.args.termination_status!=='missed_frame')continue;const alertSlices=[slice].concat(slice.subSlices);alerts.push(new Alert(new EventInfo('Missed Frame','Frame was not submitted before deadline.'),slice.start,alertSlices));}}
+function getMissedFrameAlerts(rendererHelpers){const alerts=[];for(const rendererHelper of rendererHelpers){if(!rendererHelper.compositorThread)continue;const thread=rendererHelper.compositorThread;const asyncSlices=Object.values(thread.asyncSliceGroup.slices);for(const slice of asyncSlices){if(slice.title==='PipelineReporter'&&slice.args.chrome_frame_reporter&&slice.args.chrome_frame_reporter.state==='STATE_DROPPED'){const alertSlices=[slice].concat(slice.subSlices);alerts.push(new Alert(new EventInfo('Dropped Frame','Frame was dropped (i.e. not produced/presented).'),slice.start,alertSlices));}}}
 return alerts;}
 ChromeAuditor.prototype={__proto__:Auditor.prototype,runAnnotate(){if(!this.modelHelper)return;for(const pid in this.modelHelper.rendererHelpers){const rendererHelper=this.modelHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI){rendererHelper.process.important=false;}}},installUserFriendlyCategoryDriverIfNeeded(){this.model.addUserFriendlyCategoryDriver(tr.e.chrome.ChromeUserFriendlyCategoryDriver);},runAudit(){if(!this.modelHelper)return;this.model.replacePIDRefsInPatchups(tr.model.BROWSER_PROCESS_PID_REF,this.modelHelper.browserProcess.pid);this.model.applyObjectRefPatchups();const alerts=getMissedFrameAlerts(Object.values(this.modelHelper.rendererHelpers));this.model.alerts=this.model.alerts.concat(alerts);}};Auditor.register(ChromeAuditor);return{ChromeAuditor,};});'use strict';tr.exportTo('tr.e.chrome',function(){const KNOWN_PROPERTIES={absX:1,absY:1,address:1,anonymous:1,childNeeds:1,children:1,classNames:1,col:1,colSpan:1,float:1,height:1,htmlId:1,name:1,posChildNeeds:1,positioned:1,positionedMovement:1,relX:1,relY:1,relativePositioned:1,row:1,rowSpan:1,selfNeeds:1,stickyPositioned:1,tag:1,width:1};function LayoutObject(snapshot,args){this.snapshot_=snapshot;this.id_=args.address;this.name_=args.name;this.childLayoutObjects_=[];this.otherProperties_={};this.tag_=args.tag;this.relativeRect_=tr.b.math.Rect.fromXYWH(args.relX,args.relY,args.width,args.height);this.absoluteRect_=tr.b.math.Rect.fromXYWH(args.absX,args.absY,args.width,args.height);this.isFloat_=args.float;this.isStickyPositioned_=args.stickyPositioned;this.isPositioned_=args.positioned;this.isRelativePositioned_=args.relativePositioned;this.isAnonymous_=args.anonymous;this.htmlId_=args.htmlId;this.classNames_=args.classNames;this.needsLayoutReasons_=[];if(args.selfNeeds){this.needsLayoutReasons_.push('self');}
 if(args.childNeeds){this.needsLayoutReasons_.push('child');}
@@ -5033,7 +4804,8 @@
 if(markers[0].domainId===domainId){throw new Error('A clock domain cannot sync with itself.');}
 markers.push(marker);this.onSyncCompleted_(markers[0],marker);},get completeSyncIds(){const completeSyncIds=[];for(const[syncId,markers]of this.markersBySyncId){if(markers.length===2)completeSyncIds.push(syncId);}
 return completeSyncIds;},get markersBySyncId(){return this.markersBySyncId_;},get domainsSeen(){return this.domainsSeen_;},getModelTimeTransformer(domainId){this.onDomainSeen_(domainId);if(!this.modelDomainId_){this.selectModelDomainId_();}
-return this.getTimeTransformerRaw_(domainId,this.modelDomainId_).fn;},getTimeTransformerError(fromDomainId,toDomainId){this.onDomainSeen_(fromDomainId);this.onDomainSeen_(toDomainId);return this.getTimeTransformerRaw_(fromDomainId,toDomainId).error;},getTimeTransformerRaw_(fromDomainId,toDomainId){const transformer=this.getTransformerBetween_(fromDomainId,toDomainId);if(!transformer){throw new Error('No clock sync markers exist pairing clock domain "'+
+return this.getTimeTransformerRaw_(domainId,this.modelDomainId_).fn;},getModelTimeTransformerInverse(domainId){this.onDomainSeen_(domainId);if(!this.modelDomainId_){this.selectModelDomainId_();}
+return this.getTimeTransformerRaw_(this.modelDomainId_,domainId).fn;},getTimeTransformerError(fromDomainId,toDomainId){this.onDomainSeen_(fromDomainId);this.onDomainSeen_(toDomainId);return this.getTimeTransformerRaw_(fromDomainId,toDomainId).error;},getTimeTransformerRaw_(fromDomainId,toDomainId){const transformer=this.getTransformerBetween_(fromDomainId,toDomainId);if(!transformer){throw new Error('No clock sync markers exist pairing clock domain "'+
 fromDomainId+'" '+'with target clock domain "'+
 toDomainId+'".');}
 return transformer;},getTransformerBetween_(fromDomainId,toDomainId){const visitedDomainIds=new Set();const queue=[{domainId:fromDomainId,transformer:Transformer.IDENTITY}];while(queue.length>0){queue.sort((domain1,domain2)=>domain1.transformer.error-domain2.transformer.error);const current=queue.shift();if(current.domainId===toDomainId){return current.transformer;}
@@ -5388,7 +5160,8 @@
 for(const event of this.childEvents()){event.start+=shiftAmount;}
 this.updateBounds();},convertTimestampToModelTime(sourceClockDomainName,ts){if(sourceClockDomainName!=='traceEventClock'){throw new Error('Only traceEventClock is supported.');}
 return tr.b.Unit.timestampFromUs(ts)+
-this.timestampShiftToZeroAmount_;},get numProcesses(){let n=0;for(const p in this.processes){n++;}
+this.timestampShiftToZeroAmount_;},convertTimestampFromModelTime(targetClockDomainName,ts){if(targetClockDomainName!=='traceEventClock'){throw new Error('Only traceEventClock is supported.');}
+const convertFn=this.clockSyncManager.getModelTimeTransformerInverse(tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL);return convertFn(ts)-this.timestampShiftToZeroAmount_;},get numProcesses(){let n=0;for(const p in this.processes){n++;}
 return n;},getProcess(pid){return this.processes[pid];},getOrCreateProcess(pid){if(!this.processes[pid]){this.processes[pid]=new Process(this,pid);}
 return this.processes[pid];},addStackFrame(stackFrame){if(this.stackFrames[stackFrame.id]){throw new Error('Stack frame already exists');}
 this.stackFrames[stackFrame.id]=stackFrame;return stackFrame;},updateCategories_(){const categoriesDict={};this.userModel.addCategoriesToDict(categoriesDict);this.device.addCategoriesToDict(categoriesDict);this.kernel.addCategoriesToDict(categoriesDict);for(const pid in this.processes){this.processes[pid].addCategoriesToDict(categoriesDict);}
@@ -5800,7 +5573,7 @@
 class ProfilingDictionaryReader{constructor(opt_metadata,opt_maps,opt_groups,opt_parent){this.metadata=opt_metadata||new Map();this.maps=opt_maps||new Map();this.groups=opt_groups||new Map();this.parent_=opt_parent||undefined;this.inflated_=undefined;this.raw_=undefined;this.boundGetString_=this.getString.bind(this);this.deferenceStrings_=o=>deferenceStrings(this.boundGetString_,o);}
 static empty(){return new ProfilingDictionaryReader();}
 get parent(){return this.parent_;}
-get raw(){if(this.raw_)return this.raw_;this.raw_={};for(const[name,group]of this.groups.entries()){this.raw_[name]=group;}
+get ptr(){if(this.raw_)return this.raw_;this.raw_={};for(const[name,group]of this.groups.entries()){this.raw_[name]=group;}
 return this.raw_;}
 get inflated(){if(this.inflated_)return this.inflated_;this.inflated_={};for(const[name,group]of this.groups.entries()){this.inflated_[name]=this.inflateGroup(group);}
 return this.inflated_;}
@@ -5878,7 +5651,7 @@
 XMarkerAnnotationView.prototype={__proto__:tr.ui.annotations.AnnotationView.prototype,draw(ctx){const dt=this.viewport_.currentDisplayTransform;const viewX=dt.xWorldToView(this.annotation_.timestamp);ctx.beginPath();tr.ui.b.drawLine(ctx,viewX,0,viewX,ctx.canvas.height);ctx.strokeStyle=this.annotation_.strokeStyle;ctx.stroke();}};return{XMarkerAnnotationView,};});'use strict';tr.exportTo('tr.model',function(){function XMarkerAnnotation(timestamp){tr.model.Annotation.apply(this,arguments);this.timestamp=timestamp;this.strokeStyle='rgba(0, 0, 255, 0.5)';}
 XMarkerAnnotation.fromDict=function(dict){return new XMarkerAnnotation(dict.args.timestamp);};XMarkerAnnotation.prototype={__proto__:tr.model.Annotation.prototype,toDict(){return{typeName:'xmarker',args:{timestamp:this.timestamp}};},createView_(viewport){return new tr.ui.annotations.XMarkerAnnotationView(viewport,this);}};tr.model.Annotation.register(XMarkerAnnotation,{typeName:'xmarker'});return{XMarkerAnnotation,};});'use strict';tr.exportTo('tr.e.importer',function(){const Base64=tr.b.Base64;const deepCopy=tr.b.deepCopy;const ColorScheme=tr.b.ColorScheme;const HeapDumpTraceEventImporter=tr.e.importer.HeapDumpTraceEventImporter;const LegacyHeapDumpTraceEventImporter=tr.e.importer.LegacyHeapDumpTraceEventImporter;const StreamingEventExpander=tr.e.importer.StreamingEventExpander;const ProfilingDictionaryReader=tr.e.importer.ProfilingDictionaryReader;const MEASURE_NAME_REGEX=tr.e.measure.MEASURE_NAME_REGEX;function getEventColor(event,opt_customName){if(event.cname){return ColorScheme.getColorIdForReservedName(event.cname);}else if(opt_customName||event.name){return ColorScheme.getColorIdForGeneralPurposeString(opt_customName||event.name);}}
 function isLegacyChromeClockSyncEvent(event){return event.name!==undefined&&event.name.startsWith(LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX)&&((event.ph==='S')||(event.ph==='F'));}
-const PRODUCER='producer';const CONSUMER='consumer';const STEP='step';const BACKGROUND=tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;const LIGHT=tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;const DETAILED=tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;const MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER=[undefined,BACKGROUND,LIGHT,DETAILED];const GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX='global/';const LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX='ClockSyncEvent.';const BYTE_STAT_NAME_MAP={'pc':'privateCleanResident','pd':'privateDirtyResident','sc':'sharedCleanResident','sd':'sharedDirtyResident','pss':'proportionalResident','sw':'swapped'};const WEAK_MEMORY_ALLOCATOR_DUMP_FLAG=1<<0;const OBJECT_TYPE_NAME_PATTERNS=[{prefix:'const char *WTF::getStringWithTypeName() [T = ',suffix:']'},{prefix:'const char* WTF::getStringWithTypeName() [with T = ',suffix:']'},{prefix:'const char *__cdecl WTF::getStringWithTypeName<',suffix:'>(void)'}];const SUBTRACE_FIELDS=new Set(['powerTraceAsString','systemTraceEvents','androidProcessDump',]);const NON_METADATA_FIELDS=new Set(['displayTimeUnit','samples','stackFrames','traceAnnotations','traceEvents',...SUBTRACE_FIELDS]);function TraceEventImporter(model,eventData){this.hasEvents_=undefined;this.importPriority=1;this.model_=model;this.events_=undefined;this.sampleEvents_=undefined;this.stackFrameEvents_=undefined;this.stackFrameTree_=new tr.model.ProfileTree();this.subtraces_=[];this.eventsWereFromString_=false;this.softwareMeasuredCpuCount_=undefined;this.allAsyncEvents_=[];this.allFlowEvents_=[];this.allObjectEvents_=[];this.contextProcessorPerThread={};this.traceEventSampleStackFramesByName_={};this.v8ProcessCodeMaps_={};this.v8ProcessRootStackFrame_={};this.v8SamplingData_=[];this.profileTrees_=new Map();this.profileInfo_=new Map();this.legacyChromeClockSyncStartEvent_=undefined;this.legacyChromeClockSyncFinishEvent_=undefined;this.allMemoryDumpEvents_={};this.heapProfileExpander=new ProfilingDictionaryReader();this.objectTypeNameMap_={};this.clockDomainId_=tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;this.toModelTime_=undefined;if(typeof(eventData)==='string'||eventData instanceof String){eventData=eventData.trim();if(eventData[0]==='['){eventData=eventData.replace(/\s*,\s*$/,'');if(eventData[eventData.length-1]!==']'){eventData=eventData+']';}}
+const PRODUCER='producer';const CONSUMER='consumer';const STEP='step';const BACKGROUND=tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;const LIGHT=tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;const DETAILED=tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;const MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER=[undefined,BACKGROUND,LIGHT,DETAILED];const GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX='global/';const LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX='ClockSyncEvent.';const BYTE_STAT_NAME_MAP={'pc':'privateCleanResident','pd':'privateDirtyResident','sc':'sharedCleanResident','sd':'sharedDirtyResident','pss':'proportionalResident','sw':'swapped'};const WEAK_MEMORY_ALLOCATOR_DUMP_FLAG=1<<0;const OBJECT_TYPE_NAME_PATTERNS=[{prefix:'const char *WTF::getStringWithTypeName() [T = ',suffix:']'},{prefix:'const char* WTF::getStringWithTypeName() [with T = ',suffix:']'},{prefix:'const char *__cdecl WTF::getStringWithTypeName<',suffix:'>(void)'}];const SUBTRACE_FIELDS=new Set(['powerTraceAsString','systemTraceEvents','androidProcessDump','cgroupDump',]);const NON_METADATA_FIELDS=new Set(['displayTimeUnit','samples','stackFrames','traceAnnotations','traceEvents',...SUBTRACE_FIELDS]);function TraceEventImporter(model,eventData){this.hasEvents_=undefined;this.importPriority=1;this.model_=model;this.events_=undefined;this.sampleEvents_=undefined;this.stackFrameEvents_=undefined;this.stackFrameTree_=new tr.model.ProfileTree();this.subtraces_=[];this.eventsWereFromString_=false;this.softwareMeasuredCpuCount_=undefined;this.allAsyncEvents_=[];this.allFlowEvents_=[];this.allObjectEvents_=[];this.contextProcessorPerThread={};this.traceEventSampleStackFramesByName_={};this.v8ProcessCodeMaps_={};this.v8ProcessRootStackFrame_={};this.v8SamplingData_=[];this.profileTrees_=new Map();this.profileInfo_=new Map();this.legacyChromeClockSyncStartEvent_=undefined;this.legacyChromeClockSyncFinishEvent_=undefined;this.allMemoryDumpEvents_={};this.heapProfileExpander=new ProfilingDictionaryReader();this.objectTypeNameMap_={};this.clockDomainId_=tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;this.toModelTime_=undefined;if(typeof(eventData)==='string'||eventData instanceof String){eventData=eventData.trim();if(eventData[0]==='['){eventData=eventData.replace(/\s*,\s*$/,'');if(eventData[eventData.length-1]!==']'){eventData=eventData+']';}}
 this.events_=JSON.parse(eventData);this.eventsWereFromString_=true;}else{this.events_=eventData;}
 if(this.events_.traceEvents){const container=this.events_;this.events_=this.events_.traceEvents;for(const subtraceField of SUBTRACE_FIELDS){if(container[subtraceField]){this.storeSubtrace_(container[subtraceField]);}}
 this.storeSamples_(container.samples);this.storeStackFrames_(container.stackFrames);this.storeDisplayTimeUnit_(container.displayTimeUnit);this.storeTraceAnnotations_(container.traceAnnotations);this.storeMetadata_(container);}else if(this.events_ instanceof tr.b.TraceStream){const parser=oboe().node('{cat ph}',function(e){return oboe.drop;}).node('!.powerTraceAsString',this.storeSubtrace_.bind(this)).node('!.systemTraceEvents',this.storeSubtrace_.bind(this)).node('!.samples',this.storeSamples_.bind(this)).node('!.stackFrames',this.storeStackFrames_.bind(this)).node('!.displayTimeUnit',this.storeDisplayTimeUnit_.bind(this)).node('!.traceAnnotations',this.storeTraceAnnotations_.bind(this)).done(this.storeMetadata_.bind(this));this.events_.rewind();while(this.events_.hasData){parser.write(this.events_.readNumBytes());}
@@ -5917,10 +5690,10 @@
 const profileTree=new tr.model.ProfileTree();profileTreeMap.set(id,profileTree);const info=this.profileInfo_.get(id);if(info!==undefined){profileTree.startTime=info.startTime;profileTree.pid=info.pid;profileTree.tid=info.tid;}
 return profileTree;},processSample(event){if(event.args===undefined||event.args.data===undefined){return;}
 if(event.id===undefined){throw new Error('No event ID in sample');}
-const data=event.args.data;if(data.startTime!==undefined){this.profileInfo_.set(event.id,{startTime:data.startTime,pid:event.pid,tid:event.tid});}
+const data=event.args.data;if(data.startTime!==undefined){this.profileInfo_.set(`${event.pid} ${event.id}`,{startTime:data.startTime,pid:event.pid,tid:event.tid});}
 const timeDeltas=data.timeDeltas;for(const sampleType in data){if(sampleType==='timeDeltas'||sampleType==='startTime'){continue;}
 if(data[sampleType].samples&&timeDeltas&&data[sampleType].samples.length!==timeDeltas.length){throw new Error('samples and timeDeltas array should have same length');}
-const profileTree=this.getOrCreateProfileTree_(sampleType,event.id);const nodes=data[sampleType].nodes;const samples=data[sampleType].samples;if(nodes!==undefined){for(const node of nodes){const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);const profileNode=ProfileNodeType.constructFromObject(profileTree,node);if(profileNode===undefined){continue;}
+const profileTree=this.getOrCreateProfileTree_(sampleType,`${event.pid} ${event.id}`);const nodes=data[sampleType].nodes;const samples=data[sampleType].samples;if(nodes!==undefined){for(const node of nodes){const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);const profileNode=ProfileNodeType.constructFromObject(profileTree,node);if(profileNode===undefined){continue;}
 profileTree.add(profileNode);}}
 if(samples!==undefined){const thread=this.model_.getOrCreateProcess(profileTree.pid).getOrCreateThread(profileTree.tid);for(let i=0,len=samples.length;i<len;++i){const node=profileTree.getNode(samples[i]);profileTree.endTime+=timeDeltas[i];if(node===undefined)continue;const start=this.toModelTimeFromUs_(profileTree.endTime);this.model_.samples.push(new tr.model.Sample(start,node.sampleTitle,node,thread));}}}},processLegacyV8Sample(event){const data=event.args.data;const sampleType='legacySample';const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);if(data.vm_state==='js'&&!data.stack.length)return;const profileTree=this.getOrCreateProfileTree_(sampleType,event.pid);if(profileTree.getNode(-1)===undefined){profileTree.add(new ProfileNodeType(-1,{url:'',scriptId:-1,functionName:'unknown'},undefined));}
 let node=undefined;if(data.stack.length>0&&this.v8ProcessCodeMaps_[event.pid]){const map=this.v8ProcessCodeMaps_[event.pid];data.stack.reverse();let parentNode=undefined;for(let i=0;i<data.stack.length;i++){const entry=map.lookupEntry(data.stack[i]);if(entry===undefined){node=profileTree.getNode(-1);}else{node=profileTree.getNode(entry.id);if(node===undefined){const sourceInfo=entry.sourceInfo;node=new ProfileNodeType(entry.id,{functionName:entry.name,url:entry.sourceInfo.file,lineNumber:sourceInfo.line!==-1?sourceInfo.line:undefined,columnNumber:sourceInfo.column!==-1?sourceInfo.column:undefined,scriptid:entry.sourceInfo.scriptId},parentNode);profileTree.add(node);}}
@@ -6298,9 +6071,12 @@
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addL2Cycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.l2Sample(hwcTitle,'cycles',ts,eventBase);}
 this.importer.registerEventHandler(hwcEventName,handler.bind(this));}};Parser.register(MaliParser);return{MaliParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function MemReclaimParser(importer){Parser.call(this,importer);importer.registerEventHandler('mm_vmscan_kswapd_wake',MemReclaimParser.prototype.kswapdWake.bind(this));importer.registerEventHandler('mm_vmscan_kswapd_sleep',MemReclaimParser.prototype.kswapdSleep.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_begin',MemReclaimParser.prototype.reclaimBegin.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_end',MemReclaimParser.prototype.reclaimEnd.bind(this));importer.registerEventHandler('lowmemory_kill',MemReclaimParser.prototype.lowmemoryKill.bind(this));}
 const kswapdWakeRE=/nid=(\d+) order=(\d+)/;const kswapdSleepRE=/nid=(\d+)/;const reclaimBeginRE=/order=(\d+) may_writepage=\d+ gfp_flags=(.+)/;const reclaimEndRE=/nr_reclaimed=(\d+)/;const lowmemoryRE=/([^ ]+) \((\d+)\), page cache (\d+)kB \(limit (\d+)kB\), free (-?\d+)Kb/;MemReclaimParser.prototype={__proto__:Parser.prototype,kswapdWake(eventName,cpuNumber,pid,ts,eventBase){const event=kswapdWakeRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const nid=parseInt(event[1]);const order=parseInt(event[2]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS){if(order>kthread.order){kthread.order=order;}}else{kthread.openSliceTS=ts;kthread.order=order;}
-return true;},kswapdSleep(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim',eventBase.threadName,kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order});}
-kthread.openSliceTS=undefined;kthread.order=undefined;return true;},reclaimBegin(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimBeginRE.exec(eventBase.details);if(!event)return false;const order=parseInt(event[1]);const gfp=event[2];const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.openSliceTS=ts;kthread.order=order;kthread.gfp=gfp;return true;},reclaimEnd(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimEndRE.exec(eventBase.details);if(!event)return false;const nrReclaimed=parseInt(event[1]);const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS!==undefined){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim','direct reclaim',kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order,gfp:kthread.gfp,nr_reclaimed:nrReclaimed});}
-kthread.openSliceTS=undefined;kthread.order=undefined;kthread.gfp=undefined;return true;},lowmemoryKill(eventName,cpuNumber,pid,ts,eventBase){const event=lowmemoryRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const killedName=event[1];const killedPid=parseInt(event[2]);const cache=parseInt(event[3]);const free=parseInt(event[5]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.thread.sliceGroup.pushCompleteSlice('lowmemory','low memory kill',ts,0,0,0,{killed_name:killedName,killed_pid:killedPid,cache,free});return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency_limits',PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));}
+kthread.waitingFor='kswapSleep';return true;},kswapdSleep(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.waitingFor!=='kswapSleep')return false;kthread.waitingFor=undefined;if(kthread.openSliceTS){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim',eventBase.threadName,kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order});}
+kthread.openSliceTS=undefined;kthread.order=undefined;return true;},reclaimBegin(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimBeginRE.exec(eventBase.details);if(!event)return false;const order=parseInt(event[1]);const gfp=event[2];const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.openMemReclaimSliceTS=ts;kthread.order=order;kthread.gfp=gfp;kthread.waitingFor='reclaimEnd';return true;},reclaimEnd(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimEndRE.exec(eventBase.details);if(!event)return false;const nrReclaimed=parseInt(event[1]);const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.waitingFor!=='reclaimEnd')return false;kthread.waitingFor=undefined;if(kthread.openMemReclaimSliceTS!==undefined){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim','direct reclaim',kthread.openMemReclaimSliceTS,ts-kthread.openMemReclaimSliceTS,0,0,{order:kthread.order,gfp:kthread.gfp,nr_reclaimed:nrReclaimed});kthread.openMemReclaimSliceTS=undefined;kthread.order=undefined;kthread.gfp=undefined;return true;}
+return false;},lowmemoryKill(eventName,cpuNumber,pid,ts,eventBase){const event=lowmemoryRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const killedName=event[1];const killedPid=parseInt(event[2]);const cache=parseInt(event[3]);const free=parseInt(event[5]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.thread.sliceGroup.pushCompleteSlice('lowmemory','low memory kill',ts,0,0,0,{killed_name:killedName,killed_pid:killedPid,cache,free});return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function MSMParser(importer){Parser.call(this,importer);importer.registerEventHandler('msm_gpu_freq_change',MSMParser.prototype.gpuFrequency.bind(this));importer.registerEventHandler('msm_gpu_submit_flush',MSMParser.prototype.gpuSubmitFlush.bind(this));importer.registerEventHandler('msm_gpu_submit_retired',MSMParser.prototype.gpuSubmitRetired.bind(this));this.model_=importer.model_;this.submits={};this.num_submits=0;}
+MSMParser.prototype={__proto__:Parser.prototype,gpuFrequency(eventName,cpuNumber,pid,ts,eventBase){const event=/new_freq=(\d+)/.exec(eventBase.details);if(!event)return false;const freq=parseInt(event[1]);const counter=this.model_.kernel.getOrCreateCounter('GPU','GPU Frequency');if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries('frequency',ColorScheme.getColorIdForGeneralPurposeString(counter.name)));}
+counter.series.forEach(function(series){series.addCounterSample(ts,freq);});return true;},gpuSubmitFlush(eventName,cpuNumber,pid,ts,eventBase){const event=/id=(\d+) pid=(\d+) ring=(\d+):(\d+) ticks=(\d+)/.exec(eventBase.details);if(!event)return false;const id=parseInt(event[1]);const submit={};submit.flushTS=ts;submit.flushTicks=parseInt(event[5]);submit.pid=parseInt(event[2]);this.submits[id]=submit;this.num_submits++;return true;},gpuSubmitRetired(eventName,cpuNumber,pid,ts,eventBase){const event=/id=(\d+) pid=(\d+) ring=(\d+):(\d+) elapsed=(\d+) ns mhz=(\d+) start=(\d+) end=(\d+)/.exec(eventBase.details);if(!event)return false;const id=parseInt(event[1]);if(!(id in this.submits))return true;const submit=this.submits[id];delete this.submits[id];this.num_submits--;const gpuThread=this.importer.getOrCreatePseudoThread('GPU');submit.elapsedNs=parseInt(event[5]);submit.mhz=parseInt(event[6]);submit.startTicks=parseInt(event[7]);submit.endTicks=parseInt(event[8]);function ticks2ms(ticks){return ticks/19200;}
+const queuedDuration=ticks2ms(submit.startTicks-submit.flushTicks);const runningDuration=ticks2ms(submit.endTicks-submit.startTicks);submit.queuedDuration=queuedDuration;submit.runningDuration=runningDuration;const queued=new tr.model.AsyncSlice('',event[1]+' queued',tr.b.ColorScheme.getColorIdForReservedName('thread_state_runnable'),submit.flushTS,submit,queuedDuration);const running=new tr.model.AsyncSlice('',event[1]+' running',tr.b.ColorScheme.getColorIdForReservedName('thread_state_running'),submit.flushTS+queuedDuration,submit,runningDuration);const async=new tr.model.AsyncSlice('','pipeline',ColorScheme.getColorIdForGeneralPurposeString('ongpu:'+submit.pid),submit.flushTS,submit,queuedDuration+runningDuration);async.hidden=true;async.subSlices.push(queued);async.subSlices.push(running);gpuThread.thread.asyncSliceGroup.push(async);const onGpu=new tr.model.ThreadSlice('',event[1],ColorScheme.getColorIdForGeneralPurposeString('ongpu:'+submit.pid),submit.flushTS+queuedDuration,submit,runningDuration);gpuThread.thread.sliceGroup.pushSlice(onGpu);return true;}};Parser.register(MSMParser);return{MSMParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency_limits',PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));}
 PowerParser.prototype={__proto__:Parser.prototype,cpuStateSlice(ts,targetCpuNumber,eventType,cpuState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);if(eventType!=='1'){this.importer.model.importWarning({type:'parse_error',message:'Don\'t understand power_start events of '+'type '+eventType});return;}
 const powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));}
 powerCounter.series.forEach(function(series){series.addCounterSample(ts,cpuState);});},cpuIdleSlice(ts,targetCpuNumber,cpuState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);const powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name)));}
@@ -6322,7 +6098,9 @@
 thread.lastActiveTs=ts;thread.lastActiveValue=event[2];return true;},syncWaitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=syncWaitRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
 const tgid=parseInt(eventBase.tgid);const thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;const slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
 const name='fence_wait("'+event[2]+'")';if(event[1]==='begin'){const slice=slices.beginSlice(null,name,ts,{'Start state':event[3]});}else if(event[1]==='end'){if(slices.openSliceCount>0){slices.endSlice(ts);}}else{return false;}
-return true;},syncPtEvent(eventName,cpuNumber,pid,ts,eventBase){return!!syncPtRE.exec(eventBase.details);}};Parser.register(SyncParser);return{SyncParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function WorkqueueParser(importer){Parser.call(this,importer);importer.registerEventHandler('workqueue_execute_start',WorkqueueParser.prototype.executeStartEvent.bind(this));importer.registerEventHandler('workqueue_execute_end',WorkqueueParser.prototype.executeEndEvent.bind(this));importer.registerEventHandler('workqueue_queue_work',WorkqueueParser.prototype.executeQueueWork.bind(this));importer.registerEventHandler('workqueue_activate_work',WorkqueueParser.prototype.executeActivateWork.bind(this));}
+return true;},syncPtEvent(eventName,cpuNumber,pid,ts,eventBase){return!!syncPtRE.exec(eventBase.details);}};Parser.register(SyncParser);return{SyncParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function ThermalParser(importer){Parser.call(this,importer);importer.registerEventHandler('thermal_temperature',ThermalParser.prototype.traceMarkWriteTemperatureEvent.bind(this));importer.registerEventHandler('cdev_update',ThermalParser.prototype.traceMarkWriteCdevEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+ThermalParser.prototype={__proto__:Parser.prototype,thermalMark(name,subName,value,ts){const ctr=this.model_.kernel.getOrCreateCounter(null,name+' '+subName);if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,value);});},traceMarkWriteTemperatureEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/thermal_zone=(\S+) id=(\d+) temp_prev=(\d+) temp=(\d+)/.exec(eventBase.details);const name=event[1];const temp=parseInt(event[4]);this.thermalMark(name,'Temperature',temp,ts);return true;},traceMarkWriteCdevEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/type=(\S+) target=(\d+)/.exec(eventBase.details);const name=event[1];const rate=parseInt(event[2]);this.thermalMark(name,'CoolingDevice',rate,ts);return true;}};Parser.register(ThermalParser);return{ThermalParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function WorkqueueParser(importer){Parser.call(this,importer);importer.registerEventHandler('workqueue_execute_start',WorkqueueParser.prototype.executeStartEvent.bind(this));importer.registerEventHandler('workqueue_execute_end',WorkqueueParser.prototype.executeEndEvent.bind(this));importer.registerEventHandler('workqueue_queue_work',WorkqueueParser.prototype.executeQueueWork.bind(this));importer.registerEventHandler('workqueue_activate_work',WorkqueueParser.prototype.executeActivateWork.bind(this));}
 const workqueueExecuteStartRE=/work struct (.+): function (\S+)/;const workqueueExecuteEndRE=/work struct (.+)/;WorkqueueParser.prototype={__proto__:Parser.prototype,executeStartEvent(eventName,cpuNumber,pid,ts,eventBase){const event=workqueueExecuteStartRE.exec(eventBase.details);if(!event)return false;const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);kthread.openSliceTS=ts;kthread.openSlice=event[2];return true;},executeEndEvent(eventName,cpuNumber,pid,ts,eventBase){const event=workqueueExecuteEndRE.exec(eventBase.details);if(!event)return false;const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);if(kthread.openSlice){const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,{},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
 kthread.openSlice=undefined;return true;},executeQueueWork(eventName,cpuNumber,pid,ts,eventBase){return true;},executeActivateWork(eventName,cpuNumber,pid,ts,eventBase){return true;}};Parser.register(WorkqueueParser);return{WorkqueueParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID='linux_clock_monotonic_to_ftrace_global';const IMPORT_PRIORITY=2;function FTraceImporter(model,events){this.importPriority=IMPORT_PRIORITY;this.model_=model;this.events_=events;this.wakeups_=[];this.blockedReasons_=[];this.kernelThreadStates_={};this.buildMapFromLinuxPidsToThreads_();this.lines_=[];this.pseudoThreadCounter=1;this.parsers_=[];this.eventHandlers_={};this.haveClockSyncedMonotonicToGlobal_=false;this.clockDomainId_=tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL;}
 const TestExports={};const lineREWithTGID=new RegExp('^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]'+'\\s+[dX.][Nnp.][Hhs.][0-9a-f.]'+'\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');const lineParserWithTGID=function(line){const groups=lineREWithTGID.exec(line);if(!groups)return groups;let tgid=groups[3];if(tgid[0]==='-')tgid=undefined;return{threadName:groups[1],pid:groups[2],tgid,cpuNumber:groups[4],timestamp:groups[5],eventName:groups[6],details:groups[7]};};TestExports.lineParserWithTGID=lineParserWithTGID;const lineREWithIRQInfo=new RegExp('^\\s*(.+)-(\\d+)\\s+\\[(\\d+)\\]'+'\\s+[dX.][Nnp.][Hhs.][0-9a-f.]'+'\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');const lineParserWithIRQInfo=function(line){const groups=lineREWithIRQInfo.exec(line);if(!groups)return groups;return{threadName:groups[1],pid:groups[2],cpuNumber:groups[3],timestamp:groups[4],eventName:groups[5],details:groups[6]};};TestExports.lineParserWithIRQInfo=lineParserWithIRQInfo;const lineREWithLegacyFmt=/^\s*(.+)-(\d+)\s+\[(\d+)\]\s*(\d+\.\d+):\s+(\S+):\s(.*)$/;const lineParserWithLegacyFmt=function(line){const groups=lineREWithLegacyFmt.exec(line);if(!groups){return groups;}
@@ -6623,20 +6401,22 @@
 if(fiCandidate===undefined){if(reachedFCIQuiescence_(searchEnd,quietWindowBegin,searchBegin)){fiCandidate=quietWindowBegin;}else{return undefined;}}
 return Math.max(fiCandidate,domContentLoadedEnd);}
 return{findInteractiveTime,findFirstCpuIdleTime,requiredFCIWindowSizeMs,findFCITaskClusters,};});'use strict';tr.exportTo('tr.model.um',function(){const LOAD_SUBTYPE_NAMES={SUCCESSFUL:'Successful',FAILED:'Failed',};const DOES_LOAD_SUBTYPE_NAME_EXIST={};for(const key in LOAD_SUBTYPE_NAMES){DOES_LOAD_SUBTYPE_NAME_EXIST[LOAD_SUBTYPE_NAMES[key]]=true;}
-function LoadExpectation(parentModel,initiatorTitle,start,duration,renderer,navigationStart,fmpEvent,dclEndEvent,cpuIdleTime,timeToInteractive,url,frameId){if(!DOES_LOAD_SUBTYPE_NAME_EXIST[initiatorTitle]){throw new Error(initiatorTitle+' is not in LOAD_SUBTYPE_NAMES');}
-tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);this.renderProcess=renderer;this.renderMainThread=undefined;this.routingId=undefined;this.parentRoutingId=undefined;this.loadFinishedEvent=undefined;this.navigationStart=navigationStart;this.fmpEvent=fmpEvent;this.domContentLoadedEndEvent=dclEndEvent;this.firstCpuIdleTime=cpuIdleTime;this.timeToInteractive=timeToInteractive;this.url=url;this.frameId=frameId;}
+function LoadExpectation(parentModel,initiatorTitle,start,duration,renderer,navigationStart,fmpEvent,fcpEvent,dclEndEvent,cpuIdleTime,timeToInteractive,totalBlockingTime,url,frameId){if(!DOES_LOAD_SUBTYPE_NAME_EXIST[initiatorTitle]){throw new Error(initiatorTitle+' is not in LOAD_SUBTYPE_NAMES');}
+tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);this.renderProcess=renderer;this.renderMainThread=undefined;this.routingId=undefined;this.parentRoutingId=undefined;this.loadFinishedEvent=undefined;this.navigationStart=navigationStart;this.fmpEvent=fmpEvent;this.fcpEvent=fcpEvent;this.domContentLoadedEndEvent=dclEndEvent;this.firstCpuIdleTime=cpuIdleTime;this.timeToInteractive=timeToInteractive;this.totalBlockingTime=totalBlockingTime;this.url=url;this.frameId=frameId;}
 LoadExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:LoadExpectation};tr.model.um.UserExpectation.subTypes.register(LoadExpectation,{stageTitle:'Load',colorId:tr.b.ColorScheme.getColorIdForReservedName('rail_load')});return{LOAD_SUBTYPE_NAMES,LoadExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const LONG_TASK_THRESHOLD_MS=50;const IGNORE_URLS=['','about:blank',];function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
 return snapshot;}
 function findFirstMeaningfulPaintCandidates(rendererHelper){const candidatesForFrameId={};for(const ev of rendererHelper.process.getDescendantEvents()){if(!tr.e.chrome.EventFinderUtils.hasCategoryAndName(ev,'loading','firstMeaningfulPaintCandidate')){continue;}
 if(rendererHelper.isTelemetryInternalEvent(ev))continue;const frameIdRef=ev.args.frame;if(frameIdRef===undefined)continue;let list=candidatesForFrameId[frameIdRef];if(list===undefined){candidatesForFrameId[frameIdRef]=list=[];}
 list.push(ev);}
 return candidatesForFrameId;}
-function computeInteractivityMetricSample_(rendererHelper,navigationStart,fmpEvent,domContentLoadedEndEvent,searchWindowEnd){if(domContentLoadedEndEvent===undefined||fmpEvent===undefined){return{interactiveTime:undefined,firstCpuIdleTime:undefined};}
-const firstMeaningfulPaintTime=fmpEvent.start;const mainThreadTasks=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const longTasks=mainThreadTasks.filter(task=>task.duration>=LONG_TASK_THRESHOLD_MS);const longTasksInWindow=longTasks.filter(task=>task.range.intersectsExplicitRangeInclusive(firstMeaningfulPaintTime,searchWindowEnd));const resourceLoadEvents=tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd));const firstCpuIdleTime=tr.e.chrome.findFirstCpuIdleTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow);const interactiveTime=resourceLoadEvents.length>0?tr.e.chrome.findInteractiveTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow,resourceLoadEvents):undefined;return{interactiveTime,firstCpuIdleTime};}
-function constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,navigationStart,fmpEvent,searchWindowEnd,url,frameId){const dclTimesForFrame=frameToDomContentLoadedEndEvents.get(frameId)||[];const dclSearchRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd);const dclTimesInWindow=dclSearchRange.filterArray(dclTimesForFrame,event=>event.start);let domContentLoadedEndEvent=undefined;if(dclTimesInWindow.length!==0){domContentLoadedEndEvent=dclTimesInWindow[dclTimesInWindow.length-1];}
-const{interactiveTime,firstCpuIdleTime}=computeInteractivityMetricSample_(rendererHelper,navigationStart,fmpEvent,domContentLoadedEndEvent,searchWindowEnd);const duration=(interactiveTime===undefined)?searchWindowEnd-navigationStart.start:interactiveTime-navigationStart.start;return new tr.model.um.LoadExpectation(rendererHelper.modelHelper.model,tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL,navigationStart.start,duration,rendererHelper.process,navigationStart,fmpEvent,domContentLoadedEndEvent,firstCpuIdleTime,interactiveTime,url,frameId);}
-function collectLoadExpectationsForRenderer(rendererHelper){const samples=[];const frameToNavStartEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const frameToDomContentLoadedEndEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'domContentLoadedEventEnd','blink.user_timing');function addSamples(frameIdRef,navigationStart,fmpCandidateEvents,searchWindowEnd,url){let fmpMarkerEvent=tr.e.chrome.EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(fmpCandidateEvents,searchWindowEnd);if(fmpMarkerEvent!==undefined&&navigationStart.start>fmpMarkerEvent.start){fmpMarkerEvent=undefined;}
-samples.push(constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,navigationStart,fmpMarkerEvent,searchWindowEnd,url,frameIdRef));}
+function computeTotalBlockingTime_(fcpTime,interactiveTime,topLevelTasks){let sumBlockingTime=0;for(const event of topLevelTasks){if(event.duration<LONG_TASK_THRESHOLD_MS)continue;if(event.end<fcpTime)continue;if(event.start>interactiveTime)continue;const clippedStart=Math.max(event.start,fcpTime);const clippedEnd=Math.min(event.end,interactiveTime);const clippedDuration=clippedEnd-clippedStart;if(clippedDuration<LONG_TASK_THRESHOLD_MS)continue;sumBlockingTime+=(clippedDuration-LONG_TASK_THRESHOLD_MS);}
+return sumBlockingTime;}
+function computeInteractivityMetricSample_(rendererHelper,navigationStart,fcpEvent,domContentLoadedEndEvent,searchWindowEnd){if(domContentLoadedEndEvent===undefined||fcpEvent===undefined){return{interactiveTime:undefined,firstCpuIdleTime:undefined,totalBlockingTime:undefined};}
+const firstContentfulPaintTime=fcpEvent.start;const mainThreadTasks=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const longTasks=mainThreadTasks.filter(task=>task.duration>=LONG_TASK_THRESHOLD_MS);const longTasksInWindow=longTasks.filter(task=>task.range.intersectsExplicitRangeInclusive(firstContentfulPaintTime,searchWindowEnd));const resourceLoadEvents=tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd));const firstCpuIdleTime=tr.e.chrome.findFirstCpuIdleTime(firstContentfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow);const interactiveTime=resourceLoadEvents.length>0?tr.e.chrome.findInteractiveTime(firstContentfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow,resourceLoadEvents):undefined;const totalBlockingTime=interactiveTime?computeTotalBlockingTime_(fcpEvent.start,interactiveTime,longTasks):undefined;return{interactiveTime,firstCpuIdleTime,totalBlockingTime};}
+function constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,frameToFcpEvents,navigationStart,fmpEvent,searchWindowEnd,url,frameId){const searchRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd);const dclTimesForFrame=frameToDomContentLoadedEndEvents.get(frameId)||[];const dclTimesInWindow=searchRange.filterArray(dclTimesForFrame,event=>event.start);let domContentLoadedEndEvent=undefined;if(dclTimesInWindow.length!==0){domContentLoadedEndEvent=dclTimesInWindow[dclTimesInWindow.length-1];}
+const fcpForFrame=frameToFcpEvents.get(frameId)||[];const fcpInWindow=searchRange.filterArray(fcpForFrame,event=>event.start);const fcpEvent=fcpInWindow[0];const{interactiveTime,firstCpuIdleTime,totalBlockingTime}=computeInteractivityMetricSample_(rendererHelper,navigationStart,fcpEvent,domContentLoadedEndEvent,searchWindowEnd);const duration=(interactiveTime===undefined)?searchWindowEnd-navigationStart.start:interactiveTime-navigationStart.start;return new tr.model.um.LoadExpectation(rendererHelper.modelHelper.model,tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL,navigationStart.start,duration,rendererHelper.process,navigationStart,fmpEvent,fcpEvent,domContentLoadedEndEvent,firstCpuIdleTime,interactiveTime,totalBlockingTime,url,frameId);}
+function collectLoadExpectationsForRenderer(rendererHelper){const samples=[];const frameToNavStartEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const frameToDomContentLoadedEndEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'domContentLoadedEventEnd','blink.user_timing');const frameToFcpEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'firstContentfulPaint','loading');function addSamples(frameIdRef,navigationStart,fmpCandidateEvents,searchWindowEnd,url){let fmpMarkerEvent=tr.e.chrome.EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(fmpCandidateEvents,searchWindowEnd);if(fmpMarkerEvent!==undefined&&navigationStart.start>fmpMarkerEvent.start){fmpMarkerEvent=undefined;}
+samples.push(constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,frameToFcpEvents,navigationStart,fmpMarkerEvent,searchWindowEnd,url,frameIdRef));}
 const candidatesForFrameId=findFirstMeaningfulPaintCandidates(rendererHelper);for(const[frameIdRef,navStartEvents]of frameToNavStartEvents){const fmpCandidateEvents=candidatesForFrameId[frameIdRef]||[];let prevNavigation={navigationEvent:undefined,url:undefined};for(let index=0;index<navStartEvents.length;index++){const currNavigation=navStartEvents[index];let url;let isLoadingMainFrame=false;if(currNavigation.args.data){url=currNavigation.args.data.documentLoaderURL;isLoadingMainFrame=currNavigation.args.data.isLoadingMainFrame;}else{const snapshot=findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,currNavigation.start);if(snapshot){url=snapshot.args.documentLoaderURL;isLoadingMainFrame=snapshot.args.isLoadingMainFrame;}}
 if(!isLoadingMainFrame)continue;if(url===undefined||IGNORE_URLS.includes(url))continue;if(prevNavigation.navigationEvent!==undefined){addSamples(frameIdRef,prevNavigation.navigationEvent,fmpCandidateEvents,currNavigation.start,prevNavigation.url);}
 prevNavigation={navigationEvent:currNavigation,url};}
@@ -6918,7 +6698,8 @@
 if(opt_dictionary.color){spanEl.style.color=opt_dictionary.color;}}
 return spanEl;}
 function createLink(opt_args){let ownerDocument=document;if(opt_args&&opt_args.ownerDocument){ownerDocument=opt_args.ownerDocument;}
-const linkEl=ownerDocument.createElement('a');if(opt_args){if(opt_args.href)linkEl.href=opt_args.href;if(opt_args.tooltip)linkEl.title=opt_args.tooltip;if(opt_args.color)linkEl.style.color=opt_args.color;if(opt_args.bold)linkEl.style.fontWeight='bold';if(opt_args.italic)linkEl.style.fontStyle='italic';if(opt_args.className)linkEl.className=opt_args.className;if(opt_args.parent)Polymer.dom(opt_args.parent).appendChild(linkEl);if(opt_args.marginLeft)linkEl.style.marginLeft=opt_args.marginLeft;if(opt_args.marginRight)linkEl.style.marginRight=opt_args.marginRight;if(opt_args.backgroundColor){linkEl.style.backgroundColor=opt_args.backgroundColor;}
+const linkEl=ownerDocument.createElement('a');if(opt_args){if(opt_args.href){linkEl.href=opt_args.href;linkEl.target='_blank';}
+if(opt_args.tooltip)linkEl.title=opt_args.tooltip;if(opt_args.color)linkEl.style.color=opt_args.color;if(opt_args.bold)linkEl.style.fontWeight='bold';if(opt_args.italic)linkEl.style.fontStyle='italic';if(opt_args.className)linkEl.className=opt_args.className;if(opt_args.parent)Polymer.dom(opt_args.parent).appendChild(linkEl);if(opt_args.marginLeft)linkEl.style.marginLeft=opt_args.marginLeft;if(opt_args.marginRight)linkEl.style.marginRight=opt_args.marginRight;if(opt_args.backgroundColor){linkEl.style.backgroundColor=opt_args.backgroundColor;}
 if(opt_args.textContent){Polymer.dom(linkEl).textContent=opt_args.textContent;}}
 return linkEl;}
 function createDiv(opt_dictionary){const divEl=document.createElement('div');if(opt_dictionary){if(opt_dictionary.className){divEl.className=opt_dictionary.className;}
@@ -7319,7 +7100,7 @@
 static deserialize(data,deserializer){return new UnmergeableDiagnosticSet(d.map(i=>deserializer.getDiagnostic(i).diagnostic));}
 serialize(serializer){return this._diagnostics.map(d=>serializer.getOrAllocateDiagnosticId('',d));}
 static fromDict(d){return new UnmergeableDiagnosticSet(d.diagnostics.map(d=>((typeof d==='string')?new tr.v.d.DiagnosticRef(d):tr.v.d.Diagnostic.fromDict(d))));}}
-tr.v.d.Diagnostic.register(UnmergeableDiagnosticSet,{elementName:'tr-v-ui-unmergeable-diagnostic-set-span'});return{UnmergeableDiagnosticSet,};});'use strict';tr.exportTo('tr.v.d',function(){const RESERVED_INFOS={ANGLE_REVISIONS:{name:'angleRevisions',type:tr.v.d.GenericSet},ARCHITECTURES:{name:'architectures',type:tr.v.d.GenericSet},BENCHMARKS:{name:'benchmarks',type:tr.v.d.GenericSet},BENCHMARK_START:{name:'benchmarkStart',type:tr.v.d.DateRange},BENCHMARK_DESCRIPTIONS:{name:'benchmarkDescriptions',type:tr.v.d.GenericSet},BOTS:{name:'bots',type:tr.v.d.GenericSet},BUG_COMPONENTS:{name:'bugComponents',type:tr.v.d.GenericSet},BUILDS:{name:'builds',type:tr.v.d.GenericSet},CATAPULT_REVISIONS:{name:'catapultRevisions',type:tr.v.d.GenericSet},CHROMIUM_COMMIT_POSITIONS:{name:'chromiumCommitPositions',type:tr.v.d.GenericSet},CHROMIUM_REVISIONS:{name:'chromiumRevisions',type:tr.v.d.GenericSet},DESCRIPTION:{name:'description',type:tr.v.d.GenericSet},DEVICE_IDS:{name:'deviceIds',type:tr.v.d.GenericSet},DOCUMENTATION_URLS:{name:'documentationUrls',type:tr.v.d.GenericSet},FUCHSIA_GARNET_REVISIONS:{name:'fuchsiaGarnetRevisions',type:tr.v.d.GenericSet},FUCHSIA_PERIDOT_REVISIONS:{name:'fuchsiaPeridotRevisions',type:tr.v.d.GenericSet},FUCHSIA_TOPAZ_REVISIONS:{name:'fuchsiaTopazRevisions',type:tr.v.d.GenericSet},FUCHSIA_ZIRCON_REVISIONS:{name:'fuchsiaZirconRevisions',type:tr.v.d.GenericSet},GPUS:{name:'gpus',type:tr.v.d.GenericSet},IS_REFERENCE_BUILD:{name:'isReferenceBuild',type:tr.v.d.GenericSet},LABELS:{name:'labels',type:tr.v.d.GenericSet},LOG_URLS:{name:'logUrls',type:tr.v.d.GenericSet},MASTERS:{name:'masters',type:tr.v.d.GenericSet},MEMORY_AMOUNTS:{name:'memoryAmounts',type:tr.v.d.GenericSet},OS_NAMES:{name:'osNames',type:tr.v.d.GenericSet},OS_VERSIONS:{name:'osVersions',type:tr.v.d.GenericSet},OWNERS:{name:'owners',type:tr.v.d.GenericSet},POINT_ID:{name:'pointId',type:tr.v.d.GenericSet},PRODUCT_VERSIONS:{name:'productVersions',type:tr.v.d.GenericSet},REVISION_TIMESTAMPS:{name:'revisionTimestamps',type:tr.v.d.DateRange},SKIA_REVISIONS:{name:'skiaRevisions',type:tr.v.d.GenericSet},STATISTICS_NAMES:{name:'statisticsNames',type:tr.v.d.GenericSet},STORIES:{name:'stories',type:tr.v.d.GenericSet},STORYSET_REPEATS:{name:'storysetRepeats',type:tr.v.d.GenericSet},STORY_TAGS:{name:'storyTags',type:tr.v.d.GenericSet},SUMMARY_KEYS:{name:'summaryKeys',type:tr.v.d.GenericSet},TEST_PATH:{name:'testPath',type:tr.v.d.GenericSet},TRACE_START:{name:'traceStart',type:tr.v.d.DateRange},TRACE_URLS:{name:'traceUrls',type:tr.v.d.GenericSet},V8_COMMIT_POSITIONS:{name:'v8CommitPositions',type:tr.v.d.DateRange},V8_REVISIONS:{name:'v8Revisions',type:tr.v.d.GenericSet},WEBRTC_REVISIONS:{name:'webrtcRevisions',type:tr.v.d.GenericSet},WEBRTC_INTERNAL_REVISIONS:{name:'webrtcInternalRevisions',type:tr.v.d.GenericSet},};const RESERVED_NAMES={};const RESERVED_NAMES_TO_TYPES=new Map();for(const[codename,info]of Object.entries(RESERVED_INFOS)){RESERVED_NAMES[codename]=info.name;if(RESERVED_NAMES_TO_TYPES.has(info.name)){throw new Error(`Duplicate reserved name "${info.name}"`);}
+tr.v.d.Diagnostic.register(UnmergeableDiagnosticSet,{elementName:'tr-v-ui-unmergeable-diagnostic-set-span'});return{UnmergeableDiagnosticSet,};});'use strict';tr.exportTo('tr.v.d',function(){const RESERVED_INFOS={ALERT_GROUPING:{name:'alertGrouping',type:tr.v.d.GenericSet},ANGLE_REVISIONS:{name:'angleRevisions',type:tr.v.d.GenericSet},ARCHITECTURES:{name:'architectures',type:tr.v.d.GenericSet},BENCHMARKS:{name:'benchmarks',type:tr.v.d.GenericSet},BENCHMARK_START:{name:'benchmarkStart',type:tr.v.d.DateRange},BENCHMARK_DESCRIPTIONS:{name:'benchmarkDescriptions',type:tr.v.d.GenericSet},BOTS:{name:'bots',type:tr.v.d.GenericSet},BUG_COMPONENTS:{name:'bugComponents',type:tr.v.d.GenericSet},BUILDS:{name:'builds',type:tr.v.d.GenericSet},CATAPULT_REVISIONS:{name:'catapultRevisions',type:tr.v.d.GenericSet},CHROMIUM_COMMIT_POSITIONS:{name:'chromiumCommitPositions',type:tr.v.d.GenericSet},CHROMIUM_REVISIONS:{name:'chromiumRevisions',type:tr.v.d.GenericSet},DESCRIPTION:{name:'description',type:tr.v.d.GenericSet},DEVICE_IDS:{name:'deviceIds',type:tr.v.d.GenericSet},DOCUMENTATION_URLS:{name:'documentationUrls',type:tr.v.d.GenericSet},INFO_BLURB:{name:'infoBlurb',type:tr.v.d.GenericSet},FUCHSIA_GARNET_REVISIONS:{name:'fuchsiaGarnetRevisions',type:tr.v.d.GenericSet},FUCHSIA_PERIDOT_REVISIONS:{name:'fuchsiaPeridotRevisions',type:tr.v.d.GenericSet},FUCHSIA_TOPAZ_REVISIONS:{name:'fuchsiaTopazRevisions',type:tr.v.d.GenericSet},FUCHSIA_ZIRCON_REVISIONS:{name:'fuchsiaZirconRevisions',type:tr.v.d.GenericSet},GPUS:{name:'gpus',type:tr.v.d.GenericSet},IS_REFERENCE_BUILD:{name:'isReferenceBuild',type:tr.v.d.GenericSet},LABELS:{name:'labels',type:tr.v.d.GenericSet},LOG_URLS:{name:'logUrls',type:tr.v.d.GenericSet},MASTERS:{name:'masters',type:tr.v.d.GenericSet},MEMORY_AMOUNTS:{name:'memoryAmounts',type:tr.v.d.GenericSet},OS_NAMES:{name:'osNames',type:tr.v.d.GenericSet},OS_VERSIONS:{name:'osVersions',type:tr.v.d.GenericSet},OWNERS:{name:'owners',type:tr.v.d.GenericSet},POINT_ID:{name:'pointId',type:tr.v.d.GenericSet},PRODUCT_VERSIONS:{name:'productVersions',type:tr.v.d.GenericSet},REVISION_TIMESTAMPS:{name:'revisionTimestamps',type:tr.v.d.DateRange},SKIA_REVISIONS:{name:'skiaRevisions',type:tr.v.d.GenericSet},STATISTICS_NAMES:{name:'statisticsNames',type:tr.v.d.GenericSet},STORIES:{name:'stories',type:tr.v.d.GenericSet},STORYSET_REPEATS:{name:'storysetRepeats',type:tr.v.d.GenericSet},STORY_TAGS:{name:'storyTags',type:tr.v.d.GenericSet},SUMMARY_KEYS:{name:'summaryKeys',type:tr.v.d.GenericSet},TEST_PATH:{name:'testPath',type:tr.v.d.GenericSet},TRACE_START:{name:'traceStart',type:tr.v.d.DateRange},TRACE_URLS:{name:'traceUrls',type:tr.v.d.GenericSet},V8_COMMIT_POSITIONS:{name:'v8CommitPositions',type:tr.v.d.DateRange},V8_REVISIONS:{name:'v8Revisions',type:tr.v.d.GenericSet},WEBRTC_REVISIONS:{name:'webrtcRevisions',type:tr.v.d.GenericSet},WEBRTC_INTERNAL_REVISIONS:{name:'webrtcInternalRevisions',type:tr.v.d.GenericSet},};const RESERVED_NAMES={};const RESERVED_NAMES_TO_TYPES=new Map();for(const[codename,info]of Object.entries(RESERVED_INFOS)){RESERVED_NAMES[codename]=info.name;if(RESERVED_NAMES_TO_TYPES.has(info.name)){throw new Error(`Duplicate reserved name "${info.name}"`);}
 RESERVED_NAMES_TO_TYPES.set(info.name,info.type);}
 const RESERVED_NAMES_SET=new Set(Object.values(RESERVED_NAMES));return{RESERVED_INFOS,RESERVED_NAMES,RESERVED_NAMES_SET,RESERVED_NAMES_TO_TYPES,};});'use strict';tr.exportTo('tr.v.d',function(){class DiagnosticMap extends Map{constructor(opt_allowReservedNames){super();if(opt_allowReservedNames===undefined){opt_allowReservedNames=true;}
 this.allowReservedNames_=opt_allowReservedNames;}
@@ -7363,13 +7144,17 @@
 const DEFAULT_SUMMARY_OPTIONS=new Map([['avg',true],['count',true],['geometricMean',false],['max',true],['min',true],['nans',false],['std',true],['sum',true],]);class Histogram{constructor(name,unit,opt_binBoundaries){if(!(unit instanceof tr.b.Unit)){throw new Error('unit must be a Unit: '+unit);}
 let binBoundaries=opt_binBoundaries;if(!binBoundaries){const baseUnit=unit.baseUnit?unit.baseUnit:unit;binBoundaries=DEFAULT_BOUNDARIES_FOR_UNIT.get(baseUnit.unitName);}
 this.binBoundariesDict_=binBoundaries.asDict();this.allBins=binBoundaries.bins.slice();this.description='';const allowReservedNames=false;this.diagnostics_=new tr.v.d.DiagnosticMap(allowReservedNames);this.maxNumSampleValues_=this.defaultMaxNumSampleValues_;this.name_=name;this.nanDiagnosticMaps=[];this.numNans=0;this.running_=undefined;this.sampleValues_=[];this.sampleMeans_=[];this.summaryOptions=new Map(DEFAULT_SUMMARY_OPTIONS);this.summaryOptions.set('percentile',[]);this.summaryOptions.set('iprs',[]);this.summaryOptions.set('ci',[]);this.unit=unit;}
-static create(name,unit,samples,opt_options){const options=opt_options||{};const hist=new Histogram(name,unit,options.binBoundaries);if(options.description)hist.description=options.description;if(options.summaryOptions){let summaryOptions=options.summaryOptions;if(!(summaryOptions instanceof Map)){summaryOptions=Object.entries(summaryOptions);}
+static create(name,unit,samples,opt_options){const options=opt_options||{};const hist=new Histogram(name,unit,options.binBoundaries);if(options.alertGrouping!==undefined){hist.setAlertGrouping(options.alertGrouping);}
+if(options.description)hist.description=options.description;if(options.summaryOptions){let summaryOptions=options.summaryOptions;if(!(summaryOptions instanceof Map)){summaryOptions=Object.entries(summaryOptions);}
 for(const[name,value]of summaryOptions){hist.summaryOptions.set(name,value);}}
 if(options.diagnostics!==undefined){let diagnostics=options.diagnostics;if(!(diagnostics instanceof Map)){diagnostics=Object.entries(diagnostics);}
 for(const[name,diagnostic]of diagnostics){if(!diagnostic)continue;hist.diagnostics.set(name,diagnostic);}}
 if(!(samples instanceof Array))samples=[samples];for(const sample of samples){if(typeof sample==='object'){hist.addSample(sample.value,sample.diagnostics);}else{hist.addSample(sample);}}
 return hist;}
 get diagnostics(){return this.diagnostics_;}
+setAlertGrouping(alertGrouping){if(alertGrouping===undefined||alertGrouping===null||alertGrouping.length===undefined){throw Error('alertGrouping must be an array');}
+for(const alertGroup of alertGrouping){if(!Object.values(tr.v.d.ALERT_GROUPS).includes(alertGroup)){throw Error(`Alert group ${alertGroup} must be added to `+'/tracing/value/diagnostics/alert_groups.html');}}
+this.diagnostics.set(tr.v.d.RESERVED_NAMES.ALERT_GROUPING,new tr.v.d.GenericSet(alertGrouping));}
 get running(){return this.running_;}
 get maxNumSampleValues(){return this.maxNumSampleValues_;}
 set maxNumSampleValues(n){this.maxNumSampleValues_=n;tr.b.math.Statistics.uniformlySampleArray(this.sampleValues_,this.maxNumSampleValues_);}
@@ -7591,7 +7376,7 @@
 Polymer({is:'tr-ui-a-generic-object-view',ready(){this.object_=undefined;},get object(){return this.object_;},set object(object){this.object_=object;this.updateContents_();},updateContents_(){Polymer.dom(this.$.content).textContent='';this.appendElementsForType_('',this.object_,0,0,5,'');},appendElementsForType_(label,object,indent,depth,maxDepth,suffix){if(depth>maxDepth){this.appendSimpleText_(label,indent,'<recursion limit reached>',suffix);return;}
 if(object===undefined){this.appendSimpleText_(label,indent,'undefined',suffix);return;}
 if(object===null){this.appendSimpleText_(label,indent,'null',suffix);return;}
-if(!(object instanceof Object)){const type=typeof object;if(type!=='string'){return this.appendSimpleText_(label,indent,object,suffix);}
+if(!(object instanceof Object)){const type=typeof object;if(type!=='string'){return this.appendSimpleText_(label,indent,String(object),suffix);}
 let objectReplaced=false;if((object[0]==='{'&&object[object.length-1]==='}')||(object[0]==='['&&object[object.length-1]===']')){try{object=JSON.parse(object);objectReplaced=true;}catch(e){}}
 if(!objectReplaced){if(object.includes('\n')){const lines=object.split('\n');lines.forEach(function(line,i){let text;let ioff;let ll;let ss;if(i===0){text='"'+line;ioff=0;ll=label;ss='';}else if(i<lines.length-1){text=line;ioff=1;ll='';ss='';}else{text=line+'"';ioff=1;ll='';ss=suffix;}
 const el=this.appendSimpleText_(ll,indent+ioff*label.length+ioff,text,ss);el.style.whiteSpace='pre';return el;},this);return;}
@@ -7774,11 +7559,11 @@
 function drawProjectedQuadToContext(passNumber,quad,p1,p2,p3,p4,ctx,quadCanvas){if(passNumber===0){drawProjectedQuadBackgroundToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else if(passNumber===1){drawProjectedQuadOutlineToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else if(passNumber===2){drawProjectedQuadSelectionOutlineToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else{throw new Error('Invalid pass number');}}
 const tmpP1=vec3.create();const tmpP2=vec3.create();const tmpP3=vec3.create();const tmpP4=vec3.create();function transformAndProcessQuads(matrix,viewport,quads,numPasses,handleQuadFunc,opt_arg1,opt_arg2){for(let passNumber=0;passNumber<numPasses;passNumber++){for(let i=0;i<quads.length;i++){const quad=quads[i];transform(tmpP1,quad.p1,matrix,viewport);transform(tmpP2,quad.p2,matrix,viewport);transform(tmpP3,quad.p3,matrix,viewport);transform(tmpP4,quad.p4,matrix,viewport);handleQuadFunc(passNumber,quad,tmpP1,tmpP2,tmpP3,tmpP4,opt_arg1,opt_arg2);}}}
 const QuadStackView=tr.ui.b.define('quad-stack-view');QuadStackView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.className='quad-stack-view';this.style.display='flex';this.style.position='relative';const node=tr.ui.b.instantiateTemplate('#quad-stack-view-template',THIS_DOC);Polymer.dom(this).appendChild(node);this.updateHeaderVisibility_();const header=Polymer.dom(this).querySelector('#header');header.style.position='absolute';header.style.fontSize='70%';header.style.top='10px';header.style.left='10px';header.style.right='150px';const scroller=Polymer.dom(this).querySelector('#canvas-scroller');scroller.style.flexGrow=1;scroller.style.flexShrink=1;scroller.style.flexBasis='auto';scroller.style.minWidth=0;scroller.style.minHeight=0;scroller.style.overflow='auto';this.canvas_=Polymer.dom(this).querySelector('#canvas');this.chromeImages_={left:Polymer.dom(this).querySelector('#chrome-left'),mid:Polymer.dom(this).querySelector('#chrome-mid'),right:Polymer.dom(this).querySelector('#chrome-right')};const stackingDistanceSlider=Polymer.dom(this).querySelector('#stacking-distance-slider');stackingDistanceSlider.style.position='absolute';stackingDistanceSlider.style.fontSize='70%';stackingDistanceSlider.style.top='10px';stackingDistanceSlider.style.right='10px';stackingDistanceSlider.value=tr.b.Settings.get('quadStackView.stackingDistance',45);stackingDistanceSlider.addEventListener('change',this.onStackingDistanceChange_.bind(this));stackingDistanceSlider.addEventListener('input',this.onStackingDistanceChange_.bind(this));this.trackMouse_();this.camera_=new tr.ui.b.Camera(this.mouseModeSelector_);this.camera_.addEventListener('renderrequired',this.onRenderRequired_.bind(this));this.cameraWasReset_=false;this.camera_.canvas=this.canvas_;this.viewportRect_=tr.b.math.Rect.fromXYWH(0,0,0,0);this.pixelRatio_=window.devicePixelRatio||1;},updateHeaderVisibility_(){if(this.headerText){Polymer.dom(this).querySelector('#header').style.display='';}else{Polymer.dom(this).querySelector('#header').style.display='none';}},get headerText(){return Polymer.dom(this).querySelector('#header').textContent;},set headerText(headerText){Polymer.dom(this).querySelector('#header').textContent=headerText;this.updateHeaderVisibility_();},onStackingDistanceChange_(e){tr.b.Settings.set('quadStackView.stackingDistance',this.stackingDistance);this.scheduleRender();e.stopPropagation();},get stackingDistance(){return Polymer.dom(this).querySelector('#stacking-distance-slider').value;},get mouseModeSelector(){return this.mouseModeSelector_;},get camera(){return this.camera_;},set quads(q){this.quads_=q;this.scheduleRender();},set deviceRect(rect){if(!rect||rect.equalTo(this.deviceRect_))return;this.deviceRect_=rect;this.camera_.deviceRect=rect;this.chromeQuad_=undefined;},resize(){if(!this.offsetParent)return true;const width=parseInt(window.getComputedStyle(this.offsetParent).width);const height=parseInt(window.getComputedStyle(this.offsetParent).height);const rect=tr.b.math.Rect.fromXYWH(0,0,width,height);if(rect.equalTo(this.viewportRect_))return false;this.viewportRect_=rect;this.canvas_.style.width=width+'px';this.canvas_.style.height=height+'px';this.canvas_.width=this.pixelRatio_*width;this.canvas_.height=this.pixelRatio_*height;if(!this.cameraWasReset_){this.camera_.resetCamera();this.cameraWasReset_=true;}
-return true;},readyToDraw(){if(!this.chromeImages_.left.src){let leftContent=window.getComputedStyle(this.chromeImages_.left).backgroundImage;leftContent=tr.ui.b.extractUrlString(leftContent);let midContent=window.getComputedStyle(this.chromeImages_.mid).backgroundImage;midContent=tr.ui.b.extractUrlString(midContent);let rightContent=window.getComputedStyle(this.chromeImages_.right).backgroundImage;rightContent=tr.ui.b.extractUrlString(rightContent);this.chromeImages_.left.src=leftContent;this.chromeImages_.mid.src=midContent;this.chromeImages_.right.src=rightContent;}
+return true;},readyToDptr(){if(!this.chromeImages_.left.src){let leftContent=window.getComputedStyle(this.chromeImages_.left).backgroundImage;leftContent=tr.ui.b.extractUrlString(leftContent);let midContent=window.getComputedStyle(this.chromeImages_.mid).backgroundImage;midContent=tr.ui.b.extractUrlString(midContent);let rightContent=window.getComputedStyle(this.chromeImages_.right).backgroundImage;rightContent=tr.ui.b.extractUrlString(rightContent);this.chromeImages_.left.src=leftContent;this.chromeImages_.mid.src=midContent;this.chromeImages_.right.src=rightContent;}
 return(this.chromeImages_.left.height>0)&&(this.chromeImages_.mid.height>0)&&(this.chromeImages_.right.height>0);},get chromeQuad(){if(this.chromeQuad_)return this.chromeQuad_;const chromeCanvas=document.createElement('canvas');const offsetY=this.chromeImages_.left.height;chromeCanvas.width=this.deviceRect_.width;chromeCanvas.height=this.deviceRect_.height+offsetY;const leftWidth=this.chromeImages_.left.width;const midWidth=this.chromeImages_.mid.width;const rightWidth=this.chromeImages_.right.width;const chromeCtx=chromeCanvas.getContext('2d');chromeCtx.drawImage(this.chromeImages_.left,0,0);chromeCtx.save();chromeCtx.translate(leftWidth,0);const s=(this.deviceRect_.width-leftWidth-rightWidth)/midWidth;chromeCtx.scale(s,1);chromeCtx.drawImage(this.chromeImages_.mid,0,0);chromeCtx.restore();chromeCtx.drawImage(this.chromeImages_.right,leftWidth+s*midWidth,0);const chromeRect=tr.b.math.Rect.fromXYWH(this.deviceRect_.x,this.deviceRect_.y-offsetY,this.deviceRect_.width,this.deviceRect_.height+offsetY);const chromeQuad=tr.b.math.Quad.fromRect(chromeRect);chromeQuad.stackingGroupId=this.maxStackingGroupId_+1;chromeQuad.imageData=chromeCtx.getImageData(0,0,chromeCanvas.width,chromeCanvas.height);chromeQuad.shadowOffset=[0,0];chromeQuad.shadowBlur=5;chromeQuad.borderWidth=3;this.chromeQuad_=chromeQuad;return this.chromeQuad_;},scheduleRender(){if(this.redrawScheduled_)return false;this.redrawScheduled_=true;tr.b.requestAnimationFrame(this.render,this);},onRenderRequired_(e){this.scheduleRender();},stackTransformAndProcessQuads_(numPasses,handleQuadFunc,includeChromeQuad,opt_arg1,opt_arg2){const mv=this.camera_.modelViewMatrix;const p=this.camera_.projectionMatrix;const viewport=tr.b.math.Rect.fromXYWH(0,0,this.canvas_.width,this.canvas_.height);const quadStacks=[];for(let i=0;i<this.quads_.length;++i){const quad=this.quads_[i];const stackingId=quad.stackingGroupId||0;while(stackingId>=quadStacks.length){quadStacks.push([]);}
 quadStacks[stackingId].push(quad);}
 const mvp=mat4.create();this.maxStackingGroupId_=quadStacks.length;const effectiveStackingDistance=this.stackingDistance*this.camera_.stackingDistanceDampening;mat4.multiply(mvp,p,mv);for(let i=0;i<quadStacks.length;++i){transformAndProcessQuads(mvp,viewport,quadStacks[i],numPasses,handleQuadFunc,opt_arg1,opt_arg2);mat4.translate(mv,mv,[0,0,effectiveStackingDistance]);mat4.multiply(mvp,p,mv);}
-if(includeChromeQuad&&this.deviceRect_){transformAndProcessQuads(mvp,viewport,[this.chromeQuad],numPasses,drawProjectedQuadToContext,opt_arg1,opt_arg2);}},render(){this.redrawScheduled_=false;if(!this.readyToDraw()){setTimeout(this.scheduleRender.bind(this),constants.IMAGE_LOAD_RETRY_TIME_MS);return;}
+if(includeChromeQuad&&this.deviceRect_){transformAndProcessQuads(mvp,viewport,[this.chromeQuad],numPasses,drawProjectedQuadToContext,opt_arg1,opt_arg2);}},render(){this.redrawScheduled_=false;if(!this.readyToDptr()){setTimeout(this.scheduleRender.bind(this),constants.IMAGE_LOAD_RETRY_TIME_MS);return;}
 if(!this.quads_)return;const canvasCtx=this.canvas_.getContext('2d');if(!this.resize()){canvasCtx.clearRect(0,0,this.canvas_.width,this.canvas_.height);}
 const quadCanvas=document.createElement('canvas');this.stackTransformAndProcessQuads_(3,drawProjectedQuadToContext,true,canvasCtx,quadCanvas);quadCanvas.width=0;},trackMouse_(){this.mouseModeSelector_=document.createElement('tr-ui-b-mouse-mode-selector');this.mouseModeSelector_.targetElement=this.canvas_;this.mouseModeSelector_.supportedModeMask=tr.ui.b.MOUSE_SELECTOR_MODE.SELECTION|tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN|tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM|tr.ui.b.MOUSE_SELECTOR_MODE.ROTATE;this.mouseModeSelector_.mode=tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN;this.mouseModeSelector_.pos={x:0,y:100};Polymer.dom(this).appendChild(this.mouseModeSelector_);this.mouseModeSelector_.settingsKey='quadStackView.mouseModeSelector';this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.ROTATE,tr.ui.b.MODIFIER.SHIFT);this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN,tr.ui.b.MODIFIER.SPACE);this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM,tr.ui.b.MODIFIER.CMD_OR_CTRL);this.mouseModeSelector_.addEventListener('updateselection',this.onSelectionUpdate_.bind(this));this.mouseModeSelector_.addEventListener('endselection',this.onSelectionUpdate_.bind(this));},extractRelativeMousePosition_(e){const br=this.canvas_.getBoundingClientRect();return[this.pixelRatio_*(e.clientX-this.canvas_.offsetLeft-br.left),this.pixelRatio_*(e.clientY-this.canvas_.offsetTop-br.top)];},onSelectionUpdate_(e){const mousePos=this.extractRelativeMousePosition_(e);const res=[];function handleQuad(passNumber,quad,p1,p2,p3,p4){if(tr.b.math.pointInImplicitQuad(mousePos,p1,p2,p3,p4)){res.push(quad);}}
 this.stackTransformAndProcessQuads_(1,handleQuad,false);e=new tr.b.Event('selectionchange');e.quads=res;this.dispatchEvent(e);}};return{QuadStackView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const ColorScheme=tr.b.ColorScheme;const THIS_DOC=document.currentScript.ownerDocument;const TILE_HEATMAP_TYPE={};TILE_HEATMAP_TYPE.NONE='none';TILE_HEATMAP_TYPE.SCHEDULED_PRIORITY='scheduledPriority';TILE_HEATMAP_TYPE.USING_GPU_MEMORY='usingGpuMemory';const cc=tr.ui.e.chrome.cc;function createTileRectsSelectorBaseOptions(){return[{label:'None',value:'none'},{label:'Coverage Rects',value:'coverage'}];}
@@ -7851,7 +7636,7 @@
 tr.b.dispatchSimpleEvent(this,'selection-change');},createPictureBtn_(pictures){if(!(pictures instanceof Array)){pictures=[pictures];}
 const link=document.createElement('tr-ui-a-analysis-link');link.selection=function(){const layeredPicture=new tr.e.cc.LayeredPicture(pictures);const snapshot=new tr.e.cc.PictureSnapshot(layeredPicture);snapshot.picture=layeredPicture;const selection=new tr.model.EventSet();selection.push(snapshot);return selection;};Polymer.dom(link).textContent='View in Picture Debugger';return link;},onRequestSelectionChangeFromAnalysisEl_(e){if(!(e.selection instanceof tr.ui.e.chrome.cc.Selection)){return;}
 e.stopPropagation();this.selection=e.selection;},get extraHighlightsByLayerId(){return this.layerTreeQuadStackView_.extraHighlightsByLayerId;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.layerTreeQuadStackView_.extraHighlightsByLayerId=extraHighlightsByLayerId;}};return{LayerView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const LayerTreeHostImplSnapshotView=tr.ui.b.define('tr-ui-e-chrome-cc-layer-tree-host-impl-snapshot-view',tr.ui.analysis.ObjectSnapshotView);LayerTreeHostImplSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){Polymer.dom(this).classList.add('tr-ui-e-chrome-cc-lthi-s-view');this.style.display='flex';this.style.flexDirection='row';this.style.flexGrow=1;this.style.flexShrink=1;this.style.flexBasis='auto';this.style.minWidth=0;this.selection_=undefined;this.layerPicker_=new tr.ui.e.chrome.cc.LayerPicker();this.layerPicker_.style.flexGrow=0;this.layerPicker_.style.flexShrink=0;this.layerPicker_.style.flexBasis='auto';this.layerPicker_.style.minWidth='200px';this.layerPicker_.addEventListener('selection-change',this.onLayerPickerSelectionChanged_.bind(this));this.layerView_=new tr.ui.e.chrome.cc.LayerView();this.layerView_.addEventListener('selection-change',this.onLayerViewSelectionChanged_.bind(this));this.layerView_.style.flexGrow=1;this.layerView_.style.flexShrink=1;this.layerView_.style.flexBasis='auto';this.layerView_.style.minWidth=0;this.dragHandle_=document.createElement('tr-ui-b-drag-handle');this.dragHandle_.style.flexGrow=0;this.dragHandle_.style.flexShrink=0;this.dragHandle_.style.flexBasis='auto';this.dragHandle_.horizontal=false;this.dragHandle_.target=this.layerPicker_;Polymer.dom(this).appendChild(this.layerPicker_);Polymer.dom(this).appendChild(this.dragHandle_);Polymer.dom(this).appendChild(this.layerView_);this.onLayerViewSelectionChanged_();this.onLayerPickerSelectionChanged_();},get objectSnapshot(){return this.objectSnapshot_;},set objectSnapshot(objectSnapshot){this.objectSnapshot_=objectSnapshot;const lthi=this.objectSnapshot;let layerTreeImpl;if(lthi){layerTreeImpl=lthi.getTree(this.layerPicker_.whichTree);}
-this.layerPicker_.lthiSnapshot=lthi;this.layerView_.layerTreeImpl=layerTreeImpl;this.layerView_.regenerateContent();if(!this.selection_)return;this.selection=this.selection_.findEquivalent(lthi);},get selection(){return this.selection_;},set selection(selection){if(this.selection_===selection)return;this.selection_=selection;this.layerPicker_.selection=selection;this.layerView_.selection=selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerPickerSelectionChanged_(){this.selection_=this.layerPicker_.selection;this.layerView_.selection=this.selection;this.layerView_.layerTreeImpl=this.layerPicker_.layerTreeImpl;this.layerView_.isRenderPassQuads=this.layerPicker_.isRenderPassQuads;this.layerView_.regenerateContent();tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerViewSelectionChanged_(){this.selection_=this.layerView_.selection;this.layerPicker_.selection=this.selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},get extraHighlightsByLayerId(){return this.layerView_.extraHighlightsByLayerId;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.layerView_.extraHighlightsByLayerId=extraHighlightsByLayerId;}};tr.ui.analysis.ObjectSnapshotView.register(LayerTreeHostImplSnapshotView,{typeName:'cc::LayerTreeHostImpl'});return{LayerTreeHostImplSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const OPS_TIMING_ITERATIONS=3;const CHART_PADDING_LEFT=65;const CHART_PADDING_RIGHT=40;const AXIS_PADDING_LEFT=60;const AXIS_PADDING_RIGHT=35;const AXIS_PADDING_TOP=25;const AXIS_PADDING_BOTTOM=45;const AXIS_LABEL_PADDING=5;const AXIS_TICK_SIZE=10;const LABEL_PADDING=5;const LABEL_INTERLEAVE_OFFSET=15;const BAR_PADDING=5;const VERTICAL_TICKS=5;const HUE_CHAR_CODE_ADJUSTMENT=5.7;const PictureOpsChartSummaryView=tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-chart-summary-view');PictureOpsChartSummaryView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.flexGrow=0;this.style.flexShrink=0;this.style.flexBasis='auto';this.style.fontSize=0;this.style.margin=0;this.style.minHeight='200px';this.style.minWidth='200px';this.style.overflow='hidden';this.style.padding=0;this.picture_=undefined;this.pictureDataProcessed_=false;this.chartScale_=window.devicePixelRatio;this.chart_=document.createElement('canvas');this.chartCtx_=this.chart_.getContext('2d');Polymer.dom(this).appendChild(this.chart_);this.opsTimingData_=[];this.chartWidth_=0;this.chartHeight_=0;this.requiresRedraw_=true;this.currentBarMouseOverTarget_=null;this.chart_.addEventListener('mousemove',this.onMouseMove_.bind(this));try{new ResizeObserver(this.onResize_.bind(this)).observe(this);}catch(e){}},get requiresRedraw(){return this.requiresRedraw_;},set requiresRedraw(requiresRedraw){this.requiresRedraw_=requiresRedraw;},get picture(){return this.picture_;},set picture(picture){this.picture_=picture;this.pictureDataProcessed_=false;if(Polymer.dom(this).classList.contains('hidden'))return;this.processPictureData_();this.requiresRedraw=true;this.updateChartContents();},hide(){Polymer.dom(this).classList.add('hidden');this.style.display='none';},show(){Polymer.dom(this).classList.remove('hidden');this.style.display='';if(!this.pictureDataProcessed_){this.processPictureData_();}
+this.layerPicker_.lthiSnapshot=lthi;this.layerView_.layerTreeImpl=layerTreeImpl;this.layerView_.regenerateContent();if(!this.selection_)return;this.selection=this.selection_.findEquivalent(lthi);},get selection(){return this.selection_;},set selection(selection){if(this.selection_===selection)return;this.selection_=selection;this.layerPicker_.selection=selection;this.layerView_.selection=selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerPickerSelectionChanged_(){this.selection_=this.layerPicker_.selection;this.layerView_.selection=this.selection;this.layerView_.layerTreeImpl=this.layerPicker_.layerTreeImpl;this.layerView_.isRenderPassQuads=this.layerPicker_.isRenderPassQuads;this.layerView_.regenerateContent();tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerViewSelectionChanged_(){this.selection_=this.layerView_.selection;this.layerPicker_.selection=this.selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},get extraHighlightsByLayerId(){return this.layerView_.extraHighlightsByLayerId;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.layerView_.extraHighlightsByLayerId=extraHighlightsByLayerId;}};tr.ui.analysis.ObjectSnapshotView.register(LayerTreeHostImplSnapshotView,{typeName:'cc::LayerTreeHostImpl'});return{LayerTreeHostImplSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const OPS_TIMING_ITERATIONS=3;const CHART_PADDING_LEFT=65;const CHART_PADDING_RIGHT=40;const AXIS_PADDING_LEFT=60;const AXIS_PADDING_RIGHT=35;const AXIS_PADDING_TOP=25;const AXIS_PADDING_BOTTOM=45;const AXIS_LABEL_PADDING=5;const AXIS_TICK_SIZE=10;const LABEL_PADDING=5;const LABEL_INTERLEAVE_OFFSET=15;const BAR_PADDING=5;const VERTICAL_TICKS=5;const HUE_CHAR_CODE_ADJUSTMENT=5.7;const PictureOpsChartSummaryView=tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-chart-summary-view');PictureOpsChartSummaryView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.flexGrow=0;this.style.flexShrink=0;this.style.flexBasis='auto';this.style.fontSize=0;this.style.margin=0;this.style.minHeight='200px';this.style.minWidth='200px';this.style.overflow='hidden';this.style.padding=0;this.picture_=undefined;this.pictureDataProcessed_=false;this.chartScale_=window.devicePixelRatio;this.chart_=document.createElement('canvas');this.chartCtx_=this.chart_.getContext('2d');Polymer.dom(this).appendChild(this.chart_);this.opsTimingData_=[];this.chartWidth_=0;this.chartHeight_=0;this.requiresRedraw_=true;this.currentBarMouseOverTarget_=null;this.chart_.addEventListener('mousemove',this.onMouseMove_.bind(this));try{new ResizeObserver(this.onResize_.bind(this)).observe(this);}catch(e){}},get requiresRedptr(){return this.requiresRedraw_;},set requiresRedraw(requiresRedraw){this.requiresRedraw_=requiresRedraw;},get picture(){return this.picture_;},set picture(picture){this.picture_=picture;this.pictureDataProcessed_=false;if(Polymer.dom(this).classList.contains('hidden'))return;this.processPictureData_();this.requiresRedraw=true;this.updateChartContents();},hide(){Polymer.dom(this).classList.add('hidden');this.style.display='none';},show(){Polymer.dom(this).classList.remove('hidden');this.style.display='';if(!this.pictureDataProcessed_){this.processPictureData_();}
 this.requiresRedraw=true;this.updateChartContents();},onMouseMove_(e){const lastBarMouseOverTarget=this.currentBarMouseOverTarget_;this.currentBarMouseOverTarget_=null;const x=e.offsetX;const y=e.offsetY;const chartLeft=CHART_PADDING_LEFT;const chartRight=this.chartWidth_-CHART_PADDING_RIGHT;const chartTop=AXIS_PADDING_TOP;const chartBottom=this.chartHeight_-AXIS_PADDING_BOTTOM;const chartInnerWidth=chartRight-chartLeft;if(x>chartLeft&&x<chartRight&&y>chartTop&&y<chartBottom){this.currentBarMouseOverTarget_=Math.floor((x-chartLeft)/chartInnerWidth*this.opsTimingData_.length);this.currentBarMouseOverTarget_=tr.b.math.clamp(this.currentBarMouseOverTarget_,0,this.opsTimingData_.length-1);}
 if(this.currentBarMouseOverTarget_===lastBarMouseOverTarget)return;this.drawChartContents_();},onResize_(){this.requiresRedraw=true;this.updateChartContents();},updateChartContents(){if(this.requiresRedraw){this.updateChartDimensions_();}
 this.drawChartContents_();},updateChartDimensions_(){this.chartWidth_=this.offsetWidth;this.chartHeight_=this.offsetHeight;this.chart_.width=this.chartWidth_*this.chartScale_;this.chart_.height=this.chartHeight_*this.chartScale_;this.chart_.style.width=this.chartWidth_+'px';this.chart_.style.height=this.chartHeight_+'px';this.chartCtx_.scale(this.chartScale_,this.chartScale_);},processPictureData_(){this.resetOpsTimingData_();this.pictureDataProcessed_=true;if(!this.picture_)return;let ops=this.picture_.getOps();if(!ops)return;ops=this.picture_.tagOpsWithTimings(ops);if(ops[0].cmd_time===undefined)return;this.collapseOpsToTimingBuckets_(ops);},drawChartContents_(){this.clearChartContents_();if(this.opsTimingData_.length===0){this.showNoTimingDataMessage_();return;}
@@ -7929,7 +7714,8 @@
 if(event.category){rows.push({name:'Category',value:event.category});}
 if(event.model!==undefined){const ufc=event.model.getUserFriendlyCategoryFromEvent(event);if(ufc!==undefined){rows.push({name:'User Friendly Category',value:ufc});}}
 if(event.name){rows.push({name:'Name',value:event.name});}
-rows.push({name:'Start',value:tr.v.ui.createScalarSpan(event.start,{unit:tr.b.Unit.byName.timeStampInMs})});if(event.duration){rows.push({name:'Wall Duration',value:tr.v.ui.createScalarSpan(event.duration,{unit:tr.b.Unit.byName.timeDurationInMs})});}
+rows.push({name:'Start',value:tr.v.ui.createScalarSpan(event.start,{unit:tr.b.Unit.byName.timeStampInMs})});if(event.category==='android'&&event.model!==undefined){rows.push({name:'Start (Absolute time)',value:tr.v.ui.createScalarSpan(event.model.convertTimestampFromModelTime('traceEventClock',event.start),{unit:tr.b.Unit.byName.timeStampInMs})});}
+if(event.duration){rows.push({name:'Wall Duration',value:tr.v.ui.createScalarSpan(event.duration,{unit:tr.b.Unit.byName.timeDurationInMs})});}
 if(event.cpuDuration){rows.push({name:'CPU Duration',value:tr.v.ui.createScalarSpan(event.cpuDuration,{unit:tr.b.Unit.byName.timeDurationInMs})});}
 if(event.subSlices!==undefined&&event.subSlices.length!==0){if(event.selfTime){rows.push({name:'Self Time',value:tr.v.ui.createScalarSpan(event.selfTime,{unit:tr.b.Unit.byName.timeDurationInMs})});}
 if(event.cpuSelfTime){const cpuSelfTimeEl=tr.v.ui.createScalarSpan(event.cpuSelfTime,{unit:tr.b.Unit.byName.timeDurationInMs});if(event.cpuSelfTime>event.selfTime){cpuSelfTimeEl.warning=' Note that CPU Self Time is larger than Self Time. '+'This is a known limitation of this system, which occurs '+'due to several subslices, rounding issues, and imprecise '+'time at which we get cpu- and real-time.';}
@@ -8293,21 +8079,21 @@
 if(slice.title==='RenderAccessibilityImpl::SendLocationChanges'){renderAccessibilityLocationsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}}}
 for(const browserHelper of Object.values(chromeHelper.browserHelpers)){const mainThread=browserHelper.mainThread;if(mainThread===undefined)continue;for(const slice of mainThread.getDescendantEvents()){if(slice.title==='BrowserAccessibilityManager::OnAccessibilityEvents'){browserAccessibilityEventsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}}}
 histograms.addHistogram(browserAccessibilityEventsHist);histograms.addHistogram(renderAccessibilityEventsHist);histograms.addHistogram(renderAccessibilityLocationsHist);}
-tr.metrics.MetricRegistry.register(accessibilityMetric);return{accessibilityMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MESSAGE_LOOP_EVENT_NAME='Startup.BrowserMessageLoopStartTime';const CONTENT_START_EVENT_NAME='content::Start';const NAVIGATION_EVENT_NAME='Navigation StartToCommit';const FIRST_CONTENTFUL_PAINT_EVENT_NAME='firstContentfulPaint';function androidStartupMetric(histograms,model){let messageLoopStartEvents=[];let navigationEvents=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;for(const helper of chromeHelper.browserHelpers){for(const ev of helper.mainThread.asyncSliceGroup.childEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}}}
+tr.metrics.MetricRegistry.register(accessibilityMetric);return{accessibilityMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MESSAGE_LOOP_EVENT_NAME='Startup.BrowserMessageLoopStartTime';const CONTENT_START_EVENT_NAME='content::Start';const NAVIGATION_EVENT_NAME='Navigation StartToCommit';const FIRST_CONTENTFUL_PAINT_EVENT_NAME='firstContentfulPaint';const APPLICATION_START_EVENT_NAME='Startup.LoadTime.ProcessCreateToApplicationStart';function androidStartupMetric(histograms,model){let messageLoopStartEvents=[];let applicationStartEvents=[];let navigationEvents=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;for(const helper of chromeHelper.browserHelpers){for(const ev of helper.mainThread.asyncSliceGroup.childEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===APPLICATION_START_EVENT_NAME){applicationStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}}}
 let contentStartEvents=[];let firstContentfulPaintEvents=[];const rendererHelpers=chromeHelper.rendererHelpers;const pids=Object.keys(rendererHelpers);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(!rendererHelper.mainThread)continue;for(const ev of rendererHelper.mainThread.sliceGroup.childEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}}
-let totalBrowserStarts=messageLoopStartEvents.length;let totalContentStartEvents=contentStartEvents.length;let totalFcpEvents=firstContentfulPaintEvents.length;let totalNavigations=navigationEvents.length;if(totalFcpEvents!==totalBrowserStarts||totalNavigations!==totalBrowserStarts||totalContentStartEvents!==totalBrowserStarts||totalBrowserStarts===0){messageLoopStartEvents=[];contentStartEvents=[];navigationEvents=[];firstContentfulPaintEvents=[];for(const proc of Object.values(model.processes)){for(const ev of proc.getDescendantEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}
+let totalBrowserStarts=messageLoopStartEvents.length;let totalContentStartEvents=contentStartEvents.length;let totalFcpEvents=firstContentfulPaintEvents.length;let totalNavigations=navigationEvents.length;let totalApplicationStartEvents=applicationStartEvents.length;if(totalFcpEvents!==totalBrowserStarts||totalNavigations!==totalBrowserStarts||totalContentStartEvents!==totalBrowserStarts||totalApplicationStartEvents!==totalBrowserStarts||totalBrowserStarts===0){messageLoopStartEvents=[];contentStartEvents=[];navigationEvents=[];firstContentfulPaintEvents=[];applicationStartEvents=[];for(const proc of Object.values(model.processes)){for(const ev of proc.getDescendantEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===APPLICATION_START_EVENT_NAME){applicationStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}
 for(const ev of proc.getDescendantEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}}}
-totalBrowserStarts=messageLoopStartEvents.length;totalContentStartEvents=contentStartEvents.length;totalNavigations=navigationEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;}
+totalBrowserStarts=messageLoopStartEvents.length;totalContentStartEvents=contentStartEvents.length;totalNavigations=navigationEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;totalApplicationStartEvents=applicationStartEvents.length;}
 function orderEvents(event1,event2){return event1.start-event2.start;}
-messageLoopStartEvents.sort(orderEvents);contentStartEvents.sort(orderEvents);navigationEvents.sort(orderEvents);firstContentfulPaintEvents.sort(orderEvents);if(totalFcpEvents<totalBrowserStarts){throw new Error('Found fewer FCP events ('+totalFcpEvents+') than browser starts ('+totalBrowserStarts+')');}
-const messageLoopStartHistogram=histograms.createHistogram('messageloop_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const contentStartHistogram=histograms.createHistogram('experimental_content_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationStartHistogram=histograms.createHistogram('experimental_navigation_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationCommitHistogram=histograms.createHistogram('navigation_commit_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const firstContentfulPaintHistogram=histograms.createHistogram('first_contentful_paint_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);let contentIndex=0;let navIndex=0;let fcpIndex=0;for(let loopStartIndex=0;loopStartIndex<totalBrowserStarts;){const startEvent=messageLoopStartEvents[loopStartIndex];if(fcpIndex===totalFcpEvents){break;}
-const contentStartEvent=contentIndex<contentStartEvents.length?contentStartEvents[contentIndex]:null;if(contentStartEvent&&contentStartEvent.start<startEvent.start){contentIndex++;continue;}
-const navEvent=navIndex<navigationEvents.length?navigationEvents[navIndex]:null;if(navEvent&&navEvent.start<startEvent.start){navIndex++;continue;}
-const fcpEvent=firstContentfulPaintEvents[fcpIndex];if(fcpEvent.start<startEvent.start){fcpIndex++;continue;}
+messageLoopStartEvents.sort(orderEvents);applicationStartEvents.sort(orderEvents);contentStartEvents.sort(orderEvents);navigationEvents.sort(orderEvents);firstContentfulPaintEvents.sort(orderEvents);if(totalFcpEvents<totalBrowserStarts){throw new Error('Found fewer FCP events ('+totalFcpEvents+') than browser starts ('+totalBrowserStarts+')');}
+const messageLoopStartHistogram=histograms.createHistogram('messageloop_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const contentStartHistogram=histograms.createHistogram('experimental_content_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationStartHistogram=histograms.createHistogram('experimental_navigation_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationCommitHistogram=histograms.createHistogram('navigation_commit_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const firstContentfulPaintHistogram=histograms.createHistogram('first_contentful_paint_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const applicationStartHistogram=histograms.createHistogram('process_create_to_app_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);let contentIndex=0;let navIndex=0;let fcpIndex=0;for(let loopStartIndex=0;loopStartIndex<totalBrowserStarts;){const loopStartEvent=messageLoopStartEvents[loopStartIndex];const applicationStartEvent=applicationStartEvents[loopStartIndex];if(fcpIndex===totalFcpEvents){break;}
+const contentStartEvent=contentIndex<contentStartEvents.length?contentStartEvents[contentIndex]:null;if(contentStartEvent&&contentStartEvent.start<loopStartEvent.start){contentIndex++;continue;}
+const navEvent=navIndex<navigationEvents.length?navigationEvents[navIndex]:null;if(navEvent&&navEvent.start<loopStartEvent.start){navIndex++;continue;}
+const fcpEvent=firstContentfulPaintEvents[fcpIndex];if(fcpEvent.start<loopStartEvent.start){fcpIndex++;continue;}
 loopStartIndex++;if(fcpIndex<2){continue;}
-messageLoopStartHistogram.addSample(startEvent.duration,{events:new tr.v.d.RelatedEventSet([startEvent])});if(contentStartEvent){contentStartHistogram.addSample(contentStartEvent.start-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,contentStartEvent])});}
-if(navEvent){navigationStartHistogram.addSample(navEvent.start-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,navEvent])});navigationCommitHistogram.addSample(navEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,navEvent])});}
-firstContentfulPaintHistogram.addSample(fcpEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,fcpEvent])});}}
+messageLoopStartHistogram.addSample(loopStartEvent.duration,{events:new tr.v.d.RelatedEventSet([loopStartEvent])});if(contentStartEvent){contentStartHistogram.addSample(contentStartEvent.start-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,contentStartEvent])});}
+if(navEvent){navigationStartHistogram.addSample(navEvent.start-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,navEvent])});navigationCommitHistogram.addSample(navEvent.end-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,navEvent])});}
+firstContentfulPaintHistogram.addSample(fcpEvent.end-loopStartEvent.start,{events:new tr.v.d.RelatedEventSet([loopStartEvent,fcpEvent])});if(applicationStartEvent){applicationStartHistogram.addSample(applicationStartEvent.duration,{events:new tr.v.d.RelatedEventSet([applicationStartEvent])});}}}
 tr.metrics.MetricRegistry.register(androidStartupMetric);return{androidStartupMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MAX_INPUT_EVENT_TO_STARTUP_DELAY_IN_MS=2000;const MIN_DRAW_DELAY_IN_MS=80;const MAX_DRAW_DELAY_IN_MS=2000;function findProcess(processName,model){for(const pid in model.processes){const process=model.processes[pid];if(process.name===processName){return process;}}
 return undefined;}
 function findThreads(process,threadPrefix){if(process===undefined)return undefined;const threads=[];for(const tid in process.threads){const thread=process.threads[tid];if(thread.name.startsWith(threadPrefix)){threads.push(thread);}}
@@ -8351,6 +8137,7 @@
 function isFullMarkCompactorEvent(event){return event.title==='V8.GCCompactor';}
 function isMarkCompactorSummaryEvent(event){return event.title==='V8.GCMarkCompactorSummary';}
 function isMarkCompactorMarkingSummaryEvent(event){return event.title==='V8.GCMarkCompactorMarkingSummary';}
+function isScavengerStackScanningEvent(event){return event.title==='V8.GCScavengerStackScanning';}
 function isIncrementalMarkingEvent(event){return event.title.startsWith('V8.GCIncrementalMarking');}
 function isLatencyMarkCompactorEvent(event){return event.title==='V8.GCFinalizeMC';}
 function isMemoryMarkCompactorEvent(event){return event.title==='V8.GCFinalizeMCReduceMemory';}
@@ -8367,7 +8154,7 @@
 return TOP_GC_EVENTS[event.title];}
 function topGarbageCollectionEventNames(){return Object.values(TOP_GC_EVENTS);}
 function subGarbageCollectionEventName(event){const topEvent=findParent(event,isTopGarbageCollectionEvent);const prefix=topEvent?topGarbageCollectionEventName(topEvent):'unknown';const name=event.title.replace('V8.GC_MC_','').replace('V8.GC_SCAVENGER_','').replace('V8.GC_','').replace(/_/g,'-').toLowerCase();return prefix+'-'+name;}
-function jsExecutionThreads(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let threads=[];for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;threads.push(rendererHelper.mainThread);threads=threads.concat(rendererHelper.dedicatedWorkerThreads);threads=threads.concat(rendererHelper.foregroundWorkerThreads);}
+function jsExecutionThreads(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let threads=[];for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;threads.push(rendererHelper.mainThread);threads=threads.concat(rendererHelper.dedicatedWorkerThreads);threads=threads.concat(rendererHelper.serviceWorkerThreads);threads=threads.concat(rendererHelper.foregroundWorkerThreads);}
 return threads;}
 function groupAndProcessEvents(model,filterCallback,groupCallback,processCallback,groups){const groupToEvents={};if(groups){for(const group of groups){groupToEvents[group]=[];}}
 const threads=jsExecutionThreads(model);for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;const group=groupCallback(event);if(groups&&!(group in groupToEvents)){continue;}
@@ -8375,6 +8162,8 @@
 for(const[group,events]of Object.entries(groupToEvents)){processCallback(group,events);}}
 function filterEvents(model,filterCallback){const threads=jsExecutionThreads(model);const events=[];for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;events.push(event);}}
 return events;}
+function filterAndOrderEvents(model,filterCallback,keyCallback){const threads=jsExecutionThreads(model);const events={};for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;const key=keyCallback(event);if(events[key]){events[key].push(event);}else{events[key]=[event];}}}
+return events;}
 function unionOfIntervals(intervals){if(intervals.length===0)return[];return tr.b.math.mergeRanges(intervals.map(x=>{return{min:x.start,max:x.end};}),1e-6,function(ranges){return{start:ranges.reduce((acc,x)=>Math.min(acc,x.min),ranges[0].min),end:ranges.reduce((acc,x)=>Math.max(acc,x.max),ranges[0].max)};});}
 function hasV8Stats(globalMemoryDump){let v8stats=undefined;globalMemoryDump.iterateContainerDumps(function(dump){v8stats=v8stats||dump.getMemoryAllocatorDumpByFullName('v8');});return!!v8stats;}
 function rangeForMemoryDumps(model){const startOfFirstDumpWithV8=model.globalMemoryDumps.filter(hasV8Stats).reduce((start,dump)=>Math.min(start,dump.start),Infinity);if(startOfFirstDumpWithV8===Infinity)return new tr.b.math.Range();return tr.b.math.Range.fromExplicitRange(startOfFirstDumpWithV8,Infinity);}
@@ -8389,8 +8178,10 @@
 function addMutatorUtilization(metricName,eventFilter,timeWindows,rendererHelpers,histograms){const histogramMap=new Map();for(const timeWindow of timeWindows){const summaryOptions={avg:false,count:false,max:false,min:true,std:false,sum:false};const description=`The minimum mutator utilization in ${timeWindow}ms time window`;const histogram=histograms.createHistogram(`${metricName}-${timeWindow}ms_window`,tr.b.Unit.byName.normalizedPercentage_biggerIsBetter,[],{summaryOptions,description});histogramMap.set(timeWindow,histogram);}
 for(const rendererHelper of rendererHelpers){if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread===undefined)continue;const pauses=[];for(const event of rendererHelper.mainThread.sliceGroup.childEvents()){if(eventFilter(event)&&event.end>event.start){pauses.push({start:event.start,end:event.end});}}
 pauses.sort((a,b)=>a.start-b.start);const start=rendererHelper.mainThread.bounds.min;const end=rendererHelper.mainThread.bounds.max;for(const timeWindow of timeWindows){const mu=mutatorUtilization(start,end,timeWindow,pauses);histogramMap.get(timeWindow).addSample(mu.min);}}}
-return{addMutatorUtilization,findParent,forcedGCEventName,filterEvents,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,topGarbageCollectionEventNames,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP={'BlinkGC.AtomicPauseMarkEpilogue':'blink-gc-atomic-pause-mark-epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink-gc-atomic-pause-mark-prologue','BlinkGC.AtomicPauseMarkRoots':'blink-gc-atomic-pause-mark-roots','BlinkGC.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step','BlinkGC.UnifiedMarkingStep':'blink-gc-unified-marking-by-v8','BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact'};const BLINK_TOP_GC_ROOTS_MARKING_EVENTS=['BlinkGC.VisitRoots'];const BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure'];const BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.IncrementalMarkingStep','BlinkGC.UnifiedMarkingStep'];const BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking',].concat(BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS);const BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS=['BlinkGC.ConcurrentMarkingStep'];const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation'];const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS=['BlinkGC.ConcurrentSweepingStep'];const BLINK_TOP_GC_EVENTS=Object.keys(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP).concat(BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP[event.title];}
+return{addMutatorUtilization,findParent,forcedGCEventName,filterEvents,filterAndOrderEvents,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isScavengerStackScanningEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,topGarbageCollectionEventNames,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP={'BlinkGC.AtomicPauseMarkEpilogue':'blink-gc-atomic-pause-mark-epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink-gc-atomic-pause-mark-prologue','BlinkGC.AtomicPauseMarkRoots':'blink-gc-atomic-pause-mark-roots','BlinkGC.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step','BlinkGC.UnifiedMarkingStep':'blink-gc-unified-marking-by-v8','BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact'};const BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP={'BlinkGC.AtomicPauseMarkEpilogue':'blink:gc:main_thread:cycle:full:atomic:mark:epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink:gc:main_thread:cycle:full:atomic:mark:prologue','BlinkGC.AtomicPauseMarkRoots':'blink:gc:main_thread:cycle:full:atomic:mark:roots','BlinkGC.IncrementalMarkingStartMarking':'blink:gc:main_thread:cycle:full:incremental:mark:start','BlinkGC.IncrementalMarkingStep':'blink:gc:main_thread:cycle:full:incremental:mark:step','BlinkGC.UnifiedMarkingStep':'unified:gc:main_thread:cycle:full:mark:step','BlinkGC.CompleteSweep':'blink:gc:main_thread:cycle:full:sweep:complete','BlinkGC.LazySweepInIdle':'blink:gc:main_thread:cycle:full:sweep:idle','BlinkGC.LazySweepOnAllocation':'blink:gc:main_thread:cycle:full:sweep:on_allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink:gc:main_thread:cycle:full:atomic:sweep:compact'};const BLINK_TOP_GC_ROOTS_MARKING_EVENTS=['BlinkGC.VisitRoots'];const BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure'];const BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.IncrementalMarkingStep','BlinkGC.UnifiedMarkingStep'];const BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking',].concat(BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS);const BLINK_GC_FORCED_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking','BlinkGC.MarkBailOutObjects','BlinkGC.MarkFlushV8References','BlinkGC.MarkFlushEphemeronPairs',];const BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS=['BlinkGC.ConcurrentMarkingStep'];const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation'];const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS=['BlinkGC.ConcurrentSweepingStep'];const BLINK_TOP_GC_EVENTS=Object.keys(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP).concat(BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP[event.title];}
 function blinkGarbageCollectionEventNames(){return Object.values(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP);}
+function blinkGarbageCollectionEventNewName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP[event.title];}
+function blinkGarbageCollectionEventNewNames(){return Object.values(BLINK_NON_AGGREGATED_GC_EVENTS_NEW_NAMES_MAP);}
 function isNonForcedEvent(event){return(!event.args||!event.args.forced)&&!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);}
 function isNonForcedBlinkGarbageCollectionEvent(event){return BLINK_TOP_GC_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedNonAggregatedBlinkGarbageCollectionEvent(event){return event.title in BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP&&isNonForcedEvent(event);}
@@ -8401,35 +8192,33 @@
 function
 isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent(event){return BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedBlinkGarbageCollectionForegroundMarkingEvent(event){return BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent(event){return BLINK_GC_FORCED_FOREGROUND_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent(event){return BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedBlinkGarbageCollectionForegroundSweepingEvent(event){return BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent(event){return BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
 function isNonNestedNonForcedBlinkGarbageCollectionEvent(event){return isNonForcedBlinkGarbageCollectionEvent(event)&&!tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isGarbageCollectionEvent);}
-function blinkGcMetric(histograms,model){addDurationOfTopEvents(histograms,model);addDurationOfAtomicPause(histograms,model);addDurationOfAtomicPauseTransitiveClosure(histograms,model);addTotalDurationOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);addTotalDurationOfRootsMarking(histograms,model);addTotalDurationOfMarkingTransitiveClosure(histograms,model);addTotalDurationOfForegroundMarking(histograms,model);addTotalDurationOfBackgroundMarking(histograms,model);addTotalDurationOfForegroundSweeping(histograms,model);addTotalDurationOfBackgroundSweeping(histograms,model);}
-tr.metrics.MetricRegistry.register(blinkGcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
-function createNumericForTotalEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:true,max:false,min:false,std:false,sum:true,percentile:[0.90]});return n;}
-function createNumericForUnifiedEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:true,max:true,min:false,std:false,sum:true,percentile:[0.90]});return n;}
-function addDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedNonAggregatedBlinkGarbageCollectionEvent,blinkGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForTopEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},blinkGarbageCollectionEventNames());}
-function addDurationOfAtomicPause(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionAtomicPauseEvent,event=>event.args.epoch,function(group,events){const cpuDuration=createNumericForTopEventTime('blink-gc-atomic-pause');cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));histograms.addHistogram(cpuDuration);});}
-function addDurationOfAtomicPauseTransitiveClosure(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent,event=>event.args.epoch,function(group,events){const cpuDuration=createNumericForTopEventTime('blink-gc-atomic-pause-mark-transitive-closure');cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));histograms.addHistogram(cpuDuration);});}
-function addTotalDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionEvent,event=>'blink-gc-total',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-total']);}
-function addTotalDurationOfRootsMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionRootsMarkingEvent,event=>'blink-gc-mark-roots',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-mark-roots']);}
-function addTotalDurationOfMarkingTransitiveClosure(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent,event=>'blink-gc-mark-transitive-closure',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-mark-transitive-closure']);}
-function addTotalDurationOfForegroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForegroundMarkingEvent,event=>'blink-gc-mark-foreground',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-mark-foreground']);}
-function addTotalDurationOfBackgroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent,event=>'blink-gc-mark-background',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-mark-background']);}
-function addTotalDurationOfForegroundSweeping(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForegroundSweepingEvent,event=>'blink-gc-sweep-foreground',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-sweep-foreground']);}
-function addTotalDurationOfBackgroundSweeping(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent,event=>'blink-gc-sweep-background',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['blink-gc-sweep-background']);}
+function blinkGcMetric(histograms,model){addDurationOfTopEvents(histograms,model);addDurationOfAtomicPause(histograms,model);addDurationOfAtomicPauseTransitiveClosure(histograms,model);addTotalDurationOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);addTotalDurationOfRootsMarking(histograms,model);addTotalDurationOfMarkingTransitiveClosure(histograms,model);addTotalDurationOfForegroundMarking(histograms,model);addTotalDurationOfForcedForegroundMarking(histograms,model);addTotalDurationOfBackgroundMarking(histograms,model);addTotalDurationOfForegroundSweeping(histograms,model);addTotalDurationOfBackgroundSweeping(histograms,model);}
+function getEventEpochUniqueId(event){return event.parentContainer.parent.stableId+':'+event.args.epoch;}
+tr.metrics.MetricRegistry.register(blinkGcMetric);const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForEventTime(name){const n=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:true,std:true,sum:true,percentile:[0.90]});return n;}
+function addDurationOfTopEvents(histograms,model){const nameToNumeric={};const nameToEpochNumeric={};for(const name of blinkGarbageCollectionEventNames()){nameToNumeric[name]=createNumericForEventTime(name);}
+for(const name of blinkGarbageCollectionEventNewNames()){nameToEpochNumeric[name]=createNumericForEventTime(name);}
+tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedNonAggregatedBlinkGarbageCollectionEvent,getEventEpochUniqueId,function(epoch,events){const namesToPerEpochDurations={};for(const event of events){nameToNumeric[blinkGarbageCollectionEventName(event)].addSample(event.cpuDuration);const name=blinkGarbageCollectionEventNewName(event);namesToPerEpochDurations[name]=(namesToPerEpochDurations[name]||0)+event.cpuDuration;}
+for(const name in namesToPerEpochDurations){nameToEpochNumeric[name].addSample(namesToPerEpochDurations[name]);}});for(const name of blinkGarbageCollectionEventNames()){histograms.addHistogram(nameToNumeric[name]);}
+for(const name of blinkGarbageCollectionEventNewNames()){histograms.addHistogram(nameToEpochNumeric[name]);}}
+function addIndividualDurationsOfEvents(histograms,model,name,filter){const cpuDuration=createNumericForEventTime(name);tr.metrics.v8.utils.groupAndProcessEvents(model,filter,event=>name,function(group,events){for(const event of events){cpuDuration.addSample(event.cpuDuration);}},[name]);histograms.addHistogram(cpuDuration);}
+function addPerEpochDurationsOfEvents(histograms,model,name,filter){const cpuDuration=createNumericForEventTime(name);tr.metrics.v8.utils.groupAndProcessEvents(model,filter,getEventEpochUniqueId,function(epoch,events){cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));});histograms.addHistogram(cpuDuration);}
+function addDurationOfAtomicPause(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-atomic-pause',isNonForcedBlinkGarbageCollectionAtomicPauseEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:atomic',isNonForcedBlinkGarbageCollectionAtomicPauseEvent);}
+function addDurationOfAtomicPauseTransitiveClosure(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-atomic-pause-mark-transitive-closure',isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:atomic:mark:transitive_closure',isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent);}
+function addTotalDurationOfTopEvents(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-total',isNonForcedBlinkGarbageCollectionEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full',isNonForcedBlinkGarbageCollectionEvent);}
+function addTotalDurationOfRootsMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-roots',isNonForcedBlinkGarbageCollectionRootsMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:roots',isNonForcedBlinkGarbageCollectionRootsMarkingEvent);}
+function addTotalDurationOfMarkingTransitiveClosure(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-transitive-closure',isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:transitive_closure',isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent);}
+function addTotalDurationOfForegroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-foreground',isNonForcedBlinkGarbageCollectionForegroundMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark',isNonForcedBlinkGarbageCollectionForegroundMarkingEvent);}
+function addTotalDurationOfForcedForegroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-foreground-forced',isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:mark:forced',isNonForcedBlinkGarbageCollectionForcedForegroundMarkEvent);}
+function addTotalDurationOfBackgroundMarking(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-mark-background',isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:concurrent_thread:cycle:full:mark',isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent);}
+function addTotalDurationOfForegroundSweeping(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-sweep-foreground',isNonForcedBlinkGarbageCollectionForegroundSweepingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:main_thread:cycle:full:sweep',isNonForcedBlinkGarbageCollectionForegroundSweepingEvent);}
+function addTotalDurationOfBackgroundSweeping(histograms,model){addIndividualDurationsOfEvents(histograms,model,'blink-gc-sweep-background',isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent);addPerEpochDurationsOfEvents(histograms,model,'blink:gc:concurrent_thread:cycle:full:sweep',isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent);}
 function isV8OrBlinkTopLevelGarbageCollectionEvent(event){return tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent(event)||isNonNestedNonForcedBlinkGarbageCollectionEvent(event);}
-function addTotalDurationOfBlinkAndV8TopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8OrBlinkTopLevelGarbageCollectionEvent,event=>'unified-gc-total',function(name,events){const cpuDuration=createNumericForUnifiedEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
-histograms.addHistogram(cpuDuration);},['unified-gc-total']);}
+function addTotalDurationOfBlinkAndV8TopEvents(histograms,model){addIndividualDurationsOfEvents(histograms,model,'unified-gc-total',isV8OrBlinkTopLevelGarbageCollectionEvent);}
 return{blinkGcMetric,};});'use strict';tr.exportTo('tr.metrics.blink',function(){function leakDetectionMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper===undefined){throw new Error('Chrome is not present.');}
 const rendererHelpers=modelHelper.rendererHelpers;if(Object.keys(rendererHelpers).length===0){throw new Error('Renderer process is not present.');}
 const pids=Object.keys(rendererHelpers);const chromeDumps=tr.metrics.sh.splitGlobalDumpsByBrowserName(model,undefined).get('chrome');const sumCounter=new Map();for(const pid of pids){for(const[key,count]of countLeakedBlinkObjects(chromeDumps,pid)){sumCounter.set(key,(sumCounter.get(key)||0)+count);}}
@@ -8440,10 +8229,11 @@
 return diffCounter;}
 function countBlinkObjects(dump,pid){const counter=new Map();const processesMemoryDumps=dump.processMemoryDumps;if(processesMemoryDumps[pid]===undefined)return counter;const blinkObjectsDump=processesMemoryDumps[pid].memoryAllocatorDumps.find(dump=>dump.fullName==='blink_objects');for(const v of blinkObjectsDump.children){counter.set(v.name,v.numerics.object_count.value);}
 return counter;}
-return{leakDetectionMetric,};});'use strict';tr.exportTo('tr.metrics.console',function(){const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e4,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;const SOURCES=['all','js','network'];function consoleErrorMetric(histograms,model){const counts={};for(const source of SOURCES){counts[source]=0;}
-for(const slice of model.getDescendantEvents()){if(slice.category==='blink.console'&&slice.title==='ConsoleMessage::Error'){const source=slice.args.source.toLowerCase();counts.all++;if(source in counts){counts[source]++;}}
-if(slice.category==='v8.console'&&(slice.title==='V8ConsoleMessage::Exception'||slice.title==='V8ConsoleMessage::Error'||slice.title==='V8ConsoleMessage::Assert')){counts.all++;counts.js++;}}
-for(const source of SOURCES){histograms.createHistogram(`console:error:${source}`,tr.b.Unit.byName.count_smallerIsBetter,counts[source],{description:`Number of ${source} console error messages`,summaryOptions:SUMMARY_OPTIONS});}}
+return{leakDetectionMetric,};});'use strict';tr.exportTo('tr.metrics.console',function(){const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e4,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;const SOURCES=['all','js','network'];function consoleErrorMetric(histograms,model){const counts={};for(const source of SOURCES){counts[source]={count:0,details:[]};}
+for(const slice of model.getDescendantEvents()){if(slice.category==='blink.console'&&slice.title==='ConsoleMessage::Error'){const source=slice.args.source.toLowerCase();counts.all.count++;if(slice.args.message){counts.all.details.push({pid:slice.getProcess().pid,...slice.args.message});}
+if(source in counts){counts[source].count++;if(slice.args.message){counts[source].details.push({pid:slice.getProcess().pid,...slice.args.message});}}}
+if(slice.category==='v8.console'&&(slice.title==='V8ConsoleMessage::Exception'||slice.title==='V8ConsoleMessage::Error'||slice.title==='V8ConsoleMessage::Assert')){counts.all.count++;counts.js.count++;}}
+for(const source of SOURCES){const hist=histograms.createHistogram(`console:error:${source}`,tr.b.Unit.byName.count_smallerIsBetter,{value:counts[source].count,diagnostics:{details:new tr.v.d.GenericSet(counts[source].details)}},{description:`Number of ${source} console error messages`,summaryOptions:SUMMARY_OPTIONS,});}}
 tr.metrics.MetricRegistry.register(consoleErrorMetric);return{consoleErrorMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function getCpuSnapshotsFromModel(model){const snapshots=[];for(const pid in model.processes){const snapshotInstances=model.processes[pid].objects.getAllInstancesNamed('CPUSnapshots');if(!snapshotInstances)continue;for(const object of snapshotInstances[0].snapshots){snapshots.push(object.args.processes);}}
 return snapshots;}
 function getProcessSumsFromSnapshot(snapshot){const processSums=new Map();for(const processData of snapshot){const processName=processData.name;if(!(processSums.has(processName))){processSums.set(processName,{sum:0.0,paths:new Set()});}
@@ -8458,7 +8248,7 @@
 tr.metrics.MetricRegistry.register(cpuProcessMetric);return{cpuProcessMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function mediaMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(chromeHelper===undefined)return;for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){const mainThread=rendererHelper.mainThread;if(mainThread===undefined)continue;const videoThreads=rendererHelper.process.findAllThreadsMatching(thread=>(thread.name?thread.name.startsWith('ThreadPoolSingleThreadSharedForegroundBlocking'):false));const compositorThread=rendererHelper.compositorThread;if(compositorThread!==undefined){videoThreads.push(compositorThread);}
 const audioThreads=rendererHelper.process.findAllThreadsNamed('AudioOutputDevice');if(audioThreads.length===0&&videoThreads.length===0)continue;const processData=new PerProcessData();processData.recordPlayStarts(mainThread);if(!processData.hasPlaybacks)continue;if(videoThreads.length!==0){processData.calculateTimeToVideoPlays(videoThreads);processData.calculateDroppedFrameCounts(videoThreads);}
 if(audioThreads.length!==0){processData.calculateTimeToAudioPlays(audioThreads);}
-processData.calculateSeekTimes(mainThread);processData.calculateBufferingTimes(mainThread);processData.addMetricToHistograms(histograms);}}
+processData.calculateSeekTimes(mainThread);processData.calculateBufferingTimes(mainThread);const allThreads=rendererHelper.process.findAllThreadsMatching(function(){return true;});processData.calculateVideoPlaybackQuality(allThreads);processData.addMetricToHistograms(histograms);}}
 class PerProcessData{constructor(){this.playbackIdToDataMap_=new Map();}
 recordPlayStarts(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::DoLoad'){const id=event.args.id;if(this.playbackIdToDataMap_.has(id)){throw new Error('Unexpected multiple initialization of a media playback');}
 this.playbackIdToDataMap_.set(id,new PerPlaybackData(event.start));}}}
@@ -8468,15 +8258,18 @@
 calculateSeekTimes(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::DoSeek'){this.getPerPlaybackObject_(event.args.id).processDoSeek(event.args.target,event.start);}else if(event.title==='WebMediaPlayerImpl::OnPipelineSeeked'){this.getPerPlaybackObject_(event.args.id).processOnPipelineSeeked(event.args.target,event.start);}else if(event.title==='WebMediaPlayerImpl::BufferingHaveEnough'){this.getPerPlaybackObject_(event.args.id).processBufferingHaveEnough(event.start);}}}
 calculateBufferingTimes(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::OnEnded'){this.getPerPlaybackObject_(event.args.id).processOnEnded(event.start,event.args.duration);}}}
 calculateDroppedFrameCounts(videoThreads){for(const thread of videoThreads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoFramesDropped'){this.getPerPlaybackObject_(event.args.id).processVideoFramesDropped(event.args.count);}}}}
+calculateVideoPlaybackQuality(threads){for(const thread of threads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoPlaybackRoughness'){this.getPerPlaybackObject_(event.args.id).processVideoRoughness(event.args.roughness);}else if(event.title==='VideoPlaybackFreezing'){this.getPerPlaybackObject_(event.args.id).processVideoFreezing(event.args.freezing);}}}}
 addMetricToHistograms(histograms){for(const[id,playbackData]of this.playbackIdToDataMap_){playbackData.addMetricToHistograms(histograms);}}
 getPerPlaybackObject_(playbackId){let perPlaybackObject=this.playbackIdToDataMap_.get(playbackId);if(perPlaybackObject===undefined){perPlaybackObject=new PerPlaybackData(undefined);this.playbackIdToDataMap_.set(playbackId,perPlaybackObject);}
 return perPlaybackObject;}}
-class PerPlaybackData{constructor(playStartTime){this.playStart_=playStartTime;this.timeToVideoPlay_=undefined;this.timeToAudioPlay_=undefined;this.bufferingTime_=undefined;this.droppedFrameCount_=0;this.seekError_=false;this.seekTimes_=new Map();this.currentSeek_=undefined;}
+class PerPlaybackData{constructor(playStartTime){this.playStart_=playStartTime;this.timeToVideoPlay_=undefined;this.timeToAudioPlay_=undefined;this.bufferingTime_=undefined;this.droppedFrameCount_=0;this.seekError_=false;this.seekTimes_=new Map();this.currentSeek_=undefined;this.roughness_=undefined;this.freezing_=undefined;}
 get timeToVideoPlay(){return this.timeToVideoPlay_;}
 get timeToAudioPlay(){return this.timeToAudioPlay_;}
 get bufferingTime(){return this.bufferingTime_;}
 get droppedFrameCount(){return(this.timeToVideoPlay_!==undefined)?this.droppedFrameCount_:undefined;}
 get seekTimes(){if(this.seekError_||this.currentSeek_!==undefined)return new Map();return this.seekTimes_;}
+get roughness(){return this.roughness_;}
+get freezing(){return this.freezing_;}
 processVideoRenderTime(videoRenderTime){if(this.playStart_!==undefined&&this.timeToVideoPlay_===undefined){this.timeToVideoPlay_=videoRenderTime-this.playStart_;}}
 processAudioRenderTime(audioRenderTime){if(this.playStart_!==undefined&&this.timeToAudioPlay_===undefined){this.timeToAudioPlay_=audioRenderTime-this.playStart_;}}
 processVideoFramesDropped(count){this.droppedFrameCount_+=count;}
@@ -8490,22 +8283,26 @@
 if(currentSeek.pipelineSeekTime===undefined){return;}
 currentSeek.seekTime=time-currentSeek.startTime;this.currentSeek_=undefined;}
 processOnEnded(playEndTime,duration){if(this.playStart_===undefined)return;if(this.seekTimes_.size!==0||this.seekError_)return;if(this.bufferingTime_!==undefined)return;duration=tr.b.convertUnit(duration,tr.b.UnitPrefixScale.METRIC.NONE,tr.b.UnitPrefixScale.METRIC.MILLI);const playTime=playEndTime-this.playStart_;if(this.timeToVideoPlay_!==undefined){this.bufferingTime_=playTime-duration-this.timeToVideoPlay_;}else if(this.timeToAudioPlay!==undefined){this.bufferingTime_=playTime-duration-this.timeToAudioPlay_;}}
+processVideoRoughness(roughness){if(this.roughness_===undefined||this.roughness_>roughness){this.roughness_=roughness;}}
+processVideoFreezing(freezing){if(this.freezing_===undefined||this.freezing_>freezing){this.freezing_=freezing;}}
 addMetricToHistograms(histograms){this.addSample_(histograms,'time_to_video_play',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.timeToVideoPlay);this.addSample_(histograms,'time_to_audio_play',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.timeToAudioPlay);this.addSample_(histograms,'dropped_frame_count',tr.b.Unit.byName.count_smallerIsBetter,this.droppedFrameCount);for(const[key,value]of this.seekTimes.entries()){const keyString=key.toString().replace('.','_');this.addSample_(histograms,'pipeline_seek_time_'+keyString,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value.pipelineSeekTime);this.addSample_(histograms,'seek_time_'+keyString,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value.seekTime);}
-this.addSample_(histograms,'buffering_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.bufferingTime);}
+this.addSample_(histograms,'buffering_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.bufferingTime);this.addSample_(histograms,'roughness',tr.b.Unit.byName.count_smallerIsBetter,this.roughness);this.addSample_(histograms,'freezing',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.freezing);}
 addSample_(histograms,name,unit,sample){if(sample===undefined)return;const histogram=histograms.getHistogramNamed(name);if(histogram===undefined){histograms.createHistogram(name,unit,sample);}else{histogram.addSample(sample);}}}
-tr.metrics.MetricRegistry.register(mediaMetric);return{mediaMetric,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const UNKNOWN_THREAD_NAME='Unknown';const CATEGORY_THREAD_MAP=new Map();CATEGORY_THREAD_MAP.set('total_all',[/.*/]);CATEGORY_THREAD_MAP.set('browser',[/^Browser Compositor$/,/^CrBrowserMain$/]);CATEGORY_THREAD_MAP.set('display_compositor',[/^VizCompositorThread$/]);CATEGORY_THREAD_MAP.set('GPU',[/^Chrome_InProcGpuThread$/,/^CrGpuMain$/]);CATEGORY_THREAD_MAP.set('IO',[/IOThread/]);CATEGORY_THREAD_MAP.set('raster',[/CompositorTileWorker/]);CATEGORY_THREAD_MAP.set('renderer_compositor',[/^Compositor$/]);CATEGORY_THREAD_MAP.set('renderer_main',[/^CrRendererMain$/]);CATEGORY_THREAD_MAP.set('total_rendering',[/^Browser Compositor$/,/^Chrome_InProcGpuThread$/,/^Compositor$/,/CompositorTileWorker/,/^CrBrowserMain$/,/^CrGpuMain$/,/^CrRendererMain$/,/IOThread/,/^VizCompositorThread$/]);const ALL_CATEGORIES=[...CATEGORY_THREAD_MAP.keys(),'other'];function addValueToMap_(map,key,value){const oldValue=map.get(key)||0;map.set(key,oldValue+value);}
-function categoryShouldHaveBreakdown(category){return category==='total_all'||category==='total_rendering';}
+tr.metrics.MetricRegistry.register(mediaMetric);return{mediaMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function memoryAblationMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper.gpuHelper)return;const gpuProcess=modelHelper.gpuHelper.process;const events=[...gpuProcess.findTopmostSlicesNamed('Memory.GPU.PeakMemoryUsage.AblationTimes')];const allocHistogram=histograms.createHistogram('Ablation Alloc',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,10000,20),description:'The amount of time spent allocating the ablation '+'memory',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const deallocHistogram=histograms.createHistogram('Ablation Dealloc',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,10000,20),description:'The amount of time spent deallocating the ablation '+'memory',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});for(let i=0;i<events.length;i++){allocHistogram.addSample(events[i].args.alloc);deallocHistogram.addSample(events[i].args.dealloc);}}
+tr.metrics.MetricRegistry.register(memoryAblationMetric,{requiredCategories:['gpu.memory'],});return{memoryAblationMetric,};});'use strict';tr.exportTo('tr.metrics.pa',function(){function pcscanMetric(histograms,model){function createNumericForProcess(name,processName,desc){function createNumericForEventTime(name,desc){const n=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);n.description=desc;n.customizeSummaryOptions({avg:true,count:true,max:true,min:true,std:true,sum:true});return n;}
+const scheme=['pa','pcscan',processName];if(name)scheme.push(name);return createNumericForEventTime(scheme.join(':'),desc);}
+function createHistsForProcess(processName){return{scan:createNumericForProcess('scan',processName,'Time for scanning heap for quarantine pointers'),sweep:createNumericForProcess('sweep',processName,'Time for sweeping quarantine'),clear:createNumericForProcess('clear',processName,'Time for clearing quarantine entries'),total:createNumericForProcess('',processName,'Total time for PCScan execution')};}
+function addSample(hists,slice){if(!(slice instanceof tr.model.ThreadSlice))return;if(slice.category!=='partition_alloc')return;if(slice.title==='PCScan.Scan'){hists.scan.addSample(slice.duration);}else if(slice.title==='PCScan.Sweep'){hists.sweep.addSample(slice.duration);}else if(slice.title==='PCScan.Clear'){hists.clear.addSample(slice.duration);}else if(slice.title==='PCScan'){hists.total.addSample(slice.duration);}}
+function addHistsForProcess(processHists,processHelpers){for(const helper of Object.values(processHelpers)){const processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(helper.process.name);if(!processHists.has(processName)){processHists.set(processName,createHistsForProcess(processName));}
+for(const slice of helper.process.getDescendantEvents()){addSample(processHists.get(processName),slice);}}}
+const helper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const processHists=new Map();addHistsForProcess(processHists,helper.browserHelpers);addHistsForProcess(processHists,helper.rendererHelpers);for(const hists of processHists.values()){for(const hist of Object.values(hists)){histograms.addHistogram(hist);}}}
+tr.metrics.MetricRegistry.register(pcscanMetric);return{pcscanMetric,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const UNKNOWN_THREAD_NAME='Unknown';const CATEGORY_THREAD_MAP=new Map();CATEGORY_THREAD_MAP.set('total_all',[/.*/]);CATEGORY_THREAD_MAP.set('browser',[/^Browser Compositor$/,/^CrBrowserMain$/]);CATEGORY_THREAD_MAP.set('display_compositor',[/^VizCompositorThread$/]);CATEGORY_THREAD_MAP.set('GPU',[/^Chrome_InProcGpuThread$/,/^CrGpuMain$/]);CATEGORY_THREAD_MAP.set('IO',[/IOThread/]);CATEGORY_THREAD_MAP.set('raster',[/CompositorTileWorker/]);CATEGORY_THREAD_MAP.set('renderer_compositor',[/^Compositor$/]);CATEGORY_THREAD_MAP.set('renderer_main',[/^CrRendererMain$/]);CATEGORY_THREAD_MAP.set('total_rendering',[/^Browser Compositor$/,/^Chrome_InProcGpuThread$/,/^Compositor$/,/CompositorTileWorker/,/^CrBrowserMain$/,/^CrGpuMain$/,/^CrRendererMain$/,/IOThread/,/^VizCompositorThread$/]);const ALL_CATEGORIES=[...CATEGORY_THREAD_MAP.keys(),'other'];function addValueToMap_(map,key,value){const oldValue=map.get(key)||0;map.set(key,oldValue+value);}
+function addToArrayInMap_(map,key,value){const arr=map.get(key)||[];arr.push(value);map.set(key,arr);}
 function*getCategories_(threadName){let isOther=true;for(const[category,regexps]of CATEGORY_THREAD_MAP){for(const regexp of regexps){if(regexp.test(threadName)){if(category!=='total_all')isOther=false;yield category;break;}}}
 if(isOther)yield'other';}
-function isSubset_(regexps1,regexps2){for(const r1 of regexps1){if(regexps2.find(r2=>r2.toString()===r1.toString())===undefined){return false;}}
-return true;}
-function addCpuUtilizationHistograms(histograms,model,segments,segmentCostFunc,histogramNameFunc,description,unit){if(!unit)unit=tr.b.Unit.byName.unitlessNumber;const histogramMap=new Map();for(const category of ALL_CATEGORIES){const histogram=histograms.createHistogram(histogramNameFunc(category),unit,[],{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(1,50,20),description,summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histogramMap.set(category,histogram);}
-for(const[category,regexps]of CATEGORY_THREAD_MAP){const relatedCategories=new tr.v.d.RelatedNameMap();const histogram=histogramMap.get(category);for(const[otherCategory,otherRegexps]of CATEGORY_THREAD_MAP){if(otherCategory===category)continue;if(category!=='all'&&!isSubset_(otherRegexps,regexps))continue;const otherHistogram=histogramMap.get(otherCategory);relatedCategories.set(otherCategory,otherHistogram.name);}
-if([...relatedCategories.values()].length>0){histogram.diagnostics.set('breakdown',relatedCategories);}}
-for(const segment of segments){const threadValues=new Map();for(const thread of model.getAllThreads()){addValueToMap_(threadValues,thread.name||UNKNOWN_THREAD_NAME,segmentCostFunc(thread,segment));}
-const categoryValues=new Map();const breakdowns=new Map();for(const[threadName,coresPerSec]of threadValues){for(const category of getCategories_(threadName)){addValueToMap_(categoryValues,category,coresPerSec);if(!categoryShouldHaveBreakdown(category))continue;if(!breakdowns.has(category)){breakdowns.set(category,new tr.v.d.Breakdown());}
-breakdowns.get(category).set(threadName,coresPerSec);}}
-for(const category of ALL_CATEGORIES){const value=categoryValues.get(category)||0;const diagnostics=new tr.v.d.DiagnosticMap();const breakdown=breakdowns.get(category);if(breakdown)diagnostics.set('breakdown',breakdown);const histogram=histogramMap.get(category);histogram.addSample(value,diagnostics);}}}
+function addCpuUtilizationHistograms(histograms,model,segments,segmentCostFunc,histogramNameFunc,description){const categoryValues=new Map();for(const segment of segments){const threadValues=new Map();for(const thread of model.getAllThreads()){addValueToMap_(threadValues,thread.name||UNKNOWN_THREAD_NAME,segmentCostFunc(thread,segment));}
+for(const[threadName,coresPerSec]of threadValues){for(const category of getCategories_(threadName)){addToArrayInMap_(categoryValues,category,coresPerSec);}}}
+const unit=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;for(const category of ALL_CATEGORIES){const values=categoryValues.get(category)||0;if(!values)continue;const avg=values.reduce((sum,e)=>sum+e,0)/segments.length;histograms.createHistogram(histogramNameFunc(category),unit,avg,{description,summaryOptions:{},});}}
 const SUMMARY_OPTIONS={percentile:[0.90,0.95],ci:[0.95],};return{addCpuUtilizationHistograms,SUMMARY_OPTIONS,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const PRESENT_EVENT='Display::FrameDisplayed';const DISPLAY_EVENT='BenchmarkInstrumentation::DisplayRenderingStats';const DRM_EVENT='DrmEventFlipComplete';const SURFACE_FLINGER_EVENT='vsync_before';const COMPOSITOR_FRAME_PRESENTED_EVENT='FramePresented';const MIN_FRAME_LENGTH=0.5;const MIN_FRAME_COUNT=10;const PAUSE_THRESHOLD=20;const ASH_ENVIRONMENT='ash';const BROWSER_ENVIRONMENT='browser';class FrameEvent{constructor(event){this.event_=event;}
 get eventStart(){return this.event_.start;}
 get frameStart(){if(this.event_.title!==DRM_EVENT)return this.event_.start;const data=this.event_.args.data;const TIME=tr.b.UnitScale.TIME;return tr.b.convertUnit(data['vblank.tv_sec'],TIME.SEC,TIME.MILLI_SEC)+
@@ -8531,11 +8328,11 @@
 return legacyEvents;}
 function computeFrameSegments_(events,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const frameEvents=events.map(e=>new FrameEvent(e));const frameSegments=[];for(const segment of segments){const filtered=segment.boundsRange.filterArray(frameEvents,x=>x.eventStart);if(filtered.length<minFrameCount)continue;for(let i=1;i<filtered.length;i++){const duration=filtered[i].frameStart-filtered[i-1].frameStart;frameSegments.push(new FrameSegment(filtered[i-1],duration));}}
 return frameSegments;}
-function addBasicFrameTimeHistograms_(histograms,frameSegments,prefix){const frameTimes=(frameSegments.length===0)?[0]:frameSegments.map(x=>x.duration);histograms.createHistogram(`${prefix}frame_times`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,frameTimes,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),description:'Raw frame times.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram(`${prefix}percentage_smooth`,tr.b.Unit.byName.unitlessNumber_biggerIsBetter,100*tr.b.math.Statistics.sum(frameTimes,(x=>(x<17?1:0)))/frameTimes.length,{description:'Percentage of frames that were hitting 60 FPS.',summaryOptions:{},});}
+function addBasicFrameTimeHistograms_(histograms,frameSegments,prefix){const frameTimes=(frameSegments.length===0)?[0]:frameSegments.map(x=>x.duration);histograms.createHistogram(`${prefix}frame_times`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,frameTimes,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),description:'Raw frame times.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
 function addFrameTimeHistograms(histograms,model,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const events=getDisplayCompositorPresentationEvents_(modelHelper);if(!events)return;addFrameTimeHistogramsHelper(histograms,model,segments,events,'',true,minFrameCount);const eventsExp=getDisplayCompositorPresentationEventsExp_(modelHelper);if(eventsExp&&eventsExp.length>0){addFrameTimeHistogramsHelper(histograms,model,segments,eventsExp,'exp_',false,minFrameCount);}}
-function addFrameTimeHistogramsHelper(histograms,model,segments,events,prefix,addCpuMetrics,minFrameCount){const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,prefix+'');if(addCpuMetrics){tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getCpuTimeForRange(segment.boundsRange),category=>`thread_${category}_cpu_time_per_frame`,'CPU cores of a thread group per frame',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getNumToplevelSlicesForRange(segment.boundsRange),category=>`tasks_per_frame_${category}`,'Number of tasks of a thread group per frame',tr.b.Unit.byName.unitlessNumber_smallerIsBetter);let totalWallTime=0;let totalCpuTime=0;for(const segment of frameSegments){for(const thread of model.getAllThreads()){totalCpuTime+=thread.getCpuTimeForRange(segment.boundsRange);totalWallTime+=thread.getWallTimeForRange(segment.boundsRange);}}
+function addFrameTimeHistogramsHelper(histograms,model,segments,events,prefix,addCpuMetrics,minFrameCount){const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,prefix+'');if(addCpuMetrics){tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getCpuTimeForRange(segment.boundsRange),category=>`thread_${category}_cpu_time_per_frame`,'CPU cores of a thread group per frame');tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getNumToplevelSlicesForRange(segment.boundsRange),category=>`tasks_per_frame_${category}`,'Number of tasks of a thread group per frame');let totalWallTime=0;let totalCpuTime=0;for(const segment of frameSegments){for(const thread of model.getAllThreads()){totalCpuTime+=thread.getCpuTimeForRange(segment.boundsRange);totalWallTime+=thread.getWallTimeForRange(segment.boundsRange);}}
 histograms.createHistogram('cpu_wall_time_ratio',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,totalCpuTime/totalWallTime,{description:'Ratio of total cpu-time vs. wall-time.',summaryOptions:{},});}
-const refreshPeriod=getRefreshPeriod(model,frameSegments.map(fs=>fs.boundsRange));frameSegments.forEach(fs=>fs.updateLength(refreshPeriod));const validFrames=frameSegments.filter(fs=>fs.length>=MIN_FRAME_LENGTH);const totalFrameDuration=tr.b.math.Statistics.sum(frameSegments,fs=>fs.duration);addJankCountHistograms(histograms,validFrames,prefix);const frameLengths=validFrames.map(frame=>frame.length);histograms.createHistogram(prefix+'frame_lengths',tr.b.Unit.byName.unitlessNumber_smallerIsBetter,frameLengths,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,5,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Frame times in vsyncs.'});histograms.createHistogram(prefix+'avg_surface_fps',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,frameLengths.length/tr.b.convertUnit(totalFrameDuration,tr.b.UnitScale.TIME.MILLI_SEC,tr.b.UnitScale.TIME.SEC),{description:'Average frames per second.',summaryOptions:{},});}
+const refreshPeriod=getRefreshPeriod(model,frameSegments.map(fs=>fs.boundsRange));frameSegments.forEach(fs=>fs.updateLength(refreshPeriod));const validFrames=frameSegments.filter(fs=>fs.length>=MIN_FRAME_LENGTH);const totalFrameDuration=tr.b.math.Statistics.sum(frameSegments,fs=>fs.duration);addJankCountHistograms(histograms,validFrames,prefix);const frameLengths=validFrames.map(frame=>frame.length);histograms.createHistogram(prefix+'avg_surface_fps',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,frameLengths.length/tr.b.convertUnit(totalFrameDuration,tr.b.UnitScale.TIME.MILLI_SEC,tr.b.UnitScale.TIME.SEC),{description:'Average frames per second.',summaryOptions:{},});}
 function addUIFrameTimeHistograms(histograms,model,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const events=getUIPresentationEvents_(model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper));if(events.length===0)return;const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,'ui_');}
 function addJankCountHistograms(histograms,validFrames,prefix){const jankEvents=[];for(let i=1;i<validFrames.length;i++){const change=Math.round((validFrames[i].length-validFrames[i-1].length));if(change>0&&change<PAUSE_THRESHOLD){jankEvents.push(validFrames[i].event);}}
 const jankCount=jankEvents.length;const diagnostics=new tr.v.d.DiagnosticMap();diagnostics.set('events',new tr.v.d.RelatedEventSet(jankEvents));diagnostics.set('timestamps',new tr.v.d.GenericSet(jankEvents.map(e=>e.start)));const histogram=histograms.createHistogram(prefix+'jank_count',tr.b.Unit.byName.count_smallerIsBetter,{value:jankCount,diagnostics},{description:'Number of changes in frame rate.',summaryOptions:{},});}
@@ -8546,30 +8343,7 @@
 return{addFrameTimeHistograms,addUIFrameTimeHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const RGB_DECODE_EVENT='ImageFrameGenerator::decode';const YUV_DECODE_EVENT='ImageFrameGenerator::decodeToYUV';const BLINK_GPU_RASTER_DECODE_EVENT='GpuImageDecodeCache::DecodeImage';const BLINK_SOFTWARE_RASTER_DECODE_EVENT='SoftwareImageDecodeCache::'+'DecodeImageInTask';function getImageDecodingEvents_(modelHelper,ranges){if(!modelHelper||!modelHelper.rendererHelpers)return[];const events=[];for(const renderer of Object.values(modelHelper.rendererHelpers)){for(const thread of renderer.rasterWorkerThreads){const slices=thread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title===RGB_DECODE_EVENT||slice.title===YUV_DECODE_EVENT||slice.title===BLINK_GPU_RASTER_DECODE_EVENT||slice.title===BLINK_SOFTWARE_RASTER_DECODE_EVENT){events.push(slice);}}}}
 return events;}
 function addImageDecodeTimeHistograms(histograms,model,segments){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const decodeEvents=getImageDecodingEvents_(modelHelper,segments.map(s=>s.boundsRange));if(!decodeEvents)return;histograms.createHistogram('rgb_decode_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===RGB_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of the Blink RGB decoding path for a chunk '+'of image data (possibly the whole image).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('yuv_decode_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===YUV_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of the Blink YUV decoding path for a '+'chunk of image data (possibly the whole image).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('blink_decode_time_gpu_rasterization',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===BLINK_GPU_RASTER_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of decoding and scaling within the '+'GpuImageDecodeCache for a chunk of image data '+'(possibly the whole image)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('blink_decode_time_software_rasterization',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===BLINK_SOFTWARE_RASTER_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of decoding and scaling within the '+'SoftwareImageDecodeCache for a chunk of image data '+'(possibly the whole image)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
-return{addImageDecodeTimeHistograms};});'use strict';tr.exportTo('tr.metrics.rendering',function(){function eventIsValidGraphicsEvent_(event,eventMap){if(event.title!=='Graphics.Pipeline'||!event.bindId||!event.args||!event.args.step){return false;}
-const bindId=event.bindId;if(eventMap.has(bindId)&&event.args.step in eventMap.get(bindId)){if(event.args.step==='IssueBeginFrame'||event.args.step==='ReceiveBeginFrame'){throw new Error('Unexpected duplicate step: '+event.args.step);}
-return false;}
-return true;}
-function generateBreakdownForCompositorPipelineInClient_(flow){const breakdown=new tr.v.d.Breakdown();breakdown.set('time before GenerateRenderPass',flow.GenerateRenderPass.start-flow.ReceiveBeginFrame.start);breakdown.set('GenerateRenderPass duration',flow.GenerateRenderPass.duration);breakdown.set('GenerateCompositorFrame duration',flow.GenerateCompositorFrame.duration);breakdown.set('SubmitCompositorFrame duration',flow.SubmitCompositorFrame.duration);return breakdown;}
-function generateBreakdownForCompositorPipelineInService_(flow){const breakdown=new tr.v.d.Breakdown();breakdown.set('Processing CompositorFrame on reception',flow.ReceiveCompositorFrame.duration);breakdown.set('Delay before SurfaceAggregation',flow.SurfaceAggregation.start-flow.ReceiveCompositorFrame.end);breakdown.set('SurfaceAggregation duration',flow.SurfaceAggregation.duration);return breakdown;}
-function generateBreakdownForDraw_(drawEvent){const breakdown=new tr.v.d.Breakdown();for(const slice of drawEvent.subSlices){breakdown.set(slice.title,slice.duration);}
-return breakdown;}
-function getDisplayCompositorThread_(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const gpuHelper=chromeHelper.gpuHelper;if(gpuHelper){const thread=gpuHelper.process.findAtMostOneThreadNamed('VizCompositorThread');if(thread){return thread;}}
-if(!chromeHelper.browserProcess)return null;return chromeHelper.browserProcess.findAtMostOneThreadNamed('CrBrowserMain');}
-function getRasterTaskTimes(sourceFrameNumber,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const renderers=modelHelper.telemetryHelper.renderersWithIR;if(renderers.length===0)return;const rasterThreads=renderers[0].rasterWorkerThreads;let earliestStart=undefined;let lastEnd=undefined;for(const rasterThread of rasterThreads){for(const slice of[...rasterThread.findTopmostSlicesNamed('TaskGraphRunner::RunTask')]){if(slice.args&&slice.args.source_frame_number_&&slice.args.source_frame_number_===sourceFrameNumber){if(earliestStart===undefined||slice.start<earliestStart){earliestStart=slice.start;}
-if(lastEnd===undefined||slice.end>lastEnd){lastEnd=slice.end;}}}}
-return{start:earliestStart,end:lastEnd};}
-function addPipelineHistograms(histograms,model,segments){const ranges=segments.map(s=>s.boundsRange);const bindEvents=new Map();for(const thread of model.getAllThreads()){for(const event of thread.sliceGroup.childEvents()){if(!eventIsValidGraphicsEvent_(event,bindEvents))continue;for(const range of ranges){if(range.containsExplicitRangeInclusive(event.start,event.end)){if(!bindEvents.has(event.bindId))bindEvents.set(event.bindId,{});break;}}
-if(bindEvents.has(event.bindId)){bindEvents.get(event.bindId)[event.args.step]=event;}}}
-const dcThread=getDisplayCompositorThread_(model);const drawEvents={};if(dcThread){const events=[...dcThread.findTopmostSlicesNamed('Graphics.Pipeline.DrawAndSwap')];for(const segment of segments){const filteredEvents=segment.boundsRange.filterArray(events,evt=>evt.start);for(const event of filteredEvents){if((event.args&&event.args.status==='canceled')||!event.id.startsWith(':ptr:')){continue;}
-const id=parseInt(event.id.substring(5),16);if(id in drawEvents){throw new Error('Duplicate draw events: '+id);}
-drawEvents[id]=event;}}}
-const issueToReceipt=histograms.createHistogram('pipeline:begin_frame_transport',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency of begin-frame message from the display '+'compositor to the client, including the IPC latency and task-'+'queue time in the client.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const issueToRasterStart=histograms.createHistogram('pipeline:begin_frame_to_raster_start',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame message and '+'the beginning of the first CompositorTask run in the compositor.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const issueToRasterEnd=histograms.createHistogram('pipeline:begin_frame_to_raster_end',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame message and '+'the end of the last CompositorTask run in the compositor.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const receiptToSubmit=histograms.createHistogram('pipeline:begin_frame_to_frame_submission',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame reception and '+'CompositorFrame submission in the renderer.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const submitToAggregate=histograms.createHistogram('pipeline:frame_submission_to_display',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between CompositorFrame submission in the '+'renderer to display in the display-compositor, including IPC '+'latency, task-queue time in the display-compositor, and '+'additional processing (e.g. surface-sync etc.)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const aggregateToDraw=histograms.createHistogram('pipeline:draw',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'How long it takes for the gpu-swap step.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});for(const flow of bindEvents.values()){if(!flow.IssueBeginFrame||!flow.ReceiveBeginFrame||!flow.SubmitCompositorFrame||!flow.SurfaceAggregation){continue;}
-issueToReceipt.addSample(flow.ReceiveBeginFrame.start-
-flow.IssueBeginFrame.start);receiptToSubmit.addSample(flow.SubmitCompositorFrame.end-flow.ReceiveBeginFrame.start,{breakdown:generateBreakdownForCompositorPipelineInClient_(flow)});submitToAggregate.addSample(flow.SurfaceAggregation.end-flow.SubmitCompositorFrame.end,{breakdown:generateBreakdownForCompositorPipelineInService_(flow)});if(flow.SubmitCompositorFrame.parentSlice){const sourceFrameNumber=flow.SubmitCompositorFrame.parentSlice.args.source_frame_number_;const rasterDuration=getRasterTaskTimes(sourceFrameNumber,model);if(rasterDuration&&rasterDuration.start&&rasterDuration.end){const receiveToStart=rasterDuration.start-
-flow.ReceiveBeginFrame.start;const receiveToEnd=rasterDuration.end-flow.ReceiveBeginFrame.end;if(receiveToEnd>0){issueToRasterStart.addSample(receiveToStart>0?receiveToStart:0);issueToRasterEnd.addSample(receiveToEnd);}}}
-if(flow.SurfaceAggregation.args&&flow.SurfaceAggregation.args.display_trace){const displayTrace=flow.SurfaceAggregation.args.display_trace;if(!(displayTrace in drawEvents))continue;const drawEvent=drawEvents[displayTrace];aggregateToDraw.addSample(drawEvent.duration,{breakdown:generateBreakdownForDraw_(drawEvent)});}}}
-return{addPipelineHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const IMPL_THREAD_RENDERING_STATS_EVENT='BenchmarkInstrumentation::ImplThreadRenderingStats';const VISIBLE_CONTENT_DATA='visible_content_area';const APPROXIMATED_VISIBLE_CONTENT_DATA='approximated_visible_content_area';const CHECKERBOARDED_VISIBLE_CONTENT_DATA='checkerboarded_visible_content_area';function addPixelsHistograms(histograms,model,segments){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;const approximatedPixelPercentages=[];const checkerboardedPixelPercentages=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.compositorThread===undefined)continue;const slices=rendererHelper.compositorThread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==IMPL_THREAD_RENDERING_STATS_EVENT)continue;const data=slice.args.data;if(!(VISIBLE_CONTENT_DATA in data)){throw new Error(`${VISIBLE_CONTENT_DATA} is missing`);}
+return{addImageDecodeTimeHistograms};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const IMPL_THREAD_RENDERING_STATS_EVENT='BenchmarkInstrumentation::ImplThreadRenderingStats';const VISIBLE_CONTENT_DATA='visible_content_area';const APPROXIMATED_VISIBLE_CONTENT_DATA='approximated_visible_content_area';const CHECKERBOARDED_VISIBLE_CONTENT_DATA='checkerboarded_visible_content_area';function addPixelsHistograms(histograms,model,segments){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;const approximatedPixelPercentages=[];const checkerboardedPixelPercentages=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.compositorThread===undefined)continue;const slices=rendererHelper.compositorThread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==IMPL_THREAD_RENDERING_STATS_EVENT)continue;const data=slice.args.data;if(!(VISIBLE_CONTENT_DATA in data)){throw new Error(`${VISIBLE_CONTENT_DATA} is missing`);}
 const visibleContentArea=data[VISIBLE_CONTENT_DATA];if(visibleContentArea===0){continue;}
 if(APPROXIMATED_VISIBLE_CONTENT_DATA in data){approximatedPixelPercentages.push(data[APPROXIMATED_VISIBLE_CONTENT_DATA]/visibleContentArea);}
 if(CHECKERBOARDED_VISIBLE_CONTENT_DATA in data){checkerboardedPixelPercentages.push(data[CHECKERBOARDED_VISIBLE_CONTENT_DATA]/visibleContentArea);}}}
@@ -8580,7 +8354,7 @@
 const queueingDurations=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of targetRenderers){const mainThread=rendererHelper.mainThread;const compositorThread=rendererHelper.compositorThread;if(mainThread===undefined||compositorThread===undefined)continue;const beginMainFrameTimes=getEventTimesByBeginFrameId_(mainThread,BEGIN_MAIN_FRAME_EVENT,ranges);const sendBeginFrameTimes=getEventTimesByBeginFrameId_(compositorThread,SEND_BEGIN_FRAME_EVENT,ranges);for(const[id,time]of sendBeginFrameTimes){queueingDurations.push(beginMainFrameTimes.get(id)-time);}}
 histograms.createHistogram('queueing_durations',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,queueingDurations,{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(0.01,2,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Time between ScheduledActionSendBeginMainFrame in '+'the compositor thread and the corresponding '+'BeginMainFrame in the main thread.'});}
 return{addQueueingDurationHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const GESTURE_EVENT='SyntheticGestureController::running';function renderingMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;let segments=chromeHelper.telemetryHelper.irSegments;if(segments.length===0){segments=chromeHelper.telemetryHelper.animationSegments;}
-if(segments.length>0){tr.metrics.rendering.addFrameTimeHistograms(histograms,model,segments);tr.metrics.rendering.addImageDecodeTimeHistograms(histograms,model,segments);tr.metrics.rendering.addPipelineHistograms(histograms,model,segments);tr.metrics.rendering.addPixelsHistograms(histograms,model,segments);tr.metrics.rendering.addQueueingDurationHistograms(histograms,model,segments);}
+if(segments.length>0){tr.metrics.rendering.addFrameTimeHistograms(histograms,model,segments);tr.metrics.rendering.addImageDecodeTimeHistograms(histograms,model,segments);tr.metrics.rendering.addPixelsHistograms(histograms,model,segments);tr.metrics.rendering.addQueueingDurationHistograms(histograms,model,segments);}
 const uiSegments=chromeHelper.telemetryHelper.uiSegments;if(uiSegments.length>0){tr.metrics.rendering.addUIFrameTimeHistograms(histograms,model,chromeHelper.telemetryHelper.uiSegments);}}
 tr.metrics.MetricRegistry.register(renderingMetric,{requiredCategories:['benchmark','toplevel'],});return{renderingMetric,};});'use strict';tr.exportTo('tr.metrics',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const EventFinderUtils=tr.e.chrome.EventFinderUtils;const METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(80e3,30);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function reportedByPageMetric(histograms,model){const timeToViewable=histograms.createHistogram('reported_by_page:time_to_viewable',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from navigation start'+'to telemetry:reported_by_page:viewable',summaryOptions:SUMMARY_OPTIONS,});const timeToInteractive=histograms.createHistogram('reported_by_page:time_to_interactive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from navigation start '+'to telemetry:reported_by_page:interactive',summaryOptions:SUMMARY_OPTIONS,});const benchmarkTime=histograms.createHistogram('reported_by_page:benchmark_time',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from telemetry:reported_by_page:benchmark_begin '+'to telemetry:reported_by_page:benchmark_end',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread===undefined)continue;measureUserTime(rendererHelper,'navigationStart','telemetry:reported_by_page:viewable',timeToViewable);measureUserTime(rendererHelper,'navigationStart','telemetry:reported_by_page:interactive',timeToInteractive);measureUserTime(rendererHelper,'telemetry:reported_by_page:benchmark_begin','telemetry:reported_by_page:benchmark_end',benchmarkTime);}}
 function measureUserTime(rendererHelper,startName,endName,histogram){const startEventByNavId=new Map();for(const event of rendererHelper.mainThread.sliceGroup.childEvents()){const navId=getNavigationId(event);if(!navId)continue;if(EventFinderUtils.hasCategoryAndName(event,'blink.user_timing',startName)){startEventByNavId.set(navId,event);}
@@ -8682,7 +8456,7 @@
 const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addRectsBasedSpeedIndexSample(rectsBasedSpeedIndexSamples,rendererHelper,expectation.navigationStart.start,expectation.duration,expectation.navigationStart.args.frame);}
 return rectsBasedSpeedIndexSamples;}
 function rectsBasedSpeedIndexMetric(histograms,model){const rectsBasedSpeedIndexHistogram=histograms.createHistogram('rectsBasedSpeedIndex',timeDurationInMs_smallerIsBetter,[],{binBoundaries:BIN_BOUNDARIES,description:' the average time at which visible parts of the'+' page are displayed (in ms).',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const samples=collectRectsBasedSpeedIndexSamplesFromLoadExpectations(model,chromeHelper);for(const sample of samples){rectsBasedSpeedIndexHistogram.addSample(sample.value);}}
-tr.metrics.MetricRegistry.register(rectsBasedSpeedIndexMetric);return{rectsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LONG_TASK_THRESHOLD_MS=50;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const RelatedEventSet=tr.v.d.RelatedEventSet;const hasCategoryAndName=tr.metrics.sh.hasCategoryAndName;const EventFinderUtils=tr.e.chrome.EventFinderUtils;function createBreakdownDiagnostic(breakdownTree){const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownTree){breakdownDiagnostic.set(label,breakdownTree[label].total);}
+tr.metrics.MetricRegistry.register(rectsBasedSpeedIndexMetric);return{rectsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.v.d',function(){const ALERT_GROUPS={CPU_USAGE:'cpu_usage',LOADING_PAINT:'loading_paint',LOADING_INTERACTIVITY:'loading_interactivity',LOADING_LAYOUT:'loading_layout',};return{ALERT_GROUPS,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LONG_TASK_THRESHOLD_MS=50;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const RelatedEventSet=tr.v.d.RelatedEventSet;const hasCategoryAndName=tr.metrics.sh.hasCategoryAndName;const EventFinderUtils=tr.e.chrome.EventFinderUtils;function createBreakdownDiagnostic(breakdownTree){const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownTree){breakdownDiagnostic.set(label,breakdownTree[label].total);}
 return breakdownDiagnostic;}
 const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const TIME_TO_INTERACTIVE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,40e3,35).addExponentialBins(80e3,15);const LAYOUT_SHIFT_SCORE_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,50,25);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
 return snapshot;}
@@ -8703,7 +8477,7 @@
 function findLayoutShiftSamples(rendererHelper){let sample;EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'LayoutShift','loading').forEach((events)=>{const evData=events.pop().args.data;if(evData.is_main_frame){sample={value:evData.cumulative_score};}});return sample?[sample]:[];}
 function addFirstMeaningfulPaintSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToFMPRange);const timeToFirstMeaningfulPaint=navStartToFMPRange.duration;const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToFMPRange);samples.push({value:timeToFirstMeaningfulPaint,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
 function addFirstMeaningfulPaintCpuTimeSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const mainThreadCpuTime=rendererHelper.mainThread.getCpuTimeForRange(navStartToFMPRange);const breakdownTree=tr.metrics.sh.generateCpuTimeBreakdownTree(rendererHelper.mainThread,navStartToFMPRange);samples.push({value:mainThreadCpuTime,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
-function decorateInteractivitySampleWithDiagnostics_(rendererHelper,eventTimestamp,navigationStartEvent,firstMeaningfulPaintTime,domContentLoadedEndTime,url){if(eventTimestamp===undefined)return undefined;const navigationStartTime=navigationStartEvent.start;const navStartToEventTimeRange=tr.b.math.Range.fromExplicitRange(navigationStartTime,eventTimestamp);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventTimeRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventTimeRange);const breakdownDiagnostic=createBreakdownDiagnostic(breakdownTree);return{value:navStartToEventTimeRange.duration,diagnostics:tr.v.d.DiagnosticMap.fromObject({'Start':new RelatedEventSet(navigationStartEvent),'Navigation infos':new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,navigationStartTime,firstMeaningfulPaintTime,domContentLoadedEndTime,eventTimestamp,}]),'Breakdown of [navStart, eventTimestamp]':breakdownDiagnostic,}),};}
+function decorateInteractivitySampleWithDiagnostics_(rendererHelper,eventTimestamp,navigationStartEvent,firstContentfulPaintTime,domContentLoadedEndTime,url){if(eventTimestamp===undefined)return undefined;const navigationStartTime=navigationStartEvent.start;const navStartToEventTimeRange=tr.b.math.Range.fromExplicitRange(navigationStartTime,eventTimestamp);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventTimeRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventTimeRange);const breakdownDiagnostic=createBreakdownDiagnostic(breakdownTree);return{value:navStartToEventTimeRange.duration,diagnostics:tr.v.d.DiagnosticMap.fromObject({'Start':new RelatedEventSet(navigationStartEvent),'Navigation infos':new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,navigationStartTime,firstContentfulPaintTime,domContentLoadedEndTime,eventTimestamp,}]),'Breakdown of [navStart, eventTimestamp]':breakdownDiagnostic,}),};}
 function getCandidateIndex(entry){return entry.targetEvent.args.data.candidateIndex;}
 function findLastCandidateForEachNavigation(timeToXEntries){const entryMap=new Map();for(const e of timeToXEntries){const navStartEvent=e.navigationStartEvent;if(!entryMap.has(navStartEvent)){entryMap.set(navStartEvent,[]);}
 entryMap.get(navStartEvent).push(e);}
@@ -8714,16 +8488,17 @@
 function findLargestImagePaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents){const timeToPaintEntries=findTimeToXEntries('loading','LargestImagePaint::Candidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const timeToPaintBlockingEntries=findTimeToXEntries('loading','LargestImagePaint::NoCandidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const lastCandidateEvents=findLastCandidateForEachNavigation(timeToPaintEntries.concat(timeToPaintBlockingEntries)).filter(event=>event.targetEvent.title!=='LargestImagePaint::NoCandidate');return collectTimeToEvent(rendererHelper,lastCandidateEvents);}
 function findLargestContentfulPaintHistogramSamples(allBrowserEvents){const lcp=new tr.e.chrome.LargestContentfulPaint(allBrowserEvents);const lcpSamples=lcp.findCandidates().map(candidate=>{const{durationInMilliseconds,size,type,inMainFrame,mainFrameTreeNodeId}=candidate;return{value:durationInMilliseconds,diagnostics:{size:new tr.v.d.GenericSet([size]),type:new tr.v.d.GenericSet([type]),inMainFrame:new tr.v.d.GenericSet([inMainFrame]),mainFrameTreeNodeId:new tr.v.d.GenericSet([mainFrameTreeNodeId]),},};});return lcpSamples;}
 function collectLoadingMetricsForRenderer(rendererHelper){const frameToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const navIdToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByNavId(rendererHelper,'navigationStart','blink.user_timing');const firstPaintSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('loading','firstPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const timeToFCPEntries=findTimeToXEntries('loading','firstContentfulPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const firstContentfulPaintSamples=collectTimeToEvent(rendererHelper,timeToFCPEntries);const firstContentfulPaintCpuTimeSamples=collectTimeToEventInCpuTime(rendererHelper,timeToFCPEntries);const onLoadSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('blink.user_timing','loadEventStart',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const aboveTheFoldLoadedToVisibleSamples=getAboveTheFoldLoadedToVisibleSamples(rendererHelper);const firstViewportReadySamples=getFirstViewportReadySamples(rendererHelper,navIdToNavStartEvents);const largestImagePaintSamples=findLargestImagePaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const largestTextPaintSamples=findLargestTextPaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const layoutShiftSamples=findLayoutShiftSamples(rendererHelper);const navigationStartSamples=timeToFCPEntries.map(entry=>{return{value:entry.navigationStartEvent.start};});return{frameToNavStartEvents,firstPaintSamples,firstContentfulPaintSamples,firstContentfulPaintCpuTimeSamples,onLoadSamples,aboveTheFoldLoadedToVisibleSamples,firstViewportReadySamples,largestImagePaintSamples,largestTextPaintSamples,layoutShiftSamples,navigationStartSamples,};}
-function collectMetricsFromLoadExpectations(model,chromeHelper){const interactiveSamples=[];const firstCpuIdleSamples=[];const firstMeaningfulPaintSamples=[];const firstMeaningfulPaintCpuTimeSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+function collectMetricsFromLoadExpectations(model,chromeHelper){const interactiveSamples=[];const firstCpuIdleSamples=[];const firstMeaningfulPaintSamples=[];const firstMeaningfulPaintCpuTimeSamples=[];const totalBlockingTimeSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
 const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];if(expectation.fmpEvent!==undefined){addFirstMeaningfulPaintSample(firstMeaningfulPaintSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);addFirstMeaningfulPaintCpuTimeSample(firstMeaningfulPaintCpuTimeSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);}
-if(expectation.firstCpuIdleTime!==undefined){firstCpuIdleSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.firstCpuIdleTime,expectation.navigationStart,expectation.fmpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}
-if(expectation.timeToInteractive!==undefined){interactiveSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.timeToInteractive,expectation.navigationStart,expectation.fmpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}}
-return{firstMeaningfulPaintSamples,firstMeaningfulPaintCpuTimeSamples,firstCpuIdleSamples,interactiveSamples,};}
+if(expectation.firstCpuIdleTime!==undefined){firstCpuIdleSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.firstCpuIdleTime,expectation.navigationStart,expectation.fcpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}
+if(expectation.timeToInteractive!==undefined){interactiveSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.timeToInteractive,expectation.navigationStart,expectation.fcpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}
+if(expectation.totalBlockingTime!==undefined){totalBlockingTimeSamples.push({value:expectation.totalBlockingTime,diagnostics:{url:new tr.v.d.GenericSet([expectation.url]),navigationStart:new RelatedEventSet(expectation.navigationStart),firstContentfulPaint:new RelatedEventSet(expectation.fcpEvent),interactiveTime:new tr.v.d.GenericSet([expectation.timeToInteractive]),}});}}
+return{firstMeaningfulPaintSamples,firstMeaningfulPaintCpuTimeSamples,firstCpuIdleSamples,interactiveSamples,totalBlockingTimeSamples,};}
 function addSamplesToHistogram(samples,histogram,histograms){for(const sample of samples){histogram.addSample(sample.value,sample.diagnostics);if(histogram.name!=='timeToFirstContentfulPaint')continue;if(!sample.breakdownTree)continue;for(const[category,breakdown]of Object.entries(sample.breakdownTree)){const relatedName=`${histogram.name}:${category}`;let relatedHist=histograms.getHistogramsNamed(relatedName)[0];if(!relatedHist){relatedHist=histograms.createHistogram(relatedName,histogram.unit,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,summaryOptions:{count:false,max:false,min:false,sum:false,},});let relatedNames=histogram.diagnostics.get('breakdown');if(!relatedNames){relatedNames=new tr.v.d.RelatedNameMap();histogram.diagnostics.set('breakdown',relatedNames);}
 relatedNames.set(category,relatedName);}
 relatedHist.addSample(breakdown.total,{breakdown:tr.v.d.Breakdown.fromEntries(Object.entries(breakdown.events)),});}}}
-function loadingMetric(histograms,model){const firstPaintHistogram=histograms.createHistogram('timeToFirstPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintHistogram=histograms.createHistogram('timeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const onLoadHistogram=histograms.createHistogram('timeToOnload',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to onload. '+'This is temporary metric used for PCv1/v2 sanity checking',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintHistogram=histograms.createHistogram('timeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const timeToInteractiveHistogram=histograms.createHistogram('timeToInteractive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to Interactive',summaryOptions:SUMMARY_OPTIONS,});const timeToFirstCpuIdleHistogram=histograms.createHistogram('timeToFirstCpuIdle',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to First CPU Idle',summaryOptions:SUMMARY_OPTIONS,});const aboveTheFoldLoadedToVisibleHistogram=histograms.createHistogram('aboveTheFoldLoadedToVisible',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from first visible to load for AMP pages only.',summaryOptions:SUMMARY_OPTIONS,});const firstViewportReadyHistogram=histograms.createHistogram('timeToFirstViewportReady',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from navigation to load for AMP pages only. ',summaryOptions:SUMMARY_OPTIONS,});const largestImagePaintHistogram=histograms.createHistogram('largestImagePaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Image Paint',summaryOptions:SUMMARY_OPTIONS,});const largestTextPaintHistogram=histograms.createHistogram('largestTextPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Text Paint',summaryOptions:SUMMARY_OPTIONS,});const largestContentfulPaintHistogram=histograms.createHistogram('largestContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Contentful Paint',summaryOptions:SUMMARY_OPTIONS,});const layoutShiftHistogram=histograms.createHistogram('mainFrameCumulativeLayoutShift',unitlessNumber_smallerIsBetter,[],{binBoundaries:LAYOUT_SHIFT_SCORE_BOUNDARIES,description:'Main Frame Document Cumulative Layout Shift Score',summaryOptions:SUMMARY_OPTIONS,});const navigationStartHistogram=histograms.createHistogram('navigationStart',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'navigationStart',summaryOptions:SUMMARY_OPTIONS,});tr.metrics.sh.rectsBasedSpeedIndexMetric(histograms,model);const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;const samplesSet=collectLoadingMetricsForRenderer(rendererHelper);const lcpSamples=findLargestContentfulPaintHistogramSamples(chromeHelper.browserHelper.mainThread.sliceGroup.slices);addSamplesToHistogram(lcpSamples,largestContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstPaintSamples,firstPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintSamples,firstContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintCpuTimeSamples,firstContentfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.onLoadSamples,onLoadHistogram,histograms);addSamplesToHistogram(samplesSet.aboveTheFoldLoadedToVisibleSamples,aboveTheFoldLoadedToVisibleHistogram,histograms);addSamplesToHistogram(samplesSet.firstViewportReadySamples,firstViewportReadyHistogram,histograms);addSamplesToHistogram(samplesSet.largestImagePaintSamples,largestImagePaintHistogram,histograms);addSamplesToHistogram(samplesSet.largestTextPaintSamples,largestTextPaintHistogram,histograms);addSamplesToHistogram(samplesSet.layoutShiftSamples,layoutShiftHistogram,histograms);addSamplesToHistogram(samplesSet.navigationStartSamples,navigationStartHistogram,histograms);}
-const samplesSet=collectMetricsFromLoadExpectations(model,chromeHelper);addSamplesToHistogram(samplesSet.firstMeaningfulPaintSamples,firstMeaningfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstMeaningfulPaintCpuTimeSamples,firstMeaningfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.interactiveSamples,timeToInteractiveHistogram,histograms);addSamplesToHistogram(samplesSet.firstCpuIdleSamples,timeToFirstCpuIdleHistogram,histograms);}
+function loadingMetric(histograms,model){const firstPaintHistogram=histograms.createHistogram('timeToFirstPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstContentfulPaintHistogram=histograms.createHistogram('timeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstContentfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const onLoadHistogram=histograms.createHistogram('timeToOnload',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to onload. '+'This is temporary metric used for PCv1/v2 sanity checking',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintHistogram=histograms.createHistogram('timeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const firstMeaningfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const timeToInteractiveHistogram=histograms.createHistogram('timeToInteractive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to Interactive',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});const totalBlockingTimeHistogram=histograms.createHistogram('totalBlockingTime',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Total Blocking Time',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});const timeToFirstCpuIdleHistogram=histograms.createHistogram('timeToFirstCpuIdle',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to First CPU Idle',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_INTERACTIVITY],});const aboveTheFoldLoadedToVisibleHistogram=histograms.createHistogram('aboveTheFoldLoadedToVisible',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from first visible to load for AMP pages only.',summaryOptions:SUMMARY_OPTIONS,});const firstViewportReadyHistogram=histograms.createHistogram('timeToFirstViewportReady',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from navigation to load for AMP pages only. ',summaryOptions:SUMMARY_OPTIONS,});const largestImagePaintHistogram=histograms.createHistogram('largestImagePaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Image Paint',summaryOptions:SUMMARY_OPTIONS,});const largestTextPaintHistogram=histograms.createHistogram('largestTextPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Text Paint',summaryOptions:SUMMARY_OPTIONS,});const largestContentfulPaintHistogram=histograms.createHistogram('largestContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Contentful Paint',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_PAINT],});const layoutShiftHistogram=histograms.createHistogram('mainFrameCumulativeLayoutShift',unitlessNumber_smallerIsBetter,[],{binBoundaries:LAYOUT_SHIFT_SCORE_BOUNDARIES,description:'Main Frame Document Cumulative Layout Shift Score',summaryOptions:SUMMARY_OPTIONS,alertGrouping:[tr.v.d.ALERT_GROUPS.LOADING_LAYOUT],});const navigationStartHistogram=histograms.createHistogram('navigationStart',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'navigationStart',summaryOptions:SUMMARY_OPTIONS,});tr.metrics.sh.rectsBasedSpeedIndexMetric(histograms,model);const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;const samplesSet=collectLoadingMetricsForRenderer(rendererHelper);const lcpSamples=findLargestContentfulPaintHistogramSamples(chromeHelper.browserHelper.mainThread.sliceGroup.slices);addSamplesToHistogram(lcpSamples,largestContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstPaintSamples,firstPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintSamples,firstContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintCpuTimeSamples,firstContentfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.onLoadSamples,onLoadHistogram,histograms);addSamplesToHistogram(samplesSet.aboveTheFoldLoadedToVisibleSamples,aboveTheFoldLoadedToVisibleHistogram,histograms);addSamplesToHistogram(samplesSet.firstViewportReadySamples,firstViewportReadyHistogram,histograms);addSamplesToHistogram(samplesSet.largestImagePaintSamples,largestImagePaintHistogram,histograms);addSamplesToHistogram(samplesSet.largestTextPaintSamples,largestTextPaintHistogram,histograms);addSamplesToHistogram(samplesSet.layoutShiftSamples,layoutShiftHistogram,histograms);addSamplesToHistogram(samplesSet.navigationStartSamples,navigationStartHistogram,histograms);}
+const samplesSet=collectMetricsFromLoadExpectations(model,chromeHelper);addSamplesToHistogram(samplesSet.firstMeaningfulPaintSamples,firstMeaningfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstMeaningfulPaintCpuTimeSamples,firstMeaningfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.interactiveSamples,timeToInteractiveHistogram,histograms);addSamplesToHistogram(samplesSet.firstCpuIdleSamples,timeToFirstCpuIdleHistogram,histograms);addSamplesToHistogram(samplesSet.totalBlockingTimeSamples,totalBlockingTimeHistogram,histograms);}
 tr.metrics.MetricRegistry.register(loadingMetric);return{loadingMetric,createBreakdownDiagnostic};});'use strict';tr.exportTo('tr.metrics',function(){const SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY=tr.v.HistogramBinBoundaries.createExponential(1,1000,50);function spaNavigationMetric(histograms,model){const histogram=new tr.v.Histogram('spaNavigationStartToFpDuration',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY);histogram.description='Latency between the input event causing'+' a SPA navigation and the first paint event after it';histogram.customizeSummaryOptions({count:false,sum:false,});const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper){return;}
 const rendererHelpers=modelHelper.rendererHelpers;if(!rendererHelpers){return;}
 const browserHelper=modelHelper.browserHelper;for(const rendererHelper of Object.values(rendererHelpers)){const spaNavigations=tr.metrics.findSpaNavigationsOnRenderer(rendererHelper,browserHelper);for(const spaNav of spaNavigations){let beginTs=0;if(spaNav.navStartCandidates.inputLatencyAsyncSlice){const beginData=spaNav.navStartCandidates.inputLatencyAsyncSlice.args.data;beginTs=model.convertTimestampToModelTime('traceEventClock',beginData.INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT.time);}else{beginTs=spaNav.navStartCandidates.goToIndexSlice.start;}
@@ -8737,7 +8512,7 @@
 let processCpuTime=0;for(const tid in process.threads){const thread=process.threads[tid];processCpuTime+=thread.getCpuTimeForRange(rangeOfInterest);}
 allProcessCpuTime+=processCpuTime;}
 let normalizedAllProcessCpuTime=0;if(rangeOfInterest.duration>0){normalizedAllProcessCpuTime=allProcessCpuTime/rangeOfInterest.duration;}
-const unit=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const cpuTimeHist=new tr.v.Histogram('cpu_time_percentage',unit,CPU_TIME_PERCENTAGE_BOUNDARIES);cpuTimeHist.description='Percent CPU utilization, normalized against a single core. Can be '+'greater than 100% if machine has multiple cores.';cpuTimeHist.customizeSummaryOptions({avg:true,count:false,max:false,min:false,std:false,sum:false});cpuTimeHist.addSample(normalizedAllProcessCpuTime);histograms.addHistogram(cpuTimeHist);}
+const unit=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const cpuTimeHist=new tr.v.Histogram('cpu_time_percentage',unit,CPU_TIME_PERCENTAGE_BOUNDARIES);cpuTimeHist.description='Percent CPU utilization, normalized against a single core. Can be '+'greater than 100% if machine has multiple cores.';cpuTimeHist.setAlertGrouping([tr.v.d.ALERT_GROUPS.CPU_USAGE]);cpuTimeHist.customizeSummaryOptions({avg:true,count:false,max:false,min:false,std:false,sum:false});cpuTimeHist.addSample(normalizedAllProcessCpuTime);histograms.addHistogram(cpuTimeHist);}
 tr.metrics.MetricRegistry.register(cpuTimeMetric,{supportsRangeOfInterest:true});return{cpuTimeMetric,};});'use strict';tr.exportTo('tr.v',function(){class HistogramDeserializer{static deserialize(data){const deserializer=new HistogramDeserializer(data[0],data[1]);return data.slice(2).map(datum=>tr.v.Histogram.deserialize(datum,deserializer));}
 constructor(objects,diagnostics){this.objects_=objects;this.diagnostics_=[];for(const[type,diagnosticsByName]of Object.entries(diagnostics||{})){for(const[name,diagnosticsById]of Object.entries(diagnosticsByName)){for(const[id,data]of Object.entries(diagnosticsById)){const diagnostic=tr.v.d.Diagnostic.deserialize(type,data,this);this.diagnostics_[parseInt(id)]={name,diagnostic};}}}}
 getObject(id){return this.objects_[id];}
@@ -9173,13 +8948,16 @@
 const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addSpeedIndexScreenshotsBasedSample(speedIndexScreenshotsBasedSamples,expectation.navigationStart,expectation.duration,chromeHelper.browserHelper);}
 return speedIndexScreenshotsBasedSamples;}
 function screenshotsBasedSpeedIndexMetric(histograms,model){const speedIndexScreenshotsBasedHistogram=histograms.createHistogram('speedIndexScreenshotsBased',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'The average time at which visible parts of the'+' page are displayed.',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const samples=collectSpeedIndexSamplesFromLoadExpectations(model,chromeHelper);for(const sample of samples){speedIndexScreenshotsBasedHistogram.addSample(sample.value);}}
-tr.metrics.MetricRegistry.register(screenshotsBasedSpeedIndexMetric);return{screenshotsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function webviewStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('webview_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebView startup wall time';const startupCPUHist=new tr.v.Histogram('webview_startup_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupCPUHist.description='WebView startup CPU time';const loadWallHist=new tr.v.Histogram('webview_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebView blank URL load wall time';const loadCPUHist=new tr.v.Histogram('webview_url_load_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadCPUHist.description='WebView blank URL load CPU time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebViewStartupInterval'){startupWallHist.addSample(slice.duration);startupCPUHist.addSample(slice.cpuDuration);}
+tr.metrics.MetricRegistry.register(screenshotsBasedSpeedIndexMetric);return{screenshotsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function weblayerStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('weblayer_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebLayer startup wall time';const loadWallHist=new tr.v.Histogram('weblayer_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebLayer blank URL load wall time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebLayerStartupInterval'){startupWallHist.addSample(slice.duration);}
+if(slice.title==='WebLayerBlankUrlLoadInterval'){loadWallHist.addSample(slice.duration);}}
+histograms.addHistogram(startupWallHist);histograms.addHistogram(loadWallHist);}
+tr.metrics.MetricRegistry.register(weblayerStartupMetric);return{weblayerStartupMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function webviewStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('webview_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebView startup wall time';const startupCPUHist=new tr.v.Histogram('webview_startup_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupCPUHist.description='WebView startup CPU time';const loadWallHist=new tr.v.Histogram('webview_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebView blank URL load wall time';const loadCPUHist=new tr.v.Histogram('webview_url_load_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadCPUHist.description='WebView blank URL load CPU time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebViewStartupInterval'){startupWallHist.addSample(slice.duration);startupCPUHist.addSample(slice.cpuDuration);}
 if(slice.title==='WebViewBlankUrlLoadInterval'){loadWallHist.addSample(slice.duration);loadCPUHist.addSample(slice.cpuDuration);}}
 histograms.addHistogram(startupWallHist);histograms.addHistogram(startupCPUHist);histograms.addHistogram(loadWallHist);histograms.addHistogram(loadCPUHist);}
 tr.metrics.MetricRegistry.register(webviewStartupMetric);return{webviewStartupMetric,};});'use strict';tr.exportTo('tr.metrics.tabs',function(){function tabsMetric(histograms,model,opt_options){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper){return;}
 const tabSwitchRequestDelays=[];const TAB_SWITCHING_REQUEST_TITLE='TabSwitchVisibilityRequest';let startTabSwitchVisibilityRequest=Number.MAX_SAFE_INTEGER;for(const helper of chromeHelper.browserHelpers){if(!helper.mainThread)continue;for(const slice of helper.mainThread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_REQUEST_TITLE&&!slice.error){tabSwitchRequestDelays.push(slice.duration);if(slice.start<startTabSwitchVisibilityRequest){startTabSwitchVisibilityRequest=slice.start;}}}}
 histograms.createHistogram('tab_switching_request_delay',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchRequestDelays,{description:'Delay before tab-request is made',summaryOptions:{sum:false}});const tabSwitchLatencies=[];const TAB_SWITCHING_SLICE_TITLE='TabSwitching::Latency';function extractLatencyFromHelpers(helpers,legacy){for(const helper of helpers){if(!helper.mainThread){continue;}
-const thread=helper.mainThread;for(const slice of thread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_SLICE_TITLE&&(legacy||slice.args.latency)&&slice.start>startTabSwitchVisibilityRequest){tabSwitchLatencies.push(legacy?slice.duration:slice.args.latency);}}}}
+const thread=helper.mainThread;for(const slice of thread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_SLICE_TITLE&&(legacy||slice.args.latency)&&slice.start>startTabSwitchVisibilityRequest-1){tabSwitchLatencies.push(legacy?slice.duration:slice.args.latency);}}}}
 extractLatencyFromHelpers(chromeHelper.browserHelpers);extractLatencyFromHelpers(Object.values(chromeHelper.rendererHelpers));if(tabSwitchLatencies.length===0){extractLatencyFromHelpers(chromeHelper.browserHelpers,true);}
 histograms.createHistogram('tab_switching_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchLatencies,{description:'Tab switching time in ms',summaryOptions:{sum:false}});}
 tr.metrics.MetricRegistry.register(tabsMetric,{supportsRangeOfInterest:false,});return{tabsMetric,};});'use strict';tr.exportTo('tr.metrics',function(){const MEMORY_INFRA_TRACING_CATEGORY='disabled-by-default-memory-infra';const TIME_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1e-3,1e5,30);const BYTE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e9,30);const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e5,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;function addMemoryInfraHistograms(histograms,model,categoryNamesToTotalEventSizes){const memoryDumpCount=model.globalMemoryDumps.length;if(memoryDumpCount===0)return;let totalOverhead=0;let nonMemoryInfraThreadOverhead=0;const overheadByProvider={};for(const process of Object.values(model.processes)){for(const thread of Object.values(process.threads)){for(const slice of Object.values(thread.sliceGroup.slices)){if(slice.category!==MEMORY_INFRA_TRACING_CATEGORY)continue;totalOverhead+=slice.duration;if(thread.name!=='MemoryInfra'){nonMemoryInfraThreadOverhead+=slice.duration;}
@@ -9197,20 +8975,17 @@
 function mergeBins_(x,y){x.sum+=y.sum;const allBins=[...x.bins,...y.bins];allBins.sort((a,b)=>a.min-b.min);x.bins=[];let last=undefined;for(const bin of allBins){if(last!==undefined&&bin.min===last.min){if(last.max!==bin.max)throw new Error('Incompatible bins');if(bin.count===0)continue;last.count+=bin.count;for(const event of bin.events){last.events.add(event);}
 last.processes.addDiagnostic(bin.processes);}else{if(last!==undefined&&bin.min<last.max){throw new Error('Incompatible bins');}
 x.bins.push(bin);last=bin;}}}
-function subtractBins_(x,y){x.sum-=y.sum;let p1=0;let p2=0;while(p2<y.bins.length){while(p1<x.bins.length&&x.bins[p1].min!==y.bins[p2].min){p1++;}
-if(p1===x.bins.length)throw new Error('Cannot subtract');if(x.bins[p1].max!==y.bins[p2].max){throw new Error('Incompatible bins');}
-if(x.bins[p1].count<y.bins[p2].count){throw new Error('Cannot subtract');}
-x.bins[p1].count-=y.bins[p2].count;for(const event of y.bins[p2].events){x.bins[p1].events.add(event);}
-const processName=tr.b.getOnlyElement(x.bins[p1].processes)[0];x.bins[p1].processes.set(processName,x.bins[p1].count);p2++;}}
 function getHistogramUnit_(name){return tr.b.Unit.byName.unitlessNumber_smallerIsBetter;}
+function getIsHistogramBinsLinear_(histogramName){return histogramName.startsWith('Graphics.Smoothness.Throughput')||histogramName.startsWith('Memory.Memory.GPU.PeakMemoryUsage');}
 function getHistogramBoundaries_(name){if(name.startsWith('Event.Latency.Scroll')){return tr.v.HistogramBinBoundaries.createExponential(1e3,1e5,50);}
 if(name.startsWith('Graphics.Smoothness.Throughput')){return tr.v.HistogramBinBoundaries.createLinear(0,100,101);}
 if(name.startsWith('Memory.Memory.GPU.PeakMemoryUsage')){return tr.v.HistogramBinBoundaries.createLinear(0,1e6,100);}
 return tr.v.HistogramBinBoundaries.createExponential(1e-3,1e3,50);}
 function umaMetric(histograms,model){const histogramValues=new Map();const nameCounts=new Map();for(const process of model.getAllProcesses()){const histogramEvents=new Map();for(const event of process.instantEvents){if(event.title!=='UMAHistogramSamples')continue;const name=event.args.name;const events=histogramEvents.get(name)||[];if(!histogramEvents.has(name))histogramEvents.set(name,events);events.push(event);}
-let processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(process.name);nameCounts.set(processName,(nameCounts.get(processName)||0)+1);processName=`${processName}_${nameCounts.get(processName)}`;for(const[name,events]of histogramEvents){const values=histogramValues.get(name)||{sum:0,bins:[]};if(!histogramValues.has(name))histogramValues.set(name,values);const endValues=parseBuckets_(events[events.length-1],processName);if(events.length===1){mergeBins_(values,endValues);}else if(events.length===2){subtractBins_(endValues,parseBuckets_(events[0],processName));mergeBins_(values,endValues);}else{throw new Error('There should be at most two snapshots of an UMA '+'histogram in each process');}}}
-for(const[name,values]of histogramValues){const histogram=new tr.v.Histogram(name,getHistogramUnit_(name),getHistogramBoundaries_(name));let sumOfMiddles=0;let sumOfBinLengths=0;for(const bin of values.bins){sumOfMiddles+=bin.count*(bin.min+bin.max)/2;sumOfBinLengths+=bin.count*(bin.max-bin.min);}
-const shift=(values.sum-sumOfMiddles)/sumOfBinLengths;if(Math.abs(shift)>0.5)throw new Error('Samples sum is wrong');for(const bin of values.bins){if(bin.count===0)continue;const shiftedValue=(bin.min+bin.max)/2+shift*(bin.max-bin.min);for(const[processName,count]of bin.processes){bin.processes.set(processName,shiftedValue*count/bin.count);}
+let processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(process.name);nameCounts.set(processName,(nameCounts.get(processName)||0)+1);processName=`${processName}_${nameCounts.get(processName)}`;for(const[name,events]of histogramEvents){const values=histogramValues.get(name)||{sum:0,bins:[]};if(!histogramValues.has(name))histogramValues.set(name,values);const endValues=parseBuckets_(events[events.length-1],processName);if(events.length===1){mergeBins_(values,endValues,name);}else{throw new Error('There should be at most one snapshot of UMA '+`histogram for ${name} in each process.`);}}}
+for(const[name,values]of histogramValues){const histogram=new tr.v.Histogram(name,getHistogramUnit_(name),getHistogramBoundaries_(name));const isLinear=getIsHistogramBinsLinear_(name);let sumOfMiddles=0;let sumOfBinLengths=0;for(const bin of values.bins){sumOfMiddles+=bin.count*(bin.min+bin.max)/2;sumOfBinLengths+=bin.count*(bin.max-bin.min);}
+const shift=(values.sum-sumOfMiddles)/sumOfBinLengths;if(isLinear&&Math.abs(shift)>0.5){throw new Error(`Samples sum is wrong for ${name}.`);}
+for(const bin of values.bins){if(bin.count===0)continue;const shiftedValue=(bin.min+bin.max)/2+shift*(bin.max-bin.min);for(const[processName,count]of bin.processes){bin.processes.set(processName,shiftedValue*count/bin.count);}
 for(let i=0;i<bin.count;i++){histogram.addSample(shiftedValue,{processes:bin.processes,events:bin.events});}}
 histograms.addHistogram(histogram);}}
 tr.metrics.MetricRegistry.register(umaMetric,{requiredCategories:['benchmark'],});return{umaMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(4,200,100);function computeExecuteMetrics(histograms,model){const cpuTotalExecution=new tr.v.Histogram('v8_execution_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalExecution.description='cpu total time spent in script execution';const wallTotalExecution=new tr.v.Histogram('v8_execution_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalExecution.description='wall total time spent in script execution';const cpuSelfExecution=new tr.v.Histogram('v8_execution_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfExecution.description='cpu self time spent in script execution';const wallSelfExecution=new tr.v.Histogram('v8_execution_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfExecution.description='wall self time spent in script execution';for(const e of model.findTopmostSlicesNamed('V8.Execute')){cpuTotalExecution.addSample(e.cpuDuration);wallTotalExecution.addSample(e.duration);cpuSelfExecution.addSample(e.cpuSelfTime);wallSelfExecution.addSample(e.selfTime);}
@@ -9230,9 +9005,54 @@
 function computeDeoptimizeCodeMetrics(histograms,model){const cpuTotalDeoptimizeCode=new tr.v.Histogram('v8_deoptimize_code_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalDeoptimizeCode.description='cpu total time spent in code deoptimization';const wallTotalDeoptimizeCode=new tr.v.Histogram('v8_deoptimize_code_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalDeoptimizeCode.description='wall total time spent in code deoptimization';for(const e of model.findTopmostSlicesNamed('V8.DeoptimizeCode')){cpuTotalDeoptimizeCode.addSample(e.cpuDuration);wallTotalDeoptimizeCode.addSample(e.duration);}
 histograms.addHistogram(cpuTotalDeoptimizeCode);histograms.addHistogram(wallTotalDeoptimizeCode);}
 function executionMetric(histograms,model){computeExecuteMetrics(histograms,model);computeParseLazyMetrics(histograms,model);computeCompileIgnitionMetrics(histograms,model);computeCompileFullCodeMetrics(histograms,model);computeRecompileMetrics(histograms,model);computeOptimizeCodeMetrics(histograms,model);computeDeoptimizeCodeMetrics(histograms,model);}
-tr.metrics.MetricRegistry.register(executionMetric);return{executionMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const TARGET_FPS=60;const MS_PER_SECOND=1000;const WINDOW_SIZE_MS=MS_PER_SECOND/TARGET_FPS;function gcMetric(histograms,model,options){options=options||{};addDurationOfTopEvents(histograms,model);addTotalDurationOfTopEvents(histograms,model);if(options.include_sub_events){addDurationOfSubEvents(histograms,model);}
-addPercentageInV8ExecuteOfTopEvents(histograms,model);addTotalPercentageInV8Execute(histograms,model);addMarkCompactorMutatorUtilization(histograms,model);addTotalMarkCompactorTime(histograms,model);addTotalMarkCompactorMarkingTime(histograms,model);}
-tr.metrics.MetricRegistry.register(gcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
+tr.metrics.MetricRegistry.register(executionMetric);return{executionMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const TARGET_FPS=60;const MS_PER_SECOND=1000;const WINDOW_SIZE_MS=MS_PER_SECOND/TARGET_FPS;const EPSILON=1e-6;const METRICS=['v8:gc:cycle:full','v8:gc:cycle:full:cpp','v8:gc:cycle:full:mark','v8:gc:cycle:full:mark:cpp','v8:gc:cycle:full:weak','v8:gc:cycle:full:weak:cpp','v8:gc:cycle:full:sweep','v8:gc:cycle:full:sweep:cpp','v8:gc:cycle:full:compact','v8:gc:cycle:full:compact:cpp','v8:gc:cycle:main_thread:full','v8:gc:cycle:main_thread:full:cpp','v8:gc:cycle:main_thread:full:mark','v8:gc:cycle:main_thread:full:mark:cpp','v8:gc:cycle:main_thread:full:weak','v8:gc:cycle:main_thread:full:weak:cpp','v8:gc:cycle:main_thread:full:sweep','v8:gc:cycle:main_thread:full:sweep:cpp','v8:gc:cycle:main_thread:full:compact','v8:gc:cycle:main_thread:full:compact:cpp','v8:gc:event:main_thread:full:atomic','v8:gc:event:main_thread:full:atomic:cpp','v8:gc:event:main_thread:full:atomic:mark','v8:gc:event:main_thread:full:atomic:mark:cpp','v8:gc:event:main_thread:full:atomic:weak','v8:gc:event:main_thread:full:atomic:weak:cpp','v8:gc:event:main_thread:full:atomic:sweep','v8:gc:event:main_thread:full:atomic:sweep:cpp','v8:gc:event:main_thread:full:atomic:compact','v8:gc:event:main_thread:full:atomic:compact:cpp','v8:gc:event:main_thread:full:incremental','v8:gc:event:main_thread:full:incremental:cpp','v8:gc:event:main_thread:full:incremental:mark','v8:gc:event:main_thread:full:incremental:mark:cpp','v8:gc:event:main_thread:full:incremental:sweep','v8:gc:event:main_thread:full:incremental:sweep:cpp','v8:gc:cycle:young','v8:gc:cycle:main_thread:young',];const V8_FULL_ATOMIC_EVENTS=['V8.GCCompactor','V8.GCFinalizeMC','V8.GCFinalizeMCReduceMemory',];const V8_FULL_MARK_EVENTS=['V8.GC_MC_BACKGROUND_MARKING','V8.GC_MC_MARK','V8.GCIncrementalMarking','V8.GCIncrementalMarkingFinalize','V8.GCIncrementalMarkingStart',];const V8_FULL_COMPACT_EVENTS=['V8.GC_MC_BACKGROUND_EVACUATE_COPY','V8.GC_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS','V8.GC_MC_EVACUATE',];const V8_FULL_SWEEP_EVENTS=['V8.GC_MC_BACKGROUND_SWEEPING','V8.GC_MC_SWEEP',];const V8_FULL_WEAK_EVENTS=['V8.GC_MC_CLEAR',];const V8_YOUNG_EVENTS=['V8.GC_SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL','V8.GCScavenger',];const CPP_GC_FULL_MARK_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.ConcurrentMarkingStep','BlinkGC.IncrementalMarkingStartMarking','BlinkGC.IncrementalMarkingStep','BlinkGC.MarkBailOutObjects','BlinkGC.MarkFlushEphemeronPairs','BlinkGC.MarkFlushV8References','BlinkGC.UnifiedMarkingStep',];const CPP_GC_FULL_COMPACT_EVENTS=['BlinkGC.AtomicPauseSweepAndCompact',];const CPP_GC_FULL_SWEEP_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.ConcurrentSweepingStep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation',];const RULES=[{events:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic',},{events:V8_FULL_MARK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:mark',},{events:CPP_GC_FULL_MARK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:mark:cpp',},{events:V8_FULL_MARK_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:mark',},{events:CPP_GC_FULL_MARK_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:mark:cpp',},{events:V8_FULL_COMPACT_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:compact',},{events:CPP_GC_FULL_COMPACT_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:compact:cpp',},{events:V8_FULL_SWEEP_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:sweep',},{events:CPP_GC_FULL_SWEEP_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:sweep:cpp',},{events:V8_FULL_WEAK_EVENTS,inside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:atomic:weak',},{events:V8_FULL_SWEEP_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:sweep',},{events:CPP_GC_FULL_SWEEP_EVENTS,outside:V8_FULL_ATOMIC_EVENTS,contribute_to:'full:incremental:sweep:cpp',},{events:V8_YOUNG_EVENTS,contribute_to:'young:atomic',},];const Granularity={CYCLE:'cycle',EVENT:'event',};const ThreadType={MAIN:'main',BACKGROUND:'background',ALL_THREADS:'all_threads',};class Metric{constructor(name){const parts=name.split(':');this.granularity_=parts[2];assert(this.granularity_===Granularity.CYCLE||this.granularity_===Granularity.EVENT);this.thread_=ThreadType.ALL_THREADS;let phasesIndex=3;if(parts[3]==='main_thread'){this.thread_=ThreadType.MAIN;phasesIndex=4;}
+if(parts[3]==='background_threads'){this.thread_=ThreadType.BACKGROUND;phasesIndex=4;}
+this.phases_=parts.slice(phasesIndex);const maxValue=this.isPerCycleMetric()?10000:1000;const boundaries=tr.v.HistogramBinBoundaries.createExponential(0.1,maxValue,100);this.histogram=new tr.v.Histogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,boundaries);this.histogram.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:false,sum:this.isPerCycleMetric(),});}
+isPerCycleMetric(){return this.granularity_===Granularity.CYCLE;}
+isMoreGeneralThanOrEqualTo(phases){const phasesSet=new Set(phases.split(':'));return this.phases_.every(phase=>phasesSet.has(phase));}
+contributingEvents(rules,events){const eventsByName=groupBy(events,e=>e.title);function matches(rule,event){function isEnclosing(name){if(!eventsByName.has(name))return false;return eventsByName.get(name).some(e=>encloses(e,event));}
+if(!rule.events.includes(event.title)){return false;}
+if(rule.inside&&!rule.inside.some(isEnclosing)){return false;}
+if(rule.outside&&rule.outside.some(isEnclosing)){return false;}
+return true;}
+const result=[];for(const event of events){const matching=rules.filter(r=>matches(r,event));if(matching.length===0){continue;}
+assert(matching.length===1,`${event.userFriendlyName} matches more than one rule: `+
+JSON.stringify(matching));if(this.isMoreGeneralThanOrEqualTo(matching[0].contribute_to)){result.push(event);}}
+return result;}
+apply(rules,events,threadTypes){const filtered=this.contributingEvents(rules,events);const eventsByThread=groupBy(filtered,e=>e.parentContainer.tid);let flattened=[];for(const[tid,threadEvents]of eventsByThread){if(this.thread_===ThreadType.ALL_THREADS||this.thread_===threadTypes.get(tid)){flattened=flattened.concat(flatten(threadEvents));}}
+if(this.isPerCycleMetric()){let sum=0;for(const event of flattened){sum+=event.cpuDuration;}
+if(flattened.length>0){this.histogram.addSample(sum);}}else{for(const event of flattened){this.histogram.addSample(event.cpuDuration);}}}}
+function assert(condition,message){if(!condition){throw new Error(message);}}
+function groupBy(objects,keyCallback){const result=new Map();for(const object of objects){const group=keyCallback(object);if(result.has(group)){result.get(group).push(object);}else{result.set(group,[object]);}}
+return result;}
+function eventsMentionedIn(rules){let result=[];for(const rule of rules){result=result.concat(rule.events);if(rule.inside){result=result.concat(rule.inside);}
+if(rule.outside){result=result.concat(rule.outside);}}
+return result;}
+function encloses(event1,event2){return(event1.start-EPSILON<=event2.start&&event2.end<=event1.end+EPSILON);}
+function jsExecutionThreadsWithTypes(rendererHelper){const mainThreads=([rendererHelper.mainThread].concat(rendererHelper.dedicatedWorkerThreads).concat(rendererHelper.serviceWorkerThreads));const backgroundThreads=rendererHelper.foregroundWorkerThreads;const threadTypes=new Map();for(const thread of mainThreads){threadTypes.set(thread.tid,ThreadType.MAIN);}
+for(const thread of backgroundThreads){threadTypes.set(thread.tid,ThreadType.BACKGROUND);}
+return[mainThreads.concat(backgroundThreads),threadTypes];}
+function flatten(events){function compareWithEpsilon(a,b){if(a.start<b.start-EPSILON)return-1;if(a.start>b.start+EPSILON)return 1;return b.end-a.end;}
+events.sort(compareWithEpsilon);let last=events[0];const result=[last];for(const e of events){if(e.end>last.end+EPSILON){assert(e.start>=last.end-EPSILON,'Overlapping events: '+
+e.userFriendlyName+' '+
+last.userFriendlyName);result.push(e);last=e;}}
+return result;}
+function groupByEpoch(events){function isV8Event(event){return event.category&&event.category.includes('v8');}
+function getEpoch(event){function checkEpochConsistency(epoch,event){if(epoch===null)return;assert(epoch===event.args.epoch,`${event.userFriendlyName} has epoch ${event.args.epoch} `+`which contradicts the epoch of nested events ${epoch}`);}
+const result={v8:null,cpp:null};while(event){if('epoch'in event.args){if(isV8Event(event)){checkEpochConsistency(result.v8,event);result.v8=event.args.epoch;}else{checkEpochConsistency(result.cpp,event);result.cpp=event.args.epoch;}}
+event=event.parentSlice;}
+return result;}
+const cppToV8=new Map();for(const event of events){const epoch=getEpoch(event);if(epoch.cpp!==null&&epoch.v8!==null){assert(!cppToV8.has(epoch.cpp)||cppToV8.get(epoch.cpp)===epoch.v8,`CppGC epoch ${epoch.cpp} corresponds to two v8 epochs `+`${cppToV8.get(epoch.cpp)} and ${epoch.v8}. `+`Detected at ${event.userFriendlyName}.`);cppToV8.set(epoch.cpp,epoch.v8);}}
+const result=new Map();for(const event of events){const epoch=getEpoch(event);if(epoch.cpp===null&&epoch.v8===null){continue;}
+assert(epoch.cpp===null||cppToV8.has(epoch.cpp),`CppGC epoch ${epoch.cpp} doesn't have the corresponding V8 epoch. `+`Detected at ${event.userFriendlyName}`);const key=epoch.v8===null?cppToV8.get(epoch.cpp):epoch.v8;if(result.has(key)){result.get(key).push(event);}else{result.set(key,[event]);}}
+return result;}
+function addGarbageCollectionMetrics(metricNames,histograms,model){const metrics=metricNames.map(name=>new Metric(name));const gcEventNames=new Set(eventsMentionedIn(RULES));const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;const[threads,threadTypes]=jsExecutionThreadsWithTypes(rendererHelper);const events=[];for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(gcEventNames.has(event.title)){events.push(event);}}}
+for(const cycleEvents of groupByEpoch(events).values()){if(cycleEvents.some(tr.metrics.v8.utils.isForcedGarbageCollectionEvent)){continue;}
+for(const metric of metrics){metric.apply(RULES,cycleEvents,threadTypes);}}}
+for(const metric of metrics){histograms.addHistogram(metric.histogram);}}
+function gcMetric(histograms,model,options){options=options||{};addDurationOfTopEvents(histograms,model);addTotalDurationOfTopEvents(histograms,model);if(options.include_sub_events){addDurationOfSubEvents(histograms,model);}
+addPercentageInV8ExecuteOfTopEvents(histograms,model);addTotalPercentageInV8Execute(histograms,model);addMarkCompactorMutatorUtilization(histograms,model);addTotalMarkCompactorTime(histograms,model);addTotalMarkCompactorMarkingTime(histograms,model);addScavengerSurvivedFromStackEvents(histograms,model);}
+tr.metrics.MetricRegistry.register(gcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const bytes_smallerIsBetter=tr.b.Unit.byName.sizeInBytes_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
 function createNumericForSubEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:false,std:false,sum:false,percentile:[0.90]});return n;}
 function createNumericForIdleTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:false,std:false,sum:true,percentile:[]});return n;}
 function createPercentage(name,numerator,denominator,unit){const hist=new tr.v.Histogram(name,unit);if(denominator===0){hist.addSample(0);}else{hist.addSample(numerator/denominator);}
@@ -9245,13 +9065,16 @@
 histograms.addHistogram(foregroundDuration);histograms.addHistogram(backgroundDuration);histograms.addHistogram(totalDuration,{breakdown:relatedNames});}
 function addTotalMarkCompactorTime(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8MarkCompactorSummary,event=>'v8-gc-mark-compactor',(name,events)=>createHistogramFromSummary(histograms,name,events),['v8-gc-mark-compactor']);}
 function addTotalMarkCompactorMarkingTime(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8MarkCompactorMarkingSummary,event=>'v8-gc-mark-compactor-marking',(name,events)=>createHistogramFromSummary(histograms,name,events),['v8-gc-mark-compactor-marking']);}
+function createNumericForTotalBytes(name){const n=new tr.v.Histogram(name,bytes_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:false,max:false,min:false,std:false,sum:true,percentile:[]});return n;}
+function createNumericForSampledPercent(name){const n=new tr.v.Histogram(name,percentage_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:true,std:true,sum:false,percentile:[]});return n;}
+function addScavengerSurvivedFromStackEvents(histograms,model){const baseName='v8-gc-scavenger-survived';tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isScavengerStackScanningEvent,event=>baseName,function(name,events){const sampledPercentage=createNumericForSampledPercent(baseName+'-percentage-from-stack');let survivedWithoutStack=0;let survivedWithStack=0;events.forEach(function(event){const bytesBefore=event.args.survived_bytes_before;const bytesAfter=event.args.survived_bytes_after;sampledPercentage.addSample((bytesAfter>0)?(bytesAfter-bytesBefore)/bytesAfter:0);survivedWithoutStack+=bytesBefore;survivedWithStack+=bytesAfter;});histograms.addHistogram(sampledPercentage);const totalBytesSurvivedWithoutStack=createNumericForTotalBytes(baseName+'-total-bytes-without-stack');totalBytesSurvivedWithoutStack.addSample(survivedWithoutStack);histograms.addHistogram(totalBytesSurvivedWithoutStack);const totalBytesSurvivedWithStack=createNumericForTotalBytes(baseName+'-total-bytes-with-stack');totalBytesSurvivedWithStack.addSample(survivedWithStack);histograms.addHistogram(totalBytesSurvivedWithStack);const overallPercentage=createPercentage(baseName+'-total-percentage-from-stack',survivedWithStack-survivedWithoutStack,survivedWithStack,percentage_smallerIsBetter);histograms.addHistogram(overallPercentage);},[baseName]);}
 function addDurationOfSubEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedSubGarbageCollectionEvent,tr.metrics.v8.utils.subGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForSubEventTime(name);events.forEach(function(event){cpuDuration.addSample(event.cpuDuration);});histograms.addHistogram(cpuDuration);});}
 function addPercentageInV8ExecuteOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,tr.metrics.v8.utils.topGarbageCollectionEventName,function(name,events){addPercentageInV8Execute(histograms,model,name,events);},tr.metrics.v8.utils.topGarbageCollectionEventNames());}
 function addTotalPercentageInV8Execute(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,event=>'v8-gc-total',function(name,events){addPercentageInV8Execute(histograms,model,name,events);},['v8-gc-total']);}
 function addPercentageInV8Execute(histograms,model,name,events){let cpuDurationInV8Execute=0;let cpuDurationTotal=0;events.forEach(function(event){const v8Execute=tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isV8ExecuteEvent);if(v8Execute){cpuDurationInV8Execute+=event.cpuDuration;}
 cpuDurationTotal+=event.cpuDuration;});const percentage=createPercentage(name+'_percentage_in_v8_execute',cpuDurationInV8Execute,cpuDurationTotal,percentage_smallerIsBetter);histograms.addHistogram(percentage);}
 function addMarkCompactorMutatorUtilization(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=Object.values(chromeHelper.rendererHelpers);tr.metrics.v8.utils.addMutatorUtilization('v8-gc-mark-compactor-mmu',tr.metrics.v8.utils.isNotForcedMarkCompactorEvent,[100],rendererHelpers,histograms);}
-return{gcMetric,WINDOW_SIZE_MS,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const COUNT_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1000000,50);const DURATION_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.1,10000,50);const SUMMARY_OPTIONS={std:false,count:false,sum:false,min:false,max:false,};function convertMicroToMilli_(time){return tr.b.convertUnit(time,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);}
+return{gcMetric,WINDOW_SIZE_MS,addGarbageCollectionMetrics,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const COUNT_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1000000,50);const DURATION_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.1,10000,50);const SUMMARY_OPTIONS={std:false,count:false,sum:false,min:false,max:false,};function convertMicroToMilli_(time){return tr.b.convertUnit(time,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);}
 function addDurationHistogram(histogramName,time,histograms){const value=convertMicroToMilli_(time);histograms.createHistogram(`${histogramName}:duration`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,{value},{binBoundaries:DURATION_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});}
 function addCountHistogram(histogramName,value,histograms){histograms.createHistogram(`${histogramName}:count`,tr.b.Unit.byName.count_smallerIsBetter,{value},{binBoundaries:COUNT_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS});}
 function runtimeStatsTotalMetric(histograms,model){const v8Slices=tr.metrics.v8.utils.filterEvents(model,ev=>ev instanceof tr.e.v8.V8ThreadSlice);const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(v8Slices);let overallV8Time=runtimeGroupCollection.totalTime;let overallV8Count=runtimeGroupCollection.totalCount;let mainThreadTime=runtimeGroupCollection.totalTime;let mainThreadCount=runtimeGroupCollection.totalCount;let mainThreadV8Time=runtimeGroupCollection.totalTime;let mainThreadV8Count=runtimeGroupCollection.totalCount;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addDurationHistogram(runtimeGroup.name,runtimeGroup.time,histograms);if(runtimeGroup.name==='Blink C++'){overallV8Time-=runtimeGroup.time;mainThreadV8Time-=runtimeGroup.time;}else if(runtimeGroup.name.includes('Background')){mainThreadTime-=runtimeGroup.time;mainThreadV8Time-=runtimeGroup.time;}
@@ -9259,7 +9082,15 @@
 if(runtimeGroupCollection.blinkRCSGroupCollection.totalTime>0){const blinkRCSGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;for(const group of blinkRCSGroupCollection.runtimeGroups){addDurationHistogram(group.name,group.time,histograms);addCountHistogram(group.name,group.count,histograms);}}
 addDurationHistogram('V8-Only',overallV8Time,histograms);addCountHistogram('V8-Only',overallV8Count,histograms);addDurationHistogram('Total-Main-Thread',mainThreadTime,histograms);addCountHistogram('Total-Main-Thread',mainThreadCount,histograms);addDurationHistogram('V8-Only-Main-Thread',mainThreadV8Time,histograms);addCountHistogram('V8-Only-Main-Thread',mainThreadV8Count,histograms);}
 tr.metrics.MetricRegistry.register(runtimeStatsTotalMetric);return{runtimeStatsTotalMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){function v8AndMemoryMetrics(histograms,model){tr.metrics.v8.executionMetric(histograms,model);tr.metrics.v8.gcMetric(histograms,model);tr.metrics.sh.memoryMetric(histograms,model,{rangeOfInterest:tr.metrics.v8.utils.rangeForMemoryDumps(model)});}
-tr.metrics.MetricRegistry.register(v8AndMemoryMetrics);return{v8AndMemoryMetrics,};});'use strict';tr.exportTo('tr.metrics.vr',function(){const VR_GL_THREAD_NAME='VrShellGL';function createHistograms(histograms,name,options,hasCpuTime){const createdHistograms={wall:histograms.createHistogram(name+'_wall',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options)};if(hasCpuTime){createdHistograms.cpu=histograms.createHistogram(name+'_cpu',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options);}
+tr.metrics.MetricRegistry.register(v8AndMemoryMetrics);return{v8AndMemoryMetrics,};});'use strict';tr.exportTo('tr.metrics.v8',function(){function computeSyncInstantiationTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.SyncInstantiate'))return;const wasmSyncInstantiationTimeCPU=new tr.v.Histogram('v8:wasm:sync_instantiate:cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);wasmSyncInstantiationTimeCPU.description='cpu time spent instantiating a WebAssembly module';const wasmSyncInstantiationTimeWall=new tr.v.Histogram('v8:wasm:sync_instantiate:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);wasmSyncInstantiationTimeWall.description='wall time spent instantiating a WebAssembly module';for(const e of wasmEvents['wasm.SyncInstantiate']){wasmSyncInstantiationTimeCPU.addSample(e.cpuDuration);wasmSyncInstantiationTimeWall.addSample(e.duration);}
+histograms.addHistogram(wasmSyncInstantiationTimeCPU);histograms.addHistogram(wasmSyncInstantiationTimeWall);}
+function computeStreamingBaselineCompileTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.StartStreamingCompilation')||!wasmEvents.hasOwnProperty('wasm.BaselineFinished')){return;}
+const histogram=new tr.v.Histogram('v8:wasm:streaming_baseline_compilation:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);const compilationStart=wasmEvents['wasm.StartStreamingCompilation'][0].start;const compilationEnd=wasmEvents['wasm.BaselineFinished'][0].end;histogram.addSample(compilationEnd-compilationStart);histograms.addHistogram(histogram);}
+function computeCompilationTierupWallTimeMetric(histograms,wasmEvents){if(!wasmEvents.hasOwnProperty('wasm.BaselineFinished')||!wasmEvents.hasOwnProperty('wasm.TopTierFinished')){return;}
+const histogram=new tr.v.Histogram('v8:wasm:compilation_tierup:wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);const tierupStart=wasmEvents['wasm.BaselineFinished'][0].start;const tierupEnd=wasmEvents['wasm.TopTierFinished'][0].end;histogram.addSample(tierupEnd-tierupStart);histograms.addHistogram(histogram);}
+function collectWasmEvents(model){const wasmEvents=tr.metrics.v8.utils.filterAndOrderEvents(model,event=>event.title.startsWith('wasm.'),event=>event.title);return wasmEvents;}
+function wasmMetric(histograms,model){const wasmEvents=collectWasmEvents(model);computeSyncInstantiationTimeMetric(histograms,wasmEvents);computeStreamingBaselineCompileTimeMetric(histograms,wasmEvents);computeCompilationTierupWallTimeMetric(histograms,wasmEvents);}
+tr.metrics.MetricRegistry.register(wasmMetric);return{wasmMetric,};});'use strict';tr.exportTo('tr.metrics.vr',function(){const VR_GL_THREAD_NAME='VrShellGL';function createHistograms(histograms,name,options,hasCpuTime){const createdHistograms={wall:histograms.createHistogram(name+'_wall',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options)};if(hasCpuTime){createdHistograms.cpu=histograms.createHistogram(name+'_cpu',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options);}
 return createdHistograms;}
 function frameCycleDurationMetric(histograms,model,opt_options){const histogramsByEventTitle=new Map();const expectationEvents=tr.importer.VR_EXPECTATION_EVENTS;for(const eventName in expectationEvents){const extraInfo=expectationEvents[eventName];histogramsByEventTitle.set(eventName,createHistograms(histograms,extraInfo.histogramName,{description:extraInfo.description},extraInfo.hasCpuTime));}
 histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateAnimationsAndOpacity',createHistograms(histograms,'update_animations_and_opacity',{description:'Duration to apply animation and opacity changes'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateBindings',createHistograms(histograms,'update_bindings',{description:'Duration to push binding values'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateLayout',createHistograms(histograms,'update_layout',{description:'Duration to compute element sizes, layout and textures'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateWorldSpaceTransform',createHistograms(histograms,'update_world_space_transforms',{description:'Duration to calculate element transforms in world space'},true));histogramsByEventTitle.set('UiRenderer::DrawUiView',createHistograms(histograms,'draw_ui',{description:'Duration to draw the UI'},true));histogramsByEventTitle.set('UiElementRenderer::DrawTexturedQuad',createHistograms(histograms,'draw_textured_quad',{description:'Duration to draw a textured element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientQuad',createHistograms(histograms,'draw_gradient_quad',{description:'Duration to draw a gradient element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientGridQuad',createHistograms(histograms,'draw_gradient_grid_quad',{description:'Duration to draw a gradient grid element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawController',createHistograms(histograms,'draw_controller',{description:'Duration to draw the controller'},true));histogramsByEventTitle.set('UiElementRenderer::DrawLaser',createHistograms(histograms,'draw_laser',{description:'Duration to draw the laser'},true));histogramsByEventTitle.set('UiElementRenderer::DrawReticle',createHistograms(histograms,'draw_reticle',{description:'Duration to draw the reticle'},true));histogramsByEventTitle.set('UiElementRenderer::DrawShadow',createHistograms(histograms,'draw_shadow',{description:'Duration to draw a shadow element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawStars',createHistograms(histograms,'draw_stars',{description:'Duration to draw the stars'},true));histogramsByEventTitle.set('UiElementRenderer::DrawBackground',createHistograms(histograms,'draw_background',{description:'Duration to draw the textured background'},true));histogramsByEventTitle.set('UiElementRenderer::DrawKeyboard',createHistograms(histograms,'draw_keyboard',{description:'Duration to draw the keyboard'},true));const drawUiSubSlicesMap=new Map();const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let rangeOfInterest=model.bounds;const userExpectationsOfInterest=[tr.model.um.AnimationExpectation];if(opt_options&&opt_options.rangeOfInterest){rangeOfInterest=opt_options.rangeOfInterest;userExpectationsOfInterest.push(tr.model.um.ResponseExpectation);}
@@ -9315,7 +9146,18 @@
 function getSmoothnessStats(driftTimes){const meanDriftTime=tr.b.math.Statistics.mean(driftTimes);const normDriftTimes=driftTimes.map(driftTime=>Math.abs(driftTime-meanDriftTime));const framesSeverelyOutOfSync=normDriftTimes.filter(driftTime=>driftTime>2*VSYNC_DURATION_US).length;const framesOutOfSync=normDriftTimes.filter(driftTime=>driftTime>VSYNC_DURATION_US).length;const percentBadlyOutOfSync=framesSeverelyOutOfSync/driftTimes.length;const percentOutOfSync=framesOutOfSync/driftTimes.length;const framesOutOfSyncOnlyOnce=framesOutOfSync-framesSeverelyOutOfSync;let smoothnessScore=1-(framesOutOfSyncOnlyOnce+
 SEVERITY*framesSeverelyOutOfSync)/driftTimes.length;if(smoothnessScore<0){smoothnessScore=0;}
 return{framesOutOfSync,framesSeverelyOutOfSync,percentBadlyOutOfSync,percentOutOfSync,smoothnessScore};}
-return{webrtcRenderingMetric,};});'use strict';Polymer({is:'tr-ui-a-alert-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},getRowsForSingleAlert_(alert){const rows=[];for(const argName in alert.args){const argView=document.createElement('tr-ui-a-generic-object-view');argView.object=alert.args[argName];rows.push({name:argName,value:argView});}
+return{webrtcRenderingMetric,};});'use strict';tr.exportTo('tr.metrics.webui',function(){function webuiMetric(histograms,model,opt_options){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper){return;}
+const WEBUI_TITLE_PREFIX='webui_metric:';const traces=new Map();const benchmarkValues=new Map();for(const helper of chromeHelper.browserHelpers){if(!helper.mainThread)continue;for(const slice of helper.mainThread.sliceGroup.slices.concat(helper.mainThread.asyncSliceGroup.slices)){if(!slice.error&&slice.title.startsWith(WEBUI_TITLE_PREFIX)){if(!traces.has(slice.title)){traces.set(slice.title,[]);}
+traces.get(slice.title).push(slice.duration);}}}
+const BENCHMARK_BEGIN='benchmark_begin';const BENCHMARK_END='benchmark_end';const BENCHMARK_VALUE='benchmark_value';const marks=new Map();for(const helper of Object.values(chromeHelper.rendererHelpers)){for(const event of helper.mainThread.sliceGroup.childEvents()){const navId=getNavigationId(event);if(!navId||!event.category.includes('blink.user_timing'))continue;const{title}=event;const index=title.lastIndexOf(':');if(index===-1){continue;}
+const name=title.substring(0,index);const lastPart=title.substring(index+1);if(lastPart===BENCHMARK_BEGIN){marks.set(name,event);}else if(lastPart===BENCHMARK_END){if(!marks.has(name)){continue;}
+const range=tr.b.math.Range.fromExplicitRange(marks.get(name).start,event.start);if(!traces.has(name)){traces.set(name,[]);}
+traces.get(name).push(range.duration);marks.delete(name);}else if(lastPart===BENCHMARK_VALUE){const index2=name.lastIndexOf(':');if(index2===-1){continue;}
+const key=name.substring(0,index2);const value=Number(name.substring(index2+1));if(key&&!isNaN(value)){if(!benchmarkValues.has(key)){benchmarkValues.set(key,[]);}
+benchmarkValues.get(key).push(value);}}}}
+traces.forEach((value,key)=>{histograms.createHistogram(key,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value);});benchmarkValues.forEach((value,key)=>{histograms.createHistogram(key,tr.b.Unit.byName.unitlessNumber_smallerIsBetter,value);});}
+function getNavigationId(event){return event.args.data&&event.args.data.navigationId;}
+tr.metrics.MetricRegistry.register(webuiMetric,{supportsRangeOfInterest:false,});return{webuiMetric,};});'use strict';Polymer({is:'tr-ui-a-alert-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},getRowsForSingleAlert_(alert){const rows=[];for(const argName in alert.args){const argView=document.createElement('tr-ui-a-generic-object-view');argView.object=alert.args[argName];rows.push({name:argName,value:argView});}
 if(alert.associatedEvents.length){alert.associatedEvents.forEach(function(event,i){const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(new tr.model.EventSet(event),event.title);let valueString='';if(event instanceof tr.model.TimedEvent){valueString='took '+event.duration.toFixed(2)+'ms';}
 rows.push({name:linkEl,value:valueString});});}
 const descriptionEl=tr.ui.b.createDiv({textContent:alert.info.description,maxWidth:'300px'});rows.push({name:'Description',value:descriptionEl});if(alert.info.docLinks){alert.info.docLinks.forEach(function(linkObject){const linkEl=document.createElement('a');linkEl.target='_blank';linkEl.href=linkObject.href;Polymer.dom(linkEl).textContent=Polymer.dom(linkObject).textContent;rows.push({name:linkObject.label,value:linkEl});});}
@@ -9968,7 +9810,8 @@
 for(let i=0;i<subGroupRows.length;i++){rowsWithHeadings.push({row:subGroupRows[i],heading:(i===0?subGroup.title:'')});}}
 this.setPrebuiltSubRows(this.group_,rowsWithHeadings);}};function stripSlice_(slice){if(slice.subSlices!==undefined&&slice.subSlices.length===1){const subSlice=slice.subSlices[0];if(tr.b.math.approximately(subSlice.start,slice.start,1)&&tr.b.math.approximately(subSlice.duration,slice.duration,1)){return subSlice;}}
 return slice;}
-function makeLevelSubRows_(slices){const rows=[];const putSlice=(slice,level)=>{while(rows.length<=level){rows.push([]);}
+function makeLevelSubRows_(slices){const rows=[];const putSlice=(slice,level)=>{if(slice.hidden){return;}
+while(rows.length<=level){rows.push([]);}
 rows[level].push(slice);};const putSliceRecursively=(slice,level)=>{putSlice(slice,level);if(slice.subSlices!==undefined){for(const subSlice of slice.subSlices){putSliceRecursively(subSlice,level+1);}}};for(const slice of slices){putSliceRecursively(stripSlice_(slice),0);}
 return rows;}
 function groupAsyncSlicesIntoSubRows(slices,opt_skipSort){if(!opt_skipSort){slices.sort((x,y)=>x.start-y.start);}
@@ -10111,9 +9954,9 @@
 for(const labelEl of unsupportedLabelEls){Polymer.dom(this.tabStrip_).appendChild(labelEl);}
 if(previouslyActivePanelType&&supportedPanelTypes.includes(previouslyActivePanelType)){this.activePanelType=previouslyActivePanelType;Polymer.dom(this).setAttribute('expanded',true);}else{if(this.activePanel){Polymer.dom(this.activePanelContainer_).removeChild(this.activePanel);}
 Polymer.dom(this).removeAttribute('expanded');}},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){if(range===undefined){throw new Error('Must not be undefined');}
-this.rangeOfInterest_=range;if(this.activePanel){this.activePanel.rangeOfInterest=range;}}});'use strict';Polymer({is:'tr-ui-timeline-view-help-overlay',ready(){const mod=tr.isMac?'cmd ':'ctrl';const spans=Polymer.dom(this.root).querySelectorAll('span.mod');for(let i=0;i<spans.length;i++){Polymer.dom(spans[i]).textContent=mod;}}});'use strict';Polymer({is:'tr-ui-timeline-view-metadata-overlay',created(){this.metadata_=undefined;},ready(){this.$.table.tableColumns=[{title:'name',value:d=>d.name,},{title:'value',value:d=>{const gov=document.createElement('tr-ui-a-generic-object-view');gov.object=d.value;return gov;},}];},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.table.tableRows=this.metadata_;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-v-ui-preferred-display-unit',ready(){this.preferredTimeDisplayMode_=undefined;},attached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},detached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},get preferredTimeDisplayMode(){return this.preferredTimeDisplayMode_;},set preferredTimeDisplayMode(v){if(this.preferredTimeDisplayMode_===v)return;this.preferredTimeDisplayMode_=v;tr.b.Unit.didPreferredTimeDisplayUnitChange();}});'use strict';const POLYFILL_WARNING_MESSAGE='Trace Viewer is running with WebComponentsV0 polyfill, and some '+'features may be broken. As a workaround, you may try running chrome '+'with "--enable-blink-features=ShadowDOMV0,CustomElementsV0,HTMLImports" '+'flag. See crbug.com/1036492.';Polymer({is:'tr-ui-timeline-view',created(){this.trackViewContainer_=undefined;this.queuedModel_=undefined;this.builtPromise_=undefined;this.doneBuilding_=undefined;},attached(){this.async(function(){this.trackViewContainer_=Polymer.dom(this).querySelector('#track_view_container');if(!this.trackViewContainer_){throw new Error('missing trackviewContainer');}
+this.rangeOfInterest_=range;if(this.activePanel){this.activePanel.rangeOfInterest=range;}}});'use strict';Polymer({is:'tr-ui-timeline-view-help-overlay',ready(){const mod=tr.isMac?'cmd ':'ctrl';const spans=Polymer.dom(this.root).querySelectorAll('span.mod');for(let i=0;i<spans.length;i++){Polymer.dom(spans[i]).textContent=mod;}}});'use strict';Polymer({is:'tr-ui-timeline-view-metadata-overlay',created(){this.metadata_=undefined;},ready(){this.$.table.tableColumns=[{title:'name',value:d=>d.name,},{title:'value',value:d=>{const gov=document.createElement('tr-ui-a-generic-object-view');gov.object=d.value;return gov;},}];},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.table.tableRows=this.metadata_;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-v-ui-preferred-display-unit',ready(){this.preferredTimeDisplayMode_=undefined;},attached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},detached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},get preferredTimeDisplayMode(){return this.preferredTimeDisplayMode_;},set preferredTimeDisplayMode(v){if(this.preferredTimeDisplayMode_===v)return;this.preferredTimeDisplayMode_=v;tr.b.Unit.didPreferredTimeDisplayUnitChange();}});'use strict';const POLYFILL_WARNING_MESSAGE='Trace Viewer is running with WebComponentsV0 polyfill, and some '+'features may be broken. See crbug.com/1036492.';Polymer({is:'tr-ui-timeline-view',created(){this.trackViewContainer_=undefined;this.queuedModel_=undefined;this.builtPromise_=undefined;this.doneBuilding_=undefined;},attached(){this.async(function(){this.trackViewContainer_=Polymer.dom(this).querySelector('#track_view_container');if(!this.trackViewContainer_){throw new Error('missing trackviewContainer');}
 if(this.queuedModel_)this.updateContents_();});},ready(){this.tabIndex=0;this.polyfillWarnedOnce_=false;this.titleEl_=this.$.title;this.leftControlsEl_=this.$.left_controls;this.rightControlsEl_=this.$.right_controls;this.collapsingControlsEl_=this.$.collapsing_controls;this.sidePanelContainer_=this.$.side_panel_container;this.brushingStateController_=new tr.c.BrushingStateController(this);this.findCtl_=this.$.view_find_control;this.findCtl_.controller=new tr.ui.FindController(this.brushingStateController_);this.scriptingCtl_=document.createElement('tr-ui-scripting-control');this.scriptingCtl_.controller=new tr.c.ScriptingController(this.brushingStateController_);this.sidePanelContainer_.brushingStateController=this.brushingStateController_;if(window.tr.metrics&&window.tr.metrics.sh&&window.tr.metrics.sh.SystemHealthMetric){this.railScoreSpan_=document.createElement('tr-metrics-ui-sh-system-health-span');Polymer.dom(this.rightControls).appendChild(this.railScoreSpan_);}else{this.railScoreSpan_=undefined;}
-this.flowEventFilter_=this.$.flow_event_filter_dropdown;this.processFilter_=this.$.process_filter_dropdown;this.optionsDropdown_=this.$.view_options_dropdown;this.selectedFlowEvents_=new Set();this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.ui.b.createCheckBox(this,'highlightVSync','tr.ui.TimelineView.highlightVSync',false,'Highlight VSync');Polymer.dom(this.optionsDropdown_).appendChild(this.highlightVSyncCheckbox_);this.initMetadataButton_();this.initConsoleButton_();this.initHelpButton_();Polymer.dom(this.collapsingControls).appendChild(this.scriptingCtl_);this.dragEl_=this.$.drag_handle;this.analysisEl_=this.$.analysis;this.analysisEl_.brushingStateController=this.brushingStateController_;this.addEventListener('requestSelectionChange',function(e){const sc=this.brushingStateController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);this.bindKeyListeners_();this.dragEl_.target=this.analysisEl_;},get globalMode(){return this.hotkeyController.globalMode;},set globalMode(globalMode){globalMode=!!globalMode;this.brushingStateController_.historyEnabled=globalMode;this.hotkeyController.globalMode=globalMode;},get hotkeyController(){return this.$.hkc;},warnPolyfill(){if(this.polyfillWarnedOnce_)return;console.warn(POLYFILL_WARNING_MESSAGE);this.polyfillWarnedOnce_=true;if(!window.__hideTraceViewerPolyfillWarning){const polyfillWarningsEl=Polymer.dom(this.root).querySelector('#polyfill-warning');polyfillWarningsEl.addMessage(POLYFILL_WARNING_MESSAGE,[{buttonText:'Hide',onClick:()=>polyfillWarningsEl.clearMessages()}]);}},updateDocumentFavicon(){let hue;if(!this.model){hue='blue';}else{hue=this.model.faviconHue;}
+this.flowEventFilter_=this.$.flow_event_filter_dropdown;this.processFilter_=this.$.process_filter_dropdown;this.optionsDropdown_=this.$.view_options_dropdown;this.selectedFlowEvents_=new Set();this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.ui.b.createCheckBox(this,'highlightVSync','tr.ui.TimelineView.highlightVSync',false,'Highlight VSync');Polymer.dom(this.optionsDropdown_).appendChild(this.highlightVSyncCheckbox_);this.initMetadataButton_();this.initConsoleButton_();this.initHelpButton_();Polymer.dom(this.collapsingControls).appendChild(this.scriptingCtl_);this.dragEl_=this.$.drag_handle;this.analysisEl_=this.$.analysis;this.analysisEl_.brushingStateController=this.brushingStateController_;this.addEventListener('requestSelectionChange',function(e){const sc=this.brushingStateController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);this.bindKeyListeners_();this.dragEl_.target=this.analysisEl_;},get globalMode(){return this.hotkeyController.globalMode;},set globalMode(globalMode){globalMode=!!globalMode;this.brushingStateController_.historyEnabled=globalMode;this.hotkeyController.globalMode=globalMode;},get hotkeyController(){return this.$.hkc;},warnPolyfill(){if(this.polyfillWarnedOnce_)return;console.warn(POLYFILL_WARNING_MESSAGE);this.polyfillWarnedOnce_=true;},updateDocumentFavicon(){let hue;if(!this.model){hue='blue';}else{hue=this.model.faviconHue;}
 let faviconData=tr.ui.b.FaviconsByHue[hue];if(faviconData===undefined){faviconData=tr.ui.b.FaviconsByHue.blue;}
 let link=Polymer.dom(document.head).querySelector('link[rel="shortcut icon"]');if(!link){link=document.createElement('link');link.rel='shortcut icon';Polymer.dom(document.head).appendChild(link);}
 link.href=faviconData;},get selectedFlowEvents(){return this.selectedFlowEvents_;},set selectedFlowEvents(selectedFlowEvents){this.selectedFlowEvents_=selectedFlowEvents;},get highlightVSync(){return this.highlightVSync_;},set highlightVSync(highlightVSync){this.highlightVSync_=highlightVSync;if(!this.trackView_)return;this.trackView_.viewport.highlightVSync=highlightVSync;},initHelpButton_(){const helpButtonEl=this.$.view_help_button;const dlg=new tr.ui.b.Overlay();dlg.title='Chrome Tracing Help';dlg.visible=false;dlg.appendChild(document.createElement('tr-ui-timeline-view-help-overlay'));function onClick(e){dlg.visible=!dlg.visible;e.stopPropagation();}
@@ -10192,7 +10035,8 @@
 if(config){return{excluded:config.excluded_categories||[],included:config.included_categories||[],};}}}
 function validateTraceCategories(requiredCategories,categories){if(!requiredCategories)return;if(!categories)throw new Error('Missing trace config metadata');for(const cat of requiredCategories){const isDisabledByDefault=(cat.indexOf('disabled-by-default')===0);let missing=false;if(isDisabledByDefault){if(!categories.included.includes(cat)){missing=true;}}else if(categories.excluded.includes(cat)){missing=true;}
 if(missing){throw new Error(`Trace is missing required category "${cat}"`);}}}
-function validateDiagnosticNames(histograms){for(const hist of histograms){for(const name of hist.diagnostics.keys()){if(tr.v.d.RESERVED_NAMES_SET.has(name)){throw new Error(`Illegal diagnostic name "${name}" on Histogram "${hist.name}"`);}}}}
+function validateDiagnosticNames(histograms){for(const hist of histograms){for(const name of hist.diagnostics.keys()){if(name===tr.v.d.RESERVED_NAMES.ALERT_GROUPING){continue;}
+if(tr.v.d.RESERVED_NAMES_SET.has(name)){throw new Error(`Illegal diagnostic name "${name}" on Histogram "${hist.name}"`);}}}}
 function addTelemetryInfo(histograms,model){for(const metadata of model.metadata){if(!metadata.value||!metadata.value.telemetry)continue;for(const[name,value]of Object.entries(metadata.value.telemetry)){const type=tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);if(type===undefined){throw new Error(`Unexpected telemetry.${name}`);}
 histograms.addSharedDiagnosticToAllHistograms(name,new type(value));}}}
 function metricMapFunction(result,model,options){const histograms=runMetrics(model,options,result.addFailure.bind(result));addTelemetryInfo(histograms,model);if(model.canonicalUrl!==undefined){const info=tr.v.d.RESERVED_INFOS.TRACE_URLS;histograms.addSharedDiagnosticToAllHistograms(info.name,new info.type([model.canonicalUrl]));}
@@ -10291,7 +10135,7 @@
 if(names.includes(this.viewState.displayStatisticName)){this.displayStatisticName=this.viewState.displayStatisticName;this.$.statistic.value=this.displayStatisticName;}else{this.viewState.displayStatisticName=names[0]||'';}},get anyOverviewCharts_(){for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){if(row.isOverviewed)return true;}
 return false;},async toggleOverviewLineCharts_(){const showOverviews=!this.anyOverviewCharts_;const mark=tr.b.Timing.mark('histogram-set-controls',(showOverviews?'show':'hide')+'OverviewCharts');for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){await row.update({isOverviewed:showOverviews});}
 this.$.hide_overview.style.display=showOverviews?'inline':'none';this.$.show_overview.style.display=showOverviews?'none':'inline';await tr.b.animationFrame();mark.end();},set helpHref(href){this.$.help.href=href;this.$.help.style.display='inline';},set feedbackHref(href){this.$.feedback.href=href;this.$.feedback.style.display='inline';},clearSearch_(){this.set('searchQuery','');this.$.search.focus();},getAlphaString_(alphaIndex){return(''+ALPHA_OPTIONS[alphaIndex]).substr(0,5);},openAlphaSlider_(){const alphaButtonRect=this.$.alpha.getBoundingClientRect();this.$.alpha_slider_container.style.display='flex';this.$.alpha_slider_container.style.top=alphaButtonRect.bottom+'px';this.$.alpha_slider_container.style.left=alphaButtonRect.left+'px';this.$.alpha_slider.focus();},closeAlphaSlider_(){this.$.alpha_slider_container.style.display='';},updateAlpha_(){this.alphaIndex=this.$.alpha_slider.value;},getAlphaIndexFromViewState_(){for(let i=0;i<ALPHA_OPTIONS.length;++i){if(ALPHA_OPTIONS[i]>=this.viewState.alpha)return i;}
-return ALPHA_OPTIONS.length-1;},set enableVisualization(enable){this.$.show_visualization.style.display=enable?'inline':'none';},loadVisualization_(){tr.b.dispatchSimpleEvent(this,'loadVisualization',true,true,{});},});return{};});'use strict';tr.exportTo('tr.v',function(){class HistogramSetHierarchy{constructor(name){this.name=name;this.description='';this.depth=0;this.subRows=[];this.columns=new Map();}*walk(){yield this;for(const row of this.subRows)yield*row.walk();}
+return ALPHA_OPTIONS.length-1;},});return{};});'use strict';tr.exportTo('tr.v',function(){class HistogramSetHierarchy{constructor(name){this.name=name;this.description='';this.depth=0;this.subRows=[];this.columns=new Map();}*walk(){yield this;for(const row of this.subRows)yield*row.walk();}
 static*walkAll(rootRows){for(const rootRow of rootRows)yield*rootRow.walk();}
 static build(histogramArrayMap){const rootRows=[];HistogramSetHierarchy.buildInternal_(histogramArrayMap,[],rootRows);const histograms=new tr.v.HistogramSet();for(const row of HistogramSetHierarchy.walkAll(rootRows)){for(const hist of row.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;histograms.addHistogram(hist);}}
 histograms.deduplicateDiagnostics();for(const row of HistogramSetHierarchy.walkAll(rootRows)){row.maybeRebin_();}
@@ -10387,48 +10231,11 @@
 return;}
 await this.updateContents_();},onSortColumnChanged_(event){tr.b.Timing.instant('histogram-set-table','sortColumn');this.viewState.update({sortColumnIndex:event.sortColumnIndex,sortDescending:event.sortDescending,});},onRequestSelectionChange_(event){if(event.selection instanceof tr.model.EventSet)return;event.stopPropagation();tr.b.Timing.instant('histogram-set-table','selectHistogramNames');let histogramNames=event.selection;histogramNames.sort();histogramNames=histogramNames.map(escapeRegExp).join('|');this.viewState.update({showAll:true,searchQuery:`^(${histogramNames})$`,});},get leafHistograms(){const histograms=new tr.v.HistogramSet();for(const row of
 tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows)){if(row.subRows.length)continue;for(const hist of row.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;histograms.addHistogram(hist);}}
-return histograms;}});return{MIDLINE_HORIZONTAL_ELLIPSIS,};});'use strict';tr.exportTo('tr.v.ui',function(){const PAGE_BREAKDOWN_KEY='pageBreakdown';Polymer({is:'tr-v-ui-metrics-visualization',created(){this.charts_=new Map();},ready(){this.$.start.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_();});this.$.end.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_();});this.$.search_page.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_();});},build(chartData){this.title_=chartData.title;this.aggregateData_=chartData.aggregate;this.data_=chartData.page;this.submetricsData_=chartData.submetrics;this.benchmarkCount_=chartData.aggregate.length;const aggregateChart=this.initializeColumnChart(this.title_);Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);this.charts_.set(tr.v.ui.AGGREGATE_KEY,aggregateChart);this.setChartColors_(tr.v.ui.AGGREGATE_KEY);aggregateChart.data=chartData.aggregate;this.setChartSize_(tr.v.ui.AGGREGATE_KEY);const newChart=this.initializeColumnChart(this.title_+' Breakdown');newChart.enableToolTip=true;newChart.toolTipCallBack=(rect)=>this.openChildChart_(rect);Polymer.dom(this.$.pageByPageContainer).appendChild(newChart);this.charts_.set(PAGE_BREAKDOWN_KEY,newChart);this.setChartColors_(PAGE_BREAKDOWN_KEY);newChart.data=this.data_;this.setChartSize_(PAGE_BREAKDOWN_KEY);},setChartSize_(page){const chart=this.charts_.get(page);const pageCount=chart.data.length;chart.graphHeight=tr.b.math.clamp(pageCount*20,400,600);chart.graphWidth=tr.b.math.clamp(pageCount*30,200,1000);},setChartColors_(page){const chart=this.charts_.get(page);const metrics=tr.v.ui.METRICS.get(this.title_);for(let i=0;i<this.benchmarkCount_;++i){for(let j=0;j<metrics.length;++j){const mainColorIndex=j%tr.v.ui.COLORS.length;const subColorIndex=i%tr.v.ui.COLORS[mainColorIndex].length;const color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];const series=metrics[j]+'-'+this.aggregateData_[i].x;chart.getDataSeries(series).color=color;if(i===0){chart.getDataSeries(series).title=metrics[j];}else{chart.getDataSeries(series).title='';}}}},initializeColumnChart(title){const newChart=new tr.ui.b.NameColumnChart();newChart.hideLegend=false;newChart.isStacked=true;newChart.yAxisLabel='ms';newChart.hideXAxis=true;newChart.displayXInHover=true;newChart.isGrouped=true;newChart.showTitleInLegend=true;newChart.chartTitle=title;newChart.titleHeight='14pt';return newChart;},initializeChildChart_(title,height,width){const div=document.createElement('div');div.classList.add('container');Polymer.dom(this.$.submetricsContainer).insertBefore(div,this.$.submetricsContainer.firstChild);const childChart=new tr.ui.b.NameBarChart();childChart.xAxisLabel='ms';childChart.chartTitle=title;childChart.graphHeight=height;childChart.graphWidth=width;childChart.titleHeight='14pt';childChart.isStacked=true;childChart.hideLegend=true;childChart.isGrouped=true;childChart.isWaterfall=true;div.appendChild(childChart);const button=this.initializeCloseButton_(div,this.$.submetricsContainer);div.appendChild(button);return childChart;},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},openChildChart_(rect){const metrics=tr.v.ui.METRICS.get(this.title_);let metric;let metricIndex;for(let i=0;i<metrics.length;++i){if(rect.key.startsWith(metrics[i])){metric=metrics[i];metricIndex=i;break;}}
-const page=rect.datum.group;const title=this.title_+' '+metric+': '+page;const submetrics=this.submetricsData_.get(page).get(metric);const width=tr.b.math.clamp(submetrics.size*150,300,700);const height=tr.b.math.clamp(submetrics.size*this.benchmarkCount_*50,300,700);const childChart=this.initializeChildChart_(title,height,width);childChart.data=this.processSubmetrics_(childChart,submetrics,0,metricIndex).data;},processSubmetrics_(chart,submetrics,hideValue,metricIndex){const finalData=[];let submetricIndex=0;for(const submetric of submetrics.values()){let benchmarkIndex=0;for(const benchmark of submetric.values()){benchmark.hide=!hideValue?0:hideValue;const series=benchmark.x+'-'+benchmark.group;const mainColorIndex=metricIndex%tr.v.ui.COLORS.length;const subColorIndex=benchmarkIndex%tr.v.ui.COLORS[mainColorIndex].length;chart.getDataSeries(series).color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];if(benchmarkIndex===(this.benchmarkCount_-1)){hideValue+=benchmark[series];}
-finalData.push(benchmark);benchmarkIndex++;}
-submetricIndex++;}
-return{data:finalData,hide:hideValue};},filterByPercentile_(){const startPercentile=this.$.start.value;const endPercentile=this.$.end.value;if(startPercentile===''||endPercentile==='')return;const length=this.data_.length/(this.benchmarkCount_+1);const startIndex=this.getPercentileIndex_(startPercentile,length);const endIndex=this.getPercentileIndex_(endPercentile,length);this.charts_.get(PAGE_BREAKDOWN_KEY).data=this.data_.slice(startIndex,endIndex);},getPercentileIndex_(percentile,arrayLength){const index=Math.ceil(arrayLength*(percentile/100.0));if(index===-1)return 0;if(index>=arrayLength)return arrayLength;return index*this.benchmarkCount_;},searchByPage_(){const criteria=this.$.search_page.value;if(criteria==='')return;const query=new RegExp(criteria);const filteredData=[...this.data_].filter(group=>{if(group.group)return group.group.match(query);return false;});if(filteredData.length<1){this.$.search_error.style.display='block';return;}
-const page=filteredData[0].group;const title=this.title_+' Breakdown: '+page;const metricToSubmetricMap=this.submetricsData_.get(page);let totalSubmetrics=0;for(const submetrics of metricToSubmetricMap.values()){for(const benchmark of submetrics.values()){totalSubmetrics+=benchmark.length;}}
-const width=tr.b.math.clamp(totalSubmetrics*150,300,700);const height=tr.b.math.clamp(totalSubmetrics*this.benchmarkCount_*30,300,700);const childChart=this.initializeChildChart_(title,height,width);const childData=[];let hide=0;let metricIndex=0;for(const submetrics of metricToSubmetricMap.values()){const submetricsData=this.processSubmetrics_(childChart,submetrics,hide,metricIndex);childData.push(...submetricsData.data);hide=submetricsData.hide;metricIndex++;}
-childChart.data=childData;},});});'use strict';Polymer({is:'tr-v-ui-raster-visualization',ready(){this.$.pageSelector.addEventListener('click',()=>{this.selectPage_();});this.$.search_page.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_();});this.$.search_button.addEventListener('click',()=>{this.searchByPage_();});},build(chartData){this.data_=chartData;const aggregateChart=this.createChart_('Aggregate Data by Run');Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);aggregateChart.enableToolTip=true;aggregateChart.toolTipCallBack=(rect)=>this.openBenchmarkChart_(rect);this.setChartColors_(aggregateChart,this.data_.get(tr.v.ui.AGGREGATE_KEY));aggregateChart.data=this.data_.get(tr.v.ui.AGGREGATE_KEY);this.setChartSize_(aggregateChart,this.data_.get(tr.v.ui.AGGREGATE_KEY).length);for(const page of this.data_.keys()){if(page===tr.v.ui.AGGREGATE_KEY)continue;const option=document.createElement('option');option.textContent=page;option.value=page;this.$.pageSelector.appendChild(option);}},setChartSize_(chart,pageCount,dataLength){chart.graphHeight=tr.b.math.clamp(pageCount*25,175,1000);chart.graphWidth=tr.b.math.clamp(pageCount*25,500,1000);},setChartColors_(chart,data){const metrics=new Map();let count=0;for(const thread of tr.v.ui.FRAME.values()){for(const metric of thread.keys()){metrics.set(metric,count);count++;}}
-for(let i=0;i<Math.floor(data.length/tr.v.ui.FRAME.length);++i){let j=0;for(const[threadName,thread]of tr.v.ui.FRAME.entries()){for(const metric of thread.keys()){let color='transparent';if(thread.get(metric)){const mainColorIndex=metrics.get(metric)%tr.v.ui.COLORS.length;const subColorIndex=i%tr.v.ui.COLORS[mainColorIndex].length;color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];}
-const series=metric+'-'+data[i*2+j].x+'-'+threadName;chart.getDataSeries(series).color=color;chart.getDataSeries(series).title=!i?metric:'';}
-j++;}}},createChart_(title){const newChart=new tr.ui.b.NameBarChart();newChart.chartTitle=title;newChart.xAxisLabel='ms';newChart.hideLegend=false;newChart.showTitleInLegend=true;newChart.hideYAxis=true;newChart.isStacked=true;newChart.displayXInHover=true;newChart.isGrouped=true;return newChart;},openBenchmarkChart_(rect){const benchmarkIndex=Math.floor(rect.index/tr.v.ui.FRAME.length);const title=rect.datum.x;const div=document.createElement('div');Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const chart=this.createChart_(title);div.appendChild(chart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const newDataSet=[];for(const page of this.data_.keys()){if(page===tr.v.ui.AGGREGATE_KEY)continue;for(let i=0;i<tr.v.ui.FRAME.length;i++){newDataSet.push(this.data_.get(page)[benchmarkIndex*tr.v.ui.FRAME.length+i]);}}
-this.setChartColors_(chart,newDataSet);chart.data=newDataSet;this.setChartSize_(chart,newDataSet.length);},selectPage_(){const div=document.createElement('div');const page=this.$.pageSelector.value;if(page==='')return;Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const pageChart=this.createChart_(page);div.appendChild(pageChart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const pageData=this.data_.get(page);this.setChartColors_(pageChart,pageData);pageChart.data=pageData;this.setChartSize_(pageChart,pageData.length);},searchByPage_(){const criteria=this.$.search_page.value;if(criteria==='')return;const query=new RegExp(criteria);const filteredData=[...this.data_.keys()].filter(page=>page.match(query));if(filteredData.length<1){this.$.search_error.style.display='block';return;}
-const page=filteredData[0];const div=document.createElement('div');Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const pageChart=this.createChart_(page);div.appendChild(pageChart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const pageData=this.data_.get(page);this.setChartColors_(pageChart,pageData);pageChart.data=pageData;this.setChartSize_(pageChart,pageData.length);},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},});'use strict';tr.exportTo('tr.v.ui',function(){const STATISTICS_KEY='statistics';const SUBMETRICS_KEY='submetrics';const AGGREGATE_KEY='aggregate';const RASTER_START_METRIC_KEY='pipeline:begin_frame_to_raster_start';const COLORS=[['#FFD740','#FFC400','#FFAB00','#E29800'],['#FF6E40','#FF3D00','#DD2C00','#A32000'],['#40C4FF','#00B0FF','#0091EA','#006DAF'],['#89C641','#54B503','#4AA510','#377A0D'],['#B388FF','#7C4DFF','#651FFF','#6200EA'],['#FF80AB','#FF4081','#F50057','#C51162'],['#FFAB40','#FF9100','#FF6D00','#D65C02'],['#8C9EFF','#536DFE','#3D5AFE','#304FFE']];const FRAME=[new Map([['pipeline:begin_frame_to_raster_start',false],['pipeline:begin_frame_to_raster_end',true]]),new Map([['pipeline:begin_frame_transport',true],['pipeline:begin_frame_to_frame_submission',true],['pipeline:frame_submission_to_display',true],['pipeline:draw',true]])];const METRICS=new Map([['Pipeline',['pipeline:begin_frame_transport','pipeline:begin_frame_to_frame_submission','pipeline:frame_submission_to_display','pipeline:draw']],['Thread',['thread_browser_cpu_time_per_frame','thread_display_compositor_cpu_time_per_frame','thread_GPU_cpu_time_per_frame','thread_IO_cpu_time_per_frame','thread_other_cpu_time_per_frame','thread_raster_cpu_time_per_frame','thread_renderer_compositor_cpu_time_per_frame','thread_renderer_main_cpu_time_per_frame']]]);function getValueFromMap(key,map){let retrievedValue=map.get(key);if(!retrievedValue){retrievedValue=new Map();map.set(key,retrievedValue);}
-return retrievedValue;}
-Polymer({is:'tr-v-ui-visualizations-data-container',created(){this.orderedBenchmarks_=[];this.groupedData_=new Map();},build(leafHistograms,histograms){if(!leafHistograms||leafHistograms.length<1||!histograms||histograms.length<1){this.$.data_error.style.display='block';return;}
-this.processHistograms_(this.groupHistograms_(histograms),this.groupHistograms_(leafHistograms));this.buildCharts_();},processHistograms_(histograms,leafHistograms){const benchmarkStartGrouping=tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START);const benchmarkToStartTime=new Map();for(const[metric,benchmarks]of histograms.entries()){for(const[benchmark,pages]of leafHistograms.get(metric).entries()){for(const[page,histograms]of pages.entries()){for(const histogram of histograms){const aggregateToBenchmarkMap=getValueFromMap(AGGREGATE_KEY,this.groupedData_);const benchmarkToMetricMap=getValueFromMap(benchmark,aggregateToBenchmarkMap);benchmarkToMetricMap.set(metric,new Map([[STATISTICS_KEY,histogram.running]]));}}}
-for(const[benchmark,pages]of benchmarks.entries()){for(const[page,histograms]of pages.entries()){for(const histogram of histograms){if(!benchmarkToStartTime.get(benchmark)){benchmarkToStartTime.set(benchmark,benchmarkStartGrouping.callback(histogram));}
-const pageToBenchmarkMap=getValueFromMap(page,this.groupedData_);const benchmarkToMetricMap=getValueFromMap(benchmark,pageToBenchmarkMap);const mergedSubmetrics=new tr.v.d.DiagnosticMap();for(const bin of histogram.allBins){for(const map of bin.diagnosticMaps){mergedSubmetrics.addDiagnostics(map);}}
-if(benchmarkToMetricMap.get(metric))continue;benchmarkToMetricMap.set(metric,new Map([[STATISTICS_KEY,histogram.running],[SUBMETRICS_KEY,mergedSubmetrics.get('breakdown')]]));}}}}
-this.orderedBenchmarks_=this.sortBenchmarks_(benchmarkToStartTime);},groupHistograms_(histograms){const groupings=[tr.v.HistogramGrouping.HISTOGRAM_NAME,tr.v.HistogramGrouping.DISPLAY_LABEL,tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES)];return histograms.groupHistogramsRecursively(groupings);},sortBenchmarks_(benchmarks){return Array.from(benchmarks.keys()).sort((a,b)=>{Date.parse(benchmarks.get(a))-Date.parse(benchmarks.get(b));});},getSeriesKey_(metric,benchmark){return metric+'-'+benchmark;},buildCharts_(){const rasterDataToBePassed=this.buildRasterChart_();this.$.rasterVisualization.build(rasterDataToBePassed);for(const chartName of METRICS.keys()){const metricsDataToBePassed=this.buildMetricsData_(chartName);const newChart=this.$.metricsVisualization.cloneNode(true);newChart.style.display='block';Polymer.dom(this.$.metrics_container).appendChild(newChart);newChart.build(metricsDataToBePassed);}},buildRasterChart_(){const orderedPages=[...this.groupedData_.keys()].filter((page)=>this.filterPagesWithoutRasterMetric_(page)).sort((a,b)=>this.sortByRasterStart_(a,b));const allChartData=new Map();for(const page of orderedPages){const pageMap=this.groupedData_.get(page);let chartData=[];for(const benchmark of this.orderedBenchmarks_){if(!pageMap.has(benchmark))continue;const benchmarkMap=pageMap.get(benchmark);const benchmarkData=[];if(benchmarkMap.get(RASTER_START_METRIC_KEY)===undefined){continue;}
-for(const[threadName,thread]of FRAME.entries()){const data={x:benchmark,hide:0};if(page!==AGGREGATE_KEY)data.group=page;let rasterBegin=0;for(const metric of thread.keys()){const metricMap=benchmarkMap.get(metric);const key=this.getSeriesKey_(metric,data.x+'-'+threadName);const stats=metricMap.get(STATISTICS_KEY);const mean=stats?stats.mean:0;let roundedMean=Math.round(mean*100)/100;if(metric===RASTER_START_METRIC_KEY){rasterBegin=roundedMean;}else if(metric==='pipeline:begin_frame_to_raster_end'){roundedMean-=rasterBegin;}
-data[key]=roundedMean;}
-benchmarkData.push(data);}
-chartData=chartData.concat(benchmarkData);}
-allChartData.set(page,chartData);}
-return allChartData;},buildMetricsData_(chartName){const orderedPages=[...this.groupedData_.keys()].sort((a,b)=>this.sortByTotal_(a,b,chartName));const chartData=[];const aggregateChart=[];for(const page of orderedPages){const pageMap=this.groupedData_.get(page);for(const benchmark of this.orderedBenchmarks_){if(!pageMap.has(benchmark))continue;const data={x:benchmark,group:page};const benchmarkMap=pageMap.get(benchmark);for(const metric of METRICS.get(chartName)){const metricMap=benchmarkMap.get(metric);const key=this.getSeriesKey_(metric,benchmark);const stats=metricMap.get(STATISTICS_KEY);const mean=stats?stats.mean:0;data[key]=Math.round(mean*100)/100;}
-if(page===AGGREGATE_KEY){aggregateChart.push(data);}else{chartData.push(data);}}
-chartData.push({});}
-chartData.shift();return{title:chartName,aggregate:aggregateChart,page:chartData,submetrics:this.processSubmetricsData_(chartName)};},submetricsHelper_(submetric,value,benchmark,metricToSubmetricMap){let submetricToBenchmarkMap=metricToSubmetricMap.get(submetric);if(!submetricToBenchmarkMap){submetricToBenchmarkMap=[];metricToSubmetricMap.set(submetric,submetricToBenchmarkMap);}
-const data={x:submetric,hide:0,group:benchmark};const mean=value;const roundedMean=Math.round(mean*100)/100;if(!roundedMean)return;data[this.getSeriesKey_(submetric,benchmark)]=roundedMean;submetricToBenchmarkMap.push(data);},processSubmetricsData_(chartName){const submetrics=new Map();for(const[page,pageMap]of this.groupedData_.entries()){if(page===AGGREGATE_KEY)continue;const pageToMetricMap=getValueFromMap(page,submetrics);for(const benchmark of this.orderedBenchmarks_){const benchmarkMap=pageMap.get(benchmark);if(!benchmarkMap)continue;for(const metric of METRICS.get(chartName)){const metricMap=benchmarkMap.get(metric);const metricToSubmetricMap=getValueFromMap(metric,pageToMetricMap);const submetrics=metricMap.get(SUBMETRICS_KEY);if(!submetrics){this.submetricsHelper_(metric,metricMap.get(STATISTICS_KEY),benchmark,metricToSubmetricMap);continue;}
-for(const[submetric,value]of[...submetrics]){this.submetricsHelper_(submetric,value,benchmark,metricToSubmetricMap);}}}}
-return submetrics;},sortByTotal_(a,b,chartName){if(a===AGGREGATE_KEY)return-1;if(b===AGGREGATE_KEY)return 1;let aValue=0;const aMap=this.groupedData_.get(a);if(aMap.get(this.orderedBenchmarks_[0])!==undefined){for(const metric of METRICS.get(chartName)){const aMetricMap=aMap.get(this.orderedBenchmarks_[0]).get(metric);const aStats=aMetricMap.get(STATISTICS_KEY);aValue+=aStats?aStats.mean:0;}}
-let bValue=0;const bMap=this.groupedData_.get(b);if(bMap.get(this.orderedBenchmarks_[0])!==undefined){for(const metric of METRICS.get(chartName)){const bMetricMap=bMap.get(this.orderedBenchmarks_[0]).get(metric);const bStats=bMetricMap.get(STATISTICS_KEY);bValue+=bStats?bStats.mean:0;}}
-return aValue-bValue;},filterPagesWithoutRasterMetric_(page){const pageMap=this.groupedData_.get(page);for(const benchmark of this.orderedBenchmarks_){const pageMetricMap=pageMap.get(benchmark);if(!pageMetricMap)continue;const wantedMetric=pageMetricMap.get(RASTER_START_METRIC_KEY);if(wantedMetric!==undefined)return true;}
-return false;},sortByRasterStart_(a,b){if(a===AGGREGATE_KEY)return 1;if(b===AGGREGATE_KEY)return-1;let aValue=0;const aMap=this.groupedData_.get(a);if(aMap.get(this.orderedBenchmarks_[0])!==undefined){const aMetricMap=aMap.get(this.orderedBenchmarks_[0]).get(RASTER_START_METRIC_KEY);const aStats=aMetricMap.get(STATISTICS_KEY);aValue=aStats?aStats.mean:0;}
-let bValue=0;const bMap=this.groupedData_.get(b);if(bMap.get(this.orderedBenchmarks_[0])!==undefined){const bMetricMap=bMap.get(this.orderedBenchmarks_[0]).get(RASTER_START_METRIC_KEY);const bStats=bMetricMap.get(STATISTICS_KEY);bValue=bStats?bStats.mean:0;}
-return bValue-aValue;},});return{STATISTICS_KEY,SUBMETRICS_KEY,AGGREGATE_KEY,COLORS,FRAME,METRICS,getValueFromMap,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-view',listeners:{export:'onExport_',loadVisualization:'onLoadVisualization_'},created(){this.brushingStateController_=new tr.ui.NullBrushingStateController();this.viewState_=new tr.v.ui.HistogramSetViewState();this.visualizationLoaded_=false;},ready(){this.$.table.viewState=this.viewState;this.$.controls.viewState=this.viewState;},attached(){this.brushingStateController.parentController=tr.c.BrushingStateController.getControllerForElement(this.parentNode);},get brushingStateController(){return this.brushingStateController_;},get viewState(){return this.viewState_;},get histograms(){return this.$.table.histograms;},async build(histograms,opt_options){const options=opt_options||{};const progress=options.progress||(()=>Promise.resolve());if(options.helpHref)this.$.controls.helpHref=options.helpHref;if(options.feedbackHref){this.$.controls.feedbackHref=options.feedbackHref;}
+return histograms;}});return{MIDLINE_HORIZONTAL_ELLIPSIS,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-view',listeners:{export:'onExport_',},created(){this.brushingStateController_=new tr.ui.NullBrushingStateController();this.viewState_=new tr.v.ui.HistogramSetViewState();},ready(){this.$.table.viewState=this.viewState;this.$.controls.viewState=this.viewState;},attached(){this.brushingStateController.parentController=tr.c.BrushingStateController.getControllerForElement(this.parentNode);},get brushingStateController(){return this.brushingStateController_;},get viewState(){return this.viewState_;},get histograms(){return this.$.table.histograms;},async build(histograms,opt_options){const options=opt_options||{};const progress=options.progress||(()=>Promise.resolve());if(options.helpHref)this.$.controls.helpHref=options.helpHref;if(options.feedbackHref){this.$.controls.feedbackHref=options.feedbackHref;}
 if(histograms===undefined||histograms.length===0){this.$.container.style.display='none';this.$.zero.style.display='block';this.style.display='block';return;}
-this.$.zero.style.display='none';this.$.container.style.display='block';this.$.container.style.maxHeight=(window.innerHeight-16)+'px';const buildMark=tr.b.Timing.mark('histogram-set-view','build');await progress('Finding important Histograms...');const sourceHistogramsMark=tr.b.Timing.mark('histogram-set-view','sourceHistograms');const sourceHistograms=histograms.sourceHistograms;sourceHistogramsMark.end();this.$.controls.showAllEnabled=(sourceHistograms.length!==histograms.length);await progress('Collecting parameters...');const collectParametersMark=tr.b.Timing.mark('histogram-set-view','collectParameters');const parameterCollector=new tr.v.HistogramParameterCollector();parameterCollector.process(histograms);this.$.controls.baseStatisticNames=parameterCollector.statisticNames;this.$.controls.possibleGroupings=parameterCollector.possibleGroupings;const displayLabels=parameterCollector.labels;this.$.controls.displayLabels=displayLabels;collectParametersMark.end();const hist=[...histograms][0];const benchmarks=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARKS);let enable=false;if(benchmarks!==undefined&&benchmarks.length>0){for(const benchmark of benchmarks){if(benchmark.includes('rendering')){enable=true;break;}}}
-this.$.controls.enableVisualization=enable;await this.$.table.build(histograms,sourceHistograms,displayLabels,progress);buildMark.end();},onExport_(event){const mark=tr.b.Timing.mark('histogram-set-view','export'+
+this.$.zero.style.display='none';this.$.container.style.display='block';this.$.container.style.maxHeight=(window.innerHeight-16)+'px';const buildMark=tr.b.Timing.mark('histogram-set-view','build');await progress('Finding important Histograms...');const sourceHistogramsMark=tr.b.Timing.mark('histogram-set-view','sourceHistograms');const sourceHistograms=histograms.sourceHistograms;sourceHistogramsMark.end();this.$.controls.showAllEnabled=(sourceHistograms.length!==histograms.length);await progress('Collecting parameters...');const collectParametersMark=tr.b.Timing.mark('histogram-set-view','collectParameters');const parameterCollector=new tr.v.HistogramParameterCollector();parameterCollector.process(histograms);this.$.controls.baseStatisticNames=parameterCollector.statisticNames;this.$.controls.possibleGroupings=parameterCollector.possibleGroupings;const displayLabels=parameterCollector.labels;this.$.controls.displayLabels=displayLabels;collectParametersMark.end();await this.$.table.build(histograms,sourceHistograms,displayLabels,progress);buildMark.end();},onExport_(event){const mark=tr.b.Timing.mark('histogram-set-view','export'+
 (event.merged?'Merged':'Raw')+event.format.toUpperCase());const histograms=event.merged?this.$.table.leafHistograms:this.histograms;let blob;if(event.format==='csv'){const csv=new tr.v.CSVBuilder(histograms);csv.build();blob=new window.Blob([csv.toString()],{type:'text/csv'});}else if(event.format==='json'){blob=new window.Blob([JSON.stringify(histograms.asDicts())],{type:'text/json'});}else{throw new Error(`Unable to export format "${event.format}"`);}
-const path=window.location.pathname.split('/');const basename=path[path.length-1].split('.')[0]||'histograms';const anchor=document.createElement('a');anchor.download=`${basename}.${event.format}`;anchor.href=window.URL.createObjectURL(blob);anchor.click();mark.end();},onLoadVisualization_(event){if(!this.visualizationLoaded_){this.$.visualizations.style.display='block';this.$.visualizations.build(this.$.table.leafHistograms,this.histograms);this.visualizationLoaded_=true;}else if(this.$.visualizations.style.display==='none'){this.$.visualizations.style.display='block';}else{this.$.visualizations.style.display='none';}},});return{};});'use strict';tr.exportTo('tr.ui',function(){Polymer({is:'tr-ui-sp-metrics-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.rangeOfInterest_=undefined;this.metricLatenciesMs_=[];this.metrics_=[];tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(function(m){if(m.constructor.name==='sampleMetric')return;this.metrics_.push({label:m.constructor.name,value:m.constructor.name});},this);this.metrics_.sort((x,y)=>x.label.localeCompare(y.label));this.settingsKey_='metrics-side-panel-metric-name';this.currentMetricName_='responsivenessMetric';const metricSelector=tr.ui.b.createSelector(this,'currentMetricName_',this.settingsKey_,this.currentMetricName_,this.metrics_);Polymer.dom(this.$.top_left_controls).appendChild(metricSelector);metricSelector.addEventListener('change',this.onMetricChange_.bind(this));this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.recomputeButton_=tr.ui.b.createButton('Recompute',this.onRecompute_,this);Polymer.dom(this.$.top_left_controls).appendChild(this.recomputeButton_);this.$.results.addEventListener('display-ready',()=>{this.$.results.style.display='';});},async build(model){this.model_=model;await this.updateContents_();},get metricLatencyMs(){return tr.b.math.Statistics.mean(this.metricLatenciesMs_);},onMetricChange_(){this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.metricLatenciesMs_=[];this.updateContents_();},onRecompute_(){this.updateContents_();},get textLabel(){return'Metrics';},supportsModel(m){if(!m){return{supported:false,reason:'No model available'};}
+const path=window.location.pathname.split('/');const basename=path[path.length-1].split('.')[0]||'histograms';const anchor=document.createElement('a');anchor.download=`${basename}.${event.format}`;anchor.href=window.URL.createObjectURL(blob);anchor.click();mark.end();},});return{};});'use strict';tr.exportTo('tr.ui',function(){Polymer({is:'tr-ui-sp-metrics-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.rangeOfInterest_=undefined;this.metricLatenciesMs_=[];this.metrics_=[];tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(function(m){if(m.constructor.name==='sampleMetric')return;this.metrics_.push({label:m.constructor.name,value:m.constructor.name});},this);this.metrics_.sort((x,y)=>x.label.localeCompare(y.label));this.settingsKey_='metrics-side-panel-metric-name';this.currentMetricName_='responsivenessMetric';const metricSelector=tr.ui.b.createSelector(this,'currentMetricName_',this.settingsKey_,this.currentMetricName_,this.metrics_);Polymer.dom(this.$.top_left_controls).appendChild(metricSelector);metricSelector.addEventListener('change',this.onMetricChange_.bind(this));this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.recomputeButton_=tr.ui.b.createButton('Recompute',this.onRecompute_,this);Polymer.dom(this.$.top_left_controls).appendChild(this.recomputeButton_);this.$.results.addEventListener('display-ready',()=>{this.$.results.style.display='';});},async build(model){this.model_=model;await this.updateContents_();},get metricLatencyMs(){return tr.b.math.Statistics.mean(this.metricLatenciesMs_);},onMetricChange_(){this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.metricLatenciesMs_=[];this.updateContents_();},onRecompute_(){this.updateContents_();},get textLabel(){return'Metrics';},supportsModel(m){if(!m){return{supported:false,reason:'No model available'};}
 return{supported:true};},get model(){return this.model_;},set model(model){this.build(model);},get selection(){},set selection(_){},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){this.rangeOfInterest_=range;if(this.currentMetricTypeInfo_&&this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest){if((this.metricLatencyMs===undefined)||(this.metricLatencyMs<100)){this.updateContents_();}else{this.recomputeButton_.style.background='red';}}},async updateContents_(){Polymer.dom(this.$.error).textContent='';this.$.results.style.display='none';if(!this.model_){Polymer.dom(this.$.error).textContent='Missing model';return;}
 const options={metrics:[this.currentMetricName_]};if(this.currentMetricTypeInfo_&&this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest&&this.rangeOfInterest&&!this.rangeOfInterest.isEmpty){options.rangeOfInterest=this.rangeOfInterest;}
 const startDate=new Date();const addFailureCb=failure=>{Polymer.dom(this.$.error).textContent=failure.description;};const histograms=tr.metrics.runMetrics(this.model_,options,addFailureCb);this.metricLatenciesMs_.push(new Date()-startDate);while(this.metricLatenciesMs_.length>20){this.metricLatenciesMs_.shift();}
diff --git a/runtime/platform/assert.h b/runtime/platform/assert.h
index c31c1cc..64351b6 100644
--- a/runtime/platform/assert.h
+++ b/runtime/platform/assert.h
@@ -140,7 +140,12 @@
 
 inline void Expect::StringEquals(const char* expected, const char* actual) {
   if (strcmp(expected, actual) == 0) return;
-  Fail("expected:\n<\"%s\">\nbut was:\n<\"%s\">", expected, actual);
+  if (actual == nullptr) {
+    Fail("expected:\n<\"%s\">\nbut was nullptr", expected);
+  } else {
+    if (strcmp(expected, actual) == 0) return;
+    Fail("expected:\n<\"%s\">\nbut was:\n<\"%s\">", expected, actual);
+  }
 }
 
 inline void Expect::IsSubstring(const char* needle, const char* haystack) {
diff --git a/runtime/platform/priority_queue.h b/runtime/platform/priority_queue.h
new file mode 100644
index 0000000..2064fcc
--- /dev/null
+++ b/runtime/platform/priority_queue.h
@@ -0,0 +1,269 @@
+// 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.
+
+#ifndef RUNTIME_PLATFORM_PRIORITY_QUEUE_H_
+#define RUNTIME_PLATFORM_PRIORITY_QUEUE_H_
+
+#include "platform/assert.h"
+#include "platform/globals.h"
+#include "platform/hashmap.h"
+#include "platform/utils.h"
+
+namespace dart {
+
+// A min-priority queue with deletion support.
+//
+// The [PriorityQueue] allows insertion of entries with a priority [P] and a
+// value [V]. The minimum element can be queried in O(1) time.
+// Insertion/Deletion operations have O(N) time.
+//
+// In addition to the normal insert/minimum/remove-minimum operations this
+// priority queue allows deletion-by-value. We have therefore an invariant
+// is that the value must be unique amongst all entries.
+template <typename P, typename V>
+class PriorityQueue {
+ public:
+  static const intptr_t kMinimumSize = 16;
+
+  struct Entry {
+    P priority;
+    V value;
+  };
+
+  PriorityQueue() : hashmap_(&MatchFun, kMinimumSize) {
+    min_heap_size_ = kMinimumSize;
+    min_heap_ =
+        reinterpret_cast<Entry*>(malloc(sizeof(Entry) * min_heap_size_));
+    if (min_heap_ == nullptr) FATAL("Cannot allocate memory.");
+    size_ = 0;
+  }
+
+  ~PriorityQueue() { free(min_heap_); }
+
+  // Whether the queue is empty.
+  bool IsEmpty() const { return size_ == 0; }
+
+  // Inserts a new entry with [priority] and [value], requires there to be no
+  // existing entry with given [value].
+  void Insert(const P& priority, const V& value) {
+    ASSERT(!ContainsValue(value));
+
+    if (size_ == min_heap_size_) {
+      Resize(min_heap_size_ << 1);
+    }
+
+    Set(size_, {priority, value});
+    BubbleUp(size_);
+
+    size_++;
+  }
+
+  // Returns a reference to the minimum entry.
+  //
+  // The caller can access it's priority and value in read-only mode only.
+  const Entry& Minimum() const {
+    ASSERT(!IsEmpty());
+    return min_heap_[0];
+  }
+
+  // Removes the minimum entry.
+  void RemoveMinimum() {
+    ASSERT(!IsEmpty());
+    RemoveAt(0);
+  }
+
+  // Removes an existing entry with the given [value].
+  //
+  // Returns true if such an entry was removed.
+  bool RemoveByValue(const V& value) {
+    auto entry = FindMapEntry(value);
+    if (entry != nullptr) {
+      const intptr_t offset = ValueOfMapEntry(entry);
+      RemoveAt(offset);
+
+      ASSERT(hashmap_.size() == size_);
+      return true;
+    }
+    return false;
+  }
+
+  // Whether the priority queue contains an entry with the given [value].
+  bool ContainsValue(const V& value) { return FindMapEntry(value) != nullptr; }
+
+  // Changes the priority of an existing entry with given [value] or adds a
+  // new entry.
+  bool InsertOrChangePriority(const P& priority, const V& value) {
+    auto map_entry = FindMapEntry(value);
+    if (map_entry == nullptr) {
+      Insert(priority, value);
+      return true;
+    }
+
+    const intptr_t offset = ValueOfMapEntry(map_entry);
+    ASSERT(offset < size_);
+
+    Entry& entry = min_heap_[offset];
+    entry.priority = priority;
+    if (offset == 0) {
+      BubbleDown(offset);
+    } else {
+      intptr_t parent = (offset - 1) / 2;
+      intptr_t diff = entry.priority - min_heap_[parent].priority;
+      if (diff < 0) {
+        BubbleUp(offset);
+      } else if (diff > 0) {
+        BubbleDown(offset);
+      }
+    }
+    return false;
+  }
+
+#ifdef TESTING
+  intptr_t min_heap_size() { return min_heap_size_; }
+#endif  // TESTING
+
+ private:
+  // Utility functions dealing with the SimpleHashMap interface.
+  static bool MatchFun(void* key1, void* key2) { return key1 == key2; }
+
+  SimpleHashMap::Entry* FindMapEntry(const V& key, bool insert = false) {
+    return hashmap_.Lookup(CastKey(key), HashKey(key), insert);
+  }
+  void RemoveMapEntry(const V& key) {
+    ASSERT(FindMapEntry(key) != nullptr);
+    hashmap_.Remove(CastKey(key), HashKey(key));
+  }
+  void SetMapEntry(const V& key, intptr_t value) {
+    FindMapEntry(key, /*insert=*/true)->value = reinterpret_cast<void*>(value);
+  }
+  static uint32_t HashKey(const V& key) {
+    return static_cast<uint32_t>(reinterpret_cast<intptr_t>(CastKey(key)));
+  }
+  static intptr_t ValueOfMapEntry(SimpleHashMap::Entry* entry) {
+    return reinterpret_cast<intptr_t>(entry->value);
+  }
+  static void* CastKey(const V& key) {
+    return reinterpret_cast<void*>((const_cast<V&>(key)));
+  }
+
+  void RemoveAt(intptr_t offset) {
+    ASSERT(offset < size_);
+
+    size_--;
+
+    if (offset == size_) {
+      RemoveMapEntry(min_heap_[offset].value);
+    } else {
+      Replace(offset, size_);
+      BubbleDown(offset);
+    }
+
+    if (size_ <= (min_heap_size_ >> 2) &&
+        kMinimumSize <= (min_heap_size_ >> 1)) {
+      Resize(min_heap_size_ >> 1);
+    }
+  }
+
+  void BubbleUp(intptr_t offset) {
+    while (true) {
+      if (offset == 0) return;
+
+      intptr_t parent = (offset - 1) / 2;
+      if (min_heap_[parent].priority > min_heap_[offset].priority) {
+        Swap(parent, offset);
+      }
+      offset = parent;
+    }
+  }
+
+  void BubbleDown(intptr_t offset) {
+    while (true) {
+      intptr_t left_child_index = 2 * offset + 1;
+      bool has_left_child = left_child_index < size_;
+
+      if (!has_left_child) return;
+
+      intptr_t smallest_index = offset;
+
+      if (min_heap_[left_child_index].priority < min_heap_[offset].priority) {
+        smallest_index = left_child_index;
+      }
+
+      intptr_t right_child_index = left_child_index + 1;
+      bool has_right_child = right_child_index < size_;
+      if (has_right_child) {
+        if (min_heap_[right_child_index].priority <
+            min_heap_[smallest_index].priority) {
+          smallest_index = right_child_index;
+        }
+      }
+
+      if (offset == smallest_index) {
+        return;
+      }
+
+      Swap(offset, smallest_index);
+      offset = smallest_index;
+    }
+  }
+
+  void Set(intptr_t offset1, const Entry& entry) {
+    min_heap_[offset1] = entry;
+    SetMapEntry(entry.value, offset1);
+  }
+
+  void Swap(intptr_t offset1, intptr_t offset2) {
+    Entry temp = min_heap_[offset1];
+    min_heap_[offset1] = min_heap_[offset2];
+    min_heap_[offset2] = temp;
+
+    SetMapEntry(min_heap_[offset1].value, offset1);
+    SetMapEntry(min_heap_[offset2].value, offset2);
+  }
+
+  void Replace(intptr_t index, intptr_t with_other) {
+    RemoveMapEntry(min_heap_[index].value);
+
+    const Entry& entry = min_heap_[with_other];
+    SetMapEntry(entry.value, index);
+    min_heap_[index] = entry;
+  }
+
+  void Resize(intptr_t new_min_heap_size) {
+    ASSERT(size_ < new_min_heap_size);
+    ASSERT(new_min_heap_size != min_heap_size_);
+
+    Entry* new_backing = reinterpret_cast<Entry*>(
+        realloc(min_heap_, sizeof(Entry) * new_min_heap_size));
+
+    if (new_backing == NULL) FATAL("Cannot allocate memory.");
+
+    min_heap_ = new_backing;
+    min_heap_size_ = new_min_heap_size;
+  }
+
+  // The array is representing a tree structure with guaranteed log(n) height.
+  // It has the property that the value of node N is always equal or smaller
+  // than the value of N's children. Furthermore it is a "dense" tree in the
+  // sense that all rows/layers of the tree are fully occupied except the last
+  // one. The way to represent such "dense" trees is via an array that allows
+  // finding left/right children by <2*index+1><2*index+2> and the parent by
+  // <(index-1)/2>.
+  //
+  // Insertion operations can be performed by adding one more entry at the end
+  // (bottom right) and bubbling it up until the tree invariant is satisfied
+  // again.
+  //
+  // Deletion operations can be performed by replacing the minimum element
+  // (first entry) by the last entry (bottom right) and bubbling it down until
+  // the tree invariant is satisified again.
+  Entry* min_heap_;
+  intptr_t min_heap_size_;
+  intptr_t size_;
+  SimpleHashMap hashmap_;
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_PLATFORM_PRIORITY_QUEUE_H_
diff --git a/runtime/platform/text_buffer.cc b/runtime/platform/text_buffer.cc
index 104fe76..2a3b80f 100644
--- a/runtime/platform/text_buffer.cc
+++ b/runtime/platform/text_buffer.cc
@@ -14,10 +14,18 @@
 intptr_t BaseTextBuffer::Printf(const char* format, ...) {
   va_list args;
   va_start(args, format);
+  intptr_t len = VPrintf(format, args);
+  va_end(args);
+  return len;
+}
+
+intptr_t BaseTextBuffer::VPrintf(const char* format, va_list args) {
+  va_list args1;
+  va_copy(args1, args);
   intptr_t remaining = capacity_ - length_;
   ASSERT(remaining >= 0);
-  intptr_t len = Utils::VSNPrint(buffer_ + length_, remaining, format, args);
-  va_end(args);
+  intptr_t len = Utils::VSNPrint(buffer_ + length_, remaining, format, args1);
+  va_end(args1);
   if (len >= remaining) {
     if (!EnsureCapacity(len)) {
       length_ = capacity_ - 1;
@@ -27,7 +35,7 @@
     remaining = capacity_ - length_;
     ASSERT(remaining > len);
     va_list args2;
-    va_start(args2, format);
+    va_copy(args2, args);
     intptr_t len2 =
         Utils::VSNPrint(buffer_ + length_, remaining, format, args2);
     va_end(args2);
diff --git a/runtime/platform/text_buffer.h b/runtime/platform/text_buffer.h
index c44d955..78f8e4f 100644
--- a/runtime/platform/text_buffer.h
+++ b/runtime/platform/text_buffer.h
@@ -20,6 +20,7 @@
   virtual ~BaseTextBuffer() {}
 
   intptr_t Printf(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
+  intptr_t VPrintf(const char* format, va_list args);
   void AddChar(char ch);
   void EscapeAndAddUTF16CodeUnit(uint16_t cu);
   void EscapeAndAddCodeUnit(uint32_t cu);
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index baa4ff4..eecab24 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -267,26 +267,29 @@
 
   // Adds two int64_t values with wrapping around
   // (two's complement arithmetic).
-  static inline int64_t AddWithWrapAround(int64_t a, int64_t b) {
+  template <typename T = int64_t>
+  static inline T AddWithWrapAround(T a, T b) {
     // Avoid undefined behavior by doing arithmetic in the unsigned type.
-    return static_cast<int64_t>(static_cast<uint64_t>(a) +
-                                static_cast<uint64_t>(b));
+    using Unsigned = typename std::make_unsigned<T>::type;
+    return static_cast<T>(static_cast<Unsigned>(a) + static_cast<Unsigned>(b));
   }
 
   // Subtracts two int64_t values with wrapping around
   // (two's complement arithmetic).
-  static inline int64_t SubWithWrapAround(int64_t a, int64_t b) {
+  template <typename T = int64_t>
+  static inline T SubWithWrapAround(T a, T b) {
     // Avoid undefined behavior by doing arithmetic in the unsigned type.
-    return static_cast<int64_t>(static_cast<uint64_t>(a) -
-                                static_cast<uint64_t>(b));
+    using Unsigned = typename std::make_unsigned<T>::type;
+    return static_cast<T>(static_cast<Unsigned>(a) - static_cast<Unsigned>(b));
   }
 
   // Multiplies two int64_t values with wrapping around
   // (two's complement arithmetic).
-  static inline int64_t MulWithWrapAround(int64_t a, int64_t b) {
+  template <typename T = int64_t>
+  static inline T MulWithWrapAround(T a, T b) {
     // Avoid undefined behavior by doing arithmetic in the unsigned type.
-    return static_cast<int64_t>(static_cast<uint64_t>(a) *
-                                static_cast<uint64_t>(b));
+    using Unsigned = typename std::make_unsigned<T>::type;
+    return static_cast<T>(static_cast<Unsigned>(a) * static_cast<Unsigned>(b));
   }
 
   // Shifts int64_t value left. Supports any non-negative number of bits and
@@ -358,15 +361,17 @@
     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);
-    if (n == kBitsPerWord) {
-      static_assert((sizeof(uword) * kBitsPerByte) == kBitsPerWord,
-                            "Unexpected uword size");
-      return std::numeric_limits<uword>::max();
-    }
-    return (static_cast<uword>(1) << n) - 1;
+    return NBitMaskUnsafe(n);
   }
 
   static word SignedNBitMask(uint32_t n) {
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
index 73ffe1d..fdebc07 100644
--- a/runtime/tests/vm/dart/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -720,20 +720,22 @@
   final mixedYieldsExpected = const <String>[
     r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
     r'^<asynchronous suspension>$',
-    r'^#1      mixedYields2 \(.*/utils.dart:66(:3)?\)$',
+    r'^#1      mixedYields3 \(.*/utils.dart:70(:3)?\)$',
     r'^<asynchronous suspension>$',
-    r'^#2      mixedYields \(.*/utils.dart:61(:3)?\)$',
+    r'^#2      mixedYields2 \(.*/utils.dart:66(:3)?\)$',
+    r'^<asynchronous suspension>$',
+    r'^#3      mixedYields \(.*/utils.dart:61(:3)?\)$',
     r'^<asynchronous suspension>$',
   ];
   await doTestAwait(
       mixedYields,
       mixedYieldsExpected +
           const <String>[
-            r'^#3      doTestAwait ',
+            r'^#4      doTestAwait ',
             r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
+            r'^#5      doTestsLazy ',
             r'^<asynchronous suspension>$',
-            r'^#5      main ',
+            r'^#6      main ',
             r'^<asynchronous suspension>$',
           ],
       debugInfoFilename);
@@ -741,7 +743,7 @@
       mixedYields,
       mixedYieldsExpected +
           const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
+            r'^#4      doTestAwaitThen.<anonymous closure> ',
             r'^<asynchronous suspension>$',
           ],
       debugInfoFilename);
@@ -782,20 +784,22 @@
   final nonAsyncNoStackExpected = const <String>[
     r'^#0      throwAsync \(.*/utils.dart:21(:3)?\)$',
     r'^<asynchronous suspension>$',
-    r'^#1      nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$',
+    r'^#1      nonAsyncNoStack2 \(.*/utils.dart:97(:36)?\)$',
     r'^<asynchronous suspension>$',
-    r'^#2      nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$',
+    r'^#2      nonAsyncNoStack1 \(.*/utils.dart:95(:36)?\)$',
+    r'^<asynchronous suspension>$',
+    r'^#3      nonAsyncNoStack \(.*/utils.dart:93(:35)?\)$',
     r'^<asynchronous suspension>$',
   ];
   await doTestAwait(
       nonAsyncNoStack,
       nonAsyncNoStackExpected +
           const <String>[
-            r'^#3      doTestAwait ',
+            r'^#4      doTestAwait ',
             r'^<asynchronous suspension>$',
-            r'^#4      doTestsLazy ',
+            r'^#5      doTestsLazy ',
             r'^<asynchronous suspension>$',
-            r'^#5      main ',
+            r'^#6      main ',
             r'^<asynchronous suspension>$',
           ],
       debugInfoFilename);
@@ -803,7 +807,7 @@
       nonAsyncNoStack,
       nonAsyncNoStackExpected +
           const <String>[
-            r'^#3      doTestAwaitThen.<anonymous closure> ',
+            r'^#4      doTestAwaitThen.<anonymous closure> ',
             r'^<asynchronous suspension>$',
           ],
       debugInfoFilename);
diff --git a/runtime/tests/vm/dart/dylib_utils.dart b/runtime/tests/vm/dart/dylib_utils.dart
index 3ac9c3f..a805b6c 100644
--- a/runtime/tests/vm/dart/dylib_utils.dart
+++ b/runtime/tests/vm/dart/dylib_utils.dart
@@ -6,7 +6,7 @@
 import 'dart:io' show Platform;
 
 String _platformPath(String name, {String path = ""}) {
-  if (Platform.isLinux || Platform.isAndroid)
+  if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
diff --git a/runtime/tests/vm/dart/isolate_send_function_types_test.dart b/runtime/tests/vm/dart/isolate_send_function_types_test.dart
index 1129e87..f3b7f17 100644
--- a/runtime/tests/vm/dart/isolate_send_function_types_test.dart
+++ b/runtime/tests/vm/dart/isolate_send_function_types_test.dart
@@ -22,7 +22,7 @@
     Expect.equals(
         await caughtErrorCompleter.future,
         "Invalid argument(s): Illegal argument in isolate message : "
-        "(function types are not supported yet)");
+        "(object is a FunctionType)");
   }
 
   Future<void> genericFunc<T>() async {
@@ -36,7 +36,7 @@
     Expect.equals(
         await caughtErrorCompleter.future,
         "Invalid argument(s): Illegal argument in isolate message : "
-        "(function types are not supported yet)");
+        "(object is a FunctionType)");
   }
 
   await genericFunc<int>();
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 f2e8a70..ecc33a1 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
@@ -14,6 +14,7 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import '../../../../../tests/ffi/calloc.dart';
 import '../../../../../tests/ffi/dylib_utils.dart';
 
 final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
@@ -21,7 +22,7 @@
     Platform.executableArguments.contains('--enable-isolate-groups');
 final sdkRoot = Platform.script.resolve('../../../../../');
 
-class Isolate extends Struct {}
+class Isolate extends Opaque {}
 
 abstract class FfiBindings {
   static final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
@@ -62,7 +63,7 @@
       Expect.isTrue(isolate.address != 0);
       return isolate;
     } finally {
-      free(cname);
+      calloc.free(cname);
     }
   }
 
@@ -86,8 +87,8 @@
         onError != null ? onError.nativePort : 0,
         onExit != null ? onExit.nativePort : 0);
 
-    free(libraryUri);
-    free(functionName);
+    calloc.free(libraryUri);
+    calloc.free(functionName);
   }
 }
 
@@ -120,7 +121,7 @@
     // wait a little here to ensure the write of the callback has arrived.
     await Future.delayed(const Duration(milliseconds: 100));
     Expect.equals('xbz', Utf8.fromUtf8(peer.cast()));
-    free(peer);
+    calloc.free(peer);
   }
 }
 
diff --git a/runtime/tests/vm/dart/isolates/thread_pool_test.dart b/runtime/tests/vm/dart/isolates/thread_pool_test.dart
index 7a301bc0..3d689ca 100644
--- a/runtime/tests/vm/dart/isolates/thread_pool_test.dart
+++ b/runtime/tests/vm/dart/isolates/thread_pool_test.dart
@@ -16,7 +16,7 @@
 // This should be larger than max-new-space-size/tlab-size.
 const int threadCount = 200;
 
-class Isolate extends Struct {}
+class Isolate extends Opaque {}
 
 typedef Dart_CurrentIsolateFT = Pointer<Isolate> Function();
 typedef Dart_CurrentIsolateNFT = Pointer<Isolate> Function();
diff --git a/runtime/tests/vm/dart/regress_37382_test.dart b/runtime/tests/vm/dart/regress_37382_test.dart
index e0d818c..0a25345 100644
--- a/runtime/tests/vm/dart/regress_37382_test.dart
+++ b/runtime/tests/vm/dart/regress_37382_test.dart
@@ -4,11 +4,23 @@
 
 import 'package:expect/expect.dart';
 
+void expectType(Type type, Pattern text) {
+  var typeString = "$type";
+  if (typeString.contains("minified:")) {
+    return; // No checks for minimized types.
+  }
+  var match = text.matchAsPrefix(typeString);
+  if (match != null && match.end == typeString.length) return;
+  Expect.fail(
+      "$typeString was not matched by $text${match == null ? "" : ", match: ${match[0]}"}");
+}
+
 class A<X, Y> {
   R f<R>(R Function<S, T>(A<S, T>) t) => t<X, Y>(this);
 }
 
 main() {
   A<num, num> a = A<int, int>();
-  Expect.equals(a.f.runtimeType.toString(), '<R>(<S, T>(A<S, T>) => R) => R');
+  expectType(a.f.runtimeType,
+      RegExp(r"<(\w+)>\(<(\w+), (\w+)>\(A<\2, \3>\) => \1\) => \1$"));
 }
diff --git a/runtime/tests/vm/dart/regress_41971_test.dart b/runtime/tests/vm/dart/regress_41971_test.dart
index 28f63ad..7979d0d 100644
--- a/runtime/tests/vm/dart/regress_41971_test.dart
+++ b/runtime/tests/vm/dart/regress_41971_test.dart
@@ -11,6 +11,8 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import '../../../../tests/ffi/calloc.dart';
+
 class X {
   int field;
   X(this.field);
@@ -35,8 +37,8 @@
 }
 
 void main() {
-  final p = allocate<Int32>(count: 128);
+  final p = calloc<Int32>(128);
   p[0] = 42;
   Expect.equals(42, loadFrom(p));
-  free(p);
+  calloc.free(p);
 }
diff --git a/runtime/tests/vm/dart/regress_42067_test.dart b/runtime/tests/vm/dart/regress_42067_test.dart
new file mode 100644
index 0000000..21f87c8
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_42067_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.
+
+// VMOptions=--deterministic --optimization_counter_threshold=100
+
+// Verifies correct code is generated for Float64x2.fromFloat32x4 in case of
+// high register pressure.
+// Regression test for https://github.com/dart-lang/sdk/issues/42067.
+
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+@pragma('vm:never-inline')
+doTest(double x) {
+  Float32x4 a0 = Float32x4.splat(x + 1);
+  Float32x4 a1 = Float32x4.splat(x + 2);
+  Float32x4 a2 = Float32x4.splat(x + 3);
+  Float32x4 a3 = Float32x4.splat(x + 4);
+  Float32x4 a4 = Float32x4.splat(x + 5);
+  Float32x4 a5 = Float32x4.splat(x + 6);
+  Float32x4 a6 = Float32x4.splat(x + 7);
+  Float32x4 a7 = Float32x4.splat(x + 8);
+  return Float64x2.fromFloat32x4(a0) +
+      Float64x2.fromFloat32x4(a1) +
+      Float64x2.fromFloat32x4(a2) +
+      Float64x2.fromFloat32x4(a3) +
+      Float64x2.fromFloat32x4(a4) +
+      Float64x2.fromFloat32x4(a5) +
+      Float64x2.fromFloat32x4(a6) +
+      Float64x2.fromFloat32x4(a7) +
+      Float64x2.fromFloat32x4(a0) +
+      Float64x2.fromFloat32x4(a1) +
+      Float64x2.fromFloat32x4(a2) +
+      Float64x2.fromFloat32x4(a3) +
+      Float64x2.fromFloat32x4(a4) +
+      Float64x2.fromFloat32x4(a5) +
+      Float64x2.fromFloat32x4(a6) +
+      Float64x2.fromFloat32x4(a7);
+}
+
+void main() {
+  for (int i = 0; i < 200; ++i) {
+    Expect.approxEquals(88.0, doTest(1.0).x);
+  }
+}
diff --git a/runtime/tests/vm/dart/sdk_hash_test.dart b/runtime/tests/vm/dart/sdk_hash_test.dart
index 8e31050..0ad4dba 100644
--- a/runtime/tests/vm/dart/sdk_hash_test.dart
+++ b/runtime/tests/vm/dart/sdk_hash_test.dart
@@ -35,7 +35,7 @@
       ]);
       Expect.equals('', result.stderr);
       Expect.equals(0, result.exitCode);
-      Expect.equals('', result.stdout);
+      Expect.equals('$unsoundNullSafetyMessage\n', result.stdout);
     }
 
     {
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index 1b578b9..28e5c47 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -39,7 +39,10 @@
 
 void expectOutput(String what, Result result) {
   if (result.output != what) {
-    reportError(result, 'Expected test to print \'${what}\' to stdout');
+    reportError(
+        result,
+        'Expected test to print \'${what}\' to stdout. '
+        'Actual: ${result.output}');
   }
 }
 
@@ -127,6 +130,12 @@
     final snapshot1Path = p.join(temp, 'snapshot1');
     final snapshot2Path = p.join(temp, 'snapshot2');
 
+    if (expectedStdout.isEmpty) {
+      expectedStdout = nullSafetyMessage;
+    } else {
+      expectedStdout = '$nullSafetyMessage\n$expectedStdout';
+    }
+
     print("Version ${Platform.version}");
 
     final generate1Result = await runDart('GENERATE SNAPSHOT 1', [
@@ -183,8 +192,15 @@
       testPath,
       '--train'
     ]);
-    expectOutput("OK(Trained)", trainingResult);
+    expectOutput("$nullSafetyMessage\nOK(Trained)", trainingResult);
     final runResult = await runSnapshot!(snapshotPath);
     expectOutput("OK(Run)", runResult);
   });
 }
+
+final String nullSafetyMessage =
+    hasSoundNullSafety ? soundNullSafetyMessage : unsoundNullSafetyMessage;
+
+const String soundNullSafetyMessage = 'Info: Compiling with sound null safety';
+const String unsoundNullSafetyMessage =
+    'Info: Compiling without sound null safety';
diff --git a/runtime/tests/vm/dart/split_literals.dart b/runtime/tests/vm/dart/split_literals.dart
new file mode 100644
index 0000000..b71e9bd
--- /dev/null
+++ b/runtime/tests/vm/dart/split_literals.dart
@@ -0,0 +1,21 @@
+// 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 "split_literals_deferred.dart" deferred as lib;
+
+class Box {
+  final contents;
+  const Box(this.contents);
+  String toString() => "Box($contents)";
+}
+
+main() async {
+  print("Root literal!");
+  print(const <String>["Root literal in a list!"]);
+  print(const <String, String>{"key": "Root literal in a map!"});
+  print(const Box("Root literal in a box!"));
+
+  await lib.loadLibrary();
+  lib.foo();
+}
diff --git a/runtime/tests/vm/dart/split_literals_deferred.dart b/runtime/tests/vm/dart/split_literals_deferred.dart
new file mode 100644
index 0000000..015ae1d
--- /dev/null
+++ b/runtime/tests/vm/dart/split_literals_deferred.dart
@@ -0,0 +1,12 @@
+// 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 "split_literals.dart";
+
+void foo() {
+  print("Deferred literal!");
+  print(const <String>["Deferred literal in a list!"]);
+  print(const <String, String>{"key": "Deferred literal in a map!"});
+  print(const Box("Deferred literal in a box!"));
+}
diff --git a/runtime/tests/vm/dart/split_literals_test.dart b/runtime/tests/vm/dart/split_literals_test.dart
new file mode 100644
index 0000000..6cbc01b
--- /dev/null
+++ b/runtime/tests/vm/dart/split_literals_test.dart
@@ -0,0 +1,115 @@
+// 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 "dart:convert";
+import "dart:io";
+
+import "package:expect/expect.dart";
+import "package:path/path.dart" as path;
+
+import "use_flag_test_helper.dart";
+
+main(List<String> args) async {
+  if (!isAOTRuntime) {
+    return; // Running in JIT: AOT binaries not available.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree not available on the test device.
+  }
+
+  // These are the tools we need to be available to run on a given platform:
+  if (!File(platformDill).existsSync()) {
+    throw "Cannot run test as $platformDill does not exist";
+  }
+  if (!await testExecutable(genSnapshot)) {
+    throw "Cannot run test as $genSnapshot not available";
+  }
+
+  sanitizedPartitioning(manifest) {
+    // Filter core libraries, relativize URIs, and sort to make the results less
+    // sensitive to compiler or test harness changes.
+    print(manifest);
+    var units = <List<String>>[];
+    for (var unit in manifest['loadingUnits']) {
+      var uris = <String>[];
+      for (var uri in unit['libraries']) {
+        if (uri.startsWith("dart:")) continue;
+        uris.add(Uri.parse(uri).pathSegments.last);
+      }
+      uris.sort((a, b) => a.compareTo(b));
+      units.add(uris);
+    }
+    units.sort((a, b) => a.first.compareTo(b.first));
+    print(units);
+    return units;
+  }
+
+  await withTempDir("split-literals-test", (String tempDir) async {
+    final source =
+        path.join(sdkDir, "runtime/tests/vm/dart_2/split_literals.dart");
+    final dill = path.join(tempDir, "split_literals.dart.dill");
+    final snapshot = path.join(tempDir, "split_literals.so");
+    final manifest = path.join(tempDir, "split_literals.txt");
+    final deferredSnapshot = snapshot + "-2.part.so";
+
+    // Compile source to kernel.
+    await run(genKernel, <String>[
+      "--aot",
+      "--platform=$platformDill",
+      "-o",
+      dill,
+      source,
+    ]);
+
+    // Compile kernel to ELF.
+    await run(genSnapshot, <String>[
+      "--use_bare_instructions=false", //# object: ok
+      "--use_bare_instructions=true", //# bare: ok
+      "--snapshot-kind=app-aot-elf",
+      "--elf=$snapshot",
+      "--loading-unit-manifest=$manifest",
+      dill,
+    ]);
+    var manifestContent = jsonDecode(await new File(manifest).readAsString());
+    Expect.equals(2, manifestContent["loadingUnits"].length);
+    // Note package:expect doesn't do deep equals on collections.
+    Expect.equals(
+        "[[split_literals.dart],"
+        " [split_literals_deferred.dart]]",
+        sanitizedPartitioning(manifestContent).toString());
+    Expect.isTrue(await new File(deferredSnapshot).exists());
+
+    bool containsSubsequence(haystack, needle) {
+      outer:
+      for (var i = 0, n = haystack.length - needle.length; i < n; i++) {
+        for (var j = 0; j < needle.length; j++) {
+          if (haystack[i + j] != needle.codeUnitAt(j)) continue outer;
+        }
+        return true;
+      }
+      return false;
+    }
+
+    var unit_1 = await new File(snapshot).readAsBytes();
+    Expect.isTrue(containsSubsequence(unit_1, "Root literal!"));
+    Expect.isTrue(containsSubsequence(unit_1, "Root literal in a list!"));
+    Expect.isTrue(containsSubsequence(unit_1, "Root literal in a map!"));
+    Expect.isTrue(containsSubsequence(unit_1, "Root literal in a box!"));
+    Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal!"));
+    Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a list!"));
+    Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a map!"));
+    Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a box!"));
+
+    var unit_2 = await new File(deferredSnapshot).readAsBytes();
+    Expect.isTrue(!containsSubsequence(unit_2, "Root literal!"));
+    Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a list!"));
+    Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a map!"));
+    Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a box!"));
+    Expect.isTrue(containsSubsequence(unit_2, "Deferred literal!"));
+    Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a list!"));
+    Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a map!"));
+    Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a box!"));
+  });
+}
diff --git a/runtime/tests/vm/dart/thread_priority_macos_test.dart b/runtime/tests/vm/dart/thread_priority_macos_test.dart
index b7c8280..473c1ce 100644
--- a/runtime/tests/vm/dart/thread_priority_macos_test.dart
+++ b/runtime/tests/vm/dart/thread_priority_macos_test.dart
@@ -10,6 +10,8 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import '../../../../tests/ffi/calloc.dart';
+
 // pthread_t pthread_self()
 typedef PthreadSelfFT = int Function();
 typedef PthreadSelfNFT = IntPtr Function();
@@ -34,11 +36,11 @@
 
 main(args) {
   if (Platform.isMacOS) {
-    final policy = allocate<Int32>(count: 1);
-    final param = allocate<SchedParam>(count: 1);
+    final policy = calloc<Int32>(1);
+    final param = calloc<SchedParam>(1);
     Expect.equals(0, pthreadGetSchedParam(pthreadSelf(), policy, param));
     Expect.equals(15, param.ref.schedPriority);
-    free(policy);
-    free(param);
+    calloc.free(policy);
+    calloc.free(param);
   }
 }
diff --git a/runtime/tests/vm/dart_2/dylib_utils.dart b/runtime/tests/vm/dart_2/dylib_utils.dart
index 75ba33b..083e941 100644
--- a/runtime/tests/vm/dart_2/dylib_utils.dart
+++ b/runtime/tests/vm/dart_2/dylib_utils.dart
@@ -7,7 +7,7 @@
 
 String _platformPath(String name, {String path}) {
   if (path == null) path = "";
-  if (Platform.isLinux || Platform.isAndroid)
+  if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
diff --git a/runtime/tests/vm/dart_2/isolate_send_function_types_test.dart b/runtime/tests/vm/dart_2/isolate_send_function_types_test.dart
index e45e045..8075c8b 100644
--- a/runtime/tests/vm/dart_2/isolate_send_function_types_test.dart
+++ b/runtime/tests/vm/dart_2/isolate_send_function_types_test.dart
@@ -22,7 +22,7 @@
     Expect.equals(
         await caughtErrorCompleter.future,
         "Invalid argument(s): Illegal argument in isolate message : "
-        "(function types are not supported yet)");
+        "(object is a FunctionType)");
   }
 
   void genericFunc<T>() async {
@@ -36,7 +36,7 @@
     Expect.equals(
         await caughtErrorCompleter.future,
         "Invalid argument(s): Illegal argument in isolate message : "
-        "(function types are not supported yet)");
+        "(object is a FunctionType)");
   }
 
   await genericFunc<int>();
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 0daead0..bcd6270 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
@@ -14,6 +14,7 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import '../../../../../tests/ffi/calloc.dart';
 import '../../../../../tests/ffi/dylib_utils.dart';
 
 final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
@@ -21,7 +22,7 @@
     Platform.executableArguments.contains('--enable-isolate-groups');
 final sdkRoot = Platform.script.resolve('../../../../../');
 
-class Isolate extends Struct {}
+class Isolate extends Opaque {}
 
 abstract class FfiBindings {
   static final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
@@ -62,7 +63,7 @@
       Expect.isTrue(isolate.address != 0);
       return isolate;
     } finally {
-      free(cname);
+      calloc.free(cname);
     }
   }
 
@@ -86,8 +87,8 @@
         onError != null ? onError.nativePort : 0,
         onExit != null ? onExit.nativePort : 0);
 
-    free(libraryUri);
-    free(functionName);
+    calloc.free(libraryUri);
+    calloc.free(functionName);
   }
 }
 
@@ -120,7 +121,7 @@
     // wait a little here to ensure the write of the callback has arrived.
     await Future.delayed(const Duration(milliseconds: 100));
     Expect.equals('xbz', Utf8.fromUtf8(peer.cast()));
-    free(peer);
+    calloc.free(peer);
   }
 }
 
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 ff8a7e6..695fda2 100644
--- a/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart
@@ -16,7 +16,7 @@
 // This should be larger than max-new-space-size/tlab-size.
 const int threadCount = 200;
 
-class Isolate extends Struct {}
+class Isolate extends Opaque {}
 
 typedef Dart_CurrentIsolateFT = Pointer<Isolate> Function();
 typedef Dart_CurrentIsolateNFT = Pointer<Isolate> Function();
diff --git a/runtime/tests/vm/dart_2/regress_37382_test.dart b/runtime/tests/vm/dart_2/regress_37382_test.dart
index e0d818c..0a25345 100644
--- a/runtime/tests/vm/dart_2/regress_37382_test.dart
+++ b/runtime/tests/vm/dart_2/regress_37382_test.dart
@@ -4,11 +4,23 @@
 
 import 'package:expect/expect.dart';
 
+void expectType(Type type, Pattern text) {
+  var typeString = "$type";
+  if (typeString.contains("minified:")) {
+    return; // No checks for minimized types.
+  }
+  var match = text.matchAsPrefix(typeString);
+  if (match != null && match.end == typeString.length) return;
+  Expect.fail(
+      "$typeString was not matched by $text${match == null ? "" : ", match: ${match[0]}"}");
+}
+
 class A<X, Y> {
   R f<R>(R Function<S, T>(A<S, T>) t) => t<X, Y>(this);
 }
 
 main() {
   A<num, num> a = A<int, int>();
-  Expect.equals(a.f.runtimeType.toString(), '<R>(<S, T>(A<S, T>) => R) => R');
+  expectType(a.f.runtimeType,
+      RegExp(r"<(\w+)>\(<(\w+), (\w+)>\(A<\2, \3>\) => \1\) => \1$"));
 }
diff --git a/runtime/tests/vm/dart_2/regress_41971_test.dart b/runtime/tests/vm/dart_2/regress_41971_test.dart
index 28f63ad..7979d0d 100644
--- a/runtime/tests/vm/dart_2/regress_41971_test.dart
+++ b/runtime/tests/vm/dart_2/regress_41971_test.dart
@@ -11,6 +11,8 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import '../../../../tests/ffi/calloc.dart';
+
 class X {
   int field;
   X(this.field);
@@ -35,8 +37,8 @@
 }
 
 void main() {
-  final p = allocate<Int32>(count: 128);
+  final p = calloc<Int32>(128);
   p[0] = 42;
   Expect.equals(42, loadFrom(p));
-  free(p);
+  calloc.free(p);
 }
diff --git a/runtime/tests/vm/dart_2/regress_42067_test.dart b/runtime/tests/vm/dart_2/regress_42067_test.dart
new file mode 100644
index 0000000..21f87c8
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_42067_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.
+
+// VMOptions=--deterministic --optimization_counter_threshold=100
+
+// Verifies correct code is generated for Float64x2.fromFloat32x4 in case of
+// high register pressure.
+// Regression test for https://github.com/dart-lang/sdk/issues/42067.
+
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+@pragma('vm:never-inline')
+doTest(double x) {
+  Float32x4 a0 = Float32x4.splat(x + 1);
+  Float32x4 a1 = Float32x4.splat(x + 2);
+  Float32x4 a2 = Float32x4.splat(x + 3);
+  Float32x4 a3 = Float32x4.splat(x + 4);
+  Float32x4 a4 = Float32x4.splat(x + 5);
+  Float32x4 a5 = Float32x4.splat(x + 6);
+  Float32x4 a6 = Float32x4.splat(x + 7);
+  Float32x4 a7 = Float32x4.splat(x + 8);
+  return Float64x2.fromFloat32x4(a0) +
+      Float64x2.fromFloat32x4(a1) +
+      Float64x2.fromFloat32x4(a2) +
+      Float64x2.fromFloat32x4(a3) +
+      Float64x2.fromFloat32x4(a4) +
+      Float64x2.fromFloat32x4(a5) +
+      Float64x2.fromFloat32x4(a6) +
+      Float64x2.fromFloat32x4(a7) +
+      Float64x2.fromFloat32x4(a0) +
+      Float64x2.fromFloat32x4(a1) +
+      Float64x2.fromFloat32x4(a2) +
+      Float64x2.fromFloat32x4(a3) +
+      Float64x2.fromFloat32x4(a4) +
+      Float64x2.fromFloat32x4(a5) +
+      Float64x2.fromFloat32x4(a6) +
+      Float64x2.fromFloat32x4(a7);
+}
+
+void main() {
+  for (int i = 0; i < 200; ++i) {
+    Expect.approxEquals(88.0, doTest(1.0).x);
+  }
+}
diff --git a/runtime/tests/vm/dart_2/sdk_hash_test.dart b/runtime/tests/vm/dart_2/sdk_hash_test.dart
index c73dc03..40f245d 100644
--- a/runtime/tests/vm/dart_2/sdk_hash_test.dart
+++ b/runtime/tests/vm/dart_2/sdk_hash_test.dart
@@ -35,7 +35,7 @@
       ]);
       Expect.equals('', result.stderr);
       Expect.equals(0, result.exitCode);
-      Expect.equals('', result.stdout);
+      Expect.equals('$unsoundNullSafetyMessage\n', result.stdout);
     }
 
     {
diff --git a/runtime/tests/vm/dart_2/snapshot_test_helper.dart b/runtime/tests/vm/dart_2/snapshot_test_helper.dart
index eef877f..ae68005 100644
--- a/runtime/tests/vm/dart_2/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart_2/snapshot_test_helper.dart
@@ -39,7 +39,10 @@
 
 void expectOutput(String what, Result result) {
   if (result.output != what) {
-    reportError(result, 'Expected test to print \'${what}\' to stdout');
+    reportError(
+        result,
+        'Expected test to print \'${what}\' to stdout. '
+        'Actual: ${result.output}');
   }
 }
 
@@ -127,6 +130,12 @@
     final snapshot1Path = p.join(temp, 'snapshot1');
     final snapshot2Path = p.join(temp, 'snapshot2');
 
+    if (expectedStdout.isEmpty) {
+      expectedStdout = unsoundNullSafetyMessage;
+    } else {
+      expectedStdout = '$unsoundNullSafetyMessage\n$expectedStdout';
+    }
+
     print("Version ${Platform.version}");
 
     final generate1Result = await runDart('GENERATE SNAPSHOT 1', [
@@ -183,8 +192,11 @@
       testPath,
       '--train'
     ]);
-    expectOutput("OK(Trained)", trainingResult);
+    expectOutput("$unsoundNullSafetyMessage\nOK(Trained)", trainingResult);
     final runResult = await runSnapshot(snapshotPath);
     expectOutput("OK(Run)", runResult);
   });
 }
+
+const String unsoundNullSafetyMessage =
+    'Info: Compiling without sound null safety';
diff --git a/runtime/tests/vm/dart_2/split_literals.dart b/runtime/tests/vm/dart_2/split_literals.dart
new file mode 100644
index 0000000..b71e9bd
--- /dev/null
+++ b/runtime/tests/vm/dart_2/split_literals.dart
@@ -0,0 +1,21 @@
+// 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 "split_literals_deferred.dart" deferred as lib;
+
+class Box {
+  final contents;
+  const Box(this.contents);
+  String toString() => "Box($contents)";
+}
+
+main() async {
+  print("Root literal!");
+  print(const <String>["Root literal in a list!"]);
+  print(const <String, String>{"key": "Root literal in a map!"});
+  print(const Box("Root literal in a box!"));
+
+  await lib.loadLibrary();
+  lib.foo();
+}
diff --git a/runtime/tests/vm/dart_2/split_literals_deferred.dart b/runtime/tests/vm/dart_2/split_literals_deferred.dart
new file mode 100644
index 0000000..015ae1d
--- /dev/null
+++ b/runtime/tests/vm/dart_2/split_literals_deferred.dart
@@ -0,0 +1,12 @@
+// 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 "split_literals.dart";
+
+void foo() {
+  print("Deferred literal!");
+  print(const <String>["Deferred literal in a list!"]);
+  print(const <String, String>{"key": "Deferred literal in a map!"});
+  print(const Box("Deferred literal in a box!"));
+}
diff --git a/runtime/tests/vm/dart_2/split_literals_test.dart b/runtime/tests/vm/dart_2/split_literals_test.dart
new file mode 100644
index 0000000..6cbc01b
--- /dev/null
+++ b/runtime/tests/vm/dart_2/split_literals_test.dart
@@ -0,0 +1,115 @@
+// 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 "dart:convert";
+import "dart:io";
+
+import "package:expect/expect.dart";
+import "package:path/path.dart" as path;
+
+import "use_flag_test_helper.dart";
+
+main(List<String> args) async {
+  if (!isAOTRuntime) {
+    return; // Running in JIT: AOT binaries not available.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree not available on the test device.
+  }
+
+  // These are the tools we need to be available to run on a given platform:
+  if (!File(platformDill).existsSync()) {
+    throw "Cannot run test as $platformDill does not exist";
+  }
+  if (!await testExecutable(genSnapshot)) {
+    throw "Cannot run test as $genSnapshot not available";
+  }
+
+  sanitizedPartitioning(manifest) {
+    // Filter core libraries, relativize URIs, and sort to make the results less
+    // sensitive to compiler or test harness changes.
+    print(manifest);
+    var units = <List<String>>[];
+    for (var unit in manifest['loadingUnits']) {
+      var uris = <String>[];
+      for (var uri in unit['libraries']) {
+        if (uri.startsWith("dart:")) continue;
+        uris.add(Uri.parse(uri).pathSegments.last);
+      }
+      uris.sort((a, b) => a.compareTo(b));
+      units.add(uris);
+    }
+    units.sort((a, b) => a.first.compareTo(b.first));
+    print(units);
+    return units;
+  }
+
+  await withTempDir("split-literals-test", (String tempDir) async {
+    final source =
+        path.join(sdkDir, "runtime/tests/vm/dart_2/split_literals.dart");
+    final dill = path.join(tempDir, "split_literals.dart.dill");
+    final snapshot = path.join(tempDir, "split_literals.so");
+    final manifest = path.join(tempDir, "split_literals.txt");
+    final deferredSnapshot = snapshot + "-2.part.so";
+
+    // Compile source to kernel.
+    await run(genKernel, <String>[
+      "--aot",
+      "--platform=$platformDill",
+      "-o",
+      dill,
+      source,
+    ]);
+
+    // Compile kernel to ELF.
+    await run(genSnapshot, <String>[
+      "--use_bare_instructions=false", //# object: ok
+      "--use_bare_instructions=true", //# bare: ok
+      "--snapshot-kind=app-aot-elf",
+      "--elf=$snapshot",
+      "--loading-unit-manifest=$manifest",
+      dill,
+    ]);
+    var manifestContent = jsonDecode(await new File(manifest).readAsString());
+    Expect.equals(2, manifestContent["loadingUnits"].length);
+    // Note package:expect doesn't do deep equals on collections.
+    Expect.equals(
+        "[[split_literals.dart],"
+        " [split_literals_deferred.dart]]",
+        sanitizedPartitioning(manifestContent).toString());
+    Expect.isTrue(await new File(deferredSnapshot).exists());
+
+    bool containsSubsequence(haystack, needle) {
+      outer:
+      for (var i = 0, n = haystack.length - needle.length; i < n; i++) {
+        for (var j = 0; j < needle.length; j++) {
+          if (haystack[i + j] != needle.codeUnitAt(j)) continue outer;
+        }
+        return true;
+      }
+      return false;
+    }
+
+    var unit_1 = await new File(snapshot).readAsBytes();
+    Expect.isTrue(containsSubsequence(unit_1, "Root literal!"));
+    Expect.isTrue(containsSubsequence(unit_1, "Root literal in a list!"));
+    Expect.isTrue(containsSubsequence(unit_1, "Root literal in a map!"));
+    Expect.isTrue(containsSubsequence(unit_1, "Root literal in a box!"));
+    Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal!"));
+    Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a list!"));
+    Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a map!"));
+    Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a box!"));
+
+    var unit_2 = await new File(deferredSnapshot).readAsBytes();
+    Expect.isTrue(!containsSubsequence(unit_2, "Root literal!"));
+    Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a list!"));
+    Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a map!"));
+    Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a box!"));
+    Expect.isTrue(containsSubsequence(unit_2, "Deferred literal!"));
+    Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a list!"));
+    Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a map!"));
+    Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a box!"));
+  });
+}
diff --git a/runtime/tests/vm/dart_2/thread_priority_macos_test.dart b/runtime/tests/vm/dart_2/thread_priority_macos_test.dart
index b466eb0..fdce726 100644
--- a/runtime/tests/vm/dart_2/thread_priority_macos_test.dart
+++ b/runtime/tests/vm/dart_2/thread_priority_macos_test.dart
@@ -10,6 +10,8 @@
 import 'package:expect/expect.dart';
 import 'package:ffi/ffi.dart';
 
+import '../../../../tests/ffi/calloc.dart';
+
 // pthread_t pthread_self()
 typedef PthreadSelfFT = int Function();
 typedef PthreadSelfNFT = IntPtr Function();
@@ -34,11 +36,11 @@
 
 main(args) {
   if (Platform.isMacOS) {
-    final policy = allocate<Int32>(count: 1);
-    final param = allocate<SchedParam>(count: 1);
+    final policy = calloc<Int32>(1);
+    final param = calloc<SchedParam>(1);
     Expect.equals(0, pthreadGetSchedParam(pthreadSelf(), policy, param));
     Expect.equals(15, param.ref.schedPriority);
-    free(policy);
-    free(param);
+    calloc.free(policy);
+    calloc.free(param);
   }
 }
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 802cc8b..4b8f66d 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -58,9 +58,11 @@
 [ $builder_tag == tsan ]
 dart/appjit_cha_deopt_test: SkipSlow
 dart/regress_40462_test: SkipSlow
+dart/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart_2/appjit_cha_deopt_test: SkipSlow
 dart_2/regress_40462_test: SkipSlow
+dart_2/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 dart_2/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 
 [ $compiler == app_jitk ]
diff --git a/runtime/vm/bitfield.h b/runtime/vm/bitfield.h
index c033379..1eaa94d 100644
--- a/runtime/vm/bitfield.h
+++ b/runtime/vm/bitfield.h
@@ -14,7 +14,10 @@
 
 // BitField is a template for encoding and decoding a value of type T
 // inside a storage of type S.
-template <typename S, typename T, int position, int size>
+template <typename S,
+          typename T,
+          int position,
+          int size = (sizeof(S) * kBitsPerByte) - position>
 class BitField {
  public:
   typedef T Type;
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index f0c2d76..5e3ddd7 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -48,7 +48,7 @@
   // Eagerly compile the _Closure class as it is the class of all closure
   // instances. This allows us to just finalize function types without going
   // through the hoops of trying to compile their scope class.
-  ObjectStore* object_store = thread->isolate()->object_store();
+  ObjectStore* object_store = thread->isolate_group()->object_store();
   Zone* zone = thread->zone();
   Class& cls = Class::Handle(zone, object_store->closure_class());
   cls.EnsureIsFinalized(thread);
@@ -111,9 +111,9 @@
   if (setjmp(*jump.Set()) == 0) {
     kernel::KernelLoader loader(program.get(), /*uri_to_source_table=*/nullptr);
 
-    Isolate* isolate = thread->isolate();
+    auto isolate_group = thread->isolate_group();
 
-    if (isolate->obfuscate()) {
+    if (isolate_group->obfuscate()) {
       loader.ReadObfuscationProhibitions();
     }
 
@@ -121,7 +121,7 @@
     Library& library = Library::Handle(zone);
     for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
       ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
-      library = isolate->object_store()->bootstrap_library(id);
+      library = isolate_group->object_store()->bootstrap_library(id);
       loader.LoadLibrary(library);
     }
 
@@ -133,14 +133,14 @@
     const Object& result = Object::Handle(zone, loader.LoadProgram());
     program.reset();
     if (result.IsError()) {
-      return Error::Cast(result).raw();
+      return Error::Cast(result).ptr();
     }
 
     // The builtin library should be registered with the VM.
     const auto& dart_builtin =
         String::Handle(zone, String::New("dart:_builtin"));
     library = Library::LookupLibrary(thread, dart_builtin);
-    isolate->object_store()->set_builtin_library(library);
+    isolate_group->object_store()->set_builtin_library(library);
 
     if (FLAG_precompiled_mode) {
       loader.ReadLoadingUnits();
@@ -157,7 +157,7 @@
 ErrorPtr Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer,
                                     intptr_t kernel_buffer_size) {
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   Zone* zone = thread->zone();
   String& uri = String::Handle(zone);
   Library& lib = Library::Handle(zone);
@@ -168,13 +168,13 @@
   for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
     ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
     uri = Symbols::New(thread, bootstrap_libraries[i].uri);
-    lib = isolate->object_store()->bootstrap_library(id);
-    ASSERT(lib.raw() == Library::LookupLibrary(thread, uri));
+    lib = isolate_group->object_store()->bootstrap_library(id);
+    ASSERT(lib.ptr() == Library::LookupLibrary(thread, uri));
     if (lib.IsNull()) {
       lib = Library::NewLibraryHelper(uri, false);
       lib.SetLoadRequested();
       lib.Register(thread);
-      isolate->object_store()->set_bootstrap_library(id, lib);
+      isolate_group->object_store()->set_bootstrap_library(id, lib);
     }
   }
 
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index df3b7ec..6750bf9 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -30,6 +30,8 @@
   V(AbstractType_toString, 1)                                                  \
   V(Type_getHashCode, 1)                                                       \
   V(Type_equality, 2)                                                          \
+  V(FunctionType_getHashCode, 1)                                               \
+  V(FunctionType_equality, 2)                                                  \
   V(LibraryPrefix_isLoaded, 1)                                                 \
   V(LibraryPrefix_setLoaded, 1)                                                \
   V(LibraryPrefix_loadingUnit, 1)                                              \
@@ -469,8 +471,6 @@
   V(MethodMirror_return_type, 2)                                               \
   V(MethodMirror_source, 1)                                                    \
   V(ParameterMirror_type, 3)                                                   \
-  V(TypedefMirror_referent, 1)                                                 \
-  V(TypedefMirror_declaration, 1)                                              \
   V(VariableMirror_type, 2)
 
 class BootstrapNatives : public AllStatic {
diff --git a/runtime/vm/canonical_tables.cc b/runtime/vm/canonical_tables.cc
index d5ab2ff..13c9470 100644
--- a/runtime/vm/canonical_tables.cc
+++ b/runtime/vm/canonical_tables.cc
@@ -45,11 +45,14 @@
     if (!name_a.Equals(name_b)) {
       return false;
     }
-    const Object& owner_a = Object::Handle(TypeParameter::Cast(a).Owner());
-    const Object& owner_b = Object::Handle(TypeParameter::Cast(b).Owner());
-    return IsMatch(owner_a, owner_b);
+    if (TypeParameter::Cast(a).index() != TypeParameter::Cast(b).index() ||
+        TypeParameter::Cast(a).base() != TypeParameter::Cast(b).base()) {
+      return false;
+    }
+    return TypeParameter::Cast(a).parameterized_class_id() ==
+           TypeParameter::Cast(b).parameterized_class_id();
   }
-  return a.raw() == b.raw();
+  return a.ptr() == b.ptr();
 }
 
 uword MetadataMapTraits::Hash(const Object& key) {
diff --git a/runtime/vm/canonical_tables.h b/runtime/vm/canonical_tables.h
index f0c3d2b..004b07f 100644
--- a/runtime/vm/canonical_tables.h
+++ b/runtime/vm/canonical_tables.h
@@ -21,7 +21,7 @@
     String& result = String::Handle(StringFrom(data_, len_, Heap::kOld));
     result.SetCanonical();
     result.SetHash(hash_);
-    return result.raw();
+    return result.ptr();
   }
   bool Equals(const String& other) const {
     ASSERT(other.HasHash());
@@ -167,11 +167,50 @@
   }
   static uword Hash(const CanonicalTypeKey& key) { return key.Hash(); }
   static ObjectPtr NewKey(const CanonicalTypeKey& obj) {
-    return obj.key_.raw();
+    return obj.key_.ptr();
   }
 };
 typedef UnorderedHashSet<CanonicalTypeTraits> CanonicalTypeSet;
 
+class CanonicalFunctionTypeKey {
+ public:
+  explicit CanonicalFunctionTypeKey(const FunctionType& key) : key_(key) {}
+  bool Matches(const FunctionType& arg) const { return key_.Equals(arg); }
+  uword Hash() const { return key_.Hash(); }
+  const FunctionType& key_;
+
+ private:
+  DISALLOW_ALLOCATION();
+};
+
+// Traits for looking up Canonical FunctionType based on its hash.
+class CanonicalFunctionTypeTraits {
+ public:
+  static const char* Name() { return "CanonicalFunctionTypeTraits"; }
+  static bool ReportStats() { return false; }
+
+  // Called when growing the table.
+  static bool IsMatch(const Object& a, const Object& b) {
+    ASSERT(a.IsFunctionType() && b.IsFunctionType());
+    const FunctionType& arg1 = FunctionType::Cast(a);
+    const FunctionType& arg2 = FunctionType::Cast(b);
+    return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
+  }
+  static bool IsMatch(const CanonicalFunctionTypeKey& a, const Object& b) {
+    ASSERT(b.IsFunctionType());
+    return a.Matches(FunctionType::Cast(b));
+  }
+  static uword Hash(const Object& key) {
+    ASSERT(key.IsFunctionType());
+    return FunctionType::Cast(key).Hash();
+  }
+  static uword Hash(const CanonicalFunctionTypeKey& key) { return key.Hash(); }
+  static ObjectPtr NewKey(const CanonicalFunctionTypeKey& obj) {
+    return obj.key_.ptr();
+  }
+};
+typedef UnorderedHashSet<CanonicalFunctionTypeTraits> CanonicalFunctionTypeSet;
+
 class CanonicalTypeParameterKey {
  public:
   explicit CanonicalTypeParameterKey(const TypeParameter& key) : key_(key) {}
@@ -206,7 +245,7 @@
   }
   static uword Hash(const CanonicalTypeParameterKey& key) { return key.Hash(); }
   static ObjectPtr NewKey(const CanonicalTypeParameterKey& obj) {
-    return obj.key_.raw();
+    return obj.key_.ptr();
   }
 };
 typedef UnorderedHashSet<CanonicalTypeParameterTraits>
@@ -248,7 +287,7 @@
   }
   static uword Hash(const CanonicalTypeArgumentsKey& key) { return key.Hash(); }
   static ObjectPtr NewKey(const CanonicalTypeArgumentsKey& obj) {
-    return obj.key_.raw();
+    return obj.key_.ptr();
   }
 };
 typedef UnorderedHashSet<CanonicalTypeArgumentsTraits>
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 175f985..cc14ad3 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -30,7 +30,7 @@
 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
 
 bool ClassFinalizer::AllClassesFinalized() {
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
   const GrowableObjectArray& classes =
       GrowableObjectArray::Handle(object_store->pending_classes());
   return classes.Length() == 0;
@@ -48,7 +48,7 @@
     return;
   }
   // Switch all functions' code to unoptimized.
-  const ClassTable& class_table = *Isolate::Current()->class_table();
+  const ClassTable& class_table = *IsolateGroup::Current()->class_table();
   Class& cls = Class::Handle();
   for (intptr_t i = 0; i < added_subclass_to_cids.length(); i++) {
     intptr_t cid = added_subclass_to_cids[i];
@@ -84,7 +84,7 @@
 static void CollectFinalizedSuperClasses(
     const Class& cls_,
     GrowableArray<intptr_t>* finalized_super_classes) {
-  Class& cls = Class::Handle(cls_.raw());
+  Class& cls = Class::Handle(cls_.ptr());
   AbstractType& super_type = Type::Handle();
   super_type = cls.super_type();
   if (!super_type.IsNull()) {
@@ -117,7 +117,7 @@
     ScopedHandle<Class> current_class(&class_handles_);
     ScopedHandle<AbstractType> type(&type_handles_);
 
-    *current_class = klass.raw();
+    *current_class = klass.ptr();
     while (true) {
       // We don't care about top types.
       const intptr_t cid = current_class->id();
@@ -175,10 +175,10 @@
 bool ClassFinalizer::ProcessPendingClasses() {
   Thread* thread = Thread::Current();
   TIMELINE_DURATION(thread, Isolate, "ProcessPendingClasses");
-  Isolate* isolate = thread->isolate();
-  ASSERT(isolate != NULL);
+  auto isolate_group = thread->isolate_group();
+  ASSERT(isolate_group != nullptr);
   HANDLESCOPE(thread);
-  ObjectStore* object_store = isolate->object_store();
+  ObjectStore* object_store = isolate_group->object_store();
   const Error& error = Error::Handle(thread->zone(), thread->sticky_error());
   if (!error.IsNull()) {
     return false;
@@ -225,7 +225,7 @@
   if (FLAG_trace_class_finalization) {
     OS::PrintErr("VerifyBootstrapClasses START.\n");
   }
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
 
   Class& cls = Class::Handle();
 #if defined(DEBUG)
@@ -284,34 +284,28 @@
   if (FLAG_trace_class_finalization) {
     OS::PrintErr("VerifyBootstrapClasses END.\n");
   }
-  Isolate::Current()->heap()->Verify();
+  IsolateGroup::Current()->heap()->Verify();
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-void ClassFinalizer::FinalizeTypeParameters(const Class& cls) {
+void ClassFinalizer::FinalizeTypeParameters(const Class& cls,
+                                            FinalizationKind finalization) {
   if (FLAG_trace_type_finalization) {
-    THR_Print("Finalizing type parameters of '%s'\n",
-              String::Handle(cls.Name()).ToCString());
+    THR_Print("%s type parameters of '%s'\n",
+              String::Handle(cls.Name()).ToCString(),
+              finalization == kFinalize ? "Finalizing" : "Canonicalizing");
   }
-  // The type parameter bounds are not finalized here.
-  const intptr_t offset = cls.NumTypeArguments() - cls.NumTypeParameters();
-  const TypeArguments& type_parameters =
+  const TypeArguments& type_params =
       TypeArguments::Handle(cls.type_parameters());
-  if (!type_parameters.IsNull()) {
-    TypeParameter& type_parameter = TypeParameter::Handle();
-    const intptr_t num_types = type_parameters.Length();
-    for (intptr_t i = 0; i < num_types; i++) {
-      type_parameter ^= type_parameters.TypeAt(i);
-      if (!type_parameter.IsFinalized()) {
-        ASSERT(type_parameter.index() == i);
-        type_parameter.set_index(offset + i);
-        type_parameter.SetIsFinalized();
-      } else {
-        ASSERT(type_parameter.index() == offset + i);
+  if (!type_params.IsNull()) {
+    const intptr_t num_type_params = type_params.Length();
+    TypeParameter& type_param = TypeParameter::Handle();
+    for (intptr_t i = 0; i < num_type_params; i++) {
+      type_param ^= type_params.TypeAt(i);
+      if (!type_param.IsBeingFinalized()) {
+        type_param ^= FinalizeType(type_param, finalization);
+        type_params.SetTypeAt(i, type_param);
       }
-      // The declaration of a type parameter is canonical.
-      ASSERT(type_parameter.IsDeclaration());
-      ASSERT(type_parameter.IsCanonical());
     }
   }
 }
@@ -328,6 +322,7 @@
 // pending finalization that are mutually recursive with the checked type.
 void ClassFinalizer::CheckRecursiveType(const AbstractType& type,
                                         PendingTypes* pending_types) {
+  ASSERT(!type.IsFunctionType());
   ASSERT(pending_types != NULL);
   Zone* zone = Thread::Current()->zone();
   if (FLAG_trace_type_finalization) {
@@ -338,13 +333,7 @@
   const TypeArguments& arguments =
       TypeArguments::Handle(zone, type.arguments());
   // A type can only be recursive via its type arguments.
-  if (arguments.IsNull()) {
-    // However, Kernel does not keep the relation between a function type and
-    // its declaring typedef. Therefore, a typedef-declared function type may
-    // refer to the still unfinalized typedef via a type in its signature.
-    ASSERT(type.IsFunctionType());
-    return;
-  }
+  ASSERT(!arguments.IsNull());
   const intptr_t num_type_args = arguments.Length();
   ASSERT(num_type_args > 0);
   ASSERT(num_type_args == type_cls.NumTypeArguments());
@@ -372,8 +361,8 @@
                 String::Handle(pending_type.Name()).ToCString(),
                 pending_type.ToCString());
     }
-    if ((pending_type.raw() != type.raw()) && pending_type.IsType() &&
-        (pending_type.type_class() == type_cls.raw())) {
+    if ((pending_type.ptr() != type.ptr()) && pending_type.IsType() &&
+        (pending_type.type_class() == type_cls.ptr())) {
       pending_arguments = pending_type.arguments();
       // By using TypeEquality::kInSubtypeTest, we throw a wider net than
       // using canonical or syntactical equality and may reject more
@@ -416,9 +405,6 @@
   // Also, the type parameters of the type class must be finalized.
   Class& type_class = Class::Handle(zone, type.type_class());
   type_class.EnsureDeclarationLoaded();
-  if (!type_class.is_type_finalized()) {
-    FinalizeTypeParameters(type_class);
-  }
 
   // The finalized type argument vector needs num_type_arguments types.
   const intptr_t num_type_arguments = type_class.NumTypeArguments();
@@ -430,13 +416,6 @@
   TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
   ASSERT(arguments.IsNull() || (arguments.Length() == num_type_parameters));
 
-  // Mark the type as being finalized in order to detect self reference and
-  // postpone bound checking (if required) until after all types in the graph of
-  // mutually recursive types are finalized.
-  type.SetIsBeingFinalized();
-  ASSERT(pending_types != NULL);
-  pending_types->Add(type);
-
   // The full type argument vector consists of the type arguments of the
   // super types of type_class, which are initialized from the parsed
   // type arguments, followed by the parsed type arguments.
@@ -471,8 +450,12 @@
       if (!arguments.IsNull()) {
         for (intptr_t i = 0; i < num_type_parameters; i++) {
           type_arg = full_arguments.TypeAt(offset + i);
-          ASSERT(!type_arg.IsBeingFinalized());
-          type_arg = FinalizeType(type_arg, kFinalize, pending_types);
+          if (!type_arg.IsBeingFinalized()) {
+            type_arg = FinalizeType(type_arg, kFinalize, pending_types);
+          } else {
+            ASSERT(type_arg.IsTypeParameter());
+            // The bound of the type parameter is still being finalized.
+          }
           full_arguments.SetTypeAt(offset + i, type_arg);
         }
       }
@@ -537,7 +520,7 @@
                                            TrailPtr trail) {
   ASSERT(arguments.Length() >= cls.NumTypeArguments());
   if (!cls.is_type_finalized()) {
-    FinalizeTypeParameters(cls);
+    FinalizeTypeParameters(cls, kFinalize);
   }
   AbstractType& super_type = AbstractType::Handle(cls.super_type());
   if (!super_type.IsNull()) {
@@ -559,14 +542,25 @@
         super_type_arg = super_type_args.TypeAt(i);
         if (!super_type_arg.IsTypeRef()) {
           if (super_type_arg.IsBeingFinalized()) {
-            ASSERT(super_type_arg.IsType());
-            CheckRecursiveType(super_type_arg, pending_types);
-            if (FLAG_trace_type_finalization) {
-              THR_Print("Creating TypeRef '%s': '%s'\n",
-                        String::Handle(super_type_arg.Name()).ToCString(),
-                        super_type_arg.ToCString());
+            // A type parameter being finalized indicates an unfinalized bound,
+            // but the bound is not relevant here. Its index is finalized.
+            if (!super_type_arg.IsTypeParameter()) {
+              if (super_type_arg.IsType()) {
+                CheckRecursiveType(super_type_arg, pending_types);
+              } else {
+                // The spec prohibits a typedef-declared function type to refer
+                // to itself. However, self-reference can occur via type
+                // arguments of the base class,
+                // e.g. `class Derived extends Base<TypeDef<Derived>> {}`.
+                ASSERT(super_type_arg.IsFunctionType());
+              }
+              if (FLAG_trace_type_finalization) {
+                THR_Print("Creating TypeRef '%s': '%s'\n",
+                          String::Handle(super_type_arg.Name()).ToCString(),
+                          super_type_arg.ToCString());
+              }
+              super_type_arg = TypeRef::New(super_type_arg);
             }
-            super_type_arg = TypeRef::New(super_type_arg);
             super_type_args.SetTypeAt(i, super_type_arg);
           } else {
             if (!super_type_arg.IsFinalized()) {
@@ -595,7 +589,7 @@
           // While finalizing D<T>, the super type arg D<T> (a typeref) gets
           // instantiated from vector [T], yielding itself.
           if (super_type_arg.IsTypeRef() &&
-              (super_type_arg.arguments() == arguments.raw())) {
+              (super_type_arg.arguments() == arguments.ptr())) {
             ASSERT(super_type_arg.IsBeingFinalized());
             arguments.SetTypeAt(i, super_type_arg);
             continue;
@@ -603,23 +597,27 @@
           super_type_arg = super_type_arg.InstantiateFrom(
               arguments, Object::null_type_arguments(), kNoneFree, Heap::kOld,
               trail);
-          if (super_type_arg.IsBeingFinalized()) {
+          if (super_type_arg.IsBeingFinalized() &&
+              !super_type_arg.IsTypeParameter()) {
             // The super_type_arg was instantiated from a type being finalized.
-            // We need to finish finalizing its type arguments.
+            // We need to finish finalizing its type arguments, unless it is a
+            // type parameter, in which case there is nothing more to do.
             AbstractType& unfinalized_type = AbstractType::Handle();
             if (super_type_arg.IsTypeRef()) {
               unfinalized_type = TypeRef::Cast(super_type_arg).type();
             } else {
               ASSERT(super_type_arg.IsType());
-              unfinalized_type = super_type_arg.raw();
+              unfinalized_type = super_type_arg.ptr();
             }
             if (FLAG_trace_type_finalization) {
               THR_Print("Instantiated unfinalized '%s': '%s'\n",
                         String::Handle(unfinalized_type.Name()).ToCString(),
                         unfinalized_type.ToCString());
             }
-            CheckRecursiveType(unfinalized_type, pending_types);
-            pending_types->Add(unfinalized_type);
+            if (unfinalized_type.IsType()) {
+              CheckRecursiveType(unfinalized_type, pending_types);
+              pending_types->Add(unfinalized_type);
+            }
             const Class& super_cls =
                 Class::Handle(unfinalized_type.type_class());
             const TypeArguments& super_args =
@@ -658,24 +656,34 @@
   ASSERT((pending_types == NULL) || (finalization < kCanonicalize));
   if (type.IsFinalized()) {
     // Ensure type is canonical if canonicalization is requested.
-    if ((finalization >= kCanonicalize) && !type.IsCanonical()) {
+    if ((finalization >= kCanonicalize) && !type.IsCanonical() &&
+        !type.IsBeingFinalized()) {
       return type.Canonicalize(Thread::Current(), nullptr);
     }
-    return type.raw();
+    return type.ptr();
   }
-  ASSERT(finalization >= kFinalize);
 
   if (type.IsTypeRef()) {
     // The referenced type will be finalized later by the code that set the
     // is_being_finalized mark bit.
-    return type.raw();
+    return type.ptr();
+  }
+
+  if (type.IsTypeParameter() && type.IsBeingFinalized()) {
+    // The base and index have already been adjusted, but the bound referring
+    // back to the type parameter is still being finalized.
+    return type.ptr();
   }
 
   // Recursive types must be processed in FinalizeTypeArguments() and cannot be
   // encountered here.
   ASSERT(!type.IsBeingFinalized());
 
-  Zone* zone = Thread::Current()->zone();
+  // Mark the type as being finalized in order to detect self reference.
+  type.SetIsBeingFinalized();
+
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
 
   if (FLAG_trace_type_finalization) {
     THR_Print("Finalizing type '%s'\n",
@@ -686,100 +694,71 @@
     const TypeParameter& type_parameter = TypeParameter::Cast(type);
     const Class& parameterized_class =
         Class::Handle(zone, type_parameter.parameterized_class());
-    intptr_t offset;
+    // The base and index of a function type parameter are eagerly calculated
+    // upon loading and do not require adjustment here.
     if (!parameterized_class.IsNull()) {
       // The index must reflect the position of this type parameter in the type
       // arguments vector of its parameterized class. The offset to add is the
       // number of type arguments in the super type, which is equal to the
       // difference in number of type arguments and type parameters of the
       // parameterized class.
-      offset = parameterized_class.NumTypeArguments() -
-               parameterized_class.NumTypeParameters();
-    } else {
-      const Function& function =
-          Function::Handle(zone, type_parameter.parameterized_function());
-      ASSERT(!function.IsNull());
-      offset = function.NumParentTypeParameters();
+      const intptr_t offset = parameterized_class.NumTypeArguments() -
+                              parameterized_class.NumTypeParameters();
+      type_parameter.set_base(offset);  // Informative, but not needed.
+      type_parameter.set_index(type_parameter.index() + offset);
+
+      // Remove the reference to the parameterized class.
+      type_parameter.set_parameterized_class_id(kClassCid);
     }
-    type_parameter.set_index(type_parameter.index() + offset);
+
+    AbstractType& t = AbstractType::Handle(zone);
+    t = type_parameter.bound();
+    if (!t.IsBeingFinalized()) {
+      t = FinalizeType(t, kFinalize);
+      type_parameter.set_bound(t);
+    }
+    t = type_parameter.default_argument();
+    // The default argument cannot create a cycle with the type parameter.
+    t = FinalizeType(t, kFinalize);
+    type_parameter.set_default_argument(t);
+
     type_parameter.SetIsFinalized();
 
     if (FLAG_trace_type_finalization) {
-      THR_Print("Done finalizing type parameter '%s' with index %" Pd "\n",
-                String::Handle(zone, type_parameter.name()).ToCString(),
+      THR_Print("Done finalizing type parameter at index %" Pd "\n",
                 type_parameter.index());
     }
 
-    if (type_parameter.IsDeclaration()) {
-      // The declaration of a type parameter is canonical.
-      ASSERT(type_parameter.IsCanonical());
-      return type_parameter.raw();
+    if (finalization >= kCanonicalize) {
+      return type_parameter.Canonicalize(thread, nullptr);
     }
-    return type_parameter.Canonicalize(Thread::Current(), nullptr);
+    return type_parameter.ptr();
   }
 
-  // At this point, we can only have a Type.
-  ASSERT(type.IsType());
+  // If the type is a function type, we also need to finalize the types in its
+  // signature, i.e. finalize the result type and parameter types of the
+  // signature function of this function type.
+  if (type.IsFunctionType()) {
+    return FinalizeSignature(zone, FunctionType::Cast(type), finalization,
+                             pending_types);
+  }
 
   // This type is the root type of the type graph if no pending types queue is
-  // allocated yet.
+  // allocated yet. A function type is a collection of types, but not a root.
   const bool is_root_type = pending_types == NULL;
   if (is_root_type) {
     pending_types = new PendingTypes(zone, 4);
   }
 
+  // At this point, we can only have a Type.
+  ASSERT(type.IsType());
+  pending_types->Add(type);
+
   const intptr_t num_expanded_type_arguments =
       ExpandAndFinalizeTypeArguments(type, pending_types);
 
   // Self referencing types may get finalized indirectly.
   if (!type.IsFinalized()) {
-    // If the type is a function type, we also need to finalize the types in its
-    // signature, i.e. finalize the result type and parameter types of the
-    // signature function of this function type.
-    // We do this after marking this type as finalized in order to allow a
-    // typedef function type to refer to itself via its parameter types and
-    // result type.
-    if (type.IsFunctionType()) {
-      const Type& fun_type = Type::Cast(type);
-      const Class& scope_class = Class::Handle(zone, fun_type.type_class());
-      if (scope_class.IsTypedefClass()) {
-        Function& signature =
-            Function::Handle(zone, scope_class.signature_function());
-        if (!scope_class.is_type_finalized()) {
-          FinalizeSignature(signature, finalization);
-        }
-        // If the function type is a generic typedef, instantiate its signature
-        // from its type arguments.
-        // Example: typedef F<T> = S Function<S>(T x) has uninstantiated
-        // signature (T x) => S.
-        // The instantiated signature of F(int) becomes (int x) => S.
-        // Note that after this step, the signature of the function type is not
-        // identical to the canonical signature of the typedef class anymore.
-        if (scope_class.IsGeneric() && !signature.HasInstantiatedSignature()) {
-          if (FLAG_trace_type_finalization) {
-            THR_Print("Instantiating signature '%s' of typedef '%s'\n",
-                      String::Handle(zone, signature.Signature()).ToCString(),
-                      String::Handle(zone, fun_type.Name()).ToCString());
-          }
-          const TypeArguments& instantiator_type_arguments =
-              TypeArguments::Handle(zone, fun_type.arguments());
-          signature = signature.InstantiateSignatureFrom(
-              instantiator_type_arguments, Object::null_type_arguments(),
-              kNoneFree, Heap::kOld);
-          // Note that if instantiator_type_arguments contains type parameters,
-          // as in F<K>, the signature is still uninstantiated (the typedef type
-          // parameters were substituted in the signature with typedef type
-          // arguments). Note also that the function type parameters were not
-          // modified.
-          FinalizeSignature(signature, finalization);
-        }
-        fun_type.set_signature(signature);
-      } else {
-        FinalizeSignature(Function::Handle(zone, fun_type.signature()),
-                          finalization);
-      }
-    }
-
     if (FLAG_trace_type_finalization) {
       THR_Print("Marking type '%s' as finalized\n",
                 String::Handle(zone, type.Name()).ToCString());
@@ -798,108 +777,73 @@
     if (FLAG_trace_type_finalization) {
       THR_Print("Canonicalizing type '%s'\n",
                 String::Handle(zone, type.Name()).ToCString());
-      AbstractType& canonical_type = AbstractType::Handle(
-          zone, type.Canonicalize(Thread::Current(), nullptr));
+      AbstractType& canonical_type =
+          AbstractType::Handle(zone, type.Canonicalize(thread, nullptr));
       THR_Print("Done canonicalizing type '%s'\n",
                 String::Handle(zone, canonical_type.Name()).ToCString());
-      return canonical_type.raw();
+      return canonical_type.ptr();
     }
-    return type.Canonicalize(Thread::Current(), nullptr);
+    return type.Canonicalize(thread, nullptr);
   } else {
-    return type.raw();
+    return type.ptr();
   }
 }
 
-void ClassFinalizer::FinalizeSignature(const Function& function,
-                                       FinalizationKind finalization) {
-  AbstractType& type = AbstractType::Handle();
-  AbstractType& finalized_type = AbstractType::Handle();
-  // Finalize function type parameters, including their bounds and default args.
-  const intptr_t num_parent_type_params = function.NumParentTypeParameters();
-  const intptr_t num_type_params = function.NumTypeParameters();
+AbstractTypePtr ClassFinalizer::FinalizeSignature(Zone* zone,
+                                                  const FunctionType& signature,
+                                                  FinalizationKind finalization,
+                                                  PendingTypes* pending_types) {
+  AbstractType& type = AbstractType::Handle(zone);
+  AbstractType& finalized_type = AbstractType::Handle(zone);
+  // Finalize signature type parameters, their upper bounds and default args.
+  const intptr_t num_type_params = signature.NumTypeParameters();
   if (num_type_params > 0) {
-    TypeParameter& type_param = TypeParameter::Handle();
+    TypeParameter& type_param = TypeParameter::Handle(zone);
     const TypeArguments& type_params =
-        TypeArguments::Handle(function.type_parameters());
+        TypeArguments::Handle(zone, signature.type_parameters());
     for (intptr_t i = 0; i < num_type_params; i++) {
       type_param ^= type_params.TypeAt(i);
-      if (!type_param.IsFinalized()) {
-        ASSERT(type_param.index() == i);
-        type_param.set_index(num_parent_type_params + i);
-        type_param.SetIsFinalized();
-      } else {
-        ASSERT(type_param.index() == num_parent_type_params + i);
-      }
-      // The declaration of a type parameter is canonical.
-      ASSERT(type_param.IsDeclaration());
-      ASSERT(type_param.IsCanonical());
-    }
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type_param ^= type_params.TypeAt(i);
-      type = type_param.bound();
-      finalized_type = FinalizeType(type, finalization);
-      if (finalized_type.raw() != type.raw()) {
-        type_param.set_bound(finalized_type);
-      }
-      type = type_param.default_argument();
-      finalized_type = FinalizeType(type, finalization);
-      if (finalized_type.raw() != type.raw()) {
-        type_param.set_default_argument(finalized_type);
+      finalized_type ^= FinalizeType(type_param, kFinalize, pending_types);
+      if (type_param.ptr() != finalized_type.ptr()) {
+        type_params.SetTypeAt(i, TypeParameter::Cast(finalized_type));
       }
     }
-    function.UpdateCachedDefaultTypeArguments(Thread::Current());
   }
+
   // Finalize result type.
-  type = function.result_type();
-  finalized_type = FinalizeType(type, finalization);
-  if (finalized_type.raw() != type.raw()) {
-    function.set_result_type(finalized_type);
+  type = signature.result_type();
+  finalized_type = FinalizeType(type, kFinalize, pending_types);
+  if (finalized_type.ptr() != type.ptr()) {
+    signature.set_result_type(finalized_type);
   }
   // Finalize formal parameter types.
-  const intptr_t num_parameters = function.NumParameters();
+  const intptr_t num_parameters = signature.NumParameters();
   for (intptr_t i = 0; i < num_parameters; i++) {
-    type = function.ParameterTypeAt(i);
-    finalized_type = FinalizeType(type, finalization);
-    if (type.raw() != finalized_type.raw()) {
-      function.SetParameterTypeAt(i, finalized_type);
+    type = signature.ParameterTypeAt(i);
+    finalized_type = FinalizeType(type, kFinalize, pending_types);
+    if (type.ptr() != finalized_type.ptr()) {
+      signature.SetParameterTypeAt(i, finalized_type);
     }
   }
-}
 
-// Finalize bounds and default arguments of the type parameters of class cls.
-void ClassFinalizer::FinalizeUpperBounds(const Class& cls,
-                                         FinalizationKind finalization) {
-  const intptr_t num_type_params = cls.NumTypeParameters();
-  TypeParameter& type_param = TypeParameter::Handle();
-  AbstractType& type = AbstractType::Handle();
-  const TypeArguments& type_params =
-      TypeArguments::Handle(cls.type_parameters());
-  ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
-         (type_params.Length() == num_type_params));
-  for (intptr_t i = 0; i < num_type_params; i++) {
-    type_param ^= type_params.TypeAt(i);
-    // First, finalize the default argument (no cycles possible here).
-    type = type_param.default_argument();
-    type = FinalizeType(type, finalization);
-    type_param.set_default_argument(type);
-    // Next, finalize the bound.
-    type = type_param.bound();
-    // Bound may be finalized, but not canonical yet.
-    if (type.IsCanonical() || type.IsBeingFinalized()) {
-      // A bound involved in F-bounded quantification may form a cycle.
-      continue;
-    }
-    type = FinalizeType(type, finalization);
-    type_param.set_bound(type);
+  if (FLAG_trace_type_finalization) {
+    THR_Print("Marking function type '%s' as finalized\n",
+              String::Handle(zone, signature.Name()).ToCString());
   }
+  signature.SetIsFinalized();
+
+  if (finalization >= kCanonicalize) {
+    return signature.Canonicalize(Thread::Current(), nullptr);
+  }
+  return signature.ptr();
 }
 
 #if defined(TARGET_ARCH_X64)
 static bool IsPotentialExactGeneric(const AbstractType& type) {
   // TODO(dartbug.com/34170) Investigate supporting this for fields with types
   // that depend on type parameters of the enclosing class.
-  if (type.IsType() && !type.IsFunctionType() && !type.IsDartFunctionType() &&
-      type.IsInstantiated() && !type.IsFutureOrType()) {
+  if (type.IsType() && !type.IsDartFunctionType() && type.IsInstantiated() &&
+      !type.IsFutureOrType()) {
     const Class& cls = Class::Handle(type.type_class());
     return cls.IsGeneric();
   }
@@ -934,13 +878,15 @@
   //   instance method.
 
   // Finalize type of fields and check for conflicts in super classes.
-  Isolate* isolate = Isolate::Current();
+  auto isolate_group = IsolateGroup::Current();
   Zone* zone = Thread::Current()->zone();
   Array& array = Array::Handle(zone, cls.fields());
   Field& field = Field::Handle(zone);
   AbstractType& type = AbstractType::Handle(zone);
+  Function& function = Function::Handle(zone);
+  FunctionType& signature = FunctionType::Handle(zone);
   const intptr_t num_fields = array.Length();
-  const bool track_exactness = isolate->use_field_guards();
+  const bool track_exactness = isolate_group->use_field_guards();
   for (intptr_t i = 0; i < num_fields; i++) {
     field ^= array.At(i);
     type = field.type();
@@ -950,15 +896,24 @@
       field.set_static_type_exactness_state(
           StaticTypeExactnessState::Uninitialized());
     }
+    function = field.InitializerFunction();
+    if (!function.IsNull()) {
+      // TODO(regis): It looks like the initializer is never set at this point.
+      // Remove this finalization code?
+      signature = function.signature();
+      signature ^= FinalizeType(signature);
+      function.set_signature(signature);
+    }
   }
   // Finalize function signatures and check for conflicts in super classes and
   // interfaces.
   array = cls.current_functions();
-  Function& function = Function::Handle(zone);
   const intptr_t num_functions = array.Length();
   for (intptr_t i = 0; i < num_functions; i++) {
     function ^= array.At(i);
-    FinalizeSignature(function);
+    signature = function.signature();
+    signature ^= FinalizeType(signature);
+    function.set_signature(signature);
     if (function.IsSetterFunction() || function.IsImplicitSetterFunction()) {
       continue;
     }
@@ -975,7 +930,7 @@
     return;
   }
 
-  Class& cls = Class::Handle(zone, iface.raw());
+  Class& cls = Class::Handle(zone, iface.ptr());
   AbstractType& type = AbstractType::Handle(zone);
 
   while (!cls.is_implemented()) {
@@ -1011,45 +966,16 @@
     FinalizeTypesInClass(super_class);
   }
   // Finalize type parameters before finalizing the super type.
-  FinalizeTypeParameters(cls);
+  FinalizeTypeParameters(cls, kFinalize);
+  ASSERT(super_class.ptr() == cls.SuperClass());  // Not modified.
   ASSERT(super_class.IsNull() || super_class.is_type_finalized());
-  FinalizeUpperBounds(cls);
+  FinalizeTypeParameters(cls, kCanonicalize);
   // Finalize super type.
   AbstractType& super_type = AbstractType::Handle(cls.super_type());
   if (!super_type.IsNull()) {
     super_type = FinalizeType(super_type);
     cls.set_super_type(super_type);
   }
-  if (cls.IsTypedefClass()) {
-    Function& signature = Function::Handle(cls.signature_function());
-    Type& type = Type::Handle(signature.SignatureType());
-    ASSERT(type.signature() == signature.raw());
-    ASSERT(type.type_class() == cls.raw());
-
-    cls.set_is_type_finalized();
-
-    // Finalize the result and parameter types of the signature
-    // function of this typedef class.
-    FinalizeSignature(signature);  // Does not modify signature type.
-    ASSERT(signature.SignatureType() == type.raw());
-
-    // Finalize the signature type of this typedef.
-    type ^= FinalizeType(type);
-    ASSERT(type.type_class() == cls.raw());
-
-    // If a different canonical signature type is returned, update the signature
-    // function of the typedef.
-    signature = type.signature();
-    signature.SetSignatureType(type);
-    cls.set_signature_function(signature);
-
-    // Closure instances do not refer to this typedef as their class, so there
-    // is no need to add this typedef class to the subclasses of _Closure.
-    ASSERT(super_type.IsNull() || super_type.IsObjectType());
-
-    return;
-  }
-
   // Finalize interface types (but not necessarily interface classes).
   Array& interface_types = Array::Handle(cls.interfaces());
   AbstractType& interface_type = AbstractType::Handle();
@@ -1178,7 +1104,7 @@
     }
 
     Zone* zone = thread->zone();
-    ClassTable* class_table = thread->isolate()->class_table();
+    ClassTable* class_table = thread->isolate_group()->class_table();
     auto& interface_class = Class::Handle(zone);
 
     // We scan every interface this [cls] implements and invalidate all CHA
@@ -1200,7 +1126,6 @@
 
 ErrorPtr ClassFinalizer::LoadClassMembers(const Class& cls) {
   ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
-  ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(!cls.is_finalized());
 
   LongJumpScope jump;
@@ -1252,24 +1177,26 @@
   const Field& sentinel = Field::Handle(
       zone, enum_cls.LookupStaticField(Symbols::_DeletedEnumSentinel()));
   ASSERT(!sentinel.IsNull());
-  sentinel.SetStaticValue(enum_value, true);
+
+  // The static const field contains `Object::null()` instead of
+  // `Object::sentinel()` - so it's not considered an initializing store.
+  sentinel.SetStaticConstFieldValue(enum_value,
+                                    /*assert_initializing_store*/ false);
 
   ASSERT(enum_cls.kernel_offset() > 0);
-  Error& error = Error::Handle(zone);
+  Object& error = Error::Handle(zone);
   for (intptr_t i = 0; i < fields.Length(); i++) {
     field = Field::RawCast(fields.At(i));
     if (!field.is_static() || !field.is_const() ||
-        (sentinel.raw() == field.raw())) {
+        (sentinel.ptr() == field.ptr())) {
       continue;
     }
     // Hot-reload expects the static const fields to be evaluated when
     // performing a reload.
     if (!FLAG_precompiled_mode) {
-      if (field.IsUninitialized()) {
-        error = field.InitializeStatic();
-        if (!error.IsNull()) {
-          ReportError(error);
-        }
+      error = field.StaticConstFieldValue();
+      if (error.IsError()) {
+        ReportError(Error::Cast(error));
       }
     }
   }
@@ -1339,15 +1266,15 @@
 void ClassFinalizer::VerifyImplicitFieldOffsets() {
 #ifdef DEBUG
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
 
-  if (isolate->obfuscate()) {
+  if (isolate_group->obfuscate()) {
     // Field names are obfuscated.
     return;
   }
 
   Zone* zone = thread->zone();
-  const ClassTable& class_table = *(isolate->class_table());
+  const ClassTable& class_table = *(isolate_group->class_table());
   Class& cls = Class::Handle(zone);
   Array& fields_array = Array::Handle(zone);
   Field& field = Field::Handle(zone);
@@ -1380,16 +1307,17 @@
 }
 
 void ClassFinalizer::SortClasses() {
-  Thread* T = Thread::Current();
-  Zone* Z = T->zone();
-  Isolate* I = T->isolate();
+  auto T = Thread::Current();
+  auto Z = T->zone();
+  auto I = T->isolate();
+  auto IG = T->isolate_group();
 
   // Prevent background compiler from adding deferred classes or canonicalizing
   // new types while classes are being sorted and type hashes are modified.
   BackgroundCompiler::Stop(I);
   SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
 
-  ClassTable* table = I->class_table();
+  ClassTable* table = IG->class_table();
   intptr_t num_cids = table->NumCids();
 
   std::unique_ptr<intptr_t[]> old_to_new_cid(new intptr_t[num_cids]);
@@ -1415,7 +1343,7 @@
     if (!cls.is_declaration_loaded()) {
       continue;
     }
-    if (cls.SuperClass() == I->object_store()->object_class()) {
+    if (cls.SuperClass() == IG->object_store()->object_class()) {
       dfs_stack.Add(cid);
     }
   }
@@ -1476,25 +1404,25 @@
   void VisitObject(ObjectPtr obj) {
     if (obj->IsClass()) {
       ClassPtr cls = Class::RawCast(obj);
-      const classid_t old_cid = cls->ptr()->id_;
+      const classid_t old_cid = cls->untag()->id_;
       if (ClassTable::IsTopLevelCid(old_cid)) {
         // We don't remap cids of top level classes.
         return;
       }
-      cls->ptr()->id_ = Map(old_cid);
+      cls->untag()->id_ = Map(old_cid);
     } else if (obj->IsField()) {
       FieldPtr field = Field::RawCast(obj);
-      field->ptr()->guarded_cid_ = Map(field->ptr()->guarded_cid_);
-      field->ptr()->is_nullable_ = Map(field->ptr()->is_nullable_);
+      field->untag()->guarded_cid_ = Map(field->untag()->guarded_cid_);
+      field->untag()->is_nullable_ = Map(field->untag()->is_nullable_);
     } else if (obj->IsTypeParameter()) {
       TypeParameterPtr param = TypeParameter::RawCast(obj);
-      param->ptr()->parameterized_class_id_ =
-          Map(param->ptr()->parameterized_class_id_);
+      param->untag()->parameterized_class_id_ =
+          Map(param->untag()->parameterized_class_id_);
     } else if (obj->IsType()) {
       TypePtr type = Type::RawCast(obj);
-      ObjectPtr id = type->ptr()->type_class_id_;
+      ObjectPtr id = type->untag()->type_class_id_;
       if (!id->IsHeapObject()) {
-        type->ptr()->type_class_id_ =
+        type->untag()->type_class_id_ =
             Smi::New(Map(Smi::Value(Smi::RawCast(id))));
       }
     } else {
@@ -1503,7 +1431,7 @@
       if (old_cid != new_cid) {
         // Don't touch objects that are unchanged. In particular, Instructions,
         // which are write-protected.
-        obj->ptr()->SetClassIdUnsynchronized(new_cid);
+        obj->untag()->SetClassIdUnsynchronized(new_cid);
       }
     }
   }
@@ -1527,12 +1455,11 @@
     IG->ForEachIsolate(
         [&](Isolate* I) {
           I->set_remapping_cids(true);
-
-          // Update the class table. Do it before rewriting cids in headers, as
-          // the heap walkers load an object's size *after* calling the visitor.
-          I->class_table()->Remap(old_to_new_cid);
         },
         /*is_at_safepoint=*/true);
+    // Update the class table. Do it before rewriting cids in headers, as
+    // the heap walkers load an object's size *after* calling the visitor.
+    IG->class_table()->Remap(old_to_new_cid);
 
     // Rewrite cids in headers and cids in Classes, Fields, Types and
     // TypeParameters.
@@ -1544,11 +1471,11 @@
     IG->ForEachIsolate(
         [&](Isolate* I) {
           I->set_remapping_cids(false);
-#if defined(DEBUG)
-          I->class_table()->Validate();
-#endif
         },
         /*is_at_safepoint=*/true);
+#if defined(DEBUG)
+    IG->class_table()->Validate();
+#endif
   }
 
 #if defined(DEBUG)
@@ -1562,34 +1489,37 @@
 // In the Dart VM heap the following instances directly use cids for the
 // computation of canonical hash codes:
 //
-//    * RawType (due to TypeLayout::type_class_id_)
-//    * RawTypeParameter (due to TypeParameterLayout::parameterized_class_id_)
+//    * TypePtr (due to UntaggedType::type_class_id_)
+//    * TypeParameterPtr (due to UntaggedTypeParameter::parameterized_class_id_)
 //
 // The following instances use cids for the computation of canonical hash codes
 // indirectly:
 //
-//    * RawTypeRef (due to TypeRefLayout::type_->type_class_id)
-//    * RawType (due to TypeLayout::signature_'s result/parameter types)
-//    * RawTypeArguments (due to type references)
-//    * RawInstance (due to instance fields)
-//    * RawArray (due to type arguments & array entries)
+//    * TypeRefPtr (due to UntaggedTypeRef::type_->type_class_id)
+//    * TypePtr (due to type arguments)
+//    * FunctionTypePtr (due to the result and parameter types)
+//    * TypeArgumentsPtr (due to type references)
+//    * InstancePtr (due to instance fields)
+//    * ArrayPtr (due to type arguments & array entries)
 //
 // Caching of the canonical hash codes happens for:
 //
-//    * TypeLayout::hash_
-//    * TypeParameterLayout::hash_
-//    * TypeArgumentsLayout::hash_
-//    * RawInstance (weak table)
-//    * RawArray (weak table)
+//    * UntaggedType::hash_
+//    * UntaggedFunctionType::hash_
+//    * UntaggedTypeParameter::hash_
+//    * UntaggedTypeArguments::hash_
+//    * InstancePtr (weak table)
+//    * ArrayPtr (weak table)
 //
 // No caching of canonical hash codes (i.e. it gets re-computed every time)
 // happens for:
 //
-//    * RawTypeRef (computed via TypeRefLayout::type_->type_class_id)
+//    * TypeRefPtr (computed via UntaggedTypeRef::type_->type_class_id)
 //
 // Usages of canonical hash codes are:
 //
 //   * ObjectStore::canonical_types()
+//   * ObjectStore::canonical_function_types()
 //   * ObjectStore::canonical_type_parameters()
 //   * ObjectStore::canonical_type_arguments()
 //   * Class::constants()
@@ -1599,6 +1529,7 @@
   explicit ClearTypeHashVisitor(Zone* zone)
       : type_param_(TypeParameter::Handle(zone)),
         type_(Type::Handle(zone)),
+        function_type_(FunctionType::Handle(zone)),
         type_args_(TypeArguments::Handle(zone)) {}
 
   void VisitObject(ObjectPtr obj) {
@@ -1608,6 +1539,9 @@
     } else if (obj->IsType()) {
       type_ ^= obj;
       type_.SetHash(0);
+    } else if (obj->IsFunctionType()) {
+      function_type_ ^= obj;
+      function_type_.SetHash(0);
     } else if (obj->IsTypeArguments()) {
       type_args_ ^= obj;
       type_args_.SetHash(0);
@@ -1617,23 +1551,25 @@
  private:
   TypeParameter& type_param_;
   Type& type_;
+  FunctionType& function_type_;
   TypeArguments& type_args_;
 };
 
 void ClassFinalizer::RehashTypes() {
-  Thread* T = Thread::Current();
-  Zone* Z = T->zone();
-  Isolate* I = T->isolate();
+  auto T = Thread::Current();
+  auto Z = T->zone();
+  auto I = T->isolate();
+  auto IG = T->isolate_group();
 
   // Clear all cached hash values.
   {
     HeapIterationScope his(T);
     ClearTypeHashVisitor visitor(Z);
-    I->heap()->VisitObjects(&visitor);
+    IG->heap()->VisitObjects(&visitor);
   }
 
   // Rehash the canonical Types table.
-  ObjectStore* object_store = I->object_store();
+  ObjectStore* object_store = IG->object_store();
   Array& types = Array::Handle(Z);
   Type& type = Type::Handle(Z);
   {
@@ -1653,6 +1589,27 @@
   }
   object_store->set_canonical_types(types_table.Release());
 
+  // Rehash the canonical FunctionTypes table.
+  Array& function_types = Array::Handle(Z);
+  FunctionType& function_type = FunctionType::Handle(Z);
+  {
+    CanonicalFunctionTypeSet function_types_table(
+        Z, object_store->canonical_function_types());
+    function_types = HashTables::ToArray(function_types_table, false);
+    function_types_table.Release();
+  }
+
+  dict_size = Utils::RoundUpToPowerOfTwo(function_types.Length() * 4 / 3);
+  CanonicalFunctionTypeSet function_types_table(
+      Z, HashTables::New<CanonicalFunctionTypeSet>(dict_size, Heap::kOld));
+  for (intptr_t i = 0; i < function_types.Length(); i++) {
+    function_type ^= function_types.At(i);
+    bool present = function_types_table.Insert(function_type);
+    // Two recursive types with different topology (and hashes) may be equal.
+    ASSERT(!present || function_type.IsRecursive());
+  }
+  object_store->set_canonical_function_types(function_types_table.Release());
+
   // Rehash the canonical TypeParameters table.
   Array& typeparams = Array::Handle(Z);
   TypeParameter& typeparam = TypeParameter::Handle(Z);
@@ -1704,7 +1661,8 @@
   UNREACHABLE();
 #else
   auto const thread = Thread::Current();
-  auto const isolate = thread->isolate();
+  auto const isolate_group = thread->isolate_group();
+  SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
   StackZone stack_zone(thread);
   HANDLESCOPE(thread);
   auto const zone = thread->zone();
@@ -1734,12 +1692,12 @@
   };
 
   ClearCodeVisitor visitor(zone, including_nonchanging_cids);
-  ProgramVisitor::WalkProgram(zone, isolate, &visitor);
+  ProgramVisitor::WalkProgram(zone, isolate_group, &visitor);
 
   // Apart from normal function code and allocation stubs we have two global
   // code objects to clear.
   if (including_nonchanging_cids) {
-    auto object_store = isolate->object_store();
+    auto object_store = isolate_group->object_store();
     auto& null_code = Code::Handle(zone);
     object_store->set_build_method_extractor_code(null_code);
   }
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index e46d8e5..623bdb5 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -31,10 +31,6 @@
       FinalizationKind finalization = kCanonicalize,
       PendingTypes* pending_types = NULL);
 
-  // Finalize the types in the functions's signature.
-  static void FinalizeSignature(const Function& function,
-                                FinalizationKind finalization = kCanonicalize);
-
   // Return false if we still have classes pending to be finalized.
   static bool AllClassesFinalized();
 
@@ -78,8 +74,17 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
  private:
+  // Finalize the types in the signature and the signature itself.
+  static AbstractTypePtr FinalizeSignature(
+      Zone* zone,
+      const FunctionType& signature,
+      FinalizationKind finalization = kCanonicalize,
+      PendingTypes* pending_types = NULL);
+
   static void AllocateEnumValues(const Class& enum_cls);
-  static void FinalizeTypeParameters(const Class& cls);
+  static void FinalizeTypeParameters(
+      const Class& cls,
+      FinalizationKind finalization = kCanonicalize);
   static intptr_t ExpandAndFinalizeTypeArguments(const AbstractType& type,
                                                  PendingTypes* pending_types);
   static void FinalizeTypeArguments(const Class& cls,
@@ -89,9 +94,6 @@
                                     TrailPtr trail);
   static void CheckRecursiveType(const AbstractType& type,
                                  PendingTypes* pending_types);
-  static void FinalizeUpperBounds(
-      const Class& cls,
-      FinalizationKind finalization = kCanonicalize);
   static void FinalizeMemberTypes(const Class& cls);
   static void PrintClassInformation(const Class& cls);
 
diff --git a/runtime/vm/class_finalizer_test.cc b/runtime/vm/class_finalizer_test.cc
index 7f91581..d51c4cf 100644
--- a/runtime/vm/class_finalizer_test.cc
+++ b/runtime/vm/class_finalizer_test.cc
@@ -20,14 +20,14 @@
   SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   cls.SetFunctions(Object::empty_array());
   cls.SetFields(Object::empty_array());
-  return cls.raw();
+  return cls.ptr();
 }
 
 ISOLATE_UNIT_TEST_CASE(ClassFinalizer) {
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  ObjectStore* object_store = isolate->object_store();
-  const GrowableObjectArray& pending_classes =
+  auto isolate_group = thread->isolate_group();
+  ObjectStore* object_store = isolate_group->object_store();
+  const auto& pending_classes =
       GrowableObjectArray::Handle(zone, object_store->pending_classes());
   GrowableArray<const Class*> classes_1;
   classes_1.Add(&Class::Handle(CreateTestClass("BMW")));
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 8421944..5fb3b61 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -14,7 +14,7 @@
 
 namespace dart {
 
-// Size of the class-id part of the object header. See ObjectLayout.
+// 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)                           \
@@ -22,7 +22,6 @@
   V(PatchClass)                                                                \
   V(Function)                                                                  \
   V(ClosureData)                                                               \
-  V(SignatureData)                                                             \
   V(FfiTrampolineData)                                                         \
   V(Field)                                                                     \
   V(Script)                                                                    \
@@ -58,6 +57,7 @@
   V(TypeArguments)                                                             \
   V(AbstractType)                                                              \
   V(Type)                                                                      \
+  V(FunctionType)                                                              \
   V(TypeRef)                                                                   \
   V(TypeParameter)                                                             \
   V(Closure)                                                                   \
@@ -230,6 +230,7 @@
 bool IsTwoByteStringClassId(intptr_t index);
 bool IsExternalStringClassId(intptr_t index);
 bool IsBuiltinListClassId(intptr_t index);
+bool IsTypeClassId(intptr_t index);
 bool IsTypedDataBaseClassId(intptr_t index);
 bool IsTypedDataClassId(intptr_t index);
 bool IsTypedDataViewClassId(intptr_t index);
@@ -315,6 +316,11 @@
           (index == kByteBufferCid));
 }
 
+inline bool IsTypeClassId(intptr_t index) {
+  // Only Type and FunctionType can be encountered as instance types at runtime.
+  return index == kTypeCid || index == kFunctionTypeCid;
+}
+
 inline bool IsTypedDataBaseClassId(intptr_t index) {
   // Make sure this is updated when new TypedData types are added.
   COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 582ff56..ac501cf 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -32,8 +32,7 @@
         calloc(capacity_, sizeof(RelaxedAtomic<intptr_t>))));
   } else {
     // Duplicate the class table from the VM isolate.
-    auto vm_shared_class_table =
-        Dart::vm_isolate()->group()->shared_class_table();
+    auto vm_shared_class_table = Dart::vm_isolate_group()->shared_class_table();
     capacity_ = vm_shared_class_table->capacity_;
     // Note that [calloc] will zero-initialize the memory.
     RelaxedAtomic<intptr_t>* table = reinterpret_cast<RelaxedAtomic<intptr_t>*>(
@@ -98,7 +97,7 @@
     table_.store(static_cast<ClassPtr*>(calloc(capacity_, sizeof(ClassPtr))));
   } else {
     // Duplicate the class table from the VM isolate.
-    ClassTable* vm_class_table = Dart::vm_isolate()->class_table();
+    ClassTable* vm_class_table = Dart::vm_isolate_group()->class_table();
     capacity_ = vm_class_table->capacity_;
     // Note that [calloc] will zero-initialize the memory.
     ClassPtr* table =
@@ -161,7 +160,7 @@
   // parallel to [ClassTable].
 
   const intptr_t instance_size =
-      cls.is_abstract() ? 0 : Class::host_instance_size(cls.raw());
+      cls.is_abstract() ? 0 : Class::host_instance_size(cls.ptr());
 
   const intptr_t expected_cid =
       shared_class_table_->Register(cid, instance_size);
@@ -169,7 +168,7 @@
   if (cid != kIllegalCid) {
     ASSERT(cid > 0 && cid < kNumPredefinedCids && cid < top_);
     ASSERT(table_.load()[cid] == nullptr);
-    table_.load()[cid] = cls.raw();
+    table_.load()[cid] = cls.ptr();
   } else {
     if (top_ == capacity_) {
       const intptr_t new_capacity = capacity_ + kCapacityIncrement;
@@ -177,7 +176,7 @@
     }
     ASSERT(top_ < capacity_);
     cls.set_id(top_);
-    table_.load()[top_] = cls.raw();
+    table_.load()[top_] = cls.ptr();
     top_++;  // Increment next index.
   }
   ASSERT(expected_cid == cls.id());
@@ -201,7 +200,7 @@
   }
   ASSERT(tlc_top_ < tlc_capacity_);
   cls.set_id(ClassTable::CidFromTopLevelIndex(tlc_top_));
-  tlc_table_.load()[tlc_top_] = cls.raw();
+  tlc_table_.load()[tlc_top_] = cls.ptr();
   tlc_top_++;  // Increment next index.
 }
 
@@ -497,7 +496,7 @@
       continue;
     }
     cls = At(i);
-    if (cls.raw() != nullptr) {
+    if (cls.ptr() != nullptr) {
       name = cls.Name();
       OS::PrintErr("%" Pd ": %s\n", i, name.ToCString());
     }
@@ -524,7 +523,7 @@
   object->AddProperty("type", "ClassList");
   {
     JSONArray members(object, "classes");
-    for (intptr_t i = 1; i < top_; i++) {
+    for (intptr_t i = ClassId::kObjectCid; i < top_; i++) {
       if (HasValidClassAt(i)) {
         cls = At(i);
         members.AddValue(cls);
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 529040e..3660e29 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -25,7 +25,7 @@
 class Isolate;
 class IsolateGroup;
 class IsolateGroupReloadContext;
-class IsolateReloadContext;
+class ProgramReloadContext;
 class JSONArray;
 class JSONObject;
 class JSONStream;
@@ -144,7 +144,7 @@
   }
 
   void ResetBeforeHotReload() {
-    // The [IsolateReloadContext] is now source-of-truth for GC.
+    // The [ProgramReloadContext] is now source-of-truth for GC.
     auto table = table_.load();
     for (intptr_t i = 0; i < top_; i++) {
       // Don't use memset, which changes this from a relaxed atomic operation
@@ -156,7 +156,7 @@
   void ResetAfterHotReload(intptr_t* old_table,
                            intptr_t num_old_cids,
                            bool is_rollback) {
-    // The [IsolateReloadContext] is no longer source-of-truth for GC after we
+    // The [ProgramReloadContext] is no longer source-of-truth for GC after we
     // return, so we restore size information for all classes.
     if (is_rollback) {
       SetNumCids(num_old_cids);
@@ -259,7 +259,7 @@
                            ClassPtr** tlc_copy,
                            intptr_t* copy_num_cids,
                            intptr_t* copy_num_tlc_cids) {
-    // The [IsolateReloadContext] will need to maintain a copy of the old class
+    // The [ProgramReloadContext] will need to maintain a copy of the old class
     // table until instances have been morphed.
     const intptr_t num_cids = NumCids();
     const intptr_t num_tlc_cids = NumTopLevelCids();
@@ -298,7 +298,7 @@
                            intptr_t num_old_cids,
                            intptr_t num_old_tlc_cids,
                            bool is_rollback) {
-    // The [IsolateReloadContext] is no longer source-of-truth for GC after we
+    // The [ProgramReloadContext] is no longer source-of-truth for GC after we
     // return, so we restore size information for all classes.
     if (is_rollback) {
       SetNumCids(num_old_cids, num_old_tlc_cids);
diff --git a/runtime/vm/closure_functions_cache.cc b/runtime/vm/closure_functions_cache.cc
new file mode 100644
index 0000000..e70d6ce
--- /dev/null
+++ b/runtime/vm/closure_functions_cache.cc
@@ -0,0 +1,203 @@
+// 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.
+
+#include "vm/closure_functions_cache.h"
+
+#include "vm/compiler/jit/compiler.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+
+namespace dart {
+
+FunctionPtr ClosureFunctionsCache::LookupClosureFunction(
+    const Class& owner,
+    TokenPosition token_pos) {
+  auto thread = Thread::Current();
+  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
+  return LookupClosureFunctionLocked(owner, token_pos);
+}
+
+FunctionPtr ClosureFunctionsCache::LookupClosureFunctionLocked(
+    const Class& owner,
+    TokenPosition token_pos) {
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
+
+  DEBUG_ASSERT(
+      thread->isolate_group()->program_lock()->IsCurrentThreadReader());
+
+  const auto& closures =
+      GrowableObjectArray::Handle(zone, object_store->closure_functions());
+  auto& closure = Function::Handle(zone);
+  intptr_t num_closures = closures.Length();
+  for (intptr_t i = 0; i < num_closures; i++) {
+    closure ^= closures.At(i);
+    if (closure.token_pos() == token_pos && closure.Owner() == owner.ptr()) {
+      return closure.ptr();
+    }
+  }
+  return Function::null();
+}
+
+FunctionPtr ClosureFunctionsCache::LookupClosureFunction(
+    const Function& parent,
+    TokenPosition token_pos) {
+  auto thread = Thread::Current();
+  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
+  return LookupClosureFunctionLocked(parent, token_pos);
+}
+
+FunctionPtr ClosureFunctionsCache::LookupClosureFunctionLocked(
+    const Function& parent,
+    TokenPosition token_pos) {
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
+
+  DEBUG_ASSERT(
+      thread->isolate_group()->program_lock()->IsCurrentThreadReader());
+
+  const auto& closures =
+      GrowableObjectArray::Handle(zone, object_store->closure_functions());
+  auto& closure = Function::Handle(zone);
+  intptr_t num_closures = closures.Length();
+  for (intptr_t i = 0; i < num_closures; i++) {
+    closure ^= closures.At(i);
+    if (closure.token_pos() == token_pos &&
+        closure.parent_function() == parent.ptr()) {
+      return closure.ptr();
+    }
+  }
+  return Function::null();
+}
+
+void ClosureFunctionsCache::AddClosureFunctionLocked(const Function& function) {
+  ASSERT(!Compiler::IsBackgroundCompilation());
+
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
+
+  DEBUG_ASSERT(
+      thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
+
+  const auto& closures =
+      GrowableObjectArray::Handle(zone, object_store->closure_functions());
+  ASSERT(!closures.IsNull());
+  ASSERT(function.IsNonImplicitClosureFunction());
+  closures.Add(function, Heap::kOld);
+}
+
+intptr_t ClosureFunctionsCache::FindClosureIndex(const Function& needle) {
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
+
+  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
+
+  const auto& closures_array =
+      GrowableObjectArray::Handle(zone, object_store->closure_functions());
+  intptr_t num_closures = closures_array.Length();
+  for (intptr_t i = 0; i < num_closures; i++) {
+    if (closures_array.At(i) == needle.ptr()) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+FunctionPtr ClosureFunctionsCache::ClosureFunctionFromIndex(intptr_t idx) {
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
+
+  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
+
+  const auto& closures_array =
+      GrowableObjectArray::Handle(zone, object_store->closure_functions());
+  if (idx < 0 || idx >= closures_array.Length()) {
+    return Function::null();
+  }
+  return Function::RawCast(closures_array.At(idx));
+}
+
+FunctionPtr ClosureFunctionsCache::GetUniqueInnerClosure(
+    const Function& outer) {
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
+
+  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
+
+  const auto& closures =
+      GrowableObjectArray::Handle(zone, object_store->closure_functions());
+  auto& entry = Function::Handle(zone);
+  for (intptr_t i = (closures.Length() - 1); i >= 0; i--) {
+    entry ^= closures.At(i);
+    if (entry.parent_function() == outer.ptr()) {
+#if defined(DEBUG)
+      auto& other = Function::Handle(zone);
+      for (intptr_t j = i - 1; j >= 0; j--) {
+        other ^= closures.At(j);
+        ASSERT(other.parent_function() != outer.ptr());
+      }
+#endif
+      return entry.ptr();
+    }
+  }
+  return Function::null();
+}
+
+void ClosureFunctionsCache::ForAllClosureFunctions(
+    std::function<bool(const Function&)> callback) {
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
+
+  auto& current_data = Array::Handle(zone);
+  auto& entry = Function::Handle(zone);
+
+  // NOTE: Inner functions may get added to the closures array while iterating -
+  // we guarantee that any closure functions added on this thread by a
+  // [callback] call will be visited as well.
+  //
+  // We avoid holding a lock while accessing the closures array, since often
+  // times [callback] will do very heavy things (e.g. compiling the function).
+  //
+  // This means we can possibly miss a concurrently added closure function -
+  // which the caller should be ok with (or it guarantees that this cannot
+  // happen).
+  const auto& closures =
+      GrowableObjectArray::Handle(zone, object_store->closure_functions());
+
+  {
+    // The empty read locker scope will implicitly issue an acquire memory
+    // fence, which means any closure functions added so far will be visible and
+    // iterated further down.
+    SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
+  }
+
+  // We have an outer loop to ensure any new closure functions added by
+  // [callback] will be iterated as well.
+  intptr_t i = 0;
+  while (true) {
+    intptr_t current_length = closures.Length();
+    if (i == current_length) break;
+
+    current_data = closures.data();
+    if (current_data.Length() < current_length) {
+      current_length = current_data.Length();
+    }
+
+    for (; i < current_length; ++i) {
+      entry ^= current_data.At(i);
+      if (!callback(entry)) {
+        return;  // Stop iteration.
+      }
+    }
+  }
+}
+
+}  // namespace dart
diff --git a/runtime/vm/closure_functions_cache.h b/runtime/vm/closure_functions_cache.h
new file mode 100644
index 0000000..019c12b
--- /dev/null
+++ b/runtime/vm/closure_functions_cache.h
@@ -0,0 +1,72 @@
+// 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.
+
+#ifndef RUNTIME_VM_CLOSURE_FUNCTIONS_CACHE_H_
+#define RUNTIME_VM_CLOSURE_FUNCTIONS_CACHE_H_
+
+#include <functional>
+
+#include "vm/allocation.h"
+#include "vm/token_position.h"
+
+namespace dart {
+
+class Class;
+class Function;
+class FunctionPtr;
+
+// Implementation of cache for inner closure functions.
+//
+// This cache is populated lazily by the compiler: When compiling a function,
+// the flow graph builder will recursively traverse the kernel AST for the
+// function and any inner functions. This will cause the lazy-creation of inner
+// closure functions.
+//
+// The cache is currently implemented as O(n) lookup in a growable list.
+//
+// Parts of the VM have certain requirements that are maintained:
+//
+//   * parent functions need to come before inner functions
+//   * closure functions list can grow while iterating
+//   * the index of closure function must be stable
+//
+// If the linear lookup turns out to be too expensive, the list of closures
+// could be maintained in a hash map, with the key being the token position of
+// the closure. There are almost no collisions with this simple hash value.
+// However, iterating over all closure functions becomes more difficult,
+// especially when the list/map changes while iterating over it (see
+// requirements above).
+class ClosureFunctionsCache : public AllStatic {
+ public:
+  static FunctionPtr LookupClosureFunction(const Class& owner,
+                                           TokenPosition pos);
+  static FunctionPtr LookupClosureFunctionLocked(const Class& owner,
+                                                 TokenPosition pos);
+
+  static FunctionPtr LookupClosureFunction(const Function& parent,
+                                           TokenPosition token_pos);
+  static FunctionPtr LookupClosureFunctionLocked(const Function& parent,
+                                                 TokenPosition token_pos);
+
+  static void AddClosureFunctionLocked(const Function& function);
+
+  static intptr_t FindClosureIndex(const Function& needle);
+  static FunctionPtr ClosureFunctionFromIndex(intptr_t idx);
+
+  static FunctionPtr GetUniqueInnerClosure(const Function& outer);
+
+  // Visits all closure functions registered in the object store.
+  //
+  // Iterates in-order, thereby allowing new closures being added during the
+  // iteration.
+  //
+  // The iteration continues until either [callback] returns `false` or all
+  // closure functions have been visited.
+  static void ForAllClosureFunctions(
+      std::function<bool(const Function&)> callback);
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_CLOSURE_FUNCTIONS_CACHE_H_
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 895f537..12ec76e 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -91,7 +91,7 @@
   if (address == 0) {
     OUT_OF_MEMORY();
   }
-  return ObjectLayout::FromAddr(address);
+  return UntaggedObject::FromAddr(address);
 }
 
 void Deserializer::InitializeHeader(ObjectPtr raw,
@@ -100,14 +100,14 @@
                                     bool is_canonical) {
   ASSERT(Utils::IsAligned(size, kObjectAlignment));
   uword tags = 0;
-  tags = ObjectLayout::ClassIdTag::update(class_id, tags);
-  tags = ObjectLayout::SizeTag::update(size, tags);
-  tags = ObjectLayout::CanonicalBit::update(is_canonical, tags);
-  tags = ObjectLayout::OldBit::update(true, tags);
-  tags = ObjectLayout::OldAndNotMarkedBit::update(true, tags);
-  tags = ObjectLayout::OldAndNotRememberedBit::update(true, tags);
-  tags = ObjectLayout::NewBit::update(false, tags);
-  raw->ptr()->tags_ = tags;
+  tags = UntaggedObject::ClassIdTag::update(class_id, tags);
+  tags = UntaggedObject::SizeTag::update(size, tags);
+  tags = UntaggedObject::CanonicalBit::update(is_canonical, tags);
+  tags = UntaggedObject::OldBit::update(true, tags);
+  tags = UntaggedObject::OldAndNotMarkedBit::update(true, tags);
+  tags = UntaggedObject::OldAndNotRememberedBit::update(true, tags);
+  tags = UntaggedObject::NewBit::update(false, tags);
+  raw->untag()->tags_ = tags;
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -185,7 +185,7 @@
 
   void Trace(Serializer* s, ObjectPtr object) {
     ClassPtr cls = Class::RawCast(object);
-    intptr_t class_id = cls->ptr()->id_;
+    intptr_t class_id = cls->untag()->id_;
 
     if (class_id == kIllegalCid) {
       // Classes expected to be dropped by the precompiler should not be traced.
@@ -211,7 +211,7 @@
       ClassPtr cls = predefined_[i];
       s->AssignRef(cls);
       AutoTraceObject(cls);
-      intptr_t class_id = cls->ptr()->id_;
+      intptr_t class_id = cls->untag()->id_;
       s->WriteCid(class_id);
     }
     count = objects_.length();
@@ -235,28 +235,28 @@
 
  private:
   void WriteClass(Serializer* s, ClassPtr cls) {
-    AutoTraceObjectName(cls, cls->ptr()->name_);
+    AutoTraceObjectName(cls, cls->untag()->name_);
     WriteFromTo(cls);
-    intptr_t class_id = cls->ptr()->id_;
+    intptr_t class_id = cls->untag()->id_;
     if (class_id == kIllegalCid) {
       s->UnexpectedObject(cls, "Class with illegal cid");
     }
     s->WriteCid(class_id);
     if (s->kind() == Snapshot::kFullCore &&
-        RequireLegacyErasureOfConstants(cls)) {
+        RequireCanonicalTypeErasureOfConstants(cls)) {
       s->UnexpectedObject(cls, "Class with non mode agnostic constants");
     }
     if (s->kind() != Snapshot::kFullAOT) {
-      s->Write<uint32_t>(cls->ptr()->kernel_offset_);
+      s->Write<uint32_t>(cls->untag()->kernel_offset_);
     }
     s->Write<int32_t>(Class::target_instance_size_in_words(cls));
     s->Write<int32_t>(Class::target_next_field_offset_in_words(cls));
     s->Write<int32_t>(Class::target_type_arguments_field_offset_in_words(cls));
-    s->Write<int16_t>(cls->ptr()->num_type_arguments_);
-    s->Write<uint16_t>(cls->ptr()->num_native_fields_);
-    s->WriteTokenPosition(cls->ptr()->token_pos_);
-    s->WriteTokenPosition(cls->ptr()->end_token_pos_);
-    s->Write<uint32_t>(cls->ptr()->state_bits_);
+    s->Write<int16_t>(cls->untag()->num_type_arguments_);
+    s->Write<uint16_t>(cls->untag()->num_native_fields_);
+    s->WriteTokenPosition(cls->untag()->token_pos_);
+    s->WriteTokenPosition(cls->untag()->end_token_pos_);
+    s->Write<uint32_t>(cls->untag()->state_bits_);
 
     // In AOT, the bitmap of unboxed fields should also be serialized
     if (FLAG_precompiled_mode && !ClassTable::IsTopLevelCid(class_id)) {
@@ -268,18 +268,18 @@
   GrowableArray<ClassPtr> predefined_;
   GrowableArray<ClassPtr> objects_;
 
-  bool RequireLegacyErasureOfConstants(ClassPtr cls) {
+  bool RequireCanonicalTypeErasureOfConstants(ClassPtr cls) {
     // Do not generate a core snapshot containing constants that would require
-    // a legacy erasure of their types if loaded in an isolate running in weak
-    // mode.
-    if (cls->ptr()->host_type_arguments_field_offset_in_words_ ==
+    // a canonical erasure of their types if loaded in an isolate running in
+    // unsound nullability mode.
+    if (cls->untag()->host_type_arguments_field_offset_in_words_ ==
             Class::kNoTypeArguments ||
-        cls->ptr()->constants_ == Array::null()) {
+        cls->untag()->constants_ == Array::null()) {
       return false;
     }
     Zone* zone = Thread::Current()->zone();
     const Class& clazz = Class::Handle(zone, cls);
-    return clazz.RequireLegacyErasureOfConstants(zone);
+    return clazz.RequireCanonicalTypeErasureOfConstants(zone);
   }
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
@@ -289,11 +289,11 @@
   ClassDeserializationCluster() : DeserializationCluster("Class") {}
   ~ClassDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     predefined_start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     intptr_t count = d->ReadUnsigned();
-    ClassTable* table = d->isolate()->class_table();
+    ClassTable* table = d->isolate_group()->class_table();
     for (intptr_t i = 0; i < count; i++) {
       intptr_t class_id = d->ReadCid();
       ASSERT(table->HasValidClassAt(class_id));
@@ -311,46 +311,46 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
-    ClassTable* table = d->isolate()->class_table();
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ClassTable* table = d->isolate_group()->class_table();
 
     for (intptr_t id = predefined_start_index_; id < predefined_stop_index_;
          id++) {
       ClassPtr cls = static_cast<ClassPtr>(d->Ref(id));
       ReadFromTo(cls);
       intptr_t class_id = d->ReadCid();
-      cls->ptr()->id_ = class_id;
+      cls->untag()->id_ = class_id;
 #if !defined(DART_PRECOMPILED_RUNTIME)
       if (d->kind() != Snapshot::kFullAOT) {
-        cls->ptr()->kernel_offset_ = d->Read<uint32_t>();
+        cls->untag()->kernel_offset_ = d->Read<uint32_t>();
       }
 #endif
       if (!IsInternalVMdefinedClassId(class_id)) {
-        cls->ptr()->host_instance_size_in_words_ = d->Read<int32_t>();
-        cls->ptr()->host_next_field_offset_in_words_ = d->Read<int32_t>();
+        cls->untag()->host_instance_size_in_words_ = d->Read<int32_t>();
+        cls->untag()->host_next_field_offset_in_words_ = d->Read<int32_t>();
 #if !defined(DART_PRECOMPILED_RUNTIME)
         // Only one pair is serialized. The target field only exists when
         // DART_PRECOMPILED_RUNTIME is not defined
-        cls->ptr()->target_instance_size_in_words_ =
-            cls->ptr()->host_instance_size_in_words_;
-        cls->ptr()->target_next_field_offset_in_words_ =
-            cls->ptr()->host_next_field_offset_in_words_;
+        cls->untag()->target_instance_size_in_words_ =
+            cls->untag()->host_instance_size_in_words_;
+        cls->untag()->target_next_field_offset_in_words_ =
+            cls->untag()->host_next_field_offset_in_words_;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
       } else {
         d->Read<int32_t>();  // Skip.
         d->Read<int32_t>();  // Skip.
       }
-      cls->ptr()->host_type_arguments_field_offset_in_words_ =
+      cls->untag()->host_type_arguments_field_offset_in_words_ =
           d->Read<int32_t>();
 #if !defined(DART_PRECOMPILED_RUNTIME)
-      cls->ptr()->target_type_arguments_field_offset_in_words_ =
-          cls->ptr()->host_type_arguments_field_offset_in_words_;
+      cls->untag()->target_type_arguments_field_offset_in_words_ =
+          cls->untag()->host_type_arguments_field_offset_in_words_;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
-      cls->ptr()->num_type_arguments_ = d->Read<int16_t>();
-      cls->ptr()->num_native_fields_ = d->Read<uint16_t>();
-      cls->ptr()->token_pos_ = d->ReadTokenPosition();
-      cls->ptr()->end_token_pos_ = d->ReadTokenPosition();
-      cls->ptr()->state_bits_ = d->Read<uint32_t>();
+      cls->untag()->num_type_arguments_ = d->Read<int16_t>();
+      cls->untag()->num_native_fields_ = d->Read<uint16_t>();
+      cls->untag()->token_pos_ = d->ReadTokenPosition();
+      cls->untag()->end_token_pos_ = d->ReadTokenPosition();
+      cls->untag()->state_bits_ = d->Read<uint32_t>();
 
       if (FLAG_precompiled_mode) {
         d->ReadUnsigned64();  // Skip unboxed fields bitmap.
@@ -365,30 +365,30 @@
 
       intptr_t class_id = d->ReadCid();
       ASSERT(class_id >= kNumPredefinedCids);
-      cls->ptr()->id_ = class_id;
+      cls->untag()->id_ = class_id;
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
       if (d->kind() != Snapshot::kFullAOT) {
-        cls->ptr()->kernel_offset_ = d->Read<uint32_t>();
+        cls->untag()->kernel_offset_ = d->Read<uint32_t>();
       }
 #endif
-      cls->ptr()->host_instance_size_in_words_ = d->Read<int32_t>();
-      cls->ptr()->host_next_field_offset_in_words_ = d->Read<int32_t>();
-      cls->ptr()->host_type_arguments_field_offset_in_words_ =
+      cls->untag()->host_instance_size_in_words_ = d->Read<int32_t>();
+      cls->untag()->host_next_field_offset_in_words_ = d->Read<int32_t>();
+      cls->untag()->host_type_arguments_field_offset_in_words_ =
           d->Read<int32_t>();
 #if !defined(DART_PRECOMPILED_RUNTIME)
-      cls->ptr()->target_instance_size_in_words_ =
-          cls->ptr()->host_instance_size_in_words_;
-      cls->ptr()->target_next_field_offset_in_words_ =
-          cls->ptr()->host_next_field_offset_in_words_;
-      cls->ptr()->target_type_arguments_field_offset_in_words_ =
-          cls->ptr()->host_type_arguments_field_offset_in_words_;
+      cls->untag()->target_instance_size_in_words_ =
+          cls->untag()->host_instance_size_in_words_;
+      cls->untag()->target_next_field_offset_in_words_ =
+          cls->untag()->host_next_field_offset_in_words_;
+      cls->untag()->target_type_arguments_field_offset_in_words_ =
+          cls->untag()->host_type_arguments_field_offset_in_words_;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
-      cls->ptr()->num_type_arguments_ = d->Read<int16_t>();
-      cls->ptr()->num_native_fields_ = d->Read<uint16_t>();
-      cls->ptr()->token_pos_ = d->ReadTokenPosition();
-      cls->ptr()->end_token_pos_ = d->ReadTokenPosition();
-      cls->ptr()->state_bits_ = d->Read<uint32_t>();
+      cls->untag()->num_type_arguments_ = d->Read<int16_t>();
+      cls->untag()->num_native_fields_ = d->Read<uint16_t>();
+      cls->untag()->token_pos_ = d->ReadTokenPosition();
+      cls->untag()->end_token_pos_ = d->ReadTokenPosition();
+      cls->untag()->state_bits_ = d->Read<uint32_t>();
 
       table->AllocateIndex(class_id);
       table->SetAt(class_id, cls);
@@ -415,10 +415,10 @@
     TypeArgumentsPtr type_args = TypeArguments::RawCast(object);
     objects_.Add(type_args);
 
-    s->Push(type_args->ptr()->instantiations_);
-    const intptr_t length = Smi::Value(type_args->ptr()->length_);
+    s->Push(type_args->untag()->instantiations_);
+    const intptr_t length = Smi::Value(type_args->untag()->length_);
     for (intptr_t i = 0; i < length; i++) {
-      s->Push(type_args->ptr()->types()[i]);
+      s->Push(type_args->untag()->types()[i]);
     }
   }
 
@@ -430,7 +430,7 @@
       TypeArgumentsPtr type_args = objects_[i];
       s->AssignRef(type_args);
       AutoTraceObject(type_args);
-      const intptr_t length = Smi::Value(type_args->ptr()->length_);
+      const intptr_t length = Smi::Value(type_args->untag()->length_);
       s->WriteUnsigned(length);
     }
   }
@@ -440,15 +440,15 @@
     for (intptr_t i = 0; i < count; i++) {
       TypeArgumentsPtr type_args = objects_[i];
       AutoTraceObject(type_args);
-      const intptr_t length = Smi::Value(type_args->ptr()->length_);
+      const intptr_t length = Smi::Value(type_args->untag()->length_);
       s->WriteUnsigned(length);
-      intptr_t hash = Smi::Value(type_args->ptr()->hash_);
+      intptr_t hash = Smi::Value(type_args->untag()->hash_);
       s->Write<int32_t>(hash);
-      const intptr_t nullability = Smi::Value(type_args->ptr()->nullability_);
+      const intptr_t nullability = Smi::Value(type_args->untag()->nullability_);
       s->WriteUnsigned(nullability);
       WriteField(type_args, instantiations_);
       for (intptr_t j = 0; j < length; j++) {
-        s->WriteElementRef(type_args->ptr()->types()[j], j);
+        s->WriteElementRef(type_args->untag()->types()[j], j);
       }
     }
   }
@@ -464,7 +464,7 @@
       : DeserializationCluster("TypeArguments") {}
   ~TypeArgumentsDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -476,39 +476,33 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeArgumentsPtr type_args = static_cast<TypeArgumentsPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(type_args, kTypeArgumentsCid,
                                      TypeArguments::InstanceSize(length),
-                                     is_canonical);
-      type_args->ptr()->length_ = Smi::New(length);
-      type_args->ptr()->hash_ = Smi::New(d->Read<int32_t>());
-      type_args->ptr()->nullability_ = Smi::New(d->ReadUnsigned());
-      type_args->ptr()->instantiations_ = static_cast<ArrayPtr>(d->ReadRef());
+                                     stamp_canonical);
+      type_args->untag()->length_ = Smi::New(length);
+      type_args->untag()->hash_ = Smi::New(d->Read<int32_t>());
+      type_args->untag()->nullability_ = Smi::New(d->ReadUnsigned());
+      type_args->untag()->instantiations_ = static_cast<ArrayPtr>(d->ReadRef());
       for (intptr_t j = 0; j < length; j++) {
-        type_args->ptr()->types()[j] =
+        type_args->untag()->types()[j] =
             static_cast<AbstractTypePtr>(d->ReadRef());
       }
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
-      CanonicalTypeArgumentsSet table(
-          d->zone(), d->isolate()->object_store()->canonical_type_arguments());
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize) {
+      Thread* thread = Thread::Current();
       TypeArguments& type_arg = TypeArguments::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         type_arg ^= refs.At(i);
-        ASSERT(type_arg.IsCanonical());
-        bool present = table.Insert(type_arg);
-        // Two recursive types with different topology (and hashes) may be
-        // equal.
-        ASSERT(!present || type_arg.IsRecursive());
+        type_arg = type_arg.Canonicalize(thread, nullptr);
+        refs.SetAt(i, type_arg);
       }
-      d->isolate()->object_store()->set_canonical_type_arguments(
-          table.Release());
     }
   }
 };
@@ -542,7 +536,7 @@
       AutoTraceObject(cls);
       WriteFromTo(cls);
       if (s->kind() != Snapshot::kFullAOT) {
-        s->Write<int32_t>(cls->ptr()->library_kernel_offset_);
+        s->Write<int32_t>(cls->untag()->library_kernel_offset_);
       }
     }
   }
@@ -557,7 +551,7 @@
   PatchClassDeserializationCluster() : DeserializationCluster("PatchClass") {}
   ~PatchClassDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -568,7 +562,8 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       PatchClassPtr cls = static_cast<PatchClassPtr>(d->Ref(id));
       Deserializer::InitializeHeader(cls, kPatchClassCid,
@@ -576,7 +571,7 @@
       ReadFromTo(cls);
 #if !defined(DART_PRECOMPILED_RUNTIME)
       if (d->kind() != Snapshot::kFullAOT) {
-        cls->ptr()->library_kernel_offset_ = d->Read<int32_t>();
+        cls->untag()->library_kernel_offset_ = d->Read<int32_t>();
       }
 #endif
     }
@@ -596,11 +591,11 @@
 
     PushFromTo(func);
     if (kind == Snapshot::kFullAOT) {
-      s->Push(func->ptr()->code_);
+      s->Push(func->untag()->code_);
     } else if (kind == Snapshot::kFullJIT) {
-      NOT_IN_PRECOMPILED(s->Push(func->ptr()->unoptimized_code_));
-      s->Push(func->ptr()->code_);
-      s->Push(func->ptr()->ic_data_array_);
+      NOT_IN_PRECOMPILED(s->Push(func->untag()->unoptimized_code_));
+      s->Push(func->untag()->code_);
+      s->Push(func->untag()->ic_data_array_);
     }
   }
 
@@ -630,13 +625,13 @@
       }
 
       if (kind != Snapshot::kFullAOT) {
-        s->WriteTokenPosition(func->ptr()->token_pos_);
-        s->WriteTokenPosition(func->ptr()->end_token_pos_);
-        s->Write<uint32_t>(func->ptr()->kernel_offset_);
+        s->WriteTokenPosition(func->untag()->token_pos_);
+        s->WriteTokenPosition(func->untag()->end_token_pos_);
+        s->Write<uint32_t>(func->untag()->kernel_offset_);
       }
 
-      s->Write<uint32_t>(func->ptr()->packed_fields_);
-      s->Write<uint32_t>(func->ptr()->kind_tag_);
+      s->Write<uint32_t>(func->untag()->packed_fields_);
+      s->Write<uint32_t>(func->untag()->kind_tag_);
     }
   }
 
@@ -666,7 +661,7 @@
   FunctionDeserializationCluster() : DeserializationCluster("Function") {}
   ~FunctionDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -676,7 +671,8 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     Snapshot::Kind kind = d->kind();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -686,57 +682,57 @@
       ReadFromTo(func);
 
       if (kind == Snapshot::kFullAOT) {
-        func->ptr()->code_ = static_cast<CodePtr>(d->ReadRef());
+        func->untag()->code_ = static_cast<CodePtr>(d->ReadRef());
       } else if (kind == Snapshot::kFullJIT) {
-        NOT_IN_PRECOMPILED(func->ptr()->unoptimized_code_ =
+        NOT_IN_PRECOMPILED(func->untag()->unoptimized_code_ =
                                static_cast<CodePtr>(d->ReadRef()));
-        func->ptr()->code_ = static_cast<CodePtr>(d->ReadRef());
-        func->ptr()->ic_data_array_ = static_cast<ArrayPtr>(d->ReadRef());
+        func->untag()->code_ = static_cast<CodePtr>(d->ReadRef());
+        func->untag()->ic_data_array_ = static_cast<ArrayPtr>(d->ReadRef());
       }
 
 #if defined(DEBUG)
-      func->ptr()->entry_point_ = 0;
-      func->ptr()->unchecked_entry_point_ = 0;
+      func->untag()->entry_point_ = 0;
+      func->untag()->unchecked_entry_point_ = 0;
 #endif
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
       if (kind != Snapshot::kFullAOT) {
-        func->ptr()->token_pos_ = d->ReadTokenPosition();
-        func->ptr()->end_token_pos_ = d->ReadTokenPosition();
-        func->ptr()->kernel_offset_ = d->Read<uint32_t>();
+        func->untag()->token_pos_ = d->ReadTokenPosition();
+        func->untag()->end_token_pos_ = d->ReadTokenPosition();
+        func->untag()->kernel_offset_ = d->Read<uint32_t>();
       }
-      func->ptr()->unboxed_parameters_info_.Reset();
+      func->untag()->unboxed_parameters_info_.Reset();
 #endif
-      func->ptr()->packed_fields_ = d->Read<uint32_t>();
-      func->ptr()->kind_tag_ = d->Read<uint32_t>();
+      func->untag()->packed_fields_ = d->Read<uint32_t>();
+      func->untag()->kind_tag_ = d->Read<uint32_t>();
       if (kind == Snapshot::kFullAOT) {
         // Omit fields used to support de/reoptimization.
       } else {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-        func->ptr()->usage_counter_ = 0;
-        func->ptr()->optimized_instruction_count_ = 0;
-        func->ptr()->optimized_call_site_count_ = 0;
-        func->ptr()->deoptimization_counter_ = 0;
-        func->ptr()->state_bits_ = 0;
-        func->ptr()->inlining_depth_ = 0;
+        func->untag()->usage_counter_ = 0;
+        func->untag()->optimized_instruction_count_ = 0;
+        func->untag()->optimized_call_site_count_ = 0;
+        func->untag()->deoptimization_counter_ = 0;
+        func->untag()->state_bits_ = 0;
+        func->untag()->inlining_depth_ = 0;
 #endif
       }
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
     if (d->kind() == Snapshot::kFullAOT) {
       Function& func = Function::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         func ^= refs.At(i);
-        ASSERT(func.raw()->ptr()->code_->IsCode());
-        uword entry_point = func.raw()->ptr()->code_->ptr()->entry_point_;
+        ASSERT(func.ptr()->untag()->code_->IsCode());
+        uword entry_point = func.ptr()->untag()->code_->untag()->entry_point_;
         ASSERT(entry_point != 0);
-        func.raw()->ptr()->entry_point_ = entry_point;
+        func.ptr()->untag()->entry_point_ = entry_point;
         uword unchecked_entry_point =
-            func.raw()->ptr()->code_->ptr()->unchecked_entry_point_;
+            func.ptr()->untag()->code_->untag()->unchecked_entry_point_;
         ASSERT(unchecked_entry_point != 0);
-        func.raw()->ptr()->unchecked_entry_point_ = unchecked_entry_point;
+        func.ptr()->untag()->unchecked_entry_point_ = unchecked_entry_point;
       }
     } else if (d->kind() == Snapshot::kFullJIT) {
       Function& func = Function::Handle(d->zone());
@@ -745,17 +741,17 @@
         func ^= refs.At(i);
         code = func.CurrentCode();
         if (func.HasCode() && !code.IsDisabled()) {
-          func.SetInstructions(code);  // Set entrypoint.
+          func.SetInstructionsSafe(code);  // Set entrypoint.
           func.SetWasCompiled(true);
         } else {
-          func.ClearCode();  // Set code and entrypoint to lazy compile stub.
+          func.ClearCodeSafe();  // Set code and entrypoint to lazy compile stub
         }
       }
     } else {
       Function& func = Function::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         func ^= refs.At(i);
-        func.ClearCode();  // Set code and entrypoint to lazy compile stub.
+        func.ClearCodeSafe();  // Set code and entrypoint to lazy compile stub.
       }
     }
   }
@@ -772,13 +768,12 @@
     objects_.Add(data);
 
     if (s->kind() != Snapshot::kFullAOT) {
-      s->Push(data->ptr()->context_scope_);
+      s->Push(data->untag()->context_scope_);
     }
-    s->Push(data->ptr()->parent_function_);
-    s->Push(data->ptr()->signature_type_);
-    s->Push(data->ptr()->closure_);
-    s->Push(data->ptr()->default_type_arguments_);
-    s->Push(data->ptr()->default_type_arguments_info_);
+    s->Push(data->untag()->parent_function_);
+    s->Push(data->untag()->closure_);
+    s->Push(data->untag()->default_type_arguments_);
+    s->Push(data->untag()->default_type_arguments_info_);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -800,7 +795,6 @@
         WriteField(data, context_scope_);
       }
       WriteField(data, parent_function_);
-      WriteField(data, signature_type_);
       WriteField(data, closure_);
       WriteField(data, default_type_arguments_);
       WriteField(data, default_type_arguments_info_);
@@ -817,7 +811,7 @@
   ClosureDataDeserializationCluster() : DeserializationCluster("ClosureData") {}
   ~ClosureDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -828,92 +822,29 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ClosureDataPtr data = static_cast<ClosureDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kClosureDataCid,
                                      ClosureData::InstanceSize());
       if (d->kind() == Snapshot::kFullAOT) {
-        data->ptr()->context_scope_ = ContextScope::null();
+        data->untag()->context_scope_ = ContextScope::null();
       } else {
-        data->ptr()->context_scope_ =
+        data->untag()->context_scope_ =
             static_cast<ContextScopePtr>(d->ReadRef());
       }
-      data->ptr()->parent_function_ = static_cast<FunctionPtr>(d->ReadRef());
-      data->ptr()->signature_type_ = static_cast<TypePtr>(d->ReadRef());
-      data->ptr()->closure_ = static_cast<InstancePtr>(d->ReadRef());
-      data->ptr()->default_type_arguments_ =
+      data->untag()->parent_function_ = static_cast<FunctionPtr>(d->ReadRef());
+      data->untag()->closure_ = static_cast<InstancePtr>(d->ReadRef());
+      data->untag()->default_type_arguments_ =
           static_cast<TypeArgumentsPtr>(d->ReadRef());
-      data->ptr()->default_type_arguments_info_ =
+      data->untag()->default_type_arguments_info_ =
           static_cast<SmiPtr>(d->ReadRef());
     }
   }
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-class SignatureDataSerializationCluster : public SerializationCluster {
- public:
-  SignatureDataSerializationCluster() : SerializationCluster("SignatureData") {}
-  ~SignatureDataSerializationCluster() {}
-
-  void Trace(Serializer* s, ObjectPtr object) {
-    SignatureDataPtr data = SignatureData::RawCast(object);
-    objects_.Add(data);
-    PushFromTo(data);
-  }
-
-  void WriteAlloc(Serializer* s) {
-    s->WriteCid(kSignatureDataCid);
-    const intptr_t count = objects_.length();
-    s->WriteUnsigned(count);
-    for (intptr_t i = 0; i < count; i++) {
-      SignatureDataPtr data = objects_[i];
-      s->AssignRef(data);
-    }
-  }
-
-  void WriteFill(Serializer* s) {
-    const intptr_t count = objects_.length();
-    for (intptr_t i = 0; i < count; i++) {
-      SignatureDataPtr data = objects_[i];
-      AutoTraceObject(data);
-      WriteFromTo(data);
-    }
-  }
-
- private:
-  GrowableArray<SignatureDataPtr> objects_;
-};
-#endif  // !DART_PRECOMPILED_RUNTIME
-
-class SignatureDataDeserializationCluster : public DeserializationCluster {
- public:
-  SignatureDataDeserializationCluster()
-      : DeserializationCluster("SignatureData") {}
-  ~SignatureDataDeserializationCluster() {}
-
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
-    start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    const intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, SignatureData::InstanceSize()));
-    }
-    stop_index_ = d->next_index();
-  }
-
-  void ReadFill(Deserializer* d, bool is_canonical) {
-    for (intptr_t id = start_index_; id < stop_index_; id++) {
-      SignatureDataPtr data = static_cast<SignatureDataPtr>(d->Ref(id));
-      Deserializer::InitializeHeader(data, kSignatureDataCid,
-                                     SignatureData::InstanceSize());
-      ReadFromTo(data);
-    }
-  }
-};
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
 class FfiTrampolineDataSerializationCluster : public SerializationCluster {
  public:
   FfiTrampolineDataSerializationCluster()
@@ -943,10 +874,10 @@
       WriteFromTo(data);
 
       if (s->kind() == Snapshot::kFullAOT) {
-        s->WriteUnsigned(data->ptr()->callback_id_);
+        s->WriteUnsigned(data->untag()->callback_id_);
       } else {
         // FFI callbacks can only be written to AOT snapshots.
-        ASSERT(data->ptr()->callback_target_ == Object::null());
+        ASSERT(data->untag()->callback_target_ == Object::null());
       }
     }
   }
@@ -962,7 +893,7 @@
       : DeserializationCluster("FfiTrampolineData") {}
   ~FfiTrampolineDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -973,19 +904,19 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       FfiTrampolineDataPtr data = static_cast<FfiTrampolineDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kFfiTrampolineDataCid,
                                      FfiTrampolineData::InstanceSize());
       ReadFromTo(data);
-      data->ptr()->callback_id_ =
+      data->untag()->callback_id_ =
           d->kind() == Snapshot::kFullAOT ? d->ReadUnsigned() : 0;
     }
   }
 };
 
-
 #if !defined(DART_PRECOMPILED_RUNTIME)
 class FieldSerializationCluster : public SerializationCluster {
  public:
@@ -998,22 +929,22 @@
 
     Snapshot::Kind kind = s->kind();
 
-    s->Push(field->ptr()->name_);
-    s->Push(field->ptr()->owner_);
-    s->Push(field->ptr()->type_);
+    s->Push(field->untag()->name_);
+    s->Push(field->untag()->owner_);
+    s->Push(field->untag()->type_);
     // Write out the initializer function
-    s->Push(field->ptr()->initializer_function_);
+    s->Push(field->untag()->initializer_function_);
 
     if (kind != Snapshot::kFullAOT) {
-      s->Push(field->ptr()->guarded_list_length_);
+      s->Push(field->untag()->guarded_list_length_);
     }
     if (kind == Snapshot::kFullJIT) {
-      s->Push(field->ptr()->dependent_code_);
+      s->Push(field->untag()->dependent_code_);
     }
     // Write out either the initial static value or field offset.
-    if (Field::StaticBit::decode(field->ptr()->kind_bits_)) {
+    if (Field::StaticBit::decode(field->untag()->kind_bits_)) {
       const intptr_t field_id =
-          Smi::Value(field->ptr()->host_offset_or_field_id_);
+          Smi::Value(field->untag()->host_offset_or_field_id_);
       s->Push(s->initial_field_table()->At(field_id));
     } else {
       s->Push(Smi::New(Field::TargetOffsetOf(field)));
@@ -1035,7 +966,7 @@
     const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       FieldPtr field = objects_[i];
-      AutoTraceObjectName(field, field->ptr()->name_);
+      AutoTraceObjectName(field, field->untag()->name_);
 
       WriteField(field, name_);
       WriteField(field, owner_);
@@ -1050,19 +981,19 @@
       }
 
       if (kind != Snapshot::kFullAOT) {
-        s->WriteTokenPosition(field->ptr()->token_pos_);
-        s->WriteTokenPosition(field->ptr()->end_token_pos_);
-        s->WriteCid(field->ptr()->guarded_cid_);
-        s->WriteCid(field->ptr()->is_nullable_);
-        s->Write<int8_t>(field->ptr()->static_type_exactness_state_);
-        s->Write<uint32_t>(field->ptr()->kernel_offset_);
+        s->WriteTokenPosition(field->untag()->token_pos_);
+        s->WriteTokenPosition(field->untag()->end_token_pos_);
+        s->WriteCid(field->untag()->guarded_cid_);
+        s->WriteCid(field->untag()->is_nullable_);
+        s->Write<int8_t>(field->untag()->static_type_exactness_state_);
+        s->Write<uint32_t>(field->untag()->kernel_offset_);
       }
-      s->Write<uint16_t>(field->ptr()->kind_bits_);
+      s->Write<uint16_t>(field->untag()->kind_bits_);
 
       // Write out either the initial static value or field offset.
-      if (Field::StaticBit::decode(field->ptr()->kind_bits_)) {
+      if (Field::StaticBit::decode(field->untag()->kind_bits_)) {
         const intptr_t field_id =
-            Smi::Value(field->ptr()->host_offset_or_field_id_);
+            Smi::Value(field->untag()->host_offset_or_field_id_);
         WriteFieldValue("static value", s->initial_field_table()->At(field_id));
         s->WriteUnsigned(field_id);
       } else {
@@ -1081,7 +1012,7 @@
   FieldDeserializationCluster() : DeserializationCluster("Field") {}
   ~FieldDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1091,7 +1022,8 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     Snapshot::Kind kind = d->kind();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -1099,42 +1031,57 @@
       Deserializer::InitializeHeader(field, kFieldCid, Field::InstanceSize());
       ReadFromTo(field);
       if (kind != Snapshot::kFullAOT) {
-        field->ptr()->guarded_list_length_ = static_cast<SmiPtr>(d->ReadRef());
+        field->untag()->guarded_list_length_ =
+            static_cast<SmiPtr>(d->ReadRef());
       }
       if (kind == Snapshot::kFullJIT) {
-        field->ptr()->dependent_code_ = static_cast<ArrayPtr>(d->ReadRef());
+        field->untag()->dependent_code_ = static_cast<ArrayPtr>(d->ReadRef());
       }
       if (kind != Snapshot::kFullAOT) {
-        field->ptr()->token_pos_ = d->ReadTokenPosition();
-        field->ptr()->end_token_pos_ = d->ReadTokenPosition();
-        field->ptr()->guarded_cid_ = d->ReadCid();
-        field->ptr()->is_nullable_ = d->ReadCid();
-        field->ptr()->static_type_exactness_state_ = d->Read<int8_t>();
+        field->untag()->token_pos_ = d->ReadTokenPosition();
+        field->untag()->end_token_pos_ = d->ReadTokenPosition();
+        field->untag()->guarded_cid_ = d->ReadCid();
+        field->untag()->is_nullable_ = d->ReadCid();
+        const int8_t static_type_exactness_state = d->Read<int8_t>();
+#if defined(TARGET_ARCH_X64)
+        field->untag()->static_type_exactness_state_ =
+            static_type_exactness_state;
+#else
+        // We might produce core snapshots using X64 VM and then consume
+        // them in IA32 or ARM VM. In which case we need to simply ignore
+        // static type exactness state written into snapshot because non-X64
+        // builds don't have this feature enabled.
+        // TODO(dartbug.com/34170) Support other architectures.
+        USE(static_type_exactness_state);
+        field->untag()->static_type_exactness_state_ =
+            StaticTypeExactnessState::NotTracking().Encode();
+#endif  // defined(TARGET_ARCH_X64)
 #if !defined(DART_PRECOMPILED_RUNTIME)
-        field->ptr()->kernel_offset_ = d->Read<uint32_t>();
+        field->untag()->kernel_offset_ = d->Read<uint32_t>();
 #endif
       }
-      field->ptr()->kind_bits_ = d->Read<uint16_t>();
+      field->untag()->kind_bits_ = d->Read<uint16_t>();
 
       ObjectPtr value_or_offset = d->ReadRef();
-      if (Field::StaticBit::decode(field->ptr()->kind_bits_)) {
+      if (Field::StaticBit::decode(field->untag()->kind_bits_)) {
         const intptr_t field_id = d->ReadUnsigned();
         d->initial_field_table()->SetAt(
             field_id, static_cast<InstancePtr>(value_or_offset));
-        field->ptr()->host_offset_or_field_id_ = Smi::New(field_id);
+        field->untag()->host_offset_or_field_id_ = Smi::New(field_id);
       } else {
-        field->ptr()->host_offset_or_field_id_ = Smi::RawCast(value_or_offset);
+        field->untag()->host_offset_or_field_id_ =
+            Smi::RawCast(value_or_offset);
 #if !defined(DART_PRECOMPILED_RUNTIME)
-        field->ptr()->target_offset_ =
-            Smi::Value(field->ptr()->host_offset_or_field_id_);
+        field->untag()->target_offset_ =
+            Smi::Value(field->untag()->host_offset_or_field_id_);
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
       }
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
     Field& field = Field::Handle(d->zone());
-    if (!Isolate::Current()->use_field_guards()) {
+    if (!IsolateGroup::Current()->use_field_guards()) {
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         field ^= refs.At(i);
         field.set_guarded_cid_unsafe(kDynamicCid);
@@ -1180,12 +1127,21 @@
     const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       ScriptPtr script = objects_[i];
-      AutoTraceObjectName(script, script->ptr()->url_);
+      AutoTraceObjectName(script, script->untag()->url_);
       WriteFromTo(script);
-      s->Write<int32_t>(script->ptr()->line_offset_);
-      s->Write<int32_t>(script->ptr()->col_offset_);
-      s->Write<uint8_t>(script->ptr()->flags_);
-      s->Write<int32_t>(script->ptr()->kernel_script_index_);
+      s->Write<int32_t>(script->untag()->line_offset_);
+      s->Write<int32_t>(script->untag()->col_offset_);
+      if (s->kind() != Snapshot::kFullAOT) {
+        // Clear out the max position cache in snapshots to ensure no
+        // differences in the snapshot due to triggering caching vs. not.
+        int32_t written_flags =
+            UntaggedScript::CachedMaxPositionBitField::update(
+                0, script->untag()->flags_and_max_position_);
+        written_flags = UntaggedScript::HasCachedMaxPositionBit::update(
+            false, written_flags);
+        s->Write<int32_t>(written_flags);
+      }
+      s->Write<int32_t>(script->untag()->kernel_script_index_);
     }
   }
 
@@ -1199,7 +1155,7 @@
   ScriptDeserializationCluster() : DeserializationCluster("Script") {}
   ~ScriptDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1209,17 +1165,20 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ScriptPtr script = static_cast<ScriptPtr>(d->Ref(id));
       Deserializer::InitializeHeader(script, kScriptCid,
                                      Script::InstanceSize());
       ReadFromTo(script);
-      script->ptr()->line_offset_ = d->Read<int32_t>();
-      script->ptr()->col_offset_ = d->Read<int32_t>();
-      script->ptr()->flags_ = d->Read<uint8_t>();
-      script->ptr()->kernel_script_index_ = d->Read<int32_t>();
-      script->ptr()->load_timestamp_ = 0;
+      script->untag()->line_offset_ = d->Read<int32_t>();
+      script->untag()->col_offset_ = d->Read<int32_t>();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+      script->untag()->flags_and_max_position_ = d->Read<int32_t>();
+#endif
+      script->untag()->kernel_script_index_ = d->Read<int32_t>();
+      script->untag()->load_timestamp_ = 0;
     }
   }
 };
@@ -1250,14 +1209,14 @@
     const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       LibraryPtr lib = objects_[i];
-      AutoTraceObjectName(lib, lib->ptr()->url_);
+      AutoTraceObjectName(lib, lib->untag()->url_);
       WriteFromTo(lib);
-      s->Write<int32_t>(lib->ptr()->index_);
-      s->Write<uint16_t>(lib->ptr()->num_imports_);
-      s->Write<int8_t>(lib->ptr()->load_state_);
-      s->Write<uint8_t>(lib->ptr()->flags_);
+      s->Write<int32_t>(lib->untag()->index_);
+      s->Write<uint16_t>(lib->untag()->num_imports_);
+      s->Write<int8_t>(lib->untag()->load_state_);
+      s->Write<uint8_t>(lib->untag()->flags_);
       if (s->kind() != Snapshot::kFullAOT) {
-        s->Write<uint32_t>(lib->ptr()->kernel_offset_);
+        s->Write<uint32_t>(lib->untag()->kernel_offset_);
       }
     }
   }
@@ -1272,7 +1231,7 @@
   LibraryDeserializationCluster() : DeserializationCluster("Library") {}
   ~LibraryDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1282,21 +1241,22 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LibraryPtr lib = static_cast<LibraryPtr>(d->Ref(id));
       Deserializer::InitializeHeader(lib, kLibraryCid, Library::InstanceSize());
       ReadFromTo(lib);
-      lib->ptr()->native_entry_resolver_ = NULL;
-      lib->ptr()->native_entry_symbol_resolver_ = NULL;
-      lib->ptr()->index_ = d->Read<int32_t>();
-      lib->ptr()->num_imports_ = d->Read<uint16_t>();
-      lib->ptr()->load_state_ = d->Read<int8_t>();
-      lib->ptr()->flags_ =
-          LibraryLayout::InFullSnapshotBit::update(true, d->Read<uint8_t>());
+      lib->untag()->native_entry_resolver_ = NULL;
+      lib->untag()->native_entry_symbol_resolver_ = NULL;
+      lib->untag()->index_ = d->Read<int32_t>();
+      lib->untag()->num_imports_ = d->Read<uint16_t>();
+      lib->untag()->load_state_ = d->Read<int8_t>();
+      lib->untag()->flags_ =
+          UntaggedLibrary::InFullSnapshotBit::update(true, d->Read<uint8_t>());
 #if !defined(DART_PRECOMPILED_RUNTIME)
       if (d->kind() != Snapshot::kFullAOT) {
-        lib->ptr()->kernel_offset_ = d->Read<uint32_t>();
+        lib->untag()->kernel_offset_ = d->Read<uint32_t>();
       }
 #endif
     }
@@ -1344,7 +1304,7 @@
   NamespaceDeserializationCluster() : DeserializationCluster("Namespace") {}
   ~NamespaceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1354,7 +1314,8 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       NamespacePtr ns = static_cast<NamespacePtr>(d->Ref(id));
       Deserializer::InitializeHeader(ns, kNamespaceCid,
@@ -1394,7 +1355,7 @@
       KernelProgramInfoPtr info = objects_[i];
       AutoTraceObject(info);
       WriteFromTo(info);
-      s->Write<uint32_t>(info->ptr()->kernel_binary_version_);
+      s->Write<uint32_t>(info->untag()->kernel_binary_version_);
     }
   }
 
@@ -1410,7 +1371,7 @@
       : DeserializationCluster("KernelProgramInfo") {}
   ~KernelProgramInfoDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1421,17 +1382,18 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       KernelProgramInfoPtr info = static_cast<KernelProgramInfoPtr>(d->Ref(id));
       Deserializer::InitializeHeader(info, kKernelProgramInfoCid,
                                      KernelProgramInfo::InstanceSize());
       ReadFromTo(info);
-      info->ptr()->kernel_binary_version_ = d->Read<uint32_t>();
+      info->untag()->kernel_binary_version_ = d->Read<uint32_t>();
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
     Array& array = Array::Handle(d->zone());
     KernelProgramInfo& info = KernelProgramInfo::Handle(d->zone());
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -1457,28 +1419,45 @@
       objects_.Add(code);
     }
 
-    if (!(s->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions)) {
-      s->Push(code->ptr()->object_pool_);
+    if (s->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions) {
+      if (FLAG_retain_function_objects) {
+        ObjectPoolPtr pool = code->untag()->object_pool_;
+        if ((pool != ObjectPool::null()) && s->InCurrentLoadingUnit(code)) {
+          const intptr_t length = pool->untag()->length_;
+          uint8_t* entry_bits = pool->untag()->entry_bits();
+          for (intptr_t i = 0; i < length; i++) {
+            auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
+            if (entry_type == ObjectPool::EntryType::kTaggedObject) {
+              s->Push(pool->untag()->data()[i].raw_obj_);
+            }
+          }
+        }
+      }
+    } else {
+      if (s->InCurrentLoadingUnit(code->untag()->object_pool_)) {
+        s->Push(code->untag()->object_pool_);
+      }
     }
-    s->Push(code->ptr()->owner_);
-    s->Push(code->ptr()->exception_handlers_);
-    s->Push(code->ptr()->pc_descriptors_);
-    s->Push(code->ptr()->catch_entry_);
-    if (s->InCurrentLoadingUnit(code->ptr()->compressed_stackmaps_)) {
-      s->Push(code->ptr()->compressed_stackmaps_);
+
+    s->Push(code->untag()->owner_);
+    s->Push(code->untag()->exception_handlers_);
+    s->Push(code->untag()->pc_descriptors_);
+    s->Push(code->untag()->catch_entry_);
+    if (s->InCurrentLoadingUnit(code->untag()->compressed_stackmaps_)) {
+      s->Push(code->untag()->compressed_stackmaps_);
     }
     if (!FLAG_precompiled_mode || !FLAG_dwarf_stack_traces_mode) {
-      s->Push(code->ptr()->inlined_id_to_function_);
-      if (s->InCurrentLoadingUnit(code->ptr()->code_source_map_)) {
-        s->Push(code->ptr()->code_source_map_);
+      s->Push(code->untag()->inlined_id_to_function_);
+      if (s->InCurrentLoadingUnit(code->untag()->code_source_map_)) {
+        s->Push(code->untag()->code_source_map_);
       }
     }
     if (s->kind() == Snapshot::kFullJIT) {
-      s->Push(code->ptr()->deopt_info_array_);
-      s->Push(code->ptr()->static_calls_target_table_);
+      s->Push(code->untag()->deopt_info_array_);
+      s->Push(code->untag()->static_calls_target_table_);
     } else if (s->kind() == Snapshot::kFullAOT) {
 #if defined(DART_PRECOMPILER)
-      auto const calls_array = code->ptr()->static_calls_target_table_;
+      auto const calls_array = code->untag()->static_calls_target_table_;
       if (calls_array != Array::null()) {
         // Some Code entries in the static calls target table may only be
         // accessible via here, so push the Code objects.
@@ -1507,9 +1486,9 @@
 #endif
     }
 #if !defined(PRODUCT)
-    s->Push(code->ptr()->return_address_metadata_);
+    s->Push(code->untag()->return_address_metadata_);
     if (FLAG_code_comments) {
-      s->Push(code->ptr()->comments_);
+      s->Push(code->untag()->comments_);
     }
 #endif
   }
@@ -1529,7 +1508,7 @@
   static void Insert(GrowableArray<CodeOrderInfo>* order_list,
                      IntMap<intptr_t>* order_map,
                      CodePtr code) {
-    InstructionsPtr instr = code->ptr()->instructions_;
+    InstructionsPtr instr = code->untag()->instructions_;
     intptr_t key = static_cast<intptr_t>(instr);
     intptr_t order;
     if (order_map->HasKey(key)) {
@@ -1561,7 +1540,7 @@
     GrowableArray<CodeOrderInfo> order_list;
     IntMap<intptr_t> order_map;
     for (intptr_t i = 0; i < codes->length(); i++) {
-      Insert(&order_list, &order_map, (*codes)[i]->raw());
+      Insert(&order_list, &order_map, (*codes)[i]->ptr());
     }
     order_list.Sort(CompareCodeOrderInfo);
     ASSERT(order_list.length() == codes->length());
@@ -1571,20 +1550,6 @@
   }
 
   void WriteAlloc(Serializer* s) {
-    Sort(&objects_);
-    auto loading_units = s->loading_units();
-    if (loading_units != nullptr) {
-      for (intptr_t i = LoadingUnit::kRootId + 1; i < loading_units->length();
-           i++) {
-        auto unit_objects = loading_units->At(i)->deferred_objects();
-        Sort(unit_objects);
-        for (intptr_t j = 0; j < unit_objects->length(); j++) {
-          deferred_objects_.Add(unit_objects->At(j)->raw());
-        }
-      }
-    }
-    s->PrepareInstructions(&objects_);
-
     s->WriteCid(kCodeCid);
     const intptr_t count = objects_.length();
     s->WriteUnsigned(count);
@@ -1621,7 +1586,7 @@
     AutoTraceObjectName(code, MakeDisambiguatedCodeName(s, code));
 
     intptr_t pointer_offsets_length =
-        Code::PtrOffBits::decode(code->ptr()->state_bits_);
+        Code::PtrOffBits::decode(code->untag()->state_bits_);
     if (pointer_offsets_length != 0) {
       FATAL("Cannot serialize code with embedded pointers");
     }
@@ -1630,34 +1595,38 @@
       s->UnexpectedObject(code, "Disabled code");
     }
 
-    s->WriteInstructions(code->ptr()->instructions_,
-                         code->ptr()->unchecked_offset_, code, deferred);
+    s->WriteInstructions(code->untag()->instructions_,
+                         code->untag()->unchecked_offset_, code, deferred);
     if (kind == Snapshot::kFullJIT) {
       // TODO(rmacnak): Fix references to disabled code before serializing.
       // For now, we may write the FixCallersTarget or equivalent stub. This
       // will cause a fixup if this code is called.
       const uint32_t active_unchecked_offset =
-          code->ptr()->unchecked_entry_point_ - code->ptr()->entry_point_;
-      s->WriteInstructions(code->ptr()->active_instructions_,
+          code->untag()->unchecked_entry_point_ - code->untag()->entry_point_;
+      s->WriteInstructions(code->untag()->active_instructions_,
                            active_unchecked_offset, code, deferred);
     }
 
     // No need to write object pool out if we are producing full AOT
     // snapshot with bare instructions.
     if (!(kind == Snapshot::kFullAOT && FLAG_use_bare_instructions)) {
-      WriteField(code, object_pool_);
+      if (s->InCurrentLoadingUnit(code->untag()->object_pool_)) {
+        WriteField(code, object_pool_);
+      } else {
+        WriteFieldValue(object_pool_, ObjectPool::null());
+      }
 #if defined(DART_PRECOMPILER)
     } else if (FLAG_write_v8_snapshot_profile_to != nullptr &&
-               code->ptr()->object_pool_ != ObjectPool::null()) {
+               code->untag()->object_pool_ != ObjectPool::null()) {
       // If we are writing V8 snapshot profile then attribute references
       // going through the object pool to the code object itself.
-      ObjectPoolPtr pool = code->ptr()->object_pool_;
+      ObjectPoolPtr pool = code->untag()->object_pool_;
 
-      for (intptr_t i = 0; i < pool->ptr()->length_; i++) {
-        uint8_t bits = pool->ptr()->entry_bits()[i];
+      for (intptr_t i = 0; i < pool->untag()->length_; i++) {
+        uint8_t bits = pool->untag()->entry_bits()[i];
         if (ObjectPool::TypeBits::decode(bits) ==
             ObjectPool::EntryType::kTaggedObject) {
-          s->AttributeElementRef(pool->ptr()->data()[i].raw_obj_, i);
+          s->AttributeElementRef(pool->untag()->data()[i].raw_obj_, i);
         }
       }
 #endif  // defined(DART_PRECOMPILER)
@@ -1666,7 +1635,7 @@
     WriteField(code, exception_handlers_);
     WriteField(code, pc_descriptors_);
     WriteField(code, catch_entry_);
-    if (s->InCurrentLoadingUnit(code->ptr()->compressed_stackmaps_)) {
+    if (s->InCurrentLoadingUnit(code->untag()->compressed_stackmaps_)) {
       WriteField(code, compressed_stackmaps_);
     } else {
       WriteFieldValue(compressed_stackmaps_, CompressedStackMaps::null());
@@ -1676,7 +1645,7 @@
       WriteFieldValue(code_source_map_, CodeSourceMap::null());
     } else {
       WriteField(code, inlined_id_to_function_);
-      if (s->InCurrentLoadingUnit(code->ptr()->code_source_map_)) {
+      if (s->InCurrentLoadingUnit(code->untag()->code_source_map_)) {
         WriteField(code, code_source_map_);
       } else {
         WriteFieldValue(code_source_map_, CodeSourceMap::null());
@@ -1689,12 +1658,12 @@
 
 #if defined(DART_PRECOMPILER)
     if (FLAG_write_v8_snapshot_profile_to != nullptr &&
-        code->ptr()->static_calls_target_table_ != Array::null()) {
+        code->untag()->static_calls_target_table_ != Array::null()) {
       // If we are writing V8 snapshot profile then attribute references
       // going through static calls.
-      array_ = code->ptr()->static_calls_target_table_;
-      intptr_t index = code->ptr()->object_pool_ != ObjectPool::null()
-                           ? code->ptr()->object_pool_->ptr()->length_
+      array_ = code->untag()->static_calls_target_table_;
+      intptr_t index = code->untag()->object_pool_ != ObjectPool::null()
+                           ? code->untag()->object_pool_->untag()->length_
                            : 0;
       for (auto entry : StaticCallsTable(array_)) {
         auto kind = Code::KindField::decode(
@@ -1723,10 +1692,11 @@
       WriteField(code, comments_);
     }
 #endif
-    s->Write<int32_t>(code->ptr()->state_bits_);
+    s->Write<int32_t>(code->untag()->state_bits_);
   }
 
-  GrowableArray<CodePtr>* discovered_objects() { return &objects_; }
+  GrowableArray<CodePtr>* objects() { return &objects_; }
+  GrowableArray<CodePtr>* deferred_objects() { return &deferred_objects_; }
 
   // Some code objects would have their owners dropped from the snapshot,
   // which makes it is impossible to recover program structure when
@@ -1737,7 +1707,8 @@
     ASSERT(s->profile_writer() != nullptr);
 
     for (auto code : objects_) {
-      ObjectPtr owner = WeakSerializationReference::Unwrap(code->ptr()->owner_);
+      ObjectPtr owner =
+          WeakSerializationReference::Unwrap(code->untag()->owner_);
       if (s->CreateArtificalNodeIfNeeded(owner)) {
         AutoTraceObject(code);
         s->AttributePropertyRef(owner, ":owner_",
@@ -1771,7 +1742,7 @@
   CodeDeserializationCluster() : DeserializationCluster("Code") {}
   ~CodeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     PageSpace* old_space = d->heap()->old_space();
     start_index_ = d->next_index();
     const intptr_t count = d->ReadUnsigned();
@@ -1789,7 +1760,8 @@
     deferred_stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ReadFill(d, id, false);
     }
@@ -1807,41 +1779,44 @@
     // There would be a single global pool if this is a full AOT snapshot
     // with bare instructions.
     if (!(d->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions)) {
-      code->ptr()->object_pool_ = static_cast<ObjectPoolPtr>(d->ReadRef());
+      code->untag()->object_pool_ = static_cast<ObjectPoolPtr>(d->ReadRef());
     } else {
-      code->ptr()->object_pool_ = ObjectPool::null();
+      code->untag()->object_pool_ = ObjectPool::null();
     }
-    code->ptr()->owner_ = d->ReadRef();
-    code->ptr()->exception_handlers_ =
+    code->untag()->owner_ = d->ReadRef();
+    code->untag()->exception_handlers_ =
         static_cast<ExceptionHandlersPtr>(d->ReadRef());
-    code->ptr()->pc_descriptors_ = static_cast<PcDescriptorsPtr>(d->ReadRef());
-    code->ptr()->catch_entry_ = d->ReadRef();
-    code->ptr()->compressed_stackmaps_ =
+    code->untag()->pc_descriptors_ =
+        static_cast<PcDescriptorsPtr>(d->ReadRef());
+    code->untag()->catch_entry_ = d->ReadRef();
+    code->untag()->compressed_stackmaps_ =
         static_cast<CompressedStackMapsPtr>(d->ReadRef());
-    code->ptr()->inlined_id_to_function_ = static_cast<ArrayPtr>(d->ReadRef());
-    code->ptr()->code_source_map_ = static_cast<CodeSourceMapPtr>(d->ReadRef());
+    code->untag()->inlined_id_to_function_ =
+        static_cast<ArrayPtr>(d->ReadRef());
+    code->untag()->code_source_map_ =
+        static_cast<CodeSourceMapPtr>(d->ReadRef());
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
     if (d->kind() == Snapshot::kFullJIT) {
-      code->ptr()->deopt_info_array_ = static_cast<ArrayPtr>(d->ReadRef());
-      code->ptr()->static_calls_target_table_ =
+      code->untag()->deopt_info_array_ = static_cast<ArrayPtr>(d->ReadRef());
+      code->untag()->static_calls_target_table_ =
           static_cast<ArrayPtr>(d->ReadRef());
     }
 #endif  // !DART_PRECOMPILED_RUNTIME
 
 #if !defined(PRODUCT)
-    code->ptr()->return_address_metadata_ = d->ReadRef();
-    code->ptr()->var_descriptors_ = LocalVarDescriptors::null();
-    code->ptr()->comments_ = FLAG_code_comments
-                                 ? static_cast<ArrayPtr>(d->ReadRef())
-                                 : Array::null();
-    code->ptr()->compile_timestamp_ = 0;
+    code->untag()->return_address_metadata_ = d->ReadRef();
+    code->untag()->var_descriptors_ = LocalVarDescriptors::null();
+    code->untag()->comments_ = FLAG_code_comments
+                                   ? static_cast<ArrayPtr>(d->ReadRef())
+                                   : Array::null();
+    code->untag()->compile_timestamp_ = 0;
 #endif
 
-    code->ptr()->state_bits_ = d->Read<int32_t>();
+    code->untag()->state_bits_ = d->Read<int32_t>();
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
     d->EndInstructions(refs, start_index_, stop_index_);
 
 #if !defined(PRODUCT)
@@ -1889,12 +1864,17 @@
     ObjectPoolPtr pool = ObjectPool::RawCast(object);
     objects_.Add(pool);
 
-    const intptr_t length = pool->ptr()->length_;
-    uint8_t* entry_bits = pool->ptr()->entry_bits();
-    for (intptr_t i = 0; i < length; i++) {
-      auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
-      if (entry_type == ObjectPool::EntryType::kTaggedObject) {
-        s->Push(pool->ptr()->data()[i].raw_obj_);
+    if (s->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions &&
+        FLAG_retain_function_objects) {
+      // Treat pool as weak.
+    } else {
+      const intptr_t length = pool->untag()->length_;
+      uint8_t* entry_bits = pool->untag()->entry_bits();
+      for (intptr_t i = 0; i < length; i++) {
+        auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
+        if (entry_type == ObjectPool::EntryType::kTaggedObject) {
+          s->Push(pool->untag()->data()[i].raw_obj_);
+        }
       }
     }
   }
@@ -1907,33 +1887,41 @@
       ObjectPoolPtr pool = objects_[i];
       s->AssignRef(pool);
       AutoTraceObject(pool);
-      const intptr_t length = pool->ptr()->length_;
+      const intptr_t length = pool->untag()->length_;
       s->WriteUnsigned(length);
     }
   }
 
   void WriteFill(Serializer* s) {
+    bool weak = s->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions &&
+                FLAG_retain_function_objects;
+
     const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       ObjectPoolPtr pool = objects_[i];
       AutoTraceObject(pool);
-      const intptr_t length = pool->ptr()->length_;
+      const intptr_t length = pool->untag()->length_;
       s->WriteUnsigned(length);
-      uint8_t* entry_bits = pool->ptr()->entry_bits();
+      uint8_t* entry_bits = pool->untag()->entry_bits();
       for (intptr_t j = 0; j < length; j++) {
         s->Write<uint8_t>(entry_bits[j]);
-        ObjectPoolLayout::Entry& entry = pool->ptr()->data()[j];
+        UntaggedObjectPool::Entry& entry = pool->untag()->data()[j];
         switch (ObjectPool::TypeBits::decode(entry_bits[j])) {
           case ObjectPool::EntryType::kTaggedObject: {
-            if ((entry.raw_obj_ == StubCode::CallNoScopeNative().raw()) ||
-                (entry.raw_obj_ == StubCode::CallAutoScopeNative().raw())) {
+            if ((entry.raw_obj_ == StubCode::CallNoScopeNative().ptr()) ||
+                (entry.raw_obj_ == StubCode::CallAutoScopeNative().ptr())) {
               // Natives can run while precompiling, becoming linked and
               // switching their stub. Reset to the initial stub used for
               // lazy-linking.
-              s->WriteElementRef(StubCode::CallBootstrapNative().raw(), j);
+              s->WriteElementRef(StubCode::CallBootstrapNative().ptr(), j);
               break;
             }
-            s->WriteElementRef(entry.raw_obj_, j);
+            if (weak && !s->HasRef(entry.raw_obj_)) {
+              // Any value will do, but null has the shortest id.
+              s->WriteElementRef(Object::null(), j);
+            } else {
+              s->WriteElementRef(entry.raw_obj_, j);
+            }
             break;
           }
           case ObjectPool::EntryType::kImmediate: {
@@ -1962,7 +1950,7 @@
   ObjectPoolDeserializationCluster() : DeserializationCluster("ObjectPool") {}
   ~ObjectPoolDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1974,17 +1962,20 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
+    fill_position_ = d->position();
+
     for (intptr_t id = start_index_; id < stop_index_; id += 1) {
       const intptr_t length = d->ReadUnsigned();
       ObjectPoolPtr pool = static_cast<ObjectPoolPtr>(d->Ref(id + 0));
       Deserializer::InitializeHeader(pool, kObjectPoolCid,
                                      ObjectPool::InstanceSize(length));
-      pool->ptr()->length_ = length;
+      pool->untag()->length_ = length;
       for (intptr_t j = 0; j < length; j++) {
         const uint8_t entry_bits = d->Read<uint8_t>();
-        pool->ptr()->entry_bits()[j] = entry_bits;
-        ObjectPoolLayout::Entry& entry = pool->ptr()->data()[j];
+        pool->untag()->entry_bits()[j] = entry_bits;
+        UntaggedObjectPool::Entry& entry = pool->untag()->data()[j];
         switch (ObjectPool::TypeBits::decode(entry_bits)) {
           case ObjectPool::EntryType::kTaggedObject:
             entry.raw_obj_ = d->ReadRef();
@@ -2004,6 +1995,41 @@
       }
     }
   }
+
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    intptr_t restore_position = d->position();
+    d->set_position(fill_position_);
+
+    ObjectPool& pool = ObjectPool::Handle();
+    Object& entry = Object::Handle();
+    for (intptr_t id = start_index_; id < stop_index_; id += 1) {
+      pool ^= refs.At(id);
+      const intptr_t length = d->ReadUnsigned();
+      for (intptr_t j = 0; j < length; j++) {
+        const uint8_t entry_bits = d->Read<uint8_t>();
+        switch (ObjectPool::TypeBits::decode(entry_bits)) {
+          case ObjectPool::EntryType::kTaggedObject:
+            entry = refs.At(d->ReadUnsigned());
+            pool.SetObjectAt(j, entry);
+            break;
+          case ObjectPool::EntryType::kImmediate:
+            d->Read<intptr_t>();
+            break;
+          case ObjectPool::EntryType::kNativeFunction: {
+            // Read nothing.
+            break;
+          }
+          default:
+            UNREACHABLE();
+        }
+      }
+    }
+
+    d->set_position(restore_position);
+  }
+
+ private:
+  intptr_t fill_position_ = 0;
 };
 
 #if defined(DART_PRECOMPILER)
@@ -2126,7 +2152,7 @@
       : DeserializationCluster("WeakSerializationReference") {}
   ~WeakSerializationReferenceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2140,13 +2166,14 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       auto const ref = static_cast<WeakSerializationReferencePtr>(d->Ref(id));
       Deserializer::InitializeHeader(
           ref, kWeakSerializationReferenceCid,
           WeakSerializationReference::InstanceSize());
-      ref->ptr()->cid_ = d->ReadCid();
+      ref->untag()->cid_ = d->ReadCid();
     }
   }
 };
@@ -2171,7 +2198,7 @@
       PcDescriptorsPtr desc = objects_[i];
       s->AssignRef(desc);
       AutoTraceObject(desc);
-      const intptr_t length = desc->ptr()->length_;
+      const intptr_t length = desc->untag()->length_;
       s->WriteUnsigned(length);
     }
   }
@@ -2181,9 +2208,9 @@
     for (intptr_t i = 0; i < count; i++) {
       PcDescriptorsPtr desc = objects_[i];
       AutoTraceObject(desc);
-      const intptr_t length = desc->ptr()->length_;
+      const intptr_t length = desc->untag()->length_;
       s->WriteUnsigned(length);
-      uint8_t* cdata = reinterpret_cast<uint8_t*>(desc->ptr()->data());
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(desc->untag()->data());
       s->WriteBytes(cdata, length);
     }
   }
@@ -2199,7 +2226,7 @@
       : DeserializationCluster("PcDescriptors") {}
   ~PcDescriptorsDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2211,14 +2238,15 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id += 1) {
       const intptr_t length = d->ReadUnsigned();
       PcDescriptorsPtr desc = static_cast<PcDescriptorsPtr>(d->Ref(id));
       Deserializer::InitializeHeader(desc, kPcDescriptorsCid,
                                      PcDescriptors::InstanceSize(length));
-      desc->ptr()->length_ = length;
-      uint8_t* cdata = reinterpret_cast<uint8_t*>(desc->ptr()->data());
+      desc->untag()->length_ = length;
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(desc->untag()->data());
       d->ReadBytes(cdata, length);
     }
   }
@@ -2240,7 +2268,7 @@
     // will be loaded into read-only memory. Extra bytes due to allocation
     // rounding need to be deterministically set for reliable deduplication in
     // shared images.
-    if (object->ptr()->InVMIsolateHeap() ||
+    if (object->untag()->InVMIsolateHeap() ||
         s->heap()->old_space()->IsObjectFromImagePages(object)) {
       // This object is already read-only.
     } else {
@@ -2293,7 +2321,7 @@
       : DeserializationCluster("ROData"), cid_(cid) {}
   ~RODataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     intptr_t count = d->ReadUnsigned();
     uint32_t running_offset = 0;
@@ -2304,23 +2332,27 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     // No-op.
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && IsStringClassId(cid_) &&
-        (d->isolate() != Dart::vm_isolate())) {
-      CanonicalStringSet table(d->zone(),
-                               d->isolate()->object_store()->symbol_table());
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize && IsStringClassId(cid_)) {
+      CanonicalStringSet table(
+          d->zone(), d->isolate_group()->object_store()->symbol_table());
       String& str = String::Handle(d->zone());
+      String& str2 = String::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         str ^= refs.At(i);
-        ASSERT(str.IsCanonical());
-        bool present = table.Insert(str);
-        ASSERT(!present);
+        str2 ^= table.InsertOrGet(str);
+        if (str.ptr() == str2.ptr()) {
+          // str.SetCanonical();
+        } else {
+          FATAL("Lost canonicalization race");
+          refs.SetAt(i, str2);
+        }
       }
-      d->isolate()->object_store()->set_symbol_table(table.Release());
+      d->isolate_group()->object_store()->set_symbol_table(table.Release());
     }
   }
 
@@ -2339,7 +2371,7 @@
     ExceptionHandlersPtr handlers = ExceptionHandlers::RawCast(object);
     objects_.Add(handlers);
 
-    s->Push(handlers->ptr()->handled_types_data_);
+    s->Push(handlers->untag()->handled_types_data_);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2350,7 +2382,7 @@
       ExceptionHandlersPtr handlers = objects_[i];
       s->AssignRef(handlers);
       AutoTraceObject(handlers);
-      const intptr_t length = handlers->ptr()->num_entries_;
+      const intptr_t length = handlers->untag()->num_entries_;
       s->WriteUnsigned(length);
     }
   }
@@ -2360,11 +2392,11 @@
     for (intptr_t i = 0; i < count; i++) {
       ExceptionHandlersPtr handlers = objects_[i];
       AutoTraceObject(handlers);
-      const intptr_t length = handlers->ptr()->num_entries_;
+      const intptr_t length = handlers->untag()->num_entries_;
       s->WriteUnsigned(length);
       WriteField(handlers, handled_types_data_);
       for (intptr_t j = 0; j < length; j++) {
-        const ExceptionHandlerInfo& info = handlers->ptr()->data()[j];
+        const ExceptionHandlerInfo& info = handlers->untag()->data()[j];
         s->Write<uint32_t>(info.handler_pc_offset);
         s->Write<int16_t>(info.outer_try_index);
         s->Write<int8_t>(info.needs_stacktrace);
@@ -2385,7 +2417,7 @@
       : DeserializationCluster("ExceptionHandlers") {}
   ~ExceptionHandlersDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2397,18 +2429,19 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ExceptionHandlersPtr handlers =
           static_cast<ExceptionHandlersPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(handlers, kExceptionHandlersCid,
                                      ExceptionHandlers::InstanceSize(length));
-      handlers->ptr()->num_entries_ = length;
-      handlers->ptr()->handled_types_data_ =
+      handlers->untag()->num_entries_ = length;
+      handlers->untag()->handled_types_data_ =
           static_cast<ArrayPtr>(d->ReadRef());
       for (intptr_t j = 0; j < length; j++) {
-        ExceptionHandlerInfo& info = handlers->ptr()->data()[j];
+        ExceptionHandlerInfo& info = handlers->untag()->data()[j];
         info.handler_pc_offset = d->Read<uint32_t>();
         info.outer_try_index = d->Read<int16_t>();
         info.needs_stacktrace = d->Read<int8_t>();
@@ -2429,10 +2462,10 @@
     ContextPtr context = Context::RawCast(object);
     objects_.Add(context);
 
-    s->Push(context->ptr()->parent_);
-    const intptr_t length = context->ptr()->num_variables_;
+    s->Push(context->untag()->parent_);
+    const intptr_t length = context->untag()->num_variables_;
     for (intptr_t i = 0; i < length; i++) {
-      s->Push(context->ptr()->data()[i]);
+      s->Push(context->untag()->data()[i]);
     }
   }
 
@@ -2444,7 +2477,7 @@
       ContextPtr context = objects_[i];
       s->AssignRef(context);
       AutoTraceObject(context);
-      const intptr_t length = context->ptr()->num_variables_;
+      const intptr_t length = context->untag()->num_variables_;
       s->WriteUnsigned(length);
     }
   }
@@ -2454,11 +2487,11 @@
     for (intptr_t i = 0; i < count; i++) {
       ContextPtr context = objects_[i];
       AutoTraceObject(context);
-      const intptr_t length = context->ptr()->num_variables_;
+      const intptr_t length = context->untag()->num_variables_;
       s->WriteUnsigned(length);
       WriteField(context, parent_);
       for (intptr_t j = 0; j < length; j++) {
-        s->WriteElementRef(context->ptr()->data()[j], j);
+        s->WriteElementRef(context->untag()->data()[j], j);
       }
     }
   }
@@ -2473,7 +2506,7 @@
   ContextDeserializationCluster() : DeserializationCluster("Context") {}
   ~ContextDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2485,16 +2518,17 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ContextPtr context = static_cast<ContextPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(context, kContextCid,
                                      Context::InstanceSize(length));
-      context->ptr()->num_variables_ = length;
-      context->ptr()->parent_ = static_cast<ContextPtr>(d->ReadRef());
+      context->untag()->num_variables_ = length;
+      context->untag()->parent_ = static_cast<ContextPtr>(d->ReadRef());
       for (intptr_t j = 0; j < length; j++) {
-        context->ptr()->data()[j] = d->ReadRef();
+        context->untag()->data()[j] = d->ReadRef();
       }
     }
   }
@@ -2510,7 +2544,7 @@
     ContextScopePtr scope = ContextScope::RawCast(object);
     objects_.Add(scope);
 
-    const intptr_t length = scope->ptr()->num_variables_;
+    const intptr_t length = scope->untag()->num_variables_;
     PushFromTo(scope, length);
   }
 
@@ -2522,7 +2556,7 @@
       ContextScopePtr scope = objects_[i];
       s->AssignRef(scope);
       AutoTraceObject(scope);
-      const intptr_t length = scope->ptr()->num_variables_;
+      const intptr_t length = scope->untag()->num_variables_;
       s->WriteUnsigned(length);
     }
   }
@@ -2532,9 +2566,9 @@
     for (intptr_t i = 0; i < count; i++) {
       ContextScopePtr scope = objects_[i];
       AutoTraceObject(scope);
-      const intptr_t length = scope->ptr()->num_variables_;
+      const intptr_t length = scope->untag()->num_variables_;
       s->WriteUnsigned(length);
-      s->Write<bool>(scope->ptr()->is_implicit_);
+      s->Write<bool>(scope->untag()->is_implicit_);
       WriteFromTo(scope, length);
     }
   }
@@ -2550,7 +2584,7 @@
       : DeserializationCluster("ContextScope") {}
   ~ContextScopeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2562,14 +2596,15 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ContextScopePtr scope = static_cast<ContextScopePtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(scope, kContextScopeCid,
                                      ContextScope::InstanceSize(length));
-      scope->ptr()->num_variables_ = length;
-      scope->ptr()->is_implicit_ = d->Read<bool>();
+      scope->untag()->num_variables_ = length;
+      scope->untag()->is_implicit_ = d->Read<bool>();
       ReadFromTo(scope, length);
     }
   }
@@ -2601,9 +2636,9 @@
     const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       UnlinkedCallPtr unlinked = objects_[i];
-      AutoTraceObjectName(unlinked, unlinked->ptr()->target_name_);
+      AutoTraceObjectName(unlinked, unlinked->untag()->target_name_);
       WriteFromTo(unlinked);
-      s->Write<bool>(unlinked->ptr()->can_patch_to_monomorphic_);
+      s->Write<bool>(unlinked->untag()->can_patch_to_monomorphic_);
     }
   }
 
@@ -2618,7 +2653,7 @@
       : DeserializationCluster("UnlinkedCall") {}
   ~UnlinkedCallDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2629,13 +2664,14 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       UnlinkedCallPtr unlinked = static_cast<UnlinkedCallPtr>(d->Ref(id));
       Deserializer::InitializeHeader(unlinked, kUnlinkedCallCid,
                                      UnlinkedCall::InstanceSize());
       ReadFromTo(unlinked);
-      unlinked->ptr()->can_patch_to_monomorphic_ = d->Read<bool>();
+      unlinked->untag()->can_patch_to_monomorphic_ = d->Read<bool>();
     }
   }
 };
@@ -2667,12 +2703,12 @@
     const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       ICDataPtr ic = objects_[i];
-      AutoTraceObjectName(ic, ic->ptr()->target_name_);
+      AutoTraceObjectName(ic, ic->untag()->target_name_);
       WriteFromTo(ic);
       if (kind != Snapshot::kFullAOT) {
-        NOT_IN_PRECOMPILED(s->Write<int32_t>(ic->ptr()->deopt_id_));
+        NOT_IN_PRECOMPILED(s->Write<int32_t>(ic->untag()->deopt_id_));
       }
-      s->Write<uint32_t>(ic->ptr()->state_bits_);
+      s->Write<uint32_t>(ic->untag()->state_bits_);
     }
   }
 
@@ -2686,7 +2722,7 @@
   ICDataDeserializationCluster() : DeserializationCluster("ICData") {}
   ~ICDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2696,13 +2732,14 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ICDataPtr ic = static_cast<ICDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(ic, kICDataCid, ICData::InstanceSize());
       ReadFromTo(ic);
-      NOT_IN_PRECOMPILED(ic->ptr()->deopt_id_ = d->Read<int32_t>());
-      ic->ptr()->state_bits_ = d->Read<int32_t>();
+      NOT_IN_PRECOMPILED(ic->untag()->deopt_id_ = d->Read<int32_t>());
+      ic->untag()->state_bits_ = d->Read<int32_t>();
     }
   }
 };
@@ -2734,9 +2771,9 @@
     const intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       MegamorphicCachePtr cache = objects_[i];
-      AutoTraceObjectName(cache, cache->ptr()->target_name_);
+      AutoTraceObjectName(cache, cache->untag()->target_name_);
       WriteFromTo(cache);
-      s->Write<int32_t>(cache->ptr()->filled_entry_count_);
+      s->Write<int32_t>(cache->untag()->filled_entry_count_);
     }
   }
 
@@ -2751,7 +2788,7 @@
       : DeserializationCluster("MegamorphicCache") {}
   ~MegamorphicCacheDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2762,18 +2799,19 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       MegamorphicCachePtr cache = static_cast<MegamorphicCachePtr>(d->Ref(id));
       Deserializer::InitializeHeader(cache, kMegamorphicCacheCid,
                                      MegamorphicCache::InstanceSize());
       ReadFromTo(cache);
-      cache->ptr()->filled_entry_count_ = d->Read<int32_t>();
+      cache->untag()->filled_entry_count_ = d->Read<int32_t>();
     }
   }
 
 #if defined(DART_PRECOMPILED_RUNTIME)
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
     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
@@ -2809,7 +2847,7 @@
   void Trace(Serializer* s, ObjectPtr object) {
     SubtypeTestCachePtr cache = SubtypeTestCache::RawCast(object);
     objects_.Add(cache);
-    s->Push(cache->ptr()->cache_);
+    s->Push(cache->untag()->cache_);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2842,7 +2880,7 @@
       : DeserializationCluster("SubtypeTestCache") {}
   ~SubtypeTestCacheDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2853,12 +2891,13 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       SubtypeTestCachePtr cache = static_cast<SubtypeTestCachePtr>(d->Ref(id));
       Deserializer::InitializeHeader(cache, kSubtypeTestCacheCid,
                                      SubtypeTestCache::InstanceSize());
-      cache->ptr()->cache_ = static_cast<ArrayPtr>(d->ReadRef());
+      cache->untag()->cache_ = static_cast<ArrayPtr>(d->ReadRef());
     }
   }
 };
@@ -2872,7 +2911,7 @@
   void Trace(Serializer* s, ObjectPtr object) {
     LoadingUnitPtr unit = LoadingUnit::RawCast(object);
     objects_.Add(unit);
-    s->Push(unit->ptr()->parent_);
+    s->Push(unit->untag()->parent_);
   }
 
   void WriteAlloc(Serializer* s) {
@@ -2891,7 +2930,7 @@
       LoadingUnitPtr unit = objects_[i];
       AutoTraceObject(unit);
       WriteField(unit, parent_);
-      s->Write<int32_t>(unit->ptr()->id_);
+      s->Write<int32_t>(unit->untag()->id_);
     }
   }
 
@@ -2905,7 +2944,7 @@
   LoadingUnitDeserializationCluster() : DeserializationCluster("LoadingUnit") {}
   ~LoadingUnitDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2916,16 +2955,17 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LoadingUnitPtr unit = static_cast<LoadingUnitPtr>(d->Ref(id));
       Deserializer::InitializeHeader(unit, kLoadingUnitCid,
                                      LoadingUnit::InstanceSize());
-      unit->ptr()->parent_ = static_cast<LoadingUnitPtr>(d->ReadRef());
-      unit->ptr()->base_objects_ = Array::null();
-      unit->ptr()->id_ = d->Read<int32_t>();
-      unit->ptr()->loaded_ = false;
-      unit->ptr()->load_outstanding_ = false;
+      unit->untag()->parent_ = static_cast<LoadingUnitPtr>(d->ReadRef());
+      unit->untag()->base_objects_ = Array::null();
+      unit->untag()->id_ = d->Read<int32_t>();
+      unit->untag()->loaded_ = false;
+      unit->untag()->load_outstanding_ = false;
     }
   }
 };
@@ -2958,9 +2998,9 @@
       LanguageErrorPtr error = objects_[i];
       AutoTraceObject(error);
       WriteFromTo(error);
-      s->WriteTokenPosition(error->ptr()->token_pos_);
-      s->Write<bool>(error->ptr()->report_after_token_);
-      s->Write<int8_t>(error->ptr()->kind_);
+      s->WriteTokenPosition(error->untag()->token_pos_);
+      s->Write<bool>(error->untag()->report_after_token_);
+      s->Write<int8_t>(error->untag()->kind_);
     }
   }
 
@@ -2975,7 +3015,7 @@
       : DeserializationCluster("LanguageError") {}
   ~LanguageErrorDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2986,15 +3026,16 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LanguageErrorPtr error = static_cast<LanguageErrorPtr>(d->Ref(id));
       Deserializer::InitializeHeader(error, kLanguageErrorCid,
                                      LanguageError::InstanceSize());
       ReadFromTo(error);
-      error->ptr()->token_pos_ = d->ReadTokenPosition();
-      error->ptr()->report_after_token_ = d->Read<bool>();
-      error->ptr()->kind_ = d->Read<int8_t>();
+      error->untag()->token_pos_ = d->ReadTokenPosition();
+      error->untag()->report_after_token_ = d->Read<bool>();
+      error->untag()->kind_ = d->Read<int8_t>();
     }
   }
 };
@@ -3042,7 +3083,7 @@
       : DeserializationCluster("UnhandledException") {}
   ~UnhandledExceptionDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3053,7 +3094,8 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       UnhandledExceptionPtr exception =
           static_cast<UnhandledExceptionPtr>(d->Ref(id));
@@ -3069,14 +3111,15 @@
  public:
   explicit InstanceSerializationCluster(intptr_t cid)
       : SerializationCluster("Instance"), cid_(cid) {
-    ClassPtr cls = Isolate::Current()->class_table()->At(cid);
+    ClassPtr cls = IsolateGroup::Current()->class_table()->At(cid);
     host_next_field_offset_in_words_ =
-        cls->ptr()->host_next_field_offset_in_words_;
+        cls->untag()->host_next_field_offset_in_words_;
     ASSERT(host_next_field_offset_in_words_ > 0);
 #if !defined(DART_PRECOMPILED_RUNTIME)
     target_next_field_offset_in_words_ =
-        cls->ptr()->target_next_field_offset_in_words_;
-    target_instance_size_in_words_ = cls->ptr()->target_instance_size_in_words_;
+        cls->untag()->target_next_field_offset_in_words_;
+    target_instance_size_in_words_ =
+        cls->untag()->target_instance_size_in_words_;
     ASSERT(target_next_field_offset_in_words_ > 0);
     ASSERT(target_instance_size_in_words_ > 0);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -3096,7 +3139,7 @@
       // Skips unboxed fields
       if (!unboxed_fields_bitmap.Get(offset / kWordSize)) {
         ObjectPtr raw_obj = *reinterpret_cast<ObjectPtr*>(
-            reinterpret_cast<uword>(instance->ptr()) + offset);
+            reinterpret_cast<uword>(instance->untag()) + offset);
         s->Push(raw_obj);
       }
       offset += kWordSize;
@@ -3138,11 +3181,11 @@
         if (unboxed_fields_bitmap.Get(offset / kWordSize)) {
           // Writes 32 bits of the unboxed value at a time
           const uword value = *reinterpret_cast<uword*>(
-              reinterpret_cast<uword>(instance->ptr()) + offset);
+              reinterpret_cast<uword>(instance->untag()) + offset);
           s->WriteWordWith32BitWrites(value);
         } else {
           ObjectPtr raw_obj = *reinterpret_cast<ObjectPtr*>(
-              reinterpret_cast<uword>(instance->ptr()) + offset);
+              reinterpret_cast<uword>(instance->untag()) + offset);
           s->WriteElementRef(raw_obj, offset);
         }
         offset += kWordSize;
@@ -3161,13 +3204,35 @@
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
-class InstanceDeserializationCluster : public DeserializationCluster {
+class AbstractInstanceDeserializationCluster : public DeserializationCluster {
+ protected:
+  explicit AbstractInstanceDeserializationCluster(const char* name)
+      : DeserializationCluster(name) {}
+
+ public:
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize) {
+      Thread* thread = Thread::Current();
+      SafepointMutexLocker ml(
+          thread->isolate_group()->constant_canonicalization_mutex());
+      Instance& instance = Instance::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        instance ^= refs.At(i);
+        instance = instance.CanonicalizeLocked(thread);
+        refs.SetAt(i, instance);
+      }
+    }
+  }
+};
+
+class InstanceDeserializationCluster
+    : public AbstractInstanceDeserializationCluster {
  public:
   explicit InstanceDeserializationCluster(intptr_t cid)
-      : DeserializationCluster("Instance"), cid_(cid) {}
+      : AbstractInstanceDeserializationCluster("Instance"), cid_(cid) {}
   ~InstanceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3181,7 +3246,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
     intptr_t instance_size =
         Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
@@ -3190,24 +3255,24 @@
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       InstancePtr instance = static_cast<InstancePtr>(d->Ref(id));
       Deserializer::InitializeHeader(instance, cid_, instance_size,
-                                     is_canonical);
+                                     stamp_canonical);
       intptr_t offset = Instance::NextFieldOffset();
       while (offset < next_field_offset) {
         if (unboxed_fields_bitmap.Get(offset / kWordSize)) {
           uword* p = reinterpret_cast<uword*>(
-              reinterpret_cast<uword>(instance->ptr()) + offset);
+              reinterpret_cast<uword>(instance->untag()) + offset);
           // Reads 32 bits of the unboxed value at a time
           *p = d->ReadWordWith32BitReads();
         } else {
           ObjectPtr* p = reinterpret_cast<ObjectPtr*>(
-              reinterpret_cast<uword>(instance->ptr()) + offset);
+              reinterpret_cast<uword>(instance->untag()) + offset);
           *p = d->ReadRef();
         }
         offset += kWordSize;
       }
       if (offset < instance_size) {
         ObjectPtr* p = reinterpret_cast<ObjectPtr*>(
-            reinterpret_cast<uword>(instance->ptr()) + offset);
+            reinterpret_cast<uword>(instance->untag()) + offset);
         *p = Object::null();
         offset += kWordSize;
       }
@@ -3249,8 +3314,8 @@
       LibraryPrefixPtr prefix = objects_[i];
       AutoTraceObject(prefix);
       WriteFromTo(prefix);
-      s->Write<uint16_t>(prefix->ptr()->num_imports_);
-      s->Write<bool>(prefix->ptr()->is_deferred_load_);
+      s->Write<uint16_t>(prefix->untag()->num_imports_);
+      s->Write<bool>(prefix->untag()->is_deferred_load_);
     }
   }
 
@@ -3265,7 +3330,7 @@
       : DeserializationCluster("LibraryPrefix") {}
   ~LibraryPrefixDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3276,15 +3341,16 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LibraryPrefixPtr prefix = static_cast<LibraryPrefixPtr>(d->Ref(id));
       Deserializer::InitializeHeader(prefix, kLibraryPrefixCid,
                                      LibraryPrefix::InstanceSize());
       ReadFromTo(prefix);
-      prefix->ptr()->num_imports_ = d->Read<uint16_t>();
-      prefix->ptr()->is_deferred_load_ = d->Read<bool>();
-      prefix->ptr()->is_loaded_ = !prefix->ptr()->is_deferred_load_;
+      prefix->untag()->num_imports_ = d->Read<uint16_t>();
+      prefix->untag()->is_deferred_load_ = d->Read<bool>();
+      prefix->untag()->is_loaded_ = !prefix->untag()->is_deferred_load_;
     }
   }
 };
@@ -3305,14 +3371,14 @@
 
     PushFromTo(type);
 
-    if (type->ptr()->type_class_id_->IsHeapObject()) {
+    if (type->untag()->type_class_id_->IsHeapObject()) {
       // Type class is still an unresolved class.
       UNREACHABLE();
     }
 
-    SmiPtr raw_type_class_id = Smi::RawCast(type->ptr()->type_class_id_);
+    SmiPtr raw_type_class_id = Smi::RawCast(type->untag()->type_class_id_);
     ClassPtr type_class =
-        s->isolate()->class_table()->At(Smi::Value(raw_type_class_id));
+        s->isolate_group()->class_table()->At(Smi::Value(raw_type_class_id));
     s->Push(type_class);
   }
 
@@ -3337,16 +3403,16 @@
   void WriteType(Serializer* s, TypePtr type) {
     AutoTraceObject(type);
     WriteFromTo(type);
-    s->WriteTokenPosition(type->ptr()->token_pos_);
-    ASSERT(type->ptr()->type_state_ < (1 << TypeLayout::kTypeStateBitSize));
-    ASSERT(type->ptr()->nullability_ < (1 << kNullabilityBitSize));
-    static_assert(TypeLayout::kTypeStateBitSize + kNullabilityBitSize <=
+    ASSERT(type->untag()->type_state_ < (1 << UntaggedType::kTypeStateBitSize));
+    ASSERT(type->untag()->nullability_ < (1 << kNullabilityBitSize));
+    static_assert(UntaggedType::kTypeStateBitSize + kNullabilityBitSize <=
                       kBitsPerByte * sizeof(uint8_t),
                   "Cannot pack type_state_ and nullability_ into a uint8_t");
-    const uint8_t combined = (type->ptr()->type_state_ << kNullabilityBitSize) |
-                             type->ptr()->nullability_;
-    ASSERT_EQUAL(type->ptr()->type_state_, combined >> kNullabilityBitSize);
-    ASSERT_EQUAL(type->ptr()->nullability_, combined & kNullabilityBitMask);
+    const uint8_t combined =
+        (type->untag()->type_state_ << kNullabilityBitSize) |
+        type->untag()->nullability_;
+    ASSERT_EQUAL(type->untag()->type_state_, combined >> kNullabilityBitSize);
+    ASSERT_EQUAL(type->untag()->nullability_, combined & kNullabilityBitMask);
     s->Write<uint8_t>(combined);
   }
 
@@ -3359,7 +3425,7 @@
   TypeDeserializationCluster() : DeserializationCluster("Type") {}
   ~TypeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3369,33 +3435,27 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypePtr type = static_cast<TypePtr>(d->Ref(id));
       Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
-                                     is_canonical);
+                                     stamp_canonical);
       ReadFromTo(type);
-      type->ptr()->token_pos_ = d->ReadTokenPosition();
       const uint8_t combined = d->Read<uint8_t>();
-      type->ptr()->type_state_ = combined >> kNullabilityBitSize;
-      type->ptr()->nullability_ = combined & kNullabilityBitMask;
+      type->untag()->type_state_ = combined >> kNullabilityBitSize;
+      type->untag()->nullability_ = combined & kNullabilityBitMask;
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
-      CanonicalTypeSet table(d->zone(),
-                             d->isolate()->object_store()->canonical_types());
-      Type& type = Type::Handle(d->zone());
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize) {
+      Thread* thread = Thread::Current();
+      AbstractType& type = AbstractType::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         type ^= refs.At(i);
-        ASSERT(type.IsCanonical());
-        bool present = table.Insert(type);
-        // Two recursive types with different topology (and hashes) may be
-        // equal.
-        ASSERT(!present || type.IsRecursive());
+        type = type.Canonicalize(thread, nullptr);
+        refs.SetAt(i, type);
       }
-      d->isolate()->object_store()->set_canonical_types(table.Release());
     }
 
     Type& type = Type::Handle(d->zone());
@@ -3418,6 +3478,120 @@
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+class FunctionTypeSerializationCluster : public SerializationCluster {
+ public:
+  FunctionTypeSerializationCluster() : SerializationCluster("FunctionType") {}
+  ~FunctionTypeSerializationCluster() {}
+
+  void Trace(Serializer* s, ObjectPtr object) {
+    FunctionTypePtr type = FunctionType::RawCast(object);
+    objects_.Add(type);
+    PushFromTo(type);
+  }
+
+  void WriteAlloc(Serializer* s) {
+    s->WriteCid(kFunctionTypeCid);
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      FunctionTypePtr type = objects_[i];
+      s->AssignRef(type);
+    }
+  }
+
+  void WriteFill(Serializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      WriteFunctionType(s, objects_[i]);
+    }
+  }
+
+ private:
+  void WriteFunctionType(Serializer* s, FunctionTypePtr type) {
+    AutoTraceObject(type);
+    WriteFromTo(type);
+    ASSERT(type->untag()->type_state_ <
+           (1 << UntaggedFunctionType::kTypeStateBitSize));
+    ASSERT(type->untag()->nullability_ < (1 << kNullabilityBitSize));
+    static_assert(
+        UntaggedFunctionType::kTypeStateBitSize + kNullabilityBitSize <=
+            kBitsPerByte * sizeof(uint8_t),
+        "Cannot pack type_state_ and nullability_ into a uint8_t");
+    const uint8_t combined =
+        (type->untag()->type_state_ << kNullabilityBitSize) |
+        type->untag()->nullability_;
+    ASSERT_EQUAL(type->untag()->type_state_, combined >> kNullabilityBitSize);
+    ASSERT_EQUAL(type->untag()->nullability_, combined & kNullabilityBitMask);
+    s->Write<uint8_t>(combined);
+    s->Write<uint32_t>(type->untag()->packed_fields_);
+  }
+
+  GrowableArray<FunctionTypePtr> objects_;
+};
+#endif  // !DART_PRECOMPILED_RUNTIME
+
+class FunctionTypeDeserializationCluster : public DeserializationCluster {
+ public:
+  FunctionTypeDeserializationCluster()
+      : DeserializationCluster("FunctionType") {}
+  ~FunctionTypeDeserializationCluster() {}
+
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
+    start_index_ = d->next_index();
+    PageSpace* old_space = d->heap()->old_space();
+    const intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(
+          AllocateUninitialized(old_space, FunctionType::InstanceSize()));
+    }
+    stop_index_ = d->next_index();
+  }
+
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      FunctionTypePtr type = static_cast<FunctionTypePtr>(d->Ref(id));
+      Deserializer::InitializeHeader(type, kFunctionTypeCid,
+                                     FunctionType::InstanceSize(),
+                                     stamp_canonical);
+      ReadFromTo(type);
+      const uint8_t combined = d->Read<uint8_t>();
+      type->untag()->type_state_ = combined >> kNullabilityBitSize;
+      type->untag()->nullability_ = combined & kNullabilityBitMask;
+      type->untag()->packed_fields_ = d->Read<uint32_t>();
+    }
+  }
+
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize) {
+      Thread* thread = Thread::Current();
+      AbstractType& type = AbstractType::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        type ^= refs.At(i);
+        type = type.Canonicalize(thread, nullptr);
+        refs.SetAt(i, type);
+      }
+    }
+
+    FunctionType& type = FunctionType::Handle(d->zone());
+    Code& stub = Code::Handle(d->zone());
+
+    if (Snapshot::IncludesCode(d->kind())) {
+      for (intptr_t id = start_index_; id < stop_index_; id++) {
+        type ^= refs.At(id);
+        stub = type.type_test_stub();
+        type.SetTypeTestingStub(stub);  // Update type_test_stub_entry_point_
+      }
+    } else {
+      for (intptr_t id = start_index_; id < stop_index_; id++) {
+        type ^= refs.At(id);
+        stub = TypeTestingStubGenerator::DefaultCodeForType(type);
+        type.SetTypeTestingStub(stub);
+      }
+    }
+  }
+};
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
 class TypeRefSerializationCluster : public SerializationCluster {
  public:
   TypeRefSerializationCluster() : SerializationCluster("TypeRef") {}
@@ -3458,7 +3632,7 @@
   TypeRefDeserializationCluster() : DeserializationCluster("TypeRef") {}
   ~TypeRefDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3468,16 +3642,16 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeRefPtr type = static_cast<TypeRefPtr>(d->Ref(id));
-      Deserializer::InitializeHeader(type, kTypeRefCid,
-                                     TypeRef::InstanceSize());
+      Deserializer::InitializeHeader(type, kTypeRefCid, TypeRef::InstanceSize(),
+                                     stamp_canonical);
       ReadFromTo(type);
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
     TypeRef& type_ref = TypeRef::Handle(d->zone());
     Code& stub = Code::Handle(d->zone());
 
@@ -3532,18 +3706,18 @@
   void WriteTypeParameter(Serializer* s, TypeParameterPtr type) {
     AutoTraceObject(type);
     WriteFromTo(type);
-    s->Write<int32_t>(type->ptr()->parameterized_class_id_);
-    s->WriteTokenPosition(type->ptr()->token_pos_);
-    s->Write<int16_t>(type->ptr()->index_);
-    ASSERT(type->ptr()->flags_ < (1 << TypeParameterLayout::kFlagsBitSize));
-    ASSERT(type->ptr()->nullability_ < (1 << kNullabilityBitSize));
-    static_assert(TypeParameterLayout::kFlagsBitSize + kNullabilityBitSize <=
+    s->Write<int32_t>(type->untag()->parameterized_class_id_);
+    s->Write<uint16_t>(type->untag()->base_);
+    s->Write<uint16_t>(type->untag()->index_);
+    ASSERT(type->untag()->flags_ < (1 << UntaggedTypeParameter::kFlagsBitSize));
+    ASSERT(type->untag()->nullability_ < (1 << kNullabilityBitSize));
+    static_assert(UntaggedTypeParameter::kFlagsBitSize + kNullabilityBitSize <=
                       kBitsPerByte * sizeof(uint8_t),
                   "Cannot pack flags_ and nullability_ into a uint8_t");
-    const uint8_t combined = (type->ptr()->flags_ << kNullabilityBitSize) |
-                             type->ptr()->nullability_;
-    ASSERT_EQUAL(type->ptr()->flags_, combined >> kNullabilityBitSize);
-    ASSERT_EQUAL(type->ptr()->nullability_, combined & kNullabilityBitMask);
+    const uint8_t combined = (type->untag()->flags_ << kNullabilityBitSize) |
+                             type->untag()->nullability_;
+    ASSERT_EQUAL(type->untag()->flags_, combined >> kNullabilityBitSize);
+    ASSERT_EQUAL(type->untag()->nullability_, combined & kNullabilityBitMask);
     s->Write<uint8_t>(combined);
   }
 
@@ -3557,7 +3731,7 @@
       : DeserializationCluster("TypeParameter") {}
   ~TypeParameterDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3568,36 +3742,31 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeParameterPtr type = static_cast<TypeParameterPtr>(d->Ref(id));
-      Deserializer::InitializeHeader(
-          type, kTypeParameterCid, TypeParameter::InstanceSize(), is_canonical);
+      Deserializer::InitializeHeader(type, kTypeParameterCid,
+                                     TypeParameter::InstanceSize(),
+                                     stamp_canonical);
       ReadFromTo(type);
-      type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
-      type->ptr()->token_pos_ = d->ReadTokenPosition();
-      type->ptr()->index_ = d->Read<int16_t>();
+      type->untag()->parameterized_class_id_ = d->Read<int32_t>();
+      type->untag()->base_ = d->Read<uint16_t>();
+      type->untag()->index_ = d->Read<uint16_t>();
       const uint8_t combined = d->Read<uint8_t>();
-      type->ptr()->flags_ = combined >> kNullabilityBitSize;
-      type->ptr()->nullability_ = combined & kNullabilityBitMask;
+      type->untag()->flags_ = combined >> kNullabilityBitSize;
+      type->untag()->nullability_ = combined & kNullabilityBitMask;
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
-      CanonicalTypeParameterSet table(
-          d->zone(), d->isolate()->object_store()->canonical_type_parameters());
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize) {
+      Thread* thread = Thread::Current();
       TypeParameter& type_param = TypeParameter::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         type_param ^= refs.At(i);
-        ASSERT(type_param.IsCanonical());
-        if (!type_param.IsDeclaration()) {
-          bool present = table.Insert(type_param);
-          ASSERT(!present);
-        }
+        type_param ^= type_param.Canonicalize(thread, nullptr);
+        refs.SetAt(i, type_param);
       }
-      d->isolate()->object_store()->set_canonical_type_parameters(
-          table.Release());
     }
 
     TypeParameter& type_param = TypeParameter::Handle(d->zone());
@@ -3656,12 +3825,14 @@
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
-class ClosureDeserializationCluster : public DeserializationCluster {
+class ClosureDeserializationCluster
+    : public AbstractInstanceDeserializationCluster {
  public:
-  ClosureDeserializationCluster() : DeserializationCluster("Closure") {}
+  ClosureDeserializationCluster()
+      : AbstractInstanceDeserializationCluster("Closure") {}
   ~ClosureDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3671,11 +3842,11 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ClosurePtr closure = static_cast<ClosurePtr>(d->Ref(id));
       Deserializer::InitializeHeader(closure, kClosureCid,
-                                     Closure::InstanceSize(), is_canonical);
+                                     Closure::InstanceSize(), stamp_canonical);
       ReadFromTo(closure);
     }
   }
@@ -3711,7 +3882,7 @@
       MintPtr mint = mints_[i];
       s->AssignRef(mint);
       AutoTraceObject(mint);
-      s->Write<int64_t>(mint->ptr()->value_);
+      s->Write<int64_t>(mint->untag()->value_);
     }
   }
 
@@ -3728,7 +3899,7 @@
   MintDeserializationCluster() : DeserializationCluster("int") {}
   ~MintDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     PageSpace* old_space = d->heap()->old_space();
 
     start_index_ = d->next_index();
@@ -3741,27 +3912,32 @@
         MintPtr mint = static_cast<MintPtr>(
             AllocateUninitialized(old_space, Mint::InstanceSize()));
         Deserializer::InitializeHeader(mint, kMintCid, Mint::InstanceSize(),
-                                       is_canonical);
-        mint->ptr()->value_ = value;
+                                       stamp_canonical);
+        mint->untag()->value_ = value;
         d->AssignRef(mint);
       }
     }
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {}
+  void ReadFill(Deserializer* d, bool stamp_canonical) {}
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize) {
       const Class& mint_cls = Class::Handle(
-          d->zone(), Isolate::Current()->object_store()->mint_class());
-      mint_cls.set_constants(Object::null_array());
+          d->zone(), d->isolate_group()->object_store()->mint_class());
       Object& number = Object::Handle(d->zone());
+      Mint& number2 = Mint::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
         number = refs.At(i);
-        if (number.IsMint()) {
-          ASSERT(number.IsCanonical());
+        if (!number.IsMint()) continue;
+        number2 =
+            mint_cls.LookupCanonicalMint(d->zone(), Mint::Cast(number).value());
+        if (number2.IsNull()) {
+          number.SetCanonical();
           mint_cls.InsertCanonicalMint(d->zone(), Mint::Cast(number));
+        } else {
+          refs.SetAt(i, number2);
         }
       }
     }
@@ -3794,7 +3970,7 @@
     for (intptr_t i = 0; i < count; i++) {
       DoublePtr dbl = objects_[i];
       AutoTraceObject(dbl);
-      s->Write<double>(dbl->ptr()->value_);
+      s->Write<double>(dbl->untag()->value_);
     }
   }
 
@@ -3808,7 +3984,7 @@
   DoubleDeserializationCluster() : DeserializationCluster("double") {}
   ~DoubleDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3818,12 +3994,33 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       DoublePtr dbl = static_cast<DoublePtr>(d->Ref(id));
       Deserializer::InitializeHeader(dbl, kDoubleCid, Double::InstanceSize(),
-                                     is_canonical);
-      dbl->ptr()->value_ = d->Read<double>();
+                                     stamp_canonical);
+      dbl->untag()->value_ = d->Read<double>();
+    }
+  }
+
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize) {
+      const Class& cls = Class::Handle(
+          d->zone(), d->isolate_group()->object_store()->double_class());
+      SafepointMutexLocker ml(
+          d->isolate_group()->constant_canonicalization_mutex());
+      Double& dbl = Double::Handle(d->zone());
+      Double& dbl2 = Double::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        dbl ^= refs.At(i);
+        dbl2 = cls.LookupCanonicalDouble(d->zone(), dbl.value());
+        if (dbl2.IsNull()) {
+          dbl.SetCanonical();
+          cls.InsertCanonicalDouble(d->zone(), dbl);
+        } else {
+          refs.SetAt(i, dbl2);
+        }
+      }
     }
   }
 };
@@ -3872,7 +4069,7 @@
       : DeserializationCluster("GrowableObjectArray") {}
   ~GrowableObjectArrayDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3883,13 +4080,13 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       GrowableObjectArrayPtr list =
           static_cast<GrowableObjectArrayPtr>(d->Ref(id));
       Deserializer::InitializeHeader(list, kGrowableObjectArrayCid,
                                      GrowableObjectArray::InstanceSize(),
-                                     is_canonical);
+                                     stamp_canonical);
       ReadFromTo(list);
     }
   }
@@ -3915,7 +4112,7 @@
       TypedDataPtr data = objects_[i];
       s->AssignRef(data);
       AutoTraceObject(data);
-      const intptr_t length = Smi::Value(data->ptr()->length_);
+      const intptr_t length = Smi::Value(data->untag()->length_);
       s->WriteUnsigned(length);
     }
   }
@@ -3926,9 +4123,9 @@
     for (intptr_t i = 0; i < count; i++) {
       TypedDataPtr data = objects_[i];
       AutoTraceObject(data);
-      const intptr_t length = Smi::Value(data->ptr()->length_);
+      const intptr_t length = Smi::Value(data->untag()->length_);
       s->WriteUnsigned(length);
-      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->untag()->data());
       s->WriteBytes(cdata, length * element_size);
     }
   }
@@ -3945,7 +4142,7 @@
       : DeserializationCluster("TypedData"), cid_(cid) {}
   ~TypedDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3958,18 +4155,20 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypedDataPtr data = static_cast<TypedDataPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
       const intptr_t length_in_bytes = length * element_size;
-      Deserializer::InitializeHeader(
-          data, cid_, TypedData::InstanceSize(length_in_bytes), is_canonical);
-      data->ptr()->length_ = Smi::New(length);
-      data->ptr()->RecomputeDataField();
-      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
+      Deserializer::InitializeHeader(data, cid_,
+                                     TypedData::InstanceSize(length_in_bytes),
+                                     stamp_canonical);
+      data->untag()->length_ = Smi::New(length);
+      data->untag()->RecomputeDataField();
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->untag()->data());
       d->ReadBytes(cdata, length_in_bytes);
     }
   }
@@ -4023,7 +4222,7 @@
       : DeserializationCluster("TypedDataView"), cid_(cid) {}
   ~TypedDataViewDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4034,16 +4233,17 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
-      Deserializer::InitializeHeader(view, cid_, TypedDataView::InstanceSize(),
-                                     is_canonical);
+      Deserializer::InitializeHeader(view, cid_, TypedDataView::InstanceSize());
       ReadFromTo(view);
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    ASSERT(!canonicalize);
     auto& view = TypedDataView::Handle(d->zone());
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       view ^= refs.At(id);
@@ -4083,9 +4283,9 @@
     for (intptr_t i = 0; i < count; i++) {
       ExternalTypedDataPtr data = objects_[i];
       AutoTraceObject(data);
-      const intptr_t length = Smi::Value(data->ptr()->length_);
+      const intptr_t length = Smi::Value(data->untag()->length_);
       s->WriteUnsigned(length);
-      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data_);
+      uint8_t* cdata = reinterpret_cast<uint8_t*>(data->untag()->data_);
       s->Align(ExternalTypedData::kDataSerializationAlignment);
       s->WriteBytes(cdata, length * element_size);
     }
@@ -4103,7 +4303,7 @@
       : DeserializationCluster("ExternalTypedData"), cid_(cid) {}
   ~ExternalTypedDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4114,7 +4314,8 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -4122,9 +4323,9 @@
       const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(data, cid_,
                                      ExternalTypedData::InstanceSize());
-      data->ptr()->length_ = Smi::New(length);
+      data->untag()->length_ = Smi::New(length);
       d->Align(ExternalTypedData::kDataSerializationAlignment);
-      data->ptr()->data_ = const_cast<uint8_t*>(d->CurrentBufferAddress());
+      data->untag()->data_ = const_cast<uint8_t*>(d->CurrentBufferAddress());
       d->Advance(length * element_size);
       // No finalizer / external size 0.
     }
@@ -4175,7 +4376,7 @@
   StackTraceDeserializationCluster() : DeserializationCluster("StackTrace") {}
   ~StackTraceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4186,7 +4387,8 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       StackTracePtr trace = static_cast<StackTracePtr>(d->Ref(id));
       Deserializer::InitializeHeader(trace, kStackTraceCid,
@@ -4224,9 +4426,9 @@
       RegExpPtr regexp = objects_[i];
       AutoTraceObject(regexp);
       WriteFromTo(regexp);
-      s->Write<int32_t>(regexp->ptr()->num_one_byte_registers_);
-      s->Write<int32_t>(regexp->ptr()->num_two_byte_registers_);
-      s->Write<int8_t>(regexp->ptr()->type_flags_);
+      s->Write<int32_t>(regexp->untag()->num_one_byte_registers_);
+      s->Write<int32_t>(regexp->untag()->num_two_byte_registers_);
+      s->Write<int8_t>(regexp->untag()->type_flags_);
     }
   }
 
@@ -4240,7 +4442,7 @@
   RegExpDeserializationCluster() : DeserializationCluster("RegExp") {}
   ~RegExpDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4250,15 +4452,16 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RegExpPtr regexp = static_cast<RegExpPtr>(d->Ref(id));
       Deserializer::InitializeHeader(regexp, kRegExpCid,
                                      RegExp::InstanceSize());
       ReadFromTo(regexp);
-      regexp->ptr()->num_one_byte_registers_ = d->Read<int32_t>();
-      regexp->ptr()->num_two_byte_registers_ = d->Read<int32_t>();
-      regexp->ptr()->type_flags_ = d->Read<int8_t>();
+      regexp->untag()->num_one_byte_registers_ = d->Read<int32_t>();
+      regexp->untag()->num_two_byte_registers_ = d->Read<int32_t>();
+      regexp->untag()->type_flags_ = d->Read<int8_t>();
     }
   }
 };
@@ -4305,7 +4508,7 @@
       : DeserializationCluster("WeakProperty") {}
   ~WeakPropertyDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4316,13 +4519,14 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
+    ASSERT(!stamp_canonical);  // Never canonical.
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       WeakPropertyPtr property = static_cast<WeakPropertyPtr>(d->Ref(id));
       Deserializer::InitializeHeader(property, kWeakPropertyCid,
                                      WeakProperty::InstanceSize());
       ReadFromTo(property);
-      property->ptr()->next_ = WeakProperty::null();
+      property->untag()->next_ = WeakProperty::null();
     }
   }
 };
@@ -4337,11 +4541,11 @@
     LinkedHashMapPtr map = LinkedHashMap::RawCast(object);
     objects_.Add(map);
 
-    s->Push(map->ptr()->type_arguments_);
+    s->Push(map->untag()->type_arguments_);
 
-    intptr_t used_data = Smi::Value(map->ptr()->used_data_);
-    ArrayPtr data_array = map->ptr()->data_;
-    ObjectPtr* data_elements = data_array->ptr()->data();
+    intptr_t used_data = Smi::Value(map->untag()->used_data_);
+    ArrayPtr data_array = map->untag()->data_;
+    ObjectPtr* data_elements = data_array->untag()->data();
     for (intptr_t i = 0; i < used_data; i += 2) {
       ObjectPtr key = data_elements[i];
       if (key != data_array) {
@@ -4370,15 +4574,15 @@
 
       WriteField(map, type_arguments_);
 
-      const intptr_t used_data = Smi::Value(map->ptr()->used_data_);
+      const intptr_t used_data = Smi::Value(map->untag()->used_data_);
       ASSERT((used_data & 1) == 0);  // Keys + values, so must be even.
-      const intptr_t deleted_keys = Smi::Value(map->ptr()->deleted_keys_);
+      const intptr_t deleted_keys = Smi::Value(map->untag()->deleted_keys_);
 
       // Write out the number of (not deleted) key/value pairs that will follow.
       s->Write<int32_t>((used_data >> 1) - deleted_keys);
 
-      ArrayPtr data_array = map->ptr()->data_;
-      ObjectPtr* data_elements = data_array->ptr()->data();
+      ArrayPtr data_array = map->untag()->data_;
+      ObjectPtr* data_elements = data_array->untag()->data();
       for (intptr_t i = 0; i < used_data; i += 2) {
         ObjectPtr key = data_elements[i];
         if (key != data_array) {
@@ -4395,13 +4599,14 @@
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
-class LinkedHashMapDeserializationCluster : public DeserializationCluster {
+class LinkedHashMapDeserializationCluster
+    : public AbstractInstanceDeserializationCluster {
  public:
   LinkedHashMapDeserializationCluster()
-      : DeserializationCluster("LinkedHashMap") {}
+      : AbstractInstanceDeserializationCluster("LinkedHashMap") {}
   ~LinkedHashMapDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4412,15 +4617,17 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     PageSpace* old_space = d->heap()->old_space();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LinkedHashMapPtr map = static_cast<LinkedHashMapPtr>(d->Ref(id));
-      Deserializer::InitializeHeader(
-          map, kLinkedHashMapCid, LinkedHashMap::InstanceSize(), is_canonical);
+      Deserializer::InitializeHeader(map, kLinkedHashMapCid,
+                                     LinkedHashMap::InstanceSize(),
+                                     stamp_canonical);
 
-      map->ptr()->type_arguments_ = static_cast<TypeArgumentsPtr>(d->ReadRef());
+      map->untag()->type_arguments_ =
+          static_cast<TypeArgumentsPtr>(d->ReadRef());
 
       // TODO(rmacnak): Reserve ref ids and co-allocate in ReadAlloc.
       intptr_t pairs = d->Read<int32_t>();
@@ -4431,21 +4638,21 @@
 
       ArrayPtr data = static_cast<ArrayPtr>(
           AllocateUninitialized(old_space, Array::InstanceSize(data_size)));
-      data->ptr()->type_arguments_ = TypeArguments::null();
-      data->ptr()->length_ = Smi::New(data_size);
+      data->untag()->type_arguments_ = TypeArguments::null();
+      data->untag()->length_ = Smi::New(data_size);
       intptr_t i;
       for (i = 0; i < used_data; i++) {
-        data->ptr()->data()[i] = d->ReadRef();
+        data->untag()->data()[i] = d->ReadRef();
       }
       for (; i < data_size; i++) {
-        data->ptr()->data()[i] = Object::null();
+        data->untag()->data()[i] = Object::null();
       }
 
-      map->ptr()->index_ = TypedData::null();
-      map->ptr()->hash_mask_ = Smi::New(0);
-      map->ptr()->data_ = data;
-      map->ptr()->used_data_ = Smi::New(used_data);
-      map->ptr()->deleted_keys_ = Smi::New(0);
+      map->untag()->index_ = TypedData::null();
+      map->untag()->hash_mask_ = Smi::New(0);
+      map->untag()->data_ = data;
+      map->untag()->used_data_ = Smi::New(used_data);
+      map->untag()->deleted_keys_ = Smi::New(0);
     }
   }
 };
@@ -4461,10 +4668,10 @@
     ArrayPtr array = Array::RawCast(object);
     objects_.Add(array);
 
-    s->Push(array->ptr()->type_arguments_);
-    const intptr_t length = Smi::Value(array->ptr()->length_);
+    s->Push(array->untag()->type_arguments_);
+    const intptr_t length = Smi::Value(array->untag()->length_);
     for (intptr_t i = 0; i < length; i++) {
-      s->Push(array->ptr()->data()[i]);
+      s->Push(array->untag()->data()[i]);
     }
   }
 
@@ -4476,7 +4683,7 @@
       ArrayPtr array = objects_[i];
       s->AssignRef(array);
       AutoTraceObject(array);
-      const intptr_t length = Smi::Value(array->ptr()->length_);
+      const intptr_t length = Smi::Value(array->untag()->length_);
       s->WriteUnsigned(length);
     }
   }
@@ -4486,11 +4693,11 @@
     for (intptr_t i = 0; i < count; i++) {
       ArrayPtr array = objects_[i];
       AutoTraceObject(array);
-      const intptr_t length = Smi::Value(array->ptr()->length_);
+      const intptr_t length = Smi::Value(array->untag()->length_);
       s->WriteUnsigned(length);
       WriteField(array, type_arguments_);
       for (intptr_t j = 0; j < length; j++) {
-        s->WriteElementRef(array->ptr()->data()[j], j);
+        s->WriteElementRef(array->untag()->data()[j], j);
       }
     }
   }
@@ -4501,13 +4708,14 @@
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
-class ArrayDeserializationCluster : public DeserializationCluster {
+class ArrayDeserializationCluster
+    : public AbstractInstanceDeserializationCluster {
  public:
   explicit ArrayDeserializationCluster(intptr_t cid)
-      : DeserializationCluster("Array"), cid_(cid) {}
+      : AbstractInstanceDeserializationCluster("Array"), cid_(cid) {}
   ~ArrayDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4519,17 +4727,17 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ArrayPtr array = static_cast<ArrayPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(array, cid_, Array::InstanceSize(length),
-                                     is_canonical);
-      array->ptr()->type_arguments_ =
+                                     stamp_canonical);
+      array->untag()->type_arguments_ =
           static_cast<TypeArgumentsPtr>(d->ReadRef());
-      array->ptr()->length_ = Smi::New(length);
+      array->untag()->length_ = Smi::New(length);
       for (intptr_t j = 0; j < length; j++) {
-        array->ptr()->data()[j] = d->ReadRef();
+        array->untag()->data()[j] = d->ReadRef();
       }
     }
   }
@@ -4557,7 +4765,7 @@
       OneByteStringPtr str = objects_[i];
       s->AssignRef(str);
       AutoTraceObject(str);
-      const intptr_t length = Smi::Value(str->ptr()->length_);
+      const intptr_t length = Smi::Value(str->untag()->length_);
       s->WriteUnsigned(length);
     }
   }
@@ -4567,10 +4775,10 @@
     for (intptr_t i = 0; i < count; i++) {
       OneByteStringPtr str = objects_[i];
       AutoTraceObject(str);
-      const intptr_t length = Smi::Value(str->ptr()->length_);
+      const intptr_t length = Smi::Value(str->untag()->length_);
       ASSERT(length <= compiler::target::kSmiMax);
       s->WriteUnsigned(length);
-      s->WriteBytes(str->ptr()->data(), length);
+      s->WriteBytes(str->untag()->data(), length);
     }
   }
 
@@ -4579,13 +4787,40 @@
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
-class OneByteStringDeserializationCluster : public DeserializationCluster {
+class StringDeserializationCluster : public DeserializationCluster {
+ protected:
+  explicit StringDeserializationCluster(const char* name)
+      : DeserializationCluster(name) {}
+
+ public:
+  void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) {
+    if (canonicalize) {
+      CanonicalStringSet table(
+          d->zone(), d->isolate_group()->object_store()->symbol_table());
+      String& str = String::Handle(d->zone());
+      String& str2 = String::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        str ^= refs.At(i);
+        str2 ^= table.InsertOrGet(str);
+        if (str.ptr() == str2.ptr()) {
+          str.SetCanonical();
+        } else {
+          refs.SetAt(i, str2);
+        }
+      }
+      d->isolate_group()->object_store()->set_symbol_table(table.Release());
+    }
+  }
+};
+
+class OneByteStringDeserializationCluster
+    : public StringDeserializationCluster {
  public:
   OneByteStringDeserializationCluster()
-      : DeserializationCluster("OneByteString") {}
+      : StringDeserializationCluster("OneByteString") {}
   ~OneByteStringDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4597,38 +4832,23 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       OneByteStringPtr str = static_cast<OneByteStringPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(str, kOneByteStringCid,
                                      OneByteString::InstanceSize(length),
-                                     is_canonical);
-      str->ptr()->length_ = Smi::New(length);
+                                     stamp_canonical);
+      str->untag()->length_ = Smi::New(length);
       StringHasher hasher;
       for (intptr_t j = 0; j < length; j++) {
         uint8_t code_unit = d->Read<uint8_t>();
-        str->ptr()->data()[j] = code_unit;
+        str->untag()->data()[j] = code_unit;
         hasher.Add(code_unit);
       }
       String::SetCachedHash(str, hasher.Finalize());
     }
   }
-
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
-      CanonicalStringSet table(d->zone(),
-                               d->isolate()->object_store()->symbol_table());
-      String& str = String::Handle(d->zone());
-      for (intptr_t i = start_index_; i < stop_index_; i++) {
-        str ^= refs.At(i);
-        ASSERT(str.IsCanonical());
-        bool present = table.Insert(str);
-        ASSERT(!present);
-      }
-      d->isolate()->object_store()->set_symbol_table(table.Release());
-    }
-  }
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -4650,7 +4870,7 @@
       TwoByteStringPtr str = objects_[i];
       s->AssignRef(str);
       AutoTraceObject(str);
-      const intptr_t length = Smi::Value(str->ptr()->length_);
+      const intptr_t length = Smi::Value(str->untag()->length_);
       s->WriteUnsigned(length);
     }
   }
@@ -4660,10 +4880,11 @@
     for (intptr_t i = 0; i < count; i++) {
       TwoByteStringPtr str = objects_[i];
       AutoTraceObject(str);
-      const intptr_t length = Smi::Value(str->ptr()->length_);
+      const intptr_t length = Smi::Value(str->untag()->length_);
       ASSERT(length <= (compiler::target::kSmiMax / 2));
       s->WriteUnsigned(length);
-      s->WriteBytes(reinterpret_cast<uint8_t*>(str->ptr()->data()), length * 2);
+      s->WriteBytes(reinterpret_cast<uint8_t*>(str->untag()->data()),
+                    length * 2);
     }
   }
 
@@ -4672,13 +4893,14 @@
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
-class TwoByteStringDeserializationCluster : public DeserializationCluster {
+class TwoByteStringDeserializationCluster
+    : public StringDeserializationCluster {
  public:
   TwoByteStringDeserializationCluster()
-      : DeserializationCluster("TwoByteString") {}
+      : StringDeserializationCluster("TwoByteString") {}
   ~TwoByteStringDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d, bool is_canonical) {
+  void ReadAlloc(Deserializer* d, bool stamp_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4690,39 +4912,24 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d, bool is_canonical) {
+  void ReadFill(Deserializer* d, bool stamp_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TwoByteStringPtr str = static_cast<TwoByteStringPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
       Deserializer::InitializeHeader(str, kTwoByteStringCid,
                                      TwoByteString::InstanceSize(length),
-                                     is_canonical);
-      str->ptr()->length_ = Smi::New(length);
+                                     stamp_canonical);
+      str->untag()->length_ = Smi::New(length);
       StringHasher hasher;
       for (intptr_t j = 0; j < length; j++) {
         uint16_t code_unit = d->Read<uint8_t>();
         code_unit = code_unit | (d->Read<uint8_t>() << 8);
-        str->ptr()->data()[j] = code_unit;
+        str->untag()->data()[j] = code_unit;
         hasher.Add(code_unit);
       }
       String::SetCachedHash(str, hasher.Finalize());
     }
   }
-
-  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
-      CanonicalStringSet table(d->zone(),
-                               d->isolate()->object_store()->symbol_table());
-      String& str = String::Handle(d->zone());
-      for (intptr_t i = start_index_; i < stop_index_; i++) {
-        str ^= refs.At(i);
-        ASSERT(str.IsCanonical());
-        bool present = table.Insert(str);
-        ASSERT(!present);
-      }
-      d->isolate()->object_store()->set_symbol_table(table.Release());
-    }
-  }
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -4754,34 +4961,34 @@
     // written into the snapshot.
 
     s->AddBaseObject(Object::null(), "Null", "null");
-    s->AddBaseObject(Object::sentinel().raw(), "Null", "sentinel");
-    s->AddBaseObject(Object::transition_sentinel().raw(), "Null",
+    s->AddBaseObject(Object::sentinel().ptr(), "Null", "sentinel");
+    s->AddBaseObject(Object::transition_sentinel().ptr(), "Null",
                      "transition_sentinel");
-    s->AddBaseObject(Object::empty_array().raw(), "Array", "<empty_array>");
-    s->AddBaseObject(Object::zero_array().raw(), "Array", "<zero_array>");
-    s->AddBaseObject(Object::dynamic_type().raw(), "Type", "<dynamic type>");
-    s->AddBaseObject(Object::void_type().raw(), "Type", "<void type>");
-    s->AddBaseObject(Object::empty_type_arguments().raw(), "TypeArguments",
+    s->AddBaseObject(Object::empty_array().ptr(), "Array", "<empty_array>");
+    s->AddBaseObject(Object::zero_array().ptr(), "Array", "<zero_array>");
+    s->AddBaseObject(Object::dynamic_type().ptr(), "Type", "<dynamic type>");
+    s->AddBaseObject(Object::void_type().ptr(), "Type", "<void type>");
+    s->AddBaseObject(Object::empty_type_arguments().ptr(), "TypeArguments",
                      "[]");
-    s->AddBaseObject(Bool::True().raw(), "bool", "true");
-    s->AddBaseObject(Bool::False().raw(), "bool", "false");
-    ASSERT(Object::extractor_parameter_types().raw() != Object::null());
-    s->AddBaseObject(Object::extractor_parameter_types().raw(), "Array",
+    s->AddBaseObject(Bool::True().ptr(), "bool", "true");
+    s->AddBaseObject(Bool::False().ptr(), "bool", "false");
+    ASSERT(Object::extractor_parameter_types().ptr() != Object::null());
+    s->AddBaseObject(Object::extractor_parameter_types().ptr(), "Array",
                      "<extractor parameter types>");
-    ASSERT(Object::extractor_parameter_names().raw() != Object::null());
-    s->AddBaseObject(Object::extractor_parameter_names().raw(), "Array",
+    ASSERT(Object::extractor_parameter_names().ptr() != Object::null());
+    s->AddBaseObject(Object::extractor_parameter_names().ptr(), "Array",
                      "<extractor parameter names>");
-    s->AddBaseObject(Object::empty_context_scope().raw(), "ContextScope",
+    s->AddBaseObject(Object::empty_context_scope().ptr(), "ContextScope",
                      "<empty>");
-    s->AddBaseObject(Object::empty_object_pool().raw(), "ObjectPool",
+    s->AddBaseObject(Object::empty_object_pool().ptr(), "ObjectPool",
                      "<empty>");
-    s->AddBaseObject(Object::empty_compressed_stackmaps().raw(),
+    s->AddBaseObject(Object::empty_compressed_stackmaps().ptr(),
                      "CompressedStackMaps", "<empty>");
-    s->AddBaseObject(Object::empty_descriptors().raw(), "PcDescriptors",
+    s->AddBaseObject(Object::empty_descriptors().ptr(), "PcDescriptors",
                      "<empty>");
-    s->AddBaseObject(Object::empty_var_descriptors().raw(),
+    s->AddBaseObject(Object::empty_var_descriptors().ptr(),
                      "LocalVarDescriptors", "<empty>");
-    s->AddBaseObject(Object::empty_exception_handlers().raw(),
+    s->AddBaseObject(Object::empty_exception_handlers().ptr(),
                      "ExceptionHandlers", "<empty>");
 
     for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
@@ -4795,7 +5002,7 @@
     s->AddBaseObject(SubtypeTestCache::cached_array_, "Array",
                      "<empty subtype entries>");
 
-    ClassTable* table = s->isolate()->class_table();
+    ClassTable* table = s->isolate_group()->class_table();
     for (intptr_t cid = kClassCid; cid < kInstanceCid; cid++) {
       // Error, CallSiteData has no class object.
       if (cid != kErrorCid && cid != kCallSiteDataCid) {
@@ -4808,25 +5015,25 @@
 
     if (!Snapshot::IncludesCode(s->kind())) {
       for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-        s->AddBaseObject(StubCode::EntryAt(i).raw(), "Code", "<stub code>");
+        s->AddBaseObject(StubCode::EntryAt(i).ptr(), "Code", "<stub code>");
       }
     }
   }
 
   void PushRoots(Serializer* s) {
-    s->Push(symbols_.raw());
+    s->Push(symbols_.ptr());
     if (Snapshot::IncludesCode(s->kind())) {
       for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-        s->Push(StubCode::EntryAt(i).raw());
+        s->Push(StubCode::EntryAt(i).ptr());
       }
     }
   }
 
   void WriteRoots(Serializer* s) {
-    s->WriteRootRef(symbols_.raw(), "symbol-table");
+    s->WriteRootRef(symbols_.ptr(), "symbol-table");
     if (Snapshot::IncludesCode(s->kind())) {
       for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-        s->WriteRootRef(StubCode::EntryAt(i).raw(),
+        s->WriteRootRef(StubCode::EntryAt(i).ptr(),
                         zone_->PrintToString("Stub:%s", StubCode::NameAt(i)));
       }
     }
@@ -4847,25 +5054,25 @@
     // written into the snapshot.
 
     d->AddBaseObject(Object::null());
-    d->AddBaseObject(Object::sentinel().raw());
-    d->AddBaseObject(Object::transition_sentinel().raw());
-    d->AddBaseObject(Object::empty_array().raw());
-    d->AddBaseObject(Object::zero_array().raw());
-    d->AddBaseObject(Object::dynamic_type().raw());
-    d->AddBaseObject(Object::void_type().raw());
-    d->AddBaseObject(Object::empty_type_arguments().raw());
-    d->AddBaseObject(Bool::True().raw());
-    d->AddBaseObject(Bool::False().raw());
-    ASSERT(Object::extractor_parameter_types().raw() != Object::null());
-    d->AddBaseObject(Object::extractor_parameter_types().raw());
-    ASSERT(Object::extractor_parameter_names().raw() != Object::null());
-    d->AddBaseObject(Object::extractor_parameter_names().raw());
-    d->AddBaseObject(Object::empty_context_scope().raw());
-    d->AddBaseObject(Object::empty_object_pool().raw());
-    d->AddBaseObject(Object::empty_compressed_stackmaps().raw());
-    d->AddBaseObject(Object::empty_descriptors().raw());
-    d->AddBaseObject(Object::empty_var_descriptors().raw());
-    d->AddBaseObject(Object::empty_exception_handlers().raw());
+    d->AddBaseObject(Object::sentinel().ptr());
+    d->AddBaseObject(Object::transition_sentinel().ptr());
+    d->AddBaseObject(Object::empty_array().ptr());
+    d->AddBaseObject(Object::zero_array().ptr());
+    d->AddBaseObject(Object::dynamic_type().ptr());
+    d->AddBaseObject(Object::void_type().ptr());
+    d->AddBaseObject(Object::empty_type_arguments().ptr());
+    d->AddBaseObject(Bool::True().ptr());
+    d->AddBaseObject(Bool::False().ptr());
+    ASSERT(Object::extractor_parameter_types().ptr() != Object::null());
+    d->AddBaseObject(Object::extractor_parameter_types().ptr());
+    ASSERT(Object::extractor_parameter_names().ptr() != Object::null());
+    d->AddBaseObject(Object::extractor_parameter_names().ptr());
+    d->AddBaseObject(Object::empty_context_scope().ptr());
+    d->AddBaseObject(Object::empty_object_pool().ptr());
+    d->AddBaseObject(Object::empty_compressed_stackmaps().ptr());
+    d->AddBaseObject(Object::empty_descriptors().ptr());
+    d->AddBaseObject(Object::empty_var_descriptors().ptr());
+    d->AddBaseObject(Object::empty_exception_handlers().ptr());
 
     for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
       d->AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
@@ -4875,7 +5082,7 @@
     }
     d->AddBaseObject(SubtypeTestCache::cached_array_);
 
-    ClassTable* table = d->isolate()->class_table();
+    ClassTable* table = d->isolate_group()->class_table();
     for (intptr_t cid = kClassCid; cid <= kUnwindErrorCid; cid++) {
       // Error, CallSiteData has no class object.
       if (cid != kErrorCid && cid != kCallSiteDataCid) {
@@ -4888,14 +5095,14 @@
 
     if (!Snapshot::IncludesCode(d->kind())) {
       for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
-        d->AddBaseObject(StubCode::EntryAt(i).raw());
+        d->AddBaseObject(StubCode::EntryAt(i).ptr());
       }
     }
   }
 
   void ReadRoots(Deserializer* d) {
     symbol_table_ ^= d->ReadRef();
-    d->isolate()->object_store()->set_symbol_table(symbol_table_);
+    d->isolate_group()->object_store()->set_symbol_table(symbol_table_);
     if (Snapshot::IncludesCode(d->kind())) {
       for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
         Code* code = Code::ReadOnlyHandle();
@@ -4910,7 +5117,7 @@
     // allocations (e.g., FinalizeVMIsolate) before allocating new pages.
     d->heap()->old_space()->AbandonBumpAllocation();
 
-    Symbols::InitFromSnapshot(d->isolate());
+    Symbols::InitFromSnapshot(d->isolate_group());
 
     Object::set_vm_isolate_snapshot_object_table(refs);
   }
@@ -4937,6 +5144,7 @@
         object_store_(object_store),
         saved_symbol_table_(Array::Handle()),
         saved_canonical_types_(Array::Handle()),
+        saved_canonical_function_types_(Array::Handle()),
         saved_canonical_type_parameters_(Array::Handle()),
         saved_canonical_type_arguments_(Array::Handle()),
         dispatch_table_entries_(Array::Handle()) {
@@ -4948,6 +5156,10 @@
     object_store->set_canonical_types(
         Array::Handle(HashTables::New<CanonicalTypeSet>(4)));
 
+    saved_canonical_function_types_ = object_store->canonical_function_types();
+    object_store->set_canonical_function_types(
+        Array::Handle(HashTables::New<CanonicalFunctionTypeSet>(4)));
+
     saved_canonical_type_parameters_ =
         object_store->canonical_type_parameters();
     object_store->set_canonical_type_parameters(
@@ -4960,6 +5172,8 @@
   ~ProgramSerializationRoots() {
     object_store_->set_symbol_table(saved_symbol_table_);
     object_store_->set_canonical_types(saved_canonical_types_);
+    object_store_->set_canonical_function_types(
+        saved_canonical_function_types_);
     object_store_->set_canonical_type_parameters(
         saved_canonical_type_parameters_);
     object_store_->set_canonical_type_arguments(
@@ -4976,7 +5190,7 @@
     } else {
       // Base objects carried over from WriteVMSnapshot.
       for (intptr_t i = 0; i < base_objects_->length(); i++) {
-        s->AddBaseObject((*base_objects_)[i]->raw());
+        s->AddBaseObject((*base_objects_)[i]->ptr());
       }
     }
   }
@@ -5021,6 +5235,7 @@
   ObjectStore* object_store_;
   Array& saved_symbol_table_;
   Array& saved_canonical_types_;
+  Array& saved_canonical_function_types_;
   Array& saved_canonical_type_parameters_;
   Array& saved_canonical_type_arguments_;
   Array& dispatch_table_entries_;
@@ -5053,12 +5268,13 @@
   }
 
   void PostLoad(Deserializer* d, const Array& refs) {
-    Isolate* isolate = d->thread()->isolate();
-    isolate->class_table()->CopySizesFromClassObjects();
+    auto isolate = d->thread()->isolate();
+    auto isolate_group = d->thread()->isolate_group();
+    isolate_group->class_table()->CopySizesFromClassObjects();
     d->heap()->old_space()->EvaluateAfterLoading();
 
     const Array& units =
-        Array::Handle(isolate->object_store()->loading_units());
+        Array::Handle(isolate_group->object_store()->loading_units());
     if (!units.IsNull()) {
       LoadingUnit& unit = LoadingUnit::Handle();
       unit ^= units.At(LoadingUnit::kRootId);
@@ -5083,7 +5299,7 @@
   void AddBaseObjects(Serializer* s) {
     ZoneGrowableArray<Object*>* objects = unit_->parent()->objects();
     for (intptr_t i = 0; i < objects->length(); i++) {
-      s->AddBaseObject(objects->At(i)->raw());
+      s->AddBaseObject(objects->At(i)->ptr());
     }
   }
 
@@ -5092,16 +5308,26 @@
     for (intptr_t i = 0; i < num_deferred_objects; i++) {
       const Object* deferred_object = (*unit_->deferred_objects())[i];
       ASSERT(deferred_object->IsCode());
-      CodePtr code = static_cast<CodePtr>(deferred_object->raw());
-      s->Push(code->ptr()->compressed_stackmaps_);
-      s->Push(code->ptr()->code_source_map_);
-    }
-    {
-      GrowableArray<CodePtr> raw_codes(num_deferred_objects);
-      for (intptr_t i = 0; i < num_deferred_objects; i++) {
-        raw_codes.Add((*unit_->deferred_objects())[i]->raw());
+      CodePtr code = static_cast<CodePtr>(deferred_object->ptr());
+      if (FLAG_use_bare_instructions) {
+        if (FLAG_retain_function_objects) {
+          ObjectPoolPtr pool = code->untag()->object_pool_;
+          if (pool != ObjectPool::null()) {
+            const intptr_t length = pool->untag()->length_;
+            uint8_t* entry_bits = pool->untag()->entry_bits();
+            for (intptr_t i = 0; i < length; i++) {
+              auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
+              if (entry_type == ObjectPool::EntryType::kTaggedObject) {
+                s->Push(pool->untag()->data()[i].raw_obj_);
+              }
+            }
+          }
+        }
+      } else {
+        s->Push(code->untag()->object_pool_);
       }
-      s->PrepareInstructions(&raw_codes);
+      s->Push(code->untag()->compressed_stackmaps_);
+      s->Push(code->untag()->code_source_map_);
     }
   }
 
@@ -5110,7 +5336,7 @@
     intptr_t start_index = 0;
     intptr_t num_deferred_objects = unit_->deferred_objects()->length();
     if (num_deferred_objects != 0) {
-      start_index = s->RefId(unit_->deferred_objects()->At(0)->raw());
+      start_index = s->RefId(unit_->deferred_objects()->At(0)->ptr());
       ASSERT(start_index > 0);
     }
     s->WriteUnsigned(start_index);
@@ -5118,12 +5344,36 @@
     for (intptr_t i = 0; i < num_deferred_objects; i++) {
       const Object* deferred_object = (*unit_->deferred_objects())[i];
       ASSERT(deferred_object->IsCode());
-      CodePtr code = static_cast<CodePtr>(deferred_object->raw());
+      CodePtr code = static_cast<CodePtr>(deferred_object->ptr());
       ASSERT(s->RefId(code) == (start_index + i));
-      s->WriteInstructions(code->ptr()->instructions_,
-                           code->ptr()->unchecked_offset_, code, false);
-      s->WriteRootRef(code->ptr()->compressed_stackmaps_, "deferred-code");
-      s->WriteRootRef(code->ptr()->code_source_map_, "deferred-code");
+      s->WriteInstructions(code->untag()->instructions_,
+                           code->untag()->unchecked_offset_, code, false);
+      if (!FLAG_use_bare_instructions) {
+        s->WriteRootRef(code->untag()->object_pool_, "deferred-code");
+      }
+      s->WriteRootRef(code->untag()->compressed_stackmaps_, "deferred-code");
+      s->WriteRootRef(code->untag()->code_source_map_, "deferred-code");
+    }
+
+    if (FLAG_use_bare_instructions && FLAG_retain_function_objects) {
+      ObjectPoolPtr pool =
+          s->isolate_group()->object_store()->global_object_pool();
+      const intptr_t length = pool->untag()->length_;
+      uint8_t* entry_bits = pool->untag()->entry_bits();
+      intptr_t last_write = 0;
+      for (intptr_t i = 0; i < length; i++) {
+        auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
+        if (entry_type == ObjectPool::EntryType::kTaggedObject) {
+          if (s->IsWritten(pool->untag()->data()[i].raw_obj_)) {
+            intptr_t skip = i - last_write;
+            s->WriteUnsigned(skip);
+            s->WriteRootRef(pool->untag()->data()[i].raw_obj_,
+                            "deferred-literal");
+            last_write = i;
+          }
+        }
+      }
+      s->WriteUnsigned(length - last_write);
     }
 #endif
   }
@@ -5151,21 +5401,38 @@
     for (intptr_t id = deferred_start_index_; id < deferred_stop_index_; id++) {
       CodePtr code = static_cast<CodePtr>(d->Ref(id));
       d->ReadInstructions(code, false);
-      if (code->ptr()->owner_->IsFunction()) {
-        FunctionPtr func = static_cast<FunctionPtr>(code->ptr()->owner_);
-        uword entry_point = code->ptr()->entry_point_;
+      if (code->untag()->owner_->IsFunction()) {
+        FunctionPtr func = static_cast<FunctionPtr>(code->untag()->owner_);
+        uword entry_point = code->untag()->entry_point_;
         ASSERT(entry_point != 0);
-        func->ptr()->entry_point_ = entry_point;
-        uword unchecked_entry_point = code->ptr()->unchecked_entry_point_;
+        func->untag()->entry_point_ = entry_point;
+        uword unchecked_entry_point = code->untag()->unchecked_entry_point_;
         ASSERT(unchecked_entry_point != 0);
-        func->ptr()->unchecked_entry_point_ = unchecked_entry_point;
+        func->untag()->unchecked_entry_point_ = unchecked_entry_point;
       }
-      code->ptr()->compressed_stackmaps_ =
+      if (!FLAG_use_bare_instructions) {
+        code->untag()->object_pool_ = static_cast<ObjectPoolPtr>(d->ReadRef());
+      }
+      code->untag()->compressed_stackmaps_ =
           static_cast<CompressedStackMapsPtr>(d->ReadRef());
-      code->ptr()->code_source_map_ =
+      code->untag()->code_source_map_ =
           static_cast<CodeSourceMapPtr>(d->ReadRef());
     }
 
+    if (FLAG_use_bare_instructions && FLAG_retain_function_objects) {
+      ObjectPoolPtr pool =
+          d->isolate_group()->object_store()->global_object_pool();
+      const intptr_t length = pool->untag()->length_;
+      uint8_t* entry_bits = pool->untag()->entry_bits();
+      for (intptr_t i = d->ReadUnsigned(); i < length; i += d->ReadUnsigned()) {
+        auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
+        ASSERT(entry_type == ObjectPool::EntryType::kTaggedObject);
+        // The existing entry will usually be null, but it might also be an
+        // equivalent object that was duplicated in another loading unit.
+        pool->untag()->data()[i].raw_obj_ = d->ReadRef();
+      }
+    }
+
     // Reinitialize the dispatch table by rereading the table's serialization
     // in the root snapshot.
     IsolateGroup* group = d->thread()->isolate()->group();
@@ -5198,7 +5465,7 @@
                        bool vm,
                        V8SnapshotProfileWriter* profile_writer)
     : ThreadStackResource(thread),
-      heap_(thread->isolate()->heap()),
+      heap_(thread->isolate_group()->heap()),
       zone_(thread->zone()),
       kind_(kind),
       stream_(stream),
@@ -5225,8 +5492,8 @@
       deduped_instructions_sources_(zone_)
 #endif
 {
-  num_cids_ = thread->isolate()->class_table()->NumCids();
-  num_tlc_cids_ = thread->isolate()->class_table()->NumTopLevelCids();
+  num_cids_ = thread->isolate_group()->class_table()->NumCids();
+  num_tlc_cids_ = thread->isolate_group()->class_table()->NumTopLevelCids();
   canonical_clusters_by_cid_ = new SerializationCluster*[num_cids_];
   for (intptr_t i = 0; i < num_cids_; i++) {
     canonical_clusters_by_cid_[i] = nullptr;
@@ -5371,28 +5638,28 @@
       name = FunctionSerializationCluster::MakeDisambiguatedFunctionName(this,
                                                                          func);
       owner_ref_name = "owner_";
-      owner = func->ptr()->owner_;
+      owner = func->untag()->owner_;
       break;
     }
     case kClassCid: {
       ClassPtr cls = static_cast<ClassPtr>(obj);
       type = "Class";
-      name_string = cls->ptr()->name_;
+      name_string = cls->untag()->name_;
       owner_ref_name = "library_";
-      owner = cls->ptr()->library_;
+      owner = cls->untag()->library_;
       break;
     }
     case kPatchClassCid: {
       PatchClassPtr patch_cls = static_cast<PatchClassPtr>(obj);
       type = "PatchClass";
       owner_ref_name = "patched_class_";
-      owner = patch_cls->ptr()->patched_class_;
+      owner = patch_cls->untag()->patched_class_;
       break;
     }
     case kLibraryCid: {
       LibraryPtr lib = static_cast<LibraryPtr>(obj);
       type = "Library";
-      name_string = lib->ptr()->url_;
+      name_string = lib->untag()->url_;
       break;
     }
     default:
@@ -5451,7 +5718,7 @@
 #else
   Zone* Z = zone_;
   if (cid >= kNumPredefinedCids || cid == kInstanceCid) {
-    Push(isolate()->class_table()->At(cid));
+    Push(isolate_group()->class_table()->At(cid));
     return new (Z) InstanceSerializationCluster(cid);
   }
   if (IsTypedDataViewClassId(cid)) {
@@ -5481,8 +5748,6 @@
       return new (Z) FunctionSerializationCluster();
     case kClosureDataCid:
       return new (Z) ClosureDataSerializationCluster();
-    case kSignatureDataCid:
-      return new (Z) SignatureDataSerializationCluster();
     case kFfiTrampolineDataCid:
       return new (Z) FfiTrampolineDataSerializationCluster();
     case kFieldCid:
@@ -5525,6 +5790,8 @@
       return new (Z) LibraryPrefixSerializationCluster();
     case kTypeCid:
       return new (Z) TypeSerializationCluster();
+    case kFunctionTypeCid:
+      return new (Z) FunctionTypeSerializationCluster();
     case kTypeRefCid:
       return new (Z) TypeRefSerializationCluster();
     case kTypeParameterCid:
@@ -5578,6 +5845,9 @@
     // TODO(41974): Are these always type testing stubs?
     unit_id = LoadingUnit::kRootId;
   }
+  if (unit_id == LoadingUnit::kRootId) {
+    return true;
+  }
   if (unit_id != current_loading_unit_id_) {
     if (record) {
       (*loading_units_)[unit_id]->AddDeferredObject(static_cast<CodePtr>(obj));
@@ -5588,11 +5858,58 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-void Serializer::PrepareInstructions(GrowableArray<CodePtr>* code_objects) {
+void Serializer::PrepareInstructions() {
+  if (!Snapshot::IncludesCode(kind())) return;
+
+  CodeSerializationCluster* cluster =
+      static_cast<CodeSerializationCluster*>(clusters_by_cid_[kCodeCid]);
+
+  // Code objects that have identical/duplicate instructions must be adjacent in
+  // the order that Code objects are written because the encoding of the
+  // reference from the Code to the Instructions assumes monotonically
+  // increasing offsets as part of a delta encoding. Also the code order table
+  // that allows for mapping return addresses back to Code objects depends on
+  // this sorting.
+  if (cluster != nullptr) {
+    CodeSerializationCluster::Sort(cluster->objects());
+  }
+  if ((loading_units_ != nullptr) &&
+      (current_loading_unit_id_ == LoadingUnit::kRootId)) {
+    for (intptr_t i = LoadingUnit::kRootId + 1; i < loading_units_->length();
+         i++) {
+      auto unit_objects = loading_units_->At(i)->deferred_objects();
+      CodeSerializationCluster::Sort(unit_objects);
+      for (intptr_t j = 0; j < unit_objects->length(); j++) {
+        cluster->deferred_objects()->Add(unit_objects->At(j)->ptr());
+      }
+    }
+  }
+
 #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
   if ((kind() == Snapshot::kFullAOT) && FLAG_use_bare_instructions) {
+    // Group the code objects whose instructions are not being deferred in this
+    // snapshot unit in the order they will be written: first the code objects
+    // encountered for this first time in this unit being written by the
+    // CodeSerializationCluster, then code object previously deferred whose
+    // instructions are now written by UnitSerializationRoots. This order needs
+    // to be known to finalize bare-instructions-mode's PC-relative calls.
+    GrowableArray<CodePtr> code_objects;
+    if (cluster != nullptr) {
+      auto in = cluster->objects();
+      for (intptr_t i = 0; i < in->length(); i++) {
+        code_objects.Add(in->At(i));
+      }
+    }
+    if (loading_units_ != nullptr) {
+      auto in =
+          loading_units_->At(current_loading_unit_id_)->deferred_objects();
+      for (intptr_t i = 0; i < in->length(); i++) {
+        code_objects.Add(in->At(i)->ptr());
+      }
+    }
+
     GrowableArray<ImageWriterCommand> writer_commands;
-    RelocateCodeObjects(vm_, code_objects, &writer_commands);
+    RelocateCodeObjects(vm_, &code_objects, &writer_commands);
     image_writer_->PrepareForSerialization(&writer_commands);
   }
 #endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
@@ -5706,7 +6023,7 @@
     is_canonical = true;
   } else {
     cid = object->GetClassId();
-    is_canonical = object->ptr()->IsCanonical();
+    is_canonical = object->untag()->IsCanonical();
   }
 
   SerializationCluster** cluster_ref =
@@ -5738,13 +6055,13 @@
   }
   Object& object = Object::Handle(raw_object);
   OS::PrintErr("Unexpected object (%s, %s): 0x%" Px " %s\n", message,
-               Snapshot::KindToCString(kind_), static_cast<uword>(object.raw()),
+               Snapshot::KindToCString(kind_), static_cast<uword>(object.ptr()),
                object.ToCString());
 #if defined(SNAPSHOT_BACKTRACE)
   while (!object.IsNull()) {
     object = ParentOf(object);
     OS::PrintErr("referenced by 0x%" Px " %s\n",
-                 static_cast<uword>(object.raw()), object.ToCString());
+                 static_cast<uword>(object.ptr()), object.ToCString());
   }
 #endif
   OS::Abort();
@@ -5753,8 +6070,8 @@
 #if defined(SNAPSHOT_BACKTRACE)
 ObjectPtr Serializer::ParentOf(const Object& object) {
   for (intptr_t i = 0; i < parent_pairs_.length(); i += 2) {
-    if (parent_pairs_[i]->raw() == object.raw()) {
-      return parent_pairs_[i + 1]->raw();
+    if (parent_pairs_[i]->ptr() == object.ptr()) {
+      return parent_pairs_[i + 1]->ptr();
     }
   }
   return Object::null();
@@ -5800,6 +6117,22 @@
   }
 
   GrowableArray<SerializationCluster*> canonical_clusters;
+  // The order that PostLoad runs matters for some classes. Explicitly place
+  // these clusters first, then add the rest ordered by class id.
+#define ADD_NEXT(cid)                                                          \
+  if (canonical_clusters_by_cid_[cid] != nullptr) {                            \
+    canonical_clusters.Add(canonical_clusters_by_cid_[cid]);                   \
+    canonical_clusters_by_cid_[cid] = nullptr;                                 \
+  }
+  ADD_NEXT(kOneByteStringCid)
+  ADD_NEXT(kTwoByteStringCid)
+  ADD_NEXT(kMintCid)
+  ADD_NEXT(kDoubleCid)
+  ADD_NEXT(kTypeParameterCid)
+  ADD_NEXT(kTypeCid)
+  ADD_NEXT(kTypeArgumentsCid)
+  ADD_NEXT(kClosureCid)
+#undef ADD_NEXT
   for (intptr_t cid = 0; cid < num_cids_; cid++) {
     if (canonical_clusters_by_cid_[cid] != nullptr) {
       canonical_clusters.Add(canonical_clusters_by_cid_[cid]);
@@ -5826,6 +6159,8 @@
   }
 #endif
 
+  PrepareInstructions();
+
   intptr_t num_objects = num_base_objects_ + num_written_objects_;
 #if defined(ARCH_IS_64_BIT)
   if (!Utils::IsInt(32, num_objects)) {
@@ -5943,8 +6278,7 @@
   ASSERT(code_cluster != nullptr);
   // Reference IDs in a cluster are allocated sequentially, so we can use the
   // first code object's reference ID to calculate the cluster index.
-  const intptr_t first_code_id =
-      RefId(code_cluster->discovered_objects()->At(0));
+  const intptr_t first_code_id = RefId(code_cluster->objects()->At(0));
   // The first object in the code cluster must have its reference ID allocated.
   ASSERT(IsAllocatedReference(first_code_id));
 
@@ -6082,7 +6416,8 @@
     // snapshot, we always serialize at least _one_ byte for the DispatchTable.
     if (dispatch_table_size_ > 0) {
       const auto& dispatch_table_entries = Array::Handle(
-          zone_, isolate()->object_store()->dispatch_table_code_entries());
+          zone_,
+          isolate_group()->object_store()->dispatch_table_code_entries());
       auto const entry_count =
           dispatch_table_entries.IsNull() ? 0 : dispatch_table_entries.Length();
       clusters_by_size.Add(new (zone_) FakeSerializationCluster(
@@ -6113,7 +6448,7 @@
                            bool is_non_root_unit,
                            intptr_t offset)
     : ThreadStackResource(thread),
-      heap_(thread->isolate()->heap()),
+      heap_(thread->isolate_group()->heap()),
       zone_(thread->zone()),
       kind_(kind),
       stream_(buffer, size),
@@ -6180,8 +6515,6 @@
       return new (Z) FunctionDeserializationCluster();
     case kClosureDataCid:
       return new (Z) ClosureDataDeserializationCluster();
-    case kSignatureDataCid:
-      return new (Z) SignatureDataDeserializationCluster();
     case kFfiTrampolineDataCid:
       return new (Z) FfiTrampolineDataDeserializationCluster();
     case kFieldCid:
@@ -6226,6 +6559,8 @@
       return new (Z) LibraryPrefixDeserializationCluster();
     case kTypeCid:
       return new (Z) TypeDeserializationCluster();
+    case kFunctionTypeCid:
+      return new (Z) FunctionTypeDeserializationCluster();
     case kTypeRefCid:
       return new (Z) TypeRefDeserializationCluster();
     case kTypeParameterCid:
@@ -6277,7 +6612,8 @@
   const intptr_t first_code_id = stream->ReadUnsigned();
 
   auto const I = isolate();
-  auto code = I->object_store()->dispatch_table_null_error_stub();
+  auto const IG = isolate_group();
+  auto code = IG->object_store()->dispatch_table_null_error_stub();
   ASSERT(code != Code::null());
   uword null_entry = Code::EntryPointOf(code);
 
@@ -6442,21 +6778,21 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
     if (FLAG_use_bare_instructions) {
       uword entry_point = StubCode::NotLoaded().EntryPoint();
-      code->ptr()->entry_point_ = entry_point;
-      code->ptr()->unchecked_entry_point_ = entry_point;
-      code->ptr()->monomorphic_entry_point_ = entry_point;
-      code->ptr()->monomorphic_unchecked_entry_point_ = entry_point;
-      code->ptr()->instructions_length_ = 0;
+      code->untag()->entry_point_ = entry_point;
+      code->untag()->unchecked_entry_point_ = entry_point;
+      code->untag()->monomorphic_entry_point_ = entry_point;
+      code->untag()->monomorphic_unchecked_entry_point_ = entry_point;
+      code->untag()->instructions_length_ = 0;
       return;
     }
 #endif
     InstructionsPtr instr = StubCode::NotLoaded().instructions();
     uint32_t unchecked_offset = 0;
-    code->ptr()->instructions_ = instr;
+    code->untag()->instructions_ = instr;
 #if defined(DART_PRECOMPILED_RUNTIME)
-    code->ptr()->instructions_length_ = Instructions::Size(instr);
+    code->untag()->instructions_length_ = Instructions::Size(instr);
 #else
-    code->ptr()->unchecked_offset_ = unchecked_offset;
+    code->untag()->unchecked_offset_ = unchecked_offset;
 #endif
     Code::InitializeCachedEntryPointsFrom(code, instr, unchecked_offset);
     return;
@@ -6465,7 +6801,7 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
   if (FLAG_use_bare_instructions) {
     // There are no serialized RawInstructions objects in this mode.
-    code->ptr()->instructions_ = Instructions::null();
+    code->untag()->instructions_ = Instructions::null();
     previous_text_offset_ += ReadUnsigned();
     const uword payload_start =
         image_reader_->GetBareInstructionsAt(previous_text_offset_);
@@ -6484,10 +6820,10 @@
     const uword monomorphic_entry_point =
         payload_start + monomorphic_entry_offset;
 
-    code->ptr()->entry_point_ = entry_point;
-    code->ptr()->unchecked_entry_point_ = entry_point + unchecked_offset;
-    code->ptr()->monomorphic_entry_point_ = monomorphic_entry_point;
-    code->ptr()->monomorphic_unchecked_entry_point_ =
+    code->untag()->entry_point_ = entry_point;
+    code->untag()->unchecked_entry_point_ = entry_point + unchecked_offset;
+    code->untag()->monomorphic_entry_point_ = monomorphic_entry_point;
+    code->untag()->monomorphic_unchecked_entry_point_ =
         monomorphic_entry_point + unchecked_offset;
     return;
   }
@@ -6495,17 +6831,17 @@
 
   InstructionsPtr instr = image_reader_->GetInstructionsAt(Read<uint32_t>());
   uint32_t unchecked_offset = ReadUnsigned();
-  code->ptr()->instructions_ = instr;
+  code->untag()->instructions_ = instr;
 #if defined(DART_PRECOMPILED_RUNTIME)
-  code->ptr()->instructions_length_ = Instructions::Size(instr);
+  code->untag()->instructions_length_ = Instructions::Size(instr);
 #else
-  code->ptr()->unchecked_offset_ = unchecked_offset;
+  code->untag()->unchecked_offset_ = unchecked_offset;
   if (kind() == Snapshot::kFullJIT) {
     const uint32_t active_offset = Read<uint32_t>();
     instr = image_reader_->GetInstructionsAt(active_offset);
     unchecked_offset = ReadUnsigned();
   }
-  code->ptr()->active_instructions_ = instr;
+  code->untag()->active_instructions_ = instr;
 #endif
   Code::InitializeCachedEntryPointsFrom(code, instr, unchecked_offset);
 }
@@ -6520,7 +6856,7 @@
       CodePtr code = static_cast<CodePtr>(refs.At(id));
       uword start = Code::PayloadStartOf(code);
       ASSERT(start <= previous_end);
-      code->ptr()->instructions_length_ = previous_end - start;
+      code->untag()->instructions_length_ = previous_end - start;
       previous_end = start;
     }
 
@@ -6534,7 +6870,7 @@
       code = refs.At(start_index + i);
       order_table.SetAt(i, code);
     }
-    ObjectStore* object_store = Isolate::Current()->object_store();
+    ObjectStore* object_store = IsolateGroup::Current()->object_store();
     GrowableObjectArray& order_tables =
         GrowableObjectArray::Handle(zone_, object_store->code_order_tables());
     if (order_tables.IsNull()) {
@@ -6575,15 +6911,28 @@
 
   canonical_clusters_ = new DeserializationCluster*[num_canonical_clusters_];
   clusters_ = new DeserializationCluster*[num_clusters_];
-  refs_ = Array::New(num_objects_ + kFirstReference, Heap::kOld);
+  refs = Array::New(num_objects_ + kFirstReference, Heap::kOld);
   if (initial_field_table_len > 0) {
     initial_field_table_->AllocateIndex(initial_field_table_len - 1);
     ASSERT_EQUAL(initial_field_table_->NumFieldIds(), initial_field_table_len);
   }
 
   {
-    NoSafepointScope no_safepoint;
+    // The deserializer initializes objects without using the write barrier,
+    // partly for speed since we know all the deserialized objects will be
+    // long-lived and partly because the target objects can be not yet
+    // initialized at the time of the write. To make this safe, we must ensure
+    // there are no other threads mutating this heap, and that incremental
+    // marking is not in progress. This is normally the case anyway for the
+    // main snapshot being deserialized at isolate load, but needs checks for
+    // loading secondary snapshots are part of deferred loading.
+    HeapIterationScope iter(thread());
+    // For bump-pointer allocation in old-space.
     HeapLocker hl(thread(), heap_->old_space());
+    // Must not perform any other type of allocation, which might trigger GC
+    // while there are still uninitialized objects.
+    NoSafepointScope no_safepoint;
+    refs_ = refs.ptr();
 
     roots->AddBaseObjects(this);
 
@@ -6593,39 +6942,48 @@
              num_base_objects_, next_ref_index_ - kFirstReference);
     }
 
-    for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
-      canonical_clusters_[i] = ReadCluster();
-      canonical_clusters_[i]->ReadAlloc(this, /*is_canonical*/ true);
+    {
+      TIMELINE_DURATION(thread(), Isolate, "ReadAlloc");
+      for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+        canonical_clusters_[i] = ReadCluster();
+        TIMELINE_DURATION(thread(), Isolate, canonical_clusters_[i]->name());
+        canonical_clusters_[i]->ReadAlloc(this, /*is_canonical*/ true);
 #if defined(DEBUG)
-      intptr_t serializers_next_ref_index_ = Read<int32_t>();
-      ASSERT_EQUAL(serializers_next_ref_index_, next_ref_index_);
+        intptr_t serializers_next_ref_index_ = Read<int32_t>();
+        ASSERT_EQUAL(serializers_next_ref_index_, next_ref_index_);
 #endif
-    }
-    for (intptr_t i = 0; i < num_clusters_; i++) {
-      clusters_[i] = ReadCluster();
-      clusters_[i]->ReadAlloc(this, /*is_canonical*/ false);
+      }
+      for (intptr_t i = 0; i < num_clusters_; i++) {
+        clusters_[i] = ReadCluster();
+        TIMELINE_DURATION(thread(), Isolate, clusters_[i]->name());
+        clusters_[i]->ReadAlloc(this, /*is_canonical*/ false);
 #if defined(DEBUG)
-      intptr_t serializers_next_ref_index_ = Read<int32_t>();
-      ASSERT_EQUAL(serializers_next_ref_index_, next_ref_index_);
+        intptr_t serializers_next_ref_index_ = Read<int32_t>();
+        ASSERT_EQUAL(serializers_next_ref_index_, next_ref_index_);
 #endif
+      }
     }
 
     // We should have completely filled the ref array.
     ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects_);
 
-    for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
-      canonical_clusters_[i]->ReadFill(this, /*is_canonical*/ true);
+    {
+      TIMELINE_DURATION(thread(), Isolate, "PostLoad");
+      for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+        bool stamp_canonical = isolate() == Dart::vm_isolate();
+        canonical_clusters_[i]->ReadFill(this, stamp_canonical);
 #if defined(DEBUG)
-      int32_t section_marker = Read<int32_t>();
-      ASSERT(section_marker == kSectionMarker);
+        int32_t section_marker = Read<int32_t>();
+        ASSERT(section_marker == kSectionMarker);
 #endif
-    }
-    for (intptr_t i = 0; i < num_clusters_; i++) {
-      clusters_[i]->ReadFill(this, /*is_canonical*/ false);
+      }
+      for (intptr_t i = 0; i < num_clusters_; i++) {
+        clusters_[i]->ReadFill(this, /*stamp_canonical*/ false);
 #if defined(DEBUG)
-      int32_t section_marker = Read<int32_t>();
-      ASSERT(section_marker == kSectionMarker);
+        int32_t section_marker = Read<int32_t>();
+        ASSERT(section_marker == kSectionMarker);
 #endif
+      }
     }
 
     roots->ReadRoots(this);
@@ -6635,30 +6993,29 @@
     ASSERT(section_marker == kSectionMarker);
 #endif
 
-    refs = refs_;
     refs_ = NULL;
   }
 
   roots->PostLoad(this, refs);
 
 #if defined(DEBUG)
-  Isolate* isolate = thread()->isolate();
-  isolate->ValidateClassTable();
-  if (isolate != Dart::vm_isolate()) {
-    isolate->heap()->Verify();
+  isolate()->ValidateClassTable();
+  if (isolate() != Dart::vm_isolate()) {
+    isolate_group()->heap()->Verify();
   }
 #endif
 
-  // TODO(rmacnak): When splitting literals, load clusters requiring
-  // canonicalization first, canonicalize and update the ref array, the load
-  // the remaining clusters to avoid a full heap walk to update references to
-  // the losers of any canonicalization races.
-  for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
-    canonical_clusters_[i]->PostLoad(this, refs, /*is_canonical*/ true);
-  }
-
-  for (intptr_t i = 0; i < num_clusters_; i++) {
-    clusters_[i]->PostLoad(this, refs, /*is_canonical*/ false);
+  {
+    TIMELINE_DURATION(thread(), Isolate, "PostLoad");
+    for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+      TIMELINE_DURATION(thread(), Isolate, canonical_clusters_[i]->name());
+      bool canonicalize = isolate() != Dart::vm_isolate();
+      canonical_clusters_[i]->PostLoad(this, refs, canonicalize);
+    }
+    for (intptr_t i = 0; i < num_clusters_; i++) {
+      TIMELINE_DURATION(thread(), Isolate, clusters_[i]->name());
+      clusters_[i]->PostLoad(this, refs, /*canonicalize*/ false);
+    }
   }
 }
 
@@ -6683,7 +7040,7 @@
       mapped_text_size_(0) {
   ASSERT(isolate() != NULL);
   ASSERT(heap() != NULL);
-  ObjectStore* object_store = isolate()->object_store();
+  ObjectStore* object_store = isolate_group()->object_store();
   ASSERT(object_store != NULL);
 
 #if defined(DEBUG)
@@ -6710,7 +7067,7 @@
   serializer.ReserveHeader();
   serializer.WriteVersionAndFeatures(true);
   VMSerializationRoots roots(
-      Array::Handle(Dart::vm_isolate()->object_store()->symbol_table()));
+      Array::Handle(Dart::vm_isolate_group()->object_store()->symbol_table()));
   ZoneGrowableArray<Object*>* objects = serializer.Serialize(&roots);
   serializer.FillHeader(serializer.kind());
   clustered_vm_size_ = serializer.bytes_written();
@@ -6739,15 +7096,15 @@
                         isolate_image_writer_, /*vm=*/false, profile_writer_);
   serializer.set_loading_units(units);
   serializer.set_current_loading_unit_id(LoadingUnit::kRootId);
-  ObjectStore* object_store = isolate()->object_store();
+  ObjectStore* object_store = isolate_group()->object_store();
   ASSERT(object_store != NULL);
 
   // These type arguments must always be retained.
-  ASSERT(object_store->type_argument_int()->ptr()->IsCanonical());
-  ASSERT(object_store->type_argument_double()->ptr()->IsCanonical());
-  ASSERT(object_store->type_argument_string()->ptr()->IsCanonical());
-  ASSERT(object_store->type_argument_string_dynamic()->ptr()->IsCanonical());
-  ASSERT(object_store->type_argument_string_string()->ptr()->IsCanonical());
+  ASSERT(object_store->type_argument_int()->untag()->IsCanonical());
+  ASSERT(object_store->type_argument_double()->untag()->IsCanonical());
+  ASSERT(object_store->type_argument_string()->untag()->IsCanonical());
+  ASSERT(object_store->type_argument_string_dynamic()->untag()->IsCanonical());
+  ASSERT(object_store->type_argument_string_string()->untag()->IsCanonical());
 
   serializer.ReserveHeader();
   serializer.WriteVersionAndFeatures(false);
@@ -7078,7 +7435,7 @@
                                        /* is_executable */ true);
   }
 
-  ProgramDeserializationRoots roots(thread_->isolate()->object_store());
+  ProgramDeserializationRoots roots(thread_->isolate_group()->object_store());
   deserializer.Deserialize(&roots);
 
   PatchGlobalObjectPool();
@@ -7105,7 +7462,7 @@
   }
   {
     Array& units =
-        Array::Handle(thread_->isolate()->object_store()->loading_units());
+        Array::Handle(isolate_group()->object_store()->loading_units());
     uint32_t main_program_hash = Smi::Value(Smi::RawCast(units.At(0)));
     uint32_t unit_program_hash = deserializer.Read<uint32_t>();
     if (main_program_hash != unit_program_hash) {
@@ -7148,19 +7505,19 @@
     auto zone = thread_->zone();
     const auto& pool = ObjectPool::Handle(
         zone, ObjectPool::RawCast(
-                  thread_->isolate()->object_store()->global_object_pool()));
+                  isolate_group()->object_store()->global_object_pool()));
     auto& entry = Object::Handle(zone);
     auto& smi = Smi::Handle(zone);
     for (intptr_t i = 0; i < pool.Length(); i++) {
       if (pool.TypeAt(i) == ObjectPool::EntryType::kTaggedObject) {
         entry = pool.ObjectAt(i);
-        if (entry.raw() == StubCode::SwitchableCallMiss().raw()) {
+        if (entry.ptr() == StubCode::SwitchableCallMiss().ptr()) {
           smi = Smi::FromAlignedAddress(
               StubCode::SwitchableCallMiss().MonomorphicEntryPoint());
           pool.SetTypeAt(i, ObjectPool::EntryType::kImmediate,
                          ObjectPool::Patchability::kPatchable);
           pool.SetObjectAt(i, smi);
-        } else if (entry.raw() == StubCode::MegamorphicCall().raw()) {
+        } else if (entry.ptr() == StubCode::MegamorphicCall().ptr()) {
           smi = Smi::FromAlignedAddress(
               StubCode::MegamorphicCall().MonomorphicEntryPoint());
           pool.SetTypeAt(i, ObjectPool::EntryType::kImmediate,
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 031ab05..d35b83a 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -116,16 +116,20 @@
 
   // Allocate memory for all objects in the cluster and write their addresses
   // into the ref array. Do not touch this memory.
-  virtual void ReadAlloc(Deserializer* deserializer, bool is_canonical) = 0;
+  virtual void ReadAlloc(Deserializer* deserializer, bool stamp_canonical) = 0;
 
   // Initialize the cluster's objects. Do not touch the memory of other objects.
-  virtual void ReadFill(Deserializer* deserializer, bool is_canonical) = 0;
+  virtual void ReadFill(Deserializer* deserializer, bool stamp_canonical) = 0;
 
   // Complete any action that requires the full graph to be deserialized, such
   // as rehashing.
   virtual void PostLoad(Deserializer* deserializer,
                         const Array& refs,
-                        bool is_canonical) {}
+                        bool canonicalize) {
+    if (canonicalize) {
+      FATAL1("%s needs canonicalization but doesn't define PostLoad", name());
+    }
+  }
 
   const char* name() const { return name_; }
 
@@ -323,33 +327,31 @@
 
   template <typename T, typename... P>
   void WriteFromTo(T obj, P&&... args) {
-    ObjectPtr* from = obj->ptr()->from();
-    ObjectPtr* to = obj->ptr()->to_snapshot(kind(), args...);
+    ObjectPtr* from = obj->untag()->from();
+    ObjectPtr* to = obj->untag()->to_snapshot(kind(), args...);
     for (ObjectPtr* p = from; p <= to; p++) {
-      WriteOffsetRef(*p, (p - reinterpret_cast<ObjectPtr*>(obj->ptr())) *
+      WriteOffsetRef(*p, (p - reinterpret_cast<ObjectPtr*>(obj->untag())) *
                              sizeof(ObjectPtr));
     }
   }
 
   template <typename T, typename... P>
   void PushFromTo(T obj, P&&... args) {
-    ObjectPtr* from = obj->ptr()->from();
-    ObjectPtr* to = obj->ptr()->to_snapshot(kind(), args...);
+    ObjectPtr* from = obj->untag()->from();
+    ObjectPtr* to = obj->untag()->to_snapshot(kind(), args...);
     for (ObjectPtr* p = from; p <= to; p++) {
       Push(*p);
     }
   }
 
-  void WriteTokenPosition(TokenPosition pos) {
-    Write<int32_t>(pos.SnapshotEncode());
-  }
+  void WriteTokenPosition(TokenPosition pos) { Write(pos.Serialize()); }
 
   void WriteCid(intptr_t cid) {
-    COMPILE_ASSERT(ObjectLayout::kClassIdTagSize <= 32);
+    COMPILE_ASSERT(UntaggedObject::kClassIdTagSize <= 32);
     Write<int32_t>(cid);
   }
 
-  void PrepareInstructions(GrowableArray<CodePtr>* codes);
+  void PrepareInstructions();
   void WriteInstructions(InstructionsPtr instr,
                          uint32_t unchecked_offset,
                          CodePtr code,
@@ -382,6 +384,7 @@
   void set_loading_units(GrowableArray<LoadingUnitSerializationData*>* units) {
     loading_units_ = units;
   }
+  intptr_t current_loading_unit_id() { return current_loading_unit_id_; }
   void set_current_loading_unit_id(intptr_t id) {
     current_loading_unit_id_ = id;
   }
@@ -416,6 +419,13 @@
     FATAL("Missing ref");
   }
 
+  bool HasRef(ObjectPtr object) const {
+    return heap_->GetObjectId(object) != kUnreachableReference;
+  }
+  bool IsWritten(ObjectPtr object) const {
+    return heap_->GetObjectId(object) > num_base_objects_;
+  }
+
  private:
   const char* ReadOnlyObjectType(intptr_t cid);
 
@@ -477,7 +487,7 @@
 
 #define PushFromTo(obj, ...) s->PushFromTo(obj, ##__VA_ARGS__);
 
-#define WriteField(obj, field) s->WritePropertyRef(obj->ptr()->field, #field)
+#define WriteField(obj, field) s->WritePropertyRef(obj->untag()->field, #field)
 
 class SerializerWritingObjectScope {
  public:
@@ -575,6 +585,8 @@
 
   uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
 
+  intptr_t position() const { return stream_.Position(); }
+  void set_position(intptr_t p) { stream_.SetPosition(p); }
   const uint8_t* CurrentBufferAddress() const {
     return stream_.AddressOfCurrentPosition();
   }
@@ -586,23 +598,23 @@
 
   void AssignRef(ObjectPtr object) {
     ASSERT(next_ref_index_ <= num_objects_);
-    refs_->ptr()->data()[next_ref_index_] = object;
+    refs_->untag()->data()[next_ref_index_] = object;
     next_ref_index_++;
   }
 
   ObjectPtr Ref(intptr_t index) const {
     ASSERT(index > 0);
     ASSERT(index <= num_objects_);
-    return refs_->ptr()->data()[index];
+    return refs_->untag()->data()[index];
   }
 
   ObjectPtr ReadRef() { return Ref(ReadUnsigned()); }
 
   template <typename T, typename... P>
   void ReadFromTo(T obj, P&&... params) {
-    ObjectPtr* from = obj->ptr()->from();
-    ObjectPtr* to_snapshot = obj->ptr()->to_snapshot(kind(), params...);
-    ObjectPtr* to = obj->ptr()->to(params...);
+    ObjectPtr* from = obj->untag()->from();
+    ObjectPtr* to_snapshot = obj->untag()->to_snapshot(kind(), params...);
+    ObjectPtr* to = obj->untag()->to(params...);
     for (ObjectPtr* p = from; p <= to_snapshot; p++) {
       *p = ReadRef();
     }
@@ -616,11 +628,11 @@
   }
 
   TokenPosition ReadTokenPosition() {
-    return TokenPosition::SnapshotDecode(Read<int32_t>());
+    return TokenPosition::Deserialize(Read<int32_t>());
   }
 
   intptr_t ReadCid() {
-    COMPILE_ASSERT(ObjectLayout::kClassIdTagSize <= 32);
+    COMPILE_ASSERT(UntaggedObject::kClassIdTagSize <= 32);
     return Read<int32_t>();
   }
 
@@ -677,7 +689,8 @@
   Thread* thread() const { return thread_; }
   Zone* zone() const { return thread_->zone(); }
   Isolate* isolate() const { return thread_->isolate(); }
-  Heap* heap() const { return isolate()->heap(); }
+  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
+  Heap* heap() const { return isolate_group()->heap(); }
 
   // Writes a full snapshot of the program(VM isolate, regular isolate group).
   void WriteFullSnapshot(
@@ -729,6 +742,8 @@
   ApiErrorPtr ReadUnitSnapshot(const LoadingUnit& unit);
 
  private:
+  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
+
   ApiErrorPtr ConvertToApiError(char* message);
   void PatchGlobalObjectPool();
   void InitializeBSS();
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index edce815..dd8bc1d 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -4,53 +4,94 @@
 
 #include "vm/code_descriptors.h"
 
+#include "platform/utils.h"
 #include "vm/compiler/api/deopt_id.h"
+#include "vm/flags.h"
 #include "vm/log.h"
+#include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/zone_text_buffer.h"
 
 namespace dart {
 
-void DescriptorList::AddDescriptor(PcDescriptorsLayout::Kind kind,
+DescriptorList::DescriptorList(
+    Zone* zone,
+    const GrowableArray<const Function*>* inline_id_to_function)
+    : function_(Function::Handle(
+          zone,
+          FLAG_check_token_positions && (inline_id_to_function != nullptr)
+              ? inline_id_to_function->At(0)->ptr()
+              : Function::null())),
+      script_(Script::Handle(
+          zone,
+          function_.IsNull() ? Script::null() : function_.script())),
+      encoded_data_(zone, kInitialStreamSize),
+      prev_pc_offset(0),
+      prev_deopt_id(0),
+      prev_token_pos(0) {}
+
+void DescriptorList::AddDescriptor(UntaggedPcDescriptors::Kind kind,
                                    intptr_t pc_offset,
                                    intptr_t deopt_id,
-                                   TokenPosition token_pos,
+                                   const TokenPosition token_pos,
                                    intptr_t try_index,
                                    intptr_t yield_index) {
   // yield index 0 is reserved for normal entry.
   RELEASE_ASSERT(yield_index != 0);
 
-  ASSERT((kind == PcDescriptorsLayout::kRuntimeCall) ||
-         (kind == PcDescriptorsLayout::kBSSRelocation) ||
-         (kind == PcDescriptorsLayout::kOther) ||
-         (yield_index != PcDescriptorsLayout::kInvalidYieldIndex) ||
+  ASSERT((kind == UntaggedPcDescriptors::kRuntimeCall) ||
+         (kind == UntaggedPcDescriptors::kBSSRelocation) ||
+         (kind == UntaggedPcDescriptors::kOther) ||
+         (yield_index != UntaggedPcDescriptors::kInvalidYieldIndex) ||
          (deopt_id != DeoptId::kNone));
 
   // When precompiling, we only use pc descriptors for exceptions,
   // relocations and yield indices.
   if (!FLAG_precompiled_mode || try_index != -1 ||
-      yield_index != PcDescriptorsLayout::kInvalidYieldIndex ||
-      kind == PcDescriptorsLayout::kBSSRelocation) {
+      yield_index != UntaggedPcDescriptors::kInvalidYieldIndex ||
+      kind == UntaggedPcDescriptors::kBSSRelocation) {
     const int32_t kind_and_metadata =
-        PcDescriptorsLayout::KindAndMetadata::Encode(kind, try_index,
-                                                     yield_index);
+        UntaggedPcDescriptors::KindAndMetadata::Encode(kind, try_index,
+                                                       yield_index);
 
     encoded_data_.WriteSLEB128(kind_and_metadata);
     encoded_data_.WriteSLEB128(pc_offset - prev_pc_offset);
     prev_pc_offset = pc_offset;
 
     if (!FLAG_precompiled_mode) {
+      if (FLAG_check_token_positions && token_pos.IsReal()) {
+        if (!function_.IsNull() &&
+            !token_pos.IsWithin(function_.token_pos(),
+                                function_.end_token_pos())) {
+          FATAL("Token position %s for PC descriptor %s at offset 0x%" Px
+                " invalid for function %s (%s, %s)",
+                token_pos.ToCString(),
+                UntaggedPcDescriptors::KindToCString(kind), pc_offset,
+                function_.ToFullyQualifiedCString(),
+                function_.token_pos().ToCString(),
+                function_.end_token_pos().ToCString());
+        }
+        if (!script_.IsNull() && !script_.IsValidTokenPosition(token_pos)) {
+          FATAL("Token position %s for PC descriptor %s at offset 0x%" Px
+                " invalid for script %s of function %s",
+                token_pos.ToCString(),
+                UntaggedPcDescriptors::KindToCString(kind), pc_offset,
+                script_.ToCString(), function_.ToFullyQualifiedCString());
+        }
+      }
+      const int32_t encoded_pos = token_pos.Serialize();
       encoded_data_.WriteSLEB128(deopt_id - prev_deopt_id);
-      encoded_data_.WriteSLEB128(token_pos.value() - prev_token_pos);
+      encoded_data_.WriteSLEB128(
+          Utils::SubWithWrapAround(encoded_pos, prev_token_pos));
       prev_deopt_id = deopt_id;
-      prev_token_pos = token_pos.value();
+      prev_token_pos = encoded_pos;
     }
   }
 }
 
 PcDescriptorsPtr DescriptorList::FinalizePcDescriptors(uword entry_point) {
   if (encoded_data_.bytes_written() == 0) {
-    return Object::empty_descriptors().raw();
+    return Object::empty_descriptors().ptr();
   }
   return PcDescriptors::New(encoded_data_.buffer(),
                             encoded_data_.bytes_written());
@@ -74,7 +115,7 @@
 
 CompressedStackMapsPtr CompressedStackMapsBuilder::Finalize() const {
   if (encoded_bytes_.bytes_written() == 0) {
-    return Object::empty_compressed_stackmaps().raw();
+    return Object::empty_compressed_stackmaps().ptr();
   }
   return CompressedStackMaps::NewInlined(encoded_bytes_.buffer(),
                                          encoded_bytes_.bytes_written());
@@ -84,7 +125,7 @@
     uword entry_point) const {
   intptr_t num_handlers = Length();
   if (num_handlers == 0) {
-    return Object::empty_exception_handlers().raw();
+    return Object::empty_exception_handlers().ptr();
   }
   const ExceptionHandlers& handlers =
       ExceptionHandlers::Handle(ExceptionHandlers::New(num_handlers));
@@ -109,7 +150,7 @@
       handlers.SetHandledTypes(i, *list_[i].handler_types);
     }
   }
-  return handlers.raw();
+  return handlers.ptr();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -193,12 +234,57 @@
   for (intptr_t i = 0; i < stream_.bytes_written(); i++) {
     dest[i] = src[i];
   }
-  return td.raw();
+  return td.ptr();
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-const TokenPosition CodeSourceMapBuilder::kInitialPosition =
-    TokenPosition(TokenPosition::kDartCodeProloguePos);
+uint8_t CodeSourceMapOps::Read(ReadStream* stream,
+                               int32_t* arg1,
+                               int32_t* arg2) {
+  ASSERT(stream != nullptr && arg1 != nullptr);
+  const int32_t n = stream->Read<int32_t>();
+  const uint8_t op = OpField::decode(n);
+  *arg1 = ArgField::decode(n);
+  if (*arg1 > kMaxArgValue) {
+    *arg1 |= kSignBits;
+  }
+#if defined(DART_PRECOMPILER)
+  // The special handling for non-symbolic stack trace mode only needs to
+  // happen in the precompiler, because those CSMs are not serialized in
+  // precompiled snapshots.
+  if (op == kChangePosition && FLAG_dwarf_stack_traces_mode) {
+    const int32_t m = stream->Read<int32_t>();
+    if (arg2 != nullptr) {
+      *arg2 = m;
+    }
+  }
+#endif
+  return op;
+}
+
+void CodeSourceMapOps::Write(BaseWriteStream* stream,
+                             uint8_t op,
+                             int32_t arg1,
+                             int32_t arg2) {
+  ASSERT(stream != nullptr);
+  ASSERT(arg1 >= kMinArgValue && arg1 <= kMaxArgValue);
+  if (arg1 < 0) {
+    arg1 &= ~kSignBits;
+  }
+  const int32_t n = OpField::encode(op) | ArgField::encode(arg1);
+  stream->Write(n);
+#if defined(DART_PRECOMPILER)
+  if (op == kChangePosition && FLAG_dwarf_stack_traces_mode) {
+    // For non-symbolic stack traces, the CodeSourceMaps are not serialized,
+    // so we need not worry about increasing snapshot size by including more
+    // information here.
+    stream->Write(arg2);
+  }
+#endif
+}
+
+const TokenPosition& CodeSourceMapBuilder::kInitialPosition =
+    TokenPosition::kDartCodePrologue;
 
 CodeSourceMapBuilder::CodeSourceMapBuilder(
     Zone* zone,
@@ -206,7 +292,8 @@
     const GrowableArray<intptr_t>& caller_inline_id,
     const GrowableArray<TokenPosition>& inline_id_to_token_pos,
     const GrowableArray<const Function*>& inline_id_to_function)
-    : buffered_pc_offset_(0),
+    : zone_(zone),
+      buffered_pc_offset_(0),
       buffered_inline_id_stack_(),
       buffered_token_pos_stack_(),
       written_pc_offset_(0),
@@ -217,6 +304,7 @@
       inline_id_to_function_(inline_id_to_function),
       inlined_functions_(
           GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld))),
+      script_(Script::Handle(zone, Script::null())),
       stream_(zone, 64),
       stack_traces_only_(stack_traces_only) {
   buffered_inline_id_stack_.Add(0);
@@ -226,63 +314,70 @@
 }
 
 void CodeSourceMapBuilder::FlushBuffer() {
-  FlushBufferStack();
-  FlushBufferPosition();
-  FlushBufferPC();
-}
-
-void CodeSourceMapBuilder::FlushBufferStack() {
-  for (intptr_t i = buffered_inline_id_stack_.length() - 1; i >= 0; i--) {
-    intptr_t buffered_id = buffered_inline_id_stack_[i];
-    if (i < written_inline_id_stack_.length()) {
-      intptr_t written_id = written_inline_id_stack_[i];
+  // 1. Flush the inlining stack.
+  //
+  // The top-most position where the buffered and written stack match.
+  intptr_t common_index;
+  for (common_index = buffered_inline_id_stack_.length() - 1; common_index >= 0;
+       common_index--) {
+    intptr_t buffered_id = buffered_inline_id_stack_[common_index];
+    if (common_index < written_inline_id_stack_.length()) {
+      intptr_t written_id = written_inline_id_stack_[common_index];
       if (buffered_id == written_id) {
-        // i is the top-most position where the buffered and written stack
-        // match.
-        while (written_inline_id_stack_.length() > i + 1) {
-          WritePop();
-        }
-        for (intptr_t j = i + 1; j < buffered_inline_id_stack_.length(); j++) {
-          TokenPosition buffered_pos = buffered_token_pos_stack_[j - 1];
-          TokenPosition written_pos = written_token_pos_stack_[j - 1];
-          if (buffered_pos != written_pos) {
-            WriteChangePosition(buffered_pos);
-          }
-          WritePush(buffered_inline_id_stack_[j]);
-        }
-        return;
+        break;
       }
     }
   }
-  UNREACHABLE();
-}
+  if (common_index < 0) {
+    // The base, which is the root function, should _always_ match.
+    UNREACHABLE();
+  }
+  while (written_inline_id_stack_.length() > common_index + 1) {
+    WritePop();
+  }
+  for (intptr_t j = common_index + 1; j < buffered_inline_id_stack_.length();
+       j++) {
+    const auto& buffered_pos = buffered_token_pos_stack_[j - 1];
+    const auto& written_pos = written_token_pos_stack_[j - 1];
+    if (buffered_pos != written_pos) {
+      WriteChangePosition(buffered_pos);
+    }
+    WritePush(buffered_inline_id_stack_[j]);
+  }
 
-void CodeSourceMapBuilder::FlushBufferPosition() {
-  ASSERT(buffered_token_pos_stack_.length() ==
-         written_token_pos_stack_.length());
+  ASSERT_EQUAL(buffered_token_pos_stack_.length(),
+               written_token_pos_stack_.length());
 
+  // 2. Flush the current token position.
   intptr_t top = buffered_token_pos_stack_.length() - 1;
-  TokenPosition buffered_pos = buffered_token_pos_stack_[top];
-  TokenPosition written_pos = written_token_pos_stack_[top];
+  const auto& buffered_pos = buffered_token_pos_stack_[top];
+  const auto& written_pos = written_token_pos_stack_[top];
   if (buffered_pos != written_pos) {
     WriteChangePosition(buffered_pos);
   }
-}
 
-void CodeSourceMapBuilder::FlushBufferPC() {
+  // 3. Flush the current PC offset.
   if (buffered_pc_offset_ != written_pc_offset_) {
     WriteAdvancePC(buffered_pc_offset_ - written_pc_offset_);
   }
 }
 
-void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset,
-                                                 intptr_t inline_id) {
-  if (buffered_inline_id_stack_.Last() == inline_id) {
+void CodeSourceMapBuilder::StartInliningInterval(
+    int32_t pc_offset,
+    const InstructionSource& source) {
+  if (!source.token_pos.IsReal() && !source.token_pos.IsSynthetic()) {
+    // Only record inlining intervals for token positions that might need
+    // to be checked against the appropriate function and/or script.
+    return;
+  }
+
+  if (buffered_inline_id_stack_.Last() == source.inlining_id) {
     // No change in function stack.
     return;
   }
-  if (inline_id == -1) {
-    // Basic blocking missing an inline_id.
+
+  if (source.inlining_id < 0) {
+    // Inlining ID is unset for this source, so assume the current inlining ID.
     return;
   }
 
@@ -294,7 +389,7 @@
   // stack.
 
   // Pop to a common ancestor.
-  intptr_t common_parent = inline_id;
+  intptr_t common_parent = source.inlining_id;
   while (!IsOnBufferedStack(common_parent)) {
     common_parent = caller_inline_id_[common_parent];
   }
@@ -304,61 +399,64 @@
 
   // Push to the new top-of-stack function.
   GrowableArray<intptr_t> to_push;
-  intptr_t id = inline_id;
-  while (id != common_parent) {
+  for (intptr_t id = source.inlining_id; id != common_parent;
+       id = caller_inline_id_[id]) {
     to_push.Add(id);
-    id = caller_inline_id_[id];
   }
   for (intptr_t i = to_push.length() - 1; i >= 0; i--) {
     intptr_t callee_id = to_push[i];
-    TokenPosition call_token;
-    if (callee_id != 0) {
-      // TODO(rmacnak): Should make this array line up with the others.
-      call_token = inline_id_to_token_pos_[callee_id - 1];
-    } else {
-      UNREACHABLE();
-    }
-
-    // Report caller as at the position of the call.
-    BufferChangePosition(call_token);
-
+    // We should never push the root function or its "caller".
+    ASSERT(callee_id > 0);
+    BufferChangePosition(inline_id_to_token_pos_[callee_id - 1]);
     BufferPush(callee_id);
   }
+  if (FLAG_check_token_positions) {
+    // Only update the cached script_ on inlining interval changes, since it's
+    // a non-trivial computation.
+    script_ = inline_id_to_function_[source.inlining_id]->script();
+  }
 }
 
-void CodeSourceMapBuilder::BeginCodeSourceRange(int32_t pc_offset) {}
+void CodeSourceMapBuilder::BeginCodeSourceRange(
+    int32_t pc_offset,
+    const InstructionSource& source) {
+  StartInliningInterval(pc_offset, source);
+}
 
 void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset,
-                                              TokenPosition pos) {
+                                              const InstructionSource& source) {
   if (pc_offset == buffered_pc_offset_) {
     return;  // Empty intermediate instruction.
   }
-  if (pos != buffered_token_pos_stack_.Last()) {
+  StartInliningInterval(pc_offset, source);
+  if (source.token_pos != buffered_token_pos_stack_.Last()) {
     if (!stack_traces_only_) {
       FlushBuffer();
     }
-    BufferChangePosition(pos);
+    BufferChangePosition(source.token_pos);
   }
   BufferAdvancePC(pc_offset - buffered_pc_offset_);
 }
 
-void CodeSourceMapBuilder::NoteDescriptor(PcDescriptorsLayout::Kind kind,
+void CodeSourceMapBuilder::NoteDescriptor(UntaggedPcDescriptors::Kind kind,
                                           int32_t pc_offset,
-                                          TokenPosition pos) {
+                                          const InstructionSource& source) {
   const uint8_t kCanThrow =
-      PcDescriptorsLayout::kIcCall | PcDescriptorsLayout::kUnoptStaticCall |
-      PcDescriptorsLayout::kRuntimeCall | PcDescriptorsLayout::kOther;
+      UntaggedPcDescriptors::kIcCall | UntaggedPcDescriptors::kUnoptStaticCall |
+      UntaggedPcDescriptors::kRuntimeCall | UntaggedPcDescriptors::kOther;
   if ((kind & kCanThrow) != 0) {
-    BufferChangePosition(pos);
+    StartInliningInterval(pc_offset, source);
+    BufferChangePosition(source.token_pos);
     BufferAdvancePC(pc_offset - buffered_pc_offset_);
     FlushBuffer();
   }
 }
 
 void CodeSourceMapBuilder::NoteNullCheck(int32_t pc_offset,
-                                         TokenPosition pos,
+                                         const InstructionSource& source,
                                          intptr_t name_index) {
-  BufferChangePosition(pos);
+  StartInliningInterval(pc_offset, source);
+  BufferChangePosition(source.token_pos);
   BufferAdvancePC(pc_offset - buffered_pc_offset_);
   FlushBuffer();
   WriteNullCheck(name_index);
@@ -367,7 +465,7 @@
 intptr_t CodeSourceMapBuilder::GetFunctionId(intptr_t inline_id) {
   const Function& function = *inline_id_to_function_[inline_id];
   for (intptr_t i = 0; i < inlined_functions_.Length(); i++) {
-    if (inlined_functions_.At(i) == function.raw()) {
+    if (inlined_functions_.At(i) == function.ptr()) {
       return i;
     }
   }
@@ -376,9 +474,20 @@
   return inlined_functions_.Length() - 1;
 }
 
+TokenPosition CodeSourceMapBuilder::RootPosition(
+    const InstructionSource& source) {
+  if (source.inlining_id <= 0) return source.token_pos;
+
+  intptr_t id = source.inlining_id;
+  while (caller_inline_id_[id] != 0) {
+    id = caller_inline_id_[id];
+  }
+  return inline_id_to_token_pos_[id - 1];
+}
+
 ArrayPtr CodeSourceMapBuilder::InliningIdToFunction() {
   if (inlined_functions_.Length() == 0) {
-    return Object::empty_array().raw();
+    return Object::empty_array().ptr();
   }
   return Array::MakeFixedLength(inlined_functions_);
 }
@@ -388,40 +497,68 @@
     FlushBuffer();
   }
   intptr_t length = stream_.bytes_written();
-  const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length));
+  const auto& map = CodeSourceMap::Handle(zone_, CodeSourceMap::New(length));
   NoSafepointScope no_safepoint;
   memmove(map.Data(), stream_.buffer(), length);
-  return map.raw();
+  return map.ptr();
 }
 
-void CodeSourceMapBuilder::WriteChangePosition(TokenPosition pos) {
-  stream_.Write<uint8_t>(kChangePosition);
-  intptr_t position_or_line = pos.value();
+void CodeSourceMapBuilder::BufferChangePosition(TokenPosition pos) {
+  if (FLAG_check_token_positions && pos.IsReal()) {
+    const intptr_t inline_id = buffered_inline_id_stack_.Last();
+    const auto& function = *inline_id_to_function_[inline_id];
+    if (function.end_token_pos().IsReal() &&
+        !pos.IsWithin(function.token_pos(), function.end_token_pos())) {
+      TextBuffer buffer(256);
+      buffer.Printf("Token position %s is invalid for function %s (%s, %s)",
+                    pos.ToCString(), function.ToFullyQualifiedCString(),
+                    function.token_pos().ToCString(),
+                    function.end_token_pos().ToCString());
+      if (inline_id > 0) {
+        buffer.Printf(" while compiling function %s",
+                      inline_id_to_function_[0]->ToFullyQualifiedCString());
+      }
+      FATAL("%s", buffer.buffer());
+    }
+    script_ = function.script();
+    if (!script_.IsNull() && !script_.IsValidTokenPosition(pos)) {
+      TextBuffer buffer(256);
+      buffer.Printf("Token position %s is invalid for script %s of function %s",
+                    pos.ToCString(), script_.ToCString(),
+                    function.ToFullyQualifiedCString());
+      if (inline_id != 0) {
+        buffer.Printf(" inlined into function %s",
+                      inline_id_to_function_[0]->ToFullyQualifiedCString());
+      }
+      FATAL("%s", buffer.buffer());
+    }
+  }
+  buffered_token_pos_stack_.Last() = pos;
+}
+
+void CodeSourceMapBuilder::WriteChangePosition(const TokenPosition pos) {
+  const TokenPosition& last_written = written_token_pos_stack_.Last();
+  intptr_t position_or_line =
+      Utils::SubWithWrapAround(pos.Serialize(), last_written.Serialize());
+  intptr_t column = TokenPosition::kNoSource.Serialize();
 #if defined(DART_PRECOMPILER)
-  intptr_t column = TokenPosition::kNoSourcePos;
   if (FLAG_precompiled_mode) {
     // Don't use the raw position value directly in precompiled mode. Instead,
     // use the value of kNoSource as a fallback when no line or column
     // information is found.
-    position_or_line = TokenPosition::kNoSourcePos;
-    intptr_t inline_id = buffered_inline_id_stack_.Last();
-    if (inline_id < inline_id_to_function_.length()) {
-      const Function* function = inline_id_to_function_[inline_id];
-      Script& script = Script::Handle(function->script());
-      script.GetTokenLocationUsingLineStarts(pos.SourcePosition(),
-                                             &position_or_line, &column);
-    }
+    position_or_line = TokenPosition::kNoSource.Serialize();
+    const intptr_t inline_id = written_inline_id_stack_.Last();
+    ASSERT(inline_id < inline_id_to_function_.length());
+    script_ = inline_id_to_function_[inline_id]->script();
+    script_.GetTokenLocation(pos, &position_or_line, &column);
+    intptr_t old_line = TokenPosition::kNoSource.Serialize();
+    script_.GetTokenLocation(last_written, &old_line);
+    position_or_line =
+        Utils::SubWithWrapAround<int32_t>(position_or_line, old_line);
   }
 #endif
-  stream_.Write<int32_t>(position_or_line);
-#if defined(DART_PRECOMPILER)
-  // For non-symbolic stack traces, the CodeSourceMaps are not serialized,
-  // so we need not worry about increasing snapshot size by including more
-  // information here.
-  if (FLAG_dwarf_stack_traces_mode) {
-    stream_.Write<int32_t>(column);
-  }
-#endif
+  CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kChangePosition,
+                          position_or_line, column);
   written_token_pos_stack_.Last() = pos;
 }
 
@@ -437,32 +574,34 @@
 
   int32_t current_pc_offset = 0;
   function_stack->Add(&root_);
-  token_positions->Add(CodeSourceMapBuilder::kInitialPosition);
+  token_positions->Add(InitialPosition());
 
   while (stream.PendingBytes() > 0) {
-    uint8_t opcode = stream.Read<uint8_t>();
+    int32_t arg;
+    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
     switch (opcode) {
-      case CodeSourceMapBuilder::kChangePosition: {
+      case CodeSourceMapOps::kChangePosition: {
+        const TokenPosition& old_token =
+            (*token_positions)[token_positions->length() - 1];
         (*token_positions)[token_positions->length() - 1] =
-            ReadPosition(&stream);
+            TokenPosition::Deserialize(
+                Utils::AddWithWrapAround(arg, old_token.Serialize()));
         break;
       }
-      case CodeSourceMapBuilder::kAdvancePC: {
-        int32_t delta = stream.Read<int32_t>();
-        current_pc_offset += delta;
+      case CodeSourceMapOps::kAdvancePC: {
+        current_pc_offset += arg;
         if (current_pc_offset > pc_offset) {
           return;
         }
         break;
       }
-      case CodeSourceMapBuilder::kPushFunction: {
-        int32_t func = stream.Read<int32_t>();
+      case CodeSourceMapOps::kPushFunction: {
         function_stack->Add(
-            &Function::Handle(Function::RawCast(functions_.At(func))));
-        token_positions->Add(CodeSourceMapBuilder::kInitialPosition);
+            &Function::Handle(Function::RawCast(functions_.At(arg))));
+        token_positions->Add(InitialPosition());
         break;
       }
-      case CodeSourceMapBuilder::kPopFunction: {
+      case CodeSourceMapOps::kPopFunction: {
         // We never pop the root function.
         ASSERT(function_stack->length() > 1);
         ASSERT(token_positions->length() > 1);
@@ -470,8 +609,7 @@
         token_positions->RemoveLast();
         break;
       }
-      case CodeSourceMapBuilder::kNullCheck: {
-        stream.Read<int32_t>();
+      case CodeSourceMapOps::kNullCheck: {
         break;
       }
       default:
@@ -501,38 +639,35 @@
   function_stack.Add(0);
 
   while (stream.PendingBytes() > 0) {
-    uint8_t opcode = stream.Read<uint8_t>();
+    int32_t arg;
+    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
     switch (opcode) {
-      case CodeSourceMapBuilder::kChangePosition: {
-        ReadPosition(&stream);
+      case CodeSourceMapOps::kChangePosition: {
         break;
       }
-      case CodeSourceMapBuilder::kAdvancePC: {
-        int32_t delta = stream.Read<int32_t>();
+      case CodeSourceMapOps::kAdvancePC: {
         // Format: [start, end, inline functions...]
         JSONArray inline_interval(&inline_intervals);
         inline_interval.AddValue(static_cast<intptr_t>(current_pc_offset));
         inline_interval.AddValue(
-            static_cast<intptr_t>(current_pc_offset + delta - 1));
+            static_cast<intptr_t>(current_pc_offset + arg - 1));
         for (intptr_t i = 0; i < function_stack.length(); i++) {
           inline_interval.AddValue(function_stack[i]);
         }
-        current_pc_offset += delta;
+        current_pc_offset += arg;
         break;
       }
-      case CodeSourceMapBuilder::kPushFunction: {
-        int32_t func = stream.Read<int32_t>();
-        function_stack.Add(func);
+      case CodeSourceMapOps::kPushFunction: {
+        function_stack.Add(arg);
         break;
       }
-      case CodeSourceMapBuilder::kPopFunction: {
+      case CodeSourceMapOps::kPopFunction: {
         // We never pop the root function.
         ASSERT(function_stack.length() > 1);
         function_stack.RemoveLast();
         break;
       }
-      case CodeSourceMapBuilder::kNullCheck: {
-        stream.Read<int32_t>();
+      case CodeSourceMapOps::kNullCheck: {
         break;
       }
       default:
@@ -554,37 +689,34 @@
   THR_Print("Inline intervals for function '%s' {\n",
             root_.ToFullyQualifiedCString());
   while (stream.PendingBytes() > 0) {
-    uint8_t opcode = stream.Read<uint8_t>();
+    int32_t arg;
+    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
     switch (opcode) {
-      case CodeSourceMapBuilder::kChangePosition: {
-        ReadPosition(&stream);
+      case CodeSourceMapOps::kChangePosition: {
         break;
       }
-      case CodeSourceMapBuilder::kAdvancePC: {
-        int32_t delta = stream.Read<int32_t>();
+      case CodeSourceMapOps::kAdvancePC: {
         THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
-                  start + current_pc_offset + delta - 1);
+                  start + current_pc_offset + arg - 1);
         for (intptr_t i = 0; i < function_stack.length(); i++) {
           THR_Print("%s ", function_stack[i]->ToCString());
         }
         THR_Print("\n");
-        current_pc_offset += delta;
+        current_pc_offset += arg;
         break;
       }
-      case CodeSourceMapBuilder::kPushFunction: {
-        int32_t func = stream.Read<int32_t>();
+      case CodeSourceMapOps::kPushFunction: {
         function_stack.Add(
-            &Function::Handle(Function::RawCast(functions_.At(func))));
+            &Function::Handle(Function::RawCast(functions_.At(arg))));
         break;
       }
-      case CodeSourceMapBuilder::kPopFunction: {
+      case CodeSourceMapOps::kPopFunction: {
         // We never pop the root function.
         ASSERT(function_stack.length() > 1);
         function_stack.RemoveLast();
         break;
       }
-      case CodeSourceMapBuilder::kNullCheck: {
-        stream.Read<int32_t>();
+      case CodeSourceMapOps::kNullCheck: {
         break;
       }
       default:
@@ -603,37 +735,40 @@
 
   int32_t current_pc_offset = 0;
   function_stack.Add(&root_);
-  token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
+  token_positions.Add(InitialPosition());
 
   THR_Print("Source positions for function '%s' {\n",
             root_.ToFullyQualifiedCString());
   while (stream.PendingBytes() > 0) {
-    uint8_t opcode = stream.Read<uint8_t>();
+    int32_t arg;
+    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
     switch (opcode) {
-      case CodeSourceMapBuilder::kChangePosition: {
-        token_positions[token_positions.length() - 1] = ReadPosition(&stream);
+      case CodeSourceMapOps::kChangePosition: {
+        const TokenPosition& old_token =
+            token_positions[token_positions.length() - 1];
+        token_positions[token_positions.length() - 1] =
+            TokenPosition::Deserialize(
+                Utils::AddWithWrapAround(arg, old_token.Serialize()));
         break;
       }
-      case CodeSourceMapBuilder::kAdvancePC: {
-        int32_t delta = stream.Read<int32_t>();
+      case CodeSourceMapOps::kAdvancePC: {
         THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
-                  start + current_pc_offset + delta - 1);
+                  start + current_pc_offset + arg - 1);
         for (intptr_t i = 0; i < function_stack.length(); i++) {
-          THR_Print("%s@%" Pd " ", function_stack[i]->ToCString(),
-                    token_positions[i].value());
+          THR_Print("%s@%s", function_stack[i]->ToCString(),
+                    token_positions[i].ToCString());
         }
         THR_Print("\n");
-        current_pc_offset += delta;
+        current_pc_offset += arg;
         break;
       }
-      case CodeSourceMapBuilder::kPushFunction: {
-        int32_t func = stream.Read<int32_t>();
+      case CodeSourceMapOps::kPushFunction: {
         function_stack.Add(
-            &Function::Handle(Function::RawCast(functions_.At(func))));
-        token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
+            &Function::Handle(Function::RawCast(functions_.At(arg))));
+        token_positions.Add(InitialPosition());
         break;
       }
-      case CodeSourceMapBuilder::kPopFunction: {
+      case CodeSourceMapOps::kPopFunction: {
         // We never pop the root function.
         ASSERT(function_stack.length() > 1);
         ASSERT(token_positions.length() > 1);
@@ -641,11 +776,9 @@
         token_positions.RemoveLast();
         break;
       }
-      case CodeSourceMapBuilder::kNullCheck: {
-        const intptr_t name_index = stream.Read<int32_t>();
-        THR_Print("%" Px "-%" Px ": null check PP#%" Pd "\n",
-                  start + current_pc_offset, start + current_pc_offset,
-                  name_index);
+      case CodeSourceMapOps::kNullCheck: {
+        THR_Print("%" Px "-%" Px ": null check PP#%" Pd32 "\n",
+                  start + current_pc_offset, start + current_pc_offset, arg);
         break;
       }
       default:
@@ -662,29 +795,26 @@
   int32_t current_pc_offset = 0;
 
   while (stream.PendingBytes() > 0) {
-    uint8_t opcode = stream.Read<uint8_t>();
+    int32_t arg;
+    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg);
     switch (opcode) {
-      case CodeSourceMapBuilder::kChangePosition: {
-        ReadPosition(&stream);
+      case CodeSourceMapOps::kChangePosition: {
         break;
       }
-      case CodeSourceMapBuilder::kAdvancePC: {
-        int32_t delta = stream.Read<int32_t>();
-        current_pc_offset += delta;
+      case CodeSourceMapOps::kAdvancePC: {
+        current_pc_offset += arg;
         RELEASE_ASSERT(current_pc_offset <= pc_offset);
         break;
       }
-      case CodeSourceMapBuilder::kPushFunction: {
-        stream.Read<int32_t>();
+      case CodeSourceMapOps::kPushFunction: {
         break;
       }
-      case CodeSourceMapBuilder::kPopFunction: {
+      case CodeSourceMapOps::kPopFunction: {
         break;
       }
-      case CodeSourceMapBuilder::kNullCheck: {
-        const int32_t name_index = stream.Read<int32_t>();
+      case CodeSourceMapOps::kNullCheck: {
         if (current_pc_offset == pc_offset) {
-          return name_index;
+          return arg;
         }
         break;
       }
@@ -697,17 +827,4 @@
   return -1;
 }
 
-TokenPosition CodeSourceMapReader::ReadPosition(ReadStream* stream) {
-  const intptr_t line = stream->Read<int32_t>();
-#if defined(DART_PRECOMPILER)
-  // The special handling for non-symbolic stack trace mode only needs to
-  // happen in the precompiler, because those CSMs are not serialized in
-  // precompiled snapshots.
-  if (FLAG_dwarf_stack_traces_mode) {
-    stream->Read<int32_t>();  // Discard the column information.
-  }
-#endif
-  return TokenPosition(line);
-}
-
 }  // namespace dart
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index f42190b..0d15c38 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -9,8 +9,8 @@
 #include "vm/globals.h"
 #include "vm/growable_array.h"
 #include "vm/log.h"
-#include "vm/object.h"
 #include "vm/runtime_entry.h"
+#include "vm/token_position.h"
 
 namespace dart {
 
@@ -18,15 +18,13 @@
 
 class DescriptorList : public ZoneAllocated {
  public:
-  explicit DescriptorList(Zone* zone)
-      : encoded_data_(zone, kInitialStreamSize),
-        prev_pc_offset(0),
-        prev_deopt_id(0),
-        prev_token_pos(0) {}
+  explicit DescriptorList(
+      Zone* zone,
+      const GrowableArray<const Function*>* inline_id_to_function = nullptr);
 
   ~DescriptorList() {}
 
-  void AddDescriptor(PcDescriptorsLayout::Kind kind,
+  void AddDescriptor(UntaggedPcDescriptors::Kind kind,
                      intptr_t pc_offset,
                      intptr_t deopt_id,
                      TokenPosition token_pos,
@@ -38,11 +36,13 @@
  private:
   static constexpr intptr_t kInitialStreamSize = 64;
 
+  const Function& function_;
+  const Script& script_;
   ZoneWriteStream encoded_data_;
 
   intptr_t prev_pc_offset;
   intptr_t prev_deopt_id;
-  intptr_t prev_token_pos;
+  int32_t prev_token_pos;
 
   DISALLOW_COPY_AND_ASSIGN(DescriptorList);
 };
@@ -164,6 +164,56 @@
 };
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
+// Instructions have two pieces of information needed to get accurate source
+// locations: the token position and the inlining id. The inlining id tells us
+// which function, and thus which script, to use for this instruction and the
+// token position, when real, tells us the position in the source for the
+// script for the instruction.
+//
+// Thus, we bundle the two pieces of information in InstructionSource structs
+// when copying or retrieving to lower the likelihood that the token position
+// is used without the appropriate inlining id.
+struct InstructionSource {
+  // Treat an instruction source without inlining id information as unset.
+  InstructionSource() : InstructionSource(TokenPosition::kNoSource) {}
+  explicit InstructionSource(TokenPosition pos) : InstructionSource(pos, -1) {}
+  InstructionSource(TokenPosition pos, intptr_t id)
+      : token_pos(pos), inlining_id(id) {}
+
+  const TokenPosition token_pos;
+  const intptr_t inlining_id;
+
+  DISALLOW_ALLOCATION();
+};
+
+struct CodeSourceMapOps : AllStatic {
+  static const uint8_t kChangePosition = 0;
+  static const uint8_t kAdvancePC = 1;
+  static const uint8_t kPushFunction = 2;
+  static const uint8_t kPopFunction = 3;
+  static const uint8_t kNullCheck = 4;
+
+  static uint8_t Read(ReadStream* stream,
+                      int32_t* arg1,
+                      int32_t* arg2 = nullptr);
+
+  static void Write(BaseWriteStream* stream,
+                    uint8_t op,
+                    int32_t arg1 = 0,
+                    int32_t arg2 = 0);
+
+ private:
+  static constexpr intptr_t kOpBits = 3;
+
+  using OpField = BitField<int32_t, uint8_t, 0, kOpBits>;
+  using ArgField = BitField<int32_t, int32_t, OpField::kNextBit>;
+
+  static constexpr int32_t kMaxArgValue =
+      Utils::NBitMaskUnsafe(ArgField::bitsize() - 1);
+  static constexpr int32_t kMinArgValue = ~kMaxArgValue;
+  static constexpr int32_t kSignBits = static_cast<uint32_t>(kMinArgValue) << 1;
+};
+
 // A CodeSourceMap maps from pc offsets to a stack of inlined functions and
 // their positions. This is encoded as a little bytecode that pushes and pops
 // functions and changes the top function's position as the PC advances.
@@ -186,36 +236,37 @@
   // The position at which a function implicitly starts, for both the root and
   // after a push bytecode. We use the classifying position kDartCodePrologue
   // since it is the most common.
-  static const TokenPosition kInitialPosition;
+  static const TokenPosition& kInitialPosition;
 
-  static const uint8_t kChangePosition = 0;
-  static const uint8_t kAdvancePC = 1;
-  static const uint8_t kPushFunction = 2;
-  static const uint8_t kPopFunction = 3;
-  static const uint8_t kNullCheck = 4;
-
-  void StartInliningInterval(int32_t pc_offset, intptr_t inline_id);
-  void BeginCodeSourceRange(int32_t pc_offset);
-  void EndCodeSourceRange(int32_t pc_offset, TokenPosition pos);
-  void NoteDescriptor(PcDescriptorsLayout::Kind kind,
+  void BeginCodeSourceRange(int32_t pc_offset, const InstructionSource& source);
+  void EndCodeSourceRange(int32_t pc_offset, const InstructionSource& source);
+  void NoteDescriptor(UntaggedPcDescriptors::Kind kind,
                       int32_t pc_offset,
-                      TokenPosition pos);
-  void NoteNullCheck(int32_t pc_offset, TokenPosition pos, intptr_t name_index);
+                      const InstructionSource& source);
+  void NoteNullCheck(int32_t pc_offset,
+                     const InstructionSource& source,
+                     intptr_t name_index);
 
+  // If source is from an inlined call, returns the token position of the
+  // original call in the root function, otherwise the source's token position.
+  TokenPosition RootPosition(const InstructionSource& source);
   ArrayPtr InliningIdToFunction();
   CodeSourceMapPtr Finalize();
 
+  const GrowableArray<const Function*>& inline_id_to_function() const {
+    return inline_id_to_function_;
+  }
+
  private:
   intptr_t GetFunctionId(intptr_t inline_id);
+  void StartInliningInterval(int32_t pc_offset,
+                             const InstructionSource& source);
 
-  void BufferChangePosition(TokenPosition pos) {
-    buffered_token_pos_stack_.Last() = pos;
-  }
+  void BufferChangePosition(TokenPosition pos);
   void WriteChangePosition(TokenPosition pos);
   void BufferAdvancePC(int32_t distance) { buffered_pc_offset_ += distance; }
   void WriteAdvancePC(int32_t distance) {
-    stream_.Write<uint8_t>(kAdvancePC);
-    stream_.Write<int32_t>(distance);
+    CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kAdvancePC, distance);
     written_pc_offset_ += distance;
   }
   void BufferPush(intptr_t inline_id) {
@@ -223,8 +274,8 @@
     buffered_token_pos_stack_.Add(kInitialPosition);
   }
   void WritePush(intptr_t inline_id) {
-    stream_.Write<uint8_t>(kPushFunction);
-    stream_.Write<int32_t>(GetFunctionId(inline_id));
+    CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kPushFunction,
+                            GetFunctionId(inline_id));
     written_inline_id_stack_.Add(inline_id);
     written_token_pos_stack_.Add(kInitialPosition);
   }
@@ -233,19 +284,15 @@
     buffered_token_pos_stack_.RemoveLast();
   }
   void WritePop() {
-    stream_.Write<uint8_t>(kPopFunction);
+    CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kPopFunction);
     written_inline_id_stack_.RemoveLast();
     written_token_pos_stack_.RemoveLast();
   }
   void WriteNullCheck(int32_t name_index) {
-    stream_.Write<uint8_t>(kNullCheck);
-    stream_.Write<int32_t>(name_index);
+    CodeSourceMapOps::Write(&stream_, CodeSourceMapOps::kNullCheck, name_index);
   }
 
   void FlushBuffer();
-  void FlushBufferStack();
-  void FlushBufferPosition();
-  void FlushBufferPC();
 
   bool IsOnBufferedStack(intptr_t inline_id) {
     for (intptr_t i = 0; i < buffered_inline_id_stack_.length(); i++) {
@@ -254,6 +301,7 @@
     return false;
   }
 
+  Zone* const zone_;
   intptr_t buffered_pc_offset_;
   GrowableArray<intptr_t> buffered_inline_id_stack_;
   GrowableArray<TokenPosition> buffered_token_pos_stack_;
@@ -268,6 +316,7 @@
 
   const GrowableObjectArray& inlined_functions_;
 
+  Script& script_;
   ZoneWriteStream stream_;
 
   const bool stack_traces_only_;
@@ -292,6 +341,16 @@
   intptr_t GetNullCheckNameIndexAt(int32_t pc_offset);
 
  private:
+  static const TokenPosition& InitialPosition() {
+    if (FLAG_precompiled_mode) {
+      // In precompiled mode, the CodeSourceMap stores lines instead of
+      // real token positions and uses kNoSourcePos for no line information.
+      return TokenPosition::kNoSource;
+    } else {
+      return CodeSourceMapBuilder::kInitialPosition;
+    }
+  }
+
   // Reads a TokenPosition value from a CSM, handling the different encoding for
   // when non-symbolic stack traces are enabled.
   static TokenPosition ReadPosition(ReadStream* stream);
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index d8e2c41..e096382 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -27,7 +27,7 @@
   EXPECT_EQ(20, value);
   {
     TransitionNativeToVM transition(Thread::Current());
-    Isolate::Current()->heap()->CollectAllGarbage();
+    IsolateGroup::Current()->heap()->CollectAllGarbage();
   }
 }
 
@@ -99,7 +99,7 @@
       PcDescriptors::Handle(code.pc_descriptors());
   int call_count = 0;
   PcDescriptors::Iterator iter(descriptors,
-                               PcDescriptorsLayout::kUnoptStaticCall);
+                               UntaggedPcDescriptors::kUnoptStaticCall);
   CompressedStackMapsBuilder compressed_maps_builder(thread->zone());
   while (iter.MoveNext()) {
     compressed_maps_builder.AddEntry(iter.PcOffset(), stack_bitmap, 0);
@@ -123,7 +123,7 @@
 ISOLATE_UNIT_TEST_CASE(DescriptorList_TokenPositions) {
   DescriptorList* descriptors = new DescriptorList(thread->zone());
   ASSERT(descriptors != NULL);
-  const intptr_t token_positions[] = {
+  const int32_t token_positions[] = {
       kMinInt32,
       5,
       13,
@@ -141,12 +141,12 @@
       TokenPosition::kMinSourcePos,
       TokenPosition::kMaxSourcePos,
   };
-  const intptr_t num_token_positions =
-      sizeof(token_positions) / sizeof(token_positions[0]);
+  const intptr_t num_token_positions = ARRAY_SIZE(token_positions);
 
   for (intptr_t i = 0; i < num_token_positions; i++) {
-    descriptors->AddDescriptor(PcDescriptorsLayout::kRuntimeCall, 0, 0,
-                               TokenPosition(token_positions[i]), 0, 1);
+    const TokenPosition& tp = TokenPosition::Deserialize(token_positions[i]);
+    descriptors->AddDescriptor(UntaggedPcDescriptors::kRuntimeCall, 0, 0, tp, 0,
+                               1);
   }
 
   const PcDescriptors& finalized_descriptors =
@@ -154,15 +154,16 @@
 
   ASSERT(!finalized_descriptors.IsNull());
   PcDescriptors::Iterator it(finalized_descriptors,
-                             PcDescriptorsLayout::kRuntimeCall);
+                             UntaggedPcDescriptors::kRuntimeCall);
 
   intptr_t i = 0;
   while (it.MoveNext()) {
-    if (token_positions[i] != it.TokenPos().value()) {
-      OS::PrintErr("[%" Pd "]: Expected: %" Pd " != %" Pd "\n", i,
-                   token_positions[i], it.TokenPos().value());
+    const TokenPosition& tp = TokenPosition::Deserialize(token_positions[i]);
+    if (tp != it.TokenPos()) {
+      OS::PrintErr("[%" Pd "]: Expected: %s != %s\n", i, tp.ToCString(),
+                   it.TokenPos().ToCString());
     }
-    EXPECT(token_positions[i] == it.TokenPos().value());
+    EXPECT(tp == it.TokenPos());
     i++;
   }
 }
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc
index 38729b1..89de68a 100644
--- a/runtime/vm/code_patcher_arm.cc
+++ b/runtime/vm/code_patcher_arm.cc
@@ -73,7 +73,7 @@
   ICData& ic_data = ICData::Handle();
   ic_data ^= static_call.Data();
   if (ic_data_result != NULL) {
-    *ic_data_result = ic_data.raw();
+    *ic_data_result = ic_data.ptr();
   }
   return ic_data.GetTargetAt(0);
 }
diff --git a/runtime/vm/code_patcher_arm64.cc b/runtime/vm/code_patcher_arm64.cc
index 824274a..a1d4c4d 100644
--- a/runtime/vm/code_patcher_arm64.cc
+++ b/runtime/vm/code_patcher_arm64.cc
@@ -16,8 +16,8 @@
  public:
   PoolPointerCall(uword pc, const Code& code)
       : end_(pc), object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
-    // Last instruction: blr ip0.
-    ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f0200);
+    // Last instruction: blr lr.
+    ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f03c0);
     InstructionPattern::DecodeLoadWordFromPool(end_ - 2 * Instr::kInstrSize,
                                                &reg_, &index_);
   }
@@ -109,7 +109,7 @@
   ICData& ic_data = ICData::Handle();
   ic_data ^= static_call.Data();
   if (ic_data_result != NULL) {
-    *ic_data_result = ic_data.raw();
+    *ic_data_result = ic_data.ptr();
   }
   return ic_data.GetTargetAt(0);
 }
diff --git a/runtime/vm/code_patcher_arm64_test.cc b/runtime/vm/code_patcher_arm64_test.cc
index 61767d8..54fc1b9 100644
--- a/runtime/vm/code_patcher_arm64_test.cc
+++ b/runtime/vm/code_patcher_arm64_test.cc
@@ -28,9 +28,10 @@
       Library::Handle(), class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::Handle(Symbols::New(thread, "callerFunction"));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   const Function& function = Function::Handle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kNoSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
 
   const String& target_name = String::Handle(String::New("targetFunction"));
   const intptr_t kTypeArgsLen = 0;
@@ -41,8 +42,9 @@
       function, target_name, args_descriptor, 15, 1, ICData::kInstance));
   const Code& stub = StubCode::OneArgCheckInlineCache();
 
-  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
-  __ set_constant_pool_allowed(true);
+  // Code is generated, but not executed. Just parsed with CodePatcher.
+  __ set_constant_pool_allowed(true);  // Uninitialized pp is OK.
+  SPILLS_LR_TO_FRAME({});              // Clobbered LR is OK.
 
   compiler::ObjectPoolBuilder& op = __ object_pool_builder();
   const intptr_t ic_data_index =
@@ -51,10 +53,9 @@
       op.AddObject(stub, ObjectPool::Patchability::kPatchable);
   ASSERT((ic_data_index + 1) == stub_index);
   __ LoadDoubleWordFromPoolIndex(R5, CODE_REG, ic_data_index);
-  __ ldr(LR, compiler::FieldAddress(
-                 CODE_REG,
-                 Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
-  __ blr(LR);
+  __ Call(compiler::FieldAddress(
+      CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+  RESTORES_LR_FROM_FRAME({});  // Clobbered LR is OK.
   __ ret();
 }
 
diff --git a/runtime/vm/code_patcher_arm_test.cc b/runtime/vm/code_patcher_arm_test.cc
index 96c34e6..c9026d5 100644
--- a/runtime/vm/code_patcher_arm_test.cc
+++ b/runtime/vm/code_patcher_arm_test.cc
@@ -28,9 +28,10 @@
       Library::Handle(), class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::Handle(Symbols::New(thread, "callerFunction"));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   const Function& function = Function::Handle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kNoSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
 
   const String& target_name = String::Handle(String::New("targetFunction"));
   const intptr_t kTypeArgsLen = 0;
@@ -40,11 +41,13 @@
   const ICData& ic_data = ICData::ZoneHandle(ICData::New(
       function, target_name, args_descriptor, 15, 1, ICData::kInstance));
 
-  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
-  __ set_constant_pool_allowed(true);
+  // Code is generated, but not executed. Just parsed with CodePatcher.
+  __ set_constant_pool_allowed(true);  // Uninitialized pp is OK.
+  SPILLS_LR_TO_FRAME({});              // Clobbered LR is OK.
 
   __ LoadObject(R9, ic_data);
   __ BranchLinkPatchable(StubCode::OneArgCheckInlineCache());
+  RESTORES_LR_FROM_FRAME({});  // Clobbered LR is OK.
   __ Ret();
 }
 
diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc
index 2c123dc..3104115 100644
--- a/runtime/vm/code_patcher_ia32.cc
+++ b/runtime/vm/code_patcher_ia32.cc
@@ -94,14 +94,14 @@
     return LoadUnaligned(reinterpret_cast<ObjectPtr*>(start_ + 1));
   }
   void set_data(const Object& data) const {
-    StoreUnaligned(reinterpret_cast<ObjectPtr*>(start_ + 1), data.raw());
+    StoreUnaligned(reinterpret_cast<ObjectPtr*>(start_ + 1), data.ptr());
   }
 
   CodePtr target() const {
     return LoadUnaligned(reinterpret_cast<CodePtr*>(start_ + 6));
   }
   void set_target(const Code& target) const {
-    StoreUnaligned(reinterpret_cast<CodePtr*>(start_ + 6), target.raw());
+    StoreUnaligned(reinterpret_cast<CodePtr*>(start_ + 6), target.ptr());
   }
 
  private:
@@ -147,7 +147,7 @@
 
   void set_target(const Code& target) const {
     uword* target_addr = reinterpret_cast<uword*>(start_ + 1);
-    uword imm = static_cast<uword>(target.raw());
+    uword imm = static_cast<uword>(target.ptr());
     *target_addr = imm;
     CPU::FlushICache(start_ + 1, sizeof(imm));
   }
@@ -238,7 +238,7 @@
   ICData& ic_data = ICData::Handle();
   ic_data ^= static_call.ic_data();
   if (ic_data_result != NULL) {
-    *ic_data_result = ic_data.raw();
+    *ic_data_result = ic_data.ptr();
   }
   return ic_data.GetTargetAt(0);
 }
diff --git a/runtime/vm/code_patcher_ia32_test.cc b/runtime/vm/code_patcher_ia32_test.cc
index 812f485..36c6ec5 100644
--- a/runtime/vm/code_patcher_ia32_test.cc
+++ b/runtime/vm/code_patcher_ia32_test.cc
@@ -28,9 +28,10 @@
       Library::Handle(), class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::Handle(Symbols::New(thread, "callerFunction"));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   const Function& function = Function::Handle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kNoSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
 
   const String& target_name = String::Handle(String::New("targetFunction"));
   const intptr_t kTypeArgsLen = 0;
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc
index 0077394..c916789 100644
--- a/runtime/vm/code_patcher_x64.cc
+++ b/runtime/vm/code_patcher_x64.cc
@@ -78,7 +78,7 @@
   CodePtr target() const {
     Code& code = Code::Handle();
     code ^= object_pool_.ObjectAt(code_index_);
-    return code.raw();
+    return code.ptr();
   }
 
   void set_target(const Code& target) const {
@@ -197,7 +197,7 @@
   CodePtr Target() const {
     Code& code = Code::Handle();
     code ^= object_pool_.ObjectAt(code_index_);
-    return code.raw();
+    return code.ptr();
   }
 
   void SetTarget(const Code& target) const {
@@ -335,7 +335,7 @@
   BareSwitchableCall(uword return_address, const Code& code)
       : SwitchableCallBase(code) {
     object_pool_ = ObjectPool::RawCast(
-        Isolate::Current()->object_store()->global_object_pool());
+        IsolateGroup::Current()->object_store()->global_object_pool());
 
     uword pc = return_address;
 
@@ -401,7 +401,7 @@
     if (result != Code::null()) {
       return result;
     }
-    result = ReversePc::Lookup(Dart::vm_isolate()->group(), pc);
+    result = ReversePc::Lookup(Dart::vm_isolate_group(), pc);
     if (result != Code::null()) {
       return result;
     }
@@ -476,7 +476,7 @@
   ICData& ic_data = ICData::Handle();
   ic_data ^= static_call.ic_data();
   if (ic_data_result != NULL) {
-    *ic_data_result = ic_data.raw();
+    *ic_data_result = ic_data.ptr();
   }
   return ic_data.GetTargetAt(0);
 }
diff --git a/runtime/vm/code_patcher_x64_test.cc b/runtime/vm/code_patcher_x64_test.cc
index d00b53c..e5666e3 100644
--- a/runtime/vm/code_patcher_x64_test.cc
+++ b/runtime/vm/code_patcher_x64_test.cc
@@ -28,9 +28,10 @@
       Library::Handle(), class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::Handle(Symbols::New(thread, "callerFunction"));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   const Function& function = Function::Handle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kNoSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
 
   const String& target_name = String::Handle(String::New("targetFunction"));
   const intptr_t kTypeArgsLen = 0;
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index d2f88ed..7afcf22 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -4,6 +4,7 @@
 
 #include "vm/compilation_trace.h"
 
+#include "vm/closure_functions_cache.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/globals.h"
 #include "vm/log.h"
@@ -104,7 +105,7 @@
     *newline = 0;
     error_ = CompileTriple(uri, cls_name, func_name);
     if (error_.IsError()) {
-      return error_.raw();
+      return error_.ptr();
     }
     cursor = newline + 1;
   }
@@ -112,8 +113,8 @@
   // Next, compile common dispatchers. These aren't found with the normal
   // lookup above because they have irregular lookup that depends on the
   // arguments descriptor (e.g. call() versus call(x)).
-  const Class& closure_class =
-      Class::Handle(zone_, thread_->isolate()->object_store()->closure_class());
+  const Class& closure_class = Class::Handle(
+      zone_, thread_->isolate_group()->object_store()->closure_class());
   Array& arguments_descriptor = Array::Handle(zone_);
   Function& dispatcher = Function::Handle(zone_);
   for (intptr_t argc = 1; argc <= 4; argc++) {
@@ -124,27 +125,28 @@
     arguments_descriptor = ArgumentsDescriptor::NewBoxed(kTypeArgsLen, argc);
     dispatcher = closure_class.GetInvocationDispatcher(
         Symbols::Call(), arguments_descriptor,
-        FunctionLayout::kInvokeFieldDispatcher, true /* create_if_absent */);
+        UntaggedFunction::kInvokeFieldDispatcher, true /* create_if_absent */);
     error_ = CompileFunction(dispatcher);
     if (error_.IsError()) {
-      return error_.raw();
+      return error_.ptr();
     }
   }
 
-  // Finally, compile closures in all compiled functions. Don't cache the
-  // length since compiling may append to this list.
-  const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle(
-      zone_, thread_->isolate()->object_store()->closure_functions());
-  for (intptr_t i = 0; i < closure_functions.Length(); i++) {
-    function_ ^= closure_functions.At(i);
-    function2_ = function_.parent_function();
+  // Finally, compile closures in all compiled functions. Note: We rely on the
+  // fact that parent functions are visited before children.
+  error_ = Object::null();
+  auto& result = Object::Handle(zone_);
+  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& func) {
+    function2_ = func.parent_function();
     if (function2_.HasCode()) {
-      error_ = CompileFunction(function_);
-      if (error_.IsError()) {
-        return error_.raw();
+      result = CompileFunction(function_);
+      if (result.IsError()) {
+        error_ = result.ptr();
+        return false;  // Stop iteration.
       }
     }
-  }
+    return true;
+  });
 
   return Object::null();
 }
@@ -237,7 +239,7 @@
                   function_name_.ToCString(),
                   Error::Cast(error_).ToErrorCString());
       }
-      return error_.raw();
+      return error_.ptr();
     }
 
     function_ = cls_.LookupFunctionAllowPrivate(function_name_);
@@ -263,7 +265,7 @@
                   class_name_.ToCString(), function_name_.ToCString(),
                   Error::Cast(error_).ToErrorCString());
             }
-            return error_.raw();
+            return error_.ptr();
           }
         }
       }
@@ -279,7 +281,7 @@
   }
 
   if (!field_.IsNull() && field_.is_const() && field_.is_static() &&
-      (field_.StaticValue() == Object::sentinel().raw())) {
+      (field_.StaticValue() == Object::sentinel().ptr())) {
     processed = true;
     error_ = field_.InitializeStatic();
     if (error_.IsError()) {
@@ -290,7 +292,7 @@
             field_.ToCString(), uri_.ToCString(), class_name_.ToCString(),
             function_name_.ToCString(), Error::Cast(error_).ToErrorCString());
       }
-      return error_.raw();
+      return error_.ptr();
     }
   }
 
@@ -304,7 +306,7 @@
                   function_name_.ToCString(),
                   Error::Cast(error_).ToErrorCString());
       }
-      return error_.raw();
+      return error_.ptr();
     }
     if (add_closure) {
       function_ = function_.ImplicitClosureFunction();
@@ -316,7 +318,7 @@
               uri_.ToCString(), class_name_.ToCString(),
               function_name_.ToCString(), Error::Cast(error_).ToErrorCString());
         }
-        return error_.raw();
+        return error_.ptr();
       }
     } else if (is_dyn) {
       function_name_ = function_.name();  // With private mangling.
@@ -332,7 +334,7 @@
               uri_.ToCString(), class_name_.ToCString(),
               function_name_.ToCString(), Error::Cast(error_).ToErrorCString());
         }
-        return error_.raw();
+        return error_.ptr();
       }
     }
   }
@@ -349,7 +351,7 @@
             uri_.ToCString(), class_name_.ToCString(),
             function_name_.ToCString(), Error::Cast(error_).ToErrorCString());
       }
-      return error_.raw();
+      return error_.ptr();
     }
   }
 
@@ -369,12 +371,12 @@
 
   error_ = Compiler::CompileFunction(thread_, function);
   if (error_.IsError()) {
-    return error_.raw();
+    return error_.ptr();
   }
 
   SpeculateInstanceCallTargets(function);
 
-  return error_.raw();
+  return error_.ptr();
 }
 
 // For instance calls, if the receiver's static type has one concrete
@@ -401,14 +403,15 @@
     if (static_type_.IsNull()) {
       continue;
     } else if (static_type_.IsDoubleType()) {
-      receiver_cls_ = Isolate::Current()->class_table()->At(kDoubleCid);
+      receiver_cls_ = IsolateGroup::Current()->class_table()->At(kDoubleCid);
     } else if (static_type_.IsIntType()) {
-      receiver_cls_ = Isolate::Current()->class_table()->At(kSmiCid);
+      receiver_cls_ = IsolateGroup::Current()->class_table()->At(kSmiCid);
     } else if (static_type_.IsStringType()) {
-      receiver_cls_ = Isolate::Current()->class_table()->At(kOneByteStringCid);
+      receiver_cls_ =
+          IsolateGroup::Current()->class_table()->At(kOneByteStringCid);
     } else if (static_type_.IsDartFunctionType() ||
                static_type_.IsDartClosureType()) {
-      receiver_cls_ = Isolate::Current()->class_table()->At(kClosureCid);
+      receiver_cls_ = IsolateGroup::Current()->class_table()->At(kClosureCid);
     } else if (static_type_.HasTypeClass()) {
       receiver_cls_ = static_type_.type_class();
       if (receiver_cls_.is_implemented() || receiver_cls_.is_abstract()) {
@@ -470,7 +473,7 @@
 }
 
 void TypeFeedbackSaver::SaveClasses() {
-  ClassTable* table = Isolate::Current()->class_table();
+  ClassTable* table = IsolateGroup::Current()->class_table();
 
   intptr_t num_cids = table->NumCids();
   WriteInt(num_cids);
@@ -482,7 +485,7 @@
 }
 
 void TypeFeedbackSaver::SaveFields() {
-  ClassTable* table = Isolate::Current()->class_table();
+  ClassTable* table = IsolateGroup::Current()->class_table();
   intptr_t num_cids = table->NumCids();
   for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
     cls_ = table->At(cid);
@@ -516,7 +519,7 @@
   WriteString(str_);
 
   WriteInt(function.kind());
-  WriteInt(function.token_pos().value());
+  WriteInt(function.token_pos().Serialize());
 
   code_ = function.CurrentCode();
   intptr_t usage = function.usage_counter();
@@ -533,7 +536,7 @@
 
   call_sites_ = function.ic_data_array();
   if (call_sites_.IsNull()) {
-    call_sites_ = Object::empty_array().raw();  // Remove edge case.
+    call_sites_ = Object::empty_array().ptr();  // Remove edge case.
   }
 
   // First element is edge counters.
@@ -615,23 +618,23 @@
 
   error_ = CheckHeader();
   if (error_.IsError()) {
-    return error_.raw();
+    return error_.ptr();
   }
 
   error_ = LoadClasses();
   if (error_.IsError()) {
-    return error_.raw();
+    return error_.ptr();
   }
 
   error_ = LoadFields();
   if (error_.IsError()) {
-    return error_.raw();
+    return error_.ptr();
   }
 
   while (stream_->PendingBytes() > 0) {
     error_ = LoadFunction();
     if (error_.IsError()) {
-      return error_.raw();
+      return error_.ptr();
     }
   }
 
@@ -642,7 +645,7 @@
         (func_.usage_counter() >= FLAG_optimization_counter_threshold)) {
       error_ = Compiler::CompileOptimizedFunction(thread_, func_);
       if (error_.IsError()) {
-        return error_.raw();
+        return error_.ptr();
       }
     }
   }
@@ -738,7 +741,7 @@
     if (!skip && (num_fields > 0)) {
       error_ = cls_.EnsureIsFinalized(thread_);
       if (error_.IsError()) {
-        return error_.raw();
+        return error_.ptr();
       }
       fields_ = cls_.fields();
     }
@@ -806,15 +809,15 @@
   if (!cls_.IsNull()) {
     error_ = cls_.EnsureIsFinalized(thread_);
     if (error_.IsError()) {
-      return error_.raw();
+      return error_.ptr();
     }
   } else {
     skip = true;
   }
 
   func_name_ = ReadString();  // Without private mangling.
-  FunctionLayout::Kind kind = static_cast<FunctionLayout::Kind>(ReadInt());
-  intptr_t token_pos = ReadInt();
+  UntaggedFunction::Kind kind = static_cast<UntaggedFunction::Kind>(ReadInt());
+  const TokenPosition& token_pos = TokenPosition::Deserialize(ReadInt());
   intptr_t usage = ReadInt();
   intptr_t inlining_depth = ReadInt();
   intptr_t num_call_sites = ReadInt();
@@ -833,11 +836,11 @@
   if (!skip) {
     error_ = Compiler::CompileFunction(thread_, func_);
     if (error_.IsError()) {
-      return error_.raw();
+      return error_.ptr();
     }
     call_sites_ = func_.ic_data_array();
     if (call_sites_.IsNull()) {
-      call_sites_ = Object::empty_array().raw();  // Remove edge case.
+      call_sites_ = Object::empty_array().ptr();  // Remove edge case.
     }
     if (call_sites_.Length() != num_call_sites + 1) {
       skip = true;
@@ -890,7 +893,7 @@
 
       intptr_t reuse_index = call_site_.FindCheck(cids);
       if (reuse_index == -1) {
-        cls_ = thread_->isolate()->class_table()->At(cids[0]);
+        cls_ = thread_->isolate_group()->class_table()->At(cids[0]);
         // Use target name and args descriptor from the current program
         // instead of saved feedback to get the correct private mangling and
         // ensure no arity mismatch crashes.
@@ -925,8 +928,8 @@
   return Error::null();
 }
 
-FunctionPtr TypeFeedbackLoader::FindFunction(FunctionLayout::Kind kind,
-                                             intptr_t token_pos) {
+FunctionPtr TypeFeedbackLoader::FindFunction(UntaggedFunction::Kind kind,
+                                             const TokenPosition& token_pos) {
   if (cls_name_.Equals(Symbols::TopLevel())) {
     func_ = lib_.LookupFunctionAllowPrivate(func_name_);
   } else {
@@ -935,7 +938,7 @@
 
   if (!func_.IsNull()) {
     // Found regular method.
-  } else if (kind == FunctionLayout::kMethodExtractor) {
+  } else if (kind == UntaggedFunction::kMethodExtractor) {
     ASSERT(Field::IsGetterName(func_name_));
     // Without private mangling:
     String& name = String::Handle(zone_, Field::NameFromGetter(func_name_));
@@ -947,7 +950,7 @@
     } else {
       func_ = Function::null();
     }
-  } else if (kind == FunctionLayout::kDynamicInvocationForwarder) {
+  } else if (kind == UntaggedFunction::kDynamicInvocationForwarder) {
     // Without private mangling:
     String& name = String::Handle(
         zone_, Function::DemangleDynamicInvocationForwarderName(func_name_));
@@ -955,29 +958,18 @@
     if (!func_.IsNull() && func_.IsDynamicFunction()) {
       name = func_.name();  // With private mangling.
       name = Function::CreateDynamicInvocationForwarderName(name);
+      SafepointWriteRwLocker ml(thread_,
+                                thread_->isolate_group()->program_lock());
       func_ = func_.CreateDynamicInvocationForwarder(name);
     } else {
       func_ = Function::null();
     }
-  } else if (kind == FunctionLayout::kClosureFunction) {
+  } else if (kind == UntaggedFunction::kClosureFunction) {
     // Note this lookup relies on parent functions appearing before child
     // functions in the serialized feedback, so the parent will have already
     // been unoptimized compilated and the child function created and added to
     // ObjectStore::closure_functions_.
-    const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle(
-        zone_, thread_->isolate()->object_store()->closure_functions());
-    bool found = false;
-    for (intptr_t i = 0; i < closure_functions.Length(); i++) {
-      func_ ^= closure_functions.At(i);
-      if ((func_.Owner() == cls_.raw()) &&
-          (func_.token_pos().value() == token_pos)) {
-        found = true;
-        break;
-      }
-    }
-    if (!found) {
-      func_ = Function::null();
-    }
+    func_ = ClosureFunctionsCache::LookupClosureFunction(cls_, token_pos);
   } else {
     // This leaves unhandled:
     // - kInvokeFieldDispatcher (how to get a valid args descriptor?)
@@ -986,7 +978,7 @@
   }
 
   if (!func_.IsNull()) {
-    if (kind == FunctionLayout::kImplicitClosureFunction) {
+    if (kind == UntaggedFunction::kImplicitClosureFunction) {
       func_ = func_.ImplicitClosureFunction();
     }
     if (func_.is_abstract() || (func_.kind() != kind)) {
@@ -994,7 +986,7 @@
     }
   }
 
-  return func_.raw();
+  return func_.ptr();
 }
 
 ClassPtr TypeFeedbackLoader::ReadClassByName() {
@@ -1020,7 +1012,7 @@
       }
     }
   }
-  return cls_.raw();
+  return cls_.ptr();
 }
 
 StringPtr TypeFeedbackLoader::ReadString() {
diff --git a/runtime/vm/compilation_trace.h b/runtime/vm/compilation_trace.h
index 80d671e..aa4a6b7 100644
--- a/runtime/vm/compilation_trace.h
+++ b/runtime/vm/compilation_trace.h
@@ -102,7 +102,8 @@
   ObjectPtr LoadClasses();
   ObjectPtr LoadFields();
   ObjectPtr LoadFunction();
-  FunctionPtr FindFunction(FunctionLayout::Kind kind, intptr_t token_pos);
+  FunctionPtr FindFunction(UntaggedFunction::Kind kind,
+                           const TokenPosition& token_pos);
 
   ClassPtr ReadClassByName();
   StringPtr ReadString();
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 6493a81..4ea2220 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -38,7 +38,7 @@
             "generate exhaustive class tests instead of a megamorphic call");
 
 // Quick access to the current isolate and zone.
-#define I (isolate())
+#define IG (isolate_group())
 #define Z (zone())
 
 #ifdef DART_PRECOMPILER
@@ -49,15 +49,15 @@
 //   the receiver type can be only the function's class.
 // Returns Function::null() if there is no unique dynamic target for
 // given 'fname'. 'fname' must be a symbol.
-static void GetUniqueDynamicTarget(Isolate* isolate,
+static void GetUniqueDynamicTarget(IsolateGroup* isolate_group,
                                    const String& fname,
                                    Object* function) {
   UniqueFunctionsMap functions_map(
-      isolate->object_store()->unique_dynamic_targets());
+      isolate_group->object_store()->unique_dynamic_targets());
   ASSERT(fname.IsSymbol());
   *function = functions_map.GetOrNull(fname);
-  ASSERT(functions_map.Release().raw() ==
-         isolate->object_store()->unique_dynamic_targets());
+  ASSERT(functions_map.Release().ptr() ==
+         isolate_group->object_store()->unique_dynamic_targets());
 }
 
 AotCallSpecializer::AotCallSpecializer(
@@ -70,8 +70,9 @@
       precompiler_(precompiler),
       has_unique_no_such_method_(false) {
   Function& target_function = Function::Handle();
-  if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) {
-    GetUniqueDynamicTarget(isolate(), Symbols::NoSuchMethod(),
+  if (isolate_group()->object_store()->unique_dynamic_targets() !=
+      Array::null()) {
+    GetUniqueDynamicTarget(isolate_group(), Symbols::NoSuchMethod(),
                            &target_function);
     has_unique_no_such_method_ = !target_function.IsNull();
   }
@@ -79,13 +80,15 @@
 
 bool AotCallSpecializer::TryCreateICDataForUniqueTarget(
     InstanceCallInstr* call) {
-  if (isolate()->object_store()->unique_dynamic_targets() == Array::null()) {
+  if (isolate_group()->object_store()->unique_dynamic_targets() ==
+      Array::null()) {
     return false;
   }
 
   // Check if the target is unique.
   Function& target_function = Function::Handle(Z);
-  GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function);
+  GetUniqueDynamicTarget(isolate_group(), call->function_name(),
+                         &target_function);
 
   if (target_function.IsNull()) {
     return false;
@@ -152,20 +155,20 @@
     return false;
   }
 
-  if (call->function_name().raw() != Symbols::GetRuntimeType().raw()) {
+  if (call->function_name().ptr() != Symbols::GetRuntimeType().ptr()) {
     return false;
   }
 
   // There is only a single function Object.get:runtimeType that can be invoked
   // by this call. Convert dynamic invocation to a static one.
-  const Class& cls = Class::Handle(Z, I->object_store()->object_class());
+  const Class& cls = Class::Handle(Z, IG->object_store()->object_class());
   const Function& function =
       Function::Handle(Z, call->ResolveForReceiverClass(cls));
   ASSERT(!function.IsNull());
-  const Function& target = Function::ZoneHandle(Z, function.raw());
+  const Function& target = Function::ZoneHandle(Z, function.ptr());
   StaticCallInstr* static_call =
       StaticCallInstr::FromCall(Z, call, target, call->CallCount());
-  static_call->SetResultType(Z, CompileType::FromCid(kTypeCid));
+  // Since the result is either a Type or a FunctionType, we cannot pin it.
   call->ReplaceWith(static_call, current_iterator());
   return true;
 }
@@ -192,7 +195,7 @@
 
   if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() &&
       IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) {
-    const Class& cls = Class::Handle(Z, I->object_store()->object_class());
+    const Class& cls = Class::Handle(Z, IG->object_store()->object_class());
     const Function& have_same_runtime_type = Function::ZoneHandle(
         Z,
         cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType()));
@@ -203,7 +206,7 @@
     args->Add(right->ArgumentValueAt(0)->CopyWithType(Z));
     const intptr_t kTypeArgsLen = 0;
     StaticCallInstr* static_call = new (Z) StaticCallInstr(
-        call->token_pos(), have_same_runtime_type, kTypeArgsLen,
+        call->source(), have_same_runtime_type, kTypeArgsLen,
         Object::null_array(),  // argument_names
         args, call->deopt_id(), call->CallCount(), ICData::kOptimized);
     static_call->SetResultType(Z, CompileType::FromCid(kBoolCid));
@@ -311,7 +314,7 @@
     Definition* conversion = NULL;
 
     if (input->Type()->ToNullableCid() == kSmiCid) {
-      conversion = new (Z) SmiToDoubleInstr(input, call->token_pos());
+      conversion = new (Z) SmiToDoubleInstr(input, call->source());
     } else if (FlowGraphCompiler::SupportsUnboxedInt64() &&
                FlowGraphCompiler::CanConvertInt64ToDouble()) {
       conversion = new (Z) Int64ToDoubleInstr(input, DeoptId::kNone,
@@ -512,7 +515,7 @@
         // We prefer equality compare, since it doesn't require boxing.
         if (!can_use_equality_compare && can_use_strict_compare) {
           replacement = new (Z) StrictCompareInstr(
-              instr->token_pos(),
+              instr->source(),
               (op_kind == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT,
               left_value->CopyWithType(Z), right_value->CopyWithType(Z),
               /*needs_number_check=*/false, DeoptId::kNone);
@@ -522,7 +525,7 @@
         if (supports_unboxed_int) {
           if (can_use_equality_compare) {
             replacement = new (Z) EqualityCompareInstr(
-                instr->token_pos(), op_kind, left_value->CopyWithType(Z),
+                instr->source(), op_kind, left_value->CopyWithType(Z),
                 right_value->CopyWithType(Z), kMintCid, DeoptId::kNone,
                 Instruction::kNotSpeculative);
             break;
@@ -530,7 +533,7 @@
             left_value = PrepareStaticOpInput(left_value, kMintCid, instr);
             right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
             replacement = new (Z) RelationalOpInstr(
-                instr->token_pos(), op_kind, left_value, right_value, kMintCid,
+                instr->source(), op_kind, left_value, right_value, kMintCid,
                 DeoptId::kNone, Instruction::kNotSpeculative);
             break;
           } else {
@@ -672,7 +675,7 @@
           left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
           right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
           replacement = new (Z) EqualityCompareInstr(
-              instr->token_pos(), op_kind, left_value, right_value, kDoubleCid,
+              instr->source(), op_kind, left_value, right_value, kDoubleCid,
               DeoptId::kNone, Instruction::kNotSpeculative);
           break;
         }
@@ -688,7 +691,7 @@
         left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
         right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
         replacement = new (Z) RelationalOpInstr(
-            instr->token_pos(), op_kind, left_value, right_value, kDoubleCid,
+            instr->source(), op_kind, left_value, right_value, kDoubleCid,
             DeoptId::kNone, Instruction::kNotSpeculative);
         break;
       }
@@ -706,8 +709,8 @@
         left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
         right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
         replacement = new (Z) BinaryDoubleOpInstr(
-            op_kind, left_value, right_value, DeoptId::kNone,
-            instr->token_pos(), Instruction::kNotSpeculative);
+            op_kind, left_value, right_value, DeoptId::kNone, instr->source(),
+            Instruction::kNotSpeculative);
         break;
       }
 
@@ -809,7 +812,7 @@
 
   if (has_one_target) {
     const Function& target = targets.FirstTarget();
-    FunctionLayout::Kind function_kind = target.kind();
+    UntaggedFunction::Kind function_kind = target.kind();
     if (flow_graph()->CheckForInstanceCall(instr, function_kind) ==
         FlowGraph::ToCheck::kNoCheck) {
       StaticCallInstr* call = StaticCallInstr::FromCall(
@@ -870,11 +873,11 @@
       instr->ArgumentValueAt(receiver_idx)->Type()->ToCid();
   if (receiver_cid != kDynamicCid) {
     const Class& receiver_class =
-        Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
+        Class::Handle(Z, isolate_group()->class_table()->At(receiver_cid));
     const Function& function =
         Function::Handle(Z, instr->ResolveForReceiverClass(receiver_class));
     if (!function.IsNull()) {
-      const Function& target = Function::ZoneHandle(Z, function.raw());
+      const Function& target = Function::ZoneHandle(Z, function.ptr());
       StaticCallInstr* call =
           StaticCallInstr::FromCall(Z, instr, target, instr->CallCount());
       instr->ReplaceWith(call, current_iterator());
@@ -893,7 +896,8 @@
         // Skip sentinel cid. It may appear in the unreachable code after
         // inlining a method which doesn't return.
         if (cid == kNeverCid) continue;
-        const Class& cls = Class::Handle(Z, isolate()->class_table()->At(cid));
+        const Class& cls =
+            Class::Handle(Z, isolate_group()->class_table()->At(cid));
         const Function& target =
             Function::Handle(Z, instr->ResolveForReceiverClass(cls));
         if (target.recognized_kind() != MethodRecognizer::kObjectEquals) {
@@ -903,7 +907,7 @@
       }
       if (is_object_eq) {
         auto* replacement = new (Z) StrictCompareInstr(
-            instr->token_pos(),
+            instr->source(),
             (instr->token_kind() == Token::kEQ) ? Token::kEQ_STRICT
                                                 : Token::kNE_STRICT,
             instr->ArgumentValueAt(0)->CopyWithType(Z),
@@ -952,7 +956,7 @@
       Class& cls = Class::Handle(Z);
       for (intptr_t i = 0; i < class_ids.length(); i++) {
         const intptr_t cid = class_ids[i];
-        cls = isolate()->class_table()->At(cid);
+        cls = isolate_group()->class_table()->At(cid);
         target = instr->ResolveForReceiverClass(cls);
         ASSERT(target.IsNull() || !target.IsInvokeFieldDispatcher());
         if (target.IsNull()) {
@@ -963,9 +967,9 @@
           // First we are trying to compute a single target for all subclasses.
           if (single_target.IsNull()) {
             ASSERT(i == 0);
-            single_target = target.raw();
+            single_target = target.ptr();
             continue;
-          } else if (single_target.raw() == target.raw()) {
+          } else if (single_target.ptr() == target.ptr()) {
             continue;
           }
 
@@ -988,12 +992,12 @@
           single_target = Function::null();
         }
 
-        ASSERT(ic_data.raw() != ICData::null());
-        ASSERT(single_target.raw() == Function::null());
+        ASSERT(ic_data.ptr() != ICData::null());
+        ASSERT(single_target.ptr() == Function::null());
         ic_data.AddReceiverCheck(cid, target);
       }
 
-      if (single_target.raw() != Function::null()) {
+      if (single_target.ptr() != Function::null()) {
         // If this is a getter or setter invocation try inlining it right away
         // instead of replacing it with a static call.
         if ((op_kind == Token::kGET) || (op_kind == Token::kSET)) {
@@ -1013,12 +1017,12 @@
 
         // We have computed that there is only a single target for this call
         // within the whole hierarchy. Replace InstanceCall with StaticCall.
-        const Function& target = Function::ZoneHandle(Z, single_target.raw());
+        const Function& target = Function::ZoneHandle(Z, single_target.ptr());
         StaticCallInstr* call =
             StaticCallInstr::FromCall(Z, instr, target, instr->CallCount());
         instr->ReplaceWith(call, current_iterator());
         return;
-      } else if ((ic_data.raw() != ICData::null()) &&
+      } else if ((ic_data.ptr() != ICData::null()) &&
                  !ic_data.NumberOfChecksIs(0)) {
         const CallTargets* targets = CallTargets::Create(Z, ic_data);
         ASSERT(!targets->is_empty());
@@ -1067,7 +1071,7 @@
 
   // Ignore callsites like f.call() for now. Those need to be handled
   // specially if f is a closure.
-  if (call->function_name().raw() == Symbols::Call().raw()) {
+  if (call->function_name().ptr() == Symbols::Call().ptr()) {
     return false;
   }
 
@@ -1085,7 +1089,7 @@
   ArgumentsDescriptor args_desc(args_desc_array);
   target = Resolver::ResolveDynamicForReceiverClass(
       receiver_class, getter_name, args_desc, /*allow_add=*/false);
-  if (target.raw() == Function::null() || target.IsMethodExtractor()) {
+  if (target.ptr() == Function::null() || target.IsMethodExtractor()) {
     return false;
   }
 
@@ -1098,12 +1102,12 @@
 
   InputsArray* get_arguments = new (Z) InputsArray(Z, 1);
   get_arguments->Add(call->ArgumentValueAt(receiver_idx)->CopyWithType(Z));
-  InstanceCallInstr* invoke_get = new (Z) InstanceCallInstr(
-      call->token_pos(), getter_name, Token::kGET, get_arguments,
-      /*type_args_len=*/0,
-      /*argument_names=*/Object::empty_array(),
-      /*checked_argument_count=*/1,
-      thread()->compiler_state().GetNextDeoptId());
+  InstanceCallInstr* invoke_get = new (Z)
+      InstanceCallInstr(call->source(), getter_name, Token::kGET, get_arguments,
+                        /*type_args_len=*/0,
+                        /*argument_names=*/Object::empty_array(),
+                        /*checked_argument_count=*/1,
+                        thread()->compiler_state().GetNextDeoptId());
 
   // Arguments to the .call() are the same as arguments to the
   // original call (including type arguments), but receiver
@@ -1118,7 +1122,7 @@
   }
 
   InstanceCallInstr* invoke_call = new (Z) InstanceCallInstr(
-      call->token_pos(), Symbols::Call(), Token::kILLEGAL, call_arguments,
+      call->source(), Symbols::Call(), Token::kILLEGAL, call_arguments,
       call->type_args_len(), call->argument_names(),
       /*checked_argument_count=*/1,
       thread()->compiler_state().GetNextDeoptId());
@@ -1163,7 +1167,7 @@
       call->ArgumentValueAt(receiver_idx)->Type()->ToCid();
   if (receiver_cid != kDynamicCid) {
     const Class& receiver_class =
-        Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
+        Class::Handle(Z, isolate_group()->class_table()->At(receiver_cid));
     const Function& function =
         Function::ZoneHandle(Z, call->ResolveForReceiverClass(receiver_class));
     if (!function.IsNull()) {
@@ -1204,7 +1208,7 @@
 
   if (lower_limit == upper_limit) {
     StrictCompareInstr* check_cid = new (Z)
-        StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT,
+        StrictCompareInstr(call->source(), Token::kEQ_STRICT,
                            new (Z) Value(left_cid), new (Z) Value(lower_cid),
                            /* number_check = */ false, DeoptId::kNone);
     ReplaceCall(call, check_cid);
@@ -1229,7 +1233,7 @@
 
   const intptr_t kTypeArgsLen = 0;
   StaticCallInstr* new_call = new (Z) StaticCallInstr(
-      call->token_pos(), target, kTypeArgsLen,
+      call->source(), target, kTypeArgsLen,
       Object::null_array(),  // argument_names
       args, call->deopt_id(), call->CallCount(), ICData::kOptimized);
   Environment* copy =
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.cc b/runtime/vm/compiler/aot/dispatch_table_generator.cc
index 415b1ef..2198ae7 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.cc
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.cc
@@ -444,7 +444,7 @@
   for (classid_t cid = kIllegalCid + 1; cid < num_classes_; cid++) {
     obj = classes_->At(cid);
     if (obj.IsClass()) {
-      klass = Class::RawCast(obj.raw());
+      klass = Class::RawCast(obj.ptr());
       functions = klass.current_functions();
       if (!functions.IsNull()) {
         for (intptr_t j = 0; j < functions.Length(); j++) {
@@ -489,7 +489,7 @@
     if (cid > kIllegalCid) {
       obj = classes_->At(cid);
       if (obj.IsClass()) {
-        klass = Class::RawCast(obj.raw());
+        klass = Class::RawCast(obj.ptr());
         concrete = !klass.is_abstract();
         klass = klass.SuperClass();
         if (!klass.IsNull()) {
@@ -558,7 +558,7 @@
   for (classid_t cid = kIllegalCid + 1; cid < num_classes_; cid++) {
     obj = classes_->At(cid);
     if (obj.IsClass()) {
-      klass = Class::RawCast(obj.raw());
+      klass = Class::RawCast(obj.ptr());
       GrowableArray<Interval>& subclasss_cid_ranges = cid_subclass_ranges[cid];
 
       functions = klass.current_functions();
@@ -572,7 +572,7 @@
             if (sid != SelectorMap::kInvalidSelectorId) {
               auto MakeIntervals = [&](const Function& function, int32_t sid) {
                 // A function handle that survives until the table is built.
-                auto& function_handle = Function::ZoneHandle(Z, function.raw());
+                auto& function_handle = Function::ZoneHandle(Z, function.ptr());
 
                 for (intptr_t i = 0; i < subclasss_cid_ranges.length(); i++) {
                   Interval& subclass_cid_range = subclasss_cid_ranges[i];
@@ -667,7 +667,7 @@
     table_rows_[i]->FillTable(classes_, entries);
   }
   entries.MakeImmutable();
-  return entries.raw();
+  return entries.ptr();
 }
 
 }  // namespace compiler
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index d7f198e..28b5d0f 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -7,6 +7,7 @@
 #include "platform/unicode.h"
 #include "vm/canonical_tables.h"
 #include "vm/class_finalizer.h"
+#include "vm/closure_functions_cache.h"
 #include "vm/code_patcher.h"
 #include "vm/compiler/aot/aot_call_specializer.h"
 #include "vm/compiler/aot/precompiler_tracer.h"
@@ -57,6 +58,7 @@
 
 #define T (thread())
 #define I (isolate())
+#define IG (isolate_group())
 #define Z (zone())
 
 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynamic targets");
@@ -161,8 +163,11 @@
       dropped_class_count_(0),
       dropped_typearg_count_(0),
       dropped_type_count_(0),
+      dropped_functiontype_count_(0),
+      dropped_typeparam_count_(0),
       dropped_library_count_(0),
-      libraries_(GrowableObjectArray::Handle(I->object_store()->libraries())),
+      libraries_(GrowableObjectArray::Handle(
+          isolate_->group()->object_store()->libraries())),
       pending_functions_(
           GrowableObjectArray::Handle(GrowableObjectArray::New())),
       sent_selectors_(),
@@ -175,6 +180,7 @@
       classes_to_retain_(),
       typeargs_to_retain_(),
       types_to_retain_(),
+      functiontypes_to_retain_(),
       typeparams_to_retain_(),
       consts_to_retain_(),
       seen_table_selectors_(),
@@ -228,7 +234,7 @@
 
       if (FLAG_use_bare_instructions && FLAG_use_table_dispatch) {
         dispatch_table_generator_ = new compiler::DispatchTableGenerator(Z);
-        dispatch_table_generator_->Initialize(I->class_table());
+        dispatch_table_generator_->Initialize(IG->class_table());
       }
 
       // Precompile constructors to compute information such as
@@ -237,7 +243,7 @@
           /*including_nonchanging_cids=*/FLAG_use_bare_instructions);
 
       {
-        CompilerState state(thread_, /*is_aot=*/true);
+        CompilerState state(thread_, /*is_aot=*/true, /*is_optimizing=*/true);
         PrecompileConstructors();
       }
 
@@ -256,7 +262,7 @@
           set_il_serialization_stream(file);
         }
         if (FLAG_populate_llvm_constant_pool) {
-          auto const object_store = I->object_store();
+          auto const object_store = IG->object_store();
           auto& llvm_constants = GrowableObjectArray::Handle(
               Z, GrowableObjectArray::New(16, Heap::kOld));
           auto& llvm_functions = GrowableObjectArray::Handle(
@@ -291,12 +297,16 @@
 #define DO(member, name)                                                       \
   stub_code = StubCode::BuildIsolateSpecific##name##Stub(                      \
       global_object_pool_builder());                                           \
-  I->object_store()->set_##member(stub_code);
+  IG->object_store()->set_##member(stub_code);
         OBJECT_STORE_STUB_CODE_LIST(DO)
 #undef DO
-        stub_code =
-            StubCode::GetBuildMethodExtractorStub(global_object_pool_builder());
-        I->object_store()->set_build_method_extractor_code(stub_code);
+
+        {
+          SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
+          stub_code = StubCode::GetBuildMethodExtractorStub(
+              global_object_pool_builder());
+        }
+        IG->object_store()->set_build_method_extractor_code(stub_code);
       }
 
       CollectDynamicFunctionNames();
@@ -312,15 +322,15 @@
       // not be retained, although they will be used and expected to be
       // canonical.
       AddTypeArguments(
-          TypeArguments::Handle(Z, I->object_store()->type_argument_int()));
+          TypeArguments::Handle(Z, IG->object_store()->type_argument_int()));
       AddTypeArguments(
-          TypeArguments::Handle(Z, I->object_store()->type_argument_double()));
+          TypeArguments::Handle(Z, IG->object_store()->type_argument_double()));
       AddTypeArguments(
-          TypeArguments::Handle(Z, I->object_store()->type_argument_string()));
+          TypeArguments::Handle(Z, IG->object_store()->type_argument_string()));
       AddTypeArguments(TypeArguments::Handle(
-          Z, I->object_store()->type_argument_string_dynamic()));
+          Z, IG->object_store()->type_argument_string_dynamic()));
       AddTypeArguments(TypeArguments::Handle(
-          Z, I->object_store()->type_argument_string_string()));
+          Z, IG->object_store()->type_argument_string_string()));
 
       // Compile newly found targets and add their callees until we reach a
       // fixed point.
@@ -336,7 +346,7 @@
         // dart code stub.
         const auto& pool = ObjectPool::Handle(
             ObjectPool::NewFromBuilder(*global_object_pool_builder()));
-        I->object_store()->set_global_object_pool(pool);
+        IG->object_store()->set_global_object_pool(pool);
         global_object_pool_builder()->Reset();
 
         if (FLAG_print_gop) {
@@ -354,13 +364,13 @@
         if (FLAG_populate_llvm_constant_pool) {
           // We don't want the Array backing for any mappings in the snapshot,
           // only the pools themselves.
-          I->object_store()->set_llvm_constant_hash_table(Array::null_array());
+          IG->object_store()->set_llvm_constant_hash_table(Array::null_array());
 
           // Keep any functions, classes, etc. referenced from the LLVM pools,
           // even if they could have been dropped due to not being otherwise
           // needed at runtime.
           const auto& constant_pool = GrowableObjectArray::Handle(
-              Z, I->object_store()->llvm_constant_pool());
+              Z, IG->object_store()->llvm_constant_pool());
           auto& object = Object::Handle(Z);
           for (intptr_t i = 0; i < constant_pool.Length(); i++) {
             object = constant_pool.At(i);
@@ -375,7 +385,7 @@
           }
 
           const auto& function_pool = GrowableObjectArray::Handle(
-              Z, I->object_store()->llvm_function_pool());
+              Z, IG->object_store()->llvm_function_pool());
           auto& function = Function::Handle(Z);
           for (intptr_t i = 0; i < function_pool.Length(); i++) {
             function ^= function_pool.At(i);
@@ -397,28 +407,29 @@
       DropFields();
       TraceTypesFromRetainedClasses();
       DropTypes();
+      DropFunctionTypes();
       DropTypeParameters();
       DropTypeArguments();
 
       // Clear these before dropping classes as they may hold onto otherwise
       // dead instances of classes we will remove or otherwise unused symbols.
-      I->object_store()->set_unique_dynamic_targets(Array::null_array());
+      IG->object_store()->set_unique_dynamic_targets(Array::null_array());
       Class& null_class = Class::Handle(Z);
       Function& null_function = Function::Handle(Z);
       Field& null_field = Field::Handle(Z);
-      I->object_store()->set_pragma_class(null_class);
-      I->object_store()->set_pragma_name(null_field);
-      I->object_store()->set_pragma_options(null_field);
-      I->object_store()->set_completer_class(null_class);
-      I->object_store()->set_symbol_class(null_class);
-      I->object_store()->set_compiletime_error_class(null_class);
-      I->object_store()->set_growable_list_factory(null_function);
-      I->object_store()->set_simple_instance_of_function(null_function);
-      I->object_store()->set_simple_instance_of_true_function(null_function);
-      I->object_store()->set_simple_instance_of_false_function(null_function);
-      I->object_store()->set_async_star_move_next_helper(null_function);
-      I->object_store()->set_complete_on_async_return(null_function);
-      I->object_store()->set_async_star_stream_controller(null_class);
+      IG->object_store()->set_pragma_class(null_class);
+      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);
+      IG->object_store()->set_simple_instance_of_true_function(null_function);
+      IG->object_store()->set_simple_instance_of_false_function(null_function);
+      IG->object_store()->set_async_star_move_next_helper(null_function);
+      IG->object_store()->set_complete_on_async_return(null_function);
+      IG->object_store()->set_async_star_stream_controller(null_class);
       DropMetadata();
       DropLibraryEntries();
     }
@@ -444,11 +455,11 @@
   intptr_t symbols_after = -1;
   intptr_t capacity = -1;
   if (FLAG_trace_precompiler) {
-    Symbols::GetStats(I, &symbols_before, &capacity);
+    Symbols::GetStats(IG, &symbols_before, &capacity);
   }
 
   if (FLAG_trace_precompiler) {
-    Symbols::GetStats(I, &symbols_after, &capacity);
+    Symbols::GetStats(IG, &symbols_after, &capacity);
     THR_Print("Precompiled %" Pd " functions,", function_count_);
     THR_Print(" %" Pd " dynamic types,", class_count_);
     THR_Print(" %" Pd " dynamic selectors.\n", selector_count_);
@@ -457,6 +468,8 @@
     THR_Print(" %" Pd " fields,", dropped_field_count_);
     THR_Print(" %" Pd " symbols,", symbols_before - symbols_after);
     THR_Print(" %" Pd " types,", dropped_type_count_);
+    THR_Print(" %" Pd " function types,", dropped_functiontype_count_);
+    THR_Print(" %" Pd " type parameters,", dropped_typeparam_count_);
     THR_Print(" %" Pd " type arguments,", dropped_typearg_count_);
     THR_Print(" %" Pd " classes,", dropped_class_count_);
     THR_Print(" %" Pd " libraries.\n", dropped_library_count_);
@@ -478,6 +491,7 @@
       if (FLAG_trace_precompiler) {
         THR_Print("Precompiling constructor %s\n", function.ToCString());
       }
+      ASSERT(Class::Handle(zone_, function.Owner()).is_finalized());
       CompileFunction(precompiler_, Thread::Current(), zone_, function);
     }
 
@@ -489,7 +503,7 @@
   phase_ = Phase::kCompilingConstructorsForInstructionCounts;
   HANDLESCOPE(T);
   ConstructorVisitor visitor(this, Z);
-  ProgramVisitor::WalkProgram(Z, I, &visitor);
+  ProgramVisitor::WalkProgram(Z, IG, &visitor);
   phase_ = Phase::kPreparation;
 }
 
@@ -501,7 +515,7 @@
 
   AddSelector(Symbols::Call());  // For speed, not correctness.
 
-  const Library& lib = Library::Handle(I->object_store()->root_library());
+  const Library& lib = Library::Handle(IG->object_store()->root_library());
   if (lib.IsNull()) {
     const String& msg = String::Handle(
         Z, String::New("Cannot find root library in isolate.\n"));
@@ -555,7 +569,7 @@
   Class& subcls = Class::Handle(Z);
   Array& fields = Array::Handle(Z);
   Field& field = Field::Handle(Z);
-  Function& function = Function::Handle(Z);
+  FunctionType& signature = FunctionType::Handle(Z);
   Function& dispatcher = Function::Handle(Z);
   Array& args_desc = Array::Handle(Z);
   AbstractType& field_type = AbstractType::Handle(Z);
@@ -580,9 +594,9 @@
         if (!IsSent(field_name)) continue;
         // Create arguments descriptor with fixed parameters from
         // signature of field_type.
-        function = Type::Cast(field_type).signature();
-        if (function.IsGeneric()) continue;
-        if (function.HasOptionalParameters()) continue;
+        signature ^= field_type.ptr();
+        if (signature.IsGeneric()) continue;
+        if (signature.HasOptionalParameters()) continue;
         if (FLAG_trace_precompiler) {
           THR_Print("Found callback field %s\n", field_name.ToCString());
         }
@@ -592,15 +606,16 @@
         // unboxed parameters.
         args_desc =
             ArgumentsDescriptor::NewBoxed(0,  // No type argument vector.
-                                          function.num_fixed_parameters());
+                                          signature.num_fixed_parameters());
         cids.Clear();
         if (CHA::ConcreteSubclasses(cls, &cids)) {
           for (intptr_t j = 0; j < cids.length(); ++j) {
-            subcls = I->class_table()->At(cids[j]);
+            subcls = IG->class_table()->At(cids[j]);
             if (subcls.is_allocated()) {
               // Add dispatcher to cls.
               dispatcher = subcls.GetInvocationDispatcher(
-                  field_name, args_desc, FunctionLayout::kInvokeFieldDispatcher,
+                  field_name, args_desc,
+                  UntaggedFunction::kInvokeFieldDispatcher,
                   /* create_if_absent = */ true);
               if (FLAG_trace_precompiler) {
                 THR_Print("Added invoke-field-dispatcher for %s to %s\n",
@@ -620,6 +635,9 @@
       FLAG_use_bare_instructions ? global_object_pool_builder()->CurrentLength()
                                  : 0;
   RELEASE_ASSERT(!function.HasCode());
+  // Ffi trampoline functions have no signature.
+  ASSERT(function.kind() == UntaggedFunction::kFfiTrampoline ||
+         FunctionType::Handle(Z, function.signature()).IsFinalized());
 
   TracingScope tracing_scope(this);
   function_count_++;
@@ -706,8 +724,8 @@
 }
 
 static bool IsPotentialClosureCall(const String& selector) {
-  return selector.raw() == Symbols::Call().raw() ||
-         selector.raw() == Symbols::DynamicCall().raw();
+  return selector.ptr() == Symbols::Call().ptr() ||
+         selector.ptr() == Symbols::DynamicCall().ptr();
 }
 
 void Precompiler::AddCalleesOfHelper(const Object& entry,
@@ -757,7 +775,7 @@
 void Precompiler::AddTypesOf(const Class& cls) {
   if (cls.IsNull()) return;
   if (classes_to_retain_.HasKey(&cls)) return;
-  classes_to_retain_.Insert(&Class::ZoneHandle(Z, cls.raw()));
+  classes_to_retain_.Insert(&Class::ZoneHandle(Z, cls.ptr()));
 
   Array& interfaces = Array::Handle(Z, cls.interfaces());
   AbstractType& type = AbstractType::Handle(Z);
@@ -770,10 +788,6 @@
 
   type = cls.super_type();
   AddType(type);
-
-  if (cls.IsTypedefClass()) {
-    AddTypesOf(Function::Handle(Z, cls.signature_function()));
-  }
 }
 
 void Precompiler::AddTypesOf(const Function& function) {
@@ -781,15 +795,10 @@
   if (functions_to_retain_.ContainsKey(function)) return;
   functions_to_retain_.Insert(function);
 
-  AddTypeArguments(TypeArguments::Handle(Z, function.type_parameters()));
+  const FunctionType& signature = FunctionType::Handle(Z, function.signature());
+  AddType(signature);
 
   AbstractType& type = AbstractType::Handle(Z);
-  type = function.result_type();
-  AddType(type);
-  for (intptr_t i = 0; i < function.NumParameters(); i++) {
-    type = function.ParameterTypeAt(i);
-    AddType(type);
-  }
   // At this point, ensure any cached default type arguments are canonicalized.
   function.UpdateCachedDefaultTypeArguments(thread());
   if (function.CachesDefaultTypeArguments()) {
@@ -799,19 +808,16 @@
     AddTypeArguments(defaults);
   }
   Code& code = Code::Handle(Z, function.CurrentCode());
-  if (code.IsNull()) {
-    ASSERT(function.kind() == FunctionLayout::kSignatureFunction);
-  } else {
-    const ExceptionHandlers& handlers =
-        ExceptionHandlers::Handle(Z, code.exception_handlers());
-    if (!handlers.IsNull()) {
-      Array& types = Array::Handle(Z);
-      for (intptr_t i = 0; i < handlers.num_entries(); i++) {
-        types = handlers.GetHandledTypes(i);
-        for (intptr_t j = 0; j < types.Length(); j++) {
-          type ^= types.At(j);
-          AddType(type);
-        }
+  ASSERT(!code.IsNull());
+  const ExceptionHandlers& handlers =
+      ExceptionHandlers::Handle(Z, code.exception_handlers());
+  if (!handlers.IsNull()) {
+    Array& types = Array::Handle(Z);
+    for (intptr_t i = 0; i < handlers.num_entries(); i++) {
+      types = handlers.GetHandledTypes(i);
+      for (intptr_t j = 0; j < types.Length(); j++) {
+        type ^= types.At(j);
+        AddType(type);
       }
     }
   }
@@ -821,12 +827,6 @@
   if (!parent.IsNull()) {
     AddTypesOf(parent);
   }
-  if (function.IsSignatureFunction() || function.IsClosureFunction()) {
-    type = function.ExistingSignatureType();
-    if (!type.IsNull()) {
-      AddType(type);
-    }
-  }
   // A class may have all functions inlined except a local function.
   const Class& owner = Class::Handle(Z, function.Owner());
   AddTypesOf(owner);
@@ -838,21 +838,35 @@
   if (abstype.IsTypeParameter()) {
     const auto& param = TypeParameter::Cast(abstype);
     if (typeparams_to_retain_.HasKey(&param)) return;
-    typeparams_to_retain_.Insert(&TypeParameter::ZoneHandle(Z, param.raw()));
+    typeparams_to_retain_.Insert(&TypeParameter::ZoneHandle(Z, param.ptr()));
 
     auto& type = AbstractType::Handle(Z, param.bound());
     AddType(type);
     type = param.default_argument();
     AddType(type);
-    const auto& function = Function::Handle(Z, param.parameterized_function());
-    AddTypesOf(function);
-    const Class& cls = Class::Handle(Z, param.parameterized_class());
-    AddTypesOf(cls);
+    return;
+  }
+
+  if (abstype.IsFunctionType()) {
+    if (functiontypes_to_retain_.HasKey(&FunctionType::Cast(abstype))) return;
+    const FunctionType& signature =
+        FunctionType::ZoneHandle(Z, FunctionType::Cast(abstype).ptr());
+    functiontypes_to_retain_.Insert(&signature);
+
+    AddTypeArguments(TypeArguments::Handle(Z, signature.type_parameters()));
+
+    AbstractType& type = AbstractType::Handle(Z);
+    type = signature.result_type();
+    AddType(type);
+    for (intptr_t i = 0; i < signature.NumParameters(); i++) {
+      type = signature.ParameterTypeAt(i);
+      AddType(type);
+    }
     return;
   }
 
   if (types_to_retain_.HasKey(&abstype)) return;
-  types_to_retain_.Insert(&AbstractType::ZoneHandle(Z, abstype.raw()));
+  types_to_retain_.Insert(&AbstractType::ZoneHandle(Z, abstype.ptr()));
 
   if (abstype.IsType()) {
     const Type& type = Type::Cast(abstype);
@@ -860,10 +874,6 @@
     AddTypesOf(cls);
     const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
     AddTypeArguments(vector);
-    if (type.IsFunctionType()) {
-      const Function& func = Function::Handle(Z, type.signature());
-      AddTypesOf(func);
-    }
   } else if (abstype.IsTypeRef()) {
     AbstractType& type = AbstractType::Handle(Z);
     type = TypeRef::Cast(abstype).type();
@@ -875,7 +885,7 @@
   if (args.IsNull()) return;
 
   if (typeargs_to_retain_.HasKey(&args)) return;
-  typeargs_to_retain_.Insert(&TypeArguments::ZoneHandle(Z, args.raw()));
+  typeargs_to_retain_.Insert(&TypeArguments::ZoneHandle(Z, args.ptr()));
 
   AbstractType& arg = AbstractType::Handle(Z);
   for (intptr_t i = 0; i < args.Length(); i++) {
@@ -894,8 +904,8 @@
     return;
   }
 
-  if (instance.raw() == Object::sentinel().raw() ||
-      instance.raw() == Object::transition_sentinel().raw()) {
+  if (instance.ptr() == Object::sentinel().ptr() ||
+      instance.ptr() == Object::transition_sentinel().ptr()) {
     return;
   }
 
@@ -923,7 +933,7 @@
     const Library& target = Library::Handle(Z, prefix.GetLibrary(0));
     cls = target.toplevel_class();
     if (!classes_to_retain_.HasKey(&cls)) {
-      classes_to_retain_.Insert(&Class::ZoneHandle(Z, cls.raw()));
+      classes_to_retain_.Insert(&Class::ZoneHandle(Z, cls.ptr()));
     }
     return;
   }
@@ -938,7 +948,7 @@
   // Constants are canonicalized and we avoid repeated processing of them.
   if (consts_to_retain_.HasKey(&instance)) return;
 
-  consts_to_retain_.Insert(&Instance::ZoneHandle(Z, instance.raw()));
+  consts_to_retain_.Insert(&Instance::ZoneHandle(Z, instance.ptr()));
 
   if (cls.NumTypeArguments() > 0) {
     AddTypeArguments(TypeArguments::Handle(Z, instance.GetTypeArguments()));
@@ -946,8 +956,8 @@
 
   class ConstObjectVisitor : public ObjectPointerVisitor {
    public:
-    ConstObjectVisitor(Precompiler* precompiler, Isolate* isolate)
-        : ObjectPointerVisitor(isolate->group()),
+    ConstObjectVisitor(Precompiler* precompiler, IsolateGroup* isolate_group)
+        : ObjectPointerVisitor(isolate_group),
           precompiler_(precompiler),
           subinstance_(Object::Handle()) {}
 
@@ -966,18 +976,18 @@
     Object& subinstance_;
   };
 
-  ConstObjectVisitor visitor(this, I);
-  instance.raw()->ptr()->VisitPointers(&visitor);
+  ConstObjectVisitor visitor(this, IG);
+  instance.ptr()->untag()->VisitPointers(&visitor);
 }
 
 void Precompiler::AddClosureCall(const String& call_selector,
                                  const Array& arguments_descriptor) {
   const Class& cache_class =
-      Class::Handle(Z, I->object_store()->closure_class());
+      Class::Handle(Z, IG->object_store()->closure_class());
   const Function& dispatcher =
       Function::Handle(Z, cache_class.GetInvocationDispatcher(
                               call_selector, arguments_descriptor,
-                              FunctionLayout::kInvokeFieldDispatcher,
+                              UntaggedFunction::kInvokeFieldDispatcher,
                               true /* create_if_absent */));
   AddFunction(dispatcher);
 }
@@ -989,15 +999,15 @@
 
   if (fields_to_retain_.HasKey(&field)) return;
 
-  fields_to_retain_.Insert(&Field::ZoneHandle(Z, field.raw()));
+  fields_to_retain_.Insert(&Field::ZoneHandle(Z, field.ptr()));
 
   if (field.is_static()) {
     const Object& value = Object::Handle(Z, field.StaticValue());
     // Should not be in the middle of initialization while precompiling.
-    ASSERT(value.raw() != Object::transition_sentinel().raw());
+    ASSERT(value.ptr() != Object::transition_sentinel().ptr());
 
-    if (value.raw() != Object::sentinel().raw() &&
-        value.raw() != Object::null()) {
+    if (value.ptr() != Object::sentinel().ptr() &&
+        value.ptr() != Object::null()) {
       ASSERT(value.IsInstance());
       AddConstObject(Instance::Cast(value));
     }
@@ -1025,15 +1035,15 @@
 
   // Resolver::ResolveDynamic uses.
   const auto& selector = String::Handle(Z, function.name());
-  if (selector.raw() == Symbols::toString().raw()) return true;
-  if (selector.raw() == Symbols::AssignIndexToken().raw()) return true;
-  if (selector.raw() == Symbols::IndexToken().raw()) return true;
-  if (selector.raw() == Symbols::hashCode().raw()) return true;
-  if (selector.raw() == Symbols::NoSuchMethod().raw()) return true;
-  if (selector.raw() == Symbols::EqualOperator().raw()) return true;
+  if (selector.ptr() == Symbols::toString().ptr()) return true;
+  if (selector.ptr() == Symbols::AssignIndexToken().ptr()) return true;
+  if (selector.ptr() == Symbols::IndexToken().ptr()) return true;
+  if (selector.ptr() == Symbols::hashCode().ptr()) return true;
+  if (selector.ptr() == Symbols::NoSuchMethod().ptr()) return true;
+  if (selector.ptr() == Symbols::EqualOperator().ptr()) return true;
 
   // Use the same check for _Closure.call as in stack_trace.{h|cc}.
-  if (selector.raw() == Symbols::Call().raw()) {
+  if (selector.ptr() == Symbols::Call().ptr()) {
     const auto& name = String::Handle(Z, function.QualifiedScrubbedName());
     if (name.Equals(Symbols::_ClosureCall())) return true;
   }
@@ -1079,7 +1089,7 @@
 
   ASSERT(!selector.IsNull());
   if (!IsSent(selector)) {
-    sent_selectors_.Insert(&String::ZoneHandle(Z, selector.raw()));
+    sent_selectors_.Insert(&String::ZoneHandle(Z, selector.ptr()));
     selector_count_++;
     changed_ = true;
 
@@ -1166,7 +1176,7 @@
       // Check for @pragma on the class itself.
       if (cls.has_pragma()) {
         metadata ^= lib.GetMetadata(cls);
-        if (FindEntryPointPragma(isolate(), metadata, &reusable_field_handle,
+        if (FindEntryPointPragma(IG, metadata, &reusable_field_handle,
                                  &reusable_object_handle) ==
             EntryPointPragma::kAlways) {
           AddInstantiatedClass(cls);
@@ -1183,9 +1193,8 @@
         if (field.has_pragma()) {
           metadata ^= lib.GetMetadata(field);
           if (metadata.IsNull()) continue;
-          EntryPointPragma pragma =
-              FindEntryPointPragma(isolate(), metadata, &reusable_field_handle,
-                                   &reusable_object_handle);
+          EntryPointPragma pragma = FindEntryPointPragma(
+              IG, metadata, &reusable_field_handle, &reusable_object_handle);
           if (pragma == EntryPointPragma::kNever) continue;
 
           AddField(field);
@@ -1210,9 +1219,8 @@
         if (function.has_pragma()) {
           metadata ^= lib.GetMetadata(function);
           if (metadata.IsNull()) continue;
-          auto type =
-              FindEntryPointPragma(isolate(), metadata, &reusable_field_handle,
-                                   &reusable_object_handle);
+          auto type = FindEntryPointPragma(IG, metadata, &reusable_field_handle,
+                                           &reusable_object_handle);
 
           if (type == EntryPointPragma::kAlways ||
               type == EntryPointPragma::kCallOnly) {
@@ -1221,7 +1229,7 @@
 
           if ((type == EntryPointPragma::kAlways ||
                type == EntryPointPragma::kGetterOnly) &&
-              function.kind() != FunctionLayout::kConstructor &&
+              function.kind() != UntaggedFunction::kConstructor &&
               !function.IsSetterFunction()) {
             function2 = function.ImplicitClosureFunction();
             AddFunction(function2);
@@ -1231,29 +1239,29 @@
             AddInstantiatedClass(cls);
           }
         }
-        if (function.kind() == FunctionLayout::kImplicitGetter &&
+        if (function.kind() == UntaggedFunction::kImplicitGetter &&
             !implicit_getters.IsNull()) {
           for (intptr_t i = 0; i < implicit_getters.Length(); ++i) {
             field ^= implicit_getters.At(i);
-            if (function.accessor_field() == field.raw()) {
+            if (function.accessor_field() == field.ptr()) {
               AddFunction(function);
             }
           }
         }
-        if (function.kind() == FunctionLayout::kImplicitSetter &&
+        if (function.kind() == UntaggedFunction::kImplicitSetter &&
             !implicit_setters.IsNull()) {
           for (intptr_t i = 0; i < implicit_setters.Length(); ++i) {
             field ^= implicit_setters.At(i);
-            if (function.accessor_field() == field.raw()) {
+            if (function.accessor_field() == field.ptr()) {
               AddFunction(function);
             }
           }
         }
-        if (function.kind() == FunctionLayout::kImplicitStaticGetter &&
+        if (function.kind() == UntaggedFunction::kImplicitStaticGetter &&
             !implicit_static_getters.IsNull()) {
           for (intptr_t i = 0; i < implicit_static_getters.Length(); ++i) {
             field ^= implicit_static_getters.At(i);
-            if (function.accessor_field() == field.raw()) {
+            if (function.accessor_field() == field.ptr()) {
               AddFunction(function);
             }
           }
@@ -1309,7 +1317,7 @@
 
         // Handle the implicit call type conversions.
         if (Field::IsGetterName(selector) &&
-            (function.kind() != FunctionLayout::kMethodExtractor)) {
+            (function.kind() != UntaggedFunction::kMethodExtractor)) {
           // Call-through-getter.
           // Function is get:foo and somewhere foo (or dyn:foo) is called.
           // Note that we need to skip method extractors (which were potentially
@@ -1327,7 +1335,7 @@
             function2 = function.GetDynamicInvocationForwarder(selector2);
             AddFunction(function2);
           }
-        } else if (function.kind() == FunctionLayout::kRegularFunction) {
+        } else if (function.kind() == UntaggedFunction::kRegularFunction) {
           selector2 = Field::LookupGetterSymbol(selector);
           selector3 = String::null();
           if (!selector2.IsNull()) {
@@ -1352,18 +1360,18 @@
         }
 
         const bool is_getter =
-            function.kind() == FunctionLayout::kImplicitGetter ||
-            function.kind() == FunctionLayout::kGetterFunction;
+            function.kind() == UntaggedFunction::kImplicitGetter ||
+            function.kind() == UntaggedFunction::kGetterFunction;
         const bool is_setter =
-            function.kind() == FunctionLayout::kImplicitSetter ||
-            function.kind() == FunctionLayout::kSetterFunction;
+            function.kind() == UntaggedFunction::kImplicitSetter ||
+            function.kind() == UntaggedFunction::kSetterFunction;
         const bool is_regular =
-            function.kind() == FunctionLayout::kRegularFunction;
+            function.kind() == UntaggedFunction::kRegularFunction;
         if (is_getter || is_setter || is_regular) {
           selector2 = Function::CreateDynamicInvocationForwarderName(selector);
           if (IsSent(selector2)) {
-            if (function.kind() == FunctionLayout::kImplicitGetter ||
-                function.kind() == FunctionLayout::kImplicitSetter) {
+            if (function.kind() == UntaggedFunction::kImplicitGetter ||
+                function.kind() == UntaggedFunction::kImplicitSetter) {
               field = function.accessor_field();
               metadata = kernel::ProcedureAttributesOf(field, Z);
             } else if (!found_metadata) {
@@ -1398,7 +1406,7 @@
            String::Cast(a).Equals(String::Cast(b));
   }
   static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); }
-  static ObjectPtr NewKey(const String& str) { return str.raw(); }
+  static ObjectPtr NewKey(const String& str) { return str.ptr(); }
 };
 
 typedef UnorderedHashMap<NameFunctionsTraits> Table;
@@ -1422,7 +1430,7 @@
                                      Function* dyn_function) {
   AddNameToFunctionsTable(zone, table, fname, function);
 
-  *dyn_function = function.raw();
+  *dyn_function = function.ptr();
   if (kernel::NeedsDynamicInvocationForwarder(function)) {
     *mangled_name = function.name();
     *mangled_name =
@@ -1510,12 +1518,12 @@
       // create lazily.
       // => We disable unique target optimization if the target belongs to the
       //    lazily created functions.
-      key_demangled = key.raw();
+      key_demangled = key.ptr();
       if (Function::IsDynamicInvocationForwarderName(key)) {
         key_demangled = Function::DemangleDynamicInvocationForwarderName(key);
       }
-      if (function.name() != key.raw() &&
-          function.name() != key_demangled.raw()) {
+      if (function.name() != key.ptr() &&
+          function.name() != key_demangled.ptr()) {
         continue;
       }
       functions_map.UpdateOrInsert(key, function);
@@ -1537,8 +1545,7 @@
               functions_map.NumOccupied(), table.NumOccupied());
   }
 
-  isolate()->object_store()->set_unique_dynamic_targets(
-      functions_map.Release());
+  IG->object_store()->set_unique_dynamic_targets(functions_map.Release());
   table.Release();
 }
 
@@ -1549,7 +1556,6 @@
   String& name = String::Handle(Z);
   Function& function = Function::Handle(Z);
   Function& function2 = Function::Handle(Z);
-  GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
 
   for (intptr_t i = 0; i < libraries_.Length(); i++) {
     lib ^= libraries_.At(i);
@@ -1589,9 +1595,8 @@
     }
   }
 
-  closures = isolate()->object_store()->closure_functions();
-  for (intptr_t j = 0; j < closures.Length(); j++) {
-    function ^= closures.At(j);
+  auto& parent_function = Function::Handle(Z);
+  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& function) {
     bool retain = possibly_retained_functions_.ContainsKey(function);
     if (retain) {
       AddTypesOf(function);
@@ -1602,13 +1607,14 @@
       // It can happen that all uses of a function are inlined, leaving
       // a compiled local function with an uncompiled parent. Retain such
       // parents and their enclosing classes and libraries.
-      function = function.parent_function();
-      while (!function.IsNull()) {
-        AddTypesOf(function);
-        function = function.parent_function();
+      parent_function = function.parent_function();
+      while (!parent_function.IsNull()) {
+        AddTypesOf(parent_function);
+        parent_function = parent_function.parent_function();
       }
     }
-  }
+    return true;  // Continue iteration.
+  });
 }
 
 void Precompiler::FinalizeDispatchTable() {
@@ -1617,7 +1623,7 @@
   // dropping functions, as we may clear references to Code objects.
   const auto& entries =
       Array::Handle(Z, dispatch_table_generator_->BuildCodeArray());
-  I->object_store()->set_dispatch_table_code_entries(entries);
+  IG->object_store()->set_dispatch_table_code_entries(entries);
   // Delete the dispatch table generator to ensure there's no attempt
   // to add new entries after this point.
   delete dispatch_table_generator_;
@@ -1650,12 +1656,31 @@
         : table_(Array::Handle(zone)),
           kind_and_offset_(Smi::Handle(zone)),
           target_function_(Function::Handle(zone)),
-          target_code_(Code::Handle(zone)) {}
+          target_code_(Code::Handle(zone)),
+          pool_(ObjectPool::Handle(zone)) {}
 
     void VisitCode(const Code& code) {
       if (!code.IsFunctionCode()) return;
       table_ = code.static_calls_target_table();
       StaticCallsTable static_calls(table_);
+
+      // With bare instructions, there is a global pool and per-Code local
+      // pools. Instructions are generated to use offsets into the global pool,
+      // but we still use the local pool to track which Code are using which
+      // pool values for the purposes of analyzing snapshot size
+      // (--write_v8_snapshot_profile_to and --print_instructions_sizes_to) and
+      // deferred loading deciding which snapshots to place pool values in.
+      // We don't keep track of which offsets in the local pools correspond to
+      // which entries in the static call table, so we don't properly replace
+      // the old references to the CallStaticFunction stub, but it is sufficient
+      // for the local pool to include the actual call target.
+      compiler::ObjectPoolBuilder builder;
+      bool append_to_pool = FLAG_use_bare_instructions;
+      if (append_to_pool) {
+        pool_ = code.object_pool();
+        pool_.CopyInto(&builder);
+      }
+
       for (auto& view : static_calls) {
         kind_and_offset_ = view.Get<Code::kSCallTableKindAndOffset>();
         auto const kind = Code::KindField::decode(kind_and_offset_.Value());
@@ -1677,6 +1702,9 @@
               Code::OffsetField::decode(kind_and_offset_.Value());
           const uword pc = pc_offset + code.PayloadStart();
           CodePatcher::PatchStaticCallAt(pc, code, target_code_);
+          if (append_to_pool) {
+            builder.AddObject(Object::ZoneHandle(target_code_.ptr()));
+          }
         }
         if (FLAG_trace_precompiler) {
           THR_Print("Updated static call entry to %s in \"%s\"\n",
@@ -1684,6 +1712,10 @@
                     code.ToCString());
         }
       }
+
+      if (append_to_pool) {
+        code.set_object_pool(ObjectPool::NewFromBuilder(builder));
+      }
     }
 
    private:
@@ -1691,11 +1723,12 @@
     Smi& kind_and_offset_;
     Function& target_function_;
     Code& target_code_;
+    ObjectPool& pool_;
   };
 
   HANDLESCOPE(T);
   StaticCallTableEntryFixer visitor(Z);
-  ProgramVisitor::WalkProgram(Z, I, &visitor);
+  ProgramVisitor::WalkProgram(Z, IG, &visitor);
 }
 
 void Precompiler::DropFunctions() {
@@ -1706,7 +1739,6 @@
   Code& code = Code::Handle(Z);
   Object& owner = Object::Handle(Z);
   GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z);
-  GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
 
   auto drop_function = [&](const Function& function) {
     if (function.HasCode()) {
@@ -1778,23 +1810,22 @@
         retained_functions.Add(Object::null_object());
         functions = Array::MakeFixedLength(retained_functions);
       } else {
-        functions = Object::empty_array().raw();
+        functions = Object::empty_array().ptr();
       }
       cls.set_invocation_dispatcher_cache(functions);
     }
   }
 
-  closures = isolate()->object_store()->closure_functions();
   retained_functions = GrowableObjectArray::New();
-  for (intptr_t j = 0; j < closures.Length(); j++) {
-    function ^= closures.At(j);
+  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& function) {
     if (functions_to_retain_.ContainsKey(function)) {
       retained_functions.Add(function);
     } else {
       drop_function(function);
     }
-  }
-  isolate()->object_store()->set_closure_functions(retained_functions);
+    return true;  // Continue iteration.
+  });
+  IG->object_store()->set_closure_functions(retained_functions);
 }
 
 void Precompiler::DropFields() {
@@ -1834,8 +1865,9 @@
 
           // This cleans up references to field current and initial values.
           if (field.is_static()) {
-            field.SetStaticValue(Object::null_instance(),
-                                 /*save_initial_value=*/true);
+            field.SetStaticValue(Object::null_instance());
+            field.SetStaticConstFieldValue(Object::null_instance(),
+                                           /*assert_initializing_store=*/false);
           }
         }
       }
@@ -1851,7 +1883,7 @@
 }
 
 void Precompiler::AttachOptimizedTypeTestingStub() {
-  Isolate::Current()->heap()->CollectAllGarbage();
+  IsolateGroup::Current()->heap()->CollectAllGarbage();
   GrowableHandlePtrArray<const AbstractType> types(Z, 200);
   {
     class TypesCollector : public ObjectVisitor {
@@ -1861,7 +1893,9 @@
           : type_(AbstractType::Handle(zone)), types_(types) {}
 
       void VisitObject(ObjectPtr obj) {
-        if (obj->GetClassId() == kTypeCid || obj->GetClassId() == kTypeRefCid) {
+        if (obj->GetClassId() == kTypeCid ||
+            obj->GetClassId() == kFunctionTypeCid ||
+            obj->GetClassId() == kTypeRefCid) {
           type_ ^= obj;
           types_->Add(type_);
         }
@@ -1876,10 +1910,10 @@
     TypesCollector visitor(Z, &types);
 
     // Find all type objects in this isolate.
-    I->heap()->VisitObjects(&visitor);
+    IG->heap()->VisitObjects(&visitor);
 
     // Find all type objects in the vm-isolate.
-    Dart::vm_isolate()->heap()->VisitObjects(&visitor);
+    Dart::vm_isolate_group()->heap()->VisitObjects(&visitor);
   }
 
   TypeUsageInfo* type_usage_info = Thread::Current()->type_usage_info();
@@ -1914,7 +1948,7 @@
 }
 
 void Precompiler::DropTypes() {
-  ObjectStore* object_store = I->object_store();
+  ObjectStore* object_store = IG->object_store();
   GrowableObjectArray& retained_types =
       GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
   Array& types_array = Array::Handle(Z);
@@ -1940,7 +1974,7 @@
   const intptr_t dict_size =
       Utils::RoundUpToPowerOfTwo(retained_types.Length() * 4 / 3);
   types_array = HashTables::New<CanonicalTypeSet>(dict_size, Heap::kOld);
-  CanonicalTypeSet types_table(Z, types_array.raw());
+  CanonicalTypeSet types_table(Z, types_array.ptr());
   bool present;
   for (intptr_t i = 0; i < retained_types.Length(); i++) {
     type ^= retained_types.At(i);
@@ -1950,8 +1984,47 @@
   object_store->set_canonical_types(types_table.Release());
 }
 
+void Precompiler::DropFunctionTypes() {
+  ObjectStore* object_store = IG->object_store();
+  GrowableObjectArray& retained_types =
+      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+  Array& types_array = Array::Handle(Z);
+  FunctionType& type = FunctionType::Handle(Z);
+  // First drop all the function types that are not referenced.
+  {
+    CanonicalFunctionTypeSet types_table(
+        Z, object_store->canonical_function_types());
+    types_array = HashTables::ToArray(types_table, false);
+    for (intptr_t i = 0; i < types_array.Length(); i++) {
+      type ^= types_array.At(i);
+      bool retain = functiontypes_to_retain_.HasKey(&type);
+      if (retain) {
+        retained_types.Add(type);
+      } else {
+        type.ClearCanonical();
+        dropped_functiontype_count_++;
+      }
+    }
+    types_table.Release();
+  }
+
+  // Now construct a new function type table and save in the object store.
+  const intptr_t dict_size =
+      Utils::RoundUpToPowerOfTwo(retained_types.Length() * 4 / 3);
+  types_array =
+      HashTables::New<CanonicalFunctionTypeSet>(dict_size, Heap::kOld);
+  CanonicalFunctionTypeSet types_table(Z, types_array.ptr());
+  bool present;
+  for (intptr_t i = 0; i < retained_types.Length(); i++) {
+    type ^= retained_types.At(i);
+    present = types_table.Insert(type);
+    ASSERT(!present);
+  }
+  object_store->set_canonical_function_types(types_table.Release());
+}
+
 void Precompiler::DropTypeParameters() {
-  ObjectStore* object_store = I->object_store();
+  ObjectStore* object_store = IG->object_store();
   GrowableObjectArray& retained_typeparams =
       GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
   Array& typeparams_array = Array::Handle(Z);
@@ -1982,7 +2055,7 @@
       Utils::RoundUpToPowerOfTwo(retained_typeparams.Length() * 4 / 3);
   typeparams_array =
       HashTables::New<CanonicalTypeParameterSet>(dict_size, Heap::kOld);
-  CanonicalTypeParameterSet typeparams_table(Z, typeparams_array.raw());
+  CanonicalTypeParameterSet typeparams_table(Z, typeparams_array.ptr());
   bool present;
   for (intptr_t i = 0; i < retained_typeparams.Length(); i++) {
     typeparam ^= retained_typeparams.At(i);
@@ -1993,7 +2066,7 @@
 }
 
 void Precompiler::DropTypeArguments() {
-  ObjectStore* object_store = I->object_store();
+  ObjectStore* object_store = IG->object_store();
   Array& typeargs_array = Array::Handle(Z);
   GrowableObjectArray& retained_typeargs =
       GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
@@ -2021,7 +2094,7 @@
       Utils::RoundUpToPowerOfTwo(retained_typeargs.Length() * 4 / 3);
   typeargs_array =
       HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld);
-  CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.raw());
+  CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.ptr());
   bool present;
   for (intptr_t i = 0; i < retained_typeargs.Length(); i++) {
     typeargs ^= retained_typeargs.At(i);
@@ -2191,7 +2264,7 @@
 
     lib.RehashDictionary(dict, used * 4 / 3 + 1);
     if (!(retain_root_library_caches_ &&
-          (lib.raw() == I->object_store()->root_library()))) {
+          (lib.ptr() == IG->object_store()->root_library()))) {
       lib.DropDependenciesAndCaches();
     }
   }
@@ -2206,10 +2279,10 @@
   // corpses because the class table entry may be used to find the size of
   // corpses. Request a full GC and wait for the sweeper tasks to finish before
   // we continue.
-  I->heap()->CollectAllGarbage();
-  I->heap()->WaitForSweeperTasks(T);
+  IG->heap()->CollectAllGarbage();
+  IG->heap()->WaitForSweeperTasks(T);
 
-  ClassTable* class_table = I->class_table();
+  ClassTable* class_table = IG->class_table();
   intptr_t num_cids = class_table->NumCids();
 
   for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
@@ -2249,7 +2322,7 @@
   const GrowableObjectArray& retained_libraries =
       GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
   const Library& root_lib =
-      Library::Handle(Z, I->object_store()->root_library());
+      Library::Handle(Z, IG->object_store()->root_library());
   Library& lib = Library::Handle(Z);
   Class& toplevel_class = Class::Handle(Z);
 
@@ -2267,7 +2340,7 @@
     } else if (lib.is_dart_scheme()) {
       // The core libraries are referenced from the object store.
       retain = true;
-    } else if (lib.raw() == root_lib.raw()) {
+    } else if (lib.ptr() == root_lib.ptr()) {
       // The root library might have no surviving members if it only exports
       // main from another library. It will still be referenced from the object
       // store, so retain it.
@@ -2287,7 +2360,7 @@
     } else {
       toplevel_class = lib.toplevel_class();
 
-      I->class_table()->UnregisterTopLevel(toplevel_class.id());
+      IG->class_table()->UnregisterTopLevel(toplevel_class.id());
       toplevel_class.set_id(kIllegalCid);  // We check this when serializing.
 
       dropped_library_count_++;
@@ -2299,7 +2372,7 @@
   }
 
   Library::RegisterLibraries(T, retained_libraries);
-  libraries_ = retained_libraries.raw();
+  libraries_ = retained_libraries.ptr();
 }
 
 // Traits for the HashTable template.
@@ -2307,7 +2380,7 @@
   static uint32_t Hash(const Object& key) { return Code::Cast(key).Size(); }
   static const char* Name() { return "CodeKeyTraits"; }
   static bool IsMatch(const Object& x, const Object& y) {
-    return x.raw() == y.raw();
+    return x.ptr() == y.ptr();
   }
   static bool ReportStats() { return false; }
 };
@@ -2331,7 +2404,7 @@
   };
 
   CodeChecker visitor;
-  ProgramVisitor::WalkProgram(Z, I, &visitor);
+  ProgramVisitor::WalkProgram(Z, IG, &visitor);
   const CodeSet& visited = visitor.visited();
 
   FunctionSet::Iterator it(&functions_to_retain_);
@@ -2341,14 +2414,14 @@
     function ^= functions_to_retain_.GetKey(it.Current());
     if (!function.HasCode()) continue;
     code = function.CurrentCode();
-    if (!visited.ContainsKey(code)) return function.raw();
+    if (!visited.ContainsKey(code)) return function.ptr();
   }
   return Function::null();
 }
 #endif
 
 void Precompiler::Obfuscate() {
-  if (!I->obfuscate()) {
+  if (!IG->obfuscate()) {
     return;
   }
 
@@ -2371,11 +2444,11 @@
   };
 
   GrowableHandlePtrArray<const Script> scripts(Z, 100);
-  Isolate::Current()->heap()->CollectAllGarbage();
+  IsolateGroup::Current()->heap()->CollectAllGarbage();
   {
     HeapIterationScope his(T);
     ScriptsCollector visitor(Z, &scripts);
-    I->heap()->VisitObjects(&visitor);
+    IG->heap()->VisitObjects(&visitor);
   }
 
   {
@@ -2412,10 +2485,10 @@
   }
 
   // Obfuscation is done. Move obfuscation map into malloced memory.
-  I->set_obfuscation_map(Obfuscator::SerializeMap(T));
+  IG->set_obfuscation_map(Obfuscator::SerializeMap(T));
 
   // Discard obfuscation mappings to avoid including them into snapshot.
-  I->object_store()->set_obfuscation_map(Array::Handle(Z));
+  IG->object_store()->set_obfuscation_map(Array::Handle(Z));
 }
 
 void Precompiler::FinalizeAllClasses() {
@@ -2450,6 +2523,8 @@
   const auto pool_attachment = FLAG_use_bare_instructions
                                    ? Code::PoolAttachment::kNotAttachPool
                                    : Code::PoolAttachment::kAttachPool;
+
+  SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
   const Code& code = Code::Handle(
       Code::FinalizeCodeAndNotify(function, graph_compiler, assembler,
                                   pool_attachment, optimized(), stats));
@@ -2523,7 +2598,7 @@
       ZoneGrowableArray<const ICData*>* ic_data_array = nullptr;
       const Function& function = parsed_function()->function();
 
-      CompilerState compiler_state(thread(), /*is_aot=*/true,
+      CompilerState compiler_state(thread(), /*is_aot=*/true, optimized(),
                                    CompilerState::ShouldTrace(function));
 
       {
@@ -2561,16 +2636,6 @@
       } else if (optimized()) {
         TIMELINE_DURATION(thread(), CompilerVerbose, "OptimizationPasses");
 
-        pass_state.inline_id_to_function.Add(&function);
-        // We do not add the token position now because we don't know the
-        // position of the inlined call until later. A side effect of this
-        // is that the length of |inline_id_to_function| is always larger
-        // than the length of |inline_id_to_token_pos| by one.
-        // Top scope function has no caller (-1). We do this because we expect
-        // all token positions to be at an inlined call.
-        // Top scope function has no caller (-1).
-        pass_state.caller_inline_id.Add(-1);
-
         AotCallSpecializer call_specializer(precompiler_, flow_graph,
                                             &speculative_policy);
         pass_state.call_specializer = &call_specializer;
@@ -2681,13 +2746,13 @@
       // We bailed out or we encountered an error.
       const Error& error = Error::Handle(thread()->StealStickyError());
 
-      if (error.raw() == Object::branch_offset_error().raw()) {
+      if (error.ptr() == Object::branch_offset_error().ptr()) {
         // Compilation failed due to an out of range branch offset in the
         // assembler. We try again (done = false) with far branches enabled.
         done = false;
         ASSERT(!use_far_branches);
         use_far_branches = true;
-      } else if (error.raw() == Object::speculative_inlining_error().raw()) {
+      } else if (error.ptr() == Object::speculative_inlining_error().ptr()) {
         // The return value of setjmp is the deopt id of the check instruction
         // that caused the bailout.
         done = false;
@@ -2743,7 +2808,7 @@
     per_compile_timer.Start();
 
     ParsedFunction* parsed_function = new (zone)
-        ParsedFunction(thread, Function::ZoneHandle(zone, function.raw()));
+        ParsedFunction(thread, Function::ZoneHandle(zone, function.ptr()));
     if (trace_compiler) {
       THR_Print("Precompiling %sfunction: '%s' @ token %" Pd ", size %" Pd "\n",
                 (optimized ? "optimized " : ""),
@@ -2763,7 +2828,7 @@
       const Error& error = Error::Handle(thread->StealStickyError());
       ASSERT(error.IsLanguageError() &&
              LanguageError::Cast(error).kind() != Report::kBailout);
-      return error.raw();
+      return error.ptr();
     }
 
     per_compile_timer.Stop();
@@ -2793,7 +2858,7 @@
     // Precompilation may encounter compile-time errors.
     // Do not attempt to optimize functions that can cause errors.
     function.set_is_optimizable(false);
-    return error.raw();
+    return error.ptr();
   }
   UNREACHABLE();
   return Error::null();
@@ -2818,15 +2883,15 @@
 
 Obfuscator::Obfuscator(Thread* thread, const String& private_key)
     : state_(NULL) {
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
-  if (!isolate->obfuscate()) {
+  auto isolate_group = thread->isolate_group();
+  if (!isolate_group->obfuscate()) {
     // Nothing to do.
     return;
   }
+  auto zone = thread->zone();
 
   // Create ObfuscationState from ObjectStore::obfusction_map().
-  ObjectStore* store = thread->isolate()->object_store();
+  ObjectStore* store = isolate_group->object_store();
   Array& obfuscation_state = Array::Handle(zone, store->obfuscation_map());
 
   if (store->obfuscation_map() == Array::null()) {
@@ -2843,7 +2908,7 @@
   if (store->obfuscation_map() == Array::null()) {
     // We are just starting the obfuscation. Initialize the renaming map.
     // Note: InitializeRenamingMap uses state_.
-    InitializeRenamingMap(isolate);
+    InitializeRenamingMap();
   }
 }
 
@@ -2853,7 +2918,7 @@
   }
 }
 
-void Obfuscator::InitializeRenamingMap(Isolate* isolate) {
+void Obfuscator::InitializeRenamingMap() {
 // Prevent renaming of all pseudo-keywords and operators.
 // Note: not all pseudo-keywords are mentioned in DART_KEYWORD_LIST
 // (for example 'hide', 'show' and async related keywords are omitted).
@@ -2954,7 +3019,7 @@
     renamed_ = BuildRename(name, atomic);
     renames_.UpdateOrInsert(name, renamed_);
   }
-  return renamed_.raw();
+  return renamed_.ptr();
 }
 
 static const char* const kGetterPrefix = "get:";
@@ -2987,7 +3052,7 @@
 void Obfuscator::ObfuscationState::SaveState() {
   saved_state_.SetAt(kSavedStateNameIndex, String::Handle(String::New(name_)));
   saved_state_.SetAt(kSavedStateRenamesIndex, renames_.Release());
-  thread_->isolate()->object_store()->set_obfuscation_map(saved_state_);
+  thread_->isolate_group()->object_store()->set_obfuscation_map(saved_state_);
 }
 
 void Obfuscator::ObfuscationState::PreventRenaming(const char* name) {
@@ -3030,8 +3095,8 @@
                                      should_be_private ? "_" : "", name_);
     // Must check if our generated name clashes with something that will
     // have an identity renaming.
-  } while (renames_.GetOrNull(renamed_) == renamed_.raw());
-  return renamed_.raw();
+  } while (renames_.GetOrNull(renamed_) == renamed_.ptr());
+  return renamed_.ptr();
 }
 
 StringPtr Obfuscator::ObfuscationState::BuildRename(const String& name,
@@ -3085,7 +3150,7 @@
     } else if (is_setter) {
       return Symbols::FromSet(thread_, string_);
     }
-    return string_.raw();
+    return string_.ptr();
   } else {
     return NewAtomicRename(is_private);
   }
@@ -3093,8 +3158,9 @@
 
 void Obfuscator::Deobfuscate(Thread* thread,
                              const GrowableObjectArray& pieces) {
-  const Array& obfuscation_state = Array::Handle(
-      thread->zone(), thread->isolate()->object_store()->obfuscation_map());
+  const Array& obfuscation_state =
+      Array::Handle(thread->zone(),
+                    thread->isolate_group()->object_store()->obfuscation_map());
   if (obfuscation_state.IsNull()) {
     return;
   }
@@ -3102,19 +3168,19 @@
   const Array& renames = Array::Handle(
       thread->zone(), GetRenamesFromSavedState(obfuscation_state));
 
-  ObfuscationMap renames_map(renames.raw());
+  ObfuscationMap renames_map(renames.ptr());
   String& piece = String::Handle();
   for (intptr_t i = 0; i < pieces.Length(); i++) {
     piece ^= pieces.At(i);
     ASSERT(piece.IsSymbol());
 
     // Fast path: skip '.'
-    if (piece.raw() == Symbols::Dot().raw()) {
+    if (piece.ptr() == Symbols::Dot().ptr()) {
       continue;
     }
 
     // Fast path: check if piece has an identity obfuscation.
-    if (renames_map.GetOrNull(piece) == piece.raw()) {
+    if (renames_map.GetOrNull(piece) == piece.ptr()) {
       continue;
     }
 
@@ -3124,7 +3190,7 @@
     ObfuscationMap::Iterator it(&renames_map);
     while (it.MoveNext()) {
       const intptr_t entry = it.Current();
-      if (renames_map.GetPayload(entry, 0) == piece.raw()) {
+      if (renames_map.GetPayload(entry, 0) == piece.ptr()) {
         piece ^= renames_map.GetKey(entry);
         pieces.SetAt(i, piece);
         break;
@@ -3143,15 +3209,16 @@
 }
 
 const char** Obfuscator::SerializeMap(Thread* thread) {
-  const Array& obfuscation_state = Array::Handle(
-      thread->zone(), thread->isolate()->object_store()->obfuscation_map());
+  const Array& obfuscation_state =
+      Array::Handle(thread->zone(),
+                    thread->isolate_group()->object_store()->obfuscation_map());
   if (obfuscation_state.IsNull()) {
     return NULL;
   }
 
   const Array& renames = Array::Handle(
       thread->zone(), GetRenamesFromSavedState(obfuscation_state));
-  ObfuscationMap renames_map(renames.raw());
+  ObfuscationMap renames_map(renames.ptr());
 
   const char** result = new const char*[renames_map.NumOccupied() * 2 + 1];
   intptr_t idx = 0;
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 41a7902..42406c4 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -62,7 +62,7 @@
   static inline intptr_t Hashcode(Key key) { return key->Hash(); }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair->raw() == key->raw();
+    return pair->ptr() == key->ptr();
   }
 };
 
@@ -73,7 +73,7 @@
   static uint32_t Hash(const Object& key) { return Function::Cast(key).Hash(); }
   static const char* Name() { return "FunctionKeyTraits"; }
   static bool IsMatch(const Object& x, const Object& y) {
-    return x.raw() == y.raw();
+    return x.ptr() == y.ptr();
   }
   static bool ReportStats() { return false; }
 };
@@ -94,13 +94,13 @@
   static inline intptr_t Hashcode(Key key) {
     const TokenPosition token_pos = key->token_pos();
     if (token_pos.IsReal()) {
-      return token_pos.value();
+      return token_pos.Hash();
     }
     return key->kernel_offset();
   }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair->raw() == key->raw();
+    return pair->ptr() == key->ptr();
   }
 };
 
@@ -117,10 +117,10 @@
 
   static Value ValueOf(Pair kv) { return kv; }
 
-  static inline intptr_t Hashcode(Key key) { return key->token_pos().value(); }
+  static inline intptr_t Hashcode(Key key) { return key->token_pos().Hash(); }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair->raw() == key->raw();
+    return pair->ptr() == key->ptr();
   }
 };
 
@@ -140,12 +140,32 @@
   static inline intptr_t Hashcode(Key key) { return key->Hash(); }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair->raw() == key->raw();
+    return pair->ptr() == key->ptr();
   }
 };
 
 typedef DirectChainedHashMap<AbstractTypeKeyValueTrait> AbstractTypeSet;
 
+class FunctionTypeKeyValueTrait {
+ public:
+  // Typedefs needed for the DirectChainedHashMap template.
+  typedef const FunctionType* Key;
+  typedef const FunctionType* Value;
+  typedef const FunctionType* Pair;
+
+  static Key KeyOf(Pair kv) { return kv; }
+
+  static Value ValueOf(Pair kv) { return kv; }
+
+  static inline intptr_t Hashcode(Key key) { return key->Hash(); }
+
+  static inline bool IsKeyEqual(Pair pair, Key key) {
+    return pair->ptr() == key->ptr();
+  }
+};
+
+typedef DirectChainedHashMap<FunctionTypeKeyValueTrait> FunctionTypeSet;
+
 class TypeParameterKeyValueTrait {
  public:
   // Typedefs needed for the DirectChainedHashMap template.
@@ -160,7 +180,7 @@
   static inline intptr_t Hashcode(Key key) { return key->Hash(); }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair->raw() == key->raw();
+    return pair->ptr() == key->ptr();
   }
 };
 
@@ -180,7 +200,7 @@
   static inline intptr_t Hashcode(Key key) { return key->Hash(); }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair->raw() == key->raw();
+    return pair->ptr() == key->ptr();
   }
 };
 
@@ -200,7 +220,7 @@
   static inline intptr_t Hashcode(Key key) { return key->GetClassId(); }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair->raw() == key->raw();
+    return pair->ptr() == key->ptr();
   }
 };
 
@@ -306,6 +326,7 @@
   void DropFields();
   void TraceTypesFromRetainedClasses();
   void DropTypes();
+  void DropFunctionTypes();
   void DropTypeParameters();
   void DropTypeArguments();
   void DropMetadata();
@@ -331,6 +352,7 @@
   Thread* thread() const { return thread_; }
   Zone* zone() const { return zone_; }
   Isolate* isolate() const { return isolate_; }
+  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
 
   Thread* thread_;
   Zone* zone_;
@@ -346,6 +368,7 @@
   intptr_t dropped_class_count_;
   intptr_t dropped_typearg_count_;
   intptr_t dropped_type_count_;
+  intptr_t dropped_functiontype_count_;
   intptr_t dropped_typeparam_count_;
   intptr_t dropped_library_count_;
 
@@ -360,6 +383,7 @@
   ClassSet classes_to_retain_;
   TypeArgumentsSet typeargs_to_retain_;
   AbstractTypeSet types_to_retain_;
+  FunctionTypeSet functiontypes_to_retain_;
   TypeParameterSet typeparams_to_retain_;
   InstanceSet consts_to_retain_;
   TableSelectorSet seen_table_selectors_;
@@ -381,7 +405,7 @@
   static bool ReportStats() { return false; }
 
   static bool IsMatch(const Object& a, const Object& b) {
-    return String::Cast(a).raw() == String::Cast(b).raw();
+    return String::Cast(a).ptr() == String::Cast(b).ptr();
   }
   static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); }
 };
@@ -397,7 +421,7 @@
 
   // Only for non-descriptor lookup and table expansion.
   static bool IsMatch(const Object& a, const Object& b) {
-    return a.raw() == b.raw();
+    return a.ptr() == b.ptr();
   }
 
   static uword Hash(const Object& key) { return String::Cast(key).Hash(); }
@@ -443,7 +467,7 @@
   // input and it always preserves leading '_' even for atomic renames.
   StringPtr Rename(const String& name, bool atomic = false) {
     if (state_ == NULL) {
-      return name.raw();
+      return name.ptr();
     }
 
     return state_->RenameImpl(name, atomic);
@@ -466,7 +490,7 @@
  private:
   // Populate renaming map with names that should have identity renaming.
   // (or in other words: with those names that should not be renamed).
-  void InitializeRenamingMap(Isolate* isolate);
+  void InitializeRenamingMap();
 
   // ObjectStore::obfuscation_map() is an Array with two elements:
   // first element is the last used rename and the second element is
@@ -478,13 +502,13 @@
   static ArrayPtr GetRenamesFromSavedState(const Array& saved_state) {
     Array& renames = Array::Handle();
     renames ^= saved_state.At(kSavedStateRenamesIndex);
-    return renames.raw();
+    return renames.ptr();
   }
 
   static StringPtr GetNameFromSavedState(const Array& saved_state) {
     String& name = String::Handle();
     name ^= saved_state.At(kSavedStateNameIndex);
-    return name.raw();
+    return name.ptr();
   }
 
   class ObfuscationState : public ZoneAllocated {
@@ -581,7 +605,7 @@
   ~Obfuscator() {}
 
   StringPtr Rename(const String& name, bool atomic = false) {
-    return name.raw();
+    return name.ptr();
   }
 
   void PreventRenaming(const String& name) {}
diff --git a/runtime/vm/compiler/aot/precompiler_tracer.cc b/runtime/vm/compiler/aot/precompiler_tracer.cc
index fcb56b2..40f6f58 100644
--- a/runtime/vm/compiler/aot/precompiler_tracer.cc
+++ b/runtime/vm/compiler/aot/precompiler_tracer.cc
@@ -32,6 +32,7 @@
 PrecompilerTracer::PrecompilerTracer(Precompiler* precompiler, void* stream)
     : zone_(Thread::Current()->zone()),
       precompiler_(precompiler),
+      buffer_(1024),
       stream_(stream),
       strings_(HashTables::New<StringTable>(1024)),
       entities_(HashTables::New<EntityTable>(1024)),
@@ -46,6 +47,11 @@
   Write(",");
   WriteStringTable();
   Write("}\n");
+
+  const intptr_t output_length = buffer_.length();
+  char* output = buffer_.Steal();
+  Dart::file_write_callback()(output, output_length, stream_);
+  free(output);
   Dart::file_close_callback()(stream_);
 
   strings_.Release();
@@ -147,7 +153,7 @@
     } else if (obj.IsField()) {
       cls_ = Field::Cast(obj).Owner();
     }
-    if (cls_.raw() != Class::null()) {
+    if (cls_.ptr() != Class::null()) {
       InternEntity(cls_);
     }
   }
diff --git a/runtime/vm/compiler/aot/precompiler_tracer.h b/runtime/vm/compiler/aot/precompiler_tracer.h
index b654457..70a9359 100644
--- a/runtime/vm/compiler/aot/precompiler_tracer.h
+++ b/runtime/vm/compiler/aot/precompiler_tracer.h
@@ -92,7 +92,7 @@
     static const char* Name() { return "EntityTableTraits"; }
 
     static bool IsMatch(const Object& a, const Object& b) {
-      return a.raw() == b.raw();
+      return a.ptr() == b.ptr();
     }
 
     static uword Hash(const Object& obj) {
@@ -119,8 +119,7 @@
   void Write(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) {
     va_list va;
     va_start(va, format);
-    const char* line = OS::VSCreate(zone_, format, va);
-    Dart::file_write_callback()(line, strlen(line), stream_);
+    buffer_.VPrintf(format, va);
     va_end(va);
   }
 
@@ -131,6 +130,7 @@
 
   Zone* zone_;
   Precompiler* precompiler_;
+  TextBuffer buffer_;
   void* stream_;
   StringTable strings_;
   EntityTable entities_;
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index fd9c7c7..2bdbc86 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -34,14 +34,16 @@
   COMPILE_ASSERT(IsAbiPreservedRegister(CALLEE_SAVED_TEMP));
 
   // Save LR by moving it to a callee saved temporary register.
-  assembler->Comment("IntrinsicCallPrologue");
-  assembler->mov(CALLEE_SAVED_TEMP, Operand(LR));
+  __ Comment("IntrinsicCallPrologue");
+  SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(
+      __ mov(CALLEE_SAVED_TEMP, Operand(LR)));
 }
 
 void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
   // Restore LR.
-  assembler->Comment("IntrinsicCallEpilogue");
-  assembler->mov(LR, Operand(CALLEE_SAVED_TEMP));
+  __ Comment("IntrinsicCallEpilogue");
+  RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(
+      __ mov(LR, Operand(CALLEE_SAVED_TEMP)));
 }
 
 // Allocate a GrowableObjectArray:: using the backing array specified.
@@ -93,7 +95,7 @@
                                              Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
   __ adds(R0, R0, Operand(R1));                      // Adds.
-  __ bx(LR, VC);                                     // Return if no overflow.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, VC));       // Return if no overflow.
   // Otherwise fall through.
   __ Bind(normal_ir_body);
 }
@@ -106,7 +108,7 @@
                                              Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   __ subs(R0, R0, Operand(R1));  // Subtract.
-  __ bx(LR, VC);                 // Return if no overflow.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, VC));  // Return if no overflow.
   // Otherwise fall through.
   __ Bind(normal_ir_body);
 }
@@ -114,7 +116,7 @@
 void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   __ subs(R0, R1, Operand(R0));  // Subtract.
-  __ bx(LR, VC);                 // Return if no overflow.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, VC));  // Return if no overflow.
   // Otherwise fall through.
   __ Bind(normal_ir_body);
 }
@@ -125,7 +127,7 @@
   __ SmiUntag(R0);           // Untags R0. We only want result shifted by one.
   __ smull(R0, IP, R0, R1);  // IP:R0 <- R0 * R1.
   __ cmp(IP, Operand(R0, ASR, 31));
-  __ bx(LR, EQ);
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, EQ));
   __ Bind(normal_ir_body);  // Fall through on overflow.
 }
 
@@ -155,10 +157,10 @@
   // Check for quick zero results.
   __ cmp(left, Operand(0));
   __ mov(R0, Operand(0), EQ);
-  __ bx(LR, EQ);  // left is 0? Return 0.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, EQ));  // left is 0? Return 0.
   __ cmp(left, Operand(right));
   __ mov(R0, Operand(0), EQ);
-  __ bx(LR, EQ);  // left == right? Return 0.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, EQ));  // left == right? Return 0.
 
   // Check if result should be left.
   __ cmp(left, Operand(0));
@@ -167,8 +169,7 @@
   __ cmp(left, Operand(right));
   // left is less than right, result is left.
   __ mov(R0, Operand(left), LT);
-  __ bx(LR, LT);
-
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, LT));
   __ Bind(&modulo);
   // result <- left - right * (left / right)
   __ SmiUntag(left);
@@ -209,8 +210,7 @@
 
   __ cmp(R1, Operand(0));
   __ mov(R0, Operand(R1, LSL, 1), GE);  // Tag and move result to R0.
-  __ bx(LR, GE);
-
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, GE));
   // Result is negative, adjust it.
   __ cmp(R0, Operand(0));
   __ sub(R0, R1, Operand(R0), LT);
@@ -241,7 +241,7 @@
   // cannot tag the result.
   __ CompareImmediate(R0, 0x40000000);
   __ SmiTag(R0, NE);  // Not equal. Okay to tag and return.
-  __ bx(LR, NE);      // Return.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
   __ Bind(normal_ir_body);
 }
 
@@ -251,7 +251,8 @@
   __ tst(R0, Operand(kSmiTagMask));                 // Test for Smi.
   __ b(normal_ir_body, NE);
   __ rsbs(R0, R0, Operand(0));  // R0 is a Smi. R0 <- 0 - R0.
-  __ bx(LR, VC);  // Return if there wasn't overflow, fall through otherwise.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(
+      LR, VC));  // Return if there wasn't overflow, fall through otherwise.
   // R0 is not a Smi. Fall through.
   __ Bind(normal_ir_body);
 }
@@ -314,8 +315,7 @@
 
   // No overflow, result in R0.
   __ mov(R0, Operand(R1, LSL, R0), EQ);
-  __ bx(LR, EQ);
-
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, EQ));
   // Arguments are Smi but the shift produced an overflow to Mint.
   __ CompareImmediate(R1, 0);
   __ b(normal_ir_body, LT);
@@ -500,8 +500,8 @@
   // Receiver is Mint, return false if right is Smi.
   __ tst(R0, Operand(kSmiTagMask));
   __ LoadObject(R0, CastHandle<Object>(FalseObject()), EQ);
-  __ bx(LR, EQ);
-  // TODO(srdjan): Implement Mint == Mint comparison.
+  READS_RETURN_ADDRESS_FROM_LR(
+      __ bx(LR, EQ));  // TODO(srdjan): Implement Mint == Mint comparison.
 
   __ Bind(normal_ir_body);
 }
@@ -1047,7 +1047,7 @@
     __ vmstat();
     __ LoadObject(R0, CastHandle<Object>(FalseObject()));
     // Return false if D0 or D1 was NaN before checking true condition.
-    __ bx(LR, VS);
+    READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, VS));
     __ LoadObject(R0, CastHandle<Object>(TrueObject()), true_condition);
     __ Ret();
 
@@ -1216,15 +1216,14 @@
     // If the low word isn't 0, then it isn't infinity.
     __ cmp(R1, Operand(0));
     __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
-    __ bx(LR, NE);  // Return if NE.
+    READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));  // Return if NE.
 
     // Mask off the sign bit.
     __ AndImmediate(R2, R2, 0x7FFFFFFF);
     // Compare with +infinity.
     __ CompareImmediate(R2, 0x7FF00000);
     __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
-    __ bx(LR, NE);
-
+    READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
     __ LoadObject(R0, CastHandle<Object>(TrueObject()));
     __ Ret();
   }
@@ -1280,7 +1279,7 @@
     // Check for overflow and that it fits into Smi.
     __ CompareImmediate(R0, 0xC0000000);
     __ SmiTag(R0, PL);
-    __ bx(LR, PL);
+    READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, PL));
     __ Bind(normal_ir_body);
   }
 }
@@ -1317,8 +1316,7 @@
   __ vcvtdi(D1, S2);
   __ vcmpd(D0, D1);
   __ vmstat();
-  __ bx(LR, EQ);
-
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, EQ));
   // Convert the double bits to a hash code that fits in a Smi.
   __ Bind(&double_hash);
   __ ldr(R0, FieldAddress(R1, target::Double::value_offset()));
@@ -1445,10 +1443,18 @@
              kIfNotInRange, target);
 }
 
+static void JumpIfNotType(Assembler* assembler,
+                          Register cid,
+                          Register tmp,
+                          Label* target) {
+  RangeCheck(assembler, cid, tmp, kTypeCid, kFunctionTypeCid, kIfNotInRange,
+             target);
+}
+
 // Return type quickly for simple types (not parameterized and not signature).
 void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
                                         Label* normal_ir_body) {
-  Label use_declaration_type, not_double, not_integer;
+  Label use_declaration_type, not_double, not_integer, not_string;
   __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
 
@@ -1474,12 +1480,19 @@
   __ Ret();
 
   __ Bind(&not_integer);
-  JumpIfNotString(assembler, R1, R0, &use_declaration_type);
+  JumpIfNotString(assembler, R1, R0, &not_string);
   __ LoadIsolate(R0);
   __ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
   __ LoadFromOffset(R0, R0, target::ObjectStore::string_type_offset());
   __ Ret();
 
+  __ Bind(&not_string);
+  JumpIfNotType(assembler, R1, R0, &use_declaration_type);
+  __ LoadIsolate(R0);
+  __ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
+  __ LoadFromOffset(R0, R0, target::ObjectStore::type_type_offset());
+  __ Ret();
+
   __ Bind(&use_declaration_type);
   __ LoadClassById(R2, R1);
   __ ldrh(R3, FieldAddress(R2, target::Class::num_type_arguments_offset()));
@@ -1579,9 +1592,8 @@
   __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ ldr(R0, FieldAddress(R0, target::String::hash_offset()));
   __ cmp(R0, Operand(0));
-  __ bx(LR, NE);
-  // Hash not yet computed.
-  __ Bind(normal_ir_body);
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
+  __ Bind(normal_ir_body);  // Hash not yet computed.
 }
 
 void AsmIntrinsifier::Type_getHashCode(Assembler* assembler,
@@ -1589,9 +1601,8 @@
   __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ ldr(R0, FieldAddress(R0, target::Type::hash_offset()));
   __ cmp(R0, Operand(0));
-  __ bx(LR, NE);
-  // Hash not yet computed.
-  __ Bind(normal_ir_body);
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
+  __ Bind(normal_ir_body);  // Hash not yet computed.
 }
 
 void AsmIntrinsifier::Type_equality(Assembler* assembler,
@@ -1646,6 +1657,27 @@
   __ Bind(normal_ir_body);
 }
 
+void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::FunctionType::hash_offset()));
+  __ cmp(R0, Operand(0));
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
+  __ Bind(normal_ir_body);  // Hash not yet computed.
+}
+
+void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  __ ldm(IA, SP, (1 << R1 | 1 << R2));
+  __ cmp(R1, Operand(R2));
+  __ b(normal_ir_body, NE);
+
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
+  __ Ret();
+
+  __ Bind(normal_ir_body);
+}
+
 void GenerateSubstringMatchesSpecialization(Assembler* assembler,
                                             intptr_t receiver_cid,
                                             intptr_t other_cid,
@@ -1831,7 +1863,7 @@
   __ ldr(R1, Address(SP, 0 * target::kWordSize));
   __ ldr(R0, FieldAddress(R1, target::String::hash_offset()));
   __ cmp(R0, Operand(0));
-  __ bx(LR, NE);  // Return if already computed.
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));  // Return if already computed.
 
   __ ldr(R2, FieldAddress(R1, target::String::length_offset()));
 
@@ -1941,10 +1973,10 @@
   // R1: new object end address.
   // R2: allocation size.
   {
-    const intptr_t shift = target::ObjectLayout::kTagBitsSizeTagPos -
+    const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2;
 
-    __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);
+    __ CompareImmediate(R2, target::UntaggedObject::kSizeTagMaxSizeTag);
     __ mov(R3, Operand(R2, LSL, shift), LS);
     __ mov(R3, Operand(0), HI);
 
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 1c1271d..80d2290 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -38,15 +38,15 @@
   COMPILE_ASSERT(CALLEE_SAVED_TEMP2 != CODE_REG);
   COMPILE_ASSERT(CALLEE_SAVED_TEMP2 != ARGS_DESC_REG);
 
-  assembler->Comment("IntrinsicCallPrologue");
-  assembler->mov(CALLEE_SAVED_TEMP, LR);
-  assembler->mov(CALLEE_SAVED_TEMP2, ARGS_DESC_REG);
+  __ Comment("IntrinsicCallPrologue");
+  SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(__ mov(CALLEE_SAVED_TEMP, LR));
+  __ mov(CALLEE_SAVED_TEMP2, ARGS_DESC_REG);
 }
 
 void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
-  assembler->Comment("IntrinsicCallEpilogue");
-  assembler->mov(LR, CALLEE_SAVED_TEMP);
-  assembler->mov(ARGS_DESC_REG, CALLEE_SAVED_TEMP2);
+  __ Comment("IntrinsicCallEpilogue");
+  RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(__ mov(LR, CALLEE_SAVED_TEMP));
+  __ mov(ARGS_DESC_REG, CALLEE_SAVED_TEMP2);
 }
 
 // Allocate a GrowableObjectArray:: using the backing array specified.
@@ -1513,10 +1513,18 @@
              kIfNotInRange, target);
 }
 
+static void JumpIfNotType(Assembler* assembler,
+                          Register cid,
+                          Register tmp,
+                          Label* target) {
+  RangeCheck(assembler, cid, tmp, kTypeCid, kFunctionTypeCid, kIfNotInRange,
+             target);
+}
+
 // Return type quickly for simple types (not parameterized and not signature).
 void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
                                         Label* normal_ir_body) {
-  Label use_declaration_type, not_double, not_integer;
+  Label use_declaration_type, not_double, not_integer, not_string;
   __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
 
@@ -1542,12 +1550,19 @@
   __ ret();
 
   __ Bind(&not_integer);
-  JumpIfNotString(assembler, R1, R0, &use_declaration_type);
+  JumpIfNotString(assembler, R1, R0, &not_string);
   __ LoadIsolate(R0);
   __ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
   __ LoadFromOffset(R0, R0, target::ObjectStore::string_type_offset());
   __ ret();
 
+  __ Bind(&not_string);
+  JumpIfNotType(assembler, R1, R0, &use_declaration_type);
+  __ LoadIsolate(R0);
+  __ LoadFromOffset(R0, R0, target::Isolate::cached_object_store_offset());
+  __ LoadFromOffset(R0, R0, target::ObjectStore::type_type_offset());
+  __ ret();
+
   __ Bind(&use_declaration_type);
   __ LoadClassById(R2, R1);
   __ ldr(
@@ -1723,6 +1738,28 @@
   __ Bind(normal_ir_body);
 }
 
+void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::FunctionType::hash_offset()));
+  __ cbz(normal_ir_body, R0);
+  __ ret();
+  // Hash not yet computed.
+  __ Bind(normal_ir_body);
+}
+
+void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  __ ldp(R1, R2, Address(SP, 0 * target::kWordSize, Address::PairOffset));
+  __ cmp(R1, Operand(R2));
+  __ b(normal_ir_body, NE);
+
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
 void AsmIntrinsifier::Object_getHash(Assembler* assembler,
                                      Label* normal_ir_body) {
   __ ldr(R0, Address(SP, 0 * target::kWordSize));
@@ -1739,7 +1776,7 @@
   // R0: Untagged address of header word (ldxr/stxr do not support offsets).
   __ sub(R0, R0, Operand(kHeapObjectTag));
   __ SmiUntag(R1);
-  __ LslImmediate(R1, R1, target::ObjectLayout::kHashTagPos);
+  __ LslImmediate(R1, R1, target::UntaggedObject::kHashTagPos);
   Label retry;
   __ Bind(&retry);
   __ ldxr(R2, R0, kEightBytes);
@@ -1971,7 +2008,7 @@
 
   // R1: Untagged address of header word (ldxr/stxr do not support offsets).
   __ sub(R1, R1, Operand(kHeapObjectTag));
-  __ LslImmediate(R0, R0, target::ObjectLayout::kHashTagPos);
+  __ LslImmediate(R0, R0, target::UntaggedObject::kHashTagPos);
   Label retry;
   __ Bind(&retry);
   __ ldxr(R2, R1, kEightBytes);
@@ -1979,7 +2016,7 @@
   __ stxr(R4, R2, R1, kEightBytes);
   __ cbnz(&retry, R4);
 
-  __ LsrImmediate(R0, R0, target::ObjectLayout::kHashTagPos);
+  __ LsrImmediate(R0, R0, target::UntaggedObject::kHashTagPos);
   __ SmiTag(R0);
   __ ret();
 }
@@ -2038,10 +2075,10 @@
   // R1: new object end address.
   // R2: allocation size.
   {
-    const intptr_t shift = target::ObjectLayout::kTagBitsSizeTagPos -
+    const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2;
 
-    __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);
+    __ CompareImmediate(R2, target::UntaggedObject::kSizeTagMaxSizeTag);
     __ LslImmediate(R2, R2, shift);
     __ csel(R2, R2, ZR, LS);
 
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index ec97c64..89f488c 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -1538,10 +1538,14 @@
              kIfNotInRange, target);
 }
 
+static void JumpIfNotType(Assembler* assembler, Register cid, Label* target) {
+  RangeCheck(assembler, cid, kTypeCid, kFunctionTypeCid, kIfNotInRange, target);
+}
+
 // Return type quickly for simple types (not parameterized and not signature).
 void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
                                         Label* normal_ir_body) {
-  Label use_declaration_type, not_double, not_integer;
+  Label use_declaration_type, not_double, not_integer, not_string;
   __ movl(EAX, Address(ESP, +1 * target::kWordSize));
   __ LoadClassIdMayBeSmi(EDI, EAX);
 
@@ -1574,14 +1578,24 @@
   // If object is a string (one byte, two byte or external variants) return
   // string type.
   __ movl(EAX, EDI);
-  JumpIfNotString(assembler, EAX, &use_declaration_type);
+  JumpIfNotString(assembler, EAX, &not_string);
 
   __ LoadIsolate(EAX);
   __ movl(EAX, Address(EAX, target::Isolate::cached_object_store_offset()));
   __ movl(EAX, Address(EAX, target::ObjectStore::string_type_offset()));
   __ ret();
 
-  // Object is neither double, nor integer, nor string.
+  __ Bind(&not_string);
+  // If object is a type or function type, return Dart type.
+  __ movl(EAX, EDI);
+  JumpIfNotType(assembler, EAX, &use_declaration_type);
+
+  __ LoadIsolate(EAX);
+  __ movl(EAX, Address(EAX, target::Isolate::cached_object_store_offset()));
+  __ movl(EAX, Address(EAX, target::ObjectStore::type_type_offset()));
+  __ ret();
+
+  // Object is neither double, nor integer, nor string, nor type.
   __ Bind(&use_declaration_type);
   __ LoadClassById(EBX, EDI);
   __ movzxw(EDI, FieldAddress(EBX, target::Class::num_type_arguments_offset()));
@@ -1752,6 +1766,30 @@
   __ Bind(normal_ir_body);
 }
 
+void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // FunctionType object.
+  __ movl(EAX, FieldAddress(EAX, target::FunctionType::hash_offset()));
+  __ testl(EAX, EAX);
+  __ j(EQUAL, normal_ir_body, Assembler::kNearJump);
+  __ ret();
+  __ Bind(normal_ir_body);
+  // Hash not yet computed.
+}
+
+void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  __ movl(EDI, Address(ESP, +1 * target::kWordSize));
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
+  __ cmpl(EDI, EBX);
+  __ j(NOT_EQUAL, normal_ir_body);
+
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
 // bool _substringMatches(int start, String other)
 void AsmIntrinsifier::StringBaseSubstringMatches(Assembler* assembler,
                                                  Label* normal_ir_body) {
@@ -1954,9 +1992,9 @@
   // EDI: allocation size.
   {
     Label size_tag_overflow, done;
-    __ cmpl(EDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+    __ cmpl(EDI, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shll(EDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+    __ shll(EDI, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done, Assembler::kNearJump);
 
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 8a424dd..bcfbd8e 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -1444,10 +1444,13 @@
              kIfNotInRange, target);
 }
 
+static void JumpIfNotType(Assembler* assembler, Register cid, Label* target) {
+  RangeCheck(assembler, cid, kTypeCid, kFunctionTypeCid, kIfNotInRange, target);
+}
 // Return type quickly for simple types (not parameterized and not signature).
 void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
                                         Label* normal_ir_body) {
-  Label use_declaration_type, not_integer, not_double;
+  Label use_declaration_type, not_integer, not_double, not_string;
   __ movq(RAX, Address(RSP, +1 * target::kWordSize));
   __ LoadClassIdMayBeSmi(RCX, RAX);
 
@@ -1481,14 +1484,24 @@
   // If object is a string (one byte, two byte or external variants) return
   // string type.
   __ movq(RAX, RCX);
-  JumpIfNotString(assembler, RAX, &use_declaration_type);
+  JumpIfNotString(assembler, RAX, &not_string);
 
   __ LoadIsolate(RAX);
   __ movq(RAX, Address(RAX, target::Isolate::cached_object_store_offset()));
   __ movq(RAX, Address(RAX, target::ObjectStore::string_type_offset()));
   __ ret();
 
-  // Object is neither double, nor integer, nor string.
+  __ Bind(&not_string);
+  // If object is a type or function type, return Dart type.
+  __ movq(RAX, RCX);
+  JumpIfNotType(assembler, RAX, &use_declaration_type);
+
+  __ LoadIsolate(RAX);
+  __ movq(RAX, Address(RAX, target::Isolate::cached_object_store_offset()));
+  __ movq(RAX, Address(RAX, target::ObjectStore::type_type_offset()));
+  __ ret();
+
+  // Object is neither double, nor integer, nor string, nor type.
   __ Bind(&use_declaration_type);
   __ LoadClassById(RDI, RCX);
   __ movzxw(RCX, FieldAddress(RDI, target::Class::num_type_arguments_offset()));
@@ -1663,6 +1676,32 @@
   __ Bind(normal_ir_body);
 }
 
+void AsmIntrinsifier::FunctionType_getHashCode(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // FunctionType object.
+  __ movq(RAX, FieldAddress(RAX, target::FunctionType::hash_offset()));
+  ASSERT(kSmiTag == 0);
+  ASSERT(kSmiTagShift == 1);
+  __ testq(RAX, RAX);
+  __ j(ZERO, normal_ir_body, Assembler::kNearJump);
+  __ ret();
+  __ Bind(normal_ir_body);
+  // Hash not yet computed.
+}
+
+void AsmIntrinsifier::FunctionType_equality(Assembler* assembler,
+                                            Label* normal_ir_body) {
+  __ movq(RCX, Address(RSP, +1 * target::kWordSize));
+  __ movq(RDX, Address(RSP, +2 * target::kWordSize));
+  __ cmpq(RCX, RDX);
+  __ j(NOT_EQUAL, normal_ir_body);
+
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
+  __ ret();
+
+  __ Bind(normal_ir_body);
+}
+
 void AsmIntrinsifier::Object_getHash(Assembler* assembler,
                                      Label* normal_ir_body) {
   __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // Object.
@@ -1676,7 +1715,7 @@
   __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Object.
   __ movq(RDX, Address(RSP, +1 * target::kWordSize));  // Value.
   __ SmiUntag(RDX);
-  __ shlq(RDX, Immediate(target::ObjectLayout::kHashTagPos));
+  __ shlq(RDX, Immediate(target::UntaggedObject::kHashTagPos));
   // lock+orq is an atomic read-modify-write.
   __ lock();
   __ orq(FieldAddress(RAX, target::Object::tags_offset()), RDX);
@@ -1914,11 +1953,11 @@
   __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump);
   __ incq(RAX);
   __ Bind(&set_hash_code);
-  __ shlq(RAX, Immediate(target::ObjectLayout::kHashTagPos));
+  __ shlq(RAX, Immediate(target::UntaggedObject::kHashTagPos));
   // lock+orq is an atomic read-modify-write.
   __ lock();
   __ orq(FieldAddress(RBX, target::Object::tags_offset()), RAX);
-  __ sarq(RAX, Immediate(target::ObjectLayout::kHashTagPos));
+  __ sarq(RAX, Immediate(target::UntaggedObject::kHashTagPos));
   __ SmiTag(RAX);
   __ ret();
 }
@@ -1981,9 +2020,9 @@
   // RDI: allocation size.
   {
     Label size_tag_overflow, done;
-    __ cmpq(RDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+    __ cmpq(RDI, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shlq(RDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+    __ shlq(RDI, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done, Assembler::kNearJump);
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index bcab63b..4ba28d6 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -19,6 +19,9 @@
 #error ARM cross-compile only supported on Linux, Android, iOS, and Mac
 #endif
 
+// For use by LR related macros (e.g. CLOBBERS_LR).
+#define __ this->
+
 namespace dart {
 
 DECLARE_FLAG(bool, check_code_pointer);
@@ -34,16 +37,13 @@
       use_far_branches_(use_far_branches),
       constant_pool_allowed_(false) {
   generate_invoke_write_barrier_wrapper_ = [&](Condition cond, Register reg) {
-    ldr(LR,
+    Call(
         Address(THR, target::Thread::write_barrier_wrappers_thread_offset(reg)),
         cond);
-    blx(LR, cond);
   };
   generate_invoke_array_write_barrier_ = [&](Condition cond) {
-    ldr(LR,
-        Address(THR, target::Thread::array_write_barrier_entry_point_offset()),
-        cond);
-    blx(LR, cond);
+    Call(Address(THR, target::Thread::array_write_barrier_entry_point_offset()),
+         cond);
   };
 }
 
@@ -1625,10 +1625,7 @@
       return;
     }
   }
-  if (!CanLoadFromObjectPool(object)) {
-    UNREACHABLE();
-    return;
-  }
+  RELEASE_ASSERT(CanLoadFromObjectPool(object));
   // Make sure that class CallPattern is able to decode this load from the
   // object pool.
   const auto index = is_unique ? object_pool_builder().AddObject(object)
@@ -1726,12 +1723,11 @@
 void Assembler::StoreIntoObject(Register object,
                                 const Address& dest,
                                 Register value,
-                                CanBeSmi can_be_smi,
-                                bool lr_reserved) {
+                                CanBeSmi can_be_smi) {
   // x.slot = x. Barrier should have be removed at the IL level.
   ASSERT(object != value);
-  ASSERT(object != LR);
-  ASSERT(value != LR);
+  ASSERT(object != LINK_REGISTER);
+  ASSERT(value != LINK_REGISTER);
   ASSERT(object != TMP);
   ASSERT(value != TMP);
 
@@ -1743,17 +1739,23 @@
   //    in progress
   // If so, call the WriteBarrier stub, which will either add object to the
   // store buffer (case 1) or add value to the marking stack (case 2).
-  // Compare ObjectLayout::StorePointer.
+  // Compare UntaggedObject::StorePointer.
   Label done;
   if (can_be_smi == kValueCanBeSmi) {
     BranchIfSmi(value, &done);
   }
-  if (!lr_reserved) Push(LR);
-  ldrb(TMP, FieldAddress(object, target::Object::tags_offset()));
-  ldrb(LR, FieldAddress(value, target::Object::tags_offset()));
-  and_(TMP, LR, Operand(TMP, LSR, target::ObjectLayout::kBarrierOverlapShift));
-  ldr(LR, Address(THR, target::Thread::write_barrier_mask_offset()));
-  tst(TMP, Operand(LR));
+  const bool preserve_lr = lr_state().LRContainsReturnAddress();
+  if (preserve_lr) {
+    SPILLS_LR_TO_FRAME(Push(LR));
+  }
+  CLOBBERS_LR({
+    ldrb(TMP, FieldAddress(object, target::Object::tags_offset()));
+    ldrb(LR, FieldAddress(value, target::Object::tags_offset()));
+    and_(TMP, LR,
+         Operand(TMP, LSR, target::UntaggedObject::kBarrierOverlapShift));
+    ldr(LR, Address(THR, target::Thread::write_barrier_mask_offset()));
+    tst(TMP, Operand(LR));
+  });
   if (value != kWriteBarrierValueReg) {
     // Unlikely. Only non-graph intrinsics.
     // TODO(rmacnak): Shuffle registers in intrinsics.
@@ -1781,20 +1783,21 @@
   } else {
     generate_invoke_write_barrier_wrapper_(NE, object);
   }
-  if (!lr_reserved) Pop(LR);
+  if (preserve_lr) {
+    RESTORES_LR_FROM_FRAME(Pop(LR));
+  }
   Bind(&done);
 }
 
 void Assembler::StoreIntoArray(Register object,
                                Register slot,
                                Register value,
-                               CanBeSmi can_be_smi,
-                               bool lr_reserved) {
+                               CanBeSmi can_be_smi) {
   // x.slot = x. Barrier should have be removed at the IL level.
   ASSERT(object != value);
-  ASSERT(object != LR);
-  ASSERT(value != LR);
-  ASSERT(slot != LR);
+  ASSERT(object != LINK_REGISTER);
+  ASSERT(value != LINK_REGISTER);
+  ASSERT(slot != LINK_REGISTER);
   ASSERT(object != TMP);
   ASSERT(value != TMP);
   ASSERT(slot != TMP);
@@ -1807,17 +1810,24 @@
   //    in progress
   // If so, call the WriteBarrier stub, which will either add object to the
   // store buffer (case 1) or add value to the marking stack (case 2).
-  // Compare ObjectLayout::StorePointer.
+  // Compare UntaggedObject::StorePointer.
   Label done;
   if (can_be_smi == kValueCanBeSmi) {
     BranchIfSmi(value, &done);
   }
-  if (!lr_reserved) Push(LR);
-  ldrb(TMP, FieldAddress(object, target::Object::tags_offset()));
-  ldrb(LR, FieldAddress(value, target::Object::tags_offset()));
-  and_(TMP, LR, Operand(TMP, LSR, target::ObjectLayout::kBarrierOverlapShift));
-  ldr(LR, Address(THR, target::Thread::write_barrier_mask_offset()));
-  tst(TMP, Operand(LR));
+  const bool preserve_lr = lr_state().LRContainsReturnAddress();
+  if (preserve_lr) {
+    SPILLS_LR_TO_FRAME(Push(LR));
+  }
+
+  CLOBBERS_LR({
+    ldrb(TMP, FieldAddress(object, target::Object::tags_offset()));
+    ldrb(LR, FieldAddress(value, target::Object::tags_offset()));
+    and_(TMP, LR,
+         Operand(TMP, LSR, target::UntaggedObject::kBarrierOverlapShift));
+    ldr(LR, Address(THR, target::Thread::write_barrier_mask_offset()));
+    tst(TMP, Operand(LR));
+  });
 
   if ((object != kWriteBarrierObjectReg) || (value != kWriteBarrierValueReg) ||
       (slot != kWriteBarrierSlotReg)) {
@@ -1827,23 +1837,24 @@
     UNIMPLEMENTED();
   }
   generate_invoke_array_write_barrier_(NE);
-  if (!lr_reserved) Pop(LR);
+  if (preserve_lr) {
+    RESTORES_LR_FROM_FRAME(Pop(LR));
+  }
   Bind(&done);
 }
 
 void Assembler::StoreIntoObjectOffset(Register object,
                                       int32_t offset,
                                       Register value,
-                                      CanBeSmi can_value_be_smi,
-                                      bool lr_reserved) {
+                                      CanBeSmi can_value_be_smi) {
   int32_t ignored = 0;
   if (Address::CanHoldStoreOffset(kFourBytes, offset - kHeapObjectTag,
                                   &ignored)) {
     StoreIntoObject(object, FieldAddress(object, offset), value,
-                    can_value_be_smi, lr_reserved);
+                    can_value_be_smi);
   } else {
     AddImmediate(IP, object, offset - kHeapObjectTag);
-    StoreIntoObject(object, Address(IP), value, can_value_be_smi, lr_reserved);
+    StoreIntoObject(object, Address(IP), value, can_value_be_smi);
   }
 }
 
@@ -1856,7 +1867,7 @@
   StoreIntoObjectFilter(object, value, &done, kValueCanBeSmi, kJumpToNoUpdate);
 
   ldrb(TMP, FieldAddress(object, target::Object::tags_offset()));
-  tst(TMP, Operand(1 << target::ObjectLayout::kOldAndNotRememberedBit));
+  tst(TMP, Operand(1 << target::UntaggedObject::kOldAndNotRememberedBit));
   b(&done, ZERO);
 
   Stop("Store buffer update is required");
@@ -1979,29 +1990,29 @@
 }
 
 void Assembler::ExtractClassIdFromTags(Register result, Register tags) {
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
-  Lsr(result, tags, Operand(target::ObjectLayout::kClassIdTagPos), AL);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
+  Lsr(result, tags, Operand(target::UntaggedObject::kClassIdTagPos), AL);
 }
 
 void Assembler::ExtractInstanceSizeFromTags(Register result, Register tags) {
-  ASSERT(target::ObjectLayout::kSizeTagPos == 8);
-  ASSERT(target::ObjectLayout::kSizeTagSize == 8);
+  ASSERT(target::UntaggedObject::kSizeTagPos == 8);
+  ASSERT(target::UntaggedObject::kSizeTagSize == 8);
   Lsr(result, tags,
-      Operand(target::ObjectLayout::kSizeTagPos -
+      Operand(target::UntaggedObject::kSizeTagPos -
               target::ObjectAlignment::kObjectAlignmentLog2),
       AL);
   AndImmediate(result, result,
-               (Utils::NBitMask(target::ObjectLayout::kSizeTagSize)
+               (Utils::NBitMask(target::UntaggedObject::kSizeTagSize)
                 << target::ObjectAlignment::kObjectAlignmentLog2));
 }
 
 void Assembler::LoadClassId(Register result, Register object, Condition cond) {
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
   const intptr_t class_id_offset =
       target::Object::tags_offset() +
-      target::ObjectLayout::kClassIdTagPos / kBitsPerByte;
+      target::UntaggedObject::kClassIdTagPos / kBitsPerByte;
   ldrh(result, FieldAddress(object, class_id_offset), cond);
 }
 
@@ -2122,6 +2133,7 @@
     } else {
       EmitType5(cond, dest, link);
     }
+    label->UpdateLRState(lr_state());
   } else {
     const intptr_t position = buffer_.Size();
     if (use_far_branches()) {
@@ -2131,7 +2143,7 @@
       // Use the offset field of the branch instruction for linking the sites.
       EmitType5(cond, label->position_, link);
     }
-    label->LinkTo(position);
+    label->LinkTo(position, lr_state());
   }
 }
 
@@ -2199,7 +2211,7 @@
       label->position_ = Assembler::DecodeBranchOffset(next);
     }
   }
-  label->BindTo(bound_pc);
+  label->BindTo(bound_pc, lr_state());
 }
 
 void Assembler::Bind(Label* label) {
@@ -2604,8 +2616,7 @@
   const intptr_t index =
       object_pool_builder().FindObject(ToObject(target), patchable);
   LoadWordFromPoolIndex(CODE_REG, index, PP, AL);
-  ldr(LR, FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
-  blx(LR);  // Use blx instruction so that the return branch prediction works.
+  Call(FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
 }
 
 void Assembler::BranchLinkPatchable(const Code& target,
@@ -2628,13 +2639,14 @@
   const intptr_t index =
       object_pool_builder().FindObject(ToObject(target), equivalence);
   LoadWordFromPoolIndex(CODE_REG, index, PP, AL);
-  ldr(LR, FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
-  blx(LR);  // Use blx instruction so that the return branch prediction works.
+  Call(FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
 }
 
 void Assembler::BranchLink(const ExternalLabel* label) {
-  LoadImmediate(LR, label->address());  // Target address is never patched.
-  blx(LR);  // Use blx instruction so that the return branch prediction works.
+  CLOBBERS_LR({
+    LoadImmediate(LR, label->address());  // Target address is never patched.
+    blx(LR);  // Use blx instruction so that the return branch prediction works.
+  });
 }
 
 void Assembler::BranchLinkOffset(Register base, int32_t offset) {
@@ -3117,8 +3129,8 @@
   PopList(regs);
 }
 
-void Assembler::Ret() {
-  bx(LR);
+void Assembler::Ret(Condition cond /* = AL */) {
+  READS_RETURN_ADDRESS_FROM_LR(bx(LR, cond));
 }
 
 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
@@ -3149,7 +3161,8 @@
 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) {
   Comment("EnterCallRuntimeFrame");
   // Preserve volatile CPU registers and PP.
-  EnterFrame(kDartVolatileCpuRegs | (1 << PP) | (1 << FP) | (1 << LR), 0);
+  SPILLS_LR_TO_FRAME(
+      EnterFrame(kDartVolatileCpuRegs | (1 << PP) | (1 << FP) | (1 << LR), 0));
   COMPILE_ASSERT((kDartVolatileCpuRegs & (1 << PP)) == 0);
 
   // Preserve all volatile FPU registers.
@@ -3199,7 +3212,8 @@
   }
 
   // Restore volatile CPU registers.
-  LeaveFrame(kDartVolatileCpuRegs | (1 << PP) | (1 << FP) | (1 << LR));
+  RESTORES_LR_FROM_FRAME(
+      LeaveFrame(kDartVolatileCpuRegs | (1 << PP) | (1 << FP) | (1 << LR)));
 }
 
 void Assembler::CallRuntime(const RuntimeEntry& entry,
@@ -3213,15 +3227,16 @@
   // Registers are pushed in descending order: R5 | R6 | R7/R11 | R14.
   COMPILE_ASSERT(PP < CODE_REG);
   COMPILE_ASSERT(CODE_REG < FP);
-  COMPILE_ASSERT(FP < LR);
+  COMPILE_ASSERT(FP < LINK_REGISTER.code);
 
   if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
-    EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << LR), 0);
+    SPILLS_LR_TO_FRAME(
+        EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << LR), 0));
 
     // Setup pool pointer for this dart function.
     if (load_pool_pointer) LoadPoolPointer();
   } else {
-    EnterFrame((1 << FP) | (1 << LR), 0);
+    SPILLS_LR_TO_FRAME(EnterFrame((1 << FP) | (1 << LR), 0));
   }
   set_constant_pool_allowed(true);
 
@@ -3252,7 +3267,7 @@
 
   // This will implicitly drop saved PP, PC marker due to restoring SP from FP
   // first.
-  LeaveFrame((1 << FP) | (1 << LR));
+  RESTORES_LR_FROM_FRAME(LeaveFrame((1 << FP) | (1 << LR)));
 }
 
 void Assembler::LeaveDartFrameAndReturn() {
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index f853da7..62a6414 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -752,9 +752,14 @@
   // Branch and link to [base + offset]. Call sequence is never patched.
   void BranchLinkOffset(Register base, int32_t offset);
 
-  void Call(Address target) {
-    ldr(LR, target);
-    blx(LR);
+  void Call(Address target, Condition cond = AL) {
+    // CLOBBERS_LR uses __ to access the assembler.
+#define __ this->
+    CLOBBERS_LR({
+      ldr(LR, target, cond);
+      blx(LR, cond);
+    });
+#undef __
   }
   void Call(const Code& code) { BranchLink(code); }
 
@@ -855,18 +860,15 @@
   void StoreIntoObject(Register object,      // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
                        Register value,       // Value we are storing.
-                       CanBeSmi can_value_be_smi = kValueCanBeSmi,
-                       bool lr_reserved = false);
+                       CanBeSmi can_value_be_smi = kValueCanBeSmi);
   void StoreIntoArray(Register object,
                       Register slot,
                       Register value,
-                      CanBeSmi can_value_be_smi = kValueCanBeSmi,
-                      bool lr_reserved = false);
+                      CanBeSmi can_value_be_smi = kValueCanBeSmi);
   void StoreIntoObjectOffset(Register object,
                              int32_t offset,
                              Register value,
-                             CanBeSmi can_value_be_smi = kValueCanBeSmi,
-                             bool lr_reserved = false);
+                             CanBeSmi can_value_be_smi = kValueCanBeSmi);
 
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
@@ -1116,7 +1118,7 @@
   // Function frame setup and tear down.
   void EnterFrame(RegList regs, intptr_t frame_space);
   void LeaveFrame(RegList regs, bool allow_pop_pc = false);
-  void Ret();
+  void Ret(Condition cond = AL);
   void ReserveAlignedFrameSpace(intptr_t frame_space);
 
   // In debug mode, this generates code to check that:
@@ -1252,7 +1254,7 @@
   // before the code can be used.
   //
   // The neccessary information for the "linker" (i.e. the relocation
-  // information) is stored in [CodeLayout::static_calls_target_table_]: an
+  // information) is stored in [UntaggedCode::static_calls_target_table_]: an
   // entry of the form
   //
   //   (Code::kPcRelativeCall & pc_offset, <target-code>, <target-function>)
@@ -1282,6 +1284,9 @@
   bool constant_pool_allowed() const { return constant_pool_allowed_; }
   void set_constant_pool_allowed(bool b) { constant_pool_allowed_ = b; }
 
+  compiler::LRState lr_state() const { return lr_state_; }
+  void set_lr_state(compiler::LRState b) { lr_state_ = b; }
+
   // Whether we can branch to a target which is [distance] bytes away from the
   // beginning of the branch instruction.
   //
@@ -1301,6 +1306,10 @@
  private:
   bool use_far_branches_;
 
+  bool constant_pool_allowed_;
+
+  compiler::LRState lr_state_ = compiler::LRState::OnEntry();
+
   // If you are thinking of using one or both of these instructions directly,
   // instead LoadImmediate should probably be used.
   void movw(Register rd, uint16_t imm16, Condition cond = AL);
@@ -1310,8 +1319,6 @@
 
   void BranchLink(const ExternalLabel* label);
 
-  bool constant_pool_allowed_;
-
   void LoadObjectHelper(Register rd,
                         const Object& object,
                         Condition cond,
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 00b02db..29a0ec9 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -22,6 +22,9 @@
 
 DEFINE_FLAG(bool, use_far_branches, false, "Always use far branches");
 
+// For use by LR related macros (e.g. CLOBBERS_LR).
+#define __ this->
+
 namespace compiler {
 
 Assembler::Assembler(ObjectPoolBuilder* object_pool_builder,
@@ -30,14 +33,12 @@
       use_far_branches_(use_far_branches),
       constant_pool_allowed_(false) {
   generate_invoke_write_barrier_wrapper_ = [&](Register reg) {
-    ldr(LR, Address(THR,
-                    target::Thread::write_barrier_wrappers_thread_offset(reg)));
-    blr(LR);
+    Call(Address(THR,
+                 target::Thread::write_barrier_wrappers_thread_offset(reg)));
   };
   generate_invoke_array_write_barrier_ = [&]() {
-    ldr(LR,
+    Call(
         Address(THR, target::Thread::array_write_barrier_entry_point_offset()));
-    blr(LR);
   };
 }
 
@@ -200,7 +201,7 @@
       label->position_ = BindImm19Branch(position, dest);
     }
   }
-  label->BindTo(bound_pc);
+  label->BindTo(bound_pc, lr_state());
 }
 
 static int CountLeadingZeros(uint64_t value, int width) {
@@ -649,14 +650,11 @@
   const intptr_t index =
       object_pool_builder().FindObject(ToObject(target), patchable);
   LoadWordFromPoolIndex(CODE_REG, index);
-  ldr(TMP,
-      FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
-  blr(TMP);
+  Call(FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
 }
 
 void Assembler::BranchLinkToRuntime() {
-  ldr(LR, Address(THR, target::Thread::call_to_runtime_entry_point_offset()));
-  blr(LR);
+  Call(Address(THR, target::Thread::call_to_runtime_entry_point_offset()));
 }
 
 void Assembler::BranchLinkWithEquivalence(const Code& target,
@@ -665,9 +663,7 @@
   const intptr_t index =
       object_pool_builder().FindObject(ToObject(target), equivalence);
   LoadWordFromPoolIndex(CODE_REG, index);
-  ldr(TMP,
-      FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
-  blr(TMP);
+  Call(FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
 }
 
 void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) {
@@ -968,26 +964,25 @@
 void Assembler::StoreIntoObjectOffset(Register object,
                                       int32_t offset,
                                       Register value,
-                                      CanBeSmi value_can_be_smi,
-                                      bool lr_reserved) {
+                                      CanBeSmi value_can_be_smi) {
   if (Address::CanHoldOffset(offset - kHeapObjectTag)) {
     StoreIntoObject(object, FieldAddress(object, offset), value,
-                    value_can_be_smi, lr_reserved);
+                    value_can_be_smi);
   } else {
     AddImmediate(TMP, object, offset - kHeapObjectTag);
-    StoreIntoObject(object, Address(TMP), value, value_can_be_smi, lr_reserved);
+    StoreIntoObject(object, Address(TMP), value, value_can_be_smi);
   }
 }
 
 void Assembler::StoreIntoObject(Register object,
                                 const Address& dest,
                                 Register value,
-                                CanBeSmi can_be_smi,
-                                bool lr_reserved) {
+                                CanBeSmi can_be_smi) {
+  const bool spill_lr = lr_state().LRContainsReturnAddress();
   // x.slot = x. Barrier should have be removed at the IL level.
   ASSERT(object != value);
-  ASSERT(object != LR);
-  ASSERT(value != LR);
+  ASSERT(object != LINK_REGISTER);
+  ASSERT(value != LINK_REGISTER);
   ASSERT(object != TMP);
   ASSERT(object != TMP2);
   ASSERT(value != TMP);
@@ -1001,7 +996,7 @@
   //    in progress
   // If so, call the WriteBarrier stub, which will either add object to the
   // store buffer (case 1) or add value to the marking stack (case 2).
-  // Compare ObjectLayout::StorePointer.
+  // Compare UntaggedObject::StorePointer.
   Label done;
   if (can_be_smi == kValueCanBeSmi) {
     BranchIfSmi(value, &done);
@@ -1011,11 +1006,13 @@
   ldr(TMP2, FieldAddress(value, target::Object::tags_offset(), kByte),
       kUnsignedByte);
   and_(TMP, TMP2,
-       Operand(TMP, LSR, target::ObjectLayout::kBarrierOverlapShift));
+       Operand(TMP, LSR, target::UntaggedObject::kBarrierOverlapShift));
   tst(TMP, Operand(BARRIER_MASK));
   b(&done, ZERO);
 
-  if (!lr_reserved) Push(LR);
+  if (spill_lr) {
+    SPILLS_LR_TO_FRAME(Push(LR));
+  }
   Register objectForCall = object;
   if (value != kWriteBarrierValueReg) {
     // Unlikely. Only non-graph intrinsics.
@@ -1041,15 +1038,17 @@
       PopPair(kWriteBarrierValueReg, objectForCall);
     }
   }
-  if (!lr_reserved) Pop(LR);
+  if (spill_lr) {
+    RESTORES_LR_FROM_FRAME(Pop(LR));
+  }
   Bind(&done);
 }
 
 void Assembler::StoreIntoArray(Register object,
                                Register slot,
                                Register value,
-                               CanBeSmi can_be_smi,
-                               bool lr_reserved) {
+                               CanBeSmi can_be_smi) {
+  const bool spill_lr = lr_state().LRContainsReturnAddress();
   ASSERT(object != TMP);
   ASSERT(object != TMP2);
   ASSERT(value != TMP);
@@ -1065,7 +1064,7 @@
   //    in progress
   // If so, call the WriteBarrier stub, which will either add object to the
   // store buffer (case 1) or add value to the marking stack (case 2).
-  // Compare ObjectLayout::StorePointer.
+  // Compare UntaggedObject::StorePointer.
   Label done;
   if (can_be_smi == kValueCanBeSmi) {
     BranchIfSmi(value, &done);
@@ -1075,11 +1074,12 @@
   ldr(TMP2, FieldAddress(value, target::Object::tags_offset(), kByte),
       kUnsignedByte);
   and_(TMP, TMP2,
-       Operand(TMP, LSR, target::ObjectLayout::kBarrierOverlapShift));
+       Operand(TMP, LSR, target::UntaggedObject::kBarrierOverlapShift));
   tst(TMP, Operand(BARRIER_MASK));
   b(&done, ZERO);
-  if (!lr_reserved) Push(LR);
-
+  if (spill_lr) {
+    SPILLS_LR_TO_FRAME(Push(LR));
+  }
   if ((object != kWriteBarrierObjectReg) || (value != kWriteBarrierValueReg) ||
       (slot != kWriteBarrierSlotReg)) {
     // Spill and shuffle unimplemented. Currently StoreIntoArray is only used
@@ -1088,7 +1088,9 @@
     UNIMPLEMENTED();
   }
   generate_invoke_array_write_barrier_();
-  if (!lr_reserved) Pop(LR);
+  if (spill_lr) {
+    RESTORES_LR_FROM_FRAME(Pop(LR));
+  }
   Bind(&done);
 }
 
@@ -1102,7 +1104,7 @@
 
   ldr(TMP, FieldAddress(object, target::Object::tags_offset(), kByte),
       kUnsignedByte);
-  tsti(TMP, Immediate(1 << target::ObjectLayout::kOldAndNotRememberedBit));
+  tsti(TMP, Immediate(1 << target::UntaggedObject::kOldAndNotRememberedBit));
   b(&done, ZERO);
 
   Stop("Store buffer update is required");
@@ -1154,25 +1156,26 @@
 }
 
 void Assembler::ExtractClassIdFromTags(Register result, Register tags) {
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
-  LsrImmediate(result, tags, target::ObjectLayout::kClassIdTagPos, kFourBytes);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
+  LsrImmediate(result, tags, target::UntaggedObject::kClassIdTagPos,
+               kFourBytes);
 }
 
 void Assembler::ExtractInstanceSizeFromTags(Register result, Register tags) {
-  ASSERT(target::ObjectLayout::kSizeTagPos == 8);
-  ASSERT(target::ObjectLayout::kSizeTagSize == 8);
-  ubfx(result, tags, target::ObjectLayout::kSizeTagPos,
-       target::ObjectLayout::kSizeTagSize);
+  ASSERT(target::UntaggedObject::kSizeTagPos == 8);
+  ASSERT(target::UntaggedObject::kSizeTagSize == 8);
+  ubfx(result, tags, target::UntaggedObject::kSizeTagPos,
+       target::UntaggedObject::kSizeTagSize);
   LslImmediate(result, result, target::ObjectAlignment::kObjectAlignmentLog2);
 }
 
 void Assembler::LoadClassId(Register result, Register object) {
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
   const intptr_t class_id_offset =
       target::Object::tags_offset() +
-      target::ObjectLayout::kClassIdTagPos / kBitsPerByte;
+      target::UntaggedObject::kClassIdTagPos / kBitsPerByte;
   LoadFromOffset(result, object, class_id_offset - kHeapObjectTag,
                  kUnsignedTwoBytes);
 }
@@ -1324,7 +1327,7 @@
 }
 
 void Assembler::EnterFrame(intptr_t frame_size) {
-  PushPair(FP, LR);  // low: FP, high: LR.
+  SPILLS_LR_TO_FRAME(PushPair(FP, LR));  // low: FP, high: LR.
   mov(FP, SP);
 
   if (frame_size > 0) {
@@ -1334,7 +1337,7 @@
 
 void Assembler::LeaveFrame() {
   mov(SP, FP);
-  PopPair(FP, LR);  // low: FP, high: LR.
+  RESTORES_LR_FROM_FRAME(PopPair(FP, LR));  // low: FP, high: LR.
 }
 
 void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) {
@@ -1621,12 +1624,14 @@
 }
 
 void Assembler::EnterCFrame(intptr_t frame_space) {
-  EnterFrame(0);
+  Push(FP);
+  mov(FP, SP);
   ReserveAlignedFrameSpace(frame_space);
 }
 
 void Assembler::LeaveCFrame() {
-  LeaveFrame();
+  mov(SP, FP);
+  Pop(FP);
 }
 
 // R0 receiver, R5 ICData entries array
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 3290499..86a8b3d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1100,7 +1100,12 @@
   }
 
   void b(int32_t offset) { EmitUnconditionalBranchOp(B, offset); }
-  void bl(int32_t offset) { EmitUnconditionalBranchOp(BL, offset); }
+  void bl(int32_t offset) {
+    // CLOBBERS_LR uses __ to access the assembler.
+#define __ this->
+    CLOBBERS_LR(EmitUnconditionalBranchOp(BL, offset));
+#undef __
+  }
 
   // Branches to the given label if the condition holds.
   // [distance] is ignored on ARM.
@@ -1138,8 +1143,21 @@
 
   // Branch, link, return.
   void br(Register rn) { EmitUnconditionalBranchRegOp(BR, rn); }
-  void blr(Register rn) { EmitUnconditionalBranchRegOp(BLR, rn); }
-  void ret(Register rn = R30) { EmitUnconditionalBranchRegOp(RET, rn); }
+  void blr(Register rn) {
+    // CLOBBERS_LR uses __ to access the assembler.
+#define __ this->
+    CLOBBERS_LR(EmitUnconditionalBranchRegOp(BLR, rn));
+#undef __
+  }
+  void ret(Register rn = kNoRegister2) {
+    if (rn == kNoRegister2) {
+      // READS_RETURN_ADDRESS_FROM_LR uses __ to access the assembler.
+#define __ this->
+      READS_RETURN_ADDRESS_FROM_LR(rn = LR);
+#undef __
+    }
+    EmitUnconditionalBranchRegOp(RET, rn);
+  }
 
   // Breakpoint.
   void brk(uint16_t imm) { EmitExceptionGenOp(BRK, imm); }
@@ -1529,8 +1547,13 @@
       CodeEntryKind entry_kind = CodeEntryKind::kNormal);
 
   void Call(Address target) {
-    ldr(LR, target);
-    blr(LR);
+    // CLOBBERS_LR uses __ to access the assembler.
+#define __ this->
+    CLOBBERS_LR({
+      ldr(LR, target);
+      blr(LR);
+    });
+#undef __
   }
   void Call(const Code& code) { BranchLink(code); }
 
@@ -1632,19 +1655,16 @@
   void StoreIntoObject(Register object,
                        const Address& dest,
                        Register value,
-                       CanBeSmi can_value_be_smi = kValueCanBeSmi,
-                       bool lr_reserved = false);
+                       CanBeSmi can_value_be_smi = kValueCanBeSmi);
   void StoreIntoArray(Register object,
                       Register slot,
                       Register value,
-                      CanBeSmi can_value_be_smi = kValueCanBeSmi,
-                      bool lr_reserved = false);
+                      CanBeSmi can_value_be_smi = kValueCanBeSmi);
 
   void StoreIntoObjectOffset(Register object,
                              int32_t offset,
                              Register value,
-                             CanBeSmi can_value_be_smi = kValueCanBeSmi,
-                             bool lr_reserved = false);
+                             CanBeSmi can_value_be_smi = kValueCanBeSmi);
   void StoreIntoObjectNoBarrier(Register object,
                                 const Address& dest,
                                 Register value);
@@ -1669,6 +1689,9 @@
   bool constant_pool_allowed() const { return constant_pool_allowed_; }
   void set_constant_pool_allowed(bool b) { constant_pool_allowed_ = b; }
 
+  compiler::LRState lr_state() const { return lr_state_; }
+  void set_lr_state(compiler::LRState state) { lr_state_ = state; }
+
   intptr_t FindImmediate(int64_t imm);
   bool CanLoadFromObjectPool(const Object& object) const;
   void LoadNativeEntry(Register dst,
@@ -1728,7 +1751,7 @@
 
   void EnterFrame(intptr_t frame_size);
   void LeaveFrame();
-  void Ret() { ret(LR); }
+  void Ret() { ret(); }
 
   // Emit code to transition between generated mode and native mode.
   //
@@ -1847,7 +1870,7 @@
   // the code can be used.
   //
   // The neccessary information for the "linker" (i.e. the relocation
-  // information) is stored in [CodeLayout::static_calls_target_table_]: an
+  // information) is stored in [UntaggedCode::static_calls_target_table_]: an
   // entry of the form
   //
   //   (Code::kPcRelativeCall & pc_offset, <target-code>, <target-function>)
@@ -1931,6 +1954,8 @@
 
   bool constant_pool_allowed_;
 
+  compiler::LRState lr_state_ = compiler::LRState::OnEntry();
+
   void LoadWordFromPoolIndexFixed(Register dst, intptr_t index);
 
   // Note: the function never clobbers TMP, TMP2 scratch registers.
@@ -2212,6 +2237,7 @@
       } else {
         EmitConditionalBranchOp(op, cond, dest);
       }
+      label->UpdateLRState(lr_state());
     } else {
       const int64_t position = buffer_.Size();
       if (use_far_branches()) {
@@ -2224,7 +2250,7 @@
       } else {
         EmitConditionalBranchOp(op, cond, label->position_);
       }
-      label->LinkTo(position);
+      label->LinkTo(position, lr_state());
     }
   }
 
@@ -2244,6 +2270,7 @@
       } else {
         EmitCompareAndBranchOp(op, rt, dest, sz);
       }
+      label->UpdateLRState(lr_state());
     } else {
       const int64_t position = buffer_.Size();
       if (use_far_branches()) {
@@ -2253,7 +2280,7 @@
       } else {
         EmitCompareAndBranchOp(op, rt, label->position_, sz);
       }
-      label->LinkTo(position);
+      label->LinkTo(position, lr_state());
     }
   }
 
@@ -2273,6 +2300,7 @@
       } else {
         EmitTestAndBranchOp(op, rt, bit_number, dest);
       }
+      label->UpdateLRState(lr_state());
     } else {
       int64_t position = buffer_.Size();
       if (use_far_branches()) {
@@ -2282,7 +2310,7 @@
       } else {
         EmitTestAndBranchOp(op, rt, bit_number, label->position_);
       }
-      label->LinkTo(position);
+      label->LinkTo(position, lr_state());
     }
   }
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index 8cf9ac2..c6d8847 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -1901,11 +1901,12 @@
 
 ASSEMBLER_TEST_GENERATE(AdrBlr, assembler) {
   __ movz(R0, Immediate(123), 0);
-  __ add(R3, ZR, Operand(LR));  // Save LR.
+  SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(
+      __ add(R3, ZR, Operand(LR)));  // Save LR.
   // R1 <- PC + 4*Instr::kInstrSize
   __ adr(R1, Immediate(4 * Instr::kInstrSize));
   __ blr(R1);
-  __ add(LR, ZR, Operand(R3));
+  RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(__ add(LR, ZR, Operand(R3)));
   __ ret();
 
   // blr goes here.
@@ -2642,7 +2643,7 @@
 }
 
 ASSEMBLER_TEST_RUN(CompareObjectNull, test) {
-  EXPECT_EQ(static_cast<uword>(Bool::True().raw()),
+  EXPECT_EQ(static_cast<uword>(Bool::True().ptr()),
             test->InvokeWithCodeAndThread<uword>());
 }
 
@@ -2656,7 +2657,7 @@
 }
 
 ASSEMBLER_TEST_RUN(LoadObjectTrue, test) {
-  EXPECT_EQ(static_cast<uword>(Bool::True().raw()),
+  EXPECT_EQ(static_cast<uword>(Bool::True().ptr()),
             test->InvokeWithCodeAndThread<uword>());
 }
 
@@ -2670,7 +2671,7 @@
 }
 
 ASSEMBLER_TEST_RUN(LoadObjectFalse, test) {
-  EXPECT_EQ(static_cast<uword>(Bool::False().raw()),
+  EXPECT_EQ(static_cast<uword>(Bool::False().ptr()),
             test->InvokeWithCodeAndThread<uword>());
 }
 
@@ -4604,12 +4605,12 @@
   __ Push(CODE_REG);
   __ Push(THR);
   __ Push(BARRIER_MASK);
-  __ Push(LR);
+  SPILLS_LR_TO_FRAME(__ Push(LR));
   __ mov(THR, R2);
   __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
   __ StoreIntoObject(R1, FieldAddress(R1, GrowableObjectArray::data_offset()),
                      R0);
-  __ Pop(LR);
+  RESTORES_LR_FROM_FRAME(__ Pop(LR));
   __ Pop(BARRIER_MASK);
   __ Pop(THR);
   __ Pop(CODE_REG);
diff --git a/runtime/vm/compiler/assembler/assembler_arm_test.cc b/runtime/vm/compiler/assembler/assembler_arm_test.cc
index 9199d5a..0addf7b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm_test.cc
@@ -66,7 +66,7 @@
 
 ASSEMBLER_TEST_GENERATE(Simple, assembler) {
   __ mov(R0, Operand(42));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Simple, test) {
@@ -76,7 +76,7 @@
 
 ASSEMBLER_TEST_GENERATE(MoveNegated, assembler) {
   __ mvn(R0, Operand(42));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(MoveNegated, test) {
@@ -91,7 +91,7 @@
   __ mov(R0, o);
   EXPECT(Operand::CanHold(0x30000003, &o));
   __ add(R0, R0, o);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(MoveRotImm, test) {
@@ -102,7 +102,7 @@
 
 ASSEMBLER_TEST_GENERATE(MovImm16, assembler) {
   __ LoadPatchableImmediate(R0, 0x12345678);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(MovImm16, test) {
@@ -116,7 +116,7 @@
   __ cmp(R0, Operand(0));
   __ LoadImmediate(R0, 0x12345678, EQ);
   __ LoadImmediate(R0, 0x87654321, NE);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(LoadImmediate, test) {
@@ -128,7 +128,7 @@
 ASSEMBLER_TEST_GENERATE(LoadHalfWordUnaligned, assembler) {
   __ LoadHalfWordUnaligned(R1, R0, TMP);
   __ mov(R0, Operand(R1));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(LoadHalfWordUnaligned, test) {
@@ -151,7 +151,7 @@
 ASSEMBLER_TEST_GENERATE(LoadHalfWordUnsignedUnaligned, assembler) {
   __ LoadHalfWordUnsignedUnaligned(R1, R0, TMP);
   __ mov(R0, Operand(R1));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(LoadHalfWordUnsignedUnaligned, test) {
@@ -173,7 +173,7 @@
   __ LoadImmediate(R1, 0xABCD);
   __ StoreWordUnaligned(R1, R0, TMP);
   __ mov(R0, Operand(R1));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(StoreHalfWordUnaligned, test) {
@@ -201,7 +201,7 @@
 ASSEMBLER_TEST_GENERATE(LoadWordUnaligned, assembler) {
   __ LoadWordUnaligned(R1, R0, TMP);
   __ mov(R0, Operand(R1));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(LoadWordUnaligned, test) {
@@ -231,7 +231,7 @@
   __ LoadImmediate(R1, 0x12345678);
   __ StoreWordUnaligned(R1, R0, TMP);
   __ mov(R0, Operand(R1));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(StoreWordUnaligned, test) {
@@ -286,7 +286,7 @@
     __ vmovrrd(R0, R1, D3);       // R0:R1 = D3, R0:R1 == 41:43
     __ sub(R0, R1, Operand(R0));  // 43-41
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmov, test) {
@@ -307,7 +307,7 @@
     __ vstrs(S0, Address(R2, (-target::kWordSize * 30)));
     __ ldr(R0, Address(SP, (target::kWordSize * 30), Address::PostIndex));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SingleVLoadStore, test) {
@@ -334,7 +334,7 @@
     // as:
     __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SingleVShiftLoadStore, test) {
@@ -360,7 +360,7 @@
     __ ldr(R1, Address(R2, (-target::kWordSize * 29)));
     __ ldr(R0, Address(SP, (target::kWordSize * 30), Address::PostIndex));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleVLoadStore, test) {
@@ -384,7 +384,7 @@
     __ vdivs(S0, S0, S1);  // 14.7f
     __ vsqrts(S0, S0);     // 3.8340579f
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SingleFPOperations, test) {
@@ -408,7 +408,7 @@
     __ vdivd(D0, D0, D1);  // 14.7
     __ vsqrtd(D0, D0);     // 3.8340579
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleFPOperations, test) {
@@ -447,7 +447,7 @@
     __ vmovsr(S3, R3);
     __ vcvtdi(D0, S3);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(IntToDoubleConversion, test) {
@@ -472,7 +472,7 @@
     __ LoadDImmediate(D2, 1.0 * (1LL << 32), R0);
     __ vmlad(D0, D1, D2);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(LongToDoubleConversion, test) {
@@ -491,7 +491,7 @@
     __ vmovsr(S3, R3);
     __ vcvtsi(S0, S3);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(IntToFloatConversion, test) {
@@ -509,7 +509,7 @@
     __ vcvtis(S1, S0);
     __ vmovrs(R0, S1);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(FloatToIntConversion, test) {
@@ -530,7 +530,7 @@
     __ vcvtid(S0, D0);
     __ vmovrs(R0, S0);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleToIntConversion, test) {
@@ -551,7 +551,7 @@
     __ LoadSImmediate(S2, 12.8f);
     __ vcvtds(D0, S2);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(FloatToDoubleConversion, test) {
@@ -569,7 +569,7 @@
     __ LoadDImmediate(D1, 12.8, R0);
     __ vcvtsd(S0, D1);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleToFloatConversion, test) {
@@ -607,7 +607,7 @@
     __ add(R0, R0, Operand(16), VC);
   }
   // R0 is 0 if all tests passed.
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(FloatCompare, test) {
@@ -643,7 +643,7 @@
     __ add(R0, R0, Operand(16), VC);
   }
   // R0 is 0 if all tests passed.
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(DoubleCompare, test) {
@@ -662,7 +662,7 @@
   __ mov(R0, Operand(R0, LSL, 1));
   __ movs(R1, Operand(R1, LSR, 1));
   __ b(&loop_entry, NE);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Loop, test) {
@@ -677,7 +677,7 @@
   __ b(&skip);
   __ mov(R0, Operand(11));
   __ Bind(&skip);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(ForwardBranch, test) {
@@ -695,7 +695,7 @@
   __ mov(R0, Operand(R0, LSL, 1));
   __ movs(R1, Operand(R1, LSR, 1));
   __ b(&loop_entry, NE);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Loop2, test) {
@@ -716,7 +716,7 @@
   __ mov(R0, Operand(R0, LSL, 1));
   __ movs(R1, Operand(R1, LSR, 1));
   __ b(&loop_entry, NE);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Loop3, test) {
@@ -729,7 +729,7 @@
   __ mov(R1, Operand(123));
   __ Push(R1);
   __ Pop(R0);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(LoadStore, test) {
@@ -744,7 +744,7 @@
   __ PushRegisterPair(R2, R3);
   __ Pop(R0);
   __ Pop(R1);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(PushRegisterPair, test) {
@@ -759,7 +759,7 @@
   __ PushRegisterPair(R3, R2);
   __ Pop(R0);
   __ Pop(R1);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(PushRegisterPairReversed, test) {
@@ -775,7 +775,7 @@
   __ Push(R3);
   __ Push(R2);
   __ PopRegisterPair(R0, R1);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(PopRegisterPair, test) {
@@ -790,7 +790,7 @@
   __ Push(R3);
   __ Push(R2);
   __ PopRegisterPair(R1, R0);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(PopRegisterPairReversed, test) {
@@ -811,7 +811,7 @@
   __ tst(IP, Operand(0));
   __ b(&retry, NE);  // NE if context switch occurred between ldrex and strex.
   __ Pop(R0);        // 42
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Semaphore, test) {
@@ -829,7 +829,7 @@
   __ strex(IP, R1, SP);  // IP == 1, failure
   __ Pop(R0);            // 40
   __ add(R0, R0, Operand(IP));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(FailedSemaphore, test) {
@@ -844,7 +844,7 @@
   __ add(R0, R1, Operand(4));
   __ rsbs(R0, R0, Operand(100));
   __ rsc(R0, R0, Operand(100));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddSub, test) {
@@ -859,7 +859,7 @@
   __ mov(R0, Operand(0));
   __ adds(R2, R2, Operand(R1));
   __ adcs(R0, R0, Operand(R0));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddCarry, test) {
@@ -875,7 +875,7 @@
   __ adds(IP, R2, Operand(R1));  // c_out = 1.
   __ adcs(IP, R2, Operand(R0));  // c_in = 1, c_out = 1.
   __ adc(R0, R0, Operand(R0));   // c_in = 1.
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddCarryInOut, test) {
@@ -890,7 +890,7 @@
   __ mov(R0, Operand(0));
   __ subs(R2, R2, Operand(R1));
   __ sbcs(R0, R0, Operand(R0));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SubCarry, test) {
@@ -905,7 +905,7 @@
   __ subs(IP, R0, Operand(R1));  // c_out = 1.
   __ sbcs(IP, R0, Operand(R0));  // c_in = 1, c_out = 1.
   __ sbc(R0, R0, Operand(R0));   // c_in = 1.
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SubCarryInOut, test) {
@@ -920,7 +920,7 @@
   __ adds(IP, R0, Operand(1));  // c_out = 1.
   __ adcs(IP, R1, Operand(0));  // c_in = 1, c_out = 1, v = 1.
   __ mov(R0, Operand(1), VS);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Overflow, test) {
@@ -935,7 +935,7 @@
   __ and_(R1, R2, Operand(R1));
   __ mov(R3, Operand(42));
   __ orr(R0, R1, Operand(R3));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AndOrr, test) {
@@ -948,11 +948,11 @@
   __ mov(R0, Operand(0));
   __ tst(R0, Operand(R1));      // Set zero-flag.
   __ orrs(R0, R0, Operand(1));  // Clear zero-flag.
-  __ bx(LR, EQ);
+  __ Ret(EQ);
   __ mov(R0, Operand(42));
-  __ bx(LR, NE);  // Only this return should fire.
+  __ Ret(NE);  // Only this return should fire.
   __ mov(R0, Operand(2));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Orrs, test) {
@@ -966,7 +966,7 @@
   __ mov(R2, Operand(40));
   __ mul(R3, R2, R1);
   __ mov(R0, Operand(R3));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Multiply, test) {
@@ -986,7 +986,7 @@
     __ vmovrs(R1, S0);       // r1 = r0/r2
     __ mls(R0, R1, R2, R0);  // r0 = r0 - r1*r2
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(QuotientRemainder, test) {
@@ -1008,7 +1008,7 @@
   __ mla(R2, IP, R3, R4);
   __ add(R1, R2, Operand(R1));
   __ Pop(R4);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Multiply64To64, test) {
@@ -1021,7 +1021,7 @@
 
 ASSEMBLER_TEST_GENERATE(Multiply32To64, assembler) {
   __ smull(R0, R1, R0, R2);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Multiply32To64, test) {
@@ -1034,7 +1034,7 @@
 
 ASSEMBLER_TEST_GENERATE(MultiplyAccumAccum32To64, assembler) {
   __ umaal(R0, R1, R2, R3);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(MultiplyAccumAccum32To64, test) {
@@ -1066,10 +1066,10 @@
   __ cmp(R1, Operand(3));
   __ b(&error, NE);
   __ mov(R0, Operand(0));
-  __ bx(LR);
+  __ Ret();
   __ Bind(&error);
   __ mov(R0, Operand(1));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Clz, test) {
@@ -1081,7 +1081,7 @@
 ASSEMBLER_TEST_GENERATE(Rbit, assembler) {
   __ mov(R0, Operand(0x15));
   __ rbit(R0, R0);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Rbit, test) {
@@ -1100,7 +1100,7 @@
   __ b(&skip, NE);
   __ mov(R0, Operand(0));
   __ Bind(&skip);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Tst, test) {
@@ -1116,7 +1116,7 @@
   __ mov(R0, Operand(R0, LSL, 1));
   __ mov(R1, Operand(1));
   __ mov(R0, Operand(R0, LSL, R1));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Lsl, test) {
@@ -1132,7 +1132,7 @@
   __ mov(R0, Operand(R0, LSR, 1));
   __ mov(R1, Operand(1));
   __ mov(R0, Operand(R0, LSR, R1));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Lsr, test) {
@@ -1147,7 +1147,7 @@
   __ mov(R0, Operand(1));
   __ Lsl(R0, R0, Operand(31));
   __ Lsr(R0, R0, Operand(31));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Lsr1, test) {
@@ -1162,7 +1162,7 @@
   __ mov(R0, Operand(1));
   __ Lsl(R0, R0, Operand(31));
   __ Asr(R0, R0, Operand(31));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Asr1, test) {
@@ -1174,7 +1174,7 @@
 ASSEMBLER_TEST_GENERATE(Rsb, assembler) {
   __ mov(R3, Operand(10));
   __ rsb(R0, R3, Operand(42));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Rsb, test) {
@@ -1218,7 +1218,7 @@
   __ mov(R0, Operand(0));
   __ Bind(&Done);
   __ ldr(R1, Address(SP, (target::kWordSize * 30), Address::PostIndex));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Ldrh, test) {
@@ -1233,7 +1233,7 @@
   __ str(R1, Address(SP, (-target::kWordSize * 30), Address::PreIndex));
   __ ldrsb(R0, Address(R2, (-target::kWordSize * 30)));
   __ ldr(R1, Address(SP, (target::kWordSize * 30), Address::PostIndex));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Ldrsb, test) {
@@ -1248,7 +1248,7 @@
   __ str(R1, Address(SP, (-target::kWordSize * 30), Address::PreIndex));
   __ ldrb(R0, Address(R2, (-target::kWordSize * 30)));
   __ ldr(R1, Address(SP, (target::kWordSize * 30), Address::PostIndex));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Ldrb, test) {
@@ -1263,7 +1263,7 @@
   __ str(R1, Address(SP, (-target::kWordSize * 30), Address::PreIndex));
   __ ldrsh(R0, Address(R2, (-target::kWordSize * 30)));
   __ ldr(R1, Address(SP, (target::kWordSize * 30), Address::PostIndex));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Ldrsh, test) {
@@ -1278,7 +1278,7 @@
   __ str(R1, Address(SP, (-target::kWordSize * 30), Address::PreIndex));
   __ ldrh(R0, Address(R2, (-target::kWordSize * 30)));
   __ ldr(R1, Address(SP, (target::kWordSize * 30), Address::PostIndex));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Ldrh1, test) {
@@ -1297,7 +1297,7 @@
   __ add(SP, SP, Operand(target::kWordSize * 30));
   __ sub(R0, R0, Operand(R2));
   __ add(R1, R1, Operand(R3));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Ldrd, test) {
@@ -1340,7 +1340,7 @@
   __ Pop(R9);                   // Restore R9.
   __ Pop(R9);                   // Restore R9.
   __ Pop(R9);                   // Restore R9.
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Ldm_stm_da, test) {
@@ -1354,7 +1354,7 @@
   __ mov(R1, Operand(target::kWordSize));
   __ str(R2, Address(SP, R1, LSL, 1, Address::NegOffset));
   __ ldr(R0, Address(SP, (-target::kWordSize * 2), Address::Offset));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddressShiftStrLSL1NegOffset, test) {
@@ -1368,7 +1368,7 @@
   __ mov(R1, Operand(target::kWordSize));
   __ str(R2, Address(SP, (-target::kWordSize * 32), Address::Offset));
   __ ldr(R0, Address(SP, R1, LSL, 5, Address::NegOffset));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddressShiftLdrLSL5NegOffset, test) {
@@ -1382,7 +1382,7 @@
   __ mov(R1, Operand(target::kWordSize * 2));
   __ str(R2, Address(SP, R1, LSR, 1, Address::NegOffset));
   __ ldr(R0, Address(SP, -target::kWordSize, Address::Offset));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddressShiftStrLRS1NegOffset, test) {
@@ -1396,7 +1396,7 @@
   __ mov(R1, Operand(target::kWordSize * 2));
   __ str(R2, Address(SP, -target::kWordSize, Address::Offset));
   __ ldr(R0, Address(SP, R1, LSR, 1, Address::NegOffset));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddressShiftLdrLRS1NegOffset, test) {
@@ -1412,7 +1412,7 @@
   __ str(R2, Address(SP, R1, LSL, 5, Address::NegPreIndex));
   __ ldr(R0, Address(R3, (-target::kWordSize * 32), Address::Offset));
   __ mov(SP, Operand(R3));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddressShiftStrLSLNegPreIndex, test) {
@@ -1426,7 +1426,7 @@
   __ mov(R1, Operand(target::kWordSize));
   __ str(R2, Address(SP, (-target::kWordSize * 32), Address::PreIndex));
   __ ldr(R0, Address(SP, R1, LSL, 5, Address::PostIndex));
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(AddressShiftLdrLSLNegPreIndex, test) {
@@ -1478,7 +1478,7 @@
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmdVldmd, test) {
@@ -1532,7 +1532,7 @@
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmsVldms, test) {
@@ -1584,7 +1584,7 @@
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure into R0 if NE
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmdVldmd1, test) {
@@ -1636,7 +1636,7 @@
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmsVldms1, test) {
@@ -1698,7 +1698,7 @@
     // Restore used callee-saved FPU registers.
     __ vldmd(IA_W, SP, D8, 3);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmdVldmd_off, test) {
@@ -1754,7 +1754,7 @@
     __ vmstat();
     __ mov(R0, Operand(0), NE);  // Put failure value into R0 if NE
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VstmsVldms_off, test) {
@@ -1772,7 +1772,7 @@
     __ udiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Udiv, test) {
@@ -1790,7 +1790,7 @@
     __ sdiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Sdiv, test) {
@@ -1808,7 +1808,7 @@
     __ udiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Udiv_zero, test) {
@@ -1826,7 +1826,7 @@
     __ sdiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Sdiv_zero, test) {
@@ -1844,7 +1844,7 @@
     __ udiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Udiv_corner, test) {
@@ -1862,7 +1862,7 @@
     __ sdiv(R2, R0, R1);
     __ mov(R0, Operand(R2));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Sdiv_corner, test) {
@@ -1882,14 +1882,14 @@
   __ mov(R1, Operand(9));
   __ IntegerDivide(R0, R0, R1, D0, D1);
   HostCPUFeatures::set_integer_division_supported(orig);
-  __ bx(LR);
+  __ Ret();
 #else
   if (TargetCPUFeatures::can_divide()) {
     __ mov(R0, Operand(27));
     __ mov(R1, Operand(9));
     __ IntegerDivide(R0, R0, R1, D0, D1);
   }
-  __ bx(LR);
+  __ Ret();
 #endif
 }
 
@@ -1921,14 +1921,14 @@
     __ IntegerDivide(R0, R0, R1, D0, D1);
     HostCPUFeatures::set_integer_division_supported(orig);
   }
-  __ bx(LR);
+  __ Ret();
 #else
   if (TargetCPUFeatures::can_divide()) {
     __ mov(R0, Operand(27));
     __ mov(R1, Operand(9));
     __ IntegerDivide(R0, R0, R1, D0, D1);
   }
-  __ bx(LR);
+  __ Ret();
 #endif
 }
 
@@ -1955,7 +1955,7 @@
   __ LoadImmediate(R1, -9);
   __ muls(R2, R0, R1);
   __ mov(R0, Operand(42), MI);
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Muls, test) {
@@ -1994,7 +1994,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vaddqi8, test) {
@@ -2035,7 +2035,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vaddqi16, test) {
@@ -2076,7 +2076,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vaddqi32, test) {
@@ -2105,7 +2105,7 @@
 
     __ add(R0, R0, Operand(R2));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vaddqi64, test) {
@@ -2140,7 +2140,7 @@
     __ LoadImmediate(R0, 1);
     __ Bind(&fail);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vshlqu64, test) {
@@ -2175,7 +2175,7 @@
     __ LoadImmediate(R0, 1);
     __ Bind(&fail);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vshlqi64, test) {
@@ -2225,12 +2225,12 @@
     __ b(&fail, NE);
 
     __ LoadImmediate(R0, 1);
-    __ bx(LR);
+    __ Ret();
 
     __ Bind(&fail);
     __ LoadImmediate(R0, 0);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Mint_shl_ok, test) {
@@ -2280,12 +2280,12 @@
     __ b(&fail, NE);
 
     __ LoadImmediate(R0, 0);
-    __ bx(LR);
+    __ Ret();
 
     __ Bind(&fail);
     __ LoadImmediate(R0, 1);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Mint_shl_overflow, test) {
@@ -2326,7 +2326,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vsubqi8, test) {
@@ -2367,7 +2367,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vsubqi16, test) {
@@ -2408,7 +2408,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vsubqi32, test) {
@@ -2437,7 +2437,7 @@
 
     __ add(R0, R0, Operand(R2));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vsubqi64, test) {
@@ -2478,7 +2478,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmulqi8, test) {
@@ -2519,7 +2519,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmulqi16, test) {
@@ -2560,7 +2560,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmulqi32, test) {
@@ -2591,7 +2591,7 @@
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vaddqs, test) {
@@ -2622,7 +2622,7 @@
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vsubqs, test) {
@@ -2653,7 +2653,7 @@
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmulqs, test) {
@@ -2688,12 +2688,12 @@
 
     __ LoadImmediate(R0, 0);
     __ CompareImmediate(R2, 1);
-    __ bx(LR, NE);
+    __ Ret(NE);
     __ CompareImmediate(R3, 1);
-    __ bx(LR, NE);
+    __ Ret(NE);
     __ LoadImmediate(R0, 42);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VtblX, test) {
@@ -2728,12 +2728,12 @@
 
     __ LoadImmediate(R0, 0);
     __ CompareImmediate(R2, 1);
-    __ bx(LR, NE);
+    __ Ret(NE);
     __ CompareImmediate(R3, 1);
-    __ bx(LR, NE);
+    __ Ret(NE);
     __ LoadImmediate(R0, 42);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VtblY, test) {
@@ -2768,12 +2768,12 @@
 
     __ LoadImmediate(R0, 0);
     __ CompareImmediate(R2, 1);
-    __ bx(LR, NE);
+    __ Ret(NE);
     __ CompareImmediate(R3, 1);
-    __ bx(LR, NE);
+    __ Ret(NE);
     __ LoadImmediate(R0, 42);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VtblZ, test) {
@@ -2808,12 +2808,12 @@
 
     __ LoadImmediate(R0, 0);
     __ CompareImmediate(R2, 1);
-    __ bx(LR, NE);
+    __ Ret(NE);
     __ CompareImmediate(R3, 1);
-    __ bx(LR, NE);
+    __ Ret(NE);
     __ LoadImmediate(R0, 42);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(VtblW, test) {
@@ -2852,7 +2852,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Veorq, test) {
@@ -2891,7 +2891,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vornq, test) {
@@ -2930,7 +2930,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vorrq, test) {
@@ -2969,7 +2969,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vandq, test) {
@@ -3003,7 +3003,7 @@
     __ vcvtis(S0, S4);
     __ vmovrs(R0, S0);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmovq, test) {
@@ -3022,7 +3022,7 @@
     __ vmvnq(Q2, Q1);          // Q2 <- ~Q1.
     __ vmovrs(R0, S10);        // Now R0 should be 42 again.
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmvnq, test) {
@@ -3052,7 +3052,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vdupb, test) {
@@ -3082,7 +3082,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vduph, test) {
@@ -3112,7 +3112,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vdupw, test) {
@@ -3142,7 +3142,7 @@
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vzipqw, test) {
@@ -3184,7 +3184,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vceqqi32, test) {
@@ -3217,7 +3217,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vceqqs, test) {
@@ -3258,7 +3258,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vcgeqi32, test) {
@@ -3299,7 +3299,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vcugeqi32, test) {
@@ -3332,7 +3332,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vcgeqs, test) {
@@ -3373,7 +3373,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vcgtqi32, test) {
@@ -3414,7 +3414,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vcugtqi32, test) {
@@ -3447,7 +3447,7 @@
     __ add(R0, R0, Operand(R2));
     __ add(R0, R0, Operand(R3));
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vcgtqs, test) {
@@ -3479,7 +3479,7 @@
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vminqs, test) {
@@ -3511,7 +3511,7 @@
     __ vcvtis(S0, S8);
     __ vmovrs(R0, S0);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vmaxqs, test) {
@@ -3530,7 +3530,7 @@
     __ vmovs(S7, S4);
     __ vrecpeqs(Q0, Q1);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vrecpeqs, test) {
@@ -3556,7 +3556,7 @@
 
     __ vrecpsqs(Q0, Q1, Q2);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vrecpsqs, test) {
@@ -3583,7 +3583,7 @@
     __ vrecpsqs(Q2, Q1, Q0);
     __ vmulqs(Q0, Q0, Q2);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Reciprocal, test) {
@@ -3604,7 +3604,7 @@
 
     __ vrsqrteqs(Q0, Q1);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vrsqrteqs, test) {
@@ -3630,7 +3630,7 @@
 
     __ vrsqrtsqs(Q0, Q1, Q2);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vrsqrtsqs, test) {
@@ -3661,7 +3661,7 @@
     __ vrsqrtsqs(Q2, Q1, Q2);
     __ vmulqs(Q0, Q0, Q2);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(ReciprocalSqrt, test) {
@@ -3702,7 +3702,7 @@
     __ vrecpsqs(Q2, Q1, Q0);
     __ vmulqs(Q0, Q0, Q2);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SIMDSqrt, test) {
@@ -3747,7 +3747,7 @@
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SIMDSqrt2, test) {
@@ -3784,7 +3784,7 @@
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(SIMDDiv, test) {
@@ -3809,7 +3809,7 @@
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vabsqs, test) {
@@ -3834,7 +3834,7 @@
     __ vadds(S0, S0, S2);
     __ vadds(S0, S0, S3);
   }
-  __ bx(LR);
+  __ Ret();
 }
 
 ASSEMBLER_TEST_RUN(Vnegqs, test) {
@@ -3852,11 +3852,11 @@
 // R1: growable array.
 // R2: current thread.
 ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
-  __ PushList((1 << LR) | (1 << THR));
+  SPILLS_LR_TO_FRAME(__ PushList((1 << LR) | (1 << THR)));
   __ mov(THR, Operand(R2));
   __ StoreIntoObject(R1, FieldAddress(R1, GrowableObjectArray::data_offset()),
                      R0);
-  __ PopList((1 << LR) | (1 << THR));
+  RESTORES_LR_FROM_FRAME(__ PopList((1 << LR) | (1 << THR)));
   __ Ret();
 }
 
diff --git a/runtime/vm/compiler/assembler/assembler_base.cc b/runtime/vm/compiler/assembler/assembler_base.cc
index 96d98a1..7034652 100644
--- a/runtime/vm/compiler/assembler/assembler_base.cc
+++ b/runtime/vm/compiler/assembler/assembler_base.cc
@@ -327,6 +327,7 @@
     if (parent_ != nullptr) {
       const intptr_t idx = parent_->object_pool_index_table_.LookupValue(entry);
       if (idx != ObjIndexPair::kNoIndex) {
+        used_from_parent_.Add(idx);
         return idx;
       }
     }
diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h
index d240da5..a650f43 100644
--- a/runtime/vm/compiler/assembler/assembler_base.h
+++ b/runtime/vm/compiler/assembler/assembler_base.h
@@ -28,6 +28,152 @@
 
 namespace compiler {
 
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+// On ARM and ARM64 branch-link family of instructions puts return address
+// into a dedicated register (LR), which called code will then preserve
+// manually if needed. To ensure that LR is not clobbered accidentally we
+// discourage direct use of the register and instead require users to wrap
+// their code in one of the macroses below, which would verify that it is
+// safe to modify LR.
+// We use RELEASE_ASSERT instead of ASSERT because we use LR state (tracked
+// by the assembler) to generate different code sequences for write barriers
+// so we would like to ensure that incorrect code will trigger an assertion
+// instead of producing incorrect code.
+
+// Class representing the state of LR register. In addition to tracking
+// whether LR currently contain return address or not it also tracks
+// entered frames - and whether they preserved a return address or not.
+class LRState {
+ public:
+  LRState(const LRState&) = default;
+  LRState& operator=(const LRState&) = default;
+
+  bool LRContainsReturnAddress() const {
+    RELEASE_ASSERT(!IsUnknown());
+    return (state_ & kLRContainsReturnAddressMask) != 0;
+  }
+
+  LRState SetLRContainsReturnAddress(bool v) const {
+    RELEASE_ASSERT(!IsUnknown());
+    return LRState(frames_, v ? (state_ | 1) : (state_ & ~1));
+  }
+
+  // Returns a |LRState| representing a state after pushing current value
+  // of LR on the stack. LR is assumed clobberable in the new state.
+  LRState EnterFrame() const {
+    RELEASE_ASSERT(!IsUnknown());
+    // 1 bit is used for LR state the rest for frame states.
+    constexpr auto kMaxFrames = (sizeof(state_) * kBitsPerByte) - 1;
+    RELEASE_ASSERT(frames_ < kMaxFrames);
+    // LSB will be clear after the shift meaning that LR can be clobbered.
+    return LRState(frames_ + 1, state_ << 1);
+  }
+
+  // Returns a |LRState| representing a state after popping  LR from the stack.
+  // Note that for inner frames LR would usually be assumed cloberrable
+  // even after leaving a frame. Only outerframe would restore return address
+  // into LR.
+  LRState LeaveFrame() const {
+    RELEASE_ASSERT(!IsUnknown());
+    RELEASE_ASSERT(frames_ > 0);
+    return LRState(frames_ - 1, state_ >> 1);
+  }
+
+  bool IsUnknown() const { return *this == Unknown(); }
+
+  static LRState Unknown() { return LRState(kUnknownMarker, kUnknownMarker); }
+
+  static LRState OnEntry() { return LRState(0, 1); }
+
+  static LRState Clobbered() { return LRState(0, 0); }
+
+  bool operator==(const LRState& other) const {
+    return frames_ == other.frames_ && state_ == other.state_;
+  }
+
+ private:
+  LRState(uint8_t frames, uint8_t state) : frames_(frames), state_(state) {}
+
+  // LR state is encoded in the LSB of state_ bitvector.
+  static constexpr uint8_t kLRContainsReturnAddressMask = 1;
+
+  static constexpr uint8_t kUnknownMarker = 0xFF;
+
+  // Number of frames on the stack or kUnknownMarker when representing
+  // Unknown state.
+  uint8_t frames_ = 0;
+
+  // Bit vector with frames_ + 1 bits: LSB represents LR state, other bits
+  // represent state of LR in each entered frame. Normally this value would
+  // just be (1 << frames_).
+  uint8_t state_ = 1;
+};
+
+// READS_RETURN_ADDRESS_FROM_LR(...) macro verifies that LR contains return
+// address before allowing to use it.
+#define READS_RETURN_ADDRESS_FROM_LR(block)                                    \
+  do {                                                                         \
+    RELEASE_ASSERT(__ lr_state().LRContainsReturnAddress());                   \
+    constexpr Register LR = LR_DO_NOT_USE_DIRECTLY;                            \
+    USE(LR);                                                                   \
+    block;                                                                     \
+  } while (0)
+
+// WRITES_RETURN_ADDRESS_TO_LR(...) macro verifies that LR contains return
+// address before allowing to write into it. LR is considered to still
+// contain return address after this operation.
+#define WRITES_RETURN_ADDRESS_TO_LR(block) READS_RETURN_ADDRESS_FROM_LR(block)
+
+// CLOBBERS_LR(...) checks that LR does *not* contain return address and it is
+// safe to clobber it.
+#define CLOBBERS_LR(block)                                                     \
+  do {                                                                         \
+    RELEASE_ASSERT(!(__ lr_state().LRContainsReturnAddress()));                \
+    constexpr Register LR = LR_DO_NOT_USE_DIRECTLY;                            \
+    USE(LR);                                                                   \
+    block;                                                                     \
+  } while (0)
+
+// SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(...) checks that LR contains return
+// address, executes |block| and marks that LR can be safely clobbered
+// afterwards (assuming that |block| moved LR value onto into another register).
+#define SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(block)                       \
+  do {                                                                         \
+    READS_RETURN_ADDRESS_FROM_LR(block);                                       \
+    __ set_lr_state(__ lr_state().SetLRContainsReturnAddress(false));          \
+  } while (0)
+
+// RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(...) checks that LR does not
+// contain return address, executes |block| and marks LR as containing return
+// address (assuming that |block| restored LR value from another register).
+#define RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(block)                     \
+  do {                                                                         \
+    CLOBBERS_LR(block);                                                        \
+    __ set_lr_state(__ lr_state().SetLRContainsReturnAddress(true));           \
+  } while (0)
+
+// SPILLS_LR_TO_FRAME(...) executes |block| and updates tracked LR state to
+// record that we entered a frame which preserved LR. LR can be clobbered
+// afterwards.
+#define SPILLS_LR_TO_FRAME(block)                                              \
+  do {                                                                         \
+    constexpr Register LR = LR_DO_NOT_USE_DIRECTLY;                            \
+    USE(LR);                                                                   \
+    block;                                                                     \
+    __ set_lr_state(__ lr_state().EnterFrame());                               \
+  } while (0)
+
+// RESTORE_LR(...) checks that LR does not contain return address, executes
+// |block| and updates tracked LR state to record that we exited a frame.
+// Whether LR contains return address or not after this operation depends on
+// the frame state (only the outermost frame usually restores LR).
+#define RESTORES_LR_FROM_FRAME(block)                                          \
+  do {                                                                         \
+    CLOBBERS_LR(block);                                                        \
+    __ set_lr_state(__ lr_state().LeaveFrame());                               \
+  } while (0)
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+
 enum OperandSize {
   // Architecture-independent constants.
   kByte,
@@ -106,20 +252,51 @@
   intptr_t position_;
   intptr_t unresolved_;
   intptr_t unresolved_near_positions_[kMaxUnresolvedBranches];
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+  // On ARM/ARM64 we track LR state: whether it contains return address or
+  // whether it can be clobbered. To make sure that our tracking it correct
+  // for non linear code sequences we additionally verify at labels that
+  // incomming states are compatible.
+  LRState lr_state_ = LRState::Unknown();
+
+  void UpdateLRState(LRState new_state) {
+    if (lr_state_.IsUnknown()) {
+      lr_state_ = new_state;
+    } else {
+      RELEASE_ASSERT(lr_state_ == new_state);
+    }
+  }
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
 
   void Reinitialize() { position_ = 0; }
 
-  void BindTo(intptr_t position) {
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+  void BindTo(intptr_t position, LRState lr_state)
+#else
+  void BindTo(intptr_t position)
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+  {
     ASSERT(!IsBound());
     ASSERT(!HasNear());
     position_ = -position - kBias;
     ASSERT(IsBound());
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+    UpdateLRState(lr_state);
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
   }
 
-  void LinkTo(intptr_t position) {
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+  void LinkTo(intptr_t position, LRState lr_state)
+#else
+  void LinkTo(intptr_t position)
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+  {
     ASSERT(!IsBound());
     position_ = position + kBias;
     ASSERT(IsLinked());
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+    UpdateLRState(lr_state);
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
   }
 
   void NearLinkTo(intptr_t position) {
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index de9ce35..99a7a02 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -1990,7 +1990,7 @@
   StoreIntoObjectFilter(object, value, &done, kValueCanBeSmi, kJumpToNoUpdate);
 
   testb(FieldAddress(object, target::Object::tags_offset()),
-        Immediate(1 << target::ObjectLayout::kOldAndNotRememberedBit));
+        Immediate(1 << target::UntaggedObject::kOldAndNotRememberedBit));
   j(ZERO, &done, Assembler::kNearJump);
 
   Stop("Store buffer update is required");
@@ -2693,11 +2693,11 @@
 }
 
 void Assembler::LoadClassId(Register result, Register object) {
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
   const intptr_t class_id_offset =
       target::Object::tags_offset() +
-      target::ObjectLayout::kClassIdTagPos / kBitsPerByte;
+      target::UntaggedObject::kClassIdTagPos / kBitsPerByte;
   movzxw(result, FieldAddress(object, class_id_offset));
 }
 
@@ -2723,11 +2723,11 @@
                                      Register scratch,
                                      Label* is_smi) {
   ASSERT(kSmiTagShift == 1);
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
   const intptr_t class_id_offset =
       target::Object::tags_offset() +
-      target::ObjectLayout::kClassIdTagPos / kBitsPerByte;
+      target::UntaggedObject::kClassIdTagPos / kBitsPerByte;
 
   // Untag optimistically. Tag bit is shifted into the CARRY.
   SmiUntag(object);
@@ -2754,7 +2754,7 @@
   } else {
     ASSERT(result != object);
     static const intptr_t kSmiCidSource =
-        kSmiCid << target::ObjectLayout::kClassIdTagPos;
+        kSmiCid << target::UntaggedObject::kClassIdTagPos;
 
     // Make a dummy "Object" whose cid is kSmiCid.
     movl(result, Immediate(reinterpret_cast<int32_t>(&kSmiCidSource) + 1));
diff --git a/runtime/vm/compiler/assembler/assembler_ia32_test.cc b/runtime/vm/compiler/assembler/assembler_ia32_test.cc
index 6c13141..4f98613 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32_test.cc
@@ -4588,7 +4588,7 @@
 }
 
 ASSEMBLER_TEST_GENERATE(TestObjectCompare, assembler) {
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
   const Object& obj = Object::ZoneHandle(object_store->smi_class());
   Label fail;
   __ LoadObject(EAX, obj);
diff --git a/runtime/vm/compiler/assembler/assembler_test.cc b/runtime/vm/compiler/assembler/assembler_test.cc
index 02f6b59..8488eae 100644
--- a/runtime/vm/compiler/assembler/assembler_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_test.cc
@@ -29,38 +29,38 @@
   Smi& smi = Smi::Handle();
   Thread* thread = Thread::Current();
 
-  EXPECT(old_array.raw() == grow_old_array.data());
-  EXPECT(!thread->StoreBufferContains(grow_old_array.raw()));
-  EXPECT(old_array.raw() == grow_new_array.data());
-  EXPECT(!thread->StoreBufferContains(grow_new_array.raw()));
+  EXPECT(old_array.ptr() == grow_old_array.data());
+  EXPECT(!thread->StoreBufferContains(grow_old_array.ptr()));
+  EXPECT(old_array.ptr() == grow_new_array.data());
+  EXPECT(!thread->StoreBufferContains(grow_new_array.ptr()));
 
   // Store Smis into the old object.
   for (int i = -128; i < 128; i++) {
     smi = Smi::New(i);
-    TEST_CODE(smi.raw(), grow_old_array.raw(), thread);
-    EXPECT(static_cast<ArrayPtr>(smi.raw()) == grow_old_array.data());
-    EXPECT(!thread->StoreBufferContains(grow_old_array.raw()));
+    TEST_CODE(smi.ptr(), grow_old_array.ptr(), thread);
+    EXPECT(static_cast<ArrayPtr>(smi.ptr()) == grow_old_array.data());
+    EXPECT(!thread->StoreBufferContains(grow_old_array.ptr()));
   }
 
   // Store an old object into the old object.
-  TEST_CODE(old_array.raw(), grow_old_array.raw(), thread);
-  EXPECT(old_array.raw() == grow_old_array.data());
-  EXPECT(!thread->StoreBufferContains(grow_old_array.raw()));
+  TEST_CODE(old_array.ptr(), grow_old_array.ptr(), thread);
+  EXPECT(old_array.ptr() == grow_old_array.data());
+  EXPECT(!thread->StoreBufferContains(grow_old_array.ptr()));
 
   // Store a new object into the old object.
-  TEST_CODE(new_array.raw(), grow_old_array.raw(), thread);
-  EXPECT(new_array.raw() == grow_old_array.data());
-  EXPECT(thread->StoreBufferContains(grow_old_array.raw()));
+  TEST_CODE(new_array.ptr(), grow_old_array.ptr(), thread);
+  EXPECT(new_array.ptr() == grow_old_array.data());
+  EXPECT(thread->StoreBufferContains(grow_old_array.ptr()));
 
   // Store a new object into the new object.
-  TEST_CODE(new_array.raw(), grow_new_array.raw(), thread);
-  EXPECT(new_array.raw() == grow_new_array.data());
-  EXPECT(!thread->StoreBufferContains(grow_new_array.raw()));
+  TEST_CODE(new_array.ptr(), grow_new_array.ptr(), thread);
+  EXPECT(new_array.ptr() == grow_new_array.data());
+  EXPECT(!thread->StoreBufferContains(grow_new_array.ptr()));
 
   // Store an old object into the new object.
-  TEST_CODE(old_array.raw(), grow_new_array.raw(), thread);
-  EXPECT(old_array.raw() == grow_new_array.data());
-  EXPECT(!thread->StoreBufferContains(grow_new_array.raw()));
+  TEST_CODE(old_array.ptr(), grow_new_array.ptr(), thread);
+  EXPECT(old_array.ptr() == grow_new_array.data());
+  EXPECT(!thread->StoreBufferContains(grow_new_array.ptr()));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 0bc1761..3e02ea9 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -114,15 +114,6 @@
   }
 }
 
-void Assembler::PushImmediate(const Immediate& imm) {
-  if (imm.is_int32()) {
-    pushq(imm);
-  } else {
-    LoadImmediate(TMP, imm);
-    pushq(TMP);
-  }
-}
-
 void Assembler::popq(Register reg) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitRegisterREX(reg, REX_NONE);
@@ -1399,14 +1390,14 @@
   //    in progress
   // If so, call the WriteBarrier stub, which will either add object to the
   // store buffer (case 1) or add value to the marking stack (case 2).
-  // Compare ObjectLayout::StorePointer.
+  // Compare UntaggedObject::StorePointer.
   Label done;
   if (can_be_smi == kValueCanBeSmi) {
     testq(value, Immediate(kSmiTagMask));
     j(ZERO, &done, kNearJump);
   }
   movb(TMP, FieldAddress(object, target::Object::tags_offset()));
-  shrl(TMP, Immediate(target::ObjectLayout::kBarrierOverlapShift));
+  shrl(TMP, Immediate(target::UntaggedObject::kBarrierOverlapShift));
   andl(TMP, Address(THR, target::Thread::write_barrier_mask_offset()));
   testb(FieldAddress(value, target::Object::tags_offset()), TMP);
   j(ZERO, &done, kNearJump);
@@ -1451,14 +1442,14 @@
   //    in progress
   // If so, call the WriteBarrier stub, which will either add object to the
   // store buffer (case 1) or add value to the marking stack (case 2).
-  // Compare ObjectLayout::StorePointer.
+  // Compare UntaggedObject::StorePointer.
   Label done;
   if (can_be_smi == kValueCanBeSmi) {
     testq(value, Immediate(kSmiTagMask));
     j(ZERO, &done, kNearJump);
   }
   movb(TMP, FieldAddress(object, target::Object::tags_offset()));
-  shrl(TMP, Immediate(target::ObjectLayout::kBarrierOverlapShift));
+  shrl(TMP, Immediate(target::UntaggedObject::kBarrierOverlapShift));
   andl(TMP, Address(THR, target::Thread::write_barrier_mask_offset()));
   testb(FieldAddress(value, target::Object::tags_offset()), TMP);
   j(ZERO, &done, kNearJump);
@@ -1486,7 +1477,7 @@
   StoreIntoObjectFilter(object, value, &done, kValueCanBeSmi, kJumpToNoUpdate);
 
   testb(FieldAddress(object, target::Object::tags_offset()),
-        Immediate(1 << target::ObjectLayout::kOldAndNotRememberedBit));
+        Immediate(1 << target::UntaggedObject::kOldAndNotRememberedBit));
   j(ZERO, &done, Assembler::kNearJump);
 
   Stop("Store buffer update is required");
@@ -2169,29 +2160,29 @@
 }
 
 void Assembler::ExtractClassIdFromTags(Register result, Register tags) {
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
   movl(result, tags);
-  shrl(result, Immediate(target::ObjectLayout::kClassIdTagPos));
+  shrl(result, Immediate(target::UntaggedObject::kClassIdTagPos));
 }
 
 void Assembler::ExtractInstanceSizeFromTags(Register result, Register tags) {
-  ASSERT(target::ObjectLayout::kSizeTagPos == 8);
-  ASSERT(target::ObjectLayout::kSizeTagSize == 8);
+  ASSERT(target::UntaggedObject::kSizeTagPos == 8);
+  ASSERT(target::UntaggedObject::kSizeTagSize == 8);
   movzxw(result, tags);
-  shrl(result, Immediate(target::ObjectLayout::kSizeTagPos -
+  shrl(result, Immediate(target::UntaggedObject::kSizeTagPos -
                          target::ObjectAlignment::kObjectAlignmentLog2));
   AndImmediate(result,
-               Immediate(Utils::NBitMask(target::ObjectLayout::kSizeTagSize)
+               Immediate(Utils::NBitMask(target::UntaggedObject::kSizeTagSize)
                          << target::ObjectAlignment::kObjectAlignmentLog2));
 }
 
 void Assembler::LoadClassId(Register result, Register object) {
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
   const intptr_t class_id_offset =
       target::Object::tags_offset() +
-      target::ObjectLayout::kClassIdTagPos / kBitsPerByte;
+      target::UntaggedObject::kClassIdTagPos / kBitsPerByte;
   movzxw(result, FieldAddress(object, class_id_offset));
 }
 
@@ -2216,11 +2207,11 @@
                                      intptr_t class_id,
                                      Label* is_smi) {
   ASSERT(kSmiTagShift == 1);
-  ASSERT(target::ObjectLayout::kClassIdTagPos == 16);
-  ASSERT(target::ObjectLayout::kClassIdTagSize == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagPos == 16);
+  ASSERT(target::UntaggedObject::kClassIdTagSize == 16);
   const intptr_t class_id_offset =
       target::Object::tags_offset() +
-      target::ObjectLayout::kClassIdTagPos / kBitsPerByte;
+      target::UntaggedObject::kClassIdTagPos / kBitsPerByte;
 
   // Untag optimistically. Tag bit is shifted into the CARRY.
   SmiUntag(object);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 3b5fa5c..1295e25 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -304,7 +304,7 @@
   void pushq(Register reg);
   void pushq(const Address& address) { EmitUnaryL(address, 0xFF, 6); }
   void pushq(const Immediate& imm);
-  void PushImmediate(const Immediate& imm);
+  void PushImmediate(const Immediate& imm) { pushq(imm); }
   void PushImmediate(int64_t value) { PushImmediate(Immediate(value)); }
 
   void popq(Register reg);
@@ -915,6 +915,15 @@
                           OperandSize sz = kEightBytes) {
     LoadFromOffset(dst, FieldAddress(base, index, scale, payload_offset), sz);
   }
+  void StoreFieldToOffset(Register src,
+                          Register base,
+                          int32_t offset,
+                          OperandSize sz = kEightBytes) {
+    if (sz != kEightBytes) {
+      UNIMPLEMENTED();
+    }
+    StoreMemoryValue(src, base, offset - kHeapObjectTag);
+  }
   void LoadFromStack(Register dst, intptr_t depth);
   void StoreToStack(Register src, intptr_t depth);
   void CompareToStack(Register src, intptr_t depth);
@@ -1028,7 +1037,7 @@
   // before the code can be used.
   //
   // The neccessary information for the "linker" (i.e. the relocation
-  // information) is stored in [CodeLayout::static_calls_target_table_]: an
+  // information) is stored in [UntaggedCode::static_calls_target_table_]: an
   // entry of the form
   //
   //   (Code::kPcRelativeCall & pc_offset, <target-code>, <target-function>)
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index 7a21b97..39d492d 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -4935,7 +4935,7 @@
 }
 
 ASSEMBLER_TEST_GENERATE(TestObjectCompare, assembler) {
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
   const Object& obj = Object::ZoneHandle(object_store->smi_class());
   Label fail;
   EnterTestFrame(assembler);
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index e7e73a5..fdbe05c 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -309,20 +309,20 @@
     String& var_name = String::Handle(zone);
     for (intptr_t i = 0; i < var_desc_length; i++) {
       var_name = var_descriptors.GetName(i);
-      LocalVarDescriptorsLayout::VarInfo var_info;
+      UntaggedLocalVarDescriptors::VarInfo var_info;
       var_descriptors.GetInfo(i, &var_info);
       const int8_t kind = var_info.kind();
-      if (kind == LocalVarDescriptorsLayout::kSavedCurrentContext) {
+      if (kind == UntaggedLocalVarDescriptors::kSavedCurrentContext) {
         THR_Print("  saved current CTX reg offset %d\n", var_info.index());
       } else {
-        if (kind == LocalVarDescriptorsLayout::kContextLevel) {
+        if (kind == UntaggedLocalVarDescriptors::kContextLevel) {
           THR_Print("  context level %d scope %d", var_info.index(),
                     var_info.scope_id);
-        } else if (kind == LocalVarDescriptorsLayout::kStackVar) {
+        } else if (kind == UntaggedLocalVarDescriptors::kStackVar) {
           THR_Print("  stack var '%s' offset %d", var_name.ToCString(),
                     var_info.index());
         } else {
-          ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
+          ASSERT(kind == UntaggedLocalVarDescriptors::kContextVar);
           THR_Print("  context var '%s' level %d offset %d",
                     var_name.ToCString(), var_info.scope_id, var_info.index());
         }
@@ -339,7 +339,8 @@
   THR_Print("%s}\n", handlers.ToCString());
 
 #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
-  if (code.catch_entry_moves_maps() != Object::null()) {
+  if (FLAG_precompiled_mode &&
+      code.catch_entry_moves_maps() != Object::null()) {
     THR_Print("Catch entry moves for function '%s' {\n", function_fullname);
     CatchEntryMovesMapReader reader(
         TypedData::Handle(code.catch_entry_moves_maps()));
@@ -389,9 +390,9 @@
 
         dst_type = AbstractType::null();
         if (object.IsAbstractType()) {
-          dst_type = AbstractType::Cast(object).raw();
+          dst_type = AbstractType::Cast(object).ptr();
         } else if (object.IsCode()) {
-          code = Code::Cast(object).raw();
+          code = Code::Cast(object).ptr();
         }
 
         auto kind = Code::KindField::decode(kind_type_and_offset.Value());
diff --git a/runtime/vm/compiler/backend/block_builder.h b/runtime/vm/compiler/backend/block_builder.h
index 99d3764..ef51d8d 100644
--- a/runtime/vm/compiler/backend/block_builder.h
+++ b/runtime/vm/compiler/backend/block_builder.h
@@ -20,6 +20,8 @@
  public:
   BlockBuilder(FlowGraph* flow_graph, BlockEntryInstr* entry)
       : flow_graph_(flow_graph),
+        source_(InstructionSource(flow_graph_->function().token_pos(),
+                                  flow_graph->inlining_id())),
         entry_(entry),
         current_(entry),
         dummy_env_(
@@ -63,8 +65,8 @@
     const auto& function = flow_graph_->function();
     const auto representation = FlowGraph::ReturnRepresentationOf(function);
     ReturnInstr* instr = new ReturnInstr(
-        TokenPos(), value, CompilerState::Current().GetNextDeoptId(),
-        PcDescriptorsLayout::kInvalidYieldIndex, representation);
+        Source(), value, CompilerState::Current().GetNextDeoptId(),
+        UntaggedPcDescriptors::kInvalidYieldIndex, representation);
     AddInstruction(instr);
     entry_->set_last_instruction(instr);
     return instr;
@@ -88,7 +90,8 @@
                            with_frame ? FPREG : SPREG));
   }
 
-  TokenPosition TokenPos() { return flow_graph_->function().token_pos(); }
+  TokenPosition TokenPos() const { return source_.token_pos; }
+  const InstructionSource& Source() const { return source_; }
 
   Definition* AddNullDefinition() {
     return flow_graph_->GetConstant(Object::ZoneHandle());
@@ -158,7 +161,8 @@
     }
   }
 
-  FlowGraph* flow_graph_;
+  FlowGraph* const flow_graph_;
+  const InstructionSource source_;
   BlockEntryInstr* entry_;
   Instruction* current_;
   Environment* dummy_env_;
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 4cc16cf..427c0b9 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -68,12 +68,12 @@
   //
   // ASSERT(IsUnknown(definition->constant_value()) ||
   //        IsNonConstant(value) ||
-  //        (definition->constant_value().raw() == value.raw()));
+  //        (definition->constant_value().ptr() == value.ptr()));
   //
   // But the final disjunct is not true (e.g., mint or double constants are
   // heap-allocated and so not necessarily pointer-equal on each iteration).
-  if (definition->constant_value().raw() != value.raw()) {
-    definition->constant_value() = value.raw();
+  if (definition->constant_value().ptr() != value.ptr()) {
+    definition->constant_value() = value.ptr();
     if (definition->input_use_list() != NULL) {
       definition_worklist_.Add(definition);
     }
@@ -86,7 +86,7 @@
   // This should be kept in line with Identical_comparison (identical.cc)
   // (=> Instance::IsIdenticalTo in object.cc).
 
-  if (left.raw() == right.raw()) return true;
+  if (left.ptr() == right.ptr()) return true;
   if (left.GetClassId() != right.GetClassId()) return false;
   if (left.IsInteger()) {
     return Integer::Cast(left).Equals(Integer::Cast(right));
@@ -107,7 +107,7 @@
   // Join(unknown, X)      = X
   // Join(X, non-constant) = non-constant
   if (IsUnknown(*left) || IsNonConstant(right)) {
-    *left = right.raw();
+    *left = right.ptr();
     return;
   }
 
@@ -115,7 +115,7 @@
   if (IsIdenticalConstants(*left, right)) return;
 
   // Join(X, Y) = non-constant
-  *left = non_constant_.raw();
+  *left = non_constant_.ptr();
 }
 
 // --------------------------------------------------------------------------
@@ -254,7 +254,7 @@
       if (IsNonConstant(value)) {
         SetReachable(instr->true_successor());
         SetReachable(instr->false_successor());
-      } else if (value.raw() == Bool::True().raw()) {
+      } else if (value.ptr() == Bool::True().ptr()) {
         SetReachable(instr->true_successor());
       } else if (!IsUnknown(value)) {  // Any other constant.
         SetReachable(instr->false_successor());
@@ -875,7 +875,7 @@
     return;
   }
   if (value.IsBool()) {
-    bool val = value.raw() != Bool::True().raw();
+    bool val = value.ptr() != Bool::True().ptr();
     SetValue(instr, Bool::Get(val));
   } else {
     SetValue(instr, non_constant_);
@@ -908,7 +908,7 @@
       SetValue(instr, non_constant_);
     }
   } else if (IsConstant(value)) {
-    if (value.IsInstance() && (value.raw() != Object::sentinel().raw())) {
+    if (value.IsInstance() && (value.ptr() != Object::sentinel().ptr())) {
       const Instance& instance = Instance::Cast(value);
       if (instr->instantiator_type_arguments()->BindsToConstantNull() &&
           instr->function_type_arguments()->BindsToConstantNull()) {
@@ -1001,7 +1001,7 @@
     } else {
       Object& value = Object::Handle();
       if (instr->Evaluate(constant, &value)) {
-        SetValue(instr, Object::ZoneHandle(Z, value.raw()));
+        SetValue(instr, Object::ZoneHandle(Z, value.ptr()));
         return;
       }
     }
@@ -1021,7 +1021,7 @@
       return;
     }
     if (instantiator_type_args_obj.IsTypeArguments()) {
-      instantiator_type_args ^= instantiator_type_args_obj.raw();
+      instantiator_type_args ^= instantiator_type_args_obj.ptr();
     } else {
       SetValue(instr, non_constant_);
       return;
@@ -1035,7 +1035,7 @@
       return;
     }
     if (function_type_args_obj.IsTypeArguments()) {
-      function_type_args ^= function_type_args_obj.raw();
+      function_type_args ^= function_type_args_obj.ptr();
     } else {
       SetValue(instr, non_constant_);
       return;
@@ -1086,7 +1086,7 @@
       SetValue(instr, non_constant_);
       return;
     }
-    instantiator_type_args ^= instantiator_type_args_obj.raw();
+    instantiator_type_args ^= instantiator_type_args_obj.ptr();
     if (instr->CanShareInstantiatorTypeArguments()) {
       SetValue(instr, instantiator_type_args);
       return;
@@ -1105,7 +1105,7 @@
       SetValue(instr, non_constant_);
       return;
     }
-    function_type_args ^= function_type_args_obj.raw();
+    function_type_args ^= function_type_args_obj.ptr();
     if (instr->CanShareFunctionTypeArguments()) {
       SetValue(instr, function_type_args);
       return;
@@ -1148,7 +1148,7 @@
                                             binary_op->is_truncating(),
                                             binary_op->representation(), T));
     if (!result.IsNull()) {
-      SetValue(binary_op, Integer::ZoneHandle(Z, result.raw()));
+      SetValue(binary_op, Integer::ZoneHandle(Z, result.ptr()));
       return;
     }
   }
@@ -1218,7 +1218,7 @@
         Z, Evaluator::UnaryIntegerEvaluate(value, unary_op->op_kind(),
                                            unary_op->representation(), T));
     if (!result.IsNull()) {
-      SetValue(unary_op, Integer::ZoneHandle(Z, result.raw()));
+      SetValue(unary_op, Integer::ZoneHandle(Z, result.ptr()));
       return;
     }
   }
@@ -1712,7 +1712,7 @@
       THR_Print("Constant v%" Pd " = %s\n", defn->ssa_temp_index(),
                 defn->constant_value().ToCString());
     }
-    constant_value_ = defn->constant_value().raw();
+    constant_value_ = defn->constant_value().ptr();
     if ((constant_value_.IsString() || constant_value_.IsMint() ||
          constant_value_.IsDouble()) &&
         !constant_value_.IsCanonical()) {
diff --git a/runtime/vm/compiler/backend/constant_propagator.h b/runtime/vm/compiler/backend/constant_propagator.h
index d0dca7d..36368d0 100644
--- a/runtime/vm/compiler/backend/constant_propagator.h
+++ b/runtime/vm/compiler/backend/constant_propagator.h
@@ -36,7 +36,7 @@
   static void OptimizeBranches(FlowGraph* graph);
 
   // Used to initialize the abstract value of definitions.
-  static ObjectPtr Unknown() { return Object::unknown_constant().raw(); }
+  static ObjectPtr Unknown() { return Object::unknown_constant().ptr(); }
 
  private:
   void Analyze();
@@ -60,9 +60,9 @@
   // first one.
   void Join(Object* left, const Object& right);
 
-  bool IsUnknown(const Object& value) { return value.raw() == unknown_.raw(); }
+  bool IsUnknown(const Object& value) { return value.ptr() == unknown_.ptr(); }
   bool IsNonConstant(const Object& value) {
-    return value.raw() == non_constant_.raw();
+    return value.ptr() == non_constant_.ptr();
   }
   bool IsConstant(const Object& value) {
     return !IsNonConstant(value) && !IsUnknown(value);
diff --git a/runtime/vm/compiler/backend/constant_propagator_test.cc b/runtime/vm/compiler/backend/constant_propagator_test.cc
index 24e7df1..3eb3218 100644
--- a/runtime/vm/compiler/backend/constant_propagator_test.cc
+++ b/runtime/vm/compiler/backend/constant_propagator_test.cc
@@ -19,7 +19,7 @@
 // its uses (which includes comparison and the phi itself).
 ISOLATE_UNIT_TEST_CASE(ConstantPropagation_PhiUnwrappingAndConvergence) {
   using compiler::BlockBuilder;
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
   FlowGraphBuilderHelper H;
 
   // We are going to build the following graph:
@@ -53,15 +53,14 @@
     BlockBuilder builder(H.flow_graph(), b2);
     v1 = H.Phi(b2, {{b1, v0}, {b3, FlowGraphBuilderHelper::kPhiSelfReference}});
     builder.AddPhi(v1);
-    auto v2 = builder.AddDefinition(new EqualityCompareInstr(
-        TokenPosition::kNoSource, Token::kEQ, new Value(v1), new Value(v0),
-        kSmiCid, S.GetNextDeoptId()));
-    builder.AddBranch(
-        new StrictCompareInstr(
-            TokenPosition::kNoSource, Token::kEQ_STRICT, new Value(v2),
-            new Value(H.flow_graph()->GetConstant(Bool::True())),
-            /*needs_number_check=*/false, S.GetNextDeoptId()),
-        b4, b3);
+    auto v2 = builder.AddDefinition(
+        new EqualityCompareInstr(InstructionSource(), Token::kEQ, new Value(v1),
+                                 new Value(v0), kSmiCid, S.GetNextDeoptId()));
+    builder.AddBranch(new StrictCompareInstr(
+                          InstructionSource(), Token::kEQ_STRICT, new Value(v2),
+                          new Value(H.flow_graph()->GetConstant(Bool::True())),
+                          /*needs_number_check=*/false, S.GetNextDeoptId()),
+                      b4, b3);
   }
 
   {
@@ -114,7 +113,7 @@
     FoldingResult expected) {
   using compiler::BlockBuilder;
 
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
   FlowGraphBuilderHelper H;
 
   // Add a variable into the scope which would provide static type for the
@@ -158,12 +157,12 @@
     BlockBuilder builder(H.flow_graph(), b1);
     auto v0 = builder.AddParameter(/*index=*/0, /*param_offset=*/0,
                                    /*with_frame=*/true, kTagged);
-    builder.AddBranch(new StrictCompareInstr(
-                          TokenPosition::kNoSource, Token::kEQ_STRICT,
-                          new Value(H.IntConstant(1)),
-                          new Value(redundant_phi ? H.IntConstant(1) : v0),
-                          /*needs_number_check=*/false, S.GetNextDeoptId()),
-                      b2, b3);
+    builder.AddBranch(
+        new StrictCompareInstr(
+            InstructionSource(), Token::kEQ_STRICT, new Value(H.IntConstant(1)),
+            new Value(redundant_phi ? H.IntConstant(1) : v0),
+            /*needs_number_check=*/false, S.GetNextDeoptId()),
+        b2, b3);
   }
 
   {
diff --git a/runtime/vm/compiler/backend/evaluator.cc b/runtime/vm/compiler/backend/evaluator.cc
index ce4660c..5364b28 100644
--- a/runtime/vm/compiler/backend/evaluator.cc
+++ b/runtime/vm/compiler/backend/evaluator.cc
@@ -118,7 +118,7 @@
     result ^= result.Canonicalize(thread);
   }
 
-  return result.raw();
+  return result.ptr();
 }
 
 IntegerPtr Evaluator::UnaryIntegerEvaluate(const Object& value,
@@ -147,7 +147,7 @@
     result ^= result.Canonicalize(thread);
   }
 
-  return result.raw();
+  return result.ptr();
 }
 
 double Evaluator::EvaluateDoubleOp(const double left,
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 0b7acfc..5b8b058 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -192,7 +192,7 @@
   if (constant == nullptr) {
     // Otherwise, allocate and add it to the pool.
     constant =
-        new (zone()) ConstantInstr(Object::ZoneHandle(zone(), object.raw()));
+        new (zone()) ConstantInstr(Object::ZoneHandle(zone(), object.ptr()));
     constant->set_ssa_temp_index(alloc_ssa_temp_index());
     if (NeedsPairLocation(constant->representation())) {
       alloc_ssa_temp_index();
@@ -481,7 +481,7 @@
 
 FlowGraph::ToCheck FlowGraph::CheckForInstanceCall(
     InstanceCallInstr* call,
-    FunctionLayout::Kind kind) const {
+    UntaggedFunction::Kind kind) const {
   if (!FLAG_use_cha_deopt && !isolate()->all_classes_finalized()) {
     // Even if class or function are private, lazy class finalization
     // may later add overriding methods.
@@ -543,7 +543,7 @@
   }
 
   const String& method_name =
-      (kind == FunctionLayout::kMethodExtractor)
+      (kind == UntaggedFunction::kMethodExtractor)
           ? String::Handle(zone(), Field::NameFromGetter(call->function_name()))
           : call->function_name();
 
@@ -551,7 +551,7 @@
   // that is actually valid on a null receiver.
   if (receiver_maybe_null) {
     const Class& null_class =
-        Class::Handle(zone(), isolate()->object_store()->null_class());
+        Class::Handle(zone(), isolate_group()->object_store()->null_class());
     Function& target = Function::Handle(zone());
     if (null_class.EnsureIsFinalized(thread()) == Error::null()) {
       target = Resolver::ResolveDynamicAnyArgs(zone(), null_class, method_name);
@@ -585,13 +585,13 @@
 Instruction* FlowGraph::CreateCheckClass(Definition* to_check,
                                          const Cids& cids,
                                          intptr_t deopt_id,
-                                         TokenPosition token_pos) {
+                                         const InstructionSource& source) {
   if (cids.IsMonomorphic() && cids.MonomorphicReceiverCid() == kSmiCid) {
     return new (zone())
-        CheckSmiInstr(new (zone()) Value(to_check), deopt_id, token_pos);
+        CheckSmiInstr(new (zone()) Value(to_check), deopt_id, source);
   }
   return new (zone())
-      CheckClassInstr(new (zone()) Value(to_check), deopt_id, cids, token_pos);
+      CheckClassInstr(new (zone()) Value(to_check), deopt_id, cids, source);
 }
 
 Definition* FlowGraph::CreateCheckBound(Definition* length,
@@ -607,12 +607,12 @@
 
 void FlowGraph::AddExactnessGuard(InstanceCallInstr* call,
                                   intptr_t receiver_cid) {
-  const Class& cls = Class::Handle(
-      zone(), Isolate::Current()->class_table()->At(receiver_cid));
+  const Class& cls =
+      Class::Handle(zone(), isolate_group()->class_table()->At(receiver_cid));
 
   Definition* load_type_args = new (zone()) LoadFieldInstr(
       call->Receiver()->CopyWithType(),
-      Slot::GetTypeArgumentsSlotFor(thread(), cls), call->token_pos());
+      Slot::GetTypeArgumentsSlotFor(thread(), cls), call->source());
   InsertBefore(call, load_type_args, call->env(), FlowGraph::kValue);
 
   const AbstractType& type =
@@ -620,7 +620,7 @@
   ASSERT(!type.IsNull());
   const TypeArguments& args = TypeArguments::Handle(zone(), type.arguments());
   Instruction* guard = new (zone()) CheckConditionInstr(
-      new StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT,
+      new StrictCompareInstr(call->source(), Token::kEQ_STRICT,
                              new (zone()) Value(load_type_args),
                              new (zone()) Value(GetConstant(args)),
                              /*needs_number_check=*/false, call->deopt_id()),
@@ -2742,7 +2742,7 @@
   PhiInstr* phi =
       AddPhi(mid_point, condition.oper2, GetConstant(Bool::False()));
   StrictCompareInstr* circuit = new (zone()) StrictCompareInstr(
-      inherit->token_pos(), Token::kEQ_STRICT, new (zone()) Value(phi),
+      inherit->source(), Token::kEQ_STRICT, new (zone()) Value(phi),
       new (zone()) Value(GetConstant(Bool::True())), false,
       DeoptId::kNone);  // don't inherit
 
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index a288e47..8a8bb32 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -76,7 +76,7 @@
   }
 
   static inline bool IsKeyEqual(Pair kv, Key key) {
-    return kv->value().raw() == key.raw();
+    return kv->value().ptr() == key.ptr();
   }
 };
 
@@ -211,7 +211,7 @@
   Instruction* CreateCheckClass(Definition* to_check,
                                 const Cids& cids,
                                 intptr_t deopt_id,
-                                TokenPosition token_pos);
+                                const InstructionSource& source);
 
   Definition* CreateCheckBound(Definition* length,
                                Definition* index,
@@ -234,11 +234,12 @@
   // Return value indicates that the call needs no check at all,
   // just a null check, or a full class check.
   ToCheck CheckForInstanceCall(InstanceCallInstr* call,
-                               FunctionLayout::Kind kind) const;
+                               UntaggedFunction::Kind kind) const;
 
   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(); }
 
   intptr_t max_block_id() const { return max_block_id_; }
   void set_max_block_id(intptr_t id) { max_block_id_ = id; }
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc
index 5b753ce..0943943 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.cc
+++ b/runtime/vm/compiler/backend/flow_graph_checker.cc
@@ -24,8 +24,8 @@
 // succ/pred/block links are not maintained.
 static bool IsSpecialConstant(Definition* def) {
   if (auto c = def->AsConstant()) {
-    return c->value().raw() == Symbols::OptimizedOut().raw() ||
-           c->value().raw() == Object::ZoneHandle().raw();
+    return c->value().ptr() == Symbols::OptimizedOut().ptr() ||
+           c->value().ptr() == Object::ZoneHandle().ptr();
   }
   return false;
 }
@@ -141,8 +141,8 @@
                 ->OriginalDefinitionIgnoreBoxingAndConstraints();
         ASSERT((arg_def == env_def) ||
                (arg_def->IsConstant() && env_def->IsConstant() &&
-                arg_def->AsConstant()->value().raw() ==
-                    env_def->AsConstant()->value().raw()));
+                arg_def->AsConstant()->value().ptr() ==
+                    env_def->AsConstant()->value().ptr()));
       }
     }
   }
@@ -274,6 +274,44 @@
          instruction->deopt_id() != DeoptId::kNone);
 #endif  // !defined(DART_PRECOMPILER)
 
+  // If checking token positions and the flow graph has an inlining ID,
+  // check the inlining ID and token position for instructions with real or
+  // synthetic token positions.
+  if (FLAG_check_token_positions && flow_graph_->inlining_id() >= 0) {
+    const TokenPosition& pos = instruction->token_pos();
+    if (pos.IsReal() || pos.IsSynthetic()) {
+      ASSERT(instruction->has_inlining_id());
+      const intptr_t inlining_id = instruction->inlining_id();
+      const auto& function = *inline_id_to_function_[inlining_id];
+      if (function.end_token_pos().IsReal() &&
+          !pos.IsWithin(function.token_pos(), function.end_token_pos())) {
+        TextBuffer buffer(256);
+        buffer.Printf("Token position %s is invalid for function %s (%s, %s)",
+                      pos.ToCString(), function.ToFullyQualifiedCString(),
+                      function.token_pos().ToCString(),
+                      function.end_token_pos().ToCString());
+        if (inlining_id > 0) {
+          buffer.Printf(" while compiling function %s",
+                        inline_id_to_function_[0]->ToFullyQualifiedCString());
+        }
+        FATAL("%s", buffer.buffer());
+      }
+      script_ = function.script();
+      if (!script_.IsNull() && !script_.IsValidTokenPosition(pos)) {
+        TextBuffer buffer(256);
+        buffer.Printf(
+            "Token position %s is invalid for script %s of function %s",
+            pos.ToCString(), script_.ToCString(),
+            function.ToFullyQualifiedCString());
+        if (inlining_id > 0) {
+          buffer.Printf(" while compiling function %s",
+                        inline_id_to_function_[0]->ToFullyQualifiedCString());
+        }
+        FATAL("%s", buffer.buffer());
+      }
+    }
+  }
+
   // Check all regular inputs.
   for (intptr_t i = 0, n = instruction->InputCount(); i < n; ++i) {
     VisitUseDef(instruction, instruction->InputAt(i), i, /*is_env*/ false);
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.h b/runtime/vm/compiler/backend/flow_graph_checker.h
index 0079d98..411b1fe 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.h
+++ b/runtime/vm/compiler/backend/flow_graph_checker.h
@@ -32,9 +32,12 @@
   // Constructs graph checker. The checker uses some custom-made
   // visitation to perform additional checks, and uses the
   // FlowGraphVisitor structure for anything else.
-  explicit FlowGraphChecker(FlowGraph* flow_graph)
+  FlowGraphChecker(FlowGraph* flow_graph,
+                   const GrowableArray<const Function*>& inline_id_to_function)
       : FlowGraphVisitor(flow_graph->preorder()),
         flow_graph_(flow_graph),
+        inline_id_to_function_(inline_id_to_function),
+        script_(Script::Handle(flow_graph_->zone())),
         current_block_(nullptr) {}
 
   // Performs a sanity check on the flow graph.
@@ -66,6 +69,8 @@
       PolymorphicInstanceCallInstr* call) override;
 
   FlowGraph* const flow_graph_;
+  const GrowableArray<const Function*>& inline_id_to_function_;
+  Script& script_;
   BlockEntryInstr* current_block_;
 };
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 213bb7a..9bd27a4 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -67,6 +67,34 @@
 DECLARE_FLAG(int, gc_every);
 DECLARE_FLAG(bool, trace_compiler);
 
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+compiler::LRState ComputeInnerLRState(const FlowGraph& flow_graph) {
+  auto entry = flow_graph.graph_entry();
+  const bool frameless = !entry->NeedsFrame();
+
+  bool has_native_entries = false;
+  for (intptr_t i = 0; i < entry->SuccessorCount(); i++) {
+    if (entry->SuccessorAt(i)->IsNativeEntry()) {
+      has_native_entries = true;
+      break;
+    }
+  }
+
+  auto state = compiler::LRState::OnEntry();
+  if (has_native_entries) {
+    // We will setup three (3) frames on the stack when entering through
+    // native entry. Keep in sync with NativeEntry/NativeReturn.
+    state = state.EnterFrame().EnterFrame();
+  }
+
+  if (!frameless) {
+    state = state.EnterFrame();
+  }
+
+  return state;
+}
+#endif
+
 // Assign locations to incoming arguments, i.e., values pushed above spill slots
 // with PushArgument.  Recursively allocates from outermost to innermost
 // environment.
@@ -132,22 +160,23 @@
       intrinsic_mode_(false),
       stats_(stats),
       double_class_(
-          Class::ZoneHandle(isolate()->object_store()->double_class())),
-      mint_class_(Class::ZoneHandle(isolate()->object_store()->mint_class())),
-      float32x4_class_(
-          Class::ZoneHandle(isolate()->object_store()->float32x4_class())),
-      float64x2_class_(
-          Class::ZoneHandle(isolate()->object_store()->float64x2_class())),
+          Class::ZoneHandle(isolate_group()->object_store()->double_class())),
+      mint_class_(
+          Class::ZoneHandle(isolate_group()->object_store()->mint_class())),
+      float32x4_class_(Class::ZoneHandle(
+          isolate_group()->object_store()->float32x4_class())),
+      float64x2_class_(Class::ZoneHandle(
+          isolate_group()->object_store()->float64x2_class())),
       int32x4_class_(
-          Class::ZoneHandle(isolate()->object_store()->int32x4_class())),
+          Class::ZoneHandle(isolate_group()->object_store()->int32x4_class())),
       list_class_(Class::ZoneHandle(Library::Handle(Library::CoreLibrary())
                                         .LookupClass(Symbols::List()))),
       parallel_move_resolver_(this),
       pending_deoptimization_env_(NULL),
       deopt_id_to_ic_data_(deopt_id_to_ic_data),
       edge_counters_array_(Array::ZoneHandle()) {
-  ASSERT(flow_graph->parsed_function().function().raw() ==
-         parsed_function.function().raw());
+  ASSERT(flow_graph->parsed_function().function().ptr() ==
+         parsed_function.function().ptr());
   if (is_optimizing) {
     // No need to collect extra ICData objects created during compilation.
     deopt_id_to_ic_data_ = nullptr;
@@ -163,6 +192,10 @@
 #else
   const bool stack_traces_only = false;
 #endif
+  // Make sure that the function is at the position for inline_id 0.
+  ASSERT(inline_id_to_function.length() >= 1);
+  ASSERT(inline_id_to_function[0]->ptr() ==
+         flow_graph->parsed_function().function().ptr());
   code_source_map_builder_ = new (zone_)
       CodeSourceMapBuilder(zone_, stack_traces_only, caller_inline_id,
                            inline_id_to_token_pos, inline_id_to_function);
@@ -200,7 +233,8 @@
 void FlowGraphCompiler::InitCompiler() {
   compressed_stackmaps_builder_ =
       new (zone()) CompressedStackMapsBuilder(zone());
-  pc_descriptors_list_ = new (zone()) DescriptorList(zone());
+  pc_descriptors_list_ = new (zone()) DescriptorList(
+      zone(), &code_source_map_builder_->inline_id_to_function());
   exception_handlers_list_ = new (zone()) ExceptionHandlerList();
 #if defined(DART_PRECOMPILER)
   catch_entry_moves_maps_builder_ = new (zone()) CatchEntryMovesMapBuilder();
@@ -239,7 +273,7 @@
     for (intptr_t i = 0; i < num_counters; ++i) {
       edge_counters.SetAt(i, Object::smi_zero());
     }
-    edge_counters_array_ = edge_counters.raw();
+    edge_counters_array_ = edge_counters.ptr();
   }
 }
 
@@ -252,13 +286,14 @@
 }
 
 bool FlowGraphCompiler::CanOSRFunction() const {
-  return isolate()->use_osr() && CanOptimizeFunction() && !is_optimizing();
+  return isolate_group()->use_osr() && CanOptimizeFunction() &&
+         !is_optimizing();
 }
 
 void FlowGraphCompiler::InsertBSSRelocation(BSS::Relocation reloc) {
   const intptr_t offset = assembler()->InsertAlignedRelocation(reloc);
-  AddDescriptor(PcDescriptorsLayout::kBSSRelocation, /*pc_offset=*/offset,
-                /*deopt_id=*/DeoptId::kNone, TokenPosition::kNoSource,
+  AddDescriptor(UntaggedPcDescriptors::kBSSRelocation, /*pc_offset=*/offset,
+                /*deopt_id=*/DeoptId::kNone, InstructionSource(),
                 /*try_index=*/-1);
 }
 
@@ -267,7 +302,7 @@
   if ((FLAG_stacktrace_every > 0) || (FLAG_deoptimize_every > 0) ||
       (FLAG_gc_every > 0) ||
       (isolate()->reload_every_n_stack_overflow_checks() > 0)) {
-    if (!Isolate::IsSystemIsolate(isolate())) {
+    if (!IsolateGroup::IsSystemIsolateGroup(isolate_group())) {
       return true;
     }
   }
@@ -354,7 +389,7 @@
                                         intptr_t dst_index) {
   if (src.IsConstant()) {
     // Skip dead locations.
-    if (src.constant().raw() == Symbols::OptimizedOut().raw()) {
+    if (src.constant().ptr() == Symbols::OptimizedOut().ptr()) {
       return CatchEntryMove();
     }
     const intptr_t pool_index =
@@ -459,12 +494,12 @@
 #endif  // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
 }
 
-void FlowGraphCompiler::EmitCallsiteMetadata(TokenPosition token_pos,
+void FlowGraphCompiler::EmitCallsiteMetadata(const InstructionSource& source,
                                              intptr_t deopt_id,
-                                             PcDescriptorsLayout::Kind kind,
+                                             UntaggedPcDescriptors::Kind kind,
                                              LocationSummary* locs,
                                              Environment* env) {
-  AddCurrentDescriptor(kind, deopt_id, token_pos);
+  AddCurrentDescriptor(kind, deopt_id, source);
   RecordSafepoint(locs);
   RecordCatchEntryMoves(env);
   if ((deopt_id != DeoptId::kNone) && !FLAG_precompiled_mode) {
@@ -476,16 +511,17 @@
     } else {
       // Add deoptimization continuation point after the call and before the
       // arguments are removed.
-      AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id_after,
-                           token_pos);
+      AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id_after,
+                           source);
     }
   }
 }
 
-void FlowGraphCompiler::EmitYieldPositionMetadata(TokenPosition token_pos,
-                                                  intptr_t yield_index) {
-  AddDescriptor(PcDescriptorsLayout::kOther, assembler()->CodeSize(),
-                DeoptId::kNone, token_pos, CurrentTryIndex(), yield_index);
+void FlowGraphCompiler::EmitYieldPositionMetadata(
+    const InstructionSource& source,
+    intptr_t yield_index) {
+  AddDescriptor(UntaggedPcDescriptors::kOther, assembler()->CodeSize(),
+                DeoptId::kNone, source, CurrentTryIndex(), yield_index);
 }
 
 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) {
@@ -494,26 +530,30 @@
       // Instructions that can be deoptimization targets need to record kDeopt
       // PcDescriptor corresponding to their deopt id. GotoInstr records its
       // own so that it can control the placement.
-      AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, instr->deopt_id(),
-                           instr->token_pos());
+      AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, instr->deopt_id(),
+                           instr->source());
     }
     AllocateRegistersLocally(instr);
   }
 }
 
 void FlowGraphCompiler::EmitSourceLine(Instruction* instr) {
-  if (!instr->token_pos().IsReal() || (instr->env() == NULL)) {
+  if (!instr->token_pos().IsReal()) {
     return;
   }
-  const Script& script =
-      Script::Handle(zone(), instr->env()->function().script());
+  const InstructionSource& source = instr->source();
+  const intptr_t inlining_id = source.inlining_id < 0 ? 0 : source.inlining_id;
+  const Function& function =
+      *code_source_map_builder_->inline_id_to_function()[inlining_id];
+  ASSERT(instr->env() == nullptr ||
+         instr->env()->function().ptr() == function.ptr());
+  const auto& script = Script::Handle(zone(), function.script());
   intptr_t line_nr;
-  intptr_t column_nr;
-  script.GetTokenLocation(instr->token_pos(), &line_nr, &column_nr);
-  const String& line = String::Handle(zone(), script.GetLine(line_nr));
-  assembler()->Comment("Line %" Pd " in '%s':\n           %s", line_nr,
-                       instr->env()->function().ToFullyQualifiedCString(),
-                       line.ToCString());
+  if (script.GetTokenLocation(source.token_pos, &line_nr)) {
+    const String& line = String::Handle(zone(), script.GetLine(line_nr));
+    assembler()->Comment("Line %" Pd " in '%s':\n           %s", line_nr,
+                         function.ToFullyQualifiedCString(), line.ToCString());
+  }
 }
 
 static bool IsPusher(Instruction* instr) {
@@ -553,6 +593,10 @@
     ASSERT(block_order()[1] == flow_graph().graph_entry()->normal_entry());
   }
 
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+  const auto inner_lr_state = ComputeInnerLRState(flow_graph());
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+
   for (intptr_t i = 0; i < block_order().length(); ++i) {
     // Compile the block entry.
     BlockEntryInstr* entry = block_order()[i];
@@ -563,6 +607,16 @@
       continue;
     }
 
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+    // At the start of every non-entry block we expect return address either
+    // to be  spilled into the frame or to be in the LR register.
+    if (entry->IsFunctionEntry() || entry->IsNativeEntry()) {
+      assembler()->set_lr_state(compiler::LRState::OnEntry());
+    } else {
+      assembler()->set_lr_state(inner_lr_state);
+    }
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+
 #if defined(DEBUG)
     if (!is_optimizing()) {
       FrameStateClear();
@@ -575,7 +629,7 @@
       }
     }
 
-    BeginCodeSourceRange();
+    BeginCodeSourceRange(entry->source());
     ASSERT(pending_deoptimization_env_ == NULL);
     pending_deoptimization_env_ = entry->env();
     set_current_instruction(entry);
@@ -584,7 +638,7 @@
     StatsEnd(entry);
     set_current_instruction(nullptr);
     pending_deoptimization_env_ = NULL;
-    EndCodeSourceRange(entry->token_pos());
+    EndCodeSourceRange(entry->source());
 
     if (skip_body_compilation()) {
       ASSERT(entry == flow_graph().graph_entry()->normal_entry());
@@ -597,9 +651,6 @@
       set_current_instruction(instr);
       StatsBegin(instr);
 
-      // Compose intervals.
-      code_source_map_builder_->StartInliningInterval(assembler()->CodeSize(),
-                                                      instr->inlining_id());
       if (FLAG_code_comments || FLAG_disassemble ||
           FLAG_disassemble_optimized) {
         if (FLAG_source_lines) {
@@ -610,7 +661,7 @@
       if (instr->IsParallelMove()) {
         parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove());
       } else {
-        BeginCodeSourceRange();
+        BeginCodeSourceRange(instr->source());
         EmitInstructionPrologue(instr);
         ASSERT(pending_deoptimization_env_ == NULL);
         pending_deoptimization_env_ = instr->env();
@@ -624,7 +675,7 @@
         } else {
           EmitInstructionEpilogue(instr);
         }
-        EndCodeSourceRange(instr->token_pos());
+        EndCodeSourceRange(instr->source());
       }
 
 #if defined(DEBUG)
@@ -701,25 +752,39 @@
 }
 
 void FlowGraphCompiler::GenerateDeferredCode() {
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+  const auto lr_state = ComputeInnerLRState(flow_graph());
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+
   for (intptr_t i = 0; i < slow_path_code_.length(); i++) {
     SlowPathCode* const slow_path = slow_path_code_[i];
     const CombinedCodeStatistics::EntryCounter stats_tag =
         CombinedCodeStatistics::SlowPathCounterFor(
             slow_path->instruction()->tag());
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+    assembler()->set_lr_state(lr_state);
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
     set_current_instruction(slow_path->instruction());
     SpecialStatsBegin(stats_tag);
-    BeginCodeSourceRange();
+    BeginCodeSourceRange(slow_path->instruction()->source());
     DEBUG_ONLY(current_instruction_ = slow_path->instruction());
     slow_path->GenerateCode(this);
     DEBUG_ONLY(current_instruction_ = nullptr);
-    EndCodeSourceRange(slow_path->instruction()->token_pos());
+    EndCodeSourceRange(slow_path->instruction()->source());
     SpecialStatsEnd(stats_tag);
     set_current_instruction(nullptr);
   }
+  // All code generated by deferred deopt info is treated as in the root
+  // function.
+  const InstructionSource deopt_source(TokenPosition::kDeferredDeoptInfo,
+                                       /*inlining_id=*/0);
   for (intptr_t i = 0; i < deopt_infos_.length(); i++) {
-    BeginCodeSourceRange();
+    BeginCodeSourceRange(deopt_source);
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+    assembler()->set_lr_state(lr_state);
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
     deopt_infos_[i]->GenerateCode(this, i);
-    EndCodeSourceRange(TokenPosition::kDeferredDeoptInfo);
+    EndCodeSourceRange(deopt_source);
   }
 }
 
@@ -738,28 +803,31 @@
   exception_handlers_list_->SetNeedsStackTrace(try_index);
 }
 
-void FlowGraphCompiler::AddDescriptor(PcDescriptorsLayout::Kind kind,
+void FlowGraphCompiler::AddDescriptor(UntaggedPcDescriptors::Kind kind,
                                       intptr_t pc_offset,
                                       intptr_t deopt_id,
-                                      TokenPosition token_pos,
+                                      const InstructionSource& source,
                                       intptr_t try_index,
                                       intptr_t yield_index) {
-  code_source_map_builder_->NoteDescriptor(kind, pc_offset, token_pos);
+  code_source_map_builder_->NoteDescriptor(kind, pc_offset, source);
   // Don't emit deopt-descriptors in AOT mode.
-  if (FLAG_precompiled_mode && (kind == PcDescriptorsLayout::kDeopt)) return;
-  pc_descriptors_list_->AddDescriptor(kind, pc_offset, deopt_id, token_pos,
+  if (FLAG_precompiled_mode && (kind == UntaggedPcDescriptors::kDeopt)) return;
+  // Use the token position of the original call in the root function if source
+  // has an inlining id.
+  const auto& root_pos = code_source_map_builder_->RootPosition(source);
+  pc_descriptors_list_->AddDescriptor(kind, pc_offset, deopt_id, root_pos,
                                       try_index, yield_index);
 }
 
 // Uses current pc position and try-index.
-void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptorsLayout::Kind kind,
+void FlowGraphCompiler::AddCurrentDescriptor(UntaggedPcDescriptors::Kind kind,
                                              intptr_t deopt_id,
-                                             TokenPosition token_pos) {
-  AddDescriptor(kind, assembler()->CodeSize(), deopt_id, token_pos,
+                                             const InstructionSource& source) {
+  AddDescriptor(kind, assembler()->CodeSize(), deopt_id, source,
                 CurrentTryIndex());
 }
 
-void FlowGraphCompiler::AddNullCheck(TokenPosition token_pos,
+void FlowGraphCompiler::AddNullCheck(const InstructionSource& source,
                                      const String& name) {
 #if defined(DART_PRECOMPILER)
   // If we are generating an AOT snapshot and have DWARF stack traces enabled,
@@ -770,7 +838,7 @@
 #endif
   const intptr_t name_index =
       assembler()->object_pool_builder().FindObject(name);
-  code_source_map_builder_->NoteNullCheck(assembler()->CodeSize(), token_pos,
+  code_source_map_builder_->NoteNullCheck(assembler()->CodeSize(), source,
                                           name_index);
 }
 
@@ -1133,7 +1201,7 @@
 ArrayPtr FlowGraphCompiler::CreateDeoptInfo(compiler::Assembler* assembler) {
   // No deopt information if we precompile (no deoptimization allowed).
   if (FLAG_precompiled_mode) {
-    return Array::empty_array().raw();
+    return Array::empty_array().ptr();
   }
   // For functions with optional arguments, all incoming arguments are copied
   // to spill slots. The deoptimization environment does not track them.
@@ -1144,7 +1212,7 @@
 
   intptr_t deopt_info_table_size = DeoptTable::SizeFor(deopt_infos_.length());
   if (deopt_info_table_size == 0) {
-    return Object::empty_array().raw();
+    return Object::empty_array().ptr();
   } else {
     const Array& array =
         Array::Handle(Array::New(deopt_info_table_size, Heap::kOld));
@@ -1158,7 +1226,7 @@
           deopt_infos_[i]->reason(), deopt_infos_[i]->flags());
       DeoptTable::SetEntry(array, i, offset, info, reason_and_flags);
     }
-    return array.raw();
+    return array.ptr();
   }
 }
 
@@ -1188,8 +1256,8 @@
     // descriptor for IrregexpFunction.
     ASSERT(parsed_function().scope() == nullptr);
     var_descs = LocalVarDescriptors::New(1);
-    LocalVarDescriptorsLayout::VarInfo info;
-    info.set_kind(LocalVarDescriptorsLayout::kSavedCurrentContext);
+    UntaggedLocalVarDescriptors::VarInfo info;
+    info.set_kind(UntaggedLocalVarDescriptors::kSavedCurrentContext);
     info.scope_id = 0;
     info.begin_pos = TokenPosition::kMinSource;
     info.end_pos = TokenPosition::kMinSource;
@@ -1277,6 +1345,8 @@
 }
 
 bool FlowGraphCompiler::TryIntrinsifyHelper() {
+  ASSERT(!flow_graph().IsCompiledForOsr());
+
   compiler::Label exit;
   set_intrinsic_slow_path_label(&exit);
 
@@ -1320,14 +1390,14 @@
   return complete;
 }
 
-void FlowGraphCompiler::GenerateStubCall(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateStubCall(const InstructionSource& source,
                                          const Code& stub,
-                                         PcDescriptorsLayout::Kind kind,
+                                         UntaggedPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          intptr_t deopt_id,
                                          Environment* env) {
   EmitCallToStub(stub);
-  EmitCallsiteMetadata(token_pos, deopt_id, kind, locs, env);
+  EmitCallsiteMetadata(source, deopt_id, kind, locs, env);
 }
 
 static const Code& StubEntryFor(const ICData& ic_data, bool optimized) {
@@ -1359,7 +1429,7 @@
 }
 
 void FlowGraphCompiler::GenerateInstanceCall(intptr_t deopt_id,
-                                             TokenPosition token_pos,
+                                             const InstructionSource& source,
                                              LocationSummary* locs,
                                              const ICData& ic_data_in,
                                              Code::EntryKind entry_kind,
@@ -1367,7 +1437,7 @@
   ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original());
   if (FLAG_precompiled_mode) {
     ic_data = ic_data.AsUnaryClassChecks();
-    EmitInstanceCallAOT(ic_data, deopt_id, token_pos, locs, entry_kind,
+    EmitInstanceCallAOT(ic_data, deopt_id, source, locs, entry_kind,
                         receiver_can_be_smi);
     return;
   }
@@ -1377,22 +1447,22 @@
     // function entry.
     ASSERT(may_reoptimize() || flow_graph().IsCompiledForOsr());
     EmitOptimizedInstanceCall(StubEntryFor(ic_data, /*optimized=*/true),
-                              ic_data, deopt_id, token_pos, locs, entry_kind);
+                              ic_data, deopt_id, source, locs, entry_kind);
     return;
   }
 
   if (is_optimizing()) {
-    EmitMegamorphicInstanceCall(ic_data_in, deopt_id, token_pos, locs,
+    EmitMegamorphicInstanceCall(ic_data_in, deopt_id, source, locs,
                                 kInvalidTryIndex);
     return;
   }
 
   EmitInstanceCallJIT(StubEntryFor(ic_data, /*optimized=*/false), ic_data,
-                      deopt_id, token_pos, locs, entry_kind);
+                      deopt_id, source, locs, entry_kind);
 }
 
 void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id,
-                                           TokenPosition token_pos,
+                                           const InstructionSource& source,
                                            const Function& function,
                                            ArgumentsInfo args_info,
                                            LocationSummary* locs,
@@ -1413,21 +1483,21 @@
   // optimized static calls.
   if (is_optimizing() && (!ForcedOptimization() || FLAG_precompiled_mode)) {
     EmitOptimizedStaticCall(function, arguments_descriptor,
-                            args_info.size_with_type_args, deopt_id, token_pos,
+                            args_info.size_with_type_args, deopt_id, source,
                             locs, entry_kind);
   } else {
-    ICData& call_ic_data = ICData::ZoneHandle(zone(), ic_data.raw());
+    ICData& call_ic_data = ICData::ZoneHandle(zone(), ic_data.ptr());
     if (call_ic_data.IsNull()) {
       const intptr_t kNumArgsChecked = 0;
       call_ic_data =
           GetOrAddStaticCallICData(deopt_id, function, arguments_descriptor,
                                    kNumArgsChecked, rebind_rule)
-              ->raw();
+              ->ptr();
       call_ic_data = call_ic_data.Original();
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRewind, deopt_id, token_pos);
-    EmitUnoptimizedStaticCall(args_info.size_with_type_args, deopt_id,
-                              token_pos, locs, call_ic_data, entry_kind);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRewind, deopt_id, source);
+    EmitUnoptimizedStaticCall(args_info.size_with_type_args, deopt_id, source,
+                              locs, call_ic_data, entry_kind);
   }
 }
 
@@ -1619,6 +1689,7 @@
         result_location = locs->in(0);
         break;
       case Location::kRequiresFpuRegister:
+      case Location::kRequiresStackSlot:
         UNREACHABLE();
         break;
     }
@@ -1635,15 +1706,20 @@
 
 void ParallelMoveResolver::EmitNativeCode(ParallelMoveInstr* parallel_move) {
   ASSERT(moves_.is_empty());
+
   // Build up a worklist of moves.
   BuildInitialMoveList(parallel_move);
 
+  const InstructionSource& move_source = InstructionSource(
+      TokenPosition::kParallelMove, parallel_move->inlining_id());
   for (int i = 0; i < moves_.length(); ++i) {
     const MoveOperands& move = *moves_[i];
     // Skip constants to perform them last.  They don't block other moves
     // and skipping such moves with register destinations keeps those
     // registers free for the whole algorithm.
-    if (!move.IsEliminated() && !move.src().IsConstant()) PerformMove(i);
+    if (!move.IsEliminated() && !move.src().IsConstant()) {
+      PerformMove(move_source, i);
+    }
   }
 
   // Perform the moves with constant sources.
@@ -1651,9 +1727,9 @@
     const MoveOperands& move = *moves_[i];
     if (!move.IsEliminated()) {
       ASSERT(move.src().IsConstant());
-      compiler_->BeginCodeSourceRange();
+      compiler_->BeginCodeSourceRange(move_source);
       EmitMove(i);
-      compiler_->EndCodeSourceRange(TokenPosition::kParallelMove);
+      compiler_->EndCodeSourceRange(move_source);
     }
   }
 
@@ -1672,7 +1748,8 @@
   }
 }
 
-void ParallelMoveResolver::PerformMove(int index) {
+void ParallelMoveResolver::PerformMove(const InstructionSource& source,
+                                       int index) {
   // Each call to this function performs a move and deletes it from the move
   // graph.  We first recursively perform any move blocking this one.  We
   // mark a move as "pending" on entry to PerformMove in order to detect
@@ -1705,7 +1782,7 @@
       // only a single incoming edge to an operand, this move must also be
       // involved in the same cycle.  In that case, the blocking move will
       // be created but will be "pending" when we return from PerformMove.
-      PerformMove(i);
+      PerformMove(source, i);
     }
   }
 
@@ -1727,17 +1804,17 @@
     const MoveOperands& other_move = *moves_[i];
     if (other_move.Blocks(destination)) {
       ASSERT(other_move.IsPending());
-      compiler_->BeginCodeSourceRange();
+      compiler_->BeginCodeSourceRange(source);
       EmitSwap(index);
-      compiler_->EndCodeSourceRange(TokenPosition::kParallelMove);
+      compiler_->EndCodeSourceRange(source);
       return;
     }
   }
 
   // This move is not blocked.
-  compiler_->BeginCodeSourceRange();
+  compiler_->BeginCodeSourceRange(source);
   EmitMove(index);
-  compiler_->EndCodeSourceRange(TokenPosition::kParallelMove);
+  compiler_->EndCodeSourceRange(source);
 }
 
 void ParallelMoveResolver::EmitMove(int index) {
@@ -1896,12 +1973,12 @@
       ((*deopt_id_to_ic_data_)[deopt_id] != NULL)) {
     const ICData* res = (*deopt_id_to_ic_data_)[deopt_id];
     ASSERT(res->deopt_id() == deopt_id);
-    ASSERT(res->target_name() == target_name.raw());
+    ASSERT(res->target_name() == target_name.ptr());
     ASSERT(res->NumArgsTested() == num_args_tested);
     ASSERT(res->TypeArgsLen() ==
            ArgumentsDescriptor(arguments_descriptor).TypeArgsLen());
     ASSERT(!res->is_static_call());
-    ASSERT(res->receivers_static_type() == receiver_type.raw());
+    ASSERT(res->receivers_static_type() == receiver_type.ptr());
     return res;
   }
 
@@ -2012,13 +2089,13 @@
   }
 }
 
-void FlowGraphCompiler::BeginCodeSourceRange() {
-  code_source_map_builder_->BeginCodeSourceRange(assembler()->CodeSize());
+void FlowGraphCompiler::BeginCodeSourceRange(const InstructionSource& source) {
+  code_source_map_builder_->BeginCodeSourceRange(assembler()->CodeSize(),
+                                                 source);
 }
 
-void FlowGraphCompiler::EndCodeSourceRange(TokenPosition token_pos) {
-  code_source_map_builder_->EndCodeSourceRange(assembler()->CodeSize(),
-                                               token_pos);
+void FlowGraphCompiler::EndCodeSourceRange(const InstructionSource& source) {
+  code_source_map_builder_->EndCodeSourceRange(assembler()->CodeSize(), source);
 }
 
 const CallTargets* FlowGraphCompiler::ResolveCallTargetsForReceiverCid(
@@ -2044,13 +2121,13 @@
                                         const ArgumentsDescriptor& args_desc,
                                         Function* fn_return,
                                         bool* class_is_abstract_return) {
-  Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto class_table = thread->isolate_group()->class_table();
   if (class_id < 0) return false;
-  if (class_id >= isolate->class_table()->NumCids()) return false;
+  if (class_id >= class_table->NumCids()) return false;
 
-  ClassPtr raw_class = isolate->class_table()->At(class_id);
+  ClassPtr raw_class = class_table->At(class_id);
   if (raw_class == nullptr) return false;
   Class& cls = Class::Handle(zone, raw_class);
   if (cls.IsNull()) return false;
@@ -2065,7 +2142,7 @@
       Function::Handle(zone, Resolver::ResolveDynamicForReceiverClass(
                                  cls, name, args_desc, allow_add));
   if (target_function.IsNull()) return false;
-  *fn_return = target_function.raw();
+  *fn_return = target_function.ptr();
   return true;
 }
 
@@ -2074,7 +2151,7 @@
     const CallTargets& targets,
     ArgumentsInfo args_info,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     bool complete,
     intptr_t total_ic_calls,
@@ -2087,7 +2164,7 @@
     EmitTestAndCall(targets, call->function_name(), args_info,
                     deopt,  // No cid match.
                     &ok,    // Found cid.
-                    deopt_id, token_pos, locs, complete, total_ic_calls,
+                    deopt_id, source, locs, complete, total_ic_calls,
                     call->entry_kind());
     assembler()->Bind(&ok);
   } else {
@@ -2096,13 +2173,13 @@
       EmitTestAndCall(targets, call->function_name(), args_info,
                       NULL,  // No cid match.
                       &ok,   // Found cid.
-                      deopt_id, token_pos, locs, true, total_ic_calls,
+                      deopt_id, source, locs, true, total_ic_calls,
                       call->entry_kind());
       assembler()->Bind(&ok);
     } else {
       const ICData& unary_checks =
           ICData::ZoneHandle(zone(), call->ic_data()->AsUnaryClassChecks());
-      EmitInstanceCallAOT(unary_checks, deopt_id, token_pos, locs,
+      EmitInstanceCallAOT(unary_checks, deopt_id, source, locs,
                           call->entry_kind(), receiver_can_be_smi);
     }
   }
@@ -2127,7 +2204,7 @@
                                         compiler::Label* failed,
                                         compiler::Label* match_found,
                                         intptr_t deopt_id,
-                                        TokenPosition token_index,
+                                        const InstructionSource& source_index,
                                         LocationSummary* locs,
                                         bool complete,
                                         intptr_t total_ic_calls,
@@ -2179,8 +2256,9 @@
     // Do not use the code from the function, but let the code be patched so
     // that we can record the outgoing edges to other code.
     const Function& function = *targets.TargetAt(smi_case)->target;
-    GenerateStaticDartCall(deopt_id, token_index, PcDescriptorsLayout::kOther,
-                           locs, function, entry_kind);
+    GenerateStaticDartCall(deopt_id, source_index,
+                           UntaggedPcDescriptors::kOther, locs, function,
+                           entry_kind);
     __ Drop(args_info.size_with_type_args);
     if (match_found != NULL) {
       __ Jump(match_found);
@@ -2229,8 +2307,9 @@
     // Do not use the code from the function, but let the code be patched so
     // that we can record the outgoing edges to other code.
     const Function& function = *targets.TargetAt(i)->target;
-    GenerateStaticDartCall(deopt_id, token_index, PcDescriptorsLayout::kOther,
-                           locs, function, entry_kind);
+    GenerateStaticDartCall(deopt_id, source_index,
+                           UntaggedPcDescriptors::kOther, locs, function,
+                           entry_kind);
     __ Drop(args_info.size_with_type_args);
     if (!is_last_check || add_megamorphic_call) {
       __ Jump(match_found);
@@ -2240,7 +2319,7 @@
   if (add_megamorphic_call) {
     int try_index = kInvalidTryIndex;
     EmitMegamorphicInstanceCall(function_name, arguments_descriptor, deopt_id,
-                                token_index, locs, try_index);
+                                source_index, locs, try_index);
   }
 }
 
@@ -2328,7 +2407,7 @@
 //
 // See [GenerateInlineInstanceof] for calling convention.
 SubtypeTestCachePtr FlowGraphCompiler::GenerateFunctionTypeTest(
-    TokenPosition token_pos,
+    const InstructionSource& source,
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
@@ -2359,14 +2438,14 @@
 // may fall through to it. Otherwise, this inline code will jump to the label
 // is_instance or to the label is_not_instance.
 SubtypeTestCachePtr FlowGraphCompiler::GenerateInlineInstanceof(
-    TokenPosition token_pos,
+    const InstructionSource& source,
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
   __ Comment("InlineInstanceof");
 
   if (type.IsFunctionType()) {
-    return GenerateFunctionTypeTest(token_pos, type, is_instance_lbl,
+    return GenerateFunctionTypeTest(source, type, is_instance_lbl,
                                     is_not_instance_lbl);
   }
 
@@ -2377,21 +2456,21 @@
     // a parameterized class.
     if (type_class.NumTypeArguments() > 0) {
       return GenerateInstantiatedTypeWithArgumentsTest(
-          token_pos, type, is_instance_lbl, is_not_instance_lbl);
+          source, type, is_instance_lbl, is_not_instance_lbl);
       // Fall through to runtime call.
     }
     const bool has_fall_through = GenerateInstantiatedTypeNoArgumentsTest(
-        token_pos, type, is_instance_lbl, is_not_instance_lbl);
+        source, type, is_instance_lbl, is_not_instance_lbl);
     if (has_fall_through) {
       // If test non-conclusive so far, try the inlined type-test cache.
       // 'type' is known at compile time.
       return GenerateSubtype1TestCacheLookup(
-          token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
+          source, type_class, is_instance_lbl, is_not_instance_lbl);
     } else {
       return SubtypeTestCache::null();
     }
   }
-  return GenerateUninstantiatedTypeTest(token_pos, type, is_instance_lbl,
+  return GenerateUninstantiatedTypeTest(source, type, is_instance_lbl,
                                         is_not_instance_lbl);
 }
 
@@ -2404,8 +2483,7 @@
   AbstractType& bound = AbstractType::Handle(zone(), type_param.bound());
   bound = bound.UnwrapFutureOr();
   return !bound.IsTopTypeForSubtyping() && !bound.IsObjectType() &&
-                 !bound.IsFunctionType() && !bound.IsDartFunctionType() &&
-                 bound.IsType()
+                 !bound.IsDartFunctionType() && bound.IsType()
              ? kTestTypeFiveArgs
              : kTestTypeSevenArgs;
 }
@@ -2417,7 +2495,7 @@
 //
 // See [GenerateInlineInstanceof] for calling convention.
 SubtypeTestCachePtr FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
-    TokenPosition token_pos,
+    const InstructionSource& source,
     const Class& type_class,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
@@ -2432,7 +2510,7 @@
   // supertype may yield a wrong result for Null in NNBD strong mode (because
   // Null also extends Object).
   if (!type_class.IsObjectClass() ||
-      !Isolate::Current()->use_strict_null_safety_checks()) {
+      !IsolateGroup::Current()->use_strict_null_safety_checks()) {
     // We don't use TypeTestABI::kScratchReg for the first scratch register as
     // it is not defined on IA32. Instead, we use the subtype test cache
     // register, as it is clobbered by the subtype test cache stub call anyway.
@@ -2475,7 +2553,7 @@
 // See [GenerateInlineInstanceof] for calling convention.
 SubtypeTestCachePtr
 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
-    TokenPosition token_pos,
+    const InstructionSource& source,
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
@@ -2509,8 +2587,8 @@
     if (IsListClass(type_class)) {
       GenerateListTypeCheck(kScratchReg, is_instance_lbl);
     }
-    return GenerateSubtype1TestCacheLookup(
-        token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
+    return GenerateSubtype1TestCacheLookup(source, type_class, is_instance_lbl,
+                                           is_not_instance_lbl);
   }
   // If one type argument only, check if type argument is a top type.
   if (type_arguments.Length() == 1) {
@@ -2519,7 +2597,7 @@
     if (tp_argument.IsTopTypeForSubtyping()) {
       // Instance class test only necessary.
       return GenerateSubtype1TestCacheLookup(
-          token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
+          source, type_class, is_instance_lbl, is_not_instance_lbl);
     }
   }
 
@@ -2539,7 +2617,7 @@
 //
 // Uses kScratchReg, so this implementation cannot be shared with IA32.
 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
-    TokenPosition token_pos,
+    const InstructionSource& source,
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
@@ -2597,7 +2675,7 @@
 //
 // See [GenerateInlineInstanceof] for calling convention.
 SubtypeTestCachePtr FlowGraphCompiler::GenerateUninstantiatedTypeTest(
-    TokenPosition token_pos,
+    const InstructionSource& source,
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
@@ -2620,16 +2698,17 @@
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ CompareObject(kTypeArgumentsReg, Object::null_object());
     __ BranchIf(EQUAL, is_instance_lbl);
-    __ LoadFieldFromOffset(kScratchReg, kTypeArgumentsReg,
-                           TypeArguments::type_at_offset(type_param.index()));
+    __ LoadFieldFromOffset(
+        kScratchReg, kTypeArgumentsReg,
+        compiler::target::TypeArguments::type_at_offset(type_param.index()));
     // kScratchReg: Concrete type of type.
     // Check if type argument is dynamic, Object?, or void.
     __ CompareObject(kScratchReg, Object::dynamic_type());
     __ BranchIf(EQUAL, is_instance_lbl);
     __ CompareObject(
         kScratchReg,
-        Type::ZoneHandle(zone(),
-                         isolate()->object_store()->nullable_object_type()));
+        Type::ZoneHandle(
+            zone(), isolate_group()->object_store()->nullable_object_type()));
     __ BranchIf(EQUAL, is_instance_lbl);
     __ CompareObject(kScratchReg, Object::void_type());
     __ BranchIf(EQUAL, is_instance_lbl);
@@ -2679,7 +2758,7 @@
 // - kFunctionTypeArgumentsReg: function type arguments or raw_null.
 // Returns:
 // - true or false in kInstanceOfResultReg.
-void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateInstanceOf(const InstructionSource& source,
                                            intptr_t deopt_id,
                                            const AbstractType& type,
                                            LocationSummary* locs) {
@@ -2708,7 +2787,7 @@
   // kInstanceReg, kInstantiatorTypeArgumentsReg, and kFunctionTypeArgumentsReg
   // are preserved across the call.
   test_cache =
-      GenerateInlineInstanceof(token_pos, type, &is_instance, &is_not_instance);
+      GenerateInlineInstanceof(source, type, &is_instance, &is_not_instance);
 
   // test_cache is null if there is no fall-through.
   compiler::Label done;
@@ -2716,8 +2795,8 @@
     // Generate Runtime call.
     __ LoadUniqueObject(TypeTestABI::kDstTypeReg, type);
     __ LoadUniqueObject(TypeTestABI::kSubtypeTestCacheReg, test_cache);
-    GenerateStubCall(token_pos, StubCode::InstanceOf(),
-                     /*kind=*/PcDescriptorsLayout::kOther, locs, deopt_id);
+    GenerateStubCall(source, StubCode::InstanceOf(),
+                     /*kind=*/UntaggedPcDescriptors::kOther, locs, deopt_id);
     __ Jump(&done, compiler::Assembler::kNearJump);
   }
   __ Bind(&is_not_instance);
@@ -2759,7 +2838,7 @@
   }
   GenerateBoolToJump(TypeTestABI::kSubtypeTestCacheResultReg, is_instance_lbl,
                      is_not_instance_lbl);
-  return type_test_cache.raw();
+  return type_test_cache.ptr();
 }
 
 // Generates an assignable check for a given object. Emits no code if the
@@ -2777,12 +2856,13 @@
 //
 // Performance notes: positive checks must be quick, negative checks can be slow
 // as they throw an exception.
-void FlowGraphCompiler::GenerateAssertAssignable(CompileType* receiver_type,
-                                                 TokenPosition token_pos,
-                                                 intptr_t deopt_id,
-                                                 const String& dst_name,
-                                                 LocationSummary* locs) {
-  ASSERT(!token_pos.IsClassifying());
+void FlowGraphCompiler::GenerateAssertAssignable(
+    CompileType* receiver_type,
+    const InstructionSource& source,
+    intptr_t deopt_id,
+    const String& dst_name,
+    LocationSummary* locs) {
+  ASSERT(!source.token_pos.IsClassifying());
   ASSERT(CheckAssertAssignableTypeTestingABILocations(*locs));
 
   // Non-null if we have a constant destination type.
@@ -2812,14 +2892,14 @@
     }
   }
 
-  GenerateTTSCall(token_pos, deopt_id, type_reg, dst_type, dst_name, locs);
+  GenerateTTSCall(source, deopt_id, type_reg, dst_type, dst_name, locs);
   __ Bind(&done);
 }
 
 // Generates a call to the type testing stub for the type in [reg_with_type].
 // Provide a non-null [dst_type] and [dst_name] if they are known at compile
 // time.
-void FlowGraphCompiler::GenerateTTSCall(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateTTSCall(const InstructionSource& source,
                                         intptr_t deopt_id,
                                         Register reg_with_type,
                                         const AbstractType& dst_type,
@@ -2849,9 +2929,9 @@
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeTTSCallTypeTarget(dst_type);
   } else {
-    GenerateIndirectTTSCall(reg_with_type, sub_type_cache_index);
+    GenerateIndirectTTSCall(assembler(), reg_with_type, sub_type_cache_index);
   }
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kOther, locs);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kOther, locs);
 }
 
 // Optimize assignable type check by adding inlined tests for:
@@ -2910,7 +2990,7 @@
   if (dst_type.IsObjectType()) {
     // Special case: non-nullable Object.
     ASSERT(dst_type.IsNonNullable() &&
-           isolate()->use_strict_null_safety_checks());
+           isolate_group()->use_strict_null_safety_checks());
     __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
     __ BranchIf(NOT_EQUAL, done);
     // Fall back to type testing stub in caller to throw the exception.
@@ -2932,7 +3012,7 @@
     // Special case: Instantiate the type parameter on the caller side, invoking
     // the TTS of the corresponding type parameter in the caller.
     const TypeParameter& type_param = TypeParameter::Cast(dst_type);
-    if (isolate()->use_strict_null_safety_checks() &&
+    if (isolate_group()->use_strict_null_safety_checks() &&
         !type_param.IsNonNullable()) {
       // If the type parameter is nullable when running in strong mode, we need
       // to handle null before calling the TTS because the type parameter may be
@@ -2959,6 +3039,10 @@
     return output_dst_type();
   }
 
+  if (dst_type.IsFunctionType()) {
+    return output_dst_type();
+  }
+
   if (auto const hi = thread()->hierarchy_info()) {
     const Class& type_class = Class::Handle(zone(), dst_type.type_class());
 
@@ -3092,9 +3176,9 @@
     __ CallRuntime(runtime_entry_, num_args);
   }
   const intptr_t deopt_id = instruction()->deopt_id();
-  compiler->AddDescriptor(PcDescriptorsLayout::kOther,
+  compiler->AddDescriptor(UntaggedPcDescriptors::kOther,
                           compiler->assembler()->CodeSize(), deopt_id,
-                          instruction()->token_pos(), try_index_);
+                          instruction()->source(), try_index_);
   AddMetadataForRuntimeCall(compiler);
   compiler->RecordSafepoint(locs, num_args);
   if (!FLAG_precompiled_mode || (try_index_ != kInvalidTryIndex) ||
@@ -3140,7 +3224,7 @@
 CodePtr NullErrorSlowPath::GetStub(FlowGraphCompiler* compiler,
                                    CheckNullInstr::ExceptionType exception_type,
                                    bool save_fpu_registers) {
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   switch (exception_type) {
     case CheckNullInstr::kNoSuchMethod:
       return save_fpu_registers
@@ -3195,7 +3279,7 @@
   const Field& original_field = Field::ZoneHandle(
       instruction()->AsLoadField()->slot().field().Original());
   __ LoadObject(LateInitializationErrorABI::kFieldReg, original_field);
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& stub = Code::ZoneHandle(
       compiler->zone(),
       save_fpu_registers
@@ -3339,8 +3423,6 @@
   EmitNativeMoveArchitecture(destination, source);
 }
 
-// TODO(dartbug.com/36730): Remove this if PairLocations can be converted
-// into NativeLocations.
 void FlowGraphCompiler::EmitMoveToNative(
     const compiler::ffi::NativeLocation& dst,
     Location src_loc,
@@ -3359,8 +3441,6 @@
   }
 }
 
-// TODO(dartbug.com/36730): Remove this if PairLocations can be converted
-// into NativeLocations.
 void FlowGraphCompiler::EmitMoveFromNative(
     Location dst_loc,
     Representation dst_type,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index ca9a298..7a145d1 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -134,7 +134,7 @@
 
   // Perform the move at the moves_ index in question (possibly requiring
   // other moves to satisfy dependencies).
-  void PerformMove(int index);
+  void PerformMove(const InstructionSource& source, int index);
 
   // Emit a move and remove it from the move graph.
   void EmitMove(int index);
@@ -461,7 +461,9 @@
   // speculative optimizations and call patching are disabled.
   bool ForcedOptimization() const { return function().ForceOptimize(); }
 
-  const FlowGraph& flow_graph() const { return flow_graph_; }
+  const FlowGraph& flow_graph() const {
+    return intrinsic_mode() ? *intrinsic_flow_graph_ : flow_graph_;
+  }
 
   BlockEntryInstr* current_block() const { return current_block_; }
   void set_current_block(BlockEntryInstr* value) { current_block_ = value; }
@@ -486,6 +488,10 @@
   void ExitIntrinsicMode();
   bool intrinsic_mode() const { return intrinsic_mode_; }
 
+  void set_intrinsic_flow_graph(const FlowGraph& flow_graph) {
+    intrinsic_flow_graph_ = &flow_graph;
+  }
+
   void set_intrinsic_slow_path_label(compiler::Label* label) {
     ASSERT(intrinsic_slow_path_label_ == nullptr || label == nullptr);
     intrinsic_slow_path_label_ = label;
@@ -583,7 +589,7 @@
       const LocationSummary& locs);
 
   void GenerateAssertAssignable(CompileType* receiver_type,
-                                TokenPosition token_pos,
+                                const InstructionSource& source,
                                 intptr_t deopt_id,
                                 const String& dst_name,
                                 LocationSummary* locs);
@@ -593,57 +599,58 @@
                                                const AbstractType& dst_type,
                                                compiler::Label* done);
 
-  void GenerateTTSCall(TokenPosition token_pos,
+  void GenerateTTSCall(const InstructionSource& source,
                        intptr_t deopt_id,
                        Register reg_with_type,
                        const AbstractType& dst_type,
                        const String& dst_name,
                        LocationSummary* locs);
 
-  void GenerateIndirectTTSCall(Register reg_with_type,
-                               intptr_t sub_type_cache_index);
+  static void GenerateIndirectTTSCall(compiler::Assembler* assembler,
+                                      Register reg_with_type,
+                                      intptr_t sub_type_cache_index);
 #endif
 
-  void GenerateRuntimeCall(TokenPosition token_pos,
+  void GenerateRuntimeCall(const InstructionSource& source,
                            intptr_t deopt_id,
                            const RuntimeEntry& entry,
                            intptr_t argument_count,
                            LocationSummary* locs);
 
-  void GenerateStubCall(TokenPosition token_pos,
+  void GenerateStubCall(const InstructionSource& source,
                         const Code& stub,
-                        PcDescriptorsLayout::Kind kind,
+                        UntaggedPcDescriptors::Kind kind,
                         LocationSummary* locs,
                         intptr_t deopt_id = DeoptId::kNone,
                         Environment* env = nullptr);
 
-  void GeneratePatchableCall(TokenPosition token_pos,
+  void GeneratePatchableCall(const InstructionSource& source,
                              const Code& stub,
-                             PcDescriptorsLayout::Kind kind,
+                             UntaggedPcDescriptors::Kind kind,
                              LocationSummary* locs);
 
   void GenerateDartCall(intptr_t deopt_id,
-                        TokenPosition token_pos,
+                        const InstructionSource& source,
                         const Code& stub,
-                        PcDescriptorsLayout::Kind kind,
+                        UntaggedPcDescriptors::Kind kind,
                         LocationSummary* locs,
                         Code::EntryKind entry_kind = Code::EntryKind::kNormal);
 
   void GenerateStaticDartCall(
       intptr_t deopt_id,
-      TokenPosition token_pos,
-      PcDescriptorsLayout::Kind kind,
+      const InstructionSource& source,
+      UntaggedPcDescriptors::Kind kind,
       LocationSummary* locs,
       const Function& target,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal);
 
-  void GenerateInstanceOf(TokenPosition token_pos,
+  void GenerateInstanceOf(const InstructionSource& source,
                           intptr_t deopt_id,
                           const AbstractType& type,
                           LocationSummary* locs);
 
   void GenerateInstanceCall(intptr_t deopt_id,
-                            TokenPosition token_pos,
+                            const InstructionSource& source,
                             LocationSummary* locs,
                             const ICData& ic_data,
                             Code::EntryKind entry_kind,
@@ -651,7 +658,7 @@
 
   void GenerateStaticCall(
       intptr_t deopt_id,
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const Function& function,
       ArgumentsInfo args_info,
       LocationSummary* locs,
@@ -695,14 +702,14 @@
       const Code& stub,
       const ICData& ic_data,
       intptr_t deopt_id,
-      TokenPosition token_pos,
+      const InstructionSource& source,
       LocationSummary* locs,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal);
 
   void EmitInstanceCallJIT(const Code& stub,
                            const ICData& ic_data,
                            intptr_t deopt_id,
-                           TokenPosition token_pos,
+                           const InstructionSource& source,
                            LocationSummary* locs,
                            Code::EntryKind entry_kind);
 
@@ -710,7 +717,7 @@
                                    const CallTargets& targets,
                                    ArgumentsInfo args_info,
                                    intptr_t deopt_id,
-                                   TokenPosition token_pos,
+                                   const InstructionSource& source,
                                    LocationSummary* locs,
                                    bool complete,
                                    intptr_t total_call_count,
@@ -718,14 +725,14 @@
 
   void EmitMegamorphicInstanceCall(const ICData& icdata,
                                    intptr_t deopt_id,
-                                   TokenPosition token_pos,
+                                   const InstructionSource& source,
                                    LocationSummary* locs,
                                    intptr_t try_index,
                                    intptr_t slow_path_argument_count = 0) {
     const String& name = String::Handle(icdata.target_name());
     const Array& arguments_descriptor =
         Array::Handle(icdata.arguments_descriptor());
-    EmitMegamorphicInstanceCall(name, arguments_descriptor, deopt_id, token_pos,
+    EmitMegamorphicInstanceCall(name, arguments_descriptor, deopt_id, source,
                                 locs, try_index);
   }
 
@@ -733,7 +740,7 @@
   void EmitMegamorphicInstanceCall(const String& function_name,
                                    const Array& arguments_descriptor,
                                    intptr_t deopt_id,
-                                   TokenPosition token_pos,
+                                   const InstructionSource& source,
                                    LocationSummary* locs,
                                    intptr_t try_index,
                                    intptr_t slow_path_argument_count = 0);
@@ -741,7 +748,7 @@
   void EmitInstanceCallAOT(
       const ICData& ic_data,
       intptr_t deopt_id,
-      TokenPosition token_pos,
+      const InstructionSource& source,
       LocationSummary* locs,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal,
       bool receiver_can_be_smi = true);
@@ -752,7 +759,7 @@
                        compiler::Label* failed,
                        compiler::Label* match_found,
                        intptr_t deopt_id,
-                       TokenPosition token_index,
+                       const InstructionSource& source_index,
                        LocationSummary* locs,
                        bool complete,
                        intptr_t total_ic_calls,
@@ -765,12 +772,12 @@
   Condition EmitEqualityRegConstCompare(Register reg,
                                         const Object& obj,
                                         bool needs_number_check,
-                                        TokenPosition token_pos,
+                                        const InstructionSource& source,
                                         intptr_t deopt_id);
   Condition EmitEqualityRegRegCompare(Register left,
                                       Register right,
                                       bool needs_number_check,
-                                      TokenPosition token_pos,
+                                      const InstructionSource& source,
                                       intptr_t deopt_id);
   Condition EmitBoolTest(Register value, BranchLabels labels, bool invert);
 
@@ -793,13 +800,14 @@
   //
   // If [env] is not `nullptr` it will be used instead of the
   // `pending_deoptimization_env`.
-  void EmitCallsiteMetadata(TokenPosition token_pos,
+  void EmitCallsiteMetadata(const InstructionSource& source,
                             intptr_t deopt_id,
-                            PcDescriptorsLayout::Kind kind,
+                            UntaggedPcDescriptors::Kind kind,
                             LocationSummary* locs,
                             Environment* env = nullptr);
 
-  void EmitYieldPositionMetadata(TokenPosition token_pos, intptr_t yield_index);
+  void EmitYieldPositionMetadata(const InstructionSource& source,
+                                 intptr_t yield_index);
 
   void EmitComment(Instruction* instr);
 
@@ -833,19 +841,19 @@
                            const Array& handler_types,
                            bool needs_stacktrace);
   void SetNeedsStackTrace(intptr_t try_index);
-  void AddCurrentDescriptor(PcDescriptorsLayout::Kind kind,
+  void AddCurrentDescriptor(UntaggedPcDescriptors::Kind kind,
                             intptr_t deopt_id,
-                            TokenPosition token_pos);
+                            const InstructionSource& source);
   void AddDescriptor(
-      PcDescriptorsLayout::Kind kind,
+      UntaggedPcDescriptors::Kind kind,
       intptr_t pc_offset,
       intptr_t deopt_id,
-      TokenPosition token_pos,
+      const InstructionSource& source,
       intptr_t try_index,
-      intptr_t yield_index = PcDescriptorsLayout::kInvalidYieldIndex);
+      intptr_t yield_index = UntaggedPcDescriptors::kInvalidYieldIndex);
 
   // Add NullCheck information for the current PC.
-  void AddNullCheck(TokenPosition token_pos, const String& name);
+  void AddNullCheck(const InstructionSource& source, const String& name);
 
   void RecordSafepoint(LocationSummary* locs,
                        intptr_t slow_path_argument_count = 0);
@@ -938,17 +946,18 @@
 
   Thread* thread() const { return thread_; }
   Isolate* isolate() const { return thread_->isolate(); }
+  IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
   Zone* zone() const { return zone_; }
 
   void AddStubCallTarget(const Code& code);
   void AddDispatchTableCallTarget(const compiler::TableSelector* selector);
 
-  ArrayPtr edge_counters_array() const { return edge_counters_array_.raw(); }
+  ArrayPtr edge_counters_array() const { return edge_counters_array_.ptr(); }
 
   ArrayPtr InliningIdToFunction() const;
 
-  void BeginCodeSourceRange();
-  void EndCodeSourceRange(TokenPosition token_pos);
+  void BeginCodeSourceRange(const InstructionSource& source);
+  void EndCodeSourceRange(const InstructionSource& source);
 
   static bool LookupMethodFor(int class_id,
                               const String& name,
@@ -1008,14 +1017,14 @@
       const Array& arguments_descriptor,
       intptr_t size_with_type_args,
       intptr_t deopt_id,
-      TokenPosition token_pos,
+      const InstructionSource& source,
       LocationSummary* locs,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal);
 
   void EmitUnoptimizedStaticCall(
       intptr_t size_with_type_args,
       intptr_t deopt_id,
-      TokenPosition token_pos,
+      const InstructionSource& source,
       LocationSummary* locs,
       const ICData& ic_data,
       Code::EntryKind entry_kind = Code::EntryKind::kNormal);
@@ -1043,37 +1052,37 @@
                      compiler::Label* is_not_instance_lbl);
 
   SubtypeTestCachePtr GenerateInlineInstanceof(
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const AbstractType& type,
       compiler::Label* is_instance_lbl,
       compiler::Label* is_not_instance_lbl);
 
   SubtypeTestCachePtr GenerateInstantiatedTypeWithArgumentsTest(
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const AbstractType& dst_type,
       compiler::Label* is_instance_lbl,
       compiler::Label* is_not_instance_lbl);
 
   bool GenerateInstantiatedTypeNoArgumentsTest(
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const AbstractType& dst_type,
       compiler::Label* is_instance_lbl,
       compiler::Label* is_not_instance_lbl);
 
   SubtypeTestCachePtr GenerateUninstantiatedTypeTest(
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const AbstractType& dst_type,
       compiler::Label* is_instance_lbl,
       compiler::Label* is_not_instance_label);
 
   SubtypeTestCachePtr GenerateFunctionTypeTest(
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const AbstractType& dst_type,
       compiler::Label* is_instance_lbl,
       compiler::Label* is_not_instance_label);
 
   SubtypeTestCachePtr GenerateSubtype1TestCacheLookup(
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const Class& type_class,
       compiler::Label* is_instance_lbl,
       compiler::Label* is_not_instance_lbl);
@@ -1125,7 +1134,7 @@
   void CompactBlocks();
 
   bool IsListClass(const Class& cls) const {
-    return cls.raw() == list_class_.raw();
+    return cls.ptr() == list_class_.ptr();
   }
 
   void EmitSourceLine(Instruction* instr);
@@ -1195,6 +1204,7 @@
   compiler::Assembler* assembler_;
   const ParsedFunction& parsed_function_;
   const FlowGraph& flow_graph_;
+  const FlowGraph* intrinsic_flow_graph_ = nullptr;
   const GrowableArray<BlockEntryInstr*>& block_order_;
 
 #if defined(DEBUG)
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 1d85187..d9a48c0 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -31,7 +31,7 @@
 
 void FlowGraphCompiler::ArchSpecificInitialization() {
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    auto object_store = isolate()->object_store();
+    auto object_store = isolate_group()->object_store();
 
     const auto& stub =
         Code::ZoneHandle(object_store->write_barrier_wrappers_stub());
@@ -198,15 +198,31 @@
   }
 
   ASSERT(deopt_env() != NULL);
-  __ ldr(LR, compiler::Address(
-                 THR, compiler::target::Thread::deoptimize_entry_offset()));
-  __ blx(LR);
-  ASSERT(kReservedCpuRegisters & (1 << LR));
+  __ Call(compiler::Address(
+      THR, compiler::target::Thread::deoptimize_entry_offset()));
   set_pc_offset(assembler->CodeSize());
 #undef __
 }
 
+#define __ assembler->
+// Static methods of FlowGraphCompiler that take an assembler.
+
+void FlowGraphCompiler::GenerateIndirectTTSCall(compiler::Assembler* assembler,
+                                                Register reg_to_call,
+                                                intptr_t sub_type_cache_index) {
+  __ LoadField(
+      TTSInternalRegs::kScratchReg,
+      compiler::FieldAddress(
+          reg_to_call,
+          compiler::target::AbstractType::type_test_stub_entry_point_offset()));
+  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
+                           sub_type_cache_index);
+  __ blx(TTSInternalRegs::kScratchReg);
+}
+
+#undef __
 #define __ assembler()->
+// Instance methods of FlowGraphCompiler.
 
 // Fall through if bool_register contains null.
 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
@@ -224,18 +240,6 @@
   __ Bind(&fall_through);
 }
 
-void FlowGraphCompiler::GenerateIndirectTTSCall(Register reg_to_call,
-                                                intptr_t sub_type_cache_index) {
-  __ LoadField(
-      R9,
-      compiler::FieldAddress(
-          reg_to_call,
-          compiler::target::AbstractType::type_test_stub_entry_point_offset()));
-  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
-                           sub_type_cache_index);
-  __ blx(R9);
-}
-
 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
   if (is_optimizing()) {
     return;
@@ -254,7 +258,7 @@
   ASSERT(extracted_method.IsZoneHandle());
 
   const Code& build_method_extractor = Code::ZoneHandle(
-      isolate()->object_store()->build_method_extractor_code());
+      isolate_group()->object_store()->build_method_extractor_code());
 
   const intptr_t stub_index = __ object_pool_builder().AddObject(
       build_method_extractor, ObjectPool::Patchability::kNotPatchable);
@@ -309,18 +313,31 @@
                   THR, compiler::target::Thread::optimize_entry_offset()),
               GE);
   }
-  __ Comment("Enter frame");
-  if (flow_graph().IsCompiledForOsr()) {
-    const intptr_t extra_slots = ExtraStackSlotsOnOsrEntry();
-    ASSERT(extra_slots >= 0);
-    __ EnterOsrFrame(extra_slots * compiler::target::kWordSize);
-  } else {
-    ASSERT(StackSize() >= 0);
-    __ EnterDartFrame(StackSize() * compiler::target::kWordSize);
+
+  if (flow_graph().graph_entry()->NeedsFrame()) {
+    __ Comment("Enter frame");
+    if (flow_graph().IsCompiledForOsr()) {
+      const intptr_t extra_slots = ExtraStackSlotsOnOsrEntry();
+      ASSERT(extra_slots >= 0);
+      __ EnterOsrFrame(extra_slots * compiler::target::kWordSize);
+    } else {
+      ASSERT(StackSize() >= 0);
+      __ EnterDartFrame(StackSize() * compiler::target::kWordSize);
+    }
+  } else if (FLAG_use_bare_instructions) {
+    assembler()->set_constant_pool_allowed(true);
   }
 }
 
+const InstructionSource& PrologueSource() {
+  static InstructionSource prologue_source(TokenPosition::kDartCodePrologue,
+                                           /*inlining_id=*/0);
+  return prologue_source;
+}
+
 void FlowGraphCompiler::EmitPrologue() {
+  BeginCodeSourceRange(PrologueSource());
+
   EmitFrameEntry();
   ASSERT(assembler()->constant_pool_allowed());
 
@@ -346,7 +363,7 @@
     }
   }
 
-  EndCodeSourceRange(TokenPosition::kDartCodePrologue);
+  EndCodeSourceRange(PrologueSource());
 }
 
 // Input parameters:
@@ -410,28 +427,28 @@
   }
 }
 
-void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
+void FlowGraphCompiler::GeneratePatchableCall(const InstructionSource& source,
                                               const Code& stub,
-                                              PcDescriptorsLayout::Kind kind,
+                                              UntaggedPcDescriptors::Kind kind,
                                               LocationSummary* locs) {
   __ BranchLinkPatchable(stub);
-  EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
+  EmitCallsiteMetadata(source, DeoptId::kNone, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
-                                         TokenPosition token_pos,
+                                         const InstructionSource& source,
                                          const Code& stub,
-                                         PcDescriptorsLayout::Kind kind,
+                                         UntaggedPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   __ BranchLinkPatchable(stub, entry_kind);
-  EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+  EmitCallsiteMetadata(source, deopt_id, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
-                                               TokenPosition token_pos,
-                                               PcDescriptorsLayout::Kind kind,
+                                               const InstructionSource& source,
+                                               UntaggedPcDescriptors::Kind kind,
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
@@ -439,7 +456,7 @@
   if (CanPcRelativeCall(target)) {
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeCallTarget(target, entry_kind);
-    EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+    EmitCallsiteMetadata(source, deopt_id, kind, locs);
   } else {
     ASSERT(is_optimizing());
     // Call sites to the same target can share object pool entries. These
@@ -448,18 +465,18 @@
     // instead.
     const auto& stub = StubCode::CallStaticFunction();
     __ BranchLinkWithEquivalence(stub, target, entry_kind);
-    EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+    EmitCallsiteMetadata(source, deopt_id, kind, locs);
     AddStaticCallTarget(target, entry_kind);
   }
 }
 
-void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateRuntimeCall(const InstructionSource& source,
                                             intptr_t deopt_id,
                                             const RuntimeEntry& entry,
                                             intptr_t argument_count,
                                             LocationSummary* locs) {
   __ CallRuntime(entry, argument_count);
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kOther, locs);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kOther, locs);
 }
 
 void FlowGraphCompiler::EmitEdgeCounter(intptr_t edge_id) {
@@ -486,12 +503,13 @@
 #endif  // DEBUG
 }
 
-void FlowGraphCompiler::EmitOptimizedInstanceCall(const Code& stub,
-                                                  const ICData& ic_data,
-                                                  intptr_t deopt_id,
-                                                  TokenPosition token_pos,
-                                                  LocationSummary* locs,
-                                                  Code::EntryKind entry_kind) {
+void FlowGraphCompiler::EmitOptimizedInstanceCall(
+    const Code& stub,
+    const ICData& ic_data,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
@@ -504,15 +522,15 @@
   __ LoadObject(R8, parsed_function().function());
   __ LoadFromOffset(R0, SP, (ic_data.SizeWithoutTypeArgs() - 1) * kWordSize);
   __ LoadUniqueObject(R9, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub, PcDescriptorsLayout::kIcCall,
-                   locs, entry_kind);
+  GenerateDartCall(deopt_id, source, stub, UntaggedPcDescriptors::kIcCall, locs,
+                   entry_kind);
   __ Drop(ic_data.SizeWithTypeArgs());
 }
 
 void FlowGraphCompiler::EmitInstanceCallJIT(const Code& stub,
                                             const ICData& ic_data,
                                             intptr_t deopt_id,
-                                            TokenPosition token_pos,
+                                            const InstructionSource& source,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
@@ -526,9 +544,8 @@
       entry_kind == Code::EntryKind::kNormal
           ? Code::entry_point_offset(Code::EntryKind::kMonomorphic)
           : Code::entry_point_offset(Code::EntryKind::kMonomorphicUnchecked);
-  __ ldr(LR, compiler::FieldAddress(CODE_REG, entry_point_offset));
-  __ blx(LR);
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kIcCall, locs);
+  __ Call(compiler::FieldAddress(CODE_REG, entry_point_offset));
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.SizeWithTypeArgs());
 }
 
@@ -536,7 +553,7 @@
     const String& name,
     const Array& arguments_descriptor,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     intptr_t try_index,
     intptr_t slow_path_argument_count) {
@@ -556,23 +573,22 @@
     if (FLAG_use_bare_instructions) {
       // The AOT runtime will replace the slot in the object pool with the
       // entrypoint address - see clustered_snapshot.cc.
-      __ LoadUniqueObject(LR, StubCode::MegamorphicCall());
+      CLOBBERS_LR(__ LoadUniqueObject(LR, StubCode::MegamorphicCall()));
     } else {
       __ LoadUniqueObject(CODE_REG, StubCode::MegamorphicCall());
-      __ ldr(LR, compiler::FieldAddress(
-                     CODE_REG, compiler::target::Code::entry_point_offset(
-                                   Code::EntryKind::kMonomorphic)));
+      CLOBBERS_LR(
+          __ ldr(LR, compiler::FieldAddress(
+                         CODE_REG, compiler::target::Code::entry_point_offset(
+                                       Code::EntryKind::kMonomorphic))));
     }
     __ LoadUniqueObject(R9, cache);
-    __ blx(LR);
+    CLOBBERS_LR(__ blx(LR));
 
   } else {
     __ LoadUniqueObject(R9, cache);
     __ LoadUniqueObject(CODE_REG, StubCode::MegamorphicCall());
-    __ ldr(LR, compiler::FieldAddress(
-                   CODE_REG,
-                   Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
-    __ blx(LR);
+    __ Call(compiler::FieldAddress(
+        CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
   }
 
   RecordSafepoint(locs, slow_path_argument_count);
@@ -583,19 +599,16 @@
     if (try_index == kInvalidTryIndex) {
       try_index = CurrentTryIndex();
     }
-    AddDescriptor(PcDescriptorsLayout::kOther, assembler()->CodeSize(),
-                  DeoptId::kNone, token_pos, try_index);
+    AddDescriptor(UntaggedPcDescriptors::kOther, assembler()->CodeSize(),
+                  DeoptId::kNone, source, try_index);
   } else if (is_optimizing()) {
-    AddCurrentDescriptor(PcDescriptorsLayout::kOther, DeoptId::kNone,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kOther, DeoptId::kNone, source);
     AddDeoptIndexAtCall(deopt_id_after);
   } else {
-    AddCurrentDescriptor(PcDescriptorsLayout::kOther, DeoptId::kNone,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kOther, DeoptId::kNone, source);
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
-    AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id_after,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id_after, source);
   }
   RecordCatchEntryMoves(pending_deoptimization_env_, try_index);
   __ Drop(args_desc.SizeWithTypeArgs());
@@ -603,7 +616,7 @@
 
 void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
                                             intptr_t deopt_id,
-                                            TokenPosition token_pos,
+                                            const InstructionSource& source,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind,
                                             bool receiver_can_be_smi) {
@@ -627,7 +640,7 @@
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     // The AOT runtime will replace the slot in the object pool with the
     // entrypoint address - see clustered_snapshot.cc.
-    __ LoadUniqueObject(LR, initial_stub);
+    CLOBBERS_LR(__ LoadUniqueObject(LR, initial_stub));
   } else {
     __ LoadUniqueObject(CODE_REG, initial_stub);
     const intptr_t entry_point_offset =
@@ -636,28 +649,30 @@
                   Code::EntryKind::kMonomorphic)
             : compiler::target::Code::entry_point_offset(
                   Code::EntryKind::kMonomorphicUnchecked);
-    __ ldr(LR, compiler::FieldAddress(CODE_REG, entry_point_offset));
+    CLOBBERS_LR(
+        __ ldr(LR, compiler::FieldAddress(CODE_REG, entry_point_offset)));
   }
   __ LoadUniqueObject(R9, data);
-  __ blx(LR);
+  CLOBBERS_LR(__ blx(LR));
 
-  EmitCallsiteMetadata(token_pos, DeoptId::kNone, PcDescriptorsLayout::kOther,
+  EmitCallsiteMetadata(source, DeoptId::kNone, UntaggedPcDescriptors::kOther,
                        locs);
   __ Drop(ic_data.SizeWithTypeArgs());
 }
 
-void FlowGraphCompiler::EmitUnoptimizedStaticCall(intptr_t size_with_type_args,
-                                                  intptr_t deopt_id,
-                                                  TokenPosition token_pos,
-                                                  LocationSummary* locs,
-                                                  const ICData& ic_data,
-                                                  Code::EntryKind entry_kind) {
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+    intptr_t size_with_type_args,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    const ICData& ic_data,
+    Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(R9, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub,
-                   PcDescriptorsLayout::kUnoptStaticCall, locs, entry_kind);
+  GenerateDartCall(deopt_id, source, stub,
+                   UntaggedPcDescriptors::kUnoptStaticCall, locs, entry_kind);
   __ Drop(size_with_type_args);
 }
 
@@ -666,7 +681,7 @@
     const Array& arguments_descriptor,
     intptr_t size_with_type_args,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
@@ -680,7 +695,7 @@
   }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
-  GenerateStaticDartCall(deopt_id, token_pos, PcDescriptorsLayout::kOther, locs,
+  GenerateStaticDartCall(deopt_id, source, UntaggedPcDescriptors::kOther, locs,
                          function, entry_kind);
   __ Drop(size_with_type_args);
 }
@@ -696,27 +711,29 @@
   }
   intptr_t offset = (selector_offset - DispatchTable::OriginElement()) *
                     compiler::target::kWordSize;
-  if (offset == 0) {
-    __ ldr(LR, compiler::Address(DISPATCH_TABLE_REG, cid_reg, LSL,
-                                 compiler::target::kWordSizeLog2));
-  } else {
-    __ add(LR, DISPATCH_TABLE_REG,
-           compiler::Operand(cid_reg, LSL, compiler::target::kWordSizeLog2));
-    if (!Utils::IsAbsoluteUint(12, offset)) {
-      const intptr_t adjust = offset & -(1 << 12);
-      __ AddImmediate(LR, LR, adjust);
-      offset -= adjust;
+  CLOBBERS_LR({
+    if (offset == 0) {
+      __ ldr(LR, compiler::Address(DISPATCH_TABLE_REG, cid_reg, LSL,
+                                   compiler::target::kWordSizeLog2));
+    } else {
+      __ add(LR, DISPATCH_TABLE_REG,
+             compiler::Operand(cid_reg, LSL, compiler::target::kWordSizeLog2));
+      if (!Utils::IsAbsoluteUint(12, offset)) {
+        const intptr_t adjust = offset & -(1 << 12);
+        __ AddImmediate(LR, LR, adjust);
+        offset -= adjust;
+      }
+      __ ldr(LR, compiler::Address(LR, offset));
     }
-    __ ldr(LR, compiler::Address(LR, offset));
-  }
-  __ blx(LR);
+    __ blx(LR);
+  });
 }
 
 Condition FlowGraphCompiler::EmitEqualityRegConstCompare(
     Register reg,
     const Object& obj,
     bool needs_number_check,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     intptr_t deopt_id) {
   if (needs_number_check) {
     ASSERT(!obj.IsMint() && !obj.IsDouble());
@@ -727,8 +744,7 @@
     } else {
       __ BranchLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRuntimeCall, deopt_id,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
     // Stub returns result in flags (result of a cmp, we need Z computed).
     __ Drop(1);   // Discard constant.
     __ Pop(reg);  // Restore 'reg'.
@@ -738,11 +754,12 @@
   return EQ;
 }
 
-Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
-                                                       Register right,
-                                                       bool needs_number_check,
-                                                       TokenPosition token_pos,
-                                                       intptr_t deopt_id) {
+Condition FlowGraphCompiler::EmitEqualityRegRegCompare(
+    Register left,
+    Register right,
+    bool needs_number_check,
+    const InstructionSource& source,
+    intptr_t deopt_id) {
   if (needs_number_check) {
     __ Push(left);
     __ Push(right);
@@ -751,8 +768,7 @@
     } else {
       __ BranchLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRuntimeCall, deopt_id,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
     // Stub returns result in flags (result of a cmp, we need Z computed).
     __ Pop(right);
     __ Pop(left);
@@ -874,16 +890,17 @@
       const intptr_t source_offset = source.ToStackSlotOffset();
       const intptr_t dest_offset = destination.ToStackSlotOffset();
 
-      // LR not used by register allocator.
-      ASSERT(((1 << LR) & kDartAvailableCpuRegs) == 0);
+      CLOBBERS_LR({
+        // LR not used by register allocator.
+        COMPILE_ASSERT(((1 << LR) & kDartAvailableCpuRegs) == 0);
+        // StoreToOffset uses TMP in the case where dest_offset is too large or
+        // small in order to calculate a new base. We fall back to using LR as a
+        // temporary as we know we're in a ParallelMove.
+        const Register temp_reg = LR;
 
-      // StoreToOffset uses TMP in the case where dest_offset is too large or
-      // small in order to calculate a new base. We fall back to using LR as a
-      // temporary as we know we're in a ParallelMove.
-      const Register temp_reg = LR;
-
-      __ LoadFromOffset(temp_reg, source.base_reg(), source_offset);
-      __ StoreToOffset(temp_reg, destination.base_reg(), dest_offset);
+        __ LoadFromOffset(temp_reg, source.base_reg(), source_offset);
+        __ StoreToOffset(temp_reg, destination.base_reg(), dest_offset);
+      });
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index d841daf..40347c7 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -30,7 +30,7 @@
 
 void FlowGraphCompiler::ArchSpecificInitialization() {
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    auto object_store = isolate()->object_store();
+    auto object_store = isolate_group()->object_store();
 
     const auto& stub =
         Code::ZoneHandle(object_store->write_barrier_wrappers_stub());
@@ -192,13 +192,30 @@
   }
 
   ASSERT(deopt_env() != NULL);
-  __ ldr(LR, compiler::Address(THR, Thread::deoptimize_entry_offset()));
-  __ blr(LR);
+  __ Call(compiler::Address(THR, Thread::deoptimize_entry_offset()));
   set_pc_offset(assembler->CodeSize());
 #undef __
 }
 
+#define __ assembler->
+// Static methods of FlowGraphCompiler that take an assembler.
+
+void FlowGraphCompiler::GenerateIndirectTTSCall(compiler::Assembler* assembler,
+                                                Register reg_to_call,
+                                                intptr_t sub_type_cache_index) {
+  __ LoadField(
+      TTSInternalRegs::kScratchReg,
+      compiler::FieldAddress(
+          reg_to_call,
+          compiler::target::AbstractType::type_test_stub_entry_point_offset()));
+  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
+                           sub_type_cache_index);
+  __ blr(TTSInternalRegs::kScratchReg);
+}
+
+#undef __
 #define __ assembler()->
+// Instance methods of FlowGraphCompiler.
 
 // Fall through if bool_register contains null.
 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
@@ -214,18 +231,6 @@
   __ Bind(&fall_through);
 }
 
-void FlowGraphCompiler::GenerateIndirectTTSCall(Register reg_to_call,
-                                                intptr_t sub_type_cache_index) {
-  __ LoadField(
-      R9,
-      compiler::FieldAddress(
-          reg_to_call,
-          compiler::target::AbstractType::type_test_stub_entry_point_offset()));
-  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
-                           sub_type_cache_index);
-  __ blr(R9);
-}
-
 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
   if (is_optimizing()) {
     return;
@@ -244,7 +249,7 @@
   ASSERT(extracted_method.IsZoneHandle());
 
   const Code& build_method_extractor = Code::ZoneHandle(
-      isolate()->object_store()->build_method_extractor_code());
+      isolate_group()->object_store()->build_method_extractor_code());
 
   const intptr_t stub_index = __ object_pool_builder().AddObject(
       build_method_extractor, ObjectPool::Patchability::kNotPatchable);
@@ -300,18 +305,31 @@
     __ br(TMP);
     __ Bind(&dont_optimize);
   }
-  __ Comment("Enter frame");
-  if (flow_graph().IsCompiledForOsr()) {
-    const intptr_t extra_slots = ExtraStackSlotsOnOsrEntry();
-    ASSERT(extra_slots >= 0);
-    __ EnterOsrFrame(extra_slots * kWordSize);
-  } else {
-    ASSERT(StackSize() >= 0);
-    __ EnterDartFrame(StackSize() * kWordSize);
+
+  if (flow_graph().graph_entry()->NeedsFrame()) {
+    __ Comment("Enter frame");
+    if (flow_graph().IsCompiledForOsr()) {
+      const intptr_t extra_slots = ExtraStackSlotsOnOsrEntry();
+      ASSERT(extra_slots >= 0);
+      __ EnterOsrFrame(extra_slots * kWordSize);
+    } else {
+      ASSERT(StackSize() >= 0);
+      __ EnterDartFrame(StackSize() * kWordSize);
+    }
+  } else if (FLAG_use_bare_instructions) {
+    assembler()->set_constant_pool_allowed(true);
   }
 }
 
+const InstructionSource& PrologueSource() {
+  static InstructionSource prologue_source(TokenPosition::kDartCodePrologue,
+                                           /*inlining_id=*/0);
+  return prologue_source;
+}
+
 void FlowGraphCompiler::EmitPrologue() {
+  BeginCodeSourceRange(PrologueSource());
+
   EmitFrameEntry();
   ASSERT(assembler()->constant_pool_allowed());
 
@@ -337,7 +355,7 @@
     }
   }
 
-  EndCodeSourceRange(TokenPosition::kDartCodePrologue);
+  EndCodeSourceRange(PrologueSource());
 }
 
 // Input parameters:
@@ -402,28 +420,28 @@
   }
 }
 
-void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
+void FlowGraphCompiler::GeneratePatchableCall(const InstructionSource& source,
                                               const Code& stub,
-                                              PcDescriptorsLayout::Kind kind,
+                                              UntaggedPcDescriptors::Kind kind,
                                               LocationSummary* locs) {
   __ BranchLinkPatchable(stub);
-  EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
+  EmitCallsiteMetadata(source, DeoptId::kNone, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
-                                         TokenPosition token_pos,
+                                         const InstructionSource& source,
                                          const Code& stub,
-                                         PcDescriptorsLayout::Kind kind,
+                                         UntaggedPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   __ BranchLinkPatchable(stub, entry_kind);
-  EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+  EmitCallsiteMetadata(source, deopt_id, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
-                                               TokenPosition token_pos,
-                                               PcDescriptorsLayout::Kind kind,
+                                               const InstructionSource& source,
+                                               UntaggedPcDescriptors::Kind kind,
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
@@ -431,7 +449,7 @@
   if (CanPcRelativeCall(target)) {
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeCallTarget(target, entry_kind);
-    EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+    EmitCallsiteMetadata(source, deopt_id, kind, locs);
   } else {
     // Call sites to the same target can share object pool entries. These
     // call sites are never patched for breakpoints: the function is deoptimized
@@ -440,18 +458,18 @@
     ASSERT(is_optimizing());
     const auto& stub = StubCode::CallStaticFunction();
     __ BranchLinkWithEquivalence(stub, target, entry_kind);
-    EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+    EmitCallsiteMetadata(source, deopt_id, kind, locs);
     AddStaticCallTarget(target, entry_kind);
   }
 }
 
-void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateRuntimeCall(const InstructionSource& source,
                                             intptr_t deopt_id,
                                             const RuntimeEntry& entry,
                                             intptr_t argument_count,
                                             LocationSummary* locs) {
   __ CallRuntime(entry, argument_count);
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kOther, locs);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kOther, locs);
 }
 
 void FlowGraphCompiler::EmitEdgeCounter(intptr_t edge_id) {
@@ -469,12 +487,13 @@
   __ StoreFieldToOffset(TMP, R0, Array::element_offset(edge_id));
 }
 
-void FlowGraphCompiler::EmitOptimizedInstanceCall(const Code& stub,
-                                                  const ICData& ic_data,
-                                                  intptr_t deopt_id,
-                                                  TokenPosition token_pos,
-                                                  LocationSummary* locs,
-                                                  Code::EntryKind entry_kind) {
+void FlowGraphCompiler::EmitOptimizedInstanceCall(
+    const Code& stub,
+    const ICData& ic_data,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
@@ -487,15 +506,15 @@
   __ LoadObject(R6, parsed_function().function());
   __ LoadFromOffset(R0, SP, (ic_data.SizeWithoutTypeArgs() - 1) * kWordSize);
   __ LoadUniqueObject(R5, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub, PcDescriptorsLayout::kIcCall,
-                   locs, entry_kind);
+  GenerateDartCall(deopt_id, source, stub, UntaggedPcDescriptors::kIcCall, locs,
+                   entry_kind);
   __ Drop(ic_data.SizeWithTypeArgs());
 }
 
 void FlowGraphCompiler::EmitInstanceCallJIT(const Code& stub,
                                             const ICData& ic_data,
                                             intptr_t deopt_id,
-                                            TokenPosition token_pos,
+                                            const InstructionSource& source,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
@@ -515,9 +534,8 @@
       entry_kind == Code::EntryKind::kNormal
           ? Code::entry_point_offset(Code::EntryKind::kMonomorphic)
           : Code::entry_point_offset(Code::EntryKind::kMonomorphicUnchecked);
-  __ ldr(LR, compiler::FieldAddress(CODE_REG, entry_point_offset));
-  __ blr(LR);
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kIcCall, locs);
+  __ Call(compiler::FieldAddress(CODE_REG, entry_point_offset));
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.SizeWithTypeArgs());
 }
 
@@ -525,7 +543,7 @@
     const String& name,
     const Array& arguments_descriptor,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     intptr_t try_index,
     intptr_t slow_path_argument_count) {
@@ -550,14 +568,14 @@
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     // The AOT runtime will replace the slot in the object pool with the
     // entrypoint address - see clustered_snapshot.cc.
-    __ LoadDoubleWordFromPoolIndex(R5, LR, data_index);
+    CLOBBERS_LR(__ LoadDoubleWordFromPoolIndex(R5, LR, data_index));
   } else {
     __ LoadDoubleWordFromPoolIndex(R5, CODE_REG, data_index);
-    __ ldr(LR, compiler::FieldAddress(
-                   CODE_REG,
-                   Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+    CLOBBERS_LR(__ ldr(LR, compiler::FieldAddress(
+                               CODE_REG, Code::entry_point_offset(
+                                             Code::EntryKind::kMonomorphic))));
   }
-  __ blr(LR);
+  CLOBBERS_LR(__ blr(LR));
 
   RecordSafepoint(locs, slow_path_argument_count);
   const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id);
@@ -567,19 +585,16 @@
     if (try_index == kInvalidTryIndex) {
       try_index = CurrentTryIndex();
     }
-    AddDescriptor(PcDescriptorsLayout::kOther, assembler()->CodeSize(),
-                  DeoptId::kNone, token_pos, try_index);
+    AddDescriptor(UntaggedPcDescriptors::kOther, assembler()->CodeSize(),
+                  DeoptId::kNone, source, try_index);
   } else if (is_optimizing()) {
-    AddCurrentDescriptor(PcDescriptorsLayout::kOther, DeoptId::kNone,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kOther, DeoptId::kNone, source);
     AddDeoptIndexAtCall(deopt_id_after);
   } else {
-    AddCurrentDescriptor(PcDescriptorsLayout::kOther, DeoptId::kNone,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kOther, DeoptId::kNone, source);
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
-    AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id_after,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id_after, source);
   }
   RecordCatchEntryMoves(pending_deoptimization_env_, try_index);
   __ Drop(args_desc.SizeWithTypeArgs());
@@ -587,7 +602,7 @@
 
 void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
                                             intptr_t deopt_id,
-                                            TokenPosition token_pos,
+                                            const InstructionSource& source,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind,
                                             bool receiver_can_be_smi) {
@@ -619,7 +634,7 @@
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     // The AOT runtime will replace the slot in the object pool with the
     // entrypoint address - see clustered_snapshot.cc.
-    __ LoadDoubleWordFromPoolIndex(R5, LR, data_index);
+    CLOBBERS_LR(__ LoadDoubleWordFromPoolIndex(R5, LR, data_index));
   } else {
     __ LoadDoubleWordFromPoolIndex(R5, CODE_REG, data_index);
     const intptr_t entry_point_offset =
@@ -628,27 +643,29 @@
                   Code::EntryKind::kMonomorphic)
             : compiler::target::Code::entry_point_offset(
                   Code::EntryKind::kMonomorphicUnchecked);
-    __ ldr(LR, compiler::FieldAddress(CODE_REG, entry_point_offset));
+    CLOBBERS_LR(
+        __ ldr(LR, compiler::FieldAddress(CODE_REG, entry_point_offset)));
   }
-  __ blr(LR);
+  CLOBBERS_LR(__ blr(LR));
 
-  EmitCallsiteMetadata(token_pos, DeoptId::kNone, PcDescriptorsLayout::kOther,
+  EmitCallsiteMetadata(source, DeoptId::kNone, UntaggedPcDescriptors::kOther,
                        locs);
   __ Drop(ic_data.SizeWithTypeArgs());
 }
 
-void FlowGraphCompiler::EmitUnoptimizedStaticCall(intptr_t size_with_type_args,
-                                                  intptr_t deopt_id,
-                                                  TokenPosition token_pos,
-                                                  LocationSummary* locs,
-                                                  const ICData& ic_data,
-                                                  Code::EntryKind entry_kind) {
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+    intptr_t size_with_type_args,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    const ICData& ic_data,
+    Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(R5, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub,
-                   PcDescriptorsLayout::kUnoptStaticCall, locs, entry_kind);
+  GenerateDartCall(deopt_id, source, stub,
+                   UntaggedPcDescriptors::kUnoptStaticCall, locs, entry_kind);
   __ Drop(size_with_type_args);
 }
 
@@ -657,7 +674,7 @@
     const Array& arguments_descriptor,
     intptr_t size_with_type_args,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
@@ -671,7 +688,7 @@
   }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
-  GenerateStaticDartCall(deopt_id, token_pos, PcDescriptorsLayout::kOther, locs,
+  GenerateStaticDartCall(deopt_id, source, UntaggedPcDescriptors::kOther, locs,
                          function, entry_kind);
   __ Drop(size_with_type_args);
 }
@@ -687,16 +704,15 @@
   }
   const intptr_t offset = selector_offset - DispatchTable::OriginElement();
   __ AddImmediate(cid_reg, cid_reg, offset);
-  __ ldr(LR, compiler::Address(DISPATCH_TABLE_REG, cid_reg, UXTX,
-                               compiler::Address::Scaled));
-  __ blr(LR);
+  __ Call(compiler::Address(DISPATCH_TABLE_REG, cid_reg, UXTX,
+                            compiler::Address::Scaled));
 }
 
 Condition FlowGraphCompiler::EmitEqualityRegConstCompare(
     Register reg,
     const Object& obj,
     bool needs_number_check,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     intptr_t deopt_id) {
   if (needs_number_check) {
     ASSERT(!obj.IsMint() && !obj.IsDouble());
@@ -707,8 +723,7 @@
     } else {
       __ BranchLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRuntimeCall, deopt_id,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
     // Stub returns result in flags (result of a cmp, we need Z computed).
     // Discard constant.
     // Restore 'reg'.
@@ -719,11 +734,12 @@
   return EQ;
 }
 
-Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
-                                                       Register right,
-                                                       bool needs_number_check,
-                                                       TokenPosition token_pos,
-                                                       intptr_t deopt_id) {
+Condition FlowGraphCompiler::EmitEqualityRegRegCompare(
+    Register left,
+    Register right,
+    bool needs_number_check,
+    const InstructionSource& source,
+    intptr_t deopt_id) {
   if (needs_number_check) {
     __ PushPair(right, left);
     if (is_optimizing()) {
@@ -731,8 +747,7 @@
     } else {
       __ BranchLinkPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRuntimeCall, deopt_id,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
     // Stub returns result in flags (result of a cmp, we need Z computed).
     __ PopPair(right, left);
   } else {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index e0cb95a..d89ec9a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -249,7 +249,7 @@
   __ Drop(1);
   GenerateBoolToJump(TypeTestABI::kSubtypeTestCacheResultReg, is_instance_lbl,
                      is_not_instance_lbl);
-  return type_test_cache.raw();
+  return type_test_cache.ptr();
 }
 
 // If instanceof type test cannot be performed successfully at compile time and
@@ -263,7 +263,7 @@
 // - ECX: function type arguments or raw_null.
 // Returns:
 // - true or false in EAX.
-void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateInstanceOf(const InstructionSource& source,
                                            intptr_t deopt_id,
                                            const AbstractType& type,
                                            LocationSummary* locs) {
@@ -291,7 +291,7 @@
   // Generate inline instanceof test.
   SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
   test_cache =
-      GenerateInlineInstanceof(token_pos, type, &is_instance, &is_not_instance);
+      GenerateInlineInstanceof(source, type, &is_instance, &is_not_instance);
 
   // test_cache is null if there is no fall-through.
   compiler::Label done;
@@ -305,7 +305,7 @@
     // Can reuse kInstanceReg as scratch here since it was pushed above.
     __ LoadObject(TypeTestABI::kInstanceReg, test_cache);
     __ pushl(TypeTestABI::kInstanceReg);
-    GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
+    GenerateRuntimeCall(source, deopt_id, kInstanceofRuntimeEntry, 5, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // instanceof runtime call will be left as the result of the operation.
     __ Drop(5);
@@ -334,12 +334,13 @@
 // - object in EAX for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
 // as they throw an exception.
-void FlowGraphCompiler::GenerateAssertAssignable(CompileType* receiver_type,
-                                                 TokenPosition token_pos,
-                                                 intptr_t deopt_id,
-                                                 const String& dst_name,
-                                                 LocationSummary* locs) {
-  ASSERT(!token_pos.IsClassifying());
+void FlowGraphCompiler::GenerateAssertAssignable(
+    CompileType* receiver_type,
+    const InstructionSource& source,
+    intptr_t deopt_id,
+    const String& dst_name,
+    LocationSummary* locs) {
+  ASSERT(!source.token_pos.IsClassifying());
   ASSERT(CheckAssertAssignableTypeTestingABILocations(*locs));
 
   const auto& dst_type =
@@ -359,19 +360,19 @@
     __ Comment("AssertAssignable for runtime type");
     // kDstTypeReg should already contain the destination type.
     const bool null_safety =
-        Isolate::Current()->use_strict_null_safety_checks();
-    GenerateStubCall(token_pos,
+        IsolateGroup::Current()->use_strict_null_safety_checks();
+    GenerateStubCall(source,
                      null_safety ? StubCode::TypeIsTopTypeForSubtypingNullSafe()
                                  : StubCode::TypeIsTopTypeForSubtyping(),
-                     PcDescriptorsLayout::kOther, locs, deopt_id);
+                     UntaggedPcDescriptors::kOther, locs, deopt_id);
     // TypeTestABI::kSubtypeTestCacheReg is 0 if the type is a top type.
     __ BranchIfZero(TypeTestABI::kSubtypeTestCacheReg, &is_assignable,
                     compiler::Assembler::kNearJump);
 
-    GenerateStubCall(token_pos,
+    GenerateStubCall(source,
                      null_safety ? StubCode::NullIsAssignableToTypeNullSafe()
                                  : StubCode::NullIsAssignableToType(),
-                     PcDescriptorsLayout::kOther, locs, deopt_id);
+                     UntaggedPcDescriptors::kOther, locs, deopt_id);
     // TypeTestABI::kSubtypeTestCacheReg is 0 if the object is null and is
     // assignable.
     __ BranchIfZero(TypeTestABI::kSubtypeTestCacheReg, &is_assignable,
@@ -389,7 +390,7 @@
     }
 
     // Generate inline type check, linking to runtime call if not assignable.
-    test_cache = GenerateInlineInstanceof(token_pos, dst_type, &is_assignable,
+    test_cache = GenerateInlineInstanceof(source, dst_type, &is_assignable,
                                           &runtime_call);
   }
 
@@ -409,7 +410,7 @@
   __ LoadObject(TypeTestABI::kInstanceReg, test_cache);
   __ pushl(TypeTestABI::kInstanceReg);
   __ PushObject(Smi::ZoneHandle(zone(), Smi::New(kTypeCheckFromInline)));
-  GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
+  GenerateRuntimeCall(source, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
   // Pop the parameters supplied to the runtime entry. The result of the
   // type check runtime call is the checked value.
   __ Drop(7);
@@ -439,6 +440,8 @@
 // NOTE: If the entry code shape changes, ReturnAddressLocator in profiler.cc
 // needs to be updated to match.
 void FlowGraphCompiler::EmitFrameEntry() {
+  RELEASE_ASSERT(flow_graph().graph_entry()->NeedsFrame());
+
   const Function& function = parsed_function().function();
   if (CanOptimizeFunction() && function.IsOptimizable() &&
       (!is_optimizing() || may_reoptimize())) {
@@ -472,7 +475,15 @@
   }
 }
 
+const InstructionSource& PrologueSource() {
+  static InstructionSource prologue_source(TokenPosition::kDartCodePrologue,
+                                           /*inlining_id=*/0);
+  return prologue_source;
+}
+
 void FlowGraphCompiler::EmitPrologue() {
+  BeginCodeSourceRange(PrologueSource());
+
   EmitFrameEntry();
 
   // In unoptimized code, initialize (non-argument) stack allocated slots.
@@ -499,7 +510,7 @@
     }
   }
 
-  EndCodeSourceRange(TokenPosition::kDartCodePrologue);
+  EndCodeSourceRange(PrologueSource());
 }
 
 void FlowGraphCompiler::CompileGraph() {
@@ -526,50 +537,51 @@
 }
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
-                                         TokenPosition token_pos,
+                                         const InstructionSource& source,
                                          const Code& stub,
-                                         PcDescriptorsLayout::Kind kind,
+                                         UntaggedPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   __ Call(stub, /*moveable_target=*/false, entry_kind);
-  EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+  EmitCallsiteMetadata(source, deopt_id, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
-                                               TokenPosition token_pos,
-                                               PcDescriptorsLayout::Kind kind,
+                                               const InstructionSource& source,
+                                               UntaggedPcDescriptors::Kind kind,
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   const auto& stub = StubCode::CallStaticFunction();
   __ Call(stub, /*movable_target=*/true, entry_kind);
-  EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+  EmitCallsiteMetadata(source, deopt_id, kind, locs);
   AddStaticCallTarget(target, entry_kind);
 }
 
-void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateRuntimeCall(const InstructionSource& source,
                                             intptr_t deopt_id,
                                             const RuntimeEntry& entry,
                                             intptr_t argument_count,
                                             LocationSummary* locs) {
   __ CallRuntime(entry, argument_count);
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kOther, locs);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kOther, locs);
 }
 
-void FlowGraphCompiler::EmitUnoptimizedStaticCall(intptr_t size_with_type_args,
-                                                  intptr_t deopt_id,
-                                                  TokenPosition token_pos,
-                                                  LocationSummary* locs,
-                                                  const ICData& ic_data,
-                                                  Code::EntryKind entry_kind) {
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+    intptr_t size_with_type_args,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    const ICData& ic_data,
+    Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(ECX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub,
-                   PcDescriptorsLayout::kUnoptStaticCall, locs, entry_kind);
+  GenerateDartCall(deopt_id, source, stub,
+                   UntaggedPcDescriptors::kUnoptStaticCall, locs, entry_kind);
   __ Drop(size_with_type_args);
 }
 
@@ -586,12 +598,13 @@
       compiler::FieldAddress(EAX, Array::element_offset(edge_id)), 1);
 }
 
-void FlowGraphCompiler::EmitOptimizedInstanceCall(const Code& stub,
-                                                  const ICData& ic_data,
-                                                  intptr_t deopt_id,
-                                                  TokenPosition token_pos,
-                                                  LocationSummary* locs,
-                                                  Code::EntryKind entry_kind) {
+void FlowGraphCompiler::EmitOptimizedInstanceCall(
+    const Code& stub,
+    const ICData& ic_data,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
@@ -605,15 +618,15 @@
   __ movl(EBX, compiler::Address(
                    ESP, (ic_data.SizeWithoutTypeArgs() - 1) * kWordSize));
   __ LoadObject(ECX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub, PcDescriptorsLayout::kIcCall,
-                   locs, entry_kind);
+  GenerateDartCall(deopt_id, source, stub, UntaggedPcDescriptors::kIcCall, locs,
+                   entry_kind);
   __ Drop(ic_data.SizeWithTypeArgs());
 }
 
 void FlowGraphCompiler::EmitInstanceCallJIT(const Code& stub,
                                             const ICData& ic_data,
                                             intptr_t deopt_id,
-                                            TokenPosition token_pos,
+                                            const InstructionSource& source,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
@@ -630,7 +643,7 @@
           ? Code::entry_point_offset(Code::EntryKind::kMonomorphic)
           : Code::entry_point_offset(Code::EntryKind::kMonomorphicUnchecked);
   __ call(compiler::FieldAddress(CODE_REG, entry_point_offset));
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kIcCall, locs);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.SizeWithTypeArgs());
 }
 
@@ -638,7 +651,7 @@
     const String& name,
     const Array& arguments_descriptor,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     intptr_t try_index,
     intptr_t slow_path_argument_count) {
@@ -657,7 +670,7 @@
   __ call(compiler::FieldAddress(
       CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
 
-  AddCurrentDescriptor(PcDescriptorsLayout::kOther, DeoptId::kNone, token_pos);
+  AddCurrentDescriptor(UntaggedPcDescriptors::kOther, DeoptId::kNone, source);
   RecordSafepoint(locs, slow_path_argument_count);
   const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id);
   // Precompilation not implemented on ia32 platform.
@@ -667,8 +680,7 @@
   } else {
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
-    AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id_after,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id_after, source);
   }
   RecordCatchEntryMoves(pending_deoptimization_env_, try_index);
   __ Drop(args_desc.SizeWithTypeArgs());
@@ -676,7 +688,7 @@
 
 void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
                                             intptr_t deopt_id,
-                                            TokenPosition token_pos,
+                                            const InstructionSource& source,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind,
                                             bool receiver_can_be_smi) {
@@ -689,7 +701,7 @@
     const Array& arguments_descriptor,
     intptr_t size_with_type_args,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
@@ -700,7 +712,7 @@
   }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
-  GenerateStaticDartCall(deopt_id, token_pos, PcDescriptorsLayout::kOther, locs,
+  GenerateStaticDartCall(deopt_id, source, UntaggedPcDescriptors::kOther, locs,
                          function, entry_kind);
   __ Drop(size_with_type_args);
 }
@@ -717,7 +729,7 @@
     Register reg,
     const Object& obj,
     bool needs_number_check,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     intptr_t deopt_id) {
   ASSERT(!needs_number_check || (!obj.IsMint() && !obj.IsDouble()));
 
@@ -735,8 +747,7 @@
     } else {
       __ Call(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRuntimeCall, deopt_id,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
     // Stub returns result in flags (result of a cmpl, we need ZF computed).
     __ popl(reg);  // Discard constant.
     __ popl(reg);  // Restore 'reg'.
@@ -746,11 +757,12 @@
   return EQUAL;
 }
 
-Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
-                                                       Register right,
-                                                       bool needs_number_check,
-                                                       TokenPosition token_pos,
-                                                       intptr_t deopt_id) {
+Condition FlowGraphCompiler::EmitEqualityRegRegCompare(
+    Register left,
+    Register right,
+    bool needs_number_check,
+    const InstructionSource& source,
+    intptr_t deopt_id) {
   if (needs_number_check) {
     __ pushl(left);
     __ pushl(right);
@@ -759,8 +771,7 @@
     } else {
       __ Call(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRuntimeCall, deopt_id,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
     // Stub returns result in flags (result of a cmpl, we need ZF computed).
     __ popl(right);
     __ popl(left);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index aad34de..89f2a24 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -30,7 +30,7 @@
 
 void FlowGraphCompiler::ArchSpecificInitialization() {
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    auto object_store = isolate()->object_store();
+    auto object_store = isolate_group()->object_store();
 
     const auto& stub =
         Code::ZoneHandle(object_store->write_barrier_wrappers_stub());
@@ -199,7 +199,22 @@
 #undef __
 }
 
+#define __ assembler->
+// Static methods of FlowGraphCompiler that take an assembler.
+
+void FlowGraphCompiler::GenerateIndirectTTSCall(compiler::Assembler* assembler,
+                                                Register reg_to_call,
+                                                intptr_t sub_type_cache_index) {
+  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
+                           sub_type_cache_index);
+  __ Call(compiler::FieldAddress(
+      reg_to_call,
+      compiler::target::AbstractType::type_test_stub_entry_point_offset()));
+}
+
+#undef __
 #define __ assembler()->
+// Instance methods of FlowGraphCompiler.
 
 // Fall through if bool_register contains null.
 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
@@ -217,15 +232,6 @@
   __ Bind(&fall_through);
 }
 
-void FlowGraphCompiler::GenerateIndirectTTSCall(Register reg_to_call,
-                                                intptr_t sub_type_cache_index) {
-  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
-                           sub_type_cache_index);
-  __ Call(compiler::FieldAddress(
-      reg_to_call,
-      compiler::target::AbstractType::type_test_stub_entry_point_offset()));
-}
-
 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
   if (is_optimizing()) {
     return;
@@ -252,7 +258,7 @@
   ASSERT(extracted_method.IsZoneHandle());
 
   const Code& build_method_extractor = Code::ZoneHandle(
-      isolate()->object_store()->build_method_extractor_code());
+      isolate_group()->object_store()->build_method_extractor_code());
   ASSERT(!build_method_extractor.IsNull());
 
   const intptr_t stub_index = __ object_pool_builder().AddObject(
@@ -283,6 +289,13 @@
 // NOTE: If the entry code shape changes, ReturnAddressLocator in profiler.cc
 // needs to be updated to match.
 void FlowGraphCompiler::EmitFrameEntry() {
+  if (!flow_graph().graph_entry()->NeedsFrame()) {
+    if (FLAG_use_bare_instructions) {
+      assembler()->set_constant_pool_allowed(true);
+    }
+    return;
+  }
+
   if (flow_graph().IsCompiledForOsr()) {
     const intptr_t extra_slots = ExtraStackSlotsOnOsrEntry();
     ASSERT(extra_slots >= 0);
@@ -317,8 +330,14 @@
   }
 }
 
+const InstructionSource& PrologueSource() {
+  static InstructionSource prologue_source(TokenPosition::kDartCodePrologue,
+                                           /*inlining_id=*/0);
+  return prologue_source;
+}
+
 void FlowGraphCompiler::EmitPrologue() {
-  BeginCodeSourceRange();
+  BeginCodeSourceRange(PrologueSource());
 
   EmitFrameEntry();
   ASSERT(assembler()->constant_pool_allowed());
@@ -345,7 +364,7 @@
     }
   }
 
-  EndCodeSourceRange(TokenPosition::kDartCodePrologue);
+  EndCodeSourceRange(PrologueSource());
 }
 
 void FlowGraphCompiler::CompileGraph() {
@@ -404,28 +423,28 @@
   }
 }
 
-void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
+void FlowGraphCompiler::GeneratePatchableCall(const InstructionSource& source,
                                               const Code& stub,
-                                              PcDescriptorsLayout::Kind kind,
+                                              UntaggedPcDescriptors::Kind kind,
                                               LocationSummary* locs) {
   __ CallPatchable(stub);
-  EmitCallsiteMetadata(token_pos, DeoptId::kNone, kind, locs);
+  EmitCallsiteMetadata(source, DeoptId::kNone, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
-                                         TokenPosition token_pos,
+                                         const InstructionSource& source,
                                          const Code& stub,
-                                         PcDescriptorsLayout::Kind kind,
+                                         UntaggedPcDescriptors::Kind kind,
                                          LocationSummary* locs,
                                          Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   __ CallPatchable(stub, entry_kind);
-  EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+  EmitCallsiteMetadata(source, deopt_id, kind, locs);
 }
 
 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
-                                               TokenPosition token_pos,
-                                               PcDescriptorsLayout::Kind kind,
+                                               const InstructionSource& source,
+                                               UntaggedPcDescriptors::Kind kind,
                                                LocationSummary* locs,
                                                const Function& target,
                                                Code::EntryKind entry_kind) {
@@ -434,7 +453,7 @@
   if (CanPcRelativeCall(target)) {
     __ GenerateUnRelocatedPcRelativeCall();
     AddPcRelativeCallTarget(target, entry_kind);
-    EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+    EmitCallsiteMetadata(source, deopt_id, kind, locs);
   } else {
     // Call sites to the same target can share object pool entries. These
     // call sites are never patched for breakpoints: the function is deoptimized
@@ -442,32 +461,33 @@
     // instead.
     const auto& stub_entry = StubCode::CallStaticFunction();
     __ CallWithEquivalence(stub_entry, target, entry_kind);
-    EmitCallsiteMetadata(token_pos, deopt_id, kind, locs);
+    EmitCallsiteMetadata(source, deopt_id, kind, locs);
     AddStaticCallTarget(target, entry_kind);
   }
 }
 
-void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos,
+void FlowGraphCompiler::GenerateRuntimeCall(const InstructionSource& source,
                                             intptr_t deopt_id,
                                             const RuntimeEntry& entry,
                                             intptr_t argument_count,
                                             LocationSummary* locs) {
   __ CallRuntime(entry, argument_count);
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kOther, locs);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kOther, locs);
 }
 
-void FlowGraphCompiler::EmitUnoptimizedStaticCall(intptr_t size_with_type_args,
-                                                  intptr_t deopt_id,
-                                                  TokenPosition token_pos,
-                                                  LocationSummary* locs,
-                                                  const ICData& ic_data,
-                                                  Code::EntryKind entry_kind) {
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+    intptr_t size_with_type_args,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    const ICData& ic_data,
+    Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   const Code& stub =
       StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
   __ LoadObject(RBX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub,
-                   PcDescriptorsLayout::kUnoptStaticCall, locs, entry_kind);
+  GenerateDartCall(deopt_id, source, stub,
+                   UntaggedPcDescriptors::kUnoptStaticCall, locs, entry_kind);
   __ Drop(size_with_type_args, RCX);
 }
 
@@ -485,12 +505,13 @@
       compiler::FieldAddress(RAX, Array::element_offset(edge_id)), 1);
 }
 
-void FlowGraphCompiler::EmitOptimizedInstanceCall(const Code& stub,
-                                                  const ICData& ic_data,
-                                                  intptr_t deopt_id,
-                                                  TokenPosition token_pos,
-                                                  LocationSummary* locs,
-                                                  Code::EntryKind entry_kind) {
+void FlowGraphCompiler::EmitOptimizedInstanceCall(
+    const Code& stub,
+    const ICData& ic_data,
+    intptr_t deopt_id,
+    const InstructionSource& source,
+    LocationSummary* locs,
+    Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
   ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
   // Each ICData propagated from unoptimized to optimized code contains the
@@ -504,15 +525,15 @@
   __ movq(RDX, compiler::Address(
                    RSP, (ic_data.SizeWithoutTypeArgs() - 1) * kWordSize));
   __ LoadUniqueObject(RBX, ic_data);
-  GenerateDartCall(deopt_id, token_pos, stub, PcDescriptorsLayout::kIcCall,
-                   locs, entry_kind);
+  GenerateDartCall(deopt_id, source, stub, UntaggedPcDescriptors::kIcCall, locs,
+                   entry_kind);
   __ Drop(ic_data.SizeWithTypeArgs(), RCX);
 }
 
 void FlowGraphCompiler::EmitInstanceCallJIT(const Code& stub,
                                             const ICData& ic_data,
                                             intptr_t deopt_id,
-                                            TokenPosition token_pos,
+                                            const InstructionSource& source,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
@@ -529,7 +550,7 @@
           ? Code::entry_point_offset(Code::EntryKind::kMonomorphic)
           : Code::entry_point_offset(Code::EntryKind::kMonomorphicUnchecked);
   __ call(compiler::FieldAddress(CODE_REG, entry_point_offset));
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kIcCall, locs);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kIcCall, locs);
   __ Drop(ic_data.SizeWithTypeArgs(), RCX);
 }
 
@@ -537,7 +558,7 @@
     const String& name,
     const Array& arguments_descriptor,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     intptr_t try_index,
     intptr_t slow_path_argument_count) {
@@ -580,19 +601,16 @@
     if (try_index == kInvalidTryIndex) {
       try_index = CurrentTryIndex();
     }
-    AddDescriptor(PcDescriptorsLayout::kOther, assembler()->CodeSize(),
-                  DeoptId::kNone, token_pos, try_index);
+    AddDescriptor(UntaggedPcDescriptors::kOther, assembler()->CodeSize(),
+                  DeoptId::kNone, source, try_index);
   } else if (is_optimizing()) {
-    AddCurrentDescriptor(PcDescriptorsLayout::kOther, DeoptId::kNone,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kOther, DeoptId::kNone, source);
     AddDeoptIndexAtCall(deopt_id_after);
   } else {
-    AddCurrentDescriptor(PcDescriptorsLayout::kOther, DeoptId::kNone,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kOther, DeoptId::kNone, source);
     // Add deoptimization continuation point after the call and before the
     // arguments are removed.
-    AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id_after,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id_after, source);
   }
   RecordCatchEntryMoves(pending_deoptimization_env_, try_index);
   __ Drop(args_desc.SizeWithTypeArgs(), RCX);
@@ -600,7 +618,7 @@
 
 void FlowGraphCompiler::EmitInstanceCallAOT(const ICData& ic_data,
                                             intptr_t deopt_id,
-                                            TokenPosition token_pos,
+                                            const InstructionSource& source,
                                             LocationSummary* locs,
                                             Code::EntryKind entry_kind,
                                             bool receiver_can_be_smi) {
@@ -635,7 +653,7 @@
   __ LoadUniqueObject(RBX, data);
   __ call(RCX);
 
-  EmitCallsiteMetadata(token_pos, deopt_id, PcDescriptorsLayout::kOther, locs);
+  EmitCallsiteMetadata(source, deopt_id, UntaggedPcDescriptors::kOther, locs);
   __ Drop(ic_data.SizeWithTypeArgs(), RCX);
 }
 
@@ -644,7 +662,7 @@
     const Array& arguments_descriptor,
     intptr_t size_with_type_args,
     intptr_t deopt_id,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     LocationSummary* locs,
     Code::EntryKind entry_kind) {
   ASSERT(CanCallDart());
@@ -658,7 +676,7 @@
   }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
-  GenerateStaticDartCall(deopt_id, token_pos, PcDescriptorsLayout::kOther, locs,
+  GenerateStaticDartCall(deopt_id, source, UntaggedPcDescriptors::kOther, locs,
                          function, entry_kind);
   __ Drop(size_with_type_args, RCX);
 }
@@ -684,7 +702,7 @@
     Register reg,
     const Object& obj,
     bool needs_number_check,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     intptr_t deopt_id) {
   ASSERT(!needs_number_check || (!obj.IsMint() && !obj.IsDouble()));
 
@@ -702,8 +720,7 @@
     } else {
       __ CallPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRuntimeCall, deopt_id,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
     // Stub returns result in flags (result of a cmpq, we need ZF computed).
     __ popq(reg);  // Discard constant.
     __ popq(reg);  // Restore 'reg'.
@@ -713,11 +730,12 @@
   return EQUAL;
 }
 
-Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
-                                                       Register right,
-                                                       bool needs_number_check,
-                                                       TokenPosition token_pos,
-                                                       intptr_t deopt_id) {
+Condition FlowGraphCompiler::EmitEqualityRegRegCompare(
+    Register left,
+    Register right,
+    bool needs_number_check,
+    const InstructionSource& source,
+    intptr_t deopt_id) {
   if (needs_number_check) {
     __ pushq(left);
     __ pushq(right);
@@ -726,8 +744,7 @@
     } else {
       __ CallPatchable(StubCode::UnoptimizedIdenticalWithNumberCheck());
     }
-    AddCurrentDescriptor(PcDescriptorsLayout::kRuntimeCall, deopt_id,
-                         token_pos);
+    AddCurrentDescriptor(UntaggedPcDescriptors::kRuntimeCall, deopt_id, source);
     // Stub returns result in flags (result of a cmpq, we need ZF computed).
     __ popq(right);
     __ popq(left);
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 7ae73e4..a276c17 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -115,7 +115,7 @@
     const Class& klass,
     bool include_abstract,
     bool exclude_null) {
-  ClassTable* table = thread()->isolate()->class_table();
+  ClassTable* table = thread()->isolate_group()->class_table();
   const intptr_t cid_count = table->NumCids();
   std::unique_ptr<CidRangeVector[]>* cid_ranges = nullptr;
   if (include_abstract) {
@@ -143,7 +143,7 @@
 
 const CidRangeVector& HierarchyInfo::SubclassRangesForClass(
     const Class& klass) {
-  ClassTable* table = thread()->isolate()->class_table();
+  ClassTable* table = thread()->isolate_group()->class_table();
   const intptr_t cid_count = table->NumCids();
   if (cid_subclass_ranges_ == nullptr) {
     cid_subclass_ranges_.reset(new CidRangeVector[cid_count]);
@@ -176,7 +176,7 @@
                                    bool include_abstract,
                                    bool exclude_null) {
   Zone* zone = thread()->zone();
-  ClassTable* class_table = thread()->isolate()->class_table();
+  ClassTable* class_table = thread()->isolate_group()->class_table();
 
   // Only really used if `use_subtype_test == true`.
   const Type& dst_type = Type::Handle(zone, Type::RawCast(klass.RareType()));
@@ -217,7 +217,7 @@
       test_succeeded = cls_type.IsSubtypeOf(dst_type, Heap::kNew);
     } else {
       while (!cls.IsObjectClass()) {
-        if (cls.raw() == klass.raw()) {
+        if (cls.ptr() == klass.ptr()) {
           test_succeeded = true;
           break;
         }
@@ -354,8 +354,7 @@
 bool HierarchyInfo::CanUseSubtypeRangeCheckFor(const AbstractType& type) {
   ASSERT(type.IsFinalized());
 
-  if (!type.IsInstantiated() || !type.IsType() || type.IsFunctionType() ||
-      type.IsDartFunctionType()) {
+  if (!type.IsInstantiated() || !type.IsType() || type.IsDartFunctionType()) {
     return false;
   }
 
@@ -398,7 +397,7 @@
     const AbstractType& type) {
   ASSERT(type.IsFinalized());
 
-  if (!type.IsType() || type.IsFunctionType() || type.IsDartFunctionType()) {
+  if (!type.IsType() || type.IsDartFunctionType()) {
     return false;
   }
 
@@ -566,8 +565,6 @@
 }
 #endif  // DEBUG
 
-Definition::Definition(intptr_t deopt_id) : Instruction(deopt_id) {}
-
 // A value in the constant propagation lattice.
 //    - non-constant sentinel
 //    - a constant (any non-sentinel value)
@@ -886,12 +883,12 @@
 CheckClassInstr::CheckClassInstr(Value* value,
                                  intptr_t deopt_id,
                                  const Cids& cids,
-                                 TokenPosition token_pos)
-    : TemplateInstruction(deopt_id),
+                                 const InstructionSource& source)
+    : TemplateInstruction(source, deopt_id),
       cids_(cids),
       licm_hoisted_(false),
       is_bit_test_(IsCompactCidRange(cids)),
-      token_pos_(token_pos) {
+      token_pos_(source.token_pos) {
   // Expected useful check data.
   const intptr_t number_of_checks = cids.length();
   ASSERT(number_of_checks > 0);
@@ -997,9 +994,9 @@
 }
 
 AllocateUninitializedContextInstr::AllocateUninitializedContextInstr(
-    TokenPosition token_pos,
+    const InstructionSource& source,
     intptr_t num_context_variables)
-    : TemplateAllocation(token_pos),
+    : TemplateAllocation(source),
       num_context_variables_(num_context_variables) {
   // This instruction is not used in AOT for code size reasons.
   ASSERT(!CompilerState::Current().is_aot());
@@ -1021,7 +1018,7 @@
 void AllocateTypedDataInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForTypedData(class_id()));
-  compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+  compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
                              locs());
 }
 
@@ -1061,15 +1058,15 @@
 }
 
 bool GuardFieldClassInstr::AttributesEqual(Instruction* other) const {
-  return field().raw() == other->AsGuardFieldClass()->field().raw();
+  return field().ptr() == other->AsGuardFieldClass()->field().ptr();
 }
 
 bool GuardFieldLengthInstr::AttributesEqual(Instruction* other) const {
-  return field().raw() == other->AsGuardFieldLength()->field().raw();
+  return field().ptr() == other->AsGuardFieldLength()->field().ptr();
 }
 
 bool GuardFieldTypeInstr::AttributesEqual(Instruction* other) const {
-  return field().raw() == other->AsGuardFieldType()->field().raw();
+  return field().ptr() == other->AsGuardFieldType()->field().ptr();
 }
 
 Instruction* AssertSubtypeInstr::Canonicalize(FlowGraph* flow_graph) {
@@ -1089,9 +1086,9 @@
             ? TypeArguments::null_type_arguments()
             : TypeArguments::Cast(function_type_arguments()->BoundConstant());
     auto& constant_sub_type = AbstractType::Handle(
-        Z, AbstractType::Cast(sub_type()->BoundConstant()).raw());
+        Z, AbstractType::Cast(sub_type()->BoundConstant()).ptr());
     auto& constant_super_type = AbstractType::Handle(
-        Z, AbstractType::Cast(super_type()->BoundConstant()).raw());
+        Z, AbstractType::Cast(super_type()->BoundConstant()).ptr());
 
     ASSERT(!constant_super_type.IsTypeRef());
     ASSERT(!constant_sub_type.IsTypeRef());
@@ -1135,13 +1132,13 @@
 
 bool LoadStaticFieldInstr::AttributesEqual(Instruction* other) const {
   ASSERT(IsFieldInitialized());
-  return field().raw() == other->AsLoadStaticField()->field().raw();
+  return field().ptr() == other->AsLoadStaticField()->field().ptr();
 }
 
 bool LoadStaticFieldInstr::IsFieldInitialized() const {
   const Field& field = this->field();
-  return (field.StaticValue() != Object::sentinel().raw()) &&
-         (field.StaticValue() != Object::transition_sentinel().raw());
+  return (field.StaticValue() != Object::sentinel().ptr()) &&
+         (field.StaticValue() != Object::transition_sentinel().ptr());
 }
 
 Definition* LoadStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) {
@@ -1156,8 +1153,9 @@
   return this;
 }
 
-ConstantInstr::ConstantInstr(const Object& value, TokenPosition token_pos)
-    : value_(value), token_pos_(token_pos) {
+ConstantInstr::ConstantInstr(const Object& value,
+                             const InstructionSource& source)
+    : TemplateDefinition(source), value_(value), token_pos_(source.token_pos) {
   // Check that the value is not an incorrect Integer representation.
   ASSERT(!value.IsMint() || !Smi::IsValid(Mint::Cast(value).AsInt64Value()));
   // Check that clones of fields are not stored as constants.
@@ -1169,7 +1167,7 @@
   // values, and sentinel values are canonical by construction and so we skip
   // them here.
   if (!value.IsNull() && !value.IsSmi() && value.IsInstance() &&
-      !value.IsCanonical() && (value.raw() != Object::sentinel().raw())) {
+      !value.IsCanonical() && (value.ptr() != Object::sentinel().ptr())) {
     // The only allowed type for which IsCanonical() never answers true is
     // TypeParameter. (They are treated as canonical due to how they are
     // created, but there is no way to canonicalize a new TypeParameter
@@ -1202,7 +1200,7 @@
 bool ConstantInstr::AttributesEqual(Instruction* other) const {
   ConstantInstr* other_constant = other->AsConstant();
   ASSERT(other_constant != NULL);
-  return (value().raw() == other_constant->value().raw() &&
+  return (value().ptr() == other_constant->value().ptr() &&
           representation() == other_constant->representation());
 }
 
@@ -2462,11 +2460,11 @@
     Definition* replacement = NULL;
     if (Token::IsRelationalOperator(kind())) {
       replacement = new RelationalOpInstr(
-          token_pos(), kind(), left()->CopyWithType(), right()->CopyWithType(),
+          source(), kind(), left()->CopyWithType(), right()->CopyWithType(),
           op_cid, DeoptId::kNone, speculative_mode);
     } else if (Token::IsEqualityOperator(kind())) {
       replacement = new EqualityCompareInstr(
-          token_pos(), kind(), left()->CopyWithType(), right()->CopyWithType(),
+          source(), kind(), left()->CopyWithType(), right()->CopyWithType(),
           op_cid, DeoptId::kNone, speculative_mode);
     }
     if (replacement != NULL) {
@@ -2745,8 +2743,10 @@
     case Slot::Kind::kFunction_kind_tag:
     case Slot::Kind::kFunction_packed_fields:
     case Slot::Kind::kFunction_parameter_names:
-    case Slot::Kind::kFunction_parameter_types:
-    case Slot::Kind::kFunction_type_parameters:
+    case Slot::Kind::kFunction_signature:
+    case Slot::Kind::kFunctionType_packed_fields:
+    case Slot::Kind::kFunctionType_parameter_types:
+    case Slot::Kind::kFunctionType_type_parameters:
     case Slot::Kind::kPointerBase_data_field:
     case Slot::Kind::kType_arguments:
     case Slot::Kind::kTypeArgumentsIndex:
@@ -2880,10 +2880,10 @@
   // Check that instance really has the field which we
   // are trying to load from.
   Class& cls = Class::Handle(instance.clazz());
-  while (cls.raw() != Class::null() && cls.raw() != field.Owner()) {
+  while (cls.ptr() != Class::null() && cls.ptr() != field.Owner()) {
     cls = cls.SuperClass();
   }
-  if (cls.raw() != field.Owner()) {
+  if (cls.ptr() != field.Owner()) {
     // Failed to find the field in class or its superclasses.
     return false;
   }
@@ -3070,7 +3070,7 @@
 
   if (instantiator_type_arguments()->BindsToConstant()) {
     const Object& val = instantiator_type_arguments()->BoundConstant();
-    instantiator_type_args = (val.raw() == TypeArguments::null())
+    instantiator_type_args = (val.ptr() == TypeArguments::null())
                                  ? &TypeArguments::null_type_arguments()
                                  : &TypeArguments::Cast(val);
   }
@@ -3078,7 +3078,7 @@
   if (function_type_arguments()->BindsToConstant()) {
     const Object& val = function_type_arguments()->BoundConstant();
     function_type_args =
-        (val.raw() == TypeArguments::null())
+        (val.ptr() == TypeArguments::null())
             ? &TypeArguments::null_type_arguments()
             : &TypeArguments::Cast(function_type_arguments()->BoundConstant());
   }
@@ -3463,10 +3463,10 @@
   PassiveObject& constant = PassiveObject::Handle();
   Value* other = NULL;
   if (compare->right()->BindsToConstant()) {
-    constant = compare->right()->BoundConstant().raw();
+    constant = compare->right()->BoundConstant().ptr();
     other = compare->left();
   } else if (compare->left()->BindsToConstant()) {
-    constant = compare->left()->BoundConstant().raw();
+    constant = compare->left()->BoundConstant().ptr();
     other = compare->right();
   } else {
     return compare;
@@ -3476,17 +3476,17 @@
   Definition* other_defn = other->definition();
   Token::Kind kind = compare->kind();
   // Handle e === true.
-  if ((kind == Token::kEQ_STRICT) && (constant.raw() == Bool::True().raw()) &&
+  if ((kind == Token::kEQ_STRICT) && (constant.ptr() == Bool::True().ptr()) &&
       can_merge) {
     return other_defn;
   }
   // Handle e !== false.
-  if ((kind == Token::kNE_STRICT) && (constant.raw() == Bool::False().raw()) &&
+  if ((kind == Token::kNE_STRICT) && (constant.ptr() == Bool::False().ptr()) &&
       can_merge) {
     return other_defn;
   }
   // Handle e !== true.
-  if ((kind == Token::kNE_STRICT) && (constant.raw() == Bool::True().raw()) &&
+  if ((kind == Token::kNE_STRICT) && (constant.ptr() == Bool::True().ptr()) &&
       other_defn->IsComparison() && can_merge &&
       other_defn->HasOnlyUse(other)) {
     ComparisonInstr* comp = other_defn->AsComparison();
@@ -3496,7 +3496,7 @@
     }
   }
   // Handle e === false.
-  if ((kind == Token::kEQ_STRICT) && (constant.raw() == Bool::False().raw()) &&
+  if ((kind == Token::kEQ_STRICT) && (constant.ptr() == Bool::False().ptr()) &&
       other_defn->IsComparison() && can_merge &&
       other_defn->HasOnlyUse(other)) {
     ComparisonInstr* comp = other_defn->AsComparison();
@@ -3604,7 +3604,7 @@
         THR_Print("Merging test smi v%" Pd "\n", bit_and->ssa_temp_index());
       }
       TestSmiInstr* test = new TestSmiInstr(
-          comparison()->token_pos(),
+          comparison()->source(),
           negate ? Token::NegateComparison(comparison()->kind())
                  : comparison()->kind(),
           bit_and->left()->Copy(zone), bit_and->right()->Copy(zone));
@@ -3663,12 +3663,12 @@
   return this;
 }
 
-TestCidsInstr::TestCidsInstr(TokenPosition token_pos,
+TestCidsInstr::TestCidsInstr(const InstructionSource& source,
                              Token::Kind kind,
                              Value* value,
                              const ZoneGrowableArray<intptr_t>& cid_results,
                              intptr_t deopt_id)
-    : TemplateComparison(token_pos, kind, deopt_id),
+    : TemplateComparison(source, kind, deopt_id),
       cid_results_(cid_results),
       licm_hoisted_(false) {
   ASSERT((kind == Token::kIS) || (kind == Token::kISNOT));
@@ -3902,7 +3902,7 @@
   CallTargets* targets = new (zone) CallTargets(zone);
   const intptr_t count = 1;
   targets->cid_ranges_.Add(new (zone) TargetInfo(
-      receiver_cid, receiver_cid, &Function::ZoneHandle(zone, target.raw()),
+      receiver_cid, receiver_cid, &Function::ZoneHandle(zone, target.ptr()),
       count, StaticTypeExactnessState::NotTracking()));
   return targets;
 }
@@ -3950,7 +3950,7 @@
       bool class_is_abstract = false;
       if (FlowGraphCompiler::LookupMethodFor(i, name, args_desc, &fn,
                                              &class_is_abstract) &&
-          fn.raw() == target.raw()) {
+          fn.ptr() == target.ptr()) {
         if (!class_is_abstract) {
           target_info->cid_start = i;
           target_info->exactness = StaticTypeExactnessState::NotTracking();
@@ -3963,7 +3963,7 @@
 
   // Spread class-ids to following classes where a lookup yields the same
   // method.
-  const intptr_t max_cid = Isolate::Current()->class_table()->NumCids();
+  const intptr_t max_cid = IsolateGroup::Current()->class_table()->NumCids();
   for (int idx = 0; idx < length; idx++) {
     int upper_limit_cid =
         (idx == length - 1) ? max_cid : targets[idx + 1].cid_start;
@@ -3980,7 +3980,7 @@
       bool class_is_abstract = false;
       if (FlowGraphCompiler::LookupMethodFor(i, name, args_desc, &fn,
                                              &class_is_abstract) &&
-          fn.raw() == target.raw()) {
+          fn.ptr() == target.ptr()) {
         cid_end_including_abstract = i;
         if (!class_is_abstract) {
           target_info->cid_end = i;
@@ -3997,7 +3997,7 @@
     if ((cid_end_including_abstract > target_info->cid_end) &&
         (idx < length - 1) &&
         ((cid_end_including_abstract + 1) == targets[idx + 1].cid_start) &&
-        (target.raw() == targets.TargetAt(idx + 1)->target->raw())) {
+        (target.ptr() == targets.TargetAt(idx + 1)->target->ptr())) {
       target_info->cid_end = cid_end_including_abstract;
       target_info->exactness = StaticTypeExactnessState::NotTracking();
     }
@@ -4019,7 +4019,7 @@
   for (int src = 1; src < length(); src++) {
     const Function& target = *TargetAt(dest)->target;
     if (TargetAt(dest)->cid_end + 1 >= TargetAt(src)->cid_start &&
-        target.raw() == TargetAt(src)->target->raw() &&
+        target.ptr() == TargetAt(src)->target->ptr() &&
         !target.is_polymorphic_target()) {
       TargetAt(dest)->cid_end = TargetAt(src)->cid_end;
       TargetAt(dest)->count += TargetAt(src)->count;
@@ -4066,8 +4066,8 @@
 void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Bind(compiler->GetJumpLabel(this));
   if (!compiler->is_optimizing()) {
-    compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, GetDeoptId(),
-                                   TokenPosition::kNoSource);
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
+                                   InstructionSource());
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -4093,8 +4093,8 @@
     // The deoptimization descriptor points after the edge counter code for
     // uniformity with ARM, where we can reuse pattern matching code that
     // matches backwards from the end of the pattern.
-    compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, GetDeoptId(),
-                                   TokenPosition::kNoSource);
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
+                                   InstructionSource());
   }
   if (HasParallelMove()) {
     if (compiler::Assembler::EmittingComments()) {
@@ -4167,8 +4167,8 @@
     // The deoptimization descriptor points after the edge counter code for
     // uniformity with ARM, where we can reuse pattern matching code that
     // matches backwards from the end of the pattern.
-    compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, GetDeoptId(),
-                                   TokenPosition::kNoSource);
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
+                                   InstructionSource());
   }
   if (HasParallelMove()) {
     if (compiler::Assembler::EmittingComments()) {
@@ -4187,6 +4187,10 @@
   __ Comment("SaveArguments");
 
   // Save the argument registers, in reverse order.
+  const auto& return_loc = marshaller_.Location(compiler::ffi::kResultIndex);
+  if (return_loc.IsPointerToMemory()) {
+    SaveArgument(compiler, return_loc.AsPointerToMemory().pointer_location());
+  }
   for (intptr_t i = marshaller_.num_args(); i-- > 0;) {
     SaveArgument(compiler, marshaller_.Location(i));
   }
@@ -4214,8 +4218,24 @@
     const auto& dst = compiler::ffi::NativeStackLocation(
         nloc.payload_type(), nloc.payload_type(), SPREG, 0);
     compiler->EmitNativeMove(dst, nloc, &temp_alloc);
+  } else if (nloc.IsPointerToMemory()) {
+    const auto& pointer_loc = nloc.AsPointerToMemory().pointer_location();
+    if (pointer_loc.IsRegisters()) {
+      const auto& regs_loc = pointer_loc.AsRegisters();
+      ASSERT(regs_loc.num_regs() == 1);
+      __ PushRegister(regs_loc.reg_at(0));
+    } else {
+      ASSERT(pointer_loc.IsStack());
+      // It's already on the stack, so we don't have to save it.
+    }
   } else {
-    UNREACHABLE();
+    ASSERT(nloc.IsMultiple());
+    const auto& multiple = nloc.AsMultiple();
+    const intptr_t num = multiple.locations().length();
+    // Save the argument registers, in reverse order.
+    for (intptr_t i = num; i-- > 0;) {
+      SaveArgument(compiler, *multiple.locations().At(i));
+    }
   }
 }
 
@@ -4316,11 +4336,11 @@
     __ LoadObject(InitStaticFieldABI::kFieldReg,
                   Field::ZoneHandle(field().Original()));
 
-    auto object_store = compiler->isolate()->object_store();
+    auto object_store = compiler->isolate_group()->object_store();
     const auto& init_static_field_stub = Code::ZoneHandle(
         compiler->zone(), object_store->init_static_field_stub());
-    compiler->GenerateStubCall(token_pos(), init_static_field_stub,
-                               /*kind=*/PcDescriptorsLayout::kOther, locs(),
+    compiler->GenerateStubCall(source(), init_static_field_stub,
+                               /*kind=*/UntaggedPcDescriptors::kOther, locs(),
                                deopt_id());
     __ Bind(&no_call);
   }
@@ -4353,7 +4373,7 @@
 
   __ LoadObject(InitInstanceFieldABI::kFieldReg, original_field);
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   auto& stub = Code::ZoneHandle(compiler->zone());
   if (field.needs_load_guard()) {
     stub = object_store->init_instance_field_stub();
@@ -4379,8 +4399,8 @@
   // Instruction inputs are popped from the stack at this point,
   // so deoptimization environment has to be adjusted.
   // This adjustment is done in FlowGraph::AttachEnvironment.
-  compiler->GenerateStubCall(token_pos(), stub,
-                             /*kind=*/PcDescriptorsLayout::kOther, locs(),
+  compiler->GenerateStubCall(source(), stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs(),
                              deopt_id());
   __ Bind(&no_call);
 }
@@ -4395,12 +4415,12 @@
 }
 
 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& throw_stub =
       Code::ZoneHandle(compiler->zone(), object_store->throw_stub());
 
-  compiler->GenerateStubCall(token_pos(), throw_stub,
-                             /*kind=*/PcDescriptorsLayout::kOther, locs(),
+  compiler->GenerateStubCall(source(), throw_stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs(),
                              deopt_id());
   // Issue(dartbug.com/41353): Right now we have to emit an extra breakpoint
   // instruction: The ThrowInstr will terminate the current block. The very
@@ -4422,13 +4442,13 @@
 }
 
 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& re_throw_stub =
       Code::ZoneHandle(compiler->zone(), object_store->re_throw_stub());
 
   compiler->SetNeedsStackTrace(catch_try_index());
-  compiler->GenerateStubCall(token_pos(), re_throw_stub,
-                             /*kind=*/PcDescriptorsLayout::kOther, locs(),
+  compiler->GenerateStubCall(source(), re_throw_stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs(),
                              deopt_id());
   // Issue(dartbug.com/41353): Right now we have to emit an extra breakpoint
   // instruction: The ThrowInstr will terminate the current block. The very
@@ -4454,15 +4474,15 @@
   // Check that the type of the value is allowed in conditional context.
   ASSERT(locs()->always_calls());
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& assert_boolean_stub =
       Code::ZoneHandle(compiler->zone(), object_store->assert_boolean_stub());
 
   compiler::Label done;
   __ CompareObject(AssertBooleanABI::kObjectReg, Object::null_instance());
   __ BranchIf(NOT_EQUAL, &done);
-  compiler->GenerateStubCall(token_pos(), assert_boolean_stub,
-                             /*kind=*/PcDescriptorsLayout::kOther, locs(),
+  compiler->GenerateStubCall(source(), assert_boolean_stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs(),
                              deopt_id());
   __ Bind(&done);
 }
@@ -4522,8 +4542,12 @@
       /*old_base=*/SPREG, /*new_base=*/FPREG,
       (-kExitLinkSlotFromEntryFp + kEntryFramePadding) *
           compiler::target::kWordSize);
+  const auto& location =
+      marshaller_.NativeLocationOfNativeParameter(def_index_);
   const auto& src =
-      rebase.Rebase(marshaller_.NativeLocationOfNativeParameter(index_));
+      rebase.Rebase(location.IsPointerToMemory()
+                        ? location.AsPointerToMemory().pointer_location()
+                        : location);
   NoTemporaryAllocator no_temp;
   const Location out_loc = locs()->out(0);
   const Representation out_rep = representation();
@@ -4665,13 +4689,13 @@
   __ Drop(num_temps());
 }
 
-StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos,
+StrictCompareInstr::StrictCompareInstr(const InstructionSource& source,
                                        Token::Kind kind,
                                        Value* left,
                                        Value* right,
                                        bool needs_number_check,
                                        intptr_t deopt_id)
-    : TemplateComparison(token_pos, kind, deopt_id),
+    : TemplateComparison(source, kind, deopt_id),
       needs_number_check_(needs_number_check) {
   ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
   SetInputAt(0, left);
@@ -4700,7 +4724,7 @@
                                                    right.constant());
   } else {
     true_condition = compiler->EmitEqualityRegRegCompare(
-        left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id());
+        left.reg(), right.reg(), needs_number_check(), source(), deopt_id());
   }
   return true_condition != kInvalidCondition && (kind() != Token::kEQ_STRICT)
              ? InvertCondition(true_condition)
@@ -4757,11 +4781,11 @@
   }
   switch (kind) {
     case Token::kADD:
-      return StubCode::SmiAddInlineCache().raw();
+      return StubCode::SmiAddInlineCache().ptr();
     case Token::kLT:
-      return StubCode::SmiLessInlineCache().raw();
+      return StubCode::SmiLessInlineCache().ptr();
     case Token::kEQ:
-      return StubCode::SmiEqualInlineCache().raw();
+      return StubCode::SmiEqualInlineCache().ptr();
     default:
       return Code::null();
   }
@@ -4833,7 +4857,7 @@
     smi_op_target = Resolver::ResolveDynamicAnyArgs(zone, smi_class, demangled);
   }
 #endif
-  return smi_op_target.raw();
+  return smi_op_target.ptr();
 }
 
 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -4858,33 +4882,33 @@
 
     AbstractType& receivers_static_type = AbstractType::Handle(zone);
     if (receivers_static_type_ != nullptr) {
-      receivers_static_type = receivers_static_type_->raw();
+      receivers_static_type = receivers_static_type_->ptr();
     }
 
     call_ic_data = compiler->GetOrAddInstanceCallICData(
         deopt_id(), function_name(), arguments_descriptor,
         checked_argument_count(), receivers_static_type, binary_smi_op_target);
   } else {
-    call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw());
+    call_ic_data = &ICData::ZoneHandle(zone, ic_data()->ptr());
   }
 
   if (compiler->is_optimizing() && HasICData()) {
     if (ic_data()->NumberOfUsedChecks() > 0) {
       const ICData& unary_ic_data =
           ICData::ZoneHandle(zone, ic_data()->AsUnaryClassChecks());
-      compiler->GenerateInstanceCall(deopt_id(), token_pos(), locs(),
+      compiler->GenerateInstanceCall(deopt_id(), source(), locs(),
                                      unary_ic_data, entry_kind(),
                                      !receiver_is_not_smi());
     } else {
       // Call was not visited yet, use original ICData in order to populate it.
-      compiler->GenerateInstanceCall(deopt_id(), token_pos(), locs(),
+      compiler->GenerateInstanceCall(deopt_id(), source(), locs(),
                                      *call_ic_data, entry_kind(),
                                      !receiver_is_not_smi());
     }
   } else {
     // Unoptimized code.
-    compiler->AddCurrentDescriptor(PcDescriptorsLayout::kRewind, deopt_id(),
-                                   token_pos());
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kRewind, deopt_id(),
+                                   source());
 
     // If the ICData contains a (Smi, Smi, <binary-smi-op-target>) stub already
     // we will call the specialized IC Stub that works as a normal IC Stub but
@@ -4896,7 +4920,7 @@
       auto& target = Function::Handle();
       call_ic_data->GetCheckAt(0, &class_ids, &target);
       if (class_ids[0] == kSmiCid && class_ids[1] == kSmiCid &&
-          target.raw() == binary_smi_op_target.raw()) {
+          target.ptr() == binary_smi_op_target.ptr()) {
         use_specialized_smi_ic_stub = true;
       }
     }
@@ -4904,10 +4928,10 @@
     if (use_specialized_smi_ic_stub) {
       ASSERT(ArgumentCount() == 2);
       compiler->EmitInstanceCallJIT(specialized_binary_smi_ic_stub,
-                                    *call_ic_data, deopt_id(), token_pos(),
-                                    locs(), entry_kind());
+                                    *call_ic_data, deopt_id(), source(), locs(),
+                                    entry_kind());
     } else {
-      compiler->GenerateInstanceCall(deopt_id(), token_pos(), locs(),
+      compiler->GenerateInstanceCall(deopt_id(), source(), locs(),
                                      *call_ic_data, entry_kind(),
                                      !receiver_is_not_smi());
     }
@@ -4995,12 +5019,9 @@
     args->Add(call->ArgumentValueAt(i)->CopyWithType());
   }
   args->Add(cid);
-  auto dispatch_table_call = new (zone) DispatchTableCallInstr(
-      call->token_pos(), interface_target, selector, args,
-      call->type_args_len(), call->argument_names());
-  if (call->has_inlining_id()) {
-    dispatch_table_call->set_inlining_id(call->inlining_id());
-  }
+  auto dispatch_table_call = new (zone)
+      DispatchTableCallInstr(call->source(), interface_target, selector, args,
+                             call->type_args_len(), call->argument_names());
   return dispatch_table_call;
 }
 
@@ -5014,14 +5035,14 @@
   const Register cid_reg = locs()->in(0).reg();
   compiler->EmitDispatchTableCall(cid_reg, selector()->offset,
                                   arguments_descriptor);
-  compiler->EmitCallsiteMetadata(token_pos(), DeoptId::kNone,
-                                 PcDescriptorsLayout::kOther, locs());
+  compiler->EmitCallsiteMetadata(source(), DeoptId::kNone,
+                                 UntaggedPcDescriptors::kOther, locs());
   if (selector()->called_on_null && !selector()->on_null_interface) {
     Value* receiver = ArgumentValueAt(FirstArgIndex());
     if (receiver->Type()->is_nullable()) {
       const String& function_name =
           String::ZoneHandle(interface_target().name());
-      compiler->AddNullCheck(token_pos(), function_name);
+      compiler->AddNullCheck(source(), function_name);
     }
   }
   __ Drop(ArgumentsSize());
@@ -5086,7 +5107,7 @@
 bool CallTargets::HasSingleTarget() const {
   if (length() == 0) return false;
   for (int i = 0; i < length(); i++) {
-    if (TargetAt(i)->target->raw() != TargetAt(0)->target->raw()) return false;
+    if (TargetAt(i)->target->ptr() != TargetAt(0)->target->ptr()) return false;
   }
   return true;
 }
@@ -5119,7 +5140,7 @@
   const intptr_t len = targets_.length();
   Function& target = Function::Handle();
   for (intptr_t i = 0; i < len; i++) {
-    target = targets_.TargetAt(i)->target->raw();
+    target = targets_.TargetAt(i)->target->ptr();
     if (!target.IsDispatcherOrImplicitAccessor()) {
       return false;
     }
@@ -5142,7 +5163,7 @@
                           argument_names());
   UpdateReceiverSminess(compiler->zone());
   compiler->EmitPolymorphicInstanceCall(
-      this, targets(), args_info, deopt_id(), token_pos(), locs(), complete(),
+      this, targets(), args_info, deopt_id(), source(), locs(), complete(),
       total_call_count(), !receiver_is_not_smi());
 }
 
@@ -5151,29 +5172,36 @@
   bool is_string = true;
   bool is_integer = true;
   bool is_double = true;
+  bool is_type = true;
 
   const intptr_t num_checks = targets.length();
   for (intptr_t i = 0; i < num_checks; i++) {
-    ASSERT(targets.TargetAt(i)->target->raw() ==
-           targets.TargetAt(0)->target->raw());
+    ASSERT(targets.TargetAt(i)->target->ptr() ==
+           targets.TargetAt(0)->target->ptr());
     const intptr_t start = targets[i].cid_start;
     const intptr_t end = targets[i].cid_end;
     for (intptr_t cid = start; cid <= end; cid++) {
       is_string = is_string && IsStringClassId(cid);
       is_integer = is_integer && IsIntegerClassId(cid);
       is_double = is_double && (cid == kDoubleCid);
+      is_type = is_type && IsTypeClassId(cid);
     }
   }
 
   if (is_string) {
     ASSERT(!is_integer);
     ASSERT(!is_double);
+    ASSERT(!is_type);
     return Type::StringType();
   } else if (is_integer) {
     ASSERT(!is_double);
+    ASSERT(!is_type);
     return Type::IntType();
   } else if (is_double) {
+    ASSERT(!is_type);
     return Type::Double();
+  } else if (is_type) {
+    return Type::DartTypeType();
   }
 
   return Type::null();
@@ -5291,11 +5319,11 @@
         deopt_id(), function(), arguments_descriptor, num_args_checked,
         rebind_rule_);
   } else {
-    call_ic_data = &ICData::ZoneHandle(ic_data()->raw());
+    call_ic_data = &ICData::ZoneHandle(ic_data()->ptr());
   }
   ArgumentsInfo args_info(type_args_len(), ArgumentCount(), ArgumentsSize(),
                           argument_names());
-  compiler->GenerateStaticCall(deopt_id(), token_pos(), function(), args_info,
+  compiler->GenerateStaticCall(deopt_id(), source(), function(), args_info,
                                locs(), *call_ic_data, rebind_rule_,
                                entry_kind());
   if (function().IsFactory()) {
@@ -5324,7 +5352,7 @@
 }
 
 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  compiler->GenerateAssertAssignable(value()->Type(), token_pos(), deopt_id(),
+  compiler->GenerateAssertAssignable(value()->Type(), source(), deopt_id(),
                                      dst_name(), locs());
   ASSERT(locs()->in(kInstancePos).reg() == locs()->out(0).reg());
 }
@@ -5357,13 +5385,13 @@
   __ PushRegister(AssertSubtypeABI::kSubTypeReg);
   __ PushRegister(AssertSubtypeABI::kSuperTypeReg);
   __ PushRegister(AssertSubtypeABI::kDstNameReg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kSubtypeCheckRuntimeEntry, 5, locs());
+  compiler->GenerateRuntimeCall(source(), deopt_id(), kSubtypeCheckRuntimeEntry,
+                                5, locs());
 
   __ Drop(5);
 #else
-  compiler->GenerateStubCall(token_pos(), StubCode::AssertSubtype(),
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), StubCode::AssertSubtype(),
+                             UntaggedPcDescriptors::kOther, locs());
 #endif
 }
 
@@ -5475,7 +5503,7 @@
 
 void CheckNullInstr::AddMetadataForRuntimeCall(CheckNullInstr* check_null,
                                                FlowGraphCompiler* compiler) {
-  compiler->AddNullCheck(check_null->token_pos(), check_null->function_name());
+  compiler->AddNullCheck(check_null->source(), check_null->function_name());
 }
 
 void RangeErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
@@ -5483,7 +5511,7 @@
 #if defined(TARGET_ARCH_IA32)
   UNREACHABLE();
 #else
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& stub = Code::ZoneHandle(
       compiler->zone(),
       save_fpu_registers
@@ -5679,31 +5707,31 @@
 
 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left,
                                                            Value* new_right) {
-  return new EqualityCompareInstr(token_pos(), kind(), new_left, new_right,
+  return new EqualityCompareInstr(source(), kind(), new_left, new_right,
                                   operation_cid(), deopt_id());
 }
 
 ComparisonInstr* RelationalOpInstr::CopyWithNewOperands(Value* new_left,
                                                         Value* new_right) {
-  return new RelationalOpInstr(token_pos(), kind(), new_left, new_right,
+  return new RelationalOpInstr(source(), kind(), new_left, new_right,
                                operation_cid(), deopt_id(),
                                SpeculativeModeOfInputs());
 }
 
 ComparisonInstr* StrictCompareInstr::CopyWithNewOperands(Value* new_left,
                                                          Value* new_right) {
-  return new StrictCompareInstr(token_pos(), kind(), new_left, new_right,
+  return new StrictCompareInstr(source(), kind(), new_left, new_right,
                                 needs_number_check(), DeoptId::kNone);
 }
 
 ComparisonInstr* TestSmiInstr::CopyWithNewOperands(Value* new_left,
                                                    Value* new_right) {
-  return new TestSmiInstr(token_pos(), kind(), new_left, new_right);
+  return new TestSmiInstr(source(), kind(), new_left, new_right);
 }
 
 ComparisonInstr* TestCidsInstr::CopyWithNewOperands(Value* new_left,
                                                     Value* new_right) {
-  return new TestCidsInstr(token_pos(), kind(), new_left, cid_results(),
+  return new TestCidsInstr(source(), kind(), new_left, cid_results(),
                            deopt_id());
 }
 
@@ -5874,7 +5902,7 @@
   //   v8 <- StringInterpolate(v2)
 
   // Don't compile-time fold when optimizing the interpolation function itself.
-  if (flow_graph->function().raw() == CallFunction().raw()) {
+  if (flow_graph->function().ptr() == CallFunction().ptr()) {
     return this;
   }
 
@@ -5970,14 +5998,14 @@
                                    intptr_t class_id,
                                    AlignmentType alignment,
                                    intptr_t deopt_id,
-                                   TokenPosition token_pos,
+                                   const InstructionSource& source,
                                    CompileType* result_type)
-    : TemplateDefinition(deopt_id),
+    : TemplateDefinition(source, deopt_id),
       index_unboxed_(index_unboxed),
       index_scale_(index_scale),
       class_id_(class_id),
       alignment_(StrengthenAlignment(class_id, alignment)),
-      token_pos_(token_pos),
+      token_pos_(source.token_pos),
       result_type_(result_type) {
   SetInputAt(0, array);
   SetInputAt(1, index);
@@ -5991,7 +6019,7 @@
       auto load = new (Z) LoadIndexedInstr(
           array()->CopyWithType(Z), box->value()->CopyWithType(Z),
           /*index_unboxed=*/true, index_scale(), class_id(), alignment_,
-          GetDeoptId(), token_pos(), result_type_);
+          GetDeoptId(), source(), result_type_);
       flow_graph->InsertBefore(this, load, env(), FlowGraph::kValue);
       return load;
     }
@@ -6008,15 +6036,15 @@
                                      intptr_t class_id,
                                      AlignmentType alignment,
                                      intptr_t deopt_id,
-                                     TokenPosition token_pos,
+                                     const InstructionSource& source,
                                      SpeculativeMode speculative_mode)
-    : TemplateInstruction(deopt_id),
+    : TemplateInstruction(source, deopt_id),
       emit_store_barrier_(emit_store_barrier),
       index_unboxed_(index_unboxed),
       index_scale_(index_scale),
       class_id_(class_id),
       alignment_(StrengthenAlignment(class_id, alignment)),
-      token_pos_(token_pos),
+      token_pos_(source.token_pos),
       speculative_mode_(speculative_mode) {
   SetInputAt(kArrayPos, array);
   SetInputAt(kIndexPos, index);
@@ -6032,7 +6060,7 @@
           array()->CopyWithType(Z), box->value()->CopyWithType(Z),
           value()->CopyWithType(Z), emit_store_barrier_,
           /*index_unboxed=*/true, index_scale(), class_id(), alignment_,
-          GetDeoptId(), token_pos(), speculative_mode_);
+          GetDeoptId(), source(), speculative_mode_);
       flow_graph->InsertBefore(this, store, env(), FlowGraph::kEffect);
       return nullptr;
     }
@@ -6048,11 +6076,11 @@
     ZoneGrowableArray<Value*>* inputs,
     intptr_t deopt_id,
     MethodRecognizer::Kind recognized_kind,
-    TokenPosition token_pos)
-    : PureDefinition(deopt_id),
+    const InstructionSource& source)
+    : PureDefinition(source, deopt_id),
       inputs_(inputs),
       recognized_kind_(recognized_kind),
-      token_pos_(token_pos) {
+      token_pos_(source.token_pos) {
   ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_));
   for (intptr_t i = 0; i < inputs_->length(); ++i) {
     ASSERT((*inputs)[i] != NULL);
@@ -6178,6 +6206,9 @@
   NativeFunction native_function = NativeEntry::ResolveNative(
       library, native_name(), num_params, &auto_setup_scope);
   if (native_function == NULL) {
+    if (has_inlining_id()) {
+      UNIMPLEMENTED();
+    }
     Report::MessageF(Report::kError, Script::Handle(function().script()),
                      function().token_pos(), Report::AtLocation,
                      "native function '%s' (%" Pd " arguments) cannot be found",
@@ -6187,7 +6218,7 @@
   set_native_c_function(native_function);
 }
 
-#if !defined(TARGET_ARCH_ARM)
+#if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_ARM64)
 
 LocationSummary* BitCastInstr::MakeLocationSummary(Zone* zone, bool opt) const {
   UNREACHABLE();
@@ -6197,13 +6228,16 @@
   UNREACHABLE();
 }
 
-#endif  // defined(TARGET_ARCH_ARM)
+#endif  // !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_ARM64)
 
 Representation FfiCallInstr::RequiredInputRepresentation(intptr_t idx) const {
-  if (idx == TargetAddressIndex()) {
+  if (idx < TargetAddressIndex()) {
+    return marshaller_.RepInFfiCall(idx);
+  } else if (idx == TargetAddressIndex()) {
     return kUnboxedFfiIntPtr;
   } else {
-    return marshaller_.RepInFfiCall(idx);
+    ASSERT(idx == TypedDataIndex());
+    return kTagged;
   }
 }
 
@@ -6213,7 +6247,7 @@
                                                    bool is_optimizing) const {
   // The temporary register needs to be callee-saved and not an argument
   // register.
-  ASSERT(((1 << CallingConventions::kFirstCalleeSavedCpuReg) &
+  ASSERT(((1 << CallingConventions::kFfiAnyNonAbiRegister) &
           CallingConventions::kArgumentRegisters) == 0);
 
   constexpr intptr_t kNumTemps = 2;
@@ -6222,51 +6256,216 @@
       LocationSummary(zone, /*num_inputs=*/InputCount(),
                       /*num_temps=*/kNumTemps, LocationSummary::kCall);
 
+  const Register temp0 = CallingConventions::kSecondNonArgumentRegister;
+  const Register temp1 = CallingConventions::kFfiAnyNonAbiRegister;
+  ASSERT(temp0 != temp1);
+  summary->set_temp(0, Location::RegisterLocation(temp0));
+  summary->set_temp(1, Location::RegisterLocation(temp1));
+
   summary->set_in(TargetAddressIndex(),
                   Location::RegisterLocation(
                       CallingConventions::kFirstNonArgumentRegister));
-  summary->set_temp(0, Location::RegisterLocation(
-                           CallingConventions::kSecondNonArgumentRegister));
-  summary->set_temp(1, Location::RegisterLocation(
-                           CallingConventions::kFirstCalleeSavedCpuReg));
-  summary->set_out(0, marshaller_.LocInFfiCall(compiler::ffi::kResultIndex));
-
-  for (intptr_t i = 0, n = marshaller_.num_args(); i < n; ++i) {
+  for (intptr_t i = 0, n = marshaller_.NumDefinitions(); i < n; ++i) {
     summary->set_in(i, marshaller_.LocInFfiCall(i));
   }
 
+  if (marshaller_.PassTypedData()) {
+    // The register allocator already preserves this value across the call on
+    // a stack slot, so we'll use the spilled value directly.
+    summary->set_in(TypedDataIndex(), Location::RequiresStackSlot());
+
+    // We don't care about return location, but we need to pass a register.
+    summary->set_out(
+        0, Location::RegisterLocation(CallingConventions::kReturnReg));
+  } else {
+    summary->set_out(0, marshaller_.LocInFfiCall(compiler::ffi::kResultIndex));
+  }
+
   return summary;
 }
 
 void FfiCallInstr::EmitParamMoves(FlowGraphCompiler* compiler) {
+  if (compiler::Assembler::EmittingComments()) {
+    __ Comment("EmitParamMoves");
+  }
+
   const Register saved_fp = locs()->temp(0).reg();
   const Register temp = locs()->temp(1).reg();
 
+  // Moves for return pointer.
+  const auto& return_location =
+      marshaller_.Location(compiler::ffi::kResultIndex);
+  if (return_location.IsPointerToMemory()) {
+    const auto& pointer_location =
+        return_location.AsPointerToMemory().pointer_location();
+    const auto& pointer_register =
+        pointer_location.IsRegisters()
+            ? pointer_location.AsRegisters().reg_at(0)
+            : temp;
+    __ MoveRegister(pointer_register, SPREG);
+    __ AddImmediate(pointer_register, marshaller_.PassByPointerStackOffset(
+                                          compiler::ffi::kResultIndex));
+
+    if (pointer_location.IsStack()) {
+      const auto& pointer_stack = pointer_location.AsStack();
+      __ StoreMemoryValue(pointer_register, pointer_stack.base_register(),
+                          pointer_stack.offset_in_bytes());
+    }
+  }
+
+  // Moves for arguments.
   compiler::ffi::FrameRebase rebase(zone_, /*old_base=*/FPREG,
                                     /*new_base=*/saved_fp,
                                     /*stack_delta=*/0);
-  for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
-    const Location origin = rebase.Rebase(locs()->in(i));
-    const Representation origin_rep = RequiredInputRepresentation(i);
-    const auto& target = marshaller_.Location(i);
-    ConstantTemporaryAllocator temp_alloc(temp);
-    if (origin.IsConstant()) {
-      compiler->EmitMoveConst(target, origin, origin_rep, &temp_alloc);
-    } else {
-      compiler->EmitMoveToNative(target, origin, origin_rep, &temp_alloc);
+  intptr_t def_index = 0;
+  for (intptr_t arg_index = 0; arg_index < marshaller_.num_args();
+       arg_index++) {
+    const intptr_t num_defs = marshaller_.NumDefinitions(arg_index);
+    const auto& arg_target = marshaller_.Location(arg_index);
+
+    // First deal with moving all individual definitions passed in to the
+    // FfiCall to the right native location based on calling convention.
+    for (intptr_t i = 0; i < num_defs; i++) {
+      const Location origin = rebase.Rebase(locs()->in(def_index));
+      const Representation origin_rep =
+          RequiredInputRepresentation(def_index) == kTagged
+              ? kUnboxedFfiIntPtr  // When arg_target.IsPointerToMemory().
+              : RequiredInputRepresentation(def_index);
+
+      // Find the native location where this individual definition should be
+      // moved to.
+      const auto& def_target =
+          arg_target.payload_type().IsPrimitive()
+              ? arg_target
+              : arg_target.IsMultiple()
+                    ? *arg_target.AsMultiple().locations()[i]
+                    : arg_target.IsPointerToMemory()
+                          ? arg_target.AsPointerToMemory().pointer_location()
+                          : /*arg_target.IsStack()*/ arg_target.Split(
+                                zone_, num_defs, i);
+
+      ConstantTemporaryAllocator temp_alloc(temp);
+      if (origin.IsConstant()) {
+        compiler->EmitMoveConst(def_target, origin, origin_rep, &temp_alloc);
+      } else {
+        compiler->EmitMoveToNative(def_target, origin, origin_rep, &temp_alloc);
+      }
+      def_index++;
     }
+
+    // Then make sure that any pointers passed through the calling convention
+    // actually have a copy of the struct.
+    // Note that the step above has already moved the pointer into the expected
+    // native location.
+    if (arg_target.IsPointerToMemory()) {
+      NoTemporaryAllocator temp_alloc;
+      const auto& pointer_loc =
+          arg_target.AsPointerToMemory().pointer_location();
+
+      // TypedData/Pointer data pointed to in temp.
+      const auto& dst = compiler::ffi::NativeRegistersLocation(
+          zone_, pointer_loc.payload_type(), pointer_loc.container_type(),
+          temp);
+      compiler->EmitNativeMove(dst, pointer_loc, &temp_alloc);
+      __ LoadField(
+          temp,
+          compiler::FieldAddress(
+              temp, compiler::target::TypedDataBase::data_field_offset()));
+
+      // Copy chuncks.
+      const intptr_t sp_offset =
+          marshaller_.PassByPointerStackOffset(arg_index);
+      // Struct size is rounded up to a multiple of target::kWordSize.
+      // This is safe because we do the same rounding when we allocate the
+      // space on the stack.
+      for (intptr_t i = 0; i < arg_target.payload_type().SizeInBytes();
+           i += compiler::target::kWordSize) {
+        __ LoadMemoryValue(TMP, temp, i);
+        __ StoreMemoryValue(TMP, SPREG, i + sp_offset);
+      }
+
+      // Store the stack address in the argument location.
+      __ MoveRegister(temp, SPREG);
+      __ AddImmediate(temp, sp_offset);
+      const auto& src = compiler::ffi::NativeRegistersLocation(
+          zone_, pointer_loc.payload_type(), pointer_loc.container_type(),
+          temp);
+      compiler->EmitNativeMove(pointer_loc, src, &temp_alloc);
+    }
+  }
+
+  if (compiler::Assembler::EmittingComments()) {
+    __ Comment("EmitParamMovesEnd");
   }
 }
 
 void FfiCallInstr::EmitReturnMoves(FlowGraphCompiler* compiler) {
-  const auto& src = marshaller_.Location(compiler::ffi::kResultIndex);
-  if (src.payload_type().IsVoid()) {
+  __ Comment("EmitReturnMoves");
+
+  const auto& returnLocation =
+      marshaller_.Location(compiler::ffi::kResultIndex);
+  if (returnLocation.payload_type().IsVoid()) {
     return;
   }
-  const Location dst_loc = locs()->out(0);
-  const Representation dst_type = representation();
+
   NoTemporaryAllocator no_temp;
-  compiler->EmitMoveFromNative(dst_loc, dst_type, src, &no_temp);
+  if (returnLocation.IsRegisters() || returnLocation.IsFpuRegisters()) {
+    const auto& src = returnLocation;
+    const Location dst_loc = locs()->out(0);
+    const Representation dst_type = representation();
+    compiler->EmitMoveFromNative(dst_loc, dst_type, src, &no_temp);
+  } else if (returnLocation.IsPointerToMemory() ||
+             returnLocation.IsMultiple()) {
+    ASSERT(returnLocation.payload_type().IsCompound());
+    ASSERT(marshaller_.PassTypedData());
+
+    const Register temp0 = TMP != kNoRegister ? TMP : locs()->temp(0).reg();
+    const Register temp1 = locs()->temp(1).reg();
+    ASSERT(temp0 != temp1);
+
+    // Get the typed data pointer which we have pinned to a stack slot.
+    const Location typed_data_loc = locs()->in(TypedDataIndex());
+    ASSERT(typed_data_loc.IsStackSlot());
+    ASSERT(typed_data_loc.base_reg() == FPREG);
+    __ LoadMemoryValue(temp0, FPREG, 0);
+    __ LoadMemoryValue(temp0, temp0, typed_data_loc.ToStackSlotOffset());
+    __ LoadField(
+        temp0,
+        compiler::FieldAddress(
+            temp0, compiler::target::TypedDataBase::data_field_offset()));
+
+    if (returnLocation.IsPointerToMemory()) {
+      // Copy blocks from the stack location to TypedData.
+      // Struct size is rounded up to a multiple of target::kWordSize.
+      // This is safe because we do the same rounding when we allocate the
+      // TypedData in IL.
+      const intptr_t sp_offset =
+          marshaller_.PassByPointerStackOffset(compiler::ffi::kResultIndex);
+      for (intptr_t i = 0; i < marshaller_.TypedDataSizeInBytes();
+           i += compiler::target::kWordSize) {
+        __ LoadMemoryValue(temp1, SPREG, i + sp_offset);
+        __ StoreMemoryValue(temp1, temp0, i);
+      }
+    } else {
+      ASSERT(returnLocation.IsMultiple());
+      // Copy to the struct from the native locations.
+      const auto& multiple =
+          marshaller_.Location(compiler::ffi::kResultIndex).AsMultiple();
+
+      int offset_in_bytes = 0;
+      for (int i = 0; i < multiple.locations().length(); i++) {
+        const auto& src = *multiple.locations().At(i);
+        const auto& dst = compiler::ffi::NativeStackLocation(
+            src.payload_type(), src.container_type(), temp0, offset_in_bytes);
+        compiler->EmitNativeMove(dst, src, &no_temp);
+        offset_in_bytes += src.payload_type().SizeInBytes();
+      }
+    }
+  } else {
+    UNREACHABLE();
+  }
+
+  __ Comment("EmitReturnMovesEnd");
 }
 
 static Location FirstArgumentLocation() {
@@ -6397,10 +6596,37 @@
 }
 
 void NativeReturnInstr::EmitReturnMoves(FlowGraphCompiler* compiler) {
-  const auto& dst = marshaller_.Location(compiler::ffi::kResultIndex);
-  if (dst.payload_type().IsVoid()) {
+  const auto& dst1 = marshaller_.Location(compiler::ffi::kResultIndex);
+  if (dst1.payload_type().IsVoid()) {
     return;
   }
+  if (dst1.IsMultiple()) {
+    Register typed_data_reg = locs()->in(0).reg();
+    // Load the data pointer out of the TypedData/Pointer.
+    __ LoadField(typed_data_reg,
+                 compiler::FieldAddress(
+                     typed_data_reg,
+                     compiler::target::TypedDataBase::data_field_offset()));
+
+    const auto& multiple = dst1.AsMultiple();
+    int offset_in_bytes = 0;
+    for (intptr_t i = 0; i < multiple.locations().length(); i++) {
+      const auto& dst = *multiple.locations().At(i);
+      ASSERT(!dst.IsRegisters() ||
+             dst.AsRegisters().reg_at(0) != typed_data_reg);
+      const auto& src = compiler::ffi::NativeStackLocation(
+          dst.payload_type(), dst.container_type(), typed_data_reg,
+          offset_in_bytes);
+      NoTemporaryAllocator no_temp;
+      compiler->EmitNativeMove(dst, src, &no_temp);
+      offset_in_bytes += dst.payload_type().SizeInBytes();
+    }
+    return;
+  }
+  const auto& dst = dst1.IsPointerToMemory()
+                        ? dst1.AsPointerToMemory().pointer_return_location()
+                        : dst1;
+
   const Location src_loc = locs()->in(0);
   const Representation src_type = RequiredInputRepresentation(0);
   NoTemporaryAllocator no_temp;
@@ -6413,14 +6639,32 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(
-      0, marshaller_.LocationOfNativeParameter(compiler::ffi::kResultIndex));
+  ASSERT(marshaller_.NumReturnDefinitions() == 1);
+  const auto& native_loc = marshaller_.Location(compiler::ffi::kResultIndex);
+  const auto& native_return_loc =
+      native_loc.IsPointerToMemory()
+          ? native_loc.AsPointerToMemory().pointer_return_location()
+          : native_loc;
+  if (native_loc.IsMultiple()) {
+    // We pass in a typed data for easy copying in machine code.
+    // Can be any register which does not conflict with return registers.
+    Register typed_data_reg = CallingConventions::kSecondNonArgumentRegister;
+    ASSERT(typed_data_reg != CallingConventions::kReturnReg);
+    ASSERT(typed_data_reg != CallingConventions::kSecondReturnReg);
+    locs->set_in(0, Location::RegisterLocation(typed_data_reg));
+  } else {
+    locs->set_in(0, native_return_loc.AsLocation());
+  }
   return locs;
 }
 
 #undef Z
 
 Representation FfiCallInstr::representation() const {
+  if (marshaller_.PassTypedData()) {
+    // Don't care, we're discarding the value.
+    return kTagged;
+  }
   return marshaller_.RepInFfiCall(compiler::ffi::kResultIndex);
 }
 
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index c1a0446..169949e 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -51,6 +51,7 @@
 class FlowGraphCompiler;
 class FlowGraphSerializer;
 class FlowGraphVisitor;
+class ForwardInstructionIterator;
 class Instruction;
 class LocalVariable;
 class LoopInfo;
@@ -60,6 +61,7 @@
 class RangeBoundary;
 class SExpList;
 class SExpression;
+class SuccessorsIterable;
 class TypeUsageInfo;
 class UnboxIntegerInstr;
 
@@ -788,13 +790,19 @@
     kNotSpeculative
   };
 
-  explicit Instruction(intptr_t deopt_id = DeoptId::kNone)
+  // If the source has the inlining ID of the root function, then don't set
+  // the inlining ID to that; instead, treat it as unset.
+  explicit Instruction(const InstructionSource& source,
+                       intptr_t deopt_id = DeoptId::kNone)
       : deopt_id_(deopt_id),
         previous_(NULL),
         next_(NULL),
         env_(NULL),
         locs_(NULL),
-        inlining_id_(-1) {}
+        inlining_id_(source.inlining_id) {}
+
+  explicit Instruction(intptr_t deopt_id = DeoptId::kNone)
+      : Instruction(InstructionSource(), deopt_id) {}
 
   virtual ~Instruction() {}
 
@@ -815,6 +823,11 @@
 
   virtual TokenPosition token_pos() const { return TokenPosition::kNoSource; }
 
+  // Returns the source information for this instruction.
+  InstructionSource source() const {
+    return InstructionSource(token_pos(), inlining_id());
+  }
+
   virtual intptr_t InputCount() const = 0;
   virtual Value* InputAt(intptr_t i) const = 0;
   void SetInputAt(intptr_t i, Value* value) {
@@ -903,6 +916,8 @@
   virtual intptr_t SuccessorCount() const;
   virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
 
+  inline SuccessorsIterable successors() const;
+
   void Goto(JoinEntryInstr* entry);
 
   virtual const char* DebugName() const = 0;
@@ -1073,12 +1088,13 @@
   // Get the block entry for this instruction.
   virtual BlockEntryInstr* GetBlock();
 
-  intptr_t inlining_id() const { return inlining_id_; }
-  void set_inlining_id(intptr_t value) {
+  virtual intptr_t inlining_id() const { return inlining_id_; }
+  virtual void set_inlining_id(intptr_t value) {
     ASSERT(value >= 0);
+    ASSERT(!has_inlining_id() || inlining_id_ == value);
     inlining_id_ = value;
   }
-  bool has_inlining_id() const { return inlining_id_ >= 0; }
+  virtual bool has_inlining_id() const { return inlining_id_ >= 0; }
 
   // Returns a hash code for use with hash maps.
   virtual intptr_t Hashcode() const;
@@ -1210,6 +1226,8 @@
 class PureInstruction : public Instruction {
  public:
   explicit PureInstruction(intptr_t deopt_id) : Instruction(deopt_id) {}
+  explicit PureInstruction(const InstructionSource& source, intptr_t deopt_id)
+      : Instruction(source, deopt_id) {}
 
   virtual bool AllowsCSE() const { return true; }
   virtual bool HasUnknownSideEffects() const { return false; }
@@ -1246,6 +1264,11 @@
   explicit TemplateInstruction(intptr_t deopt_id = DeoptId::kNone)
       : CSETrait<Instruction, PureInstruction>::Base(deopt_id), inputs_() {}
 
+  TemplateInstruction(const InstructionSource& source,
+                      intptr_t deopt_id = DeoptId::kNone)
+      : CSETrait<Instruction, PureInstruction>::Base(source, deopt_id),
+        inputs_() {}
+
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
 
@@ -1487,6 +1510,19 @@
   // environment) from their definition's use lists for all instructions.
   void ClearAllInstructions();
 
+  class InstructionsIterable {
+   public:
+    explicit InstructionsIterable(BlockEntryInstr* block) : block_(block) {}
+
+    inline ForwardInstructionIterator begin() const;
+    inline ForwardInstructionIterator end() const;
+
+   private:
+    BlockEntryInstr* block_;
+  };
+
+  InstructionsIterable instructions() { return InstructionsIterable(this); }
+
   DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry)
 
   TO_S_EXPRESSION_SUPPORT
@@ -1551,8 +1587,14 @@
   DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr);
 };
 
-class ForwardInstructionIterator : public ValueObject {
+class ForwardInstructionIterator {
  public:
+  ForwardInstructionIterator(const ForwardInstructionIterator& other) = default;
+  ForwardInstructionIterator& operator=(
+      const ForwardInstructionIterator& other) = default;
+
+  ForwardInstructionIterator() : current_(nullptr) {}
+
   explicit ForwardInstructionIterator(BlockEntryInstr* block_entry)
       : current_(block_entry) {
     Advance();
@@ -1570,10 +1612,16 @@
 
   Instruction* Current() const { return current_; }
 
+  Instruction* operator*() const { return Current(); }
+
   bool operator==(const ForwardInstructionIterator& other) const {
     return current_ == other.current_;
   }
 
+  bool operator!=(const ForwardInstructionIterator& other) const {
+    return !(*this == other);
+  }
+
   ForwardInstructionIterator& operator++() {
     Advance();
     return *this;
@@ -1583,6 +1631,15 @@
   Instruction* current_;
 };
 
+ForwardInstructionIterator BlockEntryInstr::InstructionsIterable::begin()
+    const {
+  return ForwardInstructionIterator(block_);
+}
+
+ForwardInstructionIterator BlockEntryInstr::InstructionsIterable::end() const {
+  return ForwardInstructionIterator();
+}
+
 class BackwardInstructionIterator : public ValueObject {
  public:
   explicit BackwardInstructionIterator(BlockEntryInstr* block_entry)
@@ -1677,6 +1734,10 @@
     spill_slot_count_ = count;
   }
 
+  // Returns true if this flow graph needs a stack frame.
+  bool NeedsFrame() const { return needs_frame_; }
+  void MarkFrameless() { needs_frame_ = false; }
+
   // Number of stack slots reserved for compiling try-catch. For functions
   // without try-catch, this is 0. Otherwise, it is the number of local
   // variables.
@@ -1731,6 +1792,7 @@
   intptr_t entry_count_;
   intptr_t spill_slot_count_;
   intptr_t fixed_slot_count_;  // For try-catch in optimized code.
+  bool needs_frame_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr);
 };
@@ -2004,7 +2066,7 @@
                                   /*stack_depth=*/0),
         graph_entry_(graph_entry),
         predecessor_(NULL),
-        catch_handler_types_(Array::ZoneHandle(handler_types.raw())),
+        catch_handler_types_(Array::ZoneHandle(handler_types.ptr())),
         catch_try_index_(catch_try_index),
         exception_var_(exception_var),
         stacktrace_var_(stacktrace_var),
@@ -2152,7 +2214,12 @@
 // Abstract super-class of all instructions that define a value (Bind, Phi).
 class Definition : public Instruction {
  public:
-  explicit Definition(intptr_t deopt_id = DeoptId::kNone);
+  explicit Definition(intptr_t deopt_id = DeoptId::kNone)
+      : Instruction(deopt_id) {}
+
+  explicit Definition(const InstructionSource& source,
+                      intptr_t deopt_id = DeoptId::kNone)
+      : Instruction(source, deopt_id) {}
 
   // Overridden by definitions that have call counts.
   virtual intptr_t CallCount() const { return -1; }
@@ -2364,6 +2431,8 @@
 class PureDefinition : public Definition {
  public:
   explicit PureDefinition(intptr_t deopt_id) : Definition(deopt_id) {}
+  explicit PureDefinition(const InstructionSource& source, intptr_t deopt_id)
+      : Definition(source, deopt_id) {}
 
   virtual bool AllowsCSE() const { return true; }
   virtual bool HasUnknownSideEffects() const { return false; }
@@ -2376,6 +2445,10 @@
  public:
   explicit TemplateDefinition(intptr_t deopt_id = DeoptId::kNone)
       : CSETrait<Definition, PureDefinition>::Base(deopt_id), inputs_() {}
+  TemplateDefinition(const InstructionSource& source,
+                     intptr_t deopt_id = DeoptId::kNone)
+      : CSETrait<Definition, PureDefinition>::Base(source, deopt_id),
+        inputs_() {}
 
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
@@ -2579,16 +2652,13 @@
 class NativeParameterInstr : public Definition {
  public:
   NativeParameterInstr(const compiler::ffi::CallbackMarshaller& marshaller,
-                       intptr_t index)
-      : marshaller_(marshaller), index_(index) {
-    const auto& loc = marshaller.NativeLocationOfNativeParameter(index_);
-    ASSERT(loc.IsStack() && loc.AsStack().base_register() == SPREG);
-  }
+                       intptr_t def_index)
+      : marshaller_(marshaller), def_index_(def_index) {}
 
   DECLARE_INSTRUCTION(NativeParameter)
 
   virtual Representation representation() const {
-    return marshaller_.RepInFfiCall(index_);
+    return marshaller_.RepInFfiCall(def_index_);
   }
 
   intptr_t InputCount() const { return 0; }
@@ -2612,7 +2682,7 @@
   virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
 
   const compiler::ffi::CallbackMarshaller& marshaller_;
-  const intptr_t index_;
+  const intptr_t def_index_;
 
   DISALLOW_COPY_AND_ASSIGN(NativeParameterInstr);
 };
@@ -2899,13 +2969,13 @@
  public:
   // The [yield_index], if provided, will cause the instruction to emit extra
   // yield_index -> pc offset into the [PcDescriptors].
-  ReturnInstr(TokenPosition token_pos,
+  ReturnInstr(const InstructionSource& source,
               Value* value,
               intptr_t deopt_id,
-              intptr_t yield_index = PcDescriptorsLayout::kInvalidYieldIndex,
+              intptr_t yield_index = UntaggedPcDescriptors::kInvalidYieldIndex,
               Representation representation = kTagged)
-      : TemplateInstruction(deopt_id),
-        token_pos_(token_pos),
+      : TemplateInstruction(source, deopt_id),
+        token_pos_(source.token_pos),
         yield_index_(yield_index),
         representation_(representation) {
     SetInputAt(0, value);
@@ -2960,11 +3030,11 @@
 // Represents a return from a Dart function into native code.
 class NativeReturnInstr : public ReturnInstr {
  public:
-  NativeReturnInstr(TokenPosition token_pos,
+  NativeReturnInstr(const InstructionSource& source,
                     Value* value,
                     const compiler::ffi::CallbackMarshaller& marshaller,
                     intptr_t deopt_id)
-      : ReturnInstr(token_pos, value, deopt_id), marshaller_(marshaller) {}
+      : ReturnInstr(source, value, deopt_id), marshaller_(marshaller) {}
 
   DECLARE_INSTRUCTION(NativeReturn)
 
@@ -2991,10 +3061,10 @@
 
 class ThrowInstr : public TemplateInstruction<1, Throws> {
  public:
-  explicit ThrowInstr(TokenPosition token_pos,
+  explicit ThrowInstr(const InstructionSource& source,
                       intptr_t deopt_id,
                       Value* exception)
-      : TemplateInstruction(deopt_id), token_pos_(token_pos) {
+      : TemplateInstruction(source, deopt_id), token_pos_(source.token_pos) {
     SetInputAt(0, exception);
   }
 
@@ -3019,13 +3089,13 @@
  public:
   // 'catch_try_index' can be kInvalidTryIndex if the
   // rethrow has been artificially generated by the parser.
-  ReThrowInstr(TokenPosition token_pos,
+  ReThrowInstr(const InstructionSource& source,
                intptr_t catch_try_index,
                intptr_t deopt_id,
                Value* exception,
                Value* stacktrace)
-      : TemplateInstruction(deopt_id),
-        token_pos_(token_pos),
+      : TemplateInstruction(source, deopt_id),
+        token_pos_(source.token_pos),
         catch_try_index_(catch_try_index) {
     SetInputAt(0, exception);
     SetInputAt(1, stacktrace);
@@ -3240,11 +3310,11 @@
   DEFINE_INSTRUCTION_TYPE_CHECK(Comparison)
 
  protected:
-  ComparisonInstr(TokenPosition token_pos,
+  ComparisonInstr(const InstructionSource& source,
                   Token::Kind kind,
                   intptr_t deopt_id = DeoptId::kNone)
-      : Definition(deopt_id),
-        token_pos_(token_pos),
+      : Definition(source, deopt_id),
+        token_pos_(source.token_pos),
         kind_(kind),
         operation_cid_(kIllegalCid) {}
 
@@ -3262,8 +3332,10 @@
   virtual bool HasUnknownSideEffects() const { return false; }
 
  protected:
-  PureComparison(TokenPosition token_pos, Token::Kind kind, intptr_t deopt_id)
-      : ComparisonInstr(token_pos, kind, deopt_id) {}
+  PureComparison(const InstructionSource& source,
+                 Token::Kind kind,
+                 intptr_t deopt_id)
+      : ComparisonInstr(source, kind, deopt_id) {}
 };
 
 template <intptr_t N,
@@ -3272,12 +3344,10 @@
 class TemplateComparison
     : public CSETrait<ComparisonInstr, PureComparison>::Base {
  public:
-  TemplateComparison(TokenPosition token_pos,
+  TemplateComparison(const InstructionSource& source,
                      Token::Kind kind,
                      intptr_t deopt_id = DeoptId::kNone)
-      : CSETrait<ComparisonInstr, PureComparison>::Base(token_pos,
-                                                        kind,
-                                                        deopt_id),
+      : CSETrait<ComparisonInstr, PureComparison>::Base(source, kind, deopt_id),
         inputs_() {}
 
   virtual intptr_t InputCount() const { return N; }
@@ -3319,6 +3389,13 @@
   Value* InputAt(intptr_t i) const { return comparison()->InputAt(i); }
 
   virtual TokenPosition token_pos() const { return comparison_->token_pos(); }
+  virtual intptr_t inlining_id() const { return comparison_->inlining_id(); }
+  virtual void set_inlining_id(intptr_t value) {
+    return comparison_->set_inlining_id(value);
+  }
+  virtual bool has_inlining_id() const {
+    return comparison_->has_inlining_id();
+  }
 
   virtual bool ComputeCanDeoptimize() const {
     return comparison()->ComputeCanDeoptimize();
@@ -3491,8 +3568,9 @@
 
 class ConstantInstr : public TemplateDefinition<0, NoThrow, Pure> {
  public:
-  ConstantInstr(const Object& value,
-                TokenPosition token_pos = TokenPosition::kConstant);
+  explicit ConstantInstr(const Object& value)
+      : ConstantInstr(value, InstructionSource(TokenPosition::kConstant)) {}
+  ConstantInstr(const Object& value, const InstructionSource& source);
 
   DECLARE_INSTRUCTION(Constant)
   virtual CompileType ComputeType() const;
@@ -3560,14 +3638,14 @@
     kDstNamePos = 4,
   };
 
-  AssertSubtypeInstr(TokenPosition token_pos,
+  AssertSubtypeInstr(const InstructionSource& source,
                      Value* instantiator_type_arguments,
                      Value* function_type_arguments,
                      Value* sub_type,
                      Value* super_type,
                      Value* dst_name,
                      intptr_t deopt_id)
-      : TemplateInstruction(deopt_id), token_pos_(token_pos) {
+      : TemplateInstruction(source, deopt_id), token_pos_(source.token_pos) {
     SetInputAt(kInstantiatorTAVPos, instantiator_type_arguments);
     SetInputAt(kFunctionTAVPos, function_type_arguments);
     SetInputAt(kSubTypePos, sub_type);
@@ -3627,7 +3705,7 @@
     kFunctionTAVPos = 3,
   };
 
-  AssertAssignableInstr(TokenPosition token_pos,
+  AssertAssignableInstr(const InstructionSource& source,
                         Value* value,
                         Value* dst_type,
                         Value* instantiator_type_arguments,
@@ -3635,8 +3713,8 @@
                         const String& dst_name,
                         intptr_t deopt_id,
                         Kind kind = kUnknown)
-      : TemplateDefinition(deopt_id),
-        token_pos_(token_pos),
+      : TemplateDefinition(source, deopt_id),
+        token_pos_(source.token_pos),
         dst_name_(dst_name),
         kind_(kind) {
     ASSERT(!dst_name.IsNull());
@@ -3691,8 +3769,10 @@
 
 class AssertBooleanInstr : public TemplateDefinition<1, Throws, Pure> {
  public:
-  AssertBooleanInstr(TokenPosition token_pos, Value* value, intptr_t deopt_id)
-      : TemplateDefinition(deopt_id), token_pos_(token_pos) {
+  AssertBooleanInstr(const InstructionSource& source,
+                     Value* value,
+                     intptr_t deopt_id)
+      : TemplateDefinition(source, deopt_id), token_pos_(source.token_pos) {
     SetInputAt(0, value);
   }
 
@@ -3809,12 +3889,12 @@
                    intptr_t type_args_len,
                    const Array& argument_names,
                    InputsArray* inputs,
-                   TokenPosition token_pos)
-      : Definition(deopt_id),
+                   const InstructionSource& source)
+      : Definition(source, deopt_id),
         type_args_len_(type_args_len),
         argument_names_(argument_names),
         inputs_(inputs),
-        token_pos_(token_pos) {
+        token_pos_(source.token_pos) {
     ASSERT(argument_names.IsZoneHandle() || argument_names.InVMIsolateHeap());
     ASSERT(inputs_->length() >= kExtraInputs);
     for (intptr_t i = 0, n = inputs_->length(); i < n; ++i) {
@@ -3898,14 +3978,14 @@
   ClosureCallInstr(InputsArray* inputs,
                    intptr_t type_args_len,
                    const Array& argument_names,
-                   TokenPosition token_pos,
+                   const InstructionSource& source,
                    intptr_t deopt_id,
                    Code::EntryKind entry_kind = Code::EntryKind::kNormal)
       : TemplateDartCall(deopt_id,
                          type_args_len,
                          argument_names,
                          inputs,
-                         token_pos),
+                         source),
         entry_kind_(entry_kind) {}
 
   DECLARE_INSTRUCTION(ClosureCall)
@@ -3934,7 +4014,7 @@
 // (InstanceCallInstr, PolymorphicInstanceCallInstr).
 class InstanceCallBaseInstr : public TemplateDartCall<0> {
  public:
-  InstanceCallBaseInstr(TokenPosition token_pos,
+  InstanceCallBaseInstr(const InstructionSource& source,
                         const String& function_name,
                         Token::Kind token_kind,
                         InputsArray* arguments,
@@ -3948,7 +4028,7 @@
                          type_args_len,
                          argument_names,
                          arguments,
-                         token_pos),
+                         source),
         ic_data_(ic_data),
         function_name_(function_name),
         token_kind_(token_kind),
@@ -4074,7 +4154,7 @@
 class InstanceCallInstr : public InstanceCallBaseInstr {
  public:
   InstanceCallInstr(
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const String& function_name,
       Token::Kind token_kind,
       InputsArray* arguments,
@@ -4086,7 +4166,7 @@
       const Function& interface_target = Function::null_function(),
       const Function& tearoff_interface_target = Function::null_function())
       : InstanceCallBaseInstr(
-            token_pos,
+            source,
             function_name,
             token_kind,
             arguments,
@@ -4099,7 +4179,7 @@
         checked_argument_count_(checked_argument_count) {}
 
   InstanceCallInstr(
-      TokenPosition token_pos,
+      const InstructionSource& source,
       const String& function_name,
       Token::Kind token_kind,
       InputsArray* arguments,
@@ -4109,7 +4189,7 @@
       intptr_t deopt_id,
       const Function& interface_target = Function::null_function(),
       const Function& tearoff_interface_target = Function::null_function())
-      : InstanceCallBaseInstr(token_pos,
+      : InstanceCallBaseInstr(source,
                               function_name,
                               token_kind,
                               arguments,
@@ -4171,13 +4251,10 @@
       args->Add(call->ArgumentValueAt(i)->CopyWithType(zone));
     }
     auto new_call = new (zone) PolymorphicInstanceCallInstr(
-        call->token_pos(), call->function_name(), call->token_kind(), args,
+        call->source(), call->function_name(), call->token_kind(), args,
         call->type_args_len(), call->argument_names(), call->ic_data(),
         call->deopt_id(), call->interface_target(),
         call->tearoff_interface_target(), targets, complete);
-    if (call->has_inlining_id()) {
-      new_call->set_inlining_id(call->inlining_id());
-    }
     new_call->set_result_type(call->result_type());
     new_call->set_entry_kind(call->entry_kind());
     new_call->set_has_unique_selector(call->has_unique_selector());
@@ -4218,7 +4295,7 @@
   ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
-  PolymorphicInstanceCallInstr(TokenPosition token_pos,
+  PolymorphicInstanceCallInstr(const InstructionSource& source,
                                const String& function_name,
                                Token::Kind token_kind,
                                InputsArray* arguments,
@@ -4230,7 +4307,7 @@
                                const Function& tearoff_interface_target,
                                const CallTargets& targets,
                                bool complete)
-      : InstanceCallBaseInstr(token_pos,
+      : InstanceCallBaseInstr(source,
                               function_name,
                               token_kind,
                               arguments,
@@ -4260,7 +4337,7 @@
 // Takes untagged ClassId of the receiver as extra input.
 class DispatchTableCallInstr : public TemplateDartCall<1> {
  public:
-  DispatchTableCallInstr(TokenPosition token_pos,
+  DispatchTableCallInstr(const InstructionSource& source,
                          const Function& interface_target,
                          const compiler::TableSelector* selector,
                          InputsArray* arguments,
@@ -4270,7 +4347,7 @@
                          type_args_len,
                          argument_names,
                          arguments,
-                         token_pos),
+                         source),
         interface_target_(interface_target),
         selector_(selector) {
     ASSERT(selector != nullptr);
@@ -4332,7 +4409,7 @@
 
 class StrictCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
  public:
-  StrictCompareInstr(TokenPosition token_pos,
+  StrictCompareInstr(const InstructionSource& source,
                      Token::Kind kind,
                      Value* left,
                      Value* right,
@@ -4379,11 +4456,11 @@
 // comparison pattern.
 class TestSmiInstr : public TemplateComparison<2, NoThrow, Pure> {
  public:
-  TestSmiInstr(TokenPosition token_pos,
+  TestSmiInstr(const InstructionSource& source,
                Token::Kind kind,
                Value* left,
                Value* right)
-      : TemplateComparison(token_pos, kind) {
+      : TemplateComparison(source, kind) {
     ASSERT(kind == Token::kEQ || kind == Token::kNE);
     SetInputAt(0, left);
     SetInputAt(1, right);
@@ -4414,7 +4491,7 @@
 // other results even in the no-deopt case.
 class TestCidsInstr : public TemplateComparison<1, NoThrow, Pure> {
  public:
-  TestCidsInstr(TokenPosition token_pos,
+  TestCidsInstr(const InstructionSource& source,
                 Token::Kind kind,
                 Value* value,
                 const ZoneGrowableArray<intptr_t>& cid_results,
@@ -4454,14 +4531,14 @@
 
 class EqualityCompareInstr : public TemplateComparison<2, NoThrow, Pure> {
  public:
-  EqualityCompareInstr(TokenPosition token_pos,
+  EqualityCompareInstr(const InstructionSource& source,
                        Token::Kind kind,
                        Value* left,
                        Value* right,
                        intptr_t cid,
                        intptr_t deopt_id,
                        SpeculativeMode speculative_mode = kGuardInputs)
-      : TemplateComparison(token_pos, kind, deopt_id),
+      : TemplateComparison(source, kind, deopt_id),
         speculative_mode_(speculative_mode) {
     ASSERT(Token::IsEqualityOperator(kind));
     SetInputAt(0, left);
@@ -4502,14 +4579,14 @@
 
 class RelationalOpInstr : public TemplateComparison<2, NoThrow, Pure> {
  public:
-  RelationalOpInstr(TokenPosition token_pos,
+  RelationalOpInstr(const InstructionSource& source,
                     Token::Kind kind,
                     Value* left,
                     Value* right,
                     intptr_t cid,
                     intptr_t deopt_id,
                     SpeculativeMode speculative_mode = kGuardInputs)
-      : TemplateComparison(token_pos, kind, deopt_id),
+      : TemplateComparison(source, kind, deopt_id),
         speculative_mode_(speculative_mode) {
     ASSERT(Token::IsRelationalOperator(kind));
     SetInputAt(0, left);
@@ -4633,7 +4710,7 @@
 
 class StaticCallInstr : public TemplateDartCall<0> {
  public:
-  StaticCallInstr(TokenPosition token_pos,
+  StaticCallInstr(const InstructionSource& source,
                   const Function& function,
                   intptr_t type_args_len,
                   const Array& argument_names,
@@ -4645,20 +4722,19 @@
                          type_args_len,
                          argument_names,
                          arguments,
-                         token_pos),
-        ic_data_(NULL),
+                         source),
+        ic_data_(GetICData(ic_data_array, deopt_id, /*is_static_call=*/true)),
         call_count_(0),
         function_(function),
         rebind_rule_(rebind_rule),
         result_type_(NULL),
         is_known_list_constructor_(false),
         identity_(AliasIdentity::Unknown()) {
-    ic_data_ = GetICData(ic_data_array, deopt_id, /*is_static_call=*/true);
     ASSERT(function.IsZoneHandle());
     ASSERT(!function.IsNull());
   }
 
-  StaticCallInstr(TokenPosition token_pos,
+  StaticCallInstr(const InstructionSource& source,
                   const Function& function,
                   intptr_t type_args_len,
                   const Array& argument_names,
@@ -4670,7 +4746,7 @@
                          type_args_len,
                          argument_names,
                          arguments,
-                         token_pos),
+                         source),
         ic_data_(NULL),
         call_count_(call_count),
         function_(function),
@@ -4694,16 +4770,12 @@
     for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
       args->Add(call->ArgumentValueAt(i)->CopyWithType());
     }
-    StaticCallInstr* new_call = new (zone)
-        StaticCallInstr(call->token_pos(), target, call->type_args_len(),
-                        call->argument_names(), args, call->deopt_id(),
-                        call_count, ICData::kNoRebind);
+    StaticCallInstr* new_call = new (zone) StaticCallInstr(
+        call->source(), target, call->type_args_len(), call->argument_names(),
+        args, call->deopt_id(), call_count, ICData::kNoRebind);
     if (call->result_type() != NULL) {
       new_call->result_type_ = call->result_type();
     }
-    if (call->has_inlining_id()) {
-      new_call->set_inlining_id(call->inlining_id());
-    }
     new_call->set_entry_kind(call->entry_kind());
     return new_call;
   }
@@ -4817,8 +4889,11 @@
 
 class LoadLocalInstr : public TemplateDefinition<0, NoThrow> {
  public:
-  LoadLocalInstr(const LocalVariable& local, TokenPosition token_pos)
-      : local_(local), is_last_(false), token_pos_(token_pos) {}
+  LoadLocalInstr(const LocalVariable& local, const InstructionSource& source)
+      : TemplateDefinition(source),
+        local_(local),
+        is_last_(false),
+        token_pos_(source.token_pos) {}
 
   DECLARE_INSTRUCTION(LoadLocal)
   virtual CompileType ComputeType() const;
@@ -4939,8 +5014,12 @@
  public:
   StoreLocalInstr(const LocalVariable& local,
                   Value* value,
-                  TokenPosition token_pos)
-      : local_(local), is_dead_(false), is_last_(false), token_pos_(token_pos) {
+                  const InstructionSource& source)
+      : TemplateDefinition(source),
+        local_(local),
+        is_dead_(false),
+        is_last_(false),
+        token_pos_(source.token_pos) {
     SetInputAt(0, value);
   }
 
@@ -4982,20 +5061,16 @@
   NativeCallInstr(const String* name,
                   const Function* function,
                   bool link_lazily,
-                  TokenPosition position,
+                  const InstructionSource& source,
                   InputsArray* args)
-      : TemplateDartCall(DeoptId::kNone,
-                         0,
-                         Array::null_array(),
-                         args,
-                         position),
+      : TemplateDartCall(DeoptId::kNone, 0, Array::null_array(), args, source),
         native_name_(name),
         function_(function),
         native_c_function_(NULL),
         is_bootstrap_native_(false),
         is_auto_scope_(true),
         link_lazily_(link_lazily),
-        token_pos_(position) {
+        token_pos_(source.token_pos) {
     ASSERT(name->IsZoneHandle());
     ASSERT(function->IsZoneHandle());
   }
@@ -5046,7 +5121,11 @@
 // are unboxed and passed through the native calling convention. However, not
 // all dart objects can be passed as arguments. Please see the FFI documentation
 // for more details.
-// TODO(35775): Add link to the documentation when it's written.
+//
+// Arguments to FfiCallInstr:
+// - The arguments to the native call, marshalled in IL as far as possible.
+// - The argument address.
+// - A TypedData for the return value to populate in machine code (optional).
 class FfiCallInstr : public Definition {
  public:
   FfiCallInstr(Zone* zone,
@@ -5055,17 +5134,23 @@
       : Definition(deopt_id),
         zone_(zone),
         marshaller_(marshaller),
-        inputs_(marshaller.num_args() + 1) {
-    inputs_.FillWith(nullptr, 0, marshaller.num_args() + 1);
+        inputs_(marshaller.NumDefinitions() + 1 +
+                (marshaller.PassTypedData() ? 1 : 0)) {
+    inputs_.FillWith(
+        nullptr, 0,
+        marshaller.NumDefinitions() + 1 + (marshaller.PassTypedData() ? 1 : 0));
   }
 
   DECLARE_INSTRUCTION(FfiCall)
 
-  // Number of arguments to the native function.
-  intptr_t NativeArgCount() const { return InputCount() - 1; }
-
   // Input index of the function pointer to invoke.
-  intptr_t TargetAddressIndex() const { return NativeArgCount(); }
+  intptr_t TargetAddressIndex() const { return marshaller_.NumDefinitions(); }
+
+  // Input index of the typed data to populate if return value is struct.
+  intptr_t TypedDataIndex() const {
+    ASSERT(marshaller_.PassTypedData());
+    return marshaller_.NumDefinitions() + 1;
+  }
 
   virtual intptr_t InputCount() const { return inputs_.length(); }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
@@ -5190,11 +5275,11 @@
 
 class DebugStepCheckInstr : public TemplateInstruction<0, NoThrow> {
  public:
-  DebugStepCheckInstr(TokenPosition token_pos,
-                      PcDescriptorsLayout::Kind stub_kind,
+  DebugStepCheckInstr(const InstructionSource& source,
+                      UntaggedPcDescriptors::Kind stub_kind,
                       intptr_t deopt_id)
-      : TemplateInstruction<0, NoThrow>(deopt_id),
-        token_pos_(token_pos),
+      : TemplateInstruction(source, deopt_id),
+        token_pos_(source.token_pos),
         stub_kind_(stub_kind) {}
 
   DECLARE_INSTRUCTION(DebugStepCheck)
@@ -5208,7 +5293,7 @@
 
  private:
   const TokenPosition token_pos_;
-  const PcDescriptorsLayout::Kind stub_kind_;
+  const UntaggedPcDescriptors::Kind stub_kind_;
 
   DISALLOW_COPY_AND_ASSIGN(DebugStepCheckInstr);
 };
@@ -5250,11 +5335,12 @@
                           Value* instance,
                           Value* value,
                           StoreBarrierType emit_store_barrier,
-                          TokenPosition token_pos,
+                          const InstructionSource& source,
                           Kind kind = Kind::kOther)
-      : slot_(slot),
+      : TemplateInstruction(source),
+        slot_(slot),
         emit_store_barrier_(emit_store_barrier),
-        token_pos_(token_pos),
+        token_pos_(source.token_pos),
         is_initialization_(kind == Kind::kInitializing) {
     SetInputAt(kInstancePos, instance);
     SetInputAt(kValuePos, value);
@@ -5265,14 +5351,14 @@
                           Value* instance,
                           Value* value,
                           StoreBarrierType emit_store_barrier,
-                          TokenPosition token_pos,
+                          const InstructionSource& source,
                           const ParsedFunction* parsed_function,
                           Kind kind = Kind::kOther)
       : StoreInstanceFieldInstr(Slot::Get(field, parsed_function),
                                 instance,
                                 value,
                                 emit_store_barrier,
-                                token_pos,
+                                source,
                                 kind) {}
 
   virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
@@ -5420,7 +5506,7 @@
 
 // For a field of static type G<T0, ..., Tn> and a stored value of runtime
 // type T checks that type arguments of T at G exactly match <T0, ..., Tn>
-// and updates guarded state (FieldLayout::static_type_exactness_state_)
+// and updates guarded state (UntaggedField::static_type_exactness_state_)
 // accordingly.
 //
 // See StaticTypeExactnessState for more information.
@@ -5444,12 +5530,12 @@
 class LoadStaticFieldInstr : public TemplateDefinition<0, Throws> {
  public:
   LoadStaticFieldInstr(const Field& field,
-                       TokenPosition token_pos,
+                       const InstructionSource& source,
                        bool calls_initializer = false,
                        intptr_t deopt_id = DeoptId::kNone)
-      : TemplateDefinition(deopt_id),
+      : TemplateDefinition(source, deopt_id),
         field_(field),
-        token_pos_(token_pos),
+        token_pos_(source.token_pos),
         calls_initializer_(calls_initializer) {
     ASSERT(!calls_initializer || (deopt_id != DeoptId::kNone));
   }
@@ -5493,8 +5579,10 @@
  public:
   StoreStaticFieldInstr(const Field& field,
                         Value* value,
-                        TokenPosition token_pos)
-      : field_(field), token_pos_(token_pos) {
+                        const InstructionSource& source)
+      : TemplateDefinition(source),
+        field_(field),
+        token_pos_(source.token_pos) {
     ASSERT(field.IsZoneHandle());
     SetInputAt(kValuePos, value);
     CheckField(field);
@@ -5545,7 +5633,7 @@
                    intptr_t class_id,
                    AlignmentType alignment,
                    intptr_t deopt_id,
-                   TokenPosition token_pos,
+                   const InstructionSource& source,
                    CompileType* result_type = nullptr);
 
   TokenPosition token_pos() const { return token_pos_; }
@@ -5617,9 +5705,10 @@
                      Value* index,
                      intptr_t element_count,
                      intptr_t class_id,
-                     TokenPosition token_pos)
-      : class_id_(class_id),
-        token_pos_(token_pos),
+                     const InstructionSource& source)
+      : TemplateDefinition(source),
+        class_id_(class_id),
+        token_pos_(source.token_pos),
         element_count_(element_count),
         representation_(kTagged) {
     ASSERT(element_count == 1 || element_count == 2 || element_count == 4);
@@ -5724,10 +5813,10 @@
 class StringInterpolateInstr : public TemplateDefinition<1, Throws> {
  public:
   StringInterpolateInstr(Value* value,
-                         TokenPosition token_pos,
+                         const InstructionSource& source,
                          intptr_t deopt_id)
-      : TemplateDefinition(deopt_id),
-        token_pos_(token_pos),
+      : TemplateDefinition(source, deopt_id),
+        token_pos_(source.token_pos),
         function_(Function::ZoneHandle()) {
     SetInputAt(0, value);
   }
@@ -5837,7 +5926,7 @@
                     intptr_t class_id,
                     AlignmentType alignment,
                     intptr_t deopt_id,
-                    TokenPosition token_pos,
+                    const InstructionSource& source,
                     SpeculativeMode speculative_mode = kGuardInputs);
   DECLARE_INSTRUCTION(StoreIndexed)
 
@@ -5933,13 +6022,15 @@
 
 class InstanceOfInstr : public TemplateDefinition<3, Throws> {
  public:
-  InstanceOfInstr(TokenPosition token_pos,
+  InstanceOfInstr(const InstructionSource& source,
                   Value* value,
                   Value* instantiator_type_arguments,
                   Value* function_type_arguments,
                   const AbstractType& type,
                   intptr_t deopt_id)
-      : TemplateDefinition(deopt_id), token_pos_(token_pos), type_(type) {
+      : TemplateDefinition(source, deopt_id),
+        token_pos_(source.token_pos),
+        type_(type) {
     ASSERT(!type.IsNull());
     SetInputAt(0, value);
     SetInputAt(1, instantiator_type_arguments);
@@ -5978,10 +6069,10 @@
 // either reside in new space or be in the store buffer.
 class AllocationInstr : public Definition {
  public:
-  explicit AllocationInstr(TokenPosition token_pos,
+  explicit AllocationInstr(const InstructionSource& source,
                            intptr_t deopt_id = DeoptId::kNone)
-      : Definition(deopt_id),
-        token_pos_(token_pos),
+      : Definition(source, deopt_id),
+        token_pos_(source.token_pos),
         identity_(AliasIdentity::Unknown()) {}
 
   virtual TokenPosition token_pos() const { return token_pos_; }
@@ -6005,9 +6096,9 @@
 template <intptr_t N, typename ThrowsTrait>
 class TemplateAllocation : public AllocationInstr {
  public:
-  explicit TemplateAllocation(TokenPosition token_pos,
+  explicit TemplateAllocation(const InstructionSource& source,
                               intptr_t deopt_id = DeoptId::kNone)
-      : AllocationInstr(token_pos, deopt_id), inputs_() {}
+      : AllocationInstr(source, deopt_id), inputs_() {}
 
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
@@ -6026,10 +6117,10 @@
 
 class AllocateObjectInstr : public AllocationInstr {
  public:
-  AllocateObjectInstr(TokenPosition token_pos,
+  AllocateObjectInstr(const InstructionSource& source,
                       const Class& cls,
                       Value* type_arguments = nullptr)
-      : AllocationInstr(token_pos),
+      : AllocationInstr(source),
         cls_(cls),
         type_arguments_(type_arguments),
         closure_function_(Function::ZoneHandle()) {
@@ -6047,7 +6138,7 @@
 
   const Function& closure_function() const { return closure_function_; }
   void set_closure_function(const Function& function) {
-    closure_function_ = function.raw();
+    closure_function_ = function.ptr();
   }
 
   virtual intptr_t InputCount() const {
@@ -6093,7 +6184,7 @@
 class AllocateUninitializedContextInstr
     : public TemplateAllocation<0, NoThrow> {
  public:
-  AllocateUninitializedContextInstr(TokenPosition token_pos,
+  AllocateUninitializedContextInstr(const InstructionSource& source,
                                     intptr_t num_context_variables);
 
   DECLARE_INSTRUCTION(AllocateUninitializedContext)
@@ -6205,8 +6296,9 @@
 
 class ArrayAllocationInstr : public AllocationInstr {
  public:
-  explicit ArrayAllocationInstr(TokenPosition token_pos, intptr_t deopt_id)
-      : AllocationInstr(token_pos, deopt_id) {}
+  explicit ArrayAllocationInstr(const InstructionSource& source,
+                                intptr_t deopt_id)
+      : AllocationInstr(source, deopt_id) {}
 
   virtual Value* num_elements() const = 0;
 
@@ -6226,8 +6318,9 @@
 template <intptr_t N, typename ThrowsTrait>
 class TemplateArrayAllocation : public ArrayAllocationInstr {
  public:
-  explicit TemplateArrayAllocation(TokenPosition token_pos, intptr_t deopt_id)
-      : ArrayAllocationInstr(token_pos, deopt_id), inputs_() {}
+  explicit TemplateArrayAllocation(const InstructionSource& source,
+                                   intptr_t deopt_id)
+      : ArrayAllocationInstr(source, deopt_id), inputs_() {}
 
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
@@ -6243,11 +6336,11 @@
 
 class CreateArrayInstr : public TemplateArrayAllocation<2, Throws> {
  public:
-  CreateArrayInstr(TokenPosition token_pos,
+  CreateArrayInstr(const InstructionSource& source,
                    Value* element_type,
                    Value* num_elements,
                    intptr_t deopt_id)
-      : TemplateArrayAllocation(token_pos, deopt_id) {
+      : TemplateArrayAllocation(source, deopt_id) {
     SetInputAt(kElementTypePos, element_type);
     SetInputAt(kLengthPos, num_elements);
   }
@@ -6281,11 +6374,11 @@
 
 class AllocateTypedDataInstr : public TemplateArrayAllocation<1, Throws> {
  public:
-  AllocateTypedDataInstr(TokenPosition token_pos,
+  AllocateTypedDataInstr(const InstructionSource& source,
                          classid_t class_id,
                          Value* num_elements,
                          intptr_t deopt_id)
-      : TemplateArrayAllocation(token_pos, deopt_id), class_id_(class_id) {
+      : TemplateArrayAllocation(source, deopt_id), class_id_(class_id) {
     SetInputAt(kLengthPos, num_elements);
   }
 
@@ -6450,12 +6543,12 @@
  public:
   LoadFieldInstr(Value* instance,
                  const Slot& slot,
-                 TokenPosition token_pos,
+                 const InstructionSource& source,
                  bool calls_initializer = false,
                  intptr_t deopt_id = DeoptId::kNone)
-      : TemplateDefinition(deopt_id),
+      : TemplateDefinition(source, deopt_id),
         slot_(slot),
-        token_pos_(token_pos),
+        token_pos_(source.token_pos),
         calls_initializer_(calls_initializer),
         throw_exception_on_initialization_(false) {
     ASSERT(!calls_initializer || (deopt_id != DeoptId::kNone));
@@ -6558,12 +6651,14 @@
 
 class InstantiateTypeInstr : public TemplateDefinition<2, Throws> {
  public:
-  InstantiateTypeInstr(TokenPosition token_pos,
+  InstantiateTypeInstr(const InstructionSource& source,
                        const AbstractType& type,
                        Value* instantiator_type_arguments,
                        Value* function_type_arguments,
                        intptr_t deopt_id)
-      : TemplateDefinition(deopt_id), token_pos_(token_pos), type_(type) {
+      : TemplateDefinition(source, deopt_id),
+        token_pos_(source.token_pos),
+        type_(type) {
     ASSERT(type.IsZoneHandle() || type.IsReadOnlyHandle());
     SetInputAt(0, instantiator_type_arguments);
     SetInputAt(1, function_type_arguments);
@@ -6593,15 +6688,15 @@
 
 class InstantiateTypeArgumentsInstr : public TemplateDefinition<3, Throws> {
  public:
-  InstantiateTypeArgumentsInstr(TokenPosition token_pos,
+  InstantiateTypeArgumentsInstr(const InstructionSource& source,
                                 Value* instantiator_type_arguments,
                                 Value* function_type_arguments,
                                 Value* type_arguments,
                                 const Class& instantiator_class,
                                 const Function& function,
                                 intptr_t deopt_id)
-      : TemplateDefinition(deopt_id),
-        token_pos_(token_pos),
+      : TemplateDefinition(source, deopt_id),
+        token_pos_(source.token_pos),
         instantiator_class_(instantiator_class),
         function_(function) {
     ASSERT(instantiator_class.IsReadOnlyHandle() ||
@@ -6678,9 +6773,9 @@
 // for the given [context_variables].
 class AllocateContextInstr : public TemplateAllocation<0, NoThrow> {
  public:
-  AllocateContextInstr(TokenPosition token_pos,
+  AllocateContextInstr(const InstructionSource& source,
                        const ZoneGrowableArray<const Slot*>& context_slots)
-      : TemplateAllocation(token_pos), context_slots_(context_slots) {}
+      : TemplateAllocation(source), context_slots_(context_slots) {}
 
   DECLARE_INSTRUCTION(AllocateContext)
   virtual CompileType ComputeType() const;
@@ -6712,12 +6807,12 @@
 // it contains exactly the provided [context_variables].
 class CloneContextInstr : public TemplateDefinition<1, NoThrow> {
  public:
-  CloneContextInstr(TokenPosition token_pos,
+  CloneContextInstr(const InstructionSource& source,
                     Value* context_value,
                     const ZoneGrowableArray<const Slot*>& context_slots,
                     intptr_t deopt_id)
-      : TemplateDefinition(deopt_id),
-        token_pos_(token_pos),
+      : TemplateDefinition(source, deopt_id),
+        token_pos_(source.token_pos),
         context_slots_(context_slots) {
     SetInputAt(0, context_value);
   }
@@ -7287,11 +7382,11 @@
                       Value* left,
                       Value* right,
                       intptr_t deopt_id,
-                      TokenPosition token_pos,
+                      const InstructionSource& source,
                       SpeculativeMode speculative_mode = kGuardInputs)
-      : TemplateDefinition(deopt_id),
+      : TemplateDefinition(source, deopt_id),
         op_kind_(op_kind),
-        token_pos_(token_pos),
+        token_pos_(source.token_pos),
         speculative_mode_(speculative_mode) {
     SetInputAt(0, left);
     SetInputAt(1, right);
@@ -7349,8 +7444,8 @@
   DoubleTestOpInstr(MethodRecognizer::Kind op_kind,
                     Value* value,
                     intptr_t deopt_id,
-                    TokenPosition token_pos)
-      : TemplateComparison(token_pos, Token::kEQ, deopt_id), op_kind_(op_kind) {
+                    const InstructionSource& source)
+      : TemplateComparison(source, Token::kEQ, deopt_id), op_kind_(op_kind) {
     SetInputAt(0, value);
   }
 
@@ -7555,7 +7650,7 @@
                             Value* left,
                             Value* right,
                             TemplateDartCall<0>* call)
-      : TemplateComparison(call->token_pos(), op_kind, call->deopt_id()),
+      : TemplateComparison(call->source(), op_kind, call->deopt_id()),
         call_(call),
         is_negated_(false) {
     ASSERT(call->type_args_len() == 0);
@@ -8082,13 +8177,13 @@
     kOsrOnly,
   };
 
-  CheckStackOverflowInstr(TokenPosition token_pos,
+  CheckStackOverflowInstr(const InstructionSource& source,
                           intptr_t stack_depth,
                           intptr_t loop_depth,
                           intptr_t deopt_id,
                           Kind kind)
-      : TemplateInstruction(deopt_id),
-        token_pos_(token_pos),
+      : TemplateInstruction(source, deopt_id),
+        token_pos_(source.token_pos),
         stack_depth_(stack_depth),
         loop_depth_(loop_depth),
         kind_(kind) {
@@ -8129,8 +8224,8 @@
 // TODO(vegorov): remove this instruction in favor of Int32ToDouble.
 class SmiToDoubleInstr : public TemplateDefinition<1, NoThrow, Pure> {
  public:
-  SmiToDoubleInstr(Value* value, TokenPosition token_pos)
-      : token_pos_(token_pos) {
+  SmiToDoubleInstr(Value* value, const InstructionSource& source)
+      : TemplateDefinition(source), token_pos_(source.token_pos) {
     SetInputAt(0, value);
   }
 
@@ -8397,7 +8492,7 @@
   InvokeMathCFunctionInstr(ZoneGrowableArray<Value*>* inputs,
                            intptr_t deopt_id,
                            MethodRecognizer::Kind recognized_kind,
-                           TokenPosition token_pos);
+                           const InstructionSource& source);
 
   static intptr_t ArgumentCountFor(MethodRecognizer::Kind recognized_kind_);
 
@@ -8544,7 +8639,7 @@
   CheckClassInstr(Value* value,
                   intptr_t deopt_id,
                   const Cids& cids,
-                  TokenPosition token_pos);
+                  const InstructionSource& source);
 
   DECLARE_INSTRUCTION(CheckClass)
 
@@ -8603,9 +8698,11 @@
 
 class CheckSmiInstr : public TemplateInstruction<1, NoThrow, Pure> {
  public:
-  CheckSmiInstr(Value* value, intptr_t deopt_id, TokenPosition token_pos)
-      : TemplateInstruction(deopt_id),
-        token_pos_(token_pos),
+  CheckSmiInstr(Value* value,
+                intptr_t deopt_id,
+                const InstructionSource& source)
+      : TemplateInstruction(source, deopt_id),
+        token_pos_(source.token_pos),
         licm_hoisted_(false) {
     SetInputAt(0, value);
   }
@@ -8645,10 +8742,10 @@
   CheckNullInstr(Value* value,
                  const String& function_name,
                  intptr_t deopt_id,
-                 TokenPosition token_pos,
+                 const InstructionSource& source,
                  ExceptionType exception_type = kNoSuchMethod)
-      : TemplateDefinition(deopt_id),
-        token_pos_(token_pos),
+      : TemplateDefinition(source, deopt_id),
+        token_pos_(source.token_pos),
         function_name_(function_name),
         exception_type_(exception_type) {
     ASSERT(function_name.IsNotTemporaryScopedHandle());
@@ -9516,7 +9613,7 @@
   if (auto static_call = this->AsStaticCall()) {
     return static_call->function().name();
   } else if (auto instance_call = this->AsInstanceCall()) {
-    return instance_call->function_name().raw();
+    return instance_call->function_name().ptr();
   } else {
     UNREACHABLE();
   }
@@ -9524,7 +9621,39 @@
 
 inline bool Value::CanBe(const Object& value) {
   ConstantInstr* constant = definition()->AsConstant();
-  return (constant == nullptr) || constant->value().raw() == value.raw();
+  return (constant == nullptr) || constant->value().ptr() == value.ptr();
+}
+
+class SuccessorsIterable {
+ public:
+  struct Iterator {
+    const Instruction* instr;
+    intptr_t index;
+
+    BlockEntryInstr* operator*() const { return instr->SuccessorAt(index); }
+    Iterator& operator++() {
+      index++;
+      return *this;
+    }
+
+    bool operator==(const Iterator& other) {
+      return instr == other.instr && index == other.index;
+    }
+
+    bool operator!=(const Iterator& other) { return !(*this == other); }
+  };
+
+  explicit SuccessorsIterable(const Instruction* instr) : instr_(instr) {}
+
+  Iterator begin() const { return {instr_, 0}; }
+  Iterator end() const { return {instr_, instr_->SuccessorCount()}; }
+
+ private:
+  const Instruction* instr_;
+};
+
+SuccessorsIterable Instruction::successors() const {
+  return SuccessorsIterable(this);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 04b1857..694c7f9 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -379,9 +379,11 @@
     // At this point there are no pending buffered registers.
     // Use LR as it's the highest free register, it is not allocatable and
     // it is clobbered by the call.
-    static_assert(((1 << LR) & kDartAvailableCpuRegs) == 0,
-                  "LR should not be allocatable");
-    return LR;
+    CLOBBERS_LR({
+      static_assert(((1 << LR) & kDartAvailableCpuRegs) == 0,
+                    "LR should not be allocatable");
+      return LR;
+    });
   }
 
  private:
@@ -482,8 +484,7 @@
     ASSERT(result == CallingConventions::kReturnFpuReg);
   }
 
-  if (compiler->intrinsic_mode()) {
-    // Intrinsics don't have a frame.
+  if (!compiler->flow_graph().graph_entry()->NeedsFrame()) {
     __ Ret();
     return;
   }
@@ -503,8 +504,8 @@
   __ Bind(&stack_ok);
 #endif
   ASSERT(__ constant_pool_allowed());
-  if (yield_index() != PcDescriptorsLayout::kInvalidYieldIndex) {
-    compiler->EmitYieldPositionMetadata(token_pos(), yield_index());
+  if (yield_index() != UntaggedPcDescriptors::kInvalidYieldIndex) {
+    compiler->EmitYieldPositionMetadata(source(), yield_index());
   }
   __ LeaveDartFrameAndReturn();  // Disallows constant pool use.
   // This ReturnInstr may be emitted out of order by the optimizer. The next
@@ -623,8 +624,8 @@
     __ LoadImmediate(R9, 0);
   }
   __ blx(R2);
-  compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
-                                 PcDescriptorsLayout::kOther, locs());
+  compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                 UntaggedPcDescriptors::kOther, locs());
   __ Drop(argument_count);
 }
 
@@ -1268,10 +1269,10 @@
                          ? compiler::ObjectPoolBuilderEntry::kPatchable
                          : compiler::ObjectPoolBuilderEntry::kNotPatchable);
   if (link_lazily()) {
-    compiler->GeneratePatchableCall(token_pos(), *stub,
-                                    PcDescriptorsLayout::kOther, locs());
+    compiler->GeneratePatchableCall(source(), *stub,
+                                    UntaggedPcDescriptors::kOther, locs());
   } else {
-    compiler->GenerateStubCall(token_pos(), *stub, PcDescriptorsLayout::kOther,
+    compiler->GenerateStubCall(source(), *stub, UntaggedPcDescriptors::kOther,
                                locs());
   }
   __ Pop(result);
@@ -1297,7 +1298,7 @@
   __ EnterDartFrame(0, /*load_pool_pointer=*/false);
 
   // Reserve space for arguments and align frame before entering C++ world.
-  __ ReserveAlignedFrameSpace(marshaller_.StackTopInBytes());
+  __ ReserveAlignedFrameSpace(marshaller_.RequiredStackSpaceInBytes());
 
   EmitParamMoves(compiler);
 
@@ -1313,8 +1314,8 @@
   // For historical reasons, the PC on ARM points 8 bytes past the current
   // instruction. Therefore we emit the metadata here, 8 bytes (2 instructions)
   // after the original mov.
-  compiler->EmitCallsiteMetadata(TokenPosition::kNoSource, deopt_id(),
-                                 PcDescriptorsLayout::Kind::kOther, locs());
+  compiler->EmitCallsiteMetadata(InstructionSource(), deopt_id(),
+                                 UntaggedPcDescriptors::Kind::kOther, locs());
 
   // Update information in the thread object and enter a safepoint.
   if (CanExecuteGeneratedCodeInSafepoint()) {
@@ -1359,6 +1360,7 @@
   __ PopRegister(TMP);
 }
 
+// Keep in sync with NativeEntryInstr::EmitNativeCode.
 void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   EmitReturnMoves(compiler);
 
@@ -1390,17 +1392,15 @@
 
   __ PopNativeCalleeSavedRegisters();
 
-#if defined(TARGET_OS_FUCHSIA)
-  UNREACHABLE();  // Fuchsia does not allow dart:ffi.
-#elif defined(USING_SHADOW_CALL_STACK)
+#if defined(TARGET_OS_FUCHSIA) && defined(USING_SHADOW_CALL_STACK)
 #error Unimplemented
 #endif
 
   // Leave the entry frame.
-  __ LeaveFrame(1 << LR | 1 << FP);
+  RESTORES_LR_FROM_FRAME(__ LeaveFrame(1 << LR | 1 << FP));
 
   // Leave the dummy frame holding the pushed arguments.
-  __ LeaveFrame(1 << LR | 1 << FP);
+  RESTORES_LR_FROM_FRAME(__ LeaveFrame(1 << LR | 1 << FP));
 
   __ Ret();
 
@@ -1408,6 +1408,7 @@
   __ set_constant_pool_allowed(true);
 }
 
+// Keep in sync with NativeReturnInstr::EmitNativeCode and ComputeInnerLRState.
 void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Constant pool cannot be used until we enter the actual Dart frame.
   __ set_constant_pool_allowed(false);
@@ -1416,20 +1417,18 @@
 
   // Create a dummy frame holding the pushed arguments. This simplifies
   // NativeReturnInstr::EmitNativeCode.
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  SPILLS_LR_TO_FRAME(__ EnterFrame((1 << FP) | (1 << LR), 0));
 
   // Save the argument registers, in reverse order.
   SaveArguments(compiler);
 
   // Enter the entry frame.
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  SPILLS_LR_TO_FRAME(__ EnterFrame((1 << FP) | (1 << LR), 0));
 
   // Save a space for the code object.
   __ PushImmediate(0);
 
-#if defined(TARGET_OS_FUCHSIA)
-  UNREACHABLE();  // Fuchsia does not allow dart:ffi.
-#elif defined(USING_SHADOW_CALL_STACK)
+#if defined(TARGET_OS_FUCHSIA) && defined(USING_SHADOW_CALL_STACK)
 #error Unimplemented
 #endif
 
@@ -1519,9 +1518,12 @@
 
   // Load a dummy return address which suggests that we are inside of
   // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
-  __ LoadFromOffset(LR, THR,
-                    compiler::target::Thread::invoke_dart_code_stub_offset());
-  __ LoadFieldFromOffset(LR, LR, compiler::target::Code::entry_point_offset());
+  CLOBBERS_LR({
+    __ LoadFromOffset(LR, THR,
+                      compiler::target::Thread::invoke_dart_code_stub_offset());
+    __ LoadFieldFromOffset(LR, LR,
+                           compiler::target::Code::entry_point_offset());
+  });
 
   FunctionEntryInstr::EmitNativeCode(compiler);
 }
@@ -1593,9 +1595,8 @@
   const Array& kNoArgumentNames = Object::null_array();
   ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
                           kNoArgumentNames);
-  compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
-                               args_info, locs(), ICData::Handle(),
-                               ICData::kStatic);
+  compiler->GenerateStaticCall(deopt_id(), source(), CallFunction(), args_info,
+                               locs(), ICData::Handle(), ICData::kStatic);
   ASSERT(locs()->out(0).reg() == R0);
 }
 
@@ -2193,8 +2194,7 @@
     case kArrayCid:
       if (ShouldEmitStoreBarrier()) {
         const Register value = locs()->in(2).reg();
-        __ StoreIntoArray(array, temp, value, CanValueBeSmi(),
-                          /*lr_reserved=*/!compiler->intrinsic_mode());
+        __ StoreIntoArray(array, temp, value, CanValueBeSmi());
       } else if (locs()->in(2).IsConstant()) {
         const Object& constant = locs()->in(2).constant();
         __ StoreIntoObjectNoBarrier(array, compiler::Address(temp), constant);
@@ -2359,9 +2359,9 @@
 }
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
@@ -2619,8 +2619,8 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateStubCall(TokenPosition::kNoSource,  // No token position.
-                               stub, PcDescriptorsLayout::kOther, locs);
+    compiler->GenerateStubCall(InstructionSource(),  // No token position.
+                               stub, UntaggedPcDescriptors::kOther, locs);
     __ MoveRegister(result_, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -2836,9 +2836,9 @@
 }
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   compiler::Label skip_store;
 
@@ -3016,13 +3016,8 @@
 
   if (ShouldEmitStoreBarrier()) {
     const Register value_reg = locs()->in(1).reg();
-    // In intrinsic mode, there is no stack frame and the function will return
-    // by executing 'ret LR' directly. Therefore we cannot overwrite LR. (see
-    // ReturnInstr::EmitNativeCode).
-    ASSERT(!locs()->live_registers()->Contains(Location::RegisterLocation(LR)));
     __ StoreIntoObjectOffset(instance_reg, offset_in_bytes, value_reg,
-                             CanValueBeSmi(),
-                             /*lr_reserved=*/!compiler->intrinsic_mode());
+                             CanValueBeSmi());
   } else {
     if (locs()->in(1).IsConstant()) {
       __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes,
@@ -3080,7 +3075,7 @@
   ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
   ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
 
-  compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
+  compiler->GenerateInstanceOf(source(), deopt_id(), type(), locs());
   ASSERT(locs()->out(0).reg() == R0);
 }
 
@@ -3132,7 +3127,7 @@
   // data area to be initialized.
   // R8: null
   if (num_elements > 0) {
-    const intptr_t array_size = instance_size - sizeof(ArrayLayout);
+    const intptr_t array_size = instance_size - sizeof(UntaggedArray);
     __ LoadObject(R8, Object::null_object());
     if (num_elements >= 2) {
       __ mov(R9, compiler::Operand(R8));
@@ -3142,7 +3137,7 @@
       __ LoadImmediate(R9, 0x1);
 #endif  // DEBUG
     }
-    __ AddImmediate(R6, R0, sizeof(ArrayLayout) - kHeapObjectTag);
+    __ AddImmediate(R6, R0, sizeof(UntaggedArray) - kHeapObjectTag);
     if (array_size < (kInlineArraySize * compiler::target::kWordSize)) {
       __ InitializeFieldsNoBarrierUnrolled(
           R0, R6, 0, num_elements * compiler::target::kWordSize, R8, R9);
@@ -3156,8 +3151,8 @@
 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   TypeUsageInfo* type_usage_info = compiler->thread()->type_usage_info();
   if (type_usage_info != nullptr) {
-    const Class& list_class = Class::Handle(
-        compiler->thread()->isolate()->class_table()->At(kArrayCid));
+    const Class& list_class =
+        Class::Handle(compiler->isolate_group()->class_table()->At(kArrayCid));
     RegisterTypeArgumentsUse(compiler->function(), type_usage_info, list_class,
                              element_type()->definition());
   }
@@ -3181,11 +3176,11 @@
   }
 
   __ Bind(&slow_path);
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& allocate_array_stub =
       Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
-  compiler->GenerateStubCall(token_pos(), allocate_array_stub,
-                             PcDescriptorsLayout::kOther, locs(), deopt_id());
+  compiler->GenerateStubCall(source(), allocate_array_stub,
+                             UntaggedPcDescriptors::kOther, locs(), deopt_id());
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -3271,9 +3266,9 @@
 }
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   const Register instance_reg = locs()->in(0).reg();
   if (slot().representation() != kTagged) {
@@ -3479,7 +3474,7 @@
                 "Should be ordered to push arguments with one instruction");
   __ PushList((1 << instantiator_type_args_reg) |
               (1 << function_type_args_reg));
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
+  compiler->GenerateRuntimeCall(source(), deopt_id(),
                                 kInstantiateTypeRuntimeEntry, 3, locs());
   __ Drop(3);          // Drop 2 type vectors, and uninstantiated type.
   __ Pop(result_reg);  // Pop instantiated type.
@@ -3543,8 +3538,8 @@
     __ b(&type_arguments_instantiated, EQ);
   }
   // Lookup cache in stub before calling runtime.
-  compiler->GenerateStubCall(token_pos(), GetStub(),
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), GetStub(), UntaggedPcDescriptors::kOther,
+                             locs());
   __ Bind(&type_arguments_instantiated);
 }
 
@@ -3579,13 +3574,12 @@
 
     compiler->SaveLiveRegisters(locs);
 
-    auto object_store = compiler->isolate()->object_store();
+    auto object_store = compiler->isolate_group()->object_store();
     const auto& allocate_context_stub = Code::ZoneHandle(
         compiler->zone(), object_store->allocate_context_stub());
     __ LoadImmediate(R1, instruction()->num_context_variables());
-    compiler->GenerateStubCall(instruction()->token_pos(),
-                               allocate_context_stub,
-                               PcDescriptorsLayout::kOther, locs);
+    compiler->GenerateStubCall(instruction()->source(), allocate_context_stub,
+                               UntaggedPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == R0);
     compiler->RestoreLiveRegisters(instruction()->locs());
     __ b(exit_label());
@@ -3630,12 +3624,12 @@
   ASSERT(locs()->temp(0).reg() == R1);
   ASSERT(locs()->out(0).reg() == R0);
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& allocate_context_stub =
       Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
   __ LoadImmediate(R1, num_context_variables());
-  compiler->GenerateStubCall(token_pos(), allocate_context_stub,
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), allocate_context_stub,
+                             UntaggedPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
@@ -3653,11 +3647,11 @@
   ASSERT(locs()->in(0).reg() == R4);
   ASSERT(locs()->out(0).reg() == R0);
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& clone_context_stub =
       Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
-  compiler->GenerateStubCall(token_pos(), clone_context_stub,
-                             /*kind=*/PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), clone_context_stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
@@ -3678,8 +3672,8 @@
     if (compiler->is_optimizing()) {
       compiler->AddDeoptIndexAtCall(deopt_id);
     } else {
-      compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id,
-                                     TokenPosition::kNoSource);
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id,
+                                     InstructionSource());
     }
   }
   if (HasParallelMove()) {
@@ -3714,7 +3708,6 @@
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 2;
   const bool using_shared_stub = UseSharedSlowPathStub(opt);
-  ASSERT((kReservedCpuRegisters & (1 << LR)) != 0);
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps,
                       using_shared_stub ? LocationSummary::kCallOnSharedSlowPath
@@ -3733,7 +3726,7 @@
       : TemplateSlowPathCode(instruction) {}
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) {
+    if (compiler->isolate_group()->use_osr() && osr_entry_label()->IsLinked()) {
       const Register value = instruction()->locs()->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
@@ -3760,26 +3753,25 @@
       const uword entry_point_offset = compiler::target::Thread::
           stack_overflow_shared_stub_entry_point_offset(
               instruction()->locs()->live_registers()->FpuRegisterCount() > 0);
-      __ ldr(LR, compiler::Address(THR, entry_point_offset));
-      __ blx(LR);
+      __ Call(compiler::Address(THR, entry_point_offset));
       compiler->RecordSafepoint(instruction()->locs(), kNumSlowPathArgs);
       compiler->RecordCatchEntryMoves();
       compiler->AddDescriptor(
-          PcDescriptorsLayout::kOther, compiler->assembler()->CodeSize(),
-          instruction()->deopt_id(), instruction()->token_pos(),
+          UntaggedPcDescriptors::kOther, compiler->assembler()->CodeSize(),
+          instruction()->deopt_id(), instruction()->source(),
           compiler->CurrentTryIndex());
     } else {
       compiler->GenerateRuntimeCall(
-          instruction()->token_pos(), instruction()->deopt_id(),
+          instruction()->source(), instruction()->deopt_id(),
           kStackOverflowRuntimeEntry, kNumSlowPathArgs, instruction()->locs());
     }
 
-    if (compiler->isolate()->use_osr() && !compiler->is_optimizing() &&
+    if (compiler->isolate_group()->use_osr() && !compiler->is_optimizing() &&
         instruction()->in_loop()) {
       // In unoptimized code, record loop stack checks as possible OSR entries.
-      compiler->AddCurrentDescriptor(PcDescriptorsLayout::kOsrEntry,
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOsrEntry,
                                      instruction()->deopt_id(),
-                                     TokenPosition::kNoSource);
+                                     InstructionSource());
     }
     compiler->pending_deoptimization_env_ = NULL;
     if (!using_shared_stub) {
@@ -3789,7 +3781,7 @@
   }
 
   compiler::Label* osr_entry_label() {
-    ASSERT(Isolate::Current()->use_osr());
+    ASSERT(IsolateGroup::Current()->use_osr());
     return &osr_entry_label_;
   }
 
@@ -3802,7 +3794,7 @@
                                compiler::target::Thread::stack_limit_offset()));
   __ cmp(SP, compiler::Operand(IP));
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
   const auto& stub = Code::ZoneHandle(
       compiler->zone(),
@@ -3818,8 +3810,8 @@
     // reflect live registers being saved in the shared spilling stubs (see
     // the stub above).
     auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
-    compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
-                                   PcDescriptorsLayout::kOther, locs(),
+    compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                   UntaggedPcDescriptors::kOther, locs(),
                                    extended_env);
     return;
   }
@@ -3978,7 +3970,7 @@
             /*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->source(), locs, try_index_, kNumSlowPathArgs);
     __ mov(result, compiler::Operand(R0));
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -4127,7 +4119,7 @@
             /*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->source(), locs, try_index_, kNumSlowPathArgs);
     __ mov(result, compiler::Operand(R0));
     compiler->RestoreLiveRegisters(locs);
     compiler->pending_deoptimization_env_ = nullptr;
@@ -5015,13 +5007,13 @@
   // Shared slow path is used in BoxInt64Instr::EmitNativeCode in
   // FLAG_use_bare_instructions mode and only after VM isolate stubs where
   // replaced with isolate-specific stubs.
-  auto object_store = Isolate::Current()->object_store();
+  auto object_store = IsolateGroup::Current()->object_store();
   const bool stubs_in_vm_isolate =
       object_store->allocate_mint_with_fpu_regs_stub()
-          ->ptr()
+          ->untag()
           ->InVMIsolateHeap() ||
       object_store->allocate_mint_without_fpu_regs_stub()
-          ->ptr()
+          ->untag()
           ->InVMIsolateHeap();
   const bool shared_slow_path_call = SlowPathSharingSupported(opt) &&
                                      FLAG_use_bare_instructions &&
@@ -5072,7 +5064,7 @@
     __ TryAllocate(compiler->mint_class(),
                    compiler->intrinsic_slow_path_label(), out_reg, tmp);
   } else if (locs()->call_on_shared_slow_path()) {
-    auto object_store = compiler->isolate()->object_store();
+    auto object_store = compiler->isolate_group()->object_store();
     const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
     const auto& stub = Code::ZoneHandle(
         compiler->zone(),
@@ -5082,7 +5074,7 @@
     ASSERT(!locs()->live_registers()->ContainsRegister(
         AllocateMintABI::kResultReg));
     auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
-    compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+    compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
                                locs(), DeoptId::kNone, extended_env);
   } else {
     BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
@@ -5538,9 +5530,9 @@
   __ vcvtsd(r.s(1), q.d(1));
 }
 
-// Low (< 7) Q registers are needed for the vcvtsd instruction.
+// Low (< 7) Q registers are needed for the vcvtds instruction.
 // TODO(dartbug.com/30953) support register range constraints in the regalloc.
-DEFINE_EMIT(Float32x4ToFloat64x2, (FixedQRegisterView<Q6> r, QRegisterView q)) {
+DEFINE_EMIT(Float32x4ToFloat64x2, (QRegisterView r, FixedQRegisterView<Q6> q)) {
   // Set X.
   __ vcvtds(r.d(0), q.s(0));
   // Set Y.
@@ -6128,7 +6120,7 @@
   const Array& kNoArgumentNames = Object::null_array();
   ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
                           kNoArgumentNames);
-  compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
+  compiler->GenerateStaticCall(deopt_id(), instance_call()->source(), target,
                                args_info, locs(), ICData::Handle(),
                                ICData::kStatic);
   __ Bind(&done);
@@ -6638,8 +6630,8 @@
     // reflect live registers being saved in the shared spilling stubs (see
     // the stub above).
     auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
-    compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
-                                   PcDescriptorsLayout::kOther, locs(),
+    compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                   UntaggedPcDescriptors::kOther, locs(),
                                    extended_env);
     CheckNullInstr::AddMetadataForRuntimeCall(this, compiler);
     return;
@@ -7537,8 +7529,8 @@
     }
     // Add a deoptimization descriptor for deoptimizing instructions that
     // may be inserted before this instruction.
-    compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, GetDeoptId(),
-                                   TokenPosition::kNoSource);
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
+                                   InstructionSource());
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -7628,7 +7620,7 @@
     Register reg,
     const Object& obj) {
   return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
-                                               token_pos(), deopt_id());
+                                               source(), deopt_id());
 }
 
 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -7711,7 +7703,7 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+  compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
                              locs());
 }
 
@@ -7721,7 +7713,7 @@
 #else
   ASSERT(!compiler->is_optimizing());
   __ BranchLinkPatchable(StubCode::DebugStepCheck());
-  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
+  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, source());
   compiler->RecordSafepoint(locs());
 #endif
 }
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 50100ea..26ea233 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -24,7 +24,7 @@
 #include "vm/symbols.h"
 #include "vm/type_testing_stubs.h"
 
-#define __ compiler->assembler()->
+#define __ (compiler->assembler())->
 #define Z (compiler->zone())
 
 namespace dart {
@@ -303,14 +303,16 @@
   }
 
   // Returns free temp register to hold argument value.
-  Register GetFreeTempRegister() {
-    // While pushing arguments only Push, PushPair, LoadObject and
-    // LoadFromOffset are used. They do not clobber TMP or LR.
-    static_assert(((1 << LR) & kDartAvailableCpuRegs) == 0,
-                  "LR should not be allocatable");
-    static_assert(((1 << TMP) & kDartAvailableCpuRegs) == 0,
-                  "TMP should not be allocatable");
-    return (pending_register_ == TMP) ? LR : TMP;
+  Register GetFreeTempRegister(FlowGraphCompiler* compiler) {
+    CLOBBERS_LR({
+      // While pushing arguments only Push, PushPair, LoadObject and
+      // LoadFromOffset are used. They do not clobber TMP or LR.
+      static_assert(((1 << LR) & kDartAvailableCpuRegs) == 0,
+                    "LR should not be allocatable");
+      static_assert(((1 << TMP) & kDartAvailableCpuRegs) == 0,
+                    "TMP should not be allocatable");
+      return (pending_register_ == TMP) ? LR : TMP;
+    });
   }
 
  private:
@@ -336,7 +338,7 @@
         if (compiler::IsSameObject(compiler::NullObject(), value.constant())) {
           reg = NULL_REG;
         } else {
-          reg = pusher.GetFreeTempRegister();
+          reg = pusher.GetFreeTempRegister(compiler);
           __ LoadObject(reg, value.constant());
         }
       } else if (value.IsFpuRegister()) {
@@ -346,7 +348,7 @@
       } else {
         ASSERT(value.IsStackSlot());
         const intptr_t value_offset = value.ToStackSlotOffset();
-        reg = pusher.GetFreeTempRegister();
+        reg = pusher.GetFreeTempRegister(compiler);
         __ LoadFromOffset(reg, value.base_reg(), value_offset);
       }
       pusher.PushRegister(compiler, reg);
@@ -390,8 +392,7 @@
     ASSERT(result == CallingConventions::kReturnFpuReg);
   }
 
-  if (compiler->intrinsic_mode()) {
-    // Intrinsics don't have a frame.
+  if (!compiler->flow_graph().graph_entry()->NeedsFrame()) {
     __ ret();
     return;
   }
@@ -411,8 +412,8 @@
   __ Bind(&stack_ok);
 #endif
   ASSERT(__ constant_pool_allowed());
-  if (yield_index() != PcDescriptorsLayout::kInvalidYieldIndex) {
-    compiler->EmitYieldPositionMetadata(token_pos(), yield_index());
+  if (yield_index() != UntaggedPcDescriptors::kInvalidYieldIndex) {
+    compiler->EmitYieldPositionMetadata(source(), yield_index());
   }
   __ LeaveDartFrame();  // Disallows constant pool use.
   __ ret();
@@ -527,8 +528,8 @@
     __ LoadImmediate(R5, 0);
   }
   __ blr(R2);
-  compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
-                                 PcDescriptorsLayout::kOther, locs());
+  compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                 UntaggedPcDescriptors::kOther, locs());
   __ Drop(argument_count);
 }
 
@@ -959,7 +960,7 @@
   Location right = locs()->in(1);
   if (right.IsConstant()) {
     ASSERT(right.constant().IsSmi());
-    const int64_t imm = static_cast<int64_t>(right.constant().raw());
+    const int64_t imm = static_cast<int64_t>(right.constant().ptr());
     __ TestImmediate(left, imm);
   } else {
     __ tst(left, compiler::Operand(right.reg()));
@@ -1101,10 +1102,10 @@
                      link_lazily() ? ObjectPool::Patchability::kPatchable
                                    : ObjectPool::Patchability::kNotPatchable);
   if (link_lazily()) {
-    compiler->GeneratePatchableCall(token_pos(), *stub,
-                                    PcDescriptorsLayout::kOther, locs());
+    compiler->GeneratePatchableCall(source(), *stub,
+                                    UntaggedPcDescriptors::kOther, locs());
   } else {
-    compiler->GenerateStubCall(token_pos(), *stub, PcDescriptorsLayout::kOther,
+    compiler->GenerateStubCall(source(), *stub, UntaggedPcDescriptors::kOther,
                                locs());
   }
   __ Pop(result);
@@ -1128,7 +1129,7 @@
   __ EnterDartFrame(0, PP);
 
   // Make space for arguments and align the frame.
-  __ ReserveAlignedFrameSpace(marshaller_.StackTopInBytes());
+  __ ReserveAlignedFrameSpace(marshaller_.RequiredStackSpaceInBytes());
 
   EmitParamMoves(compiler);
 
@@ -1141,8 +1142,8 @@
   // ADR loads relative to itself, so add kInstrSize to point to the next
   // instruction.
   __ adr(temp, compiler::Immediate(Instr::kInstrSize));
-  compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
-                                 PcDescriptorsLayout::Kind::kOther, locs());
+  compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                 UntaggedPcDescriptors::Kind::kOther, locs());
 
   __ StoreToOffset(temp, FPREG, kSavedCallerPcSlotFromFp * kWordSize);
 
@@ -1197,6 +1198,7 @@
   __ set_constant_pool_allowed(true);
 }
 
+// Keep in sync with NativeEntryInstr::EmitNativeCode.
 void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   EmitReturnMoves(compiler);
 
@@ -1204,11 +1206,11 @@
 
   // The dummy return address is in LR, no need to pop it as on Intel.
 
-  // These can be anything besides the return register (R0) and THR (R26).
-  const Register vm_tag_reg = R1;
-  const Register old_exit_frame_reg = R2;
-  const Register old_exit_through_ffi_reg = R3;
-  const Register tmp = R4;
+  // These can be anything besides the return registers (R0, R1) and THR (R26).
+  const Register vm_tag_reg = R2;
+  const Register old_exit_frame_reg = R3;
+  const Register old_exit_through_ffi_reg = R4;
+  const Register tmp = R5;
 
   __ PopPair(old_exit_frame_reg, old_exit_through_ffi_reg);
 
@@ -1227,12 +1229,6 @@
 
   __ PopNativeCalleeSavedRegisters();
 
-#if defined(TARGET_OS_FUCHSIA)
-  UNREACHABLE();  // Fuchsia does not allow dart:ffi.
-#elif defined(USING_SHADOW_CALL_STACK)
-#error Unimplemented
-#endif
-
   // Leave the entry frame.
   __ LeaveFrame();
 
@@ -1248,6 +1244,7 @@
   __ set_constant_pool_allowed(true);
 }
 
+// Keep in sync with NativeReturnInstr::EmitNativeCode and ComputeInnerLRState.
 void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Constant pool cannot be used until we enter the actual Dart frame.
   __ set_constant_pool_allowed(false);
@@ -1273,12 +1270,6 @@
   // Save a space for the code object.
   __ PushImmediate(0);
 
-#if defined(TARGET_OS_FUCHSIA)
-  UNREACHABLE();  // Fuchsia does not allow dart:ffi.
-#elif defined(USING_SHADOW_CALL_STACK)
-#error Unimplemented
-#endif
-
   __ PushNativeCalleeSavedRegisters();
 
   // Load the thread object. If we were called by a trampoline, the thread is
@@ -1310,6 +1301,14 @@
   // Now that we have THR, we can set CSP.
   __ SetupCSPFromThread(THR);
 
+#if defined(TARGET_OS_FUCHSIA)
+  __ str(R18,
+         compiler::Address(
+             THR, compiler::target::Thread::saved_shadow_call_stack_offset()));
+#elif defined(USING_SHADOW_CALL_STACK)
+#error Unimplemented
+#endif
+
   // Refresh pinned registers values (inc. write barrier mask and null object).
   __ RestorePinnedRegisters();
 
@@ -1367,9 +1366,12 @@
 
   // Load a dummy return address which suggests that we are inside of
   // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
-  __ LoadFromOffset(LR, THR,
-                    compiler::target::Thread::invoke_dart_code_stub_offset());
-  __ LoadFieldFromOffset(LR, LR, compiler::target::Code::entry_point_offset());
+  CLOBBERS_LR({
+    __ LoadFromOffset(LR, THR,
+                      compiler::target::Thread::invoke_dart_code_stub_offset());
+    __ LoadFieldFromOffset(LR, LR,
+                           compiler::target::Code::entry_point_offset());
+  });
 
   FunctionEntryInstr::EmitNativeCode(compiler);
 }
@@ -1439,9 +1441,8 @@
   const Array& kNoArgumentNames = Object::null_array();
   ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
                           kNoArgumentNames);
-  compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
-                               args_info, locs(), ICData::Handle(),
-                               ICData::kStatic);
+  compiler->GenerateStaticCall(deopt_id(), source(), CallFunction(), args_info,
+                               locs(), ICData::Handle(), ICData::kStatic);
   ASSERT(locs()->out(0).reg() == R0);
 }
 
@@ -1908,8 +1909,7 @@
                                           Smi::Cast(index.constant()).Value());
     }
     const Register value = locs()->in(2).reg();
-    __ StoreIntoArray(array, temp, value, CanValueBeSmi(),
-                      /*lr_reserved=*/!compiler->intrinsic_mode());
+    __ StoreIntoArray(array, temp, value, CanValueBeSmi());
     return;
   }
 
@@ -2063,9 +2063,9 @@
 }
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
@@ -2308,8 +2308,8 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateStubCall(TokenPosition::kNoSource,  // No token position.
-                               stub, PcDescriptorsLayout::kOther, locs);
+    compiler->GenerateStubCall(InstructionSource(),  // No token position.
+                               stub, UntaggedPcDescriptors::kOther, locs);
     __ MoveRegister(result_, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -2351,8 +2351,7 @@
   BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp);
   __ MoveRegister(temp, box_reg);
   __ StoreIntoObjectOffset(instance_reg, offset, temp,
-                           compiler::Assembler::kValueIsNotSmi,
-                           /*lr_reserved=*/!compiler->intrinsic_mode());
+                           compiler::Assembler::kValueIsNotSmi);
   __ Bind(&done);
 }
 
@@ -2396,9 +2395,9 @@
 }
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   compiler::Label skip_store;
 
@@ -2458,8 +2457,7 @@
       BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2);
       __ MoveRegister(temp2, temp);
       __ StoreIntoObjectOffset(instance_reg, offset_in_bytes, temp2,
-                               compiler::Assembler::kValueIsNotSmi,
-                               /*lr_reserved=*/!compiler->intrinsic_mode());
+                               compiler::Assembler::kValueIsNotSmi);
     } else {
       __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes);
     }
@@ -2566,13 +2564,8 @@
 
   if (ShouldEmitStoreBarrier()) {
     const Register value_reg = locs()->in(1).reg();
-    // In intrinsic mode, there is no stack frame and the function will return
-    // by executing 'ret LR' directly. Therefore we cannot overwrite LR. (see
-    // ReturnInstr::EmitNativeCode).
-    ASSERT((kDartAvailableCpuRegs & (1 << LR)) == 0);
     __ StoreIntoObjectOffset(instance_reg, offset_in_bytes, value_reg,
-                             CanValueBeSmi(),
-                             /*lr_reserved=*/!compiler->intrinsic_mode());
+                             CanValueBeSmi());
   } else {
     if (locs()->in(1).IsConstant()) {
       __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes,
@@ -2630,7 +2623,7 @@
   ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
   ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
 
-  compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
+  compiler->GenerateInstanceOf(source(), deopt_id(), type(), locs());
   ASSERT(locs()->out(0).reg() == R0);
 }
 
@@ -2680,9 +2673,9 @@
   // data area to be initialized.
   // R6: null
   if (num_elements > 0) {
-    const intptr_t array_size = instance_size - sizeof(ArrayLayout);
+    const intptr_t array_size = instance_size - sizeof(UntaggedArray);
     __ LoadObject(R6, Object::null_object());
-    __ AddImmediate(R8, R0, sizeof(ArrayLayout) - kHeapObjectTag);
+    __ AddImmediate(R8, R0, sizeof(UntaggedArray) - kHeapObjectTag);
     if (array_size < (kInlineArraySize * kWordSize)) {
       intptr_t current_offset = 0;
       while (current_offset < array_size) {
@@ -2706,8 +2699,8 @@
 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   TypeUsageInfo* type_usage_info = compiler->thread()->type_usage_info();
   if (type_usage_info != nullptr) {
-    const Class& list_class = Class::Handle(
-        compiler->thread()->isolate()->class_table()->At(kArrayCid));
+    const Class& list_class =
+        Class::Handle(compiler->isolate_group()->class_table()->At(kArrayCid));
     RegisterTypeArgumentsUse(compiler->function(), type_usage_info, list_class,
                              element_type()->definition());
   }
@@ -2730,11 +2723,11 @@
   }
 
   __ Bind(&slow_path);
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& allocate_array_stub =
       Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
-  compiler->GenerateStubCall(token_pos(), allocate_array_stub,
-                             PcDescriptorsLayout::kOther, locs(), deopt_id());
+  compiler->GenerateStubCall(source(), allocate_array_stub,
+                             UntaggedPcDescriptors::kOther, locs(), deopt_id());
   ASSERT(locs()->out(0).reg() == kResultReg);
   __ Bind(&done);
 }
@@ -2811,9 +2804,9 @@
 }
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   const Register instance_reg = locs()->in(0).reg();
   if (slot().representation() != kTagged) {
@@ -2991,7 +2984,7 @@
   __ LoadObject(TMP, type());
   __ PushPair(TMP, NULL_REG);
   __ PushPair(function_type_args_reg, instantiator_type_args_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
+  compiler->GenerateRuntimeCall(source(), deopt_id(),
                                 kInstantiateTypeRuntimeEntry, 3, locs());
   __ Drop(3);          // Drop 2 type vectors, and uninstantiated type.
   __ Pop(result_reg);  // Pop instantiated type.
@@ -3058,8 +3051,8 @@
   }
   // Lookup cache in stub before calling runtime.
 
-  compiler->GenerateStubCall(token_pos(), GetStub(),
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), GetStub(), UntaggedPcDescriptors::kOther,
+                             locs());
   __ Bind(&type_arguments_instantiated);
 }
 
@@ -3094,14 +3087,13 @@
 
     compiler->SaveLiveRegisters(locs);
 
-    auto object_store = compiler->isolate()->object_store();
+    auto object_store = compiler->isolate_group()->object_store();
     const auto& allocate_context_stub = Code::ZoneHandle(
         compiler->zone(), object_store->allocate_context_stub());
 
     __ LoadImmediate(R1, instruction()->num_context_variables());
-    compiler->GenerateStubCall(instruction()->token_pos(),
-                               allocate_context_stub,
-                               PcDescriptorsLayout::kOther, locs);
+    compiler->GenerateStubCall(instruction()->source(), allocate_context_stub,
+                               UntaggedPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == R0);
     compiler->RestoreLiveRegisters(instruction()->locs());
     __ b(exit_label());
@@ -3146,12 +3138,12 @@
   ASSERT(locs()->temp(0).reg() == R1);
   ASSERT(locs()->out(0).reg() == R0);
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& allocate_context_stub =
       Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
   __ LoadImmediate(R1, num_context_variables());
-  compiler->GenerateStubCall(token_pos(), allocate_context_stub,
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), allocate_context_stub,
+                             UntaggedPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
@@ -3169,11 +3161,11 @@
   ASSERT(locs()->in(0).reg() == R5);
   ASSERT(locs()->out(0).reg() == R0);
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& clone_context_stub =
       Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
-  compiler->GenerateStubCall(token_pos(), clone_context_stub,
-                             /*kind=*/PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), clone_context_stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
@@ -3194,8 +3186,8 @@
     if (compiler->is_optimizing()) {
       compiler->AddDeoptIndexAtCall(deopt_id);
     } else {
-      compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id,
-                                     TokenPosition::kNoSource);
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id,
+                                     InstructionSource());
     }
   }
   if (HasParallelMove()) {
@@ -3230,7 +3222,6 @@
   const intptr_t kNumInputs = 0;
   const intptr_t kNumTemps = 1;
   const bool using_shared_stub = UseSharedSlowPathStub(opt);
-  ASSERT((kReservedCpuRegisters & (1 << LR)) != 0);
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps,
                       using_shared_stub ? LocationSummary::kCallOnSharedSlowPath
@@ -3249,7 +3240,7 @@
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     auto locs = instruction()->locs();
-    if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) {
+    if (compiler->isolate_group()->use_osr() && osr_entry_label()->IsLinked()) {
       const Register value = locs->temp(0).reg();
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
@@ -3271,7 +3262,7 @@
     compiler->pending_deoptimization_env_ = env;
 
     if (using_shared_stub) {
-      auto object_store = compiler->isolate()->object_store();
+      auto object_store = compiler->isolate_group()->object_store();
       const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
       const auto& stub = Code::ZoneHandle(
           compiler->zone(),
@@ -3286,27 +3277,26 @@
         const uword entry_point_offset =
             Thread::stack_overflow_shared_stub_entry_point_offset(
                 locs->live_registers()->FpuRegisterCount() > 0);
-        __ ldr(LR, compiler::Address(THR, entry_point_offset));
-        __ blr(LR);
+        __ Call(compiler::Address(THR, entry_point_offset));
       }
       compiler->RecordSafepoint(locs, kNumSlowPathArgs);
       compiler->RecordCatchEntryMoves();
       compiler->AddDescriptor(
-          PcDescriptorsLayout::kOther, compiler->assembler()->CodeSize(),
-          instruction()->deopt_id(), instruction()->token_pos(),
+          UntaggedPcDescriptors::kOther, compiler->assembler()->CodeSize(),
+          instruction()->deopt_id(), instruction()->source(),
           compiler->CurrentTryIndex());
     } else {
       compiler->GenerateRuntimeCall(
-          instruction()->token_pos(), instruction()->deopt_id(),
+          instruction()->source(), instruction()->deopt_id(),
           kStackOverflowRuntimeEntry, kNumSlowPathArgs, locs);
     }
 
-    if (compiler->isolate()->use_osr() && !compiler->is_optimizing() &&
+    if (compiler->isolate_group()->use_osr() && !compiler->is_optimizing() &&
         instruction()->in_loop()) {
       // In unoptimized code, record loop stack checks as possible OSR entries.
-      compiler->AddCurrentDescriptor(PcDescriptorsLayout::kOsrEntry,
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOsrEntry,
                                      instruction()->deopt_id(),
-                                     TokenPosition::kNoSource);
+                                     InstructionSource());
     }
     compiler->pending_deoptimization_env_ = NULL;
     if (!using_shared_stub) {
@@ -3316,7 +3306,7 @@
   }
 
   compiler::Label* osr_entry_label() {
-    ASSERT(Isolate::Current()->use_osr());
+    ASSERT(IsolateGroup::Current()->use_osr());
     return &osr_entry_label_;
   }
 
@@ -3478,7 +3468,7 @@
             /*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->source(), locs, try_index_, kNumSlowPathArgs);
     __ mov(result, R0);
     compiler->RestoreLiveRegisters(locs);
     __ b(exit_label());
@@ -3624,7 +3614,7 @@
             /*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->source(), locs, try_index_, kNumSlowPathArgs);
     __ mov(result, R0);
     compiler->RestoreLiveRegisters(locs);
     compiler->pending_deoptimization_env_ = nullptr;
@@ -3787,7 +3777,7 @@
   if (locs()->in(1).IsConstant()) {
     const Object& constant = locs()->in(1).constant();
     ASSERT(constant.IsSmi());
-    const int64_t imm = static_cast<int64_t>(constant.raw());
+    const int64_t imm = static_cast<int64_t>(constant.ptr());
     switch (op_kind()) {
       case Token::kADD: {
         if (deopt == NULL) {
@@ -4243,13 +4233,13 @@
   // Shared slow path is used in BoxInt64Instr::EmitNativeCode in
   // FLAG_use_bare_instructions mode and only after VM isolate stubs where
   // replaced with isolate-specific stubs.
-  auto object_store = Isolate::Current()->object_store();
+  auto object_store = IsolateGroup::Current()->object_store();
   const bool stubs_in_vm_isolate =
       object_store->allocate_mint_with_fpu_regs_stub()
-          ->ptr()
+          ->untag()
           ->InVMIsolateHeap() ||
       object_store->allocate_mint_without_fpu_regs_stub()
-          ->ptr()
+          ->untag()
           ->InVMIsolateHeap();
   const bool shared_slow_path_call = SlowPathSharingSupported(opt) &&
                                      FLAG_use_bare_instructions &&
@@ -4293,7 +4283,7 @@
     __ TryAllocate(compiler->mint_class(),
                    compiler->intrinsic_slow_path_label(), out, temp);
   } else if (locs()->call_on_shared_slow_path()) {
-    auto object_store = compiler->isolate()->object_store();
+    auto object_store = compiler->isolate_group()->object_store();
     const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
     const auto& stub = Code::ZoneHandle(
         compiler->zone(),
@@ -4303,7 +4293,7 @@
     ASSERT(!locs()->live_registers()->ContainsRegister(
         AllocateMintABI::kResultReg));
     auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
-    compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+    compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
                                locs(), DeoptId::kNone, extended_env);
   } else {
     BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
@@ -5170,7 +5160,7 @@
   const Array& kNoArgumentNames = Object::null_array();
   ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
                           kNoArgumentNames);
-  compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
+  compiler->GenerateStaticCall(deopt_id(), instance_call()->source(), target,
                                args_info, locs(), ICData::Handle(),
                                ICData::kStatic);
   __ Bind(&done);
@@ -5677,7 +5667,7 @@
   if (index_loc.IsConstant()) {
     const Register length = length_loc.reg();
     const Smi& index = Smi::Cast(index_loc.constant());
-    __ CompareImmediate(length, static_cast<int64_t>(index.raw()));
+    __ CompareImmediate(length, static_cast<int64_t>(index.ptr()));
     __ b(deopt, LS);
   } else if (length_loc.IsConstant()) {
     const Smi& length = Smi::Cast(length_loc.constant());
@@ -5689,7 +5679,7 @@
       __ tst(index, compiler::Operand(index));
       __ b(deopt, MI);
     } else {
-      __ CompareImmediate(index, static_cast<int64_t>(length.raw()));
+      __ CompareImmediate(index, static_cast<int64_t>(length.ptr()));
       __ b(deopt, CS);
     }
   } else {
@@ -6476,6 +6466,74 @@
   }
 }
 
+LocationSummary* BitCastInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  LocationSummary* summary =
+      new (zone) LocationSummary(zone, /*num_inputs=*/InputCount(),
+                                 /*num_temps=*/0, LocationSummary::kNoCall);
+  switch (from()) {
+    case kUnboxedInt32:
+    case kUnboxedInt64:
+      summary->set_in(0, Location::RequiresRegister());
+      break;
+    case kUnboxedFloat:
+    case kUnboxedDouble:
+      summary->set_in(0, Location::RequiresFpuRegister());
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  switch (to()) {
+    case kUnboxedInt32:
+    case kUnboxedInt64:
+      summary->set_out(0, Location::RequiresRegister());
+      break;
+    case kUnboxedFloat:
+    case kUnboxedDouble:
+      summary->set_out(0, Location::RequiresFpuRegister());
+      break;
+    default:
+      UNREACHABLE();
+  }
+  return summary;
+}
+
+void BitCastInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  switch (from()) {
+    case kUnboxedInt32: {
+      ASSERT(to() == kUnboxedFloat);
+      const Register from_reg = locs()->in(0).reg();
+      const FpuRegister to_reg = locs()->out(0).fpu_reg();
+      __ fmovsr(to_reg, from_reg);
+      break;
+    }
+    case kUnboxedFloat: {
+      ASSERT(to() == kUnboxedInt32);
+      const FpuRegister from_reg = locs()->in(0).fpu_reg();
+      const Register to_reg = locs()->out(0).reg();
+      __ fmovrs(to_reg, from_reg);
+      break;
+    }
+    case kUnboxedInt64: {
+      ASSERT(to() == kUnboxedDouble);
+
+      const Register from_reg = locs()->in(0).reg();
+      const FpuRegister to_reg = locs()->out(0).fpu_reg();
+      __ fmovdr(to_reg, from_reg);
+      break;
+    }
+    case kUnboxedDouble: {
+      ASSERT(to() == kUnboxedInt64);
+      const FpuRegister from_reg = locs()->in(0).fpu_reg();
+      const Register to_reg = locs()->out(0).reg();
+      __ fmovrd(to_reg, from_reg);
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+}
+
 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const {
   return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
 }
@@ -6509,8 +6567,8 @@
     }
     // Add a deoptimization descriptor for deoptimizing instructions that
     // may be inserted before this instruction.
-    compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, GetDeoptId(),
-                                   TokenPosition::kNoSource);
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
+                                   InstructionSource());
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -6598,7 +6656,7 @@
     return kInvalidCondition;
   } else {
     return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
-                                                 token_pos(), deopt_id());
+                                                 source(), deopt_id());
   }
 }
 
@@ -6676,7 +6734,7 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+  compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
                              locs());
 }
 
@@ -6686,7 +6744,7 @@
 #else
   ASSERT(!compiler->is_optimizing());
   __ BranchLinkPatchable(StubCode::DebugStepCheck());
-  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
+  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, source());
   compiler->RecordSafepoint(locs());
 #endif
 }
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
index 6c30d95..eb7f1fa 100644
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ b/runtime/vm/compiler/backend/il_deserializer.cc
@@ -7,6 +7,7 @@
 #include "vm/compiler/backend/il_serializer.h"
 #include "vm/compiler/backend/range_analysis.h"
 #include "vm/compiler/call_specializer.h"
+#include "vm/compiler/frontend/base_flow_graph_builder.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/flags.h"
 #include "vm/json_writer.h"
@@ -768,9 +769,14 @@
   TokenPosition token_pos = TokenPosition::kNoSource;
   if (auto const token_int =
           CheckInteger(list->ExtraLookupValue("token_pos"))) {
-    token_pos = TokenPosition(token_int->value());
+    token_pos = TokenPosition::Deserialize(token_int->value());
   }
-  InstrInfo common_info = {deopt_id, token_pos};
+  intptr_t inlining_id = -1;
+  if (auto const inlining_int =
+          CheckInteger(list->ExtraLookupValue("inlining_id"))) {
+    inlining_id = inlining_int->value();
+  }
+  InstrInfo common_info = {deopt_id, InstructionSource(token_pos, inlining_id)};
 
   // Parse the environment before handling the instruction, as we may have
   // references to PushArguments and parsing the instruction may pop
@@ -859,7 +865,7 @@
   }
 
   auto const inst =
-      new (zone()) AllocateObjectInstr(info.token_pos, cls, type_arguments);
+      new (zone()) AllocateObjectInstr(info.source, cls, type_arguments);
 
   if (auto const closure_sexp = CheckTaggedList(
           sexp->ExtraLookupValue("closure_function"), "Function")) {
@@ -907,7 +913,7 @@
   }
 
   return new (zone())
-      AssertAssignableInstr(info.token_pos, val, dst_type, inst_type_args,
+      AssertAssignableInstr(info.source, val, dst_type, inst_type_args,
                             func_type_args, dst_name, info.deopt_id, kind);
 }
 
@@ -917,7 +923,7 @@
   auto const val = ParseValue(Retrieve(sexp, 1));
   if (val == nullptr) return nullptr;
 
-  return new (zone()) AssertBooleanInstr(info.token_pos, val, info.deopt_id);
+  return new (zone()) AssertBooleanInstr(info.source, val, info.deopt_id);
 }
 
 BooleanNegateInstr* FlowGraphDeserializer::DeserializeBooleanNegate(
@@ -973,7 +979,7 @@
   }
 
   return new (zone())
-      CheckNullInstr(val, func_name, info.deopt_id, info.token_pos);
+      CheckNullInstr(val, func_name, info.deopt_id, info.source);
 }
 
 CheckStackOverflowInstr* FlowGraphDeserializer::DeserializeCheckStackOverflow(
@@ -997,7 +1003,7 @@
     kind = CheckStackOverflowInstr::kOsrOnly;
   }
 
-  return new (zone()) CheckStackOverflowInstr(info.token_pos, stack_depth,
+  return new (zone()) CheckStackOverflowInstr(info.source, stack_depth,
                                               loop_depth, info.deopt_id, kind);
 }
 
@@ -1006,20 +1012,20 @@
     const InstrInfo& info) {
   Object& obj = Object::ZoneHandle(zone());
   if (!ParseDartValue(Retrieve(sexp, 1), &obj)) return nullptr;
-  return new (zone()) ConstantInstr(obj, info.token_pos);
+  return new (zone()) ConstantInstr(obj, info.source);
 }
 
 DebugStepCheckInstr* FlowGraphDeserializer::DeserializeDebugStepCheck(
     SExpList* sexp,
     const InstrInfo& info) {
-  auto kind = PcDescriptorsLayout::kAnyKind;
+  auto kind = UntaggedPcDescriptors::kAnyKind;
   if (auto const kind_sexp = CheckSymbol(Retrieve(sexp, "stub_kind"))) {
-    if (!PcDescriptorsLayout::ParseKind(kind_sexp->value(), &kind)) {
-      StoreError(kind_sexp, "not a valid PcDescriptorsLayout::Kind name");
+    if (!UntaggedPcDescriptors::ParseKind(kind_sexp->value(), &kind)) {
+      StoreError(kind_sexp, "not a valid UntaggedPcDescriptors::Kind name");
       return nullptr;
     }
   }
-  return new (zone()) DebugStepCheckInstr(info.token_pos, kind, info.deopt_id);
+  return new (zone()) DebugStepCheckInstr(info.source, kind, info.deopt_id);
 }
 
 GotoInstr* FlowGraphDeserializer::DeserializeGoto(SExpList* sexp,
@@ -1075,7 +1081,7 @@
   }
 
   auto const inst = new (zone()) InstanceCallInstr(
-      info.token_pos, function_name, token_kind, call_info.inputs,
+      info.source, function_name, token_kind, call_info.inputs,
       call_info.type_args_len, call_info.argument_names, checked_arg_count,
       info.deopt_id, interface_target, tearoff_interface_target);
 
@@ -1117,7 +1123,7 @@
     calls_initializer = calls_initializer_sexp->value();
   }
 
-  return new (zone()) LoadFieldInstr(instance, *slot, info.token_pos,
+  return new (zone()) LoadFieldInstr(instance, *slot, info.source,
                                      calls_initializer, info.deopt_id);
 }
 
@@ -1145,7 +1151,7 @@
   if (!ParseCallInfo(sexp, &call_info)) return nullptr;
 
   return new (zone()) NativeCallInstr(&name, &function, link_lazily,
-                                      info.token_pos, call_info.inputs);
+                                      info.source, call_info.inputs);
 }
 
 ParameterInstr* FlowGraphDeserializer::DeserializeParameter(
@@ -1174,7 +1180,7 @@
                                                       const InstrInfo& info) {
   Value* val = ParseValue(Retrieve(list, 1));
   if (val == nullptr) return nullptr;
-  return new (zone()) ReturnInstr(info.token_pos, val, info.deopt_id);
+  return new (zone()) ReturnInstr(info.source, val, info.deopt_id);
 }
 
 SpecialParameterInstr* FlowGraphDeserializer::DeserializeSpecialParameter(
@@ -1218,10 +1224,9 @@
     }
   }
 
-  auto const inst = new (zone())
-      StaticCallInstr(info.token_pos, function, call_info.type_args_len,
-                      call_info.argument_names, call_info.inputs, info.deopt_id,
-                      call_count, rebind_rule);
+  auto const inst = new (zone()) StaticCallInstr(
+      info.source, function, call_info.type_args_len, call_info.argument_names,
+      call_info.inputs, info.deopt_id, call_count, rebind_rule);
 
   if (call_info.result_type != nullptr) {
     inst->SetResultType(zone(), *call_info.result_type);
@@ -1261,8 +1266,8 @@
     if (init_sexp->value()) kind = StoreInstanceFieldInstr::Kind::kInitializing;
   }
 
-  return new (zone()) StoreInstanceFieldInstr(
-      *slot, instance, value, barrier_type, info.token_pos, kind);
+  return new (zone()) StoreInstanceFieldInstr(*slot, instance, value,
+                                              barrier_type, info.source, kind);
 }
 
 StrictCompareInstr* FlowGraphDeserializer::DeserializeStrictCompare(
@@ -1284,7 +1289,7 @@
     needs_check = check_sexp->value();
   }
 
-  return new (zone()) StrictCompareInstr(info.token_pos, kind, left, right,
+  return new (zone()) StrictCompareInstr(info.source, kind, left, right,
                                          needs_check, info.deopt_id);
 }
 
@@ -1292,7 +1297,7 @@
                                                     const InstrInfo& info) {
   Value* exception = ParseValue(Retrieve(sexp, 1));
   if (exception == nullptr) return nullptr;
-  return new (zone()) ThrowInstr(info.token_pos, info.deopt_id, exception);
+  return new (zone()) ThrowInstr(info.source, info.deopt_id, exception);
 }
 
 bool FlowGraphDeserializer::ParseCallInfo(SExpList* call,
@@ -1461,7 +1466,7 @@
     // early if we parse one.
     if (sym->Equals("null")) return true;
     if (sym->Equals("sentinel")) {
-      *out = Object::sentinel().raw();
+      *out = Object::sentinel().ptr();
       return true;
     }
 
@@ -1473,7 +1478,7 @@
       StoreError(sym, "not a reference to a constant definition");
       return false;
     }
-    *out = val->BoundConstant().raw();
+    *out = val->BoundConstant().ptr();
     // Values used in constant definitions have already been canonicalized,
     // so just exit.
     return true;
@@ -1482,7 +1487,7 @@
   // Other instance values may need to be canonicalized, so do that before
   // returning.
   if (auto const b = sexp->AsBool()) {
-    *out = Bool::Get(b->value()).raw();
+    *out = Bool::Get(b->value()).ptr();
   } else if (auto const str = sexp->AsString()) {
     *out = String::New(str->value(), Heap::kOld);
   } else if (auto const i = sexp->AsInteger()) {
@@ -1501,8 +1506,12 @@
       return ParseField(list, out);
     } else if (tag->Equals("Function")) {
       return ParseFunction(list, out);
+    } else if (tag->Equals("FunctionType")) {
+      return ParseFunctionType(list, out);
     } else if (tag->Equals("TypeParameter")) {
       return ParseTypeParameter(list, out);
+    } else if (tag->Equals("Array")) {
+      return ParseArray(list, out);
     } else if (tag->Equals("ImmutableList")) {
       return ParseImmutableList(list, out);
     } else if (tag->Equals("Instance")) {
@@ -1567,7 +1576,7 @@
   auto const ref_sexp = Retrieve(list, 1);
   if (ref_sexp == nullptr) return false;
   if (auto const cid_sexp = ref_sexp->AsInteger()) {
-    ClassTable* table = thread()->isolate()->class_table();
+    ClassTable* table = thread()->isolate_group()->class_table();
     if (!table->HasValidClassAt(cid_sexp->value())) {
       StoreError(cid_sexp, "no valid class found for cid");
       return false;
@@ -1642,13 +1651,13 @@
   auto& function = Function::Cast(*out);
   // Check the kind expected by the S-expression if one was specified.
   if (auto const kind_sexp = CheckSymbol(list->ExtraLookupValue("kind"))) {
-    FunctionLayout::Kind kind;
-    if (!FunctionLayout::ParseKind(kind_sexp->value(), &kind)) {
+    UntaggedFunction::Kind kind;
+    if (!UntaggedFunction::ParseKind(kind_sexp->value(), &kind)) {
       StoreError(kind_sexp, "unexpected function kind");
       return false;
     }
     if (function.kind() != kind) {
-      auto const kind_str = FunctionLayout::KindToCString(function.kind());
+      auto const kind_str = UntaggedFunction::KindToCString(function.kind());
       StoreError(list, "retrieved function has kind %s", kind_str);
       return false;
     }
@@ -1656,7 +1665,43 @@
   return true;
 }
 
-bool FlowGraphDeserializer::ParseImmutableList(SExpList* list, Object* out) {
+bool FlowGraphDeserializer::ParseFunctionType(SExpList* list, Object* out) {
+  ASSERT(out != nullptr);
+  if (list == nullptr) return false;
+  auto& type_params = TypeArguments::ZoneHandle(zone());
+  if (auto const type_params_sexp = Retrieve(list, "type_params")) {
+    if (!ParseTypeArguments(type_params_sexp, &type_params)) return false;
+  }
+  auto& result_type = AbstractType::ZoneHandle(zone());
+  if (auto const result_type_sexp = Retrieve(list, "result_type")) {
+    if (!ParseAbstractType(result_type_sexp, &result_type)) return false;
+  }
+  auto& parameter_types = Array::ZoneHandle(zone());
+  if (auto const parameter_types_sexp = Retrieve(list, "parameter_types")) {
+    if (!ParseDartValue(parameter_types_sexp, &parameter_types)) return false;
+  }
+  auto& parameter_names = Array::ZoneHandle(zone());
+  if (auto const parameter_names_sexp = Retrieve(list, "parameter_names")) {
+    if (!ParseDartValue(parameter_names_sexp, &parameter_names)) return false;
+  }
+  intptr_t packed_fields;
+  if (auto const packed_fields_sexp =
+          CheckInteger(list->ExtraLookupValue("packed_fields"))) {
+    packed_fields = packed_fields_sexp->value();
+  } else {
+    return false;
+  }
+  auto& sig = FunctionType::ZoneHandle(zone(), FunctionType::New());
+  sig.set_type_parameters(type_params);
+  sig.set_result_type(result_type);
+  sig.set_parameter_types(parameter_types);
+  sig.set_parameter_names(parameter_names);
+  sig.set_packed_fields(packed_fields);
+  *out = sig.ptr();
+  return true;
+}
+
+bool FlowGraphDeserializer::ParseArray(SExpList* list, Object* out) {
   ASSERT(out != nullptr);
   if (list == nullptr) return false;
 
@@ -1673,7 +1718,13 @@
     if (!ParseTypeArguments(type_args_sexp, &array_type_args_)) return false;
     arr.SetTypeArguments(array_type_args_);
   }
-  arr.MakeImmutable();
+  return true;
+}
+
+bool FlowGraphDeserializer::ParseImmutableList(SExpList* list, Object* out) {
+  if (!ParseArray(list, out)) return false;
+
+  Array::Cast(*out).MakeImmutable();
   return CanonicalizeInstance(list, out);
 }
 
@@ -1683,7 +1734,7 @@
   auto const cid_sexp = CheckInteger(Retrieve(list, 1));
   if (cid_sexp == nullptr) return false;
 
-  auto const table = thread()->isolate()->class_table();
+  auto const table = thread()->isolate_group()->class_table();
   if (!table->HasValidClassAt(cid_sexp->value())) {
     StoreError(cid_sexp, "cid is not valid");
     return false;
@@ -1719,7 +1770,7 @@
       StoreError(list, "class for instance has non-final instance fields");
       return false;
     }
-    auto& fresh_handle = Field::Handle(zone(), instance_field_.raw());
+    auto& fresh_handle = Field::Handle(zone(), instance_field_.ptr());
     final_fields.Add(&fresh_handle);
   }
 
@@ -1799,7 +1850,7 @@
       StoreError(sexp, "reference to non-constant definition");
       return false;
     }
-    *out = val->BoundConstant().raw();
+    *out = val->BoundConstant().ptr();
     if (!out->IsType()) {
       StoreError(sexp, "expected Type constant");
       return false;
@@ -1833,7 +1884,7 @@
   }
   TokenPosition token_pos = TokenPosition::kNoSource;
   if (const auto pos_sexp = CheckInteger(list->ExtraLookupValue("token_pos"))) {
-    token_pos = TokenPosition(pos_sexp->value());
+    token_pos = TokenPosition::Deserialize(pos_sexp->value());
   }
   auto type_args_ptr = &Object::null_type_arguments();
   if (const auto ta_sexp = list->ExtraLookupValue("type_args")) {
@@ -1847,13 +1898,8 @@
   if (!ParseClass(cls_sexp, &type_class_)) return false;
   const Nullability nullability =
       type_class_.IsNullClass() ? Nullability::kNullable : Nullability::kLegacy;
-  *out = Type::New(type_class_, *type_args_ptr, token_pos, nullability);
+  *out = Type::New(type_class_, *type_args_ptr, nullability);
   auto& type = Type::Cast(*out);
-  if (auto const sig_sexp = list->ExtraLookupValue("signature")) {
-    auto& function = Function::Handle(zone());
-    if (!ParseDartValue(sig_sexp, &function)) return false;
-    type.set_signature(function);
-  }
   if (is_recursive) {
     while (!pending_typerefs->is_empty()) {
       auto const ref = pending_typerefs->RemoveLast();
@@ -1894,7 +1940,7 @@
       StoreError(sexp, "reference to non-constant definition");
       return false;
     }
-    *out = val->BoundConstant().raw();
+    *out = val->BoundConstant().ptr();
     if (!out->IsTypeArguments()) {
       StoreError(sexp, "expected TypeArguments constant");
       return false;
@@ -1924,46 +1970,32 @@
   ASSERT(out != nullptr);
   if (list == nullptr) return false;
 
-  const Function* function = nullptr;
-  const Class* cls = nullptr;
-  if (auto const func_sexp = CheckSymbol(list->ExtraLookupValue("function"))) {
-    if (!ParseCanonicalName(func_sexp, &type_param_function_)) return false;
-    if (!type_param_function_.IsFunction() || type_param_function_.IsNull()) {
-      StoreError(func_sexp, "not a function name");
-      return false;
-    }
-    function = &type_param_function_;
-  } else if (auto const class_sexp =
-                 CheckInteger(list->ExtraLookupValue("class"))) {
-    const intptr_t cid = class_sexp->value();
-    auto const table = thread()->isolate()->class_table();
+  Class& cls = Class::Handle();
+  if (auto const cid_sexp = CheckInteger(list->ExtraLookupValue("cid"))) {
+    const intptr_t cid = cid_sexp->value();
+    ClassTable* table = thread()->isolate_group()->class_table();
     if (!table->HasValidClassAt(cid)) {
-      StoreError(class_sexp, "not a valid class id");
+      StoreError(cid_sexp, "no valid class found for cid");
       return false;
     }
-    type_param_class_ = table->At(cid);
-    cls = &type_param_class_;
+    cls = table->At(cid);
   } else {
-    // If we weren't given an explicit source, check in the function for this
-    // flow graph.
-    ASSERT(parsed_function_ != nullptr);
-    function = &parsed_function_->function();
+    return false;
   }
-
+  auto const base_sexp = CheckInteger(list->ExtraLookupValue("base"));
+  if (base_sexp == nullptr) return false;
+  intptr_t base = base_sexp->value();
+  auto const index_sexp = CheckInteger(list->ExtraLookupValue("index"));
+  if (index_sexp == nullptr) return false;
+  intptr_t index = index_sexp->value();
   auto const name_sexp = CheckSymbol(Retrieve(list, 1));
   if (name_sexp == nullptr) return false;
   tmp_string_ = String::New(name_sexp->value());
 
-  *out = TypeParameter::null();
-  if (function != nullptr) {
-    *out = function->LookupTypeParameter(tmp_string_, nullptr);
-  } else if (cls != nullptr) {
-    *out = cls->LookupTypeParameter(tmp_string_);
-  }
-  if (out->IsNull()) {
-    StoreError(name_sexp, "no type parameter found for name");
-    return false;
-  }
+  *out =
+      TypeParameter::New(cls, base, index, tmp_string_, Object::dynamic_type(),
+                         false, Nullability::kLegacy);
+  TypeParameter::Cast(*out).SetIsFinalized();
   return CanonicalizeInstance(list, out);
 }
 
@@ -2020,7 +2052,7 @@
       String::FromUTF8(reinterpret_cast<const uint8_t*>(name), lib_end - name);
   name_library_ = Library::LookupLibrary(thread(), tmp_string_);
   if (*lib_end == '\0') {
-    *obj = name_library_.raw();
+    *obj = name_library_.ptr();
     return true;
   }
   const char* const class_start = lib_end + 1;
@@ -2049,7 +2081,7 @@
     return false;
   }
   if (*class_end == '\0') {
-    *obj = name_class_.raw();
+    *obj = name_class_.ptr();
     return true;
   }
   if (*class_end == '.') {
@@ -2068,7 +2100,7 @@
                  empty_name ? "at top level" : name_class_.ToCString());
       return false;
     }
-    *obj = name_field_.raw();
+    *obj = name_field_.ptr();
     return true;
   }
   if (class_end[1] == '\0') {
@@ -2145,21 +2177,10 @@
     }
     func_start = func_end + 1;
   }
-  *obj = name_function_.raw();
+  *obj = name_function_.ptr();
   return true;
 }
 
-// Following the lead of BaseFlowGraphBuilder::MayCloneField here.
-const Field& FlowGraphDeserializer::MayCloneField(const Field& field) const {
-  if ((Compiler::IsBackgroundCompilation() ||
-       FLAG_force_clone_compiler_objects) &&
-      field.IsOriginal()) {
-    return Field::ZoneHandle(zone(), field.CloneFromOriginal());
-  }
-  ASSERT(field.IsZoneHandle());
-  return field;
-}
-
 bool FlowGraphDeserializer::ParseSlot(SExpList* list, const Slot** out) {
   ASSERT(out != nullptr);
   const auto offset_sexp = CheckInteger(Retrieve(list, 1));
@@ -2180,7 +2201,9 @@
       const auto field_sexp = CheckTaggedList(Retrieve(list, "field"), "Field");
       if (!ParseDartValue(field_sexp, &field)) return false;
       ASSERT(parsed_function_ != nullptr);
-      *out = &Slot::Get(MayCloneField(field), parsed_function_);
+      *out =
+          &Slot::Get(kernel::BaseFlowGraphBuilder::MayCloneField(zone(), field),
+                     parsed_function_);
       break;
     }
     case Slot::Kind::kTypeArguments:
@@ -2337,7 +2360,7 @@
     ic_data.set_is_megamorphic(is_mega_sexp->value());
   }
 
-  auto const class_table = thread()->isolate()->class_table();
+  auto const class_table = thread()->isolate_group()->class_table();
   GrowableArray<intptr_t> class_ids(zone(), 2);
   for (intptr_t i = 1, n = list->Length(); i < n; i++) {
     auto const entry = CheckList(Retrieve(list, i));
diff --git a/runtime/vm/compiler/backend/il_deserializer.h b/runtime/vm/compiler/backend/il_deserializer.h
index 3959d37..5049850 100644
--- a/runtime/vm/compiler/backend/il_deserializer.h
+++ b/runtime/vm/compiler/backend/il_deserializer.h
@@ -67,7 +67,6 @@
         name_library_(Library::Handle(zone)),
         type_class_(Class::Handle(zone)),
         type_param_class_(Class::Handle(zone)),
-        type_param_function_(Function::Handle(zone)),
         tmp_string_(String::Handle(zone)) {
     // See canonicalization comment in ParseDartValue as to why this is
     // currently necessary.
@@ -196,8 +195,8 @@
 #undef HANDLER_DECL
 
   struct InstrInfo {
-    intptr_t deopt_id;
-    TokenPosition token_pos;
+    const intptr_t deopt_id;
+    const InstructionSource source;
   };
 
   enum HandledInstruction {
@@ -282,9 +281,12 @@
   bool ParseClosure(SExpList* list, Object* out);
   bool ParseField(SExpList* list, Object* out);
   bool ParseFunction(SExpList* list, Object* out);
+  bool ParseSignature(SExpList* list, Object* out);
+  bool ParseArray(SExpList* list, Object* out);
   bool ParseImmutableList(SExpList* list, Object* out);
   bool ParseInstance(SExpList* list, Object* out);
   bool ParseType(SExpression* sexp, Object* out);
+  bool ParseFunctionType(SExpList* list, Object* out);
   bool ParseTypeParameter(SExpList* list, Object* out);
   bool ParseTypeArguments(SExpression* sexp, Object* out);
   bool ParseTypeRef(SExpList* list, Object* out);
@@ -401,7 +403,6 @@
   Library& name_library_;              // ParseCanonicalName
   Class& type_class_;                  // ParseType
   Class& type_param_class_;            // ParseTypeParameter
-  Function& type_param_function_;      // ParseTypeParameter
   // Uses of string handles tend to be immediate, so we only need one.
   String& tmp_string_;
 
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 985299e..a78e47b 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -234,8 +234,7 @@
   Register result = locs()->in(0).reg();
   ASSERT(result == EAX);
 
-  if (compiler->intrinsic_mode()) {
-    // Intrinsics don't have a frame.
+  if (!compiler->flow_graph().graph_entry()->NeedsFrame()) {
     __ ret();
     return;
   }
@@ -255,13 +254,14 @@
   __ int3();
   __ Bind(&done);
 #endif
-  if (yield_index() != PcDescriptorsLayout::kInvalidYieldIndex) {
-    compiler->EmitYieldPositionMetadata(token_pos(), yield_index());
+  if (yield_index() != UntaggedPcDescriptors::kInvalidYieldIndex) {
+    compiler->EmitYieldPositionMetadata(source(), yield_index());
   }
   __ LeaveFrame();
   __ ret();
 }
 
+// Keep in sync with NativeEntryInstr::EmitNativeCode.
 void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   EmitReturnMoves(compiler);
 
@@ -331,15 +331,14 @@
   __ popl(ESI);
   __ popl(EBX);
 
-#if defined(TARGET_OS_FUCHSIA)
-  UNREACHABLE();  // Fuchsia does not allow dart:ffi.
-#elif defined(USING_SHADOW_CALL_STACK)
+#if defined(TARGET_OS_FUCHSIA) && defined(USING_SHADOW_CALL_STACK)
 #error Unimplemented
 #endif
 
   // Leave the entry frame.
   __ LeaveFrame();
 
+  // We deal with `ret 4` for structs in the JIT callback trampolines.
   __ ret();
 }
 
@@ -449,7 +448,7 @@
     } else {
       if (compiler::Assembler::IsSafeSmi(value_) || value_.IsNull()) {
         __ movl(LocationToStackSlotAddress(destination),
-                compiler::Immediate(static_cast<int32_t>(value_.raw())));
+                compiler::Immediate(static_cast<int32_t>(value_.ptr())));
       } else {
         __ pushl(EAX);
         __ LoadObjectSafely(EAX, value_);
@@ -835,7 +834,7 @@
   Location right = locs()->in(1);
   if (right.IsConstant()) {
     ASSERT(right.constant().IsSmi());
-    const int32_t imm = static_cast<int32_t>(right.constant().raw());
+    const int32_t imm = static_cast<int32_t>(right.constant().ptr());
     __ testl(left, compiler::Immediate(imm));
   } else {
     __ testl(left, right.reg());
@@ -978,7 +977,7 @@
   const compiler::ExternalLabel label(
       reinterpret_cast<uword>(native_c_function()));
   __ movl(ECX, compiler::Immediate(label.address()));
-  compiler->GenerateStubCall(token_pos(), *stub, PcDescriptorsLayout::kOther,
+  compiler->GenerateStubCall(source(), *stub, UntaggedPcDescriptors::kOther,
                              locs());
 
   __ popl(result);
@@ -1000,7 +999,7 @@
 
   // We need to create a dummy "exit frame". It will have a null code object.
   __ LoadObject(CODE_REG, Object::null_object());
-  __ EnterDartFrame(marshaller_.StackTopInBytes());
+  __ EnterDartFrame(marshaller_.RequiredStackSpaceInBytes());
 
   // Align frame before entering C++ world.
   if (OS::ActivationFrameAlignment() > 1) {
@@ -1017,8 +1016,8 @@
   // PC-relative 'leaq' available, so we have do a trick with 'call'.
   compiler::Label get_pc;
   __ call(&get_pc);
-  compiler->EmitCallsiteMetadata(TokenPosition::kNoSource, deopt_id(),
-                                 PcDescriptorsLayout::Kind::kOther, locs());
+  compiler->EmitCallsiteMetadata(InstructionSource(), deopt_id(),
+                                 UntaggedPcDescriptors::Kind::kOther, locs());
   __ Bind(&get_pc);
   __ popl(temp);
   __ movl(compiler::Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), temp);
@@ -1037,6 +1036,16 @@
   ASSERT(temp == EBX && branch == EAX);
   __ call(temp);
 
+  // Restore the stack when a struct by value is returned into memory pointed
+  // to by a pointer that is passed into the function.
+  if (CallingConventions::kUsesRet4 &&
+      marshaller_.Location(compiler::ffi::kResultIndex).IsPointerToMemory()) {
+    // Callee uses `ret 4` instead of `ret` to return.
+    // See: https://c9x.me/x86/html/file_module_x86_id_280.html
+    // Caller does `sub esp, 4` immediately after return to balance stack.
+    __ subl(SPREG, compiler::Immediate(compiler::target::kWordSize));
+  }
+
   // The x86 calling convention requires floating point values to be returned on
   // the "floating-point stack" (aka. register ST0). We don't use the
   // floating-point stack in Dart, so we need to move the return value back into
@@ -1058,6 +1067,7 @@
   __ popl(temp);
 }
 
+// Keep in sync with NativeReturnInstr::EmitNativeCode.
 void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Bind(compiler->GetJumpLabel(this));
 
@@ -1068,9 +1078,7 @@
   __ xorl(EAX, EAX);
   __ pushl(EAX);
 
-#if defined(TARGET_OS_FUCHSIA)
-  UNREACHABLE();  // Fuchsia does not allow dart:ffi.
-#elif defined(USING_SHADOW_CALL_STACK)
+#if defined(TARGET_OS_FUCHSIA) && defined(USING_SHADOW_CALL_STACK)
 #error Unimplemented
 #endif
 
@@ -1231,9 +1239,8 @@
   const Array& kNoArgumentNames = Object::null_array();
   ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
                           kNoArgumentNames);
-  compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
-                               args_info, locs(), ICData::Handle(),
-                               ICData::kStatic);
+  compiler->GenerateStaticCall(deopt_id(), source(), CallFunction(), args_info,
+                               locs(), ICData::Handle(), ICData::kStatic);
   ASSERT(locs()->out(0).reg() == EAX);
 }
 
@@ -1884,9 +1891,9 @@
 }
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
@@ -2133,8 +2140,8 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateStubCall(TokenPosition::kNoSource, stub,
-                               PcDescriptorsLayout::kOther, locs);
+    compiler->GenerateStubCall(InstructionSource(), stub,
+                               UntaggedPcDescriptors::kOther, locs);
     __ MoveRegister(result_, EAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -2218,9 +2225,9 @@
 }
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   compiler::Label skip_store;
 
@@ -2429,7 +2436,7 @@
   ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
   ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
 
-  compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
+  compiler->GenerateInstanceOf(source(), deopt_id(), type(), locs());
   ASSERT(locs()->out(0).reg() == EAX);
 }
 
@@ -2480,10 +2487,10 @@
   // EDI: iterator which initially points to the start of the variable
   // data area to be initialized.
   if (num_elements > 0) {
-    const intptr_t array_size = instance_size - sizeof(ArrayLayout);
+    const intptr_t array_size = instance_size - sizeof(UntaggedArray);
     const compiler::Immediate& raw_null =
         compiler::Immediate(static_cast<intptr_t>(Object::null()));
-    __ leal(EDI, compiler::FieldAddress(EAX, sizeof(ArrayLayout)));
+    __ leal(EDI, compiler::FieldAddress(EAX, sizeof(UntaggedArray)));
     if (array_size < (kInlineArraySize * kWordSize)) {
       intptr_t current_offset = 0;
       __ movl(EBX, raw_null);
@@ -2523,11 +2530,11 @@
   }
 
   __ Bind(&slow_path);
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& allocate_array_stub =
       Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
-  compiler->GenerateStubCall(token_pos(), allocate_array_stub,
-                             PcDescriptorsLayout::kOther, locs(), deopt_id());
+  compiler->GenerateStubCall(source(), allocate_array_stub,
+                             UntaggedPcDescriptors::kOther, locs(), deopt_id());
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2602,9 +2609,9 @@
 }
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   const Register instance_reg = locs()->in(0).reg();
   if (slot().representation() != kTagged) {
@@ -2774,7 +2781,7 @@
   __ PushObject(type());
   __ pushl(instantiator_type_args_reg);  // Push instantiator type arguments.
   __ pushl(function_type_args_reg);      // Push function type arguments.
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
+  compiler->GenerateRuntimeCall(source(), deopt_id(),
                                 kInstantiateTypeRuntimeEntry, 3, locs());
   __ Drop(3);           // Drop 2 type vectors, and uninstantiated type.
   __ popl(result_reg);  // Pop instantiated type.
@@ -2840,8 +2847,8 @@
     __ Bind(&non_null_type_args);
   }
   // Lookup cache in stub before calling runtime.
-  compiler->GenerateStubCall(token_pos(), GetStub(),
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), GetStub(), UntaggedPcDescriptors::kOther,
+                             locs());
   __ Bind(&type_arguments_instantiated);
 }
 
@@ -2876,9 +2883,9 @@
     compiler->SaveLiveRegisters(locs);
 
     __ movl(EDX, compiler::Immediate(instruction()->num_context_variables()));
-    compiler->GenerateStubCall(instruction()->token_pos(),
+    compiler->GenerateStubCall(instruction()->source(),
                                StubCode::AllocateContext(),
-                               PcDescriptorsLayout::kOther, locs);
+                               UntaggedPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == EAX);
     compiler->RestoreLiveRegisters(instruction()->locs());
     __ jmp(exit_label());
@@ -2925,8 +2932,8 @@
   ASSERT(locs()->out(0).reg() == EAX);
 
   __ movl(EDX, compiler::Immediate(num_context_variables()));
-  compiler->GenerateStubCall(token_pos(), StubCode::AllocateContext(),
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), StubCode::AllocateContext(),
+                             UntaggedPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
@@ -2944,8 +2951,8 @@
   ASSERT(locs()->in(0).reg() == ECX);
   ASSERT(locs()->out(0).reg() == EAX);
 
-  compiler->GenerateStubCall(token_pos(), StubCode::CloneContext(),
-                             /*kind=*/PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), StubCode::CloneContext(),
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
@@ -2966,8 +2973,8 @@
     if (compiler->is_optimizing()) {
       compiler->AddDeoptIndexAtCall(deopt_id);
     } else {
-      compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id,
-                                     TokenPosition::kNoSource);
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id,
+                                     InstructionSource());
     }
   }
   if (HasParallelMove()) {
@@ -3018,7 +3025,7 @@
       : TemplateSlowPathCode(instruction) {}
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) {
+    if (compiler->isolate_group()->use_osr() && osr_entry_label()->IsLinked()) {
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
       __ movl(compiler::Address(THR, Thread::stack_overflow_flags_offset()),
@@ -3034,15 +3041,15 @@
         instruction(), /*num_slow_path_args=*/0);
     compiler->pending_deoptimization_env_ = env;
     compiler->GenerateRuntimeCall(
-        instruction()->token_pos(), instruction()->deopt_id(),
+        instruction()->source(), instruction()->deopt_id(),
         kStackOverflowRuntimeEntry, 0, instruction()->locs());
 
-    if (compiler->isolate()->use_osr() && !compiler->is_optimizing() &&
+    if (compiler->isolate_group()->use_osr() && !compiler->is_optimizing() &&
         instruction()->in_loop()) {
       // In unoptimized code, record loop stack checks as possible OSR entries.
-      compiler->AddCurrentDescriptor(PcDescriptorsLayout::kOsrEntry,
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOsrEntry,
                                      instruction()->deopt_id(),
-                                     TokenPosition::kNoSource);
+                                     InstructionSource());
     }
     compiler->pending_deoptimization_env_ = NULL;
     compiler->RestoreLiveRegisters(instruction()->locs());
@@ -3050,7 +3057,7 @@
   }
 
   compiler::Label* osr_entry_label() {
-    ASSERT(Isolate::Current()->use_osr());
+    ASSERT(IsolateGroup::Current()->use_osr());
     return &osr_entry_label_;
   }
 
@@ -5107,7 +5114,7 @@
   const Array& kNoArgumentNames = Object::null_array();
   ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
                           kNoArgumentNames);
-  compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
+  compiler->GenerateStaticCall(deopt_id(), instance_call()->source(), target,
                                args_info, locs(), ICData::Handle(),
                                ICData::kStatic);
   __ Bind(&done);
@@ -5691,17 +5698,17 @@
       __ testl(index, index);
       __ j(NEGATIVE, deopt);
     } else {
-      __ cmpl(index, compiler::Immediate(static_cast<int32_t>(length.raw())));
+      __ cmpl(index, compiler::Immediate(static_cast<int32_t>(length.ptr())));
       __ j(ABOVE_EQUAL, deopt);
     }
   } else if (index_loc.IsConstant()) {
     const Smi& index = Smi::Cast(index_loc.constant());
     if (length_loc.IsStackSlot()) {
       const compiler::Address& length = LocationToStackSlotAddress(length_loc);
-      __ cmpl(length, compiler::Immediate(static_cast<int32_t>(index.raw())));
+      __ cmpl(length, compiler::Immediate(static_cast<int32_t>(index.ptr())));
     } else {
       Register length = length_loc.reg();
-      __ cmpl(length, compiler::Immediate(static_cast<int32_t>(index.raw())));
+      __ cmpl(length, compiler::Immediate(static_cast<int32_t>(index.ptr())));
     }
     __ j(BELOW_EQUAL, deopt);
   } else if (length_loc.IsStackSlot()) {
@@ -6441,8 +6448,8 @@
     }
     // Add a deoptimization descriptor for deoptimizing instructions that
     // may be inserted before this instruction.
-    compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, GetDeoptId(),
-                                   TokenPosition::kNoSource);
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
+                                   InstructionSource());
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -6524,7 +6531,7 @@
     Register reg,
     const Object& obj) {
   return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
-                                               token_pos(), deopt_id());
+                                               source(), deopt_id());
 }
 
 // Detect pattern when one value is zero and another is a power of 2.
@@ -6628,8 +6635,8 @@
   // ECX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
   __ xorl(ECX, ECX);
   __ call(EBX);
-  compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
-                                 PcDescriptorsLayout::kOther, locs());
+  compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                 UntaggedPcDescriptors::kOther, locs());
   __ Drop(argument_count);
 }
 
@@ -6678,7 +6685,7 @@
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+  compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
                              locs());
 }
 
@@ -6688,7 +6695,7 @@
 #else
   ASSERT(!compiler->is_optimizing());
   __ Call(StubCode::DebugStepCheck());
-  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
+  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, source());
   compiler->RecordSafepoint(locs());
 #endif
 }
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 6a3fc15..79b93d5 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -127,13 +127,13 @@
     const CidRange& range = targets[i];
     const auto target_info = targets.TargetAt(i);
     const intptr_t count = target_info->count;
-    target = target_info->target->raw();
+    target = target_info->target->ptr();
     if (i > 0) {
       f->AddString(" | ");
     }
     if (range.IsSingleCid()) {
-      const Class& cls =
-          Class::Handle(Isolate::Current()->class_table()->At(range.cid_start));
+      const Class& cls = Class::Handle(
+          IsolateGroup::Current()->class_table()->At(range.cid_start));
       f->Printf("%s", String::Handle(cls.Name()).ToCString());
       f->Printf(" cid %" Pd " cnt:%" Pd " trgt:'%s'", range.cid_start, count,
                 target.ToQualifiedCString());
@@ -168,8 +168,8 @@
     if (i > 0) {
       f->AddString(" | ");
     }
-    const Class& cls =
-        Class::Handle(Isolate::Current()->class_table()->At(range.cid_start));
+    const Class& cls = Class::Handle(
+        IsolateGroup::Current()->class_table()->At(range.cid_start));
     f->Printf("%s etc. ", String::Handle(cls.Name()).ToCString());
     if (range.IsSingleCid()) {
       f->Printf(" cid %" Pd, range.cid_start);
@@ -209,8 +209,8 @@
       if (k > 0) {
         f->AddString(", ");
       }
-      const Class& cls =
-          Class::Handle(Isolate::Current()->class_table()->At(class_ids[k]));
+      const Class& cls = Class::Handle(
+          IsolateGroup::Current()->class_table()->At(class_ids[k]));
       f->Printf("%s", String::Handle(cls.Name()).ToCString());
     }
     f->Printf(" cnt:%" Pd " trgt:'%s'", count, target.ToQualifiedCString());
@@ -233,7 +233,7 @@
     const intptr_t count = ic_data.GetCountAt(i);
     const intptr_t cid = ic_data.GetReceiverClassIdAt(i);
     const Class& cls =
-        Class::Handle(Isolate::Current()->class_table()->At(cid));
+        Class::Handle(IsolateGroup::Current()->class_table()->At(cid));
     f->Printf("%s : %" Pd ", ", String::Handle(cls.Name()).ToCString(), count);
   }
   f->AddString("]");
@@ -814,14 +814,14 @@
 void CheckClassIdInstr::PrintOperandsTo(BaseTextBuffer* f) const {
   value()->PrintTo(f);
 
-  const Class& cls =
-      Class::Handle(Isolate::Current()->class_table()->At(cids().cid_start));
+  const Class& cls = Class::Handle(
+      IsolateGroup::Current()->class_table()->At(cids().cid_start));
   const String& name = String::Handle(cls.ScrubbedName());
   if (cids().IsSingleCid()) {
     f->Printf(", %s", name.ToCString());
   } else {
-    const Class& cls2 =
-        Class::Handle(Isolate::Current()->class_table()->At(cids().cid_end));
+    const Class& cls2 = Class::Handle(
+        IsolateGroup::Current()->class_table()->At(cids().cid_end));
     const String& name2 = String::Handle(cls2.ScrubbedName());
     f->Printf(", cid %" Pd "-%" Pd " %s-%s", cids().cid_start, cids().cid_end,
               name.ToCString(), name2.ToCString());
@@ -1059,7 +1059,7 @@
 
 void ReturnInstr::PrintOperandsTo(BaseTextBuffer* f) const {
   Instruction::PrintOperandsTo(f);
-  if (yield_index() != PcDescriptorsLayout::kInvalidYieldIndex) {
+  if (yield_index() != UntaggedPcDescriptors::kInvalidYieldIndex) {
     f->Printf(", yield_index = %" Pd "", yield_index());
   }
 }
@@ -1067,11 +1067,26 @@
 void FfiCallInstr::PrintOperandsTo(BaseTextBuffer* f) const {
   f->AddString(" pointer=");
   InputAt(TargetAddressIndex())->PrintTo(f);
-  for (intptr_t i = 0, n = InputCount(); i < n - 1; ++i) {
+  if (marshaller_.PassTypedData()) {
+    f->AddString(", typed_data=");
+    InputAt(TypedDataIndex())->PrintTo(f);
+  }
+  intptr_t def_index = 0;
+  for (intptr_t arg_index = 0; arg_index < marshaller_.num_args();
+       arg_index++) {
+    const auto& arg_location = marshaller_.Location(arg_index);
+    const bool is_compound = arg_location.container_type().IsCompound();
+    const intptr_t num_defs = marshaller_.NumDefinitions(arg_index);
     f->AddString(", ");
-    InputAt(i)->PrintTo(f);
+    if (is_compound) f->AddString("(");
+    for (intptr_t i = 0; i < num_defs; i++) {
+      InputAt(def_index)->PrintTo(f);
+      if ((i + 1) < num_defs) f->AddString(", ");
+      def_index++;
+    }
+    if (is_compound) f->AddString(")");
     f->AddString(" (@");
-    marshaller_.Location(i).PrintTo(f);
+    arg_location.PrintTo(f);
     f->AddString(")");
   }
 }
@@ -1093,10 +1108,10 @@
 
 void NativeParameterInstr::PrintOperandsTo(BaseTextBuffer* f) const {
   // Where the calling convention puts it.
-  marshaller_.Location(index_).PrintTo(f);
+  marshaller_.Location(marshaller_.ArgumentIndex(def_index_)).PrintTo(f);
   f->AddString(" at ");
   // Where the arguments are when pushed on the stack.
-  marshaller_.NativeLocationOfNativeParameter(index_).PrintTo(f);
+  marshaller_.NativeLocationOfNativeParameter(def_index_).PrintTo(f);
 }
 
 void CatchBlockEntryInstr::PrintTo(BaseTextBuffer* f) const {
@@ -1137,7 +1152,7 @@
   } else {
     const Object& owner = Object::Handle(code_.owner());
     if (owner.IsFunction()) {
-      name = Function::Handle(Function::RawCast(owner.raw()))
+      name = Function::Handle(Function::RawCast(owner.ptr()))
                  .ToFullyQualifiedCString();
     }
   }
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
index 5e6fc92..31fd469 100644
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ b/runtime/vm/compiler/backend/il_serializer.cc
@@ -37,7 +37,7 @@
                                          const FlowGraph* flow_graph)
     : flow_graph_(ASSERT_NOTNULL(flow_graph)),
       zone_(zone),
-      object_store_(flow_graph->thread()->isolate()->object_store()),
+      object_store_(flow_graph->thread()->isolate_group()->object_store()),
       open_recursive_types_(zone_),
       llvm_constants_(
           GrowableObjectArray::Handle(zone_,
@@ -65,7 +65,7 @@
       serialize_parent_(Function::Handle(zone_)),
       type_arguments_elem_(AbstractType::Handle(zone_)),
       type_class_(Class::Handle(zone_)),
-      type_function_(Function::Handle(zone_)),
+      type_signature_(FunctionType::Handle(zone_)),
       type_ref_type_(AbstractType::Handle(zone_)) {
   // Double-check that the zone in the flow graph is a parent of the
   // zone we'll be using for serialization.
@@ -389,20 +389,12 @@
   if (t.IsTypeParameter()) {
     const auto& param = TypeParameter::Cast(t);
     AddSymbol(sexp, "TypeParameter");
+    AddExtraInteger(sexp, "cid", param.parameterized_class_id());
+    AddExtraInteger(sexp, "base", param.base());
+    AddExtraInteger(sexp, "index", param.index());
     tmp_string_ = param.name();
     AddSymbol(sexp, tmp_string_.ToCString());
-    if (param.IsFunctionTypeParameter()) {
-      if (param.parameterized_function() != flow_graph_->function().raw()) {
-        type_function_ = param.parameterized_function();
-        sexp->AddExtra("function", CanonicalNameToSExp(type_function_));
-      } else if (FLAG_verbose_flow_graph_serialization) {
-        sexp->AddExtra("function",
-                       CanonicalNameToSExp(flow_graph_->function()));
-      }
-    } else if (param.IsClassTypeParameter()) {
-      type_class_ = param.parameterized_class();
-      AddExtraInteger(sexp, "class", type_class_.id());
-    }
+    // TODO(regis): bound, default argument, flags, nullability, hash.
     return sexp;
   }
   if (t.IsTypeRef()) {
@@ -433,21 +425,37 @@
     }
     return sexp;
   }
+  // We want to check for the type being recursive before we may serialize
+  // any sub-parts that include possible TypeRefs to this type.
+  const bool is_recursive = t.IsRecursive();
+  intptr_t hash = 0;
+  if (is_recursive) {
+    hash = t.Hash();
+    AddExtraInteger(sexp, "hash", hash);
+    open_recursive_types_.Insert(hash, &t);
+  }
+  if (t.IsFunctionType()) {
+    const auto& sig = FunctionType::Handle(zone(), FunctionType::Cast(t).ptr());
+    AddSymbol(sexp, "FunctionType");
+    function_type_args_ = sig.type_parameters();
+    if (auto const ta_sexp = NonEmptyTypeArgumentsToSExp(function_type_args_)) {
+      sexp->AddExtra("type_params", ta_sexp);
+    }
+    auto& type = AbstractType::Handle(zone(), sig.result_type());
+    sexp->AddExtra("result_type", AbstractTypeToSExp(type));
+    auto& parameter_types = Array::Handle(zone(), sig.parameter_types());
+    sexp->AddExtra("parameter_types", ArrayToSExp(parameter_types));
+    auto& parameter_names = Array::Handle(zone(), sig.parameter_names());
+    sexp->AddExtra("parameter_names", ArrayToSExp(parameter_names));
+    AddExtraInteger(sexp, "packed_fields", sig.packed_fields());
+    // If we were parsing a recursive type, we're now done building it, so
+    // remove it from the open recursive types.
+    if (is_recursive) open_recursive_types_.Remove(hash);
+    return sexp;
+  }
   ASSERT(t.IsType());
   AddSymbol(sexp, "Type");
   const auto& type = Type::Cast(t);
-  if (!type.token_pos().IsNoSource()) {
-    AddExtraInteger(sexp, "token_pos", type.token_pos().value());
-  }
-  // We want to check for the type being recursive before we may serialize
-  // any sub-parts that include possible TypeRefs to this type.
-  const bool is_recursive = type.IsRecursive();
-  intptr_t hash = 0;
-  if (is_recursive) {
-    hash = type.Hash();
-    AddExtraInteger(sexp, "hash", hash);
-    open_recursive_types_.Insert(hash, &type);
-  }
   if (type.HasTypeClass()) {
     type_class_ = type.type_class();
     // This avoids re-entry as long as serializing a class doesn't involve
@@ -458,10 +466,6 @@
     // just printing out this version.
     AddExtraString(sexp, "name", type.ToCString());
   }
-  if (type.IsFunctionType()) {
-    type_function_ = type.signature();
-    sexp->AddExtra("signature", DartValueToSExp(type_function_));
-  }
   // Since type arguments may themselves be instantiations of generic
   // types, we may call back into this function in the middle of printing
   // the TypeArguments and so we must allocate a fresh handle here.
@@ -580,9 +584,9 @@
       AddExtraSymbol(sexp, "native_name", tmp_string_.ToCString());
     }
   }
-  if (func.kind() != FunctionLayout::Kind::kRegularFunction ||
+  if (func.kind() != UntaggedFunction::Kind::kRegularFunction ||
       FLAG_verbose_flow_graph_serialization) {
-    AddExtraSymbol(sexp, "kind", FunctionLayout::KindToCString(func.kind()));
+    AddExtraSymbol(sexp, "kind", UntaggedFunction::KindToCString(func.kind()));
   }
   function_type_args_ = func.type_parameters();
   if (auto const ta_sexp = NonEmptyTypeArgumentsToSExp(function_type_args_)) {
@@ -591,7 +595,7 @@
   return sexp;
 }
 
-SExpression* FlowGraphSerializer::ArrayToSExp(const Array& arr) {
+SExpression* FlowGraphSerializer::ImmutableListToSExp(const Array& arr) {
   if (arr.IsNull()) return nullptr;
   // We should only be getting immutable lists when serializing Dart values
   // in flow graphs.
@@ -612,6 +616,18 @@
   return sexp;
 }
 
+SExpression* FlowGraphSerializer::ArrayToSExp(const Array& arr) {
+  if (arr.IsNull()) return nullptr;
+  auto sexp = new (zone()) SExpList(zone());
+  AddSymbol(sexp, "Array");
+  auto& array_elem = Object::Handle(zone());
+  for (intptr_t i = 0; i < arr.Length(); i++) {
+    array_elem = arr.At(i);
+    sexp->Add(DartValueToSExp(array_elem));
+  }
+  return sexp;
+}
+
 SExpression* FlowGraphSerializer::ClosureToSExp(const Closure& c) {
   if (c.IsNull()) return nullptr;
   auto sexp = new (zone()) SExpList(zone());
@@ -660,7 +676,7 @@
   if (dartval.IsNull()) {
     return new (zone()) SExpSymbol("null");
   }
-  if (dartval.raw() == Object::sentinel().raw()) {
+  if (dartval.ptr() == Object::sentinel().ptr()) {
     return new (zone()) SExpSymbol("sentinel");
   }
   if (dartval.IsString()) {
@@ -691,7 +707,7 @@
     return CodeToSExp(Code::Cast(dartval));
   }
   if (dartval.IsArray()) {
-    return ArrayToSExp(Array::Cast(dartval));
+    return ImmutableListToSExp(Array::Cast(dartval));
   }
   if (dartval.IsFunction()) {
     return FunctionToSExp(Function::Cast(dartval));
@@ -823,7 +839,10 @@
     sexp->AddExtra("env", env()->ToSExpression(s));
   }
   if (!token_pos().IsNoSource()) {
-    s->AddExtraInteger(sexp, "token_pos", token_pos().value());
+    s->AddExtraInteger(sexp, "token_pos", token_pos().Serialize());
+  }
+  if (has_inlining_id()) {
+    s->AddExtraInteger(sexp, "inlining_id", inlining_id());
   }
 }
 
@@ -1060,9 +1079,10 @@
     SExpList* sexp,
     FlowGraphSerializer* s) const {
   Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (stub_kind_ != PcDescriptorsLayout::kAnyKind ||
+  if (stub_kind_ != UntaggedPcDescriptors::kAnyKind ||
       FLAG_verbose_flow_graph_serialization) {
-    auto const stub_kind_name = PcDescriptorsLayout::KindToCString(stub_kind_);
+    auto const stub_kind_name =
+        UntaggedPcDescriptors::KindToCString(stub_kind_);
     ASSERT(stub_kind_name != nullptr);
     s->AddExtraSymbol(sexp, "stub_kind", stub_kind_name);
   }
@@ -1240,8 +1260,8 @@
     }
   } else {
     if (interface_target().IsNull() ||
-        (function_name().raw() != interface_target().name() &&
-         function_name().raw() != tearoff_interface_target().name())) {
+        (function_name().ptr() != interface_target().name() &&
+         function_name().ptr() != tearoff_interface_target().name())) {
       s->AddExtraString(sexp, "function_name", function_name().ToCString());
     }
   }
diff --git a/runtime/vm/compiler/backend/il_serializer.h b/runtime/vm/compiler/backend/il_serializer.h
index c5d8d6f..fda5731 100644
--- a/runtime/vm/compiler/backend/il_serializer.h
+++ b/runtime/vm/compiler/backend/il_serializer.h
@@ -72,6 +72,7 @@
   // value is the null object, the null pointer is returned.
   SExpression* AbstractTypeToSExp(const AbstractType& typ);
   SExpression* ArrayToSExp(const Array& arr);
+  SExpression* ImmutableListToSExp(const Array& arr);
   SExpression* ClassToSExp(const Class& cls);
   SExpression* ClosureToSExp(const Closure& c);
   SExpression* ContextToSExp(const Context& c);
@@ -133,7 +134,7 @@
 
   // A map of currently open (being serialized) recursive types. We use this
   // to determine whether to serialize the referred types in TypeRefs.
-  IntMap<const Type*> open_recursive_types_;
+  IntMap<const AbstractType*> open_recursive_types_;
 
   // Used for --populate-llvm-constant-pool in ConstantPoolToSExp.
   class LLVMPoolMapKeyEqualsTraits : public AllStatic {
@@ -142,10 +143,10 @@
     static bool ReportStats() { return false; }
 
     static bool IsMatch(const Object& a, const Object& b) {
-      return a.raw() == b.raw();
+      return a.ptr() == b.ptr();
     }
     static uword Hash(const Object& obj) {
-      if (obj.IsSmi()) return static_cast<uword>(obj.raw());
+      if (obj.IsSmi()) return static_cast<uword>(obj.ptr());
       if (obj.IsInstance()) return Instance::Cast(obj).CanonicalizeHash();
       return obj.GetClassId();
     }
@@ -188,7 +189,7 @@
   Function& serialize_parent_;         // SerializeCanonicalName
   AbstractType& type_arguments_elem_;  // TypeArgumentsToSExp
   Class& type_class_;                  // AbstractTypeToSExp
-  Function& type_function_;            // AbstractTypeToSExp
+  FunctionType& type_signature_;       // AbstractTypeToSExp
   AbstractType& type_ref_type_;        // AbstractTypeToSExp
 };
 
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index 1a514be..ab32cd4 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -35,7 +35,7 @@
   auto& lib = Library::Handle();
   lib ^= Api::UnwrapHandle(api_lib);
   EXPECT(!lib.IsNull());
-  return lib.raw();
+  return lib.ptr();
 }
 
 FunctionPtr GetFunction(const Library& lib, const char* name) {
@@ -43,7 +43,7 @@
   const auto& func = Function::Handle(lib.LookupFunctionAllowPrivate(
       String::Handle(Symbols::New(thread, name))));
   EXPECT(!func.IsNull());
-  return func.raw();
+  return func.ptr();
 }
 
 ClassPtr GetClass(const Library& lib, const char* name) {
@@ -51,14 +51,14 @@
   const auto& cls = Class::Handle(
       lib.LookupClassAllowPrivate(String::Handle(Symbols::New(thread, name))));
   EXPECT(!cls.IsNull());
-  return cls.raw();
+  return cls.ptr();
 }
 
 TypeParameterPtr GetClassTypeParameter(const Class& klass, const char* name) {
   const auto& param = TypeParameter::Handle(
       klass.LookupTypeParameter(String::Handle(String::New(name))));
   EXPECT(!param.IsNull());
-  return param.raw();
+  return param.ptr();
 }
 
 TypeParameterPtr GetFunctionTypeParameter(const Function& fun,
@@ -67,12 +67,12 @@
   const auto& param = TypeParameter::Handle(
       fun.LookupTypeParameter(String::Handle(String::New(name)), &fun_level));
   EXPECT(!param.IsNull());
-  return param.raw();
+  return param.ptr();
 }
 
 ObjectPtr Invoke(const Library& lib, const char* name) {
   Thread* thread = Thread::Current();
-  Dart_Handle api_lib = Api::NewHandle(thread, lib.raw());
+  Dart_Handle api_lib = Api::NewHandle(thread, lib.ptr());
   Dart_Handle result;
   {
     TransitionVMToNative transition(thread);
@@ -97,7 +97,7 @@
   auto pipeline = CompilationPipeline::New(zone, function_);
 
   parsed_function_ = new (zone)
-      ParsedFunction(thread, Function::ZoneHandle(zone, function_.raw()));
+      ParsedFunction(thread, Function::ZoneHandle(zone, function_.ptr()));
   pipeline->ParseFunction(parsed_function_);
 
   // Extract type feedback before the graph is built, as the graph
@@ -125,15 +125,6 @@
   pass_state_->reorder_blocks = reorder_blocks;
 
   if (optimized) {
-    pass_state_->inline_id_to_function.Add(&function_);
-    // We do not add the token position now because we don't know the
-    // position of the inlined call until later. A side effect of this
-    // is that the length of |inline_id_to_function| is always larger
-    // than the length of |inline_id_to_token_pos| by one.
-    // Top scope function has no caller (-1). We do this because we expect
-    // all token positions to be at an inlined call.
-    pass_state_->caller_inline_id.Add(-1);
-
     JitCallSpecializer jit_call_specializer(flow_graph_, &speculative_policy);
     AotCallSpecializer aot_call_specializer(/*precompiler=*/nullptr,
                                             flow_graph_, &speculative_policy);
@@ -180,8 +171,13 @@
   const auto& deopt_info_array =
       Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler));
   const auto pool_attachment = Code::PoolAttachment::kAttachPool;
-  const auto& code = Code::Handle(Code::FinalizeCode(
-      &graph_compiler, &assembler, pool_attachment, optimized, nullptr));
+  Code& code = Code::Handle();
+  {
+    SafepointWriteRwLocker ml(thread_,
+                              thread_->isolate_group()->program_lock());
+    code ^= Code::FinalizeCode(&graph_compiler, &assembler, pool_attachment,
+                               optimized, nullptr);
+  }
   code.set_is_optimized(optimized);
   code.set_owner(function_);
 
@@ -195,11 +191,15 @@
   graph_compiler.FinalizeStaticCallTargetsTable(code);
   graph_compiler.FinalizeCodeSourceMap(code);
 
-  if (optimized) {
-    function_.InstallOptimizedCode(code);
-  } else {
-    function_.set_unoptimized_code(code);
-    function_.AttachCode(code);
+  {
+    SafepointWriteRwLocker ml(thread_,
+                              thread_->isolate_group()->program_lock());
+    if (optimized) {
+      function_.InstallOptimizedCode(code);
+    } else {
+      function_.set_unoptimized_code(code);
+      function_.AttachCode(code);
+    }
   }
 
   // We expect there to be no deoptimizations.
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index 01da0c3..e34a5fe 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -66,11 +66,13 @@
 class TestPipeline : public ValueObject {
  public:
   explicit TestPipeline(const Function& function,
-                        CompilerPass::PipelineMode mode)
+                        CompilerPass::PipelineMode mode,
+                        bool is_optimizing = true)
       : function_(function),
         thread_(Thread::Current()),
         compiler_state_(thread_,
                         mode == CompilerPass::PipelineMode::kAOT,
+                        is_optimizing,
                         CompilerState::ShouldTrace(function)),
         mode_(mode) {}
   ~TestPipeline() { delete pass_state_; }
@@ -311,15 +313,17 @@
 
  private:
   static FlowGraph& MakeDummyGraph(Thread* thread) {
+    const FunctionType& signature =
+        FunctionType::ZoneHandle(FunctionType::New());
     const Function& func = Function::ZoneHandle(Function::New(
-        String::Handle(Symbols::New(thread, "dummy")),
-        FunctionLayout::kRegularFunction,
+        signature, String::Handle(Symbols::New(thread, "dummy")),
+        UntaggedFunction::kRegularFunction,
         /*is_static=*/true,
         /*is_const=*/false,
         /*is_abstract=*/false,
         /*is_external=*/false,
         /*is_native=*/true,
-        Class::Handle(thread->isolate()->object_store()->object_class()),
+        Class::Handle(thread->isolate_group()->object_store()->object_class()),
         TokenPosition::kNoSource));
 
     Zone* zone = thread->zone();
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 34af406..d81e582 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -305,8 +305,7 @@
     ASSERT(result == CallingConventions::kReturnFpuReg);
   }
 
-  if (compiler->intrinsic_mode()) {
-    // Intrinsics don't have a frame.
+  if (!compiler->flow_graph().graph_entry()->NeedsFrame()) {
     __ ret();
     return;
   }
@@ -327,8 +326,8 @@
   __ Bind(&done);
 #endif
   ASSERT(__ constant_pool_allowed());
-  if (yield_index() != PcDescriptorsLayout::kInvalidYieldIndex) {
-    compiler->EmitYieldPositionMetadata(token_pos(), yield_index());
+  if (yield_index() != UntaggedPcDescriptors::kInvalidYieldIndex) {
+    compiler->EmitYieldPositionMetadata(source(), yield_index());
   }
   __ LeaveDartFrame();  // Disallows constant pool use.
   __ ret();
@@ -341,6 +340,7 @@
     CallingConventions::kCalleeSaveCpuRegisters,
     CallingConventions::kCalleeSaveXmmRegisters);
 
+// Keep in sync with NativeEntryInstr::EmitNativeCode.
 void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   EmitReturnMoves(compiler);
 
@@ -375,9 +375,7 @@
   // Restore C++ ABI callee-saved registers.
   __ PopRegisters(kCalleeSaveRegistersSet);
 
-#if defined(TARGET_OS_FUCHSIA)
-  UNREACHABLE();  // Fuchsia does not allow dart:ffi.
-#elif defined(USING_SHADOW_CALL_STACK)
+#if defined(TARGET_OS_FUCHSIA) && defined(USING_SHADOW_CALL_STACK)
 #error Unimplemented
 #endif
 
@@ -901,7 +899,7 @@
   Location right = locs()->in(1);
   if (right.IsConstant()) {
     ASSERT(right.constant().IsSmi());
-    const int64_t imm = static_cast<int64_t>(right.constant().raw());
+    const int64_t imm = static_cast<int64_t>(right.constant().ptr());
     __ TestImmediate(left_reg, compiler::Immediate(imm));
   } else {
     __ testq(left_reg, right.reg());
@@ -1025,8 +1023,8 @@
     compiler::ExternalLabel label(NativeEntry::LinkNativeCallEntry());
     __ LoadNativeEntry(RBX, &label,
                        compiler::ObjectPoolBuilderEntry::kPatchable);
-    compiler->GeneratePatchableCall(token_pos(), *stub,
-                                    PcDescriptorsLayout::kOther, locs());
+    compiler->GeneratePatchableCall(source(), *stub,
+                                    UntaggedPcDescriptors::kOther, locs());
   } else {
     if (is_bootstrap_native()) {
       stub = &StubCode::CallBootstrapNative();
@@ -1039,7 +1037,7 @@
         reinterpret_cast<uword>(native_c_function()));
     __ LoadNativeEntry(RBX, &label,
                        compiler::ObjectPoolBuilderEntry::kNotPatchable);
-    compiler->GenerateStubCall(token_pos(), *stub, PcDescriptorsLayout::kOther,
+    compiler->GenerateStubCall(source(), *stub, UntaggedPcDescriptors::kOther,
                                locs());
   }
   __ popq(result);
@@ -1062,7 +1060,7 @@
   // but have a null code object.
   __ LoadObject(CODE_REG, Object::null_object());
   __ set_constant_pool_allowed(false);
-  __ EnterDartFrame(marshaller_.StackTopInBytes(), PP);
+  __ EnterDartFrame(marshaller_.RequiredStackSpaceInBytes(), PP);
 
   // Align frame before entering C++ world.
   if (OS::ActivationFrameAlignment() > 1) {
@@ -1076,8 +1074,8 @@
   // instruction, so 'AddressRIPRelative' loads the address of the following
   // 'movq'.
   __ leaq(TMP, compiler::Address::AddressRIPRelative(0));
-  compiler->EmitCallsiteMetadata(TokenPosition::kNoSource, deopt_id(),
-                                 PcDescriptorsLayout::Kind::kOther, locs());
+  compiler->EmitCallsiteMetadata(InstructionSource(), deopt_id(),
+                                 UntaggedPcDescriptors::Kind::kOther, locs());
   __ movq(compiler::Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP);
 
   if (CanExecuteGeneratedCodeInSafepoint()) {
@@ -1124,6 +1122,7 @@
   __ popq(TMP);
 }
 
+// Keep in sync with NativeReturnInstr::EmitNativeCode.
 void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ Bind(compiler->GetJumpLabel(this));
 
@@ -1131,9 +1130,7 @@
   // NativeReturnInstr::EmitNativeCode.
   __ EnterFrame(0);
 
-#if defined(TARGET_OS_FUCHSIA)
-  UNREACHABLE();  // Fuchsia does not allow dart:ffi.
-#elif defined(USING_SHADOW_CALL_STACK)
+#if defined(TARGET_OS_FUCHSIA) && defined(USING_SHADOW_CALL_STACK)
 #error Unimplemented
 #endif
 
@@ -1321,9 +1318,8 @@
   const Array& kNoArgumentNames = Object::null_array();
   ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
                           kNoArgumentNames);
-  compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(),
-                               args_info, locs(), ICData::Handle(),
-                               ICData::kStatic);
+  compiler->GenerateStaticCall(deopt_id(), source(), CallFunction(), args_info,
+                               locs(), ICData::Handle(), ICData::kStatic);
   ASSERT(locs()->out(0).reg() == RAX);
 }
 
@@ -1522,8 +1518,8 @@
     locs->live_registers()->Remove(Location::RegisterLocation(result_));
 
     compiler->SaveLiveRegisters(locs);
-    compiler->GenerateStubCall(TokenPosition::kNoSource,  // No token position.
-                               stub, PcDescriptorsLayout::kOther, locs);
+    compiler->GenerateStubCall(InstructionSource(),  // No token position.
+                               stub, UntaggedPcDescriptors::kOther, locs);
     __ MoveRegister(result_, RAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -2048,9 +2044,9 @@
 }
 
 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t field_cid = field().guarded_cid();
@@ -2408,9 +2404,9 @@
 }
 
 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   compiler::Label skip_store;
 
@@ -2648,7 +2644,7 @@
   ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
   ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
 
-  compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
+  compiler->GenerateInstanceOf(source(), deopt_id(), type(), locs());
   ASSERT(locs()->out(0).reg() == RAX);
 }
 
@@ -2698,9 +2694,9 @@
   // RDI: iterator which initially points to the start of the variable
   // data area to be initialized.
   if (num_elements > 0) {
-    const intptr_t array_size = instance_size - sizeof(ArrayLayout);
+    const intptr_t array_size = instance_size - sizeof(UntaggedArray);
     __ LoadObject(R12, Object::null_object());
-    __ leaq(RDI, compiler::FieldAddress(RAX, sizeof(ArrayLayout)));
+    __ leaq(RDI, compiler::FieldAddress(RAX, sizeof(UntaggedArray)));
     if (array_size < (kInlineArraySize * kWordSize)) {
       intptr_t current_offset = 0;
       while (current_offset < array_size) {
@@ -2723,8 +2719,8 @@
 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   TypeUsageInfo* type_usage_info = compiler->thread()->type_usage_info();
   if (type_usage_info != nullptr) {
-    const Class& list_class = Class::Handle(
-        compiler->thread()->isolate()->class_table()->At(kArrayCid));
+    const Class& list_class =
+        Class::Handle(compiler->isolate_group()->class_table()->At(kArrayCid));
     RegisterTypeArgumentsUse(compiler->function(), type_usage_info, list_class,
                              element_type()->definition());
   }
@@ -2747,11 +2743,11 @@
   }
 
   __ Bind(&slow_path);
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& allocate_array_stub =
       Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
-  compiler->GenerateStubCall(token_pos(), allocate_array_stub,
-                             PcDescriptorsLayout::kOther, locs(), deopt_id());
+  compiler->GenerateStubCall(source(), allocate_array_stub,
+                             UntaggedPcDescriptors::kOther, locs(), deopt_id());
   __ Bind(&done);
   ASSERT(locs()->out(0).reg() == kResultReg);
 }
@@ -2830,9 +2826,9 @@
 }
 
 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(compiler::target::ObjectLayout::kClassIdTagSize == 16);
-  ASSERT(sizeof(FieldLayout::guarded_cid_) == 2);
-  ASSERT(sizeof(FieldLayout::is_nullable_) == 2);
+  ASSERT(compiler::target::UntaggedObject::kClassIdTagSize == 16);
+  ASSERT(sizeof(UntaggedField::guarded_cid_) == 2);
+  ASSERT(sizeof(UntaggedField::is_nullable_) == 2);
 
   const Register instance_reg = locs()->in(0).reg();
   if (slot().representation() != kTagged) {
@@ -3018,7 +3014,7 @@
   __ PushObject(type());
   __ pushq(instantiator_type_args_reg);  // Push instantiator type arguments.
   __ pushq(function_type_args_reg);      // Push function type arguments.
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
+  compiler->GenerateRuntimeCall(source(), deopt_id(),
                                 kInstantiateTypeRuntimeEntry, 3, locs());
   __ Drop(3);           // Drop 2 type vectors, and uninstantiated type.
   __ popq(result_reg);  // Pop instantiated type.
@@ -3084,8 +3080,8 @@
     __ Bind(&non_null_type_args);
   }
   // Lookup cache in stub before calling runtime.
-  compiler->GenerateStubCall(token_pos(), GetStub(),
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), GetStub(), UntaggedPcDescriptors::kOther,
+                             locs());
   __ Bind(&type_arguments_instantiated);
 }
 
@@ -3119,15 +3115,14 @@
 
     compiler->SaveLiveRegisters(locs);
 
-    auto object_store = compiler->isolate()->object_store();
+    auto object_store = compiler->isolate_group()->object_store();
     const auto& allocate_context_stub = Code::ZoneHandle(
         compiler->zone(), object_store->allocate_context_stub());
 
     __ LoadImmediate(
         R10, compiler::Immediate(instruction()->num_context_variables()));
-    compiler->GenerateStubCall(instruction()->token_pos(),
-                               allocate_context_stub,
-                               PcDescriptorsLayout::kOther, locs);
+    compiler->GenerateStubCall(instruction()->source(), allocate_context_stub,
+                               UntaggedPcDescriptors::kOther, locs);
     ASSERT(instruction()->locs()->out(0).reg() == RAX);
     compiler->RestoreLiveRegisters(instruction()->locs());
     __ jmp(exit_label());
@@ -3172,13 +3167,13 @@
   ASSERT(locs()->temp(0).reg() == R10);
   ASSERT(locs()->out(0).reg() == RAX);
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& allocate_context_stub =
       Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
 
   __ LoadImmediate(R10, compiler::Immediate(num_context_variables()));
-  compiler->GenerateStubCall(token_pos(), allocate_context_stub,
-                             PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), allocate_context_stub,
+                             UntaggedPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone,
@@ -3196,11 +3191,11 @@
   ASSERT(locs()->in(0).reg() == R9);
   ASSERT(locs()->out(0).reg() == RAX);
 
-  auto object_store = compiler->isolate()->object_store();
+  auto object_store = compiler->isolate_group()->object_store();
   const auto& clone_context_stub =
       Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
-  compiler->GenerateStubCall(token_pos(), clone_context_stub,
-                             /*kind=*/PcDescriptorsLayout::kOther, locs());
+  compiler->GenerateStubCall(source(), clone_context_stub,
+                             /*kind=*/UntaggedPcDescriptors::kOther, locs());
 }
 
 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone,
@@ -3221,8 +3216,8 @@
     if (compiler->is_optimizing()) {
       compiler->AddDeoptIndexAtCall(deopt_id);
     } else {
-      compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, deopt_id,
-                                     TokenPosition::kNoSource);
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, deopt_id,
+                                     InstructionSource());
     }
   }
   if (HasParallelMove()) {
@@ -3276,7 +3271,7 @@
       : TemplateSlowPathCode(instruction) {}
 
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
-    if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) {
+    if (compiler->isolate_group()->use_osr() && osr_entry_label()->IsLinked()) {
       __ Comment("CheckStackOverflowSlowPathOsr");
       __ Bind(osr_entry_label());
       __ movq(compiler::Address(THR, Thread::stack_overflow_flags_offset()),
@@ -3304,21 +3299,21 @@
       compiler->RecordSafepoint(instruction()->locs(), kNumSlowPathArgs);
       compiler->RecordCatchEntryMoves();
       compiler->AddDescriptor(
-          PcDescriptorsLayout::kOther, compiler->assembler()->CodeSize(),
-          instruction()->deopt_id(), instruction()->token_pos(),
+          UntaggedPcDescriptors::kOther, compiler->assembler()->CodeSize(),
+          instruction()->deopt_id(), instruction()->source(),
           compiler->CurrentTryIndex());
     } else {
       compiler->GenerateRuntimeCall(
-          instruction()->token_pos(), instruction()->deopt_id(),
+          instruction()->source(), instruction()->deopt_id(),
           kStackOverflowRuntimeEntry, kNumSlowPathArgs, instruction()->locs());
     }
 
-    if (compiler->isolate()->use_osr() && !compiler->is_optimizing() &&
+    if (compiler->isolate_group()->use_osr() && !compiler->is_optimizing() &&
         instruction()->in_loop()) {
       // In unoptimized code, record loop stack checks as possible OSR entries.
-      compiler->AddCurrentDescriptor(PcDescriptorsLayout::kOsrEntry,
+      compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOsrEntry,
                                      instruction()->deopt_id(),
-                                     TokenPosition::kNoSource);
+                                     InstructionSource());
     }
     compiler->pending_deoptimization_env_ = NULL;
     if (!using_shared_stub) {
@@ -3328,7 +3323,7 @@
   }
 
   compiler::Label* osr_entry_label() {
-    ASSERT(Isolate::Current()->use_osr());
+    ASSERT(IsolateGroup::Current()->use_osr());
     return &osr_entry_label_;
   }
 
@@ -3509,7 +3504,7 @@
             /*type_args_len=*/0, /*num_arguments=*/2));
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->source(), locs, try_index_, kNumSlowPathArgs);
     __ MoveRegister(result, RAX);
     compiler->RestoreLiveRegisters(locs);
     __ jmp(exit_label());
@@ -3684,7 +3679,7 @@
 
     compiler->EmitMegamorphicInstanceCall(
         selector, arguments_descriptor, instruction()->call()->deopt_id(),
-        instruction()->token_pos(), locs, try_index_, kNumSlowPathArgs);
+        instruction()->source(), locs, try_index_, kNumSlowPathArgs);
     __ MoveRegister(result, RAX);
     compiler->RestoreLiveRegisters(locs);
     compiler->pending_deoptimization_env_ = nullptr;
@@ -3793,7 +3788,7 @@
 
 static bool CanBeImmediate(const Object& constant) {
   return constant.IsSmi() &&
-         compiler::Immediate(static_cast<int64_t>(constant.raw())).is_int32();
+         compiler::Immediate(static_cast<int64_t>(constant.ptr())).is_int32();
 }
 
 static bool IsSmiValue(const Object& constant, intptr_t value) {
@@ -3902,7 +3897,7 @@
   if (locs()->in(1).IsConstant()) {
     const Object& constant = locs()->in(1).constant();
     ASSERT(constant.IsSmi());
-    const int64_t imm = static_cast<int64_t>(constant.raw());
+    const int64_t imm = static_cast<int64_t>(constant.ptr());
     switch (op_kind()) {
       case Token::kADD: {
         __ AddImmediate(left, compiler::Immediate(imm));
@@ -4509,13 +4504,13 @@
   // Shared slow path is used in BoxInt64Instr::EmitNativeCode in
   // FLAG_use_bare_instructions mode and only after VM isolate stubs where
   // replaced with isolate-specific stubs.
-  auto object_store = Isolate::Current()->object_store();
+  auto object_store = IsolateGroup::Current()->object_store();
   const bool stubs_in_vm_isolate =
       object_store->allocate_mint_with_fpu_regs_stub()
-          ->ptr()
+          ->untag()
           ->InVMIsolateHeap() ||
       object_store->allocate_mint_without_fpu_regs_stub()
-          ->ptr()
+          ->untag()
           ->InVMIsolateHeap();
   const bool shared_slow_path_call = SlowPathSharingSupported(opt) &&
                                      FLAG_use_bare_instructions &&
@@ -4559,7 +4554,7 @@
                    compiler->intrinsic_slow_path_label(),
                    compiler::Assembler::kNearJump, out, temp);
   } else if (locs()->call_on_shared_slow_path()) {
-    auto object_store = compiler->isolate()->object_store();
+    auto object_store = compiler->isolate_group()->object_store();
     const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
     const auto& stub = Code::ZoneHandle(
         compiler->zone(),
@@ -4569,7 +4564,7 @@
     ASSERT(!locs()->live_registers()->ContainsRegister(
         AllocateMintABI::kResultReg));
     auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
-    compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+    compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
                                locs(), DeoptId::kNone, extended_env);
   } else {
     BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
@@ -5340,7 +5335,7 @@
   const Array& kNoArgumentNames = Object::null_array();
   ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kSizeOfArguments,
                           kNoArgumentNames);
-  compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target,
+  compiler->GenerateStaticCall(deopt_id(), instance_call()->source(), target,
                                args_info, locs(), ICData::Handle(),
                                ICData::kStatic);
   __ Bind(&done);
@@ -5965,7 +5960,7 @@
     Register length = length_loc.reg();
     const Smi& index = Smi::Cast(index_loc.constant());
     __ CompareImmediate(length,
-                        compiler::Immediate(static_cast<int64_t>(index.raw())));
+                        compiler::Immediate(static_cast<int64_t>(index.ptr())));
     __ j(BELOW_EQUAL, deopt);
   } else if (length_loc.IsConstant()) {
     const Smi& length = Smi::Cast(length_loc.constant());
@@ -5978,7 +5973,7 @@
       __ j(NEGATIVE, deopt);
     } else {
       __ CompareImmediate(
-          index, compiler::Immediate(static_cast<int64_t>(length.raw())));
+          index, compiler::Immediate(static_cast<int64_t>(length.ptr())));
       __ j(ABOVE_EQUAL, deopt);
     }
   } else {
@@ -6853,8 +6848,8 @@
     }
     // Add a deoptimization descriptor for deoptimizing instructions that
     // may be inserted before this instruction.
-    compiler->AddCurrentDescriptor(PcDescriptorsLayout::kDeopt, GetDeoptId(),
-                                   TokenPosition::kNoSource);
+    compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kDeopt, GetDeoptId(),
+                                   InstructionSource());
   }
   if (HasParallelMove()) {
     compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
@@ -6935,7 +6930,7 @@
     Register reg,
     const Object& obj) {
   return compiler->EmitEqualityRegConstCompare(reg, obj, needs_number_check(),
-                                               token_pos(), deopt_id());
+                                               source(), deopt_id());
 }
 
 LocationSummary* DispatchTableCallInstr::MakeLocationSummary(Zone* zone,
@@ -6983,8 +6978,8 @@
     __ xorq(RBX, RBX);
   }
   __ call(RCX);
-  compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
-                                 PcDescriptorsLayout::kOther, locs());
+  compiler->EmitCallsiteMetadata(source(), deopt_id(),
+                                 UntaggedPcDescriptors::kOther, locs());
   __ Drop(argument_count);
 }
 
@@ -7040,7 +7035,7 @@
   }
   const Code& stub = Code::ZoneHandle(
       compiler->zone(), StubCode::GetAllocationStubForClass(cls()));
-  compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+  compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
                              locs());
 }
 
@@ -7050,7 +7045,7 @@
 #else
   ASSERT(!compiler->is_optimizing());
   __ CallPatchable(StubCode::DebugStepCheck());
-  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
+  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, source());
   compiler->RecordSafepoint(locs());
 #endif
 }
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 7b04675..ce2f680 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -111,7 +111,7 @@
 static bool IsCallRecursive(const Function& function, Definition* call) {
   Environment* env = call->env();
   while (env != NULL) {
-    if (function.raw() == env->function().raw()) {
+    if (function.ptr() == env->function().ptr()) {
       return true;
     }
     env = env->outer();
@@ -421,11 +421,11 @@
         if (current->IsPolymorphicInstanceCall()) {
           PolymorphicInstanceCallInstr* instance_call =
               current->AsPolymorphicInstanceCall();
-          target = instance_call->targets().FirstTarget().raw();
+          target = instance_call->targets().FirstTarget().ptr();
           call = instance_call;
         } else if (current->IsStaticCall()) {
           StaticCallInstr* static_call = current->AsStaticCall();
-          target = static_call->function().raw();
+          target = static_call->function().ptr();
           call = static_call;
         } else if (current->IsClosureCall()) {
           // TODO(srdjan): Add data for closure calls.
@@ -569,8 +569,7 @@
                   const Array& arguments_descriptor,
                   intptr_t first_arg_index,  // 1 if type args are passed.
                   GrowableArray<Value*>* arguments,
-                  const Function& caller,
-                  intptr_t caller_inlining_id)
+                  const Function& caller)
       : call(call),
         arguments_descriptor(arguments_descriptor),
         first_arg_index(first_arg_index),
@@ -578,8 +577,7 @@
         callee_graph(NULL),
         parameter_stubs(NULL),
         exit_collector(NULL),
-        caller(caller),
-        caller_inlining_id(caller_inlining_id) {}
+        caller(caller) {}
 
   Definition* call;
   const Array& arguments_descriptor;
@@ -589,7 +587,6 @@
   ZoneGrowableArray<Definition*>* parameter_stubs;
   InlineExitCollector* exit_collector;
   const Function& caller;
-  const intptr_t caller_inlining_id;
 };
 
 class CallSiteInliner;
@@ -598,8 +595,7 @@
  public:
   PolymorphicInliner(CallSiteInliner* owner,
                      PolymorphicInstanceCallInstr* call,
-                     const Function& caller_function,
-                     intptr_t caller_inlining_id);
+                     const Function& caller_function);
 
   bool Inline();
 
@@ -630,7 +626,6 @@
   InlineExitCollector* exit_collector_;
 
   const Function& caller_function_;
-  const intptr_t caller_inlining_id_;
 };
 
 static void ReplaceParameterStubs(Zone* zone,
@@ -713,7 +708,7 @@
           ASSERT(call_data->call->IsClosureCall());
           LoadFieldInstr* context_load = new (zone) LoadFieldInstr(
               new Value((*arguments)[first_arg_index]->definition()),
-              Slot::Closure_context(), call_data->call->token_pos());
+              Slot::Closure_context(), call_data->call->source());
           context_load->set_ssa_temp_index(
               caller_graph->alloc_ssa_temp_index());
           if (FlowGraph::NeedsPairLocation(context_load->representation())) {
@@ -1052,7 +1047,12 @@
         {
           callee_graph = builder.BuildGraph();
 #if defined(DEBUG)
-          FlowGraphChecker(callee_graph).Check("Builder (callee)");
+          // The inlining IDs of instructions in the callee graph are unset
+          // until we call SetInliningID later.
+          GrowableArray<const Function*> callee_inline_id_to_function;
+          callee_inline_id_to_function.Add(&function);
+          FlowGraphChecker(callee_graph, callee_inline_id_to_function)
+              .Check("Builder (callee)");
 #endif
           CalleeGraphValidator::Validate(callee_graph);
         }
@@ -1135,7 +1135,12 @@
           callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(),
                                    param_stubs);
 #if defined(DEBUG)
-          FlowGraphChecker(callee_graph).Check("SSA (callee)");
+          // The inlining IDs of instructions in the callee graph are unset
+          // until we call SetInliningID later.
+          GrowableArray<const Function*> callee_inline_id_to_function;
+          callee_inline_id_to_function.Add(&function);
+          FlowGraphChecker(callee_graph, callee_inline_id_to_function)
+              .Check("SSA (callee)");
 #endif
         }
 
@@ -1263,10 +1268,8 @@
         }
 
         FlowGraphInliner::SetInliningId(
-            callee_graph,
-            inliner_->NextInlineId(callee_graph->function(),
-                                   call_data->call->token_pos(),
-                                   call_data->caller_inlining_id));
+            callee_graph, inliner_->NextInlineId(callee_graph->function(),
+                                                 call_data->call->source()));
         TRACE_INLINING(THR_Print("     Success\n"));
         TRACE_INLINING(THR_Print(
             "       with reason %s, code size %" Pd ", call sites: %" Pd "\n",
@@ -1278,7 +1281,7 @@
 
         if (error.IsLanguageError() &&
             (LanguageError::Cast(error).kind() == Report::kBailout)) {
-          if (error.raw() == Object::background_compilation_error().raw()) {
+          if (error.ptr() == Object::background_compilation_error().ptr()) {
             // Fall through to exit the compilation, and retry it later.
           } else {
             TRACE_INLINING(
@@ -1335,7 +1338,7 @@
         continue;
       }
       if ((info.inlined_depth == depth) &&
-          (info.caller->raw() == caller.raw()) &&
+          (info.caller->ptr() == caller.ptr()) &&
           !Contains(call_instructions_printed, info.call_instr->GetDeoptId())) {
         for (int t = 0; t < depth; t++) {
           THR_Print("  ");
@@ -1354,7 +1357,7 @@
         continue;
       }
       if ((info.inlined_depth == depth) &&
-          (info.caller->raw() == caller.raw()) &&
+          (info.caller->ptr() == caller.ptr()) &&
           !Contains(call_instructions_printed, info.call_instr->GetDeoptId())) {
         for (int t = 0; t < depth; t++) {
           THR_Print("  ");
@@ -1393,7 +1396,7 @@
     // TODO(zerny): Use a hash map for the cache.
     for (intptr_t i = 0; i < function_cache_.length(); ++i) {
       ParsedFunction* parsed_function = function_cache_[i];
-      if (parsed_function->function().raw() == function.raw()) {
+      if (parsed_function->function().ptr() == function.ptr()) {
         *in_cache = true;
         return parsed_function;
       }
@@ -1439,8 +1442,7 @@
       }
       InlinedCallData call_data(
           call, Array::ZoneHandle(Z, call->GetArgumentsDescriptor()),
-          call->FirstArgIndex(), &arguments, call_info[call_idx].caller(),
-          call_info[call_idx].caller_graph->inlining_id());
+          call->FirstArgIndex(), &arguments, call_info[call_idx].caller());
 
       // Under AOT, calls outside loops may pass our regular heuristics due
       // to a relatively high ratio. So, unless we are optimizing solely for
@@ -1478,7 +1480,7 @@
           call->Receiver()->definition()->OriginalDefinition();
       if (AllocateObjectInstr* alloc = receiver->AsAllocateObject()) {
         if (!alloc->closure_function().IsNull()) {
-          target = alloc->closure_function().raw();
+          target = alloc->closure_function().ptr();
           ASSERT(alloc->cls().IsClosureClass());
         }
       } else if (ConstantInstr* constant = receiver->AsConstant()) {
@@ -1504,10 +1506,9 @@
       }
       const Array& arguments_descriptor =
           Array::ZoneHandle(Z, call->GetArgumentsDescriptor());
-      InlinedCallData call_data(
-          call, arguments_descriptor, call->FirstArgIndex(), &arguments,
-          call_info[call_idx].caller(),
-          call_info[call_idx].caller_graph->inlining_id());
+      InlinedCallData call_data(call, arguments_descriptor,
+                                call->FirstArgIndex(), &arguments,
+                                call_info[call_idx].caller());
       if (TryInlining(target, call->argument_names(), &call_data, false)) {
         InlineCall(&call_data);
         inlined = true;
@@ -1531,9 +1532,7 @@
         continue;
       }
       const Function& cl = call_info[call_idx].caller();
-      intptr_t caller_inlining_id =
-          call_info[call_idx].caller_graph->inlining_id();
-      PolymorphicInliner inliner(this, call, cl, caller_inlining_id);
+      PolymorphicInliner inliner(this, call, cl);
       if (inliner.Inline()) inlined = true;
     }
     return inlined;
@@ -1653,8 +1652,7 @@
 
 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner,
                                        PolymorphicInstanceCallInstr* call,
-                                       const Function& caller_function,
-                                       intptr_t caller_inlining_id)
+                                       const Function& caller_function)
     : owner_(owner),
       call_(call),
       num_variants_(call->NumberOfChecks()),
@@ -1663,8 +1661,7 @@
       non_inlined_variants_(new (zone()) CallTargets(zone())),
       inlined_entries_(num_variants_),
       exit_collector_(new (Z) InlineExitCollector(owner->caller_graph(), call)),
-      caller_function_(caller_function),
-      caller_inlining_id_(caller_inlining_id) {}
+      caller_function_(caller_function) {}
 
 Isolate* PolymorphicInliner::isolate() const {
   return owner_->caller_graph()->isolate();
@@ -1689,7 +1686,7 @@
 //   * JoinEntry: the inlined body is shared and this is a subsequent variant.
 bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) {
   for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
-    if ((target.raw() == inlined_variants_.TargetAt(i)->target->raw()) &&
+    if ((target.ptr() == inlined_variants_.TargetAt(i)->target->ptr()) &&
         !target.is_polymorphic_target()) {
       // The call target is shared with a previous inlined variant.  Share
       // the graph.  This requires a join block at the entry, and edge-split
@@ -1746,7 +1743,7 @@
 
 bool PolymorphicInliner::CheckNonInlinedDuplicate(const Function& target) {
   for (intptr_t i = 0; i < non_inlined_variants_->length(); ++i) {
-    if (target.raw() == non_inlined_variants_->TargetAt(i)->target->raw()) {
+    if (target.ptr() == non_inlined_variants_->TargetAt(i)->target->ptr()) {
       return true;
     }
   }
@@ -1770,8 +1767,8 @@
   const Array& arguments_descriptor =
       Array::ZoneHandle(Z, call_->GetArgumentsDescriptor());
   InlinedCallData call_data(call_, arguments_descriptor, call_->FirstArgIndex(),
-                            &arguments, caller_function_, caller_inlining_id_);
-  Function& target = Function::ZoneHandle(zone(), target_info.target->raw());
+                            &arguments, caller_function_);
+  Function& target = Function::ZoneHandle(zone(), target_info.target->ptr());
   if (!owner_->TryInlining(target, call_->argument_names(), &call_data,
                            false)) {
     return false;
@@ -1818,7 +1815,7 @@
   }
   if (FlowGraphInliner::TryInlineRecognizedMethod(
           owner_->caller_graph(), receiver_cid, target, call_, redefinition,
-          call_->token_pos(), call_->ic_data(), graph_entry, &entry, &last,
+          call_->source(), call_->ic_data(), graph_entry, &entry, &last,
           &result, owner_->inliner_->speculative_policy())) {
     // The empty Object constructor is the only case where the inlined body is
     // empty and there is no result.
@@ -1830,7 +1827,7 @@
     InlineExitCollector* exit_collector =
         new (Z) InlineExitCollector(owner_->caller_graph(), call_);
     ReturnInstr* return_result = new (Z)
-        ReturnInstr(call_->token_pos(), new (Z) Value(result), DeoptId::kNone);
+        ReturnInstr(call_->source(), new (Z) Value(result), DeoptId::kNone);
     owner_->caller_graph()->AppendTo(
         last, return_result,
         call_->env(),  // Return can become deoptimization target.
@@ -1952,7 +1949,7 @@
         ConstantInstr* cid_constant_end =
             owner_->caller_graph()->GetConstant(cid_end);
         RelationalOpInstr* compare_top = new RelationalOpInstr(
-            call_->token_pos(), Token::kLTE, new Value(load_cid),
+            call_->source(), Token::kLTE, new Value(load_cid),
             new Value(cid_constant_end), kSmiCid, call_->deopt_id());
         BranchInstr* branch_top = upper_limit_branch =
             new BranchInstr(compare_top, DeoptId::kNone);
@@ -1969,12 +1966,12 @@
         *branch_top->true_successor_address() = below_target;
 
         RelationalOpInstr* compare_bottom = new RelationalOpInstr(
-            call_->token_pos(), Token::kGTE, new Value(load_cid),
+            call_->source(), Token::kGTE, new Value(load_cid),
             new Value(cid_constant), kSmiCid, call_->deopt_id());
         branch = new BranchInstr(compare_bottom, DeoptId::kNone);
       } else {
         StrictCompareInstr* compare =
-            new StrictCompareInstr(call_->token_pos(), Token::kEQ_STRICT,
+            new StrictCompareInstr(call_->source(), Token::kEQ_STRICT,
                                    new Value(load_cid), new Value(cid_constant),
                                    /* number_check = */ false, DeoptId::kNone);
         branch = new BranchInstr(compare, DeoptId::kNone);
@@ -2083,7 +2080,7 @@
     fallback_call->InheritDeoptTarget(zone(), call_);
     fallback_call->set_total_call_count(call_->CallCount());
     ReturnInstr* fallback_return = new ReturnInstr(
-        call_->token_pos(), new Value(fallback_call), DeoptId::kNone);
+        call_->source(), new Value(fallback_call), DeoptId::kNone);
     fallback_return->InheritDeoptTargetAfter(owner_->caller_graph(), call_,
                                              fallback_call);
     AppendInstruction(AppendInstruction(cursor, fallback_call),
@@ -2240,20 +2237,18 @@
   *call_site_count = function.optimized_call_site_count();
 }
 
-// TODO(srdjan): This is only needed when disassembling and/or profiling.
-// Sets inlining id for all instructions of this flow-graph, as well for the
-// FlowGraph itself.
 void FlowGraphInliner::SetInliningId(FlowGraph* flow_graph,
                                      intptr_t inlining_id) {
   ASSERT(flow_graph->inlining_id() < 0);
   flow_graph->set_inlining_id(inlining_id);
+  // We only need to set the inlining ID on instructions that may possibly
+  // have token positions, so no need to set it on blocks or internal
+  // definitions.
   for (BlockIterator block_it = flow_graph->postorder_iterator();
        !block_it.Done(); block_it.Advance()) {
     for (ForwardInstructionIterator it(block_it.Current()); !it.Done();
          it.Advance()) {
       Instruction* current = it.Current();
-      // Do not overwrite owner function.
-      ASSERT(!current->has_inlining_id());
       current->set_inlining_id(inlining_id);
     }
   }
@@ -2262,10 +2257,10 @@
 // Use function name to determine if inlineable operator.
 // Add names as necessary.
 static bool IsInlineableOperator(const Function& function) {
-  return (function.name() == Symbols::IndexToken().raw()) ||
-         (function.name() == Symbols::AssignIndexToken().raw()) ||
-         (function.name() == Symbols::Plus().raw()) ||
-         (function.name() == Symbols::Minus().raw());
+  return (function.name() == Symbols::IndexToken().ptr()) ||
+         (function.name() == Symbols::AssignIndexToken().ptr()) ||
+         (function.name() == Symbols::Plus().ptr()) ||
+         (function.name() == Symbols::Minus().ptr());
 }
 
 bool FlowGraphInliner::FunctionHasPreferInlinePragma(const Function& function) {
@@ -2291,7 +2286,7 @@
   // replace them with inline FG before inlining introduces any superfluous
   // AssertAssignable instructions.
   if (function.IsDispatcherOrImplicitAccessor() &&
-      !(function.kind() == FunctionLayout::kDynamicInvocationForwarder &&
+      !(function.kind() == UntaggedFunction::kDynamicInvocationForwarder &&
         function.IsRecognized())) {
     // Smaller or same size as the call.
     return true;
@@ -2304,7 +2299,7 @@
 
   if (function.IsGetterFunction() || function.IsSetterFunction() ||
       IsInlineableOperator(function) ||
-      (function.kind() == FunctionLayout::kConstructor)) {
+      (function.kind() == UntaggedFunction::kConstructor)) {
     const intptr_t count = function.optimized_instruction_count();
     if ((count != 0) && (count < FLAG_inline_getters_setters_smaller_than)) {
       return true;
@@ -2368,16 +2363,17 @@
 }
 
 intptr_t FlowGraphInliner::NextInlineId(const Function& function,
-                                        TokenPosition tp,
-                                        intptr_t parent_id) {
+                                        const InstructionSource& source) {
   const intptr_t id = inline_id_to_function_->length();
   // TODO(johnmccutchan): Do not allow IsNoSource once all nodes have proper
   // source positions.
-  ASSERT(tp.IsReal() || tp.IsSynthetic() || tp.IsNoSource());
+  ASSERT(source.token_pos.IsReal() || source.token_pos.IsSynthetic() ||
+         source.token_pos.IsNoSource());
   RELEASE_ASSERT(!function.IsNull());
+  ASSERT(FunctionType::Handle(function.signature()).IsFinalized());
   inline_id_to_function_->Add(&function);
-  inline_id_to_token_pos_->Add(tp);
-  caller_inline_id_->Add(parent_id);
+  inline_id_to_token_pos_->Add(source.token_pos);
+  caller_inline_id_->Add(source.inlining_id);
   // We always have one less token position than functions.
   ASSERT(inline_id_to_token_pos_->length() ==
          (inline_id_to_function_->length() - 1));
@@ -2416,7 +2412,7 @@
   // Insert array length load and bounds check.
   LoadFieldInstr* length = new (Z) LoadFieldInstr(
       new (Z) Value(*array), Slot::GetLengthFieldForArrayCid(array_cid),
-      call->token_pos());
+      call->source());
   *cursor = flow_graph->AppendTo(*cursor, length, NULL, FlowGraph::kValue);
   *index = flow_graph->CreateCheckBound(length, *index, call->deopt_id());
   *cursor =
@@ -2426,7 +2422,7 @@
     // Insert data elements load.
     LoadFieldInstr* elements = new (Z)
         LoadFieldInstr(new (Z) Value(*array), Slot::GrowableObjectArray_data(),
-                       call->token_pos());
+                       call->source());
     *cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
     // Load from the data from backing store which is a fixed-length array.
     *array = elements;
@@ -2481,7 +2477,7 @@
   intptr_t index_scale = compiler::target::Instance::ElementSizeFor(array_cid);
   LoadIndexedInstr* load = new (Z) LoadIndexedInstr(
       new (Z) Value(array), new (Z) Value(index), /*index_unboxed=*/false,
-      index_scale, array_cid, kAlignedAccess, deopt_id, call->token_pos(),
+      index_scale, array_cid, kAlignedAccess, deopt_id, call->source(),
       ResultType(call));
 
   *last = load;
@@ -2516,7 +2512,7 @@
                              const Function& target,
                              Instruction* call,
                              Definition* receiver,
-                             TokenPosition token_pos,
+                             const InstructionSource& source,
                              const Cids* value_check,
                              FlowGraphInliner::ExactnessInfo* exactness,
                              GraphEntryInstr* graph_entry,
@@ -2565,7 +2561,7 @@
             LoadFieldInstr(new (Z) Value(array),
                            Slot::GetTypeArgumentsSlotFor(flow_graph->thread(),
                                                          instantiator_class),
-                           call->token_pos());
+                           call->source());
         cursor = flow_graph->AppendTo(cursor, load_type_args, NULL,
                                       FlowGraph::kValue);
         type_args = load_type_args;
@@ -2627,7 +2623,7 @@
       auto const function_type_args = flow_graph->constant_null();
       auto const dst_type = flow_graph->GetConstant(value_type);
       AssertAssignableInstr* assert_value = new (Z) AssertAssignableInstr(
-          token_pos, new (Z) Value(stored_value), new (Z) Value(dst_type),
+          source, new (Z) Value(stored_value), new (Z) Value(dst_type),
           new (Z) Value(type_args), new (Z) Value(function_type_args),
           Symbols::Value(), call->deopt_id());
       cursor = flow_graph->AppendTo(cursor, assert_value, call->env(),
@@ -2661,7 +2657,7 @@
     // an unboxed double, an unboxed Float32x4, or unboxed Int32x4.
     needs_store_barrier = kNoStoreBarrier;
     Instruction* check = flow_graph->CreateCheckClass(
-        stored_value, *value_check, call->deopt_id(), call->token_pos());
+        stored_value, *value_check, call->deopt_id(), call->source());
     cursor =
         flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect);
   }
@@ -2704,7 +2700,7 @@
   *last = new (Z) StoreIndexedInstr(
       new (Z) Value(array), new (Z) Value(index), new (Z) Value(stored_value),
       needs_store_barrier, /*index_unboxed=*/false, index_scale, array_cid,
-      kAlignedAccess, call->deopt_id(), call->token_pos());
+      kAlignedAccess, call->deopt_id(), call->source());
   flow_graph->AppendTo(cursor, *last, call->env(), FlowGraph::kEffect);
   // We need a return value to replace uses of the original definition. However,
   // the final instruction is a use of 'void operator[]=()', so we use null.
@@ -2733,7 +2729,7 @@
   // Arguments are checked. No need for class check.
   BinaryDoubleOpInstr* double_bin_op = new (Z)
       BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right),
-                          call->deopt_id(), call->token_pos());
+                          call->deopt_id(), call->source());
   flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
   *last = double_bin_op;
   *result = double_bin_op->AsDefinition();
@@ -2760,7 +2756,7 @@
   // Arguments are checked. No need for class check.
 
   DoubleTestOpInstr* double_test_op = new (Z) DoubleTestOpInstr(
-      kind, new (Z) Value(receiver), call->deopt_id(), call->token_pos());
+      kind, new (Z) Value(receiver), call->deopt_id(), call->source());
   flow_graph->AppendTo(*entry, double_test_op, call->env(), FlowGraph::kValue);
   *last = double_test_op;
   *result = double_test_op->AsDefinition();
@@ -2813,7 +2809,7 @@
   // This is an internal method, no need to check argument types.
   StoreInstanceFieldInstr* store = new (Z)
       StoreInstanceFieldInstr(field, new (Z) Value(array), new (Z) Value(value),
-                              store_barrier_type, call->token_pos());
+                              store_barrier_type, call->source());
   flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect);
   *last = store;
   // We need a return value to replace uses of the original definition. However,
@@ -2907,7 +2903,7 @@
   LoadIndexedInstr* load = new (Z) LoadIndexedInstr(
       new (Z) Value(array), new (Z) Value(index),
       /*index_unboxed=*/false, /*index_scale=*/1, view_cid, kUnalignedAccess,
-      DeoptId::kNone, call->token_pos(), ResultType(call));
+      DeoptId::kNone, call->source(), ResultType(call));
   flow_graph->AppendTo(
       cursor, load, call->deopt_id() != DeoptId::kNone ? call->env() : nullptr,
       FlowGraph::kValue);
@@ -2932,7 +2928,7 @@
       new (Z) Value(array), new (Z) Value(index), new (Z) Value(stored_value),
       kNoStoreBarrier, /*index_unboxed=*/false,
       /*index_scale=*/1, view_cid, kUnalignedAccess, call->deopt_id(),
-      call->token_pos());
+      call->source());
 }
 
 static bool InlineByteArrayBaseStore(FlowGraph* flow_graph,
@@ -3034,7 +3030,7 @@
   // Handle value check.
   if (value_check != nullptr) {
     Instruction* check = flow_graph->CreateCheckClass(
-        stored_value, *value_check, call->deopt_id(), call->token_pos());
+        stored_value, *value_check, call->deopt_id(), call->source());
     cursor =
         flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect);
   }
@@ -3043,7 +3039,7 @@
   if (needs_null_check) {
     String& name = String::ZoneHandle(Z, target.name());
     Instruction* check = new (Z) CheckNullInstr(
-        new (Z) Value(stored_value), name, call->deopt_id(), call->token_pos());
+        new (Z) Value(stored_value), name, call->deopt_id(), call->source());
     cursor =
         flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect);
     // With an explicit null check, a non-speculative unbox suffices.
@@ -3143,9 +3139,8 @@
                                               Definition* str,
                                               Definition* index,
                                               Instruction* cursor) {
-  LoadFieldInstr* length = new (Z)
-      LoadFieldInstr(new (Z) Value(str), Slot::GetLengthFieldForArrayCid(cid),
-                     str->token_pos());
+  LoadFieldInstr* length = new (Z) LoadFieldInstr(
+      new (Z) Value(str), Slot::GetLengthFieldForArrayCid(cid), str->source());
   cursor = flow_graph->AppendTo(cursor, length, NULL, FlowGraph::kValue);
 
   // Bounds check.
@@ -3168,7 +3163,7 @@
   LoadIndexedInstr* load_indexed = new (Z) LoadIndexedInstr(
       new (Z) Value(str), new (Z) Value(index), /*index_unboxed=*/false,
       compiler::target::Instance::ElementSizeFor(cid), cid, kAlignedAccess,
-      DeoptId::kNone, call->token_pos());
+      DeoptId::kNone, call->source());
   cursor = flow_graph->AppendTo(cursor, load_indexed, NULL, FlowGraph::kValue);
 
   auto box = BoxInstr::Create(kUnboxedIntPtr, new Value(load_indexed));
@@ -3257,7 +3252,7 @@
   Definition* result = nullptr;
   if (FlowGraphInliner::TryInlineRecognizedMethod(
           flow_graph, receiver_cid, target, call,
-          call->Receiver()->definition(), call->token_pos(), call->ic_data(),
+          call->Receiver()->definition(), call->source(), call->ic_data(),
           /*graph_entry=*/nullptr, &entry, &last, &result, policy,
           &exactness_info)) {
     // The empty Object constructor is the only case where the inlined body is
@@ -3277,7 +3272,7 @@
       case FlowGraph::ToCheck::kCheckCid: {
         Instruction* check_class = flow_graph->CreateCheckClass(
             call->Receiver()->definition(), targets, call->deopt_id(),
-            call->token_pos());
+            call->source());
         flow_graph->InsertBefore(call, check_class, call->env(),
                                  FlowGraph::kEffect);
         break;
@@ -3285,7 +3280,7 @@
       case FlowGraph::ToCheck::kCheckNull: {
         Instruction* check_null = new (Z) CheckNullInstr(
             call->Receiver()->CopyWithType(Z), call->function_name(),
-            call->deopt_id(), call->token_pos());
+            call->deopt_id(), call->source());
         flow_graph->InsertBefore(call, check_null, call->env(),
                                  FlowGraph::kEffect);
         break;
@@ -3341,7 +3336,7 @@
   }
   if (FlowGraphInliner::TryInlineRecognizedMethod(
           flow_graph, receiver_cid, call->function(), call, receiver,
-          call->token_pos(), call->ic_data(), /*graph_entry=*/nullptr, &entry,
+          call->source(), call->ic_data(), /*graph_entry=*/nullptr, &entry,
           &last, &result, policy)) {
     // The empty Object constructor is the only case where the inlined body is
     // empty and there is no result.
@@ -3498,12 +3493,11 @@
         // inserted to be non-speculative.
         CheckNullInstr* check1 =
             new (Z) CheckNullInstr(new (Z) Value(receiver), Symbols::FirstArg(),
-                                   call->deopt_id(), call->token_pos());
+                                   call->deopt_id(), call->source());
 
-        CheckNullInstr* check2 = new (Z)
-            CheckNullInstr(new (Z) Value(call->ArgumentAt(1)),
-                           Symbols::SecondArg(), call->deopt_id(),
-                           call->token_pos(), CheckNullInstr::kArgumentError);
+        CheckNullInstr* check2 = new (Z) CheckNullInstr(
+            new (Z) Value(call->ArgumentAt(1)), Symbols::SecondArg(),
+            call->deopt_id(), call->source(), CheckNullInstr::kArgumentError);
 
         (*last)->SetInputAt(0, new (Z) Value(check1));
         (*last)->SetInputAt(1, new (Z) Value(check2));
@@ -3564,7 +3558,7 @@
         args->Add(new (Z) Value(call->ArgumentAt(i)));
       }
       *last = new (Z) InvokeMathCFunctionInstr(args, call->deopt_id(), kind,
-                                               call->token_pos());
+                                               call->source());
       break;
     }
   }
@@ -3657,7 +3651,7 @@
     const Function& target,
     Definition* call,
     Definition* receiver,
-    TokenPosition token_pos,
+    const InstructionSource& source,
     const ICData* ic_data,
     GraphEntryInstr* graph_entry,
     FunctionEntryInstr** entry,
@@ -3737,9 +3731,9 @@
     case MethodRecognizer::kGrowableArraySetIndexed:
     case MethodRecognizer::kObjectArraySetIndexedUnchecked:
     case MethodRecognizer::kGrowableArraySetIndexedUnchecked:
-      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
-                              token_pos, /* value_check = */ NULL, exactness,
-                              graph_entry, entry, last, result);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver, source,
+                              /* value_check = */ NULL, exactness, graph_entry,
+                              entry, last, result);
     case MethodRecognizer::kInt8ArraySetIndexed:
     case MethodRecognizer::kUint8ArraySetIndexed:
     case MethodRecognizer::kUint8ClampedArraySetIndexed:
@@ -3753,53 +3747,53 @@
         return false;
       }
       Cids* value_check = Cids::CreateMonomorphic(Z, kSmiCid);
-      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
-                              token_pos, value_check, exactness, graph_entry,
-                              entry, last, result);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver, source,
+                              value_check, exactness, graph_entry, entry, last,
+                              result);
     }
     case MethodRecognizer::kInt32ArraySetIndexed:
     case MethodRecognizer::kUint32ArraySetIndexed: {
       // Value check not needed for Int32 and Uint32 arrays because they
       // implicitly contain unboxing instructions which check for right type.
-      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
-                              token_pos, /* value_check = */ NULL, exactness,
-                              graph_entry, entry, last, result);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver, source,
+                              /* value_check = */ NULL, exactness, graph_entry,
+                              entry, last, result);
     }
     case MethodRecognizer::kInt64ArraySetIndexed:
     case MethodRecognizer::kUint64ArraySetIndexed:
       if (!ShouldInlineInt64ArrayOps()) {
         return false;
       }
-      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
-                              token_pos, /* value_check = */ NULL, exactness,
-                              graph_entry, entry, last, result);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver, source,
+                              /* value_check = */ NULL, exactness, graph_entry,
+                              entry, last, result);
     case MethodRecognizer::kFloat32ArraySetIndexed:
     case MethodRecognizer::kFloat64ArraySetIndexed: {
       if (!CanUnboxDouble()) {
         return false;
       }
       Cids* value_check = Cids::CreateMonomorphic(Z, kDoubleCid);
-      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
-                              token_pos, value_check, exactness, graph_entry,
-                              entry, last, result);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver, source,
+                              value_check, exactness, graph_entry, entry, last,
+                              result);
     }
     case MethodRecognizer::kFloat32x4ArraySetIndexed: {
       if (!ShouldInlineSimd()) {
         return false;
       }
       Cids* value_check = Cids::CreateMonomorphic(Z, kFloat32x4Cid);
-      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
-                              token_pos, value_check, exactness, graph_entry,
-                              entry, last, result);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver, source,
+                              value_check, exactness, graph_entry, entry, last,
+                              result);
     }
     case MethodRecognizer::kFloat64x2ArraySetIndexed: {
       if (!ShouldInlineSimd()) {
         return false;
       }
       Cids* value_check = Cids::CreateMonomorphic(Z, kFloat64x2Cid);
-      return InlineSetIndexed(flow_graph, kind, target, call, receiver,
-                              token_pos, value_check, exactness, graph_entry,
-                              entry, last, result);
+      return InlineSetIndexed(flow_graph, kind, target, call, receiver, source,
+                              value_check, exactness, graph_entry, entry, last,
+                              result);
     }
     case MethodRecognizer::kByteArrayBaseGetInt8:
       return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
@@ -4092,7 +4086,7 @@
           FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
                              call->GetBlock()->try_index(), DeoptId::kNone);
       (*entry)->InheritDeoptTarget(Z, call);
-      *last = new (Z) CreateArrayInstr(call->token_pos(), type, num_elements,
+      *last = new (Z) CreateArrayInstr(call->source(), type, num_elements,
                                        call->deopt_id());
       flow_graph->AppendTo(
           *entry, *last,
@@ -4112,8 +4106,8 @@
               FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
                                  call->GetBlock()->try_index(), DeoptId::kNone);
           (*entry)->InheritDeoptTarget(Z, call);
-          *last = new (Z) CreateArrayInstr(call->token_pos(), type,
-                                           num_elements, call->deopt_id());
+          *last = new (Z) CreateArrayInstr(call->source(), type, num_elements,
+                                           call->deopt_id());
           flow_graph->AppendTo(
               *entry, *last,
               call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
@@ -4135,9 +4129,11 @@
         type = Type::Double();
       } else if (IsIntegerClassId(receiver_cid)) {
         type = Type::IntType();
+      } else if (IsTypeClassId(receiver_cid)) {
+        type = Type::DartTypeType();
       } else if (receiver_cid != kClosureCid) {
         const Class& cls = Class::Handle(
-            Z, flow_graph->isolate()->class_table()->At(receiver_cid));
+            Z, flow_graph->isolate_group()->class_table()->At(receiver_cid));
         if (!cls.IsGeneric()) {
           type = cls.DeclarationType();
         }
@@ -4191,7 +4187,7 @@
       *last = new (Z) StoreIndexedInstr(
           new (Z) Value(str), new (Z) Value(index), new (Z) Value(value),
           kNoStoreBarrier, /*index_unboxed=*/false, index_scale, cid,
-          kAlignedAccess, call->deopt_id(), call->token_pos());
+          kAlignedAccess, call->deopt_id(), call->source());
       flow_graph->AppendTo(value, *last, env, FlowGraph::kEffect);
 
       // We need a return value to replace uses of the original definition.
diff --git a/runtime/vm/compiler/backend/inliner.h b/runtime/vm/compiler/backend/inliner.h
index 10a404c..404654b 100644
--- a/runtime/vm/compiler/backend/inliner.h
+++ b/runtime/vm/compiler/backend/inliner.h
@@ -25,6 +25,7 @@
 class ICData;
 class InstanceCallInstr;
 class Instruction;
+struct InstructionSource;
 class Precompiler;
 class StaticCallInstr;
 class TargetEntryInstr;
@@ -125,8 +126,7 @@
 
   FlowGraph* flow_graph() const { return flow_graph_; }
   intptr_t NextInlineId(const Function& function,
-                        TokenPosition tp,
-                        intptr_t caller_id);
+                        const InstructionSource& source);
 
   bool trace_inlining() const { return trace_inlining_; }
 
@@ -156,7 +156,7 @@
                                         const Function& target,
                                         Definition* call,
                                         Definition* receiver,
-                                        TokenPosition token_pos,
+                                        const InstructionSource& source,
                                         const ICData* ic_data,
                                         GraphEntryInstr* graph_entry,
                                         FunctionEntryInstr** entry,
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index ecdac22..f87c06e 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -702,47 +702,12 @@
     }
   }
 
-  if (defn->IsParameter()) {
-    // Only function entries may have unboxed parameters, possibly making the
-    // parameters size different from the number of parameters on 32-bit
-    // architectures.
-    const intptr_t parameters_size = block->IsFunctionEntry()
-                                         ? flow_graph_.direct_parameters_size()
-                                         : flow_graph_.num_direct_parameters();
-    ParameterInstr* param = defn->AsParameter();
-    intptr_t slot_index =
-        param->param_offset() + (second_location_for_definition ? -1 : 0);
-    ASSERT(slot_index >= 0);
-    if (param->base_reg() == FPREG) {
-      // Slot index for the rightmost fixed parameter is -1.
-      slot_index -= parameters_size;
-    } else {
-      // Slot index for a "frameless" parameter is reversed.
-      ASSERT(param->base_reg() == SPREG);
-      ASSERT(slot_index < parameters_size);
-      slot_index = parameters_size - 1 - slot_index;
-    }
-
-    if (param->base_reg() == FPREG) {
-      slot_index =
-          compiler::target::frame_layout.FrameSlotForVariableIndex(-slot_index);
-    } else {
-      ASSERT(param->base_reg() == SPREG);
-      slot_index += compiler::target::frame_layout.last_param_from_entry_sp;
-    }
-
-    if (param->representation() == kUnboxedInt64 ||
-        param->representation() == kTagged) {
-      const auto location = Location::StackSlot(slot_index, param->base_reg());
-      range->set_assigned_location(location);
-      range->set_spill_slot(location);
-    } else {
-      ASSERT(param->representation() == kUnboxedDouble);
-      const auto location =
-          Location::DoubleStackSlot(slot_index, param->base_reg());
-      range->set_assigned_location(location);
-      range->set_spill_slot(location);
-    }
+  if (auto param = defn->AsParameter()) {
+    const auto location =
+        ComputeParameterLocation(block, param, param->base_reg(),
+                                 second_location_for_definition ? 1 : 0);
+    range->set_assigned_location(location);
+    range->set_spill_slot(location);
   } else if (defn->IsSpecialParameter()) {
     SpecialParameterInstr* param = defn->AsSpecialParameter();
     ASSERT(param->kind() == SpecialParameterInstr::kArgDescriptor);
@@ -1405,7 +1370,7 @@
     }
   }
 
-// Block all allocatable registers for calls.
+  // Block all allocatable registers for calls.
   if (locs->always_calls() && !locs->callee_safe_call()) {
     // Expected shape of live range:
     //
@@ -1442,7 +1407,8 @@
                pair->At(1).policy() == Location::kAny);
       } else {
         ASSERT(!locs->in(j).IsUnallocated() ||
-               locs->in(j).policy() == Location::kAny);
+               locs->in(j).policy() == Location::kAny ||
+               locs->in(j).policy() == Location::kRequiresStackSlot);
       }
     }
 
@@ -3011,6 +2977,164 @@
   }
 }
 
+Location FlowGraphAllocator::ComputeParameterLocation(BlockEntryInstr* block,
+                                                      ParameterInstr* param,
+                                                      Register base_reg,
+                                                      intptr_t pair_index) {
+  ASSERT(pair_index == 0 || param->HasPairRepresentation());
+
+  // Only function entries may have unboxed parameters, possibly making the
+  // parameters size different from the number of parameters on 32-bit
+  // architectures.
+  const intptr_t parameters_size = block->IsFunctionEntry()
+                                       ? flow_graph_.direct_parameters_size()
+                                       : flow_graph_.num_direct_parameters();
+  intptr_t slot_index = param->param_offset() - pair_index;
+  ASSERT(slot_index >= 0);
+  if (base_reg == FPREG) {
+    // Slot index for the rightmost fixed parameter is -1.
+    slot_index -= parameters_size;
+  } else {
+    // Slot index for a "frameless" parameter is reversed.
+    ASSERT(base_reg == SPREG);
+    ASSERT(slot_index < parameters_size);
+    slot_index = parameters_size - 1 - slot_index;
+  }
+
+  if (base_reg == FPREG) {
+    slot_index =
+        compiler::target::frame_layout.FrameSlotForVariableIndex(-slot_index);
+  } else {
+    ASSERT(base_reg == SPREG);
+    slot_index += compiler::target::frame_layout.last_param_from_entry_sp;
+  }
+
+  if (param->representation() == kUnboxedInt64 ||
+      param->representation() == kTagged) {
+    return Location::StackSlot(slot_index, base_reg);
+  } else {
+    ASSERT(param->representation() == kUnboxedDouble);
+    return Location::DoubleStackSlot(slot_index, base_reg);
+  }
+}
+
+void FlowGraphAllocator::RemoveFrameIfNotNeeded() {
+  // Intrinsic functions are naturally frameless.
+  if (intrinsic_mode_) {
+    flow_graph_.graph_entry()->MarkFrameless();
+    return;
+  }
+
+  // For now only AOT compiled code in bare instructions mode supports
+  // frameless functions. Outside of bare instructions mode we need to preserve
+  // caller PP - so all functions need a frame if they have their own pool which
+  // is hard to determine at this stage.
+  if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
+    return;
+  }
+
+  // Optional parameter handling needs special changes to become frameless.
+  // Specifically we need to rebase IL instructions which directly access frame
+  // ({Load,Store}IndexedUnsafeInstr) to use SP rather than FP.
+  // For now just always give such functions a frame.
+  if (flow_graph_.parsed_function().function().HasOptionalParameters()) {
+    return;
+  }
+
+  // If we have spills we need to create a frame.
+  if (flow_graph_.graph_entry()->spill_slot_count() > 0) {
+    return;
+  }
+
+#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM)
+  bool has_write_barrier_call = false;
+#endif
+  for (auto block : flow_graph_.reverse_postorder()) {
+    for (auto instruction : block->instructions()) {
+      if (instruction->HasLocs() && instruction->locs()->can_call()) {
+        // Function contains a call and thus needs a frame.
+        return;
+      }
+
+      // Some instructions contain write barriers inside, which can call
+      // a helper stub. This however is a leaf call and we can entirely
+      // ignore it on ia32 and x64, because return address is always on the
+      // stack. On ARM/ARM64 however return address is in LR and needs to
+      // be explicitly preserved in the frame. Write barrier instruction
+      // sequence has explicit support for emitting LR spill/restore
+      // if necessary, however for code size purposes it does not make
+      // sense to make function frameless if it contains more than 1
+      // write barrier invocation.
+#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM)
+      if (auto store_field = instruction->AsStoreInstanceField()) {
+        if (store_field->ShouldEmitStoreBarrier()) {
+          if (has_write_barrier_call) {
+            // We already have at least one write barrier call.
+            // For code size purposes it is better if we have copy of
+            // LR spill/restore.
+            return;
+          }
+          has_write_barrier_call = true;
+        }
+      }
+
+      if (auto store_indexed = instruction->AsStoreIndexed()) {
+        if (store_indexed->ShouldEmitStoreBarrier()) {
+          if (has_write_barrier_call) {
+            // We already have at least one write barrier call.
+            // For code size purposes it is better if we have copy of
+            // LR spill/restore.
+            return;
+          }
+          has_write_barrier_call = true;
+        }
+      }
+#endif
+    }
+  }
+
+  // Good to go. No need to setup a frame due to the call.
+  auto entry = flow_graph_.graph_entry();
+
+  entry->MarkFrameless();
+
+  // Fix location of parameters to use SP as their base register instead of FP.
+  auto fix_location_for = [&](BlockEntryInstr* block, ParameterInstr* param,
+                              intptr_t vreg, intptr_t pair_index) {
+    auto fp_relative =
+        ComputeParameterLocation(block, param, FPREG, pair_index);
+    auto sp_relative =
+        ComputeParameterLocation(block, param, SPREG, pair_index);
+    for (LiveRange* range = GetLiveRange(vreg); range != nullptr;
+         range = range->next_sibling()) {
+      if (range->assigned_location().Equals(fp_relative)) {
+        range->set_assigned_location(sp_relative);
+        range->set_spill_slot(sp_relative);
+        for (UsePosition* use = range->first_use(); use != nullptr;
+             use = use->next()) {
+          ASSERT(use->location_slot()->Equals(fp_relative));
+          *use->location_slot() = sp_relative;
+        }
+      }
+    }
+  };
+
+  for (auto block : entry->successors()) {
+    if (FunctionEntryInstr* entry = block->AsFunctionEntry()) {
+      for (auto defn : *entry->initial_definitions()) {
+        if (auto param = defn->AsParameter()) {
+          const auto vreg = param->ssa_temp_index();
+          fix_location_for(block, param, vreg, 0);
+          if (param->HasPairRepresentation()) {
+            fix_location_for(block, param, ToSecondPairVreg(vreg),
+                             /*pair_index=*/1);
+          }
+        }
+      }
+    }
+  }
+}
+
 void FlowGraphAllocator::AllocateRegisters() {
   CollectRepresentations();
 
@@ -3055,13 +3179,16 @@
   PrepareForAllocation(Location::kFpuRegister, kNumberOfFpuRegisters,
                        unallocated_xmm_, fpu_regs_, blocked_fpu_registers_);
   AllocateUnallocatedRanges();
-  ResolveControlFlow();
 
   GraphEntryInstr* entry = block_order_[0]->AsGraphEntry();
   ASSERT(entry != NULL);
   intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor;
   entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count);
 
+  RemoveFrameIfNotNeeded();
+
+  ResolveControlFlow();
+
   if (FLAG_print_ssa_liveranges && CompilerState::ShouldTrace()) {
     const Function& function = flow_graph_.function();
 
diff --git a/runtime/vm/compiler/backend/linearscan.h b/runtime/vm/compiler/backend/linearscan.h
index 9843b0b..2d6e919 100644
--- a/runtime/vm/compiler/backend/linearscan.h
+++ b/runtime/vm/compiler/backend/linearscan.h
@@ -172,6 +172,8 @@
   void AllocateUnallocatedRanges();
   void AdvanceActiveIntervals(const intptr_t start);
 
+  void RemoveFrameIfNotNeeded();
+
   // Connect split siblings over non-linear control flow edges.
   void ResolveControlFlow();
 
@@ -260,6 +262,11 @@
 
   void PrintLiveRanges();
 
+  Location ComputeParameterLocation(BlockEntryInstr* block,
+                                    ParameterInstr* param,
+                                    Register base_reg,
+                                    intptr_t pair_index);
+
   const FlowGraph& flow_graph_;
 
   ReachingDefs reaching_defs_;
diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc
index d31957c..858150d 100644
--- a/runtime/vm/compiler/backend/locations.cc
+++ b/runtime/vm/compiler/backend/locations.cc
@@ -155,7 +155,8 @@
   // restrictions.
   if (always_calls()) {
     if (loc.IsUnallocated()) {
-      ASSERT(loc.policy() == Location::kAny);
+      ASSERT(loc.policy() == Location::kAny ||
+             loc.policy() == Location::kRequiresStackSlot);
     } else if (loc.IsPairLocation()) {
       ASSERT(!loc.AsPairLocation()->At(0).IsUnallocated() ||
              loc.AsPairLocation()->At(0).policy() == Location::kAny);
@@ -280,6 +281,8 @@
           return "R";
         case kRequiresFpuRegister:
           return "DR";
+        case kRequiresStackSlot:
+          return "RS";
         case kWritableRegister:
           return "WR";
         case kSameAsFirstInput:
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index 942e10a..ea708e4 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -238,6 +238,7 @@
     kPrefersRegister,
     kRequiresRegister,
     kRequiresFpuRegister,
+    kRequiresStackSlot,
     kWritableRegister,
     kSameAsFirstInput,
   };
@@ -265,6 +266,10 @@
     return UnallocatedLocation(kRequiresFpuRegister);
   }
 
+  static Location RequiresStackSlot() {
+    return UnallocatedLocation(kRequiresStackSlot);
+  }
+
   static Location WritableRegister() {
     return UnallocatedLocation(kWritableRegister);
   }
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 8a60a63..febd184 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2725,9 +2725,10 @@
     case Slot::Kind::kClosure_instantiator_type_arguments:
     case Slot::Kind::kClosureData_default_type_arguments:
     case Slot::Kind::kFunction_data:
+    case Slot::Kind::kFunction_signature:
     case Slot::Kind::kFunction_parameter_names:
-    case Slot::Kind::kFunction_parameter_types:
-    case Slot::Kind::kFunction_type_parameters:
+    case Slot::Kind::kFunctionType_parameter_types:
+    case Slot::Kind::kFunctionType_type_parameters:
     case Slot::Kind::kPointerBase_data_field:
     case Slot::Kind::kTypedDataView_data:
     case Slot::Kind::kType_arguments:
@@ -2753,6 +2754,7 @@
       *range = Range::Full(RepresentationToRangeSize(slot().representation()));
       break;
 
+    case Slot::Kind::kFunctionType_packed_fields:
     case Slot::Kind::kClosure_hash:
     case Slot::Kind::kLinkedHashMap_hash_mask:
     case Slot::Kind::kLinkedHashMap_used_data:
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index 269a793..573bc43 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -1684,7 +1684,6 @@
 
   ~LoadOptimizer() { aliased_set_->RollbackAliasedIdentites(); }
 
-  Isolate* isolate() const { return graph_->isolate(); }
   Zone* zone() const { return graph_->zone(); }
 
   static bool OptimizeGraph(FlowGraph* graph) {
@@ -1692,9 +1691,7 @@
 
     // For now, bail out for large functions to avoid OOM situations.
     // TODO(fschneider): Fix the memory consumption issue.
-    intptr_t function_length = graph->function().end_token_pos().Pos() -
-                               graph->function().token_pos().Pos();
-    if (function_length >= FLAG_huge_method_cutoff_in_tokens) {
+    if (graph->function().SourceSize() >= FLAG_huge_method_cutoff_in_tokens) {
       return false;
     }
 
@@ -1759,7 +1756,7 @@
       value = store_static->value();
     }
     return value != nullptr && value->BindsToConstant() &&
-           (value->BoundConstant().raw() == Object::sentinel().raw());
+           (value->BoundConstant().ptr() == Object::sentinel().ptr());
   }
 
   // This optimization pass tries to get rid of lazy initializer calls in
@@ -2850,9 +2847,7 @@
 
     // For now, bail out for large functions to avoid OOM situations.
     // TODO(fschneider): Fix the memory consumption issue.
-    intptr_t function_length = graph->function().end_token_pos().Pos() -
-                               graph->function().token_pos().Pos();
-    if (function_length >= FLAG_huge_method_cutoff_in_tokens) {
+    if (graph->function().SourceSize() >= FLAG_huge_method_cutoff_in_tokens) {
       return;
     }
 
@@ -3557,10 +3552,10 @@
               flow_graph_->GetConstant(Smi::ZoneHandle(Z, Smi::New(index)))),
           /*index_unboxed=*/false,
           /*index_scale=*/compiler::target::Instance::ElementSizeFor(array_cid),
-          array_cid, kAlignedAccess, DeoptId::kNone, alloc->token_pos());
+          array_cid, kAlignedAccess, DeoptId::kNone, alloc->source());
     } else {
-      load = new (Z)
-          LoadFieldInstr(new (Z) Value(alloc), *slot, alloc->token_pos());
+      load =
+          new (Z) LoadFieldInstr(new (Z) Value(alloc), *slot, alloc->source());
     }
     flow_graph_->InsertBefore(load_point, load, nullptr, FlowGraph::kValue);
     values->Add(new (Z) Value(load));
@@ -3575,11 +3570,11 @@
     num_elements = instr->num_context_variables();
   } else if (auto instr = alloc->AsCreateArray()) {
     cls = &Class::ZoneHandle(
-        flow_graph_->isolate()->object_store()->array_class());
+        flow_graph_->isolate_group()->object_store()->array_class());
     num_elements = instr->GetConstantNumElements();
   } else if (auto instr = alloc->AsAllocateTypedData()) {
     cls = &Class::ZoneHandle(
-        flow_graph_->isolate()->class_table()->At(instr->class_id()));
+        flow_graph_->isolate_group()->class_table()->At(instr->class_id()));
     num_elements = instr->GetConstantNumElements();
   } else {
     UNREACHABLE();
@@ -3695,11 +3690,13 @@
     }
   }
   if (alloc->IsCreateArray()) {
-    AddSlot(slots,
-            Slot::GetTypeArgumentsSlotFor(
-                flow_graph_->thread(),
-                Class::Handle(
-                    Z, flow_graph_->isolate()->object_store()->array_class())));
+    AddSlot(
+        slots,
+        Slot::GetTypeArgumentsSlotFor(
+            flow_graph_->thread(),
+            Class::Handle(
+                Z,
+                flow_graph_->isolate_group()->object_store()->array_class())));
   }
 
   // Collect all instructions that mention this object in the environment.
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index bc3b72f..859888f 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -224,15 +224,16 @@
   const Error& err = Error::Handle(cls.EnsureIsFinalized(thread));
   EXPECT(err.IsNull());
 
-  const Field& field = Field::Handle(
+  const Field& original_field = Field::Handle(
       cls.LookupField(String::Handle(Symbols::New(thread, "field"))));
-  EXPECT(!field.IsNull());
+  EXPECT(!original_field.IsNull());
+  const Field& field = Field::Handle(original_field.CloneFromOriginal());
 
   const Function& blackhole =
       Function::ZoneHandle(GetFunction(lib, "blackhole"));
 
   using compiler::BlockBuilder;
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
   FlowGraphBuilderHelper H;
 
   // We are going to build the following graph:
@@ -261,9 +262,9 @@
     BlockBuilder builder(H.flow_graph(), b1);
     auto& slot = Slot::Get(field, &H.flow_graph()->parsed_function());
     v0 = builder.AddDefinition(
-        new AllocateObjectInstr(TokenPosition::kNoSource, cls));
+        new AllocateObjectInstr(InstructionSource(), cls));
     v1 = builder.AddDefinition(
-        new LoadFieldInstr(new Value(v0), slot, TokenPosition::kNoSource));
+        new LoadFieldInstr(new Value(v0), slot, InstructionSource()));
     auto v2 = builder.AddDefinition(make_redefinition(&S, H.flow_graph(), v0));
     auto args = new InputsArray(2);
     args->Add(new Value(v1));
@@ -271,12 +272,12 @@
       args->Add(new Value(v2));
     }
     call = builder.AddInstruction(new StaticCallInstr(
-        TokenPosition::kNoSource, blackhole, 0, Array::empty_array(), args,
+        InstructionSource(), blackhole, 0, Array::empty_array(), args,
         S.GetNextDeoptId(), 0, ICData::RebindRule::kStatic));
     v4 = builder.AddDefinition(
-        new LoadFieldInstr(new Value(v2), slot, TokenPosition::kNoSource));
+        new LoadFieldInstr(new Value(v2), slot, InstructionSource()));
     ret = builder.AddInstruction(new ReturnInstr(
-        TokenPosition::kNoSource, new Value(v4), S.GetNextDeoptId()));
+        InstructionSource(), new Value(v4), S.GetNextDeoptId()));
   }
   H.FinishGraph();
   DominatorBasedCSE::Optimize(H.flow_graph());
@@ -310,7 +311,7 @@
                                  FlowGraph* flow_graph,
                                  Definition* defn) {
   return new CheckNullInstr(new Value(defn), String::ZoneHandle(),
-                            S->GetNextDeoptId(), TokenPosition::kNoSource);
+                            S->GetNextDeoptId(), InstructionSource());
 }
 
 static Definition* MakeRedefinition(CompilerState* S,
@@ -323,7 +324,7 @@
                                         FlowGraph* flow_graph,
                                         Definition* defn) {
   const auto& dst_type = AbstractType::ZoneHandle(Type::ObjectType());
-  return new AssertAssignableInstr(TokenPosition::kNoSource, new Value(defn),
+  return new AssertAssignableInstr(InstructionSource(), new Value(defn),
                                    new Value(flow_graph->GetConstant(dst_type)),
                                    new Value(flow_graph->constant_null()),
                                    new Value(flow_graph->constant_null()),
@@ -387,15 +388,16 @@
   const Error& err = Error::Handle(cls.EnsureIsFinalized(thread));
   EXPECT(err.IsNull());
 
-  const Field& field = Field::Handle(
+  const Field& original_field = Field::Handle(
       cls.LookupField(String::Handle(Symbols::New(thread, "field"))));
-  EXPECT(!field.IsNull());
+  EXPECT(!original_field.IsNull());
+  const Field& field = Field::Handle(original_field.CloneFromOriginal());
 
   const Function& blackhole =
       Function::ZoneHandle(GetFunction(lib, "blackhole"));
 
   using compiler::BlockBuilder;
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
   FlowGraphBuilderHelper H;
 
   // We are going to build the following graph:
@@ -433,36 +435,36 @@
     BlockBuilder builder(H.flow_graph(), b1);
     auto& slot = Slot::Get(field, &H.flow_graph()->parsed_function());
     v0 = builder.AddDefinition(
-        new AllocateObjectInstr(TokenPosition::kNoSource, cls));
+        new AllocateObjectInstr(InstructionSource(), cls));
     v5 = builder.AddDefinition(
-        new AllocateObjectInstr(TokenPosition::kNoSource, cls));
+        new AllocateObjectInstr(InstructionSource(), cls));
     if (!make_host_escape) {
-      builder.AddInstruction(new StoreInstanceFieldInstr(
-          slot, new Value(v5), new Value(v0), kEmitStoreBarrier,
-          TokenPosition::kNoSource));
+      builder.AddInstruction(
+          new StoreInstanceFieldInstr(slot, new Value(v5), new Value(v0),
+                                      kEmitStoreBarrier, InstructionSource()));
     }
     v1 = builder.AddDefinition(
-        new LoadFieldInstr(new Value(v0), slot, TokenPosition::kNoSource));
+        new LoadFieldInstr(new Value(v0), slot, InstructionSource()));
     auto v2 = builder.AddDefinition(make_redefinition(&S, H.flow_graph(), v5));
     auto args = new InputsArray(2);
     args->Add(new Value(v1));
     if (make_it_escape) {
       auto v6 = builder.AddDefinition(
-          new LoadFieldInstr(new Value(v2), slot, TokenPosition::kNoSource));
+          new LoadFieldInstr(new Value(v2), slot, InstructionSource()));
       args->Add(new Value(v6));
     } else if (make_host_escape) {
-      builder.AddInstruction(new StoreInstanceFieldInstr(
-          slot, new Value(v2), new Value(v0), kEmitStoreBarrier,
-          TokenPosition::kNoSource));
+      builder.AddInstruction(
+          new StoreInstanceFieldInstr(slot, new Value(v2), new Value(v0),
+                                      kEmitStoreBarrier, InstructionSource()));
       args->Add(new Value(v5));
     }
     call = builder.AddInstruction(new StaticCallInstr(
-        TokenPosition::kNoSource, blackhole, 0, Array::empty_array(), args,
+        InstructionSource(), blackhole, 0, Array::empty_array(), args,
         S.GetNextDeoptId(), 0, ICData::RebindRule::kStatic));
     v4 = builder.AddDefinition(
-        new LoadFieldInstr(new Value(v0), slot, TokenPosition::kNoSource));
+        new LoadFieldInstr(new Value(v0), slot, InstructionSource()));
     ret = builder.AddInstruction(new ReturnInstr(
-        TokenPosition::kNoSource, new Value(v4), S.GetNextDeoptId()));
+        InstructionSource(), new Value(v4), S.GetNextDeoptId()));
   }
   H.FinishGraph();
   DominatorBasedCSE::Optimize(H.flow_graph());
@@ -550,7 +552,7 @@
 // https://github.com/flutter/flutter/issues/48114.
 ISOLATE_UNIT_TEST_CASE(LoadOptimizer_AliasingViaTypedDataAndUntaggedTypedData) {
   using compiler::BlockBuilder;
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
   FlowGraphBuilderHelper H;
 
   const auto& lib = Library::Handle(Library::TypedDataLibrary());
@@ -597,7 +599,7 @@
 
     //   array <- StaticCall(...) {_Uint32List}
     array = builder.AddDefinition(new StaticCallInstr(
-        TokenPosition::kNoSource, function, 0, Array::empty_array(),
+        InstructionSource(), function, 0, Array::empty_array(),
         new InputsArray(), DeoptId::kNone, 0, ICData::kNoRebind));
     array->UpdateType(CompileType::FromCid(kTypedDataUint32ArrayCid));
     array->SetResultType(zone, CompileType::FromCid(kTypedDataUint32ArrayCid));
@@ -607,7 +609,7 @@
     v1 = builder.AddDefinition(new LoadIndexedInstr(
         new Value(array), new Value(vc0), /*index_unboxed=*/false, 1,
         kTypedDataUint32ArrayCid, kAlignedAccess, DeoptId::kNone,
-        TokenPosition::kNoSource));
+        InstructionSource()));
 
     //   v2 <- LoadUntagged(array)
     //   StoreIndexed(v2, index=0, value=42)
@@ -615,17 +617,17 @@
     store = builder.AddInstruction(new StoreIndexedInstr(
         new Value(v2), new Value(vc0), new Value(vc42), kNoStoreBarrier,
         /*index_unboxed=*/false, 1, kTypedDataUint32ArrayCid, kAlignedAccess,
-        DeoptId::kNone, TokenPosition::kNoSource));
+        DeoptId::kNone, InstructionSource()));
 
     //   v3 <- LoadIndexed(array)
     v3 = builder.AddDefinition(new LoadIndexedInstr(
         new Value(array), new Value(vc0), /*index_unboxed=*/false, 1,
         kTypedDataUint32ArrayCid, kAlignedAccess, DeoptId::kNone,
-        TokenPosition::kNoSource));
+        InstructionSource()));
 
     //   return v3
     ret = builder.AddInstruction(new ReturnInstr(
-        TokenPosition::kNoSource, new Value(v3), S.GetNextDeoptId()));
+        InstructionSource(), new Value(v3), S.GetNextDeoptId()));
   }
   H.FinishGraph();
 
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index f0a4f2c..5b814c5 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -319,7 +319,7 @@
   // itself stays behind in the compilation global cache. Thus we must always
   // try to add it to the list of guarded fields of the current function.
   if (slot.is_guarded_field()) {
-    if (thread->isolate()->use_field_guards()) {
+    if (thread->isolate_group()->use_field_guards()) {
       ASSERT(parsed_function != nullptr);
       parsed_function->AddToGuardedFields(&slot.field());
     } else {
@@ -364,8 +364,8 @@
     case Kind::kCapturedVariable:
       return (offset_in_bytes_ == other->offset_in_bytes_) &&
              (flags_ == other->flags_) &&
-             (DataAs<const String>()->raw() ==
-              other->DataAs<const String>()->raw());
+             (DataAs<const String>()->ptr() ==
+              other->DataAs<const String>()->ptr());
 
     case Kind::kDartField:
       return (offset_in_bytes_ == other->offset_in_bytes_) &&
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 4e2414f..1b554c5 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -52,16 +52,18 @@
 //   (i.e. initialized once at construction time and does not change after
 //   that) or like a non-final field.
 #define NULLABLE_BOXED_NATIVE_SLOTS_LIST(V)                                    \
-  V(Context, ContextLayout, parent, Context, FINAL)                            \
-  V(Closure, ClosureLayout, instantiator_type_arguments, TypeArguments, FINAL) \
-  V(Closure, ClosureLayout, delayed_type_arguments, TypeArguments, FINAL)      \
-  V(Closure, ClosureLayout, function_type_arguments, TypeArguments, FINAL)     \
-  V(ClosureData, ClosureDataLayout, default_type_arguments, TypeArguments,     \
+  V(Function, UntaggedFunction, signature, FunctionType, FINAL)                \
+  V(Context, UntaggedContext, parent, Context, FINAL)                          \
+  V(Closure, UntaggedClosure, instantiator_type_arguments, TypeArguments,      \
     FINAL)                                                                     \
-  V(Function, FunctionLayout, type_parameters, TypeArguments, FINAL)           \
-  V(Type, TypeLayout, arguments, TypeArguments, FINAL)                         \
-  V(WeakProperty, WeakPropertyLayout, key, Dynamic, VAR)                       \
-  V(WeakProperty, WeakPropertyLayout, value, Dynamic, VAR)
+  V(Closure, UntaggedClosure, delayed_type_arguments, TypeArguments, FINAL)    \
+  V(Closure, UntaggedClosure, function_type_arguments, TypeArguments, FINAL)   \
+  V(ClosureData, UntaggedClosureData, default_type_arguments, TypeArguments,   \
+    FINAL)                                                                     \
+  V(Type, UntaggedType, arguments, TypeArguments, FINAL)                       \
+  V(FunctionType, UntaggedFunctionType, type_parameters, TypeArguments, FINAL) \
+  V(WeakProperty, UntaggedWeakProperty, key, Dynamic, VAR)                     \
+  V(WeakProperty, UntaggedWeakProperty, value, Dynamic, VAR)
 
 // The list of slots that correspond to non-nullable boxed fields of native
 // objects in the following format:
@@ -77,35 +79,35 @@
 //   (i.e. initialized once at construction time and does not change after
 //   that) or like a non-final field.
 #define NONNULLABLE_BOXED_NATIVE_SLOTS_LIST(V)                                 \
-  V(Array, ArrayLayout, length, Smi, FINAL)                                    \
-  V(Closure, ClosureLayout, function, Function, FINAL)                         \
-  V(Closure, ClosureLayout, context, Context, FINAL)                           \
-  V(Closure, ClosureLayout, hash, Context, VAR)                                \
-  V(ClosureData, ClosureDataLayout, default_type_arguments_info, Smi, FINAL)   \
-  V(Function, FunctionLayout, data, Dynamic, FINAL)                            \
-  V(Function, FunctionLayout, parameter_names, Array, FINAL)                   \
-  V(Function, FunctionLayout, parameter_types, Array, FINAL)                   \
-  V(GrowableObjectArray, GrowableObjectArrayLayout, length, Smi, VAR)          \
-  V(GrowableObjectArray, GrowableObjectArrayLayout, data, Array, VAR)          \
-  V(TypedDataBase, TypedDataBaseLayout, length, Smi, FINAL)                    \
-  V(TypedDataView, TypedDataViewLayout, offset_in_bytes, Smi, FINAL)           \
-  V(TypedDataView, TypedDataViewLayout, data, Dynamic, FINAL)                  \
-  V(String, StringLayout, length, Smi, FINAL)                                  \
-  V(LinkedHashMap, LinkedHashMapLayout, index, TypedDataUint32Array, VAR)      \
-  V(LinkedHashMap, LinkedHashMapLayout, data, Array, VAR)                      \
-  V(LinkedHashMap, LinkedHashMapLayout, hash_mask, Smi, VAR)                   \
-  V(LinkedHashMap, LinkedHashMapLayout, used_data, Smi, VAR)                   \
-  V(LinkedHashMap, LinkedHashMapLayout, deleted_keys, Smi, VAR)                \
-  V(ArgumentsDescriptor, ArrayLayout, type_args_len, Smi, FINAL)               \
-  V(ArgumentsDescriptor, ArrayLayout, positional_count, Smi, FINAL)            \
-  V(ArgumentsDescriptor, ArrayLayout, count, Smi, FINAL)                       \
-  V(ArgumentsDescriptor, ArrayLayout, size, Smi, FINAL)                        \
-  V(PointerBase, PointerBaseLayout, data_field, Dynamic, FINAL)                \
-  V(TypeArguments, TypeArgumentsLayout, length, Smi, FINAL)                    \
-  V(TypeParameter, TypeParameterLayout, bound, Dynamic, FINAL)                 \
-  V(TypeParameter, TypeParameterLayout, name, Dynamic, FINAL)                  \
-  V(UnhandledException, UnhandledExceptionLayout, exception, Dynamic, FINAL)   \
-  V(UnhandledException, UnhandledExceptionLayout, stacktrace, Dynamic, FINAL)
+  V(Array, UntaggedArray, length, Smi, FINAL)                                  \
+  V(Closure, UntaggedClosure, function, Function, FINAL)                       \
+  V(Closure, UntaggedClosure, context, Context, FINAL)                         \
+  V(Closure, UntaggedClosure, hash, Context, VAR)                              \
+  V(ClosureData, UntaggedClosureData, default_type_arguments_info, Smi, FINAL) \
+  V(Function, UntaggedFunction, data, Dynamic, FINAL)                          \
+  V(Function, UntaggedFunction, parameter_names, Array, FINAL)                 \
+  V(FunctionType, UntaggedFunctionType, parameter_types, Array, FINAL)         \
+  V(GrowableObjectArray, UntaggedGrowableObjectArray, length, Smi, VAR)        \
+  V(GrowableObjectArray, UntaggedGrowableObjectArray, data, Array, VAR)        \
+  V(TypedDataBase, UntaggedTypedDataBase, length, Smi, FINAL)                  \
+  V(TypedDataView, UntaggedTypedDataView, offset_in_bytes, Smi, FINAL)         \
+  V(TypedDataView, UntaggedTypedDataView, data, Dynamic, FINAL)                \
+  V(String, UntaggedString, length, Smi, FINAL)                                \
+  V(LinkedHashMap, UntaggedLinkedHashMap, index, TypedDataUint32Array, VAR)    \
+  V(LinkedHashMap, UntaggedLinkedHashMap, data, Array, VAR)                    \
+  V(LinkedHashMap, UntaggedLinkedHashMap, hash_mask, Smi, VAR)                 \
+  V(LinkedHashMap, UntaggedLinkedHashMap, used_data, Smi, VAR)                 \
+  V(LinkedHashMap, UntaggedLinkedHashMap, deleted_keys, Smi, VAR)              \
+  V(ArgumentsDescriptor, UntaggedArray, type_args_len, Smi, FINAL)             \
+  V(ArgumentsDescriptor, UntaggedArray, positional_count, Smi, FINAL)          \
+  V(ArgumentsDescriptor, UntaggedArray, count, Smi, FINAL)                     \
+  V(ArgumentsDescriptor, UntaggedArray, size, Smi, FINAL)                      \
+  V(PointerBase, UntaggedPointerBase, data_field, Dynamic, FINAL)              \
+  V(TypeArguments, UntaggedTypeArguments, length, Smi, FINAL)                  \
+  V(TypeParameter, UntaggedTypeParameter, bound, Dynamic, FINAL)               \
+  V(TypeParameter, UntaggedTypeParameter, name, Dynamic, FINAL)                \
+  V(UnhandledException, UntaggedUnhandledException, exception, Dynamic, FINAL) \
+  V(UnhandledException, UntaggedUnhandledException, stacktrace, Dynamic, FINAL)
 
 // List of slots that correspond to unboxed fields of native objects in the
 // following format:
@@ -123,9 +125,10 @@
 //
 // Note: As the underlying field is unboxed, these slots cannot be nullable.
 #define UNBOXED_NATIVE_SLOTS_LIST(V)                                           \
-  V(Function, FunctionLayout, kind_tag, Uint32, FINAL)                         \
-  V(Function, FunctionLayout, packed_fields, Uint32, FINAL)                    \
-  V(TypeParameter, TypeParameterLayout, flags, Uint8, FINAL)
+  V(Function, UntaggedFunction, kind_tag, Uint32, FINAL)                       \
+  V(Function, UntaggedFunction, packed_fields, Uint32, FINAL)                  \
+  V(FunctionType, UntaggedFunctionType, packed_fields, Uint32, FINAL)          \
+  V(TypeParameter, UntaggedTypeParameter, flags, Uint8, FINAL)
 
 // For uses that do not need the exact_type (boxed) or representation (unboxed)
 // or whether a boxed native slot is nullable. (Generally, such users only need
diff --git a/runtime/vm/compiler/backend/slot_test.cc b/runtime/vm/compiler/backend/slot_test.cc
index 8c4b620..a7e95b4 100644
--- a/runtime/vm/compiler/backend/slot_test.cc
+++ b/runtime/vm/compiler/backend/slot_test.cc
@@ -46,9 +46,10 @@
       Script::Handle(), TokenPosition::kNoSource));
   dummy_class.set_is_synthesized_class();
 
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   const Function& dummy_function = Function::ZoneHandle(
-      Function::New(String::Handle(Symbols::New(thread, "foo")),
-                    FunctionLayout::kRegularFunction, false, false, false,
+      Function::New(signature, String::Handle(Symbols::New(thread, "foo")),
+                    UntaggedFunction::kRegularFunction, false, false, false,
                     false, false, dummy_class, TokenPosition::kMinSource));
 
   const Field& field = Field::Handle(
@@ -63,7 +64,8 @@
   field.set_is_nullable_unsafe(false);
 
   // Enter compiler state.
-  CompilerState compiler_state(thread, /*is_aot=*/false);
+  CompilerState compiler_state(thread, /*is_aot=*/false,
+                               /*is_optimizing=*/true);
 
   const Field& field_clone_1 = Field::ZoneHandle(field.CloneFromOriginal());
   const Field& field_clone_2 = Field::ZoneHandle(field.CloneFromOriginal());
@@ -81,8 +83,8 @@
 
   // Check that the field was added (once) to the list of guarded fields.
   EXPECT_EQ(1, parsed_function->guarded_fields()->length());
-  EXPECT_EQ(parsed_function->guarded_fields()->At(0)->raw(),
-            field_clone_1.raw());
+  EXPECT_EQ(parsed_function->guarded_fields()->At(0)->ptr(),
+            field_clone_1.ptr());
 
   // Change the guarded state of the field to "unknown" - emulating concurrent
   // modification of the guarded state in mutator) and create a new clone of
@@ -98,8 +100,8 @@
   const Slot& slot3 = Slot::Get(field_clone_3, parsed_function2);
   EXPECT_EQ(&slot1, &slot3);
   EXPECT_EQ(1, parsed_function2->guarded_fields()->length());
-  EXPECT_EQ(parsed_function2->guarded_fields()->At(0)->raw(),
-            field_clone_1.raw());
+  EXPECT_EQ(parsed_function2->guarded_fields()->At(0)->ptr(),
+            field_clone_1.ptr());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 8d96744..3ae21f6 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -303,7 +303,7 @@
   }
   Thread* thread = Thread::Current();
   const Class& null_class =
-      Class::Handle(thread->isolate()->object_store()->null_class());
+      Class::Handle(thread->isolate_group()->object_store()->null_class());
   Function& target = Function::Handle();
   if (Error::Handle(null_class.EnsureIsFinalized(thread)).IsNull()) {
     target = Resolver::ResolveDynamicAnyArgs(thread->zone(), null_class,
@@ -393,7 +393,7 @@
   } else if ((is_simple_instance_of || (instance_of != NULL)) &&
              comparison->InputAt(1)->BindsToConstant() &&
              comparison->InputAt(1)->BoundConstant().IsBool()) {
-    if (comparison->InputAt(1)->BoundConstant().raw() == Bool::False().raw()) {
+    if (comparison->InputAt(1)->BoundConstant().ptr() == Bool::False().ptr()) {
       negated = !negated;
     }
     BlockEntryInstr* true_successor =
@@ -508,14 +508,14 @@
   Instruction* check_clone = NULL;
   if (check->IsCheckSmi()) {
     check_clone = new CheckSmiInstr(assert->value()->Copy(zone()),
-                                    assert->deopt_id(), check->token_pos());
+                                    assert->deopt_id(), check->source());
     check_clone->AsCheckSmi()->set_licm_hoisted(
         check->AsCheckSmi()->licm_hoisted());
   } else {
     ASSERT(check->IsCheckClass());
     check_clone =
         new CheckClassInstr(assert->value()->Copy(zone()), assert->deopt_id(),
-                            check->AsCheckClass()->cids(), check->token_pos());
+                            check->AsCheckClass()->cids(), check->source());
     check_clone->AsCheckClass()->set_licm_hoisted(
         check->AsCheckClass()->licm_hoisted());
   }
@@ -564,7 +564,8 @@
 
   // Climb up the hierarchy to find a suitable supertype. Note that interface
   // types are not considered, making the union potentially non-commutative
-  if (abstract_type->IsInstantiated() && !abstract_type->IsDynamicType()) {
+  if (abstract_type->IsInstantiated() && !abstract_type->IsDynamicType() &&
+      !abstract_type->IsFunctionType()) {
     Class& cls = Class::Handle(abstract_type->type_class());
     for (; !cls.IsNull() && !cls.IsGeneric(); cls = cls.SuperClass()) {
       type_ = &AbstractType::ZoneHandle(cls.RareType());
@@ -775,8 +776,8 @@
       return type_;
     }
 
-    Isolate* I = Isolate::Current();
-    const Class& type_class = Class::Handle(I->class_table()->At(cid_));
+    auto IG = IsolateGroup::Current();
+    const Class& type_class = Class::Handle(IG->class_table()->At(cid_));
     type_ = &AbstractType::ZoneHandle(type_class.RareType());
   }
 
@@ -862,7 +863,7 @@
     // *not* assignable to it (because int implements Comparable<num> and not
     // Comparable<int>).
     if (type.IsFutureOrType() ||
-        type.type_class() == CompilerState::Current().ComparableClass().raw()) {
+        type.type_class() == CompilerState::Current().ComparableClass().ptr()) {
       const auto& args = TypeArguments::Handle(Type::Cast(type).arguments());
       const auto& arg0 = AbstractType::Handle(args.TypeAt(0));
       return !recurse || CanPotentiallyBeSmi(arg0, /*recurse=*/true);
@@ -887,7 +888,7 @@
     return;
   } else if ((cid_ != kIllegalCid) && (cid_ != kDynamicCid)) {
     const Class& cls =
-        Class::Handle(Isolate::Current()->class_table()->At(cid_));
+        Class::Handle(IsolateGroup::Current()->class_table()->At(cid_));
     type_name = String::Handle(cls.ScrubbedName()).ToCString();
   } else if (type_ != NULL) {
     type_name = type_->IsDynamicType()
@@ -1145,7 +1146,7 @@
     // Do not trust static parameter type of 'operator ==' as it is a
     // non-nullable Object but VM handles comparison with null in
     // the callee, so 'operator ==' can take null as an argument.
-    if ((function.name() != Symbols::EqualOperator().raw()) &&
+    if ((function.name() != Symbols::EqualOperator().ptr()) &&
         (param->was_type_checked_by_caller() ||
          (is_unchecked_entry_param &&
           !param->is_explicit_covariant_parameter()))) {
@@ -1356,9 +1357,9 @@
             ? TypeArguments::null_type_arguments()
             : TypeArguments::Cast(type_args_value->BoundConstant());
     const Class& cls =
-        Class::Handle(Isolate::Current()->class_table()->At(cid));
-    Type& type = Type::ZoneHandle(Type::New(
-        cls, type_args, TokenPosition::kNoSource, Nullability::kNonNullable));
+        Class::Handle(IsolateGroup::Current()->class_table()->At(cid));
+    Type& type =
+        Type::ZoneHandle(Type::New(cls, type_args, Nullability::kNonNullable));
     ASSERT(type.IsInstantiated());
     type.SetIsFinalized();
     return CompileType(CompileType::kNonNullable, cid, &type);
@@ -1480,8 +1481,9 @@
 CompileType AllocateObjectInstr::ComputeType() const {
   if (!closure_function().IsNull()) {
     ASSERT(cls().id() == kClosureCid);
-    return CompileType(CompileType::kNonNullable, kClosureCid,
-                       &Type::ZoneHandle(closure_function().SignatureType()));
+    const FunctionType& sig =
+        FunctionType::ZoneHandle(closure_function().signature());
+    return CompileType(CompileType::kNonNullable, kClosureCid, &sig);
   }
   // TODO(vegorov): Incorporate type arguments into the returned type.
   return CompileType::FromCid(cls().id());
@@ -1498,7 +1500,7 @@
 CompileType LoadFieldInstr::ComputeType() const {
   const AbstractType& field_type = slot().static_type();
   CompileType compile_type_cid = slot().ComputeCompileType();
-  if (field_type.raw() == AbstractType::null()) {
+  if (field_type.ptr() == AbstractType::null()) {
     return compile_type_cid;
   }
 
@@ -1747,17 +1749,17 @@
         AbstractType::Handle(TypeParameter::Cast(array_type).bound()));
   }
   if (!array_type.IsType()) {
-    return Object::dynamic_type().raw();
+    return Object::dynamic_type().ptr();
   }
   const intptr_t cid = array_type.type_class_id();
   if (cid == kGrowableObjectArrayCid || cid == kArrayCid ||
       cid == kImmutableArrayCid ||
       array_type.type_class() ==
-          Isolate::Current()->object_store()->list_class()) {
+          IsolateGroup::Current()->object_store()->list_class()) {
     const auto& type_args = TypeArguments::Handle(array_type.arguments());
     return type_args.TypeAtNullSafe(Array::kElementTypeTypeArgPos);
   }
-  return Object::dynamic_type().raw();
+  return Object::dynamic_type().ptr();
 }
 
 static AbstractTypePtr GetElementTypeFromArray(Value* array) {
@@ -1768,7 +1770,7 @@
     auto& elem_type = AbstractType::Handle(ExtractElementTypeFromArrayType(
         *(array->definition()->Type()->ToAbstractType())));
     if (!elem_type.IsDynamicType()) {
-      return elem_type.raw();
+      return elem_type.ptr();
     }
   }
   return ExtractElementTypeFromArrayType(*(array->Type()->ToAbstractType()));
diff --git a/runtime/vm/compiler/backend/type_propagator_test.cc b/runtime/vm/compiler/backend/type_propagator_test.cc
index 852a885..a278009 100644
--- a/runtime/vm/compiler/backend/type_propagator_test.cc
+++ b/runtime/vm/compiler/backend/type_propagator_test.cc
@@ -26,7 +26,7 @@
 using compiler::BlockBuilder;
 
 ISOLATE_UNIT_TEST_CASE(TypePropagator_RedefinitionAfterStrictCompareWithNull) {
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
 
   FlowGraphBuilderHelper H;
 
@@ -61,7 +61,7 @@
     v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
     builder.AddBranch(
         new StrictCompareInstr(
-            TokenPosition::kNoSource, Token::kEQ_STRICT, new Value(v0),
+            InstructionSource(), Token::kEQ_STRICT, new Value(v0),
             new Value(H.flow_graph()->GetConstant(Object::Handle())),
             /*needs_number_check=*/false, S.GetNextDeoptId()),
         b2, b3);
@@ -101,7 +101,7 @@
 
 ISOLATE_UNIT_TEST_CASE(
     TypePropagator_RedefinitionAfterStrictCompareWithLoadClassId) {
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
 
   FlowGraphBuilderHelper H;
 
@@ -128,7 +128,7 @@
     auto load_cid = builder.AddDefinition(new LoadClassIdInstr(new Value(v0)));
     builder.AddBranch(
         new StrictCompareInstr(
-            TokenPosition::kNoSource, Token::kEQ_STRICT, new Value(load_cid),
+            InstructionSource(), Token::kEQ_STRICT, new Value(load_cid),
             new Value(H.IntConstant(kDoubleCid)),
             /*needs_number_check=*/false, S.GetNextDeoptId()),
         b2, b3);
@@ -164,20 +164,21 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(TypePropagator_Refinement) {
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
 
   const Class& object_class =
-      Class::Handle(thread->isolate()->object_store()->object_class());
+      Class::Handle(thread->isolate_group()->object_store()->object_class());
 
+  const FunctionType& signature = FunctionType::Handle(FunctionType::New());
   const Function& target_func = Function::ZoneHandle(Function::New(
-      String::Handle(Symbols::New(thread, "dummy2")),
-      FunctionLayout::kRegularFunction,
+      signature, String::Handle(Symbols::New(thread, "dummy2")),
+      UntaggedFunction::kRegularFunction,
       /*is_static=*/true,
       /*is_const=*/false,
       /*is_abstract=*/false,
       /*is_external=*/false,
       /*is_native=*/true, object_class, TokenPosition::kNoSource));
-  target_func.set_result_type(AbstractType::Handle(Type::IntType()));
+  signature.set_result_type(AbstractType::Handle(Type::IntType()));
 
   const Field& field = Field::ZoneHandle(
       Field::New(String::Handle(Symbols::New(thread, "dummy")),
@@ -223,8 +224,8 @@
     BlockBuilder builder(H.flow_graph(), b1);
     v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
     builder.AddBranch(new StrictCompareInstr(
-                          TokenPosition::kNoSource, Token::kEQ_STRICT,
-                          new Value(v0), new Value(H.IntConstant(1)),
+                          InstructionSource(), Token::kEQ_STRICT, new Value(v0),
+                          new Value(H.IntConstant(1)),
                           /*needs_number_check=*/false, S.GetNextDeoptId()),
                       b2, b3);
   }
@@ -232,7 +233,7 @@
   {
     BlockBuilder builder(H.flow_graph(), b2);
     v2 = builder.AddDefinition(
-        new StaticCallInstr(TokenPosition::kNoSource, target_func,
+        new StaticCallInstr(InstructionSource(), target_func,
                             /*type_args_len=*/0,
                             /*argument_names=*/Array::empty_array(),
                             new InputsArray(0), S.GetNextDeoptId(),
@@ -258,7 +259,7 @@
   EXPECT_PROPERTY(v2->Type(), it.IsNullableInt());
   EXPECT_PROPERTY(v3->Type(), it.IsNullableInt());
 
-  auto v4 = new LoadStaticFieldInstr(field, TokenPosition::kNoSource);
+  auto v4 = new LoadStaticFieldInstr(field, InstructionSource());
   H.flow_graph()->InsertBefore(v2, v4, nullptr, FlowGraph::kValue);
   v2->ReplaceUsesWith(v4);
   v2->RemoveFromGraph();
@@ -271,7 +272,7 @@
 // This test verifies that mutable compile types are not incorrectly cached
 // as reaching types after inference.
 ISOLATE_UNIT_TEST_CASE(TypePropagator_Regress36156) {
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
   FlowGraphBuilderHelper H;
 
   // We are going to build the following graph:
@@ -313,8 +314,8 @@
     BlockBuilder builder(H.flow_graph(), b1);
     v0 = builder.AddParameter(0, 0, /*with_frame=*/true, kTagged);
     builder.AddBranch(new StrictCompareInstr(
-                          TokenPosition::kNoSource, Token::kEQ_STRICT,
-                          new Value(v0), new Value(H.IntConstant(1)),
+                          InstructionSource(), Token::kEQ_STRICT, new Value(v0),
+                          new Value(H.IntConstant(1)),
                           /*needs_number_check=*/false, S.GetNextDeoptId()),
                       b6, b2);
   }
@@ -322,8 +323,8 @@
   {
     BlockBuilder builder(H.flow_graph(), b2);
     builder.AddBranch(new StrictCompareInstr(
-                          TokenPosition::kNoSource, Token::kEQ_STRICT,
-                          new Value(v0), new Value(H.IntConstant(2)),
+                          InstructionSource(), Token::kEQ_STRICT, new Value(v0),
+                          new Value(H.IntConstant(2)),
                           /*needs_number_check=*/false, S.GetNextDeoptId()),
                       b3, b4);
   }
@@ -354,8 +355,8 @@
     BlockBuilder builder(H.flow_graph(), b7);
     v5 = H.Phi(b7, {{b5, v3}, {b6, H.DoubleConstant(1.0)}});
     builder.AddPhi(v5);
-    builder.AddInstruction(new ReturnInstr(TokenPosition::kNoSource,
-                                           new Value(v5), S.GetNextDeoptId()));
+    builder.AddInstruction(new ReturnInstr(InstructionSource(), new Value(v5),
+                                           S.GetNextDeoptId()));
   }
 
   H.FinishGraph();
@@ -402,7 +403,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CompileType_CanBeSmi) {
-  CompilerState S(thread, /*is_aot=*/false);
+  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
 
   const char* late_tag = TestCase::LateTag();
   auto script_chars = Utils::CStringUniquePtr(
diff --git a/runtime/vm/compiler/backend/typed_data_aot_test.cc b/runtime/vm/compiler/backend/typed_data_aot_test.cc
index 72f41e3..68bca62 100644
--- a/runtime/vm/compiler/backend/typed_data_aot_test.cc
+++ b/runtime/vm/compiler/backend/typed_data_aot_test.cc
@@ -4,6 +4,7 @@
 
 #include <vector>
 
+#include "vm/closure_functions_cache.h"
 #include "vm/compiler/backend/il_printer.h"
 #include "vm/compiler/backend/il_test_helper.h"
 #include "vm/compiler/call_specializer.h"
@@ -45,7 +46,7 @@
   LoadIndexedInstr* load_indexed = nullptr;
 
   ILMatcher cursor(flow_graph, entry);
-  if (Isolate::Current()->null_safety()) {
+  if (IsolateGroup::Current()->null_safety()) {
     RELEASE_ASSERT(cursor.TryMatch({
         kMoveGlob,
         {kMatchAndMoveLoadField, &load_field},
@@ -134,10 +135,10 @@
       kMatchReturn,
   }));
 
-  EXPECT(length_call->Selector() == Symbols::GetLength().raw());
+  EXPECT(length_call->Selector() == Symbols::GetLength().ptr());
   EXPECT(pusharg1->InputAt(0)->definition()->IsParameter());
   EXPECT(pusharg2->InputAt(0)->definition()->IsParameter());
-  EXPECT(index_get_call->Selector() == Symbols::IndexToken().raw());
+  EXPECT(index_get_call->Selector() == Symbols::IndexToken().ptr());
 }
 
 // This test asserts that we are inlining get:length, [] and []= for all typed
@@ -182,7 +183,7 @@
 
     // Ensure the IL matches what we expect.
     ILMatcher cursor(flow_graph, entry);
-    if (Isolate::Current()->null_safety()) {
+    if (IsolateGroup::Current()->null_safety()) {
       EXPECT(cursor.TryMatch({
           // Before loop
           kMoveGlob,
@@ -327,7 +328,7 @@
 
     // Ensure the IL matches what we expect.
     ILMatcher cursor(flow_graph, entry, /*trace=*/true);
-    if (Isolate::Current()->null_safety()) {
+    if (IsolateGroup::Current()->null_safety()) {
       EXPECT(cursor.TryMatch({
           // LoadField length
           kMoveGlob,
@@ -435,7 +436,7 @@
   // With null safety nulls cannot be passed as non-nullable arguments, so
   // skip all error stages and only run the last stage.
   const intptr_t first_stage =
-      Isolate::Current()->null_safety() ? kLastStage : 0;
+      IsolateGroup::Current()->null_safety() ? kLastStage : 0;
   for (intptr_t stage = first_stage; stage <= kLastStage; ++stage) {
     run_test("Uint8List", "int", int8_list, int_value, stage);
     run_test("Int8List", "int", uint8_list, int_value, stage);
@@ -472,17 +473,11 @@
   Invoke(root_library, "test");
   const auto& test_function =
       Function::Handle(GetFunction(root_library, "test"));
-  const auto& closures = GrowableObjectArray::Handle(
-      Isolate::Current()->object_store()->closure_functions());
-  auto& function = Function::Handle();
-  for (intptr_t i = closures.Length() - 1; 0 <= i; ++i) {
-    function ^= closures.At(i);
-    if (function.parent_function() == test_function.raw()) {
-      break;
-    }
-    function = Function::null();
-  }
-  RELEASE_ASSERT(!function.IsNull());
+
+  const auto& function = Function::Handle(
+      ClosureFunctionsCache::GetUniqueInnerClosure(test_function));
+  RELEASE_ASSERT(function.IsFunction());
+
   TestPipeline pipeline(function, CompilerPass::kAOT);
   FlowGraph* flow_graph = pipeline.RunPasses({});
 
diff --git a/runtime/vm/compiler/backend/yield_position_test.cc b/runtime/vm/compiler/backend/yield_position_test.cc
index a32bb74..c28b700 100644
--- a/runtime/vm/compiler/backend/yield_position_test.cc
+++ b/runtime/vm/compiler/backend/yield_position_test.cc
@@ -4,6 +4,7 @@
 
 #include <utility>
 
+#include "vm/closure_functions_cache.h"
 #include "vm/compiler/backend/il_test_helper.h"
 #include "vm/compiler/compiler_pass.h"
 #include "vm/object.h"
@@ -26,7 +27,7 @@
     while (!it.Done()) {
       if (auto return_instr = it.Current()->AsReturn()) {
         if (return_instr->yield_index() !=
-            PcDescriptorsLayout::kInvalidYieldIndex) {
+            UntaggedPcDescriptors::kInvalidYieldIndex) {
           ASSERT(return_instr->yield_index() > 0);
           array->Add(
               Pair(return_instr->yield_index(), return_instr->token_pos()));
@@ -42,9 +43,9 @@
 static YieldPoints* GetYieldPointsFromCode(const Code& code) {
   auto array = new YieldPoints();
   const auto& pc_descriptor = PcDescriptors::Handle(code.pc_descriptors());
-  PcDescriptors::Iterator it(pc_descriptor, PcDescriptorsLayout::kOther);
+  PcDescriptors::Iterator it(pc_descriptor, UntaggedPcDescriptors::kOther);
   while (it.MoveNext()) {
-    if (it.YieldIndex() != PcDescriptorsLayout::kInvalidYieldIndex) {
+    if (it.YieldIndex() != UntaggedPcDescriptors::kInvalidYieldIndex) {
       array->Add(Pair(it.YieldIndex(), it.TokenPos()));
     }
   }
@@ -78,19 +79,9 @@
       Function::Handle(GetFunction(root_library, "foo"));
 
   // Grab the inner, lazily created, closure from the object store.
-  const auto& closures = GrowableObjectArray::Handle(
-      Isolate::Current()->object_store()->closure_functions());
-  ASSERT(!closures.IsNull());
-  auto& closure = Object::Handle();
-  for (intptr_t i = 0; i < closures.Length(); ++i) {
-    closure = closures.At(i);
-    if (Function::Cast(closure).parent_function() == outer_function.raw()) {
-      break;
-    }
-    closure = Object::null();
-  }
-  RELEASE_ASSERT(closure.IsFunction());
-  const auto& function = Function::Cast(closure);
+  const auto& function = Function::Handle(
+      ClosureFunctionsCache::GetUniqueInnerClosure(outer_function));
+  RELEASE_ASSERT(function.IsFunction());
 
   // Ensure we have 3 different return instructions with yield indices attached
   // to them.
@@ -103,11 +94,11 @@
     EXPECT_EQ(3, yield_points.length());
 
     EXPECT_EQ(1, yield_points[0].first);
-    EXPECT_EQ(88, yield_points[0].second.value());
+    EXPECT_EQ(88, yield_points[0].second.Pos());
     EXPECT_EQ(2, yield_points[1].first);
-    EXPECT_EQ(129, yield_points[1].second.value());
+    EXPECT_EQ(129, yield_points[1].second.Pos());
     EXPECT_EQ(3, yield_points[2].first);
-    EXPECT_EQ(170, yield_points[2].second.value());
+    EXPECT_EQ(170, yield_points[2].second.Pos());
   };
 
   validate_indices(*GetYieldPointsFromGraph(flow_graph));
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index c096c35..b6f5265 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -13,7 +13,7 @@
 namespace dart {
 
 // Quick access to the current isolate and zone.
-#define I (isolate())
+#define IG (isolate_group())
 #define Z (zone())
 
 static void RefineUseTypes(Definition* instr) {
@@ -150,7 +150,7 @@
 
   if (all_cids_known) {
     const Class& receiver_class =
-        Class::Handle(Z, isolate()->class_table()->At(class_ids[0]));
+        Class::Handle(Z, IG->class_table()->At(class_ids[0]));
     if (!receiver_class.is_finalized()) {
       // Do not eagerly finalize classes. ResolveDynamicForReceiverClass can
       // cause class finalization, since callee's receiver class may not be
@@ -232,7 +232,7 @@
   if (to_check->Type()->ToCid() != kSmiCid) {
     InsertBefore(insert_before,
                  new (Z) CheckSmiInstr(new (Z) Value(to_check), deopt_id,
-                                       insert_before->token_pos()),
+                                       insert_before->source()),
                  deopt_environment, FlowGraph::kEffect);
   }
 }
@@ -243,8 +243,8 @@
                                     Environment* deopt_environment,
                                     Instruction* insert_before) {
   // Type propagation has not run yet, we cannot eliminate the check.
-  Instruction* check = flow_graph_->CreateCheckClass(
-      to_check, cids, deopt_id, insert_before->token_pos());
+  Instruction* check = flow_graph_->CreateCheckClass(to_check, cids, deopt_id,
+                                                     insert_before->source());
   InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect);
 }
 
@@ -264,7 +264,7 @@
   if (to_check->Type()->is_nullable()) {
     CheckNullInstr* check_null =
         new (Z) CheckNullInstr(to_check->CopyWithType(Z), function_name,
-                               deopt_id, insert_before->token_pos());
+                               deopt_id, insert_before->source());
     if (FLAG_trace_strong_mode_types) {
       THR_Print("[Strong mode] Inserted %s\n", check_null->ToCString());
     }
@@ -355,7 +355,7 @@
 
     // Comparing char-codes instead of strings.
     EqualityCompareInstr* comp =
-        new (Z) EqualityCompareInstr(call->token_pos(), op_kind, left_val,
+        new (Z) EqualityCompareInstr(call->source(), op_kind, left_val,
                                      right_val, kSmiCid, call->deopt_id());
     ReplaceCall(call, comp);
 
@@ -394,11 +394,11 @@
   } else if (binary_feedback.OperandsAre(kSmiCid)) {
     InsertBefore(call,
                  new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(),
-                                       call->token_pos()),
+                                       call->source()),
                  call->env(), FlowGraph::kEffect);
     InsertBefore(call,
                  new (Z) CheckSmiInstr(new (Z) Value(right), call->deopt_id(),
-                                       call->token_pos()),
+                                       call->source()),
                  call->env(), FlowGraph::kEffect);
     cid = kSmiCid;
   } else if (binary_feedback.OperandsAreSmiOrMint() &&
@@ -440,7 +440,7 @@
       if ((right_const != NULL && right_const->value().IsNull()) ||
           (left_const != NULL && left_const->value().IsNull())) {
         StrictCompareInstr* comp = new (Z)
-            StrictCompareInstr(call->token_pos(), Token::kEQ_STRICT,
+            StrictCompareInstr(call->source(), Token::kEQ_STRICT,
                                new (Z) Value(left), new (Z) Value(right),
                                /* number_check = */ false, DeoptId::kNone);
         ReplaceCall(call, comp);
@@ -450,9 +450,9 @@
     }
   }
   ASSERT(cid != kIllegalCid);
-  EqualityCompareInstr* comp = new (Z)
-      EqualityCompareInstr(call->token_pos(), op_kind, new (Z) Value(left),
-                           new (Z) Value(right), cid, call->deopt_id());
+  EqualityCompareInstr* comp =
+      new (Z) EqualityCompareInstr(call->source(), op_kind, new (Z) Value(left),
+                                   new (Z) Value(right), cid, call->deopt_id());
   ReplaceCall(call, comp);
   return true;
 }
@@ -470,11 +470,11 @@
   if (binary_feedback.OperandsAre(kSmiCid)) {
     InsertBefore(call,
                  new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(),
-                                       call->token_pos()),
+                                       call->source()),
                  call->env(), FlowGraph::kEffect);
     InsertBefore(call,
                  new (Z) CheckSmiInstr(new (Z) Value(right), call->deopt_id(),
-                                       call->token_pos()),
+                                       call->source()),
                  call->env(), FlowGraph::kEffect);
     cid = kSmiCid;
   } else if (binary_feedback.OperandsAreSmiOrMint() &&
@@ -503,7 +503,7 @@
   }
   ASSERT(cid != kIllegalCid);
   RelationalOpInstr* comp =
-      new (Z) RelationalOpInstr(call->token_pos(), op_kind, new (Z) Value(left),
+      new (Z) RelationalOpInstr(call->source(), op_kind, new (Z) Value(left),
                                 new (Z) Value(right), cid, call->deopt_id());
   ReplaceCall(call, comp);
   return true;
@@ -634,7 +634,7 @@
 
     BinaryDoubleOpInstr* double_bin_op = new (Z)
         BinaryDoubleOpInstr(op_kind, new (Z) Value(left), new (Z) Value(right),
-                            call->deopt_id(), call->token_pos());
+                            call->deopt_id(), call->source());
     ReplaceCall(call, double_bin_op);
   } else if (operands_type == kMintCid) {
     if (!FlowGraphCompiler::SupportsUnboxedInt64()) return false;
@@ -661,7 +661,7 @@
         // because the smi operation can still deoptimize.
         InsertBefore(call,
                      new (Z) CheckSmiInstr(new (Z) Value(left),
-                                           call->deopt_id(), call->token_pos()),
+                                           call->deopt_id(), call->source()),
                      call->env(), FlowGraph::kEffect);
         ConstantInstr* constant = flow_graph()->GetConstant(
             Smi::Handle(Z, Smi::New(Smi::Cast(obj).Value() - 1)));
@@ -708,7 +708,7 @@
   if (call->Targets().ReceiverIs(kSmiCid)) {
     InsertBefore(call,
                  new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(),
-                                       call->token_pos()),
+                                       call->source()),
                  call->env(), FlowGraph::kEffect);
     unary_op = new (Z)
         UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id());
@@ -744,8 +744,8 @@
     field = field.CloneFromOriginal();
   }
 
-  switch (flow_graph()->CheckForInstanceCall(call,
-                                             FunctionLayout::kImplicitGetter)) {
+  switch (flow_graph()->CheckForInstanceCall(
+      call, UntaggedFunction::kImplicitGetter)) {
     case FlowGraph::ToCheck::kCheckNull:
       AddCheckNull(call->Receiver(), call->function_name(), call->deopt_id(),
                    call->env(), call);
@@ -771,7 +771,7 @@
   const bool calls_initializer = field.NeedsInitializationCheckOnLoad();
   const Slot& slot = Slot::Get(field, &flow_graph()->parsed_function());
   LoadFieldInstr* load = new (Z) LoadFieldInstr(
-      new (Z) Value(receiver), slot, call->token_pos(), calls_initializer,
+      new (Z) Value(receiver), slot, call->source(), calls_initializer,
       calls_initializer ? call->deopt_id() : DeoptId::kNone);
 
   // Note that this is a case of LoadField -> InstanceCall lazy deopt.
@@ -801,18 +801,21 @@
     return false;
   }
   const Function& target = targets.FirstTarget();
-  if (target.kind() != FunctionLayout::kImplicitSetter) {
+  if (target.kind() != UntaggedFunction::kImplicitSetter) {
     // Non-implicit setter are inlined like normal method calls.
     return false;
   }
+  if (!CompilerState::Current().is_aot() && !target.WasCompiled()) {
+    return false;
+  }
   Field& field = Field::ZoneHandle(Z, target.accessor_field());
   ASSERT(!field.IsNull());
   if (should_clone_fields_) {
     field = field.CloneFromOriginal();
   }
 
-  switch (flow_graph()->CheckForInstanceCall(instr,
-                                             FunctionLayout::kImplicitSetter)) {
+  switch (flow_graph()->CheckForInstanceCall(
+      instr, UntaggedFunction::kImplicitSetter)) {
     case FlowGraph::ToCheck::kCheckNull:
       AddCheckNull(instr->Receiver(), instr->function_name(), instr->deopt_id(),
                    instr->env(), instr);
@@ -839,7 +842,7 @@
     }
   }
 
-  if (I->use_field_guards()) {
+  if (IG->use_field_guards()) {
     if (field.guarded_cid() != kDynamicCid) {
       InsertBefore(instr,
                    new (Z)
@@ -897,10 +900,9 @@
       if (!dst_type.IsInstantiated()) {
         const Class& owner = Class::Handle(Z, field.Owner());
         if (owner.NumTypeArguments() > 0) {
-          instantiator_type_args = new (Z)
-              LoadFieldInstr(new (Z) Value(instr->ArgumentAt(0)),
-                             Slot::GetTypeArgumentsSlotFor(thread(), owner),
-                             instr->token_pos());
+          instantiator_type_args = new (Z) LoadFieldInstr(
+              new (Z) Value(instr->ArgumentAt(0)),
+              Slot::GetTypeArgumentsSlotFor(thread(), owner), instr->source());
           InsertBefore(instr, instantiator_type_args, instr->env(),
                        FlowGraph::kValue);
         }
@@ -909,7 +911,7 @@
       InsertBefore(
           instr,
           new (Z) AssertAssignableInstr(
-              instr->token_pos(), new (Z) Value(instr->ArgumentAt(1)),
+              instr->source(), new (Z) Value(instr->ArgumentAt(1)),
               new (Z) Value(flow_graph_->GetConstant(dst_type)),
               new (Z) Value(instantiator_type_args),
               new (Z) Value(function_type_args),
@@ -922,8 +924,8 @@
   ASSERT(instr->FirstArgIndex() == 0);
   StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
       field, new (Z) Value(instr->ArgumentAt(0)),
-      new (Z) Value(instr->ArgumentAt(1)), kEmitStoreBarrier,
-      instr->token_pos(), &flow_graph()->parsed_function());
+      new (Z) Value(instr->ArgumentAt(1)), kEmitStoreBarrier, instr->source(),
+      &flow_graph()->parsed_function());
 
   // Discard the environment from the original instruction because the store
   // can't deoptimize.
@@ -963,11 +965,14 @@
     return false;
   }
   const Function& target = targets.FirstTarget();
-  if (target.kind() != FunctionLayout::kImplicitGetter) {
+  if (target.kind() != UntaggedFunction::kImplicitGetter) {
     // Non-implicit getters are inlined like normal methods by conventional
     // inlining in FlowGraphInliner.
     return false;
   }
+  if (!CompilerState::Current().is_aot() && !target.WasCompiled()) {
+    return false;
+  }
   return TryInlineImplicitInstanceGetter(call);
 }
 
@@ -982,7 +987,7 @@
     args->Add(new (Z) Value(call->ArgumentAt(i)));
   }
   InvokeMathCFunctionInstr* invoke = new (Z) InvokeMathCFunctionInstr(
-      args, call->deopt_id(), recognized_kind, call->token_pos());
+      args, call->deopt_id(), recognized_kind, call->source());
   ReplaceCall(call, invoke);
 }
 
@@ -1004,7 +1009,7 @@
       AddReceiverCheck(call);
       ReplaceCall(call,
                   new (Z) SmiToDoubleInstr(new (Z) Value(call->ArgumentAt(0)),
-                                           call->token_pos()));
+                                           call->source()));
       return true;
     } else if ((receiver_cid == kMintCid) && CanConvertInt64ToDouble()) {
       AddReceiverCheck(call);
@@ -1097,7 +1102,7 @@
     }
   }
 
-  const ClassTable& class_table = *isolate()->class_table();
+  const ClassTable& class_table = *IG->class_table();
   Bool& prev = Bool::Handle(Z);
   Class& cls = Class::Handle(Z);
 
@@ -1127,14 +1132,14 @@
     results->Add(cls.id());
     results->Add(static_cast<intptr_t>(is_subtype));
     if (prev.IsNull()) {
-      prev = Bool::Get(is_subtype).raw();
+      prev = Bool::Get(is_subtype).ptr();
     } else {
       if (is_subtype != prev.value()) {
         results_differ = true;
       }
     }
   }
-  return results_differ ? Bool::null() : prev.raw();
+  return results_differ ? Bool::null() : prev.ptr();
 }
 
 // Returns true if checking against this type is a direct class id comparison.
@@ -1235,7 +1240,7 @@
   if (type.IsNullType() || (type.IsNeverType() && type.IsLegacy()) ||
       left_value->Type()->IsSubtypeOf(type)) {
     Definition* replacement = new (Z) StrictCompareInstr(
-        call->token_pos(),
+        call->source(),
         (type.IsNullType() || (type.IsNeverType() && type.IsLegacy()))
             ? Token::kEQ_STRICT
             : Token::kNE_STRICT,
@@ -1266,12 +1271,12 @@
     instantiator_type_args = flow_graph()->constant_null();
     function_type_args = flow_graph()->constant_null();
     ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf()));
-    type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw();
+    type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).ptr();
   } else {
     ASSERT(call->ArgumentCount() == 4);
     instantiator_type_args = call->ArgumentAt(1);
     function_type_args = call->ArgumentAt(2);
-    type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw();
+    type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).ptr();
   }
 
   if (TryOptimizeInstanceOfUsingStaticTypes(call, type)) {
@@ -1286,7 +1291,7 @@
         flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(type_cid)));
 
     StrictCompareInstr* check_cid = new (Z) StrictCompareInstr(
-        call->token_pos(), Token::kEQ_STRICT, new (Z) Value(left_cid),
+        call->source(), Token::kEQ_STRICT, new (Z) Value(left_cid),
         new (Z) Value(cid), /* number_check = */ false, DeoptId::kNone);
     ReplaceCall(call, check_cid);
     return;
@@ -1313,7 +1318,7 @@
           return;
         }
         TestCidsInstr* test_cids = new (Z) TestCidsInstr(
-            call->token_pos(), Token::kIS, new (Z) Value(left), *results,
+            call->source(), Token::kIS, new (Z) Value(left), *results,
             can_deopt ? call->deopt_id() : DeoptId::kNone);
         // Remove type.
         ReplaceCall(call, test_cids);
@@ -1332,7 +1337,7 @@
   }
 
   InstanceOfInstr* instance_of = new (Z) InstanceOfInstr(
-      call->token_pos(), new (Z) Value(left),
+      call->source(), new (Z) Value(left),
       new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args),
       type, call->deopt_id());
   ReplaceCall(call, instance_of);
@@ -1388,7 +1393,7 @@
               Definition* arg = call->ArgumentAt(1);
               AddCheckSmi(arg, call->deopt_id(), call->env(), call);
               ReplaceCall(call, new (Z) SmiToDoubleInstr(new (Z) Value(arg),
-                                                         call->token_pos()));
+                                                         call->source()));
               return;
             } else if (binary_feedback.ArgumentIs(kMintCid) &&
                        CanConvertInt64ToDouble()) {
@@ -1455,7 +1460,7 @@
     ZoneGrowableArray<intptr_t>* results,
     const AbstractType& type) {
   ASSERT(results->length() >= 2);  // At least on entry.
-  const ClassTable& class_table = *Isolate::Current()->class_table();
+  const ClassTable& class_table = *IsolateGroup::Current()->class_table();
   if ((*results)[0] != kSmiCid) {
     const Class& smi_class = Class::Handle(class_table.At(kSmiCid));
     const bool smi_is_subtype =
@@ -1562,10 +1567,10 @@
 }
 
 void TypedDataSpecializer::TryInlineCall(TemplateDartCall<0>* call) {
-  const bool is_length_getter = call->Selector() == Symbols::GetLength().raw();
-  const bool is_index_get = call->Selector() == Symbols::IndexToken().raw();
+  const bool is_length_getter = call->Selector() == Symbols::GetLength().ptr();
+  const bool is_index_get = call->Selector() == Symbols::IndexToken().ptr();
   const bool is_index_set =
-      call->Selector() == Symbols::AssignIndexToken().raw();
+      call->Selector() == Symbols::AssignIndexToken().ptr();
 
   if (is_length_getter || is_index_get || is_index_set) {
     EnsureIsInitialized();
@@ -1675,7 +1680,7 @@
                                            Definition** value) {
   auto check =
       new (Z) CheckNullInstr(new (Z) Value(*value), Symbols::OptimizedOut(),
-                             call->deopt_id(), call->token_pos());
+                             call->deopt_id(), call->source());
   flow_graph_->InsertBefore(call, check, call->env(), FlowGraph::kValue);
 
   // Use data dependency as control dependency.
@@ -1686,7 +1691,7 @@
                                              Definition* array,
                                              Definition** index) {
   auto length = new (Z) LoadFieldInstr(
-      new (Z) Value(array), Slot::TypedDataBase_length(), call->token_pos());
+      new (Z) Value(array), Slot::TypedDataBase_length(), call->source());
   flow_graph_->InsertBefore(call, length, call->env(), FlowGraph::kValue);
 
   auto check = new (Z) GenericCheckBoundInstr(
@@ -1700,7 +1705,7 @@
 Definition* TypedDataSpecializer::AppendLoadLength(TemplateDartCall<0>* call,
                                                    Definition* array) {
   auto length = new (Z) LoadFieldInstr(
-      new (Z) Value(array), Slot::TypedDataBase_length(), call->token_pos());
+      new (Z) Value(array), Slot::TypedDataBase_length(), call->source());
   flow_graph_->InsertBefore(call, length, call->env(), FlowGraph::kValue);
   return length;
 }
@@ -1719,7 +1724,7 @@
 
   Definition* load = new (Z) LoadIndexedInstr(
       new (Z) Value(data), new (Z) Value(index), /*index_unboxed=*/false,
-      index_scale, cid, kAlignedAccess, DeoptId::kNone, call->token_pos());
+      index_scale, cid, kAlignedAccess, DeoptId::kNone, call->source());
   flow_graph_->InsertBefore(call, load, call->env(), FlowGraph::kValue);
 
   if (cid == kTypedDataFloat32ArrayCid) {
@@ -1798,7 +1803,7 @@
   auto store = new (Z) StoreIndexedInstr(
       new (Z) Value(data), new (Z) Value(index), new (Z) Value(value),
       kNoStoreBarrier, /*index_unboxed=*/false, index_scale, cid,
-      kAlignedAccess, DeoptId::kNone, call->token_pos(),
+      kAlignedAccess, DeoptId::kNone, call->source(),
       Instruction::kNotSpeculative);
   flow_graph_->InsertBefore(call, store, call->env(), FlowGraph::kEffect);
 }
diff --git a/runtime/vm/compiler/call_specializer.h b/runtime/vm/compiler/call_specializer.h
index 5bb2cb7..ccad4cb 100644
--- a/runtime/vm/compiler/call_specializer.h
+++ b/runtime/vm/compiler/call_specializer.h
@@ -75,6 +75,7 @@
  protected:
   Thread* thread() const { return flow_graph_->thread(); }
   Isolate* isolate() const { return flow_graph_->isolate(); }
+  IsolateGroup* isolate_group() const { return flow_graph_->isolate_group(); }
   Zone* zone() const { return flow_graph_->zone(); }
   const Function& function() const { return flow_graph_->function(); }
 
diff --git a/runtime/vm/compiler/cha.cc b/runtime/vm/compiler/cha.cc
index eed831e..790c237 100644
--- a/runtime/vm/compiler/cha.cc
+++ b/runtime/vm/compiler/cha.cc
@@ -13,11 +13,11 @@
 
 void CHA::AddToGuardedClasses(const Class& cls, intptr_t subclass_count) {
   for (intptr_t i = 0; i < guarded_classes_.length(); i++) {
-    if (guarded_classes_[i].cls->raw() == cls.raw()) {
+    if (guarded_classes_[i].cls->ptr() == cls.ptr()) {
       return;
     }
   }
-  GuardedClassInfo info = {&Class::ZoneHandle(thread_->zone(), cls.raw()),
+  GuardedClassInfo info = {&Class::ZoneHandle(thread_->zone(), cls.ptr()),
                            subclass_count};
   guarded_classes_.Add(info);
   return;
@@ -51,7 +51,7 @@
 }
 
 bool CHA::HasSubclasses(intptr_t cid) const {
-  const ClassTable& class_table = *thread_->isolate()->class_table();
+  const ClassTable& class_table = *thread_->isolate_group()->class_table();
   Class& cls = Class::Handle(thread_->zone(), class_table.At(cid));
   return HasSubclasses(cls);
 }
@@ -84,8 +84,6 @@
 }
 
 bool CHA::IsImplemented(const Class& cls) {
-  // Function type aliases have different type checking rules.
-  ASSERT(!cls.IsTypedefClass());
   // Can't track dependencies for classes on the VM heap since those are
   // read-only.
   // TODO(fschneider): Enable tracking of CHA dependent code for VM heap
diff --git a/runtime/vm/compiler/cha_test.cc b/runtime/vm/compiler/cha_test.cc
index c2c605c..b4ea6ce 100644
--- a/runtime/vm/compiler/cha_test.cc
+++ b/runtime/vm/compiler/cha_test.cc
@@ -99,7 +99,7 @@
   EXPECT(cha.IsGuardedClass(class_d.id()));
 
   const Class& closure_class =
-      Class::Handle(Isolate::Current()->object_store()->closure_class());
+      Class::Handle(IsolateGroup::Current()->object_store()->closure_class());
   EXPECT(!cha.HasSubclasses(closure_class.id()));
 }
 
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 97af823..2a6f91f 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -48,6 +48,31 @@
 
 namespace dart {
 
+CompilerPassState::CompilerPassState(
+    Thread* thread,
+    FlowGraph* flow_graph,
+    SpeculativeInliningPolicy* speculative_policy,
+    Precompiler* precompiler)
+    : thread(thread),
+      precompiler(precompiler),
+      inlining_depth(0),
+      sinking(NULL),
+      call_specializer(NULL),
+      speculative_policy(speculative_policy),
+      reorder_blocks(false),
+      sticky_flags(0),
+      flow_graph_(flow_graph) {
+  // Top scope function is at inlining id 0.
+  inline_id_to_function.Add(&flow_graph->parsed_function().function());
+  // Top scope function has no caller (-1).
+  caller_inline_id.Add(-1);
+  // We do not add a token position for the top scope function to
+  // |inline_id_to_token_pos| because it is not (currently) inlined into
+  // another graph at a given token position. A side effect of this is that
+  // the length of |inline_id_to_function| and |caller_inline_id| is always
+  // larger than the length of |inline_id_to_token_pos| by one.
+}
+
 CompilerPass* CompilerPass::passes_[CompilerPass::kNumPasses] = {NULL};
 
 DEFINE_OPTION_HANDLER(CompilerPass::ParseFilters,
@@ -197,7 +222,8 @@
     }
     PrintGraph(state, kTraceAfter, round);
 #if defined(DEBUG)
-    FlowGraphChecker(state->flow_graph()).Check(name());
+    FlowGraphChecker(state->flow_graph(), state->inline_id_to_function)
+        .Check(name());
 #endif
   }
 }
@@ -263,6 +289,7 @@
   if (FLAG_early_round_trip_serialization) {
     INVOKE_PASS(RoundTripSerialization);
   }
+  INVOKE_PASS(SetOuterInliningId);
   INVOKE_PASS(TypePropagation);
   INVOKE_PASS(Canonicalize);
   INVOKE_PASS(BranchSimplify);
diff --git a/runtime/vm/compiler/compiler_pass.h b/runtime/vm/compiler/compiler_pass.h
index 2897609..1904561 100644
--- a/runtime/vm/compiler/compiler_pass.h
+++ b/runtime/vm/compiler/compiler_pass.h
@@ -69,16 +69,7 @@
   CompilerPassState(Thread* thread,
                     FlowGraph* flow_graph,
                     SpeculativeInliningPolicy* speculative_policy,
-                    Precompiler* precompiler = NULL)
-      : thread(thread),
-        precompiler(precompiler),
-        inlining_depth(0),
-        sinking(NULL),
-        call_specializer(NULL),
-        speculative_policy(speculative_policy),
-        reorder_blocks(false),
-        sticky_flags(0),
-        flow_graph_(flow_graph) {}
+                    Precompiler* precompiler = NULL);
 
   FlowGraph* flow_graph() const { return flow_graph_; }
 
diff --git a/runtime/vm/compiler/compiler_state.cc b/runtime/vm/compiler/compiler_state.cc
index ed8dc49..38d4932 100644
--- a/runtime/vm/compiler/compiler_state.cc
+++ b/runtime/vm/compiler/compiler_state.cc
@@ -85,7 +85,7 @@
     // When obfuscation is enabled we need to obfuscate the name of the
     // class before looking it up.
     String& name = String::Handle(zone, Symbols::New(thread, "Comparable"));
-    if (thread->isolate()->obfuscate()) {
+    if (thread->isolate_group()->obfuscate()) {
       Obfuscator obfuscator(thread, Object::null_string());
       name = obfuscator.Rename(name);
     }
diff --git a/runtime/vm/compiler/compiler_state.h b/runtime/vm/compiler/compiler_state.h
index 913e36b..a200ea9 100644
--- a/runtime/vm/compiler/compiler_state.h
+++ b/runtime/vm/compiler/compiler_state.h
@@ -32,10 +32,12 @@
  public:
   CompilerState(Thread* thread,
                 bool is_aot,
+                bool is_optimizing,
                 CompilerTracing tracing = CompilerTracing::kOn)
       : ThreadStackResource(thread),
         cha_(thread),
         is_aot_(is_aot),
+        is_optimizing_(is_optimizing),
         tracing_(tracing) {
     previous_ = thread->SetCompilerState(this);
   }
@@ -82,6 +84,11 @@
 
   bool is_aot() const { return is_aot_; }
 
+  bool is_optimizing() const { return is_optimizing_; }
+  bool should_clone_fields() {
+    return !is_aot() && (is_optimizing() || FLAG_force_clone_compiler_objects);
+  }
+
   bool should_trace() const { return tracing_ == CompilerTracing::kOn; }
 
   static bool ShouldTrace() { return Current().should_trace(); }
@@ -103,6 +110,7 @@
   ZoneGrowableArray<LocalVariable*>* dummy_captured_vars_ = nullptr;
 
   const bool is_aot_;
+  const bool is_optimizing_;
 
   const CompilerTracing tracing_;
 
diff --git a/runtime/vm/compiler/ffi/call.cc b/runtime/vm/compiler/ffi/call.cc
index 39402f5..1735a69 100644
--- a/runtime/vm/compiler/ffi/call.cc
+++ b/runtime/vm/compiler/ffi/call.cc
@@ -14,51 +14,47 @@
 namespace ffi {
 
 // TODO(dartbug.com/36607): Cache the trampolines.
-FunctionPtr TrampolineFunction(const Function& dart_signature,
-                               const Function& c_signature) {
+FunctionPtr TrampolineFunction(const FunctionType& dart_signature,
+                               const FunctionType& c_signature) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   String& name = String::Handle(zone, Symbols::New(thread, "FfiTrampoline"));
   const Library& lib = Library::Handle(zone, Library::FfiLibrary());
   const Class& owner_class = Class::Handle(zone, lib.toplevel_class());
-  Function& function =
-      Function::Handle(zone, Function::New(name, FunctionLayout::kFfiTrampoline,
-                                           /*is_static=*/true,
-                                           /*is_const=*/false,
-                                           /*is_abstract=*/false,
-                                           /*is_external=*/false,
-                                           /*is_native=*/false, owner_class,
-                                           TokenPosition::kMinSource));
+  FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
+  Function& function = Function::Handle(
+      zone, Function::New(signature, name, UntaggedFunction::kFfiTrampoline,
+                          /*is_static=*/true,
+                          /*is_const=*/false,
+                          /*is_abstract=*/false,
+                          /*is_external=*/false,
+                          /*is_native=*/false, owner_class,
+                          TokenPosition::kMinSource));
   function.set_is_debuggable(false);
   function.set_num_fixed_parameters(dart_signature.num_fixed_parameters());
-  function.set_result_type(
+  signature.set_result_type(
       AbstractType::Handle(zone, dart_signature.result_type()));
-  function.set_parameter_types(
+  signature.set_parameter_types(
       Array::Handle(zone, dart_signature.parameter_types()));
 
   // The signature function won't have any names for the parameters. We need to
   // assign unique names for scope building and error messages.
-  function.CreateNameArrayIncludingFlags(Heap::kNew);
+  signature.CreateNameArrayIncludingFlags(Heap::kOld);
   const intptr_t num_params = dart_signature.num_fixed_parameters();
   for (intptr_t i = 0; i < num_params; ++i) {
     if (i == 0) {
-      name = Symbols::ClosureParameter().raw();
+      name = Symbols::ClosureParameter().ptr();
     } else {
       name = Symbols::NewFormatted(thread, ":ffi_param%" Pd, i);
     }
-    function.SetParameterNameAt(i, name);
+    signature.SetParameterNameAt(i, name);
   }
-  function.TruncateUnusedParameterFlags();
+  signature.FinalizeNameArrays(function);
   function.SetFfiCSignature(c_signature);
+  signature ^= ClassFinalizer::FinalizeType(signature);
+  function.set_signature(signature);
 
-  Type& type = Type::Handle(zone);
-  type ^= function.SignatureType(Nullability::kLegacy);
-  type ^= ClassFinalizer::FinalizeType(type);
-  function.SetSignatureType(type);
-  ASSERT(
-      Type::Handle(function.SignatureType(Nullability::kLegacy)).IsFinalized());
-
-  return function.raw();
+  return function.ptr();
 }
 
 }  // namespace ffi
diff --git a/runtime/vm/compiler/ffi/call.h b/runtime/vm/compiler/ffi/call.h
index 050b1d8..5a4e5f0 100644
--- a/runtime/vm/compiler/ffi/call.h
+++ b/runtime/vm/compiler/ffi/call.h
@@ -19,8 +19,8 @@
 
 namespace ffi {
 
-FunctionPtr TrampolineFunction(const Function& dart_signature,
-                               const Function& c_signature);
+FunctionPtr TrampolineFunction(const FunctionType& dart_signature,
+                               const FunctionType& c_signature);
 
 }  // namespace ffi
 
diff --git a/runtime/vm/compiler/ffi/callback.cc b/runtime/vm/compiler/ffi/callback.cc
index 8d1fe95..c38f9d6 100644
--- a/runtime/vm/compiler/ffi/callback.cc
+++ b/runtime/vm/compiler/ffi/callback.cc
@@ -4,6 +4,7 @@
 
 #include "vm/compiler/ffi/callback.h"
 
+#include "vm/class_finalizer.h"
 #include "vm/symbols.h"
 
 namespace dart {
@@ -12,7 +13,7 @@
 
 namespace ffi {
 
-FunctionPtr NativeCallbackFunction(const Function& c_signature,
+FunctionPtr NativeCallbackFunction(const FunctionType& c_signature,
                                    const Function& dart_target,
                                    const Instance& exceptional_return) {
   Thread* const thread = Thread::Current();
@@ -20,7 +21,7 @@
 
   // Create a new Function named '<target>_FfiCallback' and stick it in the
   // 'dart:ffi' library. Note that these functions will never be invoked by
-  // Dart, so they have may have duplicate names.
+  // Dart, so they may have duplicate names.
   Zone* const zone = thread->zone();
   const auto& name = String::Handle(
       zone, Symbols::FromConcat(thread, Symbols::FfiCallback(),
@@ -28,7 +29,8 @@
   const Library& lib = Library::Handle(zone, Library::FfiLibrary());
   const Class& owner_class = Class::Handle(zone, lib.toplevel_class());
   const Function& function =
-      Function::Handle(zone, Function::New(name, FunctionLayout::kFfiTrampoline,
+      Function::Handle(zone, Function::New(Object::null_function_type(), name,
+                                           UntaggedFunction::kFfiTrampoline,
                                            /*is_static=*/true,
                                            /*is_const=*/false,
                                            /*is_abstract=*/false,
@@ -50,9 +52,6 @@
   //
   // Exceptional return values currently cannot be pointers because we don't
   // have constant pointers.
-  //
-  // TODO(36730): We'll need to extend this when we support passing/returning
-  // structs by value.
   ASSERT(exceptional_return.IsNull() || exceptional_return.IsNumber());
   if (!exceptional_return.IsSmi() && exceptional_return.IsNew()) {
     function.SetFfiCallbackExceptionalReturn(Instance::Handle(
@@ -61,7 +60,7 @@
     function.SetFfiCallbackExceptionalReturn(exceptional_return);
   }
 
-  return function.raw();
+  return function.ptr();
 }
 
 }  // namespace ffi
diff --git a/runtime/vm/compiler/ffi/callback.h b/runtime/vm/compiler/ffi/callback.h
index 265143e..37a4967 100644
--- a/runtime/vm/compiler/ffi/callback.h
+++ b/runtime/vm/compiler/ffi/callback.h
@@ -19,7 +19,7 @@
 
 namespace ffi {
 
-FunctionPtr NativeCallbackFunction(const Function& c_signature,
+FunctionPtr NativeCallbackFunction(const FunctionType& c_signature,
                                    const Function& dart_target,
                                    const Instance& exceptional_return);
 
diff --git a/runtime/vm/compiler/ffi/marshaller.cc b/runtime/vm/compiler/ffi/marshaller.cc
index 6620468..480f045 100644
--- a/runtime/vm/compiler/ffi/marshaller.cc
+++ b/runtime/vm/compiler/ffi/marshaller.cc
@@ -27,7 +27,7 @@
 // Representations of the arguments and return value of a C signature function.
 static const NativeFunctionType& NativeFunctionSignature(
     Zone* zone,
-    const Function& c_signature) {
+    const FunctionType& c_signature) {
   ASSERT(c_signature.NumOptionalParameters() == 0);
   ASSERT(c_signature.NumOptionalPositionalParameters() == 0);
 
@@ -55,7 +55,8 @@
 BaseMarshaller::BaseMarshaller(Zone* zone, const Function& dart_signature)
     : zone_(zone),
       dart_signature_(dart_signature),
-      c_signature_(Function::ZoneHandle(zone, dart_signature.FfiCSignature())),
+      c_signature_(
+          FunctionType::ZoneHandle(zone, dart_signature.FfiCSignature())),
       native_calling_convention_(NativeCallingConvention::FromSignature(
           zone,
           NativeFunctionSignature(zone_, c_signature_))) {
@@ -75,11 +76,224 @@
   return dart_signature_.FfiCSignatureContainsHandles();
 }
 
-Location CallMarshaller::LocInFfiCall(intptr_t arg_index) const {
-  if (arg_index == kResultIndex) {
-    return Location(arg_index).AsLocation();
+intptr_t BaseMarshaller::NumDefinitions() const {
+  intptr_t total = 0;
+  for (intptr_t i = 0; i < num_args(); i++) {
+    total += NumDefinitions(i);
+  }
+  return total;
+}
+
+intptr_t BaseMarshaller::NumDefinitions(intptr_t arg_index) const {
+  if (ArgumentIndexIsReturn(arg_index)) {
+    return NumReturnDefinitions();
   }
 
+  const auto& loc = Location(arg_index);
+  const auto& type = loc.payload_type();
+
+  if (type.IsPrimitive()) {
+    // All non-struct arguments are 1 definition in IL. Even 64 bit values
+    // on 32 bit architectures.
+    return 1;
+  }
+
+  ASSERT(type.IsCompound());
+  if (loc.IsMultiple()) {
+    // One IL definition for every nested location.
+    const auto& multiple = loc.AsMultiple();
+    return multiple.locations().length();
+  }
+
+  if (loc.IsPointerToMemory()) {
+    // For FFI calls, pass in TypedDataBase (1 IL definition) in IL, and copy
+    // contents to stack and pass pointer in right location in MC.
+    // For FFI callbacks, get the pointer in a NativeParameter and construct
+    // the TypedDataBase in IL.
+    return 1;
+  }
+
+  ASSERT(loc.IsStack());
+  // For stack, word size definitions in IL. In FFI calls passed in to the
+  // native call, in FFI callbacks read in separate NativeParams.
+  const intptr_t size_in_bytes = type.SizeInBytes();
+  const intptr_t num_defs =
+      Utils::RoundUp(size_in_bytes, compiler::target::kWordSize) /
+      compiler::target::kWordSize;
+  return num_defs;
+}
+
+intptr_t BaseMarshaller::NumReturnDefinitions() const {
+  // For FFI calls we always have 1 definition, because the IL instruction can
+  // only be 1 definition. We pass in a TypedDataBase in IL and fill it in
+  // machine code.
+  //
+  // For FFI callbacks we always have 1 definition. If it's a struct and the
+  // native ABI is passing a pointer, we copy to it in IL. If it's a multiple
+  // locations return value we copy the value in machine code because some
+  // native locations cannot be expressed in IL in Location.
+  return 1;
+}
+
+bool BaseMarshaller::ArgumentIndexIsReturn(intptr_t arg_index) const {
+  ASSERT(arg_index == kResultIndex || arg_index >= 0);
+  return arg_index == kResultIndex;
+}
+
+// Definitions in return value count down.
+bool BaseMarshaller::DefinitionIndexIsReturn(intptr_t def_index_global) const {
+  return def_index_global <= kResultIndex;
+}
+
+intptr_t BaseMarshaller::ArgumentIndex(intptr_t def_index_global) const {
+  if (DefinitionIndexIsReturn(def_index_global)) {
+    const intptr_t def = DefinitionInArgument(def_index_global, kResultIndex);
+    ASSERT(def < NumReturnDefinitions());
+    return kResultIndex;
+  }
+  ASSERT(def_index_global < NumDefinitions());
+  intptr_t defs = 0;
+  intptr_t arg_index = 0;
+  for (; arg_index < num_args(); arg_index++) {
+    defs += NumDefinitions(arg_index);
+    if (defs > def_index_global) {
+      return arg_index;
+    }
+  }
+  UNREACHABLE();
+}
+
+intptr_t BaseMarshaller::FirstDefinitionIndex(intptr_t arg_index) const {
+  if (arg_index <= kResultIndex) {
+    return kResultIndex;
+  }
+  ASSERT(arg_index < num_args());
+  intptr_t num_defs = 0;
+  for (intptr_t i = 0; i < arg_index; i++) {
+    num_defs += NumDefinitions(i);
+  }
+  return num_defs;
+}
+
+intptr_t BaseMarshaller::DefinitionInArgument(intptr_t def_index_global,
+                                              intptr_t arg_index) const {
+  if (ArgumentIndexIsReturn(arg_index)) {
+    // Counting down for return definitions.
+    const intptr_t def = kResultIndex - def_index_global;
+    ASSERT(def < NumReturnDefinitions());
+    return def;
+  } else {
+    // Counting up for arguments in consecutive order.
+    const intptr_t def = def_index_global - FirstDefinitionIndex(arg_index);
+    ASSERT(def < NumDefinitions());
+    return def;
+  }
+}
+
+intptr_t BaseMarshaller::DefinitionIndex(intptr_t def_index_in_arg,
+                                         intptr_t arg_index) const {
+  ASSERT(def_index_in_arg < NumDefinitions(arg_index));
+  if (ArgumentIndexIsReturn(arg_index)) {
+    return kResultIndex - def_index_in_arg;
+  } else {
+    return FirstDefinitionIndex(arg_index) + def_index_in_arg;
+  }
+}
+
+static Representation SelectRepresentationInIL(Zone* zone,
+                                               const NativeLocation& location) {
+  if (location.container_type().IsInt() && location.payload_type().IsFloat()) {
+    // IL can only pass integers to integer Locations, so pass as integer if
+    // the Location requires it to be an integer.
+    return location.container_type().AsRepresentationOverApprox(zone);
+  }
+  // Representations do not support 8 or 16 bit ints, over approximate to 32
+  // bits.
+  return location.payload_type().AsRepresentationOverApprox(zone);
+}
+
+// Implemented partially in BaseMarshaller because most Representations are
+// the same in Calls and Callbacks.
+Representation BaseMarshaller::RepInFfiCall(intptr_t def_index_global) const {
+  intptr_t arg_index = ArgumentIndex(def_index_global);
+  const auto& location = Location(arg_index);
+
+  if (location.container_type().IsPrimitive()) {
+    return SelectRepresentationInIL(zone_, location);
+  }
+  ASSERT(location.container_type().IsCompound());
+
+  if (location.IsStack()) {
+    // Split the struct in architecture size chunks.
+    return compiler::target::kWordSize == 8 ? Representation::kUnboxedInt64
+                                            : Representation::kUnboxedInt32;
+  }
+
+  if (location.IsMultiple()) {
+    const intptr_t def_index_in_arg =
+        DefinitionInArgument(def_index_global, arg_index);
+    const auto& def_loc =
+        *(location.AsMultiple().locations()[def_index_in_arg]);
+    return SelectRepresentationInIL(zone_, def_loc);
+  }
+
+  ASSERT(location.IsPointerToMemory());
+  UNREACHABLE();  // Implemented in subclasses.
+}
+
+Representation CallMarshaller::RepInFfiCall(intptr_t def_index_global) const {
+  intptr_t arg_index = ArgumentIndex(def_index_global);
+  const auto& location = Location(arg_index);
+  if (location.IsPointerToMemory()) {
+    if (ArgumentIndexIsReturn(arg_index)) {
+      // The IL type is the unboxed pointer.
+      const auto& pointer_location = location.AsPointerToMemory();
+      const auto& rep = pointer_location.pointer_location().payload_type();
+      ASSERT(rep.Equals(
+          pointer_location.pointer_return_location().payload_type()));
+      return rep.AsRepresentation();
+    } else {
+      // We're passing Pointer/TypedData object, the GC might move TypedData so
+      // we can't load the address from it eagerly.
+      return kTagged;
+    }
+  }
+  return BaseMarshaller::RepInFfiCall(def_index_global);
+}
+
+Representation CallbackMarshaller::RepInFfiCall(
+    intptr_t def_index_global) const {
+  intptr_t arg_index = ArgumentIndex(def_index_global);
+  const auto& location = Location(arg_index);
+  if (location.IsPointerToMemory()) {
+    // The IL type is the unboxed pointer, and FFI callback return. In the
+    // latter we've already copied the data into the result location in IL.
+    const auto& pointer_location = location.AsPointerToMemory();
+    const auto& rep = pointer_location.pointer_location().payload_type();
+    ASSERT(
+        rep.Equals(pointer_location.pointer_return_location().payload_type()));
+    return rep.AsRepresentation();
+  }
+  if (ArgumentIndexIsReturn(arg_index) && location.IsMultiple()) {
+    // We're passing a TypedData.
+    return Representation::kTagged;
+  }
+  return BaseMarshaller::RepInFfiCall(def_index_global);
+}
+
+void BaseMarshaller::RepsInFfiCall(intptr_t arg_index,
+                                   GrowableArray<Representation>* out) const {
+  const intptr_t num_definitions = NumDefinitions(arg_index);
+  const intptr_t first_def = FirstDefinitionIndex(arg_index);
+  for (int i = 0; i < num_definitions; i++) {
+    out->Add(RepInFfiCall(first_def + i));
+  }
+}
+
+// Helper method for `LocInFfiCall` to turn a stack location into either any
+// location or a pair of two any locations.
+static Location ConvertToAnyLocation(const NativeStackLocation& loc,
+                                     Representation rep_in_ffi_call) {
   // Floating point values are never split: they are either in a single "FPU"
   // register or a contiguous 64-bit slot on the stack. Unboxed 64-bit integer
   // values, in contrast, can be split between any two registers on a 32-bit
@@ -90,33 +304,149 @@
   // convention is concerned. However, the representation of these arguments
   // are set to kUnboxedInt32 or kUnboxedInt64 already, so we don't have to
   // account for that here.
-  const bool is_atomic = RepInFfiCall(arg_index) == kUnboxedDouble ||
-                         RepInFfiCall(arg_index) == kUnboxedFloat;
+  const bool is_atomic =
+      rep_in_ffi_call == kUnboxedDouble || rep_in_ffi_call == kUnboxedFloat;
 
-  const NativeLocation& loc = this->Location(arg_index);
-  // Don't pin stack locations, they need to be moved anyway.
-  if (loc.IsStack()) {
-    if (loc.payload_type().SizeInBytes() == 2 * compiler::target::kWordSize &&
-        !is_atomic) {
-      return Location::Pair(Location::Any(), Location::Any());
-    }
-    return Location::Any();
+  if (loc.payload_type().IsPrimitive() &&
+      loc.payload_type().SizeInBytes() == 2 * compiler::target::kWordSize &&
+      !is_atomic) {
+    return Location::Pair(Location::Any(), Location::Any());
   }
+  return Location::Any();
+}
 
+static Location SelectFpuLocationInIL(Zone* zone,
+                                      const NativeLocation& location) {
+  ASSERT((location.IsFpuRegisters()));
 #if defined(TARGET_ARCH_ARM)
   // Only pin FPU register if it is the lowest bits.
-  if (loc.IsFpuRegisters()) {
-    const auto& fpu_loc = loc.AsFpuRegisters();
-    if (fpu_loc.IsLowestBits()) {
-      return fpu_loc.WidenToQFpuRegister(zone_).AsLocation();
-    }
-    return Location::Any();
+  const auto& fpu_loc = location.AsFpuRegisters();
+  if (fpu_loc.IsLowestBits()) {
+    return fpu_loc.WidenToQFpuRegister(zone).AsLocation();
   }
+  return Location::Any();
 #endif  // defined(TARGET_ARCH_ARM)
 
+  return location.AsLocation();
+}
+
+Location CallMarshaller::LocInFfiCall(intptr_t def_index_global) const {
+  const intptr_t arg_index = ArgumentIndex(def_index_global);
+  const NativeLocation& loc = this->Location(arg_index);
+
+  if (ArgumentIndexIsReturn(arg_index)) {
+    const intptr_t def = kResultIndex - def_index_global;
+    if (loc.IsMultiple()) {
+      ASSERT(loc.AsMultiple().locations()[def]->IsExpressibleAsLocation());
+      return loc.AsMultiple().locations()[def]->AsLocation();
+    }
+
+    if (loc.IsPointerToMemory()) {
+      // No location at all, because we store into TypedData passed to the
+      // FfiCall instruction. But we have to supply a location.
+      return Location::RegisterLocation(CallingConventions::kReturnReg);
+    }
+
+    return loc.AsLocation();
+  }
+
+  if (loc.IsMultiple()) {
+    const intptr_t def_index_in_arg =
+        def_index_global - FirstDefinitionIndex(arg_index);
+    const auto& def_loc = *(loc.AsMultiple().locations()[def_index_in_arg]);
+    if (def_loc.IsStack()) {
+      // Don't pin stack locations, they need to be moved anyway.
+      return ConvertToAnyLocation(def_loc.AsStack(),
+                                  RepInFfiCall(def_index_global));
+    }
+
+    if (def_loc.IsFpuRegisters()) {
+      return SelectFpuLocationInIL(zone_, def_loc);
+    }
+
+    return def_loc.AsLocation();
+  }
+
+  if (loc.IsPointerToMemory()) {
+    const auto& pointer_location = loc.AsPointerToMemory().pointer_location();
+    if (pointer_location.IsStack()) {
+      // Don't pin stack locations, they need to be moved anyway.
+      return ConvertToAnyLocation(pointer_location.AsStack(),
+                                  RepInFfiCall(def_index_global));
+    }
+    return pointer_location.AsLocation();
+  }
+
+  if (loc.IsStack()) {
+    return ConvertToAnyLocation(loc.AsStack(), RepInFfiCall(def_index_global));
+  }
+
+  if (loc.IsFpuRegisters()) {
+    return SelectFpuLocationInIL(zone_, loc);
+  }
+
+  ASSERT(loc.IsRegisters());
   return loc.AsLocation();
 }
 
+bool CallMarshaller::PassTypedData() const {
+  return IsStruct(compiler::ffi::kResultIndex);
+}
+
+intptr_t CallMarshaller::TypedDataSizeInBytes() const {
+  ASSERT(PassTypedData());
+  return Utils::RoundUp(
+      Location(compiler::ffi::kResultIndex).payload_type().SizeInBytes(),
+      compiler::target::kWordSize);
+}
+
+// Const to be able to look up the `RequiredStackSpaceInBytes` in
+// `PassByPointerStackOffset`.
+const intptr_t kAfterLastArgumentIndex = kIntptrMax;
+
+intptr_t CallMarshaller::PassByPointerStackOffset(intptr_t arg_index) const {
+  ASSERT(arg_index == kResultIndex ||
+         (arg_index >= 0 && arg_index < num_args()) ||
+         arg_index == kAfterLastArgumentIndex);
+
+  intptr_t stack_offset = 0;
+
+  // First the native arguments are on the stack.
+  // This is governed by the native ABI, the rest we can chose freely.
+  stack_offset += native_calling_convention_.StackTopInBytes();
+  stack_offset = Utils::RoundUp(stack_offset, compiler::target::kWordSize);
+  if (arg_index == kResultIndex) {
+    return stack_offset;
+  }
+
+  // Then save space for the result.
+  const auto& result_location = Location(compiler::ffi::kResultIndex);
+  if (result_location.IsPointerToMemory()) {
+    stack_offset += result_location.payload_type().SizeInBytes();
+    stack_offset = Utils::RoundUp(stack_offset, compiler::target::kWordSize);
+  }
+
+  // And finally put the arguments on the stack that are passed by pointer.
+  for (int i = 0; i < num_args(); i++) {
+    if (arg_index == i) {
+      return stack_offset;
+    }
+    const auto& arg_location = Location(i);
+    if (arg_location.IsPointerToMemory()) {
+      stack_offset += arg_location.payload_type().SizeInBytes();
+      stack_offset = Utils::RoundUp(stack_offset, compiler::target::kWordSize);
+    }
+  }
+
+  // The total stack space we need.
+  ASSERT(arg_index == kAfterLastArgumentIndex);
+  return stack_offset;
+}
+
+intptr_t CallMarshaller::RequiredStackSpaceInBytes() const {
+  return PassByPointerStackOffset(kAfterLastArgumentIndex);
+}
+
 // This classes translates the ABI location of arguments into the locations they
 // will inhabit after entry-frame setup in the invocation of a native callback.
 //
@@ -133,15 +463,26 @@
  public:
   static NativeLocations& TranslateArgumentLocations(
       Zone* zone,
-      const NativeLocations& arg_locs) {
-    auto& pushed_locs = *(new (zone) NativeLocations(arg_locs.length()));
+      const NativeLocations& argument_locations,
+      const NativeLocation& return_loc) {
+    const bool treat_return_loc = return_loc.IsPointerToMemory();
+
+    auto& pushed_locs = *(new (zone) NativeLocations(
+        argument_locations.length() + (treat_return_loc ? 1 : 0)));
 
     CallbackArgumentTranslator translator;
-    for (intptr_t i = 0, n = arg_locs.length(); i < n; i++) {
-      translator.AllocateArgument(*arg_locs[i]);
+    for (intptr_t i = 0, n = argument_locations.length(); i < n; i++) {
+      translator.AllocateArgument(*argument_locations[i]);
     }
-    for (intptr_t i = 0, n = arg_locs.length(); i < n; ++i) {
-      pushed_locs.Add(&translator.TranslateArgument(zone, *arg_locs[i]));
+    if (treat_return_loc) {
+      translator.AllocateArgument(return_loc);
+    }
+    for (intptr_t i = 0, n = argument_locations.length(); i < n; ++i) {
+      pushed_locs.Add(
+          &translator.TranslateArgument(zone, *argument_locations[i]));
+    }
+    if (treat_return_loc) {
+      pushed_locs.Add(&translator.TranslateArgument(zone, return_loc));
     }
 
     return pushed_locs;
@@ -155,8 +496,16 @@
       argument_slots_required_ += arg.AsRegisters().num_regs();
     } else if (arg.IsFpuRegisters()) {
       argument_slots_required_ += 8 / target::kWordSize;
+    } else if (arg.IsPointerToMemory()) {
+      if (arg.AsPointerToMemory().pointer_location().IsRegisters()) {
+        argument_slots_required_ += 1;
+      }
     } else {
-      UNREACHABLE();
+      ASSERT(arg.IsMultiple());
+      const auto& multiple = arg.AsMultiple();
+      for (intptr_t i = 0; i < multiple.locations().length(); i++) {
+        AllocateArgument(*multiple.locations().At(i));
+      }
     }
   }
 
@@ -192,12 +541,33 @@
       return result;
     }
 
-    ASSERT(arg.IsFpuRegisters());
-    const auto& result = *new (zone) NativeStackLocation(
-        arg.payload_type(), arg.container_type(), SPREG,
-        argument_slots_used_ * compiler::target::kWordSize);
-    argument_slots_used_ += 8 / target::kWordSize;
-    return result;
+    if (arg.IsFpuRegisters()) {
+      const auto& result = *new (zone) NativeStackLocation(
+          arg.payload_type(), arg.container_type(), SPREG,
+          argument_slots_used_ * compiler::target::kWordSize);
+      argument_slots_used_ += 8 / target::kWordSize;
+      return result;
+    }
+
+    if (arg.IsPointerToMemory()) {
+      const auto& pointer_loc = arg.AsPointerToMemory().pointer_location();
+      const auto& pointer_ret_loc =
+          arg.AsPointerToMemory().pointer_return_location();
+      const auto& pointer_translated = TranslateArgument(zone, pointer_loc);
+      return *new (zone) PointerToMemoryLocation(
+          pointer_translated, pointer_ret_loc, arg.payload_type().AsCompound());
+    }
+
+    ASSERT(arg.IsMultiple());
+    const auto& multiple = arg.AsMultiple();
+    NativeLocations& multiple_locations =
+        *new (zone) NativeLocations(multiple.locations().length());
+    for (intptr_t i = 0; i < multiple.locations().length(); i++) {
+      multiple_locations.Add(
+          &TranslateArgument(zone, *multiple.locations().At(i)));
+    }
+    return *new (zone) MultipleNativeLocations(
+        multiple.payload_type().AsCompound(), multiple_locations);
   }
 
   intptr_t argument_slots_used_ = 0;
@@ -209,7 +579,46 @@
     : BaseMarshaller(zone, dart_signature),
       callback_locs_(CallbackArgumentTranslator::TranslateArgumentLocations(
           zone_,
-          native_calling_convention_.argument_locations())) {}
+          native_calling_convention_.argument_locations(),
+          native_calling_convention_.return_location())) {}
+
+const NativeLocation& CallbackMarshaller::NativeLocationOfNativeParameter(
+    intptr_t def_index) const {
+  const intptr_t arg_index = ArgumentIndex(def_index);
+  if (arg_index == kResultIndex) {
+    const auto& result_loc = Location(arg_index);
+    if (result_loc.IsPointerToMemory()) {
+      // If it's a pointer we return it in the last.
+      return *callback_locs_.At(callback_locs_.length() - 1);
+    }
+    // The other return types are not translated.
+    return result_loc;
+  }
+
+  // Check that we only have stack arguments.
+  const auto& loc = *callback_locs_.At(arg_index);
+  ASSERT(loc.IsStack() || loc.IsPointerToMemory() || loc.IsMultiple());
+  if (loc.IsStack()) {
+    ASSERT(loc.AsStack().base_register() == SPREG);
+    if (loc.payload_type().IsPrimitive()) {
+      return loc;
+    }
+    const intptr_t index = DefinitionInArgument(def_index, arg_index);
+    const intptr_t count = NumDefinitions(arg_index);
+    return loc.Split(zone_, count, index);
+  } else if (loc.IsPointerToMemory()) {
+    const auto& pointer_loc = loc.AsPointerToMemory().pointer_location();
+    ASSERT(pointer_loc.IsStack() &&
+           pointer_loc.AsStack().base_register() == SPREG);
+    return loc;
+  }
+  const auto& multiple = loc.AsMultiple();
+  const intptr_t index = DefinitionInArgument(def_index, arg_index);
+  const auto& multi_loc = *multiple.locations().At(index);
+  ASSERT(multi_loc.IsStack() && multi_loc.AsStack().base_register() == SPREG);
+  return multi_loc;
+}
+
 }  // namespace ffi
 
 }  // namespace compiler
diff --git a/runtime/vm/compiler/ffi/marshaller.h b/runtime/vm/compiler/ffi/marshaller.h
index be567b6..657817e 100644
--- a/runtime/vm/compiler/ffi/marshaller.h
+++ b/runtime/vm/compiler/ffi/marshaller.h
@@ -39,9 +39,27 @@
     return native_calling_convention_.argument_locations().length();
   }
 
-  intptr_t StackTopInBytes() const {
-    return native_calling_convention_.StackTopInBytes();
-  }
+  // Number of definitions passed to FfiCall, number of NativeParams, or number
+  // of definitions passed to NativeReturn in IL.
+  //
+  // All non-struct values have 1 definition, struct values can have either 1
+  // or multiple definitions. If a struct has multiple definitions, they either
+  // correspond to the number of native locations in the native ABI or to word-
+  // sized chunks.
+  //
+  // `arg_index` is the index of an argument.
+  // `def_index_in_argument` is the definition in one argument.
+  // `def_index_global` is the index of the definition in all arguments.
+  intptr_t NumDefinitions() const;
+  intptr_t NumDefinitions(intptr_t arg_index) const;
+  intptr_t NumReturnDefinitions() const;
+  bool ArgumentIndexIsReturn(intptr_t arg_index) const;
+  bool DefinitionIndexIsReturn(intptr_t def_index_global) const;
+  intptr_t ArgumentIndex(intptr_t def_index_global) const;
+  intptr_t FirstDefinitionIndex(intptr_t arg_index) const;
+  intptr_t DefinitionInArgument(intptr_t def_index_global,
+                                intptr_t arg_index) const;
+  intptr_t DefinitionIndex(intptr_t def_index_in_arg, intptr_t arg_index) const;
 
   // The location of the argument at `arg_index`.
   const NativeLocation& Location(intptr_t arg_index) const {
@@ -53,20 +71,18 @@
 
   // Unboxed representation on how the value is passed or received from regular
   // Dart code.
+  //
+  // Implemented in BaseMarshaller because most Representations are the same
+  // in Calls and Callbacks.
   Representation RepInDart(intptr_t arg_index) const {
     return Location(arg_index).payload_type().AsRepresentationOverApprox(zone_);
   }
 
   // Representation on how the value is passed to or recieved from the FfiCall
   // instruction or StaticCall, NativeParameter, and NativeReturn instructions.
-  Representation RepInFfiCall(intptr_t arg_index) const {
-    if (Location(arg_index).container_type().IsInt() &&
-        Location(arg_index).payload_type().IsFloat()) {
-      return Location(arg_index).container_type().AsRepresentationOverApprox(
-          zone_);
-    }
-    return Location(arg_index).payload_type().AsRepresentationOverApprox(zone_);
-  }
+  virtual Representation RepInFfiCall(intptr_t def_index_global) const;
+  void RepsInFfiCall(intptr_t arg_index,
+                     GrowableArray<Representation>* out) const;
 
   // Bitcasting floats to ints, only required in SoftFP.
   bool RequiresBitCast(intptr_t index) const {
@@ -94,6 +110,12 @@
            kFfiHandleCid;
   }
 
+  bool IsStruct(intptr_t arg_index) const {
+    const auto& type = AbstractType::Handle(zone_, CType(arg_index));
+    const bool predefined = IsFfiTypeClassId(type.type_class_id());
+    return !predefined;
+  }
+
   // Treated as a null constant in Dart.
   bool IsVoid(intptr_t arg_index) const {
     return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
@@ -113,7 +135,7 @@
   // Contains the function pointer as argument #0.
   // The Dart signature is used for the function and argument names.
   const Function& dart_signature_;
-  const Function& c_signature_;
+  const FunctionType& c_signature_;
   const NativeCallingConvention& native_calling_convention_;
 };
 
@@ -122,7 +144,24 @@
   CallMarshaller(Zone* zone, const Function& dart_signature)
       : BaseMarshaller(zone, dart_signature) {}
 
-  dart::Location LocInFfiCall(intptr_t arg_index) const;
+  virtual Representation RepInFfiCall(intptr_t def_index_global) const;
+
+  // The location of the inputs to the IL FfiCall instruction.
+  dart::Location LocInFfiCall(intptr_t def_index_global) const;
+
+  // Allocate a TypedData before the FfiCall and pass it in to the FfiCall so
+  // that it can be populated in assembly.
+  bool PassTypedData() const;
+  intptr_t TypedDataSizeInBytes() const;
+
+  // We allocate space for PointerToMemory arguments and PointerToMemory return
+  // locations on the stack. This is faster than allocation ExternalTypedData.
+  // Normal TypedData is not an option, as these might be relocated by GC
+  // during FFI calls.
+  intptr_t PassByPointerStackOffset(intptr_t arg_index) const;
+
+  // The total amount of stack space required for FFI trampolines.
+  intptr_t RequiredStackSpaceInBytes() const;
 
  protected:
   ~CallMarshaller() {}
@@ -132,19 +171,19 @@
  public:
   CallbackMarshaller(Zone* zone, const Function& dart_signature);
 
-  // All parameters are saved on stack to do safe-point transition.
-  const NativeLocation& NativeLocationOfNativeParameter(
-      intptr_t arg_index) const {
-    if (arg_index == kResultIndex) {
-      // No moving around of result.
-      return Location(arg_index);
-    }
-    return *callback_locs_.At(arg_index);
-  }
+  virtual Representation RepInFfiCall(intptr_t def_index_global) const;
 
   // All parameters are saved on stack to do safe-point transition.
-  dart::Location LocationOfNativeParameter(intptr_t arg_index) const {
-    return NativeLocationOfNativeParameter(arg_index).AsLocation();
+  const NativeLocation& NativeLocationOfNativeParameter(
+      intptr_t def_index) const;
+
+  // All parameters are saved on stack to do safe-point transition.
+  dart::Location LocationOfNativeParameter(intptr_t def_index) const {
+    const auto& native_loc = NativeLocationOfNativeParameter(def_index);
+    if (native_loc.IsPointerToMemory()) {
+      return native_loc.AsPointerToMemory().pointer_location().AsLocation();
+    }
+    return native_loc.AsLocation();
   }
 
  protected:
diff --git a/runtime/vm/compiler/ffi/native_calling_convention.cc b/runtime/vm/compiler/ffi/native_calling_convention.cc
index e53a1e8..86b2eba 100644
--- a/runtime/vm/compiler/ffi/native_calling_convention.cc
+++ b/runtime/vm/compiler/ffi/native_calling_convention.cc
@@ -225,10 +225,10 @@
       const NativeCompoundType& payload_type) {
     const auto& compound_type = payload_type.AsCompound();
     if (compound_type.ContainsHomogenuousFloats() && !SoftFpAbi() &&
-        compound_type.members().length() <= 4) {
-      const auto& elem_type = *(compound_type.members().At(0));
+        compound_type.NumPrimitiveMembersRecursive() <= 4) {
+      const auto& elem_type = compound_type.FirstPrimitiveMember();
       const intptr_t size = compound_type.SizeInBytes();
-      const intptr_t elem_size = compound_type.members().At(0)->SizeInBytes();
+      const intptr_t elem_size = elem_type.SizeInBytes();
       const auto reg_kind = FpuRegisterKindFromSize(elem_size);
       ASSERT(size % elem_size == 0);
       const intptr_t num_registers = size / elem_size;
@@ -291,9 +291,9 @@
     const auto& compound_type = payload_type.AsCompound();
     const intptr_t size = compound_type.SizeInBytes();
     if (compound_type.ContainsHomogenuousFloats() &&
-        compound_type.members().length() <= 4) {
-      const auto& elem_type = *(compound_type.members().At(0));
-      const intptr_t elem_size = compound_type.members().At(0)->SizeInBytes();
+        compound_type.NumPrimitiveMembersRecursive() <= 4) {
+      const auto& elem_type = compound_type.FirstPrimitiveMember();
+      const intptr_t elem_size = elem_type.SizeInBytes();
       const auto reg_kind = kQuadFpuReg;
       ASSERT(size % elem_size == 0);
       const intptr_t num_registers = size / elem_size;
@@ -623,13 +623,13 @@
 static const NativeLocation& CompoundResultLocation(
     Zone* zone,
     const NativeCompoundType& payload_type) {
-  const intptr_t num_members = payload_type.members().length();
+  const intptr_t num_members = payload_type.NumPrimitiveMembersRecursive();
   if (payload_type.ContainsHomogenuousFloats() && !SoftFpAbi() &&
       num_members <= 4) {
     NativeLocations& multiple_locations =
         *new (zone) NativeLocations(zone, num_members);
     for (int i = 0; i < num_members; i++) {
-      const auto& member = payload_type.members().At(0)->AsPrimitive();
+      const auto& member = payload_type.FirstPrimitiveMember();
       multiple_locations.Add(new (zone) NativeFpuRegistersLocation(
           member, member, FpuRegisterKindFromSize(member.SizeInBytes()), i));
     }
diff --git a/runtime/vm/compiler/ffi/native_calling_convention.h b/runtime/vm/compiler/ffi/native_calling_convention.h
index 9faf620..d1a942e 100644
--- a/runtime/vm/compiler/ffi/native_calling_convention.h
+++ b/runtime/vm/compiler/ffi/native_calling_convention.h
@@ -24,7 +24,7 @@
 // Calculates native calling convention, is not aware of Dart calling
 // convention constraints.
 //
-// This class is meant to beembedded in a class that is aware of Dart calling
+// This class is meant to be embedded in a class that is aware of Dart calling
 // convention constraints.
 class NativeCallingConvention : public ZoneAllocated {
  public:
diff --git a/runtime/vm/compiler/ffi/native_type.cc b/runtime/vm/compiler/ffi/native_type.cc
index 1ffb1a2e..837c17f 100644
--- a/runtime/vm/compiler/ffi/native_type.cc
+++ b/runtime/vm/compiler/ffi/native_type.cc
@@ -156,7 +156,7 @@
 static bool ContainsHomogenuousFloatsInternal(const NativeTypes& types);
 
 // Keep consistent with
-// pkg/vm/lib/transformations/ffi_definitions.dart:_calculateSizeAndOffsets.
+// pkg/vm/lib/transformations/ffi_definitions.dart:_calculateStructLayout.
 NativeCompoundType& NativeCompoundType::FromNativeTypes(
     Zone* zone,
     const NativeTypes& members) {
@@ -514,6 +514,32 @@
   return_type_.PrintTo(f);
 }
 
+intptr_t NativePrimitiveType::NumPrimitiveMembersRecursive() const {
+  return 1;
+}
+
+intptr_t NativeCompoundType::NumPrimitiveMembersRecursive() const {
+  intptr_t count = 0;
+  for (intptr_t i = 0; i < members_.length(); i++) {
+    count += members_[i]->NumPrimitiveMembersRecursive();
+  }
+  return count;
+}
+
+const NativePrimitiveType& NativePrimitiveType::FirstPrimitiveMember() const {
+  return *this;
+}
+
+const NativePrimitiveType& NativeCompoundType::FirstPrimitiveMember() const {
+  ASSERT(NumPrimitiveMembersRecursive() >= 1);
+  for (intptr_t i = 0; i < members().length(); i++) {
+    if (members_[i]->NumPrimitiveMembersRecursive() >= 1) {
+      return members_[i]->FirstPrimitiveMember();
+    }
+  }
+  UNREACHABLE();
+}
+
 bool NativeCompoundType::ContainsOnlyFloats(intptr_t offset_in_bytes,
                                             intptr_t size_in_bytes) const {
   ASSERT(size_in_bytes >= 0);
diff --git a/runtime/vm/compiler/ffi/native_type.h b/runtime/vm/compiler/ffi/native_type.h
index 140c54f..73d6915 100644
--- a/runtime/vm/compiler/ffi/native_type.h
+++ b/runtime/vm/compiler/ffi/native_type.h
@@ -117,6 +117,11 @@
   const char* ToCString() const;
 #endif
 
+  virtual intptr_t NumPrimitiveMembersRecursive() const { UNREACHABLE(); }
+  virtual const NativePrimitiveType& FirstPrimitiveMember() const {
+    UNREACHABLE();
+  }
+
   virtual ~NativeType() {}
 
  protected:
@@ -177,6 +182,9 @@
                        bool multi_line = false,
                        bool verbose = true) const;
 
+  virtual intptr_t NumPrimitiveMembersRecursive() const;
+  virtual const NativePrimitiveType& FirstPrimitiveMember() const;
+
   virtual ~NativePrimitiveType() {}
 
  private:
@@ -188,7 +196,6 @@
 // Struct
 //
 // TODO(dartbug.com/38491): Support unions.
-// TODO(dartbug.com/37271): Support nested compound types.
 // TODO(dartbug.com/35763): Support inline fixed-length arrays.
 class NativeCompoundType : public NativeType {
  public:
@@ -234,6 +241,9 @@
   // and arm64.
   bool ContainsHomogenuousFloats() const;
 
+  virtual intptr_t NumPrimitiveMembersRecursive() const;
+  virtual const NativePrimitiveType& FirstPrimitiveMember() const;
+
  private:
   NativeCompoundType(const NativeTypes& members,
                      const ZoneGrowableArray<intptr_t>& member_offsets,
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 06d5d73..c931003 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -17,7 +17,7 @@
 namespace kernel {
 
 #define Z (zone_)
-#define I (thread_->isolate())
+#define IG (thread_->isolate_group())
 
 Fragment& Fragment::operator+=(const Fragment& other) {
   if (entry == NULL) {
@@ -128,8 +128,9 @@
                                              bool number_check /* = false */) {
   Value* right = Pop();
   Value* left = Pop();
-  StrictCompareInstr* compare = new (Z) StrictCompareInstr(
-      position, kind, left, right, number_check, GetNextDeoptId());
+  StrictCompareInstr* compare =
+      new (Z) StrictCompareInstr(InstructionSource(position), kind, left, right,
+                                 number_check, GetNextDeoptId());
   Push(compare);
   return Fragment(compare);
 }
@@ -138,9 +139,8 @@
                                              bool number_check /* = false */) {
   Value* right = Pop();
   Value* left = Pop();
-  StrictCompareInstr* compare =
-      new (Z) StrictCompareInstr(TokenPosition::kNoSource, kind, left, right,
-                                 number_check, GetNextDeoptId());
+  StrictCompareInstr* compare = new (Z) StrictCompareInstr(
+      InstructionSource(), kind, left, right, number_check, GetNextDeoptId());
   Push(compare);
   return Fragment(compare);
 }
@@ -165,7 +165,7 @@
   Value* right_value = Pop();
   Value* left_value = Pop();
   StrictCompareInstr* compare = new (Z) StrictCompareInstr(
-      TokenPosition::kNoSource, negate ? Token::kNE_STRICT : Token::kEQ_STRICT,
+      InstructionSource(), negate ? Token::kNE_STRICT : Token::kEQ_STRICT,
       left_value, right_value, false, GetNextDeoptId());
   BranchInstr* branch = new (Z) BranchInstr(compare, GetNextDeoptId());
   *then_entry = *branch->true_successor_address() = BuildTargetEntry();
@@ -179,8 +179,8 @@
   Value* rhs = Pop();
   Value* lhs = Pop();
   StrictCompareInstr* compare =
-      new (Z) StrictCompareInstr(TokenPosition::kNoSource, Token::kEQ_STRICT,
-                                 lhs, rhs, false, GetNextDeoptId());
+      new (Z) StrictCompareInstr(InstructionSource(), Token::kEQ_STRICT, lhs,
+                                 rhs, false, GetNextDeoptId());
   BranchInstr* branch = new (Z) BranchInstr(compare, GetNextDeoptId());
   *then_entry = *branch->true_successor_address() = BuildTargetEntry();
   *otherwise_entry = *branch->false_successor_address() = BuildTargetEntry();
@@ -203,8 +203,9 @@
     ASSERT(!function.has_unboxed_return());
     representation = kTagged;
   }
-  ReturnInstr* return_instr = new (Z) ReturnInstr(
-      position, value, GetNextDeoptId(), yield_index, representation);
+  ReturnInstr* return_instr =
+      new (Z) ReturnInstr(InstructionSource(position), value, GetNextDeoptId(),
+                          yield_index, representation);
   if (exit_collector_ != nullptr) exit_collector_->AddExit(return_instr);
 
   instructions <<= return_instr;
@@ -216,7 +217,7 @@
                                                   intptr_t stack_depth,
                                                   intptr_t loop_depth) {
   return Fragment(new (Z) CheckStackOverflowInstr(
-      position, stack_depth, loop_depth, GetNextDeoptId(),
+      InstructionSource(position), stack_depth, loop_depth, GetNextDeoptId(),
       CheckStackOverflowInstr::kOsrAndPreemption));
 }
 
@@ -376,9 +377,9 @@
 
   // We use C behavior when dereferencing pointers, so we use aligned access in
   // all cases.
-  LoadIndexedInstr* instr = new (Z) LoadIndexedInstr(
-      array, index, index_unboxed, index_scale, class_id, kAlignedAccess,
-      DeoptId::kNone, TokenPosition::kNoSource);
+  LoadIndexedInstr* instr = new (Z)
+      LoadIndexedInstr(array, index, index_unboxed, index_scale, class_id,
+                       kAlignedAccess, DeoptId::kNone, InstructionSource());
   Push(instr);
   return Fragment(instr);
 }
@@ -462,14 +463,14 @@
 
 Fragment BaseFlowGraphBuilder::LoadField(const Field& field,
                                          bool calls_initializer) {
-  return LoadNativeField(Slot::Get(MayCloneField(field), parsed_function_),
+  return LoadNativeField(Slot::Get(MayCloneField(Z, field), parsed_function_),
                          calls_initializer);
 }
 
 Fragment BaseFlowGraphBuilder::LoadNativeField(const Slot& native_field,
                                                bool calls_initializer) {
   LoadFieldInstr* load = new (Z) LoadFieldInstr(
-      Pop(), native_field, TokenPosition::kNoSource, calls_initializer,
+      Pop(), native_field, InstructionSource(), calls_initializer,
       calls_initializer ? GetNextDeoptId() : DeoptId::kNone);
   Push(load);
   return Fragment(load);
@@ -477,8 +478,7 @@
 
 Fragment BaseFlowGraphBuilder::LoadLocal(LocalVariable* variable) {
   ASSERT(!variable->is_captured());
-  LoadLocalInstr* load =
-      new (Z) LoadLocalInstr(*variable, TokenPosition::kNoSource);
+  LoadLocalInstr* load = new (Z) LoadLocalInstr(*variable, InstructionSource());
   Push(load);
   return Fragment(load);
 }
@@ -497,11 +497,10 @@
   return Fragment(new (Z) GuardFieldClassInstr(Pop(), field, deopt_id));
 }
 
-const Field& BaseFlowGraphBuilder::MayCloneField(const Field& field) {
-  if ((Compiler::IsBackgroundCompilation() ||
-       FLAG_force_clone_compiler_objects) &&
-      field.IsOriginal()) {
-    return Field::ZoneHandle(Z, field.CloneFromOriginal());
+const Field& BaseFlowGraphBuilder::MayCloneField(Zone* zone,
+                                                 const Field& field) {
+  if (CompilerState::Current().should_clone_fields() && field.IsOriginal()) {
+    return Field::ZoneHandle(zone, field.CloneFromOriginal());
   } else {
     ASSERT(field.IsZoneHandle());
     return field;
@@ -518,8 +517,9 @@
   if (value->BindsToConstant()) {
     emit_store_barrier = kNoStoreBarrier;
   }
-  StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
-      field, Pop(), value, emit_store_barrier, position, kind);
+  StoreInstanceFieldInstr* store =
+      new (Z) StoreInstanceFieldInstr(field, Pop(), value, emit_store_barrier,
+                                      InstructionSource(position), kind);
   return Fragment(store);
 }
 
@@ -534,8 +534,8 @@
   }
 
   StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
-      MayCloneField(field), Pop(), value, emit_store_barrier,
-      TokenPosition::kNoSource, parsed_function_, kind);
+      MayCloneField(Z, field), Pop(), value, emit_store_barrier,
+      InstructionSource(), parsed_function_, kind);
 
   return Fragment(store);
 }
@@ -545,8 +545,8 @@
     StoreInstanceFieldInstr::Kind
         kind /* = StoreInstanceFieldInstr::Kind::kOther */) {
   Fragment instructions;
-  const Field& field_clone = MayCloneField(field);
-  if (I->use_field_guards()) {
+  const Field& field_clone = MayCloneField(Z, field);
+  if (IG->use_field_guards()) {
     LocalVariable* store_expression = MakeTemporary();
     instructions += LoadLocal(store_expression);
     instructions += GuardFieldClass(field_clone, GetNextDeoptId());
@@ -579,7 +579,7 @@
 Fragment BaseFlowGraphBuilder::LoadStaticField(const Field& field,
                                                bool calls_initializer) {
   LoadStaticFieldInstr* load = new (Z) LoadStaticFieldInstr(
-      field, TokenPosition::kNoSource, calls_initializer,
+      field, InstructionSource(), calls_initializer,
       calls_initializer ? GetNextDeoptId() : DeoptId::kNone);
   Push(load);
   return Fragment(load);
@@ -609,15 +609,15 @@
       compiler::LookupConvertUtf8DecoderScanFlagsField();
   auto scan = new (Z) Utf8ScanInstr(
       decoder, bytes, start, end, table,
-      Slot::Get(MayCloneField(scan_flags_field), parsed_function_));
+      Slot::Get(MayCloneField(Z, scan_flags_field), parsed_function_));
   Push(scan);
   return Fragment(scan);
 }
 
 Fragment BaseFlowGraphBuilder::StoreStaticField(TokenPosition position,
                                                 const Field& field) {
-  return Fragment(
-      new (Z) StoreStaticFieldInstr(MayCloneField(field), Pop(), position));
+  return Fragment(new (Z) StoreStaticFieldInstr(MayCloneField(Z, field), Pop(),
+                                                InstructionSource(position)));
 }
 
 Fragment BaseFlowGraphBuilder::StoreIndexed(classid_t class_id) {
@@ -630,7 +630,7 @@
       index, value, emit_store_barrier, /*index_unboxed=*/false,
 
       compiler::target::Instance::ElementSizeFor(class_id), class_id,
-      kAlignedAccess, DeoptId::kNone, TokenPosition::kNoSource);
+      kAlignedAccess, DeoptId::kNone, InstructionSource());
   return Fragment(store);
 }
 
@@ -645,7 +645,7 @@
   Value* c_pointer = Pop();
   StoreIndexedInstr* instr = new (Z) StoreIndexedInstr(
       c_pointer, index, value, kNoStoreBarrier, index_unboxed, index_scale,
-      class_id, alignment, DeoptId::kNone, TokenPosition::kNoSource,
+      class_id, alignment, DeoptId::kNone, InstructionSource(),
       Instruction::SpeculativeMode::kNotSpeculative);
   return Fragment(instr);
 }
@@ -668,7 +668,8 @@
                                              LocalVariable* variable) {
   ASSERT(!variable->is_captured());
   Value* value = Pop();
-  StoreLocalInstr* store = new (Z) StoreLocalInstr(*variable, value, position);
+  StoreLocalInstr* store =
+      new (Z) StoreLocalInstr(*variable, value, InstructionSource(position));
   Fragment instructions(store);
   Push(store);
   return instructions;
@@ -823,7 +824,7 @@
   Value* right = Pop();
   Value* left = Pop();
   RelationalOpInstr* instr = new (Z) RelationalOpInstr(
-      TokenPosition::kNoSource, kind, left, right, kSmiCid, GetNextDeoptId());
+      InstructionSource(), kind, left, right, kSmiCid, GetNextDeoptId());
   Push(instr);
   return Fragment(instr);
 }
@@ -873,7 +874,7 @@
 
   Fragment failing(nsm);
   const Code& nsm_handler = Code::ZoneHandle(
-      Z, I->object_store()->call_closure_no_such_method_stub());
+      Z, IG->object_store()->call_closure_no_such_method_stub());
   failing += LoadArgDescriptor();
   failing += TailCall(nsm_handler);
 
@@ -882,8 +883,8 @@
 
 Fragment BaseFlowGraphBuilder::AssertBool(TokenPosition position) {
   Value* value = Pop();
-  AssertBooleanInstr* instr =
-      new (Z) AssertBooleanInstr(position, value, GetNextDeoptId());
+  AssertBooleanInstr* instr = new (Z)
+      AssertBooleanInstr(InstructionSource(position), value, GetNextDeoptId());
   Push(instr);
   return Fragment(instr);
 }
@@ -897,7 +898,7 @@
 Fragment BaseFlowGraphBuilder::AllocateContext(
     const ZoneGrowableArray<const Slot*>& context_slots) {
   AllocateContextInstr* allocate =
-      new (Z) AllocateContextInstr(TokenPosition::kNoSource, context_slots);
+      new (Z) AllocateContextInstr(InstructionSource(), context_slots);
   Push(allocate);
   return Fragment(allocate);
 }
@@ -905,8 +906,9 @@
 Fragment BaseFlowGraphBuilder::AllocateClosure(
     TokenPosition position,
     const Function& closure_function) {
-  const Class& cls = Class::ZoneHandle(Z, I->object_store()->closure_class());
-  AllocateObjectInstr* allocate = new (Z) AllocateObjectInstr(position, cls);
+  const Class& cls = Class::ZoneHandle(Z, IG->object_store()->closure_class());
+  AllocateObjectInstr* allocate =
+      new (Z) AllocateObjectInstr(InstructionSource(position), cls);
   allocate->set_closure_function(closure_function);
   Push(allocate);
   return Fragment(allocate);
@@ -915,7 +917,7 @@
 Fragment BaseFlowGraphBuilder::CreateArray() {
   Value* element_count = Pop();
   CreateArrayInstr* array =
-      new (Z) CreateArrayInstr(TokenPosition::kNoSource,
+      new (Z) CreateArrayInstr(InstructionSource(),
                                Pop(),  // Element type.
                                element_count, GetNextDeoptId());
   Push(array);
@@ -925,8 +927,8 @@
 Fragment BaseFlowGraphBuilder::AllocateTypedData(TokenPosition position,
                                                  classid_t class_id) {
   Value* num_elements = Pop();
-  auto* instr = new (Z) AllocateTypedDataInstr(position, class_id, num_elements,
-                                               GetNextDeoptId());
+  auto* instr = new (Z) AllocateTypedDataInstr(
+      InstructionSource(position), class_id, num_elements, GetNextDeoptId());
   Push(instr);
   return Fragment(instr);
 }
@@ -934,9 +936,9 @@
 Fragment BaseFlowGraphBuilder::InstantiateType(const AbstractType& type) {
   Value* function_type_args = Pop();
   Value* instantiator_type_args = Pop();
-  InstantiateTypeInstr* instr = new (Z) InstantiateTypeInstr(
-      TokenPosition::kNoSource, type, instantiator_type_args,
-      function_type_args, GetNextDeoptId());
+  InstantiateTypeInstr* instr = new (Z)
+      InstantiateTypeInstr(InstructionSource(), type, instantiator_type_args,
+                           function_type_args, GetNextDeoptId());
   Push(instr);
   return Fragment(instr);
 }
@@ -951,7 +953,7 @@
   Value* instantiator_type_args = Pop();
   const Class& instantiator_class = Class::ZoneHandle(Z, function_.Owner());
   InstantiateTypeArgumentsInstr* instr = new (Z) InstantiateTypeArgumentsInstr(
-      TokenPosition::kNoSource, instantiator_type_args, function_type_args,
+      InstructionSource(), instantiator_type_args, function_type_args,
       type_arguments, instantiator_class, function_, GetNextDeoptId());
   Push(instr);
   instructions += Fragment(instr);
@@ -965,7 +967,7 @@
   const Function& function = Object::null_function();
   const Class& instantiator_class = Class::ZoneHandle(Z);
   InstantiateTypeArgumentsInstr* instr = new (Z) InstantiateTypeArgumentsInstr(
-      TokenPosition::kNoSource, instantiator_type_args, function_type_args,
+      InstructionSource(), instantiator_type_args, function_type_args,
       type_arguments, instantiator_class, function, GetNextDeoptId());
   Push(instr);
   return Fragment(instr);
@@ -982,8 +984,8 @@
                                               intptr_t argument_count) {
   ASSERT((argument_count == 0) || (argument_count == 1));
   Value* type_arguments = (argument_count > 0) ? Pop() : nullptr;
-  AllocateObjectInstr* allocate =
-      new (Z) AllocateObjectInstr(position, klass, type_arguments);
+  AllocateObjectInstr* allocate = new (Z)
+      AllocateObjectInstr(InstructionSource(position), klass, type_arguments);
   Push(allocate);
   return Fragment(allocate);
 }
@@ -1005,8 +1007,7 @@
   ASSERT(dart_type.IsFunctionType() && native_type.IsFunctionType());
   const Function& target =
       Function::ZoneHandle(compiler::ffi::TrampolineFunction(
-          Function::Handle(Z, Type::Cast(dart_type).signature()),
-          Function::Handle(Z, Type::Cast(native_type).signature())));
+          FunctionType::Cast(dart_type), FunctionType::Cast(native_type)));
 
   Fragment code;
   // Store the pointer in the context, we cannot load the untagged address
@@ -1046,7 +1047,8 @@
   return Fragment();
 #else
   return Fragment(new (Z) DebugStepCheckInstr(
-      position, PcDescriptorsLayout::kRuntimeCall, GetNextDeoptId()));
+      InstructionSource(position), UntaggedPcDescriptors::kRuntimeCall,
+      GetNextDeoptId()));
 #endif
 }
 
@@ -1056,10 +1058,10 @@
                                          bool clear_the_temp /* = true */) {
   Fragment instructions = LoadLocal(receiver);
 
-  CheckNullInstr* check_null = new (Z)
-      CheckNullInstr(Pop(), function_name, GetNextDeoptId(), position,
-                     function_name.IsNull() ? CheckNullInstr::kCastError
-                                            : CheckNullInstr::kNoSuchMethod);
+  CheckNullInstr* check_null = new (Z) CheckNullInstr(
+      Pop(), function_name, GetNextDeoptId(), InstructionSource(position),
+      function_name.IsNull() ? CheckNullInstr::kCastError
+                             : CheckNullInstr::kNoSuchMethod);
 
   // Does not use the redefinition, no `Push(check_null)`.
   instructions <<= check_null;
@@ -1078,8 +1080,8 @@
 Fragment BaseFlowGraphBuilder::CheckNullOptimized(TokenPosition position,
                                                   const String& function_name) {
   Value* value = Pop();
-  CheckNullInstr* check_null =
-      new (Z) CheckNullInstr(value, function_name, GetNextDeoptId(), position);
+  CheckNullInstr* check_null = new (Z) CheckNullInstr(
+      value, function_name, GetNextDeoptId(), InstructionSource(position));
   Push(check_null);  // Use the redefinition.
   return Fragment(check_null);
 }
@@ -1106,7 +1108,7 @@
 Fragment BaseFlowGraphBuilder::BuildEntryPointsIntrospection() {
   if (!FLAG_enable_testing_pragmas) return Drop();
 
-  auto& function = Function::Handle(Z, parsed_function_->function().raw());
+  auto& function = Function::Handle(Z, parsed_function_->function().ptr());
 
   if (function.IsImplicitClosureFunction()) {
     const auto& parent = Function::Handle(Z, function.parent_function());
@@ -1123,7 +1125,7 @@
       options.IsNull() || !options.IsClosure()) {
     return Drop();
   }
-  auto& closure = Closure::ZoneHandle(Z, Closure::Cast(options).raw());
+  auto& closure = Closure::ZoneHandle(Z, Closure::Cast(options).ptr());
   LocalVariable* entry_point_num = MakeTemporary();
 
   auto& function_name = String::ZoneHandle(
@@ -1157,18 +1159,19 @@
                                            bool is_statically_checked) {
   const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0) + 1;
   InputsArray* arguments = GetArguments(total_count);
-  ClosureCallInstr* call = new (Z) ClosureCallInstr(
-      arguments, type_args_len, argument_names, position, GetNextDeoptId(),
-      is_statically_checked ? Code::EntryKind::kUnchecked
-                            : Code::EntryKind::kNormal);
+  ClosureCallInstr* call = new (Z)
+      ClosureCallInstr(arguments, type_args_len, argument_names,
+                       InstructionSource(position), GetNextDeoptId(),
+                       is_statically_checked ? Code::EntryKind::kUnchecked
+                                             : Code::EntryKind::kNormal);
   Push(call);
   return Fragment(call);
 }
 
 Fragment BaseFlowGraphBuilder::StringInterpolate(TokenPosition position) {
   Value* array = Pop();
-  StringInterpolateInstr* interpolate =
-      new (Z) StringInterpolateInstr(array, position, GetNextDeoptId());
+  StringInterpolateInstr* interpolate = new (Z) StringInterpolateInstr(
+      array, InstructionSource(position), GetNextDeoptId());
   Push(interpolate);
   return Fragment(interpolate);
 }
@@ -1195,8 +1198,8 @@
   Value* value = Pop();
 
   AssertAssignableInstr* instr = new (Z) AssertAssignableInstr(
-      position, value, dst_type, instantiator_type_args, function_type_args,
-      dst_name, GetNextDeoptId(), kind);
+      InstructionSource(position), value, dst_type, instantiator_type_args,
+      function_type_args, dst_name, GetNextDeoptId(), kind);
   Push(instr);
 
   return Fragment(instr);
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 790ac1a..50e198a 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -190,7 +190,7 @@
   Fragment LoadContextAt(int depth);
   Fragment GuardFieldLength(const Field& field, intptr_t deopt_id);
   Fragment GuardFieldClass(const Field& field, intptr_t deopt_id);
-  const Field& MayCloneField(const Field& field);
+  static const Field& MayCloneField(Zone* zone, const Field& field);
   Fragment StoreInstanceField(
       TokenPosition position,
       const Slot& field,
@@ -287,7 +287,7 @@
                                TargetEntryInstr** otherwise_entry);
   Fragment Return(
       TokenPosition position,
-      intptr_t yield_index = PcDescriptorsLayout::kInvalidYieldIndex);
+      intptr_t yield_index = UntaggedPcDescriptors::kInvalidYieldIndex);
   Fragment CheckStackOverflow(TokenPosition position,
                               intptr_t stack_depth,
                               intptr_t loop_depth);
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index a8cb442..f968c45 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -29,7 +29,7 @@
                     "Not a constant expression: unexpected kernel tag %s (%d)",
                     Reader::TagName(tag), tag);
   }
-  return result_.raw();
+  return result_.ptr();
 }
 
 InstancePtr ConstantReader::ReadConstantExpression() {
@@ -54,7 +54,7 @@
                     "Not a constant expression: unexpected kernel tag %s (%d)",
                     Reader::TagName(tag), tag);
   }
-  return result_.raw();
+  return result_.ptr();
 }
 
 ObjectPtr ConstantReader::ReadAnnotations() {
@@ -85,20 +85,21 @@
         H.thread()->isolate_group()->kernel_constants_mutex());
     KernelConstantsMap constant_map(H.info().constants());
     result_ ^= constant_map.GetOrNull(constant_offset);
-    ASSERT(constant_map.Release().raw() == H.info().constants());
+    ASSERT(constant_map.Release().ptr() == H.info().constants());
   }
 
   // On miss, evaluate, and insert value.
   if (result_.IsNull()) {
+    LeaveCompilerScope cs(H.thread());
     result_ = ReadConstantInternal(constant_offset);
     SafepointMutexLocker ml(
         H.thread()->isolate_group()->kernel_constants_mutex());
     KernelConstantsMap constant_map(H.info().constants());
     auto insert = constant_map.InsertNewOrGetValue(constant_offset, result_);
-    ASSERT(insert == result_.raw());
+    ASSERT(insert == result_.ptr());
     H.info().set_constants(constant_map.Release());  // update!
   }
-  return result_.raw();
+  return result_.ptr();
 }
 
 bool ConstantReader::IsInstanceConstant(intptr_t constant_offset,
@@ -110,14 +111,14 @@
   // Peek for an instance of the given clazz.
   if (reader.ReadByte() == kInstanceConstant) {
     const NameIndex index = reader.ReadCanonicalNameReference();
-    return H.LookupClassByKernelClass(index) == clazz.raw();
+    return H.LookupClassByKernelClass(index) == clazz.ptr();
   }
   return false;
 }
 
 InstancePtr ConstantReader::ReadConstantInternal(intptr_t constant_offset) {
   // Get reader directly into raw bytes of constant table.
-  bool null_safety = H.thread()->isolate()->null_safety();
+  bool null_safety = H.thread()->isolate_group()->null_safety();
   KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
   reader.ReadUInt();  // skip variable-sized int for adjusted constant offset
   reader.SetOffset(reader.ReaderOffset() + constant_offset);
@@ -129,8 +130,8 @@
       instance = Instance::null();
       break;
     case kBoolConstant:
-      instance = reader.ReadByte() == 1 ? Object::bool_true().raw()
-                                        : Object::bool_false().raw();
+      instance = reader.ReadByte() == 1 ? Object::bool_true().ptr()
+                                        : Object::bool_false().ptr();
       break;
     case kIntConstant: {
       uint8_t payload = 0;
@@ -169,7 +170,7 @@
       instance = Double::New(reader.ReadDouble(), Heap::kOld);
       break;
     case kStringConstant:
-      instance = H.DartSymbolPlain(reader.ReadStringReference()).raw();
+      instance = H.DartSymbolPlain(reader.ReadStringReference()).ptr();
       break;
     case kSymbolConstant: {
       Library& library = Library::Handle(Z);
@@ -198,14 +199,14 @@
       // Build type from the raw bytes (needs temporary translator).
       TypeTranslator type_translator(
           &reader, this, active_class_, true,
-          active_class_->RequireLegacyErasure(null_safety));
+          active_class_->RequireConstCanonicalTypeErasure(null_safety));
       auto& type_arguments =
           TypeArguments::Handle(Z, TypeArguments::New(1, Heap::kOld));
       AbstractType& type = type_translator.BuildType();
       type_arguments.SetTypeAt(0, type);
       // Instantiate class.
-      type = Type::New(list_class, type_arguments, TokenPosition::kNoSource);
-      type = ClassFinalizer::FinalizeType(type);
+      type = Type::New(list_class, type_arguments);
+      type = ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
       type_arguments = type.arguments();
       // Fill array with constant elements.
       const intptr_t length = reader.ReadUInt();
@@ -221,7 +222,7 @@
         constant = ReadConstant(entry_offset);
         array.SetAt(j, constant);
       }
-      instance = array.raw();
+      instance = array.ptr();
       break;
     }
     case kInstanceConstant: {
@@ -241,7 +242,7 @@
       // Build type from the raw bytes (needs temporary translator).
       TypeTranslator type_translator(
           &reader, this, active_class_, true,
-          active_class_->RequireLegacyErasure(null_safety));
+          active_class_->RequireConstCanonicalTypeErasure(null_safety));
       const intptr_t number_of_type_arguments = reader.ReadUInt();
       if (klass.NumTypeArguments() > 0) {
         auto& type_arguments = TypeArguments::Handle(
@@ -250,9 +251,9 @@
           type_arguments.SetTypeAt(j, type_translator.BuildType());
         }
         // Instantiate class.
-        auto& type = AbstractType::Handle(
-            Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
-        type = ClassFinalizer::FinalizeType(type);
+        auto& type = AbstractType::Handle(Z, Type::New(klass, type_arguments));
+        type =
+            ClassFinalizer::FinalizeType(type, ClassFinalizer::kCanonicalize);
         type_arguments = type.arguments();
         instance.SetTypeArguments(type_arguments);
       } else {
@@ -284,7 +285,7 @@
       // Build type from the raw bytes (needs temporary translator).
       TypeTranslator type_translator(
           &reader, this, active_class_, true,
-          active_class_->RequireLegacyErasure(null_safety));
+          active_class_->RequireConstCanonicalTypeErasure(null_safety));
       const intptr_t number_of_type_arguments = reader.ReadUInt();
       ASSERT(number_of_type_arguments > 0);
       auto& type_arguments = TypeArguments::Handle(
@@ -294,7 +295,7 @@
       }
       type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
       // Make a copy of the old closure, and set delayed type arguments.
-      Closure& closure = Closure::Handle(Z, Closure::RawCast(constant.raw()));
+      Closure& closure = Closure::Handle(Z, Closure::RawCast(constant.ptr()));
       Function& function = Function::Handle(Z, closure.function());
       const auto& type_arguments2 =
           TypeArguments::Handle(Z, closure.instantiator_type_arguments());
@@ -317,9 +318,13 @@
     }
     case kTypeLiteralConstant: {
       // Build type from the raw bytes (needs temporary translator).
-      // Legacy erasure is not applied to type literals. See issue #42262.
+      // Const canonical type erasure is not applied to constant type literals.
+      // However, CFE must ensure that constant type literals can be
+      // canonicalized to an identical representant independently of the null
+      // safety mode currently in use (sound or unsound) or migration state of
+      // the declaring library (legacy or opted-in).
       TypeTranslator type_translator(&reader, this, active_class_, true);
-      instance = type_translator.BuildType().raw();
+      instance = type_translator.BuildType().ptr();
       break;
     }
     default:
diff --git a/runtime/vm/compiler/frontend/constant_reader.h b/runtime/vm/compiler/frontend/constant_reader.h
index 85f230d..94e8b3b 100644
--- a/runtime/vm/compiler/frontend/constant_reader.h
+++ b/runtime/vm/compiler/frontend/constant_reader.h
@@ -59,7 +59,7 @@
     return (key1.Value() == key2.Value());
   }
   static bool IsMatch(const intptr_t key1, const Object& b) {
-    return KeyAsSmi(key1) == Smi::Cast(b).raw();
+    return KeyAsSmi(key1) == Smi::Cast(b).ptr();
   }
   static uword Hash(const Object& obj) {
     const Smi& key = Smi::Cast(obj);
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index e09620b..5034b6d 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -260,7 +260,7 @@
 
     ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True());
     BranchInstr* branch = new (Z) BranchInstr(
-        new (Z) StrictCompareInstr(TokenPosition::kNoSource, Token::kEQ_STRICT,
+        new (Z) StrictCompareInstr(InstructionSource(), Token::kEQ_STRICT,
                                    new (Z) Value(true_const),
                                    new (Z) Value(true_const), false,
                                    CompilerState::Current().GetNextDeoptId()),
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 54435dc..fbced06 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -4,6 +4,7 @@
 
 #include "vm/compiler/frontend/kernel_binary_flowgraph.h"
 
+#include "vm/closure_functions_cache.h"
 #include "vm/compiler/ffi/callback.h"
 #include "vm/compiler/frontend/flow_graph_builder.h"  // For dart::FlowGraphBuilder::SimpleInstanceOfType.
 #include "vm/compiler/frontend/prologue_builder.h"
@@ -19,6 +20,7 @@
 #define H (translation_helper_)
 #define T (type_translator_)
 #define I Isolate::Current()
+#define IG IsolateGroup::Current()
 #define B (flow_graph_builder_)
 
 Class& StreamingFlowGraphBuilder::GetSuperOrDie() {
@@ -163,6 +165,8 @@
   if (PeekTag() == kNullLiteral) {
     SkipExpression();  // read past the null literal.
     if (H.thread()->IsMutatorThread()) {
+      ASSERT(field.IsOriginal());
+      LeaveCompilerScope cs(H.thread());
       field.RecordStore(Object::null_object());
     } else {
       ASSERT(field.is_nullable(/* silence_assert = */ true));
@@ -194,6 +198,7 @@
   if (has_initializer && PeekTag() == kNullLiteral) {
     SkipExpression();  // read past the null literal.
     if (H.thread()->IsMutatorThread()) {
+      LeaveCompilerScope cs(H.thread());
       field.RecordStore(Object::null_object());
     } else {
       ASSERT(field.is_nullable(/* silence_assert = */ true));
@@ -316,7 +321,7 @@
         if (class_field.is_late()) {
           if (!is_constructor_initialized) {
             instructions += BuildLateFieldInitializer(
-                Field::ZoneHandle(Z, class_field.raw()),
+                Field::ZoneHandle(Z, class_field.ptr()),
                 initializer_tag == kSomething);
           }
         } else if (initializer_tag == kSomething) {
@@ -325,7 +330,7 @@
           // value produced by the field initializer. However we still need to
           // execute it for its side effects.
           instructions += BuildFieldInitializer(
-              Field::ZoneHandle(Z, class_field.raw()),
+              Field::ZoneHandle(Z, class_field.ptr()),
               /*only_for_side_effects=*/is_constructor_initialized);
           ExitScope(field_offset);
         }
@@ -352,7 +357,7 @@
         case kFieldInitializer: {
           ReadCanonicalNameReference();
           instructions += BuildFieldInitializer(
-              Field::ZoneHandle(Z, initializer_fields[i]->raw()),
+              Field::ZoneHandle(Z, initializer_fields[i]->ptr()),
               /*only_for_size_effects=*/false);
           break;
         }
@@ -487,7 +492,7 @@
   Fragment prologue = B->BuildDefaultTypeHandling(dart_function);
 
   if (dart_function.IsClosureFunction() &&
-      dart_function.NumParentTypeParameters() > 0) {
+      dart_function.NumParentTypeArguments() > 0) {
     LocalVariable* closure = parsed_function()->ParameterVariable(0);
 
     // Function with yield points can not be generic itself but the outer
@@ -503,10 +508,9 @@
       prologue += LoadLocal(closure);
       prologue += LoadNativeField(Slot::Closure_function_type_arguments());
 
-      prologue += IntConstant(dart_function.NumParentTypeParameters());
+      prologue += IntConstant(dart_function.NumParentTypeArguments());
 
-      prologue += IntConstant(dart_function.NumTypeParameters() +
-                              dart_function.NumParentTypeParameters());
+      prologue += IntConstant(dart_function.NumTypeArguments());
 
       const auto& prepend_function =
           flow_graph_builder_->PrependTypeArgumentsFunction();
@@ -557,7 +561,7 @@
     dispatch += Constant(offsets);
     dispatch += LoadLocal(scopes()->switch_variable);
 
-    // Ideally this would just be LoadIndexedTypedData(kTypedDataInt32ArrayCid),
+    // Ideally this would just be LoadIndexed(kTypedDataInt32ArrayCid),
     // but that doesn't work in unoptimised code.
     // The optimiser will turn this into that in any case.
     dispatch += InstanceCall(TokenPosition::kNoSource, Symbols::IndexToken(),
@@ -704,8 +708,8 @@
   // included in b).  So we just use the normal implementation in the body.
   Fragment body;
   if ((dart_function.NumParameters() == 2) &&
-      (dart_function.name() == Symbols::EqualOperator().raw()) &&
-      (dart_function.Owner() != I->object_store()->object_class())) {
+      (dart_function.name() == Symbols::EqualOperator().ptr()) &&
+      (dart_function.Owner() != IG->object_store()->object_class())) {
     TargetEntryInstr* null_entry;
     TargetEntryInstr* non_null_entry;
 
@@ -1000,46 +1004,47 @@
 
   ActiveClassScope active_class_scope(active_class(), &klass);
   ActiveMemberScope active_member(active_class(), &outermost_function);
-  ActiveTypeParametersScope active_type_params(active_class(), function, Z);
+  FunctionType& signature = FunctionType::Handle(Z, function.signature());
+  ActiveTypeParametersScope active_type_params(active_class(), function,
+                                               &signature, Z);
 
   ParseKernelASTFunction();
 
   switch (function.kind()) {
-    case FunctionLayout::kRegularFunction:
-    case FunctionLayout::kGetterFunction:
-    case FunctionLayout::kSetterFunction:
-    case FunctionLayout::kClosureFunction:
-    case FunctionLayout::kConstructor: {
+    case UntaggedFunction::kRegularFunction:
+    case UntaggedFunction::kGetterFunction:
+    case UntaggedFunction::kSetterFunction:
+    case UntaggedFunction::kClosureFunction:
+    case UntaggedFunction::kConstructor: {
       if (B->IsRecognizedMethodForFlowGraph(function)) {
         return B->BuildGraphOfRecognizedMethod(function);
       }
       return BuildGraphOfFunction(function.IsGenerativeConstructor());
     }
-    case FunctionLayout::kImplicitGetter:
-    case FunctionLayout::kImplicitStaticGetter:
-    case FunctionLayout::kImplicitSetter: {
+    case UntaggedFunction::kImplicitGetter:
+    case UntaggedFunction::kImplicitStaticGetter:
+    case UntaggedFunction::kImplicitSetter: {
       const Field& field = Field::Handle(Z, function.accessor_field());
       if (field.is_const() && field.IsUninitialized()) {
         EvaluateConstFieldValue(field);
       }
       return B->BuildGraphOfFieldAccessor(function);
     }
-    case FunctionLayout::kFieldInitializer:
+    case UntaggedFunction::kFieldInitializer:
       return BuildGraphOfFieldInitializer();
-    case FunctionLayout::kDynamicInvocationForwarder:
+    case UntaggedFunction::kDynamicInvocationForwarder:
       return B->BuildGraphOfDynamicInvocationForwarder(function);
-    case FunctionLayout::kMethodExtractor:
+    case UntaggedFunction::kMethodExtractor:
       return flow_graph_builder_->BuildGraphOfMethodExtractor(function);
-    case FunctionLayout::kNoSuchMethodDispatcher:
+    case UntaggedFunction::kNoSuchMethodDispatcher:
       return flow_graph_builder_->BuildGraphOfNoSuchMethodDispatcher(function);
-    case FunctionLayout::kInvokeFieldDispatcher:
+    case UntaggedFunction::kInvokeFieldDispatcher:
       return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(function);
-    case FunctionLayout::kImplicitClosureFunction:
+    case UntaggedFunction::kImplicitClosureFunction:
       return flow_graph_builder_->BuildGraphOfImplicitClosureFunction(function);
-    case FunctionLayout::kFfiTrampoline:
+    case UntaggedFunction::kFfiTrampoline:
       return flow_graph_builder_->BuildGraphOfFfiTrampoline(function);
-    case FunctionLayout::kSignatureFunction:
-    case FunctionLayout::kIrregexpFunction:
+    case UntaggedFunction::kIrregexpFunction:
       break;
   }
   UNREACHABLE();
@@ -1056,13 +1061,13 @@
 
   // Mark forwarding stubs.
   switch (function.kind()) {
-    case FunctionLayout::kRegularFunction:
-    case FunctionLayout::kImplicitClosureFunction:
-    case FunctionLayout::kGetterFunction:
-    case FunctionLayout::kSetterFunction:
-    case FunctionLayout::kClosureFunction:
-    case FunctionLayout::kConstructor:
-    case FunctionLayout::kDynamicInvocationForwarder:
+    case UntaggedFunction::kRegularFunction:
+    case UntaggedFunction::kImplicitClosureFunction:
+    case UntaggedFunction::kGetterFunction:
+    case UntaggedFunction::kSetterFunction:
+    case UntaggedFunction::kClosureFunction:
+    case UntaggedFunction::kConstructor:
+    case UntaggedFunction::kDynamicInvocationForwarder:
       ReadForwardingStubTarget(function);
       break;
     default:
@@ -1072,32 +1077,31 @@
   set_scopes(parsed_function()->EnsureKernelScopes());
 
   switch (function.kind()) {
-    case FunctionLayout::kRegularFunction:
-    case FunctionLayout::kGetterFunction:
-    case FunctionLayout::kSetterFunction:
-    case FunctionLayout::kClosureFunction:
-    case FunctionLayout::kConstructor:
-    case FunctionLayout::kImplicitClosureFunction:
+    case UntaggedFunction::kRegularFunction:
+    case UntaggedFunction::kGetterFunction:
+    case UntaggedFunction::kSetterFunction:
+    case UntaggedFunction::kClosureFunction:
+    case UntaggedFunction::kConstructor:
+    case UntaggedFunction::kImplicitClosureFunction:
       ReadUntilFunctionNode();
       SetupDefaultParameterValues();
       break;
-    case FunctionLayout::kImplicitGetter:
-    case FunctionLayout::kImplicitStaticGetter:
-    case FunctionLayout::kImplicitSetter:
-    case FunctionLayout::kFieldInitializer:
-    case FunctionLayout::kMethodExtractor:
-    case FunctionLayout::kNoSuchMethodDispatcher:
-    case FunctionLayout::kInvokeFieldDispatcher:
-    case FunctionLayout::kFfiTrampoline:
+    case UntaggedFunction::kImplicitGetter:
+    case UntaggedFunction::kImplicitStaticGetter:
+    case UntaggedFunction::kImplicitSetter:
+    case UntaggedFunction::kFieldInitializer:
+    case UntaggedFunction::kMethodExtractor:
+    case UntaggedFunction::kNoSuchMethodDispatcher:
+    case UntaggedFunction::kInvokeFieldDispatcher:
+    case UntaggedFunction::kFfiTrampoline:
       break;
-    case FunctionLayout::kDynamicInvocationForwarder:
+    case UntaggedFunction::kDynamicInvocationForwarder:
       if (PeekTag() != kField) {
         ReadUntilFunctionNode();
         SetupDefaultParameterValues();
       }
       break;
-    case FunctionLayout::kSignatureFunction:
-    case FunctionLayout::kIrregexpFunction:
+    case UntaggedFunction::kIrregexpFunction:
       UNREACHABLE();
       break;
   }
@@ -1111,7 +1115,7 @@
     procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
     if (procedure_helper.IsForwardingStub() && !procedure_helper.IsAbstract()) {
       const NameIndex target_name =
-          procedure_helper.forwarding_stub_super_target_;
+          procedure_helper.concrete_forwarding_stub_target_;
       ASSERT(target_name != NameIndex::kInvalidName);
       const String& name = function.IsSetterFunction()
                                ? H.DartSetterName(target_name)
@@ -1936,9 +1940,9 @@
       Value* right_value = Pop();
       Value* left_value = Pop();
       StrictCompareInstr* compare = new (Z) StrictCompareInstr(
-          TokenPosition::kNoSource,
-          negate ? Token::kNE_STRICT : Token::kEQ_STRICT, left_value,
-          right_value, false, flow_graph_builder_->GetNextDeoptId());
+          InstructionSource(), negate ? Token::kNE_STRICT : Token::kEQ_STRICT,
+          left_value, right_value, false,
+          flow_graph_builder_->GetNextDeoptId());
       branch =
           new (Z) BranchInstr(compare, flow_graph_builder_->GetNextDeoptId());
       negate = false;
@@ -2089,7 +2093,7 @@
         initialize += Goto(join);
       }
     } else {
-      // The variable has no initializer, so throw a LateInitializationError.
+      // The variable has no initializer, so throw a late initialization error.
       Fragment initialize(is_uninitialized);
       initialize += flow_graph_builder_->ThrowLateInitializationError(
           position, "_throwLocalNotInitialized", variable->name());
@@ -2169,7 +2173,6 @@
 
   return instructions;
 }
-
 Fragment StreamingFlowGraphBuilder::BuildPropertyGet(TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
   const TokenPosition position = ReadPosition();  // read position.
@@ -2200,7 +2203,7 @@
     interface_target = &Function::ZoneHandle(
         Z,
         H.LookupMethodByMember(itarget_name, H.DartGetterName(itarget_name)));
-    ASSERT(getter_name.raw() == interface_target->name());
+    ASSERT(getter_name.ptr() == interface_target->name());
   } else if (!H.IsRoot(itarget_name) && H.IsMethod(itarget_name)) {
     tearoff_interface_target = &Function::ZoneHandle(
         Z,
@@ -2292,7 +2295,7 @@
     interface_target = &Function::ZoneHandle(
         Z,
         H.LookupMethodByMember(itarget_name, H.DartSetterName(itarget_name)));
-    ASSERT(setter_name.raw() == interface_target->name());
+    ASSERT(setter_name.ptr() == interface_target->name());
   }
 
   if (direct_call.check_receiver_for_null_) {
@@ -2342,7 +2345,7 @@
                                       Zone* zone,
                                       const Class& klass) {
   Function& nsm_function = Function::Handle(zone);
-  Class& iterate_klass = Class::Handle(zone, klass.raw());
+  Class& iterate_klass = Class::Handle(zone, klass.ptr());
   if (!iterate_klass.IsNull() &&
       iterate_klass.EnsureIsFinalized(thread) == Error::null()) {
     while (!iterate_klass.IsNull()) {
@@ -2384,13 +2387,13 @@
 
   // Push the arguments for allocating the invocation mirror:
   //   - the name.
-  instructions += Constant(String::ZoneHandle(Z, name.raw()));
+  instructions += Constant(String::ZoneHandle(Z, name.ptr()));
 
   //   - the arguments descriptor.
   const Array& args_descriptor =
       Array::Handle(Z, ArgumentsDescriptor::NewBoxed(
                            num_type_arguments, num_arguments, argument_names));
-  instructions += Constant(Array::ZoneHandle(Z, args_descriptor.raw()));
+  instructions += Constant(Array::ZoneHandle(Z, args_descriptor.ptr()));
 
   //   - an array containing the actual arguments.
   instructions += LoadLocal(actuals_array);
@@ -2471,7 +2474,7 @@
 
     Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, parent_klass);
     instructions +=
-        StaticCall(position, Function::ZoneHandle(Z, nsm_function.raw()),
+        StaticCall(position, Function::ZoneHandle(Z, nsm_function.ptr()),
                    /* argument_count = */ 2, ICData::kNSMDispatch);
     instructions += DropTempsPreserveTop(1);  // Drop array
   } else {
@@ -2481,7 +2484,7 @@
     instructions += LoadLocal(parsed_function()->receiver_var());
 
     instructions +=
-        StaticCall(position, Function::ZoneHandle(Z, function.raw()),
+        StaticCall(position, Function::ZoneHandle(Z, function.ptr()),
                    /* argument_count = */ 1, Array::null_array(),
                    ICData::kSuper, &result_type);
   }
@@ -2529,7 +2532,7 @@
 
     Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, klass);
     instructions +=
-        StaticCall(position, Function::ZoneHandle(Z, nsm_function.raw()),
+        StaticCall(position, Function::ZoneHandle(Z, nsm_function.ptr()),
                    /* argument_count = */ 2, ICData::kNSMDispatch);
     instructions += Drop();  // Drop result of NoSuchMethod invocation
     instructions += Drop();  // Drop array
@@ -2543,7 +2546,7 @@
     SkipInterfaceMemberNameReference();  // skip target_reference.
 
     instructions += StaticCall(
-        position, Function::ZoneHandle(Z, function.raw()),
+        position, Function::ZoneHandle(Z, function.ptr()),
         /* argument_count = */ 2, Array::null_array(), ICData::kSuper,
         /*result_type=*/nullptr, /*type_args_len=*/0,
         /*use_unchecked_entry=*/true);
@@ -2576,8 +2579,9 @@
       // during loading. See also Class::InjectCIDFields.
       ASSERT(Class::Handle(field.Owner()).library() ==
                  Library::InternalLibrary() &&
-             Class::Handle(field.Owner()).Name() == Symbols::ClassID().raw());
-      return Constant(Instance::ZoneHandle(Z, field.StaticValue()));
+             Class::Handle(field.Owner()).Name() == Symbols::ClassID().ptr());
+      return Constant(Instance::ZoneHandle(
+          Z, Instance::RawCast(field.StaticConstFieldValue())));
     } else {
       const Class& owner = Class::Handle(Z, field.Owner());
       const String& getter_name = H.DartGetterName(target);
@@ -2662,7 +2666,10 @@
 
 Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
-  ReadFlags();                                    // read flags.
+
+  const uint8_t flags = ReadFlags();  // read flags.
+  const bool is_invariant = (flags & kMethodInvocationFlagInvariant) != 0;
+
   const TokenPosition position = ReadPosition();  // read position.
   if (p != NULL) *p = position;
 
@@ -2676,7 +2683,7 @@
   const Tag receiver_tag = PeekTag();  // peek tag for receiver.
 
   bool is_unchecked_closure_call = false;
-  bool is_unchecked_call = result_type.IsSkipCheck();
+  bool is_unchecked_call = is_invariant || result_type.IsSkipCheck();
   if (call_site_attributes.receiver_type != nullptr) {
     if (call_site_attributes.receiver_type->IsFunctionType()) {
       AlternativeReadingScope alt(&reader_);
@@ -2786,7 +2793,7 @@
     interface_target = &Function::ZoneHandle(
         Z, H.LookupMethodByMember(itarget_name,
                                   H.DartProcedureName(itarget_name)));
-    ASSERT(name.raw() == interface_target->name());
+    ASSERT(name.ptr() == interface_target->name());
     ASSERT(!interface_target->IsGetterFunction());
   }
 
@@ -2805,7 +2812,7 @@
   //     those cases require a dynamic invocation forwarder.
   const Function* direct_call_target = &direct_call.target_;
   if (H.IsRoot(itarget_name) &&
-      (name.raw() != Symbols::EqualOperator().raw())) {
+      (name.ptr() != Symbols::EqualOperator().ptr())) {
     mangled_name = &String::ZoneHandle(
         Z, Function::CreateDynamicInvocationForwarderName(name));
     if (!direct_call_target->IsNull()) {
@@ -2855,7 +2862,7 @@
   // used. We must guarantee this invariant because violation will lead to an
   // illegal IL once we replace x.[]=(...) with a sequence that does not
   // actually produce any value. See http://dartbug.com/29135 for more details.
-  if (name.raw() == Symbols::AssignIndexToken().raw()) {
+  if (name.ptr() == Symbols::AssignIndexToken().ptr()) {
     instructions += Drop();
     instructions += NullConstant();
   }
@@ -2966,7 +2973,7 @@
 
     Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, klass);
     instructions += StaticCall(TokenPosition::kNoSource,
-                               Function::ZoneHandle(Z, nsm_function.raw()),
+                               Function::ZoneHandle(Z, nsm_function.ptr()),
                                /* argument_count = */ 2, ICData::kNSMDispatch);
     instructions += DropTempsPreserveTop(1);  // Drop actuals_array temp.
     return instructions;
@@ -2995,7 +3002,7 @@
     ++argument_count;                             // include receiver
     SkipInterfaceMemberNameReference();           // interfaceTargetReference
     return instructions +
-           StaticCall(position, Function::ZoneHandle(Z, function.raw()),
+           StaticCall(position, Function::ZoneHandle(Z, function.ptr()),
                       argument_count, argument_names, ICData::kSuper,
                       &result_type, type_args_len,
                       /*use_unchecked_entry_point=*/true);
@@ -3035,11 +3042,11 @@
 
   const bool special_case_unchecked_cast =
       klass.IsTopLevel() && (klass.library() == Library::InternalLibrary()) &&
-      (target.name() == Symbols::UnsafeCast().raw());
+      (target.name() == Symbols::UnsafeCast().ptr());
 
   const bool special_case_identical =
       klass.IsTopLevel() && (klass.library() == Library::CoreLibrary()) &&
-      (target.name() == Symbols::Identical().raw());
+      (target.name() == Symbols::Identical().ptr());
 
   const bool special_case =
       special_case_identical || special_case_unchecked_cast;
@@ -3127,12 +3134,14 @@
 
   Class& klass = Class::ZoneHandle(
       Z, H.LookupClassByKernelClass(H.EnclosingName(kernel_name)));
+  const auto& error = klass.EnsureIsFinalized(H.thread());
+  ASSERT(error == Error::null());
 
   Fragment instructions;
 
   if (klass.NumTypeArguments() > 0) {
     if (!klass.IsGeneric()) {
-      Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw());
+      Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).ptr());
 
       // TODO(27590): Can we move this code into [ReceiverType]?
       type ^= ClassFinalizer::FinalizeType(type, ClassFinalizer::kFinalize);
@@ -3569,14 +3578,10 @@
   // The type argument for the factory call.
   Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
 
-  if (length == 0) {
-    instructions += IntConstant(0);
-    instructions += StaticCall(
-        position,
-        Function::ZoneHandle(Z, I->object_store()->growable_list_factory()), 2,
-        ICData::kStatic);
-    return instructions;
-  }
+  // List literals up to 8 elements are lowered in the front-end
+  // (pkg/vm/lib/transformations/list_literals_lowering.dart)
+  const intptr_t kNumSpecializedListLiteralConstructors = 8;
+  ASSERT(length > kNumSpecializedListLiteralConstructors);
 
   LocalVariable* type = MakeTemporary();
   instructions += LoadLocal(type);
@@ -3594,11 +3599,14 @@
     instructions += StoreIndexed(kArrayCid);
   }
 
-  const Class& factory_class =
-      Class::Handle(Z, Library::LookupCoreClass(Symbols::List()));
-  const Function& factory_method = Function::ZoneHandle(
-      Z, factory_class.LookupFactory(
-             Library::PrivateCoreLibName(Symbols::ListLiteralFactory())));
+  const Class& growable_list_class =
+      Class::Handle(Z, Library::LookupCoreClass(Symbols::_GrowableList()));
+  ASSERT(!growable_list_class.IsNull());
+
+  const Function& factory_method =
+      Function::ZoneHandle(Z, growable_list_class.LookupFunctionAllowPrivate(
+                                  Symbols::_GrowableListLiteralFactory()));
+  ASSERT(!factory_method.IsNull());
 
   instructions += StaticCall(position, factory_method, 2, ICData::kStatic);
   instructions += DropTempsPreserveTop(1);  // Instantiated type_arguments.
@@ -3750,7 +3758,7 @@
 Fragment StreamingFlowGraphBuilder::BuildFutureNullValue(
     TokenPosition* position) {
   if (position != NULL) *position = TokenPosition::kNoSource;
-  const Class& future = Class::Handle(Z, I->object_store()->future_class());
+  const Class& future = Class::Handle(Z, IG->object_store()->future_class());
   ASSERT(!future.IsNull());
   const auto& error = future.EnsureIsFinalized(thread());
   ASSERT(error == Error::null());
@@ -3791,7 +3799,7 @@
 
   instructions += AllocateObject(
       TokenPosition::kNoSource,
-      Class::ZoneHandle(Z, I->object_store()->closure_class()), 0);
+      Class::ZoneHandle(Z, IG->object_store()->closure_class()), 0);
   LocalVariable* new_closure = MakeTemporary();
 
   intptr_t num_type_args = ReadListLength();
@@ -3914,7 +3922,7 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildAssertBlock() {
-  if (!I->asserts()) {
+  if (!IG->asserts()) {
     SkipStatementList();
     return Fragment();
   }
@@ -3938,7 +3946,7 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildAssertStatement() {
-  if (!I->asserts()) {
+  if (!IG->asserts()) {
     SetOffset(ReaderOffset() - 1);  // Include the tag.
     SkipStatement();                // read this statement.
     return Fragment();
@@ -4781,9 +4789,9 @@
     //
     LocalVariable* exception_var = parsed_function()->ParameterVariable(2);
     LocalVariable* stack_trace_var = parsed_function()->ParameterVariable(3);
-    ASSERT(exception_var->name().raw() == Symbols::ExceptionParameter().raw());
-    ASSERT(stack_trace_var->name().raw() ==
-           Symbols::StackTraceParameter().raw());
+    ASSERT(exception_var->name().ptr() == Symbols::ExceptionParameter().ptr());
+    ASSERT(stack_trace_var->name().ptr() ==
+           Symbols::StackTraceParameter().ptr());
 
     TargetEntryInstr* no_error;
     TargetEntryInstr* error;
@@ -4836,8 +4844,9 @@
 
   // Use position of equal sign if it exists. If the equal sign does not exist
   // use the position of the identifier.
-  TokenPosition debug_position =
-      Utils::Maximum(helper.position_, helper.equals_position_);
+  const TokenPosition debug_position = helper.equals_position_.IsReal()
+                                           ? helper.equals_position_
+                                           : helper.position_;
   if (NeedsDebugStepCheck(stack(), debug_position)) {
     instructions = DebugStepCheck(debug_position) + instructions;
   }
@@ -4879,93 +4888,107 @@
     // Positions has to be unique in regards to the parent.
     // A non-real at this point is probably -1, we cannot blindly use that
     // as others might use it too. Create a new dummy non-real TokenPosition.
-    position = TokenPosition(offset).ToSynthetic();
+    position = TokenPosition::Synthetic(offset);
   }
 
   // The VM has a per-isolate table of functions indexed by the enclosing
   // function and token position.
   Function& function = Function::ZoneHandle(Z);
 
-  // NOTE: This is not TokenPosition in the general sense!
-  function = I->LookupClosureFunction(parsed_function()->function(), position);
+  {
+    SafepointReadRwLocker ml(thread(),
+                             thread()->isolate_group()->program_lock());
+    // NOTE: This is not TokenPosition in the general sense!
+    function = ClosureFunctionsCache::LookupClosureFunctionLocked(
+        parsed_function()->function(), position);
+  }
+
   if (function.IsNull()) {
-    for (intptr_t i = 0; i < scopes()->function_scopes.length(); ++i) {
-      if (scopes()->function_scopes[i].kernel_offset != offset) {
-        continue;
-      }
-
-      const String* name;
-      if (declaration) {
-        name = &H.DartSymbolObfuscate(name_index);
-      } else {
-        name = &Symbols::AnonymousClosure();
-      }
-      // NOTE: This is not TokenPosition in the general sense!
-      if (!closure_owner_.IsNull()) {
-        function = Function::NewClosureFunctionWithKind(
-            FunctionLayout::kClosureFunction, *name,
-            parsed_function()->function(), position, closure_owner_);
-      } else {
-        function = Function::NewClosureFunction(
-            *name, parsed_function()->function(), position);
-      }
-
-      function.set_is_debuggable(function_node_helper.dart_async_marker_ ==
-                                 FunctionNodeHelper::kSync);
-      switch (function_node_helper.dart_async_marker_) {
-        case FunctionNodeHelper::kSyncStar:
-          function.set_modifier(FunctionLayout::kSyncGen);
-          break;
-        case FunctionNodeHelper::kAsync:
-          function.set_modifier(FunctionLayout::kAsync);
-          function.set_is_inlinable(!FLAG_causal_async_stacks);
-          break;
-        case FunctionNodeHelper::kAsyncStar:
-          function.set_modifier(FunctionLayout::kAsyncGen);
-          function.set_is_inlinable(!FLAG_causal_async_stacks);
-          break;
-        default:
-          // no special modifier
-          break;
-      }
-      function.set_is_generated_body(function_node_helper.async_marker_ ==
-                                     FunctionNodeHelper::kSyncYielding);
-      // sync* functions contain two nested synthetic functions, the first of
-      // which (sync_op_gen) is a regular sync function so we need to manually
-      // label it generated:
-      if (function.parent_function() != Function::null()) {
-        const auto& parent = Function::Handle(function.parent_function());
-        if (parent.IsSyncGenerator()) {
-          function.set_is_generated_body(true);
+    SafepointWriteRwLocker ml(thread(),
+                              thread()->isolate_group()->program_lock());
+    // NOTE: This is not TokenPosition in the general sense!
+    function = ClosureFunctionsCache::LookupClosureFunctionLocked(
+        parsed_function()->function(), position);
+    if (function.IsNull()) {
+      for (intptr_t i = 0; i < scopes()->function_scopes.length(); ++i) {
+        if (scopes()->function_scopes[i].kernel_offset != offset) {
+          continue;
         }
+
+        const String* name;
+        if (declaration) {
+          name = &H.DartSymbolObfuscate(name_index);
+        } else {
+          name = &Symbols::AnonymousClosure();
+        }
+        // NOTE: This is not TokenPosition in the general sense!
+        if (!closure_owner_.IsNull()) {
+          function = Function::NewClosureFunctionWithKind(
+              UntaggedFunction::kClosureFunction, *name,
+              parsed_function()->function(), position, closure_owner_);
+        } else {
+          function = Function::NewClosureFunction(
+              *name, parsed_function()->function(), position);
+        }
+
+        function.set_is_debuggable(function_node_helper.dart_async_marker_ ==
+                                   FunctionNodeHelper::kSync);
+        switch (function_node_helper.dart_async_marker_) {
+          case FunctionNodeHelper::kSyncStar:
+            function.set_modifier(UntaggedFunction::kSyncGen);
+            break;
+          case FunctionNodeHelper::kAsync:
+            function.set_modifier(UntaggedFunction::kAsync);
+            function.set_is_inlinable(!FLAG_causal_async_stacks);
+            break;
+          case FunctionNodeHelper::kAsyncStar:
+            function.set_modifier(UntaggedFunction::kAsyncGen);
+            function.set_is_inlinable(!FLAG_causal_async_stacks);
+            break;
+          default:
+            // no special modifier
+            break;
+        }
+        function.set_is_generated_body(function_node_helper.async_marker_ ==
+                                       FunctionNodeHelper::kSyncYielding);
+        // sync* functions contain two nested synthetic functions, the first of
+        // which (sync_op_gen) is a regular sync function so we need to manually
+        // label it generated:
+        if (function.parent_function() != Function::null()) {
+          const auto& parent = Function::Handle(function.parent_function());
+          if (parent.IsSyncGenerator()) {
+            function.set_is_generated_body(true);
+          }
+        }
+        // Note: Is..() methods use the modifiers set above, so order matters.
+        if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+          function.set_is_inlinable(!FLAG_causal_async_stacks &&
+                                    !FLAG_lazy_async_stacks);
+        }
+
+        function.set_end_token_pos(function_node_helper.end_position_);
+        LocalScope* scope = scopes()->function_scopes[i].scope;
+        const ContextScope& context_scope = ContextScope::Handle(
+            Z, scope->PreserveOuterScope(flow_graph_builder_->context_depth_));
+        function.set_context_scope(context_scope);
+        function.set_kernel_offset(offset);
+        type_translator_.SetupFunctionParameters(Class::Handle(Z), function,
+                                                 false,  // is_method
+                                                 true,   // is_closure
+                                                 &function_node_helper);
+        // type_translator_.SetupUnboxingInfoMetadata is not called here at the
+        // moment because closures do not have unboxed parameters and return
+        // value
+        function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
+
+        // Finalize function type.
+        FunctionType& signature = FunctionType::Handle(Z, function.signature());
+        signature ^= ClassFinalizer::FinalizeType(signature);
+        function.set_signature(signature);
+
+        ClosureFunctionsCache::AddClosureFunctionLocked(function);
+        break;
       }
-      // Note: Is..() methods use the modifiers set above, so order matters.
-      if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
-        function.set_is_inlinable(!FLAG_causal_async_stacks &&
-                                  !FLAG_lazy_async_stacks);
-      }
-
-      function.set_end_token_pos(function_node_helper.end_position_);
-      LocalScope* scope = scopes()->function_scopes[i].scope;
-      const ContextScope& context_scope = ContextScope::Handle(
-          Z, scope->PreserveOuterScope(flow_graph_builder_->context_depth_));
-      function.set_context_scope(context_scope);
-      function.set_kernel_offset(offset);
-      type_translator_.SetupFunctionParameters(Class::Handle(Z), function,
-                                               false,  // is_method
-                                               true,   // is_closure
-                                               &function_node_helper);
-      // type_translator_.SetupUnboxingInfoMetadata is not called here at the
-      // moment because closures do not have unboxed parameters and return value
-      function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
-
-      // Finalize function type.
-      Type& signature_type = Type::Handle(Z, function.SignatureType());
-      signature_type ^= ClassFinalizer::FinalizeType(signature_type);
-      function.SetSignatureType(signature_type);
-
-      I->AddClosureFunction(function);
-      break;
     }
   }
 
@@ -5052,8 +5075,8 @@
   const TypeArguments& type_arguments =
       T.BuildTypeArguments(list_length);  // read types.
   ASSERT(type_arguments.Length() == 1 && type_arguments.IsInstantiated());
-  const Function& native_sig = Function::Handle(
-      Z, Type::CheckedHandle(Z, type_arguments.TypeAt(0)).signature());
+  const FunctionType& native_sig =
+      FunctionType::CheckedHandle(Z, type_arguments.TypeAt(0));
 
   Fragment code;
   const intptr_t positional_count =
@@ -5090,10 +5113,10 @@
   code += Constant(result);
 
   auto& ffi_callback_functions = GrowableObjectArray::Handle(Z);
-  ffi_callback_functions ^= I->object_store()->ffi_callback_functions();
+  ffi_callback_functions ^= IG->object_store()->ffi_callback_functions();
   if (ffi_callback_functions.IsNull()) {
     ffi_callback_functions ^= GrowableObjectArray::New();
-    I->object_store()->set_ffi_callback_functions(ffi_callback_functions);
+    IG->object_store()->set_ffi_callback_functions(ffi_callback_functions);
   }
   ffi_callback_functions.Add(result);
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 0718d9d..f469fc4 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -155,7 +155,7 @@
   Fragment LoadLocal(LocalVariable* variable);
   Fragment Return(
       TokenPosition position,
-      intptr_t yield_index = PcDescriptorsLayout::kInvalidYieldIndex);
+      intptr_t yield_index = UntaggedPcDescriptors::kInvalidYieldIndex);
   Fragment EvaluateAssertion();
   Fragment RethrowException(TokenPosition position, int catch_try_index);
   Fragment ThrowNoSuchMethodError(const Function& target);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
index 80ddd91..a688d7c 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
@@ -247,4 +247,45 @@
   EXPECT(String::Cast(store3->value()->BoundConstant()).Equals("cd"));
 }
 
+ISOLATE_UNIT_TEST_CASE(StreamingFlowGraphBuilder_InvariantFlagInListLiterals) {
+  const char* kScript = R"(
+    test() {
+      return [...[], 42];
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function = Function::Handle(GetFunction(root_library, "test"));
+
+  Invoke(root_library, "test");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+  });
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  InstanceCallInstr* call_add = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  // clang-format off
+  RELEASE_ASSERT(cursor.TryMatch({
+    kMatchAndMoveFunctionEntry,
+    kMatchAndMoveCheckStackOverflow,
+    kMoveDebugStepChecks,
+    kMatchAndMoveStaticCall,
+    kMatchAndMoveStaticCall,
+    {kMatchAndMoveInstanceCall, &call_add},
+    kMoveDebugStepChecks,
+    kMatchReturn,
+  }));
+  // clang-format on
+
+  EXPECT(call_add != nullptr);
+  EXPECT(call_add->function_name().Equals("add"));
+  EXPECT(call_add->entry_kind() == Code::EntryKind::kUnchecked);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 6b6a2d55..a736b8e 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -792,13 +792,6 @@
 uint32_t KernelSourceFingerprintHelper::CalculateClassFingerprint(
     const Class& klass) {
   Zone* zone = Thread::Current()->zone();
-
-  // Handle typedefs.
-  if (klass.IsTypedefClass()) {
-    const Function& func = Function::Handle(zone, klass.signature_function());
-    return CalculateFunctionFingerprint(func);
-  }
-
   String& name = String::Handle(zone, klass.Name());
   const Array& fields = Array::Handle(zone, klass.fields());
   const Array& functions = Array::Handle(zone, klass.current_functions());
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index fa468cc..054b900 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -5,6 +5,8 @@
 #include "vm/compiler/frontend/kernel_to_il.h"
 
 #include "platform/assert.h"
+#include "platform/globals.h"
+#include "vm/class_id.h"
 #include "vm/compiler/aot/precompiler.h"
 #include "vm/compiler/backend/il.h"
 #include "vm/compiler/backend/il_printer.h"
@@ -12,13 +14,17 @@
 #include "vm/compiler/backend/range_analysis.h"
 #include "vm/compiler/ffi/abi.h"
 #include "vm/compiler/ffi/marshaller.h"
+#include "vm/compiler/ffi/native_calling_convention.h"
+#include "vm/compiler/ffi/native_type.h"
 #include "vm/compiler/ffi/recognized_method.h"
 #include "vm/compiler/frontend/kernel_binary_flowgraph.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/compiler/frontend/prologue_builder.h"
 #include "vm/compiler/jit/compiler.h"
+#include "vm/compiler/runtime_api.h"
 #include "vm/kernel_isolate.h"
 #include "vm/kernel_loader.h"
+#include "vm/log.h"
 #include "vm/longjump.h"
 #include "vm/native_entry.h"
 #include "vm/object_store.h"
@@ -26,6 +32,7 @@
 #include "vm/resolver.h"
 #include "vm/scopes.h"
 #include "vm/stack_frame.h"
+#include "vm/symbols.h"
 
 namespace dart {
 namespace kernel {
@@ -34,6 +41,7 @@
 #define H (translation_helper_)
 #define T (type_translator_)
 #define I Isolate::Current()
+#define IG IsolateGroup::Current()
 
 FlowGraphBuilder::FlowGraphBuilder(
     ParsedFunction* parsed_function,
@@ -141,7 +149,7 @@
   if (scopes_ != nullptr && scopes_->type_arguments_variable != nullptr) {
 #ifdef DEBUG
     Function& function =
-        Function::Handle(Z, parsed_function_->function().raw());
+        Function::Handle(Z, parsed_function_->function().ptr());
     while (function.IsClosureFunction()) {
       function = function.parent_function();
     }
@@ -319,7 +327,7 @@
   Fragment instructions = LoadLocal(context_variable);
 
   CloneContextInstr* clone_instruction = new (Z) CloneContextInstr(
-      TokenPosition::kNoSource, Pop(), context_slots, GetNextDeoptId());
+      InstructionSource(), Pop(), context_slots, GetNextDeoptId());
   instructions <<= clone_instruction;
   Push(clone_instruction);
 
@@ -345,8 +353,8 @@
   const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0);
   InputsArray* arguments = GetArguments(total_count);
   InstanceCallInstr* call = new (Z) InstanceCallInstr(
-      position, name, kind, arguments, type_args_len, argument_names,
-      checked_argument_count, ic_data_array_, GetNextDeoptId(),
+      InstructionSource(position), name, kind, arguments, type_args_len,
+      argument_names, checked_argument_count, ic_data_array_, GetNextDeoptId(),
       interface_target, tearoff_interface_target);
   if ((result_type != NULL) && !result_type->IsTrivial()) {
     call->SetResultType(Z, result_type->ToCompileType(Z));
@@ -394,9 +402,9 @@
 Fragment FlowGraphBuilder::ThrowException(TokenPosition position) {
   Fragment instructions;
   Value* exception = Pop();
-  instructions +=
-      Fragment(new (Z) ThrowInstr(position, GetNextDeoptId(), exception))
-          .closed();
+  instructions += Fragment(new (Z) ThrowInstr(InstructionSource(position),
+                                              GetNextDeoptId(), exception))
+                      .closed();
   // Use its side effect of leaving a constant on the stack (does not change
   // the graph).
   NullConstant();
@@ -409,10 +417,10 @@
   Fragment instructions;
   Value* stacktrace = Pop();
   Value* exception = Pop();
-  instructions +=
-      Fragment(new (Z) ReThrowInstr(position, catch_try_index, GetNextDeoptId(),
-                                    exception, stacktrace))
-          .closed();
+  instructions += Fragment(new (Z) ReThrowInstr(
+                               InstructionSource(position), catch_try_index,
+                               GetNextDeoptId(), exception, stacktrace))
+                      .closed();
   // Use its side effect of leaving a constant on the stack (does not change
   // the graph).
   NullConstant();
@@ -524,9 +532,9 @@
   const intptr_t num_args =
       function->NumParameters() + (function->IsGeneric() ? 1 : 0);
   InputsArray* arguments = GetArguments(num_args);
-  NativeCallInstr* call =
-      new (Z) NativeCallInstr(name, function, FLAG_link_natives_lazily,
-                              function->end_token_pos(), arguments);
+  NativeCallInstr* call = new (Z)
+      NativeCallInstr(name, function, FLAG_link_natives_lazily,
+                      InstructionSource(function->end_token_pos()), arguments);
   Push(call);
   return Fragment(call);
 }
@@ -587,9 +595,9 @@
                                       bool use_unchecked_entry) {
   const intptr_t total_count = argument_count + (type_args_count > 0 ? 1 : 0);
   InputsArray* arguments = GetArguments(total_count);
-  StaticCallInstr* call = new (Z)
-      StaticCallInstr(position, target, type_args_count, argument_names,
-                      arguments, ic_data_array_, GetNextDeoptId(), rebind_rule);
+  StaticCallInstr* call = new (Z) StaticCallInstr(
+      InstructionSource(position), target, type_args_count, argument_names,
+      arguments, ic_data_array_, GetNextDeoptId(), rebind_rule);
   SetResultTypeForStaticCall(call, target, argument_count, result_type);
   if (use_unchecked_entry) {
     call->set_entry_kind(Code::EntryKind::kUnchecked);
@@ -687,7 +695,7 @@
     level = InvocationMirror::Level::kTopLevel;
   } else {
     receiver = owner.RareType();
-    if (target.kind() == FunctionLayout::kConstructor) {
+    if (target.kind() == UntaggedFunction::kConstructor) {
       level = InvocationMirror::Level::kConstructor;
     } else {
       level = InvocationMirror::Level::kStatic;
@@ -1316,7 +1324,7 @@
       } else {
         body += Box(native_rep.AsRepresentationOverApprox(zone_));
         if (kind == MethodRecognizer::kFfiLoadPointer) {
-          const auto class_table = thread_->isolate()->class_table();
+          const auto class_table = thread_->isolate_group()->class_table();
           ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
           const auto& pointer_class =
               Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
@@ -1376,7 +1384,7 @@
 
       if (kind == MethodRecognizer::kFfiStorePointer) {
         // Do type check before anything untagged is on the stack.
-        const auto class_table = thread_->isolate()->class_table();
+        const auto class_table = thread_->isolate_group()->class_table();
         ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
         const auto& pointer_class =
             Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
@@ -1446,7 +1454,7 @@
       body += NullConstant();
     } break;
     case MethodRecognizer::kFfiFromAddress: {
-      const auto class_table = thread_->isolate()->class_table();
+      const auto class_table = thread_->isolate_group()->class_table();
       ASSERT(class_table->HasValidClassAt(kFfiPointerCid));
       const auto& pointer_class =
           Class::ZoneHandle(H.zone(), class_table->At(kFfiPointerCid));
@@ -1489,7 +1497,7 @@
     const Function& function,
     classid_t cid) {
   auto token_pos = function.token_pos();
-  auto class_table = Thread::Current()->isolate()->class_table();
+  auto class_table = Thread::Current()->isolate_group()->class_table();
 
   ASSERT(class_table->HasValidClassAt(cid));
   const auto& view_class = Class::ZoneHandle(H.zone(), class_table->At(cid));
@@ -1542,7 +1550,8 @@
     const Function& function,
     classid_t cid) {
   const auto token_pos = function.token_pos();
-  ASSERT(Thread::Current()->isolate()->class_table()->HasValidClassAt(cid));
+  ASSERT(
+      Thread::Current()->isolate_group()->class_table()->HasValidClassAt(cid));
 
   ASSERT(function.IsFactory() && (function.NumParameters() == 2));
   LocalVariable* length = parsed_function_->RawParameterVariable(1);
@@ -1706,7 +1715,7 @@
     AssertAssignableInstr::Kind kind) {
   Fragment instructions;
 
-  instructions += Constant(AbstractType::ZoneHandle(dst_type.raw()));
+  instructions += Constant(AbstractType::ZoneHandle(dst_type.ptr()));
 
   if (!dst_type.IsInstantiated(kCurrentClass)) {
     instructions += LoadInstantiatorTypeArguments();
@@ -1732,9 +1741,9 @@
   Fragment instructions;
   instructions += LoadInstantiatorTypeArguments();
   instructions += LoadFunctionTypeArguments();
-  instructions += Constant(AbstractType::ZoneHandle(Z, sub_type_value.raw()));
-  instructions += Constant(AbstractType::ZoneHandle(Z, super_type_value.raw()));
-  instructions += Constant(String::ZoneHandle(Z, dst_name_value.raw()));
+  instructions += Constant(AbstractType::ZoneHandle(Z, sub_type_value.ptr()));
+  instructions += Constant(AbstractType::ZoneHandle(Z, super_type_value.ptr()));
+  instructions += Constant(String::ZoneHandle(Z, dst_name_value.ptr()));
   instructions += AssertSubtype(position);
   return instructions;
 }
@@ -1748,9 +1757,9 @@
   Value* function_type_args = Pop();
   Value* instantiator_type_args = Pop();
 
-  AssertSubtypeInstr* instr = new (Z)
-      AssertSubtypeInstr(position, instantiator_type_args, function_type_args,
-                         sub_type, super_type, dst_name, GetNextDeoptId());
+  AssertSubtypeInstr* instr = new (Z) AssertSubtypeInstr(
+      InstructionSource(position), instantiator_type_args, function_type_args,
+      sub_type, super_type, dst_name, GetNextDeoptId());
   instructions += Fragment(instr);
 
   return instructions;
@@ -1908,7 +1917,7 @@
     name = function.ParameterNameAt(num_fixed_params + i);
     names.SetAt(i, name);
   }
-  return names.raw();
+  return names.ptr();
 }
 
 Fragment FlowGraphBuilder::PushExplicitParameters(
@@ -2048,7 +2057,7 @@
     // If noSuchMethod is not found on the receiver class, call
     // Object.noSuchMethod.
     no_such_method = Resolver::ResolveDynamicForReceiverClass(
-        Class::Handle(Z, I->object_store()->object_class()),
+        Class::Handle(Z, IG->object_store()->object_class()),
         Symbols::NoSuchMethod(), two_arguments);
   }
   body += StaticCall(TokenPosition::kMinSource, no_such_method,
@@ -2117,7 +2126,7 @@
     Fragment set,
     Fragment not_set) {
   // Required named arguments only exist if null_safety is enabled.
-  if (!I->use_strict_null_safety_checks()) return not_set;
+  if (!IG->use_strict_null_safety_checks()) return not_set;
 
   Fragment check_required;
   // First, we convert the index to be in terms of the number of optional
@@ -2292,7 +2301,7 @@
   // required named arguments.
   if (info.descriptor.NamedCount() == 0) {
     // No work to do if there are no possible required named parameters.
-    if (!I->use_strict_null_safety_checks()) {
+    if (!IG->use_strict_null_safety_checks()) {
       return Fragment();
     }
     // If the below changes, we can no longer assume that flag slots existing
@@ -2549,7 +2558,7 @@
   loop_body += LoadNativeField(Slot::TypeParameter_flags());
   loop_body += Box(kUnboxedUint8);
   loop_body += IntConstant(
-      TypeParameterLayout::GenericCovariantImplBit::mask_in_place());
+      UntaggedTypeParameter::GenericCovariantImplBit::mask_in_place());
   loop_body += SmiBinaryOp(Token::kBIT_AND);
   loop_body += IntConstant(0);
   TargetEntryInstr *is_noncovariant, *is_covariant;
@@ -2679,11 +2688,13 @@
   info.parameter_names = MakeTemporary("parameter_names");
 
   body += LoadLocal(info.function);
-  body += LoadNativeField(Slot::Function_parameter_types());
+  body += LoadNativeField(Slot::Function_signature());
+  body += LoadNativeField(Slot::FunctionType_parameter_types());
   info.parameter_types = MakeTemporary("parameter_types");
 
   body += LoadLocal(info.function);
-  body += LoadNativeField(Slot::Function_type_parameters());
+  body += LoadNativeField(Slot::Function_signature());
+  body += LoadNativeField(Slot::FunctionType_type_parameters());
   info.type_parameters = MakeTemporary("type_parameters");
 
   body += LoadLocal(info.closure);
@@ -2803,8 +2814,8 @@
 
   // Determine if this is `class Closure { get call => this; }`
   const Class& closure_class =
-      Class::Handle(Z, I->object_store()->closure_class());
-  const bool is_closure_call = (owner.raw() == closure_class.raw()) &&
+      Class::Handle(Z, IG->object_store()->closure_class());
+  const bool is_closure_call = (owner.ptr() == closure_class.ptr()) &&
                                field_name.Equals(Symbols::Call());
 
   graph_entry_ =
@@ -3059,7 +3070,7 @@
           Function::ZoneHandle(Z, function.parent_function());
       const Class& owner = Class::ZoneHandle(Z, parent.Owner());
       AbstractType& type = AbstractType::ZoneHandle(Z);
-      type = Type::New(owner, TypeArguments::Handle(Z), owner.token_pos());
+      type = Type::New(owner, TypeArguments::Handle(Z));
       type = ClassFinalizer::FinalizeType(type);
       body += Constant(type);
     } else {
@@ -3355,7 +3366,7 @@
   // type check mode in this case.
   const auto& target = Function::Handle(
       Z, function.IsDynamicInvocationForwarder() ? function.ForwardingTarget()
-                                                 : function.raw());
+                                                 : function.ptr());
   ASSERT(target.IsImplicitGetterOrSetter());
 
   const bool is_method = !function.IsStaticFunction();
@@ -3424,8 +3435,11 @@
 #endif
     }
   } else if (field.is_const()) {
-    ASSERT(!field.IsUninitialized());
-    body += Constant(Instance::ZoneHandle(Z, field.StaticValue()));
+    const auto& value = Object::Handle(Z, field.StaticConstFieldValue());
+    if (value.IsError()) {
+      Report::LongJump(Error::Cast(value));
+    }
+    body += Constant(Instance::ZoneHandle(Z, Instance::RawCast(value.ptr())));
   } else {
     // Static fields
     //  - with trivial initializer
@@ -3485,7 +3499,7 @@
 
   // Should never build a dynamic invocation forwarder for equality
   // operator.
-  ASSERT(function.name() != Symbols::EqualOperator().raw());
+  ASSERT(function.name() != Symbols::EqualOperator().ptr());
 
   // Even if the caller did not pass argument vector we would still
   // call the target with instantiate-to-bounds type arguments.
@@ -3528,7 +3542,7 @@
   // used. We must guarantee this invariant because violation will lead to an
   // illegal IL once we replace x.[]=(...) with a sequence that does not
   // actually produce any value. See http://dartbug.com/29135 for more details.
-  if (name.raw() == Symbols::AssignIndexToken().raw()) {
+  if (name.ptr() == Symbols::AssignIndexToken().ptr()) {
     body += Drop();
     body += NullConstant();
   }
@@ -3558,6 +3572,67 @@
   fragment.current->AsDefinition()->set_range(range);
 }
 
+static classid_t TypedDataCidUnboxed(Representation unboxed_representation) {
+  switch (unboxed_representation) {
+    case kUnboxedFloat:
+      // Note kTypedDataFloat32ArrayCid loads kUnboxedDouble.
+      UNREACHABLE();
+      return kTypedDataFloat32ArrayCid;
+    case kUnboxedInt32:
+      return kTypedDataInt32ArrayCid;
+    case kUnboxedUint32:
+      return kTypedDataUint32ArrayCid;
+    case kUnboxedInt64:
+      return kTypedDataInt64ArrayCid;
+    case kUnboxedDouble:
+      return kTypedDataFloat64ArrayCid;
+    default:
+      UNREACHABLE();
+  }
+  UNREACHABLE();
+}
+
+Fragment FlowGraphBuilder::StoreIndexedTypedDataUnboxed(
+    Representation unboxed_representation,
+    intptr_t index_scale,
+    bool index_unboxed) {
+  ASSERT(unboxed_representation == kUnboxedInt32 ||
+         unboxed_representation == kUnboxedUint32 ||
+         unboxed_representation == kUnboxedInt64 ||
+         unboxed_representation == kUnboxedFloat ||
+         unboxed_representation == kUnboxedDouble);
+  Fragment fragment;
+  if (unboxed_representation == kUnboxedFloat) {
+    fragment += BitCast(kUnboxedFloat, kUnboxedInt32);
+    unboxed_representation = kUnboxedInt32;
+  }
+  fragment += StoreIndexedTypedData(TypedDataCidUnboxed(unboxed_representation),
+                                    index_scale, index_unboxed);
+  return fragment;
+}
+
+Fragment FlowGraphBuilder::LoadIndexedTypedDataUnboxed(
+    Representation unboxed_representation,
+    intptr_t index_scale,
+    bool index_unboxed) {
+  ASSERT(unboxed_representation == kUnboxedInt32 ||
+         unboxed_representation == kUnboxedUint32 ||
+         unboxed_representation == kUnboxedInt64 ||
+         unboxed_representation == kUnboxedFloat ||
+         unboxed_representation == kUnboxedDouble);
+  Representation representation_for_load = unboxed_representation;
+  if (unboxed_representation == kUnboxedFloat) {
+    representation_for_load = kUnboxedInt32;
+  }
+  Fragment fragment;
+  fragment += LoadIndexed(TypedDataCidUnboxed(representation_for_load),
+                          index_scale, index_unboxed);
+  if (unboxed_representation == kUnboxedFloat) {
+    fragment += BitCast(kUnboxedInt32, kUnboxedFloat);
+  }
+  return fragment;
+}
+
 Fragment FlowGraphBuilder::EnterHandleScope() {
   auto* instr = new (Z)
       EnterHandleScopeInstr(EnterHandleScopeInstr::Kind::kEnterHandleScope);
@@ -3610,7 +3685,7 @@
   code += LoadLocal(MakeTemporary());  // Duplicate handle pointer.
   code += ConvertUnboxedToUntagged(kUnboxedIntPtr);
   code += LoadLocal(object);
-  code += RawStoreField(compiler::target::LocalHandle::raw_offset());
+  code += RawStoreField(compiler::target::LocalHandle::ptr_offset());
 
   code += DropTempsPreserveTop(1);  // Drop object below handle.
   return code;
@@ -3619,14 +3694,14 @@
 Fragment FlowGraphBuilder::UnwrapHandle() {
   Fragment code;
   code += ConvertUnboxedToUntagged(kUnboxedIntPtr);
-  code += IntConstant(compiler::target::LocalHandle::raw_offset());
+  code += IntConstant(compiler::target::LocalHandle::ptr_offset());
   code += UnboxTruncate(kUnboxedIntPtr);
   code += LoadIndexed(kArrayCid, /*index_scale=*/1, /*index_unboxed=*/true);
   return code;
 }
 
 Fragment FlowGraphBuilder::UnhandledException() {
-  const auto class_table = thread_->isolate()->class_table();
+  const auto class_table = thread_->isolate_group()->class_table();
   ASSERT(class_table->HasValidClassAt(kUnhandledExceptionCid));
   const auto& klass =
       Class::ZoneHandle(H.zone(), class_table->At(kUnhandledExceptionCid));
@@ -3659,9 +3734,9 @@
 
 Fragment FlowGraphBuilder::NativeReturn(
     const compiler::ffi::CallbackMarshaller& marshaller) {
-  auto* instr = new (Z) NativeReturnInstr(TokenPosition::kNoSource, Pop(),
-                                          marshaller, DeoptId::kNone);
-  return Fragment(instr);
+  auto* instr = new (Z)
+      NativeReturnInstr(InstructionSource(), Pop(), marshaller, DeoptId::kNone);
+  return Fragment(instr).closed();
 }
 
 Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) {
@@ -3703,10 +3778,297 @@
   return Fragment(instr);
 }
 
-Fragment FlowGraphBuilder::FfiConvertArgumentToDart(
+Fragment FlowGraphBuilder::WrapTypedDataBaseInStruct(
+    const AbstractType& struct_type) {
+  const auto& struct_sub_class = Class::ZoneHandle(Z, struct_type.type_class());
+  struct_sub_class.EnsureIsFinalized(thread_);
+  const auto& lib_ffi = Library::Handle(Z, Library::FfiLibrary());
+  const auto& struct_class =
+      Class::Handle(Z, lib_ffi.LookupClass(Symbols::Struct()));
+  const auto& struct_addressof = Field::ZoneHandle(
+      Z, struct_class.LookupInstanceFieldAllowPrivate(Symbols::_addressOf()));
+  ASSERT(!struct_addressof.IsNull());
+
+  Fragment body;
+  LocalVariable* typed_data = MakeTemporary("typed_data_base");
+  body += AllocateObject(TokenPosition::kNoSource, struct_sub_class, 0);
+  body += LoadLocal(MakeTemporary("struct"));  // Duplicate Struct.
+  body += LoadLocal(typed_data);
+  body += StoreInstanceField(struct_addressof,
+                             StoreInstanceFieldInstr::Kind::kInitializing);
+  body += DropTempsPreserveTop(1);  // Drop TypedData.
+  return body;
+}
+
+Fragment FlowGraphBuilder::LoadTypedDataBaseFromStruct() {
+  const Library& lib_ffi = Library::Handle(zone_, Library::FfiLibrary());
+  const Class& struct_class =
+      Class::Handle(zone_, lib_ffi.LookupClass(Symbols::Struct()));
+  const Field& struct_addressof = Field::ZoneHandle(
+      zone_,
+      struct_class.LookupInstanceFieldAllowPrivate(Symbols::_addressOf()));
+  ASSERT(!struct_addressof.IsNull());
+
+  Fragment body;
+  body += LoadField(struct_addressof, /*calls_initializer=*/false);
+  return body;
+}
+
+Fragment FlowGraphBuilder::CopyFromStructToStack(
+    LocalVariable* variable,
+    const GrowableArray<Representation>& representations) {
+  Fragment body;
+  const intptr_t num_defs = representations.length();
+  int offset_in_bytes = 0;
+  for (intptr_t i = 0; i < num_defs; i++) {
+    body += LoadLocal(variable);
+    body += LoadTypedDataBaseFromStruct();
+    body += LoadUntagged(compiler::target::Pointer::data_field_offset());
+    body += IntConstant(offset_in_bytes);
+    const Representation representation = representations[i];
+    offset_in_bytes += RepresentationUtils::ValueSize(representation);
+    body += LoadIndexedTypedDataUnboxed(representation, /*index_scale=*/1,
+                                        /*index_unboxed=*/false);
+  }
+  return body;
+}
+
+Fragment FlowGraphBuilder::PopFromStackToTypedDataBase(
+    ZoneGrowableArray<LocalVariable*>* definitions,
+    const GrowableArray<Representation>& representations) {
+  Fragment body;
+  const intptr_t num_defs = representations.length();
+  ASSERT(definitions->length() == num_defs);
+
+  LocalVariable* uint8_list = MakeTemporary("uint8_list");
+  int offset_in_bytes = 0;
+  for (intptr_t i = 0; i < num_defs; i++) {
+    const Representation representation = representations[i];
+    body += LoadLocal(uint8_list);
+    body += LoadUntagged(compiler::target::TypedDataBase::data_field_offset());
+    body += IntConstant(offset_in_bytes);
+    body += LoadLocal(definitions->At(i));
+    body += StoreIndexedTypedDataUnboxed(representation, /*index_scale=*/1,
+                                         /*index_unboxed=*/false);
+    offset_in_bytes += RepresentationUtils::ValueSize(representation);
+  }
+  body += DropTempsPreserveTop(num_defs);  // Drop chunck defs keep TypedData.
+  return body;
+}
+
+static intptr_t chunk_size(intptr_t bytes_left) {
+  ASSERT(bytes_left >= 1);
+  if (bytes_left >= 8 && compiler::target::kWordSize == 8) {
+    return 8;
+  }
+  if (bytes_left >= 4) {
+    return 4;
+  }
+  if (bytes_left >= 2) {
+    return 2;
+  }
+  return 1;
+}
+
+static classid_t typed_data_cid(intptr_t chunk_size) {
+  switch (chunk_size) {
+    case 8:
+      return kTypedDataInt64ArrayCid;
+    case 4:
+      return kTypedDataInt32ArrayCid;
+    case 2:
+      return kTypedDataInt16ArrayCid;
+    case 1:
+      return kTypedDataInt8ArrayCid;
+  }
+  UNREACHABLE();
+}
+
+Fragment FlowGraphBuilder::CopyFromTypedDataBaseToUnboxedAddress(
+    intptr_t length_in_bytes) {
+  Fragment body;
+  Value* unboxed_address_value = Pop();
+  LocalVariable* typed_data_base = MakeTemporary("typed_data_base");
+  Push(unboxed_address_value->definition());
+  LocalVariable* unboxed_address = MakeTemporary("unboxed_address");
+
+  intptr_t offset_in_bytes = 0;
+  while (offset_in_bytes < length_in_bytes) {
+    const intptr_t bytes_left = length_in_bytes - offset_in_bytes;
+    const intptr_t chunk_sizee = chunk_size(bytes_left);
+    const classid_t typed_data_cidd = typed_data_cid(chunk_sizee);
+
+    body += LoadLocal(typed_data_base);
+    body += LoadUntagged(compiler::target::TypedDataBase::data_field_offset());
+    body += IntConstant(offset_in_bytes);
+    body += LoadIndexed(typed_data_cidd, /*index_scale=*/1,
+                        /*index_unboxed=*/false);
+    LocalVariable* chunk_value = MakeTemporary("chunk_value");
+
+    body += LoadLocal(unboxed_address);
+    body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
+    body += IntConstant(offset_in_bytes);
+    body += LoadLocal(chunk_value);
+    body += StoreIndexedTypedData(typed_data_cidd, /*index_scale=*/1,
+                                  /*index_unboxed=*/false);
+    body += DropTemporary(&chunk_value);
+
+    offset_in_bytes += chunk_sizee;
+  }
+  ASSERT(offset_in_bytes == length_in_bytes);
+
+  body += DropTemporary(&unboxed_address);
+  body += DropTemporary(&typed_data_base);
+  return body;
+}
+
+Fragment FlowGraphBuilder::CopyFromUnboxedAddressToTypedDataBase(
+    intptr_t length_in_bytes) {
+  Fragment body;
+  Value* typed_data_base_value = Pop();
+  LocalVariable* unboxed_address = MakeTemporary("unboxed_address");
+  Push(typed_data_base_value->definition());
+  LocalVariable* typed_data_base = MakeTemporary("typed_data_base");
+
+  intptr_t offset_in_bytes = 0;
+  while (offset_in_bytes < length_in_bytes) {
+    const intptr_t bytes_left = length_in_bytes - offset_in_bytes;
+    const intptr_t chunk_sizee = chunk_size(bytes_left);
+    const classid_t typed_data_cidd = typed_data_cid(chunk_sizee);
+
+    body += LoadLocal(unboxed_address);
+    body += ConvertUnboxedToUntagged(kUnboxedFfiIntPtr);
+    body += IntConstant(offset_in_bytes);
+    body += LoadIndexed(typed_data_cidd, /*index_scale=*/1,
+                        /*index_unboxed=*/false);
+    LocalVariable* chunk_value = MakeTemporary("chunk_value");
+
+    body += LoadLocal(typed_data_base);
+    body += LoadUntagged(compiler::target::TypedDataBase::data_field_offset());
+    body += IntConstant(offset_in_bytes);
+    body += LoadLocal(chunk_value);
+    body += StoreIndexedTypedData(typed_data_cidd, /*index_scale=*/1,
+                                  /*index_unboxed=*/false);
+    body += DropTemporary(&chunk_value);
+
+    offset_in_bytes += chunk_sizee;
+  }
+  ASSERT(offset_in_bytes == length_in_bytes);
+
+  body += DropTemporary(&typed_data_base);
+  body += DropTemporary(&unboxed_address);
+  return body;
+}
+
+Fragment FlowGraphBuilder::FfiCallConvertStructArgumentToNative(
+    LocalVariable* variable,
     const compiler::ffi::BaseMarshaller& marshaller,
     intptr_t arg_index) {
   Fragment body;
+  const auto& native_loc = marshaller.Location(arg_index);
+  if (native_loc.IsStack() || native_loc.IsMultiple()) {
+    // Break struct in pieces to separate IL definitions to pass those
+    // separate definitions into the FFI call.
+    GrowableArray<Representation> representations;
+    marshaller.RepsInFfiCall(arg_index, &representations);
+    body += CopyFromStructToStack(variable, representations);
+  } else {
+    ASSERT(native_loc.IsPointerToMemory());
+    // Only load the typed data, do copying in the FFI call machine code.
+    body += LoadLocal(variable);  // User-defined struct.
+    body += LoadTypedDataBaseFromStruct();
+  }
+  return body;
+}
+
+Fragment FlowGraphBuilder::FfiCallConvertStructReturnToDart(
+    const compiler::ffi::BaseMarshaller& marshaller,
+    intptr_t arg_index) {
+  Fragment body;
+  // The typed data is allocated before the FFI call, and is populated in
+  // machine code. So, here, it only has to be wrapped in the struct class.
+  const auto& struct_type =
+      AbstractType::Handle(Z, marshaller.CType(arg_index));
+  body += WrapTypedDataBaseInStruct(struct_type);
+  return body;
+}
+
+Fragment FlowGraphBuilder::FfiCallbackConvertStructArgumentToDart(
+    const compiler::ffi::BaseMarshaller& marshaller,
+    intptr_t arg_index,
+    ZoneGrowableArray<LocalVariable*>* definitions) {
+  const intptr_t length_in_bytes =
+      marshaller.Location(arg_index).payload_type().SizeInBytes();
+
+  Fragment body;
+  if ((marshaller.Location(arg_index).IsMultiple() ||
+       marshaller.Location(arg_index).IsStack())) {
+    // Allocate and populate a TypedData from the individual NativeParameters.
+    body += IntConstant(length_in_bytes);
+    body +=
+        AllocateTypedData(TokenPosition::kNoSource, kTypedDataUint8ArrayCid);
+    GrowableArray<Representation> representations;
+    marshaller.RepsInFfiCall(arg_index, &representations);
+    body += PopFromStackToTypedDataBase(definitions, representations);
+  } else {
+    ASSERT(marshaller.Location(arg_index).IsPointerToMemory());
+    // Allocate a TypedData and copy contents pointed to by an address into it.
+    LocalVariable* address_of_struct = MakeTemporary("address_of_struct");
+    body += IntConstant(length_in_bytes);
+    body +=
+        AllocateTypedData(TokenPosition::kNoSource, kTypedDataUint8ArrayCid);
+    LocalVariable* typed_data_base = MakeTemporary("typed_data_base");
+    body += LoadLocal(address_of_struct);
+    body += LoadLocal(typed_data_base);
+    body += CopyFromUnboxedAddressToTypedDataBase(length_in_bytes);
+    body += DropTempsPreserveTop(1);  // address_of_struct.
+  }
+  // Wrap typed data in struct class.
+  const auto& struct_type =
+      AbstractType::Handle(Z, marshaller.CType(arg_index));
+  body += WrapTypedDataBaseInStruct(struct_type);
+  return body;
+}
+
+Fragment FlowGraphBuilder::FfiCallbackConvertStructReturnToNative(
+    const compiler::ffi::CallbackMarshaller& marshaller,
+    intptr_t arg_index) {
+  Fragment body;
+  const auto& native_loc = marshaller.Location(arg_index);
+  if (native_loc.IsMultiple()) {
+    // We pass in typed data to native return instruction, and do the copying
+    // in machine code.
+    body += LoadTypedDataBaseFromStruct();
+  } else {
+    ASSERT(native_loc.IsPointerToMemory());
+    // We copy the data into the right location in IL.
+    const intptr_t length_in_bytes =
+        marshaller.Location(arg_index).payload_type().SizeInBytes();
+
+    body += LoadTypedDataBaseFromStruct();
+    LocalVariable* typed_data_base = MakeTemporary("typed_data_base");
+
+    auto* pointer_to_return =
+        new (Z) NativeParameterInstr(marshaller, compiler::ffi::kResultIndex);
+    Push(pointer_to_return);  // Address where return value should be stored.
+    body <<= pointer_to_return;
+    body += UnboxTruncate(kUnboxedFfiIntPtr);
+    LocalVariable* unboxed_address = MakeTemporary("unboxed_address");
+
+    body += LoadLocal(typed_data_base);
+    body += LoadLocal(unboxed_address);
+    body += CopyFromTypedDataBaseToUnboxedAddress(length_in_bytes);
+    body += DropTempsPreserveTop(1);  // Keep address, drop typed_data_base.
+  }
+  return body;
+}
+
+Fragment FlowGraphBuilder::FfiConvertPrimitiveToDart(
+    const compiler::ffi::BaseMarshaller& marshaller,
+    intptr_t arg_index) {
+  ASSERT(!marshaller.IsStruct(arg_index));
+
+  Fragment body;
   if (marshaller.IsPointer(arg_index)) {
     body += Box(kUnboxedFfiIntPtr);
     body += FfiPointerFromAddress(
@@ -3718,8 +4080,9 @@
     body += NullConstant();
   } else {
     if (marshaller.RequiresBitCast(arg_index)) {
-      body += BitCast(marshaller.RepInFfiCall(arg_index),
-                      marshaller.RepInDart(arg_index));
+      body += BitCast(
+          marshaller.RepInFfiCall(marshaller.FirstDefinitionIndex(arg_index)),
+          marshaller.RepInDart(arg_index));
     }
 
     body += Box(marshaller.RepInDart(arg_index));
@@ -3727,12 +4090,13 @@
   return body;
 }
 
-Fragment FlowGraphBuilder::FfiConvertArgumentToNative(
+Fragment FlowGraphBuilder::FfiConvertPrimitiveToNative(
     const compiler::ffi::BaseMarshaller& marshaller,
     intptr_t arg_index,
     LocalVariable* api_local_scope) {
-  Fragment body;
+  ASSERT(!marshaller.IsStruct(arg_index));
 
+  Fragment body;
   if (marshaller.IsPointer(arg_index)) {
     // This can only be Pointer, so it is always safe to LoadUntagged.
     body += LoadUntagged(compiler::target::Pointer::data_field_offset());
@@ -3744,8 +4108,9 @@
   }
 
   if (marshaller.RequiresBitCast(arg_index)) {
-    body += BitCast(marshaller.RepInDart(arg_index),
-                    marshaller.RepInFfiCall(arg_index));
+    body += BitCast(
+        marshaller.RepInDart(arg_index),
+        marshaller.RepInFfiCall(marshaller.FirstDefinitionIndex(arg_index)));
   }
 
   return body;
@@ -3817,14 +4182,30 @@
     ++try_depth_;
 
     body += EnterHandleScope();
-    api_local_scope = MakeTemporary();
+    api_local_scope = MakeTemporary("api_local_scope");
+  }
+
+  // Allocate typed data before FfiCall and pass it in to ffi call if needed.
+  LocalVariable* typed_data = nullptr;
+  if (marshaller.PassTypedData()) {
+    body += IntConstant(marshaller.TypedDataSizeInBytes());
+    body +=
+        AllocateTypedData(TokenPosition::kNoSource, kTypedDataUint8ArrayCid);
+    typed_data = MakeTemporary();
   }
 
   // Unbox and push the arguments.
   for (intptr_t i = 0; i < marshaller.num_args(); i++) {
-    body += LoadLocal(
-        parsed_function_->ParameterVariable(kFirstArgumentParameterOffset + i));
-    body += FfiConvertArgumentToNative(marshaller, i, api_local_scope);
+    if (marshaller.IsStruct(i)) {
+      body += FfiCallConvertStructArgumentToNative(
+          parsed_function_->ParameterVariable(kFirstArgumentParameterOffset +
+                                              i),
+          marshaller, i);
+    } else {
+      body += LoadLocal(parsed_function_->ParameterVariable(
+          kFirstArgumentParameterOffset + i));
+      body += FfiConvertPrimitiveToNative(marshaller, i, api_local_scope);
+    }
   }
 
   // Push the function pointer, which is stored (as Pointer object) in the
@@ -3834,12 +4215,17 @@
   body += LoadNativeField(Slot::Closure_context());
   body += LoadNativeField(Slot::GetContextVariableSlotFor(
       thread_, *MakeImplicitClosureScope(
-                    Z, Class::Handle(I->object_store()->ffi_pointer_class()))
+                    Z, Class::Handle(IG->object_store()->ffi_pointer_class()))
                     ->context_variables()[0]));
 
   // This can only be Pointer, so it is always safe to LoadUntagged.
   body += LoadUntagged(compiler::target::Pointer::data_field_offset());
   body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
+
+  if (marshaller.PassTypedData()) {
+    body += LoadLocal(typed_data);
+  }
+
   body += FfiCall(marshaller);
 
   for (intptr_t i = 0; i < marshaller.num_args(); i++) {
@@ -3850,7 +4236,23 @@
     }
   }
 
-  body += FfiConvertArgumentToDart(marshaller, compiler::ffi::kResultIndex);
+  const intptr_t num_defs = marshaller.NumReturnDefinitions();
+  ASSERT(num_defs >= 1);
+  auto defs = new (Z) ZoneGrowableArray<LocalVariable*>(Z, num_defs);
+  LocalVariable* def = MakeTemporary();
+  defs->Add(def);
+
+  if (marshaller.PassTypedData()) {
+    // Drop call result, typed data with contents is already on the stack.
+    body += Drop();
+  }
+
+  if (marshaller.IsStruct(compiler::ffi::kResultIndex)) {
+    body += FfiCallConvertStructReturnToDart(marshaller,
+                                             compiler::ffi::kResultIndex);
+  } else {
+    body += FfiConvertPrimitiveToDart(marshaller, compiler::ffi::kResultIndex);
+  }
 
   if (signature_contains_handles) {
     body += DropTempsPreserveTop(1);  // Drop api_local_scope.
@@ -3909,10 +4311,23 @@
 
   // Box and push the arguments.
   for (intptr_t i = 0; i < marshaller.num_args(); i++) {
-    auto* parameter = new (Z) NativeParameterInstr(marshaller, i);
-    Push(parameter);
-    body <<= parameter;
-    body += FfiConvertArgumentToDart(marshaller, i);
+    const intptr_t num_defs = marshaller.NumDefinitions(i);
+    auto defs = new (Z) ZoneGrowableArray<LocalVariable*>(Z, num_defs);
+
+    for (intptr_t j = 0; j < num_defs; j++) {
+      const intptr_t def_index = marshaller.DefinitionIndex(j, i);
+      auto* parameter = new (Z) NativeParameterInstr(marshaller, def_index);
+      Push(parameter);
+      body <<= parameter;
+      LocalVariable* def = MakeTemporary();
+      defs->Add(def);
+    }
+
+    if (marshaller.IsStruct(i)) {
+      body += FfiCallbackConvertStructArgumentToDart(marshaller, i, defs);
+    } else {
+      body += FfiConvertPrimitiveToDart(marshaller, i);
+    }
   }
 
   // Call the target.
@@ -3923,7 +4338,6 @@
                      Function::ZoneHandle(Z, function.FfiCallbackTarget()),
                      marshaller.num_args(), Array::empty_array(),
                      ICData::kNoRebind);
-
   if (marshaller.IsVoid(compiler::ffi::kResultIndex)) {
     body += Drop();
     body += IntConstant(0);
@@ -3932,8 +4346,15 @@
         CheckNullOptimized(TokenPosition::kNoSource,
                            String::ZoneHandle(Z, marshaller.function_name()));
   }
-  body += FfiConvertArgumentToNative(marshaller, compiler::ffi::kResultIndex,
-                                     /*api_local_scope=*/nullptr);
+
+  if (marshaller.IsStruct(compiler::ffi::kResultIndex)) {
+    body += FfiCallbackConvertStructReturnToNative(marshaller,
+                                                   compiler::ffi::kResultIndex);
+  } else {
+    body += FfiConvertPrimitiveToNative(marshaller, compiler::ffi::kResultIndex,
+                                        /*api_local_scope=*/nullptr);
+  }
+
   body += NativeReturn(marshaller);
 
   --try_depth_;
@@ -3955,13 +4376,32 @@
     catch_body += UnboxTruncate(kUnboxedFfiIntPtr);
   } else if (marshaller.IsHandle(compiler::ffi::kResultIndex)) {
     catch_body += UnhandledException();
-    catch_body += FfiConvertArgumentToNative(
-        marshaller, compiler::ffi::kResultIndex, /*api_local_scope=*/nullptr);
+    catch_body +=
+        FfiConvertPrimitiveToNative(marshaller, compiler::ffi::kResultIndex,
+                                    /*api_local_scope=*/nullptr);
+
+  } else if (marshaller.IsStruct(compiler::ffi::kResultIndex)) {
+    ASSERT(function.FfiCallbackExceptionalReturn() == Object::null());
+    // Manufacture empty result.
+    const intptr_t size =
+        Utils::RoundUp(marshaller.Location(compiler::ffi::kResultIndex)
+                           .payload_type()
+                           .SizeInBytes(),
+                       compiler::target::kWordSize);
+    catch_body += IntConstant(size);
+    catch_body +=
+        AllocateTypedData(TokenPosition::kNoSource, kTypedDataUint8ArrayCid);
+    catch_body += WrapTypedDataBaseInStruct(
+        AbstractType::Handle(Z, marshaller.CType(compiler::ffi::kResultIndex)));
+    catch_body += FfiCallbackConvertStructReturnToNative(
+        marshaller, compiler::ffi::kResultIndex);
+
   } else {
     catch_body += Constant(
         Instance::ZoneHandle(Z, function.FfiCallbackExceptionalReturn()));
-    catch_body += FfiConvertArgumentToNative(
-        marshaller, compiler::ffi::kResultIndex, /*api_local_scope=*/nullptr);
+    catch_body +=
+        FfiConvertPrimitiveToNative(marshaller, compiler::ffi::kResultIndex,
+                                    /*api_local_scope=*/nullptr);
   }
 
   catch_body += NativeReturn(marshaller);
@@ -4030,7 +4470,7 @@
 
 Fragment FlowGraphBuilder::BuildNullAssertions() {
   Fragment code;
-  if (I->null_safety() || !I->asserts() || !FLAG_null_assertions) {
+  if (IG->null_safety() || !IG->asserts() || !FLAG_null_assertions) {
     return code;
   }
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 1041f9c..c1dd552 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -203,7 +203,7 @@
   Fragment Return(
       TokenPosition position,
       bool omit_result_type_check = false,
-      intptr_t yield_index = PcDescriptorsLayout::kInvalidYieldIndex);
+      intptr_t yield_index = UntaggedPcDescriptors::kInvalidYieldIndex);
   void SetResultTypeForStaticCall(StaticCallInstr* call,
                                   const Function& target,
                                   intptr_t argument_count,
@@ -252,6 +252,17 @@
   bool NeedsDebugStepCheck(const Function& function, TokenPosition position);
   bool NeedsDebugStepCheck(Value* value, TokenPosition position);
 
+  // Deals with StoreIndexed not working with kUnboxedFloat.
+  // TODO(dartbug.com/43448): Remove this workaround.
+  Fragment StoreIndexedTypedDataUnboxed(Representation unboxed_representation,
+                                        intptr_t index_scale,
+                                        bool index_unboxed);
+  // Deals with LoadIndexed not working with kUnboxedFloat.
+  // TODO(dartbug.com/43448): Remove this workaround.
+  Fragment LoadIndexedTypedDataUnboxed(Representation unboxed_representation,
+                                       intptr_t index_scale,
+                                       bool index_unboxed);
+
   // Truncates (instead of deoptimizing) if the origin does not fit into the
   // target representation.
   Fragment UnboxTruncate(Representation to);
@@ -266,16 +277,81 @@
 
   // Pops a Dart object and push the unboxed native version, according to the
   // semantics of FFI argument translation.
-  Fragment FfiConvertArgumentToNative(
+  //
+  // Works for FFI call arguments, and FFI callback return values.
+  Fragment FfiConvertPrimitiveToNative(
       const compiler::ffi::BaseMarshaller& marshaller,
       intptr_t arg_index,
       LocalVariable* api_local_scope);
 
-  // Reverse of 'FfiConvertArgumentToNative'.
-  Fragment FfiConvertArgumentToDart(
+  // Pops an unboxed native value, and pushes a Dart object, according to the
+  // semantics of FFI argument translation.
+  //
+  // Works for FFI call return values, and FFI callback arguments.
+  Fragment FfiConvertPrimitiveToDart(
       const compiler::ffi::BaseMarshaller& marshaller,
       intptr_t arg_index);
 
+  // We pass in `variable` instead of on top of the stack so that we can have
+  // multiple consecutive calls that keep only struct parts on the stack with
+  // no struct parts in between.
+  Fragment FfiCallConvertStructArgumentToNative(
+      LocalVariable* variable,
+      const compiler::ffi::BaseMarshaller& marshaller,
+      intptr_t arg_index);
+
+  Fragment FfiCallConvertStructReturnToDart(
+      const compiler::ffi::BaseMarshaller& marshaller,
+      intptr_t arg_index);
+
+  // We pass in multiple `definitions`, which are also expected to be the top
+  // of the stack. This eases storing each definition in the resulting struct.
+  Fragment FfiCallbackConvertStructArgumentToDart(
+      const compiler::ffi::BaseMarshaller& marshaller,
+      intptr_t arg_index,
+      ZoneGrowableArray<LocalVariable*>* definitions);
+
+  Fragment FfiCallbackConvertStructReturnToNative(
+      const compiler::ffi::CallbackMarshaller& marshaller,
+      intptr_t arg_index);
+
+  // Wraps a TypedDataBase from the stack and wraps it in a subclass of Struct.
+  Fragment WrapTypedDataBaseInStruct(const AbstractType& struct_type);
+
+  // Loads the addressOf field from a subclass of Struct.
+  Fragment LoadTypedDataBaseFromStruct();
+
+  // Breaks up a subclass of Struct in multiple definitions and puts them on
+  // the stack.
+  //
+  // Takes in the Struct as a local `variable` so that can be anywhere on the
+  // stack and this function can be called multiple times to leave only the
+  // results of this function on the stack without any Structs in between.
+  //
+  // The struct contents are heterogeneous, so pass in `representations` to
+  // know what representation to load.
+  Fragment CopyFromStructToStack(
+      LocalVariable* variable,
+      const GrowableArray<Representation>& representations);
+
+  // Copy `definitions` into TypedData.
+  //
+  // Expects the TypedData on top of the stack and `definitions` right under it.
+  //
+  // Leaves TypedData on stack.
+  //
+  // The struct contents are heterogeneous, so pass in `representations` to
+  // know what representation to load.
+  Fragment PopFromStackToTypedDataBase(
+      ZoneGrowableArray<LocalVariable*>* definitions,
+      const GrowableArray<Representation>& representations);
+
+  // Copies bytes from a TypedDataBase to the address of an kUnboxedFfiIntPtr.
+  Fragment CopyFromTypedDataBaseToUnboxedAddress(intptr_t length_in_bytes);
+
+  // Copies bytes from the address of an kUnboxedFfiIntPtr to a TypedDataBase.
+  Fragment CopyFromUnboxedAddressToTypedDataBase(intptr_t length_in_bytes);
+
   // Generates a call to `Thread::EnterApiScope`.
   Fragment EnterHandleScope();
 
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 794f917..d7fe4f9 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -18,6 +18,7 @@
 #define H (translation_helper_)
 #define T (type_translator_)
 #define I Isolate::Current()
+#define IG IsolateGroup::Current()
 
 namespace dart {
 namespace kernel {
@@ -93,7 +94,7 @@
     funcs = GrowableObjectArray::New(16, Heap::kNew);
     info_.set_potential_pragma_functions(funcs);
   }
-  return funcs.raw();
+  return funcs.ptr();
 }
 
 void TranslationHelper::AddPotentialExtensionLibrary(const Library& library) {
@@ -108,53 +109,53 @@
   if (potential_extension_libraries_ != nullptr) {
     GrowableObjectArray* result = potential_extension_libraries_;
     potential_extension_libraries_ = nullptr;
-    return result->raw();
+    return result->ptr();
   }
   return GrowableObjectArray::null();
 }
 
 void TranslationHelper::SetStringOffsets(const TypedData& string_offsets) {
   ASSERT(string_offsets_.IsNull());
-  string_offsets_ = string_offsets.raw();
+  string_offsets_ = string_offsets.ptr();
 }
 
 void TranslationHelper::SetStringData(const ExternalTypedData& string_data) {
   ASSERT(string_data_.IsNull());
-  string_data_ = string_data.raw();
+  string_data_ = string_data.ptr();
 }
 
 void TranslationHelper::SetCanonicalNames(const TypedData& canonical_names) {
   ASSERT(canonical_names_.IsNull());
-  canonical_names_ = canonical_names.raw();
+  canonical_names_ = canonical_names.ptr();
 }
 
 void TranslationHelper::SetMetadataPayloads(
     const ExternalTypedData& metadata_payloads) {
   ASSERT(metadata_payloads_.IsNull());
   ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize));
-  metadata_payloads_ = metadata_payloads.raw();
+  metadata_payloads_ = metadata_payloads.ptr();
 }
 
 void TranslationHelper::SetMetadataMappings(
     const ExternalTypedData& metadata_mappings) {
   ASSERT(metadata_mappings_.IsNull());
-  metadata_mappings_ = metadata_mappings.raw();
+  metadata_mappings_ = metadata_mappings.ptr();
 }
 
 void TranslationHelper::SetConstants(const Array& constants) {
   ASSERT(constants_.IsNull() ||
          (constants.IsNull() || constants.Length() == 0));
-  constants_ = constants.raw();
+  constants_ = constants.ptr();
 }
 
 void TranslationHelper::SetConstantsTable(
     const ExternalTypedData& constants_table) {
   ASSERT(constants_table_.IsNull());
-  constants_table_ = constants_table.raw();
+  constants_table_ = constants_table.ptr();
 }
 
 void TranslationHelper::SetKernelProgramInfo(const KernelProgramInfo& info) {
-  info_ = info.raw();
+  info_ = info.ptr();
 }
 
 intptr_t TranslationHelper::StringOffset(StringIndex index) const {
@@ -339,7 +340,7 @@
 }
 
 InstancePtr TranslationHelper::Canonicalize(const Instance& instance) {
-  if (instance.IsNull()) return instance.raw();
+  if (instance.IsNull()) return instance.ptr();
 
   return instance.Canonicalize(thread());
 }
@@ -390,7 +391,7 @@
 const String& TranslationHelper::DartSymbolObfuscate(
     const char* content) const {
   String& result = String::ZoneHandle(Z, Symbols::New(thread_, content));
-  if (I->obfuscate()) {
+  if (IG->obfuscate()) {
     Obfuscator obfuscator(thread_, String::Handle(Z));
     result = obfuscator.Rename(result, true);
   }
@@ -406,7 +407,7 @@
   }
   String& result =
       String::ZoneHandle(Z, Symbols::FromUTF8(thread_, buffer, length));
-  if (I->obfuscate()) {
+  if (IG->obfuscate()) {
     Obfuscator obfuscator(thread_, String::Handle(Z));
     result = obfuscator.Rename(result, true);
   }
@@ -601,7 +602,7 @@
       Z, klass.LookupFieldAllowPrivate(
              DartSymbolObfuscate(CanonicalNameString(kernel_field))));
   CheckStaticLookup(field);
-  return field.raw();
+  return field.ptr();
 }
 
 FunctionPtr TranslationHelper::LookupStaticMethodByKernelProcedure(
@@ -617,7 +618,7 @@
     Function& function =
         Function::Handle(Z, library.LookupFunctionAllowPrivate(procedure_name));
     CheckStaticLookup(function);
-    return function.raw();
+    return function.ptr();
   } else {
     ASSERT(IsClass(enclosing));
     Class& klass = Class::Handle(Z, LookupClassByKernelClass(enclosing));
@@ -626,7 +627,7 @@
     Function& function = Function::ZoneHandle(
         Z, klass.LookupFunctionAllowPrivate(procedure_name));
     CheckStaticLookup(function);
-    return function.raw();
+    return function.ptr();
   }
 }
 
@@ -648,7 +649,7 @@
   Function& function = Function::Handle(
       Z, owner.LookupConstructorAllowPrivate(DartConstructorName(constructor)));
   CheckStaticLookup(function);
-  return function.raw();
+  return function.ptr();
 }
 
 FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor(
@@ -685,13 +686,13 @@
 #endif
   CheckStaticLookup(function);
   ASSERT(!function.IsNull());
-  return function.raw();
+  return function.ptr();
 }
 
 FunctionPtr TranslationHelper::LookupDynamicFunction(const Class& klass,
                                                      const String& name) {
   // Search the superclass chain for the selector.
-  Class& iterate_klass = Class::Handle(Z, klass.raw());
+  Class& iterate_klass = Class::Handle(Z, klass.ptr());
   while (!iterate_klass.IsNull()) {
     FunctionPtr function =
         iterate_klass.LookupDynamicFunctionAllowPrivate(name);
@@ -712,8 +713,7 @@
     type = klass.DeclarationType();
   } else {
     // Note that the type argument vector is not yet extended.
-    type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
-                     klass.token_pos());
+    type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()));
   }
   return type;
 }
@@ -726,23 +726,27 @@
   bool is_method = !function.IsStaticFunction();
   intptr_t parameter_count = (is_method ? 1 : 0) + (is_setter ? 1 : 0);
 
+  const FunctionType& signature = FunctionType::Handle(Z, function.signature());
   function.SetNumOptionalParameters(0, false);
   function.set_num_fixed_parameters(parameter_count);
-  function.set_parameter_types(
-      Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
-  function.CreateNameArrayIncludingFlags(Heap::kNew);
+  if (parameter_count > 0) {
+    signature.set_parameter_types(
+        Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
+  }
+  signature.CreateNameArrayIncludingFlags(Heap::kOld);
 
   intptr_t pos = 0;
   if (is_method) {
-    function.SetParameterTypeAt(pos, GetDeclarationType(klass));
-    function.SetParameterNameAt(pos, Symbols::This());
+    signature.SetParameterTypeAt(pos, GetDeclarationType(klass));
+    signature.SetParameterNameAt(pos, Symbols::This());
     pos++;
   }
   if (is_setter) {
-    function.SetParameterTypeAt(pos, field_type);
-    function.SetParameterNameAt(pos, Symbols::Value());
+    signature.SetParameterTypeAt(pos, field_type);
+    signature.SetParameterNameAt(pos, Symbols::Value());
     pos++;
   }
+  signature.FinalizeNameArrays(function);
 }
 
 void TranslationHelper::ReportError(const char* format, ...) {
@@ -801,14 +805,14 @@
     const Library& library =
         Library::Handle(Z, LookupLibraryByKernelLibrary(parent));
     *name_to_modify = library.PrivateName(*name_to_modify);
-    if (obfuscate && I->obfuscate()) {
+    if (obfuscate && IG->obfuscate()) {
       const String& library_key = String::Handle(library.private_key());
       Obfuscator obfuscator(thread_, library_key);
       *name_to_modify = obfuscator.Rename(*name_to_modify);
     }
   } else if (symbolize) {
     *name_to_modify = Symbols::New(thread_, *name_to_modify);
-    if (obfuscate && I->obfuscate()) {
+    if (obfuscate && IG->obfuscate()) {
       const String& library_key = String::Handle();
       Obfuscator obfuscator(thread_, library_key);
       *name_to_modify = obfuscator.Rename(*name_to_modify);
@@ -823,14 +827,14 @@
                                              bool obfuscate) {
   if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_') {
     *name_to_modify = library.PrivateName(*name_to_modify);
-    if (obfuscate && I->obfuscate()) {
+    if (obfuscate && IG->obfuscate()) {
       const String& library_key = String::Handle(library.private_key());
       Obfuscator obfuscator(thread_, library_key);
       *name_to_modify = obfuscator.Rename(*name_to_modify);
     }
   } else if (symbolize) {
     *name_to_modify = Symbols::New(thread_, *name_to_modify);
-    if (obfuscate && I->obfuscate()) {
+    if (obfuscate && IG->obfuscate()) {
       const String& library_key = String::Handle();
       Obfuscator obfuscator(thread_, library_key);
       *name_to_modify = obfuscator.Rename(*name_to_modify);
@@ -1102,8 +1106,9 @@
     }
       FALL_THROUGH;
     case kStubTarget:
-      if (stub_kind_ == kForwardingSuperStubKind) {
-        forwarding_stub_super_target_ = helper_->ReadCanonicalNameReference();
+      if (stub_kind_ == kConcreteForwardingStubKind) {
+        concrete_forwarding_stub_target_ =
+            helper_->ReadCanonicalNameReference();
       } else {
         helper_->ReadCanonicalNameReference();
       }
@@ -1854,7 +1859,7 @@
     loading_units.SetAt(id, unit);
   }
 
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IG->object_store();
   ASSERT(object_store->loading_units() == Array::null());
   object_store->set_loading_units(loading_units);
 }
@@ -2853,17 +2858,19 @@
   }
 }
 
-ActiveTypeParametersScope::ActiveTypeParametersScope(ActiveClass* active_class,
-                                                     const Function& innermost,
-                                                     Zone* Z)
+ActiveTypeParametersScope::ActiveTypeParametersScope(
+    ActiveClass* active_class,
+    const Function& innermost,
+    const FunctionType* innermost_signature,
+    Zone* Z)
     : active_class_(active_class), saved_(*active_class) {
-  active_class_->enclosing = &innermost;
+  active_class_->enclosing = innermost_signature;
 
   intptr_t num_params = 0;
 
   Function& f = Function::Handle(Z);
   TypeArguments& f_params = TypeArguments::Handle(Z);
-  for (f = innermost.raw(); f.parent_function() != Object::null();
+  for (f = innermost.ptr(); f.parent_function() != Object::null();
        f = f.parent_function()) {
     f_params = f.type_parameters();
     num_params += f_params.Length();
@@ -2874,7 +2881,7 @@
       TypeArguments::Handle(Z, TypeArguments::New(num_params));
 
   intptr_t index = num_params;
-  for (f = innermost.raw(); f.parent_function() != Object::null();
+  for (f = innermost.ptr(); f.parent_function() != Object::null();
        f = f.parent_function()) {
     f_params = f.type_parameters();
     for (intptr_t j = f_params.Length() - 1; j >= 0; --j) {
@@ -2887,11 +2894,11 @@
 
 ActiveTypeParametersScope::ActiveTypeParametersScope(
     ActiveClass* active_class,
-    const Function* function,
+    const FunctionType* innermost_signature,
     const TypeArguments& new_params,
     Zone* Z)
     : active_class_(active_class), saved_(*active_class) {
-  active_class_->enclosing = function;
+  active_class_->enclosing = innermost_signature;
 
   if (new_params.IsNull()) return;
 
@@ -2918,7 +2925,7 @@
                                ConstantReader* constant_reader,
                                ActiveClass* active_class,
                                bool finalize,
-                               bool apply_legacy_erasure)
+                               bool apply_canonical_type_erasure)
     : helper_(helper),
       constant_reader_(constant_reader),
       translation_helper_(helper->translation_helper_),
@@ -2929,14 +2936,14 @@
       zone_(translation_helper_.zone()),
       result_(AbstractType::Handle(translation_helper_.zone())),
       finalize_(finalize),
-      apply_legacy_erasure_(apply_legacy_erasure) {}
+      apply_canonical_type_erasure_(apply_canonical_type_erasure) {}
 
 AbstractType& TypeTranslator::BuildType() {
   BuildTypeInternal();
 
   // We return a new `ZoneHandle` here on purpose: The intermediate language
   // instructions do not make a copy of the handle, so we do it.
-  return AbstractType::ZoneHandle(Z, result_.raw());
+  return AbstractType::ZoneHandle(Z, result_.ptr());
 }
 
 AbstractType& TypeTranslator::BuildTypeWithoutFinalization() {
@@ -2947,7 +2954,7 @@
 
   // We return a new `ZoneHandle` here on purpose: The intermediate language
   // instructions do not make a copy of the handle, so we do it.
-  return AbstractType::ZoneHandle(Z, result_.raw());
+  return AbstractType::ZoneHandle(Z, result_.ptr());
 }
 
 void TypeTranslator::BuildTypeInternal() {
@@ -2955,24 +2962,24 @@
   switch (tag) {
     case kInvalidType:
     case kDynamicType:
-      result_ = Object::dynamic_type().raw();
+      result_ = Object::dynamic_type().ptr();
       break;
     case kVoidType:
-      result_ = Object::void_type().raw();
+      result_ = Object::void_type().ptr();
       break;
     case kNeverType: {
-      const Nullability nullability = helper_->ReadNullability();
-      if (apply_legacy_erasure_) {
-        result_ = I->object_store()->null_type();
-      } else {
-        result_ = Type::Handle(Z, I->object_store()->never_type())
-                      .ToNullability(nullability, Heap::kOld);
+      Nullability nullability = helper_->ReadNullability();
+      if (apply_canonical_type_erasure_ &&
+          nullability != Nullability::kNullable) {
+        nullability = Nullability::kLegacy;
       }
+      result_ = Type::Handle(Z, IG->object_store()->never_type())
+                    .ToNullability(nullability, Heap::kOld);
       break;
     }
     case kBottomType:
       // Map Bottom type to Null type until not emitted by CFE anymore.
-      result_ = I->object_store()->null_type();
+      result_ = IG->object_store()->null_type();
       ASSERT(result_.IsNullable());
       break;
     case kInterfaceType:
@@ -3002,7 +3009,7 @@
   //   => We therefore ignore errors in `A` or `B`.
 
   Nullability nullability = helper_->ReadNullability();
-  if (apply_legacy_erasure_) {
+  if (apply_canonical_type_erasure_ && nullability != Nullability::kNullable) {
     nullability = Nullability::kLegacy;
   }
 
@@ -3020,8 +3027,7 @@
       result_ = Type::Cast(result_).ToNullability(nullability, Heap::kOld);
     } else {
       // Note that the type argument vector is not yet extended.
-      result_ = Type::New(klass, Object::null_type_arguments(),
-                          klass.token_pos(), nullability);
+      result_ = Type::New(klass, Object::null_type_arguments(), nullability);
     }
     return;
   }
@@ -3030,8 +3036,7 @@
       helper_->ReadListLength();  // read type_arguments list length.
   const TypeArguments& type_arguments =
       BuildTypeArguments(length);  // read type arguments.
-  result_ =
-      Type::New(klass, type_arguments, TokenPosition::kNoSource, nullability);
+  result_ = Type::New(klass, type_arguments, nullability);
   result_ = result_.NormalizeFutureOrType(Heap::kOld);
   if (finalize_) {
     ASSERT(active_class_->klass != NULL);
@@ -3040,17 +3045,16 @@
 }
 
 void TypeTranslator::BuildFunctionType(bool simple) {
-  Function& signature_function = Function::ZoneHandle(
-      Z, Function::NewSignatureFunction(*active_class_->klass,
-                                        active_class_->enclosing != NULL
-                                            ? *active_class_->enclosing
-                                            : Function::Handle(Z),
-                                        TokenPosition::kNoSource));
-
+  const intptr_t num_enclosing_type_arguments =
+      active_class_->enclosing != NULL
+          ? active_class_->enclosing->NumTypeArguments()
+          : 0;
   Nullability nullability = helper_->ReadNullability();
-  if (apply_legacy_erasure_) {
+  if (apply_canonical_type_erasure_ && nullability != Nullability::kNullable) {
     nullability = Nullability::kLegacy;
   }
+  FunctionType& signature = FunctionType::ZoneHandle(
+      Z, FunctionType::New(num_enclosing_type_arguments, nullability));
 
   // Suspend finalization of types inside this one. They will be finalized after
   // the whole function type is constructed.
@@ -3061,13 +3065,14 @@
   finalize_ = false;
 
   if (!simple) {
-    LoadAndSetupTypeParameters(active_class_, signature_function,
-                               helper_->ReadListLength(), signature_function);
+    LoadAndSetupTypeParameters(
+        active_class_, Object::null_function(), Object::null_class(), signature,
+        helper_->ReadListLength(), active_class_->klass->nnbd_mode());
   }
 
   ActiveTypeParametersScope scope(
-      active_class_, &signature_function,
-      TypeArguments::Handle(Z, signature_function.type_parameters()), Z);
+      active_class_, &signature,
+      TypeArguments::Handle(Z, signature.type_parameters()), Z);
 
   intptr_t required_count;
   intptr_t all_count;
@@ -3084,23 +3089,25 @@
     all_count = positional_count;
   }
 
-  // The additional first parameter is the receiver type (set to dynamic).
-  signature_function.set_num_fixed_parameters(1 + required_count);
-  signature_function.SetNumOptionalParameters(
-      all_count - required_count, positional_count > required_count);
+  // The additional first parameter is the receiver (type set to dynamic).
+  const intptr_t kImplicitClosureParam = 1;
+  signature.set_num_implicit_parameters(kImplicitClosureParam);
+  signature.set_num_fixed_parameters(kImplicitClosureParam + required_count);
+  signature.SetNumOptionalParameters(all_count - required_count,
+                                     positional_count > required_count);
 
-  signature_function.set_parameter_types(
-      Array::Handle(Z, Array::New(1 + all_count, Heap::kOld)));
-  signature_function.CreateNameArrayIncludingFlags(Heap::kOld);
+  signature.set_parameter_types(Array::Handle(
+      Z, Array::New(kImplicitClosureParam + all_count, Heap::kOld)));
+  signature.CreateNameArrayIncludingFlags(Heap::kOld);
 
   intptr_t pos = 0;
-  signature_function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
-  signature_function.SetParameterNameAt(pos, H.DartSymbolPlain("_receiver_"));
+  signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
+  signature.SetParameterNameAt(pos, H.DartSymbolPlain("_receiver_"));
   ++pos;
   for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
     BuildTypeInternal();  // read ith positional parameter.
-    signature_function.SetParameterTypeAt(pos, result_);
-    signature_function.SetParameterNameAt(pos, H.DartSymbolPlain("noname"));
+    signature.SetParameterTypeAt(pos, result_);
+    signature.SetParameterNameAt(pos, H.DartSymbolPlain("noname"));
   }
 
   if (!simple) {
@@ -3111,41 +3118,34 @@
       String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
       BuildTypeInternal();  // read named_parameters[i].type.
       const uint8_t flags = helper_->ReadFlags();  // read flags
-      signature_function.SetParameterTypeAt(pos, result_);
-      signature_function.SetParameterNameAt(pos, name);
-      if (!apply_legacy_erasure_ &&
-          (flags & static_cast<uint8_t>(NamedTypeFlags::kIsRequired)) != 0) {
-        signature_function.SetIsRequiredAt(pos);
+      signature.SetParameterTypeAt(pos, result_);
+      signature.SetParameterNameAt(pos, name);
+      if ((flags & static_cast<uint8_t>(NamedTypeFlags::kIsRequired)) != 0) {
+        signature.SetIsRequiredAt(pos);
       }
     }
   }
-  signature_function.TruncateUnusedParameterFlags();
+  signature.TruncateUnusedParameterFlags();
 
   if (!simple) {
     helper_->SkipOptionalDartType();  // read typedef type.
   }
 
   BuildTypeInternal();  // read return type.
-  signature_function.set_result_type(result_);
+  signature.set_result_type(result_);
 
   finalize_ = finalize;
 
-  Type& signature_type =
-      Type::ZoneHandle(Z, signature_function.SignatureType(nullability));
-
   if (finalize_) {
-    signature_type ^= ClassFinalizer::FinalizeType(signature_type);
-    // Do not refer to signature_function anymore, since it may have been
-    // replaced during canonicalization.
-    signature_function = Function::null();
+    signature ^= ClassFinalizer::FinalizeType(signature);
   }
 
-  result_ = signature_type.raw();
+  result_ = signature.ptr();
 }
 
 void TypeTranslator::BuildTypeParameterType() {
   Nullability nullability = helper_->ReadNullability();
-  if (apply_legacy_erasure_) {
+  if (apply_canonical_type_erasure_ && nullability != Nullability::kNullable) {
     nullability = Nullability::kLegacy;
   }
 
@@ -3288,8 +3288,7 @@
   // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to
   // finalize the argument types.
   // (This can for example make the [type_arguments] vector larger)
-  Type& type = Type::Handle(
-      Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource));
+  Type& type = Type::Handle(Z, Type::New(receiver_class, type_arguments));
   if (finalize_) {
     type ^= ClassFinalizer::FinalizeType(type);
   }
@@ -3301,16 +3300,23 @@
 
 void TypeTranslator::LoadAndSetupTypeParameters(
     ActiveClass* active_class,
-    const Object& set_on,
+    const Function& function,
+    const Class& parameterized_class,
+    const FunctionType& parameterized_signature,
     intptr_t type_parameter_count,
-    const Function& parameterized_function) {
+    const NNBDMode nnbd_mode) {
+  ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
   ASSERT(type_parameter_count >= 0);
   if (type_parameter_count == 0) {
     return;
   }
-  ASSERT(set_on.IsClass() || set_on.IsFunction());
-  bool set_on_class = set_on.IsClass();
-  ASSERT(set_on_class == parameterized_function.IsNull());
+
+  // The finalized index of a type parameter can only be determined if the
+  // length of the flattened type argument vector is known, which in turn can
+  // only be determined after the super type and its class have been loaded.
+  // Due to the added complexity of loading classes out of order from the kernel
+  // file, class type parameter indices are not finalized during class loading.
+  // However, function type parameter indices can be immediately finalized.
 
   // First setup the type parameters, so if any of the following code uses it
   // (in a recursive way) we're fine.
@@ -3318,42 +3324,50 @@
   TypeParameter& parameter = TypeParameter::Handle(Z);
   const Type& null_bound = Type::Handle(Z);
 
-  const NNBDMode nnbd_mode = set_on.IsClass()
-                                 ? Class::Cast(set_on).nnbd_mode()
-                                 : Function::Cast(set_on).nnbd_mode();
   const Nullability nullability = (nnbd_mode == NNBDMode::kOptedInLib)
                                       ? Nullability::kNonNullable
                                       : Nullability::kLegacy;
 
-  // Step a) Create array of [TypeParameter] objects (without bound).
+  // Step a)
+  // - Create array of [TypeParameter] objects (without bound).
+  // - Create array of [String] objects.
   type_parameters = TypeArguments::New(type_parameter_count);
+  intptr_t offset = 0;
+  if (!parameterized_class.IsNull()) {
+    ASSERT(parameterized_class.type_parameters() == TypeArguments::null());
+    parameterized_class.set_type_parameters(type_parameters);
+  } else {
+    ASSERT(parameterized_signature.type_parameters() == TypeArguments::null());
+    parameterized_signature.set_type_parameters(type_parameters);
+    offset = parameterized_signature.NumParentTypeArguments();
+    if (!function.IsNull()) {
+      function.SetNumTypeParameters(type_parameter_count);
+    }
+  }
+
   const Library& lib = Library::Handle(Z, active_class->klass->library());
   {
     AlternativeReadingScope alt(&helper_->reader_);
+    String& name = String::Handle(Z);
     for (intptr_t i = 0; i < type_parameter_count; i++) {
       TypeParameterHelper helper(helper_);
       helper.Finish();
+      if (parameterized_class.IsNull() && function.IsNull()) {
+        // Erase provided name and use a canonical one instead.
+        name = Symbols::NewFormatted(H.thread(), "X%" Pd, offset + i);
+      } else {
+        name = H.DartIdentifier(lib, helper.name_index_).ptr();
+      }
       parameter = TypeParameter::New(
-          set_on_class ? *active_class->klass : Class::Handle(Z),
-          parameterized_function, i,
-          H.DartIdentifier(lib, helper.name_index_),  // read ith name index.
-          null_bound, helper.IsGenericCovariantImpl(), nullability,
-          TokenPosition::kNoSource);
-      parameter.SetCanonical();
-      parameter.SetDeclaration(true);
+          parameterized_class, offset, offset + i, name, null_bound,
+          helper.IsGenericCovariantImpl(), nullability);
       type_parameters.SetTypeAt(i, parameter);
     }
   }
 
-  if (set_on.IsClass()) {
-    Class::Cast(set_on).set_type_parameters(type_parameters);
-  } else {
-    Function::Cast(set_on).set_type_parameters(type_parameters);
-  }
-
-  const Function* enclosing = NULL;
-  if (!parameterized_function.IsNull()) {
-    enclosing = &parameterized_function;
+  const FunctionType* enclosing = NULL;
+  if (!parameterized_signature.IsNull()) {
+    enclosing = &parameterized_signature;
   }
   ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z);
 
@@ -3374,9 +3388,8 @@
     helper.Finish();
   }
 
-  if (set_on.IsFunction()) {
-    Function::Cast(set_on).UpdateCachedDefaultTypeArguments(Thread::Current());
-  }
+  // Note that function.UpdateCachedDefaultTypeArguments() is called in
+  // function.set_signature() and is not required here.
 
   // Fix bounds and default arguments in all derived type parameters (with
   // different nullabilities).
@@ -3387,10 +3400,13 @@
          i < n; ++i) {
       derived ^= active_class->derived_type_parameters->At(i);
       if (derived.bound() == AbstractType::null() &&
-          (derived.parameterized_class() == set_on.raw() ||
-           derived.parameterized_function() == set_on.raw())) {
-        ASSERT(!derived.IsFinalized());
-        parameter ^= type_parameters.TypeAt(derived.index());
+          ((!parameterized_class.IsNull() &&
+            derived.parameterized_class() == parameterized_class.ptr()) ||
+           (!parameterized_signature.IsNull() &&
+            derived.parameterized_class() == Class::null() &&
+            derived.index() >= offset &&
+            derived.index() < offset + type_parameter_count))) {
+        parameter ^= type_parameters.TypeAt(derived.index() - offset);
         type = parameter.bound();
         derived.set_bound(type);
         type = parameter.default_argument();
@@ -3402,7 +3418,6 @@
 
 const Type& TypeTranslator::ReceiverType(const Class& klass) {
   ASSERT(!klass.IsNull());
-  ASSERT(!klass.IsTypedefClass());
   // Note that if klass is _Closure, the returned type will be _Closure,
   // and not the signature type.
   Type& type = Type::ZoneHandle(Z);
@@ -3410,7 +3425,7 @@
     type = klass.DeclarationType();
   } else {
     type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
-                     klass.token_pos(), Nullability::kNonNullable);
+                     Nullability::kNonNullable);
   }
   return type;
 }
@@ -3522,13 +3537,16 @@
   bool is_factory = function.IsFactory();
   intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0;
 
+  const FunctionType& signature = FunctionType::Handle(Z, function.signature());
+  ASSERT(!signature.IsNull());
   if (!is_factory) {
-    LoadAndSetupTypeParameters(active_class_, function,
-                               helper_->ReadListLength(), function);
+    LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
+                               signature, helper_->ReadListLength(),
+                               function.nnbd_mode());
     function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
   }
 
-  ActiveTypeParametersScope scope(active_class_, function, Z);
+  ActiveTypeParametersScope scope(active_class_, function, &signature, Z);
 
   function_node_helper->ReadUntilExcluding(
       FunctionNodeHelper::kPositionalParameters);
@@ -3553,23 +3571,27 @@
   }
   intptr_t parameter_count = extra_parameters + total_parameter_count;
 
-  function.set_parameter_types(
-      Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
-  function.CreateNameArrayIncludingFlags(Heap::kOld);
   intptr_t pos = 0;
-  if (is_method) {
-    ASSERT(!klass.IsNull());
-    function.SetParameterTypeAt(pos, H.GetDeclarationType(klass));
-    function.SetParameterNameAt(pos, Symbols::This());
-    pos++;
-  } else if (is_closure) {
-    function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
-    function.SetParameterNameAt(pos, Symbols::ClosureParameter());
-    pos++;
-  } else if (is_factory) {
-    function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
-    function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
-    pos++;
+  if (parameter_count > 0) {
+    signature.set_parameter_types(
+        Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
+    signature.CreateNameArrayIncludingFlags(Heap::kOld);
+    if (is_method) {
+      ASSERT(!klass.IsNull());
+      signature.SetParameterTypeAt(pos, H.GetDeclarationType(klass));
+      signature.SetParameterNameAt(pos, Symbols::This());
+      pos++;
+    } else if (is_closure) {
+      signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
+      signature.SetParameterNameAt(pos, Symbols::ClosureParameter());
+      pos++;
+    } else if (is_factory) {
+      signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
+      signature.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
+      pos++;
+    }
+  } else {
+    ASSERT(!is_method && !is_closure && !is_factory);
   }
 
   const Library& lib = Library::Handle(Z, active_class_->klass->library());
@@ -3585,8 +3607,9 @@
       helper_->SkipExpression();  // read (actual) initializer.
     }
 
-    function.SetParameterTypeAt(pos, type);
-    function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
+    signature.SetParameterTypeAt(pos, type);
+    signature.SetParameterNameAt(pos,
+                                 H.DartIdentifier(lib, helper.name_index_));
   }
 
   intptr_t named_parameter_count_check =
@@ -3602,13 +3625,14 @@
       helper_->SkipExpression();  // read (actual) initializer.
     }
 
-    function.SetParameterTypeAt(pos, type);
-    function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
+    signature.SetParameterTypeAt(pos, type);
+    signature.SetParameterNameAt(pos,
+                                 H.DartIdentifier(lib, helper.name_index_));
     if (helper.IsRequired()) {
-      function.SetIsRequiredAt(pos);
+      signature.SetIsRequiredAt(pos);
     }
   }
-  function.TruncateUnusedParameterFlags();
+  signature.FinalizeNameArrays(function);
 
   function_node_helper->SetJustRead(FunctionNodeHelper::kNamedParameters);
 
@@ -3616,7 +3640,7 @@
   if (!function.IsGenerativeConstructor()) {
     const AbstractType& return_type =
         BuildTypeWithoutFinalization();  // read return type.
-    function.set_result_type(return_type);
+    signature.set_result_type(return_type);
     function_node_helper->SetJustRead(FunctionNodeHelper::kReturnType);
   }
 }
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 36c8a5e..9eaf327 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -196,7 +196,7 @@
 
   void SetExpressionEvaluationFunction(const Function& function) {
     ASSERT(expression_evaluation_function_ == nullptr);
-    expression_evaluation_function_ = &Function::Handle(zone_, function.raw());
+    expression_evaluation_function_ = &Function::Handle(zone_, function.ptr());
   }
   const Function& GetExpressionEvaluationFunction() {
     if (expression_evaluation_function_ == nullptr) {
@@ -207,11 +207,11 @@
   void SetExpressionEvaluationRealClass(const Class& real_class) {
     ASSERT(expression_evaluation_real_class_ == nullptr);
     ASSERT(!real_class.IsNull());
-    expression_evaluation_real_class_ = &Class::Handle(zone_, real_class.raw());
+    expression_evaluation_real_class_ = &Class::Handle(zone_, real_class.ptr());
   }
   ClassPtr GetExpressionEvaluationRealClass() {
     ASSERT(expression_evaluation_real_class_ != nullptr);
-    return expression_evaluation_real_class_->raw();
+    return expression_evaluation_real_class_->ptr();
   }
 
  private:
@@ -296,8 +296,8 @@
   void SetNext(Field field) { next_read_ = field; }
   void SetJustRead(Field field) { next_read_ = field + 1; }
 
-  TokenPosition position_;
-  TokenPosition end_position_;
+  TokenPosition position_ = TokenPosition::kNoSource;
+  TokenPosition end_position_ = TokenPosition::kNoSource;
   AsyncMarker async_marker_;
   AsyncMarker dart_async_marker_;
   intptr_t total_parameter_count_ = 0;
@@ -352,7 +352,7 @@
     return (flags_ & kIsGenericCovariantImpl) != 0;
   }
 
-  TokenPosition position_;
+  TokenPosition position_ = TokenPosition::kNoSource;
   uint8_t flags_ = 0;
   StringIndex name_index_;
 
@@ -415,8 +415,8 @@
     return (flags_ & kIsGenericCovariantImpl) != 0;
   }
 
-  TokenPosition position_;
-  TokenPosition equals_position_;
+  TokenPosition position_ = TokenPosition::kNoSource;
+  TokenPosition equals_position_ = TokenPosition::kNoSource;
   uint8_t flags_ = 0;
   StringIndex name_index_;
   intptr_t annotation_count_ = 0;
@@ -456,10 +456,10 @@
     kFinal = 1 << 0,
     kConst = 1 << 1,
     kStatic = 1 << 2,
-    kIsCovariant = 1 << 5,
-    kIsGenericCovariantImpl = 1 << 6,
-    kIsLate = 1 << 7,
-    kExtensionMember = 1 << 8,
+    kIsCovariant = 1 << 3,
+    kIsGenericCovariantImpl = 1 << 4,
+    kIsLate = 1 << 5,
+    kExtensionMember = 1 << 6,
   };
 
   explicit FieldHelper(KernelReaderHelper* helper)
@@ -488,8 +488,8 @@
 
   NameIndex canonical_name_getter_;
   NameIndex canonical_name_setter_;
-  TokenPosition position_;
-  TokenPosition end_position_;
+  TokenPosition position_ = TokenPosition::kNoSource;
+  TokenPosition end_position_ = TokenPosition::kNoSource;
   uint32_t flags_ = 0;
   intptr_t source_uri_index_ = 0;
   intptr_t annotation_count_ = 0;
@@ -537,12 +537,12 @@
 
   enum StubKind {
     kRegularStubKind,
-    kForwardingStubKind,
-    kForwardingSuperStubKind,
+    kAbstractForwardingStubKind,
+    kConcreteForwardingStubKind,
     kNoSuchMethodForwarderStubKind,
     kMemberSignatureStubKind,
-    kMixinStubKind,
-    kMixinSuperStubKind,
+    kAbstractMixinStubKind,
+    kConcreteMixinStubKind,
   };
 
   enum Flag {
@@ -574,8 +574,8 @@
   bool IsExternal() const { return (flags_ & kExternal) != 0; }
   bool IsConst() const { return (flags_ & kConst) != 0; }
   bool IsForwardingStub() const {
-    return stub_kind_ == kForwardingStubKind ||
-           stub_kind_ == kForwardingSuperStubKind;
+    return stub_kind_ == kAbstractForwardingStubKind ||
+           stub_kind_ == kConcreteForwardingStubKind;
   }
   bool IsRedirectingFactoryConstructor() const {
     return (flags_ & kRedirectingFactoryConstructor) != 0;
@@ -589,9 +589,9 @@
   }
 
   NameIndex canonical_name_;
-  TokenPosition start_position_;
-  TokenPosition position_;
-  TokenPosition end_position_;
+  TokenPosition start_position_ = TokenPosition::kNoSource;
+  TokenPosition position_ = TokenPosition::kNoSource;
+  TokenPosition end_position_ = TokenPosition::kNoSource;
   Kind kind_;
   uint32_t flags_ = 0;
   intptr_t source_uri_index_ = 0;
@@ -599,7 +599,7 @@
   StubKind stub_kind_;
 
   // Only valid if the 'isForwardingStub' flag is set.
-  NameIndex forwarding_stub_super_target_;
+  NameIndex concrete_forwarding_stub_target_;
 
  private:
   KernelReaderHelper* helper_;
@@ -655,9 +655,9 @@
   bool IsSynthetic() { return (flags_ & kSynthetic) != 0; }
 
   NameIndex canonical_name_;
-  TokenPosition start_position_;
-  TokenPosition position_;
-  TokenPosition end_position_;
+  TokenPosition start_position_ = TokenPosition::kNoSource;
+  TokenPosition position_ = TokenPosition::kNoSource;
+  TokenPosition end_position_ = TokenPosition::kNoSource;
   uint8_t flags_ = 0;
   intptr_t source_uri_index_ = 0;
   intptr_t annotation_count_ = 0;
@@ -733,9 +733,9 @@
   }
 
   NameIndex canonical_name_;
-  TokenPosition start_position_;
-  TokenPosition position_;
-  TokenPosition end_position_;
+  TokenPosition start_position_ = TokenPosition::kNoSource;
+  TokenPosition position_ = TokenPosition::kNoSource;
+  TokenPosition end_position_ = TokenPosition::kNoSource;
   StringIndex name_index_;
   intptr_t source_uri_index_ = 0;
   intptr_t annotation_count_ = 0;
@@ -1316,12 +1316,12 @@
 
   bool MemberIsProcedure() {
     ASSERT(member != NULL);
-    FunctionLayout::Kind function_kind = member->kind();
-    return function_kind == FunctionLayout::kRegularFunction ||
-           function_kind == FunctionLayout::kGetterFunction ||
-           function_kind == FunctionLayout::kSetterFunction ||
-           function_kind == FunctionLayout::kMethodExtractor ||
-           function_kind == FunctionLayout::kDynamicInvocationForwarder ||
+    UntaggedFunction::Kind function_kind = member->kind();
+    return function_kind == UntaggedFunction::kRegularFunction ||
+           function_kind == UntaggedFunction::kGetterFunction ||
+           function_kind == UntaggedFunction::kSetterFunction ||
+           function_kind == UntaggedFunction::kMethodExtractor ||
+           function_kind == UntaggedFunction::kDynamicInvocationForwarder ||
            member->IsFactory();
   }
 
@@ -1330,7 +1330,7 @@
     return member->IsFactory();
   }
 
-  bool RequireLegacyErasure(bool null_safety) const {
+  bool RequireConstCanonicalTypeErasure(bool null_safety) const {
     return klass != nullptr && !null_safety &&
            Library::Handle(klass->library()).nnbd_compiled_mode() ==
                NNBDCompiledMode::kAgnostic;
@@ -1346,7 +1346,7 @@
   void RecordDerivedTypeParameter(Zone* zone,
                                   const TypeParameter& original,
                                   const TypeParameter& derived) {
-    if (original.raw() != derived.raw() &&
+    if (original.ptr() != derived.ptr() &&
         original.bound() == AbstractType::null()) {
       if (derived_type_parameters == nullptr) {
         derived_type_parameters = &GrowableObjectArray::Handle(
@@ -1365,9 +1365,9 @@
 
   const Function* member;
 
-  // The innermost enclosing function. This is used for building types, as a
+  // The innermost enclosing signature. This is used for building types, as a
   // parent for function types.
-  const Function* enclosing;
+  const FunctionType* enclosing;
 
   const TypeArguments* local_type_parameters;
 
@@ -1410,9 +1410,9 @@
 class ActiveEnclosingFunctionScope {
  public:
   ActiveEnclosingFunctionScope(ActiveClass* active_class,
-                               const Function* enclosing)
+                               const FunctionType* enclosing_signature)
       : active_class_(active_class), saved_(*active_class) {
-    active_class_->enclosing = enclosing;
+    active_class_->enclosing = enclosing_signature;
   }
 
   ~ActiveEnclosingFunctionScope() { *active_class_ = saved_; }
@@ -1430,16 +1430,17 @@
   // parameters defined by 'innermost' and any enclosing *closures* (but not
   // enclosing methods/top-level functions/classes).
   //
-  // Also, the enclosing function is set to 'innermost'.
+  // Also, the enclosing signature is set to innermost's signature.
   ActiveTypeParametersScope(ActiveClass* active_class,
                             const Function& innermost,
+                            const FunctionType* innermost_signature,
                             Zone* Z);
 
   // Append the list of the local type parameters to the list in ActiveClass.
   //
-  // Also, the enclosing function is set to 'function'.
+  // Also, the enclosing signature is set to 'signature'.
   ActiveTypeParametersScope(ActiveClass* active_class,
-                            const Function* function,
+                            const FunctionType* innermost_signature,
                             const TypeArguments& new_params,
                             Zone* Z);
 
@@ -1458,7 +1459,7 @@
                  ConstantReader* constant_reader,
                  ActiveClass* active_class,
                  bool finalize = false,
-                 bool apply_legacy_erasure = false);
+                 bool apply_canonical_type_erasure = false);
 
   AbstractType& BuildType();
   AbstractType& BuildTypeWithoutFinalization();
@@ -1470,9 +1471,11 @@
       intptr_t length);
 
   void LoadAndSetupTypeParameters(ActiveClass* active_class,
-                                  const Object& set_on,
+                                  const Function& function,
+                                  const Class& parameterized_class,
+                                  const FunctionType& parameterized_signature,
                                   intptr_t type_parameter_count,
-                                  const Function& parameterized_function);
+                                  const NNBDMode nnbd_mode);
 
   const Type& ReceiverType(const Class& klass);
 
@@ -1530,7 +1533,7 @@
   Zone* zone_;
   AbstractType& result_;
   bool finalize_;
-  const bool apply_legacy_erasure_;
+  const bool apply_canonical_type_erasure_;
 
   friend class ScopeBuilder;
   friend class KernelLoader;
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index 64fb780..6b1fee9 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -205,8 +205,8 @@
   } else {
     ASSERT(num_opt_named_params > 0);
 
-    bool check_required_params =
-        Isolate::Current()->use_strict_null_safety_checks();
+    const bool check_required_params =
+        IsolateGroup::Current()->use_strict_null_safety_checks();
     const intptr_t first_name_offset =
         compiler::target::ArgumentsDescriptor::first_named_entry_offset() -
         compiler::target::Array::data_offset();
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index ba75d00..11f7de3 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -14,6 +14,7 @@
 #define H (translation_helper_)
 #define T (type_translator_)
 #define I Isolate::Current()
+#define IG IsolateGroup::Current()
 
 ScopeBuilder::ScopeBuilder(ParsedFunction* parsed_function)
     : result_(NULL),
@@ -53,14 +54,16 @@
 
   // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
   // e.g. for type translation.
-  const Class& klass = Class::Handle(zone_, function.Owner());
+  const Class& klass = Class::Handle(Z, function.Owner());
 
   Function& outermost_function =
       Function::Handle(Z, function.GetOutermostFunction());
 
   ActiveClassScope active_class_scope(&active_class_, &klass);
   ActiveMemberScope active_member(&active_class_, &outermost_function);
-  ActiveTypeParametersScope active_type_params(&active_class_, function, Z);
+  FunctionType& signature = FunctionType::Handle(Z, function.signature());
+  ActiveTypeParametersScope active_type_params(&active_class_, function,
+                                               &signature, Z);
 
   LocalScope* enclosing_scope = NULL;
   if (function.IsImplicitClosureFunction() && !function.is_static()) {
@@ -87,7 +90,7 @@
   scope_->set_end_token_pos(function.end_token_pos());
 
   // Add function type arguments variable before current context variable.
-  if ((function.IsGeneric() || function.HasGenericParent())) {
+  if (function.IsGeneric() || function.HasGenericParent()) {
     LocalVariable* type_args_var = MakeVariable(
         TokenPosition::kNoSource, TokenPosition::kNoSource,
         Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
@@ -113,7 +116,7 @@
           function.kernel_offset());
 
   switch (function.kind()) {
-    case FunctionLayout::kImplicitClosureFunction: {
+    case UntaggedFunction::kImplicitClosureFunction: {
       const auto& parent = Function::Handle(Z, function.parent_function());
       const auto& target =
           Function::Handle(Z, function.ImplicitClosureTarget(Z));
@@ -126,11 +129,11 @@
       }
     }
       FALL_THROUGH;
-    case FunctionLayout::kClosureFunction:
-    case FunctionLayout::kRegularFunction:
-    case FunctionLayout::kGetterFunction:
-    case FunctionLayout::kSetterFunction:
-    case FunctionLayout::kConstructor: {
+    case UntaggedFunction::kClosureFunction:
+    case UntaggedFunction::kRegularFunction:
+    case UntaggedFunction::kGetterFunction:
+    case UntaggedFunction::kSetterFunction:
+    case UntaggedFunction::kConstructor: {
       const Tag tag = helper_.PeekTag();
       helper_.ReadUntilFunctionNode();
       function_node_helper.ReadUntilExcluding(
@@ -201,7 +204,7 @@
         ASSERT(
             Class::Handle(
                 AbstractType::Handle(function.ParameterTypeAt(1)).type_class())
-                .ScrubbedName() == Symbols::_SyncIterator().raw());
+                .ScrubbedName() == Symbols::_SyncIterator().ptr());
         type_check_mode = kTypeCheckForStaticFunction;
       } else if (function.is_static()) {
         // In static functions we don't check anything.
@@ -244,8 +247,8 @@
       }
       break;
     }
-    case FunctionLayout::kImplicitGetter:
-    case FunctionLayout::kImplicitSetter: {
+    case UntaggedFunction::kImplicitGetter:
+    case UntaggedFunction::kImplicitSetter: {
       ASSERT(helper_.PeekTag() == kField);
       const bool is_setter = function.IsImplicitSetterFunction();
       const bool is_method = !function.IsStaticFunction();
@@ -290,7 +293,7 @@
       }
       break;
     }
-    case FunctionLayout::kImplicitStaticGetter: {
+    case UntaggedFunction::kImplicitStaticGetter: {
       ASSERT(helper_.PeekTag() == kField);
       ASSERT(function.IsStaticFunction());
       // In addition to static field initializers, scopes/local variables
@@ -301,7 +304,7 @@
       }
       break;
     }
-    case FunctionLayout::kFieldInitializer: {
+    case UntaggedFunction::kFieldInitializer: {
       ASSERT(helper_.PeekTag() == kField);
       if (!function.is_static()) {
         Class& klass = Class::Handle(Z, function.Owner());
@@ -315,7 +318,7 @@
       VisitNode();
       break;
     }
-    case FunctionLayout::kDynamicInvocationForwarder: {
+    case UntaggedFunction::kDynamicInvocationForwarder: {
       const String& name = String::Handle(Z, function.name());
       ASSERT(Function::IsDynamicInvocationForwarderName(name));
 
@@ -363,7 +366,7 @@
           attrs);
       break;
     }
-    case FunctionLayout::kMethodExtractor: {
+    case UntaggedFunction::kMethodExtractor: {
       // Add a receiver parameter.  Though it is captured, we emit code to
       // explicitly copy it to a fixed offset in a freshly-allocated context
       // instead of using the generic code for regular functions.
@@ -377,7 +380,7 @@
       parsed_function_->set_receiver_var(variable);
       break;
     }
-    case FunctionLayout::kFfiTrampoline: {
+    case UntaggedFunction::kFfiTrampoline: {
       needs_expr_temp_ = true;
       // Callbacks and calls with handles need try/catch variables.
       if ((function.FfiCallbackTarget() != Function::null() ||
@@ -393,7 +396,7 @@
       }
       FALL_THROUGH;
     }
-    case FunctionLayout::kInvokeFieldDispatcher: {
+    case UntaggedFunction::kInvokeFieldDispatcher: {
       if (function.IsDynamicClosureCallDispatcher()) {
         auto const vars = parsed_function_->EnsureDynamicClosureCallVars();
         ASSERT(vars != nullptr);
@@ -406,20 +409,19 @@
       }
     }
       FALL_THROUGH;
-    case FunctionLayout::kNoSuchMethodDispatcher: {
+    case UntaggedFunction::kNoSuchMethodDispatcher: {
       for (intptr_t i = 0; i < function.NumParameters(); ++i) {
         LocalVariable* variable = MakeVariable(
             TokenPosition::kNoSource, TokenPosition::kNoSource,
             String::ZoneHandle(Z, function.ParameterNameAt(i)),
             AbstractType::ZoneHandle(Z, function.IsFfiTrampoline()
                                             ? function.ParameterTypeAt(i)
-                                            : Object::dynamic_type().raw()));
+                                            : Object::dynamic_type().ptr()));
         scope_->InsertParameterAt(i, variable);
       }
       break;
     }
-    case FunctionLayout::kSignatureFunction:
-    case FunctionLayout::kIrregexpFunction:
+    case UntaggedFunction::kIrregexpFunction:
       UNREACHABLE();
   }
   if (needs_expr_temp_) {
@@ -964,7 +966,7 @@
     case kEmptyStatement:
       return;
     case kAssertBlock:
-      if (I->asserts()) {
+      if (IG->asserts()) {
         PositionScope scope(&helper_.reader_);
         intptr_t offset =
             helper_.ReaderOffset() - 1;  // -1 to include tag byte.
@@ -984,7 +986,7 @@
       }
       return;
     case kAssertStatement:
-      if (I->asserts()) {
+      if (IG->asserts()) {
         VisitExpression();            // Read condition.
         helper_.ReadPosition();       // read condition start offset.
         helper_.ReadPosition();       // read condition end offset.
@@ -1399,7 +1401,7 @@
 }
 
 void ScopeBuilder::VisitTypeParameterType() {
-  Function& function = Function::Handle(Z, parsed_function_->function().raw());
+  Function& function = Function::Handle(Z, parsed_function_->function().ptr());
   while (function.IsClosureFunction()) {
     function = function.parent_function();
   }
@@ -1535,7 +1537,7 @@
   if (helper.IsCovariant()) {
     variable->set_is_explicit_covariant_parameter();
   }
-  if (variable->name().raw() == Symbols::IteratorParameter().raw()) {
+  if (variable->name().ptr() == Symbols::IteratorParameter().ptr()) {
     variable->set_is_forced_stack();
   }
 
diff --git a/runtime/vm/compiler/frontend/scope_builder.h b/runtime/vm/compiler/frontend/scope_builder.h
index c8680c3..1531508 100644
--- a/runtime/vm/compiler/frontend/scope_builder.h
+++ b/runtime/vm/compiler/frontend/scope_builder.h
@@ -162,7 +162,7 @@
   intptr_t name_index_;
 
   bool needs_expr_temp_;
-  TokenPosition first_body_token_position_;
+  TokenPosition first_body_token_position_ = TokenPosition::kNoSource;
 
   KernelReaderHelper helper_;
   ConstantReader constant_reader_;
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 2e0c310..61cf909 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -46,8 +46,6 @@
   // `compiler->is_optimizing()` is set to true during EmitNativeCode.
   GraphInstrinsicCodeGenScope optimizing_scope(compiler);
 
-  // The FlowGraph here is constructed by the intrinsics builder methods, and
-  // is different from compiler->flow_graph(), the original method's flow graph.
   compiler->assembler()->Comment("Graph intrinsic begin");
   for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) {
     BlockEntryInstr* block = graph->reverse_postorder()[i];
@@ -95,6 +93,8 @@
 
   FlowGraph* graph =
       new FlowGraph(parsed_function, graph_entry, block_id, prologue_info);
+  compiler->set_intrinsic_flow_graph(*graph);
+
   const Function& function = parsed_function.function();
 
   switch (function.recognized_kind()) {
@@ -170,8 +170,8 @@
                                     Definition* array,
                                     Definition* index,
                                     const Slot& length_field) {
-  Definition* length = builder->AddDefinition(new LoadFieldInstr(
-      new Value(array), length_field, TokenPosition::kNoSource));
+  Definition* length = builder->AddDefinition(
+      new LoadFieldInstr(new Value(array), length_field, InstructionSource()));
   // Note that the intrinsifier must always use deopting array bound
   // checks, because intrinsics currently don't support calls.
   Definition* safe_index = new CheckArrayBoundInstr(
@@ -247,7 +247,7 @@
   Definition* result = builder.AddDefinition(new LoadIndexedInstr(
       new Value(array), new Value(index), /*index_unboxed=*/false,
       /*index_scale=*/target::Instance::ElementSizeFor(array_cid), array_cid,
-      kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+      kAlignedAccess, DeoptId::kNone, builder.Source()));
 
   // We don't perform [RangeAnalysis] for graph intrinsics. To inform the
   // following boxing instruction about a more precise range we attach it here
@@ -355,7 +355,7 @@
       // maps to kUnboxedInt64. All other situations get away with
       // truncating even non-smi values.
       builder.AddInstruction(new CheckSmiInstr(new Value(value), DeoptId::kNone,
-                                               builder.TokenPos()));
+                                               builder.Source()));
       FALL_THROUGH;
 #endif
     case kTypedDataInt8ArrayCid:
@@ -410,7 +410,7 @@
       Zone* zone = flow_graph->zone();
       Cids* value_check = Cids::CreateMonomorphic(zone, value_check_cid);
       builder.AddInstruction(new CheckClassInstr(
-          new Value(value), DeoptId::kNone, *value_check, builder.TokenPos()));
+          new Value(value), DeoptId::kNone, *value_check, builder.Source()));
       value = builder.AddUnboxInstr(rep, new Value(value),
                                     /* is_checked = */ true);
       if (array_cid == kTypedDataFloat32ArrayCid) {
@@ -434,7 +434,7 @@
       new Value(array), new Value(index), new Value(value), kNoStoreBarrier,
       /*index_unboxed=*/false,
       /*index_scale=*/target::Instance::ElementSizeFor(array_cid), array_cid,
-      kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+      kAlignedAccess, DeoptId::kNone, builder.Source()));
   // Return null.
   Definition* null_def = builder.AddNullDefinition();
   builder.AddReturn(new Value(null_def));
@@ -573,7 +573,7 @@
   Definition* load = builder.AddDefinition(new LoadIndexedInstr(
       new Value(str), new Value(index), /*index_unboxed=*/false,
       target::Instance::ElementSizeFor(cid), cid, kAlignedAccess,
-      DeoptId::kNone, builder.TokenPos()));
+      DeoptId::kNone, builder.Source()));
 
   // We don't perform [RangeAnalysis] for graph intrinsics. To inform the
   // following boxing instruction about a more precise range we attach it here
@@ -631,7 +631,7 @@
   Cids* value_check = Cids::CreateMonomorphic(zone, cid);
   // Check argument. Receiver (left) is known to be a Float32x4.
   builder.AddInstruction(new CheckClassInstr(new Value(right), DeoptId::kNone,
-                                             *value_check, builder.TokenPos()));
+                                             *value_check, builder.Source()));
   Definition* left_simd = builder.AddUnboxInstr(rep, new Value(left),
                                                 /* is_checked = */ true);
 
@@ -737,7 +737,7 @@
   VerifyParameterIsBoxed(&builder, 0);
 
   Definition* length = builder.AddDefinition(
-      new LoadFieldInstr(new Value(array), field, builder.TokenPos()));
+      new LoadFieldInstr(new Value(array), field, builder.Source()));
 
   length = CreateUnboxedResultIfNeeded(&builder, length);
   builder.AddReturn(new Value(length));
@@ -781,9 +781,9 @@
   VerifyParameterIsBoxed(&builder, 0);
 
   Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
-      new Value(array), Slot::GrowableObjectArray_data(), builder.TokenPos()));
+      new Value(array), Slot::GrowableObjectArray_data(), builder.Source()));
   Definition* capacity = builder.AddDefinition(new LoadFieldInstr(
-      new Value(backing_store), Slot::Array_length(), builder.TokenPos()));
+      new Value(backing_store), Slot::Array_length(), builder.Source()));
   capacity = CreateUnboxedResultIfNeeded(&builder, capacity);
   builder.AddReturn(new Value(capacity));
   return true;
@@ -805,11 +805,11 @@
 
   Definition* backing_store = builder.AddDefinition(
       new LoadFieldInstr(new Value(growable_array),
-                         Slot::GrowableObjectArray_data(), builder.TokenPos()));
+                         Slot::GrowableObjectArray_data(), builder.Source()));
   Definition* result = builder.AddDefinition(new LoadIndexedInstr(
       new Value(backing_store), new Value(index), /*index_unboxed=*/false,
       /*index_scale=*/target::Instance::ElementSizeFor(kArrayCid), kArrayCid,
-      kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+      kAlignedAccess, DeoptId::kNone, builder.Source()));
   result = CreateUnboxedResultIfNeeded(&builder, result);
   builder.AddReturn(new Value(result));
   return true;
@@ -836,7 +836,7 @@
       new Value(array), new Value(index), new Value(value), kEmitStoreBarrier,
       /*index_unboxed=*/false,
       /*index_scale=*/target::Instance::ElementSizeFor(kArrayCid), kArrayCid,
-      kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+      kAlignedAccess, DeoptId::kNone, builder.Source()));
   // Return null.
   Definition* null_def = builder.AddNullDefinition();
   builder.AddReturn(new Value(null_def));
@@ -861,13 +861,13 @@
                            Slot::GrowableObjectArray_length());
 
   Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
-      new Value(array), Slot::GrowableObjectArray_data(), builder.TokenPos()));
+      new Value(array), Slot::GrowableObjectArray_data(), builder.Source()));
 
   builder.AddInstruction(new StoreIndexedInstr(
       new Value(backing_store), new Value(index), new Value(value),
       kEmitStoreBarrier, /*index_unboxed=*/false,
       /*index_scale=*/target::Instance::ElementSizeFor(kArrayCid), kArrayCid,
-      kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+      kAlignedAccess, DeoptId::kNone, builder.Source()));
   // Return null.
   Definition* null_def = builder.AddNullDefinition();
   builder.AddReturn(new Value(null_def));
@@ -888,11 +888,11 @@
 
   Cids* value_check = Cids::CreateMonomorphic(zone, kArrayCid);
   builder.AddInstruction(new CheckClassInstr(new Value(data), DeoptId::kNone,
-                                             *value_check, builder.TokenPos()));
+                                             *value_check, builder.Source()));
 
   builder.AddInstruction(new StoreInstanceFieldInstr(
       Slot::GrowableObjectArray_data(), new Value(growable_array),
-      new Value(data), kEmitStoreBarrier, builder.TokenPos()));
+      new Value(data), kEmitStoreBarrier, builder.Source()));
   // Return null.
   Definition* null_def = builder.AddNullDefinition();
   builder.AddReturn(new Value(null_def));
@@ -911,10 +911,10 @@
   VerifyParameterIsBoxed(&builder, 1);
 
   builder.AddInstruction(
-      new CheckSmiInstr(new Value(length), DeoptId::kNone, builder.TokenPos()));
+      new CheckSmiInstr(new Value(length), DeoptId::kNone, builder.Source()));
   builder.AddInstruction(new StoreInstanceFieldInstr(
       Slot::GrowableObjectArray_length(), new Value(growable_array),
-      new Value(length), kNoStoreBarrier, builder.TokenPos()));
+      new Value(length), kNoStoreBarrier, builder.Source()));
   Definition* null_def = builder.AddNullDefinition();
   builder.AddReturn(new Value(null_def));
   return true;
@@ -984,7 +984,7 @@
 
   Definition* unboxed_result =
       builder->AddDefinition(new InvokeMathCFunctionInstr(
-          args, DeoptId::kNone, kind, builder->TokenPos()));
+          args, DeoptId::kNone, kind, builder->Source()));
   Definition* result =
       CreateBoxedResultIfNeeded(builder, unboxed_result, kUnboxedDouble);
   builder->AddReturn(new Value(result));
@@ -1143,7 +1143,7 @@
   ASSERT(Intrinsifier::CanIntrinsifyFieldAccessor(function));
 
   auto& field = Field::Handle(zone, function.accessor_field());
-  if (Field::ShouldCloneFields()) {
+  if (CompilerState::Current().should_clone_fields()) {
     field = field.CloneFromOriginal();
   }
   ASSERT(field.is_instance() && !field.is_late() && !field.needs_load_guard());
@@ -1158,7 +1158,7 @@
   VerifyParameterIsBoxed(&builder, 0);
 
   Definition* field_value = builder.AddDefinition(new (zone) LoadFieldInstr(
-      new (zone) Value(receiver), slot, builder.TokenPos()));
+      new (zone) Value(receiver), slot, builder.Source()));
 
   // We only support cases where we do not have to create a box (whose
   // allocation could fail).
@@ -1186,7 +1186,7 @@
   ASSERT(Intrinsifier::CanIntrinsifyFieldAccessor(function));
 
   auto& field = Field::Handle(zone, function.accessor_field());
-  if (Field::ShouldCloneFields()) {
+  if (CompilerState::Current().should_clone_fields()) {
     field = field.CloneFromOriginal();
   }
   ASSERT(field.is_instance() && !field.is_final());
@@ -1220,7 +1220,7 @@
 
   builder.AddInstruction(new (zone) StoreInstanceFieldInstr(
       slot, new (zone) Value(receiver), new (zone) Value(value), barrier_mode,
-      builder.TokenPos()));
+      builder.Source()));
 
   builder.AddReturn(new (zone) Value(flow_graph->constant_null()));
   return true;
diff --git a/runtime/vm/compiler/graph_intrinsifier_arm.cc b/runtime/vm/compiler/graph_intrinsifier_arm.cc
index 1cebb33..baea3aa 100644
--- a/runtime/vm/compiler/graph_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/graph_intrinsifier_arm.cc
@@ -23,14 +23,16 @@
   COMPILE_ASSERT(IsAbiPreservedRegister(CALLEE_SAVED_TEMP));
 
   // Save LR by moving it to a callee saved temporary register.
-  assembler->Comment("IntrinsicCallPrologue");
-  assembler->mov(CALLEE_SAVED_TEMP, Operand(LR));
+  __ Comment("IntrinsicCallPrologue");
+  SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(
+      __ mov(CALLEE_SAVED_TEMP, Operand(LR)));
 }
 
 void GraphIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
   // Restore LR.
-  assembler->Comment("IntrinsicCallEpilogue");
-  assembler->mov(LR, Operand(CALLEE_SAVED_TEMP));
+  __ Comment("IntrinsicCallEpilogue");
+  RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(
+      __ mov(LR, Operand(CALLEE_SAVED_TEMP)));
 }
 
 #undef __
diff --git a/runtime/vm/compiler/graph_intrinsifier_arm64.cc b/runtime/vm/compiler/graph_intrinsifier_arm64.cc
index 99d33b4..27be6fa 100644
--- a/runtime/vm/compiler/graph_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/graph_intrinsifier_arm64.cc
@@ -27,15 +27,15 @@
   COMPILE_ASSERT(CALLEE_SAVED_TEMP2 != CODE_REG);
   COMPILE_ASSERT(CALLEE_SAVED_TEMP2 != ARGS_DESC_REG);
 
-  assembler->Comment("IntrinsicCallPrologue");
-  assembler->mov(CALLEE_SAVED_TEMP, LR);
-  assembler->mov(CALLEE_SAVED_TEMP2, ARGS_DESC_REG);
+  __ Comment("IntrinsicCallPrologue");
+  SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(__ mov(CALLEE_SAVED_TEMP, LR));
+  __ mov(CALLEE_SAVED_TEMP2, ARGS_DESC_REG);
 }
 
 void GraphIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
-  assembler->Comment("IntrinsicCallEpilogue");
-  assembler->mov(LR, CALLEE_SAVED_TEMP);
-  assembler->mov(ARGS_DESC_REG, CALLEE_SAVED_TEMP2);
+  __ Comment("IntrinsicCallEpilogue");
+  RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(__ mov(LR, CALLEE_SAVED_TEMP));
+  __ mov(ARGS_DESC_REG, CALLEE_SAVED_TEMP2);
 }
 
 #undef __
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 9931e91..a8f9559 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -91,7 +91,7 @@
   // If we intrinsify, the intrinsified code therefore does not depend on the
   // field guard and we do not add it to the guarded fields via
   // [ParsedFunction::AddToGuardedFields].
-  if (Field::ShouldCloneFields()) {
+  if (CompilerState::Current().should_clone_fields()) {
     field = field.CloneFromOriginal();
   }
 
@@ -216,7 +216,7 @@
   };
 
   for (intptr_t i = 0; i < kNumLibs; i++) {
-    lib = intrinsics[i].library.raw();
+    lib = intrinsics[i].library.ptr();
     for (IntrinsicDesc* intrinsic = intrinsics[i].intrinsics;
          intrinsic->class_name != nullptr; intrinsic++) {
       func = Function::null();
@@ -260,7 +260,6 @@
     return false;
   }
 
-  ASSERT(!compiler->flow_graph().IsCompiledForOsr());
   if (GraphIntrinsifier::GraphIntrinsify(parsed_function, compiler)) {
     return compiler->intrinsic_slow_path_label()->IsUnused();
   }
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 3e142f4..06056b5 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -212,6 +212,15 @@
   ASSERT(thread->IsMutatorThread());
   const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
 
+  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
+    // other isolate exited the lock, ensuring the initializing stores for
+    // [function] are visible in the current thread.
+    SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
+  }
+
   // In single-isolate scenarios the lazy compile stub is only invoked if
   // 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
@@ -337,7 +346,7 @@
 
   // CreateDeoptInfo uses the object pool and needs to be done before
   // FinalizeCode.
-  Array& deopt_info_array = Array::Handle(zone, Object::empty_array().raw());
+  Array& deopt_info_array = Array::Handle(zone, Object::empty_array().ptr());
   deopt_info_array = graph_compiler->CreateDeoptInfo(assembler);
 
   // Allocates instruction object. Since this occurs only at safepoint,
@@ -370,64 +379,64 @@
     function.AttachCode(code);
     function.SetWasCompiled(true);
   } else if (optimized()) {
-    // Installs code while at safepoint.
-    if (thread()->IsMutatorThread()) {
-      const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
-      if (!is_osr) {
-        function.InstallOptimizedCode(code);
-      }
-      ASSERT(code.owner() == function.raw());
-    } else {
-      // Background compilation.
-      // Before installing code check generation counts if the code may
-      // have become invalid.
-      const bool trace_compiler =
-          FLAG_trace_compiler || FLAG_trace_optimizing_compiler;
-      bool code_is_valid = true;
-      if (!flow_graph->parsed_function().guarded_fields()->is_empty()) {
-        const ZoneGrowableArray<const Field*>& guarded_fields =
-            *flow_graph->parsed_function().guarded_fields();
-        Field& original = Field::Handle();
-        for (intptr_t i = 0; i < guarded_fields.length(); i++) {
-          const Field& field = *guarded_fields[i];
-          ASSERT(!field.IsOriginal());
-          original = field.Original();
-          if (!field.IsConsistentWith(original)) {
-            code_is_valid = false;
-            if (trace_compiler) {
-              THR_Print("--> FAIL: Field %s guarded state changed.",
-                        field.ToCString());
-            }
-            break;
-          }
-        }
-      }
-      if (!thread()
-               ->compiler_state()
-               .cha()
-               .IsConsistentWithCurrentHierarchy()) {
-        code_is_valid = false;
-        if (trace_compiler) {
-          THR_Print("--> FAIL: Class hierarchy has new subclasses.");
-        }
-      }
+    // We cannot execute generated code while installing code.
+    ASSERT(Thread::Current()->IsAtSafepoint() ||
+           (Thread::Current()->IsMutatorThread() &&
+            IsolateGroup::Current()->ContainsOnlyOneIsolate()));
+    // We are validating our CHA / field guard / ... assumptions. To prevent
+    // another thread from concurrently changing them, we have to guarantee
+    // mutual exclusion.
+    DEBUG_ASSERT(
+        IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
 
-      // Setting breakpoints at runtime could make a function non-optimizable.
-      if (code_is_valid && Compiler::CanOptimizeFunction(thread(), function)) {
-        const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
-        ASSERT(!is_osr);  // OSR is not compiled in background.
+    const bool trace_compiler =
+        FLAG_trace_compiler || FLAG_trace_optimizing_compiler;
+    bool code_is_valid = true;
+    if (!flow_graph->parsed_function().guarded_fields()->is_empty()) {
+      const ZoneGrowableArray<const Field*>& guarded_fields =
+          *flow_graph->parsed_function().guarded_fields();
+      Field& original = Field::Handle();
+      for (intptr_t i = 0; i < guarded_fields.length(); i++) {
+        const Field& field = *guarded_fields[i];
+        ASSERT(!field.IsOriginal());
+        original = field.Original();
+        if (!field.IsConsistentWith(original)) {
+          code_is_valid = false;
+          if (trace_compiler) {
+            THR_Print("--> FAIL: Field %s guarded state changed.",
+                      field.ToCString());
+          }
+          break;
+        }
+      }
+    }
+
+    if (!thread()->compiler_state().cha().IsConsistentWithCurrentHierarchy()) {
+      code_is_valid = false;
+      if (trace_compiler) {
+        THR_Print("--> FAIL: Class hierarchy has new subclasses.");
+      }
+    }
+
+    // Setting breakpoints at runtime could make a function non-optimizable.
+    if (code_is_valid && Compiler::CanOptimizeFunction(thread(), function)) {
+      if (osr_id() == Compiler::kNoOSRDeoptId) {
         function.InstallOptimizedCode(code);
       } else {
-        code = Code::null();
+        // OSR is not compiled in background.
+        ASSERT(!Compiler::IsBackgroundCompilation());
       }
-      if (function.usage_counter() < 0) {
-        // Reset to 0 so that it can be recompiled if needed.
-        if (code_is_valid) {
-          function.SetUsageCounter(0);
-        } else {
-          // Trigger another optimization pass soon.
-          function.SetUsageCounter(FLAG_optimization_counter_threshold - 100);
-        }
+      ASSERT(code.owner() == function.ptr());
+    } else {
+      code = Code::null();
+    }
+    if (function.usage_counter() < 0) {
+      // Reset to 0 so that it can be recompiled if needed.
+      if (code_is_valid) {
+        function.SetUsageCounter(0);
+      } else {
+        // Trigger another optimization pass soon.
+        function.SetUsageCounter(FLAG_optimization_counter_threshold - 100);
       }
     }
 
@@ -460,7 +469,7 @@
       function.SetUsageCounter(0);
     }
   }
-  return code.raw();
+  return code.ptr();
 }
 
 void CompileParsedFunctionHelper::CheckIfBackgroundCompilerIsBeingStopped(
@@ -484,6 +493,7 @@
   }
   Zone* const zone = thread()->zone();
   HANDLESCOPE(thread());
+  EnterCompilerScope cs(thread());
 
   // We may reattempt compilation if the function needs to be assembled using
   // far branches on ARM. In the else branch of the setjmp call, done is set to
@@ -506,7 +516,7 @@
       FlowGraph* flow_graph = nullptr;
       ZoneGrowableArray<const ICData*>* ic_data_array = nullptr;
 
-      CompilerState compiler_state(thread(), /*is_aot=*/false,
+      CompilerState compiler_state(thread(), /*is_aot=*/false, optimized(),
                                    CompilerState::ShouldTrace(function));
 
       {
@@ -577,15 +587,6 @@
       } else if (optimized()) {
         TIMELINE_DURATION(thread(), CompilerVerbose, "OptimizationPasses");
 
-        pass_state.inline_id_to_function.Add(&function);
-        // We do not add the token position now because we don't know the
-        // position of the inlined call until later. A side effect of this
-        // is that the length of |inline_id_to_function| is always larger
-        // than the length of |inline_id_to_token_pos| by one.
-        // Top scope function has no caller (-1). We do this because we expect
-        // all token positions to be at an inlined call.
-        pass_state.caller_inline_id.Add(-1);
-
         JitCallSpecializer call_specializer(flow_graph, &speculative_policy);
         pass_state.call_specializer = &call_specializer;
 
@@ -662,13 +663,13 @@
       // We bailed out or we encountered an error.
       const Error& error = Error::Handle(thread()->StealStickyError());
 
-      if (error.raw() == Object::branch_offset_error().raw()) {
+      if (error.ptr() == Object::branch_offset_error().ptr()) {
         // Compilation failed due to an out of range branch offset in the
         // assembler. We try again (done = false) with far branches enabled.
         done = false;
         ASSERT(!use_far_branches);
         use_far_branches = true;
-      } else if (error.raw() == Object::speculative_inlining_error().raw()) {
+      } else if (error.ptr() == Object::speculative_inlining_error().ptr()) {
         // Can only happen with precompilation.
         UNREACHABLE();
       } else {
@@ -690,7 +691,7 @@
       }
     }
   }
-  return result->raw();
+  return result->ptr();
 }
 
 static ObjectPtr CompileFunctionHelper(CompilationPipeline* pipeline,
@@ -713,10 +714,9 @@
     per_compile_timer.Start();
 
     ParsedFunction* parsed_function = new (zone)
-        ParsedFunction(thread, Function::ZoneHandle(zone, function.raw()));
+        ParsedFunction(thread, Function::ZoneHandle(zone, function.ptr()));
     if (trace_compiler) {
-      const intptr_t token_size =
-          function.end_token_pos().Pos() - function.token_pos().Pos();
+      const intptr_t token_size = function.SourceSize();
       THR_Print("Compiling %s%sfunction %s: '%s' @ token %s, size %" Pd "\n",
                 (osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "),
                 (optimized ? "optimized " : ""),
@@ -747,7 +747,7 @@
 
         // We got an error during compilation.
         // If it was a bailout, then disable optimization.
-        if (error.raw() == Object::background_compilation_error().raw()) {
+        if (error.ptr() == Object::background_compilation_error().ptr()) {
           if (FLAG_trace_compiler) {
             THR_Print(
                 "--> disabling background optimizations for '%s' (will "
@@ -775,7 +775,7 @@
           // The background compiler does not execute Dart code or handle
           // isolate messages.
           ASSERT(!error.IsUnwindError());
-          return error.raw();
+          return error.ptr();
         }
       }
       if (optimized) {
@@ -794,7 +794,7 @@
           function.SetIsOptimizable(false);
           return Error::null();
         }
-        return error.raw();
+        return error.ptr();
       } else {
         ASSERT(!optimized);
         // The non-optimizing compiler can get an unhandled exception
@@ -803,7 +803,7 @@
         ASSERT(error.IsUnhandledException() || error.IsUnwindError() ||
                (error.IsLanguageError() &&
                 LanguageError::Cast(error).kind() != Report::kBailout));
-        return error.raw();
+        return error.ptr();
       }
       UNREACHABLE();
     }
@@ -817,14 +817,14 @@
                 code.Size(), per_compile_timer.TotalElapsedTime());
     }
 
-    return result.raw();
+    return result.ptr();
   } else {
     Thread* const thread = Thread::Current();
     StackZone stack_zone(thread);
     // We got an error during compilation or it is a bailout from background
     // compilation (e.g., during parsing with EnsureIsFinalized).
     const Error& error = Error::Handle(thread->StealStickyError());
-    if (error.raw() == Object::background_compilation_error().raw()) {
+    if (error.ptr() == Object::background_compilation_error().ptr()) {
       // Exit compilation, retry it later.
       if (FLAG_trace_bailout) {
         THR_Print("Aborted background compilation: %s\n",
@@ -834,7 +834,7 @@
     }
     // Do not attempt to optimize functions that can cause errors.
     function.set_is_optimizable(false);
-    return error.raw();
+    return error.ptr();
   }
   UNREACHABLE();
   return Object::null();
@@ -886,16 +886,16 @@
       CompileFunctionHelper(pipeline, function, false, /* not optimized */
                             kNoOSRDeoptId));
   if (result.IsError()) {
-    return Error::Cast(result).raw();
+    return Error::Cast(result).ptr();
   }
   // Since CompileFunctionHelper replaces the current code, re-attach the
   // the original code if the function was already compiled.
-  if (!original_code.IsNull() && result.raw() == function.CurrentCode() &&
+  if (!original_code.IsNull() && result.ptr() == function.CurrentCode() &&
       !original_code.IsDisabled()) {
     function.AttachCode(original_code);
   }
   ASSERT(function.unoptimized_code() != Object::null());
-  ASSERT(function.unoptimized_code() == result.raw());
+  ASSERT(function.unoptimized_code() == result.ptr());
   if (FLAG_trace_compiler) {
     THR_Print("Ensure unoptimized code for %s\n", function.ToCString());
   }
@@ -935,11 +935,11 @@
   // if state changed while compiling in background.
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  CompilerState state(thread, /*is_aot=*/false);
+  CompilerState state(thread, /*is_aot=*/false, /*is_optimizing=*/false);
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     ParsedFunction* parsed_function =
-        new ParsedFunction(thread, Function::ZoneHandle(zone, function.raw()));
+        new ParsedFunction(thread, Function::ZoneHandle(zone, function.ptr()));
     ZoneGrowableArray<const ICData*>* ic_data_array =
         new ZoneGrowableArray<const ICData*>();
     ZoneGrowableArray<intptr_t>* context_level_array =
@@ -978,7 +978,7 @@
     if (!func.HasCode() && !func.is_abstract()) {
       result = CompileFunction(thread, func);
       if (result.IsError()) {
-        return Error::Cast(result).raw();
+        return Error::Cast(result).ptr();
       }
       ASSERT(!result.IsNull());
     }
@@ -1010,7 +1010,7 @@
 class QueueElement {
  public:
   explicit QueueElement(const Function& function)
-      : next_(NULL), function_(function.raw()) {}
+      : next_(NULL), function_(function.ptr()) {}
 
   virtual ~QueueElement() {
     next_ = NULL;
@@ -1023,7 +1023,9 @@
   QueueElement* next() const { return next_; }
 
   ObjectPtr function() const { return function_; }
-  ObjectPtr* function_ptr() { return reinterpret_cast<ObjectPtr*>(&function_); }
+  ObjectPtr* function_untag() {
+    return reinterpret_cast<ObjectPtr*>(&function_);
+  }
 
  private:
   QueueElement* next_;
@@ -1043,7 +1045,7 @@
     ASSERT(visitor != NULL);
     QueueElement* p = first_;
     while (p != NULL) {
-      visitor->VisitPointer(p->function_ptr());
+      visitor->VisitPointer(p->function_untag());
       p = p->next();
     }
   }
@@ -1088,7 +1090,7 @@
   bool ContainsObj(const Object& obj) const {
     QueueElement* p = first_;
     while (p != NULL) {
-      if (p->function() == obj.raw()) {
+      if (p->function() == obj.ptr()) {
         return true;
       }
       p = p->next();
@@ -1291,9 +1293,9 @@
 
 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
   const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
-  FATAL3("Precompilation missed function %s (%" Pd ", %s)\n",
+  FATAL3("Precompilation missed function %s (%s, %s)\n",
          function.ToLibNamePrefixedQualifiedCString(),
-         function.token_pos().value(),
+         function.token_pos().ToCString(),
          Function::KindToCString(function.kind()));
 }
 
diff --git a/runtime/vm/compiler/jit/compiler.h b/runtime/vm/compiler/jit/compiler.h
index 75d59521..2e2d563 100644
--- a/runtime/vm/compiler/jit/compiler.h
+++ b/runtime/vm/compiler/jit/compiler.h
@@ -79,8 +79,8 @@
   // Generates code for given function without optimization and sets its code
   // field.
   //
-  // Returns the raw code object if compilation succeeds.  Otherwise returns a
-  // RawError.  Also installs the generated code on the function.
+  // Returns the raw code object if compilation succeeds.  Otherwise returns an
+  // ErrorPtr.  Also installs the generated code on the function.
   static ObjectPtr CompileFunction(Thread* thread, const Function& function);
 
   // Generates unoptimized code if not present, current code is unchanged.
diff --git a/runtime/vm/compiler/jit/jit_call_specializer.cc b/runtime/vm/compiler/jit/jit_call_specializer.cc
index 05ce2af..873174d 100644
--- a/runtime/vm/compiler/jit/jit_call_specializer.cc
+++ b/runtime/vm/compiler/jit/jit_call_specializer.cc
@@ -35,7 +35,7 @@
     SpeculativeInliningPolicy* speculative_policy)
     : CallSpecializer(flow_graph,
                       speculative_policy,
-                      Field::ShouldCloneFields()) {}
+                      CompilerState::Current().should_clone_fields()) {}
 
 bool JitCallSpecializer::IsAllowedForInlining(intptr_t deopt_id) const {
   return true;
@@ -203,12 +203,16 @@
           THR_Print("  getter usage count: %" Pd "\n", getter.usage_counter());
         }
       }
-      ASSERT(field.IsOriginal());
-      field.set_is_unboxing_candidate(false);
-      Thread* thread = Thread::Current();
-      SafepointWriteRwLocker ml(thread,
-                                thread->isolate_group()->program_lock());
-      field.DeoptimizeDependentCode();
+      // We determined it's not beneficial for performance to unbox the
+      // field, therefore we mark it as boxed here.
+      //
+      // Calling `DisableFieldUnboxing` will cause transition the field to
+      // boxed and deoptimize dependent code.
+      //
+      // NOTE: It will also, as a side-effect, change our field clone's
+      // `is_unboxing_candidate()` bit. So we assume the compiler has so far
+      // not relied on this bit.
+      field.DisableFieldUnboxing();
     } else {
       flow_graph()->parsed_function().AddToGuardedFields(&field);
     }
@@ -226,7 +230,7 @@
   ASSERT(alloc->IsAllocateContext() || alloc->IsCloneContext());
 
   AllocateUninitializedContextInstr* replacement =
-      new AllocateUninitializedContextInstr(alloc->token_pos(),
+      new AllocateUninitializedContextInstr(alloc->source(),
                                             context_variables.length());
   alloc->ReplaceWith(replacement, current_iterator());
 
@@ -236,7 +240,7 @@
   if (context_value != NULL) {
     LoadFieldInstr* load =
         new (Z) LoadFieldInstr(context_value->CopyWithType(Z),
-                               Slot::Context_parent(), alloc->token_pos());
+                               Slot::Context_parent(), alloc->source());
     flow_graph()->InsertAfter(cursor, load, NULL, FlowGraph::kValue);
     cursor = load;
     initial_value = new (Z) Value(load);
@@ -245,7 +249,7 @@
   }
   StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
       Slot::Context_parent(), new (Z) Value(replacement), initial_value,
-      kNoStoreBarrier, alloc->token_pos(),
+      kNoStoreBarrier, alloc->source(),
       StoreInstanceFieldInstr::Kind::kInitializing);
   flow_graph()->InsertAfter(cursor, store, nullptr, FlowGraph::kEffect);
   cursor = replacement;
@@ -253,7 +257,7 @@
   for (auto& slot : context_variables) {
     if (context_value != nullptr) {
       LoadFieldInstr* load = new (Z) LoadFieldInstr(
-          context_value->CopyWithType(Z), *slot, alloc->token_pos());
+          context_value->CopyWithType(Z), *slot, alloc->source());
       flow_graph()->InsertAfter(cursor, load, nullptr, FlowGraph::kValue);
       cursor = load;
       initial_value = new (Z) Value(load);
@@ -263,7 +267,7 @@
 
     store = new (Z) StoreInstanceFieldInstr(
         *slot, new (Z) Value(replacement), initial_value, kNoStoreBarrier,
-        alloc->token_pos(), StoreInstanceFieldInstr::Kind::kInitializing);
+        alloc->source(), StoreInstanceFieldInstr::Kind::kInitializing);
     flow_graph()->InsertAfter(cursor, store, nullptr, FlowGraph::kEffect);
     cursor = store;
   }
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index ecd99a1..3abd57b 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -291,43 +291,43 @@
 }
 
 static Token::Kind RecognizeTokenKindHelper(const String& name) {
-  if (name.raw() == Symbols::Plus().raw()) {
+  if (name.ptr() == Symbols::Plus().ptr()) {
     return Token::kADD;
-  } else if (name.raw() == Symbols::Minus().raw()) {
+  } else if (name.ptr() == Symbols::Minus().ptr()) {
     return Token::kSUB;
-  } else if (name.raw() == Symbols::Star().raw()) {
+  } else if (name.ptr() == Symbols::Star().ptr()) {
     return Token::kMUL;
-  } else if (name.raw() == Symbols::Slash().raw()) {
+  } else if (name.ptr() == Symbols::Slash().ptr()) {
     return Token::kDIV;
-  } else if (name.raw() == Symbols::TruncDivOperator().raw()) {
+  } else if (name.ptr() == Symbols::TruncDivOperator().ptr()) {
     return Token::kTRUNCDIV;
-  } else if (name.raw() == Symbols::Percent().raw()) {
+  } else if (name.ptr() == Symbols::Percent().ptr()) {
     return Token::kMOD;
-  } else if (name.raw() == Symbols::BitOr().raw()) {
+  } else if (name.ptr() == Symbols::BitOr().ptr()) {
     return Token::kBIT_OR;
-  } else if (name.raw() == Symbols::Ampersand().raw()) {
+  } else if (name.ptr() == Symbols::Ampersand().ptr()) {
     return Token::kBIT_AND;
-  } else if (name.raw() == Symbols::Caret().raw()) {
+  } else if (name.ptr() == Symbols::Caret().ptr()) {
     return Token::kBIT_XOR;
-  } else if (name.raw() == Symbols::LeftShiftOperator().raw()) {
+  } else if (name.ptr() == Symbols::LeftShiftOperator().ptr()) {
     return Token::kSHL;
-  } else if (name.raw() == Symbols::RightShiftOperator().raw()) {
+  } else if (name.ptr() == Symbols::RightShiftOperator().ptr()) {
     return Token::kSHR;
-  } else if (name.raw() == Symbols::Tilde().raw()) {
+  } else if (name.ptr() == Symbols::Tilde().ptr()) {
     return Token::kBIT_NOT;
-  } else if (name.raw() == Symbols::UnaryMinus().raw()) {
+  } else if (name.ptr() == Symbols::UnaryMinus().ptr()) {
     return Token::kNEGATE;
-  } else if (name.raw() == Symbols::EqualOperator().raw()) {
+  } else if (name.ptr() == Symbols::EqualOperator().ptr()) {
     return Token::kEQ;
-  } else if (name.raw() == Symbols::Token(Token::kNE).raw()) {
+  } else if (name.ptr() == Symbols::Token(Token::kNE).ptr()) {
     return Token::kNE;
-  } else if (name.raw() == Symbols::LAngleBracket().raw()) {
+  } else if (name.ptr() == Symbols::LAngleBracket().ptr()) {
     return Token::kLT;
-  } else if (name.raw() == Symbols::RAngleBracket().raw()) {
+  } else if (name.ptr() == Symbols::RAngleBracket().ptr()) {
     return Token::kGT;
-  } else if (name.raw() == Symbols::LessEqualOperator().raw()) {
+  } else if (name.ptr() == Symbols::LessEqualOperator().ptr()) {
     return Token::kLTE;
-  } else if (name.raw() == Symbols::GreaterEqualOperator().raw()) {
+  } else if (name.ptr() == Symbols::GreaterEqualOperator().ptr()) {
     return Token::kGTE;
   } else if (Field::IsGetterName(name)) {
     return Token::kGET;
@@ -366,8 +366,8 @@
   ASSERT(factory.IsFactory());
   const Class& function_class = Class::Handle(factory.Owner());
   const Library& lib = Library::Handle(function_class.library());
-  ASSERT((lib.raw() == Library::CoreLibrary()) ||
-         (lib.raw() == Library::TypedDataLibrary()));
+  ASSERT((lib.ptr() == Library::CoreLibrary()) ||
+         (lib.ptr() == Library::TypedDataLibrary()));
   const String& factory_name = String::Handle(factory.name());
   for (intptr_t i = 0;
        factory_recognizer_list[i].symbol_id != Symbols::kIllegal; i++) {
@@ -393,11 +393,11 @@
     return kDynamicCid;
   }
 
-  if (owner.Name() == Symbols::List().raw()) {
-    if (function.name() == Symbols::ListFactory().raw()) {
+  if (owner.Name() == Symbols::List().ptr()) {
+    if (function.name() == Symbols::ListFactory().ptr()) {
       ASSERT(argument_count == 1 || argument_count == 2);
       return (argument_count == 1) ? kGrowableObjectArrayCid : kArrayCid;
-    } else if (function.name() == Symbols::ListFilledFactory().raw()) {
+    } else if (function.name() == Symbols::ListFilledFactory().ptr()) {
       ASSERT(argument_count == 3 || argument_count == 4);
       return (argument_count == 3) ? kArrayCid : kDynamicCid;
     }
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 6c80aa5..185af0a 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -195,7 +195,7 @@
   V(::, reachabilityFence, ReachabilityFence, 0xde1dc5bd)                      \
   V(_Utf8Decoder, _scan, Utf8DecoderScan, 0xb35ced99)                          \
   V(_Future, timeout, FutureTimeout, 0x6ad7d1ef)                               \
-  V(Future, wait, FutureWait, 0xb4396ca1)                                      \
+  V(Future, wait, FutureWait, 0x264aacc2)                                      \
 
 // List of intrinsics:
 // (class-name, function-name, intrinsification method, fingerprint).
@@ -232,7 +232,7 @@
   V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 0xd8114d5f)                   \
   V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, 0xd0dd0025)       \
   V(Object, ==, ObjectEquals, 0xd3f5f95a)                                      \
-  V(Object, get:runtimeType, ObjectRuntimeType, 0x8177627e)                    \
+  V(Object, get:runtimeType, ObjectRuntimeType, 0x81775ebd)                    \
   V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, 0xe61da79f)       \
   V(_StringBase, get:hashCode, String_getHashCode, 0x4e27ab52)                 \
   V(_StringBase, get:_identityHashCode, String_identityHash, 0x1fec4010)       \
@@ -246,6 +246,8 @@
   V(_TwoByteString, ==, TwoByteString_equality, 0x483ef8d2)                    \
   V(_Type, get:hashCode, Type_getHashCode, 0x4e27ab52)                         \
   V(_Type, ==, Type_equality, 0xd3f5f1d8)                                      \
+  V(_FunctionType, get:hashCode, FunctionType_getHashCode, 0x4e27ab52)         \
+  V(_FunctionType, ==, FunctionType_equality, 0xd3f5f1d8)                      \
   V(::, _getHash, Object_getHash, 0x1d1372ac)                                  \
   V(::, _setHash, Object_setHash, 0x77e0bb27)                                  \
 
@@ -434,7 +436,7 @@
   V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x1b858d66)              \
   V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x9e2320c0)          \
   V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0xfa1f5cf1)              \
-  V(Object, get:runtimeType, ObjectRuntimeType, 0x8177627e)
+  V(Object, get:runtimeType, ObjectRuntimeType, 0x81775ebd)
 
 // List of recognized list factories:
 // (factory-name-symbol, class-name-string, constructor-name-string,
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index a14f615..ff5ea61 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -53,7 +53,7 @@
     current_caller = (*code_objects_)[i];
 
     const intptr_t code_text_offset = next_text_offset_;
-    if (!AddInstructionsToText(current_caller.raw())) {
+    if (!AddInstructionsToText(current_caller.ptr())) {
       continue;
     }
 
@@ -71,8 +71,15 @@
   // We're guaranteed to have all calls resolved, since
   //   * backwards calls are resolved eagerly
   //   * forward calls are resolved once the target is written
-  ASSERT(all_unresolved_calls_.IsEmpty());
-  ASSERT(unresolved_calls_by_destination_.IsEmpty());
+  if (!all_unresolved_calls_.IsEmpty()) {
+    for (auto call : all_unresolved_calls_) {
+      OS::PrintErr("Unresolved call to %s from %s\n",
+                   Object::Handle(call->callee).ToCString(),
+                   Object::Handle(call->caller).ToCString());
+    }
+  }
+  RELEASE_ASSERT(all_unresolved_calls_.IsEmpty());
+  RELEASE_ASSERT(unresolved_calls_by_destination_.IsEmpty());
 
   // Any trampolines we created must be patched with the right offsets.
   auto it = trampolines_by_destination_.GetIterator();
@@ -273,8 +280,8 @@
     const intptr_t text_offset =
         code_text_offset + AdjustPayloadOffset(call_instruction_offset);
 
-    UnresolvedCall unresolved_call(code.raw(), call_instruction_offset,
-                                   text_offset, destination_.raw(),
+    UnresolvedCall unresolved_call(code.ptr(), call_instruction_offset,
+                                   text_offset, destination_.ptr(),
                                    offset_into_target, is_tail_call);
     if (!TryResolveBackwardsCall(&unresolved_call)) {
       EnqueueUnresolvedCall(new UnresolvedCall(unresolved_call));
@@ -420,7 +427,7 @@
   target_ = call.Get<Code::kSCallTableCodeOrTypeTarget>();
   if (target_.IsAbstractType()) {
     target_ = AbstractType::Cast(target_).type_test_stub();
-    destination_ = Code::Cast(target_).raw();
+    destination_ = Code::Cast(target_).ptr();
 
     // The AssertAssignableInstr will emit pc-relative calls to the TTS iff
     // dst_type is instantiated. If we happened to not install an optimized
@@ -433,24 +440,24 @@
     // into the types directly, but that does not work for types which
     // live in the "vm-isolate" - such as `Type::dynamic_type()`).
     if (destination_.InVMIsolateHeap()) {
-      auto object_store = thread_->isolate()->object_store();
+      auto object_store = thread_->isolate_group()->object_store();
 
-      if (destination_.raw() == StubCode::DefaultTypeTest().raw()) {
+      if (destination_.ptr() == StubCode::DefaultTypeTest().ptr()) {
         destination_ = object_store->default_tts_stub();
-      } else if (destination_.raw() ==
-                 StubCode::DefaultNullableTypeTest().raw()) {
+      } else if (destination_.ptr() ==
+                 StubCode::DefaultNullableTypeTest().ptr()) {
         destination_ = object_store->default_nullable_tts_stub();
-      } else if (destination_.raw() == StubCode::TopTypeTypeTest().raw()) {
+      } else if (destination_.ptr() == StubCode::TopTypeTypeTest().ptr()) {
         destination_ = object_store->top_type_tts_stub();
-      } else if (destination_.raw() == StubCode::UnreachableTypeTest().raw()) {
+      } else if (destination_.ptr() == StubCode::UnreachableTypeTest().ptr()) {
         destination_ = object_store->unreachable_tts_stub();
-      } else if (destination_.raw() == StubCode::SlowTypeTest().raw()) {
+      } else if (destination_.ptr() == StubCode::SlowTypeTest().ptr()) {
         destination_ = object_store->slow_tts_stub();
-      } else if (destination_.raw() ==
-                 StubCode::NullableTypeParameterTypeTest().raw()) {
+      } else if (destination_.ptr() ==
+                 StubCode::NullableTypeParameterTypeTest().ptr()) {
         destination_ = object_store->nullable_type_parameter_tts_stub();
-      } else if (destination_.raw() ==
-                 StubCode::TypeParameterTypeTest().raw()) {
+      } else if (destination_.ptr() ==
+                 StubCode::TypeParameterTypeTest().ptr()) {
         destination_ = object_store->type_parameter_tts_stub();
       } else {
         UNREACHABLE();
@@ -458,10 +465,10 @@
     }
   } else {
     ASSERT(target_.IsCode());
-    destination_ = Code::Cast(target_).raw();
+    destination_ = Code::Cast(target_).ptr();
   }
   ASSERT(!destination_.InVMIsolateHeap());
-  return destination_.raw();
+  return destination_.ptr();
 }
 
 void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls() {
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 739f168..a13025f 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -55,7 +55,7 @@
   } else if (a.IsDouble() && b.IsDouble()) {
     return Double::Cast(a).value() == Double::Cast(b).value();
   }
-  return a.raw() == b.raw();
+  return a.ptr() == b.ptr();
 }
 
 bool IsEqualType(const AbstractType& a, const AbstractType& b) {
@@ -121,7 +121,7 @@
 }
 
 Object& NewZoneHandle(Zone* zone, const Object& obj) {
-  return Object::ZoneHandle(zone, obj.raw());
+  return Object::ZoneHandle(zone, obj.ptr());
 }
 
 const Object& NullObject() {
@@ -161,17 +161,17 @@
 }
 
 const Class& GrowableObjectArrayClass() {
-  auto object_store = Isolate::Current()->object_store();
+  auto object_store = IsolateGroup::Current()->object_store();
   return Class::Handle(object_store->growable_object_array_class());
 }
 
 const Class& MintClass() {
-  auto object_store = Isolate::Current()->object_store();
+  auto object_store = IsolateGroup::Current()->object_store();
   return Class::Handle(object_store->mint_class());
 }
 
 const Class& DoubleClass() {
-  auto object_store = Isolate::Current()->object_store();
+  auto object_store = IsolateGroup::Current()->object_store();
   return Class::Handle(object_store->double_class());
 }
 
@@ -294,54 +294,56 @@
 }
 
 bool SizeFitsInSizeTag(uword instance_size) {
-  return dart::ObjectLayout::SizeTag::SizeFits(
+  return dart::UntaggedObject::SizeTag::SizeFits(
       TranslateOffsetInWordsToHost(instance_size));
 }
 
 uword MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size) {
-  return dart::ObjectLayout::SizeTag::encode(
+  return dart::UntaggedObject::SizeTag::encode(
              TranslateOffsetInWordsToHost(instance_size)) |
-         dart::ObjectLayout::ClassIdTag::encode(cid) |
-         dart::ObjectLayout::NewBit::encode(true);
+         dart::UntaggedObject::ClassIdTag::encode(cid) |
+         dart::UntaggedObject::NewBit::encode(true);
 }
 
 word Object::tags_offset() {
   return 0;
 }
 
-const word ObjectLayout::kCardRememberedBit =
-    dart::ObjectLayout::kCardRememberedBit;
+const word UntaggedObject::kCardRememberedBit =
+    dart::UntaggedObject::kCardRememberedBit;
 
-const word ObjectLayout::kOldAndNotRememberedBit =
-    dart::ObjectLayout::kOldAndNotRememberedBit;
+const word UntaggedObject::kOldAndNotRememberedBit =
+    dart::UntaggedObject::kOldAndNotRememberedBit;
 
-const word ObjectLayout::kOldAndNotMarkedBit =
-    dart::ObjectLayout::kOldAndNotMarkedBit;
+const word UntaggedObject::kOldAndNotMarkedBit =
+    dart::UntaggedObject::kOldAndNotMarkedBit;
 
-const word ObjectLayout::kSizeTagPos = dart::ObjectLayout::kSizeTagPos;
+const word UntaggedObject::kSizeTagPos = dart::UntaggedObject::kSizeTagPos;
 
-const word ObjectLayout::kSizeTagSize = dart::ObjectLayout::kSizeTagSize;
+const word UntaggedObject::kSizeTagSize = dart::UntaggedObject::kSizeTagSize;
 
-const word ObjectLayout::kClassIdTagPos = dart::ObjectLayout::kClassIdTagPos;
+const word UntaggedObject::kClassIdTagPos =
+    dart::UntaggedObject::kClassIdTagPos;
 
-const word ObjectLayout::kClassIdTagSize = dart::ObjectLayout::kClassIdTagSize;
+const word UntaggedObject::kClassIdTagSize =
+    dart::UntaggedObject::kClassIdTagSize;
 
-const word ObjectLayout::kHashTagPos = dart::ObjectLayout::kHashTagPos;
+const word UntaggedObject::kHashTagPos = dart::UntaggedObject::kHashTagPos;
 
-const word ObjectLayout::kHashTagSize = dart::ObjectLayout::kHashTagSize;
+const word UntaggedObject::kHashTagSize = dart::UntaggedObject::kHashTagSize;
 
-const word ObjectLayout::kSizeTagMaxSizeTag =
-    dart::ObjectLayout::SizeTag::kMaxSizeTagInUnitsOfAlignment *
+const word UntaggedObject::kSizeTagMaxSizeTag =
+    dart::UntaggedObject::SizeTag::kMaxSizeTagInUnitsOfAlignment *
     ObjectAlignment::kObjectAlignment;
 
-const word ObjectLayout::kTagBitsSizeTagPos =
-    dart::ObjectLayout::TagBits::kSizeTagPos;
+const word UntaggedObject::kTagBitsSizeTagPos =
+    dart::UntaggedObject::TagBits::kSizeTagPos;
 
-const word AbstractTypeLayout::kTypeStateFinalizedInstantiated =
-    dart::AbstractTypeLayout::kFinalizedInstantiated;
+const word UntaggedAbstractType::kTypeStateFinalizedInstantiated =
+    dart::UntaggedAbstractType::kFinalizedInstantiated;
 
-const word ObjectLayout::kBarrierOverlapShift =
-    dart::ObjectLayout::kBarrierOverlapShift;
+const word UntaggedObject::kBarrierOverlapShift =
+    dart::UntaggedObject::kBarrierOverlapShift;
 
 bool IsTypedDataClassId(intptr_t cid) {
   return dart::IsTypedDataClassId(cid);
@@ -430,7 +432,7 @@
 }
 
 bool Class::TraceAllocation(const dart::Class& klass) {
-  return klass.TraceAllocation(dart::Isolate::Current());
+  return klass.TraceAllocation(dart::IsolateGroup::Current());
 }
 
 word Instance::first_field_offset() {
@@ -780,7 +782,7 @@
 
 word ToRawSmi(const dart::Object& a) {
   RELEASE_ASSERT(IsSmi(a));
-  return static_cast<word>(static_cast<intptr_t>(a.raw()));
+  return static_cast<word>(static_cast<intptr_t>(a.ptr()));
 }
 
 word ToRawSmi(intptr_t value) {
@@ -808,7 +810,7 @@
   static_assert(kHostWordSize == kWordSize,
                 "Can't embed raw pointers to runtime objects when host and "
                 "target word sizes are different");
-  return static_cast<word>(a.raw());
+  return static_cast<word>(a.ptr());
 }
 #endif  // defined(TARGET_ARCH_IA32)
 
@@ -823,12 +825,12 @@
 
 const word String::kHashBits = dart::String::kHashBits;
 
-const int8_t Nullability::kNullable =
-    static_cast<int8_t>(dart::Nullability::kNullable);
-const int8_t Nullability::kNonNullable =
-    static_cast<int8_t>(dart::Nullability::kNonNullable);
-const int8_t Nullability::kLegacy =
-    static_cast<int8_t>(dart::Nullability::kLegacy);
+const uint8_t Nullability::kNullable =
+    static_cast<uint8_t>(dart::Nullability::kNullable);
+const uint8_t Nullability::kNonNullable =
+    static_cast<uint8_t>(dart::Nullability::kNonNullable);
+const uint8_t Nullability::kLegacy =
+    static_cast<uint8_t>(dart::Nullability::kLegacy);
 
 bool Heap::IsAllocatableInNewSpace(intptr_t instance_size) {
   return dart::Heap::IsAllocatableInNewSpace(instance_size);
@@ -920,10 +922,18 @@
   return -kWordSize;
 }
 
+word AbstractType::NextFieldOffset() {
+  return -kWordSize;
+}
+
 word Type::NextFieldOffset() {
   return -kWordSize;
 }
 
+word FunctionType::NextFieldOffset() {
+  return -kWordSize;
+}
+
 word TypeRef::NextFieldOffset() {
   return -kWordSize;
 }
@@ -980,10 +990,6 @@
   return -kWordSize;
 }
 
-word SignatureData::NextFieldOffset() {
-  return -kWordSize;
-}
-
 word FfiTrampolineData::NextFieldOffset() {
   return -kWordSize;
 }
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index cb104ad..d690ef4 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -40,7 +40,7 @@
 class Zone;
 
 #define DO(clazz)                                                              \
-  class clazz##Layout;                                                         \
+  class Untagged##clazz;                                                       \
   class clazz;
 CLASS_LIST_FOR_HANDLES(DO)
 #undef DO
@@ -336,7 +336,7 @@
   return Utils::RoundUp(size, kObjectAlignment);
 }
 // Information about frame_layout that compiler should be targeting.
-extern FrameLayout frame_layout;
+extern UntaggedFrame frame_layout;
 
 constexpr intptr_t kIntSpillFactor = sizeof(int64_t) / kWordSize;
 constexpr intptr_t kDoubleSpillFactor = sizeof(double) / kWordSize;
@@ -406,7 +406,7 @@
 // Currently we use the same names for classes, constants and getters to make
 // migration easier.
 
-class ObjectLayout : public AllStatic {
+class UntaggedObject : public AllStatic {
  public:
   static const word kCardRememberedBit;
   static const word kOldAndNotRememberedBit;
@@ -424,7 +424,7 @@
   static bool IsTypedDataClassId(intptr_t cid);
 };
 
-class AbstractTypeLayout : public AllStatic {
+class UntaggedAbstractType : public AllStatic {
  public:
   static const word kTypeStateFinalizedInstantiated;
 };
@@ -454,7 +454,7 @@
 
   static word super_type_offset();
 
-  // The offset of the ObjectLayout::num_type_arguments_ field in bytes.
+  // The offset of the UntaggedObject::num_type_arguments_ field in bytes.
   static word num_type_arguments_offset();
 
   // The value used if no type arguments vector is present.
@@ -485,7 +485,8 @@
 
 class Instance : public AllStatic {
  public:
-  // Returns the offset to the first field of [RawInstance].
+  // 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 DataOffsetFor(intptr_t cid);
   static word ElementSizeFor(intptr_t cid);
@@ -501,8 +502,7 @@
   static word kind_tag_offset();
   static word packed_fields_offset();
   static word parameter_names_offset();
-  static word parameter_types_offset();
-  static word type_parameters_offset();
+  static word signature_offset();
   static word usage_counter_offset();
   static word InstanceSize();
   static word NextFieldOffset();
@@ -643,7 +643,7 @@
 
 class LocalHandle : public AllStatic {
  public:
-  static word raw_offset();
+  static word ptr_offset();
 };
 
 class Pointer : public PointerBase {
@@ -656,6 +656,8 @@
 class AbstractType : public AllStatic {
  public:
   static word type_test_stub_entry_point_offset();
+  static word InstanceSize();
+  static word NextFieldOffset();
 };
 
 class Type : public AllStatic {
@@ -663,13 +665,24 @@
   static word hash_offset();
   static word type_state_offset();
   static word arguments_offset();
-  static word signature_offset();
   static word type_class_id_offset();
   static word nullability_offset();
   static word InstanceSize();
   static word NextFieldOffset();
 };
 
+class FunctionType : public AllStatic {
+ public:
+  static word hash_offset();
+  static word type_state_offset();
+  static word packed_fields_offset();
+  static word parameter_types_offset();
+  static word type_parameters_offset();
+  static word nullability_offset();
+  static word InstanceSize();
+  static word NextFieldOffset();
+};
+
 class TypeRef : public AllStatic {
  public:
   static word type_offset();
@@ -679,9 +692,9 @@
 
 class Nullability : public AllStatic {
  public:
-  static const int8_t kNullable;
-  static const int8_t kNonNullable;
-  static const int8_t kLegacy;
+  static const uint8_t kNullable;
+  static const uint8_t kNonNullable;
+  static const uint8_t kLegacy;
 };
 
 class Double : public AllStatic {
@@ -770,12 +783,6 @@
   static word NextFieldOffset();
 };
 
-class SignatureData : public AllStatic {
- public:
-  static word InstanceSize();
-  static word NextFieldOffset();
-};
-
 class FfiTrampolineData : public AllStatic {
  public:
   static word InstanceSize();
@@ -1044,6 +1051,7 @@
   static word unboxed_int64_runtime_arg_offset();
 
   static word callback_code_offset();
+  static word callback_stack_return_offset();
 
   static word AllocateArray_entry_point_offset();
   static word write_barrier_code_offset();
@@ -1124,6 +1132,7 @@
   static word double_type_offset();
   static word int_type_offset();
   static word string_type_offset();
+  static word type_type_offset();
 };
 
 class Isolate : public AllStatic {
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 63c13d4..9694444 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -19,7 +19,7 @@
 
 #if defined(TARGET_ARCH_ARM)
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    84;
+    76;
 static constexpr dart::compiler::target::word
     ICData_receivers_static_type_offset = 16;
 static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
@@ -86,12 +86,12 @@
 static constexpr dart::compiler::target::word Array_tags_offset = 0;
 static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word Class_declaration_type_offset =
-    56;
+    48;
 static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    92;
+    88;
 static constexpr dart::compiler::target::word Class_super_type_offset = 44;
 static constexpr dart::compiler::target::word
-    Class_host_type_arguments_field_offset_in_words_offset = 104;
+    Class_host_type_arguments_field_offset_in_words_offset = 100;
 static constexpr dart::compiler::target::word
     SharedClassTable_class_heap_stats_table_offset = 0;
 static constexpr dart::compiler::target::word Closure_context_offset = 20;
@@ -104,9 +104,9 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 20;
+    ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 24;
+    ClosureData_default_type_arguments_info_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -131,19 +131,16 @@
     24;
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 46;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 54;
-static constexpr dart::compiler::target::word Function_code_offset = 44;
-static constexpr dart::compiler::target::word Function_data_offset = 36;
+static constexpr dart::compiler::target::word Function_code_offset = 36;
+static constexpr dart::compiler::target::word Function_data_offset = 28;
 static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
     4, 8};
-static constexpr dart::compiler::target::word Function_kind_tag_offset = 72;
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 64;
 static constexpr dart::compiler::target::word Function_packed_fields_offset =
-    76;
+    68;
 static constexpr dart::compiler::target::word Function_parameter_names_offset =
-    28;
-static constexpr dart::compiler::target::word Function_parameter_types_offset =
-    24;
-static constexpr dart::compiler::target::word Function_type_parameters_offset =
-    32;
+    20;
+static constexpr dart::compiler::target::word Function_signature_offset = 24;
 static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
     4;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -182,7 +179,7 @@
     LinkedHashMap_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
     20;
-static constexpr dart::compiler::target::word LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
@@ -201,6 +198,7 @@
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
     156;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
 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;
@@ -248,7 +246,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 = 728;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 732;
 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;
@@ -259,7 +257,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 = 736;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 740;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -301,7 +299,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    724;
+    728;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     64;
@@ -382,19 +380,27 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 724;
 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;
 static constexpr dart::compiler::target::word Type_hash_offset = 20;
-static constexpr dart::compiler::target::word Type_signature_offset = 24;
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 12;
-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 Type_type_state_offset = 24;
+static constexpr dart::compiler::target::word Type_nullability_offset = 25;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 32;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 40;
+    FunctionType_packed_fields_offset = 32;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 32;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    43;
+    35;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
@@ -402,7 +408,7 @@
     16;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
 static constexpr dart::compiler::target::word TypeParameter_bound_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 42;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 34;
 static constexpr dart::compiler::target::word TypeParameter_name_offset = 12;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
@@ -436,14 +442,15 @@
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
         660, 664, 668, 672, 676, -1, 680, -1, 684, 688, -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_InstanceSize = 12;
 static constexpr dart::compiler::target::word Array_header_size = 12;
 static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 128;
+static constexpr dart::compiler::target::word Class_InstanceSize = 124;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 28;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word Code_InstanceSize = 96;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
@@ -466,7 +473,8 @@
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
 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 Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 40;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     16;
@@ -505,7 +513,6 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word Script_InstanceSize = 64;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word SignatureData_InstanceSize = 12;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
 static constexpr dart::compiler::target::word Smi_InstanceSize = 4;
@@ -516,9 +523,9 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 12;
-static constexpr dart::compiler::target::word Type_InstanceSize = 36;
+static constexpr dart::compiler::target::word Type_InstanceSize = 28;
 static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 20;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 44;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 36;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
@@ -535,7 +542,7 @@
 
 #if defined(TARGET_ARCH_X64)
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    132;
+    116;
 static constexpr dart::compiler::target::word
     ICData_receivers_static_type_offset = 32;
 static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
@@ -604,12 +611,12 @@
 static constexpr dart::compiler::target::word Array_tags_offset = 0;
 static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word Class_declaration_type_offset =
-    112;
+    96;
 static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    172;
+    164;
 static constexpr dart::compiler::target::word Class_super_type_offset = 88;
 static constexpr dart::compiler::target::word
-    Class_host_type_arguments_field_offset_in_words_offset = 184;
+    Class_host_type_arguments_field_offset_in_words_offset = 176;
 static constexpr dart::compiler::target::word
     SharedClassTable_class_heap_stats_table_offset = 0;
 static constexpr dart::compiler::target::word Closure_context_offset = 40;
@@ -622,9 +629,9 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 40;
+    ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 48;
+    ClosureData_default_type_arguments_info_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -649,19 +656,16 @@
     48;
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 82;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 90;
-static constexpr dart::compiler::target::word Function_code_offset = 88;
-static constexpr dart::compiler::target::word Function_data_offset = 72;
+static constexpr dart::compiler::target::word Function_code_offset = 72;
+static constexpr dart::compiler::target::word Function_data_offset = 56;
 static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
     8, 16};
-static constexpr dart::compiler::target::word Function_kind_tag_offset = 120;
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 104;
 static constexpr dart::compiler::target::word Function_packed_fields_offset =
-    124;
+    108;
 static constexpr dart::compiler::target::word Function_parameter_names_offset =
-    56;
-static constexpr dart::compiler::target::word Function_parameter_types_offset =
-    48;
-static constexpr dart::compiler::target::word Function_type_parameters_offset =
-    64;
+    40;
+static constexpr dart::compiler::target::word Function_signature_offset = 48;
 static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
     8;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -700,7 +704,7 @@
     LinkedHashMap_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
     40;
-static constexpr dart::compiler::target::word LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
@@ -719,6 +723,7 @@
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
     312;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
 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 =
@@ -768,7 +773,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 376;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1464;
+    1472;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 208;
@@ -779,7 +784,7 @@
     Thread_call_to_runtime_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 256;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1480;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1488;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -821,7 +826,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1456;
+    1464;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
@@ -903,20 +908,28 @@
     72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
     1448;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 1456;
 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 = 32;
 static constexpr dart::compiler::target::word Type_hash_offset = 40;
-static constexpr dart::compiler::target::word Type_signature_offset = 48;
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
-static constexpr dart::compiler::target::word Type_type_state_offset = 60;
-static constexpr dart::compiler::target::word Type_nullability_offset = 61;
+static constexpr dart::compiler::target::word Type_type_state_offset = 48;
+static constexpr dart::compiler::target::word Type_nullability_offset = 49;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 64;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 72;
+    FunctionType_packed_fields_offset = 64;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 56;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 60;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    75;
+    63;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
@@ -924,7 +937,7 @@
     32;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
 static constexpr dart::compiler::target::word TypeParameter_bound_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 74;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 62;
 static constexpr dart::compiler::target::word TypeParameter_name_offset = 24;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
@@ -959,14 +972,15 @@
     Thread_write_barrier_wrappers_thread_offset[] = {
         1304, 1312, 1320, 1328, -1,   -1,   1336, 1344,
         1352, 1360, 1368, -1,   1376, 1384, -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_InstanceSize = 24;
 static constexpr dart::compiler::target::word Array_header_size = 24;
 static constexpr dart::compiler::target::word Bool_InstanceSize = 16;
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 208;
+static constexpr dart::compiler::target::word Class_InstanceSize = 200;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 56;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 48;
 static constexpr dart::compiler::target::word Code_InstanceSize = 176;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
@@ -989,7 +1003,8 @@
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
 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 = 144;
+static constexpr dart::compiler::target::word Function_InstanceSize = 128;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 72;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     32;
@@ -1028,7 +1043,6 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word Script_InstanceSize = 104;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word SignatureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word Smi_InstanceSize = 8;
@@ -1040,9 +1054,9 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 16;
-static constexpr dart::compiler::target::word Type_InstanceSize = 64;
+static constexpr dart::compiler::target::word Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 40;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 80;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 64;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -1059,7 +1073,7 @@
 
 #if defined(TARGET_ARCH_IA32)
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    84;
+    76;
 static constexpr dart::compiler::target::word
     ICData_receivers_static_type_offset = 16;
 static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
@@ -1126,12 +1140,12 @@
 static constexpr dart::compiler::target::word Array_tags_offset = 0;
 static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word Class_declaration_type_offset =
-    56;
+    48;
 static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    92;
+    88;
 static constexpr dart::compiler::target::word Class_super_type_offset = 44;
 static constexpr dart::compiler::target::word
-    Class_host_type_arguments_field_offset_in_words_offset = 104;
+    Class_host_type_arguments_field_offset_in_words_offset = 100;
 static constexpr dart::compiler::target::word
     SharedClassTable_class_heap_stats_table_offset = 0;
 static constexpr dart::compiler::target::word Closure_context_offset = 20;
@@ -1144,9 +1158,9 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 20;
+    ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 24;
+    ClosureData_default_type_arguments_info_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -1171,19 +1185,16 @@
     24;
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 46;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 54;
-static constexpr dart::compiler::target::word Function_code_offset = 44;
-static constexpr dart::compiler::target::word Function_data_offset = 36;
+static constexpr dart::compiler::target::word Function_code_offset = 36;
+static constexpr dart::compiler::target::word Function_data_offset = 28;
 static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
     4, 8};
-static constexpr dart::compiler::target::word Function_kind_tag_offset = 72;
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 64;
 static constexpr dart::compiler::target::word Function_packed_fields_offset =
-    76;
+    68;
 static constexpr dart::compiler::target::word Function_parameter_names_offset =
-    28;
-static constexpr dart::compiler::target::word Function_parameter_types_offset =
-    24;
-static constexpr dart::compiler::target::word Function_type_parameters_offset =
-    32;
+    20;
+static constexpr dart::compiler::target::word Function_signature_offset = 24;
 static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
     4;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -1222,7 +1233,7 @@
     LinkedHashMap_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
     20;
-static constexpr dart::compiler::target::word LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
@@ -1241,6 +1252,7 @@
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
     156;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
 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;
@@ -1288,7 +1300,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 = 696;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 700;
 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;
@@ -1299,7 +1311,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 = 704;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 708;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1341,7 +1353,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    692;
+    696;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     64;
@@ -1422,19 +1434,27 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_callback_code_offset = 688;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 692;
 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;
 static constexpr dart::compiler::target::word Type_hash_offset = 20;
-static constexpr dart::compiler::target::word Type_signature_offset = 24;
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 12;
-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 Type_type_state_offset = 24;
+static constexpr dart::compiler::target::word Type_nullability_offset = 25;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 32;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 40;
+    FunctionType_packed_fields_offset = 32;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 32;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    43;
+    35;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
@@ -1442,7 +1462,7 @@
     16;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
 static constexpr dart::compiler::target::word TypeParameter_bound_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 42;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 34;
 static constexpr dart::compiler::target::word TypeParameter_name_offset = 12;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
@@ -1473,14 +1493,15 @@
 static constexpr dart::compiler::target::word ClassTable_element_size = 1;
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     4, 12, 8, 16};
+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_InstanceSize = 12;
 static constexpr dart::compiler::target::word Array_header_size = 12;
 static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 128;
+static constexpr dart::compiler::target::word Class_InstanceSize = 124;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 28;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word Code_InstanceSize = 96;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
@@ -1503,7 +1524,8 @@
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
 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 Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 40;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     16;
@@ -1542,7 +1564,6 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word Script_InstanceSize = 64;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word SignatureData_InstanceSize = 12;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
 static constexpr dart::compiler::target::word Smi_InstanceSize = 4;
@@ -1553,9 +1574,9 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 12;
-static constexpr dart::compiler::target::word Type_InstanceSize = 36;
+static constexpr dart::compiler::target::word Type_InstanceSize = 28;
 static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 20;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 44;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 36;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
@@ -1572,7 +1593,7 @@
 
 #if defined(TARGET_ARCH_ARM64)
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    132;
+    116;
 static constexpr dart::compiler::target::word
     ICData_receivers_static_type_offset = 32;
 static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
@@ -1641,12 +1662,12 @@
 static constexpr dart::compiler::target::word Array_tags_offset = 0;
 static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word Class_declaration_type_offset =
-    112;
+    96;
 static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    172;
+    164;
 static constexpr dart::compiler::target::word Class_super_type_offset = 88;
 static constexpr dart::compiler::target::word
-    Class_host_type_arguments_field_offset_in_words_offset = 184;
+    Class_host_type_arguments_field_offset_in_words_offset = 176;
 static constexpr dart::compiler::target::word
     SharedClassTable_class_heap_stats_table_offset = 0;
 static constexpr dart::compiler::target::word Closure_context_offset = 40;
@@ -1659,9 +1680,9 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 40;
+    ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 48;
+    ClosureData_default_type_arguments_info_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -1686,19 +1707,16 @@
     48;
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 82;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 90;
-static constexpr dart::compiler::target::word Function_code_offset = 88;
-static constexpr dart::compiler::target::word Function_data_offset = 72;
+static constexpr dart::compiler::target::word Function_code_offset = 72;
+static constexpr dart::compiler::target::word Function_data_offset = 56;
 static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
     8, 16};
-static constexpr dart::compiler::target::word Function_kind_tag_offset = 120;
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 104;
 static constexpr dart::compiler::target::word Function_packed_fields_offset =
-    124;
+    108;
 static constexpr dart::compiler::target::word Function_parameter_names_offset =
-    56;
-static constexpr dart::compiler::target::word Function_parameter_types_offset =
-    48;
-static constexpr dart::compiler::target::word Function_type_parameters_offset =
-    64;
+    40;
+static constexpr dart::compiler::target::word Function_signature_offset = 48;
 static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
     8;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -1737,7 +1755,7 @@
     LinkedHashMap_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
     40;
-static constexpr dart::compiler::target::word LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
@@ -1756,6 +1774,7 @@
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
     312;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
 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 =
@@ -1805,7 +1824,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 376;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 208;
@@ -1816,7 +1835,7 @@
     Thread_call_to_runtime_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 256;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1552;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1858,7 +1877,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1528;
+    1536;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
@@ -1940,20 +1959,28 @@
     72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
     1520;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 1528;
 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 = 32;
 static constexpr dart::compiler::target::word Type_hash_offset = 40;
-static constexpr dart::compiler::target::word Type_signature_offset = 48;
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
-static constexpr dart::compiler::target::word Type_type_state_offset = 60;
-static constexpr dart::compiler::target::word Type_nullability_offset = 61;
+static constexpr dart::compiler::target::word Type_type_state_offset = 48;
+static constexpr dart::compiler::target::word Type_nullability_offset = 49;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 64;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 72;
+    FunctionType_packed_fields_offset = 64;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 56;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 60;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    75;
+    63;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
@@ -1961,7 +1988,7 @@
     32;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
 static constexpr dart::compiler::target::word TypeParameter_bound_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 74;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 62;
 static constexpr dart::compiler::target::word TypeParameter_name_offset = 24;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
@@ -1997,14 +2024,15 @@
         1304, 1312, 1320, 1328, 1336, 1344, 1352, 1360, 1368, 1376, 1384,
         1392, 1400, 1408, 1416, -1,   -1,   -1,   -1,   1424, 1432, -1,
         -1,   1440, 1448, 1456, -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_InstanceSize = 24;
 static constexpr dart::compiler::target::word Array_header_size = 24;
 static constexpr dart::compiler::target::word Bool_InstanceSize = 16;
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 208;
+static constexpr dart::compiler::target::word Class_InstanceSize = 200;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 56;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 48;
 static constexpr dart::compiler::target::word Code_InstanceSize = 176;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
@@ -2027,7 +2055,8 @@
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
 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 = 144;
+static constexpr dart::compiler::target::word Function_InstanceSize = 128;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 72;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     32;
@@ -2066,7 +2095,6 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word Script_InstanceSize = 104;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word SignatureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word Smi_InstanceSize = 8;
@@ -2078,9 +2106,9 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 16;
-static constexpr dart::compiler::target::word Type_InstanceSize = 64;
+static constexpr dart::compiler::target::word Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 40;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 80;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 64;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -2099,7 +2127,7 @@
 
 #if defined(TARGET_ARCH_ARM)
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    84;
+    76;
 static constexpr dart::compiler::target::word
     ICData_receivers_static_type_offset = 16;
 static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
@@ -2166,12 +2194,12 @@
 static constexpr dart::compiler::target::word Array_tags_offset = 0;
 static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word Class_declaration_type_offset =
-    56;
+    48;
 static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    92;
+    88;
 static constexpr dart::compiler::target::word Class_super_type_offset = 44;
 static constexpr dart::compiler::target::word
-    Class_host_type_arguments_field_offset_in_words_offset = 104;
+    Class_host_type_arguments_field_offset_in_words_offset = 100;
 static constexpr dart::compiler::target::word Closure_context_offset = 20;
 static constexpr dart::compiler::target::word
     Closure_delayed_type_arguments_offset = 12;
@@ -2182,9 +2210,9 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 20;
+    ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 24;
+    ClosureData_default_type_arguments_info_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -2209,19 +2237,16 @@
     24;
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 46;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 54;
-static constexpr dart::compiler::target::word Function_code_offset = 44;
-static constexpr dart::compiler::target::word Function_data_offset = 36;
+static constexpr dart::compiler::target::word Function_code_offset = 36;
+static constexpr dart::compiler::target::word Function_data_offset = 28;
 static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
     4, 8};
-static constexpr dart::compiler::target::word Function_kind_tag_offset = 72;
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 64;
 static constexpr dart::compiler::target::word Function_packed_fields_offset =
-    76;
+    68;
 static constexpr dart::compiler::target::word Function_parameter_names_offset =
-    28;
-static constexpr dart::compiler::target::word Function_parameter_types_offset =
-    24;
-static constexpr dart::compiler::target::word Function_type_parameters_offset =
-    32;
+    20;
+static constexpr dart::compiler::target::word Function_signature_offset = 24;
 static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
     4;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -2259,7 +2284,7 @@
     LinkedHashMap_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
     20;
-static constexpr dart::compiler::target::word LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
@@ -2278,6 +2303,7 @@
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
     156;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
 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;
@@ -2325,7 +2351,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 = 728;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 732;
 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;
@@ -2336,7 +2362,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 = 736;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 740;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -2378,7 +2404,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    724;
+    728;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     64;
@@ -2459,19 +2485,27 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 724;
 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;
 static constexpr dart::compiler::target::word Type_hash_offset = 20;
-static constexpr dart::compiler::target::word Type_signature_offset = 24;
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 12;
-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 Type_type_state_offset = 24;
+static constexpr dart::compiler::target::word Type_nullability_offset = 25;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 32;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 40;
+    FunctionType_packed_fields_offset = 32;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 32;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    43;
+    35;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
@@ -2479,7 +2513,7 @@
     16;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
 static constexpr dart::compiler::target::word TypeParameter_bound_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 42;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 34;
 static constexpr dart::compiler::target::word TypeParameter_name_offset = 12;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
@@ -2510,14 +2544,15 @@
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
         660, 664, 668, 672, 676, -1, 680, -1, 684, 688, -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_InstanceSize = 12;
 static constexpr dart::compiler::target::word Array_header_size = 12;
 static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 128;
+static constexpr dart::compiler::target::word Class_InstanceSize = 124;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 28;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word Code_InstanceSize = 76;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
@@ -2540,7 +2575,8 @@
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
 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 Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 40;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     16;
@@ -2579,7 +2615,6 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word SignatureData_InstanceSize = 12;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
 static constexpr dart::compiler::target::word Smi_InstanceSize = 4;
@@ -2590,9 +2625,9 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 12;
-static constexpr dart::compiler::target::word Type_InstanceSize = 36;
+static constexpr dart::compiler::target::word Type_InstanceSize = 28;
 static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 20;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 44;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 36;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
@@ -2609,7 +2644,7 @@
 
 #if defined(TARGET_ARCH_X64)
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    132;
+    116;
 static constexpr dart::compiler::target::word
     ICData_receivers_static_type_offset = 32;
 static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
@@ -2678,12 +2713,12 @@
 static constexpr dart::compiler::target::word Array_tags_offset = 0;
 static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word Class_declaration_type_offset =
-    112;
+    96;
 static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    172;
+    164;
 static constexpr dart::compiler::target::word Class_super_type_offset = 88;
 static constexpr dart::compiler::target::word
-    Class_host_type_arguments_field_offset_in_words_offset = 184;
+    Class_host_type_arguments_field_offset_in_words_offset = 176;
 static constexpr dart::compiler::target::word Closure_context_offset = 40;
 static constexpr dart::compiler::target::word
     Closure_delayed_type_arguments_offset = 24;
@@ -2694,9 +2729,9 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 40;
+    ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 48;
+    ClosureData_default_type_arguments_info_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -2721,19 +2756,16 @@
     48;
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 82;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 90;
-static constexpr dart::compiler::target::word Function_code_offset = 88;
-static constexpr dart::compiler::target::word Function_data_offset = 72;
+static constexpr dart::compiler::target::word Function_code_offset = 72;
+static constexpr dart::compiler::target::word Function_data_offset = 56;
 static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
     8, 16};
-static constexpr dart::compiler::target::word Function_kind_tag_offset = 120;
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 104;
 static constexpr dart::compiler::target::word Function_packed_fields_offset =
-    124;
+    108;
 static constexpr dart::compiler::target::word Function_parameter_names_offset =
-    56;
-static constexpr dart::compiler::target::word Function_parameter_types_offset =
-    48;
-static constexpr dart::compiler::target::word Function_type_parameters_offset =
-    64;
+    40;
+static constexpr dart::compiler::target::word Function_signature_offset = 48;
 static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
     8;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -2771,7 +2803,7 @@
     LinkedHashMap_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
     40;
-static constexpr dart::compiler::target::word LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
@@ -2790,6 +2822,7 @@
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
     312;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
 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 =
@@ -2839,7 +2872,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 376;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1464;
+    1472;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 208;
@@ -2850,7 +2883,7 @@
     Thread_call_to_runtime_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 256;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1480;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1488;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -2892,7 +2925,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1456;
+    1464;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
@@ -2974,20 +3007,28 @@
     72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
     1448;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 1456;
 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 = 32;
 static constexpr dart::compiler::target::word Type_hash_offset = 40;
-static constexpr dart::compiler::target::word Type_signature_offset = 48;
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
-static constexpr dart::compiler::target::word Type_type_state_offset = 60;
-static constexpr dart::compiler::target::word Type_nullability_offset = 61;
+static constexpr dart::compiler::target::word Type_type_state_offset = 48;
+static constexpr dart::compiler::target::word Type_nullability_offset = 49;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 64;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 72;
+    FunctionType_packed_fields_offset = 64;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 56;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 60;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    75;
+    63;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
@@ -2995,7 +3036,7 @@
     32;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
 static constexpr dart::compiler::target::word TypeParameter_bound_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 74;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 62;
 static constexpr dart::compiler::target::word TypeParameter_name_offset = 24;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
@@ -3027,14 +3068,15 @@
     Thread_write_barrier_wrappers_thread_offset[] = {
         1304, 1312, 1320, 1328, -1,   -1,   1336, 1344,
         1352, 1360, 1368, -1,   1376, 1384, -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_InstanceSize = 24;
 static constexpr dart::compiler::target::word Array_header_size = 24;
 static constexpr dart::compiler::target::word Bool_InstanceSize = 16;
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 208;
+static constexpr dart::compiler::target::word Class_InstanceSize = 200;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 56;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 48;
 static constexpr dart::compiler::target::word Code_InstanceSize = 144;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
@@ -3057,7 +3099,8 @@
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
 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 = 144;
+static constexpr dart::compiler::target::word Function_InstanceSize = 128;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 72;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     32;
@@ -3096,7 +3139,6 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word Script_InstanceSize = 88;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word SignatureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word Smi_InstanceSize = 8;
@@ -3108,9 +3150,9 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 16;
-static constexpr dart::compiler::target::word Type_InstanceSize = 64;
+static constexpr dart::compiler::target::word Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 40;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 80;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 64;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -3127,7 +3169,7 @@
 
 #if defined(TARGET_ARCH_IA32)
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    84;
+    76;
 static constexpr dart::compiler::target::word
     ICData_receivers_static_type_offset = 16;
 static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
@@ -3194,12 +3236,12 @@
 static constexpr dart::compiler::target::word Array_tags_offset = 0;
 static constexpr dart::compiler::target::word Array_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word Class_declaration_type_offset =
-    56;
+    48;
 static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    92;
+    88;
 static constexpr dart::compiler::target::word Class_super_type_offset = 44;
 static constexpr dart::compiler::target::word
-    Class_host_type_arguments_field_offset_in_words_offset = 104;
+    Class_host_type_arguments_field_offset_in_words_offset = 100;
 static constexpr dart::compiler::target::word Closure_context_offset = 20;
 static constexpr dart::compiler::target::word
     Closure_delayed_type_arguments_offset = 12;
@@ -3210,9 +3252,9 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 20;
+    ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 24;
+    ClosureData_default_type_arguments_info_offset = 20;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     24;
@@ -3237,19 +3279,16 @@
     24;
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 46;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 54;
-static constexpr dart::compiler::target::word Function_code_offset = 44;
-static constexpr dart::compiler::target::word Function_data_offset = 36;
+static constexpr dart::compiler::target::word Function_code_offset = 36;
+static constexpr dart::compiler::target::word Function_data_offset = 28;
 static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
     4, 8};
-static constexpr dart::compiler::target::word Function_kind_tag_offset = 72;
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 64;
 static constexpr dart::compiler::target::word Function_packed_fields_offset =
-    76;
+    68;
 static constexpr dart::compiler::target::word Function_parameter_names_offset =
-    28;
-static constexpr dart::compiler::target::word Function_parameter_types_offset =
-    24;
-static constexpr dart::compiler::target::word Function_type_parameters_offset =
-    32;
+    20;
+static constexpr dart::compiler::target::word Function_signature_offset = 24;
 static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
     4;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -3287,7 +3326,7 @@
     LinkedHashMap_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
     20;
-static constexpr dart::compiler::target::word LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
@@ -3306,6 +3345,7 @@
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
     156;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
 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;
@@ -3353,7 +3393,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 = 696;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 700;
 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;
@@ -3364,7 +3404,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 = 704;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 708;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3406,7 +3446,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 132;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    692;
+    696;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     64;
@@ -3487,19 +3527,27 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     36;
 static constexpr dart::compiler::target::word Thread_callback_code_offset = 688;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 692;
 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;
 static constexpr dart::compiler::target::word Type_hash_offset = 20;
-static constexpr dart::compiler::target::word Type_signature_offset = 24;
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 12;
-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 Type_type_state_offset = 24;
+static constexpr dart::compiler::target::word Type_nullability_offset = 25;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 32;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 40;
+    FunctionType_packed_fields_offset = 32;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 32;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    43;
+    35;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 8;
@@ -3507,7 +3555,7 @@
     16;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 20;
 static constexpr dart::compiler::target::word TypeParameter_bound_offset = 20;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 42;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 34;
 static constexpr dart::compiler::target::word TypeParameter_name_offset = 12;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
@@ -3535,14 +3583,15 @@
 static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     4, 12, 8, 16};
+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_InstanceSize = 12;
 static constexpr dart::compiler::target::word Array_header_size = 12;
 static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 128;
+static constexpr dart::compiler::target::word Class_InstanceSize = 124;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 28;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word Code_InstanceSize = 76;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
@@ -3565,7 +3614,8 @@
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
 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 Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 40;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 8;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     16;
@@ -3604,7 +3654,6 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word SignatureData_InstanceSize = 12;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
 static constexpr dart::compiler::target::word Smi_InstanceSize = 4;
@@ -3615,9 +3664,9 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 12;
-static constexpr dart::compiler::target::word Type_InstanceSize = 36;
+static constexpr dart::compiler::target::word Type_InstanceSize = 28;
 static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 20;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 44;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 36;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
@@ -3634,7 +3683,7 @@
 
 #if defined(TARGET_ARCH_ARM64)
 static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    132;
+    116;
 static constexpr dart::compiler::target::word
     ICData_receivers_static_type_offset = 32;
 static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
@@ -3703,12 +3752,12 @@
 static constexpr dart::compiler::target::word Array_tags_offset = 0;
 static constexpr dart::compiler::target::word Array_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word Class_declaration_type_offset =
-    112;
+    96;
 static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    172;
+    164;
 static constexpr dart::compiler::target::word Class_super_type_offset = 88;
 static constexpr dart::compiler::target::word
-    Class_host_type_arguments_field_offset_in_words_offset = 184;
+    Class_host_type_arguments_field_offset_in_words_offset = 176;
 static constexpr dart::compiler::target::word Closure_context_offset = 40;
 static constexpr dart::compiler::target::word
     Closure_delayed_type_arguments_offset = 24;
@@ -3719,9 +3768,9 @@
 static constexpr dart::compiler::target::word
     Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_offset = 40;
+    ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    ClosureData_default_type_arguments_info_offset = 48;
+    ClosureData_default_type_arguments_info_offset = 40;
 static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word Code_saved_instructions_offset =
     48;
@@ -3746,19 +3795,16 @@
     48;
 static constexpr dart::compiler::target::word Field_is_nullable_offset = 82;
 static constexpr dart::compiler::target::word Field_kind_bits_offset = 90;
-static constexpr dart::compiler::target::word Function_code_offset = 88;
-static constexpr dart::compiler::target::word Function_data_offset = 72;
+static constexpr dart::compiler::target::word Function_code_offset = 72;
+static constexpr dart::compiler::target::word Function_data_offset = 56;
 static constexpr dart::compiler::target::word Function_entry_point_offset[] = {
     8, 16};
-static constexpr dart::compiler::target::word Function_kind_tag_offset = 120;
+static constexpr dart::compiler::target::word Function_kind_tag_offset = 104;
 static constexpr dart::compiler::target::word Function_packed_fields_offset =
-    124;
+    108;
 static constexpr dart::compiler::target::word Function_parameter_names_offset =
-    56;
-static constexpr dart::compiler::target::word Function_parameter_types_offset =
-    48;
-static constexpr dart::compiler::target::word Function_type_parameters_offset =
-    64;
+    40;
+static constexpr dart::compiler::target::word Function_signature_offset = 48;
 static constexpr dart::compiler::target::word FutureOr_type_arguments_offset =
     8;
 static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
@@ -3796,7 +3842,7 @@
     LinkedHashMap_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
     40;
-static constexpr dart::compiler::target::word LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
@@ -3815,6 +3861,7 @@
 static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
     312;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
 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 =
@@ -3864,7 +3911,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 376;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_auto_scope_native_wrapper_entry_point_offset = 648;
 static constexpr dart::compiler::target::word Thread_bool_false_offset = 208;
@@ -3875,7 +3922,7 @@
     Thread_call_to_runtime_entry_point_offset = 520;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 256;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1552;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3917,7 +3964,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 248;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1528;
+    1536;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     128;
@@ -3999,20 +4046,28 @@
     72;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
     1520;
+static constexpr dart::compiler::target::word
+    Thread_callback_stack_return_offset = 1528;
 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 = 32;
 static constexpr dart::compiler::target::word Type_hash_offset = 40;
-static constexpr dart::compiler::target::word Type_signature_offset = 48;
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
-static constexpr dart::compiler::target::word Type_type_state_offset = 60;
-static constexpr dart::compiler::target::word Type_nullability_offset = 61;
+static constexpr dart::compiler::target::word Type_type_state_offset = 48;
+static constexpr dart::compiler::target::word Type_nullability_offset = 49;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
-    TypeParameter_parameterized_class_id_offset = 64;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 72;
+    FunctionType_packed_fields_offset = 64;
+static constexpr dart::compiler::target::word
+    FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    TypeParameter_parameterized_class_id_offset = 56;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 60;
 static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
-    75;
+    63;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word TypeArguments_length_offset = 16;
@@ -4020,7 +4075,7 @@
     32;
 static constexpr dart::compiler::target::word TypeArguments_types_offset = 40;
 static constexpr dart::compiler::target::word TypeParameter_bound_offset = 40;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 74;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 62;
 static constexpr dart::compiler::target::word TypeParameter_name_offset = 24;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
@@ -4053,14 +4108,15 @@
         1304, 1312, 1320, 1328, 1336, 1344, 1352, 1360, 1368, 1376, 1384,
         1392, 1400, 1408, 1416, -1,   -1,   -1,   -1,   1424, 1432, -1,
         -1,   1440, 1448, 1456, -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_InstanceSize = 24;
 static constexpr dart::compiler::target::word Array_header_size = 24;
 static constexpr dart::compiler::target::word Bool_InstanceSize = 16;
 static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 208;
+static constexpr dart::compiler::target::word Class_InstanceSize = 200;
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word ClosureData_InstanceSize = 56;
+static constexpr dart::compiler::target::word ClosureData_InstanceSize = 48;
 static constexpr dart::compiler::target::word Code_InstanceSize = 144;
 static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
@@ -4083,7 +4139,8 @@
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
 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 = 144;
+static constexpr dart::compiler::target::word Function_InstanceSize = 128;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 72;
 static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
     32;
@@ -4122,7 +4179,6 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word Script_InstanceSize = 88;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word SignatureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word Smi_InstanceSize = 8;
@@ -4134,9 +4190,9 @@
 static constexpr dart::compiler::target::word
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 16;
-static constexpr dart::compiler::target::word Type_InstanceSize = 64;
+static constexpr dart::compiler::target::word Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 40;
-static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 80;
+static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 64;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
 static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
@@ -4224,12 +4280,12 @@
 static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
     4;
 static constexpr dart::compiler::target::word
-    AOT_Class_declaration_type_offset = 56;
+    AOT_Class_declaration_type_offset = 48;
 static constexpr dart::compiler::target::word
-    AOT_Class_num_type_arguments_offset = 92;
+    AOT_Class_num_type_arguments_offset = 88;
 static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_Class_host_type_arguments_field_offset_in_words_offset = 104;
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 100;
 static constexpr dart::compiler::target::word
     AOT_SharedClassTable_class_heap_stats_table_offset = 0;
 static constexpr dart::compiler::target::word AOT_Closure_context_offset = 20;
@@ -4242,9 +4298,9 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 20;
+    AOT_ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 24;
+    AOT_ClosureData_default_type_arguments_info_offset = 20;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 24;
@@ -4270,19 +4326,17 @@
     AOT_Field_guarded_list_length_offset = 24;
 static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 42;
 static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 46;
-static constexpr dart::compiler::target::word AOT_Function_code_offset = 44;
-static constexpr dart::compiler::target::word AOT_Function_data_offset = 36;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 36;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 28;
 static constexpr dart::compiler::target::word
     AOT_Function_entry_point_offset[] = {4, 8};
-static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 48;
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_Function_packed_fields_offset = 52;
+    AOT_Function_packed_fields_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_Function_parameter_names_offset = 28;
-static constexpr dart::compiler::target::word
-    AOT_Function_parameter_types_offset = 24;
-static constexpr dart::compiler::target::word
-    AOT_Function_type_parameters_offset = 32;
+    AOT_Function_parameter_names_offset = 20;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    24;
 static constexpr dart::compiler::target::word
     AOT_FutureOr_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
@@ -4328,7 +4382,7 @@
     AOT_LinkedHashMap_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashMap_used_data_offset = 20;
-static constexpr dart::compiler::target::word AOT_LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
@@ -4352,6 +4406,8 @@
     68;
 static constexpr dart::compiler::target::word
     AOT_ObjectStore_string_type_offset = 156;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    48;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word
@@ -4405,7 +4461,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 =
-    728;
+    732;
 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 =
@@ -4418,7 +4474,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 =
-    736;
+    740;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -4461,7 +4517,7 @@
 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 = 724;
+    AOT_Thread_exit_through_ffi_offset = 728;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 64;
@@ -4548,22 +4604,30 @@
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
     720;
 static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 724;
+static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 16;
 static constexpr dart::compiler::target::word AOT_Type_hash_offset = 20;
-static constexpr dart::compiler::target::word AOT_Type_signature_offset = 24;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
     12;
-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_Type_type_state_offset = 24;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 25;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 32;
+    AOT_FunctionType_packed_fields_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    40;
+    32;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 43;
+    AOT_TypeParameter_nullability_offset = 35;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -4575,7 +4639,7 @@
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
     20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    42;
+    34;
 static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
     12;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
@@ -4614,14 +4678,16 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
         660, 664, 668, 672, 676, -1, 680, -1, 684, 688, -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;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 12;
 static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 112;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 108;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 88;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word
@@ -4646,7 +4712,9 @@
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 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_Function_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    40;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 16;
@@ -4691,8 +4759,6 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_SignatureData_InstanceSize =
-    12;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Smi_InstanceSize = 4;
@@ -4705,11 +4771,11 @@
     AOT_TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word AOT_TwoByteString_InstanceSize =
     12;
-static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 36;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
     20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    44;
+    36;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_TypedData_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -4798,12 +4864,12 @@
 static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
     8;
 static constexpr dart::compiler::target::word
-    AOT_Class_declaration_type_offset = 112;
+    AOT_Class_declaration_type_offset = 96;
 static constexpr dart::compiler::target::word
-    AOT_Class_num_type_arguments_offset = 172;
+    AOT_Class_num_type_arguments_offset = 164;
 static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Class_host_type_arguments_field_offset_in_words_offset = 184;
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 176;
 static constexpr dart::compiler::target::word
     AOT_SharedClassTable_class_heap_stats_table_offset = 0;
 static constexpr dart::compiler::target::word AOT_Closure_context_offset = 40;
@@ -4816,9 +4882,9 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 40;
+    AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 48;
+    AOT_ClosureData_default_type_arguments_info_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -4844,19 +4910,17 @@
     AOT_Field_guarded_list_length_offset = 48;
 static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 74;
 static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 78;
-static constexpr dart::compiler::target::word AOT_Function_code_offset = 88;
-static constexpr dart::compiler::target::word AOT_Function_data_offset = 72;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 72;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_Function_entry_point_offset[] = {8, 16};
-static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 96;
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 80;
 static constexpr dart::compiler::target::word
-    AOT_Function_packed_fields_offset = 100;
+    AOT_Function_packed_fields_offset = 84;
 static constexpr dart::compiler::target::word
-    AOT_Function_parameter_names_offset = 56;
-static constexpr dart::compiler::target::word
-    AOT_Function_parameter_types_offset = 48;
-static constexpr dart::compiler::target::word
-    AOT_Function_type_parameters_offset = 64;
+    AOT_Function_parameter_names_offset = 40;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    48;
 static constexpr dart::compiler::target::word
     AOT_FutureOr_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
@@ -4902,7 +4966,7 @@
     AOT_LinkedHashMap_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashMap_used_data_offset = 40;
-static constexpr dart::compiler::target::word AOT_LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
@@ -4926,6 +4990,8 @@
     136;
 static constexpr dart::compiler::target::word
     AOT_ObjectStore_string_type_offset = 312;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    96;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -4979,7 +5045,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 376;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1464;
+    1472;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -4992,7 +5058,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 256;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1480;
+    1488;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -5035,7 +5101,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1456;
+    AOT_Thread_exit_through_ffi_offset = 1464;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
@@ -5123,22 +5189,30 @@
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
     1448;
 static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 1456;
+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 = 32;
 static constexpr dart::compiler::target::word AOT_Type_hash_offset = 40;
-static constexpr dart::compiler::target::word AOT_Type_signature_offset = 48;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
     24;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 60;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 61;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 48;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 49;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 64;
+    AOT_FunctionType_packed_fields_offset = 64;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 56;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    72;
+    60;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 75;
+    AOT_TypeParameter_nullability_offset = 63;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -5150,7 +5224,7 @@
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    74;
+    62;
 static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
     24;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
@@ -5191,14 +5265,16 @@
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
         1304, 1312, 1320, 1328, -1,   -1,   1336, 1344,
         1352, 1360, 1368, -1,   1376, 1384, -1,   -1};
+static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
+    24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
 static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 192;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 184;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 152;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
@@ -5223,7 +5299,9 @@
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 104;
+static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    72;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 32;
@@ -5268,8 +5346,6 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 88;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_SignatureData_InstanceSize =
-    24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_Smi_InstanceSize = 8;
@@ -5282,11 +5358,11 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_InstanceSize =
     16;
-static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 64;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    80;
+    64;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_TypedData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -5378,12 +5454,12 @@
 static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
     8;
 static constexpr dart::compiler::target::word
-    AOT_Class_declaration_type_offset = 112;
+    AOT_Class_declaration_type_offset = 96;
 static constexpr dart::compiler::target::word
-    AOT_Class_num_type_arguments_offset = 172;
+    AOT_Class_num_type_arguments_offset = 164;
 static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Class_host_type_arguments_field_offset_in_words_offset = 184;
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 176;
 static constexpr dart::compiler::target::word
     AOT_SharedClassTable_class_heap_stats_table_offset = 0;
 static constexpr dart::compiler::target::word AOT_Closure_context_offset = 40;
@@ -5396,9 +5472,9 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 40;
+    AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 48;
+    AOT_ClosureData_default_type_arguments_info_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -5424,19 +5500,17 @@
     AOT_Field_guarded_list_length_offset = 48;
 static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 74;
 static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 78;
-static constexpr dart::compiler::target::word AOT_Function_code_offset = 88;
-static constexpr dart::compiler::target::word AOT_Function_data_offset = 72;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 72;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_Function_entry_point_offset[] = {8, 16};
-static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 96;
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 80;
 static constexpr dart::compiler::target::word
-    AOT_Function_packed_fields_offset = 100;
+    AOT_Function_packed_fields_offset = 84;
 static constexpr dart::compiler::target::word
-    AOT_Function_parameter_names_offset = 56;
-static constexpr dart::compiler::target::word
-    AOT_Function_parameter_types_offset = 48;
-static constexpr dart::compiler::target::word
-    AOT_Function_type_parameters_offset = 64;
+    AOT_Function_parameter_names_offset = 40;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    48;
 static constexpr dart::compiler::target::word
     AOT_FutureOr_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
@@ -5482,7 +5556,7 @@
     AOT_LinkedHashMap_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashMap_used_data_offset = 40;
-static constexpr dart::compiler::target::word AOT_LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
@@ -5506,6 +5580,8 @@
     136;
 static constexpr dart::compiler::target::word
     AOT_ObjectStore_string_type_offset = 312;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    96;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -5559,7 +5635,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 376;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -5572,7 +5648,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 256;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1552;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -5615,7 +5691,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1528;
+    AOT_Thread_exit_through_ffi_offset = 1536;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
@@ -5703,22 +5779,30 @@
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
     1520;
 static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 1528;
+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 = 32;
 static constexpr dart::compiler::target::word AOT_Type_hash_offset = 40;
-static constexpr dart::compiler::target::word AOT_Type_signature_offset = 48;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
     24;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 60;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 61;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 48;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 49;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 64;
+    AOT_FunctionType_packed_fields_offset = 64;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 56;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    72;
+    60;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 75;
+    AOT_TypeParameter_nullability_offset = 63;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -5730,7 +5814,7 @@
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    74;
+    62;
 static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
     24;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
@@ -5772,14 +5856,16 @@
         1304, 1312, 1320, 1328, 1336, 1344, 1352, 1360, 1368, 1376, 1384,
         1392, 1400, 1408, 1416, -1,   -1,   -1,   -1,   1424, 1432, -1,
         -1,   1440, 1448, 1456, -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;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
 static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 192;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 184;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 152;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
@@ -5804,7 +5890,9 @@
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 104;
+static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    72;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 32;
@@ -5849,8 +5937,6 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 88;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_SignatureData_InstanceSize =
-    24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_Smi_InstanceSize = 8;
@@ -5863,11 +5949,11 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_InstanceSize =
     16;
-static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 64;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    80;
+    64;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_TypedData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -5957,12 +6043,12 @@
 static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
     4;
 static constexpr dart::compiler::target::word
-    AOT_Class_declaration_type_offset = 56;
+    AOT_Class_declaration_type_offset = 48;
 static constexpr dart::compiler::target::word
-    AOT_Class_num_type_arguments_offset = 92;
+    AOT_Class_num_type_arguments_offset = 88;
 static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_Class_host_type_arguments_field_offset_in_words_offset = 104;
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 100;
 static constexpr dart::compiler::target::word AOT_Closure_context_offset = 20;
 static constexpr dart::compiler::target::word
     AOT_Closure_delayed_type_arguments_offset = 12;
@@ -5973,9 +6059,9 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 20;
+    AOT_ClosureData_default_type_arguments_offset = 16;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 24;
+    AOT_ClosureData_default_type_arguments_info_offset = 20;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 24;
@@ -6001,19 +6087,17 @@
     AOT_Field_guarded_list_length_offset = 24;
 static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 42;
 static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 46;
-static constexpr dart::compiler::target::word AOT_Function_code_offset = 44;
-static constexpr dart::compiler::target::word AOT_Function_data_offset = 36;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 36;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 28;
 static constexpr dart::compiler::target::word
     AOT_Function_entry_point_offset[] = {4, 8};
-static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 48;
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 40;
 static constexpr dart::compiler::target::word
-    AOT_Function_packed_fields_offset = 52;
+    AOT_Function_packed_fields_offset = 44;
 static constexpr dart::compiler::target::word
-    AOT_Function_parameter_names_offset = 28;
-static constexpr dart::compiler::target::word
-    AOT_Function_parameter_types_offset = 24;
-static constexpr dart::compiler::target::word
-    AOT_Function_type_parameters_offset = 32;
+    AOT_Function_parameter_names_offset = 20;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    24;
 static constexpr dart::compiler::target::word
     AOT_FutureOr_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
@@ -6057,7 +6141,7 @@
     AOT_LinkedHashMap_type_arguments_offset = 4;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashMap_used_data_offset = 20;
-static constexpr dart::compiler::target::word AOT_LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 8;
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
@@ -6081,6 +6165,8 @@
     68;
 static constexpr dart::compiler::target::word
     AOT_ObjectStore_string_type_offset = 156;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    48;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word
@@ -6134,7 +6220,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 =
-    728;
+    732;
 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 =
@@ -6147,7 +6233,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 =
-    736;
+    740;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 44;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -6190,7 +6276,7 @@
 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 = 724;
+    AOT_Thread_exit_through_ffi_offset = 728;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 64;
@@ -6277,22 +6363,30 @@
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
     720;
 static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 724;
+static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 16;
 static constexpr dart::compiler::target::word AOT_Type_hash_offset = 20;
-static constexpr dart::compiler::target::word AOT_Type_signature_offset = 24;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
     12;
-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_Type_type_state_offset = 24;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 25;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 32;
+    AOT_FunctionType_packed_fields_offset = 32;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 28;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    40;
+    32;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 43;
+    AOT_TypeParameter_nullability_offset = 35;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 4;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -6304,7 +6398,7 @@
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
     20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    42;
+    34;
 static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
     12;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
@@ -6340,14 +6434,16 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
         660, 664, 668, 672, 676, -1, 680, -1, 684, 688, -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;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 12;
 static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 112;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 108;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word
@@ -6372,7 +6468,9 @@
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 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_Function_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    40;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 16;
@@ -6417,8 +6515,6 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_SignatureData_InstanceSize =
-    12;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Smi_InstanceSize = 4;
@@ -6431,11 +6527,11 @@
     AOT_TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word AOT_TwoByteString_InstanceSize =
     12;
-static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 36;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
     20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    44;
+    36;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_TypedData_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -6524,12 +6620,12 @@
 static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
     8;
 static constexpr dart::compiler::target::word
-    AOT_Class_declaration_type_offset = 112;
+    AOT_Class_declaration_type_offset = 96;
 static constexpr dart::compiler::target::word
-    AOT_Class_num_type_arguments_offset = 172;
+    AOT_Class_num_type_arguments_offset = 164;
 static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Class_host_type_arguments_field_offset_in_words_offset = 184;
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 176;
 static constexpr dart::compiler::target::word AOT_Closure_context_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Closure_delayed_type_arguments_offset = 24;
@@ -6540,9 +6636,9 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 40;
+    AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 48;
+    AOT_ClosureData_default_type_arguments_info_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -6568,19 +6664,17 @@
     AOT_Field_guarded_list_length_offset = 48;
 static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 74;
 static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 78;
-static constexpr dart::compiler::target::word AOT_Function_code_offset = 88;
-static constexpr dart::compiler::target::word AOT_Function_data_offset = 72;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 72;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_Function_entry_point_offset[] = {8, 16};
-static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 96;
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 80;
 static constexpr dart::compiler::target::word
-    AOT_Function_packed_fields_offset = 100;
+    AOT_Function_packed_fields_offset = 84;
 static constexpr dart::compiler::target::word
-    AOT_Function_parameter_names_offset = 56;
-static constexpr dart::compiler::target::word
-    AOT_Function_parameter_types_offset = 48;
-static constexpr dart::compiler::target::word
-    AOT_Function_type_parameters_offset = 64;
+    AOT_Function_parameter_names_offset = 40;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    48;
 static constexpr dart::compiler::target::word
     AOT_FutureOr_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
@@ -6624,7 +6718,7 @@
     AOT_LinkedHashMap_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashMap_used_data_offset = 40;
-static constexpr dart::compiler::target::word AOT_LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
@@ -6648,6 +6742,8 @@
     136;
 static constexpr dart::compiler::target::word
     AOT_ObjectStore_string_type_offset = 312;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    96;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -6701,7 +6797,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 376;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1464;
+    1472;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -6714,7 +6810,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 256;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1480;
+    1488;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -6757,7 +6853,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1456;
+    AOT_Thread_exit_through_ffi_offset = 1464;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
@@ -6845,22 +6941,30 @@
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
     1448;
 static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 1456;
+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 = 32;
 static constexpr dart::compiler::target::word AOT_Type_hash_offset = 40;
-static constexpr dart::compiler::target::word AOT_Type_signature_offset = 48;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
     24;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 60;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 61;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 48;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 49;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 64;
+    AOT_FunctionType_packed_fields_offset = 64;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 56;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    72;
+    60;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 75;
+    AOT_TypeParameter_nullability_offset = 63;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -6872,7 +6976,7 @@
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    74;
+    62;
 static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
     24;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
@@ -6910,14 +7014,16 @@
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
         1304, 1312, 1320, 1328, -1,   -1,   1336, 1344,
         1352, 1360, 1368, -1,   1376, 1384, -1,   -1};
+static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
+    24;
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
 static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 192;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 184;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
@@ -6942,7 +7048,9 @@
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 104;
+static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    72;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 32;
@@ -6987,8 +7095,6 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 88;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_SignatureData_InstanceSize =
-    24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_Smi_InstanceSize = 8;
@@ -7001,11 +7107,11 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_InstanceSize =
     16;
-static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 64;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    80;
+    64;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_TypedData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
@@ -7097,12 +7203,12 @@
 static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset =
     8;
 static constexpr dart::compiler::target::word
-    AOT_Class_declaration_type_offset = 112;
+    AOT_Class_declaration_type_offset = 96;
 static constexpr dart::compiler::target::word
-    AOT_Class_num_type_arguments_offset = 172;
+    AOT_Class_num_type_arguments_offset = 164;
 static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88;
 static constexpr dart::compiler::target::word
-    AOT_Class_host_type_arguments_field_offset_in_words_offset = 184;
+    AOT_Class_host_type_arguments_field_offset_in_words_offset = 176;
 static constexpr dart::compiler::target::word AOT_Closure_context_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Closure_delayed_type_arguments_offset = 24;
@@ -7113,9 +7219,9 @@
 static constexpr dart::compiler::target::word
     AOT_Closure_instantiator_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_offset = 40;
+    AOT_ClosureData_default_type_arguments_offset = 32;
 static constexpr dart::compiler::target::word
-    AOT_ClosureData_default_type_arguments_info_offset = 48;
+    AOT_ClosureData_default_type_arguments_info_offset = 40;
 static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_Code_saved_instructions_offset = 48;
@@ -7141,19 +7247,17 @@
     AOT_Field_guarded_list_length_offset = 48;
 static constexpr dart::compiler::target::word AOT_Field_is_nullable_offset = 74;
 static constexpr dart::compiler::target::word AOT_Field_kind_bits_offset = 78;
-static constexpr dart::compiler::target::word AOT_Function_code_offset = 88;
-static constexpr dart::compiler::target::word AOT_Function_data_offset = 72;
+static constexpr dart::compiler::target::word AOT_Function_code_offset = 72;
+static constexpr dart::compiler::target::word AOT_Function_data_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_Function_entry_point_offset[] = {8, 16};
-static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 96;
+static constexpr dart::compiler::target::word AOT_Function_kind_tag_offset = 80;
 static constexpr dart::compiler::target::word
-    AOT_Function_packed_fields_offset = 100;
+    AOT_Function_packed_fields_offset = 84;
 static constexpr dart::compiler::target::word
-    AOT_Function_parameter_names_offset = 56;
-static constexpr dart::compiler::target::word
-    AOT_Function_parameter_types_offset = 48;
-static constexpr dart::compiler::target::word
-    AOT_Function_type_parameters_offset = 64;
+    AOT_Function_parameter_names_offset = 40;
+static constexpr dart::compiler::target::word AOT_Function_signature_offset =
+    48;
 static constexpr dart::compiler::target::word
     AOT_FutureOr_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
@@ -7197,7 +7301,7 @@
     AOT_LinkedHashMap_type_arguments_offset = 8;
 static constexpr dart::compiler::target::word
     AOT_LinkedHashMap_used_data_offset = 40;
-static constexpr dart::compiler::target::word AOT_LocalHandle_raw_offset = 0;
+static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
 static constexpr dart::compiler::target::word
     AOT_MarkingStackBlock_pointers_offset = 16;
 static constexpr dart::compiler::target::word AOT_MarkingStackBlock_top_offset =
@@ -7221,6 +7325,8 @@
     136;
 static constexpr dart::compiler::target::word
     AOT_ObjectStore_string_type_offset = 312;
+static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
+    96;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word
@@ -7274,7 +7380,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 376;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 648;
 static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -7287,7 +7393,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 256;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1552;
+    1560;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 88;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -7330,7 +7436,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 248;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1528;
+    AOT_Thread_exit_through_ffi_offset = 1536;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 128;
@@ -7418,22 +7524,30 @@
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
     1520;
 static constexpr dart::compiler::target::word
+    AOT_Thread_callback_stack_return_offset = 1528;
+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 = 32;
 static constexpr dart::compiler::target::word AOT_Type_hash_offset = 40;
-static constexpr dart::compiler::target::word AOT_Type_signature_offset = 48;
 static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
     24;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 60;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 61;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 48;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 49;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_parameterized_class_id_offset = 64;
+    AOT_FunctionType_packed_fields_offset = 64;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_parameter_types_offset = 40;
+static constexpr dart::compiler::target::word
+    AOT_FunctionType_type_parameters_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_TypeParameter_parameterized_class_id_offset = 56;
 static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
-    72;
+    60;
 static constexpr dart::compiler::target::word
-    AOT_TypeParameter_nullability_offset = 75;
+    AOT_TypeParameter_nullability_offset = 63;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
 static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -7445,7 +7559,7 @@
 static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
-    74;
+    62;
 static constexpr dart::compiler::target::word AOT_TypeParameter_name_offset =
     24;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
@@ -7484,14 +7598,16 @@
         1304, 1312, 1320, 1328, 1336, 1344, 1352, 1360, 1368, 1376, 1384,
         1392, 1400, 1408, 1416, -1,   -1,   -1,   -1,   1424, 1432, -1,
         -1,   1440, 1448, 1456, -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;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
 static constexpr dart::compiler::target::word AOT_Bool_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 192;
+static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 184;
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
@@ -7516,7 +7632,9 @@
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 104;
+static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 88;
+static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
+    72;
 static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
 static constexpr dart::compiler::target::word
     AOT_GrowableObjectArray_InstanceSize = 32;
@@ -7561,8 +7679,6 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 88;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
-static constexpr dart::compiler::target::word AOT_SignatureData_InstanceSize =
-    24;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_Smi_InstanceSize = 8;
@@ -7575,11 +7691,11 @@
     AOT_TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_InstanceSize =
     16;
-static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 64;
+static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
-    80;
+    64;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_TypedData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index bc52da9..75c72ff 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -112,8 +112,7 @@
   FIELD(Function, kind_tag_offset)                                             \
   FIELD(Function, packed_fields_offset)                                        \
   FIELD(Function, parameter_names_offset)                                      \
-  FIELD(Function, parameter_types_offset)                                      \
-  FIELD(Function, type_parameters_offset)                                      \
+  FIELD(Function, signature_offset)                                            \
   FIELD(FutureOr, type_arguments_offset)                                       \
   FIELD(GrowableObjectArray, data_offset)                                      \
   FIELD(GrowableObjectArray, length_offset)                                    \
@@ -140,7 +139,7 @@
   FIELD(LinkedHashMap, index_offset)                                           \
   FIELD(LinkedHashMap, type_arguments_offset)                                  \
   FIELD(LinkedHashMap, used_data_offset)                                       \
-  FIELD(LocalHandle, raw_offset)                                               \
+  FIELD(LocalHandle, ptr_offset)                                               \
   FIELD(MarkingStackBlock, pointers_offset)                                    \
   FIELD(MarkingStackBlock, top_offset)                                         \
   FIELD(MegamorphicCache, buckets_offset)                                      \
@@ -153,6 +152,7 @@
   FIELD(ObjectStore, double_type_offset)                                       \
   FIELD(ObjectStore, int_type_offset)                                          \
   FIELD(ObjectStore, string_type_offset)                                       \
+  FIELD(ObjectStore, type_type_offset)                                         \
   FIELD(OneByteString, data_offset)                                            \
   FIELD(PointerBase, data_field_offset)                                        \
   FIELD(Pointer, type_arguments_offset)                                        \
@@ -256,14 +256,18 @@
   FIELD(Thread, write_barrier_entry_point_offset)                              \
   FIELD(Thread, write_barrier_mask_offset)                                     \
   FIELD(Thread, callback_code_offset)                                          \
+  FIELD(Thread, callback_stack_return_offset)                                  \
   FIELD(TimelineStream, enabled_offset)                                        \
   FIELD(TwoByteString, data_offset)                                            \
   FIELD(Type, arguments_offset)                                                \
   FIELD(Type, hash_offset)                                                     \
-  FIELD(Type, signature_offset)                                                \
   FIELD(Type, type_class_id_offset)                                            \
   FIELD(Type, type_state_offset)                                               \
   FIELD(Type, nullability_offset)                                              \
+  FIELD(FunctionType, hash_offset)                                             \
+  FIELD(FunctionType, packed_fields_offset)                                    \
+  FIELD(FunctionType, parameter_types_offset)                                  \
+  FIELD(FunctionType, type_parameters_offset)                                  \
   FIELD(TypeParameter, parameterized_class_id_offset)                          \
   FIELD(TypeParameter, index_offset)                                           \
   FIELD(TypeParameter, nullability_offset)                                     \
@@ -298,85 +302,87 @@
       kNumberOfCpuRegisters - 1,                                               \
       [](Register reg) { return (kDartAvailableCpuRegs & (1 << reg)) != 0; })) \
                                                                                \
-  SIZEOF(ApiError, InstanceSize, ApiErrorLayout)                               \
-  SIZEOF(Array, InstanceSize, ArrayLayout)                                     \
-  SIZEOF(Array, header_size, ArrayLayout)                                      \
-  SIZEOF(Bool, InstanceSize, BoolLayout)                                       \
-  SIZEOF(Capability, InstanceSize, CapabilityLayout)                           \
-  SIZEOF(Class, InstanceSize, ClassLayout)                                     \
-  SIZEOF(Closure, InstanceSize, ClosureLayout)                                 \
-  SIZEOF(ClosureData, InstanceSize, ClosureDataLayout)                         \
-  SIZEOF(Code, InstanceSize, CodeLayout)                                       \
-  SIZEOF(CodeSourceMap, HeaderSize, CodeSourceMapLayout)                       \
-  SIZEOF(CompressedStackMaps, HeaderSize, CompressedStackMapsLayout)           \
-  SIZEOF(Context, InstanceSize, ContextLayout)                                 \
-  SIZEOF(Context, header_size, ContextLayout)                                  \
-  SIZEOF(ContextScope, InstanceSize, ContextScopeLayout)                       \
-  SIZEOF(Double, InstanceSize, DoubleLayout)                                   \
-  SIZEOF(DynamicLibrary, InstanceSize, DynamicLibraryLayout)                   \
-  SIZEOF(ExceptionHandlers, InstanceSize, ExceptionHandlersLayout)             \
-  SIZEOF(ExternalOneByteString, InstanceSize, ExternalOneByteStringLayout)     \
-  SIZEOF(ExternalTwoByteString, InstanceSize, ExternalTwoByteStringLayout)     \
-  SIZEOF(ExternalTypedData, InstanceSize, ExternalTypedDataLayout)             \
-  SIZEOF(FfiTrampolineData, InstanceSize, FfiTrampolineDataLayout)             \
-  SIZEOF(Field, InstanceSize, FieldLayout)                                     \
-  SIZEOF(Float32x4, InstanceSize, Float32x4Layout)                             \
-  SIZEOF(Float64x2, InstanceSize, Float64x2Layout)                             \
-  SIZEOF(Function, InstanceSize, FunctionLayout)                               \
-  SIZEOF(FutureOr, InstanceSize, FutureOrLayout)                               \
-  SIZEOF(GrowableObjectArray, InstanceSize, GrowableObjectArrayLayout)         \
-  SIZEOF(ICData, InstanceSize, ICDataLayout)                                   \
-  SIZEOF(Instance, InstanceSize, InstanceLayout)                               \
-  SIZEOF(Instructions, UnalignedHeaderSize, InstructionsLayout)                \
-  SIZEOF(InstructionsSection, UnalignedHeaderSize, InstructionsSectionLayout)  \
-  SIZEOF(Int32x4, InstanceSize, Int32x4Layout)                                 \
-  SIZEOF(Integer, InstanceSize, IntegerLayout)                                 \
-  SIZEOF(KernelProgramInfo, InstanceSize, KernelProgramInfoLayout)             \
-  SIZEOF(LanguageError, InstanceSize, LanguageErrorLayout)                     \
-  SIZEOF(Library, InstanceSize, LibraryLayout)                                 \
-  SIZEOF(LibraryPrefix, InstanceSize, LibraryPrefixLayout)                     \
-  SIZEOF(LinkedHashMap, InstanceSize, LinkedHashMapLayout)                     \
-  SIZEOF(LocalVarDescriptors, InstanceSize, LocalVarDescriptorsLayout)         \
-  SIZEOF(MegamorphicCache, InstanceSize, MegamorphicCacheLayout)               \
-  SIZEOF(Mint, InstanceSize, MintLayout)                                       \
-  SIZEOF(MirrorReference, InstanceSize, MirrorReferenceLayout)                 \
-  SIZEOF(MonomorphicSmiableCall, InstanceSize, MonomorphicSmiableCallLayout)   \
-  SIZEOF(Namespace, InstanceSize, NamespaceLayout)                             \
+  SIZEOF(AbstractType, InstanceSize, UntaggedAbstractType)                     \
+  SIZEOF(ApiError, InstanceSize, UntaggedApiError)                             \
+  SIZEOF(Array, InstanceSize, UntaggedArray)                                   \
+  SIZEOF(Array, header_size, UntaggedArray)                                    \
+  SIZEOF(Bool, InstanceSize, UntaggedBool)                                     \
+  SIZEOF(Capability, InstanceSize, UntaggedCapability)                         \
+  SIZEOF(Class, InstanceSize, UntaggedClass)                                   \
+  SIZEOF(Closure, InstanceSize, UntaggedClosure)                               \
+  SIZEOF(ClosureData, InstanceSize, UntaggedClosureData)                       \
+  SIZEOF(Code, InstanceSize, UntaggedCode)                                     \
+  SIZEOF(CodeSourceMap, HeaderSize, UntaggedCodeSourceMap)                     \
+  SIZEOF(CompressedStackMaps, HeaderSize, UntaggedCompressedStackMaps)         \
+  SIZEOF(Context, InstanceSize, UntaggedContext)                               \
+  SIZEOF(Context, header_size, UntaggedContext)                                \
+  SIZEOF(ContextScope, InstanceSize, UntaggedContextScope)                     \
+  SIZEOF(Double, InstanceSize, UntaggedDouble)                                 \
+  SIZEOF(DynamicLibrary, InstanceSize, UntaggedDynamicLibrary)                 \
+  SIZEOF(ExceptionHandlers, InstanceSize, UntaggedExceptionHandlers)           \
+  SIZEOF(ExternalOneByteString, InstanceSize, UntaggedExternalOneByteString)   \
+  SIZEOF(ExternalTwoByteString, InstanceSize, UntaggedExternalTwoByteString)   \
+  SIZEOF(ExternalTypedData, InstanceSize, UntaggedExternalTypedData)           \
+  SIZEOF(FfiTrampolineData, InstanceSize, UntaggedFfiTrampolineData)           \
+  SIZEOF(Field, InstanceSize, UntaggedField)                                   \
+  SIZEOF(Float32x4, InstanceSize, UntaggedFloat32x4)                           \
+  SIZEOF(Float64x2, InstanceSize, UntaggedFloat64x2)                           \
+  SIZEOF(Function, InstanceSize, UntaggedFunction)                             \
+  SIZEOF(FunctionType, InstanceSize, UntaggedFunctionType)                     \
+  SIZEOF(FutureOr, InstanceSize, UntaggedFutureOr)                             \
+  SIZEOF(GrowableObjectArray, InstanceSize, UntaggedGrowableObjectArray)       \
+  SIZEOF(ICData, InstanceSize, UntaggedICData)                                 \
+  SIZEOF(Instance, InstanceSize, UntaggedInstance)                             \
+  SIZEOF(Instructions, UnalignedHeaderSize, UntaggedInstructions)              \
+  SIZEOF(InstructionsSection, UnalignedHeaderSize,                             \
+         UntaggedInstructionsSection)                                          \
+  SIZEOF(Int32x4, InstanceSize, UntaggedInt32x4)                               \
+  SIZEOF(Integer, InstanceSize, UntaggedInteger)                               \
+  SIZEOF(KernelProgramInfo, InstanceSize, UntaggedKernelProgramInfo)           \
+  SIZEOF(LanguageError, InstanceSize, UntaggedLanguageError)                   \
+  SIZEOF(Library, InstanceSize, UntaggedLibrary)                               \
+  SIZEOF(LibraryPrefix, InstanceSize, UntaggedLibraryPrefix)                   \
+  SIZEOF(LinkedHashMap, InstanceSize, UntaggedLinkedHashMap)                   \
+  SIZEOF(LocalVarDescriptors, InstanceSize, UntaggedLocalVarDescriptors)       \
+  SIZEOF(MegamorphicCache, InstanceSize, UntaggedMegamorphicCache)             \
+  SIZEOF(Mint, InstanceSize, UntaggedMint)                                     \
+  SIZEOF(MirrorReference, InstanceSize, UntaggedMirrorReference)               \
+  SIZEOF(MonomorphicSmiableCall, InstanceSize, UntaggedMonomorphicSmiableCall) \
+  SIZEOF(Namespace, InstanceSize, UntaggedNamespace)                           \
   SIZEOF(NativeArguments, StructSize, NativeArguments)                         \
-  SIZEOF(Number, InstanceSize, NumberLayout)                                   \
-  SIZEOF(Object, InstanceSize, ObjectLayout)                                   \
-  SIZEOF(ObjectPool, InstanceSize, ObjectPoolLayout)                           \
-  SIZEOF(OneByteString, InstanceSize, OneByteStringLayout)                     \
-  SIZEOF(PatchClass, InstanceSize, PatchClassLayout)                           \
-  SIZEOF(PcDescriptors, HeaderSize, PcDescriptorsLayout)                       \
-  SIZEOF(Pointer, InstanceSize, PointerLayout)                                 \
-  SIZEOF(ReceivePort, InstanceSize, ReceivePortLayout)                         \
-  SIZEOF(RegExp, InstanceSize, RegExpLayout)                                   \
-  SIZEOF(Script, InstanceSize, ScriptLayout)                                   \
-  SIZEOF(SendPort, InstanceSize, SendPortLayout)                               \
-  SIZEOF(SignatureData, InstanceSize, SignatureDataLayout)                     \
-  SIZEOF(SingleTargetCache, InstanceSize, SingleTargetCacheLayout)             \
-  SIZEOF(Smi, InstanceSize, SmiLayout)                                         \
-  SIZEOF(StackTrace, InstanceSize, StackTraceLayout)                           \
-  SIZEOF(String, InstanceSize, StringLayout)                                   \
-  SIZEOF(SubtypeTestCache, InstanceSize, SubtypeTestCacheLayout)               \
-  SIZEOF(LoadingUnit, InstanceSize, LoadingUnitLayout)                         \
-  SIZEOF(TransferableTypedData, InstanceSize, TransferableTypedDataLayout)     \
-  SIZEOF(TwoByteString, InstanceSize, TwoByteStringLayout)                     \
-  SIZEOF(Type, InstanceSize, TypeLayout)                                       \
-  SIZEOF(TypeArguments, InstanceSize, TypeArgumentsLayout)                     \
-  SIZEOF(TypeParameter, InstanceSize, TypeParameterLayout)                     \
-  SIZEOF(TypeRef, InstanceSize, TypeRefLayout)                                 \
-  SIZEOF(TypedData, InstanceSize, TypedDataLayout)                             \
-  SIZEOF(TypedDataBase, InstanceSize, TypedDataBaseLayout)                     \
-  SIZEOF(TypedDataView, InstanceSize, TypedDataViewLayout)                     \
-  SIZEOF(UnhandledException, InstanceSize, UnhandledExceptionLayout)           \
-  SIZEOF(UnlinkedCall, InstanceSize, UnlinkedCallLayout)                       \
-  SIZEOF(UnwindError, InstanceSize, UnwindErrorLayout)                         \
-  SIZEOF(UserTag, InstanceSize, UserTagLayout)                                 \
-  SIZEOF(WeakProperty, InstanceSize, WeakPropertyLayout)                       \
+  SIZEOF(Number, InstanceSize, UntaggedNumber)                                 \
+  SIZEOF(Object, InstanceSize, UntaggedObject)                                 \
+  SIZEOF(ObjectPool, InstanceSize, UntaggedObjectPool)                         \
+  SIZEOF(OneByteString, InstanceSize, UntaggedOneByteString)                   \
+  SIZEOF(PatchClass, InstanceSize, UntaggedPatchClass)                         \
+  SIZEOF(PcDescriptors, HeaderSize, UntaggedPcDescriptors)                     \
+  SIZEOF(Pointer, InstanceSize, UntaggedPointer)                               \
+  SIZEOF(ReceivePort, InstanceSize, UntaggedReceivePort)                       \
+  SIZEOF(RegExp, InstanceSize, UntaggedRegExp)                                 \
+  SIZEOF(Script, InstanceSize, UntaggedScript)                                 \
+  SIZEOF(SendPort, InstanceSize, UntaggedSendPort)                             \
+  SIZEOF(SingleTargetCache, InstanceSize, UntaggedSingleTargetCache)           \
+  SIZEOF(Smi, InstanceSize, UntaggedSmi)                                       \
+  SIZEOF(StackTrace, InstanceSize, UntaggedStackTrace)                         \
+  SIZEOF(String, InstanceSize, UntaggedString)                                 \
+  SIZEOF(SubtypeTestCache, InstanceSize, UntaggedSubtypeTestCache)             \
+  SIZEOF(LoadingUnit, InstanceSize, UntaggedLoadingUnit)                       \
+  SIZEOF(TransferableTypedData, InstanceSize, UntaggedTransferableTypedData)   \
+  SIZEOF(TwoByteString, InstanceSize, UntaggedTwoByteString)                   \
+  SIZEOF(Type, InstanceSize, UntaggedType)                                     \
+  SIZEOF(TypeArguments, InstanceSize, UntaggedTypeArguments)                   \
+  SIZEOF(TypeParameter, InstanceSize, UntaggedTypeParameter)                   \
+  SIZEOF(TypeRef, InstanceSize, UntaggedTypeRef)                               \
+  SIZEOF(TypedData, InstanceSize, UntaggedTypedData)                           \
+  SIZEOF(TypedDataBase, InstanceSize, UntaggedTypedDataBase)                   \
+  SIZEOF(TypedDataView, InstanceSize, UntaggedTypedDataView)                   \
+  SIZEOF(UnhandledException, InstanceSize, UntaggedUnhandledException)         \
+  SIZEOF(UnlinkedCall, InstanceSize, UntaggedUnlinkedCall)                     \
+  SIZEOF(UnwindError, InstanceSize, UntaggedUnwindError)                       \
+  SIZEOF(UserTag, InstanceSize, UntaggedUserTag)                               \
+  SIZEOF(WeakProperty, InstanceSize, UntaggedWeakProperty)                     \
   SIZEOF(WeakSerializationReference, InstanceSize,                             \
-         WeakSerializationReferenceLayout)                                     \
+         UntaggedWeakSerializationReference)                                   \
   PAYLOAD_SIZEOF(CodeSourceMap, InstanceSize, HeaderSize)                      \
   PAYLOAD_SIZEOF(CompressedStackMaps, InstanceSize, HeaderSize)                \
   PAYLOAD_SIZEOF(InstructionsSection, InstanceSize, HeaderSize)                \
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 8295e00..e08b548 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -118,6 +118,11 @@
   __ Ret();
 
   if (is_final) {
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+    // We are jumping over LeaveStubFrame so restore LR state to match one
+    // at the jump point.
+    __ set_lr_state(compiler::LRState::OnEntry().EnterFrame());
+#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
     __ Bind(&throw_exception);
     __ PushObject(NullObject());  // Make room for (unused) result.
     __ PushRegister(kFieldReg);
@@ -191,16 +196,21 @@
 
 // For use in GenerateTypeIsTopTypeForSubtyping and
 // GenerateNullIsAssignableToType.
-static void EnsureIsTypeOrTypeParameter(Assembler* assembler,
-                                        Register type_reg,
-                                        Register scratch_reg) {
+static void EnsureIsTypeOrFunctionTypeOrTypeParameter(Assembler* assembler,
+                                                      Register type_reg,
+                                                      Register scratch_reg) {
 #if defined(DEBUG)
-  compiler::Label is_type_param_or_type;
+  compiler::Label is_type_param_or_type_or_function_type;
   __ LoadClassIdMayBeSmi(scratch_reg, type_reg);
   __ CompareImmediate(scratch_reg, kTypeParameterCid);
-  __ BranchIf(EQUAL, &is_type_param_or_type, compiler::Assembler::kNearJump);
+  __ BranchIf(EQUAL, &is_type_param_or_type_or_function_type,
+              compiler::Assembler::kNearJump);
   __ CompareImmediate(scratch_reg, kTypeCid);
-  __ BranchIf(EQUAL, &is_type_param_or_type, compiler::Assembler::kNearJump);
+  __ BranchIf(EQUAL, &is_type_param_or_type_or_function_type,
+              compiler::Assembler::kNearJump);
+  __ CompareImmediate(scratch_reg, kFunctionTypeCid);
+  __ BranchIf(EQUAL, &is_type_param_or_type_or_function_type,
+              compiler::Assembler::kNearJump);
   // Type references show up in F-bounded polymorphism, which is limited
   // to classes. Thus, TypeRefs only appear in places like class type
   // arguments or the bounds of uninstantiated class type parameters.
@@ -210,8 +220,8 @@
   // a function type parameter or the type of a function parameter
   // (respectively), we should never see a TypeRef here. This check is here
   // in case this changes and we need to update this stub.
-  __ Stop("not a type or type parameter");
-  __ Bind(&is_type_param_or_type);
+  __ Stop("not a type or function type or type parameter");
+  __ Bind(&is_type_param_or_type_or_function_type);
 #endif
 }
 
@@ -260,12 +270,14 @@
   __ MoveRegister(scratch1_reg, TypeTestABI::kDstTypeReg);
   __ Bind(&check_top_type);
   // scratch1_reg: Current type to check.
-  EnsureIsTypeOrTypeParameter(assembler, scratch1_reg, scratch2_reg);
+  EnsureIsTypeOrFunctionTypeOrTypeParameter(assembler, scratch1_reg,
+                                            scratch2_reg);
   compiler::Label is_type_ref;
-  __ CompareClassId(scratch1_reg, kTypeParameterCid, scratch2_reg);
+  __ CompareClassId(scratch1_reg, kTypeCid, scratch2_reg);
   // Type parameters can't be top types themselves, though a particular
   // instantiation may result in a top type.
-  __ BranchIf(EQUAL, &done);
+  // Function types cannot be top types.
+  __ BranchIf(NOT_EQUAL, &done);
   __ LoadField(
       scratch2_reg,
       compiler::FieldAddress(scratch1_reg,
@@ -372,7 +384,8 @@
     __ BranchIf(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
     __ Bind(&check_null_assignable);
     // scratch1_reg: Current type to check.
-    EnsureIsTypeOrTypeParameter(assembler, scratch1_reg, scratch2_reg);
+    EnsureIsTypeOrFunctionTypeOrTypeParameter(assembler, scratch1_reg,
+                                              scratch2_reg);
     compiler::Label is_not_type;
     __ CompareClassId(scratch1_reg, kTypeCid, scratch2_reg);
     __ BranchIf(NOT_EQUAL, &is_not_type, compiler::Assembler::kNearJump);
@@ -606,13 +619,7 @@
                          target::Type::type_state_offset(), kByte);
   __ CompareImmediate(
       TypeTestABI::kScratchReg,
-      target::AbstractTypeLayout::kTypeStateFinalizedInstantiated);
-  __ BranchIf(NOT_EQUAL, &is_complex_case, Assembler::kNearJump);
-
-  // Check whether this [Type] is a function type.
-  __ LoadFieldFromOffset(TypeTestABI::kScratchReg, TypeTestABI::kDstTypeReg,
-                         target::Type::signature_offset());
-  __ CompareObject(TypeTestABI::kScratchReg, NullObject());
+      target::UntaggedAbstractType::kTypeStateFinalizedInstantiated);
   __ BranchIf(NOT_EQUAL, &is_complex_case, Assembler::kNearJump);
 
   // This [Type] could be a FutureOr. Subtype2TestCache does not support Smi.
@@ -670,7 +677,7 @@
 void StubCodeCompiler::GenerateAllocateUnhandledExceptionStub(
     Assembler* assembler) {
   Thread* thread = Thread::Current();
-  auto class_table = thread->isolate()->class_table();
+  auto class_table = thread->isolate_group()->class_table();
   ASSERT(class_table->HasValidClassAt(kUnhandledExceptionCid));
   const auto& cls = Class::ZoneHandle(thread->zone(),
                                       class_table->At(kUnhandledExceptionCid));
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index 5f3e09c..357c005 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -112,8 +112,8 @@
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
 #elif defined(TARGET_ARCH_IA32)
   static constexpr intptr_t kNativeCallbackTrampolineSize = 10;
-  static constexpr intptr_t kNativeCallbackSharedStubSize = 90;
-  static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
+  static constexpr intptr_t kNativeCallbackSharedStubSize = 134;
+  static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
 #elif defined(TARGET_ARCH_ARM)
   static constexpr intptr_t kNativeCallbackTrampolineSize = 12;
   static constexpr intptr_t kNativeCallbackSharedStubSize = 140;
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 44b632d..0dfaa61 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -183,7 +183,7 @@
 
   // To make the stack map calculation architecture independent we do the same
   // as on intel.
-  __ Push(LR);
+  READS_RETURN_ADDRESS_FROM_LR(__ Push(LR));
   __ PushRegisters(all_registers);
   __ ldr(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
   __ EnterStubFrame();
@@ -195,7 +195,7 @@
   __ LeaveStubFrame();
   __ PopRegisters(all_registers);
   __ Drop(1);  // We use the LR restored via LeaveStubFrame.
-  __ bx(LR);
+  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR));
 }
 
 void StubCodeCompiler::GenerateSharedStub(
@@ -208,7 +208,9 @@
   ASSERT(!store_runtime_result_in_result_register || allow_return);
   auto perform_runtime_call = [&]() {
     if (store_runtime_result_in_result_register) {
-      __ PushRegister(LR);
+      // Reserve space for the result on the stack. This needs to be a GC
+      // safe value.
+      __ PushImmediate(Smi::RawValue(0));
     }
     __ CallRuntime(*target, /*argument_count=*/0);
     if (store_runtime_result_in_result_register) {
@@ -307,11 +309,11 @@
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
 
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  SPILLS_LR_TO_FRAME(__ EnterFrame((1 << FP) | (1 << LR), 0));
   __ ReserveAlignedFrameSpace(0);
   __ ldr(R0, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ blx(R0);
-  __ LeaveFrame((1 << FP) | (1 << LR), 0);
+  RESTORES_LR_FROM_FRAME(__ LeaveFrame((1 << FP) | (1 << LR), 0));
 
   __ PopRegisters(all_registers);
   __ Ret();
@@ -322,7 +324,7 @@
   all_registers.AddAllGeneralRegisters();
   __ PushRegisters(all_registers);
 
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  SPILLS_LR_TO_FRAME(__ EnterFrame((1 << FP) | (1 << LR), 0));
   __ ReserveAlignedFrameSpace(0);
 
   // Set the execution state to VM while waiting for the safepoint to end.
@@ -333,7 +335,7 @@
 
   __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ blx(R0);
-  __ LeaveFrame((1 << FP) | (1 << LR), 0);
+  RESTORES_LR_FROM_FRAME(__ LeaveFrame((1 << FP) | (1 << LR), 0));
 
   __ PopRegisters(all_registers);
   __ Ret();
@@ -353,7 +355,7 @@
   COMPILE_ASSERT(IsAbiPreservedRegister(R4));
 
   // TransitionGeneratedToNative might clobber LR if it takes the slow path.
-  __ mov(R4, Operand(LR));
+  SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(__ mov(R4, Operand(LR)));
 
   __ LoadImmediate(R9, target::Thread::exit_through_ffi());
   __ TransitionGeneratedToNative(R8, FPREG, R9 /*volatile*/, NOTFP,
@@ -402,7 +404,8 @@
 
   // Save THR (callee-saved), R4 & R5 (temporaries, callee-saved), and LR.
   COMPILE_ASSERT(StubCodeCompiler::kNativeCallbackTrampolineStackDelta == 4);
-  __ PushList((1 << LR) | (1 << THR) | (1 << R4) | (1 << R5));
+  SPILLS_LR_TO_FRAME(
+      __ PushList((1 << LR) | (1 << THR) | (1 << R4) | (1 << R5)));
 
   // Don't rely on TMP being preserved by assembler macros anymore.
   __ mov(R4, Operand(TMP));
@@ -578,8 +581,7 @@
   __ mov(R1, Operand(R9));  // Pass the function entrypoint to call.
 
   // Call native function invocation wrapper or redirection via simulator.
-  __ ldr(LR, wrapper);
-  __ blx(LR);
+  __ Call(wrapper);
 
   // Mark that the thread is executing Dart code.
   __ LoadImmediate(R2, VMTag::kDartTagId);
@@ -910,7 +912,7 @@
   __ LoadImmediate(IP, kZapCodeReg);
   __ Push(IP);
   // Return address for "call" to deopt stub.
-  __ LoadImmediate(LR, kZapReturnAddress);
+  WRITES_RETURN_ADDRESS_TO_LR(__ LoadImmediate(LR, kZapReturnAddress));
   __ ldr(CODE_REG,
          Address(THR, target::Thread::lazy_deopt_from_return_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
@@ -925,7 +927,7 @@
   __ LoadImmediate(IP, kZapCodeReg);
   __ Push(IP);
   // Return address for "call" to deopt stub.
-  __ LoadImmediate(LR, kZapReturnAddress);
+  WRITES_RETURN_ADDRESS_TO_LR(__ LoadImmediate(LR, kZapReturnAddress));
   __ ldr(CODE_REG,
          Address(THR, target::Thread::lazy_deopt_from_throw_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
@@ -1056,10 +1058,10 @@
     // R3: new object end address.
     // R9: allocation size.
     {
-      const intptr_t shift = target::ObjectLayout::kTagBitsSizeTagPos -
+      const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
                              target::ObjectAlignment::kObjectAlignmentLog2;
 
-      __ CompareImmediate(R9, target::ObjectLayout::kSizeTagMaxSizeTag);
+      __ CompareImmediate(R9, target::UntaggedObject::kSizeTagMaxSizeTag);
       __ mov(R8, Operand(R9, LSL, shift), LS);
       __ mov(R8, Operand(0), HI);
 
@@ -1112,13 +1114,13 @@
   // Pop arguments; result is popped in IP.
   __ PopList((1 << R1) | (1 << R2) | (1 << IP));  // R2 is restored.
   __ mov(R0, Operand(IP));
+  __ LeaveStubFrame();
 
   // Write-barrier elimination might be enabled for this array (depending on the
   // array length). To be sure we will check if the allocated object is in old
   // space and if so call a leaf runtime to add it to the remembered set.
   EnsureIsNewOrRemembered(assembler);
 
-  __ LeaveStubFrame();
   __ Ret();
 }
 
@@ -1172,8 +1174,8 @@
 //   R2 : arguments array.
 //   R3 : current thread.
 void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
-  __ Push(LR);  // Marker for the profiler.
-  __ EnterFrame((1 << FP) | (1 << LR), 0);
+  READS_RETURN_ADDRESS_FROM_LR(__ Push(LR));  // Marker for the profiler.
+  SPILLS_LR_TO_FRAME(__ EnterFrame((1 << FP) | (1 << LR), 0));
 
   // Push code object to PC marker slot.
   __ ldr(IP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
@@ -1293,7 +1295,7 @@
   __ set_constant_pool_allowed(false);
 
   // Restore the frame pointer and return.
-  __ LeaveFrame((1 << FP) | (1 << LR));
+  RESTORES_LR_FROM_FRAME(__ LeaveFrame((1 << FP) | (1 << LR)));
   __ Drop(1);
   __ Ret();
 }
@@ -1303,7 +1305,7 @@
 // Input:
 //   R1: number of context variables.
 // Output:
-//   R0: new allocated RawContext object.
+//   R0: new allocated Context object.
 // Clobbered:
 //   R2, R3, R8, R9
 static void GenerateAllocateContext(Assembler* assembler, Label* slow_case) {
@@ -1347,9 +1349,9 @@
   // R1: number of context variables.
   // R2: object size.
   // R3: next object start.
-  const intptr_t shift = target::ObjectLayout::kTagBitsSizeTagPos -
+  const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
                          target::ObjectAlignment::kObjectAlignmentLog2;
-  __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);
+  __ CompareImmediate(R2, target::UntaggedObject::kSizeTagMaxSizeTag);
   // If no size tag overflow, shift R2 left, else set R2 to zero.
   __ mov(R9, Operand(R2, LSL, shift), LS);
   __ mov(R9, Operand(0), HI);
@@ -1375,7 +1377,7 @@
 // Input:
 //   R1: number of context variables.
 // Output:
-//   R0: new allocated RawContext object.
+//   R0: new allocated Context object.
 // Clobbered:
 //   Potentially any since is can go to runtime.
 void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
@@ -1436,7 +1438,7 @@
 // Input:
 //   R4: context variable to clone.
 // Output:
-//   R0: new allocated RawContext object.
+//   R0: new allocated Context object.
 // Clobbered:
 //   Potentially any since it can go to runtime.
 void StubCodeCompiler::GenerateCloneContextStub(Assembler* assembler) {
@@ -1507,19 +1509,17 @@
 }
 
 void StubCodeCompiler::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
-  RegList saved = (1 << LR) | (1 << kWriteBarrierObjectReg);
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
     if ((kDartAvailableCpuRegs & (1 << i)) == 0) continue;
 
     Register reg = static_cast<Register>(i);
     intptr_t start = __ CodeSize();
-    __ PushList(saved);
+    SPILLS_LR_TO_FRAME(__ PushList((1 << LR) | (1 << kWriteBarrierObjectReg)));
     __ mov(kWriteBarrierObjectReg, Operand(reg));
-    __ ldr(LR,
-           Address(THR, target::Thread::write_barrier_entry_point_offset()));
-    __ blx(LR);
-    __ PopList(saved);
-    __ bx(LR);
+    __ Call(Address(THR, target::Thread::write_barrier_entry_point_offset()));
+    RESTORES_LR_FROM_FRAME(
+        __ PopList((1 << LR) | (1 << kWriteBarrierObjectReg)));
+    READS_RETURN_ADDRESS_FROM_LR(__ bx(LR));
     intptr_t end = __ CodeSize();
 
     RELEASE_ASSERT(end - start == kStoreBufferWrapperSize);
@@ -1545,13 +1545,13 @@
 
   if (cards) {
     __ ldr(TMP, FieldAddress(R1, target::Object::tags_offset()));
-    __ tst(TMP, Operand(1 << target::ObjectLayout::kCardRememberedBit));
+    __ tst(TMP, Operand(1 << target::UntaggedObject::kCardRememberedBit));
     __ b(&remember_card, NOT_ZERO);
   } else {
 #if defined(DEBUG)
     Label ok;
     __ ldr(TMP, FieldAddress(R1, target::Object::tags_offset()));
-    __ tst(TMP, Operand(1 << target::ObjectLayout::kCardRememberedBit));
+    __ tst(TMP, Operand(1 << target::UntaggedObject::kCardRememberedBit));
     __ b(&ok, ZERO);
     __ Stop("Wrong barrier");
     __ Bind(&ok);
@@ -1568,7 +1568,7 @@
   Label retry;
   __ Bind(&retry);
   __ ldrex(R2, R3);
-  __ bic(R2, R2, Operand(1 << target::ObjectLayout::kOldAndNotRememberedBit));
+  __ bic(R2, R2, Operand(1 << target::UntaggedObject::kOldAndNotRememberedBit));
   __ strex(R4, R2, R3);
   __ cmp(R4, Operand(1));
   __ b(&retry, EQ);
@@ -1616,9 +1616,9 @@
   // R3: Untagged address of header word (ldrex/strex do not support offsets).
   __ Bind(&marking_retry);
   __ ldrex(R2, R3);
-  __ tst(R2, Operand(1 << target::ObjectLayout::kOldAndNotMarkedBit));
+  __ tst(R2, Operand(1 << target::UntaggedObject::kOldAndNotMarkedBit));
   __ b(&lost_race, ZERO);
-  __ bic(R2, R2, Operand(1 << target::ObjectLayout::kOldAndNotMarkedBit));
+  __ bic(R2, R2, Operand(1 << target::UntaggedObject::kOldAndNotMarkedBit));
   __ strex(R4, R2, R3);
   __ cmp(R4, Operand(1));
   __ b(&marking_retry, EQ);
@@ -2629,7 +2629,7 @@
   // used to initialize this register.
   const Register kCacheArrayReg = TypeTestABI::kSubtypeTestCacheReg;
   const Register kScratchReg = TypeTestABI::kScratchReg;
-  const Register kInstanceCidOrFunction = R9;
+
   // Registers that are only used for n >= 3 and must be preserved if used.
   Register kInstanceInstantiatorTypeArgumentsReg = kNoRegister;
   // Registers that are only used for n >= 7 and must be preserved if used.
@@ -2674,16 +2674,18 @@
 
   Label loop, not_closure;
   if (n >= 5) {
-    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
+    __ LoadClassIdMayBeSmi(STCInternalRegs::kInstanceCidOrFunctionReg,
+                           TypeTestABI::kInstanceReg);
   } else {
-    __ LoadClassId(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
+    __ LoadClassId(STCInternalRegs::kInstanceCidOrFunctionReg,
+                   TypeTestABI::kInstanceReg);
   }
-  __ CompareImmediate(kInstanceCidOrFunction, kClosureCid);
+  __ CompareImmediate(STCInternalRegs::kInstanceCidOrFunctionReg, kClosureCid);
   __ b(&not_closure, NE);
 
   // Closure handling.
   {
-    __ ldr(kInstanceCidOrFunction,
+    __ ldr(STCInternalRegs::kInstanceCidOrFunctionReg,
            FieldAddress(TypeTestABI::kInstanceReg,
                         target::Closure::function_offset()));
     if (n >= 3) {
@@ -2709,7 +2711,7 @@
     __ Bind(&not_closure);
     if (n >= 3) {
       Label has_no_type_arguments;
-      __ LoadClassById(kScratchReg, kInstanceCidOrFunction);
+      __ LoadClassById(kScratchReg, STCInternalRegs::kInstanceCidOrFunctionReg);
       __ mov(kInstanceInstantiatorTypeArgumentsReg, Operand(kNullReg));
       __ ldr(
           kScratchReg,
@@ -2729,7 +2731,7 @@
         __ PushRegister(kNullReg);
       }
     }
-    __ SmiTag(kInstanceCidOrFunction);
+    __ SmiTag(STCInternalRegs::kInstanceCidOrFunctionReg);
   }
 
   const intptr_t kNoDepth = -1;
@@ -2746,7 +2748,7 @@
                      target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmp(kScratchReg, Operand(kNullReg));
   __ b(&not_found, EQ);
-  __ cmp(kScratchReg, Operand(kInstanceCidOrFunction));
+  __ cmp(kScratchReg, Operand(STCInternalRegs::kInstanceCidOrFunctionReg));
   if (n == 1) {
     __ b(&found, EQ);
   } else {
@@ -2915,7 +2917,8 @@
 // The arguments are stored in the Thread object.
 // Does not return.
 void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
-  __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset());
+  WRITES_RETURN_ADDRESS_TO_LR(
+      __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset()));
 
   word offset_from_thread = 0;
   bool ok = target::CanLoadFromThread(NullObject(), &offset_from_thread);
@@ -2930,7 +2933,8 @@
   __ LoadFromOffset(R1, THR, target::Thread::active_stacktrace_offset());
   __ StoreToOffset(R2, THR, target::Thread::active_stacktrace_offset());
 
-  __ bx(LR);  // Jump to the exception handler code.
+  READS_RETURN_ADDRESS_FROM_LR(
+      __ bx(LR));  // Jump to the exception handler code.
 }
 
 // Deoptimize a frame on the call stack before rewinding.
@@ -2942,7 +2946,8 @@
   __ Push(IP);
 
   // Load the deopt pc into LR.
-  __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset());
+  WRITES_RETURN_ADDRESS_TO_LR(
+      __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset()));
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
 
   // After we have deoptimized, jump to the correct frame.
@@ -3479,10 +3484,10 @@
   /* R1: new object end address. */
   /* R2: allocation size. */
   {
-    __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);
+    __ CompareImmediate(R2, target::UntaggedObject::kSizeTagMaxSizeTag);
     __ mov(R3,
            Operand(R2, LSL,
-                   target::ObjectLayout::kTagBitsSizeTagPos -
+                   target::UntaggedObject::kTagBitsSizeTagPos -
                        target::ObjectAlignment::kObjectAlignmentLog2),
            LS);
     __ mov(R3, Operand(0), HI);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 7168025..2bbe95e 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -194,7 +194,7 @@
 
   // To make the stack map calculation architecture independent we do the same
   // as on intel.
-  __ Push(LR);
+  READS_RETURN_ADDRESS_FROM_LR(__ Push(LR));
   __ PushRegisters(all_registers);
   __ ldr(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
   __ EnterStubFrame();
@@ -206,7 +206,7 @@
   __ LeaveStubFrame();
   __ PopRegisters(all_registers);
   __ Drop(1);  // We use the LR restored via LeaveStubFrame.
-  __ ret(LR);
+  READS_RETURN_ADDRESS_FROM_LR(__ ret(LR));
 }
 
 void StubCodeCompiler::GenerateSharedStub(
@@ -302,7 +302,7 @@
     Assembler* assembler) {
   COMPILE_ASSERT(IsAbiPreservedRegister(R19));
 
-  __ mov(R19, LR);
+  SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(__ mov(R19, LR));
   __ LoadImmediate(R10, target::Thread::exit_through_ffi());
   __ TransitionGeneratedToNative(R9, FPREG, R10 /*volatile*/,
                                  /*enter_safepoint=*/true);
@@ -368,12 +368,15 @@
   // Save THR (callee-saved) and LR on real real C stack (CSP). Keeps it
   // aligned.
   COMPILE_ASSERT(StubCodeCompiler::kNativeCallbackTrampolineStackDelta == 2);
-  __ stp(THR, LR, Address(CSP, -2 * target::kWordSize, Address::PairPreIndex));
+  SPILLS_LR_TO_FRAME(__ stp(
+      THR, LR, Address(CSP, -2 * target::kWordSize, Address::PairPreIndex)));
 
   COMPILE_ASSERT(!IsArgumentRegister(THR));
 
   RegisterSet all_registers;
   all_registers.AddAllArgumentRegisters();
+  all_registers.Add(Location::RegisterLocation(
+      CallingConventions::kPointerToReturnStructRegisterCall));
 
   // The call below might clobber R9 (volatile, holding callback_id).
   all_registers.Add(Location::RegisterLocation(R9));
@@ -442,7 +445,8 @@
   __ EnterSafepoint(/*scratch=*/R9);
 
   // Pop LR and THR from the real stack (CSP).
-  __ ldp(THR, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex));
+  RESTORES_LR_FROM_FRAME(__ ldp(
+      THR, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex)));
 
   __ ret();
 
@@ -674,8 +678,7 @@
   __ mov(R1, R5);  // Pass the function entrypoint to call.
 
   // Call native function invocation wrapper or redirection via simulator.
-  __ ldr(LR, wrapper);
-  __ blr(LR);
+  __ Call(wrapper);
 
   // Restore SP and CSP.
   __ mov(SP, CSP);
@@ -1020,7 +1023,7 @@
   __ LoadImmediate(TMP, kZapCodeReg);
   __ Push(TMP);
   // Return address for "call" to deopt stub.
-  __ LoadImmediate(LR, kZapReturnAddress);
+  WRITES_RETURN_ADDRESS_TO_LR(__ LoadImmediate(LR, kZapReturnAddress));
   __ ldr(CODE_REG,
          Address(THR, target::Thread::lazy_deopt_from_return_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
@@ -1035,7 +1038,7 @@
   __ LoadImmediate(TMP, kZapCodeReg);
   __ Push(TMP);
   // Return address for "call" to deopt stub.
-  __ LoadImmediate(LR, kZapReturnAddress);
+  WRITES_RETURN_ADDRESS_TO_LR(__ LoadImmediate(LR, kZapReturnAddress));
   __ ldr(CODE_REG,
          Address(THR, target::Thread::lazy_deopt_from_throw_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
@@ -1186,9 +1189,9 @@
     // R2: array length as Smi.
     // R3: array size.
     // R7: new object end address.
-    const intptr_t shift = target::ObjectLayout::kTagBitsSizeTagPos -
+    const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2;
-    __ CompareImmediate(R3, target::ObjectLayout::kSizeTagMaxSizeTag);
+    __ CompareImmediate(R3, target::UntaggedObject::kSizeTagMaxSizeTag);
     // If no size tag overflow, shift R1 left, else set R1 to zero.
     __ LslImmediate(TMP, R3, shift);
     __ csel(R1, TMP, R1, LS);
@@ -1241,13 +1244,13 @@
   __ Pop(R1);
   __ Pop(R2);
   __ Pop(R0);
+  __ LeaveStubFrame();
 
   // Write-barrier elimination might be enabled for this array (depending on the
   // array length). To be sure we will check if the allocated object is in old
   // space and if so call a leaf runtime to add it to the remembered set.
   EnsureIsNewOrRemembered(assembler);
 
-  __ LeaveStubFrame();
   __ ret();
 }
 
@@ -1307,7 +1310,7 @@
   // from over-writing Dart frames.
   __ mov(SP, CSP);
   __ SetupCSPFromThread(R3);
-  __ Push(LR);  // Marker for the profiler.
+  READS_RETURN_ADDRESS_FROM_LR(__ Push(LR));  // Marker for the profiler.
   __ EnterFrame(0);
 
   // Push code object to PC marker slot.
@@ -1425,17 +1428,7 @@
   __ Pop(R4);
   __ StoreToOffset(R4, THR, target::Thread::vm_tag_offset());
 
-#if defined(TARGET_OS_FUCHSIA)
-  __ mov(R3, THR);
-#endif
-
-  __ PopNativeCalleeSavedRegisters();  // Clobbers THR
-
-#if defined(TARGET_OS_FUCHSIA)
-  __ str(R18, Address(R3, target::Thread::saved_shadow_call_stack_offset()));
-#elif defined(USING_SHADOW_CALL_STACK)
-#error Unimplemented
-#endif
+  __ PopNativeCalleeSavedRegisters();
 
   // Restore the frame pointer and C stack pointer and return.
   __ LeaveFrame();
@@ -1449,7 +1442,7 @@
 // Input:
 //   R1: number of context variables.
 // Output:
-//   R0: new allocated RawContext object.
+//   R0: new allocated Context object.
 // Clobbered:
 //   R2, R3, R4, TMP
 static void GenerateAllocateContextSpaceStub(Assembler* assembler,
@@ -1492,9 +1485,9 @@
   // R0: new object.
   // R1: number of context variables.
   // R2: object size.
-  const intptr_t shift = target::ObjectLayout::kTagBitsSizeTagPos -
+  const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
                          target::ObjectAlignment::kObjectAlignmentLog2;
-  __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);
+  __ CompareImmediate(R2, target::UntaggedObject::kSizeTagMaxSizeTag);
   // If no size tag overflow, shift R2 left, else set R2 to zero.
   __ LslImmediate(TMP, R2, shift);
   __ csel(R2, TMP, R2, LS);
@@ -1519,7 +1512,7 @@
 // Input:
 //   R1: number of context variables.
 // Output:
-//   R0: new allocated RawContext object.
+//   R0: new allocated Context object.
 // Clobbered:
 //   R2, R3, R4, TMP
 void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
@@ -1583,7 +1576,7 @@
 // Input:
 //   R5: context variable to clone.
 // Output:
-//   R0: new allocated RawContext object.
+//   R0: new allocated Context object.
 // Clobbered:
 //   R1, (R2), R3, R4, (TMP)
 void StubCodeCompiler::GenerateCloneContextStub(Assembler* assembler) {
@@ -1662,15 +1655,13 @@
 
     Register reg = static_cast<Register>(i);
     intptr_t start = __ CodeSize();
-    __ Push(LR);
+    SPILLS_LR_TO_FRAME(__ Push(LR));
     __ Push(kWriteBarrierObjectReg);
     __ mov(kWriteBarrierObjectReg, reg);
-    __ ldr(LR,
-           Address(THR, target::Thread::write_barrier_entry_point_offset()));
-    __ blr(LR);
+    __ Call(Address(THR, target::Thread::write_barrier_entry_point_offset()));
     __ Pop(kWriteBarrierObjectReg);
-    __ Pop(LR);
-    __ ret(LR);
+    RESTORES_LR_FROM_FRAME(__ Pop(LR));
+    READS_RETURN_ADDRESS_FROM_LR(__ ret(LR));
     intptr_t end = __ CodeSize();
 
     RELEASE_ASSERT(end - start == kStoreBufferWrapperSize);
@@ -1696,12 +1687,12 @@
 
   if (cards) {
     __ LoadFieldFromOffset(TMP, R1, target::Object::tags_offset(), kFourBytes);
-    __ tbnz(&remember_card, TMP, target::ObjectLayout::kCardRememberedBit);
+    __ tbnz(&remember_card, TMP, target::UntaggedObject::kCardRememberedBit);
   } else {
 #if defined(DEBUG)
     Label ok;
     __ LoadFieldFromOffset(TMP, R1, target::Object::tags_offset(), kFourBytes);
-    __ tbz(&ok, TMP, target::ObjectLayout::kCardRememberedBit);
+    __ tbz(&ok, TMP, target::UntaggedObject::kCardRememberedBit);
     __ Stop("Wrong barrier");
     __ Bind(&ok);
 #endif
@@ -1720,7 +1711,7 @@
   __ Bind(&retry);
   __ ldxr(R2, R3, kEightBytes);
   __ AndImmediate(R2, R2,
-                  ~(1 << target::ObjectLayout::kOldAndNotRememberedBit));
+                  ~(1 << target::UntaggedObject::kOldAndNotRememberedBit));
   __ stxr(R4, R2, R3, kEightBytes);
   __ cbnz(&retry, R4);
 
@@ -1770,8 +1761,8 @@
   // R3: Untagged address of header word (ldxr/stxr do not support offsets).
   __ Bind(&marking_retry);
   __ ldxr(R2, R3, kEightBytes);
-  __ tbz(&lost_race, R2, target::ObjectLayout::kOldAndNotMarkedBit);
-  __ AndImmediate(R2, R2, ~(1 << target::ObjectLayout::kOldAndNotMarkedBit));
+  __ tbz(&lost_race, R2, target::UntaggedObject::kOldAndNotMarkedBit);
+  __ AndImmediate(R2, R2, ~(1 << target::UntaggedObject::kOldAndNotMarkedBit));
   __ stxr(R4, R2, R3, kEightBytes);
   __ cbnz(&marking_retry, R4);
 
@@ -2786,7 +2777,7 @@
 // Used to check class and type arguments. Arguments passed in registers:
 //
 // Inputs (mostly from TypeTestABI struct):
-//   - kSubtypeTestCacheReg: SubtypeTestCacheLayout
+//   - kSubtypeTestCacheReg: UntaggedSubtypeTestCache
 //   - kInstanceReg: instance to test against.
 //   - kDstTypeReg: destination type (for n>=3).
 //   - kInstantiatorTypeArgumentsReg: instantiator type arguments (for n=5).
@@ -2809,10 +2800,6 @@
 
   const Register kCacheArrayReg = TypeTestABI::kSubtypeTestCacheReg;
   const Register kScratchReg = TypeTestABI::kScratchReg;
-  const Register kInstanceCidOrFunction = R6;
-  const Register kInstanceInstantiatorTypeArgumentsReg = R5;
-  const Register kInstanceParentFunctionTypeArgumentsReg = R9;
-  const Register kInstanceDelayedFunctionTypeArgumentsReg = R10;
 
   // All of these must be distinct from TypeTestABI::kSubtypeTestCacheResultReg
   // since it is used for kNullReg as well.
@@ -2830,29 +2817,30 @@
 
   Label loop, not_closure;
   if (n >= 5) {
-    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction,
+    __ LoadClassIdMayBeSmi(STCInternalRegs::kInstanceCidOrFunctionReg,
                            TypeTestABI::TypeTestABI::kInstanceReg);
   } else {
-    __ LoadClassId(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
+    __ LoadClassId(STCInternalRegs::kInstanceCidOrFunctionReg,
+                   TypeTestABI::kInstanceReg);
   }
-  __ CompareImmediate(kInstanceCidOrFunction, kClosureCid);
+  __ CompareImmediate(STCInternalRegs::kInstanceCidOrFunctionReg, kClosureCid);
   __ b(&not_closure, NE);
 
   // Closure handling.
   {
-    __ ldr(kInstanceCidOrFunction,
+    __ ldr(STCInternalRegs::kInstanceCidOrFunctionReg,
            FieldAddress(TypeTestABI::kInstanceReg,
                         target::Closure::function_offset()));
     if (n >= 3) {
       __ ldr(
-          kInstanceInstantiatorTypeArgumentsReg,
+          STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
           FieldAddress(TypeTestABI::kInstanceReg,
                        target::Closure::instantiator_type_arguments_offset()));
       if (n >= 7) {
-        __ ldr(kInstanceParentFunctionTypeArgumentsReg,
+        __ ldr(STCInternalRegs::kInstanceParentFunctionTypeArgumentsReg,
                FieldAddress(TypeTestABI::kInstanceReg,
                             target::Closure::function_type_arguments_offset()));
-        __ ldr(kInstanceDelayedFunctionTypeArgumentsReg,
+        __ ldr(STCInternalRegs::kInstanceDelayedFunctionTypeArgumentsReg,
                FieldAddress(TypeTestABI::kInstanceReg,
                             target::Closure::delayed_type_arguments_offset()));
       }
@@ -2865,8 +2853,8 @@
     __ Bind(&not_closure);
     if (n >= 3) {
       Label has_no_type_arguments;
-      __ LoadClassById(kScratchReg, kInstanceCidOrFunction);
-      __ mov(kInstanceInstantiatorTypeArgumentsReg, kNullReg);
+      __ LoadClassById(kScratchReg, STCInternalRegs::kInstanceCidOrFunctionReg);
+      __ mov(STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg, kNullReg);
       __ LoadFieldFromOffset(
           kScratchReg, kScratchReg,
           target::Class::host_type_arguments_field_offset_in_words_offset(),
@@ -2875,16 +2863,18 @@
       __ b(&has_no_type_arguments, EQ);
       __ add(kScratchReg, TypeTestABI::kInstanceReg,
              Operand(kScratchReg, LSL, 3));
-      __ ldr(kInstanceInstantiatorTypeArgumentsReg,
+      __ ldr(STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
              FieldAddress(kScratchReg, 0));
       __ Bind(&has_no_type_arguments);
 
       if (n >= 7) {
-        __ mov(kInstanceParentFunctionTypeArgumentsReg, kNullReg);
-        __ mov(kInstanceDelayedFunctionTypeArgumentsReg, kNullReg);
+        __ mov(STCInternalRegs::kInstanceParentFunctionTypeArgumentsReg,
+               kNullReg);
+        __ mov(STCInternalRegs::kInstanceDelayedFunctionTypeArgumentsReg,
+               kNullReg);
       }
     }
-    __ SmiTag(kInstanceCidOrFunction);
+    __ SmiTag(STCInternalRegs::kInstanceCidOrFunctionReg);
   }
 
   Label found, done, next_iteration;
@@ -2897,7 +2887,7 @@
                      target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmp(kScratchReg, Operand(kNullReg));
   __ b(&done, EQ);
-  __ cmp(kScratchReg, Operand(kInstanceCidOrFunction));
+  __ cmp(kScratchReg, Operand(STCInternalRegs::kInstanceCidOrFunctionReg));
   if (n == 1) {
     __ b(&found, EQ);
   } else {
@@ -2912,7 +2902,8 @@
            Address(kCacheArrayReg,
                    target::kWordSize *
                        target::SubtypeTestCache::kInstanceTypeArguments));
-    __ cmp(kScratchReg, Operand(kInstanceInstantiatorTypeArgumentsReg));
+    __ cmp(kScratchReg,
+           Operand(STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg));
     if (n == 3) {
       __ b(&found, EQ);
     } else {
@@ -2939,7 +2930,9 @@
                        target::kWordSize *
                            target::SubtypeTestCache::
                                kInstanceParentFunctionTypeArguments));
-        __ cmp(kScratchReg, Operand(kInstanceParentFunctionTypeArgumentsReg));
+        __ cmp(
+            kScratchReg,
+            Operand(STCInternalRegs::kInstanceParentFunctionTypeArgumentsReg));
         __ b(&next_iteration, NE);
 
         __ ldr(kScratchReg,
@@ -2947,7 +2940,9 @@
                        target::kWordSize *
                            target::SubtypeTestCache::
                                kInstanceDelayedFunctionTypeArguments));
-        __ cmp(kScratchReg, Operand(kInstanceDelayedFunctionTypeArgumentsReg));
+        __ cmp(
+            kScratchReg,
+            Operand(STCInternalRegs::kInstanceDelayedFunctionTypeArgumentsReg));
         __ b(&found, EQ);
       }
     }
@@ -3003,10 +2998,10 @@
 void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
   ASSERT(kExceptionObjectReg == R0);
   ASSERT(kStackTraceObjectReg == R1);
-  // TransitionGeneratedToNative might clobber LR if it takes the slow path.
+  __ set_lr_state(compiler::LRState::Clobbered());
   __ mov(CALLEE_SAVED_TEMP, R0);  // Program counter.
-  __ mov(SP, R1);  // Stack pointer.
-  __ mov(FP, R2);  // Frame_pointer.
+  __ mov(SP, R1);                 // Stack pointer.
+  __ mov(FP, R2);                 // Frame_pointer.
   __ mov(THR, R3);
   __ SetupCSPFromThread(THR);
 #if defined(TARGET_OS_FUCHSIA)
@@ -3048,7 +3043,8 @@
 // The arguments are stored in the Thread object.
 // Does not return.
 void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
-  __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset());
+  WRITES_RETURN_ADDRESS_TO_LR(
+      __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset()));
 
   word offset_from_thread = 0;
   bool ok = target::CanLoadFromThread(NullObject(), &offset_from_thread);
@@ -3075,7 +3071,8 @@
   __ Push(TMP);
 
   // Load the deopt pc into LR.
-  __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset());
+  WRITES_RETURN_ADDRESS_TO_LR(
+      __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset()));
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
 
   // After we have deoptimized, jump to the correct frame.
@@ -3618,9 +3615,9 @@
   /* R1: new object end address. */
   /* R2: allocation size. */
   {
-    __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);
+    __ CompareImmediate(R2, target::UntaggedObject::kSizeTagMaxSizeTag);
     __ LslImmediate(R2, R2,
-                    target::ObjectLayout::kTagBitsSizeTagPos -
+                    target::UntaggedObject::kTagBitsSizeTagPos -
                         target::ObjectAlignment::kObjectAlignmentLog2);
     __ csel(R2, ZR, R2, HI);
 
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 4d499af..229be66 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -213,7 +213,7 @@
 void StubCodeCompiler::GenerateJITCallbackTrampolines(
     Assembler* assembler,
     intptr_t next_callback_id) {
-  Label done;
+  Label done, ret_4;
 
   // EAX is volatile and doesn't hold any arguments.
   COMPILE_ASSERT(!IsArgumentRegister(EAX) && !IsCalleeSavedRegister(EAX));
@@ -232,16 +232,20 @@
 
   const intptr_t shared_stub_start = __ CodeSize();
 
-  // Save THR which is callee-saved.
+  // Save THR and EBX which are callee-saved.
   __ pushl(THR);
+  __ pushl(EBX);
+
+  // We need the callback ID after the call for return stack.
+  __ pushl(EAX);
 
   // THR & return address
-  COMPILE_ASSERT(StubCodeCompiler::kNativeCallbackTrampolineStackDelta == 2);
+  COMPILE_ASSERT(StubCodeCompiler::kNativeCallbackTrampolineStackDelta == 4);
 
   // Load the thread, verify the callback ID and exit the safepoint.
   //
   // We exit the safepoint inside DLRT_GetThreadForNativeCallbackTrampoline
-  // in order to safe code size on this shared stub.
+  // in order to save code size on this shared stub.
   {
     __ EnterFrame(0);
     __ ReserveAlignedFrameSpace(compiler::target::kWordSize);
@@ -278,14 +282,54 @@
   // the saved THR and the return address. The target will know to skip them.
   __ call(ECX);
 
+  // Register state:
+  // - callee saved registers (should be restored)
+  //   - EBX available as scratch because we restore it later.
+  //   - ESI(THR) contains thread
+  //   - EDI
+  // - return registers (should not be touched)
+  //   - EAX
+  //   - EDX
+  // - available scratch registers
+  //   - ECX free
+
+  // Load the return stack delta from the thread.
+  __ movl(ECX,
+          compiler::Address(
+              THR, compiler::target::Thread::callback_stack_return_offset()));
+  __ popl(EBX);  // Compiler callback id.
+  __ movzxb(EBX, __ ElementAddressForRegIndex(
+                     /*external=*/false,
+                     /*array_cid=*/kTypedDataUint8ArrayCid,
+                     /*index=*/1,
+                     /*index_unboxed=*/false,
+                     /*array=*/ECX,
+                     /*index=*/EBX));
+#if defined(DEBUG)
+  // Stack delta should be either 0 or 4.
+  Label check_done;
+  __ BranchIfZero(EBX, &check_done);
+  __ CompareImmediate(EBX, compiler::target::kWordSize);
+  __ BranchIf(EQUAL, &check_done);
+  __ Breakpoint();
+  __ Bind(&check_done);
+#endif
+
   // EnterSafepoint takes care to not clobber *any* registers (besides scratch).
   __ EnterSafepoint(/*scratch=*/ECX);
 
-  // Restore THR (callee-saved).
+  // Restore callee-saved registers.
+  __ movl(ECX, EBX);
+  __ popl(EBX);
   __ popl(THR);
 
+  __ cmpl(ECX, compiler::Immediate(Smi::RawValue(0)));
+  __ j(NOT_EQUAL, &ret_4, compiler::Assembler::kNearJump);
   __ ret();
 
+  __ Bind(&ret_4);
+  __ ret(Immediate(4));
+
   // 'kNativeCallbackSharedStubSize' is an upper bound because the exact
   // instruction size can vary slightly based on OS calling conventions.
   ASSERT((__ CodeSize() - shared_stub_start) <= kNativeCallbackSharedStubSize);
@@ -822,9 +866,9 @@
     {
       Label size_tag_overflow, done;
       __ movl(EDI, EBX);
-      __ cmpl(EDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+      __ cmpl(EDI, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
       __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-      __ shll(EDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+      __ shll(EDI, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
                              target::ObjectAlignment::kObjectAlignmentLog2));
       __ jmp(&done, Assembler::kNearJump);
 
@@ -1034,7 +1078,7 @@
 // Input:
 // EDX: number of context variables.
 // Output:
-// EAX: new allocated RawContext object.
+// EAX: new allocated Context object.
 // Clobbered:
 // EBX
 static void GenerateAllocateContextSpaceStub(Assembler* assembler,
@@ -1084,9 +1128,9 @@
     Label size_tag_overflow, done;
     __ leal(EBX, Address(EDX, TIMES_4, fixed_size_plus_alignment_padding));
     __ andl(EBX, Immediate(-target::ObjectAlignment::kObjectAlignment));
-    __ cmpl(EBX, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+    __ cmpl(EBX, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shll(EBX, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+    __ shll(EBX, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done);
 
@@ -1113,7 +1157,7 @@
 // Input:
 // EDX: number of context variables.
 // Output:
-// EAX: new allocated RawContext object.
+// EAX: new allocated Context object.
 // Clobbered:
 // EBX, EDX
 void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
@@ -1179,7 +1223,7 @@
 // Input:
 //   ECX: context variable.
 // Output:
-//   EAX: new allocated RawContext object.
+//   EAX: new allocated Context object.
 // Clobbered:
 //   EBX, ECX, EDX
 void StubCodeCompiler::GenerateCloneContextStub(Assembler* assembler) {
@@ -1276,7 +1320,8 @@
   // Spilled: EAX, ECX
   // EDX: Address being stored
   __ movl(EAX, FieldAddress(EDX, target::Object::tags_offset()));
-  __ testl(EAX, Immediate(1 << target::ObjectLayout::kOldAndNotRememberedBit));
+  __ testl(EAX,
+           Immediate(1 << target::UntaggedObject::kOldAndNotRememberedBit));
   __ j(NOT_EQUAL, &add_to_buffer, Assembler::kNearJump);
   __ popl(ECX);
   __ popl(EAX);
@@ -1289,12 +1334,12 @@
 
   if (cards) {
     // Check if this object is using remembered cards.
-    __ testl(EAX, Immediate(1 << target::ObjectLayout::kCardRememberedBit));
+    __ testl(EAX, Immediate(1 << target::UntaggedObject::kCardRememberedBit));
     __ j(NOT_EQUAL, &remember_card, Assembler::kFarJump);  // Unlikely.
   } else {
 #if defined(DEBUG)
     Label ok;
-    __ testl(EAX, Immediate(1 << target::ObjectLayout::kCardRememberedBit));
+    __ testl(EAX, Immediate(1 << target::UntaggedObject::kCardRememberedBit));
     __ j(ZERO, &ok, Assembler::kFarJump);  // Unlikely.
     __ Stop("Wrong barrier");
     __ Bind(&ok);
@@ -1304,7 +1349,7 @@
   // lock+andl is an atomic read-modify-write.
   __ lock();
   __ andl(FieldAddress(EDX, target::Object::tags_offset()),
-          Immediate(~(1 << target::ObjectLayout::kOldAndNotRememberedBit)));
+          Immediate(~(1 << target::UntaggedObject::kOldAndNotRememberedBit)));
 
   // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
@@ -2947,9 +2992,9 @@
   /* EDI: allocation size. */
   {
     Label size_tag_overflow, done;
-    __ cmpl(EDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+    __ cmpl(EDI, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shll(EDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+    __ shll(EDI, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done, Assembler::kNearJump);
     __ Bind(&size_tag_overflow);
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 08b540d..175ed5d 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -1100,9 +1100,9 @@
     // RDI: allocation size.
     {
       Label size_tag_overflow, done;
-      __ cmpq(RDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+      __ cmpq(RDI, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
       __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-      __ shlq(RDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+      __ shlq(RDI, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
                              target::ObjectAlignment::kObjectAlignmentLog2));
       __ jmp(&done, Assembler::kNearJump);
 
@@ -1374,7 +1374,7 @@
 // Input:
 //   R10: number of context variables.
 // Output:
-//   RAX: new, uinitialised allocated RawContext object.
+//   RAX: new, uinitialised allocated Context object.
 // Clobbered:
 //   R13
 static void GenerateAllocateContextSpaceStub(Assembler* assembler,
@@ -1420,9 +1420,9 @@
     Label size_tag_overflow, done;
     __ leaq(R13, Address(R10, TIMES_8, fixed_size_plus_alignment_padding));
     __ andq(R13, Immediate(-target::ObjectAlignment::kObjectAlignment));
-    __ cmpq(R13, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+    __ cmpq(R13, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shlq(R13, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+    __ shlq(R13, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done);
 
@@ -1449,7 +1449,7 @@
 // Input:
 //   R10: number of context variables.
 // Output:
-//   RAX: new allocated RawContext object.
+//   RAX: new allocated Context object.
 // Clobbered:
 //   R9, R13
 void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
@@ -1517,7 +1517,7 @@
 // Input:
 //   R9: context to clone.
 // Output:
-//   RAX: new allocated RawContext object.
+//   RAX: new allocated Context object.
 // Clobbered:
 //   R10, R13
 void StubCodeCompiler::GenerateCloneContextStub(Assembler* assembler) {
@@ -1621,13 +1621,13 @@
 
   if (cards) {
     __ movl(TMP, FieldAddress(RDX, target::Object::tags_offset()));
-    __ testl(TMP, Immediate(1 << target::ObjectLayout::kCardRememberedBit));
+    __ testl(TMP, Immediate(1 << target::UntaggedObject::kCardRememberedBit));
     __ j(NOT_ZERO, &remember_card, Assembler::kFarJump);
   } else {
 #if defined(DEBUG)
     Label ok;
     __ movl(TMP, FieldAddress(RDX, target::Object::tags_offset()));
-    __ testl(TMP, Immediate(1 << target::ObjectLayout::kCardRememberedBit));
+    __ testl(TMP, Immediate(1 << target::UntaggedObject::kCardRememberedBit));
     __ j(ZERO, &ok, Assembler::kFarJump);
     __ Stop("Wrong barrier");
     __ Bind(&ok);
@@ -1640,7 +1640,7 @@
   // lock+andq is an atomic read-modify-write.
   __ lock();
   __ andq(FieldAddress(RDX, target::Object::tags_offset()),
-          Immediate(~(1 << target::ObjectLayout::kOldAndNotRememberedBit)));
+          Immediate(~(1 << target::UntaggedObject::kOldAndNotRememberedBit)));
 
   // Save registers being destroyed.
   __ pushq(RAX);
@@ -1690,9 +1690,9 @@
   __ movq(RAX, FieldAddress(TMP, target::Object::tags_offset()));
   __ Bind(&retry);
   __ movq(RCX, RAX);
-  __ testq(RCX, Immediate(1 << target::ObjectLayout::kOldAndNotMarkedBit));
+  __ testq(RCX, Immediate(1 << target::UntaggedObject::kOldAndNotMarkedBit));
   __ j(ZERO, &lost_race);  // Marked by another thread.
-  __ andq(RCX, Immediate(~(1 << target::ObjectLayout::kOldAndNotMarkedBit)));
+  __ andq(RCX, Immediate(~(1 << target::UntaggedObject::kOldAndNotMarkedBit)));
   __ LockCmpxchgq(FieldAddress(TMP, target::Object::tags_offset()), RCX);
   __ j(NOT_EQUAL, &retry, Assembler::kNearJump);
 
@@ -2367,7 +2367,7 @@
     __ j(EQUAL, &call_target_function_through_unchecked_entry);
 
     // Check trivial exactness.
-    // Note: ICDataLayout::receivers_static_type_ is guaranteed to be not null
+    // Note: UntaggedICData::receivers_static_type_ is guaranteed to be not null
     // because we only emit calls to this stub when it is not null.
     __ movq(RCX,
             FieldAddress(RBX, target::ICData::receivers_static_type_offset()));
@@ -2731,7 +2731,7 @@
 // Used to check class and type arguments. Arguments passed in registers:
 //
 // Input registers (from TypeTestABI struct):
-//   - kSubtypeTestCacheReg: SubtypeTestCacheLayout
+//   - kSubtypeTestCacheReg: UntaggedSubtypeTestCache
 //   - kInstanceReg: instance to test against (must be preserved).
 //   - kDstTypeReg: destination type (for n>=3).
 //   - kInstantiatorTypeArgumentsReg : instantiator type arguments (for n>=5).
@@ -2752,12 +2752,8 @@
   const Register kNullReg = TypeTestABI::kSubtypeTestCacheResultReg;
   __ LoadObject(kNullReg, NullObject());
 
-  // All of these must be distinct from TypeTestABI::kSubtypeTestCacheResultReg
-  // since it is used for kNullReg as well.
-  const Register kCacheArrayReg = RDI;
   const Register kScratchReg = TypeTestABI::kScratchReg;
-  const Register kInstanceCidOrFunction = R10;
-  const Register kInstanceInstantiatorTypeArgumentsReg = R13;
+
   // Only used for n >= 7, so set conditionally in that case to catch misuse.
   Register kInstanceParentFunctionTypeArgumentsReg = kNoRegister;
   Register kInstanceDelayedFunctionTypeArgumentsReg = kNoRegister;
@@ -2775,29 +2771,31 @@
 
   // We avoid a load-acquire barrier here by relying on the fact that all other
   // loads from the array are data-dependent loads.
-  __ movq(kCacheArrayReg,
+  __ movq(STCInternalRegs::kCacheEntryReg,
           FieldAddress(TypeTestABI::kSubtypeTestCacheReg,
                        target::SubtypeTestCache::cache_offset()));
-  __ addq(kCacheArrayReg,
+  __ addq(STCInternalRegs::kCacheEntryReg,
           Immediate(target::Array::data_offset() - kHeapObjectTag));
 
   Label loop, not_closure;
   if (n >= 5) {
-    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
+    __ LoadClassIdMayBeSmi(STCInternalRegs::kInstanceCidOrFunctionReg,
+                           TypeTestABI::kInstanceReg);
   } else {
-    __ LoadClassId(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
+    __ LoadClassId(STCInternalRegs::kInstanceCidOrFunctionReg,
+                   TypeTestABI::kInstanceReg);
   }
-  __ cmpq(kInstanceCidOrFunction, Immediate(kClosureCid));
+  __ cmpq(STCInternalRegs::kInstanceCidOrFunctionReg, Immediate(kClosureCid));
   __ j(NOT_EQUAL, &not_closure, Assembler::kNearJump);
 
   // Closure handling.
   {
-    __ movq(kInstanceCidOrFunction,
+    __ movq(STCInternalRegs::kInstanceCidOrFunctionReg,
             FieldAddress(TypeTestABI::kInstanceReg,
                          target::Closure::function_offset()));
     if (n >= 3) {
       __ movq(
-          kInstanceInstantiatorTypeArgumentsReg,
+          STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
           FieldAddress(TypeTestABI::kInstanceReg,
                        target::Closure::instantiator_type_arguments_offset()));
       if (n >= 7) {
@@ -2818,8 +2816,8 @@
     __ Bind(&not_closure);
     if (n >= 3) {
       Label has_no_type_arguments;
-      __ LoadClassById(kScratchReg, kInstanceCidOrFunction);
-      __ movq(kInstanceInstantiatorTypeArgumentsReg, kNullReg);
+      __ LoadClassById(kScratchReg, STCInternalRegs::kInstanceCidOrFunctionReg);
+      __ movq(STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg, kNullReg);
       __ movl(
           kScratchReg,
           FieldAddress(kScratchReg,
@@ -2827,7 +2825,7 @@
                            host_type_arguments_field_offset_in_words_offset()));
       __ cmpl(kScratchReg, Immediate(target::Class::kNoTypeArguments));
       __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
-      __ movq(kInstanceInstantiatorTypeArgumentsReg,
+      __ movq(STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
               FieldAddress(TypeTestABI::kInstanceReg, kScratchReg, TIMES_8, 0));
       __ Bind(&has_no_type_arguments);
 
@@ -2836,7 +2834,7 @@
         __ movq(kInstanceDelayedFunctionTypeArgumentsReg, kNullReg);
       }
     }
-    __ SmiTag(kInstanceCidOrFunction);
+    __ SmiTag(STCInternalRegs::kInstanceCidOrFunctionReg);
   }
 
   Label found, not_found, next_iteration;
@@ -2844,23 +2842,23 @@
   // Loop header.
   __ Bind(&loop);
   __ movq(kScratchReg,
-          Address(kCacheArrayReg,
+          Address(STCInternalRegs::kCacheEntryReg,
                   target::kWordSize *
                       target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmpq(kScratchReg, kNullReg);
   __ j(EQUAL, &not_found, Assembler::kNearJump);
-  __ cmpq(kScratchReg, kInstanceCidOrFunction);
+  __ cmpq(kScratchReg, STCInternalRegs::kInstanceCidOrFunctionReg);
   if (n == 1) {
     __ j(EQUAL, &found, Assembler::kNearJump);
   } else {
     __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
     __ cmpq(TypeTestABI::kDstTypeReg,
-            Address(kCacheArrayReg,
+            Address(STCInternalRegs::kCacheEntryReg,
                     target::kWordSize *
                         target::SubtypeTestCache::kDestinationType));
     __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
-    __ cmpq(kInstanceInstantiatorTypeArgumentsReg,
-            Address(kCacheArrayReg,
+    __ cmpq(STCInternalRegs::kInstanceInstantiatorTypeArgumentsReg,
+            Address(STCInternalRegs::kCacheEntryReg,
                     target::kWordSize *
                         target::SubtypeTestCache::kInstanceTypeArguments));
     if (n == 3) {
@@ -2869,12 +2867,12 @@
       __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
       __ cmpq(
           TypeTestABI::kInstantiatorTypeArgumentsReg,
-          Address(kCacheArrayReg,
+          Address(STCInternalRegs::kCacheEntryReg,
                   target::kWordSize *
                       target::SubtypeTestCache::kInstantiatorTypeArguments));
       __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
       __ cmpq(TypeTestABI::kFunctionTypeArgumentsReg,
-              Address(kCacheArrayReg,
+              Address(STCInternalRegs::kCacheEntryReg,
                       target::kWordSize *
                           target::SubtypeTestCache::kFunctionTypeArguments));
 
@@ -2885,13 +2883,13 @@
         __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
 
         __ cmpq(kInstanceParentFunctionTypeArgumentsReg,
-                Address(kCacheArrayReg,
+                Address(STCInternalRegs::kCacheEntryReg,
                         target::kWordSize *
                             target::SubtypeTestCache::
                                 kInstanceParentFunctionTypeArguments));
         __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
         __ cmpq(kInstanceDelayedFunctionTypeArgumentsReg,
-                Address(kCacheArrayReg,
+                Address(STCInternalRegs::kCacheEntryReg,
                         target::kWordSize *
                             target::SubtypeTestCache::
                                 kInstanceDelayedFunctionTypeArguments));
@@ -2901,14 +2899,14 @@
   }
 
   __ Bind(&next_iteration);
-  __ addq(kCacheArrayReg,
+  __ addq(STCInternalRegs::kCacheEntryReg,
           Immediate(target::kWordSize *
                     target::SubtypeTestCache::kTestEntryLength));
   __ jmp(&loop, Assembler::kNearJump);
 
   __ Bind(&found);
   __ movq(TypeTestABI::kSubtypeTestCacheResultReg,
-          Address(kCacheArrayReg,
+          Address(STCInternalRegs::kCacheEntryReg,
                   target::kWordSize * target::SubtypeTestCache::kTestResult));
 
   __ Bind(&not_found);
@@ -3569,9 +3567,9 @@
   /* R13: scratch register. */
   {
     Label size_tag_overflow, done;
-    __ cmpq(RDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+    __ cmpq(RDI, Immediate(target::UntaggedObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shlq(RDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+    __ shlq(RDI, Immediate(target::UntaggedObject::kTagBitsSizeTagPos -
                            target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done, Assembler::kNearJump);
 
diff --git a/runtime/vm/compiler/type_testing_stubs_arm.cc b/runtime/vm/compiler/type_testing_stubs_arm.cc
index ed1ace2..ccd9d36 100644
--- a/runtime/vm/compiler/type_testing_stubs_arm.cc
+++ b/runtime/vm/compiler/type_testing_stubs_arm.cc
@@ -20,16 +20,8 @@
     const Type& type,
     const Class& type_class) {
   BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class);
-  if (!compiler::IsSameObject(
-          compiler::NullObject(),
-          compiler::CastHandle<Object>(slow_type_test_stub))) {
-    __ GenerateUnRelocatedPcRelativeTailCall();
-    unresolved_calls->Add(new compiler::UnresolvedPcRelativeCall(
-        __ CodeSize(), slow_type_test_stub, /*is_tail_call=*/true));
-  } else {
-    __ Branch(compiler::Address(
-        THR, compiler::target::Thread::slow_type_test_entry_point_offset()));
-  }
+  __ Branch(compiler::Address(
+      THR, compiler::target::Thread::slow_type_test_entry_point_offset()));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/type_testing_stubs_arm64.cc b/runtime/vm/compiler/type_testing_stubs_arm64.cc
index 0540b01..850b198 100644
--- a/runtime/vm/compiler/type_testing_stubs_arm64.cc
+++ b/runtime/vm/compiler/type_testing_stubs_arm64.cc
@@ -20,19 +20,11 @@
     const Type& type,
     const Class& type_class) {
   BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class);
-  if (!compiler::IsSameObject(
-          compiler::NullObject(),
-          compiler::CastHandle<Object>(slow_type_test_stub))) {
-    __ GenerateUnRelocatedPcRelativeTailCall();
-    unresolved_calls->Add(new compiler::UnresolvedPcRelativeCall(
-        __ CodeSize(), slow_type_test_stub, /*is_tail_call=*/true));
-  } else {
-    __ ldr(TMP,
-           compiler::Address(
-               THR,
-               compiler::target::Thread::slow_type_test_entry_point_offset()));
-    __ br(TMP);
-  }
+  __ ldr(
+      TMP,
+      compiler::Address(
+          THR, compiler::target::Thread::slow_type_test_entry_point_offset()));
+  __ br(TMP);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/type_testing_stubs_x64.cc b/runtime/vm/compiler/type_testing_stubs_x64.cc
index f7a974c..7722cee 100644
--- a/runtime/vm/compiler/type_testing_stubs_x64.cc
+++ b/runtime/vm/compiler/type_testing_stubs_x64.cc
@@ -20,16 +20,8 @@
     const Type& type,
     const Class& type_class) {
   BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class);
-  if (!compiler::IsSameObject(
-          compiler::NullObject(),
-          compiler::CastHandle<Object>(slow_type_test_stub))) {
-    __ GenerateUnRelocatedPcRelativeTailCall();
-    unresolved_calls->Add(new compiler::UnresolvedPcRelativeCall(
-        __ CodeSize(), slow_type_test_stub, /*is_tail_call=*/true));
-  } else {
-    __ jmp(compiler::Address(
-        THR, compiler::target::Thread::slow_type_test_entry_point_offset()));
-  }
+  __ jmp(compiler::Address(
+      THR, compiler::target::Thread::slow_type_test_entry_point_offset()));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/write_barrier_elimination.cc b/runtime/vm/compiler/write_barrier_elimination.cc
index efc79e8..84b000f 100644
--- a/runtime/vm/compiler/write_barrier_elimination.cc
+++ b/runtime/vm/compiler/write_barrier_elimination.cc
@@ -351,9 +351,10 @@
 
 #define FOR_EACH_NATIVE_SLOT(class, underlying_type, field, __, ___)           \
   case Slot::Kind::k##class##_##field:                                         \
-    return std::is_base_of<InstanceLayout, underlying_type>::value ||          \
-           std::is_base_of<ContextLayout, underlying_type>::value ||           \
-           std::is_base_of<UnhandledExceptionLayout, underlying_type>::value;
+    return std::is_base_of<UntaggedInstance, underlying_type>::value ||        \
+           std::is_base_of<UntaggedContext, underlying_type>::value ||         \
+           std::is_base_of<UntaggedUnhandledException,                         \
+                           underlying_type>::value;
 
       NATIVE_SLOTS_LIST(FOR_EACH_NATIVE_SLOT)
 #undef FOR_EACH_NATIVE_SLOT
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index 1a5afc1..9dcd004 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -267,8 +267,9 @@
   EXPECT(val.IsInteger());
   EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
 
-  intptr_t initial_class_table_size =
-      Isolate::Current()->class_table()->NumCids();
+  auto class_table = IsolateGroup::Current()->class_table();
+
+  intptr_t initial_class_table_size = class_table->NumCids();
 
   val = Api::UnwrapHandle(
       TestCase::EvaluateExpression(lib, expression,
@@ -279,8 +280,7 @@
   EXPECT(val.IsInteger());
   EXPECT_EQ(7, Integer::Cast(val).AsInt64Value());
 
-  intptr_t final_class_table_size =
-      Isolate::Current()->class_table()->NumCids();
+  intptr_t final_class_table_size = class_table->NumCids();
   // Eval should not eat into this non-renewable resource.
   EXPECT_EQ(initial_class_table_size, final_class_table_size);
 }
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 5c2d42f..82ccda5 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -16,6 +16,20 @@
 
 namespace dart {
 
+// LR register should not be used directly in handwritten assembly patterns,
+// because it might contain return address. Instead use macross CLOBBERS_LR,
+// SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER,
+// RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR, SPILLS_LR_TO_FRAME,
+// RESTORES_LR_FROM_FRAME, READS_RETURN_ADDRESS_FROM_LR,
+// WRITES_RETURN_ADDRESS_TO_LR to get access to LR constant in a checked way.
+//
+// To prevent accidental use of LR constant we rename it to
+// LR_DO_NOT_USE_DIRECTLY (while keeping the code in this file and other files
+// which are permitted to access LR constant the same by defining LR as
+// LR_DO_NOT_USE_DIRECTLY). You can also use LINK_REGISTER if you need
+// to compare LR register code.
+#define LR LR_DO_NOT_USE_DIRECTLY
+
 // We support both VFPv3-D16 and VFPv3-D32 profiles, but currently only one at
 // a time.
 #if defined(__ARM_ARCH_7A__)
@@ -94,7 +108,7 @@
 #endif
   IP = R12,
   SP = R13,
-  LR = R14,
+  LR = R14,  // Note: direct access to this constant is not allowed. See above.
   PC = R15,
 };
 
@@ -289,7 +303,6 @@
 const Register DISPATCH_TABLE_REG = NOTFP;  // Dispatch table register.
 const Register SPREG = SP;                  // Stack pointer register.
 const Register FPREG = FP;                  // Frame pointer register.
-const Register LRREG = LR;                  // Link register.
 const Register ARGS_DESC_REG = R4;
 const Register CODE_REG = R6;
 const Register THR = R10;  // Caches current thread in generated code.
@@ -324,6 +337,24 @@
   static const Register kResultTypeReg = R0;
 };
 
+// Registers in addition to those listed in TypeTestABI used inside the
+// implementation of type testing stubs that are _not_ preserved.
+struct TTSInternalRegs {
+  static const Register kInstanceTypeArgumentsReg = R4;
+  static const Register kScratchReg = R9;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
+};
+
+// Registers in addition to those listed in TypeTestABI used inside the
+// implementation of subtype test cache stubs that are _not_ preserved.
+struct STCInternalRegs {
+  static const Register kInstanceCidOrFunctionReg = R9;
+
+  static const intptr_t kInternalRegisters = (1 << kInstanceCidOrFunctionReg);
+};
+
 // Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
 struct TypeTestABI {
   static const Register kInstanceReg = R0;
@@ -343,10 +374,17 @@
   static const intptr_t kSubtypeTestCacheStubCallerSavedRegisters =
       1 << kSubtypeTestCacheReg;
 
-  static const intptr_t kAbiRegisters =
+  static const intptr_t kPreservedAbiRegisters =
       (1 << kInstanceReg) | (1 << kDstTypeReg) |
-      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
-      (1 << kSubtypeTestCacheReg) | (1 << kScratchReg);
+      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg);
+
+  static const intptr_t kNonPreservedAbiRegisters =
+      TTSInternalRegs::kInternalRegisters |
+      STCInternalRegs::kInternalRegisters | (1 << kSubtypeTestCacheReg) |
+      (1 << kScratchReg) | (1 << kSubtypeTestCacheResultReg) | (1 << CODE_REG);
+
+  static const intptr_t kAbiRegisters =
+      kPreservedAbiRegisters | kNonPreservedAbiRegisters;
 };
 
 // Calling convention when calling AssertSubtypeStub.
@@ -366,15 +404,6 @@
   // (throws if the subtype check fails).
 };
 
-// Registers used inside the implementation of type testing stubs.
-struct TTSInternalRegs {
-  static const Register kInstanceTypeArgumentsReg = R4;
-  static const Register kScratchReg = R9;
-
-  static const intptr_t kInternalRegisters =
-      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
-};
-
 // ABI for InitStaticFieldStub.
 struct InitStaticFieldABI {
   static const Register kFieldReg = R0;
@@ -532,7 +561,7 @@
   // We choose these to avoid overlap between themselves and reserved registers.
   static constexpr Register kFirstNonArgumentRegister = R8;
   static constexpr Register kSecondNonArgumentRegister = R9;
-  static constexpr Register kFirstCalleeSavedCpuReg = R4;
+  static constexpr Register kFfiAnyNonAbiRegister = R4;
   static constexpr Register kStackPointerRegister = SPREG;
 
   COMPILE_ASSERT(
@@ -1035,6 +1064,22 @@
 constexpr uword kBreakInstructionFiller = 0xE1200070;   // bkpt #0
 constexpr uword kDataMemoryBarrier = 0xf57ff050 | 0xb;  // dmb ish
 
+struct LinkRegister {
+  const int32_t code = LR;
+};
+
+constexpr bool operator==(Register r, LinkRegister) {
+  return r == LR;
+}
+
+constexpr bool operator!=(Register r, LinkRegister lr) {
+  return !(r == lr);
+}
+
+#undef LR
+
+#define LINK_REGISTER (LinkRegister())
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_CONSTANTS_ARM_H_
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 5e94310..e44ab62 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -16,6 +16,20 @@
 
 namespace dart {
 
+// LR register should not be used directly in handwritten assembly patterns,
+// because it might contain return address. Instead use macross CLOBBERS_LR,
+// SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER,
+// RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR, SPILLS_LR_TO_FRAME,
+// RESTORES_LR_FROM_FRAME, READS_RETURN_ADDRESS_FROM_LR,
+// WRITES_RETURN_ADDRESS_TO_LR to get access to LR constant in a checked way.
+//
+// To prevent accidental use of LR constant we rename it to
+// LR_DO_NOT_USE_DIRECTLY (while keeping the code in this file and other files
+// which are permitted to access LR constant the same by defining LR as
+// LR_DO_NOT_USE_DIRECTLY). You can also use LINK_REGISTER if you need
+// to compare LR register code.
+#define LR LR_DO_NOT_USE_DIRECTLY
+
 enum Register {
   R0 = 0,
   R1 = 1,
@@ -51,6 +65,7 @@
   R31 = 31,  // ZR, CSP
   kNumberOfCpuRegisters = 32,
   kNoRegister = -1,
+  kNoRegister2 = -2,
 
   // These registers both use the encoding R31, but to avoid mistakes we give
   // them different values, and then translate before encoding.
@@ -62,7 +77,7 @@
   IP1 = R17,
   SP = R15,
   FP = R29,
-  LR = R30,
+  LR = R30,  // Note: direct access to this constant is not allowed. See above.
 };
 
 enum VRegister {
@@ -122,7 +137,6 @@
 const Register CODE_REG = R24;
 const Register FPREG = FP;          // Frame pointer register.
 const Register SPREG = R15;         // Stack pointer register.
-const Register LRREG = LR;          // Link register.
 const Register ARGS_DESC_REG = R4;  // Arguments descriptor register.
 const Register THR = R26;           // Caches current thread in generated code.
 const Register CALLEE_SAVED_TEMP = R19;
@@ -156,6 +170,31 @@
   static const Register kResultTypeReg = R0;
 };
 
+// Registers in addition to those listed in TypeTestABI used inside the
+// implementation of type testing stubs that are _not_ preserved.
+struct TTSInternalRegs {
+  static const Register kInstanceTypeArgumentsReg = R7;
+  static const Register kScratchReg = R9;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
+};
+
+// Registers in addition to those listed in TypeTestABI used inside the
+// implementation of subtype test cache stubs that are _not_ preserved.
+struct STCInternalRegs {
+  static const Register kInstanceCidOrFunctionReg = R6;
+  static const Register kInstanceInstantiatorTypeArgumentsReg = R5;
+  static const Register kInstanceParentFunctionTypeArgumentsReg = R9;
+  static const Register kInstanceDelayedFunctionTypeArgumentsReg = R10;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kInstanceCidOrFunctionReg) |
+      (1 << kInstanceInstantiatorTypeArgumentsReg) |
+      (1 << kInstanceParentFunctionTypeArgumentsReg) |
+      (1 << kInstanceDelayedFunctionTypeArgumentsReg);
+};
+
 // Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
 struct TypeTestABI {
   static const Register kInstanceReg = R0;
@@ -175,11 +214,17 @@
   static const intptr_t kSubtypeTestCacheStubCallerSavedRegisters =
       1 << kSubtypeTestCacheReg;
 
-  static const intptr_t kAbiRegisters =
+  static const intptr_t kPreservedAbiRegisters =
       (1 << kInstanceReg) | (1 << kDstTypeReg) |
-      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
-      (1 << kSubtypeTestCacheReg) | (1 << kScratchReg) |
-      (1 << kSubtypeTestCacheResultReg);
+      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg);
+
+  static const intptr_t kNonPreservedAbiRegisters =
+      TTSInternalRegs::kInternalRegisters |
+      STCInternalRegs::kInternalRegisters | (1 << kSubtypeTestCacheReg) |
+      (1 << kScratchReg) | (1 << kSubtypeTestCacheResultReg) | (1 << CODE_REG);
+
+  static const intptr_t kAbiRegisters =
+      kPreservedAbiRegisters | kNonPreservedAbiRegisters;
 };
 
 // Calling convention when calling AssertSubtypeStub.
@@ -199,15 +244,6 @@
   // (throws if the subtype check fails).
 };
 
-// Registers used inside the implementation of type testing stubs.
-struct TTSInternalRegs {
-  static const Register kInstanceTypeArgumentsReg = R7;
-  static const Register kScratchReg = R9;
-
-  static const intptr_t kInternalRegisters =
-      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
-};
-
 // ABI for InitStaticFieldStub.
 struct InitStaticFieldABI {
   static const Register kFieldReg = R0;
@@ -289,6 +325,8 @@
 const RegList kAbiArgumentCpuRegs =
     R(R0) | R(R1) | R(R2) | R(R3) | R(R4) | R(R5) | R(R6) | R(R7);
 #if defined(TARGET_OS_FUCHSIA)
+// We rely on R18 not bying touched by Dart generated assembly or stubs at all.
+// We rely on that any calls into C++ also preserve R18.
 const RegList kAbiPreservedCpuRegs = R(R18) | R(R19) | R(R20) | R(R21) |
                                      R(R22) | R(R23) | R(R24) | R(R25) |
                                      R(R26) | R(R27) | R(R28);
@@ -392,7 +430,7 @@
   static constexpr Register kSecondReturnReg = kNoRegister;
   static constexpr FpuRegister kReturnFpuReg = V0;
 
-  static constexpr Register kFirstCalleeSavedCpuReg = kAbiFirstPreservedCpuReg;
+  static constexpr Register kFfiAnyNonAbiRegister = R19;
   static constexpr Register kFirstNonArgumentRegister = R9;
   static constexpr Register kSecondNonArgumentRegister = R10;
   static constexpr Register kStackPointerRegister = SPREG;
@@ -1371,6 +1409,24 @@
 
 const uint64_t kBreakInstructionFiller = 0xD4200000D4200000L;  // brk #0; brk #0
 
+struct LinkRegister {};
+
+constexpr bool operator==(Register r, LinkRegister) {
+  return r == LR;
+}
+
+constexpr bool operator!=(Register r, LinkRegister lr) {
+  return !(r == lr);
+}
+
+inline Register ConcreteRegister(LinkRegister) {
+  return LR;
+}
+
+#undef LR
+
+#define LINK_REGISTER (LinkRegister())
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_CONSTANTS_ARM64_H_
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 8e47d4d..d5242f1 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -266,13 +266,22 @@
   static constexpr Register kSecondReturnReg = EDX;
   static constexpr Register kPointerToReturnStructRegisterReturn = kReturnReg;
 
+  // Whether the callee uses `ret 4` instead of `ret` to return with struct
+  // return values.
+  // See: https://c9x.me/x86/html/file_module_x86_id_280.html
+#if defined(_WIN32)
+  static const bool kUsesRet4 = false;
+#else
+  static const bool kUsesRet4 = true;
+#endif
+
   // Floating point values are returned on the "FPU stack" (in "ST" registers).
   // However, we use XMM0 in our compiler pipeline as the location.
   // The move from and to ST is done in FfiCallInstr::EmitNativeCode and
   // NativeReturnInstr::EmitNativeCode.
   static constexpr XmmRegister kReturnFpuReg = XMM0;
 
-  static constexpr Register kFirstCalleeSavedCpuReg = EBX;
+  static constexpr Register kFfiAnyNonAbiRegister = EBX;
   static constexpr Register kFirstNonArgumentRegister = EAX;
   static constexpr Register kSecondNonArgumentRegister = ECX;
   static constexpr Register kStackPointerRegister = SPREG;
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 480f565..8ebeb8e 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -146,6 +146,28 @@
   static const Register kResultTypeReg = RAX;
 };
 
+// Registers in addition to those listed in TypeTestABI used inside the
+// implementation of type testing stubs that are _not_ preserved.
+struct TTSInternalRegs {
+  static const Register kInstanceTypeArgumentsReg = RSI;
+  static const Register kScratchReg = R8;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
+};
+
+// Registers in addition to those listed in TypeTestABI used inside the
+// implementation of subtype test cache stubs that are _not_ preserved.
+struct STCInternalRegs {
+  static const Register kCacheEntryReg = RDI;
+  static const Register kInstanceCidOrFunctionReg = R10;
+  static const Register kInstanceInstantiatorTypeArgumentsReg = R13;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kCacheEntryReg) | (1 << kInstanceCidOrFunctionReg) |
+      (1 << kInstanceInstantiatorTypeArgumentsReg);
+};
+
 // Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
 struct TypeTestABI {
   static const Register kInstanceReg = RAX;
@@ -164,11 +186,17 @@
   // No registers need saving across SubtypeTestCacheStub calls.
   static const intptr_t kSubtypeTestCacheStubCallerSavedRegisters = 0;
 
-  static const intptr_t kAbiRegisters =
+  static const intptr_t kPreservedAbiRegisters =
       (1 << kInstanceReg) | (1 << kDstTypeReg) |
-      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
-      (1 << kSubtypeTestCacheReg) | (1 << kScratchReg) |
-      (1 << kSubtypeTestCacheResultReg);
+      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg);
+
+  static const intptr_t kNonPreservedAbiRegisters =
+      TTSInternalRegs::kInternalRegisters |
+      STCInternalRegs::kInternalRegisters | (1 << kSubtypeTestCacheReg) |
+      (1 << kScratchReg) | (1 << kSubtypeTestCacheResultReg) | (1 << CODE_REG);
+
+  static const intptr_t kAbiRegisters =
+      kPreservedAbiRegisters | kNonPreservedAbiRegisters;
 };
 
 // Calling convention when calling AssertSubtypeStub.
@@ -247,18 +275,6 @@
   static const Register kResultReg = RAX;
 };
 
-// Registers used inside the implementation of type testing stubs.
-struct TTSInternalRegs {
-  static const Register kInstanceTypeArgumentsReg = RSI;
-  static const Register kScratchReg = R8;
-
-  static const intptr_t kInternalRegisters =
-      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
-};
-
-// TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
-// of reusing the constants of the instantiation stubs ABI.
-
 typedef uint32_t RegList;
 const RegList kAllCpuRegistersList = 0xFFFF;
 const RegList kAllFpuRegistersList = 0xFFFF;
@@ -445,12 +461,12 @@
 
   COMPILE_ASSERT((kArgumentRegisters & kReservedCpuRegisters) == 0);
 
-  static constexpr Register kFirstCalleeSavedCpuReg = RBX;
+  static constexpr Register kFfiAnyNonAbiRegister = R12;
   static constexpr Register kFirstNonArgumentRegister = RAX;
   static constexpr Register kSecondNonArgumentRegister = RBX;
   static constexpr Register kStackPointerRegister = SPREG;
 
-  COMPILE_ASSERT(((R(kFirstCalleeSavedCpuReg)) & kCalleeSaveCpuRegisters) != 0);
+  COMPILE_ASSERT(((R(kFfiAnyNonAbiRegister)) & kCalleeSaveCpuRegisters) != 0);
 
   COMPILE_ASSERT(
       ((R(kFirstNonArgumentRegister) | R(kSecondNonArgumentRegister)) &
diff --git a/runtime/vm/cpu_arm64.cc b/runtime/vm/cpu_arm64.cc
index 0d6b8b3..df0f48b 100644
--- a/runtime/vm/cpu_arm64.cc
+++ b/runtime/vm/cpu_arm64.cc
@@ -20,7 +20,7 @@
 #include <unistd.h>
 #endif
 
-#if defined(HOST_OS_IOS)
+#if defined(HOST_OS_MACOS) || defined(HOST_OS_IOS)
 #include <libkern/OSCacheControl.h>
 #endif
 
@@ -42,7 +42,7 @@
 // On iOS we use sys_icache_invalidate from Darwin. See:
 //
 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html
-#if defined(HOST_OS_IOS)
+#if defined(HOST_OS_MACOS) || defined(HOST_OS_IOS)
   sys_icache_invalidate(reinterpret_cast<void*>(start), size);
 #elif defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
   extern void __clear_cache(char*, char*);
@@ -54,7 +54,7 @@
                                       size, ZX_CACHE_FLUSH_INSN);
   ASSERT(result == ZX_OK);
 #else
-#error FlushICache only tested/supported on Android, Fuchsia, Linux and iOS
+#error FlushICache not implemented for this OS
 #endif
 
 #endif
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 9f63a72..44237ab4 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -220,7 +220,7 @@
     return Utils::StrDup("--causal-async-stacks is deprecated!");
   }
 
-  FrameLayout::Init();
+  UntaggedFrame::Init();
 
   set_thread_exit_callback(thread_exit);
   SetFileCallbacks(file_open, file_read, file_write, file_close);
@@ -278,7 +278,7 @@
         instructions_snapshot, nullptr, -1, api_flags));
     // ObjectStore should be created later, after null objects are initialized.
     auto group = new IsolateGroup(std::move(source), /*embedder_data=*/nullptr,
-                                  /*object_store=*/nullptr);
+                                  /*object_store=*/nullptr, api_flags);
     group->CreateHeap(/*is_vm_isolate=*/true,
                       /*is_service_or_kernel_isolate=*/false);
     IsolateGroup::RegisterIsolateGroup(group);
@@ -294,13 +294,13 @@
     ASSERT(T != NULL);
     StackZone zone(T);
     HandleScope handle_scope(T);
-    Object::InitNullAndBool(vm_isolate_);
+    Object::InitNullAndBool(vm_isolate_->group());
     vm_isolate_->set_object_store(new ObjectStore());
     vm_isolate_->isolate_object_store()->Init();
     vm_isolate_->isolate_group_->object_store_ =
         vm_isolate_->object_store_shared_ptr_;
     TargetCPUFeatures::Init();
-    Object::Init(vm_isolate_);
+    Object::Init(vm_isolate_->group());
     ArgumentsDescriptor::Init();
     ICData::Init();
     SubtypeTestCache::Init();
@@ -326,7 +326,7 @@
             "Precompiled runtime requires a precompiled snapshot");
 #else
         StubCode::Init();
-        Object::FinishInit(vm_isolate_);
+        Object::FinishInit(vm_isolate_->group());
         // MallocHooks can't be initialized until StubCode has been since stack
         // trace generation relies on stub methods that are generated in
         // StubCode::Init().
@@ -345,24 +345,24 @@
         return Utils::StrDup(error.ToErrorCString());
       }
 
-      Object::FinishInit(vm_isolate_);
+      Object::FinishInit(vm_isolate_->group());
 #if defined(SUPPORT_TIMELINE)
       if (tbes.enabled()) {
         tbes.SetNumArguments(2);
         tbes.FormatArgument(0, "snapshotSize", "%" Pd, snapshot->length());
         tbes.FormatArgument(
             1, "heapSize", "%" Pd64,
-            vm_isolate_->heap()->UsedInWords(Heap::kOld) * kWordSize);
+            vm_isolate_group()->heap()->UsedInWords(Heap::kOld) * kWordSize);
       }
 #endif  // !defined(PRODUCT)
       if (FLAG_trace_isolates) {
         OS::PrintErr("Size of vm isolate snapshot = %" Pd "\n",
                      snapshot->length());
-        vm_isolate_->heap()->PrintSizes();
+        vm_isolate_group()->heap()->PrintSizes();
         MegamorphicCacheTable::PrintSizes(vm_isolate_);
         intptr_t size;
         intptr_t capacity;
-        Symbols::GetStats(vm_isolate_, &size, &capacity);
+        Symbols::GetStats(vm_isolate_->group(), &size, &capacity);
         OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
         OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
       }
@@ -373,7 +373,7 @@
 #else
       vm_snapshot_kind_ = Snapshot::kNone;
       StubCode::Init();
-      Object::FinishInit(vm_isolate_);
+      Object::FinishInit(vm_isolate_->group());
       // MallocHooks can't be initialized until StubCode has been since stack
       // trace generation relies on stub methods that are generated in
       // StubCode::Init().
@@ -381,7 +381,7 @@
       // initialization for the actual malloc hooks to increase accuracy of
       // memory consumption statistics.
       MallocHooks::Init();
-      Symbols::Init(vm_isolate_);
+      Symbols::Init(vm_isolate_->group());
 #endif
     }
     // We need to initialize the constants here for the vm isolate thread due to
@@ -397,10 +397,10 @@
 #if defined(SUPPORT_TIMELINE)
       TimelineBeginEndScope tbes(Timeline::GetVMStream(), "FinalizeVMIsolate");
 #endif
-      Object::FinalizeVMIsolate(vm_isolate_);
+      Object::FinalizeVMIsolate(vm_isolate_->group());
     }
 #if defined(DEBUG)
-    vm_isolate_->heap()->Verify(kRequireMarked);
+    vm_isolate_group()->heap()->Verify(kRequireMarked);
 #endif
   }
   // Allocate the "persistent" scoped handles for the predefined API
@@ -687,32 +687,22 @@
   return isolate;
 }
 
-#if defined(DART_PRECOMPILED_RUNTIME)
-static bool CloneIntoChildIsolateAOT(Thread* T,
-                                     Isolate* I,
-                                     IsolateGroup* source_isolate_group) {
-  // In AOT we speed up isolate spawning by copying donor's isolate structure.
-  if (source_isolate_group == nullptr) {
-    return false;
-  }
-  I->isolate_object_store()->Init();
-  I->isolate_object_store()->PreallocateObjects();
-  I->set_field_table(T, source_isolate_group->initial_field_table()->Clone(I));
-
-  return true;
-}
-#endif
-
 ErrorPtr Dart::InitIsolateFromSnapshot(Thread* T,
                                        Isolate* I,
                                        const uint8_t* snapshot_data,
                                        const uint8_t* snapshot_instructions,
                                        const uint8_t* kernel_buffer,
                                        intptr_t kernel_buffer_size) {
+  auto IG = I->group();
+  if (kernel_buffer != nullptr) {
+    SafepointReadRwLocker reader(T, IG->program_lock());
+    I->field_table()->MarkReadyToUse();
+  }
+
   Error& error = Error::Handle(T->zone());
-  error = Object::Init(I, kernel_buffer, kernel_buffer_size);
+  error = Object::Init(IG, kernel_buffer, kernel_buffer_size);
   if (!error.IsNull()) {
-    return error.raw();
+    return error.ptr();
   }
   if ((snapshot_data != NULL) && kernel_buffer == NULL) {
     // Read the snapshot and setup the initial state.
@@ -739,21 +729,25 @@
     FullSnapshotReader reader(snapshot, snapshot_instructions, T);
     const Error& error = Error::Handle(reader.ReadProgramSnapshot());
     if (!error.IsNull()) {
-      return error.raw();
+      return error.ptr();
     }
 
-    I->set_field_table(T, I->group()->initial_field_table()->Clone(I));
+    {
+      SafepointReadRwLocker reader(T, IG->program_lock());
+      I->set_field_table(T, IG->initial_field_table()->Clone(I));
+      I->field_table()->MarkReadyToUse();
+    }
 
 #if defined(SUPPORT_TIMELINE)
     if (tbes.enabled()) {
       tbes.SetNumArguments(2);
       tbes.FormatArgument(0, "snapshotSize", "%" Pd, snapshot->length());
       tbes.FormatArgument(1, "heapSize", "%" Pd64,
-                          I->heap()->UsedInWords(Heap::kOld) * kWordSize);
+                          IG->heap()->UsedInWords(Heap::kOld) * kWordSize);
     }
 #endif  // defined(SUPPORT_TIMELINE)
     if (FLAG_trace_isolates) {
-      I->heap()->PrintSizes();
+      IG->heap()->PrintSizes();
       MegamorphicCacheTable::PrintSizes(I);
     }
   } else {
@@ -823,8 +817,8 @@
   StackZone printing_zone(T);
   HandleScope printing_scope(T);
   TextBuffer b(1000);
-  const auto& constants =
-      GrowableObjectArray::Handle(I->object_store()->llvm_constant_pool());
+  const auto& constants = GrowableObjectArray::Handle(
+      I->group()->object_store()->llvm_constant_pool());
   if (constants.IsNull()) {
     b.AddString("No constant pool information in snapshot.\n\n");
   } else {
@@ -845,8 +839,8 @@
     }
     b.AddString("End of constant pool.\n\n");
   }
-  const auto& functions =
-      GrowableObjectArray::Handle(I->object_store()->llvm_function_pool());
+  const auto& functions = GrowableObjectArray::Handle(
+      I->group()->object_store()->llvm_function_pool());
   if (functions.IsNull()) {
     b.AddString("No function pool information in snapshot.\n\n");
   } else {
@@ -873,6 +867,7 @@
   // Initialize the new isolate.
   Thread* T = Thread::Current();
   Isolate* I = T->isolate();
+  auto IG = T->isolate_group();
 #if defined(SUPPORT_TIMELINE)
   TimelineBeginEndScope tbes(T, Timeline::GetIsolateStream(),
                              "InitializeIsolate");
@@ -883,58 +878,84 @@
   StackZone zone(T);
   HandleScope handle_scope(T);
   bool was_child_cloned_into_existing_isolate = false;
-#if defined(DART_PRECOMPILED_RUNTIME)
-  if (CloneIntoChildIsolateAOT(T, I, source_isolate_group)) {
+  if (source_isolate_group != nullptr) {
+    I->isolate_object_store()->Init();
+    I->isolate_object_store()->PreallocateObjects();
+
+    // If a static field gets registered in [IsolateGroup::RegisterStaticField]:
+    //
+    //   * before this block it will ignore this isolate. The [Clone] of the
+    //     initial field table will pick up the new value.
+    //   * after this block it will add the new static field to this isolate.
+    {
+      SafepointReadRwLocker reader(T, source_isolate_group->program_lock());
+      I->set_field_table(T,
+                         source_isolate_group->initial_field_table()->Clone(I));
+      I->field_table()->MarkReadyToUse();
+    }
+
     was_child_cloned_into_existing_isolate = true;
   } else {
-#endif
     const Error& error = Error::Handle(
         InitIsolateFromSnapshot(T, I, snapshot_data, snapshot_instructions,
                                 kernel_buffer, kernel_buffer_size));
     if (!error.IsNull()) {
-      return error.raw();
+      return error.ptr();
     }
-#if defined(DART_PRECOMPILED_RUNTIME)
   }
-#endif
 
   Object::VerifyBuiltinVtables();
-  DEBUG_ONLY(I->heap()->Verify(kForbidMarked));
+  DEBUG_ONLY(IG->heap()->Verify(kForbidMarked));
 
 #if defined(DART_PRECOMPILED_RUNTIME)
-  ASSERT(I->object_store()->build_method_extractor_code() != Code::null());
-  if (FLAG_print_llvm_constant_pool) {
-    PrintLLVMConstantPool(T, I);
-  }
+  const bool kIsAotRuntime = true;
 #else
-#if !defined(TARGET_ARCH_IA32)
-  if (I != Dart::vm_isolate()) {
-    I->object_store()->set_build_method_extractor_code(
-        Code::Handle(StubCode::GetBuildMethodExtractorStub(nullptr)));
-  }
+  const bool kIsAotRuntime = false;
 #endif
+
+  if (kIsAotRuntime || was_child_cloned_into_existing_isolate) {
+#if !defined(TARGET_ARCH_IA32)
+    ASSERT(IG->object_store()->build_method_extractor_code() != Code::null());
+#endif
+#if defined(DART_PRECOMPILED_RUNTIME)
+    if (FLAG_print_llvm_constant_pool) {
+      PrintLLVMConstantPool(T, I);
+    }
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
+  } else {
+#if !defined(TARGET_ARCH_IA32)
+    if (I != Dart::vm_isolate()) {
+      if (IG->object_store()->build_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)));
+        }
+      }
+    }
+#endif  // !defined(TARGET_ARCH_IA32)
+  }
 
   I->set_ic_miss_code(StubCode::SwitchableCallMiss());
 
   if ((snapshot_data == NULL) || (kernel_buffer != NULL)) {
     Error& error = Error::Handle();
-    error ^= I->object_store()->PreallocateObjects();
+    error ^= IG->object_store()->PreallocateObjects();
     if (!error.IsNull()) {
-      return error.raw();
+      return error.ptr();
     }
     error ^= I->isolate_object_store()->PreallocateObjects();
     if (!error.IsNull()) {
-      return error.raw();
+      return error.ptr();
     }
   }
 
   if (!was_child_cloned_into_existing_isolate) {
-    I->heap()->InitGrowthControl();
+    IG->heap()->InitGrowthControl();
   }
   I->set_init_callback_data(isolate_data);
   if (FLAG_print_class_table) {
-    I->class_table()->Print();
+    IG->class_table()->Print();
   }
 #if !defined(PRODUCT)
   ServiceIsolate::MaybeMakeServiceIsolate(I);
@@ -967,6 +988,8 @@
 const char* Dart::FeaturesString(Isolate* isolate,
                                  bool is_vm_isolate,
                                  Snapshot::Kind kind) {
+  auto isolate_group = isolate != nullptr ? isolate->group() : nullptr;
+
   TextBuffer buffer(64);
 
 // Different fields are included for DEBUG/RELEASE/PRODUCT.
@@ -987,21 +1010,22 @@
 #define ADD_C(name, PCV, PV, T, DV, C) ADD_FLAG(name, FLAG_##name)
 #define ADD_D(name, T, DV, C) ADD_FLAG(name, FLAG_##name)
 
-#define ADD_ISOLATE_FLAG(name, isolate_flag, flag)                             \
+#define ADD_ISOLATE_GROUP_FLAG(name, isolate_flag, flag)                       \
   do {                                                                         \
-    const bool value = (isolate != NULL) ? isolate->name() : flag;             \
+    const bool value =                                                         \
+        isolate_group != nullptr ? isolate_group->name() : flag;               \
     ADD_FLAG(#name, value);                                                    \
   } while (0);
 
   if (Snapshot::IncludesCode(kind)) {
     VM_GLOBAL_FLAG_LIST(ADD_P, ADD_R, ADD_C, ADD_D);
 
-    // enabling assertions affects deopt ids.
-    ADD_ISOLATE_FLAG(asserts, enable_asserts, FLAG_enable_asserts);
+    // Enabling assertions affects deopt ids.
+    ADD_ISOLATE_GROUP_FLAG(asserts, enable_asserts, FLAG_enable_asserts);
     if (kind == Snapshot::kFullJIT) {
-      ADD_ISOLATE_FLAG(use_field_guards, use_field_guards,
-                       FLAG_use_field_guards);
-      ADD_ISOLATE_FLAG(use_osr, use_osr, FLAG_use_osr);
+      ADD_ISOLATE_GROUP_FLAG(use_field_guards, use_field_guards,
+                             FLAG_use_field_guards);
+      ADD_ISOLATE_GROUP_FLAG(use_osr, use_osr, FLAG_use_osr);
     }
 #if !defined(PRODUCT)
     buffer.AddString(FLAG_code_comments ? " code-comments"
@@ -1039,8 +1063,8 @@
   }
 
   if (!Snapshot::IsAgnosticToNullSafety(kind)) {
-    if (isolate != NULL) {
-      if (isolate->null_safety()) {
+    if (isolate_group != nullptr) {
+      if (isolate_group->null_safety()) {
         buffer.AddString(" null-safety");
       } else {
         buffer.AddString(" no-null-safety");
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 27ad70d..b7406c1 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -81,6 +81,7 @@
   static void ShutdownIsolate();
 
   static Isolate* vm_isolate() { return vm_isolate_; }
+  static IsolateGroup* vm_isolate_group() { return vm_isolate_->group(); }
   static ThreadPool* thread_pool() { return thread_pool_; }
   static bool VmIsolateNameEquals(const char* name);
 
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 2071a31..1cc6888 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -119,11 +119,6 @@
     if (obj->IsFunction()) {
       funcHandle_ ^= obj;
       classHandle_ ^= funcHandle_.Owner();
-      // Signature functions get created, but not canonicalized, when function
-      // types get instantiated during run time type tests.
-      if (funcHandle_.IsSignatureFunction()) {
-        return;
-      }
       // Verify that the result type of a function is canonical or a
       // TypeParameter.
       typeHandle_ ^= funcHandle_.result_type();
@@ -147,7 +142,7 @@
 
 static InstancePtr GetListInstance(Zone* zone, const Object& obj) {
   if (obj.IsInstance()) {
-    ObjectStore* object_store = Isolate::Current()->object_store();
+    ObjectStore* object_store = IsolateGroup::Current()->object_store();
     const Type& list_rare_type =
         Type::Handle(zone, object_store->non_nullable_list_rare_type());
     ASSERT(!list_rare_type.IsNull());
@@ -156,7 +151,7 @@
     if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
                            Nullability::kNonNullable, list_rare_type,
                            Heap::kNew)) {
-      return instance.raw();
+      return instance.ptr();
     }
   }
   return Instance::null();
@@ -164,7 +159,7 @@
 
 static InstancePtr GetMapInstance(Zone* zone, const Object& obj) {
   if (obj.IsInstance()) {
-    ObjectStore* object_store = Isolate::Current()->object_store();
+    ObjectStore* object_store = IsolateGroup::Current()->object_store();
     const Type& map_rare_type =
         Type::Handle(zone, object_store->non_nullable_map_rare_type());
     ASSERT(!map_rare_type.IsNull());
@@ -173,7 +168,7 @@
     if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
                            Nullability::kNonNullable, map_rare_type,
                            Heap::kNew)) {
-      return instance.raw();
+      return instance.ptr();
     }
   }
   return Instance::null();
@@ -185,9 +180,9 @@
   // compiletime_error_class was removed.
   return false;
 #else
-  Isolate* I = Thread::Current()->isolate();
-  const Class& error_class =
-      Class::Handle(zone, I->object_store()->compiletime_error_class());
+  auto isolate_group = Thread::Current()->isolate_group();
+  const Class& error_class = Class::Handle(
+      zone, isolate_group->object_store()->compiletime_error_class());
   ASSERT(!error_class.IsNull());
   return (obj.GetClassId() == error_class.id());
 #endif
@@ -210,7 +205,7 @@
   obj = arguments->NativeArgAt(arg_index);
   if (IsStringClassId(obj.GetClassId())) {
     ASSERT(thread->api_top_scope() != NULL);
-    *str = Api::NewHandle(thread, obj.raw());
+    *str = Api::NewHandle(thread, obj.ptr());
     return true;
   }
   if (obj.IsNull()) {
@@ -336,7 +331,7 @@
   LocalHandles* local_handles = Api::TopScope(thread)->local_handles();
   ASSERT(local_handles != NULL);
   LocalHandle* ref = local_handles->AllocateHandle();
-  ref->set_raw(raw);
+  ref->set_ptr(raw);
   return ref->apiHandle();
 }
 
@@ -344,10 +339,10 @@
   if (raw == Object::null()) {
     return Null();
   }
-  if (raw == Bool::True().raw()) {
+  if (raw == Bool::True().ptr()) {
     return True();
   }
-  if (raw == Bool::False().raw()) {
+  if (raw == Bool::False().ptr()) {
     return False();
   }
   ASSERT(thread->execution_state() == Thread::kThreadInVM);
@@ -364,10 +359,10 @@
          thread->isolate()->group()->api_state()->IsActivePersistentHandle(
              reinterpret_cast<Dart_PersistentHandle>(object)) ||
          Dart::IsReadOnlyApiHandle(object));
-  ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
-         PersistentHandle::raw_offset() == 0 && LocalHandle::raw_offset() == 0);
+  ASSERT(FinalizablePersistentHandle::ptr_offset() == 0 &&
+         PersistentHandle::ptr_offset() == 0 && LocalHandle::ptr_offset() == 0);
 #endif
-  return (reinterpret_cast<LocalHandle*>(object))->raw();
+  return (reinterpret_cast<LocalHandle*>(object))->ptr();
 }
 
 #define DEFINE_UNWRAP(type)                                                    \
@@ -465,7 +460,7 @@
   if (!error.IsError()) {
     error = UnhandledException::New(Instance::Cast(error), Instance::Handle());
   }
-  return Api::NewHandle(T, error.raw());
+  return Api::NewHandle(T, error.ptr());
 }
 
 Dart_Handle Api::AcquiredError(IsolateGroup* isolate_group) {
@@ -507,9 +502,9 @@
 }
 
 static Dart_Handle InitNewReadOnlyApiHandle(ObjectPtr raw) {
-  ASSERT(raw->ptr()->InVMIsolateHeap());
+  ASSERT(raw->untag()->InVMIsolateHeap());
   LocalHandle* ref = Dart::AllocateReadOnlyApiHandle();
-  ref->set_raw(raw);
+  ref->set_ptr(raw);
   return ref->apiHandle();
 }
 
@@ -521,16 +516,16 @@
   ASSERT(state != NULL);
 
   ASSERT(true_handle_ == NULL);
-  true_handle_ = InitNewReadOnlyApiHandle(Bool::True().raw());
+  true_handle_ = InitNewReadOnlyApiHandle(Bool::True().ptr());
 
   ASSERT(false_handle_ == NULL);
-  false_handle_ = InitNewReadOnlyApiHandle(Bool::False().raw());
+  false_handle_ = InitNewReadOnlyApiHandle(Bool::False().ptr());
 
   ASSERT(null_handle_ == NULL);
   null_handle_ = InitNewReadOnlyApiHandle(Object::null());
 
   ASSERT(empty_string_handle_ == NULL);
-  empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().raw());
+  empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().ptr());
 }
 
 void Api::Cleanup() {
@@ -552,18 +547,18 @@
   if (cid == kExternalOneByteStringCid) {
     ExternalOneByteStringPtr raw_string =
         static_cast<ExternalOneByteStringPtr>(raw_obj);
-    *peer = raw_string->ptr()->peer_;
+    *peer = raw_string->untag()->peer_;
     return true;
   }
   if (cid == kOneByteStringCid || cid == kTwoByteStringCid) {
-    Isolate* isolate = arguments->thread()->isolate();
-    *peer = isolate->heap()->GetPeer(raw_obj);
+    auto isolate_group = arguments->thread()->isolate_group();
+    *peer = isolate_group->heap()->GetPeer(raw_obj);
     return (*peer != 0);
   }
   if (cid == kExternalTwoByteStringCid) {
     ExternalTwoByteStringPtr raw_string =
         static_cast<ExternalTwoByteStringPtr>(raw_obj);
-    *peer = raw_string->ptr()->peer_;
+    *peer = raw_string->untag()->peer_;
     return true;
   }
   return false;
@@ -577,11 +572,11 @@
     if (cid >= kNumPredefinedCids) {
       ASSERT(Instance::Cast(Object::Handle(raw_obj)).IsValidNativeIndex(0));
       TypedDataPtr native_fields = *reinterpret_cast<TypedDataPtr*>(
-          ObjectLayout::ToAddr(raw_obj) + sizeof(ObjectLayout));
+          UntaggedObject::ToAddr(raw_obj) + sizeof(UntaggedObject));
       if (native_fields == TypedData::null()) {
         *value = 0;
       } else {
-        *value = *bit_cast<intptr_t*, uint8_t*>(native_fields->ptr()->data());
+        *value = *bit_cast<intptr_t*, uint8_t*>(native_fields->untag()->data());
       }
       return true;
     }
@@ -597,7 +592,7 @@
   if (raw_obj->IsHeapObject()) {
     intptr_t cid = raw_obj->GetClassId();
     if (cid == kBoolCid) {
-      *value = (raw_obj == Object::bool_true().raw());
+      *value = (raw_obj == Object::bool_true().ptr());
       return true;
     }
     if (cid == kNullCid) {
@@ -616,7 +611,7 @@
   if (raw_obj->IsHeapObject()) {
     intptr_t cid = raw_obj->GetClassId();
     if (cid == kMintCid) {
-      *value = static_cast<MintPtr>(raw_obj)->ptr()->value_;
+      *value = static_cast<MintPtr>(raw_obj)->untag()->value_;
       return true;
     }
     return false;
@@ -633,12 +628,12 @@
   if (raw_obj->IsHeapObject()) {
     intptr_t cid = raw_obj->GetClassId();
     if (cid == kDoubleCid) {
-      *value = static_cast<DoublePtr>(raw_obj)->ptr()->value_;
+      *value = static_cast<DoublePtr>(raw_obj)->untag()->value_;
       return true;
     }
     if (cid == kMintCid) {
       *value =
-          static_cast<double>(static_cast<MintPtr>(raw_obj)->ptr()->value_);
+          static_cast<double>(static_cast<MintPtr>(raw_obj)->untag()->value_);
       return true;
     }
     return false;
@@ -655,32 +650,32 @@
   ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
   intptr_t cid = raw_obj->GetClassIdMayBeSmi();
   int class_num_fields = arguments->thread()
-                             ->isolate()
+                             ->isolate_group()
                              ->class_table()
                              ->At(cid)
-                             ->ptr()
+                             ->untag()
                              ->num_native_fields_;
   if (num_fields != class_num_fields) {
     // No native fields or mismatched native field count.
     return false;
   }
   TypedDataPtr native_fields = *reinterpret_cast<TypedDataPtr*>(
-      ObjectLayout::ToAddr(raw_obj) + sizeof(ObjectLayout));
+      UntaggedObject::ToAddr(raw_obj) + sizeof(UntaggedObject));
   if (native_fields == TypedData::null()) {
     // Native fields not initialized.
     memset(field_values, 0, (num_fields * sizeof(field_values[0])));
     return true;
   }
-  ASSERT(class_num_fields == Smi::Value(native_fields->ptr()->length()));
+  ASSERT(class_num_fields == Smi::Value(native_fields->untag()->length()));
   intptr_t* native_values =
-      reinterpret_cast<intptr_t*>(native_fields->ptr()->data());
+      reinterpret_cast<intptr_t*>(native_fields->untag()->data());
   memmove(field_values, native_values, (num_fields * sizeof(field_values[0])));
   return true;
 }
 
 void Api::SetWeakHandleReturnValue(NativeArguments* args,
                                    Dart_WeakPersistentHandle retval) {
-  args->SetReturnUnsafe(FinalizablePersistentHandle::Cast(retval)->raw());
+  args->SetReturnUnsafe(FinalizablePersistentHandle::Cast(retval)->ptr());
 }
 
 PersistentHandle* PersistentHandle::Cast(Dart_PersistentHandle handle) {
@@ -708,7 +703,7 @@
 void FinalizablePersistentHandle::Finalize(
     IsolateGroup* isolate_group,
     FinalizablePersistentHandle* handle) {
-  if (!handle->raw()->IsHeapObject()) {
+  if (!handle->ptr()->IsHeapObject()) {
     return;  // Free handle.
   }
   Dart_HandleFinalizer callback = handle->callback();
@@ -840,7 +835,7 @@
     const Object& excp = Object::Handle(Z, Api::UnwrapHandle(exception));
     obj = String::New(GetErrorString(T, excp));
   } else {
-    obj = Api::UnwrapInstanceHandle(Z, exception).raw();
+    obj = Api::UnwrapInstanceHandle(Z, exception).ptr();
     if (obj.IsNull()) {
       RETURN_TYPE_ERROR(Z, exception, Instance);
     }
@@ -873,7 +868,7 @@
     // that GC won't touch the raw error object before creating a valid
     // handle for it in the surviving zone.
     NoSafepointScope no_safepoint;
-    ErrorPtr raw_error = Api::UnwrapErrorHandle(thread->zone(), handle).raw();
+    ErrorPtr raw_error = Api::UnwrapErrorHandle(thread->zone(), handle).ptr();
     thread->UnwindScopes(thread->top_exit_frame_info());
     // Note that thread's zone is different here than at the beginning of this
     // function.
@@ -887,7 +882,7 @@
   DARTSCOPE(Thread::Current());
   const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
   if (obj.IsString()) {
-    return Api::NewHandle(T, obj.raw());
+    return Api::NewHandle(T, obj.ptr());
   } else if (obj.IsInstance()) {
     CHECK_CALLBACK_STATE(T);
     const Instance& receiver = Instance::Cast(obj);
@@ -925,7 +920,7 @@
   TransitionNativeToVM transition(thread);
   NoSafepointScope no_safepoint_scope;
   PersistentHandle* ref = PersistentHandle::Cast(object);
-  return Api::NewHandle(thread, ref->raw());
+  return Api::NewHandle(thread, ref->ptr());
 }
 
 DART_EXPORT Dart_Handle
@@ -942,7 +937,7 @@
   if (weak_ref->IsFinalizedNotFreed()) {
     return Dart_Null();
   }
-  return Api::NewHandle(thread, weak_ref->raw());
+  return Api::NewHandle(thread, weak_ref->ptr());
 }
 
 static Dart_Handle HandleFromFinalizable(Dart_FinalizableHandle object) {
@@ -955,7 +950,7 @@
   NoSafepointScope no_safepoint_scope;
   FinalizablePersistentHandle* weak_ref =
       FinalizablePersistentHandle::Cast(object);
-  return Api::NewHandle(thread, weak_ref->raw());
+  return Api::NewHandle(thread, weak_ref->ptr());
 }
 
 DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object) {
@@ -965,7 +960,7 @@
   ASSERT(state != NULL);
   const Object& old_ref = Object::Handle(Z, Api::UnwrapHandle(object));
   PersistentHandle* new_ref = state->AllocatePersistentHandle();
-  new_ref->set_raw(old_ref);
+  new_ref->set_ptr(old_ref);
   return new_ref->apiHandle();
 }
 
@@ -978,7 +973,7 @@
   ASSERT(state->IsValidPersistentHandle(obj1));
   const Object& obj2_ref = Object::Handle(Z, Api::UnwrapHandle(obj2));
   PersistentHandle* obj1_ref = PersistentHandle::Cast(obj1);
-  obj1_ref->set_raw(obj2_ref);
+  obj1_ref->set_ptr(obj2_ref);
 }
 
 static Dart_WeakPersistentHandle AllocateWeakPersistentHandle(
@@ -987,12 +982,12 @@
     void* peer,
     intptr_t external_allocation_size,
     Dart_HandleFinalizer callback) {
-  if (!ref.raw()->IsHeapObject()) {
+  if (!ref.ptr()->IsHeapObject()) {
     return NULL;
   }
   FinalizablePersistentHandle* finalizable_ref =
-      FinalizablePersistentHandle::New(thread->isolate(), ref, peer, callback,
-                                       external_allocation_size,
+      FinalizablePersistentHandle::New(thread->isolate_group(), ref, peer,
+                                       callback, external_allocation_size,
                                        /*auto_delete=*/false);
   return finalizable_ref->ApiWeakPersistentHandle();
 }
@@ -1016,13 +1011,13 @@
     void* peer,
     intptr_t external_allocation_size,
     Dart_HandleFinalizer callback) {
-  if (!ref.raw()->IsHeapObject()) {
+  if (!ref.ptr()->IsHeapObject()) {
     return NULL;
   }
 
   FinalizablePersistentHandle* finalizable_ref =
-      FinalizablePersistentHandle::New(thread->isolate(), ref, peer, callback,
-                                       external_allocation_size,
+      FinalizablePersistentHandle::New(thread->isolate_group(), ref, peer,
+                                       callback, external_allocation_size,
                                        /*auto_delete=*/true);
   return finalizable_ref->ApiFinalizableHandle();
 }
@@ -1276,7 +1271,7 @@
 
   if (success) {
     if (is_new_group) {
-      I->heap()->InitGrowthControl();
+      group->heap()->InitGrowthControl();
     }
     // A Thread structure has been associated to the thread, we do the
     // safepoint transition explicitly here instead of using the
@@ -1308,10 +1303,9 @@
   return false;
 }
 
-Isolate* CreateWithinExistingIsolateGroupAOT(IsolateGroup* group,
-                                             const char* name,
-                                             char** error) {
-#if defined(DART_PRECOMPILED_RUNTIME)
+Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
+                                          const char* name,
+                                          char** error) {
   API_TIMELINE_DURATION(Thread::Current());
   CHECK_NO_ISOLATE(Isolate::Current());
 
@@ -1326,171 +1320,6 @@
   ASSERT(isolate->source() == source);
 
   return isolate;
-#else
-  UNREACHABLE();
-#endif
-}
-
-Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
-                                          const char* name,
-                                          char** error) {
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  API_TIMELINE_DURATION(Thread::Current());
-  CHECK_NO_ISOLATE(Isolate::Current());
-
-  // During isolate start we'll make a temporary anonymous group from the same
-  // [source]. Once the isolate has been fully loaded we will merge it's heap
-  // into the shared heap.
-  auto spawning_group = new IsolateGroup(group->shareable_source(),
-                                         /*isolate_group_data=*/nullptr);
-  IsolateGroup::RegisterIsolateGroup(spawning_group);
-  spawning_group->CreateHeap(
-      /*is_vm_isolate=*/false,
-      IsServiceOrKernelIsolateName(group->source()->name));
-
-  Isolate* isolate = reinterpret_cast<Isolate*>(
-      CreateIsolate(spawning_group, /*is_new_group=*/false, name,
-                    /*isolate_data=*/nullptr, error));
-  if (isolate == nullptr) return nullptr;
-
-  auto source = spawning_group->source();
-  ASSERT(isolate->source() == source);
-
-  if (source->script_kernel_buffer != nullptr) {
-    Dart_EnterScope();
-    {
-      Thread* T = Thread::Current();
-      TransitionNativeToVM transition(T);
-      HANDLESCOPE(T);
-      StackZone zone(T);
-
-      // NOTE: We do not attach a finalizer for this object, because the
-      // embedder will free it once the isolate group has shutdown.
-      const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
-          kExternalTypedDataUint8ArrayCid,
-          const_cast<uint8_t*>(source->script_kernel_buffer),
-          source->script_kernel_size, Heap::kOld));
-
-      std::unique_ptr<kernel::Program> program =
-          kernel::Program::ReadFromTypedData(td,
-                                             const_cast<const char**>(error));
-      if (program == nullptr) {
-        UNIMPLEMENTED();
-      }
-      const Object& tmp =
-          kernel::KernelLoader::LoadEntireProgram(program.get());
-
-      // If the existing isolate could spawn with a root library we should be
-      // able to do the same
-      RELEASE_ASSERT(!tmp.IsNull() && tmp.IsLibrary());
-      isolate->object_store()->set_root_library(Library::Cast(tmp));
-    }
-    Dart_ExitScope();
-  }
-
-  // If we are running in AppJIT training mode we'll have to remap class ids.
-  if (auto permutation_map = group->source()->cid_permutation_map.get()) {
-    Dart_EnterScope();
-    {
-      auto T = Thread::Current();
-      TransitionNativeToVM transition(T);
-      HANDLESCOPE(T);
-
-      // Remap all class ids loaded atm (e.g. from snapshot) and do appropriate
-      // re-hashing of constants and types.
-      ClassFinalizer::RemapClassIds(permutation_map);
-      // Types use cid's as part of their hashes.
-      ClassFinalizer::RehashTypes();
-      // Const objects use cid's as part of their hashes.
-      isolate->RehashConstants();
-    }
-    Dart_ExitScope();
-  }
-
-  auto thread = Thread::Current();
-  {
-    TransitionNativeToVM native_to_vm(thread);
-
-    // Ensure there are no helper threads running.
-    BackgroundCompiler::Stop(isolate);
-    isolate->heap()->WaitForMarkerTasks(thread);
-    isolate->heap()->WaitForSweeperTasks(thread);
-    SafepointOperationScope safepoint_operation(thread);
-    isolate->group()->ReleaseStoreBuffers();
-    RELEASE_ASSERT(isolate->heap()->old_space()->tasks() == 0);
-  }
-
-  Dart_ExitIsolate();
-  {
-    const bool kBypassSafepoint = false;
-    Thread::EnterIsolateGroupAsHelper(group, Thread::kUnknownTask,
-                                      kBypassSafepoint);
-    ASSERT(group == IsolateGroup::Current());
-
-    {
-      auto thread = Thread::Current();
-
-      // Prevent additions of new isolates to [group] until we're done.
-      group->RunWithLockedGroup([&]() {
-        // Ensure no other old space GC tasks are running and "occupy" the old
-        // space.
-        SafepointOperationScope safepoint_scope(thread);
-        {
-          auto old_space = group->heap()->old_space();
-          MonitorLocker ml(old_space->tasks_lock());
-          while (old_space->tasks() > 0) {
-            ml.Wait();
-          }
-          old_space->set_tasks(1);
-        }
-
-        // Merge the heap from [spawning_group] to [group].
-        group->heap()->MergeFrom(isolate->group()->heap());
-
-        spawning_group->UnregisterIsolate(isolate);
-        const bool shutdown_group =
-            spawning_group->UnregisterIsolateDecrementCount(isolate);
-        ASSERT(shutdown_group);
-
-        isolate->isolate_group_ = group;
-        group->RegisterIsolateLocked(isolate);
-        isolate->class_table()->shared_class_table_ =
-            group->shared_class_table();
-        isolate->set_shared_class_table(group->shared_class_table());
-
-        // Even though the mutator thread was descheduled, it will still
-        // retain its [Thread] structure with valid isolate/isolate_group
-        // pointers.
-        // If GC happens before the mutator gets scheduled again, we have to
-        // ensure the isolate group change is reflected in the threads
-        // structure.
-        ASSERT(isolate->mutator_thread() != nullptr);
-        ASSERT(isolate->mutator_thread()->isolate_group() == spawning_group);
-        isolate->mutator_thread()->isolate_group_ = group;
-
-        // Allow other old space GC tasks to run again.
-        {
-          auto old_space = group->heap()->old_space();
-          MonitorLocker ml(old_space->tasks_lock());
-          ASSERT(old_space->tasks() == 1);
-          old_space->set_tasks(0);
-          ml.NotifyAll();
-        }
-      });
-    }
-
-    Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
-  }
-
-  spawning_group->Shutdown();
-
-  Dart_EnterIsolate(Api::CastIsolate(isolate));
-  ASSERT(Thread::Current()->isolate_group() == isolate->group());
-
-  return isolate;
-#else
-  UNREACHABLE();
-#endif
 }
 
 DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags) {
@@ -1518,7 +1347,7 @@
   std::unique_ptr<IsolateGroupSource> source(
       new IsolateGroupSource(script_uri, non_null_name, snapshot_data,
                              snapshot_instructions, nullptr, -1, *flags));
-  auto group = new IsolateGroup(std::move(source), isolate_group_data);
+  auto group = new IsolateGroup(std::move(source), isolate_group_data, *flags);
   group->CreateHeap(
       /*is_vm_isolate=*/false, IsServiceOrKernelIsolateName(non_null_name));
   IsolateGroup::RegisterIsolateGroup(group);
@@ -1551,7 +1380,7 @@
   std::shared_ptr<IsolateGroupSource> source(
       new IsolateGroupSource(script_uri, non_null_name, nullptr, nullptr,
                              kernel_buffer, kernel_buffer_size, *flags));
-  auto group = new IsolateGroup(source, isolate_group_data);
+  auto group = new IsolateGroup(source, isolate_group_data, *flags);
   IsolateGroup::RegisterIsolateGroup(group);
   group->CreateHeap(
       /*is_vm_isolate=*/false, IsServiceOrKernelIsolateName(non_null_name));
@@ -1589,7 +1418,7 @@
 
   Isolate* isolate;
 #if defined(DART_PRECOMPILED_RUNTIME)
-  isolate = CreateWithinExistingIsolateGroupAOT(member->group(), name, error);
+  isolate = CreateWithinExistingIsolateGroup(member->group(), name, error);
   if (isolate != nullptr) {
     isolate->set_origin_id(member->origin_id());
     isolate->set_init_callback_data(child_isolate_data);
@@ -1910,15 +1739,15 @@
   NoSafepointScope no_safepoint_scope;
   const Error& error_handle = Api::UnwrapErrorHandle(Z, error);
   if ((isolate->sticky_error() != Error::null()) &&
-      (error_handle.raw() != Object::null())) {
+      (error_handle.ptr() != Object::null())) {
     FATAL1("%s expects there to be no sticky error.", CURRENT_FUNC);
   }
   if (!error_handle.IsUnhandledException() &&
-      (error_handle.raw() != Object::null())) {
+      (error_handle.ptr() != Object::null())) {
     FATAL1("%s expects the error to be an unhandled exception error or null.",
            CURRENT_FUNC);
   }
-  isolate->SetStickyError(error_handle.raw());
+  isolate->SetStickyError(error_handle.ptr());
 }
 
 DART_EXPORT bool Dart_HasStickyError() {
@@ -1991,7 +1820,7 @@
 #else
   DARTSCOPE(Thread::Current());
   API_TIMELINE_DURATION(T);
-  Isolate* I = T->isolate();
+  auto I = T->isolate();
   if (vm_snapshot_data_buffer != nullptr) {
     CHECK_NULL(vm_snapshot_data_size);
   }
@@ -2005,7 +1834,7 @@
   BackgroundCompiler::Stop(I);
 
 #if defined(DEBUG)
-  I->heap()->CollectAllGarbage();
+  T->isolate_group()->heap()->CollectAllGarbage();
   {
     HeapIterationScope iteration(T);
     CheckFunctionTypesVisitor check_canonical(T);
@@ -2132,7 +1961,7 @@
   }
   if (FLAG_print_class_table) {
     HANDLESCOPE(Thread::Current());
-    I->class_table()->Print();
+    I->group()->class_table()->Print();
   }
   return Api::Success();
 }
@@ -2210,7 +2039,7 @@
   Object& result =
       Object::Handle(Z, DartLibraryCalls::EnsureScheduleImmediate());
   if (result.IsError()) {
-    return Api::NewHandle(T, result.raw());
+    return Api::NewHandle(T, result.ptr());
   }
 
   // Drain the microtask queue. Propagate any errors to the entry frame.
@@ -2220,7 +2049,7 @@
     const Error* error;
     {
       NoSafepointScope no_safepoint;
-      ErrorPtr raw_error = Error::Cast(result).raw();
+      ErrorPtr raw_error = Error::Cast(result).ptr();
       T->UnwindScopes(T->top_exit_frame_info());
       error = &Error::Handle(T->zone(), raw_error);
     }
@@ -2420,7 +2249,7 @@
     *value = Bool::Cast(result).value();
     return Api::Success();
   } else if (result.IsError()) {
-    return Api::NewHandle(T, result.raw());
+    return Api::NewHandle(T, result.ptr());
   } else {
     return Api::NewError("Expected boolean result from ==");
   }
@@ -2550,7 +2379,7 @@
   Thread* thread = Thread::Current();
   CHECK_ISOLATE(thread->isolate());
   TransitionNativeToVM transition(thread);
-  return Api::ClassId(handle) == kTypeCid;
+  return IsTypeClassId(Api::ClassId(handle));
 }
 
 DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
@@ -2614,7 +2443,7 @@
   API_TIMELINE_DURATION(T);
   const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
   if (obj.IsInstance()) {
-    ObjectStore* object_store = T->isolate()->object_store();
+    ObjectStore* object_store = T->isolate_group()->object_store();
     const Type& future_rare_type =
         Type::Handle(Z, object_store->non_nullable_future_rare_type());
     ASSERT(!future_rare_type.IsNull());
@@ -2632,10 +2461,10 @@
 DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance) {
   DARTSCOPE(Thread::Current());
   API_TIMELINE_DURATION(T);
-  Isolate* I = T->isolate();
+  auto isolate_group = T->isolate_group();
   const Object& obj = Object::Handle(Z, Api::UnwrapHandle(instance));
   if (obj.IsNull()) {
-    return Api::NewHandle(T, I->object_store()->null_type());
+    return Api::NewHandle(T, isolate_group->object_store()->null_type());
   }
   if (!obj.IsInstance()) {
     RETURN_TYPE_ERROR(Z, instance, Instance);
@@ -2735,7 +2564,7 @@
   if (library.IsNull()) {
     return Dart_Null();
   }
-  return Api::NewHandle(Thread::Current(), library.raw());
+  return Api::NewHandle(Thread::Current(), library.ptr());
 }
 
 // --- Numbers, Integers and Doubles ----
@@ -2942,7 +2771,7 @@
     return Api::NewError("function_name must refer to a static method.");
   }
 
-  if (func.kind() != FunctionLayout::kRegularFunction) {
+  if (func.kind() != UntaggedFunction::kRegularFunction) {
     return Api::NewError(
         "function_name must be the name of a regular function.");
   }
@@ -3217,7 +3046,7 @@
     ASSERT(*peer != NULL);
   } else {
     NoSafepointScope no_safepoint_scope;
-    *peer = thread->isolate()->heap()->GetPeer(str.raw());
+    *peer = thread->heap()->GetPeer(str.ptr());
   }
   *char_size = str.CharSize();
   *str_len = str.Length();
@@ -3248,7 +3077,8 @@
 DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id,
                                        intptr_t length) {
   DARTSCOPE(Thread::Current());
-  if (T->isolate()->null_safety() && element_type_id != Dart_CoreType_Dynamic) {
+  if (T->isolate_group()->null_safety() &&
+      element_type_id != Dart_CoreType_Dynamic) {
     return Api::NewError(
         "Cannot use legacy types with --sound-null-safety enabled. "
         "Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
@@ -3258,10 +3088,10 @@
   const Array& arr = Array::Handle(Z, Array::New(length));
   if (element_type_id != Dart_CoreType_Dynamic) {
     arr.SetTypeArguments(TypeArguments::Handle(
-        Z, TypeArgumentsForElementType(T->isolate()->object_store(),
+        Z, TypeArgumentsForElementType(T->isolate_group()->object_store(),
                                        element_type_id)));
   }
-  return Api::NewHandle(T, arr.raw());
+  return Api::NewHandle(T, arr.ptr());
 }
 
 static bool CanTypeContainNull(const Type& type) {
@@ -3322,12 +3152,12 @@
   for (intptr_t i = 0; i < arr.Length(); ++i) {
     arr.SetAt(i, instance);
   }
-  return Api::NewHandle(T, arr.raw());
+  return Api::NewHandle(T, arr.ptr());
 }
 
 #define GET_LIST_LENGTH(zone, type, obj, len)                                  \
   type& array = type::Handle(zone);                                            \
-  array ^= obj.raw();                                                          \
+  array ^= obj.ptr();                                                          \
   *len = array.Length();                                                       \
   return Api::Success();
 
@@ -3386,7 +3216,7 @@
         "Length of List object is greater than the "
         "maximum value that 'len' parameter can hold");
   } else if (retval.IsError()) {
-    return Api::NewHandle(T, retval.raw());
+    return Api::NewHandle(T, retval.ptr());
   } else {
     return Api::NewError("Length of List object is not an integer");
   }
@@ -3561,10 +3391,10 @@
   String& dot_name = String::Handle(String::New("."));
   String& constr_name = String::Handle(String::Concat(class_name, dot_name));
   result = ResolveConstructor(CURRENT_FUNC, cls, class_name, constr_name, 1);
-  if (result.IsError()) return result.raw();
+  if (result.IsError()) return result.ptr();
   ASSERT(result.IsFunction());
   Function& constructor = Function::Handle(zone);
-  constructor ^= result.raw();
+  constructor ^= result.ptr();
   if (!constructor.IsGenerativeConstructor()) {
     const String& message = String::Handle(
         String::NewFormatted("%s: class '%s' is not a constructor.",
@@ -3577,7 +3407,7 @@
   args.SetAt(0, exception);
   args.SetAt(1, String::Handle(String::New(exception_message)));
   result = DartEntry::InvokeFunction(constructor, args);
-  if (result.IsError()) return result.raw();
+  if (result.IsError()) return result.ptr();
   ASSERT(result.IsNull());
 
   if (thread->top_exit_frame_info() == 0) {
@@ -3592,7 +3422,7 @@
   const Instance* saved_exception;
   {
     NoSafepointScope no_safepoint;
-    InstancePtr raw_exception = exception.raw();
+    InstancePtr raw_exception = exception.ptr();
     thread->UnwindScopes(thread->top_exit_frame_info());
     saved_exception = &Instance::Handle(raw_exception);
   }
@@ -3713,7 +3543,7 @@
         args.SetAt(1, intobj);
         result = DartEntry::InvokeFunction(function, args);
         if (result.IsError()) {
-          return Api::NewHandle(T, result.raw());
+          return Api::NewHandle(T, result.ptr());
         }
         if (!result.IsInteger()) {
           return Api::NewError(
@@ -3802,7 +3632,7 @@
         const Object& result =
             Object::Handle(Z, DartEntry::InvokeFunction(function, args));
         if (result.IsError()) {
-          return Api::NewHandle(T, result.raw());
+          return Api::NewHandle(T, result.ptr());
         }
       }
       return Api::Success();
@@ -3856,7 +3686,7 @@
     const Object& iterator = Object::Handle(
         Send0Arg(instance, String::Handle(Z, String::New("get:keys"))));
     if (!iterator.IsInstance()) {
-      return Api::NewHandle(T, iterator.raw());
+      return Api::NewHandle(T, iterator.ptr());
     }
     return Api::NewHandle(T, Send0Arg(Instance::Cast(iterator),
                                       String::Handle(String::New("toList"))));
@@ -3986,8 +3816,8 @@
 static ObjectPtr GetByteDataConstructor(Thread* thread,
                                         const String& constructor_name,
                                         intptr_t num_args) {
-  const Library& lib =
-      Library::Handle(thread->isolate()->object_store()->typed_data_library());
+  const Library& lib = Library::Handle(
+      thread->isolate_group()->object_store()->typed_data_library());
   ASSERT(!lib.IsNull());
   const Class& cls = Class::Handle(
       thread->zone(), lib.LookupClassAllowPrivate(Symbols::ByteData()));
@@ -4015,7 +3845,7 @@
   // Invoke the constructor and return the new object.
   result = DartEntry::InvokeFunction(factory, args);
   ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
-  return Api::NewHandle(thread, result.raw());
+  return Api::NewHandle(thread, result.ptr());
 }
 
 static Dart_Handle NewTypedData(Thread* thread, intptr_t cid, intptr_t length) {
@@ -4033,10 +3863,11 @@
   CHECK_LENGTH(length, ExternalTypedData::MaxElements(cid));
   Zone* zone = thread->zone();
   intptr_t bytes = length * ExternalTypedData::ElementSizeInBytes(cid);
-  auto& cls = Class::Handle(zone, thread->isolate()->class_table()->At(cid));
+  auto& cls =
+      Class::Handle(zone, thread->isolate_group()->class_table()->At(cid));
   auto& result = Object::Handle(zone, cls.EnsureIsAllocateFinalized(thread));
   if (result.IsError()) {
-    return Api::NewHandle(thread, result.raw());
+    return Api::NewHandle(thread, result.ptr());
   }
   result = ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data), length,
                                   thread->heap()->SpaceForExternal(bytes));
@@ -4044,7 +3875,7 @@
     AllocateFinalizableHandle(thread, result, peer, external_allocation_size,
                               callback);
   }
-  return Api::NewHandle(thread, result.raw());
+  return Api::NewHandle(thread, result.ptr());
 }
 
 static Dart_Handle NewExternalByteData(Thread* thread,
@@ -4084,7 +3915,7 @@
   // Invoke the constructor and return the new object.
   result = DartEntry::InvokeFunction(factory, args);
   ASSERT(result.IsNull() || result.IsInstance() || result.IsError());
-  return Api::NewHandle(thread, result.raw());
+  return Api::NewHandle(thread, result.ptr());
 }
 
 DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type,
@@ -4223,8 +4054,8 @@
                                           const String& class_name,
                                           const String& constructor_name,
                                           intptr_t num_args) {
-  const Library& lib =
-      Library::Handle(thread->isolate()->object_store()->typed_data_library());
+  const Library& lib = Library::Handle(
+      thread->isolate_group()->object_store()->typed_data_library());
   ASSERT(!lib.IsNull());
   const Class& cls =
       Class::Handle(thread->zone(), lib.LookupClassAllowPrivate(class_name));
@@ -4258,7 +4089,7 @@
   // Invoke the factory constructor and return the new object.
   result = DartEntry::InvokeFunction(factory, args);
   ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
-  return Api::NewHandle(T, result.raw());
+  return Api::NewHandle(T, result.ptr());
 }
 
 // Structure to record acquired typed data for verification purposes.
@@ -4358,13 +4189,13 @@
   }
   if (FLAG_verify_acquired_data) {
     if (external) {
-      ASSERT(!I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+      ASSERT(!T->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
     } else {
-      ASSERT(I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+      ASSERT(T->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
     }
     const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
     WeakTable* table = I->group()->api_state()->acquired_table();
-    intptr_t current = table->GetValue(obj.raw());
+    intptr_t current = table->GetValue(obj.ptr());
     if (current != 0) {
       return Api::NewError("Data was already acquired for this object.");
     }
@@ -4372,7 +4203,7 @@
     // data to remain in place, even though the API spec doesn't guarantee it.
     // TODO(koda/asiva): Make final decision and document it.
     AcquiredData* ad = new AcquiredData(data_tmp, size_in_bytes, !external);
-    table->SetValue(obj.raw(), reinterpret_cast<intptr_t>(ad));
+    table->SetValue(obj.ptr(), reinterpret_cast<intptr_t>(ad));
     data_tmp = ad->GetData();
   }
   *data = data_tmp;
@@ -4393,12 +4224,12 @@
   if (FLAG_verify_acquired_data) {
     const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
     WeakTable* table = I->group()->api_state()->acquired_table();
-    intptr_t current = table->GetValue(obj.raw());
+    intptr_t current = table->GetValue(obj.ptr());
     if (current == 0) {
       return Api::NewError("Data was not acquired for this object.");
     }
     AcquiredData* ad = reinterpret_cast<AcquiredData*>(current);
-    table->SetValue(obj.raw(), 0);  // Delete entry from table.
+    table->SetValue(obj.ptr(), 0);  // Delete entry from table.
     delete ad;
   }
   return Api::Success();
@@ -4464,7 +4295,7 @@
   }
   ErrorPtr error = constructor.VerifyCallEntryPoint();
   if (error != Error::null()) return error;
-  return constructor.raw();
+  return constructor.ptr();
 }
 
 DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
@@ -4487,7 +4318,7 @@
     RETURN_TYPE_ERROR(Z, type, Type);
   }
   Type& type_obj = Type::Handle();
-  type_obj ^= unchecked_type.raw();
+  type_obj ^= unchecked_type.ptr();
   if (!type_obj.IsFinalized()) {
     return Api::NewError(
         "%s expects argument 'type' to be a fully resolved type.",
@@ -4505,7 +4336,7 @@
   String& dot_name = String::Handle(Z);
   result = Api::UnwrapHandle(constructor_name);
   if (result.IsNull()) {
-    dot_name = Symbols::Dot().raw();
+    dot_name = Symbols::Dot().ptr();
   } else if (result.IsString()) {
     dot_name = String::Concat(Symbols::Dot(), String::Cast(result));
   } else {
@@ -4518,11 +4349,11 @@
   result = ResolveConstructor("Dart_New", cls, base_constructor_name,
                               constr_name, number_of_arguments);
   if (result.IsError()) {
-    return Api::NewHandle(T, result.raw());
+    return Api::NewHandle(T, result.ptr());
   }
   ASSERT(result.IsFunction());
   Function& constructor = Function::Handle(Z);
-  constructor ^= result.raw();
+  constructor ^= result.ptr();
 
   Instance& new_object = Instance::Handle(Z);
   if (constructor.IsGenerativeConstructor()) {
@@ -4560,7 +4391,7 @@
     argument = Api::UnwrapHandle(arguments[i]);
     if (!argument.IsNull() && !argument.IsInstance()) {
       if (argument.IsError()) {
-        return Api::NewHandle(T, argument.raw());
+        return Api::NewHandle(T, argument.ptr());
       } else {
         return Api::NewError(
             "%s expects arguments[%d] to be an Instance handle.", CURRENT_FUNC,
@@ -4573,23 +4404,23 @@
   // Invoke the constructor and return the new object.
   result = DartEntry::InvokeFunction(constructor, args);
   if (result.IsError()) {
-    return Api::NewHandle(T, result.raw());
+    return Api::NewHandle(T, result.ptr());
   }
 
   if (constructor.IsGenerativeConstructor()) {
     ASSERT(result.IsNull());
   } else {
     ASSERT(result.IsNull() || result.IsInstance());
-    new_object ^= result.raw();
+    new_object ^= result.ptr();
   }
-  return Api::NewHandle(T, new_object.raw());
+  return Api::NewHandle(T, new_object.ptr());
 }
 
 static InstancePtr AllocateObject(Thread* thread, const Class& cls) {
   if (!cls.is_fields_marked_nullable()) {
     // Mark all fields as nullable.
     Zone* zone = thread->zone();
-    Class& iterate_cls = Class::Handle(zone, cls.raw());
+    Class& iterate_cls = Class::Handle(zone, cls.ptr());
     Field& field = Field::Handle(zone);
     Array& fields = Array::Handle(zone);
     while (!iterate_cls.IsNull()) {
@@ -4661,7 +4492,7 @@
   }
   const Instance& instance = Instance::Handle(Z, AllocateObject(T, cls));
   instance.SetNativeFields(num_native_fields, native_fields);
-  return Api::NewHandle(T, instance.raw());
+  return Api::NewHandle(T, instance.ptr());
 }
 
 static Dart_Handle SetupArguments(Thread* thread,
@@ -4678,7 +4509,7 @@
     if (!arg.IsNull() && !arg.IsInstance()) {
       *args = Array::null();
       if (arg.IsError()) {
-        return Api::NewHandle(thread, arg.raw());
+        return Api::NewHandle(thread, arg.ptr());
       } else {
         return Api::NewError(
             "%s expects arguments[%d] to be an Instance handle.", "Dart_Invoke",
@@ -4756,9 +4587,9 @@
       const Object& retval =
           Object::Handle(Z, DartEntry::InvokeFunction(constructor, args));
       if (retval.IsError()) {
-        result = Api::NewHandle(T, retval.raw());
+        result = Api::NewHandle(T, retval.ptr());
       } else {
-        result = Api::NewHandle(T, instance.raw());
+        result = Api::NewHandle(T, instance.ptr());
       }
     }
     return result;
@@ -4776,7 +4607,7 @@
   CHECK_CALLBACK_STATE(T);
 
   String& function_name =
-      String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
+      String::Handle(Z, Api::UnwrapStringHandle(Z, name).ptr());
   if (function_name.IsNull()) {
     RETURN_TYPE_ERROR(Z, name, String);
   }
@@ -4821,7 +4652,7 @@
     // receiver is already resolved and finalized, hence it is not necessary
     // to check here.
     Instance& instance = Instance::Handle(Z);
-    instance ^= obj.raw();
+    instance ^= obj.ptr();
 
     // Setup args and check for malformed arguments in the arguments list.
     result = SetupArguments(T, number_of_arguments, arguments, 1, &args);
@@ -4899,7 +4730,7 @@
   CHECK_CALLBACK_STATE(T);
 
   String& field_name =
-      String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
+      String::Handle(Z, Api::UnwrapStringHandle(Z, name).ptr());
   if (field_name.IsNull()) {
     RETURN_TYPE_ERROR(Z, name, String);
   }
@@ -4924,7 +4755,7 @@
                             respect_reflectable, check_is_entrypoint));
   } else if (obj.IsNull() || obj.IsInstance()) {
     Instance& instance = Instance::Handle(Z);
-    instance ^= obj.raw();
+    instance ^= obj.ptr();
     if (Library::IsPrivate(field_name)) {
       const Class& cls = Class::Handle(Z, instance.clazz());
       const Library& lib = Library::Handle(Z, cls.library());
@@ -4964,7 +4795,7 @@
   CHECK_CALLBACK_STATE(T);
 
   String& field_name =
-      String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
+      String::Handle(Z, Api::UnwrapStringHandle(Z, name).ptr());
   if (field_name.IsNull()) {
     RETURN_TYPE_ERROR(Z, name, String);
   }
@@ -4975,7 +4806,7 @@
     RETURN_TYPE_ERROR(Z, value, Instance);
   }
   Instance& value_instance = Instance::Handle(Z);
-  value_instance ^= value_obj.raw();
+  value_instance ^= value_obj.ptr();
 
   const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
   const bool respect_reflectable = false;
@@ -5000,7 +4831,7 @@
                             check_is_entrypoint));
   } else if (obj.IsNull() || obj.IsInstance()) {
     Instance& instance = Instance::Handle(Z);
-    instance ^= obj.raw();
+    instance ^= obj.ptr();
     if (Library::IsPrivate(field_name)) {
       const Class& cls = Class::Handle(Z, instance.clazz());
       const Library& lib = Library::Handle(Z, cls.library());
@@ -5062,7 +4893,7 @@
   {
     NoSafepointScope no_safepoint;
     InstancePtr raw_exception =
-        Api::UnwrapInstanceHandle(zone, exception).raw();
+        Api::UnwrapInstanceHandle(zone, exception).ptr();
     thread->UnwindScopes(thread->top_exit_frame_info());
     saved_exception = &Instance::Handle(raw_exception);
   }
@@ -5100,9 +4931,9 @@
   {
     NoSafepointScope no_safepoint;
     InstancePtr raw_exception =
-        Api::UnwrapInstanceHandle(zone, exception).raw();
+        Api::UnwrapInstanceHandle(zone, exception).ptr();
     StackTracePtr raw_stacktrace =
-        Api::UnwrapStackTraceHandle(zone, stacktrace).raw();
+        Api::UnwrapStackTraceHandle(zone, stacktrace).ptr();
     thread->UnwindScopes(thread->top_exit_frame_info());
     saved_exception = &Instance::Handle(raw_exception);
     saved_stacktrace = &StackTrace::Handle(raw_stacktrace);
@@ -5471,26 +5302,26 @@
     // "_", and the mirrors library, if it is not supported.
 
     if (!FLAG_enable_mirrors && name.Equals(Symbols::DartLibraryMirrors())) {
-      return Symbols::False().raw();
+      return Symbols::False().ptr();
     }
 
     if (!Api::IsFfiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
-      return Symbols::False().raw();
+      return Symbols::False().ptr();
     }
 
     if (name.Equals(Symbols::DartVMProduct())) {
 #ifdef PRODUCT
-      return Symbols::True().raw();
+      return Symbols::True().ptr();
 #else
-      return Symbols::False().raw();
+      return Symbols::False().ptr();
 #endif
     }
 
     if (name.Equals(Symbols::DartDeveloperTimeline())) {
 #ifdef SUPPORT_TIMELINE
-      return Symbols::True().raw();
+      return Symbols::True().ptr();
 #else
-      return Symbols::False().raw();
+      return Symbols::False().ptr();
 #endif
     }
 
@@ -5506,17 +5337,17 @@
         const Library& library =
             Library::Handle(Library::LookupLibrary(thread, dart_library_name));
         if (!library.IsNull()) {
-          return Symbols::True().raw();
+          return Symbols::True().ptr();
         }
       }
     }
     // Check for default VM provided values. If it was not overridden on the
     // command line.
     if (Symbols::DartIsVM().Equals(name)) {
-      return Symbols::True().raw();
+      return Symbols::True().ptr();
     }
   }
-  return result.raw();
+  return result.ptr();
 }
 
 StringPtr Api::CallEnvironmentCallback(Thread* thread, const String& name) {
@@ -5524,7 +5355,7 @@
   Dart_EnvironmentCallback callback = isolate->environment_callback();
   if (callback != NULL) {
     Scope api_scope(thread);
-    Dart_Handle api_name = Api::NewHandle(thread, name.raw());
+    Dart_Handle api_name = Api::NewHandle(thread, name.ptr());
     Dart_Handle api_response;
     {
       TransitionVMToNative transition(thread);
@@ -5533,7 +5364,7 @@
     const Object& response =
         Object::Handle(thread->zone(), Api::UnwrapHandle(api_response));
     if (response.IsString()) {
-      return String::Cast(response).raw();
+      return String::Cast(response).ptr();
     } else if (response.IsError()) {
       Exceptions::ThrowArgumentError(
           String::Handle(String::New(Error::Cast(response).ToErrorCString())));
@@ -5636,9 +5467,9 @@
   DARTSCOPE(Thread::Current());
   API_TIMELINE_DURATION(T);
   StackZone zone(T);
-  Isolate* I = T->isolate();
+  IsolateGroup* IG = T->isolate_group();
 
-  Library& library = Library::Handle(Z, I->object_store()->root_library());
+  Library& library = Library::Handle(Z, IG->object_store()->root_library());
   if (!library.IsNull()) {
     const String& library_url = String::Handle(Z, library.url());
     return Api::NewError("%s: A script has already been loaded from '%s'.",
@@ -5662,11 +5493,11 @@
   program.reset();
 
   if (tmp.IsError()) {
-    return Api::NewHandle(T, tmp.raw());
+    return Api::NewHandle(T, tmp.ptr());
   }
 
-  I->source()->script_kernel_size = buffer_size;
-  I->source()->script_kernel_buffer = buffer;
+  IG->source()->script_kernel_size = buffer_size;
+  IG->source()->script_kernel_buffer = buffer;
 
   // TODO(32618): Setting root library based on whether it has 'main' or not
   // is not correct because main can be in the exported namespace of a library
@@ -5675,9 +5506,9 @@
     return Api::NewError("%s: The binary program does not contain 'main'.",
                          CURRENT_FUNC);
   }
-  library ^= tmp.raw();
-  I->object_store()->set_root_library(library);
-  return Api::NewHandle(T, library.raw());
+  library ^= tmp.ptr();
+  IG->object_store()->set_root_library(library);
+  return Api::NewHandle(T, library.ptr());
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -5686,7 +5517,8 @@
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
   TransitionNativeToVM transition(thread);
-  return Api::NewHandle(thread, isolate->object_store()->root_library());
+  return Api::NewHandle(thread,
+                        isolate->group()->object_store()->root_library());
 }
 
 DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library) {
@@ -5694,8 +5526,8 @@
   const Object& obj = Object::Handle(Z, Api::UnwrapHandle(library));
   if (obj.IsNull() || obj.IsLibrary()) {
     Library& lib = Library::Handle(Z);
-    lib ^= obj.raw();
-    T->isolate()->object_store()->set_root_library(lib);
+    lib ^= obj.ptr();
+    T->isolate_group()->object_store()->set_root_library(lib);
     return library;
   }
   RETURN_TYPE_ERROR(Z, library, Library);
@@ -5795,18 +5627,17 @@
     }
 
     // Construct the type object, canonicalize it and return.
-    type ^=
-        Type::New(cls, type_args_obj, TokenPosition::kNoSource, nullability);
+    type ^= Type::New(cls, type_args_obj, nullability);
   }
   type ^= ClassFinalizer::FinalizeType(type);
-  return Api::NewHandle(T, type.raw());
+  return Api::NewHandle(T, type.ptr());
 }
 
 DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library,
                                      Dart_Handle class_name,
                                      intptr_t number_of_type_arguments,
                                      Dart_Handle* type_arguments) {
-  if (Thread::Current()->isolate()->null_safety()) {
+  if (IsolateGroup::Current()->null_safety()) {
     return Api::NewError(
         "Cannot use legacy types with --sound-null-safety enabled. "
         "Use Dart_GetNullableType or Dart_GetNonNullableType instead.");
@@ -5885,7 +5716,7 @@
   }
   const String& url = String::Handle(Z, lib.url());
   ASSERT(!url.IsNull());
-  return Api::NewHandle(T, url.raw());
+  return Api::NewHandle(T, url.ptr());
 }
 
 DART_EXPORT Dart_Handle Dart_LibraryResolvedUrl(Dart_Handle library) {
@@ -5900,15 +5731,15 @@
   ASSERT(!script.IsNull());
   const String& url = String::Handle(script.resolved_url());
   ASSERT(!url.IsNull());
-  return Api::NewHandle(T, url.raw());
+  return Api::NewHandle(T, url.ptr());
 }
 
 DART_EXPORT Dart_Handle Dart_GetLoadedLibraries() {
   DARTSCOPE(Thread::Current());
-  Isolate* I = T->isolate();
+  auto IG = T->isolate_group();
 
   const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(Z, I->object_store()->libraries());
+      GrowableObjectArray::Handle(Z, IG->object_store()->libraries());
   int num_libs = libs.Length();
 
   // Create new list and populate with the loaded libraries.
@@ -5919,7 +5750,7 @@
     ASSERT(!lib.IsNull());
     library_list.SetAt(i, lib);
   }
-  return Api::NewHandle(T, library_list.raw());
+  return Api::NewHandle(T, library_list.ptr());
 }
 
 DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url) {
@@ -5934,7 +5765,7 @@
     return Api::NewError("%s: library '%s' not found.", CURRENT_FUNC,
                          url_str.ToCString());
   } else {
-    return Api::NewHandle(T, library.raw());
+    return Api::NewHandle(T, library.ptr());
   }
 }
 
@@ -5986,20 +5817,20 @@
   IsolateGroupSource* source = Isolate::Current()->source();
   source->add_loaded_blob(Z, td);
 
-  return Api::NewHandle(T, result.raw());
+  return Api::NewHandle(T, result.ptr());
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
 DART_EXPORT Dart_Handle Dart_GetImportsOfScheme(Dart_Handle scheme) {
   DARTSCOPE(Thread::Current());
-  Isolate* I = T->isolate();
+  auto IG = T->isolate_group();
   const String& scheme_vm = Api::UnwrapStringHandle(Z, scheme);
   if (scheme_vm.IsNull()) {
     RETURN_TYPE_ERROR(Z, scheme, String);
   }
 
   const GrowableObjectArray& libraries =
-      GrowableObjectArray::Handle(Z, I->object_store()->libraries());
+      GrowableObjectArray::Handle(Z, IG->object_store()->libraries());
   const GrowableObjectArray& result =
       GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
   Library& importer = Library::Handle(Z);
@@ -6053,7 +5884,7 @@
   // If this is an auxiliary isolate inside a larger isolate group, we will not
   // re-initialize the growth policy.
   if (I->group()->ContainsOnlyOneIsolate()) {
-    I->heap()->old_space()->EvaluateAfterLoading();
+    I->group()->heap()->old_space()->EvaluateAfterLoading();
   }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -6078,11 +5909,11 @@
                                         bool transient_error) {
   DARTSCOPE(Thread::Current());
   API_TIMELINE_DURATION(T);
-  Isolate* I = T->isolate();
+  auto IG = T->isolate_group();
   CHECK_CALLBACK_STATE(T);
 
   const Array& loading_units =
-      Array::Handle(I->object_store()->loading_units());
+      Array::Handle(IG->object_store()->loading_units());
   if (loading_units.IsNull() || (loading_unit_id < LoadingUnit::kRootId) ||
       (loading_unit_id >= loading_units.Length())) {
     return Api::NewError("Invalid loading unit");
@@ -6095,8 +5926,9 @@
 
   if (error) {
     CHECK_NULL(error_message);
-    unit.CompleteLoad(String::Handle(String::New(error_message)),
-                      transient_error);
+    return Api::NewHandle(
+        T, unit.CompleteLoad(String::Handle(String::New(error_message)),
+                             transient_error));
   } else {
 #if defined(SUPPORT_TIMELINE)
     TimelineBeginEndScope tbes(T, Timeline::GetIsolateStream(),
@@ -6117,13 +5949,11 @@
     FullSnapshotReader reader(snapshot, snapshot_instructions, T);
     const Error& error = Error::Handle(reader.ReadUnitSnapshot(unit));
     if (!error.IsNull()) {
-      return Api::NewHandle(T, error.raw());
+      return Api::NewHandle(T, error.ptr());
     }
 
-    unit.CompleteLoad(String::Handle(), false);
+    return Api::NewHandle(T, unit.CompleteLoad(String::Handle(), false));
   }
-
-  return Api::Success();
 }
 
 DART_EXPORT Dart_Handle
@@ -6206,8 +6036,8 @@
   }
   {
     NoSafepointScope no_safepoint;
-    ObjectPtr raw_obj = obj.raw();
-    *peer = thread->isolate()->heap()->GetPeer(raw_obj);
+    ObjectPtr raw_obj = obj.ptr();
+    *peer = thread->heap()->GetPeer(raw_obj);
   }
   return Api::Success();
 }
@@ -6226,8 +6056,8 @@
   }
   {
     NoSafepointScope no_safepoint;
-    ObjectPtr raw_obj = obj.raw();
-    thread->isolate()->heap()->SetPeer(raw_obj, peer);
+    ObjectPtr raw_obj = obj.ptr();
+    thread->heap()->SetPeer(raw_obj, peer);
   }
   return Api::Success();
 }
@@ -6264,7 +6094,9 @@
                      const uint8_t* platform_kernel,
                      intptr_t platform_kernel_size,
                      bool incremental_compile,
-                     const char* package_config) {
+                     bool snapshot_compile,
+                     const char* package_config,
+                     Dart_KernelCompilationVerbosityLevel verbosity) {
   API_TIMELINE_DURATION(Thread::Current());
 
   Dart_KernelCompilationResult result = {};
@@ -6272,9 +6104,10 @@
   result.status = Dart_KernelCompilationStatus_Unknown;
   result.error = Utils::StrDup("Dart_CompileToKernel is unsupported.");
 #else
-  result = KernelIsolate::CompileToKernel(script_uri, platform_kernel,
-                                          platform_kernel_size, 0, NULL,
-                                          incremental_compile, package_config);
+  result = KernelIsolate::CompileToKernel(
+      script_uri, platform_kernel, platform_kernel_size, 0, NULL,
+      incremental_compile, snapshot_compile, package_config, NULL, NULL,
+      verbosity);
   if (result.status == Dart_KernelCompilationStatus_Ok) {
     Dart_KernelCompilationResult accept_result =
         KernelIsolate::AcceptCompilation();
@@ -6590,7 +6423,7 @@
   CHECK_NULL(buffer);
   CHECK_NULL(buffer_length);
   CompilationTraceSaver saver(thread->zone());
-  ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
+  ProgramVisitor::WalkProgram(thread->zone(), thread->isolate_group(), &saver);
   saver.StealBuffer(buffer, buffer_length);
   return Api::Success();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
@@ -6612,7 +6445,7 @@
   saver.WriteHeader();
   saver.SaveClasses();
   saver.SaveFields();
-  ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
+  ProgramVisitor::WalkProgram(thread->zone(), thread->isolate_group(), &saver);
   *buffer = stream.buffer();
   *buffer_length = stream.bytes_written();
 
@@ -6637,7 +6470,7 @@
   const Object& error =
       Object::Handle(loader.CompileTrace(buffer, buffer_length));
   if (error.IsError()) {
-    return Api::NewHandle(T, Error::Cast(error).raw());
+    return Api::NewHandle(T, Error::Cast(error).ptr());
   }
   return Api::Success();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
@@ -6660,7 +6493,7 @@
   TypeFeedbackLoader loader(thread);
   const Object& error = Object::Handle(loader.LoadFeedback(&stream));
   if (error.IsError()) {
-    return Api::NewHandle(T, Error::Cast(error).raw());
+    return Api::NewHandle(T, Error::Cast(error).ptr());
   }
   return Api::Success();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
@@ -6679,7 +6512,7 @@
   ClassFinalizer::ClearAllCode();
   // Make sure that ICData etc. that have been cleared are also removed from
   // the heap so that they are not found by the heap verifier.
-  Isolate::Current()->heap()->CollectAllGarbage();
+  IsolateGroup::Current()->heap()->CollectAllGarbage();
   ClassFinalizer::SortClasses();
   return Api::Success();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
@@ -6702,7 +6535,8 @@
     return result;
   }
   CHECK_CALLBACK_STATE(T);
-  CompilerState state(Thread::Current(), /*is_aot=*/true);
+  CompilerState state(Thread::Current(), /*is_aot=*/true,
+                      /*is_optimizing=*/true);
   CHECK_ERROR_HANDLE(Precompiler::CompileAll());
   return Api::Success();
 #endif
@@ -6801,7 +6635,7 @@
   ProgramVisitor::AssignUnits(T);
 
   const Array& loading_units =
-      Array::Handle(T->isolate()->object_store()->loading_units());
+      Array::Handle(T->isolate_group()->object_store()->loading_units());
   const uint32_t program_hash = ProgramVisitor::Hash(T);
   loading_units.SetAt(0, Smi::Handle(Z, Smi::New(program_hash)));
   GrowableArray<LoadingUnitSerializationData*> data;
@@ -6858,7 +6692,7 @@
   CHECK_NULL(callback);
 
   // Mark as not split.
-  T->isolate()->object_store()->set_loading_units(Object::null_array());
+  T->isolate_group()->object_store()->set_loading_units(Object::null_array());
 
   CreateAppAOTSnapshot(callback, callback_data, strip, /*as_elf*/ false,
                        debug_callback_data, nullptr, nullptr, 0);
@@ -6939,7 +6773,7 @@
   CHECK_NULL(callback);
 
   // Mark as not split.
-  T->isolate()->object_store()->set_loading_units(Object::null_array());
+  T->isolate_group()->object_store()->set_loading_units(Object::null_array());
 
   CreateAppAOTSnapshot(callback, callback_data, strip, /*as_elf*/ true,
                        debug_callback_data, nullptr, nullptr, 0);
@@ -6985,8 +6819,8 @@
 
   const GrowableObjectArray& result =
       GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(Z, T->isolate()->object_store()->libraries());
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      Z, T->isolate_group()->object_store()->libraries());
   Library& lib = Library::Handle(Z);
   LoadingUnit& unit = LoadingUnit::Handle(Z);
   String& uri = String::Handle(Z);
@@ -7023,10 +6857,12 @@
       Class::Handle(zone, core_lib.LookupClassAllowPrivate(Symbols::_RegExp()));
   ASSERT(!reg_exp_class.IsNull());
 
+  auto thread = Thread::Current();
   Function& func = Function::Handle(
       zone, reg_exp_class.LookupFunctionAllowPrivate(execute_match_name));
   ASSERT(!func.IsNull());
   Code& code = Code::Handle(zone);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   if (func.HasCode()) {
     code = func.CurrentCode();
     ASSERT(!code.IsNull());
@@ -7151,7 +6987,8 @@
 #else
   DARTSCOPE(Thread::Current());
   API_TIMELINE_DURATION(T);
-  Isolate* I = T->isolate();
+  auto I = T->isolate();
+  auto IG = T->isolate_group();
   CHECK_NULL(isolate_snapshot_data_buffer);
   CHECK_NULL(isolate_snapshot_data_size);
   CHECK_NULL(isolate_snapshot_instructions_buffer);
@@ -7172,7 +7009,7 @@
   ProgramVisitor::Dedup(T);
 
   if (FLAG_dump_tables) {
-    Symbols::DumpTable(I);
+    Symbols::DumpTable(IG);
     DumpTypeTable(I);
     DumpTypeParameterTable(I);
     DumpTypeArgumentsTable(I);
@@ -7209,7 +7046,7 @@
 #else
   Thread* thread = Thread::Current();
   DARTSCOPE(thread);
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
 
   if (buffer == NULL) {
     RETURN_NULL_ERROR(buffer);
@@ -7223,13 +7060,13 @@
   TextBuffer text_buffer(kInitialBufferSize);
 
   text_buffer.AddChar('[');
-  if (isolate->obfuscation_map() != NULL) {
-    for (intptr_t i = 0; isolate->obfuscation_map()[i] != NULL; i++) {
+  if (isolate_group->obfuscation_map() != nullptr) {
+    for (intptr_t i = 0; isolate_group->obfuscation_map()[i] != nullptr; i++) {
       if (i > 0) {
         text_buffer.AddChar(',');
       }
       text_buffer.AddChar('"');
-      text_buffer.AddEscapedString(isolate->obfuscation_map()[i]);
+      text_buffer.AddEscapedString(isolate_group->obfuscation_map()[i]);
       text_buffer.AddChar('"');
     }
   }
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 80f0462..cefda8b 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -307,13 +307,7 @@
 
   static StringPtr GetEnvironmentValue(Thread* thread, const String& name);
 
-  static bool IsFfiEnabled() {
-#if defined(TAGET_OS_FUCHSIA)
-    return false;
-#else
-    return FLAG_enable_ffi;
-#endif
-  }
+  static bool IsFfiEnabled() { return FLAG_enable_ffi; }
 
  private:
   static Dart_Handle InitNewHandle(Thread* thread, ObjectPtr raw);
@@ -353,9 +347,6 @@
 Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
                                           const char* name,
                                           char** error);
-Isolate* CreateWithinExistingIsolateGroupAOT(IsolateGroup* group,
-                                             const char* name,
-                                             char** error);
 
 }  // namespace dart.
 
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 785a41d..a9fd5ba 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -930,7 +930,7 @@
   {
     TransitionNativeToVM transition(thread);
     const Type& null_type_obj = Api::UnwrapTypeHandle(zone, type);
-    EXPECT(null_type_obj.raw() == Type::NullType());
+    EXPECT(null_type_obj.ptr() == Type::NullType());
   }
 
   Dart_Handle instance = Dart_True();
@@ -940,7 +940,7 @@
   {
     TransitionNativeToVM transition(thread);
     const Type& bool_type_obj = Api::UnwrapTypeHandle(zone, type);
-    EXPECT(bool_type_obj.raw() == Type::BoolType());
+    EXPECT(bool_type_obj.ptr() == Type::BoolType());
   }
 
   // Errors propagate.
@@ -2942,7 +2942,7 @@
     HANDLESCOPE(thread);
     String& str1 = String::Handle();
     str1 = String::New("Test String");
-    Dart_Handle ref = Api::NewHandle(thread, str1.raw());
+    Dart_Handle ref = Api::NewHandle(thread, str1.ptr());
     String& str2 = String::Handle();
     str2 ^= Api::UnwrapHandle(ref);
     EXPECT(str1.Equals(str2));
@@ -2996,22 +2996,22 @@
     HANDLESCOPE(thread);
     for (int i = 0; i < 500; i++) {
       String& str = String::Handle();
-      str ^= PersistentHandle::Cast(handles[i])->raw();
+      str ^= PersistentHandle::Cast(handles[i])->ptr();
       EXPECT(str.Equals(kTestString1));
     }
     for (int i = 500; i < 1000; i++) {
       String& str = String::Handle();
-      str ^= PersistentHandle::Cast(handles[i])->raw();
+      str ^= PersistentHandle::Cast(handles[i])->ptr();
       EXPECT(str.Equals(kTestString2));
     }
     for (int i = 1000; i < 1500; i++) {
       String& str = String::Handle();
-      str ^= PersistentHandle::Cast(handles[i])->raw();
+      str ^= PersistentHandle::Cast(handles[i])->ptr();
       EXPECT(str.Equals(kTestString1));
     }
     for (int i = 1500; i < 2000; i++) {
       String& str = String::Handle();
-      str ^= PersistentHandle::Cast(handles[i])->raw();
+      str ^= PersistentHandle::Cast(handles[i])->ptr();
       EXPECT(str.Equals(kTestString2));
     }
   }
@@ -3071,7 +3071,7 @@
     TransitionNativeToVM transition(T);
     HANDLESCOPE(T);
     String& str = String::Handle();
-    str ^= PersistentHandle::Cast(obj)->raw();
+    str ^= PersistentHandle::Cast(obj)->ptr();
     EXPECT(str.Equals(kTestString1));
   }
 
@@ -3082,7 +3082,7 @@
     TransitionNativeToVM transition(T);
     HANDLESCOPE(T);
     String& str = String::Handle();
-    str ^= PersistentHandle::Cast(obj)->raw();
+    str ^= PersistentHandle::Cast(obj)->ptr();
     EXPECT(str.Equals(kTestString2));
   }
 
@@ -3404,7 +3404,7 @@
 }
 
 TEST_CASE(DartAPI_WeakPersistentHandleCleanupFinalizer) {
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   const char* kTestString1 = "Test String1";
   Dart_EnterScope();
@@ -3444,7 +3444,7 @@
 }
 
 TEST_CASE(DartAPI_FinalizableHandleCleanupFinalizer) {
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   const char* kTestString1 = "Test String1";
   Dart_EnterScope();
@@ -3641,7 +3641,7 @@
 }
 
 TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSize) {
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
   EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
   EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
   Dart_WeakPersistentHandle weak1 = NULL;
@@ -3691,7 +3691,7 @@
 }
 
 TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSize) {
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
   EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
   EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
   static const intptr_t kWeak1ExternalSize = 1 * KB;
@@ -3733,7 +3733,7 @@
 }
 
 TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeNewspaceGC) {
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_WeakPersistentHandle weak1 = NULL;
   // Large enough to exceed any new space limit. Not actually allocated.
   const intptr_t kWeak1ExternalSize = 500 * MB;
@@ -3775,7 +3775,7 @@
 }
 
 TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeNewspaceGC) {
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_FinalizableHandle weak1 = nullptr;
   Dart_PersistentHandle strong1 = nullptr;
   // Large enough to exceed any new space limit. Not actually allocated.
@@ -3819,7 +3819,7 @@
 
 TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeOldspaceGC) {
   // Check that external allocation in old space can trigger GC.
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_EnterScope();
   Dart_Handle live = AllocateOldString("live");
   EXPECT_VALID(live);
@@ -3827,7 +3827,7 @@
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
-    EXPECT_EQ(0, isolate->heap()->ExternalInWords(Heap::kOld));
+    EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
   }
   const intptr_t kSmallExternalSize = 1 * KB;
   {
@@ -3843,7 +3843,7 @@
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
     EXPECT_EQ(kSmallExternalSize,
-              isolate->heap()->ExternalInWords(Heap::kOld) * kWordSize);
+              heap->ExternalInWords(Heap::kOld) * kWordSize);
   }
   // Large enough to trigger GC in old space. Not actually allocated.
   const intptr_t kHugeExternalSize = (kWordSize == 4) ? 513 * MB : 1025 * MB;
@@ -3853,8 +3853,7 @@
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
     // Expect small garbage to be collected.
-    EXPECT_EQ(kHugeExternalSize,
-              isolate->heap()->ExternalInWords(Heap::kOld) * kWordSize);
+    EXPECT_EQ(kHugeExternalSize, heap->ExternalInWords(Heap::kOld) * kWordSize);
   }
   Dart_ExitScope();
   Dart_DeleteWeakPersistentHandle(weak);
@@ -3863,14 +3862,14 @@
 
 TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeOldspaceGC) {
   // Check that external allocation in old space can trigger GC.
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_EnterScope();
   Dart_Handle live = AllocateOldString("live");
   EXPECT_VALID(live);
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
-    EXPECT_EQ(0, isolate->heap()->ExternalInWords(Heap::kOld));
+    EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
   }
   const intptr_t kSmallExternalSize = 1 * KB;
   {
@@ -3884,7 +3883,7 @@
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
     EXPECT_EQ(kSmallExternalSize,
-              isolate->heap()->ExternalInWords(Heap::kOld) * kWordSize);
+              heap->ExternalInWords(Heap::kOld) * kWordSize);
   }
   // Large enough to trigger GC in old space. Not actually allocated.
   const intptr_t kHugeExternalSize = (kWordSize == 4) ? 513 * MB : 1025 * MB;
@@ -3893,14 +3892,13 @@
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
     // Expect small garbage to be collected.
-    EXPECT_EQ(kHugeExternalSize,
-              isolate->heap()->ExternalInWords(Heap::kOld) * kWordSize);
+    EXPECT_EQ(kHugeExternalSize, heap->ExternalInWords(Heap::kOld) * kWordSize);
   }
   Dart_ExitScope();
 }
 
 TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeOddReferents) {
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_WeakPersistentHandle weak1 = NULL;
   static const intptr_t kWeak1ExternalSize = 1 * KB;
   Dart_WeakPersistentHandle weak2 = NULL;
@@ -3934,7 +3932,7 @@
 }
 
 TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeOddReferents) {
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_FinalizableHandle weak1 = nullptr;
   Dart_PersistentHandle strong1 = nullptr;
   static const intptr_t kWeak1ExternalSize = 1 * KB;
@@ -4566,7 +4564,6 @@
 }
 
 TEST_CASE(DartAPI_TypeGetParameterizedTypes) {
-  // TODO(dartbug.com/40176): Clean up this test once the API supports NNBD.
   const char* kScriptChars =
       "class MyClass0<A, B> {\n"
       "}\n"
@@ -4640,7 +4637,10 @@
 
   // Now create objects of the type and validate the object type matches
   // the one returned above. Also get the runtime type of the object and
-  // verify that it matches the type returned above.
+  // verify that it matches the type returned above. Note: we use
+  // Dart_ObjectEquals instead of Dart_IdentityEquals since we are comparing
+  // type literals with non-literals which would fail in unsound null safety
+  // mode.
   // MyClass0<int, double> type.
   Dart_Handle type0_obj = Dart_Invoke(lib, NewString("getMyClass0"), 0, NULL);
   EXPECT_VALID(type0_obj);
@@ -4649,7 +4649,10 @@
   EXPECT(instanceOf);
   type0_obj = Dart_Invoke(lib, NewString("getMyClass0Type"), 0, NULL);
   EXPECT_VALID(type0_obj);
-  EXPECT(Dart_IdentityEquals(type0_obj, myclass0_type));
+
+  bool equal = false;
+  EXPECT_VALID(Dart_ObjectEquals(type0_obj, myclass0_type, &equal));
+  EXPECT(equal);
 
   // MyClass1<List<int>, List> type.
   Dart_Handle type1_obj = Dart_Invoke(lib, NewString("getMyClass1"), 0, NULL);
@@ -4658,7 +4661,9 @@
   EXPECT(instanceOf);
   type1_obj = Dart_Invoke(lib, NewString("getMyClass1Type"), 0, NULL);
   EXPECT_VALID(type1_obj);
-  EXPECT(Dart_IdentityEquals(type1_obj, myclass1_type));
+
+  EXPECT_VALID(Dart_ObjectEquals(type1_obj, myclass1_type, &equal));
+  EXPECT(equal);
 
   // MyClass0<double, int> type.
   type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1"), 0, NULL);
@@ -4667,7 +4672,8 @@
   EXPECT(!instanceOf);
   type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1Type"), 0, NULL);
   EXPECT_VALID(type0_obj);
-  EXPECT(!Dart_IdentityEquals(type0_obj, myclass0_type));
+  EXPECT_VALID(Dart_ObjectEquals(type0_obj, myclass0_type, &equal));
+  EXPECT(!equal);
 
   // MyClass1<List<int>, List<double>> type.
   type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1"), 0, NULL);
@@ -4676,7 +4682,8 @@
   EXPECT(instanceOf);
   type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1Type"), 0, NULL);
   EXPECT_VALID(type1_obj);
-  EXPECT(!Dart_IdentityEquals(type1_obj, myclass1_type));
+  EXPECT_VALID(Dart_ObjectEquals(type1_obj, myclass1_type, &equal));
+  EXPECT(!equal);
 }
 
 static void TestFieldOk(Dart_Handle container,
@@ -5096,7 +5103,7 @@
   // (1 + 2) * kWordSize + size of object header.
   // We check to make sure the instance size computed by the VM matches
   // our expectations.
-  intptr_t header_size = sizeof(ObjectLayout);
+  intptr_t header_size = sizeof(UntaggedObject);
   EXPECT_EQ(
       Utils::RoundUp(((1 + 2) * kWordSize) + header_size, kObjectAlignment),
       cls.host_instance_size());
@@ -8281,17 +8288,17 @@
 // the peer and checks that the count of peer objects is decremented
 // by one.
 TEST_CASE(DartAPI_OneNewSpacePeer) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_Handle str = NewString("a string");
   EXPECT_VALID(str);
   EXPECT(Dart_IsString(str));
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
   void* out = &out;
   EXPECT_VALID(Dart_GetPeer(str, &out));
   EXPECT(out == NULL);
   int peer = 1234;
   EXPECT_VALID(Dart_SetPeer(str, &peer));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   out = &out;
   EXPECT_VALID(Dart_GetPeer(str, &out));
   EXPECT(out == reinterpret_cast<void*>(&peer));
@@ -8299,34 +8306,34 @@
   out = &out;
   EXPECT_VALID(Dart_GetPeer(str, &out));
   EXPECT(out == NULL);
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
 }
 
 // Allocates an object in new space and assigns it a peer.  Allows the
 // peer referent to be garbage collected and checks that the count of
 // peer objects is decremented by one.
 TEST_CASE(DartAPI_CollectOneNewSpacePeer) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_EnterScope();
   {
     CHECK_API_SCOPE(thread);
     Dart_Handle str = NewString("a string");
     EXPECT_VALID(str);
     EXPECT(Dart_IsString(str));
-    EXPECT_EQ(0, isolate->heap()->PeerCount());
+    EXPECT_EQ(0, heap->PeerCount());
     void* out = &out;
     EXPECT_VALID(Dart_GetPeer(str, &out));
     EXPECT(out == NULL);
     int peer = 1234;
     EXPECT_VALID(Dart_SetPeer(str, &peer));
-    EXPECT_EQ(1, isolate->heap()->PeerCount());
+    EXPECT_EQ(1, heap->PeerCount());
     out = &out;
     EXPECT_VALID(Dart_GetPeer(str, &out));
     EXPECT(out == reinterpret_cast<void*>(&peer));
     {
       TransitionNativeToVM transition(thread);
       GCTestHelper::CollectNewSpace();
-      EXPECT_EQ(1, isolate->heap()->PeerCount());
+      EXPECT_EQ(1, heap->PeerCount());
     }
     out = &out;
     EXPECT_VALID(Dart_GetPeer(str, &out));
@@ -8336,7 +8343,7 @@
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::CollectNewSpace();
-    EXPECT_EQ(0, isolate->heap()->PeerCount());
+    EXPECT_EQ(0, heap->PeerCount());
   }
 }
 
@@ -8344,37 +8351,37 @@
 // the peers and checks that the count of peer objects is decremented
 // by two.
 TEST_CASE(DartAPI_TwoNewSpacePeers) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_Handle s1 = NewString("s1");
   EXPECT_VALID(s1);
   EXPECT(Dart_IsString(s1));
   void* o1 = &o1;
   EXPECT_VALID(Dart_GetPeer(s1, &o1));
   EXPECT(o1 == NULL);
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
   int p1 = 1234;
   EXPECT_VALID(Dart_SetPeer(s1, &p1));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   EXPECT_VALID(Dart_GetPeer(s1, &o1));
   EXPECT(o1 == reinterpret_cast<void*>(&p1));
   Dart_Handle s2 = NewString("a string");
   EXPECT_VALID(s2);
   EXPECT(Dart_IsString(s2));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   void* o2 = &o2;
   EXPECT(Dart_GetPeer(s2, &o2));
   EXPECT(o2 == NULL);
   int p2 = 5678;
   EXPECT_VALID(Dart_SetPeer(s2, &p2));
-  EXPECT_EQ(2, isolate->heap()->PeerCount());
+  EXPECT_EQ(2, heap->PeerCount());
   EXPECT_VALID(Dart_GetPeer(s2, &o2));
   EXPECT(o2 == reinterpret_cast<void*>(&p2));
   EXPECT_VALID(Dart_SetPeer(s1, NULL));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   EXPECT(Dart_GetPeer(s1, &o1));
   EXPECT(o1 == NULL);
   EXPECT_VALID(Dart_SetPeer(s2, NULL));
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
   EXPECT(Dart_GetPeer(s2, &o2));
   EXPECT(o2 == NULL);
 }
@@ -8383,32 +8390,32 @@
 // the peer referents to be garbage collected and check that the count
 // of peer objects is decremented by two.
 TEST_CASE(DartAPI_CollectTwoNewSpacePeers) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_EnterScope();
   {
     CHECK_API_SCOPE(thread);
     Dart_Handle s1 = NewString("s1");
     EXPECT_VALID(s1);
     EXPECT(Dart_IsString(s1));
-    EXPECT_EQ(0, isolate->heap()->PeerCount());
+    EXPECT_EQ(0, heap->PeerCount());
     void* o1 = &o1;
     EXPECT(Dart_GetPeer(s1, &o1));
     EXPECT(o1 == NULL);
     int p1 = 1234;
     EXPECT_VALID(Dart_SetPeer(s1, &p1));
-    EXPECT_EQ(1, isolate->heap()->PeerCount());
+    EXPECT_EQ(1, heap->PeerCount());
     EXPECT_VALID(Dart_GetPeer(s1, &o1));
     EXPECT(o1 == reinterpret_cast<void*>(&p1));
     Dart_Handle s2 = NewString("s2");
     EXPECT_VALID(s2);
     EXPECT(Dart_IsString(s2));
-    EXPECT_EQ(1, isolate->heap()->PeerCount());
+    EXPECT_EQ(1, heap->PeerCount());
     void* o2 = &o2;
     EXPECT(Dart_GetPeer(s2, &o2));
     EXPECT(o2 == NULL);
     int p2 = 5678;
     EXPECT_VALID(Dart_SetPeer(s2, &p2));
-    EXPECT_EQ(2, isolate->heap()->PeerCount());
+    EXPECT_EQ(2, heap->PeerCount());
     EXPECT_VALID(Dart_GetPeer(s2, &o2));
     EXPECT(o2 == reinterpret_cast<void*>(&p2));
   }
@@ -8416,7 +8423,7 @@
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::CollectNewSpace();
-    EXPECT_EQ(0, isolate->heap()->PeerCount());
+    EXPECT_EQ(0, heap->PeerCount());
   }
 }
 
@@ -8424,7 +8431,7 @@
 // garbage collections and checks that the peer count is stable.
 TEST_CASE(DartAPI_CopyNewSpacePeers) {
   const int kPeerCount = 10;
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_Handle s[kPeerCount];
   for (int i = 0; i < kPeerCount; ++i) {
     s[i] = NewString("a string");
@@ -8434,22 +8441,22 @@
     EXPECT_VALID(Dart_GetPeer(s[i], &o));
     EXPECT(o == NULL);
   }
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
   int p[kPeerCount];
   for (int i = 0; i < kPeerCount; ++i) {
     EXPECT_VALID(Dart_SetPeer(s[i], &p[i]));
-    EXPECT_EQ(i + 1, isolate->heap()->PeerCount());
+    EXPECT_EQ(i + 1, heap->PeerCount());
     void* o = &o;
     EXPECT_VALID(Dart_GetPeer(s[i], &o));
     EXPECT(o == reinterpret_cast<void*>(&p[i]));
   }
-  EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
+  EXPECT_EQ(kPeerCount, heap->PeerCount());
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::CollectNewSpace();
-    EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
+    EXPECT_EQ(kPeerCount, heap->PeerCount());
     GCTestHelper::CollectNewSpace();
-    EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
+    EXPECT_EQ(kPeerCount, heap->PeerCount());
   }
 }
 
@@ -8457,11 +8464,11 @@
 // the peer to old space.  Removes the peer and check that the count
 // of peer objects is decremented by one.
 TEST_CASE(DartAPI_OnePromotedPeer) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_Handle str = NewString("a string");
   EXPECT_VALID(str);
   EXPECT(Dart_IsString(str));
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
   void* out = &out;
   EXPECT(Dart_GetPeer(str, &out));
   EXPECT(out == NULL);
@@ -8470,7 +8477,7 @@
   out = &out;
   EXPECT(Dart_GetPeer(str, &out));
   EXPECT(out == reinterpret_cast<void*>(&peer));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::CollectNewSpace();
@@ -8486,36 +8493,36 @@
   }
   EXPECT_VALID(Dart_GetPeer(str, &out));
   EXPECT(out == reinterpret_cast<void*>(&peer));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   EXPECT_VALID(Dart_SetPeer(str, NULL));
   out = &out;
   EXPECT_VALID(Dart_GetPeer(str, &out));
   EXPECT(out == NULL);
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
 }
 
 // Allocates an object in old space and assigns it a peer.  Removes
 // the peer and checks that the count of peer objects is decremented
 // by one.
 TEST_CASE(DartAPI_OneOldSpacePeer) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_Handle str = AllocateOldString("str");
   EXPECT_VALID(str);
   EXPECT(Dart_IsString(str));
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
   void* out = &out;
   EXPECT(Dart_GetPeer(str, &out));
   EXPECT(out == NULL);
   int peer = 1234;
   EXPECT_VALID(Dart_SetPeer(str, &peer));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   out = &out;
   EXPECT_VALID(Dart_GetPeer(str, &out));
   EXPECT(out == reinterpret_cast<void*>(&peer));
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::CollectOldSpace();
-    EXPECT_EQ(1, isolate->heap()->PeerCount());
+    EXPECT_EQ(1, heap->PeerCount());
   }
   EXPECT_VALID(Dart_GetPeer(str, &out));
   EXPECT(out == reinterpret_cast<void*>(&peer));
@@ -8523,14 +8530,14 @@
   out = &out;
   EXPECT_VALID(Dart_GetPeer(str, &out));
   EXPECT(out == NULL);
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
 }
 
 // Allocates an object in old space and assigns it a peer.  Allow the
 // peer referent to be garbage collected and check that the count of
 // peer objects is decremented by one.
 TEST_CASE(DartAPI_CollectOneOldSpacePeer) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_EnterScope();
   {
     Thread* T = Thread::Current();
@@ -8538,20 +8545,20 @@
     Dart_Handle str = AllocateOldString("str");
     EXPECT_VALID(str);
     EXPECT(Dart_IsString(str));
-    EXPECT_EQ(0, isolate->heap()->PeerCount());
+    EXPECT_EQ(0, heap->PeerCount());
     void* out = &out;
     EXPECT(Dart_GetPeer(str, &out));
     EXPECT(out == NULL);
     int peer = 1234;
     EXPECT_VALID(Dart_SetPeer(str, &peer));
-    EXPECT_EQ(1, isolate->heap()->PeerCount());
+    EXPECT_EQ(1, heap->PeerCount());
     out = &out;
     EXPECT_VALID(Dart_GetPeer(str, &out));
     EXPECT(out == reinterpret_cast<void*>(&peer));
     {
       TransitionNativeToVM transition(thread);
       GCTestHelper::CollectOldSpace();
-      EXPECT_EQ(1, isolate->heap()->PeerCount());
+      EXPECT_EQ(1, heap->PeerCount());
     }
     EXPECT_VALID(Dart_GetPeer(str, &out));
     EXPECT(out == reinterpret_cast<void*>(&peer));
@@ -8560,7 +8567,7 @@
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::CollectOldSpace();
-    EXPECT_EQ(0, isolate->heap()->PeerCount());
+    EXPECT_EQ(0, heap->PeerCount());
   }
 }
 
@@ -8568,40 +8575,40 @@
 // the peers and checks that the count of peer objects is decremented
 // by two.
 TEST_CASE(DartAPI_TwoOldSpacePeers) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_Handle s1 = AllocateOldString("s1");
   EXPECT_VALID(s1);
   EXPECT(Dart_IsString(s1));
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
   void* o1 = &o1;
   EXPECT(Dart_GetPeer(s1, &o1));
   EXPECT(o1 == NULL);
   int p1 = 1234;
   EXPECT_VALID(Dart_SetPeer(s1, &p1));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   o1 = &o1;
   EXPECT_VALID(Dart_GetPeer(s1, &o1));
   EXPECT(o1 == reinterpret_cast<void*>(&p1));
   Dart_Handle s2 = AllocateOldString("s2");
   EXPECT_VALID(s2);
   EXPECT(Dart_IsString(s2));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   void* o2 = &o2;
   EXPECT(Dart_GetPeer(s2, &o2));
   EXPECT(o2 == NULL);
   int p2 = 5678;
   EXPECT_VALID(Dart_SetPeer(s2, &p2));
-  EXPECT_EQ(2, isolate->heap()->PeerCount());
+  EXPECT_EQ(2, heap->PeerCount());
   o2 = &o2;
   EXPECT_VALID(Dart_GetPeer(s2, &o2));
   EXPECT(o2 == reinterpret_cast<void*>(&p2));
   EXPECT_VALID(Dart_SetPeer(s1, NULL));
-  EXPECT_EQ(1, isolate->heap()->PeerCount());
+  EXPECT_EQ(1, heap->PeerCount());
   o1 = &o1;
   EXPECT(Dart_GetPeer(s1, &o1));
   EXPECT(o1 == NULL);
   EXPECT_VALID(Dart_SetPeer(s2, NULL));
-  EXPECT_EQ(0, isolate->heap()->PeerCount());
+  EXPECT_EQ(0, heap->PeerCount());
   o2 = &o2;
   EXPECT_VALID(Dart_GetPeer(s2, &o2));
   EXPECT(o2 == NULL);
@@ -8611,7 +8618,7 @@
 // the peer referents to be garbage collected and checks that the
 // count of peer objects is decremented by two.
 TEST_CASE(DartAPI_CollectTwoOldSpacePeers) {
-  Isolate* isolate = Isolate::Current();
+  Heap* heap = IsolateGroup::Current()->heap();
   Dart_EnterScope();
   {
     Thread* T = Thread::Current();
@@ -8619,26 +8626,26 @@
     Dart_Handle s1 = AllocateOldString("s1");
     EXPECT_VALID(s1);
     EXPECT(Dart_IsString(s1));
-    EXPECT_EQ(0, isolate->heap()->PeerCount());
+    EXPECT_EQ(0, heap->PeerCount());
     void* o1 = &o1;
     EXPECT(Dart_GetPeer(s1, &o1));
     EXPECT(o1 == NULL);
     int p1 = 1234;
     EXPECT_VALID(Dart_SetPeer(s1, &p1));
-    EXPECT_EQ(1, isolate->heap()->PeerCount());
+    EXPECT_EQ(1, heap->PeerCount());
     o1 = &o1;
     EXPECT_VALID(Dart_GetPeer(s1, &o1));
     EXPECT(o1 == reinterpret_cast<void*>(&p1));
     Dart_Handle s2 = AllocateOldString("s2");
     EXPECT_VALID(s2);
     EXPECT(Dart_IsString(s2));
-    EXPECT_EQ(1, isolate->heap()->PeerCount());
+    EXPECT_EQ(1, heap->PeerCount());
     void* o2 = &o2;
     EXPECT(Dart_GetPeer(s2, &o2));
     EXPECT(o2 == NULL);
     int p2 = 5678;
     EXPECT_VALID(Dart_SetPeer(s2, &p2));
-    EXPECT_EQ(2, isolate->heap()->PeerCount());
+    EXPECT_EQ(2, heap->PeerCount());
     o2 = &o2;
     EXPECT_VALID(Dart_GetPeer(s2, &o2));
     EXPECT(o2 == reinterpret_cast<void*>(&p2));
@@ -8647,7 +8654,7 @@
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::CollectOldSpace();
-    EXPECT_EQ(0, isolate->heap()->PeerCount());
+    EXPECT_EQ(0, heap->PeerCount());
   }
 }
 
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 7c3e3de..73df245 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -195,7 +195,7 @@
   switch (cid) {
     case kOneByteStringCid: {
       OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
-      const char* str = reinterpret_cast<const char*>(raw_str->ptr()->data());
+      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++) {
@@ -331,10 +331,10 @@
 Dart_CObject* ApiMessageReader::CreateDartCObjectString(ObjectPtr raw) {
   ASSERT(IsOneByteStringClassId(raw->GetClassId()));
   OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
-  intptr_t len = Smi::Value(raw_str->ptr()->length());
+  intptr_t len = Smi::Value(raw_str->untag()->length());
   Dart_CObject* object = AllocateDartCObjectString(len);
   char* p = object->value.as_string;
-  memmove(p, raw_str->ptr()->data(), len);
+  memmove(p, raw_str->untag()->data(), len);
   p[len] = '\0';
   return object;
 }
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index b9ba995..0741b90 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -127,9 +127,9 @@
 class LocalHandle {
  public:
   // Accessors.
-  ObjectPtr raw() const { return raw_; }
-  void set_raw(ObjectPtr raw) { raw_ = raw; }
-  static intptr_t raw_offset() { return OFFSET_OF(LocalHandle, raw_); }
+  ObjectPtr ptr() const { return ptr_; }
+  void set_ptr(ObjectPtr ptr) { ptr_ = ptr; }
+  static intptr_t ptr_offset() { return OFFSET_OF(LocalHandle, ptr_); }
 
   Dart_Handle apiHandle() { return reinterpret_cast<Dart_Handle>(this); }
 
@@ -137,7 +137,7 @@
   LocalHandle() {}
   ~LocalHandle() {}
 
-  ObjectPtr raw_;
+  ObjectPtr ptr_;
   DISALLOW_ALLOCATION();  // Allocated through AllocateHandle methods.
   DISALLOW_COPY_AND_ASSIGN(LocalHandle);
 };
@@ -151,16 +151,17 @@
 class PersistentHandle {
  public:
   // Accessors.
-  ObjectPtr raw() const { return raw_; }
-  void set_raw(ObjectPtr ref) { raw_ = ref; }
-  void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); }
-  void set_raw(const Object& object) { raw_ = object.raw(); }
-  ObjectPtr* raw_addr() { return &raw_; }
+  ObjectPtr ptr() const { return ptr_; }
+  void set_ptr(ObjectPtr ref) { ptr_ = ref; }
+  void set_ptr(const LocalHandle& ref) { ptr_ = ref.ptr(); }
+  void set_ptr(const Object& object) { ptr_ = object.ptr(); }
+  ObjectPtr* raw_addr() { return &ptr_; }
+
   Dart_PersistentHandle apiHandle() {
     return reinterpret_cast<Dart_PersistentHandle>(this);
   }
 
-  static intptr_t raw_offset() { return OFFSET_OF(PersistentHandle, raw_); }
+  static intptr_t ptr_offset() { return OFFSET_OF(PersistentHandle, ptr_); }
 
   static PersistentHandle* Cast(Dart_PersistentHandle handle);
 
@@ -170,18 +171,18 @@
   PersistentHandle() {}
   ~PersistentHandle() {}
 
-  // Overload the raw_ field as a next pointer when adding freed
+  // Overload the ptr_ field as a next pointer when adding freed
   // handles to the free list.
   PersistentHandle* Next() {
-    return reinterpret_cast<PersistentHandle*>(static_cast<uword>(raw_));
+    return reinterpret_cast<PersistentHandle*>(static_cast<uword>(ptr_));
   }
   void SetNext(PersistentHandle* free_list) {
-    raw_ = static_cast<ObjectPtr>(reinterpret_cast<uword>(free_list));
-    ASSERT(!raw_->IsHeapObject());
+    ptr_ = static_cast<ObjectPtr>(reinterpret_cast<uword>(free_list));
+    ASSERT(!ptr_->IsHeapObject());
   }
   void FreeHandle(PersistentHandle* free_list) { SetNext(free_list); }
 
-  ObjectPtr raw_;
+  ObjectPtr ptr_;
   DISALLOW_ALLOCATION();  // Allocated through AllocateHandle methods.
   DISALLOW_COPY_AND_ASSIGN(PersistentHandle);
 };
@@ -190,7 +191,7 @@
 // dart API.
 class FinalizablePersistentHandle {
  public:
-  static FinalizablePersistentHandle* New(Isolate* isolate,
+  static FinalizablePersistentHandle* New(IsolateGroup* isolate_group,
                                           const Object& object,
                                           void* peer,
                                           Dart_HandleFinalizer callback,
@@ -198,10 +199,10 @@
                                           bool auto_delete);
 
   // Accessors.
-  ObjectPtr raw() const { return raw_; }
-  ObjectPtr* raw_addr() { return &raw_; }
-  static intptr_t raw_offset() {
-    return OFFSET_OF(FinalizablePersistentHandle, raw_);
+  ObjectPtr ptr() const { return ptr_; }
+  ObjectPtr* ptr_addr() { return &ptr_; }
+  static intptr_t ptr_offset() {
+    return OFFSET_OF(FinalizablePersistentHandle, ptr_);
   }
   void* peer() const { return peer_; }
   Dart_HandleFinalizer callback() const { return callback_; }
@@ -215,7 +216,7 @@
   bool auto_delete() const { return auto_delete_; }
 
   bool IsFinalizedNotFreed() const {
-    return raw_ == static_cast<ObjectPtr>(reinterpret_cast<uword>(this));
+    return ptr_ == static_cast<ObjectPtr>(reinterpret_cast<uword>(this));
   }
 
   intptr_t external_size() const {
@@ -287,21 +288,21 @@
   friend class FinalizablePersistentHandles;
 
   FinalizablePersistentHandle()
-      : raw_(nullptr), peer_(NULL), external_data_(0), callback_(NULL) {}
+      : ptr_(nullptr), peer_(NULL), external_data_(0), callback_(NULL) {}
   ~FinalizablePersistentHandle() {}
 
   static void Finalize(IsolateGroup* isolate_group,
                        FinalizablePersistentHandle* handle);
 
-  // Overload the raw_ field as a next pointer when adding freed
+  // Overload the ptr_ field as a next pointer when adding freed
   // handles to the free list.
   FinalizablePersistentHandle* Next() {
     return reinterpret_cast<FinalizablePersistentHandle*>(
-        static_cast<uword>(raw_));
+        static_cast<uword>(ptr_));
   }
   void SetNext(FinalizablePersistentHandle* free_list) {
-    raw_ = static_cast<ObjectPtr>(reinterpret_cast<uword>(free_list));
-    ASSERT(!raw_->IsHeapObject());
+    ptr_ = static_cast<ObjectPtr>(reinterpret_cast<uword>(free_list));
+    ASSERT(!ptr_->IsHeapObject());
   }
 
   void SetFinalizedNotFreed() {
@@ -315,16 +316,16 @@
   }
 
   void Clear() {
-    raw_ = Object::null();
+    ptr_ = Object::null();
     peer_ = nullptr;
     external_data_ = 0;
     callback_ = nullptr;
     auto_delete_ = false;
   }
 
-  void set_raw(ObjectPtr raw) { raw_ = raw; }
-  void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); }
-  void set_raw(const Object& object) { raw_ = object.raw(); }
+  void set_ptr(ObjectPtr raw) { ptr_ = raw; }
+  void set_ptr(const LocalHandle& ref) { ptr_ = ref.ptr(); }
+  void set_ptr(const Object& object) { ptr_ = object.ptr(); }
 
   void set_peer(void* peer) { peer_ = peer; }
 
@@ -354,10 +355,10 @@
   // Returns the space to charge for the external size.
   Heap::Space SpaceForExternal() const {
     // Non-heap and VM-heap objects count as old space here.
-    return raw_->IsSmiOrOldObject() ? Heap::kOld : Heap::kNew;
+    return ptr_->IsSmiOrOldObject() ? Heap::kOld : Heap::kNew;
   }
 
-  ObjectPtr raw_;
+  ObjectPtr ptr_;
   void* peer_;
   uword external_data_;
   Dart_HandleFinalizer callback_;
@@ -483,7 +484,7 @@
     } else {
       handle = reinterpret_cast<PersistentHandle*>(AllocateScopedHandle());
     }
-    handle->set_raw(Object::null());
+    handle->set_ptr(Object::null());
     return handle;
   }
 
@@ -561,7 +562,7 @@
     if (free_list_ != NULL) {
       handle = free_list_;
       free_list_ = handle->Next();
-      handle->set_raw(Object::null());
+      handle->set_ptr(Object::null());
       return handle;
     }
 
@@ -828,7 +829,7 @@
     MutexLocker ml(&mutex_);
     if (acquired_error_ == nullptr) {
       acquired_error_ = persistent_handles_.AllocateHandle();
-      acquired_error_->set_raw(ApiError::typed_data_acquire_error());
+      acquired_error_->set_ptr(ApiError::typed_data_acquire_error());
     }
     return acquired_error_;
   }
@@ -864,21 +865,21 @@
 };
 
 inline FinalizablePersistentHandle* FinalizablePersistentHandle::New(
-    Isolate* isolate,
+    IsolateGroup* isolate_group,
     const Object& object,
     void* peer,
     Dart_HandleFinalizer callback,
     intptr_t external_size,
     bool auto_delete) {
-  ApiState* state = isolate->group()->api_state();
+  ApiState* state = isolate_group->api_state();
   ASSERT(state != NULL);
   FinalizablePersistentHandle* ref = state->AllocateWeakPersistentHandle();
-  ref->set_raw(object);
+  ref->set_ptr(object);
   ref->set_peer(peer);
   ref->set_callback(callback);
   ref->set_auto_delete(auto_delete);
   // This may trigger GC, so it must be called last.
-  ref->SetExternalSize(external_size, isolate->group());
+  ref->SetExternalSize(external_size, isolate_group);
   return ref;
 }
 
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 8761060..4f201b3 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -110,7 +110,7 @@
     if (FLAG_use_bare_instructions) {
       Thread* thread = Thread::Current();
       thread->set_global_object_pool(
-          thread->isolate()->object_store()->global_object_pool());
+          thread->isolate_group()->object_store()->global_object_pool());
       const DispatchTable* dispatch_table = thread->isolate()->dispatch_table();
       if (dispatch_table != nullptr) {
         thread->set_dispatch_table_array(dispatch_table->ArrayOrigin());
@@ -134,7 +134,7 @@
     const Object& result =
         Object::Handle(zone, Compiler::CompileFunction(thread, function));
     if (result.IsError()) {
-      return Error::Cast(result).raw();
+      return Error::Cast(result).ptr();
     }
 
     // At this point we should have native code.
@@ -164,7 +164,7 @@
                                 Thread* thread) {
   ASSERT(!code.IsNull());
   ASSERT(thread->no_callback_scope_depth() == 0);
-  ASSERT(!Isolate::Current()->null_safety_not_set());
+  ASSERT(!IsolateGroup::Current()->null_safety_not_set());
 
   invokestub entrypoint =
       reinterpret_cast<invokestub>(StubCode::InvokeDartCode().EntryPoint());
@@ -185,7 +185,7 @@
 ObjectPtr DartEntry::ResolveCallable(Thread* thread,
                                      const Array& arguments,
                                      const Array& arguments_descriptor) {
-  auto isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   auto zone = thread->zone();
 
   const ArgumentsDescriptor args_desc(arguments_descriptor);
@@ -211,7 +211,7 @@
       }
 
       if (matches) {
-        return function.raw();
+        return function.ptr();
       }
     }
 
@@ -229,8 +229,8 @@
       break;
     }
     if (!OSThread::Current()->HasStackHeadroom()) {
-      const Instance& exception =
-          Instance::Handle(zone, isolate->object_store()->stack_overflow());
+      const Instance& exception = Instance::Handle(
+          zone, isolate_group->object_store()->stack_overflow());
       return UnhandledException::New(exception, StackTrace::Handle(zone));
     }
 
@@ -239,7 +239,7 @@
     const Object& getter_result = Object::Handle(
         zone, DartEntry::InvokeFunction(function, getter_arguments));
     if (getter_result.IsError()) {
-      return getter_result.raw();
+      return getter_result.ptr();
     }
     ASSERT(getter_result.IsNull() || getter_result.IsInstance());
 
@@ -299,11 +299,11 @@
   const Object& resolved_result = Object::Handle(
       zone, ResolveCallable(thread, arguments, arguments_descriptor));
   if (resolved_result.IsError()) {
-    return resolved_result.raw();
+    return resolved_result.ptr();
   }
 
   const auto& function =
-      Function::Handle(zone, Function::RawCast(resolved_result.raw()));
+      Function::Handle(zone, Function::RawCast(resolved_result.ptr()));
   return InvokeCallable(thread, function, arguments, arguments_descriptor);
 }
 
@@ -314,7 +314,7 @@
                                         const Array& arguments_descriptor) {
   auto const zone = thread->zone();
   const ArgumentsDescriptor args_desc(arguments_descriptor);
-  ASSERT(receiver.raw() == arguments.At(args_desc.FirstArgIndex()));
+  ASSERT(receiver.ptr() == arguments.At(args_desc.FirstArgIndex()));
   // Allocate an Invocation object.
   const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
 
@@ -355,7 +355,8 @@
     ASSERT(!FLAG_lazy_dispatchers);
     // If noSuchMethod(invocation) is not found, call Object::noSuchMethod.
     function = Resolver::ResolveDynamicForReceiverClass(
-        Class::Handle(zone, thread->isolate()->object_store()->object_class()),
+        Class::Handle(zone,
+                      thread->isolate_group()->object_store()->object_class()),
         Symbols::NoSuchMethod(), nsm_args_desc);
   }
   ASSERT(!function.IsNull());
@@ -388,7 +389,7 @@
       kFirstNamedEntryIndex + (index * kNamedEntrySize) + kNameOffset;
   String& result = String::Handle();
   result ^= array_.At(offset);
-  return result.raw();
+  return result.ptr();
 }
 
 intptr_t ArgumentsDescriptor::PositionAt(intptr_t index) const {
@@ -399,7 +400,7 @@
 
 bool ArgumentsDescriptor::MatchesNameAt(intptr_t index,
                                         const String& other) const {
-  return NameAt(index) == other.raw();
+  return NameAt(index) == other.ptr();
 }
 
 ArrayPtr ArgumentsDescriptor::GetArgumentNames() const {
@@ -419,7 +420,7 @@
     ASSERT(names.At(index) == Object::null());
     names.SetAt(index, name);
   }
-  return names.raw();
+  return names.ptr();
 }
 
 void ArgumentsDescriptor::PrintTo(BaseTextBuffer* buffer) const {
@@ -515,7 +516,7 @@
   descriptor.MakeImmutable();
   descriptor ^= descriptor.Canonicalize(thread);
   ASSERT(!descriptor.IsNull());
-  return descriptor.raw();
+  return descriptor.ptr();
 }
 
 ArrayPtr ArgumentsDescriptor::New(intptr_t type_args_len,
@@ -570,7 +571,7 @@
     descriptor ^= descriptor.Canonicalize(thread);
   }
   ASSERT(!descriptor.IsNull());
-  return descriptor.raw();
+  return descriptor.ptr();
 }
 
 void ArgumentsDescriptor::Init() {
@@ -614,9 +615,9 @@
       DartEntry::InvokeFunction(constructor, constructor_arguments));
   ASSERT(retval.IsNull() || retval.IsError());
   if (retval.IsError()) {
-    return retval.raw();
+    return retval.ptr();
   }
-  return exception_object.raw();
+  return exception_object.ptr();
 }
 
 ObjectPtr DartLibraryCalls::ToString(const Instance& receiver) {
@@ -635,7 +636,7 @@
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, args));
   ASSERT(result.IsInstance() || result.IsError());
-  return result.raw();
+  return result.ptr();
 }
 
 ObjectPtr DartLibraryCalls::HashCode(const Instance& receiver) {
@@ -651,7 +652,7 @@
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, args));
   ASSERT(result.IsInstance() || result.IsError());
-  return result.raw();
+  return result.ptr();
 }
 
 ObjectPtr DartLibraryCalls::Equals(const Instance& left,
@@ -670,10 +671,10 @@
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, args));
   ASSERT(result.IsInstance() || result.IsError());
-  return result.raw();
+  return result.ptr();
 }
 
-// On success, returns a RawInstance.  On failure, a RawError.
+// On success, returns an InstancePtr.  On failure, an ErrorPtr.
 ObjectPtr DartLibraryCalls::IdentityHashCode(const Instance& object) {
   const int kNumArguments = 1;
   Thread* thread = Thread::Current();
@@ -688,14 +689,14 @@
   const Object& result =
       Object::Handle(zone, DartEntry::InvokeFunction(function, args));
   ASSERT(result.IsInstance() || result.IsError());
-  return result.raw();
+  return result.ptr();
 }
 
 ObjectPtr DartLibraryCalls::LookupHandler(Dart_Port port_id) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Function& function = Function::Handle(
-      zone, thread->isolate()->object_store()->lookup_port_handler());
+      zone, thread->isolate_group()->object_store()->lookup_port_handler());
   const int kTypeArgsLen = 0;
   const int kNumArguments = 1;
   if (function.IsNull()) {
@@ -709,7 +710,7 @@
                                        kTypeArgsLen, kNumArguments,
                                        Object::empty_array());
     ASSERT(!function.IsNull());
-    thread->isolate()->object_store()->set_lookup_port_handler(function);
+    thread->isolate_group()->object_store()->set_lookup_port_handler(function);
   }
   Array& args = Array::Handle(
       zone, thread->isolate()->isolate_object_store()->dart_args_1());
@@ -720,14 +721,14 @@
   args.SetAt(0, Integer::Handle(zone, Integer::New(port_id)));
   const Object& result =
       Object::Handle(zone, DartEntry::InvokeFunction(function, args));
-  return result.raw();
+  return result.ptr();
 }
 
 ObjectPtr DartLibraryCalls::LookupOpenPorts() {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Function& function = Function::Handle(
-      zone, thread->isolate()->object_store()->lookup_open_ports());
+      zone, thread->isolate_group()->object_store()->lookup_open_ports());
   const int kTypeArgsLen = 0;
   const int kNumArguments = 0;
   if (function.IsNull()) {
@@ -741,20 +742,21 @@
                                        kTypeArgsLen, kNumArguments,
                                        Object::empty_array());
     ASSERT(!function.IsNull());
-    thread->isolate()->object_store()->set_lookup_open_ports(function);
+    thread->isolate_group()->object_store()->set_lookup_open_ports(function);
   }
   const Object& result = Object::Handle(
       zone, DartEntry::InvokeFunction(function, Object::empty_array()));
-  return result.raw();
+  return result.ptr();
 }
 
 ObjectPtr DartLibraryCalls::HandleMessage(const Object& handler,
                                           const Instance& message) {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  Function& function = Function::Handle(
-      zone, isolate->object_store()->handle_message_function());
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto isolate = thread->isolate();
+  auto object_store = thread->isolate_group()->object_store();
+  Function& function =
+      Function::Handle(zone, object_store->handle_message_function());
   const int kTypeArgsLen = 0;
   const int kNumArguments = 2;
   if (function.IsNull()) {
@@ -768,13 +770,13 @@
                                        kTypeArgsLen, kNumArguments,
                                        Object::empty_array());
     ASSERT(!function.IsNull());
-    isolate->object_store()->set_handle_message_function(function);
+    object_store->set_handle_message_function(function);
   }
-  Array& args = Array::Handle(
-      zone, thread->isolate()->isolate_object_store()->dart_args_2());
+  Array& args =
+      Array::Handle(zone, isolate->isolate_object_store()->dart_args_2());
   if (args.IsNull()) {
     args = Array::New(kNumArguments);
-    thread->isolate()->isolate_object_store()->set_dart_args_2(args);
+    isolate->isolate_object_store()->set_dart_args_2(args);
   }
   args.SetAt(0, handler);
   args.SetAt(1, message);
@@ -789,7 +791,7 @@
   const Object& result =
       Object::Handle(zone, DartEntry::InvokeFunction(function, args));
   ASSERT(result.IsNull() || result.IsError());
-  return result.raw();
+  return result.ptr();
 }
 
 ObjectPtr DartLibraryCalls::DrainMicrotaskQueue() {
@@ -802,7 +804,7 @@
   const Object& result = Object::Handle(
       zone, DartEntry::InvokeFunction(function, Object::empty_array()));
   ASSERT(result.IsNull() || result.IsError());
-  return result.raw();
+  return result.ptr();
 }
 
 ObjectPtr DartLibraryCalls::EnsureScheduleImmediate() {
@@ -816,7 +818,7 @@
   const Object& result = Object::Handle(
       zone, DartEntry::InvokeFunction(function, Object::empty_array()));
   ASSERT(result.IsNull() || result.IsError());
-  return result.raw();
+  return result.ptr();
 }
 
 ObjectPtr DartLibraryCalls::MapSetAt(const Instance& map,
@@ -835,7 +837,7 @@
   args.SetAt(2, value);
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, args));
-  return result.raw();
+  return result.ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index c85f683..cfd0c06 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -185,21 +185,21 @@
  public:
   // Invokes the specified instance function or static function.
   // The first argument of an instance function is the receiver.
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr.  On failure, an ErrorPtr.
   // This is used when there is no type argument vector and
   // no named arguments in the call.
   static ObjectPtr InvokeFunction(const Function& function,
                                   const Array& arguments);
 
   // Invokes the specified code as if it was a Dart function.
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr.  On failure, an ErrorPtr.
   static ObjectPtr InvokeCode(const Code& code,
                               const Array& arguments_descriptor,
                               const Array& arguments,
                               Thread* thread);
 
   // Invokes the specified instance, static, or closure function.
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr.  On failure, an ErrorPtr.
   static ObjectPtr InvokeFunction(
       const Function& function,
       const Array& arguments,
@@ -210,7 +210,7 @@
   // object, performing any needed dynamic checks if the callable cannot receive
   // dynamic invocation.
   //
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr.  On failure, an ErrorPtr.
   //
   // Used when an ArgumentsDescriptor is not required, that is, when there
   // are no type arguments or named arguments.
@@ -220,13 +220,13 @@
   // object, performing any needed dynamic checks if the callable cannot receive
   // dynamic invocation.
   //
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr.  On failure, an ErrorPtr.
   static ObjectPtr InvokeClosure(Thread* thread,
                                  const Array& arguments,
                                  const Array& arguments_descriptor);
 
   // Invokes the noSuchMethod instance function on the receiver.
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr.  On failure, an ErrorPtr.
   static ObjectPtr InvokeNoSuchMethod(Thread* thread,
                                       const Instance& receiver,
                                       const String& target_name,
@@ -241,7 +241,7 @@
   // callable or, if Function::null() is returned, an appropriate target for
   // invoking noSuchMethod.
   //
-  // On success, returns a RawFunction. On failure, a RawError.
+  // On success, returns a FunctionPtr. On failure, an ErrorPtr.
   static ObjectPtr ResolveCallable(Thread* thread,
                                    const Array& arguments,
                                    const Array& arguments_descriptor);
@@ -250,7 +250,7 @@
   // checks needed if the function cannot receive dynamic invocation. Helper
   // method used within InvokeClosure.
   //
-  // On success, returns a RawInstance. On failure, a RawError.
+  // On success, returns an InstancePtr. On failure, an ErrorPtr.
   static ObjectPtr InvokeCallable(Thread* thread,
                                   const Function& callable_function,
                                   const Array& arguments,
@@ -261,22 +261,22 @@
 // Each may return an exception object.
 class DartLibraryCalls : public AllStatic {
  public:
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr. On failure, an ErrorPtr.
   static ObjectPtr InstanceCreate(const Library& library,
                                   const String& exception_name,
                                   const String& constructor_name,
                                   const Array& arguments);
 
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr. On failure, an ErrorPtr.
   static ObjectPtr ToString(const Instance& receiver);
 
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr. On failure, an ErrorPtr.
   static ObjectPtr HashCode(const Instance& receiver);
 
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr. On failure, an ErrorPtr.
   static ObjectPtr Equals(const Instance& left, const Instance& right);
 
-  // On success, returns a RawInstance.  On failure, a RawError.
+  // On success, returns an InstancePtr. On failure, an ErrorPtr.
   static ObjectPtr IdentityHashCode(const Instance& object);
 
   // Returns the handler if one has been registered for this port id.
@@ -285,21 +285,21 @@
   // Returns a list of open ReceivePorts.
   static ObjectPtr LookupOpenPorts();
 
-  // Returns null on success, a RawError on failure.
+  // Returns null on success, an ErrorPtr on failure.
   static ObjectPtr HandleMessage(const Object& handler,
                                  const Instance& dart_message);
 
-  // Returns null on success, a RawError on failure.
+  // Returns null on success, an ErrorPtr on failure.
   static ObjectPtr DrainMicrotaskQueue();
 
   // Ensures that the isolate's _pendingImmediateCallback is set to
   // _startMicrotaskLoop from dart:async.
-  // Returns null on success, a RawError on failure.
+  // Returns null on success, an ErrorPtr on failure.
   static ObjectPtr EnsureScheduleImmediate();
 
   // map[key] = value;
   //
-  // Returns null on success, a RawError on failure.
+  // Returns null on success, an ErrorPtr on failure.
   static ObjectPtr MapSetAt(const Instance& map,
                             const Instance& key,
                             const Instance& value);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index d1096d7..7f6775d 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -6,6 +6,7 @@
 
 #include "include/dart_api.h"
 
+#include "vm/closure_functions_cache.h"
 #include "vm/code_descriptors.h"
 #include "vm/code_patcher.h"
 #include "vm/compiler/api/deopt_id.h"
@@ -61,7 +62,7 @@
                                        TokenPosition end_token_pos,
                                        intptr_t requested_line_number,
                                        intptr_t requested_column_number)
-    : script_(script.raw()),
+    : script_(script.ptr()),
       url_(script.url()),
       token_pos_(token_pos),
       end_token_pos_(end_token_pos),
@@ -80,7 +81,7 @@
                                        intptr_t requested_line_number,
                                        intptr_t requested_column_number)
     : script_(Script::null()),
-      url_(url.raw()),
+      url_(url.ptr()),
       token_pos_(TokenPosition::kNoSource),
       end_token_pos_(TokenPosition::kNoSource),
       next_(NULL),
@@ -109,10 +110,9 @@
                                      TokenPosition token_pos) {
   ASSERT(!IsLatent());
   ASSERT(func.script() == script_);
-  ASSERT((func.token_pos() <= token_pos) &&
-         (token_pos <= func.end_token_pos()));
+  ASSERT(token_pos.IsWithin(func.token_pos(), func.end_token_pos()));
   ASSERT(func.is_debuggable());
-  function_ = func.raw();
+  function_ = func.ptr();
   token_pos_ = token_pos;
   end_token_pos_ = token_pos;
   code_token_pos_ = token_pos;
@@ -184,7 +184,7 @@
       fp_(fp),
       sp_(sp),
       ctx_(Context::ZoneHandle()),
-      code_(Code::ZoneHandle(code.raw())),
+      code_(Code::ZoneHandle(code.ptr())),
       function_(Function::ZoneHandle(code.function())),
       live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
       token_pos_initialized_(false),
@@ -194,7 +194,7 @@
       line_number_(-1),
       column_number_(-1),
       context_level_(-1),
-      deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
+      deopt_frame_(Array::ZoneHandle(deopt_frame.ptr())),
       deopt_frame_offset_(deopt_frame_offset),
       kind_(kind),
       vars_initialized_(false),
@@ -365,7 +365,7 @@
   if (!for_over_await) {
     bpt = breakpoints();
     while (bpt != NULL) {
-      if (bpt->IsPerClosure() && (bpt->closure() == closure.raw())) break;
+      if (bpt->IsPerClosure() && (bpt->closure() == closure.ptr())) break;
       bpt = bpt->next();
     }
   }
@@ -394,26 +394,25 @@
                              const Script& script,
                              TokenPosition token_pos,
                              TokenPosition end_token_pos) {
-  TokenPosition func_start = func.token_pos();
-  if (((func_start <= token_pos) && (token_pos <= func.end_token_pos())) ||
-      ((token_pos <= func_start) && (func_start <= end_token_pos))) {
-    // Check script equality second because it allocates
-    // handles as a side effect.
-    return func.script() == script.raw();
+  const TokenPosition& func_start = func.token_pos();
+  if (token_pos.IsWithin(func_start, func.end_token_pos()) ||
+      func_start.IsWithin(token_pos, end_token_pos)) {
+    // Check script equality last because it allocates handles as a side effect.
+    return func.script() == script.ptr();
   }
   return false;
 }
 
 static bool IsImplicitFunction(const Function& func) {
   switch (func.kind()) {
-    case FunctionLayout::kImplicitGetter:
-    case FunctionLayout::kImplicitSetter:
-    case FunctionLayout::kImplicitStaticGetter:
-    case FunctionLayout::kFieldInitializer:
-    case FunctionLayout::kMethodExtractor:
-    case FunctionLayout::kNoSuchMethodDispatcher:
-    case FunctionLayout::kInvokeFieldDispatcher:
-    case FunctionLayout::kIrregexpFunction:
+    case UntaggedFunction::kImplicitGetter:
+    case UntaggedFunction::kImplicitSetter:
+    case UntaggedFunction::kImplicitStaticGetter:
+    case UntaggedFunction::kFieldInitializer:
+    case UntaggedFunction::kMethodExtractor:
+    case UntaggedFunction::kNoSuchMethodDispatcher:
+    case UntaggedFunction::kInvokeFieldDispatcher:
+    case UntaggedFunction::kIrregexpFunction:
       return true;
     default:
       if (func.token_pos() == func.end_token_pos()) {
@@ -444,7 +443,7 @@
   }
   CodeBreakpoint* cbpt = code_breakpoints_;
   while (cbpt != NULL) {
-    if (func.raw() == cbpt->function()) {
+    if (func.ptr() == cbpt->function()) {
       return true;
     }
     cbpt = cbpt->next_;
@@ -455,7 +454,7 @@
 bool Debugger::HasBreakpoint(const Code& code) {
   CodeBreakpoint* cbpt = code_breakpoints_;
   while (cbpt != NULL) {
-    if (code.raw() == cbpt->code_) {
+    if (code.ptr() == cbpt->code_) {
       return true;
     }
     cbpt = cbpt->next_;
@@ -536,7 +535,7 @@
     token_pos_initialized_ = true;
     token_pos_ = TokenPosition::kNoSource;
     GetPcDescriptors();
-    PcDescriptors::Iterator iter(pc_desc_, PcDescriptorsLayout::kAnyKind);
+    PcDescriptors::Iterator iter(pc_desc_, UntaggedPcDescriptors::kAnyKind);
     const uword pc_offset = pc_ - code().PayloadStart();
     while (iter.MoveNext()) {
       if (iter.PcOffset() == pc_offset) {
@@ -566,24 +565,20 @@
 
 intptr_t ActivationFrame::LineNumber() {
   // Compute line number lazily since it causes scanning of the script.
-  if ((line_number_ < 0) && TokenPos().IsSourcePosition()) {
-    const TokenPosition token_pos = TokenPos().SourcePosition();
+  const TokenPosition& token_pos = TokenPos();
+  if ((line_number_ < 0) && token_pos.IsReal()) {
     const Script& script = Script::Handle(SourceScript());
-    script.GetTokenLocation(token_pos, &line_number_, NULL);
+    script.GetTokenLocation(token_pos, &line_number_, &column_number_);
   }
   return line_number_;
 }
 
 intptr_t ActivationFrame::ColumnNumber() {
   // Compute column number lazily since it causes scanning of the script.
-  if ((column_number_ < 0) && TokenPos().IsSourcePosition()) {
-    const TokenPosition token_pos = TokenPos().SourcePosition();
+  const TokenPosition& token_pos = TokenPos();
+  if ((column_number_ < 0) && token_pos.IsReal()) {
     const Script& script = Script::Handle(SourceScript());
-    if (script.HasSource()) {
-      script.GetTokenLocation(token_pos, &line_number_, &column_number_);
-    } else {
-      column_number_ = -1;
-    }
+    script.GetTokenLocation(token_pos, &line_number_, &column_number_);
   }
   return column_number_;
 }
@@ -648,13 +643,14 @@
     }
     intptr_t var_desc_len = var_descriptors_.Length();
     bool found = false;
+    // We store the deopt ids as real token positions.
+    const auto to_compare = TokenPosition::Deserialize(deopt_id);
     for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
-      LocalVarDescriptorsLayout::VarInfo var_info;
+      UntaggedLocalVarDescriptors::VarInfo var_info;
       var_descriptors_.GetInfo(cur_idx, &var_info);
       const int8_t kind = var_info.kind();
-      if ((kind == LocalVarDescriptorsLayout::kContextLevel) &&
-          (deopt_id >= var_info.begin_pos.value()) &&
-          (deopt_id <= var_info.end_pos.value())) {
+      if ((kind == UntaggedLocalVarDescriptors::kContextLevel) &&
+          to_compare.IsWithin(var_info.begin_pos, var_info.end_pos)) {
         context_level_ = var_info.index();
         found = true;
         break;
@@ -677,18 +673,18 @@
   intptr_t ctxt_slot = -1;
   intptr_t var_desc_len = var_descriptors_.Length();
   for (intptr_t i = 0; i < var_desc_len; i++) {
-    LocalVarDescriptorsLayout::VarInfo var_info;
+    UntaggedLocalVarDescriptors::VarInfo var_info;
     var_descriptors_.GetInfo(i, &var_info);
-    if (var_descriptors_.GetName(i) == name.raw()) {
+    if (var_descriptors_.GetName(i) == name.ptr()) {
       const int8_t kind = var_info.kind();
       if (!live_frame_) {
-        ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
+        ASSERT(kind == UntaggedLocalVarDescriptors::kContextVar);
       }
       const auto variable_index = VariableIndex(var_info.index());
-      if (kind == LocalVarDescriptorsLayout::kStackVar) {
+      if (kind == UntaggedLocalVarDescriptors::kStackVar) {
         return GetStackVar(variable_index);
       } else {
-        ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
+        ASSERT(kind == UntaggedLocalVarDescriptors::kContextVar);
         var_ctxt_level = var_info.scope_id;
         ctxt_slot = variable_index.value();
         break;
@@ -724,7 +720,7 @@
 
     if (!closure.IsNull() && caller_closure_finder->IsRunningAsync(closure)) {
       closure = caller_closure_finder->FindCaller(closure);
-      return closure.raw();
+      return closure.ptr();
     }
   }
 
@@ -782,11 +778,11 @@
   intptr_t var_desc_len = var_descriptors_.Length();
   intptr_t await_jump_var = -1;
   for (intptr_t i = 0; i < var_desc_len; i++) {
-    LocalVarDescriptorsLayout::VarInfo var_info;
+    UntaggedLocalVarDescriptors::VarInfo var_info;
     var_descriptors_.GetInfo(i, &var_info);
     const int8_t kind = var_info.kind();
-    if (var_descriptors_.GetName(i) == Symbols::AwaitJumpVar().raw()) {
-      ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
+    if (var_descriptors_.GetName(i) == Symbols::AwaitJumpVar().ptr()) {
+      ASSERT(kind == UntaggedLocalVarDescriptors::kContextVar);
       ASSERT(!ctx_.IsNull());
       var_ctxt_level = var_info.scope_id;
       ctxt_slot = var_info.index();
@@ -818,7 +814,7 @@
   const auto& pc_descriptors =
       PcDescriptors::Handle(zone, code().pc_descriptors());
   ASSERT(!pc_descriptors.IsNull());
-  PcDescriptors::Iterator it(pc_descriptors, PcDescriptorsLayout::kOther);
+  PcDescriptors::Iterator it(pc_descriptors, UntaggedPcDescriptors::kOther);
   while (it.MoveNext()) {
     if (it.YieldIndex() == await_jump_var) {
       try_index_ = it.TryIndex();
@@ -831,13 +827,14 @@
 
 bool ActivationFrame::IsAsyncMachinery() const {
   ASSERT(!function_.IsNull());
-  Isolate* isolate = Isolate::Current();
-  if (function_.raw() == isolate->object_store()->complete_on_async_return()) {
+  auto isolate_group = IsolateGroup::Current();
+  if (function_.ptr() ==
+      isolate_group->object_store()->complete_on_async_return()) {
     // We are completing an async function's completer.
     return true;
   }
   if (function_.Owner() ==
-      isolate->object_store()->async_star_stream_controller()) {
+      isolate_group->object_store()->async_star_stream_controller()) {
     // We are inside the async* stream controller code.
     return true;
   }
@@ -851,10 +848,10 @@
   intptr_t var_desc_len = var_descriptors_.Length();
   Object& obj = Object::Handle();
   for (intptr_t i = 0; i < var_desc_len; i++) {
-    LocalVarDescriptorsLayout::VarInfo var_info;
+    UntaggedLocalVarDescriptors::VarInfo var_info;
     var_descriptors_.GetInfo(i, &var_info);
     const int8_t kind = var_info.kind();
-    if (kind == LocalVarDescriptorsLayout::kSavedCurrentContext) {
+    if (kind == UntaggedLocalVarDescriptors::kSavedCurrentContext) {
       if (FLAG_trace_debugger_stacktrace) {
         OS::PrintErr("\tFound saved current ctx at index %d\n",
                      var_info.index());
@@ -862,14 +859,14 @@
       const auto variable_index = VariableIndex(var_info.index());
       obj = GetStackVar(variable_index);
       if (obj.IsClosure()) {
-        ASSERT(function().name() == Symbols::Call().raw());
+        ASSERT(function().name() == Symbols::Call().ptr());
         ASSERT(function().IsInvokeFieldDispatcher());
         // Closure.call frames.
         ctx_ = Closure::Cast(obj).context();
       } else if (obj.IsContext()) {
-        ctx_ = Context::Cast(obj).raw();
+        ctx_ = Context::Cast(obj).ptr();
       } else {
-        ASSERT(obj.IsNull() || obj.raw() == Symbols::OptimizedOut().raw());
+        ASSERT(obj.IsNull() || obj.ptr() == Symbols::OptimizedOut().ptr());
         ctx_ = Context::null();
       }
       return ctx_;
@@ -879,7 +876,7 @@
 }
 
 ObjectPtr ActivationFrame::GetAsyncOperation() {
-  if (function().name() == Symbols::AsyncOperation().raw()) {
+  if (function().name() == Symbols::AsyncOperation().ptr()) {
     return GetParameter(0);
   }
   return Object::null();
@@ -918,58 +915,58 @@
   intptr_t var_desc_len = var_descriptors_.Length();
   for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
     ASSERT(var_names.length() == desc_indices_.length());
-    LocalVarDescriptorsLayout::VarInfo var_info;
+    UntaggedLocalVarDescriptors::VarInfo var_info;
     var_descriptors_.GetInfo(cur_idx, &var_info);
     const int8_t kind = var_info.kind();
-    if ((kind != LocalVarDescriptorsLayout::kStackVar) &&
-        (kind != LocalVarDescriptorsLayout::kContextVar)) {
+    if ((kind != UntaggedLocalVarDescriptors::kStackVar) &&
+        (kind != UntaggedLocalVarDescriptors::kContextVar)) {
       continue;
     }
-    if ((var_info.begin_pos <= activation_token_pos) &&
-        (activation_token_pos <= var_info.end_pos)) {
-      if ((kind == LocalVarDescriptorsLayout::kContextVar) &&
-          (ContextLevel() < var_info.scope_id)) {
-        // The variable is textually in scope but the context level
-        // at the activation frame's PC is lower than the context
-        // level of the variable. The context containing the variable
-        // has already been removed from the chain. This can happen when we
-        // break at a return statement, since the contexts get discarded
-        // before the debugger gets called.
-        continue;
-      }
-      // The current variable is textually in scope. Now check whether
-      // there is another local variable with the same name that shadows
-      // or is shadowed by this variable.
-      String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
-      intptr_t indices_len = desc_indices_.length();
-      bool name_match_found = false;
-      for (intptr_t i = 0; i < indices_len; i++) {
-        if (var_name.Equals(*var_names[i])) {
-          // Found two local variables with the same name. Now determine
-          // which one is shadowed.
-          name_match_found = true;
-          LocalVarDescriptorsLayout::VarInfo i_var_info;
-          var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
-          if (i_var_info.begin_pos < var_info.begin_pos) {
-            // The variable we found earlier is in an outer scope
-            // and is shadowed by the current variable. Replace the
-            // descriptor index of the previously found variable
-            // with the descriptor index of the current variable.
-            desc_indices_[i] = cur_idx;
-          } else {
-            // The variable we found earlier is in an inner scope
-            // and shadows the current variable. Skip the current
-            // variable. (Nothing to do.)
-          }
-          break;  // Stop looking for name matches.
+    if (!activation_token_pos.IsWithin(var_info.begin_pos, var_info.end_pos)) {
+      continue;
+    }
+    if ((kind == UntaggedLocalVarDescriptors::kContextVar) &&
+        (ContextLevel() < var_info.scope_id)) {
+      // The variable is textually in scope but the context level
+      // at the activation frame's PC is lower than the context
+      // level of the variable. The context containing the variable
+      // has already been removed from the chain. This can happen when we
+      // break at a return statement, since the contexts get discarded
+      // before the debugger gets called.
+      continue;
+    }
+    // The current variable is textually in scope. Now check whether
+    // there is another local variable with the same name that shadows
+    // or is shadowed by this variable.
+    String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
+    intptr_t indices_len = desc_indices_.length();
+    bool name_match_found = false;
+    for (intptr_t i = 0; i < indices_len; i++) {
+      if (var_name.Equals(*var_names[i])) {
+        // Found two local variables with the same name. Now determine
+        // which one is shadowed.
+        name_match_found = true;
+        UntaggedLocalVarDescriptors::VarInfo i_var_info;
+        var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
+        if (i_var_info.begin_pos < var_info.begin_pos) {
+          // The variable we found earlier is in an outer scope
+          // and is shadowed by the current variable. Replace the
+          // descriptor index of the previously found variable
+          // with the descriptor index of the current variable.
+          desc_indices_[i] = cur_idx;
+        } else {
+          // The variable we found earlier is in an inner scope
+          // and shadows the current variable. Skip the current
+          // variable. (Nothing to do.)
         }
+        break;  // Stop looking for name matches.
       }
-      if (!name_match_found) {
-        // No duplicate name found. Add the current descriptor index to the
-        // list of visible variables.
-        desc_indices_.Add(cur_idx);
-        var_names.Add(&var_name);
-      }
+    }
+    if (!name_match_found) {
+      // No duplicate name found. Add the current descriptor index to the
+      // list of visible variables.
+      desc_indices_.Add(cur_idx);
+      var_names.Add(&var_name);
     }
   }
   vars_initialized_ = true;
@@ -1028,7 +1025,7 @@
   Object& obj = Object::Handle();
   for (int i = 0; i < deopt_frame_.Length(); i++) {
     obj = deopt_frame_.At(i);
-    if (obj.raw() == Symbols::OptimizedOut().raw()) {
+    if (obj.ptr() == Symbols::OptimizedOut().ptr()) {
       return false;
     }
   }
@@ -1096,7 +1093,7 @@
 
   *name = var_descriptors_.GetName(desc_index);
 
-  LocalVarDescriptorsLayout::VarInfo var_info;
+  UntaggedLocalVarDescriptors::VarInfo var_info;
   var_descriptors_.GetInfo(desc_index, &var_info);
   ASSERT(declaration_token_pos != NULL);
   *declaration_token_pos = var_info.declaration_pos;
@@ -1107,10 +1104,10 @@
   ASSERT(value != NULL);
   const int8_t kind = var_info.kind();
   const auto variable_index = VariableIndex(var_info.index());
-  if (kind == LocalVarDescriptorsLayout::kStackVar) {
+  if (kind == UntaggedLocalVarDescriptors::kStackVar) {
     *value = GetStackVar(variable_index);
   } else {
-    ASSERT(kind == LocalVarDescriptorsLayout::kContextVar);
+    ASSERT(kind == UntaggedLocalVarDescriptors::kContextVar);
     *value = GetContextVar(var_info.scope_id, variable_index.value());
   }
 }
@@ -1131,7 +1128,7 @@
   // It's possible that ctx was optimized out as no locals were captured by the
   // context. See issue #38182.
   if (ctx.IsNull()) {
-    return Symbols::OptimizedOut().raw();
+    return Symbols::OptimizedOut().ptr();
   }
 
   intptr_t level_diff = frame_ctx_level - var_ctx_level;
@@ -1142,7 +1139,7 @@
     ASSERT((ctx_slot >= 0) && (ctx_slot < ctx.num_variables()));
     return ctx.At(ctx_slot);
   } else if (level_diff > 0) {
-    Context& var_ctx = Context::Handle(ctx.raw());
+    Context& var_ctx = Context::Handle(ctx.ptr());
     while (level_diff > 0 && !var_ctx.IsNull()) {
       level_diff--;
       var_ctx = var_ctx.parent();
@@ -1167,12 +1164,12 @@
   Object& value = Instance::Handle();
   const Array& list = Array::Handle(Array::New(2 * num_variables));
   for (intptr_t i = 0; i < num_variables; i++) {
-    TokenPosition ignore;
+    TokenPosition ignore = TokenPosition::kNoSource;
     VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
     list.SetAt(2 * i, var_name);
     list.SetAt((2 * i) + 1, value);
   }
-  return list.raw();
+  return list.ptr();
 }
 
 ObjectPtr ActivationFrame::GetReceiver() {
@@ -1181,13 +1178,13 @@
   String& var_name = String::Handle();
   Instance& value = Instance::Handle();
   for (intptr_t i = 0; i < num_variables; i++) {
-    TokenPosition ignore;
+    TokenPosition ignore = TokenPosition::kNoSource;
     VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
     if (var_name.Equals(Symbols::This())) {
-      return value.raw();
+      return value.ptr();
     }
   }
-  return Symbols::OptimizedOut().raw();
+  return Symbols::OptimizedOut().ptr();
 }
 
 static bool IsSyntheticVariableName(const String& var_name) {
@@ -1232,11 +1229,11 @@
   TypeArguments& type_arguments = TypeArguments::Handle();
   intptr_t num_variables = desc_indices_.length();
   for (intptr_t i = 0; i < num_variables; i++) {
-    TokenPosition ignore;
+    TokenPosition ignore = TokenPosition::kNoSource;
     VariableAt(i, &name, &ignore, &ignore, &ignore, &value);
     if (name.Equals(Symbols::FunctionTypeArgumentsVar())) {
       type_arguments_available = true;
-      type_arguments ^= value.raw();
+      type_arguments ^= value.ptr();
     } else if (!name.Equals(Symbols::This()) &&
                !IsSyntheticVariableName(name)) {
       if (IsPrivateVariableName(name)) {
@@ -1262,18 +1259,18 @@
 
   if ((function().IsGeneric() || function().HasGenericParent()) &&
       type_arguments_available) {
-    intptr_t num_vars =
-        function().NumTypeParameters() + function().NumParentTypeParameters();
+    intptr_t num_vars = function().NumTypeArguments();
     type_params_names.Grow(num_vars);
     type_params_names.SetLength(num_vars);
     TypeArguments& type_params = TypeArguments::Handle();
     TypeParameter& type_param = TypeParameter::Handle();
-    Function& current = Function::Handle(function().raw());
+    Function& current = Function::Handle(function().ptr());
     intptr_t mapping_offset = num_vars;
     for (intptr_t i = 0; !current.IsNull(); i += current.NumTypeParameters(),
                   current = current.parent_function()) {
       type_params = current.type_parameters();
       intptr_t size = current.NumTypeParameters();
+      ASSERT(size == 0 || type_params.Length() == size);
       ASSERT(mapping_offset >= size);
       mapping_offset -= size;
       for (intptr_t j = 0; j < size; ++j) {
@@ -1297,7 +1294,7 @@
     }
   }
 
-  return type_arguments.raw();
+  return type_arguments.ptr();
 }
 
 const char* ActivationFrame::ToCString() {
@@ -1347,7 +1344,7 @@
   const Script& script = Script::Handle(SourceScript());
   jsobj->AddProperty("type", "Frame");
   jsobj->AddProperty("kind", KindToCString(kind_));
-  const TokenPosition pos = TokenPos().SourcePosition();
+  const TokenPosition& pos = TokenPos();
   jsobj->AddLocation(script, pos);
   jsobj->AddProperty("function", function());
   jsobj->AddProperty("code", code());
@@ -1357,9 +1354,9 @@
     for (intptr_t v = 0; v < num_vars; v++) {
       String& var_name = String::Handle();
       Instance& var_value = Instance::Handle();
-      TokenPosition declaration_token_pos;
-      TokenPosition visible_start_token_pos;
-      TokenPosition visible_end_token_pos;
+      TokenPosition declaration_token_pos = TokenPosition::kNoSource;
+      TokenPosition visible_start_token_pos = TokenPosition::kNoSource;
+      TokenPosition visible_end_token_pos = TokenPosition::kNoSource;
       VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos,
                  &visible_end_token_pos, &var_value);
       if (!IsSyntheticVariableName(var_name)) {
@@ -1383,7 +1380,7 @@
   jsobj->AddProperty("type", "Frame");
   jsobj->AddProperty("kind", KindToCString(kind_));
   const Script& script = Script::Handle(SourceScript());
-  const TokenPosition pos = TokenPos().SourcePosition();
+  const TokenPosition& pos = TokenPos();
   jsobj->AddLocation(script, pos);
   jsobj->AddProperty("function", function());
   jsobj->AddProperty("code", code());
@@ -1416,15 +1413,15 @@
                                  ActivationFrame::kAsyncCausal));
 }
 
-const uint8_t kSafepointKind = PcDescriptorsLayout::kIcCall |
-                               PcDescriptorsLayout::kUnoptStaticCall |
-                               PcDescriptorsLayout::kRuntimeCall;
+const uint8_t kSafepointKind = UntaggedPcDescriptors::kIcCall |
+                               UntaggedPcDescriptors::kUnoptStaticCall |
+                               UntaggedPcDescriptors::kRuntimeCall;
 
 CodeBreakpoint::CodeBreakpoint(const Code& code,
                                TokenPosition token_pos,
                                uword pc,
-                               PcDescriptorsLayout::Kind kind)
-    : code_(code.raw()),
+                               UntaggedPcDescriptors::Kind kind)
+    : code_(code.ptr()),
       token_pos_(token_pos),
       pc_(pc),
       line_number_(-1),
@@ -1448,7 +1445,7 @@
   pc_ = 0ul;
   bpt_location_ = NULL;
   next_ = NULL;
-  breakpoint_kind_ = PcDescriptorsLayout::kOther;
+  breakpoint_kind_ = UntaggedPcDescriptors::kOther;
 #endif
 }
 
@@ -1470,7 +1467,7 @@
   // Compute line number lazily since it causes scanning of the script.
   if (line_number_ < 0) {
     const Script& script = Script::Handle(SourceCode());
-    script.GetTokenLocation(token_pos_, &line_number_, NULL);
+    script.GetTokenLocation(token_pos_, &line_number_);
   }
   return line_number_;
 }
@@ -1622,13 +1619,13 @@
 
   // Iterate over all classes, deoptimize functions.
   // TODO(hausner): Could possibly be combined with RemoveOptimizedCode()
-  const ClassTable& class_table = *isolate_->class_table();
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
+  const ClassTable& class_table = *isolate_->group()->class_table();
+  auto thread = Thread::Current();
+  auto isolate_group = thread->isolate_group();
+  auto zone = thread->zone();
   CallSiteResetter resetter(zone);
   Class& cls = Class::Handle(zone);
   Array& functions = Array::Handle(zone);
-  GrowableObjectArray& closures = GrowableObjectArray::Handle(zone);
   Function& function = Function::Handle(zone);
   Code& code = Code::Handle(zone);
 
@@ -1636,7 +1633,7 @@
   const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
   // TODO(dartbug.com/36097): Need to stop other mutators running in same IG
   // before deoptimizing the world.
-  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
   for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
     const classid_t cid =
         i < num_classes ? i : ClassTable::CidFromTopLevelIndex(i - num_classes);
@@ -1680,11 +1677,7 @@
   }
 
   // Disable optimized closure functions.
-  closures = isolate_->object_store()->closure_functions();
-  const intptr_t num_closures = closures.Length();
-  for (intptr_t pos = 0; pos < num_closures; pos++) {
-    function ^= closures.At(pos);
-    ASSERT(!function.IsNull());
+  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& function) {
     if (function.HasOptimizedCode()) {
       function.SwitchToUnoptimizedCode();
     }
@@ -1692,7 +1685,8 @@
     if (!code.IsNull()) {
       resetter.ResetSwitchableCalls(code);
     }
-  }
+    return true;  // Continue iteration.
+  });
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -1739,7 +1733,7 @@
   isolate->set_deopt_context(NULL);
   delete deopt_context;
 
-  return dest_frame.raw();
+  return dest_frame.ptr();
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -1864,7 +1858,7 @@
   for (intptr_t i = 0; i < length; ++i) {
     code ^= code_array.At(i);
 
-    if (code.raw() == StubCode::AsynchronousGapMarker().raw()) {
+    if (code.ptr() == StubCode::AsynchronousGapMarker().ptr()) {
       stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
       // Once we reach a gap, the rest is async.
       async_frames = true;
@@ -2048,7 +2042,7 @@
       break;
     }
 
-    async_activation = Closure::RawCast(next_async_activation.raw());
+    async_activation = Closure::RawCast(next_async_activation.ptr());
   }
 
   return stack_trace;
@@ -2118,11 +2112,11 @@
     // fewer frames that the pre-allocated trace (such as memory exhaustion with
     // a shallow stack).
     if (!code_object.IsNull()) {
-      code ^= code_object.raw();
+      code ^= code_object.ptr();
       ASSERT(code.IsFunctionCode());
       function = code.function();
       if (function.is_visible()) {
-        ASSERT(function.raw() == code.function());
+        ASSERT(function.ptr() == code.function());
         uword pc =
             code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
         if (code.is_optimized() && ex_trace.expand_inlined()) {
@@ -2131,7 +2125,7 @@
                it.Advance()) {
             function = it.function();
             code = it.code();
-            ASSERT(function.raw() == code.function());
+            ASSERT(function.ptr() == code.function());
             uword pc = it.pc();
             ASSERT(pc != 0);
             ASSERT(code.PayloadStart() <= pc);
@@ -2178,7 +2172,7 @@
     return false;
   }
   ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception);
-  if (handler_frame == NULL) {
+  if (handler_frame == nullptr) {
     // Did not find an exception handler that catches this exception.
     // Note that this check is not precise, since we can't check
     // uninstantiated types, i.e. types containing type parameters.
@@ -2186,6 +2180,14 @@
     // it will be caught once we unwind the stack.
     return true;
   }
+  // If handler_frame's function is annotated with
+  // @pragma('vm:notify-debugger-on-exception'), we specifically want to notify
+  // the debugger of this otherwise ignored exception.
+  if (Library::FindPragma(Thread::Current(), /*only_core=*/false,
+                          handler_frame->function(),
+                          Symbols::vm_notify_debugger_on_exception())) {
+    return true;
+  }
   return false;
 }
 
@@ -2239,16 +2241,15 @@
   intptr_t token_start_column = -1;
   intptr_t token_line = -1;
   if (requested_column >= 0) {
-    TokenPosition ignored;
-    TokenPosition end_of_line_pos;
+    TokenPosition ignored = TokenPosition::kNoSource;
+    TokenPosition end_of_line_pos = TokenPosition::kNoSource;
     script.GetTokenLocation(pos, &token_line, &token_start_column);
     script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
     TokenPosition token_end_pos =
-        (end_of_line_pos < next_closest_token_position)
-            ? end_of_line_pos
-            : next_closest_token_position;
+        TokenPosition::Min(next_closest_token_position, end_of_line_pos);
 
-    if ((token_end_pos < exact_token_pos) ||
+    if ((token_end_pos.IsReal() && exact_token_pos.IsReal() &&
+         (token_end_pos < exact_token_pos)) ||
         (token_start_column > *best_column)) {
       // Prefer the token with the lowest column number compatible
       // with the requested column.
@@ -2261,9 +2262,11 @@
     *best_fit_pos = pos;
     *best_line = token_line;
     *best_column = token_start_column;
-    // best_token_pos is only used when column number is specified.
-    *best_token_pos = TokenPosition(exact_token_pos.value() -
-                                    (requested_column - *best_column));
+    // best_token_pos should only be real when the column number is specified.
+    if (requested_column >= 0 && exact_token_pos.IsReal()) {
+      *best_token_pos = TokenPosition::Deserialize(
+          exact_token_pos.Pos() - (requested_column - *best_column));
+    }
   }
 }
 
@@ -2330,12 +2333,9 @@
                                              TokenPosition exact_token_pos) {
   ASSERT(!func.HasOptimizedCode());
 
-  if (requested_token_pos < func.token_pos()) {
-    requested_token_pos = func.token_pos();
-  }
-  if (last_token_pos > func.end_token_pos()) {
-    last_token_pos = func.end_token_pos();
-  }
+  requested_token_pos =
+      TokenPosition::Max(requested_token_pos, func.token_pos());
+  last_token_pos = TokenPosition::Min(last_token_pos, func.end_token_pos());
 
   Zone* zone = Thread::Current()->zone();
   Script& script = Script::Handle(zone, func.script());
@@ -2351,15 +2351,19 @@
   TokenPosition best_fit_pos = TokenPosition::kMaxSource;
   intptr_t best_column = INT_MAX;
   intptr_t best_line = INT_MAX;
-  // best_token_pos and exact_token_pos are only used
-  // if column number is provided.
+  // best_token_pos is only set to a real position if a real exact_token_pos
+  // and a column number are provided.
   TokenPosition best_token_pos = TokenPosition::kNoSource;
 
   PcDescriptors::Iterator iter(desc, kSafepointKind);
   while (iter.MoveNext()) {
-    const TokenPosition pos = iter.TokenPos();
-    if ((!pos.IsReal()) || (pos < requested_token_pos) ||
-        (pos > last_token_pos)) {
+    const TokenPosition& pos = iter.TokenPos();
+    if (pos.IsSynthetic() && pos == requested_token_pos) {
+      // if there's a safepoint for a synthetic function start and the start
+      // was requested, we're done.
+      return pos;
+    }
+    if (!pos.IsWithin(requested_token_pos, last_token_pos)) {
       // Token is not in the target range.
       continue;
     }
@@ -2368,8 +2372,9 @@
       // Find next closest safepoint
       PcDescriptors::Iterator iter2(desc, kSafepointKind);
       while (iter2.MoveNext()) {
-        const TokenPosition next = iter2.TokenPos();
-        if (next < next_closest_token_position && next > pos) {
+        const TokenPosition& next = iter2.TokenPos();
+        if (!next.IsReal()) continue;
+        if ((pos < next) && (next < next_closest_token_position)) {
           next_closest_token_position = next;
         }
       }
@@ -2384,33 +2389,31 @@
   // the token on the line which is at the best fit column (if column
   // was specified) and has the lowest code address.
   if (best_fit_pos != TokenPosition::kMaxSource) {
+    ASSERT(best_fit_pos.IsReal());
     const Script& script = Script::Handle(zone, func.script());
     const TokenPosition begin_pos = best_fit_pos;
 
-    TokenPosition end_of_line_pos;
-    if (best_line == -1) {
-      script.GetTokenLocation(begin_pos, &best_line, NULL);
+    TokenPosition end_of_line_pos = TokenPosition::kNoSource;
+    if (best_line < 0) {
+      script.GetTokenLocation(begin_pos, &best_line);
     }
     ASSERT(best_line > 0);
-    TokenPosition ignored;
+    TokenPosition ignored = TokenPosition::kNoSource;
     script.TokenRangeAtLine(best_line, &ignored, &end_of_line_pos);
-    if (end_of_line_pos < begin_pos) {
-      end_of_line_pos = begin_pos;
-    }
+    end_of_line_pos = TokenPosition::Max(end_of_line_pos, begin_pos);
 
     uword lowest_pc_offset = kUwordMax;
     PcDescriptors::Iterator iter(desc, kSafepointKind);
     while (iter.MoveNext()) {
-      const TokenPosition pos = iter.TokenPos();
-      if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
-        // Token is not on same line as best fit.
-        continue;
-      }
-
-      if (requested_column >= 0) {
+      const TokenPosition& pos = iter.TokenPos();
+      if (best_token_pos.IsReal()) {
         if (pos != best_token_pos) {
+          // Not an match for the requested column.
           continue;
         }
+      } else if (!pos.IsWithin(begin_pos, end_of_line_pos)) {
+        // Token is not on same line as best fit.
+        continue;
       }
 
       // Prefer the lowest pc offset.
@@ -2443,7 +2446,7 @@
   ASSERT(!code.IsNull());
   PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
   uword lowest_pc_offset = kUwordMax;
-  PcDescriptorsLayout::Kind lowest_kind = PcDescriptorsLayout::kAnyKind;
+  UntaggedPcDescriptors::Kind lowest_kind = UntaggedPcDescriptors::kAnyKind;
   // Find the safe point with the lowest compiled code address
   // that maps to the token position of the source breakpoint.
   PcDescriptors::Iterator iter(desc, kSafepointKind);
@@ -2482,38 +2485,27 @@
     TokenPosition start_pos,
     TokenPosition end_pos,
     GrowableObjectArray* code_function_list) {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  Class& cls = Class::Handle(zone);
-  Array& functions = Array::Handle(zone);
-  GrowableObjectArray& closures = GrowableObjectArray::Handle(zone);
-  Function& function = Function::Handle(zone);
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
 
-  closures = isolate_->object_store()->closure_functions();
-  const intptr_t num_closures = closures.Length();
-  for (intptr_t pos = 0; pos < num_closures; pos++) {
-    function ^= closures.At(pos);
+  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& function) {
     ASSERT(!function.IsNull());
     if ((function.token_pos() == start_pos) &&
         (function.end_token_pos() == end_pos) &&
-        (function.script() == script.raw())) {
-      if (function.is_debuggable()) {
-        if (function.HasCode()) {
-          code_function_list->Add(function);
-        }
+        (function.script() == script.ptr())) {
+      if (function.is_debuggable() && function.HasCode()) {
+        code_function_list->Add(function);
       }
-      if (function.HasImplicitClosureFunction()) {
-        function = function.ImplicitClosureFunction();
-        if (function.is_debuggable()) {
-          if (function.HasCode()) {
-            code_function_list->Add(function);
-          }
-        }
-      }
+      ASSERT(!function.HasImplicitClosureFunction());
     }
-  }
+    return true;  // Continue iteration.
+  });
 
-  const ClassTable& class_table = *isolate_->class_table();
+  Class& cls = Class::Handle(zone);
+  Function& function = Function::Handle(zone);
+  Array& functions = Array::Handle(zone);
+
+  const ClassTable& class_table = *isolate_->group()->class_table();
   const intptr_t num_classes = class_table.NumCids();
   const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
   for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
@@ -2541,7 +2533,7 @@
           if (function.is_debuggable() && function.HasCode() &&
               function.token_pos() == start_pos &&
               function.end_token_pos() == end_pos &&
-              function.script() == script.raw()) {
+              function.script() == script.ptr()) {
             code_function_list->Add(function);
             function_added = true;
           }
@@ -2557,14 +2549,14 @@
   }
 }
 
-static void SelectBestFit(Function* best_fit, Function* func) {
+static void UpdateBestFit(Function* best_fit, const Function& func) {
   if (best_fit->IsNull()) {
-    *best_fit = func->raw();
-  } else {
-    if ((func->token_pos() > best_fit->token_pos()) &&
-        ((func->end_token_pos() <= best_fit->end_token_pos()))) {
-      *best_fit = func->raw();
-    }
+    *best_fit = func.ptr();
+  } else if ((best_fit->token_pos().IsSynthetic() ||
+              func.token_pos().IsSynthetic() ||
+              (best_fit->token_pos() < func.token_pos())) &&
+             (func.end_token_pos() <= best_fit->end_token_pos())) {
+    *best_fit = func.ptr();
   }
 }
 
@@ -2576,7 +2568,8 @@
                            TokenPosition token_pos,
                            TokenPosition last_token_pos,
                            Function* best_fit) {
-  Thread* thread = Thread::Current();
+  auto thread = Thread::Current();
+  auto isolate_group = thread->isolate_group();
   Zone* zone = thread->zone();
   Class& cls = Class::Handle(zone);
 
@@ -2586,7 +2579,7 @@
   // Return the first fit found, but if a library doesn't contain a fit,
   // process the next one.
   const GrowableObjectArray& libs = GrowableObjectArray::Handle(
-      zone, thread->isolate()->object_store()->libraries());
+      zone, isolate_group->object_store()->libraries());
   Library& lib = Library::Handle(zone);
   for (int i = 0; i < libs.Length(); i++) {
     lib ^= libs.At(i);
@@ -2594,7 +2587,7 @@
     const Array& scripts = Array::Handle(zone, lib.LoadedScripts());
     bool lib_has_script = false;
     for (intptr_t j = 0; j < scripts.Length(); j++) {
-      if (scripts.At(j) == script.raw()) {
+      if (scripts.At(j) == script.ptr()) {
         lib_has_script = true;
         break;
       }
@@ -2610,22 +2603,15 @@
       }
       continue;
     }
-    const GrowableObjectArray& closures = GrowableObjectArray::Handle(
-        zone, isolate_->object_store()->closure_functions());
-    Array& functions = Array::Handle(zone);
-    Function& function = Function::Handle(zone);
-    Array& fields = Array::Handle(zone);
-    Field& field = Field::Handle(zone);
-    Error& error = Error::Handle(zone);
 
-    const intptr_t num_closures = closures.Length();
-    for (intptr_t i = 0; i < num_closures; i++) {
-      function ^= closures.At(i);
-      if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
+    ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& fun) {
+      if (FunctionOverlaps(fun, script, token_pos, last_token_pos)) {
         // Select the inner most closure.
-        SelectBestFit(best_fit, &function);
+        UpdateBestFit(best_fit, fun);
       }
-    }
+      return true;  // Continue iteration
+    });
+
     if (!best_fit->IsNull()) {
       // The inner most closure found will be the best fit. Going
       // over class functions below will not help in any further
@@ -2633,7 +2619,13 @@
       return true;
     }
 
-    const ClassTable& class_table = *isolate_->class_table();
+    Array& functions = Array::Handle(zone);
+    Function& function = Function::Handle(zone);
+    Array& fields = Array::Handle(zone);
+    Field& field = Field::Handle(zone);
+    Error& error = Error::Handle(zone);
+
+    const ClassTable& class_table = *isolate_->group()->class_table();
     const intptr_t num_classes = class_table.NumCids();
     const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
     for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
@@ -2646,7 +2638,7 @@
       cls = class_table.At(cid);
       // This class is relevant to us only if it belongs to the
       // library to which |script| belongs.
-      if (cls.library() != lib.raw()) {
+      if (cls.library() != lib.ptr()) {
         continue;
       }
       // Parse class definition if not done yet.
@@ -2674,7 +2666,7 @@
             // present in the functions of a class. Hence, we can return
             // right away as looking through other functions of a class
             // will not narrow down to any inner function/closure.
-            *best_fit = function.raw();
+            *best_fit = function.ptr();
             return true;
           }
         }
@@ -2688,11 +2680,11 @@
       if (!fields.IsNull()) {
         const intptr_t num_fields = fields.Length();
         for (intptr_t pos = 0; pos < num_fields; pos++) {
-          TokenPosition start;
-          TokenPosition end;
+          TokenPosition start = TokenPosition::kNoSource;
+          TokenPosition end = TokenPosition::kNoSource;
           field ^= fields.At(pos);
           ASSERT(!field.IsNull());
-          if (field.Script() != script.raw()) {
+          if (field.Script() != script.ptr()) {
             // The field should be defined in the script we want to set
             // the breakpoint in.
             continue;
@@ -2702,8 +2694,8 @@
           }
           start = field.token_pos();
           end = field.end_token_pos();
-          if ((start <= token_pos && token_pos <= end) ||
-              (token_pos <= start && start <= last_token_pos)) {
+          if (token_pos.IsWithin(start, end) ||
+              start.IsWithin(token_pos, last_token_pos)) {
             return true;
           }
         }
@@ -2759,8 +2751,8 @@
     MakeCodeBreakpointAt(func, loc);
   }
   if (FLAG_verbose_debug) {
-    intptr_t line_number;
-    intptr_t column_number;
+    intptr_t line_number = -1;
+    intptr_t column_number = -1;
     script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
     OS::PrintErr("Resolved code breakpoint for function '%s' at line %" Pd
                  " col %" Pd "\n",
@@ -2782,7 +2774,7 @@
     }
     // If func was not set (still Null), the best fit is a field.
   } else {
-    func = function.raw();
+    func = function.ptr();
     if (!func.token_pos().IsReal()) {
       return NULL;  // Missing source positions?
     }
@@ -2803,7 +2795,7 @@
       // have already been compiled. We can resolve the breakpoint now.
       // If requested_column is larger than zero, [token_pos, last_token_pos]
       // governs one single line of code.
-      TokenPosition exact_token_pos = TokenPosition(-1);
+      TokenPosition exact_token_pos = TokenPosition::kNoSource;
       if (token_pos != last_token_pos && requested_column >= 0) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
         exact_token_pos =
@@ -2823,8 +2815,8 @@
   // initializer of a field at |token_pos|. Hence, Register an unresolved
   // breakpoint.
   if (FLAG_verbose_debug) {
-    intptr_t line_number;
-    intptr_t column_number;
+    intptr_t line_number = -1;
+    intptr_t column_number = -1;
     script.GetTokenLocation(token_pos, &line_number, &column_number);
     if (func.IsNull()) {
       OS::PrintErr(
@@ -2924,7 +2916,7 @@
     Breakpoint* bpt = loc->breakpoints();
     while (bpt != NULL) {
       if (bpt->IsPerClosure()) {
-        if (closure.raw() == bpt->closure()) {
+        if (closure.ptr() == bpt->closure()) {
           return bpt;
         }
       }
@@ -2974,8 +2966,8 @@
   Zone* zone = Thread::Current()->zone();
   Library& lib = Library::Handle(zone);
   Script& script = Script::Handle(zone);
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(isolate_->object_store()->libraries());
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      isolate_->group()->object_store()->libraries());
   bool is_package = script_url.StartsWith(Symbols::PackageScheme());
   Script& script_for_lib = Script::Handle(zone);
   for (intptr_t i = 0; i < libs.Length(); i++) {
@@ -2987,8 +2979,8 @@
     script_for_lib = lib.LookupScript(script_url, !is_package);
     if (!script_for_lib.IsNull()) {
       if (script.IsNull()) {
-        script = script_for_lib.raw();
-      } else if (script.raw() != script_for_lib.raw()) {
+        script = script_for_lib.ptr();
+      } else if (script.ptr() != script_for_lib.ptr()) {
         if (FLAG_verbose_debug) {
           OS::PrintErr("Multiple scripts match url '%s'\n",
                        script_url.ToCString());
@@ -3010,7 +3002,8 @@
     }
     return latent_bpt;
   }
-  TokenPosition first_token_idx, last_token_idx;
+  TokenPosition first_token_idx = TokenPosition::kNoSource;
+  TokenPosition last_token_idx = TokenPosition::kNoSource;
   script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
   if (!first_token_idx.IsReal()) {
     // Script does not contain the given line number.
@@ -3322,13 +3315,14 @@
   uword pc_offset = return_address - code.PayloadStart();
   const PcDescriptors& descriptors =
       PcDescriptors::Handle(code.pc_descriptors());
-  PcDescriptors::Iterator iter(
-      descriptors, PcDescriptorsLayout::kRewind | PcDescriptorsLayout::kIcCall |
-                       PcDescriptorsLayout::kUnoptStaticCall);
+  PcDescriptors::Iterator iter(descriptors,
+                               UntaggedPcDescriptors::kRewind |
+                                   UntaggedPcDescriptors::kIcCall |
+                                   UntaggedPcDescriptors::kUnoptStaticCall);
   intptr_t rewind_deopt_id = -1;
   uword rewind_pc = 0;
   while (iter.MoveNext()) {
-    if (iter.Kind() == PcDescriptorsLayout::kRewind) {
+    if (iter.Kind() == UntaggedPcDescriptors::kRewind) {
       // Remember the last rewind so we don't need to iterator twice.
       rewind_pc = code.PayloadStart() + iter.PcOffset();
       rewind_deopt_id = iter.DeoptId();
@@ -3530,10 +3524,10 @@
       return false;
     }
     const TokenPosition looking_for = top_frame->TokenPos();
-    PcDescriptors::Iterator it(pc_descriptors, PcDescriptorsLayout::kOther);
+    PcDescriptors::Iterator it(pc_descriptors, UntaggedPcDescriptors::kOther);
     while (it.MoveNext()) {
       if (it.TokenPos() == looking_for &&
-          it.YieldIndex() != PcDescriptorsLayout::kInvalidYieldIndex) {
+          it.YieldIndex() != UntaggedPcDescriptors::kInvalidYieldIndex) {
         return true;
       }
     }
@@ -3612,8 +3606,8 @@
       // Only set breakpoint when entering async_op the first time.
       // :async_future should be uninitialised at this point:
       if (async_future.IsNull()) {
-        const Function& async_op =
-            Function::Handle(frame->function().GetGeneratedClosure());
+        const Function& async_op = Function::Handle(
+            ClosureFunctionsCache::GetUniqueInnerClosure(frame->function()));
         if (!async_op.IsNull()) {
           SetBreakpointAtAsyncOp(async_op);
           // After setting the breakpoint we stop stepping and continue the
@@ -3773,7 +3767,7 @@
       Object& closure = Object::Handle(top_frame->GetClosure());
       ASSERT(closure.IsInstance());
       ASSERT(Instance::Cast(closure).IsClosure());
-      if (closure.raw() == bpt->closure()) {
+      if (closure.ptr() == bpt->closure()) {
         return bpt;
       }
     }
@@ -3825,24 +3819,28 @@
 // the given token position.
 FunctionPtr Debugger::FindInnermostClosure(const Function& function,
                                            TokenPosition token_pos) {
-  Zone* zone = Thread::Current()->zone();
+  ASSERT(function.end_token_pos().IsReal());
+  const TokenPosition& func_start = function.token_pos();
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
   const Script& outer_origin = Script::Handle(zone, function.script());
-  const GrowableObjectArray& closures = GrowableObjectArray::Handle(
-      zone, Isolate::Current()->object_store()->closure_functions());
-  const intptr_t num_closures = closures.Length();
-  Function& closure = Function::Handle(zone);
+
   Function& best_fit = Function::Handle(zone);
-  for (intptr_t i = 0; i < num_closures; i++) {
-    closure ^= closures.At(i);
-    if ((function.token_pos() < closure.token_pos()) &&
-        (closure.end_token_pos() < function.end_token_pos()) &&
-        (closure.token_pos() <= token_pos) &&
-        (token_pos <= closure.end_token_pos()) &&
-        (closure.script() == outer_origin.raw())) {
-      SelectBestFit(&best_fit, &closure);
+  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& closure) {
+    const TokenPosition& closure_start = closure.token_pos();
+    const TokenPosition& closure_end = closure.end_token_pos();
+    // We're only interested in closures that have real ending token positions.
+    // The starting token position can be synthetic.
+    if (closure_end.IsReal() && (function.end_token_pos() > closure_end) &&
+        (!closure_start.IsReal() || !func_start.IsReal() ||
+         (closure_start > func_start)) &&
+        token_pos.IsWithin(closure_start, closure_end) &&
+        (closure.script() == outer_origin.ptr())) {
+      UpdateBestFit(&best_fit, closure);
     }
-  }
-  return best_fit.raw();
+    return true;  // Continue iteration.
+  });
+  return best_fit.ptr();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -3851,13 +3849,13 @@
 TokenPosition Debugger::FindExactTokenPosition(const Script& script,
                                                TokenPosition start_of_line,
                                                intptr_t column_number) {
-  intptr_t line = -1;
-  intptr_t col = -1;
-  Zone* zone = Thread::Current()->zone();
-  kernel::KernelLineStartsReader line_starts_reader(
-      TypedData::Handle(zone, script.line_starts()), zone);
-  line_starts_reader.LocationForPosition(start_of_line.value(), &line, &col);
-  return TokenPosition(start_of_line.value() + (column_number - col));
+  intptr_t line;
+  intptr_t col;
+  if (script.GetTokenLocation(start_of_line, &line, &col)) {
+    return TokenPosition::Deserialize(start_of_line.Pos() +
+                                      (column_number - col));
+  }
+  return TokenPosition::kNoSource;
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -3957,14 +3955,16 @@
     // Common, fast path.
     return;
   }
-  Zone* zone = Thread::Current()->zone();
+  auto thread = Thread::Current();
+  auto isolate_group = thread->isolate_group();
+  auto zone = thread->zone();
   Library& lib = Library::Handle(zone);
   Script& script = Script::Handle(zone);
   String& url = String::Handle(zone);
   BreakpointLocation* loc = latent_locations_;
   BreakpointLocation* prev_loc = NULL;
   const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(isolate_->object_store()->libraries());
+      GrowableObjectArray::Handle(isolate_group->object_store()->libraries());
   while (loc != NULL) {
     url = loc->url();
     bool found_match = false;
@@ -3988,7 +3988,8 @@
         intptr_t line_number = matched_loc->requested_line_number();
         intptr_t column_number = matched_loc->requested_column_number();
         ASSERT(line_number >= 0);
-        TokenPosition first_token_pos, last_token_pos;
+        TokenPosition first_token_pos = TokenPosition::kNoSource;
+        TokenPosition last_token_pos = TokenPosition::kNoSource;
         script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
         if (!first_token_pos.IsDebugPause() || !last_token_pos.IsDebugPause()) {
           // Script does not contain the given line number or there are no
@@ -4222,7 +4223,7 @@
     TokenPosition code_token_pos) {
   BreakpointLocation* loc = breakpoint_locations_;
   while (loc != NULL) {
-    if (loc->script_ == script.raw() &&
+    if (loc->script_ == script.ptr() &&
         (!token_pos.IsReal() || (loc->token_pos_ == token_pos)) &&
         ((requested_line == -1) ||
          (loc->requested_line_number_ == requested_line)) &&
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 0312163..653c38b 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -74,7 +74,7 @@
   void SetIsPerClosure(const Instance& closure) {
     ASSERT(kind_ == kNone);
     kind_ = kPerClosure;
-    closure_ = closure.raw();
+    closure_ = closure.ptr();
   }
 
   // Mark that this breakpoint is a result of a step OverAwait request.
@@ -192,7 +192,7 @@
   CodeBreakpoint(const Code& code,
                  TokenPosition token_pos,
                  uword pc,
-                 PcDescriptorsLayout::Kind kind);
+                 UntaggedPcDescriptors::Kind kind);
   ~CodeBreakpoint();
 
   FunctionPtr function() const;
@@ -230,7 +230,7 @@
   BreakpointLocation* bpt_location_;
   CodeBreakpoint* next_;
 
-  PcDescriptorsLayout::Kind breakpoint_kind_;
+  UntaggedPcDescriptors::Kind breakpoint_kind_;
   CodePtr saved_value_;
 
   friend class Debugger;
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index bcd63b0..7d9d0ab 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -35,7 +35,7 @@
       return Api::NewError("%s expects argument '%s' to be of type %s.",       \
                            CURRENT_FUNC, #param, #type);                       \
     }                                                                          \
-    var ^= tmp.raw();                                                          \
+    var ^= tmp.ptr();                                                          \
   } while (0)
 
 #define CHECK_AND_CAST(type, var, param)                                       \
diff --git a/runtime/vm/debugger_arm.cc b/runtime/vm/debugger_arm.cc
index 9862592..7fe5605 100644
--- a/runtime/vm/debugger_arm.cc
+++ b/runtime/vm/debugger_arm.cc
@@ -23,14 +23,14 @@
   ASSERT(!is_enabled_);
   Code& stub_target = Code::Handle();
   switch (breakpoint_kind_) {
-    case PcDescriptorsLayout::kIcCall:
-      stub_target = StubCode::ICCallBreakpoint().raw();
+    case UntaggedPcDescriptors::kIcCall:
+      stub_target = StubCode::ICCallBreakpoint().ptr();
       break;
-    case PcDescriptorsLayout::kUnoptStaticCall:
-      stub_target = StubCode::UnoptStaticCallBreakpoint().raw();
+    case UntaggedPcDescriptors::kUnoptStaticCall:
+      stub_target = StubCode::UnoptStaticCallBreakpoint().ptr();
       break;
-    case PcDescriptorsLayout::kRuntimeCall:
-      stub_target = StubCode::RuntimeCallBreakpoint().raw();
+    case UntaggedPcDescriptors::kRuntimeCall:
+      stub_target = StubCode::RuntimeCallBreakpoint().ptr();
       break;
     default:
       UNREACHABLE();
@@ -45,9 +45,9 @@
   ASSERT(is_enabled_);
   const Code& code = Code::Handle(code_);
   switch (breakpoint_kind_) {
-    case PcDescriptorsLayout::kIcCall:
-    case PcDescriptorsLayout::kUnoptStaticCall:
-    case PcDescriptorsLayout::kRuntimeCall: {
+    case UntaggedPcDescriptors::kIcCall:
+    case UntaggedPcDescriptors::kUnoptStaticCall:
+    case UntaggedPcDescriptors::kRuntimeCall: {
       CodePatcher::PatchStaticCallAt(pc_, code, Code::Handle(saved_value_));
       break;
     }
diff --git a/runtime/vm/debugger_arm64.cc b/runtime/vm/debugger_arm64.cc
index dc132f8..d3f251b 100644
--- a/runtime/vm/debugger_arm64.cc
+++ b/runtime/vm/debugger_arm64.cc
@@ -23,20 +23,20 @@
   ASSERT(!is_enabled_);
   const Code& code = Code::Handle(code_);
   switch (breakpoint_kind_) {
-    case PcDescriptorsLayout::kIcCall: {
+    case UntaggedPcDescriptors::kIcCall: {
       Object& data = Object::Handle();
       saved_value_ = CodePatcher::GetInstanceCallAt(pc_, code, &data);
       CodePatcher::PatchInstanceCallAt(pc_, code, data,
                                        StubCode::ICCallBreakpoint());
       break;
     }
-    case PcDescriptorsLayout::kUnoptStaticCall: {
+    case UntaggedPcDescriptors::kUnoptStaticCall: {
       saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
       CodePatcher::PatchPoolPointerCallAt(
           pc_, code, StubCode::UnoptStaticCallBreakpoint());
       break;
     }
-    case PcDescriptorsLayout::kRuntimeCall: {
+    case UntaggedPcDescriptors::kRuntimeCall: {
       saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
       CodePatcher::PatchPoolPointerCallAt(pc_, code,
                                           StubCode::RuntimeCallBreakpoint());
@@ -52,15 +52,15 @@
   ASSERT(is_enabled_);
   const Code& code = Code::Handle(code_);
   switch (breakpoint_kind_) {
-    case PcDescriptorsLayout::kIcCall: {
+    case UntaggedPcDescriptors::kIcCall: {
       Object& data = Object::Handle();
       CodePatcher::GetInstanceCallAt(pc_, code, &data);
       CodePatcher::PatchInstanceCallAt(pc_, code, data,
                                        Code::Handle(saved_value_));
       break;
     }
-    case PcDescriptorsLayout::kUnoptStaticCall:
-    case PcDescriptorsLayout::kRuntimeCall: {
+    case UntaggedPcDescriptors::kUnoptStaticCall:
+    case UntaggedPcDescriptors::kRuntimeCall: {
       CodePatcher::PatchPoolPointerCallAt(pc_, code,
                                           Code::Handle(saved_value_));
       break;
diff --git a/runtime/vm/debugger_ia32.cc b/runtime/vm/debugger_ia32.cc
index d580561..f9de84f 100644
--- a/runtime/vm/debugger_ia32.cc
+++ b/runtime/vm/debugger_ia32.cc
@@ -33,17 +33,17 @@
   thread->isolate_group()->RunWithStoppedMutators([&]() {
     WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
     switch (breakpoint_kind_) {
-      case PcDescriptorsLayout::kIcCall: {
-        stub_target = StubCode::ICCallBreakpoint().raw();
+      case UntaggedPcDescriptors::kIcCall: {
+        stub_target = StubCode::ICCallBreakpoint().ptr();
         break;
       }
-      case PcDescriptorsLayout::kUnoptStaticCall: {
-        stub_target = StubCode::UnoptStaticCallBreakpoint().raw();
+      case UntaggedPcDescriptors::kUnoptStaticCall: {
+        stub_target = StubCode::UnoptStaticCallBreakpoint().ptr();
         break;
       }
-      case PcDescriptorsLayout::kRuntimeCall: {
+      case UntaggedPcDescriptors::kRuntimeCall: {
         saved_value_ = CodePatcher::GetStaticCallTargetAt(pc_, code);
-        stub_target = StubCode::RuntimeCallBreakpoint().raw();
+        stub_target = StubCode::RuntimeCallBreakpoint().ptr();
         break;
       }
       default:
@@ -64,9 +64,9 @@
   thread->isolate_group()->RunWithStoppedMutators([&]() {
     WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
     switch (breakpoint_kind_) {
-      case PcDescriptorsLayout::kIcCall:
-      case PcDescriptorsLayout::kUnoptStaticCall:
-      case PcDescriptorsLayout::kRuntimeCall: {
+      case UntaggedPcDescriptors::kIcCall:
+      case UntaggedPcDescriptors::kUnoptStaticCall:
+      case UntaggedPcDescriptors::kRuntimeCall: {
         CodePatcher::PatchStaticCallAt(pc_, code, Code::Handle(saved_value_));
         break;
       }
diff --git a/runtime/vm/debugger_x64.cc b/runtime/vm/debugger_x64.cc
index dfb07df..7a0e046 100644
--- a/runtime/vm/debugger_x64.cc
+++ b/runtime/vm/debugger_x64.cc
@@ -24,14 +24,14 @@
   ASSERT(!is_enabled_);
   Code& stub_target = Code::Handle();
   switch (breakpoint_kind_) {
-    case PcDescriptorsLayout::kIcCall:
-      stub_target = StubCode::ICCallBreakpoint().raw();
+    case UntaggedPcDescriptors::kIcCall:
+      stub_target = StubCode::ICCallBreakpoint().ptr();
       break;
-    case PcDescriptorsLayout::kUnoptStaticCall:
-      stub_target = StubCode::UnoptStaticCallBreakpoint().raw();
+    case UntaggedPcDescriptors::kUnoptStaticCall:
+      stub_target = StubCode::UnoptStaticCallBreakpoint().ptr();
       break;
-    case PcDescriptorsLayout::kRuntimeCall:
-      stub_target = StubCode::RuntimeCallBreakpoint().raw();
+    case UntaggedPcDescriptors::kRuntimeCall:
+      stub_target = StubCode::RuntimeCallBreakpoint().ptr();
       break;
     default:
       UNREACHABLE();
@@ -46,9 +46,9 @@
   ASSERT(is_enabled_);
   const Code& code = Code::Handle(code_);
   switch (breakpoint_kind_) {
-    case PcDescriptorsLayout::kIcCall:
-    case PcDescriptorsLayout::kUnoptStaticCall:
-    case PcDescriptorsLayout::kRuntimeCall: {
+    case UntaggedPcDescriptors::kIcCall:
+    case UntaggedPcDescriptors::kUnoptStaticCall:
+    case UntaggedPcDescriptors::kRuntimeCall: {
       CodePatcher::PatchPoolPointerCallAt(pc_, code,
                                           Code::Handle(saved_value_));
       break;
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index a510fe0..6452f3f 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -32,7 +32,7 @@
   ASSERT(!Smi::IsValid(value()));
   Mint& mint = Mint::Handle();
   mint ^= Integer::New(value());
-  *mint_slot = mint.raw();
+  *mint_slot = mint.ptr();
 
   if (FLAG_trace_deoptimization_verbose) {
     OS::PrintErr("materializing mint at %" Px ": %" Pd64 "\n",
@@ -46,10 +46,10 @@
   *float32x4_slot = raw_float32x4;
 
   if (FLAG_trace_deoptimization_verbose) {
-    float x = raw_float32x4->ptr()->x();
-    float y = raw_float32x4->ptr()->y();
-    float z = raw_float32x4->ptr()->z();
-    float w = raw_float32x4->ptr()->w();
+    float x = raw_float32x4->untag()->x();
+    float y = raw_float32x4->untag()->y();
+    float z = raw_float32x4->untag()->z();
+    float w = raw_float32x4->untag()->w();
     OS::PrintErr("materializing Float32x4 at %" Px ": %g,%g,%g,%g\n",
                  reinterpret_cast<uword>(slot()), x, y, z, w);
   }
@@ -61,8 +61,8 @@
   *float64x2_slot = raw_float64x2;
 
   if (FLAG_trace_deoptimization_verbose) {
-    double x = raw_float64x2->ptr()->x();
-    double y = raw_float64x2->ptr()->y();
+    double x = raw_float64x2->untag()->x();
+    double y = raw_float64x2->untag()->y();
     OS::PrintErr("materializing Float64x2 at %" Px ": %g,%g\n",
                  reinterpret_cast<uword>(slot()), x, y);
   }
@@ -74,10 +74,10 @@
   *int32x4_slot = raw_int32x4;
 
   if (FLAG_trace_deoptimization_verbose) {
-    uint32_t x = raw_int32x4->ptr()->x();
-    uint32_t y = raw_int32x4->ptr()->y();
-    uint32_t z = raw_int32x4->ptr()->z();
-    uint32_t w = raw_int32x4->ptr()->w();
+    uint32_t x = raw_int32x4->untag()->x();
+    uint32_t y = raw_int32x4->untag()->y();
+    uint32_t z = raw_int32x4->untag()->z();
+    uint32_t w = raw_int32x4->untag()->w();
     OS::PrintErr("materializing Int32x4 at %" Px ": %x,%x,%x,%x\n",
                  reinterpret_cast<uword>(slot()), x, y, z, w);
   }
@@ -87,7 +87,7 @@
   DeferredObject* obj = deopt_context->GetDeferredObject(index());
   *slot() = obj->object();
   if (FLAG_trace_deoptimization_verbose) {
-    const Class& cls = Class::Handle(Isolate::Current()->class_table()->At(
+    const Class& cls = Class::Handle(IsolateGroup::Current()->class_table()->At(
         Object::Handle(obj->object()).GetClassId()));
     OS::PrintErr("writing instance of class %s ref at %" Px ".\n",
                  cls.ToCString(), reinterpret_cast<uword>(slot()));
@@ -107,7 +107,7 @@
   const Code& code = Code::Handle(zone, function.unoptimized_code());
 
   uword continue_at_pc =
-      code.GetPcForDeoptId(deopt_id_, PcDescriptorsLayout::kDeopt);
+      code.GetPcForDeoptId(deopt_id_, UntaggedPcDescriptors::kDeopt);
   if (continue_at_pc == 0) {
     FATAL2("Can't locate continuation PC for deoptid %" Pd " within %s\n",
            deopt_id_, function.ToFullyQualifiedCString());
@@ -120,7 +120,7 @@
                  reinterpret_cast<uword>(slot()), continue_at_pc);
   }
 
-  uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptorsLayout::kIcCall);
+  uword pc = code.GetPcForDeoptId(deopt_id_, UntaggedPcDescriptors::kIcCall);
   if (pc != 0) {
     // If the deoptimization happened at an IC call, update the IC data
     // to avoid repeated deoptimization at the same site next time around.
@@ -152,6 +152,7 @@
   Function& function = Function::Handle(zone);
   function ^= deopt_context->ObjectAt(index_);
   ASSERT(!function.IsNull());
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Error& error =
       Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function));
   if (!error.IsNull()) {
@@ -160,7 +161,7 @@
   const Code& code = Code::Handle(zone, function.unoptimized_code());
   ASSERT(!code.IsNull());
   ASSERT(function.HasCode());
-  *reinterpret_cast<ObjectPtr*>(dest_addr) = code.raw();
+  *reinterpret_cast<ObjectPtr*>(dest_addr) = code.ptr();
 
   if (FLAG_trace_deoptimization_verbose) {
     THR_Print("materializing pc marker at 0x%" Px ": %s, %s\n",
@@ -213,7 +214,7 @@
   if (object_ == NULL) {
     Create();
   }
-  return object_->raw();
+  return object_->ptr();
 }
 
 void DeferredObject::Create() {
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 54cac1a..0a63ce4 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -33,7 +33,7 @@
                            intptr_t* cpu_registers,
                            bool is_lazy_deopt,
                            bool deoptimizing_code)
-    : code_(code.raw()),
+    : code_(code.ptr()),
       object_pool_(code.GetObjectPool()),
       deopt_info_(TypedData::null()),
       dest_frame_is_allocated_(false),
@@ -64,7 +64,7 @@
   }
 #endif
   ASSERT(!deopt_info.IsNull());
-  deopt_info_ = deopt_info.raw();
+  deopt_info_ = deopt_info.ptr();
 
   const Function& function = Function::Handle(code.function());
 
@@ -382,14 +382,15 @@
     const Function& top_function = Function::Handle(code.function());
     const Script& script = Script::Handle(top_function.script());
     const TokenPosition token_pos = code.GetTokenIndexOfPC(top_frame->pc());
-    intptr_t line, column;
-    script.GetTokenLocation(token_pos, &line, &column);
-    String& line_string = String::Handle(script.GetLine(line));
     THR_Print("  Function: %s\n", top_function.ToFullyQualifiedCString());
-    char line_buffer[80];
-    Utils::SNPrint(line_buffer, sizeof(line_buffer), "  Line %" Pd ": '%s'",
-                   line, line_string.ToCString());
-    THR_Print("%s\n", line_buffer);
+    intptr_t line;
+    if (script.GetTokenLocation(token_pos, &line)) {
+      String& line_string = String::Handle(script.GetLine(line));
+      char line_buffer[80];
+      Utils::SNPrint(line_buffer, sizeof(line_buffer), "  Line %" Pd ": '%s'",
+                     line, line_string.ToCString());
+      THR_Print("%s\n", line_buffer);
+    }
     THR_Print("  Deopt args: %" Pd "\n", deopt_arg_count);
   }
 
@@ -404,7 +405,7 @@
     obj = static_cast<ObjectPtr>(dest_frame_[i]);
     dest_array.SetAt(i, obj);
   }
-  return dest_array.raw();
+  return dest_array.ptr();
 }
 
 // Deoptimization instruction creating return address using function and
@@ -474,7 +475,7 @@
   void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
     const PassiveObject& obj = PassiveObject::Handle(
         deopt_context->zone(), deopt_context->ObjectAt(object_table_index_));
-    *reinterpret_cast<ObjectPtr*>(dest_addr) = obj.raw();
+    *reinterpret_cast<ObjectPtr*>(dest_addr) = obj.ptr();
   }
 
   CatchEntryMove ToCatchEntryMove(DeoptContext* deopt_context,
@@ -713,8 +714,8 @@
     if (function.IsNull()) {
       *reinterpret_cast<ObjectPtr*>(dest_addr) =
           deopt_context->is_lazy_deopt()
-              ? StubCode::DeoptimizeLazyFromReturn().raw()
-              : StubCode::Deoptimize().raw();
+              ? StubCode::DeoptimizeLazyFromReturn().ptr()
+              : StubCode::Deoptimize().ptr();
       return;
     }
 
@@ -724,7 +725,7 @@
     // materialization to maintain the invariant that Dart frames always have
     // a pc marker.
     *reinterpret_cast<ObjectPtr*>(dest_addr) =
-        StubCode::FrameAwaitingMaterialization().raw();
+        StubCode::FrameAwaitingMaterialization().ptr();
     deopt_context->DeferPcMarkerMaterialization(object_table_index_, dest_addr);
   }
 
@@ -891,7 +892,7 @@
   *code = function.unoptimized_code();
   ASSERT(!code->IsNull());
   uword res = code->GetPcForDeoptId(ret_address_instr->deopt_id(),
-                                    PcDescriptorsLayout::kDeopt);
+                                    UntaggedPcDescriptors::kDeopt);
   ASSERT(res != 0);
   return res;
 }
@@ -1293,7 +1294,7 @@
   frame_start_ = -1;
 
   ++current_info_number_;
-  return deopt_info.raw();
+  return deopt_info.ptr();
 }
 
 intptr_t DeoptTable::SizeFor(intptr_t length) {
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index dd896cc..cbd15c2 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -389,7 +389,7 @@
 
   RegisterSource(Kind kind, intptr_t index)
       : source_index_(KindField::encode(kind) |
-                      IndexFieldLayout::encode(index)) {}
+                      UntaggedIndexField::encode(index)) {}
 
   template <typename T>
   T Value(DeoptContext* context) const {
@@ -419,13 +419,15 @@
 
  private:
   class KindField : public BitField<intptr_t, intptr_t, 0, 1> {};
-  class IndexFieldLayout
+  class UntaggedIndexField
       : public BitField<intptr_t, intptr_t, 1, kBitsPerWord - 1> {};
 
   bool is_register() const {
     return KindField::decode(source_index_) == kRegister;
   }
-  intptr_t raw_index() const { return IndexFieldLayout::decode(source_index_); }
+  intptr_t raw_index() const {
+    return UntaggedIndexField::decode(source_index_);
+  }
 
   RegisterType reg() const { return static_cast<RegisterType>(raw_index()); }
 
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index cfafd48..beee2d1 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -15,21 +15,19 @@
 
 class DwarfPosition {
  public:
-  // The DWARF standard uses 0 to denote missing line or column information.
-  DwarfPosition(intptr_t line, intptr_t column)
-      : line_(line > 0 ? line : 0), column_(column > 0 ? column : 0) {
+  DwarfPosition(int32_t line, int32_t column) : line_(line), column_(column) {
     // Should only have no line information if also no column information.
-    ASSERT(line_ > 0 || column_ == 0);
+    ASSERT(line_ > 0 || column_ <= 0);
   }
-  explicit DwarfPosition(intptr_t line) : DwarfPosition(line, 0) {}
-  constexpr DwarfPosition() : line_(0), column_(0) {}
+  explicit DwarfPosition(int32_t line) : DwarfPosition(line, -1) {}
+  constexpr DwarfPosition() : line_(-1), column_(-1) {}
 
-  intptr_t line() const { return line_; }
-  intptr_t column() const { return column_; }
+  int32_t line() const { return line_; }
+  int32_t column() const { return column_; }
 
  private:
-  intptr_t line_;
-  intptr_t column_;
+  int32_t line_;
+  int32_t column_;
 };
 
 static constexpr auto kNoDwarfPositionInfo = DwarfPosition();
@@ -136,7 +134,7 @@
   }
 
   // Generate an appropriately zoned ZoneHandle for storing.
-  const auto& code = Code::ZoneHandle(zone_, orig_code.raw());
+  const auto& code = Code::ZoneHandle(zone_, orig_code.ptr());
   codes_.Add(&code);
   // Currently assumes the name has the same lifetime as the Zone of the
   // Dwarf object (which is currently true).  Otherwise, need to copy.
@@ -164,7 +162,7 @@
     return pair->index_;
   }
   intptr_t index = functions_.length();
-  const Function& zone_func = Function::ZoneHandle(zone_, function.raw());
+  const Function& zone_func = Function::ZoneHandle(zone_, function.ptr());
   function_to_index_.Insert(FunctionIndexPair(&zone_func, index));
   functions_.Add(&zone_func);
   const Script& script = Script::Handle(zone_, function.script());
@@ -180,7 +178,7 @@
   }
   // DWARF file numbers start from 1.
   intptr_t index = scripts_.length() + 1;
-  const Script& zone_script = Script::ZoneHandle(zone_, script.raw());
+  const Script& zone_script = Script::ZoneHandle(zone_, script.ptr());
   script_to_index_.Insert(ScriptIndexPair(&zone_script, index));
   scripts_.Add(&zone_script);
   return index;
@@ -291,7 +289,7 @@
   // them in our abbreviation above in WriteAbbreviations.
   stream->uleb128(kCompilationUnit);
   const Library& root_library = Library::Handle(
-      zone_, Isolate::Current()->object_store()->root_library());
+      zone_, IsolateGroup::Current()->object_store()->root_library());
   const String& root_uri = String::Handle(zone_, root_library.url());
   stream->string(root_uri.ToCString());  // DW_AT_name
   stream->string("Dart VM");             // DW_AT_producer
@@ -392,15 +390,6 @@
   }
 }
 
-static DwarfPosition ReadPosition(ReadStream* stream) {
-  const intptr_t line = stream->Read<int32_t>();
-  if (!FLAG_dwarf_stack_traces_mode) {
-    return DwarfPosition(line);
-  }
-  const intptr_t column = stream->Read<int32_t>();
-  return DwarfPosition(line, column);
-}
-
 // Our state machine encodes position metadata such that we don't know the
 // end pc for an inlined function until it is popped, but DWARF DIEs encode
 // it where the function is pushed. We expand the state transitions into
@@ -431,21 +420,24 @@
   node_stack.Add(root_node);
 
   while (stream.PendingBytes() > 0) {
-    uint8_t opcode = stream.Read<uint8_t>();
+    int32_t arg1;
+    int32_t arg2 = -1;
+    const uint8_t opcode = CodeSourceMapOps::Read(&stream, &arg1, &arg2);
     switch (opcode) {
-      case CodeSourceMapBuilder::kChangePosition: {
-        token_positions[token_positions.length() - 1] = ReadPosition(&stream);
+      case CodeSourceMapOps::kChangePosition: {
+        const DwarfPosition& old_pos =
+            token_positions[token_positions.length() - 1];
+        token_positions[token_positions.length() - 1] =
+            DwarfPosition(Utils::AddWithWrapAround(old_pos.line(), arg1), arg2);
         break;
       }
-      case CodeSourceMapBuilder::kAdvancePC: {
-        int32_t delta = stream.Read<int32_t>();
-        current_pc_offset += delta;
+      case CodeSourceMapOps::kAdvancePC: {
+        current_pc_offset += arg1;
         break;
       }
-      case CodeSourceMapBuilder::kPushFunction: {
-        int32_t func = stream.Read<int32_t>();
+      case CodeSourceMapOps::kPushFunction: {
         const Function& child_func =
-            Function::ZoneHandle(zone_, Function::RawCast(functions.At(func)));
+            Function::ZoneHandle(zone_, Function::RawCast(functions.At(arg1)));
         InliningNode* child_node = new (zone_)
             InliningNode(child_func, token_positions.Last(), current_pc_offset);
         node_stack.Last()->AppendChild(child_node);
@@ -453,7 +445,7 @@
         token_positions.Add(kNoDwarfPositionInfo);
         break;
       }
-      case CodeSourceMapBuilder::kPopFunction: {
+      case CodeSourceMapOps::kPopFunction: {
         // We never pop the root function.
         ASSERT(node_stack.length() > 1);
         ASSERT(token_positions.length() > 1);
@@ -462,8 +454,7 @@
         token_positions.RemoveLast();
         break;
       }
-      case CodeSourceMapBuilder::kNullCheck: {
-        stream.Read<int32_t>();
+      case CodeSourceMapOps::kNullCheck: {
         break;
       }
       default:
@@ -499,10 +490,13 @@
   stream->OffsetFromSymbol(root_asm_name, node->end_pc_offset);
   // DW_AT_call_file
   stream->uleb128(file);
+
+  // The DWARF standard uses 0 to denote missing line or column information.
+
   // DW_AT_call_line
-  stream->uleb128(node->position.line());
+  stream->uleb128(node->position.line() < 0 ? 0 : node->position.line());
   // DW_at_call_column
-  stream->uleb128(node->position.column());
+  stream->uleb128(node->position.column() < 0 ? 0 : node->position.column());
 
   for (InliningNode* child = node->children_head; child != NULL;
        child = child->children_next) {
@@ -609,16 +603,20 @@
     token_positions.Add(kNoDwarfPositionInfo);
 
     while (code_map_stream.PendingBytes() > 0) {
-      uint8_t opcode = code_map_stream.Read<uint8_t>();
+      int32_t arg1;
+      int32_t arg2 = -1;
+      const uint8_t opcode =
+          CodeSourceMapOps::Read(&code_map_stream, &arg1, &arg2);
       switch (opcode) {
-        case CodeSourceMapBuilder::kChangePosition: {
-          token_positions[token_positions.length() - 1] =
-              ReadPosition(&code_map_stream);
+        case CodeSourceMapOps::kChangePosition: {
+          const DwarfPosition& old_pos =
+              token_positions[token_positions.length() - 1];
+          token_positions[token_positions.length() - 1] = DwarfPosition(
+              Utils::AddWithWrapAround(old_pos.line(), arg1), arg2);
           break;
         }
-        case CodeSourceMapBuilder::kAdvancePC: {
-          int32_t delta = code_map_stream.Read<int32_t>();
-          current_pc_offset += delta;
+        case CodeSourceMapOps::kAdvancePC: {
+          current_pc_offset += arg1;
 
           const Function& function = *(function_stack.Last());
           script = function.script();
@@ -632,8 +630,14 @@
           }
 
           // 2. Update LNP line.
-          const intptr_t line = token_positions.Last().line();
-          const intptr_t column = token_positions.Last().column();
+          // The DWARF standard uses 0 to denote missing line or column
+          // information.
+          const intptr_t line = token_positions.Last().line() < 0
+                                    ? 0
+                                    : token_positions.Last().line();
+          const intptr_t column = token_positions.Last().column() < 0
+                                      ? 0
+                                      : token_positions.Last().column();
           if (line != previous_line) {
             stream->u1(DW_LNS_advance_line);
             stream->sleb128(line - previous_line);
@@ -668,15 +672,14 @@
           previous_pc_offset = current_pc_offset;
           break;
         }
-        case CodeSourceMapBuilder::kPushFunction: {
-          int32_t func_index = code_map_stream.Read<int32_t>();
-          const Function& child_func = Function::Handle(
-              zone_, Function::RawCast(functions.At(func_index)));
+        case CodeSourceMapOps::kPushFunction: {
+          const Function& child_func =
+              Function::Handle(zone_, Function::RawCast(functions.At(arg1)));
           function_stack.Add(&child_func);
           token_positions.Add(kNoDwarfPositionInfo);
           break;
         }
-        case CodeSourceMapBuilder::kPopFunction: {
+        case CodeSourceMapOps::kPopFunction: {
           // We never pop the root function.
           ASSERT(function_stack.length() > 1);
           ASSERT(token_positions.length() > 1);
@@ -684,8 +687,7 @@
           token_positions.RemoveLast();
           break;
         }
-        case CodeSourceMapBuilder::kNullCheck: {
-          code_map_stream.Read<int32_t>();
+        case CodeSourceMapOps::kNullCheck: {
           break;
         }
         default:
@@ -746,8 +748,7 @@
 }
 
 Trie<const char>* Dwarf::CreateReverseObfuscationTrie(Zone* zone) {
-  auto const I = Thread::Current()->isolate();
-  auto const map_array = I->obfuscation_map();
+  auto const map_array = IsolateGroup::Current()->obfuscation_map();
   if (map_array == nullptr) return nullptr;
 
   Trie<const char>* trie = nullptr;
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index 22df262..b66788e 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -32,7 +32,7 @@
   }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair.script_->raw() == key->raw();
+    return pair.script_->ptr() == key->ptr();
   }
 
   ScriptIndexPair(const Script* s, intptr_t index) : script_(s), index_(index) {
@@ -60,10 +60,10 @@
 
   static Value ValueOf(Pair kv) { return kv.index_; }
 
-  static inline intptr_t Hashcode(Key key) { return key->token_pos().value(); }
+  static inline intptr_t Hashcode(Key key) { return key->token_pos().Hash(); }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
-    return pair.function_->raw() == key->raw();
+    return pair.function_->ptr() == key->ptr();
   }
 
   FunctionIndexPair(const Function* f, intptr_t index)
@@ -116,7 +116,7 @@
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
     // Code objects are always allocated in old space, so they don't move.
-    return pair.code->raw() == key->raw();
+    return pair.code->ptr() == key->ptr();
   }
 };
 
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 6cc253e..0390269 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -69,7 +69,7 @@
         cur_index_(0),
         dropped_frames_(0) {
     ASSERT(
-        stacktrace_.raw() ==
+        stacktrace_.ptr() ==
         Isolate::Current()->isolate_object_store()->preallocated_stack_trace());
   }
   ~PreallocatedStackTraceBuilder() {}
@@ -297,7 +297,7 @@
           UNREACHABLE();
       }
 
-      dst_values.Add(&Object::Handle(zone, value.raw()));
+      dst_values.Add(&Object::Handle(zone, value.ptr()));
     }
 
     {
@@ -305,7 +305,7 @@
 
       for (int j = 0; j < moves.count(); j++) {
         const CatchEntryMove& move = moves.At(j);
-        *TaggedSlotAt(fp, move.dest_slot()) = dst_values[j]->raw();
+        *TaggedSlotAt(fp, move.dest_slot()) = dst_values[j]->ptr();
       }
     }
   }
@@ -719,20 +719,20 @@
   }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   Class& error_class =
-      Class::Handle(zone, isolate->object_store()->error_class());
+      Class::Handle(zone, isolate_group->object_store()->error_class());
   if (error_class.IsNull()) {
     const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
     error_class = core_lib.LookupClass(Symbols::Error());
     ASSERT(!error_class.IsNull());
-    isolate->object_store()->set_error_class(error_class);
+    isolate_group->object_store()->set_error_class(error_class);
   }
   // If instance class extends 'class Error' return '_stackTrace' field.
   Class& test_class = Class::Handle(zone, instance.clazz());
   AbstractType& type = AbstractType::Handle(zone, AbstractType::null());
   while (true) {
-    if (test_class.raw() == error_class.raw()) {
+    if (test_class.ptr() == error_class.ptr()) {
       return error_class.LookupInstanceFieldAllowPrivate(
           Symbols::_stackTrace());
     }
@@ -758,23 +758,24 @@
   // should jump there instead.
   RELEASE_ASSERT(thread->long_jump_base() == nullptr);
   Zone* zone = thread->zone();
+  auto object_store = thread->isolate_group()->object_store();
   Isolate* isolate = thread->isolate();
 #if !defined(PRODUCT)
   // Do not notify debugger on stack overflow and out of memory exceptions.
   // The VM would crash when the debugger calls back into the VM to
   // get values of variables.
-  if (incoming_exception.raw() != isolate->object_store()->out_of_memory() &&
-      incoming_exception.raw() != isolate->object_store()->stack_overflow()) {
+  if (incoming_exception.ptr() != object_store->out_of_memory() &&
+      incoming_exception.ptr() != object_store->stack_overflow()) {
     isolate->debugger()->PauseException(incoming_exception);
   }
 #endif
   bool use_preallocated_stacktrace = false;
-  Instance& exception = Instance::Handle(zone, incoming_exception.raw());
+  Instance& exception = Instance::Handle(zone, incoming_exception.ptr());
   if (exception.IsNull()) {
     exception ^=
         Exceptions::Create(Exceptions::kNullThrown, Object::empty_array());
-  } else if (exception.raw() == isolate->object_store()->out_of_memory() ||
-             exception.raw() == isolate->object_store()->stack_overflow()) {
+  } else if (exception.ptr() == object_store->out_of_memory() ||
+             exception.ptr() == object_store->stack_overflow()) {
     use_preallocated_stacktrace = true;
   }
   // Find the exception handler and determine if the handler needs a
@@ -789,8 +790,7 @@
   if (use_preallocated_stacktrace) {
     if (handler_pc == 0) {
       // No Dart frame.
-      ASSERT(incoming_exception.raw() ==
-             isolate->object_store()->out_of_memory());
+      ASSERT(incoming_exception.ptr() == object_store->out_of_memory());
       const UnhandledException& error = UnhandledException::Handle(
           zone,
           isolate->isolate_object_store()->preallocated_unhandled_exception());
@@ -800,7 +800,7 @@
     stacktrace = isolate->isolate_object_store()->preallocated_stack_trace();
     PreallocatedStackTraceBuilder frame_builder(stacktrace);
     ASSERT(existing_stacktrace.IsNull() ||
-           (existing_stacktrace.raw() == stacktrace.raw()));
+           (existing_stacktrace.ptr() == stacktrace.ptr()));
     ASSERT(existing_stacktrace.IsNull() || is_rethrow);
     if (handler_needs_stacktrace && existing_stacktrace.IsNull()) {
       BuildStackTrace(&frame_builder);
@@ -811,7 +811,7 @@
       // reverse is not necessarily true (e.g. Dart_PropagateError can cause
       // a rethrow being called without an existing stacktrace.)
       ASSERT(is_rethrow);
-      stacktrace = existing_stacktrace.raw();
+      stacktrace = existing_stacktrace.ptr();
     } else {
       // Get stacktrace field of class Error to determine whether we have a
       // subclass of Error which carries around its stack trace.
@@ -855,7 +855,7 @@
     // the isolate etc.). This can happen in the compiler, which is not
     // allowed to allocate in new space, so we pass the kOld argument.
     const UnhandledException& unhandled_exception = UnhandledException::Handle(
-        zone, exception.raw() == isolate->object_store()->out_of_memory()
+        zone, exception.ptr() == object_store->out_of_memory()
                   ? isolate->isolate_object_store()
                         ->preallocated_unhandled_exception()
                   : UnhandledException::New(exception, stacktrace, Heap::kOld));
@@ -910,16 +910,16 @@
   const Array& args = Array::Handle(zone, Array::New(4));
 
   ExceptionType exception_type =
-      (dst_name.raw() == Symbols::InTypeCast().raw()) ? kCast : kType;
+      (dst_name.ptr() == Symbols::InTypeCast().ptr()) ? kCast : kType;
 
   DartFrameIterator iterator(thread,
                              StackFrameIterator::kNoCrossThreadIteration);
   const Script& script = Script::Handle(zone, GetCallerScript(&iterator));
   const String& url = String::Handle(
-      zone, script.IsNull() ? Symbols::OptimizedOut().raw() : script.url());
+      zone, script.IsNull() ? Symbols::OptimizedOut().ptr() : script.url());
   intptr_t line = -1;
   intptr_t column = -1;
-  if (!script.IsNull() && location.IsReal()) {
+  if (!script.IsNull()) {
     script.GetTokenLocation(location, &line, &column);
   }
   // Initialize '_url', '_line', and '_column' arguments.
@@ -1059,18 +1059,18 @@
 }
 
 void Exceptions::ThrowOOM() {
-  Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  auto thread = Thread::Current();
+  auto isolate_group = thread->isolate_group();
   const Instance& oom = Instance::Handle(
-      thread->zone(), isolate->object_store()->out_of_memory());
+      thread->zone(), isolate_group->object_store()->out_of_memory());
   Throw(thread, oom);
 }
 
 void Exceptions::ThrowStackOverflow() {
-  Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  auto thread = Thread::Current();
+  auto isolate_group = thread->isolate_group();
   const Instance& stack_overflow = Instance::Handle(
-      thread->zone(), isolate->object_store()->stack_overflow());
+      thread->zone(), isolate_group->object_store()->stack_overflow());
   Throw(thread, stack_overflow);
 }
 
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 20aef13..090615c 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -88,8 +88,8 @@
       const String& name);
   DART_NORETURN static void ThrowLateFieldNotInitialized(const String& name);
 
-  // Returns a RawInstance if the exception is successfully created,
-  // otherwise returns a RawError.
+  // Returns an InstancePtr if the exception is successfully created,
+  // otherwise returns an ErrorPtr.
   static ObjectPtr Create(ExceptionType type, const Array& arguments);
 
   // Returns RawUnhandledException that wraps exception of type [type] with
diff --git a/runtime/vm/ffi_callback_trampolines.cc b/runtime/vm/ffi_callback_trampolines.cc
index 4bf926e..169d8f8 100644
--- a/runtime/vm/ffi_callback_trampolines.cc
+++ b/runtime/vm/ffi_callback_trampolines.cc
@@ -45,10 +45,13 @@
   }
 
   if (trampolines_left_on_page_ == 0) {
+    // Fuchsia requires memory to be allocated with ZX_RIGHT_EXECUTE in order
+    // to be flipped to kReadExecute after being kReadWrite.
     VirtualMemory* const memory = VirtualMemory::AllocateAligned(
         /*size=*/VirtualMemory::PageSize(),
         /*alignment=*/VirtualMemory::PageSize(),
-        /*is_executable=*/false, /*name=*/"Dart VM FFI callback trampolines");
+        /*is_executable=*/true, /*name=*/"Dart VM FFI callback trampolines");
+    memory->Protect(VirtualMemory::kReadWrite);
 
     if (memory == nullptr) {
       Exceptions::ThrowOOM();
diff --git a/runtime/vm/field_table.cc b/runtime/vm/field_table.cc
index a6358a1..f045860 100644
--- a/runtime/vm/field_table.cc
+++ b/runtime/vm/field_table.cc
@@ -22,6 +22,25 @@
   free(table_);        // Allocated in FieldTable::Grow()
 }
 
+bool FieldTable::IsReadyToUse() const {
+  DEBUG_ASSERT(
+      IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
+  return is_ready_to_use_;
+}
+
+void FieldTable::MarkReadyToUse() {
+  // The isolate will mark it's field table ready-to-use upon initialization of
+  // the isolate. Only after it was marked as ready-to-use will it participate
+  // in new static field registrations.
+  //
+  // By requiring a read lock here we ensure no other thread is is registering a
+  // new static field at this moment (it would need exlusive writer lock).
+  DEBUG_ASSERT(
+      IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
+  ASSERT(!is_ready_to_use_);
+  is_ready_to_use_ = true;
+}
+
 void FieldTable::FreeOldTables() {
   while (old_tables_->length() > 0) {
     free(old_tables_->RemoveLast());
@@ -32,21 +51,26 @@
   return field_id * sizeof(InstancePtr);  // NOLINT
 }
 
-void FieldTable::Register(const Field& field) {
-  ASSERT(Thread::Current()->IsMutatorThread());
+bool FieldTable::Register(const Field& field, intptr_t expected_field_id) {
+  DEBUG_ASSERT(
+      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+  ASSERT(is_ready_to_use_);
+
   if (free_head_ < 0) {
+    bool grown_backing_store = false;
     if (top_ == capacity_) {
       const intptr_t new_capacity = capacity_ + kCapacityIncrement;
       Grow(new_capacity);
+      grown_backing_store = true;
     }
 
     ASSERT(top_ < capacity_);
-
+    ASSERT(expected_field_id == -1 || expected_field_id == top_);
     field.set_field_id(top_);
-    table_[top_] = Object::sentinel().raw();
+    table_[top_] = Object::sentinel().ptr();
 
     ++top_;
-    return;
+    return grown_backing_store;
   }
 
   // Reuse existing free element. This is "slow path" that should only be
@@ -54,7 +78,8 @@
   intptr_t reused_free = free_head_;
   free_head_ = Smi::Value(Smi::RawCast(table_[free_head_]));
   field.set_field_id(reused_free);
-  table_[reused_free] = Object::sentinel().raw();
+  table_[reused_free] = Object::sentinel().ptr();
+  return false;
 }
 
 void FieldTable::Free(intptr_t field_id) {
@@ -104,6 +129,9 @@
 }
 
 FieldTable* FieldTable::Clone(Isolate* for_isolate) {
+  DEBUG_ASSERT(
+      IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
+
   FieldTable* clone = new FieldTable(for_isolate);
   auto new_table = static_cast<InstancePtr*>(
       malloc(capacity_ * sizeof(InstancePtr)));  // NOLINT
diff --git a/runtime/vm/field_table.h b/runtime/vm/field_table.h
index 4fc1ca8..4350745 100644
--- a/runtime/vm/field_table.h
+++ b/runtime/vm/field_table.h
@@ -27,10 +27,14 @@
         free_head_(-1),
         table_(nullptr),
         old_tables_(new MallocGrowableArray<InstancePtr*>()),
-        isolate_(isolate) {}
+        isolate_(isolate),
+        is_ready_to_use_(isolate == nullptr) {}
 
   ~FieldTable();
 
+  bool IsReadyToUse() const;
+  void MarkReadyToUse();
+
   intptr_t NumFieldIds() const { return top_; }
   intptr_t Capacity() const { return capacity_; }
 
@@ -43,7 +47,9 @@
 
   bool IsValidIndex(intptr_t index) const { return index >= 0 && index < top_; }
 
-  void Register(const Field& field);
+  // Returns whether registering this field caused a growth in the backing
+  // store.
+  bool Register(const Field& field, intptr_t expected_field_id = -1);
   void AllocateIndex(intptr_t index);
 
   // Static field elements are being freed only during isolate reload
@@ -89,6 +95,10 @@
   // mutator thread up-to-date.
   Isolate* isolate_;
 
+  // Whether this field table is ready to use by e.g. registering new static
+  // fields.
+  bool is_ready_to_use_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(FieldTable);
 };
 
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 36303f8..087b781 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -90,6 +90,8 @@
     "-1 means never.")                                                         \
   P(background_compilation, bool, kDartUseBackgroundCompilation,               \
     "Run optimizing compilation in background")                                \
+  P(check_token_positions, bool, false,                                        \
+    "Check validity of token positions while compiling flow graphs")           \
   R(code_comments, false, bool, false,                                         \
     "Include comments into code and disassembly.")                             \
   P(collect_code, bool, false, "Attempt to GC infrequently used code.")        \
diff --git a/runtime/vm/frame_layout.h b/runtime/vm/frame_layout.h
index 4327050..d410e93 100644
--- a/runtime/vm/frame_layout.h
+++ b/runtime/vm/frame_layout.h
@@ -8,7 +8,7 @@
 #include "platform/assert.h"
 #include "platform/globals.h"
 
-// FrameLayout structure captures configuration specific properties of the
+// UntaggedFrame structure captures configuration specific properties of the
 // frame layout used by the runtime system and compiler.
 //
 // Runtime system uses runtime_frame_layout defined in stack_frame.h.
@@ -19,7 +19,7 @@
 // Forward declarations.
 class LocalVariable;
 
-struct FrameLayout {
+struct UntaggedFrame {
   // The offset (in words) from FP to the first object.
   int first_object_from_fp;
 
diff --git a/runtime/vm/growable_array.h b/runtime/vm/growable_array.h
index 85bfedc..84e378d 100644
--- a/runtime/vm/growable_array.h
+++ b/runtime/vm/growable_array.h
@@ -54,14 +54,14 @@
       : zone_(zone), array_(zone, initial_capacity) {}
 
   // Use unique zone handles to store objects.
-  void Add(const T& t) { array_.Add(&T::ZoneHandle(zone_, t.raw())); }
+  void Add(const T& t) { array_.Add(&T::ZoneHandle(zone_, t.ptr())); }
 
   T& operator[](intptr_t index) const { return *array_[index]; }
 
   const T& At(intptr_t index) const { return operator[](index); }
 
   void SetAt(intptr_t index, const T& t) {
-    array_[index] = &T::ZoneHandle(zone_, t.raw());
+    array_[index] = &T::ZoneHandle(zone_, t.ptr());
   }
 
   intptr_t length() const { return array_.length(); }
diff --git a/runtime/vm/growable_array_test.cc b/runtime/vm/growable_array_test.cc
index 7c0ee5d..91d0074 100644
--- a/runtime/vm/growable_array_test.cc
+++ b/runtime/vm/growable_array_test.cc
@@ -97,13 +97,13 @@
   GrowableHandlePtrArray<const String> test1(zone, 1);
   EXPECT_EQ(0, test1.length());
   test1.Add(Symbols::Int());
-  EXPECT(test1[0].raw() == Symbols::Int().raw());
+  EXPECT(test1[0].ptr() == Symbols::Int().ptr());
   EXPECT_EQ(1, test1.length());
 
   ZoneGrowableHandlePtrArray<const String>* test2 =
       new ZoneGrowableHandlePtrArray<const String>(zone, 1);
   test2->Add(Symbols::GetterPrefix());
-  EXPECT((*test2)[0].raw() == Symbols::GetterPrefix().raw());
+  EXPECT((*test2)[0].ptr() == Symbols::GetterPrefix().ptr());
   EXPECT_EQ(1, test2->length());
 }
 
diff --git a/runtime/vm/guard_field_test.cc b/runtime/vm/guard_field_test.cc
index 5c13efe..7645e46 100644
--- a/runtime/vm/guard_field_test.cc
+++ b/runtime/vm/guard_field_test.cc
@@ -24,7 +24,7 @@
   Field& field =
       Field::ZoneHandle(cls.LookupInstanceFieldAllowPrivate(fieldname));
   EXPECT(!field.IsNull());
-  return field.raw();
+  return field.ptr();
 }
 
 TEST_CASE(GuardFieldSimpleTest) {
diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h
index b558abe..cb6d01d 100644
--- a/runtime/vm/hash_table.h
+++ b/runtime/vm/hash_table.h
@@ -49,7 +49,7 @@
 // If you *know* that no mutating operations were called, you can optimize:
 //  ...
 //  obj ^= cache.GetOrNull(name);
-//  ASSERT(cache.Release().raw() == get_foo_cache());
+//  ASSERT(cache.Release().ptr() == get_foo_cache());
 //
 // TODO(koda): When exposing these to Dart code, document and assert that
 // KeyTraits methods must not run Dart code (since the C++ code doesn't check
@@ -225,8 +225,8 @@
   // Sets the key of a previously unoccupied entry. This must not be the last
   // unoccupied entry.
   void InsertKey(intptr_t entry, const Object& key) const {
-    ASSERT(key.raw() != UnusedMarker().raw());
-    ASSERT(key.raw() != DeletedMarker().raw());
+    ASSERT(key.ptr() != UnusedMarker().ptr());
+    ASSERT(key.ptr() != DeletedMarker().ptr());
     ASSERT(!IsOccupied(entry));
     AdjustSmiValueAt(kOccupiedEntriesIndex, 1);
     if (IsDeleted(entry)) {
@@ -243,13 +243,13 @@
   const Object& DeletedMarker() const { return *data_; }
 
   bool IsUnused(intptr_t entry) const {
-    return InternalGetKey(entry) == UnusedMarker().raw();
+    return InternalGetKey(entry) == UnusedMarker().ptr();
   }
   bool IsOccupied(intptr_t entry) const {
     return !IsUnused(entry) && !IsDeleted(entry);
   }
   bool IsDeleted(intptr_t entry) const {
-    return InternalGetKey(entry) == DeletedMarker().raw();
+    return InternalGetKey(entry) == DeletedMarker().ptr();
   }
 
   ObjectPtr GetKey(intptr_t entry) const {
@@ -307,7 +307,7 @@
   }
   void UpdateCollisions(intptr_t collisions) const {
     if (KeyTraits::ReportStats()) {
-      if (data_->raw()->ptr()->InVMIsolateHeap()) {
+      if (data_->ptr()->untag()->InVMIsolateHeap()) {
         return;
       }
       AdjustSmiValueAt(kNumProbesIndex, collisions + 1);
@@ -447,14 +447,14 @@
         Thread::Current()->zone(),
         Array::New(Table::ArrayLengthForNumOccupied(initial_capacity), space));
     table.Initialize();
-    return table.Release().raw();
+    return table.Release().ptr();
   }
 
   template <typename Table>
   static ArrayPtr New(const Array& array) {
-    Table table(Thread::Current()->zone(), array.raw());
+    Table table(Thread::Current()->zone(), array.ptr());
     table.Initialize();
-    return table.Release().raw();
+    return table.Release().ptr();
   }
 
   // Clears 'to' and inserts all elements from 'from', in iteration order.
@@ -506,7 +506,7 @@
     Table new_table(New<Table>(new_capacity,  // Is rounded up to power of 2.
                                table.data_->IsOld() ? Heap::kOld : Heap::kNew));
     Copy(table, new_table);
-    *table.data_ = new_table.Release().raw();
+    *table.data_ = new_table.Release().ptr();
     NOT_IN_PRODUCT(table.UpdateGrowth(); table.PrintStats();)
   }
 
@@ -529,7 +529,7 @@
         }
       }
     }
-    return result.raw();
+    return result.ptr();
   }
 };
 
@@ -581,7 +581,7 @@
     if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
       BaseIterTable::InsertKey(entry, key);
       BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
-      return value_if_absent.raw();
+      return value_if_absent.ptr();
     } else {
       return BaseIterTable::GetPayload(entry, 0);
     }
@@ -597,7 +597,7 @@
           BaseIterTable::BaseTable::Traits::NewKey(key);
       BaseIterTable::InsertKey(entry, BaseIterTable::KeyHandle());
       BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
-      return value_if_absent.raw();
+      return value_if_absent.ptr();
     } else {
       return BaseIterTable::GetPayload(entry, 0);
     }
@@ -659,7 +659,7 @@
     intptr_t entry = -1;
     if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
       BaseIterTable::InsertKey(entry, key);
-      return key.raw();
+      return key.ptr();
     } else {
       return BaseIterTable::GetKey(entry);
     }
@@ -674,7 +674,7 @@
       BaseIterTable::KeyHandle() =
           BaseIterTable::BaseTable::Traits::NewKey(key);
       BaseIterTable::InsertKey(entry, BaseIterTable::KeyHandle());
-      return BaseIterTable::KeyHandle().raw();
+      return BaseIterTable::KeyHandle().ptr();
     } else {
       return BaseIterTable::GetKey(entry);
     }
@@ -725,8 +725,8 @@
     Object& entry = Object::Handle();
     for (intptr_t i = 0; i < this->data_->Length(); i++) {
       entry = this->data_->At(i);
-      if (entry.raw() == BaseSet::UnusedMarker().raw() ||
-          entry.raw() == BaseSet::DeletedMarker().raw() || entry.IsSmi()) {
+      if (entry.ptr() == BaseSet::UnusedMarker().ptr() ||
+          entry.ptr() == BaseSet::DeletedMarker().ptr() || entry.IsSmi()) {
         // empty, deleted, num_used/num_deleted
         OS::PrintErr("%" Pd ": %s\n", i, entry.ToCString());
       } else {
diff --git a/runtime/vm/heap/become.cc b/runtime/vm/heap/become.cc
index 1a1415b..ea959e1 100644
--- a/runtime/vm/heap/become.cc
+++ b/runtime/vm/heap/become.cc
@@ -24,16 +24,16 @@
   ForwardingCorpse* result = reinterpret_cast<ForwardingCorpse*>(addr);
 
   uword tags = result->tags_;  // Carry-over any identity hash.
-  tags = ObjectLayout::SizeTag::update(size, tags);
-  tags = ObjectLayout::ClassIdTag::update(kForwardingCorpse, tags);
+  tags = UntaggedObject::SizeTag::update(size, tags);
+  tags = UntaggedObject::ClassIdTag::update(kForwardingCorpse, tags);
   bool is_old = (addr & kNewObjectAlignmentOffset) == kOldObjectAlignmentOffset;
-  tags = ObjectLayout::OldBit::update(is_old, tags);
-  tags = ObjectLayout::OldAndNotMarkedBit::update(is_old, tags);
-  tags = ObjectLayout::OldAndNotRememberedBit::update(is_old, tags);
-  tags = ObjectLayout::NewBit::update(!is_old, tags);
+  tags = UntaggedObject::OldBit::update(is_old, tags);
+  tags = UntaggedObject::OldAndNotMarkedBit::update(is_old, tags);
+  tags = UntaggedObject::OldAndNotRememberedBit::update(is_old, tags);
+  tags = UntaggedObject::NewBit::update(!is_old, tags);
 
   result->tags_ = tags;
-  if (size > ObjectLayout::SizeTag::kMaxSizeTag) {
+  if (size > UntaggedObject::SizeTag::kMaxSizeTag) {
     *result->SizeAddress() = size;
   }
   result->set_target(Object::null());
@@ -60,7 +60,7 @@
 }
 
 static void ForwardObjectTo(ObjectPtr before_obj, ObjectPtr after_obj) {
-  const intptr_t size_before = before_obj->ptr()->HeapSize();
+  const intptr_t size_before = before_obj->untag()->HeapSize();
 
   uword corpse_addr = static_cast<uword>(before_obj) - kHeapObjectTag;
   ForwardingCorpse* forwarder =
@@ -70,7 +70,7 @@
     FATAL("become: ForwardObjectTo failure.");
   }
   // Still need to be able to iterate over the forwarding corpse.
-  const intptr_t size_after = before_obj->ptr()->HeapSize();
+  const intptr_t size_after = before_obj->untag()->HeapSize();
   if (size_before != size_after) {
     FATAL("become: Before and after sizes do not match.");
   }
@@ -99,10 +99,10 @@
       }
       if (visiting_object_ == nullptr) {
         *p = new_target;
-      } else if (visiting_object_->ptr()->IsCardRemembered()) {
-        visiting_object_->ptr()->StoreArrayPointer(p, new_target, thread_);
+      } else if (visiting_object_->untag()->IsCardRemembered()) {
+        visiting_object_->untag()->StoreArrayPointer(p, new_target, thread_);
       } else {
-        visiting_object_->ptr()->StorePointer(p, new_target, thread_);
+        visiting_object_->untag()->StorePointer(p, new_target, thread_);
       }
     }
   }
@@ -111,10 +111,11 @@
     visiting_object_ = obj;
     // The incoming remembered bit may be unreliable. Clear it so we can
     // consistently reapply the barrier to all slots.
-    if ((obj != nullptr) && obj->IsOldObject() && obj->ptr()->IsRemembered()) {
+    if ((obj != nullptr) && obj->IsOldObject() &&
+        obj->untag()->IsRemembered()) {
       ASSERT(!obj->IsForwardingCorpse());
       ASSERT(!obj->IsFreeListElement());
-      obj->ptr()->ClearRememberedBit();
+      obj->untag()->ClearRememberedBit();
     }
   }
 
@@ -132,7 +133,7 @@
 
   virtual void VisitObject(ObjectPtr obj) {
     pointer_visitor_->VisitingObject(obj);
-    obj->ptr()->VisitPointers(pointer_visitor_);
+    obj->untag()->VisitPointers(pointer_visitor_);
   }
 
  private:
@@ -149,8 +150,8 @@
   virtual void VisitHandle(uword addr) {
     FinalizablePersistentHandle* handle =
         reinterpret_cast<FinalizablePersistentHandle*>(addr);
-    if (IsForwardingObject(handle->raw())) {
-      *handle->raw_addr() = GetForwardedObject(handle->raw());
+    if (IsForwardingObject(handle->ptr())) {
+      *handle->ptr_addr() = GetForwardedObject(handle->ptr());
     }
   }
 
@@ -191,7 +192,7 @@
 void Become::MakeDummyObject(const Instance& instance) {
   // Make the forward pointer point to itself.
   // This is needed to distinguish it from a real forward object.
-  ForwardObjectTo(instance.raw(), instance.raw());
+  ForwardObjectTo(instance.ptr(), instance.ptr());
 }
 
 static bool IsDummyObject(ObjectPtr object) {
@@ -206,13 +207,13 @@
   OS::PrintErr("BEFORE IS HEAP OBJECT: %s\n",
                before_obj->IsHeapObject() ? "YES" : "NO");
   OS::PrintErr("BEFORE IN VMISOLATE HEAP OBJECT: %s\n",
-               before_obj->ptr()->InVMIsolateHeap() ? "YES" : "NO");
+               before_obj->untag()->InVMIsolateHeap() ? "YES" : "NO");
 
   OS::PrintErr("AFTER ADDRESS: %#" Px "\n", static_cast<uword>(after_obj));
   OS::PrintErr("AFTER IS HEAP OBJECT: %s\n",
                after_obj->IsHeapObject() ? "YES" : "NO");
   OS::PrintErr("AFTER IN VMISOLATE HEAP OBJECT: %s\n",
-               after_obj->ptr()->InVMIsolateHeap() ? "YES" : "NO");
+               after_obj->untag()->InVMIsolateHeap() ? "YES" : "NO");
 
   if (before_obj->IsHeapObject()) {
     OS::PrintErr("BEFORE OBJECT CLASS ID=%" Pd "\n", before_obj->GetClassId());
@@ -251,7 +252,7 @@
       CrashDump(before_obj, after_obj);
       FATAL("become: Cannot become immediates");
     }
-    if (before_obj->ptr()->InVMIsolateHeap()) {
+    if (before_obj->untag()->InVMIsolateHeap()) {
       CrashDump(before_obj, after_obj);
       FATAL("become: Cannot forward VM heap objects");
     }
diff --git a/runtime/vm/heap/become.h b/runtime/vm/heap/become.h
index 5bcc42c..9914056 100644
--- a/runtime/vm/heap/become.h
+++ b/runtime/vm/heap/become.h
@@ -27,7 +27,7 @@
   void set_target(ObjectPtr target) { target_ = target; }
 
   intptr_t HeapSize() {
-    intptr_t size = ObjectLayout::SizeTag::decode(tags_);
+    intptr_t size = UntaggedObject::SizeTag::decode(tags_);
     if (size != 0) return size;
     return *SizeAddress();
   }
diff --git a/runtime/vm/heap/become_test.cc b/runtime/vm/heap/become_test.cc
index b3e89220..a375486 100644
--- a/runtime/vm/heap/become_test.cc
+++ b/runtime/vm/heap/become_test.cc
@@ -16,7 +16,7 @@
   const String& before_obj = String::Handle(String::New("old", before_space));
   const String& after_obj = String::Handle(String::New("new", after_space));
 
-  EXPECT(before_obj.raw() != after_obj.raw());
+  EXPECT(before_obj.ptr() != after_obj.ptr());
 
   // Allocate the arrays in old space to test the remembered set.
   const Array& before = Array::Handle(Array::New(1, Heap::kOld));
@@ -26,11 +26,11 @@
 
   Become::ElementsForwardIdentity(before, after);
 
-  EXPECT(before_obj.raw() == after_obj.raw());
+  EXPECT(before_obj.ptr() == after_obj.ptr());
 
   GCTestHelper::CollectAllGarbage();
 
-  EXPECT(before_obj.raw() == after_obj.raw());
+  EXPECT(before_obj.ptr() == after_obj.ptr());
 }
 
 ISOLATE_UNIT_TEST_CASE(BecomeFowardOldToOld) {
@@ -50,18 +50,17 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(BecomeForwardPeer) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   const Array& before_obj = Array::Handle(Array::New(0, Heap::kOld));
   const Array& after_obj = Array::Handle(Array::New(0, Heap::kOld));
-  EXPECT(before_obj.raw() != after_obj.raw());
+  EXPECT(before_obj.ptr() != after_obj.ptr());
 
   void* peer = reinterpret_cast<void*>(42);
   void* no_peer = reinterpret_cast<void*>(0);
-  heap->SetPeer(before_obj.raw(), peer);
-  EXPECT_EQ(peer, heap->GetPeer(before_obj.raw()));
-  EXPECT_EQ(no_peer, heap->GetPeer(after_obj.raw()));
+  heap->SetPeer(before_obj.ptr(), peer);
+  EXPECT_EQ(peer, heap->GetPeer(before_obj.ptr()));
+  EXPECT_EQ(no_peer, heap->GetPeer(after_obj.ptr()));
 
   const Array& before = Array::Handle(Array::New(1, Heap::kOld));
   before.SetAt(0, before_obj);
@@ -69,9 +68,9 @@
   after.SetAt(0, after_obj);
   Become::ElementsForwardIdentity(before, after);
 
-  EXPECT(before_obj.raw() == after_obj.raw());
-  EXPECT_EQ(peer, heap->GetPeer(before_obj.raw()));
-  EXPECT_EQ(peer, heap->GetPeer(after_obj.raw()));
+  EXPECT(before_obj.ptr() == after_obj.ptr());
+  EXPECT_EQ(peer, heap->GetPeer(before_obj.ptr()));
+  EXPECT_EQ(peer, heap->GetPeer(after_obj.ptr()));
 }
 
 ISOLATE_UNIT_TEST_CASE(BecomeForwardRememberedObject) {
@@ -81,10 +80,10 @@
   const Array& after_obj = Array::Handle(Array::New(1, Heap::kOld));
   before_obj.SetAt(0, new_element);
   after_obj.SetAt(0, old_element);
-  EXPECT(before_obj.raw()->ptr()->IsRemembered());
-  EXPECT(!after_obj.raw()->ptr()->IsRemembered());
+  EXPECT(before_obj.ptr()->untag()->IsRemembered());
+  EXPECT(!after_obj.ptr()->untag()->IsRemembered());
 
-  EXPECT(before_obj.raw() != after_obj.raw());
+  EXPECT(before_obj.ptr() != after_obj.ptr());
 
   const Array& before = Array::Handle(Array::New(1, Heap::kOld));
   before.SetAt(0, before_obj);
@@ -93,20 +92,20 @@
 
   Become::ElementsForwardIdentity(before, after);
 
-  EXPECT(before_obj.raw() == after_obj.raw());
-  EXPECT(!after_obj.raw()->ptr()->IsRemembered());
+  EXPECT(before_obj.ptr() == after_obj.ptr());
+  EXPECT(!after_obj.ptr()->untag()->IsRemembered());
 
   GCTestHelper::CollectAllGarbage();
 
-  EXPECT(before_obj.raw() == after_obj.raw());
+  EXPECT(before_obj.ptr() == after_obj.ptr());
 }
 
 ISOLATE_UNIT_TEST_CASE(BecomeForwardRememberedCards) {
   const intptr_t length = Heap::kNewAllocatableSize / kWordSize;
   ASSERT(Array::UseCardMarkingForAllocation(length));
   const Array& card_remembered_array = Array::Handle(Array::New(length));
-  EXPECT(card_remembered_array.raw()->ptr()->IsCardRemembered());
-  EXPECT(!card_remembered_array.raw()->ptr()->IsRemembered());
+  EXPECT(card_remembered_array.ptr()->untag()->IsCardRemembered());
+  EXPECT(!card_remembered_array.ptr()->untag()->IsRemembered());
 
   const String& old_element = String::Handle(String::New("old", Heap::kOld));
   const String& new_element = String::Handle(String::New("new", Heap::kNew));
@@ -124,10 +123,10 @@
   after.SetAt(0, new_element);
   Become::ElementsForwardIdentity(before, after);
 
-  EXPECT(old_element.raw() == new_element.raw());
-  EXPECT(old_element.raw()->IsNewObject());
-  EXPECT(card_remembered_array.raw()->ptr()->IsCardRemembered());
-  EXPECT(!card_remembered_array.raw()->ptr()->IsRemembered());
+  EXPECT(old_element.ptr() == new_element.ptr());
+  EXPECT(old_element.ptr()->IsNewObject());
+  EXPECT(card_remembered_array.ptr()->untag()->IsCardRemembered());
+  EXPECT(!card_remembered_array.ptr()->untag()->IsRemembered());
 
   {
     HANDLESCOPE(thread);
@@ -137,9 +136,9 @@
 
   GCTestHelper::CollectAllGarbage();
 
-  EXPECT(old_element.raw() == new_element.raw());
-  EXPECT(card_remembered_array.raw()->ptr()->IsCardRemembered());
-  EXPECT(!card_remembered_array.raw()->ptr()->IsRemembered());
+  EXPECT(old_element.ptr() == new_element.ptr());
+  EXPECT(card_remembered_array.ptr()->untag()->IsCardRemembered());
+  EXPECT(!card_remembered_array.ptr()->untag()->IsRemembered());
 
   {
     HANDLESCOPE(thread);
diff --git a/runtime/vm/heap/compactor.cc b/runtime/vm/heap/compactor.cc
index cd6e83f..5a432f7 100644
--- a/runtime/vm/heap/compactor.cc
+++ b/runtime/vm/heap/compactor.cc
@@ -274,13 +274,14 @@
     const intptr_t length = typed_data_views_.length();
     for (intptr_t i = 0; i < length; ++i) {
       auto raw_view = typed_data_views_[i];
-      const classid_t cid = raw_view->ptr()->typed_data_->GetClassIdMayBeSmi();
+      const classid_t cid =
+          raw_view->untag()->typed_data_->GetClassIdMayBeSmi();
 
       // If we have external typed data we can simply return, since the backing
       // store lives in C-heap and will not move. Otherwise we have to update
       // the inner pointer.
       if (IsTypedDataClassId(cid)) {
-        raw_view->ptr()->RecomputeDataFieldForInternalTypedData();
+        raw_view->untag()->RecomputeDataFieldForInternalTypedData();
       } else {
         ASSERT(IsExternalTypedDataClassId(cid));
       }
@@ -475,9 +476,9 @@
   intptr_t block_dead_size = 0;
   uword current = first_object;
   while (current < block_end) {
-    ObjectPtr obj = ObjectLayout::FromAddr(current);
-    intptr_t size = obj->ptr()->HeapSize();
-    if (obj->ptr()->IsMarked()) {
+    ObjectPtr obj = UntaggedObject::FromAddr(current);
+    intptr_t size = obj->untag()->HeapSize();
+    if (obj->untag()->IsMarked()) {
       forwarding_block->RecordLive(current, size);
       ASSERT(static_cast<intptr_t>(forwarding_block->Lookup(current)) ==
              block_live_size);
@@ -505,9 +506,9 @@
 
   uword old_addr = first_object;
   while (old_addr < block_end) {
-    ObjectPtr old_obj = ObjectLayout::FromAddr(old_addr);
-    intptr_t size = old_obj->ptr()->HeapSize();
-    if (old_obj->ptr()->IsMarked()) {
+    ObjectPtr old_obj = UntaggedObject::FromAddr(old_addr);
+    intptr_t size = old_obj->untag()->HeapSize();
+    if (old_obj->untag()->IsMarked()) {
       uword new_addr = forwarding_block->Lookup(old_addr);
       if (new_addr != free_current_) {
         // The only situation where these two don't match is if we are moving
@@ -526,7 +527,7 @@
         free_end_ = free_page_->object_end();
         ASSERT(free_current_ == new_addr);
       }
-      ObjectPtr new_obj = ObjectLayout::FromAddr(new_addr);
+      ObjectPtr new_obj = UntaggedObject::FromAddr(new_addr);
 
       // Fast path for no movement. There's often a large block of objects at
       // the beginning that don't move.
@@ -536,11 +537,11 @@
                 reinterpret_cast<void*>(old_addr), size);
 
         if (IsTypedDataClassId(new_obj->GetClassId())) {
-          static_cast<TypedDataPtr>(new_obj)->ptr()->RecomputeDataField();
+          static_cast<TypedDataPtr>(new_obj)->untag()->RecomputeDataField();
         }
       }
-      new_obj->ptr()->ClearMarkBit();
-      new_obj->ptr()->VisitPointers(compactor_);
+      new_obj->untag()->ClearMarkBit();
+      new_obj->untag()->VisitPointers(compactor_);
 
       ASSERT(free_current_ == new_addr);
       free_current_ += size;
@@ -573,7 +574,8 @@
 void GCCompactor::SetupImagePageBoundaries() {
   MallocGrowableArray<ImagePageRange> ranges(4);
 
-  OldPage* image_page = Dart::vm_isolate()->heap()->old_space()->image_pages_;
+  OldPage* image_page =
+      Dart::vm_isolate_group()->heap()->old_space()->image_pages_;
   while (image_page != NULL) {
     ImagePageRange range = {image_page->object_start(),
                             image_page->object_end()};
@@ -601,7 +603,7 @@
     return;  // Not moved.
   }
 
-  uword old_addr = ObjectLayout::ToAddr(old_target);
+  uword old_addr = UntaggedObject::ToAddr(old_target);
   intptr_t lo = 0;
   intptr_t hi = image_page_hi_;
   while (lo <= hi) {
@@ -624,7 +626,7 @@
   }
 
   ObjectPtr new_target =
-      ObjectLayout::FromAddr(forwarding_page->Lookup(old_addr));
+      UntaggedObject::FromAddr(forwarding_page->Lookup(old_addr));
   ASSERT(!new_target->IsSmiOrNewObject());
   *ptr = new_target;
 }
@@ -633,9 +635,9 @@
                                              ObjectPtr* first,
                                              ObjectPtr* last) {
   // First we forward all fields of the typed data view.
-  ObjectPtr old_backing = view->ptr()->typed_data_;
+  ObjectPtr old_backing = view->untag()->typed_data_;
   VisitPointers(first, last);
-  ObjectPtr new_backing = view->ptr()->typed_data_;
+  ObjectPtr new_backing = view->untag()->typed_data_;
 
   const bool backing_moved = old_backing != new_backing;
   if (backing_moved) {
@@ -655,10 +657,10 @@
   } else {
     // The backing store didn't move, we therefore don't need to update the
     // inner pointer.
-    if (view->ptr()->data_ == 0) {
-      ASSERT(RawSmiValue(view->ptr()->offset_in_bytes_) == 0 &&
-             RawSmiValue(view->ptr()->length_) == 0 &&
-             view->ptr()->typed_data_ == Object::null());
+    if (view->untag()->data_ == 0) {
+      ASSERT(RawSmiValue(view->untag()->offset_in_bytes_) == 0 &&
+             RawSmiValue(view->untag()->length_) == 0 &&
+             view->untag()->typed_data_ == Object::null());
     }
   }
 }
@@ -674,7 +676,7 @@
 void GCCompactor::VisitHandle(uword addr) {
   FinalizablePersistentHandle* handle =
       reinterpret_cast<FinalizablePersistentHandle*>(addr);
-  ForwardPointer(handle->raw_addr());
+  ForwardPointer(handle->ptr_addr());
 }
 
 void GCCompactor::ForwardStackPointers() {
diff --git a/runtime/vm/heap/freelist.cc b/runtime/vm/heap/freelist.cc
index 2923aee..edc9534 100644
--- a/runtime/vm/heap/freelist.cc
+++ b/runtime/vm/heap/freelist.cc
@@ -22,16 +22,16 @@
   FreeListElement* result = reinterpret_cast<FreeListElement*>(addr);
 
   uword tags = 0;
-  tags = ObjectLayout::SizeTag::update(size, tags);
-  tags = ObjectLayout::ClassIdTag::update(kFreeListElement, tags);
+  tags = UntaggedObject::SizeTag::update(size, tags);
+  tags = UntaggedObject::ClassIdTag::update(kFreeListElement, tags);
   ASSERT((addr & kNewObjectAlignmentOffset) == kOldObjectAlignmentOffset);
-  tags = ObjectLayout::OldBit::update(true, tags);
-  tags = ObjectLayout::OldAndNotMarkedBit::update(true, tags);
-  tags = ObjectLayout::OldAndNotRememberedBit::update(true, tags);
-  tags = ObjectLayout::NewBit::update(false, tags);
+  tags = UntaggedObject::OldBit::update(true, tags);
+  tags = UntaggedObject::OldAndNotMarkedBit::update(true, tags);
+  tags = UntaggedObject::OldAndNotRememberedBit::update(true, tags);
+  tags = UntaggedObject::NewBit::update(false, tags);
   result->tags_ = tags;
 
-  if (size > ObjectLayout::SizeTag::kMaxSizeTag) {
+  if (size > UntaggedObject::SizeTag::kMaxSizeTag) {
     *result->SizeAddress() = size;
   }
   result->set_next(NULL);
@@ -47,7 +47,7 @@
 
 intptr_t FreeListElement::HeaderSizeFor(intptr_t size) {
   if (size == 0) return 0;
-  return ((size > ObjectLayout::SizeTag::kMaxSizeTag) ? 3 : 2) * kWordSize;
+  return ((size > UntaggedObject::SizeTag::kMaxSizeTag) ? 3 : 2) * kWordSize;
 }
 
 FreeList::FreeList() : mutex_() {
@@ -373,41 +373,4 @@
   return NULL;
 }
 
-void FreeList::MergeFrom(FreeList* donor, bool is_protected) {
-  // The [other] free list is from a dying isolate. There are no other threads
-  // accessing it, so there is no need to lock here.
-  MutexLocker ml(&mutex_);
-  for (intptr_t i = 0; i < (kNumLists + 1); ++i) {
-    FreeListElement* donor_head = donor->free_lists_[i];
-    if (donor_head != nullptr) {
-      // If we didn't have a freelist element before we have to set the bit now,
-      // since we will get 1+ elements from [other].
-      FreeListElement* old_head = free_lists_[i];
-      if (old_head == nullptr && i != kNumLists) {
-        free_map_.Set(i, true);
-      }
-
-      // Chain other's list in.
-      FreeListElement* last = donor_head;
-      while (last->next() != nullptr) {
-        last = last->next();
-      }
-
-      if (is_protected) {
-        VirtualMemory::Protect(reinterpret_cast<void*>(last), sizeof(*last),
-                               VirtualMemory::kReadWrite);
-      }
-      last->set_next(old_head);
-      if (is_protected) {
-        VirtualMemory::Protect(reinterpret_cast<void*>(last), sizeof(*last),
-                               VirtualMemory::kReadExecute);
-      }
-      free_lists_[i] = donor_head;
-    }
-  }
-
-  last_free_small_size_ =
-      Utils::Maximum(last_free_small_size_, donor->last_free_small_size_);
-}
-
 }  // namespace dart
diff --git a/runtime/vm/heap/freelist.h b/runtime/vm/heap/freelist.h
index 677a0f2..7a1e2d0 100644
--- a/runtime/vm/heap/freelist.h
+++ b/runtime/vm/heap/freelist.h
@@ -29,7 +29,7 @@
   void set_next(FreeListElement* next) { next_ = next; }
 
   intptr_t HeapSize() {
-    intptr_t size = ObjectLayout::SizeTag::decode(tags_);
+    intptr_t size = UntaggedObject::SizeTag::decode(tags_);
     if (size != 0) return size;
     return *SizeAddress();
   }
@@ -154,8 +154,6 @@
   void set_end(uword value) { end_ = value; }
   void AddUnaccountedSize(intptr_t size) { unaccounted_size_ += size; }
 
-  void MergeFrom(FreeList* donor, bool is_protected);
-
  private:
   static const int kNumLists = 128;
   static const intptr_t kInitialFreeListSearchBudget = 1000;
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index a1d5866..9757a28 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -236,7 +236,7 @@
 
 HeapIterationScope::HeapIterationScope(Thread* thread, bool writable)
     : ThreadStackResource(thread),
-      heap_(isolate()->heap()),
+      heap_(isolate_group()->heap()),
       old_space_(heap_->old_space()),
       writable_(writable) {
   isolate()->safepoint_handler()->SafepointThreads(thread);
@@ -313,7 +313,7 @@
 }
 
 void HeapIterationScope::IterateVMIsolateObjects(ObjectVisitor* visitor) const {
-  Dart::vm_isolate()->heap()->VisitObjects(visitor);
+  Dart::vm_isolate_group()->heap()->VisitObjects(visitor);
 }
 
 void HeapIterationScope::IterateObjectPointers(
@@ -429,7 +429,7 @@
 
 void Heap::EvacuateNewSpace(Thread* thread, GCReason reason) {
   ASSERT((reason != kOldSpace) && (reason != kPromotion));
-  if (thread->isolate_group() == Dart::vm_isolate()->group()) {
+  if (thread->isolate_group() == Dart::vm_isolate_group()) {
     // The vm isolate cannot safely collect garbage due to unvisited read-only
     // handles and slots bootstrapped with RAW_NULL. Ignore GC requests to
     // trigger a nice out-of-memory message instead of a crash in the middle of
@@ -453,7 +453,7 @@
 void Heap::CollectNewSpaceGarbage(Thread* thread, GCReason reason) {
   NoActiveIsolateScope no_active_isolate_scope;
   ASSERT((reason != kOldSpace) && (reason != kPromotion));
-  if (thread->isolate_group() == Dart::vm_isolate()->group()) {
+  if (thread->isolate_group() == Dart::vm_isolate_group()) {
     // The vm isolate cannot safely collect garbage due to unvisited read-only
     // handles and slots bootstrapped with RAW_NULL. Ignore GC requests to
     // trigger a nice out-of-memory message instead of a crash in the middle of
@@ -493,7 +493,7 @@
   if (FLAG_use_compactor) {
     type = kMarkCompact;
   }
-  if (thread->isolate_group() == Dart::vm_isolate()->group()) {
+  if (thread->isolate_group() == Dart::vm_isolate_group()) {
     // The vm isolate cannot safely collect garbage due to unvisited read-only
     // handles and slots bootstrapped with RAW_NULL. Ignore GC requests to
     // trigger a nice out-of-memory message instead of a crash in the middle of
@@ -717,30 +717,6 @@
   gc_on_nth_allocation_ = num_allocations;
 }
 
-void Heap::MergeFrom(Heap* donor) {
-  ASSERT(!donor->read_only_);
-  ASSERT(donor->old_space()->tasks() == 0);
-
-  new_space_.MergeFrom(donor->new_space());
-  old_space_.MergeFrom(donor->old_space());
-
-  for (intptr_t i = 0; i < kNumWeakSelectors; ++i) {
-    // The new space rehashing should not be necessary.
-    new_weak_tables_[i]->MergeFrom(donor->new_weak_tables_[i]);
-    old_weak_tables_[i]->MergeFrom(donor->old_weak_tables_[i]);
-  }
-
-  StoreBufferBlock* block =
-      donor->isolate_group()->store_buffer()->TakeBlocks();
-  while (block != nullptr) {
-    StoreBufferBlock* next = block->next();
-    block->set_next(nullptr);
-    isolate_group()->store_buffer()->PushBlock(block,
-                                               StoreBuffer::kIgnoreThreshold);
-    block = next;
-  }
-}
-
 void Heap::CollectForDebugging() {
   if (gc_on_nth_allocation_ == kNoForcedGarbageCollection) return;
   if (Thread::Current()->IsAtSafepoint()) {
@@ -764,7 +740,7 @@
 
   this->AddRegionsToObjectSet(allocated_set);
   Isolate* vm_isolate = Dart::vm_isolate();
-  vm_isolate->heap()->AddRegionsToObjectSet(allocated_set);
+  vm_isolate->group()->heap()->AddRegionsToObjectSet(allocated_set);
 
   {
     VerifyObjectVisitor object_visitor(isolate_group(), allocated_set,
@@ -780,7 +756,7 @@
     // VM isolate heap is premarked.
     VerifyObjectVisitor vm_object_visitor(isolate_group(), allocated_set,
                                           kRequireMarked);
-    vm_isolate->heap()->VisitObjects(&vm_object_visitor);
+    vm_isolate->group()->heap()->VisitObjects(&vm_object_visitor);
   }
 
   return allocated_set;
@@ -1210,37 +1186,37 @@
 
 NoHeapGrowthControlScope::NoHeapGrowthControlScope()
     : ThreadStackResource(Thread::Current()) {
-  Heap* heap = isolate()->heap();
+  Heap* heap = isolate_group()->heap();
   current_growth_controller_state_ = heap->GrowthControlState();
   heap->DisableGrowthControl();
 }
 
 NoHeapGrowthControlScope::~NoHeapGrowthControlScope() {
-  Heap* heap = isolate()->heap();
+  Heap* heap = isolate_group()->heap();
   heap->SetGrowthControlState(current_growth_controller_state_);
 }
 
 WritableVMIsolateScope::WritableVMIsolateScope(Thread* thread)
     : ThreadStackResource(thread) {
   if (FLAG_write_protect_code && FLAG_write_protect_vm_isolate) {
-    Dart::vm_isolate()->heap()->WriteProtect(false);
+    Dart::vm_isolate_group()->heap()->WriteProtect(false);
   }
 }
 
 WritableVMIsolateScope::~WritableVMIsolateScope() {
-  ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0);
+  ASSERT(Dart::vm_isolate_group()->heap()->UsedInWords(Heap::kNew) == 0);
   if (FLAG_write_protect_code && FLAG_write_protect_vm_isolate) {
-    Dart::vm_isolate()->heap()->WriteProtect(true);
+    Dart::vm_isolate_group()->heap()->WriteProtect(true);
   }
 }
 
 WritableCodePages::WritableCodePages(Thread* thread, Isolate* isolate)
     : StackResource(thread), isolate_(isolate) {
-  isolate_->heap()->WriteProtectCode(false);
+  isolate_->group()->heap()->WriteProtectCode(false);
 }
 
 WritableCodePages::~WritableCodePages() {
-  isolate_->heap()->WriteProtectCode(true);
+  isolate_->group()->heap()->WriteProtectCode(true);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 026d793..ac1f0ff 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -300,8 +300,9 @@
   void PrintMemoryUsageJSON(JSONObject* jsobj) const;
 
   // The heap map contains the sizes and class ids for the objects in each page.
-  void PrintHeapMapToJSONStream(Isolate* isolate, JSONStream* stream) {
-    old_space_.PrintHeapMapToJSONStream(isolate, stream);
+  void PrintHeapMapToJSONStream(IsolateGroup* isolate_group,
+                                JSONStream* stream) {
+    old_space_.PrintHeapMapToJSONStream(isolate_group, stream);
   }
 #endif  // PRODUCT
 
@@ -322,8 +323,6 @@
 
   void CollectOnNthAllocation(intptr_t num_allocations);
 
-  void MergeFrom(Heap* donor);
-
  private:
   class GCStats : public ValueObject {
    public:
@@ -429,7 +428,7 @@
   friend class ServiceEvent;
   friend class Scavenger;             // VerifyGC
   friend class PageSpace;             // VerifyGC
-  friend class IsolateReloadContext;  // VisitObjects
+  friend class ProgramReloadContext;  // VisitObjects
   friend class ClassFinalizer;        // VisitObjects
   friend class HeapIterationScope;    // VisitObjects
   friend class ProgramVisitor;        // VisitObjectsImagePages
diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc
index b2c1009..fc85962 100644
--- a/runtime/vm/heap/heap_test.cc
+++ b/runtime/vm/heap/heap_test.cc
@@ -94,7 +94,7 @@
   const Class& cls = Class::Handle(
       lib.LookupClass(String::Handle(Symbols::New(Thread::Current(), name))));
   EXPECT(!cls.IsNull());  // No ambiguity error expected.
-  return cls.raw();
+  return cls.ptr();
 }
 
 TEST_CASE(ClassHeapStats) {
@@ -109,8 +109,8 @@
       "  return new A();\n"
       "}\n";
   Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, NULL);
-  Isolate* isolate = Isolate::Current();
-  ClassTable* class_table = isolate->class_table();
+  auto isolate_group = IsolateGroup::Current();
+  ClassTable* class_table = isolate_group->class_table();
   {
     // GC before main so allocations during the tests don't cause unexpected GC.
     TransitionNativeToVM transition(thread);
@@ -135,7 +135,7 @@
       CountObjectsVisitor visitor(thread, class_table->NumCids());
       HeapIterationScope iter(thread);
       iter.IterateObjects(&visitor);
-      isolate->group()->VisitWeakPersistentHandles(&visitor);
+      isolate_group->VisitWeakPersistentHandles(&visitor);
       EXPECT_EQ(2, visitor.new_count_[cid]);
       EXPECT_EQ(0, visitor.old_count_[cid]);
     }
@@ -148,7 +148,7 @@
       CountObjectsVisitor visitor(thread, class_table->NumCids());
       HeapIterationScope iter(thread);
       iter.IterateObjects(&visitor);
-      isolate->group()->VisitWeakPersistentHandles(&visitor);
+      isolate_group->VisitWeakPersistentHandles(&visitor);
       EXPECT_EQ(1, visitor.new_count_[cid]);
       EXPECT_EQ(0, visitor.old_count_[cid]);
     }
@@ -162,7 +162,7 @@
       CountObjectsVisitor visitor(thread, class_table->NumCids());
       HeapIterationScope iter(thread);
       iter.IterateObjects(&visitor);
-      isolate->group()->VisitWeakPersistentHandles(&visitor);
+      isolate_group->VisitWeakPersistentHandles(&visitor);
       EXPECT_EQ(0, visitor.new_count_[cid]);
       EXPECT_EQ(1, visitor.old_count_[cid]);
     }
@@ -175,7 +175,7 @@
       CountObjectsVisitor visitor(thread, class_table->NumCids());
       HeapIterationScope iter(thread);
       iter.IterateObjects(&visitor);
-      isolate->group()->VisitWeakPersistentHandles(&visitor);
+      isolate_group->VisitWeakPersistentHandles(&visitor);
       EXPECT_EQ(0, visitor.new_count_[cid]);
       EXPECT_EQ(1, visitor.old_count_[cid]);
     }
@@ -187,7 +187,7 @@
       CountObjectsVisitor visitor(thread, class_table->NumCids());
       HeapIterationScope iter(thread);
       iter.IterateObjects(&visitor);
-      isolate->group()->VisitWeakPersistentHandles(&visitor);
+      isolate_group->VisitWeakPersistentHandles(&visitor);
       EXPECT_EQ(0, visitor.new_count_[cid]);
       EXPECT_EQ(1, visitor.old_count_[cid]);
     }
@@ -203,7 +203,7 @@
       CountObjectsVisitor visitor(thread, class_table->NumCids());
       HeapIterationScope iter(thread);
       iter.IterateObjects(&visitor);
-      isolate->group()->VisitWeakPersistentHandles(&visitor);
+      isolate_group->VisitWeakPersistentHandles(&visitor);
       EXPECT_EQ(0, visitor.new_count_[cid]);
       EXPECT_EQ(0, visitor.old_count_[cid]);
     }
@@ -234,16 +234,15 @@
 };
 
 ISOLATE_UNIT_TEST_CASE(FindObject) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
   Heap::Space spaces[2] = {Heap::kOld, Heap::kNew};
   for (size_t space = 0; space < ARRAY_SIZE(spaces); ++space) {
     const String& obj = String::Handle(String::New("x", spaces[space]));
     {
       HeapIterationScope iteration(thread);
       NoSafepointScope no_safepoint;
-      FindOnly find_only(obj.raw());
-      EXPECT(obj.raw() == heap->FindObject(&find_only));
+      FindOnly find_only(obj.ptr());
+      EXPECT(obj.ptr() == heap->FindObject(&find_only));
     }
   }
   {
@@ -261,17 +260,16 @@
   // progress.
   GCTestHelper::WaitForGCTasks();
 
-  Heap* heap = Thread::Current()->isolate()->heap();
-  EXPECT(heap->Contains(ObjectLayout::ToAddr(obj.raw())));
+  Heap* heap = IsolateGroup::Current()->heap();
+  EXPECT(heap->Contains(UntaggedObject::ToAddr(obj.ptr())));
   heap->WriteProtect(true);
-  EXPECT(heap->Contains(ObjectLayout::ToAddr(obj.raw())));
+  EXPECT(heap->Contains(UntaggedObject::ToAddr(obj.ptr())));
   heap->WriteProtect(false);
-  EXPECT(heap->Contains(ObjectLayout::ToAddr(obj.raw())));
+  EXPECT(heap->Contains(UntaggedObject::ToAddr(obj.ptr())));
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_DeadOldToNew) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   heap->WaitForMarkerTasks(thread);  // Finalize marking to get live size.
@@ -294,8 +292,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_DeadNewToOld) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   heap->WaitForMarkerTasks(thread);  // Finalize marking to get live size.
@@ -318,8 +315,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_DeadGenCycle) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   heap->WaitForMarkerTasks(thread);  // Finalize marking to get live size.
@@ -343,8 +339,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_LiveNewToOld) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   heap->WaitForMarkerTasks(thread);  // Finalize marking to get live size.
@@ -366,8 +361,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_LiveOldToNew) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   heap->WaitForMarkerTasks(thread);  // Finalize marking to get live size.
@@ -389,8 +383,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_LiveOldDeadNew) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   heap->WaitForMarkerTasks(thread);  // Finalize marking to get live size.
@@ -412,8 +405,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_LiveNewDeadOld) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   heap->WaitForMarkerTasks(thread);  // Finalize marking to get live size.
@@ -435,8 +427,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_LiveNewToOldChain) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   intptr_t size_before =
@@ -459,8 +450,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(CollectAllGarbage_LiveOldToNewChain) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
 
   heap->CollectAllGarbage();
   intptr_t size_before =
@@ -485,8 +475,8 @@
 static void NoopFinalizer(void* isolate_callback_data, void* peer) {}
 
 ISOLATE_UNIT_TEST_CASE(ExternalPromotion) {
-  Isolate* isolate = Isolate::Current();
-  Heap* heap = isolate->heap();
+  auto isolate_group = IsolateGroup::Current();
+  Heap* heap = isolate_group->heap();
 
   heap->CollectAllGarbage();
   intptr_t size_before = kWordSize * (heap->new_space()->ExternalInWords() +
@@ -496,7 +486,8 @@
   Array& neu = Array::Handle();
   for (intptr_t i = 0; i < 100; i++) {
     neu = Array::New(1, Heap::kNew);
-    FinalizablePersistentHandle::New(isolate, neu, NULL, NoopFinalizer, 1 * MB,
+    FinalizablePersistentHandle::New(isolate_group, neu, NULL, NoopFinalizer,
+                                     1 * MB,
                                      /*auto_delete=*/true);
     old.SetAt(i, neu);
   }
@@ -548,8 +539,9 @@
       Bequest* bequest = message->bequest();
       PersistentHandle* handle = bequest->handle();
       // Object in the receiving isolate's heap.
-      EXPECT(isolate()->heap()->Contains(ObjectLayout::ToAddr(handle->raw())));
-      response_obj = handle->raw();
+      EXPECT(isolate()->group()->heap()->Contains(
+          UntaggedObject::ToAddr(handle->ptr())));
+      response_obj = handle->ptr();
       isolate()->group()->api_state()->FreePersistentHandle(handle);
     } else {
       Thread* thread = Thread::Current();
@@ -558,12 +550,12 @@
     }
     if (response_obj.IsString()) {
       String& response = String::Handle();
-      response ^= response_obj.raw();
+      response ^= response_obj.ptr();
       msg_.reset(Utils::StrDup(response.ToCString()));
     } else {
       ASSERT(response_obj.IsArray());
       Array& response_array = Array::Handle();
-      response_array ^= response_obj.raw();
+      response_array ^= response_obj.ptr();
       ASSERT(response_array.Length() == 1);
       ExternalTypedData& response = ExternalTypedData::Handle();
       response ^= response_array.At(0);
@@ -606,7 +598,7 @@
       String& string = String::Handle(String::New(TEST_MESSAGE));
       PersistentHandle* handle =
           Isolate::Current()->group()->api_state()->AllocatePersistentHandle();
-      handle->set_raw(string.raw());
+      handle->set_ptr(string.ptr());
 
       reinterpret_cast<Isolate*>(worker)->bequeath(
           std::unique_ptr<Bequest>(new Bequest(handle, port_id)));
@@ -641,7 +633,7 @@
 
     PersistentHandle* handle =
         Isolate::Current()->group()->api_state()->AllocatePersistentHandle();
-    handle->set_raw(string.raw());
+    handle->set_ptr(string.ptr());
 
     reinterpret_cast<Isolate*>(worker)->bequeath(
         std::unique_ptr<Bequest>(new Bequest(handle, port_id)));
@@ -662,14 +654,15 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(ExternalAllocationStats) {
-  Isolate* isolate = thread->isolate();
-  Heap* heap = thread->heap();
+  auto isolate_group = thread->isolate_group();
+  Heap* heap = isolate_group->heap();
 
   Array& old = Array::Handle(Array::New(100, Heap::kOld));
   Array& neu = Array::Handle();
   for (intptr_t i = 0; i < 100; i++) {
     neu = Array::New(1, Heap::kNew);
-    FinalizablePersistentHandle::New(isolate, neu, NULL, NoopFinalizer, 1 * MB,
+    FinalizablePersistentHandle::New(isolate_group, neu, NULL, NoopFinalizer,
+                                     1 * MB,
                                      /*auto_delete=*/true);
     old.SetAt(i, neu);
 
@@ -679,10 +672,11 @@
       HeapTestHelper::Scavenge(thread);
     }
 
-    CountObjectsVisitor visitor(thread, isolate->class_table()->NumCids());
+    CountObjectsVisitor visitor(thread,
+                                isolate_group->class_table()->NumCids());
     HeapIterationScope iter(thread);
     iter.IterateObjects(&visitor);
-    isolate->group()->VisitWeakPersistentHandles(&visitor);
+    isolate_group->VisitWeakPersistentHandles(&visitor);
     EXPECT_LE(visitor.old_external_size_[kArrayCid],
               heap->old_space()->ExternalInWords() * kWordSize);
     EXPECT_LE(visitor.new_external_size_[kArrayCid],
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index bceb31c..5a6229b 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -50,18 +50,18 @@
     WeakPropertyPtr cur_weak = delayed_weak_properties_;
     delayed_weak_properties_ = WeakProperty::null();
     while (cur_weak != WeakProperty::null()) {
-      WeakPropertyPtr next_weak = cur_weak->ptr()->next_;
-      ObjectPtr raw_key = cur_weak->ptr()->key_;
+      WeakPropertyPtr next_weak = cur_weak->untag()->next_;
+      ObjectPtr raw_key = cur_weak->untag()->key_;
       // Reset the next pointer in the weak property.
-      cur_weak->ptr()->next_ = WeakProperty::null();
-      if (raw_key->ptr()->IsMarked()) {
-        ObjectPtr raw_val = cur_weak->ptr()->value_;
-        marked =
-            marked || (raw_val->IsHeapObject() && !raw_val->ptr()->IsMarked());
+      cur_weak->untag()->next_ = WeakProperty::null();
+      if (raw_key->untag()->IsMarked()) {
+        ObjectPtr raw_val = cur_weak->untag()->value_;
+        marked = marked ||
+                 (raw_val->IsHeapObject() && !raw_val->untag()->IsMarked());
 
         // The key is marked so we make sure to properly visit all pointers
         // originating from this weak property.
-        cur_weak->ptr()->VisitPointersNonvirtual(this);
+        cur_weak->untag()->VisitPointersNonvirtual(this);
       } else {
         // Requeue this weak property to be handled later.
         EnqueueWeakProperty(cur_weak);
@@ -89,7 +89,7 @@
 
         intptr_t size;
         if (class_id != kWeakPropertyCid) {
-          size = raw_obj->ptr()->VisitPointersNonvirtual(this);
+          size = raw_obj->untag()->VisitPointersNonvirtual(this);
         } else {
           WeakPropertyPtr raw_weak = static_cast<WeakPropertyPtr>(raw_obj);
           size = ProcessWeakProperty(raw_weak, /* did_mark */ true);
@@ -132,25 +132,25 @@
     ASSERT(raw_weak->IsHeapObject());
     ASSERT(raw_weak->IsOldObject());
     ASSERT(raw_weak->IsWeakProperty());
-    ASSERT(raw_weak->ptr()->IsMarked());
-    ASSERT(raw_weak->ptr()->next_ == WeakProperty::null());
-    raw_weak->ptr()->next_ = delayed_weak_properties_;
+    ASSERT(raw_weak->untag()->IsMarked());
+    ASSERT(raw_weak->untag()->next_ == WeakProperty::null());
+    raw_weak->untag()->next_ = delayed_weak_properties_;
     delayed_weak_properties_ = raw_weak;
   }
 
   intptr_t ProcessWeakProperty(WeakPropertyPtr raw_weak, bool did_mark) {
     // The fate of the weak property is determined by its key.
-    ObjectPtr raw_key = LoadPointerIgnoreRace(&raw_weak->ptr()->key_);
+    ObjectPtr raw_key = LoadPointerIgnoreRace(&raw_weak->untag()->key_);
     if (raw_key->IsHeapObject() && raw_key->IsOldObject() &&
-        !raw_key->ptr()->IsMarked()) {
+        !raw_key->untag()->IsMarked()) {
       // Key was white. Enqueue the weak property.
       if (did_mark) {
         EnqueueWeakProperty(raw_weak);
       }
-      return raw_weak->ptr()->HeapSize();
+      return raw_weak->untag()->HeapSize();
     }
     // Key is gray or black. Make the weak property black.
-    return raw_weak->ptr()->VisitPointersNonvirtual(this);
+    return raw_weak->untag()->VisitPointersNonvirtual(this);
   }
 
   void ProcessDeferredMarking() {
@@ -162,7 +162,7 @@
       const intptr_t class_id = raw_obj->GetClassId();
       intptr_t size;
       if (class_id != kWeakPropertyCid) {
-        size = raw_obj->ptr()->VisitPointersNonvirtual(this);
+        size = raw_obj->untag()->VisitPointersNonvirtual(this);
       } else {
         WeakPropertyPtr raw_weak = static_cast<WeakPropertyPtr>(raw_obj);
         size = ProcessWeakProperty(raw_weak, did_mark);
@@ -188,9 +188,9 @@
     delayed_weak_properties_ = WeakProperty::null();
     intptr_t weak_properties_cleared = 0;
     while (cur_weak != WeakProperty::null()) {
-      WeakPropertyPtr next_weak = cur_weak->ptr()->next_;
-      cur_weak->ptr()->next_ = WeakProperty::null();
-      RELEASE_ASSERT(!cur_weak->ptr()->key_->ptr()->IsMarked());
+      WeakPropertyPtr next_weak = cur_weak->untag()->next_;
+      cur_weak->untag()->next_ = WeakProperty::null();
+      RELEASE_ASSERT(!cur_weak->untag()->key_->untag()->IsMarked());
       WeakProperty::Clear(cur_weak);
       weak_properties_cleared++;
       // Advance to next weak property in the queue.
@@ -209,7 +209,7 @@
     ASSERT(raw_obj->IsOldObject());
 
     // Push the marked object on the marking stack.
-    ASSERT(raw_obj->ptr()->IsMarked());
+    ASSERT(raw_obj->untag()->IsMarked());
     work_list_.Push(raw_obj);
   }
 
@@ -219,10 +219,10 @@
       raw_obj = OldPage::ToWritable(raw_obj);
     }
     if (!sync) {
-      raw_obj->ptr()->SetMarkBitUnsynchronized();
+      raw_obj->untag()->SetMarkBitUnsynchronized();
       return true;
     } else {
-      return raw_obj->ptr()->TryAcquireMarkBit();
+      return raw_obj->untag()->TryAcquireMarkBit();
     }
   }
 
@@ -244,7 +244,7 @@
     // was allocated after the concurrent marker started. It can read either a
     // zero or the header of an object allocated black, both of which appear
     // marked.
-    if (raw_obj->ptr()->IsMarkedIgnoreRace()) {
+    if (raw_obj->untag()->IsMarkedIgnoreRace()) {
       return;
     }
 
@@ -290,7 +290,7 @@
   if (!raw_obj->IsOldObject()) {
     return false;
   }
-  return !raw_obj->ptr()->IsMarked();
+  return !raw_obj->untag()->IsMarked();
 }
 
 class MarkingWeakVisitor : public HandleVisitor {
@@ -302,7 +302,7 @@
   void VisitHandle(uword addr) {
     FinalizablePersistentHandle* handle =
         reinterpret_cast<FinalizablePersistentHandle*>(addr);
-    ObjectPtr raw_obj = handle->raw();
+    ObjectPtr raw_obj = handle->ptr();
     if (IsUnreachable(raw_obj)) {
       handle->UpdateUnreachable(thread()->isolate_group());
     }
@@ -426,7 +426,7 @@
     for (intptr_t i = 0; i < size; i++) {
       if (table->IsValidEntryAtExclusive(i)) {
         ObjectPtr raw_obj = table->ObjectAtExclusive(i);
-        if (raw_obj->IsHeapObject() && !raw_obj->ptr()->IsMarked()) {
+        if (raw_obj->IsHeapObject() && !raw_obj->untag()->IsMarked()) {
           table->InvalidateAtExclusive(i);
         }
       }
@@ -447,8 +447,8 @@
     while (!reading->IsEmpty()) {
       ObjectPtr raw_object = reading->Pop();
       ASSERT(!raw_object->IsForwardingCorpse());
-      ASSERT(raw_object->ptr()->IsRemembered());
-      if (raw_object->ptr()->IsMarked()) {
+      ASSERT(raw_object->untag()->IsRemembered());
+      if (raw_object->untag()->IsMarked()) {
         writing->Push(raw_object);
         if (writing->IsFull()) {
           store_buffer->PushBlock(writing, StoreBuffer::kIgnoreThreshold);
@@ -473,7 +473,7 @@
     for (ObjectPtr* current = first; current <= last; current++) {
       ObjectPtr raw_obj = *current;
       ASSERT(raw_obj->IsHeapObject());
-      if (raw_obj->IsOldObject() && !raw_obj->ptr()->IsMarked()) {
+      if (raw_obj->IsOldObject() && !raw_obj->untag()->IsMarked()) {
         // Object has become garbage. Replace it will null.
         *current = Object::null();
       }
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index d3b62fa..43628c6 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -97,9 +97,9 @@
   uword obj_addr = object_start();
   uword end_addr = object_end();
   while (obj_addr < end_addr) {
-    ObjectPtr raw_obj = ObjectLayout::FromAddr(obj_addr);
+    ObjectPtr raw_obj = UntaggedObject::FromAddr(obj_addr);
     visitor->VisitObject(raw_obj);
-    obj_addr += raw_obj->ptr()->HeapSize();
+    obj_addr += raw_obj->untag()->HeapSize();
   }
   ASSERT(obj_addr == end_addr);
 }
@@ -111,8 +111,8 @@
   uword obj_addr = object_start();
   uword end_addr = object_end();
   while (obj_addr < end_addr) {
-    ObjectPtr raw_obj = ObjectLayout::FromAddr(obj_addr);
-    obj_addr += raw_obj->ptr()->VisitPointers(visitor);
+    ObjectPtr raw_obj = UntaggedObject::FromAddr(obj_addr);
+    obj_addr += raw_obj->untag()->VisitPointers(visitor);
   }
   ASSERT(obj_addr == end_addr);
 }
@@ -128,11 +128,12 @@
 
   bool table_is_empty = false;
 
-  ArrayPtr obj = static_cast<ArrayPtr>(ObjectLayout::FromAddr(object_start()));
+  ArrayPtr obj =
+      static_cast<ArrayPtr>(UntaggedObject::FromAddr(object_start()));
   ASSERT(obj->IsArray());
-  ASSERT(obj->ptr()->IsCardRemembered());
-  ObjectPtr* obj_from = obj->ptr()->from();
-  ObjectPtr* obj_to = obj->ptr()->to(Smi::Value(obj->ptr()->length_));
+  ASSERT(obj->untag()->IsCardRemembered());
+  ObjectPtr* obj_from = obj->untag()->from();
+  ObjectPtr* obj_to = obj->untag()->to(Smi::Value(obj->untag()->length_));
 
   const intptr_t size = card_table_size();
   for (intptr_t i = 0; i < size; i++) {
@@ -183,10 +184,10 @@
   uword end_addr = object_end();
   if (visitor->VisitRange(obj_addr, end_addr)) {
     while (obj_addr < end_addr) {
-      ObjectPtr raw_obj = ObjectLayout::FromAddr(obj_addr);
-      uword next_obj_addr = obj_addr + raw_obj->ptr()->HeapSize();
+      ObjectPtr raw_obj = UntaggedObject::FromAddr(obj_addr);
+      uword next_obj_addr = obj_addr + raw_obj->untag()->HeapSize();
       if (visitor->VisitRange(obj_addr, next_obj_addr) &&
-          raw_obj->ptr()->FindObject(visitor)) {
+          raw_obj->untag()->FindObject(visitor)) {
         return raw_obj;  // Found object, return it.
       }
       obj_addr = next_obj_addr;
@@ -887,7 +888,7 @@
  public:
   explicit HeapMapAsJSONVisitor(JSONArray* array) : array_(array) {}
   virtual void VisitObject(ObjectPtr obj) {
-    array_->AddValue(obj->ptr()->HeapSize() / kObjectAlignment);
+    array_->AddValue(obj->untag()->HeapSize() / kObjectAlignment);
     array_->AddValue(obj->GetClassId());
   }
 
@@ -895,7 +896,7 @@
   JSONArray* array_;
 };
 
-void PageSpace::PrintHeapMapToJSONStream(Isolate* isolate,
+void PageSpace::PrintHeapMapToJSONStream(IsolateGroup* isolate_group,
                                          JSONStream* stream) const {
   JSONObject heap_map(stream);
   heap_map.AddProperty("type", "HeapMap");
@@ -905,7 +906,7 @@
   heap_map.AddProperty("pageSizeBytes", kOldPageSizeInWords * kWordSize);
   {
     JSONObject class_list(&heap_map, "classList");
-    isolate->class_table()->PrintToJSONObject(&class_list);
+    isolate_group->class_table()->PrintToJSONObject(&class_list);
   }
   {
     // "pages" is an array [page0, page1, ..., pageN], each page of the form
@@ -1034,7 +1035,7 @@
   if (oom_reservation_ == nullptr) {
     return false;
   }
-  ObjectLayout* ptr = reinterpret_cast<ObjectLayout*>(oom_reservation_);
+  UntaggedObject* ptr = reinterpret_cast<UntaggedObject*>(oom_reservation_);
   if (!ptr->IsMarked()) {
     ptr->SetMarkBit();
   }
@@ -1056,10 +1057,10 @@
     // FreeListElements are generally held untagged, but ObjectPointerVisitors
     // expect tagged pointers.
     ObjectPtr ptr =
-        ObjectLayout::FromAddr(reinterpret_cast<uword>(oom_reservation_));
+        UntaggedObject::FromAddr(reinterpret_cast<uword>(oom_reservation_));
     visitor->VisitPointer(&ptr);
     oom_reservation_ =
-        reinterpret_cast<FreeListElement*>(ObjectLayout::ToAddr(ptr));
+        reinterpret_cast<FreeListElement*>(UntaggedObject::ToAddr(ptr));
   }
 }
 
@@ -1436,7 +1437,7 @@
 }
 
 bool PageSpace::IsObjectFromImagePages(dart::ObjectPtr object) {
-  uword object_addr = ObjectLayout::ToAddr(object);
+  uword object_addr = UntaggedObject::ToAddr(object);
   OldPage* image_page = image_pages_;
   while (image_page != nullptr) {
     if (image_page->Contains(object_addr)) {
@@ -1447,95 +1448,6 @@
   return false;
 }
 
-static void AppendList(OldPage** pages,
-                       OldPage** pages_tail,
-                       OldPage** other_pages,
-                       OldPage** other_pages_tail) {
-  ASSERT((*pages == nullptr) == (*pages_tail == nullptr));
-  ASSERT((*other_pages == nullptr) == (*other_pages_tail == nullptr));
-
-  if (*other_pages != nullptr) {
-    if (*pages_tail == nullptr) {
-      *pages = *other_pages;
-      *pages_tail = *other_pages_tail;
-    } else {
-      const bool is_execute = FLAG_write_protect_code &&
-                              (*pages_tail)->type() == OldPage::kExecutable;
-      if (is_execute) {
-        (*pages_tail)->WriteProtect(false);
-      }
-      (*pages_tail)->set_next(*other_pages);
-      if (is_execute) {
-        (*pages_tail)->WriteProtect(true);
-      }
-      *pages_tail = *other_pages_tail;
-    }
-    *other_pages = nullptr;
-    *other_pages_tail = nullptr;
-  }
-}
-
-static void EnsureEqualImagePages(OldPage* pages, OldPage* other_pages) {
-#if defined(DEBUG)
-  while (pages != nullptr) {
-    ASSERT((pages == nullptr) == (other_pages == nullptr));
-    ASSERT(pages->object_start() == other_pages->object_start());
-    ASSERT(pages->object_end() == other_pages->object_end());
-    pages = pages->next();
-    other_pages = other_pages->next();
-  }
-#endif
-}
-
-void PageSpace::MergeFrom(PageSpace* donor) {
-  donor->AbandonBumpAllocation();
-
-  ASSERT(donor->tasks_ == 0);
-  ASSERT(donor->concurrent_marker_tasks_ == 0);
-  ASSERT(donor->phase_ == kDone);
-  DEBUG_ASSERT(donor->iterating_thread_ == nullptr);
-  ASSERT(donor->marker_ == nullptr);
-
-  for (intptr_t i = 0; i < num_freelists_; ++i) {
-    ASSERT(donor->freelists_[i].top() == 0);
-    ASSERT(donor->freelists_[i].end() == 0);
-    const bool is_protected =
-        FLAG_write_protect_code && i == OldPage::kExecutable;
-    freelists_[i].MergeFrom(&donor->freelists_[i], is_protected);
-    donor->freelists_[i].Reset();
-  }
-
-  // The freelist locks will be taken in MergeOtherFreelist above, and the
-  // locking order is the freelist locks are taken before the page list locks,
-  // so don't take the pages lock until after MergeOtherFreelist.
-  MutexLocker ml(&pages_lock_);
-  MutexLocker ml2(&donor->pages_lock_);
-
-  AppendList(&pages_, &pages_tail_, &donor->pages_, &donor->pages_tail_);
-  AppendList(&exec_pages_, &exec_pages_tail_, &donor->exec_pages_,
-             &donor->exec_pages_tail_);
-  AppendList(&large_pages_, &large_pages_tail_, &donor->large_pages_,
-             &donor->large_pages_tail_);
-  // We intentionall do not merge [image_pages_] beause [this] and [other] have
-  // the same mmap()ed image page areas.
-  EnsureEqualImagePages(image_pages_, donor->image_pages_);
-
-  // We intentionaly do not increase [max_capacity_in_words_] because this can
-  // lead [max_capacity_in_words_] to become larger and larger and eventually
-  // wrap-around and become negative.
-  allocated_black_in_words_ += donor->allocated_black_in_words_;
-  gc_time_micros_ += donor->gc_time_micros_;
-  collections_ += donor->collections_;
-
-  usage_.capacity_in_words += donor->usage_.capacity_in_words;
-  usage_.used_in_words += donor->usage_.used_in_words;
-  usage_.external_in_words += donor->usage_.external_in_words;
-
-  page_space_controller_.MergeFrom(&donor->page_space_controller_);
-
-  ASSERT(FLAG_concurrent_mark || donor->enable_concurrent_mark_ == false);
-}
-
 PageSpaceController::PageSpaceController(Heap* heap,
                                          int heap_growth_ratio,
                                          int heap_growth_max,
@@ -1771,12 +1683,6 @@
   // TODO(rmacnak): Hasten the soft threshold at some discount?
 }
 
-void PageSpaceController::MergeFrom(PageSpaceController* donor) {
-  last_usage_.capacity_in_words += donor->last_usage_.capacity_in_words;
-  last_usage_.used_in_words += donor->last_usage_.used_in_words;
-  last_usage_.external_in_words += donor->last_usage_.external_in_words;
-}
-
 void PageSpaceGarbageCollectionHistory::AddGarbageCollectionTime(int64_t start,
                                                                  int64_t end) {
   Entry entry;
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index a786f78..3004841 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -95,9 +95,9 @@
     if (alias_offset == 0) {
       return obj;  // Not aliased.
     }
-    uword addr = ObjectLayout::ToAddr(obj);
+    uword addr = UntaggedObject::ToAddr(obj);
     if (memory->Contains(addr)) {
-      return ObjectLayout::FromAddr(addr + alias_offset);
+      return UntaggedObject::FromAddr(addr + alias_offset);
     }
     // obj is executable.
     ASSERT(memory->ContainsAlias(addr));
@@ -112,9 +112,9 @@
     if (alias_offset == 0) {
       return obj;  // Not aliased.
     }
-    uword addr = ObjectLayout::ToAddr(obj);
+    uword addr = UntaggedObject::ToAddr(obj);
     if (memory->ContainsAlias(addr)) {
-      return ObjectLayout::FromAddr(addr - alias_offset);
+      return UntaggedObject::FromAddr(addr - alias_offset);
     }
     // obj is writable.
     ASSERT(memory->Contains(addr));
@@ -240,8 +240,6 @@
   friend class PageSpace;  // For MergeOtherPageSpaceController
 
   void RecordUpdate(SpaceUsage before, SpaceUsage after, const char* reason);
-  void MergeFrom(PageSpaceController* donor);
-
   void RecordUpdate(SpaceUsage before,
                     SpaceUsage after,
                     intptr_t growth_in_pages,
@@ -412,7 +410,8 @@
 
 #ifndef PRODUCT
   void PrintToJSONObject(JSONObject* object) const;
-  void PrintHeapMapToJSONStream(Isolate* isolate, JSONStream* stream) const;
+  void PrintHeapMapToJSONStream(IsolateGroup* isolate_group,
+                                JSONStream* stream) const;
 #endif  // PRODUCT
 
   void AllocateBlack(intptr_t size) {
@@ -489,8 +488,6 @@
 
   bool IsObjectFromImagePages(ObjectPtr object);
 
-  void MergeFrom(PageSpace* donor);
-
  private:
   // Ids for time and data records in Heap::GCStats.
   enum {
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 3f6f09d..baba05a 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -43,7 +43,7 @@
 // object headers, and which doesn't intersect with the target address because
 // of object alignment.
 enum {
-  kForwardingMask = 1 << ObjectLayout::kCardRememberedBit,
+  kForwardingMask = 1 << UntaggedObject::kCardRememberedBit,
   kNotForwarded = 0,
   kForwarded = kForwardingMask,
 };
@@ -127,22 +127,23 @@
     // First we forward all fields of the typed data view.
     VisitPointers(first, last);
 
-    if (view->ptr()->data_ == nullptr) {
-      ASSERT(RawSmiValue(view->ptr()->offset_in_bytes_) == 0 &&
-             RawSmiValue(view->ptr()->length_) == 0);
+    if (view->untag()->data_ == nullptr) {
+      ASSERT(RawSmiValue(view->untag()->offset_in_bytes_) == 0 &&
+             RawSmiValue(view->untag()->length_) == 0);
       return;
     }
 
     // Validate 'this' is a typed data view.
     const uword view_header =
-        *reinterpret_cast<uword*>(ObjectLayout::ToAddr(view));
+        *reinterpret_cast<uword*>(UntaggedObject::ToAddr(view));
     ASSERT(!IsForwarding(view_header) || view->IsOldObject());
     ASSERT(IsTypedDataViewClassId(view->GetClassIdMayBeSmi()));
 
     // Validate that the backing store is not a forwarding word.
-    TypedDataBasePtr td = view->ptr()->typed_data_;
+    TypedDataBasePtr td = view->untag()->typed_data_;
     ASSERT(td->IsHeapObject());
-    const uword td_header = *reinterpret_cast<uword*>(ObjectLayout::ToAddr(td));
+    const uword td_header =
+        *reinterpret_cast<uword*>(UntaggedObject::ToAddr(td));
     ASSERT(!IsForwarding(td_header) || td->IsOldObject());
 
     // We can always obtain the class id from the forwarded backing store.
@@ -156,7 +157,7 @@
 
     // Now we update the inner pointer.
     ASSERT(IsTypedDataClassId(cid));
-    view->ptr()->RecomputeDataFieldForInternalTypedData();
+    view->untag()->RecomputeDataFieldForInternalTypedData();
   }
 
   virtual void VisitPointers(ObjectPtr* first, ObjectPtr* last) {
@@ -172,7 +173,7 @@
     visiting_old_object_ = obj;
     if (obj != nullptr) {
       // Card update happens in OldPage::VisitRememberedCards.
-      ASSERT(!obj->ptr()->IsCardRemembered());
+      ASSERT(!obj->untag()->IsCardRemembered());
     }
   }
 
@@ -255,10 +256,10 @@
   void UpdateStoreBuffer(ObjectPtr* p, ObjectPtr obj) {
     ASSERT(obj->IsHeapObject());
     // If the newly written object is not a new object, drop it immediately.
-    if (!obj->IsNewObject() || visiting_old_object_->ptr()->IsRemembered()) {
+    if (!obj->IsNewObject() || visiting_old_object_->untag()->IsRemembered()) {
       return;
     }
-    visiting_old_object_->ptr()->SetRememberedBit();
+    visiting_old_object_->untag()->SetRememberedBit();
     thread_->StoreBufferAddObjectGC(visiting_old_object_);
   }
 
@@ -271,7 +272,7 @@
       return;
     }
 
-    uword raw_addr = ObjectLayout::ToAddr(raw_obj);
+    uword raw_addr = UntaggedObject::ToAddr(raw_obj);
     // The scavenger is only expects objects located in the from space.
     ASSERT(from_->Contains(raw_addr));
     // Read the header word of the object and determine if the object has
@@ -283,7 +284,7 @@
       // Get the new location of the object.
       new_obj = ForwardedObj(header);
     } else {
-      intptr_t size = raw_obj->ptr()->HeapSize(header);
+      intptr_t size = raw_obj->untag()->HeapSize(header);
       uword new_addr = 0;
       // Check whether object should be promoted.
       if (!NewPage::Of(raw_obj)->IsSurvivor(raw_addr)) {
@@ -298,7 +299,7 @@
         if (LIKELY(new_addr != 0)) {
           // If promotion succeeded then we need to remember it so that it can
           // be traversed later.
-          promoted_list_.Push(ObjectLayout::FromAddr(new_addr));
+          promoted_list_.Push(UntaggedObject::FromAddr(new_addr));
           bytes_promoted_ += size;
         } else {
           // Promotion did not succeed. Copy into the to space instead.
@@ -316,26 +317,26 @@
       objcpy(reinterpret_cast<void*>(new_addr),
              reinterpret_cast<void*>(raw_addr), size);
 
-      new_obj = ObjectLayout::FromAddr(new_addr);
+      new_obj = UntaggedObject::FromAddr(new_addr);
       if (new_obj->IsOldObject()) {
         // Promoted: update age/barrier tags.
         uword tags = static_cast<uword>(header);
-        tags = ObjectLayout::OldBit::update(true, tags);
-        tags = ObjectLayout::OldAndNotRememberedBit::update(true, tags);
-        tags = ObjectLayout::NewBit::update(false, tags);
+        tags = UntaggedObject::OldBit::update(true, tags);
+        tags = UntaggedObject::OldAndNotRememberedBit::update(true, tags);
+        tags = UntaggedObject::NewBit::update(false, tags);
         // Setting the forwarding pointer below will make this tenured object
         // visible to the concurrent marker, but we haven't visited its slots
         // yet. We mark the object here to prevent the concurrent marker from
         // adding it to the mark stack and visiting its unprocessed slots. We
         // push it to the mark stack after forwarding its slots.
-        tags = ObjectLayout::OldAndNotMarkedBit::update(!thread_->is_marking(),
-                                                        tags);
-        new_obj->ptr()->tags_ = tags;
+        tags = UntaggedObject::OldAndNotMarkedBit::update(
+            !thread_->is_marking(), tags);
+        new_obj->untag()->tags_ = tags;
       }
 
-      intptr_t cid = ObjectLayout::ClassIdTag::decode(header);
+      intptr_t cid = UntaggedObject::ClassIdTag::decode(header);
       if (IsTypedDataClassId(cid)) {
-        static_cast<TypedDataPtr>(new_obj)->ptr()->RecomputeDataField();
+        static_cast<TypedDataPtr>(new_obj)->untag()->RecomputeDataField();
       }
 
       // Try to install forwarding address.
@@ -451,7 +452,7 @@
   void VisitHandle(uword addr) {
     FinalizablePersistentHandle* handle =
         reinterpret_cast<FinalizablePersistentHandle*>(addr);
-    ObjectPtr* p = handle->raw_addr();
+    ObjectPtr* p = handle->ptr_addr();
     if (scavenger_->IsUnreachable(p)) {
       handle->UpdateUnreachable(thread()->isolate_group());
     } else {
@@ -715,19 +716,6 @@
   tail_ = tail;
 }
 
-void SemiSpace::MergeFrom(SemiSpace* donor) {
-  for (NewPage* page = donor->head_; page != nullptr; page = page->next()) {
-    page->Release();
-  }
-
-  AddList(donor->head_, donor->tail_);
-  capacity_in_words_ += donor->capacity_in_words_;
-
-  donor->head_ = nullptr;
-  donor->tail_ = nullptr;
-  donor->capacity_in_words_ = 0;
-}
-
 // The initial estimate of how many words we can scavenge per microsecond (usage
 // before / scavenge time). This is a conservative value observed running
 // Flutter on a Nexus 4. After the first scavenge, we instead use a value based
@@ -788,8 +776,8 @@
   void VisitPointers(ObjectPtr* from, ObjectPtr* to) {
     for (ObjectPtr* ptr = from; ptr <= to; ptr++) {
       ObjectPtr raw_obj = *ptr;
-      RELEASE_ASSERT(!raw_obj->ptr()->IsCardRemembered());
-      RELEASE_ASSERT(raw_obj->ptr()->IsRemembered());
+      RELEASE_ASSERT(!raw_obj->untag()->IsCardRemembered());
+      RELEASE_ASSERT(raw_obj->untag()->IsRemembered());
       RELEASE_ASSERT(raw_obj->IsOldObject());
       in_store_buffer_->Add(raw_obj);
     }
@@ -812,18 +800,18 @@
     if (raw_obj->IsPseudoObject()) return;
     RELEASE_ASSERT(raw_obj->IsOldObject());
 
-    if (raw_obj->ptr()->IsCardRemembered()) {
-      RELEASE_ASSERT(!raw_obj->ptr()->IsRemembered());
+    if (raw_obj->untag()->IsCardRemembered()) {
+      RELEASE_ASSERT(!raw_obj->untag()->IsRemembered());
       // TODO(rmacnak): Verify card tables.
       return;
     }
 
-    RELEASE_ASSERT(raw_obj->ptr()->IsRemembered() ==
+    RELEASE_ASSERT(raw_obj->untag()->IsRemembered() ==
                    in_store_buffer_->Contains(raw_obj));
 
     visiting_ = raw_obj;
-    is_remembered_ = raw_obj->ptr()->IsRemembered();
-    raw_obj->ptr()->VisitPointers(this);
+    is_remembered_ = raw_obj->untag()->IsRemembered();
+    raw_obj->untag()->VisitPointers(this);
   }
 
   void VisitPointers(ObjectPtr* from, ObjectPtr* to) {
@@ -838,7 +826,7 @@
               " reverse-continue to find the store with a missing barrier.\n",
               static_cast<uword>(visiting_), static_cast<uword>(raw_obj), ptr);
         }
-        RELEASE_ASSERT(to_->Contains(ObjectLayout::ToAddr(raw_obj)));
+        RELEASE_ASSERT(to_->Contains(UntaggedObject::ToAddr(raw_obj)));
       }
     }
   }
@@ -1036,12 +1024,12 @@
     while (!pending->IsEmpty()) {
       ObjectPtr raw_object = pending->Pop();
       ASSERT(!raw_object->IsForwardingCorpse());
-      ASSERT(raw_object->ptr()->IsRemembered());
-      raw_object->ptr()->ClearRememberedBit();
+      ASSERT(raw_object->untag()->IsRemembered());
+      raw_object->untag()->ClearRememberedBit();
       visitor->VisitingOldObject(raw_object);
       // Note that this treats old-space WeakProperties as strong. A dead key
       // won't be reclaimed until after the key is promoted.
-      raw_object->ptr()->VisitPointersNonvirtual(visitor);
+      raw_object->untag()->VisitPointersNonvirtual(visitor);
     }
     pending->Reset();
     // Return the emptied block for recycling (no need to check threshold).
@@ -1114,7 +1102,7 @@
   if (!raw_obj->IsNewObject()) {
     return false;
   }
-  uword raw_addr = ObjectLayout::ToAddr(raw_obj);
+  uword raw_addr = UntaggedObject::ToAddr(raw_obj);
   if (to_->Contains(raw_addr)) {
     return false;
   }
@@ -1138,7 +1126,7 @@
   while (scan_ != nullptr) {
     uword resolved_top = scan_->resolved_top_;
     while (resolved_top < scan_->top_) {
-      ObjectPtr raw_obj = ObjectLayout::FromAddr(resolved_top);
+      ObjectPtr raw_obj = UntaggedObject::FromAddr(resolved_top);
       resolved_top += ProcessCopied(raw_obj);
     }
     scan_->resolved_top_ = resolved_top;
@@ -1159,10 +1147,10 @@
     // Resolve or copy all objects referred to by the current object. This
     // can potentially push more objects on this stack as well as add more
     // objects to be resolved in the to space.
-    ASSERT(!raw_object->ptr()->IsRemembered());
+    ASSERT(!raw_object->untag()->IsRemembered());
     VisitingOldObject(raw_object);
-    raw_object->ptr()->VisitPointersNonvirtual(this);
-    if (raw_object->ptr()->IsMarked()) {
+    raw_object->untag()->VisitPointersNonvirtual(this);
+    if (raw_object->untag()->IsMarked()) {
       // Complete our promise from ScavengePointer. Note that marker cannot
       // visit this object until it pops a block from the mark stack, which
       // involves a memory fence from the mutex, so even on architectures
@@ -1184,23 +1172,23 @@
   WeakPropertyPtr cur_weak = delayed_weak_properties_;
   delayed_weak_properties_ = WeakProperty::null();
   while (cur_weak != WeakProperty::null()) {
-    WeakPropertyPtr next_weak = cur_weak->ptr()->next_;
+    WeakPropertyPtr next_weak = cur_weak->untag()->next_;
     // Promoted weak properties are not enqueued. So we can guarantee that
     // we do not need to think about store barriers here.
     ASSERT(cur_weak->IsNewObject());
-    ObjectPtr raw_key = cur_weak->ptr()->key_;
+    ObjectPtr raw_key = cur_weak->untag()->key_;
     ASSERT(raw_key->IsHeapObject());
     // Key still points into from space even if the object has been
     // promoted to old space by now. The key will be updated accordingly
     // below when VisitPointers is run.
     ASSERT(raw_key->IsNewObject());
-    uword raw_addr = ObjectLayout::ToAddr(raw_key);
+    uword raw_addr = UntaggedObject::ToAddr(raw_key);
     ASSERT(from_->Contains(raw_addr));
     uword header = *reinterpret_cast<uword*>(raw_addr);
     // Reset the next pointer in the weak property.
-    cur_weak->ptr()->next_ = WeakProperty::null();
+    cur_weak->untag()->next_ = WeakProperty::null();
     if (IsForwarding(header)) {
-      cur_weak->ptr()->VisitPointersNonvirtual(this);
+      cur_weak->untag()->VisitPointersNonvirtual(this);
     } else {
       EnqueueWeakProperty(cur_weak);
     }
@@ -1241,12 +1229,12 @@
   ASSERT(raw_weak->IsNewObject());
   ASSERT(raw_weak->IsWeakProperty());
 #if defined(DEBUG)
-  uword raw_addr = ObjectLayout::ToAddr(raw_weak);
+  uword raw_addr = UntaggedObject::ToAddr(raw_weak);
   uword header = *reinterpret_cast<uword*>(raw_addr);
   ASSERT(!IsForwarding(header));
 #endif  // defined(DEBUG)
-  ASSERT(raw_weak->ptr()->next_ == WeakProperty::null());
-  raw_weak->ptr()->next_ = delayed_weak_properties_;
+  ASSERT(raw_weak->untag()->next_ == WeakProperty::null());
+  raw_weak->untag()->next_ = delayed_weak_properties_;
   delayed_weak_properties_ = raw_weak;
 }
 
@@ -1256,19 +1244,19 @@
   if (UNLIKELY(class_id == kWeakPropertyCid)) {
     WeakPropertyPtr raw_weak = static_cast<WeakPropertyPtr>(raw_obj);
     // The fate of the weak property is determined by its key.
-    ObjectPtr raw_key = raw_weak->ptr()->key_;
+    ObjectPtr raw_key = raw_weak->untag()->key_;
     if (raw_key->IsHeapObject() && raw_key->IsNewObject()) {
-      uword raw_addr = ObjectLayout::ToAddr(raw_key);
+      uword raw_addr = UntaggedObject::ToAddr(raw_key);
       uword header = *reinterpret_cast<uword*>(raw_addr);
       if (!IsForwarding(header)) {
         // Key is white.  Enqueue the weak property.
         EnqueueWeakProperty(raw_weak);
-        return raw_weak->ptr()->HeapSize();
+        return raw_weak->untag()->HeapSize();
       }
     }
     // Key is gray or black.  Make the weak property black.
   }
-  return raw_obj->ptr()->VisitPointersNonvirtual(this);
+  return raw_obj->untag()->VisitPointersNonvirtual(this);
 }
 
 void Scavenger::MournWeakTables() {
@@ -1281,7 +1269,7 @@
       if (table->IsValidEntryAtExclusive(i)) {
         ObjectPtr raw_obj = table->ObjectAtExclusive(i);
         ASSERT(raw_obj->IsHeapObject());
-        uword raw_addr = ObjectLayout::ToAddr(raw_obj);
+        uword raw_addr = UntaggedObject::ToAddr(raw_obj);
         uword header = *reinterpret_cast<uword*>(raw_addr);
         if (IsForwarding(header)) {
           // The object has survived.  Preserve its record.
@@ -1333,13 +1321,13 @@
   WeakPropertyPtr cur_weak = delayed_weak_properties_;
   delayed_weak_properties_ = WeakProperty::null();
   while (cur_weak != WeakProperty::null()) {
-    WeakPropertyPtr next_weak = cur_weak->ptr()->next_;
+    WeakPropertyPtr next_weak = cur_weak->untag()->next_;
     // Reset the next pointer in the weak property.
-    cur_weak->ptr()->next_ = WeakProperty::null();
+    cur_weak->untag()->next_ = WeakProperty::null();
 
 #if defined(DEBUG)
-    ObjectPtr raw_key = cur_weak->ptr()->key_;
-    uword raw_addr = ObjectLayout::ToAddr(raw_key);
+    ObjectPtr raw_key = cur_weak->untag()->key_;
+    uword raw_addr = UntaggedObject::ToAddr(raw_key);
     uword header = *reinterpret_cast<uword*>(raw_addr);
     ASSERT(!IsForwarding(header));
     ASSERT(raw_key->IsHeapObject());
@@ -1382,10 +1370,10 @@
     uword cur = page->object_start();
     if (!visitor->VisitRange(cur, page->object_end())) continue;
     while (cur < page->object_end()) {
-      ObjectPtr raw_obj = ObjectLayout::FromAddr(cur);
-      uword next = cur + raw_obj->ptr()->HeapSize();
+      ObjectPtr raw_obj = UntaggedObject::FromAddr(cur);
+      uword next = cur + raw_obj->untag()->HeapSize();
       if (visitor->VisitRange(cur, next) &&
-          raw_obj->ptr()->FindObject(visitor)) {
+          raw_obj->untag()->FindObject(visitor)) {
         return raw_obj;  // Found object, return it.
       }
       cur = next;
@@ -1396,7 +1384,7 @@
 }
 
 void Scavenger::TryAllocateNewTLAB(Thread* thread, intptr_t min_size) {
-  ASSERT(heap_ != Dart::vm_isolate()->heap());
+  ASSERT(heap_ != Dart::vm_isolate_group()->heap());
   ASSERT(!scavenging_);
 
   AbandonRemainingTLAB(thread);
@@ -1604,11 +1592,11 @@
   class ReverseFromForwardingVisitor : public ObjectVisitor {
     uword ReadHeader(ObjectPtr raw_obj) {
       return reinterpret_cast<std::atomic<uword>*>(
-                 ObjectLayout::ToAddr(raw_obj))
+                 UntaggedObject::ToAddr(raw_obj))
           ->load(std::memory_order_relaxed);
     }
     void WriteHeader(ObjectPtr raw_obj, uword header) {
-      reinterpret_cast<std::atomic<uword>*>(ObjectLayout::ToAddr(raw_obj))
+      reinterpret_cast<std::atomic<uword>*>(UntaggedObject::ToAddr(raw_obj))
           ->store(header, std::memory_order_relaxed);
     }
     void VisitObject(ObjectPtr from_obj) {
@@ -1616,20 +1604,20 @@
       if (IsForwarding(from_header)) {
         ObjectPtr to_obj = ForwardedObj(from_header);
         uword to_header = ReadHeader(to_obj);
-        intptr_t size = to_obj->ptr()->HeapSize();
+        intptr_t size = to_obj->untag()->HeapSize();
 
         // Reset the ages bits in case this was a promotion.
         uword from_header = static_cast<uword>(to_header);
-        from_header = ObjectLayout::OldBit::update(false, from_header);
+        from_header = UntaggedObject::OldBit::update(false, from_header);
         from_header =
-            ObjectLayout::OldAndNotRememberedBit::update(false, from_header);
-        from_header = ObjectLayout::NewBit::update(true, from_header);
+            UntaggedObject::OldAndNotRememberedBit::update(false, from_header);
+        from_header = UntaggedObject::NewBit::update(true, from_header);
         from_header =
-            ObjectLayout::OldAndNotMarkedBit::update(false, from_header);
+            UntaggedObject::OldAndNotMarkedBit::update(false, from_header);
 
         WriteHeader(from_obj, from_header);
 
-        ForwardingCorpse::AsForwarder(ObjectLayout::ToAddr(to_obj), size)
+        ForwardingCorpse::AsForwarder(UntaggedObject::ToAddr(to_obj), size)
             ->set_target(from_obj);
       }
     }
@@ -1721,13 +1709,4 @@
   ASSERT((UsedInWords() == 0) || failed_to_promote_);
 }
 
-void Scavenger::MergeFrom(Scavenger* donor) {
-  MutexLocker ml(&space_lock_);
-  MutexLocker ml2(&donor->space_lock_);
-  to_->MergeFrom(donor->to_);
-
-  external_size_ += donor->external_size_;
-  donor->external_size_ = 0;
-}
-
 }  // namespace dart
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index 5e7486b..ed36fe1 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -57,17 +57,17 @@
     uword addr = object_start();
     uword end = object_end();
     while (addr < end) {
-      ObjectPtr obj = ObjectLayout::FromAddr(addr);
+      ObjectPtr obj = UntaggedObject::FromAddr(addr);
       visitor->VisitObject(obj);
-      addr += obj->ptr()->HeapSize();
+      addr += obj->untag()->HeapSize();
     }
   }
   void VisitObjectPointers(ObjectPointerVisitor* visitor) const {
     uword addr = object_start();
     uword end = object_end();
     while (addr < end) {
-      ObjectPtr obj = ObjectLayout::FromAddr(addr);
-      intptr_t size = obj->ptr()->VisitPointers(visitor);
+      ObjectPtr obj = UntaggedObject::FromAddr(addr);
+      intptr_t size = obj->untag()->VisitPointers(visitor);
       addr += size;
     }
   }
@@ -184,7 +184,6 @@
   NewPage* head() const { return head_; }
 
   void AddList(NewPage* head, NewPage* tail);
-  void MergeFrom(SemiSpace* donor);
 
  private:
   // Size of NewPages in this semi-space.
@@ -281,8 +280,6 @@
   // Promote all live objects.
   void Evacuate();
 
-  void MergeFrom(Scavenger* donor);
-
   int64_t UsedInWords() const {
     MutexLocker ml(&space_lock_);
     return to_->capacity_in_words();
@@ -376,7 +373,7 @@
 
   uword TryAllocateFromTLAB(Thread* thread, intptr_t size) {
     ASSERT(Utils::IsAligned(size, kObjectAlignment));
-    ASSERT(heap_ != Dart::vm_isolate()->heap());
+    ASSERT(heap_ != Dart::vm_isolate_group()->heap());
 
     const uword result = thread->top();
     const intptr_t remaining = thread->end() - result;
diff --git a/runtime/vm/heap/sweeper.cc b/runtime/vm/heap/sweeper.cc
index 9013eba..d814521 100644
--- a/runtime/vm/heap/sweeper.cc
+++ b/runtime/vm/heap/sweeper.cc
@@ -27,28 +27,28 @@
   uword current = start;
 
   while (current < end) {
-    ObjectPtr raw_obj = ObjectLayout::FromAddr(current);
+    ObjectPtr raw_obj = UntaggedObject::FromAddr(current);
     ASSERT(OldPage::Of(raw_obj) == page);
     // These acquire operations balance release operations in array
     // truncaton, ensuring the writes creating the filler object are ordered
     // before the writes inserting the filler object into the freelist.
-    uword tags = raw_obj->ptr()->tags_.load(std::memory_order_acquire);
-    intptr_t obj_size = raw_obj->ptr()->HeapSize(tags);
-    if (ObjectLayout::IsMarked(tags)) {
+    uword tags = raw_obj->untag()->tags_.load(std::memory_order_acquire);
+    intptr_t obj_size = raw_obj->untag()->HeapSize(tags);
+    if (UntaggedObject::IsMarked(tags)) {
       // Found marked object. Clear the mark bit and update swept bytes.
-      raw_obj->ptr()->ClearMarkBit();
+      raw_obj->untag()->ClearMarkBit();
       used_in_bytes += obj_size;
     } else {
       uword free_end = current + obj_size;
       while (free_end < end) {
-        ObjectPtr next_obj = ObjectLayout::FromAddr(free_end);
-        tags = next_obj->ptr()->tags_.load(std::memory_order_acquire);
-        if (ObjectLayout::IsMarked(tags)) {
+        ObjectPtr next_obj = UntaggedObject::FromAddr(free_end);
+        tags = next_obj->untag()->tags_.load(std::memory_order_acquire);
+        if (UntaggedObject::IsMarked(tags)) {
           // Reached the end of the free block.
           break;
         }
         // Expand the free block by the size of this object.
-        free_end += next_obj->ptr()->HeapSize(tags);
+        free_end += next_obj->untag()->HeapSize(tags);
       }
       obj_size = free_end - current;
       if (is_executable) {
@@ -84,21 +84,22 @@
   ASSERT(!page->is_image_page());
 
   intptr_t words_to_end = 0;
-  ObjectPtr raw_obj = ObjectLayout::FromAddr(page->object_start());
+  ObjectPtr raw_obj = UntaggedObject::FromAddr(page->object_start());
   ASSERT(OldPage::Of(raw_obj) == page);
-  if (raw_obj->ptr()->IsMarked()) {
-    raw_obj->ptr()->ClearMarkBit();
-    words_to_end = (raw_obj->ptr()->HeapSize() >> kWordSizeLog2);
+  if (raw_obj->untag()->IsMarked()) {
+    raw_obj->untag()->ClearMarkBit();
+    words_to_end = (raw_obj->untag()->HeapSize() >> kWordSizeLog2);
   }
 #ifdef DEBUG
   // Array::MakeFixedLength creates trailing filler objects,
   // but they are always unreachable. Verify that they are not marked.
-  uword current = ObjectLayout::ToAddr(raw_obj) + raw_obj->ptr()->HeapSize();
+  uword current =
+      UntaggedObject::ToAddr(raw_obj) + raw_obj->untag()->HeapSize();
   uword end = page->object_end();
   while (current < end) {
-    ObjectPtr cur_obj = ObjectLayout::FromAddr(current);
-    ASSERT(!cur_obj->ptr()->IsMarked());
-    intptr_t obj_size = cur_obj->ptr()->HeapSize();
+    ObjectPtr cur_obj = UntaggedObject::FromAddr(current);
+    ASSERT(!cur_obj->untag()->IsMarked());
+    intptr_t obj_size = cur_obj->untag()->HeapSize();
     memset(reinterpret_cast<void*>(current), Heap::kZapByte, obj_size);
     current += obj_size;
   }
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index 4dc7da0..34a6593 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -18,22 +18,22 @@
 
 void VerifyObjectVisitor::VisitObject(ObjectPtr raw_obj) {
   if (raw_obj->IsHeapObject()) {
-    uword raw_addr = ObjectLayout::ToAddr(raw_obj);
+    uword raw_addr = UntaggedObject::ToAddr(raw_obj);
     if (raw_obj->IsFreeListElement() || raw_obj->IsForwardingCorpse()) {
-      if (raw_obj->IsOldObject() && raw_obj->ptr()->IsMarked()) {
+      if (raw_obj->IsOldObject() && raw_obj->untag()->IsMarked()) {
         FATAL1("Marked free list element encountered %#" Px "\n", raw_addr);
       }
     } else {
       switch (mark_expectation_) {
         case kForbidMarked:
-          if (raw_obj->IsOldObject() && raw_obj->ptr()->IsMarked()) {
+          if (raw_obj->IsOldObject() && raw_obj->untag()->IsMarked()) {
             FATAL1("Marked object encountered %#" Px "\n", raw_addr);
           }
           break;
         case kAllowMarked:
           break;
         case kRequireMarked:
-          if (raw_obj->IsOldObject() && !raw_obj->ptr()->IsMarked()) {
+          if (raw_obj->IsOldObject() && !raw_obj->untag()->IsMarked()) {
             FATAL1("Unmarked object encountered %#" Px "\n", raw_addr);
           }
           break;
@@ -53,8 +53,8 @@
             allocated_set_->Contains(OldPage::ToWritable(raw_obj))) {
           continue;
         }
-        FATAL2("Invalid object pointer encountered %#" Px ": %#" Px "\n",
-               reinterpret_cast<uword>(current), static_cast<uword>(raw_obj));
+        uword raw_addr = UntaggedObject::ToAddr(raw_obj);
+        FATAL1("Invalid object pointer encountered %#" Px "\n", raw_addr);
       }
     }
   }
@@ -63,7 +63,7 @@
 void VerifyWeakPointersVisitor::VisitHandle(uword addr) {
   FinalizablePersistentHandle* handle =
       reinterpret_cast<FinalizablePersistentHandle*>(addr);
-  ObjectPtr raw_obj = handle->raw();
+  ObjectPtr raw_obj = handle->ptr();
   visitor_->VisitPointer(&raw_obj);
 }
 
@@ -107,7 +107,7 @@
   if (!FLAG_enable_isolate_groups || FLAG_precompiled_mode) {
     if ((obj->GetClassId() >= kInstanceCid) &&
         (obj->GetClassId() != kTypeArgumentsCid)) {
-      if (obj->ptr()->IsCanonical()) {
+      if (obj->untag()->IsCanonical()) {
         instanceHandle_ ^= obj;
         const bool is_canonical = instanceHandle_.CheckIsCanonical(thread_);
         if (!is_canonical) {
diff --git a/runtime/vm/heap/weak_code.cc b/runtime/vm/heap/weak_code.cc
index 97f832a..a50936a 100644
--- a/runtime/vm/heap/weak_code.cc
+++ b/runtime/vm/heap/weak_code.cc
@@ -50,7 +50,7 @@
   WeakProperty& weak_property = WeakProperty::Handle();
   for (intptr_t i = 0; i < dependent_code.Length(); i++) {
     weak_property ^= dependent_code.At(i);
-    if (code.raw() == weak_property.key()) {
+    if (code.ptr() == weak_property.key()) {
       return true;
     }
   }
@@ -59,7 +59,7 @@
 
 void WeakCodeReferences::DisableCode() {
   Thread* thread = Thread::Current();
-  const Array& code_objects = Array::Handle(thread->zone(), array_.raw());
+  const Array& code_objects = Array::Handle(thread->zone(), array_.ptr());
 #if defined(DART_PRECOMPILED_RUNTIME)
   ASSERT(code_objects.IsNull());
   return;
@@ -101,10 +101,10 @@
     }
     owner = code.owner();
     if (owner.IsFunction()) {
-      function ^= owner.raw();
+      function ^= owner.ptr();
     } else if (owner.IsClass()) {
       Class& cls = Class::Handle();
-      cls ^= owner.raw();
+      cls ^= owner.ptr();
       cls.DisableAllocationStub();
       continue;
     } else if (owner.IsNull()) {
@@ -113,10 +113,10 @@
     }
 
     // If function uses dependent code switch it to unoptimized.
-    if (code.is_optimized() && (function.CurrentCode() == code.raw())) {
+    if (code.is_optimized() && (function.CurrentCode() == code.ptr())) {
       ReportSwitchingCode(code);
       function.SwitchToUnoptimizedCode();
-    } else if (function.unoptimized_code() == code.raw()) {
+    } else if (function.unoptimized_code() == code.ptr()) {
       ReportSwitchingCode(code);
       function.SetWasCompiled(false);
       function.ClearICDataArray();
diff --git a/runtime/vm/heap/weak_table.cc b/runtime/vm/heap/weak_table.cc
index fdb0a7d..4070590 100644
--- a/runtime/vm/heap/weak_table.cc
+++ b/runtime/vm/heap/weak_table.cc
@@ -140,12 +140,4 @@
   free(old_data);
 }
 
-void WeakTable::MergeFrom(WeakTable* donor) {
-  for (intptr_t i = 0; i < donor->size(); i++) {
-    if (donor->IsValidEntryAtExclusive(i)) {
-      SetValueExclusive(donor->ObjectAtExclusive(i), ValueIndex(i));
-    }
-  }
-}
-
 }  // namespace dart
diff --git a/runtime/vm/heap/weak_table.h b/runtime/vm/heap/weak_table.h
index c7728b0..c72d773 100644
--- a/runtime/vm/heap/weak_table.h
+++ b/runtime/vm/heap/weak_table.h
@@ -133,8 +133,6 @@
 
   void Reset();
 
-  void MergeFrom(WeakTable* donor);
-
  private:
   enum {
     kObjectOffset = 0,
diff --git a/runtime/vm/heap/weak_table_test.cc b/runtime/vm/heap/weak_table_test.cc
index edbca24..f7ceb89 100644
--- a/runtime/vm/heap/weak_table_test.cc
+++ b/runtime/vm/heap/weak_table_test.cc
@@ -20,43 +20,43 @@
   // Initially absent.
   Heap* heap = thread->heap();
   const intptr_t kNoValue = WeakTable::kNoValue;
-  EXPECT_EQ(kNoValue, heap->GetObjectId(old_obj.raw()));
-  EXPECT_EQ(kNoValue, heap->GetObjectId(new_obj.raw()));
-  EXPECT_EQ(kNoValue, heap->GetObjectId(imm_obj.raw()));
+  EXPECT_EQ(kNoValue, heap->GetObjectId(old_obj.ptr()));
+  EXPECT_EQ(kNoValue, heap->GetObjectId(new_obj.ptr()));
+  EXPECT_EQ(kNoValue, heap->GetObjectId(imm_obj.ptr()));
 
   // Found after insert.
-  heap->SetObjectId(old_obj.raw(), 100);
-  heap->SetObjectId(new_obj.raw(), 200);
-  heap->SetObjectId(imm_obj.raw(), 300);
-  EXPECT_EQ(100, heap->GetObjectId(old_obj.raw()));
-  EXPECT_EQ(200, heap->GetObjectId(new_obj.raw()));
-  EXPECT_EQ(300, heap->GetObjectId(imm_obj.raw()));
+  heap->SetObjectId(old_obj.ptr(), 100);
+  heap->SetObjectId(new_obj.ptr(), 200);
+  heap->SetObjectId(imm_obj.ptr(), 300);
+  EXPECT_EQ(100, heap->GetObjectId(old_obj.ptr()));
+  EXPECT_EQ(200, heap->GetObjectId(new_obj.ptr()));
+  EXPECT_EQ(300, heap->GetObjectId(imm_obj.ptr()));
 
   // Found after update.
-  heap->SetObjectId(old_obj.raw(), 400);
-  heap->SetObjectId(new_obj.raw(), 500);
-  heap->SetObjectId(imm_obj.raw(), 600);
-  EXPECT_EQ(400, heap->GetObjectId(old_obj.raw()));
-  EXPECT_EQ(500, heap->GetObjectId(new_obj.raw()));
-  EXPECT_EQ(600, heap->GetObjectId(imm_obj.raw()));
+  heap->SetObjectId(old_obj.ptr(), 400);
+  heap->SetObjectId(new_obj.ptr(), 500);
+  heap->SetObjectId(imm_obj.ptr(), 600);
+  EXPECT_EQ(400, heap->GetObjectId(old_obj.ptr()));
+  EXPECT_EQ(500, heap->GetObjectId(new_obj.ptr()));
+  EXPECT_EQ(600, heap->GetObjectId(imm_obj.ptr()));
 
   // Found after GC.
   GCTestHelper::CollectNewSpace();
-  EXPECT_EQ(400, heap->GetObjectId(old_obj.raw()));
-  EXPECT_EQ(500, heap->GetObjectId(new_obj.raw()));
-  EXPECT_EQ(600, heap->GetObjectId(imm_obj.raw()));
+  EXPECT_EQ(400, heap->GetObjectId(old_obj.ptr()));
+  EXPECT_EQ(500, heap->GetObjectId(new_obj.ptr()));
+  EXPECT_EQ(600, heap->GetObjectId(imm_obj.ptr()));
 
   // Found after GC.
   GCTestHelper::CollectOldSpace();
-  EXPECT_EQ(400, heap->GetObjectId(old_obj.raw()));
-  EXPECT_EQ(500, heap->GetObjectId(new_obj.raw()));
-  EXPECT_EQ(600, heap->GetObjectId(imm_obj.raw()));
+  EXPECT_EQ(400, heap->GetObjectId(old_obj.ptr()));
+  EXPECT_EQ(500, heap->GetObjectId(new_obj.ptr()));
+  EXPECT_EQ(600, heap->GetObjectId(imm_obj.ptr()));
 
   // Absent after reset.
   heap->ResetObjectIdTable();
-  EXPECT_EQ(kNoValue, heap->GetObjectId(old_obj.raw()));
-  EXPECT_EQ(kNoValue, heap->GetObjectId(new_obj.raw()));
-  EXPECT_EQ(kNoValue, heap->GetObjectId(imm_obj.raw()));
+  EXPECT_EQ(kNoValue, heap->GetObjectId(old_obj.ptr()));
+  EXPECT_EQ(kNoValue, heap->GetObjectId(new_obj.ptr()));
+  EXPECT_EQ(kNoValue, heap->GetObjectId(imm_obj.ptr()));
 }
 
 }  // namespace dart
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 84d523c..6147404 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -42,15 +42,15 @@
             "Print sizes of all instruction objects to the given file");
 #endif
 
-const InstructionsSectionLayout* Image::ExtraInfo(const uword raw_memory,
-                                                  const uword size) {
+const UntaggedInstructionsSection* Image::ExtraInfo(const uword raw_memory,
+                                                    const uword size) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   auto const raw_value =
       FieldValue(raw_memory, HeaderField::InstructionsSectionOffset);
   if (raw_value != kNoInstructionsSection) {
     ASSERT(raw_value >= kHeaderSize);
     ASSERT(raw_value <= size - InstructionsSection::HeaderSize());
-    auto const layout = reinterpret_cast<const InstructionsSectionLayout*>(
+    auto const layout = reinterpret_cast<const UntaggedInstructionsSection*>(
         raw_memory + raw_value);
     // The instructions section is likely non-empty in bare instructions mode
     // (unless splitting into multiple outputs and there are no Code objects
@@ -146,8 +146,8 @@
   ObjectPtr obj = key;
   ASSERT(!obj->IsSmi());
 
-  uword body = ObjectLayout::ToAddr(obj) + sizeof(ObjectLayout);
-  uword end = ObjectLayout::ToAddr(obj) + obj->ptr()->HeapSize();
+  uword body = UntaggedObject::ToAddr(obj) + sizeof(UntaggedObject);
+  uword end = UntaggedObject::ToAddr(obj) + obj->untag()->HeapSize();
 
   uint32_t hash = obj->GetClassId();
   // Don't include the header. Objects in the image are pre-marked, but objects
@@ -169,16 +169,16 @@
     return false;
   }
 
-  intptr_t heap_size = a->ptr()->HeapSize();
-  if (b->ptr()->HeapSize() != heap_size) {
+  intptr_t heap_size = a->untag()->HeapSize();
+  if (b->untag()->HeapSize() != heap_size) {
     return false;
   }
 
   // Don't include the header. Objects in the image are pre-marked, but objects
   // in the current isolate are not.
-  uword body_a = ObjectLayout::ToAddr(a) + sizeof(ObjectLayout);
-  uword body_b = ObjectLayout::ToAddr(b) + sizeof(ObjectLayout);
-  uword body_size = heap_size - sizeof(ObjectLayout);
+  uword body_a = UntaggedObject::ToAddr(a) + sizeof(UntaggedObject);
+  uword body_b = UntaggedObject::ToAddr(b) + sizeof(UntaggedObject);
+  uword body_size = heap_size - sizeof(UntaggedObject);
   return 0 == memcmp(reinterpret_cast<const void*>(body_a),
                      reinterpret_cast<const void*>(body_b), body_size);
 }
@@ -259,12 +259,12 @@
     case kCodeSourceMapCid: {
       auto raw_map = CodeSourceMap::RawCast(raw_object);
       return compiler::target::CodeSourceMap::InstanceSize(
-          raw_map->ptr()->length_);
+          raw_map->untag()->length_);
     }
     case kPcDescriptorsCid: {
       auto raw_desc = PcDescriptors::RawCast(raw_object);
       return compiler::target::PcDescriptors::InstanceSize(
-          raw_desc->ptr()->length_);
+          raw_desc->untag()->length_);
     }
     case kInstructionsCid: {
       auto raw_insns = Instructions::RawCast(raw_object);
@@ -377,7 +377,7 @@
       js.PrintPropertyStr("l", url);
       js.PrintPropertyStr("c", name);
     } else if (owner.IsClass()) {
-      cls ^= owner.raw();
+      cls ^= owner.ptr();
       name = cls.ScrubbedName();
       lib = cls.library();
       url = lib.url();
@@ -388,7 +388,7 @@
                      data.code_->QualifiedName(
                          NameFormattingParams::DisambiguatedWithoutClassName(
                              Object::kInternalName)));
-    js.PrintProperty("s", SizeInSnapshot(data.insns_->raw()));
+    js.PrintProperty("s", SizeInSnapshot(data.insns_->ptr()));
     js.CloseObject();
   }
   if (trampolines_total_size != 0) {
@@ -435,7 +435,7 @@
 void ImageWriter::Write(NonStreamingWriteStream* clustered_stream, bool vm) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Heap* heap = thread->isolate()->heap();
+  Heap* heap = thread->isolate_group()->heap();
   TIMELINE_DURATION(thread, Isolate, "WriteInstructions");
 
   // Handlify collected raw pointers as building the names below
@@ -451,7 +451,7 @@
 
     // Reset object id as an isolate snapshot after a VM snapshot will not use
     // the VM snapshot's text image.
-    heap->SetObjectId(data.insns_->raw(), 0);
+    heap->SetObjectId(data.insns_->ptr(), 0);
   }
   for (intptr_t i = 0; i < objects_.length(); i++) {
     ObjectData& data = objects_[i];
@@ -514,10 +514,10 @@
     if (obj.IsCompressedStackMaps()) {
       const CompressedStackMaps& map = CompressedStackMaps::Cast(obj);
       const intptr_t payload_size = map.payload_size();
-      stream->WriteTargetWord(map.raw()->ptr()->flags_and_size_);
+      stream->WriteTargetWord(map.ptr()->untag()->flags_and_size_);
       ASSERT_EQUAL(stream->Position() - object_start,
                    compiler::target::CompressedStackMaps::HeaderSize());
-      stream->WriteBytes(map.raw()->ptr()->data(), payload_size);
+      stream->WriteBytes(map.ptr()->untag()->data(), payload_size);
     } else if (obj.IsCodeSourceMap()) {
       const CodeSourceMap& map = CodeSourceMap::Cast(obj);
       stream->WriteTargetWord(map.Length());
@@ -529,15 +529,15 @@
       stream->WriteTargetWord(desc.Length());
       ASSERT_EQUAL(stream->Position() - object_start,
                    compiler::target::PcDescriptors::HeaderSize());
-      stream->WriteBytes(desc.raw()->ptr()->data(), desc.Length());
+      stream->WriteBytes(desc.ptr()->untag()->data(), desc.Length());
     } else if (obj.IsString()) {
       const String& str = String::Cast(obj);
-      RELEASE_ASSERT(String::GetCachedHash(str.raw()) != 0);
+      RELEASE_ASSERT(String::GetCachedHash(str.ptr()) != 0);
       RELEASE_ASSERT(str.IsOneByteString() || str.IsTwoByteString());
 
-      stream->WriteTargetWord(static_cast<uword>(str.raw()->ptr()->length_));
+      stream->WriteTargetWord(static_cast<uword>(str.ptr()->untag()->length_));
 #if !defined(HASH_IN_OBJECT_HEADER)
-      stream->WriteTargetWord(static_cast<uword>(str.raw()->ptr()->hash_));
+      stream->WriteTargetWord(static_cast<uword>(str.ptr()->untag()->hash_));
 #endif
       ASSERT_EQUAL(stream->Position() - object_start,
                    compiler::target::String::InstanceSize());
@@ -558,15 +558,15 @@
 }
 
 static UNLESS_DEBUG(constexpr) const uword kReadOnlyGCBits =
-    ObjectLayout::OldBit::encode(true) |
-    ObjectLayout::OldAndNotMarkedBit::encode(false) |
-    ObjectLayout::OldAndNotRememberedBit::encode(true) |
-    ObjectLayout::NewBit::encode(false);
+    UntaggedObject::OldBit::encode(true) |
+    UntaggedObject::OldAndNotMarkedBit::encode(false) |
+    UntaggedObject::OldAndNotRememberedBit::encode(true) |
+    UntaggedObject::NewBit::encode(false);
 
 uword ImageWriter::GetMarkedTags(classid_t cid,
                                  intptr_t size,
                                  bool is_canonical /* = false */) {
-  // ObjectLayout::SizeTag expects a size divisible by kObjectAlignment and
+  // UntaggedObject::SizeTag expects a size divisible by kObjectAlignment and
   // checks this in debug mode, but the size on the target machine may not be
   // divisible by the host machine's object alignment if they differ.
   //
@@ -583,16 +583,17 @@
       size << (kObjectAlignmentLog2 -
                compiler::target::ObjectAlignment::kObjectAlignmentLog2);
 
-  return kReadOnlyGCBits | ObjectLayout::ClassIdTag::encode(cid) |
-         ObjectLayout::SizeTag::encode(adjusted_size) |
-         ObjectLayout::CanonicalBit::encode(is_canonical);
+  return kReadOnlyGCBits | UntaggedObject::ClassIdTag::encode(cid) |
+         UntaggedObject::SizeTag::encode(adjusted_size) |
+         UntaggedObject::CanonicalBit::encode(is_canonical);
 }
 
 uword ImageWriter::GetMarkedTags(const Object& obj) {
-  uword tags = GetMarkedTags(obj.raw()->GetClassId(), SizeInSnapshot(obj),
-                             obj.IsCanonical());
+  uword tags = GetMarkedTags(obj.ptr()->untag()->GetClassId(),
+                             SizeInSnapshot(obj), obj.IsCanonical());
 #if defined(HASH_IN_OBJECT_HEADER)
-  tags = ObjectLayout::HashTag::update(obj.raw()->ptr()->GetHeaderHash(), tags);
+  tags = UntaggedObject::HashTag::update(obj.ptr()->untag()->GetHeaderHash(),
+                                         tags);
 #endif
   return tags;
 }
@@ -740,7 +741,7 @@
       const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
       auto const type = is_trampoline ? trampoline_type_ : instructions_type_;
       const intptr_t size = is_trampoline ? data.trampoline_length
-                                          : SizeInSnapshot(data.insns_->raw());
+                                          : SizeInSnapshot(data.insns_->ptr());
       profile_writer_->SetObjectTypeAndName(id, type, object_name);
       profile_writer_->AttributeBytesTo(id, size);
       const intptr_t element_offset = id.second - parent_id.second;
@@ -769,7 +770,7 @@
 
       // Write Instructions with the mark and read-only bits set.
       text_offset += WriteTargetWord(GetMarkedTags(insns));
-      text_offset += WriteFixed(insns.raw_ptr()->size_and_flags_);
+      text_offset += WriteFixed(insns.untag()->size_and_flags_);
       text_offset +=
           Align(compiler::target::Instructions::kNonBarePayloadAlignment,
                 text_offset);
@@ -798,7 +799,7 @@
       const uword payload_size = insns.Size();
       descriptors = code.pc_descriptors();
       PcDescriptors::Iterator iterator(
-          descriptors, /*kind_mask=*/PcDescriptorsLayout::kBSSRelocation);
+          descriptors, /*kind_mask=*/UntaggedPcDescriptors::kBSSRelocation);
 
       auto const payload_end = payload_start + payload_size;
       auto cursor = payload_start;
@@ -835,7 +836,7 @@
             : compiler::target::ObjectAlignment::kObjectAlignment;
     text_offset += AlignWithBreakInstructions(alignment, text_offset);
 
-    ASSERT_EQUAL(text_offset - instr_start, SizeInSnapshot(insns.raw()));
+    ASSERT_EQUAL(text_offset - instr_start, SizeInSnapshot(insns.ptr()));
   }
 
   // Should be a no-op unless writing bare instruction payloads, in which case
@@ -1293,8 +1294,8 @@
   assembly_stream_->WriteString(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
 
 #elif defined(TARGET_ARCH_ARM64)
-  COMPILE_ASSERT(FP == R29);
-  COMPILE_ASSERT(LR == R30);
+  COMPILE_ASSERT(R29 == FP);
+  COMPILE_ASSERT(R30 == LINK_REGISTER);
   assembly_stream_->WriteString(".cfi_def_cfa x29, 0\n");  // CFA is fp+0
   assembly_stream_->WriteString(
       ".cfi_offset x29, 0\n");  // saved fp is *(CFA+0)
@@ -1556,10 +1557,10 @@
   ASSERT(!FLAG_precompiled_mode || !FLAG_use_bare_instructions);
   ASSERT(Utils::IsAligned(offset, kObjectAlignment));
 
-  ObjectPtr result = ObjectLayout::FromAddr(
+  ObjectPtr result = UntaggedObject::FromAddr(
       reinterpret_cast<uword>(instructions_image_) + offset);
   ASSERT(result->IsInstructions());
-  ASSERT(result->ptr()->IsMarked());
+  ASSERT(result->untag()->IsMarked());
 
   return Instructions::RawCast(result);
 }
@@ -1568,8 +1569,8 @@
   ASSERT(Utils::IsAligned(offset, kObjectAlignment));
 
   ObjectPtr result =
-      ObjectLayout::FromAddr(reinterpret_cast<uword>(data_image_) + offset);
-  ASSERT(result->ptr()->IsMarked());
+      UntaggedObject::FromAddr(reinterpret_cast<uword>(data_image_) + offset);
+  ASSERT(result->untag()->IsMarked());
 
   return result;
 }
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index cc5ac6d..a11356f 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -126,13 +126,13 @@
 
   // We don't use a handle or the tagged pointer because this object cannot be
   // moved in memory by the GC.
-  static const InstructionsSectionLayout* ExtraInfo(const uword raw_memory,
-                                                    const uword size);
+  static const UntaggedInstructionsSection* ExtraInfo(const uword raw_memory,
+                                                      const uword size);
 
   // Most internal uses would cast this to uword, so just store it as such.
   const uword raw_memory_;
   const intptr_t snapshot_size_;
-  const InstructionsSectionLayout* const extra_info_;
+  const UntaggedInstructionsSection* const extra_info_;
 
   // For access to private constants.
   friend class AssemblyImageWriter;
@@ -295,7 +295,7 @@
 
   static intptr_t SizeInSnapshot(ObjectPtr object);
   static intptr_t SizeInSnapshot(const Object& object) {
-    return SizeInSnapshot(object.raw());
+    return SizeInSnapshot(object.ptr());
   }
 
   // Returns nullptr if there is no profile writer.
@@ -430,7 +430,7 @@
   // instruction for the target architecture is used.
   intptr_t AlignWithBreakInstructions(intptr_t alignment, intptr_t offset);
 
-  Heap* heap_;  // Used for mapping RawInstructiosn to object ids.
+  Heap* heap_;  // Used for mapping InstructionsPtr to object ids.
   intptr_t next_data_offset_;
   intptr_t next_text_offset_;
   GrowableArray<ObjectData> objects_;
@@ -501,7 +501,7 @@
         owner_(Object::Handle(zone)),
         string_(String::Handle(zone)),
         insns_(Instructions::Handle(zone)),
-        store_(Isolate::Current()->object_store()) {}
+        store_(IsolateGroup::Current()->object_store()) {}
 
   const char* StubNameForType(const AbstractType& type) const;
 
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index 83ae8f5..16bb992 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -11,6 +11,7 @@
 #include "vm/constants.h"
 #include "vm/cpu.h"
 #include "vm/object.h"
+#include "vm/object_store.h"
 #include "vm/reverse_pc_lookup_cache.h"
 
 namespace dart {
@@ -220,12 +221,14 @@
   Register dst;
   if (IsLoadWithOffset(instr, PP, &offset, &dst)) {
     intptr_t index = ObjectPool::IndexFromOffset(offset);
-    const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-    if (!pool.IsNull()) {
-      if (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
-        *obj = pool.ObjectAt(index);
-        return true;
-      }
+    const ObjectPool& pool = ObjectPool::Handle(
+        FLAG_use_bare_instructions
+            ? IsolateGroup::Current()->object_store()->global_object_pool()
+            : code.object_pool());
+    if (!pool.IsNull() && (index < pool.Length()) &&
+        (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) {
+      *obj = pool.ObjectAt(index);
+      return true;
     }
   } else if (IsLoadWithOffset(instr, THR, &offset, &dst)) {
     return Thread::ObjectAtOffset(offset, obj);
@@ -310,7 +313,7 @@
 
   InstructionPattern::DecodeLoadWordFromPool(data_load_end, &reg,
                                              &target_pool_index_);
-  ASSERT(reg == LR);
+  ASSERT(reg == LINK_REGISTER);
 }
 
 CodePtr BareSwitchableCallPattern::target() const {
@@ -319,7 +322,7 @@
   if (result != Code::null()) {
     return result;
   }
-  result = ReversePc::Lookup(Dart::vm_isolate()->group(), pc);
+  result = ReversePc::Lookup(Dart::vm_isolate_group(), pc);
   if (result != Code::null()) {
     return result;
   }
@@ -342,7 +345,7 @@
   const int32_t B24 = 1 << 24;
   int32_t instruction = (static_cast<int32_t>(AL) << kConditionShift) | B24 |
                         B21 | (0xfff << 8) | B4 |
-                        (static_cast<int32_t>(LR) << kRmShift);
+                        (LINK_REGISTER.code << kRmShift);
   return bx_lr->InstructionBits() == instruction;
 }
 
diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h
index 1ddbc90..5fe9ab3 100644
--- a/runtime/vm/instructions_arm.h
+++ b/runtime/vm/instructions_arm.h
@@ -25,7 +25,7 @@
 class Code;
 class Object;
 class ObjectPool;
-class CodeLayout;
+class UntaggedCode;
 
 class InstructionPattern : public AllStatic {
  public:
diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc
index 2eed6c0..210fca3 100644
--- a/runtime/vm/instructions_arm64.cc
+++ b/runtime/vm/instructions_arm64.cc
@@ -11,6 +11,7 @@
 #include "vm/constants.h"
 #include "vm/cpu.h"
 #include "vm/object.h"
+#include "vm/object_store.h"
 #include "vm/reverse_pc_lookup_cache.h"
 
 namespace dart {
@@ -53,8 +54,8 @@
       native_function_pool_index_(-1),
       target_code_pool_index_(-1) {
   ASSERT(code.ContainsInstructionAt(pc));
-  // Last instruction: blr ip0.
-  ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f0200);
+  // Last instruction: blr lr.
+  ASSERT(*(reinterpret_cast<uint32_t*>(end_) - 1) == 0xd63f03c0);
 
   Register reg;
   uword native_function_load_end = InstructionPattern::DecodeLoadWordFromPool(
@@ -330,17 +331,15 @@
     if (instr->RnField() == PP) {
       // PP is untagged on ARM64.
       ASSERT(Utils::IsAligned(offset, 8));
-      // A code object may have an object pool attached in bare instructions
-      // mode if the v8 snapshot profile writer is active, but this pool cannot
-      // be used for object loading.
-      if (FLAG_use_bare_instructions) return false;
       intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag);
-      const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-      if (!pool.IsNull()) {
-        if (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
-          *obj = pool.ObjectAt(index);
-          return true;
-        }
+      const ObjectPool& pool = ObjectPool::Handle(
+          FLAG_use_bare_instructions
+              ? IsolateGroup::Current()->object_store()->global_object_pool()
+              : code.object_pool());
+      if (!pool.IsNull() && (index < pool.Length()) &&
+          (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) {
+        *obj = pool.ObjectAt(index);
+        return true;
       }
     } else if (instr->RnField() == THR) {
       return Thread::ObjectAtOffset(offset, obj);
@@ -449,7 +448,7 @@
   InstructionPattern::DecodeLoadDoubleWordFromPool(
       pc - Instr::kInstrSize, &ic_data_reg, &code_reg, &pool_index);
   ASSERT(ic_data_reg == R5);
-  ASSERT(code_reg == LR);
+  ASSERT(code_reg == LINK_REGISTER);
 
   data_pool_index_ = pool_index;
   target_pool_index_ = pool_index + 1;
@@ -461,7 +460,7 @@
   if (result != Code::null()) {
     return result;
   }
-  result = ReversePc::Lookup(Dart::vm_isolate()->group(), pc);
+  result = ReversePc::Lookup(Dart::vm_isolate_group(), pc);
   if (result != Code::null()) {
     return result;
   }
@@ -479,7 +478,7 @@
 
 bool ReturnPattern::IsValid() const {
   Instr* bx_lr = Instr::At(pc_);
-  const Register crn = ConcreteRegister(LR);
+  const Register crn = ConcreteRegister(LINK_REGISTER);
   const int32_t instruction = RET | (static_cast<int32_t>(crn) << kRnShift);
   return bx_lr->InstructionBits() == instruction;
 }
diff --git a/runtime/vm/instructions_arm64_test.cc b/runtime/vm/instructions_arm64_test.cc
index 4a6528c..6ede71a 100644
--- a/runtime/vm/instructions_arm64_test.cc
+++ b/runtime/vm/instructions_arm64_test.cc
@@ -16,9 +16,11 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
-  __ set_constant_pool_allowed(true);
+  // Code is generated, but not executed. Just parsed with CallPattern
+  __ set_constant_pool_allowed(true);  // Uninitialized pp is OK.
+  SPILLS_LR_TO_FRAME({});              // Clobbered LR is OK.
   __ BranchLinkPatchable(StubCode::InvokeDartCode());
+  RESTORES_LR_FROM_FRAME({});  // Clobbered LR is OK.
   __ ret();
 }
 
@@ -28,7 +30,7 @@
   // before the end of the code buffer.
   uword end = test->payload_start() + test->code().Size();
   CallPattern call(end - Instr::kInstrSize, test->code());
-  EXPECT_EQ(StubCode::InvokeDartCode().raw(), call.TargetCode());
+  EXPECT_EQ(StubCode::InvokeDartCode().ptr(), call.TargetCode());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/instructions_arm_test.cc b/runtime/vm/instructions_arm_test.cc
index e9fc409..90f439d 100644
--- a/runtime/vm/instructions_arm_test.cc
+++ b/runtime/vm/instructions_arm_test.cc
@@ -16,9 +16,11 @@
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Call, assembler) {
-  // Code accessing pp is generated, but not executed. Uninitialized pp is OK.
-  __ set_constant_pool_allowed(true);
+  // Code is generated, but not executed. Just parsed with CallPattern.
+  __ set_constant_pool_allowed(true);  // Uninitialized pp is OK.
+  SPILLS_LR_TO_FRAME({});              // Clobbered LR is OK.
   __ BranchLinkPatchable(StubCode::InvokeDartCode());
+  RESTORES_LR_FROM_FRAME({});  // Clobbered LR is OK.
   __ Ret();
 }
 
@@ -28,7 +30,7 @@
   // before the end of the code buffer.
   uword end = test->payload_start() + test->code().Size();
   CallPattern call(end - Instr::kInstrSize, test->code());
-  EXPECT_EQ(StubCode::InvokeDartCode().raw(), call.TargetCode());
+  EXPECT_EQ(StubCode::InvokeDartCode().ptr(), call.TargetCode());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc
index 256faa9..7495066f 100644
--- a/runtime/vm/instructions_x64.cc
+++ b/runtime/vm/instructions_x64.cc
@@ -14,6 +14,7 @@
 #include "vm/constants.h"
 #include "vm/cpu.h"
 #include "vm/object.h"
+#include "vm/object_store.h"
 
 namespace dart {
 
@@ -63,22 +64,26 @@
     if ((bytes[1] == 0x8b) || (bytes[1] == 0x3b)) {  // movq, cmpq
       if ((bytes[2] & 0xc7) == (0x80 | (PP & 7))) {  // [r15+disp32]
         intptr_t index = IndexFromPPLoadDisp32(pc + 3);
-        const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-        if (!pool.IsNull()) {
-          if (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
-            *obj = pool.ObjectAt(index);
-            return true;
-          }
+        const ObjectPool& pool = ObjectPool::Handle(
+            FLAG_use_bare_instructions
+                ? IsolateGroup::Current()->object_store()->global_object_pool()
+                : code.object_pool());
+        if (!pool.IsNull() && (index < pool.Length()) &&
+            (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) {
+          *obj = pool.ObjectAt(index);
+          return true;
         }
       }
       if ((bytes[2] & 0xc7) == (0x40 | (PP & 7))) {  // [r15+disp8]
         intptr_t index = IndexFromPPLoadDisp8(pc + 3);
-        const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-        if (!pool.IsNull()) {
-          if (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
-            *obj = pool.ObjectAt(index);
-            return true;
-          }
+        const ObjectPool& pool = ObjectPool::Handle(
+            FLAG_use_bare_instructions
+                ? IsolateGroup::Current()->object_store()->global_object_pool()
+                : code.object_pool());
+        if (!pool.IsNull() && (index < pool.Length()) &&
+            (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject)) {
+          *obj = pool.ObjectAt(index);
+          return true;
         }
       }
     }
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 4500d86..a837201 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -106,6 +106,7 @@
 // Quick access to the locally defined thread() and isolate() methods.
 #define T (thread())
 #define I (isolate())
+#define IG (isolate_group())
 
 #if defined(DEBUG)
 // Helper class to ensure that a live origin_id is never reused
@@ -124,8 +125,8 @@
 
 static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
                                                  const Instance& obj) {
-  if (ApiObjectConverter::CanConvert(obj.raw())) {
-    return Message::New(dest_port, obj.raw(), Message::kNormalPriority);
+  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);
@@ -190,7 +191,7 @@
     Array& new_array =
         Array::Handle(Array::Grow(loaded_blobs, length + 1, Heap::kOld));
     new_array.SetAt(length, weak_property);
-    loaded_blobs_ = new_array.raw();
+    loaded_blobs_ = new_array.ptr();
   }
   num_blob_loads_++;
 }
@@ -329,7 +330,8 @@
 
 IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
                            void* embedder_data,
-                           ObjectStore* object_store)
+                           ObjectStore* object_store,
+                           Dart_IsolateFlags api_flags)
     : embedder_data_(embedder_data),
       thread_pool_(),
       isolates_lock_(new SafepointRwLock()),
@@ -345,11 +347,7 @@
       safepoint_handler_(new SafepointHandler(this)),
       shared_class_table_(new SharedClassTable()),
       object_store_(object_store),
-#if defined(DART_PRECOMPILED_RUNTIME)
       class_table_(new ClassTable(shared_class_table_.get())),
-#else
-      class_table_(nullptr),
-#endif
       store_buffer_(new StoreBuffer()),
       heap_(nullptr),
       saved_unlinked_calls_(Array::null()),
@@ -378,6 +376,7 @@
       program_lock_(new SafepointRwLock()),
       active_mutators_monitor_(new Monitor()),
       max_active_mutators_(Scavenger::MaxMutatorThreadCount()) {
+  FlagsCopyFrom(api_flags);
   const bool is_vm_isolate = Dart::VmIsolateNameEquals(source_->name);
   if (!is_vm_isolate) {
     thread_pool_.reset(
@@ -392,15 +391,9 @@
 }
 
 IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
-                           void* embedder_data)
-    : IsolateGroup(source,
-                   embedder_data,
-#if !defined(DART_PRECOMPILED_RUNTIME)
-                   // in JIT, with --enable_isolate_groups keep object store
-                   // on isolate, rather than on isolate group
-                   FLAG_enable_isolate_groups ? nullptr :
-#endif
-                                              new ObjectStore()) {
+                           void* embedder_data,
+                           Dart_IsolateFlags api_flags)
+    : IsolateGroup(source, embedder_data, new ObjectStore(), api_flags) {
   if (object_store() != nullptr) {
     object_store()->InitStubs();
   }
@@ -414,6 +407,13 @@
   // Ensure we destroy the heap before the other members.
   heap_ = nullptr;
   ASSERT(marking_stack_ == nullptr);
+
+  if (obfuscation_map_ != nullptr) {
+    for (intptr_t i = 0; obfuscation_map_[i] != nullptr; i++) {
+      delete[] obfuscation_map_[i];
+    }
+    delete[] obfuscation_map_;
+  }
 }
 
 void IsolateGroup::RegisterIsolate(Isolate* isolate) {
@@ -429,7 +429,7 @@
 
 bool IsolateGroup::ContainsOnlyOneIsolate() {
   SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
-  return isolate_count_ == 0;
+  return isolate_count_ == 1;
 }
 
 void IsolateGroup::RunWithLockedGroup(std::function<void()> fun) {
@@ -522,7 +522,7 @@
 }
 
 void IsolateGroup::set_saved_unlinked_calls(const Array& saved_unlinked_calls) {
-  saved_unlinked_calls_ = saved_unlinked_calls.raw();
+  saved_unlinked_calls_ = saved_unlinked_calls.ptr();
 }
 
 Thread* IsolateGroup::ScheduleThreadLocked(MonitorLocker* ml,
@@ -753,16 +753,9 @@
 }
 
 void IsolateGroup::PrintMemoryUsageJSON(JSONStream* stream) {
-  int64_t used = 0;
-  int64_t capacity = 0;
-  int64_t external_used = 0;
-
-  for (auto it = isolates_.Begin(); it != isolates_.End(); ++it) {
-    Isolate* isolate = *it;
-    used += isolate->heap()->TotalUsedInWords();
-    capacity += isolate->heap()->TotalCapacityInWords();
-    external_used += isolate->heap()->TotalExternalInWords();
-  }
+  int64_t used = heap()->TotalUsedInWords();
+  int64_t capacity = heap()->TotalCapacityInWords();
+  int64_t external_used = heap()->TotalExternalInWords();
 
   JSONObject jsobj(stream);
   // This is the same "MemoryUsage" that the isolate-specific "getMemoryUsage"
@@ -886,20 +879,20 @@
 void Isolate::RegisterClass(const Class& cls) {
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   if (group()->IsReloading()) {
-    reload_context()->RegisterClass(cls);
+    program_reload_context()->RegisterClass(cls);
     return;
   }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   if (cls.IsTopLevel()) {
-    class_table()->RegisterTopLevel(cls);
+    group()->class_table()->RegisterTopLevel(cls);
   } else {
-    class_table()->Register(cls);
+    group()->class_table()->Register(cls);
   }
 }
 
 #if defined(DEBUG)
 void Isolate::ValidateClassTable() {
-  class_table()->Validate();
+  group()->class_table()->Validate();
 }
 #endif  // DEBUG
 
@@ -908,15 +901,31 @@
   ASSERT(program_lock()->IsCurrentThreadWriter());
 
   ASSERT(field.is_static());
-  initial_field_table()->Register(field);
-  initial_field_table()->SetAt(field.field_id(), initial_value.raw());
+  const bool need_to_grow_backing_store =
+      initial_field_table()->Register(field);
+  const intptr_t field_id = field.field_id();
+  initial_field_table()->SetAt(field_id, initial_value.ptr());
 
-  // TODO(dartbug.com/36097): When we start sharing the object stores (and
-  // therefore libraries, classes, fields) we'll have to register the initial
-  // static field value in all isolates.
-  auto current = Isolate::Current();
-  current->field_table()->AllocateIndex(field.field_id());
-  current->field_table()->SetAt(field.field_id(), initial_value.raw());
+  if (need_to_grow_backing_store) {
+    // We have to stop other isolates from accessing their field state, since
+    // we'll have to grow the backing store.
+    SafepointOperationScope ops(Thread::Current());
+    for (auto isolate : isolates_) {
+      auto field_table = isolate->field_table();
+      if (field_table->IsReadyToUse()) {
+        field_table->Register(field, field_id);
+        field_table->SetAt(field_id, initial_value.ptr());
+      }
+    }
+  } else {
+    for (auto isolate : isolates_) {
+      auto field_table = isolate->field_table();
+      if (field_table->IsReadyToUse()) {
+        field_table->Register(field, field_id);
+        field_table->SetAt(field_id, initial_value.ptr());
+      }
+    }
+  }
 }
 
 void Isolate::RehashConstants() {
@@ -927,10 +936,10 @@
   thread->heap()->ResetCanonicalHashTable();
 
   Class& cls = Class::Handle(zone);
-  intptr_t top = class_table()->NumCids();
+  intptr_t top = group()->class_table()->NumCids();
   for (intptr_t cid = kInstanceCid; cid < top; cid++) {
-    if (!class_table()->IsValidIndex(cid) ||
-        !class_table()->HasValidClassAt(cid)) {
+    if (!group()->class_table()->IsValidIndex(cid) ||
+        !group()->class_table()->HasValidClassAt(cid)) {
       continue;
     }
     if ((cid == kTypeArgumentsCid) || IsStringClassId(cid)) {
@@ -938,7 +947,7 @@
       // that aren't based on address.
       continue;
     }
-    cls = class_table()->At(cid);
+    cls = group()->class_table()->At(cid);
     cls.RehashConstants(zone);
   }
 }
@@ -955,7 +964,7 @@
   // Verify that all canonical instances are correctly setup in the
   // corresponding canonical tables.
   BackgroundCompiler::Stop(this);
-  heap()->CollectAllGarbage();
+  group()->heap()->CollectAllGarbage();
   Thread* thread = Thread::Current();
   HeapIterationScope iteration(thread);
   VerifyCanonicalVisitor check_canonical(thread);
@@ -1005,6 +1014,7 @@
 #endif
   bool IsCurrentIsolate() const;
   virtual Isolate* isolate() const { return isolate_; }
+  virtual IsolateGroup* isolate_group() const { return isolate_->group(); }
 
  private:
   // A result of false indicates that the isolate should terminate the
@@ -1105,7 +1115,7 @@
             const UnwindError& error =
                 UnwindError::Handle(UnwindError::New(msg));
             error.set_is_user_initiated(true);
-            return error.raw();
+            return error.ptr();
           } else if (msg_type == Isolate::kInternalKillMsg) {
             const String& msg =
                 String::Handle(String::New("isolate terminated by vm"));
@@ -1146,7 +1156,7 @@
       break;
     }
     case Isolate::kLowMemoryMsg: {
-      I->heap()->NotifyLowMemory();
+      I->group()->heap()->NotifyLowMemory();
       break;
     }
     case Isolate::kDrainServiceExtensionsMsg: {
@@ -1292,12 +1302,12 @@
   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.raw()));
+    ASSERT(ApiObjectConverter::CanConvert(msg_obj.ptr()));
   } else if (message->IsBequest()) {
     Bequest* bequest = message->bequest();
     PersistentHandle* handle = bequest->handle();
-    const Object& obj = Object::Handle(zone, handle->raw());
-    msg_obj = obj.raw();
+    const Object& obj = Object::Handle(zone, handle->ptr());
+    msg_obj = obj.ptr();
   } else {
     MessageSnapshotReader reader(message.get(), thread);
     msg_obj = reader.ReadObject();
@@ -1315,7 +1325,7 @@
     UNREACHABLE();
   }
   Instance& msg = Instance::Handle(zone);
-  msg ^= msg_obj.raw();  // Can't use Instance::Cast because may be null.
+  msg ^= msg_obj.ptr();  // Can't use Instance::Cast because may be null.
 
   MessageStatus status = kOK;
   if (message->IsOOB()) {
@@ -1471,9 +1481,9 @@
     Zone* zone = T->zone();
     const UnhandledException& uhe = UnhandledException::Cast(result);
     const Instance& exception = Instance::Handle(zone, uhe.exception());
-    if (exception.raw() == I->object_store()->out_of_memory()) {
+    if (exception.ptr() == IG->object_store()->out_of_memory()) {
       exception_cstr = "Out of Memory";  // Cf. OutOfMemoryError.toString().
-    } else if (exception.raw() == I->object_store()->stack_overflow()) {
+    } else if (exception.ptr() == IG->object_store()->stack_overflow()) {
       exception_cstr = "Stack Overflow";  // Cf. StackOverflowError.toString().
     } else {
       const Object& exception_str =
@@ -1511,8 +1521,8 @@
       if (result.IsUnhandledException()) {
         const UnhandledException& error = UnhandledException::Cast(result);
         InstancePtr exception = error.exception();
-        if ((exception == I->object_store()->out_of_memory()) ||
-            (exception == I->object_store()->stack_overflow())) {
+        if ((exception == IG->object_store()->out_of_memory()) ||
+            (exception == IG->object_store()->stack_overflow())) {
           // We didn't notify the debugger when the stack was full. Do it now.
           I->debugger()->PauseException(Instance::Handle(exception));
         }
@@ -1524,28 +1534,72 @@
   return kOK;
 }
 
+void IsolateGroup::FlagsInitialize(Dart_IsolateFlags* api_flags) {
+  api_flags->version = DART_FLAGS_CURRENT_VERSION;
+#define INIT_FROM_FLAG(when, name, bitname, isolate_flag, flag)                \
+  api_flags->isolate_flag = flag;
+  BOOL_ISOLATE_GROUP_FLAG_LIST(INIT_FROM_FLAG)
+#undef INIT_FROM_FLAG
+  api_flags->copy_parent_code = false;
+}
+
+void IsolateGroup::FlagsCopyTo(Dart_IsolateFlags* api_flags) {
+  api_flags->version = DART_FLAGS_CURRENT_VERSION;
+#define INIT_FROM_FIELD(when, name, bitname, isolate_flag, flag)               \
+  api_flags->isolate_flag = name();
+  BOOL_ISOLATE_GROUP_FLAG_LIST(INIT_FROM_FIELD)
+#undef INIT_FROM_FIELD
+  api_flags->copy_parent_code = false;
+}
+
+void IsolateGroup::FlagsCopyFrom(const Dart_IsolateFlags& api_flags) {
+#if defined(DART_PRECOMPILER)
+#define FLAG_FOR_PRECOMPILER(action) action
+#else
+#define FLAG_FOR_PRECOMPILER(action)
+#endif
+
+#if !defined(PRODUCT)
+#define FLAG_FOR_NONPRODUCT(action) action
+#else
+#define FLAG_FOR_NONPRODUCT(action)
+#endif
+
+#define FLAG_FOR_PRODUCT(action) action
+
+#define SET_FROM_FLAG(when, name, bitname, isolate_flag, flag)                 \
+  FLAG_FOR_##when(isolate_group_flags_ = bitname##Bit::update(                 \
+                      api_flags.isolate_flag, isolate_group_flags_));
+
+  BOOL_ISOLATE_GROUP_FLAG_LIST(SET_FROM_FLAG)
+  // Needs to be called manually, otherwise we don't set the null_safety_set
+  // bit.
+  set_null_safety(api_flags.null_safety);
+#undef FLAG_FOR_NONPRODUCT
+#undef FLAG_FOR_PRECOMPILER
+#undef FLAG_FOR_PRODUCT
+#undef SET_FROM_FLAG
+}
+
 void Isolate::FlagsInitialize(Dart_IsolateFlags* api_flags) {
-  const bool false_by_default = false;
-  const bool true_by_default = true;
-  USE(true_by_default);
-  USE(false_by_default);
+  IsolateGroup::FlagsInitialize(api_flags);
 
   api_flags->version = DART_FLAGS_CURRENT_VERSION;
 #define INIT_FROM_FLAG(when, name, bitname, isolate_flag, flag)                \
   api_flags->isolate_flag = flag;
   BOOL_ISOLATE_FLAG_LIST(INIT_FROM_FLAG)
 #undef INIT_FROM_FLAG
-  api_flags->entry_points = NULL;
   api_flags->copy_parent_code = false;
 }
 
 void Isolate::FlagsCopyTo(Dart_IsolateFlags* api_flags) const {
+  group()->FlagsCopyTo(api_flags);
+
   api_flags->version = DART_FLAGS_CURRENT_VERSION;
 #define INIT_FROM_FIELD(when, name, bitname, isolate_flag, flag)               \
   api_flags->isolate_flag = name();
   BOOL_ISOLATE_FLAG_LIST(INIT_FROM_FIELD)
 #undef INIT_FROM_FIELD
-  api_flags->entry_points = NULL;
   api_flags->copy_parent_code = false;
 }
 
@@ -1571,34 +1625,10 @@
 
   BOOL_ISOLATE_FLAG_LIST(SET_FROM_FLAG)
   isolate_flags_ = CopyParentCodeBit::update(copy_parent_code_, isolate_flags_);
-  // Needs to be called manually, otherwise we don't set the null_safety_set
-  // bit.
-  set_null_safety(api_flags.null_safety);
 #undef FLAG_FOR_NONPRODUCT
 #undef FLAG_FOR_PRECOMPILER
 #undef FLAG_FOR_PRODUCT
 #undef SET_FROM_FLAG
-
-  // Copy entry points list.
-  ASSERT(embedder_entry_points_ == NULL);
-  if (api_flags.entry_points != NULL) {
-    intptr_t count = 0;
-    while (api_flags.entry_points[count].function_name != NULL)
-      count++;
-    embedder_entry_points_ = new Dart_QualifiedFunctionName[count + 1];
-    for (intptr_t i = 0; i < count; i++) {
-      embedder_entry_points_[i].library_uri =
-          Utils::StrDup(api_flags.entry_points[i].library_uri);
-      embedder_entry_points_[i].class_name =
-          Utils::StrDup(api_flags.entry_points[i].class_name);
-      embedder_entry_points_[i].function_name =
-          Utils::StrDup(api_flags.entry_points[i].function_name);
-    }
-    memset(&embedder_entry_points_[count], 0,
-           sizeof(Dart_QualifiedFunctionName));
-  }
-
-  // Leave others at defaults.
 }
 
 #if defined(DEBUG)
@@ -1636,11 +1666,7 @@
       isolate_object_store_(
           new IsolateObjectStore(isolate_group->object_store())),
       object_store_shared_ptr_(isolate_group->object_store_shared_ptr()),
-#if defined(DART_PRECOMPILED_RUNTIME)
       class_table_(isolate_group->class_table_shared_ptr()),
-#else
-      class_table_(new ClassTable(shared_class_table_)),
-#endif
 #if !defined(DART_PRECOMPILED_RUNTIME)
       native_callback_trampolines_(),
 #endif
@@ -1678,7 +1704,7 @@
   // move to the OSThread structure.
   set_user_tag(UserTags::kDefaultUserTag);
 
-  if (obfuscate()) {
+  if (group()->obfuscate()) {
     OS::PrintErr(
         "Warning: This VM has been configured to obfuscate symbol information "
         "which violates the Dart standard.\n"
@@ -1695,7 +1721,7 @@
 Isolate::~Isolate() {
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   // TODO(32796): Re-enable assertion.
-  // RELEASE_ASSERT(reload_context_ == NULL);
+  // RELEASE_ASSERT(program_reload_context_ == NULL);
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
   delete optimizing_background_compiler_;
@@ -1729,23 +1755,6 @@
   mutator_thread_->isolate_ = nullptr;
   delete mutator_thread_;
   mutator_thread_ = nullptr;
-
-  if (obfuscation_map_ != nullptr) {
-    for (intptr_t i = 0; obfuscation_map_[i] != nullptr; i++) {
-      delete[] obfuscation_map_[i];
-    }
-    delete[] obfuscation_map_;
-  }
-
-  if (embedder_entry_points_ != nullptr) {
-    for (intptr_t i = 0; embedder_entry_points_[i].function_name != nullptr;
-         i++) {
-      free(const_cast<char*>(embedder_entry_points_[i].library_uri));
-      free(const_cast<char*>(embedder_entry_points_[i].class_name));
-      free(const_cast<char*>(embedder_entry_points_[i].function_name));
-    }
-    delete[] embedder_entry_points_;
-  }
 }
 
 void Isolate::InitVM() {
@@ -1773,12 +1782,7 @@
     // Non-vm isolates need to have isolate object store initialized is that
     // exit_listeners have to be null-initialized as they will be used if
     // we fail to create isolate below, have to do low level shutdown.
-    if (result->object_store() == nullptr) {
-      // in JIT with --enable-isolate-groups each isolate still
-      // has to have its own object store
-      result->set_object_store(new ObjectStore());
-      result->object_store()->InitStubs();
-    }
+    ASSERT(result->group()->object_store() != nullptr);
     result->isolate_object_store()->Init();
   }
 
@@ -1865,8 +1869,8 @@
                                   const Object& arg2) {
   Thread* thread = Thread::Current();
   Api::Scope api_scope(thread);
-  Dart_Handle api_arg1 = Api::NewHandle(thread, arg1.raw());
-  Dart_Handle api_arg2 = Api::NewHandle(thread, arg2.raw());
+  Dart_Handle api_arg1 = Api::NewHandle(thread, arg1.ptr());
+  Dart_Handle api_arg2 = Api::NewHandle(thread, arg2.ptr());
   Dart_Handle api_result;
   {
     TransitionVMToNative transition(thread);
@@ -1890,8 +1894,8 @@
 
 void Isolate::SetupImagePage(const uint8_t* image_buffer, bool is_executable) {
   Image image(image_buffer);
-  heap()->SetupImagePage(image.object_start(), image.object_size(),
-                         is_executable);
+  group()->heap()->SetupImagePage(image.object_start(), image.object_size(),
+                                  is_executable);
 }
 
 void Isolate::ScheduleInterrupts(uword interrupt_bits) {
@@ -1945,7 +1949,7 @@
   const Error& error = Error::Handle(debugger_->PausePostRequest());
   if (!error.IsNull()) {
     if (Thread::Current()->top_exit_frame_info() == 0) {
-      return error.raw();
+      return error.ptr();
     } else {
       Exceptions::PropagateError(error);
       UNREACHABLE();
@@ -1991,8 +1995,8 @@
 
   ForEachIsolate([&](Isolate* isolate) {
     isolate->SetHasAttemptedReload(true);
-    isolate->reload_context_ =
-        new IsolateReloadContext(group_reload_context_, isolate);
+    isolate->program_reload_context_ =
+        new ProgramReloadContext(group_reload_context_, isolate);
   });
   const bool success =
       group_reload_context_->Reload(force_reload, root_script_url, packages_url,
@@ -2024,8 +2028,8 @@
 
   ForEachIsolate([&](Isolate* isolate) {
     isolate->SetHasAttemptedReload(true);
-    isolate->reload_context_ =
-        new IsolateReloadContext(group_reload_context_, isolate);
+    isolate->program_reload_context_ =
+        new ProgramReloadContext(group_reload_context_, isolate);
   });
   const bool success = group_reload_context_->Reload(
       force_reload,
@@ -2047,8 +2051,8 @@
   // Another thread may be in the middle of GetClassForHeapWalkAt.
   SafepointOperationScope safepoint_scope(Thread::Current());
 
-  delete reload_context_;
-  reload_context_ = nullptr;
+  delete program_reload_context_;
+  program_reload_context_ = nullptr;
 }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -2058,7 +2062,7 @@
   if (is_runnable() == true) {
     return "Isolate is already runnable";
   }
-  if (object_store()->root_library() == Library::null()) {
+  if (group()->object_store()->root_library() == Library::null()) {
     return "The embedder has to ensure there is a root library (e.g. by "
            "calling Dart_LoadScriptFromKernel ).";
   }
@@ -2069,7 +2073,7 @@
 void Isolate::MakeRunnableLocked() {
   ASSERT(mutex_.IsOwnedByCurrentThread());
   ASSERT(!is_runnable());
-  ASSERT(object_store()->root_library() != Library::null());
+  ASSERT(group()->object_store()->root_library() != Library::null());
 
   // Set the isolate as runnable and if we are being spawned schedule
   // isolate on thread pool for execution.
@@ -2324,59 +2328,6 @@
                          reinterpret_cast<uword>(this));
 }
 
-void Isolate::AddClosureFunction(const Function& function) const {
-  ASSERT(!Compiler::IsBackgroundCompilation());
-  GrowableObjectArray& closures =
-      GrowableObjectArray::Handle(object_store()->closure_functions());
-  ASSERT(!closures.IsNull());
-  ASSERT(function.IsNonImplicitClosureFunction());
-  closures.Add(function, Heap::kOld);
-}
-
-// If the linear lookup turns out to be too expensive, the list
-// of closures could be maintained in a hash map, with the key
-// being the token position of the closure. There are almost no
-// collisions with this simple hash value. However, iterating over
-// all closure functions becomes more difficult, especially when
-// the list/map changes while iterating over it.
-FunctionPtr Isolate::LookupClosureFunction(const Function& parent,
-                                           TokenPosition token_pos) const {
-  const GrowableObjectArray& closures =
-      GrowableObjectArray::Handle(object_store()->closure_functions());
-  ASSERT(!closures.IsNull());
-  Function& closure = Function::Handle();
-  intptr_t num_closures = closures.Length();
-  for (intptr_t i = 0; i < num_closures; i++) {
-    closure ^= closures.At(i);
-    if ((closure.token_pos() == token_pos) &&
-        (closure.parent_function() == parent.raw())) {
-      return closure.raw();
-    }
-  }
-  return Function::null();
-}
-
-intptr_t Isolate::FindClosureIndex(const Function& needle) const {
-  const GrowableObjectArray& closures_array =
-      GrowableObjectArray::Handle(object_store()->closure_functions());
-  intptr_t num_closures = closures_array.Length();
-  for (intptr_t i = 0; i < num_closures; i++) {
-    if (closures_array.At(i) == needle.raw()) {
-      return i;
-    }
-  }
-  return -1;
-}
-
-FunctionPtr Isolate::ClosureFunctionFromIndex(intptr_t idx) const {
-  const GrowableObjectArray& closures_array =
-      GrowableObjectArray::Handle(object_store()->closure_functions());
-  if ((idx < 0) || (idx >= closures_array.Length())) {
-    return Function::null();
-  }
-  return Function::RawCast(closures_array.At(idx));
-}
-
 // static
 void Isolate::NotifyLowMemory() {
   Isolate::KillAllIsolates(Isolate::kLowMemoryMsg);
@@ -2391,7 +2342,7 @@
   NoSafepointScope no_safepoint_scope;
 
   // Notify exit listeners that this isolate is shutting down.
-  if (object_store() != nullptr) {
+  if (group()->object_store() != nullptr) {
     const Error& error = Error::Handle(thread->sticky_error());
     if (error.IsNull() || !error.IsUnwindError() ||
         UnwindError::Cast(error).is_user_initiated()) {
@@ -2424,10 +2375,10 @@
     MegamorphicCacheTable::PrintSizes(this);
   }
   if (FLAG_dump_symbol_stats) {
-    Symbols::DumpStats(this);
+    Symbols::DumpStats(group());
   }
   if (FLAG_trace_isolates) {
-    heap()->PrintSizes();
+    group()->heap()->PrintSizes();
     OS::PrintErr(
         "[-] Stopping isolate:\n"
         "\tisolate:    %s\n",
@@ -2608,21 +2559,11 @@
                                   ValidationPolicy validate_frames) {
   ASSERT(visitor != nullptr);
 
-  // Visit objects in the object store if there is no isolate group object store
-  if (group()->object_store() == nullptr && object_store() != nullptr) {
-    object_store()->VisitObjectPointers(visitor);
-  }
   // Visit objects in the isolate object store.
   if (isolate_object_store() != nullptr) {
     isolate_object_store()->VisitObjectPointers(visitor);
   }
 
-  // Visit objects in the class table unless it's shared by the group.
-  // If it is shared, it is visited by IsolateGroup::VisitObjectPointers
-  if (group()->class_table() != class_table()) {
-    class_table()->VisitObjectPointers(visitor);
-  }
-
   // Visit objects in the field table.
   if (!visitor->trace_values_through_fields()) {
     field_table()->VisitObjectPointers(visitor);
@@ -2668,9 +2609,10 @@
   }
 #if !defined(DART_PRECOMPILED_RUNTIME)
   // Visit objects that are being used for isolate reload.
-  if (reload_context() != nullptr) {
-    reload_context()->VisitObjectPointers(visitor);
-    reload_context()->group_reload_context()->VisitObjectPointers(visitor);
+  if (program_reload_context() != nullptr) {
+    program_reload_context()->VisitObjectPointers(visitor);
+    program_reload_context()->group_reload_context()->VisitObjectPointers(
+        visitor);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   if (ServiceIsolate::IsServiceIsolate(this)) {
@@ -2867,15 +2809,15 @@
   ClassPtr raw_class = nullptr;
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   if (group()->IsReloading()) {
-    raw_class = reload_context()->GetClassForHeapWalkAt(cid);
+    raw_class = program_reload_context()->GetClassForHeapWalkAt(cid);
   } else {
-    raw_class = class_table()->At(cid);
+    raw_class = group()->class_table()->At(cid);
   }
 #else
-  raw_class = class_table()->At(cid);
+  raw_class = group()->class_table()->At(cid);
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   ASSERT(raw_class != nullptr);
-  ASSERT(remapping_cids() || raw_class->ptr()->id_ == cid);
+  ASSERT(remapping_cids() || raw_class->untag()->id_ == cid);
   return raw_class;
 }
 
@@ -2970,8 +2912,8 @@
   jsobj.AddPropertyTimeMillis("startTime", start_time);
   {
     JSONObject jsheap(&jsobj, "_heaps");
-    heap()->PrintToJSONObject(Heap::kNew, &jsheap);
-    heap()->PrintToJSONObject(Heap::kOld, &jsheap);
+    group()->heap()->PrintToJSONObject(Heap::kNew, &jsheap);
+    group()->heap()->PrintToJSONObject(Heap::kOld, &jsheap);
   }
 
   {
@@ -3042,7 +2984,7 @@
     jsobj.AddProperty("pauseEvent", &pause_event);
   }
 
-  const Library& lib = Library::Handle(object_store()->root_library());
+  const Library& lib = Library::Handle(group()->object_store()->root_library());
   if (!lib.IsNull()) {
     jsobj.AddProperty("rootLib", lib);
   }
@@ -3063,7 +3005,7 @@
 
   {
     const GrowableObjectArray& libs =
-        GrowableObjectArray::Handle(object_store()->libraries());
+        GrowableObjectArray::Handle(group()->object_store()->libraries());
     intptr_t num_libs = libs.Length();
     Library& lib = Library::Handle();
 
@@ -3113,33 +3055,33 @@
 }
 
 void Isolate::PrintMemoryUsageJSON(JSONStream* stream) {
-  heap()->PrintMemoryUsageJSON(stream);
+  group()->heap()->PrintMemoryUsageJSON(stream);
 }
 
 #endif
 
 void Isolate::set_tag_table(const GrowableObjectArray& value) {
-  tag_table_ = value.raw();
+  tag_table_ = value.ptr();
 }
 
 void Isolate::set_current_tag(const UserTag& tag) {
   uword user_tag = tag.tag();
   ASSERT(user_tag < kUwordMax);
   set_user_tag(user_tag);
-  current_tag_ = tag.raw();
+  current_tag_ = tag.ptr();
 }
 
 void Isolate::set_default_tag(const UserTag& tag) {
-  default_tag_ = tag.raw();
+  default_tag_ = tag.ptr();
 }
 
 void Isolate::set_ic_miss_code(const Code& code) {
-  ic_miss_code_ = code.raw();
+  ic_miss_code_ = code.ptr();
 }
 
 void Isolate::set_deoptimized_code_array(const GrowableObjectArray& value) {
   ASSERT(Thread::Current()->IsMutatorThread());
-  deoptimized_code_array_ = value.raw();
+  deoptimized_code_array_ = value.ptr();
 }
 
 void Isolate::TrackDeoptimizedCode(const Code& code) {
@@ -3165,12 +3107,12 @@
 #if !defined(PRODUCT)
 void Isolate::set_pending_service_extension_calls(
     const GrowableObjectArray& value) {
-  pending_service_extension_calls_ = value.raw();
+  pending_service_extension_calls_ = value.ptr();
 }
 
 void Isolate::set_registered_service_extension_handlers(
     const GrowableObjectArray& value) {
-  registered_service_extension_handlers_ = value.raw();
+  registered_service_extension_handlers_ = value.ptr();
 }
 #endif  // !defined(PRODUCT)
 
@@ -3263,14 +3205,14 @@
         Service::PostError(method_name, parameter_keys, parameter_values,
                            reply_port, id, Error::Cast(result));
       }
-      return Error::Cast(result).raw();
+      return Error::Cast(result).ptr();
     }
     // Drain the microtask queue.
     result = DartLibraryCalls::DrainMicrotaskQueue();
     // Propagate the error.
     if (result.IsError()) {
       // Remaining service extension calls are dropped.
-      return Error::Cast(result).raw();
+      return Error::Cast(result).ptr();
     }
   }
   return Error::null();
@@ -3410,11 +3352,12 @@
   set_message_notify_callback(Isolate::WakePauseEventHandler);
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  const bool had_isolate_reload_context = reload_context() != nullptr;
-  const int64_t start_time_micros =
-      !had_isolate_reload_context
-          ? 0
-          : reload_context()->group_reload_context()->start_time_micros();
+  const bool had_program_reload_context = program_reload_context() != nullptr;
+  const int64_t start_time_micros = !had_program_reload_context
+                                        ? 0
+                                        : program_reload_context()
+                                              ->group_reload_context()
+                                              ->start_time_micros();
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   bool resume = false;
   bool handle_non_service_messages = false;
@@ -3433,7 +3376,7 @@
     }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    if (had_isolate_reload_context && (reload_context() == nullptr)) {
+    if (had_program_reload_context && (program_reload_context() == nullptr)) {
       if (FLAG_trace_reload) {
         const int64_t reload_time_micros =
             OS::GetCurrentMonotonicMicros() - start_time_micros;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index e88229a..0b8dd2c 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -57,7 +57,7 @@
 class ICData;
 class IsolateObjectStore;
 class IsolateProfilerData;
-class IsolateReloadContext;
+class ProgramReloadContext;
 class Log;
 class Message;
 class MessageHandler;
@@ -172,33 +172,35 @@
 
 // List of Isolate flags with corresponding members of Dart_IsolateFlags and
 // corresponding global command line flags.
-#define BOOL_ISOLATE_FLAG_LIST(V)                                              \
-  BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V)                                     \
-  BOOL_ISOLATE_FLAG_LIST_CUSTOM_GETTER(V)
+#define BOOL_ISOLATE_FLAG_LIST(V) BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V)
+
+#define BOOL_ISOLATE_GROUP_FLAG_LIST(V)                                        \
+  BOOL_ISOLATE_GROUP_FLAG_LIST_DEFAULT_GETTER(V)                               \
+  BOOL_ISOLATE_GROUP_FLAG_LIST_CUSTOM_GETTER(V)
 
 // List of Isolate flags with default getters.
 //
 //     V(when, name, bit-name, Dart_IsolateFlags-name, command-line-flag-name)
 //
-#define BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V)                               \
+#define BOOL_ISOLATE_GROUP_FLAG_LIST_DEFAULT_GETTER(V)                         \
+  V(PRECOMPILER, obfuscate, Obfuscate, obfuscate, false)                       \
   V(NONPRODUCT, asserts, EnableAsserts, enable_asserts, FLAG_enable_asserts)   \
   V(NONPRODUCT, use_field_guards, UseFieldGuards, use_field_guards,            \
     FLAG_use_field_guards)                                                     \
-  V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr)                        \
-  V(PRECOMPILER, obfuscate, Obfuscate, obfuscate, false_by_default)            \
+  V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr)
+
+#define BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V)                               \
   V(PRODUCT, should_load_vmservice_library, ShouldLoadVmService,               \
-    load_vmservice_library, false_by_default)                                  \
-  V(PRODUCT, copy_parent_code, CopyParentCode, copy_parent_code,               \
-    false_by_default)                                                          \
-  V(PRODUCT, is_system_isolate, IsSystemIsolate, is_system_isolate,            \
-    false_by_default)
+    load_vmservice_library, false)                                             \
+  V(PRODUCT, copy_parent_code, CopyParentCode, copy_parent_code, false)        \
+  V(PRODUCT, is_system_isolate, IsSystemIsolate, is_system_isolate, false)
 
 // List of Isolate flags with custom getters named #name().
 //
 //     V(when, name, bit-name, Dart_IsolateFlags-name, default_value)
 //
-#define BOOL_ISOLATE_FLAG_LIST_CUSTOM_GETTER(V)                                \
-  V(PRODUCT, null_safety, NullSafety, null_safety, false_by_default)
+#define BOOL_ISOLATE_GROUP_FLAG_LIST_CUSTOM_GETTER(V)                          \
+  V(PRODUCT, null_safety, NullSafety, null_safety, false)
 
 // Represents the information used for spawning the first isolate within an
 // isolate group.
@@ -332,8 +334,11 @@
  public:
   IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
                void* embedder_data,
-               ObjectStore* object_store);
-  IsolateGroup(std::shared_ptr<IsolateGroupSource> source, void* embedder_data);
+               ObjectStore* object_store,
+               Dart_IsolateFlags api_flags);
+  IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
+               void* embedder_data,
+               Dart_IsolateFlags api_flags);
   ~IsolateGroup();
 
   IsolateGroupSource* source() const { return source_.get(); }
@@ -413,8 +418,68 @@
     return shared_class_table_.get();
   }
 
+  void set_obfuscation_map(const char** map) { obfuscation_map_ = map; }
+  const char** obfuscation_map() const { return obfuscation_map_; }
+
   bool is_system_isolate_group() const { return is_system_isolate_group_; }
 
+  // IsolateGroup-specific flag handling.
+  static void FlagsInitialize(Dart_IsolateFlags* api_flags);
+  void FlagsCopyTo(Dart_IsolateFlags* api_flags);
+  void FlagsCopyFrom(const Dart_IsolateFlags& api_flags);
+
+#if defined(DART_PRECOMPILER)
+#define FLAG_FOR_PRECOMPILER(from_field, from_flag) (from_field)
+#else
+#define FLAG_FOR_PRECOMPILER(from_field, from_flag) (from_flag)
+#endif
+
+#if !defined(PRODUCT)
+#define FLAG_FOR_NONPRODUCT(from_field, from_flag) (from_field)
+#else
+#define FLAG_FOR_NONPRODUCT(from_field, from_flag) (from_flag)
+#endif
+
+#define FLAG_FOR_PRODUCT(from_field, from_flag) (from_field)
+
+#define DECLARE_GETTER(when, name, bitname, isolate_flag_name, flag_name)      \
+  bool name() const {                                                          \
+    return FLAG_FOR_##when(bitname##Bit::decode(isolate_group_flags_),         \
+                           flag_name);                                         \
+  }
+  BOOL_ISOLATE_GROUP_FLAG_LIST_DEFAULT_GETTER(DECLARE_GETTER)
+#undef FLAG_FOR_NONPRODUCT
+#undef FLAG_FOR_PRECOMPILER
+#undef FLAG_FOR_PRODUCT
+#undef DECLARE_GETTER
+
+  bool null_safety_not_set() const {
+    return !NullSafetySetBit::decode(isolate_group_flags_);
+  }
+
+  bool null_safety() const {
+    ASSERT(!null_safety_not_set());
+    return NullSafetyBit::decode(isolate_group_flags_);
+  }
+
+  void set_null_safety(bool null_safety) {
+    isolate_group_flags_ = NullSafetySetBit::update(true, isolate_group_flags_);
+    isolate_group_flags_ =
+        NullSafetyBit::update(null_safety, isolate_group_flags_);
+  }
+
+  bool use_strict_null_safety_checks() const {
+    return null_safety() || FLAG_strict_null_safety_checks;
+  }
+
+#if defined(PRODUCT)
+  void set_use_osr(bool use_osr) { ASSERT(!use_osr); }
+#else   // defined(PRODUCT)
+  void set_use_osr(bool use_osr) {
+    isolate_group_flags_ = UseOsrBit::update(use_osr, isolate_group_flags_);
+  }
+#endif  // defined(PRODUCT)
+
   StoreBuffer* store_buffer() const { return store_buffer_.get(); }
   ClassTable* class_table() const { return class_table_.get(); }
   ObjectStore* object_store() const { return object_store_.get(); }
@@ -647,12 +712,19 @@
   friend class Dart;  // For `object_store_ = ` in Dart::Init
   friend class Heap;
   friend class StackFrame;  // For `[isolates_].First()`.
-  // For `object_store_shared_ptr()`, `class_table_shared_ptr()`
+  // For `object_store_shared_untag()`, `class_table_shared_untag()`
   friend class Isolate;
 
-#define ISOLATE_GROUP_FLAG_BITS(V) V(CompactionInProgress)
+#define ISOLATE_GROUP_FLAG_BITS(V)                                             \
+  V(CompactionInProgress)                                                      \
+  V(EnableAsserts)                                                             \
+  V(NullSafety)                                                                \
+  V(NullSafetySet)                                                             \
+  V(Obfuscate)                                                                 \
+  V(UseFieldGuards)                                                            \
+  V(UseOsr)
 
-  // Isolate specific flags.
+  // Isolate group specific flags.
   enum FlagBits {
 #define DECLARE_BIT(Name) k##Name##Bit,
     ISOLATE_GROUP_FLAG_BITS(DECLARE_BIT)
@@ -673,6 +745,8 @@
     return object_store_;
   }
 
+  const char** obfuscation_map_ = nullptr;
+
   bool is_vm_isolate_heap_ = false;
   void* embedder_data_ = nullptr;
 
@@ -718,8 +792,8 @@
   uint64_t id_ = 0;
 
   std::unique_ptr<SharedClassTable> shared_class_table_;
-  std::shared_ptr<ObjectStore> object_store_;  // nullptr in JIT mode
-  std::shared_ptr<ClassTable> class_table_;    // nullptr in JIT mode
+  std::shared_ptr<ObjectStore> object_store_;
+  std::shared_ptr<ClassTable> class_table_;
   std::unique_ptr<StoreBuffer> store_buffer_;
   std::unique_ptr<Heap> heap_;
   std::unique_ptr<DispatchTable> dispatch_table_;
@@ -832,8 +906,6 @@
     return group()->safepoint_handler();
   }
 
-  ClassTable* class_table() { return class_table_.get(); }
-
   ClassPtr* cached_class_table_table() { return cached_class_table_table_; }
   void set_cached_class_table_table(ClassPtr* cached_class_table_table) {
     cached_class_table_table_ = cached_class_table_table;
@@ -842,7 +914,6 @@
     return OFFSET_OF(Isolate, cached_class_table_table_);
   }
 
-  SharedClassTable* shared_class_table() const { return shared_class_table_; }
   // Used during isolate creation to re-register isolate with right group.
   void set_shared_class_table(SharedClassTable* table) {
     shared_class_table_ = table;
@@ -852,7 +923,6 @@
     return OFFSET_OF(Isolate, shared_class_table_);
   }
 
-  ObjectStore* object_store() const { return object_store_shared_ptr_.get(); }
   void set_object_store(ObjectStore* object_store);
   static intptr_t cached_object_store_offset() {
     return OFFSET_OF(Isolate, cached_object_store_);
@@ -929,8 +999,6 @@
 
   void SendInternalLibMessage(LibMsgId msg_id, uint64_t capability);
 
-  Heap* heap() const { return isolate_group_->heap(); }
-
   void set_init_callback_data(void* value) { init_callback_data_ = value; }
   void* init_callback_data() const { return init_callback_data_; }
 
@@ -1134,7 +1202,9 @@
   VMTagCounters* vm_tag_counters() { return &vm_tag_counters_; }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  IsolateReloadContext* reload_context() { return reload_context_; }
+  ProgramReloadContext* program_reload_context() {
+    return program_reload_context_;
+  }
 
   void DeleteReloadContext();
 
@@ -1249,12 +1319,6 @@
   void PauseEventHandler();
 #endif
 
-  void AddClosureFunction(const Function& function) const;
-  FunctionPtr LookupClosureFunction(const Function& parent,
-                                    TokenPosition token_pos) const;
-  intptr_t FindClosureIndex(const Function& needle) const;
-  FunctionPtr ClosureFunctionFromIndex(intptr_t idx) const;
-
   bool is_service_isolate() const {
     return IsServiceIsolateBit::decode(isolate_flags_);
   }
@@ -1283,13 +1347,6 @@
     isolate_flags_ = ShouldLoadVmServiceBit::update(value, isolate_flags_);
   }
 
-  Dart_QualifiedFunctionName* embedder_entry_points() const {
-    return embedder_entry_points_;
-  }
-
-  void set_obfuscation_map(const char** map) { obfuscation_map_ = map; }
-  const char** obfuscation_map() const { return obfuscation_map_; }
-
   const DispatchTable* dispatch_table() const {
     return group()->dispatch_table();
   }
@@ -1315,8 +1372,6 @@
 
 #define DECLARE_GETTER(when, name, bitname, isolate_flag_name, flag_name)      \
   bool name() const {                                                          \
-    const bool false_by_default = false;                                       \
-    USE(false_by_default);                                                     \
     return FLAG_FOR_##when(bitname##Bit::decode(isolate_flags_), flag_name);   \
   }
   BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(DECLARE_GETTER)
@@ -1325,32 +1380,6 @@
 #undef FLAG_FOR_PRODUCT
 #undef DECLARE_GETTER
 
-#if defined(PRODUCT)
-  void set_use_osr(bool use_osr) { ASSERT(!use_osr); }
-#else   // defined(PRODUCT)
-  void set_use_osr(bool use_osr) {
-    isolate_flags_ = UseOsrBit::update(use_osr, isolate_flags_);
-  }
-#endif  // defined(PRODUCT)
-
-  bool null_safety_not_set() const {
-    return !NullSafetySetBit::decode(isolate_flags_);
-  }
-
-  bool null_safety() const {
-    ASSERT(!null_safety_not_set());
-    return NullSafetyBit::decode(isolate_flags_);
-  }
-
-  void set_null_safety(bool null_safety) {
-    isolate_flags_ = NullSafetySetBit::update(true, isolate_flags_);
-    isolate_flags_ = NullSafetyBit::update(null_safety, isolate_flags_);
-  }
-
-  bool use_strict_null_safety_checks() const {
-    return null_safety() || FLAG_strict_null_safety_checks;
-  }
-
   bool has_attempted_stepping() const {
     return HasAttemptedSteppingBit::decode(isolate_flags_);
   }
@@ -1522,14 +1551,8 @@
   V(HasAttemptedReload)                                                        \
   V(HasAttemptedStepping)                                                      \
   V(ShouldPausePostServiceRequest)                                             \
-  V(EnableAsserts)                                                             \
-  V(UseFieldGuards)                                                            \
-  V(UseOsr)                                                                    \
-  V(Obfuscate)                                                                 \
   V(CopyParentCode)                                                            \
   V(ShouldLoadVmService)                                                       \
-  V(NullSafety)                                                                \
-  V(NullSafetySet)                                                             \
   V(IsSystemIsolate)
 
   // Isolate specific flags.
@@ -1583,7 +1606,7 @@
       0;  // we can only reload when this is 0.
   // Per-isolate copy of FLAG_reload_every.
   intptr_t reload_every_n_stack_overflow_checks_;
-  IsolateReloadContext* reload_context_ = nullptr;
+  ProgramReloadContext* program_reload_context_ = nullptr;
   // Ring buffer of objects assigned an id.
   ObjectIdRing* object_id_ring_ = nullptr;
 #endif  // !defined(PRODUCT)
@@ -1632,9 +1655,6 @@
   HandlerInfoCache handler_info_cache_;
   CatchEntryMovesCache catch_entry_moves_cache_;
 
-  Dart_QualifiedFunctionName* embedder_entry_points_ = nullptr;
-  const char** obfuscation_map_ = nullptr;
-
   DispatchTable* dispatch_table_ = nullptr;
 
   // Used during message sending of messages between isolates.
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 8e586b3..433af1e 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -60,6 +60,7 @@
 DECLARE_FLAG(bool, trace_deoptimization);
 
 #define I (isolate())
+#define IG (isolate_group())
 #define Z zone_
 
 #define TIMELINE_SCOPE(name)                                                   \
@@ -161,9 +162,9 @@
     }
 
     if (new_field) {
-      const Field& field = Field::Handle(to_field.raw());
+      const Field& field = Field::Handle(to_field.ptr());
       field.set_needs_load_guard(true);
-      field.set_is_unboxing_candidate(false);
+      field.set_is_unboxing_candidate_unsafe(false);
       new_fields_offsets->Add(field.HostOffset());
     }
   }
@@ -223,8 +224,8 @@
     result.SetCanonical();
   }
 #if defined(HASH_IN_OBJECT_HEADER)
-  const uint32_t hash = Object::GetCachedHash(instance.raw());
-  Object::SetCachedHash(result.raw(), hash);
+  const uint32_t hash = Object::GetCachedHash(instance.ptr());
+  Object::SetCachedHash(result.ptr(), hash);
 #endif
 
   // Morph the context from instance to result using mapping_.
@@ -245,7 +246,7 @@
 
   // Convert the instance into a filler object.
   Become::MakeDummyObject(instance);
-  return result.raw();
+  return result.ptr();
 }
 
 void InstanceMorpher::CreateMorphedCopies() {
@@ -304,8 +305,8 @@
                                                    const Class& from,
                                                    const Class& to)
     : ReasonForCancelling(zone),
-      from_(Class::ZoneHandle(zone, from.raw())),
-      to_(Class::ZoneHandle(zone, to.raw())) {}
+      from_(Class::ZoneHandle(zone, from.ptr())),
+      to_(Class::ZoneHandle(zone, to.ptr())) {}
 
 void ClassReasonForCancelling::AppendTo(JSONArray* array) {
   JSONObject jsobj(array);
@@ -346,7 +347,7 @@
     if (!a.IsClass() || !b.IsClass()) {
       return false;
     }
-    return IsolateReloadContext::IsSameClass(Class::Cast(a), Class::Cast(b));
+    return ProgramReloadContext::IsSameClass(Class::Cast(a), Class::Cast(b));
   }
 
   static uword Hash(const Object& obj) {
@@ -371,7 +372,7 @@
     if (!a.IsLibrary() || !b.IsLibrary()) {
       return false;
     }
-    return IsolateReloadContext::IsSameLibrary(Library::Cast(a),
+    return ProgramReloadContext::IsSameLibrary(Library::Cast(a),
                                                Library::Cast(b));
   }
 
@@ -384,7 +385,7 @@
   static const char* Name() { return "BecomeMapTraits"; }
 
   static bool IsMatch(const Object& a, const Object& b) {
-    return a.raw() == b.raw();
+    return a.ptr() == b.ptr();
   }
 
   static uword Hash(const Object& obj) {
@@ -397,6 +398,8 @@
     } else if (obj.IsClosure()) {
       return String::HashRawSymbol(
           Function::Handle(Closure::Cast(obj).function()).name());
+    } else if (obj.IsLibraryPrefix()) {
+      return String::HashRawSymbol(LibraryPrefix::Cast(obj).name());
     } else {
       FATAL1("Unexpected type in become: %s\n", obj.ToCString());
     }
@@ -404,7 +407,7 @@
   }
 };
 
-bool IsolateReloadContext::IsSameClass(const Class& a, const Class& b) {
+bool ProgramReloadContext::IsSameClass(const Class& a, const Class& b) {
   // TODO(turnidge): We need to look at generic type arguments for
   // synthetic mixin classes.  Their names are not necessarily unique
   // currently.
@@ -419,12 +422,12 @@
   const Library& b_lib = Library::Handle(b.library());
 
   if (a_lib.IsNull() || b_lib.IsNull()) {
-    return a_lib.raw() == b_lib.raw();
+    return a_lib.ptr() == b_lib.ptr();
   }
   return (a_lib.private_key() == b_lib.private_key());
 }
 
-bool IsolateReloadContext::IsSameLibrary(const Library& a_lib,
+bool ProgramReloadContext::IsSameLibrary(const Library& a_lib,
                                          const Library& b_lib) {
   const String& a_lib_url =
       String::Handle(a_lib.IsNull() ? String::null() : a_lib.url());
@@ -452,7 +455,7 @@
       old_root_url_prefix_(String::null()) {}
 IsolateGroupReloadContext::~IsolateGroupReloadContext() {}
 
-IsolateReloadContext::IsolateReloadContext(
+ProgramReloadContext::ProgramReloadContext(
     std::shared_ptr<IsolateGroupReloadContext> group_reload_context,
     Isolate* isolate)
     : zone_(Thread::Current()->zone()),
@@ -469,13 +472,13 @@
       become_enum_mappings_(GrowableObjectArray::null()),
       saved_root_library_(Library::null()),
       saved_libraries_(GrowableObjectArray::null()) {
-  // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not
+  // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The ProgramReloadContext is not
   // associated with the isolate yet and if a GC is triggered here the raw
   // objects will not be properly accounted for.
   ASSERT(zone_ != NULL);
 }
 
-IsolateReloadContext::~IsolateReloadContext() {
+ProgramReloadContext::~ProgramReloadContext() {
   ASSERT(zone_ == Thread::Current()->zone());
   ASSERT(saved_class_table_.load(std::memory_order_relaxed) == nullptr);
   ASSERT(saved_tlc_class_table_.load(std::memory_order_relaxed) == nullptr);
@@ -509,12 +512,12 @@
  public:
   Aborted(Zone* zone, const Error& error)
       : ReasonForCancelling(zone),
-        error_(Error::ZoneHandle(zone, error.raw())) {}
+        error_(Error::ZoneHandle(zone, error.ptr())) {}
 
  private:
   const Error& error_;
 
-  ErrorPtr ToError() { return error_.raw(); }
+  ErrorPtr ToError() { return error_.ptr(); }
   StringPtr ToString() {
     return String::NewFormatted("%s", error_.ToErrorCString());
   }
@@ -559,21 +562,14 @@
 
   Thread* thread = Thread::Current();
 
-  // All isolates have the same sources, so all of them have the same libraries.
-  // We use the [first_isolate_] here to determine which of libraries have
-  // changed.
-  ASSERT(first_isolate_ == nullptr);
-  first_isolate_ = thread->isolate();
-
   // All isolates within an isolate group need to share one heap.
   // TODO(dartbug.com/36097): Remove this assert once the shared heap CL has
   // landed.
   RELEASE_ASSERT(!FLAG_enable_isolate_groups);
-  Heap* heap = first_isolate_->heap();
+  Heap* heap = IG->heap();
 
-  num_old_libs_ = GrowableObjectArray::Handle(
-                      Z, first_isolate_->object_store()->libraries())
-                      .Length();
+  num_old_libs_ =
+      GrowableObjectArray::Handle(Z, IG->object_store()->libraries()).Length();
 
   // Grab root library before calling CheckpointBeforeReload.
   GetRootLibUrl(root_script_url);
@@ -626,13 +622,13 @@
     }
 
     ExternalTypedData& external_typed_data =
-        ExternalTypedData::Handle(Z, kernel_program.get()->typed_data()->raw());
+        ExternalTypedData::Handle(Z, kernel_program.get()->typed_data()->ptr());
     IsolateGroupSource* source = Isolate::Current()->source();
     source->add_loaded_blob(Z, external_typed_data);
 
     modified_libs_ = new (Z) BitVector(Z, num_old_libs_);
     kernel::KernelLoader::FindModifiedLibraries(
-        kernel_program.get(), first_isolate_, modified_libs_, force_reload,
+        kernel_program.get(), isolate_group_, modified_libs_, force_reload,
         &skip_reload, p_num_received_classes, p_num_received_procedures);
     modified_libs_transitive_ = new (Z) BitVector(Z, num_old_libs_);
     BuildModifiedLibrariesClosure(modified_libs_);
@@ -688,9 +684,10 @@
   // TODO(johnmccutchan): Deoptimizing dependent code here (before the reload)
   // is paranoid. This likely can be moved to the commit phase.
   ForEachIsolate([&](Isolate* isolate) {
-    isolate->reload_context()->EnsuredUnoptimizedCodeForStack();
-    isolate->reload_context()->DeoptimizeDependentCode();
-    isolate->reload_context()->ReloadPhase1AllocateStorageMapsAndCheckpoint();
+    isolate->program_reload_context()->EnsuredUnoptimizedCodeForStack();
+    isolate->program_reload_context()->DeoptimizeDependentCode();
+    isolate->program_reload_context()
+        ->ReloadPhase1AllocateStorageMapsAndCheckpoint();
   });
   // Renumbering the libraries has invalidated this.
   modified_libs_ = nullptr;
@@ -708,7 +705,7 @@
     TIMELINE_SCOPE(CheckpointClasses);
     CheckpointSharedClassTable();
     ForEachIsolate([&](Isolate* isolate) {
-      isolate->reload_context()->CheckpointClasses();
+      isolate->program_reload_context()->CheckpointClasses();
     });
   }
 
@@ -730,7 +727,7 @@
 
   auto& tmp = Object::Handle(Z);
   ForEachIsolate([&](Isolate* isolate) {
-    tmp = isolate->reload_context()->ReloadPhase2LoadKernel(
+    tmp = isolate->program_reload_context()->ReloadPhase2LoadKernel(
         kernel_program.get(), root_lib_url_);
     if (tmp.IsError()) {
       results.SetAt(isolateIndex, tmp);
@@ -749,7 +746,7 @@
 
     DiscardSavedClassTable(/*is_rollback=*/true);
     ForEachIsolate([&](Isolate* isolate) {
-      isolate->reload_context()->ReloadPhase4Rollback();
+      isolate->program_reload_context()->ReloadPhase4Rollback();
     });
     CommonFinalizeTail(num_old_libs_);
   } else {
@@ -757,7 +754,7 @@
     TIR_Print("---- LOAD SUCCEEDED\n");
 
     ForEachIsolate([&](Isolate* isolate) {
-      isolate->reload_context()->ReloadPhase3FinalizeLoading();
+      isolate->program_reload_context()->ReloadPhase3FinalizeLoading();
     });
 
     if (FLAG_gc_during_reload) {
@@ -770,7 +767,7 @@
     if (!FLAG_reload_force_rollback && !HasReasonsForCancelling()) {
       TIR_Print("---- COMMITTING RELOAD\n");
       ForEachIsolate([&](Isolate* isolate) {
-        isolate->reload_context()->ReloadPhase4CommitPrepare();
+        isolate->program_reload_context()->ReloadPhase4CommitPrepare();
       });
       bool discard_class_tables = true;
       if (HasInstanceMorphers()) {
@@ -819,7 +816,7 @@
             // commit to the changed class table and deleted the saved one.
             DiscardSavedClassTable(/*is_rollback=*/false);
             ForEachIsolate([&](Isolate* isolate) {
-              isolate->reload_context()->DiscardSavedClassTable(
+              isolate->program_reload_context()->DiscardSavedClassTable(
                   /*is_rollback=*/false);
             });
           }
@@ -838,12 +835,12 @@
       if (discard_class_tables) {
         DiscardSavedClassTable(/*is_rollback=*/false);
         ForEachIsolate([&](Isolate* isolate) {
-          isolate->reload_context()->DiscardSavedClassTable(
+          isolate->program_reload_context()->DiscardSavedClassTable(
               /*is_rollback=*/false);
         });
       }
       ForEachIsolate([&](Isolate* isolate) {
-        isolate->reload_context()->ReloadPhase4CommitFinish();
+        isolate->program_reload_context()->ReloadPhase4CommitFinish();
       });
       TIR_Print("---- DONE COMMIT\n");
       isolate_group_->set_last_reload_timestamp(reload_timestamp_);
@@ -851,7 +848,7 @@
       TIR_Print("---- ROLLING BACK");
       DiscardSavedClassTable(/*is_rollback=*/true);
       ForEachIsolate([&](Isolate* isolate) {
-        isolate->reload_context()->ReloadPhase4Rollback();
+        isolate->program_reload_context()->ReloadPhase4Rollback();
       });
     }
 
@@ -859,15 +856,13 @@
     // not remove dead subclasses.  Rebuild the direct subclass
     // information from scratch.
     {
-      SafepointWriteRwLocker ml(thread,
-                                thread->isolate_group()->program_lock());
+      SafepointWriteRwLocker ml(thread, IG->program_lock());
       ForEachIsolate([&](Isolate* isolate) {
-        isolate->reload_context()->RebuildDirectSubclasses();
+        isolate->program_reload_context()->RebuildDirectSubclasses();
       });
     }
     const intptr_t final_library_count =
-        GrowableObjectArray::Handle(Z,
-                                    first_isolate_->object_store()->libraries())
+        GrowableObjectArray::Handle(Z, IG->object_store()->libraries())
             .Length();
     CommonFinalizeTail(final_library_count);
 
@@ -932,7 +927,7 @@
 void IsolateGroupReloadContext::BuildModifiedLibrariesClosure(
     BitVector* modified_libs) {
   const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(first_isolate_->object_store()->libraries());
+      GrowableObjectArray::Handle(IG->object_store()->libraries());
   Library& lib = Library::Handle();
   intptr_t num_libs = libs.Length();
 
@@ -986,7 +981,7 @@
     while (entries.HasNext()) {
       entry = entries.GetNext();
       if (entry.IsLibraryPrefix()) {
-        prefix ^= entry.raw();
+        prefix ^= entry.ptr();
         ports = prefix.imports();
         for (intptr_t import_idx = 0; import_idx < ports.Length();
              import_idx++) {
@@ -1017,7 +1012,7 @@
 
 void IsolateGroupReloadContext::GetRootLibUrl(const char* root_script_url) {
   const auto& old_root_lib =
-      Library::Handle(first_isolate_->object_store()->root_library());
+      Library::Handle(IG->object_store()->root_library());
   ASSERT(!old_root_lib.IsNull());
   const auto& old_root_lib_url = String::Handle(old_root_lib.url());
 
@@ -1025,7 +1020,7 @@
   if (root_script_url != nullptr) {
     root_lib_url_ = String::New(root_script_url);
   } else {
-    root_lib_url_ = old_root_lib_url.raw();
+    root_lib_url_ = old_root_lib_url.ptr();
   }
 
   // Check to see if the base url of the loaded libraries has moved.
@@ -1055,9 +1050,9 @@
   {
     const char* root_lib_url = root_lib_url_.ToCString();
     TransitionVMToNative transition(Thread::Current());
-    retval = KernelIsolate::CompileToKernel(root_lib_url, nullptr, 0,
-                                            modified_scripts_count,
-                                            modified_scripts, true, nullptr);
+    retval = KernelIsolate::CompileToKernel(
+        root_lib_url, nullptr, 0, modified_scripts_count, modified_scripts,
+        true, false, nullptr);
   }
   if (retval.status != Dart_KernelCompilationStatus_Ok) {
     if (retval.kernel != nullptr) {
@@ -1070,7 +1065,7 @@
   return nullptr;
 }
 
-void IsolateReloadContext::ReloadPhase1AllocateStorageMapsAndCheckpoint() {
+void ProgramReloadContext::ReloadPhase1AllocateStorageMapsAndCheckpoint() {
   // Preallocate storage for maps.
   old_classes_set_storage_ =
       HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
@@ -1095,7 +1090,7 @@
   }
 }
 
-ObjectPtr IsolateReloadContext::ReloadPhase2LoadKernel(
+ObjectPtr ProgramReloadContext::ReloadPhase2LoadKernel(
     kernel::Program* program,
     const String& root_lib_url) {
   Thread* thread = Thread::Current();
@@ -1104,50 +1099,50 @@
   if (setjmp(*jump.Set()) == 0) {
     const Object& tmp = kernel::KernelLoader::LoadEntireProgram(program);
     if (tmp.IsError()) {
-      return tmp.raw();
+      return tmp.ptr();
     }
 
     // If main method disappeared or were not there to begin with then
     // KernelLoader will return null. In this case lookup library by
     // URL.
-    auto& lib = Library::Handle(Library::RawCast(tmp.raw()));
+    auto& lib = Library::Handle(Library::RawCast(tmp.ptr()));
     if (lib.IsNull()) {
       lib = Library::LookupLibrary(thread, root_lib_url);
     }
-    isolate_->object_store()->set_root_library(lib);
+    isolate_->group()->object_store()->set_root_library(lib);
     return Object::null();
   } else {
     return thread->StealStickyError();
   }
 }
 
-void IsolateReloadContext::ReloadPhase3FinalizeLoading() {
+void ProgramReloadContext::ReloadPhase3FinalizeLoading() {
   BuildLibraryMapping();
   BuildRemovedClassesSet();
   ValidateReload();
 }
 
-void IsolateReloadContext::ReloadPhase4CommitPrepare() {
+void ProgramReloadContext::ReloadPhase4CommitPrepare() {
   CommitBeforeInstanceMorphing();
 }
 
-void IsolateReloadContext::ReloadPhase4CommitFinish() {
+void ProgramReloadContext::ReloadPhase4CommitFinish() {
   CommitAfterInstanceMorphing();
   PostCommit();
 }
 
-void IsolateReloadContext::ReloadPhase4Rollback() {
+void ProgramReloadContext::ReloadPhase4Rollback() {
   RollbackClasses();
   RollbackLibraries();
 }
 
-void IsolateReloadContext::RegisterClass(const Class& new_cls) {
+void ProgramReloadContext::RegisterClass(const Class& new_cls) {
   const Class& old_cls = Class::Handle(OldClassOrNull(new_cls));
   if (old_cls.IsNull()) {
     if (new_cls.IsTopLevel()) {
-      I->class_table()->RegisterTopLevel(new_cls);
+      IG->class_table()->RegisterTopLevel(new_cls);
     } else {
-      I->class_table()->Register(new_cls);
+      IG->class_table()->Register(new_cls);
     }
 
     if (FLAG_identity_reload) {
@@ -1162,7 +1157,7 @@
   }
   VTIR_Print("Registering class: %s\n", new_cls.ToCString());
   new_cls.set_id(old_cls.id());
-  I->class_table()->SetAt(old_cls.id(), new_cls.raw());
+  IG->class_table()->SetAt(old_cls.id(), new_cls.ptr());
   if (!old_cls.is_enum_class()) {
     new_cls.CopyCanonicalConstants(old_cls);
   }
@@ -1218,7 +1213,7 @@
   }
 }
 
-void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() {
+void ProgramReloadContext::EnsuredUnoptimizedCodeForStack() {
   TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack);
   StackFrameIterator it(ValidationPolicy::kDontValidateFrames,
                         Thread::Current(),
@@ -1239,17 +1234,17 @@
   }
 }
 
-void IsolateReloadContext::DeoptimizeDependentCode() {
+void ProgramReloadContext::DeoptimizeDependentCode() {
   TIMELINE_SCOPE(DeoptimizeDependentCode);
-  ClassTable* class_table = I->class_table();
+  ClassTable* class_table = IG->class_table();
 
-  const intptr_t bottom = Dart::vm_isolate()->class_table()->NumCids();
-  const intptr_t top = I->class_table()->NumCids();
+  const intptr_t bottom = Dart::vm_isolate_group()->class_table()->NumCids();
+  const intptr_t top = IG->class_table()->NumCids();
   Class& cls = Class::Handle();
   Array& fields = Array::Handle();
   Field& field = Field::Handle();
   Thread* thread = Thread::Current();
-  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  SafepointWriteRwLocker ml(thread, IG->program_lock());
   for (intptr_t cls_idx = bottom; cls_idx < top; cls_idx++) {
     if (!class_table->HasValidClassAt(cls_idx)) {
       // Skip.
@@ -1299,7 +1294,7 @@
   shared_class_table_->ResetBeforeHotReload();
 }
 
-void IsolateReloadContext::CheckpointClasses() {
+void ProgramReloadContext::CheckpointClasses() {
   TIR_Print("---- CHECKPOINTING CLASSES\n");
   // Checkpoint classes before a reload. We need to copy the following:
   // 1) The size of the class table.
@@ -1308,7 +1303,7 @@
   // is used to pair new classes with old classes.
 
   // Copy the class table for isolate.
-  ClassTable* class_table = I->class_table();
+  ClassTable* class_table = IG->class_table();
   ClassPtr* saved_class_table = nullptr;
   ClassPtr* saved_tlc_class_table = nullptr;
   class_table->CopyBeforeHotReload(&saved_class_table, &saved_tlc_class_table,
@@ -1351,7 +1346,7 @@
       ASSERT(!already_present);
     }
   }
-  old_classes_set_storage_ = old_classes_set.Release().raw();
+  old_classes_set_storage_ = old_classes_set.Release().ptr();
   TIR_Print("---- System had %" Pd " classes\n", saved_num_cids_);
 }
 
@@ -1392,7 +1387,7 @@
   const int64_t last_reload = isolate_group_->last_reload_timestamp();
   GrowableArray<const char*> modified_sources_uris;
   const auto& libs =
-      GrowableObjectArray::Handle(first_isolate_->object_store()->libraries());
+      GrowableObjectArray::Handle(IG->object_store()->libraries());
   Library& lib = Library::Handle(Z);
   Array& scripts = Array::Handle(Z);
   Script& script = Script::Handle(Z);
@@ -1448,17 +1443,17 @@
   }
 }
 
-void IsolateReloadContext::CheckpointLibraries() {
+void ProgramReloadContext::CheckpointLibraries() {
   TIMELINE_SCOPE(CheckpointLibraries);
   TIR_Print("---- CHECKPOINTING LIBRARIES\n");
   // Save the root library in case we abort the reload.
   const Library& root_lib = Library::Handle(object_store()->root_library());
-  saved_root_library_ = root_lib.raw();
+  saved_root_library_ = root_lib.ptr();
 
   // Save the old libraries array in case we abort the reload.
   const GrowableObjectArray& libs =
       GrowableObjectArray::Handle(object_store()->libraries());
-  saved_libraries_ = libs.raw();
+  saved_libraries_ = libs.ptr();
 
   // Make a filtered copy of the old libraries array. Keep "clean" libraries
   // that we will use instead of reloading.
@@ -1489,7 +1484,7 @@
     bool already_present = old_libraries_set.Insert(lib);
     ASSERT(!already_present);
   }
-  old_libraries_set_storage_ = old_libraries_set.Release().raw();
+  old_libraries_set_storage_ = old_libraries_set.Release().ptr();
 
   // Reset the registered libraries to the filtered array.
   Library::RegisterLibraries(Thread::Current(), new_libs);
@@ -1497,7 +1492,7 @@
   object_store()->set_root_library(Library::Handle());
 }
 
-void IsolateReloadContext::RollbackClasses() {
+void ProgramReloadContext::RollbackClasses() {
   TIR_Print("---- ROLLING BACK CLASS TABLE\n");
   ASSERT((saved_num_cids_ + saved_num_tlc_cids_) > 0);
   ASSERT(saved_class_table_.load(std::memory_order_relaxed) != nullptr);
@@ -1506,7 +1501,7 @@
   DiscardSavedClassTable(/*is_rollback=*/true);
 }
 
-void IsolateReloadContext::RollbackLibraries() {
+void ProgramReloadContext::RollbackLibraries() {
   TIR_Print("---- ROLLING BACK LIBRARY CHANGES\n");
   Thread* thread = Thread::Current();
   Library& lib = Library::Handle();
@@ -1532,7 +1527,7 @@
 }
 
 #ifdef DEBUG
-void IsolateReloadContext::VerifyMaps() {
+void ProgramReloadContext::VerifyMaps() {
   TIMELINE_SCOPE(VerifyMaps);
   Class& cls = Class::Handle();
   Class& new_cls = Class::Handle();
@@ -1567,7 +1562,7 @@
 }
 #endif
 
-void IsolateReloadContext::CommitBeforeInstanceMorphing() {
+void ProgramReloadContext::CommitBeforeInstanceMorphing() {
   TIMELINE_SCOPE(Commit);
 
 #ifdef DEBUG
@@ -1619,7 +1614,7 @@
         const intptr_t entry = it.Current();
         new_cls = Class::RawCast(class_map.GetKey(entry));
         old_cls = Class::RawCast(class_map.GetPayload(entry, 0));
-        if (new_cls.raw() != old_cls.raw()) {
+        if (new_cls.ptr() != old_cls.ptr()) {
           ASSERT(new_cls.is_enum_class() == old_cls.is_enum_class());
           if (new_cls.is_enum_class() && new_cls.is_finalized()) {
             new_cls.ReplaceEnum(this, old_cls);
@@ -1652,7 +1647,7 @@
     // Update the libraries array.
     Library& lib = Library::Handle();
     const GrowableObjectArray& libs =
-        GrowableObjectArray::Handle(I->object_store()->libraries());
+        GrowableObjectArray::Handle(IG->object_store()->libraries());
     for (intptr_t i = 0; i < libs.Length(); i++) {
       lib = Library::RawCast(libs.At(i));
       VTIR_Print("Lib '%s' at index %" Pd "\n", lib.ToCString(), i);
@@ -1672,7 +1667,7 @@
   }
 }
 
-void IsolateReloadContext::CommitAfterInstanceMorphing() {
+void ProgramReloadContext::CommitAfterInstanceMorphing() {
   {
     const GrowableObjectArray& become_enum_mappings =
         GrowableObjectArray::Handle(become_enum_mappings_);
@@ -1719,17 +1714,17 @@
 #endif
 
   if (FLAG_identity_reload) {
-    if (saved_num_cids_ != I->class_table()->NumCids()) {
+    if (saved_num_cids_ != IG->class_table()->NumCids()) {
       TIR_Print("Identity reload failed! B#C=%" Pd " A#C=%" Pd "\n",
-                saved_num_cids_, I->class_table()->NumCids());
+                saved_num_cids_, IG->class_table()->NumCids());
     }
-    if (saved_num_tlc_cids_ != I->class_table()->NumTopLevelCids()) {
+    if (saved_num_tlc_cids_ != IG->class_table()->NumTopLevelCids()) {
       TIR_Print("Identity reload failed! B#TLC=%" Pd " A#TLC=%" Pd "\n",
-                saved_num_tlc_cids_, I->class_table()->NumTopLevelCids());
+                saved_num_tlc_cids_, IG->class_table()->NumTopLevelCids());
     }
     const auto& saved_libs = GrowableObjectArray::Handle(saved_libraries_);
     const GrowableObjectArray& libs =
-        GrowableObjectArray::Handle(I->object_store()->libraries());
+        GrowableObjectArray::Handle(IG->object_store()->libraries());
     if (saved_libs.Length() != libs.Length()) {
       TIR_Print("Identity reload failed! B#L=%" Pd " A#L=%" Pd "\n",
                 saved_libs.Length(), libs.Length());
@@ -1737,7 +1732,7 @@
   }
 }
 
-bool IsolateReloadContext::IsDirty(const Library& lib) {
+bool ProgramReloadContext::IsDirty(const Library& lib) {
   const intptr_t index = lib.index();
   if (index == static_cast<classid_t>(-1)) {
     // Treat deleted libraries as dirty.
@@ -1747,7 +1742,7 @@
   return library_infos_[index].dirty;
 }
 
-void IsolateReloadContext::PostCommit() {
+void ProgramReloadContext::PostCommit() {
   TIMELINE_SCOPE(PostCommit);
   saved_root_library_ = Library::null();
   saved_libraries_ = GrowableObjectArray::null();
@@ -1828,7 +1823,7 @@
   isolate_group_->ForEachIsolate(callback);
 }
 
-void IsolateReloadContext::ValidateReload() {
+void ProgramReloadContext::ValidateReload() {
   TIMELINE_SCOPE(ValidateReload);
 
   TIR_Print("---- VALIDATING RELOAD\n");
@@ -1844,7 +1839,7 @@
       const intptr_t entry = it.Current();
       new_lib = Library::RawCast(map.GetKey(entry));
       lib = Library::RawCast(map.GetPayload(entry, 0));
-      if (new_lib.raw() != lib.raw()) {
+      if (new_lib.ptr() != lib.ptr()) {
         lib.CheckReload(new_lib, this);
       }
     }
@@ -1862,7 +1857,7 @@
       const intptr_t entry = it.Current();
       new_cls = Class::RawCast(map.GetKey(entry));
       cls = Class::RawCast(map.GetPayload(entry, 0));
-      if (new_cls.raw() != cls.raw()) {
+      if (new_cls.ptr() != cls.ptr()) {
         cls.CheckReload(new_cls, this);
       }
     }
@@ -1870,7 +1865,7 @@
   }
 }
 
-ClassPtr IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) {
+ClassPtr ProgramReloadContext::GetClassForHeapWalkAt(intptr_t cid) {
   ClassPtr* class_table = nullptr;
   intptr_t index = -1;
   if (ClassTable::IsTopLevelCid(cid)) {
@@ -1885,7 +1880,7 @@
   if (class_table != nullptr) {
     return class_table[index];
   }
-  return isolate_->class_table()->At(cid);
+  return IG->class_table()->At(cid);
 }
 
 intptr_t IsolateGroupReloadContext::GetClassSizeForHeapWalkAt(classid_t cid) {
@@ -1901,12 +1896,12 @@
   }
 }
 
-void IsolateReloadContext::DiscardSavedClassTable(bool is_rollback) {
+void ProgramReloadContext::DiscardSavedClassTable(bool is_rollback) {
   ClassPtr* local_saved_class_table =
       saved_class_table_.load(std::memory_order_relaxed);
   ClassPtr* local_saved_tlc_class_table =
       saved_tlc_class_table_.load(std::memory_order_relaxed);
-  I->class_table()->ResetAfterHotReload(
+  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);
@@ -1925,7 +1920,7 @@
   visitor->VisitPointers(from(), to());
 }
 
-void IsolateReloadContext::VisitObjectPointers(ObjectPointerVisitor* visitor) {
+void ProgramReloadContext::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointers(from(), to());
 
   ClassPtr* saved_class_table =
@@ -1943,11 +1938,11 @@
   }
 }
 
-ObjectStore* IsolateReloadContext::object_store() {
-  return isolate_->object_store();
+ObjectStore* ProgramReloadContext::object_store() {
+  return isolate_->group()->object_store();
 }
 
-void IsolateReloadContext::ResetUnoptimizedICsOnStack() {
+void ProgramReloadContext::ResetUnoptimizedICsOnStack() {
   Thread* thread = Thread::Current();
   StackZone stack_zone(thread);
   Zone* zone = stack_zone.GetZone();
@@ -1977,7 +1972,7 @@
   }
 }
 
-void IsolateReloadContext::ResetMegamorphicCaches() {
+void ProgramReloadContext::ResetMegamorphicCaches() {
   object_store()->set_megamorphic_cache_table(GrowableObjectArray::Handle());
   // Since any current optimized code will not make any more calls, it may be
   // better to clear the table instead of clearing each of the caches, allow
@@ -2028,7 +2023,7 @@
 
 typedef UnorderedHashMap<SmiTraits> IntHashMap;
 
-void IsolateReloadContext::RunInvalidationVisitors() {
+void ProgramReloadContext::RunInvalidationVisitors() {
   TIR_Print("---- RUNNING INVALIDATION HEAP VISITORS\n");
   Thread* thread = Thread::Current();
   StackZone stack_zone(thread);
@@ -2051,7 +2046,7 @@
   InvalidateFields(zone, fields, instances);
 }
 
-void IsolateReloadContext::InvalidateKernelInfos(
+void ProgramReloadContext::InvalidateKernelInfos(
     Zone* zone,
     const GrowableArray<const KernelProgramInfo*>& kernel_infos) {
   TIMELINE_SCOPE(InvalidateKernelInfos);
@@ -2081,22 +2076,21 @@
   }
 }
 
-void IsolateReloadContext::InvalidateFunctions(
+void ProgramReloadContext::InvalidateFunctions(
     Zone* zone,
     const GrowableArray<const Function*>& functions) {
   TIMELINE_SCOPE(InvalidateFunctions);
-  HANDLESCOPE(Thread::Current());
+  auto thread = Thread::Current();
+  HANDLESCOPE(thread);
 
   CallSiteResetter resetter(zone);
 
   Class& owning_class = Class::Handle(zone);
   Library& owning_lib = Library::Handle(zone);
   Code& code = Code::Handle(zone);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   for (intptr_t i = 0; i < functions.length(); i++) {
     const Function& func = *functions[i];
-    if (func.IsSignatureFunction()) {
-      continue;
-    }
 
     // Switch to unoptimized code or the lazy compilation stub.
     func.SwitchToLazyCompiledUnoptimizedCode();
@@ -2161,8 +2155,7 @@
 
   void CheckStatics(const GrowableArray<const Field*>& fields) {
     Thread* thread = Thread::Current();
-    Isolate* isolate = thread->isolate();
-    bool null_safety = isolate->null_safety();
+    const bool null_safety = thread->isolate_group()->null_safety();
     HANDLESCOPE(thread);
     instantiator_type_arguments_ = TypeArguments::null();
     for (intptr_t i = 0; i < fields.length(); i++) {
@@ -2174,7 +2167,7 @@
         continue;  // Already guarding.
       }
       value_ = field.StaticValue();
-      if (value_.raw() != Object::sentinel().raw()) {
+      if (value_.ptr() != Object::sentinel().ptr()) {
         CheckValueType(null_safety, value_, field);
       }
     }
@@ -2182,8 +2175,7 @@
 
   void CheckInstances(const GrowableArray<const Instance*>& instances) {
     Thread* thread = Thread::Current();
-    Isolate* isolate = thread->isolate();
-    bool null_safety = isolate->null_safety();
+    const bool null_safety = thread->isolate_group()->null_safety();
     HANDLESCOPE(thread);
     for (intptr_t i = 0; i < instances.length(); i++) {
       CheckInstance(null_safety, *instances[i]);
@@ -2218,7 +2210,7 @@
       return;  // Already guarding.
     }
     value_ ^= instance.GetField(field);
-    if (value_.raw() == Object::sentinel().raw()) {
+    if (value_.ptr() == Object::sentinel().ptr()) {
       if (field.is_late()) {
         // Late fields already have lazy initialization logic.
         return;
@@ -2275,24 +2267,24 @@
     for (intptr_t i = 0; entries_.At(i) != Object::null();
          i += SubtypeTestCache::kTestEntryLength) {
       if ((entries_.At(i + SubtypeTestCache::kInstanceClassIdOrFunction) ==
-           instance_cid_or_function_.raw()) &&
+           instance_cid_or_function_.ptr()) &&
           (entries_.At(i + SubtypeTestCache::kDestinationType) ==
-           type_.raw()) &&
+           type_.ptr()) &&
           (entries_.At(i + SubtypeTestCache::kInstanceTypeArguments) ==
-           instance_type_arguments_.raw()) &&
+           instance_type_arguments_.ptr()) &&
           (entries_.At(i + SubtypeTestCache::kInstantiatorTypeArguments) ==
-           instantiator_type_arguments_.raw()) &&
+           instantiator_type_arguments_.ptr()) &&
           (entries_.At(i + SubtypeTestCache::kFunctionTypeArguments) ==
-           function_type_arguments_.raw()) &&
+           function_type_arguments_.ptr()) &&
           (entries_.At(
                i + SubtypeTestCache::kInstanceParentFunctionTypeArguments) ==
-           parent_function_type_arguments_.raw()) &&
+           parent_function_type_arguments_.ptr()) &&
           (entries_.At(
                i + SubtypeTestCache::kInstanceDelayedFunctionTypeArguments) ==
-           delayed_function_type_arguments_.raw())) {
+           delayed_function_type_arguments_.ptr())) {
         cache_hit = true;
         if (entries_.At(i + SubtypeTestCache::kTestResult) !=
-            Bool::True().raw()) {
+            Bool::True().ptr()) {
           ASSERT(!FLAG_identity_reload);
           field.set_needs_load_guard(true);
         }
@@ -2330,18 +2322,18 @@
   TypeArguments& delayed_function_type_arguments_;
 };
 
-void IsolateReloadContext::InvalidateFields(
+void ProgramReloadContext::InvalidateFields(
     Zone* zone,
     const GrowableArray<const Field*>& fields,
     const GrowableArray<const Instance*>& instances) {
   TIMELINE_SCOPE(InvalidateFields);
-  SafepointMutexLocker ml(isolate()->group()->subtype_test_cache_mutex());
+  SafepointMutexLocker ml(IG->subtype_test_cache_mutex());
   FieldInvalidator invalidator(zone);
   invalidator.CheckStatics(fields);
   invalidator.CheckInstances(instances);
 }
 
-void IsolateReloadContext::InvalidateWorld() {
+void ProgramReloadContext::InvalidateWorld() {
   TIMELINE_SCOPE(InvalidateWorld);
   TIR_Print("---- INVALIDATING WORLD\n");
   ResetMegamorphicCaches();
@@ -2353,15 +2345,15 @@
   RunInvalidationVisitors();
 }
 
-ClassPtr IsolateReloadContext::OldClassOrNull(const Class& replacement_or_new) {
+ClassPtr ProgramReloadContext::OldClassOrNull(const Class& replacement_or_new) {
   UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_);
   Class& cls = Class::Handle();
   cls ^= old_classes_set.GetOrNull(replacement_or_new);
-  old_classes_set_storage_ = old_classes_set.Release().raw();
-  return cls.raw();
+  old_classes_set_storage_ = old_classes_set.Release().ptr();
+  return cls.ptr();
 }
 
-StringPtr IsolateReloadContext::FindLibraryPrivateKey(
+StringPtr ProgramReloadContext::FindLibraryPrivateKey(
     const Library& replacement_or_new) {
   const Library& old = Library::Handle(OldLibraryOrNull(replacement_or_new));
   if (old.IsNull()) {
@@ -2375,7 +2367,7 @@
   return old.private_key();
 }
 
-LibraryPtr IsolateReloadContext::OldLibraryOrNull(
+LibraryPtr ProgramReloadContext::OldLibraryOrNull(
     const Library& replacement_or_new) {
   UnorderedHashSet<LibraryMapTraits> old_libraries_set(
       old_libraries_set_storage_);
@@ -2388,12 +2380,12 @@
       (group_reload_context_->old_root_url_prefix_ != String::null())) {
     return OldLibraryOrNullBaseMoved(replacement_or_new);
   }
-  return lib.raw();
+  return lib.ptr();
 }
 
 // Attempt to find the pair to |replacement_or_new| with the knowledge that
 // the base url prefix has moved.
-LibraryPtr IsolateReloadContext::OldLibraryOrNullBaseMoved(
+LibraryPtr ProgramReloadContext::OldLibraryOrNullBaseMoved(
     const Library& replacement_or_new) {
   const String& url_prefix =
       String::Handle(group_reload_context_->root_url_prefix_);
@@ -2425,13 +2417,13 @@
     if (old_suffix.Equals(suffix)) {
       TIR_Print("`%s` is moving to `%s`\n", old_url.ToCString(),
                 new_url.ToCString());
-      return old.raw();
+      return old.ptr();
     }
   }
   return Library::null();
 }
 
-void IsolateReloadContext::BuildLibraryMapping() {
+void ProgramReloadContext::BuildLibraryMapping() {
   const GrowableObjectArray& libs =
       GrowableObjectArray::Handle(object_store()->libraries());
 
@@ -2467,7 +2459,7 @@
 //
 // Note that all such classes must belong to a library that has either been
 // changed or removed.
-void IsolateReloadContext::BuildRemovedClassesSet() {
+void ProgramReloadContext::BuildRemovedClassesSet() {
   // Find all old classes [mapped_old_classes_set].
   UnorderedHashMap<ClassMapTraits> class_map(class_map_storage_);
   UnorderedHashSet<ClassMapTraits> mapped_old_classes_set(
@@ -2499,7 +2491,7 @@
       const intptr_t entry = it_library.Current();
       new_library ^= library_map.GetKey(entry);
       old_library ^= library_map.GetPayload(entry, 0);
-      if (new_library.raw() != old_library.raw()) {
+      if (new_library.ptr() != old_library.ptr()) {
         mapped_old_library_set.InsertOrGet(old_library);
       }
     }
@@ -2531,7 +2523,7 @@
       }
     }
   }
-  removed_class_set_storage_ = removed_class_set.Release().raw();
+  removed_class_set_storage_ = removed_class_set.Release().ptr();
 
   old_classes_set.Release();
   mapped_old_classes_set.Release();
@@ -2539,27 +2531,27 @@
   library_map.Release();
 }
 
-void IsolateReloadContext::AddClassMapping(const Class& replacement_or_new,
+void ProgramReloadContext::AddClassMapping(const Class& replacement_or_new,
                                            const Class& original) {
   UnorderedHashMap<ClassMapTraits> map(class_map_storage_);
   bool update = map.UpdateOrInsert(replacement_or_new, original);
   ASSERT(!update);
   // The storage given to the map may have been reallocated, remember the new
   // address.
-  class_map_storage_ = map.Release().raw();
+  class_map_storage_ = map.Release().ptr();
 }
 
-void IsolateReloadContext::AddLibraryMapping(const Library& replacement_or_new,
+void ProgramReloadContext::AddLibraryMapping(const Library& replacement_or_new,
                                              const Library& original) {
   UnorderedHashMap<LibraryMapTraits> map(library_map_storage_);
   bool update = map.UpdateOrInsert(replacement_or_new, original);
   ASSERT(!update);
   // The storage given to the map may have been reallocated, remember the new
   // address.
-  library_map_storage_ = map.Release().raw();
+  library_map_storage_ = map.Release().ptr();
 }
 
-void IsolateReloadContext::AddStaticFieldMapping(const Field& old_field,
+void ProgramReloadContext::AddStaticFieldMapping(const Field& old_field,
                                                  const Field& new_field) {
   ASSERT(old_field.is_static());
   ASSERT(new_field.is_static());
@@ -2567,16 +2559,16 @@
   AddBecomeMapping(old_field, new_field);
 }
 
-void IsolateReloadContext::AddBecomeMapping(const Object& old,
+void ProgramReloadContext::AddBecomeMapping(const Object& old,
                                             const Object& neu) {
   ASSERT(become_map_storage_ != Array::null());
   UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_);
   bool update = become_map.UpdateOrInsert(old, neu);
   ASSERT(!update);
-  become_map_storage_ = become_map.Release().raw();
+  become_map_storage_ = become_map.Release().ptr();
 }
 
-void IsolateReloadContext::AddEnumBecomeMapping(const Object& old,
+void ProgramReloadContext::AddEnumBecomeMapping(const Object& old,
                                                 const Object& neu) {
   const GrowableObjectArray& become_enum_mappings =
       GrowableObjectArray::Handle(become_enum_mappings_);
@@ -2585,8 +2577,8 @@
   ASSERT((become_enum_mappings.Length() % 2) == 0);
 }
 
-void IsolateReloadContext::RebuildDirectSubclasses() {
-  ClassTable* class_table = I->class_table();
+void ProgramReloadContext::RebuildDirectSubclasses() {
+  ClassTable* class_table = IG->class_table();
   intptr_t num_cids = class_table->NumCids();
 
   // Clear the direct subclasses for all classes.
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index ad29eb0..74a32b9 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -235,7 +235,6 @@
 
   int64_t start_time_micros_ = -1;
   int64_t reload_timestamp_ = -1;
-  Isolate* first_isolate_ = nullptr;
   bool reload_skipped_ = false;
   bool reload_finalized_ = false;
   JSONStream* js_;
@@ -295,19 +294,19 @@
   friend class ObjectLocator;
   friend class MarkFunctionsForRecompilation;  // IsDirty.
   friend class ReasonForCancelling;
-  friend class IsolateReloadContext;
+  friend class ProgramReloadContext;
   friend class IsolateGroup;  // GetClassSizeForHeapWalkAt
-  friend class ObjectLayout;  // GetClassSizeForHeapWalkAt
+  friend class UntaggedObject;  // GetClassSizeForHeapWalkAt
 
   static Dart_FileModifiedCallback file_modified_callback_;
 };
 
-class IsolateReloadContext {
+class ProgramReloadContext {
  public:
-  IsolateReloadContext(
+  ProgramReloadContext(
       std::shared_ptr<IsolateGroupReloadContext> group_reload_context,
       Isolate* isolate);
-  ~IsolateReloadContext();
+  ~ProgramReloadContext();
 
   // All zone allocated objects must be allocated from this zone.
   Zone* zone() const { return zone_; }
@@ -335,6 +334,7 @@
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
   Isolate* isolate() { return isolate_; }
+  IsolateGroup* isolate_group() { return isolate_->group(); }
   ObjectStore* object_store();
 
   void EnsuredUnoptimizedCodeForStack();
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 6050dd30..fef7059 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -2357,7 +2357,7 @@
   String& name = String::Handle();
 
   // Lookup the Stopwatch class by name from the dart core library.
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
   const Library& core_lib = Library::Handle(object_store->core_library());
   name = String::New("Stopwatch");
   const Class& stopwatch_cls = Class::Handle(core_lib.LookupClass(name));
@@ -2424,7 +2424,7 @@
   String& name = String::Handle();
 
   // Lookup the Stopwatch class by name from the dart core library.
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
   const Library& core_lib = Library::Handle(object_store->core_library());
   name = String::New("Stopwatch");
   const Class& stopwatch_cls = Class::Handle(core_lib.LookupClass(name));
@@ -2493,7 +2493,7 @@
   String& name = String::Handle();
 
   // Lookup the Stopwatch class by name from the dart core library.
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
   const Library& core_lib = Library::Handle(object_store->core_library());
   name = String::New("Stopwatch");
   const Class& stopwatch_cls = Class::Handle(core_lib.LookupClass(name));
@@ -4195,8 +4195,7 @@
       HeapIterationScope iteration(thread);
       NoSafepointScope no_safepoint;
       FindNoInstancesOfClass find_only(cid);
-      Isolate* isolate = Isolate::Current();
-      Heap* heap = isolate->heap();
+      Heap* heap = IsolateGroup::Current()->heap();
       // We still expect to find references to static field values
       // because they are not deleted after hot reload.
       EXPECT_NE(heap->FindObject(&find_only), Object::null());
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 10a09c9..9402106 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -125,10 +125,9 @@
 // compiler and/or CPU could reorder operations to make the tasks observe the
 // round update *before* the interrupt is set.
 TEST_CASE(StackLimitInterrupts) {
-  Isolate* isolate = thread->isolate();
-  ThreadBarrier barrier(InterruptChecker::kTaskCount + 1,
-                        isolate->heap()->barrier(),
-                        isolate->heap()->barrier_done());
+  auto heap = thread->isolate_group()->heap();
+  ThreadBarrier barrier(InterruptChecker::kTaskCount + 1, heap->barrier(),
+                        heap->barrier_done());
   // Start all tasks. They will busy-wait until interrupted in the first round.
   for (intptr_t task = 0; task < InterruptChecker::kTaskCount; task++) {
     Dart::thread_pool()->Run<InterruptChecker>(thread, &barrier);
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index adfc624..01b6c5f 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -54,12 +54,12 @@
                        const Array& param_values,
                        bool parameters_are_dart_objects) {
   set_reply_port(reply_port);
-  seq_ = &Instance::ZoneHandle(seq.raw());
+  seq_ = &Instance::ZoneHandle(seq.ptr());
   method_ = method.ToCString();
 
   if (parameters_are_dart_objects) {
-    parameter_keys_ = &Array::ZoneHandle(param_keys.raw());
-    parameter_values_ = &Array::ZoneHandle(param_values.raw());
+    parameter_keys_ = &Array::ZoneHandle(param_keys.ptr());
+    parameter_values_ = &Array::ZoneHandle(param_values.ptr());
     ASSERT(parameter_keys_->Length() == parameter_values_->Length());
   } else if (param_keys.Length() > 0) {
     String& string_iterator = String::Handle();
@@ -320,7 +320,7 @@
 
 void JSONStream::PrintValue(TokenPosition tp) {
   PrintCommaIfNeeded();
-  PrintValue(tp.value());
+  PrintValue(static_cast<intptr_t>(tp.Serialize()));
 }
 
 void JSONStream::PrintValue(const ServiceEvent* event) {
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index ed49742..442f8ce 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -35,7 +35,16 @@
   }
 }
 
-void KernelLineStartsReader::LocationForPosition(intptr_t position,
+int32_t KernelLineStartsReader::MaxPosition() const {
+  const intptr_t line_count = line_starts_data_.Length();
+  intptr_t current_start = 0;
+  for (intptr_t i = 0; i < line_count; i++) {
+    current_start += helper_->At(line_starts_data_, i);
+  }
+  return current_start;
+}
+
+bool KernelLineStartsReader::LocationForPosition(intptr_t position,
                                                  intptr_t* line,
                                                  intptr_t* col) const {
   intptr_t line_count = line_starts_data_.Length();
@@ -45,46 +54,43 @@
     current_start += helper_->At(line_starts_data_, i);
     if (current_start > position) {
       *line = i;
-      if (col != NULL) {
+      if (col != nullptr) {
         *col = position - previous_start + 1;
       }
-      return;
+      return true;
     }
     if (current_start == position) {
       *line = i + 1;
-      if (col != NULL) {
+      if (col != nullptr) {
         *col = 1;
       }
-      return;
+      return true;
     }
     previous_start = current_start;
   }
 
-  // If the start of any of the lines did not cross |position|,
-  // then it means the position falls on the last line.
-  *line = line_count;
-  if (col != NULL) {
-    *col = position - current_start + 1;
-  }
+  return false;
 }
 
-void KernelLineStartsReader::TokenRangeAtLine(
-    intptr_t source_length,
+bool KernelLineStartsReader::TokenRangeAtLine(
     intptr_t line_number,
     TokenPosition* first_token_index,
     TokenPosition* last_token_index) const {
-  ASSERT(line_number <= line_starts_data_.Length());
+  if (line_number < 0 || line_number > line_starts_data_.Length()) {
+    return false;
+  }
   intptr_t cumulative = 0;
   for (intptr_t i = 0; i < line_number; ++i) {
     cumulative += helper_->At(line_starts_data_, i);
   }
-  *first_token_index = dart::TokenPosition(cumulative);
+  *first_token_index = dart::TokenPosition::Deserialize(cumulative);
   if (line_number == line_starts_data_.Length()) {
-    *last_token_index = dart::TokenPosition(source_length);
+    *last_token_index = *first_token_index;
   } else {
-    *last_token_index = dart::TokenPosition(
+    *last_token_index = dart::TokenPosition::Deserialize(
         cumulative + helper_->At(line_starts_data_, line_number) - 1);
   }
+  return true;
 }
 
 int32_t KernelLineStartsReader::KernelInt8LineStartsHelper::At(
@@ -168,7 +174,7 @@
 void KernelTokenPositionCollector::RecordTokenPosition(TokenPosition position) {
   if (record_for_script_id_ == current_script_id_ &&
       record_token_positions_into_ != NULL && position.IsReal()) {
-    record_token_positions_into_->Add(position.value());
+    record_token_positions_into_->Add(position.Serialize());
   }
 }
 
@@ -187,7 +193,7 @@
 static ArrayPtr AsSortedDuplicateFreeArray(GrowableArray<intptr_t>* source) {
   intptr_t size = source->length();
   if (size == 0) {
-    return Object::empty_array().raw();
+    return Object::empty_array().ptr();
   }
 
   source->Sort(LowestFirst);
@@ -205,7 +211,7 @@
     smi_value = Smi::New(source->At(i));
     array_object.SetAt(i, smi_value);
   }
-  return array_object.raw();
+  return array_object.ptr();
 }
 
 static void CollectKernelDataTokenPositions(
@@ -238,9 +244,9 @@
 
   GrowableArray<intptr_t> token_positions(10);
 
-  Isolate* isolate = thread->isolate();
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  auto isolate_group = thread->isolate_group();
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      zone, isolate_group->object_store()->libraries());
   Library& lib = Library::Handle(zone);
   Object& entry = Object::Handle(zone);
   Script& entry_script = Script::Handle(zone);
@@ -258,9 +264,9 @@
       data = ExternalTypedData::null();
       if (entry.IsClass()) {
         const Class& klass = Class::Cast(entry);
-        if (klass.script() == interesting_script.raw()) {
-          token_positions.Add(klass.token_pos().value());
-          token_positions.Add(klass.end_token_pos().value());
+        if (klass.script() == interesting_script.ptr()) {
+          token_positions.Add(klass.token_pos().Serialize());
+          token_positions.Add(klass.end_token_pos().Serialize());
         }
         if (klass.is_finalized()) {
           temp_array = klass.fields();
@@ -271,7 +277,7 @@
               continue;
             }
             entry_script = temp_field.Script();
-            if (entry_script.raw() != interesting_script.raw()) {
+            if (entry_script.ptr() != interesting_script.ptr()) {
               continue;
             }
             data = temp_field.KernelData();
@@ -285,7 +291,7 @@
           for (intptr_t i = 0; i < temp_array.Length(); ++i) {
             temp_function ^= temp_array.At(i);
             entry_script = temp_function.script();
-            if (entry_script.raw() != interesting_script.raw()) {
+            if (entry_script.ptr() != interesting_script.ptr()) {
               continue;
             }
             data = temp_function.KernelData();
@@ -305,7 +311,7 @@
           const intptr_t class_offset = klass.kernel_offset();
 
           entry_script = klass.script();
-          if (entry_script.raw() != interesting_script.raw()) {
+          if (entry_script.ptr() != interesting_script.ptr()) {
             continue;
           }
           CollectKernelDataTokenPositions(
@@ -313,9 +319,9 @@
               library_kernel_offset, zone, &helper, &token_positions);
         }
       } else if (entry.IsFunction()) {
-        temp_function ^= entry.raw();
+        temp_function ^= entry.ptr();
         entry_script = temp_function.script();
-        if (entry_script.raw() != interesting_script.raw()) {
+        if (entry_script.ptr() != interesting_script.ptr()) {
           continue;
         }
         data = temp_function.KernelData();
@@ -330,7 +336,7 @@
           continue;
         }
         entry_script = field.Script();
-        if (entry_script.raw() != interesting_script.raw()) {
+        if (entry_script.ptr() != interesting_script.ptr()) {
           continue;
         }
         data = field.KernelData();
@@ -341,7 +347,7 @@
     }
   }
 
-  Script& script = Script::Handle(zone, interesting_script.raw());
+  Script& script = Script::Handle(zone, interesting_script.ptr());
   Array& array_object = Array::Handle(zone);
   array_object = AsSortedDuplicateFreeArray(&token_positions);
   script.set_debug_positions(array_object);
@@ -373,7 +379,7 @@
         zone, helper.LookupConstructorByKernelConstructor(klass, kernel_name));
     constructors.SetAt(i, target);
   }
-  return constructors.raw();
+  return constructors.ptr();
 }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -569,7 +575,7 @@
                              Object::null_instance());
     }
   }
-  return param_descriptor.raw();
+  return param_descriptor.ptr();
 }
 
 ObjectPtr BuildParameterDescriptor(const Function& function) {
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 79c5670..f7c7dfb 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -140,14 +140,23 @@
     return helper_->At(line_starts_data_, index);
   }
 
-  void LocationForPosition(intptr_t position,
-                           intptr_t* line,
-                           intptr_t* col) const;
+  int32_t MaxPosition() const;
 
-  void TokenRangeAtLine(intptr_t source_length,
-                        intptr_t line_number,
-                        dart::TokenPosition* first_token_index,
-                        dart::TokenPosition* last_token_index) const;
+  // Returns whether the given offset corresponds to a valid source offset
+  // If it does, then *line and *column (if column is not nullptr) are set
+  // to the line and column the token starts at.
+  DART_WARN_UNUSED_RESULT bool LocationForPosition(
+      intptr_t position,
+      intptr_t* line,
+      intptr_t* col = nullptr) const;
+
+  // Returns whether any tokens were found for the given line. When found,
+  // *first_token_index and *last_token_index are set to the first and
+  // last token on the line, respectively.
+  DART_WARN_UNUSED_RESULT bool TokenRangeAtLine(
+      intptr_t line_number,
+      dart::TokenPosition* first_token_index,
+      dart::TokenPosition* last_token_index) const;
 
  private:
   class KernelLineStartsHelper {
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index c34523e..7e6f741 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -75,7 +75,7 @@
     }
   }
 
-  return line_starts_data.raw();
+  return line_starts_data.ptr();
 }
 
 const char* kKernelInvalidFilesize =
@@ -208,12 +208,12 @@
       isolate->CallTagHandler(Dart_kKernelTag, Object::null_object(), uri));
   if (ret.IsExternalTypedData()) {
     const auto& typed_data = ExternalTypedData::Handle(
-        thread->zone(), ExternalTypedData::RawCast(ret.raw()));
+        thread->zone(), ExternalTypedData::RawCast(ret.ptr()));
     kernel_program = kernel::Program::ReadFromTypedData(typed_data);
     return kernel_program;
   } else if (error != nullptr) {
     Api::Scope api_scope(thread);
-    Dart_Handle retval = Api::NewHandle(thread, ret.raw());
+    Dart_Handle retval = Api::NewHandle(thread, ret.ptr());
     {
       TransitionVMToNative transition(thread);
       *error = Dart_GetError(retval);
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index f547c0b..bad9b38 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 = 52;
-static const uint32_t kMaxSupportedKernelFormatVersion = 52;
+static const uint32_t kMinSupportedKernelFormatVersion = 54;
+static const uint32_t kMaxSupportedKernelFormatVersion = 54;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -42,6 +42,9 @@
   V(AssertInitializer, 12)                                                     \
   V(CheckLibraryIsLoaded, 13)                                                  \
   V(LoadLibrary, 14)                                                           \
+  V(EqualsNull, 15)                                                            \
+  V(EqualsCall, 16)                                                            \
+  V(StaticTearOff, 17)                                                         \
   V(ConstStaticInvocation, 18)                                                 \
   V(InvalidExpression, 19)                                                     \
   V(VariableGet, 20)                                                           \
@@ -126,6 +129,16 @@
   V(SimpleInterfaceType, 96)                                                   \
   V(SimpleFunctionType, 97)                                                    \
   V(ConstantExpression, 106)                                                   \
+  V(InstanceGet, 118)                                                          \
+  V(InstanceSet, 119)                                                          \
+  V(InstanceInvocation, 120)                                                   \
+  V(InstanceTearOff, 121)                                                      \
+  V(DynamicGet, 122)                                                           \
+  V(DynamicSet, 123)                                                           \
+  V(DynamicInvocation, 124)                                                    \
+  V(FunctionInvocation, 125)                                                   \
+  V(FunctionTearOff, 126)                                                      \
+  V(LocalFunctionInvocation, 127)                                              \
   V(SpecializedVariableGet, 128)                                               \
   V(SpecializedVariableSet, 136)                                               \
   V(SpecializedIntLiteral, 144)
@@ -191,6 +204,12 @@
 };
 
 // Keep in sync with package:kernel/lib/ast.dart
+enum MethodInvocationFlags {
+  kMethodInvocationFlagInvariant = 1 << 0,
+  kMethodInvocationFlagBoundsSafe = 1 << 1,
+};
+
+// Keep in sync with package:kernel/lib/ast.dart
 enum class NamedTypeFlags : uint8_t {
   kIsRequired = 1 << 0,
 };
@@ -210,14 +229,18 @@
         raw_buffer_(buffer),
         typed_data_(NULL),
         size_(size),
-        offset_(0) {}
+        offset_(0),
+        max_position_(TokenPosition::kNoSource),
+        min_position_(TokenPosition::kNoSource) {}
 
   explicit Reader(const ExternalTypedData& typed_data)
       : thread_(Thread::Current()),
         raw_buffer_(NULL),
         typed_data_(&typed_data),
         size_(typed_data.IsNull() ? 0 : typed_data.Length()),
-        offset_(0) {}
+        offset_(0),
+        max_position_(TokenPosition::kNoSource),
+        min_position_(TokenPosition::kNoSource) {}
 
   uint32_t ReadFromIndex(intptr_t end_offset,
                          intptr_t fields_before,
@@ -310,14 +333,9 @@
     // Position is saved as unsigned,
     // but actually ranges from -1 and up (thus the -1)
     intptr_t value = ReadUInt() - 1;
-    TokenPosition result = TokenPosition(value);
-    max_position_ = Utils::Maximum(max_position_, result);
-    if (min_position_.IsNoSource()) {
-      min_position_ = result;
-    } else if (result.IsReal()) {
-      min_position_ = Utils::Minimum(min_position_, result);
-    }
-
+    TokenPosition result = TokenPosition::Deserialize(value);
+    max_position_ = TokenPosition::Max(max_position_, result);
+    min_position_ = TokenPosition::Min(min_position_, result);
     return result;
   }
 
@@ -534,12 +552,8 @@
   }
 
   ~PositionScope() {
-    if (reader_->min_position_.IsNoSource()) {
-      reader_->min_position_ = min_;
-    } else if (min_.IsReal()) {
-      reader_->min_position_ = Utils::Minimum(reader_->min_position_, min_);
-    }
-    reader_->max_position_ = Utils::Maximum(reader_->max_position_, max_);
+    reader_->min_position_ = TokenPosition::Min(reader_->min_position_, min_);
+    reader_->max_position_ = TokenPosition::Max(reader_->max_position_, max_);
   }
 
  private:
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 5190afd..168cb76 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -31,10 +31,6 @@
 #define Z (T->zone())
 
 DEFINE_FLAG(bool, trace_kernel, false, "Trace Kernel service requests.");
-DEFINE_FLAG(bool,
-            suppress_fe_warnings,
-            false,
-            "Suppress warnings from the FE.");
 DEFINE_FLAG(charp,
             kernel_multiroot_filepaths,
             NULL,
@@ -179,7 +175,7 @@
     HANDLESCOPE(T);
     // Invoke main which will return the port to which load requests are sent.
     const Library& root_library =
-        Library::Handle(Z, I->object_store()->root_library());
+        Library::Handle(Z, I->group()->object_store()->root_library());
     if (root_library.IsNull()) {
       OS::PrintErr(DART_KERNEL_ISOLATE_NAME
                    ": Embedder did not install a script.");
@@ -563,15 +559,14 @@
     is_static_object.type = Dart_CObject_kBool;
     is_static_object.value.as_bool = is_static;
 
-    Isolate* isolate =
-        Thread::Current() != NULL ? Thread::Current()->isolate() : NULL;
-    ASSERT(isolate != NULL);
+    auto isolate = thread->isolate();
+    auto isolate_group = thread->isolate_group();
+    auto source = isolate_group->source();
+
     Dart_CObject isolate_id;
     isolate_id.type = Dart_CObject_kInt64;
-    isolate_id.value.as_int64 =
-        isolate != NULL ? static_cast<int64_t>(isolate->main_port()) : 0;
+    isolate_id.value.as_int64 = static_cast<int64_t>(isolate->main_port());
 
-    IsolateGroupSource* source = Isolate::Current()->source();
     intptr_t num_dills = 0;
     if (source->kernel_buffer != nullptr) {
       num_dills++;
@@ -622,14 +617,9 @@
     num_blob_loads.type = Dart_CObject_kInt64;
     num_blob_loads.value.as_int64 = source->num_blob_loads_;
 
-    Dart_CObject suppress_warnings;
-    suppress_warnings.type = Dart_CObject_kBool;
-    suppress_warnings.value.as_bool = FLAG_suppress_fe_warnings;
-
     Dart_CObject enable_asserts;
     enable_asserts.type = Dart_CObject_kBool;
-    enable_asserts.value.as_bool =
-        isolate != NULL ? isolate->asserts() : FLAG_enable_asserts;
+    enable_asserts.value.as_bool = isolate_group->asserts();
 
     intptr_t num_experimental_flags = experimental_flags->length();
     Dart_CObject** experimental_flags_array =
@@ -658,7 +648,6 @@
                                    &is_static_object,
                                    &dills_object,
                                    &num_blob_loads,
-                                   &suppress_warnings,
                                    &enable_asserts,
                                    &experimental_flags_object};
     message.value.as_array.values = message_arr;
@@ -710,11 +699,13 @@
       int source_files_count,
       Dart_SourceFile source_files[],
       bool incremental_compile,
+      bool snapshot_compile,
       const char* package_config,
       const char* multiroot_filepaths,
       const char* multiroot_scheme,
       const MallocGrowableArray<char*>* experimental_flags,
-      const char* original_working_directory) {
+      const char* original_working_directory,
+      Dart_KernelCompilationVerbosityLevel verbosity) {
     // Build the message for the Kernel isolate.
     // tag is used to specify which operation the frontend should perform.
     Dart_CObject tag;
@@ -757,39 +748,43 @@
     dart_incremental.type = Dart_CObject_kBool;
     dart_incremental.value.as_bool = incremental_compile;
 
+    Dart_CObject dart_snapshot;
+    dart_snapshot.type = Dart_CObject_kBool;
+    dart_snapshot.value.as_bool = snapshot_compile;
+
     // TODO(aam): Assert that isolate exists once we move CompileAndReadScript
     // compilation logic out of CreateIsolateAndSetupHelper and into
     // IsolateSetupHelper in main.cc.
-    Isolate* isolate =
-        Thread::Current() != NULL ? Thread::Current()->isolate() : NULL;
+    auto thread = Thread::Current();
+    auto isolate = thread != nullptr ? thread->isolate() : nullptr;
+    auto isolate_group = thread != nullptr ? thread->isolate_group() : nullptr;
+
     if (incremental_compile) {
       ASSERT(isolate != NULL);
     }
     Dart_CObject isolate_id;
     isolate_id.type = Dart_CObject_kInt64;
     isolate_id.value.as_int64 =
-        isolate != NULL ? static_cast<int64_t>(isolate->main_port()) : 0;
+        isolate != nullptr ? static_cast<int64_t>(isolate->main_port()) : 0;
 
     Dart_CObject message;
     message.type = Dart_CObject_kArray;
 
     Dart_CObject files = BuildFilesPairs(source_files_count, source_files);
 
-    Dart_CObject suppress_warnings;
-    suppress_warnings.type = Dart_CObject_kBool;
-    suppress_warnings.value.as_bool = FLAG_suppress_fe_warnings;
-
     Dart_CObject enable_asserts;
     enable_asserts.type = Dart_CObject_kBool;
-    enable_asserts.value.as_bool =
-        isolate != NULL ? isolate->asserts() : FLAG_enable_asserts;
+    enable_asserts.value.as_bool = isolate_group != nullptr
+                                       ? isolate_group->asserts()
+                                       : FLAG_enable_asserts;
 
     Dart_CObject null_safety;
     null_safety.type = Dart_CObject_kInt32;
     null_safety.value.as_int32 =
-        (isolate != NULL) ? (isolate->null_safety() ? kNullSafetyOptionStrong
-                                                    : kNullSafetyOptionWeak)
-                          : FLAG_sound_null_safety;
+        (isolate_group != nullptr)
+            ? (isolate_group->null_safety() ? kNullSafetyOptionStrong
+                                            : kNullSafetyOptionWeak)
+            : FLAG_sound_null_safety;
 
     intptr_t num_experimental_flags = experimental_flags->length();
     Dart_CObject** experimental_flags_array =
@@ -850,21 +845,27 @@
       }
     }
 
+    Dart_CObject verbosity_str;
+    verbosity_str.type = Dart_CObject_kString;
+    verbosity_str.value.as_string =
+        const_cast<char*>(KernelCompilationVerbosityLevelToString(verbosity));
+
     Dart_CObject* message_arr[] = {&tag,
                                    &send_port,
                                    &uri,
                                    &dart_platform_kernel,
                                    &dart_incremental,
+                                   &dart_snapshot,
                                    &null_safety,
                                    &isolate_id,
                                    &files,
-                                   &suppress_warnings,
                                    &enable_asserts,
                                    &experimental_flags_object,
                                    &package_config_uri,
                                    &multiroot_filepaths_object,
                                    &multiroot_scheme_object,
-                                   &original_working_directory_object};
+                                   &original_working_directory_object,
+                                   &verbosity_str};
     message.value.as_array.values = message_arr;
     message.value.as_array.length = ARRAY_SIZE(message_arr);
     // Send the message.
@@ -979,6 +980,22 @@
     return NULL;
   }
 
+  static const char* KernelCompilationVerbosityLevelToString(
+      Dart_KernelCompilationVerbosityLevel verbosity) {
+    switch (verbosity) {
+      case Dart_KernelCompilationVerbosityLevel_Error:
+        return "error";
+      case Dart_KernelCompilationVerbosityLevel_Warning:
+        return "warning";
+      case Dart_KernelCompilationVerbosityLevel_Info:
+        return "info";
+      case Dart_KernelCompilationVerbosityLevel_All:
+        return "all";
+      default:
+        UNREACHABLE();
+    }
+  }
+
   // This monitor must be held whenever linked list of requests is accessed.
   static Monitor* requests_monitor_;
 
@@ -1006,9 +1023,11 @@
     int source_file_count,
     Dart_SourceFile source_files[],
     bool incremental_compile,
+    bool snapshot_compile,
     const char* package_config,
     const char* multiroot_filepaths,
-    const char* multiroot_scheme) {
+    const char* multiroot_scheme,
+    Dart_KernelCompilationVerbosityLevel verbosity) {
   // Start the kernel Isolate if it is not already running.
   if (!Start()) {
     Dart_KernelCompilationResult result = {};
@@ -1031,8 +1050,9 @@
   return request.SendAndWaitForResponse(
       kCompileTag, kernel_port, script_uri, platform_kernel,
       platform_kernel_size, source_file_count, source_files,
-      incremental_compile, package_config, multiroot_filepaths,
-      multiroot_scheme, experimental_flags_, NULL);
+      incremental_compile, snapshot_compile, package_config,
+      multiroot_filepaths, multiroot_scheme, experimental_flags_, NULL,
+      verbosity);
 }
 
 bool KernelIsolate::DetectNullSafety(const char* script_uri,
@@ -1050,8 +1070,8 @@
   KernelCompilationRequest request;
   Dart_KernelCompilationResult result = request.SendAndWaitForResponse(
       kDetectNullabilityTag, kernel_port, script_uri, nullptr, -1, 0, nullptr,
-      false, package_config, nullptr, nullptr, experimental_flags_,
-      original_working_directory);
+      false, false, package_config, nullptr, nullptr, experimental_flags_,
+      original_working_directory, Dart_KernelCompilationVerbosityLevel_Error);
   return result.null_safety;
 }
 
@@ -1065,9 +1085,10 @@
   }
 
   KernelCompilationRequest request;
-  return request.SendAndWaitForResponse(kListDependenciesTag, kernel_port, NULL,
-                                        NULL, 0, 0, NULL, false, NULL, NULL,
-                                        NULL, experimental_flags_, NULL);
+  return request.SendAndWaitForResponse(
+      kListDependenciesTag, kernel_port, NULL, NULL, 0, 0, NULL, false, false,
+      NULL, NULL, NULL, experimental_flags_, NULL,
+      Dart_KernelCompilationVerbosityLevel_Error);
 }
 
 Dart_KernelCompilationResult KernelIsolate::AcceptCompilation() {
@@ -1082,9 +1103,10 @@
   }
 
   KernelCompilationRequest request;
-  return request.SendAndWaitForResponse(kAcceptTag, kernel_port, NULL, NULL, 0,
-                                        0, NULL, true, NULL, NULL, NULL,
-                                        experimental_flags_, NULL);
+  return request.SendAndWaitForResponse(
+      kAcceptTag, kernel_port, NULL, NULL, 0, 0, NULL, true, false, NULL, NULL,
+      NULL, experimental_flags_, NULL,
+      Dart_KernelCompilationVerbosityLevel_Error);
 }
 
 Dart_KernelCompilationResult KernelIsolate::CompileExpressionToKernel(
@@ -1129,7 +1151,8 @@
   KernelCompilationRequest request;
   return request.SendAndWaitForResponse(
       kUpdateSourcesTag, kernel_port, NULL, NULL, 0, source_files_count,
-      source_files, true, NULL, NULL, NULL, experimental_flags_, NULL);
+      source_files, true, false, NULL, NULL, NULL, experimental_flags_, NULL,
+      Dart_KernelCompilationVerbosityLevel_Error);
 }
 
 void KernelIsolate::NotifyAboutIsolateShutdown(const Isolate* isolate) {
diff --git a/runtime/vm/kernel_isolate.h b/runtime/vm/kernel_isolate.h
index 0aa5221..438e883 100644
--- a/runtime/vm/kernel_isolate.h
+++ b/runtime/vm/kernel_isolate.h
@@ -51,9 +51,12 @@
       int source_files_count = 0,
       Dart_SourceFile source_files[] = NULL,
       bool incremental_compile = true,
+      bool snapshot_compile = false,
       const char* package_config = NULL,
       const char* multiroot_filepaths = NULL,
-      const char* multiroot_scheme = NULL);
+      const char* multiroot_scheme = NULL,
+      Dart_KernelCompilationVerbosityLevel verbosity =
+          Dart_KernelCompilationVerbosityLevel_All);
 
   static bool DetectNullSafety(const char* script_uri,
                                const char* package_config,
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index f6fe2fa..804e6e5 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -29,7 +29,7 @@
 
 #define Z (zone_)
 #define I (isolate_)
-#define IG (isolate_->group())
+#define IG (thread_->isolate_group())
 #define T (type_translator_)
 #define H (translation_helper_)
 
@@ -91,10 +91,10 @@
         *simple_value_ = H.Canonicalize(*simple_value_);
         return true;
       case kTrueLiteral:
-        simple_value_ = &Bool::Handle(Z, Bool::Get(true).raw());
+        simple_value_ = &Bool::Handle(Z, Bool::Get(true).ptr());
         return true;
       case kFalseLiteral:
-        simple_value_ = &Bool::Handle(Z, Bool::Get(false).raw());
+        simple_value_ = &Bool::Handle(Z, Bool::Get(false).ptr());
         return true;
       case kNullLiteral:
         simple_value_ = &Instance::ZoneHandle(Z, Instance::null());
@@ -122,7 +122,7 @@
   for (intptr_t i = 0; i < len; i++) {
     res.SetAt(i, *fields_[i]);
   }
-  return res.raw();
+  return res.ptr();
 }
 
 ArrayPtr KernelLoader::MakeFunctionsArray() {
@@ -131,7 +131,7 @@
   for (intptr_t i = 0; i < len; i++) {
     res.SetAt(i, *functions_[i]);
   }
-  return res.raw();
+  return res.ptr();
 }
 
 LibraryPtr BuildingTranslationHelper::LookupLibraryByKernelLibrary(
@@ -322,7 +322,7 @@
     if (load_result.IsError()) return load_result;
 
     if (load_result.IsLibrary()) {
-      library ^= load_result.raw();
+      library ^= load_result.ptr();
     }
   }
 
@@ -367,7 +367,7 @@
   for (intptr_t i = 0; i < source_table_size; ++i) {
     const String& source_uri = reader.SourceTableUriFor(i);
     if (source_uri.EndsWith(uri)) {
-      return reader.GetSourceFor(i).raw();
+      return reader.GetSourceFor(i).ptr();
     }
   }
   return String::null();
@@ -487,7 +487,7 @@
       expression_evaluation_library_(Library::Handle(Z)) {
   ASSERT(T.active_class_ == &active_class_);
   T.finalize_ = false;
-  library_kernel_data_ = kernel_data.raw();
+  library_kernel_data_ = kernel_data.ptr();
   H.InitFromKernelProgramInfo(kernel_program_info_);
 }
 
@@ -556,7 +556,7 @@
         if (constant_reader.IsInstanceConstant(constant_table_offset,
                                                external_name_class_)) {
           constant = constant_reader.ReadConstant(constant_table_offset);
-          ASSERT(constant.clazz() == external_name_class_.raw());
+          ASSERT(constant.clazz() == external_name_class_.ptr());
           // We found the annotation, let's flag the function as native and
           // set the native name!
           native_name ^= constant.GetField(external_name_field_);
@@ -604,7 +604,7 @@
   intptr_t list_length = helper_.ReadListLength();  // read list length.
   ASSERT(list_length == 0);
 
-  return result.raw();
+  return result.ptr();
 }
 
 bool KernelLoader::IsClassName(NameIndex name,
@@ -673,7 +673,7 @@
         if (constant_reader.IsInstanceConstant(constant_table_offset,
                                                external_name_class_)) {
           constant = constant_reader.ReadConstant(constant_table_offset);
-          ASSERT(constant.clazz() == external_name_class_.raw());
+          ASSERT(constant.clazz() == external_name_class_.ptr());
           uri_path ^= constant.GetField(external_name_field_);
         }
       } else if (tag == kConstructorInvocation ||
@@ -800,9 +800,9 @@
                         : real_library.LookupClassAllowPrivate(klass));
   ASSERT(!real_class.IsNull());
 
-  const intptr_t num_cids = I->class_table()->NumCids();
+  const intptr_t num_cids = IG->class_table()->NumCids();
   const intptr_t num_libs =
-      GrowableObjectArray::Handle(I->object_store()->libraries()).Length();
+      GrowableObjectArray::Handle(IG->object_store()->libraries()).Length();
 
   // Load the "evaluate:source" expression evaluation library.
   ASSERT(expression_evaluation_library_.IsNull());
@@ -810,13 +810,14 @@
   H.SetExpressionEvaluationRealClass(real_class);
   const Object& result = Object::Handle(Z, LoadProgram(true));
   if (result.IsError()) {
-    return result.raw();
+    return result.ptr();
   }
   const Function& function = H.GetExpressionEvaluationFunction();
   ASSERT(!function.IsNull());
-  ASSERT(GrowableObjectArray::Handle(I->object_store()->libraries()).Length() ==
-         num_libs);
-  ASSERT(I->class_table()->NumCids() == num_cids);
+  ASSERT(
+      GrowableObjectArray::Handle(IG->object_store()->libraries()).Length() ==
+      num_libs);
+  ASSERT(IG->class_table()->NumCids() == num_cids);
 
   // Make the expression evaluation function have the right script,
   // kernel data and parent.
@@ -829,11 +830,11 @@
 
   function.set_owner(real_class);
 
-  return function.raw();
+  return function.ptr();
 }
 
 void KernelLoader::FindModifiedLibraries(Program* program,
-                                         Isolate* isolate,
+                                         IsolateGroup* isolate_group,
                                          BitVector* modified_libs,
                                          bool force_reload,
                                          bool* is_empty_program,
@@ -845,8 +846,8 @@
     if (force_reload) {
       // If a reload is being forced we mark all libraries as having
       // been modified.
-      const GrowableObjectArray& libs =
-          GrowableObjectArray::Handle(isolate->object_store()->libraries());
+      const auto& libs = GrowableObjectArray::Handle(
+          isolate_group->object_store()->libraries());
       intptr_t num_libs = libs.Length();
       Library& lib = dart::Library::Handle(zone);
       for (intptr_t i = 0; i < num_libs; i++) {
@@ -970,8 +971,8 @@
         converter.IsSimple(helper_.ReaderOffset() + 1);
     if (!has_simple_initializer || !converter.SimpleValue().IsNull()) {
       field.set_has_nontrivial_initializer(true);
-      return;
     }
+    return;
   }
   field.set_has_initializer(false);
   field.set_has_nontrivial_initializer(false);
@@ -1014,7 +1015,7 @@
   Library& library =
       Library::Handle(Z, LookupLibrary(library_helper.canonical_name_));
 
-  if (library.Loaded()) return library.raw();
+  if (library.Loaded()) return library.ptr();
 
   library.set_is_nnbd(library_helper.IsNonNullableByDefault());
   const NNBDCompiledMode mode =
@@ -1025,14 +1026,14 @@
         "null safety and not sound null safety.",
         String::Handle(library.url()).ToCString());
   }
-  if (!I->null_safety() && mode == NNBDCompiledMode::kStrong) {
+  if (!IG->null_safety() && mode == NNBDCompiledMode::kStrong) {
     H.ReportError(
         "Library '%s' was compiled with sound null safety (in strong mode) and "
         "it "
         "requires --sound-null-safety option at runtime",
         String::Handle(library.url()).ToCString());
   }
-  if (I->null_safety() && (mode == NNBDCompiledMode::kWeak)) {
+  if (IG->null_safety() && (mode == NNBDCompiledMode::kWeak)) {
     H.ReportError(
         "Library '%s' was compiled without sound null safety (in weak mode) "
         "and it "
@@ -1055,7 +1056,7 @@
   // The bootstrapper will take care of creating the native wrapper classes, but
   // we will add the synthetic constructors to them here.
   if (library.name() ==
-      Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) {
+      Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).ptr()) {
     ASSERT(library.LoadInProgress());
     loading_native_wrappers_library_ = true;
   } else {
@@ -1087,7 +1088,7 @@
   // The expression evaluation functions should be GC-able as soon as
   // they are not reachable anymore and we never look them up by name.
   const bool register_class =
-      library.raw() != expression_evaluation_library_.raw();
+      library.ptr() != expression_evaluation_library_.ptr();
 
   Class& toplevel_class =
       Class::Handle(Z, Class::New(library, Symbols::TopLevel(), script,
@@ -1105,7 +1106,7 @@
   // is no longer used.
 
   const GrowableObjectArray& classes =
-      GrowableObjectArray::Handle(Z, I->object_store()->pending_classes());
+      GrowableObjectArray::Handle(Z, IG->object_store()->pending_classes());
 
   // Load all classes.
   intptr_t next_class_offset = library_index.ClassOffset(0);
@@ -1142,7 +1143,7 @@
   }
   if (!library.Loaded()) library.SetLoaded();
 
-  return library.raw();
+  return library.ptr();
 }
 
 void KernelLoader::FinishTopLevelClassLoading(
@@ -1357,13 +1358,13 @@
     Library& target_library = Library::Handle(
         Z, LookupLibrary(dependency_helper.target_library_canonical_name_));
     if (!FLAG_enable_mirrors &&
-        target_library.url() == Symbols::DartMirrors().raw()) {
+        target_library.url() == Symbols::DartMirrors().ptr()) {
       H.ReportError(
           "import of dart:mirrors is not supported in the current Dart "
           "runtime");
     }
     if (!Api::IsFfiEnabled() &&
-        target_library.url() == Symbols::DartFfi().raw()) {
+        target_library.url() == Symbols::DartFfi().ptr()) {
       H.ReportError(
           "import of dart:ffi is not supported in the current Dart runtime");
     }
@@ -1417,8 +1418,9 @@
   // kImplementedClasses, [...].
 
   // Set type parameters.
-  T.LoadAndSetupTypeParameters(&active_class_, *klass, type_parameter_count,
-                               Function::Handle(Z));
+  T.LoadAndSetupTypeParameters(&active_class_, Object::null_function(), *klass,
+                               Object::null_function_type(),
+                               type_parameter_count, klass->nnbd_mode());
 
   // Set super type.  Some classes (e.g., Object) do not have one.
   Tag type_tag = helper_.ReadTag();  // read super class type (part 1).
@@ -1519,7 +1521,7 @@
   // The expression evaluation functions should be GC-able as soon as
   // they are not reachable anymore and we never look them up by name.
   const bool register_class =
-      library.raw() != expression_evaluation_library_.raw();
+      library.ptr() != expression_evaluation_library_.ptr();
 
   if (loading_native_wrappers_library_ || !register_class) {
     FinishClassLoading(*out_class, library, toplevel_class, class_offset,
@@ -1646,6 +1648,22 @@
       fields_.Add(&deleted_enum_sentinel);
     }
 
+    // TODO(https://dartbug.com/44454): Make VM recognize the Struct class.
+    //
+    // The FfiTrampolines currently allocate subtypes of structs and store
+    // TypedData in them, without using guards because they are force
+    // optimized. We immediately set the guarded_cid_ to kDynamicCid, which
+    // is effectively the same as calling this method first with Pointer and
+    // subsequently with TypedData with field guards.
+    if (klass.Name() == Symbols::Struct().ptr() &&
+        Library::Handle(Z, klass.library()).url() == Symbols::DartFfi().ptr()) {
+      ASSERT(fields_.length() == 1);
+      ASSERT(String::Handle(Z, fields_[0]->name())
+                 .StartsWith(Symbols::_addressOf()));
+      fields_[0]->set_guarded_cid(kDynamicCid);
+      fields_[0]->set_is_nullable(true);
+    }
+
     // Due to ReadVMAnnotations(), the klass may have been loaded at this point
     // (loading the class while evaluating annotations).
     if (klass.is_loaded()) {
@@ -1685,8 +1703,9 @@
       owner = &ClassForScriptAt(klass, source_uri_index);
     }
 
-    Function& function = Function::ZoneHandle(
-        Z, Function::New(name, FunctionLayout::kConstructor,
+    FunctionType& signature = FunctionType::Handle(Z, FunctionType::New());
+    const Function& function = Function::ZoneHandle(
+        Z, Function::New(signature, name, UntaggedFunction::kConstructor,
                          false,  // is_static
                          constructor_helper.IsConst(),
                          false,  // is_abstract
@@ -1694,9 +1713,8 @@
                          false,  // is_native
                          *owner, constructor_helper.start_position_));
     function.set_end_token_pos(constructor_helper.end_position_);
-    functions_.Add(&function);
     function.set_kernel_offset(constructor_offset);
-    function.set_result_type(T.ReceiverType(klass));
+    signature.set_result_type(T.ReceiverType(klass));
     function.set_has_pragma(has_pragma_annotation);
 
     FunctionNodeHelper function_node_helper(&helper_);
@@ -1721,6 +1739,16 @@
     constructor_helper.SetJustRead(ConstructorHelper::kFunction);
     constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
 
+    if (klass.is_finalized()) {
+      // The owner class has already been marked as finalized (e.g. class
+      // 'NativeFieldWrapperClass1'), so the signature of this added constructor
+      // must be finalized here, since finalization of member types will not be
+      // called anymore.
+      signature ^= ClassFinalizer::FinalizeType(signature);
+      function.set_signature(signature);
+    }
+    functions_.Add(&function);
+
     if ((FLAG_enable_mirrors || has_pragma_annotation) &&
         annotation_count > 0) {
       library.AddMetadata(function, constructor_offset);
@@ -1782,7 +1810,7 @@
   LibraryIndex library_index(library_kernel_data, info.kernel_binary_version());
 
   if (klass.IsTopLevel()) {
-    ASSERT(klass.raw() == toplevel_class.raw());
+    ASSERT(klass.ptr() == toplevel_class.ptr());
     kernel_loader.FinishTopLevelClassLoading(klass, library, library_index);
     return;
   }
@@ -1830,7 +1858,7 @@
       const intptr_t start = helper_.ReaderOffset();
       detected_name = DetectExternalNameCtor();
       if (!detected_name.IsNull()) {
-        *native_name = detected_name.raw();
+        *native_name = detected_name.ptr();
         continue;
       }
 
@@ -1905,7 +1933,7 @@
         if (constant_reader.IsInstanceConstant(constant_table_offset,
                                                external_name_class_)) {
           constant = constant_reader.ReadConstant(constant_table_offset);
-          ASSERT(constant.clazz() == external_name_class_.raw());
+          ASSERT(constant.clazz() == external_name_class_.ptr());
           *native_name ^= constant.GetField(external_name_field_);
         } else if (constant_reader.IsInstanceConstant(constant_table_offset,
                                                       pragma_class_)) {
@@ -1957,15 +1985,16 @@
   procedure_helper.SetJustRead(ProcedureHelper::kAnnotations);
   const Object& script_class =
       ClassForScriptAt(owner, procedure_helper.source_uri_index_);
-  FunctionLayout::Kind kind = GetFunctionType(procedure_helper.kind_);
+  UntaggedFunction::Kind kind = GetFunctionType(procedure_helper.kind_);
 
   // We do not register expression evaluation libraries with the VM:
   // The expression evaluation functions should be GC-able as soon as
   // they are not reachable anymore and we never look them up by name.
   const bool register_function = !name.Equals(Symbols::DebugProcedureName());
 
-  Function& function = Function::ZoneHandle(
-      Z, Function::New(name, kind,
+  const FunctionType& signature = FunctionType::Handle(Z, FunctionType::New());
+  const Function& function = Function::ZoneHandle(
+      Z, Function::New(signature, name, kind,
                        !is_method,  // is_static
                        false,       // is_const
                        is_abstract, is_external,
@@ -1984,7 +2013,7 @@
   function.set_is_extension_member(is_extension_member);
   if ((library.is_dart_scheme() &&
        H.IsPrivate(procedure_helper.canonical_name_)) ||
-      (function.is_static() && (library.raw() == Library::InternalLibrary()))) {
+      (function.is_static() && (library.ptr() == Library::InternalLibrary()))) {
     function.set_is_reflectable(false);
   }
   if (procedure_helper.IsMemberSignature()) {
@@ -2003,19 +2032,19 @@
                              FunctionNodeHelper::kSync);
   switch (function_node_helper.dart_async_marker_) {
     case FunctionNodeHelper::kSyncStar:
-      function.set_modifier(FunctionLayout::kSyncGen);
+      function.set_modifier(UntaggedFunction::kSyncGen);
       function.set_is_visible(!FLAG_causal_async_stacks &&
                               !FLAG_lazy_async_stacks);
       break;
     case FunctionNodeHelper::kAsync:
-      function.set_modifier(FunctionLayout::kAsync);
+      function.set_modifier(UntaggedFunction::kAsync);
       function.set_is_inlinable(!FLAG_causal_async_stacks &&
                                 !FLAG_lazy_async_stacks);
       function.set_is_visible(!FLAG_causal_async_stacks &&
                               !FLAG_lazy_async_stacks);
       break;
     case FunctionNodeHelper::kAsyncStar:
-      function.set_modifier(FunctionLayout::kAsyncGen);
+      function.set_modifier(UntaggedFunction::kAsyncGen);
       function.set_is_inlinable(!FLAG_causal_async_stacks &&
                                 !FLAG_lazy_async_stacks);
       function.set_is_visible(!FLAG_causal_async_stacks &&
@@ -2068,7 +2097,7 @@
 const Object& KernelLoader::ClassForScriptAt(const Class& klass,
                                              intptr_t source_uri_index) {
   const Script& correct_script = Script::Handle(Z, ScriptAt(source_uri_index));
-  if (klass.script() != correct_script.raw()) {
+  if (klass.script() != correct_script.ptr()) {
     // Lazily create the [patch_classes_] array in case we need it.
     if (patch_classes_.IsNull()) {
       const Array& scripts = Array::Handle(Z, kernel_program_info_.scripts());
@@ -2079,7 +2108,7 @@
     // Use cache for patch classes. This works best for in-order usages.
     PatchClass& patch_class = PatchClass::ZoneHandle(Z);
     patch_class ^= patch_classes_.At(source_uri_index);
-    if (patch_class.IsNull() || patch_class.origin_class() != klass.raw()) {
+    if (patch_class.IsNull() || patch_class.origin_class() != klass.ptr()) {
       ASSERT(!library_kernel_data_.IsNull());
       patch_class = PatchClass::New(klass, correct_script);
       patch_class.set_library_kernel_data(library_kernel_data_);
@@ -2109,8 +2138,8 @@
     wrapper.uri = &uri_string;
     UriToSourceTableEntry* pair = uri_to_source_table->LookupValue(&wrapper);
     if (pair != nullptr) {
-      sources = pair->sources->raw();
-      line_starts = pair->line_starts->raw();
+      sources = pair->sources->ptr();
+      line_starts = pair->line_starts->ptr();
     }
   }
 
@@ -2118,14 +2147,14 @@
     const String& script_source = helper_.GetSourceFor(index);
     line_starts = helper_.GetLineStartsFor(index);
 
-    if (script_source.raw() == Symbols::Empty().raw() &&
+    if (script_source.ptr() == Symbols::Empty().ptr() &&
         line_starts.Length() == 0 && uri_string.Length() > 0) {
       // Entry included only to provide URI - actual source should already exist
       // in the VM, so try to find it.
       Library& lib = Library::Handle(Z);
       Script& script = Script::Handle(Z);
       const GrowableObjectArray& libs =
-          GrowableObjectArray::Handle(isolate_->object_store()->libraries());
+          GrowableObjectArray::Handle(IG->object_store()->libraries());
       for (intptr_t i = 0; i < libs.Length(); i++) {
         lib ^= libs.At(i);
         script = lib.LookupScript(uri_string, /* useResolvedUri = */ true);
@@ -2136,7 +2165,7 @@
         }
       }
     } else {
-      sources = script_source.raw();
+      sources = script_source.ptr();
     }
   }
 
@@ -2149,7 +2178,7 @@
   script.set_constant_coverage(constant_coverage);
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   script.set_debug_positions(Array::null_array());
-  return script.raw();
+  return script.ptr();
 }
 
 InstancePtr KernelLoader::GenerateFieldAccessors(const Class& klass,
@@ -2164,7 +2193,7 @@
         converter.IsSimple(helper_.ReaderOffset() + 1);  // ignore the tag.
     if (has_simple_initializer) {
       if (field_helper->IsStatic()) {
-        return converter.SimpleValue().raw();
+        return converter.SimpleValue().ptr();
       } else {
         // Note: optimizer relies on DoubleInitialized bit in its field-unboxing
         // heuristics. See JitCallSpecializer::VisitStoreInstanceField for more
@@ -2191,12 +2220,13 @@
       H.DartGetterName(field_helper->canonical_name_getter_);
   const Object& script_class =
       ClassForScriptAt(klass, field_helper->source_uri_index_);
+  const FunctionType& signature = FunctionType::Handle(Z, FunctionType::New());
   Function& getter = Function::ZoneHandle(
       Z,
       Function::New(
-          getter_name,
-          field_helper->IsStatic() ? FunctionLayout::kImplicitStaticGetter
-                                   : FunctionLayout::kImplicitGetter,
+          signature, getter_name,
+          field_helper->IsStatic() ? UntaggedFunction::kImplicitStaticGetter
+                                   : UntaggedFunction::kImplicitGetter,
           field_helper->IsStatic(),
           // The functions created by the parser have is_const for static fields
           // that are const (not just final) and they have is_const for
@@ -2211,7 +2241,7 @@
   getter.set_end_token_pos(field_helper->end_position_);
   getter.set_kernel_offset(field.kernel_offset());
   const AbstractType& field_type = AbstractType::Handle(Z, field.type());
-  getter.set_result_type(field_type);
+  signature.set_result_type(field_type);
   getter.set_is_debuggable(false);
   getter.set_accessor_field(field);
   getter.set_is_extension_member(field.is_extension_member());
@@ -2223,18 +2253,21 @@
     ASSERT(!field_helper->IsConst());
     const String& setter_name =
         H.DartSetterName(field_helper->canonical_name_setter_);
+    const FunctionType& signature =
+        FunctionType::Handle(Z, FunctionType::New());
     Function& setter = Function::ZoneHandle(
-        Z, Function::New(setter_name, FunctionLayout::kImplicitSetter,
-                         field_helper->IsStatic(),
-                         false,  // is_const
-                         false,  // is_abstract
-                         false,  // is_external
-                         false,  // is_native
-                         script_class, field_helper->position_));
+        Z,
+        Function::New(signature, setter_name, UntaggedFunction::kImplicitSetter,
+                      field_helper->IsStatic(),
+                      false,  // is_const
+                      false,  // is_abstract
+                      false,  // is_external
+                      false,  // is_native
+                      script_class, field_helper->position_));
     functions_.Add(&setter);
     setter.set_end_token_pos(field_helper->end_position_);
     setter.set_kernel_offset(field.kernel_offset());
-    setter.set_result_type(Object::void_type());
+    signature.set_result_type(Object::void_type());
     setter.set_is_debuggable(false);
     setter.set_accessor_field(field);
     setter.set_is_extension_member(field.is_extension_member());
@@ -2244,7 +2277,7 @@
   }
 
   // If static, we do need a getter that evaluates the initializer if necessary.
-  return field_helper->IsStatic() ? Instance::sentinel().raw()
+  return field_helper->IsStatic() ? Instance::sentinel().ptr()
                                   : Instance::null();
 }
 
@@ -2291,9 +2324,9 @@
   if (url.Equals(Symbols::EvalSourceUri())) {
     if (expression_evaluation_library_.IsNull()) {
       handle = Library::New(url);
-      expression_evaluation_library_ = handle.raw();
+      expression_evaluation_library_ = handle.ptr();
     }
-    return expression_evaluation_library_.raw();
+    return expression_evaluation_library_.ptr();
   }
   handle = Library::LookupLibrary(thread_, url);
   if (handle.IsNull()) {
@@ -2329,7 +2362,7 @@
     // We do not register expression evaluation classes with the VM:
     // The expression evaluation functions should be GC-able as soon as
     // they are not reachable anymore and we never look them up by name.
-    register_class = library.raw() != expression_evaluation_library_.raw();
+    register_class = library.ptr() != expression_evaluation_library_.ptr();
 
     handle = Class::New(library, name, Script::Handle(Z),
                         TokenPosition::kNoSource, register_class);
@@ -2342,21 +2375,21 @@
     name_index_handle_ = Smi::New(klass);
     kernel_program_info_.InsertClass(thread_, name_index_handle_, handle);
   }
-  return handle.raw();
+  return handle.ptr();
 }
 
-FunctionLayout::Kind KernelLoader::GetFunctionType(
+UntaggedFunction::Kind KernelLoader::GetFunctionType(
     ProcedureHelper::Kind procedure_kind) {
   intptr_t lookuptable[] = {
-      FunctionLayout::kRegularFunction,  // Procedure::kMethod
-      FunctionLayout::kGetterFunction,   // Procedure::kGetter
-      FunctionLayout::kSetterFunction,   // Procedure::kSetter
-      FunctionLayout::kRegularFunction,  // Procedure::kOperator
-      FunctionLayout::kConstructor,      // Procedure::kFactory
+      UntaggedFunction::kRegularFunction,  // Procedure::kMethod
+      UntaggedFunction::kGetterFunction,   // Procedure::kGetter
+      UntaggedFunction::kSetterFunction,   // Procedure::kSetter
+      UntaggedFunction::kRegularFunction,  // Procedure::kOperator
+      UntaggedFunction::kConstructor,      // Procedure::kFactory
   };
   intptr_t kind = static_cast<int>(procedure_kind);
   ASSERT(0 <= kind && kind <= ProcedureHelper::kFactory);
-  return static_cast<FunctionLayout::Kind>(lookuptable[kind]);
+  return static_cast<UntaggedFunction::Kind>(lookuptable[kind]);
 }
 
 FunctionPtr CreateFieldInitializerFunction(Thread* thread,
@@ -2383,25 +2416,27 @@
   initializer_owner.set_library_kernel_offset(lib.kernel_offset());
 
   // Create a static initializer.
+  FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
   const Function& initializer_fun = Function::Handle(
-      zone, Function::New(init_name, FunctionLayout::kFieldInitializer,
-                          field.is_static(),  // is_static
-                          false,              // is_const
-                          false,              // is_abstract
-                          false,              // is_external
-                          false,              // is_native
-                          initializer_owner, TokenPosition::kNoSource));
+      zone,
+      Function::New(signature, init_name, UntaggedFunction::kFieldInitializer,
+                    field.is_static(),  // is_static
+                    false,              // is_const
+                    false,              // is_abstract
+                    false,              // is_external
+                    false,              // is_native
+                    initializer_owner, TokenPosition::kNoSource));
   if (!field.is_static()) {
     initializer_fun.set_num_fixed_parameters(1);
-    initializer_fun.set_parameter_types(
+    signature.set_parameter_types(
         Array::Handle(zone, Array::New(1, Heap::kOld)));
-    initializer_fun.CreateNameArrayIncludingFlags(Heap::kOld);
-    initializer_fun.SetParameterTypeAt(
+    signature.CreateNameArrayIncludingFlags(Heap::kOld);
+    signature.SetParameterTypeAt(
         0, AbstractType::Handle(zone, field_owner.DeclarationType()));
-    initializer_fun.SetParameterNameAt(0, Symbols::This());
-    initializer_fun.TruncateUnusedParameterFlags();
+    signature.SetParameterNameAt(0, Symbols::This());
+    signature.FinalizeNameArrays(initializer_fun);
   }
-  initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
+  signature.set_result_type(AbstractType::Handle(zone, field.type()));
   initializer_fun.set_is_reflectable(false);
   initializer_fun.set_is_inlinable(false);
   initializer_fun.set_token_pos(field.token_pos());
@@ -2409,8 +2444,12 @@
   initializer_fun.set_accessor_field(field);
   initializer_fun.InheritKernelOffsetFrom(field);
   initializer_fun.set_is_extension_member(field.is_extension_member());
+
+  signature ^= ClassFinalizer::FinalizeType(signature);
+  initializer_fun.set_signature(signature);
+
   field.SetInitializerFunction(initializer_fun);
-  return initializer_fun.raw();
+  return initializer_fun.ptr();
 }
 
 }  // namespace kernel
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index 5b983ea..00f6335 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -204,7 +204,7 @@
   // not nullptr, then they are populated with number of classes and top-level
   // procedures in [program].
   static void FindModifiedLibraries(Program* program,
-                                    Isolate* isolate,
+                                    IsolateGroup* isolate_group,
                                     BitVector* modified_libs,
                                     bool force_reload,
                                     bool* is_empty_program,
@@ -345,7 +345,7 @@
   LibraryPtr LookupLibraryFromClass(NameIndex klass);
   ClassPtr LookupClass(const Library& library, NameIndex klass);
 
-  FunctionLayout::Kind GetFunctionType(ProcedureHelper::Kind procedure_kind);
+  UntaggedFunction::Kind GetFunctionType(ProcedureHelper::Kind procedure_kind);
 
   void EnsureExternalClassIsLookedUp() {
     if (external_name_class_.IsNull()) {
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 2e7d1b3..d1607d4 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -16,44 +16,45 @@
 MegamorphicCachePtr MegamorphicCacheTable::Lookup(Thread* thread,
                                                   const String& name,
                                                   const Array& descriptor) {
-  Isolate* isolate = thread->isolate();
+  auto object_store = thread->isolate_group()->object_store();
   SafepointMutexLocker ml(thread->isolate_group()->megamorphic_table_mutex());
 
   ASSERT(name.IsSymbol());
   // TODO(rmacnak): ASSERT(descriptor.IsCanonical());
 
   // TODO(rmacnak): Make a proper hashtable a la symbol table.
-  auto& table = GrowableObjectArray::Handle(
-      isolate->object_store()->megamorphic_cache_table());
+  auto& table =
+      GrowableObjectArray::Handle(object_store->megamorphic_cache_table());
   MegamorphicCache& cache = MegamorphicCache::Handle();
   if (table.IsNull()) {
     table = GrowableObjectArray::New(Heap::kOld);
-    isolate->object_store()->set_megamorphic_cache_table(table);
+    object_store->set_megamorphic_cache_table(table);
   } else {
     for (intptr_t i = 0; i < table.Length(); i++) {
       cache ^= table.At(i);
-      if ((cache.target_name() == name.raw()) &&
-          (cache.arguments_descriptor() == descriptor.raw())) {
-        return cache.raw();
+      if ((cache.target_name() == name.ptr()) &&
+          (cache.arguments_descriptor() == descriptor.ptr())) {
+        return cache.ptr();
       }
     }
   }
 
   cache = MegamorphicCache::New(name, descriptor);
   table.Add(cache, Heap::kOld);
-  return cache.raw();
+  return cache.ptr();
 }
 
 void MegamorphicCacheTable::PrintSizes(Isolate* isolate) {
   auto thread = Thread::Current();
-  SafepointMutexLocker ml(thread->isolate_group()->megamorphic_table_mutex());
+  auto isolate_group = thread->isolate_group();
+  SafepointMutexLocker ml(isolate_group->megamorphic_table_mutex());
 
   StackZone zone(thread);
   intptr_t size = 0;
   MegamorphicCache& cache = MegamorphicCache::Handle();
   Array& buckets = Array::Handle();
   const GrowableObjectArray& table = GrowableObjectArray::Handle(
-      isolate->object_store()->megamorphic_cache_table());
+      isolate_group->object_store()->megamorphic_cache_table());
   if (table.IsNull()) return;
   intptr_t max_size = 0;
   for (intptr_t i = 0; i < table.Length(); i++) {
diff --git a/runtime/vm/message.cc b/runtime/vm/message.cc
index b4d4c69..e533e32 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -44,7 +44,7 @@
       snapshot_length_(0),
       finalizable_data_(NULL),
       priority_(priority) {
-  ASSERT(!raw_obj->IsHeapObject() || raw_obj->ptr()->InVMIsolateHeap());
+  ASSERT(!raw_obj->IsHeapObject() || raw_obj->untag()->InVMIsolateHeap());
   ASSERT((priority == kNormalPriority) ||
          (delivery_failure_port == kIllegalPort));
   ASSERT(IsRaw());
diff --git a/runtime/vm/metrics_test.cc b/runtime/vm/metrics_test.cc
index a26aaac..2881c361 100644
--- a/runtime/vm/metrics_test.cc
+++ b/runtime/vm/metrics_test.cc
@@ -89,8 +89,8 @@
 
   // Ensure we've done new/old GCs to ensure max metrics are initialized.
   String::New("<land-in-new-space>", Heap::kNew);
-  Isolate::Current()->heap()->new_space()->Scavenge();
-  Isolate::Current()->heap()->CollectAllGarbage(Heap::kLowMemory);
+  IsolateGroup::Current()->heap()->new_space()->Scavenge();
+  IsolateGroup::Current()->heap()->CollectAllGarbage(Heap::kLowMemory);
 
   // Ensure we've something live in new space.
   String::New("<land-in-new-space2>", Heap::kNew);
@@ -159,7 +159,7 @@
   EXPECT_STREQ("debugging", last_gcevent_reason);
 
   // This call emits 2 or 3 events.
-  Isolate::Current()->heap()->CollectAllGarbage(Heap::kLowMemory);
+  IsolateGroup::Current()->heap()->CollectAllGarbage(Heap::kLowMemory);
 
   EXPECT_GE(event_counter, 3UL);
   EXPECT_STREQ("MarkCompact", last_gcevent_type);
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 1c7c43a..9ed7641 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -201,7 +201,7 @@
   CHECK_CALLBACK_STATE(T);
   const Error& error = Error::Handle(T->zone(), Library::CompileAll());
   if (!error.IsNull()) {
-    return Api::NewHandle(T, error.raw());
+    return Api::NewHandle(T, error.ptr());
   }
   return Api::Success();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
@@ -221,7 +221,7 @@
   CHECK_CALLBACK_STATE(T);
   const Error& error = Error::Handle(T->zone(), Library::FinalizeAllClasses());
   if (!error.IsNull()) {
-    return Api::NewHandle(T, error.raw());
+    return Api::NewHandle(T, error.ptr());
   }
   return Api::Success();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
@@ -239,13 +239,13 @@
     TransitionNativeToVM _(Thread::Current());
     intptr_t argument = reinterpret_cast<intptr_t>(arg);
     ASSERT(argument > 0);
-    Isolate::Current()->heap()->CollectOnNthAllocation(argument);
+    IsolateGroup::Current()->heap()->CollectOnNthAllocation(argument);
     return nullptr;
 
   } else if (strcmp(command, "gc-now") == 0) {
     ASSERT(arg == nullptr);  // Don't pass an argument to this command.
     TransitionNativeToVM _(Thread::Current());
-    Isolate::Current()->heap()->CollectAllGarbage();
+    IsolateGroup::Current()->heap()->CollectAllGarbage();
     return nullptr;
 
   } else if (strcmp(command, "is-mutator-in-native") == 0) {
@@ -264,9 +264,9 @@
     Thread* const thread = Thread::Current();
     {
       SafepointOperationScope scope(thread);
-      args->isolate->heap()->WriteProtectCode(/*read_only=*/false);
+      args->isolate->group()->heap()->WriteProtectCode(/*read_only=*/false);
       (*args->callback)();
-      args->isolate->heap()->WriteProtectCode(/*read_only=*/true);
+      args->isolate->group()->heap()->WriteProtectCode(/*read_only=*/true);
     }
     Thread::ExitIsolateAsHelper();
     return nullptr;
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index b942e80..5b206ed 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -96,7 +96,7 @@
     ASSERT((index >= 0) && (index < ArgCount()));
     ObjectPtr* arg_ptr =
         &(argv_[ReverseArgOrderBit::decode(argc_tag_) ? index : -index]);
-    *arg_ptr = value.raw();
+    *arg_ptr = value.ptr();
   }
 
   // Does not include hidden type arguments vector.
@@ -152,14 +152,14 @@
     TypeArguments& type_args = TypeArguments::Handle(NativeTypeArgs());
     if (type_args.IsNull()) {
       // null vector represents infinite list of dynamics
-      return Type::dynamic_type().raw();
+      return Type::dynamic_type().ptr();
     }
     return type_args.TypeAt(index);
   }
 
   void SetReturn(const Object& value) const {
     ASSERT(thread_->execution_state() == Thread::kThreadInVM);
-    *retval_ = value.raw();
+    *retval_ = value.ptr();
   }
 
   ObjectPtr ReturnValue() const {
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index 445ccf0..e37b70d 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -48,7 +48,7 @@
   {
     Thread* T = Thread::Current();
     Api::Scope api_scope(T);
-    Dart_Handle api_function_name = Api::NewHandle(T, function_name.raw());
+    Dart_Handle api_function_name = Api::NewHandle(T, function_name.ptr());
     {
       Dart_NativeEntryResolver resolver = library.native_entry_resolver();
       TransitionVMToNative transition(T);
@@ -74,7 +74,7 @@
   Thread* thread = Thread::Current();
   REUSABLE_GROWABLE_OBJECT_ARRAY_HANDLESCOPE(thread);
   GrowableObjectArray& libs = reused_growable_object_array_handle.Handle();
-  libs = thread->isolate()->object_store()->libraries();
+  libs = thread->isolate_group()->object_store()->libraries();
   ASSERT(!libs.IsNull());
   intptr_t num_libs = libs.Length();
   for (intptr_t i = 0; i < num_libs; i++) {
@@ -139,7 +139,7 @@
     // been set.
     ObjectPtr return_value_unsafe = reinterpret_cast<BootstrapNativeFunction>(
         func)(thread, zone.GetZone(), arguments);
-    if (return_value_unsafe != Object::sentinel().raw()) {
+    if (return_value_unsafe != Object::sentinel().ptr()) {
       ASSERT(return_value_unsafe->IsDartInstance());
       arguments->SetReturnUnsafe(return_value_unsafe);
     }
@@ -295,18 +295,18 @@
     ASSERT(current_function ==
                reinterpret_cast<NativeFunction>(LinkNativeCall) ||
            current_function == target_function);
-    ASSERT(current_trampoline.raw() == StubCode::CallBootstrapNative().raw() ||
+    ASSERT(current_trampoline.ptr() == StubCode::CallBootstrapNative().ptr() ||
            current_function == target_function);
 #endif
 
     NativeFunction patch_target_function = target_function;
     Code& trampoline = Code::Handle(zone);
     if (is_bootstrap_native) {
-      trampoline = StubCode::CallBootstrapNative().raw();
+      trampoline = StubCode::CallBootstrapNative().ptr();
     } else if (is_auto_scope) {
-      trampoline = StubCode::CallAutoScopeNative().raw();
+      trampoline = StubCode::CallAutoScopeNative().ptr();
     } else {
-      trampoline = StubCode::CallNoScopeNative().raw();
+      trampoline = StubCode::CallNoScopeNative().ptr();
     }
     CodePatcher::PatchNativeCallAt(caller_frame->pc(), code,
                                    patch_target_function, trampoline);
@@ -338,15 +338,15 @@
 
 // Note: not GC safe. Use with care.
 NativeEntryData::Payload* NativeEntryData::FromTypedArray(TypedDataPtr data) {
-  return reinterpret_cast<Payload*>(data->ptr()->data());
+  return reinterpret_cast<Payload*>(data->untag()->data());
 }
 
 MethodRecognizer::Kind NativeEntryData::kind() const {
-  return FromTypedArray(data_.raw())->kind;
+  return FromTypedArray(data_.ptr())->kind;
 }
 
 void NativeEntryData::set_kind(MethodRecognizer::Kind value) const {
-  FromTypedArray(data_.raw())->kind = value;
+  FromTypedArray(data_.ptr())->kind = value;
 }
 
 MethodRecognizer::Kind NativeEntryData::GetKind(TypedDataPtr data) {
@@ -354,11 +354,11 @@
 }
 
 NativeFunctionWrapper NativeEntryData::trampoline() const {
-  return FromTypedArray(data_.raw())->trampoline;
+  return FromTypedArray(data_.ptr())->trampoline;
 }
 
 void NativeEntryData::set_trampoline(NativeFunctionWrapper value) const {
-  FromTypedArray(data_.raw())->trampoline = value;
+  FromTypedArray(data_.ptr())->trampoline = value;
 }
 
 NativeFunctionWrapper NativeEntryData::GetTrampoline(TypedDataPtr data) {
@@ -366,11 +366,11 @@
 }
 
 NativeFunction NativeEntryData::native_function() const {
-  return FromTypedArray(data_.raw())->native_function;
+  return FromTypedArray(data_.ptr())->native_function;
 }
 
 void NativeEntryData::set_native_function(NativeFunction value) const {
-  FromTypedArray(data_.raw())->native_function = value;
+  FromTypedArray(data_.ptr())->native_function = value;
 }
 
 NativeFunction NativeEntryData::GetNativeFunction(TypedDataPtr data) {
@@ -378,11 +378,11 @@
 }
 
 intptr_t NativeEntryData::argc_tag() const {
-  return FromTypedArray(data_.raw())->argc_tag;
+  return FromTypedArray(data_.ptr())->argc_tag;
 }
 
 void NativeEntryData::set_argc_tag(intptr_t value) const {
-  FromTypedArray(data_.raw())->argc_tag = value;
+  FromTypedArray(data_.ptr())->argc_tag = value;
 }
 
 intptr_t NativeEntryData::GetArgcTag(TypedDataPtr data) {
@@ -400,7 +400,7 @@
   native_entry.set_trampoline(trampoline);
   native_entry.set_native_function(native_function);
   native_entry.set_argc_tag(argc_tag);
-  return data.raw();
+  return data.ptr();
 }
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/native_entry_test.cc b/runtime/vm/native_entry_test.cc
index 2eae7dd..b3e0b19 100644
--- a/runtime/vm/native_entry_test.cc
+++ b/runtime/vm/native_entry_test.cc
@@ -62,7 +62,7 @@
     Dart_Handle arg = Dart_GetNativeArgument(args, i);
     GET_NATIVE_ARGUMENT(Integer, argument, arguments->NativeArgAt(i));
     EXPECT(argument.IsInteger());                       // May be null.
-    EXPECT_EQ(Api::UnwrapHandle(arg), argument.raw());  // May be null.
+    EXPECT_EQ(Api::UnwrapHandle(arg), argument.ptr());  // May be null.
     int64_t arg_value = -1;
     if (argument.IsNull()) {
       EXPECT_ERROR(Dart_IntegerToInt64(arg, &arg_value),
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 57ff8c6..fae18df 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -16,6 +16,7 @@
 #include "vm/bootstrap.h"
 #include "vm/canonical_tables.h"
 #include "vm/class_finalizer.h"
+#include "vm/closure_functions_cache.h"
 #include "vm/code_comments.h"
 #include "vm/code_descriptors.h"
 #include "vm/code_observers.h"
@@ -145,7 +146,6 @@
 ClassPtr Object::patch_class_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::function_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::closure_data_class_ = static_cast<ClassPtr>(RAW_NULL);
-ClassPtr Object::signature_data_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::ffi_trampoline_data_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::field_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::script_class_ = static_cast<ClassPtr>(RAW_NULL);
@@ -438,7 +438,7 @@
 
   if (start == 0) {
     // This unmangled_name is fine as it is.
-    return name.raw();
+    return name.ptr();
   }
 
   if (is_extension) {
@@ -463,9 +463,9 @@
     }
   }
 
-  return result.raw();
+  return result.ptr();
 #endif                // !defined(DART_PRECOMPILED_RUNTIME)
-  return name.raw();  // In AOT, return argument unchanged.
+  return name.ptr();  // In AOT, return argument unchanged.
 }
 
 template <typename type>
@@ -513,15 +513,14 @@
   return '\0';
 }
 
-void Object::InitNullAndBool(Isolate* isolate) {
+void Object::InitNullAndBool(IsolateGroup* isolate_group) {
   // Should only be run by the vm isolate.
-  ASSERT(isolate == Dart::vm_isolate());
+  ASSERT(isolate_group == Dart::vm_isolate_group());
+  auto heap = isolate_group->heap();
 
   // TODO(iposva): NoSafepointScope needs to be added here.
   ASSERT(class_class() == null_);
 
-  Heap* heap = isolate->heap();
-
   // Allocate and initialize the null instance.
   // 'null_' must be the first object allocated as it is used in allocation to
   // clear the object.
@@ -530,7 +529,7 @@
     null_ = static_cast<InstancePtr>(address + kHeapObjectTag);
     // The call below is using 'null_' to initialize itself.
     InitializeObject(address, kNullCid, Instance::InstanceSize());
-    null_->ptr()->SetCanonical();
+    null_->untag()->SetCanonical();
   }
 
   // Allocate and initialize the bool instances.
@@ -541,23 +540,23 @@
     // Allocate a dummy bool object to give true the desired alignment.
     uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
     InitializeObject(address, kBoolCid, Bool::InstanceSize());
-    static_cast<BoolPtr>(address + kHeapObjectTag)->ptr()->value_ = false;
+    static_cast<BoolPtr>(address + kHeapObjectTag)->untag()->value_ = false;
   }
   {
     // Allocate true.
     uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
     true_ = static_cast<BoolPtr>(address + kHeapObjectTag);
     InitializeObject(address, kBoolCid, Bool::InstanceSize());
-    true_->ptr()->value_ = true;
-    true_->ptr()->SetCanonical();
+    true_->untag()->value_ = true;
+    true_->untag()->SetCanonical();
   }
   {
     // Allocate false.
     uword address = heap->Allocate(Bool::InstanceSize(), Heap::kOld);
     false_ = static_cast<BoolPtr>(address + kHeapObjectTag);
     InitializeObject(address, kBoolCid, Bool::InstanceSize());
-    false_->ptr()->value_ = false;
-    false_->ptr()->SetCanonical();
+    false_->untag()->value_ = false;
+    false_->untag()->SetCanonical();
   }
 
   // Check that the objects have been allocated at appropriate addresses.
@@ -657,14 +656,13 @@
   }
 }
 
-void Object::Init(Isolate* isolate) {
+void Object::Init(IsolateGroup* isolate_group) {
   // Should only be run by the vm isolate.
-  ASSERT(isolate == Dart::vm_isolate());
+  ASSERT(isolate_group == Dart::vm_isolate_group());
+  Heap* heap = isolate_group->heap();
 
   InitVtables();
 
-  Heap* heap = isolate->heap();
-
 // Allocate the read only object handles here.
 #define INITIALIZE_SHARED_READONLY_HANDLE(Type, name)                          \
   name##_ = Type::ReadOnlyHandle();
@@ -672,10 +670,12 @@
 #undef INITIALIZE_SHARED_READONLY_HANDLE
 
   *null_object_ = Object::null();
+  *null_class_ = Class::null();
   *null_array_ = Array::null();
   *null_string_ = String::null();
   *null_instance_ = Instance::null();
   *null_function_ = Function::null();
+  *null_function_type_ = FunctionType::null();
   *null_type_arguments_ = TypeArguments::null();
   *empty_type_arguments_ = TypeArguments::null();
   *null_abstract_type_ = AbstractType::null();
@@ -700,9 +700,9 @@
 
     Class fake;
     // Initialization from Class::New<Class>.
-    // Directly set raw_ to break a circular dependency: SetRaw will attempt
+    // Directly set ptr_ to break a circular dependency: SetRaw will attempt
     // to lookup class class in the class table where it is not registered yet.
-    cls.raw_ = class_class_;
+    cls.ptr_ = class_class_;
     ASSERT(builtin_vtables_[kClassCid] == fake.vtable());
     cls.set_instance_size(
         Class::InstanceSize(),
@@ -720,26 +720,26 @@
     cls.set_num_type_arguments(0);
     cls.set_num_native_fields(0);
     cls.InitEmptyFields();
-    isolate->class_table()->Register(cls);
+    isolate_group->class_table()->Register(cls);
   }
 
   // Allocate and initialize the null class.
-  cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate);
+  cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate_group);
   cls.set_num_type_arguments(0);
-  isolate->object_store()->set_null_class(cls);
+  isolate_group->object_store()->set_null_class(cls);
 
   // Allocate and initialize Never class.
-  cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate);
+  cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate_group);
   cls.set_num_type_arguments(0);
   cls.set_is_allocate_finalized();
   cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
-  isolate->object_store()->set_never_class(cls);
+  isolate_group->object_store()->set_never_class(cls);
 
   // Allocate and initialize the free list element class.
-  cls =
-      Class::New<FreeListElement::FakeInstance,
-                 RTN::FreeListElement::FakeInstance>(kFreeListElement, isolate);
+  cls = Class::New<FreeListElement::FakeInstance,
+                   RTN::FreeListElement::FakeInstance>(kFreeListElement,
+                                                       isolate_group);
   cls.set_num_type_arguments(0);
   cls.set_is_allocate_finalized();
   cls.set_is_declaration_loaded();
@@ -748,7 +748,7 @@
   // Allocate and initialize the forwarding corpse class.
   cls = Class::New<ForwardingCorpse::FakeInstance,
                    RTN::ForwardingCorpse::FakeInstance>(kForwardingCorpse,
-                                                        isolate);
+                                                        isolate_group);
   cls.set_num_type_arguments(0);
   cls.set_is_allocate_finalized();
   cls.set_is_declaration_loaded();
@@ -772,146 +772,148 @@
   }
 
   // Allocate the remaining VM internal classes.
-  cls = Class::New<TypeArguments, RTN::TypeArguments>(isolate);
-  type_arguments_class_ = cls.raw();
+  cls = Class::New<TypeArguments, RTN::TypeArguments>(isolate_group);
+  type_arguments_class_ = cls.ptr();
 
-  cls = Class::New<PatchClass, RTN::PatchClass>(isolate);
-  patch_class_class_ = cls.raw();
+  cls = Class::New<PatchClass, RTN::PatchClass>(isolate_group);
+  patch_class_class_ = cls.ptr();
 
-  cls = Class::New<Function, RTN::Function>(isolate);
-  function_class_ = cls.raw();
+  cls = Class::New<Function, RTN::Function>(isolate_group);
+  function_class_ = cls.ptr();
 
-  cls = Class::New<ClosureData, RTN::ClosureData>(isolate);
-  closure_data_class_ = cls.raw();
+  cls = Class::New<ClosureData, RTN::ClosureData>(isolate_group);
+  closure_data_class_ = cls.ptr();
 
-  cls = Class::New<SignatureData, RTN::SignatureData>(isolate);
-  signature_data_class_ = cls.raw();
+  cls = Class::New<FfiTrampolineData, RTN::FfiTrampolineData>(isolate_group);
+  ffi_trampoline_data_class_ = cls.ptr();
 
-  cls = Class::New<FfiTrampolineData, RTN::FfiTrampolineData>(isolate);
-  ffi_trampoline_data_class_ = cls.raw();
+  cls = Class::New<Field, RTN::Field>(isolate_group);
+  field_class_ = cls.ptr();
 
-  cls = Class::New<Field, RTN::Field>(isolate);
-  field_class_ = cls.raw();
+  cls = Class::New<Script, RTN::Script>(isolate_group);
+  script_class_ = cls.ptr();
 
-  cls = Class::New<Script, RTN::Script>(isolate);
-  script_class_ = cls.raw();
+  cls = Class::New<Library, RTN::Library>(isolate_group);
+  library_class_ = cls.ptr();
 
-  cls = Class::New<Library, RTN::Library>(isolate);
-  library_class_ = cls.raw();
+  cls = Class::New<Namespace, RTN::Namespace>(isolate_group);
+  namespace_class_ = cls.ptr();
 
-  cls = Class::New<Namespace, RTN::Namespace>(isolate);
-  namespace_class_ = cls.raw();
+  cls = Class::New<KernelProgramInfo, RTN::KernelProgramInfo>(isolate_group);
+  kernel_program_info_class_ = cls.ptr();
 
-  cls = Class::New<KernelProgramInfo, RTN::KernelProgramInfo>(isolate);
-  kernel_program_info_class_ = cls.raw();
+  cls = Class::New<Code, RTN::Code>(isolate_group);
+  code_class_ = cls.ptr();
 
-  cls = Class::New<Code, RTN::Code>(isolate);
-  code_class_ = cls.raw();
-
-  cls = Class::New<Instructions, RTN::Instructions>(isolate);
-  instructions_class_ = cls.raw();
-
-  cls = Class::New<InstructionsSection, RTN::InstructionsSection>(isolate);
-  instructions_section_class_ = cls.raw();
-
-  cls = Class::New<ObjectPool, RTN::ObjectPool>(isolate);
-  object_pool_class_ = cls.raw();
-
-  cls = Class::New<PcDescriptors, RTN::PcDescriptors>(isolate);
-  pc_descriptors_class_ = cls.raw();
-
-  cls = Class::New<CodeSourceMap, RTN::CodeSourceMap>(isolate);
-  code_source_map_class_ = cls.raw();
-
-  cls = Class::New<CompressedStackMaps, RTN::CompressedStackMaps>(isolate);
-  compressed_stackmaps_class_ = cls.raw();
-
-  cls = Class::New<LocalVarDescriptors, RTN::LocalVarDescriptors>(isolate);
-  var_descriptors_class_ = cls.raw();
-
-  cls = Class::New<ExceptionHandlers, RTN::ExceptionHandlers>(isolate);
-  exception_handlers_class_ = cls.raw();
-
-  cls = Class::New<Context, RTN::Context>(isolate);
-  context_class_ = cls.raw();
-
-  cls = Class::New<ContextScope, RTN::ContextScope>(isolate);
-  context_scope_class_ = cls.raw();
-
-  cls = Class::New<SingleTargetCache, RTN::SingleTargetCache>(isolate);
-  singletargetcache_class_ = cls.raw();
-
-  cls = Class::New<UnlinkedCall, RTN::UnlinkedCall>(isolate);
-  unlinkedcall_class_ = cls.raw();
+  cls = Class::New<Instructions, RTN::Instructions>(isolate_group);
+  instructions_class_ = cls.ptr();
 
   cls =
-      Class::New<MonomorphicSmiableCall, RTN::MonomorphicSmiableCall>(isolate);
-  monomorphicsmiablecall_class_ = cls.raw();
+      Class::New<InstructionsSection, RTN::InstructionsSection>(isolate_group);
+  instructions_section_class_ = cls.ptr();
 
-  cls = Class::New<ICData, RTN::ICData>(isolate);
-  icdata_class_ = cls.raw();
+  cls = Class::New<ObjectPool, RTN::ObjectPool>(isolate_group);
+  object_pool_class_ = cls.ptr();
 
-  cls = Class::New<MegamorphicCache, RTN::MegamorphicCache>(isolate);
-  megamorphic_cache_class_ = cls.raw();
+  cls = Class::New<PcDescriptors, RTN::PcDescriptors>(isolate_group);
+  pc_descriptors_class_ = cls.ptr();
 
-  cls = Class::New<SubtypeTestCache, RTN::SubtypeTestCache>(isolate);
-  subtypetestcache_class_ = cls.raw();
+  cls = Class::New<CodeSourceMap, RTN::CodeSourceMap>(isolate_group);
+  code_source_map_class_ = cls.ptr();
 
-  cls = Class::New<LoadingUnit, RTN::LoadingUnit>(isolate);
-  loadingunit_class_ = cls.raw();
+  cls =
+      Class::New<CompressedStackMaps, RTN::CompressedStackMaps>(isolate_group);
+  compressed_stackmaps_class_ = cls.ptr();
 
-  cls = Class::New<ApiError, RTN::ApiError>(isolate);
-  api_error_class_ = cls.raw();
+  cls =
+      Class::New<LocalVarDescriptors, RTN::LocalVarDescriptors>(isolate_group);
+  var_descriptors_class_ = cls.ptr();
 
-  cls = Class::New<LanguageError, RTN::LanguageError>(isolate);
-  language_error_class_ = cls.raw();
+  cls = Class::New<ExceptionHandlers, RTN::ExceptionHandlers>(isolate_group);
+  exception_handlers_class_ = cls.ptr();
 
-  cls = Class::New<UnhandledException, RTN::UnhandledException>(isolate);
-  unhandled_exception_class_ = cls.raw();
+  cls = Class::New<Context, RTN::Context>(isolate_group);
+  context_class_ = cls.ptr();
 
-  cls = Class::New<UnwindError, RTN::UnwindError>(isolate);
-  unwind_error_class_ = cls.raw();
+  cls = Class::New<ContextScope, RTN::ContextScope>(isolate_group);
+  context_scope_class_ = cls.ptr();
+
+  cls = Class::New<SingleTargetCache, RTN::SingleTargetCache>(isolate_group);
+  singletargetcache_class_ = cls.ptr();
+
+  cls = Class::New<UnlinkedCall, RTN::UnlinkedCall>(isolate_group);
+  unlinkedcall_class_ = cls.ptr();
+
+  cls = Class::New<MonomorphicSmiableCall, RTN::MonomorphicSmiableCall>(
+      isolate_group);
+  monomorphicsmiablecall_class_ = cls.ptr();
+
+  cls = Class::New<ICData, RTN::ICData>(isolate_group);
+  icdata_class_ = cls.ptr();
+
+  cls = Class::New<MegamorphicCache, RTN::MegamorphicCache>(isolate_group);
+  megamorphic_cache_class_ = cls.ptr();
+
+  cls = Class::New<SubtypeTestCache, RTN::SubtypeTestCache>(isolate_group);
+  subtypetestcache_class_ = cls.ptr();
+
+  cls = Class::New<LoadingUnit, RTN::LoadingUnit>(isolate_group);
+  loadingunit_class_ = cls.ptr();
+
+  cls = Class::New<ApiError, RTN::ApiError>(isolate_group);
+  api_error_class_ = cls.ptr();
+
+  cls = Class::New<LanguageError, RTN::LanguageError>(isolate_group);
+  language_error_class_ = cls.ptr();
+
+  cls = Class::New<UnhandledException, RTN::UnhandledException>(isolate_group);
+  unhandled_exception_class_ = cls.ptr();
+
+  cls = Class::New<UnwindError, RTN::UnwindError>(isolate_group);
+  unwind_error_class_ = cls.ptr();
 
   cls = Class::New<WeakSerializationReference, RTN::WeakSerializationReference>(
-      isolate);
-  weak_serialization_reference_class_ = cls.raw();
+      isolate_group);
+  weak_serialization_reference_class_ = cls.ptr();
 
   ASSERT(class_class() != null_);
 
   // Pre-allocate classes in the vm isolate so that we can for example create a
   // symbol table and populate it with some frequently used strings as symbols.
-  cls = Class::New<Array, RTN::Array>(isolate);
-  isolate->object_store()->set_array_class(cls);
+  cls = Class::New<Array, RTN::Array>(isolate_group);
+  isolate_group->object_store()->set_array_class(cls);
   cls.set_type_arguments_field_offset(Array::type_arguments_offset(),
                                       RTN::Array::type_arguments_offset());
   cls.set_num_type_arguments(1);
-  cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate);
-  isolate->object_store()->set_immutable_array_class(cls);
+  cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate_group);
+  isolate_group->object_store()->set_immutable_array_class(cls);
   cls.set_type_arguments_field_offset(Array::type_arguments_offset(),
                                       RTN::Array::type_arguments_offset());
   cls.set_num_type_arguments(1);
-  cls = Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(isolate);
-  isolate->object_store()->set_growable_object_array_class(cls);
+  cls =
+      Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(isolate_group);
+  isolate_group->object_store()->set_growable_object_array_class(cls);
   cls.set_type_arguments_field_offset(
       GrowableObjectArray::type_arguments_offset(),
       RTN::GrowableObjectArray::type_arguments_offset());
   cls.set_num_type_arguments(1);
-  cls = Class::NewStringClass(kOneByteStringCid, isolate);
-  isolate->object_store()->set_one_byte_string_class(cls);
-  cls = Class::NewStringClass(kTwoByteStringCid, isolate);
-  isolate->object_store()->set_two_byte_string_class(cls);
-  cls = Class::New<Mint, RTN::Mint>(isolate);
-  isolate->object_store()->set_mint_class(cls);
-  cls = Class::New<Double, RTN::Double>(isolate);
-  isolate->object_store()->set_double_class(cls);
+  cls = Class::NewStringClass(kOneByteStringCid, isolate_group);
+  isolate_group->object_store()->set_one_byte_string_class(cls);
+  cls = Class::NewStringClass(kTwoByteStringCid, isolate_group);
+  isolate_group->object_store()->set_two_byte_string_class(cls);
+  cls = Class::New<Mint, RTN::Mint>(isolate_group);
+  isolate_group->object_store()->set_mint_class(cls);
+  cls = Class::New<Double, RTN::Double>(isolate_group);
+  isolate_group->object_store()->set_double_class(cls);
 
   // Ensure that class kExternalTypedDataUint8ArrayCid is registered as we
   // need it when reading in the token stream of bootstrap classes in the VM
   // isolate.
-  Class::NewExternalTypedDataClass(kExternalTypedDataUint8ArrayCid, isolate);
+  Class::NewExternalTypedDataClass(kExternalTypedDataUint8ArrayCid,
+                                   isolate_group);
 
   // Needed for object pools of VM isolate stubs.
-  Class::NewTypedDataClass(kTypedDataInt8ArrayCid, isolate);
+  Class::NewTypedDataClass(kTypedDataInt8ArrayCid, isolate_group);
 
   // Allocate and initialize the empty_array instance.
   {
@@ -919,7 +921,7 @@
     InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(0));
     Array::initializeHandle(empty_array_,
                             static_cast<ArrayPtr>(address + kHeapObjectTag));
-    empty_array_->raw_ptr()->set_length(Smi::New(0));
+    empty_array_->untag()->set_length(Smi::New(0));
     empty_array_->SetCanonical();
   }
 
@@ -930,7 +932,7 @@
     InitializeObject(address, kImmutableArrayCid, Array::InstanceSize(1));
     Array::initializeHandle(zero_array_,
                             static_cast<ArrayPtr>(address + kHeapObjectTag));
-    zero_array_->raw_ptr()->set_length(Smi::New(1));
+    zero_array_->untag()->set_length(Smi::New(1));
     smi = Smi::New(0);
     zero_array_->SetAt(0, smi);
     zero_array_->SetCanonical();
@@ -944,9 +946,9 @@
         empty_context_scope_,
         static_cast<ContextScopePtr>(address + kHeapObjectTag));
     empty_context_scope_->StoreNonPointer(
-        &empty_context_scope_->raw_ptr()->num_variables_, 0);
+        &empty_context_scope_->untag()->num_variables_, 0);
     empty_context_scope_->StoreNonPointer(
-        &empty_context_scope_->raw_ptr()->is_implicit_, true);
+        &empty_context_scope_->untag()->is_implicit_, true);
     empty_context_scope_->SetCanonical();
   }
 
@@ -957,7 +959,7 @@
     ObjectPool::initializeHandle(
         empty_object_pool_,
         static_cast<ObjectPoolPtr>(address + kHeapObjectTag));
-    empty_object_pool_->StoreNonPointer(&empty_object_pool_->raw_ptr()->length_,
+    empty_object_pool_->StoreNonPointer(&empty_object_pool_->untag()->length_,
                                         0);
     empty_object_pool_->SetCanonical();
   }
@@ -971,7 +973,7 @@
         empty_compressed_stackmaps_,
         static_cast<CompressedStackMapsPtr>(address + kHeapObjectTag));
     empty_compressed_stackmaps_->StoreNonPointer(
-        &empty_compressed_stackmaps_->raw_ptr()->flags_and_size_, 0);
+        &empty_compressed_stackmaps_->untag()->flags_and_size_, 0);
     empty_compressed_stackmaps_->SetCanonical();
   }
 
@@ -983,7 +985,7 @@
     PcDescriptors::initializeHandle(
         empty_descriptors_,
         static_cast<PcDescriptorsPtr>(address + kHeapObjectTag));
-    empty_descriptors_->StoreNonPointer(&empty_descriptors_->raw_ptr()->length_,
+    empty_descriptors_->StoreNonPointer(&empty_descriptors_->untag()->length_,
                                         0);
     empty_descriptors_->SetCanonical();
   }
@@ -998,7 +1000,7 @@
         empty_var_descriptors_,
         static_cast<LocalVarDescriptorsPtr>(address + kHeapObjectTag));
     empty_var_descriptors_->StoreNonPointer(
-        &empty_var_descriptors_->raw_ptr()->num_entries_, 0);
+        &empty_var_descriptors_->untag()->num_entries_, 0);
     empty_var_descriptors_->SetCanonical();
   }
 
@@ -1014,7 +1016,7 @@
         empty_exception_handlers_,
         static_cast<ExceptionHandlersPtr>(address + kHeapObjectTag));
     empty_exception_handlers_->StoreNonPointer(
-        &empty_exception_handlers_->raw_ptr()->num_entries_, 0);
+        &empty_exception_handlers_->untag()->num_entries_, 0);
     empty_exception_handlers_->SetCanonical();
   }
 
@@ -1026,46 +1028,46 @@
     TypeArguments::initializeHandle(
         empty_type_arguments_,
         static_cast<TypeArgumentsPtr>(address + kHeapObjectTag));
-    empty_type_arguments_->raw_ptr()->set_length(Smi::New(0));
-    empty_type_arguments_->raw_ptr()->set_hash(Smi::New(0));
+    empty_type_arguments_->untag()->set_length(Smi::New(0));
+    empty_type_arguments_->untag()->set_hash(Smi::New(0));
     empty_type_arguments_->ComputeHash();
     empty_type_arguments_->SetCanonical();
   }
 
   // The VM isolate snapshot object table is initialized to an empty array
   // as we do not have any VM isolate snapshot at this time.
-  *vm_isolate_snapshot_object_table_ = Object::empty_array().raw();
+  *vm_isolate_snapshot_object_table_ = Object::empty_array().ptr();
 
-  cls = Class::New<Instance, RTN::Instance>(kDynamicCid, isolate);
+  cls = Class::New<Instance, RTN::Instance>(kDynamicCid, isolate_group);
   cls.set_is_abstract();
   cls.set_num_type_arguments(0);
   cls.set_is_allocate_finalized();
   cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
-  dynamic_class_ = cls.raw();
+  dynamic_class_ = cls.ptr();
 
-  cls = Class::New<Instance, RTN::Instance>(kVoidCid, isolate);
+  cls = Class::New<Instance, RTN::Instance>(kVoidCid, isolate_group);
   cls.set_num_type_arguments(0);
   cls.set_is_allocate_finalized();
   cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
-  void_class_ = cls.raw();
+  void_class_ = cls.ptr();
 
-  cls = Class::New<Type, RTN::Type>(isolate);
+  cls = Class::New<Type, RTN::Type>(isolate_group);
   cls.set_is_allocate_finalized();
   cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
 
   cls = dynamic_class_;
-  *dynamic_type_ = Type::New(cls, Object::null_type_arguments(),
-                             TokenPosition::kNoSource, Nullability::kNullable);
+  *dynamic_type_ =
+      Type::New(cls, Object::null_type_arguments(), Nullability::kNullable);
   dynamic_type_->SetIsFinalized();
   dynamic_type_->ComputeHash();
   dynamic_type_->SetCanonical();
 
   cls = void_class_;
-  *void_type_ = Type::New(cls, Object::null_type_arguments(),
-                          TokenPosition::kNoSource, Nullability::kNullable);
+  *void_type_ =
+      Type::New(cls, Object::null_type_arguments(), Nullability::kNullable);
   void_type_->SetIsFinalized();
   void_type_->ComputeHash();
   void_type_->SetCanonical();
@@ -1083,8 +1085,8 @@
     cls.SetFunctions(Object::empty_array());
   }
 
-  cls = Class::New<Bool, RTN::Bool>(isolate);
-  isolate->object_store()->set_bool_class(cls);
+  cls = Class::New<Bool, RTN::Bool>(isolate_group);
+  isolate_group->object_store()->set_bool_class(cls);
 
   *smi_illegal_cid_ = Smi::New(kIllegalCid);
   *smi_zero_ = Smi::New(0);
@@ -1128,6 +1130,8 @@
   thr->clear_pending_functions();
 
   ASSERT(!null_object_->IsSmi());
+  ASSERT(!null_class_->IsSmi());
+  ASSERT(null_class_->IsClass());
   ASSERT(!null_array_->IsSmi());
   ASSERT(null_array_->IsArray());
   ASSERT(!null_string_->IsSmi());
@@ -1136,6 +1140,8 @@
   ASSERT(null_instance_->IsInstance());
   ASSERT(!null_function_->IsSmi());
   ASSERT(null_function_->IsFunction());
+  ASSERT(!null_function_type_->IsSmi());
+  ASSERT(null_function_type_->IsFunctionType());
   ASSERT(!null_type_arguments_->IsSmi());
   ASSERT(null_type_arguments_->IsTypeArguments());
   ASSERT(!null_compressed_stackmaps_->IsSmi());
@@ -1190,7 +1196,7 @@
   ASSERT(extractor_parameter_names_->IsArray());
 }
 
-void Object::FinishInit(Isolate* isolate) {
+void Object::FinishInit(IsolateGroup* isolate_group) {
   // The type testing stubs we initialize in AbstractType objects for the
   // canonical type of kDynamicCid/kVoidCid need to be set in this
   // method, which is called after StubCode::InitOnce().
@@ -1214,7 +1220,6 @@
   patch_class_class_ = static_cast<ClassPtr>(RAW_NULL);
   function_class_ = static_cast<ClassPtr>(RAW_NULL);
   closure_data_class_ = static_cast<ClassPtr>(RAW_NULL);
-  signature_data_class_ = static_cast<ClassPtr>(RAW_NULL);
   ffi_trampoline_data_class_ = static_cast<ClassPtr>(RAW_NULL);
   field_class_ = static_cast<ClassPtr>(RAW_NULL);
   script_class_ = static_cast<ClassPtr>(RAW_NULL);
@@ -1260,11 +1265,11 @@
 
   void VisitObject(ObjectPtr obj) {
     // Free list elements should never be marked.
-    ASSERT(!obj->ptr()->IsMarked());
+    ASSERT(!obj->untag()->IsMarked());
     // No forwarding corpses in the VM isolate.
     ASSERT(!obj->IsForwardingCorpse());
     if (!obj->IsFreeListElement()) {
-      obj->ptr()->SetMarkBitUnsynchronized();
+      obj->untag()->SetMarkBitUnsynchronized();
       Object::FinalizeReadOnlyObject(obj);
 #if defined(HASH_IN_OBJECT_HEADER)
       // These objects end up in the read-only VM isolate which is shared
@@ -1296,9 +1301,9 @@
   cls = class_name##_class();                                                  \
   cls.set_name(Symbols::name());
 
-void Object::FinalizeVMIsolate(Isolate* isolate) {
+void Object::FinalizeVMIsolate(IsolateGroup* isolate_group) {
   // Should only be run by the vm isolate.
-  ASSERT(isolate == Dart::vm_isolate());
+  ASSERT(isolate_group == Dart::vm_isolate_group());
 
   // Finish initialization of extractor_parameter_names_ which was
   // Started in Object::InitOnce()
@@ -1314,7 +1319,6 @@
   SET_CLASS_NAME(patch_class, PatchClass);
   SET_CLASS_NAME(function, Function);
   SET_CLASS_NAME(closure_data, ClosureData);
-  SET_CLASS_NAME(signature_data, SignatureData);
   SET_CLASS_NAME(ffi_trampoline_data, FfiTrampolineData);
   SET_CLASS_NAME(field, Field);
   SET_CLASS_NAME(script, Script);
@@ -1345,27 +1349,27 @@
   SET_CLASS_NAME(unwind_error, UnwindError);
 
   // Set up names for classes which are also pre-allocated in the vm isolate.
-  cls = isolate->object_store()->array_class();
+  cls = isolate_group->object_store()->array_class();
   cls.set_name(Symbols::_List());
-  cls = isolate->object_store()->one_byte_string_class();
+  cls = isolate_group->object_store()->one_byte_string_class();
   cls.set_name(Symbols::OneByteString());
-  cls = isolate->object_store()->never_class();
+  cls = isolate_group->object_store()->never_class();
   cls.set_name(Symbols::Never());
 
   // Set up names for the pseudo-classes for free list elements and forwarding
   // corpses. Mainly this makes VM debugging easier.
-  cls = isolate->class_table()->At(kFreeListElement);
+  cls = isolate_group->class_table()->At(kFreeListElement);
   cls.set_name(Symbols::FreeListElement());
-  cls = isolate->class_table()->At(kForwardingCorpse);
+  cls = isolate_group->class_table()->At(kForwardingCorpse);
   cls.set_name(Symbols::ForwardingCorpse());
 
   {
-    ASSERT(isolate == Dart::vm_isolate());
+    ASSERT(isolate_group == Dart::vm_isolate_group());
     Thread* thread = Thread::Current();
     WritableVMIsolateScope scope(thread);
     HeapIterationScope iteration(thread);
     FinalizeVMIsolateVisitor premarker;
-    ASSERT(isolate->heap()->UsedInWords(Heap::kNew) == 0);
+    ASSERT(isolate_group->heap()->UsedInWords(Heap::kNew) == 0);
     iteration.IterateOldObjectsNoImagePages(&premarker);
     // Make the VM isolate read-only again after setting all objects as marked.
     // Note objects in image pages are already pre-marked.
@@ -1382,9 +1386,9 @@
       String::SetCachedHash(str, hash);
     }
     intptr_t size = OneByteString::UnroundedSize(str);
-    ASSERT(size <= str->ptr()->HeapSize());
-    memset(reinterpret_cast<void*>(ObjectLayout::ToAddr(str) + size), 0,
-           str->ptr()->HeapSize() - size);
+    ASSERT(size <= str->untag()->HeapSize());
+    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(str) + size), 0,
+           str->untag()->HeapSize() - size);
   } else if (cid == kTwoByteStringCid) {
     TwoByteStringPtr str = static_cast<TwoByteStringPtr>(object);
     if (String::GetCachedHash(str) == 0) {
@@ -1393,9 +1397,9 @@
     }
     ASSERT(String::GetCachedHash(str) != 0);
     intptr_t size = TwoByteString::UnroundedSize(str);
-    ASSERT(size <= str->ptr()->HeapSize());
-    memset(reinterpret_cast<void*>(ObjectLayout::ToAddr(str) + size), 0,
-           str->ptr()->HeapSize() - size);
+    ASSERT(size <= str->untag()->HeapSize());
+    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(str) + size), 0,
+           str->untag()->HeapSize() - size);
   } else if (cid == kExternalOneByteStringCid) {
     ExternalOneByteStringPtr str =
         static_cast<ExternalOneByteStringPtr>(object);
@@ -1413,27 +1417,27 @@
   } else if (cid == kCodeSourceMapCid) {
     CodeSourceMapPtr map = CodeSourceMap::RawCast(object);
     intptr_t size = CodeSourceMap::UnroundedSize(map);
-    ASSERT(size <= map->ptr()->HeapSize());
-    memset(reinterpret_cast<void*>(ObjectLayout::ToAddr(map) + size), 0,
-           map->ptr()->HeapSize() - size);
+    ASSERT(size <= map->untag()->HeapSize());
+    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(map) + size), 0,
+           map->untag()->HeapSize() - size);
   } else if (cid == kCompressedStackMapsCid) {
     CompressedStackMapsPtr maps = CompressedStackMaps::RawCast(object);
     intptr_t size = CompressedStackMaps::UnroundedSize(maps);
-    ASSERT(size <= maps->ptr()->HeapSize());
-    memset(reinterpret_cast<void*>(ObjectLayout::ToAddr(maps) + size), 0,
-           maps->ptr()->HeapSize() - size);
+    ASSERT(size <= maps->untag()->HeapSize());
+    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(maps) + size), 0,
+           maps->untag()->HeapSize() - size);
   } else if (cid == kPcDescriptorsCid) {
     PcDescriptorsPtr desc = PcDescriptors::RawCast(object);
     intptr_t size = PcDescriptors::UnroundedSize(desc);
-    ASSERT(size <= desc->ptr()->HeapSize());
-    memset(reinterpret_cast<void*>(ObjectLayout::ToAddr(desc) + size), 0,
-           desc->ptr()->HeapSize() - size);
+    ASSERT(size <= desc->untag()->HeapSize());
+    memset(reinterpret_cast<void*>(UntaggedObject::ToAddr(desc) + size), 0,
+           desc->untag()->HeapSize() - size);
   }
 }
 
 void Object::set_vm_isolate_snapshot_object_table(const Array& table) {
   ASSERT(Isolate::Current() == Dart::vm_isolate());
-  *vm_isolate_snapshot_object_table_ = table.raw();
+  *vm_isolate_snapshot_object_table_ = table.ptr();
 }
 
 // Make unused space in an object whose type has been transformed safe
@@ -1449,47 +1453,49 @@
   if (original_size > used_size) {
     intptr_t leftover_size = original_size - used_size;
 
-    uword addr = ObjectLayout::ToAddr(obj.raw()) + used_size;
+    uword addr = UntaggedObject::ToAddr(obj.ptr()) + used_size;
     if (leftover_size >= TypedData::InstanceSize(0)) {
       // Update the leftover space as a TypedDataInt8Array object.
       TypedDataPtr raw =
-          static_cast<TypedDataPtr>(ObjectLayout::FromAddr(addr));
+          static_cast<TypedDataPtr>(UntaggedObject::FromAddr(addr));
       uword new_tags =
-          ObjectLayout::ClassIdTag::update(kTypedDataInt8ArrayCid, 0);
-      new_tags = ObjectLayout::SizeTag::update(leftover_size, new_tags);
-      const bool is_old = obj.raw()->IsOldObject();
-      new_tags = ObjectLayout::OldBit::update(is_old, new_tags);
-      new_tags = ObjectLayout::OldAndNotMarkedBit::update(is_old, new_tags);
-      new_tags = ObjectLayout::OldAndNotRememberedBit::update(is_old, new_tags);
-      new_tags = ObjectLayout::NewBit::update(!is_old, new_tags);
+          UntaggedObject::ClassIdTag::update(kTypedDataInt8ArrayCid, 0);
+      new_tags = UntaggedObject::SizeTag::update(leftover_size, new_tags);
+      const bool is_old = obj.ptr()->IsOldObject();
+      new_tags = UntaggedObject::OldBit::update(is_old, new_tags);
+      new_tags = UntaggedObject::OldAndNotMarkedBit::update(is_old, new_tags);
+      new_tags =
+          UntaggedObject::OldAndNotRememberedBit::update(is_old, new_tags);
+      new_tags = UntaggedObject::NewBit::update(!is_old, new_tags);
       // On architectures with a relaxed memory model, the concurrent marker may
       // observe the write of the filler object's header before observing the
       // new array length, and so treat it as a pointer. Ensure it is a Smi so
       // the marker won't dereference it.
       ASSERT((new_tags & kSmiTagMask) == kSmiTag);
-      raw->ptr()->tags_ = new_tags;
+      raw->untag()->tags_ = new_tags;
 
       intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0));
       ASSERT(TypedData::InstanceSize(leftover_len) == leftover_size);
-      raw->ptr()->set_length(Smi::New(leftover_len));
-      raw->ptr()->RecomputeDataField();
+      raw->untag()->set_length(Smi::New(leftover_len));
+      raw->untag()->RecomputeDataField();
     } else {
       // Update the leftover space as a basic object.
       ASSERT(leftover_size == Object::InstanceSize());
-      ObjectPtr raw = static_cast<ObjectPtr>(ObjectLayout::FromAddr(addr));
-      uword new_tags = ObjectLayout::ClassIdTag::update(kInstanceCid, 0);
-      new_tags = ObjectLayout::SizeTag::update(leftover_size, new_tags);
-      const bool is_old = obj.raw()->IsOldObject();
-      new_tags = ObjectLayout::OldBit::update(is_old, new_tags);
-      new_tags = ObjectLayout::OldAndNotMarkedBit::update(is_old, new_tags);
-      new_tags = ObjectLayout::OldAndNotRememberedBit::update(is_old, new_tags);
-      new_tags = ObjectLayout::NewBit::update(!is_old, new_tags);
+      ObjectPtr raw = static_cast<ObjectPtr>(UntaggedObject::FromAddr(addr));
+      uword new_tags = UntaggedObject::ClassIdTag::update(kInstanceCid, 0);
+      new_tags = UntaggedObject::SizeTag::update(leftover_size, new_tags);
+      const bool is_old = obj.ptr()->IsOldObject();
+      new_tags = UntaggedObject::OldBit::update(is_old, new_tags);
+      new_tags = UntaggedObject::OldAndNotMarkedBit::update(is_old, new_tags);
+      new_tags =
+          UntaggedObject::OldAndNotRememberedBit::update(is_old, new_tags);
+      new_tags = UntaggedObject::NewBit::update(!is_old, new_tags);
       // On architectures with a relaxed memory model, the concurrent marker may
       // observe the write of the filler object's header before observing the
       // new array length, and so treat it as a pointer. Ensure it is a Smi so
       // the marker won't dereference it.
       ASSERT((new_tags & kSmiTagMask) == kSmiTag);
-      raw->ptr()->tags_ = new_tags;
+      raw->untag()->tags_ = new_tags;
     }
   }
 }
@@ -1499,7 +1505,7 @@
   ASSERT(builtin_vtables_[kIllegalCid] == 0);
   ASSERT(builtin_vtables_[kFreeListElement] == 0);
   ASSERT(builtin_vtables_[kForwardingCorpse] == 0);
-  ClassTable* table = Isolate::Current()->class_table();
+  ClassTable* table = IsolateGroup::Current()->class_table();
   for (intptr_t cid = kObjectCid; cid < kNumPredefinedCids; cid++) {
     if (table->HasValidClassAt(cid)) {
       ASSERT(builtin_vtables_[cid] != 0);
@@ -1538,12 +1544,12 @@
 //
 // A non-NULL kernel argument indicates (1).
 // A NULL kernel indicates (2) or (3).
-ErrorPtr Object::Init(Isolate* isolate,
+ErrorPtr Object::Init(IsolateGroup* isolate_group,
                       const uint8_t* kernel_buffer,
                       intptr_t kernel_buffer_size) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  ASSERT(isolate == thread->isolate());
+  ASSERT(isolate_group == thread->isolate_group());
   TIMELINE_DURATION(thread, Isolate, "Object::Init");
 
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -1560,8 +1566,8 @@
     // Kernel binary.
     // This will initialize isolate group object_store, shared by all isolates
     // running in the isolate group.
-    ObjectStore* object_store = isolate->object_store();
-    SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+    ObjectStore* object_store = isolate_group->object_store();
+    SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
 
     Class& cls = Class::Handle(zone);
     Type& type = Type::Handle(zone);
@@ -1571,7 +1577,7 @@
 
     // All RawArray fields will be initialized to an empty array, therefore
     // initialize array class first.
-    cls = Class::New<Array, RTN::Array>(isolate);
+    cls = Class::New<Array, RTN::Array>(isolate_group);
     ASSERT(object_store->array_class() == Class::null());
     object_store->set_array_class(cls);
 
@@ -1586,7 +1592,8 @@
 
     // Set up the growable object array class (Has to be done after the array
     // class is setup as one of its field is an array object).
-    cls = Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(isolate);
+    cls = Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(
+        isolate_group);
     object_store->set_growable_object_array_class(cls);
     cls.set_type_arguments_field_offset(
         GrowableObjectArray::type_arguments_offset(),
@@ -1599,6 +1606,12 @@
                                               Heap::kOld);
     object_store->set_canonical_types(array);
 
+    // Initialize hash set for canonical function types.
+    const intptr_t kInitialCanonicalFunctionTypeSize = 16;
+    array = HashTables::New<CanonicalFunctionTypeSet>(
+        kInitialCanonicalFunctionTypeSize, Heap::kOld);
+    object_store->set_canonical_function_types(array);
+
     // Initialize hash set for canonical type parameters.
     const intptr_t kInitialCanonicalTypeParameterSize = 4;
     array = HashTables::New<CanonicalTypeParameterSet>(
@@ -1613,24 +1626,26 @@
 
     // Setup type class early in the process.
     const Class& type_cls =
-        Class::Handle(zone, Class::New<Type, RTN::Type>(isolate));
+        Class::Handle(zone, Class::New<Type, RTN::Type>(isolate_group));
+    const Class& function_type_cls = Class::Handle(
+        zone, Class::New<FunctionType, RTN::FunctionType>(isolate_group));
     const Class& type_ref_cls =
-        Class::Handle(zone, Class::New<TypeRef, RTN::TypeRef>(isolate));
+        Class::Handle(zone, Class::New<TypeRef, RTN::TypeRef>(isolate_group));
     const Class& type_parameter_cls = Class::Handle(
-        zone, Class::New<TypeParameter, RTN::TypeParameter>(isolate));
+        zone, Class::New<TypeParameter, RTN::TypeParameter>(isolate_group));
     const Class& library_prefix_cls = Class::Handle(
-        zone, Class::New<LibraryPrefix, RTN::LibraryPrefix>(isolate));
+        zone, Class::New<LibraryPrefix, RTN::LibraryPrefix>(isolate_group));
 
     // Pre-allocate the OneByteString class needed by the symbol table.
-    cls = Class::NewStringClass(kOneByteStringCid, isolate);
+    cls = Class::NewStringClass(kOneByteStringCid, isolate_group);
     object_store->set_one_byte_string_class(cls);
 
     // Pre-allocate the TwoByteString class needed by the symbol table.
-    cls = Class::NewStringClass(kTwoByteStringCid, isolate);
+    cls = Class::NewStringClass(kTwoByteStringCid, isolate_group);
     object_store->set_two_byte_string_class(cls);
 
     // Setup the symbol table for the symbols created in the isolate.
-    Symbols::SetupSymbolTable(isolate);
+    Symbols::SetupSymbolTable(isolate_group);
 
     // Set up the libraries array before initializing the core library.
     const GrowableObjectArray& libraries =
@@ -1638,7 +1653,7 @@
     object_store->set_libraries(libraries);
 
     // Pre-register the core library.
-    Library::InitCoreLibrary(isolate);
+    Library::InitCoreLibrary(isolate_group);
 
     // Basic infrastructure has been setup, initialize the class dictionary.
     const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
@@ -1660,9 +1675,8 @@
     // declared number of type parameters is still 0. It will become 1 after
     // patching. The array type allocated below represents the raw type _List
     // and not _List<E> as we could expect. Use with caution.
-    type =
-        Type::New(Class::Handle(zone, cls.raw()), TypeArguments::Handle(zone),
-                  TokenPosition::kNoSource, Nullability::kNonNullable);
+    type = Type::New(Class::Handle(zone, cls.ptr()),
+                     TypeArguments::Handle(zone), Nullability::kNonNullable);
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
     object_store->set_array_type(type);
@@ -1675,7 +1689,7 @@
     RegisterPrivateClass(cls, Symbols::_GrowableList(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate);
+    cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate_group);
     object_store->set_immutable_array_class(cls);
     cls.set_type_arguments_field_offset(Array::type_arguments_offset(),
                                         RTN::Array::type_arguments_offset());
@@ -1694,12 +1708,12 @@
     RegisterPrivateClass(cls, Symbols::TwoByteString(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::NewStringClass(kExternalOneByteStringCid, isolate);
+    cls = Class::NewStringClass(kExternalOneByteStringCid, isolate_group);
     object_store->set_external_one_byte_string_class(cls);
     RegisterPrivateClass(cls, Symbols::ExternalOneByteString(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::NewStringClass(kExternalTwoByteStringCid, isolate);
+    cls = Class::NewStringClass(kExternalTwoByteStringCid, isolate_group);
     object_store->set_external_two_byte_string_class(cls);
     RegisterPrivateClass(cls, Symbols::ExternalTwoByteString(), core_lib);
     pending_classes.Add(cls);
@@ -1715,43 +1729,42 @@
     }
     object_store->set_bootstrap_library(ObjectStore::kIsolate, isolate_lib);
     ASSERT(!isolate_lib.IsNull());
-    ASSERT(isolate_lib.raw() == Library::IsolateLibrary());
+    ASSERT(isolate_lib.ptr() == Library::IsolateLibrary());
 
-    cls = Class::New<Capability, RTN::Capability>(isolate);
+    cls = Class::New<Capability, RTN::Capability>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_CapabilityImpl(), isolate_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<ReceivePort, RTN::ReceivePort>(isolate);
+    cls = Class::New<ReceivePort, RTN::ReceivePort>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_RawReceivePortImpl(), isolate_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<SendPort, RTN::SendPort>(isolate);
+    cls = Class::New<SendPort, RTN::SendPort>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_SendPortImpl(), isolate_lib);
     pending_classes.Add(cls);
 
-    cls =
-        Class::New<TransferableTypedData, RTN::TransferableTypedData>(isolate);
+    cls = Class::New<TransferableTypedData, RTN::TransferableTypedData>(
+        isolate_group);
     RegisterPrivateClass(cls, Symbols::_TransferableTypedDataImpl(),
                          isolate_lib);
     pending_classes.Add(cls);
 
-    const Class& stacktrace_cls =
-        Class::Handle(zone, Class::New<StackTrace, RTN::StackTrace>(isolate));
+    const Class& stacktrace_cls = Class::Handle(
+        zone, Class::New<StackTrace, RTN::StackTrace>(isolate_group));
     RegisterPrivateClass(stacktrace_cls, Symbols::_StackTrace(), core_lib);
     pending_classes.Add(stacktrace_cls);
     // Super type set below, after Object is allocated.
 
-    cls = Class::New<RegExp, RTN::RegExp>(isolate);
+    cls = Class::New<RegExp, RTN::RegExp>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_RegExp(), core_lib);
     pending_classes.Add(cls);
 
     // Initialize the base interfaces used by the core VM classes.
 
     // Allocate and initialize the pre-allocated classes in the core library.
-    // The script and token index of these pre-allocated classes is set up in
-    // the parser when the corelib script is compiled (see
-    // Parser::ParseClassDefinition).
-    cls = Class::New<Instance, RTN::Instance>(kInstanceCid, isolate);
+    // The script and token index of these pre-allocated classes is set up when
+    // the corelib script is compiled.
+    cls = Class::New<Instance, RTN::Instance>(kInstanceCid, isolate_group);
     object_store->set_object_class(cls);
     cls.set_name(Symbols::Object());
     cls.set_num_type_arguments(0);
@@ -1760,27 +1773,31 @@
     core_lib.AddClass(cls);
     pending_classes.Add(cls);
     type = Type::NewNonParameterizedType(cls);
+    ASSERT(type.IsCanonical());
     object_store->set_object_type(type);
     type = type.ToNullability(Nullability::kLegacy, Heap::kOld);
+    ASSERT(type.IsCanonical());
     object_store->set_legacy_object_type(type);
     type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
+    ASSERT(type.IsCanonical());
     object_store->set_non_nullable_object_type(type);
     type = type.ToNullability(Nullability::kNullable, Heap::kOld);
+    ASSERT(type.IsCanonical());
     object_store->set_nullable_object_type(type);
 
-    cls = Class::New<Bool, RTN::Bool>(isolate);
+    cls = Class::New<Bool, RTN::Bool>(isolate_group);
     object_store->set_bool_class(cls);
     RegisterClass(cls, Symbols::Bool(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate_group);
     object_store->set_null_class(cls);
     cls.set_num_type_arguments(0);
     cls.set_is_prefinalized();
     RegisterClass(cls, Symbols::Null(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate_group);
     cls.set_num_type_arguments(0);
     cls.set_is_allocate_finalized();
     cls.set_is_declaration_loaded();
@@ -1796,6 +1813,9 @@
     RegisterPrivateClass(type_cls, Symbols::_Type(), core_lib);
     pending_classes.Add(type_cls);
 
+    RegisterPrivateClass(function_type_cls, Symbols::_FunctionType(), core_lib);
+    pending_classes.Add(function_type_cls);
+
     RegisterPrivateClass(type_ref_cls, Symbols::_TypeRef(), core_lib);
     pending_classes.Add(type_ref_cls);
 
@@ -1803,39 +1823,38 @@
                          core_lib);
     pending_classes.Add(type_parameter_cls);
 
-    cls = Class::New<Integer, RTN::Integer>(isolate);
+    cls = Class::New<Integer, RTN::Integer>(isolate_group);
     object_store->set_integer_implementation_class(cls);
     RegisterPrivateClass(cls, Symbols::_IntegerImplementation(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<Smi, RTN::Smi>(isolate);
+    cls = Class::New<Smi, RTN::Smi>(isolate_group);
     object_store->set_smi_class(cls);
     RegisterPrivateClass(cls, Symbols::_Smi(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<Mint, RTN::Mint>(isolate);
+    cls = Class::New<Mint, RTN::Mint>(isolate_group);
     object_store->set_mint_class(cls);
     RegisterPrivateClass(cls, Symbols::_Mint(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<Double, RTN::Double>(isolate);
+    cls = Class::New<Double, RTN::Double>(isolate_group);
     object_store->set_double_class(cls);
     RegisterPrivateClass(cls, Symbols::_Double(), core_lib);
     pending_classes.Add(cls);
 
     // Class that represents the Dart class _Closure and C++ class Closure.
-    cls = Class::New<Closure, RTN::Closure>(isolate);
+    cls = Class::New<Closure, RTN::Closure>(isolate_group);
     object_store->set_closure_class(cls);
     RegisterPrivateClass(cls, Symbols::_Closure(), core_lib);
     pending_classes.Add(cls);
 
-    cls = Class::New<WeakProperty, RTN::WeakProperty>(isolate);
+    cls = Class::New<WeakProperty, RTN::WeakProperty>(isolate_group);
     object_store->set_weak_property_class(cls);
     RegisterPrivateClass(cls, Symbols::_WeakProperty(), core_lib);
 
-// Pre-register the mirrors library so we can place the vm class
-// MirrorReference there rather than the core library.
-#if !defined(DART_PRECOMPILED_RUNTIME)
+    // Pre-register the mirrors library so we can place the vm class
+    // MirrorReference there rather than the core library.
     lib = Library::LookupLibrary(thread, Symbols::DartMirrors());
     if (lib.IsNull()) {
       lib = Library::NewLibraryHelper(Symbols::DartMirrors(), true);
@@ -1844,11 +1863,10 @@
     }
     object_store->set_bootstrap_library(ObjectStore::kMirrors, lib);
     ASSERT(!lib.IsNull());
-    ASSERT(lib.raw() == Library::MirrorsLibrary());
+    ASSERT(lib.ptr() == Library::MirrorsLibrary());
 
-    cls = Class::New<MirrorReference, RTN::MirrorReference>(isolate);
+    cls = Class::New<MirrorReference, RTN::MirrorReference>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_MirrorReference(), lib);
-#endif
 
     // Pre-register the collection library so we can place the vm class
     // LinkedHashMap there rather than the core library.
@@ -1861,8 +1879,8 @@
 
     object_store->set_bootstrap_library(ObjectStore::kCollection, lib);
     ASSERT(!lib.IsNull());
-    ASSERT(lib.raw() == Library::CollectionLibrary());
-    cls = Class::New<LinkedHashMap, RTN::LinkedHashMap>(isolate);
+    ASSERT(lib.ptr() == Library::CollectionLibrary());
+    cls = Class::New<LinkedHashMap, RTN::LinkedHashMap>(isolate_group);
     object_store->set_linked_hash_map_class(cls);
     cls.set_type_arguments_field_offset(
         LinkedHashMap::type_arguments_offset(),
@@ -1881,8 +1899,8 @@
     }
     object_store->set_bootstrap_library(ObjectStore::kAsync, lib);
     ASSERT(!lib.IsNull());
-    ASSERT(lib.raw() == Library::AsyncLibrary());
-    cls = Class::New<FutureOr, RTN::FutureOr>(isolate);
+    ASSERT(lib.ptr() == Library::AsyncLibrary());
+    cls = Class::New<FutureOr, RTN::FutureOr>(isolate_group);
     cls.set_type_arguments_field_offset(FutureOr::type_arguments_offset(),
                                         RTN::FutureOr::type_arguments_offset());
     cls.set_num_type_arguments(1);
@@ -1899,14 +1917,14 @@
     }
     object_store->set_bootstrap_library(ObjectStore::kDeveloper, lib);
     ASSERT(!lib.IsNull());
-    ASSERT(lib.raw() == Library::DeveloperLibrary());
-    cls = Class::New<UserTag, RTN::UserTag>(isolate);
+    ASSERT(lib.ptr() == Library::DeveloperLibrary());
+    cls = Class::New<UserTag, RTN::UserTag>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_UserTag(), lib);
     pending_classes.Add(cls);
 
     // Setup some default native field classes which can be extended for
     // specifying native fields in dart classes.
-    Library::InitNativeWrappersLibrary(isolate, is_kernel);
+    Library::InitNativeWrappersLibrary(isolate_group, is_kernel);
     ASSERT(object_store->native_wrappers_library() != Library::null());
 
     // Pre-register the typed_data library so the native class implementations
@@ -1919,47 +1937,48 @@
     }
     object_store->set_bootstrap_library(ObjectStore::kTypedData, lib);
     ASSERT(!lib.IsNull());
-    ASSERT(lib.raw() == Library::TypedDataLibrary());
+    ASSERT(lib.ptr() == Library::TypedDataLibrary());
 #define REGISTER_TYPED_DATA_CLASS(clazz)                                       \
-  cls = Class::NewTypedDataClass(kTypedData##clazz##ArrayCid, isolate);        \
+  cls = Class::NewTypedDataClass(kTypedData##clazz##ArrayCid, isolate_group);  \
   RegisterPrivateClass(cls, Symbols::_##clazz##List(), lib);
 
     DART_CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
 #undef REGISTER_TYPED_DATA_CLASS
 #define REGISTER_TYPED_DATA_VIEW_CLASS(clazz)                                  \
-  cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid, isolate);     \
+  cls =                                                                        \
+      Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid, isolate_group); \
   RegisterPrivateClass(cls, Symbols::_##clazz##View(), lib);                   \
   pending_classes.Add(cls);
 
     CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
 
-    cls = Class::NewTypedDataViewClass(kByteDataViewCid, isolate);
+    cls = Class::NewTypedDataViewClass(kByteDataViewCid, isolate_group);
     RegisterPrivateClass(cls, Symbols::_ByteDataView(), lib);
     pending_classes.Add(cls);
 
 #undef REGISTER_TYPED_DATA_VIEW_CLASS
 #define REGISTER_EXT_TYPED_DATA_CLASS(clazz)                                   \
   cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid,       \
-                                         isolate);                             \
+                                         isolate_group);                       \
   RegisterPrivateClass(cls, Symbols::_External##clazz(), lib);
 
-    cls = Class::New<Instance, RTN::Instance>(kByteBufferCid, isolate,
+    cls = Class::New<Instance, RTN::Instance>(kByteBufferCid, isolate_group,
                                               /*register_class=*/false);
     cls.set_instance_size(0, 0);
     cls.set_next_field_offset(-kWordSize, -compiler::target::kWordSize);
-    isolate->class_table()->Register(cls);
+    isolate_group->class_table()->Register(cls);
     RegisterPrivateClass(cls, Symbols::_ByteBuffer(), lib);
     pending_classes.Add(cls);
 
     CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
 #undef REGISTER_EXT_TYPED_DATA_CLASS
     // Register Float32x4, Int32x4, and Float64x2 in the object store.
-    cls = Class::New<Float32x4, RTN::Float32x4>(isolate);
+    cls = Class::New<Float32x4, RTN::Float32x4>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_Float32x4(), lib);
     pending_classes.Add(cls);
     object_store->set_float32x4_class(cls);
 
-    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
+    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                               /*register_class=*/true,
                                               /*is_abstract=*/true);
     RegisterClass(cls, Symbols::Float32x4(), lib);
@@ -1968,12 +1987,12 @@
     type = Type::NewNonParameterizedType(cls);
     object_store->set_float32x4_type(type);
 
-    cls = Class::New<Int32x4, RTN::Int32x4>(isolate);
+    cls = Class::New<Int32x4, RTN::Int32x4>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_Int32x4(), lib);
     pending_classes.Add(cls);
     object_store->set_int32x4_class(cls);
 
-    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
+    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                               /*register_class=*/true,
                                               /*is_abstract=*/true);
     RegisterClass(cls, Symbols::Int32x4(), lib);
@@ -1982,12 +2001,12 @@
     type = Type::NewNonParameterizedType(cls);
     object_store->set_int32x4_type(type);
 
-    cls = Class::New<Float64x2, RTN::Float64x2>(isolate);
+    cls = Class::New<Float64x2, RTN::Float64x2>(isolate_group);
     RegisterPrivateClass(cls, Symbols::_Float64x2(), lib);
     pending_classes.Add(cls);
     object_store->set_float64x2_class(cls);
 
-    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
+    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                               /*register_class=*/true,
                                               /*is_abstract=*/true);
     RegisterClass(cls, Symbols::Float64x2(), lib);
@@ -2003,7 +2022,7 @@
 
     // Abstract class that represents the Dart class Type.
     // Note that this class is implemented by Dart class _AbstractType.
-    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
+    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                               /*register_class=*/true,
                                               /*is_abstract=*/true);
     cls.set_num_type_arguments(0);
@@ -2014,7 +2033,7 @@
     object_store->set_type_type(type);
 
     // Abstract class that represents the Dart class Function.
-    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
+    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                               /*register_class=*/true,
                                               /*is_abstract=*/true);
     cls.set_num_type_arguments(0);
@@ -2028,7 +2047,7 @@
     type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
     object_store->set_non_nullable_function_type(type);
 
-    cls = Class::New<Number, RTN::Number>(isolate);
+    cls = Class::New<Number, RTN::Number>(isolate_group);
     RegisterClass(cls, Symbols::Number(), core_lib);
     pending_classes.Add(cls);
     type = Type::NewNonParameterizedType(cls);
@@ -2038,7 +2057,7 @@
     type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
     object_store->set_non_nullable_number_type(type);
 
-    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
+    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                               /*register_class=*/true,
                                               /*is_abstract=*/true);
     RegisterClass(cls, Symbols::Int(), core_lib);
@@ -2054,7 +2073,7 @@
     type = type.ToNullability(Nullability::kNullable, Heap::kOld);
     object_store->set_nullable_int_type(type);
 
-    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
+    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                               /*register_class=*/true,
                                               /*is_abstract=*/true);
     RegisterClass(cls, Symbols::Double(), core_lib);
@@ -2070,8 +2089,8 @@
     type = type.ToNullability(Nullability::kNullable, Heap::kOld);
     object_store->set_nullable_double_type(type);
 
-    name = Symbols::_String().raw();
-    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate,
+    name = Symbols::_String().ptr();
+    cls = Class::New<Instance, RTN::Instance>(kIllegalCid, isolate_group,
                                               /*register_class=*/true,
                                               /*is_abstract=*/true);
     RegisterClass(cls, name, core_lib);
@@ -2116,8 +2135,8 @@
     // name is a built-in identifier (this is wrong).  The corresponding types
     // are stored in the object store.
     cls = object_store->null_class();
-    type = Type::New(cls, Object::null_type_arguments(),
-                     TokenPosition::kNoSource, Nullability::kNullable);
+    type =
+        Type::New(cls, Object::null_type_arguments(), Nullability::kNullable);
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
     object_store->set_null_type(type);
@@ -2129,7 +2148,7 @@
 
     cls = object_store->never_class();
     type = Type::New(cls, Object::null_type_arguments(),
-                     TokenPosition::kNoSource, Nullability::kNonNullable);
+                     Nullability::kNonNullable);
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
     object_store->set_never_type(type);
@@ -2231,7 +2250,7 @@
     }
     object_store->set_bootstrap_library(ObjectStore::kFfi, lib);
 
-    cls = Class::New<Instance, RTN::Instance>(kFfiNativeTypeCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kFfiNativeTypeCid, isolate_group);
     cls.set_num_type_arguments(0);
     cls.set_is_prefinalized();
     pending_classes.Add(cls);
@@ -2239,7 +2258,7 @@
     RegisterClass(cls, Symbols::FfiNativeType(), lib);
 
 #define REGISTER_FFI_TYPE_MARKER(clazz)                                        \
-  cls = Class::New<Instance, RTN::Instance>(kFfi##clazz##Cid, isolate);        \
+  cls = Class::New<Instance, RTN::Instance>(kFfi##clazz##Cid, isolate_group);  \
   cls.set_num_type_arguments(0);                                               \
   cls.set_is_prefinalized();                                                   \
   pending_classes.Add(cls);                                                    \
@@ -2247,7 +2266,8 @@
     CLASS_LIST_FFI_TYPE_MARKER(REGISTER_FFI_TYPE_MARKER);
 #undef REGISTER_FFI_TYPE_MARKER
 
-    cls = Class::New<Instance, RTN::Instance>(kFfiNativeFunctionCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kFfiNativeFunctionCid,
+                                              isolate_group);
     cls.set_type_arguments_field_offset(Pointer::type_arguments_offset(),
                                         RTN::Pointer::type_arguments_offset());
     cls.set_num_type_arguments(1);
@@ -2255,13 +2275,13 @@
     pending_classes.Add(cls);
     RegisterClass(cls, Symbols::FfiNativeFunction(), lib);
 
-    cls = Class::NewPointerClass(kFfiPointerCid, isolate);
+    cls = Class::NewPointerClass(kFfiPointerCid, isolate_group);
     object_store->set_ffi_pointer_class(cls);
     pending_classes.Add(cls);
     RegisterClass(cls, Symbols::FfiPointer(), lib);
 
     cls = Class::New<DynamicLibrary, RTN::DynamicLibrary>(kFfiDynamicLibraryCid,
-                                                          isolate);
+                                                          isolate_group);
     cls.set_instance_size(DynamicLibrary::InstanceSize(),
                           compiler::target::RoundedAllocationSize(
                               RTN::DynamicLibrary::InstanceSize()));
@@ -2274,10 +2294,10 @@
     const Error& error = Error::Handle(
         zone, Bootstrap::DoBootstrapping(kernel_buffer, kernel_buffer_size));
     if (!error.IsNull()) {
-      return error.raw();
+      return error.ptr();
     }
 
-    isolate->class_table()->CopySizesFromClassObjects();
+    isolate_group->class_table()->CopySizesFromClassObjects();
 
     ClassFinalizer::VerifyBootstrapClasses();
 
@@ -2292,7 +2312,7 @@
     const bool injected = cls.InjectCIDFields();
     ASSERT(injected);
 
-    isolate->object_store()->InitKnownObjects();
+    isolate_group->object_store()->InitKnownObjects();
 
     // Set up recognized state of all functions (core, math and typed data).
     MethodRecognizer::InitializeState();
@@ -2301,7 +2321,7 @@
     // Object::Init version when we are running in a version of dart that has a
     // full snapshot linked in and an isolate is initialized using the full
     // snapshot.
-    ObjectStore* object_store = isolate->object_store();
+    ObjectStore* object_store = isolate_group->object_store();
 
     Class& cls = Class::Handle(zone);
 
@@ -2311,138 +2331,141 @@
     // stored in the object store. Yet we still need to create their Class
     // object so that they get put into the class_table (as a side effect of
     // Class::New()).
-    cls = Class::New<Instance, RTN::Instance>(kInstanceCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kInstanceCid, isolate_group);
     object_store->set_object_class(cls);
 
-    cls = Class::New<LibraryPrefix, RTN::LibraryPrefix>(isolate);
-    cls = Class::New<Type, RTN::Type>(isolate);
-    cls = Class::New<TypeRef, RTN::TypeRef>(isolate);
-    cls = Class::New<TypeParameter, RTN::TypeParameter>(isolate);
+    cls = Class::New<LibraryPrefix, RTN::LibraryPrefix>(isolate_group);
+    cls = Class::New<Type, RTN::Type>(isolate_group);
+    cls = Class::New<FunctionType, RTN::FunctionType>(isolate_group);
+    cls = Class::New<TypeRef, RTN::TypeRef>(isolate_group);
+    cls = Class::New<TypeParameter, RTN::TypeParameter>(isolate_group);
 
-    cls = Class::New<Array, RTN::Array>(isolate);
+    cls = Class::New<Array, RTN::Array>(isolate_group);
     object_store->set_array_class(cls);
 
-    cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate);
+    cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate_group);
     object_store->set_immutable_array_class(cls);
 
-    cls = Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(isolate);
+    cls = Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(
+        isolate_group);
     object_store->set_growable_object_array_class(cls);
 
-    cls = Class::New<LinkedHashMap, RTN::LinkedHashMap>(isolate);
+    cls = Class::New<LinkedHashMap, RTN::LinkedHashMap>(isolate_group);
     object_store->set_linked_hash_map_class(cls);
 
-    cls = Class::New<Float32x4, RTN::Float32x4>(isolate);
+    cls = Class::New<Float32x4, RTN::Float32x4>(isolate_group);
     object_store->set_float32x4_class(cls);
 
-    cls = Class::New<Int32x4, RTN::Int32x4>(isolate);
+    cls = Class::New<Int32x4, RTN::Int32x4>(isolate_group);
     object_store->set_int32x4_class(cls);
 
-    cls = Class::New<Float64x2, RTN::Float64x2>(isolate);
+    cls = Class::New<Float64x2, RTN::Float64x2>(isolate_group);
     object_store->set_float64x2_class(cls);
 
 #define REGISTER_TYPED_DATA_CLASS(clazz)                                       \
-  cls = Class::NewTypedDataClass(kTypedData##clazz##Cid, isolate);
+  cls = Class::NewTypedDataClass(kTypedData##clazz##Cid, isolate_group);
     CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
 #undef REGISTER_TYPED_DATA_CLASS
 #define REGISTER_TYPED_DATA_VIEW_CLASS(clazz)                                  \
-  cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid, isolate);
+  cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid, isolate_group);
     CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
 #undef REGISTER_TYPED_DATA_VIEW_CLASS
-    cls = Class::NewTypedDataViewClass(kByteDataViewCid, isolate);
+    cls = Class::NewTypedDataViewClass(kByteDataViewCid, isolate_group);
 #define REGISTER_EXT_TYPED_DATA_CLASS(clazz)                                   \
   cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid,       \
-                                         isolate);
+                                         isolate_group);
     CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
 #undef REGISTER_EXT_TYPED_DATA_CLASS
 
-    cls = Class::New<Instance, RTN::Instance>(kFfiNativeTypeCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kFfiNativeTypeCid, isolate_group);
     object_store->set_ffi_native_type_class(cls);
 
 #define REGISTER_FFI_CLASS(clazz)                                              \
-  cls = Class::New<Instance, RTN::Instance>(kFfi##clazz##Cid, isolate);
+  cls = Class::New<Instance, RTN::Instance>(kFfi##clazz##Cid, isolate_group);
     CLASS_LIST_FFI_TYPE_MARKER(REGISTER_FFI_CLASS);
 #undef REGISTER_FFI_CLASS
 
-    cls = Class::New<Instance, RTN::Instance>(kFfiNativeFunctionCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kFfiNativeFunctionCid,
+                                              isolate_group);
 
-    cls = Class::NewPointerClass(kFfiPointerCid, isolate);
+    cls = Class::NewPointerClass(kFfiPointerCid, isolate_group);
     object_store->set_ffi_pointer_class(cls);
 
     cls = Class::New<DynamicLibrary, RTN::DynamicLibrary>(kFfiDynamicLibraryCid,
-                                                          isolate);
+                                                          isolate_group);
 
-    cls = Class::New<Instance, RTN::Instance>(kByteBufferCid, isolate,
-                                              /*register_isolate=*/false);
+    cls = Class::New<Instance, RTN::Instance>(kByteBufferCid, isolate_group,
+                                              /*register_isolate_group=*/false);
     cls.set_instance_size_in_words(0, 0);
-    isolate->class_table()->Register(cls);
+    isolate_group->class_table()->Register(cls);
 
-    cls = Class::New<Integer, RTN::Integer>(isolate);
+    cls = Class::New<Integer, RTN::Integer>(isolate_group);
     object_store->set_integer_implementation_class(cls);
 
-    cls = Class::New<Smi, RTN::Smi>(isolate);
+    cls = Class::New<Smi, RTN::Smi>(isolate_group);
     object_store->set_smi_class(cls);
 
-    cls = Class::New<Mint, RTN::Mint>(isolate);
+    cls = Class::New<Mint, RTN::Mint>(isolate_group);
     object_store->set_mint_class(cls);
 
-    cls = Class::New<Double, RTN::Double>(isolate);
+    cls = Class::New<Double, RTN::Double>(isolate_group);
     object_store->set_double_class(cls);
 
-    cls = Class::New<Closure, RTN::Closure>(isolate);
+    cls = Class::New<Closure, RTN::Closure>(isolate_group);
     object_store->set_closure_class(cls);
 
-    cls = Class::NewStringClass(kOneByteStringCid, isolate);
+    cls = Class::NewStringClass(kOneByteStringCid, isolate_group);
     object_store->set_one_byte_string_class(cls);
 
-    cls = Class::NewStringClass(kTwoByteStringCid, isolate);
+    cls = Class::NewStringClass(kTwoByteStringCid, isolate_group);
     object_store->set_two_byte_string_class(cls);
 
-    cls = Class::NewStringClass(kExternalOneByteStringCid, isolate);
+    cls = Class::NewStringClass(kExternalOneByteStringCid, isolate_group);
     object_store->set_external_one_byte_string_class(cls);
 
-    cls = Class::NewStringClass(kExternalTwoByteStringCid, isolate);
+    cls = Class::NewStringClass(kExternalTwoByteStringCid, isolate_group);
     object_store->set_external_two_byte_string_class(cls);
 
-    cls = Class::New<Bool, RTN::Bool>(isolate);
+    cls = Class::New<Bool, RTN::Bool>(isolate_group);
     object_store->set_bool_class(cls);
 
-    cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate_group);
     object_store->set_null_class(cls);
 
-    cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate);
+    cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate_group);
     object_store->set_never_class(cls);
 
-    cls = Class::New<Capability, RTN::Capability>(isolate);
-    cls = Class::New<ReceivePort, RTN::ReceivePort>(isolate);
-    cls = Class::New<SendPort, RTN::SendPort>(isolate);
-    cls = Class::New<StackTrace, RTN::StackTrace>(isolate);
-    cls = Class::New<RegExp, RTN::RegExp>(isolate);
-    cls = Class::New<Number, RTN::Number>(isolate);
+    cls = Class::New<Capability, RTN::Capability>(isolate_group);
+    cls = Class::New<ReceivePort, RTN::ReceivePort>(isolate_group);
+    cls = Class::New<SendPort, RTN::SendPort>(isolate_group);
+    cls = Class::New<StackTrace, RTN::StackTrace>(isolate_group);
+    cls = Class::New<RegExp, RTN::RegExp>(isolate_group);
+    cls = Class::New<Number, RTN::Number>(isolate_group);
 
-    cls = Class::New<WeakProperty, RTN::WeakProperty>(isolate);
+    cls = Class::New<WeakProperty, RTN::WeakProperty>(isolate_group);
     object_store->set_weak_property_class(cls);
 
-    cls = Class::New<MirrorReference, RTN::MirrorReference>(isolate);
-    cls = Class::New<UserTag, RTN::UserTag>(isolate);
-    cls = Class::New<FutureOr, RTN::FutureOr>(isolate);
-    cls =
-        Class::New<TransferableTypedData, RTN::TransferableTypedData>(isolate);
+    cls = Class::New<MirrorReference, RTN::MirrorReference>(isolate_group);
+    cls = Class::New<UserTag, RTN::UserTag>(isolate_group);
+    cls = Class::New<FutureOr, RTN::FutureOr>(isolate_group);
+    cls = Class::New<TransferableTypedData, RTN::TransferableTypedData>(
+        isolate_group);
   }
   return Error::null();
 }
 
 #if defined(DEBUG)
 bool Object::InVMIsolateHeap() const {
-  if (FLAG_verify_handles && raw()->ptr()->InVMIsolateHeap()) {
-    Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
-    uword addr = ObjectLayout::ToAddr(raw());
+  if (FLAG_verify_handles && ptr()->untag()->InVMIsolateHeap()) {
+    Heap* vm_isolate_heap = Dart::vm_isolate_group()->heap();
+    uword addr = UntaggedObject::ToAddr(ptr());
     if (!vm_isolate_heap->Contains(addr)) {
       ASSERT(FLAG_write_protect_code);
-      addr = ObjectLayout::ToAddr(OldPage::ToWritable(raw()));
+      addr = UntaggedObject::ToAddr(OldPage::ToWritable(ptr()));
       ASSERT(vm_isolate_heap->Contains(addr));
     }
   }
-  return raw()->ptr()->InVMIsolateHeap();
+  return ptr()->untag()->InVMIsolateHeap();
 }
 #endif  // DEBUG
 
@@ -2458,7 +2481,7 @@
   // Note: we skip the header word here to avoid a racy read in the concurrent
   // marker from observing the null object when it reads into a heap page
   // allocated after marking started.
-  uword cur = address + sizeof(ObjectLayout);
+  uword cur = address + sizeof(UntaggedObject);
   uword end = address + size;
   if (class_id == kInstructionsCid) {
     compiler::target::uword initial_value = kBreakInstructionFiller;
@@ -2498,33 +2521,33 @@
   }
   uword tags = 0;
   ASSERT(class_id != kIllegalCid);
-  tags = ObjectLayout::ClassIdTag::update(class_id, tags);
-  tags = ObjectLayout::SizeTag::update(size, tags);
+  tags = UntaggedObject::ClassIdTag::update(class_id, tags);
+  tags = UntaggedObject::SizeTag::update(size, tags);
   const bool is_old =
       (address & kNewObjectAlignmentOffset) == kOldObjectAlignmentOffset;
-  tags = ObjectLayout::OldBit::update(is_old, tags);
-  tags = ObjectLayout::OldAndNotMarkedBit::update(is_old, tags);
-  tags = ObjectLayout::OldAndNotRememberedBit::update(is_old, tags);
-  tags = ObjectLayout::NewBit::update(!is_old, tags);
-  reinterpret_cast<ObjectLayout*>(address)->tags_ = tags;
+  tags = UntaggedObject::OldBit::update(is_old, tags);
+  tags = UntaggedObject::OldAndNotMarkedBit::update(is_old, tags);
+  tags = UntaggedObject::OldAndNotRememberedBit::update(is_old, tags);
+  tags = UntaggedObject::NewBit::update(!is_old, tags);
+  reinterpret_cast<UntaggedObject*>(address)->tags_ = tags;
 }
 
 void Object::CheckHandle() const {
 #if defined(DEBUG)
-  if (raw_ != Object::null()) {
-    intptr_t cid = raw_->GetClassIdMayBeSmi();
+  if (ptr_ != Object::null()) {
+    intptr_t cid = ptr_->GetClassIdMayBeSmi();
     if (cid >= kNumPredefinedCids) {
       cid = kInstanceCid;
     }
     ASSERT(vtable() == builtin_vtables_[cid]);
-    if (FLAG_verify_handles && raw_->IsHeapObject()) {
+    if (FLAG_verify_handles && ptr_->IsHeapObject()) {
       Heap* isolate_heap = IsolateGroup::Current()->heap();
       if (!isolate_heap->new_space()->scavenging()) {
-        Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
-        uword addr = ObjectLayout::ToAddr(raw_);
+        Heap* vm_isolate_heap = Dart::vm_isolate_group()->heap();
+        uword addr = UntaggedObject::ToAddr(ptr_);
         if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
           ASSERT(FLAG_write_protect_code);
-          addr = ObjectLayout::ToAddr(OldPage::ToWritable(raw_));
+          addr = UntaggedObject::ToAddr(OldPage::ToWritable(ptr_));
           ASSERT(isolate_heap->Contains(addr) ||
                  vm_isolate_heap->Contains(addr));
         }
@@ -2553,8 +2576,8 @@
     } else if (thread->top_exit_frame_info() != 0) {
       // Use the preallocated out of memory exception to avoid calling
       // into dart code or allocating any code.
-      const Instance& exception =
-          Instance::Handle(thread->isolate()->object_store()->out_of_memory());
+      const Instance& exception = Instance::Handle(
+          thread->isolate_group()->object_store()->out_of_memory());
       Exceptions::Throw(thread, exception);
       UNREACHABLE();
     } else {
@@ -2571,13 +2594,13 @@
   NoSafepointScope no_safepoint;
   InitializeObject(address, cls_id, size);
   ObjectPtr raw_obj = static_cast<ObjectPtr>(address + kHeapObjectTag);
-  ASSERT(cls_id == ObjectLayout::ClassIdTag::decode(raw_obj->ptr()->tags_));
+  ASSERT(cls_id == UntaggedObject::ClassIdTag::decode(raw_obj->untag()->tags_));
   if (raw_obj->IsOldObject() && UNLIKELY(thread->is_marking())) {
     // Black allocation. Prevents a data race between the mutator and concurrent
     // marker on ARM and ARM64 (the marker may observe a publishing store of
     // this object before the stores that initialize its slots), and helps the
     // collection to finish sooner.
-    raw_obj->ptr()->SetMarkBitUnsynchronized();
+    raw_obj->untag()->SetMarkBitUnsynchronized();
     // Setting the mark bit must not be ordered after a publishing store of this
     // object. Adding a barrier here is cheaper than making every store into the
     // heap a store-release. Compare Scavenger::ScavengePointer.
@@ -2601,14 +2624,14 @@
       for (ObjectPtr* slot = from; slot <= to; ++slot) {
         ObjectPtr value = *slot;
         if (value->IsHeapObject()) {
-          old_obj_->ptr()->CheckArrayPointerStore(slot, value, thread_);
+          old_obj_->untag()->CheckArrayPointerStore(slot, value, thread_);
         }
       }
     } else {
       for (ObjectPtr* slot = from; slot <= to; ++slot) {
         ObjectPtr value = *slot;
         if (value->IsHeapObject()) {
-          old_obj_->ptr()->CheckHeapPointerStore(value, thread_);
+          old_obj_->untag()->CheckHeapPointerStore(value, thread_);
         }
       }
     }
@@ -2631,13 +2654,13 @@
 
 ObjectPtr Object::Clone(const Object& orig, Heap::Space space) {
   const Class& cls = Class::Handle(orig.clazz());
-  intptr_t size = orig.raw()->ptr()->HeapSize();
+  intptr_t size = orig.ptr()->untag()->HeapSize();
   ObjectPtr raw_clone = Object::Allocate(cls.id(), size, space);
   NoSafepointScope no_safepoint;
   // Copy the body of the original into the clone.
-  uword orig_addr = ObjectLayout::ToAddr(orig.raw());
-  uword clone_addr = ObjectLayout::ToAddr(raw_clone);
-  static const intptr_t kHeaderSizeInBytes = sizeof(ObjectLayout);
+  uword orig_addr = UntaggedObject::ToAddr(orig.ptr());
+  uword clone_addr = UntaggedObject::ToAddr(raw_clone);
+  static const intptr_t kHeaderSizeInBytes = sizeof(UntaggedObject);
   memmove(reinterpret_cast<uint8_t*>(clone_addr + kHeaderSizeInBytes),
           reinterpret_cast<uint8_t*>(orig_addr + kHeaderSizeInBytes),
           size - kHeaderSizeInBytes);
@@ -2648,12 +2671,12 @@
     return raw_clone;
   }
   WriteBarrierUpdateVisitor visitor(Thread::Current(), raw_clone);
-  raw_clone->ptr()->VisitPointers(&visitor);
+  raw_clone->untag()->VisitPointers(&visitor);
   return raw_clone;
 }
 
 StringPtr Class::Name() const {
-  return raw_ptr()->name();
+  return untag()->name();
 }
 
 StringPtr Class::ScrubbedName() const {
@@ -2666,8 +2689,8 @@
 
 StringPtr Class::UserVisibleName() const {
 #if !defined(PRODUCT)
-  ASSERT(raw_ptr()->user_name() != String::null());
-  return raw_ptr()->user_name();
+  ASSERT(untag()->user_name() != String::null());
+  return untag()->user_name();
 #endif  // !defined(PRODUCT)
   // No caching in PRODUCT, regenerate.
   return Symbols::New(Thread::Current(), GenerateUserVisibleName());
@@ -2675,8 +2698,8 @@
 
 const char* Class::UserVisibleNameCString() const {
 #if !defined(PRODUCT)
-  ASSERT(raw_ptr()->user_name() != String::null());
-  return String::Handle(raw_ptr()->user_name()).ToCString();
+  ASSERT(untag()->user_name() != String::null());
+  return String::Handle(untag()->user_name()).ToCString();
 #endif                               // !defined(PRODUCT)
   return GenerateUserVisibleName();  // No caching in PRODUCT, regenerate.
 }
@@ -2702,7 +2725,7 @@
         Type::Handle(Type::RawCast(interfaces.At(interfaces.Length() - 1)));
     return mixin_type.type_class();
   }
-  return raw();
+  return ptr();
 }
 
 NNBDMode Class::nnbd_mode() const {
@@ -2711,23 +2734,22 @@
 
 bool Class::IsInFullSnapshot() const {
   NoSafepointScope no_safepoint;
-  return LibraryLayout::InFullSnapshotBit::decode(
-      raw_ptr()->library()->ptr()->flags_);
+  return UntaggedLibrary::InFullSnapshotBit::decode(
+      untag()->library()->untag()->flags_);
 }
 
 AbstractTypePtr Class::RareType() const {
-  if (!IsGeneric() && !IsClosureClass() && !IsTypedefClass()) {
+  if (!IsGeneric() && !IsClosureClass()) {
     return DeclarationType();
   }
   ASSERT(is_declaration_loaded());
-  const Type& type = Type::Handle(
-      Type::New(*this, Object::null_type_arguments(), TokenPosition::kNoSource,
-                Nullability::kNonNullable));
+  const Type& type = Type::Handle(Type::New(
+      *this, Object::null_type_arguments(), Nullability::kNonNullable));
   return ClassFinalizer::FinalizeType(type);
 }
 
 template <class FakeObject, class TargetFakeObject>
-ClassPtr Class::New(Isolate* isolate, bool register_class) {
+ClassPtr Class::New(IsolateGroup* isolate_group, bool register_class) {
   ASSERT(Object::class_class() != Class::null());
   Class& result = Class::Handle();
   {
@@ -2768,9 +2790,9 @@
   NOT_IN_PRECOMPILED(result.set_kernel_offset(0));
   result.InitEmptyFields();
   if (register_class) {
-    isolate->class_table()->Register(result);
+    isolate_group->class_table()->Register(result);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 static void ReportTooManyTypeArguments(const Class& cls) {
@@ -2786,7 +2808,7 @@
   if (!Utils::IsInt(16, value)) {
     ReportTooManyTypeArguments(*this);
   }
-  StoreNonPointer(&raw_ptr()->num_type_arguments_, value);
+  StoreNonPointer(&untag()->num_type_arguments_, value);
 }
 
 void Class::set_has_pragma(bool value) const {
@@ -2795,23 +2817,23 @@
 
 // Initialize class fields of type Array with empty array.
 void Class::InitEmptyFields() {
-  if (Object::empty_array().raw() == Array::null()) {
+  if (Object::empty_array().ptr() == Array::null()) {
     // The empty array has not been initialized yet.
     return;
   }
-  raw_ptr()->set_interfaces(Object::empty_array().raw());
-  raw_ptr()->set_constants(Object::null_array().raw());
+  untag()->set_interfaces(Object::empty_array().ptr());
+  untag()->set_constants(Object::null_array().ptr());
   set_functions(Object::empty_array());
   set_fields(Object::empty_array());
   set_invocation_dispatcher_cache(Object::empty_array());
 }
 
 ArrayPtr Class::OffsetToFieldMap(bool original_classes) const {
-  if (raw_ptr()->offset_in_words_to_field() == Array::null()) {
+  if (untag()->offset_in_words_to_field() == Array::null()) {
     ASSERT(is_finalized());
-    const intptr_t length = raw_ptr()->host_instance_size_in_words_;
+    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->raw());
+    Class& cls = Class::Handle(this->ptr());
     Array& fields = Array::Handle();
     Field& f = Field::Handle();
     while (!cls.IsNull()) {
@@ -2824,9 +2846,9 @@
       }
       cls = cls.SuperClass(original_classes);
     }
-    raw_ptr()->set_offset_in_words_to_field(array.raw());
+    untag()->set_offset_in_words_to_field(array.ptr());
   }
-  return raw_ptr()->offset_in_words_to_field();
+  return untag()->offset_in_words_to_field();
 }
 
 bool Class::HasInstanceFields() const {
@@ -2847,7 +2869,7 @@
       : name_(name), tmp_string_(tmp_string) {}
   bool Matches(const Function& function) const {
     if (name_.IsSymbol()) {
-      return name_.raw() == function.name();
+      return name_.ptr() == function.name();
     } else {
       *tmp_string_ = function.name();
       return name_.Equals(*tmp_string_);
@@ -2870,7 +2892,7 @@
   static bool IsMatch(const Object& a, const Object& b) {
     ASSERT(a.IsFunction() && b.IsFunction());
     // Function objects are always canonical.
-    return a.raw() == b.raw();
+    return a.ptr() == b.ptr();
   }
   static bool IsMatch(const FunctionName& name, const Object& obj) {
     return name.Matches(Function::Cast(obj));
@@ -2883,26 +2905,34 @@
 typedef UnorderedHashSet<ClassFunctionsTraits> ClassFunctionsSet;
 
 void Class::SetFunctions(const Array& value) const {
+  ASSERT(!value.IsNull());
+  const intptr_t len = value.Length();
 #if defined(DEBUG)
   Thread* thread = Thread::Current();
-  ASSERT(thread->IsMutatorThread());
   ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
+  if (is_finalized()) {
+    Function& function = Function::Handle();
+    FunctionType& signature = FunctionType::Handle();
+    for (intptr_t i = 0; i < len; ++i) {
+      function ^= value.At(i);
+      signature = function.signature();
+      ASSERT(signature.IsFinalized());
+    }
+  }
 #endif
-  ASSERT(!value.IsNull());
   set_functions(value);
-  const intptr_t len = value.Length();
   if (len >= kFunctionLookupHashTreshold) {
     ClassFunctionsSet set(HashTables::New<ClassFunctionsSet>(len, Heap::kOld));
     Function& func = Function::Handle();
     for (intptr_t i = 0; i < len; ++i) {
       func ^= value.At(i);
       // Verify that all the functions in the array have this class as owner.
-      ASSERT(func.Owner() == raw());
+      ASSERT(func.Owner() == ptr());
       set.Insert(func);
     }
-    raw_ptr()->set_functions_hash_table(set.Release().raw());
+    untag()->set_functions_hash_table(set.Release().ptr());
   } else {
-    raw_ptr()->set_functions_hash_table(Array::null());
+    untag()->set_functions_hash_table(Array::null());
   }
 }
 
@@ -2911,6 +2941,8 @@
   Thread* thread = Thread::Current();
   ASSERT(thread->IsMutatorThread());
   ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
+  ASSERT(!is_finalized() ||
+         FunctionType::Handle(function.signature()).IsFinalized());
 #endif
   const Array& arr = Array::Handle(functions());
   const Array& new_array =
@@ -2923,9 +2955,9 @@
     // Transition to using hash table.
     SetFunctions(new_array);
   } else if (new_len > kFunctionLookupHashTreshold) {
-    ClassFunctionsSet set(raw_ptr()->functions_hash_table());
+    ClassFunctionsSet set(untag()->functions_hash_table());
     set.Insert(function);
-    raw_ptr()->set_functions_hash_table(set.Release().raw());
+    untag()->set_functions_hash_table(set.Release().ptr());
   }
 }
 
@@ -2937,7 +2969,7 @@
   Function& func = Function::Handle();
   func ^= funcs.At(idx);
   ASSERT(!func.IsNull());
-  return func.raw();
+  return func.ptr();
 }
 
 FunctionPtr Class::ImplicitClosureFunctionFromIndex(intptr_t idx) const {
@@ -2954,7 +2986,7 @@
   const Function& closure_func =
       Function::Handle(func.ImplicitClosureFunction());
   ASSERT(!closure_func.IsNull());
-  return closure_func.raw();
+  return closure_func.ptr();
 }
 
 intptr_t Class::FindImplicitClosureFunctionIndex(const Function& needle) const {
@@ -2977,7 +3009,7 @@
       // Skip non-implicit closure functions.
       continue;
     }
-    if (needle.raw() == implicit_closure.raw()) {
+    if (needle.ptr() == implicit_closure.ptr()) {
       return i;
     }
   }
@@ -3003,7 +3035,7 @@
     // The invocation_dispatcher_cache is a table with some entries that
     // are functions.
     if (object.IsFunction()) {
-      if (Function::Cast(object).raw() == needle.raw()) {
+      if (Function::Cast(object).ptr() == needle.ptr()) {
         return i;
       }
     }
@@ -3023,46 +3055,41 @@
   if (!object.IsFunction()) {
     return Function::null();
   }
-  return Function::Cast(object).raw();
-}
-
-void Class::set_signature_function(const Function& value) const {
-  ASSERT(value.IsClosureFunction() || value.IsSignatureFunction());
-  raw_ptr()->set_signature_function(value.raw());
+  return Function::Cast(object).ptr();
 }
 
 void Class::set_state_bits(intptr_t bits) const {
   StoreNonPointer<uint32_t, uint32_t, std::memory_order_release>(
-      &raw_ptr()->state_bits_, static_cast<uint32_t>(bits));
+      &untag()->state_bits_, static_cast<uint32_t>(bits));
 }
 
 void Class::set_library(const Library& value) const {
-  raw_ptr()->set_library(value.raw());
+  untag()->set_library(value.ptr());
 }
 
 void Class::set_type_parameters(const TypeArguments& value) const {
   ASSERT((num_type_arguments() == kUnknownNumTypeArguments) ||
          is_prefinalized());
-  raw_ptr()->set_type_parameters(value.raw());
+  untag()->set_type_parameters(value.ptr());
 }
 
 void Class::set_functions(const Array& value) const {
   // Ensure all writes to the [Function]s are visible by the time the array
   // is visible.
-  raw_ptr()->set_functions<std::memory_order_release>(value.raw());
+  untag()->set_functions<std::memory_order_release>(value.ptr());
 }
 
 void Class::set_fields(const Array& value) const {
   // Ensure all writes to the [Field]s are visible by the time the array
   // is visible.
-  raw_ptr()->set_fields<std::memory_order_release>(value.raw());
+  untag()->set_fields<std::memory_order_release>(value.ptr());
 }
 
 void Class::set_invocation_dispatcher_cache(const Array& cache) const {
   // Ensure all writes to the cache are visible by the time the array
   // is visible.
-  raw_ptr()->set_invocation_dispatcher_cache<std::memory_order_release>(
-      cache.raw());
+  untag()->set_invocation_dispatcher_cache<std::memory_order_release>(
+      cache.ptr());
 }
 
 intptr_t Class::NumTypeParameters(Thread* thread) const {
@@ -3088,11 +3115,11 @@
   ASSERT(is_declaration_loaded());
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   const intptr_t num_type_params = NumTypeParameters();
 
   if ((super_type() == AbstractType::null()) ||
-      (super_type() == isolate->object_store()->object_type())) {
+      (super_type() == isolate_group->object_store()->object_type())) {
     return num_type_params;
   }
 
@@ -3100,8 +3127,6 @@
   ASSERT(sup_type.IsType());
 
   const auto& sup_class = Class::Handle(zone, sup_type.type_class());
-  ASSERT(!sup_class.IsTypedefClass());
-
   const intptr_t sup_class_num_type_args = sup_class.NumTypeArguments();
   if (num_type_params == 0) {
     return sup_class_num_type_args;
@@ -3140,8 +3165,10 @@
     intptr_t i = 0;
     for (; i < num_overlapping_type_args; i++) {
       type_param ^= type_params.TypeAt(i);
+      ASSERT(!type_param.IsNull());
       sup_type_arg = sup_type_args.TypeAt(sup_type_args_length -
                                           num_overlapping_type_args + i);
+      ASSERT(!sup_type_arg.IsNull());
       if (!type_param.Equals(sup_type_arg)) break;
     }
     if (i == num_overlapping_type_args) {
@@ -3172,7 +3199,7 @@
     const TypeArguments& parameters) {
   ASSERT(thread != nullptr);
   if (parameters.IsNull()) {
-    return Object::empty_type_arguments().raw();
+    return Object::empty_type_arguments().ptr();
   }
   auto const zone = thread->zone();
   const auto& result = TypeArguments::Handle(
@@ -3197,11 +3224,12 @@
 ClassPtr Class::SuperClass(bool original_classes) const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   if (super_type() == AbstractType::null()) {
     if (id() == kTypeArgumentsCid) {
       // Pretend TypeArguments objects are Dart instances.
-      return isolate->class_table()->At(kInstanceCid);
+      return isolate_group->class_table()->At(kInstanceCid);
     }
     return Class::null();
   }
@@ -3210,13 +3238,13 @@
   if (original_classes) {
     return isolate->GetClassForHeapWalkAt(type_class_id);
   } else {
-    return isolate->class_table()->At(type_class_id);
+    return isolate_group->class_table()->At(type_class_id);
   }
 }
 
 void Class::set_super_type(const AbstractType& value) const {
   ASSERT(value.IsNull() || (value.IsType() && !value.IsDynamicType()));
-  raw_ptr()->set_super_type(value.raw());
+  untag()->set_super_type(value.ptr());
 }
 
 TypeParameterPtr Class::LookupTypeParameter(const String& type_name) const {
@@ -3236,7 +3264,7 @@
       type_param ^= type_params.TypeAt(i);
       type_param_name = type_param.name();
       if (type_param_name.Equals(type_name)) {
-        return type_param.raw();
+        return type_param.ptr();
       }
     }
   }
@@ -3271,10 +3299,9 @@
     set_num_native_fields(super.num_native_fields());
 
     if (FLAG_precompiled_mode) {
-      host_bitmap = Isolate::Current()
-                        ->group()
-                        ->shared_class_table()
-                        ->GetUnboxedFieldsMapAt(super.id());
+      host_bitmap =
+          IsolateGroup::Current()->shared_class_table()->GetUnboxedFieldsMapAt(
+              super.id());
     }
   }
   // If the super class is parameterized, use the same type_arguments field,
@@ -3313,17 +3340,17 @@
         intptr_t field_size;
         switch (field.guarded_cid()) {
           case kDoubleCid:
-            field_size = sizeof(DoubleLayout::value_);
+            field_size = sizeof(UntaggedDouble::value_);
             break;
           case kFloat32x4Cid:
-            field_size = sizeof(Float32x4Layout::value_);
+            field_size = sizeof(UntaggedFloat32x4::value_);
             break;
           case kFloat64x2Cid:
-            field_size = sizeof(Float64x2Layout::value_);
+            field_size = sizeof(UntaggedFloat64x2::value_);
             break;
           default:
             if (field.is_non_nullable_integer()) {
-              field_size = sizeof(MintLayout::value_);
+              field_size = sizeof(UntaggedMint::value_);
             } else {
               UNREACHABLE();
               field_size = 0;
@@ -3405,11 +3432,11 @@
 
 FunctionPtr Class::GetInvocationDispatcher(const String& target_name,
                                            const Array& args_desc,
-                                           FunctionLayout::Kind kind,
+                                           UntaggedFunction::Kind kind,
                                            bool create_if_absent) const {
-  ASSERT(kind == FunctionLayout::kNoSuchMethodDispatcher ||
-         kind == FunctionLayout::kInvokeFieldDispatcher ||
-         kind == FunctionLayout::kDynamicInvocationForwarder);
+  ASSERT(kind == UntaggedFunction::kNoSuchMethodDispatcher ||
+         kind == UntaggedFunction::kInvokeFieldDispatcher ||
+         kind == UntaggedFunction::kDynamicInvocationForwarder);
   auto thread = Thread::Current();
   auto Z = thread->zone();
   auto& function = Function::Handle(Z);
@@ -3428,10 +3455,10 @@
       if (name.IsNull()) break;  // Reached last entry.
       if (!name.Equals(target_name)) continue;
       desc = dispatcher.Get<Class::kInvocationDispatcherArgsDesc>();
-      if (desc.raw() != args_desc.raw()) continue;
+      if (desc.ptr() != args_desc.ptr()) continue;
       function = dispatcher.Get<Class::kInvocationDispatcherFunction>();
       if (function.kind() == kind) {
-        return function.raw();
+        return function.ptr();
       }
     }
     return Function::null();
@@ -3440,7 +3467,7 @@
   // First we'll try to find it without using locks.
   function = find_entry();
   if (!function.IsNull() || !create_if_absent) {
-    return function.raw();
+    return function.ptr();
   }
 
   // If we failed to find it and possibly need to create it, use a write lock.
@@ -3448,21 +3475,24 @@
 
   // Try to find it again & return if it was added in the meantime.
   function = find_entry();
-  if (!function.IsNull()) return function.raw();
+  if (!function.IsNull()) return function.ptr();
 
   // Otherwise create it & add it.
   function = CreateInvocationDispatcher(target_name, args_desc, kind);
   AddInvocationDispatcher(target_name, args_desc, function);
-  return function.raw();
+  return function.ptr();
 }
 
-FunctionPtr Class::CreateInvocationDispatcher(const String& target_name,
-                                              const Array& args_desc,
-                                              FunctionLayout::Kind kind) const {
+FunctionPtr Class::CreateInvocationDispatcher(
+    const String& target_name,
+    const Array& args_desc,
+    UntaggedFunction::Kind kind) const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
+  FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
   Function& invocation = Function::Handle(
       zone, Function::New(
+                signature,
                 String::Handle(zone, Symbols::New(thread, target_name)), kind,
                 false,  // Not static.
                 false,  // Not const.
@@ -3473,29 +3503,24 @@
   ArgumentsDescriptor desc(args_desc);
   if (desc.TypeArgsLen() > 0) {
     // Make dispatcher function generic, since type arguments are passed.
-    const TypeArguments& type_params =
-        TypeArguments::Handle(zone, TypeArguments::New(desc.TypeArgsLen()));
-    // The presence of a type parameter array is enough to mark this dispatcher
-    // as generic. To save memory, we do not copy the type parameters to the
-    // array (they are not accessed), but leave it as an array of null objects.
-    invocation.set_type_parameters(type_params);
+    invocation.SetNumTypeParameters(desc.TypeArgsLen());
   }
 
   invocation.set_num_fixed_parameters(desc.PositionalCount());
   invocation.SetNumOptionalParameters(desc.NamedCount(),
                                       false);  // Not positional.
-  invocation.set_parameter_types(
+  signature.set_parameter_types(
       Array::Handle(zone, Array::New(desc.Count(), Heap::kOld)));
-  invocation.CreateNameArrayIncludingFlags(Heap::kOld);
+  signature.CreateNameArrayIncludingFlags(Heap::kOld);
   // Receiver.
-  invocation.SetParameterTypeAt(0, Object::dynamic_type());
-  invocation.SetParameterNameAt(0, Symbols::This());
+  signature.SetParameterTypeAt(0, Object::dynamic_type());
+  signature.SetParameterNameAt(0, Symbols::This());
   // Remaining positional parameters.
   for (intptr_t i = 1; i < desc.PositionalCount(); i++) {
-    invocation.SetParameterTypeAt(i, Object::dynamic_type());
+    signature.SetParameterTypeAt(i, Object::dynamic_type());
     char name[64];
     Utils::SNPrint(name, 64, ":p%" Pd, i);
-    invocation.SetParameterNameAt(
+    signature.SetParameterNameAt(
         i, String::Handle(zone, Symbols::New(thread, name)));
   }
 
@@ -3503,17 +3528,20 @@
   for (intptr_t i = 0; i < desc.NamedCount(); i++) {
     const intptr_t param_index = desc.PositionAt(i);
     const auto& param_name = String::Handle(zone, desc.NameAt(i));
-    invocation.SetParameterTypeAt(param_index, Object::dynamic_type());
-    invocation.SetParameterNameAt(param_index, param_name);
+    signature.SetParameterTypeAt(param_index, Object::dynamic_type());
+    signature.SetParameterNameAt(param_index, param_name);
   }
-  invocation.TruncateUnusedParameterFlags();
-  invocation.set_result_type(Object::dynamic_type());
+  signature.FinalizeNameArrays(invocation);
+  signature.set_result_type(Object::dynamic_type());
   invocation.set_is_debuggable(false);
   invocation.set_is_visible(false);
   invocation.set_is_reflectable(false);
   invocation.set_saved_args_desc(args_desc);
 
-  return invocation.raw();
+  signature ^= ClassFinalizer::FinalizeType(signature);
+  invocation.set_signature(signature);
+
+  return invocation.ptr();
 }
 
 // Method extractors are used to create implicit closures from methods.
@@ -3529,10 +3557,12 @@
       Function::Handle(zone, ImplicitClosureFunction());
 
   const Class& owner = Class::Handle(zone, closure_function.Owner());
-  Function& extractor = Function::Handle(
+  FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
+  const Function& extractor = Function::Handle(
       zone,
-      Function::New(String::Handle(zone, Symbols::New(thread, getter_name)),
-                    FunctionLayout::kMethodExtractor,
+      Function::New(signature,
+                    String::Handle(zone, Symbols::New(thread, getter_name)),
+                    UntaggedFunction::kMethodExtractor,
                     false,  // Not static.
                     false,  // Not const.
                     is_abstract(),
@@ -3544,9 +3574,10 @@
   const intptr_t kNumParameters = 1;
   extractor.set_num_fixed_parameters(kNumParameters);
   extractor.SetNumOptionalParameters(0, false);
-  extractor.set_parameter_types(Object::extractor_parameter_types());
-  extractor.set_parameter_names(Object::extractor_parameter_names());
-  extractor.set_result_type(Object::dynamic_type());
+  signature.set_parameter_types(Object::extractor_parameter_types());
+  signature.set_parameter_names(Object::extractor_parameter_names());
+  extractor.SetParameterNamesFrom(signature);
+  signature.set_result_type(Object::dynamic_type());
 
   extractor.InheritKernelOffsetFrom(*this);
 
@@ -3554,9 +3585,12 @@
   extractor.set_is_debuggable(false);
   extractor.set_is_visible(false);
 
+  signature ^= ClassFinalizer::FinalizeType(signature);
+  extractor.set_signature(signature);
+
   owner.AddFunction(extractor);
 
-  return extractor.raw();
+  return extractor.ptr();
 }
 
 FunctionPtr Function::GetMethodExtractor(const String& getter_name) const {
@@ -3578,8 +3612,8 @@
       result = CreateMethodExtractor(getter_name);
     }
   }
-  ASSERT(result.kind() == FunctionLayout::kMethodExtractor);
-  return result.raw();
+  ASSERT(result.kind() == UntaggedFunction::kMethodExtractor);
+  return result.ptr();
 }
 
 bool Library::FindPragma(Thread* T,
@@ -3587,7 +3621,7 @@
                          const Object& obj,
                          const String& pragma_name,
                          Object* options) {
-  auto I = T->isolate();
+  auto IG = T->isolate_group();
   auto Z = T->zone();
   auto& lib = Library::Handle(Z);
 
@@ -3617,14 +3651,14 @@
   }
 
   // If there is a compile-time error while evaluating the metadata, we will
-  // simply claim there was no @pramga annotation.
+  // simply claim there was no @pragma annotation.
   if (metadata_obj.IsNull() || metadata_obj.IsLanguageError()) {
     return false;
   }
   ASSERT(metadata_obj.IsArray());
 
   auto& metadata = Array::Cast(metadata_obj);
-  auto& pragma_class = Class::Handle(Z, I->object_store()->pragma_class());
+  auto& pragma_class = Class::Handle(Z, IG->object_store()->pragma_class());
   auto& pragma_name_field =
       Field::Handle(Z, pragma_class.LookupField(Symbols::name()));
   auto& pragma_options_field =
@@ -3633,12 +3667,14 @@
   auto& pragma = Object::Handle(Z);
   for (intptr_t i = 0; i < metadata.Length(); ++i) {
     pragma = metadata.At(i);
-    if (pragma.clazz() != pragma_class.raw() ||
+    if (pragma.clazz() != pragma_class.ptr() ||
         Instance::Cast(pragma).GetField(pragma_name_field) !=
-            pragma_name.raw()) {
+            pragma_name.ptr()) {
       continue;
     }
-    *options = Instance::Cast(pragma).GetField(pragma_options_field);
+    if (options != nullptr) {
+      *options = Instance::Cast(pragma).GetField(pragma_options_field);
+    }
     return true;
   }
 
@@ -3646,11 +3682,11 @@
 }
 
 bool Function::IsDynamicInvocationForwarderName(const String& name) {
-  return IsDynamicInvocationForwarderName(name.raw());
+  return IsDynamicInvocationForwarderName(name.ptr());
 }
 
 bool Function::IsDynamicInvocationForwarderName(StringPtr name) {
-  return String::StartsWith(name, Symbols::DynamicPrefix().raw());
+  return String::StartsWith(name, Symbols::DynamicPrefix().ptr());
 }
 
 StringPtr Function::DemangleDynamicInvocationForwarderName(const String& name) {
@@ -3679,7 +3715,7 @@
   forwarder.set_is_native(false);
   // TODO(dartbug.com/37737): Currently, we intentionally keep the recognized
   // kind when creating the dynamic invocation forwarder.
-  forwarder.set_kind(FunctionLayout::kDynamicInvocationForwarder);
+  forwarder.set_kind(UntaggedFunction::kDynamicInvocationForwarder);
   forwarder.set_is_debuggable(false);
 
   // TODO(vegorov) for error reporting reasons it is better to make this
@@ -3702,7 +3738,7 @@
   checks.SetAt(0, *this);
   forwarder.SetForwardingChecks(checks);
 
-  return forwarder.raw();
+  return forwarder.ptr();
 }
 
 FunctionPtr Function::GetDynamicInvocationForwarder(
@@ -3715,34 +3751,34 @@
   Function& result = Function::Handle(zone);
 
   // First we'll try to find it without using locks.
-  result =
-      owner.GetInvocationDispatcher(mangled_name, Array::null_array(),
-                                    FunctionLayout::kDynamicInvocationForwarder,
-                                    /*create_if_absent=*/false);
-  if (!result.IsNull()) return result.raw();
+  result = owner.GetInvocationDispatcher(
+      mangled_name, Array::null_array(),
+      UntaggedFunction::kDynamicInvocationForwarder,
+      /*create_if_absent=*/false);
+  if (!result.IsNull()) return result.ptr();
 
   const bool needs_dyn_forwarder =
       kernel::NeedsDynamicInvocationForwarder(*this);
   if (!allow_add) {
-    return needs_dyn_forwarder ? Function::null() : raw();
+    return needs_dyn_forwarder ? Function::null() : ptr();
   }
 
   // If we failed to find it and possibly need to create it, use a write lock.
   SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
 
   // Try to find it again & return if it was added in the mean time.
-  result =
-      owner.GetInvocationDispatcher(mangled_name, Array::null_array(),
-                                    FunctionLayout::kDynamicInvocationForwarder,
-                                    /*create_if_absent=*/false);
-  if (!result.IsNull()) return result.raw();
+  result = owner.GetInvocationDispatcher(
+      mangled_name, Array::null_array(),
+      UntaggedFunction::kDynamicInvocationForwarder,
+      /*create_if_absent=*/false);
+  if (!result.IsNull()) return result.ptr();
 
   // Otherwise create it & add it.
   result = needs_dyn_forwarder ? CreateDynamicInvocationForwarder(mangled_name)
-                               : raw();
+                               : ptr();
   owner.AddInvocationDispatcher(mangled_name, Array::null_array(), result);
 
-  return result.raw();
+  return result.ptr();
 }
 
 #endif
@@ -3764,14 +3800,13 @@
 }
 
 ArrayPtr Class::invocation_dispatcher_cache() const {
-  return raw_ptr()->invocation_dispatcher_cache();
+  return untag()->invocation_dispatcher_cache<std::memory_order_acquire>();
 }
 
 void Class::Finalize() const {
   auto thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
-  ASSERT(thread->IsMutatorThread());
-  ASSERT(!isolate->all_classes_finalized());
+  auto isolate_group = thread->isolate_group();
+  ASSERT(!thread->isolate()->all_classes_finalized());
   ASSERT(!is_finalized());
   // Prefinalized classes have a VM internal representation and no Dart fields.
   // Their instance size  is precomputed and field offsets are known.
@@ -3779,12 +3814,12 @@
     // Compute offsets of instance fields, instance size and bitmap for unboxed
     // fields.
     const auto host_bitmap = CalculateFieldOffsets();
-    if (raw() == isolate->class_table()->At(id())) {
+    if (ptr() == isolate_group->class_table()->At(id())) {
       // Sets the new size in the class table.
-      isolate->class_table()->SetAt(id(), raw());
+      isolate_group->class_table()->SetAt(id(), ptr());
       if (FLAG_precompiled_mode && !ClassTable::IsTopLevelCid(id())) {
-        isolate->group()->shared_class_table()->SetUnboxedFieldsMapAt(
-            id(), host_bitmap);
+        isolate_group->shared_class_table()->SetUnboxedFieldsMapAt(id(),
+                                                                   host_bitmap);
       }
     }
   }
@@ -3861,15 +3896,8 @@
 }
 
 void Class::DisableCHAOptimizedCode(const Class& subclass) {
-  Thread* thread = Thread::Current();
-  ASSERT(thread->IsMutatorThread());
-  // TODO(dartbug.com/36097): The program_lock acquisition has to move up the
-  // call chain to ClassFinalizer::AllocateFinalizeClass() so that:
-  //   - no two threads allocate-finalize a class at the same time(we should
-  // use the logic similar to what is used in EnsureIsAllocateFinalized()).
-  //   - code is deoptimized before we violate optimization assumptions
-  // potentially done concurrently (AddDirectSubclass/AddDirectImplementor).
-  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  DEBUG_ASSERT(
+      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
   CHACodeArray a(*this);
   if (FLAG_trace_deoptimization && a.HasCodes()) {
     if (subclass.IsNull()) {
@@ -3885,9 +3913,9 @@
   DisableCHAOptimizedCode(Class::Handle());
 }
 
-bool Class::TraceAllocation(Isolate* isolate) const {
+bool Class::TraceAllocation(IsolateGroup* isolate_group) const {
 #ifndef PRODUCT
-  auto class_table = isolate->group()->shared_class_table();
+  auto class_table = isolate_group->shared_class_table();
   return class_table->TraceAllocationFor(id());
 #else
   return false;
@@ -3896,10 +3924,10 @@
 
 void Class::SetTraceAllocation(bool trace_allocation) const {
 #ifndef PRODUCT
-  Isolate* isolate = Isolate::Current();
-  const bool changed = trace_allocation != this->TraceAllocation(isolate);
+  auto isolate_group = IsolateGroup::Current();
+  const bool changed = trace_allocation != this->TraceAllocation(isolate_group);
   if (changed) {
-    auto class_table = isolate->group()->shared_class_table();
+    auto class_table = isolate_group->shared_class_table();
     class_table->SetTraceAllocationFor(id(), trace_allocation);
     DisableAllocationStub();
   }
@@ -3911,13 +3939,13 @@
 ArrayPtr Class::dependent_code() const {
   DEBUG_ASSERT(
       IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
-  return raw_ptr()->dependent_code();
+  return untag()->dependent_code();
 }
 
 void Class::set_dependent_code(const Array& array) const {
   DEBUG_ASSERT(
       IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
-  raw_ptr()->set_dependent_code(array.raw());
+  untag()->set_dependent_code(array.ptr());
 }
 
 // Conventions:
@@ -3959,7 +3987,7 @@
                                 const AbstractType& dst_type,
                                 const String& dst_name) {
   const Array& args = Array::Handle(Array::New(4));
-  const Smi& pos = Smi::Handle(Smi::New(token_pos.value()));
+  const Smi& pos = Smi::Handle(Smi::New(token_pos.Serialize()));
   args.SetAt(0, pos);
   args.SetAt(1, src_value);
   args.SetAt(2, dst_type);
@@ -4025,7 +4053,7 @@
       // Fall through case: Indicate that we didn't find any function or field
       // using a special null instance. This is different from a field being
       // null. Callers make sure that this null does not leak into Dartland.
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
 
     // Invoke the getter and return the result.
@@ -4101,7 +4129,7 @@
                           argument_name);
   }
   field.SetStaticValue(value);
-  return value.raw();
+  return value.ptr();
 }
 
 // Creates a new array of boxed arguments suitable for invoking the callable
@@ -4139,7 +4167,7 @@
   }
   // Set the receiver slot in the callable args.
   callable_args.SetAt(first_arg_index, receiver);
-  return callable_args.raw();
+  return callable_args.ptr();
 }
 
 ObjectPtr Class::Invoke(const String& function_name,
@@ -4171,7 +4199,7 @@
     const Object& getter_result = Object::Handle(
         zone, InvokeGetter(function_name, false, respect_reflectable,
                            check_is_entrypoint));
-    if (getter_result.raw() != Object::sentinel().raw()) {
+    if (getter_result.ptr() != Object::sentinel().ptr()) {
       if (check_is_entrypoint) {
         CHECK_ERROR(EntryPointFieldInvocationError(function_name));
       }
@@ -4249,15 +4277,11 @@
   if (is_finalized()) {
     return Error::null();
   }
-  if (Compiler::IsBackgroundCompilation()) {
-    Compiler::AbortBackgroundCompilation(DeoptId::kNone,
-                                         "Class finalization while compiling");
-  }
   SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   if (is_finalized()) {
     return Error::null();
   }
-  ASSERT(thread->IsMutatorThread());
+  LeaveCompilerScope ncs(thread);
   ASSERT(thread != NULL);
   const Error& error =
       Error::Handle(thread->zone(), ClassFinalizer::LoadClassMembers(*this));
@@ -4268,7 +4292,7 @@
       UNREACHABLE();
     }
   }
-  return error.raw();
+  return error.ptr();
 }
 
 // Ensure that code outdated by finalized class is cleaned up, new instance of
@@ -4278,15 +4302,10 @@
   if (is_allocate_finalized()) {
     return Error::null();
   }
-  if (Compiler::IsBackgroundCompilation()) {
-    Compiler::AbortBackgroundCompilation(
-        DeoptId::kNone, "Class allocate finalization while compiling");
-  }
   SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   if (is_allocate_finalized()) {
     return Error::null();
   }
-  ASSERT(thread->IsMutatorThread());
   ASSERT(thread != NULL);
   Error& error = Error::Handle(thread->zone(), EnsureIsFinalized(thread));
   if (!error.IsNull()) {
@@ -4301,14 +4320,13 @@
     return Error::null();
   }
   error ^= ClassFinalizer::AllocateFinalizeClass(*this);
-  return error.raw();
+  return error.ptr();
 }
 
 void Class::SetFields(const Array& value) const {
   ASSERT(!value.IsNull());
 #if defined(DEBUG)
   Thread* thread = Thread::Current();
-  ASSERT(thread->IsMutatorThread());
   ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
   // Verify that all the fields in the array have this class as owner.
   Field& field = Field::Handle();
@@ -4316,7 +4334,7 @@
   for (intptr_t i = 0; i < len; i++) {
     field ^= value.At(i);
     ASSERT(field.IsOriginal());
-    ASSERT(field.Owner() == raw());
+    ASSERT(field.Owner() == ptr());
   }
 #endif
   // The value of static fields is already initialized to null.
@@ -4326,7 +4344,6 @@
 void Class::AddField(const Field& field) const {
 #if defined(DEBUG)
   Thread* thread = Thread::Current();
-  ASSERT(thread->IsMutatorThread());
   ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
 #endif
   const Array& arr = Array::Handle(fields());
@@ -4338,7 +4355,6 @@
 void Class::AddFields(const GrowableArray<const Field*>& new_fields) const {
 #if defined(DEBUG)
   Thread* thread = Thread::Current();
-  ASSERT(thread->IsMutatorThread());
   ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
 #endif
   const intptr_t num_new_fields = new_fields.length();
@@ -4355,7 +4371,7 @@
 
 bool Class::InjectCIDFields() const {
   if (library() != Library::InternalLibrary() ||
-      Name() != Symbols::ClassID().raw()) {
+      Name() != Symbols::ClassID().ptr()) {
     return false;
   }
 
@@ -4438,12 +4454,12 @@
   result.set_state_bits(0);
   NOT_IN_PRECOMPILED(result.set_kernel_offset(0));
   result.InitEmptyFields();
-  return result.raw();
+  return result.ptr();
 }
 
 template <class FakeInstance, class TargetFakeInstance>
 ClassPtr Class::New(intptr_t index,
-                    Isolate* isolate,
+                    IsolateGroup* isolate_group,
                     bool register_class,
                     bool is_abstract) {
   Class& result =
@@ -4452,9 +4468,9 @@
     result.set_is_abstract();
   }
   if (register_class) {
-    isolate->class_table()->Register(result);
+    isolate_group->class_table()->Register(result);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 ClassPtr Class::New(const Library& lib,
@@ -4477,11 +4493,12 @@
   if (register_class) {
     Isolate::Current()->RegisterClass(result);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 ClassPtr Class::NewInstanceClass() {
-  return Class::New<Instance, RTN::Instance>(kIllegalCid, Isolate::Current());
+  return Class::New<Instance, RTN::Instance>(kIllegalCid,
+                                             IsolateGroup::Current());
 }
 
 ClassPtr Class::NewNativeWrapper(const Library& library,
@@ -4496,14 +4513,14 @@
     cls.set_super_type(Type::Handle(Type::ObjectType()));
     // Compute instance size. First word contains a pointer to a properly
     // sized typed array once the first native field has been set.
-    const intptr_t host_instance_size = sizeof(InstanceLayout) + kWordSize;
+    const intptr_t host_instance_size = sizeof(UntaggedInstance) + kWordSize;
 #if defined(DART_PRECOMPILER)
     const intptr_t target_instance_size =
         compiler::target::Instance::InstanceSize() +
         compiler::target::kWordSize;
 #else
     const intptr_t target_instance_size =
-        sizeof(InstanceLayout) + compiler::target::kWordSize;
+        sizeof(UntaggedInstance) + compiler::target::kWordSize;
 #endif
     cls.set_instance_size(
         RoundedAllocationSize(host_instance_size),
@@ -4511,17 +4528,20 @@
     cls.set_next_field_offset(host_instance_size, target_instance_size);
     cls.set_num_native_fields(field_count);
     cls.set_is_allocate_finalized();
+    // The signature of the constructor yet to be added to this class will have
+    // to be finalized explicitly, since the class is prematurely marked as
+    // 'is_allocate_finalized' and finalization of member types will not occur.
     cls.set_is_declaration_loaded();
     cls.set_is_type_finalized();
     cls.set_is_synthesized_class();
     library.AddClass(cls);
-    return cls.raw();
+    return cls.ptr();
   } else {
     return Class::null();
   }
 }
 
-ClassPtr Class::NewStringClass(intptr_t class_id, Isolate* isolate) {
+ClassPtr Class::NewStringClass(intptr_t class_id, IsolateGroup* isolate_group) {
   intptr_t host_instance_size, target_instance_size;
   if (class_id == kOneByteStringCid) {
     host_instance_size = OneByteString::InstanceSize();
@@ -4541,8 +4561,8 @@
     target_instance_size = compiler::target::RoundedAllocationSize(
         RTN::ExternalTwoByteString::InstanceSize());
   }
-  Class& result = Class::Handle(
-      New<String, RTN::String>(class_id, isolate, /*register_class=*/false));
+  Class& result = Class::Handle(New<String, RTN::String>(
+      class_id, isolate_group, /*register_class=*/false));
   result.set_instance_size(host_instance_size, target_instance_size);
 
   const intptr_t host_next_field_offset = String::NextFieldOffset();
@@ -4550,17 +4570,18 @@
   result.set_next_field_offset(host_next_field_offset,
                                target_next_field_offset);
   result.set_is_prefinalized();
-  isolate->class_table()->Register(result);
-  return result.raw();
+  isolate_group->class_table()->Register(result);
+  return result.ptr();
 }
 
-ClassPtr Class::NewTypedDataClass(intptr_t class_id, Isolate* isolate) {
+ClassPtr Class::NewTypedDataClass(intptr_t class_id,
+                                  IsolateGroup* isolate_group) {
   ASSERT(IsTypedDataClassId(class_id));
   const intptr_t host_instance_size = TypedData::InstanceSize();
   const intptr_t target_instance_size =
       compiler::target::RoundedAllocationSize(RTN::TypedData::InstanceSize());
   Class& result = Class::Handle(New<TypedData, RTN::TypedData>(
-      class_id, isolate, /*register_class=*/false));
+      class_id, isolate_group, /*register_class=*/false));
   result.set_instance_size(host_instance_size, target_instance_size);
 
   const intptr_t host_next_field_offset = TypedData::NextFieldOffset();
@@ -4568,17 +4589,18 @@
   result.set_next_field_offset(host_next_field_offset,
                                target_next_field_offset);
   result.set_is_prefinalized();
-  isolate->class_table()->Register(result);
-  return result.raw();
+  isolate_group->class_table()->Register(result);
+  return result.ptr();
 }
 
-ClassPtr Class::NewTypedDataViewClass(intptr_t class_id, Isolate* isolate) {
+ClassPtr Class::NewTypedDataViewClass(intptr_t class_id,
+                                      IsolateGroup* isolate_group) {
   ASSERT(IsTypedDataViewClassId(class_id));
   const intptr_t host_instance_size = TypedDataView::InstanceSize();
   const intptr_t target_instance_size = compiler::target::RoundedAllocationSize(
       RTN::TypedDataView::InstanceSize());
   Class& result = Class::Handle(New<TypedDataView, RTN::TypedDataView>(
-      class_id, isolate, /*register_class=*/false));
+      class_id, isolate_group, /*register_class=*/false));
   result.set_instance_size(host_instance_size, target_instance_size);
 
   const intptr_t host_next_field_offset = TypedDataView::NextFieldOffset();
@@ -4587,17 +4609,18 @@
   result.set_next_field_offset(host_next_field_offset,
                                target_next_field_offset);
   result.set_is_prefinalized();
-  isolate->class_table()->Register(result);
-  return result.raw();
+  isolate_group->class_table()->Register(result);
+  return result.ptr();
 }
 
-ClassPtr Class::NewExternalTypedDataClass(intptr_t class_id, Isolate* isolate) {
+ClassPtr Class::NewExternalTypedDataClass(intptr_t class_id,
+                                          IsolateGroup* isolate_group) {
   ASSERT(IsExternalTypedDataClassId(class_id));
   const intptr_t host_instance_size = ExternalTypedData::InstanceSize();
   const intptr_t target_instance_size = compiler::target::RoundedAllocationSize(
       RTN::ExternalTypedData::InstanceSize());
   Class& result = Class::Handle(New<ExternalTypedData, RTN::ExternalTypedData>(
-      class_id, isolate, /*register_class=*/false));
+      class_id, isolate_group, /*register_class=*/false));
 
   const intptr_t host_next_field_offset = ExternalTypedData::NextFieldOffset();
   const intptr_t target_next_field_offset =
@@ -4606,17 +4629,18 @@
   result.set_next_field_offset(host_next_field_offset,
                                target_next_field_offset);
   result.set_is_prefinalized();
-  isolate->class_table()->Register(result);
-  return result.raw();
+  isolate_group->class_table()->Register(result);
+  return result.ptr();
 }
 
-ClassPtr Class::NewPointerClass(intptr_t class_id, Isolate* isolate) {
+ClassPtr Class::NewPointerClass(intptr_t class_id,
+                                IsolateGroup* isolate_group) {
   ASSERT(IsFfiPointerClassId(class_id));
   intptr_t host_instance_size = Pointer::InstanceSize();
   intptr_t target_instance_size =
       compiler::target::RoundedAllocationSize(RTN::Pointer::InstanceSize());
-  Class& result = Class::Handle(
-      New<Pointer, RTN::Pointer>(class_id, isolate, /*register_class=*/false));
+  Class& result = Class::Handle(New<Pointer, RTN::Pointer>(
+      class_id, isolate_group, /*register_class=*/false));
   result.set_instance_size(host_instance_size, target_instance_size);
   result.set_type_arguments_field_offset(Pointer::type_arguments_offset(),
                                          RTN::Pointer::type_arguments_offset());
@@ -4627,16 +4651,16 @@
   result.set_next_field_offset(host_next_field_offset,
                                target_next_field_offset);
   result.set_is_prefinalized();
-  isolate->class_table()->Register(result);
-  return result.raw();
+  isolate_group->class_table()->Register(result);
+  return result.ptr();
 }
 
 void Class::set_name(const String& value) const {
-  ASSERT(raw_ptr()->name() == String::null());
+  ASSERT(untag()->name() == String::null());
   ASSERT(value.IsSymbol());
-  raw_ptr()->set_name(value.raw());
+  untag()->set_name(value.ptr());
 #if !defined(PRODUCT)
-  if (raw_ptr()->user_name() == String::null()) {
+  if (untag()->user_name() == String::null()) {
     // TODO(johnmccutchan): Eagerly set user name for VM isolate classes,
     // lazily set user name for the other classes.
     // Generate and set user_name.
@@ -4649,7 +4673,7 @@
 
 #if !defined(PRODUCT)
 void Class::set_user_name(const String& value) const {
-  raw_ptr()->set_user_name(value.raw());
+  untag()->set_user_name(value.ptr());
 }
 #endif  // !defined(PRODUCT)
 
@@ -4729,8 +4753,6 @@
       return Symbols::Function().ToCString();
     case kClosureDataCid:
       return Symbols::ClosureData().ToCString();
-    case kSignatureDataCid:
-      return Symbols::SignatureData().ToCString();
     case kFfiTrampolineDataCid:
       return Symbols::FfiTrampolineData().ToCString();
     case kFieldCid:
@@ -4804,7 +4826,7 @@
   }
   String& name = String::Handle(Name());
   name = Symbols::New(Thread::Current(), String::ScrubName(name));
-  if (name.raw() == Symbols::FutureImpl().raw() &&
+  if (name.ptr() == Symbols::FutureImpl().ptr() &&
       library() == Library::AsyncLibrary()) {
     return Symbols::Future().ToCString();
   }
@@ -4812,17 +4834,17 @@
 }
 
 void Class::set_script(const Script& value) const {
-  raw_ptr()->set_script(value.raw());
+  untag()->set_script(value.ptr());
 }
 
 void Class::set_token_pos(TokenPosition token_pos) const {
   ASSERT(!token_pos.IsClassifying());
-  StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
+  StoreNonPointer(&untag()->token_pos_, token_pos);
 }
 
 void Class::set_end_token_pos(TokenPosition token_pos) const {
   ASSERT(!token_pos.IsClassifying());
-  StoreNonPointer(&raw_ptr()->end_token_pos_, token_pos);
+  StoreNonPointer(&untag()->end_token_pos_, token_pos);
 }
 
 int32_t Class::SourceFingerprint() const {
@@ -4844,15 +4866,15 @@
 
 void Class::set_is_declaration_loaded() const {
   ASSERT(!is_declaration_loaded());
-  set_state_bits(
-      ClassLoadingBits::update(ClassLayout::kDeclarationLoaded, state_bits()));
+  set_state_bits(ClassLoadingBits::update(UntaggedClass::kDeclarationLoaded,
+                                          state_bits()));
 }
 
 void Class::set_is_type_finalized() const {
   ASSERT(is_declaration_loaded());
   ASSERT(!is_type_finalized());
   set_state_bits(
-      ClassLoadingBits::update(ClassLayout::kTypeFinalized, state_bits()));
+      ClassLoadingBits::update(UntaggedClass::kTypeFinalized, state_bits()));
 }
 
 void Class::set_is_synthesized_class() const {
@@ -4886,24 +4908,24 @@
 void Class::set_is_finalized() const {
   ASSERT(!is_finalized());
   set_state_bits(
-      ClassFinalizedBits::update(ClassLayout::kFinalized, state_bits()));
+      ClassFinalizedBits::update(UntaggedClass::kFinalized, state_bits()));
 }
 
 void Class::set_is_allocate_finalized() const {
   ASSERT(!is_allocate_finalized());
-  set_state_bits(ClassFinalizedBits::update(ClassLayout::kAllocateFinalized,
+  set_state_bits(ClassFinalizedBits::update(UntaggedClass::kAllocateFinalized,
                                             state_bits()));
 }
 
 void Class::set_is_prefinalized() const {
   ASSERT(!is_finalized());
   set_state_bits(
-      ClassFinalizedBits::update(ClassLayout::kPreFinalized, state_bits()));
+      ClassFinalizedBits::update(UntaggedClass::kPreFinalized, state_bits()));
 }
 
 void Class::set_interfaces(const Array& value) const {
   ASSERT(!value.IsNull());
-  raw_ptr()->set_interfaces(value.raw());
+  untag()->set_interfaces(value.ptr());
 }
 
 void Class::AddDirectImplementor(const Class& implementor,
@@ -4912,10 +4934,10 @@
   ASSERT(is_implemented());
   ASSERT(!implementor.IsNull());
   GrowableObjectArray& direct_implementors =
-      GrowableObjectArray::Handle(raw_ptr()->direct_implementors());
+      GrowableObjectArray::Handle(untag()->direct_implementors());
   if (direct_implementors.IsNull()) {
     direct_implementors = GrowableObjectArray::New(4, Heap::kOld);
-    raw_ptr()->set_direct_implementors(direct_implementors.raw());
+    untag()->set_direct_implementors(direct_implementors.ptr());
   }
 #if defined(DEBUG)
   // Verify that the same class is not added twice.
@@ -4925,7 +4947,7 @@
   // This is rare and harmless.
   if (!is_mixin) {
     for (intptr_t i = 0; i < direct_implementors.Length(); i++) {
-      ASSERT(direct_implementors.At(i) != implementor.raw());
+      ASSERT(direct_implementors.At(i) != implementor.ptr());
     }
   }
 #endif
@@ -4934,25 +4956,25 @@
 
 void Class::ClearDirectImplementors() const {
   ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
-  raw_ptr()->set_direct_implementors(GrowableObjectArray::null());
+  untag()->set_direct_implementors(GrowableObjectArray::null());
 }
 
 void Class::AddDirectSubclass(const Class& subclass) const {
   ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
   ASSERT(!subclass.IsNull());
-  ASSERT(subclass.SuperClass() == raw());
+  ASSERT(subclass.SuperClass() == ptr());
   // Do not keep track of the direct subclasses of class Object.
   ASSERT(!IsObjectClass());
   GrowableObjectArray& direct_subclasses =
-      GrowableObjectArray::Handle(raw_ptr()->direct_subclasses());
+      GrowableObjectArray::Handle(untag()->direct_subclasses());
   if (direct_subclasses.IsNull()) {
     direct_subclasses = GrowableObjectArray::New(4, Heap::kOld);
-    raw_ptr()->set_direct_subclasses(direct_subclasses.raw());
+    untag()->set_direct_subclasses(direct_subclasses.ptr());
   }
 #if defined(DEBUG)
   // Verify that the same class is not added twice.
   for (intptr_t i = 0; i < direct_subclasses.Length(); i++) {
-    ASSERT(direct_subclasses.At(i) != subclass.raw());
+    ASSERT(direct_subclasses.At(i) != subclass.ptr());
   }
 #endif
   direct_subclasses.Add(subclass, Heap::kOld);
@@ -4960,28 +4982,28 @@
 
 void Class::ClearDirectSubclasses() const {
   ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
-  raw_ptr()->set_direct_subclasses(GrowableObjectArray::null());
+  untag()->set_direct_subclasses(GrowableObjectArray::null());
 }
 
 ArrayPtr Class::constants() const {
-  return raw_ptr()->constants();
+  return untag()->constants();
 }
 
 void Class::set_constants(const Array& value) const {
-  raw_ptr()->set_constants(value.raw());
+  untag()->set_constants(value.ptr());
 }
 
 void Class::set_declaration_type(const Type& value) const {
   ASSERT(id() != kDynamicCid && id() != kVoidCid);
   ASSERT(!value.IsNull() && value.IsCanonical() && value.IsOld());
   ASSERT((declaration_type() == Object::null()) ||
-         (declaration_type() == value.raw()));  // Set during own finalization.
+         (declaration_type() == value.ptr()));  // Set during own finalization.
   // Since DeclarationType is used as the runtime type of instances of a
   // non-generic class, its nullability must be kNonNullable.
   // The exception is DeclarationType of Null which is kNullable.
   ASSERT(value.type_class_id() != kNullCid || value.IsNullable());
   ASSERT(value.type_class_id() == kNullCid || value.IsNonNullable());
-  raw_ptr()->set_declaration_type(value.raw());
+  untag()->set_declaration_type<std::memory_order_release>(value.ptr());
 }
 
 TypePtr Class::DeclarationType() const {
@@ -5004,21 +5026,29 @@
   // The exception is type Null which is stored as kNullable.
   Type& type =
       Type::Handle(Type::New(*this, TypeArguments::Handle(type_parameters()),
-                             token_pos(), Nullability::kNonNullable));
+                             Nullability::kNonNullable));
   type ^= ClassFinalizer::FinalizeType(type);
   set_declaration_type(type);
-  return type.raw();
+  return type.ptr();
 }
 
 void Class::set_allocation_stub(const Code& value) const {
   // Never clear the stub as it may still be a target, but will be GC-d if
   // not referenced.
   ASSERT(!value.IsNull());
-  ASSERT(raw_ptr()->allocation_stub() == Code::null());
-  raw_ptr()->set_allocation_stub(value.raw());
+  ASSERT(untag()->allocation_stub() == Code::null());
+  untag()->set_allocation_stub(value.ptr());
 }
 
 void Class::DisableAllocationStub() const {
+  {
+    const Code& existing_stub = Code::Handle(allocation_stub());
+    if (existing_stub.IsNull()) {
+      return;
+    }
+  }
+  auto thread = Thread::Current();
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& existing_stub = Code::Handle(allocation_stub());
   if (existing_stub.IsNull()) {
     return;
@@ -5027,18 +5057,18 @@
   // Change the stub so that the next caller will regenerate the stub.
   existing_stub.DisableStubCode();
   // Disassociate the existing stub from class.
-  raw_ptr()->set_allocation_stub(Code::null());
+  untag()->set_allocation_stub(Code::null());
 }
 
 bool Class::IsDartFunctionClass() const {
-  return raw() == Type::Handle(Type::DartFunctionType()).type_class();
+  return ptr() == Type::Handle(Type::DartFunctionType()).type_class();
 }
 
 bool Class::IsFutureClass() const {
   // Looking up future_class in the object store would not work, because
   // this function is called during class finalization, before the object store
   // field would be initialized by InitKnownObjects().
-  return (Name() == Symbols::Future().raw()) &&
+  return (Name() == Symbols::Future().ptr()) &&
          (library() == Library::AsyncLibrary());
 }
 
@@ -5056,7 +5086,7 @@
   classid_t this_cid = cls.id();
   ASSERT(this_cid != kNullCid && this_cid != kNeverCid &&
          this_cid != kDynamicCid && this_cid != kVoidCid);
-  // Type T1 must have a type class (e.g. not a type parameter).
+  // Type T1 must have a type class (e.g. not a type param or a function type).
   ASSERT(other.HasTypeClass());
   const classid_t other_cid = other.type_class_id();
   if (other_cid == kDynamicCid || other_cid == kVoidCid) {
@@ -5064,11 +5094,11 @@
   }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   // Nullability of left and right hand sides is verified in strong mode only.
-  const bool verified_nullability = !isolate->use_strict_null_safety_checks() ||
-                                    nullability != Nullability::kNullable ||
-                                    !other.IsNonNullable();
+  const bool verified_nullability =
+      !isolate_group->use_strict_null_safety_checks() ||
+      nullability != Nullability::kNullable || !other.IsNonNullable();
 
   // Right Object.
   if (other_cid == kObjectCid) {
@@ -5079,7 +5109,7 @@
       TypeArguments::Handle(zone, other.arguments());
   // Use the 'this_class' object as if it was the receiver of this method, but
   // instead of recursing, reset it to the super class and loop.
-  Class& this_class = Class::Handle(zone, cls.raw());
+  Class& this_class = Class::Handle(zone, cls.ptr());
   while (true) {
     // Apply additional subtyping rules if T0 or T1 are 'FutureOr'.
 
@@ -5088,7 +5118,7 @@
     //     T0 <: T1 iff Future<S0> <: T1 and S0 <: T1
     if (this_cid == kFutureOrCid) {
       // Check Future<S0> <: T1.
-      ObjectStore* object_store = Isolate::Current()->object_store();
+      ObjectStore* object_store = IsolateGroup::Current()->object_store();
       const Class& future_class =
           Class::Handle(zone, object_store->future_class());
       ASSERT(!future_class.IsNull() && future_class.NumTypeParameters() == 1 &&
@@ -5146,7 +5176,7 @@
     }
 
     // Check for reflexivity.
-    if (this_class.raw() == other_class.raw()) {
+    if (this_class.ptr() == other_class.ptr()) {
       const intptr_t num_type_params = this_class.NumTypeParameters();
       if (num_type_params == 0) {
         return true;
@@ -5217,7 +5247,7 @@
 }
 
 bool Class::IsTopLevel() const {
-  return Name() == Symbols::TopLevel().raw();
+  return Name() == Symbols::TopLevel().ptr();
 }
 
 bool Class::IsPrivate() const {
@@ -5297,24 +5327,24 @@
 FunctionPtr Class::CheckFunctionType(const Function& func, MemberKind kind) {
   if ((kind == kInstance) || (kind == kInstanceAllowAbstract)) {
     if (func.IsDynamicFunction(kind == kInstanceAllowAbstract)) {
-      return func.raw();
+      return func.ptr();
     }
   } else if (kind == kStatic) {
     if (func.IsStaticFunction()) {
-      return func.raw();
+      return func.ptr();
     }
   } else if (kind == kConstructor) {
     if (func.IsGenerativeConstructor()) {
       ASSERT(!func.is_static());
-      return func.raw();
+      return func.ptr();
     }
   } else if (kind == kFactory) {
     if (func.IsFactory()) {
       ASSERT(func.is_static());
-      return func.raw();
+      return func.ptr();
     }
   } else if (kind == kAny) {
-    return func.raw();
+    return func.ptr();
   }
   return Function::null();
 }
@@ -5342,13 +5372,13 @@
     // If we want to increase resolver speed by avoiding the need for read lock,
     // we could make change this hash table to be lock-free for the reader.
     const Array& hash_table =
-        Array::Handle(thread->zone(), raw_ptr()->functions_hash_table());
+        Array::Handle(thread->zone(), untag()->functions_hash_table());
     if (!hash_table.IsNull()) {
-      ClassFunctionsSet set(hash_table.raw());
+      ClassFunctionsSet set(hash_table.ptr());
       REUSABLE_STRING_HANDLESCOPE(thread);
       function ^= set.GetOrNull(FunctionName(name, &(thread->StringHandle())));
       // No mutations.
-      ASSERT(set.Release().raw() == hash_table.raw());
+      ASSERT(set.Release().ptr() == hash_table.ptr());
       return function.IsNull() ? Function::null()
                                : CheckFunctionType(function, kind);
     }
@@ -5358,7 +5388,7 @@
     NoSafepointScope no_safepoint;
     for (intptr_t i = 0; i < len; i++) {
       function ^= funcs.At(i);
-      if (function.name() == name.raw()) {
+      if (function.name() == name.ptr()) {
         return CheckFunctionType(function, kind);
       }
     }
@@ -5382,6 +5412,7 @@
   ASSERT(!IsNull());
   Thread* thread = Thread::Current();
   RELEASE_ASSERT(is_finalized());
+  SafepointReadRwLocker ml(thread, thread->isolate_group()->program_lock());
   REUSABLE_ARRAY_HANDLESCOPE(thread);
   REUSABLE_FUNCTION_HANDLESCOPE(thread);
   REUSABLE_STRING_HANDLESCOPE(thread);
@@ -5430,7 +5461,7 @@
     function ^= funcs.At(i);
     function_name = function.name();
     if (MatchesAccessorName(function_name, prefix, prefix_length, name)) {
-      return function.raw();
+      return function.ptr();
     }
   }
 
@@ -5468,14 +5499,14 @@
     // Use fast raw pointer string compare for symbols.
     for (intptr_t i = 0; i < len; i++) {
       field ^= flds.At(i);
-      if (name.raw() == field.name()) {
+      if (name.ptr() == field.name()) {
         if (kind == kInstance) {
-          return field.is_static() ? Field::null() : field.raw();
+          return field.is_static() ? Field::null() : field.ptr();
         } else if (kind == kStatic) {
-          return field.is_static() ? field.raw() : Field::null();
+          return field.is_static() ? field.ptr() : Field::null();
         }
         ASSERT(kind == kAny);
-        return field.raw();
+        return field.ptr();
       }
     }
   } else {
@@ -5485,12 +5516,12 @@
       field_name = field.name();
       if (name.Equals(field_name)) {
         if (kind == kInstance) {
-          return field.is_static() ? Field::null() : field.raw();
+          return field.is_static() ? Field::null() : field.ptr();
         } else if (kind == kStatic) {
-          return field.is_static() ? field.raw() : Field::null();
+          return field.is_static() ? field.ptr() : Field::null();
         }
         ASSERT(kind == kAny);
-        return field.raw();
+        return field.ptr();
       }
     }
   }
@@ -5522,7 +5553,7 @@
       continue;
     }
     if (String::EqualsIgnoringPrivateKey(field_name, name)) {
-      return field.raw();
+      return field.ptr();
     }
   }
   return Field::null();
@@ -5531,7 +5562,7 @@
 FieldPtr Class::LookupInstanceFieldAllowPrivate(const String& name) const {
   Field& field = Field::Handle(LookupFieldAllowPrivate(name, true));
   if (!field.IsNull() && !field.is_static()) {
-    return field.raw();
+    return field.ptr();
   }
   return Field::null();
 }
@@ -5539,7 +5570,7 @@
 FieldPtr Class::LookupStaticFieldAllowPrivate(const String& name) const {
   Field& field = Field::Handle(LookupFieldAllowPrivate(name));
   if (!field.IsNull() && field.is_static()) {
-    return field.raw();
+    return field.ptr();
   }
   return Field::null();
 }
@@ -5613,7 +5644,7 @@
 
   // Called when growing the table.
   static bool IsMatch(const Object& a, const Object& b) {
-    return a.raw() == b.raw();
+    return a.ptr() == b.ptr();
   }
   static bool IsMatch(const KeyType& a, const Object& b) {
     return a.Matches(ObjectType::Cast(b));
@@ -5624,7 +5655,7 @@
   static uword Hash(const KeyType& key) { return key.Hash(); }
   static ObjectPtr NewKey(const KeyType& obj) {
     if (obj.key_ != NULL) {
-      return obj.key_->raw();
+      return obj.key_->ptr();
     } else {
       UNIMPLEMENTED();
       return NULL;
@@ -5638,26 +5669,27 @@
 
 // Returns an instance of Double or Double::null().
 DoublePtr Class::LookupCanonicalDouble(Zone* zone, double value) const {
-  ASSERT(this->raw() == Isolate::Current()->object_store()->double_class());
+  ASSERT(this->ptr() ==
+         IsolateGroup::Current()->object_store()->double_class());
   if (this->constants() == Array::null()) return Double::null();
 
   Double& canonical_value = Double::Handle(zone);
   CanonicalDoubleSet constants(zone, this->constants());
   canonical_value ^= constants.GetOrNull(CanonicalDoubleKey(value));
   this->set_constants(constants.Release());
-  return canonical_value.raw();
+  return canonical_value.ptr();
 }
 
 // Returns an instance of Mint or Mint::null().
 MintPtr Class::LookupCanonicalMint(Zone* zone, int64_t value) const {
-  ASSERT(this->raw() == Isolate::Current()->object_store()->mint_class());
+  ASSERT(this->ptr() == IsolateGroup::Current()->object_store()->mint_class());
   if (this->constants() == Array::null()) return Mint::null();
 
   Mint& canonical_value = Mint::Handle(zone);
   CanonicalMintSet constants(zone, this->constants());
   canonical_value ^= constants.GetOrNull(CanonicalMintKey(value));
   this->set_constants(constants.Release());
-  return canonical_value.raw();
+  return canonical_value.ptr();
 }
 
 class CanonicalInstanceKey {
@@ -5690,7 +5722,7 @@
   static bool IsMatch(const Object& a, const Object& b) {
     ASSERT(!(a.IsString() || a.IsInteger() || a.IsAbstractType()));
     ASSERT(!(b.IsString() || b.IsInteger() || b.IsAbstractType()));
-    return a.raw() == b.raw();
+    return a.ptr() == b.ptr();
   }
   static bool IsMatch(const CanonicalInstanceKey& a, const Object& b) {
     return a.Matches(Instance::Cast(b));
@@ -5702,14 +5734,14 @@
   }
   static uword Hash(const CanonicalInstanceKey& key) { return key.Hash(); }
   static ObjectPtr NewKey(const CanonicalInstanceKey& obj) {
-    return obj.key_.raw();
+    return obj.key_.ptr();
   }
 };
 typedef UnorderedHashSet<CanonicalInstanceTraits> CanonicalInstancesSet;
 
 InstancePtr Class::LookupCanonicalInstance(Zone* zone,
                                            const Instance& value) const {
-  ASSERT(this->raw() == value.clazz());
+  ASSERT(this->ptr() == value.clazz());
   ASSERT(is_finalized() || is_prefinalized());
   Instance& canonical_value = Instance::Handle(zone);
   if (this->constants() != Array::null()) {
@@ -5717,12 +5749,12 @@
     canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value));
     this->set_constants(constants.Release());
   }
-  return canonical_value.raw();
+  return canonical_value.ptr();
 }
 
 InstancePtr Class::InsertCanonicalConstant(Zone* zone,
                                            const Instance& constant) const {
-  ASSERT(this->raw() == constant.clazz());
+  ASSERT(this->ptr() == constant.clazz());
   Instance& canonical_value = Instance::Handle(zone);
   if (this->constants() == Array::null()) {
     CanonicalInstancesSet constants(
@@ -5735,7 +5767,7 @@
     canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant));
     this->set_constants(constants.Release());
   }
-  return canonical_value.raw();
+  return canonical_value.ptr();
 }
 
 void Class::InsertCanonicalDouble(Zone* zone, const Double& constant) const {
@@ -5771,7 +5803,7 @@
 
   set_constants(Object::null_array());
 
-  CanonicalInstancesSet set(zone, old_constants.raw());
+  CanonicalInstancesSet set(zone, old_constants.ptr());
   Instance& constant = Instance::Handle(zone);
   CanonicalInstancesSet::Iterator it(&set);
   while (it.MoveNext()) {
@@ -5786,38 +5818,29 @@
   set.Release();
 }
 
-bool Class::RequireLegacyErasureOfConstants(Zone* zone) const {
+bool Class::RequireCanonicalTypeErasureOfConstants(Zone* zone) const {
   const intptr_t num_type_params = NumTypeParameters();
   const intptr_t num_type_args = NumTypeArguments();
   const intptr_t from_index = num_type_args - num_type_params;
   Instance& constant = Instance::Handle(zone);
   TypeArguments& type_arguments = TypeArguments::Handle(zone);
-  AbstractType& type = AbstractType::Handle(zone);
   CanonicalInstancesSet set(zone, constants());
   CanonicalInstancesSet::Iterator it(&set);
+  bool result = false;
   while (it.MoveNext()) {
     constant ^= set.GetKey(it.Current());
     ASSERT(!constant.IsNull());
     ASSERT(!constant.IsTypeArguments());
     ASSERT(!constant.IsType());
     type_arguments = constant.GetTypeArguments();
-    if (type_arguments.IsNull()) {
-      continue;
-    }
-    for (intptr_t i = 0; i < num_type_params; i++) {
-      type = type_arguments.TypeAt(from_index + i);
-      if (!type.IsLegacy() && !type.IsVoidType() && !type.IsDynamicType() &&
-          !type.IsNullType()) {
-        set.Release();
-        return true;
-      }
-      // It is not possible for a legacy type to have non-legacy type
-      // arguments or for a legacy function type to have non-legacy parameter
-      // types, non-legacy type parameters, or required named parameters.
+    if (type_arguments.RequireConstCanonicalTypeErasure(zone, from_index,
+                                                        num_type_params)) {
+      result = true;
+      break;
     }
   }
   set.Release();
-  return false;
+  return result;
 }
 
 intptr_t TypeArguments::ComputeNullability() const {
@@ -5851,7 +5874,7 @@
 }
 
 void TypeArguments::set_nullability(intptr_t value) const {
-  raw_ptr()->set_nullability(Smi::New(value));
+  untag()->set_nullability(Smi::New(value));
 }
 
 intptr_t TypeArguments::HashForRange(intptr_t from_index, intptr_t len) const {
@@ -5888,10 +5911,10 @@
                                         intptr_t total_length) const {
   if (other_length == 0) {
     ASSERT(IsCanonical());
-    return raw();
+    return ptr();
   } else if (other_length == total_length) {
     ASSERT(other.IsCanonical());
-    return other.raw();
+    return other.ptr();
   } else if (IsNull() && other.IsNull()) {
     return TypeArguments::null();
   }
@@ -5926,7 +5949,7 @@
     type = other.TypeAt(i);
     result.SetTypeAt(this_len + i, type);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 StringPtr TypeArguments::Name() const {
@@ -5943,13 +5966,10 @@
   return Symbols::New(thread, printer.buffer());
 }
 
-void TypeArguments::PrintSubvectorName(
-    intptr_t from_index,
-    intptr_t len,
-    NameVisibility name_visibility,
-    BaseTextBuffer* printer,
-    NameDisambiguation name_disambiguation /* = NameDisambiguation::kNo */)
-    const {
+void TypeArguments::PrintSubvectorName(intptr_t from_index,
+                                       intptr_t len,
+                                       NameVisibility name_visibility,
+                                       BaseTextBuffer* printer) const {
   printer->AddString("<");
   AbstractType& type = AbstractType::Handle();
   for (intptr_t i = 0; i < len; i++) {
@@ -5958,7 +5978,7 @@
       if (type.IsNull()) {
         printer->AddString("null");  // Unfinalized vector.
       } else {
-        type.PrintName(name_visibility, printer, name_disambiguation);
+        type.PrintName(name_visibility, printer);
       }
     } else {
       printer->AddString("dynamic");
@@ -5975,7 +5995,7 @@
   if (IsNull()) {
     return buffer->AddString("null");
   }
-  buffer->Printf("(H%" Px ")", Smi::Value(raw_ptr()->hash()));
+  buffer->Printf("(H%" Px ")", Smi::Value(untag()->hash()));
   auto& type_at = AbstractType::Handle();
   for (intptr_t i = 0; i < Length(); i++) {
     type_at = TypeAt(i);
@@ -5988,7 +6008,7 @@
                                           intptr_t len,
                                           TypeEquality kind,
                                           TrailPtr trail) const {
-  if (this->raw() == other.raw()) {
+  if (this->ptr() == other.ptr()) {
     return true;
   }
   if (IsNull() || other.IsNull()) {
@@ -6011,7 +6031,7 @@
   return true;
 }
 
-bool TypeArguments::IsRecursive() const {
+bool TypeArguments::IsRecursive(TrailPtr trail) const {
   if (IsNull()) return false;
   const intptr_t num_types = Length();
   AbstractType& type = AbstractType::Handle();
@@ -6021,7 +6041,28 @@
     // argument is still being finalized and is definitely recursive. The null
     // type argument will be replaced by a non-null type before the type is
     // marked as finalized.
-    if (type.IsNull() || type.IsRecursive()) {
+    if (type.IsNull() || type.IsRecursive(trail)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool TypeArguments::RequireConstCanonicalTypeErasure(Zone* zone,
+                                                     intptr_t from_index,
+                                                     intptr_t len,
+                                                     TrailPtr trail) const {
+  if (IsNull()) return false;
+  ASSERT(Length() >= (from_index + len));
+  AbstractType& type = AbstractType::Handle(zone);
+  for (intptr_t i = 0; i < len; i++) {
+    type = TypeAt(from_index + i);
+    if (type.IsNonNullable() ||
+        (type.IsNullable() &&
+         type.RequireConstCanonicalTypeErasure(zone, trail))) {
+      // It is not possible for a legacy type to have non-nullable type
+      // arguments or for a legacy function type to have non-nullable type in
+      // its signature.
       return true;
     }
   }
@@ -6076,7 +6117,7 @@
 ArrayPtr TypeArguments::instantiations() const {
   // We rely on the fact that any loads from the array are dependent loads and
   // avoid the load-acquire barrier here.
-  return raw_ptr()->instantiations();
+  return untag()->instantiations();
 }
 
 void TypeArguments::set_instantiations(const Array& value) const {
@@ -6084,7 +6125,7 @@
   // when releasing the pointer to the array pointer.
   // => We have to use store-release here.
   ASSERT(!value.IsNull());
-  raw_ptr()->set_instantiations<std::memory_order_release>(value.raw());
+  untag()->set_instantiations<std::memory_order_release>(value.ptr());
 }
 
 bool TypeArguments::HasCount(intptr_t count) const {
@@ -6098,26 +6139,26 @@
   if (IsNull()) {
     return 0;
   }
-  return Smi::Value(raw_ptr()->length());
+  return Smi::Value(untag()->length());
 }
 
 intptr_t TypeArguments::nullability() const {
   if (IsNull()) {
     return 0;
   }
-  return Smi::Value(raw_ptr()->nullability());
+  return Smi::Value(untag()->nullability());
 }
 
 AbstractTypePtr TypeArguments::TypeAt(intptr_t index) const {
   ASSERT(!IsNull());
   ASSERT((index >= 0) && (index < Length()));
-  return raw_ptr()->element(index);
+  return untag()->element(index);
 }
 
 AbstractTypePtr TypeArguments::TypeAtNullSafe(intptr_t index) const {
   if (IsNull()) {
     // null vector represents infinite list of dynamics
-    return Type::dynamic_type().raw();
+    return Type::dynamic_type().ptr();
   }
   ASSERT((index >= 0) && (index < Length()));
   return TypeAt(index);
@@ -6126,7 +6167,7 @@
 void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
   ASSERT(!IsCanonical());
   ASSERT((index >= 0) && (index < Length()));
-  return raw_ptr()->set_element(index, value.raw());
+  return untag()->set_element(index, value.ptr());
 }
 
 bool TypeArguments::IsSubvectorInstantiated(intptr_t from_index,
@@ -6280,10 +6321,10 @@
     *with_runtime_check = false;
   }
   const intptr_t num_type_args = Length();
-  const intptr_t num_parent_type_params = function.NumParentTypeParameters();
+  const intptr_t num_parent_type_args = function.NumParentTypeArguments();
   const intptr_t num_function_type_params = function.NumTypeParameters();
   const intptr_t num_function_type_args =
-      num_parent_type_params + num_function_type_params;
+      num_parent_type_args + num_function_type_params;
   if (num_type_args > num_function_type_args) {
     // This vector cannot be a prefix of a shorter vector.
     return false;
@@ -6337,7 +6378,7 @@
   if ((instantiator_type_arguments.IsNull() ||
        instantiator_type_arguments.Length() == Length()) &&
       IsUninstantiatedIdentity()) {
-    return instantiator_type_arguments.raw();
+    return instantiator_type_arguments.ptr();
   }
   const intptr_t num_types = Length();
   TypeArguments& instantiated_array =
@@ -6359,12 +6400,12 @@
       // A returned null type indicates a failed instantiation in dead code that
       // must be propagated up to the caller, the optimizing compiler.
       if (type.IsNull()) {
-        return Object::empty_type_arguments().raw();
+        return Object::empty_type_arguments().ptr();
       }
     }
     instantiated_array.SetTypeAt(i, type);
   }
-  return instantiated_array.raw();
+  return instantiated_array.ptr();
 }
 
 TypeArgumentsPtr TypeArguments::InstantiateAndCanonicalizeFrom(
@@ -6391,10 +6432,10 @@
     if ((prior_instantiations.At(
              index +
              TypeArguments::Instantiation::kInstantiatorTypeArgsIndex) ==
-         instantiator_type_arguments.raw()) &&
+         instantiator_type_arguments.ptr()) &&
         (prior_instantiations.At(
              index + TypeArguments::Instantiation::kFunctionTypeArgsIndex) ==
-         function_type_arguments.raw())) {
+         function_type_arguments.ptr())) {
       return TypeArguments::RawCast(prior_instantiations.At(
           index + TypeArguments::Instantiation::kInstantiatedTypeArgsIndex));
     }
@@ -6412,7 +6453,7 @@
   result = result.Canonicalize(thread, nullptr);
   // InstantiateAndCanonicalizeFrom is not reentrant. It cannot have been called
   // indirectly, so the prior_instantiations array cannot have grown.
-  ASSERT(prior_instantiations.raw() == instantiations());
+  ASSERT(prior_instantiations.ptr() == instantiations());
   // Add instantiator and function type args and result to instantiations array.
   intptr_t length = prior_instantiations.Length();
   if ((index + TypeArguments::Instantiation::kSizeInWords) >= length) {
@@ -6450,7 +6491,7 @@
   prior_instantiations.SetAtRelease(
       index + TypeArguments::Instantiation::kInstantiatorTypeArgsIndex,
       instantiator_type_arguments);
-  return result.raw();
+  return result.ptr();
 }
 
 TypeArgumentsPtr TypeArguments::New(intptr_t len, Heap::Space space) {
@@ -6470,37 +6511,37 @@
     result.set_nullability(0);
   }
   // The zero array should have been initialized.
-  ASSERT(Object::zero_array().raw() != Array::null());
+  ASSERT(Object::zero_array().ptr() != Array::null());
   COMPILE_ASSERT(TypeArguments::kNoInstantiator == 0);
   result.set_instantiations(Object::zero_array());
-  return result.raw();
+  return result.ptr();
 }
 
 void TypeArguments::SetLength(intptr_t value) const {
   ASSERT(!IsCanonical());
   // This is only safe because we create a new Smi, which does not cause
   // heap allocation.
-  raw_ptr()->set_length(Smi::New(value));
+  untag()->set_length(Smi::New(value));
 }
 
 TypeArgumentsPtr TypeArguments::Canonicalize(Thread* thread,
                                              TrailPtr trail) const {
   if (IsNull() || IsCanonical()) {
     ASSERT(IsOld());
-    return this->raw();
+    return this->ptr();
   }
   const intptr_t num_types = Length();
   if (num_types == 0) {
-    return TypeArguments::empty_type_arguments().raw();
+    return TypeArguments::empty_type_arguments().ptr();
   } else if (IsRaw(0, num_types)) {
     return TypeArguments::null();
   }
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  ObjectStore* object_store = isolate->object_store();
+  auto isolate_group = thread->isolate_group();
+  ObjectStore* object_store = isolate_group->object_store();
   TypeArguments& result = TypeArguments::Handle(zone);
   {
-    SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
     CanonicalTypeArgumentsSet table(zone,
                                     object_store->canonical_type_arguments());
     result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this));
@@ -6515,7 +6556,7 @@
       if (IsCanonical()) {
         // Canonicalizing this type_arg canonicalized this type.
         ASSERT(IsRecursive());
-        return this->raw();
+        return this->ptr();
       }
       SetTypeAt(i, type_arg);
     }
@@ -6524,7 +6565,7 @@
     if (IsRecursive()) {
       SetHash(0);
     }
-    SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
     CanonicalTypeArgumentsSet table(zone,
                                     object_store->canonical_type_arguments());
     // Since we canonicalized some type arguments above we need to lookup
@@ -6536,7 +6577,7 @@
       if (this->IsNew()) {
         result ^= Object::Clone(*this, Heap::kOld);
       } else {
-        result = this->raw();
+        result = this->ptr();
       }
       ASSERT(result.IsOld());
       result.ComputeNullability();
@@ -6551,7 +6592,7 @@
   ASSERT(!result.IsNull());
   ASSERT(result.IsTypeArguments());
   ASSERT(result.IsCanonical());
-  return result.raw();
+  return result.ptr();
 }
 
 void TypeArguments::EnumerateURIs(URIs* uris) const {
@@ -6590,7 +6631,7 @@
   result.set_origin_class(origin_class);
   result.set_script(Script::Handle(origin_class.script()));
   result.set_library_kernel_offset(-1);
-  return result.raw();
+  return result.ptr();
 }
 
 PatchClassPtr PatchClass::New(const Class& patched_class,
@@ -6600,7 +6641,7 @@
   result.set_origin_class(patched_class);
   result.set_script(script);
   result.set_library_kernel_offset(-1);
-  return result.raw();
+  return result.ptr();
 }
 
 PatchClassPtr PatchClass::New() {
@@ -6611,19 +6652,19 @@
 }
 
 void PatchClass::set_patched_class(const Class& value) const {
-  raw_ptr()->set_patched_class(value.raw());
+  untag()->set_patched_class(value.ptr());
 }
 
 void PatchClass::set_origin_class(const Class& value) const {
-  raw_ptr()->set_origin_class(value.raw());
+  untag()->set_origin_class(value.ptr());
 }
 
 void PatchClass::set_script(const Script& value) const {
-  raw_ptr()->set_script(value.raw());
+  untag()->set_script(value.ptr());
 }
 
 void PatchClass::set_library_kernel_data(const ExternalTypedData& data) const {
-  raw_ptr()->set_library_kernel_data(data.raw());
+  untag()->set_library_kernel_data(data.ptr());
 }
 
 intptr_t Function::Hash() const {
@@ -6640,7 +6681,7 @@
 }
 
 void Function::InstallOptimizedCode(const Code& code) const {
-  DEBUG_ASSERT(IsMutatorOrAtSafepoint());
+  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
   // We may not have previous code if FLAG_precompile is set.
   // Hot-reload may have already disabled the current code.
   if (HasCode() && !Code::Handle(CurrentCode()).IsDisabled()) {
@@ -6650,50 +6691,64 @@
 }
 
 void Function::SetInstructions(const Code& value) const {
-  DEBUG_ASSERT(IsMutatorOrAtSafepoint());
-  SetInstructionsSafe(value);
+  // Ensure that nobody is executing this function when we install it.
+  if (untag()->code() != Code::null() && HasCode()) {
+    SafepointOperationScope safepoint(Thread::Current());
+    SetInstructionsSafe(value);
+  } else {
+    ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+    SetInstructionsSafe(value);
+  }
 }
 
 void Function::SetInstructionsSafe(const Code& value) const {
-  raw_ptr()->set_code(value.raw());
-  StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint());
-  StoreNonPointer(&raw_ptr()->unchecked_entry_point_,
+  untag()->set_code(value.ptr());
+  StoreNonPointer(&untag()->entry_point_, value.EntryPoint());
+  StoreNonPointer(&untag()->unchecked_entry_point_,
                   value.UncheckedEntryPoint());
 }
 
 void Function::AttachCode(const Code& value) const {
-  DEBUG_ASSERT(IsMutatorOrAtSafepoint());
+  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
   // Finish setting up code before activating it.
   value.set_owner(*this);
   SetInstructions(value);
   ASSERT(Function::Handle(value.function()).IsNull() ||
-         (value.function() == this->raw()));
+         (value.function() == this->ptr()));
 }
 
 bool Function::HasCode() const {
   NoSafepointScope no_safepoint;
-  ASSERT(raw_ptr()->code() != Code::null());
-  return raw_ptr()->code() != StubCode::LazyCompile().raw();
+  ASSERT(untag()->code() != Code::null());
+  return untag()->code() != StubCode::LazyCompile().ptr();
 }
 
 bool Function::HasCode(FunctionPtr function) {
   NoSafepointScope no_safepoint;
-  ASSERT(function->ptr()->code() != Code::null());
-  return function->ptr()->code() != StubCode::LazyCompile().raw();
+  ASSERT(function->untag()->code() != Code::null());
+  return function->untag()->code() != StubCode::LazyCompile().ptr();
 }
 
 void Function::ClearCode() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
 #else
-  ASSERT(Thread::Current()->IsMutatorThread());
-
-  raw_ptr()->set_unoptimized_code(Code::null());
-
+  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+  untag()->set_unoptimized_code(Code::null());
   SetInstructions(StubCode::LazyCompile());
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
+void Function::ClearCodeSafe() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#else
+  untag()->set_unoptimized_code(Code::null());
+
+  SetInstructionsSafe(StubCode::LazyCompile());
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+}
+
 void Function::EnsureHasCompiledUnoptimizedCode() const {
   ASSERT(!ForceOptimize());
   Thread* thread = Thread::Current();
@@ -6711,9 +6766,10 @@
 void Function::SwitchToUnoptimizedCode() const {
   ASSERT(HasOptimizedCode());
   Thread* thread = Thread::Current();
+  DEBUG_ASSERT(
+      thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
   Isolate* isolate = thread->isolate();
   Zone* zone = thread->zone();
-  ASSERT(thread->IsMutatorThread());
   // TODO(35224): DEBUG_ASSERT(thread->TopErrorHandlerIsExitFrame());
   const Code& current_code = Code::Handle(zone, CurrentCode());
 
@@ -6770,13 +6826,13 @@
 #else
   DEBUG_ASSERT(IsMutatorOrAtSafepoint());
   ASSERT(value.IsNull() || !value.is_optimized());
-  raw_ptr()->set_unoptimized_code(value.raw());
+  untag()->set_unoptimized_code(value.ptr());
 #endif
 }
 
 ContextScopePtr Function::context_scope() const {
   if (IsClosureFunction()) {
-    const Object& obj = Object::Handle(raw_ptr()->data());
+    const Object& obj = Object::Handle(untag()->data());
     ASSERT(!obj.IsNull());
     return ClosureData::Cast(obj).context_scope();
   }
@@ -6785,7 +6841,7 @@
 
 void Function::set_context_scope(const ContextScope& value) const {
   if (IsClosureFunction()) {
-    const Object& obj = Object::Handle(raw_ptr()->data());
+    const Object& obj = Object::Handle(untag()->data());
     ASSERT(!obj.IsNull());
     ClosureData::Cast(obj).set_context_scope(value);
     return;
@@ -6795,7 +6851,7 @@
 
 InstancePtr Function::implicit_static_closure() const {
   if (IsImplicitStaticClosureFunction()) {
-    const Object& obj = Object::Handle(raw_ptr()->data());
+    const Object& obj = Object::Handle(untag()->data());
     ASSERT(!obj.IsNull());
     return ClosureData::Cast(obj).implicit_static_closure();
   }
@@ -6804,7 +6860,7 @@
 
 void Function::set_implicit_static_closure(const Instance& closure) const {
   if (IsImplicitStaticClosureFunction()) {
-    const Object& obj = Object::Handle(raw_ptr()->data());
+    const Object& obj = Object::Handle(untag()->data());
     ASSERT(!obj.IsNull());
     ClosureData::Cast(obj).set_implicit_static_closure(closure);
     return;
@@ -6813,88 +6869,79 @@
 }
 
 ScriptPtr Function::eval_script() const {
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   if (obj.IsScript()) {
-    return Script::Cast(obj).raw();
+    return Script::Cast(obj).ptr();
   }
   return Script::null();
 }
 
 void Function::set_eval_script(const Script& script) const {
   ASSERT(token_pos() == TokenPosition::kMinSource);
-  ASSERT(raw_ptr()->data() == Object::null());
+  ASSERT(untag()->data() == Object::null());
   set_data(script);
 }
 
 FunctionPtr Function::extracted_method_closure() const {
-  ASSERT(kind() == FunctionLayout::kMethodExtractor);
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  ASSERT(kind() == UntaggedFunction::kMethodExtractor);
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(obj.IsFunction());
-  return Function::Cast(obj).raw();
+  return Function::Cast(obj).ptr();
 }
 
 void Function::set_extracted_method_closure(const Function& value) const {
-  ASSERT(kind() == FunctionLayout::kMethodExtractor);
-  ASSERT(raw_ptr()->data() == Object::null());
+  ASSERT(kind() == UntaggedFunction::kMethodExtractor);
+  ASSERT(untag()->data() == Object::null());
   set_data(value);
 }
 
 ArrayPtr Function::saved_args_desc() const {
-  ASSERT(kind() == FunctionLayout::kNoSuchMethodDispatcher ||
-         kind() == FunctionLayout::kInvokeFieldDispatcher);
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  ASSERT(kind() == UntaggedFunction::kNoSuchMethodDispatcher ||
+         kind() == UntaggedFunction::kInvokeFieldDispatcher);
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(obj.IsArray());
-  return Array::Cast(obj).raw();
+  return Array::Cast(obj).ptr();
 }
 
 void Function::set_saved_args_desc(const Array& value) const {
-  ASSERT(kind() == FunctionLayout::kNoSuchMethodDispatcher ||
-         kind() == FunctionLayout::kInvokeFieldDispatcher);
-  ASSERT(raw_ptr()->data() == Object::null());
+  ASSERT(kind() == UntaggedFunction::kNoSuchMethodDispatcher ||
+         kind() == UntaggedFunction::kInvokeFieldDispatcher);
+  ASSERT(untag()->data() == Object::null());
   set_data(value);
 }
 
 FieldPtr Function::accessor_field() const {
-  ASSERT(kind() == FunctionLayout::kImplicitGetter ||
-         kind() == FunctionLayout::kImplicitSetter ||
-         kind() == FunctionLayout::kImplicitStaticGetter ||
-         kind() == FunctionLayout::kFieldInitializer);
-  return Field::RawCast(raw_ptr()->data());
+  ASSERT(kind() == UntaggedFunction::kImplicitGetter ||
+         kind() == UntaggedFunction::kImplicitSetter ||
+         kind() == UntaggedFunction::kImplicitStaticGetter ||
+         kind() == UntaggedFunction::kFieldInitializer);
+  return Field::RawCast(untag()->data());
 }
 
 void Function::set_accessor_field(const Field& value) const {
-  ASSERT(kind() == FunctionLayout::kImplicitGetter ||
-         kind() == FunctionLayout::kImplicitSetter ||
-         kind() == FunctionLayout::kImplicitStaticGetter ||
-         kind() == FunctionLayout::kFieldInitializer);
+  ASSERT(kind() == UntaggedFunction::kImplicitGetter ||
+         kind() == UntaggedFunction::kImplicitSetter ||
+         kind() == UntaggedFunction::kImplicitStaticGetter ||
+         kind() == UntaggedFunction::kFieldInitializer);
   // Top level classes may be finalized multiple times.
-  ASSERT(raw_ptr()->data() == Object::null() ||
-         raw_ptr()->data() == value.raw());
+  ASSERT(untag()->data() == Object::null() || untag()->data() == value.ptr());
   set_data(value);
 }
 
 FunctionPtr Function::parent_function() const {
-  if (IsClosureFunction() || IsSignatureFunction()) {
-    const Object& obj = Object::Handle(raw_ptr()->data());
+  if (IsClosureFunction()) {
+    const Object& obj = Object::Handle(untag()->data());
     ASSERT(!obj.IsNull());
-    if (IsClosureFunction()) {
-      return ClosureData::Cast(obj).parent_function();
-    } else {
-      return SignatureData::Cast(obj).parent_function();
-    }
+    return ClosureData::Cast(obj).parent_function();
   }
   return Function::null();
 }
 
 void Function::set_parent_function(const Function& value) const {
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
-  if (IsClosureFunction()) {
-    ClosureData::Cast(obj).set_parent_function(value);
-  } else {
-    ASSERT(IsSignatureFunction());
-    SignatureData::Cast(obj).set_parent_function(value);
-  }
+  ASSERT(IsClosureFunction());
+  ClosureData::Cast(obj).set_parent_function(value);
 }
 
 TypeArgumentsPtr Function::InstantiateToBounds(
@@ -6911,7 +6958,7 @@
     if (kind_out != nullptr) {
       *kind_out = DefaultTypeArgumentsKind::kIsInstantiated;
     }
-    return Object::empty_type_arguments().raw();
+    return Object::empty_type_arguments().ptr();
   }
   auto& result = TypeArguments::Handle(thread->zone(), type_parameters());
   result = InstantiateTypeArgumentsToBounds(thread, result);
@@ -6923,7 +6970,7 @@
                     ? DefaultTypeArgumentsKind::kIsInstantiated
                     : DefaultTypeArgumentsKind::kNeedsInstantiation;
   }
-  return result.raw();
+  return result.ptr();
 }
 
 void Function::UpdateCachedDefaultTypeArguments(Thread* thread) const {
@@ -6934,8 +6981,9 @@
   }
   if (CachesDefaultTypeArguments()) {
     auto defaults = &Object::empty_type_arguments();
-    if (NumTypeParameters(thread) > 0) {
-      const auto& params = TypeArguments::Handle(zone, type_parameters());
+    const FunctionType& sig = FunctionType::Handle(zone, signature());
+    if (sig.NumTypeParameters(thread) > 0) {
+      const auto& params = TypeArguments::Handle(zone, sig.type_parameters());
       const intptr_t num_params = params.Length();
       auto& new_defaults = TypeArguments::Handle(
           zone, TypeArguments::New(num_params, Heap::kNew));
@@ -6971,7 +7019,7 @@
     UNREACHABLE();
   }
   const auto& closure_data =
-      ClosureData::Handle(ClosureData::RawCast(raw_ptr()->data()));
+      ClosureData::Handle(ClosureData::RawCast(untag()->data()));
   ASSERT(!closure_data.IsNull());
   if (kind_out != nullptr) {
     *kind_out = DefaultTypeArgumentsKindField::decode(
@@ -6985,13 +7033,13 @@
     UNREACHABLE();
   }
   const auto& closure_data =
-      ClosureData::Handle(ClosureData::RawCast(raw_ptr()->data()));
+      ClosureData::Handle(ClosureData::RawCast(untag()->data()));
   ASSERT(!closure_data.IsNull());
   intptr_t updated_info = closure_data.default_type_arguments_info();
   auto kind = DefaultTypeArgumentsKindFor(value);
   ASSERT(kind != DefaultTypeArgumentsKind::kInvalid);
   updated_info = DefaultTypeArgumentsKindField::update(kind, updated_info);
-  updated_info = NumParentTypeParametersField::update(NumParentTypeParameters(),
+  updated_info = NumParentTypeParametersField::update(NumParentTypeArguments(),
                                                       updated_info);
   closure_data.set_default_type_arguments_info(updated_info);
   // We could just store null for the ksharesFunction/kSharesInstantiator cases,
@@ -7014,38 +7062,18 @@
   return DefaultTypeArgumentsKind::kNeedsInstantiation;
 }
 
-FunctionPtr Function::GetGeneratedClosure() const {
-  const auto& closure_functions = GrowableObjectArray::Handle(
-      Isolate::Current()->object_store()->closure_functions());
-  auto& entry = Object::Handle();
-
-  for (auto i = (closure_functions.Length() - 1); i >= 0; i--) {
-    entry = closure_functions.At(i);
-
-    ASSERT(entry.IsFunction());
-
-    const auto& closure_function = Function::Cast(entry);
-    if (closure_function.parent_function() == raw() &&
-        closure_function.is_generated_body()) {
-      return closure_function.raw();
-    }
-  }
-
-  return Function::null();
-}
-
 // Enclosing outermost function of this local function.
 FunctionPtr Function::GetOutermostFunction() const {
   FunctionPtr parent = parent_function();
   if (parent == Object::null()) {
-    return raw();
+    return ptr();
   }
   Function& function = Function::Handle();
   do {
     function = parent;
     parent = function.parent_function();
   } while (parent != Object::null());
-  return function.raw();
+  return function.ptr();
 }
 
 bool Function::HasGenericParent() const {
@@ -7065,27 +7093,27 @@
 }
 
 FunctionPtr Function::implicit_closure_function() const {
-  if (IsClosureFunction() || IsSignatureFunction() || IsFactory() ||
-      IsDispatcherOrImplicitAccessor() || IsFieldInitializer()) {
+  if (IsClosureFunction() || IsFactory() || IsDispatcherOrImplicitAccessor() ||
+      IsFieldInitializer() || IsFfiTrampoline()) {
     return Function::null();
   }
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(obj.IsNull() || obj.IsScript() || obj.IsFunction() || obj.IsArray());
   if (obj.IsNull() || obj.IsScript()) {
     return Function::null();
   }
   if (obj.IsFunction()) {
-    return Function::Cast(obj).raw();
+    return Function::Cast(obj).ptr();
   }
   ASSERT(is_native());
   ASSERT(obj.IsArray());
   const Object& res = Object::Handle(Array::Cast(obj).At(1));
-  return res.IsNull() ? Function::null() : Function::Cast(res).raw();
+  return res.IsNull() ? Function::null() : Function::Cast(res).ptr();
 }
 
 void Function::set_implicit_closure_function(const Function& value) const {
-  ASSERT(!IsClosureFunction() && !IsSignatureFunction());
-  const Object& old_data = Object::Handle(raw_ptr()->data());
+  ASSERT(!IsClosureFunction());
+  const Object& old_data = Object::Handle(untag()->data());
   if (is_native()) {
     ASSERT(old_data.IsArray());
     ASSERT((Array::Cast(old_data).At(1) == Object::null()) || value.IsNull());
@@ -7102,36 +7130,23 @@
   }
 }
 
-TypePtr Function::ExistingSignatureType() const {
-  const Object& obj = Object::Handle(raw_ptr()->data());
-  ASSERT(!obj.IsNull());
-  if (IsSignatureFunction()) {
-    return SignatureData::Cast(obj).signature_type();
-  } else if (IsClosureFunction()) {
-    return ClosureData::Cast(obj).signature_type();
-  } else {
-    ASSERT(IsFfiTrampoline());
-    return FfiTrampolineData::Cast(obj).signature_type();
-  }
-}
-
-void Function::SetFfiCSignature(const Function& sig) const {
+void Function::SetFfiCSignature(const FunctionType& sig) const {
   ASSERT(IsFfiTrampoline());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
   FfiTrampolineData::Cast(obj).set_c_signature(sig);
 }
 
-FunctionPtr Function::FfiCSignature() const {
+FunctionTypePtr Function::FfiCSignature() const {
   ASSERT(IsFfiTrampoline());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
   return FfiTrampolineData::Cast(obj).c_signature();
 }
 
 bool Function::FfiCSignatureContainsHandles() const {
   ASSERT(IsFfiTrampoline());
-  const Function& c_signature = Function::Handle(FfiCSignature());
+  const FunctionType& c_signature = FunctionType::Handle(FfiCSignature());
   const intptr_t num_params = c_signature.num_fixed_parameters();
   for (intptr_t i = 0; i < num_params; i++) {
     const bool is_handle =
@@ -7145,128 +7160,78 @@
          kFfiHandleCid;
 }
 
+bool Function::FfiCSignatureReturnsStruct() const {
+  ASSERT(IsFfiTrampoline());
+  const FunctionType& c_signature = FunctionType::Handle(FfiCSignature());
+  const auto& return_type = AbstractType::Handle(c_signature.result_type());
+  const bool predefined = IsFfiTypeClassId(return_type.type_class_id());
+  return !predefined;
+}
+
 int32_t Function::FfiCallbackId() const {
   ASSERT(IsFfiTrampoline());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
   return FfiTrampolineData::Cast(obj).callback_id();
 }
 
 void Function::SetFfiCallbackId(int32_t value) const {
   ASSERT(IsFfiTrampoline());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
   FfiTrampolineData::Cast(obj).set_callback_id(value);
 }
 
 FunctionPtr Function::FfiCallbackTarget() const {
   ASSERT(IsFfiTrampoline());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
   return FfiTrampolineData::Cast(obj).callback_target();
 }
 
 void Function::SetFfiCallbackTarget(const Function& target) const {
   ASSERT(IsFfiTrampoline());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
   FfiTrampolineData::Cast(obj).set_callback_target(target);
 }
 
 InstancePtr Function::FfiCallbackExceptionalReturn() const {
   ASSERT(IsFfiTrampoline());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
   return FfiTrampolineData::Cast(obj).callback_exceptional_return();
 }
 
 void Function::SetFfiCallbackExceptionalReturn(const Instance& value) const {
   ASSERT(IsFfiTrampoline());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(!obj.IsNull());
   FfiTrampolineData::Cast(obj).set_callback_exceptional_return(value);
 }
 
-TypePtr Function::SignatureType(Nullability nullability) const {
-  Type& type = Type::Handle(ExistingSignatureType());
-  if (type.IsNull()) {
-    // The function type of this function is not yet cached and needs to be
-    // constructed and cached here.
-    // A function type is type parameterized in the same way as the owner class
-    // of its non-static signature function.
-    // It is not type parameterized if its signature function is static, or if
-    // none of its result type or formal parameter types are type parameterized.
-    // Unless the function type is a generic typedef, the type arguments of the
-    // function type are not explicitly stored in the function type as a vector
-    // of type arguments.
-    // The type class of a non-typedef function type is always the non-generic
-    // _Closure class, whether the type is generic or not.
-    // The type class of a typedef function type is always the typedef class,
-    // which may be generic, in which case the type stores type arguments.
-    // With the introduction of generic functions, we may reach here before the
-    // function type parameters have been resolved. Therefore, we cannot yet
-    // check whether the function type has an instantiated signature.
-    // We can do it only when the signature has been resolved.
-    // We only set the type class of the function type to the typedef class
-    // if the signature of the function type is the signature of the typedef.
-    // Note that a function type can have a typedef class as owner without
-    // representing the typedef, as in the following example:
-    // typedef F(f(int x)); where the type of f is a function type with F as
-    // owner, without representing the function type of F.
-    Class& scope_class = Class::Handle(Owner());
-    if (!scope_class.IsTypedefClass() ||
-        (scope_class.signature_function() != raw())) {
-      scope_class = Isolate::Current()->object_store()->closure_class();
-    }
-    const TypeArguments& signature_type_arguments =
-        TypeArguments::Handle(scope_class.type_parameters());
-    // Return the still unfinalized signature type.
-    type = Type::New(scope_class, signature_type_arguments, token_pos(),
-                     nullability);
-    type.set_signature(*this);
-    SetSignatureType(type);
-  }
-  return type.ToNullability(nullability, Heap::kOld);
-}
-
-void Function::SetSignatureType(const Type& value) const {
-  const Object& obj = Object::Handle(raw_ptr()->data());
-  ASSERT(!obj.IsNull());
-  if (IsSignatureFunction()) {
-    SignatureData::Cast(obj).set_signature_type(value);
-    ASSERT(!value.IsCanonical() || (value.signature() == this->raw()));
-  } else if (IsClosureFunction()) {
-    ClosureData::Cast(obj).set_signature_type(value);
-  } else {
-    ASSERT(IsFfiTrampoline());
-    FfiTrampolineData::Cast(obj).set_signature_type(value);
-  }
-}
-
-const char* Function::KindToCString(FunctionLayout::Kind kind) {
-  return FunctionLayout::KindToCString(kind);
+const char* Function::KindToCString(UntaggedFunction::Kind kind) {
+  return UntaggedFunction::KindToCString(kind);
 }
 
 FunctionPtr Function::ForwardingTarget() const {
-  ASSERT(kind() == FunctionLayout::kDynamicInvocationForwarder);
+  ASSERT(kind() == UntaggedFunction::kDynamicInvocationForwarder);
   Array& checks = Array::Handle();
-  checks ^= raw_ptr()->data();
+  checks ^= untag()->data();
   return Function::RawCast(checks.At(0));
 }
 
 void Function::SetForwardingChecks(const Array& checks) const {
-  ASSERT(kind() == FunctionLayout::kDynamicInvocationForwarder);
+  ASSERT(kind() == UntaggedFunction::kDynamicInvocationForwarder);
   ASSERT(checks.Length() >= 1);
   ASSERT(Object::Handle(checks.At(0)).IsFunction());
   set_data(checks);
 }
 
 // This field is heavily overloaded:
-//   eval function:           Script expression source
 //   kernel eval function:    Array[0] = Script
 //                            Array[1] = Kernel data
 //                            Array[2] = Kernel offset of enclosing library
-//   signature function:      SignatureData
 //   method extractor:        Function extracted closure function
 //   implicit getter:         Field
 //   implicit setter:         Field
@@ -7284,7 +7249,7 @@
 //   dyn inv forwarder:       Array[0] = Function target
 //                            Array[1] = TypeArguments default type args
 void Function::set_data(const Object& value) const {
-  raw_ptr()->set_data(value.raw());
+  untag()->set_data(value.ptr());
 }
 
 bool Function::IsInFactoryScope() const {
@@ -7300,42 +7265,43 @@
 
 void Function::set_name(const String& value) const {
   ASSERT(value.IsSymbol());
-  raw_ptr()->set_name(value.raw());
+  untag()->set_name(value.ptr());
 }
 
 void Function::set_owner(const Object& value) const {
-  ASSERT(!value.IsNull() || IsSignatureFunction());
-  raw_ptr()->set_owner(value.raw());
+  ASSERT(!value.IsNull());
+  untag()->set_owner(value.ptr());
 }
 
 RegExpPtr Function::regexp() const {
-  ASSERT(kind() == FunctionLayout::kIrregexpFunction);
-  const Array& pair = Array::Cast(Object::Handle(raw_ptr()->data()));
+  ASSERT(kind() == UntaggedFunction::kIrregexpFunction);
+  const Array& pair = Array::Cast(Object::Handle(untag()->data()));
   return RegExp::RawCast(pair.At(0));
 }
 
 class StickySpecialization : public BitField<intptr_t, bool, 0, 1> {};
 class StringSpecializationCid
-    : public BitField<intptr_t, intptr_t, 1, ObjectLayout::kClassIdTagSize> {};
+    : public BitField<intptr_t, intptr_t, 1, UntaggedObject::kClassIdTagSize> {
+};
 
 intptr_t Function::string_specialization_cid() const {
-  ASSERT(kind() == FunctionLayout::kIrregexpFunction);
-  const Array& pair = Array::Cast(Object::Handle(raw_ptr()->data()));
+  ASSERT(kind() == UntaggedFunction::kIrregexpFunction);
+  const Array& pair = Array::Cast(Object::Handle(untag()->data()));
   return StringSpecializationCid::decode(Smi::Value(Smi::RawCast(pair.At(1))));
 }
 
 bool Function::is_sticky_specialization() const {
-  ASSERT(kind() == FunctionLayout::kIrregexpFunction);
-  const Array& pair = Array::Cast(Object::Handle(raw_ptr()->data()));
+  ASSERT(kind() == UntaggedFunction::kIrregexpFunction);
+  const Array& pair = Array::Cast(Object::Handle(untag()->data()));
   return StickySpecialization::decode(Smi::Value(Smi::RawCast(pair.At(1))));
 }
 
 void Function::SetRegExpData(const RegExp& regexp,
                              intptr_t string_specialization_cid,
                              bool sticky) const {
-  ASSERT(kind() == FunctionLayout::kIrregexpFunction);
+  ASSERT(kind() == UntaggedFunction::kIrregexpFunction);
   ASSERT(IsStringClassId(string_specialization_cid));
-  ASSERT(raw_ptr()->data() == Object::null());
+  ASSERT(untag()->data() == Object::null());
   const Array& pair = Array::Handle(Array::New(2, Heap::kOld));
   pair.SetAt(0, regexp);
   pair.SetAt(1, Smi::Handle(Smi::New(StickySpecialization::encode(sticky) |
@@ -7346,7 +7312,7 @@
 
 StringPtr Function::native_name() const {
   ASSERT(is_native());
-  const Object& obj = Object::Handle(raw_ptr()->data());
+  const Object& obj = Object::Handle(untag()->data());
   ASSERT(obj.IsArray());
   return String::RawCast(Array::Cast(obj).At(0));
 }
@@ -7363,10 +7329,10 @@
   // closure function.
   //
   // We therefore handle both cases.
-  const Object& old_data = Object::Handle(zone, raw_ptr()->data());
+  const Object& old_data = Object::Handle(zone, untag()->data());
   ASSERT(old_data.IsNull() ||
          (old_data.IsFunction() &&
-          Function::Handle(zone, Function::RawCast(old_data.raw()))
+          Function::Handle(zone, Function::RawCast(old_data.ptr()))
               .IsImplicitClosureFunction()));
 
   const Array& pair = Array::Handle(zone, Array::New(2, Heap::kOld));
@@ -7375,47 +7341,83 @@
   set_data(pair);
 }
 
-void Function::set_result_type(const AbstractType& value) const {
+void Function::set_signature(const FunctionType& value) const {
+  // Signature may be reset to null in aot to save space.
+  untag()->set_signature(value.ptr());
+  if (!value.IsNull()) {
+    ASSERT(NumImplicitParameters() == value.num_implicit_parameters());
+    UpdateCachedDefaultTypeArguments(Thread::Current());
+  }
+}
+
+void FunctionType::set_result_type(const AbstractType& value) const {
   ASSERT(!value.IsNull());
-  raw_ptr()->set_result_type(value.raw());
+  untag()->set_result_type(value.ptr());
 }
 
 AbstractTypePtr Function::ParameterTypeAt(intptr_t index) const {
-  const Array& parameter_types = Array::Handle(raw_ptr()->parameter_types());
+  const Array& parameter_types =
+      Array::Handle(untag()->signature()->untag()->parameter_types());
   return AbstractType::RawCast(parameter_types.At(index));
 }
 
-void Function::SetParameterTypeAt(intptr_t index,
-                                  const AbstractType& value) const {
+AbstractTypePtr FunctionType::ParameterTypeAt(intptr_t index) const {
+  const Array& parameter_types = Array::Handle(untag()->parameter_types());
+  return AbstractType::RawCast(parameter_types.At(index));
+}
+
+void FunctionType::SetParameterTypeAt(intptr_t index,
+                                      const AbstractType& value) const {
   ASSERT(!value.IsNull());
-  // Method extractor parameters are shared and are in the VM heap.
-  ASSERT(kind() != FunctionLayout::kMethodExtractor);
-  const Array& parameter_types = Array::Handle(raw_ptr()->parameter_types());
+  const Array& parameter_types = Array::Handle(untag()->parameter_types());
   parameter_types.SetAt(index, value);
 }
 
 void Function::set_parameter_types(const Array& value) const {
-  raw_ptr()->set_parameter_types(value.raw());
+  ASSERT(value.IsNull() || value.Length() > 0);
+  untag()->signature()->untag()->set_parameter_types(value.ptr());
+}
+
+void FunctionType::set_parameter_types(const Array& value) const {
+  ASSERT(value.IsNull() || value.Length() > 0);
+  untag()->set_parameter_types(value.ptr());
 }
 
 StringPtr Function::ParameterNameAt(intptr_t index) const {
-  const Array& parameter_names = Array::Handle(raw_ptr()->parameter_names());
+  const Array& parameter_names = Array::Handle(untag()->parameter_names());
   return String::RawCast(parameter_names.At(index));
 }
 
-void Function::SetParameterNameAt(intptr_t index, const String& value) const {
+void Function::SetParameterNamesFrom(const FunctionType& signature) const {
+  untag()->set_parameter_names(signature.parameter_names());
+}
+
+StringPtr FunctionType::ParameterNameAt(intptr_t index) const {
+  const Array& parameter_names = Array::Handle(untag()->parameter_names());
+  return String::RawCast(parameter_names.At(index));
+}
+
+void FunctionType::SetParameterNameAt(intptr_t index,
+                                      const String& value) const {
   ASSERT(!value.IsNull() && value.IsSymbol());
-  const Array& parameter_names = Array::Handle(raw_ptr()->parameter_names());
+  const Array& parameter_names = Array::Handle(untag()->parameter_names());
   parameter_names.SetAt(index, value);
 }
 
 void Function::set_parameter_names(const Array& value) const {
-  raw_ptr()->set_parameter_names(value.raw());
+  ASSERT(value.IsNull() || value.Length() > 0);
+  untag()->set_parameter_names(value.ptr());
 }
 
-void Function::CreateNameArrayIncludingFlags(Heap::Space space) const {
+void FunctionType::set_parameter_names(const Array& value) const {
+  ASSERT(value.IsNull() || value.Length() > 0);
+  untag()->set_parameter_names(value.ptr());
+}
+
+void FunctionType::CreateNameArrayIncludingFlags(Heap::Space space) const {
   // Currently, we only store flags for named parameters that are required.
   const intptr_t num_parameters = NumParameters();
+  if (num_parameters == 0) return;
   intptr_t num_total_slots = num_parameters;
   if (HasOptionalNamedParameters()) {
     const intptr_t last_index = (NumOptionalNamedParameters() - 1) /
@@ -7434,8 +7436,8 @@
   set_parameter_names(array);
 }
 
-intptr_t Function::GetRequiredFlagIndex(intptr_t index,
-                                        intptr_t* flag_mask) const {
+intptr_t FunctionType::GetRequiredFlagIndex(intptr_t index,
+                                            intptr_t* flag_mask) const {
   // If these calculations change, also change
   // FlowGraphBuilder::BuildClosureCallHasRequiredNamedArgumentsCheck.
   ASSERT(flag_mask != nullptr);
@@ -7449,13 +7451,43 @@
          index / compiler::target::kNumParameterFlagsPerElement;
 }
 
+bool Function::HasRequiredNamedParameters() const {
+  const FunctionType& sig = FunctionType::Handle(signature());
+#if defined(DART_PRECOMPILED_RUNTIME)
+  if (sig.IsNull()) {
+    // Signature is not dropped in aot when any named parameter is required.
+    return false;
+  }
+#else
+  ASSERT(!sig.IsNull());
+#endif
+  const Array& parameter_names = Array::Handle(sig.parameter_names());
+  return parameter_names.Length() > NumParameters();
+}
+
 bool Function::IsRequiredAt(intptr_t index) const {
   if (index < num_fixed_parameters() + NumOptionalPositionalParameters()) {
     return false;
   }
+  const FunctionType& sig = FunctionType::Handle(signature());
+#if defined(DART_PRECOMPILED_RUNTIME)
+  if (sig.IsNull()) {
+    // Signature is not dropped in aot when any named parameter is required.
+    return false;
+  }
+#else
+  ASSERT(!sig.IsNull());
+#endif
+  return sig.IsRequiredAt(index);
+}
+
+bool FunctionType::IsRequiredAt(intptr_t index) const {
+  if (index < num_fixed_parameters() + NumOptionalPositionalParameters()) {
+    return false;
+  }
   intptr_t flag_mask;
   const intptr_t flag_index = GetRequiredFlagIndex(index, &flag_mask);
-  const Array& parameter_names = Array::Handle(raw_ptr()->parameter_names());
+  const Array& parameter_names = Array::Handle(untag()->parameter_names());
   if (flag_index >= parameter_names.Length()) {
     return false;
   }
@@ -7464,19 +7496,20 @@
   return (flags & flag_mask) != 0;
 }
 
-void Function::SetIsRequiredAt(intptr_t index) const {
+void FunctionType::SetIsRequiredAt(intptr_t index) const {
   intptr_t flag_mask;
   const intptr_t flag_index = GetRequiredFlagIndex(index, &flag_mask);
-  const Array& parameter_names = Array::Handle(raw_ptr()->parameter_names());
+  const Array& parameter_names = Array::Handle(untag()->parameter_names());
   ASSERT(flag_index < parameter_names.Length());
   const intptr_t flags =
       Smi::Value(Smi::RawCast(parameter_names.At(flag_index)));
   parameter_names.SetAt(flag_index, Smi::Handle(Smi::New(flags | flag_mask)));
 }
 
-void Function::TruncateUnusedParameterFlags() const {
-  const Array& parameter_names = Array::Handle(raw_ptr()->parameter_names());
+void FunctionType::TruncateUnusedParameterFlags() const {
   const intptr_t num_params = NumParameters();
+  if (num_params == 0) return;
+  const Array& parameter_names = Array::Handle(untag()->parameter_names());
   if (parameter_names.Length() == num_params) {
     // No flag slots to truncate.
     return;
@@ -7491,47 +7524,86 @@
   parameter_names.Truncate(last_used + 1);
 }
 
-void Function::set_type_parameters(const TypeArguments& value) const {
-  raw_ptr()->set_type_parameters(value.raw());
+void FunctionType::FinalizeNameArrays(const Function& function) const {
+  TruncateUnusedParameterFlags();
+  if (!function.IsNull()) {
+    function.SetParameterNamesFrom(*this);
+    // Unless the function is a dispatcher, its number of type parameters
+    // must match the number of type parameters in its signature.
+    ASSERT(function.kind() == UntaggedFunction::kNoSuchMethodDispatcher ||
+           function.kind() == UntaggedFunction::kInvokeFieldDispatcher ||
+           function.kind() == UntaggedFunction::kDynamicInvocationForwarder ||
+           function.NumTypeParameters() == NumTypeParameters());
+  }
 }
 
-intptr_t Function::NumTypeParameters(Thread* thread) const {
+void FunctionType::set_type_parameters(const TypeArguments& value) const {
+  untag()->set_type_parameters(value.ptr());
+}
+
+static void ReportTooManyTypeParameters(const Function& function) {
+  Report::MessageF(Report::kError, Script::Handle(), TokenPosition::kNoSource,
+                   Report::AtLocation,
+                   "too many type parameters declared in function '%s'",
+                   function.UserVisibleNameCString());
+  UNREACHABLE();
+}
+
+static void ReportTooManyTypeParameters(const FunctionType& sig) {
+  Report::MessageF(Report::kError, Script::Handle(), TokenPosition::kNoSource,
+                   Report::AtLocation,
+                   "too many type parameters declared in signature '%s' or in "
+                   "its enclosing signatures",
+                   sig.ToUserVisibleCString());
+  UNREACHABLE();
+}
+
+void FunctionType::SetNumParentTypeArguments(intptr_t value) const {
+  ASSERT(value >= 0);
+  if (!Utils::IsUint(UntaggedFunctionType::kMaxParentTypeArgumentsBits,
+                     value)) {
+    ReportTooManyTypeParameters(*this);
+  }
+  const uint32_t* original = &untag()->packed_fields_;
+  StoreNonPointer(original,
+                  UntaggedFunctionType::PackedNumParentTypeArguments::update(
+                      value, *original));
+}
+
+void Function::SetNumTypeParameters(intptr_t value) const {
+  ASSERT(value >= 0);
+  if (!Utils::IsUint(UntaggedFunction::kMaxTypeParametersBits, value)) {
+    ReportTooManyTypeParameters(*this);
+  }
+  const uint32_t* original = &untag()->packed_fields_;
+  StoreNonPointer(original, UntaggedFunction::PackedNumTypeParameters::update(
+                                value, *original));
+}
+
+intptr_t FunctionType::NumTypeParameters(Thread* thread) const {
   if (type_parameters() == TypeArguments::null()) {
     return 0;
   }
   REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
   TypeArguments& type_params = thread->TypeArgumentsHandle();
   type_params = type_parameters();
-  // We require null to represent a non-generic function.
+  // We require null to represent a non-generic signature.
   ASSERT(type_params.Length() != 0);
   return type_params.Length();
 }
 
-intptr_t Function::NumParentTypeParameters() const {
+intptr_t Function::NumParentTypeArguments() const {
   if (IsImplicitClosureFunction()) {
     return 0;
   }
-  Thread* thread = Thread::Current();
   Function& parent = Function::Handle(parent_function());
-  intptr_t num_parent_type_params = 0;
+  intptr_t num_parent_type_args = 0;
   while (!parent.IsNull()) {
-    num_parent_type_params += parent.NumTypeParameters(thread);
+    num_parent_type_args += parent.NumTypeParameters();
     if (parent.IsImplicitClosureFunction()) break;
     parent = parent.parent_function();
   }
-  return num_parent_type_params;
-}
-
-void Function::PrintSignatureTypes() const {
-  Function& sig_fun = Function::Handle(raw());
-  Type& sig_type = Type::Handle();
-  while (!sig_fun.IsNull()) {
-    sig_type = sig_fun.SignatureType();
-    THR_Print("%s%s\n",
-              sig_fun.IsImplicitClosureFunction() ? "implicit closure: " : "",
-              sig_type.ToCString());
-    sig_fun = sig_fun.parent_function();
-  }
+  return num_parent_type_args;
 }
 
 TypeParameterPtr Function::LookupTypeParameter(const String& type_name,
@@ -7547,16 +7619,18 @@
   String& type_param_name = thread->StringHandle();
   Function& function = thread->FunctionHandle();
 
-  function = this->raw();
+  function = this->ptr();
   while (!function.IsNull()) {
-    type_params = function.type_parameters();
-    if (!type_params.IsNull()) {
-      const intptr_t num_type_params = type_params.Length();
-      for (intptr_t i = 0; i < num_type_params; i++) {
-        type_param ^= type_params.TypeAt(i);
-        type_param_name = type_param.name();
-        if (type_param_name.Equals(type_name)) {
-          return type_param.raw();
+    if (function.signature() != FunctionType::null()) {
+      type_params = function.type_parameters();
+      if (!type_params.IsNull()) {
+        const intptr_t num_type_params = type_params.Length();
+        for (intptr_t i = 0; i < num_type_params; i++) {
+          type_param ^= type_params.TypeAt(i);
+          type_param_name = type_param.name();
+          if (type_param_name.Equals(type_name)) {
+            return type_param.ptr();
+          }
         }
       }
     }
@@ -7573,18 +7647,18 @@
   return TypeParameter::null();
 }
 
-void Function::set_kind(FunctionLayout::Kind value) const {
-  set_kind_tag(KindBits::update(value, raw_ptr()->kind_tag_));
+void Function::set_kind(UntaggedFunction::Kind value) const {
+  set_kind_tag(KindBits::update(value, untag()->kind_tag_));
 }
 
-void Function::set_modifier(FunctionLayout::AsyncModifier value) const {
-  set_kind_tag(ModifierBits::update(value, raw_ptr()->kind_tag_));
+void Function::set_modifier(UntaggedFunction::AsyncModifier value) const {
+  set_kind_tag(ModifierBits::update(value, untag()->kind_tag_));
 }
 
 void Function::set_recognized_kind(MethodRecognizer::Kind value) const {
   // Prevent multiple settings of kind.
   ASSERT((value == MethodRecognizer::kUnknown) || !IsRecognized());
-  set_kind_tag(RecognizedBits::update(value, raw_ptr()->kind_tag_));
+  set_kind_tag(RecognizedBits::update(value, untag()->kind_tag_));
 }
 
 void Function::set_token_pos(TokenPosition token_pos) const {
@@ -7592,35 +7666,16 @@
   UNREACHABLE();
 #else
   ASSERT(!token_pos.IsClassifying() || IsMethodExtractor());
-  StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
+  StoreNonPointer(&untag()->token_pos_, token_pos);
 #endif
 }
 
 void Function::set_kind_tag(uint32_t value) const {
-  StoreNonPointer(&raw_ptr()->kind_tag_, static_cast<uint32_t>(value));
+  StoreNonPointer(&untag()->kind_tag_, static_cast<uint32_t>(value));
 }
 
 void Function::set_packed_fields(uint32_t packed_fields) const {
-  StoreNonPointer(&raw_ptr()->packed_fields_, packed_fields);
-}
-
-void Function::set_num_fixed_parameters(intptr_t value) const {
-  ASSERT(value >= 0);
-  ASSERT(Utils::IsUint(FunctionLayout::kMaxFixedParametersBits, value));
-  const uint32_t* original = &raw_ptr()->packed_fields_;
-  StoreNonPointer(original, FunctionLayout::PackedNumFixedParameters::update(
-                                value, *original));
-}
-
-void Function::SetNumOptionalParameters(intptr_t value,
-                                        bool are_optional_positional) const {
-  ASSERT(Utils::IsUint(FunctionLayout::kMaxOptionalParametersBits, value));
-  uint32_t packed_fields = raw_ptr()->packed_fields_;
-  packed_fields = FunctionLayout::PackedHasNamedOptionalParameters::update(
-      !are_optional_positional, packed_fields);
-  packed_fields =
-      FunctionLayout::PackedNumOptionalParameters::update(value, packed_fields);
-  set_packed_fields(packed_fields);
+  StoreNonPointer(&untag()->packed_fields_, packed_fields);
 }
 
 bool Function::IsOptimizable() const {
@@ -7632,9 +7687,8 @@
     // Native methods don't need to be optimized.
     return false;
   }
-  const intptr_t function_length = end_token_pos().Pos() - token_pos().Pos();
   if (is_optimizable() && (script() != Script::null()) &&
-      (function_length < FLAG_huge_method_cutoff_in_tokens)) {
+      SourceSize() < FLAG_huge_method_cutoff_in_tokens) {
     // Additional check needed for implicit getters.
     return (unoptimized_code() == Object::null()) ||
            (Code::Handle(unoptimized_code()).Size() <
@@ -7686,24 +7740,22 @@
 }
 
 intptr_t Function::NumImplicitParameters() const {
-  const FunctionLayout::Kind k = kind();
-  if (k == FunctionLayout::kConstructor) {
+  const UntaggedFunction::Kind k = kind();
+  if (k == UntaggedFunction::kConstructor) {
     // Type arguments for factory; instance for generative constructor.
     return 1;
   }
-  if ((k == FunctionLayout::kClosureFunction) ||
-      (k == FunctionLayout::kImplicitClosureFunction) ||
-      (k == FunctionLayout::kSignatureFunction) ||
-      (k == FunctionLayout::kFfiTrampoline)) {
+  if ((k == UntaggedFunction::kClosureFunction) ||
+      (k == UntaggedFunction::kImplicitClosureFunction) ||
+      (k == UntaggedFunction::kFfiTrampoline)) {
     return 1;  // Closure object.
   }
   if (!is_static()) {
     // Closure functions defined inside instance (i.e. non-static) functions are
     // marked as non-static, but they do not have a receiver.
     // Closures are handled above.
-    ASSERT((k != FunctionLayout::kClosureFunction) &&
-           (k != FunctionLayout::kImplicitClosureFunction) &&
-           (k != FunctionLayout::kSignatureFunction));
+    ASSERT((k != UntaggedFunction::kClosureFunction) &&
+           (k != UntaggedFunction::kImplicitClosureFunction));
     return 1;  // Receiver.
   }
   return 0;  // No implicit parameters.
@@ -7804,7 +7856,7 @@
   }
   // Verify that all argument names are valid parameter names.
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   Zone* zone = thread->zone();
   String& argument_name = String::Handle(zone);
   String& parameter_name = String::Handle(zone);
@@ -7834,7 +7886,7 @@
       return false;
     }
   }
-  if (isolate->use_strict_null_safety_checks()) {
+  if (isolate_group->use_strict_null_safety_checks()) {
     // Verify that all required named parameters are filled.
     for (intptr_t j = num_parameters - NumOptionalNamedParameters();
          j < num_parameters; j++) {
@@ -7882,11 +7934,11 @@
     const ArgumentsDescriptor& args_desc) {
   ASSERT(!function.IsNull());
 
-  const intptr_t kNumCurrentTypeArgs = function.NumTypeParameters(thread);
-  const intptr_t kNumParentTypeArgs = function.NumParentTypeParameters();
+  const intptr_t kNumCurrentTypeArgs = function.NumTypeParameters();
+  const intptr_t kNumParentTypeArgs = function.NumParentTypeArguments();
   const intptr_t kNumTypeArgs = kNumCurrentTypeArgs + kNumParentTypeArgs;
   // Non-generic functions don't receive type arguments.
-  if (kNumTypeArgs == 0) return Object::empty_type_arguments().raw();
+  if (kNumTypeArgs == 0) return Object::empty_type_arguments().ptr();
   // Closure functions require that the receiver be provided (and is a closure).
   ASSERT(!function.IsClosureFunction() || receiver.IsClosure());
 
@@ -7900,7 +7952,7 @@
   // We don't try to instantiate the parent type parameters to their bounds
   // if not provided or check any closed-over type arguments against the parent
   // type parameter bounds (since they have been type checked already).
-  if (kNumCurrentTypeArgs == 0) return parent_type_args.raw();
+  if (kNumCurrentTypeArgs == 0) return parent_type_args.ptr();
 
   auto& function_type_args = TypeArguments::Handle(zone);
   // First check for delayed type arguments before using either provided or
@@ -7910,7 +7962,7 @@
     const auto& closure = Closure::Cast(receiver);
     function_type_args = closure.delayed_type_arguments();
     has_delayed_type_args =
-        function_type_args.raw() != Object::empty_type_arguments().raw();
+        function_type_args.ptr() != Object::empty_type_arguments().ptr();
   }
 
   if (args_desc.TypeArgsLen() > 0) {
@@ -7938,10 +7990,10 @@
             instantiator_type_args, parent_type_args);
         break;
       case Function::DefaultTypeArgumentsKind::kSharesInstantiatorTypeArguments:
-        function_type_args = instantiator_type_args.raw();
+        function_type_args = instantiator_type_args.ptr();
         break;
       case Function::DefaultTypeArgumentsKind::kSharesFunctionTypeArguments:
-        function_type_args = parent_type_args.raw();
+        function_type_args = parent_type_args.ptr();
         break;
     }
   }
@@ -7966,12 +8018,18 @@
       return receiver.GetTypeArguments();
     }
   }
-  return Object::empty_type_arguments().raw();
+  return Object::empty_type_arguments().ptr();
 }
 
 ObjectPtr Function::DoArgumentTypesMatch(
     const Array& args,
     const ArgumentsDescriptor& args_desc) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  if (signature() == FunctionType::null()) {
+    // Precompiler deleted signature because of missing entry point pragma.
+    return EntryPointMemberInvocationError(*this);
+  }
+#endif
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
 
@@ -7989,6 +8047,12 @@
     const Array& args,
     const ArgumentsDescriptor& args_desc,
     const TypeArguments& instantiator_type_arguments) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  if (signature() == FunctionType::null()) {
+    // Precompiler deleted signature because of missing entry point pragma.
+    return EntryPointMemberInvocationError(*this);
+  }
+#endif
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
 
@@ -8011,22 +8075,29 @@
     const ArgumentsDescriptor& args_desc,
     const TypeArguments& instantiator_type_arguments,
     const TypeArguments& function_type_arguments) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  if (signature() == FunctionType::null()) {
+    // Precompiler deleted signature because of missing entry point pragma.
+    return EntryPointMemberInvocationError(*this);
+  }
+#endif
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
 
   // Perform any non-covariant bounds checks on the provided function type
   // arguments to make sure they are appropriate subtypes of the bounds.
-  const intptr_t kNumLocalTypeArgs = NumTypeParameters(thread);
+  const intptr_t kNumLocalTypeArgs = NumTypeParameters();
   if (kNumLocalTypeArgs > 0) {
-    ASSERT(function_type_arguments.HasCount(kNumLocalTypeArgs +
-                                            NumParentTypeParameters()));
+    const intptr_t kNumParentTypeArgs = NumParentTypeArguments();
+    ASSERT(function_type_arguments.HasCount(kNumParentTypeArgs +
+                                            kNumLocalTypeArgs));
     const auto& params = TypeArguments::Handle(zone, type_parameters());
     auto& parameter = TypeParameter::Handle(zone);
     auto& type = AbstractType::Handle(zone);
     auto& bound = AbstractType::Handle(zone);
     for (intptr_t i = 0; i < kNumLocalTypeArgs; i++) {
       parameter ^= params.TypeAt(i);
-      type = parameter.raw();
+      type = parameter.ptr();
       bound = parameter.bound();
       // Only perform non-covariant checks where the bound is not the top type.
       if (parameter.IsGenericCovariantImpl() || bound.IsTopTypeForSubtyping()) {
@@ -8040,7 +8111,7 @@
       }
     }
   } else {
-    ASSERT(function_type_arguments.HasCount(NumParentTypeParameters()));
+    ASSERT(function_type_arguments.HasCount(NumParentTypeArguments()));
   }
 
   AbstractType& type = AbstractType::Handle(zone);
@@ -8213,46 +8284,39 @@
   return chars;
 }
 
-FunctionPtr Function::InstantiateSignatureFrom(
+AbstractTypePtr FunctionType::InstantiateFrom(
     const TypeArguments& instantiator_type_arguments,
     const TypeArguments& function_type_arguments,
     intptr_t num_free_fun_type_params,
-    Heap::Space space) const {
+    Heap::Space space,
+    TrailPtr trail) const {
+  ASSERT(IsFinalized() || IsBeingFinalized());
+  // A FunctionType cannot be part of a cycle (self-referencing typedefs are not
+  // allowed), therefore, the passed in trail does not need to be propagated to
+  // calls instantiating types of the signature.
   Zone* zone = Thread::Current()->zone();
-  const Object& owner = Object::Handle(zone, RawOwner());
-  // Note that parent pointers in newly instantiated signatures still points to
-  // the original uninstantiated parent signatures. That is not a problem.
-  const Function& parent = Function::Handle(zone, parent_function());
-  const intptr_t num_parent_type_params = NumParentTypeParameters();
-
   // See the comment on kCurrentAndEnclosingFree to understand why we don't
   // adjust 'num_free_fun_type_params' downward in this case.
+  const intptr_t num_parent_type_args = NumParentTypeArguments();
   bool delete_type_parameters = false;
   if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
     num_free_fun_type_params = kAllFree;
     delete_type_parameters = true;
   } else {
-    ASSERT(!HasInstantiatedSignature(kAny, num_free_fun_type_params));
-
-    // A generic typedef may declare a non-generic function type and get
-    // instantiated with unrelated function type parameters. In that case, its
-    // signature is still uninstantiated, because these type parameters are
-    // free (they are not declared by the typedef).
-    // For that reason, we only adjust num_free_fun_type_params if this
-    // signature is generic or has a generic parent.
+    ASSERT(!IsInstantiated(kAny, num_free_fun_type_params));
     if (IsGeneric() || HasGenericParent()) {
       // We only consider the function type parameters declared by the parents
       // of this signature function as free.
-      if (num_parent_type_params < num_free_fun_type_params) {
-        num_free_fun_type_params = num_parent_type_params;
+      if (num_parent_type_args < num_free_fun_type_params) {
+        num_free_fun_type_params = num_parent_type_args;
       }
     }
   }
 
-  Function& sig = Function::Handle(Function::NewSignatureFunction(
-      owner, parent, TokenPosition::kNoSource, space));
-  const intptr_t offset =
-      sig.NumParentTypeParameters() - num_parent_type_params;
+  // TODO(regis): Is this correct to use num_parent_type_args here?
+  // Or should it be 0 after instantiation?
+  FunctionType& sig = FunctionType::Handle(
+      FunctionType::New(num_parent_type_args, nullability(), space));
   AbstractType& type = AbstractType::Handle(zone);
 
   // Copy the type parameters and instantiate their bounds (if necessary).
@@ -8262,11 +8326,10 @@
     if (!type_params.IsNull()) {
       TypeArguments& instantiated_type_params = TypeArguments::Handle(zone);
       TypeParameter& type_param = TypeParameter::Handle(zone);
-      const Class& null_class = Class::Handle(zone);
       String& param_name = String::Handle(zone);
       for (intptr_t i = 0; i < type_params.Length(); ++i) {
         type_param ^= type_params.TypeAt(i);
-        ASSERT(type_param.index() == num_parent_type_params + i);
+        ASSERT(type_param.index() == num_parent_type_args + i);
         type = type_param.bound();
         if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
           type = type.InstantiateFrom(instantiator_type_arguments,
@@ -8275,21 +8338,15 @@
           // A returned null type indicates a failed instantiation in dead code
           // that must be propagated up to the caller, the optimizing compiler.
           if (type.IsNull()) {
-            return Function::null();
+            return FunctionType::null();
           }
-        }
-        if (offset > 0 || type.raw() != type_param.bound()) {
-          param_name = type_param.name();
-          ASSERT(type_param.IsFunctionTypeParameter());
           ASSERT(type_param.IsFinalized());
-          ASSERT(type_param.IsCanonical());
+          param_name = type_param.name();
           type_param = TypeParameter::New(
-              null_class, sig, type_param.index() + offset, param_name, type,
-              type_param.IsGenericCovariantImpl(), type_param.nullability(),
-              type_param.token_pos());
+              Object::null_class(), type_param.base(), type_param.index(),
+              param_name, type, type_param.IsGenericCovariantImpl(),
+              type_param.nullability());
           type_param.SetIsFinalized();
-          type_param.SetCanonical();
-          type_param.SetDeclaration(true);
           if (instantiated_type_params.IsNull()) {
             instantiated_type_params = TypeArguments::New(type_params.Length());
             for (intptr_t j = 0; j < i; ++j) {
@@ -8316,11 +8373,12 @@
     // A returned null type indicates a failed instantiation in dead code that
     // must be propagated up to the caller, the optimizing compiler.
     if (type.IsNull()) {
-      return Function::null();
+      return FunctionType::null();
     }
   }
   sig.set_result_type(type);
   const intptr_t num_params = NumParameters();
+  sig.set_num_implicit_parameters(num_implicit_parameters());
   sig.set_num_fixed_parameters(num_fixed_parameters());
   sig.SetNumOptionalParameters(NumOptionalParameters(),
                                HasOptionalPositionalParameters());
@@ -8334,7 +8392,7 @@
       // A returned null type indicates a failed instantiation in dead code that
       // must be propagated up to the caller, the optimizing compiler.
       if (type.IsNull()) {
-        return Function::null();
+        return FunctionType::null();
       }
     }
     sig.SetParameterTypeAt(i, type);
@@ -8342,19 +8400,29 @@
   sig.set_parameter_names(Array::Handle(zone, parameter_names()));
 
   if (delete_type_parameters) {
-    ASSERT(sig.HasInstantiatedSignature(kFunctions));
+    ASSERT(sig.IsInstantiated(kFunctions));
   }
-  return sig.raw();
+
+  if (IsFinalized()) {
+    sig.SetIsFinalized();
+  } else {
+    if (IsBeingFinalized()) {
+      sig.SetIsBeingFinalized();
+    }
+  }
+
+  // Canonicalization is not part of instantiation.
+  return sig.ptr();
 }
 
-// Checks if the type of the specified parameter of this function is a supertype
-// of the type of the specified parameter of the other function (i.e. check
-// parameter contravariance).
+// Checks if the type of the specified parameter of this signature is a
+// supertype of the type of the specified parameter of the other signature
+// (i.e. check parameter contravariance).
 // Note that types marked as covariant are already dealt with in the front-end.
-bool Function::IsContravariantParameter(intptr_t parameter_position,
-                                        const Function& other,
-                                        intptr_t other_parameter_position,
-                                        Heap::Space space) const {
+bool FunctionType::IsContravariantParameter(intptr_t parameter_position,
+                                            const FunctionType& other,
+                                            intptr_t other_parameter_position,
+                                            Heap::Space space) const {
   const AbstractType& param_type =
       AbstractType::Handle(ParameterTypeAt(parameter_position));
   if (param_type.IsTopTypeForSubtyping()) {
@@ -8365,8 +8433,8 @@
   return other_param_type.IsSubtypeOf(param_type, space);
 }
 
-bool Function::HasSameTypeParametersAndBounds(const Function& other,
-                                              TypeEquality kind) const {
+bool FunctionType::HasSameTypeParametersAndBounds(const FunctionType& other,
+                                                  TypeEquality kind) const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
 
@@ -8383,32 +8451,19 @@
     ASSERT(!other_type_params.IsNull());
     TypeParameter& type_param = TypeParameter::Handle(zone);
     TypeParameter& other_type_param = TypeParameter::Handle(zone);
-    AbstractType& bound = AbstractType::Handle(zone);
-    AbstractType& other_bound = AbstractType::Handle(zone);
     for (intptr_t i = 0; i < num_type_params; i++) {
       type_param ^= type_params.TypeAt(i);
       other_type_param ^= other_type_params.TypeAt(i);
-      bound = type_param.bound();
-      ASSERT(bound.IsFinalized());
-      other_bound = other_type_param.bound();
-      ASSERT(other_bound.IsFinalized());
-      if (kind == TypeEquality::kInSubtypeTest) {
-        // Bounds that are mutual subtypes are considered equal.
-        if (!bound.IsSubtypeOf(other_bound, Heap::kOld) ||
-            !other_bound.IsSubtypeOf(bound, Heap::kOld)) {
-          return false;
-        }
-      } else {
-        if (!bound.IsEquivalent(other_bound, kind)) {
-          return false;
-        }
+      if (!type_param.IsEquivalent(other_type_param, kind)) {
+        return false;
       }
     }
   }
   return true;
 }
 
-bool Function::IsSubtypeOf(const Function& other, Heap::Space space) const {
+bool FunctionType::IsSubtypeOf(const FunctionType& other,
+                               Heap::Space space) const {
   const intptr_t num_fixed_params = num_fixed_parameters();
   const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
   const intptr_t num_opt_named_params = NumOptionalNamedParameters();
@@ -8417,10 +8472,10 @@
       other.NumOptionalPositionalParameters();
   const intptr_t other_num_opt_named_params =
       other.NumOptionalNamedParameters();
-  // This function requires the same arguments or less and accepts the same
+  // This signature requires the same arguments or less and accepts the same
   // arguments or more. We can ignore implicit parameters.
-  const intptr_t num_ignored_params = NumImplicitParameters();
-  const intptr_t other_num_ignored_params = other.NumImplicitParameters();
+  const intptr_t num_ignored_params = num_implicit_parameters();
+  const intptr_t other_num_ignored_params = other.num_implicit_parameters();
   if (((num_fixed_params - num_ignored_params) >
        (other_num_fixed_params - other_num_ignored_params)) ||
       ((num_fixed_params - num_ignored_params + num_opt_pos_params) <
@@ -8435,7 +8490,7 @@
   }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   // Check the result type.
   const AbstractType& other_res_type =
       AbstractType::Handle(zone, other.result_type());
@@ -8471,7 +8526,7 @@
     found_param_name = false;
     for (intptr_t j = num_fixed_params; j < num_params; j++) {
       ASSERT(String::Handle(zone, ParameterNameAt(j)).IsSymbol());
-      if (ParameterNameAt(j) == other_param_name.raw()) {
+      if (ParameterNameAt(j) == other_param_name.ptr()) {
         found_param_name = true;
         if (!IsContravariantParameter(j, other, i, space)) {
           return false;
@@ -8483,7 +8538,7 @@
       return false;
     }
   }
-  if (isolate->use_strict_null_safety_checks()) {
+  if (isolate_group->use_strict_null_safety_checks()) {
     // Check that for each required named parameter in this function, there's a
     // corresponding required named parameter in the other function.
     String& param_name = other_param_name;
@@ -8494,7 +8549,7 @@
         bool found = false;
         for (intptr_t i = other_num_fixed_params; i < other_num_params; i++) {
           ASSERT(String::Handle(zone, other.ParameterNameAt(i)).IsSymbol());
-          if (other.ParameterNameAt(i) == param_name.raw()) {
+          if (other.ParameterNameAt(i) == param_name.ptr()) {
             found = true;
             if (!other.IsRequiredAt(i)) {
               return false;
@@ -8519,9 +8574,9 @@
 
 bool Function::IsImplicitStaticClosureFunction(FunctionPtr func) {
   NoSafepointScope no_safepoint;
-  uint32_t kind_tag = func->ptr()->kind_tag_;
+  uint32_t kind_tag = func->untag()->kind_tag_;
   return (KindBits::decode(kind_tag) ==
-          FunctionLayout::kImplicitClosureFunction) &&
+          UntaggedFunction::kImplicitClosureFunction) &&
          StaticBit::decode(kind_tag);
 }
 
@@ -8532,8 +8587,9 @@
   return static_cast<FunctionPtr>(raw);
 }
 
-FunctionPtr Function::New(const String& name,
-                          FunctionLayout::Kind kind,
+FunctionPtr Function::New(const FunctionType& signature,
+                          const String& name,
+                          UntaggedFunction::Kind kind,
                           bool is_static,
                           bool is_const,
                           bool is_abstract,
@@ -8542,16 +8598,15 @@
                           const Object& owner,
                           TokenPosition token_pos,
                           Heap::Space space) {
-  ASSERT(!owner.IsNull() || (kind == FunctionLayout::kSignatureFunction));
+  ASSERT(!owner.IsNull());
   const Function& result = Function::Handle(Function::New(space));
   result.set_kind_tag(0);
-  result.set_parameter_types(Object::empty_array());
-  result.set_parameter_names(Object::empty_array());
+  result.set_packed_fields(0);
   result.set_name(name);
   result.set_kind_tag(0);  // Ensure determinism of uninitialized bits.
   result.set_kind(kind);
   result.set_recognized_kind(MethodRecognizer::kUnknown);
-  result.set_modifier(FunctionLayout::kNoModifier);
+  result.set_modifier(UntaggedFunction::kNoModifier);
   result.set_is_static(is_static);
   result.set_is_const(is_const);
   result.set_is_abstract(is_abstract);
@@ -8569,8 +8624,6 @@
   result.set_owner(owner);
   NOT_IN_PRECOMPILED(result.set_token_pos(token_pos));
   NOT_IN_PRECOMPILED(result.set_end_token_pos(token_pos));
-  result.set_num_fixed_parameters(0);
-  result.SetNumOptionalParameters(0, false);
   NOT_IN_PRECOMPILED(result.set_usage_counter(0));
   NOT_IN_PRECOMPILED(result.set_deoptimization_counter(0));
   NOT_IN_PRECOMPILED(result.set_optimized_instruction_count(0));
@@ -8582,16 +8635,12 @@
   result.set_is_inlinable(true);
   result.reset_unboxed_parameters_and_return();
   result.SetInstructionsSafe(StubCode::LazyCompile());
-  if (kind == FunctionLayout::kClosureFunction ||
-      kind == FunctionLayout::kImplicitClosureFunction) {
+  if (kind == UntaggedFunction::kClosureFunction ||
+      kind == UntaggedFunction::kImplicitClosureFunction) {
     ASSERT(space == Heap::kOld);
     const ClosureData& data = ClosureData::Handle(ClosureData::New());
     result.set_data(data);
-  } else if (kind == FunctionLayout::kSignatureFunction) {
-    const SignatureData& data =
-        SignatureData::Handle(SignatureData::New(space));
-    result.set_data(data);
-  } else if (kind == FunctionLayout::kFfiTrampoline) {
+  } else if (kind == UntaggedFunction::kFfiTrampoline) {
     const FfiTrampolineData& data =
         FfiTrampolineData::Handle(FfiTrampolineData::New());
     result.set_data(data);
@@ -8611,28 +8660,36 @@
   if (result.ForceOptimize()) {
     result.set_is_debuggable(false);
   }
-
-  return result.raw();
+  if (!signature.IsNull()) {
+    signature.set_num_implicit_parameters(result.NumImplicitParameters());
+    result.set_signature(signature);
+  } else {
+    ASSERT(kind == UntaggedFunction::kFfiTrampoline);
+  }
+  return result.ptr();
 }
 
-FunctionPtr Function::NewClosureFunctionWithKind(FunctionLayout::Kind kind,
+FunctionPtr Function::NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
                                                  const String& name,
                                                  const Function& parent,
                                                  TokenPosition token_pos,
                                                  const Object& owner) {
-  ASSERT((kind == FunctionLayout::kClosureFunction) ||
-         (kind == FunctionLayout::kImplicitClosureFunction));
+  ASSERT((kind == UntaggedFunction::kClosureFunction) ||
+         (kind == UntaggedFunction::kImplicitClosureFunction));
   ASSERT(!parent.IsNull());
   ASSERT(!owner.IsNull());
+  const FunctionType& signature = FunctionType::Handle(FunctionType::New(
+      kind == UntaggedFunction::kClosureFunction ? parent.NumTypeArguments()
+                                                 : 0));
   const Function& result = Function::Handle(
-      Function::New(name, kind,
+      Function::New(signature, name, kind,
                     /* is_static = */ parent.is_static(),
                     /* is_const = */ false,
                     /* is_abstract = */ false,
                     /* is_external = */ false,
                     /* is_native = */ false, owner, token_pos));
   result.set_parent_function(parent);
-  return result.raw();
+  return result.ptr();
 }
 
 FunctionPtr Function::NewClosureFunction(const String& name,
@@ -8640,7 +8697,7 @@
                                          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(FunctionLayout::kClosureFunction, name,
+  return NewClosureFunctionWithKind(UntaggedFunction::kClosureFunction, name,
                                     parent, token_pos, parent_owner);
 }
 
@@ -8649,50 +8706,10 @@
                                                  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(FunctionLayout::kImplicitClosureFunction,
+  return NewClosureFunctionWithKind(UntaggedFunction::kImplicitClosureFunction,
                                     name, parent, token_pos, parent_owner);
 }
 
-FunctionPtr Function::NewSignatureFunction(const Object& owner,
-                                           const Function& parent,
-                                           TokenPosition token_pos,
-                                           Heap::Space space) {
-  const Function& result = Function::Handle(Function::New(
-      Symbols::AnonymousSignature(), FunctionLayout::kSignatureFunction,
-      /* is_static = */ false,
-      /* is_const = */ false,
-      /* is_abstract = */ false,
-      /* is_external = */ false,
-      /* is_native = */ false,
-      owner,  // Same as function type scope class.
-      token_pos, space));
-  result.set_parent_function(parent);
-  result.set_is_reflectable(false);
-  result.set_is_visible(false);
-  result.set_is_debuggable(false);
-  return result.raw();
-}
-
-FunctionPtr Function::NewEvalFunction(const Class& owner,
-                                      const Script& script,
-                                      bool is_static) {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  const Function& result = Function::Handle(
-      zone,
-      Function::New(String::Handle(Symbols::New(thread, ":Eval")),
-                    FunctionLayout::kRegularFunction, is_static,
-                    /* is_const = */ false,
-                    /* is_abstract = */ false,
-                    /* is_external = */ false,
-                    /* is_native = */ false, owner, TokenPosition::kMinSource));
-  ASSERT(!script.IsNull());
-  result.set_is_debuggable(false);
-  result.set_is_visible(true);
-  result.set_eval_script(script);
-  return result.raw();
-}
-
 bool Function::SafeToClosurize() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
   return HasImplicitClosureFunction();
@@ -8703,7 +8720,7 @@
 
 bool Function::IsDynamicClosureCallDispatcher(Thread* thread) const {
   if (!IsInvokeFieldDispatcher()) return false;
-  if (thread->isolate()->object_store()->closure_class() != Owner()) {
+  if (thread->isolate_group()->object_store()->closure_class() != Owner()) {
     return false;
   }
   const auto& handle = String::Handle(thread->zone(), name());
@@ -8721,8 +8738,7 @@
   FATAL("Cannot create implicit closure in AOT!");
   return Function::null();
 #else
-  ASSERT(!IsSignatureFunction() && !IsClosureFunction());
-
+  ASSERT(!IsClosureFunction());
   Thread* thread = Thread::Current();
   SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
 
@@ -8745,16 +8761,20 @@
     closure_function.set_context_scope(context_scope);
   }
 
+  FunctionType& closure_signature =
+      FunctionType::Handle(zone, closure_function.signature());
+
   // Set closure function's type parameters.
-  auto& type_args_handle = TypeArguments::Handle(zone, 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_function.set_type_parameters(type_args_handle);
+  closure_signature.set_type_parameters(
+      TypeArguments::Handle(zone, type_parameters()));
+  closure_function.SetNumTypeParameters(NumTypeParameters());
   closure_function.UpdateCachedDefaultTypeArguments(thread);
 
   // Set closure function's result type to this result type.
-  closure_function.set_result_type(AbstractType::Handle(zone, 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());
@@ -8775,25 +8795,25 @@
   const int num_params = num_fixed_params + num_opt_params;
   closure_function.set_num_fixed_parameters(num_fixed_params);
   closure_function.SetNumOptionalParameters(num_opt_params, has_opt_pos_params);
-  closure_function.set_parameter_types(
+  closure_signature.set_parameter_types(
       Array::Handle(zone, Array::New(num_params, Heap::kOld)));
-  closure_function.CreateNameArrayIncludingFlags(Heap::kOld);
+  closure_signature.CreateNameArrayIncludingFlags(Heap::kOld);
   AbstractType& param_type = AbstractType::Handle(zone);
   String& param_name = String::Handle(zone);
   // Add implicit closure object parameter.
   param_type = Type::DynamicType();
-  closure_function.SetParameterTypeAt(0, param_type);
-  closure_function.SetParameterNameAt(0, Symbols::ClosureParameter());
+  closure_signature.SetParameterTypeAt(0, param_type);
+  closure_signature.SetParameterNameAt(0, Symbols::ClosureParameter());
   for (int i = kClosure; i < num_params; i++) {
     param_type = ParameterTypeAt(has_receiver - kClosure + i);
-    closure_function.SetParameterTypeAt(i, param_type);
+    closure_signature.SetParameterTypeAt(i, param_type);
     param_name = ParameterNameAt(has_receiver - kClosure + i);
-    closure_function.SetParameterNameAt(i, param_name);
+    closure_signature.SetParameterNameAt(i, param_name);
     if (IsRequiredAt(has_receiver - kClosure + i)) {
-      closure_function.SetIsRequiredAt(i);
+      closure_signature.SetIsRequiredAt(i);
     }
   }
-  closure_function.TruncateUnusedParameterFlags();
+  closure_signature.FinalizeNameArrays(closure_function);
   closure_function.InheritKernelOffsetFrom(*this);
 
   // Change covariant parameter types to either Object? for an opted-in implicit
@@ -8805,26 +8825,25 @@
                                     &is_generic_covariant_impl);
 
     Type& object_type = Type::Handle(zone, Type::ObjectType());
-    ObjectStore* object_store = Isolate::Current()->object_store();
+    ObjectStore* object_store = IsolateGroup::Current()->object_store();
     object_type = nnbd_mode() == NNBDMode::kOptedInLib
                       ? object_store->nullable_object_type()
                       : 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;
       if (is_covariant.Contains(original_param_index) ||
           is_generic_covariant_impl.Contains(original_param_index)) {
-        closure_function.SetParameterTypeAt(i, object_type);
+        closure_signature.SetParameterTypeAt(i, object_type);
       }
     }
   }
-  const Type& signature_type =
-      Type::Handle(zone, closure_function.SignatureType());
-  if (!signature_type.IsFinalized()) {
-    ClassFinalizer::FinalizeType(signature_type);
-  }
+  ASSERT(!closure_signature.IsFinalized());
+  closure_signature ^= ClassFinalizer::FinalizeType(closure_signature);
+  closure_function.set_signature(closure_signature);
   set_implicit_closure_function(closure_function);
   ASSERT(closure_function.IsImplicitClosureFunction());
-  return closure_function.raw();
+  return closure_function.ptr();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -8837,24 +8856,26 @@
   }
 }
 
-StringPtr Function::Signature() const {
+StringPtr Function::InternalSignature() const {
   Thread* thread = Thread::Current();
   ZoneTextBuffer printer(thread->zone());
-  PrintSignature(kInternalName, &printer);
+  const FunctionType& sig = FunctionType::Handle(signature());
+  sig.Print(kInternalName, &printer);
   return Symbols::New(thread, printer.buffer());
 }
 
 StringPtr Function::UserVisibleSignature() const {
   Thread* thread = Thread::Current();
   ZoneTextBuffer printer(thread->zone());
-  PrintSignature(kUserVisibleName, &printer);
+  const FunctionType& sig = FunctionType::Handle(signature());
+  sig.Print(kUserVisibleName, &printer);
   return Symbols::New(thread, printer.buffer());
 }
 
-void Function::PrintSignatureParameters(Thread* thread,
-                                        Zone* zone,
-                                        NameVisibility name_visibility,
-                                        BaseTextBuffer* printer) const {
+void FunctionType::PrintParameters(Thread* thread,
+                                   Zone* zone,
+                                   NameVisibility name_visibility,
+                                   BaseTextBuffer* printer) const {
   AbstractType& param_type = AbstractType::Handle(zone);
   const intptr_t num_params = NumParameters();
   const intptr_t num_fixed_params = num_fixed_parameters();
@@ -8865,7 +8886,7 @@
   intptr_t i = 0;
   if (name_visibility == kUserVisibleName) {
     // Hide implicit parameters.
-    i = NumImplicitParameters();
+    i = num_implicit_parameters();
   }
   String& name = String::Handle(zone);
   while (i < num_fixed_params) {
@@ -8956,7 +8977,7 @@
   auto& target =
       Function::Handle(zone, Resolver::ResolveFunction(zone, owner, func_name));
 
-  if (!target.IsNull() && (target.raw() != parent.raw())) {
+  if (!target.IsNull() && (target.ptr() != parent.ptr())) {
     DEBUG_ASSERT(Isolate::Current()->HasAttemptedReload());
     if ((target.is_static() != parent.is_static()) ||
         (target.kind() != parent.kind())) {
@@ -8964,30 +8985,34 @@
     }
   }
 
-  return target.raw();
+  return target.ptr();
 }
 
 intptr_t Function::ComputeClosureHash() const {
   ASSERT(IsClosureFunction());
   const Class& cls = Class::Handle(Owner());
   uintptr_t result = String::Handle(name()).Hash();
-  result += String::Handle(Signature()).Hash();
+  result += String::Handle(InternalSignature()).Hash();
   result += String::Handle(cls.Name()).Hash();
   return result;
 }
 
-void Function::PrintSignature(NameVisibility name_visibility,
-                              BaseTextBuffer* printer) const {
+void FunctionType::Print(NameVisibility name_visibility,
+                         BaseTextBuffer* printer) const {
+  if (IsNull()) {
+    printer->AddString("null");  // Signature optimized out in precompiler.
+    return;
+  }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  String& name = String::Handle(zone);
+  auto isolate_group = thread->isolate_group();
   const TypeArguments& type_params =
       TypeArguments::Handle(zone, type_parameters());
   if (!type_params.IsNull()) {
     const intptr_t num_type_params = type_params.Length();
     ASSERT(num_type_params > 0);
     TypeParameter& type_param = TypeParameter::Handle(zone);
+    String& name = String::Handle(zone);
     AbstractType& bound = AbstractType::Handle(zone);
     printer->AddString("<");
     for (intptr_t i = 0; i < num_type_params; i++) {
@@ -8998,9 +9023,16 @@
       // Do not print default bound or non-nullable Object bound in weak mode.
       if (!bound.IsNull() &&
           (!bound.IsObjectType() ||
-           (isolate->null_safety() && bound.IsNonNullable()))) {
+           (isolate_group->null_safety() && bound.IsNonNullable()))) {
         printer->AddString(" extends ");
         bound.PrintName(name_visibility, printer);
+        if (FLAG_show_internal_names) {
+          bound = type_param.default_argument();
+          if (!bound.IsNull() && !bound.IsDynamicType()) {
+            printer->AddString(" defaults to ");
+            bound.PrintName(name_visibility, printer);
+          }
+        }
       }
       if (i < num_type_params - 1) {
         printer->AddString(", ");
@@ -9009,7 +9041,7 @@
     printer->AddString(">");
   }
   printer->AddString("(");
-  PrintSignatureParameters(thread, zone, name_visibility, printer);
+  PrintParameters(thread, zone, name_visibility, printer);
   printer->AddString(") => ");
   const AbstractType& res_type = AbstractType::Handle(zone, result_type());
   res_type.PrintName(name_visibility, printer);
@@ -9018,21 +9050,22 @@
 bool Function::HasInstantiatedSignature(Genericity genericity,
                                         intptr_t num_free_fun_type_params,
                                         TrailPtr trail) const {
+  return FunctionType::Handle(signature())
+      .IsInstantiated(genericity, num_free_fun_type_params, trail);
+}
+
+bool FunctionType::IsInstantiated(Genericity genericity,
+                                  intptr_t num_free_fun_type_params,
+                                  TrailPtr trail) const {
   if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
     num_free_fun_type_params = kAllFree;
   } else if (genericity != kCurrentClass) {
-    // A generic typedef may declare a non-generic function type and get
-    // instantiated with unrelated function type parameters. In that case, its
-    // signature is still uninstantiated, because these type parameters are
-    // free (they are not declared by the typedef).
-    // For that reason, we only adjust num_free_fun_type_params if this
-    // signature is generic or has a generic parent.
     if (IsGeneric() || HasGenericParent()) {
       // We only consider the function type parameters declared by the parents
       // of this signature function as free.
-      const int num_parent_type_params = NumParentTypeParameters();
-      if (num_parent_type_params < num_free_fun_type_params) {
-        num_free_fun_type_params = num_parent_type_params;
+      const int num_parent_type_args = NumParentTypeArguments();
+      if (num_parent_type_args < num_free_fun_type_params) {
+        num_free_fun_type_params = num_parent_type_args;
       }
     }
   }
@@ -9060,27 +9093,21 @@
 }
 
 ClassPtr Function::Owner() const {
-  if (raw_ptr()->owner() == Object::null()) {
-    ASSERT(IsSignatureFunction());
-    return Class::null();
+  ASSERT(untag()->owner() != Object::null());
+  if (untag()->owner()->IsClass()) {
+    return Class::RawCast(untag()->owner());
   }
-  if (raw_ptr()->owner()->IsClass()) {
-    return Class::RawCast(raw_ptr()->owner());
-  }
-  const Object& obj = Object::Handle(raw_ptr()->owner());
+  const Object& obj = Object::Handle(untag()->owner());
   ASSERT(obj.IsPatchClass());
   return PatchClass::Cast(obj).patched_class();
 }
 
 ClassPtr Function::origin() const {
-  if (raw_ptr()->owner() == Object::null()) {
-    ASSERT(IsSignatureFunction());
-    return Class::null();
+  ASSERT(untag()->owner() != Object::null());
+  if (untag()->owner()->IsClass()) {
+    return Class::RawCast(untag()->owner());
   }
-  if (raw_ptr()->owner()->IsClass()) {
-    return Class::RawCast(raw_ptr()->owner());
-  }
-  const Object& obj = Object::Handle(raw_ptr()->owner());
+  const Object& obj = Object::Handle(untag()->owner());
   ASSERT(obj.IsPatchClass());
   return PatchClass::Cast(obj).origin_class();
 }
@@ -9089,7 +9116,7 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
 #else
-  StoreNonPointer(&raw_ptr()->kernel_offset_, src.raw_ptr()->kernel_offset_);
+  StoreNonPointer(&untag()->kernel_offset_, src.untag()->kernel_offset_);
 #endif
 }
 
@@ -9114,7 +9141,7 @@
 ScriptPtr Function::script() const {
   // NOTE(turnidge): If you update this function, you probably want to
   // update Class::PatchFieldsAndFunctions() at the same time.
-  const Object& data = Object::Handle(raw_ptr()->data());
+  const Object& data = Object::Handle(untag()->data());
   if (IsDynamicInvocationForwarder()) {
     const auto& forwarding_target = Function::Handle(ForwardingTarget());
     return forwarding_target.script();
@@ -9126,7 +9153,7 @@
   if (data.IsArray()) {
     Object& script = Object::Handle(Array::Cast(data).At(0));
     if (script.IsScript()) {
-      return Script::Cast(script).raw();
+      return Script::Cast(script).ptr();
     }
   }
   if (token_pos() == TokenPosition::kMinSource) {
@@ -9134,26 +9161,22 @@
     // eval functions having token position 0.
     const Script& script = Script::Handle(eval_script());
     if (!script.IsNull()) {
-      return script.raw();
+      return script.ptr();
     }
   }
-  const Object& obj = Object::Handle(raw_ptr()->owner());
+  const Object& obj = Object::Handle(untag()->owner());
   if (obj.IsPatchClass()) {
     return PatchClass::Cast(obj).script();
   }
   if (IsClosureFunction()) {
     return Function::Handle(parent_function()).script();
   }
-  if (obj.IsNull()) {
-    ASSERT(IsSignatureFunction());
-    return Script::null();
-  }
   ASSERT(obj.IsClass());
   return Class::Cast(obj).script();
 }
 
 ExternalTypedDataPtr Function::KernelData() const {
-  Object& data = Object::Handle(raw_ptr()->data());
+  Object& data = Object::Handle(untag()->data());
   if (data.IsArray()) {
     Object& script = Object::Handle(Array::Cast(data).At(0));
     if (script.IsScript()) {
@@ -9166,7 +9189,7 @@
     return parent.KernelData();
   }
 
-  const Object& obj = Object::Handle(raw_ptr()->owner());
+  const Object& obj = Object::Handle(untag()->owner());
   if (obj.IsClass()) {
     Library& lib = Library::Handle(Class::Cast(obj).library());
     return lib.kernel_data();
@@ -9180,7 +9203,7 @@
       IsFfiTrampoline()) {
     return 0;
   }
-  Object& data = Object::Handle(raw_ptr()->data());
+  Object& data = Object::Handle(untag()->data());
   if (data.IsArray()) {
     Object& script = Object::Handle(Array::Cast(data).At(0));
     if (script.IsScript()) {
@@ -9193,7 +9216,7 @@
     return parent.KernelDataProgramOffset();
   }
 
-  const Object& obj = Object::Handle(raw_ptr()->owner());
+  const Object& obj = Object::Handle(untag()->owner());
   if (obj.IsClass()) {
     Library& lib = Library::Handle(Class::Cast(obj).library());
     return lib.kernel_offset();
@@ -9259,7 +9282,7 @@
                          BaseTextBuffer* printer) const {
   // If |this| is the generated asynchronous body closure, use the
   // name of the parent function.
-  Function& fun = Function::Handle(raw());
+  Function& fun = Function::Handle(ptr());
 
   if (params.disambiguate_names) {
     if (fun.IsInvokeFieldDispatcher()) {
@@ -9281,7 +9304,7 @@
         !fun.IsSyncGenerator()) {
       // Parent function is not the generator of an asynchronous body closure,
       // start at |this|.
-      fun = raw();
+      fun = ptr();
     }
   }
   if (IsClosureFunction()) {
@@ -9299,21 +9322,21 @@
         printer->AddString(".");
       }
       if (params.disambiguate_names &&
-          fun.name() == Symbols::AnonymousClosure().raw()) {
+          fun.name() == Symbols::AnonymousClosure().ptr()) {
         printer->Printf("<anonymous closure @%" Pd ">", fun.token_pos().Pos());
       } else {
         printer->AddString(fun.NameCString(params.name_visibility));
       }
       // If we skipped rewritten async/async*/sync* body then append a suffix
       // to the end of the name.
-      if (fun.raw() != raw() && params.disambiguate_names) {
+      if (fun.ptr() != ptr() && params.disambiguate_names) {
         printer->AddString("{body}");
       }
       return;
     }
   }
 
-  if (fun.kind() == FunctionLayout::kConstructor) {
+  if (fun.kind() == UntaggedFunction::kConstructor) {
     printer->AddString("new ");
   } else if (params.include_class_name) {
     const Class& cls = Class::Handle(Owner());
@@ -9330,7 +9353,7 @@
 
   // If we skipped rewritten async/async*/sync* body then append a suffix
   // to the end of the name.
-  if (fun.raw() != raw() && params.disambiguate_names) {
+  if (fun.ptr() != ptr() && params.disambiguate_names) {
     printer->AddString("{body}");
   }
 
@@ -9347,7 +9370,7 @@
     if (fun.NumOptionalPositionalParameters() != 0) {
       printer->Printf(" [%" Pd "]", fun.NumOptionalPositionalParameters());
     }
-    if (fun.NumOptionalNamedParameters() != 0) {
+    if (fun.HasOptionalNamedParameters()) {
       printer->AddString(" {");
       String& name = String::Handle();
       for (intptr_t i = 0; i < fun.NumOptionalNamedParameters(); i++) {
@@ -9361,7 +9384,7 @@
 }
 
 StringPtr Function::GetSource() const {
-  if (IsImplicitConstructor() || IsSignatureFunction() || is_synthetic()) {
+  if (IsImplicitConstructor() || is_synthetic()) {
     // We may need to handle more cases when the restrictions on mixins are
     // relaxed. In particular we might start associating some source with the
     // forwarding constructors when it becomes possible to specify a particular
@@ -9371,13 +9394,18 @@
   Zone* zone = Thread::Current()->zone();
   const Script& func_script = Script::Handle(zone, script());
 
-  intptr_t from_line;
-  intptr_t from_col;
-  intptr_t to_line;
-  intptr_t to_col;
-  intptr_t to_length;
-  func_script.GetTokenLocation(token_pos(), &from_line, &from_col);
-  func_script.GetTokenLocation(end_token_pos(), &to_line, &to_col, &to_length);
+  intptr_t from_line, from_col;
+  if (!func_script.GetTokenLocation(token_pos(), &from_line, &from_col)) {
+    return String::null();
+  }
+  intptr_t to_line, to_col;
+  if (!func_script.GetTokenLocation(end_token_pos(), &to_line, &to_col)) {
+    return String::null();
+  }
+  intptr_t to_length = func_script.GetTokenLength(end_token_pos());
+  if (to_length < 0) {
+    return String::null();
+  }
 
   if (to_length == 1) {
     // Handle special cases for end tokens of closures (where we exclude the
@@ -9388,9 +9416,9 @@
     // token semicolon belongs to the assignment so we skip it.
     const String& src = String::Handle(func_script.Source());
     if (src.IsNull() || src.Length() == 0) {
-      return Symbols::OptimizedOut().raw();
+      return Symbols::OptimizedOut().ptr();
     }
-    uint16_t end_char = src.CharAt(end_token_pos().value());
+    uint16_t end_char = src.CharAt(end_token_pos().Pos());
     if ((end_char == ',') ||  // Case 1.
         (end_char == ')') ||  // Case 2.
         (end_char == ';' && String::Handle(zone, name())
@@ -9470,7 +9498,7 @@
       ICData& ic_data = ICData::ZoneHandle(zone);
       ic_data ^= saved_ic_data.At(i);
       if (clone_ic_data) {
-        const ICData& original_ic_data = ICData::Handle(zone, ic_data.raw());
+        const ICData& original_ic_data = ICData::Handle(zone, ic_data.ptr());
         ic_data = ICData::Clone(ic_data);
         ic_data.SetOriginal(original_ic_data);
       }
@@ -9484,11 +9512,11 @@
 }
 
 void Function::set_ic_data_array(const Array& value) const {
-  raw_ptr()->set_ic_data_array<std::memory_order_release>(value.raw());
+  untag()->set_ic_data_array<std::memory_order_release>(value.ptr());
 }
 
 ArrayPtr Function::ic_data_array() const {
-  return raw_ptr()->ic_data_array<std::memory_order_acquire>();
+  return untag()->ic_data_array<std::memory_order_acquire>();
 }
 
 void Function::ClearICDataArray() const {
@@ -9501,7 +9529,7 @@
   for (intptr_t i = 1; i < array.Length(); i++) {
     ic_data ^= array.At(i);
     if (ic_data.deopt_id() == deopt_id) {
-      return ic_data.raw();
+      return ic_data.ptr();
     }
   }
   return ICData::null();
@@ -9537,7 +9565,7 @@
   }
 #endif
 
-  if (Isolate::Current()->obfuscate() || FLAG_precompiled_mode ||
+  if (IsolateGroup::Current()->obfuscate() || FLAG_precompiled_mode ||
       (Dart::vm_snapshot_kind() != Snapshot::kNone)) {
     return true;  // The kernel structure has been altered, skip checking.
   }
@@ -9571,7 +9599,7 @@
   }
   // Compiling in unoptimized mode should never fail if there are no errors.
   ASSERT(HasCode());
-  ASSERT(ForceOptimize() || unoptimized_code() == result.raw());
+  ASSERT(ForceOptimize() || unoptimized_code() == result.ptr());
   return CurrentCode();
 }
 
@@ -9618,7 +9646,7 @@
   // Issue(dartbug.com/42719):
   // Right now the metadata of _Closure.call says there are no dynamic callers -
   // even though there can be. To be conservative we return true.
-  if ((name() == Symbols::GetCall().raw() || name() == Symbols::Call().raw()) &&
+  if ((name() == Symbols::GetCall().ptr() || name() == Symbols::Call().ptr()) &&
       Class::IsClosureClass(Owner())) {
     return true;
   }
@@ -9654,6 +9682,27 @@
          (NeedsTypeArgumentTypeChecks() || NeedsArgumentTypeChecks());
 }
 
+intptr_t Function::SourceSize() const {
+  const TokenPosition& start = token_pos();
+  const TokenPosition& end = end_token_pos();
+  if (!end.IsReal() || start.IsNoSource() || start.IsClassifying()) {
+    // No source information, so just return 0.
+    return 0;
+  }
+  if (start.IsSynthetic()) {
+    // Try and approximate the source size using the parent's source size.
+    const auto& parent = Function::Handle(parent_function());
+    ASSERT(!parent.IsNull());
+    const intptr_t parent_size = parent.SourceSize();
+    if (parent_size == 0) {
+      return parent_size;
+    }
+    // Parent must have a real ending position.
+    return parent_size - (parent.end_token_pos().Pos() - end.Pos());
+  }
+  return end.Pos() - start.Pos();
+}
+
 const char* Function::ToCString() const {
   if (IsNull()) {
     return "Function: null";
@@ -9668,46 +9717,43 @@
     buffer.AddString(" abstract");
   }
   switch (kind()) {
-    case FunctionLayout::kRegularFunction:
-    case FunctionLayout::kClosureFunction:
-    case FunctionLayout::kImplicitClosureFunction:
-    case FunctionLayout::kGetterFunction:
-    case FunctionLayout::kSetterFunction:
+    case UntaggedFunction::kRegularFunction:
+    case UntaggedFunction::kClosureFunction:
+    case UntaggedFunction::kImplicitClosureFunction:
+    case UntaggedFunction::kGetterFunction:
+    case UntaggedFunction::kSetterFunction:
       break;
-    case FunctionLayout::kSignatureFunction:
-      buffer.AddString(" signature");
-      break;
-    case FunctionLayout::kConstructor:
+    case UntaggedFunction::kConstructor:
       buffer.AddString(is_static() ? " factory" : " constructor");
       break;
-    case FunctionLayout::kImplicitGetter:
+    case UntaggedFunction::kImplicitGetter:
       buffer.AddString(" getter");
       break;
-    case FunctionLayout::kImplicitSetter:
+    case UntaggedFunction::kImplicitSetter:
       buffer.AddString(" setter");
       break;
-    case FunctionLayout::kImplicitStaticGetter:
+    case UntaggedFunction::kImplicitStaticGetter:
       buffer.AddString(" static-getter");
       break;
-    case FunctionLayout::kFieldInitializer:
+    case UntaggedFunction::kFieldInitializer:
       buffer.AddString(" field-initializer");
       break;
-    case FunctionLayout::kMethodExtractor:
+    case UntaggedFunction::kMethodExtractor:
       buffer.AddString(" method-extractor");
       break;
-    case FunctionLayout::kNoSuchMethodDispatcher:
+    case UntaggedFunction::kNoSuchMethodDispatcher:
       buffer.AddString(" no-such-method-dispatcher");
       break;
-    case FunctionLayout::kDynamicInvocationForwarder:
+    case UntaggedFunction::kDynamicInvocationForwarder:
       buffer.AddString(" dynamic-invocation-forwarder");
       break;
-    case FunctionLayout::kInvokeFieldDispatcher:
+    case UntaggedFunction::kInvokeFieldDispatcher:
       buffer.AddString(" invoke-field-dispatcher");
       break;
-    case FunctionLayout::kIrregexpFunction:
+    case UntaggedFunction::kIrregexpFunction:
       buffer.AddString(" irregexp-function");
       break;
-    case FunctionLayout::kFfiTrampoline:
+    case UntaggedFunction::kFfiTrampoline:
       buffer.AddString(" ffi-trampoline-function");
       break;
     default:
@@ -9727,42 +9773,42 @@
   return buffer.buffer();
 }
 
-void ClosureData::set_context_scope(const ContextScope& value) const {
-  raw_ptr()->set_context_scope(value.raw());
+void FunctionType::set_packed_fields(uint32_t packed_fields) const {
+  StoreNonPointer(&untag()->packed_fields_, packed_fields);
 }
 
-void ClosureData::set_implicit_static_closure(const Instance& closure) const {
-  ASSERT(!closure.IsNull());
-  ASSERT(raw_ptr()->closure() == Instance::null());
-  raw_ptr()->set_closure(closure.raw());
+intptr_t FunctionType::NumParameters() const {
+  return num_fixed_parameters() + NumOptionalParameters();
 }
 
-void ClosureData::set_parent_function(const Function& value) const {
-  raw_ptr()->set_parent_function(value.raw());
-}
-
-void ClosureData::set_signature_type(const Type& value) const {
-  raw_ptr()->set_signature_type(value.raw());
+void FunctionType::set_num_implicit_parameters(intptr_t value) const {
+  ASSERT(value >= 0);
+  ASSERT(
+      Utils::IsUint(UntaggedFunctionType::kMaxImplicitParametersBits, value));
+  const uint32_t* original = &untag()->packed_fields_;
+  StoreNonPointer(original,
+                  UntaggedFunctionType::PackedNumImplicitParameters::update(
+                      value, *original));
 }
 
 void ClosureData::set_default_type_arguments(const TypeArguments& value) const {
-  raw_ptr()->set_default_type_arguments(value.raw());
+  untag()->set_default_type_arguments(value.ptr());
 }
 
 intptr_t ClosureData::default_type_arguments_info() const {
-  const SmiPtr value = raw_ptr()->default_type_arguments_info();
+  const SmiPtr value = untag()->default_type_arguments_info();
   if (value == Smi::null()) {
     static_assert(Function::DefaultTypeArgumentsKindField::decode(0) ==
                       Function::DefaultTypeArgumentsKind::kInvalid,
                   "Returning valid value for null Smi");
     return 0;
   }
-  return Smi::Value(raw_ptr()->default_type_arguments_info());
+  return Smi::Value(untag()->default_type_arguments_info());
 }
 
 void ClosureData::set_default_type_arguments_info(intptr_t value) const {
   ASSERT(Smi::IsValid(value));
-  raw_ptr()->set_default_type_arguments_info(Smi::New(value));
+  untag()->set_default_type_arguments_info(Smi::New(value));
 }
 
 ClosureDataPtr ClosureData::New() {
@@ -9786,12 +9832,6 @@
   } else {
     buffer.AddString(Function::Handle(zone, parent_function()).ToCString());
   }
-  buffer.AddString(" signature_type: ");
-  if (signature_type() == Type::null()) {
-    buffer.AddString("null");
-  } else {
-    buffer.AddString(Type::Handle(zone, signature_type()).ToCString());
-  }
   buffer.Printf(" implicit_static_closure: 0x%" Px "",
                 static_cast<uword>(implicit_static_closure()));
   buffer.AddString(" default_type_arguments: ");
@@ -9804,52 +9844,145 @@
   return buffer.buffer();
 }
 
-void SignatureData::set_parent_function(const Function& value) const {
-  raw_ptr()->set_parent_function(value.raw());
+void Function::set_num_fixed_parameters(intptr_t value) const {
+  ASSERT(value >= 0);
+  ASSERT(Utils::IsUint(UntaggedFunction::kMaxFixedParametersBits, value));
+  const uint32_t* original = &untag()->packed_fields_;
+  StoreNonPointer(original, UntaggedFunction::PackedNumFixedParameters::update(
+                                value, *original));
+  // Also store in signature.
+  FunctionType::Handle(signature()).set_num_fixed_parameters(value);
 }
 
-void SignatureData::set_signature_type(const Type& value) const {
-  raw_ptr()->set_signature_type(value.raw());
+void FunctionType::set_num_fixed_parameters(intptr_t value) const {
+  ASSERT(value >= 0);
+  ASSERT(Utils::IsUint(UntaggedFunctionType::kMaxFixedParametersBits, value));
+  const uint32_t* original = &untag()->packed_fields_;
+  StoreNonPointer(
+      original,
+      UntaggedFunctionType::PackedNumFixedParameters::update(value, *original));
 }
 
-SignatureDataPtr SignatureData::New(Heap::Space space) {
-  ASSERT(Object::signature_data_class() != Class::null());
-  ObjectPtr raw = Object::Allocate(SignatureData::kClassId,
-                                   SignatureData::InstanceSize(), space);
-  return static_cast<SignatureDataPtr>(raw);
-}
-
-const char* SignatureData::ToCString() const {
-  if (IsNull()) {
-    return "SignatureData: null";
-  }
-  const Function& parent = Function::Handle(parent_function());
-  const Type& type = Type::Handle(signature_type());
-  return OS::SCreate(Thread::Current()->zone(),
-                     "SignatureData parent_function: %s signature_type: %s",
-                     parent.IsNull() ? "null" : parent.ToCString(),
-                     type.IsNull() ? "null" : type.ToCString());
-}
-
-void FfiTrampolineData::set_signature_type(const Type& value) const {
-  raw_ptr()->set_signature_type(value.raw());
-}
-
-void FfiTrampolineData::set_c_signature(const Function& value) const {
-  raw_ptr()->set_c_signature(value.raw());
+void Function::SetNumOptionalParameters(intptr_t value,
+                                        bool are_optional_positional) const {
+  ASSERT(Utils::IsUint(UntaggedFunction::kMaxOptionalParametersBits, value));
+  uint32_t packed_fields = untag()->packed_fields_;
+  packed_fields = UntaggedFunction::PackedHasNamedOptionalParameters::update(
+      (value > 0) && !are_optional_positional, packed_fields);
+  packed_fields = UntaggedFunction::PackedNumOptionalParameters::update(
+      value, packed_fields);
+  StoreNonPointer(&untag()->packed_fields_, packed_fields);
+  // Also store in signature.
+  FunctionType::Handle(signature())
+      .SetNumOptionalParameters(value, are_optional_positional);
 }
 
 void FfiTrampolineData::set_callback_target(const Function& value) const {
-  raw_ptr()->set_callback_target(value.raw());
+  untag()->set_callback_target(value.ptr());
+}
+
+void FunctionType::SetNumOptionalParameters(
+    intptr_t value,
+    bool are_optional_positional) const {
+  ASSERT(
+      Utils::IsUint(UntaggedFunctionType::kMaxOptionalParametersBits, value));
+  uint32_t packed_fields = untag()->packed_fields_;
+  packed_fields =
+      UntaggedFunctionType::PackedHasNamedOptionalParameters::update(
+          (value > 0) && !are_optional_positional, packed_fields);
+  packed_fields = UntaggedFunctionType::PackedNumOptionalParameters::update(
+      value, packed_fields);
+  StoreNonPointer(&untag()->packed_fields_, packed_fields);
+}
+
+FunctionTypePtr FunctionType::New(Heap::Space space) {
+  ObjectPtr raw = Object::Allocate(FunctionType::kClassId,
+                                   FunctionType::InstanceSize(), space);
+  return static_cast<FunctionTypePtr>(raw);
+}
+
+FunctionTypePtr FunctionType::New(intptr_t num_parent_type_arguments,
+                                  Nullability nullability,
+                                  Heap::Space space) {
+  Zone* Z = Thread::Current()->zone();
+  const FunctionType& result =
+      FunctionType::Handle(Z, FunctionType::New(space));
+  result.set_packed_fields(0);
+  result.SetNumParentTypeArguments(num_parent_type_arguments);
+  result.set_num_fixed_parameters(0);
+  result.SetNumOptionalParameters(0, false);
+  result.set_nullability(nullability);
+  result.SetHash(0);
+  result.StoreNonPointer(&result.untag()->type_state_,
+                         UntaggedType::kAllocated);
+  result.SetTypeTestingStub(
+      Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
+  return result.ptr();
+}
+
+void FunctionType::set_type_state(uint8_t state) const {
+  ASSERT((state >= UntaggedFunctionType::kAllocated) &&
+         (state <= UntaggedFunctionType::kFinalizedUninstantiated));
+  StoreNonPointer(&untag()->type_state_, state);
+}
+
+const char* FunctionType::ToUserVisibleCString() const {
+  Zone* zone = Thread::Current()->zone();
+  ZoneTextBuffer printer(zone);
+  Print(kUserVisibleName, &printer);
+  return printer.buffer();
+}
+
+StringPtr FunctionType::ToUserVisibleString() const {
+  Thread* thread = Thread::Current();
+  ZoneTextBuffer printer(thread->zone());
+  Print(kUserVisibleName, &printer);
+  return Symbols::New(thread, printer.buffer());
+}
+
+const char* FunctionType::ToCString() const {
+  if (IsNull()) {
+    return "FunctionType: null";
+  }
+  Zone* zone = Thread::Current()->zone();
+  ZoneTextBuffer printer(zone);
+  const char* suffix = NullabilitySuffix(kInternalName);
+  if (suffix[0] != '\0') {
+    printer.AddString("(");
+  }
+  Print(kInternalName, &printer);
+  if (suffix[0] != '\0') {
+    printer.AddString(")");
+    printer.AddString(suffix);
+  }
+  return printer.buffer();
+}
+
+void ClosureData::set_context_scope(const ContextScope& value) const {
+  untag()->set_context_scope(value.ptr());
+}
+
+void ClosureData::set_implicit_static_closure(const Instance& closure) const {
+  ASSERT(!closure.IsNull());
+  ASSERT(untag()->closure() == Instance::null());
+  untag()->set_closure<std::memory_order_release>(closure.ptr());
+}
+
+void ClosureData::set_parent_function(const Function& value) const {
+  untag()->set_parent_function(value.ptr());
+}
+
+void FfiTrampolineData::set_c_signature(const FunctionType& value) const {
+  untag()->set_c_signature(value.ptr());
 }
 
 void FfiTrampolineData::set_callback_id(int32_t callback_id) const {
-  StoreNonPointer(&raw_ptr()->callback_id_, callback_id);
+  StoreNonPointer(&untag()->callback_id_, callback_id);
 }
 
 void FfiTrampolineData::set_callback_exceptional_return(
     const Instance& value) const {
-  raw_ptr()->set_callback_exceptional_return(value.raw());
+  untag()->set_callback_exceptional_return(value.ptr());
 }
 
 FfiTrampolineDataPtr FfiTrampolineData::New() {
@@ -9858,22 +9991,15 @@
       Object::Allocate(FfiTrampolineData::kClassId,
                        FfiTrampolineData::InstanceSize(), Heap::kOld);
   FfiTrampolineDataPtr data = static_cast<FfiTrampolineDataPtr>(raw);
-  data->ptr()->callback_id_ = 0;
+  data->untag()->callback_id_ = 0;
   return data;
 }
 
 const char* FfiTrampolineData::ToCString() const {
-  Type& signature_type = Type::Handle(this->signature_type());
-  String& signature_type_name =
-      String::Handle(signature_type.UserVisibleName());
-  return OS::SCreate(
-      Thread::Current()->zone(), "TrampolineData: signature=%s",
-      signature_type_name.IsNull() ? "null" : signature_type_name.ToCString());
-}
-
-bool Field::ShouldCloneFields() {
-  return Compiler::IsBackgroundCompilation() ||
-         FLAG_force_clone_compiler_objects;
+  const FunctionType& c_sig = FunctionType::Handle(c_signature());
+  return OS::SCreate(Thread::Current()->zone(),
+                     "TrampolineData: c_signature=%s",
+                     c_sig.ToUserVisibleCString());
 }
 
 FieldPtr Field::CloneFromOriginal() const {
@@ -9884,11 +10010,11 @@
   if (IsNull()) {
     return Field::null();
   }
-  Object& obj = Object::Handle(raw_ptr()->owner());
+  Object& obj = Object::Handle(untag()->owner());
   if (obj.IsField()) {
-    return Field::RawCast(obj.raw());
+    return Field::RawCast(obj.ptr());
   } else {
-    return this->raw();
+    return this->ptr();
   }
 }
 
@@ -9907,10 +10033,60 @@
   return &value;
 }
 
+void Field::DisableFieldUnboxing() const {
+  Thread* thread = Thread::Current();
+  ASSERT(!IsOriginal());
+  const Field& original = Field::Handle(Original());
+  if (!original.is_unboxing_candidate()) {
+    return;
+  }
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  if (!original.is_unboxing_candidate()) {
+    return;
+  }
+  original.set_is_unboxing_candidate(false);
+  set_is_unboxing_candidate(false);
+  original.DeoptimizeDependentCode();
+}
+
+intptr_t Field::guarded_cid() const {
+#if defined(DEBUG)
+  // This assertion ensures that the cid seen by the background compiler is
+  // consistent. So the assertion passes if the field is a clone. It also
+  // passes if the field is static, because we don't use field guards on
+  // static fields.
+  Thread* thread = Thread::Current();
+  ASSERT(!thread->IsInsideCompiler() ||
+#if !defined(DART_PRECOMPILED_RUNTIME)
+         ((CompilerState::Current().should_clone_fields() == !IsOriginal())) ||
+#endif
+         is_static());
+#endif
+  return LoadNonPointer<ClassIdTagType, std::memory_order_relaxed>(
+      &untag()->guarded_cid_);
+}
+
+bool Field::is_nullable(bool silence_assert) const {
+#if defined(DEBUG)
+  if (!silence_assert) {
+    // Same assert as guarded_cid(), because is_nullable() also needs to be
+    // consistent for the background compiler.
+    Thread* thread = Thread::Current();
+    ASSERT(
+        !thread->IsInsideCompiler() ||
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        ((CompilerState::Current().should_clone_fields() == !IsOriginal())) ||
+#endif
+        is_static());
+  }
+#endif
+  return untag()->is_nullable_ == kNullCid;
+}
+
 void Field::SetOriginal(const Field& value) const {
   ASSERT(value.IsOriginal());
   ASSERT(!value.IsNull());
-  raw_ptr()->set_owner(static_cast<ObjectPtr>(value.raw()));
+  untag()->set_owner(static_cast<ObjectPtr>(value.ptr()));
 }
 
 StringPtr Field::GetterName(const String& field_name) {
@@ -9967,26 +10143,26 @@
 void Field::set_name(const String& value) const {
   ASSERT(value.IsSymbol());
   ASSERT(IsOriginal());
-  raw_ptr()->set_name(value.raw());
+  untag()->set_name(value.ptr());
 }
 
 ObjectPtr Field::RawOwner() const {
   if (IsOriginal()) {
-    return raw_ptr()->owner();
+    return untag()->owner();
   } else {
     const Field& field = Field::Handle(Original());
     ASSERT(field.IsOriginal());
-    ASSERT(!Object::Handle(field.raw_ptr()->owner()).IsField());
-    return field.raw_ptr()->owner();
+    ASSERT(!Object::Handle(field.untag()->owner()).IsField());
+    return field.untag()->owner();
   }
 }
 
 ClassPtr Field::Owner() const {
   const Field& field = Field::Handle(Original());
   ASSERT(field.IsOriginal());
-  const Object& obj = Object::Handle(field.raw_ptr()->owner());
+  const Object& obj = Object::Handle(field.untag()->owner());
   if (obj.IsClass()) {
-    return Class::Cast(obj).raw();
+    return Class::Cast(obj).ptr();
   }
   ASSERT(obj.IsPatchClass());
   return PatchClass::Cast(obj).patched_class();
@@ -9995,9 +10171,9 @@
 ClassPtr Field::Origin() const {
   const Field& field = Field::Handle(Original());
   ASSERT(field.IsOriginal());
-  const Object& obj = Object::Handle(field.raw_ptr()->owner());
+  const Object& obj = Object::Handle(field.untag()->owner());
   if (obj.IsClass()) {
-    return Class::Cast(obj).raw();
+    return Class::Cast(obj).ptr();
   }
   ASSERT(obj.IsPatchClass());
   return PatchClass::Cast(obj).origin_class();
@@ -10008,7 +10184,7 @@
   // update Class::PatchFieldsAndFunctions() at the same time.
   const Field& field = Field::Handle(Original());
   ASSERT(field.IsOriginal());
-  const Object& obj = Object::Handle(field.raw_ptr()->owner());
+  const Object& obj = Object::Handle(field.untag()->owner());
   if (obj.IsClass()) {
     return Class::Cast(obj).script();
   }
@@ -10017,7 +10193,7 @@
 }
 
 ExternalTypedDataPtr Field::KernelData() const {
-  const Object& obj = Object::Handle(this->raw_ptr()->owner());
+  const Object& obj = Object::Handle(this->untag()->owner());
   // During background JIT compilation field objects are copied
   // and copy points to the original field via the owner field.
   if (obj.IsField()) {
@@ -10034,12 +10210,12 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
 #else
-  StoreNonPointer(&raw_ptr()->kernel_offset_, src.raw_ptr()->kernel_offset_);
+  StoreNonPointer(&untag()->kernel_offset_, src.untag()->kernel_offset_);
 #endif
 }
 
 intptr_t Field::KernelDataProgramOffset() const {
-  const Object& obj = Object::Handle(raw_ptr()->owner());
+  const Object& obj = Object::Handle(untag()->owner());
   // During background JIT compilation field objects are copied
   // and copy points to the original field via the owner field.
   if (obj.IsField()) {
@@ -10052,16 +10228,21 @@
   return PatchClass::Cast(obj).library_kernel_offset();
 }
 
-// Called at finalization time
-void Field::SetFieldType(const AbstractType& value) const {
-  ASSERT(Thread::Current()->IsMutatorThread());
+void Field::SetFieldTypeSafe(const AbstractType& value) const {
   ASSERT(IsOriginal());
   ASSERT(!value.IsNull());
-  if (value.raw() != type()) {
-    raw_ptr()->set_type(value.raw());
+  if (value.ptr() != type()) {
+    untag()->set_type(value.ptr());
   }
 }
 
+// Called at finalization time
+void Field::SetFieldType(const AbstractType& value) const {
+  DEBUG_ASSERT(
+      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+  SetFieldTypeSafe(value);
+}
+
 FieldPtr Field::New() {
   ASSERT(Object::field_class() != Class::null());
   ObjectPtr raw =
@@ -10083,7 +10264,7 @@
   result.set_name(name);
   result.set_is_static(is_static);
   if (is_static) {
-    result.set_field_id(-1);
+    result.set_field_id_unsafe(-1);
   } else {
     result.SetOffset(0, 0);
   }
@@ -10091,35 +10272,37 @@
   result.set_is_const(is_const);
   result.set_is_reflectable(is_reflectable);
   result.set_is_late(is_late);
-  result.set_is_double_initialized(false);
+  result.set_is_double_initialized_unsafe(false);
   result.set_owner(owner);
   result.set_token_pos(token_pos);
   result.set_end_token_pos(end_token_pos);
-  result.set_has_nontrivial_initializer(false);
-  result.set_has_initializer(false);
+  result.set_has_nontrivial_initializer_unsafe(false);
+  result.set_has_initializer_unsafe(false);
   if (FLAG_precompiled_mode) {
     // May be updated by KernelLoader::ReadInferredType
-    result.set_is_unboxing_candidate(false);
+    result.set_is_unboxing_candidate_unsafe(false);
   } else {
-    result.set_is_unboxing_candidate(!is_final && !is_late && !is_static);
+    result.set_is_unboxing_candidate_unsafe(!is_final && !is_late &&
+                                            !is_static);
   }
   result.set_initializer_changed_after_initialization(false);
   NOT_IN_PRECOMPILED(result.set_kernel_offset(0));
   result.set_has_pragma(false);
   result.set_static_type_exactness_state(
       StaticTypeExactnessState::NotTracking());
-  Isolate* isolate = Isolate::Current();
+  auto isolate = Isolate::Current();
+  auto isolate_group = isolate->group();
 
 // Use field guards if they are enabled and the isolate has never reloaded.
 // TODO(johnmccutchan): The reload case assumes the worst case (everything is
 // dynamic and possibly null). Attempt to relax this later.
 #if defined(PRODUCT)
   const bool use_guarded_cid =
-      FLAG_precompiled_mode || isolate->use_field_guards();
+      FLAG_precompiled_mode || isolate_group->use_field_guards();
 #else
   const bool use_guarded_cid =
       FLAG_precompiled_mode ||
-      (isolate->use_field_guards() && !isolate->HasAttemptedReload());
+      (isolate_group->use_field_guards() && !isolate->HasAttemptedReload());
 #endif  // !defined(PRODUCT)
   result.set_guarded_cid_unsafe(use_guarded_cid ? kIllegalCid : kDynamicCid);
   result.set_is_nullable_unsafe(use_guarded_cid ? false : true);
@@ -10147,8 +10330,8 @@
   const Field& result = Field::Handle(Field::New());
   InitializeNew(result, name, is_static, is_final, is_const, is_reflectable,
                 is_late, owner, token_pos, end_token_pos);
-  result.SetFieldType(type);
-  return result.raw();
+  result.SetFieldTypeSafe(type);
+  return result.ptr();
 }
 
 FieldPtr Field::NewTopLevel(const String& name,
@@ -10163,7 +10346,7 @@
   InitializeNew(result, name, true,       /* is_static */
                 is_final, is_const, true, /* is_reflectable */
                 is_late, owner, token_pos, end_token_pos);
-  return result.raw();
+  return result.ptr();
 }
 
 FieldPtr Field::Clone(const Field& original) const {
@@ -10175,7 +10358,7 @@
   clone ^= Object::Clone(*this, Heap::kOld);
   clone.SetOriginal(original);
   clone.InheritKernelOffsetFrom(original);
-  return clone.raw();
+  return clone.ptr();
 }
 
 int32_t Field::SourceFingerprint() const {
@@ -10210,24 +10393,22 @@
 }
 
 intptr_t Field::guarded_list_length() const {
-  return Smi::Value(raw_ptr()->guarded_list_length());
+  return Smi::Value(untag()->guarded_list_length());
 }
 
 void Field::set_guarded_list_length_unsafe(intptr_t list_length) const {
-  ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(IsOriginal());
-  raw_ptr()->set_guarded_list_length(Smi::New(list_length));
+  untag()->set_guarded_list_length(Smi::New(list_length));
 }
 
 intptr_t Field::guarded_list_length_in_object_offset() const {
-  return raw_ptr()->guarded_list_length_in_object_offset_ + kHeapObjectTag;
+  return untag()->guarded_list_length_in_object_offset_ + kHeapObjectTag;
 }
 
 void Field::set_guarded_list_length_in_object_offset_unsafe(
     intptr_t list_length_offset) const {
-  ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(IsOriginal());
-  StoreNonPointer(&raw_ptr()->guarded_list_length_in_object_offset_,
+  StoreNonPointer(&untag()->guarded_list_length_in_object_offset_,
                   static_cast<int8_t>(list_length_offset - kHeapObjectTag));
   ASSERT(guarded_list_length_in_object_offset() == list_length_offset);
 }
@@ -10307,7 +10488,7 @@
         Instance::Handle(zone, closure_field.StaticValue());
     ASSERT(!closure.IsNull());
     ASSERT(closure.IsClosure());
-    return closure.raw();
+    return closure.ptr();
   }
 
   UNREACHABLE();
@@ -10325,14 +10506,14 @@
 ArrayPtr Field::dependent_code() const {
   DEBUG_ASSERT(
       IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
-  return raw_ptr()->dependent_code();
+  return untag()->dependent_code();
 }
 
 void Field::set_dependent_code(const Array& array) const {
   ASSERT(IsOriginal());
   DEBUG_ASSERT(
       IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
-  raw_ptr()->set_dependent_code(array.raw());
+  untag()->set_dependent_code(array.ptr());
 }
 
 class FieldDependentArray : public WeakCodeReferences {
@@ -10387,10 +10568,10 @@
 }
 
 bool Field::IsConsistentWith(const Field& other) const {
-  return (raw_ptr()->guarded_cid_ == other.raw_ptr()->guarded_cid_) &&
-         (raw_ptr()->is_nullable_ == other.raw_ptr()->is_nullable_) &&
-         (raw_ptr()->guarded_list_length() ==
-          other.raw_ptr()->guarded_list_length()) &&
+  return (untag()->guarded_cid_ == other.untag()->guarded_cid_) &&
+         (untag()->is_nullable_ == other.untag()->is_nullable_) &&
+         (untag()->guarded_list_length() ==
+          other.untag()->guarded_list_length()) &&
          (is_unboxing_candidate() == other.is_unboxing_candidate()) &&
          (static_type_exactness_state().Encode() ==
           other.static_type_exactness_state().Encode());
@@ -10400,8 +10581,8 @@
   Thread* thread = Thread::Current();
   const FieldTable* field_table = thread->isolate()->field_table();
   const InstancePtr raw_value = field_table->At(field_id());
-  ASSERT(raw_value != Object::transition_sentinel().raw());
-  return raw_value == Object::sentinel().raw();
+  ASSERT(raw_value != Object::transition_sentinel().ptr());
+  return raw_value == Object::sentinel().ptr();
 }
 
 FunctionPtr Field::EnsureInitializerFunction() const {
@@ -10423,7 +10604,7 @@
     }
 #endif
   }
-  return initializer.raw();
+  return initializer.ptr();
 }
 
 void Field::SetInitializerFunction(const Function& initializer) const {
@@ -10437,19 +10618,19 @@
   // We have to ensure that all stores into the initializer function object
   // happen before releasing the pointer to the initializer as it may be
   // accessed without grabbing the lock.
-  raw_ptr()->set_initializer_function<std::memory_order_release>(
-      initializer.raw());
+  untag()->set_initializer_function<std::memory_order_release>(
+      initializer.ptr());
 #endif
 }
 
 bool Field::HasInitializerFunction() const {
-  return raw_ptr()->initializer_function() != Function::null();
+  return untag()->initializer_function() != Function::null();
 }
 
 ErrorPtr Field::InitializeInstance(const Instance& instance) const {
   ASSERT(IsOriginal());
   ASSERT(is_instance());
-  ASSERT(instance.GetField(*this) == Object::sentinel().raw());
+  ASSERT(instance.GetField(*this) == Object::sentinel().ptr());
   Object& value = Object::Handle();
 
   if (has_nontrivial_initializer()) {
@@ -10458,7 +10639,7 @@
     args.SetAt(0, instance);
     value = DartEntry::InvokeFunction(initializer, args);
     if (!value.IsNull() && value.IsError()) {
-      return Error::Cast(value).raw();
+      return Error::Cast(value).ptr();
     }
   } else {
     if (is_late() && !has_initializer()) {
@@ -10475,7 +10656,7 @@
   }
   ASSERT(value.IsNull() || value.IsInstance());
   if (is_late() && is_final() &&
-      (instance.GetField(*this) != Object::sentinel().raw())) {
+      (instance.GetField(*this) != Object::sentinel().ptr())) {
     Exceptions::ThrowLateFieldAssignedDuringInitialization(
         String::Handle(name()));
     UNREACHABLE();
@@ -10487,7 +10668,7 @@
 ErrorPtr Field::InitializeStatic() const {
   ASSERT(IsOriginal());
   ASSERT(is_static());
-  if (StaticValue() == Object::sentinel().raw()) {
+  if (StaticValue() == Object::sentinel().ptr()) {
     auto& value = Object::Handle();
     if (is_late()) {
       if (!has_initializer()) {
@@ -10496,9 +10677,9 @@
       }
       value = EvaluateInitializer();
       if (value.IsError()) {
-        return Error::Cast(value).raw();
+        return Error::Cast(value).ptr();
       }
-      if (is_final() && (StaticValue() != Object::sentinel().raw())) {
+      if (is_final() && (StaticValue() != Object::sentinel().ptr())) {
         Exceptions::ThrowLateFieldAssignedDuringInitialization(
             String::Handle(name()));
         UNREACHABLE();
@@ -10508,15 +10689,14 @@
       value = EvaluateInitializer();
       if (value.IsError()) {
         SetStaticValue(Object::null_instance());
-        return Error::Cast(value).raw();
+        return Error::Cast(value).ptr();
       }
     }
     ASSERT(value.IsNull() || value.IsInstance());
-    SetStaticValue(
-        value.IsNull() ? Instance::null_instance() : Instance::Cast(value),
-        is_const());
+    SetStaticValue(value.IsNull() ? Instance::null_instance()
+                                  : Instance::Cast(value));
     return Error::null();
-  } else if (StaticValue() == Object::transition_sentinel().raw()) {
+  } else if (StaticValue() == Object::transition_sentinel().ptr()) {
     ASSERT(!is_late());
     const Array& ctor_args = Array::Handle(Array::New(1));
     const String& field_name = String::Handle(name());
@@ -10527,13 +10707,48 @@
   return Error::null();
 }
 
+ObjectPtr Field::StaticConstFieldValue() const {
+  ASSERT(is_static() && is_const());
+
+  auto thread = Thread::Current();
+  auto zone = thread->zone();
+  auto initial_field_table = thread->isolate_group()->initial_field_table();
+
+  // 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()));
+  if (value.ptr() == Object::sentinel().ptr()) {
+    ASSERT(has_initializer());
+    value = EvaluateInitializer();
+    if (!value.IsError()) {
+      ASSERT(value.IsNull() || value.IsInstance());
+      SetStaticConstFieldValue(value.IsNull() ? Instance::null_instance()
+                                              : Instance::Cast(value));
+    }
+  }
+  return value.ptr();
+}
+
+void Field::SetStaticConstFieldValue(const Instance& value,
+                                     bool assert_initializing_store) const {
+  auto thread = Thread::Current();
+  auto initial_field_table = thread->isolate_group()->initial_field_table();
+
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  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());
+}
+
 ObjectPtr Field::EvaluateInitializer() const {
   Thread* const thread = Thread::Current();
   ASSERT(thread->IsMutatorThread());
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (is_static() && is_const()) {
-    ASSERT(!FLAG_precompiled_mode);
     return kernel::EvaluateStaticConstFieldInitializer(*this);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -10587,7 +10802,7 @@
   }
 
   const Class& cls =
-      Class::Handle(Isolate::Current()->class_table()->At(guarded_cid()));
+      Class::Handle(IsolateGroup::Current()->class_table()->At(guarded_cid()));
   const char* class_name = String::Handle(cls.Name()).ToCString();
 
   if (IsBuiltinListClassId(guarded_cid()) && !is_nullable() && is_final()) {
@@ -10696,7 +10911,7 @@
                                 const Class& cls,
                                 GrowableArray<const AbstractType*>* path,
                                 bool consider_only_super_classes) {
-  if (type.type_class() == cls.raw()) {
+  if (type.type_class() == cls.ptr()) {
     return true;  // Found instantiation.
   }
 
@@ -10729,20 +10944,16 @@
   return false;  // Not found.
 }
 
-void Field::SetStaticValue(const Instance& value,
-                           bool save_initial_value) const {
-  ASSERT(Thread::Current()->IsMutatorThread());
+void Field::SetStaticValue(const Instance& value) const {
+  auto thread = Thread::Current();
+  ASSERT(thread->IsMutatorThread());
 
   ASSERT(is_static());  // Valid only for static dart fields.
-  Isolate* isolate = Isolate::Current();
   const intptr_t id = field_id();
   ASSERT(id >= 0);
-  isolate->field_table()->SetAt(id, value.raw());
-  if (save_initial_value) {
-#if !defined(DART_PRECOMPILED_RUNTIME)
-    isolate->group()->initial_field_table()->SetAt(field_id(), value.raw());
-#endif
-  }
+
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  thread->isolate()->field_table()->SetAt(id, value.ptr());
 }
 
 static StaticTypeExactnessState TrivialTypeExactnessFor(const Class& cls) {
@@ -10758,7 +10969,7 @@
 }
 
 static const char* SafeTypeArgumentsToCString(const TypeArguments& args) {
-  return (args.raw() == TypeArguments::null()) ? "<null>" : args.ToCString();
+  return (args.ptr() == TypeArguments::null()) ? "<null>" : args.ToCString();
 }
 
 StaticTypeExactnessState StaticTypeExactnessState::Compute(
@@ -10766,8 +10977,8 @@
     const Instance& value,
     bool print_trace /* = false */) {
   ASSERT(!value.IsNull());  // Should be handled by the caller.
-  ASSERT(value.raw() != Object::sentinel().raw());
-  ASSERT(value.raw() != Object::transition_sentinel().raw());
+  ASSERT(value.ptr() != Object::sentinel().ptr());
+  ASSERT(value.ptr() != Object::transition_sentinel().ptr());
 
   const TypeArguments& static_type_args =
       TypeArguments::Handle(static_type.arguments());
@@ -10790,12 +11001,12 @@
   // Trivial case: field has type G<T0, ..., Tn> and value has type
   // G<U0, ..., Un>. Check if type arguments match.
   if (path.is_empty()) {
-    ASSERT(cls.raw() == static_type.type_class());
+    ASSERT(cls.ptr() == static_type.type_class());
     args = value.GetTypeArguments();
     // TODO(dartbug.com/34170) Evaluate if comparing relevant subvectors (that
     // disregards superclass own arguments) improves precision of the
     // tracking.
-    if (args.raw() == static_type_args.raw()) {
+    if (args.ptr() == static_type_args.ptr()) {
       return TrivialTypeExactnessFor(cls);
     }
 
@@ -10815,7 +11026,7 @@
   // To compute C<X0, ..., Xn> at G we walk the chain backwards and
   // instantiate Si using type parameters of S{i-1} which gives us a type
   // depending on type parameters of S{i-2}.
-  AbstractType& type = AbstractType::Handle(path.Last()->raw());
+  AbstractType& type = AbstractType::Handle(path.Last()->ptr());
   for (intptr_t i = path.length() - 2; (i >= 0) && !type.IsInstantiated();
        i--) {
     args = path[i]->arguments();
@@ -10937,7 +11148,7 @@
   TypeArguments& args = TypeArguments::Handle();
   if (static_type_exactness_state().IsTriviallyExact()) {
     args = instance.GetTypeArguments();
-    if (args.raw() == field_type_args.raw()) {
+    if (args.ptr() == field_type_args.ptr()) {
       return false;
     }
 
@@ -10958,17 +11169,17 @@
 
 void Field::RecordStore(const Object& value) const {
   ASSERT(IsOriginal());
-  if (!Isolate::Current()->use_field_guards()) {
+  if (!IsolateGroup::Current()->use_field_guards()) {
     return;
   }
 
   // We should never try to record a sentinel.
-  ASSERT(value.raw() != Object::sentinel().raw());
+  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.raw() == Object::null())) {
+      (is_nullable() && value.ptr() == Object::null())) {
     // Nothing to do: the field is not guarded or we are storing null into
     // a nullable field.
     return;
@@ -11012,16 +11223,16 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 void Field::set_type_test_cache(const SubtypeTestCache& cache) const {
-  raw_ptr()->set_type_test_cache(cache.raw());
+  untag()->set_type_test_cache(cache.ptr());
 }
 #endif
 
 bool Script::HasSource() const {
-  return raw_ptr()->source() != String::null();
+  return untag()->source() != String::null();
 }
 
 StringPtr Script::Source() const {
-  return raw_ptr()->source();
+  return untag()->source();
 }
 
 bool Script::IsPartOfDartColonLibrary() const {
@@ -11041,15 +11252,15 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 void Script::set_compile_time_constants(const Array& value) const {
-  raw_ptr()->set_compile_time_constants(value.raw());
+  untag()->set_compile_time_constants(value.ptr());
 }
 
 void Script::set_kernel_program_info(const KernelProgramInfo& info) const {
-  raw_ptr()->set_kernel_program_info(info.raw());
+  untag()->set_kernel_program_info(info.ptr());
 }
 
 void Script::set_kernel_script_index(const intptr_t kernel_script_index) const {
-  StoreNonPointer(&raw_ptr()->kernel_script_index_, kernel_script_index);
+  StoreNonPointer(&untag()->kernel_script_index_, kernel_script_index);
 }
 
 TypedDataPtr Script::kernel_string_offsets() const {
@@ -11072,16 +11283,16 @@
     Library& lib = Library::Handle(zone);
     Script& script = Script::Handle(zone);
     const GrowableObjectArray& libs = GrowableObjectArray::Handle(
-        zone, Isolate::Current()->object_store()->libraries());
+        zone, IsolateGroup::Current()->object_store()->libraries());
     for (intptr_t i = 0; i < libs.Length(); i++) {
       lib ^= libs.At(i);
       script = lib.LookupScript(uri, /* useResolvedUri = */ true);
       if (!script.IsNull()) {
         const auto& source = String::Handle(zone, script.Source());
-        const auto& line_starts = TypedData::Handle(zone, script.line_starts());
-        if (!source.IsNull() || !line_starts.IsNull()) {
+        const auto& starts = TypedData::Handle(zone, script.line_starts());
+        if (!source.IsNull() || !starts.IsNull()) {
           set_source(source);
-          set_line_starts(line_starts);
+          set_line_starts(starts);
           break;
         }
       }
@@ -11101,7 +11312,7 @@
     // Scripts in the AOT snapshot do not have a line starts array.
     // A well-formed line number array has a leading null.
     info.Add(line_separator);  // New line.
-    return info.raw();
+    return info.ptr();
   }
 #if !defined(DART_PRECOMPILED_RUNTIME)
   Smi& value = Smi::Handle(zone);
@@ -11142,103 +11353,124 @@
     previous_start = start;
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
-  return info.raw();
+  return info.ptr();
+}
+
+TokenPosition Script::MaxPosition() const {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (HasCachedMaxPosition()) {
+    return TokenPosition::Deserialize(
+        UntaggedScript::CachedMaxPositionBitField::decode(
+            untag()->flags_and_max_position_));
+  }
+  auto const zone = Thread::Current()->zone();
+  LookupSourceAndLineStarts(zone);
+  if (!HasCachedMaxPosition() && line_starts() != TypedData::null()) {
+    const auto& starts = TypedData::Handle(zone, line_starts());
+    kernel::KernelLineStartsReader reader(starts, zone);
+    const intptr_t max_position = reader.MaxPosition();
+    SetCachedMaxPosition(max_position);
+    SetHasCachedMaxPosition(true);
+    return TokenPosition::Deserialize(max_position);
+  }
+#endif
+  return TokenPosition::kNoSource;
 }
 
 void Script::set_url(const String& value) const {
-  raw_ptr()->set_url(value.raw());
+  untag()->set_url(value.ptr());
 }
 
 void Script::set_resolved_url(const String& value) const {
-  raw_ptr()->set_resolved_url(value.raw());
+  untag()->set_resolved_url(value.ptr());
 }
 
 void Script::set_source(const String& value) const {
-  raw_ptr()->set_source(value.raw());
+  untag()->set_source(value.ptr());
 }
 
 void Script::set_line_starts(const TypedData& value) const {
-  raw_ptr()->set_line_starts(value.raw());
+  untag()->set_line_starts(value.ptr());
 }
 
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 void Script::set_constant_coverage(const ExternalTypedData& value) const {
-  raw_ptr()->set_constant_coverage(value.raw());
+  untag()->set_constant_coverage(value.ptr());
 }
 
 ExternalTypedDataPtr Script::constant_coverage() const {
-  return raw_ptr()->constant_coverage();
+  return untag()->constant_coverage();
 }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
 void Script::set_debug_positions(const Array& value) const {
-  raw_ptr()->set_debug_positions(value.raw());
+  untag()->set_debug_positions(value.ptr());
 }
 
 TypedDataPtr Script::line_starts() const {
-  return raw_ptr()->line_starts();
+  return untag()->line_starts();
 }
 
 ArrayPtr Script::debug_positions() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  Array& debug_positions_array = Array::Handle(raw_ptr()->debug_positions());
+  Array& debug_positions_array = Array::Handle(untag()->debug_positions());
   if (debug_positions_array.IsNull()) {
     // This is created lazily. Now we need it.
     kernel::CollectTokenPositionsFor(*this);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
-  return raw_ptr()->debug_positions();
+  return untag()->debug_positions();
 }
 
-void Script::set_flags(uint8_t value) const {
-  StoreNonPointer(&raw_ptr()->flags_, value);
-}
-
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void Script::SetLazyLookupSourceAndLineStarts(bool value) const {
-  set_flags(ScriptLayout::LazyLookupSourceAndLineStartsBit::update(
-      value, raw_ptr()->flags_));
+  StoreNonPointer(&untag()->flags_and_max_position_,
+                  UntaggedScript::LazyLookupSourceAndLineStartsBit::update(
+                      value, untag()->flags_and_max_position_));
 }
 
 bool Script::IsLazyLookupSourceAndLineStarts() const {
-  return ScriptLayout::LazyLookupSourceAndLineStartsBit::decode(
-      raw_ptr()->flags_);
+  return UntaggedScript::LazyLookupSourceAndLineStartsBit::decode(
+      untag()->flags_and_max_position_);
 }
 
+bool Script::HasCachedMaxPosition() const {
+  return UntaggedScript::HasCachedMaxPositionBit::decode(
+      untag()->flags_and_max_position_);
+}
+
+void Script::SetHasCachedMaxPosition(bool value) const {
+  StoreNonPointer(&untag()->flags_and_max_position_,
+                  UntaggedScript::HasCachedMaxPositionBit::update(
+                      value, untag()->flags_and_max_position_));
+}
+
+void Script::SetCachedMaxPosition(intptr_t value) const {
+  StoreNonPointer(&untag()->flags_and_max_position_,
+                  UntaggedScript::CachedMaxPositionBitField::update(
+                      value, untag()->flags_and_max_position_));
+}
+#endif
+
 void Script::set_load_timestamp(int64_t value) const {
-  StoreNonPointer(&raw_ptr()->load_timestamp_, value);
+  StoreNonPointer(&untag()->load_timestamp_, value);
 }
 
 void Script::SetLocationOffset(intptr_t line_offset,
                                intptr_t col_offset) const {
   ASSERT(line_offset >= 0);
   ASSERT(col_offset >= 0);
-  StoreNonPointer(&raw_ptr()->line_offset_, line_offset);
-  StoreNonPointer(&raw_ptr()->col_offset_, col_offset);
+  StoreNonPointer(&untag()->line_offset_, line_offset);
+  StoreNonPointer(&untag()->col_offset_, col_offset);
 }
 
-// Specialized for AOT compilation, which does this lookup for every token
-// position that could be part of a stack trace.
-bool Script::GetTokenLocationUsingLineStarts(TokenPosition target_token_pos,
-                                             intptr_t* line,
-                                             intptr_t* column) const {
-#if defined(DART_PRECOMPILED_RUNTIME)
-  return false;
-#else
-  // Negative positions denote positions that do not correspond to Dart code.
-  if (target_token_pos.value() < 0) return false;
-
-  Zone* zone = Thread::Current()->zone();
-  TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
-  ASSERT(!line_starts_data.IsNull());
-
-  kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
-  line_starts_reader.LocationForPosition(target_token_pos.value(), line,
-                                         column);
-  // The line and column numbers returned are ordinals, so we shouldn't get 0.
-  ASSERT(*line > 0);
-  ASSERT(*column > 0);
-  return true;
-#endif
+bool Script::IsValidTokenPosition(TokenPosition token_pos) const {
+  const TokenPosition& max_position = MaxPosition();
+  // We may end up with scripts that have the empty string as a source file
+  // in testing and the like, so allow any token position when the max position
+  // is 0 as well as when it is kNoSource.
+  return !max_position.IsReal() || !token_pos.IsReal() ||
+         max_position.Pos() == 0 || token_pos <= max_position;
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -11259,78 +11491,79 @@
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-void Script::GetTokenLocation(TokenPosition token_pos,
+bool Script::GetTokenLocation(const TokenPosition& token_pos,
                               intptr_t* line,
-                              intptr_t* column,
-                              intptr_t* token_len) const {
-  ASSERT(line != NULL);
-  Zone* zone = Thread::Current()->zone();
+                              intptr_t* column) const {
+  ASSERT(line != nullptr);
+#if defined(DART_PRECOMPILED_RUNTIME)
+  // Scripts in the AOT snapshot do not have a line starts array.
+  return false;
+#else
+  if (!token_pos.IsReal()) return false;
 
+  auto const zone = Thread::Current()->zone();
   LookupSourceAndLineStarts(zone);
-  if (line_starts() == TypedData::null()) {
-    // Scripts in the AOT snapshot do not have a line starts array.
-    *line = -1;
-    if (column != NULL) {
-      *column = -1;
-    }
-    if (token_len != NULL) {
-      *token_len = 1;
-    }
-    return;
-  }
-#if !defined(DART_PRECOMPILED_RUNTIME)
   const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
+  if (line_starts_data.IsNull()) return false;
   kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
-  line_starts_reader.LocationForPosition(token_pos.value(), line, column);
-  if (token_len != NULL) {
-    *token_len = 1;
-    // We don't explicitly save this data: Load the source
-    // and find it from there.
-    const String& source = String::Handle(zone, Source());
-    if (!source.IsNull()) {
-      intptr_t offset = token_pos.value();
-      if (offset < source.Length() && IsIdentStartChar(source.CharAt(offset))) {
-        for (intptr_t i = offset + 1;
-             i < source.Length() && IsIdentChar(source.CharAt(i)); ++i) {
-          ++*token_len;
-        }
-      }
-    }
-  }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  return line_starts_reader.LocationForPosition(token_pos.Pos(), line, column);
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
-void Script::TokenRangeAtLine(intptr_t line_number,
+intptr_t Script::GetTokenLength(const TokenPosition& token_pos) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  // Scripts in the AOT snapshot do not have their source.
+  return -1;
+#else
+  if (!HasSource() || !token_pos.IsReal()) return -1;
+  auto const zone = Thread::Current()->zone();
+  LookupSourceAndLineStarts(zone);
+  // We don't explicitly save this data: Load the source and find it from there.
+  const String& source = String::Handle(zone, Source());
+  const intptr_t start = token_pos.Pos();
+  if (start >= source.Length()) return -1;  // Can't determine token_len.
+  intptr_t end = start;
+  if (IsIdentStartChar(source.CharAt(end++))) {
+    for (; end < source.Length(); ++end) {
+      if (!IsIdentChar(source.CharAt(end))) break;
+    }
+  }
+  return end - start;
+#endif
+}
+
+bool Script::TokenRangeAtLine(intptr_t line_number,
                               TokenPosition* first_token_index,
                               TokenPosition* last_token_index) const {
-  ASSERT(first_token_index != NULL && last_token_index != NULL);
-  ASSERT(line_number > 0);
-
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
+  ASSERT(first_token_index != nullptr && last_token_index != nullptr);
+#if defined(DART_PRECOMPILED_RUNTIME)
+  // Scripts in the AOT snapshot do not have a line starts array.
+  return false;
+#else
+  // Line numbers are 1-indexed.
+  if (line_number <= 0) return false;
+  Zone* zone = Thread::Current()->zone();
   LookupSourceAndLineStarts(zone);
-  if (line_starts() == TypedData::null()) {
-    // Scripts in the AOT snapshot do not have a line starts array.
-    *first_token_index = TokenPosition::kNoSource;
-    *last_token_index = TokenPosition::kNoSource;
-    return;
+  const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
+  kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
+  if (!line_starts_reader.TokenRangeAtLine(line_number, first_token_index,
+                                           last_token_index)) {
+    return false;
   }
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  const String& source = String::Handle(zone, Source());
+#if defined(DEBUG)
   intptr_t source_length;
-  if (source.IsNull()) {
+  if (!HasSource()) {
     Smi& value = Smi::Handle(zone);
     const Array& debug_positions_array = Array::Handle(zone, debug_positions());
     value ^= debug_positions_array.At(debug_positions_array.Length() - 1);
     source_length = value.Value();
   } else {
+    const String& source = String::Handle(zone, Source());
     source_length = source.Length();
   }
-  const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
-  kernel::KernelLineStartsReader line_starts_reader(line_starts_data,
-                                                    Thread::Current()->zone());
-  line_starts_reader.TokenRangeAtLine(source_length, line_number,
-                                      first_token_index, last_token_index);
+  ASSERT(last_token_index->Serialize() <= source_length);
+#endif
+  return true;
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -11347,7 +11580,8 @@
                                        intptr_t column = 1,
                                        intptr_t column_offset = 0,
                                        intptr_t starting_index = 0) {
-  if (starting_index < 0 || line < 1 || column < 1) {
+  if (starting_index < 0 || line < 1 || column < 1 || line <= line_offset ||
+      (line == line_offset + 1 && column <= column_offset)) {
     return -1;
   }
   intptr_t len = src.Length();
@@ -11389,14 +11623,14 @@
 }
 
 StringPtr Script::GetLine(intptr_t line_number, Heap::Space space) const {
-  const String& src = String::Handle(Source());
-  if (src.IsNull()) {
-    return Symbols::OptimizedOut().raw();
+  if (!HasSource()) {
+    return Symbols::OptimizedOut().ptr();
   }
+  const String& src = String::Handle(Source());
   const intptr_t start =
       GetRelativeSourceIndex(src, line_number, line_offset());
   if (start < 0) {
-    return Symbols::Empty().raw();
+    return Symbols::Empty().ptr();
   }
   intptr_t end = start;
   for (; end < src.Length(); end++) {
@@ -11412,11 +11646,10 @@
                              intptr_t from_column,
                              intptr_t to_line,
                              intptr_t to_column) const {
-  const String& src = String::Handle(Source());
-  if (src.IsNull()) {
-    return Symbols::OptimizedOut().raw();
+  if (!HasSource()) {
+    return Symbols::OptimizedOut().ptr();
   }
-
+  const String& src = String::Handle(Source());
   const intptr_t start = GetRelativeSourceIndex(src, from_line, line_offset(),
                                                 from_column, col_offset());
   // Lines and columns are 1-based, so need to subtract one to get offsets.
@@ -11451,11 +11684,12 @@
       String::Handle(zone, Symbols::New(thread, resolved_url)));
   result.set_source(source);
   result.SetLocationOffset(0, 0);
-  result.set_flags(0);
+  NOT_IN_PRECOMPILED(result.SetLazyLookupSourceAndLineStarts(false));
+  NOT_IN_PRECOMPILED(result.SetHasCachedMaxPosition(false));
   result.set_kernel_script_index(0);
   result.set_load_timestamp(
       FLAG_remove_script_timestamps_for_test ? 0 : OS::GetCurrentTimeMillis());
-  return result.raw();
+  return result.ptr();
 }
 
 const char* Script::ToCString() const {
@@ -11466,17 +11700,17 @@
 LibraryPtr Script::FindLibrary() const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  auto isolate_group = thread->isolate_group();
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      zone, isolate_group->object_store()->libraries());
   Library& lib = Library::Handle(zone);
   Array& scripts = Array::Handle(zone);
   for (intptr_t i = 0; i < libs.Length(); i++) {
     lib ^= libs.At(i);
     scripts = lib.LoadedScripts();
     for (intptr_t j = 0; j < scripts.Length(); j++) {
-      if (scripts.At(j) == raw()) {
-        return lib.raw();
+      if (scripts.At(j) == ptr()) {
+        return lib.ptr();
       }
     }
   }
@@ -11523,12 +11757,12 @@
     int ix = next_ix_++;
     cls ^= array_.At(ix);
     MoveToNextClass();
-    return cls.raw();
+    return cls.ptr();
   }
   ASSERT(!toplevel_class_.IsNull());
-  cls = toplevel_class_.raw();
+  cls = toplevel_class_.ptr();
   toplevel_class_ = Class::null();
-  return cls.raw();
+  return cls.ptr();
 }
 
 void ClassDictionaryIterator::MoveToNextClass() {
@@ -11561,24 +11795,24 @@
   if (!Utils::IsUint(16, value)) {
     ReportTooManyImports(*this);
   }
-  StoreNonPointer(&raw_ptr()->num_imports_, value);
+  StoreNonPointer(&untag()->num_imports_, value);
 }
 
 void Library::set_name(const String& name) const {
   ASSERT(name.IsSymbol());
-  raw_ptr()->set_name(name.raw());
+  untag()->set_name(name.ptr());
 }
 
 void Library::set_url(const String& name) const {
-  raw_ptr()->set_url(name.raw());
+  untag()->set_url(name.ptr());
 }
 
 void Library::set_kernel_data(const ExternalTypedData& data) const {
-  raw_ptr()->set_kernel_data(data.raw());
+  untag()->set_kernel_data(data.ptr());
 }
 
 void Library::set_loading_unit(const LoadingUnit& value) const {
-  raw_ptr()->set_loading_unit(value.raw());
+  untag()->set_loading_unit(value.ptr());
 }
 
 void Library::SetName(const String& name) const {
@@ -11589,20 +11823,20 @@
 
 void Library::SetLoadInProgress() const {
   // Must not already be in the process of being loaded.
-  ASSERT(raw_ptr()->load_state_ <= LibraryLayout::kLoadRequested);
-  StoreNonPointer(&raw_ptr()->load_state_, LibraryLayout::kLoadInProgress);
+  ASSERT(untag()->load_state_ <= UntaggedLibrary::kLoadRequested);
+  StoreNonPointer(&untag()->load_state_, UntaggedLibrary::kLoadInProgress);
 }
 
 void Library::SetLoadRequested() const {
   // Must not be already loaded.
-  ASSERT(raw_ptr()->load_state_ == LibraryLayout::kAllocated);
-  StoreNonPointer(&raw_ptr()->load_state_, LibraryLayout::kLoadRequested);
+  ASSERT(untag()->load_state_ == UntaggedLibrary::kAllocated);
+  StoreNonPointer(&untag()->load_state_, UntaggedLibrary::kLoadRequested);
 }
 
 void Library::SetLoaded() const {
   // Should not be already loaded or just allocated.
   ASSERT(LoadInProgress() || LoadRequested());
-  StoreNonPointer(&raw_ptr()->load_state_, LibraryLayout::kLoaded);
+  StoreNonPointer(&untag()->load_state_, UntaggedLibrary::kLoaded);
 }
 
 void Library::AddMetadata(const Object& declaration,
@@ -11621,7 +11855,7 @@
 
 ObjectPtr Library::GetMetadata(const Object& declaration) const {
 #if defined(DART_PRECOMPILED_RUNTIME)
-  return Object::empty_array().raw();
+  return Object::empty_array().ptr();
 #else
   RELEASE_ASSERT(declaration.IsClass() || declaration.IsField() ||
                  declaration.IsFunction() || declaration.IsLibrary() ||
@@ -11647,12 +11881,12 @@
   }
   if (value.IsNull()) {
     // There is no metadata for this object.
-    return Object::empty_array().raw();
+    return Object::empty_array().ptr();
   }
   if (!value.IsSmi()) {
     // Metadata is already evaluated.
     ASSERT(value.IsArray());
-    return value.raw();
+    return value.ptr();
   }
   const auto& smi_value = Smi::Cast(value);
   intptr_t kernel_offset = smi_value.Value();
@@ -11663,17 +11897,17 @@
                 /* is_annotations_offset = */ declaration.IsLibrary() ||
                     declaration.IsNamespace()));
   if (evaluated_value.IsArray() || evaluated_value.IsNull()) {
-    ASSERT(evaluated_value.raw() != Object::empty_array().raw());
+    ASSERT(evaluated_value.ptr() != Object::empty_array().ptr());
     SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
     MetadataMap map(metadata());
-    if (map.GetOrNull(declaration) == smi_value.raw()) {
+    if (map.GetOrNull(declaration) == smi_value.ptr()) {
       map.UpdateOrInsert(declaration, evaluated_value);
     } else {
-      ASSERT(map.GetOrNull(declaration) == evaluated_value.raw());
+      ASSERT(map.GetOrNull(declaration) == evaluated_value.ptr());
     }
     set_metadata(map.Release());
   }
-  return evaluated_value.raw();
+  return evaluated_value.ptr();
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -11689,14 +11923,14 @@
 ObjectPtr Library::ResolveName(const String& name) const {
   Object& obj = Object::Handle();
   if (FLAG_use_lib_cache && LookupResolvedNamesCache(name, &obj)) {
-    return obj.raw();
+    return obj.ptr();
   }
   EnsureTopLevelClassIsFinalized();
   obj = LookupLocalObject(name);
   if (!obj.IsNull()) {
     // Names that are in this library's dictionary and are unmangled
     // are not cached. This reduces the size of the cache.
-    return obj.raw();
+    return obj.ptr();
   }
   String& accessor_name = String::Handle(Field::LookupGetterSymbol(name));
   if (!accessor_name.IsNull()) {
@@ -11712,7 +11946,7 @@
     }
   }
   AddToResolvedNamesCache(name, obj);
-  return obj.raw();
+  return obj.ptr();
 }
 
 class StringEqualsTraits {
@@ -11742,7 +11976,7 @@
 // ASSERT that 'resolved_names()' has not changed only in mutator.
 #if defined(DEBUG)
   if (Thread::Current()->IsMutatorThread()) {
-    ASSERT(cache.Release().raw() == resolved_names());
+    ASSERT(cache.Release().ptr() == resolved_names());
   } else {
     // Release must be called in debug mode.
     cache.Release();
@@ -11764,7 +11998,7 @@
   }
   ResolvedNamesMap cache(resolved_names());
   cache.UpdateOrInsert(name, obj);
-  raw_ptr()->set_resolved_names(cache.Release().raw());
+  untag()->set_resolved_names(cache.Release().ptr());
 }
 
 bool Library::LookupExportedNamesCache(const String& name, Object* obj) const {
@@ -11780,7 +12014,7 @@
 // do not ASSERT that 'exported_names()' has not changed.
 #if defined(DEBUG)
   if (Thread::Current()->IsMutatorThread()) {
-    ASSERT(cache.Release().raw() == exported_names());
+    ASSERT(cache.Release().ptr() == exported_names());
   } else {
     // Release must be called in debug mode.
     cache.Release();
@@ -11799,7 +12033,7 @@
   }
   ResolvedNamesMap cache(exported_names());
   cache.UpdateOrInsert(name, obj);
-  raw_ptr()->set_exported_names(cache.Release().raw());
+  untag()->set_exported_names(cache.Release().ptr());
 }
 
 void Library::InvalidateResolvedName(const String& name) const {
@@ -11817,7 +12051,7 @@
   // caches that contain an entry for this name. If the name was previously
   // looked up but could not be resolved, the cache contains a null entry.
   GrowableObjectArray& libs = GrowableObjectArray::Handle(
-      zone, thread->isolate()->object_store()->libraries());
+      zone, thread->isolate_group()->object_store()->libraries());
   Library& lib = Library::Handle(zone);
   intptr_t num_libs = libs.Length();
   for (intptr_t i = 0; i < num_libs; i++) {
@@ -11831,7 +12065,7 @@
 // Invalidate all exported names caches in the isolate.
 void Library::InvalidateExportedNamesCaches() {
   GrowableObjectArray& libs = GrowableObjectArray::Handle(
-      Isolate::Current()->object_store()->libraries());
+      IsolateGroup::Current()->object_store()->libraries());
   Library& lib = Library::Handle();
   intptr_t num_libs = libs.Length();
   for (intptr_t i = 0; i < num_libs; i++) {
@@ -11872,7 +12106,7 @@
   new_entry = Smi::New(used);
   new_dict.SetAt(new_dict_size, new_entry);
   // Remember the new dictionary now.
-  raw_ptr()->set_dictionary(new_dict.raw());
+  untag()->set_dictionary(new_dict.ptr());
 }
 
 void Library::AddObject(const Object& obj, const String& name) const {
@@ -11908,7 +12142,7 @@
 
   // Invalidate the cache of loaded scripts.
   if (loaded_scripts() != Array::null()) {
-    raw_ptr()->set_loaded_scripts(Array::null());
+    untag()->set_loaded_scripts(Array::null());
   }
 }
 
@@ -11926,7 +12160,7 @@
   }
   Object& obj = Object::Handle();
   if (FLAG_use_exp_cache && LookupExportedNamesCache(name, &obj)) {
-    return obj.raw();
+    return obj.ptr();
   }
 
   const intptr_t lib_id = this->index();
@@ -11951,7 +12185,7 @@
   if (FLAG_use_exp_cache && !in_cycle && !Compiler::IsBackgroundCompilation()) {
     AddToExportedNamesCache(name, obj);
   }
-  return obj.raw();
+  return obj.ptr();
 }
 
 ObjectPtr Library::LookupEntry(const String& name, intptr_t* index) const {
@@ -11972,7 +12206,7 @@
     entry_name = entry.DictionaryName();
     ASSERT(!entry_name.IsNull());
     if (entry_name.Equals(name)) {
-      return entry.raw();
+      return entry.ptr();
     }
     *index = (*index + 1) % dict_size;
     entry = dict.At(*index);
@@ -11998,7 +12232,7 @@
 
   for (int i = 0; i < scripts.Length(); i++) {
     script_obj ^= scripts.At(i);
-    if (script_obj.raw() == candidate.raw()) {
+    if (script_obj.ptr() == candidate.ptr()) {
       // We already have a reference to this script.
       return;
     }
@@ -12045,7 +12279,7 @@
         owner_script = Class::Cast(entry).script();
       } else {
         ASSERT(entry.IsScript());
-        owner_script = Script::Cast(entry).raw();
+        owner_script = Script::Cast(entry).ptr();
       }
       AddScriptIfUnique(scripts, owner_script);
     }
@@ -12070,7 +12304,7 @@
 
     // Create the array of scripts and cache it in loaded_scripts_.
     const Array& scripts_array = Array::Handle(Array::MakeFixedLength(scripts));
-    raw_ptr()->set_loaded_scripts(scripts_array.raw());
+    untag()->set_loaded_scripts(scripts_array.ptr());
   }
   return loaded_scripts();
 }
@@ -12098,14 +12332,14 @@
     }
     const intptr_t start_idx = script_url.Length() - url_length;
     if ((start_idx == 0) && url.Equals(script_url)) {
-      return script.raw();
+      return script.ptr();
     } else if (start_idx > 0) {
       // If we do a suffix match, only match if the partial path
       // starts at or immediately after the path separator.
       if (((url.CharAt(0) == '/') ||
            (script_url.CharAt(start_idx - 1) == '/')) &&
           url.Equals(script_url, start_idx, url_length)) {
-        return script.raw();
+        return script.ptr();
       }
     }
   }
@@ -12138,7 +12372,7 @@
   EnsureTopLevelClassIsFinalized();
   const Object& result = Object::Handle(LookupEntry(name, &index));
   if (!result.IsNull() && !result.IsLibraryPrefix()) {
-    return result.raw();
+    return result.ptr();
   }
   return LookupReExport(name);
 }
@@ -12147,7 +12381,7 @@
   EnsureTopLevelClassIsFinalized();
   Object& obj = Object::Handle(LookupObjectAllowPrivate(name));
   if (obj.IsField()) {
-    return Field::Cast(obj).raw();
+    return Field::Cast(obj).ptr();
   }
   return Field::null();
 }
@@ -12156,7 +12390,7 @@
   EnsureTopLevelClassIsFinalized();
   Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
   if (obj.IsField()) {
-    return Field::Cast(obj).raw();
+    return Field::Cast(obj).ptr();
   }
   return Field::null();
 }
@@ -12165,7 +12399,7 @@
   EnsureTopLevelClassIsFinalized();
   Object& obj = Object::Handle(LookupObjectAllowPrivate(name));
   if (obj.IsFunction()) {
-    return Function::Cast(obj).raw();
+    return Function::Cast(obj).ptr();
   }
   return Function::null();
 }
@@ -12174,7 +12408,7 @@
   EnsureTopLevelClassIsFinalized();
   Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
   if (obj.IsFunction()) {
-    return Function::Cast(obj).raw();
+    return Function::Cast(obj).ptr();
   }
   return Function::null();
 }
@@ -12188,14 +12422,14 @@
     String& private_name = String::Handle(zone, PrivateName(name));
     obj = LookupLocalObject(private_name);
   }
-  return obj.raw();
+  return obj.ptr();
 }
 
 ObjectPtr Library::LookupObjectAllowPrivate(const String& name) const {
   // First check if name is found in the local scope of the library.
   Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
   if (!obj.IsNull()) {
-    return obj.raw();
+    return obj.ptr();
   }
 
   // Do not look up private names in imported libraries.
@@ -12222,7 +12456,7 @@
     if (!obj.IsNull()) {
       import_lib = import.target();
       import_lib_url = import_lib.url();
-      if (found_obj.raw() != obj.raw()) {
+      if (found_obj.ptr() != obj.ptr()) {
         if (first_import_lib_url.IsNull() ||
             first_import_lib_url.StartsWith(Symbols::DartScheme())) {
           // This is the first object we found, or the
@@ -12230,7 +12464,7 @@
           // system library. The newly found object hides the one
           // from the Dart library.
           first_import_lib_url = import_lib.url();
-          found_obj = obj.raw();
+          found_obj = obj.ptr();
           found_obj_name = obj.DictionaryName();
         } else if (import_lib_url.StartsWith(Symbols::DartScheme())) {
           // The newly found object is exported from a Dart system
@@ -12242,7 +12476,7 @@
           // the first object we found is a setter. Replace the first
           // object with the one we just found.
           first_import_lib_url = import_lib.url();
-          found_obj = obj.raw();
+          found_obj = obj.ptr();
           found_obj_name = found_obj.DictionaryName();
         } else {
           // We found two different objects with the same name.
@@ -12265,7 +12499,7 @@
       }
     }
   }
-  return found_obj.raw();
+  return found_obj.ptr();
 }
 
 ClassPtr Library::LookupClass(const String& name) const {
@@ -12274,7 +12508,7 @@
     obj = LookupImportedObject(name);
   }
   if (obj.IsClass()) {
-    return Class::Cast(obj).raw();
+    return Class::Cast(obj).ptr();
   }
   return Class::null();
 }
@@ -12282,7 +12516,7 @@
 ClassPtr Library::LookupLocalClass(const String& name) const {
   Object& obj = Object::Handle(LookupLocalObject(name));
   if (obj.IsClass()) {
-    return Class::Cast(obj).raw();
+    return Class::Cast(obj).ptr();
   }
   return Class::null();
 }
@@ -12293,7 +12527,7 @@
   Zone* zone = Thread::Current()->zone();
   const Class& cls = Class::Handle(zone, LookupClass(name));
   if (!cls.IsNull()) {
-    return cls.raw();
+    return cls.ptr();
   }
 
   // Now try to lookup the class using its private name, but only in
@@ -12302,7 +12536,7 @@
     String& private_name = String::Handle(zone, PrivateName(name));
     const Object& obj = Object::Handle(LookupLocalObject(private_name));
     if (obj.IsClass()) {
-      return Class::Cast(obj).raw();
+      return Class::Cast(obj).ptr();
     }
   }
   return Class::null();
@@ -12320,7 +12554,7 @@
       cls_name = Class::Cast(entry).Name();
       // Warning: comparison is not symmetric.
       if (String::EqualsIgnoringPrivateKey(cls_name, name)) {
-        return Class::Cast(entry).raw();
+        return Class::Cast(entry).ptr();
       }
     }
   }
@@ -12330,25 +12564,25 @@
 LibraryPrefixPtr Library::LookupLocalLibraryPrefix(const String& name) const {
   const Object& obj = Object::Handle(LookupLocalObject(name));
   if (obj.IsLibraryPrefix()) {
-    return LibraryPrefix::Cast(obj).raw();
+    return LibraryPrefix::Cast(obj).ptr();
   }
   return LibraryPrefix::null();
 }
 
 void Library::set_toplevel_class(const Class& value) const {
-  ASSERT(raw_ptr()->toplevel_class() == Class::null());
-  raw_ptr()->set_toplevel_class(value.raw());
+  ASSERT(untag()->toplevel_class() == Class::null());
+  untag()->set_toplevel_class(value.ptr());
 }
 
 void Library::set_dependencies(const Array& deps) const {
-  raw_ptr()->set_dependencies(deps.raw());
+  untag()->set_dependencies(deps.ptr());
 }
 
 void Library::set_metadata(const Array& value) const {
-  if (raw_ptr()->metadata() != value.raw()) {
+  if (untag()->metadata() != value.ptr()) {
     DEBUG_ASSERT(
         IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
-    raw_ptr()->set_metadata(value.raw());
+    untag()->set_metadata(value.ptr());
   }
 }
 
@@ -12372,7 +12606,7 @@
   // We need to preserve the "dart-ext:" imports because they are used by
   // Loader::ReloadNativeExtensions().
   intptr_t native_import_count = 0;
-  Array& imports = Array::Handle(raw_ptr()->imports());
+  Array& imports = Array::Handle(untag()->imports());
   Namespace& ns = Namespace::Handle();
   Library& lib = Library::Handle();
   String& url = String::Handle();
@@ -12397,13 +12631,13 @@
     }
   }
 
-  raw_ptr()->set_imports(new_imports.raw());
-  raw_ptr()->set_exports(Object::empty_array().raw());
-  StoreNonPointer(&raw_ptr()->num_imports_, 0);
-  raw_ptr()->set_resolved_names(Array::null());
-  raw_ptr()->set_exported_names(Array::null());
-  raw_ptr()->set_loaded_scripts(Array::null());
-  raw_ptr()->set_dependencies(Array::null());
+  untag()->set_imports(new_imports.ptr());
+  untag()->set_exports(Object::empty_array().ptr());
+  StoreNonPointer(&untag()->num_imports_, 0);
+  untag()->set_resolved_names(Array::null());
+  untag()->set_exported_names(Array::null());
+  untag()->set_loaded_scripts(Array::null());
+  untag()->set_dependencies(Array::null());
 }
 
 void Library::AddImport(const Namespace& ns) const {
@@ -12412,7 +12646,7 @@
   if (num_imports() == capacity) {
     capacity = capacity + kImportsCapacityIncrement + (capacity >> 2);
     imports = Array::Grow(imports, capacity);
-    raw_ptr()->set_imports(imports.raw());
+    untag()->set_imports(imports.ptr());
   }
   intptr_t index = num_imports();
   imports.SetAt(index, ns);
@@ -12422,7 +12656,7 @@
 // Convenience function to determine whether the export list is
 // non-empty.
 bool Library::HasExports() const {
-  return exports() != Object::empty_array().raw();
+  return exports() != Object::empty_array().ptr();
 }
 
 // We add one namespace at a time to the exports array and don't
@@ -12432,7 +12666,7 @@
   Array& exports = Array::Handle(this->exports());
   intptr_t num_exports = exports.Length();
   exports = Array::Grow(exports, num_exports + 1);
-  raw_ptr()->set_exports(exports.raw());
+  untag()->set_exports(exports.ptr());
   exports.SetAt(num_exports, ns);
 }
 
@@ -12440,7 +12674,7 @@
   const Array& dict = Array::Handle(Array::New(initial_size + 1, Heap::kOld));
   // The last element of the dictionary specifies the number of in use slots.
   dict.SetAt(initial_size, Object::smi_zero());
-  return dict.raw();
+  return dict.ptr();
 }
 
 void Library::InitResolvedNamesCache() const {
@@ -12449,12 +12683,12 @@
   REUSABLE_FUNCTION_HANDLESCOPE(thread);
   Array& cache = thread->ArrayHandle();
   cache = HashTables::New<ResolvedNamesMap>(64);
-  raw_ptr()->set_resolved_names(cache.raw());
+  untag()->set_resolved_names(cache.ptr());
 }
 
 void Library::ClearResolvedNamesCache() const {
   ASSERT(Thread::Current()->IsMutatorThread());
-  raw_ptr()->set_resolved_names(Array::null());
+  untag()->set_resolved_names(Array::null());
 }
 
 void Library::InitExportedNamesCache() const {
@@ -12463,11 +12697,11 @@
   REUSABLE_FUNCTION_HANDLESCOPE(thread);
   Array& cache = thread->ArrayHandle();
   cache = HashTables::New<ResolvedNamesMap>(16);
-  raw_ptr()->set_exported_names(cache.raw());
+  untag()->set_exported_names(cache.ptr());
 }
 
 void Library::ClearExportedNamesCache() const {
-  raw_ptr()->set_exported_names(Array::null());
+  untag()->set_exported_names(Array::null());
 }
 
 void Library::InitClassDictionary() const {
@@ -12478,14 +12712,14 @@
   // TODO(iposva): Find reasonable initial size.
   const int kInitialElementCount = 16;
   dictionary = NewDictionary(kInitialElementCount);
-  raw_ptr()->set_dictionary(dictionary.raw());
+  untag()->set_dictionary(dictionary.ptr());
 }
 
 void Library::InitImportList() const {
   const Array& imports =
       Array::Handle(Array::New(kInitialImportsCapacity, Heap::kOld));
-  raw_ptr()->set_imports(imports.raw());
-  StoreNonPointer(&raw_ptr()->num_imports_, 0);
+  untag()->set_imports(imports.ptr());
+  StoreNonPointer(&untag()->num_imports_, 0);
 }
 
 LibraryPtr Library::New() {
@@ -12503,21 +12737,21 @@
   url.Hash();
   const bool dart_scheme = url.StartsWith(Symbols::DartScheme());
   const Library& result = Library::Handle(zone, Library::New());
-  result.raw_ptr()->set_name(Symbols::Empty().raw());
-  result.raw_ptr()->set_url(url.raw());
-  result.raw_ptr()->set_resolved_names(Array::null());
-  result.raw_ptr()->set_exported_names(Array::null());
-  result.raw_ptr()->set_dictionary(Object::empty_array().raw());
+  result.untag()->set_name(Symbols::Empty().ptr());
+  result.untag()->set_url(url.ptr());
+  result.untag()->set_resolved_names(Array::null());
+  result.untag()->set_exported_names(Array::null());
+  result.untag()->set_dictionary(Object::empty_array().ptr());
   Array& array = Array::Handle(zone);
   array = HashTables::New<MetadataMap>(4, Heap::kOld);
-  result.raw_ptr()->set_metadata(array.raw());
-  result.raw_ptr()->set_toplevel_class(Class::null());
+  result.untag()->set_metadata(array.ptr());
+  result.untag()->set_toplevel_class(Class::null());
   GrowableObjectArray& list = GrowableObjectArray::Handle(zone);
   list = GrowableObjectArray::New(Object::empty_array(), Heap::kOld);
-  result.raw_ptr()->set_used_scripts(list.raw());
-  result.raw_ptr()->set_imports(Object::empty_array().raw());
-  result.raw_ptr()->set_exports(Object::empty_array().raw());
-  result.raw_ptr()->set_loaded_scripts(Array::null());
+  result.untag()->set_used_scripts(list.ptr());
+  result.untag()->set_imports(Object::empty_array().ptr());
+  result.untag()->set_exports(Object::empty_array().ptr());
+  result.untag()->set_loaded_scripts(Array::null());
   result.set_native_entry_resolver(NULL);
   result.set_native_entry_symbol_resolver(NULL);
   result.set_flags(0);
@@ -12533,9 +12767,9 @@
   }
   result.set_is_dart_scheme(dart_scheme);
   NOT_IN_PRECOMPILED(result.set_kernel_offset(0));
-  result.StoreNonPointer(&result.raw_ptr()->load_state_,
-                         LibraryLayout::kAllocated);
-  result.StoreNonPointer(&result.raw_ptr()->index_, -1);
+  result.StoreNonPointer(&result.untag()->load_state_,
+                         UntaggedLibrary::kAllocated);
+  result.StoreNonPointer(&result.untag()->index_, -1);
   result.InitClassDictionary();
   result.InitImportList();
   result.AllocatePrivateKey();
@@ -12547,7 +12781,7 @@
                                                Object::null_array(), result));
     result.AddImport(ns);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 LibraryPtr Library::New(const String& url) {
@@ -12555,10 +12789,10 @@
 }
 
 void Library::set_flags(uint8_t flags) const {
-  StoreNonPointer(&raw_ptr()->flags_, flags);
+  StoreNonPointer(&untag()->flags_, flags);
 }
 
-void Library::InitCoreLibrary(Isolate* isolate) {
+void Library::InitCoreLibrary(IsolateGroup* isolate_group) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const String& core_lib_url = Symbols::DartCore();
@@ -12566,8 +12800,9 @@
       Library::Handle(zone, Library::NewLibraryHelper(core_lib_url, false));
   core_lib.SetLoadRequested();
   core_lib.Register(thread);
-  isolate->object_store()->set_bootstrap_library(ObjectStore::kCore, core_lib);
-  isolate->object_store()->set_root_library(Library::Handle());
+  isolate_group->object_store()->set_bootstrap_library(ObjectStore::kCore,
+                                                       core_lib);
+  isolate_group->object_store()->set_root_library(Library::Handle());
 }
 
 // Invoke the function, or noSuchMethod if it is null.
@@ -12623,7 +12858,7 @@
         String::Handle(Field::GetterName(getter_name));
     obj = LookupLocalOrReExportObject(internal_getter_name);
     if (obj.IsFunction()) {
-      getter = Function::Cast(obj).raw();
+      getter = Function::Cast(obj).ptr();
       if (check_is_entrypoint) {
         CHECK_ERROR(getter.VerifyCallEntryPoint());
       }
@@ -12634,7 +12869,7 @@
       // exception of "main".
       if (obj.IsFunction() && check_is_entrypoint) {
         if (!getter_name.Equals(String::Handle(String::New("main"))) ||
-            raw() != Isolate::Current()->object_store()->root_library()) {
+            ptr() != IsolateGroup::Current()->object_store()->root_library()) {
           CHECK_ERROR(Function::Cast(obj).VerifyClosurizedEntryPoint());
         }
       }
@@ -12658,7 +12893,7 @@
     // Fall through case: Indicate that we didn't find any function or field
     // using a special null instance. This is different from a field being null.
     // Callers make sure that this null does not leak into Dartland.
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
 
   // Invoke the getter and return the result.
@@ -12696,13 +12931,13 @@
           InvocationMirror::kTopLevel, InvocationMirror::kSetter);
     }
     field.SetStaticValue(value);
-    return value.raw();
+    return value.ptr();
   }
 
   Function& setter = Function::Handle();
   obj = LookupLocalOrReExportObject(internal_setter_name);
   if (obj.IsFunction()) {
-    setter ^= obj.raw();
+    setter ^= obj.ptr();
   }
 
   if (!setter.IsNull() && check_is_entrypoint) {
@@ -12749,7 +12984,7 @@
   auto& result =
       Object::Handle(zone, LookupLocalOrReExportObject(function_name));
   if (result.IsFunction()) {
-    function ^= result.raw();
+    function ^= result.ptr();
   }
 
   if (!function.IsNull() && check_is_entrypoint) {
@@ -12761,7 +12996,7 @@
     const Object& getter_result = Object::Handle(
         zone, InvokeGetter(function_name, false, respect_reflectable,
                            check_is_entrypoint));
-    if (getter_result.raw() != Object::sentinel().raw()) {
+    if (getter_result.ptr() != Object::sentinel().ptr()) {
       if (check_is_entrypoint) {
         CHECK_ERROR(EntryPointFieldInvocationError(function_name));
       }
@@ -12807,7 +13042,8 @@
       arguments, type_arguments);
 }
 
-void Library::InitNativeWrappersLibrary(Isolate* isolate, bool is_kernel) {
+void Library::InitNativeWrappersLibrary(IsolateGroup* isolate_group,
+                                        bool is_kernel) {
   static const int kNumNativeWrappersClasses = 4;
   COMPILE_ASSERT((kNumNativeWrappersClasses > 0) &&
                  (kNumNativeWrappersClasses < 10));
@@ -12821,7 +13057,7 @@
   native_flds_lib.SetLoadRequested();
   native_flds_lib.Register(thread);
   native_flds_lib.SetLoadInProgress();
-  isolate->object_store()->set_native_wrappers_library(native_flds_lib);
+  isolate_group->object_store()->set_native_wrappers_library(native_flds_lib);
   static const char* const kNativeWrappersClass = "NativeFieldWrapperClass";
   static const int kNameLength = 25;
   ASSERT(kNameLength == (strlen(kNativeWrappersClass) + 1 + 1));
@@ -12857,7 +13093,7 @@
 
   static uword Hash(const Object& key) { return String::Cast(key).Hash(); }
 
-  static ObjectPtr NewKey(const String& str) { return str.raw(); }
+  static ObjectPtr NewKey(const String& str) { return str.ptr(); }
 };
 typedef UnorderedHashMap<LibraryLookupTraits> LibraryLookupMap;
 
@@ -12890,9 +13126,9 @@
       zone, loader.LoadExpressionEvaluationFunction(library_url, klass));
   kernel_pgm.reset();
 
-  if (result.IsError()) return result.raw();
+  if (result.IsError()) return result.ptr();
 
-  const auto& callee = Function::CheckedHandle(zone, result.raw());
+  const auto& callee = Function::CheckedHandle(zone, result.ptr());
 
   // type_arguments is null if all type arguments are dynamic.
   if (type_definitions.Length() == 0 || type_arguments.IsNull()) {
@@ -12914,15 +13150,14 @@
     result = DartEntry::InvokeFunction(callee, real_arguments, args_desc);
   }
 
-  return result.raw();
+  return result.ptr();
 #endif
 }
 
 // Returns library with given url in current isolate, or NULL.
 LibraryPtr Library::LookupLibrary(Thread* thread, const String& url) {
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  ObjectStore* object_store = isolate->object_store();
+  ObjectStore* object_store = thread->isolate_group()->object_store();
 
   // Make sure the URL string has an associated hash code
   // to speed up the repeated equality checks.
@@ -12935,9 +13170,9 @@
   } else {
     LibraryLookupMap map(object_store->libraries_map());
     lib ^= map.GetOrNull(url);
-    ASSERT(map.Release().raw() == object_store->libraries_map());
+    ASSERT(map.Release().ptr() == object_store->libraries_map());
   }
-  return lib.raw();
+  return lib.ptr();
 }
 
 bool Library::IsPrivate(const String& name) {
@@ -12959,17 +13194,18 @@
 void Library::AllocatePrivateKey() const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
 
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
-  if (isolate->group()->IsReloading()) {
+  if (isolate_group->IsReloading()) {
     // When reloading, we need to make sure we use the original private key
     // if this library previously existed.
-    IsolateReloadContext* reload_context = isolate->reload_context();
+    ProgramReloadContext* program_reload_context =
+        thread->isolate()->program_reload_context();
     const String& original_key =
-        String::Handle(reload_context->FindLibraryPrivateKey(*this));
+        String::Handle(program_reload_context->FindLibraryPrivateKey(*this));
     if (!original_key.IsNull()) {
-      raw_ptr()->set_private_key(original_key.raw());
+      untag()->set_private_key(original_key.ptr());
       return;
     }
   }
@@ -12981,8 +13217,8 @@
   const String& url = String::Handle(zone, this->url());
   intptr_t hash_value = url.Hash() & hash_mask;
 
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      zone, isolate_group->object_store()->libraries());
   intptr_t sequence_value = libs.Length();
 
   char private_key[32];
@@ -12991,7 +13227,7 @@
   const String& key =
       String::Handle(zone, String::New(private_key, Heap::kOld));
   key.Hash();  // This string may end up in the VM isolate.
-  raw_ptr()->set_private_key(key.raw());
+  untag()->set_private_key(key.ptr());
 }
 
 const String& Library::PrivateCoreLibName(const String& member) {
@@ -13013,7 +13249,7 @@
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
-  String& name = String::Handle(zone, class_name.raw());
+  String& name = String::Handle(zone, class_name.ptr());
   if (class_name.CharAt(0) == kPrivateIdentifierStart) {
     // Private identifiers are mangled on a per library basis.
     name = Symbols::FromConcat(thread, name,
@@ -13030,31 +13266,31 @@
   ASSERT(IsPrivate(name));
   // ASSERT(strchr(name, '@') == NULL);
   String& str = String::Handle(zone);
-  str = name.raw();
+  str = name.ptr();
   str = Symbols::FromConcat(thread, str,
                             String::Handle(zone, this->private_key()));
-  return str.raw();
+  return str.ptr();
 }
 
 LibraryPtr Library::GetLibrary(intptr_t index) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  auto isolate_group = thread->isolate_group();
+  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+      zone, isolate_group->object_store()->libraries());
   ASSERT(!libs.IsNull());
   if ((0 <= index) && (index < libs.Length())) {
     Library& lib = Library::Handle(zone);
     lib ^= libs.At(index);
-    return lib.raw();
+    return lib.ptr();
   }
   return Library::null();
 }
 
 void Library::Register(Thread* thread) const {
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  ObjectStore* object_store = isolate->object_store();
+  auto isolate_group = thread->isolate_group();
+  ObjectStore* object_store = isolate_group->object_store();
 
   // A library is "registered" in two places:
   // - A growable array mapping from index to library.
@@ -13082,7 +13318,7 @@
 void Library::RegisterLibraries(Thread* thread,
                                 const GrowableObjectArray& libs) {
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   Library& lib = Library::Handle(zone);
   String& lib_url = String::Handle(zone);
 
@@ -13095,66 +13331,66 @@
     map.InsertNewOrGetValue(lib_url, lib);
   }
   // Now remember these in the isolate's object store.
-  isolate->object_store()->set_libraries(libs);
-  isolate->object_store()->set_libraries_map(map.Release());
+  isolate_group->object_store()->set_libraries(libs);
+  isolate_group->object_store()->set_libraries_map(map.Release());
 }
 
 LibraryPtr Library::AsyncLibrary() {
-  return Isolate::Current()->object_store()->async_library();
+  return IsolateGroup::Current()->object_store()->async_library();
 }
 
 LibraryPtr Library::ConvertLibrary() {
-  return Isolate::Current()->object_store()->convert_library();
+  return IsolateGroup::Current()->object_store()->convert_library();
 }
 
 LibraryPtr Library::CoreLibrary() {
-  return Isolate::Current()->object_store()->core_library();
+  return IsolateGroup::Current()->object_store()->core_library();
 }
 
 LibraryPtr Library::CollectionLibrary() {
-  return Isolate::Current()->object_store()->collection_library();
+  return IsolateGroup::Current()->object_store()->collection_library();
 }
 
 LibraryPtr Library::DeveloperLibrary() {
-  return Isolate::Current()->object_store()->developer_library();
+  return IsolateGroup::Current()->object_store()->developer_library();
 }
 
 LibraryPtr Library::FfiLibrary() {
-  return Isolate::Current()->object_store()->ffi_library();
+  return IsolateGroup::Current()->object_store()->ffi_library();
 }
 
 LibraryPtr Library::InternalLibrary() {
-  return Isolate::Current()->object_store()->_internal_library();
+  return IsolateGroup::Current()->object_store()->_internal_library();
 }
 
 LibraryPtr Library::IsolateLibrary() {
-  return Isolate::Current()->object_store()->isolate_library();
+  return IsolateGroup::Current()->object_store()->isolate_library();
 }
 
 LibraryPtr Library::MathLibrary() {
-  return Isolate::Current()->object_store()->math_library();
+  return IsolateGroup::Current()->object_store()->math_library();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 LibraryPtr Library::MirrorsLibrary() {
-  return Isolate::Current()->object_store()->mirrors_library();
+  return IsolateGroup::Current()->object_store()->mirrors_library();
 }
 #endif
 
 LibraryPtr Library::NativeWrappersLibrary() {
-  return Isolate::Current()->object_store()->native_wrappers_library();
+  return IsolateGroup::Current()->object_store()->native_wrappers_library();
 }
 
 LibraryPtr Library::ProfilerLibrary() {
-  return Isolate::Current()->object_store()->profiler_library();
+  return IsolateGroup::Current()->object_store()->profiler_library();
 }
 
 LibraryPtr Library::TypedDataLibrary() {
-  return Isolate::Current()->object_store()->typed_data_library();
+  return IsolateGroup::Current()->object_store()->typed_data_library();
 }
 
 LibraryPtr Library::VMServiceLibrary() {
-  return Isolate::Current()->object_store()->_vmservice_library();
+  return IsolateGroup::Current()->object_store()->_vmservice_library();
 }
 
 const char* Library::ToCString() const {
@@ -13207,31 +13443,31 @@
   result.set_name(name);
   result.set_num_imports(0);
   result.set_importer(importer);
-  result.StoreNonPointer(&result.raw_ptr()->is_deferred_load_, deferred_load);
-  result.StoreNonPointer(&result.raw_ptr()->is_loaded_, !deferred_load);
+  result.StoreNonPointer(&result.untag()->is_deferred_load_, deferred_load);
+  result.StoreNonPointer(&result.untag()->is_loaded_, !deferred_load);
   result.set_imports(Array::Handle(Array::New(kInitialSize)));
   result.AddImport(import);
-  return result.raw();
+  return result.ptr();
 }
 
 void LibraryPrefix::set_name(const String& value) const {
   ASSERT(value.IsSymbol());
-  raw_ptr()->set_name(value.raw());
+  untag()->set_name(value.ptr());
 }
 
 void LibraryPrefix::set_imports(const Array& value) const {
-  raw_ptr()->set_imports(value.raw());
+  untag()->set_imports(value.ptr());
 }
 
 void LibraryPrefix::set_num_imports(intptr_t value) const {
   if (!Utils::IsUint(16, value)) {
     ReportTooManyImports(Library::Handle(importer()));
   }
-  StoreNonPointer(&raw_ptr()->num_imports_, value);
+  StoreNonPointer(&untag()->num_imports_, value);
 }
 
 void LibraryPrefix::set_importer(const Library& value) const {
-  raw_ptr()->set_importer(value.raw());
+  untag()->set_importer(value.ptr());
 }
 
 const char* LibraryPrefix::ToCString() const {
@@ -13345,7 +13581,7 @@
   if (obj.IsNull() || HidesName(name) || obj.IsLibraryPrefix()) {
     return Object::null();
   }
-  return obj.raw();
+  return obj.ptr();
 }
 
 NamespacePtr Namespace::New() {
@@ -13362,11 +13598,11 @@
   ASSERT(show_names.IsNull() || (show_names.Length() > 0));
   ASSERT(hide_names.IsNull() || (hide_names.Length() > 0));
   const Namespace& result = Namespace::Handle(Namespace::New());
-  result.raw_ptr()->set_target(target.raw());
-  result.raw_ptr()->set_show_names(show_names.raw());
-  result.raw_ptr()->set_hide_names(hide_names.raw());
-  result.raw_ptr()->set_owner(owner.raw());
-  return result.raw();
+  result.untag()->set_target(target.ptr());
+  result.untag()->set_show_names(show_names.ptr());
+  result.untag()->set_hide_names(hide_names.ptr());
+  result.untag()->set_owner(owner.ptr());
+  return result.ptr();
 }
 
 KernelProgramInfoPtr KernelProgramInfo::New() {
@@ -13390,18 +13626,18 @@
     const uint32_t binary_version) {
   const KernelProgramInfo& info =
       KernelProgramInfo::Handle(KernelProgramInfo::New());
-  info.raw_ptr()->set_string_offsets(string_offsets.raw());
-  info.raw_ptr()->set_string_data(string_data.raw());
-  info.raw_ptr()->set_canonical_names(canonical_names.raw());
-  info.raw_ptr()->set_metadata_payloads(metadata_payloads.raw());
-  info.raw_ptr()->set_metadata_mappings(metadata_mappings.raw());
-  info.raw_ptr()->set_scripts(scripts.raw());
-  info.raw_ptr()->set_constants_table(constants_table.raw());
-  info.raw_ptr()->set_libraries_cache(libraries_cache.raw());
-  info.raw_ptr()->set_classes_cache(classes_cache.raw());
-  info.raw_ptr()->set_retained_kernel_blob(retained_kernel_blob.raw());
+  info.untag()->set_string_offsets(string_offsets.ptr());
+  info.untag()->set_string_data(string_data.ptr());
+  info.untag()->set_canonical_names(canonical_names.ptr());
+  info.untag()->set_metadata_payloads(metadata_payloads.ptr());
+  info.untag()->set_metadata_mappings(metadata_mappings.ptr());
+  info.untag()->set_scripts(scripts.ptr());
+  info.untag()->set_constants_table(constants_table.ptr());
+  info.untag()->set_libraries_cache(libraries_cache.ptr());
+  info.untag()->set_classes_cache(classes_cache.ptr());
+  info.untag()->set_retained_kernel_blob(retained_kernel_blob.ptr());
   info.set_kernel_binary_version(binary_version);
-  return info.raw();
+  return info.ptr();
 }
 
 const char* KernelProgramInfo::ToCString() const {
@@ -13415,34 +13651,34 @@
 }
 
 void KernelProgramInfo::set_scripts(const Array& scripts) const {
-  raw_ptr()->set_scripts(scripts.raw());
+  untag()->set_scripts(scripts.ptr());
 }
 
 void KernelProgramInfo::set_constants(const Array& constants) const {
-  raw_ptr()->set_constants(constants.raw());
+  untag()->set_constants(constants.ptr());
 }
 
 void KernelProgramInfo::set_kernel_binary_version(uint32_t version) const {
-  StoreNonPointer(&raw_ptr()->kernel_binary_version_, version);
+  StoreNonPointer(&untag()->kernel_binary_version_, version);
 }
 
 void KernelProgramInfo::set_constants_table(
     const ExternalTypedData& value) const {
-  raw_ptr()->set_constants_table(value.raw());
+  untag()->set_constants_table(value.ptr());
 }
 
 void KernelProgramInfo::set_potential_natives(
     const GrowableObjectArray& candidates) const {
-  raw_ptr()->set_potential_natives(candidates.raw());
+  untag()->set_potential_natives(candidates.ptr());
 }
 
 void KernelProgramInfo::set_potential_pragma_functions(
     const GrowableObjectArray& candidates) const {
-  raw_ptr()->set_potential_pragma_functions(candidates.raw());
+  untag()->set_potential_pragma_functions(candidates.ptr());
 }
 
 void KernelProgramInfo::set_libraries_cache(const Array& cache) const {
-  raw_ptr()->set_libraries_cache(cache.raw());
+  untag()->set_libraries_cache(cache.ptr());
 }
 
 typedef UnorderedHashMap<SmiTraits> IntHashMap;
@@ -13466,7 +13702,7 @@
     result ^= table.GetOrNull(name_index);
     table.Release();
   }
-  return result.raw();
+  return result.ptr();
 }
 
 LibraryPtr KernelProgramInfo::InsertLibrary(Thread* thread,
@@ -13489,11 +13725,11 @@
     result ^= table.InsertOrGetValue(name_index, lib);
     set_libraries_cache(table.Release());
   }
-  return result.raw();
+  return result.ptr();
 }
 
 void KernelProgramInfo::set_classes_cache(const Array& cache) const {
-  raw_ptr()->set_classes_cache(cache.raw());
+  untag()->set_classes_cache(cache.ptr());
 }
 
 ClassPtr KernelProgramInfo::LookupClass(Thread* thread,
@@ -13515,7 +13751,7 @@
     result ^= table.GetOrNull(name_index);
     table.Release();
   }
-  return result.raw();
+  return result.ptr();
 }
 
 ClassPtr KernelProgramInfo::InsertClass(Thread* thread,
@@ -13538,7 +13774,7 @@
     result ^= table.InsertOrGetValue(name_index, klass);
     set_classes_cache(table.Release());
   }
-  return result.raw();
+  return result.ptr();
 }
 
 ErrorPtr Library::CompileAll(bool ignore_error /* = false */) {
@@ -13546,7 +13782,7 @@
   Zone* zone = thread->zone();
   Error& error = Error::Handle(zone);
   const GrowableObjectArray& libs = GrowableObjectArray::Handle(
-      Isolate::Current()->object_store()->libraries());
+      IsolateGroup::Current()->object_store()->libraries());
   Library& lib = Library::Handle(zone);
   Class& cls = Class::Handle(zone);
   for (int i = 0; i < libs.Length(); i++) {
@@ -13557,34 +13793,28 @@
       error = cls.EnsureIsFinalized(thread);
       if (!error.IsNull()) {
         if (ignore_error) continue;
-        return error.raw();
+        return error.ptr();
       }
       error = Compiler::CompileAllFunctions(cls);
       if (!error.IsNull()) {
         if (ignore_error) continue;
-        return error.raw();
+        return error.ptr();
       }
     }
   }
 
-  // Inner functions get added to the closures array. As part of compilation
-  // more closures can be added to the end of the array. Compile all the
-  // closures until we have reached the end of the "worklist".
   Object& result = Object::Handle(zone);
-  const GrowableObjectArray& closures = GrowableObjectArray::Handle(
-      zone, Isolate::Current()->object_store()->closure_functions());
-  Function& func = Function::Handle(zone);
-  for (int i = 0; i < closures.Length(); i++) {
-    func ^= closures.At(i);
+  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& func) {
     if (!func.HasCode()) {
       result = Compiler::CompileFunction(thread, func);
       if (result.IsError()) {
-        if (ignore_error) continue;
-        return Error::Cast(result).raw();
+        error = Error::Cast(result).ptr();
+        return false;  // Stop iteration.
       }
     }
-  }
-  return Error::null();
+    return true;  // Continue iteration.
+  });
+  return error.ptr();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -13595,7 +13825,7 @@
   Zone* zone = thread->zone();
   Error& error = Error::Handle(zone);
   const GrowableObjectArray& libs = GrowableObjectArray::Handle(
-      Isolate::Current()->object_store()->libraries());
+      IsolateGroup::Current()->object_store()->libraries());
   Library& lib = Library::Handle(zone);
   Class& cls = Class::Handle(zone);
   for (int i = 0; i < libs.Length(); i++) {
@@ -13614,7 +13844,7 @@
       cls = it.GetNextClass();
       error = cls.EnsureIsFinalized(thread);
       if (!error.IsNull()) {
-        return error.raw();
+        return error.ptr();
       }
     }
   }
@@ -13652,7 +13882,7 @@
       }
     }
     if (!func.IsNull()) {
-      return func.raw();
+      return func.ptr();
     }
   }
   return Function::null();
@@ -13666,7 +13896,7 @@
     // Check whether the function is reexported into the library.
     const Object& obj = Object::Handle(zone, LookupReExport(name));
     if (obj.IsFunction()) {
-      func ^= obj.raw();
+      func ^= obj.ptr();
     } else {
       // Check if there is a getter of 'name', in which case invoke it
       // and return the result.
@@ -13787,7 +14017,7 @@
     result.SetHasMonomorphicEntry(has_monomorphic_entry);
     result.set_stats(nullptr);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* Instructions::ToCString() const {
@@ -13797,7 +14027,7 @@
 CodeStatistics* Instructions::stats() const {
 #if defined(DART_PRECOMPILER)
   return reinterpret_cast<CodeStatistics*>(
-      Thread::Current()->heap()->GetPeer(raw()));
+      Thread::Current()->heap()->GetPeer(ptr()));
 #else
   return nullptr;
 #endif
@@ -13805,7 +14035,7 @@
 
 void Instructions::set_stats(CodeStatistics* stats) const {
 #if defined(DART_PRECOMPILER)
-  Thread::Current()->heap()->SetPeer(raw(), stats);
+  Thread::Current()->heap()->SetPeer(ptr(), stats);
 #endif
 }
 
@@ -13832,7 +14062,7 @@
     }
   }
 
-  return result.raw();
+  return result.ptr();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -13840,7 +14070,7 @@
     const compiler::ObjectPoolBuilder& builder) {
   const intptr_t len = builder.CurrentLength();
   if (len == 0) {
-    return Object::empty_object_pool().raw();
+    return Object::empty_object_pool().ptr();
   }
   const ObjectPool& result = ObjectPool::Handle(ObjectPool::New(len));
   for (intptr_t i = 0; i < len; i++) {
@@ -13854,7 +14084,7 @@
       result.SetRawValueAt(i, entry.raw_value_);
     }
   }
-  return result.raw();
+  return result.ptr();
 }
 
 void ObjectPool::CopyInto(compiler::ObjectPoolBuilder* builder) const {
@@ -13917,16 +14147,16 @@
 }
 
 intptr_t PcDescriptors::Length() const {
-  return raw_ptr()->length_;
+  return untag()->length_;
 }
 
 void PcDescriptors::SetLength(intptr_t value) const {
-  StoreNonPointer(&raw_ptr()->length_, value);
+  StoreNonPointer(&untag()->length_, value);
 }
 
 void PcDescriptors::CopyData(const void* bytes, intptr_t size) {
   NoSafepointScope no_safepoint;
-  uint8_t* data = UnsafeMutableNonPointer(&raw_ptr()->data()[0]);
+  uint8_t* data = UnsafeMutableNonPointer(&untag()->data()[0]);
   // We're guaranted these memory spaces do not overlap.
   memcpy(data, bytes, size);  // NOLINT
 }
@@ -13944,7 +14174,7 @@
     result.SetLength(size);
     result.CopyData(delta_encoded_data, size);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 PcDescriptorsPtr PcDescriptors::New(intptr_t length) {
@@ -13958,28 +14188,28 @@
     result ^= raw;
     result.SetLength(length);
   }
-  return result.raw();
+  return result.ptr();
 }
 
-const char* PcDescriptors::KindAsStr(PcDescriptorsLayout::Kind kind) {
+const char* PcDescriptors::KindAsStr(UntaggedPcDescriptors::Kind kind) {
   switch (kind) {
-    case PcDescriptorsLayout::kDeopt:
+    case UntaggedPcDescriptors::kDeopt:
       return "deopt        ";
-    case PcDescriptorsLayout::kIcCall:
+    case UntaggedPcDescriptors::kIcCall:
       return "ic-call      ";
-    case PcDescriptorsLayout::kUnoptStaticCall:
+    case UntaggedPcDescriptors::kUnoptStaticCall:
       return "unopt-call   ";
-    case PcDescriptorsLayout::kRuntimeCall:
+    case UntaggedPcDescriptors::kRuntimeCall:
       return "runtime-call ";
-    case PcDescriptorsLayout::kOsrEntry:
+    case UntaggedPcDescriptors::kOsrEntry:
       return "osr-entry    ";
-    case PcDescriptorsLayout::kRewind:
+    case UntaggedPcDescriptors::kRewind:
       return "rewind       ";
-    case PcDescriptorsLayout::kBSSRelocation:
+    case UntaggedPcDescriptors::kBSSRelocation:
       return "bss reloc    ";
-    case PcDescriptorsLayout::kOther:
+    case UntaggedPcDescriptors::kOther:
       return "other        ";
-    case PcDescriptorsLayout::kAnyKind:
+    case UntaggedPcDescriptors::kAnyKind:
       UNREACHABLE();
       break;
   }
@@ -14008,7 +14238,7 @@
   // First compute the buffer size required.
   intptr_t len = 1;  // Trailing '\0'.
   {
-    Iterator iter(*this, PcDescriptorsLayout::kAnyKind);
+    Iterator iter(*this, UntaggedPcDescriptors::kAnyKind);
     while (iter.MoveNext()) {
       len += Utils::SNPrint(NULL, 0, FORMAT, addr_width, iter.PcOffset(),
                             KindAsStr(iter.Kind()), iter.DeoptId(),
@@ -14020,7 +14250,7 @@
   char* buffer = Thread::Current()->zone()->Alloc<char>(len);
   // Layout the fields in the buffer.
   intptr_t index = 0;
-  Iterator iter(*this, PcDescriptorsLayout::kAnyKind);
+  Iterator iter(*this, UntaggedPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     index += Utils::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
                             iter.PcOffset(), KindAsStr(iter.Kind()),
@@ -14043,8 +14273,8 @@
     return;
   }
   intptr_t max_deopt_id = 0;
-  Iterator max_iter(*this,
-                    PcDescriptorsLayout::kDeopt | PcDescriptorsLayout::kIcCall);
+  Iterator max_iter(
+      *this, UntaggedPcDescriptors::kDeopt | UntaggedPcDescriptors::kIcCall);
   while (max_iter.MoveNext()) {
     if (max_iter.DeoptId() > max_deopt_id) {
       max_deopt_id = max_iter.DeoptId();
@@ -14055,7 +14285,7 @@
   BitVector* deopt_ids = new (zone) BitVector(zone, max_deopt_id + 1);
   BitVector* iccall_ids = new (zone) BitVector(zone, max_deopt_id + 1);
   Iterator iter(*this,
-                PcDescriptorsLayout::kDeopt | PcDescriptorsLayout::kIcCall);
+                UntaggedPcDescriptors::kDeopt | UntaggedPcDescriptors::kIcCall);
   while (iter.MoveNext()) {
     // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind.
     if (DeoptId::IsDeoptAfter(iter.DeoptId())) {
@@ -14064,7 +14294,7 @@
       // lead to issues in the future. Fix that and enable verification.
       continue;
     }
-    if (iter.Kind() == PcDescriptorsLayout::kDeopt) {
+    if (iter.Kind() == UntaggedPcDescriptors::kDeopt) {
       ASSERT(!deopt_ids->Contains(iter.DeoptId()));
       deopt_ids->Add(iter.DeoptId());
     } else {
@@ -14076,7 +14306,7 @@
 }
 
 void CodeSourceMap::SetLength(intptr_t value) const {
-  StoreNonPointer(&raw_ptr()->length_, value);
+  StoreNonPointer(&untag()->length_, value);
 }
 
 CodeSourceMapPtr CodeSourceMap::New(intptr_t length) {
@@ -14090,7 +14320,7 @@
     result ^= raw;
     result.SetLength(length);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* CodeSourceMap::ToCString() const {
@@ -14099,7 +14329,7 @@
 
 intptr_t CompressedStackMaps::Hashcode() const {
   NoSafepointScope scope;
-  uint8_t* data = UnsafeMutableNonPointer(&raw_ptr()->data()[0]);
+  uint8_t* data = UnsafeMutableNonPointer(&untag()->data()[0]);
   uint8_t* end = data + payload_size();
   uint32_t hash = payload_size();
   for (uint8_t* cursor = data; cursor < end; cursor++) {
@@ -14125,7 +14355,7 @@
           // Only look up the global table if the map will end up using it.
           maps.UsesGlobalTable() ? CompressedStackMaps::Handle(
                                        thread->zone(),
-                                       thread->isolate()
+                                       thread->isolate_group()
                                            ->object_store()
                                            ->canonicalized_stack_map_entries())
                                  : Object::null_compressed_stackmaps()) {}
@@ -14146,8 +14376,7 @@
   }
 
   NoSafepointScope scope;
-  ReadStream stream(maps_.raw_ptr()->data(), maps_.payload_size(),
-                    next_offset_);
+  ReadStream stream(maps_.untag()->data(), maps_.payload_size(), next_offset_);
 
   auto const pc_delta = stream.ReadLEB128();
   ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
@@ -14206,7 +14435,7 @@
   uint8_t byte_mask = 1U << bit_remainder;
   const intptr_t byte_offset = current_bits_offset_ + byte_index;
   NoSafepointScope scope;
-  return (bits_container_.raw_ptr()->data()[byte_offset] & byte_mask) != 0;
+  return (bits_container_.untag()->data()[byte_offset] & byte_mask) != 0;
 }
 
 void CompressedStackMaps::Iterator::LazyLoadGlobalTableEntry() const {
@@ -14215,7 +14444,7 @@
   ASSERT(current_global_table_offset_ < bits_container_.payload_size());
 
   NoSafepointScope scope;
-  ReadStream stream(bits_container_.raw_ptr()->data(),
+  ReadStream stream(bits_container_.untag()->data(),
                     bits_container_.payload_size(),
                     current_global_table_offset_);
 
@@ -14264,7 +14493,7 @@
   // The canonical empty instance should be used instead.
   ASSERT(size != 0);
 
-  if (!CompressedStackMapsLayout::SizeField::is_valid(size)) {
+  if (!UntaggedCompressedStackMaps::SizeField::is_valid(size)) {
     FATAL1(
         "Fatal error in CompressedStackMaps::New: "
         "invalid payload size %" Pu "\n",
@@ -14281,17 +14510,18 @@
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.StoreNonPointer(
-        &result.raw_ptr()->flags_and_size_,
-        CompressedStackMapsLayout::GlobalTableBit::encode(is_global_table) |
-            CompressedStackMapsLayout::UsesTableBit::encode(uses_global_table) |
-            CompressedStackMapsLayout::SizeField::encode(size));
-    auto cursor = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
+        &result.untag()->flags_and_size_,
+        UntaggedCompressedStackMaps::GlobalTableBit::encode(is_global_table) |
+            UntaggedCompressedStackMaps::UsesTableBit::encode(
+                uses_global_table) |
+            UntaggedCompressedStackMaps::SizeField::encode(size));
+    auto cursor = result.UnsafeMutableNonPointer(result.untag()->data());
     memcpy(cursor, payload, size);  // NOLINT
   }
 
   ASSERT(!result.IsGlobalTable() || !result.UsesGlobalTable());
 
-  return result.raw();
+  return result.ptr();
 }
 
 const char* CompressedStackMaps::ToCString() const {
@@ -14310,43 +14540,43 @@
 
 StringPtr LocalVarDescriptors::GetName(intptr_t var_index) const {
   ASSERT(var_index < Length());
-  ASSERT(Object::Handle(*raw()->ptr()->nameAddrAt(var_index)).IsString());
-  return *raw()->ptr()->nameAddrAt(var_index);
+  ASSERT(Object::Handle(*ptr()->untag()->nameAddrAt(var_index)).IsString());
+  return *ptr()->untag()->nameAddrAt(var_index);
 }
 
 void LocalVarDescriptors::SetVar(
     intptr_t var_index,
     const String& name,
-    LocalVarDescriptorsLayout::VarInfo* info) const {
+    UntaggedLocalVarDescriptors::VarInfo* info) const {
   ASSERT(var_index < Length());
   ASSERT(!name.IsNull());
-  StorePointer(raw()->ptr()->nameAddrAt(var_index), name.raw());
-  raw()->ptr()->data()[var_index] = *info;
+  StorePointer(ptr()->untag()->nameAddrAt(var_index), name.ptr());
+  ptr()->untag()->data()[var_index] = *info;
 }
 
 void LocalVarDescriptors::GetInfo(
     intptr_t var_index,
-    LocalVarDescriptorsLayout::VarInfo* info) const {
+    UntaggedLocalVarDescriptors::VarInfo* info) const {
   ASSERT(var_index < Length());
-  *info = raw()->ptr()->data()[var_index];
+  *info = ptr()->untag()->data()[var_index];
 }
 
 static int PrintVarInfo(char* buffer,
                         int len,
                         intptr_t i,
                         const String& var_name,
-                        const LocalVarDescriptorsLayout::VarInfo& info) {
-  const LocalVarDescriptorsLayout::VarInfoKind kind = info.kind();
+                        const UntaggedLocalVarDescriptors::VarInfo& info) {
+  const UntaggedLocalVarDescriptors::VarInfoKind kind = info.kind();
   const int32_t index = info.index();
-  if (kind == LocalVarDescriptorsLayout::kContextLevel) {
+  if (kind == UntaggedLocalVarDescriptors::kContextLevel) {
     return Utils::SNPrint(buffer, len,
                           "%2" Pd
                           " %-13s level=%-3d"
                           " begin=%-3d end=%d\n",
                           i, LocalVarDescriptors::KindToCString(kind), index,
-                          static_cast<int>(info.begin_pos.value()),
-                          static_cast<int>(info.end_pos.value()));
-  } else if (kind == LocalVarDescriptorsLayout::kContextVar) {
+                          static_cast<int>(info.begin_pos.Pos()),
+                          static_cast<int>(info.end_pos.Pos()));
+  } else if (kind == UntaggedLocalVarDescriptors::kContextVar) {
     return Utils::SNPrint(
         buffer, len,
         "%2" Pd
@@ -14377,7 +14607,7 @@
   intptr_t len = 1;  // Trailing '\0'.
   String& var_name = String::Handle();
   for (intptr_t i = 0; i < Length(); i++) {
-    LocalVarDescriptorsLayout::VarInfo info;
+    UntaggedLocalVarDescriptors::VarInfo info;
     var_name = GetName(i);
     GetInfo(i, &info);
     len += PrintVarInfo(NULL, 0, i, var_name, info);
@@ -14386,7 +14616,7 @@
   buffer[0] = '\0';
   intptr_t num_chars = 0;
   for (intptr_t i = 0; i < Length(); i++) {
-    LocalVarDescriptorsLayout::VarInfo info;
+    UntaggedLocalVarDescriptors::VarInfo info;
     var_name = GetName(i);
     GetInfo(i, &info);
     num_chars += PrintVarInfo((buffer + num_chars), (len - num_chars), i,
@@ -14396,15 +14626,15 @@
 }
 
 const char* LocalVarDescriptors::KindToCString(
-    LocalVarDescriptorsLayout::VarInfoKind kind) {
+    UntaggedLocalVarDescriptors::VarInfoKind kind) {
   switch (kind) {
-    case LocalVarDescriptorsLayout::kStackVar:
+    case UntaggedLocalVarDescriptors::kStackVar:
       return "StackVar";
-    case LocalVarDescriptorsLayout::kContextVar:
+    case UntaggedLocalVarDescriptors::kContextVar:
       return "ContextVar";
-    case LocalVarDescriptorsLayout::kContextLevel:
+    case UntaggedLocalVarDescriptors::kContextLevel:
       return "ContextLevel";
-    case LocalVarDescriptorsLayout::kSavedCurrentContext:
+    case UntaggedLocalVarDescriptors::kSavedCurrentContext:
       return "CurrentCtx";
     default:
       UNIMPLEMENTED();
@@ -14419,7 +14649,7 @@
     FATAL2(
         "Fatal error in LocalVarDescriptors::New: "
         "invalid num_variables %" Pd ". Maximum is: %d\n",
-        num_variables, LocalVarDescriptorsLayout::kMaxIndex);
+        num_variables, UntaggedLocalVarDescriptors::kMaxIndex);
   }
   LocalVarDescriptors& result = LocalVarDescriptors::Handle();
   {
@@ -14428,17 +14658,17 @@
         Object::Allocate(LocalVarDescriptors::kClassId, size, Heap::kOld);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.StoreNonPointer(&result.raw_ptr()->num_entries_, num_variables);
+    result.StoreNonPointer(&result.untag()->num_entries_, num_variables);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 intptr_t LocalVarDescriptors::Length() const {
-  return raw_ptr()->num_entries_;
+  return untag()->num_entries_;
 }
 
 intptr_t ExceptionHandlers::num_entries() const {
-  return raw_ptr()->num_entries_;
+  return untag()->num_entries_;
 }
 
 void ExceptionHandlers::SetHandlerInfo(intptr_t try_index,
@@ -14450,7 +14680,7 @@
   ASSERT((try_index >= 0) && (try_index < num_entries()));
   NoSafepointScope no_safepoint;
   ExceptionHandlerInfo* info =
-      UnsafeMutableNonPointer(&raw_ptr()->data()[try_index]);
+      UnsafeMutableNonPointer(&untag()->data()[try_index]);
   info->outer_try_index = outer_try_index;
   // Some C compilers warn about the comparison always being true when using <=
   // due to limited range of data type.
@@ -14466,32 +14696,32 @@
                                        ExceptionHandlerInfo* info) const {
   ASSERT((try_index >= 0) && (try_index < num_entries()));
   ASSERT(info != NULL);
-  *info = raw_ptr()->data()[try_index];
+  *info = untag()->data()[try_index];
 }
 
 uword ExceptionHandlers::HandlerPCOffset(intptr_t try_index) const {
   ASSERT((try_index >= 0) && (try_index < num_entries()));
-  return raw_ptr()->data()[try_index].handler_pc_offset;
+  return untag()->data()[try_index].handler_pc_offset;
 }
 
 intptr_t ExceptionHandlers::OuterTryIndex(intptr_t try_index) const {
   ASSERT((try_index >= 0) && (try_index < num_entries()));
-  return raw_ptr()->data()[try_index].outer_try_index;
+  return untag()->data()[try_index].outer_try_index;
 }
 
 bool ExceptionHandlers::NeedsStackTrace(intptr_t try_index) const {
   ASSERT((try_index >= 0) && (try_index < num_entries()));
-  return raw_ptr()->data()[try_index].needs_stacktrace != 0;
+  return untag()->data()[try_index].needs_stacktrace != 0;
 }
 
 bool ExceptionHandlers::IsGenerated(intptr_t try_index) const {
   ASSERT((try_index >= 0) && (try_index < num_entries()));
-  return raw_ptr()->data()[try_index].is_generated != 0;
+  return untag()->data()[try_index].is_generated != 0;
 }
 
 bool ExceptionHandlers::HasCatchAll(intptr_t try_index) const {
   ASSERT((try_index >= 0) && (try_index < num_entries()));
-  return raw_ptr()->data()[try_index].has_catch_all != 0;
+  return untag()->data()[try_index].has_catch_all != 0;
 }
 
 void ExceptionHandlers::SetHandledTypes(intptr_t try_index,
@@ -14499,19 +14729,19 @@
   ASSERT((try_index >= 0) && (try_index < num_entries()));
   ASSERT(!handled_types.IsNull());
   const Array& handled_types_data =
-      Array::Handle(raw_ptr()->handled_types_data());
+      Array::Handle(untag()->handled_types_data());
   handled_types_data.SetAt(try_index, handled_types);
 }
 
 ArrayPtr ExceptionHandlers::GetHandledTypes(intptr_t try_index) const {
   ASSERT((try_index >= 0) && (try_index < num_entries()));
-  Array& array = Array::Handle(raw_ptr()->handled_types_data());
+  Array& array = Array::Handle(untag()->handled_types_data());
   array ^= array.At(try_index);
-  return array.raw();
+  return array.ptr();
 }
 
 void ExceptionHandlers::set_handled_types_data(const Array& value) const {
-  raw_ptr()->set_handled_types_data(value.raw());
+  untag()->set_handled_types_data(value.ptr());
 }
 
 ExceptionHandlersPtr ExceptionHandlers::New(intptr_t num_handlers) {
@@ -14529,13 +14759,13 @@
         Object::Allocate(ExceptionHandlers::kClassId, size, Heap::kOld);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.StoreNonPointer(&result.raw_ptr()->num_entries_, num_handlers);
+    result.StoreNonPointer(&result.untag()->num_entries_, num_handlers);
   }
   const Array& handled_types_data =
       (num_handlers == 0) ? Object::empty_array()
                           : Array::Handle(Array::New(num_handlers, Heap::kOld));
   result.set_handled_types_data(handled_types_data);
-  return result.raw();
+  return result.ptr();
 }
 
 ExceptionHandlersPtr ExceptionHandlers::New(const Array& handled_types_data) {
@@ -14554,10 +14784,10 @@
         Object::Allocate(ExceptionHandlers::kClassId, size, Heap::kOld);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.StoreNonPointer(&result.raw_ptr()->num_entries_, num_handlers);
+    result.StoreNonPointer(&result.untag()->num_entries_, num_handlers);
   }
   result.set_handled_types_data(handled_types_data);
-  return result.raw();
+  return result.ptr();
 }
 
 const char* ExceptionHandlers::ToCString() const {
@@ -14613,7 +14843,7 @@
 }
 
 void SingleTargetCache::set_target(const Code& value) const {
-  raw_ptr()->set_target(value.raw());
+  untag()->set_target(value.ptr());
 }
 
 const char* SingleTargetCache::ToCString() const {
@@ -14634,11 +14864,11 @@
   result.set_entry_point(0);
   result.set_lower_limit(kIllegalCid);
   result.set_upper_limit(kIllegalCid);
-  return result.raw();
+  return result.ptr();
 }
 
 void UnlinkedCall::set_can_patch_to_monomorphic(bool value) const {
-  StoreNonPointer(&raw_ptr()->can_patch_to_monomorphic_, value);
+  StoreNonPointer(&untag()->can_patch_to_monomorphic_, value);
 }
 
 intptr_t UnlinkedCall::Hashcode() const {
@@ -14660,7 +14890,7 @@
   result ^= Object::Allocate(UnlinkedCall::kClassId,
                              UnlinkedCall::InstanceSize(), Heap::kOld);
   result.set_can_patch_to_monomorphic(!FLAG_precompiled_mode);
-  return result.raw();
+  return result.ptr();
 }
 
 MonomorphicSmiableCallPtr MonomorphicSmiableCall::New(classid_t expected_cid,
@@ -14669,10 +14899,10 @@
   result ^=
       Object::Allocate(MonomorphicSmiableCall::kClassId,
                        MonomorphicSmiableCall::InstanceSize(), Heap::kOld);
-  result.raw_ptr()->set_target(target.raw());
-  result.StoreNonPointer(&result.raw_ptr()->expected_cid_, expected_cid);
-  result.StoreNonPointer(&result.raw_ptr()->entrypoint_, target.EntryPoint());
-  return result.raw();
+  result.untag()->set_target(target.ptr());
+  result.StoreNonPointer(&result.untag()->expected_cid_, expected_cid);
+  result.StoreNonPointer(&result.untag()->entrypoint_, target.EntryPoint());
+  return result.ptr();
 }
 
 const char* MonomorphicSmiableCall::ToCString() const {
@@ -14687,17 +14917,17 @@
 
 void CallSiteData::set_target_name(const String& value) const {
   ASSERT(!value.IsNull());
-  raw_ptr()->set_target_name(value.raw());
+  untag()->set_target_name(value.ptr());
 }
 
 void CallSiteData::set_arguments_descriptor(const Array& value) const {
   ASSERT(!value.IsNull());
-  raw_ptr()->set_args_descriptor(value.raw());
+  untag()->set_args_descriptor(value.ptr());
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 void ICData::SetReceiversStaticType(const AbstractType& type) const {
-  raw_ptr()->set_receivers_static_type(type.raw());
+  untag()->set_receivers_static_type(type.ptr());
 
 #if defined(TARGET_ARCH_X64)
   if (!type.IsNull() && type.HasTypeClass() && (NumArgsTested() == 1) &&
@@ -14741,15 +14971,15 @@
 }
 
 FunctionPtr ICData::Owner() const {
-  Object& obj = Object::Handle(raw_ptr()->owner());
+  Object& obj = Object::Handle(untag()->owner());
   if (obj.IsNull()) {
     ASSERT(Dart::vm_snapshot_kind() == Snapshot::kFullAOT);
     return Function::null();
   } else if (obj.IsFunction()) {
-    return Function::Cast(obj).raw();
+    return Function::Cast(obj).ptr();
   } else {
     ICData& original = ICData::Handle();
-    original ^= obj.raw();
+    original ^= obj.ptr();
     return original.Owner();
   }
 }
@@ -14758,22 +14988,22 @@
   if (IsNull()) {
     return ICData::null();
   }
-  Object& obj = Object::Handle(raw_ptr()->owner());
+  Object& obj = Object::Handle(untag()->owner());
   if (obj.IsFunction()) {
-    return this->raw();
+    return this->ptr();
   } else {
-    return ICData::RawCast(obj.raw());
+    return ICData::RawCast(obj.ptr());
   }
 }
 
 void ICData::SetOriginal(const ICData& value) const {
   ASSERT(value.IsOriginal());
   ASSERT(!value.IsNull());
-  raw_ptr()->set_owner(static_cast<ObjectPtr>(value.raw()));
+  untag()->set_owner(static_cast<ObjectPtr>(value.ptr()));
 }
 
 void ICData::set_owner(const Function& value) const {
-  raw_ptr()->set_owner(static_cast<ObjectPtr>(value.raw()));
+  untag()->set_owner(static_cast<ObjectPtr>(value.ptr()));
 }
 
 void ICData::set_deopt_id(intptr_t value) const {
@@ -14781,23 +15011,23 @@
   UNREACHABLE();
 #else
   ASSERT(value <= kMaxInt32);
-  StoreNonPointer(&raw_ptr()->deopt_id_, value);
+  StoreNonPointer(&untag()->deopt_id_, value);
 #endif
 }
 
 void ICData::set_entries(const Array& value) const {
   ASSERT(!value.IsNull());
-  raw_ptr()->set_entries<std::memory_order_release>(value.raw());
+  untag()->set_entries<std::memory_order_release>(value.ptr());
 }
 
 intptr_t ICData::NumArgsTested() const {
-  return NumArgsTestedBits::decode(raw_ptr()->state_bits_);
+  return NumArgsTestedBits::decode(untag()->state_bits_);
 }
 
 void ICData::SetNumArgsTested(intptr_t value) const {
   ASSERT(Utils::IsUint(2, value));
-  StoreNonPointer(&raw_ptr()->state_bits_,
-                  NumArgsTestedBits::update(value, raw_ptr()->state_bits_));
+  StoreNonPointer(&untag()->state_bits_,
+                  NumArgsTestedBits::update(value, untag()->state_bits_));
 }
 
 intptr_t CallSiteData::TypeArgsLen() const {
@@ -14826,12 +15056,12 @@
 }
 
 uint32_t ICData::DeoptReasons() const {
-  return DeoptReasonBits::decode(raw_ptr()->state_bits_);
+  return DeoptReasonBits::decode(untag()->state_bits_);
 }
 
 void ICData::SetDeoptReasons(uint32_t reasons) const {
-  StoreNonPointer(&raw_ptr()->state_bits_,
-                  DeoptReasonBits::update(reasons, raw_ptr()->state_bits_));
+  StoreNonPointer(&untag()->state_bits_,
+                  DeoptReasonBits::update(reasons, untag()->state_bits_));
 }
 
 bool ICData::HasDeoptReason(DeoptReasonId reason) const {
@@ -14869,12 +15099,12 @@
 }
 
 ICData::RebindRule ICData::rebind_rule() const {
-  return (ICData::RebindRule)RebindRuleBits::decode(raw_ptr()->state_bits_);
+  return (ICData::RebindRule)RebindRuleBits::decode(untag()->state_bits_);
 }
 
 void ICData::set_rebind_rule(uint32_t rebind_rule) const {
-  StoreNonPointer(&raw_ptr()->state_bits_,
-                  RebindRuleBits::update(rebind_rule, raw_ptr()->state_bits_));
+  StoreNonPointer(&untag()->state_bits_,
+                  RebindRuleBits::update(rebind_rule, untag()->state_bits_));
 }
 
 bool ICData::is_static_call() const {
@@ -14882,7 +15112,7 @@
 }
 
 void ICData::set_state_bits(uint32_t bits) const {
-  StoreNonPointer(&raw_ptr()->state_bits_, bits);
+  StoreNonPointer(&untag()->state_bits_, bits);
 }
 
 intptr_t ICData::TestEntryLengthFor(intptr_t num_args,
@@ -14896,7 +15126,7 @@
 }
 
 intptr_t ICData::Length() const {
-  return (Smi::Value(entries()->ptr()->length()) / TestEntryLength());
+  return (Smi::Value(entries()->untag()->length()) / TestEntryLength());
 }
 
 intptr_t ICData::NumberOfChecks() const {
@@ -15058,12 +15288,12 @@
            target.name();
   }
 #endif
-  ObjectStore* store = Isolate::Current()->object_store();
-  ASSERT((target.raw() == store->simple_instance_of_true_function()) ||
-         (target.raw() == store->simple_instance_of_false_function()));
+  ObjectStore* store = IsolateGroup::Current()->object_store();
+  ASSERT((target.ptr() == store->simple_instance_of_true_function()) ||
+         (target.ptr() == store->simple_instance_of_false_function()));
   const String& instance_of_name = String::Handle(
-      Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()).raw());
-  ASSERT(target_name() == instance_of_name.raw());
+      Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()).ptr());
+  ASSERT(target_name() == instance_of_name.ptr());
   return true;
 }
 
@@ -15107,7 +15337,7 @@
         Smi::Value(Smi::RawCast(data.At(0))) == kObjectCid &&
         Smi::Value(Smi::RawCast(data.At(1))) == kObjectCid;
     if (has_dummy_entry) {
-      ASSERT(target.raw() == data.At(TargetIndexFor(num_args_tested)));
+      ASSERT(target.ptr() == data.At(TargetIndexFor(num_args_tested)));
       // Replace dummy entry.
       Smi& value = Smi::Handle();
       for (intptr_t i = 0; i < NumArgsTested(); i++) {
@@ -15149,7 +15379,7 @@
   const intptr_t new_len = data.Length() + TestEntryLength();
   data = Array::Grow(data, new_len, Heap::kOld);
   WriteSentinel(data, TestEntryLength());
-  return data.raw();
+  return data.ptr();
 }
 
 void ICData::DebugDump() const {
@@ -15277,7 +15507,7 @@
   const intptr_t entry_length = TestEntryLength();
   intptr_t data_pos = index * TestEntryLength();
   for (intptr_t i = 0; i < entry_length; i++) {
-    if (data.At(data_pos++) != smi_illegal_cid().raw()) {
+    if (data.At(data_pos++) != smi_illegal_cid().ptr()) {
       return false;
     }
   }
@@ -15338,7 +15568,7 @@
   const intptr_t data_pos = index * TestEntryLength();
   NoSafepointScope no_safepoint;
   ArrayPtr raw_data = entries();
-  return Smi::Value(Smi::RawCast(raw_data->ptr()->data()[data_pos]));
+  return Smi::Value(Smi::RawCast(raw_data->untag()->data()[data_pos]));
 }
 
 FunctionPtr ICData::GetTargetAt(intptr_t index) const {
@@ -15352,7 +15582,7 @@
 
   NoSafepointScope no_safepoint;
   ArrayPtr raw_data = entries();
-  return static_cast<FunctionPtr>(raw_data->ptr()->data()[data_pos]);
+  return static_cast<FunctionPtr>(raw_data->untag()->data()[data_pos]);
 #endif
 }
 
@@ -15412,7 +15642,7 @@
   ASSERT(NumArgsTested() > arg_nr);
   if ((arg_nr == 0) && (NumArgsTested() == 1)) {
     // Frequent case.
-    return raw();
+    return ptr();
   }
   const intptr_t kNumArgsTested = 1;
   ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested));
@@ -15444,7 +15674,7 @@
     }
   }
 
-  return result.raw();
+  return result.ptr();
 }
 
 // (cid, count) tuple used to sort ICData by count.
@@ -15515,7 +15745,7 @@
   WriteSentinel(data, result.TestEntryLength());
   result.set_entries(data);
   ASSERT(result.NumberOfChecksIs(aggregate.length()));
-  return result.raw();
+  return result.ptr();
 }
 
 UnlinkedCallPtr ICData::AsUnlinkedCall() const {
@@ -15526,7 +15756,7 @@
   result.set_arguments_descriptor(Array::Handle(arguments_descriptor()));
   result.set_can_patch_to_monomorphic(!FLAG_precompiled_mode ||
                                       receiver_cannot_be_smi());
-  return result.raw();
+  return result.ptr();
 }
 
 bool ICData::HasReceiverClassId(intptr_t class_id) const {
@@ -15584,7 +15814,7 @@
   const Array& array = Array::Handle(Array::New(len, Heap::kOld));
   WriteSentinel(array, len);
   array.MakeImmutable();
-  return array.raw();
+  return array.ptr();
 }
 
 ArrayPtr ICData::CachedEmptyICDataArray(intptr_t num_args_tested,
@@ -15636,7 +15866,7 @@
   result.set_rebind_rule(rebind_rule);
   result.SetNumArgsTested(num_args_tested);
   NOT_IN_PRECOMPILED(result.SetReceiversStaticType(receivers_static_type));
-  return result.raw();
+  return result.ptr();
 }
 
 bool ICData::IsImmutable() const {
@@ -15654,7 +15884,7 @@
   }
   result.set_deopt_id(DeoptId::kNone);
   result.set_state_bits(0);
-  return result.raw();
+  return result.ptr();
 }
 
 ICDataPtr ICData::New(const Function& owner,
@@ -15672,7 +15902,7 @@
   result.set_entries(Array::Handle(
       zone,
       CachedEmptyICDataArray(num_args_tested, result.is_tracking_exactness())));
-  return result.raw();
+  return result.ptr();
 }
 
 ICDataPtr ICData::NewWithCheck(const Function& owner,
@@ -15713,7 +15943,7 @@
 
   result.set_entries(array);
 
-  return result.raw();
+  return result.ptr();
 }
 
 ICDataPtr ICData::NewForStaticCall(const Function& owner,
@@ -15751,7 +15981,7 @@
   // Copy deoptimization reasons.
   result.SetDeoptReasons(from.DeoptReasons());
   result.set_is_megamorphic(is_megamorphic);
-  return result.raw();
+  return result.ptr();
 }
 
 ICDataPtr ICData::Clone(const ICData& from) {
@@ -15789,7 +16019,7 @@
   RELEASE_ASSERT(!is_megamorphic ||
                  result.NumberOfChecks() >= FLAG_max_polymorphic_checks);
 
-  return result.raw();
+  return result.ptr();
 }
 #endif
 
@@ -15807,11 +16037,11 @@
   // snapshots), non-heap objects, and WSRs (as there is no point in deeply
   // nesting them). We also only wrap objects in the precompiler.
   return FLAG_precompiled_mode && !object.IsNull() &&
-         object.raw()->IsHeapObject() && !object.IsWeakSerializationReference();
+         object.ptr()->IsHeapObject() && !object.IsWeakSerializationReference();
 }
 
 ObjectPtr WeakSerializationReference::Wrap(Zone* zone, const Object& target) {
-  if (!CanWrap(target)) return target.raw();
+  if (!CanWrap(target)) return target.ptr();
   ASSERT(Object::weak_serialization_reference_class() != Class::null());
   WeakSerializationReference& result = WeakSerializationReference::Handle(zone);
   {
@@ -15821,9 +16051,9 @@
     NoSafepointScope no_safepoint;
 
     result ^= raw;
-    result.raw_ptr()->set_target(target.raw());
+    result.untag()->set_target(target.ptr());
   }
-  return result.raw();
+  return result.ptr();
 }
 #endif
 
@@ -15922,49 +16152,49 @@
   ASSERT(unwrapped_owner.IsFunction() || unwrapped_owner.IsClass() ||
          unwrapped_owner.IsAbstractType());
 #endif
-  raw_ptr()->set_owner(owner.raw());
+  untag()->set_owner(owner.ptr());
 }
 
 void Code::set_state_bits(intptr_t bits) const {
-  StoreNonPointer(&raw_ptr()->state_bits_, bits);
+  StoreNonPointer(&untag()->state_bits_, bits);
 }
 
 void Code::set_is_optimized(bool value) const {
-  set_state_bits(OptimizedBit::update(value, raw_ptr()->state_bits_));
+  set_state_bits(OptimizedBit::update(value, untag()->state_bits_));
 }
 
 void Code::set_is_force_optimized(bool value) const {
-  set_state_bits(ForceOptimizedBit::update(value, raw_ptr()->state_bits_));
+  set_state_bits(ForceOptimizedBit::update(value, untag()->state_bits_));
 }
 
 void Code::set_is_alive(bool value) const {
-  set_state_bits(AliveBit::update(value, raw_ptr()->state_bits_));
+  set_state_bits(AliveBit::update(value, untag()->state_bits_));
 }
 
 void Code::set_compressed_stackmaps(const CompressedStackMaps& maps) const {
   ASSERT(maps.IsOld());
-  raw_ptr()->set_compressed_stackmaps(maps.raw());
+  untag()->set_compressed_stackmaps(maps.ptr());
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 intptr_t Code::num_variables() const {
   ASSERT(!FLAG_precompiled_mode);
-  return Smi::Value(Smi::RawCast(raw_ptr()->catch_entry()));
+  return Smi::Value(Smi::RawCast(untag()->catch_entry()));
 }
 void Code::set_num_variables(intptr_t num_variables) const {
   ASSERT(!FLAG_precompiled_mode);
-  raw_ptr()->set_catch_entry(Smi::New(num_variables));
+  untag()->set_catch_entry(Smi::New(num_variables));
 }
 #endif
 
 #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
 TypedDataPtr Code::catch_entry_moves_maps() const {
   ASSERT(FLAG_precompiled_mode);
-  return TypedData::RawCast(raw_ptr()->catch_entry());
+  return TypedData::RawCast(untag()->catch_entry());
 }
 void Code::set_catch_entry_moves_maps(const TypedData& maps) const {
   ASSERT(FLAG_precompiled_mode);
-  raw_ptr()->set_catch_entry(maps.raw());
+  untag()->set_catch_entry(maps.ptr());
 }
 #endif
 
@@ -15973,7 +16203,7 @@
   UNREACHABLE();
 #else
   ASSERT(array.IsOld());
-  raw_ptr()->set_deopt_info_array(array.raw());
+  untag()->set_deopt_info_array(array.ptr());
 #endif
 }
 
@@ -15981,7 +16211,7 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
 #else
-  raw_ptr()->set_static_calls_target_table(value.raw());
+  untag()->set_static_calls_target_table(value.ptr());
 #endif
 #if defined(DEBUG)
   // Check that the table is sorted by pc offsets.
@@ -16001,7 +16231,7 @@
 ObjectPoolPtr Code::GetObjectPool() const {
 #if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    return Isolate::Current()->object_store()->global_object_pool();
+    return IsolateGroup::Current()->object_store()->global_object_pool();
   }
 #endif
   return object_pool();
@@ -16041,7 +16271,7 @@
       ASSERT(!info.IsNull());
       *deopt_reason = DeoptTable::ReasonField::decode(reason_and_flags.Value());
       *deopt_flags = DeoptTable::FlagsField::decode(reason_and_flags.Value());
-      return info.raw();
+      return info.ptr();
     }
   }
   *deopt_reason = ICData::kDeoptUnknown;
@@ -16054,7 +16284,7 @@
   UNREACHABLE();
 #else
   NoSafepointScope no_safepoint;
-  const Array& table = Array::Handle(raw_ptr()->static_calls_target_table());
+  const Array& table = Array::Handle(untag()->static_calls_target_table());
   StaticCallsTable entries(table);
   const intptr_t pc_offset = pc - PayloadStart();
   intptr_t imin = 0;
@@ -16084,7 +16314,7 @@
   if (i < 0) {
     return Function::null();
   }
-  const Array& array = Array::Handle(raw_ptr()->static_calls_target_table());
+  const Array& array = Array::Handle(untag()->static_calls_target_table());
   StaticCallsTable entries(array);
   return entries[i].Get<kSCallTableFunctionTarget>();
 #endif
@@ -16096,7 +16326,7 @@
 #else
   const intptr_t i = BinarySearchInSCallTable(pc);
   ASSERT(i >= 0);
-  const Array& array = Array::Handle(raw_ptr()->static_calls_target_table());
+  const Array& array = Array::Handle(untag()->static_calls_target_table());
   StaticCallsTable entries(array);
   ASSERT(code.IsNull() ||
          (code.function() == entries[i].Get<kSCallTableFunctionTarget>()));
@@ -16110,7 +16340,7 @@
 #else
   const intptr_t i = BinarySearchInSCallTable(pc);
   ASSERT(i >= 0);
-  const Array& array = Array::Handle(raw_ptr()->static_calls_target_table());
+  const Array& array = Array::Handle(untag()->static_calls_target_table());
   StaticCallsTable entries(array);
 #if defined(DEBUG)
   if (entries[i].Get<kSCallTableFunctionTarget>() == Function::null()) {
@@ -16142,7 +16372,7 @@
 #if defined(PRODUCT)
   Comments* comments = new Code::Comments(Array::Handle());
 #else
-  Comments* comments = new Code::Comments(Array::Handle(raw_ptr()->comments()));
+  Comments* comments = new Code::Comments(Array::Handle(untag()->comments()));
 #endif
   return *comments;
 }
@@ -16152,7 +16382,7 @@
   UNREACHABLE();
 #else
   ASSERT(comments.comments_.IsOld());
-  raw_ptr()->set_comments(comments.comments_.raw());
+  untag()->set_comments(comments.comments_.ptr());
 #endif
 }
 
@@ -16161,7 +16391,7 @@
   UNREACHABLE();
 #else
   ASSERT(offset >= 0);
-  raw_ptr()->set_return_address_metadata(Smi::New(offset));
+  untag()->set_return_address_metadata(Smi::New(offset));
 #endif
 }
 
@@ -16170,7 +16400,7 @@
   UNREACHABLE();
   return -1;
 #else
-  const Object& object = Object::Handle(raw_ptr()->return_address_metadata());
+  const Object& object = Object::Handle(untag()->return_address_metadata());
   // In the future we may put something other than a smi in
   // |return_address_metadata_|.
   if (object.IsNull() || !object.IsSmi()) {
@@ -16181,12 +16411,12 @@
 }
 
 ArrayPtr Code::inlined_id_to_function() const {
-  return raw_ptr()->inlined_id_to_function();
+  return untag()->inlined_id_to_function();
 }
 
 void Code::set_inlined_id_to_function(const Array& value) const {
   ASSERT(value.IsOld());
-  raw_ptr()->set_inlined_id_to_function(value.raw());
+  untag()->set_inlined_id_to_function(value.ptr());
 }
 
 CodePtr Code::New(intptr_t pointer_offsets_length) {
@@ -16211,7 +16441,7 @@
     result.set_pc_descriptors(Object::empty_descriptors());
     result.set_compressed_stackmaps(Object::empty_compressed_stackmaps());
   }
-  return result.raw();
+  return result.ptr();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -16221,11 +16451,13 @@
                                     PoolAttachment pool_attachment,
                                     bool optimized,
                                     CodeStatistics* stats) {
-  DEBUG_ASSERT(IsMutatorOrAtSafepoint());
+  auto thread = Thread::Current();
+  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
+
   const auto& code = Code::Handle(
       FinalizeCode(compiler, assembler, pool_attachment, optimized, stats));
   NotifyCodeObservers(function, code, optimized);
-  return code.raw();
+  return code.ptr();
 }
 
 CodePtr Code::FinalizeCodeAndNotify(const char* name,
@@ -16234,11 +16466,13 @@
                                     PoolAttachment pool_attachment,
                                     bool optimized,
                                     CodeStatistics* stats) {
-  DEBUG_ASSERT(IsMutatorOrAtSafepoint());
+  auto thread = Thread::Current();
+  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
+
   const auto& code = Code::Handle(
       FinalizeCode(compiler, assembler, pool_attachment, optimized, stats));
   NotifyCodeObservers(name, code, optimized);
-  return code.raw();
+  return code.ptr();
 }
 
 #if defined(DART_PRECOMPILER)
@@ -16251,7 +16485,8 @@
                            PoolAttachment pool_attachment,
                            bool optimized,
                            CodeStatistics* stats /* = nullptr */) {
-  DEBUG_ASSERT(IsMutatorOrAtSafepoint());
+  auto thread = Thread::Current();
+  ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
 
   ASSERT(assembler != NULL);
   ObjectPool& object_pool = ObjectPool::Handle();
@@ -16261,13 +16496,11 @@
       object_pool =
           ObjectPool::NewFromBuilder(assembler->object_pool_builder());
     } else {
-      object_pool = ObjectPool::empty_object_pool().raw();
+      object_pool = ObjectPool::empty_object_pool().ptr();
     }
   } else {
 #if defined(DART_PRECOMPILER)
-    const bool needs_pool = (FLAG_write_v8_snapshot_profile_to != nullptr) ||
-                            (FLAG_trace_precompiler_to != nullptr);
-    if (needs_pool && assembler->HasObjectPoolBuilder() &&
+    if (assembler->HasObjectPoolBuilder() &&
         assembler->object_pool_builder().HasParent()) {
       // We are not going to write this pool into snapshot, but we will use
       // it to emit references from this code object to other objects in the
@@ -16284,7 +16517,7 @@
   intptr_t pointer_offset_count = assembler->CountPointerOffsets();
   Code& code = Code::ZoneHandle(Code::New(pointer_offset_count));
 #ifdef TARGET_ARCH_IA32
-  assembler->GetSelfHandle() = code.raw();
+  assembler->GetSelfHandle() = code.ptr();
 #endif
   Instructions& instrs = Instructions::ZoneHandle(Instructions::New(
       assembler->CodeSize(), assembler->has_monomorphic_entry()));
@@ -16307,7 +16540,6 @@
 
     // Set pointer offsets list in Code object and resolve all handles in
     // the instruction stream to raw objects.
-    Thread* thread = Thread::Current();
     for (intptr_t i = 0; i < pointer_offsets.length(); i++) {
       intptr_t offset_in_instrs = pointer_offsets[i];
       code.SetPointerOffsetAt(i, offset_in_instrs);
@@ -16318,17 +16550,17 @@
       ASSERT(object->IsOld());
       // N.B. The pointer is embedded in the Instructions object, but visited
       // through the Code object.
-      code.raw()->ptr()->StorePointerUnaligned(
-          reinterpret_cast<ObjectPtr*>(addr), object->raw(), thread);
+      code.ptr()->untag()->StorePointerUnaligned(
+          reinterpret_cast<ObjectPtr*>(addr), object->ptr(), thread);
     }
 
     // Write protect instructions and, if supported by OS, use dual mapping
     // for execution.
     if (FLAG_write_protect_code) {
-      uword address = ObjectLayout::ToAddr(instrs.raw());
+      uword address = UntaggedObject::ToAddr(instrs.ptr());
       // Check if a dual mapping exists.
-      instrs = Instructions::RawCast(OldPage::ToExecutable(instrs.raw()));
-      uword exec_address = ObjectLayout::ToAddr(instrs.raw());
+      instrs = Instructions::RawCast(OldPage::ToExecutable(instrs.ptr()));
+      uword exec_address = UntaggedObject::ToAddr(instrs.ptr());
       const bool use_dual_mapping = exec_address != address;
       ASSERT(use_dual_mapping == FLAG_dual_map_code);
 
@@ -16337,14 +16569,14 @@
       // Yet the writable mapping is still turned back from RW to R.
       if (use_dual_mapping) {
         VirtualMemory::Protect(reinterpret_cast<void*>(address),
-                               instrs.raw()->ptr()->HeapSize(),
+                               instrs.ptr()->untag()->HeapSize(),
                                VirtualMemory::kReadOnly);
         address = exec_address;
       } else {
         // If dual mapping is disabled and we write protect then we have to
         // change the single mapping from RW -> RX.
         VirtualMemory::Protect(reinterpret_cast<void*>(address),
-                               instrs.raw()->ptr()->HeapSize(),
+                               instrs.ptr()->untag()->HeapSize(),
                                VirtualMemory::kReadExecute);
       }
     }
@@ -16358,7 +16590,7 @@
 
     // Set object pool in Instructions object.
     if (!object_pool.IsNull()) {
-      code.set_object_pool(object_pool.raw());
+      code.set_object_pool(object_pool.ptr());
     }
 
 #if defined(DART_PRECOMPILER)
@@ -16382,7 +16614,7 @@
     code.SetPrologueOffset(assembler->CodeSize());
   }
 #endif
-  return code.raw();
+  return code.ptr();
 }
 
 void Code::NotifyCodeObservers(const Code& code, bool optimized) {
@@ -16434,17 +16666,18 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 bool Code::SlowFindRawCodeVisitor::FindObject(ObjectPtr raw_obj) const {
-  return CodeLayout::ContainsPC(raw_obj, pc_);
+  return UntaggedCode::ContainsPC(raw_obj, pc_);
 }
 
-CodePtr Code::LookupCodeInIsolate(Isolate* isolate, uword pc) {
-  ASSERT((isolate == Isolate::Current()) || (isolate == Dart::vm_isolate()));
-  if (isolate->heap() == NULL) {
+CodePtr Code::LookupCodeInIsolateGroup(IsolateGroup* isolate_group, uword pc) {
+  ASSERT((isolate_group == IsolateGroup::Current()) ||
+         (isolate_group == Dart::vm_isolate_group()));
+  if (isolate_group->heap() == NULL) {
     return Code::null();
   }
   HeapIterationScope heap_iteration_scope(Thread::Current());
   SlowFindRawCodeVisitor visitor(pc);
-  ObjectPtr needle = isolate->heap()->FindOldObject(&visitor);
+  ObjectPtr needle = isolate_group->heap()->FindOldObject(&visitor);
   if (needle != Code::null()) {
     return static_cast<CodePtr>(needle);
   }
@@ -16452,11 +16685,11 @@
 }
 
 CodePtr Code::LookupCode(uword pc) {
-  return LookupCodeInIsolate(Isolate::Current(), pc);
+  return LookupCodeInIsolateGroup(IsolateGroup::Current(), pc);
 }
 
 CodePtr Code::LookupCodeInVmIsolate(uword pc) {
-  return LookupCodeInIsolate(Dart::vm_isolate(), pc);
+  return LookupCodeInIsolateGroup(Dart::vm_isolate_group(), pc);
 }
 
 // Given a pc and a timestamp, lookup the code.
@@ -16465,13 +16698,13 @@
   if (!code.IsNull() && (code.compile_timestamp() == timestamp) &&
       (code.PayloadStart() == pc)) {
     // Found code in isolate.
-    return code.raw();
+    return code.ptr();
   }
   code = Code::LookupCodeInVmIsolate(pc);
   if (!code.IsNull() && (code.compile_timestamp() == timestamp) &&
       (code.PayloadStart() == pc)) {
     // Found code in VM isolate.
-    return code.raw();
+    return code.ptr();
   }
   return Code::null();
 }
@@ -16479,7 +16712,7 @@
 TokenPosition Code::GetTokenIndexOfPC(uword pc) const {
   uword pc_offset = pc - PayloadStart();
   const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
-  PcDescriptors::Iterator iter(descriptors, PcDescriptorsLayout::kAnyKind);
+  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     if (iter.PcOffset() == pc_offset) {
       return iter.TokenPos();
@@ -16489,7 +16722,7 @@
 }
 
 uword Code::GetPcForDeoptId(intptr_t deopt_id,
-                            PcDescriptorsLayout::Kind kind) const {
+                            UntaggedPcDescriptors::Kind kind) const {
   const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
   PcDescriptors::Iterator iter(descriptors, kind);
   while (iter.MoveNext()) {
@@ -16506,7 +16739,7 @@
 intptr_t Code::GetDeoptIdForOsr(uword pc) const {
   uword pc_offset = pc - PayloadStart();
   const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
-  PcDescriptors::Iterator iter(descriptors, PcDescriptorsLayout::kOsrEntry);
+  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kOsrEntry);
   while (iter.MoveNext()) {
     if (iter.PcOffset() == pc_offset) {
       return iter.DeoptId();
@@ -16579,7 +16812,8 @@
 
 bool Code::IsTypeTestStubCode() const {
   auto const cid = OwnerClassId();
-  return cid == kAbstractTypeCid || cid == kTypeCid || cid == kTypeRefCid ||
+  return cid == kAbstractTypeCid || cid == kTypeCid ||
+         cid == kFunctionTypeCid || cid == kTypeRefCid ||
          cid == kTypeParameterCid;
 }
 
@@ -16588,7 +16822,7 @@
 }
 
 void Code::DisableDartCode() const {
-  DEBUG_ASSERT(IsMutatorOrAtSafepoint());
+  SafepointOperationScope safepoint(Thread::Current());
   ASSERT(IsFunctionCode());
   ASSERT(instructions() == active_instructions());
   const Code& new_code = StubCode::FixCallersTarget();
@@ -16597,7 +16831,7 @@
 }
 
 void Code::DisableStubCode() const {
-  ASSERT(Thread::Current()->IsMutatorThread());
+  SafepointOperationScope safepoint(Thread::Current());
   ASSERT(IsAllocationStubCode());
   ASSERT(instructions() == active_instructions());
   const Code& new_code = StubCode::FixAllocationStubTarget();
@@ -16612,10 +16846,10 @@
   const uword entry_point = Instructions::EntryPoint(instructions);
   const uword monomorphic_entry_point =
       Instructions::MonomorphicEntryPoint(instructions);
-  code->ptr()->entry_point_ = entry_point;
-  code->ptr()->monomorphic_entry_point_ = monomorphic_entry_point;
-  code->ptr()->unchecked_entry_point_ = entry_point + unchecked_offset;
-  code->ptr()->monomorphic_unchecked_entry_point_ =
+  code->untag()->entry_point_ = entry_point;
+  code->untag()->monomorphic_entry_point_ = monomorphic_entry_point;
+  code->untag()->unchecked_entry_point_ = entry_point + unchecked_offset;
+  code->untag()->monomorphic_unchecked_entry_point_ =
       monomorphic_entry_point + unchecked_offset;
 }
 
@@ -16624,11 +16858,20 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
 #else
-  DEBUG_ASSERT(IsMutatorOrAtSafepoint() || !is_alive());
+  ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+  SetActiveInstructionsSafe(instructions, unchecked_offset);
+#endif
+}
+
+void Code::SetActiveInstructionsSafe(const Instructions& instructions,
+                                     uint32_t unchecked_offset) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#else
   // RawInstructions are never allocated in New space and hence a
   // store buffer update is not needed here.
-  raw_ptr()->set_active_instructions(instructions.raw());
-  Code::InitializeCachedEntryPointsFrom(raw(), instructions.raw(),
+  untag()->set_active_instructions(instructions.ptr());
+  Code::InitializeCachedEntryPointsFrom(ptr(), instructions.ptr(),
                                         unchecked_offset);
 #endif
 }
@@ -16638,7 +16881,7 @@
   UNREACHABLE();
 #else
   SetActiveInstructions(Instructions::Handle(instructions()),
-                        raw_ptr()->unchecked_offset_);
+                        untag()->unchecked_offset_);
 #endif
 }
 
@@ -16721,7 +16964,7 @@
     result ^= raw;
     result.set_num_variables(num_variables);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* Context::ToCString() const {
@@ -16791,22 +17034,23 @@
     result.set_num_variables(num_variables);
     result.set_is_implicit(is_implicit);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 TokenPosition ContextScope::TokenIndexAt(intptr_t scope_index) const {
-  return TokenPosition(Smi::Value(VariableDescAddr(scope_index)->token_pos));
+  return TokenPosition::Deserialize(
+      Smi::Value(VariableDescAddr(scope_index)->token_pos));
 }
 
 void ContextScope::SetTokenIndexAt(intptr_t scope_index,
                                    TokenPosition token_pos) const {
   StoreSmi(&VariableDescAddr(scope_index)->token_pos,
-           Smi::New(token_pos.value()));
+           Smi::New(token_pos.Serialize()));
 }
 
 TokenPosition ContextScope::DeclarationTokenIndexAt(
     intptr_t scope_index) const {
-  return TokenPosition(
+  return TokenPosition::Deserialize(
       Smi::Value(VariableDescAddr(scope_index)->declaration_token_pos));
 }
 
@@ -16814,7 +17058,7 @@
     intptr_t scope_index,
     TokenPosition declaration_token_pos) const {
   StoreSmi(&VariableDescAddr(scope_index)->declaration_token_pos,
-           Smi::New(declaration_token_pos.value()));
+           Smi::New(declaration_token_pos.Serialize()));
 }
 
 StringPtr ContextScope::NameAt(intptr_t scope_index) const {
@@ -16822,7 +17066,7 @@
 }
 
 void ContextScope::SetNameAt(intptr_t scope_index, const String& name) const {
-  StorePointer(&(VariableDescAddr(scope_index)->name), name.raw());
+  StorePointer(&(VariableDescAddr(scope_index)->name), name.ptr());
 }
 
 void ContextScope::ClearFlagsAt(intptr_t scope_index) const {
@@ -16842,27 +17086,29 @@
 }
 
 bool ContextScope::IsFinalAt(intptr_t scope_index) const {
-  return GetFlagAt(scope_index, ContextScopeLayout::VariableDesc::kIsFinal);
+  return GetFlagAt(scope_index, UntaggedContextScope::VariableDesc::kIsFinal);
 }
 
 void ContextScope::SetIsFinalAt(intptr_t scope_index, bool is_final) const {
-  SetFlagAt(scope_index, ContextScopeLayout::VariableDesc::kIsFinal, is_final);
+  SetFlagAt(scope_index, UntaggedContextScope::VariableDesc::kIsFinal,
+            is_final);
 }
 
 bool ContextScope::IsLateAt(intptr_t scope_index) const {
-  return GetFlagAt(scope_index, ContextScopeLayout::VariableDesc::kIsLate);
+  return GetFlagAt(scope_index, UntaggedContextScope::VariableDesc::kIsLate);
 }
 
 void ContextScope::SetIsLateAt(intptr_t scope_index, bool is_late) const {
-  SetFlagAt(scope_index, ContextScopeLayout::VariableDesc::kIsLate, is_late);
+  SetFlagAt(scope_index, UntaggedContextScope::VariableDesc::kIsLate, is_late);
 }
 
 bool ContextScope::IsConstAt(intptr_t scope_index) const {
-  return GetFlagAt(scope_index, ContextScopeLayout::VariableDesc::kIsConst);
+  return GetFlagAt(scope_index, UntaggedContextScope::VariableDesc::kIsConst);
 }
 
 void ContextScope::SetIsConstAt(intptr_t scope_index, bool is_const) const {
-  SetFlagAt(scope_index, ContextScopeLayout::VariableDesc::kIsConst, is_const);
+  SetFlagAt(scope_index, UntaggedContextScope::VariableDesc::kIsConst,
+            is_const);
 }
 
 intptr_t ContextScope::LateInitOffsetAt(intptr_t scope_index) const {
@@ -16882,7 +17128,7 @@
 
 void ContextScope::SetTypeAt(intptr_t scope_index,
                              const AbstractType& type) const {
-  StorePointer(&(VariableDescAddr(scope_index)->type), type.raw());
+  StorePointer(&(VariableDescAddr(scope_index)->type), type.ptr());
 }
 
 InstancePtr ContextScope::ConstValueAt(intptr_t scope_index) const {
@@ -16893,7 +17139,7 @@
 void ContextScope::SetConstValueAt(intptr_t scope_index,
                                    const Instance& value) const {
   ASSERT(IsConstAt(scope_index));
-  StorePointer(&(VariableDescAddr(scope_index)->value), value.raw());
+  StorePointer(&(VariableDescAddr(scope_index)->value), value.ptr());
 }
 
 intptr_t ContextScope::ContextIndexAt(intptr_t scope_index) const {
@@ -16935,30 +17181,30 @@
 }
 
 ArrayPtr MegamorphicCache::buckets() const {
-  return raw_ptr()->buckets();
+  return untag()->buckets();
 }
 
 void MegamorphicCache::set_buckets(const Array& buckets) const {
-  raw_ptr()->set_buckets(buckets.raw());
+  untag()->set_buckets(buckets.ptr());
 }
 
 // Class IDs in the table are smi-tagged, so we use a smi-tagged mask
 // and target class ID to avoid untagging (on each iteration of the
 // test loop) in generated code.
 intptr_t MegamorphicCache::mask() const {
-  return Smi::Value(raw_ptr()->mask());
+  return Smi::Value(untag()->mask());
 }
 
 void MegamorphicCache::set_mask(intptr_t mask) const {
-  raw_ptr()->set_mask(Smi::New(mask));
+  untag()->set_mask(Smi::New(mask));
 }
 
 intptr_t MegamorphicCache::filled_entry_count() const {
-  return raw_ptr()->filled_entry_count_;
+  return untag()->filled_entry_count_;
 }
 
 void MegamorphicCache::set_filled_entry_count(intptr_t count) const {
-  StoreNonPointer(&raw_ptr()->filled_entry_count_, count);
+  StoreNonPointer(&untag()->filled_entry_count_, count);
 }
 
 MegamorphicCachePtr MegamorphicCache::New() {
@@ -16971,7 +17217,7 @@
     result ^= raw;
   }
   result.set_filled_entry_count(0);
-  return result.raw();
+  return result.ptr();
 }
 
 MegamorphicCachePtr MegamorphicCache::New(const String& target_name,
@@ -16996,7 +17242,7 @@
   result.set_target_name(target_name);
   result.set_arguments_descriptor(arguments_descriptor);
   result.set_filled_entry_count(0);
-  return result.raw();
+  return result.ptr();
 }
 
 void MegamorphicCache::EnsureContains(const Smi& class_id,
@@ -17013,10 +17259,10 @@
       const auto& function = Function::Cast(target);
       const auto& entry_point = Smi::Handle(
           Smi::FromAlignedAddress(Code::EntryPointOf(function.CurrentCode())));
-      ASSERT(LookupLocked(class_id) == entry_point.raw());
+      ASSERT(LookupLocked(class_id) == entry_point.ptr());
     }
   } else {
-    ASSERT(LookupLocked(class_id) == target.raw());
+    ASSERT(LookupLocked(class_id) == target.ptr());
   }
 #endif  // define(DEBUG)
 }
@@ -17171,26 +17417,26 @@
     result ^= raw;
   }
   result.set_cache(Array::Handle(cached_array_));
-  return result.raw();
+  return result.ptr();
 }
 
 ArrayPtr SubtypeTestCache::cache() const {
   // We rely on the fact that any loads from the array are dependent loads and
   // avoid the load-acquire barrier here.
-  return raw_ptr()->cache<std::memory_order_relaxed>();
+  return untag()->cache<std::memory_order_relaxed>();
 }
 
 void SubtypeTestCache::set_cache(const Array& value) const {
   // We have to ensure that initializing stores to the array are available
   // when releasing the pointer to the array pointer.
   // => We have to use store-release here.
-  raw_ptr()->set_cache<std::memory_order_release>(value.raw());
+  untag()->set_cache<std::memory_order_release>(value.ptr());
 }
 
 intptr_t SubtypeTestCache::NumberOfChecks() const {
   NoSafepointScope no_safepoint;
   // Do not count the sentinel;
-  return (Smi::Value(cache()->ptr()->length()) / kTestEntryLength) - 1;
+  return (Smi::Value(cache()->untag()->length()) / kTestEntryLength) - 1;
 }
 
 void SubtypeTestCache::AddCheck(
@@ -17298,16 +17544,16 @@
   for (intptr_t i = 0; i < last_index; i++) {
     const auto entry = entries[i];
     if (entry.Get<kInstanceClassIdOrFunction>() ==
-            instance_class_id_or_function.raw() &&
-        entry.Get<kDestinationType>() == destination_type.raw() &&
-        entry.Get<kInstanceTypeArguments>() == instance_type_arguments.raw() &&
+            instance_class_id_or_function.ptr() &&
+        entry.Get<kDestinationType>() == destination_type.ptr() &&
+        entry.Get<kInstanceTypeArguments>() == instance_type_arguments.ptr() &&
         entry.Get<kInstantiatorTypeArguments>() ==
-            instantiator_type_arguments.raw() &&
-        entry.Get<kFunctionTypeArguments>() == function_type_arguments.raw() &&
+            instantiator_type_arguments.ptr() &&
+        entry.Get<kFunctionTypeArguments>() == function_type_arguments.ptr() &&
         entry.Get<kInstanceParentFunctionTypeArguments>() ==
-            instance_parent_function_type_arguments.raw() &&
+            instance_parent_function_type_arguments.ptr() &&
         entry.Get<kInstanceDelayedFunctionTypeArguments>() ==
-            instance_delayed_type_arguments.raw()) {
+            instance_delayed_type_arguments.ptr()) {
       if (index != nullptr) {
         *index = i;
       }
@@ -17355,14 +17601,14 @@
   buffer->Printf(
       "[ %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px
       ", %#" Px " ]",
-      static_cast<uword>(instance_class_id_or_function.raw()),
-      static_cast<uword>(destination_type.raw()),
-      static_cast<uword>(instance_type_arguments.raw()),
-      static_cast<uword>(instantiator_type_arguments.raw()),
-      static_cast<uword>(function_type_arguments.raw()),
-      static_cast<uword>(instance_parent_function_type_arguments.raw()),
-      static_cast<uword>(instance_delayed_type_arguments.raw()),
-      static_cast<uword>(result.raw()));
+      static_cast<uword>(instance_class_id_or_function.ptr()),
+      static_cast<uword>(destination_type.ptr()),
+      static_cast<uword>(instance_type_arguments.ptr()),
+      static_cast<uword>(instantiator_type_arguments.ptr()),
+      static_cast<uword>(function_type_arguments.ptr()),
+      static_cast<uword>(instance_parent_function_type_arguments.ptr()),
+      static_cast<uword>(instance_delayed_type_arguments.ptr()),
+      static_cast<uword>(result.ptr()));
   if (instance_class_id_or_function.IsSmi()) {
     buffer->Printf("%sclass id: %" Pd "", separator,
                    Smi::Cast(instance_class_id_or_function).Value());
@@ -17380,11 +17626,11 @@
           zone, destination_type.InstantiateFrom(instantiator_type_arguments,
                                                  function_type_arguments,
                                                  kAllFree, Heap::kNew));
-      const auto& type_class = Class::Handle(zone, test_type.type_class());
+      const auto type_class_id = test_type.type_class_id();
       buffer->Printf("%sinstantiated type: %s", separator,
                      test_type.ToCString());
-      buffer->Printf("%sinstantiated type class id: %" Pd "", separator,
-                     type_class.id());
+      buffer->Printf("%sinstantiated type class id: %d", separator,
+                     type_class_id);
     }
   }
   if (!instance_type_arguments.IsNull()) {
@@ -17453,21 +17699,21 @@
   result.set_id(kIllegalId);
   result.set_loaded(false);
   result.set_load_outstanding(false);
-  return result.raw();
+  return result.ptr();
 }
 
 LoadingUnitPtr LoadingUnit::parent() const {
-  return raw_ptr()->parent();
+  return untag()->parent();
 }
 void LoadingUnit::set_parent(const LoadingUnit& value) const {
-  raw_ptr()->set_parent(value.raw());
+  untag()->set_parent(value.ptr());
 }
 
 ArrayPtr LoadingUnit::base_objects() const {
-  return raw_ptr()->base_objects();
+  return untag()->base_objects();
 }
 void LoadingUnit::set_base_objects(const Array& value) const {
-  raw_ptr()->set_base_objects(value.raw());
+  untag()->set_base_objects(value.ptr());
 }
 
 const char* LoadingUnit::ToCString() const {
@@ -17481,8 +17727,8 @@
   return Isolate::Current()->CallDeferredLoadHandler(id());
 }
 
-void LoadingUnit::CompleteLoad(const String& error_message,
-                               bool transient_error) const {
+ObjectPtr LoadingUnit::CompleteLoad(const String& error_message,
+                                    bool transient_error) const {
   ASSERT(!loaded());
   ASSERT(load_outstanding());
   set_loaded(error_message.IsNull());
@@ -17496,12 +17742,7 @@
   args.SetAt(0, Smi::Handle(Smi::New(id())));
   args.SetAt(1, error_message);
   args.SetAt(2, Bool::Get(transient_error));
-  const Object& result = Object::Handle(DartEntry::InvokeFunction(func, args));
-  if (result.IsUnwindError()) {
-    Thread::Current()->set_sticky_error(Error::Cast(result));
-  } else if (result.IsError()) {
-    UNREACHABLE();
-  }
+  return DartEntry::InvokeFunction(func, args);
 }
 
 const char* Error::ToErrorCString() const {
@@ -17545,11 +17786,11 @@
     result ^= raw;
   }
   result.set_message(message);
-  return result.raw();
+  return result.ptr();
 }
 
 void ApiError::set_message(const String& message) const {
-  raw_ptr()->set_message(message.raw());
+  untag()->set_message(message.ptr());
 }
 
 const char* ApiError::ToErrorCString() const {
@@ -17591,7 +17832,7 @@
   result.set_kind(kind);
   result.set_message(
       String::Handle(String::NewFormattedV(format, args, space)));
-  return result.raw();
+  return result.ptr();
 }
 
 LanguageErrorPtr LanguageError::NewFormatted(const Error& prev_error,
@@ -17625,36 +17866,36 @@
   }
   result.set_formatted_message(formatted_message);
   result.set_kind(kind);
-  return result.raw();
+  return result.ptr();
 }
 
 void LanguageError::set_previous_error(const Error& value) const {
-  raw_ptr()->set_previous_error(value.raw());
+  untag()->set_previous_error(value.ptr());
 }
 
 void LanguageError::set_script(const Script& value) const {
-  raw_ptr()->set_script(value.raw());
+  untag()->set_script(value.ptr());
 }
 
 void LanguageError::set_token_pos(TokenPosition token_pos) const {
   ASSERT(!token_pos.IsClassifying());
-  StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
+  StoreNonPointer(&untag()->token_pos_, token_pos);
 }
 
 void LanguageError::set_report_after_token(bool value) {
-  StoreNonPointer(&raw_ptr()->report_after_token_, value);
+  StoreNonPointer(&untag()->report_after_token_, value);
 }
 
 void LanguageError::set_kind(uint8_t value) const {
-  StoreNonPointer(&raw_ptr()->kind_, value);
+  StoreNonPointer(&untag()->kind_, value);
 }
 
 void LanguageError::set_message(const String& value) const {
-  raw_ptr()->set_message(value.raw());
+  untag()->set_message(value.ptr());
 }
 
 void LanguageError::set_formatted_message(const String& value) const {
-  raw_ptr()->set_formatted_message(value.raw());
+  untag()->set_formatted_message(value.ptr());
 }
 
 StringPtr LanguageError::FormatMessage() const {
@@ -17671,7 +17912,7 @@
         String::Handle(String::New(prev_error.ToErrorCString())), result);
   }
   set_formatted_message(result);
-  return result.raw();
+  return result.ptr();
 }
 
 const char* LanguageError::ToErrorCString() const {
@@ -17698,7 +17939,7 @@
   }
   result.set_exception(exception);
   result.set_stacktrace(stacktrace);
-  return result.raw();
+  return result.ptr();
 }
 
 UnhandledExceptionPtr UnhandledException::New(Heap::Space space) {
@@ -17712,27 +17953,28 @@
   }
   result.set_exception(Object::null_instance());
   result.set_stacktrace(StackTrace::Handle());
-  return result.raw();
+  return result.ptr();
 }
 
 void UnhandledException::set_exception(const Instance& exception) const {
-  raw_ptr()->set_exception(exception.raw());
+  untag()->set_exception(exception.ptr());
 }
 
 void UnhandledException::set_stacktrace(const Instance& stacktrace) const {
-  raw_ptr()->set_stacktrace(stacktrace.raw());
+  untag()->set_stacktrace(stacktrace.ptr());
 }
 
 const char* UnhandledException::ToErrorCString() const {
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  auto isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   NoReloadScope no_reload_scope(isolate, thread);
   HANDLESCOPE(thread);
   Object& strtmp = Object::Handle();
   const char* exc_str;
-  if (exception() == isolate->object_store()->out_of_memory()) {
+  if (exception() == isolate_group->object_store()->out_of_memory()) {
     exc_str = "Out of Memory";
-  } else if (exception() == isolate->object_store()->stack_overflow()) {
+  } else if (exception() == isolate_group->object_store()->stack_overflow()) {
     exc_str = "Stack Overflow";
   } else {
     const Instance& exc = Instance::Handle(exception());
@@ -17769,15 +18011,15 @@
   }
   result.set_message(message);
   result.set_is_user_initiated(false);
-  return result.raw();
+  return result.ptr();
 }
 
 void UnwindError::set_message(const String& message) const {
-  raw_ptr()->set_message(message.raw());
+  untag()->set_message(message.ptr());
 }
 
 void UnwindError::set_is_user_initiated(bool value) const {
-  StoreNonPointer(&raw_ptr()->is_user_initiated_, value);
+  StoreNonPointer(&untag()->is_user_initiated_, value);
 }
 
 const char* UnwindError::ToErrorCString() const {
@@ -17811,7 +18053,7 @@
     // The getter must correspond to either an entry-point field or a getter
     // method explicitly marked.
     Field& field = Field::Handle(zone);
-    if (function.kind() == FunctionLayout::kImplicitGetter) {
+    if (function.kind() == UntaggedFunction::kImplicitGetter) {
       field = function.accessor_field();
     }
     if (!field.IsNull()) {
@@ -17872,7 +18114,7 @@
     // The setter must correspond to either an entry-point field or a setter
     // method explicitly marked.
     Field& field = Field::Handle(zone);
-    if (setter.kind() == FunctionLayout::kImplicitSetter) {
+    if (setter.kind() == UntaggedFunction::kImplicitSetter) {
       field = setter.accessor_field();
     }
     if (!field.IsNull()) {
@@ -17934,7 +18176,7 @@
       if (check_is_entrypoint) {
         CHECK_ERROR(EntryPointFieldInvocationError(function_name));
       }
-      ASSERT(function.kind() != FunctionLayout::kMethodExtractor);
+      ASSERT(function.kind() != UntaggedFunction::kMethodExtractor);
       // Invoke the getter.
       const int kNumArgs = 1;
       const Array& getter_args = Array::Handle(zone, Array::New(kNumArgs));
@@ -17947,7 +18189,7 @@
                                        getter_args, getter_args_descriptor,
                                        respect_reflectable, inst_type_args));
       if (getter_result.IsError()) {
-        return getter_result.raw();
+        return getter_result.ptr();
       }
       // Replace the closure as the receiver in the arguments list.
       args.SetAt(0, getter_result);
@@ -17994,7 +18236,7 @@
 }
 
 bool Instance::CanonicalizeEquals(const Instance& other) const {
-  if (this->raw() == other.raw()) {
+  if (this->ptr() == other.ptr()) {
     return true;  // "===".
   }
 
@@ -18012,8 +18254,8 @@
     if (instance_size != other_instance_size) {
       return false;
     }
-    uword this_addr = reinterpret_cast<uword>(this->raw_ptr());
-    uword other_addr = reinterpret_cast<uword>(other.raw_ptr());
+    uword this_addr = reinterpret_cast<uword>(this->untag());
+    uword other_addr = reinterpret_cast<uword>(other.untag());
     for (intptr_t offset = Instance::NextFieldOffset(); offset < instance_size;
          offset += kWordSize) {
       if ((*reinterpret_cast<ObjectPtr*>(this_addr + offset)) !=
@@ -18030,7 +18272,7 @@
     return 2011;  // Matches null_patch.dart.
   }
   Thread* thread = Thread::Current();
-  uint32_t hash = thread->heap()->GetCanonicalHash(raw());
+  uint32_t hash = thread->heap()->GetCanonicalHash(ptr());
   if (hash != 0) {
     return hash;
   }
@@ -18039,11 +18281,11 @@
   const intptr_t instance_size = SizeFromClass();
   ASSERT(instance_size != 0);
   hash = instance_size / kWordSize;
-  uword this_addr = reinterpret_cast<uword>(this->raw_ptr());
+  uword this_addr = reinterpret_cast<uword>(this->untag());
   Instance& member = Instance::Handle();
 
   const auto unboxed_fields_bitmap =
-      thread->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
+      thread->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
           GetClassId());
 
   for (intptr_t offset = Instance::NextFieldOffset();
@@ -18064,7 +18306,7 @@
     }
   }
   hash = FinalizeHash(hash, String::kHashBits);
-  thread->heap()->SetCanonicalHash(raw(), hash);
+  thread->heap()->SetCanonicalHash(ptr(), hash);
   return hash;
 }
 
@@ -18113,8 +18355,8 @@
   } else {
 #if defined(DEBUG)
     // Make sure that we are not missing any fields.
-    CheckForPointers has_pointers(Isolate::Current()->group());
-    this->raw()->ptr()->VisitPointers(&has_pointers);
+    CheckForPointers has_pointers(IsolateGroup::Current());
+    this->ptr()->untag()->VisitPointers(&has_pointers);
     ASSERT(!has_pointers.has_pointers());
 #endif  // DEBUG
   }
@@ -18132,7 +18374,7 @@
 
 InstancePtr Instance::CanonicalizeLocked(Thread* thread) const {
   if (this->IsCanonical()) {
-    return this->raw();
+    return this->ptr();
   }
   ASSERT(!IsNull());
   CanonicalizeFieldsLocked(thread);
@@ -18141,14 +18383,14 @@
   Instance& result =
       Instance::Handle(zone, cls.LookupCanonicalInstance(zone, *this));
   if (!result.IsNull()) {
-    return result.raw();
+    return result.ptr();
   }
   if (IsNew()) {
     ASSERT((thread->isolate() == Dart::vm_isolate()) || !InVMIsolateHeap());
     // Create a canonical object in old space.
     result ^= Object::Clone(*this, Heap::kOld);
   } else {
-    result = this->raw();
+    result = this->ptr();
   }
   ASSERT(result.IsOld());
   result.SetCanonical();
@@ -18163,7 +18405,7 @@
   SafepointMutexLocker ml(
       thread->isolate_group()->constant_canonicalization_mutex());
   result ^= cls.LookupCanonicalInstance(zone, *this);
-  return (result.raw() == this->raw());
+  return (result.ptr() == this->ptr());
 }
 #endif  // DEBUG
 
@@ -18218,7 +18460,7 @@
   } else {
     field.RecordStore(value);
     const Object* stored_value = field.CloneForUnboxed(value);
-    StorePointer(FieldAddr(field), stored_value->raw());
+    StorePointer(FieldAddr(field), stored_value->ptr());
   }
 }
 
@@ -18236,14 +18478,13 @@
     cls.EnsureDeclarationLoaded();
   }
   if (cls.IsClosureClass()) {
-    Function& signature = Function::Handle(
-        zone, Closure::Cast(*this).GetInstantiatedSignature(zone));
-    Type& type = Type::Handle(zone, signature.SignatureType());
-    if (!type.IsFinalized()) {
-      type.SetIsFinalized();
+    FunctionType& signature = FunctionType::Handle(
+        Closure::Cast(*this).GetInstantiatedSignature(zone));
+    if (!signature.IsFinalized()) {
+      signature.SetIsFinalized();
     }
-    type ^= type.Canonicalize(thread, nullptr);
-    return type.raw();
+    signature ^= signature.Canonicalize(thread, nullptr);
+    return signature.ptr();
   }
   Type& type = Type::Handle(zone);
   if (!cls.IsGeneric()) {
@@ -18254,12 +18495,11 @@
     if (cls.NumTypeArguments() > 0) {
       type_arguments = GetTypeArguments();
     }
-    type = Type::New(cls, type_arguments, TokenPosition::kNoSource,
-                     Nullability::kNonNullable, space);
+    type = Type::New(cls, type_arguments, Nullability::kNonNullable, space);
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
   }
-  return type.raw();
+  return type.ptr();
 }
 
 TypeArgumentsPtr Instance::GetTypeArguments() const {
@@ -18269,7 +18509,7 @@
   ASSERT(field_offset != Class::kNoTypeArguments);
   TypeArguments& type_arguments = TypeArguments::Handle();
   type_arguments ^= *FieldAddrAtOffset(field_offset);
-  return type_arguments.raw();
+  return type_arguments.ptr();
 }
 
 void Instance::SetTypeArguments(const TypeArguments& value) const {
@@ -18328,7 +18568,7 @@
   // In weak mode type casts, whether in legacy or opted-in libraries, the null
   // instance is detected and handled in inlined code and therefore cannot be
   // encountered here as a Dart null receiver.
-  ASSERT(Isolate::Current()->use_strict_null_safety_checks() || !IsNull());
+  ASSERT(IsolateGroup::Current()->use_strict_null_safety_checks() || !IsNull());
   // In strong mode, compute NNBD_SUBTYPE(runtimeType, other).
   // In weak mode, compute LEGACY_SUBTYPE(runtimeType, other).
   return RuntimeTypeIsSubtypeOf(other, other_instantiator_type_arguments,
@@ -18375,11 +18615,10 @@
 // stub_code_compiler.cc if any changes are made.
 bool Instance::NullIsAssignableTo(const AbstractType& other) {
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
+  auto isolate_group = thread->isolate_group();
 
   // In weak mode, Null is a bottom type (according to LEGACY_SUBTYPE).
-  if (!isolate->use_strict_null_safety_checks()) {
+  if (!isolate_group->use_strict_null_safety_checks()) {
     return true;
   }
   // "Left Null" rule: null is assignable when destination type is either
@@ -18390,7 +18629,7 @@
   }
   if (other.IsFutureOrType()) {
     return NullIsAssignableTo(
-        AbstractType::Handle(zone, other.UnwrapFutureOr()));
+        AbstractType::Handle(thread->zone(), other.UnwrapFutureOr()));
   }
   return false;
 }
@@ -18401,25 +18640,25 @@
     const TypeArguments& other_function_type_arguments) const {
   ASSERT(other.IsFinalized());
   ASSERT(!other.IsTypeRef());  // Must be dereferenced at compile time.
-  ASSERT(raw() != Object::sentinel().raw());
+  ASSERT(ptr() != Object::sentinel().ptr());
   // Instance may not have runtimeType dynamic, void, or Never.
   if (other.IsTopTypeForSubtyping()) {
     return true;
   }
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
+  auto isolate_group = thread->isolate_group();
   // In weak testing mode, Null type is a subtype of any type.
-  if (IsNull() && !isolate->use_strict_null_safety_checks()) {
+  if (IsNull() && !isolate_group->use_strict_null_safety_checks()) {
     return true;
   }
+  Zone* zone = thread->zone();
   const Class& cls = Class::Handle(zone, clazz());
   if (cls.IsClosureClass()) {
     if (other.IsDartFunctionType() || other.IsDartClosureType() ||
         other.IsObjectType()) {
       return true;
     }
-    AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
+    AbstractType& instantiated_other = AbstractType::Handle(zone, other.ptr());
     if (!other.IsInstantiated()) {
       instantiated_other = other.InstantiateFrom(
           other_instantiator_type_arguments, other_function_type_arguments,
@@ -18438,11 +18677,9 @@
     if (!instantiated_other.IsFunctionType()) {
       return false;
     }
-    Function& other_signature =
-        Function::Handle(zone, Type::Cast(instantiated_other).signature());
-    const Function& sig_fun =
-        Function::Handle(Closure::Cast(*this).GetInstantiatedSignature(zone));
-    return sig_fun.IsSubtypeOf(other_signature, Heap::kOld);
+    const FunctionType& sig = FunctionType::Handle(
+        Closure::Cast(*this).GetInstantiatedSignature(zone));
+    return sig.IsSubtypeOf(FunctionType::Cast(instantiated_other), Heap::kOld);
   }
   TypeArguments& type_arguments = TypeArguments::Handle(zone);
   if (cls.NumTypeArguments() > 0) {
@@ -18459,7 +18696,7 @@
     ASSERT(type_arguments.IsNull() ||
            (type_arguments.Length() >= cls.NumTypeArguments()));
   }
-  AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
+  AbstractType& instantiated_other = AbstractType::Handle(zone, other.ptr());
   if (!other.IsInstantiated()) {
     instantiated_other = other.InstantiateFrom(
         other_instantiator_type_arguments, other_function_type_arguments,
@@ -18471,19 +18708,20 @@
       return true;
     }
   }
-  if (!instantiated_other.IsType()) {
-    return false;
-  }
   if (IsNull()) {
-    ASSERT(isolate->use_strict_null_safety_checks());
+    ASSERT(isolate_group->use_strict_null_safety_checks());
     if (instantiated_other.IsNullType()) {
       return true;
     }
     if (RuntimeTypeIsSubtypeOfFutureOr(zone, instantiated_other)) {
       return true;
     }
+    // At this point, instantiated_other can be a function type.
     return !instantiated_other.IsNonNullable();
   }
+  if (!instantiated_other.IsType()) {
+    return false;
+  }
   // RuntimeType of non-null instance is non-nullable, so there is no need to
   // check nullability of other type.
   return Class::IsSubtypeOf(cls, type_arguments, Nullability::kNonNullable,
@@ -18521,11 +18759,11 @@
 bool Instance::OperatorEquals(const Instance& other) const {
   // TODO(koda): Optimize for all builtin classes and all classes
   // that do not override operator==.
-  return DartLibraryCalls::Equals(*this, other) == Object::bool_true().raw();
+  return DartLibraryCalls::Equals(*this, other) == Object::bool_true().ptr();
 }
 
 bool Instance::IsIdenticalTo(const Instance& other) const {
-  if (raw() == other.raw()) return true;
+  if (ptr() == other.ptr()) return true;
   if (IsInteger() && other.IsInteger()) {
     return Integer::Cast(*this).Equals(other);
   }
@@ -18542,7 +18780,7 @@
   if (native_fields == TypedData::null()) {
     return NULL;
   }
-  return reinterpret_cast<intptr_t*>(native_fields->ptr()->data());
+  return reinterpret_cast<intptr_t*>(native_fields->untag()->data());
 }
 
 void Instance::SetNativeField(int index, intptr_t value) const {
@@ -18551,7 +18789,7 @@
   if (native_fields.IsNull()) {
     // Allocate backing storage for the native fields.
     native_fields = TypedData::New(kIntPtrCid, NumNativeFields());
-    StorePointer(NativeFieldsAddr(), native_fields.raw());
+    StorePointer(NativeFieldsAddr(), native_fields.ptr());
   }
   intptr_t byte_offset = index * sizeof(intptr_t);
   TypedData::Cast(native_fields).SetIntPtr(byte_offset, value);
@@ -18565,7 +18803,7 @@
   if (native_fields.IsNull()) {
     // Allocate backing storage for the native fields.
     native_fields = TypedData::New(kIntPtrCid, NumNativeFields());
-    StorePointer(NativeFieldsAddr(), native_fields.raw());
+    StorePointer(NativeFieldsAddr(), native_fields.ptr());
   }
   for (uint16_t i = 0; i < num_native_fields; i++) {
     intptr_t byte_offset = i * sizeof(intptr_t);
@@ -18590,7 +18828,7 @@
     return false;
   }
   if (function != nullptr) {
-    *function = call_function.raw();
+    *function = call_function.ptr();
   }
   return true;
 }
@@ -18675,13 +18913,13 @@
 const char* Instance::ToCString() const {
   if (IsNull()) {
     return "null";
-  } else if (raw() == Object::sentinel().raw()) {
+  } else if (ptr() == Object::sentinel().ptr()) {
     return "sentinel";
-  } else if (raw() == Object::transition_sentinel().raw()) {
+  } else if (ptr() == Object::transition_sentinel().ptr()) {
     return "transition_sentinel";
-  } else if (raw() == Object::unknown_constant().raw()) {
+  } else if (ptr() == Object::unknown_constant().ptr()) {
     return "unknown_constant";
-  } else if (raw() == Object::non_constant().raw()) {
+  } else if (ptr() == Object::non_constant().ptr()) {
     return "non_constant";
   } else if (Thread::Current()->no_safepoint_scope_depth() > 0) {
     // Can occur when running disassembler.
@@ -18722,12 +18960,6 @@
   UNREACHABLE();
 }
 
-TokenPosition AbstractType::token_pos() const {
-  // AbstractType is an abstract class.
-  UNREACHABLE();
-  return TokenPosition::kNoSource;
-}
-
 Nullability AbstractType::nullability() const {
   // AbstractType is an abstract class.
   UNREACHABLE();
@@ -18744,7 +18976,7 @@
   Zone* zone = thread->zone();
 
   // In weak mode null can be assigned to any type.
-  if (!thread->isolate()->null_safety()) {
+  if (!thread->isolate_group()->null_safety()) {
     return false;
   }
 
@@ -18779,14 +19011,17 @@
     result_nullability = Nullability::kLegacy;
   } else {
     // Keep arg nullability.
-    return raw();
+    return ptr();
   }
   if (arg_nullability == result_nullability) {
-    return raw();
+    return ptr();
   }
   if (IsType()) {
     return Type::Cast(*this).ToNullability(result_nullability, space);
   }
+  if (IsFunctionType()) {
+    return FunctionType::Cast(*this).ToNullability(result_nullability, space);
+  }
   if (IsTypeParameter()) {
     return TypeParameter::Cast(*this).ToNullability(result_nullability, space);
   }
@@ -18804,11 +19039,11 @@
         AbstractType::Handle(zone, UnwrapFutureOr());
     const classid_t cid = unwrapped_type.type_class_id();
     if (cid == kDynamicCid || cid == kVoidCid) {
-      return unwrapped_type.raw();
+      return unwrapped_type.ptr();
     }
     if (cid == kInstanceCid) {
       if (IsNonNullable()) {
-        return unwrapped_type.raw();
+        return unwrapped_type.ptr();
       }
       if (IsNullable() || unwrapped_type.IsNullable()) {
         return Type::Cast(unwrapped_type)
@@ -18818,14 +19053,14 @@
           .ToNullability(Nullability::kLegacy, space);
     }
     if (cid == kNeverCid && unwrapped_type.IsNonNullable()) {
-      ObjectStore* object_store = Isolate::Current()->object_store();
+      ObjectStore* object_store = IsolateGroup::Current()->object_store();
       const Type& future_never_type =
           Type::Handle(zone, object_store->non_nullable_future_never_type());
       ASSERT(!future_never_type.IsNull());
       return future_never_type.ToNullability(nullability(), space);
     }
     if (cid == kNullCid) {
-      ObjectStore* object_store = Isolate::Current()->object_store();
+      ObjectStore* object_store = IsolateGroup::Current()->object_store();
       ASSERT(object_store->nullable_future_null_type() != Type::null());
       return object_store->nullable_future_null_type();
     }
@@ -18833,7 +19068,7 @@
       return Type::Cast(*this).ToNullability(Nullability::kNonNullable, space);
     }
   }
-  return raw();
+  return ptr();
 }
 
 bool AbstractType::IsInstantiated(Genericity genericity,
@@ -18874,7 +19109,14 @@
   return false;
 }
 
-bool AbstractType::IsRecursive() const {
+bool AbstractType::IsRecursive(TrailPtr trail) const {
+  // AbstractType is an abstract class.
+  UNREACHABLE();
+  return false;
+}
+
+bool AbstractType::RequireConstCanonicalTypeErasure(Zone* zone,
+                                                    TrailPtr trail) const {
   // AbstractType is an abstract class.
   UNREACHABLE();
   return false;
@@ -18912,9 +19154,9 @@
   for (intptr_t i = 0; i < len; i += 2) {
     ASSERT(trail->At(i).IsZoneHandle());
     ASSERT(trail->At(i + 1).IsZoneHandle());
-    if (trail->At(i).raw() == this->raw()) {
+    if (trail->At(i).ptr() == this->ptr()) {
       ASSERT(!trail->At(i + 1).IsNull());
-      return trail->At(i + 1).raw();
+      return trail->At(i + 1).ptr();
     }
   }
   return AbstractType::null();
@@ -18937,7 +19179,7 @@
   } else {
     const intptr_t len = (*trail)->length();
     for (intptr_t i = 0; i < len; i++) {
-      if ((*trail)->At(i).raw() == this->raw()) {
+      if ((*trail)->At(i).ptr() == this->ptr()) {
         return true;
       }
     }
@@ -18959,9 +19201,9 @@
     // one exception, when the class of the 'this' type implements the 'call'
     // method, thereby possibly creating a recursive type (see regress_29405).
     for (intptr_t i = 0; i < len; i += 2) {
-      if ((((*trail)->At(i).raw() == this->raw()) ||
+      if ((((*trail)->At(i).ptr() == this->ptr()) ||
            (buddy_is_typeref && (*trail)->At(i).Equals(*this))) &&
-          (((*trail)->At(i + 1).raw() == buddy.raw()) ||
+          (((*trail)->At(i + 1).ptr() == buddy.ptr()) ||
            (this_is_typeref && (*trail)->At(i + 1).Equals(buddy)))) {
         return true;
       }
@@ -19007,7 +19249,7 @@
   GrowableHandlePtrArray<const String> pieces(zone, 5 * (len / 3));
   for (intptr_t i = 0; i < len; i += 3) {
     // Only print URIs that have been marked.
-    if (uris->At(i + 2).raw() == Symbols::print().raw()) {
+    if (uris->At(i + 2).ptr() == Symbols::print().ptr()) {
       pieces.Add(Symbols::TwoSpaces());
       pieces.Add(uris->At(i));
       pieces.Add(Symbols::SpaceIsFromSpace());
@@ -19053,73 +19295,43 @@
   return Symbols::New(thread, printer.buffer());
 }
 
-void AbstractType::PrintName(
-    NameVisibility name_visibility,
-    BaseTextBuffer* printer,
-    NameDisambiguation name_disambiguation /* = NameDisambiguation::kNo */)
-    const {
+void AbstractType::PrintName(NameVisibility name_visibility,
+                             BaseTextBuffer* printer) const {
+  if (IsTypeRef()) {
+    // Cycles via base class type arguments are not a problem (not printed).
+    const AbstractType& ref_type =
+        AbstractType::Handle(TypeRef::Cast(*this).type());
+    ref_type.PrintName(name_visibility, printer);
+    return;
+  }
   ASSERT(name_visibility != kScrubbedName);
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Class& cls = Class::Handle(zone);
   String& name_str = String::Handle(zone);
   if (IsTypeParameter()) {
-    const TypeParameter& param = TypeParameter::Cast(*this);
-
-    // Type parameters might have the same name but be owned by different
-    // entities. If we want to disambiguate them we need to prefix
-    // type parameter name with the name of its owner.
-    if (name_disambiguation == NameDisambiguation::kYes) {
-      cls = param.parameterized_class();
-      if (cls.raw() != Class::null()) {
-        printer->AddString(cls.NameCString(name_visibility));
-        printer->AddString("::");
-      } else if (param.parameterized_function() != Function::null()) {
-        const Function& func =
-            Function::Handle(zone, param.parameterized_function());
-        func.PrintName(
-            NameFormattingParams(name_visibility, name_disambiguation),
-            printer);
-        printer->AddString("::");
-      }
-    }
-
-    name_str = param.name();
-    printer->AddString(name_str.ToCString());
+    const TypeParameter& type_param = TypeParameter::Cast(*this);
+    printer->AddString(String::Handle(type_param.name()).ToCString());
     printer->AddString(NullabilitySuffix(name_visibility));
     return;
   }
+  if (IsFunctionType()) {
+    const char* suffix = NullabilitySuffix(name_visibility);
+    if (suffix[0] != '\0') {
+      printer->AddString("(");
+    }
+    FunctionType::Cast(*this).Print(name_visibility, printer);
+    if (suffix[0] != '\0') {
+      printer->AddString(")");
+      printer->AddString(suffix);
+    }
+    return;
+  }
   const TypeArguments& args = TypeArguments::Handle(zone, arguments());
   const intptr_t num_args = args.IsNull() ? 0 : args.Length();
   intptr_t first_type_param_index;
   intptr_t num_type_params;  // Number of type parameters to print.
   cls = type_class();
-  if (IsFunctionType()) {
-    const Function& signature_function =
-        Function::Handle(zone, Type::Cast(*this).signature());
-    if (!cls.IsTypedefClass()) {
-      const char* suffix = NullabilitySuffix(name_visibility);
-      if (suffix[0] != '\0') {
-        printer->AddString("(");
-      }
-      signature_function.PrintSignature(name_visibility, printer);
-      if (suffix[0] != '\0') {
-        printer->AddString(")");
-        printer->AddString(suffix);
-      }
-      return;
-    }
-    // Instead of printing the actual signature, use the typedef name with
-    // its type arguments, if any.
-    name_str = cls.Name();  // Typedef name.
-    if (!IsFinalized() || IsBeingFinalized()) {
-      // TODO(regis): Check if this is dead code.
-      printer->AddString(name_str.ToCString());
-      printer->AddString(NullabilitySuffix(name_visibility));
-      return;
-    }
-    // Print the name of a typedef as a regular, possibly parameterized, class.
-  }
   // Do not print the full vector, but only the declared type parameters.
   num_type_params = cls.NumTypeParameters();
   if (name_visibility == kInternalName) {
@@ -19151,7 +19363,7 @@
     // Do nothing.
   } else {
     args.PrintSubvectorName(first_type_param_index, num_type_params,
-                            name_visibility, printer, name_disambiguation);
+                            name_visibility, printer);
   }
   printer->AddString(NullabilitySuffix(name_visibility));
   // The name is only used for type checking and debugging purposes.
@@ -19202,7 +19414,7 @@
     // NNBD weak mode uses LEGACY_SUBTYPE for assignability / 'as' tests,
     // and non-nullable Object is a top type according to LEGACY_SUBTYPE.
     return !IsNonNullable() ||
-           !Isolate::Current()->use_strict_null_safety_checks();
+           !IsolateGroup::Current()->use_strict_null_safety_checks();
   }
   if (cid == kFutureOrCid) {
     // FutureOr<T> where T is a top type behaves as a top type.
@@ -19250,9 +19462,7 @@
 }
 
 bool AbstractType::IsDartClosureType() const {
-  // Non-typedef function types have '_Closure' class as type class, but are not
-  // the Dart '_Closure' type.
-  return !IsFunctionType() && (type_class_id() == kClosureCid);
+  return (type_class_id() == kClosureCid);
 }
 
 bool AbstractType::IsFfiPointerType() const {
@@ -19261,10 +19471,10 @@
 
 AbstractTypePtr AbstractType::UnwrapFutureOr() const {
   if (!IsFutureOrType()) {
-    return raw();
+    return ptr();
   }
   if (arguments() == TypeArguments::null()) {
-    return Type::dynamic_type().raw();
+    return Type::dynamic_type().ptr();
   }
   Thread* thread = Thread::Current();
   REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread);
@@ -19275,12 +19485,12 @@
   type_arg = type_args.TypeAt(0);
   while (type_arg.IsFutureOrType()) {
     if (type_arg.arguments() == TypeArguments::null()) {
-      return Type::dynamic_type().raw();
+      return Type::dynamic_type().ptr();
     }
     type_args = type_arg.arguments();
     type_arg = type_args.TypeAt(0);
   }
-  return type_arg.raw();
+  return type_arg.ptr();
 }
 
 bool AbstractType::IsSubtypeOf(const AbstractType& other,
@@ -19289,7 +19499,7 @@
   ASSERT(IsFinalized());
   ASSERT(other.IsFinalized());
   // Reflexivity.
-  if (raw() == other.raw()) {
+  if (ptr() == other.ptr()) {
     return true;
   }
   // Right top type.
@@ -19314,7 +19524,7 @@
     return Instance::NullIsAssignableTo(other);
   }
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   Zone* zone = thread->zone();
   // Type parameters cannot be handled by Class::IsSubtypeOf().
   // When comparing two uninstantiated function types, one returning type
@@ -19355,36 +19565,28 @@
   if (other.IsTypeParameter()) {
     return false;
   }
-  const Class& type_cls = Class::Handle(zone, type_class());
-  const Class& other_type_cls = Class::Handle(zone, other.type_class());
   // Function types cannot be handled by Class::IsSubtypeOf().
   const bool other_is_dart_function_type = other.IsDartFunctionType();
   if (other_is_dart_function_type || other.IsFunctionType()) {
     if (IsFunctionType()) {
-      if (isolate->use_strict_null_safety_checks() && IsNullable() &&
+      if (isolate_group->use_strict_null_safety_checks() && IsNullable() &&
           other.IsNonNullable()) {
         return false;
       }
       if (other_is_dart_function_type) {
         return true;
       }
-      const Function& other_fun =
-          Function::Handle(zone, Type::Cast(other).signature());
       // Check for two function types.
-      const Function& fun =
-          Function::Handle(zone, Type::Cast(*this).signature());
-      return fun.IsSubtypeOf(other_fun, space);
+      return FunctionType::Cast(*this).IsSubtypeOf(FunctionType::Cast(other),
+                                                   space);
     }
-    if (other.IsFunctionType() && !other_type_cls.IsTypedefClass()) {
+    if (other.IsFunctionType()) {
       // [this] is not a function type. Therefore, non-function type [this]
-      // cannot be a subtype of function type [other], unless [other] is not
-      // only a function type, but also a named typedef.
-      // Indeed a typedef also behaves as a regular class-based type (with
-      // type arguments when generic).
+      // cannot be a subtype of function type [other].
       // This check is needed to avoid falling through to class-based type
       // tests, which yield incorrect result if [this] = _Closure class,
       // and [other] is a function type, because class of a function type is
-      // also _Closure (unless [other] is a typedef).
+      // also _Closure.
       return false;
     }
   }
@@ -19395,6 +19597,7 @@
     }
     return false;
   }
+  const Class& type_cls = Class::Handle(zone, type_class());
   return Class::IsSubtypeOf(type_cls, TypeArguments::Handle(zone, arguments()),
                             nullability(), other, space, trail);
 }
@@ -19443,91 +19646,95 @@
     // This only happens during bootstrapping when creating Type objects before
     // we have the instructions.
     ASSERT(type_class_id() == kDynamicCid || type_class_id() == kVoidCid);
-    StoreNonPointer(&raw_ptr()->type_test_stub_entry_point_, 0);
-  } else {
-    StoreNonPointer(&raw_ptr()->type_test_stub_entry_point_, stub.EntryPoint());
+    StoreNonPointer(&untag()->type_test_stub_entry_point_, 0);
+    untag()->set_type_test_stub(stub.ptr());
+    return;
   }
-  raw_ptr()->set_type_test_stub(stub.raw());
+
+  Thread* thread = Thread::Current();
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+  StoreNonPointer(&untag()->type_test_stub_entry_point_, stub.EntryPoint());
+  untag()->set_type_test_stub(stub.ptr());
 }
 
 TypePtr Type::NullType() {
-  return Isolate::Current()->object_store()->null_type();
+  return IsolateGroup::Current()->object_store()->null_type();
 }
 
 TypePtr Type::DynamicType() {
-  return Object::dynamic_type().raw();
+  return Object::dynamic_type().ptr();
 }
 
 TypePtr Type::VoidType() {
-  return Object::void_type().raw();
+  return Object::void_type().ptr();
 }
 
 TypePtr Type::NeverType() {
-  return Isolate::Current()->object_store()->never_type();
+  return IsolateGroup::Current()->object_store()->never_type();
 }
 
 TypePtr Type::ObjectType() {
-  return Isolate::Current()->object_store()->object_type();
+  return IsolateGroup::Current()->object_store()->object_type();
 }
 
 TypePtr Type::BoolType() {
-  return Isolate::Current()->object_store()->bool_type();
+  return IsolateGroup::Current()->object_store()->bool_type();
 }
 
 TypePtr Type::IntType() {
-  return Isolate::Current()->object_store()->int_type();
+  return IsolateGroup::Current()->object_store()->int_type();
 }
 
 TypePtr Type::NullableIntType() {
-  return Isolate::Current()->object_store()->nullable_int_type();
+  return IsolateGroup::Current()->object_store()->nullable_int_type();
 }
 
 TypePtr Type::SmiType() {
-  return Isolate::Current()->object_store()->smi_type();
+  return IsolateGroup::Current()->object_store()->smi_type();
 }
 
 TypePtr Type::MintType() {
-  return Isolate::Current()->object_store()->mint_type();
+  return IsolateGroup::Current()->object_store()->mint_type();
 }
 
 TypePtr Type::Double() {
-  return Isolate::Current()->object_store()->double_type();
+  return IsolateGroup::Current()->object_store()->double_type();
 }
 
 TypePtr Type::NullableDouble() {
-  return Isolate::Current()->object_store()->nullable_double_type();
+  return IsolateGroup::Current()->object_store()->nullable_double_type();
 }
 
 TypePtr Type::Float32x4() {
-  return Isolate::Current()->object_store()->float32x4_type();
+  return IsolateGroup::Current()->object_store()->float32x4_type();
 }
 
 TypePtr Type::Float64x2() {
-  return Isolate::Current()->object_store()->float64x2_type();
+  return IsolateGroup::Current()->object_store()->float64x2_type();
 }
 
 TypePtr Type::Int32x4() {
-  return Isolate::Current()->object_store()->int32x4_type();
+  return IsolateGroup::Current()->object_store()->int32x4_type();
 }
 
 TypePtr Type::Number() {
-  return Isolate::Current()->object_store()->number_type();
+  return IsolateGroup::Current()->object_store()->number_type();
 }
 
 TypePtr Type::StringType() {
-  return Isolate::Current()->object_store()->string_type();
+  return IsolateGroup::Current()->object_store()->string_type();
 }
 
 TypePtr Type::ArrayType() {
-  return Isolate::Current()->object_store()->array_type();
+  return IsolateGroup::Current()->object_store()->array_type();
 }
 
 TypePtr Type::DartFunctionType() {
-  return Isolate::Current()->object_store()->function_type();
+  return IsolateGroup::Current()->object_store()->function_type();
 }
 
 TypePtr Type::DartTypeType() {
-  return Isolate::Current()->object_store()->type_type();
+  return IsolateGroup::Current()->object_store()->type_type();
 }
 
 TypePtr Type::NewNonParameterizedType(const Class& type_class) {
@@ -19545,47 +19752,54 @@
   // yet, so do not call DeclarationType().
   Type& type = Type::Handle(type_class.declaration_type());
   if (type.IsNull()) {
-    type = Type::New(Class::Handle(type_class.raw()),
-                     Object::null_type_arguments(), TokenPosition::kNoSource,
-                     Nullability::kNonNullable);
+    type = Type::New(Class::Handle(type_class.ptr()),
+                     Object::null_type_arguments(), Nullability::kNonNullable);
     type.SetIsFinalized();
     type ^= type.Canonicalize(Thread::Current(), nullptr);
     type_class.set_declaration_type(type);
   }
   ASSERT(type.IsFinalized());
-  return type.raw();
+  return type.ptr();
 }
 
 void Type::SetIsFinalized() const {
   ASSERT(!IsFinalized());
   if (IsInstantiated()) {
-    set_type_state(TypeLayout::kFinalizedInstantiated);
+    set_type_state(UntaggedType::kFinalizedInstantiated);
   } else {
-    set_type_state(TypeLayout::kFinalizedUninstantiated);
+    set_type_state(UntaggedType::kFinalizedUninstantiated);
   }
 }
 
-void Type::ResetIsFinalized() const {
-  ASSERT(IsFinalized());
-  set_type_state(TypeLayout::kBeingFinalized);
-  SetIsFinalized();
+void FunctionType::SetIsFinalized() const {
+  ASSERT(!IsFinalized());
+  if (IsInstantiated()) {
+    set_type_state(UntaggedFunctionType::kFinalizedInstantiated);
+  } else {
+    set_type_state(UntaggedFunctionType::kFinalizedUninstantiated);
+  }
 }
 
 void Type::SetIsBeingFinalized() const {
   ASSERT(!IsFinalized() && !IsBeingFinalized());
-  set_type_state(TypeLayout::kBeingFinalized);
+  set_type_state(UntaggedType::kBeingFinalized);
+}
+
+void FunctionType::SetIsBeingFinalized() const {
+  ASSERT(!IsFinalized() && !IsBeingFinalized());
+  set_type_state(UntaggedFunctionType::kBeingFinalized);
 }
 
 TypePtr Type::ToNullability(Nullability value, Heap::Space space) const {
   if (nullability() == value) {
-    return raw();
+    return ptr();
   }
   // Type parameter instantiation may request a nullability change, which should
   // be ignored for types dynamic and void. Type Null cannot be the result of
   // instantiating a non-nullable type parameter (TypeError thrown).
   const classid_t cid = type_class_id();
   if (cid == kDynamicCid || cid == kVoidCid || cid == kNullCid) {
-    return raw();
+    return ptr();
   }
   if (cid == kNeverCid && value == Nullability::kNullable) {
     // Normalize Never? to Null.
@@ -19605,50 +19819,49 @@
     ASSERT(!type.IsCanonical());
     type ^= type.Canonicalize(Thread::Current(), nullptr);
   }
-  return type.raw();
+  return type.ptr();
 }
 
-FunctionPtr Type::signature() const {
-  intptr_t cid = raw_ptr()->signature()->GetClassId();
-  if (cid == kNullCid) {
-    return Function::null();
+FunctionTypePtr FunctionType::ToNullability(Nullability value,
+                                            Heap::Space space) const {
+  if (nullability() == value) {
+    return ptr();
   }
-  ASSERT(cid == kFunctionCid);
-  return Function::RawCast(raw_ptr()->signature());
-}
-
-void Type::set_signature(const Function& value) const {
-  raw_ptr()->set_signature(value.raw());
+  // Clone function type and set new nullability.
+  FunctionType& type = FunctionType::Handle();
+  // Always cloning in old space and removing space parameter would not satisfy
+  // currently existing requests for type instantiation in new space.
+  type ^= Object::Clone(*this, space);
+  type.set_nullability(value);
+  type.SetHash(0);
+  type.SetTypeTestingStub(
+      Code::Handle(TypeTestingStubGenerator::DefaultCodeForType(type)));
+  if (IsCanonical()) {
+    // Object::Clone does not clone canonical bit.
+    ASSERT(!type.IsCanonical());
+    type ^= type.Canonicalize(Thread::Current(), nullptr);
+  }
+  return type.ptr();
 }
 
 classid_t Type::type_class_id() const {
-  return Smi::Value(raw_ptr()->type_class_id());
+  return Smi::Value(untag()->type_class_id());
 }
 
 ClassPtr Type::type_class() const {
-  return Isolate::Current()->class_table()->At(type_class_id());
+  return IsolateGroup::Current()->class_table()->At(type_class_id());
 }
 
 bool Type::IsInstantiated(Genericity genericity,
                           intptr_t num_free_fun_type_params,
                           TrailPtr trail) const {
-  if (raw_ptr()->type_state_ == TypeLayout::kFinalizedInstantiated) {
+  if (untag()->type_state_ == UntaggedType::kFinalizedInstantiated) {
     return true;
   }
   if ((genericity == kAny) && (num_free_fun_type_params == kAllFree) &&
-      (raw_ptr()->type_state_ == TypeLayout::kFinalizedUninstantiated)) {
+      (untag()->type_state_ == UntaggedType::kFinalizedUninstantiated)) {
     return false;
   }
-  if (IsFunctionType()) {
-    const Function& sig_fun = Function::Handle(signature());
-    if (!sig_fun.HasInstantiatedSignature(genericity, num_free_fun_type_params,
-                                          trail)) {
-      return false;
-    }
-    // Because a generic typedef with an instantiated signature is considered
-    // uninstantiated, we still need to check the type arguments, even if the
-    // signature is instantiated.
-  }
   if (arguments() == TypeArguments::null()) {
     return true;
   }
@@ -19684,52 +19897,19 @@
   // finalizing the type argument vector of a recursive type.
   const Class& cls = Class::Handle(zone, type_class());
   TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
-  Function& sig_fun = Function::Handle(zone, signature());
-  if (!type_arguments.IsNull() &&
-      (sig_fun.IsNull() || !type_arguments.IsInstantiated())) {
-    // This type is uninstantiated because either its type arguments or its
-    // signature, or both are uninstantiated.
-    // Note that the type arguments of a function type merely document the
-    // parameterization of a generic typedef. They are otherwise ignored.
-    ASSERT(type_arguments.Length() == cls.NumTypeArguments());
-    type_arguments = type_arguments.InstantiateFrom(
-        instantiator_type_arguments, function_type_arguments,
-        num_free_fun_type_params, space, trail);
-    // A returned empty_type_arguments indicates a failed instantiation in dead
-    // code that must be propagated up to the caller, the optimizing compiler.
-    if (type_arguments.raw() == Object::empty_type_arguments().raw()) {
-      return Type::null();
-    }
+  ASSERT(type_arguments.Length() == cls.NumTypeArguments());
+  type_arguments = type_arguments.InstantiateFrom(
+      instantiator_type_arguments, function_type_arguments,
+      num_free_fun_type_params, space, trail);
+  // A returned empty_type_arguments indicates a failed instantiation in dead
+  // code that must be propagated up to the caller, the optimizing compiler.
+  if (type_arguments.ptr() == Object::empty_type_arguments().ptr()) {
+    return Type::null();
   }
   // This uninstantiated type is not modified, as it can be instantiated
   // with different instantiators. Allocate a new instantiated version of it.
-  const Type& instantiated_type = Type::Handle(
-      zone, Type::New(cls, type_arguments, token_pos(), nullability(), space));
-  // For a function type, possibly instantiate and set its signature.
-  if (!sig_fun.IsNull()) {
-    // If we are finalizing a typedef, do not yet instantiate its signature,
-    // since it gets instantiated just before the type is marked as finalized.
-    // Other function types should never get instantiated while unfinalized,
-    // even while checking bounds of recursive types.
-    if (IsFinalized()) {
-      // A generic typedef may actually declare an instantiated signature.
-      if (!sig_fun.HasInstantiatedSignature(kAny, num_free_fun_type_params)) {
-        sig_fun = sig_fun.InstantiateSignatureFrom(
-            instantiator_type_arguments, function_type_arguments,
-            num_free_fun_type_params, space);
-        // A returned null signature indicates a failed instantiation in dead
-        // code that must be propagated up to the caller, the optimizing
-        // compiler.
-        if (sig_fun.IsNull()) {
-          return Type::null();
-        }
-      }
-    } else {
-      // The Kernel frontend does not keep the information that a function type
-      // is a typedef, so we cannot assert that cls.IsTypedefClass().
-    }
-    instantiated_type.set_signature(sig_fun);
-  }
+  const Type& instantiated_type =
+      Type::Handle(zone, Type::New(cls, type_arguments, nullability(), space));
   if (IsFinalized()) {
     instantiated_type.SetIsFinalized();
   } else {
@@ -19745,7 +19925,7 @@
                         TypeEquality kind,
                         TrailPtr trail) const {
   ASSERT(!IsNull());
-  if (raw() == other.raw()) {
+  if (ptr() == other.ptr()) {
     return true;
   }
   if (other.IsTypeRef()) {
@@ -19759,19 +19939,16 @@
     return false;
   }
   const Type& other_type = Type::Cast(other);
-  if (IsFunctionType() != other_type.IsFunctionType()) {
-    return false;
-  }
   if (type_class_id() != other_type.type_class_id()) {
     return false;
   }
   Nullability this_type_nullability = nullability();
   Nullability other_type_nullability = other_type.nullability();
   Thread* thread = Thread::Current();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   Zone* zone = thread->zone();
   if (kind == TypeEquality::kInSubtypeTest) {
-    if (isolate->use_strict_null_safety_checks() &&
+    if (isolate_group->use_strict_null_safety_checks() &&
         this_type_nullability == Nullability::kNullable &&
         other_type_nullability == Nullability::kNonNullable) {
       return false;
@@ -19786,6 +19963,7 @@
       }
     } else {
       ASSERT(kind == TypeEquality::kCanonical);
+      ASSERT(IsFinalized() && other_type.IsFinalized());
     }
     if (this_type_nullability != other_type_nullability) {
       return false;
@@ -19794,8 +19972,7 @@
   if (!IsFinalized() || !other_type.IsFinalized()) {
     return false;  // Too early to decide if equal.
   }
-  if ((arguments() == other_type.arguments()) &&
-      (signature() == other_type.signature())) {
+  if (arguments() == other_type.arguments()) {
     return true;
   }
   if (arguments() != other_type.arguments()) {
@@ -19842,171 +20019,213 @@
 #endif
     }
   }
-  if (!IsFunctionType()) {
+  return true;
+}
+
+bool FunctionType::IsEquivalent(const Instance& other,
+                                TypeEquality kind,
+                                TrailPtr trail) const {
+  ASSERT(!IsNull());
+  if (ptr() == other.ptr()) {
     return true;
   }
-  ASSERT(Type::Cast(other).IsFunctionType());
+  if (other.IsTypeRef()) {
+    // Unfold right hand type. Divergence is controlled by left hand type.
+    const AbstractType& other_ref_type =
+        AbstractType::Handle(TypeRef::Cast(other).type());
+    ASSERT(!other_ref_type.IsTypeRef());
+    return IsEquivalent(other_ref_type, kind, trail);
+  }
+  if (!other.IsFunctionType()) {
+    return false;
+  }
+  const FunctionType& other_type = FunctionType::Cast(other);
+  if (packed_fields() != other_type.packed_fields()) {
+    // Different number of parent type arguments or of parameters.
+    return false;
+  }
+  Nullability this_type_nullability = nullability();
+  Nullability other_type_nullability = other_type.nullability();
+  Thread* thread = Thread::Current();
+  auto isolate_group = thread->isolate_group();
+  Zone* zone = thread->zone();
+  if (kind == TypeEquality::kInSubtypeTest) {
+    if (isolate_group->null_safety() &&
+        this_type_nullability == Nullability::kNullable &&
+        other_type_nullability == Nullability::kNonNullable) {
+      return false;
+    }
+  } else {
+    if (kind == TypeEquality::kSyntactical) {
+      if (this_type_nullability == Nullability::kLegacy) {
+        this_type_nullability = Nullability::kNonNullable;
+      }
+      if (other_type_nullability == Nullability::kLegacy) {
+        other_type_nullability = Nullability::kNonNullable;
+      }
+    } else {
+      ASSERT(kind == TypeEquality::kCanonical);
+      ASSERT(IsFinalized() && other_type.IsFinalized());
+    }
+    if (this_type_nullability != other_type_nullability) {
+      return false;
+    }
+  }
+  if (!IsFinalized() || !other_type.IsFinalized()) {
+    return false;  // Too early to decide if equal.
+  }
   // Equal function types must have equal signature types and equal optional
   // named arguments.
-  if (signature() == other_type.signature()) {
-    return true;
-  }
-  const Function& sig_fun = Function::Handle(zone, signature());
-  const Function& other_sig_fun =
-      Function::Handle(zone, other_type.signature());
 
   // Compare function type parameters and their bounds.
   // Check the type parameters and bounds of generic functions.
-  if (!sig_fun.HasSameTypeParametersAndBounds(other_sig_fun, kind)) {
-    return false;
-  }
-
-  // Compare number of function parameters.
-  const intptr_t num_fixed_params = sig_fun.num_fixed_parameters();
-  const intptr_t other_num_fixed_params = other_sig_fun.num_fixed_parameters();
-  if (num_fixed_params != other_num_fixed_params) {
-    return false;
-  }
-  const intptr_t num_opt_pos_params = sig_fun.NumOptionalPositionalParameters();
-  const intptr_t other_num_opt_pos_params =
-      other_sig_fun.NumOptionalPositionalParameters();
-  if (num_opt_pos_params != other_num_opt_pos_params) {
-    return false;
-  }
-  const intptr_t num_opt_named_params = sig_fun.NumOptionalNamedParameters();
-  const intptr_t other_num_opt_named_params =
-      other_sig_fun.NumOptionalNamedParameters();
-  if (num_opt_named_params != other_num_opt_named_params) {
-    return false;
-  }
-  const intptr_t num_ignored_params = sig_fun.NumImplicitParameters();
-  const intptr_t other_num_ignored_params =
-      other_sig_fun.NumImplicitParameters();
-  if (num_ignored_params != other_num_ignored_params) {
+  if (!HasSameTypeParametersAndBounds(other_type, kind)) {
     return false;
   }
   AbstractType& param_type = Type::Handle(zone);
   AbstractType& other_param_type = Type::Handle(zone);
   // Check the result type.
-  param_type = sig_fun.result_type();
-  other_param_type = other_sig_fun.result_type();
-  if (!param_type.IsEquivalent(other_param_type, kind)) {
+  param_type = result_type();
+  other_param_type = other_type.result_type();
+  if (!param_type.IsEquivalent(other_param_type, kind, trail)) {
     return false;
   }
   // Check the types of all parameters.
-  const intptr_t num_params = sig_fun.NumParameters();
-  ASSERT(other_sig_fun.NumParameters() == num_params);
+  const intptr_t num_params = NumParameters();
+  ASSERT(other_type.NumParameters() == num_params);
   for (intptr_t i = 0; i < num_params; i++) {
-    param_type = sig_fun.ParameterTypeAt(i);
-    other_param_type = other_sig_fun.ParameterTypeAt(i);
+    param_type = ParameterTypeAt(i);
+    other_param_type = other_type.ParameterTypeAt(i);
     // Use contravariant order in case we test for subtyping.
-    if (!other_param_type.IsEquivalent(param_type, kind)) {
+    if (!other_param_type.IsEquivalent(param_type, kind, trail)) {
       return false;
     }
   }
   // Check the names and types of optional named parameters.
-  if (num_opt_named_params == 0) {
+  if (!HasOptionalNamedParameters()) {
+    ASSERT(!other_type.HasOptionalNamedParameters());  // Same packed_fields.
     return true;
   }
-  for (intptr_t i = num_fixed_params; i < num_params; i++) {
-    if (sig_fun.ParameterNameAt(i) != other_sig_fun.ParameterNameAt(i)) {
+  for (intptr_t i = num_fixed_parameters(); i < num_params; i++) {
+    if (ParameterNameAt(i) != other_type.ParameterNameAt(i)) {
       return false;
     }
-    if (sig_fun.IsRequiredAt(i) != other_sig_fun.IsRequiredAt(i)) {
+    if (IsRequiredAt(i) != other_type.IsRequiredAt(i)) {
       return false;
     }
   }
   return true;
 }
 
-bool Type::IsRecursive() const {
-  return TypeArguments::Handle(arguments()).IsRecursive();
+bool Type::IsRecursive(TrailPtr trail) const {
+  return TypeArguments::Handle(arguments()).IsRecursive(trail);
+}
+
+bool Type::RequireConstCanonicalTypeErasure(Zone* zone, TrailPtr trail) const {
+  if (IsNonNullable()) {
+    return true;
+  }
+  if (IsLegacy()) {
+    // It is not possible for a legacy type parameter to have a non-nullable
+    // bound or non-nullable default argument.
+    return false;
+  }
+  const Class& cls = Class::Handle(zone, type_class());
+  const intptr_t num_type_params = cls.NumTypeParameters();
+  const intptr_t num_type_args = cls.NumTypeArguments();
+  const intptr_t from_index = num_type_args - num_type_params;
+  return TypeArguments::Handle(zone, arguments())
+      .RequireConstCanonicalTypeErasure(zone, from_index, num_type_params,
+                                        trail);
 }
 
 bool Type::IsDeclarationTypeOf(const Class& cls) const {
-  ASSERT(type_class() == cls.raw());
+  ASSERT(type_class() == cls.ptr());
   if (cls.IsNullClass()) {
     return true;
   }
-  if (cls.IsGeneric() || cls.IsClosureClass() || cls.IsTypedefClass()) {
+  if (cls.IsGeneric() || cls.IsClosureClass()) {
     return false;
   }
   return nullability() == Nullability::kNonNullable;
 }
 
 AbstractTypePtr Type::Canonicalize(Thread* thread, TrailPtr trail) const {
+  Zone* zone = thread->zone();
   ASSERT(IsFinalized());
   if (IsCanonical()) {
-    ASSERT(TypeArguments::Handle(arguments()).IsOld());
-    return this->raw();
+#ifdef DEBUG
+    TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+    ASSERT(type_args.IsCanonical());
+    ASSERT(type_args.IsOld());
+#endif
+    return this->ptr();
   }
-  Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-
+  auto isolate_group = thread->isolate_group();
   const classid_t cid = type_class_id();
   if (cid == kDynamicCid) {
     ASSERT(Object::dynamic_type().IsCanonical());
-    return Object::dynamic_type().raw();
+    return Object::dynamic_type().ptr();
   }
 
   if (cid == kVoidCid) {
     ASSERT(Object::void_type().IsCanonical());
-    return Object::void_type().raw();
+    return Object::void_type().ptr();
   }
 
   const Class& cls = Class::Handle(zone, type_class());
 
   // Fast canonical lookup/registry for simple types.
   if (IsDeclarationTypeOf(cls)) {
-    ASSERT(!IsFunctionType());
     ASSERT(!cls.IsNullClass() || IsNullable());
     Type& type = Type::Handle(zone, cls.declaration_type());
     if (type.IsNull()) {
-      ASSERT(!cls.raw()->ptr()->InVMIsolateHeap() ||
-             (isolate == Dart::vm_isolate()));
+      ASSERT(!cls.ptr()->untag()->InVMIsolateHeap() ||
+             (isolate_group == Dart::vm_isolate_group()));
       // Canonicalize the type arguments of the supertype, if any.
       TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
       type_args = type_args.Canonicalize(thread, trail);
       if (IsCanonical()) {
         // Canonicalizing type_args canonicalized this type.
         ASSERT(IsRecursive());
-        return this->raw();
+        return this->ptr();
       }
       set_arguments(type_args);
       type = cls.declaration_type();
       // May be set while canonicalizing type args.
       if (type.IsNull()) {
-        SafepointMutexLocker ml(
-            isolate->group()->type_canonicalization_mutex());
+        SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
         // Recheck if type exists.
         type = cls.declaration_type();
         if (type.IsNull()) {
           if (this->IsNew()) {
             type ^= Object::Clone(*this, Heap::kOld);
           } else {
-            type = this->raw();
+            type = this->ptr();
           }
           ASSERT(type.IsOld());
           type.ComputeHash();
           type.SetCanonical();
           cls.set_declaration_type(type);
-          return type.raw();
+          return type.ptr();
         }
       }
     }
     ASSERT(this->Equals(type));
-    ASSERT(type.IsCanonical());
-    ASSERT(type.IsOld());
-    return type.raw();
+    // TODO(rmacnak): Revisit immediately returning type after to changes to
+    // recanonicalization on load for literal splitting.
+    if (type.IsCanonical()) {
+      return type.ptr();
+    }
   }
 
-  AbstractType& type = Type::Handle(zone);
-  ObjectStore* object_store = isolate->object_store();
+  Type& type = Type::Handle(zone);
+  ObjectStore* object_store = isolate_group->object_store();
   {
-    SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
     CanonicalTypeSet table(zone, object_store->canonical_types());
     type ^= table.GetOrNull(CanonicalTypeKey(*this));
-    ASSERT(object_store->canonical_types() == table.Release().raw());
+    ASSERT(object_store->canonical_types() == table.Release().ptr());
   }
   if (type.IsNull()) {
     // The type was not found in the table. It is not canonical yet.
@@ -20027,7 +20246,7 @@
           type_arg = type_args.TypeAt(i);
           new_type_args.SetTypeAt(i, type_arg);
         }
-        type_args = new_type_args.raw();
+        type_args = new_type_args.ptr();
         set_arguments(type_args);
         SetHash(0);  // Flush cached hash value.
       }
@@ -20036,30 +20255,23 @@
     if (IsCanonical()) {
       // Canonicalizing type_args canonicalized this type as a side effect.
       ASSERT(IsRecursive());
-      // Cycles via typedefs are detected and disallowed, but a function type
-      // can be recursive due to a cycle in its type arguments.
-      return this->raw();
+      // A type can be recursive due to a cycle in its type arguments.
+      return this->ptr();
     }
     set_arguments(type_args);
     ASSERT(type_args.IsNull() || type_args.IsOld());
 
-    // In case of a function type, the signature has already been canonicalized
-    // when finalizing the type and passing kCanonicalize as finalization.
-    // Therefore, we do not canonicalize the signature here, which would have no
-    // effect on selecting the canonical type anyway, because the function
-    // object is not replaced when canonicalizing the signature.
-
-    // Check to see if the type got added to canonical list as part of the
+    // Check to see if the type got added to canonical table as part of the
     // type arguments canonicalization.
-    SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
     CanonicalTypeSet table(zone, object_store->canonical_types());
     type ^= table.GetOrNull(CanonicalTypeKey(*this));
     if (type.IsNull()) {
-      // Add this Type into the canonical list of types.
+      // Add this type into the canonical table of types.
       if (this->IsNew()) {
         type ^= Object::Clone(*this, Heap::kOld);
       } else {
-        type = this->raw();
+        type = this->ptr();
       }
       ASSERT(type.IsOld());
       type.SetCanonical();  // Mark object as being canonical.
@@ -20068,7 +20280,7 @@
     }
     object_store->set_canonical_types(table.Release());
   }
-  return type.raw();
+  return type.ptr();
 }
 
 #if defined(DEBUG)
@@ -20078,32 +20290,31 @@
   }
   const classid_t cid = type_class_id();
   if (cid == kDynamicCid) {
-    return (raw() == Object::dynamic_type().raw());
+    return (ptr() == Object::dynamic_type().ptr());
   }
   if (cid == kVoidCid) {
-    return (raw() == Object::void_type().raw());
+    return (ptr() == Object::void_type().ptr());
   }
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  AbstractType& type = Type::Handle(zone);
+  auto isolate_group = thread->isolate_group();
+  Type& type = Type::Handle(zone);
   const Class& cls = Class::Handle(zone, type_class());
 
   // Fast canonical lookup/registry for simple types.
   if (IsDeclarationTypeOf(cls)) {
-    ASSERT(!IsFunctionType());
     type = cls.declaration_type();
     ASSERT(type.IsCanonical());
-    return (raw() == type.raw());
+    return (ptr() == type.ptr());
   }
 
-  ObjectStore* object_store = isolate->object_store();
+  ObjectStore* object_store = isolate_group->object_store();
   {
-    SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
     CanonicalTypeSet table(zone, object_store->canonical_types());
     type ^= table.GetOrNull(CanonicalTypeKey(*this));
     object_store->set_canonical_types(table.Release());
   }
-  return (raw() == type.raw());
+  return (ptr() == type.ptr());
 }
 #endif  // DEBUG
 
@@ -20113,35 +20324,18 @@
   }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  if (IsFunctionType()) {
-    // The scope class and type arguments do not appear explicitly in the user
-    // visible name. The type arguments were used to instantiate the function
-    // type prior to this call.
-    const Function& sig_fun = Function::Handle(zone, signature());
-    AbstractType& type = AbstractType::Handle(zone);
-    const intptr_t num_params = sig_fun.NumParameters();
-    for (intptr_t i = 0; i < num_params; i++) {
-      type = sig_fun.ParameterTypeAt(i);
-      type.EnumerateURIs(uris);
-    }
-    // Handle result type last, since it appears last in the user visible name.
-    type = sig_fun.result_type();
-    type.EnumerateURIs(uris);
-  } else {
-    const Class& cls = Class::Handle(zone, type_class());
-    const String& name = String::Handle(zone, cls.UserVisibleName());
-    const Library& library = Library::Handle(zone, cls.library());
-    const String& uri = String::Handle(zone, library.url());
-    AddURI(uris, name, uri);
-    const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
-    type_args.EnumerateURIs(uris);
-  }
+  const Class& cls = Class::Handle(zone, type_class());
+  const String& name = String::Handle(zone, cls.UserVisibleName());
+  const Library& library = Library::Handle(zone, cls.library());
+  const String& uri = String::Handle(zone, library.url());
+  AddURI(uris, name, uri);
+  const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+  type_args.EnumerateURIs(uris);
 }
 
 intptr_t Type::ComputeHash() const {
   ASSERT(IsFinalized());
-  uint32_t result = 0;
-  result = CombineHashes(result, type_class_id());
+  uint32_t result = type_class_id();
   // A legacy type should have the same hash as its non-nullable version to be
   // consistent with the definition of type equality in Dart code.
   Nullability type_nullability = nullability();
@@ -20163,35 +20357,45 @@
     }
   }
   result = CombineHashes(result, type_args_hash);
-  if (IsFunctionType()) {
-    AbstractType& type = AbstractType::Handle();
-    const Function& sig_fun = Function::Handle(signature());
-    const intptr_t num_type_params = sig_fun.NumTypeParameters();
-    if (num_type_params > 0) {
-      const TypeArguments& type_params =
-          TypeArguments::Handle(sig_fun.type_parameters());
-      for (intptr_t i = 0; i < num_type_params; i++) {
-        type = type_params.TypeAt(i);
-        type = TypeParameter::Cast(type).bound();
-        result = CombineHashes(result, type.Hash());
-      }
-    }
-    type = sig_fun.result_type();
-    result = CombineHashes(result, type.Hash());
-    result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
-    const intptr_t num_params = sig_fun.NumParameters();
-    for (intptr_t i = 0; i < num_params; i++) {
-      type = sig_fun.ParameterTypeAt(i);
+  result = FinalizeHash(result, kHashBits);
+  SetHash(result);
+  return result;
+}
+
+intptr_t FunctionType::ComputeHash() const {
+  ASSERT(IsFinalized());
+  uint32_t result = packed_fields();
+  // A legacy type should have the same hash as its non-nullable version to be
+  // consistent with the definition of type equality in Dart code.
+  Nullability type_nullability = nullability();
+  if (type_nullability == Nullability::kLegacy) {
+    type_nullability = Nullability::kNonNullable;
+  }
+  result = CombineHashes(result, static_cast<uint32_t>(type_nullability));
+  AbstractType& type = AbstractType::Handle();
+  const intptr_t num_type_params = NumTypeParameters();
+  if (num_type_params > 0) {
+    const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
+    for (intptr_t i = 0; i < num_type_params; i++) {
+      type = type_params.TypeAt(i);
+      type = TypeParameter::Cast(type).bound();
       result = CombineHashes(result, type.Hash());
     }
-    if (sig_fun.NumOptionalNamedParameters() > 0) {
-      String& param_name = String::Handle();
-      for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
-        param_name = sig_fun.ParameterNameAt(i);
-        result = CombineHashes(result, param_name.Hash());
-      }
-      // Required flag is not hashed, see comment above.
+  }
+  type = result_type();
+  result = CombineHashes(result, type.Hash());
+  const intptr_t num_params = NumParameters();
+  for (intptr_t i = 0; i < num_params; i++) {
+    type = ParameterTypeAt(i);
+    result = CombineHashes(result, type.Hash());
+  }
+  if (HasOptionalNamedParameters()) {
+    String& param_name = String::Handle();
+    for (intptr_t i = num_fixed_parameters(); i < num_params; i++) {
+      param_name = ParameterNameAt(i);
+      result = CombineHashes(result, param_name.Hash());
     }
+    // Required flag is not hashed, see comment above about legacy type.
   }
   result = FinalizeHash(result, kHashBits);
   SetHash(result);
@@ -20200,12 +20404,12 @@
 
 void Type::set_type_class(const Class& value) const {
   ASSERT(!value.IsNull());
-  raw_ptr()->set_type_class_id(Smi::New(value.id()));
+  untag()->set_type_class_id(Smi::New(value.id()));
 }
 
 void Type::set_arguments(const TypeArguments& value) const {
   ASSERT(!IsCanonical());
-  raw_ptr()->set_arguments(value.raw());
+  untag()->set_arguments(value.ptr());
 }
 
 TypePtr Type::New(Heap::Space space) {
@@ -20215,7 +20419,6 @@
 
 TypePtr Type::New(const Class& clazz,
                   const TypeArguments& arguments,
-                  TokenPosition token_pos,
                   Nullability nullability,
                   Heap::Space space) {
   Zone* Z = Thread::Current()->zone();
@@ -20223,25 +20426,19 @@
   result.set_type_class(clazz);
   result.set_arguments(arguments);
   result.SetHash(0);
-  result.set_token_pos(token_pos);
-  result.StoreNonPointer(&result.raw_ptr()->type_state_,
-                         TypeLayout::kAllocated);
+  result.StoreNonPointer(&result.untag()->type_state_,
+                         UntaggedType::kAllocated);
   result.set_nullability(nullability);
 
   result.SetTypeTestingStub(
       Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
-  return result.raw();
+  return result.ptr();
 }
 
-void Type::set_token_pos(TokenPosition token_pos) const {
-  ASSERT(!token_pos.IsClassifying());
-  StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
-}
-
-void Type::set_type_state(int8_t state) const {
-  ASSERT((state >= TypeLayout::kAllocated) &&
-         (state <= TypeLayout::kFinalizedUninstantiated));
-  StoreNonPointer(&raw_ptr()->type_state_, state);
+void Type::set_type_state(uint8_t state) const {
+  ASSERT((state >= UntaggedType::kAllocated) &&
+         (state <= UntaggedType::kFinalizedUninstantiated));
+  StoreNonPointer(&untag()->type_state_, state);
 }
 
 const char* Type::ToCString() const {
@@ -20253,8 +20450,7 @@
   const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
   const char* args_cstr = "";
   if (!type_args.IsNull()) {
-    type_args.PrintSubvectorName(0, type_args.Length(), kInternalName, &args,
-                                 NameDisambiguation::kYes);
+    type_args.PrintSubvectorName(0, type_args.Length(), kInternalName, &args);
     args_cstr = args.buffer();
   }
   const Class& cls = Class::Handle(zone, type_class());
@@ -20262,24 +20458,6 @@
   const String& name = String::Handle(zone, cls.Name());
   class_name = name.IsNull() ? "<null>" : name.ToCString();
   const char* suffix = NullabilitySuffix(kInternalName);
-  if (IsFunctionType()) {
-    const Function& sig_fun = Function::Handle(zone, signature());
-    ZoneTextBuffer sig(zone);
-    if (suffix[0] != '\0') {
-      sig.AddString("(");
-    }
-    sig_fun.PrintSignature(kInternalName, &sig);
-    if (suffix[0] != '\0') {
-      sig.AddString(")");
-      sig.AddString(suffix);
-    }
-    if (cls.IsClosureClass()) {
-      ASSERT(type_args.IsNull());
-      return OS::SCreate(zone, "Function Type: %s", sig.buffer());
-    }
-    return OS::SCreate(zone, "Function Type: %s (%s%s%s)", sig.buffer(),
-                       class_name, args_cstr, suffix);
-  }
   if (IsFinalized() && IsRecursive()) {
     const intptr_t hash = Hash();
     return OS::SCreate(zone, "Type: (H%" Px ") %s%s%s", hash, class_name,
@@ -20289,6 +20467,222 @@
   }
 }
 
+bool FunctionType::IsRecursive(TrailPtr trail) const {
+  AbstractType& type = AbstractType::Handle();
+  const intptr_t num_type_params = NumTypeParameters();
+  if (num_type_params > 0) {
+    const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
+    for (intptr_t i = 0; i < num_type_params; i++) {
+      type = type_params.TypeAt(i);
+      if (type.IsRecursive(trail)) {
+        return true;
+      }
+    }
+  }
+  type = result_type();
+  if (type.IsRecursive(trail)) {
+    return true;
+  }
+  const intptr_t num_params = NumParameters();
+  for (intptr_t i = 0; i < num_params; i++) {
+    type = ParameterTypeAt(i);
+    if (type.IsRecursive(trail)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool FunctionType::RequireConstCanonicalTypeErasure(Zone* zone,
+                                                    TrailPtr trail) const {
+  if (IsNonNullable()) {
+    return true;
+  }
+  if (IsLegacy()) {
+    // It is not possible for a function type to have a non-nullable type in
+    // its signature.
+    return false;
+  }
+  AbstractType& type = AbstractType::Handle(zone);
+  const intptr_t num_type_params = NumTypeParameters();
+  if (num_type_params > 0) {
+    const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
+    TypeParameter& type_param = TypeParameter::Handle(zone);
+    for (intptr_t i = 0; i < num_type_params; i++) {
+      type_param ^= type_params.TypeAt(i);
+      type = type_param.bound();
+      if (type.RequireConstCanonicalTypeErasure(zone, trail)) {
+        return true;
+      }
+      type = type_param.default_argument();
+      if (type.RequireConstCanonicalTypeErasure(zone, trail)) {
+        return true;
+      }
+    }
+  }
+  type = result_type();
+  if (type.RequireConstCanonicalTypeErasure(zone, trail)) {
+    return true;
+  }
+  const intptr_t num_params = NumParameters();
+  for (intptr_t i = 0; i < num_params; i++) {
+    type = ParameterTypeAt(i);
+    if (type.RequireConstCanonicalTypeErasure(zone, trail)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+AbstractTypePtr FunctionType::Canonicalize(Thread* thread,
+                                           TrailPtr trail) const {
+  ASSERT(IsFinalized());
+  Zone* zone = thread->zone();
+  if (IsCanonical()) {
+#ifdef DEBUG
+    // Verify that all fields are allocated in old space and are canonical.
+    AbstractType& type = AbstractType::Handle(zone);
+    const intptr_t num_type_params = NumTypeParameters();
+    if (num_type_params > 0) {
+      const TypeArguments& type_params =
+          TypeArguments::Handle(zone, type_parameters());
+      ASSERT(type_params.IsOld());
+      for (intptr_t i = 0; i < num_type_params; i++) {
+        type = type_params.TypeAt(i);
+        ASSERT(type.IsOld());
+        ASSERT(type.IsCanonical());
+      }
+    }
+    type = result_type();
+    ASSERT(type.IsOld());
+    ASSERT(type.IsCanonical());
+    ASSERT(Array::Handle(zone, parameter_types()).IsOld());
+    ASSERT(Array::Handle(zone, parameter_names()).IsOld());
+    const intptr_t num_params = NumParameters();
+    for (intptr_t i = 0; i < num_params; i++) {
+      type = ParameterTypeAt(i);
+      ASSERT(type.IsOld());
+      ASSERT(type.IsCanonical());
+    }
+#endif
+    return ptr();
+  }
+  auto isolate_group = thread->isolate_group();
+  ObjectStore* object_store = isolate_group->object_store();
+  FunctionType& sig = FunctionType::Handle(zone);
+  {
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+    CanonicalFunctionTypeSet table(zone,
+                                   object_store->canonical_function_types());
+    sig ^= table.GetOrNull(CanonicalFunctionTypeKey(*this));
+    ASSERT(object_store->canonical_function_types() == table.Release().ptr());
+  }
+  if (sig.IsNull()) {
+    // The function type was not found in the table. It is not canonical yet.
+    // Canonicalize its type parameters and types.
+    const intptr_t num_type_params = NumTypeParameters();
+    if (num_type_params > 0) {
+      const TypeArguments& type_params =
+          TypeArguments::Handle(zone, type_parameters());
+      ASSERT(type_params.IsOld());
+      TypeParameter& type_param = TypeParameter::Handle(zone);
+      for (intptr_t i = 0; i < num_type_params; i++) {
+        type_param ^= type_params.TypeAt(i);
+        if (!type_param.IsCanonical()) {
+          type_param ^= type_param.Canonicalize(thread, trail);
+          type_params.SetTypeAt(i, type_param);
+          SetHash(0);
+        }
+      }
+    }
+    AbstractType& type = AbstractType::Handle(zone);
+    type = result_type();
+    if (!type.IsCanonical()) {
+      type = type.Canonicalize(thread, trail);
+      set_result_type(type);
+      SetHash(0);
+    }
+    ASSERT(Array::Handle(zone, parameter_types()).IsOld());
+    ASSERT(Array::Handle(zone, parameter_names()).IsOld());
+    const intptr_t num_params = NumParameters();
+    for (intptr_t i = 0; i < num_params; i++) {
+      type = ParameterTypeAt(i);
+      if (!type.IsCanonical()) {
+        type = type.Canonicalize(thread, trail);
+        SetParameterTypeAt(i, type);
+        SetHash(0);
+      }
+    }
+    if (IsCanonical()) {
+      // Canonicalizing signature types canonicalized this signature as a
+      // side effect.
+      ASSERT(IsRecursive());
+      return this->ptr();
+    }
+    // Check to see if the function type got added to canonical table as part
+    // of the canonicalization of its signature types.
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+    CanonicalFunctionTypeSet table(zone,
+                                   object_store->canonical_function_types());
+    sig ^= table.GetOrNull(CanonicalFunctionTypeKey(*this));
+    if (sig.IsNull()) {
+      // Add this function type into the canonical table of function types.
+      if (this->IsNew()) {
+        sig ^= Object::Clone(*this, Heap::kOld);
+      } else {
+        sig = this->ptr();
+      }
+      ASSERT(sig.IsOld());
+      sig.SetCanonical();  // Mark object as being canonical.
+      bool present = table.Insert(sig);
+      ASSERT(!present);
+    }
+    object_store->set_canonical_function_types(table.Release());
+  }
+  return sig.ptr();
+}
+
+#if defined(DEBUG)
+bool FunctionType::CheckIsCanonical(Thread* thread) const {
+  Zone* zone = thread->zone();
+  auto isolate_group = thread->isolate_group();
+  FunctionType& type = FunctionType::Handle(zone);
+  ObjectStore* object_store = isolate_group->object_store();
+  {
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+    CanonicalFunctionTypeSet table(zone,
+                                   object_store->canonical_function_types());
+    type ^= table.GetOrNull(CanonicalFunctionTypeKey(*this));
+    object_store->set_canonical_function_types(table.Release());
+  }
+  return ptr() == type.ptr();
+}
+#endif  // DEBUG
+
+void FunctionType::EnumerateURIs(URIs* uris) const {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  AbstractType& type = AbstractType::Handle(zone);
+  const intptr_t num_params = NumParameters();
+  for (intptr_t i = 0; i < num_params; i++) {
+    type = ParameterTypeAt(i);
+    type.EnumerateURIs(uris);
+  }
+  // Handle result type last, since it appears last in the user visible name.
+  type = result_type();
+  type.EnumerateURIs(uris);
+}
+
+bool TypeRef::RequireConstCanonicalTypeErasure(Zone* zone,
+                                               TrailPtr trail) const {
+  if (TestAndAddToTrail(&trail)) {
+    return false;
+  }
+  const AbstractType& ref_type = AbstractType::Handle(zone, type());
+  return !ref_type.IsNull() &&
+         ref_type.RequireConstCanonicalTypeErasure(zone, trail);
+}
+
 bool TypeRef::IsInstantiated(Genericity genericity,
                              intptr_t num_free_fun_type_params,
                              TrailPtr trail) const {
@@ -20303,7 +20697,7 @@
 bool TypeRef::IsEquivalent(const Instance& other,
                            TypeEquality kind,
                            TrailPtr trail) const {
-  if (raw() == other.raw()) {
+  if (ptr() == other.ptr()) {
     return true;
   }
   if (!other.IsAbstractType()) {
@@ -20325,7 +20719,7 @@
   TypeRef& instantiated_type_ref = TypeRef::Handle();
   instantiated_type_ref ^= OnlyBuddyInTrail(trail);
   if (!instantiated_type_ref.IsNull()) {
-    return instantiated_type_ref.raw();
+    return instantiated_type_ref.ptr();
   }
   instantiated_type_ref = TypeRef::New();
   AddOnlyBuddyToTrail(&trail, instantiated_type_ref);
@@ -20346,13 +20740,12 @@
 
   instantiated_type_ref.SetTypeTestingStub(Code::Handle(
       TypeTestingStubGenerator::DefaultCodeForType(instantiated_type_ref)));
-  return instantiated_type_ref.raw();
+  return instantiated_type_ref.ptr();
 }
 
 void TypeRef::set_type(const AbstractType& value) const {
-  ASSERT(value.IsNull() || value.IsFunctionType() || value.HasTypeClass());
-  ASSERT(!value.IsTypeRef());
-  raw_ptr()->set_type(value.raw());
+  ASSERT(value.IsNull() || value.IsType() || value.IsFunctionType());
+  untag()->set_type(value.ptr());
 }
 
 // A TypeRef cannot be canonical by definition. Only its referenced type can be.
@@ -20361,7 +20754,7 @@
 // represented by a TypeRef pointing to itself.
 AbstractTypePtr TypeRef::Canonicalize(Thread* thread, TrailPtr trail) const {
   if (TestAndAddToTrail(&trail)) {
-    return raw();
+    return ptr();
   }
   // TODO(regis): Try to reduce the number of nodes required to represent the
   // referenced recursive type.
@@ -20369,7 +20762,7 @@
   ASSERT(!ref_type.IsNull());
   ref_type = ref_type.Canonicalize(thread, trail);
   set_type(ref_type);
-  return raw();
+  return ptr();
 }
 
 #if defined(DEBUG)
@@ -20402,8 +20795,14 @@
   //    type arguments are set).
   const AbstractType& ref_type = AbstractType::Handle(type());
   ASSERT(!ref_type.IsNull());
-  uint32_t result = Class::Handle(ref_type.type_class()).id();
-  result = CombineHashes(result, static_cast<uint32_t>(ref_type.nullability()));
+  uint32_t result = ref_type.type_class_id();
+  // A legacy type should have the same hash as its non-nullable version to be
+  // consistent with the definition of type equality in Dart code.
+  Nullability ref_type_nullability = ref_type.nullability();
+  if (ref_type_nullability == Nullability::kLegacy) {
+    ref_type_nullability = Nullability::kNonNullable;
+  }
+  result = CombineHashes(result, static_cast<uint32_t>(ref_type_nullability));
   return FinalizeHash(result, kHashBits);
 }
 
@@ -20420,7 +20819,7 @@
 
   result.SetTypeTestingStub(
       Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
-  return result.raw();
+  return result.ptr();
 }
 
 const char* TypeRef::ToCString() const {
@@ -20441,44 +20840,46 @@
 
 void TypeParameter::SetIsFinalized() const {
   ASSERT(!IsFinalized());
-  set_flags(TypeParameterLayout::FinalizedBit::update(true, raw_ptr()->flags_));
+  set_flags(UntaggedTypeParameter::FinalizedBit::update(
+      true, UntaggedTypeParameter::BeingFinalizedBit::update(false,
+                                                             untag()->flags_)));
+}
+
+void TypeParameter::SetIsBeingFinalized() const {
+  ASSERT(!IsFinalized());
+  set_flags(
+      UntaggedTypeParameter::BeingFinalizedBit::update(true, untag()->flags_));
 }
 
 void TypeParameter::SetGenericCovariantImpl(bool value) const {
-  set_flags(TypeParameterLayout::GenericCovariantImplBit::update(
-      value, raw_ptr()->flags_));
-}
-
-void TypeParameter::SetDeclaration(bool value) const {
-  set_flags(
-      TypeParameterLayout::DeclarationBit::update(value, raw_ptr()->flags_));
+  set_flags(UntaggedTypeParameter::GenericCovariantImplBit::update(
+      value, untag()->flags_));
 }
 
 void TypeParameter::set_nullability(Nullability value) const {
-  StoreNonPointer(&raw_ptr()->nullability_, static_cast<int8_t>(value));
+  StoreNonPointer(&untag()->nullability_, static_cast<uint8_t>(value));
 }
 
 TypeParameterPtr TypeParameter::ToNullability(Nullability value,
                                               Heap::Space space) const {
   if (nullability() == value) {
-    return raw();
+    return ptr();
   }
   // Clone type parameter and set new nullability.
   TypeParameter& type_parameter = TypeParameter::Handle();
   type_parameter ^= Object::Clone(*this, space);
   type_parameter.set_nullability(value);
-  type_parameter.SetDeclaration(false);
   type_parameter.SetHash(0);
   type_parameter.SetTypeTestingStub(Code::Handle(
       TypeTestingStubGenerator::DefaultCodeForType(type_parameter)));
   if (IsCanonical()) {
     // Object::Clone does not clone canonical bit.
     ASSERT(!type_parameter.IsCanonical());
-    if (IsFinalized()) {
-      type_parameter ^= type_parameter.Canonicalize(Thread::Current(), nullptr);
-    }
+    ASSERT(IsFinalized());
+    ASSERT(type_parameter.IsFinalized());
+    type_parameter ^= type_parameter.Canonicalize(Thread::Current(), nullptr);
   }
-  return type_parameter.raw();
+  return type_parameter.ptr();
 }
 
 bool TypeParameter::IsInstantiated(Genericity genericity,
@@ -20489,13 +20890,13 @@
     return genericity == kFunctions;
   }
   ASSERT(IsFunctionTypeParameter());
-  ASSERT(IsFinalized());
   if ((genericity != kCurrentClass) && (index() < num_free_fun_type_params)) {
     return false;
   }
   // Although the type parameter is instantiated, its bound may not be.
   const AbstractType& upper_bound = AbstractType::Handle(bound());
-  if (upper_bound.IsTypeParameter() ||
+  ASSERT(!upper_bound.IsTypeRef());
+  if (upper_bound.IsTypeParameter() || upper_bound.IsFunctionType() ||
       upper_bound.arguments() != TypeArguments::null()) {
     // Use trail to break cycles created by bound referring to type parameter.
     if (!TestAndAddToTrail(&trail) &&
@@ -20510,7 +20911,7 @@
 bool TypeParameter::IsEquivalent(const Instance& other,
                                  TypeEquality kind,
                                  TrailPtr trail) const {
-  if (raw() == other.raw()) {
+  if (ptr() == other.ptr()) {
     return true;
   }
   if (other.IsTypeRef()) {
@@ -20524,22 +20925,97 @@
     return false;
   }
   const TypeParameter& other_type_param = TypeParameter::Cast(other);
-  // Class type parameters must parameterize the same class to be equivalent.
-  // Note that this check will also reject a class type parameter being compared
-  // to a function type parameter.
-  if (parameterized_class_id() != other_type_param.parameterized_class_id()) {
-    return false;
+  // Compare index, name, bound, default argument, and flags.
+  if (IsFunctionTypeParameter()) {
+    if (!other_type_param.IsFunctionTypeParameter()) {
+      return false;
+    }
+    ASSERT(IsFinalized() && other_type_param.IsFinalized());
+    if (kind == TypeEquality::kInSubtypeTest) {
+      // To be equivalent, the function type parameters should be declared
+      // at the same position in the generic function. Their index therefore
+      // needs adjustment before comparison.
+      // Example: 'foo<F>(bar<B>(B b)) { }' and 'baz<Z>(Z z) { }', baz can
+      // be assigned to bar, although B has index 1 and Z index 0.
+      if (index() - base() !=
+          other_type_param.index() - other_type_param.base()) {
+        return false;
+      }
+      AbstractType& upper_bound = AbstractType::Handle(bound());
+      AbstractType& other_type_param_upper_bound =
+          AbstractType::Handle(other_type_param.bound());
+      // Bounds that are mutual subtypes are considered equal.
+      if (!upper_bound.IsSubtypeOf(other_type_param_upper_bound, Heap::kOld) ||
+          !other_type_param_upper_bound.IsSubtypeOf(upper_bound, Heap::kOld)) {
+        return false;
+      }
+    } else {
+      if (base() != other_type_param.base() ||
+          index() != other_type_param.index()) {
+        return false;
+      }
+      // Compare bounds.
+      AbstractType& type = AbstractType::Handle(bound());
+      AbstractType& other_type = AbstractType::Handle(other_type_param.bound());
+      if (!TestAndAddBuddyToTrail(&trail, other_type_param) &&
+          !type.IsEquivalent(other_type, kind, trail)) {
+        return false;
+      }
+      if (kind == TypeEquality::kCanonical) {
+        // Compare names.
+        if (name() != other_type_param.name()) {
+          return false;
+        }
+        // Compare default arguments.
+        type = default_argument();
+        other_type = other_type_param.default_argument();
+        if (type.IsNull()) {
+          if (!other_type.IsNull()) {
+            return false;
+          }
+        } else if (!type.IsEquivalent(other_type, kind, trail)) {
+          return false;
+        }
+      }
+    }
+    if (IsGenericCovariantImpl() != other_type_param.IsGenericCovariantImpl()) {
+      return false;
+    }
+  } else {
+    if (!other_type_param.IsClassTypeParameter()) {
+      return false;
+    }
+    if (kind == TypeEquality::kCanonical) {
+      if (parameterized_class_id() !=
+          other_type_param.parameterized_class_id()) {
+        // This also rejects finalized vs unfinalized comparison.
+        return false;
+      }
+      if (base() != other_type_param.base() ||
+          index() != other_type_param.index() ||
+          name() != other_type_param.name()) {
+        return false;
+      }
+    } else {
+      ASSERT(IsFinalized() && other_type_param.IsFinalized());
+      if (index() != other_type_param.index()) {
+        return false;
+      }
+    }
+    // Compare bounds.
+    AbstractType& upper_bound = AbstractType::Handle(bound());
+    AbstractType& other_type_param_upper_bound =
+        AbstractType::Handle(other_type_param.bound());
+    if (!TestAndAddBuddyToTrail(&trail, other_type_param) &&
+        !upper_bound.IsEquivalent(other_type_param_upper_bound, kind, trail)) {
+      return false;
+    }
   }
-  // The function does not matter in type tests or when comparing types with
-  // syntactical equality, but it does matter in canonicalization.
-  if (kind == TypeEquality::kCanonical &&
-      parameterized_function() != other_type_param.parameterized_function()) {
-    return false;
-  }
+  // Compare nullability.
   Nullability this_type_param_nullability = nullability();
   Nullability other_type_param_nullability = other_type_param.nullability();
   if (kind == TypeEquality::kInSubtypeTest) {
-    if (Isolate::Current()->use_strict_null_safety_checks() &&
+    if (IsolateGroup::Current()->use_strict_null_safety_checks() &&
         (this_type_param_nullability == Nullability::kNullable) &&
         (other_type_param_nullability == Nullability::kNonNullable)) {
       return false;
@@ -20559,30 +21035,23 @@
       return false;
     }
   }
-  if (kind == TypeEquality::kInSubtypeTest) {
-    if (IsFunctionTypeParameter() && IsFinalized() &&
-        other_type_param.IsFinalized()) {
-      ASSERT(other_type_param.IsFunctionTypeParameter());  // Checked above.
-      // To be equivalent, the function type parameters should be declared
-      // at the same position in the generic function. Their index therefore
-      // needs adjustement before comparison.
-      // Example: 'foo<F>(bar<B>(B b)) { }' and 'baz<Z>(Z z) { }', baz can
-      // be assigned to bar, although B has index 1 and Z index 0.
-      const Function& sig_fun = Function::Handle(parameterized_function());
-      const Function& other_sig_fun =
-          Function::Handle(other_type_param.parameterized_function());
-      const int offset = sig_fun.NumParentTypeParameters();
-      const int other_offset = other_sig_fun.NumParentTypeParameters();
-      return index() - offset == other_type_param.index() - other_offset;
-    } else if (IsFinalized() == other_type_param.IsFinalized()) {
-      return index() == other_type_param.index();
-    }
-    return false;
+  return true;
+}
+
+bool TypeParameter::IsRecursive(TrailPtr trail) const {
+  if (TestAndAddToTrail(&trail)) {
+    return true;
   }
-  if (IsFinalized() == other_type_param.IsFinalized()) {
-    return index() == other_type_param.index();
+  AbstractType& type = AbstractType::Handle();
+  type = bound();
+  if (type.IsRecursive(trail)) {
+    return true;
   }
-  return name() == other_type_param.name();
+  type = default_argument();
+  if (type.IsRecursive(trail)) {
+    return true;
+  }
+  return false;
 }
 
 void TypeParameter::set_parameterized_class(const Class& value) const {
@@ -20591,42 +21060,51 @@
   if (!value.IsNull()) {
     cid = value.id();
   }
-  StoreNonPointer(&raw_ptr()->parameterized_class_id_, cid);
+  set_parameterized_class_id(cid);
+}
+
+void TypeParameter::set_parameterized_class_id(classid_t value) const {
+  StoreNonPointer(&untag()->parameterized_class_id_, value);
 }
 
 classid_t TypeParameter::parameterized_class_id() const {
-  return raw_ptr()->parameterized_class_id_;
+  return untag()->parameterized_class_id_;
 }
 
 ClassPtr TypeParameter::parameterized_class() const {
   classid_t cid = parameterized_class_id();
-  if (cid == kFunctionCid) {
+  // A canonicalized class type parameter does not refer to its class anymore.
+  if (cid == kClassCid || cid == kFunctionCid) {
     return Class::null();
   }
-  return Isolate::Current()->class_table()->At(cid);
+  return IsolateGroup::Current()->class_table()->At(cid);
 }
 
-void TypeParameter::set_parameterized_function(const Function& value) const {
-  raw_ptr()->set_parameterized_function(value.raw());
+void TypeParameter::set_base(intptr_t value) const {
+  ASSERT(value >= 0);
+  ASSERT(Utils::IsUint(16, value));
+  StoreNonPointer(&untag()->base_, value);
 }
 
 void TypeParameter::set_index(intptr_t value) const {
   ASSERT(value >= 0);
-  ASSERT(Utils::IsInt(16, value));
-  StoreNonPointer(&raw_ptr()->index_, value);
+  ASSERT(Utils::IsUint(16, value));
+  StoreNonPointer(&untag()->index_, value);
 }
 
 void TypeParameter::set_name(const String& value) const {
   ASSERT(value.IsSymbol());
-  raw_ptr()->set_name(value.raw());
+  untag()->set_name(value.ptr());
 }
 
 void TypeParameter::set_bound(const AbstractType& value) const {
-  raw_ptr()->set_bound(value.raw());
+  ASSERT(!IsCanonical());
+  untag()->set_bound(value.ptr());
 }
 
 void TypeParameter::set_default_argument(const AbstractType& value) const {
-  raw_ptr()->set_default_argument(value.raw());
+  ASSERT(!IsCanonical());
+  untag()->set_default_argument(value.ptr());
 }
 
 AbstractTypePtr TypeParameter::GetFromTypeArguments(
@@ -20645,28 +21123,31 @@
     intptr_t num_free_fun_type_params,
     Heap::Space space,
     TrailPtr trail) const {
-  ASSERT(IsFinalized());
   AbstractType& result = AbstractType::Handle();
   if (IsFunctionTypeParameter()) {
+    ASSERT(IsFinalized());
     if (index() >= num_free_fun_type_params) {
       // Do not instantiate the function type parameter, but possibly its bound.
-      result = raw();
+      result = ptr();
       AbstractType& upper_bound = AbstractType::Handle(bound());
       if (!upper_bound.IsInstantiated(kAny, num_free_fun_type_params,
                                       nullptr)) {
         // Use trail to break cycles created by bound referring to type param.
-        if (OnlyBuddyInTrail(trail) == Object::null()) {
-          AddOnlyBuddyToTrail(&trail, *this);
-          upper_bound = upper_bound.InstantiateFrom(
-              instantiator_type_arguments, function_type_arguments,
-              num_free_fun_type_params, space, trail);
-          if (upper_bound.raw() == Type::NeverType()) {
-            // Normalize 'X extends Never' to 'Never'.
-            result = Type::NeverType();
-          } else if (upper_bound.raw() != bound()) {
-            result ^= Object::Clone(result, space);
-            TypeParameter::Cast(result).set_bound(upper_bound);
-          }
+        // The instantiation trail must contain pairs, so add itself as buddy.
+        if (TestAndAddBuddyToTrail(&trail, *this)) {
+          // If the type parameter is already in the trail, it is returned
+          // unchanged here and will be processed when returning from recursion.
+          return ptr();
+        }
+        upper_bound = upper_bound.InstantiateFrom(
+            instantiator_type_arguments, function_type_arguments,
+            num_free_fun_type_params, space, trail);
+        if (upper_bound.ptr() == Type::NeverType()) {
+          // Normalize 'X extends Never' to 'Never'.
+          result = Type::NeverType();
+        } else if (upper_bound.ptr() != bound()) {
+          result ^= Object::Clone(result, space);
+          TypeParameter::Cast(result).set_bound(upper_bound);
         }
       }
     } else if (function_type_arguments.IsNull()) {
@@ -20677,6 +21158,7 @@
     }
   } else {
     ASSERT(IsClassTypeParameter());
+    ASSERT(IsFinalized() || IsBeingFinalized());
     if (instantiator_type_arguments.IsNull()) {
       return Type::DynamicType();
     }
@@ -20702,44 +21184,70 @@
 AbstractTypePtr TypeParameter::Canonicalize(Thread* thread,
                                             TrailPtr trail) const {
   ASSERT(IsFinalized());
-  if (IsCanonical()) {
-    return this->raw();
-  }
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-
-  const Class& cls = Class::Handle(zone, parameterized_class());
-  const Function& function = Function::Handle(
-      zone, cls.IsNull() ? parameterized_function() : Function::null());
-  const TypeArguments& type_params = TypeArguments::Handle(
-      zone, cls.IsNull() ? function.type_parameters() : cls.type_parameters());
-  const intptr_t offset =
-      cls.IsNull() ? function.NumParentTypeParameters()
-                   : (cls.NumTypeArguments() - cls.NumTypeParameters());
-  TypeParameter& type_parameter = TypeParameter::Handle(zone);
-  type_parameter ^= type_params.TypeAt(index() - offset);
-  ASSERT(!type_parameter.IsNull());
-  if (type_parameter.nullability() == nullability()) {
-    ASSERT(this->Equals(type_parameter));
-    ASSERT(type_parameter.IsCanonical());
-    ASSERT(type_parameter.IsDeclaration());
-    ASSERT(type_parameter.IsOld());
-    return type_parameter.raw();
+  if (IsCanonical()) {
+#ifdef DEBUG
+    // Verify that all fields are allocated in old space and are canonical.
+    AbstractType& type = AbstractType::Handle(zone);
+    type = bound();
+    ASSERT(type.IsOld());
+    ASSERT(type.IsCanonical());
+    type = default_argument();
+    ASSERT(type.IsOld());
+    ASSERT(type.IsCanonical());
+#endif
+    return this->ptr();
   }
-
-  ObjectStore* object_store = isolate->object_store();
+  auto isolate_group = thread->isolate_group();
+  ObjectStore* object_store = isolate_group->object_store();
+  TypeParameter& type_parameter = TypeParameter::Handle(zone);
   {
-    SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+    CanonicalTypeParameterSet table(zone,
+                                    object_store->canonical_type_parameters());
+    type_parameter ^= table.GetOrNull(CanonicalTypeParameterKey(*this));
+    ASSERT(object_store->canonical_type_parameters() == table.Release().ptr());
+  }
+  if (type_parameter.IsNull()) {
+    // The type parameter was not found in the table. It is not canonical yet.
+    // Canonicalize its bound and default argument.
+    // However, if the type parameter is already being canonicalized, it is part
+    // of a cycle via its bound. Return it now and let the caller finish
+    // canonicalizing it.
+    if (TestAndAddToTrail(&trail)) {
+      return ptr();
+    }
+    AbstractType& type = AbstractType::Handle(zone);
+    type = bound();
+    type = type.Canonicalize(thread, trail);
+    if (IsCanonical()) {
+      // Canonicalizing bound or default argument canonicalized this type
+      // parameter as a side effect.
+      ASSERT(IsRecursive());  // Self-referring bound or default argument.
+      return ptr();
+    }
+    set_bound(type);
+    type = default_argument();
+    type = type.Canonicalize(thread, trail);
+    if (IsCanonical()) {
+      // Canonicalizing bound or default argument canonicalized this type
+      // parameter as a side effect.
+      ASSERT(IsRecursive());  // Self-referring bound or default argument.
+      return this->ptr();
+    }
+    set_default_argument(type);
+    // Check to see if the type parameter got added to canonical table as part
+    // of the canonicalization of its bound and default argument.
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
     CanonicalTypeParameterSet table(zone,
                                     object_store->canonical_type_parameters());
     type_parameter ^= table.GetOrNull(CanonicalTypeParameterKey(*this));
     if (type_parameter.IsNull()) {
-      // The type parameter was not found in the table. It is not canonical yet.
-      // Add this type parameter into the canonical list of type parameters.
+      // Add this type parameter into the canonical table of type parameters.
       if (this->IsNew()) {
         type_parameter ^= Object::Clone(*this, Heap::kOld);
       } else {
-        type_parameter = this->raw();
+        type_parameter = this->ptr();
       }
       ASSERT(type_parameter.IsOld());
       type_parameter.SetCanonical();  // Mark object as being canonical.
@@ -20748,80 +21256,47 @@
     }
     object_store->set_canonical_type_parameters(table.Release());
   }
-  ASSERT(!type_parameter.IsDeclaration());
-  return type_parameter.raw();
+  return type_parameter.ptr();
 }
 
 #if defined(DEBUG)
 bool TypeParameter::CheckIsCanonical(Thread* thread) const {
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
 
-  const Class& cls = Class::Handle(zone, parameterized_class());
-  const Function& function = Function::Handle(
-      zone, cls.IsNull() ? parameterized_function() : Function::null());
-  const TypeArguments& type_params = TypeArguments::Handle(
-      zone, cls.IsNull() ? function.type_parameters() : cls.type_parameters());
-  const intptr_t offset =
-      IsFinalized()
-          ? (cls.IsNull() ? function.NumParentTypeParameters()
-                          : (cls.NumTypeArguments() - cls.NumTypeParameters()))
-          : 0;
   TypeParameter& type_parameter = TypeParameter::Handle(zone);
-  type_parameter ^= type_params.TypeAt(index() - offset);
-  ASSERT(!type_parameter.IsNull());
-  if (type_parameter.nullability() == nullability()) {
-    ASSERT(type_parameter.IsCanonical());
-    return (raw() == type_parameter.raw());
-  }
-
-  ObjectStore* object_store = isolate->object_store();
+  ObjectStore* object_store = isolate_group->object_store();
   {
-    SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
+    SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
     CanonicalTypeParameterSet table(zone,
                                     object_store->canonical_type_parameters());
     type_parameter ^= table.GetOrNull(CanonicalTypeParameterKey(*this));
     object_store->set_canonical_type_parameters(table.Release());
   }
-  return (raw() == type_parameter.raw());
+  return (ptr() == type_parameter.ptr());
 }
 #endif  // DEBUG
 
-void TypeParameter::EnumerateURIs(URIs* uris) const {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  GrowableHandlePtrArray<const String> pieces(zone, 4);
-  pieces.Add(String::Handle(zone, name()));
-  Class& cls = Class::Handle(zone, parameterized_class());
-  if (cls.IsNull()) {
-    const Function& fun = Function::Handle(zone, parameterized_function());
-    pieces.Add(Symbols::SpaceOfSpace());
-    pieces.Add(String::Handle(zone, fun.UserVisibleName()));
-    cls = fun.Owner();  // May be null.
-    // TODO(regis): Should we keep the function owner for better error messages?
-  }
-  if (!cls.IsNull()) {
-    pieces.Add(Symbols::SpaceOfSpace());
-    pieces.Add(String::Handle(zone, cls.UserVisibleName()));
-    const String& name =
-        String::Handle(zone, Symbols::FromConcatAll(thread, pieces));
-    const Library& library = Library::Handle(zone, cls.library());
-    const String& uri = String::Handle(zone, library.url());
-    AddURI(uris, name, uri);
-  }
-}
-
 intptr_t TypeParameter::ComputeHash() const {
-  ASSERT(IsFinalized());
-  uint32_t result;
-  if (IsClassTypeParameter()) {
-    result = parameterized_class_id();
+  ASSERT(IsFinalized() || IsBeingFinalized());  // Bound may not be finalized.
+  uint32_t result = parameterized_class_id();
+  // Hashing the bound reduces collisions, but may also create cycles.
+  // Therefore, we only hash the type_class_id of the bound,
+  // and do not use its full hash, as we do for TypeRef.
+  const AbstractType& upper_bound = AbstractType::Handle(bound());
+  if (upper_bound.IsTypeParameter()) {
+    ASSERT(upper_bound.IsFinalized() || upper_bound.IsBeingFinalized());
+    result = CombineHashes(result, TypeParameter::Cast(upper_bound).index());
   } else {
-    result = Function::Handle(parameterized_function()).Hash();
+    // Note that the bound may not be finalized yet.
+    result = CombineHashes(result, upper_bound.type_class_id());
   }
-  // No need to include the hash of the bound, since the type parameter is fully
-  // identified by its class and index.
+  // Since the default argument is ignored when comparing two generic function
+  // types for type equality, the hash does not depend on it.
+  result = CombineHashes(result, IsGenericCovariantImpl() ? 1 : 0);
+  result = CombineHashes(result, base());
   result = CombineHashes(result, index());
+  result = CombineHashes(result, String::Handle(name()).Hash());
   // A legacy type should have the same hash as its non-nullable version to be
   // consistent with the definition of type equality in Dart code.
   Nullability type_param_nullability = nullability();
@@ -20841,61 +21316,41 @@
 }
 
 TypeParameterPtr TypeParameter::New(const Class& parameterized_class,
-                                    const Function& parameterized_function,
+                                    intptr_t base,
                                     intptr_t index,
                                     const String& name,
                                     const AbstractType& bound,
                                     bool is_generic_covariant_impl,
-                                    Nullability nullability,
-                                    TokenPosition token_pos) {
-  ASSERT(parameterized_class.IsNull() != parameterized_function.IsNull());
+                                    Nullability nullability) {
   Zone* Z = Thread::Current()->zone();
   const TypeParameter& result = TypeParameter::Handle(Z, TypeParameter::New());
   result.set_parameterized_class(parameterized_class);
-  result.set_parameterized_function(parameterized_function);
+  result.set_base(base);
   result.set_index(index);
   result.set_name(name);
   result.set_bound(bound);
+  result.set_default_argument(Object::dynamic_type());
   result.set_flags(0);
   result.set_nullability(nullability);
   result.SetGenericCovariantImpl(is_generic_covariant_impl);
-  result.SetDeclaration(false);
   result.SetHash(0);
-  result.set_token_pos(token_pos);
 
   result.SetTypeTestingStub(
       Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
-  return result.raw();
-}
-
-void TypeParameter::set_token_pos(TokenPosition token_pos) const {
-  ASSERT(!token_pos.IsClassifying());
-  StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
+  return result.ptr();
 }
 
 void TypeParameter::set_flags(uint8_t flags) const {
-  StoreNonPointer(&raw_ptr()->flags_, flags);
+  StoreNonPointer(&untag()->flags_, flags);
 }
 
 const char* TypeParameter::ToCString() const {
   Thread* thread = Thread::Current();
-  ZoneTextBuffer printer(thread->zone());
-  auto& name_str = String::Handle(thread->zone(), name());
-  printer.Printf("TypeParameter: name ");
-  printer.AddString(name_str.ToCString());
+  Zone* zone = thread->zone();
+  ZoneTextBuffer printer(zone);
+  printer.Printf("TypeParameter: ");
+  printer.AddString(String::Handle(zone, name()).ToCString());
   printer.AddString(NullabilitySuffix(kInternalName));
-  printer.Printf("; index: %" Pd ";", index());
-  if (IsFunctionTypeParameter()) {
-    const Function& function = Function::Handle(parameterized_function());
-    printer.Printf(" function: ");
-    name_str = function.name();
-    printer.AddString(name_str.ToCString());
-  } else {
-    const Class& cls = Class::Handle(parameterized_class());
-    printer.Printf(" class: ");
-    name_str = cls.Name();
-    printer.AddString(name_str.ToCString());
-  }
   printer.Printf("; bound: ");
   const AbstractType& upper_bound = AbstractType::Handle(bound());
   if (upper_bound.IsNull()) {
@@ -20903,6 +21358,15 @@
   } else {
     upper_bound.PrintName(kInternalName, &printer);
   }
+  if (FLAG_show_internal_names) {
+    printer.Printf("; default: ");
+    const AbstractType& default_arg = AbstractType::Handle(default_argument());
+    if (default_arg.IsNull()) {
+      printer.AddString("<null>");
+    } else {
+      default_arg.PrintName(kInternalName, &printer);
+    }
+  }
   return printer.buffer();
 }
 
@@ -20932,12 +21396,12 @@
     case kMintCid: {
       Mint& result = Mint::Handle(zone);
       result ^= cls.LookupCanonicalMint(zone, Mint::Cast(*this).value());
-      return (result.raw() == this->raw());
+      return (result.ptr() == this->ptr());
     }
     case kDoubleCid: {
       Double& dbl = Double::Handle(zone);
       dbl ^= cls.LookupCanonicalDouble(zone, Double::Cast(*this).value());
-      return (dbl.raw() == this->raw());
+      return (dbl.ptr() == this->ptr());
     }
     default:
       UNREACHABLE();
@@ -21057,17 +21521,17 @@
 }
 
 IntegerPtr Integer::AsValidInteger() const {
-  if (IsSmi()) return raw();
+  if (IsSmi()) return ptr();
   if (IsMint()) {
     Mint& mint = Mint::Handle();
-    mint ^= raw();
+    mint ^= ptr();
     if (Smi::IsValid(mint.value())) {
       return Smi::New(static_cast<intptr_t>(mint.value()));
     } else {
-      return raw();
+      return ptr();
     }
   }
-  return raw();
+  return ptr();
 }
 
 const char* Integer::ToHexCString(Zone* zone) const {
@@ -21088,8 +21552,8 @@
   // In 64-bit mode, the result of any operation between two Smis will fit in a
   // 64-bit signed result, except the product of two Smis (see below).
   if (IsSmi() && other.IsSmi()) {
-    const intptr_t left_value = Smi::Value(Smi::RawCast(raw()));
-    const intptr_t right_value = Smi::Value(Smi::RawCast(other.raw()));
+    const intptr_t left_value = Smi::Value(Smi::RawCast(ptr()));
+    const intptr_t right_value = Smi::Value(Smi::RawCast(other.ptr()));
     switch (operation) {
       case Token::kADD:
         return Integer::New(left_value + right_value, space);
@@ -21166,8 +21630,8 @@
                           const Integer& other,
                           Heap::Space space) const {
   if (IsSmi() && other.IsSmi()) {
-    intptr_t op1_value = Smi::Value(Smi::RawCast(raw()));
-    intptr_t op2_value = Smi::Value(Smi::RawCast(other.raw()));
+    intptr_t op1_value = Smi::Value(Smi::RawCast(ptr()));
+    intptr_t op2_value = Smi::Value(Smi::RawCast(other.ptr()));
     intptr_t result = 0;
     switch (kind) {
       case Token::kBIT_AND:
@@ -21264,17 +21728,18 @@
 }
 
 ClassPtr Smi::Class() {
-  return Isolate::Current()->object_store()->smi_class();
+  return IsolateGroup::Current()->object_store()->smi_class();
 }
 
 void Mint::set_value(int64_t value) const {
-  StoreNonPointer(&raw_ptr()->value_, value);
+  StoreNonPointer(&untag()->value_, value);
 }
 
 MintPtr Mint::New(int64_t val, Heap::Space space) {
   // Do not allocate a Mint if Smi would do.
   ASSERT(!Smi::IsValid(val));
-  ASSERT(Isolate::Current()->object_store()->mint_class() != Class::null());
+  ASSERT(IsolateGroup::Current()->object_store()->mint_class() !=
+         Class::null());
   Mint& result = Mint::Handle();
   {
     ObjectPtr raw =
@@ -21283,7 +21748,7 @@
     result ^= raw;
   }
   result.set_value(val);
-  return result.raw();
+  return result.ptr();
 }
 
 MintPtr Mint::NewCanonical(int64_t value) {
@@ -21297,23 +21762,24 @@
   // Do not allocate a Mint if Smi would do.
   ASSERT(!Smi::IsValid(value));
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  const Class& cls = Class::Handle(zone, isolate->object_store()->mint_class());
+  auto isolate_group = thread->isolate_group();
+  const Class& cls =
+      Class::Handle(zone, isolate_group->object_store()->mint_class());
   Mint& canonical_value =
       Mint::Handle(zone, cls.LookupCanonicalMint(zone, value));
   if (!canonical_value.IsNull()) {
-    return canonical_value.raw();
+    return canonical_value.ptr();
   }
   canonical_value = Mint::New(value, Heap::kOld);
   canonical_value.SetCanonical();
   // The value needs to be added to the constants list. Grow the list if
   // it is full.
   cls.InsertCanonicalMint(zone, canonical_value);
-  return canonical_value.raw();
+  return canonical_value.ptr();
 }
 
 bool Mint::Equals(const Instance& other) const {
-  if (this->raw() == other.raw()) {
+  if (this->ptr() == other.ptr()) {
     // Both handles point to the same raw instance.
     return true;
   }
@@ -21358,13 +21824,13 @@
 }
 
 void Double::set_value(double value) const {
-  StoreNonPointer(&raw_ptr()->value_, value);
+  StoreNonPointer(&untag()->value_, value);
 }
 
 bool Double::BitwiseEqualsToDouble(double value) const {
   intptr_t value_offset = Double::value_offset();
   void* this_addr = reinterpret_cast<void*>(
-      reinterpret_cast<uword>(this->raw_ptr()) + value_offset);
+      reinterpret_cast<uword>(this->untag()) + value_offset);
   void* other_addr = reinterpret_cast<void*>(&value);
   return (memcmp(this_addr, other_addr, sizeof(value)) == 0);
 }
@@ -21380,7 +21846,7 @@
 }
 
 bool Double::CanonicalizeEquals(const Instance& other) const {
-  if (this->raw() == other.raw()) {
+  if (this->ptr() == other.ptr()) {
     return true;  // "===".
   }
   if (other.IsNull() || !other.IsDouble()) {
@@ -21394,7 +21860,8 @@
 }
 
 DoublePtr Double::New(double d, Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->double_class() != Class::null());
+  ASSERT(IsolateGroup::Current()->object_store()->double_class() !=
+         Class::null());
   Double& result = Double::Handle();
   {
     ObjectPtr raw =
@@ -21403,13 +21870,13 @@
     result ^= raw;
   }
   result.set_value(d);
-  return result.raw();
+  return result.ptr();
 }
 
 DoublePtr Double::New(const String& str, Heap::Space space) {
   double double_value;
   if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
-    return Double::Handle().raw();
+    return Double::Handle().ptr();
   }
   return New(double_value, space);
 }
@@ -21423,27 +21890,27 @@
 
 DoublePtr Double::NewCanonicalLocked(Thread* thread, double value) {
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   const Class& cls =
-      Class::Handle(zone, isolate->object_store()->double_class());
+      Class::Handle(zone, isolate_group->object_store()->double_class());
   // Linear search to see whether this value is already present in the
   // list of canonicalized constants.
   Double& canonical_value =
       Double::Handle(zone, cls.LookupCanonicalDouble(zone, value));
   if (!canonical_value.IsNull()) {
-    return canonical_value.raw();
+    return canonical_value.ptr();
   }
   canonical_value = Double::New(value, Heap::kOld);
   canonical_value.SetCanonical();
   // The value needs to be added to the constants list.
   cls.InsertCanonicalDouble(zone, canonical_value);
-  return canonical_value.raw();
+  return canonical_value.ptr();
 }
 
 DoublePtr Double::NewCanonical(const String& str) {
   double double_value;
   if (!CStringToDouble(str.ToCString(), str.Length(), &double_value)) {
-    return Double::Handle().raw();
+    return Double::Handle().ptr();
   }
   return NewCanonical(double_value);
 }
@@ -21515,25 +21982,25 @@
 
 intptr_t String::Hash(StringPtr raw) {
   StringHasher hasher;
-  uword length = Smi::Value(raw->ptr()->length());
+  uword length = Smi::Value(raw->untag()->length());
   if (raw->IsOneByteString() || raw->IsExternalOneByteString()) {
     const uint8_t* data;
     if (raw->IsOneByteString()) {
-      data = static_cast<OneByteStringPtr>(raw)->ptr()->data();
+      data = static_cast<OneByteStringPtr>(raw)->untag()->data();
     } else {
       ASSERT(raw->IsExternalOneByteString());
       ExternalOneByteStringPtr str = static_cast<ExternalOneByteStringPtr>(raw);
-      data = str->ptr()->external_data_;
+      data = str->untag()->external_data_;
     }
     return String::Hash(data, length);
   } else {
     const uint16_t* data;
     if (raw->IsTwoByteString()) {
-      data = static_cast<TwoByteStringPtr>(raw)->ptr()->data();
+      data = static_cast<TwoByteStringPtr>(raw)->untag()->data();
     } else {
       ASSERT(raw->IsExternalTwoByteString());
       ExternalTwoByteStringPtr str = static_cast<ExternalTwoByteStringPtr>(raw);
-      data = str->ptr()->external_data_;
+      data = str->untag()->external_data_;
     }
     return String::Hash(data, length);
   }
@@ -21558,7 +22025,7 @@
 }
 
 intptr_t String::CharSize() const {
-  intptr_t class_id = raw()->GetClassId();
+  intptr_t class_id = ptr()->GetClassId();
   if (class_id == kOneByteStringCid || class_id == kExternalOneByteStringCid) {
     return kOneByteChar;
   }
@@ -21568,7 +22035,7 @@
 }
 
 void* String::GetPeer() const {
-  intptr_t class_id = raw()->GetClassId();
+  intptr_t class_id = ptr()->GetClassId();
   if (class_id == kExternalOneByteStringCid) {
     return ExternalOneByteString::GetPeer(*this);
   }
@@ -21577,7 +22044,7 @@
 }
 
 bool String::Equals(const Instance& other) const {
-  if (this->raw() == other.raw()) {
+  if (this->ptr() == other.ptr()) {
     // Both handles point to the same raw instance.
     return true;
   }
@@ -21738,7 +22205,7 @@
 
 InstancePtr String::CanonicalizeLocked(Thread* thread) const {
   if (IsCanonical()) {
-    return this->raw();
+    return this->ptr();
   }
   return Symbols::New(Thread::Current(), *this);
 }
@@ -21747,7 +22214,7 @@
 bool String::CheckIsCanonical(Thread* thread) const {
   Zone* zone = thread->zone();
   const String& str = String::Handle(zone, Symbols::Lookup(thread, *this));
-  return (str.raw() == this->raw());
+  return (str.ptr() == this->ptr());
 }
 #endif  // DEBUG
 
@@ -21773,7 +22240,7 @@
         return String::null();
       }
     }
-    return strobj.raw();
+    return strobj.ptr();
   }
   ASSERT((type == Utf8::kBMP) || (type == Utf8::kSupplementary));
   const String& strobj = String::Handle(TwoByteString::New(len, space));
@@ -21783,7 +22250,7 @@
     Utf8::ReportInvalidByte(utf8_array, array_len, len);
     return String::null();
   }
-  return strobj.raw();
+  return strobj.ptr();
 }
 
 StringPtr String::FromLatin1(const uint8_t* latin1_array,
@@ -21842,7 +22309,7 @@
     result = TwoByteString::New(len, space);
   }
   String::Copy(result, 0, str, 0, len);
-  return result.raw();
+  return result.ptr();
 }
 
 StringPtr String::NewExternal(const uint8_t* characters,
@@ -22195,7 +22662,7 @@
   ASSERT(begin_index >= 0);
   ASSERT(length >= 0);
   if (begin_index <= str.Length() && length == 0) {
-    return Symbols::Empty().raw();
+    return Symbols::Empty().ptr();
   }
   if (begin_index > str.Length()) {
     return String::null();
@@ -22218,10 +22685,13 @@
     result = TwoByteString::New(length, space);
   }
   String::Copy(result, 0, str, begin_index, length);
-  return result.raw();
+  return result.ptr();
 }
 
 const char* String::ToCString() const {
+  if (IsNull()) {
+    return "String: null";
+  }
   const intptr_t len = Utf8::Length(*this);
   Zone* zone = Thread::Current()->zone();
   uint8_t* result = zone->Alloc<uint8_t>(len + 1);
@@ -22248,8 +22718,8 @@
                                                  Dart_HandleFinalizer callback,
                                                  intptr_t external_size) {
   ASSERT(callback != NULL);
-  return FinalizablePersistentHandle::New(Isolate::Current(), referent, peer,
-                                          callback, external_size,
+  return FinalizablePersistentHandle::New(IsolateGroup::Current(), referent,
+                                          peer, callback, external_size,
                                           /*auto_delete=*/true);
 }
 
@@ -22269,7 +22739,7 @@
     dst_max = Utils::Maximum(dst_max, dst);
   }
   if (!has_mapping) {
-    return str.raw();
+    return str.ptr();
   }
   if (Utf::IsLatin1(dst_max)) {
     return OneByteString::Transform(mapping, str, space);
@@ -22389,12 +22859,12 @@
   UNREACHABLE();
 
 bool String::EqualsIgnoringPrivateKey(const String& str1, const String& str2) {
-  if (str1.raw() == str2.raw()) {
+  if (str1.ptr() == str2.ptr()) {
     return true;  // Both handles point to the same raw instance.
   }
   NoSafepointScope no_safepoint;
-  intptr_t str1_class_id = str1.raw()->GetClassId();
-  intptr_t str2_class_id = str2.raw()->GetClassId();
+  intptr_t str1_class_id = str1.ptr()->GetClassId();
+  intptr_t str2_class_id = str2.ptr()->GetClassId();
   switch (str1_class_id) {
     case kOneByteStringCid:
       EQUALS_IGNORING_PRIVATE_KEY(str2_class_id, OneByteString, str1, str2);
@@ -22499,9 +22969,9 @@
 }
 
 OneByteStringPtr OneByteString::New(intptr_t len, Heap::Space space) {
-  ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
-         ((Isolate::Current()->object_store() != NULL) &&
-          (Isolate::Current()->object_store()->one_byte_string_class() !=
+  ASSERT((IsolateGroup::Current() == Dart::vm_isolate_group()) ||
+         ((IsolateGroup::Current()->object_store() != NULL) &&
+          (IsolateGroup::Current()->object_store()->one_byte_string_class() !=
            Class::null())));
   if (len < 0 || len > kMaxElements) {
     // This should be caught before we reach here.
@@ -22512,9 +22982,9 @@
                                      OneByteString::InstanceSize(len), space);
     NoSafepointScope no_safepoint;
     OneByteStringPtr result = static_cast<OneByteStringPtr>(raw);
-    result->ptr()->set_length(Smi::New(len));
+    result->untag()->set_length(Smi::New(len));
 #if !defined(HASH_IN_OBJECT_HEADER)
-    result->ptr()->set_hash(Smi::New(0));
+    result->untag()->set_hash(Smi::New(0));
 #endif
     return result;
   }
@@ -22667,8 +23137,8 @@
   OneByteStringPtr result = OneByteString::New(length, space);
   NoSafepointScope no_safepoint;
   if (length > 0) {
-    uint8_t* dest = &result->ptr()->data()[0];
-    const uint8_t* src = &raw_ptr(str)->data()[begin_index];
+    uint8_t* dest = &result->untag()->data()[0];
+    const uint8_t* src = &untag(str)->data()[begin_index];
     memmove(dest, src, length);
   }
   return result;
@@ -22707,7 +23177,7 @@
 }
 
 TwoByteStringPtr TwoByteString::New(intptr_t len, Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->two_byte_string_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->two_byte_string_class() !=
          nullptr);
   if (len < 0 || len > kMaxElements) {
     // This should be caught before we reach here.
@@ -22861,8 +23331,9 @@
     intptr_t external_allocation_size,
     Dart_HandleFinalizer callback,
     Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->external_one_byte_string_class() !=
-         Class::null());
+  ASSERT(IsolateGroup::Current()
+             ->object_store()
+             ->external_one_byte_string_class() != Class::null());
   if (len < 0 || len > kMaxElements) {
     // This should be caught before we reach here.
     FATAL1("Fatal error in ExternalOneByteString::New: invalid len %" Pd "\n",
@@ -22890,8 +23361,9 @@
     intptr_t external_allocation_size,
     Dart_HandleFinalizer callback,
     Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->external_two_byte_string_class() !=
-         Class::null());
+  ASSERT(IsolateGroup::Current()
+             ->object_store()
+             ->external_two_byte_string_class() != Class::null());
   if (len < 0 || len > kMaxElements) {
     // This should be caught before we reach here.
     FATAL1("Fatal error in ExternalTwoByteString::New: invalid len %" Pd "\n",
@@ -22913,7 +23385,8 @@
 }
 
 BoolPtr Bool::New(bool value) {
-  ASSERT(Isolate::Current()->object_store()->bool_class() != Class::null());
+  ASSERT(IsolateGroup::Current()->object_store()->bool_class() !=
+         Class::null());
   Bool& result = Bool::Handle();
   {
     // Since the two boolean instances are singletons we allocate them straight
@@ -22925,7 +23398,7 @@
   }
   result.set_value(value);
   result.SetCanonical();
-  return result.raw();
+  return result.ptr();
 }
 
 const char* Bool::ToCString() const {
@@ -22933,7 +23406,7 @@
 }
 
 bool Array::CanonicalizeEquals(const Instance& other) const {
-  if (this->raw() == other.raw()) {
+  if (this->ptr() == other.ptr()) {
     // Both handles point to the same raw instance.
     return true;
   }
@@ -22976,7 +23449,7 @@
     return 1;
   }
   Thread* thread = Thread::Current();
-  uint32_t hash = thread->heap()->GetCanonicalHash(raw());
+  uint32_t hash = thread->heap()->GetCanonicalHash(ptr());
   if (hash != 0) {
     return hash;
   }
@@ -22988,16 +23461,17 @@
     hash = CombineHashes(hash, member.CanonicalizeHash());
   }
   hash = FinalizeHash(hash, kHashBits);
-  thread->heap()->SetCanonicalHash(raw(), hash);
+  thread->heap()->SetCanonicalHash(ptr(), hash);
   return hash;
 }
 
 ArrayPtr Array::New(intptr_t len, Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->array_class() != Class::null());
+  ASSERT(IsolateGroup::Current()->object_store()->array_class() !=
+         Class::null());
   ArrayPtr result = New(kClassId, len, space);
   if (UseCardMarkingForAllocation(len)) {
     ASSERT(result->IsOldObject());
-    result->ptr()->SetCardRememberedBitUnsynchronized();
+    result->untag()->SetCardRememberedBitUnsynchronized();
   }
   return result;
 }
@@ -23012,7 +23486,7 @@
     type_args = type_args.Canonicalize(Thread::Current(), nullptr);
     result.SetTypeArguments(type_args);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 ArrayPtr Array::New(intptr_t class_id, intptr_t len, Heap::Space space) {
@@ -23024,7 +23498,7 @@
     ArrayPtr raw = static_cast<ArrayPtr>(
         Object::Allocate(class_id, Array::InstanceSize(len), space));
     NoSafepointScope no_safepoint;
-    raw->ptr()->set_length(Smi::New(len));
+    raw->untag()->set_length(Smi::New(len));
     return raw;
   }
 }
@@ -23042,13 +23516,13 @@
     dest.SetTypeArguments(TypeArguments::Handle(GetTypeArguments()));
   }
 
-  return dest.raw();
+  return dest.ptr();
 }
 
 void Array::MakeImmutable() const {
   if (IsImmutable()) return;
   ASSERT(!IsCanonical());
-  raw_ptr()->SetClassId(kImmutableArrayCid);
+  untag()->SetClassId(kImmutableArrayCid);
 }
 
 const char* Array::ToCString() const {
@@ -23079,7 +23553,7 @@
     obj = source.At(i);
     result.SetAt(i, obj);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 void Array::Truncate(intptr_t new_len) const {
@@ -23088,7 +23562,7 @@
   }
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  const Array& array = Array::Handle(zone, this->raw());
+  const Array& array = Array::Handle(zone, this->ptr());
 
   intptr_t old_len = array.Length();
   ASSERT(new_len <= old_len);
@@ -23108,18 +23582,18 @@
   // Update the size in the header field and length of the array object.
   // These release operations are balanced by acquire operations in the
   // concurrent sweeper.
-  uword old_tags = array.raw_ptr()->tags_;
+  uword old_tags = array.untag()->tags_;
   uword new_tags;
-  ASSERT(kArrayCid == ObjectLayout::ClassIdTag::decode(old_tags));
+  ASSERT(kArrayCid == UntaggedObject::ClassIdTag::decode(old_tags));
   do {
-    new_tags = ObjectLayout::SizeTag::update(new_size, old_tags);
-  } while (!array.raw_ptr()->tags_.compare_exchange_weak(
+    new_tags = UntaggedObject::SizeTag::update(new_size, old_tags);
+  } while (!array.untag()->tags_.compare_exchange_weak(
       old_tags, new_tags, std::memory_order_release));
 
   // Between the CAS of the header above and the SetLength below, the array is
   // temporarily in an inconsistent state. The header is considered the
-  // overriding source of object size by ObjectLayout::Size, but the ASSERTs in
-  // ObjectLayout::HeapSizeFromClass must handle this special case.
+  // overriding source of object size by UntaggedObject::HeapSize, but the
+  // ASSERTs in UntaggedObject::HeapSizeFromClass must handle this special case.
   array.SetLengthRelease(new_len);
 }
 
@@ -23136,7 +23610,7 @@
     if (type_arguments.IsNull() && !unique) {
       // This is a raw List (as in no type arguments), so we can return the
       // simple empty array.
-      return Object::empty_array().raw();
+      return Object::empty_array().ptr();
     }
 
     // The backing array may be a shared instance, or may not have correct
@@ -23144,7 +23618,7 @@
     Heap::Space space = thread->IsMutatorThread() ? Heap::kNew : Heap::kOld;
     Array& array = Array::Handle(zone, Array::New(0, space));
     array.SetTypeArguments(type_arguments);
-    return array.raw();
+    return array.ptr();
   }
   const Array& array = Array::Handle(zone, growable_array.data());
   ASSERT(array.IsArray());
@@ -23156,7 +23630,7 @@
 
   // Truncate the old backing array and return it.
   array.Truncate(used_len);
-  return array.raw();
+  return array.ptr();
 }
 
 void Array::CanonicalizeFieldsLocked(Thread* thread) const {
@@ -23173,7 +23647,7 @@
 }
 
 ImmutableArrayPtr ImmutableArray::New(intptr_t len, Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->immutable_array_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->immutable_array_class() !=
          Class::null());
   return static_cast<ImmutableArrayPtr>(Array::New(kClassId, len, space));
 }
@@ -23200,7 +23674,7 @@
   const Array& contents = Array::Handle(data());
   const Array& new_contents =
       Array::Handle(Array::Grow(contents, new_capacity, space));
-  raw_ptr()->set_data(new_contents.raw());
+  untag()->set_data(new_contents.ptr());
 }
 
 ObjectPtr GrowableObjectArray::RemoveLast() const {
@@ -23211,12 +23685,12 @@
   const PassiveObject& obj = PassiveObject::Handle(contents.At(index));
   contents.SetAt(index, Object::null_object());
   SetLength(index);
-  return obj.raw();
+  return obj.ptr();
 }
 
 GrowableObjectArrayPtr GrowableObjectArray::New(intptr_t capacity,
                                                 Heap::Space space) {
-  ArrayPtr raw_data = (capacity == 0) ? Object::empty_array().raw()
+  ArrayPtr raw_data = (capacity == 0) ? Object::empty_array().ptr()
                                       : Array::New(capacity, space);
   const Array& data = Array::Handle(raw_data);
   return New(data, space);
@@ -23224,8 +23698,9 @@
 
 GrowableObjectArrayPtr GrowableObjectArray::New(const Array& array,
                                                 Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->growable_object_array_class() !=
-         Class::null());
+  ASSERT(
+      IsolateGroup::Current()->object_store()->growable_object_array_class() !=
+      Class::null());
   GrowableObjectArray& result = GrowableObjectArray::Handle();
   {
     ObjectPtr raw =
@@ -23236,7 +23711,7 @@
     result.SetLength(0);
     result.SetData(array);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* GrowableObjectArray::ToCString() const {
@@ -23299,7 +23774,7 @@
                                     intptr_t used_data,
                                     intptr_t deleted_keys,
                                     Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->linked_hash_map_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->linked_hash_map_class() !=
          Class::null());
   LinkedHashMap& result =
       LinkedHashMap::Handle(LinkedHashMap::NewUninitialized(space));
@@ -23308,11 +23783,11 @@
   result.SetHashMask(hash_mask);
   result.SetUsedData(used_data);
   result.SetDeletedKeys(deleted_keys);
-  return result.raw();
+  return result.ptr();
 }
 
 LinkedHashMapPtr LinkedHashMap::NewUninitialized(Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->linked_hash_map_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->linked_hash_map_class() !=
          Class::null());
   LinkedHashMap& result = LinkedHashMap::Handle();
   {
@@ -23321,7 +23796,7 @@
     NoSafepointScope no_safepoint;
     result ^= raw;
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* LinkedHashMap::ToCString() const {
@@ -23339,7 +23814,7 @@
                             float v2,
                             float v3,
                             Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->float32x4_class() !=
          Class::null());
   Float32x4& result = Float32x4::Handle();
   {
@@ -23352,11 +23827,11 @@
   result.set_y(v1);
   result.set_z(v2);
   result.set_w(v3);
-  return result.raw();
+  return result.ptr();
 }
 
 Float32x4Ptr Float32x4::New(simd128_value_t value, Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->float32x4_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->float32x4_class() !=
          Class::null());
   Float32x4& result = Float32x4::Handle();
   {
@@ -23366,49 +23841,49 @@
     result ^= raw;
   }
   result.set_value(value);
-  return result.raw();
+  return result.ptr();
 }
 
 simd128_value_t Float32x4::value() const {
   return LoadUnaligned(
-      reinterpret_cast<const simd128_value_t*>(&raw_ptr()->value_));
+      reinterpret_cast<const simd128_value_t*>(&untag()->value_));
 }
 
 void Float32x4::set_value(simd128_value_t value) const {
-  StoreUnaligned(reinterpret_cast<simd128_value_t*>(&raw()->ptr()->value_),
+  StoreUnaligned(reinterpret_cast<simd128_value_t*>(&ptr()->untag()->value_),
                  value);
 }
 
 void Float32x4::set_x(float value) const {
-  StoreNonPointer(&raw_ptr()->value_[0], value);
+  StoreNonPointer(&untag()->value_[0], value);
 }
 
 void Float32x4::set_y(float value) const {
-  StoreNonPointer(&raw_ptr()->value_[1], value);
+  StoreNonPointer(&untag()->value_[1], value);
 }
 
 void Float32x4::set_z(float value) const {
-  StoreNonPointer(&raw_ptr()->value_[2], value);
+  StoreNonPointer(&untag()->value_[2], value);
 }
 
 void Float32x4::set_w(float value) const {
-  StoreNonPointer(&raw_ptr()->value_[3], value);
+  StoreNonPointer(&untag()->value_[3], value);
 }
 
 float Float32x4::x() const {
-  return raw_ptr()->value_[0];
+  return untag()->value_[0];
 }
 
 float Float32x4::y() const {
-  return raw_ptr()->value_[1];
+  return untag()->value_[1];
 }
 
 float Float32x4::z() const {
-  return raw_ptr()->value_[2];
+  return untag()->value_[2];
 }
 
 float Float32x4::w() const {
-  return raw_ptr()->value_[3];
+  return untag()->value_[3];
 }
 
 const char* Float32x4::ToCString() const {
@@ -23425,7 +23900,8 @@
                         int32_t v2,
                         int32_t v3,
                         Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->int32x4_class() != Class::null());
+  ASSERT(IsolateGroup::Current()->object_store()->int32x4_class() !=
+         Class::null());
   Int32x4& result = Int32x4::Handle();
   {
     ObjectPtr raw =
@@ -23437,11 +23913,12 @@
   result.set_y(v1);
   result.set_z(v2);
   result.set_w(v3);
-  return result.raw();
+  return result.ptr();
 }
 
 Int32x4Ptr Int32x4::New(simd128_value_t value, Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->int32x4_class() != Class::null());
+  ASSERT(IsolateGroup::Current()->object_store()->int32x4_class() !=
+         Class::null());
   Int32x4& result = Int32x4::Handle();
   {
     ObjectPtr raw =
@@ -23450,48 +23927,48 @@
     result ^= raw;
   }
   result.set_value(value);
-  return result.raw();
+  return result.ptr();
 }
 
 void Int32x4::set_x(int32_t value) const {
-  StoreNonPointer(&raw_ptr()->value_[0], value);
+  StoreNonPointer(&untag()->value_[0], value);
 }
 
 void Int32x4::set_y(int32_t value) const {
-  StoreNonPointer(&raw_ptr()->value_[1], value);
+  StoreNonPointer(&untag()->value_[1], value);
 }
 
 void Int32x4::set_z(int32_t value) const {
-  StoreNonPointer(&raw_ptr()->value_[2], value);
+  StoreNonPointer(&untag()->value_[2], value);
 }
 
 void Int32x4::set_w(int32_t value) const {
-  StoreNonPointer(&raw_ptr()->value_[3], value);
+  StoreNonPointer(&untag()->value_[3], value);
 }
 
 int32_t Int32x4::x() const {
-  return raw_ptr()->value_[0];
+  return untag()->value_[0];
 }
 
 int32_t Int32x4::y() const {
-  return raw_ptr()->value_[1];
+  return untag()->value_[1];
 }
 
 int32_t Int32x4::z() const {
-  return raw_ptr()->value_[2];
+  return untag()->value_[2];
 }
 
 int32_t Int32x4::w() const {
-  return raw_ptr()->value_[3];
+  return untag()->value_[3];
 }
 
 simd128_value_t Int32x4::value() const {
   return LoadUnaligned(
-      reinterpret_cast<const simd128_value_t*>(&raw_ptr()->value_));
+      reinterpret_cast<const simd128_value_t*>(&untag()->value_));
 }
 
 void Int32x4::set_value(simd128_value_t value) const {
-  StoreUnaligned(reinterpret_cast<simd128_value_t*>(&raw()->ptr()->value_),
+  StoreUnaligned(reinterpret_cast<simd128_value_t*>(&ptr()->untag()->value_),
                  value);
 }
 
@@ -23505,7 +23982,7 @@
 }
 
 Float64x2Ptr Float64x2::New(double value0, double value1, Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->float64x2_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->float64x2_class() !=
          Class::null());
   Float64x2& result = Float64x2::Handle();
   {
@@ -23516,11 +23993,11 @@
   }
   result.set_x(value0);
   result.set_y(value1);
-  return result.raw();
+  return result.ptr();
 }
 
 Float64x2Ptr Float64x2::New(simd128_value_t value, Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->float64x2_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->float64x2_class() !=
          Class::null());
   Float64x2& result = Float64x2::Handle();
   {
@@ -23530,31 +24007,31 @@
     result ^= raw;
   }
   result.set_value(value);
-  return result.raw();
+  return result.ptr();
 }
 
 double Float64x2::x() const {
-  return raw_ptr()->value_[0];
+  return untag()->value_[0];
 }
 
 double Float64x2::y() const {
-  return raw_ptr()->value_[1];
+  return untag()->value_[1];
 }
 
 void Float64x2::set_x(double x) const {
-  StoreNonPointer(&raw_ptr()->value_[0], x);
+  StoreNonPointer(&untag()->value_[0], x);
 }
 
 void Float64x2::set_y(double y) const {
-  StoreNonPointer(&raw_ptr()->value_[1], y);
+  StoreNonPointer(&untag()->value_[1], y);
 }
 
 simd128_value_t Float64x2::value() const {
-  return simd128_value_t().readFrom(&raw_ptr()->value_[0]);
+  return simd128_value_t().readFrom(&untag()->value_[0]);
 }
 
 void Float64x2::set_value(simd128_value_t value) const {
-  StoreSimd128(&raw_ptr()->value_[0], value);
+  StoreSimd128(&untag()->value_[0], value);
 }
 
 const char* Float64x2::ToCString() const {
@@ -23582,7 +24059,7 @@
 };
 
 bool TypedData::CanonicalizeEquals(const Instance& other) const {
-  if (this->raw() == other.raw()) {
+  if (this->ptr() == other.ptr()) {
     // Both handles point to the same raw instance.
     return true;
   }
@@ -23634,7 +24111,7 @@
     result.SetLength(len);
     result.RecomputeDataField();
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* TypedData::ToCString() const {
@@ -23680,7 +24157,7 @@
     result.SetLength(len);
     result.SetData(data);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 ExternalTypedDataPtr ExternalTypedData::NewFinalizeWithFree(uint8_t* data,
@@ -23689,7 +24166,7 @@
       kExternalTypedDataUint8ArrayCid, data, len, Heap::kOld));
   result.AddFinalizer(
       data, [](void* isolate_callback_data, void* data) { free(data); }, len);
-  return result.raw();
+  return result.ptr();
 }
 
 TypedDataViewPtr TypedDataView::New(intptr_t class_id, Heap::Space space) {
@@ -23701,7 +24178,7 @@
     result ^= raw;
     result.Clear();
   }
-  return result.raw();
+  return result.ptr();
 }
 
 TypedDataViewPtr TypedDataView::New(intptr_t class_id,
@@ -23711,7 +24188,7 @@
                                     Heap::Space space) {
   auto& result = TypedDataView::Handle(TypedDataView::New(class_id, space));
   result.InitializeWith(typed_data, offset_in_bytes, length);
-  return result.raw();
+  return result.ptr();
 }
 
 const char* TypedDataBase::ToCString() const {
@@ -23741,7 +24218,7 @@
   type_args = type_args.Canonicalize(thread, nullptr);
 
   const Class& cls =
-      Class::Handle(Isolate::Current()->class_table()->At(kFfiPointerCid));
+      Class::Handle(IsolateGroup::Current()->class_table()->At(kFfiPointerCid));
   cls.EnsureIsAllocateFinalized(Thread::Current());
 
   Pointer& result = Pointer::Handle(zone);
@@ -23749,7 +24226,7 @@
   result.SetTypeArguments(type_args);
   result.SetNativeAddress(native_address);
 
-  return result.raw();
+  return result.ptr();
 }
 
 const char* Pointer::ToCString() const {
@@ -23765,11 +24242,11 @@
                              DynamicLibrary::InstanceSize(), space);
   NoSafepointScope no_safepoint;
   result.SetHandle(handle);
-  return result.raw();
+  return result.ptr();
 }
 
 bool Pointer::IsPointer(const Instance& obj) {
-  return IsFfiPointerClassId(obj.raw()->GetClassId());
+  return IsFfiPointerClassId(obj.ptr()->GetClassId());
 }
 
 bool Instance::IsPointer() const {
@@ -23788,9 +24265,9 @@
                                      Capability::InstanceSize(), space);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.StoreNonPointer(&result.raw_ptr()->id_, id);
+    result.StoreNonPointer(&result.untag()->id_, id);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* Capability::ToCString() const {
@@ -23817,10 +24294,10 @@
                                      ReceivePort::InstanceSize(), space);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.raw_ptr()->set_send_port(send_port.raw());
+    result.untag()->set_send_port(send_port.ptr());
 #if !defined(PRODUCT)
-    result.raw_ptr()->set_debug_name(debug_name.raw());
-    result.raw_ptr()->set_allocation_location(allocation_location_.raw());
+    result.untag()->set_debug_name(debug_name.ptr());
+    result.untag()->set_allocation_location(allocation_location_.ptr());
 #endif  // !defined(PRODUCT)
   }
   if (is_control_port) {
@@ -23828,7 +24305,7 @@
   } else {
     PortMap::SetPortState(id, PortMap::kLivePort);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* ReceivePort::ToCString() const {
@@ -23849,10 +24326,10 @@
         Object::Allocate(SendPort::kClassId, SendPort::InstanceSize(), space);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.StoreNonPointer(&result.raw_ptr()->id_, id);
-    result.StoreNonPointer(&result.raw_ptr()->origin_id_, origin_id);
+    result.StoreNonPointer(&result.untag()->id_, id);
+    result.StoreNonPointer(&result.untag()->origin_id_, origin_id);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* SendPort::ToCString() const {
@@ -23881,11 +24358,12 @@
   }
   // Set up finalizer so it frees allocated memory if handle is
   // garbage-collected.
-  peer->set_handle(FinalizablePersistentHandle::New(
-      thread->isolate(), result, peer, &TransferableTypedDataFinalizer, length,
-      /*auto_delete=*/true));
+  peer->set_handle(
+      FinalizablePersistentHandle::New(thread->isolate_group(), result, peer,
+                                       &TransferableTypedDataFinalizer, length,
+                                       /*auto_delete=*/true));
 
-  return result.raw();
+  return result.ptr();
 }
 
 const char* TransferableTypedData::ToCString() const {
@@ -23928,11 +24406,11 @@
 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().raw()) {
+  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(thread);
+    return closure_function.NumTypeParameters();
   }
 }
 
@@ -23942,9 +24420,9 @@
   ZoneTextBuffer buffer(zone);
   buffer.AddString("Closure: ");
   const Function& fun = Function::Handle(zone, function());
-  const Function& sig_fun =
-      Function::Handle(zone, GetInstantiatedSignature(zone));
-  sig_fun.PrintSignature(NameVisibility::kUserVisibleName, &buffer);
+  const FunctionType& sig =
+      FunctionType::Handle(zone, GetInstantiatedSignature(zone));
+  sig.Print(kUserVisibleName, &buffer);
   if (fun.IsImplicitClosureFunction()) {
     buffer.Printf(" from %s", fun.ToCString());
   }
@@ -24008,15 +24486,14 @@
         Object::Allocate(Closure::kClassId, Closure::InstanceSize(), space);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.raw_ptr()->set_instantiator_type_arguments(
-        instantiator_type_arguments.raw());
-    result.raw_ptr()->set_function_type_arguments(
-        function_type_arguments.raw());
-    result.raw_ptr()->set_delayed_type_arguments(delayed_type_arguments.raw());
-    result.raw_ptr()->set_function(function.raw());
-    result.raw_ptr()->set_context(context.raw());
+    result.untag()->set_instantiator_type_arguments(
+        instantiator_type_arguments.ptr());
+    result.untag()->set_function_type_arguments(function_type_arguments.ptr());
+    result.untag()->set_delayed_type_arguments(delayed_type_arguments.ptr());
+    result.untag()->set_function(function.ptr());
+    result.untag()->set_context(context.ptr());
   }
-  return result.raw();
+  return result.ptr();
 }
 
 ClosurePtr Closure::New() {
@@ -24025,8 +24502,9 @@
   return static_cast<ClosurePtr>(raw);
 }
 
-FunctionPtr Closure::GetInstantiatedSignature(Zone* zone) const {
-  Function& sig_fun = Function::Handle(zone, function());
+FunctionTypePtr Closure::GetInstantiatedSignature(Zone* zone) const {
+  Function& fun = Function::Handle(zone, function());
+  FunctionType& sig = FunctionType::Handle(zone, fun.signature());
   TypeArguments& fn_type_args =
       TypeArguments::Handle(zone, function_type_arguments());
   const TypeArguments& delayed_type_args =
@@ -24037,75 +24515,75 @@
   // 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.raw() != Object::empty_type_arguments().raw()) {
+  if (delayed_type_args.ptr() != Object::empty_type_arguments().ptr()) {
     num_free_params = kCurrentAndEnclosingFree;
     fn_type_args = delayed_type_args.Prepend(
-        zone, fn_type_args, sig_fun.NumParentTypeParameters(),
-        sig_fun.NumTypeParameters() + sig_fun.NumParentTypeParameters());
+        zone, fn_type_args, sig.NumParentTypeArguments(),
+        sig.NumTypeParameters() + sig.NumParentTypeArguments());
   } else {
     num_free_params = kAllFree;
   }
   if (num_free_params == kCurrentAndEnclosingFree ||
-      !sig_fun.HasInstantiatedSignature(kAny)) {
-    return sig_fun.InstantiateSignatureFrom(inst_type_args, fn_type_args,
-                                            num_free_params, Heap::kOld);
+      !sig.IsInstantiated(kAny)) {
+    sig ^= sig.InstantiateFrom(inst_type_args, fn_type_args, num_free_params,
+                               Heap::kOld);
   }
-  return sig_fun.raw();
+  return sig.ptr();
 }
 
 bool StackTrace::skip_sync_start_in_parent_stack() const {
-  return raw_ptr()->skip_sync_start_in_parent_stack;
+  return untag()->skip_sync_start_in_parent_stack;
 }
 
 void StackTrace::set_skip_sync_start_in_parent_stack(bool value) const {
-  StoreNonPointer(&raw_ptr()->skip_sync_start_in_parent_stack, value);
+  StoreNonPointer(&untag()->skip_sync_start_in_parent_stack, value);
 }
 
 intptr_t StackTrace::Length() const {
-  const Array& code_array = Array::Handle(raw_ptr()->code_array());
+  const Array& code_array = Array::Handle(untag()->code_array());
   return code_array.Length();
 }
 
 ObjectPtr StackTrace::CodeAtFrame(intptr_t frame_index) const {
-  const Array& code_array = Array::Handle(raw_ptr()->code_array());
+  const Array& code_array = Array::Handle(untag()->code_array());
   return code_array.At(frame_index);
 }
 
 void StackTrace::SetCodeAtFrame(intptr_t frame_index,
                                 const Object& code) const {
-  const Array& code_array = Array::Handle(raw_ptr()->code_array());
+  const Array& code_array = Array::Handle(untag()->code_array());
   code_array.SetAt(frame_index, code);
 }
 
 SmiPtr StackTrace::PcOffsetAtFrame(intptr_t frame_index) const {
-  const Array& pc_offset_array = Array::Handle(raw_ptr()->pc_offset_array());
+  const Array& pc_offset_array = Array::Handle(untag()->pc_offset_array());
   return static_cast<SmiPtr>(pc_offset_array.At(frame_index));
 }
 
 void StackTrace::SetPcOffsetAtFrame(intptr_t frame_index,
                                     const Smi& pc_offset) const {
-  const Array& pc_offset_array = Array::Handle(raw_ptr()->pc_offset_array());
+  const Array& pc_offset_array = Array::Handle(untag()->pc_offset_array());
   pc_offset_array.SetAt(frame_index, pc_offset);
 }
 
 void StackTrace::set_async_link(const StackTrace& async_link) const {
-  raw_ptr()->set_async_link(async_link.raw());
+  untag()->set_async_link(async_link.ptr());
 }
 
 void StackTrace::set_code_array(const Array& code_array) const {
-  raw_ptr()->set_code_array(code_array.raw());
+  untag()->set_code_array(code_array.ptr());
 }
 
 void StackTrace::set_pc_offset_array(const Array& pc_offset_array) const {
-  raw_ptr()->set_pc_offset_array(pc_offset_array.raw());
+  untag()->set_pc_offset_array(pc_offset_array.ptr());
 }
 
 void StackTrace::set_expand_inlined(bool value) const {
-  StoreNonPointer(&raw_ptr()->expand_inlined_, value);
+  StoreNonPointer(&untag()->expand_inlined_, value);
 }
 
 bool StackTrace::expand_inlined() const {
-  return raw_ptr()->expand_inlined_;
+  return untag()->expand_inlined_;
 }
 
 StackTracePtr StackTrace::New(const Array& code_array,
@@ -24122,7 +24600,7 @@
   result.set_pc_offset_array(pc_offset_array);
   result.set_expand_inlined(true);  // default.
   result.set_skip_sync_start_in_parent_stack(false);
-  return result.raw();
+  return result.ptr();
 }
 
 StackTracePtr StackTrace::New(const Array& code_array,
@@ -24142,7 +24620,7 @@
   result.set_pc_offset_array(pc_offset_array);
   result.set_expand_inlined(true);  // default.
   result.set_skip_sync_start_in_parent_stack(skip_sync_start_in_parent_stack);
-  return result.raw();
+  return result.ptr();
 }
 
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -24207,8 +24685,9 @@
 static void PrintSymbolicStackFrame(Zone* zone,
                                     BaseTextBuffer* buffer,
                                     const Function& function,
-                                    TokenPosition token_pos,
-                                    intptr_t frame_index) {
+                                    TokenPosition token_pos_or_line,
+                                    intptr_t frame_index,
+                                    bool is_line = false) {
   ASSERT(!function.IsNull());
   const auto& script = Script::Handle(zone, function.script());
   const char* function_name = function.QualifiedUserVisibleNameCString();
@@ -24224,13 +24703,15 @@
 
   intptr_t line = -1;
   intptr_t column = -1;
-  if (FLAG_precompiled_mode) {
-    line = token_pos.value();
-  } else if (token_pos.IsSourcePosition()) {
+  if (is_line) {
+    ASSERT(token_pos_or_line.IsNoSource() || token_pos_or_line.IsReal());
+    if (token_pos_or_line.IsReal()) {
+      line = token_pos_or_line.Pos();
+    }
+  } else {
     ASSERT(!script.IsNull());
-    script.GetTokenLocation(token_pos.SourcePosition(), &line, &column);
+    script.GetTokenLocation(token_pos_or_line, &line, &column);
   }
-
   PrintSymbolicStackFrameIndex(buffer, frame_index);
   PrintSymbolicStackFrameBody(buffer, function_name, url, line, column);
 }
@@ -24238,7 +24719,7 @@
 const char* StackTrace::ToCString() const {
   auto const T = Thread::Current();
   auto const zone = T->zone();
-  auto& stack_trace = StackTrace::Handle(zone, this->raw());
+  auto& stack_trace = StackTrace::Handle(zone, this->ptr());
   auto& function = Function::Handle(zone);
   auto& code_object = Object::Handle(zone);
   auto& code = Code::Handle(zone);
@@ -24252,7 +24733,7 @@
   auto const isolate_instructions = reinterpret_cast<uword>(
       T->isolate_group()->source()->snapshot_instructions);
   auto const vm_instructions = reinterpret_cast<uword>(
-      Dart::vm_isolate()->group()->source()->snapshot_instructions);
+      Dart::vm_isolate_group()->source()->snapshot_instructions);
   if (FLAG_dwarf_stack_traces_mode) {
     const Image isolate_instructions_image(
         reinterpret_cast<const void*>(isolate_instructions));
@@ -24316,7 +24797,7 @@
         continue;
       }
 
-      if (code_object.raw() == StubCode::AsynchronousGapMarker().raw()) {
+      if (code_object.ptr() == StubCode::AsynchronousGapMarker().ptr()) {
         if (!in_gap) {
           buffer.AddString("<asynchronous suspension>\n");
         }
@@ -24326,7 +24807,7 @@
 
       intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i));
       ASSERT(code_object.IsCode());
-      code ^= code_object.raw();
+      code ^= code_object.ptr();
       ASSERT(code.IsFunctionCode());
       function = code.function();
       const uword pc = code.PayloadStart() + pc_offset;
@@ -24383,7 +24864,8 @@
         for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) {
           const auto& inlined = *inlined_functions[j];
           auto const pos = inlined_token_positions[j];
-          PrintSymbolicStackFrame(zone, &buffer, inlined, pos, frame_index);
+          PrintSymbolicStackFrame(zone, &buffer, inlined, pos, frame_index,
+                                  /*is_line=*/FLAG_precompiled_mode);
           frame_index++;
         }
         continue;
@@ -24423,13 +24905,13 @@
                     "symbolize stack traces in the precompiled runtime.");
 
 void RegExp::set_pattern(const String& pattern) const {
-  raw_ptr()->set_pattern(pattern.raw());
+  untag()->set_pattern(pattern.ptr());
 }
 
 void RegExp::set_function(intptr_t cid,
                           bool sticky,
                           const Function& value) const {
-  StorePointer(FunctionAddr(cid, sticky), value.raw());
+  StorePointer(FunctionAddr(cid, sticky), value.ptr());
 }
 
 void RegExp::set_bytecode(bool is_one_byte,
@@ -24437,25 +24919,25 @@
                           const TypedData& bytecode) const {
   if (sticky) {
     if (is_one_byte) {
-      raw_ptr()->set_one_byte_sticky(bytecode.raw());
+      untag()->set_one_byte_sticky(bytecode.ptr());
     } else {
-      raw_ptr()->set_two_byte_sticky(bytecode.raw());
+      untag()->set_two_byte_sticky(bytecode.ptr());
     }
   } else {
     if (is_one_byte) {
-      raw_ptr()->set_one_byte(bytecode.raw());
+      untag()->set_one_byte(bytecode.ptr());
     } else {
-      raw_ptr()->set_two_byte(bytecode.raw());
+      untag()->set_two_byte(bytecode.ptr());
     }
   }
 }
 
 void RegExp::set_num_bracket_expressions(intptr_t value) const {
-  raw_ptr()->set_num_bracket_expressions(Smi::New(value));
+  untag()->set_num_bracket_expressions(Smi::New(value));
 }
 
 void RegExp::set_capture_name_map(const Array& array) const {
-  raw_ptr()->set_capture_name_map(array.raw());
+  untag()->set_capture_name_map(array.ptr());
 }
 
 RegExpPtr RegExp::New(Heap::Space space) {
@@ -24470,7 +24952,7 @@
     result.set_num_registers(/*is_one_byte=*/false, -1);
     result.set_num_registers(/*is_one_byte=*/true, -1);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 const char* RegExpFlags::ToCString() const {
@@ -24512,7 +24994,7 @@
 }
 
 bool RegExp::CanonicalizeEquals(const Instance& other) const {
-  if (this->raw() == other.raw()) {
+  if (this->ptr() == other.ptr()) {
     return true;  // "===".
   }
   if (other.IsNull() || !other.IsRegExp()) {
@@ -24539,7 +25021,7 @@
 }
 
 WeakPropertyPtr WeakProperty::New(Heap::Space space) {
-  ASSERT(Isolate::Current()->object_store()->weak_property_class() !=
+  ASSERT(IsolateGroup::Current()->object_store()->weak_property_class() !=
          Class::null());
   ObjectPtr raw = Object::Allocate(WeakProperty::kClassId,
                                    WeakProperty::InstanceSize(), space);
@@ -24552,32 +25034,37 @@
 
 AbstractTypePtr MirrorReference::GetAbstractTypeReferent() const {
   ASSERT(Object::Handle(referent()).IsAbstractType());
-  return AbstractType::Cast(Object::Handle(referent())).raw();
+  return AbstractType::Cast(Object::Handle(referent())).ptr();
 }
 
 ClassPtr MirrorReference::GetClassReferent() const {
   ASSERT(Object::Handle(referent()).IsClass());
-  return Class::Cast(Object::Handle(referent())).raw();
+  return Class::Cast(Object::Handle(referent())).ptr();
 }
 
 FieldPtr MirrorReference::GetFieldReferent() const {
   ASSERT(Object::Handle(referent()).IsField());
-  return Field::Cast(Object::Handle(referent())).raw();
+  return Field::Cast(Object::Handle(referent())).ptr();
 }
 
 FunctionPtr MirrorReference::GetFunctionReferent() const {
   ASSERT(Object::Handle(referent()).IsFunction());
-  return Function::Cast(Object::Handle(referent())).raw();
+  return Function::Cast(Object::Handle(referent())).ptr();
+}
+
+FunctionTypePtr MirrorReference::GetFunctionTypeReferent() const {
+  ASSERT(Object::Handle(referent()).IsFunctionType());
+  return FunctionType::Cast(Object::Handle(referent())).ptr();
 }
 
 LibraryPtr MirrorReference::GetLibraryReferent() const {
   ASSERT(Object::Handle(referent()).IsLibrary());
-  return Library::Cast(Object::Handle(referent())).raw();
+  return Library::Cast(Object::Handle(referent())).ptr();
 }
 
 TypeParameterPtr MirrorReference::GetTypeParameterReferent() const {
   ASSERT(Object::Handle(referent()).IsTypeParameter());
-  return TypeParameter::Cast(Object::Handle(referent())).raw();
+  return TypeParameter::Cast(Object::Handle(referent())).ptr();
 }
 
 MirrorReferencePtr MirrorReference::New(const Object& referent,
@@ -24590,7 +25077,7 @@
     result ^= raw;
   }
   result.set_referent(referent);
-  return result.raw();
+  return result.ptr();
 }
 
 const char* MirrorReference::ToCString() const {
@@ -24611,7 +25098,7 @@
   UserTag& result = UserTag::Handle(FindTagInIsolate(thread, label));
   if (!result.IsNull()) {
     // Tag already exists, return existing instance.
-    return result.raw();
+    return result.ptr();
   }
   if (TagTableIsFull(thread)) {
     const String& error = String::Handle(String::NewFormatted(
@@ -24629,7 +25116,7 @@
   }
   result.set_label(label);
   AddTagToIsolate(thread, result);
-  return result.raw();
+  return result.ptr();
 }
 
 UserTagPtr UserTag::DefaultTag() {
@@ -24646,7 +25133,7 @@
       UserTag::Handle(zone, UserTag::New(Symbols::Default()));
   ASSERT(result.tag() == UserTags::kDefaultUserTag);
   isolate->set_default_tag(result);
-  return result.raw();
+  return result.ptr();
 }
 
 UserTagPtr UserTag::FindTagInIsolate(Thread* thread, const String& label) {
@@ -24663,7 +25150,7 @@
     tag_label = other.label();
     ASSERT(!tag_label.IsNull());
     if (tag_label.Equals(label)) {
-      return other.raw();
+      return other.ptr();
     }
   }
   return UserTag::null();
@@ -24714,7 +25201,7 @@
   for (intptr_t i = 0; i < tag_table.Length(); i++) {
     tag ^= tag_table.At(i);
     if (tag.tag() == tag_id) {
-      return tag.raw();
+      return tag.ptr();
     }
   }
   return UserTag::null();
@@ -24727,7 +25214,15 @@
 
 void DumpTypeTable(Isolate* isolate) {
   OS::PrintErr("canonical types:\n");
-  CanonicalTypeSet table(isolate->object_store()->canonical_types());
+  CanonicalTypeSet table(isolate->group()->object_store()->canonical_types());
+  table.Dump();
+  table.Release();
+}
+
+void DumpFunctionTypeTable(Isolate* isolate) {
+  OS::PrintErr("canonical function types:\n");
+  CanonicalFunctionTypeSet table(
+      isolate->group()->object_store()->canonical_function_types());
   table.Dump();
   table.Release();
 }
@@ -24735,7 +25230,7 @@
 void DumpTypeParameterTable(Isolate* isolate) {
   OS::PrintErr("canonical type parameters (cloned from declarations):\n");
   CanonicalTypeParameterSet table(
-      isolate->object_store()->canonical_type_parameters());
+      isolate->group()->object_store()->canonical_type_parameters());
   table.Dump();
   table.Release();
 }
@@ -24743,38 +25238,38 @@
 void DumpTypeArgumentsTable(Isolate* isolate) {
   OS::PrintErr("canonical type arguments:\n");
   CanonicalTypeArgumentsSet table(
-      isolate->object_store()->canonical_type_arguments());
+      isolate->group()->object_store()->canonical_type_arguments());
   table.Dump();
   table.Release();
 }
 
-EntryPointPragma FindEntryPointPragma(Isolate* I,
+EntryPointPragma FindEntryPointPragma(IsolateGroup* IG,
                                       const Array& metadata,
                                       Field* reusable_field_handle,
                                       Object* pragma) {
   for (intptr_t i = 0; i < metadata.Length(); i++) {
     *pragma = metadata.At(i);
-    if (pragma->clazz() != I->object_store()->pragma_class()) {
+    if (pragma->clazz() != IG->object_store()->pragma_class()) {
       continue;
     }
-    *reusable_field_handle = I->object_store()->pragma_name();
+    *reusable_field_handle = IG->object_store()->pragma_name();
     if (Instance::Cast(*pragma).GetField(*reusable_field_handle) !=
-        Symbols::vm_entry_point().raw()) {
+        Symbols::vm_entry_point().ptr()) {
       continue;
     }
-    *reusable_field_handle = I->object_store()->pragma_options();
+    *reusable_field_handle = IG->object_store()->pragma_options();
     *pragma = Instance::Cast(*pragma).GetField(*reusable_field_handle);
-    if (pragma->raw() == Bool::null() || pragma->raw() == Bool::True().raw()) {
+    if (pragma->ptr() == Bool::null() || pragma->ptr() == Bool::True().ptr()) {
       return EntryPointPragma::kAlways;
       break;
     }
-    if (pragma->raw() == Symbols::Get().raw()) {
+    if (pragma->ptr() == Symbols::Get().ptr()) {
       return EntryPointPragma::kGetterOnly;
     }
-    if (pragma->raw() == Symbols::Set().raw()) {
+    if (pragma->ptr() == Symbols::Set().ptr()) {
       return EntryPointPragma::kSetterOnly;
     }
-    if (pragma->raw() == Symbols::Call().raw()) {
+    if (pragma->ptr() == Symbols::Call().ptr()) {
       return EntryPointPragma::kCallOnly;
     }
   }
@@ -24801,14 +25296,14 @@
     is_marked_entrypoint = false;
   }
 #else
-  Object& metadata = Object::Handle(Object::empty_array().raw());
+  Object& metadata = Object::Handle(Object::empty_array().ptr());
   if (!annotated.IsNull()) {
     metadata = lib.GetMetadata(annotated);
   }
-  if (metadata.IsError()) return Error::RawCast(metadata.raw());
+  if (metadata.IsError()) return Error::RawCast(metadata.ptr());
   ASSERT(!metadata.IsNull() && metadata.IsArray());
   EntryPointPragma pragma =
-      FindEntryPointPragma(Isolate::Current(), Array::Cast(metadata),
+      FindEntryPointPragma(IsolateGroup::Current(), Array::Cast(metadata),
                            &Field::Handle(), &Object::Handle());
   bool is_marked_entrypoint = pragma == EntryPointPragma::kAlways;
   if (!is_marked_entrypoint) {
@@ -24821,22 +25316,7 @@
   }
 #endif
   if (!is_marked_entrypoint) {
-    const char* member_cstring =
-        member.IsFunction()
-            ? OS::SCreate(
-                  Thread::Current()->zone(), "%s (kind %s)",
-                  Function::Cast(member).ToLibNamePrefixedQualifiedCString(),
-                  Function::KindToCString(Function::Cast(member).kind()))
-            : member.ToCString();
-    char const* error = OS::SCreate(
-        Thread::Current()->zone(),
-        "ERROR: It is illegal to access '%s' through Dart C API.\n"
-        "ERROR: See "
-        "https://github.com/dart-lang/sdk/blob/master/runtime/docs/compiler/"
-        "aot/entry_point_pragma.md\n",
-        member_cstring);
-    OS::PrintErr("%s", error);
-    return ApiError::New(String::Handle(String::New(error)));
+    return EntryPointMemberInvocationError(member);
   }
   return Error::null();
 }
@@ -24857,31 +25337,64 @@
   return ApiError::New(String::Handle(String::New(error)));
 }
 
+DART_WARN_UNUSED_RESULT
+ErrorPtr EntryPointMemberInvocationError(const Object& member) {
+  const char* member_cstring =
+      member.IsFunction()
+          ? OS::SCreate(
+                Thread::Current()->zone(), "%s (kind %s)",
+                Function::Cast(member).ToLibNamePrefixedQualifiedCString(),
+                Function::KindToCString(Function::Cast(member).kind()))
+          : member.ToCString();
+  if (!FLAG_verify_entry_points) {
+    // Print a warning, but do not return an error.
+    char const* warning = OS::SCreate(
+        Thread::Current()->zone(),
+        "WARNING: '%s' is accessed through Dart C API without being marked as "
+        "an entry point; its tree-shaken signature cannot be verified.\n"
+        "WARNING: See "
+        "https://github.com/dart-lang/sdk/blob/master/runtime/docs/compiler/"
+        "aot/entry_point_pragma.md\n",
+        member_cstring);
+    OS::PrintErr("%s", warning);
+    return Error::null();
+  }
+  char const* error = OS::SCreate(
+      Thread::Current()->zone(),
+      "ERROR: It is illegal to access '%s' through Dart C API.\n"
+      "ERROR: See "
+      "https://github.com/dart-lang/sdk/blob/master/runtime/docs/compiler/"
+      "aot/entry_point_pragma.md\n",
+      member_cstring);
+  OS::PrintErr("%s", error);
+  return ApiError::New(String::Handle(String::New(error)));
+}
+
 ErrorPtr Function::VerifyCallEntryPoint() const {
   if (!FLAG_verify_entry_points) return Error::null();
 
   const Class& cls = Class::Handle(Owner());
   const Library& lib = Library::Handle(cls.library());
   switch (kind()) {
-    case FunctionLayout::kRegularFunction:
-    case FunctionLayout::kSetterFunction:
-    case FunctionLayout::kConstructor:
+    case UntaggedFunction::kRegularFunction:
+    case UntaggedFunction::kSetterFunction:
+    case UntaggedFunction::kConstructor:
       return dart::VerifyEntryPoint(lib, *this, *this,
                                     {EntryPointPragma::kCallOnly});
       break;
-    case FunctionLayout::kGetterFunction:
+    case UntaggedFunction::kGetterFunction:
       return dart::VerifyEntryPoint(
           lib, *this, *this,
           {EntryPointPragma::kCallOnly, EntryPointPragma::kGetterOnly});
       break;
-    case FunctionLayout::kImplicitGetter:
+    case UntaggedFunction::kImplicitGetter:
       return dart::VerifyEntryPoint(lib, *this, Field::Handle(accessor_field()),
                                     {EntryPointPragma::kGetterOnly});
       break;
-    case FunctionLayout::kImplicitSetter:
+    case UntaggedFunction::kImplicitSetter:
       return dart::VerifyEntryPoint(lib, *this, Field::Handle(accessor_field()),
                                     {EntryPointPragma::kSetterOnly});
-    case FunctionLayout::kMethodExtractor:
+    case UntaggedFunction::kMethodExtractor:
       return Function::Handle(extracted_method_closure())
           .VerifyClosurizedEntryPoint();
       break;
@@ -24897,10 +25410,10 @@
   const Class& cls = Class::Handle(Owner());
   const Library& lib = Library::Handle(cls.library());
   switch (kind()) {
-    case FunctionLayout::kRegularFunction:
+    case UntaggedFunction::kRegularFunction:
       return dart::VerifyEntryPoint(lib, *this, *this,
                                     {EntryPointPragma::kGetterOnly});
-    case FunctionLayout::kImplicitClosureFunction: {
+    case UntaggedFunction::kImplicitClosureFunction: {
       const Function& parent = Function::Handle(parent_function());
       return dart::VerifyEntryPoint(lib, parent, parent,
                                     {EntryPointPragma::kGetterOnly});
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 467e1b1..3c228c3 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -82,9 +82,9 @@
 
 #define BASE_OBJECT_IMPLEMENTATION(object, super)                              \
  public: /* NOLINT */                                                          \
-  using ObjectLayoutType = dart::object##Layout;                               \
+  using UntaggedObjectType = dart::Untagged##object;                           \
   using ObjectPtrType = dart::object##Ptr;                                     \
-  object##Ptr raw() const { return static_cast<object##Ptr>(raw_); }           \
+  object##Ptr ptr() const { return static_cast<object##Ptr>(ptr_); }           \
   bool Is##object() const { return true; }                                     \
   DART_NOINLINE static object& Handle() {                                      \
     return HandleImpl(Thread::Current()->zone(), object::null());              \
@@ -92,11 +92,11 @@
   DART_NOINLINE static object& Handle(Zone* zone) {                            \
     return HandleImpl(zone, object::null());                                   \
   }                                                                            \
-  DART_NOINLINE static object& Handle(object##Ptr raw_ptr) {                   \
-    return HandleImpl(Thread::Current()->zone(), raw_ptr);                     \
+  DART_NOINLINE static object& Handle(object##Ptr ptr) {                       \
+    return HandleImpl(Thread::Current()->zone(), ptr);                         \
   }                                                                            \
-  DART_NOINLINE static object& Handle(Zone* zone, object##Ptr raw_ptr) {       \
-    return HandleImpl(zone, raw_ptr);                                          \
+  DART_NOINLINE static object& Handle(Zone* zone, object##Ptr ptr) {           \
+    return HandleImpl(zone, ptr);                                              \
   }                                                                            \
   DART_NOINLINE static object& ZoneHandle() {                                  \
     return ZoneHandleImpl(Thread::Current()->zone(), object::null());          \
@@ -104,39 +104,38 @@
   DART_NOINLINE static object& ZoneHandle(Zone* zone) {                        \
     return ZoneHandleImpl(zone, object::null());                               \
   }                                                                            \
-  DART_NOINLINE static object& ZoneHandle(object##Ptr raw_ptr) {               \
-    return ZoneHandleImpl(Thread::Current()->zone(), raw_ptr);                 \
+  DART_NOINLINE static object& ZoneHandle(object##Ptr ptr) {                   \
+    return ZoneHandleImpl(Thread::Current()->zone(), ptr);                     \
   }                                                                            \
-  DART_NOINLINE static object& ZoneHandle(Zone* zone, object##Ptr raw_ptr) {   \
-    return ZoneHandleImpl(zone, raw_ptr);                                      \
+  DART_NOINLINE static object& ZoneHandle(Zone* zone, object##Ptr ptr) {       \
+    return ZoneHandleImpl(zone, ptr);                                          \
   }                                                                            \
   DART_NOINLINE static object* ReadOnlyHandle() {                              \
     object* obj = reinterpret_cast<object*>(Dart::AllocateReadOnlyHandle());   \
     initializeHandle(obj, object::null());                                     \
     return obj;                                                                \
   }                                                                            \
-  DART_NOINLINE static object& CheckedHandle(Zone* zone, ObjectPtr raw_ptr) {  \
+  DART_NOINLINE static object& CheckedHandle(Zone* zone, ObjectPtr ptr) {      \
     object* obj = reinterpret_cast<object*>(VMHandles::AllocateHandle(zone));  \
-    initializeHandle(obj, raw_ptr);                                            \
+    initializeHandle(obj, ptr);                                                \
     if (!obj->Is##object()) {                                                  \
       FATAL2("Handle check failed: saw %s expected %s", obj->ToCString(),      \
              #object);                                                         \
     }                                                                          \
     return *obj;                                                               \
   }                                                                            \
-  DART_NOINLINE static object& CheckedZoneHandle(Zone* zone,                   \
-                                                 ObjectPtr raw_ptr) {          \
+  DART_NOINLINE static object& CheckedZoneHandle(Zone* zone, ObjectPtr ptr) {  \
     object* obj =                                                              \
         reinterpret_cast<object*>(VMHandles::AllocateZoneHandle(zone));        \
-    initializeHandle(obj, raw_ptr);                                            \
+    initializeHandle(obj, ptr);                                                \
     if (!obj->Is##object()) {                                                  \
       FATAL2("Handle check failed: saw %s expected %s", obj->ToCString(),      \
              #object);                                                         \
     }                                                                          \
     return *obj;                                                               \
   }                                                                            \
-  DART_NOINLINE static object& CheckedZoneHandle(ObjectPtr raw_ptr) {          \
-    return CheckedZoneHandle(Thread::Current()->zone(), raw_ptr);              \
+  DART_NOINLINE static object& CheckedZoneHandle(ObjectPtr ptr) {              \
+    return CheckedZoneHandle(Thread::Current()->zone(), ptr);                  \
   }                                                                            \
   /* T::Cast cannot be applied to a null Object, because the object vtable */  \
   /* is not setup for type T, although some methods are supposed to work   */  \
@@ -156,23 +155,23 @@
   static const ClassId kClassId = k##object##Cid;                              \
                                                                                \
  private: /* NOLINT */                                                         \
-  static object& HandleImpl(Zone* zone, object##Ptr raw_ptr) {                 \
+  static object& HandleImpl(Zone* zone, object##Ptr ptr) {                     \
     object* obj = reinterpret_cast<object*>(VMHandles::AllocateHandle(zone));  \
-    initializeHandle(obj, raw_ptr);                                            \
+    initializeHandle(obj, ptr);                                                \
     return *obj;                                                               \
   }                                                                            \
-  static object& ZoneHandleImpl(Zone* zone, object##Ptr raw_ptr) {             \
+  static object& ZoneHandleImpl(Zone* zone, object##Ptr ptr) {                 \
     object* obj =                                                              \
         reinterpret_cast<object*>(VMHandles::AllocateZoneHandle(zone));        \
-    initializeHandle(obj, raw_ptr);                                            \
+    initializeHandle(obj, ptr);                                                \
     return *obj;                                                               \
   }                                                                            \
-  /* Initialize the handle based on the raw_ptr in the presence of null. */    \
-  static void initializeHandle(object* obj, ObjectPtr raw_ptr) {               \
-    if (raw_ptr != Object::null()) {                                           \
-      obj->SetRaw(raw_ptr);                                                    \
+  /* Initialize the handle based on the ptr in the presence of null. */        \
+  static void initializeHandle(object* obj, ObjectPtr ptr) {                   \
+    if (ptr != Object::null()) {                                               \
+      obj->SetPtr(ptr);                                                        \
     } else {                                                                   \
-      obj->raw_ = Object::null();                                              \
+      obj->ptr_ = Object::null();                                              \
       object fake_object;                                                      \
       obj->set_vtable(fake_object.vtable());                                   \
     }                                                                          \
@@ -229,9 +228,9 @@
 
 #define HEAP_OBJECT_IMPLEMENTATION(object, super)                              \
   OBJECT_IMPLEMENTATION(object, super);                                        \
-  object##Layout* raw_ptr() const {                                            \
-    ASSERT(raw() != null());                                                   \
-    return const_cast<object##Layout*>(raw()->ptr());                          \
+  Untagged##object* untag() const {                                            \
+    ASSERT(ptr() != null());                                                   \
+    return const_cast<Untagged##object*>(ptr()->untag());                      \
   }                                                                            \
   SNAPSHOT_READER_SUPPORT(object)                                              \
   friend class StackFrame;                                                     \
@@ -241,11 +240,11 @@
 #define FINAL_HEAP_OBJECT_IMPLEMENTATION_HELPER(object, rettype, super)        \
  public: /* NOLINT */                                                          \
   void operator=(object##Ptr value) {                                          \
-    raw_ = value;                                                              \
+    ptr_ = value;                                                              \
     CHECK_HANDLE();                                                            \
   }                                                                            \
   void operator^=(ObjectPtr value) {                                           \
-    raw_ = value;                                                              \
+    ptr_ = value;                                                              \
     CHECK_HANDLE();                                                            \
   }                                                                            \
                                                                                \
@@ -253,9 +252,9 @@
   object() : super() {}                                                        \
   BASE_OBJECT_IMPLEMENTATION(object, super)                                    \
   OBJECT_SERVICE_SUPPORT(object)                                               \
-  object##Layout* raw_ptr() const {                                            \
-    ASSERT(raw() != null());                                                   \
-    return const_cast<object##Layout*>(raw()->ptr());                          \
+  Untagged##object* untag() const {                                            \
+    ASSERT(ptr() != null());                                                   \
+    return const_cast<Untagged##object*>(ptr()->untag());                      \
   }                                                                            \
   static intptr_t NextFieldOffset() { return -kWordSize; }                     \
   SNAPSHOT_READER_SUPPORT(rettype)                                             \
@@ -280,25 +279,25 @@
 
 class Object {
  public:
-  using ObjectLayoutType = ObjectLayout;
+  using UntaggedObjectType = UntaggedObject;
   using ObjectPtrType = ObjectPtr;
 
   static ObjectPtr RawCast(ObjectPtr obj) { return obj; }
 
   virtual ~Object() {}
 
-  ObjectPtr raw() const { return raw_; }
+  ObjectPtr ptr() const { return ptr_; }
   void operator=(ObjectPtr value) { initializeHandle(this, value); }
 
-  bool IsCanonical() const { return raw()->ptr()->IsCanonical(); }
-  void SetCanonical() const { raw()->ptr()->SetCanonical(); }
-  void ClearCanonical() const { raw()->ptr()->ClearCanonical(); }
+  bool IsCanonical() const { return ptr()->untag()->IsCanonical(); }
+  void SetCanonical() const { ptr()->untag()->SetCanonical(); }
+  void ClearCanonical() const { ptr()->untag()->ClearCanonical(); }
   intptr_t GetClassId() const {
-    return !raw()->IsHeapObject() ? static_cast<intptr_t>(kSmiCid)
-                                  : raw()->ptr()->GetClassId();
+    return !ptr()->IsHeapObject() ? static_cast<intptr_t>(kSmiCid)
+                                  : ptr()->untag()->GetClassId();
   }
   inline ClassPtr clazz() const;
-  static intptr_t tags_offset() { return OFFSET_OF(ObjectLayout, tags_); }
+  static intptr_t tags_offset() { return OFFSET_OF(UntaggedObject, tags_); }
 
 // Class testers.
 #define DEFINE_CLASS_TESTER(clazz)                                             \
@@ -306,7 +305,7 @@
   CLASS_LIST_FOR_HANDLES(DEFINE_CLASS_TESTER);
 #undef DEFINE_CLASS_TESTER
 
-  bool IsNull() const { return raw_ == null_; }
+  bool IsNull() const { return ptr_ == null_; }
 
   // Matches Object.toString on instances (except String::ToCString, bug 20583).
   virtual const char* ToCString() const {
@@ -330,12 +329,12 @@
   // namespaces need to provide an implementation.
   virtual StringPtr DictionaryName() const;
 
-  bool IsNew() const { return raw()->IsNewObject(); }
-  bool IsOld() const { return raw()->IsOldObject(); }
+  bool IsNew() const { return ptr()->IsNewObject(); }
+  bool IsOld() const { return ptr()->IsOldObject(); }
 #if defined(DEBUG)
   bool InVMIsolateHeap() const;
 #else
-  bool InVMIsolateHeap() const { return raw()->ptr()->InVMIsolateHeap(); }
+  bool InVMIsolateHeap() const { return ptr()->untag()->InVMIsolateHeap(); }
 #endif  // DEBUG
 
   // Print the object on stdout for debugging.
@@ -349,9 +348,9 @@
 
   bool IsNotTemporaryScopedHandle() const;
 
-  static Object& Handle(Zone* zone, ObjectPtr raw_ptr) {
+  static Object& Handle(Zone* zone, ObjectPtr ptr) {
     Object* obj = reinterpret_cast<Object*>(VMHandles::AllocateHandle(zone));
-    initializeHandle(obj, raw_ptr);
+    initializeHandle(obj, ptr);
     return *obj;
   }
   static Object* ReadOnlyHandle() {
@@ -364,14 +363,14 @@
 
   static Object& Handle(Zone* zone) { return Handle(zone, null_); }
 
-  static Object& Handle(ObjectPtr raw_ptr) {
-    return Handle(Thread::Current()->zone(), raw_ptr);
+  static Object& Handle(ObjectPtr ptr) {
+    return Handle(Thread::Current()->zone(), ptr);
   }
 
-  static Object& ZoneHandle(Zone* zone, ObjectPtr raw_ptr) {
+  static Object& ZoneHandle(Zone* zone, ObjectPtr ptr) {
     Object* obj =
         reinterpret_cast<Object*>(VMHandles::AllocateZoneHandle(zone));
-    initializeHandle(obj, raw_ptr);
+    initializeHandle(obj, ptr);
     return *obj;
   }
 
@@ -381,19 +380,19 @@
     return ZoneHandle(Thread::Current()->zone(), null_);
   }
 
-  static Object& ZoneHandle(ObjectPtr raw_ptr) {
-    return ZoneHandle(Thread::Current()->zone(), raw_ptr);
+  static Object& ZoneHandle(ObjectPtr ptr) {
+    return ZoneHandle(Thread::Current()->zone(), ptr);
   }
 
   static ObjectPtr null() { return null_; }
 
 #if defined(HASH_IN_OBJECT_HEADER)
   static uint32_t GetCachedHash(const ObjectPtr obj) {
-    return obj->ptr()->GetHeaderHash();
+    return obj->untag()->GetHeaderHash();
   }
 
   static void SetCachedHash(ObjectPtr obj, uint32_t hash) {
-    obj->ptr()->SetHeaderHash(hash);
+    obj->untag()->SetHeaderHash(hash);
   }
 #endif
 
@@ -409,10 +408,12 @@
   // propagation constants.
 #define SHARED_READONLY_HANDLES_LIST(V)                                        \
   V(Object, null_object)                                                       \
+  V(Class, null_class)                                                         \
   V(Array, null_array)                                                         \
   V(String, null_string)                                                       \
   V(Instance, null_instance)                                                   \
   V(Function, null_function)                                                   \
+  V(FunctionType, null_function_type)                                          \
   V(TypeArguments, null_type_arguments)                                        \
   V(CompressedStackMaps, null_compressed_stackmaps)                            \
   V(TypeArguments, empty_type_arguments)                                       \
@@ -462,7 +463,6 @@
   static ClassPtr patch_class_class() { return patch_class_class_; }
   static ClassPtr function_class() { return function_class_; }
   static ClassPtr closure_data_class() { return closure_data_class_; }
-  static ClassPtr signature_data_class() { return signature_data_class_; }
   static ClassPtr ffi_trampoline_data_class() {
     return ffi_trampoline_data_class_;
   }
@@ -511,18 +511,18 @@
   }
 
   // Initialize the VM isolate.
-  static void InitNullAndBool(Isolate* isolate);
-  static void Init(Isolate* isolate);
+  static void InitNullAndBool(IsolateGroup* isolate_group);
+  static void Init(IsolateGroup* isolate_group);
   static void InitVtables();
-  static void FinishInit(Isolate* isolate);
-  static void FinalizeVMIsolate(Isolate* isolate);
+  static void FinishInit(IsolateGroup* isolate_group);
+  static void FinalizeVMIsolate(IsolateGroup* isolate_group);
   static void FinalizeReadOnlyObject(ObjectPtr object);
 
   static void Cleanup();
 
   // Initialize a new isolate either from a Kernel IR, from source, or from a
   // snapshot.
-  static ErrorPtr Init(Isolate* isolate,
+  static ErrorPtr Init(IsolateGroup* isolate_group,
                        const uint8_t* kernel_buffer,
                        intptr_t kernel_buffer_size);
 
@@ -531,7 +531,7 @@
                                          intptr_t used_size);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ObjectLayout));
+    return RoundedAllocationSize(sizeof(UntaggedObject));
   }
 
   template <class FakeObject>
@@ -602,11 +602,11 @@
 
  protected:
   // Used for extracting the C++ vtable during bringup.
-  Object() : raw_(null_) {}
+  Object() : ptr_(null_) {}
 
-  uword raw_value() const { return static_cast<uword>(raw()); }
+  uword raw_value() const { return static_cast<uword>(ptr()); }
 
-  inline void SetRaw(ObjectPtr value);
+  inline void SetPtr(ObjectPtr value);
   void CheckHandle() const;
 
   cpp_vtable vtable() const { return bit_copy<cpp_vtable>(*this); }
@@ -618,7 +618,7 @@
     return Utils::RoundUp(size, kObjectAlignment);
   }
 
-  bool Contains(uword addr) const { return raw()->ptr()->Contains(addr); }
+  bool Contains(uword addr) const { return ptr()->untag()->Contains(addr); }
 
   // Start of field mutator guards.
   //
@@ -628,18 +628,18 @@
 
   template <typename type, std::memory_order order = std::memory_order_relaxed>
   type LoadPointer(type const* addr) const {
-    return raw()->ptr()->LoadPointer<type, order>(addr);
+    return ptr()->untag()->LoadPointer<type, order>(addr);
   }
 
   template <typename type, std::memory_order order = std::memory_order_relaxed>
   void StorePointer(type const* addr, type value) const {
-    raw()->ptr()->StorePointer<type, order>(addr, value);
+    ptr()->untag()->StorePointer<type, order>(addr, value);
   }
 
   // Use for storing into an explicitly Smi-typed field of an object
   // (i.e., both the previous and new value are Smis).
   void StoreSmi(SmiPtr const* addr, SmiPtr value) const {
-    raw()->ptr()->StoreSmi(addr, value);
+    ptr()->untag()->StoreSmi(addr, value);
   }
 
   template <typename FieldType>
@@ -664,14 +664,14 @@
   template <typename FieldType, typename ValueType>
   void StoreNonPointer(const FieldType* addr, ValueType value) const {
     // Can't use Contains, as it uses tags_, which is set through this method.
-    ASSERT(reinterpret_cast<uword>(addr) >= ObjectLayout::ToAddr(raw()));
+    ASSERT(reinterpret_cast<uword>(addr) >= UntaggedObject::ToAddr(ptr()));
     *const_cast<FieldType*>(addr) = value;
   }
 
   template <typename FieldType, typename ValueType, std::memory_order order>
   void StoreNonPointer(const FieldType* addr, ValueType value) const {
     // Can't use Contains, as it uses tags_, which is set through this method.
-    ASSERT(reinterpret_cast<uword>(addr) >= ObjectLayout::ToAddr(raw()));
+    ASSERT(reinterpret_cast<uword>(addr) >= UntaggedObject::ToAddr(ptr()));
     reinterpret_cast<std::atomic<FieldType>*>(const_cast<FieldType*>(addr))
         ->store(value, order);
   }
@@ -711,7 +711,7 @@
 
   // End of field mutator guards.
 
-  ObjectPtr raw_;  // The raw object reference.
+  ObjectPtr ptr_;  // The raw object reference.
 
  protected:
   void AddCommonObjectProperties(JSONObject* jsobj,
@@ -733,12 +733,12 @@
                                    const String& name,
                                    const Library& lib);
 
-  /* Initialize the handle based on the raw_ptr in the presence of null. */
-  static void initializeHandle(Object* obj, ObjectPtr raw_ptr) {
-    if (raw_ptr != Object::null()) {
-      obj->SetRaw(raw_ptr);
+  /* Initialize the handle based on the ptr in the presence of null. */
+  static void initializeHandle(Object* obj, ObjectPtr ptr) {
+    if (ptr != Object::null()) {
+      obj->SetPtr(ptr);
     } else {
-      obj->raw_ = Object::null();
+      obj->ptr_ = Object::null();
       Object fake_object;
       obj->set_vtable(fake_object.vtable());
     }
@@ -764,7 +764,6 @@
   static ClassPtr patch_class_class_;     // Class of the PatchClass vm object.
   static ClassPtr function_class_;        // Class of the Function vm object.
   static ClassPtr closure_data_class_;    // Class of ClosureData vm obj.
-  static ClassPtr signature_data_class_;  // Class of SignatureData vm obj.
   static ClassPtr ffi_trampoline_data_class_;  // Class of FfiTrampolineData
                                                // vm obj.
   static ClassPtr field_class_;                // Class of the Field vm object.
@@ -806,7 +805,7 @@
 #undef DECLARE_SHARED_READONLY_HANDLE
 
   friend void ClassTable::Register(const Class& cls);
-  friend void ObjectLayout::Validate(IsolateGroup* isolate_group) const;
+  friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const;
   friend class Closure;
   friend class SnapshotReader;
   friend class InstanceDeserializationCluster;
@@ -827,18 +826,18 @@
 
 class PassiveObject : public Object {
  public:
-  void operator=(ObjectPtr value) { raw_ = value; }
-  void operator^=(ObjectPtr value) { raw_ = value; }
+  void operator=(ObjectPtr value) { ptr_ = value; }
+  void operator^=(ObjectPtr value) { ptr_ = value; }
 
-  static PassiveObject& Handle(Zone* zone, ObjectPtr raw_ptr) {
+  static PassiveObject& Handle(Zone* zone, ObjectPtr ptr) {
     PassiveObject* obj =
         reinterpret_cast<PassiveObject*>(VMHandles::AllocateHandle(zone));
-    obj->raw_ = raw_ptr;
+    obj->ptr_ = ptr;
     obj->set_vtable(0);
     return *obj;
   }
-  static PassiveObject& Handle(ObjectPtr raw_ptr) {
-    return Handle(Thread::Current()->zone(), raw_ptr);
+  static PassiveObject& Handle(ObjectPtr ptr) {
+    return Handle(Thread::Current()->zone(), ptr);
   }
   static PassiveObject& Handle() {
     return Handle(Thread::Current()->zone(), Object::null());
@@ -846,15 +845,15 @@
   static PassiveObject& Handle(Zone* zone) {
     return Handle(zone, Object::null());
   }
-  static PassiveObject& ZoneHandle(Zone* zone, ObjectPtr raw_ptr) {
+  static PassiveObject& ZoneHandle(Zone* zone, ObjectPtr ptr) {
     PassiveObject* obj =
         reinterpret_cast<PassiveObject*>(VMHandles::AllocateZoneHandle(zone));
-    obj->raw_ = raw_ptr;
+    obj->ptr_ = ptr;
     obj->set_vtable(0);
     return *obj;
   }
-  static PassiveObject& ZoneHandle(ObjectPtr raw_ptr) {
-    return ZoneHandle(Thread::Current()->zone(), raw_ptr);
+  static PassiveObject& ZoneHandle(ObjectPtr ptr) {
+    return ZoneHandle(Thread::Current()->zone(), ptr);
   }
   static PassiveObject& ZoneHandle() {
     return ZoneHandle(Thread::Current()->zone(), Object::null());
@@ -878,7 +877,7 @@
 // The third string in the triplet is "print" if the triplet should be printed.
 typedef ZoneGrowableHandlePtrArray<const String> URIs;
 
-enum class Nullability : int8_t {
+enum class Nullability : uint8_t {
   kNullable = 0,
   kNonNullable = 1,
   kLegacy = 2,
@@ -920,23 +919,23 @@
 
   intptr_t host_instance_size() const {
     ASSERT(is_finalized() || is_prefinalized());
-    return (raw_ptr()->host_instance_size_in_words_ * kWordSize);
+    return (untag()->host_instance_size_in_words_ * kWordSize);
   }
   intptr_t target_instance_size() const {
     ASSERT(is_finalized() || is_prefinalized());
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return (raw_ptr()->target_instance_size_in_words_ *
+    return (untag()->target_instance_size_in_words_ *
             compiler::target::kWordSize);
 #else
     return host_instance_size();
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   }
   static intptr_t host_instance_size(ClassPtr clazz) {
-    return (clazz->ptr()->host_instance_size_in_words_ * kWordSize);
+    return (clazz->untag()->host_instance_size_in_words_ * kWordSize);
   }
   static intptr_t target_instance_size(ClassPtr clazz) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return (clazz->ptr()->target_instance_size_in_words_ *
+    return (clazz->untag()->target_instance_size_in_words_ *
             compiler::target::kWordSize);
 #else
     return host_instance_size(clazz);
@@ -952,22 +951,22 @@
   void set_instance_size_in_words(intptr_t host_value,
                                   intptr_t target_value) const {
     ASSERT(Utils::IsAligned((host_value * kWordSize), kObjectAlignment));
-    StoreNonPointer(&raw_ptr()->host_instance_size_in_words_, host_value);
+    StoreNonPointer(&untag()->host_instance_size_in_words_, host_value);
 #if !defined(DART_PRECOMPILED_RUNTIME)
     ASSERT(Utils::IsAligned((target_value * compiler::target::kWordSize),
                             compiler::target::kObjectAlignment));
-    StoreNonPointer(&raw_ptr()->target_instance_size_in_words_, target_value);
+    StoreNonPointer(&untag()->target_instance_size_in_words_, target_value);
 #else
     ASSERT(host_value == target_value);
 #endif  // #!defined(DART_PRECOMPILED_RUNTIME)
   }
 
   intptr_t host_next_field_offset() const {
-    return raw_ptr()->host_next_field_offset_in_words_ * kWordSize;
+    return untag()->host_next_field_offset_in_words_ * kWordSize;
   }
   intptr_t target_next_field_offset() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return raw_ptr()->target_next_field_offset_in_words_ *
+    return untag()->target_next_field_offset_in_words_ *
            compiler::target::kWordSize;
 #else
     return host_next_field_offset();
@@ -983,36 +982,35 @@
                                       intptr_t target_value) const {
     ASSERT((host_value == -1) ||
            (Utils::IsAligned((host_value * kWordSize), kObjectAlignment) &&
-            (host_value == raw_ptr()->host_instance_size_in_words_)) ||
+            (host_value == untag()->host_instance_size_in_words_)) ||
            (!Utils::IsAligned((host_value * kWordSize), kObjectAlignment) &&
-            ((host_value + 1) == raw_ptr()->host_instance_size_in_words_)));
-    StoreNonPointer(&raw_ptr()->host_next_field_offset_in_words_, host_value);
+            ((host_value + 1) == untag()->host_instance_size_in_words_)));
+    StoreNonPointer(&untag()->host_next_field_offset_in_words_, host_value);
 #if !defined(DART_PRECOMPILED_RUNTIME)
     ASSERT((target_value == -1) ||
            (Utils::IsAligned((target_value * compiler::target::kWordSize),
                              compiler::target::kObjectAlignment) &&
-            (target_value == raw_ptr()->target_instance_size_in_words_)) ||
+            (target_value == untag()->target_instance_size_in_words_)) ||
            (!Utils::IsAligned((target_value * compiler::target::kWordSize),
                               compiler::target::kObjectAlignment) &&
-            ((target_value + 1) == raw_ptr()->target_instance_size_in_words_)));
-    StoreNonPointer(&raw_ptr()->target_next_field_offset_in_words_,
-                    target_value);
+            ((target_value + 1) == untag()->target_instance_size_in_words_)));
+    StoreNonPointer(&untag()->target_next_field_offset_in_words_, target_value);
 #else
     ASSERT(host_value == target_value);
 #endif  // #!defined(DART_PRECOMPILED_RUNTIME)
   }
 
   static bool is_valid_id(intptr_t value) {
-    return ObjectLayout::ClassIdTag::is_valid(value);
+    return UntaggedObject::ClassIdTag::is_valid(value);
   }
-  intptr_t id() const { return raw_ptr()->id_; }
+  intptr_t id() const { return untag()->id_; }
   void set_id(intptr_t value) const {
     ASSERT(value >= 0 && value < std::numeric_limits<classid_t>::max());
-    StoreNonPointer(&raw_ptr()->id_, value);
+    StoreNonPointer(&untag()->id_, value);
   }
-  static intptr_t id_offset() { return OFFSET_OF(ClassLayout, id_); }
+  static intptr_t id_offset() { return OFFSET_OF(UntaggedClass, id_); }
   static intptr_t num_type_arguments_offset() {
-    return OFFSET_OF(ClassLayout, num_type_arguments_);
+    return OFFSET_OF(UntaggedClass, num_type_arguments_);
   }
 
   StringPtr Name() const;
@@ -1034,22 +1032,16 @@
 
   virtual StringPtr DictionaryName() const { return Name(); }
 
-  ScriptPtr script() const { return raw_ptr()->script(); }
+  ScriptPtr script() const { return untag()->script(); }
   void set_script(const Script& value) const;
 
-  TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
+  TokenPosition token_pos() const { return untag()->token_pos_; }
   void set_token_pos(TokenPosition value) const;
-  TokenPosition end_token_pos() const { return raw_ptr()->end_token_pos_; }
+  TokenPosition end_token_pos() const { return untag()->end_token_pos_; }
   void set_end_token_pos(TokenPosition value) const;
 
   int32_t SourceFingerprint() const;
 
-  // This class represents a typedef if the signature function is not null.
-  FunctionPtr signature_function() const {
-    return raw_ptr()->signature_function();
-  }
-  void set_signature_function(const Function& value) const;
-
   // Return the Type with type parameters declared by this class filled in with
   // dynamic and type parameters declared in superclasses filled in as declared
   // in superclass clauses.
@@ -1066,17 +1058,17 @@
   TypePtr DeclarationType() const;
 
   static intptr_t declaration_type_offset() {
-    return OFFSET_OF(ClassLayout, declaration_type_);
+    return OFFSET_OF(UntaggedClass, declaration_type_);
   }
 
-  LibraryPtr library() const { return raw_ptr()->library(); }
+  LibraryPtr library() const { return untag()->library(); }
   void set_library(const Library& value) const;
 
   // The type parameters (and their bounds) are specified as an array of
   // TypeParameter.
   TypeArgumentsPtr type_parameters() const {
     ASSERT(is_declaration_loaded());
-    return raw_ptr()->type_parameters();
+    return untag()->type_parameters();
   }
   void set_type_parameters(const TypeArguments& value) const;
   intptr_t NumTypeParameters(Thread* thread) const;
@@ -1103,20 +1095,20 @@
   static const intptr_t kNoTypeArguments = -1;
   intptr_t host_type_arguments_field_offset() const {
     ASSERT(is_type_finalized() || is_prefinalized());
-    if (raw_ptr()->host_type_arguments_field_offset_in_words_ ==
+    if (untag()->host_type_arguments_field_offset_in_words_ ==
         kNoTypeArguments) {
       return kNoTypeArguments;
     }
-    return raw_ptr()->host_type_arguments_field_offset_in_words_ * kWordSize;
+    return untag()->host_type_arguments_field_offset_in_words_ * kWordSize;
   }
   intptr_t target_type_arguments_field_offset() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
     ASSERT(is_type_finalized() || is_prefinalized());
-    if (raw_ptr()->target_type_arguments_field_offset_in_words_ ==
+    if (untag()->target_type_arguments_field_offset_in_words_ ==
         compiler::target::Class::kNoTypeArguments) {
       return compiler::target::Class::kNoTypeArguments;
     }
-    return raw_ptr()->target_type_arguments_field_offset_in_words_ *
+    return untag()->target_type_arguments_field_offset_in_words_ *
            compiler::target::kWordSize;
 #else
     return host_type_arguments_field_offset();
@@ -1140,22 +1132,23 @@
   }
   void set_type_arguments_field_offset_in_words(intptr_t host_value,
                                                 intptr_t target_value) const {
-    StoreNonPointer(&raw_ptr()->host_type_arguments_field_offset_in_words_,
+    StoreNonPointer(&untag()->host_type_arguments_field_offset_in_words_,
                     host_value);
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    StoreNonPointer(&raw_ptr()->target_type_arguments_field_offset_in_words_,
+    StoreNonPointer(&untag()->target_type_arguments_field_offset_in_words_,
                     target_value);
 #else
     ASSERT(host_value == target_value);
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
   }
   static intptr_t host_type_arguments_field_offset_in_words_offset() {
-    return OFFSET_OF(ClassLayout, host_type_arguments_field_offset_in_words_);
+    return OFFSET_OF(UntaggedClass, host_type_arguments_field_offset_in_words_);
   }
 
   static intptr_t target_type_arguments_field_offset_in_words_offset() {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return OFFSET_OF(ClassLayout, target_type_arguments_field_offset_in_words_);
+    return OFFSET_OF(UntaggedClass,
+                     target_type_arguments_field_offset_in_words_);
 #else
     return host_type_arguments_field_offset_in_words_offset();
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
@@ -1164,11 +1157,11 @@
   // The super type of this class, Object type if not explicitly specified.
   AbstractTypePtr super_type() const {
     ASSERT(is_declaration_loaded());
-    return raw_ptr()->super_type();
+    return untag()->super_type();
   }
   void set_super_type(const AbstractType& value) const;
   static intptr_t super_type_offset() {
-    return OFFSET_OF(ClassLayout, super_type_);
+    return OFFSET_OF(UntaggedClass, super_type_);
   }
 
   // Asserts that the class of the super type has been resolved.
@@ -1180,7 +1173,7 @@
   // Interfaces is an array of Types.
   ArrayPtr interfaces() const {
     ASSERT(is_declaration_loaded());
-    return raw_ptr()->interfaces();
+    return untag()->interfaces();
   }
   void set_interfaces(const Array& value) const;
 
@@ -1188,7 +1181,7 @@
   GrowableObjectArrayPtr direct_implementors() const {
     DEBUG_ASSERT(
         IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
-    return raw_ptr()->direct_implementors();
+    return untag()->direct_implementors();
   }
   void AddDirectImplementor(const Class& subclass, bool is_mixin) const;
   void ClearDirectImplementors() const;
@@ -1200,7 +1193,7 @@
     return direct_subclasses_unsafe();
   }
   GrowableObjectArrayPtr direct_subclasses_unsafe() const {
-    return raw_ptr()->direct_subclasses();
+    return untag()->direct_subclasses();
   }
   void AddDirectSubclass(const Class& subclass) const;
   void ClearDirectSubclasses() const;
@@ -1233,16 +1226,13 @@
   bool IsClosureClass() const { return id() == kClosureCid; }
   static bool IsClosureClass(ClassPtr cls) {
     NoSafepointScope no_safepoint;
-    return cls->ptr()->id_ == kClosureCid;
+    return cls->untag()->id_ == kClosureCid;
   }
 
-  // Check if this class represents a typedef class.
-  bool IsTypedefClass() const { return signature_function() != Object::null(); }
-
   static bool IsInFullSnapshot(ClassPtr cls) {
     NoSafepointScope no_safepoint;
-    return LibraryLayout::InFullSnapshotBit::decode(
-        cls->ptr()->library()->ptr()->flags_);
+    return UntaggedLibrary::InFullSnapshotBit::decode(
+        cls->untag()->library()->untag()->flags_);
   }
 
   // Returns true if the type specified by cls, type_arguments, and nullability
@@ -1266,7 +1256,7 @@
   ArrayPtr fields() const {
     // We rely on the fact that any loads from the array are dependent loads
     // and avoid the load-acquire barrier here.
-    return raw_ptr()->fields();
+    return untag()->fields();
   }
   void SetFields(const Array& value) const;
   void AddField(const Field& field) const;
@@ -1290,7 +1280,7 @@
   ArrayPtr current_functions() const {
     // We rely on the fact that any loads from the array are dependent loads
     // and avoid the load-acquire barrier here.
-    return raw_ptr()->functions();
+    return untag()->functions();
   }
   ArrayPtr functions() const {
     DEBUG_ASSERT(
@@ -1337,10 +1327,10 @@
 
   void RehashConstants(Zone* zone) const;
 
-  bool RequireLegacyErasureOfConstants(Zone* zone) const;
+  bool RequireCanonicalTypeErasureOfConstants(Zone* zone) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ClassLayout));
+    return RoundedAllocationSize(sizeof(UntaggedClass));
   }
 
   bool is_implemented() const { return ImplementedBit::decode(state_bits()); }
@@ -1349,17 +1339,17 @@
   bool is_abstract() const { return AbstractBit::decode(state_bits()); }
   void set_is_abstract() const;
 
-  ClassLayout::ClassLoadingState class_loading_state() const {
+  UntaggedClass::ClassLoadingState class_loading_state() const {
     return ClassLoadingBits::decode(state_bits());
   }
 
   bool is_declaration_loaded() const {
-    return class_loading_state() >= ClassLayout::kDeclarationLoaded;
+    return class_loading_state() >= UntaggedClass::kDeclarationLoaded;
   }
   void set_is_declaration_loaded() const;
 
   bool is_type_finalized() const {
-    return class_loading_state() >= ClassLayout::kTypeFinalized;
+    return class_loading_state() >= UntaggedClass::kTypeFinalized;
   }
   void set_is_type_finalized() const;
 
@@ -1373,21 +1363,21 @@
 
   bool is_finalized() const {
     return ClassFinalizedBits::decode(state_bits()) ==
-               ClassLayout::kFinalized ||
+               UntaggedClass::kFinalized ||
            ClassFinalizedBits::decode(state_bits()) ==
-               ClassLayout::kAllocateFinalized;
+               UntaggedClass::kAllocateFinalized;
   }
   void set_is_finalized() const;
 
   bool is_allocate_finalized() const {
     return ClassFinalizedBits::decode(state_bits()) ==
-           ClassLayout::kAllocateFinalized;
+           UntaggedClass::kAllocateFinalized;
   }
   void set_is_allocate_finalized() const;
 
   bool is_prefinalized() const {
     return ClassFinalizedBits::decode(state_bits()) ==
-           ClassLayout::kPreFinalized;
+           UntaggedClass::kPreFinalized;
   }
 
   void set_is_prefinalized() const;
@@ -1417,19 +1407,19 @@
   bool is_loaded() const { return IsLoadedBit::decode(state_bits()); }
   void set_is_loaded(bool value) const;
 
-  uint16_t num_native_fields() const { return raw_ptr()->num_native_fields_; }
+  uint16_t num_native_fields() const { return untag()->num_native_fields_; }
   void set_num_native_fields(uint16_t value) const {
-    StoreNonPointer(&raw_ptr()->num_native_fields_, value);
+    StoreNonPointer(&untag()->num_native_fields_, value);
   }
 
-  CodePtr allocation_stub() const { return raw_ptr()->allocation_stub(); }
+  CodePtr allocation_stub() const { return untag()->allocation_stub(); }
   void set_allocation_stub(const Code& value) const;
 
   intptr_t kernel_offset() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     return 0;
 #else
-    return raw_ptr()->kernel_offset_;
+    return untag()->kernel_offset_;
 #endif
   }
 
@@ -1438,7 +1428,7 @@
     UNREACHABLE();
 #else
     ASSERT(value >= 0);
-    StoreNonPointer(&raw_ptr()->kernel_offset_, value);
+    StoreNonPointer(&untag()->kernel_offset_, value);
 #endif
   }
 
@@ -1452,7 +1442,7 @@
 
   FunctionPtr GetInvocationDispatcher(const String& target_name,
                                       const Array& args_desc,
-                                      FunctionLayout::Kind kind,
+                                      UntaggedFunction::Kind kind,
                                       bool create_if_absent) const;
 
   void Finalize() const;
@@ -1491,7 +1481,7 @@
 
   // Allocate a class used for VM internal objects.
   template <class FakeObject, class TargetFakeObject>
-  static ClassPtr New(Isolate* isolate, bool register_class = true);
+  static ClassPtr New(IsolateGroup* isolate_group, bool register_class = true);
 
   // Allocate instance classes.
   static ClassPtr New(const Library& lib,
@@ -1504,20 +1494,24 @@
                                    int num_fields);
 
   // Allocate the raw string classes.
-  static ClassPtr NewStringClass(intptr_t class_id, Isolate* isolate);
+  static ClassPtr NewStringClass(intptr_t class_id,
+                                 IsolateGroup* isolate_group);
 
   // Allocate the raw TypedData classes.
-  static ClassPtr NewTypedDataClass(intptr_t class_id, Isolate* isolate);
+  static ClassPtr NewTypedDataClass(intptr_t class_id,
+                                    IsolateGroup* isolate_group);
 
   // Allocate the raw TypedDataView/ByteDataView classes.
-  static ClassPtr NewTypedDataViewClass(intptr_t class_id, Isolate* isolate);
+  static ClassPtr NewTypedDataViewClass(intptr_t class_id,
+                                        IsolateGroup* isolate_group);
 
   // Allocate the raw ExternalTypedData classes.
   static ClassPtr NewExternalTypedDataClass(intptr_t class_id,
-                                            Isolate* isolate);
+                                            IsolateGroup* isolate);
 
   // Allocate the raw Pointer classes.
-  static ClassPtr NewPointerClass(intptr_t class_id, Isolate* isolate);
+  static ClassPtr NewPointerClass(intptr_t class_id,
+                                  IsolateGroup* isolate_group);
 
   // Register code that has used CHA for optimization.
   // TODO(srdjan): Also register kind of CHA optimization (e.g.: leaf class,
@@ -1536,72 +1530,74 @@
   ArrayPtr dependent_code() const;
   void set_dependent_code(const Array& array) const;
 
-  bool TraceAllocation(Isolate* isolate) const;
+  bool TraceAllocation(IsolateGroup* isolate_group) const;
   void SetTraceAllocation(bool trace_allocation) const;
 
-  void ReplaceEnum(IsolateReloadContext* reload_context,
+  void ReplaceEnum(ProgramReloadContext* reload_context,
                    const Class& old_enum) const;
-  void CopyStaticFieldValues(IsolateReloadContext* reload_context,
+  void CopyStaticFieldValues(ProgramReloadContext* reload_context,
                              const Class& old_cls) const;
   void PatchFieldsAndFunctions() const;
-  void MigrateImplicitStaticClosures(IsolateReloadContext* context,
+  void MigrateImplicitStaticClosures(ProgramReloadContext* context,
                                      const Class& new_cls) const;
   void CopyCanonicalConstants(const Class& old_cls) const;
   void CopyDeclarationType(const Class& old_cls) const;
   void CheckReload(const Class& replacement,
-                   IsolateReloadContext* context) const;
+                   ProgramReloadContext* context) const;
 
   void AddInvocationDispatcher(const String& target_name,
                                const Array& args_desc,
                                const Function& dispatcher) const;
 
   static int32_t host_instance_size_in_words(const ClassPtr cls) {
-    return cls->ptr()->host_instance_size_in_words_;
+    return cls->untag()->host_instance_size_in_words_;
   }
 
   static int32_t target_instance_size_in_words(const ClassPtr cls) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return cls->ptr()->target_instance_size_in_words_;
+    return cls->untag()->target_instance_size_in_words_;
 #else
     return host_instance_size_in_words(cls);
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
   }
 
   static int32_t host_next_field_offset_in_words(const ClassPtr cls) {
-    return cls->ptr()->host_next_field_offset_in_words_;
+    return cls->untag()->host_next_field_offset_in_words_;
   }
 
   static int32_t target_next_field_offset_in_words(const ClassPtr cls) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return cls->ptr()->target_next_field_offset_in_words_;
+    return cls->untag()->target_next_field_offset_in_words_;
 #else
     return host_next_field_offset_in_words(cls);
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
   }
 
   static int32_t host_type_arguments_field_offset_in_words(const ClassPtr cls) {
-    return cls->ptr()->host_type_arguments_field_offset_in_words_;
+    return cls->untag()->host_type_arguments_field_offset_in_words_;
   }
 
   static int32_t target_type_arguments_field_offset_in_words(
       const ClassPtr cls) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return cls->ptr()->target_type_arguments_field_offset_in_words_;
+    return cls->untag()->target_type_arguments_field_offset_in_words_;
 #else
     return host_type_arguments_field_offset_in_words(cls);
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
   }
 
  private:
-  TypePtr declaration_type() const { return raw_ptr()->declaration_type(); }
+  TypePtr declaration_type() const {
+    return untag()->declaration_type<std::memory_order_acquire>();
+  }
 
   // Caches the declaration type of this class.
   void set_declaration_type(const Type& type) const;
 
   bool CanReloadFinalized(const Class& replacement,
-                          IsolateReloadContext* context) const;
+                          ProgramReloadContext* context) const;
   bool CanReloadPreFinalized(const Class& replacement,
-                             IsolateReloadContext* context) const;
+                             ProgramReloadContext* context) const;
 
   // Tells whether instances need morphing for reload.
   bool RequiresInstanceMorphing(const Class& replacement) const;
@@ -1638,11 +1634,11 @@
   class ConstBit : public BitField<uint32_t, bool, kConstBit, 1> {};
   class ImplementedBit : public BitField<uint32_t, bool, kImplementedBit, 1> {};
   class ClassFinalizedBits : public BitField<uint32_t,
-                                             ClassLayout::ClassFinalizedState,
+                                             UntaggedClass::ClassFinalizedState,
                                              kClassFinalizedPos,
                                              kClassFinalizedSize> {};
   class ClassLoadingBits : public BitField<uint32_t,
-                                           ClassLayout::ClassLoadingState,
+                                           UntaggedClass::ClassLoadingState,
                                            kClassLoadingPos,
                                            kClassLoadingSize> {};
   class AbstractBit : public BitField<uint32_t, bool, kAbstractBit, 1> {};
@@ -1664,7 +1660,7 @@
 
   FunctionPtr CreateInvocationDispatcher(const String& target_name,
                                          const Array& args_desc,
-                                         FunctionLayout::Kind kind) const;
+                                         UntaggedFunction::Kind kind) const;
 
   // Returns the bitmap of unboxed fields
   UnboxedFieldBitmap CalculateFieldOffsets() const;
@@ -1675,13 +1671,13 @@
   // Initial value for the cached number of type arguments.
   static const intptr_t kUnknownNumTypeArguments = -1;
 
-  int16_t num_type_arguments() const { return raw_ptr()->num_type_arguments_; }
+  int16_t num_type_arguments() const { return untag()->num_type_arguments_; }
 
   uint32_t state_bits() const {
     // Ensure any following load instructions do not get performed before this
     // one.
     return LoadNonPointer<uint32_t, std::memory_order_acquire>(
-        &raw_ptr()->state_bits_);
+        &untag()->state_bits_);
   }
 
  public:
@@ -1719,7 +1715,7 @@
   // Allocate an instance class which has a VM implementation.
   template <class FakeInstance, class TargetFakeInstance>
   static ClassPtr New(intptr_t id,
-                      Isolate* isolate,
+                      IsolateGroup* isolate_group,
                       bool register_class = true,
                       bool is_abstract = false);
 
@@ -1745,32 +1741,32 @@
 
 class PatchClass : public Object {
  public:
-  ClassPtr patched_class() const { return raw_ptr()->patched_class(); }
-  ClassPtr origin_class() const { return raw_ptr()->origin_class(); }
-  ScriptPtr script() const { return raw_ptr()->script(); }
+  ClassPtr patched_class() const { return untag()->patched_class(); }
+  ClassPtr origin_class() const { return untag()->origin_class(); }
+  ScriptPtr script() const { return untag()->script(); }
   ExternalTypedDataPtr library_kernel_data() const {
-    return raw_ptr()->library_kernel_data();
+    return untag()->library_kernel_data();
   }
   void set_library_kernel_data(const ExternalTypedData& data) const;
 
   intptr_t library_kernel_offset() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return raw_ptr()->library_kernel_offset_;
+    return untag()->library_kernel_offset_;
 #else
     return -1;
 #endif
   }
   void set_library_kernel_offset(intptr_t offset) const {
     NOT_IN_PRECOMPILED(
-        StoreNonPointer(&raw_ptr()->library_kernel_offset_, offset));
+        StoreNonPointer(&untag()->library_kernel_offset_, offset));
   }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(PatchClassLayout));
+    return RoundedAllocationSize(sizeof(UntaggedPatchClass));
   }
   static bool IsInFullSnapshot(PatchClassPtr cls) {
     NoSafepointScope no_safepoint;
-    return Class::IsInFullSnapshot(cls->ptr()->patched_class());
+    return Class::IsInFullSnapshot(cls->untag()->patched_class());
   }
 
   static PatchClassPtr New(const Class& patched_class,
@@ -1791,19 +1787,19 @@
 
 class SingleTargetCache : public Object {
  public:
-  CodePtr target() const { return raw_ptr()->target(); }
+  CodePtr target() const { return untag()->target(); }
   void set_target(const Code& target) const;
   static intptr_t target_offset() {
-    return OFFSET_OF(SingleTargetCacheLayout, target_);
+    return OFFSET_OF(UntaggedSingleTargetCache, target_);
   }
 
 #define DEFINE_NON_POINTER_FIELD_ACCESSORS(type, name)                         \
-  type name() const { return raw_ptr()->name##_; }                             \
+  type name() const { return untag()->name##_; }                               \
   void set_##name(type value) const {                                          \
-    StoreNonPointer(&raw_ptr()->name##_, value);                               \
+    StoreNonPointer(&untag()->name##_, value);                                 \
   }                                                                            \
   static intptr_t name##_offset() {                                            \
-    return OFFSET_OF(SingleTargetCacheLayout, name##_);                        \
+    return OFFSET_OF(UntaggedSingleTargetCache, name##_);                      \
   }
 
   DEFINE_NON_POINTER_FIELD_ACCESSORS(uword, entry_point);
@@ -1812,7 +1808,7 @@
 #undef DEFINE_NON_POINTER_FIELD_ACCESSORS
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(SingleTargetCacheLayout));
+    return RoundedAllocationSize(sizeof(UntaggedSingleTargetCache));
   }
 
   static SingleTargetCachePtr New();
@@ -1824,26 +1820,26 @@
 
 class MonomorphicSmiableCall : public Object {
  public:
-  CodePtr target() const { return raw_ptr()->target(); }
-  classid_t expected_cid() const { return raw_ptr()->expected_cid_; }
+  CodePtr target() const { return untag()->target(); }
+  classid_t expected_cid() const { return untag()->expected_cid_; }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(MonomorphicSmiableCallLayout));
+    return RoundedAllocationSize(sizeof(UntaggedMonomorphicSmiableCall));
   }
 
   static MonomorphicSmiableCallPtr New(classid_t expected_cid,
                                        const Code& target);
 
   static intptr_t expected_cid_offset() {
-    return OFFSET_OF(MonomorphicSmiableCallLayout, expected_cid_);
+    return OFFSET_OF(UntaggedMonomorphicSmiableCall, expected_cid_);
   }
 
   static intptr_t target_offset() {
-    return OFFSET_OF(MonomorphicSmiableCallLayout, target_);
+    return OFFSET_OF(UntaggedMonomorphicSmiableCall, target_);
   }
 
   static intptr_t entrypoint_offset() {
-    return OFFSET_OF(MonomorphicSmiableCallLayout, entrypoint_);
+    return OFFSET_OF(UntaggedMonomorphicSmiableCall, entrypoint_);
   }
 
  private:
@@ -1853,8 +1849,8 @@
 
 class CallSiteData : public Object {
  public:
-  StringPtr target_name() const { return raw_ptr()->target_name(); }
-  ArrayPtr arguments_descriptor() const { return raw_ptr()->args_descriptor(); }
+  StringPtr target_name() const { return untag()->target_name(); }
+  ArrayPtr arguments_descriptor() const { return untag()->args_descriptor(); }
 
   intptr_t TypeArgsLen() const;
 
@@ -1867,11 +1863,11 @@
   intptr_t SizeWithTypeArgs() const;
 
   static intptr_t target_name_offset() {
-    return OFFSET_OF(CallSiteDataLayout, target_name_);
+    return OFFSET_OF(UntaggedCallSiteData, target_name_);
   }
 
   static intptr_t arguments_descriptor_offset() {
-    return OFFSET_OF(CallSiteDataLayout, args_descriptor_);
+    return OFFSET_OF(UntaggedCallSiteData, args_descriptor_);
   }
 
  private:
@@ -1887,11 +1883,11 @@
 class UnlinkedCall : public CallSiteData {
  public:
   bool can_patch_to_monomorphic() const {
-    return raw_ptr()->can_patch_to_monomorphic_;
+    return untag()->can_patch_to_monomorphic_;
   }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(UnlinkedCallLayout));
+    return RoundedAllocationSize(sizeof(UntaggedUnlinkedCall));
   }
 
   intptr_t Hashcode() const;
@@ -1921,7 +1917,7 @@
 
   void SetOriginal(const ICData& value) const;
 
-  bool IsOriginal() const { return Original() == this->raw(); }
+  bool IsOriginal() const { return Original() == this->ptr(); }
 
   intptr_t NumArgsTested() const;
 
@@ -1930,7 +1926,7 @@
     UNREACHABLE();
     return -1;
 #else
-    return raw_ptr()->deopt_id_;
+    return untag()->deopt_id_;
 #endif
   }
 
@@ -1938,10 +1934,10 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   AbstractTypePtr receivers_static_type() const {
-    return raw_ptr()->receivers_static_type();
+    return untag()->receivers_static_type();
   }
   bool is_tracking_exactness() const {
-    return TrackingExactnessBit::decode(raw_ptr()->state_bits_);
+    return TrackingExactnessBit::decode(untag()->state_bits_);
   }
 #else
   bool is_tracking_exactness() const { return false; }
@@ -2015,12 +2011,12 @@
   void set_is_megamorphic(bool value) const {
     // We don't have concurrent RW access to [state_bits_].
     const uint32_t updated_bits =
-        MegamorphicBit::update(value, raw_ptr()->state_bits_);
+        MegamorphicBit::update(value, untag()->state_bits_);
 
     // Though we ensure that once the state bits are updated, all other previous
     // writes to the IC are visible as well.
     StoreNonPointer<uint32_t, uint32_t, std::memory_order_release>(
-        &raw_ptr()->state_bits_, updated_bits);
+        &untag()->state_bits_, updated_bits);
   }
 
   // The length of the array. This includes all sentinel entries including
@@ -2038,11 +2034,11 @@
   bool NumberOfChecksIs(intptr_t n) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ICDataLayout));
+    return RoundedAllocationSize(sizeof(UntaggedICData));
   }
 
   static intptr_t state_bits_offset() {
-    return OFFSET_OF(ICDataLayout, state_bits_);
+    return OFFSET_OF(UntaggedICData, state_bits_);
   }
 
   static intptr_t NumArgsTestedShift() { return kNumArgsTestedPos; }
@@ -2051,13 +2047,15 @@
     return ((1 << kNumArgsTestedSize) - 1) << kNumArgsTestedPos;
   }
 
-  static intptr_t entries_offset() { return OFFSET_OF(ICDataLayout, entries_); }
+  static intptr_t entries_offset() {
+    return OFFSET_OF(UntaggedICData, entries_);
+  }
 
-  static intptr_t owner_offset() { return OFFSET_OF(ICDataLayout, owner_); }
+  static intptr_t owner_offset() { return OFFSET_OF(UntaggedICData, owner_); }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   static intptr_t receivers_static_type_offset() {
-    return OFFSET_OF(ICDataLayout, receivers_static_type_);
+    return OFFSET_OF(UntaggedICData, receivers_static_type_);
   }
 #endif
 
@@ -2142,7 +2140,7 @@
   intptr_t GetCountAt(intptr_t index) const;
   intptr_t AggregateCount() const;
 
-  // Returns this->raw() if num_args_tested == 1 and arg_nr == 1, otherwise
+  // Returns this->untag() if num_args_tested == 1 and arg_nr == 1, otherwise
   // returns a new ICData object containing only unique arg_nr checks.
   // Returns only used entries.
   ICDataPtr AsUnaryClassChecksForArgNr(intptr_t arg_nr) const;
@@ -2233,17 +2231,17 @@
   intptr_t FindCheck(const GrowableArray<intptr_t>& cids) const;
 
   ArrayPtr entries() const {
-    return raw_ptr()->entries<std::memory_order_acquire>();
+    return untag()->entries<std::memory_order_acquire>();
   }
 
   bool receiver_cannot_be_smi() const {
     return ReceiverCannotBeSmiBit::decode(
-        LoadNonPointer(&raw_ptr()->state_bits_));
+        LoadNonPointer(&untag()->state_bits_));
   }
 
   void set_receiver_cannot_be_smi(bool value) const {
     set_state_bits(ReceiverCannotBeSmiBit::encode(value) |
-                   LoadNonPointer(&raw_ptr()->state_bits_));
+                   LoadNonPointer(&untag()->state_bits_));
   }
 
  private:
@@ -2261,9 +2259,8 @@
   void set_rebind_rule(uint32_t rebind_rule) const;
   void set_state_bits(uint32_t bits) const;
   void set_tracking_exactness(bool value) const {
-    StoreNonPointer(
-        &raw_ptr()->state_bits_,
-        TrackingExactnessBit::update(value, raw_ptr()->state_bits_));
+    StoreNonPointer(&untag()->state_bits_,
+                    TrackingExactnessBit::update(value, untag()->state_bits_));
   }
 
   // Does entry |index| contain the sentinel value?
@@ -2293,7 +2290,7 @@
     // Ensure any following load instructions do not get performed before this
     // one.
     const uint32_t bits = LoadNonPointer<uint32_t, std::memory_order_acquire>(
-        &raw_ptr()->state_bits_);
+        &untag()->state_bits_);
     return MegamorphicBit::decode(bits);
   }
 
@@ -2315,7 +2312,7 @@
   };
 
   COMPILE_ASSERT(kReceiverCannotBeSmiPos + kReceiverCannotBeSmiSize <=
-                 sizeof(ICDataLayout::state_bits_) * kBitsPerWord);
+                 sizeof(UntaggedICData::state_bits_) * kBitsPerWord);
   COMPILE_ASSERT(kNumRebindRules <= (1 << kRebindRuleSize));
 
   class NumArgsTestedBits : public BitField<uint32_t,
@@ -2438,7 +2435,7 @@
 
 class Function : public Object {
  public:
-  StringPtr name() const { return raw_ptr()->name(); }
+  StringPtr name() const { return untag()->name(); }
   StringPtr UserVisibleName() const;  // Same as scrubbed name.
   const char* UserVisibleNameCString() const;
 
@@ -2454,29 +2451,16 @@
 
   StringPtr GetSource() const;
 
-  // Return the type of this function's signature. It may not be canonical yet.
-  // For example, if this function has a signature of the form
-  // '(T, [B, C]) => R', where 'T' and 'R' are type parameters of the
-  // owner class of this function, then its signature type is a parameterized
-  // function type with uninstantiated type arguments 'T' and 'R' as elements of
-  // its type argument vector.
-  // A function type is non-nullable by default.
-  TypePtr SignatureType(
-      Nullability nullability = Nullability::kNonNullable) const;
-  TypePtr ExistingSignatureType() const;
-
-  // Update the signature type (with a canonical version).
-  void SetSignatureType(const Type& value) const;
-
-  // Set the "C signature" function for an FFI trampoline.
+  // Set the "C signature" for an FFI trampoline.
   // Can only be used on FFI trampolines.
-  void SetFfiCSignature(const Function& sig) const;
+  void SetFfiCSignature(const FunctionType& sig) const;
 
-  // Retrieves the "C signature" function for an FFI trampoline.
+  // Retrieves the "C signature" for an FFI trampoline.
   // Can only be used on FFI trampolines.
-  FunctionPtr FfiCSignature() const;
+  FunctionTypePtr FfiCSignature() const;
 
   bool FfiCSignatureContainsHandles() const;
+  bool FfiCSignatureReturnsStruct() const;
 
   // Can only be called on FFI trampolines.
   // -1 for Dart -> native calls.
@@ -2499,18 +2483,18 @@
   // Can only be called on FFI trampolines.
   void SetFfiCallbackExceptionalReturn(const Instance& value) const;
 
-  // Return a new function with instantiated result and parameter types.
-  FunctionPtr InstantiateSignatureFrom(
-      const TypeArguments& instantiator_type_arguments,
-      const TypeArguments& function_type_arguments,
-      intptr_t num_free_fun_type_params,
-      Heap::Space space) const;
+  // Return the signature of this function.
+  FunctionTypePtr signature() const { return untag()->signature(); }
+  void set_signature(const FunctionType& value) const;
+  static intptr_t signature_offset() {
+    return OFFSET_OF(UntaggedFunction, signature_);
+  }
 
   // Build a string of the form '<T>(T, {B b, C c}) => R' representing the
   // internal signature of the given function. In this example, T is a type
   // parameter of this function and R is a type parameter of class C, the owner
   // of the function. B and C are not type parameters.
-  StringPtr Signature() const;
+  StringPtr InternalSignature() const;
 
   // Build a string of the form '<T>(T, {B b, C c}) => R' representing the
   // user visible signature of the given function. In this example, T is a type
@@ -2519,9 +2503,6 @@
   // Implicit parameters are hidden.
   StringPtr UserVisibleSignature() const;
 
-  void PrintSignature(NameVisibility name_visibility,
-                      BaseTextBuffer* printer) const;
-
   // Returns true if the signature of this function is instantiated, i.e. if it
   // does not involve generic parameter types or generic result type.
   // Note that function type parameters declared by this function do not make
@@ -2535,7 +2516,7 @@
   void set_owner(const Object& value) const;
   ClassPtr origin() const;
   ScriptPtr script() const;
-  ObjectPtr RawOwner() const { return raw_ptr()->owner(); }
+  ObjectPtr RawOwner() const { return untag()->owner(); }
 
   // The NNBD mode of the library declaring this function.
   // TODO(alexmarkov): nnbd_mode() doesn't work for mixins.
@@ -2552,18 +2533,16 @@
   StringPtr native_name() const;
   void set_native_name(const String& name) const;
 
-  AbstractTypePtr result_type() const { return raw_ptr()->result_type(); }
-  void set_result_type(const AbstractType& value) const;
+  AbstractTypePtr result_type() const {
+    return untag()->signature()->untag()->result_type();
+  }
 
   // The parameters, starting with NumImplicitParameters() parameters which are
   // only visible to the VM, but not to Dart users.
   // Note that type checks exclude implicit parameters.
   AbstractTypePtr ParameterTypeAt(intptr_t index) const;
-  void SetParameterTypeAt(intptr_t index, const AbstractType& value) const;
-  ArrayPtr parameter_types() const { return raw_ptr()->parameter_types(); }
-  void set_parameter_types(const Array& value) const;
-  static intptr_t parameter_types_offset() {
-    return OFFSET_OF(FunctionLayout, parameter_types_);
+  ArrayPtr parameter_types() const {
+    return untag()->signature()->untag()->parameter_types();
   }
 
   // Parameter names are valid for all valid parameter indices, and are not
@@ -2572,54 +2551,36 @@
   // array isn't necessarily NumParameters(), but the first NumParameters()
   // elements are the names.
   StringPtr ParameterNameAt(intptr_t index) const;
-  void SetParameterNameAt(intptr_t index, const String& value) const;
-  ArrayPtr parameter_names() const { return raw_ptr()->parameter_names(); }
+  ArrayPtr parameter_names() const { return untag()->parameter_names(); }
+  void SetParameterNamesFrom(const FunctionType& signature) const;
   static intptr_t parameter_names_offset() {
-    return OFFSET_OF(FunctionLayout, parameter_names_);
+    return OFFSET_OF(UntaggedFunction, parameter_names_);
   }
 
-  // Sets up the function's parameter name array, including appropriate space
-  // for any possible parameter flags. This may be an overestimate if some
-  // parameters don't have flags, and so TruncateUnusedParameterFlags() should
-  // be called after all parameter flags have been appropriately set.
-  //
-  // Assumes that the number of fixed and optional parameters for the function
-  // has already been set.
-  void CreateNameArrayIncludingFlags(Heap::Space space) const;
-
-  // Truncate the parameter names array to remove any unused flag slots. Make
-  // sure to only do this after calling SetIsRequiredAt as necessary.
-  void TruncateUnusedParameterFlags() const;
-
   // The required flags are stored at the end of the parameter_names. The flags
-  // are packed into Smis.
+  // are packed into SMIs, but omitted if they're 0.
   bool IsRequiredAt(intptr_t index) const;
-  void SetIsRequiredAt(intptr_t index) const;
 
   // The type parameters (and their bounds) are specified as an array of
-  // TypeParameter.
+  // TypeParameter stored in the signature. They are part of the function type.
   TypeArgumentsPtr type_parameters() const {
-    return raw_ptr()->type_parameters();
+    return untag()->signature()->untag()->type_parameters();
   }
-  void set_type_parameters(const TypeArguments& value) const;
-  static intptr_t type_parameters_offset() {
-    return OFFSET_OF(FunctionLayout, type_parameters_);
-  }
-  intptr_t NumTypeParameters(Thread* thread) const;
+
   intptr_t NumTypeParameters() const {
-    return NumTypeParameters(Thread::Current());
+    return UntaggedFunction::PackedNumTypeParameters::decode(
+        untag()->packed_fields_);
   }
+  void SetNumTypeParameters(intptr_t value) const;
 
-  // Returns true if this function has the same number of type parameters with
-  // equal bounds as the other function. Type parameter names are ignored.
-  bool HasSameTypeParametersAndBounds(const Function& other,
-                                      TypeEquality kind) const;
+  // Return the cumulative number of type arguments in all parent functions.
+  intptr_t NumParentTypeArguments() const;
 
-  // Return the number of type parameters declared in parent generic functions.
-  intptr_t NumParentTypeParameters() const;
-
-  // Print the signature type of this function and of all of its parents.
-  void PrintSignatureTypes() const;
+  // Return the cumulative number of type arguments in all parent functions and
+  // own type arguments.
+  intptr_t NumTypeArguments() const {
+    return NumParentTypeArguments() + NumTypeParameters();
+  }
 
   // Return a TypeParameter if the type_name is a type parameter of this
   // function or of one of its parent functions.
@@ -2629,8 +2590,8 @@
                                        intptr_t* function_level) const;
 
   // Return true if this function declares type parameters.
-  bool IsGeneric() const { return NumTypeParameters(Thread::Current()) > 0; }
-
+  // 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;
 
@@ -2639,7 +2600,9 @@
   void InstallOptimizedCode(const Code& code) const;
   void AttachCode(const Code& value) const;
   void SetInstructions(const Code& value) const;
+  void SetInstructionsSafe(const Code& value) const;
   void ClearCode() const;
+  void ClearCodeSafe() const;
 
   // Disables optimized code and switches to unoptimized code.
   void SwitchToUnoptimizedCode() const;
@@ -2659,45 +2622,41 @@
 
   // Return the most recently compiled and installed code for this function.
   // It is not the only Code object that points to this function.
-  CodePtr CurrentCode() const { return CurrentCodeOf(raw()); }
+  CodePtr CurrentCode() const { return CurrentCodeOf(ptr()); }
 
   bool SafeToClosurize() const;
 
   static CodePtr CurrentCodeOf(const FunctionPtr function) {
-    return function->ptr()->code();
+    return function->untag()->code();
   }
 
   CodePtr unoptimized_code() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     return static_cast<CodePtr>(Object::null());
 #else
-    return raw_ptr()->unoptimized_code();
+    return untag()->unoptimized_code();
 #endif
   }
   void set_unoptimized_code(const Code& value) const;
   bool HasCode() const;
   static bool HasCode(FunctionPtr function);
 
-  static intptr_t code_offset() { return OFFSET_OF(FunctionLayout, code_); }
-
-  static intptr_t result_type_offset() {
-    return OFFSET_OF(FunctionLayout, result_type_);
-  }
+  static intptr_t code_offset() { return OFFSET_OF(UntaggedFunction, code_); }
 
   static intptr_t entry_point_offset(
       CodeEntryKind entry_kind = CodeEntryKind::kNormal) {
     switch (entry_kind) {
       case CodeEntryKind::kNormal:
-        return OFFSET_OF(FunctionLayout, entry_point_);
+        return OFFSET_OF(UntaggedFunction, entry_point_);
       case CodeEntryKind::kUnchecked:
-        return OFFSET_OF(FunctionLayout, unchecked_entry_point_);
+        return OFFSET_OF(UntaggedFunction, unchecked_entry_point_);
       default:
         UNREACHABLE();
     }
   }
 
   static intptr_t unchecked_entry_point_offset() {
-    return OFFSET_OF(FunctionLayout, unchecked_entry_point_);
+    return OFFSET_OF(UntaggedFunction, unchecked_entry_point_);
   }
 
   virtual intptr_t Hash() const;
@@ -2739,6 +2698,7 @@
                DefaultTypeArgumentsKind,
                0,
                kDefaultTypeArgumentsKindFieldSize>;
+  // TODO(regis): Rename to NumParentTypeArgumentsField.
   // Just use the rest of the space for the number of parent type parameters.
   using NumParentTypeParametersField =
       BitField<intptr_t,
@@ -2769,11 +2729,6 @@
       DefaultTypeArgumentsKind* kind_out = nullptr) const;
   void set_default_type_arguments(const TypeArguments& value) const;
 
-  // Enclosed generated closure function of this local function.
-  // This will only work after the closure function has been allocated in the
-  // isolate's object_store.
-  FunctionPtr GetGeneratedClosure() const;
-
   // Enclosing outermost function of this local function.
   FunctionPtr GetOutermostFunction() const;
 
@@ -2787,19 +2742,19 @@
   FieldPtr accessor_field() const;
 
   bool IsRegularFunction() const {
-    return kind() == FunctionLayout::kRegularFunction;
+    return kind() == UntaggedFunction::kRegularFunction;
   }
 
   bool IsMethodExtractor() const {
-    return kind() == FunctionLayout::kMethodExtractor;
+    return kind() == UntaggedFunction::kMethodExtractor;
   }
 
   bool IsNoSuchMethodDispatcher() const {
-    return kind() == FunctionLayout::kNoSuchMethodDispatcher;
+    return kind() == UntaggedFunction::kNoSuchMethodDispatcher;
   }
 
   bool IsInvokeFieldDispatcher() const {
-    return kind() == FunctionLayout::kInvokeFieldDispatcher;
+    return kind() == UntaggedFunction::kInvokeFieldDispatcher;
   }
 
   bool IsDynamicInvokeFieldDispatcher() const {
@@ -2817,13 +2772,13 @@
   bool IsDynamicClosureCallDispatcher(Thread* thread) const;
 
   bool IsDynamicInvocationForwarder() const {
-    return kind() == FunctionLayout::kDynamicInvocationForwarder;
+    return kind() == UntaggedFunction::kDynamicInvocationForwarder;
   }
 
   bool IsImplicitGetterOrSetter() const {
-    return kind() == FunctionLayout::kImplicitGetter ||
-           kind() == FunctionLayout::kImplicitSetter ||
-           kind() == FunctionLayout::kImplicitStaticGetter;
+    return kind() == UntaggedFunction::kImplicitGetter ||
+           kind() == UntaggedFunction::kImplicitSetter ||
+           kind() == UntaggedFunction::kImplicitStaticGetter;
   }
 
   // Returns true iff an implicit closure function has been created
@@ -2853,25 +2808,25 @@
   FunctionPtr ForwardingTarget() const;
   void SetForwardingChecks(const Array& checks) const;
 
-  FunctionLayout::Kind kind() const {
-    return KindBits::decode(raw_ptr()->kind_tag_);
+  UntaggedFunction::Kind kind() const {
+    return KindBits::decode(untag()->kind_tag_);
   }
-  static FunctionLayout::Kind kind(FunctionPtr function) {
-    return KindBits::decode(function->ptr()->kind_tag_);
+  static UntaggedFunction::Kind kind(FunctionPtr function) {
+    return KindBits::decode(function->untag()->kind_tag_);
   }
 
-  FunctionLayout::AsyncModifier modifier() const {
-    return ModifierBits::decode(raw_ptr()->kind_tag_);
+  UntaggedFunction::AsyncModifier modifier() const {
+    return ModifierBits::decode(untag()->kind_tag_);
   }
 
-  static const char* KindToCString(FunctionLayout::Kind kind);
+  static const char* KindToCString(UntaggedFunction::Kind kind);
 
   bool IsGenerativeConstructor() const {
-    return (kind() == FunctionLayout::kConstructor) && !is_static();
+    return (kind() == UntaggedFunction::kConstructor) && !is_static();
   }
   bool IsImplicitConstructor() const;
   bool IsFactory() const {
-    return (kind() == FunctionLayout::kConstructor) && is_static();
+    return (kind() == UntaggedFunction::kConstructor) && is_static();
   }
 
   bool HasThisParameter() const {
@@ -2884,23 +2839,22 @@
       return false;
     }
     switch (kind()) {
-      case FunctionLayout::kRegularFunction:
-      case FunctionLayout::kGetterFunction:
-      case FunctionLayout::kSetterFunction:
-      case FunctionLayout::kImplicitGetter:
-      case FunctionLayout::kImplicitSetter:
-      case FunctionLayout::kMethodExtractor:
-      case FunctionLayout::kNoSuchMethodDispatcher:
-      case FunctionLayout::kInvokeFieldDispatcher:
-      case FunctionLayout::kDynamicInvocationForwarder:
+      case UntaggedFunction::kRegularFunction:
+      case UntaggedFunction::kGetterFunction:
+      case UntaggedFunction::kSetterFunction:
+      case UntaggedFunction::kImplicitGetter:
+      case UntaggedFunction::kImplicitSetter:
+      case UntaggedFunction::kMethodExtractor:
+      case UntaggedFunction::kNoSuchMethodDispatcher:
+      case UntaggedFunction::kInvokeFieldDispatcher:
+      case UntaggedFunction::kDynamicInvocationForwarder:
         return true;
-      case FunctionLayout::kClosureFunction:
-      case FunctionLayout::kImplicitClosureFunction:
-      case FunctionLayout::kSignatureFunction:
-      case FunctionLayout::kConstructor:
-      case FunctionLayout::kImplicitStaticGetter:
-      case FunctionLayout::kFieldInitializer:
-      case FunctionLayout::kIrregexpFunction:
+      case UntaggedFunction::kClosureFunction:
+      case UntaggedFunction::kImplicitClosureFunction:
+      case UntaggedFunction::kConstructor:
+      case UntaggedFunction::kImplicitStaticGetter:
+      case UntaggedFunction::kFieldInitializer:
+      case UntaggedFunction::kIrregexpFunction:
         return false;
       default:
         UNREACHABLE();
@@ -2912,23 +2866,22 @@
       return false;
     }
     switch (kind()) {
-      case FunctionLayout::kRegularFunction:
-      case FunctionLayout::kGetterFunction:
-      case FunctionLayout::kSetterFunction:
-      case FunctionLayout::kImplicitGetter:
-      case FunctionLayout::kImplicitSetter:
-      case FunctionLayout::kImplicitStaticGetter:
-      case FunctionLayout::kFieldInitializer:
-      case FunctionLayout::kIrregexpFunction:
+      case UntaggedFunction::kRegularFunction:
+      case UntaggedFunction::kGetterFunction:
+      case UntaggedFunction::kSetterFunction:
+      case UntaggedFunction::kImplicitGetter:
+      case UntaggedFunction::kImplicitSetter:
+      case UntaggedFunction::kImplicitStaticGetter:
+      case UntaggedFunction::kFieldInitializer:
+      case UntaggedFunction::kIrregexpFunction:
         return true;
-      case FunctionLayout::kClosureFunction:
-      case FunctionLayout::kImplicitClosureFunction:
-      case FunctionLayout::kSignatureFunction:
-      case FunctionLayout::kConstructor:
-      case FunctionLayout::kMethodExtractor:
-      case FunctionLayout::kNoSuchMethodDispatcher:
-      case FunctionLayout::kInvokeFieldDispatcher:
-      case FunctionLayout::kDynamicInvocationForwarder:
+      case UntaggedFunction::kClosureFunction:
+      case UntaggedFunction::kImplicitClosureFunction:
+      case UntaggedFunction::kConstructor:
+      case UntaggedFunction::kMethodExtractor:
+      case UntaggedFunction::kNoSuchMethodDispatcher:
+      case UntaggedFunction::kInvokeFieldDispatcher:
+      case UntaggedFunction::kDynamicInvocationForwarder:
         return false;
       default:
         UNREACHABLE();
@@ -2938,11 +2891,11 @@
   bool IsInFactoryScope() const;
 
   bool NeedsTypeArgumentTypeChecks() const {
-    return !(is_static() || (kind() == FunctionLayout::kConstructor));
+    return !(is_static() || (kind() == UntaggedFunction::kConstructor));
   }
 
   bool NeedsArgumentTypeChecks() const {
-    return !(is_static() || (kind() == FunctionLayout::kConstructor));
+    return !(is_static() || (kind() == UntaggedFunction::kConstructor));
   }
 
   bool NeedsMonomorphicCheckedEntry(Zone* zone) const;
@@ -2953,65 +2906,72 @@
 
   TokenPosition token_pos() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return TokenPosition();
+    return TokenPosition::kNoSource;
 #else
-    return raw_ptr()->token_pos_;
+    return untag()->token_pos_;
 #endif
   }
   void set_token_pos(TokenPosition value) const;
 
   TokenPosition end_token_pos() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return TokenPosition();
+    return TokenPosition::kNoSource;
 #else
-    return raw_ptr()->end_token_pos_;
+    return untag()->end_token_pos_;
 #endif
   }
   void set_end_token_pos(TokenPosition value) const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     UNREACHABLE();
 #else
-    StoreNonPointer(&raw_ptr()->end_token_pos_, value);
+    StoreNonPointer(&untag()->end_token_pos_, value);
 #endif
   }
 
+  // Returns the size of the source for this function.
+  intptr_t SourceSize() const;
+
+  // Reexported so they can be used by the flow graph builders.
+  using PackedHasNamedOptionalParameters =
+      UntaggedFunction::PackedHasNamedOptionalParameters;
+  using PackedNumFixedParameters = UntaggedFunction::PackedNumFixedParameters;
+  using PackedNumOptionalParameters =
+      UntaggedFunction::PackedNumOptionalParameters;
+
+  uint32_t packed_fields() const { return untag()->packed_fields_; }
+  void set_packed_fields(uint32_t packed_fields) const;
+  static intptr_t packed_fields_offset() {
+    return OFFSET_OF(UntaggedFunction, packed_fields_);
+  }
+
   intptr_t num_fixed_parameters() const {
-    return FunctionLayout::PackedNumFixedParameters::decode(
-        raw_ptr()->packed_fields_);
+    return UntaggedFunction::PackedNumFixedParameters::decode(
+        untag()->packed_fields_);
   }
   void set_num_fixed_parameters(intptr_t value) const;
 
-  uint32_t packed_fields() const { return raw_ptr()->packed_fields_; }
-  void set_packed_fields(uint32_t packed_fields) const;
-  static intptr_t packed_fields_offset() {
-    return OFFSET_OF(FunctionLayout, packed_fields_);
-  }
-  // Reexported so they can be used by the flow graph builders.
-  using PackedHasNamedOptionalParameters =
-      FunctionLayout::PackedHasNamedOptionalParameters;
-  using PackedNumFixedParameters = FunctionLayout::PackedNumFixedParameters;
-  using PackedNumOptionalParameters =
-      FunctionLayout::PackedNumOptionalParameters;
-
   bool HasOptionalParameters() const {
-    return PackedNumOptionalParameters::decode(raw_ptr()->packed_fields_) > 0;
+    return UntaggedFunction::PackedNumOptionalParameters::decode(
+               untag()->packed_fields_) > 0;
   }
   bool HasOptionalNamedParameters() const {
     return HasOptionalParameters() &&
-           PackedHasNamedOptionalParameters::decode(raw_ptr()->packed_fields_);
+           UntaggedFunction::PackedHasNamedOptionalParameters::decode(
+               untag()->packed_fields_);
   }
+  bool HasRequiredNamedParameters() const;
   bool HasOptionalPositionalParameters() const {
     return HasOptionalParameters() && !HasOptionalNamedParameters();
   }
   intptr_t NumOptionalParameters() const {
-    return PackedNumOptionalParameters::decode(raw_ptr()->packed_fields_);
+    return UntaggedFunction::PackedNumOptionalParameters::decode(
+        untag()->packed_fields_);
   }
-  void SetNumOptionalParameters(intptr_t num_optional_parameters,
-                                bool are_optional_positional) const;
-
   intptr_t NumOptionalPositionalParameters() const {
     return HasOptionalPositionalParameters() ? NumOptionalParameters() : 0;
   }
+  void SetNumOptionalParameters(intptr_t num_optional_parameters,
+                                bool are_optional_positional) const;
 
   intptr_t NumOptionalNamedParameters() const {
     return HasOptionalNamedParameters() ? NumOptionalParameters() : 0;
@@ -3033,12 +2993,12 @@
 #else
 #define DEFINE_GETTERS_AND_SETTERS(return_type, type, name)                    \
   static intptr_t name##_offset() {                                            \
-    return OFFSET_OF(FunctionLayout, name##_);                                 \
+    return OFFSET_OF(UntaggedFunction, name##_);                               \
   }                                                                            \
-  return_type name() const { return raw_ptr()->name##_; }                      \
+  return_type name() const { return untag()->name##_; }                        \
                                                                                \
   void set_##name(type value) const {                                          \
-    StoreNonPointer(&raw_ptr()->name##_, value);                               \
+    StoreNonPointer(&untag()->name##_, value);                                 \
   }
 #endif
 
@@ -3050,7 +3010,7 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
     return 0;
 #else
-    return raw_ptr()->kernel_offset_;
+    return untag()->kernel_offset_;
 #endif
   }
 
@@ -3059,7 +3019,7 @@
     UNREACHABLE();
 #else
     ASSERT(value >= 0);
-    StoreNonPointer(&raw_ptr()->kernel_offset_, value);
+    StoreNonPointer(&untag()->kernel_offset_, value);
 #endif
   }
 
@@ -3103,7 +3063,7 @@
   bool CanBeInlined() const;
 
   MethodRecognizer::Kind recognized_kind() const {
-    return RecognizedBits::decode(raw_ptr()->kind_tag_);
+    return RecognizedBits::decode(untag()->kind_tag_);
   }
   void set_recognized_kind(MethodRecognizer::Kind value) const;
 
@@ -3187,13 +3147,13 @@
 
   static constexpr intptr_t maximum_unboxed_parameter_count() {
     // Subtracts one that represents the return value
-    return FunctionLayout::UnboxedParameterBitmap::kCapacity - 1;
+    return UntaggedFunction::UnboxedParameterBitmap::kCapacity - 1;
   }
 
   void reset_unboxed_parameters_and_return() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    StoreNonPointer(&raw_ptr()->unboxed_parameters_info_,
-                    FunctionLayout::UnboxedParameterBitmap());
+    StoreNonPointer(&untag()->unboxed_parameters_info_,
+                    UntaggedFunction::UnboxedParameterBitmap());
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
   }
 
@@ -3201,8 +3161,8 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
     ASSERT(index >= 0 && index < maximum_unboxed_parameter_count());
     index++;  // position 0 is reserved for the return value
-    const_cast<FunctionLayout::UnboxedParameterBitmap*>(
-        &raw_ptr()->unboxed_parameters_info_)
+    const_cast<UntaggedFunction::UnboxedParameterBitmap*>(
+        &untag()->unboxed_parameters_info_)
         ->SetUnboxedInteger(index);
 #else
     UNREACHABLE();
@@ -3213,8 +3173,8 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
     ASSERT(index >= 0 && index < maximum_unboxed_parameter_count());
     index++;  // position 0 is reserved for the return value
-    const_cast<FunctionLayout::UnboxedParameterBitmap*>(
-        &raw_ptr()->unboxed_parameters_info_)
+    const_cast<UntaggedFunction::UnboxedParameterBitmap*>(
+        &untag()->unboxed_parameters_info_)
         ->SetUnboxedDouble(index);
 
 #else
@@ -3224,8 +3184,8 @@
 
   void set_unboxed_integer_return() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    const_cast<FunctionLayout::UnboxedParameterBitmap*>(
-        &raw_ptr()->unboxed_parameters_info_)
+    const_cast<UntaggedFunction::UnboxedParameterBitmap*>(
+        &untag()->unboxed_parameters_info_)
         ->SetUnboxedInteger(0);
 #else
     UNREACHABLE();
@@ -3234,8 +3194,8 @@
 
   void set_unboxed_double_return() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    const_cast<FunctionLayout::UnboxedParameterBitmap*>(
-        &raw_ptr()->unboxed_parameters_info_)
+    const_cast<UntaggedFunction::UnboxedParameterBitmap*>(
+        &untag()->unboxed_parameters_info_)
         ->SetUnboxedDouble(0);
 
 #else
@@ -3247,7 +3207,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
     ASSERT(index >= 0);
     index++;  // position 0 is reserved for the return value
-    return raw_ptr()->unboxed_parameters_info_.IsUnboxed(index);
+    return untag()->unboxed_parameters_info_.IsUnboxed(index);
 #else
     return false;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
@@ -3257,7 +3217,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
     ASSERT(index >= 0);
     index++;  // position 0 is reserved for the return value
-    return raw_ptr()->unboxed_parameters_info_.IsUnboxedInteger(index);
+    return untag()->unboxed_parameters_info_.IsUnboxedInteger(index);
 #else
     return false;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
@@ -3267,7 +3227,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
     ASSERT(index >= 0);
     index++;  // position 0 is reserved for the return value
-    return raw_ptr()->unboxed_parameters_info_.IsUnboxedDouble(index);
+    return untag()->unboxed_parameters_info_.IsUnboxedDouble(index);
 #else
     return false;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
@@ -3275,7 +3235,7 @@
 
   bool has_unboxed_return() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return raw_ptr()->unboxed_parameters_info_.IsUnboxed(0);
+    return untag()->unboxed_parameters_info_.IsUnboxed(0);
 #else
     return false;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
@@ -3283,7 +3243,7 @@
 
   bool has_unboxed_integer_return() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return raw_ptr()->unboxed_parameters_info_.IsUnboxedInteger(0);
+    return untag()->unboxed_parameters_info_.IsUnboxedInteger(0);
 #else
     return false;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
@@ -3291,7 +3251,7 @@
 
   bool has_unboxed_double_return() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    return raw_ptr()->unboxed_parameters_info_.IsUnboxedDouble(0);
+    return untag()->unboxed_parameters_info_.IsUnboxedDouble(0);
 #else
     return false;
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
@@ -3299,25 +3259,21 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   bool HasUnboxedParameters() const {
-    return raw_ptr()->unboxed_parameters_info_.HasUnboxedParameters();
+    return untag()->unboxed_parameters_info_.HasUnboxedParameters();
   }
   bool HasUnboxedReturnValue() const {
-    return raw_ptr()->unboxed_parameters_info_.HasUnboxedReturnValue();
+    return untag()->unboxed_parameters_info_.HasUnboxedReturnValue();
   }
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
 
-  // Returns true if the type of this function is a subtype of the type of
-  // the other function.
-  bool IsSubtypeOf(const Function& other, Heap::Space space) const;
-
   bool IsDispatcherOrImplicitAccessor() const {
     switch (kind()) {
-      case FunctionLayout::kImplicitGetter:
-      case FunctionLayout::kImplicitSetter:
-      case FunctionLayout::kImplicitStaticGetter:
-      case FunctionLayout::kNoSuchMethodDispatcher:
-      case FunctionLayout::kInvokeFieldDispatcher:
-      case FunctionLayout::kDynamicInvocationForwarder:
+      case UntaggedFunction::kImplicitGetter:
+      case UntaggedFunction::kImplicitSetter:
+      case UntaggedFunction::kImplicitStaticGetter:
+      case UntaggedFunction::kNoSuchMethodDispatcher:
+      case UntaggedFunction::kInvokeFieldDispatcher:
+      case UntaggedFunction::kDynamicInvocationForwarder:
         return true;
       default:
         return false;
@@ -3326,53 +3282,53 @@
 
   // Returns true if this function represents an explicit getter function.
   bool IsGetterFunction() const {
-    return kind() == FunctionLayout::kGetterFunction;
+    return kind() == UntaggedFunction::kGetterFunction;
   }
 
   // Returns true if this function represents an implicit getter function.
   bool IsImplicitGetterFunction() const {
-    return kind() == FunctionLayout::kImplicitGetter;
+    return kind() == UntaggedFunction::kImplicitGetter;
   }
 
   // Returns true if this function represents an implicit static getter
   // function.
   bool IsImplicitStaticGetterFunction() const {
-    return kind() == FunctionLayout::kImplicitStaticGetter;
+    return kind() == UntaggedFunction::kImplicitStaticGetter;
   }
 
   // Returns true if this function represents an explicit setter function.
   bool IsSetterFunction() const {
-    return kind() == FunctionLayout::kSetterFunction;
+    return kind() == UntaggedFunction::kSetterFunction;
   }
 
   // Returns true if this function represents an implicit setter function.
   bool IsImplicitSetterFunction() const {
-    return kind() == FunctionLayout::kImplicitSetter;
+    return kind() == UntaggedFunction::kImplicitSetter;
   }
 
   // Returns true if this function represents an initializer for a static or
   // instance field. The function returns the initial value and the caller is
   // responsible for setting the field.
   bool IsFieldInitializer() const {
-    return kind() == FunctionLayout::kFieldInitializer;
+    return kind() == UntaggedFunction::kFieldInitializer;
   }
 
   // Returns true if this function represents a (possibly implicit) closure
   // function.
   bool IsClosureFunction() const {
-    FunctionLayout::Kind k = kind();
-    return (k == FunctionLayout::kClosureFunction) ||
-           (k == FunctionLayout::kImplicitClosureFunction);
+    UntaggedFunction::Kind k = kind();
+    return (k == UntaggedFunction::kClosureFunction) ||
+           (k == UntaggedFunction::kImplicitClosureFunction);
   }
 
   // Returns true if this function represents a generated irregexp function.
   bool IsIrregexpFunction() const {
-    return kind() == FunctionLayout::kIrregexpFunction;
+    return kind() == UntaggedFunction::kIrregexpFunction;
   }
 
   // Returns true if this function represents an implicit closure function.
   bool IsImplicitClosureFunction() const {
-    return kind() == FunctionLayout::kImplicitClosureFunction;
+    return kind() == UntaggedFunction::kImplicitClosureFunction;
   }
 
   // Returns true if this function represents a non implicit closure function.
@@ -3396,24 +3352,14 @@
   // Returns true if this function represents a local function.
   bool IsLocalFunction() const { return parent_function() != Function::null(); }
 
-  // Returns true if this function represents a signature function without code.
-  bool IsSignatureFunction() const {
-    return kind() == FunctionLayout::kSignatureFunction;
-  }
-  static bool IsSignatureFunction(FunctionPtr function) {
-    NoSafepointScope no_safepoint;
-    return KindBits::decode(function->ptr()->kind_tag_) ==
-           FunctionLayout::kSignatureFunction;
-  }
-
   // Returns true if this function represents an ffi trampoline.
   bool IsFfiTrampoline() const {
-    return kind() == FunctionLayout::kFfiTrampoline;
+    return kind() == UntaggedFunction::kFfiTrampoline;
   }
   static bool IsFfiTrampoline(FunctionPtr function) {
     NoSafepointScope no_safepoint;
-    return KindBits::decode(function->ptr()->kind_tag_) ==
-           FunctionLayout::kFfiTrampoline;
+    return KindBits::decode(function->untag()->kind_tag_) ==
+           UntaggedFunction::kFfiTrampoline;
   }
 
   bool IsFfiLoad() const {
@@ -3447,7 +3393,9 @@
   //   user_func async {
   //     // ...
   //   }
-  bool IsAsyncFunction() const { return modifier() == FunctionLayout::kAsync; }
+  bool IsAsyncFunction() const {
+    return modifier() == UntaggedFunction::kAsync;
+  }
 
   // Recognise synthetic sync-yielding functions like the inner-most:
   //   user_func /* was async */ {
@@ -3465,7 +3413,7 @@
   //     // ...
   //   }
   bool IsSyncGenerator() const {
-    return modifier() == FunctionLayout::kSyncGen;
+    return modifier() == UntaggedFunction::kSyncGen;
   }
 
   // Recognise synthetic :sync_op_gen()s like:
@@ -3484,7 +3432,7 @@
   //     // ...
   //   }
   bool IsAsyncGenerator() const {
-    return modifier() == FunctionLayout::kAsyncGen;
+    return modifier() == UntaggedFunction::kAsyncGen;
   }
 
   // Recognise synthetic sync-yielding functions like the inner-most:
@@ -3499,7 +3447,7 @@
   }
 
   bool IsAsyncOrGenerator() const {
-    return modifier() != FunctionLayout::kNoModifier;
+    return modifier() != UntaggedFunction::kNoModifier;
   }
 
   // Recognise synthetic sync-yielding functions like the inner-most:
@@ -3516,7 +3464,7 @@
   }
 
   bool IsTypedDataViewFactory() const {
-    if (is_native() && kind() == FunctionLayout::kConstructor) {
+    if (is_native() && kind() == UntaggedFunction::kConstructor) {
       // This is a native factory constructor.
       const Class& klass = Class::Handle(Owner());
       return IsTypedDataViewClassId(klass.id());
@@ -3531,11 +3479,12 @@
   ErrorPtr VerifyClosurizedEntryPoint() const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(FunctionLayout));
+    return RoundedAllocationSize(sizeof(UntaggedFunction));
   }
 
-  static FunctionPtr New(const String& name,
-                         FunctionLayout::Kind kind,
+  static FunctionPtr New(const FunctionType& signature,
+                         const String& name,
+                         UntaggedFunction::Kind kind,
                          bool is_static,
                          bool is_const,
                          bool is_abstract,
@@ -3547,7 +3496,7 @@
 
   // Allocates a new Function object representing a closure function
   // with given kind - kClosureFunction or kImplicitClosureFunction.
-  static FunctionPtr NewClosureFunctionWithKind(FunctionLayout::Kind kind,
+  static FunctionPtr NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
                                                 const String& name,
                                                 const Function& parent,
                                                 TokenPosition token_pos,
@@ -3563,18 +3512,6 @@
                                                 const Function& parent,
                                                 TokenPosition token_pos);
 
-  // Allocates a new Function object representing a signature function.
-  // The owner is the scope class of the function type.
-  // The parent is the enclosing function or null if none.
-  static FunctionPtr NewSignatureFunction(const Object& owner,
-                                          const Function& parent,
-                                          TokenPosition token_pos,
-                                          Heap::Space space = Heap::kOld);
-
-  static FunctionPtr NewEvalFunction(const Class& owner,
-                                     const Script& script,
-                                     bool is_static);
-
   FunctionPtr CreateMethodExtractor(const String& getter_name) const;
   FunctionPtr GetMethodExtractor(const String& getter_name) const;
 
@@ -3616,7 +3553,7 @@
   // Sets deopt reason in all ICData-s with given deopt_id.
   void SetDeoptReasonForAll(intptr_t deopt_id, ICData::DeoptReasonId reason);
 
-  void set_modifier(FunctionLayout::AsyncModifier value) const;
+  void set_modifier(UntaggedFunction::AsyncModifier value) const;
 
 // 'WasCompiled' is true if the function was compiled once in this
 // VM instantiation. It is independent from presence of type feedback
@@ -3661,10 +3598,10 @@
 
   void SetWasExecuted(bool value) const { SetWasExecutedBit(value); }
 
-  static intptr_t data_offset() { return OFFSET_OF(FunctionLayout, data_); }
+  static intptr_t data_offset() { return OFFSET_OF(UntaggedFunction, data_); }
 
   static intptr_t kind_tag_offset() {
-    return OFFSET_OF(FunctionLayout, kind_tag_);
+    return OFFSET_OF(UntaggedFunction, kind_tag_);
   }
 
   // static: Considered during class-side or top-level resolution rather than
@@ -3710,9 +3647,9 @@
 
 #define DEFINE_ACCESSORS(name, accessor_name)                                  \
   void set_##accessor_name(bool value) const {                                 \
-    set_kind_tag(name##Bit::update(value, raw_ptr()->kind_tag_));              \
+    set_kind_tag(name##Bit::update(value, untag()->kind_tag_));                \
   }                                                                            \
-  bool accessor_name() const { return name##Bit::decode(raw_ptr()->kind_tag_); }
+  bool accessor_name() const { return name##Bit::decode(untag()->kind_tag_); }
   FOR_EACH_FUNCTION_KIND_BIT(DEFINE_ACCESSORS)
 #undef DEFINE_ACCESSORS
 
@@ -3720,23 +3657,23 @@
   //              some functions known to be execute infrequently and functions
   //              which have been de-optimized too many times.
   bool is_optimizable() const {
-    return FunctionLayout::OptimizableBit::decode(raw_ptr()->packed_fields_);
+    return UntaggedFunction::PackedOptimizable::decode(untag()->packed_fields_);
   }
   void set_is_optimizable(bool value) const {
-    set_packed_fields(FunctionLayout::OptimizableBit::update(
-        value, raw_ptr()->packed_fields_));
+    set_packed_fields(UntaggedFunction::PackedOptimizable::update(
+        value, untag()->packed_fields_));
   }
 
   // Indicates whether this function can be optimized on the background compiler
   // thread.
   bool is_background_optimizable() const {
-    return FunctionLayout::BackgroundOptimizableBit::decode(
-        raw_ptr()->packed_fields_);
+    return UntaggedFunction::PackedBackgroundOptimizable::decode(
+        untag()->packed_fields_);
   }
 
   void set_is_background_optimizable(bool value) const {
-    set_packed_fields(FunctionLayout::BackgroundOptimizableBit::update(
-        value, raw_ptr()->packed_fields_));
+    set_packed_fields(UntaggedFunction::PackedBackgroundOptimizable::update(
+        value, untag()->packed_fields_));
   }
 
   enum KindTagBits {
@@ -3757,10 +3694,11 @@
   COMPILE_ASSERT(MethodRecognizer::kNumRecognizedMethods <
                  (1 << kRecognizedTagSize));
   COMPILE_ASSERT(kNumTagBits <=
-                 (kBitsPerByte * sizeof(decltype(FunctionLayout::kind_tag_))));
+                 (kBitsPerByte *
+                  sizeof(decltype(UntaggedFunction::kind_tag_))));
 
   class KindBits : public BitField<uint32_t,
-                                   FunctionLayout::Kind,
+                                   UntaggedFunction::Kind,
                                    kKindTagPos,
                                    kKindTagSize> {};
 
@@ -3769,7 +3707,7 @@
                                          kRecognizedTagPos,
                                          kRecognizedTagSize> {};
   class ModifierBits : public BitField<uint32_t,
-                                       FunctionLayout::AsyncModifier,
+                                       UntaggedFunction::AsyncModifier,
                                        kModifierPos,
                                        kModifierSize> {};
 
@@ -3785,10 +3723,10 @@
       const TypeArguments& defaults) const;
 
   void set_parameter_names(const Array& value) const;
+  void set_parameter_types(const Array& value) const;
   void set_ic_data_array(const Array& value) const;
-  void SetInstructionsSafe(const Code& value) const;
   void set_name(const String& value) const;
-  void set_kind(FunctionLayout::Kind value) const;
+  void set_kind(UntaggedFunction::Kind value) const;
   void set_parent_function(const Function& value) const;
   FunctionPtr implicit_closure_function() const;
   void set_implicit_closure_function(const Function& value) const;
@@ -3799,68 +3737,49 @@
   void set_num_optional_parameters(intptr_t value) const;  // Encoded value.
   void set_kind_tag(uint32_t value) const;
   void set_data(const Object& value) const;
+
   static FunctionPtr New(Heap::Space space = Heap::kOld);
 
-  void PrintSignatureParameters(Thread* thread,
-                                Zone* zone,
-                                NameVisibility name_visibility,
-                                BaseTextBuffer* printer) const;
-
-  // Returns true if the type of the formal parameter at the given position in
-  // this function is contravariant with the type of the other formal parameter
-  // at the given position in the other function.
-  bool IsContravariantParameter(intptr_t parameter_position,
-                                const Function& other,
-                                intptr_t other_parameter_position,
-                                Heap::Space space) const;
-
-  // Returns the index in the parameter names array of the corresponding flag
-  // for the given parametere index. Also returns (via flag_mask) the
-  // corresponding mask within the flag.
-  intptr_t GetRequiredFlagIndex(intptr_t index, intptr_t* flag_mask) const;
-
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
   friend class Class;
   friend class SnapshotWriter;
   friend class Parser;  // For set_eval_script.
-  friend class ProgramVisitor;  // For set_parameter_names.
-  // FunctionLayout::VisitFunctionPointers accesses the private constructor of
+  // UntaggedFunction::VisitFunctionPointers accesses the private constructor of
   // Function.
-  friend class FunctionLayout;
+  friend class UntaggedFunction;
   friend class ClassFinalizer;  // To reset parent_function.
   friend class Type;            // To adjust parent_function.
+  friend class ProgramVisitor;  // For set_parameter_types/names.
 };
 
 class ClosureData : public Object {
  public:
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ClosureDataLayout));
+    return RoundedAllocationSize(sizeof(UntaggedClosureData));
   }
 
   static intptr_t default_type_arguments_offset() {
-    return OFFSET_OF(ClosureDataLayout, default_type_arguments_);
+    return OFFSET_OF(UntaggedClosureData, default_type_arguments_);
   }
   static intptr_t default_type_arguments_info_offset() {
-    return OFFSET_OF(ClosureDataLayout, default_type_arguments_info_);
+    return OFFSET_OF(UntaggedClosureData, default_type_arguments_info_);
   }
 
  private:
-  ContextScopePtr context_scope() const { return raw_ptr()->context_scope_; }
+  ContextScopePtr context_scope() const { return untag()->context_scope_; }
   void set_context_scope(const ContextScope& value) const;
 
   // Enclosing function of this local function.
-  FunctionPtr parent_function() const { return raw_ptr()->parent_function_; }
+  FunctionPtr parent_function() const { return untag()->parent_function_; }
   void set_parent_function(const Function& value) const;
 
-  // Signature type of this closure function.
-  TypePtr signature_type() const { return raw_ptr()->signature_type_; }
-  void set_signature_type(const Type& value) const;
-
-  InstancePtr implicit_static_closure() const { return raw_ptr()->closure_; }
+  InstancePtr implicit_static_closure() const {
+    return untag()->closure<std::memory_order_acquire>();
+  }
   void set_implicit_static_closure(const Instance& closure) const;
 
   TypeArgumentsPtr default_type_arguments() const {
-    return raw_ptr()->default_type_arguments_;
+    return untag()->default_type_arguments_;
   }
   void set_default_type_arguments(const TypeArguments& value) const;
 
@@ -3875,29 +3794,6 @@
   friend class HeapProfiler;
 };
 
-class SignatureData : public Object {
- public:
-  static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(SignatureDataLayout));
-  }
-
- private:
-  // Enclosing function of this signature function.
-  FunctionPtr parent_function() const { return raw_ptr()->parent_function(); }
-  void set_parent_function(const Function& value) const;
-
-  // Signature type of this signature function.
-  TypePtr signature_type() const { return raw_ptr()->signature_type(); }
-  void set_signature_type(const Type& value) const;
-
-  static SignatureDataPtr New(Heap::Space space = Heap::kOld);
-
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(SignatureData, Object);
-  friend class Class;
-  friend class Function;
-  friend class HeapProfiler;
-};
-
 enum class EntryPointPragma {
   kAlways,
   kNever,
@@ -3909,26 +3805,22 @@
 class FfiTrampolineData : public Object {
  public:
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(FfiTrampolineDataLayout));
+    return RoundedAllocationSize(sizeof(UntaggedFfiTrampolineData));
   }
 
  private:
-  // Signature type of this closure function.
-  TypePtr signature_type() const { return raw_ptr()->signature_type(); }
-  void set_signature_type(const Type& value) const;
+  FunctionTypePtr c_signature() const { return untag()->c_signature(); }
+  void set_c_signature(const FunctionType& value) const;
 
-  FunctionPtr c_signature() const { return raw_ptr()->c_signature(); }
-  void set_c_signature(const Function& value) const;
-
-  FunctionPtr callback_target() const { return raw_ptr()->callback_target(); }
+  FunctionPtr callback_target() const { return untag()->callback_target(); }
   void set_callback_target(const Function& value) const;
 
   InstancePtr callback_exceptional_return() const {
-    return raw_ptr()->callback_exceptional_return();
+    return untag()->callback_exceptional_return();
   }
   void set_callback_exceptional_return(const Instance& value) const;
 
-  int32_t callback_id() const { return raw_ptr()->callback_id_; }
+  int32_t callback_id() const { return untag()->callback_id_; }
   void set_callback_id(int32_t value) const;
 
   static FfiTrampolineDataPtr New();
@@ -3955,87 +3847,94 @@
       return true;
     }
     NoSafepointScope no_safepoint;
-    return !raw_ptr()->owner()->IsField();
+    return !untag()->owner()->IsField();
   }
 
-  // Returns whether fields must be cloned via [CloneFromOriginal] for the
-  // current compilation thread.
-  static bool ShouldCloneFields();
-
+  // Mark previously unboxed field boxed. Only operates on clones, updates
+  // original as well as this clone.
+  void DisableFieldUnboxing() const;
   // Returns a field cloned from 'this'. 'this' is set as the
   // original field of result.
   FieldPtr CloneFromOriginal() const;
 
-  StringPtr name() const { return raw_ptr()->name(); }
+  StringPtr name() const { return untag()->name(); }
   StringPtr UserVisibleName() const;  // Same as scrubbed name.
   const char* UserVisibleNameCString() const;
   virtual StringPtr DictionaryName() const { return name(); }
 
-  bool is_static() const { return StaticBit::decode(raw_ptr()->kind_bits_); }
+  uint16_t kind_bits() const {
+    return LoadNonPointer<uint16_t, std::memory_order_acquire>(
+        &untag()->kind_bits_);
+  }
+
+  bool is_static() const { return StaticBit::decode(kind_bits()); }
   bool is_instance() const { return !is_static(); }
-  bool is_final() const { return FinalBit::decode(raw_ptr()->kind_bits_); }
-  bool is_const() const { return ConstBit::decode(raw_ptr()->kind_bits_); }
-  bool is_late() const { return IsLateBit::decode(raw_ptr()->kind_bits_); }
+  bool is_final() const { return FinalBit::decode(kind_bits()); }
+  bool is_const() const { return ConstBit::decode(kind_bits()); }
+  bool is_late() const { return IsLateBit::decode(kind_bits()); }
   bool is_extension_member() const {
-    return IsExtensionMemberBit::decode(raw_ptr()->kind_bits_);
+    return IsExtensionMemberBit::decode(kind_bits());
   }
   bool needs_load_guard() const {
-    return NeedsLoadGuardBit::decode(raw_ptr()->kind_bits_);
+    return NeedsLoadGuardBit::decode(kind_bits());
   }
-  bool is_reflectable() const {
-    return ReflectableBit::decode(raw_ptr()->kind_bits_);
-  }
+  bool is_reflectable() const { return ReflectableBit::decode(kind_bits()); }
   void set_is_reflectable(bool value) const {
     ASSERT(IsOriginal());
-    set_kind_bits(ReflectableBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(ReflectableBit::update(value, untag()->kind_bits_));
   }
   bool is_double_initialized() const {
-    return DoubleInitializedBit::decode(raw_ptr()->kind_bits_);
+    return DoubleInitializedBit::decode(kind_bits());
   }
   // Called in parser after allocating field, immutable property otherwise.
   // Marks fields that are initialized with a simple double constant.
-  void set_is_double_initialized(bool value) const {
-    ASSERT(Thread::Current()->IsMutatorThread());
+  void set_is_double_initialized_unsafe(bool value) const {
     ASSERT(IsOriginal());
-    set_kind_bits(DoubleInitializedBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(DoubleInitializedBit::update(value, untag()->kind_bits_));
+  }
+
+  void set_is_double_initialized(bool value) const {
+    DEBUG_ASSERT(
+        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+    set_is_double_initialized_unsafe(value);
   }
 
   bool initializer_changed_after_initialization() const {
-    return InitializerChangedAfterInitializatonBit::decode(
-        raw_ptr()->kind_bits_);
+    return InitializerChangedAfterInitializatonBit::decode(kind_bits());
   }
   void set_initializer_changed_after_initialization(bool value) const {
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
     set_kind_bits(InitializerChangedAfterInitializatonBit::update(
-        value, raw_ptr()->kind_bits_));
+        value, untag()->kind_bits_));
   }
 
-  bool has_pragma() const {
-    return HasPragmaBit::decode(raw_ptr()->kind_bits_);
-  }
+  bool has_pragma() const { return HasPragmaBit::decode(kind_bits()); }
   void set_has_pragma(bool value) const {
-    set_kind_bits(HasPragmaBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(HasPragmaBit::update(value, untag()->kind_bits_));
   }
 
-  bool is_covariant() const {
-    return CovariantBit::decode(raw_ptr()->kind_bits_);
-  }
+  bool is_covariant() const { return CovariantBit::decode(kind_bits()); }
   void set_is_covariant(bool value) const {
-    set_kind_bits(CovariantBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(CovariantBit::update(value, untag()->kind_bits_));
   }
 
   bool is_generic_covariant_impl() const {
-    return GenericCovariantImplBit::decode(raw_ptr()->kind_bits_);
+    return GenericCovariantImplBit::decode(kind_bits());
   }
   void set_is_generic_covariant_impl(bool value) const {
-    set_kind_bits(
-        GenericCovariantImplBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(GenericCovariantImplBit::update(value, untag()->kind_bits_));
   }
 
   intptr_t kernel_offset() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     return 0;
 #else
-    return raw_ptr()->kernel_offset_;
+    return untag()->kernel_offset_;
 #endif
   }
 
@@ -4044,7 +3943,7 @@
     UNREACHABLE();
 #else
     ASSERT(value >= 0);
-    StoreNonPointer(&raw_ptr()->kernel_offset_, value);
+    StoreNonPointer(&untag()->kernel_offset_, value);
 #endif
   }
 
@@ -4060,33 +3959,38 @@
 
   inline intptr_t HostOffset() const;
   static intptr_t host_offset_or_field_id_offset() {
-    return OFFSET_OF(FieldLayout, host_offset_or_field_id_);
+    return OFFSET_OF(UntaggedField, host_offset_or_field_id_);
   }
 
   inline intptr_t TargetOffset() const;
   static inline intptr_t TargetOffsetOf(FieldPtr field);
 
+  ObjectPtr StaticConstFieldValue() const;
+  void SetStaticConstFieldValue(const Instance& value,
+                                bool assert_initializing_store = true) const;
+
   inline InstancePtr StaticValue() const;
-  void SetStaticValue(const Instance& value,
-                      bool save_initial_value = false) const;
+  void SetStaticValue(const Instance& value) const;
 
   inline intptr_t field_id() const;
   inline void set_field_id(intptr_t field_id) const;
+  inline void set_field_id_unsafe(intptr_t field_id) const;
 
   ClassPtr Owner() const;
   ClassPtr Origin() const;  // Either mixin class, or same as owner().
   ScriptPtr Script() const;
   ObjectPtr RawOwner() const;
 
-  AbstractTypePtr type() const { return raw_ptr()->type(); }
+  AbstractTypePtr type() const { return untag()->type(); }
   // Used by class finalizer, otherwise initialized in constructor.
   void SetFieldType(const AbstractType& value) const;
+  void SetFieldTypeSafe(const AbstractType& value) const;
 
   DART_WARN_UNUSED_RESULT
   ErrorPtr VerifyEntryPoint(EntryPointPragma kind) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(FieldLayout));
+    return RoundedAllocationSize(sizeof(UntaggedField));
   }
 
   static FieldPtr New(const String& name,
@@ -4113,36 +4017,47 @@
   FieldPtr Clone(const Field& original) const;
 
   static intptr_t kind_bits_offset() {
-    return OFFSET_OF(FieldLayout, kind_bits_);
+    return OFFSET_OF(UntaggedField, kind_bits_);
   }
 
-  TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
-  TokenPosition end_token_pos() const { return raw_ptr()->end_token_pos_; }
+  TokenPosition token_pos() const { return untag()->token_pos_; }
+  TokenPosition end_token_pos() const { return untag()->end_token_pos_; }
 
   int32_t SourceFingerprint() const;
 
   StringPtr InitializingExpression() const;
 
   bool has_nontrivial_initializer() const {
-    return HasNontrivialInitializerBit::decode(raw_ptr()->kind_bits_);
+    return HasNontrivialInitializerBit::decode(kind_bits());
   }
   // Called by parser after allocating field.
-  void set_has_nontrivial_initializer(bool has_nontrivial_initializer) const {
+  void set_has_nontrivial_initializer_unsafe(
+      bool has_nontrivial_initializer) const {
     ASSERT(IsOriginal());
-    ASSERT(Thread::Current()->IsMutatorThread());
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
     set_kind_bits(HasNontrivialInitializerBit::update(
-        has_nontrivial_initializer, raw_ptr()->kind_bits_));
+        has_nontrivial_initializer, untag()->kind_bits_));
+  }
+  void set_has_nontrivial_initializer(bool has_nontrivial_initializer) const {
+    DEBUG_ASSERT(
+        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+    set_has_nontrivial_initializer_unsafe(has_nontrivial_initializer);
   }
 
   bool has_initializer() const {
-    return HasInitializerBit::decode(raw_ptr()->kind_bits_);
+    return HasInitializerBit::decode(kind_bits());
   }
   // Called by parser after allocating field.
-  void set_has_initializer(bool has_initializer) const {
+  void set_has_initializer_unsafe(bool has_initializer) const {
     ASSERT(IsOriginal());
-    ASSERT(Thread::Current()->IsMutatorThread());
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
     set_kind_bits(
-        HasInitializerBit::update(has_initializer, raw_ptr()->kind_bits_));
+        HasInitializerBit::update(has_initializer, untag()->kind_bits_));
+  }
+  void set_has_initializer(bool has_initializer) const {
+    DEBUG_ASSERT(
+        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+    set_has_initializer_unsafe(has_initializer);
   }
 
   bool has_trivial_initializer() const {
@@ -4150,43 +4065,33 @@
   }
 
   bool is_non_nullable_integer() const {
-    return IsNonNullableIntBit::decode(raw_ptr()->kind_bits_);
+    return IsNonNullableIntBit::decode(kind_bits());
   }
 
   void set_is_non_nullable_integer(bool is_non_nullable_integer) const {
     ASSERT(Thread::Current()->IsMutatorThread());
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
     set_kind_bits(IsNonNullableIntBit::update(is_non_nullable_integer,
-                                              raw_ptr()->kind_bits_));
+                                              untag()->kind_bits_));
   }
 
   StaticTypeExactnessState static_type_exactness_state() const {
     return StaticTypeExactnessState::Decode(
-        raw_ptr()->static_type_exactness_state_);
+        untag()->static_type_exactness_state_);
   }
 
   void set_static_type_exactness_state(StaticTypeExactnessState state) const {
-    StoreNonPointer(&raw_ptr()->static_type_exactness_state_, state.Encode());
+    StoreNonPointer(&untag()->static_type_exactness_state_, state.Encode());
   }
 
   static intptr_t static_type_exactness_state_offset() {
-    return OFFSET_OF(FieldLayout, static_type_exactness_state_);
+    return OFFSET_OF(UntaggedField, static_type_exactness_state_);
   }
 
   // Return class id that any non-null value read from this field is guaranteed
   // to have or kDynamicCid if such class id is not known.
   // Stores to this field must update this information hence the name.
-  intptr_t guarded_cid() const {
-#if defined(DEBUG)
-    // This assertion ensures that the cid seen by the background compiler is
-    // consistent. So the assertion passes if the field is a clone. It also
-    // passes if the field is static, because we don't use field guards on
-    // static fields.
-    Thread* thread = Thread::Current();
-    ASSERT(!IsOriginal() || is_static() || thread->IsMutatorThread() ||
-           thread->IsAtSafepoint());
-#endif
-    return raw_ptr()->guarded_cid_;
-  }
+  intptr_t guarded_cid() const;
 
   void set_guarded_cid(intptr_t cid) const {
     DEBUG_ASSERT(
@@ -4194,15 +4099,10 @@
     set_guarded_cid_unsafe(cid);
   }
   void set_guarded_cid_unsafe(intptr_t cid) const {
-#if defined(DEBUG)
-    Thread* thread = Thread::Current();
-    ASSERT(!IsOriginal() || is_static() || thread->IsMutatorThread() ||
-           thread->IsAtSafepoint());
-#endif
-    StoreNonPointer(&raw_ptr()->guarded_cid_, cid);
+    StoreNonPointer(&untag()->guarded_cid_, cid);
   }
   static intptr_t guarded_cid_offset() {
-    return OFFSET_OF(FieldLayout, guarded_cid_);
+    return OFFSET_OF(UntaggedField, guarded_cid_);
   }
   // Return the list length that any list stored in this field is guaranteed
   // to have. If length is kUnknownFixedLength the length has not
@@ -4216,7 +4116,7 @@
     set_guarded_list_length_unsafe(list_length);
   }
   static intptr_t guarded_list_length_offset() {
-    return OFFSET_OF(FieldLayout, guarded_list_length_);
+    return OFFSET_OF(UntaggedField, guarded_list_length_);
   }
   intptr_t guarded_list_length_in_object_offset() const;
   void set_guarded_list_length_in_object_offset_unsafe(intptr_t offset) const;
@@ -4226,7 +4126,7 @@
     set_guarded_list_length_in_object_offset_unsafe(offset);
   }
   static intptr_t guarded_list_length_in_object_offset_offset() {
-    return OFFSET_OF(FieldLayout, guarded_list_length_in_object_offset_);
+    return OFFSET_OF(UntaggedField, guarded_list_length_in_object_offset_);
   }
 
   bool needs_length_check() const {
@@ -4247,13 +4147,19 @@
   intptr_t UnboxedFieldCid() const { return guarded_cid(); }
 
   bool is_unboxing_candidate() const {
-    return UnboxingCandidateBit::decode(raw_ptr()->kind_bits_);
+    return UnboxingCandidateBit::decode(kind_bits());
   }
+
   // Default 'true', set to false once optimizing compiler determines it should
   // be boxed.
+  void set_is_unboxing_candidate_unsafe(bool b) const {
+    set_kind_bits(UnboxingCandidateBit::update(b, untag()->kind_bits_));
+  }
+
   void set_is_unboxing_candidate(bool b) const {
-    ASSERT(IsOriginal());
-    set_kind_bits(UnboxingCandidateBit::update(b, raw_ptr()->kind_bits_));
+    DEBUG_ASSERT(
+        IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+    set_is_unboxing_candidate_unsafe(b);
   }
 
   enum {
@@ -4262,42 +4168,33 @@
     kNoFixedLength = -2,
   };
   void set_is_late(bool value) const {
-    set_kind_bits(IsLateBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(IsLateBit::update(value, untag()->kind_bits_));
   }
   void set_is_extension_member(bool value) const {
-    set_kind_bits(IsExtensionMemberBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(IsExtensionMemberBit::update(value, untag()->kind_bits_));
   }
   void set_needs_load_guard(bool value) const {
-    set_kind_bits(NeedsLoadGuardBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(NeedsLoadGuardBit::update(value, untag()->kind_bits_));
   }
   // Returns false if any value read from this field is guaranteed to be
   // not null.
   // Internally we is_nullable_ field contains either kNullCid (nullable) or
   // kInvalidCid (non-nullable) instead of boolean. This is done to simplify
   // guarding sequence in the generated code.
-  bool is_nullable(bool silence_assert = false) const {
-#if defined(DEBUG)
-    if (!silence_assert) {
-      // Same assert as guarded_cid(), because is_nullable() also needs to be
-      // consistent for the background compiler.
-      Thread* thread = Thread::Current();
-      ASSERT(!IsOriginal() || is_static() || thread->IsMutatorThread() ||
-             thread->IsAtSafepoint());
-    }
-#endif
-    return raw_ptr()->is_nullable_ == kNullCid;
-  }
+  bool is_nullable(bool silence_assert = false) const;
   void set_is_nullable(bool val) const {
     DEBUG_ASSERT(
         IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
     set_is_nullable_unsafe(val);
   }
   void set_is_nullable_unsafe(bool val) const {
-    ASSERT(Thread::Current()->IsMutatorThread());
-    StoreNonPointer(&raw_ptr()->is_nullable_, val ? kNullCid : kIllegalCid);
+    StoreNonPointer(&untag()->is_nullable_, val ? kNullCid : kIllegalCid);
   }
   static intptr_t is_nullable_offset() {
-    return OFFSET_OF(FieldLayout, is_nullable_);
+    return OFFSET_OF(UntaggedField, is_nullable_);
   }
 
   // Record store of the given value into this field. May trigger
@@ -4335,14 +4232,12 @@
 
   FunctionPtr EnsureInitializerFunction() const;
   FunctionPtr InitializerFunction() const {
-    // We rely on the fact that any loads from the initializer function
-    // are dependent loads and avoid the load-acquire barrier here.
-    return raw_ptr()->initializer_function<std::memory_order_relaxed>();
+    return untag()->initializer_function<std::memory_order_acquire>();
   }
   void SetInitializerFunction(const Function& initializer) const;
   bool HasInitializerFunction() const;
   static intptr_t initializer_function_offset() {
-    return OFFSET_OF(FieldLayout, initializer_function_);
+    return OFFSET_OF(UntaggedField, initializer_function_);
   }
 
   // For static fields only. Constructs a closure that gets/sets the
@@ -4369,7 +4264,7 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   SubtypeTestCachePtr type_test_cache() const {
-    return raw_ptr()->type_test_cache();
+    return untag()->type_test_cache();
   }
   void set_type_test_cache(const SubtypeTestCache& cache) const;
 #endif
@@ -4452,25 +4347,27 @@
 
   void set_name(const String& value) const;
   void set_is_static(bool is_static) const {
-    set_kind_bits(StaticBit::update(is_static, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(StaticBit::update(is_static, untag()->kind_bits_));
   }
   void set_is_final(bool is_final) const {
-    set_kind_bits(FinalBit::update(is_final, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(FinalBit::update(is_final, untag()->kind_bits_));
   }
   void set_is_const(bool value) const {
-    set_kind_bits(ConstBit::update(value, raw_ptr()->kind_bits_));
+    // TODO(36097): Once concurrent access is possible ensure updates are safe.
+    set_kind_bits(ConstBit::update(value, untag()->kind_bits_));
   }
-  void set_owner(const Object& value) const {
-    raw_ptr()->set_owner(value.raw());
-  }
+  void set_owner(const Object& value) const { untag()->set_owner(value.ptr()); }
   void set_token_pos(TokenPosition token_pos) const {
-    StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
+    StoreNonPointer(&untag()->token_pos_, token_pos);
   }
   void set_end_token_pos(TokenPosition token_pos) const {
-    StoreNonPointer(&raw_ptr()->end_token_pos_, token_pos);
+    StoreNonPointer(&untag()->end_token_pos_, token_pos);
   }
   void set_kind_bits(uint16_t value) const {
-    StoreNonPointer(&raw_ptr()->kind_bits_, value);
+    StoreNonPointer<uint16_t, uint16_t, std::memory_order_release>(
+        &untag()->kind_bits_, value);
   }
 
   static FieldPtr New();
@@ -4478,18 +4375,18 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Field, Object);
   friend class Class;
   friend class HeapProfiler;
-  friend class FieldLayout;
+  friend class UntaggedField;
   friend class FieldSerializationCluster;
   friend class FieldDeserializationCluster;
 };
 
 class Script : public Object {
  public:
-  StringPtr url() const { return raw_ptr()->url(); }
+  StringPtr url() const { return untag()->url(); }
   void set_url(const String& value) const;
 
   // The actual url which was loaded from disk, if provided by the embedder.
-  StringPtr resolved_url() const { return raw_ptr()->resolved_url(); }
+  StringPtr resolved_url() const { return untag()->resolved_url(); }
   bool HasSource() const;
   StringPtr Source() const;
   bool IsPartOfDartColonLibrary() const;
@@ -4497,25 +4394,26 @@
   void LookupSourceAndLineStarts(Zone* zone) const;
   GrowableObjectArrayPtr GenerateLineNumberArray() const;
 
-  intptr_t line_offset() const { return raw_ptr()->line_offset_; }
-  intptr_t col_offset() const { return raw_ptr()->col_offset_; }
+  intptr_t line_offset() const { return untag()->line_offset_; }
+  intptr_t col_offset() const { return untag()->col_offset_; }
+  // Returns the max real token position for this script, or kNoSource
+  // if there is no line starts information.
+  TokenPosition MaxPosition() const;
 
   // The load time in milliseconds since epoch.
-  int64_t load_timestamp() const { return raw_ptr()->load_timestamp_; }
+  int64_t load_timestamp() const { return untag()->load_timestamp_; }
 
   ArrayPtr compile_time_constants() const {
-    return raw_ptr()->compile_time_constants();
+    return untag()->compile_time_constants();
   }
   void set_compile_time_constants(const Array& value) const;
 
   KernelProgramInfoPtr kernel_program_info() const {
-    return raw_ptr()->kernel_program_info();
+    return untag()->kernel_program_info();
   }
   void set_kernel_program_info(const KernelProgramInfo& info) const;
 
-  intptr_t kernel_script_index() const {
-    return raw_ptr()->kernel_script_index_;
-  }
+  intptr_t kernel_script_index() const { return untag()->kernel_script_index_; }
   void set_kernel_script_index(const intptr_t kernel_script_index) const;
 
   TypedDataPtr kernel_string_offsets() const;
@@ -4541,24 +4439,30 @@
 
   void SetLocationOffset(intptr_t line_offset, intptr_t col_offset) const;
 
-  bool GetTokenLocationUsingLineStarts(TokenPosition token_pos,
-                                       intptr_t* line,
-                                       intptr_t* column) const;
-  void GetTokenLocation(TokenPosition token_pos,
-                        intptr_t* line,
-                        intptr_t* column,
-                        intptr_t* token_len = NULL) const;
+  // For real token positions when line starts are available, returns whether or
+  // not a GetTokenLocation call would succeed. Returns true for non-real token
+  // positions or if there is no line starts information.
+  bool IsValidTokenPosition(TokenPosition token_pos) const;
 
-  // Returns index of first and last token on the given line. Returns both
-  // indices < 0 if no token exists on or after the line. If a token exists
-  // after, but not on given line, returns in *first_token_index the index of
-  // the first token after the line, and a negative value in *last_token_index.
-  void TokenRangeAtLine(intptr_t line_number,
+  // Returns whether a line and column could be computed for the given token
+  // position and, if so, sets *line and *column (if not nullptr).
+  bool GetTokenLocation(const TokenPosition& token_pos,
+                        intptr_t* line,
+                        intptr_t* column = nullptr) const;
+
+  // Returns the length of the token at the given position. If the length cannot
+  // be determined, returns a negative value.
+  intptr_t GetTokenLength(const TokenPosition& token_pos) const;
+
+  // Returns whether any tokens were found for the given line. When found,
+  // *first_token_index and *last_token_index are set to the first and
+  // last token on the line, respectively.
+  bool TokenRangeAtLine(intptr_t line_number,
                         TokenPosition* first_token_index,
                         TokenPosition* last_token_index) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ScriptLayout));
+    return RoundedAllocationSize(sizeof(UntaggedScript));
   }
 
   static ScriptPtr New(const String& url, const String& source);
@@ -4570,15 +4474,20 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
   void LoadSourceFromKernel(const uint8_t* kernel_buffer,
                             intptr_t kernel_buffer_len) const;
+  bool IsLazyLookupSourceAndLineStarts() const;
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-  void SetLazyLookupSourceAndLineStarts(bool value) const;
-  bool IsLazyLookupSourceAndLineStarts() const;
-
  private:
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  bool HasCachedMaxPosition() const;
+
+  void SetLazyLookupSourceAndLineStarts(bool value) const;
+  void SetHasCachedMaxPosition(bool value) const;
+  void SetCachedMaxPosition(intptr_t value) const;
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
   void set_resolved_url(const String& value) const;
   void set_source(const String& value) const;
-  void set_flags(uint8_t value) const;
   void set_load_timestamp(int64_t value) const;
   ArrayPtr debug_positions() const;
 
@@ -4638,32 +4547,32 @@
 
 class Library : public Object {
  public:
-  StringPtr name() const { return raw_ptr()->name(); }
+  StringPtr name() const { return untag()->name(); }
   void SetName(const String& name) const;
 
-  StringPtr url() const { return raw_ptr()->url(); }
-  StringPtr private_key() const { return raw_ptr()->private_key(); }
+  StringPtr url() const { return untag()->url(); }
+  StringPtr private_key() const { return untag()->private_key(); }
   bool LoadNotStarted() const {
-    return raw_ptr()->load_state_ == LibraryLayout::kAllocated;
+    return untag()->load_state_ == UntaggedLibrary::kAllocated;
   }
   bool LoadRequested() const {
-    return raw_ptr()->load_state_ == LibraryLayout::kLoadRequested;
+    return untag()->load_state_ == UntaggedLibrary::kLoadRequested;
   }
   bool LoadInProgress() const {
-    return raw_ptr()->load_state_ == LibraryLayout::kLoadInProgress;
+    return untag()->load_state_ == UntaggedLibrary::kLoadInProgress;
   }
   void SetLoadRequested() const;
   void SetLoadInProgress() const;
   bool Loaded() const {
-    return raw_ptr()->load_state_ == LibraryLayout::kLoaded;
+    return untag()->load_state_ == UntaggedLibrary::kLoaded;
   }
   void SetLoaded() const;
 
-  LoadingUnitPtr loading_unit() const { return raw_ptr()->loading_unit(); }
+  LoadingUnitPtr loading_unit() const { return untag()->loading_unit(); }
   void set_loading_unit(const LoadingUnit& value) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(LibraryLayout));
+    return RoundedAllocationSize(sizeof(UntaggedLibrary));
   }
 
   static LibraryPtr New(const String& url);
@@ -4754,24 +4663,24 @@
                          bool only_core,
                          const Object& object,
                          const String& pragma_name,
-                         Object* options);
+                         Object* options = nullptr);
 
-  ClassPtr toplevel_class() const { return raw_ptr()->toplevel_class(); }
+  ClassPtr toplevel_class() const { return untag()->toplevel_class(); }
   void set_toplevel_class(const Class& value) const;
 
   GrowableObjectArrayPtr used_scripts() const {
-    return raw_ptr()->used_scripts();
+    return untag()->used_scripts();
   }
 
   // Library imports.
-  ArrayPtr imports() const { return raw_ptr()->imports(); }
-  ArrayPtr exports() const { return raw_ptr()->exports(); }
+  ArrayPtr imports() const { return untag()->imports(); }
+  ArrayPtr exports() const { return untag()->exports(); }
   void AddImport(const Namespace& ns) const;
-  intptr_t num_imports() const { return raw_ptr()->num_imports_; }
+  intptr_t num_imports() const { return untag()->num_imports_; }
   NamespacePtr ImportAt(intptr_t index) const;
   LibraryPtr ImportLibraryAt(intptr_t index) const;
 
-  ArrayPtr dependencies() const { return raw_ptr()->dependencies(); }
+  ArrayPtr dependencies() const { return untag()->dependencies(); }
   void set_dependencies(const Array& deps) const;
 
   void DropDependenciesAndCaches() const;
@@ -4779,37 +4688,37 @@
   // Resolving native methods for script loaded in the library.
   Dart_NativeEntryResolver native_entry_resolver() const {
     return LoadNonPointer<Dart_NativeEntryResolver, std::memory_order_relaxed>(
-        &raw_ptr()->native_entry_resolver_);
+        &untag()->native_entry_resolver_);
   }
   void set_native_entry_resolver(Dart_NativeEntryResolver value) const {
     StoreNonPointer<Dart_NativeEntryResolver, Dart_NativeEntryResolver,
-                    std::memory_order_relaxed>(
-        &raw_ptr()->native_entry_resolver_, value);
+                    std::memory_order_relaxed>(&untag()->native_entry_resolver_,
+                                               value);
   }
   Dart_NativeEntrySymbol native_entry_symbol_resolver() const {
     return LoadNonPointer<Dart_NativeEntrySymbol, std::memory_order_relaxed>(
-        &raw_ptr()->native_entry_symbol_resolver_);
+        &untag()->native_entry_symbol_resolver_);
   }
   void set_native_entry_symbol_resolver(
       Dart_NativeEntrySymbol native_symbol_resolver) const {
     StoreNonPointer<Dart_NativeEntrySymbol, Dart_NativeEntrySymbol,
                     std::memory_order_relaxed>(
-        &raw_ptr()->native_entry_symbol_resolver_, native_symbol_resolver);
+        &untag()->native_entry_symbol_resolver_, native_symbol_resolver);
   }
 
   bool is_in_fullsnapshot() const {
-    return LibraryLayout::InFullSnapshotBit::decode(raw_ptr()->flags_);
+    return UntaggedLibrary::InFullSnapshotBit::decode(untag()->flags_);
   }
   void set_is_in_fullsnapshot(bool value) const {
     set_flags(
-        LibraryLayout::InFullSnapshotBit::update(value, raw_ptr()->flags_));
+        UntaggedLibrary::InFullSnapshotBit::update(value, untag()->flags_));
   }
 
   bool is_nnbd() const {
-    return LibraryLayout::NnbdBit::decode(raw_ptr()->flags_);
+    return UntaggedLibrary::NnbdBit::decode(untag()->flags_);
   }
   void set_is_nnbd(bool value) const {
-    set_flags(LibraryLayout::NnbdBit::update(value, raw_ptr()->flags_));
+    set_flags(UntaggedLibrary::NnbdBit::update(value, untag()->flags_));
   }
 
   NNBDMode nnbd_mode() const {
@@ -4818,20 +4727,20 @@
 
   NNBDCompiledMode nnbd_compiled_mode() const {
     return static_cast<NNBDCompiledMode>(
-        LibraryLayout::NnbdCompiledModeBits::decode(raw_ptr()->flags_));
+        UntaggedLibrary::NnbdCompiledModeBits::decode(untag()->flags_));
   }
   void set_nnbd_compiled_mode(NNBDCompiledMode value) const {
-    set_flags(LibraryLayout::NnbdCompiledModeBits::update(
-        static_cast<uint8_t>(value), raw_ptr()->flags_));
+    set_flags(UntaggedLibrary::NnbdCompiledModeBits::update(
+        static_cast<uint8_t>(value), untag()->flags_));
   }
 
   StringPtr PrivateName(const String& name) const;
 
-  intptr_t index() const { return raw_ptr()->index_; }
+  intptr_t index() const { return untag()->index_; }
   void set_index(intptr_t value) const {
     ASSERT((value == -1) ||
            ((value >= 0) && (value < std::numeric_limits<classid_t>::max())));
-    StoreNonPointer(&raw_ptr()->index_, value);
+    StoreNonPointer(&untag()->index_, value);
   }
 
   void Register(Thread* thread) const;
@@ -4839,17 +4748,17 @@
                                 const GrowableObjectArray& libs);
 
   bool IsDebuggable() const {
-    return LibraryLayout::DebuggableBit::decode(raw_ptr()->flags_);
+    return UntaggedLibrary::DebuggableBit::decode(untag()->flags_);
   }
   void set_debuggable(bool value) const {
-    set_flags(LibraryLayout::DebuggableBit::update(value, raw_ptr()->flags_));
+    set_flags(UntaggedLibrary::DebuggableBit::update(value, untag()->flags_));
   }
 
   bool is_dart_scheme() const {
-    return LibraryLayout::DartSchemeBit::decode(raw_ptr()->flags_);
+    return UntaggedLibrary::DartSchemeBit::decode(untag()->flags_);
   }
   void set_is_dart_scheme(bool value) const {
-    set_flags(LibraryLayout::DartSchemeBit::update(value, raw_ptr()->flags_));
+    set_flags(UntaggedLibrary::DartSchemeBit::update(value, untag()->flags_));
   }
 
   // Includes 'dart:async', 'dart:typed_data', etc.
@@ -4857,14 +4766,14 @@
 
   inline intptr_t UrlHash() const;
 
-  ExternalTypedDataPtr kernel_data() const { return raw_ptr()->kernel_data(); }
+  ExternalTypedDataPtr kernel_data() const { return untag()->kernel_data(); }
   void set_kernel_data(const ExternalTypedData& data) const;
 
   intptr_t kernel_offset() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     return 0;
 #else
-    return raw_ptr()->kernel_offset_;
+    return untag()->kernel_offset_;
 #endif
   }
 
@@ -4873,15 +4782,16 @@
     UNREACHABLE();
 #else
     ASSERT(value >= 0);
-    StoreNonPointer(&raw_ptr()->kernel_offset_, value);
+    StoreNonPointer(&untag()->kernel_offset_, value);
 #endif
   }
 
   static LibraryPtr LookupLibrary(Thread* thread, const String& url);
   static LibraryPtr GetLibrary(intptr_t index);
 
-  static void InitCoreLibrary(Isolate* isolate);
-  static void InitNativeWrappersLibrary(Isolate* isolate, bool is_kernel_file);
+  static void InitCoreLibrary(IsolateGroup* isolate_group);
+  static void InitNativeWrappersLibrary(IsolateGroup* isolate_group,
+                                        bool is_kernel_file);
 
   static LibraryPtr AsyncLibrary();
   static LibraryPtr ConvertLibrary();
@@ -4938,7 +4848,7 @@
   static const char kPrivateKeySeparator = '@';
 
   void CheckReload(const Library& replacement,
-                   IsolateReloadContext* context) const;
+                   ProgramReloadContext* context) const;
 
   // Returns a closure of top level function 'name' in the exported namespace
   // of this library. If a top level function 'name' does not exist we look
@@ -4962,17 +4872,17 @@
   void set_num_imports(intptr_t value) const;
   void set_flags(uint8_t flags) const;
   bool HasExports() const;
-  ArrayPtr loaded_scripts() const { return raw_ptr()->loaded_scripts(); }
+  ArrayPtr loaded_scripts() const { return untag()->loaded_scripts(); }
   ArrayPtr metadata() const {
     DEBUG_ASSERT(
         IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
-    return raw_ptr()->metadata();
+    return untag()->metadata();
   }
   void set_metadata(const Array& value) const;
-  ArrayPtr dictionary() const { return raw_ptr()->dictionary(); }
+  ArrayPtr dictionary() const { return untag()->dictionary(); }
   void InitClassDictionary() const;
 
-  ArrayPtr resolved_names() const { return raw_ptr()->resolved_names(); }
+  ArrayPtr resolved_names() const { return untag()->resolved_names(); }
   bool LookupResolvedNamesCache(const String& name, Object* obj) const;
   void AddToResolvedNamesCache(const String& name, const Object& obj) const;
   void InitResolvedNamesCache() const;
@@ -4980,7 +4890,7 @@
   void InvalidateResolvedName(const String& name) const;
   void InvalidateResolvedNamesCache() const;
 
-  ArrayPtr exported_names() const { return raw_ptr()->exported_names(); }
+  ArrayPtr exported_names() const { return untag()->exported_names(); }
   bool LookupExportedNamesCache(const String& name, Object* obj) const;
   void AddToExportedNamesCache(const String& name, const Object& obj) const;
   void InitExportedNamesCache() const;
@@ -5013,13 +4923,13 @@
 // the show/hide combinators.
 class Namespace : public Object {
  public:
-  LibraryPtr target() const { return raw_ptr()->target(); }
-  ArrayPtr show_names() const { return raw_ptr()->show_names(); }
-  ArrayPtr hide_names() const { return raw_ptr()->hide_names(); }
-  LibraryPtr owner() const { return raw_ptr()->owner(); }
+  LibraryPtr target() const { return untag()->target(); }
+  ArrayPtr show_names() const { return untag()->show_names(); }
+  ArrayPtr hide_names() const { return untag()->hide_names(); }
+  LibraryPtr owner() const { return untag()->owner(); }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(NamespaceLayout));
+    return RoundedAllocationSize(sizeof(UntaggedNamespace));
   }
 
   bool HidesName(const String& name) const;
@@ -5054,37 +4964,37 @@
                                   const uint32_t binary_version);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(KernelProgramInfoLayout));
+    return RoundedAllocationSize(sizeof(UntaggedKernelProgramInfo));
   }
 
-  TypedDataPtr string_offsets() const { return raw_ptr()->string_offsets(); }
+  TypedDataPtr string_offsets() const { return untag()->string_offsets(); }
 
-  ExternalTypedDataPtr string_data() const { return raw_ptr()->string_data(); }
+  ExternalTypedDataPtr string_data() const { return untag()->string_data(); }
 
-  TypedDataPtr canonical_names() const { return raw_ptr()->canonical_names(); }
+  TypedDataPtr canonical_names() const { return untag()->canonical_names(); }
 
   ExternalTypedDataPtr metadata_payloads() const {
-    return raw_ptr()->metadata_payloads();
+    return untag()->metadata_payloads();
   }
 
   ExternalTypedDataPtr metadata_mappings() const {
-    return raw_ptr()->metadata_mappings();
+    return untag()->metadata_mappings();
   }
 
   ExternalTypedDataPtr constants_table() const {
-    return raw_ptr()->constants_table();
+    return untag()->constants_table();
   }
 
   void set_constants_table(const ExternalTypedData& value) const;
 
-  ArrayPtr scripts() const { return raw_ptr()->scripts(); }
+  ArrayPtr scripts() const { return untag()->scripts(); }
   void set_scripts(const Array& scripts) const;
 
-  ArrayPtr constants() const { return raw_ptr()->constants(); }
+  ArrayPtr constants() const { return untag()->constants(); }
   void set_constants(const Array& constants) const;
 
   uint32_t kernel_binary_version() const {
-    return raw_ptr()->kernel_binary_version_;
+    return untag()->kernel_binary_version_;
   }
   void set_kernel_binary_version(uint32_t version) const;
 
@@ -5094,26 +5004,26 @@
   //
   // This array will hold the functions which might need their native name set.
   GrowableObjectArrayPtr potential_natives() const {
-    return raw_ptr()->potential_natives();
+    return untag()->potential_natives();
   }
   void set_potential_natives(const GrowableObjectArray& candidates) const;
 
   GrowableObjectArrayPtr potential_pragma_functions() const {
-    return raw_ptr()->potential_pragma_functions();
+    return untag()->potential_pragma_functions();
   }
   void set_potential_pragma_functions(
       const GrowableObjectArray& candidates) const;
 
   ScriptPtr ScriptAt(intptr_t index) const;
 
-  ArrayPtr libraries_cache() const { return raw_ptr()->libraries_cache(); }
+  ArrayPtr libraries_cache() const { return untag()->libraries_cache(); }
   void set_libraries_cache(const Array& cache) const;
   LibraryPtr LookupLibrary(Thread* thread, const Smi& name_index) const;
   LibraryPtr InsertLibrary(Thread* thread,
                            const Smi& name_index,
                            const Library& lib) const;
 
-  ArrayPtr classes_cache() const { return raw_ptr()->classes_cache(); }
+  ArrayPtr classes_cache() const { return untag()->classes_cache(); }
   void set_classes_cache(const Array& cache) const;
   ClassPtr LookupClass(Thread* thread, const Smi& name_index) const;
   ClassPtr InsertClass(Thread* thread,
@@ -5149,20 +5059,20 @@
     EntryType type_;
   };
 
-  intptr_t Length() const { return raw_ptr()->length_; }
+  intptr_t Length() const { return untag()->length_; }
   void SetLength(intptr_t value) const {
-    StoreNonPointer(&raw_ptr()->length_, value);
+    StoreNonPointer(&untag()->length_, value);
   }
 
   static intptr_t length_offset() {
-    return OFFSET_OF(ObjectPoolLayout, length_);
+    return OFFSET_OF(UntaggedObjectPool, length_);
   }
   static intptr_t data_offset() {
-    return OFFSET_OF_RETURNED_VALUE(ObjectPoolLayout, data);
+    return OFFSET_OF_RETURNED_VALUE(UntaggedObjectPool, data);
   }
   static intptr_t element_offset(intptr_t index) {
-    return OFFSET_OF_RETURNED_VALUE(ObjectPoolLayout, data) +
-           sizeof(ObjectPoolLayout::Entry) * index;
+    return OFFSET_OF_RETURNED_VALUE(UntaggedObjectPool, data) +
+           sizeof(UntaggedObjectPool::Entry) * index;
   }
 
   struct ArrayTraits {
@@ -5170,24 +5080,24 @@
       return ObjectPool::data_offset();
     }
 
-    static constexpr intptr_t kElementSize = sizeof(ObjectPoolLayout::Entry);
+    static constexpr intptr_t kElementSize = sizeof(UntaggedObjectPool::Entry);
   };
 
   EntryType TypeAt(intptr_t index) const {
     ASSERT((index >= 0) && (index <= Length()));
-    return TypeBits::decode(raw_ptr()->entry_bits()[index]);
+    return TypeBits::decode(untag()->entry_bits()[index]);
   }
 
   Patchability PatchableAt(intptr_t index) const {
     ASSERT((index >= 0) && (index <= Length()));
-    return PatchableBit::decode(raw_ptr()->entry_bits()[index]);
+    return PatchableBit::decode(untag()->entry_bits()[index]);
   }
 
   void SetTypeAt(intptr_t index, EntryType type, Patchability patchable) const {
     ASSERT(index >= 0 && index <= Length());
     const uint8_t bits =
         PatchableBit::encode(patchable) | TypeBits::encode(type);
-    StoreNonPointer(&raw_ptr()->entry_bits()[index], bits);
+    StoreNonPointer(&untag()->entry_bits()[index], bits);
   }
 
   template <std::memory_order order = std::memory_order_relaxed>
@@ -5200,7 +5110,7 @@
   void SetObjectAt(intptr_t index, const Object& obj) const {
     ASSERT((TypeAt(index) == EntryType::kTaggedObject) ||
            (TypeAt(index) == EntryType::kImmediate && obj.IsSmi()));
-    StorePointer<ObjectPtr, order>(&EntryAddr(index)->raw_obj_, obj.raw());
+    StorePointer<ObjectPtr, order>(&EntryAddr(index)->raw_obj_, obj.ptr());
   }
 
   uword RawValueAt(intptr_t index) const {
@@ -5213,21 +5123,21 @@
   }
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(ObjectPoolLayout) ==
-           OFFSET_OF_RETURNED_VALUE(ObjectPoolLayout, data));
+    ASSERT(sizeof(UntaggedObjectPool) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedObjectPool, data));
     return 0;
   }
 
   static const intptr_t kBytesPerElement =
-      sizeof(ObjectPoolLayout::Entry) + sizeof(uint8_t);
+      sizeof(UntaggedObjectPool::Entry) + sizeof(uint8_t);
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t InstanceSize(intptr_t len) {
     // Ensure that variable length data is not adding to the object length.
-    ASSERT(sizeof(ObjectPoolLayout) ==
-           (sizeof(ObjectLayout) + (1 * kWordSize)));
+    ASSERT(sizeof(UntaggedObjectPool) ==
+           (sizeof(UntaggedObject) + (1 * kWordSize)));
     ASSERT(0 <= len && len <= kMaxElements);
-    return RoundedAllocationSize(sizeof(ObjectPoolLayout) +
+    return RoundedAllocationSize(sizeof(UntaggedObjectPool) +
                                  (len * kBytesPerElement));
   }
 
@@ -5258,15 +5168,15 @@
   void DebugPrint() const;
 
  private:
-  ObjectPoolLayout::Entry const* EntryAddr(intptr_t index) const {
+  UntaggedObjectPool::Entry const* EntryAddr(intptr_t index) const {
     ASSERT((index >= 0) && (index < Length()));
-    return &raw_ptr()->data()[index];
+    return &untag()->data()[index];
   }
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(ObjectPool, Object);
   friend class Class;
   friend class Object;
-  friend class ObjectPoolLayout;
+  friend class UntaggedObjectPool;
 };
 
 class Instructions : public Object {
@@ -5282,23 +5192,23 @@
   class FlagsBits : public BitField<uint32_t, bool, kFlagsPos, kFlagsSize> {};
 
   // Excludes HeaderSize().
-  intptr_t Size() const { return SizeBits::decode(raw_ptr()->size_and_flags_); }
+  intptr_t Size() const { return SizeBits::decode(untag()->size_and_flags_); }
   static intptr_t Size(const InstructionsPtr instr) {
-    return SizeBits::decode(instr->ptr()->size_and_flags_);
+    return SizeBits::decode(instr->untag()->size_and_flags_);
   }
 
   bool HasMonomorphicEntry() const {
-    return FlagsBits::decode(raw_ptr()->size_and_flags_);
+    return FlagsBits::decode(untag()->size_and_flags_);
   }
   static bool HasMonomorphicEntry(const InstructionsPtr instr) {
-    return FlagsBits::decode(instr->ptr()->size_and_flags_);
+    return FlagsBits::decode(instr->untag()->size_and_flags_);
   }
 
-  uword PayloadStart() const { return PayloadStart(raw()); }
-  uword MonomorphicEntryPoint() const { return MonomorphicEntryPoint(raw()); }
-  uword EntryPoint() const { return EntryPoint(raw()); }
+  uword PayloadStart() const { return PayloadStart(ptr()); }
+  uword MonomorphicEntryPoint() const { return MonomorphicEntryPoint(ptr()); }
+  uword EntryPoint() const { return EntryPoint(ptr()); }
   static uword PayloadStart(const InstructionsPtr instr) {
-    return reinterpret_cast<uword>(instr->ptr()) + HeaderSize();
+    return reinterpret_cast<uword>(instr->untag()) + HeaderSize();
   }
 
 // Note: We keep the checked entrypoint offsets even (emitting NOPs if
@@ -5346,7 +5256,7 @@
   }
 
   static const intptr_t kMaxElements =
-      (kMaxInt32 - (sizeof(InstructionsLayout) + sizeof(ObjectLayout) +
+      (kMaxInt32 - (sizeof(UntaggedInstructions) + sizeof(UntaggedObject) +
                     (2 * kMaxObjectAlignment)));
 
   // Currently, we align bare instruction payloads on 4 byte boundaries.
@@ -5369,12 +5279,13 @@
       UNREACHABLE();
     }
 #endif
-    return Utils::RoundUp(sizeof(InstructionsLayout), kNonBarePayloadAlignment);
+    return Utils::RoundUp(sizeof(UntaggedInstructions),
+                          kNonBarePayloadAlignment);
   }
 
   static intptr_t InstanceSize() {
-    ASSERT_EQUAL(sizeof(InstructionsLayout),
-                 OFFSET_OF_RETURNED_VALUE(InstructionsLayout, data));
+    ASSERT_EQUAL(sizeof(UntaggedInstructions),
+                 OFFSET_OF_RETURNED_VALUE(UntaggedInstructions, data));
     return 0;
   }
 
@@ -5398,13 +5309,13 @@
   }
 
   bool Equals(const Instructions& other) const {
-    return Equals(raw(), other.raw());
+    return Equals(ptr(), other.ptr());
   }
 
   static bool Equals(InstructionsPtr a, InstructionsPtr b) {
     if (Size(a) != Size(b)) return false;
     NoSafepointScope no_safepoint;
-    return memcmp(a->ptr(), b->ptr(), InstanceSize(Size(a))) == 0;
+    return memcmp(a->untag(), b->untag(), InstanceSize(Size(a))) == 0;
   }
 
   uint32_t Hash() const {
@@ -5417,13 +5328,13 @@
  private:
   void SetSize(intptr_t value) const {
     ASSERT(value >= 0);
-    StoreNonPointer(&raw_ptr()->size_and_flags_,
-                    SizeBits::update(value, raw_ptr()->size_and_flags_));
+    StoreNonPointer(&untag()->size_and_flags_,
+                    SizeBits::update(value, untag()->size_and_flags_));
   }
 
   void SetHasMonomorphicEntry(bool value) const {
-    StoreNonPointer(&raw_ptr()->size_and_flags_,
-                    FlagsBits::update(value, raw_ptr()->size_and_flags_));
+    StoreNonPointer(&untag()->size_and_flags_,
+                    FlagsBits::update(value, untag()->size_and_flags_));
   }
 
   // New is a private method as RawInstruction and RawCode objects should
@@ -5454,11 +5365,11 @@
  public:
   // Excludes HeaderSize().
   static intptr_t Size(const InstructionsSectionPtr instr) {
-    return instr->ptr()->payload_length_;
+    return instr->untag()->payload_length_;
   }
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(InstructionsSectionLayout) ==
-           OFFSET_OF_RETURNED_VALUE(InstructionsSectionLayout, data));
+    ASSERT(sizeof(UntaggedInstructionsSection) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedInstructionsSection, data));
     return 0;
   }
 
@@ -5467,7 +5378,7 @@
   }
 
   static intptr_t HeaderSize() {
-    return Utils::RoundUp(sizeof(InstructionsSectionLayout),
+    return Utils::RoundUp(sizeof(UntaggedInstructionsSection),
                           Instructions::kBarePayloadAlignment);
   }
 
@@ -5476,7 +5387,7 @@
 
  private:
   // Note there are no New() methods for InstructionsSection. Instead, the
-  // serializer writes the InstructionsSectionLayout object manually at the
+  // serializer writes the UntaggedInstructionsSection object manually at the
   // start of instructions Images in precompiled snapshots.
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection, Object);
@@ -5491,31 +5402,32 @@
 
   void SetVar(intptr_t var_index,
               const String& name,
-              LocalVarDescriptorsLayout::VarInfo* info) const;
+              UntaggedLocalVarDescriptors::VarInfo* info) const;
 
   void GetInfo(intptr_t var_index,
-               LocalVarDescriptorsLayout::VarInfo* info) const;
+               UntaggedLocalVarDescriptors::VarInfo* info) const;
 
   static const intptr_t kBytesPerElement =
-      sizeof(LocalVarDescriptorsLayout::VarInfo);
-  static const intptr_t kMaxElements = LocalVarDescriptorsLayout::kMaxIndex;
+      sizeof(UntaggedLocalVarDescriptors::VarInfo);
+  static const intptr_t kMaxElements = UntaggedLocalVarDescriptors::kMaxIndex;
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(LocalVarDescriptorsLayout) ==
-           OFFSET_OF_RETURNED_VALUE(LocalVarDescriptorsLayout, names));
+    ASSERT(sizeof(UntaggedLocalVarDescriptors) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedLocalVarDescriptors, names));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
     ASSERT(0 <= len && len <= kMaxElements);
     return RoundedAllocationSize(
-        sizeof(LocalVarDescriptorsLayout) +
+        sizeof(UntaggedLocalVarDescriptors) +
         (len * kWordSize)  // RawStrings for names.
-        + (len * sizeof(LocalVarDescriptorsLayout::VarInfo)));
+        + (len * sizeof(UntaggedLocalVarDescriptors::VarInfo)));
   }
 
   static LocalVarDescriptorsPtr New(intptr_t num_variables);
 
-  static const char* KindToCString(LocalVarDescriptorsLayout::VarInfoKind kind);
+  static const char* KindToCString(
+      UntaggedLocalVarDescriptors::VarInfoKind kind);
 
  private:
   FINAL_HEAP_OBJECT_IMPLEMENTATION(LocalVarDescriptors, Object);
@@ -5528,14 +5440,14 @@
   static const intptr_t kBytesPerElement = 1;
   static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
 
-  static intptr_t HeaderSize() { return sizeof(PcDescriptorsLayout); }
+  static intptr_t HeaderSize() { return sizeof(UntaggedPcDescriptors); }
   static intptr_t UnroundedSize(PcDescriptorsPtr desc) {
-    return UnroundedSize(desc->ptr()->length_);
+    return UnroundedSize(desc->untag()->length_);
   }
   static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
   static intptr_t InstanceSize() {
-    ASSERT_EQUAL(sizeof(PcDescriptorsLayout),
-                 OFFSET_OF_RETURNED_VALUE(PcDescriptorsLayout, data));
+    ASSERT_EQUAL(sizeof(UntaggedPcDescriptors),
+                 OFFSET_OF_RETURNED_VALUE(UntaggedPcDescriptors, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
@@ -5554,7 +5466,7 @@
 
   // We would have a VisitPointers function here to traverse the
   // pc descriptors table to visit objects if any in the table.
-  // Note: never return a reference to a PcDescriptorsLayout::PcDescriptorRec
+  // Note: never return a reference to a UntaggedPcDescriptors::PcDescriptorRec
   // as the object can move.
   class Iterator : ValueObject {
    public:
@@ -5567,28 +5479,29 @@
           cur_deopt_id_(0),
           cur_token_pos_(0),
           cur_try_index_(0),
-          cur_yield_index_(PcDescriptorsLayout::kInvalidYieldIndex) {}
+          cur_yield_index_(UntaggedPcDescriptors::kInvalidYieldIndex) {}
 
     bool MoveNext() {
       NoSafepointScope scope;
-      ReadStream stream(descriptors_.raw_ptr()->data(), descriptors_.Length(),
+      ReadStream stream(descriptors_.untag()->data(), descriptors_.Length(),
                         byte_index_);
       // Moves to record that matches kind_mask_.
       while (byte_index_ < descriptors_.Length()) {
         const int32_t kind_and_metadata = stream.ReadSLEB128<int32_t>();
-        cur_kind_ =
-            PcDescriptorsLayout::KindAndMetadata::DecodeKind(kind_and_metadata);
-        cur_try_index_ = PcDescriptorsLayout::KindAndMetadata::DecodeTryIndex(
+        cur_kind_ = UntaggedPcDescriptors::KindAndMetadata::DecodeKind(
+            kind_and_metadata);
+        cur_try_index_ = UntaggedPcDescriptors::KindAndMetadata::DecodeTryIndex(
             kind_and_metadata);
         cur_yield_index_ =
-            PcDescriptorsLayout::KindAndMetadata::DecodeYieldIndex(
+            UntaggedPcDescriptors::KindAndMetadata::DecodeYieldIndex(
                 kind_and_metadata);
 
         cur_pc_offset_ += stream.ReadSLEB128();
 
         if (!FLAG_precompiled_mode) {
           cur_deopt_id_ += stream.ReadSLEB128();
-          cur_token_pos_ += stream.ReadSLEB128();
+          cur_token_pos_ = Utils::AddWithWrapAround(
+              cur_token_pos_, stream.ReadSLEB128<int32_t>());
         }
         byte_index_ = stream.Position();
 
@@ -5601,11 +5514,13 @@
 
     uword PcOffset() const { return cur_pc_offset_; }
     intptr_t DeoptId() const { return cur_deopt_id_; }
-    TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
+    TokenPosition TokenPos() const {
+      return TokenPosition::Deserialize(cur_token_pos_);
+    }
     intptr_t TryIndex() const { return cur_try_index_; }
     intptr_t YieldIndex() const { return cur_yield_index_; }
-    PcDescriptorsLayout::Kind Kind() const {
-      return static_cast<PcDescriptorsLayout::Kind>(cur_kind_);
+    UntaggedPcDescriptors::Kind Kind() const {
+      return static_cast<UntaggedPcDescriptors::Kind>(cur_kind_);
     }
 
    private:
@@ -5631,7 +5546,7 @@
     intptr_t cur_pc_offset_;
     intptr_t cur_kind_;
     intptr_t cur_deopt_id_;
-    intptr_t cur_token_pos_;
+    int32_t cur_token_pos_;
     intptr_t cur_try_index_;
     intptr_t cur_yield_index_;
   };
@@ -5642,11 +5557,11 @@
       return false;
     }
     NoSafepointScope no_safepoint;
-    return memcmp(raw_ptr(), other.raw_ptr(), InstanceSize(Length())) == 0;
+    return memcmp(untag(), other.untag(), InstanceSize(Length())) == 0;
   }
 
  private:
-  static const char* KindAsStr(PcDescriptorsLayout::Kind kind);
+  static const char* KindAsStr(UntaggedPcDescriptors::Kind kind);
 
   static PcDescriptorsPtr New(intptr_t length);
 
@@ -5663,14 +5578,14 @@
   static const intptr_t kBytesPerElement = 1;
   static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
 
-  static intptr_t HeaderSize() { return sizeof(CodeSourceMapLayout); }
+  static intptr_t HeaderSize() { return sizeof(UntaggedCodeSourceMap); }
   static intptr_t UnroundedSize(CodeSourceMapPtr map) {
-    return UnroundedSize(map->ptr()->length_);
+    return UnroundedSize(map->untag()->length_);
   }
   static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
   static intptr_t InstanceSize() {
-    ASSERT_EQUAL(sizeof(CodeSourceMapLayout),
-                 OFFSET_OF_RETURNED_VALUE(CodeSourceMapLayout, data));
+    ASSERT_EQUAL(sizeof(UntaggedCodeSourceMap),
+                 OFFSET_OF_RETURNED_VALUE(UntaggedCodeSourceMap, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
@@ -5680,17 +5595,15 @@
 
   static CodeSourceMapPtr New(intptr_t length);
 
-  intptr_t Length() const { return raw_ptr()->length_; }
-  uint8_t* Data() const {
-    return UnsafeMutableNonPointer(&raw_ptr()->data()[0]);
-  }
+  intptr_t Length() const { return untag()->length_; }
+  uint8_t* Data() const { return UnsafeMutableNonPointer(&untag()->data()[0]); }
 
   bool Equals(const CodeSourceMap& other) const {
     if (Length() != other.Length()) {
       return false;
     }
     NoSafepointScope no_safepoint;
-    return memcmp(raw_ptr(), other.raw_ptr(), InstanceSize(Length())) == 0;
+    return memcmp(untag(), other.untag(), InstanceSize(Length())) == 0;
   }
 
   void PrintToJSONObject(JSONObject* jsobj, bool ref) const;
@@ -5707,27 +5620,26 @@
  public:
   static const intptr_t kHashBits = 30;
 
-  uintptr_t payload_size() const { return PayloadSizeOf(raw()); }
+  uintptr_t payload_size() const { return PayloadSizeOf(ptr()); }
   static uintptr_t PayloadSizeOf(const CompressedStackMapsPtr raw) {
-    return CompressedStackMapsLayout::SizeField::decode(
-        raw->ptr()->flags_and_size_);
+    return UntaggedCompressedStackMaps::SizeField::decode(
+        raw->untag()->flags_and_size_);
   }
 
   bool Equals(const CompressedStackMaps& other) const {
     // All of the table flags and payload size must match.
-    if (raw_ptr()->flags_and_size_ != other.raw_ptr()->flags_and_size_) {
+    if (untag()->flags_and_size_ != other.untag()->flags_and_size_) {
       return false;
     }
     NoSafepointScope no_safepoint;
-    return memcmp(raw_ptr(), other.raw_ptr(), InstanceSize(payload_size())) ==
-           0;
+    return memcmp(untag(), other.untag(), InstanceSize(payload_size())) == 0;
   }
 
   // Methods to allow use with PointerKeyValueTrait to create sets of CSMs.
   bool Equals(const CompressedStackMaps* other) const { return Equals(*other); }
   intptr_t Hashcode() const;
 
-  static intptr_t HeaderSize() { return sizeof(CompressedStackMapsLayout); }
+  static intptr_t HeaderSize() { return sizeof(UntaggedCompressedStackMaps); }
   static intptr_t UnroundedSize(CompressedStackMapsPtr maps) {
     return UnroundedSize(CompressedStackMaps::PayloadSizeOf(maps));
   }
@@ -5735,24 +5647,24 @@
     return HeaderSize() + length;
   }
   static intptr_t InstanceSize() {
-    ASSERT_EQUAL(sizeof(CompressedStackMapsLayout),
-                 OFFSET_OF_RETURNED_VALUE(CompressedStackMapsLayout, data));
+    ASSERT_EQUAL(sizeof(UntaggedCompressedStackMaps),
+                 OFFSET_OF_RETURNED_VALUE(UntaggedCompressedStackMaps, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t length) {
     return RoundedAllocationSize(UnroundedSize(length));
   }
 
-  bool UsesGlobalTable() const { return UsesGlobalTable(raw()); }
+  bool UsesGlobalTable() const { return UsesGlobalTable(ptr()); }
   static bool UsesGlobalTable(const CompressedStackMapsPtr raw) {
-    return CompressedStackMapsLayout::UsesTableBit::decode(
-        raw->ptr()->flags_and_size_);
+    return UntaggedCompressedStackMaps::UsesTableBit::decode(
+        raw->untag()->flags_and_size_);
   }
 
-  bool IsGlobalTable() const { return IsGlobalTable(raw()); }
+  bool IsGlobalTable() const { return IsGlobalTable(ptr()); }
   static bool IsGlobalTable(const CompressedStackMapsPtr raw) {
-    return CompressedStackMapsLayout::GlobalTableBit::decode(
-        raw->ptr()->flags_and_size_);
+    return UntaggedCompressedStackMaps::GlobalTableBit::decode(
+        raw->untag()->flags_and_size_);
   }
 
   static CompressedStackMapsPtr NewInlined(const void* payload, intptr_t size) {
@@ -5881,12 +5793,12 @@
   bool HasCatchAll(intptr_t try_index) const;
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(ExceptionHandlersLayout) ==
-           OFFSET_OF_RETURNED_VALUE(ExceptionHandlersLayout, data));
+    ASSERT(sizeof(UntaggedExceptionHandlers) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedExceptionHandlers, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
-    return RoundedAllocationSize(sizeof(ExceptionHandlersLayout) +
+    return RoundedAllocationSize(sizeof(UntaggedExceptionHandlers) +
                                  (len * sizeof(ExceptionHandlerInfo)));
   }
 
@@ -5935,7 +5847,7 @@
 //  * Code::owner_
 class WeakSerializationReference : public Object {
  public:
-  ObjectPtr target() const { return TargetOf(raw()); }
+  ObjectPtr target() const { return TargetOf(ptr()); }
   static ObjectPtr TargetOf(const WeakSerializationReferencePtr raw) {
 #if defined(DART_PRECOMPILED_RUNTIME)
     // WSRs in the precompiled runtime only contain some remaining info about
@@ -5943,23 +5855,23 @@
     return Object::null();
 #else
     // Outside the precompiled runtime, they should always have a target.
-    ASSERT(raw->ptr()->target() != Object::null());
-    return raw->ptr()->target();
+    ASSERT(raw->untag()->target() != Object::null());
+    return raw->untag()->target();
 #endif
   }
 
-  classid_t TargetClassId() const { return TargetClassIdOf(raw()); }
+  classid_t TargetClassId() const { return TargetClassIdOf(ptr()); }
   static classid_t TargetClassIdOf(const WeakSerializationReferencePtr raw) {
 #if defined(DART_PRECOMPILED_RUNTIME)
     // No new instances of WSRs are created in the precompiled runtime, so
     // this instance came from deserialization and thus must be the empty WSR.
-    return raw->ptr()->cid_;
+    return raw->untag()->cid_;
 #else
     return TargetOf(raw)->GetClassId();
 #endif
   }
 
-  static ObjectPtr Unwrap(const Object& obj) { return Unwrap(obj.raw()); }
+  static ObjectPtr Unwrap(const Object& obj) { return Unwrap(obj.ptr()); }
   // Gets the underlying object from a WSR, or the original object if it is
   // not one. Notably, Unwrap(Wrap(r)) == r for all raw objects r, whether
   // CanWrap(r) or not. However, this will not hold if a serialization and
@@ -5973,7 +5885,7 @@
   // WSR is returned. Useful for cases where we want to call Object methods
   // like ToCString() on whatever non-null object we can get.
   static ObjectPtr UnwrapIfTarget(const Object& obj) {
-    return UnwrapIfTarget(obj.raw());
+    return UnwrapIfTarget(obj.ptr());
   }
   static ObjectPtr UnwrapIfTarget(ObjectPtr raw) {
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -5988,7 +5900,7 @@
   }
 
   static classid_t UnwrappedClassIdOf(const Object& obj) {
-    return UnwrappedClassIdOf(obj.raw());
+    return UnwrappedClassIdOf(obj.ptr());
   }
   // Gets the class ID of the underlying object from a WSR, or the class ID of
   // the object if it is not one.
@@ -6003,7 +5915,7 @@
   }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(WeakSerializationReferenceLayout));
+    return RoundedAllocationSize(sizeof(UntaggedWeakSerializationReference));
   }
 
 #if defined(DART_PRECOMPILER)
@@ -6011,7 +5923,7 @@
   static bool CanWrap(const Object& object);
 
   // This returns ObjectPtr, not WeakSerializationReferencePtr, because
-  // target.raw() is returned when CanWrap(target) is false.
+  // target.ptr() is returned when CanWrap(target) is false.
   static ObjectPtr Wrap(Zone* zone, const Object& target);
 #endif
 
@@ -6028,18 +5940,18 @@
     UNREACHABLE();
     return NULL;
 #else
-    return raw_ptr()->active_instructions();
+    return untag()->active_instructions();
 #endif
   }
 
   // When dual mapping, these return the executable view.
-  InstructionsPtr instructions() const { return raw_ptr()->instructions(); }
+  InstructionsPtr instructions() const { return untag()->instructions(); }
   static InstructionsPtr InstructionsOf(const CodePtr code) {
-    return code->ptr()->instructions();
+    return code->untag()->instructions();
   }
 
   static intptr_t saved_instructions_offset() {
-    return OFFSET_OF(CodeLayout, instructions_);
+    return OFFSET_OF(UntaggedCode, instructions_);
   }
 
   using EntryKind = CodeEntryKind;
@@ -6050,54 +5962,55 @@
   static intptr_t entry_point_offset(EntryKind kind = EntryKind::kNormal) {
     switch (kind) {
       case EntryKind::kNormal:
-        return OFFSET_OF(CodeLayout, entry_point_);
+        return OFFSET_OF(UntaggedCode, entry_point_);
       case EntryKind::kUnchecked:
-        return OFFSET_OF(CodeLayout, unchecked_entry_point_);
+        return OFFSET_OF(UntaggedCode, unchecked_entry_point_);
       case EntryKind::kMonomorphic:
-        return OFFSET_OF(CodeLayout, monomorphic_entry_point_);
+        return OFFSET_OF(UntaggedCode, monomorphic_entry_point_);
       case EntryKind::kMonomorphicUnchecked:
-        return OFFSET_OF(CodeLayout, monomorphic_unchecked_entry_point_);
+        return OFFSET_OF(UntaggedCode, monomorphic_unchecked_entry_point_);
       default:
         UNREACHABLE();
     }
   }
 
-  ObjectPoolPtr object_pool() const { return raw_ptr()->object_pool(); }
+  ObjectPoolPtr object_pool() const { return untag()->object_pool(); }
   static intptr_t object_pool_offset() {
-    return OFFSET_OF(CodeLayout, object_pool_);
+    return OFFSET_OF(UntaggedCode, object_pool_);
   }
 
   intptr_t pointer_offsets_length() const {
-    return PtrOffBits::decode(raw_ptr()->state_bits_);
+    return PtrOffBits::decode(untag()->state_bits_);
   }
 
   bool is_optimized() const {
-    return OptimizedBit::decode(raw_ptr()->state_bits_);
+    return OptimizedBit::decode(untag()->state_bits_);
   }
   void set_is_optimized(bool value) const;
   static bool IsOptimized(CodePtr code) {
-    return Code::OptimizedBit::decode(code->ptr()->state_bits_);
+    return Code::OptimizedBit::decode(code->untag()->state_bits_);
   }
 
   bool is_force_optimized() const {
-    return ForceOptimizedBit::decode(raw_ptr()->state_bits_);
+    return ForceOptimizedBit::decode(untag()->state_bits_);
   }
   void set_is_force_optimized(bool value) const;
 
-  bool is_alive() const { return AliveBit::decode(raw_ptr()->state_bits_); }
+  bool is_alive() const { return AliveBit::decode(untag()->state_bits_); }
   void set_is_alive(bool value) const;
 
-  bool HasMonomorphicEntry() const { return HasMonomorphicEntry(raw()); }
+  bool HasMonomorphicEntry() const { return HasMonomorphicEntry(ptr()); }
   static bool HasMonomorphicEntry(const CodePtr code) {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return code->ptr()->entry_point_ != code->ptr()->monomorphic_entry_point_;
+    return code->untag()->entry_point_ !=
+           code->untag()->monomorphic_entry_point_;
 #else
     return Instructions::HasMonomorphicEntry(InstructionsOf(code));
 #endif
   }
 
   // Returns the payload start of [instructions()].
-  uword PayloadStart() const { return PayloadStartOf(raw()); }
+  uword PayloadStart() const { return PayloadStartOf(ptr()); }
   static uword PayloadStartOf(const CodePtr code) {
 #if defined(DART_PRECOMPILED_RUNTIME)
     const uword entry_offset = HasMonomorphicEntry(code)
@@ -6110,10 +6023,10 @@
   }
 
   // Returns the entry point of [instructions()].
-  uword EntryPoint() const { return EntryPointOf(raw()); }
+  uword EntryPoint() const { return EntryPointOf(ptr()); }
   static uword EntryPointOf(const CodePtr code) {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return code->ptr()->entry_point_;
+    return code->untag()->entry_point_;
 #else
     return Instructions::EntryPoint(InstructionsOf(code));
 #endif
@@ -6122,15 +6035,15 @@
   // Returns the unchecked entry point of [instructions()].
   uword UncheckedEntryPoint() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return raw_ptr()->unchecked_entry_point_;
+    return untag()->unchecked_entry_point_;
 #else
-    return EntryPoint() + raw_ptr()->unchecked_offset_;
+    return EntryPoint() + untag()->unchecked_offset_;
 #endif
   }
   // Returns the monomorphic entry point of [instructions()].
   uword MonomorphicEntryPoint() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return raw_ptr()->monomorphic_entry_point_;
+    return untag()->monomorphic_entry_point_;
 #else
     return Instructions::MonomorphicEntryPoint(instructions());
 #endif
@@ -6138,17 +6051,17 @@
   // Returns the unchecked monomorphic entry point of [instructions()].
   uword MonomorphicUncheckedEntryPoint() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return raw_ptr()->monomorphic_unchecked_entry_point_;
+    return untag()->monomorphic_unchecked_entry_point_;
 #else
-    return MonomorphicEntryPoint() + raw_ptr()->unchecked_offset_;
+    return MonomorphicEntryPoint() + untag()->unchecked_offset_;
 #endif
   }
 
   // Returns the size of [instructions()].
-  intptr_t Size() const { return PayloadSizeOf(raw()); }
+  intptr_t Size() const { return PayloadSizeOf(ptr()); }
   static intptr_t PayloadSizeOf(const CodePtr code) {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return code->ptr()->instructions_length_;
+    return code->untag()->instructions_length_;
 #else
     return Instructions::Size(InstructionsOf(code));
 #endif
@@ -6157,32 +6070,30 @@
   ObjectPoolPtr GetObjectPool() const;
   // Returns whether the given PC address is in [instructions()].
   bool ContainsInstructionAt(uword addr) const {
-    return ContainsInstructionAt(raw(), addr);
+    return ContainsInstructionAt(ptr(), addr);
   }
 
   // Returns whether the given PC address is in [InstructionsOf(code)].
   static bool ContainsInstructionAt(const CodePtr code, uword pc) {
-    return CodeLayout::ContainsPC(code, pc);
+    return UntaggedCode::ContainsPC(code, pc);
   }
 
   // Returns true if there is a debugger breakpoint set in this code object.
   bool HasBreakpoint() const;
 
-  PcDescriptorsPtr pc_descriptors() const {
-    return raw_ptr()->pc_descriptors();
-  }
+  PcDescriptorsPtr pc_descriptors() const { return untag()->pc_descriptors(); }
   void set_pc_descriptors(const PcDescriptors& descriptors) const {
     ASSERT(descriptors.IsOld());
-    raw_ptr()->set_pc_descriptors(descriptors.raw());
+    untag()->set_pc_descriptors(descriptors.ptr());
   }
 
   CodeSourceMapPtr code_source_map() const {
-    return raw_ptr()->code_source_map();
+    return untag()->code_source_map();
   }
 
   void set_code_source_map(const CodeSourceMap& code_source_map) const {
     ASSERT(code_source_map.IsOld());
-    raw_ptr()->set_code_source_map(code_source_map.raw());
+    untag()->set_code_source_map(code_source_map.ptr());
   }
 
   // Array of DeoptInfo objects.
@@ -6191,7 +6102,7 @@
     UNREACHABLE();
     return NULL;
 #else
-    return raw_ptr()->deopt_info_array();
+    return untag()->deopt_info_array();
 #endif
   }
   void set_deopt_info_array(const Array& array) const;
@@ -6207,7 +6118,7 @@
 #endif
 
   CompressedStackMapsPtr compressed_stackmaps() const {
-    return raw_ptr()->compressed_stackmaps();
+    return untag()->compressed_stackmaps();
   }
   void set_compressed_stackmaps(const CompressedStackMaps& maps) const;
 
@@ -6247,7 +6158,7 @@
     UNREACHABLE();
     return NULL;
 #else
-    return raw_ptr()->static_calls_target_table();
+    return untag()->static_calls_target_table();
 #endif
   }
 
@@ -6300,7 +6211,7 @@
     UNREACHABLE();
     return NULL;
 #else
-    return raw_ptr()->return_address_metadata();
+    return untag()->return_address_metadata();
 #endif
   }
   // Sets |return_address_metadata|.
@@ -6341,7 +6252,7 @@
     UNREACHABLE();
     return NULL;
 #else
-    return raw_ptr()->var_descriptors();
+    return untag()->var_descriptors();
 #endif
   }
   void set_var_descriptors(const LocalVarDescriptors& value) const {
@@ -6349,7 +6260,7 @@
     UNREACHABLE();
 #else
     ASSERT(value.IsOld());
-    raw_ptr()->set_var_descriptors(value.raw());
+    untag()->set_var_descriptors(value.ptr());
 #endif
   }
 
@@ -6357,11 +6268,11 @@
   LocalVarDescriptorsPtr GetLocalVarDescriptors() const;
 
   ExceptionHandlersPtr exception_handlers() const {
-    return raw_ptr()->exception_handlers();
+    return untag()->exception_handlers();
   }
   void set_exception_handlers(const ExceptionHandlers& handlers) const {
     ASSERT(handlers.IsOld());
-    raw_ptr()->set_exception_handlers(handlers.raw());
+    untag()->set_exception_handlers(handlers.ptr());
   }
 
   // WARNING: function() returns the owner which is not guaranteed to be
@@ -6373,33 +6284,36 @@
   FunctionPtr function() const {
     ASSERT(IsFunctionCode());
     return Function::RawCast(
-        WeakSerializationReference::Unwrap(raw_ptr()->owner()));
+        WeakSerializationReference::Unwrap(untag()->owner()));
   }
 
-  ObjectPtr owner() const { return raw_ptr()->owner(); }
+  ObjectPtr owner() const { return untag()->owner(); }
   void set_owner(const Object& owner) const;
 
-  classid_t OwnerClassId() const { return OwnerClassIdOf(raw()); }
+  classid_t OwnerClassId() const { return OwnerClassIdOf(ptr()); }
   static classid_t OwnerClassIdOf(CodePtr raw) {
-    return WeakSerializationReference::UnwrappedClassIdOf(raw->ptr()->owner());
+    return WeakSerializationReference::UnwrappedClassIdOf(
+        raw->untag()->owner());
   }
 
-  static intptr_t owner_offset() { return OFFSET_OF(CodeLayout, owner_); }
+  static intptr_t owner_offset() { return OFFSET_OF(UntaggedCode, owner_); }
 
   // We would have a VisitPointers function here to traverse all the
   // embedded objects in the instructions using pointer_offsets.
 
   static const intptr_t kBytesPerElement =
-      sizeof(reinterpret_cast<CodeLayout*>(0)->data()[0]);
+      sizeof(reinterpret_cast<UntaggedCode*>(0)->data()[0]);
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(CodeLayout) == OFFSET_OF_RETURNED_VALUE(CodeLayout, data));
+    ASSERT(sizeof(UntaggedCode) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedCode, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
     ASSERT(0 <= len && len <= kMaxElements);
-    return RoundedAllocationSize(sizeof(CodeLayout) + (len * kBytesPerElement));
+    return RoundedAllocationSize(sizeof(UntaggedCode) +
+                                 (len * kBytesPerElement));
   }
 #if !defined(DART_PRECOMPILED_RUNTIME)
   // Finalizes the generated code, by generating various kinds of metadata (e.g.
@@ -6452,7 +6366,7 @@
 
   // Find pc, return 0 if not found.
   uword GetPcForDeoptId(intptr_t deopt_id,
-                        PcDescriptorsLayout::Kind kind) const;
+                        UntaggedPcDescriptors::Kind kind) const;
   intptr_t GetDeoptIdForOsr(uword pc) const;
 
   const char* Name() const;
@@ -6462,7 +6376,7 @@
 #if defined(PRODUCT)
     return 0;
 #else
-    return raw_ptr()->compile_timestamp_;
+    return untag()->compile_timestamp_;
 #endif
   }
 
@@ -6477,29 +6391,29 @@
 
   void Enable() const {
     if (!IsDisabled()) return;
-    ASSERT(Thread::Current()->IsMutatorThread());
     ResetActiveInstructions();
   }
 
-  bool IsDisabled() const { return IsDisabled(raw()); }
+  bool IsDisabled() const { return IsDisabled(ptr()); }
   static bool IsDisabled(CodePtr code) {
 #if defined(DART_PRECOMPILED_RUNTIME)
     UNREACHABLE();
     return false;
 #else
-    return code->ptr()->instructions() != code->ptr()->active_instructions();
+    return code->untag()->instructions() !=
+           code->untag()->active_instructions();
 #endif
   }
 
   void set_object_pool(ObjectPoolPtr object_pool) const {
-    raw_ptr()->set_object_pool(object_pool);
+    untag()->set_object_pool(object_pool);
   }
 
  private:
   void set_state_bits(intptr_t bits) const;
 
-  friend class ObjectLayout;  // For ObjectLayout::SizeFromClass().
-  friend class CodeLayout;
+  friend class UntaggedObject;  // For UntaggedObject::SizeFromClass().
+  friend class UntaggedCode;
   enum {
     kOptimizedBit = 0,
     kForceOptimizedBit = 1,
@@ -6539,7 +6453,7 @@
 #if defined(PRODUCT)
     UNREACHABLE();
 #else
-    StoreNonPointer(&raw_ptr()->compile_timestamp_, timestamp);
+    StoreNonPointer(&untag()->compile_timestamp_, timestamp);
 #endif
   }
 
@@ -6553,6 +6467,8 @@
   // entry point addresses.
   void SetActiveInstructions(const Instructions& instructions,
                              uint32_t unchecked_offset) const;
+  void SetActiveInstructionsSafe(const Instructions& instructions,
+                                 uint32_t unchecked_offset) const;
 
   // Resets [active_instructions_] to its original value of [instructions_] and
   // updates the cached entry point addresses to match.
@@ -6560,36 +6476,36 @@
 
   void set_instructions(const Instructions& instructions) const {
     ASSERT(Thread::Current()->IsMutatorThread() || !is_alive());
-    raw_ptr()->set_instructions(instructions.raw());
+    untag()->set_instructions(instructions.ptr());
   }
 #if !defined(DART_PRECOMPILED_RUNTIME)
   void set_unchecked_offset(uword offset) const {
-    StoreNonPointer(&raw_ptr()->unchecked_offset_, offset);
+    StoreNonPointer(&untag()->unchecked_offset_, offset);
   }
 #endif
 
   // Returns the unchecked entry point offset for [instructions_].
   uint32_t UncheckedEntryPointOffset() const {
-    return UncheckedEntryPointOffsetOf(raw());
+    return UncheckedEntryPointOffsetOf(ptr());
   }
   static uint32_t UncheckedEntryPointOffsetOf(CodePtr code) {
 #if defined(DART_PRECOMPILED_RUNTIME)
     UNREACHABLE();
 #else
-    return code->ptr()->unchecked_offset_;
+    return code->untag()->unchecked_offset_;
 #endif
   }
 
   void set_pointer_offsets_length(intptr_t value) {
     // The number of fixups is limited to 1-billion.
     ASSERT(Utils::IsUint(30, value));
-    set_state_bits(PtrOffBits::update(value, raw_ptr()->state_bits_));
+    set_state_bits(PtrOffBits::update(value, untag()->state_bits_));
   }
   int32_t* PointerOffsetAddrAt(int index) const {
     ASSERT(index >= 0);
     ASSERT(index < pointer_offsets_length());
     // TODO(iposva): Unit test is missing for this functionality.
-    return &UnsafeMutableNonPointer(raw_ptr()->data())[index];
+    return &UnsafeMutableNonPointer(untag()->data())[index];
   }
   void SetPointerOffsetAt(int index, int32_t offset_in_instructions) {
     NoSafepointScope no_safepoint;
@@ -6597,7 +6513,8 @@
   }
 
   intptr_t BinarySearchInSCallTable(uword pc) const;
-  static CodePtr LookupCodeInIsolate(Isolate* isolate, uword pc);
+  static CodePtr LookupCodeInIsolateGroup(IsolateGroup* isolate_group,
+                                          uword pc);
 
   // New is a private method as RawInstruction and RawCode objects should
   // only be created using the Code::FinalizeCode method. This method creates
@@ -6619,31 +6536,33 @@
   friend class MegamorphicCacheTable;  // for set_object_pool
   friend class CodePatcher;            // for set_instructions
   friend class ProgramVisitor;         // for set_instructions
-  // So that the FunctionLayout pointer visitor can determine whether code the
+  // So that the UntaggedFunction pointer visitor can determine whether code the
   // function points to is optimized.
-  friend class FunctionLayout;
+  friend class UntaggedFunction;
   friend class CallSiteResetter;
   friend class CodeKeyValueTrait;  // for UncheckedEntryPointOffset
 };
 
 class Context : public Object {
  public:
-  ContextPtr parent() const { return raw_ptr()->parent(); }
+  ContextPtr parent() const { return untag()->parent(); }
   void set_parent(const Context& parent) const {
-    raw_ptr()->set_parent(parent.raw());
+    untag()->set_parent(parent.ptr());
   }
-  static intptr_t parent_offset() { return OFFSET_OF(ContextLayout, parent_); }
+  static intptr_t parent_offset() {
+    return OFFSET_OF(UntaggedContext, parent_);
+  }
 
-  intptr_t num_variables() const { return raw_ptr()->num_variables_; }
+  intptr_t num_variables() const { return untag()->num_variables_; }
   static intptr_t num_variables_offset() {
-    return OFFSET_OF(ContextLayout, num_variables_);
+    return OFFSET_OF(UntaggedContext, num_variables_);
   }
   static intptr_t NumVariables(const ContextPtr context) {
-    return context->ptr()->num_variables_;
+    return context->untag()->num_variables_;
   }
 
   ObjectPtr At(intptr_t context_index) const {
-    return raw_ptr()->element(context_index);
+    return untag()->element(context_index);
   }
   inline void SetAt(intptr_t context_index, const Object& value) const;
 
@@ -6664,7 +6583,7 @@
   static const intptr_t kIsSyncIndex = 2;
 
   static intptr_t variable_offset(intptr_t context_index) {
-    return OFFSET_OF_RETURNED_VALUE(ContextLayout, data) +
+    return OFFSET_OF_RETURNED_VALUE(UntaggedContext, data) +
            (kWordSize * context_index);
   }
 
@@ -6673,14 +6592,14 @@
   }
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(ContextLayout) ==
-           OFFSET_OF_RETURNED_VALUE(ContextLayout, data));
+    ASSERT(sizeof(UntaggedContext) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedContext, data));
     return 0;
   }
 
   static intptr_t InstanceSize(intptr_t len) {
     ASSERT(IsValidLength(len));
-    return RoundedAllocationSize(sizeof(ContextLayout) +
+    return RoundedAllocationSize(sizeof(UntaggedContext) +
                                  (len * kBytesPerElement));
   }
 
@@ -6688,7 +6607,7 @@
 
  private:
   void set_num_variables(intptr_t num_variables) const {
-    StoreNonPointer(&raw_ptr()->num_variables_, num_variables);
+    StoreNonPointer(&untag()->num_variables_, num_variables);
   }
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Context, Object);
@@ -6708,7 +6627,7 @@
 // which is true if the ContextScope was created for an implicit closure.
 class ContextScope : public Object {
  public:
-  intptr_t num_variables() const { return raw_ptr()->num_variables_; }
+  intptr_t num_variables() const { return untag()->num_variables_; }
 
   TokenPosition TokenIndexAt(intptr_t scope_index) const;
   void SetTokenIndexAt(intptr_t scope_index, TokenPosition token_pos) const;
@@ -6748,18 +6667,18 @@
   void SetContextLevelAt(intptr_t scope_index, intptr_t context_level) const;
 
   static const intptr_t kBytesPerElement =
-      sizeof(ContextScopeLayout::VariableDesc);
+      sizeof(UntaggedContextScope::VariableDesc);
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(ContextScopeLayout) ==
-           OFFSET_OF_RETURNED_VALUE(ContextScopeLayout, data));
+    ASSERT(sizeof(UntaggedContextScope) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedContextScope, data));
     return 0;
   }
 
   static intptr_t InstanceSize(intptr_t len) {
     ASSERT(0 <= len && len <= kMaxElements);
-    return RoundedAllocationSize(sizeof(ContextScopeLayout) +
+    return RoundedAllocationSize(sizeof(UntaggedContextScope) +
                                  (len * kBytesPerElement));
   }
 
@@ -6767,17 +6686,17 @@
 
  private:
   void set_num_variables(intptr_t num_variables) const {
-    StoreNonPointer(&raw_ptr()->num_variables_, num_variables);
+    StoreNonPointer(&untag()->num_variables_, num_variables);
   }
 
   void set_is_implicit(bool is_implicit) const {
-    StoreNonPointer(&raw_ptr()->is_implicit_, is_implicit);
+    StoreNonPointer(&untag()->is_implicit_, is_implicit);
   }
 
-  const ContextScopeLayout::VariableDesc* VariableDescAddr(
+  const UntaggedContextScope::VariableDesc* VariableDescAddr(
       intptr_t index) const {
     ASSERT((index >= 0) && (index < num_variables()));
-    return raw_ptr()->VariableDescAddr(index);
+    return untag()->VariableDescAddr(index);
   }
 
   bool GetFlagAt(intptr_t scope_index, intptr_t mask) const;
@@ -6810,13 +6729,13 @@
   void set_filled_entry_count(intptr_t num) const;
 
   static intptr_t buckets_offset() {
-    return OFFSET_OF(MegamorphicCacheLayout, buckets_);
+    return OFFSET_OF(UntaggedMegamorphicCache, buckets_);
   }
   static intptr_t mask_offset() {
-    return OFFSET_OF(MegamorphicCacheLayout, mask_);
+    return OFFSET_OF(UntaggedMegamorphicCache, mask_);
   }
   static intptr_t arguments_descriptor_offset() {
-    return OFFSET_OF(MegamorphicCacheLayout, args_descriptor_);
+    return OFFSET_OF(UntaggedMegamorphicCache, args_descriptor_);
   }
 
   static MegamorphicCachePtr New(const String& target_name,
@@ -6828,7 +6747,7 @@
   void SwitchToBareInstructions();
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(MegamorphicCacheLayout));
+    return RoundedAllocationSize(sizeof(UntaggedMegamorphicCache));
   }
 
  private:
@@ -6937,11 +6856,11 @@
   static SubtypeTestCachePtr New();
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(SubtypeTestCacheLayout));
+    return RoundedAllocationSize(sizeof(UntaggedSubtypeTestCache));
   }
 
   static intptr_t cache_offset() {
-    return OFFSET_OF(SubtypeTestCacheLayout, cache_);
+    return OFFSET_OF(UntaggedSubtypeTestCache, cache_);
   }
 
   static void Init();
@@ -6970,7 +6889,7 @@
   static LoadingUnitPtr New();
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(LoadingUnitLayout));
+    return RoundedAllocationSize(sizeof(UntaggedLoadingUnit));
   }
 
   LoadingUnitPtr parent() const;
@@ -6979,24 +6898,25 @@
   ArrayPtr base_objects() const;
   void set_base_objects(const Array& value) const;
 
-  intptr_t id() const { return raw_ptr()->id_; }
-  void set_id(intptr_t id) const { StoreNonPointer(&raw_ptr()->id_, id); }
+  intptr_t id() const { return untag()->id_; }
+  void set_id(intptr_t id) const { StoreNonPointer(&untag()->id_, id); }
 
   // True once the VM deserializes this unit's snapshot.
-  bool loaded() const { return raw_ptr()->loaded_; }
+  bool loaded() const { return untag()->loaded_; }
   void set_loaded(bool value) const {
-    StoreNonPointer(&raw_ptr()->loaded_, value);
+    StoreNonPointer(&untag()->loaded_, value);
   }
 
   // True once the VM invokes the embedder's deferred load callback until the
   // embedder calls Dart_DeferredLoadComplete[Error].
-  bool load_outstanding() const { return raw_ptr()->load_outstanding_; }
+  bool load_outstanding() const { return untag()->load_outstanding_; }
   void set_load_outstanding(bool value) const {
-    StoreNonPointer(&raw_ptr()->load_outstanding_, value);
+    StoreNonPointer(&untag()->load_outstanding_, value);
   }
 
   ObjectPtr IssueLoad() const;
-  void CompleteLoad(const String& error_message, bool transient_error) const;
+  ObjectPtr CompleteLoad(const String& error_message,
+                         bool transient_error) const;
 
  private:
   FINAL_HEAP_OBJECT_IMPLEMENTATION(LoadingUnit, Object);
@@ -7013,10 +6933,10 @@
 
 class ApiError : public Error {
  public:
-  StringPtr message() const { return raw_ptr()->message(); }
+  StringPtr message() const { return untag()->message(); }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ApiErrorLayout));
+    return RoundedAllocationSize(sizeof(UntaggedApiError));
   }
 
   static ApiErrorPtr New(const String& message, Heap::Space space = Heap::kNew);
@@ -7035,14 +6955,14 @@
 class LanguageError : public Error {
  public:
   Report::Kind kind() const {
-    return static_cast<Report::Kind>(raw_ptr()->kind_);
+    return static_cast<Report::Kind>(untag()->kind_);
   }
 
   // Build, cache, and return formatted message.
   StringPtr FormatMessage() const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(LanguageErrorLayout));
+    return RoundedAllocationSize(sizeof(UntaggedLanguageError));
   }
 
   // A null script means no source and a negative token_pos means no position.
@@ -7070,26 +6990,26 @@
 
   virtual const char* ToErrorCString() const;
 
-  TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
+  TokenPosition token_pos() const { return untag()->token_pos_; }
 
  private:
-  ErrorPtr previous_error() const { return raw_ptr()->previous_error(); }
+  ErrorPtr previous_error() const { return untag()->previous_error(); }
   void set_previous_error(const Error& value) const;
 
-  ScriptPtr script() const { return raw_ptr()->script(); }
+  ScriptPtr script() const { return untag()->script(); }
   void set_script(const Script& value) const;
 
   void set_token_pos(TokenPosition value) const;
 
-  bool report_after_token() const { return raw_ptr()->report_after_token_; }
+  bool report_after_token() const { return untag()->report_after_token_; }
   void set_report_after_token(bool value);
 
   void set_kind(uint8_t value) const;
 
-  StringPtr message() const { return raw_ptr()->message(); }
+  StringPtr message() const { return untag()->message(); }
   void set_message(const String& value) const;
 
-  StringPtr formatted_message() const { return raw_ptr()->formatted_message(); }
+  StringPtr formatted_message() const { return untag()->formatted_message(); }
   void set_formatted_message(const String& value) const;
 
   static LanguageErrorPtr New();
@@ -7100,18 +7020,18 @@
 
 class UnhandledException : public Error {
  public:
-  InstancePtr exception() const { return raw_ptr()->exception(); }
+  InstancePtr exception() const { return untag()->exception(); }
   static intptr_t exception_offset() {
-    return OFFSET_OF(UnhandledExceptionLayout, exception_);
+    return OFFSET_OF(UntaggedUnhandledException, exception_);
   }
 
-  InstancePtr stacktrace() const { return raw_ptr()->stacktrace(); }
+  InstancePtr stacktrace() const { return untag()->stacktrace(); }
   static intptr_t stacktrace_offset() {
-    return OFFSET_OF(UnhandledExceptionLayout, stacktrace_);
+    return OFFSET_OF(UntaggedUnhandledException, stacktrace_);
   }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(UnhandledExceptionLayout));
+    return RoundedAllocationSize(sizeof(UntaggedUnhandledException));
   }
 
   static UnhandledExceptionPtr New(const Instance& exception,
@@ -7133,13 +7053,13 @@
 
 class UnwindError : public Error {
  public:
-  bool is_user_initiated() const { return raw_ptr()->is_user_initiated_; }
+  bool is_user_initiated() const { return untag()->is_user_initiated_; }
   void set_is_user_initiated(bool value) const;
 
-  StringPtr message() const { return raw_ptr()->message(); }
+  StringPtr message() const { return untag()->message(); }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(UnwindErrorLayout));
+    return RoundedAllocationSize(sizeof(UntaggedUnwindError));
   }
 
   static UnwindErrorPtr New(const String& message,
@@ -7175,7 +7095,7 @@
     const Class& cls = Class::Handle(clazz());
     ASSERT(cls.is_finalized() || cls.is_prefinalized());
 #endif
-    return (clazz()->ptr()->host_instance_size_in_words_ * kWordSize);
+    return (clazz()->untag()->host_instance_size_in_words_ * kWordSize);
   }
 
   InstancePtr Canonicalize(Thread* thread) const;
@@ -7220,7 +7140,7 @@
   static bool NullIsAssignableTo(const AbstractType& other);
 
   bool IsValidNativeIndex(int index) const {
-    return ((index >= 0) && (index < clazz()->ptr()->num_native_fields_));
+    return ((index >= 0) && (index < clazz()->untag()->num_native_fields_));
   }
 
   intptr_t* NativeFieldsDataAddr() const;
@@ -7230,7 +7150,7 @@
   void SetNativeFields(uint16_t num_fields, const intptr_t* field_values) const;
 
   uint16_t NumNativeFields() const {
-    return clazz()->ptr()->num_native_fields_;
+    return clazz()->untag()->num_native_fields_;
   }
 
   void SetNativeField(int index, intptr_t value) const;
@@ -7272,7 +7192,7 @@
   ObjectPtr IdentityHashCode() const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(InstanceLayout));
+    return RoundedAllocationSize(sizeof(UntaggedInstance));
   }
 
   static InstancePtr New(const Class& cls, Heap::Space space = Heap::kNew);
@@ -7287,7 +7207,7 @@
   // Pointer handles.
   virtual bool IsPointer() const;
 
-  static intptr_t NextFieldOffset() { return sizeof(InstanceLayout); }
+  static intptr_t NextFieldOffset() { return sizeof(UntaggedInstance); }
 
  protected:
 #ifndef PRODUCT
@@ -7321,10 +7241,10 @@
     return FieldAddrAtOffset(field.HostOffset());
   }
   ObjectPtr* NativeFieldsAddr() const {
-    return FieldAddrAtOffset(sizeof(ObjectLayout));
+    return FieldAddrAtOffset(sizeof(UntaggedObject));
   }
   void SetFieldAtOffset(intptr_t offset, const Object& value) const {
-    StorePointer(FieldAddrAtOffset(offset), value.raw());
+    StorePointer(FieldAddrAtOffset(offset), value.ptr());
   }
   bool IsValidFieldOffset(intptr_t offset) const;
 
@@ -7337,7 +7257,7 @@
     return *RawFieldAddrAtOffset(offset);
   }
   void RawSetFieldAtOffset(intptr_t offset, const Object& value) const {
-    StorePointer(RawFieldAddrAtOffset(offset), value.raw());
+    StorePointer(RawFieldAddrAtOffset(offset), value.ptr());
   }
 
   static InstancePtr NewFromCidAndSize(SharedClassTable* shared_class_table,
@@ -7364,24 +7284,24 @@
 
 class LibraryPrefix : public Instance {
  public:
-  StringPtr name() const { return raw_ptr()->name(); }
+  StringPtr name() const { return untag()->name(); }
   virtual StringPtr DictionaryName() const { return name(); }
 
-  ArrayPtr imports() const { return raw_ptr()->imports(); }
-  intptr_t num_imports() const { return raw_ptr()->num_imports_; }
-  LibraryPtr importer() const { return raw_ptr()->importer(); }
+  ArrayPtr imports() const { return untag()->imports(); }
+  intptr_t num_imports() const { return untag()->num_imports_; }
+  LibraryPtr importer() const { return untag()->importer(); }
 
   LibraryPtr GetLibrary(int index) const;
   void AddImport(const Namespace& import) const;
 
-  bool is_deferred_load() const { return raw_ptr()->is_deferred_load_; }
-  bool is_loaded() const { return raw_ptr()->is_loaded_; }
+  bool is_deferred_load() const { return untag()->is_deferred_load_; }
+  bool is_loaded() const { return untag()->is_loaded_; }
   void set_is_loaded(bool value) const {
-    return StoreNonPointer(&raw_ptr()->is_loaded_, value);
+    return StoreNonPointer(&untag()->is_loaded_, value);
   }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(LibraryPrefixLayout));
+    return RoundedAllocationSize(sizeof(UntaggedLibraryPrefix));
   }
 
   static LibraryPrefixPtr New(const String& name,
@@ -7419,13 +7339,13 @@
   // expects a vector of length [count]. Always true for the null vector.
   bool HasCount(intptr_t count) const;
   static intptr_t length_offset() {
-    return OFFSET_OF(TypeArgumentsLayout, length_);
+    return OFFSET_OF(UntaggedTypeArguments, length_);
   }
   intptr_t Length() const;
   AbstractTypePtr TypeAt(intptr_t index) const;
   AbstractTypePtr TypeAtNullSafe(intptr_t index) const;
   static intptr_t types_offset() {
-    return OFFSET_OF_RETURNED_VALUE(TypeArgumentsLayout, types);
+    return OFFSET_OF_RETURNED_VALUE(UntaggedTypeArguments, types);
   }
   static intptr_t type_at_offset(intptr_t index) {
     return types_offset() + index * kWordSize;
@@ -7462,7 +7382,7 @@
   static const intptr_t kLegacyBits = 2;
   intptr_t nullability() const;
   static intptr_t nullability_offset() {
-    return OFFSET_OF(TypeArgumentsLayout, nullability_);
+    return OFFSET_OF(UntaggedTypeArguments, nullability_);
   }
 
   // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
@@ -7474,12 +7394,10 @@
 
   // Print the internal or public name of a subvector of this type argument
   // vector, e.g. "<T, dynamic, List<T>, int>".
-  void PrintSubvectorName(
-      intptr_t from_index,
-      intptr_t len,
-      NameVisibility name_visibility,
-      BaseTextBuffer* printer,
-      NameDisambiguation name_disambiguation = NameDisambiguation::kNo) const;
+  void PrintSubvectorName(intptr_t from_index,
+                          intptr_t len,
+                          NameVisibility name_visibility,
+                          BaseTextBuffer* printer) const;
   void PrintTo(BaseTextBuffer* printer) const;
 
   // Check if the subvector of length 'len' starting at 'from_index' of this
@@ -7498,6 +7416,15 @@
     return IsDynamicTypes(true, 0, len);
   }
 
+  // Return true if this vector contains a TypeRef.
+  bool IsRecursive(TrailPtr trail = nullptr) const;
+
+  // Return true if this vector contains a non-nullable type.
+  bool RequireConstCanonicalTypeErasure(Zone* zone,
+                                        intptr_t from_index,
+                                        intptr_t len,
+                                        TrailPtr trail = nullptr) const;
+
   TypeArgumentsPtr Prepend(Zone* zone,
                            const TypeArguments& other,
                            intptr_t other_length,
@@ -7555,9 +7482,6 @@
   // Return true if all types of this vector are finalized.
   bool IsFinalized() const;
 
-  // Return true if this vector contains a recursive type argument.
-  bool IsRecursive() const;
-
   // Caller must hold Isolate::constant_canonicalization_mutex_.
   virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
     return Canonicalize(thread, nullptr);
@@ -7611,25 +7535,25 @@
   intptr_t NumInstantiations() const;
 
   static intptr_t instantiations_offset() {
-    return OFFSET_OF(TypeArgumentsLayout, instantiations_);
+    return OFFSET_OF(UntaggedTypeArguments, instantiations_);
   }
 
   static const intptr_t kBytesPerElement = kWordSize;
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(TypeArgumentsLayout) ==
-           OFFSET_OF_RETURNED_VALUE(TypeArgumentsLayout, types));
+    ASSERT(sizeof(UntaggedTypeArguments) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedTypeArguments, types));
     return 0;
   }
 
   static intptr_t InstanceSize(intptr_t len) {
     // Ensure that the types() is not adding to the object size, which includes
     // 4 fields: instantiations_, length_, hash_, and nullability_.
-    ASSERT(sizeof(TypeArgumentsLayout) ==
-           (sizeof(ObjectLayout) + (kNumFields * kWordSize)));
+    ASSERT(sizeof(UntaggedTypeArguments) ==
+           (sizeof(UntaggedObject) + (kNumFields * kWordSize)));
     ASSERT(0 <= len && len <= kMaxElements);
-    return RoundedAllocationSize(sizeof(TypeArgumentsLayout) +
+    return RoundedAllocationSize(sizeof(UntaggedTypeArguments) +
                                  (len * kBytesPerElement));
   }
 
@@ -7713,7 +7637,6 @@
   virtual ClassPtr type_class() const;
   virtual TypeArgumentsPtr arguments() const;
   virtual void set_arguments(const TypeArguments& value) const;
-  virtual TokenPosition token_pos() const;
   virtual bool IsInstantiated(Genericity genericity = kAny,
                               intptr_t num_free_fun_type_params = kAllFree,
                               TrailPtr trail = nullptr) const;
@@ -7727,10 +7650,9 @@
   virtual bool IsEquivalent(const Instance& other,
                             TypeEquality kind,
                             TrailPtr trail = nullptr) const;
-  virtual bool IsRecursive() const;
-
-  // Check if this type represents a function type.
-  virtual bool IsFunctionType() const { return false; }
+  virtual bool IsRecursive(TrailPtr trail = nullptr) const;
+  virtual bool RequireConstCanonicalTypeErasure(Zone* zone,
+                                                TrailPtr trail = nullptr) const;
 
   // Instantiate this type using the given type argument vectors.
   //
@@ -7804,10 +7726,7 @@
 
   // Return the internal or public name of this type, including the names of its
   // type arguments, if any.
-  void PrintName(
-      NameVisibility visibility,
-      BaseTextBuffer* printer,
-      NameDisambiguation name_disambiguation = NameDisambiguation::kNo) const;
+  void PrintName(NameVisibility visibility, BaseTextBuffer* printer) const;
 
   // Add the class name and URI of each occuring type to the uris
   // list and mark ambiguous triplets to be printed.
@@ -7912,16 +7831,24 @@
       const TypeArguments& function_type_args);
 
   static intptr_t type_test_stub_entry_point_offset() {
-    return OFFSET_OF(AbstractTypeLayout, type_test_stub_entry_point_);
+    return OFFSET_OF(UntaggedAbstractType, type_test_stub_entry_point_);
   }
 
   uword type_test_stub_entry_point() const {
-    return raw_ptr()->type_test_stub_entry_point_;
+    return untag()->type_test_stub_entry_point_;
   }
-  CodePtr type_test_stub() const { return raw_ptr()->type_test_stub(); }
+  CodePtr type_test_stub() const { return untag()->type_test_stub(); }
 
   void SetTypeTestingStub(const Code& stub) const;
 
+  // No instances of type AbstractType are allocated, but InstanceSize() and
+  // NextFieldOffset() are required to register class _AbstractType.
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(UntaggedAbstractType));
+  }
+
+  static intptr_t NextFieldOffset() { return -kWordSize; }
+
  private:
   // Returns true if this type is a subtype of FutureOr<T> specified by 'other'.
   // Returns false if other type is not a FutureOr.
@@ -7939,33 +7866,28 @@
 
 // A Type consists of a class, possibly parameterized with type
 // arguments. Example: C<T1, T2>.
-//
-// Caution: 'TypePtr' denotes a 'raw' pointer to a VM object of class Type, as
-// opposed to 'Type' denoting a 'handle' to the same object. 'RawType' does not
-// relate to a 'raw type', as opposed to a 'cooked type' or 'rare type'.
 class Type : public AbstractType {
  public:
   static intptr_t type_class_id_offset() {
-    return OFFSET_OF(TypeLayout, type_class_id_);
+    return OFFSET_OF(UntaggedType, type_class_id_);
   }
   static intptr_t arguments_offset() {
-    return OFFSET_OF(TypeLayout, arguments_);
+    return OFFSET_OF(UntaggedType, arguments_);
   }
   static intptr_t type_state_offset() {
-    return OFFSET_OF(TypeLayout, type_state_);
+    return OFFSET_OF(UntaggedType, type_state_);
   }
-  static intptr_t hash_offset() { return OFFSET_OF(TypeLayout, hash_); }
+  static intptr_t hash_offset() { return OFFSET_OF(UntaggedType, hash_); }
   static intptr_t nullability_offset() {
-    return OFFSET_OF(TypeLayout, nullability_);
+    return OFFSET_OF(UntaggedType, nullability_);
   }
   virtual bool IsFinalized() const {
-    return (raw_ptr()->type_state_ == TypeLayout::kFinalizedInstantiated) ||
-           (raw_ptr()->type_state_ == TypeLayout::kFinalizedUninstantiated);
+    return (untag()->type_state_ == UntaggedType::kFinalizedInstantiated) ||
+           (untag()->type_state_ == UntaggedType::kFinalizedUninstantiated);
   }
   virtual void SetIsFinalized() const;
-  void ResetIsFinalized() const;  // Ignore current state and set again.
   virtual bool IsBeingFinalized() const {
-    return raw_ptr()->type_state_ == TypeLayout::kBeingFinalized;
+    return untag()->type_state_ == UntaggedType::kBeingFinalized;
   }
   virtual void SetIsBeingFinalized() const;
   virtual bool HasTypeClass() const {
@@ -7973,40 +7895,28 @@
     return true;
   }
   virtual Nullability nullability() const {
-    return static_cast<Nullability>(raw_ptr()->nullability_);
+    return static_cast<Nullability>(untag()->nullability_);
   }
   TypePtr ToNullability(Nullability value, Heap::Space space) const;
   virtual classid_t type_class_id() const;
   virtual ClassPtr type_class() const;
   void set_type_class(const Class& value) const;
-  virtual TypeArgumentsPtr arguments() const { return raw_ptr()->arguments(); }
+  virtual TypeArgumentsPtr arguments() const { return untag()->arguments(); }
   virtual void set_arguments(const TypeArguments& value) const;
-  virtual TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
   virtual bool IsInstantiated(Genericity genericity = kAny,
                               intptr_t num_free_fun_type_params = kAllFree,
                               TrailPtr trail = nullptr) const;
   virtual bool IsEquivalent(const Instance& other,
                             TypeEquality kind,
                             TrailPtr trail = nullptr) const;
-  virtual bool IsRecursive() const;
+  virtual bool IsRecursive(TrailPtr trail = nullptr) const;
+  virtual bool RequireConstCanonicalTypeErasure(Zone* zone,
+                                                TrailPtr trail = nullptr) const;
 
   // Return true if this type can be used as the declaration type of cls after
   // canonicalization (passed-in cls must match type_class()).
   bool IsDeclarationTypeOf(const Class& cls) const;
 
-  // If signature is not null, this type represents a function type. Note that
-  // the signature fully represents the type and type arguments can be ignored.
-  // However, in case of a generic typedef, they document how the typedef class
-  // was parameterized to obtain the actual signature.
-  FunctionPtr signature() const;
-  void set_signature(const Function& value) const;
-  static intptr_t signature_offset() {
-    return OFFSET_OF(TypeLayout, signature_);
-  }
-
-  virtual bool IsFunctionType() const {
-    return signature() != Function::null();
-  }
   virtual AbstractTypePtr InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       const TypeArguments& function_type_arguments,
@@ -8024,7 +7934,7 @@
   intptr_t ComputeHash() const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(TypeLayout));
+    return RoundedAllocationSize(sizeof(UntaggedType));
   }
 
   // The type of the literal 'null'.
@@ -8092,18 +8002,16 @@
 
   static TypePtr New(const Class& clazz,
                      const TypeArguments& arguments,
-                     TokenPosition token_pos,
                      Nullability nullability = Nullability::kLegacy,
                      Heap::Space space = Heap::kOld);
 
  private:
   void SetHash(intptr_t value) const;
 
-  void set_token_pos(TokenPosition token_pos) const;
-  void set_type_state(int8_t state) const;
+  void set_type_state(uint8_t state) const;
   void set_nullability(Nullability value) const {
     ASSERT(!IsCanonical());
-    StoreNonPointer(&raw_ptr()->nullability_, static_cast<int8_t>(value));
+    StoreNonPointer(&untag()->nullability_, static_cast<uint8_t>(value));
   }
 
   static TypePtr New(Heap::Space space = Heap::kOld);
@@ -8114,13 +8022,251 @@
   friend class ClearTypeHashVisitor;
 };
 
+// A FunctionType represents the type of a function. It describes most of the
+// signature of a function, excluding the names of type parameters and names
+// of parameters, but includes the names of optional named parameters.
+class FunctionType : public AbstractType {
+ public:
+  static intptr_t type_state_offset() {
+    return OFFSET_OF(UntaggedFunctionType, type_state_);
+  }
+  static intptr_t hash_offset() {
+    return OFFSET_OF(UntaggedFunctionType, hash_);
+  }
+  static intptr_t nullability_offset() {
+    return OFFSET_OF(UntaggedFunctionType, nullability_);
+  }
+  virtual bool IsFinalized() const {
+    return (untag()->type_state_ == UntaggedType::kFinalizedInstantiated) ||
+           (untag()->type_state_ == UntaggedType::kFinalizedUninstantiated);
+  }
+  virtual void SetIsFinalized() const;
+  virtual bool IsBeingFinalized() const {
+    return untag()->type_state_ == UntaggedType::kBeingFinalized;
+  }
+  virtual void SetIsBeingFinalized() const;
+  virtual bool HasTypeClass() const { return false; }
+  virtual Nullability nullability() const {
+    return static_cast<Nullability>(untag()->nullability_);
+  }
+  FunctionTypePtr ToNullability(Nullability value, Heap::Space space) const;
+  virtual classid_t type_class_id() const { return kIllegalCid; }
+  virtual bool IsInstantiated(Genericity genericity = kAny,
+                              intptr_t num_free_fun_type_params = kAllFree,
+                              TrailPtr trail = nullptr) const;
+  virtual bool IsEquivalent(const Instance& other,
+                            TypeEquality kind,
+                            TrailPtr trail = nullptr) const;
+  virtual bool IsRecursive(TrailPtr trail = nullptr) const;
+  virtual bool RequireConstCanonicalTypeErasure(Zone* zone,
+                                                TrailPtr trail = nullptr) const;
+
+  virtual AbstractTypePtr InstantiateFrom(
+      const TypeArguments& instantiator_type_arguments,
+      const TypeArguments& function_type_arguments,
+      intptr_t num_free_fun_type_params,
+      Heap::Space space,
+      TrailPtr trail = nullptr) const;
+  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
+#if defined(DEBUG)
+  // Check if type is canonical.
+  virtual bool CheckIsCanonical(Thread* thread) const;
+#endif  // DEBUG
+  virtual void EnumerateURIs(URIs* uris) const;
+
+  virtual intptr_t Hash() const;
+  intptr_t ComputeHash() const;
+
+  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 UntaggedFunctionType::PackedNumParentTypeArguments::decode(
+        untag()->packed_fields_);
+  }
+  void SetNumParentTypeArguments(intptr_t value) const;
+
+  intptr_t NumTypeArguments() const {
+    return NumParentTypeArguments() + NumTypeParameters();
+  }
+
+  intptr_t num_implicit_parameters() const {
+    return UntaggedFunctionType::PackedNumImplicitParameters::decode(
+        untag()->packed_fields_);
+  }
+  void set_num_implicit_parameters(intptr_t value) const;
+  intptr_t num_fixed_parameters() const {
+    return UntaggedFunctionType::PackedNumFixedParameters::decode(
+        untag()->packed_fields_);
+  }
+  void set_num_fixed_parameters(intptr_t value) const;
+
+  bool HasOptionalParameters() const {
+    return UntaggedFunctionType::PackedNumOptionalParameters::decode(
+               untag()->packed_fields_) > 0;
+  }
+  bool HasOptionalNamedParameters() const {
+    return HasOptionalParameters() &&
+           UntaggedFunctionType::PackedHasNamedOptionalParameters::decode(
+               untag()->packed_fields_);
+  }
+  bool HasOptionalPositionalParameters() const {
+    return HasOptionalParameters() && !HasOptionalNamedParameters();
+  }
+  intptr_t NumOptionalParameters() const {
+    return UntaggedFunctionType::PackedNumOptionalParameters::decode(
+        untag()->packed_fields_);
+  }
+  void SetNumOptionalParameters(intptr_t num_optional_parameters,
+                                bool are_optional_positional) const;
+
+  intptr_t NumOptionalPositionalParameters() const {
+    return HasOptionalPositionalParameters() ? NumOptionalParameters() : 0;
+  }
+
+  intptr_t NumOptionalNamedParameters() const {
+    return HasOptionalNamedParameters() ? NumOptionalParameters() : 0;
+  }
+  uint32_t packed_fields() const { return untag()->packed_fields_; }
+  void set_packed_fields(uint32_t packed_fields) const;
+  static intptr_t packed_fields_offset() {
+    return OFFSET_OF(UntaggedFunctionType, packed_fields_);
+  }
+
+  AbstractTypePtr result_type() const { return untag()->result_type(); }
+  void set_result_type(const AbstractType& value) const;
+
+  // The parameters, starting with NumImplicitParameters() parameters which are
+  // only visible to the VM, but not to Dart users.
+  // Note that type checks exclude implicit parameters.
+  AbstractTypePtr ParameterTypeAt(intptr_t index) const;
+  void SetParameterTypeAt(intptr_t index, const AbstractType& value) const;
+  ArrayPtr parameter_types() const { return untag()->parameter_types(); }
+  void set_parameter_types(const Array& value) const;
+  static intptr_t parameter_types_offset() {
+    return OFFSET_OF(UntaggedFunctionType, parameter_types_);
+  }
+  // Parameter names are valid for all valid parameter indices, and are not
+  // limited to named optional parameters. However, they are meaningless after
+  // canonicalization of the function type. Any particular signature may be
+  // selected as the canonical represent as the names are not part of the type.
+  // If there are parameter flags (eg required) they're stored at the end of
+  // this array, so the size of this array isn't necessarily NumParameters(),
+  // but the first NumParameters() elements are the names.
+  StringPtr ParameterNameAt(intptr_t index) const;
+  void SetParameterNameAt(intptr_t index, const String& value) const;
+  ArrayPtr parameter_names() const { return untag()->parameter_names(); }
+  void set_parameter_names(const Array& value) const;
+
+  // The required flags are stored at the end of the parameter_names. The flags
+  // are packed into SMIs, but omitted if they're 0.
+  bool IsRequiredAt(intptr_t index) const;
+  void SetIsRequiredAt(intptr_t index) const;
+
+  // Sets up the signature's parameter name array, including appropriate space
+  // for any possible parameter flags. This may be an overestimate if some
+  // parameters don't have flags, and so TruncateUnusedParameterFlags() should
+  // be called after all parameter flags have been appropriately set.
+  //
+  // Assumes that the number of fixed and optional parameters for the signature
+  // has already been set.
+  void CreateNameArrayIncludingFlags(Heap::Space space) const;
+
+  // Truncate the parameter names array to remove any unused flag slots. Make
+  // sure to only do this after calling SetIsRequiredAt as necessary.
+  void TruncateUnusedParameterFlags() const;
+
+  // Finalize the name arrays by truncating the parameter name array and copying
+  // the names in the given function.
+  void FinalizeNameArrays(const Function& function) const;
+
+  // Returns the length of the parameter names array that is required to store
+  // all the names plus all their flags. This may be an overestimate if some
+  // parameters don't have flags.
+  static intptr_t NameArrayLengthIncludingFlags(intptr_t num_parameters);
+
+  // The type parameters (and their bounds) are specified as an array of
+  // TypeParameter.
+  TypeArgumentsPtr type_parameters() const {
+    return untag()->type_parameters();
+  }
+  void set_type_parameters(const TypeArguments& value) const;
+  static intptr_t type_parameters_offset() {
+    return OFFSET_OF(UntaggedFunctionType, type_parameters_);
+  }
+  intptr_t NumTypeParameters(Thread* thread) const;
+  intptr_t NumTypeParameters() const {
+    return NumTypeParameters(Thread::Current());
+  }
+
+  // Returns true if this function type has the same number of type parameters
+  // with equal bounds as the other function type. Type parameter names and
+  // parameter names (unless optional named) are ignored.
+  bool HasSameTypeParametersAndBounds(const FunctionType& other,
+                                      TypeEquality kind) const;
+
+  // Return true if this function type declares type parameters.
+  bool IsGeneric() const { return NumTypeParameters(Thread::Current()) > 0; }
+
+  // Return true if any enclosing signature of this signature is generic.
+  bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
+
+  // Returns true if the type of the formal parameter at the given position in
+  // this function type is contravariant with the type of the other formal
+  // parameter at the given position in the other function type.
+  bool IsContravariantParameter(intptr_t parameter_position,
+                                const FunctionType& other,
+                                intptr_t other_parameter_position,
+                                Heap::Space space) const;
+
+  // Returns the index in the parameter names array of the corresponding flag
+  // for the given parametere index. Also returns (via flag_mask) the
+  // corresponding mask within the flag.
+  intptr_t GetRequiredFlagIndex(intptr_t index, intptr_t* flag_mask) const;
+
+  void Print(NameVisibility name_visibility, BaseTextBuffer* printer) const;
+  void PrintParameters(Thread* thread,
+                       Zone* zone,
+                       NameVisibility name_visibility,
+                       BaseTextBuffer* printer) const;
+
+  StringPtr ToUserVisibleString() const;
+  const char* ToUserVisibleCString() const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(UntaggedFunctionType));
+  }
+
+  static FunctionTypePtr New(intptr_t num_parent_type_arguments = 0,
+                             Nullability nullability = Nullability::kLegacy,
+                             Heap::Space space = Heap::kOld);
+
+ private:
+  void SetHash(intptr_t value) const;
+
+  void set_type_state(uint8_t state) const;
+  void set_nullability(Nullability value) const {
+    ASSERT(!IsCanonical());
+    StoreNonPointer(&untag()->nullability_, static_cast<uint8_t>(value));
+  }
+
+  static FunctionTypePtr New(Heap::Space space);
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(FunctionType, AbstractType);
+  friend class Class;
+  friend class ClearTypeHashVisitor;
+  friend class Function;
+};
+
 // A TypeRef is used to break cycles in the representation of recursive types.
 // Its only field is the recursive AbstractType it refers to, which can
 // temporarily be null during finalization.
 // Note that the cycle always involves type arguments.
 class TypeRef : public AbstractType {
  public:
-  static intptr_t type_offset() { return OFFSET_OF(TypeRefLayout, type_); }
+  static intptr_t type_offset() { return OFFSET_OF(UntaggedTypeRef, type_); }
 
   virtual bool IsFinalized() const {
     const AbstractType& ref_type = AbstractType::Handle(type());
@@ -8139,7 +8285,7 @@
     return (type() != AbstractType::null()) &&
            AbstractType::Handle(type()).HasTypeClass();
   }
-  AbstractTypePtr type() const { return raw_ptr()->type(); }
+  AbstractTypePtr type() const { return untag()->type(); }
   void set_type(const AbstractType& value) const;
   virtual classid_t type_class_id() const {
     return AbstractType::Handle(type()).type_class_id();
@@ -8150,20 +8296,15 @@
   virtual TypeArgumentsPtr arguments() const {
     return AbstractType::Handle(type()).arguments();
   }
-  virtual TokenPosition token_pos() const {
-    return AbstractType::Handle(type()).token_pos();
-  }
   virtual bool IsInstantiated(Genericity genericity = kAny,
                               intptr_t num_free_fun_type_params = kAllFree,
                               TrailPtr trail = nullptr) const;
   virtual bool IsEquivalent(const Instance& other,
                             TypeEquality kind,
                             TrailPtr trail = nullptr) const;
-  virtual bool IsRecursive() const { return true; }
-  virtual bool IsFunctionType() const {
-    const AbstractType& ref_type = AbstractType::Handle(type());
-    return !ref_type.IsNull() && ref_type.IsFunctionType();
-  }
+  virtual bool IsRecursive(TrailPtr trail = nullptr) const { return true; }
+  virtual bool RequireConstCanonicalTypeErasure(Zone* zone,
+                                                TrailPtr trail = nullptr) const;
   virtual AbstractTypePtr InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       const TypeArguments& function_type_arguments,
@@ -8180,7 +8321,7 @@
   virtual intptr_t Hash() const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(TypeRefLayout));
+    return RoundedAllocationSize(sizeof(UntaggedTypeRef));
   }
 
   static TypeRefPtr New(const AbstractType& type);
@@ -8205,80 +8346,79 @@
 class TypeParameter : public AbstractType {
  public:
   virtual bool IsFinalized() const {
-    return TypeParameterLayout::FinalizedBit::decode(raw_ptr()->flags_);
+    return UntaggedTypeParameter::FinalizedBit::decode(untag()->flags_);
   }
   virtual void SetIsFinalized() const;
-  virtual bool IsBeingFinalized() const { return false; }
-  static intptr_t flags_offset() {
-    return OFFSET_OF(TypeParameterLayout, flags_);
+  virtual bool IsBeingFinalized() const {
+    return UntaggedTypeParameter::BeingFinalizedBit::decode(untag()->flags_);
   }
+  virtual void SetIsBeingFinalized() const;
   bool IsGenericCovariantImpl() const {
-    return TypeParameterLayout::GenericCovariantImplBit::decode(
-        raw_ptr()->flags_);
+    return UntaggedTypeParameter::GenericCovariantImplBit::decode(
+        untag()->flags_);
   }
   void SetGenericCovariantImpl(bool value) const;
-  bool IsDeclaration() const {
-    return TypeParameterLayout::DeclarationBit::decode(raw_ptr()->flags_);
+  static intptr_t flags_offset() {
+    return OFFSET_OF(UntaggedTypeParameter, flags_);
   }
-  void SetDeclaration(bool value) const;
   static intptr_t nullability_offset() {
-    return OFFSET_OF(TypeParameterLayout, nullability_);
+    return OFFSET_OF(UntaggedTypeParameter, nullability_);
   }
   virtual Nullability nullability() const {
-    return static_cast<Nullability>(raw_ptr()->nullability_);
+    return static_cast<Nullability>(untag()->nullability_);
   }
   TypeParameterPtr ToNullability(Nullability value, Heap::Space space) const;
   virtual bool HasTypeClass() const { return false; }
   virtual classid_t type_class_id() const { return kIllegalCid; }
   classid_t parameterized_class_id() const;
+  void set_parameterized_class_id(classid_t value) const;
   ClassPtr parameterized_class() const;
-  FunctionPtr parameterized_function() const {
-    return raw_ptr()->parameterized_function();
-  }
   bool IsClassTypeParameter() const {
     return parameterized_class_id() != kFunctionCid;
   }
   bool IsFunctionTypeParameter() const {
-    return parameterized_function() != Function::null();
-  }
-  ObjectPtr Owner() const {
-    if (IsClassTypeParameter()) {
-      return parameterized_class();
-    } else {
-      return parameterized_function();
-    }
+    return parameterized_class_id() == kFunctionCid;
   }
 
   static intptr_t parameterized_class_id_offset() {
-    return OFFSET_OF(TypeParameterLayout, parameterized_class_id_);
-  }
-  static intptr_t index_offset() {
-    return OFFSET_OF(TypeParameterLayout, index_);
+    return OFFSET_OF(UntaggedTypeParameter, parameterized_class_id_);
   }
 
-  StringPtr name() const { return raw_ptr()->name(); }
-  static intptr_t name_offset() {
-    return OFFSET_OF(TypeParameterLayout, name_);
-  }
-  intptr_t index() const { return raw_ptr()->index_; }
+  intptr_t base() const { return untag()->base_; }
+  void set_base(intptr_t value) const;
+  intptr_t index() const { return untag()->index_; }
   void set_index(intptr_t value) const;
-  AbstractTypePtr bound() const { return raw_ptr()->bound(); }
+  static intptr_t index_offset() {
+    return OFFSET_OF(UntaggedTypeParameter, index_);
+  }
+
+  StringPtr name() const { return untag()->name(); }
+  static intptr_t name_offset() {
+    return OFFSET_OF(UntaggedTypeParameter, name_);
+  }
+  AbstractTypePtr bound() const { return untag()->bound(); }
   void set_bound(const AbstractType& value) const;
+  static intptr_t bound_offset() {
+    return OFFSET_OF(UntaggedTypeParameter, bound_);
+  }
+
   AbstractTypePtr default_argument() const {
-    return raw_ptr()->default_argument();
+    return untag()->default_argument();
   }
   void set_default_argument(const AbstractType& value) const;
-  static intptr_t bound_offset() {
-    return OFFSET_OF(TypeParameterLayout, bound_);
-  }
-  virtual TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
+
   virtual bool IsInstantiated(Genericity genericity = kAny,
                               intptr_t num_free_fun_type_params = kAllFree,
                               TrailPtr trail = nullptr) const;
   virtual bool IsEquivalent(const Instance& other,
                             TypeEquality kind,
                             TrailPtr trail = nullptr) const;
-  virtual bool IsRecursive() const { return false; }
+  virtual bool IsRecursive(TrailPtr trail = nullptr) const;
+  virtual bool RequireConstCanonicalTypeErasure(
+      Zone* zone,
+      TrailPtr trail = nullptr) const {
+    return IsNonNullable();
+  }
   virtual AbstractTypePtr InstantiateFrom(
       const TypeArguments& instantiator_type_arguments,
       const TypeArguments& function_type_arguments,
@@ -8290,7 +8430,7 @@
   // Check if type parameter is canonical.
   virtual bool CheckIsCanonical(Thread* thread) const;
 #endif  // DEBUG
-  virtual void EnumerateURIs(URIs* uris) const;
+  virtual void EnumerateURIs(URIs* uris) const { return; }
 
   virtual intptr_t Hash() const;
 
@@ -8303,27 +8443,24 @@
       const TypeArguments& function_type_arguments) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(TypeParameterLayout));
+    return RoundedAllocationSize(sizeof(UntaggedTypeParameter));
   }
 
-  // Only one of parameterized_class and parameterized_function is non-null.
+  // 'parameterized_class' is null for a function type parameter.
   static TypeParameterPtr New(const Class& parameterized_class,
-                              const Function& parameterized_function,
+                              intptr_t base,
                               intptr_t index,
                               const String& name,
                               const AbstractType& bound,
                               bool is_generic_covariant_impl,
-                              Nullability nullability,
-                              TokenPosition token_pos);
+                              Nullability nullability);
 
  private:
   intptr_t ComputeHash() const;
   void SetHash(intptr_t value) const;
 
   void set_parameterized_class(const Class& value) const;
-  void set_parameterized_function(const Function& value) const;
   void set_name(const String& value) const;
-  void set_token_pos(TokenPosition token_pos) const;
   void set_flags(uint8_t flags) const;
   void set_nullability(Nullability value) const;
 
@@ -8383,7 +8520,7 @@
   virtual uint32_t CanonicalizeHash() const { return AsTruncatedUint32Value(); }
   virtual bool Equals(const Instance& other) const;
 
-  virtual ObjectPtr HashCode() const { return raw(); }
+  virtual ObjectPtr HashCode() const { return ptr(); }
 
   virtual bool IsZero() const;
   virtual bool IsNegative() const;
@@ -8421,7 +8558,7 @@
       return (raw_value >> kSmiTagShift);
     } else {
       ASSERT(obj->IsMint());
-      return static_cast<const MintPtr>(obj)->ptr()->value_;
+      return static_cast<const MintPtr>(obj)->untag()->value_;
     }
   }
 
@@ -8436,7 +8573,7 @@
   static const intptr_t kMaxValue = kSmiMax;
   static const intptr_t kMinValue = kSmiMin;
 
-  intptr_t Value() const { return RawSmiValue(raw()); }
+  intptr_t Value() const { return RawSmiValue(ptr()); }
 
   virtual bool Equals(const Instance& other) const;
   virtual bool IsZero() const { return Value() == 0; }
@@ -8475,11 +8612,11 @@
   static bool IsValid(int64_t value) { return compiler::target::IsSmi(value); }
 
   void operator=(SmiPtr value) {
-    raw_ = value;
+    ptr_ = value;
     CHECK_HANDLE();
   }
   void operator^=(ObjectPtr value) {
-    raw_ = value;
+    ptr_ = value;
     CHECK_HANDLE();
   }
 
@@ -8519,8 +8656,8 @@
   static const int64_t kMinValue =
       static_cast<int64_t>(DART_2PART_UINT64_C(0x80000000, 00000000));
 
-  int64_t value() const { return raw_ptr()->value_; }
-  static intptr_t value_offset() { return OFFSET_OF(MintLayout, value_); }
+  int64_t value() const { return untag()->value_; }
+  static intptr_t value_offset() { return OFFSET_OF(UntaggedMint, value_); }
 
   virtual bool IsZero() const { return value() == 0; }
   virtual bool IsNegative() const { return value() < 0; }
@@ -8536,7 +8673,7 @@
   virtual int CompareWith(const Integer& other) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(MintLayout));
+    return RoundedAllocationSize(sizeof(UntaggedMint));
   }
 
  protected:
@@ -8560,7 +8697,7 @@
 // abstract class double in corelib.
 class Double : public Number {
  public:
-  double value() const { return raw_ptr()->value_; }
+  double value() const { return untag()->value_; }
 
   bool BitwiseEqualsToDouble(double value) const;
   virtual bool OperatorEquals(const Instance& other) const;
@@ -8581,10 +8718,10 @@
   static DoublePtr NewCanonical(const String& str);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(DoubleLayout));
+    return RoundedAllocationSize(sizeof(UntaggedDouble));
   }
 
-  static intptr_t value_offset() { return OFFSET_OF(DoubleLayout, value_); }
+  static intptr_t value_offset() { return OFFSET_OF(UntaggedDouble, value_); }
 
  private:
   void set_value(double value) const;
@@ -8609,10 +8746,10 @@
 // simple.  We choose a value that will prevent integer overflow for
 // 2 byte strings, since it is the worst case.
 #if defined(HASH_IN_OBJECT_HEADER)
-  static const intptr_t kSizeofRawString = sizeof(InstanceLayout) + kWordSize;
+  static const intptr_t kSizeofRawString = sizeof(UntaggedInstance) + kWordSize;
 #else
   static const intptr_t kSizeofRawString =
-      sizeof(InstanceLayout) + 2 * kWordSize;
+      sizeof(UntaggedInstance) + 2 * kWordSize;
 #endif
   static const intptr_t kMaxElements = kSmiMax / kTwoByteChar;
 
@@ -8647,19 +8784,19 @@
     DISALLOW_IMPLICIT_CONSTRUCTORS(CodePointIterator);
   };
 
-  intptr_t Length() const { return LengthOf(raw()); }
+  intptr_t Length() const { return LengthOf(ptr()); }
   static intptr_t LengthOf(StringPtr obj) {
-    return Smi::Value(obj->ptr()->length());
+    return Smi::Value(obj->untag()->length());
   }
-  static intptr_t length_offset() { return OFFSET_OF(StringLayout, length_); }
+  static intptr_t length_offset() { return OFFSET_OF(UntaggedString, length_); }
 
   intptr_t Hash() const {
-    intptr_t result = GetCachedHash(raw());
+    intptr_t result = GetCachedHash(ptr());
     if (result != 0) {
       return result;
     }
     result = String::Hash(*this, 0, this->Length());
-    SetCachedHash(raw(), result);
+    SetCachedHash(ptr(), result);
     return result;
   }
 
@@ -8667,16 +8804,16 @@
 
   bool HasHash() const {
     ASSERT(Smi::New(0) == nullptr);
-    return GetCachedHash(raw()) != 0;
+    return GetCachedHash(ptr()) != 0;
   }
 
   static intptr_t hash_offset() {
 #if defined(HASH_IN_OBJECT_HEADER)
-    COMPILE_ASSERT(ObjectLayout::kHashTagPos % kBitsPerByte == 0);
-    return OFFSET_OF(ObjectLayout, tags_) +
-           ObjectLayout::kHashTagPos / kBitsPerByte;
+    COMPILE_ASSERT(UntaggedObject::kHashTagPos % kBitsPerByte == 0);
+    return OFFSET_OF(UntaggedObject, tags_) +
+           UntaggedObject::kHashTagPos / kBitsPerByte;
 #else
-    return OFFSET_OF(StringLayout, hash_);
+    return OFFSET_OF(UntaggedString, hash_);
 #endif
   }
   static intptr_t Hash(const String& str, intptr_t begin_index, intptr_t len);
@@ -8684,7 +8821,7 @@
   static intptr_t Hash(const uint16_t* characters, intptr_t len);
   static intptr_t Hash(const int32_t* characters, intptr_t len);
   static intptr_t HashRawSymbol(const StringPtr symbol) {
-    ASSERT(symbol->ptr()->IsCanonical());
+    ASSERT(symbol->untag()->IsCanonical());
     intptr_t result = GetCachedHash(symbol);
     ASSERT(result != 0);
     return result;
@@ -8695,7 +8832,7 @@
 
   virtual ObjectPtr HashCode() const { return Integer::New(Hash()); }
 
-  uint16_t CharAt(intptr_t index) const { return CharAt(raw(), index); }
+  uint16_t CharAt(intptr_t index) const { return CharAt(ptr(), index); }
   static uint16_t CharAt(StringPtr str, intptr_t index);
 
   intptr_t CharSize() const;
@@ -8736,7 +8873,7 @@
 
   bool StartsWith(const String& other) const {
     NoSafepointScope no_safepoint;
-    return StartsWith(raw(), other.raw());
+    return StartsWith(ptr(), other.ptr());
   }
   static bool StartsWith(StringPtr str, StringPtr prefix);
   bool EndsWith(const String& other) const;
@@ -8750,26 +8887,26 @@
   virtual bool CheckIsCanonical(Thread* thread) const;
 #endif  // DEBUG
 
-  bool IsSymbol() const { return raw()->ptr()->IsCanonical(); }
+  bool IsSymbol() const { return ptr()->untag()->IsCanonical(); }
 
   bool IsOneByteString() const {
-    return raw()->GetClassId() == kOneByteStringCid;
+    return ptr()->GetClassId() == kOneByteStringCid;
   }
 
   bool IsTwoByteString() const {
-    return raw()->GetClassId() == kTwoByteStringCid;
+    return ptr()->GetClassId() == kTwoByteStringCid;
   }
 
   bool IsExternalOneByteString() const {
-    return raw()->GetClassId() == kExternalOneByteStringCid;
+    return ptr()->GetClassId() == kExternalOneByteStringCid;
   }
 
   bool IsExternalTwoByteString() const {
-    return raw()->GetClassId() == kExternalTwoByteStringCid;
+    return ptr()->GetClassId() == kExternalTwoByteStringCid;
   }
 
   bool IsExternal() const {
-    return IsExternalStringClassId(raw()->GetClassId());
+    return IsExternalStringClassId(ptr()->GetClassId());
   }
 
   void* GetPeer() const;
@@ -8900,11 +9037,11 @@
 
 #if !defined(HASH_IN_OBJECT_HEADER)
   static uint32_t GetCachedHash(const StringPtr obj) {
-    return Smi::Value(obj->ptr()->hash_);
+    return Smi::Value(obj->untag()->hash_);
   }
 
   static void SetCachedHash(StringPtr obj, uint32_t hash) {
-    obj->ptr()->hash_ = Smi::New(hash);
+    obj->untag()->hash_ = Smi::New(hash);
   }
 #endif
 
@@ -8918,10 +9055,10 @@
   void SetLength(intptr_t value) const {
     // This is only safe because we create a new Smi, which does not cause
     // heap allocation.
-    raw_ptr()->set_length(Smi::New(value));
+    untag()->set_length(Smi::New(value));
   }
 
-  void SetHash(intptr_t value) const { SetCachedHash(raw(), value); }
+  void SetHash(intptr_t value) const { SetCachedHash(ptr(), value); }
 
   template <typename HandleType, typename ElementType, typename CallbackType>
   static void ReadFromImpl(SnapshotReader* reader,
@@ -8943,7 +9080,7 @@
   friend class TwoByteString;
   friend class ExternalOneByteString;
   friend class ExternalTwoByteString;
-  friend class OneByteStringLayout;
+  friend class UntaggedOneByteString;
   friend class RODataSerializationCluster;  // SetHash
   friend class Pass2Visitor;                // Stack "handle"
 };
@@ -8979,13 +9116,13 @@
   static uint16_t CharAt(const String& str, intptr_t index) {
     ASSERT(str.IsOneByteString());
     NoSafepointScope no_safepoint;
-    return OneByteString::CharAt(static_cast<OneByteStringPtr>(str.raw()),
+    return OneByteString::CharAt(static_cast<OneByteStringPtr>(str.ptr()),
                                  index);
   }
 
   static uint16_t CharAt(OneByteStringPtr str, intptr_t index) {
     ASSERT(index >= 0 && index < String::LengthOf(str));
-    return str->ptr()->data()[index];
+    return str->untag()->data()[index];
   }
 
   static void SetCharAt(const String& str, intptr_t index, uint8_t code_unit) {
@@ -8998,22 +9135,22 @@
   static const intptr_t kMaxElements = String::kMaxElements;
 
   static intptr_t data_offset() {
-    return OFFSET_OF_RETURNED_VALUE(OneByteStringLayout, data);
+    return OFFSET_OF_RETURNED_VALUE(UntaggedOneByteString, data);
   }
 
   static intptr_t UnroundedSize(OneByteStringPtr str) {
-    return UnroundedSize(Smi::Value(str->ptr()->length()));
+    return UnroundedSize(Smi::Value(str->untag()->length()));
   }
   static intptr_t UnroundedSize(intptr_t len) {
-    return sizeof(OneByteStringLayout) + (len * kBytesPerElement);
+    return sizeof(UntaggedOneByteString) + (len * kBytesPerElement);
   }
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(OneByteStringLayout) ==
-           OFFSET_OF_RETURNED_VALUE(OneByteStringLayout, data));
+    ASSERT(sizeof(UntaggedOneByteString) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedOneByteString, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
-    ASSERT(sizeof(OneByteStringLayout) == String::kSizeofRawString);
+    ASSERT(sizeof(UntaggedOneByteString) == String::kSizeofRawString);
     ASSERT(0 <= len && len <= kMaxElements);
     return String::RoundedAllocationSize(UnroundedSize(len));
   }
@@ -9078,22 +9215,22 @@
 
  private:
   static OneByteStringPtr raw(const String& str) {
-    return static_cast<OneByteStringPtr>(str.raw());
+    return static_cast<OneByteStringPtr>(str.ptr());
   }
 
-  static const OneByteStringLayout* raw_ptr(const String& str) {
-    return reinterpret_cast<const OneByteStringLayout*>(str.raw_ptr());
+  static const UntaggedOneByteString* untag(const String& str) {
+    return reinterpret_cast<const UntaggedOneByteString*>(str.untag());
   }
 
   static uint8_t* CharAddr(const String& str, intptr_t index) {
     ASSERT((index >= 0) && (index < str.Length()));
     ASSERT(str.IsOneByteString());
-    return &str.UnsafeMutableNonPointer(raw_ptr(str)->data())[index];
+    return &str.UnsafeMutableNonPointer(untag(str)->data())[index];
   }
 
   static uint8_t* DataStart(const String& str) {
     ASSERT(str.IsOneByteString());
-    return &str.UnsafeMutableNonPointer(raw_ptr(str)->data())[0];
+    return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
   }
 
   static OneByteStringPtr ReadFrom(SnapshotReader* reader,
@@ -9117,13 +9254,13 @@
   static uint16_t CharAt(const String& str, intptr_t index) {
     ASSERT(str.IsTwoByteString());
     NoSafepointScope no_safepoint;
-    return TwoByteString::CharAt(static_cast<TwoByteStringPtr>(str.raw()),
+    return TwoByteString::CharAt(static_cast<TwoByteStringPtr>(str.ptr()),
                                  index);
   }
 
   static uint16_t CharAt(TwoByteStringPtr str, intptr_t index) {
     ASSERT(index >= 0 && index < String::LengthOf(str));
-    return str->ptr()->data()[index];
+    return str->untag()->data()[index];
   }
 
   static void SetCharAt(const String& str, intptr_t index, uint16_t ch) {
@@ -9138,21 +9275,21 @@
   static const intptr_t kMaxElements = String::kMaxElements;
 
   static intptr_t data_offset() {
-    return OFFSET_OF_RETURNED_VALUE(TwoByteStringLayout, data);
+    return OFFSET_OF_RETURNED_VALUE(UntaggedTwoByteString, data);
   }
   static intptr_t UnroundedSize(TwoByteStringPtr str) {
-    return UnroundedSize(Smi::Value(str->ptr()->length()));
+    return UnroundedSize(Smi::Value(str->untag()->length()));
   }
   static intptr_t UnroundedSize(intptr_t len) {
-    return sizeof(TwoByteStringLayout) + (len * kBytesPerElement);
+    return sizeof(UntaggedTwoByteString) + (len * kBytesPerElement);
   }
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(TwoByteStringLayout) ==
-           OFFSET_OF_RETURNED_VALUE(TwoByteStringLayout, data));
+    ASSERT(sizeof(UntaggedTwoByteString) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedTwoByteString, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
-    ASSERT(sizeof(TwoByteStringLayout) == String::kSizeofRawString);
+    ASSERT(sizeof(UntaggedTwoByteString) == String::kSizeofRawString);
     ASSERT(0 <= len && len <= kMaxElements);
     return String::RoundedAllocationSize(UnroundedSize(len));
   }
@@ -9198,24 +9335,24 @@
 
  private:
   static TwoByteStringPtr raw(const String& str) {
-    return static_cast<TwoByteStringPtr>(str.raw());
+    return static_cast<TwoByteStringPtr>(str.ptr());
   }
 
-  static const TwoByteStringLayout* raw_ptr(const String& str) {
-    return reinterpret_cast<const TwoByteStringLayout*>(str.raw_ptr());
+  static const UntaggedTwoByteString* untag(const String& str) {
+    return reinterpret_cast<const UntaggedTwoByteString*>(str.untag());
   }
 
   static uint16_t* CharAddr(const String& str, intptr_t index) {
     ASSERT((index >= 0) && (index < str.Length()));
     ASSERT(str.IsTwoByteString());
-    return &str.UnsafeMutableNonPointer(raw_ptr(str)->data())[index];
+    return &str.UnsafeMutableNonPointer(untag(str)->data())[index];
   }
 
   // Use this instead of CharAddr(0).  It will not assert that the index is <
   // length.
   static uint16_t* DataStart(const String& str) {
     ASSERT(str.IsTwoByteString());
-    return &str.UnsafeMutableNonPointer(raw_ptr(str)->data())[0];
+    return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
   }
 
   static TwoByteStringPtr ReadFrom(SnapshotReader* reader,
@@ -9238,18 +9375,18 @@
     ASSERT(str.IsExternalOneByteString());
     NoSafepointScope no_safepoint;
     return ExternalOneByteString::CharAt(
-        static_cast<ExternalOneByteStringPtr>(str.raw()), index);
+        static_cast<ExternalOneByteStringPtr>(str.ptr()), index);
   }
 
   static uint16_t CharAt(ExternalOneByteStringPtr str, intptr_t index) {
     ASSERT(index >= 0 && index < String::LengthOf(str));
-    return str->ptr()->external_data_[index];
+    return str->untag()->external_data_[index];
   }
 
-  static void* GetPeer(const String& str) { return raw_ptr(str)->peer_; }
+  static void* GetPeer(const String& str) { return untag(str)->peer_; }
 
   static intptr_t external_data_offset() {
-    return OFFSET_OF(ExternalOneByteStringLayout, external_data_);
+    return OFFSET_OF(UntaggedExternalOneByteString, external_data_);
   }
 
   // We use the same maximum elements for all strings.
@@ -9257,7 +9394,7 @@
   static const intptr_t kMaxElements = String::kMaxElements;
 
   static intptr_t InstanceSize() {
-    return String::RoundedAllocationSize(sizeof(ExternalOneByteStringLayout));
+    return String::RoundedAllocationSize(sizeof(UntaggedExternalOneByteString));
   }
 
   static ExternalOneByteStringPtr New(const uint8_t* characters,
@@ -9279,32 +9416,32 @@
 
  private:
   static ExternalOneByteStringPtr raw(const String& str) {
-    return static_cast<ExternalOneByteStringPtr>(str.raw());
+    return static_cast<ExternalOneByteStringPtr>(str.ptr());
   }
 
-  static const ExternalOneByteStringLayout* raw_ptr(const String& str) {
-    return reinterpret_cast<const ExternalOneByteStringLayout*>(str.raw_ptr());
+  static const UntaggedExternalOneByteString* untag(const String& str) {
+    return reinterpret_cast<const UntaggedExternalOneByteString*>(str.untag());
   }
 
   static const uint8_t* CharAddr(const String& str, intptr_t index) {
     ASSERT((index >= 0) && (index < str.Length()));
     ASSERT(str.IsExternalOneByteString());
-    return &(raw_ptr(str)->external_data_[index]);
+    return &(untag(str)->external_data_[index]);
   }
 
   static const uint8_t* DataStart(const String& str) {
     ASSERT(str.IsExternalOneByteString());
-    return raw_ptr(str)->external_data_;
+    return untag(str)->external_data_;
   }
 
   static void SetExternalData(const String& str,
                               const uint8_t* data,
                               void* peer) {
     ASSERT(str.IsExternalOneByteString());
-    ASSERT(
-        !Isolate::Current()->heap()->Contains(reinterpret_cast<uword>(data)));
-    str.StoreNonPointer(&raw_ptr(str)->external_data_, data);
-    str.StoreNonPointer(&raw_ptr(str)->peer_, peer);
+    ASSERT(!IsolateGroup::Current()->heap()->Contains(
+        reinterpret_cast<uword>(data)));
+    str.StoreNonPointer(&untag(str)->external_data_, data);
+    str.StoreNonPointer(&untag(str)->peer_, peer);
   }
 
   static void Finalize(void* isolate_callback_data,
@@ -9336,18 +9473,18 @@
     ASSERT(str.IsExternalTwoByteString());
     NoSafepointScope no_safepoint;
     return ExternalTwoByteString::CharAt(
-        static_cast<ExternalTwoByteStringPtr>(str.raw()), index);
+        static_cast<ExternalTwoByteStringPtr>(str.ptr()), index);
   }
 
   static uint16_t CharAt(ExternalTwoByteStringPtr str, intptr_t index) {
     ASSERT(index >= 0 && index < String::LengthOf(str));
-    return str->ptr()->external_data_[index];
+    return str->untag()->external_data_[index];
   }
 
-  static void* GetPeer(const String& str) { return raw_ptr(str)->peer_; }
+  static void* GetPeer(const String& str) { return untag(str)->peer_; }
 
   static intptr_t external_data_offset() {
-    return OFFSET_OF(ExternalTwoByteStringLayout, external_data_);
+    return OFFSET_OF(UntaggedExternalTwoByteString, external_data_);
   }
 
   // We use the same maximum elements for all strings.
@@ -9355,7 +9492,7 @@
   static const intptr_t kMaxElements = String::kMaxElements;
 
   static intptr_t InstanceSize() {
-    return String::RoundedAllocationSize(sizeof(ExternalTwoByteStringLayout));
+    return String::RoundedAllocationSize(sizeof(UntaggedExternalTwoByteString));
   }
 
   static ExternalTwoByteStringPtr New(const uint16_t* characters,
@@ -9373,32 +9510,32 @@
 
  private:
   static ExternalTwoByteStringPtr raw(const String& str) {
-    return static_cast<ExternalTwoByteStringPtr>(str.raw());
+    return static_cast<ExternalTwoByteStringPtr>(str.ptr());
   }
 
-  static const ExternalTwoByteStringLayout* raw_ptr(const String& str) {
-    return reinterpret_cast<const ExternalTwoByteStringLayout*>(str.raw_ptr());
+  static const UntaggedExternalTwoByteString* untag(const String& str) {
+    return reinterpret_cast<const UntaggedExternalTwoByteString*>(str.untag());
   }
 
   static const uint16_t* CharAddr(const String& str, intptr_t index) {
     ASSERT((index >= 0) && (index < str.Length()));
     ASSERT(str.IsExternalTwoByteString());
-    return &(raw_ptr(str)->external_data_[index]);
+    return &(untag(str)->external_data_[index]);
   }
 
   static const uint16_t* DataStart(const String& str) {
     ASSERT(str.IsExternalTwoByteString());
-    return raw_ptr(str)->external_data_;
+    return untag(str)->external_data_;
   }
 
   static void SetExternalData(const String& str,
                               const uint16_t* data,
                               void* peer) {
     ASSERT(str.IsExternalTwoByteString());
-    ASSERT(
-        !Isolate::Current()->heap()->Contains(reinterpret_cast<uword>(data)));
-    str.StoreNonPointer(&raw_ptr(str)->external_data_, data);
-    str.StoreNonPointer(&raw_ptr(str)->peer_, peer);
+    ASSERT(!IsolateGroup::Current()->heap()->Contains(
+        reinterpret_cast<uword>(data)));
+    str.StoreNonPointer(&untag(str)->external_data_, data);
+    str.StoreNonPointer(&untag(str)->peer_, peer);
   }
 
   static void Finalize(void* isolate_callback_data,
@@ -9426,10 +9563,10 @@
 // Class Bool implements Dart core class bool.
 class Bool : public Instance {
  public:
-  bool value() const { return raw_ptr()->value_; }
+  bool value() const { return untag()->value_; }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(BoolLayout));
+    return RoundedAllocationSize(sizeof(UntaggedBool));
   }
 
   static const Bool& True() { return Object::bool_true(); }
@@ -9441,13 +9578,11 @@
   }
 
   virtual uint32_t CanonicalizeHash() const {
-    return raw() == True().raw() ? 1231 : 1237;
+    return ptr() == True().ptr() ? 1231 : 1237;
   }
 
  private:
-  void set_value(bool value) const {
-    StoreNonPointer(&raw_ptr()->value_, value);
-  }
+  void set_value(bool value) const { StoreNonPointer(&untag()->value_, value); }
 
   // New should only be called to initialize the two legal bool values.
   static BoolPtr New(bool value);
@@ -9469,17 +9604,17 @@
     return Array::InstanceSize(array_length) > Heap::kNewAllocatableSize;
   }
 
-  intptr_t Length() const { return LengthOf(raw()); }
+  intptr_t Length() const { return LengthOf(ptr()); }
   static intptr_t LengthOf(const ArrayPtr array) {
-    return Smi::Value(array->ptr()->length());
+    return Smi::Value(array->untag()->length());
   }
 
-  static intptr_t length_offset() { return OFFSET_OF(ArrayLayout, length_); }
+  static intptr_t length_offset() { return OFFSET_OF(UntaggedArray, length_); }
   static intptr_t data_offset() {
-    return OFFSET_OF_RETURNED_VALUE(ArrayLayout, data);
+    return OFFSET_OF_RETURNED_VALUE(UntaggedArray, data);
   }
   static intptr_t element_offset(intptr_t index) {
-    return OFFSET_OF_RETURNED_VALUE(ArrayLayout, data) + kWordSize * index;
+    return OFFSET_OF_RETURNED_VALUE(UntaggedArray, data) + kWordSize * index;
   }
   static intptr_t index_at_offset(intptr_t offset_in_bytes) {
     intptr_t index = (offset_in_bytes - data_offset()) / kWordSize;
@@ -9496,39 +9631,41 @@
   static bool Equals(ArrayPtr a, ArrayPtr b) {
     if (a == b) return true;
     if (a->IsRawNull() || b->IsRawNull()) return false;
-    if (a->ptr()->length() != b->ptr()->length()) return false;
-    if (a->ptr()->type_arguments() != b->ptr()->type_arguments()) return false;
+    if (a->untag()->length() != b->untag()->length()) return false;
+    if (a->untag()->type_arguments() != b->untag()->type_arguments())
+      return false;
     const intptr_t length = LengthOf(a);
-    return memcmp(a->ptr()->data(), b->ptr()->data(), kWordSize * length) == 0;
+    return memcmp(a->untag()->data(), b->untag()->data(), kWordSize * length) ==
+           0;
   }
 
-  static ObjectPtr* DataOf(ArrayPtr array) { return array->ptr()->data(); }
+  static ObjectPtr* DataOf(ArrayPtr array) { return array->untag()->data(); }
 
   template <std::memory_order order = std::memory_order_relaxed>
   ObjectPtr At(intptr_t index) const {
-    return raw_ptr()->element(index);
+    return untag()->element(index);
   }
   template <std::memory_order order = std::memory_order_relaxed>
   void SetAt(intptr_t index, const Object& value) const {
     // TODO(iposva): Add storing NoSafepointScope.
-    raw_ptr()->set_element(index, value.raw());
+    untag()->set_element(index, value.ptr());
   }
 
   // Access to the array with acquire release semantics.
   ObjectPtr AtAcquire(intptr_t index) const {
-    return raw_ptr()->element<std::memory_order_acquire>(index);
+    return untag()->element<std::memory_order_acquire>(index);
   }
   void SetAtRelease(intptr_t index, const Object& value) const {
-    raw_ptr()->set_element<std::memory_order_release>(index, value.raw());
+    untag()->set_element<std::memory_order_release>(index, value.ptr());
   }
 
-  bool IsImmutable() const { return raw()->GetClassId() == kImmutableArrayCid; }
+  bool IsImmutable() const { return ptr()->GetClassId() == kImmutableArrayCid; }
 
   // Position of element type in type arguments.
   static const intptr_t kElementTypeTypeArgPos = 0;
 
   virtual TypeArgumentsPtr GetTypeArguments() const {
-    return raw_ptr()->type_arguments();
+    return untag()->type_arguments();
   }
   virtual void SetTypeArguments(const TypeArguments& value) const {
     // An Array is raw or takes one type argument. However, its type argument
@@ -9539,7 +9676,7 @@
             value.IsInstantiated() /*&& value.IsCanonical()*/));
     // TODO(asiva): Values read from a message snapshot are not properly marked
     // as canonical. See for example tests/isolate/mandel_isolate_test.dart.
-    StoreArrayPointer(&raw_ptr()->type_arguments_, value.raw());
+    StoreArrayPointer(&untag()->type_arguments_, value.ptr());
   }
 
   virtual bool CanonicalizeEquals(const Instance& other) const;
@@ -9548,10 +9685,10 @@
   static const intptr_t kBytesPerElement = kWordSize;
   static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
   static const intptr_t kMaxNewSpaceElements =
-      (Heap::kNewAllocatableSize - sizeof(ArrayLayout)) / kBytesPerElement;
+      (Heap::kNewAllocatableSize - sizeof(UntaggedArray)) / kBytesPerElement;
 
   static intptr_t type_arguments_offset() {
-    return OFFSET_OF(ArrayLayout, type_arguments_);
+    return OFFSET_OF(UntaggedArray, type_arguments_);
   }
 
   static bool IsValidLength(intptr_t len) {
@@ -9559,15 +9696,17 @@
   }
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(ArrayLayout) == OFFSET_OF_RETURNED_VALUE(ArrayLayout, data));
+    ASSERT(sizeof(UntaggedArray) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedArray, data));
     return 0;
   }
 
   static intptr_t InstanceSize(intptr_t len) {
     // Ensure that variable length data is not adding to the object length.
-    ASSERT(sizeof(ArrayLayout) == (sizeof(InstanceLayout) + (2 * kWordSize)));
+    ASSERT(sizeof(UntaggedArray) ==
+           (sizeof(UntaggedInstance) + (2 * kWordSize)));
     ASSERT(IsValidLength(len));
-    return RoundedAllocationSize(sizeof(ArrayLayout) +
+    return RoundedAllocationSize(sizeof(UntaggedArray) +
                                  (len * kBytesPerElement));
   }
 
@@ -9617,19 +9756,17 @@
   ObjectPtr const* ObjectAddr(intptr_t index) const {
     // TODO(iposva): Determine if we should throw an exception here.
     ASSERT((index >= 0) && (index < Length()));
-    return &raw_ptr()->data()[index];
+    return &untag()->data()[index];
   }
 
-  void SetLength(intptr_t value) const {
-    raw_ptr()->set_length(Smi::New(value));
-  }
+  void SetLength(intptr_t value) const { untag()->set_length(Smi::New(value)); }
   void SetLengthRelease(intptr_t value) const {
-    raw_ptr()->set_length<std::memory_order_release>(Smi::New(value));
+    untag()->set_length<std::memory_order_release>(Smi::New(value));
   }
 
   template <typename type, std::memory_order order = std::memory_order_relaxed>
   void StoreArrayPointer(type const* addr, type value) const {
-    raw()->ptr()->StoreArrayPointer<type, order>(addr, value);
+    ptr()->untag()->StoreArrayPointer<type, order>(addr, value);
   }
 
   // Store a range of pointers [from, from + count) into [to, to + count).
@@ -9638,7 +9775,7 @@
                           ObjectPtr const* from,
                           intptr_t count) {
     ASSERT(Contains(reinterpret_cast<uword>(to)));
-    if (raw()->IsNewObject()) {
+    if (ptr()->IsNewObject()) {
       memmove(const_cast<ObjectPtr*>(to), from, count * kWordSize);
     } else {
       for (intptr_t i = 0; i < count; ++i) {
@@ -9679,7 +9816,7 @@
   }
 
   static ImmutableArrayPtr raw(const Array& array) {
-    return static_cast<ImmutableArrayPtr>(array.raw());
+    return static_cast<ImmutableArrayPtr>(array.ptr());
   }
 
   friend class Class;
@@ -9694,29 +9831,29 @@
   }
   intptr_t Length() const {
     ASSERT(!IsNull());
-    return Smi::Value(raw_ptr()->length());
+    return Smi::Value(untag()->length());
   }
   void SetLength(intptr_t value) const {
     // This is only safe because we create a new Smi, which does not cause
     // heap allocation.
-    raw_ptr()->set_length(Smi::New(value));
+    untag()->set_length(Smi::New(value));
   }
 
-  ArrayPtr data() const { return raw_ptr()->data(); }
-  void SetData(const Array& value) const { raw_ptr()->set_data(value.raw()); }
+  ArrayPtr data() const { return untag()->data(); }
+  void SetData(const Array& value) const { untag()->set_data(value.ptr()); }
 
   ObjectPtr At(intptr_t index) const {
     NoSafepointScope no_safepoint;
     ASSERT(!IsNull());
     ASSERT(index < Length());
-    return data()->ptr()->element(index);
+    return data()->untag()->element(index);
   }
   void SetAt(intptr_t index, const Object& value) const {
     ASSERT(!IsNull());
     ASSERT(index < Length());
 
     // TODO(iposva): Add storing NoSafepointScope.
-    data()->ptr()->set_element(index, value.raw());
+    data()->untag()->set_element(index, value.ptr());
   }
 
   void Add(const Object& value, Heap::Space space = Heap::kNew) const;
@@ -9725,7 +9862,7 @@
   ObjectPtr RemoveLast() const;
 
   virtual TypeArgumentsPtr GetTypeArguments() const {
-    return raw_ptr()->type_arguments();
+    return untag()->type_arguments();
   }
   virtual void SetTypeArguments(const TypeArguments& value) const {
     // A GrowableObjectArray is raw or takes one type argument. However, its
@@ -9733,7 +9870,8 @@
     // reusing the type argument vector of the instantiator.
     ASSERT(value.IsNull() || ((value.Length() >= 1) && value.IsInstantiated() &&
                               value.IsCanonical()));
-    raw_ptr()->set_type_arguments(value.raw());
+
+    untag()->set_type_arguments(value.ptr());
   }
 
   // We don't expect a growable object array to be canonicalized.
@@ -9749,18 +9887,18 @@
   }
 
   static intptr_t type_arguments_offset() {
-    return OFFSET_OF(GrowableObjectArrayLayout, type_arguments_);
+    return OFFSET_OF(UntaggedGrowableObjectArray, type_arguments_);
   }
 
   static intptr_t length_offset() {
-    return OFFSET_OF(GrowableObjectArrayLayout, length_);
+    return OFFSET_OF(UntaggedGrowableObjectArray, length_);
   }
   static intptr_t data_offset() {
-    return OFFSET_OF(GrowableObjectArrayLayout, data_);
+    return OFFSET_OF(UntaggedGrowableObjectArray, data_);
   }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(GrowableObjectArrayLayout));
+    return RoundedAllocationSize(sizeof(UntaggedGrowableObjectArray));
   }
 
   static GrowableObjectArrayPtr New(Heap::Space space = Heap::kNew) {
@@ -9772,15 +9910,15 @@
                                     Heap::Space space = Heap::kNew);
 
   static SmiPtr NoSafepointLength(const GrowableObjectArrayPtr array) {
-    return array->ptr()->length();
+    return array->untag()->length();
   }
 
   static ArrayPtr NoSafepointData(const GrowableObjectArrayPtr array) {
-    return array->ptr()->data();
+    return array->untag()->data();
   }
 
  private:
-  ArrayLayout* DataArray() const { return data()->ptr(); }
+  UntaggedArray* DataArray() const { return data()->untag(); }
 
   static const int kDefaultInitialCapacity = 0;
 
@@ -9813,10 +9951,12 @@
   void set_value(simd128_value_t value) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(Float32x4Layout));
+    return RoundedAllocationSize(sizeof(UntaggedFloat32x4));
   }
 
-  static intptr_t value_offset() { return OFFSET_OF(Float32x4Layout, value_); }
+  static intptr_t value_offset() {
+    return OFFSET_OF(UntaggedFloat32x4, value_);
+  }
 
  private:
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Float32x4, Instance);
@@ -9846,10 +9986,10 @@
   void set_value(simd128_value_t value) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(Int32x4Layout));
+    return RoundedAllocationSize(sizeof(UntaggedInt32x4));
   }
 
-  static intptr_t value_offset() { return OFFSET_OF(Int32x4Layout, value_); }
+  static intptr_t value_offset() { return OFFSET_OF(UntaggedInt32x4, value_); }
 
  private:
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Int32x4, Instance);
@@ -9874,10 +10014,12 @@
   void set_value(simd128_value_t value) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(Float64x2Layout));
+    return RoundedAllocationSize(sizeof(UntaggedFloat64x2));
   }
 
-  static intptr_t value_offset() { return OFFSET_OF(Float64x2Layout, value_); }
+  static intptr_t value_offset() {
+    return OFFSET_OF(UntaggedFloat64x2, value_);
+  }
 
  private:
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Float64x2, Instance);
@@ -9887,33 +10029,33 @@
 class PointerBase : public Instance {
  public:
   static intptr_t data_field_offset() {
-    return OFFSET_OF(PointerBaseLayout, data_);
+    return OFFSET_OF(UntaggedPointerBase, data_);
   }
 };
 
 class TypedDataBase : public PointerBase {
  public:
   static intptr_t length_offset() {
-    return OFFSET_OF(TypedDataBaseLayout, length_);
+    return OFFSET_OF(UntaggedTypedDataBase, length_);
   }
 
-  SmiPtr length() const { return raw_ptr()->length(); }
+  SmiPtr length() const { return untag()->length(); }
 
   intptr_t Length() const {
     ASSERT(!IsNull());
-    return Smi::Value(raw_ptr()->length());
+    return Smi::Value(untag()->length());
   }
 
   intptr_t LengthInBytes() const {
-    return ElementSizeInBytes(raw()->GetClassId()) * Length();
+    return ElementSizeInBytes(ptr()->GetClassId()) * Length();
   }
 
   TypedDataElementType ElementType() const {
-    return ElementType(raw()->GetClassId());
+    return ElementType(ptr()->GetClassId());
   }
 
   intptr_t ElementSizeInBytes() const {
-    return element_size(ElementType(raw()->GetClassId()));
+    return element_size(ElementType(ptr()->GetClassId()));
   }
 
   static intptr_t ElementSizeInBytes(classid_t cid) {
@@ -9942,13 +10084,13 @@
   void* DataAddr(intptr_t byte_offset) const {
     ASSERT((byte_offset == 0) ||
            ((byte_offset > 0) && (byte_offset < LengthInBytes())));
-    return reinterpret_cast<void*>(Validate(raw_ptr()->data_) + byte_offset);
+    return reinterpret_cast<void*>(Validate(untag()->data_) + byte_offset);
   }
 
  protected:
   void SetLength(intptr_t value) const {
     ASSERT(value <= Smi::kMaxValue);
-    raw_ptr()->set_length(Smi::New(value));
+    untag()->set_length(Smi::New(value));
   }
 
   virtual uint8_t* Validate(uint8_t* data) const {
@@ -10009,17 +10151,17 @@
 
 #undef TYPED_GETTER_SETTER
 
-  static intptr_t data_offset() { return TypedDataLayout::payload_offset(); }
+  static intptr_t data_offset() { return UntaggedTypedData::payload_offset(); }
 
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(TypedDataLayout) ==
-           OFFSET_OF_RETURNED_VALUE(TypedDataLayout, internal_data));
+    ASSERT(sizeof(UntaggedTypedData) ==
+           OFFSET_OF_RETURNED_VALUE(UntaggedTypedData, internal_data));
     return 0;
   }
 
   static intptr_t InstanceSize(intptr_t lengthInBytes) {
     ASSERT(0 <= lengthInBytes && lengthInBytes <= kSmiMax);
-    return RoundedAllocationSize(sizeof(TypedDataLayout) + lengthInBytes);
+    return RoundedAllocationSize(sizeof(UntaggedTypedData) + lengthInBytes);
   }
 
   static intptr_t MaxElements(intptr_t class_id) {
@@ -10029,7 +10171,7 @@
 
   static intptr_t MaxNewSpaceElements(intptr_t class_id) {
     ASSERT(IsTypedDataClassId(class_id));
-    return (Heap::kNewAllocatableSize - sizeof(TypedDataLayout)) /
+    return (Heap::kNewAllocatableSize - sizeof(UntaggedTypedData)) /
            ElementSizeInBytes(class_id);
   }
 
@@ -10086,12 +10228,12 @@
 
   static bool IsTypedData(const Instance& obj) {
     ASSERT(!obj.IsNull());
-    intptr_t cid = obj.raw()->GetClassId();
+    intptr_t cid = obj.ptr()->GetClassId();
     return IsTypedDataClassId(cid);
   }
 
  protected:
-  void RecomputeDataField() { raw()->ptr()->RecomputeDataField(); }
+  void RecomputeDataField() { ptr()->untag()->RecomputeDataField(); }
 
  private:
   // Provides const access to non-pointer, non-aligned data within the object.
@@ -10102,8 +10244,7 @@
   // ensure the returned pointer does not escape.
   template <typename FieldType>
   const FieldType* ReadOnlyDataAddr(intptr_t byte_offset) const {
-    return reinterpret_cast<const FieldType*>((raw_ptr()->data()) +
-                                              byte_offset);
+    return reinterpret_cast<const FieldType*>((untag()->data()) + byte_offset);
   }
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedData, TypedDataBase);
@@ -10146,11 +10287,11 @@
                                             intptr_t external_size) const;
 
   static intptr_t data_offset() {
-    return OFFSET_OF(ExternalTypedDataLayout, data_);
+    return OFFSET_OF(UntaggedExternalTypedData, data_);
   }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ExternalTypedDataLayout));
+    return RoundedAllocationSize(sizeof(UntaggedExternalTypedData));
   }
 
   static intptr_t MaxElements(intptr_t class_id) {
@@ -10169,7 +10310,7 @@
 
   static bool IsExternalTypedData(const Instance& obj) {
     ASSERT(!obj.IsNull());
-    intptr_t cid = obj.raw()->GetClassId();
+    intptr_t cid = obj.ptr()->GetClassId();
     return IsExternalTypedDataClassId(cid);
   }
 
@@ -10178,13 +10319,13 @@
 
   void SetLength(intptr_t value) const {
     ASSERT(value <= Smi::kMaxValue);
-    raw_ptr()->set_length(Smi::New(value));
+    untag()->set_length(Smi::New(value));
   }
 
   void SetData(uint8_t* data) const {
-    ASSERT(
-        !Isolate::Current()->heap()->Contains(reinterpret_cast<uword>(data)));
-    StoreNonPointer(&raw_ptr()->data_, data);
+    ASSERT(!IsolateGroup::Current()->heap()->Contains(
+        reinterpret_cast<uword>(data)));
+    StoreNonPointer(&untag()->data_, data);
   }
 
  private:
@@ -10203,7 +10344,7 @@
                               Heap::Space space = Heap::kNew);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(TypedDataViewLayout));
+    return RoundedAllocationSize(sizeof(UntaggedTypedDataView));
   }
 
   static InstancePtr Data(const TypedDataView& view) {
@@ -10216,47 +10357,47 @@
 
   static bool IsExternalTypedDataView(const TypedDataView& view_obj) {
     const auto& data = Instance::Handle(Data(view_obj));
-    intptr_t cid = data.raw()->GetClassId();
+    intptr_t cid = data.ptr()->GetClassId();
     ASSERT(IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid));
     return IsExternalTypedDataClassId(cid);
   }
 
   static intptr_t data_offset() {
-    return OFFSET_OF(TypedDataViewLayout, typed_data_);
+    return OFFSET_OF(UntaggedTypedDataView, typed_data_);
   }
 
   static intptr_t offset_in_bytes_offset() {
-    return OFFSET_OF(TypedDataViewLayout, offset_in_bytes_);
+    return OFFSET_OF(UntaggedTypedDataView, offset_in_bytes_);
   }
 
-  InstancePtr typed_data() const { return raw_ptr()->typed_data(); }
+  InstancePtr typed_data() const { return untag()->typed_data(); }
 
   void InitializeWith(const TypedDataBase& typed_data,
                       intptr_t offset_in_bytes,
                       intptr_t length) {
     const classid_t cid = typed_data.GetClassId();
     ASSERT(IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid));
-    raw_ptr()->set_typed_data(typed_data.raw());
-    raw_ptr()->set_length(Smi::New(length));
-    raw_ptr()->set_offset_in_bytes(Smi::New(offset_in_bytes));
+    untag()->set_typed_data(typed_data.ptr());
+    untag()->set_length(Smi::New(length));
+    untag()->set_offset_in_bytes(Smi::New(offset_in_bytes));
 
     // Update the inner pointer.
     RecomputeDataField();
   }
 
-  SmiPtr offset_in_bytes() const { return raw_ptr()->offset_in_bytes(); }
+  SmiPtr offset_in_bytes() const { return untag()->offset_in_bytes(); }
 
  protected:
   virtual uint8_t* Validate(uint8_t* data) const { return data; }
 
  private:
-  void RecomputeDataField() { raw()->ptr()->RecomputeDataField(); }
+  void RecomputeDataField() { ptr()->untag()->RecomputeDataField(); }
 
   void Clear() {
-    raw_ptr()->set_length(Smi::New(0));
-    raw_ptr()->set_offset_in_bytes(Smi::New(0));
-    StoreNonPointer(&raw_ptr()->data_, nullptr);
-    raw_ptr()->set_typed_data(TypedDataBase::RawCast(Object::null()));
+    untag()->set_length(Smi::New(0));
+    untag()->set_offset_in_bytes(Smi::New(0));
+    StoreNonPointer(&untag()->data_, nullptr);
+    untag()->set_typed_data(TypedDataBase::RawCast(Object::null()));
   }
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedDataView, TypedDataBase);
@@ -10269,7 +10410,7 @@
  public:
   static InstancePtr Data(const Instance& view_obj) {
     ASSERT(!view_obj.IsNull());
-    return *reinterpret_cast<InstancePtr const*>(view_obj.raw_ptr() +
+    return *reinterpret_cast<InstancePtr const*>(view_obj.untag() +
                                                  kDataOffset);
   }
 
@@ -10290,25 +10431,25 @@
                         Heap::Space space = Heap::kNew);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(PointerLayout));
+    return RoundedAllocationSize(sizeof(UntaggedPointer));
   }
 
   static bool IsPointer(const Instance& obj);
 
   size_t NativeAddress() const {
-    return reinterpret_cast<size_t>(raw_ptr()->data_);
+    return reinterpret_cast<size_t>(untag()->data_);
   }
 
   void SetNativeAddress(size_t address) const {
     uint8_t* value = reinterpret_cast<uint8_t*>(address);
-    StoreNonPointer(&raw_ptr()->data_, value);
+    StoreNonPointer(&untag()->data_, value);
   }
 
   static intptr_t type_arguments_offset() {
-    return OFFSET_OF(PointerLayout, type_arguments_);
+    return OFFSET_OF(UntaggedPointer, type_arguments_);
   }
 
-  static intptr_t NextFieldOffset() { return sizeof(PointerLayout); }
+  static intptr_t NextFieldOffset() { return sizeof(UntaggedPointer); }
 
   static const intptr_t kNativeTypeArgPos = 0;
 
@@ -10329,22 +10470,22 @@
   static DynamicLibraryPtr New(void* handle, Heap::Space space = Heap::kNew);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(DynamicLibraryLayout));
+    return RoundedAllocationSize(sizeof(UntaggedDynamicLibrary));
   }
 
   static bool IsDynamicLibrary(const Instance& obj) {
     ASSERT(!obj.IsNull());
-    intptr_t cid = obj.raw()->GetClassId();
+    intptr_t cid = obj.ptr()->GetClassId();
     return IsFfiDynamicLibraryClassId(cid);
   }
 
   void* GetHandle() const {
     ASSERT(!IsNull());
-    return raw_ptr()->handle_;
+    return untag()->handle_;
   }
 
   void SetHandle(void* value) const {
-    StoreNonPointer(&raw_ptr()->handle_, value);
+    StoreNonPointer(&untag()->handle_, value);
   }
 
  private:
@@ -10360,7 +10501,7 @@
 class LinkedHashMap : public Instance {
  public:
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(LinkedHashMapLayout));
+    return RoundedAllocationSize(sizeof(UntaggedLinkedHashMap));
   }
 
   // Allocates a map with some default capacity, just like "new Map()".
@@ -10373,7 +10514,7 @@
                               Heap::Space space = Heap::kNew);
 
   virtual TypeArgumentsPtr GetTypeArguments() const {
-    return raw_ptr()->type_arguments();
+    return untag()->type_arguments();
   }
   virtual void SetTypeArguments(const TypeArguments& value) const {
     ASSERT(value.IsNull() ||
@@ -10381,58 +10522,58 @@
             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.
-    raw_ptr()->set_type_arguments(value.raw());
+    untag()->set_type_arguments(value.ptr());
   }
   static intptr_t type_arguments_offset() {
-    return OFFSET_OF(LinkedHashMapLayout, type_arguments_);
+    return OFFSET_OF(UntaggedLinkedHashMap, type_arguments_);
   }
 
-  TypedDataPtr index() const { return raw_ptr()->index(); }
+  TypedDataPtr index() const { return untag()->index(); }
   void SetIndex(const TypedData& value) const {
     ASSERT(!value.IsNull());
-    raw_ptr()->set_index(value.raw());
+    untag()->set_index(value.ptr());
   }
   static intptr_t index_offset() {
-    return OFFSET_OF(LinkedHashMapLayout, index_);
+    return OFFSET_OF(UntaggedLinkedHashMap, index_);
   }
 
-  ArrayPtr data() const { return raw_ptr()->data(); }
-  void SetData(const Array& value) const { raw_ptr()->set_data(value.raw()); }
+  ArrayPtr data() const { return untag()->data(); }
+  void SetData(const Array& value) const { untag()->set_data(value.ptr()); }
   static intptr_t data_offset() {
-    return OFFSET_OF(LinkedHashMapLayout, data_);
+    return OFFSET_OF(UntaggedLinkedHashMap, data_);
   }
 
-  SmiPtr hash_mask() const { return raw_ptr()->hash_mask(); }
+  SmiPtr hash_mask() const { return untag()->hash_mask(); }
   void SetHashMask(intptr_t value) const {
-    raw_ptr()->set_hash_mask(Smi::New(value));
+    untag()->set_hash_mask(Smi::New(value));
   }
   static intptr_t hash_mask_offset() {
-    return OFFSET_OF(LinkedHashMapLayout, hash_mask_);
+    return OFFSET_OF(UntaggedLinkedHashMap, hash_mask_);
   }
 
-  SmiPtr used_data() const { return raw_ptr()->used_data(); }
+  SmiPtr used_data() const { return untag()->used_data(); }
   void SetUsedData(intptr_t value) const {
-    raw_ptr()->set_used_data(Smi::New(value));
+    untag()->set_used_data(Smi::New(value));
   }
   static intptr_t used_data_offset() {
-    return OFFSET_OF(LinkedHashMapLayout, used_data_);
+    return OFFSET_OF(UntaggedLinkedHashMap, used_data_);
   }
 
-  SmiPtr deleted_keys() const { return raw_ptr()->deleted_keys(); }
+  SmiPtr deleted_keys() const { return untag()->deleted_keys(); }
   void SetDeletedKeys(intptr_t value) const {
-    raw_ptr()->set_deleted_keys(Smi::New(value));
+    untag()->set_deleted_keys(Smi::New(value));
   }
   static intptr_t deleted_keys_offset() {
-    return OFFSET_OF(LinkedHashMapLayout, deleted_keys_);
+    return OFFSET_OF(UntaggedLinkedHashMap, deleted_keys_);
   }
 
   intptr_t Length() const {
     // The map may be uninitialized.
-    if (raw_ptr()->used_data() == Object::null()) return 0;
-    if (raw_ptr()->deleted_keys() == Object::null()) return 0;
+    if (untag()->used_data() == Object::null()) return 0;
+    if (untag()->deleted_keys() == Object::null()) return 0;
 
-    intptr_t used = Smi::Value(raw_ptr()->used_data());
-    intptr_t deleted = Smi::Value(raw_ptr()->deleted_keys());
+    intptr_t used = Smi::Value(untag()->used_data());
+    intptr_t deleted = Smi::Value(untag()->deleted_keys());
     return (used >> 1) - deleted;
   }
 
@@ -10456,7 +10597,7 @@
           return false;
         }
         scratch_ = data_.At(offset_);
-        if (scratch_.raw() != data_.raw()) {
+        if (scratch_.ptr() != data_.ptr()) {
           // Slot is not deleted (self-reference indicates deletion).
           return true;
         }
@@ -10478,7 +10619,7 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap, Instance);
 
   // Keep this in sync with Dart implementation (lib/compact_hash.dart).
-  static const intptr_t kInitialIndexBits = 3;
+  static const intptr_t kInitialIndexBits = 2;
   static const intptr_t kInitialIndexSize = 1 << (kInitialIndexBits + 1);
 
   // Allocate a map, but leave all fields set to null.
@@ -10492,55 +10633,55 @@
 class Closure : public Instance {
  public:
   TypeArgumentsPtr instantiator_type_arguments() const {
-    return raw_ptr()->instantiator_type_arguments();
+    return untag()->instantiator_type_arguments();
   }
   void set_instantiator_type_arguments(const TypeArguments& args) const {
-    raw_ptr()->set_instantiator_type_arguments(args.raw());
+    untag()->set_instantiator_type_arguments(args.ptr());
   }
   static intptr_t instantiator_type_arguments_offset() {
-    return OFFSET_OF(ClosureLayout, instantiator_type_arguments_);
+    return OFFSET_OF(UntaggedClosure, instantiator_type_arguments_);
   }
 
   TypeArgumentsPtr function_type_arguments() const {
-    return raw_ptr()->function_type_arguments();
+    return untag()->function_type_arguments();
   }
   void set_function_type_arguments(const TypeArguments& args) const {
-    raw_ptr()->set_function_type_arguments(args.raw());
+    untag()->set_function_type_arguments(args.ptr());
   }
   static intptr_t function_type_arguments_offset() {
-    return OFFSET_OF(ClosureLayout, function_type_arguments_);
+    return OFFSET_OF(UntaggedClosure, function_type_arguments_);
   }
 
   TypeArgumentsPtr delayed_type_arguments() const {
-    return raw_ptr()->delayed_type_arguments();
+    return untag()->delayed_type_arguments();
   }
   void set_delayed_type_arguments(const TypeArguments& args) const {
-    raw_ptr()->set_delayed_type_arguments(args.raw());
+    untag()->set_delayed_type_arguments(args.ptr());
   }
   static intptr_t delayed_type_arguments_offset() {
-    return OFFSET_OF(ClosureLayout, delayed_type_arguments_);
+    return OFFSET_OF(UntaggedClosure, delayed_type_arguments_);
   }
 
-  FunctionPtr function() const { return raw_ptr()->function(); }
+  FunctionPtr function() const { return untag()->function(); }
   static intptr_t function_offset() {
-    return OFFSET_OF(ClosureLayout, function_);
+    return OFFSET_OF(UntaggedClosure, function_);
   }
 
-  ContextPtr context() const { return raw_ptr()->context(); }
+  ContextPtr context() const { return untag()->context(); }
   static intptr_t context_offset() {
-    return OFFSET_OF(ClosureLayout, context_);
+    return OFFSET_OF(UntaggedClosure, context_);
   }
 
   bool IsGeneric(Thread* thread) const { return NumTypeParameters(thread) > 0; }
   intptr_t NumTypeParameters(Thread* thread) const;
-  // No need for NumParentTypeParameters, as a closure is always closed over
-  // its parents type parameters (i.e., function_type_parameters() above).
+  // No need for num_parent_type_arguments, as a closure is always closed
+  // over its parents type parameters (i.e., function_type_parameters() above).
 
-  SmiPtr hash() const { return raw_ptr()->hash(); }
-  static intptr_t hash_offset() { return OFFSET_OF(ClosureLayout, hash_); }
+  SmiPtr hash() const { return untag()->hash(); }
+  static intptr_t hash_offset() { return OFFSET_OF(UntaggedClosure, hash_); }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ClosureLayout));
+    return RoundedAllocationSize(sizeof(UntaggedClosure));
   }
 
   virtual void CanonicalizeFieldsLocked(Thread* thread) const;
@@ -10563,7 +10704,7 @@
                         const Context& context,
                         Heap::Space space = Heap::kNew);
 
-  FunctionPtr GetInstantiatedSignature(Zone* zone) const;
+  FunctionTypePtr GetInstantiatedSignature(Zone* zone) const;
 
  private:
   static ClosurePtr New();
@@ -10574,10 +10715,10 @@
 
 class Capability : public Instance {
  public:
-  uint64_t Id() const { return raw_ptr()->id_; }
+  uint64_t Id() const { return untag()->id_; }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(CapabilityLayout));
+    return RoundedAllocationSize(sizeof(UntaggedCapability));
   }
   static CapabilityPtr New(uint64_t id, Heap::Space space = Heap::kNew);
 
@@ -10588,22 +10729,22 @@
 
 class ReceivePort : public Instance {
  public:
-  SendPortPtr send_port() const { return raw_ptr()->send_port(); }
-  Dart_Port Id() const { return send_port()->ptr()->id_; }
+  SendPortPtr send_port() const { return untag()->send_port(); }
+  Dart_Port Id() const { return send_port()->untag()->id_; }
 
-  InstancePtr handler() const { return raw_ptr()->handler(); }
+  InstancePtr handler() const { return untag()->handler(); }
   void set_handler(const Instance& value) const;
 
 #if !defined(PRODUCT)
   StackTracePtr allocation_location() const {
-    return raw_ptr()->allocation_location();
+    return untag()->allocation_location();
   }
 
-  StringPtr debug_name() const { return raw_ptr()->debug_name(); }
+  StringPtr debug_name() const { return untag()->debug_name(); }
 #endif
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(ReceivePortLayout));
+    return RoundedAllocationSize(sizeof(UntaggedReceivePort));
   }
   static ReceivePortPtr New(Dart_Port id,
                             const String& debug_name,
@@ -10617,16 +10758,16 @@
 
 class SendPort : public Instance {
  public:
-  Dart_Port Id() const { return raw_ptr()->id_; }
+  Dart_Port Id() const { return untag()->id_; }
 
-  Dart_Port origin_id() const { return raw_ptr()->origin_id_; }
+  Dart_Port origin_id() const { return untag()->origin_id_; }
   void set_origin_id(Dart_Port id) const {
     ASSERT(origin_id() == 0);
-    StoreNonPointer(&(raw_ptr()->origin_id_), id);
+    StoreNonPointer(&(untag()->origin_id_), id);
   }
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(SendPortLayout));
+    return RoundedAllocationSize(sizeof(UntaggedSendPort));
   }
   static SendPortPtr New(Dart_Port id, Heap::Space space = Heap::kNew);
   static SendPortPtr New(Dart_Port id,
@@ -10674,7 +10815,7 @@
                                       Heap::Space space = Heap::kNew);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(TransferableTypedDataLayout));
+    return RoundedAllocationSize(sizeof(UntaggedTransferableTypedData));
   }
 
  private:
@@ -10689,15 +10830,15 @@
 
   intptr_t Length() const;
 
-  StackTracePtr async_link() const { return raw_ptr()->async_link(); }
+  StackTracePtr async_link() const { return untag()->async_link(); }
   void set_async_link(const StackTrace& async_link) const;
   void set_expand_inlined(bool value) const;
 
-  ArrayPtr code_array() const { return raw_ptr()->code_array(); }
+  ArrayPtr code_array() const { return untag()->code_array(); }
   ObjectPtr CodeAtFrame(intptr_t frame_index) const;
   void SetCodeAtFrame(intptr_t frame_index, const Object& code) const;
 
-  ArrayPtr pc_offset_array() const { return raw_ptr()->pc_offset_array(); }
+  ArrayPtr pc_offset_array() const { return untag()->pc_offset_array(); }
   SmiPtr PcOffsetAtFrame(intptr_t frame_index) const;
   void SetPcOffsetAtFrame(intptr_t frame_index, const Smi& pc_offset) const;
 
@@ -10719,7 +10860,7 @@
   static constexpr intptr_t kSyncAsyncCroppedFrames = 2;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(StackTraceLayout));
+    return RoundedAllocationSize(sizeof(UntaggedStackTrace));
   }
   static StackTracePtr New(const Array& code_array,
                            const Array& pc_offset_array,
@@ -10818,23 +10959,23 @@
   bool is_complex() const { return (type() == kComplex); }
 
   intptr_t num_registers(bool is_one_byte) const {
-    return is_one_byte ? raw_ptr()->num_one_byte_registers_
-                       : raw_ptr()->num_two_byte_registers_;
+    return is_one_byte ? untag()->num_one_byte_registers_
+                       : untag()->num_two_byte_registers_;
   }
 
-  StringPtr pattern() const { return raw_ptr()->pattern(); }
+  StringPtr pattern() const { return untag()->pattern(); }
   SmiPtr num_bracket_expressions() const {
-    return raw_ptr()->num_bracket_expressions();
+    return untag()->num_bracket_expressions();
   }
-  ArrayPtr capture_name_map() const { return raw_ptr()->capture_name_map(); }
+  ArrayPtr capture_name_map() const { return untag()->capture_name_map(); }
 
   TypedDataPtr bytecode(bool is_one_byte, bool sticky) const {
     if (sticky) {
-      return TypedData::RawCast(is_one_byte ? raw_ptr()->one_byte_sticky_
-                                            : raw_ptr()->two_byte_sticky_);
+      return TypedData::RawCast(is_one_byte ? untag()->one_byte_sticky_
+                                            : untag()->two_byte_sticky_);
     } else {
-      return TypedData::RawCast(is_one_byte ? raw_ptr()->one_byte_
-                                            : raw_ptr()->two_byte_);
+      return TypedData::RawCast(is_one_byte ? untag()->one_byte_
+                                            : untag()->two_byte_);
     }
   }
 
@@ -10842,24 +10983,24 @@
     if (sticky) {
       switch (cid) {
         case kOneByteStringCid:
-          return OFFSET_OF(RegExpLayout, one_byte_sticky_);
+          return OFFSET_OF(UntaggedRegExp, one_byte_sticky_);
         case kTwoByteStringCid:
-          return OFFSET_OF(RegExpLayout, two_byte_sticky_);
+          return OFFSET_OF(UntaggedRegExp, two_byte_sticky_);
         case kExternalOneByteStringCid:
-          return OFFSET_OF(RegExpLayout, external_one_byte_sticky_);
+          return OFFSET_OF(UntaggedRegExp, external_one_byte_sticky_);
         case kExternalTwoByteStringCid:
-          return OFFSET_OF(RegExpLayout, external_two_byte_sticky_);
+          return OFFSET_OF(UntaggedRegExp, external_two_byte_sticky_);
       }
     } else {
       switch (cid) {
         case kOneByteStringCid:
-          return OFFSET_OF(RegExpLayout, one_byte_);
+          return OFFSET_OF(UntaggedRegExp, one_byte_);
         case kTwoByteStringCid:
-          return OFFSET_OF(RegExpLayout, two_byte_);
+          return OFFSET_OF(UntaggedRegExp, two_byte_);
         case kExternalOneByteStringCid:
-          return OFFSET_OF(RegExpLayout, external_one_byte_);
+          return OFFSET_OF(UntaggedRegExp, external_one_byte_);
         case kExternalTwoByteStringCid:
-          return OFFSET_OF(RegExpLayout, external_two_byte_);
+          return OFFSET_OF(UntaggedRegExp, external_two_byte_);
       }
     }
 
@@ -10913,36 +11054,36 @@
   void set_is_complex() const { set_type(kComplex); }
   void set_num_registers(bool is_one_byte, intptr_t value) const {
     if (is_one_byte) {
-      StoreNonPointer(&raw_ptr()->num_one_byte_registers_, value);
+      StoreNonPointer(&untag()->num_one_byte_registers_, value);
     } else {
-      StoreNonPointer(&raw_ptr()->num_two_byte_registers_, value);
+      StoreNonPointer(&untag()->num_two_byte_registers_, value);
     }
   }
 
   RegExpFlags flags() const {
-    return RegExpFlags(FlagsBits::decode(raw_ptr()->type_flags_));
+    return RegExpFlags(FlagsBits::decode(untag()->type_flags_));
   }
   void set_flags(RegExpFlags flags) const {
-    StoreNonPointer(&raw_ptr()->type_flags_,
-                    FlagsBits::update(flags.value(), raw_ptr()->type_flags_));
+    StoreNonPointer(&untag()->type_flags_,
+                    FlagsBits::update(flags.value(), untag()->type_flags_));
   }
   const char* Flags() const;
 
   virtual bool CanonicalizeEquals(const Instance& other) const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(RegExpLayout));
+    return RoundedAllocationSize(sizeof(UntaggedRegExp));
   }
 
   static RegExpPtr New(Heap::Space space = Heap::kNew);
 
  private:
   void set_type(RegExType type) const {
-    StoreNonPointer(&raw_ptr()->type_flags_,
-                    TypeBits::update(type, raw_ptr()->type_flags_));
+    StoreNonPointer(&untag()->type_flags_,
+                    TypeBits::update(type, untag()->type_flags_));
   }
 
-  RegExType type() const { return TypeBits::decode(raw_ptr()->type_flags_); }
+  RegExType type() const { return TypeBits::decode(untag()->type_flags_); }
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(RegExp, Instance);
   friend class Class;
@@ -10950,29 +11091,27 @@
 
 class WeakProperty : public Instance {
  public:
-  ObjectPtr key() const { return raw_ptr()->key(); }
-  void set_key(const Object& key) const { raw_ptr()->set_key(key.raw()); }
-  static intptr_t key_offset() { return OFFSET_OF(WeakPropertyLayout, key_); }
+  ObjectPtr key() const { return untag()->key(); }
+  void set_key(const Object& key) const { untag()->set_key(key.ptr()); }
+  static intptr_t key_offset() { return OFFSET_OF(UntaggedWeakProperty, key_); }
 
-  ObjectPtr value() const { return raw_ptr()->value(); }
-  void set_value(const Object& value) const {
-    raw_ptr()->set_value(value.raw());
-  }
+  ObjectPtr value() const { return untag()->value(); }
+  void set_value(const Object& value) const { untag()->set_value(value.ptr()); }
   static intptr_t value_offset() {
-    return OFFSET_OF(WeakPropertyLayout, value_);
+    return OFFSET_OF(UntaggedWeakProperty, value_);
   }
 
   static WeakPropertyPtr New(Heap::Space space = Heap::kNew);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(WeakPropertyLayout));
+    return RoundedAllocationSize(sizeof(UntaggedWeakProperty));
   }
 
   static void Clear(WeakPropertyPtr raw_weak) {
-    ASSERT(raw_weak->ptr()->next_ == WeakProperty::null());
+    ASSERT(raw_weak->untag()->next_ == WeakProperty::null());
     // This action is performed by the GC. No barrier.
-    raw_weak->ptr()->key_ = Object::null();
-    raw_weak->ptr()->value_ = Object::null();
+    raw_weak->untag()->key_ = Object::null();
+    raw_weak->untag()->value_ = Object::null();
   }
 
  private:
@@ -10982,10 +11121,10 @@
 
 class MirrorReference : public Instance {
  public:
-  ObjectPtr referent() const { return raw_ptr()->referent(); }
+  ObjectPtr referent() const { return untag()->referent(); }
 
   void set_referent(const Object& referent) const {
-    raw_ptr()->set_referent(referent.raw());
+    untag()->set_referent(referent.ptr());
   }
 
   AbstractTypePtr GetAbstractTypeReferent() const;
@@ -10996,6 +11135,8 @@
 
   FunctionPtr GetFunctionReferent() const;
 
+  FunctionTypePtr GetFunctionTypeReferent() const;
+
   LibraryPtr GetLibraryReferent() const;
 
   TypeParameterPtr GetTypeParameterReferent() const;
@@ -11004,7 +11145,7 @@
                                 Heap::Space space = Heap::kNew);
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(MirrorReferenceLayout));
+    return RoundedAllocationSize(sizeof(UntaggedMirrorReference));
   }
 
  private:
@@ -11014,20 +11155,20 @@
 
 class UserTag : public Instance {
  public:
-  uword tag() const { return raw_ptr()->tag(); }
+  uword tag() const { return untag()->tag(); }
   void set_tag(uword t) const {
     ASSERT(t >= UserTags::kUserTagIdOffset);
     ASSERT(t < UserTags::kUserTagIdOffset + UserTags::kMaxUserTags);
-    StoreNonPointer(&raw_ptr()->tag_, t);
+    StoreNonPointer(&untag()->tag_, t);
   }
-  static intptr_t tag_offset() { return OFFSET_OF(UserTagLayout, tag_); }
+  static intptr_t tag_offset() { return OFFSET_OF(UntaggedUserTag, tag_); }
 
-  StringPtr label() const { return raw_ptr()->label(); }
+  StringPtr label() const { return untag()->label(); }
 
   void MakeActive() const;
 
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(UserTagLayout));
+    return RoundedAllocationSize(sizeof(UntaggedUserTag));
   }
 
   static UserTagPtr New(const String& label, Heap::Space space = Heap::kOld);
@@ -11041,7 +11182,7 @@
   static void AddTagToIsolate(Thread* thread, const UserTag& tag);
 
   void set_label(const String& tag_label) const {
-    raw_ptr()->set_label(tag_label.raw());
+    untag()->set_label(tag_label.ptr());
   }
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(UserTag, Instance);
@@ -11052,14 +11193,14 @@
 class FutureOr : public Instance {
  public:
   static intptr_t InstanceSize() {
-    return RoundedAllocationSize(sizeof(FutureOrLayout));
+    return RoundedAllocationSize(sizeof(UntaggedFutureOr));
   }
 
   virtual TypeArgumentsPtr GetTypeArguments() const {
-    return raw_ptr()->type_arguments();
+    return untag()->type_arguments();
   }
   static intptr_t type_arguments_offset() {
-    return OFFSET_OF(FutureOrLayout, type_arguments_);
+    return OFFSET_OF(UntaggedFutureOr, type_arguments_);
   }
 
  private:
@@ -11070,18 +11211,18 @@
 
 // Breaking cycles and loops.
 ClassPtr Object::clazz() const {
-  uword raw_value = static_cast<uword>(raw_);
+  uword raw_value = static_cast<uword>(ptr_);
   if ((raw_value & kSmiTagMask) == kSmiTag) {
     return Smi::Class();
   }
   ASSERT(!IsolateGroup::Current()->compaction_in_progress());
-  return Isolate::Current()->class_table()->At(raw()->GetClassId());
+  return IsolateGroup::Current()->class_table()->At(ptr()->GetClassId());
 }
 
 DART_FORCE_INLINE
-void Object::SetRaw(ObjectPtr value) {
+void Object::SetPtr(ObjectPtr value) {
   NoSafepointScope no_safepoint_scope;
-  raw_ = value;
+  ptr_ = value;
   intptr_t cid = value->GetClassIdMayBeSmi();
   // Free-list elements cannot be wrapped in a handle.
   ASSERT(cid != kFreeListElement);
@@ -11091,17 +11232,16 @@
   }
   set_vtable(builtin_vtables_[cid]);
 #if defined(DEBUG)
-  if (FLAG_verify_handles && raw_->IsHeapObject()) {
-    Isolate* isolate = Isolate::Current();
-    Heap* isolate_heap = isolate->heap();
+  if (FLAG_verify_handles && ptr_->IsHeapObject()) {
+    Heap* isolate_heap = IsolateGroup::Current()->heap();
     // TODO(rmacnak): Remove after rewriting StackFrame::VisitObjectPointers
     // to not use handles.
     if (!isolate_heap->new_space()->scavenging()) {
-      Heap* vm_isolate_heap = Dart::vm_isolate()->heap();
-      uword addr = ObjectLayout::ToAddr(raw_);
+      Heap* vm_isolate_heap = Dart::vm_isolate_group()->heap();
+      uword addr = UntaggedObject::ToAddr(ptr_);
       if (!isolate_heap->Contains(addr) && !vm_isolate_heap->Contains(addr)) {
         ASSERT(FLAG_write_protect_code);
-        addr = ObjectLayout::ToAddr(OldPage::ToWritable(raw_));
+        addr = UntaggedObject::ToAddr(OldPage::ToWritable(ptr_));
         ASSERT(isolate_heap->Contains(addr) || vm_isolate_heap->Contains(addr));
       }
     }
@@ -11111,13 +11251,13 @@
 
 intptr_t Field::HostOffset() const {
   ASSERT(is_instance());  // Valid only for dart instance fields.
-  return (Smi::Value(raw_ptr()->host_offset_or_field_id()) * kWordSize);
+  return (Smi::Value(untag()->host_offset_or_field_id()) * kWordSize);
 }
 
 intptr_t Field::TargetOffset() const {
   ASSERT(is_instance());  // Valid only for dart instance fields.
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  return (raw_ptr()->target_offset_ * compiler::target::kWordSize);
+  return (untag()->target_offset_ * compiler::target::kWordSize);
 #else
   return HostOffset();
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
@@ -11125,9 +11265,9 @@
 
 inline intptr_t Field::TargetOffsetOf(const FieldPtr field) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  return field->ptr()->target_offset_;
+  return field->untag()->target_offset_;
 #else
-  return Smi::Value(field->ptr()->host_offset_or_field_id_);
+  return Smi::Value(field->untag()->host_offset_or_field_id_);
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -11135,11 +11275,11 @@
                       intptr_t target_offset_in_bytes) const {
   ASSERT(is_instance());  // Valid only for dart instance fields.
   ASSERT(kWordSize != 0);
-  raw_ptr()->set_host_offset_or_field_id(
+  untag()->set_host_offset_or_field_id(
       Smi::New(host_offset_in_bytes / kWordSize));
 #if !defined(DART_PRECOMPILED_RUNTIME)
   ASSERT(compiler::target::kWordSize != 0);
-  StoreNonPointer(&raw_ptr()->target_offset_,
+  StoreNonPointer(&untag()->target_offset_,
                   target_offset_in_bytes / compiler::target::kWordSize);
 #else
   ASSERT(host_offset_in_bytes == target_offset_in_bytes);
@@ -11148,22 +11288,26 @@
 
 InstancePtr Field::StaticValue() const {
   ASSERT(is_static());  // Valid only for static dart fields.
-  return Isolate::Current()->field_table()->At(
-      Smi::Value(raw_ptr()->host_offset_or_field_id()));
+  return Isolate::Current()->field_table()->At(field_id());
 }
 
 inline intptr_t Field::field_id() const {
-  return Smi::Value(raw_ptr()->host_offset_or_field_id());
+  return Smi::Value(untag()->host_offset_or_field_id());
 }
 
 void Field::set_field_id(intptr_t field_id) const {
+  DEBUG_ASSERT(
+      IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+  set_field_id_unsafe(field_id);
+}
+
+void Field::set_field_id_unsafe(intptr_t field_id) const {
   ASSERT(is_static());
-  ASSERT(Thread::Current()->IsMutatorThread());
-  raw_ptr()->set_host_offset_or_field_id(Smi::New(field_id));
+  untag()->set_host_offset_or_field_id(Smi::New(field_id));
 }
 
 void Context::SetAt(intptr_t index, const Object& value) const {
-  raw_ptr()->set_element(index, value.raw());
+  untag()->set_element(index, value.ptr());
 }
 
 intptr_t Instance::GetNativeField(int index) const {
@@ -11173,7 +11317,7 @@
   if (native_fields == TypedData::null()) {
     return 0;
   }
-  return reinterpret_cast<intptr_t*>(native_fields->ptr()->data())[index];
+  return reinterpret_cast<intptr_t*>(native_fields->untag()->data())[index];
 }
 
 void Instance::GetNativeFields(uint16_t num_fields,
@@ -11187,14 +11331,15 @@
       field_values[i] = 0;
     }
   }
-  intptr_t* fields = reinterpret_cast<intptr_t*>(native_fields->ptr()->data());
+  intptr_t* fields =
+      reinterpret_cast<intptr_t*>(native_fields->untag()->data());
   for (intptr_t i = 0; i < num_fields; i++) {
     field_values[i] = fields[i];
   }
 }
 
 bool String::Equals(const String& str) const {
-  if (raw() == str.raw()) {
+  if (ptr() == str.ptr()) {
     return true;  // Both handles point to the same raw instance.
   }
   if (str.IsNull()) {
@@ -11245,7 +11390,8 @@
 }
 
 inline intptr_t Type::Hash() const {
-  intptr_t result = Smi::Value(raw_ptr()->hash());
+  ASSERT(IsFinalized());
+  intptr_t result = Smi::Value(untag()->hash());
   if (result != 0) {
     return result;
   }
@@ -11255,12 +11401,27 @@
 inline void Type::SetHash(intptr_t value) const {
   // This is only safe because we create a new Smi, which does not cause
   // heap allocation.
-  raw_ptr()->set_hash(Smi::New(value));
+  untag()->set_hash(Smi::New(value));
+}
+
+inline intptr_t FunctionType::Hash() const {
+  ASSERT(IsFinalized());
+  intptr_t result = Smi::Value(untag()->hash_);
+  if (result != 0) {
+    return result;
+  }
+  return ComputeHash();
+}
+
+inline void FunctionType::SetHash(intptr_t value) const {
+  // This is only safe because we create a new Smi, which does not cause
+  // heap allocation.
+  StoreSmi(&untag()->hash_, Smi::New(value));
 }
 
 inline intptr_t TypeParameter::Hash() const {
-  ASSERT(IsFinalized());
-  intptr_t result = Smi::Value(raw_ptr()->hash());
+  ASSERT(IsFinalized() || IsBeingFinalized());  // Bound may not be finalized.
+  intptr_t result = Smi::Value(untag()->hash());
   if (result != 0) {
     return result;
   }
@@ -11270,12 +11431,12 @@
 inline void TypeParameter::SetHash(intptr_t value) const {
   // This is only safe because we create a new Smi, which does not cause
   // heap allocation.
-  raw_ptr()->set_hash(Smi::New(value));
+  untag()->set_hash(Smi::New(value));
 }
 
 inline intptr_t TypeArguments::Hash() const {
   if (IsNull()) return kAllDynamicHash;
-  intptr_t result = Smi::Value(raw_ptr()->hash());
+  intptr_t result = Smi::Value(untag()->hash());
   if (result != 0) {
     return result;
   }
@@ -11285,7 +11446,7 @@
 inline void TypeArguments::SetHash(intptr_t value) const {
   // This is only safe because we create a new Smi, which does not cause
   // heap allocation.
-  raw_ptr()->set_hash(Smi::New(value));
+  untag()->set_hash(Smi::New(value));
 }
 
 inline uint16_t String::CharAt(StringPtr str, intptr_t index) {
@@ -11455,7 +11616,7 @@
 void DumpTypeParameterTable(Isolate* isolate);
 void DumpTypeArgumentsTable(Isolate* isolate);
 
-EntryPointPragma FindEntryPointPragma(Isolate* I,
+EntryPointPragma FindEntryPointPragma(IsolateGroup* isolate_group,
                                       const Array& metadata,
                                       Field* reusable_field_handle,
                                       Object* reusable_object_handle);
@@ -11463,6 +11624,9 @@
 DART_WARN_UNUSED_RESULT
 ErrorPtr EntryPointFieldInvocationError(const String& getter_name);
 
+DART_WARN_UNUSED_RESULT
+ErrorPtr EntryPointMemberInvocationError(const Object& member);
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_OBJECT_H_
diff --git a/runtime/vm/object_arm64_test.cc b/runtime/vm/object_arm64_test.cc
index 640c91b..681b8e6 100644
--- a/runtime/vm/object_arm64_test.cc
+++ b/runtime/vm/object_arm64_test.cc
@@ -46,7 +46,7 @@
 // This is used to test Embedded Smi objects in the instructions.
 void GenerateEmbedSmiInCode(compiler::Assembler* assembler, intptr_t value) {
   const Smi& smi_object = Smi::ZoneHandle(Smi::New(value));
-  const int64_t val = static_cast<int64_t>(smi_object.raw());
+  const int64_t val = static_cast<int64_t>(smi_object.ptr());
   __ LoadImmediate(R0, val);
   __ ret();
 }
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index ac498cc..489b5e1 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -55,7 +55,8 @@
   // won't be in use while handling a service request (ObjectGraph's only use).
   virtual void VisitPointers(ObjectPtr* first, ObjectPtr* last) {
     for (ObjectPtr* current = first; current <= last; ++current) {
-      if ((*current)->IsHeapObject() && !(*current)->ptr()->InVMIsolateHeap() &&
+      if ((*current)->IsHeapObject() &&
+          !(*current)->untag()->InVMIsolateHeap() &&
           object_ids_->GetValueExclusive(*current) == 0) {  // not visited yet
         if (!include_vm_objects_ && !IsUserClass((*current)->GetClassId())) {
           continue;
@@ -93,7 +94,7 @@
       }
       if (direction == ObjectGraph::Visitor::kProceed) {
         set_gc_root_type(node.gc_root_type);
-        obj->ptr()->VisitPointers(this);
+        obj->untag()->VisitPointers(this);
         clear_gc_root_type();
       }
     }
@@ -162,17 +163,17 @@
     return -1;
   }
   Stack::Node parent = stack_->data_[parent_index];
-  uword parent_start = ObjectLayout::ToAddr(parent.obj);
+  uword parent_start = UntaggedObject::ToAddr(parent.obj);
   Stack::Node child = stack_->data_[index_];
   ASSERT(child.obj == *child.ptr);
   uword child_ptr_addr = reinterpret_cast<uword>(child.ptr);
   intptr_t offset = child_ptr_addr - parent_start;
-  if (offset > 0 && offset < parent.obj->ptr()->HeapSize()) {
+  if (offset > 0 && offset < parent.obj->untag()->HeapSize()) {
     ASSERT(Utils::IsAligned(offset, kWordSize));
     return offset >> kWordSizeLog2;
   } else {
     // Some internal VM objects visit pointers not contained within the parent.
-    // For instance, CodeLayout::VisitCodePointers visits pointers in
+    // For instance, UntaggedCode::VisitCodePointers visits pointers in
     // instructions.
     ASSERT(!parent.obj->IsDartInstance());
     return -1;
@@ -186,7 +187,7 @@
   HANDLESCOPE(thread);
   Zone* zone = thread->zone();
   const GrowableObjectArray& libraries = GrowableObjectArray::Handle(
-      zone, thread->isolate()->object_store()->libraries());
+      zone, thread->isolate_group()->object_store()->libraries());
   Library& library = Library::Handle(zone);
   Object& entry = Object::Handle(zone);
   Class& cls = Class::Handle(zone);
@@ -198,16 +199,16 @@
     while (entries.HasNext()) {
       entry = entries.GetNext();
       if (entry.IsClass()) {
-        cls ^= entry.raw();
+        cls ^= entry.ptr();
         fields = cls.fields();
         for (intptr_t j = 0; j < fields.Length(); j++) {
           field ^= fields.At(j);
-          ObjectPtr ptr = field.raw();
+          ObjectPtr ptr = field.ptr();
           visitor->VisitPointer(&ptr);
         }
       } else if (entry.IsField()) {
-        field ^= entry.raw();
-        ObjectPtr ptr = field.raw();
+        field ^= entry.ptr();
+        ObjectPtr ptr = field.ptr();
         visitor->VisitPointer(&ptr);
       }
     }
@@ -246,7 +247,7 @@
   Stack stack(isolate_group());
   stack.set_visit_weak_persistent_handles(
       visitor->visit_weak_persistent_handles());
-  ObjectPtr root_raw = root.raw();
+  ObjectPtr root_raw = root.ptr();
   stack.VisitPointer(&root_raw);
   stack.TraverseGraph(visitor);
 }
@@ -291,7 +292,7 @@
     if (ShouldSkip(obj)) {
       return kBacktrack;
     }
-    size_ += obj->ptr()->HeapSize();
+    size_ += obj->untag()->HeapSize();
     return kProceed;
   }
 
@@ -302,7 +303,7 @@
 class SizeExcludingObjectVisitor : public SizeVisitor {
  public:
   explicit SizeExcludingObjectVisitor(const Object& skip) : skip_(skip) {}
-  virtual bool ShouldSkip(ObjectPtr obj) const { return obj == skip_.raw(); }
+  virtual bool ShouldSkip(ObjectPtr obj) const { return obj == skip_.ptr(); }
 
  private:
   const Object& skip_;
@@ -446,7 +447,7 @@
   HeapIterationScope iteration_scope(Thread::Current(), true);
   // To break the trivial path, the handle 'obj' is temporarily cleared during
   // the search, but restored before returning.
-  ObjectPtr raw = obj->raw();
+  ObjectPtr raw = obj->ptr();
   *obj = Object::null();
   RetainingPathVisitor visitor(raw, path);
   IterateUserObjects(&visitor);
@@ -480,7 +481,7 @@
 
   virtual void VisitObject(ObjectPtr raw_obj) {
     source_ = raw_obj;
-    raw_obj->ptr()->VisitPointers(this);
+    raw_obj->untag()->VisitPointers(this);
   }
 
   virtual void VisitPointers(ObjectPtr* first, ObjectPtr* last) {
@@ -494,15 +495,15 @@
           references_.SetAt(obj_index, *scratch_);
 
           *scratch_ = Smi::New(0);
-          uword source_start = ObjectLayout::ToAddr(source_);
+          uword source_start = UntaggedObject::ToAddr(source_);
           uword current_ptr_addr = reinterpret_cast<uword>(current_ptr);
           intptr_t offset = current_ptr_addr - source_start;
-          if (offset > 0 && offset < source_->ptr()->HeapSize()) {
+          if (offset > 0 && offset < source_->untag()->HeapSize()) {
             ASSERT(Utils::IsAligned(offset, kWordSize));
             *scratch_ = Smi::New(offset >> kWordSizeLog2);
           } else {
             // Some internal VM objects visit pointers not contained within the
-            // parent. For instance, CodeLayout::VisitCodePointers visits
+            // parent. For instance, UntaggedCode::VisitCodePointers visits
             // pointers in instructions.
             ASSERT(!source_->IsDartInstance());
             *scratch_ = Smi::New(-1);
@@ -526,7 +527,7 @@
   Object& scratch = Object::Handle();
   HeapIterationScope iteration(Thread::Current());
   NoSafepointScope no_safepoint;
-  InboundReferencesVisitor visitor(isolate(), obj->raw(), references, &scratch);
+  InboundReferencesVisitor visitor(isolate(), obj->ptr(), references, &scratch);
   iteration.IterateObjects(&visitor);
   return visitor.length();
 }
@@ -660,7 +661,8 @@
     image_page_ranges_[i].size = 0;
   }
   intptr_t next_offset = 0;
-  OldPage* image_page = Dart::vm_isolate()->heap()->old_space()->image_pages_;
+  OldPage* image_page =
+      Dart::vm_isolate_group()->heap()->old_space()->image_pages_;
   while (image_page != NULL) {
     RELEASE_ASSERT(next_offset <= kMaxImagePages);
     image_page_ranges_[next_offset].base = image_page->object_start();
@@ -669,7 +671,7 @@
     image_page = image_page->next();
     next_offset++;
   }
-  image_page = isolate()->heap()->old_space()->image_pages_;
+  image_page = isolate_group()->heap()->old_space()->image_pages_;
   while (image_page != NULL) {
     RELEASE_ASSERT(next_offset <= kMaxImagePages);
     image_page_ranges_[next_offset].base = image_page->object_start();
@@ -679,7 +681,7 @@
     next_offset++;
   }
 
-  OldPage* page = isolate()->heap()->old_space()->pages_;
+  OldPage* page = isolate_group()->heap()->old_space()->pages_;
   while (page != NULL) {
     page->forwarding_page();
     CountingPage* counting_page =
@@ -691,7 +693,7 @@
 }
 
 bool HeapSnapshotWriter::OnImagePage(ObjectPtr obj) const {
-  const uword addr = ObjectLayout::ToAddr(obj);
+  const uword addr = UntaggedObject::ToAddr(obj);
   for (intptr_t i = 0; i < kMaxImagePages; i++) {
     if ((addr - image_page_ranges_[i].base) < image_page_ranges_[i].size) {
       return true;
@@ -717,7 +719,7 @@
   CountingPage* counting_page = FindCountingPage(obj);
   if (counting_page != nullptr) {
     // Likely: object on an ordinary page.
-    counting_page->Record(ObjectLayout::ToAddr(obj), ++object_count_);
+    counting_page->Record(UntaggedObject::ToAddr(obj), ++object_count_);
   } else {
     // Unlikely: new space object, or object on a large or image page.
     thread()->heap()->SetObjectId(obj, ++object_count_);
@@ -738,7 +740,7 @@
   intptr_t id;
   if (counting_page != nullptr) {
     // Likely: object on an ordinary page.
-    id = counting_page->Lookup(ObjectLayout::ToAddr(obj));
+    id = counting_page->Lookup(UntaggedObject::ToAddr(obj));
   } else {
     // Unlikely: new space object, or object on a large or image page.
     id = thread()->heap()->GetObjectId(obj);
@@ -775,7 +777,7 @@
     if (obj->IsPseudoObject()) return;
 
     writer_->AssignObjectId(obj);
-    obj->ptr()->VisitPointers(this);
+    obj->untag()->VisitPointers(this);
   }
 
   void VisitPointers(ObjectPtr* from, ObjectPtr* to) {
@@ -787,7 +789,7 @@
   void VisitHandle(uword addr) {
     FinalizablePersistentHandle* weak_persistent_handle =
         reinterpret_cast<FinalizablePersistentHandle*>(addr);
-    if (!weak_persistent_handle->raw()->IsHeapObject()) {
+    if (!weak_persistent_handle->ptr()->IsHeapObject()) {
       return;  // Free handle.
     }
 
@@ -832,112 +834,112 @@
 
     intptr_t cid = obj->GetClassId();
     writer_->WriteUnsigned(cid);
-    writer_->WriteUnsigned(discount_sizes_ ? 0 : obj->ptr()->HeapSize());
+    writer_->WriteUnsigned(discount_sizes_ ? 0 : obj->untag()->HeapSize());
 
     if (cid == kNullCid) {
       writer_->WriteUnsigned(kNullData);
     } else if (cid == kBoolCid) {
       writer_->WriteUnsigned(kBoolData);
       writer_->WriteUnsigned(
-          static_cast<uintptr_t>(static_cast<BoolPtr>(obj)->ptr()->value_));
+          static_cast<uintptr_t>(static_cast<BoolPtr>(obj)->untag()->value_));
     } else if (cid == kSmiCid) {
       UNREACHABLE();
     } else if (cid == kMintCid) {
       writer_->WriteUnsigned(kIntData);
-      writer_->WriteSigned(static_cast<MintPtr>(obj)->ptr()->value_);
+      writer_->WriteSigned(static_cast<MintPtr>(obj)->untag()->value_);
     } else if (cid == kDoubleCid) {
       writer_->WriteUnsigned(kDoubleData);
-      writer_->WriteBytes(&(static_cast<DoublePtr>(obj)->ptr()->value_),
+      writer_->WriteBytes(&(static_cast<DoublePtr>(obj)->untag()->value_),
                           sizeof(double));
     } else if (cid == kOneByteStringCid) {
       OneByteStringPtr str = static_cast<OneByteStringPtr>(obj);
-      intptr_t len = Smi::Value(str->ptr()->length_);
+      intptr_t len = Smi::Value(str->untag()->length_);
       intptr_t trunc_len = Utils::Minimum(len, kMaxStringElements);
       writer_->WriteUnsigned(kLatin1Data);
       writer_->WriteUnsigned(len);
       writer_->WriteUnsigned(trunc_len);
-      writer_->WriteBytes(&str->ptr()->data()[0], trunc_len);
+      writer_->WriteBytes(&str->untag()->data()[0], trunc_len);
     } else if (cid == kExternalOneByteStringCid) {
       ExternalOneByteStringPtr str = static_cast<ExternalOneByteStringPtr>(obj);
-      intptr_t len = Smi::Value(str->ptr()->length_);
+      intptr_t len = Smi::Value(str->untag()->length_);
       intptr_t trunc_len = Utils::Minimum(len, kMaxStringElements);
       writer_->WriteUnsigned(kLatin1Data);
       writer_->WriteUnsigned(len);
       writer_->WriteUnsigned(trunc_len);
-      writer_->WriteBytes(&str->ptr()->external_data_[0], trunc_len);
+      writer_->WriteBytes(&str->untag()->external_data_[0], trunc_len);
     } else if (cid == kTwoByteStringCid) {
       TwoByteStringPtr str = static_cast<TwoByteStringPtr>(obj);
-      intptr_t len = Smi::Value(str->ptr()->length_);
+      intptr_t len = Smi::Value(str->untag()->length_);
       intptr_t trunc_len = Utils::Minimum(len, kMaxStringElements);
       writer_->WriteUnsigned(kUTF16Data);
       writer_->WriteUnsigned(len);
       writer_->WriteUnsigned(trunc_len);
-      writer_->WriteBytes(&str->ptr()->data()[0], trunc_len * 2);
+      writer_->WriteBytes(&str->untag()->data()[0], trunc_len * 2);
     } else if (cid == kExternalTwoByteStringCid) {
       ExternalTwoByteStringPtr str = static_cast<ExternalTwoByteStringPtr>(obj);
-      intptr_t len = Smi::Value(str->ptr()->length_);
+      intptr_t len = Smi::Value(str->untag()->length_);
       intptr_t trunc_len = Utils::Minimum(len, kMaxStringElements);
       writer_->WriteUnsigned(kUTF16Data);
       writer_->WriteUnsigned(len);
       writer_->WriteUnsigned(trunc_len);
-      writer_->WriteBytes(&str->ptr()->external_data_[0], trunc_len * 2);
+      writer_->WriteBytes(&str->untag()->external_data_[0], trunc_len * 2);
     } else if (cid == kArrayCid || cid == kImmutableArrayCid) {
       writer_->WriteUnsigned(kLengthData);
       writer_->WriteUnsigned(
-          Smi::Value(static_cast<ArrayPtr>(obj)->ptr()->length_));
+          Smi::Value(static_cast<ArrayPtr>(obj)->untag()->length_));
     } else if (cid == kGrowableObjectArrayCid) {
       writer_->WriteUnsigned(kLengthData);
-      writer_->WriteUnsigned(
-          Smi::Value(static_cast<GrowableObjectArrayPtr>(obj)->ptr()->length_));
+      writer_->WriteUnsigned(Smi::Value(
+          static_cast<GrowableObjectArrayPtr>(obj)->untag()->length_));
     } else if (cid == kLinkedHashMapCid) {
       writer_->WriteUnsigned(kLengthData);
       writer_->WriteUnsigned(
-          Smi::Value(static_cast<LinkedHashMapPtr>(obj)->ptr()->used_data_));
+          Smi::Value(static_cast<LinkedHashMapPtr>(obj)->untag()->used_data_));
     } else if (cid == kObjectPoolCid) {
       writer_->WriteUnsigned(kLengthData);
-      writer_->WriteUnsigned(static_cast<ObjectPoolPtr>(obj)->ptr()->length_);
+      writer_->WriteUnsigned(static_cast<ObjectPoolPtr>(obj)->untag()->length_);
     } else if (IsTypedDataClassId(cid)) {
       writer_->WriteUnsigned(kLengthData);
       writer_->WriteUnsigned(
-          Smi::Value(static_cast<TypedDataPtr>(obj)->ptr()->length_));
+          Smi::Value(static_cast<TypedDataPtr>(obj)->untag()->length_));
     } else if (IsExternalTypedDataClassId(cid)) {
       writer_->WriteUnsigned(kLengthData);
       writer_->WriteUnsigned(
-          Smi::Value(static_cast<ExternalTypedDataPtr>(obj)->ptr()->length_));
+          Smi::Value(static_cast<ExternalTypedDataPtr>(obj)->untag()->length_));
     } else if (cid == kFunctionCid) {
       writer_->WriteUnsigned(kNameData);
-      ScrubAndWriteUtf8(static_cast<FunctionPtr>(obj)->ptr()->name_);
+      ScrubAndWriteUtf8(static_cast<FunctionPtr>(obj)->untag()->name_);
     } else if (cid == kCodeCid) {
-      ObjectPtr owner = static_cast<CodePtr>(obj)->ptr()->owner_;
+      ObjectPtr owner = static_cast<CodePtr>(obj)->untag()->owner_;
       if (owner->IsFunction()) {
         writer_->WriteUnsigned(kNameData);
-        ScrubAndWriteUtf8(static_cast<FunctionPtr>(owner)->ptr()->name_);
+        ScrubAndWriteUtf8(static_cast<FunctionPtr>(owner)->untag()->name_);
       } else if (owner->IsClass()) {
         writer_->WriteUnsigned(kNameData);
-        ScrubAndWriteUtf8(static_cast<ClassPtr>(owner)->ptr()->name_);
+        ScrubAndWriteUtf8(static_cast<ClassPtr>(owner)->untag()->name_);
       } else {
         writer_->WriteUnsigned(kNoData);
       }
     } else if (cid == kFieldCid) {
       writer_->WriteUnsigned(kNameData);
-      ScrubAndWriteUtf8(static_cast<FieldPtr>(obj)->ptr()->name_);
+      ScrubAndWriteUtf8(static_cast<FieldPtr>(obj)->untag()->name_);
     } else if (cid == kClassCid) {
       writer_->WriteUnsigned(kNameData);
-      ScrubAndWriteUtf8(static_cast<ClassPtr>(obj)->ptr()->name_);
+      ScrubAndWriteUtf8(static_cast<ClassPtr>(obj)->untag()->name_);
     } else if (cid == kLibraryCid) {
       writer_->WriteUnsigned(kNameData);
-      ScrubAndWriteUtf8(static_cast<LibraryPtr>(obj)->ptr()->url_);
+      ScrubAndWriteUtf8(static_cast<LibraryPtr>(obj)->untag()->url_);
     } else if (cid == kScriptCid) {
       writer_->WriteUnsigned(kNameData);
-      ScrubAndWriteUtf8(static_cast<ScriptPtr>(obj)->ptr()->url_);
+      ScrubAndWriteUtf8(static_cast<ScriptPtr>(obj)->untag()->url_);
     } else {
       writer_->WriteUnsigned(kNoData);
     }
 
     DoCount();
-    obj->ptr()->VisitPointersPrecise(isolate_, this);
+    obj->untag()->VisitPointersPrecise(isolate_, this);
     DoWrite();
-    obj->ptr()->VisitPointersPrecise(isolate_, this);
+    obj->untag()->VisitPointersPrecise(isolate_, this);
   }
 
   void ScrubAndWriteUtf8(StringPtr str) {
@@ -982,11 +984,11 @@
   void VisitHandle(uword addr) {
     FinalizablePersistentHandle* weak_persistent_handle =
         reinterpret_cast<FinalizablePersistentHandle*>(addr);
-    if (!weak_persistent_handle->raw()->IsHeapObject()) {
+    if (!weak_persistent_handle->ptr()->IsHeapObject()) {
       return;  // Free handle.
     }
 
-    writer_->WriteUnsigned(writer_->GetObjectId(weak_persistent_handle->raw()));
+    writer_->WriteUnsigned(writer_->GetObjectId(weak_persistent_handle->ptr()));
     writer_->WriteUnsigned(weak_persistent_handle->external_size());
     // Attempt to include a native symbol name.
     auto const name = NativeSymbolResolver::LookupSymbolName(
@@ -1032,7 +1034,7 @@
 
   {
     HANDLESCOPE(thread());
-    ClassTable* class_table = isolate()->class_table();
+    ClassTable* class_table = isolate_group()->class_table();
     class_count_ = class_table->NumCids() - 1;
 
     Class& cls = Class::Handle();
@@ -1202,7 +1204,7 @@
 
 void CountObjectsVisitor::VisitObject(ObjectPtr obj) {
   intptr_t cid = obj->GetClassId();
-  intptr_t size = obj->ptr()->HeapSize();
+  intptr_t size = obj->untag()->HeapSize();
   if (obj->IsNewObject()) {
     new_count_[cid] += 1;
     new_size_[cid] += size;
@@ -1215,7 +1217,7 @@
 void CountObjectsVisitor::VisitHandle(uword addr) {
   FinalizablePersistentHandle* handle =
       reinterpret_cast<FinalizablePersistentHandle*>(addr);
-  ObjectPtr obj = handle->raw();
+  ObjectPtr obj = handle->ptr();
   if (!obj->IsHeapObject()) {
     return;
   }
diff --git a/runtime/vm/object_graph_test.cc b/runtime/vm/object_graph_test.cc
index 882c685..6e968dd 100644
--- a/runtime/vm/object_graph_test.cc
+++ b/runtime/vm/object_graph_test.cc
@@ -25,7 +25,7 @@
       return kBacktrack;
     }
     ++count_;
-    size_ += obj->ptr()->HeapSize();
+    size_ += obj->untag()->HeapSize();
     return kProceed;
   }
 
@@ -40,7 +40,8 @@
 };
 
 ISOLATE_UNIT_TEST_CASE(ObjectGraph) {
-  Isolate* isolate = thread->isolate();
+  auto heap = thread->isolate_group()->heap();
+
   // Create a simple object graph with objects a, b, c, d:
   //  a+->b+->c
   //  +   +
@@ -54,14 +55,14 @@
   b.SetAt(0, c);
   b.SetAt(1, d);
   a.SetAt(11, d);
-  intptr_t a_size = a.raw()->ptr()->HeapSize();
-  intptr_t b_size = b.raw()->ptr()->HeapSize();
-  intptr_t c_size = c.raw()->ptr()->HeapSize();
-  intptr_t d_size = d.raw()->ptr()->HeapSize();
+  intptr_t a_size = a.ptr()->untag()->HeapSize();
+  intptr_t b_size = b.ptr()->untag()->HeapSize();
+  intptr_t c_size = c.ptr()->untag()->HeapSize();
+  intptr_t d_size = d.ptr()->untag()->HeapSize();
   {
     // No more allocation; raw pointers ahead.
     SafepointOperationScope safepoint(thread);
-    ObjectPtr b_raw = b.raw();
+    ObjectPtr b_raw = b.ptr();
     // Clear handles to cut unintended retained paths.
     b = Array::null();
     c = Array::null();
@@ -73,7 +74,7 @@
         // Compare count and size when 'b' is/isn't skipped.
         CounterVisitor with(Object::null(), Object::null());
         graph.IterateObjectsFrom(a, &with);
-        CounterVisitor without(b_raw, a.raw());
+        CounterVisitor without(b_raw, a.ptr());
         graph.IterateObjectsFrom(a, &without);
         // Only 'b' and 'c' were cut off.
         EXPECT_EQ(2, with.count() - without.count());
@@ -84,7 +85,7 @@
         // are thus larger, but the difference should still be just 'b' and 'c'.
         CounterVisitor with(Object::null(), Object::null());
         graph.IterateObjects(&with);
-        CounterVisitor without(b_raw, a.raw());
+        CounterVisitor without(b_raw, a.ptr());
         graph.IterateObjects(&without);
         EXPECT_EQ(2, with.count() - without.count());
         EXPECT_EQ(b_size + c_size, with.size() - without.size());
@@ -117,7 +118,7 @@
       HANDLESCOPE(thread);
       Array& path = Array::Handle(Array::New(6, Heap::kNew));
       // Trigger a full GC to increase probability of concurrent tasks.
-      isolate->heap()->CollectAllGarbage();
+      heap->CollectAllGarbage();
       intptr_t length = graph.RetainingPath(&c, path).length;
       EXPECT_LE(3, length);
       Array& expected_c = Array::Handle();
@@ -135,9 +136,9 @@
                 offset_from_parent.Value() * kWordSize);
       Array& expected_a = Array::Handle();
       expected_a ^= path.At(4);
-      EXPECT(expected_c.raw() == c.raw());
-      EXPECT(expected_b.raw() == a.At(10));
-      EXPECT(expected_a.raw() == a.raw());
+      EXPECT(expected_c.ptr() == c.ptr());
+      EXPECT(expected_b.ptr() == a.At(10));
+      EXPECT(expected_a.ptr() == a.ptr());
     }
   }
 }
@@ -149,7 +150,7 @@
   Dart_WeakPersistentHandle weak_persistent_handle;
   Array& path = Array::Handle(Array::New(1, Heap::kNew));
   ObjectGraph graph(thread);
-  Dart_Handle handle = Api::NewHandle(thread, path.raw());
+  Dart_Handle handle = Api::NewHandle(thread, path.ptr());
 
   // GC root should be a local handle
   auto result = graph.RetainingPath(&path, path);
diff --git a/runtime/vm/object_id_ring_test.cc b/runtime/vm/object_id_ring_test.cc
index d0d62c9..e1e6cf0 100644
--- a/runtime/vm/object_id_ring_test.cc
+++ b/runtime/vm/object_id_ring_test.cc
@@ -163,8 +163,10 @@
     EXPECT_EQ(ObjectIdRing::kValid, kind);
     EXPECT_NE(Object::null(), raw_obj1);
     EXPECT_NE(Object::null(), raw_obj2);
-    EXPECT_EQ(ObjectLayout::ToAddr(raw_obj), ObjectLayout::ToAddr(raw_obj1));
-    EXPECT_EQ(ObjectLayout::ToAddr(raw_obj), ObjectLayout::ToAddr(raw_obj2));
+    EXPECT_EQ(UntaggedObject::ToAddr(raw_obj),
+              UntaggedObject::ToAddr(raw_obj1));
+    EXPECT_EQ(UntaggedObject::ToAddr(raw_obj),
+              UntaggedObject::ToAddr(raw_obj2));
     // Force a scavenge.
     GCTestHelper::CollectNewSpace();
     ObjectPtr raw_object_moved1 = ring->GetObjectForId(raw_obj_id1, &kind);
@@ -173,13 +175,13 @@
     EXPECT_EQ(ObjectIdRing::kValid, kind);
     EXPECT_NE(Object::null(), raw_object_moved1);
     EXPECT_NE(Object::null(), raw_object_moved2);
-    EXPECT_EQ(ObjectLayout::ToAddr(raw_object_moved1),
-              ObjectLayout::ToAddr(raw_object_moved2));
+    EXPECT_EQ(UntaggedObject::ToAddr(raw_object_moved1),
+              UntaggedObject::ToAddr(raw_object_moved2));
     // Test that objects have moved.
-    EXPECT_NE(ObjectLayout::ToAddr(raw_obj1),
-              ObjectLayout::ToAddr(raw_object_moved1));
-    EXPECT_NE(ObjectLayout::ToAddr(raw_obj2),
-              ObjectLayout::ToAddr(raw_object_moved2));
+    EXPECT_NE(UntaggedObject::ToAddr(raw_obj1),
+              UntaggedObject::ToAddr(raw_object_moved1));
+    EXPECT_NE(UntaggedObject::ToAddr(raw_obj2),
+              UntaggedObject::ToAddr(raw_object_moved2));
     // Test that we still point at the same list.
     moved_handle = Api::NewHandle(thread, raw_object_moved1);
     // Test id reuse.
@@ -207,7 +209,7 @@
     EXPECT(!str.IsNull());
     EXPECT_EQ(3, str.Length());
 
-    ObjectPtr raw_obj = Object::RawCast(str.raw());
+    ObjectPtr raw_obj = Object::RawCast(str.ptr());
     // Verify that it is located in old heap.
     EXPECT(raw_obj->IsOldObject());
     EXPECT_NE(Object::null(), raw_obj);
@@ -221,8 +223,10 @@
     EXPECT_EQ(ObjectIdRing::kValid, kind);
     EXPECT_NE(Object::null(), raw_obj1);
     EXPECT_NE(Object::null(), raw_obj2);
-    EXPECT_EQ(ObjectLayout::ToAddr(raw_obj), ObjectLayout::ToAddr(raw_obj1));
-    EXPECT_EQ(ObjectLayout::ToAddr(raw_obj), ObjectLayout::ToAddr(raw_obj2));
+    EXPECT_EQ(UntaggedObject::ToAddr(raw_obj),
+              UntaggedObject::ToAddr(raw_obj1));
+    EXPECT_EQ(UntaggedObject::ToAddr(raw_obj),
+              UntaggedObject::ToAddr(raw_obj2));
     // Exit scope. Freeing String handle.
   }
   // Force a GC. No reference exist to the old string anymore. It should be
@@ -245,27 +249,27 @@
 
   // Insert an object and check we can look it up.
   String& obj = String::Handle(String::New("I will expire"));
-  intptr_t obj_id = ring->GetIdForObject(obj.raw());
+  intptr_t obj_id = ring->GetIdForObject(obj.ptr());
   ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
   ObjectPtr obj_lookup = ring->GetObjectForId(obj_id, &kind);
   EXPECT_EQ(ObjectIdRing::kValid, kind);
-  EXPECT_EQ(obj.raw(), obj_lookup);
+  EXPECT_EQ(obj.ptr(), obj_lookup);
 
   // Insert as many new objects as the ring size to bump out our first entry.
   Object& new_obj = Object::Handle();
   for (intptr_t i = 0; i < ObjectIdRing::kDefaultCapacity; i++) {
     new_obj = String::New("Bump");
-    intptr_t new_obj_id = ring->GetIdForObject(new_obj.raw());
+    intptr_t new_obj_id = ring->GetIdForObject(new_obj.ptr());
     ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
     ObjectPtr new_obj_lookup = ring->GetObjectForId(new_obj_id, &kind);
     EXPECT_EQ(ObjectIdRing::kValid, kind);
-    EXPECT_EQ(new_obj.raw(), new_obj_lookup);
+    EXPECT_EQ(new_obj.ptr(), new_obj_lookup);
   }
 
   // Check our first entry reports it has expired.
   obj_lookup = ring->GetObjectForId(obj_id, &kind);
   EXPECT_EQ(ObjectIdRing::kExpired, kind);
-  EXPECT_NE(obj.raw(), obj_lookup);
+  EXPECT_NE(obj.ptr(), obj_lookup);
   EXPECT_EQ(Object::null(), obj_lookup);
 }
 
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 907dda1..e9c33b4 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -71,7 +71,7 @@
   ASSERT(!instrs_.IsNull());
   uword base_address = instrs_.PayloadStart();
   intptr_t offsets_length = code.pointer_offsets_length();
-  const int32_t* offsets = code.raw_ptr()->data();
+  const int32_t* offsets = code.untag()->data();
   for (intptr_t i = 0; i < offsets_length; i++) {
     int32_t offset = offsets[i];
     ObjectPtr* object_ptr = reinterpret_cast<ObjectPtr*>(base_address + offset);
@@ -127,7 +127,7 @@
   }
   const Function& function = Function::Cast(object_);
 
-  if (function.kind() == FunctionLayout::kIrregexpFunction) {
+  if (function.kind() == UntaggedFunction::kIrregexpFunction) {
     // Regex matchers do not support breakpoints or stepping, and they only call
     // core library functions that cannot change due to reload. As a performance
     // optimization, avoid this matching of ICData to PCs for these functions'
@@ -143,7 +143,7 @@
     // calls.
 #if defined(DEBUG)
     descriptors_ = code.pc_descriptors();
-    PcDescriptors::Iterator iter(descriptors_, PcDescriptorsLayout::kIcCall);
+    PcDescriptors::Iterator iter(descriptors_, UntaggedPcDescriptors::kIcCall);
     while (iter.MoveNext()) {
       FATAL1("%s has IC calls but no ic_data_array\n", object_.ToCString());
     }
@@ -152,7 +152,7 @@
   }
 
   descriptors_ = code.pc_descriptors();
-  PcDescriptors::Iterator iter(descriptors_, PcDescriptorsLayout::kIcCall);
+  PcDescriptors::Iterator iter(descriptors_, UntaggedPcDescriptors::kIcCall);
   while (iter.MoveNext()) {
     uword pc = code.PayloadStart() + iter.PcOffset();
     CodePatcher::GetInstanceCallAt(pc, code, &object_);
@@ -191,7 +191,7 @@
   }
 }
 
-void Class::CopyStaticFieldValues(IsolateReloadContext* reload_context,
+void Class::CopyStaticFieldValues(ProgramReloadContext* reload_context,
                                   const Class& old_cls) const {
   // We only update values for non-enum classes.
   const bool update_values = !is_enum_class();
@@ -219,15 +219,21 @@
           if (update_values && !field.is_const()) {
             // Make new field point to the old field value so that both
             // old and new code see and update same value.
+            //
+            // TODO(https://dartbug.com/36097): Once we look into enabling
+            // hot-reload with --enable-isolate-groups we have to do this
+            // for all isolates.
+            reload_context->isolate()->group()->initial_field_table()->Free(
+                field.field_id());
             reload_context->isolate()->field_table()->Free(field.field_id());
-            field.set_field_id(old_field.field_id());
+            field.set_field_id_unsafe(old_field.field_id());
           }
           reload_context->AddStaticFieldMapping(old_field, field);
         } else {
           if (old_field.needs_load_guard()) {
             ASSERT(!old_field.is_unboxing_candidate());
             field.set_needs_load_guard(true);
-            field.set_is_unboxing_candidate(false);
+            field.set_is_unboxing_candidate_unsafe(false);
           }
         }
       }
@@ -272,7 +278,7 @@
   static const char* Name() { return "EnumMapTraits"; }
 
   static bool IsMatch(const Object& a, const Object& b) {
-    return a.raw() == b.raw();
+    return a.ptr() == b.ptr();
   }
 
   static uword Hash(const Object& obj) {
@@ -298,7 +304,7 @@
 //   When an enum value is deleted, we 'become' all references to the 'deleted'
 //   sentinel value. The index value is -1.
 //
-void Class::ReplaceEnum(IsolateReloadContext* reload_context,
+void Class::ReplaceEnum(ProgramReloadContext* reload_context,
                         const Class& old_enum) const {
   // We only do this for finalized enum classes.
   ASSERT(is_enum_class());
@@ -328,7 +334,7 @@
   TIR_Print("Replacing enum `%s`\n", String::Handle(Name()).ToCString());
 
   {
-    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw());
+    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.ptr());
     // Build a map of all enum name -> old enum instance.
     enum_fields = old_enum.fields();
     for (intptr_t i = 0; i < enum_fields.Length(); i++) {
@@ -338,17 +344,20 @@
         // Enum instances are only held in static fields.
         continue;
       }
+      ASSERT(field.is_const());
       if (enum_ident.Equals(Symbols::Values())) {
-        old_enum_values = field.StaticValue();
+        old_enum_values = Instance::RawCast(field.StaticConstFieldValue());
         // Non-enum instance.
         continue;
       }
       if (enum_ident.Equals(Symbols::_DeletedEnumSentinel())) {
-        old_deleted_enum_sentinel = field.StaticValue();
+        old_deleted_enum_sentinel =
+            Instance::RawCast(field.StaticConstFieldValue());
         // Non-enum instance.
         continue;
       }
-      old_enum_value = field.StaticValue();
+      old_enum_value = Instance::RawCast(field.StaticConstFieldValue());
+
       ASSERT(!old_enum_value.IsNull());
       VTIR_Print("Element %s being added to mapping\n", enum_ident.ToCString());
       bool update = enum_map.UpdateOrInsert(enum_ident, old_enum_value);
@@ -357,12 +366,12 @@
     }
     // The storage given to the map may have been reallocated, remember the new
     // address.
-    enum_map_storage = enum_map.Release().raw();
+    enum_map_storage = enum_map.Release().ptr();
   }
 
   bool enums_deleted = false;
   {
-    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw());
+    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.ptr());
     // Add a become mapping from the old instances to the new instances.
     enum_fields = fields();
     for (intptr_t i = 0; i < enum_fields.Length(); i++) {
@@ -372,17 +381,20 @@
         // Enum instances are only held in static fields.
         continue;
       }
+      ASSERT(field.is_const());
       if (enum_ident.Equals(Symbols::Values())) {
-        enum_values = field.StaticValue();
+        enum_values = Instance::RawCast(field.StaticConstFieldValue());
         // Non-enum instance.
         continue;
       }
       if (enum_ident.Equals(Symbols::_DeletedEnumSentinel())) {
-        deleted_enum_sentinel = field.StaticValue();
+        deleted_enum_sentinel =
+            Instance::RawCast(field.StaticConstFieldValue());
         // Non-enum instance.
         continue;
       }
-      enum_value = field.StaticValue();
+      enum_value = Instance::RawCast(field.StaticConstFieldValue());
+
       ASSERT(!enum_value.IsNull());
       old_enum_value ^= enum_map.GetOrNull(enum_ident);
       if (old_enum_value.IsNull()) {
@@ -399,7 +411,7 @@
     enums_deleted = enum_map.NumOccupied() > 0;
     // The storage given to the map may have been reallocated, remember the new
     // address.
-    enum_map_storage = enum_map.Release().raw();
+    enum_map_storage = enum_map.Release().ptr();
   }
 
   // Map the old E.values array to the new E.values array.
@@ -420,7 +432,7 @@
         "The following enum values were deleted from %s and will become the "
         "deleted enum sentinel:\n",
         old_enum.ToCString());
-    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.raw());
+    UnorderedHashMap<EnumMapTraits> enum_map(enum_map_storage.ptr());
     UnorderedHashMap<EnumMapTraits>::Iterator it(&enum_map);
     while (it.MoveNext()) {
       const intptr_t entry = it.Current();
@@ -463,7 +475,7 @@
     owner = func.RawOwner();
     ASSERT(!owner.IsNull());
     if (!owner.IsPatchClass()) {
-      ASSERT(owner.raw() == this->raw());
+      ASSERT(owner.ptr() == this->ptr());
       func.set_owner(patch);
     }
   }
@@ -477,14 +489,14 @@
     owner = field.RawOwner();
     ASSERT(!owner.IsNull());
     if (!owner.IsPatchClass()) {
-      ASSERT(owner.raw() == this->raw());
+      ASSERT(owner.ptr() == this->ptr());
       field.set_owner(patch);
     }
     field.ForceDynamicGuardedCidAndLength();
   }
 }
 
-void Class::MigrateImplicitStaticClosures(IsolateReloadContext* irc,
+void Class::MigrateImplicitStaticClosures(ProgramReloadContext* irc,
                                           const Class& new_cls) const {
   const Array& funcs = Array::Handle(current_functions());
   Thread* thread = Thread::Current();
@@ -526,20 +538,6 @@
   }
 };
 
-class TypedefClassConflict : public ClassReasonForCancelling {
- public:
-  TypedefClassConflict(Zone* zone, const Class& from, const Class& to)
-      : ClassReasonForCancelling(zone, from, to) {}
-
-  StringPtr ToString() {
-    return String::NewFormatted(
-        from_.IsTypedefClass()
-            ? "Typedef class cannot be redefined to be a non-typedef class: %s"
-            : "Class cannot be redefined to be a typedef class: %s",
-        from_.ToCString());
-  }
-};
-
 class EnsureFinalizedError : public ClassReasonForCancelling {
  public:
   EnsureFinalizedError(Zone* zone,
@@ -551,7 +549,7 @@
  private:
   const Error& error_;
 
-  ErrorPtr ToError() { return error_.raw(); }
+  ErrorPtr ToError() { return error_.ptr(); }
 
   StringPtr ToString() { return String::New(error_.ToErrorCString()); }
 };
@@ -642,36 +640,13 @@
   }
 };
 
-class UnimplementedDeferredLibrary : public ReasonForCancelling {
- public:
-  UnimplementedDeferredLibrary(Zone* zone,
-                               const Library& from,
-                               const Library& to,
-                               const String& name)
-      : ReasonForCancelling(zone), from_(from), to_(to), name_(name) {}
-
- private:
-  const Library& from_;
-  const Library& to_;
-  const String& name_;
-
-  StringPtr ToString() {
-    const String& lib_url = String::Handle(to_.url());
-    from_.ToCString();
-    return String::NewFormatted(
-        "Reloading support for deferred loading has not yet been implemented:"
-        " library '%s' has deferred import '%s'",
-        lib_url.ToCString(), name_.ToCString());
-  }
-};
-
 // This is executed before iterating over the instances.
 void Class::CheckReload(const Class& replacement,
-                        IsolateReloadContext* context) const {
-  ASSERT(IsolateReloadContext::IsSameClass(*this, replacement));
+                        ProgramReloadContext* context) const {
+  ASSERT(ProgramReloadContext::IsSameClass(*this, replacement));
 
   if (!is_declaration_loaded()) {
-    // The old class hasn't been used in any meanfully way, so the VM is okay
+    // The old class hasn't been used in any meaningful way, so the VM is okay
     // with any change.
     return;
   }
@@ -687,14 +662,6 @@
     return;
   }
 
-  // Class cannot change typedef property.
-  if (IsTypedefClass() != replacement.IsTypedefClass()) {
-    context->group_reload_context()->AddReasonForCancelling(
-        new (context->zone())
-            TypedefClassConflict(context->zone(), *this, replacement));
-    return;
-  }
-
   if (is_finalized()) {
     // Ensure the replacement class is also finalized.
     const Error& error =
@@ -817,7 +784,7 @@
 }
 
 bool Class::CanReloadFinalized(const Class& replacement,
-                               IsolateReloadContext* context) const {
+                               ProgramReloadContext* context) const {
   // Make sure the declaration types argument count matches for the two classes.
   // ex. class A<int,B> {} cannot be replace with class A<B> {}.
   auto group_context = context->group_reload_context();
@@ -842,7 +809,7 @@
 }
 
 bool Class::CanReloadPreFinalized(const Class& replacement,
-                                  IsolateReloadContext* context) const {
+                                  ProgramReloadContext* context) const {
   // The replacement class must also prefinalized.
   if (!replacement.is_prefinalized()) {
     context->group_reload_context()->AddReasonForCancelling(
@@ -861,22 +828,37 @@
 }
 
 void Library::CheckReload(const Library& replacement,
-                          IsolateReloadContext* context) const {
-  // TODO(26878): If the replacement library uses deferred loading,
-  // reject it.  We do not yet support reloading deferred libraries.
+                          ProgramReloadContext* context) const {
+  // Carry over the loaded bit of any deferred prefixes.
   Object& object = Object::Handle();
   LibraryPrefix& prefix = LibraryPrefix::Handle();
+  LibraryPrefix& original_prefix = LibraryPrefix::Handle();
+  String& name = String::Handle();
+  String& original_name = String::Handle();
   DictionaryIterator it(replacement);
   while (it.HasNext()) {
     object = it.GetNext();
     if (!object.IsLibraryPrefix()) continue;
-    prefix ^= object.raw();
-    if (prefix.is_deferred_load()) {
-      const String& prefix_name = String::Handle(prefix.name());
-      context->group_reload_context()->AddReasonForCancelling(
-          new (context->zone()) UnimplementedDeferredLibrary(
-              context->zone(), *this, replacement, prefix_name));
-      return;
+    prefix ^= object.ptr();
+    if (!prefix.is_deferred_load()) continue;
+
+    name = prefix.name();
+    DictionaryIterator original_it(*this);
+    while (original_it.HasNext()) {
+      object = original_it.GetNext();
+      if (!object.IsLibraryPrefix()) continue;
+      original_prefix ^= object.ptr();
+      if (!original_prefix.is_deferred_load()) continue;
+      original_name = original_prefix.name();
+      if (!name.Equals(original_name)) continue;
+
+      if (original_prefix.is_loaded()) {
+        prefix.set_is_loaded(true);
+      }
+
+      // The old prefix may be captured in the message queue for a pending load
+      // completion. This pending load should carry to the new prefix.
+      context->AddBecomeMapping(original_prefix, prefix);
     }
   }
 }
@@ -900,7 +882,7 @@
       GrowableArray<intptr_t> class_ids(2);
       Function& target = Function::Handle(zone_);
       ic.GetCheckAt(0, &class_ids, &target);
-      if ((target.raw() == smi_op_target.raw()) && (class_ids[0] == kSmiCid) &&
+      if ((target.ptr() == smi_op_target.ptr()) && (class_ids[0] == kSmiCid) &&
           (class_ids[1] == kSmiCid)) {
         // The smi fast path case, preserve the initial entry but reset the
         // count.
@@ -929,7 +911,7 @@
 
     if (rule == ICData::kStatic) {
       ASSERT(old_target_.is_static() ||
-             old_target_.kind() == FunctionLayout::kConstructor);
+             old_target_.kind() == UntaggedFunction::kConstructor);
       // This can be incorrect if the call site was an unqualified invocation.
       new_cls_ = old_target_.Owner();
       new_target_ = Resolver::ResolveFunction(zone_, new_cls_, name_);
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 1dfe634..89e394b 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/canonical_tables.h"
+#include "vm/closure_functions_cache.h"
 #include "vm/compiler/assembler/disassembler.h"
 #include "vm/debugger.h"
 #include "vm/object.h"
@@ -43,8 +44,8 @@
     jsobj->AddProperty("class", cls);
   }
   if (!ref) {
-    if (raw()->IsHeapObject()) {
-      jsobj->AddProperty("size", raw()->ptr()->HeapSize());
+    if (ptr()->IsHeapObject()) {
+      jsobj->AddProperty("size", ptr()->untag()->HeapSize());
     } else {
       jsobj->AddProperty("size", (intptr_t)0);
     }
@@ -75,7 +76,7 @@
 void Class::PrintJSONImpl(JSONStream* stream, bool ref) const {
   Isolate* isolate = Isolate::Current();
   JSONObject jsobj(stream);
-  if ((raw() == Class::null()) || (id() == kFreeListElement)) {
+  if ((ptr() == Class::null()) || (id() == kFreeListElement)) {
     // TODO(turnidge): This is weird and needs to be changed.
     jsobj.AddProperty("type", "null");
     return;
@@ -98,7 +99,7 @@
   jsobj.AddProperty("_finalized", is_finalized());
   jsobj.AddProperty("_implemented", is_implemented());
   jsobj.AddProperty("_patch", false);
-  jsobj.AddProperty("_traceAllocations", TraceAllocation(isolate));
+  jsobj.AddProperty("_traceAllocations", TraceAllocation(isolate->group()));
 
   const Class& superClass = Class::Handle(SuperClass());
   if (!superClass.IsNull()) {
@@ -174,8 +175,7 @@
   // preserved when the table grows and the entries get rehashed. Use the ring.
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  ObjectStore* object_store = isolate->object_store();
+  auto object_store = thread->isolate_group()->object_store();
   CanonicalTypeArgumentsSet typeargs_table(
       zone, object_store->canonical_type_arguments());
   const Array& table =
@@ -228,16 +228,12 @@
 static void AddFunctionServiceId(const JSONObject& jsobj,
                                  const Function& f,
                                  const Class& cls) {
-  if (cls.IsNull()) {
-    ASSERT(f.IsSignatureFunction());
-    jsobj.AddServiceId(f);
-    return;
-  }
+  ASSERT(!cls.IsNull());
   // Special kinds of functions use indices in their respective lists.
   intptr_t id = -1;
   const char* selector = NULL;
   if (f.IsNonImplicitClosureFunction()) {
-    id = Isolate::Current()->FindClosureIndex(f);
+    id = ClosureFunctionsCache::FindClosureIndex(f);
     selector = "closures";
   } else if (f.IsImplicitClosureFunction()) {
     id = cls.FindImplicitClosureFunctionIndex(f);
@@ -262,7 +258,7 @@
   // Regular functions known to their owner use their name (percent-encoded).
   String& name = String::Handle(f.name());
   Thread* thread = Thread::Current();
-  if (Resolver::ResolveFunction(thread->zone(), cls, name) == f.raw()) {
+  if (Resolver::ResolveFunction(thread->zone(), cls, name) == f.ptr()) {
     const char* encoded_name = String::EncodeIRI(name);
     if (cls.IsTopLevel()) {
       const auto& library = Library::Handle(cls.library());
@@ -283,13 +279,10 @@
 
 void Function::PrintJSONImpl(JSONStream* stream, bool ref) const {
   Class& cls = Class::Handle(Owner());
-  if (!cls.IsNull()) {
-    Error& err = Error::Handle();
-    err = cls.EnsureIsFinalized(Thread::Current());
-    ASSERT(err.IsNull());
-  } else {
-    ASSERT(IsSignatureFunction());
-  }
+  ASSERT(!cls.IsNull());
+  Error& err = Error::Handle();
+  err = cls.EnsureIsFinalized(Thread::Current());
+  ASSERT(err.IsNull());
   JSONObject jsobj(stream);
   AddCommonObjectProperties(&jsobj, "Function", ref);
   AddFunctionServiceId(jsobj, *this, cls);
@@ -336,10 +329,10 @@
   jsobj.AddProperty("_optimizedCallSiteCount", optimized_call_site_count());
   jsobj.AddProperty("_deoptimizations",
                     static_cast<intptr_t>(deoptimization_counter()));
-  if ((kind() == FunctionLayout::kImplicitGetter) ||
-      (kind() == FunctionLayout::kImplicitSetter) ||
-      (kind() == FunctionLayout::kImplicitStaticGetter) ||
-      (kind() == FunctionLayout::kFieldInitializer)) {
+  if ((kind() == UntaggedFunction::kImplicitGetter) ||
+      (kind() == UntaggedFunction::kImplicitSetter) ||
+      (kind() == UntaggedFunction::kImplicitStaticGetter) ||
+      (kind() == UntaggedFunction::kFieldInitializer)) {
     const Field& field = Field::Handle(accessor_field());
     if (!field.IsNull()) {
       jsobj.AddProperty("_field", field);
@@ -401,7 +394,7 @@
   } else if (guarded_cid() == kDynamicCid) {
     jsobj.AddProperty("_guardClass", "dynamic");
   } else {
-    ClassTable* table = Isolate::Current()->class_table();
+    ClassTable* table = IsolateGroup::Current()->class_table();
     ASSERT(table->IsValidIndex(guarded_cid()));
     cls = table->At(guarded_cid());
     jsobj.AddProperty("_guardClass", cls);
@@ -545,7 +538,7 @@
     while (entries.HasNext()) {
       entry = entries.GetNext();
       if (entry.IsLibraryPrefix()) {
-        prefix ^= entry.raw();
+        prefix ^= entry.ptr();
         imports = prefix.imports();
         if (!imports.IsNull()) {
           for (intptr_t i = 0; i < imports.Length(); i++) {
@@ -585,9 +578,9 @@
       entry = entries.GetNext();
       if (entry.IsFunction()) {
         const Function& func = Function::Cast(entry);
-        if (func.kind() == FunctionLayout::kRegularFunction ||
-            func.kind() == FunctionLayout::kGetterFunction ||
-            func.kind() == FunctionLayout::kSetterFunction) {
+        if (func.kind() == UntaggedFunction::kRegularFunction ||
+            func.kind() == UntaggedFunction::kGetterFunction ||
+            func.kind() == UntaggedFunction::kSetterFunction) {
           jsarr.AddValue(func);
         }
       }
@@ -692,7 +685,7 @@
     return;
   }
   JSONArray members(jsobj, "members");
-  Iterator iter(*this, PcDescriptorsLayout::kAnyKind);
+  Iterator iter(*this, UntaggedPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     JSONObject descriptor(&members);
     descriptor.AddPropertyF("pcOffset", "%" Px "", iter.PcOffset());
@@ -729,7 +722,7 @@
   JSONArray members(&jsobj, "members");
   String& var_name = String::Handle();
   for (intptr_t i = 0; i < Length(); i++) {
-    LocalVarDescriptorsLayout::VarInfo info;
+    UntaggedLocalVarDescriptors::VarInfo info;
     var_name = GetName(i);
     GetInfo(i, &info);
     JSONObject var(&members);
@@ -802,13 +795,13 @@
 
 void ICData::PrintToJSONArray(const JSONArray& jsarray,
                               TokenPosition token_pos) const {
-  Isolate* isolate = Isolate::Current();
+  auto class_table = IsolateGroup::Current()->class_table();
   Class& cls = Class::Handle();
   Function& func = Function::Handle();
 
   JSONObject jsobj(&jsarray);
   jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
-  jsobj.AddProperty("tokenPos", token_pos.value());
+  jsobj.AddProperty("tokenPos", static_cast<intptr_t>(token_pos.Serialize()));
   // TODO(rmacnak): Figure out how to stringify DeoptReasons().
   // jsobj.AddProperty("deoptReasons", ...);
 
@@ -819,7 +812,7 @@
     intptr_t count = GetCountAt(i);
     if (!is_static_call()) {
       intptr_t cid = GetReceiverClassIdAt(i);
-      cls = isolate->class_table()->At(cid);
+      cls = class_table->At(cid);
       cache_entry.AddProperty("receiver", cls);
     }
     cache_entry.AddProperty("target", func);
@@ -1017,7 +1010,7 @@
     cls = cls.SuperClass();
   }
   do {
-    classes.Add(&Class::Handle(cls.raw()));
+    classes.Add(&Class::Handle(cls.ptr()));
     cls = cls.SuperClass();
   } while (!cls.IsNull());
 
@@ -1058,12 +1051,12 @@
   JSONObject jsobj(stream);
 
   // Handle certain special instance values.
-  if (raw() == Object::sentinel().raw()) {
+  if (ptr() == Object::sentinel().ptr()) {
     jsobj.AddProperty("type", "Sentinel");
     jsobj.AddProperty("kind", "NotInitialized");
     jsobj.AddProperty("valueAsString", "<not initialized>");
     return;
-  } else if (raw() == Object::transition_sentinel().raw()) {
+  } else if (ptr() == Object::transition_sentinel().ptr()) {
     jsobj.AddProperty("type", "Sentinel");
     jsobj.AddProperty("kind", "BeingInitialized");
     jsobj.AddProperty("valueAsString", "<being initialized>");
@@ -1103,12 +1096,11 @@
 }
 
 void Type::PrintJSONImpl(JSONStream* stream, bool ref) const {
-  // TODO(regis): Function types are not handled properly.
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
   jsobj.AddProperty("kind", "Type");
   const Class& type_cls = Class::Handle(type_class());
-  if (type_cls.DeclarationType() == raw()) {
+  if (type_cls.DeclarationType() == ptr()) {
     intptr_t cid = type_cls.id();
     jsobj.AddFixedServiceId("classes/%" Pd "/types/%d", cid, 0);
   } else {
@@ -1127,6 +1119,13 @@
   }
 }
 
+void FunctionType::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  JSONObject jsobj(stream);
+  PrintSharedInstanceJSON(&jsobj, ref);
+  jsobj.AddProperty("kind", "FunctionType");
+  // TODO(regis): Function types were not handled before, necessary now?
+}
+
 void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
@@ -1149,6 +1148,7 @@
   const String& user_name = String::Handle(UserVisibleName());
   const String& vm_name = String::Handle(Name());
   AddNameProperties(&jsobj, user_name.ToCString(), vm_name.ToCString());
+  // TODO(regis): parameterizedClass is meaningless and always null.
   const Class& param_cls = Class::Handle(parameterized_class());
   jsobj.AddProperty("parameterizedClass", param_cls);
   if (ref) {
@@ -1193,7 +1193,7 @@
 
 void String::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
-  if (raw() == Symbols::OptimizedOut().raw()) {
+  if (ptr() == Symbols::OptimizedOut().ptr()) {
     // TODO(turnidge): This is a hack.  The user could have this
     // special string in their program.  Fixing this involves updating
     // the debugging api a bit.
@@ -1472,10 +1472,6 @@
   Object::PrintJSONImpl(stream, ref);
 }
 
-void SignatureData::PrintJSONImpl(JSONStream* stream, bool ref) const {
-  Object::PrintJSONImpl(stream, ref);
-}
-
 void Closure::PrintJSONImpl(JSONStream* stream, bool ref) const {
   Instance::PrintJSONImpl(stream, ref);
 }
diff --git a/runtime/vm/object_set.h b/runtime/vm/object_set.h
index 6d8e1ff..36a3101 100644
--- a/runtime/vm/object_set.h
+++ b/runtime/vm/object_set.h
@@ -64,7 +64,7 @@
   }
 
   bool Contains(ObjectPtr raw_obj) const {
-    uword raw_addr = ObjectLayout::ToAddr(raw_obj);
+    uword raw_addr = UntaggedObject::ToAddr(raw_obj);
     ObjectSetRegion* region;
     if (FindRegion(raw_addr, &region)) {
       return region->ContainsObject(raw_addr);
@@ -73,7 +73,7 @@
   }
 
   void Add(ObjectPtr raw_obj) {
-    uword raw_addr = ObjectLayout::ToAddr(raw_obj);
+    uword raw_addr = UntaggedObject::ToAddr(raw_obj);
     ObjectSetRegion* region;
     if (FindRegion(raw_addr, &region)) {
       return region->AddObject(raw_addr);
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 143a7bb..76c15da 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -65,7 +65,7 @@
   // Expansion of inlined functions requires additional memory at run time,
   // avoid it.
   stack_trace.set_expand_inlined(false);
-  return stack_trace.raw();
+  return stack_trace.ptr();
 }
 
 ErrorPtr IsolateObjectStore::PreallocateObjects() {
@@ -144,12 +144,9 @@
 ErrorPtr ObjectStore::PreallocateObjects() {
   Thread* thread = Thread::Current();
   IsolateGroup* isolate_group = thread->isolate_group();
-  Isolate* isolate = thread->isolate();
   // Either we are the object store on isolate group, or isolate group has no
   // object store and we are the object store on the isolate.
-  ASSERT(isolate_group != NULL && (isolate_group->object_store() == this ||
-                                   (isolate_group->object_store() == nullptr &&
-                                    isolate->object_store() == this)));
+  ASSERT(isolate_group != nullptr && isolate_group->object_store() == this);
 
   if (this->stack_overflow() != Instance::null()) {
     ASSERT(this->out_of_memory() != Instance::null());
@@ -165,13 +162,13 @@
 
   result = AllocateObjectByClassName(library, Symbols::StackOverflowError());
   if (result.IsError()) {
-    return Error::Cast(result).raw();
+    return Error::Cast(result).ptr();
   }
   set_stack_overflow(Instance::Cast(result));
 
   result = AllocateObjectByClassName(library, Symbols::OutOfMemoryError());
   if (result.IsError()) {
-    return Error::Cast(result).raw();
+    return Error::Cast(result).ptr();
   }
   set_out_of_memory(Instance::Cast(result));
 
@@ -188,7 +185,7 @@
   const Function& result = Function::Handle(
       Resolver::ResolveDynamicFunction(thread->zone(), cls, mangled));
   ASSERT(!result.IsNull());
-  return result.raw();
+  return result.ptr();
 }
 
 void ObjectStore::InitKnownObjects() {
@@ -204,8 +201,8 @@
   // The rest of these objects are only needed for code generation.
   return;
 #else
-  Isolate* isolate = thread->isolate();
-  ASSERT(isolate != NULL && isolate->object_store() == this);
+  auto isolate_group = thread->isolate_group();
+  ASSERT(isolate_group != nullptr && isolate_group->object_store() == this);
 
   const Library& async_lib = Library::Handle(zone, async_library());
   ASSERT(!async_lib.IsNull());
@@ -367,8 +364,7 @@
     ASSERT(!type.IsNull());
     type_args = TypeArguments::New(1);
     type_args.SetTypeAt(0, type);
-    type = Type::New(cls, type_args, TokenPosition::kNoSource,
-                     Nullability::kNonNullable);
+    type = Type::New(cls, type_args, Nullability::kNonNullable);
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
     set_non_nullable_future_never_type(type);
@@ -376,8 +372,7 @@
     ASSERT(!type.IsNull());
     type_args = TypeArguments::New(1);
     type_args.SetTypeAt(0, type);
-    type = Type::New(cls, type_args, TokenPosition::kNoSource,
-                     Nullability::kNullable);
+    type = Type::New(cls, type_args, Nullability::kNullable);
     type.SetIsFinalized();
     type ^= type.Canonicalize(thread, nullptr);
     set_nullable_future_null_type(type);
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 7ffcb71..3642e50 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -132,6 +132,7 @@
   RW(Class, weak_property_class)                                               \
   RW(Array, symbol_table)                                                      \
   RW(Array, canonical_types)                                                   \
+  RW(Array, canonical_function_types)                                          \
   RW(Array, canonical_type_parameters)                                         \
   RW(Array, canonical_type_arguments)                                          \
   RW(Library, async_library)                                                   \
@@ -322,7 +323,7 @@
 
 #define DECLARE_GETTER_AND_SETTER(Type, name)                                  \
   DECLARE_GETTER(Type, name)                                                   \
-  void set_##name(const Type& value) { name##_ = value.raw(); }
+  void set_##name(const Type& value) { name##_ = value.ptr(); }
   ISOLATE_OBJECT_STORE_FIELD_LIST(DECLARE_GETTER, DECLARE_GETTER_AND_SETTER)
 #undef DECLARE_GETTER
 #undef DECLARE_GETTER_AND_SETTER
@@ -392,7 +393,7 @@
   static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
 #define DECLARE_GETTER_AND_SETTER(Type, name)                                  \
   DECLARE_GETTER(Type, name)                                                   \
-  void set_##name(const Type& value) { name##_ = value.raw(); }
+  void set_##name(const Type& value) { name##_ = value.ptr(); }
 #define DECLARE_LAZY_INIT_GETTER(Type, name, init)                             \
   Type##Ptr name() {                                                           \
     if (name##_ == Type::null()) {                                             \
@@ -403,10 +404,10 @@
   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.raw(); }
+  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.raw(); }
+  void set_##name(const Type& value) { name##_ = value.ptr(); }
   OBJECT_STORE_FIELD_LIST(DECLARE_GETTER,
                           DECLARE_GETTER_AND_SETTER,
                           DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER,
@@ -436,7 +437,7 @@
     switch (index) {
 #define MAKE_CASE(CamelName, name)                                             \
   case k##CamelName:                                                           \
-    name##_library_ = value.raw();                                             \
+    name##_library_ = value.ptr();                                             \
     break;
 
       FOR_EACH_BOOTSTRAP_LIBRARY(MAKE_CASE)
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index cc5e5c1..cad9d62 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -12,6 +12,7 @@
 #include "platform/globals.h"
 
 #include "vm/class_finalizer.h"
+#include "vm/closure_functions_cache.h"
 #include "vm/code_descriptors.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/compiler_state.h"
@@ -41,7 +42,7 @@
       Library::Handle(), class_name, script, TokenPosition::kNoSource));
   cls.set_is_synthesized_class();  // Dummy class for testing.
   cls.set_is_declaration_loaded();
-  return cls.raw();
+  return cls.ptr();
 }
 
 ISOLATE_UNIT_TEST_CASE(Class) {
@@ -77,17 +78,20 @@
 
   // Create and populate the function arrays.
   const Array& functions = Array::Handle(Array::New(6));
+  FunctionType& signature = FunctionType::Handle();
   Function& function = Function::Handle();
   String& function_name = String::Handle();
   function_name = Symbols::New(thread, "foo");
-  function =
-      Function::New(function_name, FunctionLayout::kRegularFunction, false,
-                    false, false, false, false, cls, TokenPosition::kMinSource);
+  signature = FunctionType::New();
+  function = Function::New(signature, function_name,
+                           UntaggedFunction::kRegularFunction, false, false,
+                           false, false, false, cls, TokenPosition::kMinSource);
   functions.SetAt(0, function);
   function_name = Symbols::New(thread, "bar");
-  function =
-      Function::New(function_name, FunctionLayout::kRegularFunction, false,
-                    false, false, false, false, cls, TokenPosition::kMinSource);
+  signature = FunctionType::New();
+  function = Function::New(signature, function_name,
+                           UntaggedFunction::kRegularFunction, false, false,
+                           false, false, false, cls, TokenPosition::kMinSource);
 
   const int kNumFixedParameters = 2;
   const int kNumOptionalParameters = 3;
@@ -98,26 +102,30 @@
   functions.SetAt(1, function);
 
   function_name = Symbols::New(thread, "baz");
-  function =
-      Function::New(function_name, FunctionLayout::kRegularFunction, false,
-                    false, false, false, false, cls, TokenPosition::kMinSource);
+  signature = FunctionType::New();
+  function = Function::New(signature, function_name,
+                           UntaggedFunction::kRegularFunction, false, false,
+                           false, false, false, cls, TokenPosition::kMinSource);
   functions.SetAt(2, function);
 
   function_name = Symbols::New(thread, "Foo");
-  function =
-      Function::New(function_name, FunctionLayout::kRegularFunction, true,
-                    false, false, false, false, cls, TokenPosition::kMinSource);
+  signature = FunctionType::New();
+  function = Function::New(signature, function_name,
+                           UntaggedFunction::kRegularFunction, true, false,
+                           false, false, false, cls, TokenPosition::kMinSource);
 
   functions.SetAt(3, function);
   function_name = Symbols::New(thread, "Bar");
-  function =
-      Function::New(function_name, FunctionLayout::kRegularFunction, true,
-                    false, false, false, false, cls, TokenPosition::kMinSource);
+  signature = FunctionType::New();
+  function = Function::New(signature, function_name,
+                           UntaggedFunction::kRegularFunction, true, false,
+                           false, false, false, cls, TokenPosition::kMinSource);
   functions.SetAt(4, function);
   function_name = Symbols::New(thread, "BaZ");
-  function =
-      Function::New(function_name, FunctionLayout::kRegularFunction, true,
-                    false, false, false, false, cls, TokenPosition::kMinSource);
+  signature = FunctionType::New();
+  function = Function::New(signature, function_name,
+                           UntaggedFunction::kRegularFunction, true, false,
+                           false, false, false, cls, TokenPosition::kMinSource);
   functions.SetAt(5, function);
 
   // Setup the functions in the class.
@@ -135,13 +143,13 @@
   function = cls.LookupStaticFunction(function_name);
   EXPECT(!function.IsNull());
   EXPECT(function_name.Equals(String::Handle(function.name())));
-  EXPECT_EQ(cls.raw(), function.Owner());
+  EXPECT_EQ(cls.ptr(), function.Owner());
   EXPECT(function.is_static());
   function_name = String::New("baz");
   function = Resolver::ResolveDynamicFunction(Z, cls, function_name);
   EXPECT(!function.IsNull());
   EXPECT(function_name.Equals(String::Handle(function.name())));
-  EXPECT_EQ(cls.raw(), function.Owner());
+  EXPECT_EQ(cls.ptr(), function.Owner());
   EXPECT(!function.is_static());
   function = cls.LookupStaticFunction(function_name);
   EXPECT(function.IsNull());
@@ -161,8 +169,8 @@
 
 ISOLATE_UNIT_TEST_CASE(SixtyThousandDartClasses) {
   auto zone = thread->zone();
-  auto isolate = thread->isolate();
-  auto class_table = isolate->class_table();
+  auto isolate_group = thread->isolate_group();
+  auto class_table = isolate_group->class_table();
 
   const intptr_t start_cid = class_table->NumCids();
   const intptr_t num_classes = std::numeric_limits<uint16_t>::max() - start_cid;
@@ -223,7 +231,7 @@
   EXPECT_EQ((1 << 16) - 1, class_table->NumCids());
 
   // Ensure GC runs and can recognize all those new instances.
-  isolate->heap()->CollectAllGarbage();
+  isolate_group->heap()->CollectAllGarbage();
 
   // Ensure the instances are what we expect.
   for (intptr_t i = 0; i < num_classes; ++i) {
@@ -256,14 +264,14 @@
       TypeArguments::Handle(TypeArguments::New(2));
   type_arguments2.SetTypeAt(0, type1);
   type_arguments2.SetTypeAt(1, type2);
-  EXPECT_NE(type_arguments1.raw(), type_arguments2.raw());
+  EXPECT_NE(type_arguments1.ptr(), type_arguments2.ptr());
   OS::PrintErr("1: %s\n", type_arguments1.ToCString());
   OS::PrintErr("2: %s\n", type_arguments2.ToCString());
   EXPECT(type_arguments1.Equals(type_arguments2));
   TypeArguments& type_arguments3 = TypeArguments::Handle();
   type_arguments1.Canonicalize(thread, nullptr);
   type_arguments3 ^= type_arguments2.Canonicalize(thread, nullptr);
-  EXPECT_EQ(type_arguments1.raw(), type_arguments3.raw());
+  EXPECT_EQ(type_arguments1.ptr(), type_arguments3.ptr());
 }
 
 TEST_CASE(Class_EndTokenPos) {
@@ -292,7 +300,7 @@
   const Script& scr = Script::Handle(cls.script());
   intptr_t line;
   intptr_t col;
-  scr.GetTokenLocation(end_token_pos, &line, &col);
+  EXPECT(scr.GetTokenLocation(end_token_pos, &line, &col));
   EXPECT_EQ(9, line);
   EXPECT_EQ(1, col);
 }
@@ -313,7 +321,7 @@
 
   EXPECT_EQ(kObjectAlignment, empty_class.host_instance_size());
   Instance& instance = Instance::Handle(Instance::New(empty_class));
-  EXPECT_EQ(empty_class.raw(), instance.clazz());
+  EXPECT_EQ(empty_class.ptr(), instance.clazz());
 
   class_name = Symbols::New(thread, "OneFieldClass");
   const Class& one_field_class =
@@ -337,7 +345,7 @@
     one_field_class.SetFields(one_fields);
   }
   one_field_class.Finalize();
-  intptr_t header_size = sizeof(ObjectLayout);
+  intptr_t header_size = sizeof(UntaggedObject);
   EXPECT_EQ(Utils::RoundUp((header_size + (1 * kWordSize)), kObjectAlignment),
             one_field_class.host_instance_size());
   EXPECT_EQ(header_size, field.HostOffset());
@@ -348,7 +356,7 @@
 
 ISOLATE_UNIT_TEST_CASE(Smi) {
   const Smi& smi = Smi::Handle(Smi::New(5));
-  Object& smi_object = Object::Handle(smi.raw());
+  Object& smi_object = Object::Handle(smi.ptr());
   EXPECT(smi.IsSmi());
   EXPECT(smi_object.IsSmi());
   EXPECT_EQ(5, smi.Value());
@@ -552,7 +560,7 @@
   mint2 ^= Integer::NewCanonical(mint_string);
   EXPECT_EQ(mint1.value(), mint_value);
   EXPECT_EQ(mint2.value(), mint_value);
-  EXPECT_EQ(mint1.raw(), mint2.raw());
+  EXPECT_EQ(mint1.ptr(), mint2.ptr());
 #endif
 }
 
@@ -560,7 +568,7 @@
   {
     const double dbl_const = 5.0;
     const Double& dbl = Double::Handle(Double::New(dbl_const));
-    Object& dbl_object = Object::Handle(dbl.raw());
+    Object& dbl_object = Object::Handle(dbl.ptr());
     EXPECT(dbl.IsDouble());
     EXPECT(dbl_object.IsDouble());
     EXPECT_EQ(dbl_const, dbl.value());
@@ -569,7 +577,7 @@
   {
     const double dbl_const = -5.0;
     const Double& dbl = Double::Handle(Double::New(dbl_const));
-    Object& dbl_object = Object::Handle(dbl.raw());
+    Object& dbl_object = Object::Handle(dbl.ptr());
     EXPECT(dbl.IsDouble());
     EXPECT(dbl_object.IsDouble());
     EXPECT_EQ(dbl_const, dbl.value());
@@ -578,7 +586,7 @@
   {
     const double dbl_const = 0.0;
     const Double& dbl = Double::Handle(Double::New(dbl_const));
-    Object& dbl_object = Object::Handle(dbl.raw());
+    Object& dbl_object = Object::Handle(dbl.ptr());
     EXPECT(dbl.IsDouble());
     EXPECT(dbl_object.IsDouble());
     EXPECT_EQ(dbl_const, dbl.value());
@@ -593,8 +601,8 @@
     EXPECT_EQ(dbl_const, dbl1.value());
     EXPECT_EQ(dbl_const, dbl2.value());
     EXPECT_EQ(dbl_const, dbl3.value());
-    EXPECT_EQ(dbl1.raw(), dbl2.raw());
-    EXPECT_EQ(dbl1.raw(), dbl3.raw());
+    EXPECT_EQ(dbl1.ptr(), dbl2.ptr());
+    EXPECT_EQ(dbl1.ptr(), dbl3.ptr());
   }
 
   {
@@ -1787,18 +1795,18 @@
   const String& nine = String::Handle(Symbols::New(thread, "Neun"));
   const String& ten = String::Handle(Symbols::New(thread, "Zehn"));
   String& eins = String::Handle(Symbols::New(thread, "Eins"));
-  EXPECT_EQ(one.raw(), eins.raw());
-  EXPECT(one.raw() != two.raw());
+  EXPECT_EQ(one.ptr(), eins.ptr());
+  EXPECT(one.ptr() != two.ptr());
   EXPECT(two.Equals(String::Handle(String::New("Zwei"))));
-  EXPECT_EQ(two.raw(), Symbols::New(thread, "Zwei"));
-  EXPECT_EQ(three.raw(), Symbols::New(thread, "Drei"));
-  EXPECT_EQ(four.raw(), Symbols::New(thread, "Vier"));
-  EXPECT_EQ(five.raw(), Symbols::New(thread, "Fuenf"));
-  EXPECT_EQ(six.raw(), Symbols::New(thread, "Sechs"));
-  EXPECT_EQ(seven.raw(), Symbols::New(thread, "Sieben"));
-  EXPECT_EQ(eight.raw(), Symbols::New(thread, "Acht"));
-  EXPECT_EQ(nine.raw(), Symbols::New(thread, "Neun"));
-  EXPECT_EQ(ten.raw(), Symbols::New(thread, "Zehn"));
+  EXPECT_EQ(two.ptr(), Symbols::New(thread, "Zwei"));
+  EXPECT_EQ(three.ptr(), Symbols::New(thread, "Drei"));
+  EXPECT_EQ(four.ptr(), Symbols::New(thread, "Vier"));
+  EXPECT_EQ(five.ptr(), Symbols::New(thread, "Fuenf"));
+  EXPECT_EQ(six.ptr(), Symbols::New(thread, "Sechs"));
+  EXPECT_EQ(seven.ptr(), Symbols::New(thread, "Sieben"));
+  EXPECT_EQ(eight.ptr(), Symbols::New(thread, "Acht"));
+  EXPECT_EQ(nine.ptr(), Symbols::New(thread, "Neun"));
+  EXPECT_EQ(ten.ptr(), Symbols::New(thread, "Zehn"));
 
   // Make sure to cause symbol table overflow.
   for (int i = 0; i < 1024; i++) {
@@ -1807,23 +1815,23 @@
     Symbols::New(thread, buf);
   }
   eins = Symbols::New(thread, "Eins");
-  EXPECT_EQ(one.raw(), eins.raw());
-  EXPECT_EQ(two.raw(), Symbols::New(thread, "Zwei"));
-  EXPECT_EQ(three.raw(), Symbols::New(thread, "Drei"));
-  EXPECT_EQ(four.raw(), Symbols::New(thread, "Vier"));
-  EXPECT_EQ(five.raw(), Symbols::New(thread, "Fuenf"));
-  EXPECT_EQ(six.raw(), Symbols::New(thread, "Sechs"));
-  EXPECT_EQ(seven.raw(), Symbols::New(thread, "Sieben"));
-  EXPECT_EQ(eight.raw(), Symbols::New(thread, "Acht"));
-  EXPECT_EQ(nine.raw(), Symbols::New(thread, "Neun"));
-  EXPECT_EQ(ten.raw(), Symbols::New(thread, "Zehn"));
+  EXPECT_EQ(one.ptr(), eins.ptr());
+  EXPECT_EQ(two.ptr(), Symbols::New(thread, "Zwei"));
+  EXPECT_EQ(three.ptr(), Symbols::New(thread, "Drei"));
+  EXPECT_EQ(four.ptr(), Symbols::New(thread, "Vier"));
+  EXPECT_EQ(five.ptr(), Symbols::New(thread, "Fuenf"));
+  EXPECT_EQ(six.ptr(), Symbols::New(thread, "Sechs"));
+  EXPECT_EQ(seven.ptr(), Symbols::New(thread, "Sieben"));
+  EXPECT_EQ(eight.ptr(), Symbols::New(thread, "Acht"));
+  EXPECT_EQ(nine.ptr(), Symbols::New(thread, "Neun"));
+  EXPECT_EQ(ten.ptr(), Symbols::New(thread, "Zehn"));
 
   // Symbols from Strings.
   eins = String::New("Eins");
   EXPECT(!eins.IsSymbol());
   String& ein_symbol = String::Handle(Symbols::New(thread, eins));
-  EXPECT_EQ(one.raw(), ein_symbol.raw());
-  EXPECT(one.raw() != eins.raw());
+  EXPECT_EQ(one.ptr(), ein_symbol.ptr());
+  EXPECT(one.ptr() != eins.ptr());
 
   uint16_t char16[] = {'E', 'l', 'f'};
   String& elf1 = String::Handle(Symbols::FromUTF16(thread, char16, 3));
@@ -1832,8 +1840,8 @@
       Symbols::New(thread, String::Handle(String::FromUTF32(char32, 3))));
   EXPECT(elf1.IsSymbol());
   EXPECT(elf2.IsSymbol());
-  EXPECT_EQ(elf1.raw(), Symbols::New(thread, "Elf"));
-  EXPECT_EQ(elf2.raw(), Symbols::New(thread, "Elf"));
+  EXPECT_EQ(elf1.ptr(), Symbols::New(thread, "Elf"));
+  EXPECT_EQ(elf2.ptr(), Symbols::New(thread, "Elf"));
 }
 
 ISOLATE_UNIT_TEST_CASE(SymbolUnicode) {
@@ -1841,12 +1849,12 @@
   String& monkey = String::Handle(Symbols::FromUTF16(thread, monkey_utf16, 2));
   EXPECT(monkey.IsSymbol());
   const char monkey_utf8[] = {'\xf0', '\x9f', '\x90', '\xb5', 0};
-  EXPECT_EQ(monkey.raw(), Symbols::New(thread, monkey_utf8));
+  EXPECT_EQ(monkey.ptr(), Symbols::New(thread, monkey_utf8));
 
   int32_t kMonkeyFace = 0x1f435;
   String& monkey2 = String::Handle(
       Symbols::New(thread, String::Handle(String::FromUTF32(&kMonkeyFace, 1))));
-  EXPECT_EQ(monkey.raw(), monkey2.raw());
+  EXPECT_EQ(monkey.ptr(), monkey2.ptr());
 
   // Unicode cat face with tears of joy.
   int32_t kCatFaceWithTearsOfJoy = 0x1f639;
@@ -1856,7 +1864,7 @@
   uint16_t cat_utf16[] = {0xd83d, 0xde39};
   String& cat2 = String::Handle(Symbols::FromUTF16(thread, cat_utf16, 2));
   EXPECT(cat2.IsSymbol());
-  EXPECT_EQ(cat2.raw(), cat.raw());
+  EXPECT_EQ(cat2.ptr(), cat.ptr());
 }
 
 ISOLATE_UNIT_TEST_CASE(Bool) {
@@ -1875,11 +1883,11 @@
   array.SetAt(0, array);
   array.SetAt(2, array);
   element = array.At(0);
-  EXPECT_EQ(array.raw(), element.raw());
+  EXPECT_EQ(array.ptr(), element.ptr());
   element = array.At(1);
   EXPECT(element.IsNull());
   element = array.At(2);
-  EXPECT_EQ(array.raw(), element.raw());
+  EXPECT_EQ(array.ptr(), element.ptr());
 
   Array& other_array = Array::Handle(Array::New(kArrayLen));
   other_array.SetAt(0, array);
@@ -1903,7 +1911,7 @@
   EXPECT(Smi::Cast(element).IsZero());
 
   array.MakeImmutable();
-  Object& obj = Object::Handle(array.raw());
+  Object& obj = Object::Handle(array.ptr());
   EXPECT(obj.IsArray());
 }
 
@@ -2157,15 +2165,15 @@
   }
   used_size = Array::InstanceSize(array.Length());
   new_array = Array::MakeFixedLength(array);
-  addr = ObjectLayout::ToAddr(new_array.raw());
-  obj = ObjectLayout::FromAddr(addr);
+  addr = UntaggedObject::ToAddr(new_array.ptr());
+  obj = UntaggedObject::FromAddr(addr);
   EXPECT(obj.IsArray());
-  new_array ^= obj.raw();
+  new_array ^= obj.ptr();
   EXPECT_EQ(2, new_array.Length());
   addr += used_size;
-  obj = ObjectLayout::FromAddr(addr);
+  obj = UntaggedObject::FromAddr(addr);
   EXPECT(obj.IsTypedData());
-  left_over_array ^= obj.raw();
+  left_over_array ^= obj.ptr();
   EXPECT_EQ(4 * kWordSize - TypedData::InstanceSize(0),
             left_over_array.Length());
 
@@ -2180,16 +2188,16 @@
   }
   used_size = Array::InstanceSize(array.Length());
   new_array = Array::MakeFixedLength(array);
-  addr = ObjectLayout::ToAddr(new_array.raw());
-  obj = ObjectLayout::FromAddr(addr);
+  addr = UntaggedObject::ToAddr(new_array.ptr());
+  obj = UntaggedObject::FromAddr(addr);
   EXPECT(obj.IsArray());
-  new_array ^= obj.raw();
+  new_array ^= obj.ptr();
   EXPECT_EQ(3, new_array.Length());
   addr += used_size;
-  obj = ObjectLayout::FromAddr(addr);
+  obj = UntaggedObject::FromAddr(addr);
   if (TypedData::InstanceSize(0) <= 2 * kWordSize) {
     EXPECT(obj.IsTypedData());
-    left_over_array ^= obj.raw();
+    left_over_array ^= obj.ptr();
     EXPECT_EQ(2 * kWordSize - TypedData::InstanceSize(0),
               left_over_array.Length());
   } else {
@@ -2206,15 +2214,15 @@
   }
   used_size = Array::InstanceSize(array.Length());
   new_array = Array::MakeFixedLength(array);
-  addr = ObjectLayout::ToAddr(new_array.raw());
-  obj = ObjectLayout::FromAddr(addr);
+  addr = UntaggedObject::ToAddr(new_array.ptr());
+  obj = UntaggedObject::FromAddr(addr);
   EXPECT(obj.IsArray());
-  new_array ^= obj.raw();
+  new_array ^= obj.ptr();
   EXPECT_EQ(1, new_array.Length());
   addr += used_size;
-  obj = ObjectLayout::FromAddr(addr);
+  obj = UntaggedObject::FromAddr(addr);
   EXPECT(obj.IsTypedData());
-  left_over_array ^= obj.raw();
+  left_over_array ^= obj.ptr();
   EXPECT_EQ(8 * kWordSize - TypedData::InstanceSize(0),
             left_over_array.Length());
 
@@ -2225,7 +2233,7 @@
     value = Smi::New(i);
     array.Add(value);
   }
-  Heap* heap = Isolate::Current()->heap();
+  Heap* heap = IsolateGroup::Current()->heap();
   GCTestHelper::CollectAllGarbage();
   intptr_t capacity_before = heap->CapacityInWords(Heap::kOld);
   new_array = Array::MakeFixedLength(array);
@@ -2496,7 +2504,7 @@
   const Context& context = Context::Handle(Context::New(kNumVariables));
   context.set_parent(parent_context);
   EXPECT_EQ(kNumVariables, context.num_variables());
-  EXPECT(Context::Handle(context.parent()).raw() == parent_context.raw());
+  EXPECT(Context::Handle(context.parent()).ptr() == parent_context.ptr());
   EXPECT_EQ(0, Context::Handle(context.parent()).num_variables());
   EXPECT(Context::Handle(Context::Handle(context.parent()).parent()).IsNull());
   Object& variable = Object::Handle(context.At(0));
@@ -2515,7 +2523,8 @@
 ISOLATE_UNIT_TEST_CASE(ContextScope) {
   // We need an active compiler context to manipulate scopes, since local
   // variables and slots can be canonicalized in the compiler state.
-  CompilerState compiler_state(Thread::Current(), /*is_aot=*/false);
+  CompilerState compiler_state(Thread::Current(), /*is_aot=*/false,
+                               /*is_optimizing=*/false);
 
   const intptr_t parent_scope_function_level = 0;
   LocalScope* parent_scope =
@@ -2629,9 +2638,10 @@
   const Context& context = Context::Handle(Context::New(0));
   Function& parent = Function::Handle();
   const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
-  parent =
-      Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
-                    false, false, false, cls, TokenPosition::kMinSource);
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
+  parent = Function::New(signature, parent_name,
+                         UntaggedFunction::kRegularFunction, false, false,
+                         false, false, false, cls, TokenPosition::kMinSource);
   functions.SetAt(0, parent);
   {
     SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
@@ -2648,9 +2658,9 @@
   const Class& closure_class = Class::Handle(closure.clazz());
   EXPECT_EQ(closure_class.id(), kClosureCid);
   const Function& closure_function = Function::Handle(closure.function());
-  EXPECT_EQ(closure_function.raw(), function.raw());
+  EXPECT_EQ(closure_function.ptr(), function.ptr());
   const Context& closure_context = Context::Handle(closure.context());
-  EXPECT_EQ(closure_context.raw(), context.raw());
+  EXPECT_EQ(closure_context.ptr(), context.ptr());
 }
 
 ISOLATE_UNIT_TEST_CASE(ObjectPrinting) {
@@ -2659,7 +2669,7 @@
   EXPECT_STREQ("-15", Smi::Handle(Smi::New(-15)).ToCString());
 
   // bool class and true/false values.
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
   const Class& bool_class = Class::Handle(object_store->bool_class());
   EXPECT_STREQ("Library:'dart:core' Class: bool", bool_class.ToCString());
   EXPECT_STREQ("true", Bool::True().ToCString());
@@ -2706,9 +2716,10 @@
   const Library& owner_library = Library::Handle(CreateDummyLibrary(lib_name));
   owner_class.set_library(owner_library);
   const String& function_name = String::ZoneHandle(Symbols::New(thread, name));
-  return Function::New(function_name, FunctionLayout::kRegularFunction, true,
-                       false, false, false, false, owner_class,
-                       TokenPosition::kMinSource);
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
+  return Function::New(signature, function_name,
+                       UntaggedFunction::kRegularFunction, true, false, false,
+                       false, false, owner_class, TokenPosition::kMinSource);
 }
 
 // Test for Code and Instruction object creation.
@@ -2718,12 +2729,14 @@
   compiler::Assembler _assembler_(&object_pool_builder);
   GenerateIncrement(&_assembler_);
   const Function& function = Function::Handle(CreateFunction("Test_Code"));
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   const Instructions& instructions = Instructions::Handle(code.instructions());
   uword payload_start = instructions.PayloadStart();
-  EXPECT_EQ(instructions.raw(), Instructions::FromPayloadStart(payload_start));
+  EXPECT_EQ(instructions.ptr(), Instructions::FromPayloadStart(payload_start));
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
   EXPECT_EQ(1, Smi::Cast(result).Value());
@@ -2740,12 +2753,14 @@
   compiler::Assembler _assembler_(&object_pool_builder);
   GenerateIncrement(&_assembler_);
   const Function& function = Function::Handle(CreateFunction("Test_Code"));
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   Instructions& instructions = Instructions::Handle(code.instructions());
   uword payload_start = instructions.PayloadStart();
-  EXPECT_EQ(instructions.raw(), Instructions::FromPayloadStart(payload_start));
+  EXPECT_EQ(instructions.ptr(), Instructions::FromPayloadStart(payload_start));
   // Try writing into the generated code, expected to crash.
   *(reinterpret_cast<char*>(payload_start) + 1) = 1;
   if (!FLAG_write_protect_code) {
@@ -2778,21 +2793,23 @@
   compiler::Assembler _assembler_(&object_pool_builder);
   GenerateIncrement(&_assembler_);
   const Function& function = Function::Handle(CreateFunction("Test_Code"));
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   Instructions& instructions = Instructions::Handle(code.instructions());
   uword payload_start = code.PayloadStart();
   const uword unchecked_offset = code.UncheckedEntryPoint() - code.EntryPoint();
-  EXPECT_EQ(instructions.raw(), Instructions::FromPayloadStart(payload_start));
+  EXPECT_EQ(instructions.ptr(), Instructions::FromPayloadStart(payload_start));
   // Execute the executable view of the instructions (default).
   Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
   EXPECT_EQ(1, Smi::Cast(result).Value());
   // Switch to the writeable but non-executable view of the instructions.
-  instructions ^= OldPage::ToWritable(instructions.raw());
+  instructions ^= OldPage::ToWritable(instructions.ptr());
   payload_start = instructions.PayloadStart();
-  EXPECT_EQ(instructions.raw(), Instructions::FromPayloadStart(payload_start));
+  EXPECT_EQ(instructions.ptr(), Instructions::FromPayloadStart(payload_start));
   // Hook up Code and Instructions objects.
   CodeTestHelper::SetInstructions(code, instructions, unchecked_offset);
   function.AttachCode(code);
@@ -2819,14 +2836,16 @@
   GenerateEmbedStringInCode(&_assembler_, kHello);
   const Function& function =
       Function::Handle(CreateFunction("Test_EmbedStringInCode"));
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
   const Object& result =
       Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
-  EXPECT(result.raw()->IsHeapObject());
+  EXPECT(result.ptr()->IsHeapObject());
   String& string_object = String::Handle();
-  string_object ^= result.raw();
+  string_object ^= result.ptr();
   EXPECT(string_object.Length() == expected_length);
   for (int i = 0; i < expected_length; i++) {
     EXPECT(string_object.CharAt(i) == kHello[i]);
@@ -2843,6 +2862,8 @@
   GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
   const Function& function =
       Function::Handle(CreateFunction("Test_EmbedSmiInCode"));
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
@@ -2862,6 +2883,8 @@
   GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
   const Function& function =
       Function::Handle(CreateFunction("Test_EmbedSmiIn64BitCode"));
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       function, nullptr, &_assembler_, Code::PoolAttachment::kAttachPool));
   function.AttachCode(code);
@@ -2887,6 +2910,8 @@
   compiler::ObjectPoolBuilder object_pool_builder;
   compiler::Assembler _assembler_(&object_pool_builder);
   GenerateIncrement(&_assembler_);
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_,
       Code::PoolAttachment::kAttachPool));
@@ -2914,18 +2939,18 @@
   DescriptorList* builder = new DescriptorList(thread->zone());
 
   // kind, pc_offset, deopt_id, token_pos, try_index, yield_index
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 1, TokenPosition(20),
-                         1, 1);
-  builder->AddDescriptor(PcDescriptorsLayout::kDeopt, 20, 2, TokenPosition(30),
-                         0, -1);
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 30, 3, TokenPosition(40),
-                         1, 10);
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 4, TokenPosition(40),
-                         2, 20);
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 5, TokenPosition(80),
-                         3, 30);
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 80, 6, TokenPosition(150),
-                         3, 30);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 10, 1,
+                         TokenPosition::Deserialize(20), 1, 1);
+  builder->AddDescriptor(UntaggedPcDescriptors::kDeopt, 20, 2,
+                         TokenPosition::Deserialize(30), 0, -1);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 30, 3,
+                         TokenPosition::Deserialize(40), 1, 10);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 10, 4,
+                         TokenPosition::Deserialize(40), 2, 20);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 10, 5,
+                         TokenPosition::Deserialize(80), 3, 30);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 80, 6,
+                         TokenPosition::Deserialize(150), 3, 30);
 
   PcDescriptors& descriptors = PcDescriptors::Handle();
   descriptors ^= builder->FinalizePcDescriptors(0);
@@ -2934,6 +2959,8 @@
   compiler::ObjectPoolBuilder object_pool_builder;
   compiler::Assembler _assembler_(&object_pool_builder);
   GenerateIncrement(&_assembler_);
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_,
       Code::PoolAttachment::kAttachPool));
@@ -2941,41 +2968,41 @@
 
   // Verify the PcDescriptor entries by accessing them.
   const PcDescriptors& pc_descs = PcDescriptors::Handle(code.pc_descriptors());
-  PcDescriptors::Iterator iter(pc_descs, PcDescriptorsLayout::kAnyKind);
+  PcDescriptors::Iterator iter(pc_descs, UntaggedPcDescriptors::kAnyKind);
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(1, iter.YieldIndex());
-  EXPECT_EQ(20, iter.TokenPos().value());
+  EXPECT_EQ(20, iter.TokenPos().Pos());
   EXPECT_EQ(1, iter.TryIndex());
   EXPECT_EQ(static_cast<uword>(10), iter.PcOffset());
   EXPECT_EQ(1, iter.DeoptId());
-  EXPECT_EQ(PcDescriptorsLayout::kOther, iter.Kind());
+  EXPECT_EQ(UntaggedPcDescriptors::kOther, iter.Kind());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(-1, iter.YieldIndex());
-  EXPECT_EQ(30, iter.TokenPos().value());
-  EXPECT_EQ(PcDescriptorsLayout::kDeopt, iter.Kind());
+  EXPECT_EQ(30, iter.TokenPos().Pos());
+  EXPECT_EQ(UntaggedPcDescriptors::kDeopt, iter.Kind());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(10, iter.YieldIndex());
-  EXPECT_EQ(40, iter.TokenPos().value());
+  EXPECT_EQ(40, iter.TokenPos().Pos());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(20, iter.YieldIndex());
-  EXPECT_EQ(40, iter.TokenPos().value());
+  EXPECT_EQ(40, iter.TokenPos().Pos());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(30, iter.YieldIndex());
-  EXPECT_EQ(80, iter.TokenPos().value());
+  EXPECT_EQ(80, iter.TokenPos().Pos());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(30, iter.YieldIndex());
-  EXPECT_EQ(150, iter.TokenPos().value());
+  EXPECT_EQ(150, iter.TokenPos().Pos());
 
   EXPECT_EQ(3, iter.TryIndex());
   EXPECT_EQ(static_cast<uword>(80), iter.PcOffset());
-  EXPECT_EQ(150, iter.TokenPos().value());
-  EXPECT_EQ(PcDescriptorsLayout::kOther, iter.Kind());
+  EXPECT_EQ(150, iter.TokenPos().Pos());
+  EXPECT_EQ(UntaggedPcDescriptors::kOther, iter.Kind());
 
   EXPECT_EQ(false, iter.MoveNext());
 }
@@ -2984,18 +3011,18 @@
   DescriptorList* builder = new DescriptorList(thread->zone());
 
   // kind, pc_offset, deopt_id, token_pos, try_index
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 1,
-                         TokenPosition(200), 1, 10);
-  builder->AddDescriptor(PcDescriptorsLayout::kDeopt, 200, 2,
-                         TokenPosition(300), 0, -1);
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 300, 3,
-                         TokenPosition(400), 1, 10);
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 4, TokenPosition(0),
-                         2, 20);
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 5,
-                         TokenPosition(800), 3, 30);
-  builder->AddDescriptor(PcDescriptorsLayout::kOther, 800, 6,
-                         TokenPosition(150), 3, 30);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 100, 1,
+                         TokenPosition::Deserialize(200), 1, 10);
+  builder->AddDescriptor(UntaggedPcDescriptors::kDeopt, 200, 2,
+                         TokenPosition::Deserialize(300), 0, -1);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 300, 3,
+                         TokenPosition::Deserialize(400), 1, 10);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 100, 4,
+                         TokenPosition::Deserialize(0), 2, 20);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 100, 5,
+                         TokenPosition::Deserialize(800), 3, 30);
+  builder->AddDescriptor(UntaggedPcDescriptors::kOther, 800, 6,
+                         TokenPosition::Deserialize(150), 3, 30);
 
   PcDescriptors& descriptors = PcDescriptors::Handle();
   descriptors ^= builder->FinalizePcDescriptors(0);
@@ -3004,6 +3031,8 @@
   compiler::ObjectPoolBuilder object_pool_builder;
   compiler::Assembler _assembler_(&object_pool_builder);
   GenerateIncrement(&_assembler_);
+  SafepointWriteRwLocker locker(thread,
+                                thread->isolate_group()->program_lock());
   Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_,
       Code::PoolAttachment::kAttachPool));
@@ -3011,41 +3040,41 @@
 
   // Verify the PcDescriptor entries by accessing them.
   const PcDescriptors& pc_descs = PcDescriptors::Handle(code.pc_descriptors());
-  PcDescriptors::Iterator iter(pc_descs, PcDescriptorsLayout::kAnyKind);
+  PcDescriptors::Iterator iter(pc_descs, UntaggedPcDescriptors::kAnyKind);
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(10, iter.YieldIndex());
-  EXPECT_EQ(200, iter.TokenPos().value());
+  EXPECT_EQ(200, iter.TokenPos().Pos());
   EXPECT_EQ(1, iter.TryIndex());
   EXPECT_EQ(static_cast<uword>(100), iter.PcOffset());
   EXPECT_EQ(1, iter.DeoptId());
-  EXPECT_EQ(PcDescriptorsLayout::kOther, iter.Kind());
+  EXPECT_EQ(UntaggedPcDescriptors::kOther, iter.Kind());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(-1, iter.YieldIndex());
-  EXPECT_EQ(300, iter.TokenPos().value());
-  EXPECT_EQ(PcDescriptorsLayout::kDeopt, iter.Kind());
+  EXPECT_EQ(300, iter.TokenPos().Pos());
+  EXPECT_EQ(UntaggedPcDescriptors::kDeopt, iter.Kind());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(10, iter.YieldIndex());
-  EXPECT_EQ(400, iter.TokenPos().value());
+  EXPECT_EQ(400, iter.TokenPos().Pos());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(20, iter.YieldIndex());
-  EXPECT_EQ(0, iter.TokenPos().value());
+  EXPECT_EQ(0, iter.TokenPos().Pos());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(30, iter.YieldIndex());
-  EXPECT_EQ(800, iter.TokenPos().value());
+  EXPECT_EQ(800, iter.TokenPos().Pos());
 
   EXPECT_EQ(true, iter.MoveNext());
   EXPECT_EQ(30, iter.YieldIndex());
-  EXPECT_EQ(150, iter.TokenPos().value());
+  EXPECT_EQ(150, iter.TokenPos().Pos());
 
   EXPECT_EQ(3, iter.TryIndex());
   EXPECT_EQ(static_cast<uword>(800), iter.PcOffset());
-  EXPECT_EQ(150, iter.TokenPos().value());
-  EXPECT_EQ(PcDescriptorsLayout::kOther, iter.Kind());
+  EXPECT_EQ(150, iter.TokenPos().Pos());
+  EXPECT_EQ(UntaggedPcDescriptors::kOther, iter.Kind());
 
   EXPECT_EQ(false, iter.MoveNext());
 }
@@ -3055,7 +3084,7 @@
       String::Handle(Symbols::New(Thread::Current(), name));
   const Class& cls =
       Class::Handle(CreateDummyClass(class_name, Script::Handle()));
-  return cls.raw();
+  return cls.ptr();
 }
 
 static FieldPtr CreateTestField(const char* name) {
@@ -3070,7 +3099,7 @@
                                   thread->isolate_group()->program_lock());
     thread->isolate_group()->RegisterStaticField(field, Instance::sentinel());
   }
-  return field.raw();
+  return field.ptr();
 }
 
 ISOLATE_UNIT_TEST_CASE(ClassDictionaryIterator) {
@@ -3089,7 +3118,7 @@
   Class& cls = Class::Handle();
   while (iterator.HasNext()) {
     cls = iterator.GetNextClass();
-    EXPECT((cls.raw() == ae66.raw()) || (cls.raw() == re44.raw()));
+    EXPECT((cls.ptr() == ae66.ptr()) || (cls.ptr() == re44.ptr()));
     count++;
   }
   EXPECT(count == 2);
@@ -3105,9 +3134,11 @@
   const bool is_abstract = false;
   const bool is_external = false;
   const bool is_native = false;
-  return Function::New(function_name, FunctionLayout::kRegularFunction,
-                       is_static, is_const, is_abstract, is_external, is_native,
-                       cls, TokenPosition::kMinSource);
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
+  return Function::New(signature, function_name,
+                       UntaggedFunction::kRegularFunction, is_static, is_const,
+                       is_abstract, is_external, is_native, cls,
+                       TokenPosition::kMinSource);
 }
 
 ISOLATE_UNIT_TEST_CASE(ICData) {
@@ -3124,10 +3155,10 @@
                    ICData::kInstance);
   EXPECT_EQ(1, o1.NumArgsTested());
   EXPECT_EQ(id, o1.deopt_id());
-  EXPECT_EQ(function.raw(), o1.Owner());
+  EXPECT_EQ(function.ptr(), o1.Owner());
   EXPECT_EQ(0, o1.NumberOfChecks());
-  EXPECT_EQ(target_name.raw(), o1.target_name());
-  EXPECT_EQ(args_descriptor.raw(), o1.arguments_descriptor());
+  EXPECT_EQ(target_name.ptr(), o1.target_name());
+  EXPECT_EQ(args_descriptor.ptr(), o1.arguments_descriptor());
 
   const Function& target1 = Function::Handle(GetDummyTarget("Thun"));
   o1.AddReceiverCheck(kSmiCid, target1);
@@ -3137,13 +3168,13 @@
   Function& test_target = Function::Handle();
   o1.GetOneClassCheckAt(0, &test_class_id, &test_target);
   EXPECT_EQ(kSmiCid, test_class_id);
-  EXPECT_EQ(target1.raw(), test_target.raw());
+  EXPECT_EQ(target1.ptr(), test_target.ptr());
   EXPECT_EQ(kSmiCid, o1.GetCidAt(0));
   GrowableArray<intptr_t> test_class_ids;
   o1.GetCheckAt(0, &test_class_ids, &test_target);
   EXPECT_EQ(1, test_class_ids.length());
   EXPECT_EQ(kSmiCid, test_class_ids[0]);
-  EXPECT_EQ(target1.raw(), test_target.raw());
+  EXPECT_EQ(target1.ptr(), test_target.ptr());
 
   const Function& target2 = Function::Handle(GetDummyTarget("Thun"));
   o1.AddReceiverCheck(kDoubleCid, target2);
@@ -3151,7 +3182,7 @@
   EXPECT_EQ(2, o1.NumberOfUsedChecks());
   o1.GetOneClassCheckAt(1, &test_class_id, &test_target);
   EXPECT_EQ(kDoubleCid, test_class_id);
-  EXPECT_EQ(target2.raw(), test_target.raw());
+  EXPECT_EQ(target2.ptr(), test_target.ptr());
   EXPECT_EQ(kDoubleCid, o1.GetCidAt(1));
 
   o1.AddReceiverCheck(kMintCid, target2);
@@ -3164,7 +3195,7 @@
                    ICData::kInstance);
   EXPECT_EQ(2, o2.NumArgsTested());
   EXPECT_EQ(57, o2.deopt_id());
-  EXPECT_EQ(function.raw(), o2.Owner());
+  EXPECT_EQ(function.ptr(), o2.Owner());
   EXPECT_EQ(0, o2.NumberOfChecks());
   GrowableArray<intptr_t> classes;
   classes.Add(kSmiCid);
@@ -3175,14 +3206,14 @@
   EXPECT_EQ(2, test_class_ids.length());
   EXPECT_EQ(kSmiCid, test_class_ids[0]);
   EXPECT_EQ(kSmiCid, test_class_ids[1]);
-  EXPECT_EQ(target1.raw(), test_target.raw());
+  EXPECT_EQ(target1.ptr(), test_target.ptr());
 
   // Check ICData for unoptimized static calls.
   const intptr_t kNumArgsChecked = 0;
   const ICData& scall_icdata = ICData::Handle(
       ICData::NewForStaticCall(function, target1, args_descriptor, 57,
                                kNumArgsChecked, ICData::kInstance));
-  EXPECT_EQ(target1.raw(), scall_icdata.GetTargetAt(0));
+  EXPECT_EQ(target1.ptr(), scall_icdata.GetTargetAt(0));
 }
 
 ISOLATE_UNIT_TEST_CASE(SubtypeTestCache) {
@@ -3220,14 +3251,14 @@
   cache.GetCheck(0, &test_class_id_or_fun, &test_dest_type, &test_targ_0,
                  &test_targ_1, &test_targ_2, &test_targ_3, &test_targ_4,
                  &test_result);
-  EXPECT_EQ(class_id_or_fun.raw(), test_class_id_or_fun.raw());
-  EXPECT_EQ(dest_type.raw(), test_dest_type.raw());
-  EXPECT_EQ(targ_0.raw(), test_targ_0.raw());
-  EXPECT_EQ(targ_1.raw(), test_targ_1.raw());
-  EXPECT_EQ(targ_2.raw(), test_targ_2.raw());
-  EXPECT_EQ(targ_3.raw(), test_targ_3.raw());
-  EXPECT_EQ(targ_4.raw(), test_targ_4.raw());
-  EXPECT_EQ(Bool::True().raw(), test_result.raw());
+  EXPECT_EQ(class_id_or_fun.ptr(), test_class_id_or_fun.ptr());
+  EXPECT_EQ(dest_type.ptr(), test_dest_type.ptr());
+  EXPECT_EQ(targ_0.ptr(), test_targ_0.ptr());
+  EXPECT_EQ(targ_1.ptr(), test_targ_1.ptr());
+  EXPECT_EQ(targ_2.ptr(), test_targ_2.ptr());
+  EXPECT_EQ(targ_3.ptr(), test_targ_3.ptr());
+  EXPECT_EQ(targ_4.ptr(), test_targ_4.ptr());
+  EXPECT_EQ(Bool::True().ptr(), test_result.ptr());
 }
 
 ISOLATE_UNIT_TEST_CASE(MegamorphicCache) {
@@ -3248,11 +3279,11 @@
 
     EXPECT(cache.Lookup(cidA) == Object::null());
     cache.EnsureContains(cidA, valueA);
-    EXPECT(cache.Lookup(cidA) == valueA.raw());
+    EXPECT(cache.Lookup(cidA) == valueA.ptr());
 
     EXPECT(cache.Lookup(cidB) == Object::null());
     cache.EnsureContains(cidB, valueB);
-    EXPECT(cache.Lookup(cidB) == valueB.raw());
+    EXPECT(cache.Lookup(cidB) == valueB.ptr());
   }
 
   // Try to insert many keys to hit collisions & growth.
@@ -3891,16 +3922,16 @@
   reference.set_referent(library);
   const Object& returned_referent = Object::Handle(reference.referent());
   EXPECT(returned_referent.IsLibrary());
-  EXPECT_EQ(returned_referent.raw(), library.raw());
+  EXPECT_EQ(returned_referent.ptr(), library.ptr());
 
   const MirrorReference& other_reference =
       MirrorReference::Handle(MirrorReference::New(Object::Handle()));
-  EXPECT_NE(reference.raw(), other_reference.raw());
+  EXPECT_NE(reference.ptr(), other_reference.ptr());
   other_reference.set_referent(library);
-  EXPECT_NE(reference.raw(), other_reference.raw());
+  EXPECT_NE(reference.ptr(), other_reference.ptr());
   EXPECT_EQ(reference.referent(), other_reference.referent());
 
-  Object& obj = Object::Handle(reference.raw());
+  Object& obj = Object::Handle(reference.ptr());
   EXPECT(obj.IsMirrorReference());
 }
 
@@ -3911,7 +3942,7 @@
   const Function& result = Function::Handle(Resolver::ResolveDynamicFunction(
       Z, cls, String::Handle(String::New(name))));
   EXPECT(!result.IsNull());
-  return result.raw();
+  return result.ptr();
 }
 
 static FunctionPtr GetStaticFunction(const Class& cls, const char* name) {
@@ -3920,21 +3951,21 @@
   const Function& result = Function::Handle(
       cls.LookupStaticFunction(String::Handle(String::New(name))));
   EXPECT(!result.IsNull());
-  return result.raw();
+  return result.ptr();
 }
 
 static FieldPtr GetField(const Class& cls, const char* name) {
   const Field& field =
       Field::Handle(cls.LookupField(String::Handle(String::New(name))));
   EXPECT(!field.IsNull());
-  return field.raw();
+  return field.ptr();
 }
 
 static ClassPtr GetClass(const Library& lib, const char* name) {
   const Class& cls = Class::Handle(
       lib.LookupClass(String::Handle(Symbols::New(Thread::Current(), name))));
   EXPECT(!cls.IsNull());  // No ambiguity error expected.
-  return cls.raw();
+  return cls.ptr();
 }
 
 ISOLATE_UNIT_TEST_CASE(FindClosureIndex) {
@@ -3943,13 +3974,13 @@
   const Script& script = Script::Handle();
   const Class& cls = Class::Handle(CreateDummyClass(class_name, script));
   const Array& functions = Array::Handle(Array::New(1));
-  const Isolate* iso = Isolate::Current();
 
   Function& parent = Function::Handle();
   const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
-  parent =
-      Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
-                    false, false, false, cls, TokenPosition::kMinSource);
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
+  parent = Function::New(signature, parent_name,
+                         UntaggedFunction::kRegularFunction, false, false,
+                         false, false, false, cls, TokenPosition::kMinSource);
   functions.SetAt(0, parent);
   {
     SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
@@ -3961,20 +3992,25 @@
   function = Function::NewClosureFunction(function_name, parent,
                                           TokenPosition::kMinSource);
   // Add closure function to class.
-  iso->AddClosureFunction(function);
+  {
+    SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+    ClosureFunctionsCache::AddClosureFunctionLocked(function);
+  }
 
   // The closure should return a valid index.
-  intptr_t good_closure_index = iso->FindClosureIndex(function);
+  intptr_t good_closure_index =
+      ClosureFunctionsCache::FindClosureIndex(function);
   EXPECT_GE(good_closure_index, 0);
   // The parent function should return an invalid index.
-  intptr_t bad_closure_index = iso->FindClosureIndex(parent);
+  intptr_t bad_closure_index = ClosureFunctionsCache::FindClosureIndex(parent);
   EXPECT_EQ(bad_closure_index, -1);
 
   // Retrieve closure function via index.
   Function& func_from_index = Function::Handle();
-  func_from_index ^= iso->ClosureFunctionFromIndex(good_closure_index);
+  func_from_index ^=
+      ClosureFunctionsCache::ClosureFunctionFromIndex(good_closure_index);
   // Same closure function.
-  EXPECT_EQ(func_from_index.raw(), function.raw());
+  EXPECT_EQ(func_from_index.ptr(), function.ptr());
 }
 
 ISOLATE_UNIT_TEST_CASE(FindInvocationDispatcherFunctionIndex) {
@@ -3986,9 +4022,10 @@
   const Array& functions = Array::Handle(Array::New(1));
   Function& parent = Function::Handle();
   const String& parent_name = String::Handle(Symbols::New(thread, "foo_papa"));
-  parent =
-      Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
-                    false, false, false, cls, TokenPosition::kMinSource);
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
+  parent = Function::New(signature, parent_name,
+                         UntaggedFunction::kRegularFunction, false, false,
+                         false, false, false, cls, TokenPosition::kMinSource);
   functions.SetAt(0, parent);
   {
     SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
@@ -4003,7 +4040,7 @@
   Function& invocation_dispatcher = Function::Handle();
   invocation_dispatcher ^= cls.GetInvocationDispatcher(
       invocation_dispatcher_name, args_desc,
-      FunctionLayout::kNoSuchMethodDispatcher, true /* create_if_absent */);
+      UntaggedFunction::kNoSuchMethodDispatcher, true /* create_if_absent */);
   EXPECT(!invocation_dispatcher.IsNull());
   // Get index to function.
   intptr_t invocation_dispatcher_index =
@@ -4015,8 +4052,8 @@
   invocation_dispatcher_from_index ^=
       cls.InvocationDispatcherFunctionFromIndex(invocation_dispatcher_index);
   // Same function.
-  EXPECT_EQ(invocation_dispatcher.raw(),
-            invocation_dispatcher_from_index.raw());
+  EXPECT_EQ(invocation_dispatcher.ptr(),
+            invocation_dispatcher_from_index.ptr());
   // Test function not found case.
   const Function& bad_function = Function::Handle(Function::null());
   intptr_t bad_invocation_dispatcher_index =
@@ -4250,7 +4287,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(SpecialClassesHaveEmptyArrays) {
-  ObjectStore* object_store = Isolate::Current()->object_store();
+  ObjectStore* object_store = IsolateGroup::Current()->object_store();
   Class& cls = Class::Handle();
   Object& array = Object::Handle();
 
@@ -4359,7 +4396,7 @@
   // Class reference
   {
     JSONStream js;
-    Class& cls = Class::Handle(isolate->object_store()->bool_class());
+    Class& cls = Class::Handle(isolate->group()->object_store()->bool_class());
     cls.PrintJSON(&js, true);
     ElideJSONSubstring("classes", js.ToCString(), buffer);
     EXPECT_STREQ(
@@ -4370,7 +4407,7 @@
   {
     Thread* thread = Thread::Current();
     JSONStream js;
-    Class& cls = Class::Handle(isolate->object_store()->bool_class());
+    Class& cls = Class::Handle(isolate->group()->object_store()->bool_class());
     const String& func_name = String::Handle(String::New("toString"));
     Function& func =
         Function::Handle(Resolver::ResolveFunction(Z, cls, func_name));
@@ -4390,7 +4427,8 @@
   // Library reference
   {
     JSONStream js;
-    Library& lib = Library::Handle(isolate->object_store()->core_library());
+    Library& lib =
+        Library::Handle(isolate->group()->object_store()->core_library());
     lib.PrintJSON(&js, true);
     ElideJSONSubstring("libraries", js.ToCString(), buffer);
     EXPECT_STREQ(
@@ -4558,7 +4596,8 @@
   // TODO(turnidge): Add in all of the other Type siblings.
   {
     JSONStream js;
-    Instance& type = Instance::Handle(isolate->object_store()->bool_type());
+    Instance& type =
+        Instance::Handle(isolate->group()->object_store()->bool_type());
     type.PrintJSON(&js, true);
     ElideJSONSubstring("classes", js.ToCString(), buffer);
     ElideJSONSubstring("objects", buffer, buffer);
@@ -4636,7 +4675,7 @@
   EXPECT(!clazz.IsNull());
   const Instance& a0 = Instance::Handle(Instance::New(clazz));
   const Instance& a1 = Instance::Handle(Instance::New(clazz));
-  EXPECT(a0.raw() != a1.raw());
+  EXPECT(a0.ptr() != a1.ptr());
   EXPECT(a0.OperatorEquals(a0));
   EXPECT(a0.OperatorEquals(a1));
   EXPECT(a0.IsIdenticalTo(a0));
@@ -4664,73 +4703,6 @@
   EXPECT(result.IsIdenticalTo(expected));
 }
 
-static void CheckIdenticalHashStructure(Thread* T,
-                                        const Instance& a,
-                                        const Instance& b) {
-  const char* kScript =
-      "(a, b) {\n"
-      "  if (a._usedData != b._usedData ||\n"
-      "      a._deletedKeys != b._deletedKeys ||\n"
-      "      a._hashMask != b._hashMask ||\n"
-      "      a._index.length != b._index.length ||\n"
-      "      a._data.length != b._data.length) {\n"
-      "    return false;\n"
-      "  }\n"
-      "  for (var i = 0; i < a._index.length; ++i) {\n"
-      "    if (a._index[i] != b._index[i]) {\n"
-      "      return false;\n"
-      "    }\n"
-      "  }\n"
-      "  for (var i = 0; i < a._data.length; ++i) {\n"
-      "    var ad = a._data[i];\n"
-      "    var bd = b._data[i];\n"
-      "    if (!identical(ad, bd) && !(ad == a && bd == b)) {\n"
-      "      return false;\n"
-      "    }\n"
-      "  }\n"
-      "  return true;\n"
-      "}(a, b)";
-  String& name = String::Handle();
-  Array& param_names = Array::Handle(Array::New(2));
-  name = String::New("a");
-  param_names.SetAt(0, name);
-  name = String::New("b");
-  param_names.SetAt(1, name);
-  Array& param_values = Array::Handle(Array::New(2));
-  param_values.SetAt(0, a);
-  param_values.SetAt(1, b);
-  name = String::New(kScript);
-  Library& lib = Library::Handle(Library::CollectionLibrary());
-  EXPECT(Api::UnwrapHandle(TestCase::EvaluateExpression(
-             lib, name, param_names, param_values)) == Bool::True().raw());
-}
-
-TEST_CASE(LinkedHashMap) {
-  // Check that initial index size and hash mask match in Dart vs. C++.
-  // 1. Create an empty custom linked hash map in Dart.
-  const char* kScript =
-      "import 'dart:collection';\n"
-      "makeMap() {\n"
-      "  bool Function(dynamic, dynamic) eq = (a, b) => true;\n"
-      "  int Function(dynamic) hc = (a) => 42;\n"
-      "  return new LinkedHashMap(equals: eq, hashCode: hc);\n"
-      "}";
-  Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
-  EXPECT_VALID(h_lib);
-  Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeMap"), 0, NULL);
-  EXPECT_VALID(h_result);
-
-  TransitionNativeToVM transition(thread);
-
-  // 2. Create an empty internalized LinkedHashMap in C++.
-  Instance& dart_map = Instance::Handle();
-  dart_map ^= Api::UnwrapHandle(h_result);
-  LinkedHashMap& cc_map = LinkedHashMap::Handle(LinkedHashMap::NewDefault());
-
-  // 3. Expect them to have identical structure.
-  CheckIdenticalHashStructure(thread, dart_map, cc_map);
-}
-
 TEST_CASE(LinkedHashMap_iteration) {
   const char* kScript =
       "makeMap() {\n"
diff --git a/runtime/vm/object_x64_test.cc b/runtime/vm/object_x64_test.cc
index e8913ce..30e9f84 100644
--- a/runtime/vm/object_x64_test.cc
+++ b/runtime/vm/object_x64_test.cc
@@ -43,7 +43,7 @@
 // This is used to test Embedded Smi objects in the instructions.
 void GenerateEmbedSmiInCode(compiler::Assembler* assembler, intptr_t value) {
   const Smi& smi_object = Smi::ZoneHandle(Smi::New(value));
-  __ movq(RAX, compiler::Immediate(static_cast<int64_t>(smi_object.raw())));
+  __ movq(RAX, compiler::Immediate(static_cast<int64_t>(smi_object.ptr())));
   __ ret();
 }
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index c9cf923..866d0aa 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -110,12 +110,13 @@
     }
   }
 
-  // Note: the list of guarded fields must contain copies during background
+  // Note: the list of guarded fields must contain copies during optimizing
   // compilation because we will look at their guarded_cid when copying
   // the array of guarded fields from callee into the caller during
   // inlining.
-  ASSERT(!field->IsOriginal() || Thread::Current()->IsMutatorThread());
-  guarded_fields_->Add(&Field::ZoneHandle(Z, field->raw()));
+  ASSERT(field->IsOriginal() ==
+         !CompilerState::Current().should_clone_fields());
+  guarded_fields_->Add(&Field::ZoneHandle(Z, field->ptr()));
 }
 
 void ParsedFunction::Bailout(const char* origin, const char* reason) const {
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index d12a763..0c7cad8 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -317,7 +317,7 @@
   ReturnAddressLocator(Sample* sample, const Code& code)
       : stack_buffer_(sample->GetStackBuffer()),
         pc_(sample->pc()),
-        code_(Code::ZoneHandle(code.raw())) {
+        code_(Code::ZoneHandle(code.ptr())) {
     ASSERT(!code_.IsNull());
     ASSERT(code_.ContainsInstructionAt(pc()));
   }
@@ -325,7 +325,7 @@
   ReturnAddressLocator(uword pc, uword* stack_buffer, const Code& code)
       : stack_buffer_(stack_buffer),
         pc_(pc),
-        code_(Code::ZoneHandle(code.raw())) {
+        code_(Code::ZoneHandle(code.ptr())) {
     ASSERT(!code_.IsNull());
     ASSERT(code_.ContainsInstructionAt(pc_));
   }
@@ -1460,7 +1460,7 @@
 void CodeLookupTable::Add(const Object& code) {
   ASSERT(!code.IsNull());
   ASSERT(code.IsCode());
-  CodeDescriptor* cd = new CodeDescriptor(AbstractCode(code.raw()));
+  CodeDescriptor* cd = new CodeDescriptor(AbstractCode(code.ptr()));
   code_objects_.Add(cd);
 }
 
@@ -1636,7 +1636,7 @@
                                                uword pc_marker,
                                                uword* stack_buffer) {
   ASSERT(cd != NULL);
-  const Code& code = Code::Handle(Code::RawCast(cd->code().raw()));
+  const Code& code = Code::Handle(Code::RawCast(cd->code().ptr()));
   ASSERT(!code.IsNull());
   // Some stubs (and intrinsics) do not push a frame onto the stack leaving
   // the frame pointer in the caller.
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 4f92d72..5f24c2a 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -460,7 +460,7 @@
     ASSERT(code_.IsNull() || code_.IsCode());
   }
 
-  ObjectPtr raw() const { return code_.raw(); }
+  ObjectPtr ptr() const { return code_.ptr(); }
   const Object* handle() const { return &code_; }
 
   uword PayloadStart() const {
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 4f88ae4..e1a3c38 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -65,7 +65,7 @@
     }
     NoSafepointScope no_safepoint_scope;
     for (intptr_t i = 0; i < array.Length(); i++) {
-      if (code.raw() == array.At(i)) {
+      if (code.ptr() == array.At(i)) {
         return true;
       }
     }
@@ -110,7 +110,7 @@
                                  const intptr_t table_index)
     : kind_(kind),
       name_(name),
-      function_(Function::ZoneHandle(function.raw())),
+      function_(Function::ZoneHandle(function.ptr())),
       table_index_(table_index),
       profile_codes_(0),
       source_position_ticks_(0),
@@ -174,7 +174,12 @@
   intptr_t i = 0;
   for (; i < source_position_ticks_.length(); i++) {
     ProfileFunctionSourcePosition& position = source_position_ticks_[i];
-    if (position.token_pos().value() == token_position.value()) {
+    const intptr_t cmp =
+        TokenPosition::CompareForSorting(position.token_pos(), token_position);
+    if (cmp > 0) {
+      // Found insertion point.
+      break;
+    } else if (cmp == 0) {
       if (FLAG_trace_profiler_verbose) {
         OS::PrintErr("Ticking source position %s %s\n",
                      exclusive ? "exclusive" : "inclusive",
@@ -184,9 +189,6 @@
       position.Tick(exclusive);
       return;
     }
-    if (position.token_pos().value() > token_position.value()) {
-      break;
-    }
   }
 
   // Add new one, sorted by token position value.
@@ -605,7 +607,7 @@
     static inline intptr_t Hashcode(Key key) { return key->Hash(); }
 
     static inline bool IsKeyEqual(Pair kv, Key key) {
-      return kv->function()->raw() == key->raw();
+      return kv->function()->ptr() == key->ptr();
     }
   };
 
@@ -934,7 +936,7 @@
   if (cache_entry->inlined_functions.length() == 0) {
     *inlined_functions = NULL;
     *inlined_token_positions = NULL;
-    *token_position = cache_entry->token_position = TokenPosition();
+    *token_position = cache_entry->token_position = TokenPosition::kNoSource;
     return;
   }
 
@@ -1205,7 +1207,7 @@
     TokenPosition token_position = TokenPosition::kNoSource;
     Code& code = Code::ZoneHandle();
     if (profile_code->code().IsCode()) {
-      code ^= profile_code->code().raw();
+      code ^= profile_code->code().ptr();
       inlined_functions_cache_->Get(pc, code, sample, frame_index,
                                     &inlined_functions,
                                     &inlined_token_positions, &token_position);
@@ -1404,8 +1406,8 @@
   }
 
   bool IsPCInDartHeap(uword pc) {
-    return vm_isolate_->heap()->CodeContains(pc) ||
-           thread_->isolate()->heap()->CodeContains(pc);
+    return vm_isolate_->group()->heap()->CodeContains(pc) ||
+           thread_->isolate()->group()->heap()->CodeContains(pc);
   }
 
   ProfileCode* FindOrRegisterNativeProfileCode(uword pc) {
@@ -1660,7 +1662,7 @@
   Code& code = Code::ZoneHandle();
 
   if (profile_code->code().IsCode()) {
-    code ^= profile_code->code().raw();
+    code ^= profile_code->code().ptr();
     cache_->Get(pc, code, sample, frame_index, &inlined_functions,
                 &inlined_token_positions, &token_position);
     if (FLAG_trace_profiler_verbose && (inlined_functions != NULL)) {
@@ -1867,7 +1869,7 @@
                      thread_task_mask,
                      time_origin_micros,
                      time_extent_micros),
-        cls_(Class::Handle(cls.raw())) {
+        cls_(Class::Handle(cls.ptr())) {
     ASSERT(!cls_.IsNull());
   }
 
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 0ad1e7f..a3d42a8 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -115,7 +115,7 @@
     intptr_t offset;
     GrowableArray<const Function*> inlined_functions;
     GrowableArray<TokenPosition> inlined_token_positions;
-    TokenPosition token_position;
+    TokenPosition token_position = TokenPosition::kNoSource;
   };
 
   static const intptr_t kCacheSize = 128;
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 6c3589e..d4e62d2 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -164,7 +164,7 @@
   }
   Library& lib = Library::Handle();
   lib ^= Api::UnwrapHandle(api_lib);
-  return lib.raw();
+  return lib.ptr();
 }
 
 static ClassPtr GetClass(const Library& lib, const char* name) {
@@ -172,7 +172,7 @@
   const Class& cls = Class::Handle(
       lib.LookupClassAllowPrivate(String::Handle(Symbols::New(thread, name))));
   EXPECT(!cls.IsNull());  // No ambiguity error expected.
-  return cls.raw();
+  return cls.ptr();
 }
 
 static FunctionPtr GetFunction(const Library& lib, const char* name) {
@@ -180,7 +180,7 @@
   const Function& func = Function::Handle(lib.LookupFunctionAllowPrivate(
       String::Handle(Symbols::New(thread, name))));
   EXPECT(!func.IsNull());  // No ambiguity error expected.
-  return func.raw();
+  return func.ptr();
 }
 
 static void Invoke(const Library& lib,
@@ -188,7 +188,7 @@
                    intptr_t argc = 0,
                    Dart_Handle* argv = NULL) {
   Thread* thread = Thread::Current();
-  Dart_Handle api_lib = Api::NewHandle(thread, lib.raw());
+  Dart_Handle api_lib = Api::NewHandle(thread, lib.ptr());
   TransitionVMToNative transition(thread);
   Dart_Handle result = Dart_Invoke(api_lib, NewString(name), argc, argv);
   EXPECT_VALID(result);
@@ -262,39 +262,36 @@
 
   const char* CurrentToken() {
     if (!as_functions_) {
-      return NULL;
+      return nullptr;
     }
     ProfileFunction* func = GetFunction();
     const Function& function = *(func->function());
     if (function.IsNull()) {
       // No function.
-      return NULL;
+      return nullptr;
     }
     Zone* zone = Thread::Current()->zone();
     const Script& script = Script::Handle(zone, function.script());
     if (script.IsNull()) {
       // No script.
-      return NULL;
+      return nullptr;
     }
     ProfileFunctionSourcePosition pfsp(TokenPosition::kNoSource);
     if (!func->GetSinglePosition(&pfsp)) {
       // Not exactly one source position.
-      return NULL;
-    }
-    TokenPosition token_pos = pfsp.token_pos();
-    if (!token_pos.IsSourcePosition()) {
-      // Not a location in a script.
-      return NULL;
-    }
-    if (token_pos.IsSynthetic()) {
-      token_pos = token_pos.FromSynthetic();
+      return nullptr;
     }
 
-    intptr_t line = 0, column = 0, token_len = 0;
-    script.GetTokenLocation(token_pos, &line, &column, &token_len);
-    const auto& str = String::Handle(
-        zone, script.GetSnippet(line, column, line, column + token_len));
-    return str.IsNull() ? NULL : str.ToCString();
+    const TokenPosition& token_pos = pfsp.token_pos();
+    intptr_t line, column;
+    if (script.GetTokenLocation(token_pos, &line, &column)) {
+      const intptr_t token_len = script.GetTokenLength(token_pos);
+      const auto& str = String::Handle(
+          zone, script.GetSnippet(line, column, line, column + token_len));
+      if (!str.IsNull()) return str.ToCString();
+    }
+    // Couldn't get line/number information.
+    return nullptr;
   }
 
   intptr_t CurrentInclusiveTicks() {
@@ -368,7 +365,7 @@
     TokenPosition token_position = TokenPosition::kNoSource;
     Code& code = Code::ZoneHandle();
     if (profile_code->code().IsCode()) {
-      code ^= profile_code->code().raw();
+      code ^= profile_code->code().ptr();
       inlined_functions_cache_.Get(pc, code, sample_, index_,
                                    &inlined_functions_,
                                    &inlined_token_positions_, &token_position);
@@ -836,7 +833,7 @@
   Isolate* isolate = thread->isolate();
 
   const Class& double_class =
-      Class::Handle(isolate->object_store()->double_class());
+      Class::Handle(isolate->group()->object_store()->double_class());
   EXPECT(!double_class.IsNull());
 
   Dart_Handle args[2];
@@ -905,7 +902,7 @@
   Isolate* isolate = thread->isolate();
 
   const Class& array_class =
-      Class::Handle(isolate->object_store()->array_class());
+      Class::Handle(isolate->group()->object_store()->array_class());
   EXPECT(!array_class.IsNull());
 
   Invoke(root_library, "foo");
@@ -1063,7 +1060,7 @@
   Isolate* isolate = thread->isolate();
 
   const Class& closure_class =
-      Class::Handle(Isolate::Current()->object_store()->closure_class());
+      Class::Handle(IsolateGroup::Current()->object_store()->closure_class());
   EXPECT(!closure_class.IsNull());
   closure_class.SetTraceAllocation(true);
 
@@ -1121,7 +1118,7 @@
   Isolate* isolate = thread->isolate();
 
   const Library& typed_data_library =
-      Library::Handle(isolate->object_store()->typed_data_library());
+      Library::Handle(isolate->group()->object_store()->typed_data_library());
 
   const Class& float32_list_class =
       Class::Handle(GetClass(typed_data_library, "_Float32List"));
@@ -1197,7 +1194,7 @@
   Isolate* isolate = thread->isolate();
 
   const Class& one_byte_string_class =
-      Class::Handle(isolate->object_store()->one_byte_string_class());
+      Class::Handle(isolate->group()->object_store()->one_byte_string_class());
   EXPECT(!one_byte_string_class.IsNull());
 
   Dart_Handle args[2];
@@ -1275,7 +1272,7 @@
   Isolate* isolate = thread->isolate();
 
   const Class& one_byte_string_class =
-      Class::Handle(isolate->object_store()->one_byte_string_class());
+      Class::Handle(isolate->group()->object_store()->one_byte_string_class());
   EXPECT(!one_byte_string_class.IsNull());
 
   Dart_Handle args[2];
@@ -2315,10 +2312,10 @@
       "}\n";
 
   // Token position of * in `i * i`.
-  const TokenPosition squarePosition = TokenPosition(19);
+  const TokenPosition squarePosition = TokenPosition::Deserialize(19);
 
   // Token position of the call to `doWork`.
-  const TokenPosition callPosition = TokenPosition(95);
+  const TokenPosition callPosition = TokenPosition::Deserialize(95);
 
   DisableNativeProfileScope dnps;
   // Disable profiling for this thread.
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 5b7319c..b8e3de1 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -4,6 +4,7 @@
 
 #include "vm/program_visitor.h"
 
+#include "vm/closure_functions_cache.h"
 #include "vm/code_patcher.h"
 #include "vm/deopt_instructions.h"
 #include "vm/hash_map.h"
@@ -16,9 +17,9 @@
 class WorklistElement : public ZoneAllocated {
  public:
   WorklistElement(Zone* zone, const Object& object)
-      : object_(Object::Handle(zone, object.raw())), next_(nullptr) {}
+      : object_(Object::Handle(zone, object.ptr())), next_(nullptr) {}
 
-  ObjectPtr value() const { return object_.raw(); }
+  ObjectPtr value() const { return object_.ptr(); }
 
   void set_next(WorklistElement* elem) { next_ = elem; }
   WorklistElement* next() const { return next_; }
@@ -98,8 +99,8 @@
     // We don't visit null, non-heap objects, or objects in the VM heap.
     if (object.IsNull() || object.IsSmi() || object.InVMIsolateHeap()) return;
     // Check and set visited, even if we don't end up adding this to the list.
-    if (heap_->GetObjectId(object.raw()) != 0) return;
-    heap_->SetObjectId(object.raw(), 1);
+    if (heap_->GetObjectId(object.ptr()) != 0) return;
+    heap_->SetObjectId(object.ptr(), 1);
     if (object.IsClass() ||
         (object.IsFunction() && visitor_->IsFunctionVisitor()) ||
         (object.IsCode() && visitor_->IsCodeVisitor())) {
@@ -209,10 +210,10 @@
 };
 
 void ProgramVisitor::WalkProgram(Zone* zone,
-                                 Isolate* isolate,
+                                 IsolateGroup* isolate_group,
                                  ClassVisitor* visitor) {
-  auto const object_store = isolate->object_store();
-  auto const heap = isolate->heap();
+  auto const object_store = isolate_group->object_store();
+  auto const heap = isolate_group->heap();
   ProgramWalker walker(zone, heap, visitor);
 
   // Walk through the libraries and patches, looking for visitable objects.
@@ -252,17 +253,15 @@
 
   if (visitor->IsFunctionVisitor()) {
     // Function objects not necessarily reachable from classes.
-    auto& function = Function::Handle(zone);
-    const auto& closures =
-        GrowableObjectArray::Handle(zone, object_store->closure_functions());
-    ASSERT(!closures.IsNull());
-    for (intptr_t i = 0; i < closures.Length(); i++) {
-      function ^= closures.At(i);
-      walker.AddToWorklist(function);
-      ASSERT(!function.HasImplicitClosureFunction());
-    }
+    ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& fun) {
+      walker.AddToWorklist(fun);
+      ASSERT(!fun.HasImplicitClosureFunction());
+      return true;  // Continue iteration.
+    });
+
     // TODO(dartbug.com/43049): Use a more general solution and remove manual
     // tracking through object_store->ffi_callback_functions.
+    auto& function = Function::Handle(zone);
     const auto& ffi_callback_entries = GrowableObjectArray::Handle(
         zone, object_store->ffi_callback_functions());
     if (!ffi_callback_entries.IsNull()) {
@@ -319,7 +318,7 @@
   void AddCanonical(const T& obj) {
     if (!ShouldAdd(obj)) return;
     ASSERT(!canonical_objects_.HasKey(&obj));
-    canonical_objects_.Insert(&T::ZoneHandle(zone_, obj.raw()));
+    canonical_objects_.Insert(&T::ZoneHandle(zone_, obj.ptr()));
   }
 
   void AddVMBaseObjects() {
@@ -335,18 +334,18 @@
   typename T::ObjectPtrType Dedup(const T& obj) {
     if (ShouldAdd(obj)) {
       if (auto const canonical = canonical_objects_.LookupValue(&obj)) {
-        return canonical->raw();
+        return canonical->ptr();
       }
       AddCanonical(obj);
     }
-    return obj.raw();
+    return obj.ptr();
   }
 
   Zone* const zone_;
   DirectChainedHashMap<S> canonical_objects_;
 };
 
-void ProgramVisitor::BindStaticCalls(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::BindStaticCalls(Zone* zone, IsolateGroup* isolate_group) {
   class BindStaticCallsVisitor : public CodeVisitor {
    public:
     explicit BindStaticCallsVisitor(Zone* zone)
@@ -400,7 +399,7 @@
         const auto& fun = Function::Cast(target_);
         ASSERT(!FLAG_precompiled_mode || fun.HasCode());
         target_code_ = fun.HasCode() ? fun.CurrentCode()
-                                     : StubCode::CallStaticFunction().raw();
+                                     : StubCode::CallStaticFunction().ptr();
         CodePatcher::PatchStaticCallAt(pc, code, target_code_);
       }
 
@@ -423,15 +422,16 @@
   };
 
   BindStaticCallsVisitor visitor(zone);
-  WalkProgram(zone, isolate, &visitor);
+  WalkProgram(zone, isolate_group, &visitor);
 }
 
 DECLARE_FLAG(charp, trace_precompiler_to);
 DECLARE_FLAG(charp, write_v8_snapshot_profile_to);
 
-void ProgramVisitor::ShareMegamorphicBuckets(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::ShareMegamorphicBuckets(Zone* zone,
+                                             IsolateGroup* isolate_group) {
   const GrowableObjectArray& table = GrowableObjectArray::Handle(
-      zone, isolate->object_store()->megamorphic_cache_table());
+      zone, isolate_group->object_store()->megamorphic_cache_table());
   if (table.IsNull()) return;
   MegamorphicCache& cache = MegamorphicCache::Handle(zone);
 
@@ -452,9 +452,9 @@
 class StackMapEntry : public ZoneAllocated {
  public:
   StackMapEntry(Zone* zone, const CompressedStackMaps::Iterator& it)
-      : maps_(CompressedStackMaps::Handle(zone, it.maps_.raw())),
+      : maps_(CompressedStackMaps::Handle(zone, it.maps_.ptr())),
         bits_container_(
-            CompressedStackMaps::Handle(zone, it.bits_container_.raw())),
+            CompressedStackMaps::Handle(zone, it.bits_container_.ptr())),
         // If the map uses the global table, this accessor call ensures the
         // entry is fully loaded before we retrieve [it.current_bits_offset_].
         spill_slot_bit_count_(it.SpillSlotBitCount()),
@@ -522,7 +522,7 @@
   }
   const uint8_t* PayloadData() const {
     ASSERT(!Thread::Current()->IsAtSafepoint());
-    return bits_container_.raw()->ptr()->data() + bits_offset_;
+    return bits_container_.ptr()->untag()->data() + bits_offset_;
   }
 
   const CompressedStackMaps& maps_;
@@ -561,8 +561,9 @@
 
 typedef DirectChainedHashMap<StackMapEntryKeyIntValueTrait> StackMapEntryIntMap;
 
-void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(Zone* zone,
-                                                          Isolate* isolate) {
+void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(
+    Zone* zone,
+    IsolateGroup* isolate_group) {
   // Walks all the CSMs in Code objects and collects their entry information
   // for consolidation.
   class CollectStackMapEntriesVisitor : public CodeVisitor {
@@ -622,7 +623,7 @@
       const auto& data = CompressedStackMaps::Handle(
           zone_, CompressedStackMaps::NewGlobalTable(stream.buffer(),
                                                      stream.bytes_written()));
-      return data.raw();
+      return data.ptr();
     }
 
    private:
@@ -646,11 +647,13 @@
         public Dedupper<CompressedStackMaps,
                         PointerKeyValueTrait<const CompressedStackMaps>> {
    public:
-    NormalizeAndDedupCompressedStackMapsVisitor(Zone* zone, Isolate* isolate)
+    NormalizeAndDedupCompressedStackMapsVisitor(Zone* zone,
+                                                IsolateGroup* isolate_group)
         : Dedupper(zone),
           old_global_table_(CompressedStackMaps::Handle(
               zone,
-              isolate->object_store()->canonicalized_stack_map_entries())),
+              isolate_group->object_store()
+                  ->canonicalized_stack_map_entries())),
           entry_offsets_(zone),
           maps_(CompressedStackMaps::Handle(zone)) {
       ASSERT(old_global_table_.IsNull() || old_global_table_.IsGlobalTable());
@@ -661,7 +664,7 @@
       // frequency the same entry info was seen across all CSMs in each SME.
 
       CollectStackMapEntriesVisitor collect_visitor(zone, old_global_table_);
-      WalkProgram(zone, isolate, &collect_visitor);
+      WalkProgram(zone, isolate_group, &collect_visitor);
 
       // The results of phase 1 are used to create a new global table with
       // entries sorted by decreasing frequency, so that entries that appear
@@ -671,7 +674,7 @@
 
       const auto& new_global_table = CompressedStackMaps::Handle(
           zone, collect_visitor.CreateGlobalTable(&entry_offsets_));
-      isolate->object_store()->set_canonicalized_stack_map_entries(
+      isolate_group->object_store()->set_canonicalized_stack_map_entries(
           new_global_table);
 
       // 2) Visit all CSMs and replace each with a canonicalized normalized
@@ -685,7 +688,7 @@
       // First check is to make sure [maps] hasn't already been normalized,
       // since any normalized map already has a canonical entry in the set.
       if (auto const canonical = canonical_objects_.LookupValue(&maps_)) {
-        maps_ = canonical->raw();
+        maps_ = canonical->ptr();
       } else {
         maps_ = NormalizeEntries(maps_);
         maps_ = Dedup(maps_);
@@ -698,7 +701,7 @@
     CompressedStackMapsPtr NormalizeEntries(const CompressedStackMaps& maps) {
       if (maps.payload_size() == 0) {
         // No entries, so use the canonical empty map.
-        return Object::empty_compressed_stackmaps().raw();
+        return Object::empty_compressed_stackmaps().ptr();
       }
       MallocWriteStream new_payload(maps.payload_size());
       CompressedStackMaps::Iterator it(maps, old_global_table_);
@@ -720,8 +723,9 @@
     CompressedStackMaps& maps_;
   };
 
-  NormalizeAndDedupCompressedStackMapsVisitor dedup_visitor(zone, isolate);
-  WalkProgram(zone, isolate, &dedup_visitor);
+  NormalizeAndDedupCompressedStackMapsVisitor dedup_visitor(zone,
+                                                            isolate_group);
+  WalkProgram(zone, isolate_group, &dedup_visitor);
 }
 
 class PcDescriptorsKeyValueTrait {
@@ -742,7 +746,8 @@
   }
 };
 
-void ProgramVisitor::DedupPcDescriptors(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::DedupPcDescriptors(Zone* zone,
+                                        IsolateGroup* isolate_group) {
   class DedupPcDescriptorsVisitor
       : public CodeVisitor,
         public Dedupper<PcDescriptors, PcDescriptorsKeyValueTrait> {
@@ -767,7 +772,7 @@
   };
 
   DedupPcDescriptorsVisitor visitor(zone);
-  WalkProgram(zone, isolate, &visitor);
+  WalkProgram(zone, isolate_group, &visitor);
 }
 
 class TypedDataKeyValueTrait {
@@ -796,7 +801,8 @@
   bool IsCorrectType(const Object& obj) const { return obj.IsTypedData(); }
 };
 
-void ProgramVisitor::DedupDeoptEntries(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::DedupDeoptEntries(Zone* zone,
+                                       IsolateGroup* isolate_group) {
   class DedupDeoptEntriesVisitor : public CodeVisitor,
                                    public TypedDataDedupper {
    public:
@@ -831,11 +837,12 @@
 
   if (FLAG_precompiled_mode) return;
   DedupDeoptEntriesVisitor visitor(zone);
-  WalkProgram(zone, isolate, &visitor);
+  WalkProgram(zone, isolate_group, &visitor);
 }
 
 #if defined(DART_PRECOMPILER)
-void ProgramVisitor::DedupCatchEntryMovesMaps(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::DedupCatchEntryMovesMaps(Zone* zone,
+                                              IsolateGroup* isolate_group) {
   class DedupCatchEntryMovesMapsVisitor : public CodeVisitor,
                                           public TypedDataDedupper {
    public:
@@ -855,7 +862,7 @@
 
   if (!FLAG_precompiled_mode) return;
   DedupCatchEntryMovesMapsVisitor visitor(zone);
-  WalkProgram(zone, isolate, &visitor);
+  WalkProgram(zone, isolate_group, &visitor);
 }
 
 class UnlinkedCallKeyValueTrait {
@@ -876,17 +883,18 @@
   }
 };
 
-void ProgramVisitor::DedupUnlinkedCalls(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::DedupUnlinkedCalls(Zone* zone,
+                                        IsolateGroup* isolate_group) {
   class DedupUnlinkedCallsVisitor
       : public CodeVisitor,
         public Dedupper<UnlinkedCall, UnlinkedCallKeyValueTrait> {
    public:
-    explicit DedupUnlinkedCallsVisitor(Zone* zone, Isolate* isolate)
+    explicit DedupUnlinkedCallsVisitor(Zone* zone, IsolateGroup* isolate_group)
         : Dedupper(zone),
           entry_(Object::Handle(zone)),
           pool_(ObjectPool::Handle(zone)) {
       auto& gop = ObjectPool::Handle(
-          zone, isolate->object_store()->global_object_pool());
+          zone, isolate_group->object_store()->global_object_pool());
       ASSERT_EQUAL(!gop.IsNull(), FLAG_use_bare_instructions);
       DedupPool(gop);
     }
@@ -916,7 +924,7 @@
 
   if (!FLAG_precompiled_mode) return;
 
-  DedupUnlinkedCallsVisitor deduper(zone, isolate);
+  DedupUnlinkedCallsVisitor deduper(zone, isolate_group);
 
   // Note: in bare instructions mode we can still have object pools attached
   // to code objects and these pools need to be deduplicated.
@@ -927,7 +935,7 @@
   if (!FLAG_use_bare_instructions ||
       FLAG_write_v8_snapshot_profile_to != nullptr ||
       FLAG_trace_precompiler_to != nullptr) {
-    WalkProgram(zone, isolate, &deduper);
+    WalkProgram(zone, isolate_group, &deduper);
   }
 }
 #endif  // defined(DART_PRECOMPILER)
@@ -954,7 +962,8 @@
   }
 };
 
-void ProgramVisitor::DedupCodeSourceMaps(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::DedupCodeSourceMaps(Zone* zone,
+                                         IsolateGroup* isolate_group) {
   class DedupCodeSourceMapsVisitor
       : public CodeVisitor,
         public Dedupper<CodeSourceMap, CodeSourceMapKeyValueTrait> {
@@ -978,7 +987,7 @@
   };
 
   DedupCodeSourceMapsVisitor visitor(zone);
-  WalkProgram(zone, isolate, &visitor);
+  WalkProgram(zone, isolate_group, &visitor);
 }
 
 class ArrayKeyValueTrait {
@@ -1007,14 +1016,14 @@
   }
 };
 
-void ProgramVisitor::DedupLists(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::DedupLists(Zone* zone, IsolateGroup* isolate_group) {
   class DedupListsVisitor : public CodeVisitor,
                             public Dedupper<Array, ArrayKeyValueTrait> {
    public:
     explicit DedupListsVisitor(Zone* zone)
         : Dedupper(zone),
           list_(Array::Handle(zone)),
-          function_(Function::Handle(zone)) {}
+          field_(Field::Handle(zone)) {}
 
     void VisitCode(const Code& code) {
       if (!code.IsFunctionCode()) return;
@@ -1033,36 +1042,34 @@
     }
 
     void VisitFunction(const Function& function) {
-      list_ = PrepareParameterTypes(function);
-      list_ = Dedup(list_);
-      function.set_parameter_types(list_);
-
       list_ = PrepareParameterNames(function);
       list_ = Dedup(list_);
       function.set_parameter_names(list_);
+
+      // No need to dedup parameter types, as they are stored in the
+      // canonicalized function type of the function.
+      // However, the function type of the function is only needed in case of
+      // recompilation or if available to mirrors, or for copied types
+      // to lazily generated tear offs. Also avoid attempting to change
+      // read-only VM objects for de-duplication.
+      // We cannot check precisely if a function is an entry point here,
+      // because the metadata has been dropped already. However, we use the
+      // has_pragma flag on the function as a conservative approximation.
+      // Resolution requires the number of parameters (no signature needed) and
+      // their names if any named parameter is required (signature needed).
+      if (FLAG_precompiled_mode && !function.InVMIsolateHeap() &&
+          !function.IsClosureFunction() && !function.IsFfiTrampoline() &&
+          function.name() != Symbols::Call().ptr() && !function.is_native() &&
+          !function.HasRequiredNamedParameters() &&
+          !MayBeEntryPoint(function)) {
+        // Function type not needed for function type tests or resolution.
+        function.set_signature(Object::null_function_type());
+      }
     }
 
    private:
     bool IsCorrectType(const Object& obj) const { return obj.IsArray(); }
 
-    ArrayPtr PrepareParameterTypes(const Function& function) {
-      list_ = function.parameter_types();
-      // Preserve parameter types in the JIT. Needed in case of recompilation
-      // in checked mode, or if available to mirrors, or for copied types to
-      // lazily generated tear offs. Also avoid attempting to change read-only
-      // VM objects for de-duplication.
-      if (FLAG_precompiled_mode && !list_.IsNull() &&
-          !list_.InVMIsolateHeap() && !function.IsSignatureFunction() &&
-          !function.IsClosureFunction() && !function.IsFfiTrampoline() &&
-          function.name() != Symbols::Call().raw()) {
-        // Parameter types not needed for function type tests.
-        for (intptr_t i = 0; i < list_.Length(); i++) {
-          list_.SetAt(i, Object::dynamic_type());
-        }
-      }
-      return list_.raw();
-    }
-
     ArrayPtr PrepareParameterNames(const Function& function) {
       list_ = function.parameter_names();
       // Preserve parameter names in case of recompilation for the JIT. Also
@@ -1075,15 +1082,30 @@
           list_.SetAt(i, Symbols::OptimizedOut());
         }
       }
-      return list_.raw();
+      return list_.ptr();
+    }
+
+    bool MayBeEntryPoint(const Function& function) {
+      // Metadata has been dropped already.
+      // Use presence of pragma as conservative approximation.
+      if (function.has_pragma()) return true;
+      auto kind = function.kind();
+      if ((kind == UntaggedFunction::kImplicitGetter) ||
+          (kind == UntaggedFunction::kImplicitSetter) ||
+          (kind == UntaggedFunction::kImplicitStaticGetter) ||
+          (kind == UntaggedFunction::kFieldInitializer)) {
+        field_ = function.accessor_field();
+        if (!field_.IsNull() && field_.has_pragma()) return true;
+      }
+      return false;
     }
 
     Array& list_;
-    Function& function_;
+    Field& field_;
   };
 
   DedupListsVisitor visitor(zone);
-  WalkProgram(zone, isolate, &visitor);
+  WalkProgram(zone, isolate_group, &visitor);
 }
 
 // Traits for comparing two [Instructions] objects for equality, which is
@@ -1141,7 +1163,7 @@
     // In AOT, disabled code objects should not be considered for deduplication.
     ASSERT(!pair->IsDisabled() && !key->IsDisabled());
 
-    if (pair->raw() == key->raw()) return true;
+    if (pair->ptr() == key->ptr()) return true;
 
     // Notice we assume that these entries have already been de-duped, so we
     // can use pointer equality.
@@ -1168,7 +1190,8 @@
 };
 #endif
 
-void ProgramVisitor::DedupInstructions(Zone* zone, Isolate* isolate) {
+void ProgramVisitor::DedupInstructions(Zone* zone,
+                                       IsolateGroup* isolate_group) {
   class DedupInstructionsVisitor
       : public CodeVisitor,
         public Dedupper<Instructions, InstructionsKeyValueTrait>,
@@ -1180,7 +1203,7 @@
           instructions_(Instructions::Handle(zone)) {
       if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) {
         // Prefer existing objects in the VM isolate.
-        Dart::vm_isolate()->heap()->VisitObjectsImagePages(this);
+        Dart::vm_isolate_group()->heap()->VisitObjectsImagePages(this);
       }
     }
 
@@ -1197,7 +1220,7 @@
       // ProgramWalker, but as long as the deduplication process is idempotent,
       // the cached entry points won't change during the second visit.
       VisitCode(code_);
-      function.SetInstructions(code_);  // Update cached entry point.
+      function.SetInstructionsSafe(code_);  // Update cached entry point.
     }
 
     void VisitCode(const Code& code) {
@@ -1208,8 +1231,8 @@
         instructions_ = code.active_instructions();
         instructions_ = Dedup(instructions_);
       }
-      code.SetActiveInstructions(instructions_,
-                                 code.UncheckedEntryPointOffset());
+      code.SetActiveInstructionsSafe(instructions_,
+                                     code.UncheckedEntryPointOffset());
     }
 
    private:
@@ -1235,15 +1258,15 @@
       // ProgramWalker, but as long as the deduplication process is idempotent,
       // the cached entry points won't change during the second visit.
       VisitCode(code_);
-      function.SetInstructions(code_);  // Update cached entry point.
+      function.SetInstructionsSafe(code_);  // Update cached entry point.
     }
 
     void VisitCode(const Code& code) {
       if (code.IsDisabled()) return;
       canonical_ = Dedup(code);
       instructions_ = canonical_.instructions();
-      code.SetActiveInstructions(instructions_,
-                                 code.UncheckedEntryPointOffset());
+      code.SetActiveInstructionsSafe(instructions_,
+                                     code.UncheckedEntryPointOffset());
       code.set_instructions(instructions_);
     }
 
@@ -1257,33 +1280,33 @@
 
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     DedupInstructionsWithSameMetadataVisitor visitor(zone);
-    return WalkProgram(zone, isolate, &visitor);
+    return WalkProgram(zone, isolate_group, &visitor);
   }
 #endif  // defined(DART_PRECOMPILER)
 
   DedupInstructionsVisitor visitor(zone);
-  WalkProgram(zone, isolate, &visitor);
+  WalkProgram(zone, isolate_group, &visitor);
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 void ProgramVisitor::Dedup(Thread* thread) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  auto const isolate = thread->isolate();
+  auto const isolate_group = thread->isolate_group();
   StackZone stack_zone(thread);
   HANDLESCOPE(thread);
   auto const zone = thread->zone();
 
-  BindStaticCalls(zone, isolate);
-  ShareMegamorphicBuckets(zone, isolate);
-  NormalizeAndDedupCompressedStackMaps(zone, isolate);
-  DedupPcDescriptors(zone, isolate);
-  DedupDeoptEntries(zone, isolate);
+  BindStaticCalls(zone, isolate_group);
+  ShareMegamorphicBuckets(zone, isolate_group);
+  NormalizeAndDedupCompressedStackMaps(zone, isolate_group);
+  DedupPcDescriptors(zone, isolate_group);
+  DedupDeoptEntries(zone, isolate_group);
 #if defined(DART_PRECOMPILER)
-  DedupCatchEntryMovesMaps(zone, isolate);
-  DedupUnlinkedCalls(zone, isolate);
+  DedupCatchEntryMovesMaps(zone, isolate_group);
+  DedupUnlinkedCalls(zone, isolate_group);
 #endif
-  DedupCodeSourceMaps(zone, isolate);
-  DedupLists(zone, isolate);
+  DedupCodeSourceMaps(zone, isolate_group);
+  DedupLists(zone, isolate_group);
 
   // Reduces binary size but obfuscates profiler results.
   if (FLAG_dedup_instructions) {
@@ -1306,7 +1329,7 @@
     if (FLAG_precompiled_mode && !FLAG_use_bare_instructions) return;
 #endif
 
-    DedupInstructions(zone, isolate);
+    DedupInstructions(zone, isolate_group);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
@@ -1341,25 +1364,31 @@
       UNREACHABLE();
     }
 
-    ASSERT(heap_->GetLoadingUnit(code.raw()) == WeakTable::kNoValue);
-    heap_->SetLoadingUnit(code.raw(), id);
+    ASSERT(heap_->GetLoadingUnit(code.ptr()) == WeakTable::kNoValue);
+    heap_->SetLoadingUnit(code.ptr(), id);
 
     obj_ = code.code_source_map();
     MergeAssignment(obj_, id);
     obj_ = code.compressed_stackmaps();
     MergeAssignment(obj_, id);
+    if (!FLAG_use_bare_instructions) {
+      obj_ = code.object_pool();
+      MergeAssignment(obj_, id);
+    }
   }
 
   void MergeAssignment(const Object& obj, intptr_t id) {
-    intptr_t old_id = heap_->GetLoadingUnit(obj_.raw());
+    if (obj.IsNull()) return;
+
+    intptr_t old_id = heap_->GetLoadingUnit(obj_.ptr());
     if (old_id == WeakTable::kNoValue) {
-      heap_->SetLoadingUnit(obj_.raw(), id);
+      heap_->SetLoadingUnit(obj_.ptr(), id);
     } else if (old_id == id) {
       // Shared with another code in the same loading unit.
     } else {
       // Shared with another code in a different loading unit.
       // Could assign to dominating loading unit.
-      heap_->SetLoadingUnit(obj_.raw(), LoadingUnit::kRootId);
+      heap_->SetLoadingUnit(obj_.ptr(), LoadingUnit::kRootId);
     }
   }
 
@@ -1382,24 +1411,24 @@
   Code& code = Code::Handle(zone);
   for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
     inst = StubCode::EntryAt(i).instructions();
-    thread->heap()->SetLoadingUnit(inst.raw(), LoadingUnit::kRootId);
+    thread->heap()->SetLoadingUnit(inst.ptr(), LoadingUnit::kRootId);
   }
 
   // Isolate stubs.
-  ObjectStore* object_store = thread->isolate()->object_store();
+  ObjectStore* object_store = thread->isolate_group()->object_store();
   ObjectPtr* from = object_store->from();
   ObjectPtr* to = object_store->to_snapshot(Snapshot::kFullAOT);
   for (ObjectPtr* p = from; p <= to; p++) {
     if ((*p)->IsCode()) {
       code ^= *p;
       inst = code.instructions();
-      thread->heap()->SetLoadingUnit(inst.raw(), LoadingUnit::kRootId);
+      thread->heap()->SetLoadingUnit(inst.ptr(), LoadingUnit::kRootId);
     }
   }
 
   // Function code / allocation stubs.
   AssignLoadingUnitsCodeVisitor visitor(zone);
-  WalkProgram(zone, thread->isolate(), &visitor);
+  WalkProgram(zone, thread->isolate_group(), &visitor);
 }
 
 class ProgramHashVisitor : public CodeVisitor {
@@ -1462,9 +1491,9 @@
   Zone* zone = thread->zone();
 
   ProgramHashVisitor visitor(zone);
-  WalkProgram(zone, thread->isolate(), &visitor);
+  WalkProgram(zone, thread->isolate_group(), &visitor);
   visitor.VisitPool(ObjectPool::Handle(
-      zone, thread->isolate()->object_store()->global_object_pool()));
+      zone, thread->isolate_group()->object_store()->global_object_pool()));
   return visitor.hash();
 }
 
diff --git a/runtime/vm/program_visitor.h b/runtime/vm/program_visitor.h
index d535f1f..06aa481 100644
--- a/runtime/vm/program_visitor.h
+++ b/runtime/vm/program_visitor.h
@@ -87,13 +87,15 @@
 };
 
 class Thread;
-class Isolate;
+class IsolateGroup;
 
 class ProgramVisitor : public AllStatic {
  public:
   // Walks all non-null class, function, and code objects in the program as
   // necessary for the given visitor.
-  static void WalkProgram(Zone* zone, Isolate* isolate, ClassVisitor* visitor);
+  static void WalkProgram(Zone* zone,
+                          IsolateGroup* isolate_group,
+                          ClassVisitor* visitor);
 
   static void Dedup(Thread* thread);
 #if defined(DART_PRECOMPILER)
@@ -103,19 +105,19 @@
 
  private:
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  static void BindStaticCalls(Zone* zone, Isolate* isolate);
-  static void ShareMegamorphicBuckets(Zone* zone, Isolate* isolate);
+  static void BindStaticCalls(Zone* zone, IsolateGroup* isolate_group);
+  static void ShareMegamorphicBuckets(Zone* zone, IsolateGroup* isolate_group);
   static void NormalizeAndDedupCompressedStackMaps(Zone* zone,
-                                                   Isolate* isolate);
-  static void DedupPcDescriptors(Zone* zone, Isolate* isolate);
-  static void DedupDeoptEntries(Zone* zone, Isolate* isolate);
+                                                   IsolateGroup* isolate_group);
+  static void DedupPcDescriptors(Zone* zone, IsolateGroup* isolate_group);
+  static void DedupDeoptEntries(Zone* zone, IsolateGroup* isolate_group);
 #if defined(DART_PRECOMPILER)
-  static void DedupCatchEntryMovesMaps(Zone* zone, Isolate* isolate);
-  static void DedupUnlinkedCalls(Zone* zone, Isolate* isolate);
+  static void DedupCatchEntryMovesMaps(Zone* zone, IsolateGroup* isolate_group);
+  static void DedupUnlinkedCalls(Zone* zone, IsolateGroup* isolate_group);
 #endif
-  static void DedupCodeSourceMaps(Zone* zone, Isolate* isolate);
-  static void DedupLists(Zone* zone, Isolate* isolate);
-  static void DedupInstructions(Zone* zone, Isolate* isolate);
+  static void DedupCodeSourceMaps(Zone* zone, IsolateGroup* isolate_group);
+  static void DedupLists(Zone* zone, IsolateGroup* isolate_group);
+  static void DedupInstructions(Zone* zone, IsolateGroup* isolate_group);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 };
 
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 64adf66..a142516 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -16,12 +16,12 @@
 
 namespace dart {
 
-bool ObjectLayout::InVMIsolateHeap() const {
+bool UntaggedObject::InVMIsolateHeap() const {
   // All "vm-isolate" objects are pre-marked and in old space
   // (see [Object::FinalizeVMIsolate]).
   if (!IsOldObject() || !IsMarked()) return false;
 
-  auto heap = Dart::vm_isolate()->heap();
+  auto heap = Dart::vm_isolate_group()->heap();
   ASSERT(heap->UsedInWords(Heap::kNew) == 0);
   return heap->old_space()->ContainsUnsafe(ToAddr(this));
 }
@@ -35,10 +35,10 @@
   if (tagged_pointer_ == kHeapObjectTag) {
     FATAL("RAW_NULL encountered");
   }
-  ptr()->Validate(isolate_group);
+  untag()->Validate(isolate_group);
 }
 
-void ObjectLayout::Validate(IsolateGroup* isolate_group) const {
+void UntaggedObject::Validate(IsolateGroup* isolate_group) const {
   if (static_cast<uword>(Object::void_class_) == kHeapObjectTag) {
     // Validation relies on properly initialized class classes. Skip if the
     // VM is still being initialized.
@@ -90,14 +90,14 @@
 // compaction when the class objects are moving. Can use the class
 // id in the header and the sizes in the Class Table.
 // Cannot deference ptr()->tags_. May dereference other parts of the object.
-intptr_t ObjectLayout::HeapSizeFromClass(uword tags) const {
+intptr_t UntaggedObject::HeapSizeFromClass(uword tags) const {
   intptr_t class_id = ClassIdTag::decode(tags);
   intptr_t instance_size = 0;
   switch (class_id) {
     case kCodeCid: {
       const CodePtr raw_code = static_cast<const CodePtr>(this);
       intptr_t pointer_offsets_length =
-          Code::PtrOffBits::decode(raw_code->ptr()->state_bits_);
+          Code::PtrOffBits::decode(raw_code->untag()->state_bits_);
       instance_size = Code::InstanceSize(pointer_offsets_length);
       break;
     }
@@ -117,28 +117,28 @@
     }
     case kContextCid: {
       const ContextPtr raw_context = static_cast<const ContextPtr>(this);
-      intptr_t num_variables = raw_context->ptr()->num_variables_;
+      intptr_t num_variables = raw_context->untag()->num_variables_;
       instance_size = Context::InstanceSize(num_variables);
       break;
     }
     case kContextScopeCid: {
       const ContextScopePtr raw_context_scope =
           static_cast<const ContextScopePtr>(this);
-      intptr_t num_variables = raw_context_scope->ptr()->num_variables_;
+      intptr_t num_variables = raw_context_scope->untag()->num_variables_;
       instance_size = ContextScope::InstanceSize(num_variables);
       break;
     }
     case kOneByteStringCid: {
       const OneByteStringPtr raw_string =
           static_cast<const OneByteStringPtr>(this);
-      intptr_t string_length = Smi::Value(raw_string->ptr()->length_);
+      intptr_t string_length = Smi::Value(raw_string->untag()->length_);
       instance_size = OneByteString::InstanceSize(string_length);
       break;
     }
     case kTwoByteStringCid: {
       const TwoByteStringPtr raw_string =
           static_cast<const TwoByteStringPtr>(this);
-      intptr_t string_length = Smi::Value(raw_string->ptr()->length_);
+      intptr_t string_length = Smi::Value(raw_string->untag()->length_);
       instance_size = TwoByteString::InstanceSize(string_length);
       break;
     }
@@ -146,21 +146,21 @@
     case kImmutableArrayCid: {
       const ArrayPtr raw_array = static_cast<const ArrayPtr>(this);
       intptr_t array_length =
-          Smi::Value(raw_array->ptr()->length<std::memory_order_acquire>());
+          Smi::Value(raw_array->untag()->length<std::memory_order_acquire>());
       instance_size = Array::InstanceSize(array_length);
       break;
     }
     case kObjectPoolCid: {
       const ObjectPoolPtr raw_object_pool =
           static_cast<const ObjectPoolPtr>(this);
-      intptr_t len = raw_object_pool->ptr()->length_;
+      intptr_t len = raw_object_pool->untag()->length_;
       instance_size = ObjectPool::InstanceSize(len);
       break;
     }
 #define SIZE_FROM_CLASS(clazz) case kTypedData##clazz##Cid:
       CLASS_LIST_TYPED_DATA(SIZE_FROM_CLASS) {
         const TypedDataPtr raw_obj = static_cast<const TypedDataPtr>(this);
-        intptr_t array_len = Smi::Value(raw_obj->ptr()->length_);
+        intptr_t array_len = Smi::Value(raw_obj->untag()->length_);
         intptr_t lengthInBytes =
             array_len * TypedData::ElementSizeInBytes(class_id);
         instance_size = TypedData::InstanceSize(lengthInBytes);
@@ -173,21 +173,21 @@
     case kTypeArgumentsCid: {
       const TypeArgumentsPtr raw_array =
           static_cast<const TypeArgumentsPtr>(this);
-      intptr_t array_length = Smi::Value(raw_array->ptr()->length_);
+      intptr_t array_length = Smi::Value(raw_array->untag()->length_);
       instance_size = TypeArguments::InstanceSize(array_length);
       break;
     }
     case kPcDescriptorsCid: {
       const PcDescriptorsPtr raw_descriptors =
           static_cast<const PcDescriptorsPtr>(this);
-      intptr_t length = raw_descriptors->ptr()->length_;
+      intptr_t length = raw_descriptors->untag()->length_;
       instance_size = PcDescriptors::InstanceSize(length);
       break;
     }
     case kCodeSourceMapCid: {
       const CodeSourceMapPtr raw_code_source_map =
           static_cast<const CodeSourceMapPtr>(this);
-      intptr_t length = raw_code_source_map->ptr()->length_;
+      intptr_t length = raw_code_source_map->untag()->length_;
       instance_size = CodeSourceMap::InstanceSize(length);
       break;
     }
@@ -201,25 +201,25 @@
     case kLocalVarDescriptorsCid: {
       const LocalVarDescriptorsPtr raw_descriptors =
           static_cast<const LocalVarDescriptorsPtr>(this);
-      intptr_t num_descriptors = raw_descriptors->ptr()->num_entries_;
+      intptr_t num_descriptors = raw_descriptors->untag()->num_entries_;
       instance_size = LocalVarDescriptors::InstanceSize(num_descriptors);
       break;
     }
     case kExceptionHandlersCid: {
       const ExceptionHandlersPtr raw_handlers =
           static_cast<const ExceptionHandlersPtr>(this);
-      intptr_t num_handlers = raw_handlers->ptr()->num_entries_;
+      intptr_t num_handlers = raw_handlers->untag()->num_entries_;
       instance_size = ExceptionHandlers::InstanceSize(num_handlers);
       break;
     }
     case kFreeListElement: {
-      uword addr = ObjectLayout::ToAddr(this);
+      uword addr = UntaggedObject::ToAddr(this);
       FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
       instance_size = element->HeapSize();
       break;
     }
     case kForwardingCorpse: {
-      uword addr = ObjectLayout::ToAddr(this);
+      uword addr = UntaggedObject::ToAddr(this);
       ForwardingCorpse* element = reinterpret_cast<ForwardingCorpse*>(addr);
       instance_size = element->HeapSize();
       break;
@@ -264,7 +264,7 @@
     do {
       OS::Sleep(1);
       const ArrayPtr raw_array = static_cast<const ArrayPtr>(this);
-      intptr_t array_length = Smi::Value(raw_array->ptr()->length_);
+      intptr_t array_length = Smi::Value(raw_array->untag()->length_);
       instance_size = Array::InstanceSize(array_length);
     } while ((instance_size > tags_size) && (--retries_remaining > 0));
   }
@@ -276,8 +276,8 @@
   return instance_size;
 }
 
-intptr_t ObjectLayout::VisitPointersPredefined(ObjectPointerVisitor* visitor,
-                                               intptr_t class_id) {
+intptr_t UntaggedObject::VisitPointersPredefined(ObjectPointerVisitor* visitor,
+                                                 intptr_t class_id) {
   ASSERT(class_id < kNumPredefinedCids);
 
   intptr_t size = 0;
@@ -286,7 +286,7 @@
 #define RAW_VISITPOINTERS(clazz)                                               \
   case k##clazz##Cid: {                                                        \
     clazz##Ptr raw_obj = static_cast<clazz##Ptr>(this);                        \
-    size = clazz##Layout::Visit##clazz##Pointers(raw_obj, visitor);            \
+    size = Untagged##clazz::Visit##clazz##Pointers(raw_obj, visitor);          \
     break;                                                                     \
   }
     CLASS_LIST_NO_OBJECT(RAW_VISITPOINTERS)
@@ -294,15 +294,15 @@
 #define RAW_VISITPOINTERS(clazz) case kTypedData##clazz##Cid:
     CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) {
       TypedDataPtr raw_obj = static_cast<TypedDataPtr>(this);
-      size = TypedDataLayout::VisitTypedDataPointers(raw_obj, visitor);
+      size = UntaggedTypedData::VisitTypedDataPointers(raw_obj, visitor);
       break;
     }
 #undef RAW_VISITPOINTERS
 #define RAW_VISITPOINTERS(clazz) case kExternalTypedData##clazz##Cid:
     CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) {
       auto raw_obj = static_cast<ExternalTypedDataPtr>(this);
-      size = ExternalTypedDataLayout::VisitExternalTypedDataPointers(raw_obj,
-                                                                     visitor);
+      size = UntaggedExternalTypedData::VisitExternalTypedDataPointers(raw_obj,
+                                                                       visitor);
       break;
     }
 #undef RAW_VISITPOINTERS
@@ -311,24 +311,24 @@
       CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) {
         auto raw_obj = static_cast<TypedDataViewPtr>(this);
         size =
-            TypedDataViewLayout::VisitTypedDataViewPointers(raw_obj, visitor);
+            UntaggedTypedDataView::VisitTypedDataViewPointers(raw_obj, visitor);
         break;
       }
 #undef RAW_VISITPOINTERS
     case kByteBufferCid: {
       InstancePtr raw_obj = static_cast<InstancePtr>(this);
-      size = InstanceLayout::VisitInstancePointers(raw_obj, visitor);
+      size = UntaggedInstance::VisitInstancePointers(raw_obj, visitor);
       break;
     }
     case kFfiPointerCid: {
       PointerPtr raw_obj = static_cast<PointerPtr>(this);
-      size = PointerLayout::VisitPointerPointers(raw_obj, visitor);
+      size = UntaggedPointer::VisitPointerPointers(raw_obj, visitor);
       break;
     }
     case kFfiDynamicLibraryCid: {
       DynamicLibraryPtr raw_obj = static_cast<DynamicLibraryPtr>(this);
       size =
-          DynamicLibraryLayout::VisitDynamicLibraryPointers(raw_obj, visitor);
+          UntaggedDynamicLibrary::VisitDynamicLibraryPointers(raw_obj, visitor);
       break;
     }
 #define RAW_VISITPOINTERS(clazz) case kFfi##clazz##Cid:
@@ -339,13 +339,13 @@
       }
 #undef RAW_VISITPOINTERS
     case kFreeListElement: {
-      uword addr = ObjectLayout::ToAddr(this);
+      uword addr = UntaggedObject::ToAddr(this);
       FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
       size = element->HeapSize();
       break;
     }
     case kForwardingCorpse: {
-      uword addr = ObjectLayout::ToAddr(this);
+      uword addr = UntaggedObject::ToAddr(this);
       ForwardingCorpse* forwarder = reinterpret_cast<ForwardingCorpse*>(addr);
       size = forwarder->HeapSize();
       break;
@@ -377,8 +377,8 @@
 #endif
 }
 
-void ObjectLayout::VisitPointersPrecise(Isolate* isolate,
-                                        ObjectPointerVisitor* visitor) {
+void UntaggedObject::VisitPointersPrecise(Isolate* isolate,
+                                          ObjectPointerVisitor* visitor) {
   intptr_t class_id = GetClassId();
   if (class_id < kNumPredefinedCids) {
     VisitPointersPredefined(visitor, class_id);
@@ -387,12 +387,12 @@
 
   // N.B.: Not using the heap size!
   uword next_field_offset = isolate->GetClassForHeapWalkAt(class_id)
-                                ->ptr()
+                                ->untag()
                                 ->host_next_field_offset_in_words_
                             << kWordSizeLog2;
   ASSERT(next_field_offset > 0);
-  uword obj_addr = ObjectLayout::ToAddr(this);
-  uword from = obj_addr + sizeof(ObjectLayout);
+  uword obj_addr = UntaggedObject::ToAddr(this);
+  uword from = obj_addr + sizeof(UntaggedObject);
   uword to = obj_addr + next_field_offset - kWordSize;
   const auto first = reinterpret_cast<ObjectPtr*>(from);
   const auto last = reinterpret_cast<ObjectPtr*>(to);
@@ -402,7 +402,7 @@
       visitor->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
 
   if (!unboxed_fields_bitmap.IsEmpty()) {
-    intptr_t bit = sizeof(ObjectLayout) / kWordSize;
+    intptr_t bit = sizeof(UntaggedObject) / kWordSize;
     for (ObjectPtr* current = first; current <= last; current++) {
       if (!unboxed_fields_bitmap.Get(bit++)) {
         visitor->VisitPointer(current);
@@ -416,7 +416,7 @@
 #endif  // defined(SUPPORT_UNBOXED_INSTANCE_FIELDS)
 }
 
-bool ObjectLayout::FindObject(FindObjectVisitor* visitor) {
+bool UntaggedObject::FindObject(FindObjectVisitor* visitor) {
   ASSERT(visitor != NULL);
   return visitor->FindObject(static_cast<ObjectPtr>(this));
 }
@@ -425,12 +425,12 @@
 // methods on the raw object to get the first and last cells that need
 // visiting.
 #define REGULAR_VISITOR(Type)                                                  \
-  intptr_t Type##Layout::Visit##Type##Pointers(                                \
+  intptr_t Untagged##Type::Visit##Type##Pointers(                              \
       Type##Ptr raw_obj, ObjectPointerVisitor* visitor) {                      \
     /* Make sure that we got here with the tagged pointer as this. */          \
     ASSERT(raw_obj->IsHeapObject());                                           \
     ASSERT_UNCOMPRESSED(Type);                                                 \
-    visitor->VisitPointers(raw_obj->ptr()->from(), raw_obj->ptr()->to());      \
+    visitor->VisitPointers(raw_obj->untag()->from(), raw_obj->untag()->to());  \
     return Type::InstanceSize();                                               \
   }
 
@@ -440,26 +440,26 @@
 // Though as opposed to Similar to [REGULAR_VISITOR] this visitor will call the
 // specializd VisitTypedDataViewPointers
 #define TYPED_DATA_VIEW_VISITOR(Type)                                          \
-  intptr_t Type##Layout::Visit##Type##Pointers(                                \
+  intptr_t Untagged##Type::Visit##Type##Pointers(                              \
       Type##Ptr raw_obj, ObjectPointerVisitor* visitor) {                      \
     /* Make sure that we got here with the tagged pointer as this. */          \
     ASSERT(raw_obj->IsHeapObject());                                           \
     ASSERT_UNCOMPRESSED(Type);                                                 \
-    visitor->VisitTypedDataViewPointers(raw_obj, raw_obj->ptr()->from(),       \
-                                        raw_obj->ptr()->to());                 \
+    visitor->VisitTypedDataViewPointers(raw_obj, raw_obj->untag()->from(),     \
+                                        raw_obj->untag()->to());               \
     return Type::InstanceSize();                                               \
   }
 
 // For variable length objects. get_length is a code snippet that gets the
 // length of the object, which is passed to InstanceSize and the to() method.
 #define VARIABLE_VISITOR(Type, get_length)                                     \
-  intptr_t Type##Layout::Visit##Type##Pointers(                                \
+  intptr_t Untagged##Type::Visit##Type##Pointers(                              \
       Type##Ptr raw_obj, ObjectPointerVisitor* visitor) {                      \
     /* Make sure that we got here with the tagged pointer as this. */          \
     ASSERT(raw_obj->IsHeapObject());                                           \
     intptr_t length = get_length;                                              \
-    visitor->VisitPointers(raw_obj->ptr()->from(),                             \
-                           raw_obj->ptr()->to(length));                        \
+    visitor->VisitPointers(raw_obj->untag()->from(),                           \
+                           raw_obj->untag()->to(length));                      \
     return Type::InstanceSize(length);                                         \
   }
 
@@ -470,7 +470,7 @@
 
 // For fixed-length objects that don't have any pointers that need visiting.
 #define NULL_VISITOR(Type)                                                     \
-  intptr_t Type##Layout::Visit##Type##Pointers(                                \
+  intptr_t Untagged##Type::Visit##Type##Pointers(                              \
       Type##Ptr raw_obj, ObjectPointerVisitor* visitor) {                      \
     /* Make sure that we got here with the tagged pointer as this. */          \
     ASSERT(raw_obj->IsHeapObject());                                           \
@@ -481,7 +481,7 @@
 // For objects that don't have any pointers that need visiting, but have a
 // variable length.
 #define VARIABLE_NULL_VISITOR(Type, get_length)                                \
-  intptr_t Type##Layout::Visit##Type##Pointers(                                \
+  intptr_t Untagged##Type::Visit##Type##Pointers(                              \
       Type##Ptr raw_obj, ObjectPointerVisitor* visitor) {                      \
     /* Make sure that we got here with the tagged pointer as this. */          \
     ASSERT(raw_obj->IsHeapObject());                                           \
@@ -492,7 +492,7 @@
 
 // For objects that are never instantiated on the heap.
 #define UNREACHABLE_VISITOR(Type)                                              \
-  intptr_t Type##Layout::Visit##Type##Pointers(                                \
+  intptr_t Untagged##Type::Visit##Type##Pointers(                              \
       Type##Ptr raw_obj, ObjectPointerVisitor* visitor) {                      \
     UNREACHABLE();                                                             \
     return 0;                                                                  \
@@ -500,13 +500,13 @@
 
 REGULAR_VISITOR(Class)
 REGULAR_VISITOR(Type)
+REGULAR_VISITOR(FunctionType)
 REGULAR_VISITOR(TypeRef)
 REGULAR_VISITOR(TypeParameter)
 REGULAR_VISITOR(PatchClass)
 REGULAR_VISITOR(Function)
 COMPRESSED_VISITOR(Closure)
 REGULAR_VISITOR(ClosureData)
-REGULAR_VISITOR(SignatureData)
 REGULAR_VISITOR(FfiTrampolineData)
 REGULAR_VISITOR(Script)
 REGULAR_VISITOR(Library)
@@ -536,16 +536,16 @@
 REGULAR_VISITOR(SubtypeTestCache)
 REGULAR_VISITOR(LoadingUnit)
 REGULAR_VISITOR(KernelProgramInfo)
-VARIABLE_VISITOR(TypeArguments, Smi::Value(raw_obj->ptr()->length_))
-VARIABLE_VISITOR(LocalVarDescriptors, raw_obj->ptr()->num_entries_)
-VARIABLE_VISITOR(ExceptionHandlers, raw_obj->ptr()->num_entries_)
-VARIABLE_VISITOR(Context, raw_obj->ptr()->num_variables_)
-VARIABLE_COMPRESSED_VISITOR(Array, Smi::Value(raw_obj->ptr()->length()))
+VARIABLE_VISITOR(TypeArguments, Smi::Value(raw_obj->untag()->length_))
+VARIABLE_VISITOR(LocalVarDescriptors, raw_obj->untag()->num_entries_)
+VARIABLE_VISITOR(ExceptionHandlers, raw_obj->untag()->num_entries_)
+VARIABLE_VISITOR(Context, raw_obj->untag()->num_variables_)
+VARIABLE_COMPRESSED_VISITOR(Array, Smi::Value(raw_obj->untag()->length()))
 VARIABLE_COMPRESSED_VISITOR(
     TypedData,
     TypedData::ElementSizeInBytes(raw_obj->GetClassId()) *
-        Smi::Value(raw_obj->ptr()->length_))
-VARIABLE_VISITOR(ContextScope, raw_obj->ptr()->num_variables_)
+        Smi::Value(raw_obj->untag()->length_))
+VARIABLE_VISITOR(ContextScope, raw_obj->untag()->num_variables_)
 NULL_VISITOR(Mint)
 NULL_VISITOR(Double)
 NULL_VISITOR(Float32x4)
@@ -559,12 +559,12 @@
 NULL_VISITOR(DynamicLibrary)
 VARIABLE_NULL_VISITOR(Instructions, Instructions::Size(raw_obj))
 VARIABLE_NULL_VISITOR(InstructionsSection, InstructionsSection::Size(raw_obj))
-VARIABLE_NULL_VISITOR(PcDescriptors, raw_obj->ptr()->length_)
-VARIABLE_NULL_VISITOR(CodeSourceMap, raw_obj->ptr()->length_)
+VARIABLE_NULL_VISITOR(PcDescriptors, raw_obj->untag()->length_)
+VARIABLE_NULL_VISITOR(CodeSourceMap, raw_obj->untag()->length_)
 VARIABLE_NULL_VISITOR(CompressedStackMaps,
                       CompressedStackMaps::PayloadSizeOf(raw_obj))
-VARIABLE_NULL_VISITOR(OneByteString, Smi::Value(raw_obj->ptr()->length_))
-VARIABLE_NULL_VISITOR(TwoByteString, Smi::Value(raw_obj->ptr()->length_))
+VARIABLE_NULL_VISITOR(OneByteString, Smi::Value(raw_obj->untag()->length_))
+VARIABLE_NULL_VISITOR(TwoByteString, Smi::Value(raw_obj->untag()->length_))
 // Abstract types don't have their visitor called.
 UNREACHABLE_VISITOR(AbstractType)
 UNREACHABLE_VISITOR(CallSiteData)
@@ -582,18 +582,18 @@
 REGULAR_VISITOR(WeakSerializationReference)
 #endif
 
-intptr_t FieldLayout::VisitFieldPointers(FieldPtr raw_obj,
-                                         ObjectPointerVisitor* visitor) {
+intptr_t UntaggedField::VisitFieldPointers(FieldPtr raw_obj,
+                                           ObjectPointerVisitor* visitor) {
   ASSERT(raw_obj->IsHeapObject());
   ASSERT_UNCOMPRESSED(Field);
-  visitor->VisitPointers(raw_obj->ptr()->from(), raw_obj->ptr()->to());
+  visitor->VisitPointers(raw_obj->untag()->from(), raw_obj->untag()->to());
 
   if (visitor->trace_values_through_fields()) {
-    if (Field::StaticBit::decode(raw_obj->ptr()->kind_bits_)) {
+    if (Field::StaticBit::decode(raw_obj->untag()->kind_bits_)) {
       visitor->isolate_group()->ForEachIsolate(
           [&](Isolate* isolate) {
             intptr_t index =
-                Smi::Value(raw_obj->ptr()->host_offset_or_field_id_);
+                Smi::Value(raw_obj->untag()->host_offset_or_field_id_);
             visitor->VisitPointer(&isolate->field_table()->table()[index]);
           },
           /*at_safepoint=*/true);
@@ -602,7 +602,7 @@
   return Field::InstanceSize();
 }
 
-bool CodeLayout::ContainsPC(const ObjectPtr raw_obj, uword pc) {
+bool UntaggedCode::ContainsPC(const ObjectPtr raw_obj, uword pc) {
   if (!raw_obj->IsCode()) return false;
   auto const raw_code = static_cast<const CodePtr>(raw_obj);
   const uword start = Code::PayloadStartOf(raw_code);
@@ -610,11 +610,11 @@
   return (pc - start) <= size;  // pc may point just past last instruction.
 }
 
-intptr_t CodeLayout::VisitCodePointers(CodePtr raw_obj,
-                                       ObjectPointerVisitor* visitor) {
-  visitor->VisitPointers(raw_obj->ptr()->from(), raw_obj->ptr()->to());
+intptr_t UntaggedCode::VisitCodePointers(CodePtr raw_obj,
+                                         ObjectPointerVisitor* visitor) {
+  visitor->VisitPointers(raw_obj->untag()->from(), raw_obj->untag()->to());
 
-  CodeLayout* obj = raw_obj->ptr();
+  UntaggedCode* obj = raw_obj->untag();
   intptr_t length = Code::PtrOffBits::decode(obj->state_bits_);
 #if defined(TARGET_ARCH_IA32)
   // On IA32 only we embed pointers to objects directly in the generated
@@ -636,12 +636,12 @@
 #endif
 }
 
-intptr_t ObjectPoolLayout::VisitObjectPoolPointers(
+intptr_t UntaggedObjectPool::VisitObjectPoolPointers(
     ObjectPoolPtr raw_obj,
     ObjectPointerVisitor* visitor) {
-  const intptr_t length = raw_obj->ptr()->length_;
-  ObjectPoolLayout::Entry* entries = raw_obj->ptr()->data();
-  uint8_t* entry_bits = raw_obj->ptr()->entry_bits();
+  const intptr_t length = raw_obj->untag()->length_;
+  UntaggedObjectPool::Entry* entries = raw_obj->untag()->data();
+  uint8_t* entry_bits = raw_obj->untag()->entry_bits();
   for (intptr_t i = 0; i < length; ++i) {
     ObjectPool::EntryType entry_type =
         ObjectPool::TypeBits::decode(entry_bits[i]);
@@ -652,7 +652,8 @@
   return ObjectPool::InstanceSize(length);
 }
 
-bool InstructionsLayout::ContainsPC(const InstructionsPtr raw_instr, uword pc) {
+bool UntaggedInstructions::ContainsPC(const InstructionsPtr raw_instr,
+                                      uword pc) {
   const uword start = Instructions::PayloadStart(raw_instr);
   const uword size = Instructions::Size(raw_instr);
   // We use <= instead of < here because the saved-pc can be outside the
@@ -661,11 +662,12 @@
   return (pc - start) <= size;
 }
 
-intptr_t InstanceLayout::VisitInstancePointers(InstancePtr raw_obj,
-                                               ObjectPointerVisitor* visitor) {
+intptr_t UntaggedInstance::VisitInstancePointers(
+    InstancePtr raw_obj,
+    ObjectPointerVisitor* visitor) {
   // Make sure that we got here with the tagged pointer as this.
   ASSERT(raw_obj->IsHeapObject());
-  uword tags = raw_obj->ptr()->tags_;
+  uword tags = raw_obj->untag()->tags_;
   intptr_t instance_size = SizeTag::decode(tags);
   if (instance_size == 0) {
     instance_size = visitor->isolate_group()->GetClassSizeForHeapWalkAt(
@@ -673,21 +675,21 @@
   }
 
   // Calculate the first and last raw object pointer fields.
-  uword obj_addr = ObjectLayout::ToAddr(raw_obj);
-  uword from = obj_addr + sizeof(ObjectLayout);
+  uword obj_addr = UntaggedObject::ToAddr(raw_obj);
+  uword from = obj_addr + sizeof(UntaggedObject);
   uword to = obj_addr + instance_size - kWordSize;
   visitor->VisitPointers(reinterpret_cast<ObjectPtr*>(from),
                          reinterpret_cast<ObjectPtr*>(to));
   return instance_size;
 }
 
-intptr_t ImmutableArrayLayout::VisitImmutableArrayPointers(
+intptr_t UntaggedImmutableArray::VisitImmutableArrayPointers(
     ImmutableArrayPtr raw_obj,
     ObjectPointerVisitor* visitor) {
-  return ArrayLayout::VisitArrayPointers(raw_obj, visitor);
+  return UntaggedArray::VisitArrayPointers(raw_obj, visitor);
 }
 
-void ObjectLayout::RememberCard(ObjectPtr const* slot) {
+void UntaggedObject::RememberCard(ObjectPtr const* slot) {
   OldPage::Of(static_cast<ObjectPtr>(this))->RememberCard(slot);
 }
 
@@ -698,12 +700,12 @@
                           ObjectPtr* slot) {
   ObjectPtr object = static_cast<ObjectPtr>(object_in);
   ASSERT(object->IsOldObject());
-  ASSERT(object->ptr()->IsCardRemembered());
+  ASSERT(object->untag()->IsCardRemembered());
   OldPage::Of(object)->RememberCard(slot);
 }
 END_LEAF_RUNTIME_ENTRY
 
-const char* PcDescriptorsLayout::KindToCString(Kind k) {
+const char* UntaggedPcDescriptors::KindToCString(Kind k) {
   switch (k) {
 #define ENUM_CASE(name, init)                                                  \
   case Kind::k##name:                                                          \
@@ -715,7 +717,7 @@
   }
 }
 
-bool PcDescriptorsLayout::ParseKind(const char* cstr, Kind* out) {
+bool UntaggedPcDescriptors::ParseKind(const char* cstr, Kind* out) {
   ASSERT(cstr != nullptr && out != nullptr);
 #define ENUM_CASE(name, init)                                                  \
   if (strcmp(#name, cstr) == 0) {                                              \
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 15af026..8a02e59 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -28,7 +28,7 @@
 //  * Target architecture
 //  * DART_PRECOMPILED_RUNTIME (i.e, AOT vs. JIT)
 //
-// That is, fields in ObjectLayout and its subclasses should only be included or
+// That is, fields in UntaggedObject and its subclasses should only be included or
 // excluded conditionally based on these factors. Otherwise, the generated
 // offsets can be wrong (which should be caught by offset checking in dart.cc).
 //
@@ -42,7 +42,7 @@
 // Forward declarations.
 class Isolate;
 class IsolateGroup;
-#define DEFINE_FORWARD_DECLARATION(clazz) class clazz##Layout;
+#define DEFINE_FORWARD_DECLARATION(clazz) class Untagged##clazz;
 CLASS_LIST(DEFINE_FORWARD_DECLARATION)
 #undef DEFINE_FORWARD_DECLARATION
 class CodeStatistics;
@@ -59,15 +59,15 @@
 #define VISIT_NOTHING() int NothingToVisit();
 
 #define ASSERT_UNCOMPRESSED(Type)                                              \
-  ASSERT(SIZE_OF_DEREFERENCED_RETURNED_VALUE(Type##Layout, from) == kWordSize)
+  ASSERT(SIZE_OF_DEREFERENCED_RETURNED_VALUE(Untagged##Type, from) == kWordSize)
 
 // For now there are no compressed pointers, so this assert is the same as
 // the above.
 #define ASSERT_COMPRESSED(Type)                                                \
-  ASSERT(SIZE_OF_DEREFERENCED_RETURNED_VALUE(Type##Layout, from) == kWordSize)
+  ASSERT(SIZE_OF_DEREFERENCED_RETURNED_VALUE(Untagged##Type, from) == kWordSize)
 
 #define ASSERT_NOTHING_TO_VISIT(Type)                                          \
-  ASSERT(SIZE_OF_RETURNED_VALUE(Type##Layout, NothingToVisit) == sizeof(int))
+  ASSERT(SIZE_OF_RETURNED_VALUE(Untagged##Type, NothingToVisit) == sizeof(int))
 
 enum TypedDataElementType {
 #define V(name) k##name##Element,
@@ -90,13 +90,13 @@
  private: /* NOLINT */                                                         \
   VISITOR_SUPPORT(object)                                                      \
   friend class object;                                                         \
-  friend class ObjectLayout;                                                   \
+  friend class UntaggedObject;                                                 \
   friend class Heap;                                                           \
   friend class Simulator;                                                      \
   friend class SimulatorHelpers;                                               \
   friend class OffsetsTable;                                                   \
   DISALLOW_ALLOCATION();                                                       \
-  DISALLOW_IMPLICIT_CONSTRUCTORS(object##Layout)
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Untagged##object)
 
 #define RAW_HEAP_OBJECT_IMPLEMENTATION(object)                                 \
  private:                                                                      \
@@ -112,7 +112,7 @@
 // RawObject is the base class of all raw objects; even though it carries the
 // tags_ field not all raw objects are allocated in the heap and thus cannot
 // be dereferenced (e.g. RawSmi).
-class ObjectLayout {
+class UntaggedObject {
  public:
   // The tags field which is a part of the object header uses the following
   // bit fields for storing tags.
@@ -151,7 +151,7 @@
     typedef intptr_t Type;
 
     static constexpr intptr_t kMaxSizeTagInUnitsOfAlignment =
-        ((1 << ObjectLayout::kSizeTagSize) - 1);
+        ((1 << UntaggedObject::kSizeTagSize) - 1);
     static constexpr intptr_t kMaxSizeTag =
         kMaxSizeTagInUnitsOfAlignment * kObjectAlignment;
 
@@ -414,7 +414,7 @@
 
   bool Contains(uword addr) const {
     intptr_t this_size = HeapSize();
-    uword this_addr = ObjectLayout::ToAddr(this);
+    uword this_addr = UntaggedObject::ToAddr(this);
     return (addr >= this_addr) && (addr < (this_addr + this_size));
   }
 
@@ -434,7 +434,7 @@
     // Calculate the first and last raw object pointer fields.
     intptr_t instance_size = HeapSize();
     uword obj_addr = ToAddr(this);
-    uword from = obj_addr + sizeof(ObjectLayout);
+    uword from = obj_addr + sizeof(UntaggedObject);
     uword to = obj_addr + instance_size - kWordSize;
     const auto first = reinterpret_cast<ObjectPtr*>(from);
     const auto last = reinterpret_cast<ObjectPtr*>(to);
@@ -444,7 +444,7 @@
         visitor->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
 
     if (!unboxed_fields_bitmap.IsEmpty()) {
-      intptr_t bit = sizeof(ObjectLayout) / kWordSize;
+      intptr_t bit = sizeof(UntaggedObject) / kWordSize;
       for (ObjectPtr* current = first; current <= last; current++) {
         if (!unboxed_fields_bitmap.Get(bit++)) {
           visitor->VisitPointer(current);
@@ -472,7 +472,7 @@
     // Calculate the first and last raw object pointer fields.
     intptr_t instance_size = HeapSize();
     uword obj_addr = ToAddr(this);
-    uword from = obj_addr + sizeof(ObjectLayout);
+    uword from = obj_addr + sizeof(UntaggedObject);
     uword to = obj_addr + instance_size - kWordSize;
     const auto first = reinterpret_cast<ObjectPtr*>(from);
     const auto last = reinterpret_cast<ObjectPtr*>(to);
@@ -482,7 +482,7 @@
         visitor->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
 
     if (!unboxed_fields_bitmap.IsEmpty()) {
-      intptr_t bit = sizeof(ObjectLayout) / kWordSize;
+      intptr_t bit = sizeof(UntaggedObject) / kWordSize;
       for (ObjectPtr* current = first; current <= last; current++) {
         if (!unboxed_fields_bitmap.Get(bit++)) {
           visitor->V::VisitPointers(current, current);
@@ -509,7 +509,7 @@
     return static_cast<ObjectPtr>(addr + kHeapObjectTag);
   }
 
-  static uword ToAddr(const ObjectLayout* raw_obj) {
+  static uword ToAddr(const UntaggedObject* raw_obj) {
     return reinterpret_cast<uword>(raw_obj);
   }
   static uword ToAddr(const ObjectPtr raw_obj) {
@@ -568,35 +568,6 @@
     }
   }
 
- private:
-  DART_FORCE_INLINE
-  void CheckHeapPointerStore(ObjectPtr value, Thread* thread) {
-    uword source_tags = this->tags_;
-    uword target_tags = value->ptr()->tags_;
-    if (((source_tags >> kBarrierOverlapShift) & target_tags &
-         thread->write_barrier_mask()) != 0) {
-      if (value->IsNewObject()) {
-        // Generational barrier: record when a store creates an
-        // old-and-not-remembered -> new reference.
-        AddToRememberedSet(thread);
-      } else {
-        // Incremental barrier: record when a store creates an
-        // old -> old-and-not-marked reference.
-        ASSERT(value->IsOldObject());
-#if !defined(TARGET_ARCH_IA32)
-        if (ClassIdTag::decode(target_tags) == kInstructionsCid) {
-          // Instruction pages may be non-writable. Defer marking.
-          thread->DeferredMarkingStackAddObject(value);
-          return;
-        }
-#endif
-        if (value->ptr()->TryAcquireMarkBit()) {
-          thread->MarkingStackAddObject(value);
-        }
-      }
-    }
-  }
-
   template <typename type, std::memory_order order = std::memory_order_relaxed>
   void StoreArrayPointer(type const* addr, type value) {
     reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
@@ -614,12 +585,56 @@
     }
   }
 
+  template <typename type, std::memory_order order = std::memory_order_relaxed>
+  type LoadSmi(type const* addr) const {
+    return reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
+        ->load(order);
+  }
+  // Use for storing into an explicitly Smi-typed field of an object
+  // (i.e., both the previous and new value are Smis).
+  template <std::memory_order order = std::memory_order_relaxed>
+  void StoreSmi(SmiPtr const* addr, SmiPtr value) {
+    // Can't use Contains, as array length is initialized through this method.
+    ASSERT(reinterpret_cast<uword>(addr) >= UntaggedObject::ToAddr(this));
+    reinterpret_cast<std::atomic<SmiPtr>*>(const_cast<SmiPtr*>(addr))
+        ->store(value, order);
+  }
+
+ private:
+  DART_FORCE_INLINE
+  void CheckHeapPointerStore(ObjectPtr value, Thread* thread) {
+    uword source_tags = this->tags_;
+    uword target_tags = value->untag()->tags_;
+    if (((source_tags >> kBarrierOverlapShift) & target_tags &
+         thread->write_barrier_mask()) != 0) {
+      if (value->IsNewObject()) {
+        // Generational barrier: record when a store creates an
+        // old-and-not-remembered -> new reference.
+        AddToRememberedSet(thread);
+      } else {
+        // Incremental barrier: record when a store creates an
+        // old -> old-and-not-marked reference.
+        ASSERT(value->IsOldObject());
+#if !defined(TARGET_ARCH_IA32)
+        if (ClassIdTag::decode(target_tags) == kInstructionsCid) {
+          // Instruction pages may be non-writable. Defer marking.
+          thread->DeferredMarkingStackAddObject(value);
+          return;
+        }
+#endif
+        if (value->untag()->TryAcquireMarkBit()) {
+          thread->MarkingStackAddObject(value);
+        }
+      }
+    }
+  }
+
   template <typename type>
   DART_FORCE_INLINE void CheckArrayPointerStore(type const* addr,
                                                 ObjectPtr value,
                                                 Thread* thread) {
     uword source_tags = this->tags_;
-    uword target_tags = value->ptr()->tags_;
+    uword target_tags = value->untag()->tags_;
     if (((source_tags >> kBarrierOverlapShift) & target_tags &
          thread->write_barrier_mask()) != 0) {
       if (value->IsNewObject()) {
@@ -643,33 +658,16 @@
           return;
         }
 #endif
-        if (value->ptr()->TryAcquireMarkBit()) {
+        if (value->untag()->TryAcquireMarkBit()) {
           thread->MarkingStackAddObject(value);
         }
       }
     }
   }
 
- protected:
-  template <typename type, std::memory_order order = std::memory_order_relaxed>
-  type LoadSmi(type const* addr) const {
-    return reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
-        ->load(order);
-  }
-  // Use for storing into an explicitly Smi-typed field of an object
-  // (i.e., both the previous and new value are Smis).
-  template <std::memory_order order = std::memory_order_relaxed>
-  void StoreSmi(SmiPtr const* addr, SmiPtr value) {
-    // Can't use Contains, as array length is initialized through this method.
-    ASSERT(reinterpret_cast<uword>(addr) >= ObjectLayout::ToAddr(this));
-    reinterpret_cast<std::atomic<SmiPtr>*>(const_cast<SmiPtr*>(addr))
-        ->store(value, order);
-  }
-
   friend class StoreBufferUpdateVisitor;  // RememberCard
   void RememberCard(ObjectPtr const* slot);
 
- private:
   friend class Array;
   friend class ByteBuffer;
   friend class CidRewriteVisitor;
@@ -693,7 +691,7 @@
   friend class Mint;
   friend class Object;
   friend class OneByteString;  // StoreSmi
-  friend class InstanceLayout;
+  friend class UntaggedInstance;
   friend class Scavenger;
   template <bool>
   friend class ScavengerVisitorBase;
@@ -717,11 +715,11 @@
   friend class Object;
 
   DISALLOW_ALLOCATION();
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectLayout);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(UntaggedObject);
 };
 
 inline intptr_t ObjectPtr::GetClassId() const {
-  return ptr()->GetClassId();
+  return untag()->GetClassId();
 }
 
 #define POINTER_FIELD(type, name)                                              \
@@ -784,7 +782,7 @@
  protected:                                                                    \
   type name##_;
 
-class ClassLayout : public ObjectLayout {
+class UntaggedClass : public UntaggedObject {
  public:
   enum ClassFinalizedState {
     kAllocated = 0,  // Initial state.
@@ -821,10 +819,6 @@
   POINTER_FIELD(LibraryPtr, library)
   POINTER_FIELD(TypeArgumentsPtr, type_parameters)  // Array of TypeParameter.
   POINTER_FIELD(AbstractTypePtr, super_type)
-  POINTER_FIELD(FunctionPtr,
-                signature_function)  // Associated function for typedef class.
-  POINTER_FIELD(ArrayPtr,
-                constants)  // Canonicalized const instances of this class.
   POINTER_FIELD(TypePtr, declaration_type)  // Declaration type for this class.
   POINTER_FIELD(ArrayPtr,
                 invocation_dispatcher_cache)  // Cache for dispatcher functions.
@@ -834,7 +828,9 @@
                 direct_implementors)                        // Array of Class.
   POINTER_FIELD(GrowableObjectArrayPtr, direct_subclasses)  // Array of Class.
   POINTER_FIELD(ArrayPtr, dependent_code)  // CHA optimized codes.
-  VISIT_TO(ObjectPtr, dependent_code)
+  POINTER_FIELD(ArrayPtr,
+                constants)  // Canonicalized const instances of this class.
+  VISIT_TO(ObjectPtr, constants)
   ObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFullAOT:
@@ -888,16 +884,16 @@
   friend class Instance;
   friend class Isolate;
   friend class Object;
-  friend class InstanceLayout;
-  friend class InstructionsLayout;
-  friend class TypeArgumentsLayout;
+  friend class UntaggedInstance;
+  friend class UntaggedInstructions;
+  friend class UntaggedTypeArguments;
   friend class SnapshotReader;
   friend class InstanceSerializationCluster;
   friend class CidRewriteVisitor;
   friend class Api;
 };
 
-class PatchClassLayout : public ObjectLayout {
+class UntaggedPatchClass : public UntaggedObject {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(PatchClass);
 
@@ -930,7 +926,7 @@
   friend class Function;
 };
 
-class FunctionLayout : public ObjectLayout {
+class UntaggedFunction : public UntaggedObject {
  public:
   // When you add a new kind, please also update the observatory to account
   // for the new string returned by KindToCString().
@@ -946,8 +942,6 @@
   /* an implicit closure (i.e., tear-off) */                                   \
   V(ImplicitClosureFunction)                                                   \
   /* a signature only without actual code */                                   \
-  V(SignatureFunction)                                                         \
-  /* getter functions e.g: get foo() { .. } */                                 \
   V(GetterFunction)                                                            \
   /* setter functions e.g: set foo(..) { .. } */                               \
   V(SetterFunction)                                                            \
@@ -1078,9 +1072,6 @@
     uint64_t bitmap_;
   };
 
-  static constexpr intptr_t kMaxFixedParametersBits = 14;
-  static constexpr intptr_t kMaxOptionalParametersBits = 13;
-
  private:
   friend class Class;
   friend class UnitDeserializationRoots;
@@ -1094,10 +1085,8 @@
   POINTER_FIELD(StringPtr, name)
   POINTER_FIELD(ObjectPtr, owner)  // Class or patch class or mixin class
                                    // where this function is defined.
-  POINTER_FIELD(AbstractTypePtr, result_type)
-  POINTER_FIELD(ArrayPtr, parameter_types)
   POINTER_FIELD(ArrayPtr, parameter_names)
-  POINTER_FIELD(TypeArgumentsPtr, type_parameters)  // Array of TypeParameter.
+  POINTER_FIELD(FunctionTypePtr, signature)
   POINTER_FIELD(ObjectPtr,
                 data)  // Additional data specific to the function kind. See
                        // Function::set_data() for details.
@@ -1137,17 +1126,35 @@
   uint32_t kind_tag_;  // See Function::KindTagBits.
   uint32_t packed_fields_;
 
-  typedef BitField<uint32_t, bool, 0, 1> PackedHasNamedOptionalParameters;
+  // TODO(regis): Split packed_fields_ in 2 uint32_t if max values are too low.
+
+  // Keep in sync with corresponding constants in UntaggedFunctionType.
+  static constexpr intptr_t kMaxOptimizableBits = 1;
+  static constexpr intptr_t kMaxBackgroundOptimizableBits = 1;
+  static constexpr intptr_t kMaxTypeParametersBits = 7;
+  static constexpr intptr_t kMaxHasNamedOptionalParametersBits = 1;
+  static constexpr intptr_t kMaxFixedParametersBits = 10;
+  static constexpr intptr_t kMaxOptionalParametersBits = 10;
+
+  typedef BitField<uint32_t, bool, 0, kMaxOptimizableBits> PackedOptimizable;
   typedef BitField<uint32_t,
                    bool,
-                   PackedHasNamedOptionalParameters::kNextBit,
-                   1>
-      OptimizableBit;
-  typedef BitField<uint32_t, bool, OptimizableBit::kNextBit, 1>
-      BackgroundOptimizableBit;
+                   PackedOptimizable::kNextBit,
+                   kMaxBackgroundOptimizableBits>
+      PackedBackgroundOptimizable;
+  typedef BitField<uint32_t,
+                   uint8_t,
+                   PackedBackgroundOptimizable::kNextBit,
+                   kMaxTypeParametersBits>
+      PackedNumTypeParameters;
+  typedef BitField<uint32_t,
+                   bool,
+                   PackedNumTypeParameters::kNextBit,
+                   kMaxHasNamedOptionalParametersBits>
+      PackedHasNamedOptionalParameters;
   typedef BitField<uint32_t,
                    uint16_t,
-                   BackgroundOptimizableBit::kNextBit,
+                   PackedHasNamedOptionalParameters::kNextBit,
                    kMaxFixedParametersBits>
       PackedNumFixedParameters;
   typedef BitField<uint32_t,
@@ -1156,8 +1163,8 @@
                    kMaxOptionalParametersBits>
       PackedNumOptionalParameters;
   static_assert(PackedNumOptionalParameters::kNextBit <=
-                    kBitsPerWord * sizeof(decltype(packed_fields_)),
-                "FunctionLayout::packed_fields_ bitfields don't align.");
+                    kBitsPerByte * sizeof(decltype(packed_fields_)),
+                "UntaggedFunction::packed_fields_ bitfields don't fit.");
   static_assert(PackedNumOptionalParameters::kNextBit <=
                     compiler::target::kSmiBits,
                 "In-place mask for number of optional parameters cannot fit in "
@@ -1181,7 +1188,7 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 };
 
-class ClosureDataLayout : public ObjectLayout {
+class UntaggedClosureData : public UntaggedObject {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(ClosureData);
 
@@ -1189,7 +1196,6 @@
   POINTER_FIELD(ContextScopePtr, context_scope)
   POINTER_FIELD(FunctionPtr,
                 parent_function)  // Enclosing function of this local function.
-  POINTER_FIELD(TypePtr, signature_type)
   POINTER_FIELD(InstancePtr,
                 closure)  // Closure object for static implicit closures.
   // Instantiate-to-bounds TAV for use when no TAV is provided.
@@ -1201,27 +1207,13 @@
   friend class Function;
 };
 
-class SignatureDataLayout : public ObjectLayout {
- private:
-  RAW_HEAP_OBJECT_IMPLEMENTATION(SignatureData);
-
-  VISIT_FROM(ObjectPtr, parent_function)
-  POINTER_FIELD(FunctionPtr,
-                parent_function);  // Enclosing function of this sig. function.
-  POINTER_FIELD(TypePtr, signature_type)
-  VISIT_TO(ObjectPtr, signature_type)
-  ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
-
-  friend class Function;
-};
-
-class FfiTrampolineDataLayout : public ObjectLayout {
+class UntaggedFfiTrampolineData : public UntaggedObject {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData);
 
   VISIT_FROM(ObjectPtr, signature_type)
   POINTER_FIELD(TypePtr, signature_type)
-  POINTER_FIELD(FunctionPtr, c_signature)
+  POINTER_FIELD(FunctionTypePtr, c_signature)
 
   // Target Dart method for callbacks, otherwise null.
   POINTER_FIELD(FunctionPtr, callback_target)
@@ -1244,7 +1236,7 @@
   uint32_t callback_id_;
 };
 
-class FieldLayout : public ObjectLayout {
+class UntaggedField : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Field);
 
   VISIT_FROM(ObjectPtr, name)
@@ -1315,14 +1307,7 @@
   friend class StoreInstanceFieldInstr;  // For sizeof(guarded_cid_/...)
 };
 
-class alignas(8) ScriptLayout : public ObjectLayout {
- public:
-  enum {
-    kLazyLookupSourceAndLineStartsPos = 0,
-    kLazyLookupSourceAndLineStartsSize = 1,
-  };
-
- private:
+class alignas(8) UntaggedScript : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Script);
 
   VISIT_FROM(ObjectPtr, url)
@@ -1356,13 +1341,23 @@
 
   int32_t line_offset_;
   int32_t col_offset_;
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  int32_t flags_and_max_position_;
 
+ public:
   using LazyLookupSourceAndLineStartsBit =
-      BitField<uint8_t,
+      BitField<decltype(flags_and_max_position_), bool, 0, 1>;
+  using HasCachedMaxPositionBit =
+      BitField<decltype(flags_and_max_position_),
                bool,
-               kLazyLookupSourceAndLineStartsPos,
-               kLazyLookupSourceAndLineStartsSize>;
-  uint8_t flags_;
+               LazyLookupSourceAndLineStartsBit::kNextBit,
+               1>;
+  using CachedMaxPositionBitField = BitField<decltype(flags_and_max_position_),
+                                             intptr_t,
+                                             HasCachedMaxPositionBit::kNextBit>;
+
+ private:
+#endif
 
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   int64_t load_timestamp_;
@@ -1373,7 +1368,7 @@
 #endif
 };
 
-class LibraryLayout : public ObjectLayout {
+class UntaggedLibrary : public UntaggedObject {
   enum LibraryState {
     kAllocated,       // Initial state.
     kLoadRequested,   // Compiler or script requested load of library.
@@ -1457,7 +1452,7 @@
   friend class Isolate;
 };
 
-class NamespaceLayout : public ObjectLayout {
+class UntaggedNamespace : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Namespace);
 
   VISIT_FROM(ObjectPtr, target)
@@ -1469,7 +1464,7 @@
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
-class KernelProgramInfoLayout : public ObjectLayout {
+class UntaggedKernelProgramInfo : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(KernelProgramInfo);
 
   VISIT_FROM(ObjectPtr, string_offsets)
@@ -1495,7 +1490,7 @@
   }
 };
 
-class WeakSerializationReferenceLayout : public ObjectLayout {
+class UntaggedWeakSerializationReference : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(WeakSerializationReference);
 
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -1508,7 +1503,7 @@
 #endif
 };
 
-class CodeLayout : public ObjectLayout {
+class UntaggedCode : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Code);
 
   // When in the precompiled runtime, there is no disabling of Code objects
@@ -1624,7 +1619,7 @@
   friend class CallSiteResetter;
 };
 
-class ObjectPoolLayout : public ObjectLayout {
+class UntaggedObjectPool : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ObjectPool);
 
   intptr_t length_;
@@ -1647,9 +1642,11 @@
 
   friend class Object;
   friend class CodeSerializationCluster;
+  friend class UnitSerializationRoots;
+  friend class UnitDeserializationRoots;
 };
 
-class InstructionsLayout : public ObjectLayout {
+class UntaggedInstructions : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Instructions);
   VISIT_NOTHING();
 
@@ -1665,8 +1662,8 @@
   // is not allowed to create handles.
   static bool ContainsPC(const InstructionsPtr raw_instr, uword pc);
 
-  friend class CodeLayout;
-  friend class FunctionLayout;
+  friend class UntaggedCode;
+  friend class UntaggedFunction;
   friend class Code;
   friend class StackFrame;
   template <bool>
@@ -1682,7 +1679,7 @@
 // interface, to provide memory accounting for the bare instruction payloads
 // we serialize, since they are no longer part of RawInstructions objects,
 // and to avoid special casing bare instructions payload Images in the GC.
-class InstructionsSectionLayout : public ObjectLayout {
+class UntaggedInstructionsSection : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection);
   VISIT_NOTHING();
 
@@ -1703,7 +1700,7 @@
   friend class Image;
 };
 
-class PcDescriptorsLayout : public ObjectLayout {
+class UntaggedPcDescriptors : public UntaggedObject {
  public:
 // The macro argument V is passed two arguments, the raw name of the enum value
 // and the initialization expression used within the enum definition.  The uses
@@ -1801,7 +1798,7 @@
 
 // CodeSourceMap encodes a mapping from code PC ranges to source token
 // positions and the stack of inlined functions.
-class CodeSourceMapLayout : public ObjectLayout {
+class UntaggedCodeSourceMap : public UntaggedObject {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(CodeSourceMap);
   VISIT_NOTHING();
@@ -1821,7 +1818,7 @@
 // RawCompressedStackMaps is a compressed representation of the stack maps
 // for certain PC offsets into a set of instructions, where a stack map is a bit
 // map that marks each live object index starting from the base of the frame.
-class CompressedStackMapsLayout : public ObjectLayout {
+class UntaggedCompressedStackMaps : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(CompressedStackMaps);
   VISIT_NOTHING();
 
@@ -1894,7 +1891,7 @@
   friend class StackMapEntry;
 };
 
-class LocalVarDescriptorsLayout : public ObjectLayout {
+class UntaggedLocalVarDescriptors : public UntaggedObject {
  public:
   enum VarInfoKind {
     kStackVar = 1,
@@ -1921,9 +1918,12 @@
   struct VarInfo {
     int32_t index_kind = 0;  // Bitfield for slot index on stack or in context,
                              // and Entry kind of type VarInfoKind.
-    TokenPosition declaration_pos;  // Token position of declaration.
-    TokenPosition begin_pos;        // Token position of scope start.
-    TokenPosition end_pos;          // Token position of scope end.
+    TokenPosition declaration_pos =
+        TokenPosition::kNoSource;  // Token position of declaration.
+    TokenPosition begin_pos =
+        TokenPosition::kNoSource;  // Token position of scope start.
+    TokenPosition end_pos =
+        TokenPosition::kNoSource;   // Token position of scope end.
     int16_t scope_id;               // Scope to which the variable belongs.
 
     VarInfoKind kind() const {
@@ -1961,7 +1961,7 @@
   friend class Object;
 };
 
-class ExceptionHandlersLayout : public ObjectLayout {
+class UntaggedExceptionHandlers : public UntaggedObject {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(ExceptionHandlers);
 
@@ -1985,7 +1985,7 @@
   friend class Object;
 };
 
-class ContextLayout : public ObjectLayout {
+class UntaggedContext : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Context);
 
   int32_t num_variables_;
@@ -2000,7 +2000,7 @@
   friend class SnapshotReader;
 };
 
-class ContextScopeLayout : public ObjectLayout {
+class UntaggedContextScope : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ContextScope);
 
   // TODO(iposva): Switch to conventional enum offset based structure to avoid
@@ -2046,11 +2046,11 @@
   }
 
   friend class Object;
-  friend class ClosureDataLayout;
+  friend class UntaggedClosureData;
   friend class SnapshotReader;
 };
 
-class SingleTargetCacheLayout : public ObjectLayout {
+class UntaggedSingleTargetCache : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(SingleTargetCache);
   VISIT_FROM(ObjectPtr, target)
   POINTER_FIELD(CodePtr, target)
@@ -2060,7 +2060,7 @@
   ClassIdTagType upper_limit_;
 };
 
-class MonomorphicSmiableCallLayout : public ObjectLayout {
+class UntaggedMonomorphicSmiableCall : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(MonomorphicSmiableCall);
   VISIT_FROM(ObjectPtr, target)
   POINTER_FIELD(CodePtr,
@@ -2072,7 +2072,7 @@
 };
 
 // Abstract base class for RawICData/RawMegamorphicCache
-class CallSiteDataLayout : public ObjectLayout {
+class UntaggedCallSiteData : public UntaggedObject {
  protected:
   POINTER_FIELD(StringPtr, target_name);  // Name of target function.
   // arg_descriptor in RawICData and in RawMegamorphicCache should be
@@ -2082,7 +2082,7 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(CallSiteData)
 };
 
-class UnlinkedCallLayout : public CallSiteDataLayout {
+class UntaggedUnlinkedCall : public UntaggedCallSiteData {
   RAW_HEAP_OBJECT_IMPLEMENTATION(UnlinkedCall);
   VISIT_FROM(ObjectPtr, target_name)
   VISIT_TO(ObjectPtr, args_descriptor)
@@ -2091,7 +2091,7 @@
   bool can_patch_to_monomorphic_;
 };
 
-class ICDataLayout : public CallSiteDataLayout {
+class UntaggedICData : public UntaggedCallSiteData {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
   VISIT_FROM(ObjectPtr, target_name)
   POINTER_FIELD(ArrayPtr, entries)  // Contains class-ids, target and count.
@@ -2120,7 +2120,7 @@
   uint32_t state_bits_;  // Number of arguments tested in IC, deopt reasons.
 };
 
-class MegamorphicCacheLayout : public CallSiteDataLayout {
+class UntaggedMegamorphicCache : public UntaggedCallSiteData {
   RAW_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache);
 
   VISIT_FROM(ObjectPtr, target_name)
@@ -2132,7 +2132,7 @@
   int32_t filled_entry_count_;
 };
 
-class SubtypeTestCacheLayout : public ObjectLayout {
+class UntaggedSubtypeTestCache : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(SubtypeTestCache);
 
   VISIT_FROM(ObjectPtr, cache)
@@ -2140,7 +2140,7 @@
   VISIT_TO(ObjectPtr, cache)
 };
 
-class LoadingUnitLayout : public ObjectLayout {
+class UntaggedLoadingUnit : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LoadingUnit);
 
   VISIT_FROM(ObjectPtr, parent)
@@ -2152,11 +2152,11 @@
   bool loaded_;
 };
 
-class ErrorLayout : public ObjectLayout {
+class UntaggedError : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Error);
 };
 
-class ApiErrorLayout : public ErrorLayout {
+class UntaggedApiError : public UntaggedError {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ApiError);
 
   VISIT_FROM(ObjectPtr, message)
@@ -2164,7 +2164,7 @@
   VISIT_TO(ObjectPtr, message)
 };
 
-class LanguageErrorLayout : public ErrorLayout {
+class UntaggedLanguageError : public UntaggedError {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LanguageError);
 
   VISIT_FROM(ObjectPtr, previous_error)
@@ -2181,7 +2181,7 @@
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
-class UnhandledExceptionLayout : public ErrorLayout {
+class UntaggedUnhandledException : public UntaggedError {
   RAW_HEAP_OBJECT_IMPLEMENTATION(UnhandledException);
 
   VISIT_FROM(ObjectPtr, exception)
@@ -2191,7 +2191,7 @@
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
-class UnwindErrorLayout : public ErrorLayout {
+class UntaggedUnwindError : public UntaggedError {
   RAW_HEAP_OBJECT_IMPLEMENTATION(UnwindError);
 
   VISIT_FROM(ObjectPtr, message)
@@ -2200,11 +2200,11 @@
   bool is_user_initiated_;
 };
 
-class InstanceLayout : public ObjectLayout {
+class UntaggedInstance : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Instance);
 };
 
-class LibraryPrefixLayout : public InstanceLayout {
+class UntaggedLibraryPrefix : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix);
 
   VISIT_FROM(ObjectPtr, name)
@@ -2233,7 +2233,7 @@
   bool is_loaded_;
 };
 
-class TypeArgumentsLayout : public InstanceLayout {
+class UntaggedTypeArguments : public UntaggedInstance {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeArguments);
 
@@ -2254,7 +2254,7 @@
   friend class SnapshotReader;
 };
 
-class AbstractTypeLayout : public InstanceLayout {
+class UntaggedAbstractType : public UntaggedInstance {
  public:
   enum TypeState {
     kAllocated,                // Initial state.
@@ -2280,7 +2280,7 @@
   friend class StubCode;
 };
 
-class TypeLayout : public AbstractTypeLayout {
+class UntaggedType : public UntaggedAbstractType {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(Type);
 
@@ -2288,22 +2288,70 @@
   POINTER_FIELD(SmiPtr, type_class_id)
   POINTER_FIELD(TypeArgumentsPtr, arguments)
   POINTER_FIELD(SmiPtr, hash)
-  // This type object represents a function type if its signature field is a
-  // non-null function object.
-  POINTER_FIELD(FunctionPtr,
-                signature)  // If not null, this type is a function type.
-  VISIT_TO(ObjectPtr, signature)
-  TokenPosition token_pos_;
-  int8_t type_state_;
-  int8_t nullability_;
+  VISIT_TO(ObjectPtr, hash)
+  uint8_t type_state_;
+  uint8_t nullability_;
 
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 
   friend class CidRewriteVisitor;
-  friend class TypeArgumentsLayout;
+  friend class UntaggedTypeArguments;
 };
 
-class TypeRefLayout : public AbstractTypeLayout {
+class UntaggedFunctionType : public UntaggedAbstractType {
+ private:
+  RAW_HEAP_OBJECT_IMPLEMENTATION(FunctionType);
+
+  VISIT_FROM(ObjectPtr, type_test_stub)
+  POINTER_FIELD(TypeArgumentsPtr, type_parameters)  // Array of TypeParameter.
+  POINTER_FIELD(AbstractTypePtr, result_type)
+  POINTER_FIELD(ArrayPtr, parameter_types)
+  POINTER_FIELD(ArrayPtr, parameter_names);
+  POINTER_FIELD(SmiPtr, hash)
+  VISIT_TO(ObjectPtr, hash)
+  uint32_t packed_fields_;  // Number of parent type args and own parameters.
+  uint8_t type_state_;
+  uint8_t nullability_;
+
+  // Keep in sync with corresponding constants in UntaggedFunction.
+  static constexpr intptr_t kMaxParentTypeArgumentsBits = 8;
+  static constexpr intptr_t kMaxHasNamedOptionalParametersBits = 1;
+  static constexpr intptr_t kMaxImplicitParametersBits = 1;
+  static constexpr intptr_t kMaxFixedParametersBits = 10;
+  static constexpr intptr_t kMaxOptionalParametersBits = 10;
+
+  typedef BitField<uint32_t, uint8_t, 0, kMaxParentTypeArgumentsBits>
+      PackedNumParentTypeArguments;
+  typedef BitField<uint32_t,
+                   bool,
+                   PackedNumParentTypeArguments::kNextBit,
+                   kMaxHasNamedOptionalParametersBits>
+      PackedHasNamedOptionalParameters;
+  typedef BitField<uint32_t,
+                   uint8_t,
+                   PackedHasNamedOptionalParameters::kNextBit,
+                   kMaxImplicitParametersBits>
+      PackedNumImplicitParameters;
+  typedef BitField<uint32_t,
+                   uint16_t,
+                   PackedNumImplicitParameters::kNextBit,
+                   kMaxFixedParametersBits>
+      PackedNumFixedParameters;
+  typedef BitField<uint32_t,
+                   uint16_t,
+                   PackedNumFixedParameters::kNextBit,
+                   kMaxOptionalParametersBits>
+      PackedNumOptionalParameters;
+  static_assert(PackedNumOptionalParameters::kNextBit <=
+                    kBitsPerByte * sizeof(decltype(packed_fields_)),
+                "UntaggedFunctionType::packed_fields_ bitfields don't fit.");
+
+  ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
+
+  friend class Function;
+};
+
+class UntaggedTypeRef : public UntaggedAbstractType {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeRef);
 
@@ -2313,7 +2361,7 @@
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
-class TypeParameterLayout : public AbstractTypeLayout {
+class UntaggedTypeParameter : public UntaggedAbstractType {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameter);
 
@@ -2327,21 +2375,22 @@
   // TODO(dartbug.com/43901): Once a separate TypeParameters class has been
   // added, move these there and remove them from TypeParameter objects.
   POINTER_FIELD(AbstractTypePtr, default_argument)
-  POINTER_FIELD(FunctionPtr, parameterized_function)
-  VISIT_TO(ObjectPtr, parameterized_function)
-  ClassIdTagType parameterized_class_id_;
-  TokenPosition token_pos_;
-  int16_t index_;
+  VISIT_TO(ObjectPtr, default_argument)
+  ClassIdTagType parameterized_class_id_;  // Or kFunctionCid for function tp.
+  // TODO(regis): Can we use uint8_t twice below? Or keep uint16_t?
+  // Warning: BuildTypeParameterTypeTestStub assumes uint16_t.
+  uint16_t base_;  // Number of enclosing function type parameters.
+  uint16_t index_;
   uint8_t flags_;
-  int8_t nullability_;
+  uint8_t nullability_;
 
  public:
-  using FinalizedBit = BitField<decltype(flags_), bool, 0, 1>;
+  using BeingFinalizedBit = BitField<decltype(flags_), bool, 0, 1>;
+  using FinalizedBit =
+      BitField<decltype(flags_), bool, BeingFinalizedBit::kNextBit, 1>;
   using GenericCovariantImplBit =
       BitField<decltype(flags_), bool, FinalizedBit::kNextBit, 1>;
-  using DeclarationBit =
-      BitField<decltype(flags_), bool, GenericCovariantImplBit::kNextBit, 1>;
-  static constexpr intptr_t kFlagsBitSize = DeclarationBit::kNextBit;
+  static constexpr intptr_t kFlagsBitSize = GenericCovariantImplBit::kNextBit;
 
  private:
   ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
@@ -2349,7 +2398,7 @@
   friend class CidRewriteVisitor;
 };
 
-class ClosureLayout : public InstanceLayout {
+class UntaggedClosure : public UntaggedInstance {
  private:
   RAW_HEAP_OBJECT_IMPLEMENTATION(Closure);
 
@@ -2394,19 +2443,19 @@
   // any type arguments passed directly (or NSM will be invoked instead).
 };
 
-class NumberLayout : public InstanceLayout {
+class UntaggedNumber : public UntaggedInstance {
   RAW_OBJECT_IMPLEMENTATION(Number);
 };
 
-class IntegerLayout : public NumberLayout {
+class UntaggedInteger : public UntaggedNumber {
   RAW_OBJECT_IMPLEMENTATION(Integer);
 };
 
-class SmiLayout : public IntegerLayout {
+class UntaggedSmi : public UntaggedInteger {
   RAW_OBJECT_IMPLEMENTATION(Smi);
 };
 
-class MintLayout : public IntegerLayout {
+class UntaggedMint : public UntaggedInteger {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Mint);
   VISIT_NOTHING();
 
@@ -2417,9 +2466,9 @@
   friend class Integer;
   friend class SnapshotReader;
 };
-COMPILE_ASSERT(sizeof(MintLayout) == 16);
+COMPILE_ASSERT(sizeof(UntaggedMint) == 16);
 
-class DoubleLayout : public NumberLayout {
+class UntaggedDouble : public UntaggedNumber {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Double);
   VISIT_NOTHING();
 
@@ -2429,9 +2478,9 @@
   friend class SnapshotReader;
   friend class Class;
 };
-COMPILE_ASSERT(sizeof(DoubleLayout) == 16);
+COMPILE_ASSERT(sizeof(UntaggedDouble) == 16);
 
-class StringLayout : public InstanceLayout {
+class UntaggedString : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(String);
 
  protected:
@@ -2454,7 +2503,7 @@
   friend class ImageWriter;
 };
 
-class OneByteStringLayout : public StringLayout {
+class UntaggedOneByteString : public UntaggedString {
   RAW_HEAP_OBJECT_IMPLEMENTATION(OneByteString);
   VISIT_NOTHING();
 
@@ -2468,7 +2517,7 @@
   friend class String;
 };
 
-class TwoByteStringLayout : public StringLayout {
+class UntaggedTwoByteString : public UntaggedString {
   RAW_HEAP_OBJECT_IMPLEMENTATION(TwoByteString);
   VISIT_NOTHING();
 
@@ -2486,7 +2535,7 @@
 //
 // TypedData extends this with a length field, while Pointer extends this with
 // TypeArguments field.
-class PointerBaseLayout : public InstanceLayout {
+class UntaggedPointerBase : public UntaggedInstance {
  protected:
   // The contents of [data_] depends on what concrete subclass is used:
   //
@@ -2506,23 +2555,23 @@
 };
 
 // Abstract base class for RawTypedData/RawExternalTypedData/RawTypedDataView.
-class TypedDataBaseLayout : public PointerBaseLayout {
+class UntaggedTypedDataBase : public UntaggedPointerBase {
  protected:
   // The length of the view in element sizes (obtainable via
   // [TypedDataBase::ElementSizeInBytes]).
   SMI_FIELD(SmiPtr, length);
 
  private:
-  friend class TypedDataViewLayout;
+  friend class UntaggedTypedDataView;
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataBase);
 };
 
-class TypedDataLayout : public TypedDataBaseLayout {
+class UntaggedTypedData : public UntaggedTypedDataBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypedData);
 
  public:
   static intptr_t payload_offset() {
-    return OFFSET_OF_RETURNED_VALUE(TypedDataLayout, internal_data);
+    return OFFSET_OF_RETURNED_VALUE(UntaggedTypedData, internal_data);
   }
 
   // Recompute [data_] pointer to internal data.
@@ -2553,19 +2602,19 @@
   friend class ObjectPool;
   friend class ObjectPoolDeserializationCluster;
   friend class ObjectPoolSerializationCluster;
-  friend class ObjectPoolLayout;
+  friend class UntaggedObjectPool;
   friend class SnapshotReader;
 };
 
 // All _*ArrayView/_ByteDataView classes share the same layout.
-class TypedDataViewLayout : public TypedDataBaseLayout {
+class UntaggedTypedDataView : public UntaggedTypedDataBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataView);
 
  public:
   // Recompute [data_] based on internal/external [typed_data_].
   void RecomputeDataField() {
     const intptr_t offset_in_bytes = RawSmiValue(offset_in_bytes_);
-    uint8_t* payload = typed_data()->ptr()->data_;
+    uint8_t* payload = typed_data()->untag()->data_;
     data_ = payload + offset_in_bytes;
   }
 
@@ -2577,13 +2626,14 @@
   // fields don't need to be valid - only it's address.
   void RecomputeDataFieldForInternalTypedData() {
     const intptr_t offset_in_bytes = RawSmiValue(offset_in_bytes_);
-    uint8_t* payload = reinterpret_cast<uint8_t*>(
-        ObjectLayout::ToAddr(typed_data()) + TypedDataLayout::payload_offset());
+    uint8_t* payload =
+        reinterpret_cast<uint8_t*>(UntaggedObject::ToAddr(typed_data()) +
+                                   UntaggedTypedData::payload_offset());
     data_ = payload + offset_in_bytes;
   }
 
   void ValidateInnerPointer() {
-    if (typed_data()->ptr()->GetClassId() == kNullCid) {
+    if (typed_data()->untag()->GetClassId() == kNullCid) {
       // The view object must have gotten just initialized.
       if (data_ != nullptr || RawSmiValue(offset_in_bytes_) != 0 ||
           RawSmiValue(length_) != 0) {
@@ -2591,7 +2641,7 @@
       }
     } else {
       const intptr_t offset_in_bytes = RawSmiValue(offset_in_bytes_);
-      uint8_t* payload = typed_data()->ptr()->data_;
+      uint8_t* payload = typed_data()->untag()->data_;
       if ((payload + offset_in_bytes) != data_) {
         FATAL("RawTypedDataView has invalid inner pointer.");
       }
@@ -2609,14 +2659,14 @@
   friend class Object;
   friend class ObjectPoolDeserializationCluster;
   friend class ObjectPoolSerializationCluster;
-  friend class ObjectPoolLayout;
+  friend class UntaggedObjectPool;
   friend class GCCompactor;
   template <bool>
   friend class ScavengerVisitorBase;
   friend class SnapshotReader;
 };
 
-class ExternalOneByteStringLayout : public StringLayout {
+class UntaggedExternalOneByteString : public UntaggedString {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalOneByteString);
 
   const uint8_t* external_data_;
@@ -2625,7 +2675,7 @@
   friend class String;
 };
 
-class ExternalTwoByteStringLayout : public StringLayout {
+class UntaggedExternalTwoByteString : public UntaggedString {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalTwoByteString);
 
   const uint16_t* external_data_;
@@ -2634,7 +2684,7 @@
   friend class String;
 };
 
-class BoolLayout : public InstanceLayout {
+class UntaggedBool : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Bool);
   VISIT_NOTHING();
 
@@ -2643,7 +2693,7 @@
   friend class Object;
 };
 
-class ArrayLayout : public InstanceLayout {
+class UntaggedArray : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Array);
 
   VISIT_FROM(RawCompressed, type_arguments)
@@ -2658,12 +2708,12 @@
   friend class CodeSerializationCluster;
   friend class CodeDeserializationCluster;
   friend class Deserializer;
-  friend class CodeLayout;
-  friend class ImmutableArrayLayout;
+  friend class UntaggedCode;
+  friend class UntaggedImmutableArray;
   friend class SnapshotReader;
   friend class GrowableObjectArray;
   friend class LinkedHashMap;
-  friend class LinkedHashMapLayout;
+  friend class UntaggedLinkedHashMap;
   friend class Object;
   friend class ICData;            // For high performance access.
   friend class SubtypeTestCache;  // For high performance access.
@@ -2672,13 +2722,13 @@
   friend class OldPage;
 };
 
-class ImmutableArrayLayout : public ArrayLayout {
+class UntaggedImmutableArray : public UntaggedArray {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray);
 
   friend class SnapshotReader;
 };
 
-class GrowableObjectArrayLayout : public InstanceLayout {
+class UntaggedGrowableObjectArray : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray);
 
   VISIT_FROM(RawCompressed, type_arguments)
@@ -2692,7 +2742,7 @@
   friend class ReversePc;
 };
 
-class LinkedHashMapLayout : public InstanceLayout {
+class UntaggedLinkedHashMap : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap);
 
   VISIT_FROM(RawCompressed, type_arguments)
@@ -2707,7 +2757,7 @@
   friend class SnapshotReader;
 };
 
-class Float32x4Layout : public InstanceLayout {
+class UntaggedFloat32x4 : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Float32x4);
   VISIT_NOTHING();
 
@@ -2722,9 +2772,9 @@
   float z() const { return value_[2]; }
   float w() const { return value_[3]; }
 };
-COMPILE_ASSERT(sizeof(Float32x4Layout) == 24);
+COMPILE_ASSERT(sizeof(UntaggedFloat32x4) == 24);
 
-class Int32x4Layout : public InstanceLayout {
+class UntaggedInt32x4 : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Int32x4);
   VISIT_NOTHING();
 
@@ -2738,9 +2788,9 @@
   int32_t z() const { return value_[2]; }
   int32_t w() const { return value_[3]; }
 };
-COMPILE_ASSERT(sizeof(Int32x4Layout) == 24);
+COMPILE_ASSERT(sizeof(UntaggedInt32x4) == 24);
 
-class Float64x2Layout : public InstanceLayout {
+class UntaggedFloat64x2 : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Float64x2);
   VISIT_NOTHING();
 
@@ -2753,7 +2803,7 @@
   double x() const { return value_[0]; }
   double y() const { return value_[1]; }
 };
-COMPILE_ASSERT(sizeof(Float64x2Layout) == 24);
+COMPILE_ASSERT(sizeof(UntaggedFloat64x2) == 24);
 
 // Define an aliases for intptr_t.
 #if defined(ARCH_IS_32_BIT)
@@ -2766,7 +2816,7 @@
 #error Architecture is not 32-bit or 64-bit.
 #endif  // ARCH_IS_32_BIT
 
-class ExternalTypedDataLayout : public TypedDataBaseLayout {
+class UntaggedExternalTypedData : public UntaggedTypedDataBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalTypedData);
 
  protected:
@@ -2774,7 +2824,7 @@
   VISIT_TO(RawCompressed, length)
 };
 
-class PointerLayout : public PointerBaseLayout {
+class UntaggedPointer : public UntaggedPointerBase {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Pointer);
 
   VISIT_FROM(RawCompressed, type_arguments)
@@ -2784,7 +2834,7 @@
   friend class Pointer;
 };
 
-class DynamicLibraryLayout : public InstanceLayout {
+class UntaggedDynamicLibrary : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(DynamicLibrary);
   VISIT_NOTHING();
   void* handle_;
@@ -2793,13 +2843,13 @@
 };
 
 // VM implementations of the basic types in the isolate.
-class alignas(8) CapabilityLayout : public InstanceLayout {
+class alignas(8) UntaggedCapability : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Capability);
   VISIT_NOTHING();
   uint64_t id_;
 };
 
-class alignas(8) SendPortLayout : public InstanceLayout {
+class alignas(8) UntaggedSendPort : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(SendPort);
   VISIT_NOTHING();
   Dart_Port id_;
@@ -2808,7 +2858,7 @@
   friend class ReceivePort;
 };
 
-class ReceivePortLayout : public InstanceLayout {
+class UntaggedReceivePort : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ReceivePort);
 
   VISIT_FROM(ObjectPtr, send_port)
@@ -2823,7 +2873,7 @@
 #endif  // !defined(PRODUCT)
 };
 
-class TransferableTypedDataLayout : public InstanceLayout {
+class UntaggedTransferableTypedData : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(TransferableTypedData);
   VISIT_NOTHING();
 };
@@ -2832,7 +2882,7 @@
 // Currently we don't have any interface that this object is supposed
 // to implement so we just support the 'toString' method which
 // converts the stack trace into a string.
-class StackTraceLayout : public InstanceLayout {
+class UntaggedStackTrace : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(StackTrace);
 
   VISIT_FROM(ObjectPtr, async_link)
@@ -2853,7 +2903,7 @@
 };
 
 // VM type for capturing JS regular expressions.
-class RegExpLayout : public InstanceLayout {
+class UntaggedRegExp : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(RegExp);
 
   VISIT_FROM(ObjectPtr, num_bracket_expressions)
@@ -2885,7 +2935,7 @@
   int8_t type_flags_;
 };
 
-class WeakPropertyLayout : public InstanceLayout {
+class UntaggedWeakProperty : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(WeakProperty);
 
   VISIT_FROM(ObjectPtr, key)
@@ -2908,7 +2958,7 @@
 
 // MirrorReferences are used by mirrors to hold reflectees that are VM
 // internal objects, such as libraries, classes, functions or types.
-class MirrorReferenceLayout : public InstanceLayout {
+class UntaggedMirrorReference : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(MirrorReference);
 
   VISIT_FROM(ObjectPtr, referent)
@@ -2917,7 +2967,7 @@
 };
 
 // UserTag are used by the profiler to track Dart script state.
-class UserTagLayout : public InstanceLayout {
+class UntaggedUserTag : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(UserTag);
 
   VISIT_FROM(ObjectPtr, label)
@@ -2934,7 +2984,7 @@
   uword tag() const { return tag_; }
 };
 
-class FutureOrLayout : public InstanceLayout {
+class UntaggedFutureOr : public UntaggedInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(FutureOr);
 
   VISIT_FROM(RawCompressed, type_arguments)
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index 103611e..16b25bd 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -20,7 +20,6 @@
   F(Class, library_)                                                           \
   F(Class, type_parameters_)                                                   \
   F(Class, super_type_)                                                        \
-  F(Class, signature_function_)                                                \
   F(Class, constants_)                                                         \
   F(Class, declaration_type_)                                                  \
   F(Class, invocation_dispatcher_cache_)                                       \
@@ -34,19 +33,12 @@
   F(PatchClass, library_kernel_data_)                                          \
   F(Function, name_)                                                           \
   F(Function, owner_)                                                          \
-  F(Function, result_type_)                                                    \
-  F(Function, parameter_types_)                                                \
-  F(Function, parameter_names_)                                                \
-  F(Function, type_parameters_)                                                \
   F(Function, data_)                                                           \
   F(Function, ic_data_array_)                                                  \
   F(Function, code_)                                                           \
   F(ClosureData, context_scope_)                                               \
   F(ClosureData, parent_function_)                                             \
-  F(ClosureData, signature_type_)                                              \
   F(ClosureData, closure_)                                                     \
-  F(SignatureData, parent_function_)                                           \
-  F(SignatureData, signature_type_)                                            \
   F(Field, name_)                                                              \
   F(Field, owner_)                                                             \
   F(Field, type_)                                                              \
@@ -137,14 +129,18 @@
   F(Type, type_class_id_)                                                      \
   F(Type, arguments_)                                                          \
   F(Type, hash_)                                                               \
-  F(Type, signature_)                                                          \
+  F(FunctionType, type_test_stub_)                                             \
+  F(FunctionType, hash_)                                                       \
+  F(FunctionType, result_type_)                                                \
+  F(FunctionType, parameter_types_)                                            \
+  F(FunctionType, parameter_names_)                                            \
+  F(FunctionType, type_parameters_)                                            \
   F(TypeRef, type_test_stub_)                                                  \
   F(TypeRef, type_)                                                            \
   F(TypeParameter, type_test_stub_)                                            \
   F(TypeParameter, name_)                                                      \
   F(TypeParameter, hash_)                                                      \
   F(TypeParameter, bound_)                                                     \
-  F(TypeParameter, parameterized_function_)                                    \
   F(Closure, instantiator_type_arguments_)                                     \
   F(Closure, function_type_arguments_)                                         \
   F(Closure, delayed_type_arguments_)                                          \
@@ -188,7 +184,6 @@
   F(PointerBase, data_)                                                        \
   F(Pointer, type_arguments_)                                                  \
   F(DynamicLibrary, handle_)                                                   \
-  F(FfiTrampolineData, signature_type_)                                        \
   F(FfiTrampolineData, c_signature_)                                           \
   F(FfiTrampolineData, callback_target_)                                       \
   F(FfiTrampolineData, callback_exceptional_return_)                           \
@@ -228,7 +223,7 @@
 
 #define DEFINE_OFFSETS_TABLE_ENTRY(class_name, field_name)                     \
   {class_name::kClassId, #field_name,                                          \
-   OFFSET_OF(class_name##Layout, field_name)},
+   OFFSET_OF(Untagged##class_name, field_name)},
 
 // clang-format off
 OffsetsTable::OffsetsTableEntry OffsetsTable::offsets_table[] = {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 853c1cac..230bde3 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -24,7 +24,7 @@
     " port after it exceeds certain size in bytes.");
 
 #define OFFSET_OF_FROM(obj)                                                    \
-  obj.raw()->from() - reinterpret_cast<ObjectPtr*>(obj.raw()->ptr())
+  obj.ptr()->from() - reinterpret_cast<ObjectPtr*>(obj.ptr()->untag())
 
 // TODO(18854): Need to assert No GC can happen here, even though
 // allocations may happen.
@@ -32,7 +32,7 @@
   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()->raw());   \
+    object.StorePointer(((from) + i), reader->PassiveObjectHandle()->ptr());   \
   }
 
 ClassPtr Class::ReadFrom(SnapshotReader* reader,
@@ -44,13 +44,13 @@
 
   Class& cls = Class::ZoneHandle(reader->zone(), Class::null());
   cls = reader->ReadClassId(object_id);
-  return cls.raw();
+  return cls.ptr();
 }
 
-void ClassLayout::WriteTo(SnapshotWriter* writer,
-                          intptr_t object_id,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
+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.
@@ -83,11 +83,10 @@
 
   // Allocate type object.
   Type& type = Type::ZoneHandle(reader->zone(), Type::New());
-  bool is_canonical = ObjectLayout::IsCanonical(tags);
+  bool is_canonical = UntaggedObject::IsCanonical(tags);
   reader->AddBackRef(object_id, &type, kIsDeserialized);
 
   // Set all non object fields.
-  type.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
   const uint8_t combined = reader->Read<uint8_t>();
   type.set_type_state(combined >> 4);
   type.set_nullability(static_cast<Nullability>(combined & 0xf));
@@ -96,8 +95,8 @@
   reader->EnqueueTypePostprocessing(type);
 
   // Set all the object fields.
-  READ_OBJECT_FIELDS(type, type.raw()->ptr()->from(), type.raw()->ptr()->to(),
-                     as_reference);
+  READ_OBJECT_FIELDS(type, type.ptr()->untag()->from(),
+                     type.ptr()->untag()->to(), as_reference);
 
   // Read in the type class.
   (*reader->ClassHandle()) =
@@ -113,25 +112,18 @@
     type ^= type.Canonicalize(Thread::Current(), nullptr);
   }
 
-  return type.raw();
+  return type.ptr();
 }
 
-void TypeLayout::WriteTo(SnapshotWriter* writer,
-                         intptr_t object_id,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
+void UntaggedType::WriteTo(SnapshotWriter* writer,
+                           intptr_t object_id,
+                           Snapshot::Kind kind,
+                           bool as_reference) {
   ASSERT(writer != NULL);
 
-  if (signature() != Function::null()) {
-    writer->SetWriteException(Exceptions::kArgument,
-                              "Illegal argument in isolate message"
-                              " : (function types are not supported yet)");
-    UNREACHABLE();
-  }
-
   // Only resolved and finalized types should be written to a snapshot.
-  ASSERT((type_state_ == TypeLayout::kFinalizedInstantiated) ||
-         (type_state_ == TypeLayout::kFinalizedUninstantiated));
+  ASSERT((type_state_ == UntaggedType::kFinalizedInstantiated) ||
+         (type_state_ == UntaggedType::kFinalizedUninstantiated));
   ASSERT(type_class_id() != Object::null());
 
   // Write out the serialization header value for this object.
@@ -149,7 +141,7 @@
   // Lookup the type class.
   SmiPtr raw_type_class_id = Smi::RawCast(type_class_id());
   ClassPtr type_class =
-      writer->isolate()->class_table()->At(Smi::Value(raw_type_class_id));
+      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.
@@ -160,7 +152,6 @@
   writer->Write<bool>(typeclass_is_in_fullsnapshot);
 
   // Write out all the non object pointer fields.
-  writer->Write<int32_t>(token_pos_.SnapshotEncode());
   const uint8_t combined = (type_state_ << 4) | nullability_;
   ASSERT(type_state_ == (combined >> 4));
   ASSERT(nullability_ == (combined & 0xf));
@@ -190,21 +181,21 @@
   reader->EnqueueTypePostprocessing(type_ref);
 
   // Set all the object fields.
-  READ_OBJECT_FIELDS(type_ref, type_ref.raw()->ptr()->from(),
-                     type_ref.raw()->ptr()->to(), kAsReference);
+  READ_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.SetTypeTestingStub(code);
 
-  return type_ref.raw();
+  return type_ref.ptr();
 }
 
-void TypeRefLayout::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
+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.
@@ -229,13 +220,10 @@
   // Allocate type parameter object.
   TypeParameter& type_parameter =
       TypeParameter::ZoneHandle(reader->zone(), TypeParameter::New());
-  bool is_canonical = ObjectLayout::IsCanonical(tags);
+  bool is_canonical = UntaggedObject::IsCanonical(tags);
   reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
 
   // Set all non object fields.
-  type_parameter.set_token_pos(
-      TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
-  type_parameter.set_index(reader->Read<int16_t>());
   const uint8_t combined = reader->Read<uint8_t>();
   type_parameter.set_flags(combined >> 4);
   type_parameter.set_nullability(static_cast<Nullability>(combined & 0xf));
@@ -244,14 +232,13 @@
   reader->EnqueueTypePostprocessing(type_parameter);
 
   // Set all the object fields.
-  READ_OBJECT_FIELDS(type_parameter, type_parameter.raw()->ptr()->from(),
-                     type_parameter.raw()->ptr()->to(), kAsReference);
+  READ_OBJECT_FIELDS(type_parameter, type_parameter.ptr()->untag()->from(),
+                     type_parameter.ptr()->untag()->to(), kAsReference);
 
-  if (type_parameter.parameterized_function() == Function::null()) {
-    // Read in the parameterized class.
-    (*reader->ClassHandle()) =
-        Class::RawCast(reader->ReadObjectImpl(kAsReference));
-  } else {
+  // 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());
@@ -265,13 +252,13 @@
     type_parameter ^= type_parameter.Canonicalize(Thread::Current(), nullptr);
   }
 
-  return type_parameter.raw();
+  return type_parameter.ptr();
 }
 
-void TypeParameterLayout::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
+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.
@@ -285,8 +272,8 @@
   writer->WriteTags(writer->GetObjectTags(this));
 
   // Write out all the non object pointer fields.
-  writer->Write<int32_t>(token_pos_.SnapshotEncode());
-  writer->Write<int16_t>(index_);
+  writer->Write<uint16_t>(base_);
+  writer->Write<uint16_t>(index_);
   const uint8_t combined = (flags_ << 4) | nullability_;
   ASSERT(flags_ == (combined >> 4));
   ASSERT(nullability_ == (combined & 0xf));
@@ -296,15 +283,10 @@
   SnapshotWriterVisitor visitor(writer, kAsReference);
   visitor.VisitPointers(from(), to());
 
-  if (parameterized_class_id_ != kFunctionCid) {
-    ASSERT(parameterized_function() == Function::null());
-    // Write out the parameterized class.
-    ClassPtr param_class =
-        writer->isolate()->class_table()->At(parameterized_class_id_);
-    writer->WriteObjectImpl(param_class, kAsReference);
-  } else {
-    ASSERT(parameterized_function() != Function::null());
-  }
+  // 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);
 }
 
 TypeArgumentsPtr TypeArguments::ReadFrom(SnapshotReader* reader,
@@ -319,7 +301,7 @@
 
   TypeArguments& type_arguments =
       TypeArguments::ZoneHandle(reader->zone(), TypeArguments::New(len));
-  bool is_canonical = ObjectLayout::IsCanonical(tags);
+  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.
@@ -336,13 +318,13 @@
     type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
   }
 
-  return type_arguments.raw();
+  return type_arguments.ptr();
 }
 
-void TypeArgumentsLayout::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
+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.
@@ -366,10 +348,11 @@
     if (!writer->can_send_any_object()) {
       // Lookup the type class.
       TypePtr raw_type = Type::RawCast(types()[i]);
-      SmiPtr raw_type_class_id = Smi::RawCast(raw_type->ptr()->type_class_id());
-      ClassPtr type_class =
-          writer->isolate()->class_table()->At(Smi::Value(raw_type_class_id));
-      if (!writer->AllowObjectsInDartLibrary(type_class->ptr()->library())) {
+      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(types()[i], as_reference);
@@ -389,10 +372,10 @@
   return Closure::null();
 }
 
-void ClosureLayout::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
+void UntaggedClosure::WriteTo(SnapshotWriter* writer,
+                              intptr_t object_id,
+                              Snapshot::Kind kind,
+                              bool as_reference) {
   ASSERT(writer != NULL);
   ASSERT(kind == Snapshot::kMessage);
 
@@ -425,20 +408,20 @@
     // TODO(5411462): Need to assert No GC can happen here, even though
     // allocations may happen.
     intptr_t num_flds =
-        (context.raw()->ptr()->to(num_vars) - context.raw()->ptr()->from());
+        (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.raw()->ptr()->from() + i),
-                           reader->PassiveObjectHandle()->raw());
+      context.StorePointer((context.ptr()->untag()->from() + i),
+                           reader->PassiveObjectHandle()->ptr());
     }
   }
-  return context.raw();
+  return context.ptr();
 }
 
-void ContextLayout::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
+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.
@@ -483,16 +466,16 @@
     context_scope.SetTypeAt(0, *reader->TypeHandle());
     context_scope.SetContextIndexAt(0, 0);
     context_scope.SetContextLevelAt(0, 0);
-    return context_scope.raw();
+    return context_scope.ptr();
   }
   UNREACHABLE();
   return NULL;
 }
 
-void ContextScopeLayout::WriteTo(SnapshotWriter* writer,
-                                 intptr_t object_id,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
+void UntaggedContextScope::WriteTo(SnapshotWriter* writer,
+                                   intptr_t object_id,
+                                   Snapshot::Kind kind,
+                                   bool as_reference) {
   ASSERT(writer != NULL);
 
   if (is_implicit_) {
@@ -524,8 +507,8 @@
     UNREACHABLE();                                                             \
     return type::null();                                                       \
   }                                                                            \
-  void type##Layout::WriteTo(SnapshotWriter* writer, intptr_t object_id,       \
-                             Snapshot::Kind kind, bool as_reference) {         \
+  void Untagged##type::WriteTo(SnapshotWriter* writer, intptr_t object_id,     \
+                               Snapshot::Kind kind, bool as_reference) {       \
     UNREACHABLE();                                                             \
   }
 
@@ -536,8 +519,8 @@
     UNREACHABLE();                                                             \
     return type::null();                                                       \
   }                                                                            \
-  void type##Layout::WriteTo(SnapshotWriter* writer, intptr_t object_id,       \
-                             Snapshot::Kind kind, bool as_reference) {         \
+  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 ")");                   \
@@ -568,7 +551,6 @@
 MESSAGE_SNAPSHOT_UNREACHABLE(PatchClass);
 MESSAGE_SNAPSHOT_UNREACHABLE(PcDescriptors);
 MESSAGE_SNAPSHOT_UNREACHABLE(Script);
-MESSAGE_SNAPSHOT_UNREACHABLE(SignatureData);
 MESSAGE_SNAPSHOT_UNREACHABLE(SingleTargetCache);
 MESSAGE_SNAPSHOT_UNREACHABLE(String);
 MESSAGE_SNAPSHOT_UNREACHABLE(SubtypeTestCache);
@@ -580,6 +562,7 @@
 MESSAGE_SNAPSHOT_UNREACHABLE(FutureOr);
 MESSAGE_SNAPSHOT_UNREACHABLE(WeakSerializationReference);
 
+MESSAGE_SNAPSHOT_ILLEGAL(FunctionType)
 MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
 MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
 MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
@@ -599,16 +582,16 @@
   reader->AddBackRef(object_id, &api_error, kIsDeserialized);
 
   // Set all the object fields.
-  READ_OBJECT_FIELDS(api_error, api_error.raw()->ptr()->from(),
-                     api_error.raw()->ptr()->to(), kAsReference);
+  READ_OBJECT_FIELDS(api_error, api_error.ptr()->untag()->from(),
+                     api_error.ptr()->untag()->to(), kAsReference);
 
-  return api_error.raw();
+  return api_error.ptr();
 }
 
-void ApiErrorLayout::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
+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.
@@ -637,21 +620,21 @@
 
   // Set all non object fields.
   language_error.set_token_pos(
-      TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
+      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_OBJECT_FIELDS(language_error, language_error.raw()->ptr()->from(),
-                     language_error.raw()->ptr()->to(), kAsReference);
+  READ_OBJECT_FIELDS(language_error, language_error.ptr()->untag()->from(),
+                     language_error.ptr()->untag()->to(), kAsReference);
 
-  return language_error.raw();
+  return language_error.ptr();
 }
 
-void LanguageErrorLayout::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
+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.
@@ -662,7 +645,7 @@
   writer->WriteTags(writer->GetObjectTags(this));
 
   // Write out all the non object fields.
-  writer->Write<int32_t>(token_pos_.SnapshotEncode());
+  writer->Write<int32_t>(token_pos_.Serialize());
   writer->Write<bool>(report_after_token_);
   writer->Write<uint8_t>(kind_);
 
@@ -681,16 +664,16 @@
   reader->AddBackRef(object_id, &result, kIsDeserialized);
 
   // Set all the object fields.
-  READ_OBJECT_FIELDS(result, result.raw()->ptr()->from(),
-                     result.raw()->ptr()->to(), kAsReference);
+  READ_OBJECT_FIELDS(result, result.ptr()->untag()->from(),
+                     result.ptr()->untag()->to(), kAsReference);
 
-  return result.raw();
+  return result.ptr();
 }
 
-void UnhandledExceptionLayout::WriteTo(SnapshotWriter* writer,
-                                       intptr_t object_id,
-                                       Snapshot::Kind kind,
-                                       bool as_reference) {
+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);
 
@@ -713,18 +696,18 @@
   // constant.
   Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
   obj ^= Object::Allocate(kInstanceCid, Instance::InstanceSize(), Heap::kNew);
-  if (ObjectLayout::IsCanonical(tags)) {
+  if (UntaggedObject::IsCanonical(tags)) {
     obj = obj.Canonicalize(reader->thread());
   }
   reader->AddBackRef(object_id, &obj, kIsDeserialized);
 
-  return obj.raw();
+  return obj.ptr();
 }
 
-void InstanceLayout::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
+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.
@@ -751,7 +734,7 @@
     Smi& smi =
         Smi::ZoneHandle(reader->zone(), Smi::New(static_cast<intptr_t>(value)));
     reader->AddBackRef(object_id, &smi, kIsDeserialized);
-    return smi.raw();
+    return smi.ptr();
   }
 
   // Create a Mint object or get canonical one if it is a canonical constant.
@@ -761,20 +744,20 @@
   // 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 (ObjectLayout::IsCanonical(tags)) {
+  if (UntaggedObject::IsCanonical(tags)) {
     mint = Mint::NewCanonical(value);
     ASSERT(mint.IsCanonical());
   } else {
     mint = Mint::New(value);
   }
   reader->AddBackRef(object_id, &mint, kIsDeserialized);
-  return mint.raw();
+  return mint.ptr();
 }
 
-void MintLayout::WriteTo(SnapshotWriter* writer,
-                         intptr_t object_id,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
+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.
@@ -804,20 +787,20 @@
   // 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 (ObjectLayout::IsCanonical(tags)) {
+  if (UntaggedObject::IsCanonical(tags)) {
     dbl = Double::NewCanonical(value);
     ASSERT(dbl.IsCanonical());
   } else {
     dbl = Double::New(value);
   }
   reader->AddBackRef(object_id, &dbl, kIsDeserialized);
-  return dbl.raw();
+  return dbl.ptr();
 }
 
-void DoubleLayout::WriteTo(SnapshotWriter* writer,
-                           intptr_t object_id,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
+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.
@@ -839,7 +822,7 @@
                           CallbackType new_symbol,
                           Snapshot::Kind kind) {
   ASSERT(reader != NULL);
-  if (ObjectLayout::IsCanonical(tags)) {
+  if (UntaggedObject::IsCanonical(tags)) {
     // Set up canonical string object.
     ASSERT(reader != NULL);
     CharacterType* ptr = reader->zone()->Alloc<CharacterType>(len);
@@ -928,18 +911,18 @@
   }
 }
 
-void OneByteStringLayout::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
+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 TwoByteStringLayout::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
+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());
 }
@@ -962,19 +945,19 @@
   return ExternalTwoByteString::null();
 }
 
-void ExternalOneByteStringLayout::WriteTo(SnapshotWriter* writer,
-                                          intptr_t object_id,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
+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 ExternalTwoByteStringLayout::WriteTo(SnapshotWriter* writer,
-                                          intptr_t object_id,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
+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_);
@@ -1003,10 +986,10 @@
   }
   if (!as_reference) {
     // Read all the individual elements for inlined objects.
-    ASSERT(!ObjectLayout::IsCanonical(tags));
+    ASSERT(!UntaggedObject::IsCanonical(tags));
     reader->ArrayReadFrom(object_id, *array, len, tags);
   }
-  return array->raw();
+  return array->ptr();
 }
 
 ImmutableArrayPtr ImmutableArray::ReadFrom(SnapshotReader* reader,
@@ -1033,26 +1016,26 @@
   if (!as_reference) {
     // Read all the individual elements for inlined objects.
     reader->ArrayReadFrom(object_id, *array, len, tags);
-    if (ObjectLayout::IsCanonical(tags)) {
+    if (UntaggedObject::IsCanonical(tags)) {
       *array ^= array->Canonicalize(reader->thread());
     }
   }
   return raw(*array);
 }
 
-void ArrayLayout::WriteTo(SnapshotWriter* writer,
-                          intptr_t object_id,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
+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 ImmutableArrayLayout::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool 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);
@@ -1073,8 +1056,8 @@
 
   // Read type arguments of growable array object.
   *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-  array.StorePointer(&array.raw_ptr()->type_arguments_,
-                     reader->TypeArgumentsHandle()->raw());
+  array.StorePointer(&array.untag()->type_arguments_,
+                     reader->TypeArgumentsHandle()->ptr());
 
   // Read length of growable array object.
   array.SetLength(reader->ReadSmiValue());
@@ -1083,13 +1066,13 @@
   *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
   array.SetData(*(reader->ArrayHandle()));
 
-  return array.raw();
+  return array.ptr();
 }
 
-void GrowableObjectArrayLayout::WriteTo(SnapshotWriter* writer,
-                                        intptr_t object_id,
-                                        Snapshot::Kind kind,
-                                        bool as_reference) {
+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.
@@ -1143,24 +1126,24 @@
   // 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() != Dart::vm_isolate());
+  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 = ObjectLayout::IsCanonical(tags) ? false : true;
+  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.raw();
+  return map.ptr();
 }
 
-void LinkedHashMapLayout::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
+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.
@@ -1183,8 +1166,8 @@
   // Write out the keys and values.
   const bool write_as_reference = this->IsCanonical() ? false : true;
   ArrayPtr data_array = data_;
-  ObjectPtr* data_elements = data_array->ptr()->data();
-  ASSERT(used_data <= Smi::Value(data_array->ptr()->length_));
+  ObjectPtr* data_elements = data_array->untag()->data();
+  ASSERT(used_data <= Smi::Value(data_array->untag()->length_));
 #if defined(DEBUG)
   intptr_t deleted_keys_found = 0;
 #endif  // DEBUG
@@ -1219,13 +1202,13 @@
   Float32x4& simd = Float32x4::ZoneHandle(reader->zone(), Float32x4::null());
   simd = Float32x4::New(value0, value1, value2, value3);
   reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.raw();
+  return simd.ptr();
 }
 
-void Float32x4Layout::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
+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.
@@ -1258,13 +1241,13 @@
   Int32x4& simd = Int32x4::ZoneHandle(reader->zone(), Int32x4::null());
   simd = Int32x4::New(value0, value1, value2, value3);
   reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.raw();
+  return simd.ptr();
 }
 
-void Int32x4Layout::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
+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.
@@ -1295,13 +1278,13 @@
   Float64x2& simd = Float64x2::ZoneHandle(reader->zone(), Float64x2::null());
   simd = Float64x2::New(value0, value1);
   reader->AddBackRef(object_id, &simd, kIsDeserialized);
-  return simd.raw();
+  return simd.ptr();
 }
 
-void Float64x2Layout::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
+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.
@@ -1323,7 +1306,7 @@
                                  bool as_reference) {
   ASSERT(reader != NULL);
 
-  intptr_t cid = ObjectLayout::ClassIdTag::decode(tags);
+  intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
   intptr_t len = reader->ReadSmiValue();
   TypedData& result =
       TypedData::ZoneHandle(reader->zone(), TypedData::New(cid, len));
@@ -1342,12 +1325,12 @@
   // 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 (ObjectLayout::IsCanonical(tags)) {
+  if (UntaggedObject::IsCanonical(tags)) {
     result ^= result.Canonicalize(reader->thread());
     ASSERT(!result.IsNull());
     ASSERT(result.IsCanonical());
   }
-  return result.raw();
+  return result.ptr();
 }
 
 ExternalTypedDataPtr ExternalTypedData::ReadFrom(SnapshotReader* reader,
@@ -1356,7 +1339,7 @@
                                                  Snapshot::Kind kind,
                                                  bool as_reference) {
   ASSERT(!Snapshot::IsFull(kind));
-  intptr_t cid = ObjectLayout::ClassIdTag::decode(tags);
+  intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
   intptr_t length = reader->ReadSmiValue();
 
   FinalizableData finalizable_data =
@@ -1368,7 +1351,7 @@
   intptr_t external_size = obj.LengthInBytes();
   obj.AddFinalizer(finalizable_data.peer, finalizable_data.callback,
                    external_size);
-  return obj.raw();
+  return obj.ptr();
 }
 
 // This function's name can appear in Observatory.
@@ -1377,10 +1360,10 @@
   free(buffer);
 }
 
-void TypedDataLayout::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
+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(length_);  // In elements.
@@ -1477,10 +1460,10 @@
   }
 }
 
-void ExternalTypedDataLayout::WriteTo(SnapshotWriter* writer,
-                                      intptr_t object_id,
-                                      Snapshot::Kind kind,
-                                      bool as_reference) {
+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(length_);  // In elements.
@@ -1550,10 +1533,10 @@
       IsolateMessageTypedDataFinalizer);
 }
 
-void TypedDataViewLayout::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
+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());
 
@@ -1576,7 +1559,7 @@
                                          Snapshot::Kind kind,
                                          bool as_reference) {
   auto& typed_data = *reader->TypedDataBaseHandle();
-  const classid_t cid = ObjectLayout::ClassIdTag::decode(tags);
+  const classid_t cid = UntaggedObject::ClassIdTag::decode(tags);
 
   auto& view = *reader->TypedDataViewHandle();
   view = TypedDataView::New(cid);
@@ -1587,7 +1570,7 @@
   typed_data ^= reader->ReadObjectImpl(as_reference);
   view.InitializeWith(typed_data, offset_in_bytes, length);
 
-  return view.raw();
+  return view.ptr();
 }
 
 CapabilityPtr Capability::ReadFrom(SnapshotReader* reader,
@@ -1600,13 +1583,13 @@
   Capability& result =
       Capability::ZoneHandle(reader->zone(), Capability::New(id));
   reader->AddBackRef(object_id, &result, kIsDeserialized);
-  return result.raw();
+  return result.ptr();
 }
 
-void CapabilityLayout::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
+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);
 
@@ -1630,13 +1613,13 @@
   SendPort& result =
       SendPort::ZoneHandle(reader->zone(), SendPort::New(id, origin_id));
   reader->AddBackRef(object_id, &result, kIsDeserialized);
-  return result.raw();
+  return result.ptr();
 }
 
-void SendPortLayout::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
+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);
 
@@ -1664,13 +1647,13 @@
   auto& transferableTypedData = TransferableTypedData::ZoneHandle(
       reader->zone(), TransferableTypedData::New(data, length));
   reader->AddBackRef(object_id, &transferableTypedData, kIsDeserialized);
-  return transferableTypedData.raw();
+  return transferableTypedData.ptr();
 }
 
-void TransferableTypedDataLayout::WriteTo(SnapshotWriter* writer,
-                                          intptr_t object_id,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
+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));
@@ -1721,19 +1704,18 @@
   reader->AddBackRef(object_id, &regex, kIsDeserialized);
 
   // Read and Set all the other fields.
-  regex.StoreSmi(&regex.raw_ptr()->num_bracket_expressions_,
-                 reader->ReadAsSmi());
+  regex.StoreSmi(&regex.untag()->num_bracket_expressions_, reader->ReadAsSmi());
 
   *reader->ArrayHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
   regex.set_capture_name_map(*reader->ArrayHandle());
   *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
   regex.set_pattern(*reader->StringHandle());
 
-  regex.StoreNonPointer(&regex.raw_ptr()->num_one_byte_registers_,
+  regex.StoreNonPointer(&regex.untag()->num_one_byte_registers_,
                         reader->Read<int32_t>());
-  regex.StoreNonPointer(&regex.raw_ptr()->num_two_byte_registers_,
+  regex.StoreNonPointer(&regex.untag()->num_two_byte_registers_,
                         reader->Read<int32_t>());
-  regex.StoreNonPointer(&regex.raw_ptr()->type_flags_, reader->Read<int8_t>());
+  regex.StoreNonPointer(&regex.untag()->type_flags_, reader->Read<int8_t>());
 
   const Function& no_function = Function::Handle(reader->zone());
   for (intptr_t cid = kOneByteStringCid; cid <= kExternalTwoByteStringCid;
@@ -1742,13 +1724,13 @@
     regex.set_function(cid, /*sticky=*/true, no_function);
   }
 
-  return regex.raw();
+  return regex.ptr();
 }
 
-void RegExpLayout::WriteTo(SnapshotWriter* writer,
-                           intptr_t object_id,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
+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.
@@ -1779,16 +1761,16 @@
   reader->AddBackRef(object_id, &weak_property, kIsDeserialized);
 
   // Set all the object fields.
-  READ_OBJECT_FIELDS(weak_property, weak_property.raw()->ptr()->from(),
-                     weak_property.raw()->ptr()->to(), kAsReference);
+  READ_OBJECT_FIELDS(weak_property, weak_property.ptr()->untag()->from(),
+                     weak_property.ptr()->untag()->to(), kAsReference);
 
-  return weak_property.raw();
+  return weak_property.ptr();
 }
 
-void WeakPropertyLayout::WriteTo(SnapshotWriter* writer,
-                                 intptr_t object_id,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
+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.
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 0ffffe0..9b880c8 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5513,9 +5513,11 @@
                                       const Object& owner) {
   const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
 
+  const FunctionType& signature =
+      FunctionType::Handle(zone, FunctionType::New());
   Function& fn =
-      Function::Handle(zone, Function::New(Symbols::ColonMatcher(),
-                                           FunctionLayout::kIrregexpFunction,
+      Function::Handle(zone, Function::New(signature, Symbols::ColonMatcher(),
+                                           UntaggedFunction::kIrregexpFunction,
                                            true,   // Static.
                                            false,  // Not const.
                                            false,  // Not abstract.
@@ -5524,24 +5526,25 @@
                                            owner, TokenPosition::kMinSource));
 
   // TODO(zerny): Share these arrays between all irregexp functions.
+  // TODO(regis): Better, share a common signature.
   fn.set_num_fixed_parameters(kParamCount);
-  fn.set_parameter_types(
+  signature.set_parameter_types(
       Array::Handle(zone, Array::New(kParamCount, Heap::kOld)));
-  fn.CreateNameArrayIncludingFlags(Heap::kOld);
-  fn.SetParameterTypeAt(RegExpMacroAssembler::kParamRegExpIndex,
-                        Object::dynamic_type());
-  fn.SetParameterNameAt(RegExpMacroAssembler::kParamRegExpIndex,
-                        Symbols::This());
-  fn.SetParameterTypeAt(RegExpMacroAssembler::kParamStringIndex,
-                        Object::dynamic_type());
-  fn.SetParameterNameAt(RegExpMacroAssembler::kParamStringIndex,
-                        Symbols::string_param());
-  fn.SetParameterTypeAt(RegExpMacroAssembler::kParamStartOffsetIndex,
-                        Object::dynamic_type());
-  fn.SetParameterNameAt(RegExpMacroAssembler::kParamStartOffsetIndex,
-                        Symbols::start_index_param());
-  fn.set_result_type(Type::Handle(zone, Type::ArrayType()));
-  fn.TruncateUnusedParameterFlags();
+  signature.CreateNameArrayIncludingFlags(Heap::kOld);
+  signature.SetParameterTypeAt(RegExpMacroAssembler::kParamRegExpIndex,
+                               Object::dynamic_type());
+  signature.SetParameterNameAt(RegExpMacroAssembler::kParamRegExpIndex,
+                               Symbols::This());
+  signature.SetParameterTypeAt(RegExpMacroAssembler::kParamStringIndex,
+                               Object::dynamic_type());
+  signature.SetParameterNameAt(RegExpMacroAssembler::kParamStringIndex,
+                               Symbols::string_param());
+  signature.SetParameterTypeAt(RegExpMacroAssembler::kParamStartOffsetIndex,
+                               Object::dynamic_type());
+  signature.SetParameterNameAt(RegExpMacroAssembler::kParamStartOffsetIndex,
+                               Symbols::start_index_param());
+  signature.set_result_type(Type::Handle(zone, Type::ArrayType()));
+  signature.FinalizeNameArrays(fn);
 
   // Cache the result.
   regexp.set_function(specialization_cid, sticky, fn);
@@ -5580,7 +5583,7 @@
     }
   }
 
-  return regexp.raw();
+  return regexp.ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/vm/regexp_assembler.cc b/runtime/vm/regexp_assembler.cc
index 3c2e119..c36aa38 100644
--- a/runtime/vm/regexp_assembler.cc
+++ b/runtime/vm/regexp_assembler.cc
@@ -44,12 +44,12 @@
         int32_t s2[1] = {c2};
         canonicalize.get(c2, '\0', s2);
         if (s1[0] != s2[0]) {
-          return static_cast<uword>(Bool::False().raw());
+          return static_cast<uword>(Bool::False().ptr());
         }
       }
     }
   }
-  return static_cast<uword>(Bool::True().raw());
+  return static_cast<uword>(Bool::True().ptr());
 }
 
 uword /*BoolPtr*/ CaseInsensitiveCompareUTF16(uword /*StringPtr*/ str_raw,
@@ -68,7 +68,7 @@
       // Non-BMP characters do not have case-equivalents in the BMP.
       // Both have to be non-BMP for them to be able to match.
       if (!Utf16::IsLeadSurrogate(c2))
-        return static_cast<uword>(Bool::False().raw());
+        return static_cast<uword>(Bool::False().ptr());
       if (i + 1 < length.Value()) {
         uint16_t c1t = str.CharAt(lhs_index.Value() + i + 1);
         uint16_t c2t = str.CharAt(rhs_index.Value() + i + 1);
@@ -81,9 +81,9 @@
     }
     c1 = u_foldCase(c1, U_FOLD_CASE_DEFAULT);
     c2 = u_foldCase(c2, U_FOLD_CASE_DEFAULT);
-    if (c1 != c2) return static_cast<uword>(Bool::False().raw());
+    if (c1 != c2) return static_cast<uword>(Bool::False().ptr());
   }
-  return static_cast<uword>(Bool::True().raw());
+  return static_cast<uword>(Bool::True().ptr());
 }
 
 DEFINE_RAW_LEAF_RUNTIME_ENTRY(
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index 6db75e3..4d8841f 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -401,7 +401,7 @@
   NoSafepointScope no_safepoint;
   memmove(bytecode.DataAddr(0), buffer_->data(), len);
 
-  return bytecode.raw();
+  return bytecode.ptr();
 }
 
 intptr_t BytecodeRegExpMacroAssembler::length() {
@@ -505,9 +505,9 @@
   }
   if (result == IrregexpInterpreter::RE_EXCEPTION) {
     Thread* thread = Thread::Current();
-    Isolate* isolate = thread->isolate();
+    auto isolate_group = thread->isolate_group();
     const Instance& exception =
-        Instance::Handle(isolate->object_store()->stack_overflow());
+        Instance::Handle(isolate_group->object_store()->stack_overflow());
     Exceptions::Throw(thread, exception);
     UNREACHABLE();
   }
@@ -554,7 +554,7 @@
               capture_register_count * sizeof(int32_t));
     }
 
-    return result.raw();
+    return result.ptr();
   }
   if (result == IrregexpInterpreter::RE_EXCEPTION) {
     UNREACHABLE();
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index 003ceb7..552fc72 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -241,9 +241,9 @@
   TAG();
 
   Value* type = Bind(new (Z) ConstantInstr(TypeArguments::ZoneHandle(
-      Z, Isolate::Current()->object_store()->type_argument_int())));
+      Z, IsolateGroup::Current()->object_store()->type_argument_int())));
   Value* length = Bind(Uint64Constant(saved_registers_count_));
-  Value* array = Bind(new (Z) CreateArrayInstr(TokenPosition::kNoSource, type,
+  Value* array = Bind(new (Z) CreateArrayInstr(InstructionSource(), type,
                                                length, GetNextDeoptId()));
   StoreLocal(result_, array);
 
@@ -267,7 +267,7 @@
 
   // Return true on success.
   AppendInstruction(new (Z) ReturnInstr(
-      TokenPosition::kNoSource, Bind(LoadLocal(result_)), GetNextDeoptId()));
+      InstructionSource(), Bind(LoadLocal(result_)), GetNextDeoptId()));
 }
 
 void IRRegExpMacroAssembler::GenerateExitBlock() {
@@ -276,7 +276,7 @@
 
   // Return false on failure.
   AppendInstruction(new (Z) ReturnInstr(
-      TokenPosition::kNoSource, Bind(LoadLocal(result_)), GetNextDeoptId()));
+      InstructionSource(), Bind(LoadLocal(result_)), GetNextDeoptId()));
 }
 
 void IRRegExpMacroAssembler::FinalizeRegistersArray() {
@@ -323,7 +323,7 @@
   }
 
   ASSERT(retval.IsArray());
-  return Array::Cast(retval).raw();
+  return Array::Cast(retval).ptr();
 }
 
 LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name,
@@ -376,18 +376,14 @@
   ASSERT(!word_character_field.IsNull());
 
   DEBUG_ASSERT(Thread::Current()->TopErrorHandlerIsSetJump());
-  if (word_character_field.IsUninitialized()) {
-    ASSERT(!Compiler::IsBackgroundCompilation());
-    const Error& error =
-        Error::Handle(Z, word_character_field.InitializeStatic());
-    if (!error.IsNull()) {
-      Report::LongJump(error);
-    }
-  }
-  ASSERT(!word_character_field.IsUninitialized());
 
-  return new (Z) ConstantInstr(
-      Instance::ZoneHandle(Z, word_character_field.StaticValue()));
+  const auto& value =
+      Object::Handle(Z, word_character_field.StaticConstFieldValue());
+  if (value.IsError()) {
+    Report::LongJump(Error::Cast(value));
+  }
+  return new (Z)
+      ConstantInstr(Instance::ZoneHandle(Z, Instance::RawCast(value.ptr())));
 }
 
 ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind,
@@ -426,7 +422,7 @@
   Value* rhs_value = Bind(BoolConstant(true));
 
   return new (Z)
-      StrictCompareInstr(TokenPosition::kNoSource, strict_comparison, lhs_value,
+      StrictCompareInstr(InstructionSource(), strict_comparison, lhs_value,
                          rhs_value, true, GetNextDeoptId());
 }
 
@@ -472,8 +468,8 @@
     InputsArray* arguments,
     ICData::RebindRule rebind_rule) const {
   const intptr_t kTypeArgsLen = 0;
-  return new (Z) StaticCallInstr(TokenPosition::kNoSource, function,
-                                 kTypeArgsLen, Object::null_array(), arguments,
+  return new (Z) StaticCallInstr(InstructionSource(), function, kTypeArgsLen,
+                                 Object::null_array(), arguments,
                                  ic_data_array_, GetNextDeoptId(), rebind_rule);
 }
 
@@ -515,17 +511,17 @@
     InputsArray* arguments) const {
   const intptr_t kTypeArgsLen = 0;
   return new (Z) InstanceCallInstr(
-      TokenPosition::kNoSource, desc.name, desc.token_kind, arguments,
-      kTypeArgsLen, Object::null_array(), desc.checked_argument_count,
-      ic_data_array_, GetNextDeoptId());
+      InstructionSource(), desc.name, desc.token_kind, arguments, kTypeArgsLen,
+      Object::null_array(), desc.checked_argument_count, ic_data_array_,
+      GetNextDeoptId());
 }
 
 LoadLocalInstr* IRRegExpMacroAssembler::LoadLocal(LocalVariable* local) const {
-  return new (Z) LoadLocalInstr(*local, TokenPosition::kNoSource);
+  return new (Z) LoadLocalInstr(*local, InstructionSource());
 }
 
 void IRRegExpMacroAssembler::StoreLocal(LocalVariable* local, Value* value) {
-  Do(new (Z) StoreLocalInstr(*local, value, TokenPosition::kNoSource));
+  Do(new (Z) StoreLocalInstr(*local, value, InstructionSource()));
 }
 
 void IRRegExpMacroAssembler::set_current_instruction(Instruction* instruction) {
@@ -548,7 +544,7 @@
     return Bind(new (Z) ConstantInstr(*local.ConstValue()));
   }
   ASSERT(!local.is_captured());
-  return Bind(new (Z) LoadLocalInstr(local, TokenPosition::kNoSource));
+  return Bind(new (Z) LoadLocalInstr(local, InstructionSource()));
 }
 
 // In some cases, the V8 irregexp engine generates unreachable code by emitting
@@ -1691,7 +1687,7 @@
   // we set loop_depth to a non-zero value because this instruction does
   // not act as an OSR entry outside loops.
   AppendInstruction(new (Z) CheckStackOverflowInstr(
-      TokenPosition::kNoSource,
+      InstructionSource(),
       /*stack_depth=*/0,
       /*loop_depth=*/1, GetNextDeoptId(),
       is_backtrack ? CheckStackOverflowInstr::kOsrAndPreemption
@@ -1761,9 +1757,9 @@
   // Here pattern_val might be untagged so this must not trigger a GC.
   Value* index_val = BindLoadLocal(*index);
 
-  return Bind(new (Z) LoadCodeUnitsInstr(pattern_val, index_val, characters,
-                                         specialization_cid_,
-                                         TokenPosition::kNoSource));
+  return Bind(new (Z)
+                  LoadCodeUnitsInstr(pattern_val, index_val, characters,
+                                     specialization_cid_, InstructionSource()));
 }
 
 #undef __
diff --git a/runtime/vm/regexp_interpreter.cc b/runtime/vm/regexp_interpreter.cc
index 5706ca9..eb0a243 100644
--- a/runtime/vm/regexp_interpreter.cc
+++ b/runtime/vm/regexp_interpreter.cc
@@ -40,12 +40,12 @@
   Bool& ret = Bool::Handle();
   if (unicode) {
     ret = static_cast<BoolPtr>(CaseInsensitiveCompareUTF16(
-        static_cast<uword>(subject.raw()), static_cast<uword>(Smi::New(from)),
+        static_cast<uword>(subject.ptr()), static_cast<uword>(Smi::New(from)),
         static_cast<uword>(Smi::New(current)),
         static_cast<uword>(Smi::New(len))));
   } else {
     ret = static_cast<BoolPtr>(CaseInsensitiveCompareUCS2(
-        static_cast<uword>(subject.raw()), static_cast<uword>(Smi::New(from)),
+        static_cast<uword>(subject.ptr()), static_cast<uword>(Smi::New(from)),
         static_cast<uword>(Smi::New(current)),
         static_cast<uword>(Smi::New(len))));
   }
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index edad22b..4b4d12b 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -1262,7 +1262,7 @@
     array.SetAt(i * 2 + 1, smi);
   }
 
-  return array.raw();
+  return array.ptr();
 }
 
 bool RegExpParser::HasNamedCaptures() {
diff --git a/runtime/vm/report.cc b/runtime/vm/report.cc
index ded367d6..eee2f42 100644
--- a/runtime/vm/report.cc
+++ b/runtime/vm/report.cc
@@ -38,29 +38,20 @@
       UNREACHABLE();
   }
   String& result = String::Handle();
-  if (!script.IsNull() && !String::Handle(script.Source()).IsNull()) {
+  if (!script.IsNull() && script.HasSource()) {
     const String& script_url = String::Handle(script.url());
-    if (token_pos.IsReal()) {
-      intptr_t line, column, token_len;
-      script.GetTokenLocation(token_pos, &line, &column, &token_len);
+    intptr_t line, column;
+    if (script.GetTokenLocation(token_pos, &line, &column)) {
+      const intptr_t token_len = script.GetTokenLength(token_pos);
       if (report_after_token) {
-        column += token_len;
+        column += token_len < 0 ? 1 : token_len;
       }
-      // Only report the line position if we have the original source. We still
-      // need to get a valid column so that we can report the ^ mark below the
-      // snippet.
       // Allocate formatted strings in old space as they may be created during
       // optimizing compilation. Those strings are created rarely and should not
       // polute old space.
-      if (script.HasSource()) {
-        result = String::NewFormatted(
-            Heap::kOld, "'%s': %s: line %" Pd " pos %" Pd ": ",
-            script_url.ToCString(), message_header, line, column);
-      } else {
-        result =
-            String::NewFormatted(Heap::kOld, "'%s': %s: line %" Pd ": ",
-                                 script_url.ToCString(), message_header, line);
-      }
+      result = String::NewFormatted(
+          Heap::kOld, "'%s': %s: line %" Pd " pos %" Pd ": ",
+          script_url.ToCString(), message_header, line, column);
       // Append the formatted error or warning message.
       const Array& strs = Array::Handle(Array::New(6, Heap::kOld));
       strs.SetAt(0, result);
@@ -89,7 +80,7 @@
     result = String::NewFormatted(Heap::kOld, "%s: ", message_header);
     result = String::Concat(result, message, Heap::kOld);
   }
-  return result.raw();
+  return result.ptr();
 }
 
 void Report::LongJump(const Error& error) {
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index a361c5a5..6593f3e 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -36,7 +36,7 @@
     const String& function_name,
     bool allow_add,
     std::function<FunctionPtr(Class&, const String&)> lookup) {
-  Class& cls = Class::Handle(zone, receiver_class.raw());
+  Class& cls = Class::Handle(zone, receiver_class.ptr());
   if (FLAG_trace_resolving) {
     THR_Print("ResolveDynamic '%s' for class %s\n", function_name.ToCString(),
               String::Handle(zone, cls.Name()).ToCString());
@@ -47,7 +47,7 @@
       zone,
       Function::IsDynamicInvocationForwarderName(function_name)
           ? Function::DemangleDynamicInvocationForwarderName(function_name)
-          : function_name.raw());
+          : function_name.ptr());
 
   const bool is_getter = Field::IsGetterName(demangled);
   String& demangled_getter_name = String::Handle();
@@ -55,7 +55,7 @@
     demangled_getter_name = Field::NameFromGetter(demangled);
   }
 
-  const bool is_dyn_call = demangled.raw() != function_name.raw();
+  const bool is_dyn_call = demangled.ptr() != function_name.ptr();
 
   Thread* thread = Thread::Current();
   bool need_to_create_method_extractor = false;
@@ -64,10 +64,10 @@
       // Try to find a dyn:* forwarder & return it.
       function = cls.GetInvocationDispatcher(
           function_name, Array::null_array(),
-          FunctionLayout::kDynamicInvocationForwarder,
+          UntaggedFunction::kDynamicInvocationForwarder,
           /*create_if_absent=*/false);
     }
-    if (!function.IsNull()) return function.raw();
+    if (!function.IsNull()) return function.ptr();
 
     ASSERT(cls.is_finalized());
     {
@@ -81,7 +81,7 @@
           function.GetDynamicInvocationForwarder(function_name, allow_add);
     }
 #endif
-    if (!function.IsNull()) return function.raw();
+    if (!function.IsNull()) return function.ptr();
 
     // Getter invocation might actually be a method extraction.
     if (is_getter) {
@@ -105,7 +105,7 @@
     // nobody created method extractor since we last checked under ReadRwLocker.
     function = function.GetMethodExtractor(demangled);
   }
-  return function.raw();
+  return function.ptr();
 }
 
 static FunctionPtr ResolveDynamicForReceiverClassWithCustomLookup(
@@ -136,7 +136,7 @@
     }
     return Function::null();
   }
-  return function.raw();
+  return function.ptr();
 }
 
 FunctionPtr Resolver::ResolveDynamicForReceiverClass(
@@ -208,7 +208,7 @@
     // Check if we are referring to a top level function.
     const Object& object = Object::Handle(library.ResolveName(function_name));
     if (!object.IsNull() && object.IsFunction()) {
-      function ^= object.raw();
+      function ^= object.ptr();
       if (!function.AreValidArguments(type_args_len, num_arguments,
                                       argument_names, NULL)) {
         if (FLAG_trace_resolving) {
@@ -241,7 +241,7 @@
                 class_name.ToCString(), function_name.ToCString());
     }
   }
-  return function.raw();
+  return function.ptr();
 }
 
 FunctionPtr Resolver::ResolveStatic(const Class& cls,
@@ -272,7 +272,7 @@
     }
     return Function::null();
   }
-  return function.raw();
+  return function.ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/vm/reusable_handles.h b/runtime/vm/reusable_handles.h
index 7c452bc..5b05ecc 100644
--- a/runtime/vm/reusable_handles.h
+++ b/runtime/vm/reusable_handles.h
@@ -45,7 +45,7 @@
     ~Reusable##name##HandleScope() {                                           \
       ASSERT(thread_->reusable_##name##_handle_scope_active());                \
       thread_->set_reusable_##name##_handle_scope_active(false);               \
-      Handle().raw_ = name::null();                                            \
+      Handle().ptr_ = name::null();                                            \
     }                                                                          \
     name& Handle() const {                                                     \
       ASSERT(thread_->name##_handle_ != NULL);                                 \
@@ -64,7 +64,7 @@
         : handle_(thread->name##_handle_) {}                                   \
     Reusable##name##HandleScope()                                              \
         : handle_(Thread::Current()->name##_handle_) {}                        \
-    ~Reusable##name##HandleScope() { handle_->raw_ = name::null(); }           \
+    ~Reusable##name##HandleScope() { handle_->ptr_ = name::null(); }           \
     name& Handle() const {                                                     \
       ASSERT(handle_ != NULL);                                                 \
       return *handle_;                                                         \
diff --git a/runtime/vm/reverse_pc_lookup_cache.cc b/runtime/vm/reverse_pc_lookup_cache.cc
index ef62406..dad8849 100644
--- a/runtime/vm/reverse_pc_lookup_cache.cc
+++ b/runtime/vm/reverse_pc_lookup_cache.cc
@@ -25,22 +25,22 @@
   // this changes, would could sort the table list during deserialization and
   // binary search for the table.
   GrowableObjectArrayPtr tables = group->object_store()->code_order_tables();
-  intptr_t tables_length = Smi::Value(tables->ptr()->length_);
+  intptr_t tables_length = Smi::Value(tables->untag()->length_);
   for (intptr_t i = 0; i < tables_length; i++) {
     ArrayPtr table =
-        static_cast<ArrayPtr>(tables->ptr()->data_->ptr()->data()[i]);
+        static_cast<ArrayPtr>(tables->untag()->data_->untag()->data()[i]);
     intptr_t lo = 0;
-    intptr_t hi = Smi::Value(table->ptr()->length_) - 1;
+    intptr_t hi = Smi::Value(table->untag()->length_) - 1;
 
     // Fast check if pc belongs to this table.
     if (lo > hi) {
       continue;
     }
-    CodePtr first = static_cast<CodePtr>(table->ptr()->data()[lo]);
+    CodePtr first = static_cast<CodePtr>(table->untag()->data()[lo]);
     if (pc < Code::PayloadStartOf(first)) {
       continue;
     }
-    CodePtr last = static_cast<CodePtr>(table->ptr()->data()[hi]);
+    CodePtr last = static_cast<CodePtr>(table->untag()->data()[hi]);
     if (pc >= (Code::PayloadStartOf(last) + Code::PayloadSizeOf(last))) {
       continue;
     }
@@ -50,7 +50,7 @@
       intptr_t mid = (hi - lo + 1) / 2 + lo;
       ASSERT(mid >= lo);
       ASSERT(mid <= hi);
-      CodePtr code = static_cast<CodePtr>(table->ptr()->data()[mid]);
+      CodePtr code = static_cast<CodePtr>(table->untag()->data()[mid]);
       uword code_start = Code::PayloadStartOf(code);
       uword code_end = code_start + Code::PayloadSizeOf(code);
       if (pc < code_start) {
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 23f05e8..8ad3ca9 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -103,7 +103,7 @@
   Thread* thread = Thread::Current();
   TransitionGeneratedToVM transition(thread);
   VerifyPointersVisitor::VerifyPointers();
-  thread->isolate()->heap()->Verify();
+  thread->isolate_group()->heap()->Verify();
 }
 #endif
 
@@ -181,7 +181,7 @@
   const uword pc_offset = caller_frame->pc() - code.PayloadStart();
 
   if (FLAG_shared_slow_path_triggers_gc) {
-    isolate->heap()->CollectAllGarbage();
+    isolate->group()->heap()->CollectAllGarbage();
   }
 
   const CodeSourceMap& map =
@@ -196,7 +196,7 @@
     const ObjectPool& pool = ObjectPool::Handle(zone, code.GetObjectPool());
     member_name ^= pool.ObjectAt(name_index);
   } else {
-    member_name = Symbols::OptimizedOut().raw();
+    member_name = Symbols::OptimizedOut().ptr();
   }
 
   NullErrorHelper(zone, member_name);
@@ -261,7 +261,7 @@
   }
   if (len > Array::kMaxElements) {
     const Instance& exception = Instance::Handle(
-        zone, thread->isolate()->object_store()->out_of_memory());
+        zone, thread->isolate_group()->object_store()->out_of_memory());
     Exceptions::Throw(thread, exception);
   }
 
@@ -297,7 +297,7 @@
     Exceptions::ThrowRangeError("length", Integer::Cast(length), 0, max);
   } else if (len > max) {
     const Instance& exception = Instance::Handle(
-        zone, thread->isolate()->object_store()->out_of_memory());
+        zone, thread->isolate_group()->object_store()->out_of_memory());
     Exceptions::Throw(thread, exception);
   }
   const auto& typed_data =
@@ -371,7 +371,7 @@
   // outermost runtime code (to which the genenerated Dart code might not return
   // in a long time).
   bool add_to_remembered_set = true;
-  if (object->ptr()->IsRemembered()) {
+  if (object->untag()->IsRemembered()) {
     // Objects must not be added to the remembered set twice because the
     // scavenger's visitor is not idempotent.
     // Might already be remembered because of type argument store in
@@ -390,7 +390,7 @@
   }
 
   if (add_to_remembered_set) {
-    object->ptr()->AddToRememberedSet(thread);
+    object->untag()->AddToRememberedSet(thread);
   }
 
   // For incremental write barrier elimination, we need to ensure that the
@@ -481,6 +481,9 @@
   // we can't guarantee the supertype isn't the top type.
   if (supertype.IsTopTypeForSubtyping()) return;
 
+  // TODO(regis): Support for FLAG_trace_type_checks is missing here. Is it
+  // still useful or should we remove it everywhere?
+
   // The supertype or subtype may not be instantiated.
   if (AbstractType::InstantiateAndTestSubtype(
           &subtype, &supertype, instantiator_type_args, function_type_args)) {
@@ -537,12 +540,12 @@
   ASSERT(instance_type.IsInstantiated() ||
          (instance.IsClosure() && instance_type.IsInstantiated(kCurrentClass)));
   if (type.IsInstantiated()) {
-    OS::PrintErr("%s: '%s' %" Pd " %s '%s' %" Pd " (pc: %#" Px ").\n", message,
+    OS::PrintErr("%s: '%s' %d %s '%s' %d (pc: %#" Px ").\n", message,
                  String::Handle(instance_type.Name()).ToCString(),
-                 Class::Handle(instance_type.type_class()).id(),
-                 (result.raw() == Bool::True().raw()) ? "is" : "is !",
-                 String::Handle(type.Name()).ToCString(),
-                 Class::Handle(type.type_class()).id(), caller_frame->pc());
+                 instance_type.type_class_id(),
+                 (result.ptr() == Bool::True().ptr()) ? "is" : "is !",
+                 String::Handle(type.Name()).ToCString(), type.type_class_id(),
+                 caller_frame->pc());
   } else {
     // Instantiate type before printing.
     const AbstractType& instantiated_type = AbstractType::Handle(
@@ -550,7 +553,7 @@
                              function_type_arguments, kAllFree, Heap::kOld));
     OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
                  message, String::Handle(instance_type.Name()).ToCString(),
-                 (result.raw() == Bool::True().raw()) ? "is" : "is !",
+                 (result.ptr() == Bool::True().ptr()) ? "is" : "is !",
                  String::Handle(instantiated_type.Name()).ToCString(),
                  String::Handle(type.Name()).ToCString(), caller_frame->pc());
   }
@@ -608,7 +611,7 @@
   if (instance_class.IsClosureClass()) {
     const auto& closure = Closure::Cast(instance);
     const auto& closure_function = Function::Handle(zone, closure.function());
-    instance_class_id_or_function = closure_function.raw();
+    instance_class_id_or_function = closure_function.ptr();
     instance_type_arguments = closure.instantiator_type_arguments();
     instance_parent_function_type_arguments = closure.function_type_arguments();
     instance_delayed_type_arguments = closure.delayed_type_arguments();
@@ -623,7 +626,7 @@
         String::Handle(zone, instance_class.Name());
     TextBuffer buffer(256);
     buffer.Printf("  Updating test cache %#" Px " with result %s for:\n",
-                  static_cast<uword>(new_cache.raw()), result.ToCString());
+                  static_cast<uword>(new_cache.ptr()), result.ToCString());
     if (instance.IsString()) {
       buffer.Printf("    instance: '%s'\n", instance.ToCString());
     } else {
@@ -634,14 +637,14 @@
     buffer.Printf(
         "    raw entry: [ %#" Px ", %#" Px ", %#" Px ", %#" Px ", %#" Px
         ", %#" Px ", %#" Px ", %#" Px " ]\n",
-        static_cast<uword>(instance_class_id_or_function.raw()),
-        static_cast<uword>(destination_type.raw()),
-        static_cast<uword>(instance_type_arguments.raw()),
-        static_cast<uword>(instantiator_type_arguments.raw()),
-        static_cast<uword>(function_type_arguments.raw()),
-        static_cast<uword>(instance_parent_function_type_arguments.raw()),
-        static_cast<uword>(instance_delayed_type_arguments.raw()),
-        static_cast<uword>(result.raw()));
+        static_cast<uword>(instance_class_id_or_function.ptr()),
+        static_cast<uword>(destination_type.ptr()),
+        static_cast<uword>(instance_type_arguments.ptr()),
+        static_cast<uword>(instantiator_type_arguments.ptr()),
+        static_cast<uword>(function_type_arguments.ptr()),
+        static_cast<uword>(instance_parent_function_type_arguments.ptr()),
+        static_cast<uword>(instance_delayed_type_arguments.ptr()),
+        static_cast<uword>(result.ptr()));
     OS::PrintErr("%s", buffer.buffer());
   }
   {
@@ -677,7 +680,7 @@
       if (FLAG_trace_type_checks) {
         TextBuffer buffer(256);
         buffer.Printf("  Collision for test cache %#" Px " at index %" Pd ":\n",
-                      static_cast<uword>(new_cache.raw()), colliding_index);
+                      static_cast<uword>(new_cache.ptr()), colliding_index);
         buffer.Printf("    entry: ");
         new_cache.WriteEntryToBuffer(zone, &buffer, colliding_index, "      ");
         OS::PrintErr("%s\n", buffer.buffer());
@@ -685,7 +688,7 @@
       if (!FLAG_enable_isolate_groups) {
         FATAL("Duplicate subtype test cache entry");
       }
-      if (old_result.raw() != result.raw()) {
+      if (old_result.ptr() != result.ptr()) {
         FATAL("Existing subtype test cache entry has result %s, not %s",
               old_result.ToCString(), result.ToCString());
       }
@@ -702,7 +705,7 @@
       TextBuffer buffer(256);
       buffer.Printf("  Added new entry to test cache %#" Px " at index %" Pd
                     ":\n",
-                    static_cast<uword>(new_cache.raw()), len);
+                    static_cast<uword>(new_cache.ptr()), len);
       buffer.Printf("    new entry: ");
       new_cache.WriteEntryToBuffer(zone, &buffer, len, "      ");
       OS::PrintErr("%s\n", buffer.buffer());
@@ -780,7 +783,8 @@
 
   // These are guaranteed on the calling side.
   ASSERT(!dst_type.IsDynamicType());
-  ASSERT(!src_instance.IsNull() || isolate->use_strict_null_safety_checks());
+  ASSERT(!src_instance.IsNull() ||
+         isolate->group()->use_strict_null_safety_checks());
 
   const bool is_instance_of = src_instance.IsAssignableTo(
       dst_type, instantiator_type_arguments, function_type_arguments);
@@ -814,8 +818,8 @@
 #endif
     }
 
-    if (dst_name.raw() ==
-        Symbols::dynamic_assert_assignable_stc_check().raw()) {
+    if (dst_name.ptr() ==
+        Symbols::dynamic_assert_assignable_stc_check().ptr()) {
 #if !defined(TARGET_ARCH_IA32)
       // Can only come here from type testing stub via dynamic AssertAssignable.
       ASSERT(mode != kTypeCheckFromInline);
@@ -893,8 +897,8 @@
     would_update_cache_if_not_lazy =
         (!src_instance.IsNull() &&
          dst_type.type_test_stub() ==
-             StubCode::DefaultNullableTypeTest().raw()) ||
-        dst_type.type_test_stub() == StubCode::DefaultTypeTest().raw();
+             StubCode::DefaultNullableTypeTest().ptr()) ||
+        dst_type.type_test_stub() == StubCode::DefaultTypeTest().ptr();
     should_update_cache = would_update_cache_if_not_lazy && cache.IsNull();
   }
 
@@ -915,7 +919,7 @@
 #endif
     TypeTestingStubGenerator::SpecializeStubFor(thread, dst_type);
 #if defined(DEBUG)
-    ASSERT(old_code.raw() != dst_type.type_test_stub());
+    ASSERT(old_code.ptr() != dst_type.type_test_stub());
 #endif
     // Only create the cache when we come from a normal stub.
     should_update_cache = false;
@@ -1029,7 +1033,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(target_code.raw() !=
+  ASSERT(target_code.ptr() !=
          CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code));
   CodePatcher::PatchStaticCallAt(caller_frame->pc(), caller_code, target_code);
   caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
@@ -1105,7 +1109,7 @@
   const Function& target_function =
       Function::Handle(receiver_class.GetInvocationDispatcher(
           target_name, arguments_descriptor,
-          FunctionLayout::kInvokeFieldDispatcher, FLAG_lazy_dispatchers));
+          UntaggedFunction::kInvokeFieldDispatcher, FLAG_lazy_dispatchers));
   ASSERT(!target_function.IsNull() || !FLAG_lazy_dispatchers);
   if (FLAG_trace_ic) {
     OS::PrintErr(
@@ -1113,7 +1117,7 @@
         receiver_class.ToCString(), receiver_class.id(),
         target_function.IsNull() ? "null" : target_function.ToCString());
   }
-  *result = target_function.raw();
+  *result = target_function.ptr();
   return true;
 }
 
@@ -1138,19 +1142,19 @@
     const Function& target_function =
         Function::Handle(receiver_class.GetInvocationDispatcher(
             *demangled, args_descriptor,
-            FunctionLayout::kNoSuchMethodDispatcher, FLAG_lazy_dispatchers));
+            UntaggedFunction::kNoSuchMethodDispatcher, FLAG_lazy_dispatchers));
     if (FLAG_trace_ic) {
       OS::PrintErr(
           "NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n",
           receiver_class.ToCString(), receiver_class.id(),
           target_function.IsNull() ? "null" : target_function.ToCString());
     }
-    result = target_function.raw();
+    result = target_function.ptr();
   }
   // May be null if --no-lazy-dispatchers, in which case dispatch will be
   // handled by NoSuchMethodFromCallStub.
   ASSERT(!result.IsNull() || !FLAG_lazy_dispatchers);
-  return result.raw();
+  return result.ptr();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -1183,7 +1187,7 @@
   // the ic_data_array belongs to the function instead of the code. This should
   // only happen because of reload, but it sometimes happens with KBC mixed mode
   // probably through a race between foreground and background compilation.
-  if (caller_function.unoptimized_code() != caller_code.raw()) {
+  if (caller_function.unoptimized_code() != caller_code.ptr()) {
     return;
   }
 #if !defined(PRODUCT)
@@ -1242,12 +1246,12 @@
                                           const ArgumentsDescriptor& desc) {
   const bool result = receiver.IsInstanceOf(type, Object::null_type_arguments(),
                                             Object::null_type_arguments());
-  const ObjectStore* store = Isolate::Current()->object_store();
+  const ObjectStore* store = IsolateGroup::Current()->object_store();
   const Function& target =
       Function::Handle(result ? store->simple_instance_of_true_function()
                               : store->simple_instance_of_false_function());
   ASSERT(!target.IsNull());
-  return target.raw();
+  return target.ptr();
 }
 
 static FunctionPtr Resolve(
@@ -1266,8 +1270,9 @@
                                                                name, args_desc);
   }
   if (caller_arguments.length() == 2 &&
-      target_function.raw() ==
-          thread->isolate()->object_store()->simple_instance_of_function()) {
+      target_function.ptr() == thread->isolate_group()
+                                   ->object_store()
+                                   ->simple_instance_of_function()) {
     // Replace the target function with constant function.
     const AbstractType& type = AbstractType::Cast(*caller_arguments[1]);
     target_function =
@@ -1281,7 +1286,7 @@
     ASSERT(!FLAG_lazy_dispatchers);
   }
 
-  return target_function.raw();
+  return target_function.ptr();
 }
 
 // Handles a static call in unoptimized code that has one argument type not
@@ -1339,14 +1344,14 @@
 
 #if defined(DART_PRECOMPILED_RUNTIME)
 
-static bool IsSingleTarget(Isolate* isolate,
+static bool IsSingleTarget(IsolateGroup* isolate_group,
                            Zone* zone,
                            intptr_t lower_cid,
                            intptr_t upper_cid,
                            const Function& target,
                            const String& name) {
   Class& cls = Class::Handle(zone);
-  ClassTable* table = isolate->class_table();
+  ClassTable* table = isolate_group->class_table();
   Function& other_target = Function::Handle(zone);
   for (intptr_t cid = lower_cid; cid <= upper_cid; cid++) {
     if (!table->HasValidClassAt(cid)) continue;
@@ -1355,14 +1360,13 @@
     if (!cls.is_allocated()) continue;
     other_target = Resolver::ResolveDynamicAnyArgs(zone, cls, name,
                                                    /*allow_add=*/false);
-    if (other_target.raw() != target.raw()) {
+    if (other_target.ptr() != target.ptr()) {
       return false;
     }
   }
   return true;
 }
 
-
 class SavedUnlinkedCallMapKeyEqualsTraits : public AllStatic {
  public:
   static const char* Name() { return "SavedUnlinkedCallMapKeyEqualsTraits "; }
@@ -1400,7 +1404,7 @@
   const auto& new_or_old_value = UnlinkedCall::Handle(
       zone, UnlinkedCall::RawCast(
                 unlinked_call_map.InsertOrGetValue(pc, unlinked_call)));
-  RELEASE_ASSERT(new_or_old_value.raw() == unlinked_call.raw());
+  RELEASE_ASSERT(new_or_old_value.ptr() == unlinked_call.ptr());
   isolate_group->set_saved_unlinked_calls(unlinked_call_map.Release());
 }
 
@@ -1418,7 +1422,7 @@
   const auto& unlinked_call = UnlinkedCall::Cast(
       Object::Handle(zone, unlinked_call_map.GetOrDie(pc_integer)));
   isolate_group->set_saved_unlinked_calls(unlinked_call_map.Release());
-  return unlinked_call.raw();
+  return unlinked_call.ptr();
 }
 
 // NOTE: Right now we never delete [UnlinkedCall] objects. They are needed while
@@ -1574,8 +1578,8 @@
           ? NewICData()
           : NewICDataWithTarget(receiver().GetClassId(), target_function));
 
-  Object& object = Object::Handle(zone_, ic_data.raw());
-  Code& code = Code::Handle(zone_, StubCode::ICCallThroughCode().raw());
+  Object& object = Object::Handle(zone_, ic_data.ptr());
+  Code& code = Code::Handle(zone_, StubCode::ICCallThroughCode().ptr());
   // If the target function has optional parameters or is generic, it's
   // prologue requires ARGS_DESC_REG to be populated. Yet the switchable calls
   // do not populate that on the call site, which is why we don't transition
@@ -1594,12 +1598,12 @@
         Smi::Handle(zone_, Smi::New(receiver().GetClassId()));
 
     if (unlinked.can_patch_to_monomorphic()) {
-      object = expected_cid.raw();
-      code = target_code.raw();
+      object = expected_cid.ptr();
+      code = target_code.ptr();
       ASSERT(code.HasMonomorphicEntry());
     } else {
       object = MonomorphicSmiableCall::New(expected_cid.Value(), target_code);
-      code = StubCode::MonomorphicSmiableCheck().raw();
+      code = StubCode::MonomorphicSmiableCheck().ptr();
     }
   }
   CodePatcher::PatchSwitchableCallAt(caller_frame_->pc(), caller_code_, object,
@@ -1616,7 +1620,7 @@
     const Function& target_function,
     intptr_t* lower,
     intptr_t* upper) {
-  if (old_target.raw() != target_function.raw()) {
+  if (old_target.ptr() != target_function.ptr()) {
     return false;
   }
   intptr_t unchecked_lower, unchecked_upper;
@@ -1630,8 +1634,8 @@
     *upper = receiver().GetClassId();
   }
 
-  return IsSingleTarget(isolate_, zone_, unchecked_lower, unchecked_upper,
-                        target_function, name);
+  return IsSingleTarget(isolate_->group(), zone_, unchecked_lower,
+                        unchecked_upper, target_function, name);
 }
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
@@ -1642,7 +1646,7 @@
   uword pc_offset = pc - code.PayloadStart();
   const PcDescriptors& descriptors =
       PcDescriptors::Handle(zone, code.pc_descriptors());
-  PcDescriptors::Iterator iter(descriptors, PcDescriptorsLayout::kIcCall);
+  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kIcCall);
   intptr_t deopt_id = -1;
   while (iter.MoveNext()) {
     if (iter.PcOffset() == pc_offset) {
@@ -1667,8 +1671,8 @@
     old_expected_cid = MonomorphicSmiableCall::Cast(data).expected_cid();
   }
   const bool is_monomorphic_hit = old_expected_cid == receiver().GetClassId();
-  const auto& old_receiver_class =
-      Class::Handle(zone_, isolate_->class_table()->At(old_expected_cid));
+  const auto& old_receiver_class = Class::Handle(
+      zone_, isolate_->group()->class_table()->At(old_expected_cid));
   const auto& old_target = Function::Handle(
       zone_, Resolve(thread_, zone_, caller_arguments_, old_receiver_class,
                      name_, args_descriptor_));
@@ -1847,15 +1851,15 @@
   ASSERT(ic_data.NumArgsTested() == caller_arguments_.length());
 
   if (ic_data.NumArgsTested() == 1) {
-    ASSERT(old_code.raw() == StubCode::OneArgCheckInlineCache().raw() ||
-           old_code.raw() ==
-               StubCode::OneArgCheckInlineCacheWithExactnessCheck().raw() ||
-           old_code.raw() ==
-               StubCode::OneArgOptimizedCheckInlineCache().raw() ||
-           old_code.raw() ==
+    ASSERT(old_code.ptr() == StubCode::OneArgCheckInlineCache().ptr() ||
+           old_code.ptr() ==
+               StubCode::OneArgCheckInlineCacheWithExactnessCheck().ptr() ||
+           old_code.ptr() ==
+               StubCode::OneArgOptimizedCheckInlineCache().ptr() ||
+           old_code.ptr() ==
                StubCode::OneArgOptimizedCheckInlineCacheWithExactnessCheck()
-                   .raw() ||
-           old_code.raw() == StubCode::ICCallBreakpoint().raw() ||
+                   .ptr() ||
+           old_code.ptr() == StubCode::ICCallBreakpoint().ptr() ||
            (old_code.IsNull() && !should_consider_patching()));
     UpdateICDataWithTarget(ic_data, target_function);
     if (should_consider_patching()) {
@@ -1864,17 +1868,17 @@
     }
     const Code& stub = Code::Handle(
         zone_, ic_data.is_tracking_exactness()
-                   ? StubCode::OneArgCheckInlineCacheWithExactnessCheck().raw()
-                   : StubCode::OneArgCheckInlineCache().raw());
+                   ? StubCode::OneArgCheckInlineCacheWithExactnessCheck().ptr()
+                   : StubCode::OneArgCheckInlineCache().ptr());
     ReturnJIT(stub, ic_data, target_function);
   } else {
-    ASSERT(old_code.raw() == StubCode::TwoArgsCheckInlineCache().raw() ||
-           old_code.raw() == StubCode::SmiAddInlineCache().raw() ||
-           old_code.raw() == StubCode::SmiLessInlineCache().raw() ||
-           old_code.raw() == StubCode::SmiEqualInlineCache().raw() ||
-           old_code.raw() ==
-               StubCode::TwoArgsOptimizedCheckInlineCache().raw() ||
-           old_code.raw() == StubCode::ICCallBreakpoint().raw() ||
+    ASSERT(old_code.ptr() == StubCode::TwoArgsCheckInlineCache().ptr() ||
+           old_code.ptr() == StubCode::SmiAddInlineCache().ptr() ||
+           old_code.ptr() == StubCode::SmiLessInlineCache().ptr() ||
+           old_code.ptr() == StubCode::SmiEqualInlineCache().ptr() ||
+           old_code.ptr() ==
+               StubCode::TwoArgsOptimizedCheckInlineCache().ptr() ||
+           old_code.ptr() == StubCode::ICCallBreakpoint().ptr() ||
            (old_code.IsNull() && !should_consider_patching()));
     UpdateICDataWithTarget(ic_data, target_function);
     ReturnJIT(StubCode::TwoArgsCheckInlineCache(), ic_data, target_function);
@@ -2080,7 +2084,7 @@
                                            &data);
   } else {
     ASSERT(old_data.IsICData() || old_data.IsMegamorphicCache());
-    data = old_data.raw();
+    data = old_data.ptr();
   }
 #endif
   HandleMiss(data, code, target_function);
@@ -2092,21 +2096,21 @@
   switch (old_data.GetClassId()) {
 #if defined(DART_PRECOMPILED_RUNTIME)
     case kUnlinkedCallCid:
-      ASSERT(old_code.raw() == StubCode::SwitchableCallMiss().raw());
+      ASSERT(old_code.ptr() == StubCode::SwitchableCallMiss().ptr());
       DoUnlinkedCallAOT(UnlinkedCall::Cast(old_data), target_function);
       break;
     case kMonomorphicSmiableCallCid:
-      ASSERT(old_code.raw() == StubCode::MonomorphicSmiableCheck().raw());
+      ASSERT(old_code.ptr() == StubCode::MonomorphicSmiableCheck().ptr());
       FALL_THROUGH;
     case kSmiCid:
       DoMonomorphicMissAOT(old_data, target_function);
       break;
     case kSingleTargetCacheCid:
-      ASSERT(old_code.raw() == StubCode::SingleTargetCall().raw());
+      ASSERT(old_code.ptr() == StubCode::SingleTargetCall().ptr());
       DoSingleTargetMissAOT(SingleTargetCache::Cast(old_data), target_function);
       break;
     case kICDataCid:
-      ASSERT(old_code.raw() == StubCode::ICCallThroughCode().raw());
+      ASSERT(old_code.ptr() == StubCode::ICCallThroughCode().ptr());
       DoICDataMissAOT(ICData::Cast(old_data), target_function);
       break;
 #else
@@ -2120,7 +2124,7 @@
       break;
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
     case kMegamorphicCacheCid:
-      ASSERT(old_code.raw() == StubCode::MegamorphicCall().raw() ||
+      ASSERT(old_code.ptr() == StubCode::MegamorphicCall().ptr() ||
              (old_code.IsNull() && !should_consider_patching()));
       DoMegamorphicMiss(MegamorphicCache::Cast(old_data), target_function);
       break;
@@ -2235,7 +2239,7 @@
   ASSERT(!FLAG_lazy_dispatchers);
   const bool is_dynamic_call =
       Function::IsDynamicInvocationForwarderName(target_name);
-  String& demangled_target_name = String::Handle(zone, target_name.raw());
+  String& demangled_target_name = String::Handle(zone, target_name.ptr());
   if (is_dynamic_call) {
     demangled_target_name =
         Function::DemangleDynamicInvocationForwarderName(target_name);
@@ -2272,7 +2276,7 @@
             Function::Handle(zone, function.ImplicitClosureFunction());
         const Object& result = Object::Handle(
             zone, closure_function.ImplicitInstanceClosure(receiver));
-        return result.raw();
+        return result.ptr();
       }
       cls = cls.SuperClass();
     }
@@ -2283,7 +2287,7 @@
     // o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong
     // number of arguments, or try (o.foo).call(...)
 
-    if ((target_name.raw() == Symbols::Call().raw()) && receiver.IsClosure()) {
+    if ((target_name.ptr() == Symbols::Call().ptr()) && receiver.IsClosure()) {
       // Special case: closures are implemented with a call getter instead of a
       // call method and with lazy dispatchers the field-invocation-dispatcher
       // would perform the closure call.
@@ -2298,7 +2302,7 @@
     const auto& dyn_getter_name = String::Handle(
         zone, is_dynamic_call
                   ? Function::CreateDynamicInvocationForwarderName(getter_name)
-                  : getter_name.raw());
+                  : getter_name.ptr());
     ArgumentsDescriptor args_desc(orig_arguments_desc);
     while (!cls.IsNull()) {
       // If there is a function with the target name but mismatched arguments
@@ -2332,7 +2336,7 @@
         const Object& getter_result = Object::Handle(
             zone, DartEntry::InvokeFunction(function, getter_arguments));
         if (getter_result.IsError()) {
-          return getter_result.raw();
+          return getter_result.ptr();
         }
         ASSERT(getter_result.IsNull() || getter_result.IsInstance());
 
@@ -2348,7 +2352,7 @@
       zone,
       DartEntry::InvokeNoSuchMethod(thread, receiver, demangled_target_name,
                                     orig_arguments, orig_arguments_desc));
-  return result.raw();
+  return result.ptr();
 }
 
 // Invoke appropriate noSuchMethod or closure from getter.
@@ -2392,8 +2396,8 @@
   const Array& orig_arguments = Array::CheckedHandle(zone, arguments.ArgAt(3));
 
   String& orig_function_name = String::Handle(zone);
-  if ((function.kind() == FunctionLayout::kClosureFunction) ||
-      (function.kind() == FunctionLayout::kImplicitClosureFunction)) {
+  if ((function.kind() == UntaggedFunction::kClosureFunction) ||
+      (function.kind() == UntaggedFunction::kImplicitClosureFunction)) {
     // For closure the function name is always 'call'. Replace it with the
     // name of the closurized function so that exception contains more
     // relevant information.
@@ -2416,10 +2420,11 @@
 //  - garbage collection
 //  - hot reload
 static void HandleStackOverflowTestCases(Thread* thread) {
-  Isolate* isolate = thread->isolate();
+  auto isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
 
   if (FLAG_shared_slow_path_triggers_gc) {
-    isolate->heap()->CollectAllGarbage();
+    isolate->group()->heap()->CollectAllGarbage();
   }
 
   bool do_deopt = false;
@@ -2500,7 +2505,7 @@
     {
       NoReloadScope no_reload(isolate, thread);
       const Library& lib =
-          Library::Handle(isolate->object_store()->_internal_library());
+          Library::Handle(isolate_group->object_store()->_internal_library());
       const Class& cls = Class::Handle(
           lib.LookupClass(String::Handle(String::New("VMLibraryHooks"))));
       const Function& func = Function::Handle(Resolver::ResolveFunction(
@@ -2508,14 +2513,14 @@
           String::Handle(String::New("get:platformScript"))));
       Object& result = Object::Handle(
           DartEntry::InvokeFunction(func, Object::empty_array()));
-      if (result.IsUnwindError()) {
+      if (result.IsError()) {
         Exceptions::PropagateError(Error::Cast(result));
       }
       if (!result.IsInstance()) {
         FATAL1("Bad script uri hook: %s", result.ToCString());
       }
       result = DartLibraryCalls::ToString(Instance::Cast(result));
-      if (result.IsUnwindError()) {
+      if (result.IsError()) {
         Exceptions::PropagateError(Error::Cast(result));
       }
       if (!result.IsString()) {
@@ -2557,15 +2562,15 @@
     }
   }
   if (do_gc) {
-    isolate->heap()->CollectAllGarbage(Heap::kDebugging);
+    isolate->group()->heap()->CollectAllGarbage(Heap::kDebugging);
   }
 }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 static void HandleOSRRequest(Thread* thread) {
-  Isolate* isolate = thread->isolate();
-  ASSERT(isolate->use_osr());
+  auto isolate_group = thread->isolate_group();
+  ASSERT(isolate_group->use_osr());
   DartFrameIterator iterator(thread,
                              StackFrameIterator::kNoCrossThreadIteration);
   StackFrame* frame = iterator.NextFrame();
@@ -2578,7 +2583,7 @@
 
   // If the code of the frame does not match the function's unoptimized code,
   // we bail out since the code was reset by an isolate reload.
-  if (code.raw() != function.unoptimized_code()) {
+  if (code.ptr() != function.unoptimized_code()) {
     return;
   }
 
@@ -2614,14 +2619,14 @@
     const Code& code = Code::Cast(result);
     uword optimized_entry = code.EntryPoint();
     frame->set_pc(optimized_entry);
-    frame->set_pc_marker(code.raw());
+    frame->set_pc_marker(code.ptr());
   }
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 DEFINE_RUNTIME_ENTRY(AllocateMint, 0) {
   if (FLAG_shared_slow_path_triggers_gc) {
-    isolate->heap()->CollectAllGarbage();
+    isolate->group()->heap()->CollectAllGarbage();
   }
   constexpr uint64_t val = 0x7fffffff7fffffff;
   ASSERT(!Smi::IsValid(static_cast<int64_t>(val)));
@@ -2672,7 +2677,7 @@
     // Use the preallocated stack overflow exception to avoid calling
     // into dart code.
     const Instance& exception =
-        Instance::Handle(isolate->object_store()->stack_overflow());
+        Instance::Handle(isolate->group()->object_store()->stack_overflow());
     Exceptions::Throw(thread, exception);
     UNREACHABLE();
   }
@@ -2705,7 +2710,7 @@
   ASSERT(frame != NULL);
   OS::PrintErr(
       "IC call @%#" Px ": ICData: %#" Px " cnt:%" Pd " nchecks: %" Pd " %s\n",
-      frame->pc(), static_cast<uword>(ic_data.raw()), function.usage_counter(),
+      frame->pc(), static_cast<uword>(ic_data.ptr()), function.usage_counter(),
       ic_data.NumberOfChecks(), function.ToFullyQualifiedCString());
 }
 
@@ -2935,7 +2940,10 @@
   ASSERT(!unoptimized_code.IsNull());
   // The switch to unoptimized code may have already occurred.
   if (function.HasOptimizedCode()) {
-    function.SwitchToUnoptimizedCode();
+    SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+    if (function.HasOptimizedCode()) {
+      function.SwitchToUnoptimizedCode();
+    }
   }
 
   if (frame->IsMarkedForLazyDeopt()) {
@@ -3127,7 +3135,7 @@
     ASSERT(!function.IsNull());
 
     // The code will be the same as before.
-    ASSERT(code.raw() == optimized_code.raw());
+    ASSERT(code.ptr() == optimized_code.ptr());
 
     // Some sanity checking of the optimized code.
     ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
@@ -3214,8 +3222,8 @@
   Object& result = Object::Handle(zone, field.InitializeInstance(instance));
   ThrowIfError(result);
   result = instance.GetField(field);
-  ASSERT((result.raw() != Object::sentinel().raw()) &&
-         (result.raw() != Object::transition_sentinel().raw()));
+  ASSERT((result.ptr() != Object::sentinel().ptr()) &&
+         (result.ptr() != Object::transition_sentinel().ptr()));
   arguments.SetReturn(result);
 }
 
@@ -3224,8 +3232,8 @@
   Object& result = Object::Handle(zone, field.InitializeStatic());
   ThrowIfError(result);
   result = field.StaticValue();
-  ASSERT((result.raw() != Object::sentinel().raw()) &&
-         (result.raw() != Object::transition_sentinel().raw()));
+  ASSERT((result.ptr() != Object::sentinel().ptr()) &&
+         (result.ptr() != Object::transition_sentinel().ptr()));
   arguments.SetReturn(result);
 }
 
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index c84dc26..3b08708 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -32,8 +32,8 @@
       function_level_(function_level),
       loop_level_(loop_level),
       context_level_(LocalScope::kUninitializedContextLevel),
-      begin_token_pos_(TokenPosition::kNoSourcePos),
-      end_token_pos_(TokenPosition::kNoSourcePos),
+      begin_token_pos_(TokenPosition::kNoSource),
+      end_token_pos_(TokenPosition::kNoSource),
       variables_(),
       labels_(),
       context_variables_(),
@@ -110,7 +110,7 @@
   ASSERT(name.IsSymbol());
   intptr_t num_references = referenced_.length();
   for (intptr_t i = 0; i < num_references; i++) {
-    if (name.raw() == referenced_[i]->name().raw()) {
+    if (name.ptr() == referenced_[i]->name().ptr()) {
       return referenced_[i];
     }
   }
@@ -325,27 +325,27 @@
 // The parser creates internal variables that start with ":"
 static bool IsFilteredIdentifier(const String& str) {
   ASSERT(str.Length() > 0);
-  if (str.raw() == Symbols::AsyncOperation().raw()) {
+  if (str.ptr() == Symbols::AsyncOperation().ptr()) {
     // Keep :async_op for asynchronous debugging.
     return false;
   }
-  if (str.raw() == Symbols::AsyncFuture().raw()) {
+  if (str.ptr() == Symbols::AsyncFuture().ptr()) {
     // Keep :async_future for asynchronous debugging.
     return false;
   }
-  if (str.raw() == Symbols::ControllerStream().raw()) {
+  if (str.ptr() == Symbols::ControllerStream().ptr()) {
     // Keep :controller_stream for asynchronous debugging.
     return false;
   }
-  if (str.raw() == Symbols::AwaitJumpVar().raw()) {
+  if (str.ptr() == Symbols::AwaitJumpVar().ptr()) {
     // Keep :await_jump_var for asynchronous debugging.
     return false;
   }
-  if (str.raw() == Symbols::is_sync().raw()) {
+  if (str.ptr() == Symbols::is_sync().ptr()) {
     // Keep :is_sync for asynchronous debugging.
     return false;
   }
-  if (str.raw() == Symbols::FunctionTypeArgumentsVar().raw()) {
+  if (str.ptr() == Symbols::FunctionTypeArgumentsVar().ptr()) {
     // Keep :function_type_arguments for accessing type variables in debugging.
     return false;
   }
@@ -365,9 +365,9 @@
     ASSERT(func.IsLocalFunction());
     for (int i = 0; i < context_scope.num_variables(); i++) {
       String& name = String::Handle(context_scope.NameAt(i));
-      LocalVarDescriptorsLayout::VarInfoKind kind;
+      UntaggedLocalVarDescriptors::VarInfoKind kind;
       if (!IsFilteredIdentifier(name)) {
-        kind = LocalVarDescriptorsLayout::kContextVar;
+        kind = UntaggedLocalVarDescriptors::kContextVar;
       } else {
         continue;
       }
@@ -399,12 +399,12 @@
   for (int i = 0; i < this->variables_.length(); i++) {
     LocalVariable* var = variables_[i];
     if ((var->owner() == this) && !var->is_invisible()) {
-      if (var->name().raw() == Symbols::CurrentContextVar().raw()) {
+      if (var->name().ptr() == Symbols::CurrentContextVar().ptr()) {
         // This is the local variable in which the function saves its
         // own context before calling a closure function.
         LocalVarDescriptorsBuilder::VarDesc desc;
         desc.name = &var->name();
-        desc.info.set_kind(LocalVarDescriptorsLayout::kSavedCurrentContext);
+        desc.info.set_kind(UntaggedLocalVarDescriptors::kSavedCurrentContext);
         desc.info.scope_id = 0;
         desc.info.declaration_pos = TokenPosition::kMinSource;
         desc.info.begin_pos = TokenPosition::kMinSource;
@@ -416,12 +416,12 @@
         LocalVarDescriptorsBuilder::VarDesc desc;
         desc.name = &var->name();
         if (var->is_captured()) {
-          desc.info.set_kind(LocalVarDescriptorsLayout::kContextVar);
+          desc.info.set_kind(UntaggedLocalVarDescriptors::kContextVar);
           ASSERT(var->owner() != NULL);
           ASSERT(var->owner()->context_level() >= 0);
           desc.info.scope_id = var->owner()->context_level();
         } else {
-          desc.info.set_kind(LocalVarDescriptorsLayout::kStackVar);
+          desc.info.set_kind(UntaggedLocalVarDescriptors::kStackVar);
           desc.info.scope_id = *scope_id;
         }
         desc.info.set_index(var->index().value());
@@ -443,7 +443,7 @@
   ASSERT(name.IsSymbol());
   for (intptr_t i = 0; i < labels_.length(); i++) {
     SourceLabel* label = labels_[i];
-    if (label->name().raw() == name.raw()) {
+    if (label->name().ptr() == name.ptr()) {
       return label;
     }
   }
@@ -455,7 +455,7 @@
   for (intptr_t i = 0; i < variables_.length(); i++) {
     LocalVariable* var = variables_[i];
     ASSERT(var->name().IsSymbol());
-    if (var->name().raw() == name.raw()) {
+    if (var->name().ptr() == name.ptr()) {
       return var;
     }
   }
@@ -641,7 +641,7 @@
     }
   }
   ASSERT(context_scope.num_variables() == captured_idx);  // Verify count.
-  return context_scope.raw();
+  return context_scope.ptr();
 }
 
 LocalScope* LocalScope::RestoreOuterScope(const ContextScope& context_scope) {
@@ -693,11 +693,11 @@
     for (intptr_t i = 0; i < scope->num_variables(); i++) {
       LocalVariable* variable = scope->VariableAt(i);
       if (variable->is_forced_stack() ||
-          (variable->name().raw() == Symbols::ExceptionVar().raw()) ||
-          (variable->name().raw() == Symbols::SavedTryContextVar().raw()) ||
-          (variable->name().raw() == Symbols::ArgDescVar().raw()) ||
-          (variable->name().raw() ==
-           Symbols::FunctionTypeArgumentsVar().raw())) {
+          (variable->name().ptr() == Symbols::ExceptionVar().ptr()) ||
+          (variable->name().ptr() == Symbols::SavedTryContextVar().ptr()) ||
+          (variable->name().ptr() == Symbols::ArgDescVar().ptr()) ||
+          (variable->name().ptr() ==
+           Symbols::FunctionTypeArgumentsVar().ptr())) {
         // Don't capture those variables because the VM expects them to be on
         // the stack.
         continue;
@@ -727,7 +727,7 @@
   context_scope.SetContextIndexAt(0, 0);
   context_scope.SetContextLevelAt(0, 0);
   ASSERT(context_scope.num_variables() == kNumCapturedVars);  // Verify count.
-  return context_scope.raw();
+  return context_scope.ptr();
 }
 
 bool LocalVariable::Equals(const LocalVariable& other) const {
@@ -777,10 +777,11 @@
 
     VarDesc desc;
     desc.name = &Symbols::Empty();  // No name.
-    desc.info.set_kind(LocalVarDescriptorsLayout::kContextLevel);
+    desc.info.set_kind(UntaggedLocalVarDescriptors::kContextLevel);
     desc.info.scope_id = 0;
-    desc.info.begin_pos = TokenPosition(start_deopt_id);
-    desc.info.end_pos = TokenPosition(end_deopt_id);
+    // We repurpose the token position fields to store deopt IDs in this case.
+    desc.info.begin_pos = TokenPosition::Deserialize(start_deopt_id);
+    desc.info.end_pos = TokenPosition::Deserialize(end_deopt_id);
     desc.info.set_index(start_context_level);
     Add(desc);
 
@@ -790,14 +791,14 @@
 
 LocalVarDescriptorsPtr LocalVarDescriptorsBuilder::Done() {
   if (vars_.is_empty()) {
-    return Object::empty_var_descriptors().raw();
+    return Object::empty_var_descriptors().ptr();
   }
   const LocalVarDescriptors& var_desc =
       LocalVarDescriptors::Handle(LocalVarDescriptors::New(vars_.length()));
   for (int i = 0; i < vars_.length(); i++) {
     var_desc.SetVar(i, *(vars_[i].name), &vars_[i].info);
   }
-  return var_desc.raw();
+  return var_desc.ptr();
 }
 
 }  // namespace dart
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index b003324..593e186 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -259,7 +259,7 @@
  public:
   struct VarDesc {
     const String* name;
-    LocalVarDescriptorsLayout::VarInfo info;
+    UntaggedLocalVarDescriptors::VarInfo info;
   };
 
   LocalVarDescriptorsBuilder() : vars_(8) {}
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 6a674bb..a4a8c0b 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -15,6 +15,7 @@
 #include "platform/utils.h"
 #include "vm/base64.h"
 #include "vm/canonical_tables.h"
+#include "vm/closure_functions_cache.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/cpu.h"
 #include "vm/dart_api_impl.h"
@@ -100,7 +101,7 @@
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   ASSERT(zone != NULL);
-  const intptr_t id = ring_->GetIdForObject(obj.raw(), policy_);
+  const intptr_t id = ring_->GetIdForObject(obj.ptr(), policy_);
   return zone->PrintToString("objects/%" Pd "", id);
 }
 
@@ -212,7 +213,7 @@
     Exceptions::PropagateError(error);
     return Object::null();
   }
-  return object.raw();
+  return object.ptr();
 }
 
 static void PrintMissingParamError(JSONStream* js, const char* param) {
@@ -412,7 +413,7 @@
 
 static bool IsValidClassId(Isolate* isolate, intptr_t cid) {
   ASSERT(isolate != NULL);
-  ClassTable* class_table = isolate->class_table();
+  ClassTable* class_table = isolate->group()->class_table();
   ASSERT(class_table != NULL);
   return class_table->IsValidIndex(cid) && class_table->HasValidClassAt(cid);
 }
@@ -420,7 +421,7 @@
 static ClassPtr GetClassForId(Isolate* isolate, intptr_t cid) {
   ASSERT(isolate == Isolate::Current());
   ASSERT(isolate != NULL);
-  ClassTable* class_table = isolate->class_table();
+  ClassTable* class_table = isolate->group()->class_table();
   ASSERT(class_table != NULL);
   return class_table->At(cid);
 }
@@ -1495,12 +1496,11 @@
 };
 
 static bool GetScripts(Thread* thread, JSONStream* js) {
-  Isolate* isolate = thread->isolate();
+  auto object_store = thread->isolate_group()->object_store();
   Zone* zone = thread->zone();
-  ASSERT(isolate != NULL);
 
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(zone, isolate->object_store()->libraries());
+  const auto& libs =
+      GrowableObjectArray::Handle(zone, object_store->libraries());
   intptr_t num_libs = libs.Length();
 
   Library& lib = Library::Handle(zone);
@@ -1702,11 +1702,11 @@
     }
     const Integer& obj =
         Integer::Handle(thread->zone(), Smi::New(static_cast<intptr_t>(value)));
-    return obj.raw();
+    return obj.ptr();
   } else if (strcmp(arg, "bool-true") == 0) {
-    return Bool::True().raw();
+    return Bool::True().ptr();
   } else if (strcmp(arg, "bool-false") == 0) {
-    return Bool::False().raw();
+    return Bool::False().ptr();
   } else if (strcmp(arg, "null") == 0) {
     return Object::null();
   }
@@ -1724,27 +1724,26 @@
                                     const Class& klass,
                                     char** parts,
                                     int num_parts) {
-  auto isolate = thread->isolate();
   auto zone = thread->zone();
 
   if (num_parts != 4) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
 
   const char* encoded_id = parts[3];
   auto& id = String::Handle(String::New(encoded_id));
   id = String::DecodeIRI(id);
   if (id.IsNull()) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
 
   if (strcmp(parts[2], "fields") == 0) {
     // Field ids look like: "classes/17/fields/name"
     const auto& field = Field::Handle(klass.LookupField(id));
     if (field.IsNull()) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
-    return field.raw();
+    return field.ptr();
   }
   if (strcmp(parts[2], "functions") == 0) {
     // Function ids look like: "classes/17/functions/name"
@@ -1752,63 +1751,63 @@
     const auto& function =
         Function::Handle(Resolver::ResolveFunction(zone, klass, id));
     if (function.IsNull()) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
-    return function.raw();
+    return function.ptr();
   }
   if (strcmp(parts[2], "implicit_closures") == 0) {
     // Function ids look like: "classes/17/implicit_closures/11"
     intptr_t id;
     if (!GetIntegerId(parts[3], &id)) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     const auto& func =
         Function::Handle(zone, klass.ImplicitClosureFunctionFromIndex(id));
     if (func.IsNull()) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
-    return func.raw();
+    return func.ptr();
   }
   if (strcmp(parts[2], "dispatchers") == 0) {
     // Dispatcher Function ids look like: "classes/17/dispatchers/11"
     intptr_t id;
     if (!GetIntegerId(parts[3], &id)) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     const auto& func =
         Function::Handle(zone, klass.InvocationDispatcherFunctionFromIndex(id));
     if (func.IsNull()) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
-    return func.raw();
+    return func.ptr();
   }
   if (strcmp(parts[2], "closures") == 0) {
     // Closure ids look like: "classes/17/closures/11"
     intptr_t id;
     if (!GetIntegerId(parts[3], &id)) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     Function& func = Function::Handle(zone);
-    func = isolate->ClosureFunctionFromIndex(id);
+    func = ClosureFunctionsCache::ClosureFunctionFromIndex(id);
     if (func.IsNull()) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
-    return func.raw();
+    return func.ptr();
   }
 
   UNREACHABLE();
-  return Object::sentinel().raw();
+  return Object::sentinel().ptr();
 }
 
-static ObjectPtr LookupHeapObjectLibraries(Isolate* isolate,
+static ObjectPtr LookupHeapObjectLibraries(IsolateGroup* isolate_group,
                                            char** parts,
                                            int num_parts) {
   // Library ids look like "libraries/35"
   if (num_parts < 2) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
-  const GrowableObjectArray& libs =
-      GrowableObjectArray::Handle(isolate->object_store()->libraries());
+  const auto& libs =
+      GrowableObjectArray::Handle(isolate_group->object_store()->libraries());
   ASSERT(!libs.IsNull());
   const String& id = String::Handle(String::New(parts[1]));
   // Scan for private key.
@@ -1825,14 +1824,14 @@
     }
   }
   if (!lib_found) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
 
   const auto& klass = Class::Handle(lib.toplevel_class());
   ASSERT(!klass.IsNull());
 
   if (num_parts == 2) {
-    return lib.raw();
+    return lib.ptr();
   }
   if (strcmp(parts[2], "fields") == 0) {
     // Library field ids look like: "libraries/17/fields/name"
@@ -1854,7 +1853,7 @@
   if (strcmp(parts[2], "scripts") == 0) {
     // Script ids look like "libraries/35/scripts/library%2Furl.dart/12345"
     if (num_parts != 5) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     const String& id = String::Handle(String::New(parts[3]));
     ASSERT(!id.IsNull());
@@ -1864,7 +1863,7 @@
     // Each script id is tagged with a load time.
     int64_t timestamp;
     if (!GetInteger64Id(parts[4], &timestamp, 16) || (timestamp < 0)) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
 
     Script& script = Script::Handle();
@@ -1878,13 +1877,13 @@
       script_url = script.url();
       if (script_url.Equals(requested_url) &&
           (timestamp == script.load_timestamp())) {
-        return script.raw();
+        return script.ptr();
       }
     }
   }
 
   // Not found.
-  return Object::sentinel().raw();
+  return Object::sentinel().ptr();
 }
 
 static ObjectPtr LookupHeapObjectClasses(Thread* thread,
@@ -1892,18 +1891,17 @@
                                          int num_parts) {
   // Class ids look like: "classes/17"
   if (num_parts < 2) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
-  Isolate* isolate = thread->isolate();
   Zone* zone = thread->zone();
-  ClassTable* table = isolate->class_table();
+  auto table = thread->isolate_group()->class_table();
   intptr_t id;
   if (!GetIntegerId(parts[1], &id) || !table->IsValidIndex(id)) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
   Class& cls = Class::Handle(zone, table->At(id));
   if (num_parts == 2) {
-    return cls.raw();
+    return cls.ptr();
   }
   if (strcmp(parts[2], "closures") == 0) {
     // Closure ids look like: "classes/17/closures/11"
@@ -1923,53 +1921,50 @@
   } else if (strcmp(parts[2], "types") == 0) {
     // Type ids look like: "classes/17/types/11"
     if (num_parts != 4) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     intptr_t id;
     if (!GetIntegerId(parts[3], &id)) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     if (id != 0) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     const Type& type = Type::Handle(zone, cls.DeclarationType());
     if (!type.IsNull()) {
-      return type.raw();
+      return type.ptr();
     }
   }
 
   // Not found.
-  return Object::sentinel().raw();
+  return Object::sentinel().ptr();
 }
 
 static ObjectPtr LookupHeapObjectTypeArguments(Thread* thread,
                                                char** parts,
                                                int num_parts) {
-  Isolate* isolate = thread->isolate();
   // TypeArguments ids look like: "typearguments/17"
   if (num_parts < 2) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
   intptr_t id;
   if (!GetIntegerId(parts[1], &id)) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
-  ObjectStore* object_store = isolate->object_store();
+  ObjectStore* object_store = thread->isolate_group()->object_store();
   const Array& table =
       Array::Handle(thread->zone(), object_store->canonical_type_arguments());
   ASSERT(table.Length() > 0);
   const intptr_t table_size = table.Length() - 1;
   if ((id < 0) || (id >= table_size) || (table.At(id) == Object::null())) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
   return table.At(id);
 }
 
-static ObjectPtr LookupHeapObjectCode(Isolate* isolate,
-                                      char** parts,
-                                      int num_parts) {
+static ObjectPtr LookupHeapObjectCode(char** parts, int num_parts) {
   if (num_parts != 2) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
   uword pc;
   static const char* const kCollectedPrefix = "collected-";
@@ -1981,53 +1976,53 @@
   const char* id = parts[1];
   if (strncmp(kCollectedPrefix, id, kCollectedPrefixLen) == 0) {
     if (!GetUnsignedIntegerId(&id[kCollectedPrefixLen], &pc, 16)) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     // TODO(turnidge): Return "collected" instead.
     return Object::null();
   }
   if (strncmp(kNativePrefix, id, kNativePrefixLen) == 0) {
     if (!GetUnsignedIntegerId(&id[kNativePrefixLen], &pc, 16)) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     // TODO(johnmccutchan): Support native Code.
     return Object::null();
   }
   if (strncmp(kReusedPrefix, id, kReusedPrefixLen) == 0) {
     if (!GetUnsignedIntegerId(&id[kReusedPrefixLen], &pc, 16)) {
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
     // TODO(turnidge): Return "expired" instead.
     return Object::null();
   }
   int64_t timestamp = 0;
   if (!GetCodeId(id, &timestamp, &pc) || (timestamp < 0)) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
   Code& code = Code::Handle(Code::FindCode(pc, timestamp));
   if (!code.IsNull()) {
-    return code.raw();
+    return code.ptr();
   }
 
   // Not found.
-  return Object::sentinel().raw();
+  return Object::sentinel().ptr();
 }
 
 static ObjectPtr LookupHeapObjectMessage(Thread* thread,
                                          char** parts,
                                          int num_parts) {
   if (num_parts != 2) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
   uword message_id = 0;
   if (!GetUnsignedIntegerId(parts[1], &message_id, 16)) {
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
   MessageHandler::AcquiredQueues aq(thread->isolate()->message_handler());
   Message* message = aq.queue()->FindMessageById(message_id);
   if (message == NULL) {
     // The user may try to load an expired message.
-    return Object::sentinel().raw();
+    return Object::sentinel().ptr();
   }
   if (message->IsRaw()) {
     return message->raw_obj();
@@ -2078,24 +2073,24 @@
       if (result != NULL) {
         *result = lookup_result;
       }
-      return Object::sentinel().raw();
+      return Object::sentinel().ptr();
     }
-    return obj.raw();
+    return obj.ptr();
 
   } else if (strcmp(parts[0], "libraries") == 0) {
-    return LookupHeapObjectLibraries(isolate, parts, num_parts);
+    return LookupHeapObjectLibraries(isolate->group(), parts, num_parts);
   } else if (strcmp(parts[0], "classes") == 0) {
     return LookupHeapObjectClasses(thread, parts, num_parts);
   } else if (strcmp(parts[0], "typearguments") == 0) {
     return LookupHeapObjectTypeArguments(thread, parts, num_parts);
   } else if (strcmp(parts[0], "code") == 0) {
-    return LookupHeapObjectCode(isolate, parts, num_parts);
+    return LookupHeapObjectCode(parts, num_parts);
   } else if (strcmp(parts[0], "messages") == 0) {
     return LookupHeapObjectMessage(thread, parts, num_parts);
   }
 
   // Not found.
-  return Object::sentinel().raw();
+  return Object::sentinel().ptr();
 }
 
 static Breakpoint* LookupBreakpoint(Isolate* isolate,
@@ -2205,7 +2200,7 @@
     HANDLESCOPE(thread);
     obj = LookupHeapObject(thread, target_id, &lookup_result);
   }
-  if (obj.raw() == Object::sentinel().raw()) {
+  if (obj.ptr() == Object::sentinel().ptr()) {
     if (lookup_result == ObjectIdRing::kCollected) {
       PrintSentinel(js, kCollectedSentinel);
     } else if (lookup_result == ObjectIdRing::kExpired) {
@@ -2268,7 +2263,7 @@
           }
         }
       } else if (element.IsWeakProperty()) {
-        wp ^= static_cast<WeakPropertyPtr>(element.raw());
+        wp ^= static_cast<WeakPropertyPtr>(element.ptr());
         element = wp.key();
         jselement.AddProperty("parentMapKey", element);
       } else if (element.IsInstance()) {
@@ -2330,7 +2325,7 @@
     HANDLESCOPE(thread);
     obj = LookupHeapObject(thread, target_id, &lookup_result);
   }
-  if (obj.raw() == Object::sentinel().raw()) {
+  if (obj.ptr() == Object::sentinel().ptr()) {
     if (lookup_result == ObjectIdRing::kCollected) {
       PrintSentinel(js, kCollectedSentinel);
     } else if (lookup_result == ObjectIdRing::kExpired) {
@@ -2355,7 +2350,7 @@
   ObjectIdRing::LookupResult lookup_result;
   Object& obj =
       Object::Handle(LookupHeapObject(thread, target_id, &lookup_result));
-  if (obj.raw() == Object::sentinel().raw()) {
+  if (obj.ptr() == Object::sentinel().ptr()) {
     if (lookup_result == ObjectIdRing::kCollected) {
       PrintSentinel(js, kCollectedSentinel);
     } else if (lookup_result == ObjectIdRing::kExpired) {
@@ -2395,7 +2390,7 @@
   ObjectIdRing::LookupResult lookup_result;
   Object& obj =
       Object::Handle(LookupHeapObject(thread, target_id, &lookup_result));
-  if (obj.raw() == Object::sentinel().raw()) {
+  if (obj.ptr() == Object::sentinel().ptr()) {
     if (lookup_result == ObjectIdRing::kCollected) {
       PrintSentinel(js, kCollectedSentinel);
     } else if (lookup_result == ObjectIdRing::kExpired) {
@@ -2456,7 +2451,7 @@
   ObjectIdRing::LookupResult lookup_result;
   Object& receiver = Object::Handle(
       zone, LookupHeapObject(thread, receiver_id, &lookup_result));
-  if (receiver.raw() == Object::sentinel().raw()) {
+  if (receiver.ptr() == Object::sentinel().ptr()) {
     if (lookup_result == ObjectIdRing::kCollected) {
       PrintSentinel(js, kCollectedSentinel);
     } else if (lookup_result == ObjectIdRing::kExpired) {
@@ -2506,7 +2501,7 @@
         PrintInvalidParamError(js, "argumentIds");
         return true;
       }
-      if (argument.raw() == Object::sentinel().raw()) {
+      if (argument.ptr() == Object::sentinel().ptr()) {
         if (lookup_result == ObjectIdRing::kCollected) {
           PrintSentinel(js, kCollectedSentinel);
         } else if (lookup_result == ObjectIdRing::kExpired) {
@@ -2544,7 +2539,7 @@
   if (is_instance) {
     // We don't use Instance::Cast here because it doesn't allow null.
     Instance& instance = Instance::Handle(zone);
-    instance ^= receiver.raw();
+    instance ^= receiver.ptr();
     const Object& result =
         Object::Handle(zone, instance.Invoke(selector, args, arg_names));
     result.PrintJSON(js, true);
@@ -2647,7 +2642,7 @@
     for (intptr_t i = 0; i < cids.length(); i++) {
       ObjectIdRing::LookupResult lookup_result;
       obj = LookupHeapObject(thread, cids[i], &lookup_result);
-      if (obj.raw() == Object::sentinel().raw()) {
+      if (obj.ptr() == Object::sentinel().ptr()) {
         if (lookup_result == ObjectIdRing::kCollected) {
           PrintSentinel(js, kCollectedSentinel);
         } else if (lookup_result == ObjectIdRing::kExpired) {
@@ -2754,7 +2749,7 @@
     ObjectIdRing::LookupResult lookup_result;
     Object& obj = Object::Handle(
         zone, LookupHeapObject(thread, target_id, &lookup_result));
-    if (obj.raw() == Object::sentinel().raw()) {
+    if (obj.ptr() == Object::sentinel().ptr()) {
       PrintInvalidParamError(js, "targetId");
       return true;
     }
@@ -2766,11 +2761,11 @@
                                  !ContainsNonInstance(obj))) {
       Class& cls = Class::Handle(zone);
       if (obj.IsClass()) {
-        cls ^= obj.raw();
+        cls ^= obj.ptr();
         isStatic = true;
       } else {
         Instance& instance = Instance::Handle(zone);
-        instance ^= obj.raw();
+        instance ^= obj.ptr();
         cls = instance.clazz();
         isStatic = false;
       }
@@ -3009,7 +3004,7 @@
     ObjectIdRing::LookupResult lookup_result;
     Object& obj = Object::Handle(
         zone, LookupHeapObject(thread, target_id, &lookup_result));
-    if (obj.raw() == Object::sentinel().raw()) {
+    if (obj.ptr() == Object::sentinel().ptr()) {
       if (lookup_result == ObjectIdRing::kCollected) {
         PrintSentinel(js, kCollectedSentinel);
       } else if (lookup_result == ObjectIdRing::kExpired) {
@@ -3047,7 +3042,7 @@
     if ((obj.IsInstance() || obj.IsNull()) && !ContainsNonInstance(obj)) {
       // We don't use Instance::Cast here because it doesn't allow null.
       Instance& instance = Instance::Handle(zone);
-      instance ^= obj.raw();
+      instance ^= obj.ptr();
       const Class& receiver_cls = Class::Handle(zone, instance.clazz());
       const Object& result = Object::Handle(
           zone,
@@ -3141,7 +3136,7 @@
   }
 
   const Object& obj = Object::Handle(LookupHeapObject(thread, object_id, NULL));
-  if (obj.raw() == Object::sentinel().raw() || !obj.IsClass()) {
+  if (obj.ptr() == Object::sentinel().ptr() || !obj.IsClass()) {
     PrintInvalidParamError(js, "objectId");
     return true;
   }
@@ -3261,11 +3256,11 @@
     const char* script_id_param = js->LookupParam("scriptId");
     const Object& obj =
         Object::Handle(LookupHeapObject(thread, script_id_param, NULL));
-    if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
+    if (obj.ptr() == Object::sentinel().ptr() || !obj.IsScript()) {
       PrintInvalidParamError(js, "scriptId");
       return true;
     }
-    script ^= obj.raw();
+    script ^= obj.ptr();
   } else {
     if (js->HasParam("tokenPos")) {
       js->PrintError(
@@ -3283,8 +3278,8 @@
     }
   }
   SourceReport report(report_set, compile_mode);
-  report.PrintJSON(js, script, TokenPosition(start_pos),
-                   TokenPosition(end_pos));
+  report.PrintJSON(js, script, TokenPosition::Deserialize(start_pos),
+                   TokenPosition::Deserialize(end_pos));
   return true;
 #endif  // !DART_PRECOMPILED_RUNTIME
 }
@@ -3363,7 +3358,7 @@
       return isolate->PausePostRequest();
     }
   }
-  return error.raw();
+  return error.ptr();
 }
 
 static bool AddBreakpointCommon(Thread* thread,
@@ -3414,7 +3409,7 @@
 
   const char* script_id_param = js->LookupParam("scriptId");
   Object& obj = Object::Handle(LookupHeapObject(thread, script_id_param, NULL));
-  if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
+  if (obj.ptr() == Object::sentinel().ptr() || !obj.IsScript()) {
     PrintInvalidParamError(js, "scriptId");
     return true;
   }
@@ -3455,7 +3450,7 @@
 
   const char* function_id = js->LookupParam("functionId");
   Object& obj = Object::Handle(LookupHeapObject(thread, function_id, NULL));
-  if (obj.raw() == Object::sentinel().raw() || !obj.IsFunction()) {
+  if (obj.ptr() == Object::sentinel().ptr() || !obj.IsFunction()) {
     PrintInvalidParamError(js, "functionId");
     return true;
   }
@@ -3485,7 +3480,7 @@
 
   const char* object_id = js->LookupParam("objectId");
   Object& obj = Object::Handle(LookupHeapObject(thread, object_id, NULL));
-  if (obj.raw() == Object::sentinel().raw() || !obj.IsInstance()) {
+  if (obj.ptr() == Object::sentinel().ptr() || !obj.IsInstance()) {
     PrintInvalidParamError(js, "objectId");
     return true;
   }
@@ -3539,7 +3534,7 @@
   const Class& metrics_cls =
       Class::Handle(zone, prof_lib.LookupClass(metrics_cls_name));
   ASSERT(!metrics_cls.IsNull());
-  return metrics_cls.raw();
+  return metrics_cls.ptr();
 }
 
 static bool HandleNativeMetricsList(Thread* thread, JSONStream* js) {
@@ -4063,7 +4058,7 @@
   bool include_code_samples =
       BoolParameter::Parse(js->LookupParam("_code"), false);
 #if defined(DEBUG)
-  Isolate::Current()->heap()->CollectAllGarbage();
+  IsolateGroup::Current()->heap()->CollectAllGarbage();
 #endif
   if (CheckNativeAllocationProfilerDisabled(thread, js)) {
     return true;
@@ -4105,7 +4100,6 @@
       return true;
     }
   }
-  auto isolate = thread->isolate();
   auto isolate_group = thread->isolate_group();
   if (should_reset_accumulator) {
     isolate_group->UpdateLastAllocationProfileAccumulatorResetTimestamp();
@@ -4114,7 +4108,7 @@
     isolate_group->UpdateLastAllocationProfileGCTimestamp();
     isolate_group->heap()->CollectAllGarbage();
   }
-  isolate->class_table()->AllocationProfilePrintJSON(js, internal);
+  isolate_group->class_table()->AllocationProfilePrintJSON(js, internal);
   return true;
 }
 
@@ -4137,8 +4131,8 @@
 };
 
 static bool CollectAllGarbage(Thread* thread, JSONStream* js) {
-  Isolate* isolate = thread->isolate();
-  isolate->heap()->CollectAllGarbage(Heap::kDebugging);
+  auto heap = thread->isolate_group()->heap();
+  heap->CollectAllGarbage(Heap::kDebugging);
   PrintSuccess(js);
   return true;
 }
@@ -4149,20 +4143,21 @@
 };
 
 static bool GetHeapMap(Thread* thread, JSONStream* js) {
-  Isolate* isolate = thread->isolate();
+  auto isolate_group = thread->isolate_group();
   if (js->HasParam("gc")) {
     if (js->ParamIs("gc", "scavenge")) {
-      isolate->heap()->CollectGarbage(Heap::kScavenge, Heap::kDebugging);
+      isolate_group->heap()->CollectGarbage(Heap::kScavenge, Heap::kDebugging);
     } else if (js->ParamIs("gc", "mark-sweep")) {
-      isolate->heap()->CollectGarbage(Heap::kMarkSweep, Heap::kDebugging);
+      isolate_group->heap()->CollectGarbage(Heap::kMarkSweep, Heap::kDebugging);
     } else if (js->ParamIs("gc", "mark-compact")) {
-      isolate->heap()->CollectGarbage(Heap::kMarkCompact, Heap::kDebugging);
+      isolate_group->heap()->CollectGarbage(Heap::kMarkCompact,
+                                            Heap::kDebugging);
     } else {
       PrintInvalidParamError(js, "gc");
       return true;
     }
   }
-  isolate->heap()->PrintHeapMapToJSONStream(isolate, js);
+  isolate_group->heap()->PrintHeapMapToJSONStream(isolate_group, js);
   return true;
 }
 
@@ -4372,18 +4367,18 @@
   void Append(PersistentHandle* persistent_handle) {
     JSONObject obj(handles_);
     obj.AddProperty("type", "_PersistentHandle");
-    const Object& object = Object::Handle(persistent_handle->raw());
+    const Object& object = Object::Handle(persistent_handle->ptr());
     obj.AddProperty("object", object);
   }
 
   void Append(FinalizablePersistentHandle* weak_persistent_handle) {
-    if (!weak_persistent_handle->raw()->IsHeapObject()) {
+    if (!weak_persistent_handle->ptr()->IsHeapObject()) {
       return;  // Free handle.
     }
 
     JSONObject obj(handles_);
     obj.AddProperty("type", "_WeakPersistentHandle");
-    const Object& object = Object::Handle(weak_persistent_handle->raw());
+    const Object& object = Object::Handle(weak_persistent_handle->ptr());
     obj.AddProperty("object", object);
     obj.AddPropertyF(
         "peer", "0x%" Px "",
@@ -4508,7 +4503,7 @@
   // Handle heap objects.
   ObjectIdRing::LookupResult lookup_result;
   Object& obj = Object::Handle(LookupHeapObject(thread, id, &lookup_result));
-  if (obj.raw() != Object::sentinel().raw()) {
+  if (obj.ptr() != Object::sentinel().ptr()) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
     // If obj is a script from dart:* and doesn't have source loaded, try and
     // load the source before sending the response.
@@ -4556,7 +4551,7 @@
 
 static bool GetObjectStore(Thread* thread, JSONStream* js) {
   JSONObject jsobj(js);
-  thread->isolate()->object_store()->PrintToJSONObject(&jsobj);
+  thread->isolate_group()->object_store()->PrintToJSONObject(&jsobj);
   return true;
 }
 
@@ -4577,7 +4572,7 @@
 };
 
 static bool GetClassList(Thread* thread, JSONStream* js) {
-  ClassTable* table = thread->isolate()->class_table();
+  ClassTable* table = thread->isolate_group()->class_table();
   JSONObject jsobj(js);
   table->PrintToJSONObject(&jsobj);
   return true;
@@ -4594,7 +4589,7 @@
     only_with_instantiations = true;
   }
   Zone* zone = thread->zone();
-  ObjectStore* object_store = thread->isolate()->object_store();
+  ObjectStore* object_store = thread->isolate_group()->object_store();
   CanonicalTypeArgumentsSet typeargs_table(
       zone, object_store->canonical_type_arguments());
   const intptr_t table_size = typeargs_table.NumEntries();
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 281b4ba4..20deaed 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -2250,8 +2250,9 @@
   // Is this field static?
   bool static;
 
-  // The value of this field, if the field is static.
-  @Instance staticValue [optional];
+  // The value of this field, if the field is static. If uninitialized,
+  // this will take the value of an uninitialized Sentinel.
+  @Instance|Sentinel staticValue [optional];
 
   // The location of this field in the source code.
   SourceLocation location [optional];
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 145c9be..7f86141 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -252,8 +252,8 @@
   }
   if (gc_stats() != NULL) {
     jsobj.AddProperty("reason", Heap::GCReasonToString(gc_stats()->reason_));
-    isolate()->heap()->PrintToJSONObject(Heap::kNew, &jsobj);
-    isolate()->heap()->PrintToJSONObject(Heap::kOld, &jsobj);
+    isolate_group()->heap()->PrintToJSONObject(Heap::kNew, &jsobj);
+    isolate_group()->heap()->PrintToJSONObject(Heap::kOld, &jsobj);
   }
   if (bytes() != NULL) {
     jsobj.AddPropertyBase64("bytes", bytes(), bytes_length());
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index d02dbe2..735ab0f 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -14,6 +14,7 @@
 class Breakpoint;
 class Instance;
 class Isolate;
+class IsolateGroup;
 class Object;
 class StreamInfo;
 class String;
@@ -80,6 +81,7 @@
   ServiceEvent(Isolate* isolate, EventKind event_kind);
 
   Isolate* isolate() const { return isolate_; }
+  IsolateGroup* isolate_group() const { return isolate_->group(); }
 
   // Used by the C embedding api.
   Dart_Port isolate_id() const { return isolate_->main_port(); }
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index ab07c2a..e01ccd4 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -60,7 +60,7 @@
   list.SetAt(1, port_int);
   list.SetAt(2, send_port);
   list.SetAt(3, name);
-  return list.raw();
+  return list.ptr();
 }
 
 static ArrayPtr MakeServerControlMessage(const SendPort& sp,
@@ -73,7 +73,7 @@
   list.SetAt(1, sp);
   list.SetAt(2, Bool::Get(enable));
   list.SetAt(3, silenceOutput);
-  return list.raw();
+  return list.ptr();
 }
 
 const char* ServiceIsolate::kName = DART_VM_SERVICE_ISOLATE_NAME;
@@ -436,7 +436,7 @@
     HANDLESCOPE(T);
     // Invoke main which will set up the service port.
     const Library& root_library =
-        Library::Handle(Z, I->object_store()->root_library());
+        Library::Handle(Z, I->group()->object_store()->root_library());
     if (root_library.IsNull()) {
       if (FLAG_trace_service) {
         OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 515a2b2..c078398 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -55,12 +55,12 @@
     }
     if (response_obj.IsString()) {
       String& response = String::Handle();
-      response ^= response_obj.raw();
+      response ^= response_obj.ptr();
       _msg = Utils::StrDup(response.ToCString());
     } else {
       ASSERT(response_obj.IsArray());
       Array& response_array = Array::Handle();
-      response_array ^= response_obj.raw();
+      response_array ^= response_obj.ptr();
       ASSERT(response_array.Length() == 1);
       ExternalTypedData& response = ExternalTypedData::Handle();
       response ^= response_array.At(0);
@@ -101,7 +101,7 @@
   growable.Add(dummy_isolate_id);
   array = Array::MakeFixedLength(growable);
   result.SetAt(5, array);
-  return result.raw();
+  return result.ptr();
 }
 
 static ArrayPtr EvalF(Dart_Handle lib, const char* fmt, ...) {
@@ -123,14 +123,14 @@
   const Function& result = Function::Handle(Resolver::ResolveDynamicFunction(
       Thread::Current()->zone(), cls, String::Handle(String::New(name))));
   EXPECT(!result.IsNull());
-  return result.raw();
+  return result.ptr();
 }
 
 static ClassPtr GetClass(const Library& lib, const char* name) {
   const Class& cls = Class::Handle(
       lib.LookupClass(String::Handle(Symbols::New(Thread::Current(), name))));
   EXPECT(!cls.IsNull());  // No ambiguity error expected.
-  return cls.raw();
+  return cls.ptr();
 }
 
 static void HandleIsolateMessage(Isolate* isolate, const Array& msg) {
@@ -386,7 +386,7 @@
       PcDescriptors::Handle(code_c.pc_descriptors());
   EXPECT(!descriptors.IsNull());
   ObjectIdRing* ring = isolate->EnsureObjectIdRing();
-  intptr_t id = ring->GetIdForObject(descriptors.raw());
+  intptr_t id = ring->GetIdForObject(descriptors.ptr());
 
   // Build a mock message handler and wrap it in a dart port.
   ServiceTestMessageHandler handler;
@@ -457,7 +457,7 @@
       LocalVarDescriptors::Handle(code_c.GetLocalVarDescriptors());
   // Generate an ID for this object.
   ObjectIdRing* ring = isolate->EnsureObjectIdRing();
-  intptr_t id = ring->GetIdForObject(descriptors.raw());
+  intptr_t id = ring->GetIdForObject(descriptors.ptr());
 
   // Build a mock message handler and wrap it in a dart port.
   ServiceTestMessageHandler handler;
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 316a56b..fe33fb5 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -23,6 +23,11 @@
 
 namespace dart {
 
+// constants_arm.h does not define LR constant to prevent accidental direct use
+// of it during code generation. However using LR directly is okay in this
+// file because it is a simulator.
+constexpr Register LR = LR_DO_NOT_USE_DIRECTLY;
+
 DEFINE_FLAG(uint64_t,
             trace_sim_after,
             ULLONG_MAX,
@@ -233,7 +238,7 @@
   uword pc_offset = pc - code.PayloadStart();
   const PcDescriptors& descriptors =
       PcDescriptors::Handle(code.pc_descriptors());
-  PcDescriptors::Iterator iter(descriptors, PcDescriptorsLayout::kAnyKind);
+  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     if (iter.PcOffset() == pc_offset) {
       return iter.TokenPos();
@@ -276,15 +281,18 @@
   const Script& script = Script::Handle(function.script());
   const String& func_name = String::Handle(function.QualifiedScrubbedName());
   const String& url = String::Handle(script.url());
-  intptr_t line = -1;
-  intptr_t column = -1;
-  if (token_pos.IsReal()) {
-    script.GetTokenLocation(token_pos, &line, &column);
+  intptr_t line, column;
+  if (script.GetTokenLocation(token_pos, &line, &column)) {
+    OS::PrintErr(
+        "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")", pc,
+        fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
+        func_name.ToCString(), url.ToCString(), line, column);
+
+  } else {
+    OS::PrintErr("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s)", pc, fp, sp,
+                 is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
+                 func_name.ToCString(), url.ToCString());
   }
-  OS::PrintErr(
-      "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")", pc,
-      fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
-      func_name.ToCString(), url.ToCString(), line, column);
 #if defined(DART_PRECOMPILED_RUNTIME)
   intptr_t offset;
   auto const symbol_name =
@@ -299,7 +307,7 @@
   auto const Z = T->zone();
 #if defined(DART_PRECOMPILED_RUNTIME)
   auto const vm_instructions = reinterpret_cast<uword>(
-      Dart::vm_isolate()->group()->source()->snapshot_instructions);
+      Dart::vm_isolate_group()->source()->snapshot_instructions);
   auto const isolate_instructions = reinterpret_cast<uword>(
       T->isolate_group()->source()->snapshot_instructions);
   OS::PrintErr("vm_instructions=0x%" Px ", isolate_instructions=0x%" Px "\n",
@@ -530,7 +538,7 @@
           // Make the dereferencing '*' optional.
           if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) ||
               GetValue(arg1, &value)) {
-            if (Isolate::Current()->heap()->Contains(value)) {
+            if (IsolateGroup::Current()->heap()->Contains(value)) {
               OS::PrintErr("%s: \n", arg1);
 #if defined(DEBUG)
               const Object& obj = Object::Handle(static_cast<ObjectPtr>(value));
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index b80c933..1c78f20 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -22,6 +22,11 @@
 
 namespace dart {
 
+// constants_arm64.h does not define LR constant to prevent accidental direct
+// use of it during code generation. However using LR directly is okay in this
+// file because it is a simulator.
+constexpr Register LR = LR_DO_NOT_USE_DIRECTLY;
+
 DEFINE_FLAG(uint64_t,
             trace_sim_after,
             ULLONG_MAX,
@@ -261,7 +266,7 @@
   uword pc_offset = pc - code.PayloadStart();
   const PcDescriptors& descriptors =
       PcDescriptors::Handle(code.pc_descriptors());
-  PcDescriptors::Iterator iter(descriptors, PcDescriptorsLayout::kAnyKind);
+  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     if (iter.PcOffset() == pc_offset) {
       return iter.TokenPos();
@@ -304,15 +309,17 @@
   const Script& script = Script::Handle(function.script());
   const String& func_name = String::Handle(function.QualifiedScrubbedName());
   const String& url = String::Handle(script.url());
-  intptr_t line = -1;
-  intptr_t column = -1;
-  if (token_pos.IsReal()) {
-    script.GetTokenLocation(token_pos, &line, &column);
+  intptr_t line, column;
+  if (script.GetTokenLocation(token_pos, &line, &column)) {
+    OS::PrintErr(
+        "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")", pc,
+        fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
+        func_name.ToCString(), url.ToCString(), line, column);
+  } else {
+    OS::PrintErr("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s)", pc, fp, sp,
+                 is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
+                 func_name.ToCString(), url.ToCString());
   }
-  OS::PrintErr(
-      "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")", pc,
-      fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
-      func_name.ToCString(), url.ToCString(), line, column);
 #if defined(DART_PRECOMPILED_RUNTIME)
   intptr_t offset;
   auto const symbol_name =
@@ -327,7 +334,7 @@
   auto const Z = T->zone();
 #if defined(DART_PRECOMPILED_RUNTIME)
   auto const vm_instructions = reinterpret_cast<uword>(
-      Dart::vm_isolate()->group()->source()->snapshot_instructions);
+      Dart::vm_isolate_group()->source()->snapshot_instructions);
   auto const isolate_instructions = reinterpret_cast<uword>(
       T->isolate_group()->source()->snapshot_instructions);
   OS::PrintErr("vm_instructions=0x%" Px ", isolate_instructions=0x%" Px "\n",
@@ -588,10 +595,11 @@
           // Make the dereferencing '*' optional.
           if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) ||
               GetValue(arg1, &value)) {
-            if (Isolate::Current()->heap()->Contains(value)) {
+            if (IsolateGroup::Current()->heap()->Contains(value)) {
               OS::PrintErr("%s: \n", arg1);
 #if defined(DEBUG)
-              const Object& obj = Object::Handle(static_cast<ObjectPtr>(value));
+              const Object& obj = Object::Handle(
+                  static_cast<ObjectPtr>(static_cast<uword>(value)));
               obj.Print();
 #endif  // defined(DEBUG)
             } else {
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 6655cbe..5202079 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -155,6 +155,8 @@
                              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()) {
@@ -279,8 +281,8 @@
       kind_(kind),
       thread_(thread),
       zone_(thread->zone()),
-      heap_(isolate()->heap()),
-      old_space_(thread_->isolate()->heap()->old_space()),
+      heap_(isolate_group()->heap()),
+      old_space_(isolate_group()->heap()->old_space()),
       cls_(Class::Handle(zone_)),
       code_(Code::Handle(zone_)),
       instance_(Instance::Handle(zone_)),
@@ -302,7 +304,7 @@
       error_(UnhandledException::Handle(zone_)),
       set_class_(Class::ZoneHandle(
           zone_,
-          thread_->isolate()->object_store()->linked_hash_set_class())),
+          thread_->isolate_group()->object_store()->linked_hash_set_class())),
       max_vm_isolate_object_id_(
           (Snapshot::IsFull(kind))
               ? Object::vm_isolate_snapshot_object_table().Length()
@@ -325,17 +327,17 @@
     }
     Object& result = Object::Handle(zone_);
     if (backward_references_->length() > 0) {
-      result = (*backward_references_)[0].reference()->raw();
+      result = (*backward_references_)[0].reference()->ptr();
     } else {
-      result = obj.raw();
+      result = obj.ptr();
     }
     RunDelayedTypePostprocessing();
     const Object& ok = Object::Handle(zone_, RunDelayedRehashingOfMaps());
     objects_to_rehash_ = GrowableObjectArray::null();
     if (!ok.IsNull()) {
-      return ok.raw();
+      return ok.ptr();
     }
-    return result.raw();
+    return result.ptr();
   } else {
     // An error occurred while reading, return the error object.
     return Thread::Current()->StealStickyError();
@@ -406,7 +408,7 @@
         "Invalid object found in message: library is not found or loaded.");
   }
   str_ ^= ReadObjectImpl(kAsInlinedObject);
-  if (str_.raw() == Symbols::TopLevel().raw()) {
+  if (str_.ptr() == Symbols::TopLevel().ptr()) {
     cls = library_.toplevel_class();
   } else {
     str_ = String::New(String::ScrubName(str_));
@@ -416,7 +418,7 @@
     SetReadException("Invalid object found in message: class not found");
   }
   cls.EnsureIsFinalized(thread());
-  return cls.raw();
+  return cls.ptr();
 }
 
 ObjectPtr SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
@@ -479,7 +481,7 @@
   } else {
     obj = func.ImplicitStaticClosure();
   }
-  return obj.raw();
+  return obj.ptr();
 }
 
 intptr_t SnapshotReader::NextAvailableObjectId() const {
@@ -506,7 +508,7 @@
 }
 
 bool SnapshotReader::is_vm_isolate() const {
-  return isolate() == Dart::vm_isolate();
+  return isolate_group() == Dart::vm_isolate_group();
 }
 
 ObjectPtr SnapshotReader::ReadObjectImpl(bool as_reference) {
@@ -535,7 +537,7 @@
   // Read the class header information.
   intptr_t class_header = Read<int32_t>();
   intptr_t tags = ReadTags();
-  bool read_as_reference = as_reference && !ObjectLayout::IsCanonical(tags);
+  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);
@@ -559,7 +561,7 @@
 #define SNAPSHOT_READ(clazz) case kTypedData##clazz##Cid:
 
     CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-      tags = ObjectLayout::ClassIdTag::update(class_id, tags);
+      tags = UntaggedObject::ClassIdTag::update(class_id, tags);
       pobj_ =
           TypedData::ReadFrom(this, object_id, tags, kind_, read_as_reference);
       break;
@@ -568,7 +570,7 @@
 #define SNAPSHOT_READ(clazz) case kExternalTypedData##clazz##Cid:
 
     CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-      tags = ObjectLayout::ClassIdTag::update(class_id, tags);
+      tags = UntaggedObject::ClassIdTag::update(class_id, tags);
       pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, true);
       break;
     }
@@ -577,7 +579,7 @@
 
     case kByteDataViewCid:
       CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
-        tags = ObjectLayout::ClassIdTag::update(class_id, tags);
+        tags = UntaggedObject::ClassIdTag::update(class_id, tags);
         pobj_ = TypedDataView::ReadFrom(this, object_id, tags, kind_, true);
         break;
       }
@@ -590,7 +592,7 @@
       UNREACHABLE();
       break;
   }
-  return pobj_.raw();
+  return pobj_.ptr();
 }
 
 void SnapshotReader::EnqueueRehashingOfSet(const Object& set) {
@@ -641,12 +643,12 @@
     ASSERT(next_field_offset > 0);
     // Instance::NextFieldOffset() returns the offset of the first field in
     // a Dart object.
-    bool read_as_reference = ObjectLayout::IsCanonical(tags) ? false : true;
+    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(
+        isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
             result_cid);
 
     while (offset < next_field_offset) {
@@ -659,17 +661,18 @@
         pobj_ = ReadObjectImpl(read_as_reference);
         result->SetFieldAtOffset(offset, pobj_);
         if ((offset != type_argument_field_offset) &&
-            (kind_ == Snapshot::kMessage) && isolate()->use_field_guards() &&
-            (pobj_.raw() != Object::sentinel().raw())) {
+            (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()->class_table()->At(result_cid);
+          cls_ = isolate_group()->class_table()->At(result_cid);
           array_ = cls_.OffsetToFieldMap();
           field_ ^= array_.At(offset >> kWordSizeLog2);
           ASSERT(!field_.IsNull());
           ASSERT(field_.HostOffset() == offset);
-          obj_ = pobj_.raw();
+          obj_ = pobj_.ptr();
           field_.RecordStore(obj_);
         }
         // TODO(fschneider): Verify the guarded cid and length for other kinds
@@ -677,12 +680,12 @@
       }
       offset += kWordSize;
     }
-    if (ObjectLayout::IsCanonical(tags)) {
+    if (UntaggedObject::IsCanonical(tags)) {
       *result = result->Canonicalize(thread());
       ASSERT(!result->IsNull());
     }
   }
-  return result->raw();
+  return result->ptr();
 }
 
 void SnapshotReader::AddBackRef(intptr_t id,
@@ -806,29 +809,29 @@
 
   // First check if it is one of the singleton objects.
   READ_VM_SINGLETON_OBJ(kNullObject, Object::null());
-  READ_VM_SINGLETON_OBJ(kSentinelObject, Object::sentinel().raw());
+  READ_VM_SINGLETON_OBJ(kSentinelObject, Object::sentinel().ptr());
   READ_VM_SINGLETON_OBJ(kTransitionSentinelObject,
-                        Object::transition_sentinel().raw());
-  READ_VM_SINGLETON_OBJ(kEmptyArrayObject, Object::empty_array().raw());
-  READ_VM_SINGLETON_OBJ(kZeroArrayObject, Object::zero_array().raw());
-  READ_VM_SINGLETON_OBJ(kDynamicType, Object::dynamic_type().raw());
-  READ_VM_SINGLETON_OBJ(kVoidType, Object::void_type().raw());
+                        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().raw());
-  READ_VM_SINGLETON_OBJ(kTrueValue, Bool::True().raw());
-  READ_VM_SINGLETON_OBJ(kFalseValue, Bool::False().raw());
+                        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().raw());
+                        Object::extractor_parameter_types().ptr());
   READ_VM_SINGLETON_OBJ(kExtractorParameterNames,
-                        Object::extractor_parameter_names().raw());
+                        Object::extractor_parameter_names().ptr());
   READ_VM_SINGLETON_OBJ(kEmptyContextScopeObject,
-                        Object::empty_context_scope().raw());
-  READ_VM_SINGLETON_OBJ(kEmptyObjectPool, Object::empty_object_pool().raw());
-  READ_VM_SINGLETON_OBJ(kEmptyDescriptors, Object::empty_descriptors().raw());
+                        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().raw());
+                        Object::empty_var_descriptors().ptr());
   READ_VM_SINGLETON_OBJ(kEmptyExceptionHandlers,
-                        Object::empty_exception_handlers().raw());
+                        Object::empty_exception_handlers().ptr());
 
   // Check if it is a double.
   if (object_id == kDoubleObject) {
@@ -839,7 +842,8 @@
   // Check it is a singleton class object.
   intptr_t class_id = ClassIdFromObjectId(object_id);
   if (IsSingletonClassId(class_id)) {
-    return isolate()->class_table()->At(class_id);  // get singleton class.
+    return isolate_group()->class_table()->At(
+        class_id);  // get singleton class.
   }
 
   // Check if it is a singleton Argument descriptor object.
@@ -863,7 +867,8 @@
 ObjectPtr SnapshotReader::ReadIndexedObject(intptr_t object_id) {
   intptr_t class_id = ClassIdFromObjectId(object_id);
   if (IsBootstrapedClassId(class_id)) {
-    return isolate()->class_table()->At(class_id);  // get singleton class.
+    return isolate_group()->class_table()->At(
+        class_id);  // get singleton class.
   }
   if (IsObjectStoreTypeId(object_id)) {
     return GetType(object_store(), object_id);  // return type obj.
@@ -873,7 +878,7 @@
   if (index < max_vm_isolate_object_id_) {
     return VmIsolateSnapshotObject(index);
   }
-  return GetBackRef(object_id)->raw();
+  return GetBackRef(object_id)->ptr();
 }
 
 void SnapshotReader::ArrayReadFrom(intptr_t object_id,
@@ -884,7 +889,7 @@
   *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject);
   result.SetTypeArguments(*TypeArgumentsHandle());
 
-  bool as_reference = ObjectLayout::IsCanonical(tags) ? false : true;
+  bool as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
   for (intptr_t i = 0; i < len; i++) {
     *PassiveObjectHandle() = ReadObjectImpl(as_reference);
     result.SetAt(i, *PassiveObjectHandle());
@@ -911,8 +916,8 @@
     : BaseWriter(initial_size),
       thread_(thread),
       kind_(kind),
-      object_store_(isolate()->object_store()),
-      class_table_(isolate()->class_table()),
+      object_store_(isolate_group()->object_store()),
+      class_table_(isolate_group()->class_table()),
       forward_list_(forward_list),
       exception_type_(Exceptions::kNone),
       exception_msg_(NULL),
@@ -926,25 +931,25 @@
 }
 
 uint32_t SnapshotWriter::GetObjectTags(ObjectPtr raw) {
-  uword tags = raw->ptr()->tags_;
+  uword tags = raw->untag()->tags_;
 #if defined(HASH_IN_OBJECT_HEADER)
   // Clear hash to make the narrowing cast safe / appease UBSAN.
-  tags = ObjectLayout::HashTag::update(0, tags);
+  tags = UntaggedObject::HashTag::update(0, tags);
 #endif
   return tags;
 }
 
-uint32_t SnapshotWriter::GetObjectTags(ObjectLayout* raw) {
+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 = ObjectLayout::HashTag::update(0, tags);
+  tags = UntaggedObject::HashTag::update(0, tags);
 #endif
   return tags;
 }
 
 uword SnapshotWriter::GetObjectTagsAndHash(ObjectPtr raw) {
-  return raw->ptr()->tags_;
+  return raw->untag()->tags_;
 }
 
 #define VM_OBJECT_CLASS_LIST(V)                                                \
@@ -958,7 +963,7 @@
   case clazz::kClassId: {                                                      \
     object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);       \
     clazz##Ptr raw_obj = static_cast<clazz##Ptr>(rawobj);                      \
-    raw_obj->ptr()->WriteTo(this, object_id, kind(), false);                   \
+    raw_obj->untag()->WriteTo(this, object_id, kind(), false);                 \
     return true;                                                               \
   }
 
@@ -971,28 +976,28 @@
 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().raw(), kSentinelObject);
-  WRITE_VM_SINGLETON_OBJ(Object::transition_sentinel().raw(),
+  WRITE_VM_SINGLETON_OBJ(Object::sentinel().ptr(), kSentinelObject);
+  WRITE_VM_SINGLETON_OBJ(Object::transition_sentinel().ptr(),
                          kTransitionSentinelObject);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_array().raw(), kEmptyArrayObject);
-  WRITE_VM_SINGLETON_OBJ(Object::zero_array().raw(), kZeroArrayObject);
-  WRITE_VM_SINGLETON_OBJ(Object::dynamic_type().raw(), kDynamicType);
-  WRITE_VM_SINGLETON_OBJ(Object::void_type().raw(), kVoidType);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_type_arguments().raw(),
+  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().raw(), kTrueValue);
-  WRITE_VM_SINGLETON_OBJ(Bool::False().raw(), kFalseValue);
-  WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_types().raw(),
+  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().raw(),
+  WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_names().ptr(),
                          kExtractorParameterNames);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_context_scope().raw(),
+  WRITE_VM_SINGLETON_OBJ(Object::empty_context_scope().ptr(),
                          kEmptyContextScopeObject);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_object_pool().raw(), kEmptyObjectPool);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_descriptors().raw(), kEmptyDescriptors);
-  WRITE_VM_SINGLETON_OBJ(Object::empty_var_descriptors().raw(),
+  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().raw(),
+  WRITE_VM_SINGLETON_OBJ(Object::empty_exception_handlers().ptr(),
                          kEmptyExceptionHandlers);
 
   // Check if it is a singleton class object which is shared by
@@ -1000,7 +1005,7 @@
   intptr_t id = rawobj->GetClassId();
   if (id == kClassCid) {
     ClassPtr raw_class = static_cast<ClassPtr>(rawobj);
-    intptr_t class_id = raw_class->ptr()->id_;
+    intptr_t class_id = raw_class->untag()->id_;
     if (IsSingletonClassId(class_id)) {
       intptr_t object_id = ObjectIdFromClassId(class_id);
       WriteVMIsolateObject(object_id);
@@ -1033,7 +1038,7 @@
     return true;
   } else {
     // We do this check down here, because it's quite expensive.
-    if (!rawobj->ptr()->InVMIsolateHeap()) {
+    if (!rawobj->untag()->InVMIsolateHeap()) {
       return false;
     }
 
@@ -1042,7 +1047,7 @@
       case kTypedDataUint32ArrayCid: {
         object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);
         TypedDataPtr raw_obj = static_cast<TypedDataPtr>(rawobj);
-        raw_obj->ptr()->WriteTo(this, object_id, kind(), false);
+        raw_obj->untag()->WriteTo(this, object_id, kind(), false);
         return true;
       }
       default:
@@ -1091,7 +1096,7 @@
 intptr_t ForwardList::FindObject(ObjectPtr raw) {
   NoSafepointScope no_safepoint;
   intptr_t id = GetObjectId(raw);
-  ASSERT(id == 0 || NodeForObjectId(id)->obj()->raw() == raw);
+  ASSERT(id == 0 || NodeForObjectId(id)->obj()->ptr() == raw);
   return (id == 0) ? static_cast<intptr_t>(kInvalidIndex) : id;
 }
 
@@ -1130,7 +1135,7 @@
   if ((kind_ == Snapshot::kMessage) && (cid == kDoubleCid)) {
     WriteVMIsolateObject(kDoubleObject);
     DoublePtr rd = static_cast<DoublePtr>(rawobj);
-    WriteDouble(rd->ptr()->value_);
+    WriteDouble(rd->untag()->value_);
     return true;
   }
 
@@ -1160,7 +1165,7 @@
   // 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->ptr()->id_;
+    intptr_t class_id = raw_class->untag()->id_;
     if (IsBootstrapedClassId(class_id)) {
       intptr_t object_id = ObjectIdFromClassId(class_id);
       WriteIndexedObject(object_id);
@@ -1186,7 +1191,7 @@
 
   // 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->ptr()->IsCanonical();
+  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
@@ -1211,9 +1216,9 @@
                                            intptr_t object_id,
                                            bool as_reference) {
   NoSafepointScope no_safepoint;
-  ClassPtr cls = class_table_->At(ObjectLayout::ClassIdTag::decode(tags));
-  intptr_t class_id = cls->ptr()->id_;
-  ASSERT(class_id == ObjectLayout::ClassIdTag::decode(tags));
+  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;
@@ -1222,7 +1227,7 @@
 #define SNAPSHOT_WRITE(clazz)                                                  \
   case clazz::kClassId: {                                                      \
     clazz##Ptr raw_obj = static_cast<clazz##Ptr>(raw);                         \
-    raw_obj->ptr()->WriteTo(this, object_id, kind_, as_reference);             \
+    raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);           \
     return;                                                                    \
   }
 
@@ -1232,7 +1237,7 @@
 
     CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
       TypedDataPtr raw_obj = static_cast<TypedDataPtr>(raw);
-      raw_obj->ptr()->WriteTo(this, object_id, kind_, as_reference);
+      raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
       return;
     }
 #undef SNAPSHOT_WRITE
@@ -1240,7 +1245,7 @@
 
     CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
       ExternalTypedDataPtr raw_obj = static_cast<ExternalTypedDataPtr>(raw);
-      raw_obj->ptr()->WriteTo(this, object_id, kind_, as_reference);
+      raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
       return;
     }
 #undef SNAPSHOT_WRITE
@@ -1249,7 +1254,7 @@
     case kByteDataViewCid:
       CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
         auto raw_obj = static_cast<TypedDataViewPtr>(raw);
-        raw_obj->ptr()->WriteTo(this, object_id, kind_, as_reference);
+        raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
         return;
       }
 #undef SNAPSHOT_WRITE
@@ -1307,7 +1312,7 @@
        ++id) {
     if (!NodeForObjectId(id)->is_serialized()) {
       // Write the object out in the stream.
-      ObjectPtr raw = NodeForObjectId(id)->obj()->raw();
+      ObjectPtr raw = NodeForObjectId(id)->obj()->ptr();
       writer->VisitObject(raw);
 
       // Mark object as serialized.
@@ -1317,7 +1322,7 @@
   first_unprocessed_object_id_ = next_object_id();
 }
 
-void SnapshotWriter::WriteClassId(ClassLayout* cls) {
+void SnapshotWriter::WriteClassId(UntaggedClass* cls) {
   ASSERT(!Snapshot::IsFull(kind_));
   int class_id = cls->id_;
   ASSERT(!IsSingletonClassId(class_id) && !IsBootstrapedClassId(class_id));
@@ -1325,7 +1330,7 @@
   // Write out the library url and class name.
   LibraryPtr library = cls->library();
   ASSERT(library != Library::null());
-  WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
+  WriteObjectImpl(library->untag()->url_, kAsInlinedObject);
   WriteObjectImpl(cls->name(), kAsInlinedObject);
 }
 
@@ -1346,11 +1351,11 @@
   // Write out the library url, class name and signature function name.
   ClassPtr cls = GetFunctionOwner(func);
   ASSERT(cls != Class::null());
-  LibraryPtr library = cls->ptr()->library();
+  LibraryPtr library = cls->untag()->library();
   ASSERT(library != Library::null());
-  WriteObjectImpl(library->ptr()->url(), kAsInlinedObject);
-  WriteObjectImpl(cls->ptr()->name(), kAsInlinedObject);
-  WriteObjectImpl(func->ptr()->name(), kAsInlinedObject);
+  WriteObjectImpl(library->untag()->url(), kAsInlinedObject);
+  WriteObjectImpl(cls->untag()->name(), kAsInlinedObject);
+  WriteObjectImpl(func->untag()->name(), kAsInlinedObject);
   WriteObjectImpl(delayed_type_arguments, kAsInlinedObject);
 }
 
@@ -1388,7 +1393,7 @@
     WriteObjectImpl(type_arguments, kAsInlinedObject);
 
     // Write out the individual object ids.
-    bool write_as_reference = ObjectLayout::IsCanonical(tags) ? false : true;
+    bool write_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
     for (intptr_t i = 0; i < len; i++) {
       WriteObjectImpl(data[i], write_as_reference);
     }
@@ -1398,7 +1403,7 @@
 FunctionPtr SnapshotWriter::IsSerializableClosure(ClosurePtr closure) {
   // Extract the function object to check if this closure
   // can be sent in an isolate message.
-  FunctionPtr func = closure->ptr()->function();
+  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() &&
@@ -1422,18 +1427,18 @@
 }
 
 ClassPtr SnapshotWriter::GetFunctionOwner(FunctionPtr func) {
-  ObjectPtr owner = func->ptr()->owner();
+  ObjectPtr owner = func->untag()->owner();
   uword tags = GetObjectTags(owner);
-  intptr_t class_id = ObjectLayout::ClassIdTag::decode(tags);
+  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)->ptr()->patched_class_;
+  return static_cast<PatchClassPtr>(owner)->untag()->patched_class_;
 }
 
 void SnapshotWriter::CheckForNativeFields(ClassPtr cls) {
-  if (cls->ptr()->num_native_fields_ != 0) {
+  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);
@@ -1458,7 +1463,7 @@
                                    intptr_t tags,
                                    intptr_t object_id,
                                    bool as_reference) {
-  // Closure instances are handled by ClosureLayout::WriteTo().
+  // 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.
@@ -1493,24 +1498,24 @@
     WriteObjectImpl(cls, kAsInlinedObject);
 
     const auto unboxed_fields =
-        isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            cls->ptr()->id_);
+        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 = ObjectLayout::IsCanonical(tags) ? false : true;
+    bool write_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
 
     intptr_t offset = Instance::NextFieldOffset();
     while (offset < next_field_offset) {
       if (unboxed_fields.Get(offset / kWordSize)) {
         // Writes 32 bits of the unboxed value at a time
         const uword value = *reinterpret_cast<uword*>(
-            reinterpret_cast<uword>(raw->ptr()) + offset);
+            reinterpret_cast<uword>(raw->untag()) + offset);
         WriteWordWith32BitWrites(value);
       } else {
         ObjectPtr raw_obj = *reinterpret_cast<ObjectPtr*>(
-            reinterpret_cast<uword>(raw->ptr()) + offset);
+            reinterpret_cast<uword>(raw->untag()) + offset);
         WriteObjectImpl(raw_obj, write_as_reference);
       }
       offset += kWordSize;
@@ -1540,7 +1545,7 @@
   {
     NoSafepointScope no_safepoint;
     ErrorPtr error = thread()->StealStickyError();
-    ASSERT(error == Object::snapshot_writer_error().raw());
+    ASSERT(error == Object::snapshot_writer_error().ptr());
   }
 
   if (msg != NULL) {
@@ -1605,7 +1610,7 @@
     LongJumpScope jump;
     if (setjmp(*jump.Set()) == 0) {
       NoSafepointScope no_safepoint;
-      WriteObject(obj.raw());
+      WriteObject(obj.ptr());
     } else {
       FreeBuffer();
       has_exception = true;
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 2d15658..d526847 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -258,9 +258,10 @@
   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()->object_store(); }
-  ClassTable* class_table() const { return isolate()->class_table(); }
+  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_; }
@@ -400,10 +401,10 @@
   friend class PatchClass;
   friend class RegExp;
   friend class Script;
-  friend class SignatureData;
   friend class SubtypeTestCache;
   friend class TransferableTypedData;
   friend class Type;
+  friend class FunctionType;
   friend class TypedDataView;
   friend class TypeArguments;
   friend class TypeParameter;
@@ -590,13 +591,14 @@
   Thread* thread() const { return thread_; }
   Zone* zone() const { return thread_->zone(); }
   Isolate* isolate() const { return thread_->isolate(); }
-  Heap* heap() const { return isolate()->heap(); }
+  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(ObjectLayout* raw);
+  static uint32_t GetObjectTags(UntaggedObject* raw);
   static uword GetObjectTagsAndHash(ObjectPtr raw);
 
   Exceptions::ExceptionType exception_type() const { return exception_type_; }
@@ -622,7 +624,7 @@
   bool CheckAndWritePredefinedObject(ObjectPtr raw);
   bool HandleVMIsolateObject(ObjectPtr raw);
 
-  void WriteClassId(ClassLayout* cls);
+  void WriteClassId(UntaggedClass* cls);
   void WriteObjectImpl(ObjectPtr raw, bool as_reference);
   void WriteMarkedObjectImpl(ObjectPtr raw,
                              intptr_t tags,
@@ -659,36 +661,37 @@
   const char* exception_msg_;  // Message associated with exception.
   bool can_send_any_object_;   // True if any Dart instance can be sent.
 
-  friend class ArrayLayout;
-  friend class ClassLayout;
-  friend class CodeLayout;
-  friend class ContextScopeLayout;
-  friend class DynamicLibraryLayout;
-  friend class ExceptionHandlersLayout;
-  friend class FieldLayout;
-  friend class FunctionLayout;
-  friend class GrowableObjectArrayLayout;
-  friend class ImmutableArrayLayout;
-  friend class InstructionsLayout;
-  friend class LibraryLayout;
-  friend class LinkedHashMapLayout;
-  friend class LocalVarDescriptorsLayout;
-  friend class MirrorReferenceLayout;
-  friend class ObjectPoolLayout;
-  friend class PointerLayout;
-  friend class ReceivePortLayout;
-  friend class RegExpLayout;
-  friend class ScriptLayout;
-  friend class StackTraceLayout;
-  friend class SubtypeTestCacheLayout;
-  friend class TransferableTypedDataLayout;
-  friend class TypeLayout;
-  friend class TypeArgumentsLayout;
-  friend class TypeParameterLayout;
-  friend class TypeRefLayout;
-  friend class TypedDataViewLayout;
-  friend class UserTagLayout;
-  friend class WeakSerializationReferenceLayout;
+  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);
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index f793f2e..16bce51 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -29,7 +29,7 @@
   }
   if (expected.IsSmi()) {
     if (actual.IsSmi()) {
-      return expected.raw() == actual.raw();
+      return expected.ptr() == actual.ptr();
     }
     return false;
   }
@@ -37,15 +37,15 @@
     if (actual.IsDouble()) {
       Double& dbl1 = Double::Handle();
       Double& dbl2 = Double::Handle();
-      dbl1 ^= expected.raw();
-      dbl2 ^= actual.raw();
+      dbl1 ^= expected.ptr();
+      dbl2 ^= actual.ptr();
       return dbl1.value() == dbl2.value();
     }
     return false;
   }
   if (expected.IsBool()) {
     if (actual.IsBool()) {
-      return expected.raw() == actual.raw();
+      return expected.ptr() == actual.ptr();
     }
     return false;
   }
@@ -2064,8 +2064,9 @@
     Type& type = Type::Handle();
     type ^= Api::UnwrapHandle(cls);  // Dart_GetClass actually returns a Type.
     const Class& clazz = Class::Handle(type.type_class());
-    const bool required = clazz.RequireLegacyErasureOfConstants(zone.GetZone());
-    EXPECT(required == isolate->null_safety());
+    const bool required =
+        clazz.RequireCanonicalTypeErasureOfConstants(zone.GetZone());
+    EXPECT(required == isolate->group()->null_safety());
 
     // Verify that snapshot writing succeeds if erasure is not required.
     if (!required) {
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 3f074ff..03eaf12 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -6,6 +6,7 @@
 #include "vm/source_report.h"
 
 #include "vm/bit_vector.h"
+#include "vm/closure_functions_cache.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/isolate.h"
 #include "vm/kernel_loader.h"
@@ -26,8 +27,8 @@
       compile_mode_(compile_mode),
       thread_(NULL),
       script_(NULL),
-      start_pos_(TokenPosition::kNoSource),
-      end_pos_(TokenPosition::kNoSource),
+      start_pos_(TokenPosition::kMinSource),
+      end_pos_(TokenPosition::kMaxSource),
       profile_(Isolate::Current()),
       next_script_index_(0) {}
 
@@ -51,8 +52,8 @@
                         TokenPosition end_pos) {
   thread_ = thread;
   script_ = script;
-  start_pos_ = start_pos;
-  end_pos_ = end_pos;
+  start_pos_ = TokenPosition::Max(start_pos, TokenPosition::kMinSource);
+  end_pos_ = TokenPosition::Min(end_pos, TokenPosition::kMaxSource);
   ClearScriptTable();
   if (IsReportRequested(kProfile)) {
     // Build the profile.
@@ -75,14 +76,11 @@
   }
 
   if (script_ != NULL && !script_->IsNull()) {
-    if (func.script() != script_->raw()) {
+    if (func.script() != script_->ptr()) {
       // The function is from the wrong script.
       return true;
     }
-    if (((start_pos_ > TokenPosition::kMinSource) &&
-         (func.end_token_pos() < start_pos_)) ||
-        ((end_pos_ > TokenPosition::kMinSource) &&
-         (func.token_pos() > end_pos_))) {
+    if ((func.end_token_pos() < start_pos_) || (func.token_pos() > end_pos_)) {
       // The function does not intersect with the requested token range.
       return true;
     }
@@ -92,14 +90,14 @@
   if (func.ForceOptimize()) return true;
 
   switch (func.kind()) {
-    case FunctionLayout::kRegularFunction:
-    case FunctionLayout::kClosureFunction:
-    case FunctionLayout::kImplicitClosureFunction:
-    case FunctionLayout::kImplicitStaticGetter:
-    case FunctionLayout::kFieldInitializer:
-    case FunctionLayout::kGetterFunction:
-    case FunctionLayout::kSetterFunction:
-    case FunctionLayout::kConstructor:
+    case UntaggedFunction::kRegularFunction:
+    case UntaggedFunction::kClosureFunction:
+    case UntaggedFunction::kImplicitClosureFunction:
+    case UntaggedFunction::kImplicitStaticGetter:
+    case UntaggedFunction::kFieldInitializer:
+    case UntaggedFunction::kGetterFunction:
+    case UntaggedFunction::kSetterFunction:
+    case UntaggedFunction::kConstructor:
       break;
     default:
       return true;
@@ -125,14 +123,12 @@
   }
 
   if (script_ != NULL && !script_->IsNull()) {
-    if (field.Script() != script_->raw()) {
+    if (field.Script() != script_->ptr()) {
       // The field is from the wrong script.
       return true;
     }
-    if (((start_pos_ > TokenPosition::kMinSource) &&
-         (field.end_token_pos() < start_pos_)) ||
-        ((end_pos_ > TokenPosition::kMinSource) &&
-         (field.token_pos() > end_pos_))) {
+    if ((field.end_token_pos() < start_pos_) ||
+        (field.token_pos() > end_pos_)) {
       // The field does not intersect with the requested token range.
       return true;
     }
@@ -144,7 +140,7 @@
   ScriptTableEntry wrapper;
   const String& url = String::Handle(zone(), script.url());
   wrapper.key = &url;
-  wrapper.script = &Script::Handle(zone(), script.raw());
+  wrapper.script = &Script::Handle(zone(), script.ptr());
   ScriptTableEntry* pair = script_table_.LookupValue(&wrapper);
   if (pair != NULL) {
     return pair->index;
@@ -173,7 +169,7 @@
     ASSERT(url2.Equals(*url));
     ScriptTableEntry wrapper;
     wrapper.key = &url2;
-    wrapper.script = &Script::Handle(zone(), script->raw());
+    wrapper.script = &Script::Handle(zone(), script->ptr());
     ScriptTableEntry* pair = script_table_.LookupValue(&wrapper);
     ASSERT(i == pair->index);
   }
@@ -184,7 +180,7 @@
                                            const Library& lib) {
   const Array& scripts = Array::Handle(zone(), lib.LoadedScripts());
   for (intptr_t j = 0; j < scripts.Length(); j++) {
-    if (scripts.At(j) == script.raw()) {
+    if (scripts.At(j) == script.ptr()) {
       return true;
     }
   }
@@ -195,9 +191,8 @@
                                       const Function& function,
                                       const Code& code) {
   ASSERT(!code.IsNull());
-  const TokenPosition begin_pos = function.token_pos();
-  const TokenPosition end_pos = function.end_token_pos();
-
+  const TokenPosition& begin_pos = function.token_pos();
+  const TokenPosition& end_pos = function.end_token_pos();
   ZoneGrowableArray<const ICData*>* ic_data_array =
       new (zone()) ZoneGrowableArray<const ICData*>();
   function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
@@ -208,14 +203,14 @@
 
   PcDescriptors::Iterator iter(
       descriptors,
-      PcDescriptorsLayout::kIcCall | PcDescriptorsLayout::kUnoptStaticCall);
+      UntaggedPcDescriptors::kIcCall | UntaggedPcDescriptors::kUnoptStaticCall);
   while (iter.MoveNext()) {
     HANDLESCOPE(thread());
     ASSERT(iter.DeoptId() < ic_data_array->length());
     const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
     if (ic_data != NULL) {
-      const TokenPosition token_pos = iter.TokenPos();
-      if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+      const TokenPosition& token_pos = iter.TokenPos();
+      if (!token_pos.IsWithin(begin_pos, end_pos)) {
         // Does not correspond to a valid source position.
         continue;
       }
@@ -228,8 +223,8 @@
                                      const Function& function,
                                      const Code& code) {
   ASSERT(!code.IsNull());
-  const TokenPosition begin_pos = function.token_pos();
-  const TokenPosition end_pos = function.end_token_pos();
+  const TokenPosition& begin_pos = function.token_pos();
+  const TokenPosition& end_pos = function.end_token_pos();
 
   ZoneGrowableArray<const ICData*>* ic_data_array =
       new (zone()) ZoneGrowableArray<const ICData*>();
@@ -241,7 +236,7 @@
   const int kCoverageMiss = 1;
   const int kCoverageHit = 2;
 
-  intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
+  intptr_t func_length = function.SourceSize() + 1;
   GrowableArray<char> coverage(func_length);
   coverage.SetLength(func_length);
   for (int i = 0; i < func_length; i++) {
@@ -256,14 +251,14 @@
 
   PcDescriptors::Iterator iter(
       descriptors,
-      PcDescriptorsLayout::kIcCall | PcDescriptorsLayout::kUnoptStaticCall);
+      UntaggedPcDescriptors::kIcCall | UntaggedPcDescriptors::kUnoptStaticCall);
   while (iter.MoveNext()) {
     HANDLESCOPE(thread());
     ASSERT(iter.DeoptId() < ic_data_array->length());
     const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
     if (ic_data != NULL) {
-      const TokenPosition token_pos = iter.TokenPos();
-      if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+      const TokenPosition& token_pos = iter.TokenPos();
+      if (!token_pos.IsWithin(begin_pos, end_pos)) {
         // Does not correspond to a valid source position.
         continue;
       }
@@ -303,25 +298,25 @@
 void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
                                                 const Function& func,
                                                 const Code& code) {
-  const TokenPosition begin_pos = func.token_pos();
-  const TokenPosition end_pos = func.end_token_pos();
-  intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
+  const TokenPosition& begin_pos = func.token_pos();
+  const TokenPosition& end_pos = func.end_token_pos();
+  intptr_t func_length = func.SourceSize() + 1;
 
   BitVector possible(zone(), func_length);
 
   ASSERT(!code.IsNull());
 
-  const uint8_t kSafepointKind =
-      (PcDescriptorsLayout::kIcCall | PcDescriptorsLayout::kUnoptStaticCall |
-       PcDescriptorsLayout::kRuntimeCall);
+  const uint8_t kSafepointKind = (UntaggedPcDescriptors::kIcCall |
+                                  UntaggedPcDescriptors::kUnoptStaticCall |
+                                  UntaggedPcDescriptors::kRuntimeCall);
 
   const PcDescriptors& descriptors =
       PcDescriptors::Handle(zone(), code.pc_descriptors());
 
   PcDescriptors::Iterator iter(descriptors, kSafepointKind);
   while (iter.MoveNext()) {
-    const TokenPosition token_pos = iter.TokenPos();
-    if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+    const TokenPosition& token_pos = iter.TokenPos();
+    if (!token_pos.IsWithin(begin_pos, end_pos)) {
       // Does not correspond to a valid source position.
       continue;
     }
@@ -357,7 +352,7 @@
       for (intptr_t i = 0; i < profile_function->NumSourcePositions(); i++) {
         const ProfileFunctionSourcePosition& position =
             profile_function->GetSourcePosition(i);
-        if (position.token_pos().IsSourcePosition()) {
+        if (position.token_pos().IsReal()) {
           // Add as an integer.
           positions.AddValue(position.token_pos().Pos());
         } else {
@@ -510,7 +505,7 @@
     for (int i = 0; i < functions.Length(); i++) {
       func ^= functions.At(i);
       // Skip getter functions of static const field.
-      if (func.kind() == FunctionLayout::kImplicitStaticGetter) {
+      if (func.kind() == UntaggedFunction::kImplicitStaticGetter) {
         field ^= func.accessor_field();
         if (field.is_const() && field.is_static()) {
           continue;
@@ -528,16 +523,10 @@
 }
 
 void SourceReport::VisitClosures(JSONArray* jsarr) {
-  const GrowableObjectArray& closures = GrowableObjectArray::Handle(
-      thread()->isolate()->object_store()->closure_functions());
-
-  // We need to keep rechecking the length of the closures array, as handling
-  // a closure potentially adds new entries to the end.
-  Function& func = Function::Handle(zone());
-  for (int i = 0; i < closures.Length(); i++) {
-    func ^= closures.At(i);
+  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& func) {
     VisitFunction(jsarr, func);
-  }
+    return true;  // Continue iteration.
+  });
 }
 
 void SourceReport::PrintJSON(JSONStream* js,
@@ -552,7 +541,7 @@
     JSONArray ranges(&report, "ranges");
 
     const GrowableObjectArray& libs = GrowableObjectArray::Handle(
-        zone(), thread()->isolate()->object_store()->libraries());
+        zone(), thread()->isolate_group()->object_store()->libraries());
 
     // We only visit the libraries which actually load the specified script.
     Library& lib = Library::Handle(zone());
@@ -590,7 +579,7 @@
     GrowableArray<ScriptTableEntry*>* local_script_table_entries) {
   ScriptTableEntry wrapper;
   const GrowableObjectArray& libs = GrowableObjectArray::Handle(
-      zone(), thread()->isolate()->object_store()->libraries());
+      zone(), thread()->isolate_group()->object_store()->libraries());
   Library& lib = Library::Handle(zone());
   Script& scriptRef = Script::Handle(zone());
   for (int i = 0; i < libs.Length(); i++) {
@@ -600,7 +589,7 @@
       scriptRef ^= scripts.At(j);
       const String& url = String::Handle(zone(), scriptRef.url());
       wrapper.key = &url;
-      wrapper.script = &Script::Handle(zone(), scriptRef.raw());
+      wrapper.script = &Script::Handle(zone(), scriptRef.ptr());
       ScriptTableEntry* pair = local_script_table->LookupValue(&wrapper);
       if (pair != NULL) {
         // Existing one.
@@ -634,13 +623,6 @@
   // Now output the wanted constant coverage.
   for (intptr_t i = 0; i < local_script_table_entries->length(); i++) {
     const Script* script = local_script_table_entries->At(i)->script;
-    bool script_ok = true;
-    if (script_ != NULL && !script_->IsNull()) {
-      if (script->raw() != script_->raw()) {
-        // This is the wrong script.
-        script_ok = false;
-      }
-    }
 
     // Whether we want *this* script or not we need to look at the constant
     // constructor coverage. Any of those could be in a script we *do* want.
diff --git a/runtime/vm/source_report.h b/runtime/vm/source_report.h
index 4ec20c9..08f0441 100644
--- a/runtime/vm/source_report.h
+++ b/runtime/vm/source_report.h
@@ -47,8 +47,8 @@
   // in the isolate.
   void PrintJSON(JSONStream* js,
                  const Script& script,
-                 TokenPosition start_pos = TokenPosition::kNoSource,
-                 TokenPosition end_pos = TokenPosition::kNoSource);
+                 TokenPosition start_pos = TokenPosition::kMinSource,
+                 TokenPosition end_pos = TokenPosition::kMaxSource);
 
  private:
   void ClearScriptTable();
@@ -108,7 +108,7 @@
     static inline intptr_t Hashcode(Key key) { return key->key->Hash(); }
 
     static inline bool IsKeyEqual(Pair kv, Key key) {
-      return kv->script->raw() == key->script->raw();
+      return kv->script->ptr() == key->script->ptr();
     }
   };
 
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 6d6f013..5a6c5a9 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -26,7 +26,7 @@
 
 namespace dart {
 
-const FrameLayout invalid_frame_layout = {
+const UntaggedFrame invalid_frame_layout = {
     /*.first_object_from_fp = */ -1,
     /*.last_fixed_object_from_fp = */ -1,
     /*.param_end_from_fp = */ -1,
@@ -38,7 +38,7 @@
     /*.exit_link_slot_from_entry_fp = */ -1,
 };
 
-const FrameLayout default_frame_layout = {
+const UntaggedFrame default_frame_layout = {
     /*.first_object_from_fp = */ kFirstObjectSlotFromFp,
     /*.last_fixed_object_from_fp = */ kLastFixedObjectSlotFromFp,
     /*.param_end_from_fp = */ kParamEndSlotFromFp,
@@ -49,7 +49,7 @@
     /*.code_from_fp = */ kPcMarkerSlotFromFp,
     /*.exit_link_slot_from_entry_fp = */ kExitLinkSlotFromEntryFp,
 };
-const FrameLayout bare_instructions_frame_layout = {
+const UntaggedFrame bare_instructions_frame_layout = {
     /*.first_object_from_pc =*/kFirstObjectSlotFromFp,  // No saved PP slot.
     /*.last_fixed_object_from_fp = */ kLastFixedObjectSlotFromFp +
         2,  // No saved CODE, PP slots
@@ -67,19 +67,19 @@
 namespace compiler {
 
 namespace target {
-FrameLayout frame_layout = invalid_frame_layout;
+UntaggedFrame frame_layout = invalid_frame_layout;
 }
 
 }  // namespace compiler
 
-FrameLayout runtime_frame_layout = invalid_frame_layout;
+UntaggedFrame runtime_frame_layout = invalid_frame_layout;
 
-int FrameLayout::FrameSlotForVariable(const LocalVariable* variable) const {
+int UntaggedFrame::FrameSlotForVariable(const LocalVariable* variable) const {
   ASSERT(!variable->is_captured());
   return this->FrameSlotForVariableIndex(variable->index().value());
 }
 
-int FrameLayout::FrameSlotForVariableIndex(int variable_index) const {
+int UntaggedFrame::FrameSlotForVariableIndex(int variable_index) const {
   // Variable indices are:
   //    [1, 2, ..., M] for the M parameters.
   //    [0, -1, -2, ... -(N-1)] for the N [LocalVariable]s
@@ -88,7 +88,7 @@
                              : (variable_index + param_end_from_fp);
 }
 
-void FrameLayout::Init() {
+void UntaggedFrame::Init() {
   // By default we use frames with CODE_REG/PP in the frame.
   compiler::target::frame_layout = default_frame_layout;
   runtime_frame_layout = default_frame_layout;
@@ -115,7 +115,7 @@
     ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
     return cid == kFunctionCid;
   }
-  code = ReversePc::Lookup(Dart::vm_isolate()->group(), pc(),
+  code = ReversePc::Lookup(Dart::vm_isolate_group(), pc(),
                            /*is_return_address=*/true);
   if (!code.IsNull()) {
     auto const cid = code.OwnerClassId();
@@ -137,7 +137,7 @@
     ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
     return cid == kNullCid || cid == kClassCid;
   }
-  code = ReversePc::Lookup(Dart::vm_isolate()->group(), pc(),
+  code = ReversePc::Lookup(Dart::vm_isolate_group(), pc(),
                            /*is_return_address=*/true);
   if (!code.IsNull()) {
     auto const cid = code.OwnerClassId();
@@ -248,15 +248,8 @@
     maps = code.compressed_stackmaps();
     CompressedStackMaps global_table;
 
-    // The GC does not have an active isolate, only an active isolate group,
-    // yet the global compressed stack map table is only stored in the object
-    // store. It has the same contents for all isolates, so we just pick the
-    // one from the first isolate here.
-    // TODO(dartbug.com/36097): Avoid having this per-isolate and instead store
-    // it per isolate group.
-    auto isolate = isolate_group()->isolates_.First();
-
-    global_table = isolate->object_store()->canonicalized_stack_map_entries();
+    global_table =
+        isolate_group()->object_store()->canonicalized_stack_map_entries();
     CompressedStackMaps::Iterator it(maps, global_table);
     const uword start = code.PayloadStart();
     const uint32_t pc_offset = pc() - start;
@@ -357,7 +350,7 @@
     if (code != Code::null()) {
       return code;
     }
-    code = ReversePc::Lookup(Dart::vm_isolate()->group(), pc(),
+    code = ReversePc::Lookup(Dart::vm_isolate_group(), pc(),
                              /*is_return_address=*/true);
     if (code != Code::null()) {
       return code;
@@ -408,7 +401,7 @@
 
   intptr_t try_index = -1;
   uword pc_offset = pc() - code.PayloadStart();
-  PcDescriptors::Iterator iter(descriptors, PcDescriptorsLayout::kAnyKind);
+  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     const intptr_t current_try_index = iter.TryIndex();
     if ((iter.PcOffset() == pc_offset) && (current_try_index != -1)) {
@@ -437,7 +430,7 @@
   const PcDescriptors& descriptors =
       PcDescriptors::Handle(code.pc_descriptors());
   ASSERT(!descriptors.IsNull());
-  PcDescriptors::Iterator iter(descriptors, PcDescriptorsLayout::kAnyKind);
+  PcDescriptors::Iterator iter(descriptors, UntaggedPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     if (iter.PcOffset() == pc_offset) {
       return TokenPosition(iter.TokenPos());
@@ -653,7 +646,7 @@
     : index_(0),
       num_materializations_(0),
       dest_frame_size_(0),
-      code_(Code::Handle(code.raw())),
+      code_(Code::Handle(code.ptr())),
       deopt_info_(TypedData::Handle()),
       function_(Function::Handle()),
       pc_(pc),
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index dff0279..92f864f 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -28,7 +28,7 @@
 class ObjectPointerVisitor;
 class LocalVariable;
 
-extern FrameLayout runtime_frame_layout;
+extern UntaggedFrame runtime_frame_layout;
 
 // Generic stack frame.
 class StackFrame : public ValueObject {
@@ -365,7 +365,7 @@
 
   FunctionPtr function() const {
     ASSERT(!Done());
-    return function_.raw();
+    return function_.ptr();
   }
 
   uword pc() const {
@@ -375,7 +375,7 @@
 
   CodePtr code() const {
     ASSERT(!Done());
-    return code_.raw();
+    return code_.ptr();
   }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/stack_frame_arm.h b/runtime/vm/stack_frame_arm.h
index eb8e104c..e79cc9c 100644
--- a/runtime/vm/stack_frame_arm.h
+++ b/runtime/vm/stack_frame_arm.h
@@ -68,6 +68,15 @@
 // kNativeCallbackTrampolineStackDelta must be added as well.
 constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
 
+// For FFI calls passing in TypedData, we save it on the stack before entering
+// a Dart frame. This denotes how to get to the backed up typed data.
+//
+// Note: This is not kCallerSpSlotFromFp on arm.
+//
+// [fp] holds callers fp, [fp+4] holds callers lr, [fp+8] is space for
+// return address, [fp+12] is our pushed TypedData pointer.
+static const int kFfiCallerTypedDataSlotFromFp = kCallerSpSlotFromFp + 1;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_ARM_H_
diff --git a/runtime/vm/stack_frame_arm64.h b/runtime/vm/stack_frame_arm64.h
index 3ede931..a487e67 100644
--- a/runtime/vm/stack_frame_arm64.h
+++ b/runtime/vm/stack_frame_arm64.h
@@ -67,6 +67,10 @@
 // kNativeCallbackTrampolineStackDelta must be added as well.
 constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
 
+// For FFI calls passing in TypedData, we save it on the stack before entering
+// a Dart frame. This denotes how to get to the backed up typed data.
+static const int kFfiCallerTypedDataSlotFromFp = kCallerSpSlotFromFp;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_ARM64_H_
diff --git a/runtime/vm/stack_frame_ia32.h b/runtime/vm/stack_frame_ia32.h
index 2c8edad..e1d16fe 100644
--- a/runtime/vm/stack_frame_ia32.h
+++ b/runtime/vm/stack_frame_ia32.h
@@ -57,6 +57,10 @@
 // kNativeCallbackTrampolineStackDelta must be added as well.
 constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 0;
 
+// For FFI calls passing in TypedData, we save it on the stack before entering
+// a Dart frame. This denotes how to get to the backed up typed data.
+static const int kFfiCallerTypedDataSlotFromFp = kCallerSpSlotFromFp;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_IA32_H_
diff --git a/runtime/vm/stack_frame_x64.h b/runtime/vm/stack_frame_x64.h
index 835a2f5..fd6176b 100644
--- a/runtime/vm/stack_frame_x64.h
+++ b/runtime/vm/stack_frame_x64.h
@@ -68,6 +68,10 @@
 constexpr intptr_t kCallbackSlotsBeforeSavedArguments =
     2 + CallingConventions::kShadowSpaceBytes / kWordSize;
 
+// For FFI calls passing in TypedData, we save it on the stack before entering
+// a Dart frame. This denotes how to get to the backed up typed data.
+static const int kFfiCallerTypedDataSlotFromFp = kCallerSpSlotFromFp;
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STACK_FRAME_X64_H_
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index fb01137..ae8849a 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -22,7 +22,7 @@
 intptr_t GetYieldIndex(const Closure& receiver_closure) {
   const auto& function = Function::Handle(receiver_closure.function());
   if (!function.IsAsyncClosure() && !function.IsAsyncGenClosure()) {
-    return PcDescriptorsLayout::kInvalidYieldIndex;
+    return UntaggedPcDescriptors::kInvalidYieldIndex;
   }
   const auto& await_jump_var =
       Object::Handle(Context::Handle(receiver_closure.context())
@@ -32,10 +32,10 @@
 }
 
 intptr_t FindPcOffset(const PcDescriptors& pc_descs, intptr_t yield_index) {
-  if (yield_index == PcDescriptorsLayout::kInvalidYieldIndex) {
+  if (yield_index == UntaggedPcDescriptors::kInvalidYieldIndex) {
     return 0;
   }
-  PcDescriptors::Iterator iter(pc_descs, PcDescriptorsLayout::kAnyKind);
+  PcDescriptors::Iterator iter(pc_descs, UntaggedPcDescriptors::kAnyKind);
   while (iter.MoveNext()) {
     if (iter.YieldIndex() == yield_index) {
       return iter.PcOffset();
@@ -161,7 +161,7 @@
   }
   ASSERT(callback_.IsClosure());
 
-  return Closure::Cast(callback_).raw();
+  return Closure::Cast(callback_).ptr();
 }
 
 ClosurePtr CallerClosureFinder::FindCallerInAsyncClosure(
@@ -200,8 +200,8 @@
   // callback we found.
   receiver_function_ = Closure::Cast(callback_).function();
   if (!receiver_function_.IsImplicitInstanceClosureFunction() ||
-      receiver_function_.Owner() != stream_iterator_class.raw()) {
-    return Closure::Cast(callback_).raw();
+      receiver_function_.Owner() != stream_iterator_class.ptr()) {
+    return Closure::Cast(callback_).ptr();
   }
 
   // All implicit closure functions (tear-offs) have the "this" receiver
@@ -292,8 +292,8 @@
     ObjectPtr arg = last_object_in_caller[i];
     if (arg->IsHeapObject() && arg->GetClassId() == kClosureCid) {
       closure = Closure::RawCast(arg);
-      if (closure.function() == function.raw()) {
-        return closure.raw();
+      if (closure.function() == function.ptr()) {
+        return closure.ptr();
       }
     }
   }
@@ -339,7 +339,7 @@
 
     // Add the current synchronous frame.
     code = frame->LookupDartCode();
-    ASSERT(function.raw() == code.function());
+    ASSERT(function.ptr() == code.function());
     code_array.Add(code);
     const intptr_t pc_offset = frame->pc() - code.PayloadStart();
     ASSERT(pc_offset > 0 && pc_offset <= code.Size());
@@ -446,7 +446,7 @@
 
     if (!async_function_is_null && !function_is_null &&
         function.parent_function() != Function::null()) {
-      if (async_function.raw() == function.parent_function()) {
+      if (async_function.ptr() == function.parent_function()) {
         if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
           ObjectPtr* last_caller_obj =
               reinterpret_cast<ObjectPtr*>(frame->GetCallerSp());
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 7f8f3a3..e41c642 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -58,7 +58,7 @@
       ObjectPool::Handle(ObjectPool::NewFromBuilder(object_pool_builder));
 
   for (size_t i = 0; i < ARRAY_SIZE(entries_); i++) {
-    entries_[i].code->set_object_pool(object_pool.raw());
+    entries_[i].code->set_object_pool(object_pool.ptr());
   }
 }
 
@@ -69,6 +69,9 @@
     const char* name,
     compiler::ObjectPoolBuilder* object_pool_builder,
     void (*GenerateStub)(compiler::Assembler* assembler)) {
+  auto thread = Thread::Current();
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+
   compiler::Assembler assembler(object_pool_builder);
   GenerateStub(&assembler);
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
@@ -79,7 +82,7 @@
     Disassembler::DisassembleStub(name, code);
   }
 #endif  // !PRODUCT
-  return code.raw();
+  return code.ptr();
 }
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
@@ -133,13 +136,13 @@
     view.Set<Code::kSCallTableKindAndOffset>(kind_type_and_offset);
     view.Set<Code::kSCallTableCodeOrTypeTarget>(unresolved_call->target());
   }
-  return static_calls_table.raw();
+  return static_calls_table.ptr();
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 CodePtr StubCode::GetAllocationStubForClass(const Class& cls) {
   Thread* thread = Thread::Current();
-  auto object_store = thread->isolate()->object_store();
+  auto object_store = thread->isolate_group()->object_store();
   Zone* zone = thread->zone();
   const Error& error =
       Error::Handle(zone, cls.EnsureIsAllocateFinalized(thread));
@@ -168,7 +171,7 @@
             : Code::PoolAttachment::kAttachPool;
 
     auto zone = thread->zone();
-    auto object_store = thread->isolate()->object_store();
+    auto object_store = thread->isolate_group()->object_store();
     auto& allocate_object_stub = Code::ZoneHandle(zone);
     auto& allocate_object_parametrized_stub = Code::ZoneHandle(zone);
     if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
@@ -188,11 +191,13 @@
         Array::Handle(zone, compiler::StubCodeCompiler::BuildStaticCallsTable(
                                 zone, &unresolved_calls));
 
+    SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+
     auto mutator_fun = [&]() {
       stub = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
                                 /*optimized=*/false,
                                 /*stats=*/nullptr);
-      // Check if background compilation thread has not already added the stub.
+      // Check if some other thread has not already added the stub.
       if (cls.allocation_stub() == Code::null()) {
         stub.set_owner(cls);
         if (!static_calls_table.IsNull()) {
@@ -201,32 +206,13 @@
         cls.set_allocation_stub(stub);
       }
     };
-    auto bg_compiler_fun = [&]() {
-      ASSERT(Thread::Current()->IsAtSafepoint());
-      stub = cls.allocation_stub();
-      // Check if stub was already generated.
-      if (!stub.IsNull()) {
-        return;
-      }
-      stub = Code::FinalizeCode(nullptr, &assembler, pool_attachment,
-                                /*optimized=*/false, /*stats=*/nullptr);
-      stub.set_owner(cls);
-      if (!static_calls_table.IsNull()) {
-        stub.set_static_calls_target_table(static_calls_table);
-      }
-      cls.set_allocation_stub(stub);
-    };
 
     // We have to ensure no mutators are running, because:
     //
     //   a) We allocate an instructions object, which might cause us to
     //      temporarily flip page protections from (RX -> RW -> RX).
-    //
-    //   b) To ensure only one thread succeeds installing an allocation for the
-    //      given class.
-    //
-    thread->isolate_group()->RunWithStoppedMutators(
-        mutator_fun, bg_compiler_fun, /*use_force_growth=*/true);
+    thread->isolate_group()->RunWithStoppedMutators(mutator_fun,
+                                                    /*use_force_growth=*/true);
 
     // We notify code observers after finalizing the code in order to be
     // outside a [SafepointOperationScope].
@@ -238,11 +224,11 @@
 #endif  // !PRODUCT
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
-  return stub.raw();
+  return stub.ptr();
 }
 
 CodePtr StubCode::GetAllocationStubForTypedData(classid_t class_id) {
-  auto object_store = Thread::Current()->isolate()->object_store();
+  auto object_store = Thread::Current()->isolate_group()->object_store();
   switch (class_id) {
     case kTypedDataInt8ArrayCid:
       return object_store->allocate_int8_array_stub();
@@ -283,7 +269,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
   auto thread = Thread::Current();
   auto Z = thread->zone();
-  auto object_store = thread->isolate()->object_store();
+  auto object_store = thread->isolate_group()->object_store();
 
   const auto& closure_class =
       Class::ZoneHandle(Z, object_store->closure_class());
@@ -310,7 +296,7 @@
     Disassembler::DisassembleStub(name, stub);
   }
 #endif  // !PRODUCT
-  return stub.raw();
+  return stub.ptr();
 #else   // !defined(DART_PRECOMPILED_RUNTIME)
   UNIMPLEMENTED();
   return nullptr;
@@ -340,7 +326,7 @@
     }
   }
 
-  auto object_store = Isolate::Current()->object_store();
+  auto object_store = IsolateGroup::Current()->object_store();
 
 #define MATCH(member, name)                                                    \
   if (object_store->member() != Code::null() &&                                \
diff --git a/runtime/vm/stub_code_arm64_test.cc b/runtime/vm/stub_code_arm64_test.cc
index 0939ef2..9814bba 100644
--- a/runtime/vm/stub_code_arm64_test.cc
+++ b/runtime/vm/stub_code_arm64_test.cc
@@ -28,9 +28,10 @@
       Class::New(lib, class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::ZoneHandle(Symbols::New(Thread::Current(), name));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   Function& function = Function::ZoneHandle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kNoSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
   return &function;
 }
 
@@ -59,6 +60,7 @@
   compiler::ObjectPoolBuilder object_pool_builder;
   compiler::Assembler assembler(&object_pool_builder);
   GenerateCallToCallRuntimeStub(&assembler, length);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler,
       Code::PoolAttachment::kAttachPool));
@@ -101,13 +103,14 @@
   compiler::Assembler assembler(&object_pool_builder);
   GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
                                     rhs_index_value, length_value);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
       Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Instance& result = Instance::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
-  EXPECT_EQ(Bool::True().raw(), result.raw());
+  EXPECT_EQ(Bool::True().ptr(), result.ptr());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index ea6a6bc..9fee1fd 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -28,9 +28,10 @@
       Class::New(lib, class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::ZoneHandle(Symbols::New(Thread::Current(), name));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   Function& function = Function::ZoneHandle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kNoSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
   return &function;
 }
 
@@ -58,6 +59,7 @@
   compiler::ObjectPoolBuilder object_pool_builder;
   compiler::Assembler assembler(&object_pool_builder);
   GenerateCallToCallRuntimeStub(&assembler, length);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler,
       Code::PoolAttachment::kAttachPool));
@@ -99,13 +101,14 @@
   compiler::Assembler assembler(&object_pool_builder);
   GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
                                     rhs_index_value, length_value);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
       Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Instance& result = Instance::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
-  EXPECT_EQ(Bool::True().raw(), result.raw());
+  EXPECT_EQ(Bool::True().ptr(), result.ptr());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc
index b5c4388..13473ad 100644
--- a/runtime/vm/stub_code_ia32_test.cc
+++ b/runtime/vm/stub_code_ia32_test.cc
@@ -28,9 +28,10 @@
       Class::New(lib, class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::ZoneHandle(Symbols::New(Thread::Current(), name));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   Function& function = Function::ZoneHandle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kMinSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kMinSource));
   return &function;
 }
 
@@ -58,6 +59,7 @@
   const char* kName = "Test_CallRuntimeStubCode";
   compiler::Assembler assembler(nullptr);
   GenerateCallToCallRuntimeStub(&assembler, length);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler,
       Code::PoolAttachment::kAttachPool));
@@ -103,13 +105,14 @@
   compiler::Assembler assembler(nullptr);
   GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
                                     rhs_index_value, length_value);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
       Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Instance& result = Instance::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
-  EXPECT_EQ(Bool::True().raw(), result.raw());
+  EXPECT_EQ(Bool::True().ptr(), result.ptr());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/stub_code_test.cc b/runtime/vm/stub_code_test.cc
index 4b8649b..25d1d46 100644
--- a/runtime/vm/stub_code_test.cc
+++ b/runtime/vm/stub_code_test.cc
@@ -18,9 +18,10 @@
   const Class& owner_class = Class::Handle(
       Class::New(lib, class_name, script, TokenPosition::kNoSource));
   const String& function_name = String::ZoneHandle(Symbols::New(thread, name));
-  const Function& function = Function::ZoneHandle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kMinSource));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
+  Function& function = Function::ZoneHandle(Function::New(
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
   const Array& functions = Array::Handle(Array::New(1));
   functions.SetAt(0, function);
   {
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index b41ec88..c586af8 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -28,9 +28,10 @@
       Class::New(lib, class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::ZoneHandle(Symbols::New(Thread::Current(), name));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   Function& function = Function::ZoneHandle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kNoSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
   return &function;
 }
 
@@ -59,6 +60,7 @@
   compiler::ObjectPoolBuilder object_pool_builder;
   compiler::Assembler assembler(&object_pool_builder);
   GenerateCallToCallRuntimeStub(&assembler, length);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       *CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler,
       Code::PoolAttachment::kAttachPool));
@@ -101,13 +103,14 @@
   compiler::Assembler assembler(&object_pool_builder);
   GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
                                     rhs_index_value, length_value);
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   const Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
       *CreateFunction("Test_CallLeafRuntimeStubCode"), nullptr, &assembler,
       Code::PoolAttachment::kAttachPool));
   const Function& function = RegisterFakeFunction(kName, code);
   Instance& result = Instance::Handle();
   result ^= DartEntry::InvokeFunction(function, Object::empty_array());
-  EXPECT_EQ(Bool::True().raw(), result.raw());
+  EXPECT_EQ(Bool::True().ptr(), result.ptr());
 }
 
 }  // namespace dart
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index fac122b..5da457a 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -47,13 +47,13 @@
 StringPtr StringSlice::ToSymbol() const {
   if (is_all() && str_.IsOld()) {
     str_.SetCanonical();
-    return str_.raw();
+    return str_.ptr();
   } else {
     String& result =
         String::Handle(String::SubString(str_, begin_index_, len_, Heap::kOld));
     result.SetCanonical();
     result.SetHash(hash_);
-    return result.raw();
+    return result.ptr();
   }
 }
 
@@ -61,7 +61,7 @@
   String& result = String::Handle(String::Concat(str1_, str2_, Heap::kOld));
   result.SetCanonical();
   result.SetHash(hash_);
-  return result.raw();
+  return result.ptr();
 }
 
 
@@ -79,19 +79,20 @@
   return *symbol_handles_[token_id];
 }
 
-void Symbols::Init(Isolate* vm_isolate) {
+void Symbols::Init(IsolateGroup* vm_isolate_group) {
   // Should only be run by the vm isolate.
-  ASSERT(Isolate::Current() == Dart::vm_isolate());
-  ASSERT(vm_isolate == Dart::vm_isolate());
+  ASSERT(IsolateGroup::Current() == Dart::vm_isolate_group());
+  ASSERT(vm_isolate_group == Dart::vm_isolate_group());
   Zone* zone = Thread::Current()->zone();
 
   // Create and setup a symbol table in the vm isolate.
-  SetupSymbolTable(vm_isolate);
+  SetupSymbolTable(vm_isolate_group);
 
   // Create all predefined symbols.
   ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kNullCharId);
 
-  CanonicalStringSet table(zone, vm_isolate->object_store()->symbol_table());
+  CanonicalStringSet table(zone,
+                           vm_isolate_group->object_store()->symbol_table());
 
   // First set up all the predefined string symbols.
   // Create symbols for language keywords. Some keywords are equal to
@@ -118,20 +119,21 @@
     *str ^= table.InsertOrGet(*str);
     ASSERT(predefined_[c] == nullptr);
     str->SetCanonical();  // Make canonical once entered.
-    predefined_[c] = str->raw();
+    predefined_[c] = str->ptr();
     symbol_handles_[idx] = str;
   }
 
-  vm_isolate->object_store()->set_symbol_table(table.Release());
+  vm_isolate_group->object_store()->set_symbol_table(table.Release());
 }
 
-void Symbols::InitFromSnapshot(Isolate* vm_isolate) {
+void Symbols::InitFromSnapshot(IsolateGroup* vm_isolate_group) {
   // Should only be run by the vm isolate.
-  ASSERT(Isolate::Current() == Dart::vm_isolate());
-  ASSERT(vm_isolate == Dart::vm_isolate());
+  ASSERT(IsolateGroup::Current() == Dart::vm_isolate_group());
+  ASSERT(vm_isolate_group == Dart::vm_isolate_group());
   Zone* zone = Thread::Current()->zone();
 
-  CanonicalStringSet table(zone, vm_isolate->object_store()->symbol_table());
+  CanonicalStringSet table(zone,
+                           vm_isolate_group->object_store()->symbol_table());
 
   // Lookup all the predefined string symbols and language keyword symbols
   // and cache them in the read only handles for fast access.
@@ -158,28 +160,30 @@
     ASSERT(!str->IsNull());
     ASSERT(str->HasHash());
     ASSERT(str->IsCanonical());
-    predefined_[c] = str->raw();
+    predefined_[c] = str->ptr();
     symbol_handles_[idx] = str;
   }
 
-  vm_isolate->object_store()->set_symbol_table(table.Release());
+  vm_isolate_group->object_store()->set_symbol_table(table.Release());
 }
 
-void Symbols::SetupSymbolTable(Isolate* isolate) {
-  ASSERT(isolate != NULL);
+void Symbols::SetupSymbolTable(IsolateGroup* isolate_group) {
+  ASSERT(isolate_group != nullptr);
 
   // Setup the symbol table used within the String class.
-  const intptr_t initial_size = (isolate == Dart::vm_isolate())
+  const intptr_t initial_size = (isolate_group == Dart::vm_isolate_group())
                                     ? kInitialVMIsolateSymtabSize
                                     : kInitialSymtabSize;
   Array& array = Array::Handle(
       HashTables::New<CanonicalStringSet>(initial_size, Heap::kOld));
-  isolate->object_store()->set_symbol_table(array);
+  isolate_group->object_store()->set_symbol_table(array);
 }
 
-void Symbols::GetStats(Isolate* isolate, intptr_t* size, intptr_t* capacity) {
-  ASSERT(isolate != NULL);
-  CanonicalStringSet table(isolate->object_store()->symbol_table());
+void Symbols::GetStats(IsolateGroup* isolate_group,
+                       intptr_t* size,
+                       intptr_t* capacity) {
+  ASSERT(isolate_group != nullptr);
+  CanonicalStringSet table(isolate_group->object_store()->symbol_table());
   *size = table.NumOccupied();
   *capacity = table.NumEntries();
   table.Release();
@@ -340,19 +344,15 @@
   Smi& value = thread->SmiHandle();
   Array& data = thread->ArrayHandle();
   {
-    Isolate* vm_isolate = Dart::vm_isolate();
-    data = vm_isolate->object_store()->symbol_table();
+    auto vm_isolate_group = Dart::vm_isolate_group();
+    data = vm_isolate_group->object_store()->symbol_table();
     CanonicalStringSet table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
   }
   if (symbol.IsNull()) {
     IsolateGroup* group = thread->isolate_group();
-    Isolate* isolate = thread->isolate();
-    // In JIT object_store lives on isolate, not on isolate group.
-    ObjectStore* object_store = group->object_store() == nullptr
-                                    ? isolate->object_store()
-                                    : group->object_store();
+    ObjectStore* object_store = group->object_store();
     if (thread->IsAtSafepoint()) {
       // There are two cases where we can cause symbol allocation while holding
       // a safepoint:
@@ -411,7 +411,7 @@
   }
   ASSERT(symbol.IsSymbol());
   ASSERT(symbol.HasHash());
-  return symbol.raw();
+  return symbol.ptr();
 }
 
 template <typename StringType>
@@ -424,19 +424,15 @@
   Smi& value = thread->SmiHandle();
   Array& data = thread->ArrayHandle();
   {
-    Isolate* vm_isolate = Dart::vm_isolate();
-    data = vm_isolate->object_store()->symbol_table();
+    auto vm_isolate_group = Dart::vm_isolate_group();
+    data = vm_isolate_group->object_store()->symbol_table();
     CanonicalStringSet table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
   }
   if (symbol.IsNull()) {
     IsolateGroup* group = thread->isolate_group();
-    Isolate* isolate = thread->isolate();
-    // In JIT object_store lives on isolate, not on isolate group.
-    ObjectStore* object_store = group->object_store() == nullptr
-                                    ? isolate->object_store()
-                                    : group->object_store();
+    ObjectStore* object_store = group->object_store();
     // See `Symbols::NewSymbol` for more information why we separate the two
     // cases.
     if (thread->IsAtSafepoint()) {
@@ -460,7 +456,7 @@
   }
   ASSERT(symbol.IsNull() || symbol.IsSymbol());
   ASSERT(symbol.IsNull() || symbol.HasHash());
-  return symbol.raw();
+  return symbol.ptr();
 }
 
 StringPtr Symbols::LookupFromConcat(Thread* thread,
@@ -489,7 +485,7 @@
 
 StringPtr Symbols::New(Thread* thread, const String& str) {
   if (str.IsSymbol()) {
-    return str.raw();
+    return str.ptr();
   }
   return New(thread, str, 0, str.Length());
 }
@@ -532,31 +528,31 @@
   return predefined_[char_code];
 }
 
-void Symbols::DumpStats(Isolate* isolate) {
+void Symbols::DumpStats(IsolateGroup* isolate_group) {
   intptr_t size = -1;
   intptr_t capacity = -1;
   // First dump VM symbol table stats.
-  GetStats(Dart::vm_isolate(), &size, &capacity);
+  GetStats(Dart::vm_isolate_group(), &size, &capacity);
   OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
   OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
   // Now dump regular isolate symbol table stats.
-  GetStats(isolate, &size, &capacity);
+  GetStats(isolate_group, &size, &capacity);
   OS::PrintErr("Isolate: Number of symbols : %" Pd "\n", size);
   OS::PrintErr("Isolate: Symbol table capacity : %" Pd "\n", capacity);
   // TODO(koda): Consider recording growth and collision stats in HashTable,
   // in DEBUG mode.
 }
 
-void Symbols::DumpTable(Isolate* isolate) {
+void Symbols::DumpTable(IsolateGroup* isolate_group) {
   OS::PrintErr("symbols:\n");
-  CanonicalStringSet table(isolate->object_store()->symbol_table());
+  CanonicalStringSet table(isolate_group->object_store()->symbol_table());
   table.Dump();
   table.Release();
 }
 
 intptr_t Symbols::LookupPredefinedSymbol(ObjectPtr obj) {
   for (intptr_t i = 1; i < Symbols::kMaxPredefinedId; i++) {
-    if (symbol_handles_[i]->raw() == obj) {
+    if (symbol_handles_[i]->ptr() == obj) {
       return (i + kMaxPredefinedObjectIds);
     }
   }
@@ -567,7 +563,7 @@
   ASSERT(IsPredefinedSymbolId(object_id));
   intptr_t i = (object_id - kMaxPredefinedObjectIds);
   if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) {
-    return symbol_handles_[i]->raw();
+    return symbol_handles_[i]->ptr();
   }
   return Object::null();
 }
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 1e408f1..b9d33eb 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -12,7 +12,7 @@
 namespace dart {
 
 // Forward declarations.
-class Isolate;
+class IsolateGroup;
 class ObjectPointerVisitor;
 
 // One-character symbols are added implicitly.
@@ -206,7 +206,6 @@
   V(List, "List")                                                              \
   V(ListFactory, "List.")                                                      \
   V(ListFilledFactory, "List.filled")                                          \
-  V(ListLiteralFactory, "List._fromLiteral")                                   \
   V(LoadLibrary, "_loadLibrary")                                               \
   V(LocalVarDescriptors, "LocalVarDescriptors")                                \
   V(Map, "Map")                                                                \
@@ -247,7 +246,6 @@
   V(SecondArg, "y")                                                            \
   V(Set, "set")                                                                \
   V(SetterPrefix, "set:")                                                      \
-  V(SignatureData, "SignatureData")                                            \
   V(SingleTargetCache, "SingleTargetCache")                                    \
   V(SizeOfStructField, "#sizeOf")                                              \
   V(SpaceExtendsSpace, " extends ")                                            \
@@ -262,7 +260,7 @@
   V(StreamIteratorConstructor, "StreamIterator.")                              \
   V(StringBase, "_StringBase")                                                 \
   V(Struct, "Struct")                                                          \
-  V(StructFromPointer, "#fromPointer")                                         \
+  V(StructFromTypedDataBase, "#fromTypedDataBase")                             \
   V(SubtypeTestCache, "SubtypeTestCache")                                      \
   V(LoadingUnit, "LoadingUnit")                                                \
   V(SwitchExpr, ":switch_expr")                                                \
@@ -351,6 +349,7 @@
   V(_GrowableListFactory, "_GrowableList.")                                    \
   V(_GrowableListFilledFactory, "_GrowableList.filled")                        \
   V(_GrowableListGenerateFactory, "_GrowableList.generate")                    \
+  V(_GrowableListLiteralFactory, "_GrowableList._literal")                     \
   V(_GrowableListWithData, "_GrowableList._withData")                          \
   V(_ImmutableList, "_ImmutableList")                                          \
   V(_Int16ArrayFactory, "Int16List.")                                          \
@@ -401,11 +400,12 @@
   V(_SyncIterableConstructor, "_SyncIterable.")                                \
   V(_SyncIterator, "_SyncIterator")                                            \
   V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl")                  \
+  V(_AbstractType, "_AbstractType")                                            \
   V(_Type, "_Type")                                                            \
+  V(_FunctionType, "_FunctionType")                                            \
   V(_TypeParameter, "_TypeParameter")                                          \
   V(_TypeRef, "_TypeRef")                                                      \
   V(_TypeVariableMirror, "_TypeVariableMirror")                                \
-  V(_TypedefMirror, "_TypedefMirror")                                          \
   V(_Uint16ArrayFactory, "Uint16List.")                                        \
   V(_Uint16ArrayView, "_Uint16ArrayView")                                      \
   V(_Uint16List, "_Uint16List")                                                \
@@ -425,6 +425,7 @@
   V(_Utf8Decoder, "_Utf8Decoder")                                              \
   V(_VariableMirror, "_VariableMirror")                                        \
   V(_WeakProperty, "_WeakProperty")                                            \
+  V(_addressOf, "_addressOf")                                                  \
   V(_classRangeCheck, "_classRangeCheck")                                      \
   V(_current, "_current")                                                      \
   V(_ensureScheduleImmediate, "_ensureScheduleImmediate")                      \
@@ -493,6 +494,7 @@
   V(vm_inferred_type_metadata, "vm.inferred-type.metadata")                    \
   V(vm_never_inline, "vm:never-inline")                                        \
   V(vm_non_nullable_result_type, "vm:non-nullable-result-type")                \
+  V(vm_notify_debugger_on_exception, "vm:notify-debugger-on-exception")        \
   V(vm_recognized, "vm:recognized")                                            \
   V(vm_trace_entrypoints, "vm:testing.unsafe.trace-entrypoints-fn")            \
   V(vm_procedure_attributes_metadata, "vm.procedure-attributes.metadata")      \
@@ -640,11 +642,11 @@
   static const String& Token(Token::Kind token);
 
   // Initialize frequently used symbols in the vm isolate.
-  static void Init(Isolate* isolate);
-  static void InitFromSnapshot(Isolate* isolate);
+  static void Init(IsolateGroup* isolate_group);
+  static void InitFromSnapshot(IsolateGroup* isolate_group);
 
   // Initialize and setup a symbol table for the isolate.
-  static void SetupSymbolTable(Isolate* isolate);
+  static void SetupSymbolTable(IsolateGroup* isolate_group);
 
   // Creates a Symbol given a C string that is assumed to contain
   // UTF-8 encoded characters and '\0' is considered a termination character.
@@ -702,8 +704,8 @@
     return reinterpret_cast<StringPtr*>(&predefined_);
   }
 
-  static void DumpStats(Isolate* isolate);
-  static void DumpTable(Isolate* isolate);
+  static void DumpStats(IsolateGroup* isolate_group);
+  static void DumpTable(IsolateGroup* isolate_group);
 
   // Returns Symbol::Null if no symbol is found.
   template <typename StringType>
@@ -718,7 +720,9 @@
   static StringPtr LookupFromSet(Thread* thread, const String& str);
   static StringPtr LookupFromDot(Thread* thread, const String& str);
 
-  static void GetStats(Isolate* isolate, intptr_t* size, intptr_t* capacity);
+  static void GetStats(IsolateGroup* isolate_group,
+                       intptr_t* size,
+                       intptr_t* capacity);
 
  private:
   enum { kInitialVMIsolateSymtabSize = 1024, kInitialSymtabSize = 2048 };
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index 4954982..68dc056 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -13,14 +13,14 @@
 namespace dart {
 
 class IsolateGroup;
-class ObjectLayout;
+class UntaggedObject;
 
 class ObjectPtr {
  public:
   ObjectPtr* operator->() { return this; }
   const ObjectPtr* operator->() const { return this; }
-  ObjectLayout* ptr() const {
-    return reinterpret_cast<ObjectLayout*>(UntaggedPointer());
+  UntaggedObject* untag() const {
+    return reinterpret_cast<UntaggedObject*>(untagged_pointer());
   }
 
   bool IsWellFormed() const {
@@ -184,12 +184,12 @@
   explicit constexpr ObjectPtr(uword tagged) : tagged_pointer_(tagged) {}
   explicit constexpr ObjectPtr(intptr_t tagged) : tagged_pointer_(tagged) {}
   constexpr ObjectPtr(std::nullptr_t) : tagged_pointer_(0) {}  // NOLINT
-  explicit ObjectPtr(ObjectLayout* heap_object)
+  explicit ObjectPtr(UntaggedObject* heap_object)
       : tagged_pointer_(reinterpret_cast<uword>(heap_object) + kHeapObjectTag) {
   }
 
  protected:
-  uword UntaggedPointer() const {
+  uword untagged_pointer() const {
     ASSERT(IsHeapObject());
     return tagged_pointer_ - kHeapObjectTag;
   }
@@ -206,17 +206,17 @@
 #endif
 
 #define DEFINE_TAGGED_POINTER(klass, base)                                     \
-  class klass##Layout;                                                         \
+  class Untagged##klass;                                                       \
   class klass##Ptr : public base##Ptr {                                        \
    public:                                                                     \
     klass##Ptr* operator->() { return this; }                                  \
     const klass##Ptr* operator->() const { return this; }                      \
-    klass##Layout* ptr() {                                                     \
-      return reinterpret_cast<klass##Layout*>(UntaggedPointer());              \
+    Untagged##klass* untag() {                                                 \
+      return reinterpret_cast<Untagged##klass*>(untagged_pointer());           \
     }                                                                          \
     /* TODO: Return const pointer */                                           \
-    klass##Layout* ptr() const {                                               \
-      return reinterpret_cast<klass##Layout*>(UntaggedPointer());              \
+    Untagged##klass* untag() const {                                           \
+      return reinterpret_cast<Untagged##klass*>(untagged_pointer());           \
     }                                                                          \
     klass##Ptr& operator=(const klass##Ptr& other) = default;                  \
     constexpr klass##Ptr(const klass##Ptr& other) = default;                   \
@@ -224,8 +224,9 @@
         : base##Ptr(other) {}                                                  \
     klass##Ptr() : base##Ptr() {}                                              \
     explicit constexpr klass##Ptr(uword tagged) : base##Ptr(tagged) {}         \
+    explicit constexpr klass##Ptr(intptr_t tagged) : base##Ptr(tagged) {}      \
     constexpr klass##Ptr(std::nullptr_t) : base##Ptr(nullptr) {} /* NOLINT */  \
-    explicit klass##Ptr(const ObjectLayout* untagged)                          \
+    explicit klass##Ptr(const UntaggedObject* untagged)                        \
         : base##Ptr(reinterpret_cast<uword>(untagged) + kHeapObjectTag) {}     \
   };
 
@@ -233,7 +234,6 @@
 DEFINE_TAGGED_POINTER(PatchClass, Object)
 DEFINE_TAGGED_POINTER(Function, Object)
 DEFINE_TAGGED_POINTER(ClosureData, Object)
-DEFINE_TAGGED_POINTER(SignatureData, Object)
 DEFINE_TAGGED_POINTER(FfiTrampolineData, Object)
 DEFINE_TAGGED_POINTER(Field, Object)
 DEFINE_TAGGED_POINTER(Script, Object)
@@ -270,6 +270,7 @@
 DEFINE_TAGGED_POINTER(TypeArguments, Instance)
 DEFINE_TAGGED_POINTER(AbstractType, Instance)
 DEFINE_TAGGED_POINTER(Type, AbstractType)
+DEFINE_TAGGED_POINTER(FunctionType, AbstractType)
 DEFINE_TAGGED_POINTER(TypeRef, AbstractType)
 DEFINE_TAGGED_POINTER(TypeParameter, AbstractType)
 DEFINE_TAGGED_POINTER(Closure, Instance)
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 04b895a..caff423 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -61,7 +61,7 @@
 Thread::Thread(bool is_vm_isolate)
     : ThreadState(false),
       stack_limit_(0),
-      write_barrier_mask_(ObjectLayout::kGenerationalBarrierMask),
+      write_barrier_mask_(UntaggedObject::kGenerationalBarrierMask),
       isolate_(NULL),
       dispatch_table_array_(NULL),
       saved_stack_limit_(0),
@@ -79,6 +79,7 @@
       execution_state_(kThreadInNative),
       safepoint_state_(0),
       ffi_callback_code_(GrowableObjectArray::null()),
+      ffi_callback_stack_return_(TypedData::null()),
       api_top_scope_(NULL),
       task_kind_(kUnknownTask),
       dart_stream_(NULL),
@@ -226,11 +227,11 @@
 }
 
 void Thread::set_active_exception(const Object& value) {
-  active_exception_ = value.raw();
+  active_exception_ = value.ptr();
 }
 
 void Thread::set_active_stacktrace(const Object& value) {
-  active_stacktrace_ = value.raw();
+  active_stacktrace_ = value.ptr();
 }
 
 ErrorPtr Thread::sticky_error() const {
@@ -239,7 +240,7 @@
 
 void Thread::set_sticky_error(const Error& value) {
   ASSERT(!value.IsNull());
-  sticky_error_ = value.raw();
+  sticky_error_ = value.ptr();
 }
 
 void Thread::ClearStickyError() {
@@ -572,14 +573,14 @@
 void Thread::MarkingStackRelease() {
   MarkingStackBlock* block = marking_stack_block_;
   marking_stack_block_ = NULL;
-  write_barrier_mask_ = ObjectLayout::kGenerationalBarrierMask;
+  write_barrier_mask_ = UntaggedObject::kGenerationalBarrierMask;
   isolate_group()->marking_stack()->PushBlock(block);
 }
 
 void Thread::MarkingStackAcquire() {
   marking_stack_block_ = isolate_group()->marking_stack()->PopEmptyBlock();
-  write_barrier_mask_ = ObjectLayout::kGenerationalBarrierMask |
-                        ObjectLayout::kIncrementalBarrierMask;
+  write_barrier_mask_ = UntaggedObject::kGenerationalBarrierMask |
+                        UntaggedObject::kIncrementalBarrierMask;
 }
 
 void Thread::DeferredMarkingStackRelease() {
@@ -641,6 +642,8 @@
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&active_stacktrace_));
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&sticky_error_));
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&ffi_callback_code_));
+  visitor->VisitPointer(
+      reinterpret_cast<ObjectPtr*>(&ffi_callback_stack_return_));
 
   // Visit the api local scope as it has all the api local handles.
   ApiLocalScope* scope = api_top_scope_;
@@ -707,17 +710,17 @@
         continue;
 
       // Dart code won't store into canonical instances.
-      if (obj->ptr()->IsCanonical()) continue;
+      if (obj->untag()->IsCanonical()) continue;
 
       // Objects in the VM isolate heap are immutable and won't be
       // stored into. Check this condition last because there's no bit
       // in the header for it.
-      if (obj->ptr()->InVMIsolateHeap()) continue;
+      if (obj->untag()->InVMIsolateHeap()) continue;
 
       switch (op_) {
         case Thread::RestoreWriteBarrierInvariantOp::kAddToRememberedSet:
-          if (!obj->ptr()->IsRemembered()) {
-            obj->ptr()->AddToRememberedSet(current_);
+          if (!obj->untag()->IsRemembered()) {
+            obj->untag()->AddToRememberedSet(current_);
           }
           if (current_->is_marking()) {
             current_->DeferredMarkingStackAddObject(obj);
@@ -788,7 +791,7 @@
   // [object] is in fact a [Code] object.
   if (object.IsCode()) {
 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value)         \
-  if (object.raw() == expr) {                                                  \
+  if (object.ptr() == expr) {                                                  \
     return true;                                                               \
   }
     CACHED_VM_STUBS_LIST(CHECK_OBJECT)
@@ -798,7 +801,7 @@
   // For non [Code] objects we check if the object equals to any of the cached
   // non-stub entries.
 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value)         \
-  if (object.raw() == expr) {                                                  \
+  if (object.ptr() == expr) {                                                  \
     return true;                                                               \
   }
   CACHED_NON_VM_STUB_LIST(CHECK_OBJECT)
@@ -812,8 +815,8 @@
   // [object] is in fact a [Code] object.
   if (object.IsCode()) {
 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value)       \
-  ASSERT((expr)->ptr()->InVMIsolateHeap());                                    \
-  if (object.raw() == expr) {                                                  \
+  ASSERT((expr)->untag()->InVMIsolateHeap());                                  \
+  if (object.ptr() == expr) {                                                  \
     return Thread::member_name##offset();                                      \
   }
     CACHED_VM_STUBS_LIST(COMPUTE_OFFSET)
@@ -823,7 +826,7 @@
   // For non [Code] objects we check if the object equals to any of the cached
   // non-stub entries.
 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value)       \
-  if (object.raw() == expr) {                                                  \
+  if (object.ptr() == expr) {                                                  \
     return Thread::member_name##offset();                                      \
   }
   CACHED_NON_VM_STUB_LIST(COMPUTE_OFFSET)
@@ -1078,6 +1081,47 @@
   array.SetAt(callback_id, code);
 }
 
+void Thread::SetFfiCallbackStackReturn(int32_t callback_id,
+                                       intptr_t stack_return_delta) {
+#if defined(TARGET_ARCH_IA32)
+#else
+  UNREACHABLE();
+#endif
+
+  Zone* Z = Thread::Current()->zone();
+
+  /// In AOT the callback ID might have been allocated during compilation but
+  /// 'ffi_callback_code_' is initialized to empty again when the program
+  /// starts. Therefore we may need to initialize or expand it to accomodate
+  /// the callback ID.
+
+  if (ffi_callback_stack_return_ == TypedData::null()) {
+    ffi_callback_stack_return_ = TypedData::New(
+        kTypedDataInt8ArrayCid, kInitialCallbackIdsReserved, Heap::kOld);
+  }
+
+  auto& array = TypedData::Handle(Z, ffi_callback_stack_return_);
+
+  if (callback_id >= array.Length()) {
+    const int32_t capacity = array.Length();
+    if (callback_id >= capacity) {
+      // Ensure both that we grow enough and an exponential growth strategy.
+      const int32_t new_capacity =
+          Utils::Maximum(callback_id + 1, capacity * 2);
+      const auto& new_array = TypedData::Handle(
+          Z, TypedData::New(kTypedDataUint8ArrayCid, new_capacity, Heap::kOld));
+      for (intptr_t i = 0; i < capacity; i++) {
+        new_array.SetUint8(i, array.GetUint8(i));
+      }
+      array ^= new_array.ptr();
+      ffi_callback_stack_return_ = new_array.ptr();
+    }
+  }
+
+  ASSERT(callback_id < array.Length());
+  array.SetUint8(callback_id, stack_return_delta);
+}
+
 void Thread::VerifyCallbackIsolate(int32_t callback_id, uword entry) {
   NoSafepointScope _;
 
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index cc3c410..6dbacbf 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -86,72 +86,72 @@
   V(TypeParameter)
 
 #define CACHED_VM_STUBS_LIST(V)                                                \
-  V(CodePtr, write_barrier_code_, StubCode::WriteBarrier().raw(), nullptr)     \
-  V(CodePtr, array_write_barrier_code_, StubCode::ArrayWriteBarrier().raw(),   \
+  V(CodePtr, write_barrier_code_, StubCode::WriteBarrier().ptr(), nullptr)     \
+  V(CodePtr, array_write_barrier_code_, StubCode::ArrayWriteBarrier().ptr(),   \
     nullptr)                                                                   \
-  V(CodePtr, fix_callers_target_code_, StubCode::FixCallersTarget().raw(),     \
+  V(CodePtr, fix_callers_target_code_, StubCode::FixCallersTarget().ptr(),     \
     nullptr)                                                                   \
   V(CodePtr, fix_allocation_stub_code_,                                        \
-    StubCode::FixAllocationStubTarget().raw(), nullptr)                        \
-  V(CodePtr, invoke_dart_code_stub_, StubCode::InvokeDartCode().raw(),         \
+    StubCode::FixAllocationStubTarget().ptr(), nullptr)                        \
+  V(CodePtr, invoke_dart_code_stub_, StubCode::InvokeDartCode().ptr(),         \
     nullptr)                                                                   \
-  V(CodePtr, call_to_runtime_stub_, StubCode::CallToRuntime().raw(), nullptr)  \
+  V(CodePtr, call_to_runtime_stub_, StubCode::CallToRuntime().ptr(), nullptr)  \
   V(CodePtr, late_initialization_error_shared_without_fpu_regs_stub_,          \
-    StubCode::LateInitializationErrorSharedWithoutFPURegs().raw(), nullptr)    \
+    StubCode::LateInitializationErrorSharedWithoutFPURegs().ptr(), nullptr)    \
   V(CodePtr, late_initialization_error_shared_with_fpu_regs_stub_,             \
-    StubCode::LateInitializationErrorSharedWithFPURegs().raw(), nullptr)       \
+    StubCode::LateInitializationErrorSharedWithFPURegs().ptr(), nullptr)       \
   V(CodePtr, null_error_shared_without_fpu_regs_stub_,                         \
-    StubCode::NullErrorSharedWithoutFPURegs().raw(), nullptr)                  \
+    StubCode::NullErrorSharedWithoutFPURegs().ptr(), nullptr)                  \
   V(CodePtr, null_error_shared_with_fpu_regs_stub_,                            \
-    StubCode::NullErrorSharedWithFPURegs().raw(), nullptr)                     \
+    StubCode::NullErrorSharedWithFPURegs().ptr(), nullptr)                     \
   V(CodePtr, null_arg_error_shared_without_fpu_regs_stub_,                     \
-    StubCode::NullArgErrorSharedWithoutFPURegs().raw(), nullptr)               \
+    StubCode::NullArgErrorSharedWithoutFPURegs().ptr(), nullptr)               \
   V(CodePtr, null_arg_error_shared_with_fpu_regs_stub_,                        \
-    StubCode::NullArgErrorSharedWithFPURegs().raw(), nullptr)                  \
+    StubCode::NullArgErrorSharedWithFPURegs().ptr(), nullptr)                  \
   V(CodePtr, null_cast_error_shared_without_fpu_regs_stub_,                    \
-    StubCode::NullCastErrorSharedWithoutFPURegs().raw(), nullptr)              \
+    StubCode::NullCastErrorSharedWithoutFPURegs().ptr(), nullptr)              \
   V(CodePtr, null_cast_error_shared_with_fpu_regs_stub_,                       \
-    StubCode::NullCastErrorSharedWithFPURegs().raw(), nullptr)                 \
+    StubCode::NullCastErrorSharedWithFPURegs().ptr(), nullptr)                 \
   V(CodePtr, range_error_shared_without_fpu_regs_stub_,                        \
-    StubCode::RangeErrorSharedWithoutFPURegs().raw(), nullptr)                 \
+    StubCode::RangeErrorSharedWithoutFPURegs().ptr(), nullptr)                 \
   V(CodePtr, range_error_shared_with_fpu_regs_stub_,                           \
-    StubCode::RangeErrorSharedWithFPURegs().raw(), nullptr)                    \
+    StubCode::RangeErrorSharedWithFPURegs().ptr(), nullptr)                    \
   V(CodePtr, allocate_mint_with_fpu_regs_stub_,                                \
-    StubCode::AllocateMintSharedWithFPURegs().raw(), nullptr)                  \
+    StubCode::AllocateMintSharedWithFPURegs().ptr(), nullptr)                  \
   V(CodePtr, allocate_mint_without_fpu_regs_stub_,                             \
-    StubCode::AllocateMintSharedWithoutFPURegs().raw(), nullptr)               \
-  V(CodePtr, allocate_object_stub_, StubCode::AllocateObject().raw(), nullptr) \
+    StubCode::AllocateMintSharedWithoutFPURegs().ptr(), nullptr)               \
+  V(CodePtr, allocate_object_stub_, StubCode::AllocateObject().ptr(), nullptr) \
   V(CodePtr, allocate_object_parameterized_stub_,                              \
-    StubCode::AllocateObjectParameterized().raw(), nullptr)                    \
-  V(CodePtr, allocate_object_slow_stub_, StubCode::AllocateObjectSlow().raw(), \
+    StubCode::AllocateObjectParameterized().ptr(), nullptr)                    \
+  V(CodePtr, allocate_object_slow_stub_, StubCode::AllocateObjectSlow().ptr(), \
     nullptr)                                                                   \
   V(CodePtr, stack_overflow_shared_without_fpu_regs_stub_,                     \
-    StubCode::StackOverflowSharedWithoutFPURegs().raw(), nullptr)              \
+    StubCode::StackOverflowSharedWithoutFPURegs().ptr(), nullptr)              \
   V(CodePtr, stack_overflow_shared_with_fpu_regs_stub_,                        \
-    StubCode::StackOverflowSharedWithFPURegs().raw(), nullptr)                 \
-  V(CodePtr, switchable_call_miss_stub_, StubCode::SwitchableCallMiss().raw(), \
+    StubCode::StackOverflowSharedWithFPURegs().ptr(), nullptr)                 \
+  V(CodePtr, switchable_call_miss_stub_, StubCode::SwitchableCallMiss().ptr(), \
     nullptr)                                                                   \
-  V(CodePtr, throw_stub_, StubCode::Throw().raw(), nullptr)                    \
-  V(CodePtr, re_throw_stub_, StubCode::Throw().raw(), nullptr)                 \
-  V(CodePtr, assert_boolean_stub_, StubCode::AssertBoolean().raw(), nullptr)   \
-  V(CodePtr, optimize_stub_, StubCode::OptimizeFunction().raw(), nullptr)      \
-  V(CodePtr, deoptimize_stub_, StubCode::Deoptimize().raw(), nullptr)          \
+  V(CodePtr, throw_stub_, StubCode::Throw().ptr(), nullptr)                    \
+  V(CodePtr, re_throw_stub_, StubCode::Throw().ptr(), nullptr)                 \
+  V(CodePtr, assert_boolean_stub_, StubCode::AssertBoolean().ptr(), nullptr)   \
+  V(CodePtr, optimize_stub_, StubCode::OptimizeFunction().ptr(), nullptr)      \
+  V(CodePtr, deoptimize_stub_, StubCode::Deoptimize().ptr(), nullptr)          \
   V(CodePtr, lazy_deopt_from_return_stub_,                                     \
-    StubCode::DeoptimizeLazyFromReturn().raw(), nullptr)                       \
+    StubCode::DeoptimizeLazyFromReturn().ptr(), nullptr)                       \
   V(CodePtr, lazy_deopt_from_throw_stub_,                                      \
-    StubCode::DeoptimizeLazyFromThrow().raw(), nullptr)                        \
-  V(CodePtr, slow_type_test_stub_, StubCode::SlowTypeTest().raw(), nullptr)    \
+    StubCode::DeoptimizeLazyFromThrow().ptr(), nullptr)                        \
+  V(CodePtr, slow_type_test_stub_, StubCode::SlowTypeTest().ptr(), nullptr)    \
   V(CodePtr, lazy_specialize_type_test_stub_,                                  \
-    StubCode::LazySpecializeTypeTest().raw(), nullptr)                         \
-  V(CodePtr, enter_safepoint_stub_, StubCode::EnterSafepoint().raw(), nullptr) \
-  V(CodePtr, exit_safepoint_stub_, StubCode::ExitSafepoint().raw(), nullptr)   \
+    StubCode::LazySpecializeTypeTest().ptr(), nullptr)                         \
+  V(CodePtr, enter_safepoint_stub_, StubCode::EnterSafepoint().ptr(), nullptr) \
+  V(CodePtr, exit_safepoint_stub_, StubCode::ExitSafepoint().ptr(), nullptr)   \
   V(CodePtr, call_native_through_safepoint_stub_,                              \
-    StubCode::CallNativeThroughSafepoint().raw(), nullptr)
+    StubCode::CallNativeThroughSafepoint().ptr(), nullptr)
 
 #define CACHED_NON_VM_STUB_LIST(V)                                             \
   V(ObjectPtr, object_null_, Object::null(), nullptr)                          \
-  V(BoolPtr, bool_true_, Object::bool_true().raw(), nullptr)                   \
-  V(BoolPtr, bool_false_, Object::bool_false().raw(), nullptr)
+  V(BoolPtr, bool_true_, Object::bool_true().ptr(), nullptr)                   \
+  V(BoolPtr, bool_false_, Object::bool_false().ptr(), nullptr)
 
 // List of VM-global objects/addresses cached in each Thread object.
 // Important: constant false must immediately follow constant true.
@@ -351,6 +351,10 @@
     return OFFSET_OF(Thread, ffi_callback_code_);
   }
 
+  static intptr_t callback_stack_return_offset() {
+    return OFFSET_OF(Thread, ffi_callback_stack_return_);
+  }
+
   // Tag state is maintained on transitions.
   enum {
     // Always true in generated state.
@@ -424,6 +428,10 @@
 
   bool IsMutatorThread() const { return is_mutator_thread_; }
 
+#if defined(DEBUG)
+  bool IsInsideCompiler() const { return inside_compiler_; }
+#endif
+
   bool CanCollectGarbage() const;
 
   // Offset of Dart TimelineStream object.
@@ -478,6 +486,18 @@
     no_callback_scope_depth_ -= 1;
   }
 
+#if defined(DEBUG)
+  void EnterCompiler() {
+    ASSERT(!IsInsideCompiler());
+    inside_compiler_ = true;
+  }
+
+  void LeaveCompiler() {
+    ASSERT(IsInsideCompiler());
+    inside_compiler_ = false;
+  }
+#endif
+
   void StoreBufferAddObject(ObjectPtr obj);
   void StoreBufferAddObjectGC(ObjectPtr obj);
 #if defined(TESTING)
@@ -829,9 +849,17 @@
 
   // Store 'code' for the native callback identified by 'callback_id'.
   //
-  // Expands the callback code array as necessary to accomodate the callback ID.
+  // Expands the callback code array as necessary to accomodate the callback
+  // ID.
   void SetFfiCallbackCode(int32_t callback_id, const Code& code);
 
+  // Store 'stack_return' for the native callback identified by 'callback_id'.
+  //
+  // Expands the callback stack return array as necessary to accomodate the
+  // callback ID.
+  void SetFfiCallbackStackReturn(int32_t callback_id,
+                                 intptr_t stack_return_delta);
+
   // Ensure that 'callback_id' refers to a valid callback in this isolate.
   //
   // If "entry != 0", additionally checks that entry is inside the instructions
@@ -949,6 +977,7 @@
   uword execution_state_;
   std::atomic<uword> safepoint_state_;
   GrowableObjectArrayPtr ffi_callback_code_;
+  TypedDataPtr ffi_callback_stack_return_;
   uword exit_through_ffi_ = 0;
   ApiLocalScope* api_top_scope_;
 
@@ -1014,6 +1043,10 @@
   Thread* next_;  // Used to chain the thread structures in an isolate.
   bool is_mutator_thread_ = false;
 
+#if defined(DEBUG)
+  bool inside_compiler_ = false;
+#endif
+
   explicit Thread(bool is_vm_isolate);
 
   void StoreBufferRelease(
@@ -1098,6 +1131,68 @@
 };
 #endif  // defined(DEBUG)
 
+// Within a EnterCompilerScope, the thread must operate on cloned fields.
+#if defined(DEBUG)
+class EnterCompilerScope : public ThreadStackResource {
+ public:
+  explicit EnterCompilerScope(Thread* thread = nullptr)
+      : ThreadStackResource(thread != nullptr ? thread : Thread::Current()) {
+    previously_is_inside_compiler_ = this->thread()->IsInsideCompiler();
+    if (!previously_is_inside_compiler_) {
+      this->thread()->EnterCompiler();
+    }
+  }
+  ~EnterCompilerScope() {
+    if (!previously_is_inside_compiler_) {
+      thread()->LeaveCompiler();
+    }
+  }
+
+ private:
+  bool previously_is_inside_compiler_;
+  DISALLOW_COPY_AND_ASSIGN(EnterCompilerScope);
+};
+#else   // defined(DEBUG)
+class EnterCompilerScope : public ValueObject {
+ public:
+  explicit EnterCompilerScope(Thread* thread = nullptr) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(EnterCompilerScope);
+};
+#endif  // defined(DEBUG)
+
+// Within a LeaveCompilerScope, the thread must operate on cloned fields.
+#if defined(DEBUG)
+class LeaveCompilerScope : public ThreadStackResource {
+ public:
+  explicit LeaveCompilerScope(Thread* thread = nullptr)
+      : ThreadStackResource(thread != nullptr ? thread : Thread::Current()) {
+    previously_is_inside_compiler_ = this->thread()->IsInsideCompiler();
+    if (previously_is_inside_compiler_) {
+      this->thread()->LeaveCompiler();
+    }
+  }
+  ~LeaveCompilerScope() {
+    if (previously_is_inside_compiler_) {
+      thread()->EnterCompiler();
+    }
+  }
+
+ private:
+  bool previously_is_inside_compiler_;
+  DISALLOW_COPY_AND_ASSIGN(LeaveCompilerScope);
+};
+#else   // defined(DEBUG)
+class LeaveCompilerScope : public ValueObject {
+ public:
+  explicit LeaveCompilerScope(Thread* thread = nullptr) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LeaveCompilerScope);
+};
+#endif  // defined(DEBUG)
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_THREAD_H_
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 1640296..80be01e 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -85,7 +85,7 @@
 
   virtual void VisitPointers(ObjectPtr* first, ObjectPtr* last) {
     for (ObjectPtr* current = first; current <= last; ++current) {
-      if (*current == obj_->raw()) {
+      if (*current == obj_->ptr()) {
         ++count_;
       }
     }
@@ -295,7 +295,7 @@
   intptr_t done_count = 0;
   bool wait = true;
 
-  EXPECT(isolate->heap()->GrowthControlState());
+  EXPECT(isolate->group()->heap()->GrowthControlState());
 
   NoHeapGrowthControlScope no_heap_growth_scope;
 
@@ -431,9 +431,10 @@
       Class::New(lib, class_name, script, TokenPosition::kNoSource));
   const String& function_name =
       String::ZoneHandle(Symbols::New(Thread::Current(), name));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   Function& function = Function::ZoneHandle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, owner_class, TokenPosition::kNoSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, owner_class, TokenPosition::kNoSource));
   return &function;
 }
 
@@ -543,7 +544,7 @@
           EXPECT_EQ(*expected_count_, counter.count());
         }
         UserTag& tag = UserTag::Handle(zone, isolate_->current_tag());
-        if (tag.raw() != isolate_->default_tag()) {
+        if (tag.ptr() != isolate_->default_tag()) {
           String& label = String::Handle(zone, tag.label());
           EXPECT(label.Equals("foo"));
           MonitorLocker ml(monitor_);
@@ -843,7 +844,7 @@
       Zone* zone = stack_zone.GetZone();
       HANDLESCOPE(thread);
       String& old_str = String::Handle(zone, String::New("old", Heap::kOld));
-      isolate_->heap()->CollectAllGarbage();
+      isolate_->group()->heap()->CollectAllGarbage();
       EXPECT(old_str.Equals("old"));
     }
     Thread::ExitIsolateAsHelper();
diff --git a/runtime/vm/token_position.cc b/runtime/vm/token_position.cc
index 0f8ae68..507a528 100644
--- a/runtime/vm/token_position.cc
+++ b/runtime/vm/token_position.cc
@@ -4,34 +4,29 @@
 
 #include "vm/token_position.h"
 
+#include "vm/hash.h"
 #include "vm/object.h"
+#include "vm/zone_text_buffer.h"
 
 namespace dart {
 
-TokenPosition TokenPosition::SnapshotDecode(int32_t value) {
-  return TokenPosition(static_cast<intptr_t>(value));
+intptr_t TokenPosition::Hash() const {
+  return FinalizeHash(value_, 31);
 }
 
-int32_t TokenPosition::SnapshotEncode() {
+TokenPosition TokenPosition::Deserialize(int32_t value) {
+  return TokenPosition(value);
+}
+
+int32_t TokenPosition::Serialize() const {
   return static_cast<int32_t>(value_);
 }
 
-bool TokenPosition::IsSynthetic() const {
-  if (value_ >= kMinSourcePos) {
-    return false;
-  }
-  if (value_ < kLast.value()) {
-    return true;
-  }
-  return false;
-}
-
 #define DEFINE_VALUES(name, value)                                             \
   const TokenPosition TokenPosition::k##name(value);
 SENTINEL_TOKEN_DESCRIPTORS(DEFINE_VALUES);
 #undef DEFINE_VALUES
 const TokenPosition TokenPosition::kMinSource(kMinSourcePos);
-
 const TokenPosition TokenPosition::kMaxSource(kMaxSourcePos);
 
 const char* TokenPosition::ToCString() const {
@@ -41,17 +36,16 @@
     return #name;
     SENTINEL_TOKEN_DESCRIPTORS(DEFINE_CASE);
 #undef DEFINE_CASE
-    default: {
-      Zone* zone = Thread::Current()->zone();
-      ASSERT(zone != NULL);
-      if (IsSynthetic()) {
-        // TODO(johnmccutchan): Print synthetic positions differently.
-        return FromSynthetic().ToCString();
-      } else {
-        return OS::SCreate(zone, "%d", value_);
-      }
-    }
+    default:
+      break;
   }
+  ASSERT(IsReal() || IsSynthetic());
+  ZoneTextBuffer buffer(Thread::Current()->zone());
+  if (IsSynthetic()) {
+    buffer.AddString("syn:");
+  }
+  buffer.Printf("%" Pd32 "", value_);
+  return buffer.buffer();
 }
 
 }  // namespace dart
diff --git a/runtime/vm/token_position.h b/runtime/vm/token_position.h
index 270a14c..d15553e 100644
--- a/runtime/vm/token_position.h
+++ b/runtime/vm/token_position.h
@@ -17,14 +17,26 @@
 // ClassifyingTokenPositions 1 -> -1 - 1
 // ClassifyingTokenPositions N -> -1 - N
 //
-// Synthetically created AstNodes are given real source positions but encoded
-// as negative numbers from [kSmiMin32, -1 - N]. For example:
+// Real token positions represent source offsets in some script, and are encoded
+// as non-negative values which are equal to that offset.
 //
-// A source position of 0 in a synthetic AstNode would be encoded as -2 - N.
-// A source position of 1 in a synthetic AstNode would be encoded as -3 - N.
+// Synthetically created functions that correspond to user code are given
+// starting token positions unique from other synthetic functions. The value for
+// these token positions encode a unique non-negative value as a negative number
+// within [kSmiMin32, -1 - N).
 //
-// All other AstNodes are given real source positions encoded as positive
-// integers.
+// For example:
+// A synthetic token with value 0 is encoded as ((-1 - N) - (0 + 1)) = -2 - N.
+// A synthetic token with value 1 is encoded as ((-1 - N) - (1 + 1)) = -3 - N.
+//
+// Note that the encoded value is _not_ related to any possible real token
+// position, as two real token positions for different scripts can have the same
+// value and thus cannot serve as a unique nonce for a synthetic node.
+//
+// All other nodes read from user code, such as non-synthetic functions, fields,
+// etc., are given real starting token positions. All nodes coming from user
+// code, both real or synthetic, with ending token positions have real ending
+// token positions.
 //
 // This organization allows for ~1 billion token positions.
 
@@ -44,56 +56,112 @@
   V(DartCodeEpilogue, -13)                                                     \
   V(Last, -14)  // Always keep this at the end.
 
-// A token position representing a debug safe source (real) position,
-// non-debug safe source (synthetic) positions, or a classifying value used
+// A token position represents either a debug safe source (real) position,
+// non-debug safe unique (synthetic) position, or a classifying value used
 // by the profiler.
 class TokenPosition {
  public:
-  TokenPosition() : value_(kNoSource.value()) {}
+  intptr_t Hash() const;
 
-  explicit TokenPosition(intptr_t value) : value_(value) {}
-
+  // Returns whether the token positions are equal.  Defined for all token
+  // positions.
   bool operator==(const TokenPosition& b) const { return value() == b.value(); }
 
+  // Returns whether the token positions are not equal. Defined for all token
+  // positions.
   bool operator!=(const TokenPosition& b) const { return !(*this == b); }
 
-  bool operator<(const TokenPosition& b) const {
-    // TODO(johnmccutchan): Assert that this is a source position.
-    return value() < b.value();
+  // Returns whether the token position is less than [b]. Only defined for
+  // real token positions.
+  inline bool operator<(const TokenPosition& b) const {
+    return Pos() < b.Pos();
   }
 
-  bool operator>(const TokenPosition& b) const {
-    // TODO(johnmccutchan): Assert that this is a source position.
-    return b < *this;
+  // Returns whether the token position is greater than [b]. Only defined for
+  // real token positions.
+  inline bool operator>(const TokenPosition& b) const { return b < *this; }
+
+  // Returns whether the token position is less than or equal to [b]. Only
+  // defined for real token positions.
+  inline bool operator<=(const TokenPosition& b) const { return !(*this > b); }
+
+  // Returns whether the token position is greater than or equal to [b].  Only
+  // defined for real token positions.
+  inline bool operator>=(const TokenPosition& b) const { return !(*this < b); }
+
+  // For real token positions, returns whether this is between [a] and [b],
+  // inclusive. If [a] or [b] is non-real, they are treated as less than
+  // any real token position.
+  //
+  // For synthetic token positions, returns whether [a] or [b] equals this.
+  //
+  // For other token positions, always returns false.
+  bool IsWithin(const TokenPosition& a, const TokenPosition& b) const {
+    if (IsReal()) return (a.value() <= value()) && (value() <= b.value());
+    if (IsSynthetic()) return (a == *this) || (b == *this);
+    return false;
   }
 
-  bool operator<=(const TokenPosition& b) {
-    // TODO(johnmccutchan): Assert that this is a source position.
-    return !(*this > b);
+  // Returns [a] if both positions are not real, the real position if only one
+  // of [a] and [b] is real, or the minimum position of [a] and [b].
+  static const TokenPosition& Min(const TokenPosition& a,
+                                  const TokenPosition& b) {
+    if (!b.IsReal()) return a;
+    if (!a.IsReal()) return b;
+    return b.value() < a.value() ? b : a;
+  }
+  // Returns [a] if both positions are not real, the real position if only one
+  // of [a] and [b] is real, or the maximum position of [a] and [b].
+  static const TokenPosition& Max(const TokenPosition& a,
+                                  const TokenPosition& b) {
+    if (!b.IsReal()) return a;
+    if (!a.IsReal()) return b;
+    return b.value() > a.value() ? b : a;
   }
 
-  bool operator>=(const TokenPosition& b) {
-    // TODO(johnmccutchan): Assert that this is a source position.
-    return !(*this < b);
+  // Compares two arbitrary source positions for use in sorting, where a
+  // negative return means [a] sorts before [b], a return of 0 means [a] is the
+  // same as [b], and a positive return means [a] sorts after [b].
+  //
+  // Does _not_ correspond to the relational operators on token positions, as
+  // this also allows comparison of kNoSource, classifying, and synthetic token
+  // positions to each other.
+  static intptr_t CompareForSorting(const TokenPosition& a,
+                                    const TokenPosition& b) {
+    return a.value() - b.value();
   }
 
-  static const intptr_t kMaxSentinelDescriptors = 64;
+  static constexpr int32_t kMaxSentinelDescriptors = 64;
 
 #define DECLARE_VALUES(name, value)                                            \
-  static const intptr_t k##name##Pos = value;                                  \
+  static constexpr int32_t k##name##Pos = value;                               \
   static const TokenPosition k##name;
   SENTINEL_TOKEN_DESCRIPTORS(DECLARE_VALUES);
 #undef DECLARE_VALUES
-  static const intptr_t kMinSourcePos = 0;
+  // Check assumptions used in Is<X> methods below.
+#define CHECK_VALUES(name, value)                                              \
+  static_assert(k##name##Pos < 0, "Non-negative sentinel descriptor");         \
+  static_assert(                                                               \
+      k##name##Pos == kNoSourcePos || k##name##Pos <= kBoxPos,                 \
+      "Box sentinel descriptor is not greatest classifying sentinel value");   \
+  static_assert(kLastPos <= k##name##Pos,                                      \
+                "Last sentinel descriptor is not least sentinel valu");        \
+  SENTINEL_TOKEN_DESCRIPTORS(CHECK_VALUES);
+#undef CHECK_VALUES
+  static_assert(kLastPos > -kMaxSentinelDescriptors,
+                "More sentinel descriptors than expected");
+
+  static constexpr int32_t kMinSourcePos = 0;
   static const TokenPosition kMinSource;
-  static const intptr_t kMaxSourcePos = kSmiMax32 - kMaxSentinelDescriptors - 2;
+  static constexpr int32_t kMaxSourcePos =
+      kSmiMax32 - kMaxSentinelDescriptors - 2;
   static const TokenPosition kMaxSource;
 
-  // Decode from a snapshot.
-  static TokenPosition SnapshotDecode(int32_t value);
+  // Decode from a serialized form.
+  static TokenPosition Deserialize(int32_t value);
 
-  // Encode for writing into a snapshot.
-  int32_t SnapshotEncode();
+  // Encode into a serialized form.
+  int32_t Serialize() const;
 
   // Given a real token position, returns the next real token position.
   TokenPosition Next() {
@@ -101,88 +169,47 @@
     return TokenPosition(value_ + 1);
   }
 
-  // The raw value.
-  // TODO(johnmccutchan): Make this private.
-  intptr_t value() const { return value_; }
-
-  // Return the source position.
-  intptr_t Pos() const {
-    if (IsSynthetic()) {
-      return FromSynthetic().Pos();
-    }
+  // Return the source position for real token positions.
+  inline intptr_t Pos() const {
+    ASSERT(IsReal());
     return value_;
   }
 
   // Is |this| a classifying sentinel source position?
   // Classifying positions are used by the profiler to group instructions whose
   // cost isn't naturally attributable to a source location.
-  bool IsClassifying() const {
+  inline bool IsClassifying() const {
     return (value_ >= kBox.value()) && (value_ <= kLast.value());
   }
 
   // Is |this| the no source position sentinel?
-  bool IsNoSource() const { return *this == kNoSource; }
+  inline bool IsNoSource() const { return value_ == kNoSourcePos; }
 
   // Is |this| a synthetic source position?
   // Synthetic source positions are used by the profiler to attribute ticks to a
   // pieces of source, but ignored by the debugger as potential breakpoints.
-  bool IsSynthetic() const;
+  inline bool IsSynthetic() const { return value_ < kLastPos; }
 
   // Is |this| a real source position?
-  bool IsReal() const { return value_ >= kMinSourcePos; }
-
-  // Is |this| a source position?
-  bool IsSourcePosition() const { return IsReal() || IsSynthetic(); }
-
-  // Convert |this| into a real source position. Sentinel values remain
-  // unchanged.
-  TokenPosition SourcePosition() const { return FromSynthetic(); }
+  inline bool IsReal() const { return value_ >= kMinSourcePos; }
 
   // Is |this| a debug pause source position?
-  bool IsDebugPause() const {
-    // Sanity check some values here.
-    ASSERT(kNoSource.value() == kNoSourcePos);
-    ASSERT(kLast.value() < kNoSource.value());
-    ASSERT(kLast.value() > -kMaxSentinelDescriptors);
-    return IsReal();
-  }
+  inline bool IsDebugPause() const { return IsReal(); }
 
-  // Convert |this| into a synthetic source position. Sentinel values remain
-  // unchanged.
-  TokenPosition ToSynthetic() const {
-    const intptr_t value = value_;
-    if (IsClassifying() || IsNoSource()) {
-      return *this;
-    }
-    if (IsSynthetic()) {
-      return *this;
-    }
-    const TokenPosition synthetic_value =
-        TokenPosition((kLast.value() - 1) - value);
-    ASSERT(synthetic_value.IsSynthetic());
-    ASSERT(synthetic_value.value() < kLast.value());
-    return synthetic_value;
-  }
-
-  // Convert |this| from a synthetic source position. Sentinel values remain
-  // unchanged.
-  TokenPosition FromSynthetic() const {
-    const intptr_t synthetic_value = value_;
-    if (IsClassifying() || IsNoSource()) {
-      return *this;
-    }
-    if (!IsSynthetic()) {
-      return *this;
-    }
-    const TokenPosition value =
-        TokenPosition(-synthetic_value + (kLast.value() - 1));
-    ASSERT(!value.IsSynthetic());
-    return value;
+  // Creates a synthetic source position from a non-negative value.
+  static TokenPosition Synthetic(intptr_t value) {
+    ASSERT(value >= 0 && value <= kMaxSourcePos);
+    return TokenPosition((kLastPos - 1) - value);
   }
 
   const char* ToCString() const;
 
  private:
+  explicit TokenPosition(intptr_t value) : value_(value) {}
+
+  // The raw value of this TokenPosition.
+  intptr_t value() const { return value_; }
+
   int32_t value_;
 
   DISALLOW_ALLOCATION();
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 5f3d862..686b69f 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -35,9 +35,9 @@
     const AbstractType& type) const {
   NoSafepointScope no_safepoint;
   Zone* Z = Thread::Current()->zone();
-  if (type.IsType() && !type.IsFunctionType()) {
+  if (type.IsType()) {
     const intptr_t cid = Type::Cast(type).type_class_id();
-    ClassTable* class_table = Isolate::Current()->class_table();
+    ClassTable* class_table = IsolateGroup::Current()->class_table();
     klass_ = class_table->At(cid);
     ASSERT(!klass_.IsNull());
 
@@ -92,12 +92,12 @@
 CodePtr TypeTestingStubGenerator::DefaultCodeForType(
     const AbstractType& type,
     bool lazy_specialize /* = true */) {
-  auto isolate = Isolate::Current();
+  auto isolate_group = IsolateGroup::Current();
 
   if (type.IsTypeRef()) {
-    return isolate->use_strict_null_safety_checks()
-               ? StubCode::DefaultTypeTest().raw()
-               : StubCode::DefaultNullableTypeTest().raw();
+    return isolate_group->use_strict_null_safety_checks()
+               ? StubCode::DefaultTypeTest().ptr()
+               : StubCode::DefaultNullableTypeTest().ptr();
   }
 
   // During bootstrapping we have no access to stubs yet, so we'll just return
@@ -110,30 +110,36 @@
   }
 
   if (type.IsTopTypeForSubtyping()) {
-    return StubCode::TopTypeTypeTest().raw();
+    return StubCode::TopTypeTypeTest().ptr();
   }
   if (type.IsTypeParameter()) {
     const bool nullable = Instance::NullIsAssignableTo(type);
     if (nullable) {
-      return StubCode::NullableTypeParameterTypeTest().raw();
+      return StubCode::NullableTypeParameterTypeTest().ptr();
     } else {
-      return StubCode::TypeParameterTypeTest().raw();
+      return StubCode::TypeParameterTypeTest().ptr();
     }
   }
 
+  if (type.IsFunctionType()) {
+    const bool nullable = Instance::NullIsAssignableTo(type);
+    return nullable ? StubCode::DefaultNullableTypeTest().ptr()
+                    : StubCode::DefaultTypeTest().ptr();
+  }
+
   if (type.IsType()) {
     const bool should_specialize = !FLAG_precompiled_mode && lazy_specialize;
     const bool nullable = Instance::NullIsAssignableTo(type);
     if (should_specialize) {
-      return nullable ? StubCode::LazySpecializeNullableTypeTest().raw()
-                      : StubCode::LazySpecializeTypeTest().raw();
+      return nullable ? StubCode::LazySpecializeNullableTypeTest().ptr()
+                      : StubCode::LazySpecializeTypeTest().ptr();
     } else {
-      return nullable ? StubCode::DefaultNullableTypeTest().raw()
-                      : StubCode::DefaultTypeTest().raw();
+      return nullable ? StubCode::DefaultNullableTypeTest().ptr()
+                      : StubCode::DefaultTypeTest().ptr();
     }
   }
 
-  return StubCode::UnreachableTypeTest().raw();
+  return StubCode::UnreachableTypeTest().ptr();
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -148,7 +154,7 @@
 #endif
 
 TypeTestingStubGenerator::TypeTestingStubGenerator()
-    : object_store_(Isolate::Current()->object_store()) {}
+    : object_store_(IsolateGroup::Current()->object_store()) {}
 
 CodePtr TypeTestingStubGenerator::OptimizedCodeForType(
     const AbstractType& type) {
@@ -161,7 +167,7 @@
   }
 
   if (type.IsTopTypeForSubtyping()) {
-    return StubCode::TopTypeTypeTest().raw();
+    return StubCode::TopTypeTypeTest().ptr();
   }
 
   if (type.IsCanonical()) {
@@ -170,7 +176,7 @@
       const Code& code = Code::Handle(
           TypeTestingStubGenerator::BuildCodeForType(Type::Cast(type)));
       if (!code.IsNull()) {
-        return code.raw();
+        return code.ptr();
       }
 
       // Fall back to default.
@@ -205,7 +211,7 @@
 
   auto& slow_tts_stub = Code::ZoneHandle(zone);
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    slow_tts_stub = thread->isolate()->object_store()->slow_tts_stub();
+    slow_tts_stub = thread->isolate_group()->object_store()->slow_tts_stub();
   }
 
   // To use the already-defined __ Macro !
@@ -237,6 +243,7 @@
   //   a) We allocate an instructions object, which might cause us to
   //      temporarily flip page protections from (RX -> RW -> RX).
   //
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   thread->isolate_group()->RunWithStoppedMutators(install_code_fun,
                                                   /*use_force_growth=*/true);
 
@@ -257,7 +264,7 @@
   }
 #endif  // !PRODUCT
 
-  return code.raw();
+  return code.ptr();
 }
 
 void TypeTestingStubGenerator::BuildOptimizedTypeTestStubFastCases(
@@ -283,7 +290,7 @@
 
   } else if (type.IsObjectType()) {
     ASSERT(type.IsNonNullable() &&
-           Isolate::Current()->use_strict_null_safety_checks());
+           IsolateGroup::Current()->use_strict_null_safety_checks());
     compiler::Label continue_checking;
     __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
     __ BranchIf(EQUAL, &continue_checking);
@@ -495,7 +502,7 @@
     // Weak NNBD mode uses LEGACY_SUBTYPE which ignores nullability.
     // We don't need to check nullability of LHS for nullable and legacy RHS
     // ("Right Legacy", "Right Nullable" rules).
-    if (Isolate::Current()->use_strict_null_safety_checks() &&
+    if (IsolateGroup::Current()->use_strict_null_safety_checks() &&
         !type_arg.IsNullable() && !type_arg.IsLegacy()) {
       // Nullable type is not a subtype of non-nullable type.
       // TODO(dartbug.com/40736): Allocate a register for instance type argument
@@ -542,7 +549,7 @@
     const Object& object = constant->value();
     ASSERT(object.IsNull() || object.IsTypeArguments());
     const TypeArguments& type_arguments =
-        TypeArguments::Handle(TypeArguments::RawCast(object.raw()));
+        TypeArguments::Handle(TypeArguments::RawCast(object.ptr()));
     type_usage_info->UseTypeArgumentsInInstanceCreation(klass, type_arguments);
   } else if (InstantiateTypeArgumentsInstr* instantiate =
                  type_arguments->AsInstantiateTypeArguments()) {
@@ -572,7 +579,7 @@
     }
     if (cid != kDynamicCid) {
       const Class& instance_klass =
-          Class::Handle(Isolate::Current()->class_table()->At(cid));
+          Class::Handle(IsolateGroup::Current()->class_table()->At(cid));
       if (load_field->slot().IsTypeArguments() && instance_klass.IsGeneric() &&
           compiler::target::Class::TypeArgumentsFieldOffset(instance_klass) ==
               load_field->slot().offset_in_bytes()) {
@@ -675,7 +682,7 @@
     return nullptr;
   } else if (type.IsType()) {
     if (type.IsInstantiated() || type.arguments() == TypeArguments::null()) {
-      return type.raw();
+      return type.ptr();
     }
 
     const Type& from = Type::Cast(type);
@@ -685,14 +692,14 @@
     ScopedHandle<TypeArguments> to_type_arguments(&type_arguments_handles_);
 
     *to_type_arguments = TypeArguments::null();
-    *to = Type::New(klass_, *to_type_arguments, type.token_pos());
+    *to = Type::New(klass_, *to_type_arguments);
 
     *to_type_arguments = from.arguments();
     to->set_arguments(InstantiateTypeArguments(klass_, *to_type_arguments));
     to->SetIsFinalized();
     *to ^= to->Canonicalize(Thread::Current(), nullptr);
 
-    return to->raw();
+    return to->ptr();
   }
   UNREACHABLE();
   return NULL;
@@ -704,7 +711,8 @@
       finder_(zone_),
       assert_assignable_types_(),
       instance_creation_arguments_(
-          new TypeArgumentsSet[thread->isolate()->class_table()->NumCids()]),
+          new TypeArgumentsSet
+              [thread->isolate_group()->class_table()->NumCids()]),
       klass_(Class::Handle(zone_)) {
   thread->set_type_usage_info(this);
 }
@@ -746,12 +754,12 @@
       return;
     }
 
-    klass_ = klass.raw();
+    klass_ = klass.ptr();
     while (klass_.NumTypeArguments() > 0) {
       const intptr_t cid = klass_.id();
       TypeArgumentsSet& set = instance_creation_arguments_[cid];
       if (!set.HasKey(&ta)) {
-        set.Insert(&TypeArguments::ZoneHandle(zone_, ta.raw()));
+        set.Insert(&TypeArguments::ZoneHandle(zone_, ta.ptr()));
       }
       klass_ = klass_.SuperClass();
     }
@@ -759,7 +767,7 @@
 }
 
 void TypeUsageInfo::BuildTypeUsageInformation() {
-  ClassTable* class_table = thread()->isolate()->class_table();
+  ClassTable* class_table = thread()->isolate_group()->class_table();
   const intptr_t cid_count = class_table->NumCids();
 
   // Step 1) Propagate instantiated type argument vectors.
@@ -812,7 +820,7 @@
           if (!klass.IsNull()) {
             // We know that "klass<type_arguments[0:N]>" happens inside
             // [enclosing_class].
-            if (enclosing_class.raw() != klass.raw()) {
+            if (enclosing_class.ptr() != klass.ptr()) {
               // Now we try to instantiate [type_arguments] with all the known
               // instantiator type argument vectors of the [enclosing_class].
               const intptr_t enclosing_class_cid = enclosing_class.id();
@@ -855,7 +863,7 @@
                 TypeArguments::RawCast(delayed_type_argument_set.At(i));
             if (!type_argument_set.HasKey(&temp_type_arguments)) {
               type_argument_set.Insert(
-                  &TypeArguments::ZoneHandle(zone_, temp_type_arguments.raw()));
+                  &TypeArguments::ZoneHandle(zone_, temp_type_arguments.ptr()));
             }
           }
           klass = klass.SuperClass();
@@ -927,16 +935,16 @@
                                         const AbstractType* type,
                                         TypeParameter* param) {
   if (type->IsTypeParameter()) {
-    *param ^= type->raw();
+    *param ^= type->ptr();
     if (!param->IsNull() && !set->HasKey(param)) {
-      set->Insert(&TypeParameter::Handle(zone_, param->raw()));
+      set->Insert(&TypeParameter::Handle(zone_, param->ptr()));
     }
   }
 }
 
 void TypeUsageInfo::AddTypeToSet(TypeSet* set, const AbstractType* type) {
   if (!set->HasKey(type)) {
-    set->Insert(&AbstractType::ZoneHandle(zone_, type->raw()));
+    set->Insert(&AbstractType::ZoneHandle(zone_, type->ptr()));
   }
 }
 
diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h
index 09c6f1d..848ae1a 100644
--- a/runtime/vm/type_testing_stubs.h
+++ b/runtime/vm/type_testing_stubs.h
@@ -193,17 +193,7 @@
  private:
   bool FindClassFromType(const AbstractType& type) {
     if (type.IsTypeParameter()) {
-      const TypeParameter& parameter = TypeParameter::Cast(type);
-      if (!parameter.IsClassTypeParameter()) {
-        return false;
-      }
-      if (klass_.IsNull()) {
-        klass_ = parameter.parameterized_class();
-      } else {
-        // Dart has no support for nested classes.
-        ASSERT(klass_.raw() == parameter.parameterized_class());
-      }
-      return true;
+      return false;
     } else if (type.IsFunctionType()) {
       // No support for function types yet.
       return false;
@@ -250,8 +240,8 @@
       const Class& klass,
       const TypeArguments& type_arguments,
       const TypeArguments& instantiator_type_arguments) {
-    instantiator_type_arguments_ = instantiator_type_arguments.raw();
-    return InstantiateTypeArguments(klass, type_arguments).raw();
+    instantiator_type_arguments_ = instantiator_type_arguments.ptr();
+    return InstantiateTypeArguments(klass, type_arguments).ptr();
   }
 
  private:
@@ -312,7 +302,7 @@
    public:
     static inline bool IsKeyEqual(const TypeArguments* pair,
                                   const TypeArguments* key) {
-      return pair->raw() == key->raw();
+      return pair->ptr() == key->ptr();
     }
   };
 
@@ -320,7 +310,7 @@
    public:
     static inline bool IsKeyEqual(const TypeParameter* pair,
                                   const TypeParameter* key) {
-      return pair->raw() == key->raw();
+      return pair->ptr() == key->ptr();
     }
   };
 
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
index 9cc1045..bf9e154 100644
--- a/runtime/vm/type_testing_stubs_test.cc
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -7,10 +7,10 @@
 #include "platform/assert.h"
 
 #include "vm/class_finalizer.h"
+#include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/il_test_helper.h"
 #include "vm/symbols.h"
 #include "vm/type_testing_stubs.h"
-#include "vm/type_testing_stubs_test.h"
 #include "vm/unit_test.h"
 
 #if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM) ||                  \
@@ -18,6 +18,129 @@
 
 namespace dart {
 
+#define __ assembler->
+
+static void GenerateInvokeTTSStub(compiler::Assembler* assembler) {
+  auto calculate_breadcrumb = [](const Register& reg) {
+    return 0x10 + 2 * (static_cast<intptr_t>(reg));
+  };
+
+  __ EnterDartFrame(0);
+
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
+    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
+    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
+    const Register reg = static_cast<Register>(i);
+    __ LoadImmediate(reg, calculate_breadcrumb(reg));
+  }
+
+  // Load the arguments into the right TTS calling convention registers.
+  const intptr_t instance_offset =
+      (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize;
+  const intptr_t inst_type_args_offset =
+      (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize;
+  const intptr_t fun_type_args_offset =
+      (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize;
+  const intptr_t dst_type_offset =
+      (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize;
+
+  __ LoadMemoryValue(TypeTestABI::kInstanceReg, FPREG, instance_offset);
+  __ LoadMemoryValue(TypeTestABI::kInstantiatorTypeArgumentsReg, FPREG,
+                     inst_type_args_offset);
+  __ LoadMemoryValue(TypeTestABI::kFunctionTypeArgumentsReg, FPREG,
+                     fun_type_args_offset);
+  __ LoadMemoryValue(TypeTestABI::kDstTypeReg, FPREG, dst_type_offset);
+
+  const intptr_t subtype_test_cache_index = __ object_pool_builder().AddObject(
+      Object::null_object(), compiler::ObjectPoolBuilderEntry::kPatchable);
+  const intptr_t dst_name_index = __ object_pool_builder().AddObject(
+      Symbols::OptimizedOut(), compiler::ObjectPoolBuilderEntry::kPatchable);
+  ASSERT_EQUAL(subtype_test_cache_index + 1, dst_name_index);
+  ASSERT(__ constant_pool_allowed());
+
+  FlowGraphCompiler::GenerateIndirectTTSCall(
+      assembler, TypeTestABI::kDstTypeReg, subtype_test_cache_index);
+
+  // We have the guarantee that TTS preserves all input registers, if the TTS
+  // handles the type test successfully.
+  //
+  // Let the test know which TTS abi registers were not preserved.
+  ASSERT(((1 << static_cast<intptr_t>(TypeTestABI::kInstanceReg)) &
+          TypeTestABI::kPreservedAbiRegisters) != 0);
+  // First we check the instance register, freeing it up in case there are no
+  // other safe registers to use since we need two registers: one to accumulate
+  // the register mask, another to load the array address when saving the mask.
+  __ LoadFromOffset(TypeTestABI::kScratchReg, FPREG, instance_offset);
+  compiler::Label instance_matches, done_with_instance;
+  __ CompareRegisters(TypeTestABI::kScratchReg, TypeTestABI::kInstanceReg);
+  __ BranchIf(EQUAL, &instance_matches, compiler::Assembler::kNearJump);
+  __ LoadImmediate(TypeTestABI::kScratchReg,
+                   1 << static_cast<intptr_t>(TypeTestABI::kInstanceReg));
+  __ Jump(&done_with_instance, compiler::Assembler::kNearJump);
+  __ Bind(&instance_matches);
+  __ LoadImmediate(TypeTestABI::kScratchReg, 0);
+  __ Bind(&done_with_instance);
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & TypeTestABI::kPreservedAbiRegisters) == 0) continue;
+    const Register reg = static_cast<Register>(i);
+    compiler::Label done;
+    switch (reg) {
+      case TypeTestABI::kInstanceReg:
+        // Skip the already handled instance register.
+        continue;
+      case TypeTestABI::kDstTypeReg:
+        __ LoadFromOffset(TypeTestABI::kInstanceReg, FPREG, dst_type_offset);
+        break;
+      case TypeTestABI::kFunctionTypeArgumentsReg:
+        __ LoadFromOffset(TypeTestABI::kInstanceReg, FPREG,
+                          fun_type_args_offset);
+        break;
+      case TypeTestABI::kInstantiatorTypeArgumentsReg:
+        __ LoadFromOffset(TypeTestABI::kInstanceReg, FPREG,
+                          inst_type_args_offset);
+        break;
+      default:
+        FATAL("Unexpected register %s", RegisterNames::RegisterName(reg));
+        break;
+    }
+    __ CompareRegisters(reg, TypeTestABI::kInstanceReg);
+    __ BranchIf(EQUAL, &done, compiler::Assembler::kNearJump);
+    __ AddImmediate(TypeTestABI::kScratchReg, 1 << i);
+    __ Bind(&done);
+  }
+  __ SmiTag(TypeTestABI::kScratchReg);
+  __ LoadFromOffset(TypeTestABI::kInstanceReg, FPREG,
+                    (kCallerSpSlotFromFp + 5) * compiler::target::kWordSize);
+  __ StoreFieldToOffset(TypeTestABI::kScratchReg, TypeTestABI::kInstanceReg,
+                        compiler::target::Array::element_offset(0));
+
+  // Let the test know which non-TTS abi registers were not preserved.
+  __ LoadImmediate(TypeTestABI::kScratchReg, 0);
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
+    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
+    const Register reg = static_cast<Register>(i);
+    compiler::Label done;
+    __ CompareImmediate(reg, calculate_breadcrumb(reg));
+    __ BranchIf(EQUAL, &done, compiler::Assembler::kNearJump);
+    __ AddImmediate(TypeTestABI::kScratchReg, 1 << i);
+    __ Bind(&done);
+  }
+  __ SmiTag(TypeTestABI::kScratchReg);
+  __ LoadFromOffset(TypeTestABI::kInstanceReg, FPREG,
+                    (kCallerSpSlotFromFp + 4) * compiler::target::kWordSize);
+  __ StoreFieldToOffset(TypeTestABI::kScratchReg, TypeTestABI::kInstanceReg,
+                        compiler::target::Array::element_offset(0));
+
+  // Set the return from the stub to be null.
+  __ LoadObject(CallingConventions::kReturnReg, Object::null_object());
+  __ LeaveDartFrame();
+  __ Ret();
+}
+
+#undef __
+
 static void FinalizeAndCanonicalize(AbstractType* type) {
   *type = ClassFinalizer::FinalizeType(*type);
   ASSERT(type->IsCanonical());
@@ -35,31 +158,32 @@
     std::function<void(const Object& result, const SubtypeTestCache& stc)> lazy,
     std::function<void(const Object& result,
                        const SubtypeTestCache& stc,
-                       const Bool& abi_regs_modified,
-                       const Bool& rest_regs_modified)> nonlazy) {
+                       const Smi& abi_regs_modified,
+                       const Smi& rest_regs_modified)> nonlazy) {
   ASSERT(instantiator_tav.IsNull() || instantiator_tav.IsCanonical());
   ASSERT(function_tav.IsNull() || function_tav.IsCanonical());
   auto thread = Thread::Current();
 
   // Build a stub which will do calling conversion to call TTS stubs.
   const auto& klass =
-      Class::Handle(thread->isolate()->class_table()->At(kInstanceCid));
+      Class::Handle(thread->isolate_group()->class_table()->At(kInstanceCid));
   const auto& symbol = String::Handle(
       Symbols::New(thread, OS::SCreate(thread->zone(), "TTSTest")));
-  const auto& function = Function::Handle(
-      Function::New(symbol, FunctionLayout::kRegularFunction, false, false,
-                    false, false, false, klass, TokenPosition::kNoSource));
+  const auto& signature = FunctionType::ZoneHandle(FunctionType::New());
+  const auto& function = Function::Handle(Function::New(
+      signature, symbol, UntaggedFunction::kRegularFunction, false, false,
+      false, false, false, klass, TokenPosition::kNoSource));
   compiler::ObjectPoolBuilder pool_builder;
   const auto& invoke_tts = Code::Handle(
       StubCode::Generate("InvokeTTS", &pool_builder, &GenerateInvokeTTSStub));
   const auto& pool =
       ObjectPool::Handle(ObjectPool::NewFromBuilder(pool_builder));
-  invoke_tts.set_object_pool(pool.raw());
+  invoke_tts.set_object_pool(pool.ptr());
   invoke_tts.set_owner(function);
   invoke_tts.set_exception_handlers(
       ExceptionHandlers::Handle(ExceptionHandlers::New(0)));
 
-  EXPECT(pool.Length() == 2);
+  EXPECT_EQ(2, pool.Length());
   const intptr_t kSubtypeTestCacheIndex = 0;
 
   const auto& arguments_descriptor =
@@ -75,20 +199,20 @@
   arguments.SetAt(5, dst_type);
 
   // Ensure we have a) uninitialized TTS b) no/empty SubtypeTestCache.
-  auto& instantiated_dst_type = AbstractType::Handle(dst_type.raw());
+  auto& instantiated_dst_type = AbstractType::Handle(dst_type.ptr());
   if (dst_type.IsTypeParameter()) {
     instantiated_dst_type = TypeParameter::Cast(dst_type).GetFromTypeArguments(
         instantiator_tav, function_tav);
   }
   instantiated_dst_type.SetTypeTestingStub(StubCode::LazySpecializeTypeTest());
   EXPECT(instantiated_dst_type.type_test_stub() ==
-         StubCode::LazySpecializeTypeTest().raw());
+         StubCode::LazySpecializeTypeTest().ptr());
   EXPECT(pool.ObjectAt(kSubtypeTestCacheIndex) == Object::null());
 
   auto& result = Object::Handle();
   auto& result2 = Object::Handle();
-  auto& abi_regs_modified = Bool::Handle();
-  auto& rest_regs_modified = Bool::Handle();
+  auto& abi_regs_modified = Smi::Handle();
+  auto& rest_regs_modified = Smi::Handle();
   auto& tts = Code::Handle();
   auto& tts2 = Code::Handle();
   auto& stc = SubtypeTestCache::Handle();
@@ -100,7 +224,7 @@
   stc ^= pool.ObjectAt(kSubtypeTestCacheIndex);
   tts = instantiated_dst_type.type_test_stub();
   if (!result.IsError()) {
-    EXPECT(tts.raw() != StubCode::LazySpecializeTypeTest().raw());
+    EXPECT(tts.ptr() != StubCode::LazySpecializeTypeTest().ptr());
   }
   lazy(result, stc);
 
@@ -112,8 +236,8 @@
   abi_regs_modified ^= abi_regs_modified_box.At(0);
   rest_regs_modified ^= rest_regs_modified_box.At(0);
   EXPECT(result2.IsError() || !abi_regs_modified.IsNull());
-  EXPECT(tts2.raw() == tts.raw());
-  EXPECT(stc2.raw() == stc.raw());
+  EXPECT(tts2.ptr() == tts.ptr());
+  EXPECT(stc2.ptr() == stc.ptr());
   nonlazy(result2, stc2, abi_regs_modified, rest_regs_modified);
 
   // Third invocation will a) explicitly install TTS beforehand b) keep optional
@@ -130,73 +254,108 @@
   abi_regs_modified ^= abi_regs_modified_box.At(0);
   rest_regs_modified ^= rest_regs_modified_box.At(0);
   EXPECT(result2.IsError() || !abi_regs_modified.IsNull());
-  EXPECT(tts2.raw() == tts.raw());
-  EXPECT(stc2.raw() == stc.raw());
+  EXPECT(tts2.ptr() == tts.ptr());
+  EXPECT(stc2.ptr() == stc.ptr());
   nonlazy(result2, stc2, abi_regs_modified, rest_regs_modified);
 }
 
-static void ExpectLazilyHandledViaTTS(const Object& result,
-                                      const SubtypeTestCache& stc) {
+static void ReportModifiedRegisters(const Smi& modified_registers) {
+  const intptr_t reg_mask = Smi::Cast(modified_registers).Value();
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    if (((1 << i) & reg_mask) != 0) {
+      const Register reg = static_cast<Register>(i);
+      dart::Expect(__FILE__, __LINE__)
+          .Fail("%s was modified", RegisterNames::RegisterName(reg));
+    }
+  }
+}
+
+static void CommonTTSHandledChecks(const Object& result,
+                                   const SubtypeTestCache& stc) {
   // Ensure the type test succeeded.
   EXPECT(result.IsNull());
   // Ensure we didn't fall back to the subtype test cache.
   EXPECT(stc.IsNull());
 }
 
-static void ExpectHandledViaTTS(const Object& result,
-                                const SubtypeTestCache& stc,
-                                const Bool& abi_regs_modified,
-                                const Bool& rest_regs_modified) {
-  ExpectLazilyHandledViaTTS(result, stc);
-  // Ensure the TTS abi registers were preserved.
-  EXPECT(!abi_regs_modified.value());
-  // Ensure the non-TTS abi registers were preserved.
-  EXPECT(!rest_regs_modified.value());
+static void ExpectLazilyHandledViaTTS(const Object& result,
+                                      const SubtypeTestCache& stc) {
+  THR_Print("Testing lazy handled via TTS\n");
+  CommonTTSHandledChecks(result, stc);
 }
 
-static void ExpectLazilyHandledViaSTC(const Object& result,
-                                      const SubtypeTestCache& stc) {
+static void ExpectHandledViaTTS(const Object& result,
+                                const SubtypeTestCache& stc,
+                                const Smi& abi_regs_modified,
+                                const Smi& rest_regs_modified) {
+  THR_Print("Testing non-lazy handled via TTS\n");
+  CommonTTSHandledChecks(result, stc);
+  // Ensure the TTS abi registers were preserved.
+  ReportModifiedRegisters(abi_regs_modified);
+  // Ensure the non-TTS abi registers were preserved.
+  ReportModifiedRegisters(rest_regs_modified);
+}
+
+static void CommonSTCHandledChecks(const Object& result,
+                                   const SubtypeTestCache& stc) {
   // Ensure the type test succeeded.
   EXPECT(result.IsNull());
   // Ensure we did fall back to the subtype test cache.
   EXPECT(!stc.IsNull());
   // Ensure the test is marked as succeeding in the STC.
-  EXPECT(stc.NumberOfChecks() == 1);
+  EXPECT_EQ(1, stc.NumberOfChecks());
   SubtypeTestCacheTable entries(Array::Handle(stc.cache()));
   EXPECT(entries[0].Get<SubtypeTestCache::kTestResult>() ==
-         Object::bool_true().raw());
+         Object::bool_true().ptr());
+}
+
+static void ExpectLazilyHandledViaSTC(const Object& result,
+                                      const SubtypeTestCache& stc) {
+  THR_Print("Testing lazy handled via STC\n");
+  CommonSTCHandledChecks(result, stc);
 }
 
 static void ExpectHandledViaSTC(const Object& result,
                                 const SubtypeTestCache& stc,
-                                const Bool& abi_regs_modified,
-                                const Bool& rest_regs_modified) {
-  ExpectLazilyHandledViaSTC(result, stc);
+                                const Smi& abi_regs_modified,
+                                const Smi& rest_regs_modified) {
+  THR_Print("Testing non-lazy handled via STC\n");
+  CommonSTCHandledChecks(result, stc);
   // Ensure the TTS/STC abi registers were preserved.
-  EXPECT(!abi_regs_modified.value());
+  ReportModifiedRegisters(abi_regs_modified);
+  // Ensure the non-TTS abi registers were preserved.
+  ReportModifiedRegisters(rest_regs_modified);
+}
+
+static void CommonTTSFailureChecks(const Object& result,
+                                   const SubtypeTestCache& stc) {
+  // Ensure we have not updated STC (which we shouldn't do in case the type test
+  // fails, i.e. an exception is thrown).
+  EXPECT(stc.IsNull());
+  // Ensure we get a proper exception for the type test.
+  EXPECT(result.IsUnhandledException());
+  const auto& error =
+      Instance::Handle(UnhandledException::Cast(result).exception());
+  EXPECT(strstr(error.ToCString(), "_TypeError"));
 }
 
 static void ExpectLazilyFailedViaTTS(const Object& result,
                                      const SubtypeTestCache& stc) {
-  // Ensure we have not updated STC (which we shouldn't do in case the type test
-  // fails, i.e. an exception is thrown).
-  EXPECT(stc.IsNull());
-  // Ensure we get a proper exception for the type test.
-  EXPECT(result.IsUnhandledException());
-  const auto& error =
-      Instance::Handle(UnhandledException::Cast(result).exception());
-  EXPECT(strstr(error.ToCString(), "_TypeError"));
+  THR_Print("Testing lazy failure via TTS\n");
+  CommonTTSFailureChecks(result, stc);
 }
 
 static void ExpectFailedViaTTS(const Object& result,
                                const SubtypeTestCache& stc,
-                               const Bool& abi_regs_modified,
-                               const Bool& rest_regs_modified) {
-  ExpectLazilyFailedViaTTS(result, stc);
+                               const Smi& abi_regs_modified,
+                               const Smi& rest_regs_modified) {
+  THR_Print("Testing nonlazy failure via TTS\n");
+  CommonTTSFailureChecks(result, stc);
+  // Registers only need to be preserved on success.
 }
 
-static void ExpectLazilyFailedViaSTC(const Object& result,
-                                     const SubtypeTestCache& stc) {
+static void CommonSTCFailureChecks(const Object& result,
+                                   const SubtypeTestCache& stc) {
   // Ensure we have not updated STC (which we shouldn't do in case the type test
   // fails, i.e. an exception is thrown).
   EXPECT(stc.IsNull());
@@ -207,11 +366,19 @@
   EXPECT(strstr(error.ToCString(), "_TypeError"));
 }
 
+static void ExpectLazilyFailedViaSTC(const Object& result,
+                                     const SubtypeTestCache& stc) {
+  THR_Print("Testing lazy failure via STC\n");
+  CommonSTCFailureChecks(result, stc);
+}
+
 static void ExpectFailedViaSTC(const Object& result,
                                const SubtypeTestCache& stc,
-                               const Bool& abi_regs_modified,
-                               const Bool& rest_regs_modified) {
-  ExpectLazilyFailedViaSTC(result, stc);
+                               const Smi& abi_regs_modified,
+                               const Smi& rest_regs_modified) {
+  THR_Print("Testing non-lazy failure via STC\n");
+  CommonSTCFailureChecks(result, stc);
+  // Registers only need to be preserved on success.
 }
 
 const char* kSubtypeRangeCheckScript =
@@ -318,8 +485,7 @@
              ExpectFailedViaTTS);
 
   // <...> as Base<Object>
-  auto& type_base = AbstractType::Handle(
-      Type::New(class_base, tav_object, TokenPosition::kNoSource));
+  auto& type_base = AbstractType::Handle(Type::New(class_base, tav_object));
   FinalizeAndCanonicalize(&type_base);
   RunTTSTest(obj_i, type_base, tav_null, tav_null, ExpectLazilyFailedViaTTS,
              ExpectFailedViaTTS);
@@ -362,8 +528,8 @@
              ExpectFailedViaTTS);
 
   // <...> as I<Object, dynamic>
-  auto& type_i_object_dynamic = AbstractType::Handle(
-      Type::New(class_i, tav_object_dynamic, TokenPosition::kNoSource));
+  auto& type_i_object_dynamic =
+      AbstractType::Handle(Type::New(class_i, tav_object_dynamic));
   FinalizeAndCanonicalize(&type_i_object_dynamic);
   RunTTSTest(obj_i, type_i_object_dynamic, tav_null, tav_null,
              ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
@@ -389,8 +555,8 @@
   //
   //   obj as I<dynamic, T>
   //
-  auto& type_dynamic_t = AbstractType::Handle(
-      Type::New(class_i, tav_dynamic_t, TokenPosition::kNoSource));
+  auto& type_dynamic_t =
+      AbstractType::Handle(Type::New(class_i, tav_dynamic_t));
   FinalizeAndCanonicalize(&type_dynamic_t);
   RunTTSTest(obj_i, type_dynamic_t, tav_object, tav_null,
              ExpectLazilyHandledViaSTC, ExpectHandledViaSTC);
@@ -412,10 +578,10 @@
              ExpectLazilyHandledViaSTC, ExpectHandledViaSTC);
 
   // obj as Object (with null safety)
-  Isolate* isolate = Isolate::Current();
-  if (isolate->null_safety()) {
+  auto isolate_group = IsolateGroup::Current();
+  if (isolate_group->null_safety()) {
     auto& type_non_nullable_object =
-        Type::Handle(isolate->object_store()->non_nullable_object_type());
+        Type::Handle(isolate_group->object_store()->non_nullable_object_type());
     RunTTSTest(obj_a, type_non_nullable_object, tav_null, tav_null,
                ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
     RunTTSTest(Object::null_object(), type_non_nullable_object, tav_null,
@@ -492,8 +658,8 @@
   tav_int.SetTypeAt(0, type_int);
   CanonicalizeTAV(&tav_int);
 
-  auto& type_i_object_dynamic = AbstractType::Handle(
-      Type::New(class_i, tav_object_dynamic, TokenPosition::kNoSource));
+  auto& type_i_object_dynamic =
+      AbstractType::Handle(Type::New(class_i, tav_object_dynamic));
   FinalizeAndCanonicalize(&type_i_object_dynamic);
   const auto& tav_iod = TypeArguments::Handle(TypeArguments::New(1));
   tav_iod.SetTypeAt(0, type_i_object_dynamic);
@@ -511,8 +677,8 @@
   //
 
   // <...> as Base<I<Object, dynamic>>
-  auto& type_base_i_object_dynamic = AbstractType::Handle(
-      Type::New(class_base, tav_iod, TokenPosition::kNoSource));
+  auto& type_base_i_object_dynamic =
+      AbstractType::Handle(Type::New(class_base, tav_iod));
   FinalizeAndCanonicalize(&type_base_i_object_dynamic);
   RunTTSTest(obj_baseb2int, type_base_i_object_dynamic, tav_null, tav_null,
              ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
@@ -535,8 +701,7 @@
   const auto& tav_baset = TypeArguments::Handle(TypeArguments::New(1));
   tav_baset.SetTypeAt(
       0, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
-  auto& type_base_t = AbstractType::Handle(
-      Type::New(class_base, tav_baset, TokenPosition::kNoSource));
+  auto& type_base_t = AbstractType::Handle(Type::New(class_base, tav_baset));
   FinalizeAndCanonicalize(&type_base_t);
   RunTTSTest(obj_baseint, type_base_t, tav_int, tav_null,
              ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
@@ -547,8 +712,7 @@
   const auto& tav_baseb = TypeArguments::Handle(TypeArguments::New(1));
   tav_baseb.SetTypeAt(
       0, TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, "B")));
-  auto& type_base_b = AbstractType::Handle(
-      Type::New(class_base, tav_baseb, TokenPosition::kNoSource));
+  auto& type_base_b = AbstractType::Handle(Type::New(class_base, tav_baseb));
   FinalizeAndCanonicalize(&type_base_b);
   // With B == int
   RunTTSTest(obj_baseint, type_base_b, tav_null, tav_dynamic_int,
@@ -571,8 +735,8 @@
 
   //   <...> as I<dynamic, String>
   RELEASE_ASSERT(class_i.is_implemented());
-  auto& type_i_dynamic_string = Type::Handle(
-      Type::New(class_i, tav_dynamic_string, TokenPosition::kNoSource));
+  auto& type_i_dynamic_string =
+      Type::Handle(Type::New(class_i, tav_dynamic_string));
   type_i_dynamic_string = type_i_dynamic_string.ToNullability(
       Nullability::kNonNullable, Heap::kNew);
   FinalizeAndCanonicalize(&type_i_dynamic_string);
@@ -585,14 +749,12 @@
   const auto& tav_t = TypeArguments::Handle(TypeArguments::New(1));
   tav_t.SetTypeAt(
       0, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
-  auto& type_a2_t =
-      Type::Handle(Type::New(class_a2, tav_t, TokenPosition::kNoSource));
+  auto& type_a2_t = Type::Handle(Type::New(class_a2, tav_t));
   type_a2_t = type_a2_t.ToNullability(Nullability::kLegacy, Heap::kNew);
   FinalizeAndCanonicalize(&type_a2_t);
   const auto& tav_a2_t = TypeArguments::Handle(TypeArguments::New(1));
   tav_a2_t.SetTypeAt(0, type_a2_t);
-  auto& type_base_a2_t =
-      Type::Handle(Type::New(class_base, tav_a2_t, TokenPosition::kNoSource));
+  auto& type_base_a2_t = Type::Handle(Type::New(class_base, tav_a2_t));
   type_base_a2_t =
       type_base_a2_t.ToNullability(Nullability::kNonNullable, Heap::kNew);
   FinalizeAndCanonicalize(&type_base_a2_t);
@@ -604,14 +766,12 @@
   //   <...> as Base<A2<A1>>
   const auto& tav_a1 = TypeArguments::Handle(TypeArguments::New(1));
   tav_a1.SetTypeAt(0, type_a1);
-  auto& type_a2_a1 =
-      Type::Handle(Type::New(class_a2, tav_a1, TokenPosition::kNoSource));
+  auto& type_a2_a1 = Type::Handle(Type::New(class_a2, tav_a1));
   type_a2_a1 = type_a2_a1.ToNullability(Nullability::kLegacy, Heap::kNew);
   FinalizeAndCanonicalize(&type_a2_a1);
   const auto& tav_a2_a1 = TypeArguments::Handle(TypeArguments::New(1));
   tav_a2_a1.SetTypeAt(0, type_a2_a1);
-  auto& type_base_a2_a1 =
-      Type::Handle(Type::New(class_base, tav_a2_a1, TokenPosition::kNoSource));
+  auto& type_base_a2_a1 = Type::Handle(Type::New(class_base, tav_a2_a1));
   type_base_a2_a1 =
       type_base_a2_a1.ToNullability(Nullability::kNonNullable, Heap::kNew);
   FinalizeAndCanonicalize(&type_base_a2_a1);
@@ -646,8 +806,7 @@
   const auto& dst_tav = TypeArguments::Handle(TypeArguments::New(1));
   dst_tav.SetTypeAt(0,
                     TypeParameter::Handle(GetClassTypeParameter(class_b, "T")));
-  auto& dst_type =
-      Type::Handle(Type::New(class_b, dst_tav, TokenPosition::kNoSource));
+  auto& dst_type = Type::Handle(Type::New(class_b, dst_tav));
   FinalizeAndCanonicalize(&dst_type);
   const auto& cint_tav =
       TypeArguments::Handle(Instance::Cast(acint).GetTypeArguments());
@@ -683,6 +842,7 @@
 
   const auto& dst_type_t =
       TypeParameter::Handle(GetClassTypeParameter(class_a, "T"));
+
   const auto& dst_type_h =
       TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, "H"));
 
@@ -697,11 +857,15 @@
   const auto& int_instance = Integer::Handle(Integer::New(1));
   const auto& string_instance = String::Handle(String::New("foo"));
 
+  THR_Print("Testing int instance, class parameter instantiated to int\n");
   RunTTSTest(int_instance, dst_type_t, int_tav, string_tav,
              ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  THR_Print("\nTesting string instance, class parameter instantiated to int\n");
   RunTTSTest(string_instance, dst_type_t, int_tav, string_tav,
              ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
 
+  THR_Print(
+      "\nTesting string instance, function parameter instantiated to string\n");
   RunTTSTest(string_instance, dst_type_h, int_tav, string_tav,
              ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
   RunTTSTest(int_instance, dst_type_h, int_tav, string_tav,
diff --git a/runtime/vm/type_testing_stubs_test.h b/runtime/vm/type_testing_stubs_test.h
deleted file mode 100644
index c11f2d8..0000000
--- a/runtime/vm/type_testing_stubs_test.h
+++ /dev/null
@@ -1,26 +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.
-
-#ifndef RUNTIME_VM_TYPE_TESTING_STUBS_TEST_H_
-#define RUNTIME_VM_TYPE_TESTING_STUBS_TEST_H_
-
-#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM) ||                  \
-    defined(TARGET_ARCH_X64)
-
-#include "include/dart_api.h"
-
-namespace dart {
-
-namespace compiler {
-class Assembler;
-}
-
-void GenerateInvokeTTSStub(compiler::Assembler* assembler);
-
-}  // namespace dart
-
-#endif  // defined(TARGET_ARCH_ARM64) ||  defined(TARGET_ARCH_ARM) ||          \
-        // defined(TARGET_ARCH_X64)
-
-#endif  // RUNTIME_VM_TYPE_TESTING_STUBS_TEST_H_
diff --git a/runtime/vm/type_testing_stubs_test_arm.cc b/runtime/vm/type_testing_stubs_test_arm.cc
deleted file mode 100644
index 0391fe9..0000000
--- a/runtime/vm/type_testing_stubs_test_arm.cc
+++ /dev/null
@@ -1,121 +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.
-
-#include "platform/globals.h"
-
-#if defined(TARGET_ARCH_ARM)
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/runtime_api.h"
-#include "vm/constants.h"
-#include "vm/object.h"
-#include "vm/stack_frame.h"
-#include "vm/symbols.h"
-
-#define __ assembler->
-
-namespace dart {
-
-void GenerateInvokeTTSStub(compiler::Assembler* assembler) {
-  __ EnterDartFrame(0);
-
-  intptr_t sum = 0;
-  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
-    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
-    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
-    __ LoadImmediate(static_cast<Register>(i), 0x10 + 2 * i);
-    sum += 0x10 + 2 * i;
-  }
-
-  // Load the arguments into the right TTS calling convention registers.
-  __ ldr(TypeTestABI::kInstanceReg,
-         compiler::Address(
-             FP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
-  __ ldr(TypeTestABI::kInstantiatorTypeArgumentsReg,
-         compiler::Address(
-             FP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
-  __ ldr(TypeTestABI::kFunctionTypeArgumentsReg,
-         compiler::Address(
-             FP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
-  __ ldr(TypeTestABI::kDstTypeReg,
-         compiler::Address(
-             FP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
-
-  const intptr_t sub_type_cache_index = __ object_pool_builder().AddObject(
-      Object::null_object(), compiler::ObjectPoolBuilderEntry::kPatchable);
-  const intptr_t dst_name_index = __ object_pool_builder().AddObject(
-      Symbols::OptimizedOut(), compiler::ObjectPoolBuilderEntry::kPatchable);
-  ASSERT((sub_type_cache_index + 1) == dst_name_index);
-  ASSERT(__ constant_pool_allowed());
-
-  // Call the TTS.
-  __ ldr(R9, compiler::FieldAddress(
-                 TypeTestABI::kDstTypeReg,
-                 AbstractType::type_test_stub_entry_point_offset()));
-  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
-                           sub_type_cache_index);
-  __ blx(R9);
-
-  // We have the guarantee that TTS preserve all registers except for one
-  // scratch register atm (if the TTS handles the type test successfully).
-  //
-  // Let the test know whether TTS abi registers were preserved.
-  compiler::Label abi_regs_modified, store_abi_regs_modified_bool;
-  __ CompareWithMemoryValue(
-      TypeTestABI::kInstanceReg,
-      compiler::Address(
-          FP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ CompareWithMemoryValue(
-      TypeTestABI::kInstantiatorTypeArgumentsReg,
-      compiler::Address(
-          FP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ CompareWithMemoryValue(
-      TypeTestABI::kFunctionTypeArgumentsReg,
-      compiler::Address(
-          FP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ CompareWithMemoryValue(
-      TypeTestABI::kDstTypeReg,
-      compiler::Address(
-          FP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ ldr(R0, compiler::Address(THR, Thread::bool_false_offset()));
-  __ b(&store_abi_regs_modified_bool);
-  __ Bind(&abi_regs_modified);
-  __ ldr(R0, compiler::Address(THR, Thread::bool_true_offset()));
-  __ Bind(&store_abi_regs_modified_bool);
-  __ ldr(TMP, compiler::Address(
-                  FP, (kCallerSpSlotFromFp + 5) * compiler::target::kWordSize));
-  __ str(R0, compiler::FieldAddress(TMP, Array::element_offset(0)));
-
-  // Let the test know whether the non-TTS abi registers were preserved.
-  compiler::Label rest_regs_modified, store_rest_regs_modified_bool;
-  __ mov(TMP, compiler::Operand(0));
-  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
-    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
-    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
-    __ add(TMP, TMP, compiler::Operand(static_cast<Register>(i)));
-  }
-  __ cmp(TMP, compiler::Operand(sum));
-  __ BranchIf(NOT_EQUAL, &rest_regs_modified);
-  __ ldr(R0, compiler::Address(THR, Thread::bool_false_offset()));
-  __ b(&store_rest_regs_modified_bool);
-  __ Bind(&rest_regs_modified);
-  __ ldr(R0, compiler::Address(THR, Thread::bool_true_offset()));
-  __ Bind(&store_rest_regs_modified_bool);
-  __ ldr(TMP, compiler::Address(
-                  FP, (kCallerSpSlotFromFp + 4) * compiler::target::kWordSize));
-  __ str(R0, compiler::FieldAddress(TMP, Array::element_offset(0)));
-
-  __ LoadObject(R0, Object::null_object());
-  __ LeaveDartFrameAndReturn();
-}
-
-}  // namespace dart
-
-#endif  // defined(TARGET_ARCH_ARM)
diff --git a/runtime/vm/type_testing_stubs_test_arm64.cc b/runtime/vm/type_testing_stubs_test_arm64.cc
deleted file mode 100644
index 39f7d36..0000000
--- a/runtime/vm/type_testing_stubs_test_arm64.cc
+++ /dev/null
@@ -1,122 +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.
-
-#include "platform/globals.h"
-
-#if defined(TARGET_ARCH_ARM64)
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/runtime_api.h"
-#include "vm/constants.h"
-#include "vm/object.h"
-#include "vm/stack_frame.h"
-#include "vm/symbols.h"
-
-#define __ assembler->
-
-namespace dart {
-
-void GenerateInvokeTTSStub(compiler::Assembler* assembler) {
-  __ EnterDartFrame(0);
-
-  intptr_t sum = 0;
-  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
-    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
-    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
-    __ LoadImmediate(static_cast<Register>(i), 0x10 + 2 * i);
-    sum += 0x10 + 2 * i;
-  }
-
-  // Load the arguments into the right TTS calling convention registers.
-  __ ldr(TypeTestABI::kInstanceReg,
-         compiler::Address(
-             FP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
-  __ ldr(TypeTestABI::kInstantiatorTypeArgumentsReg,
-         compiler::Address(
-             FP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
-  __ ldr(TypeTestABI::kFunctionTypeArgumentsReg,
-         compiler::Address(
-             FP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
-  __ ldr(TypeTestABI::kDstTypeReg,
-         compiler::Address(
-             FP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
-
-  const intptr_t sub_type_cache_index = __ object_pool_builder().AddObject(
-      Object::null_object(), compiler::ObjectPoolBuilderEntry::kPatchable);
-  const intptr_t dst_name_index = __ object_pool_builder().AddObject(
-      Symbols::OptimizedOut(), compiler::ObjectPoolBuilderEntry::kPatchable);
-  ASSERT((sub_type_cache_index + 1) == dst_name_index);
-  ASSERT(__ constant_pool_allowed());
-
-  // Call the TTS.
-  __ ldr(R9, compiler::FieldAddress(
-                 TypeTestABI::kDstTypeReg,
-                 AbstractType::type_test_stub_entry_point_offset()));
-  __ LoadWordFromPoolIndex(TypeTestABI::kSubtypeTestCacheReg,
-                           sub_type_cache_index);
-  __ blr(R9);
-
-  // We have the guarantee that TTS preserve all registers except for one
-  // scratch register atm (if the TTS handles the type test successfully).
-  //
-  // Let the test know whether TTS abi registers were preserved.
-  compiler::Label abi_regs_modified, store_abi_regs_modified_bool;
-  __ CompareWithMemoryValue(
-      TypeTestABI::kInstanceReg,
-      compiler::Address(
-          FP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ CompareWithMemoryValue(
-      TypeTestABI::kInstantiatorTypeArgumentsReg,
-      compiler::Address(
-          FP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ CompareWithMemoryValue(
-      TypeTestABI::kFunctionTypeArgumentsReg,
-      compiler::Address(
-          FP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ CompareWithMemoryValue(
-      TypeTestABI::kDstTypeReg,
-      compiler::Address(
-          FP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ ldr(R0, compiler::Address(THR, Thread::bool_false_offset()));
-  __ b(&store_abi_regs_modified_bool);
-  __ Bind(&abi_regs_modified);
-  __ ldr(R0, compiler::Address(THR, Thread::bool_true_offset()));
-  __ Bind(&store_abi_regs_modified_bool);
-  __ ldr(TMP, compiler::Address(
-                  FP, (kCallerSpSlotFromFp + 5) * compiler::target::kWordSize));
-  __ str(R0, compiler::FieldAddress(TMP, Array::element_offset(0)));
-
-  // Let the test know whether the non-TTS abi registers were preserved.
-  compiler::Label rest_regs_modified, store_rest_regs_modified_bool;
-  __ LoadImmediate(TMP, 0);
-  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
-    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
-    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
-    __ add(TMP, TMP, compiler::Operand(static_cast<Register>(i)));
-  }
-  __ cmp(TMP, compiler::Operand(sum));
-  __ BranchIf(NOT_EQUAL, &rest_regs_modified);
-  __ ldr(R0, compiler::Address(THR, Thread::bool_false_offset()));
-  __ b(&store_rest_regs_modified_bool);
-  __ Bind(&rest_regs_modified);
-  __ ldr(R0, compiler::Address(THR, Thread::bool_true_offset()));
-  __ Bind(&store_rest_regs_modified_bool);
-  __ ldr(TMP, compiler::Address(
-                  FP, (kCallerSpSlotFromFp + 4) * compiler::target::kWordSize));
-  __ str(R0, compiler::FieldAddress(TMP, Array::element_offset(0)));
-
-  __ LoadObject(R0, Object::null_object());
-  __ LeaveDartFrame();
-  __ Ret();
-}
-
-}  // namespace dart
-
-#endif  // defined(TARGET_ARCH_ARM64)
diff --git a/runtime/vm/type_testing_stubs_test_x64.cc b/runtime/vm/type_testing_stubs_test_x64.cc
deleted file mode 100644
index 57ae551..0000000
--- a/runtime/vm/type_testing_stubs_test_x64.cc
+++ /dev/null
@@ -1,118 +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.
-
-#include "platform/globals.h"
-
-#if defined(TARGET_ARCH_X64)
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/runtime_api.h"
-#include "vm/constants.h"
-#include "vm/object.h"
-#include "vm/stack_frame.h"
-#include "vm/symbols.h"
-
-#define __ assembler->
-
-namespace dart {
-
-void GenerateInvokeTTSStub(compiler::Assembler* assembler) {
-  __ EnterDartFrame(0);
-  intptr_t sum = 0;
-  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
-    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
-    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
-    __ movq(static_cast<Register>(i), compiler::Immediate(0x10 + 2 * i));
-    sum += 0x10 + 2 * i;
-  }
-
-  // Load the arguments into the right TTS calling convention registers.
-  __ movq(TypeTestABI::kInstanceReg,
-          compiler::Address(
-              RBP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
-  __ movq(TypeTestABI::kInstantiatorTypeArgumentsReg,
-          compiler::Address(
-              RBP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
-  __ movq(TypeTestABI::kFunctionTypeArgumentsReg,
-          compiler::Address(
-              RBP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
-  __ movq(TypeTestABI::kDstTypeReg,
-          compiler::Address(
-              RBP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
-
-  const intptr_t sub_type_cache_index = __ object_pool_builder().AddObject(
-      Object::null_object(), compiler::ObjectPoolBuilderEntry::kPatchable);
-  const intptr_t sub_type_cache_offset =
-      ObjectPool::element_offset(sub_type_cache_index) - kHeapObjectTag;
-  const intptr_t dst_name_index = __ object_pool_builder().AddObject(
-      Symbols::OptimizedOut(), compiler::ObjectPoolBuilderEntry::kPatchable);
-  ASSERT((sub_type_cache_index + 1) == dst_name_index);
-  ASSERT(__ constant_pool_allowed());
-
-  // Call the TTS.
-  __ movq(TypeTestABI::kSubtypeTestCacheReg,
-          compiler::Address(PP, sub_type_cache_offset));
-  __ call(compiler::FieldAddress(
-      TypeTestABI::kDstTypeReg,
-      AbstractType::type_test_stub_entry_point_offset()));
-
-  // We have the guarantee that TTS preserve all registers except for one
-  // scratch register atm (if the TTS handles the type test successfully).
-  //
-  // Let the test know whether TTS abi registers were preserved.
-  compiler::Label abi_regs_modified, store_abi_regs_modified_bool;
-  __ cmpq(TypeTestABI::kInstanceReg,
-          compiler::Address(
-              RBP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ cmpq(TypeTestABI::kInstantiatorTypeArgumentsReg,
-          compiler::Address(
-              RBP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ cmpq(TypeTestABI::kFunctionTypeArgumentsReg,
-          compiler::Address(
-              RBP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ cmpq(TypeTestABI::kDstTypeReg,
-          compiler::Address(
-              RBP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
-  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
-  __ movq(RAX, compiler::Address(THR, Thread::bool_false_offset()));
-  __ jmp(&store_abi_regs_modified_bool);
-  __ Bind(&abi_regs_modified);
-  __ movq(RAX, compiler::Address(THR, Thread::bool_true_offset()));
-  __ Bind(&store_abi_regs_modified_bool);
-  __ movq(TMP, compiler::Address(RBP, (kCallerSpSlotFromFp + 5) *
-                                          compiler::target::kWordSize));
-  __ movq(compiler::FieldAddress(TMP, Array::element_offset(0)), RAX);
-
-  // Let the test know whether the non-TTS abi registers were preserved.
-  compiler::Label rest_regs_modified, store_rest_regs_modified_bool;
-  __ movq(TMP, compiler::Immediate(0));
-  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
-    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
-    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
-    __ addq(TMP, static_cast<Register>(i));
-  }
-  __ cmpq(TMP, compiler::Immediate(sum));
-  __ BranchIf(NOT_EQUAL, &rest_regs_modified);
-  __ movq(RAX, compiler::Address(THR, Thread::bool_false_offset()));
-  __ jmp(&store_rest_regs_modified_bool);
-  __ Bind(&rest_regs_modified);
-  __ movq(RAX, compiler::Address(THR, Thread::bool_true_offset()));
-  __ Bind(&store_rest_regs_modified_bool);
-  __ movq(TMP, compiler::Address(RBP, (kCallerSpSlotFromFp + 4) *
-                                          compiler::target::kWordSize));
-  __ movq(compiler::FieldAddress(TMP, Array::element_offset(0)), RAX);
-
-  __ LoadObject(RAX, Object::null_object());
-  __ LeaveDartFrame();
-  __ Ret();
-}
-
-}  // namespace dart
-
-#endif  // defined(TARGET_ARCH_X64)
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 52f46f8..a65d61c 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -164,13 +164,8 @@
                                                 void* group_data,
                                                 void* isolate_data) {
   char* error;
-#if defined(DART_PRECOMPILED_RUNTIME)
-  Isolate* result = CreateWithinExistingIsolateGroupAOT(
-      reinterpret_cast<Isolate*>(parent)->group(), name, &error);
-#else
   Isolate* result = CreateWithinExistingIsolateGroup(
       reinterpret_cast<Isolate*>(parent)->group(), name, &error);
-#endif
   if (error != nullptr) {
     OS::PrintErr("CreateTestIsolateInGroup failed: %s\n", error);
     free(error);
@@ -327,7 +322,8 @@
   Zone* zone = Thread::Current()->zone();
   Dart_KernelCompilationResult result = KernelIsolate::CompileToKernel(
       url, platform_strong_dill, platform_strong_dill_size, sourcefiles_count,
-      sourcefiles, incrementally, NULL, multiroot_filepaths, multiroot_scheme);
+      sourcefiles, incrementally, false, NULL, multiroot_filepaths,
+      multiroot_scheme);
   if (result.status == Dart_KernelCompilationStatus_Ok) {
     if (KernelIsolate::AcceptCompilation().status !=
         Dart_KernelCompilationStatus_Ok) {
@@ -558,13 +554,14 @@
   } else if (isolate->group()->reload_context()->reload_aborted()) {
     TransitionNativeToVM transition(thread);
     result = Api::NewHandle(
-        thread, isolate->reload_context()->group_reload_context()->error());
+        thread,
+        isolate->program_reload_context()->group_reload_context()->error());
   } else {
     result = Dart_RootLibrary();
   }
 
   TransitionNativeToVM transition(thread);
-  if (isolate->reload_context() != NULL) {
+  if (isolate->program_reload_context() != NULL) {
     isolate->DeleteReloadContext();
     isolate->group()->DeleteReloadContext();
   }
@@ -648,7 +645,7 @@
                                          param_values,
                                          TypeArguments::null_type_arguments());
   }
-  return Api::NewHandle(thread, val.raw());
+  return Api::NewHandle(thread, val.ptr());
 }
 
 #if !defined(PRODUCT)
@@ -658,8 +655,8 @@
 #endif
 
 void AssemblerTest::Assemble() {
-  const String& function_name =
-      String::ZoneHandle(Symbols::New(Thread::Current(), name_));
+  auto thread = Thread::Current();
+  const String& function_name = String::ZoneHandle(Symbols::New(thread, name_));
 
   // We make a dummy script so that exception objects can be composed for
   // assembler instructions that do runtime calls.
@@ -669,9 +666,11 @@
   const Library& lib = Library::Handle(Library::CoreLibrary());
   const Class& cls = Class::ZoneHandle(
       Class::New(lib, function_name, script, TokenPosition::kMinSource));
+  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
   Function& function = Function::ZoneHandle(Function::New(
-      function_name, FunctionLayout::kRegularFunction, true, false, false,
-      false, false, cls, TokenPosition::kMinSource));
+      signature, function_name, UntaggedFunction::kRegularFunction, true, false,
+      false, false, false, cls, TokenPosition::kMinSource));
+  SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
   code_ = Code::FinalizeCodeAndNotify(function, nullptr, assembler_,
                                       Code::PoolAttachment::kAttachPool);
   code_.set_owner(function);
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 0ef84f1..89bc50e 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -114,7 +114,7 @@
     }                                                                          \
                                                                                \
     const Error& error = Error::Handle(Thread::Current()->sticky_error());     \
-    if (error.raw() == Object::branch_offset_error().raw()) {                  \
+    if (error.ptr() == Object::branch_offset_error().ptr()) {                  \
       bool use_far_branches = true;                                            \
       compiler::ObjectPoolBuilder object_pool_builder;                         \
       compiler::Assembler assembler(&object_pool_builder, use_far_branches);   \
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 0f71c57..72c9a91 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -28,6 +28,8 @@
   "class_id.h",
   "class_table.cc",
   "class_table.h",
+  "closure_functions_cache.cc",
+  "closure_functions_cache.h",
   "clustered_snapshot.cc",
   "clustered_snapshot.h",
   "code_comments.cc",
@@ -439,11 +441,7 @@
   "thread_pool_test.cc",
   "thread_test.cc",
   "timeline_test.cc",
-  "type_testing_stubs_test.h",
   "type_testing_stubs_test.cc",
-  "type_testing_stubs_test_x64.cc",
-  "type_testing_stubs_test_arm.cc",
-  "type_testing_stubs_test_arm64.cc",
   "unicode_test.cc",
   "unit_test.cc",
   "unit_test.h",
diff --git a/samples/ffi/async/sample_async_callback.dart b/samples/ffi/async/sample_async_callback.dart
index 59ae31b..4901c55 100644
--- a/samples/ffi/async/sample_async_callback.dart
+++ b/samples/ffi/async/sample_async_callback.dart
@@ -105,7 +105,7 @@
 final executeCallback = dl.lookupFunction<Void Function(Pointer<Work>),
     void Function(Pointer<Work>)>('ExecuteCallback');
 
-class Work extends Struct {}
+class Work extends Opaque {}
 
 Future asyncSleep(int ms) {
   return new Future.delayed(Duration(milliseconds: ms));
diff --git a/samples/ffi/calloc.dart b/samples/ffi/calloc.dart
new file mode 100644
index 0000000..e17238a
--- /dev/null
+++ b/samples/ffi/calloc.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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/samples/ffi/coordinate.dart b/samples/ffi/coordinate.dart
index 8a54ba9..01f8ec3 100644
--- a/samples/ffi/coordinate.dart
+++ b/samples/ffi/coordinate.dart
@@ -16,8 +16,9 @@
 
   external Pointer<Coordinate> next;
 
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
-    return allocate<Coordinate>().ref
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {
+    return allocator<Coordinate>().ref
       ..x = x
       ..y = y
       ..next = next;
diff --git a/samples/ffi/dylib_utils.dart b/samples/ffi/dylib_utils.dart
index 220c0fc..77faa88 100644
--- a/samples/ffi/dylib_utils.dart
+++ b/samples/ffi/dylib_utils.dart
@@ -6,7 +6,7 @@
 import 'dart:io' show Platform;
 
 String _platformPath(String name, String path) {
-  if (Platform.isLinux || Platform.isAndroid)
+  if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
diff --git a/samples/ffi/resource_management/pool.dart b/samples/ffi/resource_management/pool.dart
index 7064f9f..14e07f4 100644
--- a/samples/ffi/resource_management/pool.dart
+++ b/samples/ffi/resource_management/pool.dart
@@ -5,48 +5,53 @@
 // Explicit pool used for managing resources.
 
 import "dart:async";
-import 'dart:convert';
 import 'dart:ffi';
-import 'dart:typed_data';
 
-import 'package:ffi/ffi.dart' as packageFfi;
-import 'package:ffi/ffi.dart' show Utf8;
+import 'package:ffi/ffi.dart';
 
-/// Manages native resources.
+import '../calloc.dart';
+
+/// An [Allocator] which frees all allocations at the same time.
 ///
-/// Primary implementations are [Pool] and [Unmanaged].
-abstract class ResourceManager {
-  /// Allocates memory on the native heap.
-  ///
-  /// The native memory is under management by this [ResourceManager].
-  ///
-  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
-  /// against the default public heap. Allocation of either element size or count
-  /// of 0 is undefined.
-  ///
-  /// Throws an ArgumentError on failure to allocate.
-  Pointer<T> allocate<T extends NativeType>({int count: 1});
-}
+/// The pool allows you to allocate heap memory, but ignores calls to [free].
+/// Instead you call [releaseAll] to release all the allocations at the same
+/// time.
+///
+/// Also allows other resources to be associated with the pool, through the
+/// [using] method, to have a release function called for them when the pool is
+/// released.
+///
+/// An [Allocator] can be provided to do the actual allocation and freeing.
+/// Defaults to using [calloc].
+class Pool implements Allocator {
+  /// The [Allocator] used for allocation and freeing.
+  final Allocator _wrappedAllocator;
 
-/// Manages native resources.
-class Pool implements ResourceManager {
   /// Native memory under management by this [Pool].
   final List<Pointer<NativeType>> _managedMemoryPointers = [];
 
   /// Callbacks for releasing native resources under management by this [Pool].
   final List<Function()> _managedResourceReleaseCallbacks = [];
 
-  /// Allocates memory on the native heap.
+  bool _inUse = true;
+
+  /// Creates a pool of allocations.
   ///
-  /// The native memory is under management by this [Pool].
+  /// The [allocator] is used to do the actual allocation and freeing of
+  /// memory. It defaults to using [calloc].
+  Pool([Allocator allocator = calloc]) : _wrappedAllocator = allocator;
+
+  /// Allocates memory and includes it in the pool.
   ///
-  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
-  /// against the default public heap. Allocation of either element size or count
-  /// of 0 is undefined.
+  /// Uses the allocator provided to the [Pool] constructor to do the
+  /// allocation.
   ///
-  /// Throws an ArgumentError on failure to allocate.
-  Pointer<T> allocate<T extends NativeType>({int count: 1}) {
-    final p = Unmanaged().allocate<T>(count: count);
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+    _ensureInUse();
+    final p = _wrappedAllocator.allocate<T>(byteCount, alignment: alignment);
     _managedMemoryPointers.add(p);
     return p;
   }
@@ -55,6 +60,8 @@
   ///
   /// Executes [releaseCallback] on [releaseAll].
   T using<T>(T resource, Function(T) releaseCallback) {
+    _ensureInUse();
+    releaseCallback = Zone.current.bindUnaryCallback(releaseCallback);
     _managedResourceReleaseCallbacks.add(() => releaseCallback(resource));
     return resource;
   }
@@ -65,130 +72,102 @@
   }
 
   /// Releases all resources that this [Pool] manages.
-  void releaseAll() {
-    for (final c in _managedResourceReleaseCallbacks) {
-      c();
+  ///
+  /// If [reuse] is `true`, the pool can be used again after resources
+  /// have been released. If not, the default, then the [allocate]
+  /// and [using] methods must not be called after a call to `releaseAll`.
+  void releaseAll({bool reuse = false}) {
+    if (!reuse) {
+      _inUse = false;
     }
-    _managedResourceReleaseCallbacks.clear();
+    while (_managedResourceReleaseCallbacks.isNotEmpty) {
+      _managedResourceReleaseCallbacks.removeLast()();
+    }
     for (final p in _managedMemoryPointers) {
-      Unmanaged().free(p);
+      _wrappedAllocator.free(p);
     }
     _managedMemoryPointers.clear();
   }
+
+  /// Does nothing, invoke [releaseAll] instead.
+  @override
+  void free(Pointer<NativeType> pointer) {}
+
+  void _ensureInUse() {
+    if (!_inUse) {
+      throw StateError(
+          "Pool no longer in use, `releaseAll(reuse: false)` was called.");
+    }
+  }
 }
 
-/// Creates a [Pool] to manage native resources.
+/// Runs [computation] with a new [Pool], and releases all allocations at the end.
 ///
-/// If the isolate is shut down, through `Isolate.kill()`, resources are _not_ cleaned up.
-R using<R>(R Function(Pool) f) {
-  final p = Pool();
+/// If [R] is a [Future], all allocations are released when the future completes.
+///
+/// If the isolate is shut down, through `Isolate.kill()`, resources are _not_
+/// cleaned up.
+R using<R>(R Function(Pool) computation,
+    [Allocator wrappedAllocator = calloc]) {
+  final pool = Pool(wrappedAllocator);
+  bool isAsync = false;
   try {
-    return f(p);
+    final result = computation(pool);
+    if (result is Future) {
+      isAsync = true;
+      return (result.whenComplete(pool.releaseAll) as R);
+    }
+    return result;
   } finally {
-    p.releaseAll();
+    if (!isAsync) {
+      pool.releaseAll();
+    }
   }
 }
 
 /// Creates a zoned [Pool] to manage native resources.
 ///
-/// Pool is availabe through [currentPool].
-///
-/// Please note that all throws are caught and packaged in [RethrownError].
+/// The pool is availabe through [zonePool].
 ///
 /// If the isolate is shut down, through `Isolate.kill()`, resources are _not_ cleaned up.
-R usePool<R>(R Function() f) {
-  final p = Pool();
+R withZonePool<R>(R Function() computation,
+    [Allocator wrappedAllocator = calloc]) {
+  final pool = Pool(wrappedAllocator);
+  var poolHolder = [pool];
+  bool isAsync = false;
   try {
-    return runZoned(() => f(),
-        zoneValues: {#_pool: p},
-        onError: (error, st) => throw RethrownError(error, st));
+    return runZoned(() {
+      final result = computation();
+      if (result is Future) {
+        isAsync = true;
+        result.whenComplete(pool.releaseAll);
+      }
+      return result;
+    }, zoneValues: {#_pool: poolHolder});
   } finally {
-    p.releaseAll();
+    if (!isAsync) {
+      pool.releaseAll();
+      poolHolder.remove(pool);
+    }
   }
 }
 
-/// The [Pool] in the current zone.
-Pool get currentPool => Zone.current[#_pool];
-
-class RethrownError {
-  dynamic original;
-  StackTrace originalStackTrace;
-  RethrownError(this.original, this.originalStackTrace);
-  toString() => """RethrownError(${original})
-${originalStackTrace}""";
-}
-
-/// Does not manage it's resources.
-class Unmanaged implements ResourceManager {
-  /// Allocates memory on the native heap.
-  ///
-  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
-  /// against the default public heap. Allocation of either element size or count
-  /// of 0 is undefined.
-  ///
-  /// Throws an ArgumentError on failure to allocate.
-  Pointer<T> allocate<T extends NativeType>({int count = 1}) =>
-      packageFfi.allocate(count: count);
-
-  /// Releases memory on the native heap.
-  ///
-  /// For POSIX-based systems, this uses free. On Windows, it uses HeapFree
-  /// against the default public heap. It may only be used against pointers
-  /// allocated in a manner equivalent to [allocate].
-  ///
-  /// Throws an ArgumentError on failure to free.
-  ///
-  void free(Pointer pointer) => packageFfi.free(pointer);
-}
-
-/// Does not manage it's resources.
-final Unmanaged unmanaged = Unmanaged();
-
-extension Utf8InPool on String {
-  /// Convert a [String] to a Utf8-encoded null-terminated C string.
-  ///
-  /// If 'string' contains NULL bytes, the converted string will be truncated
-  /// prematurely. Unpaired surrogate code points in [string] will be preserved
-  /// in the UTF-8 encoded result. See [Utf8Encoder] for details on encoding.
-  ///
-  /// Returns a malloc-allocated pointer to the result.
-  ///
-  /// The memory is managed by the [Pool] passed in as [pool].
-  Pointer<Utf8> toUtf8(ResourceManager pool) {
-    final units = utf8.encode(this);
-    final Pointer<Uint8> result = pool.allocate<Uint8>(count: units.length + 1);
-    final Uint8List nativeString = result.asTypedList(units.length + 1);
-    nativeString.setAll(0, units);
-    nativeString[units.length] = 0;
-    return result.cast();
+/// A zone-specific [Pool].
+///
+/// Asynchronous computations can share a [Pool]. Use [withZonePool] to create
+/// a new zone with a fresh [Pool], and that pool will then be released
+/// automatically when the function passed to [withZonePool] completes.
+/// All code inside that zone can use `zonePool` to access the pool.
+///
+/// The current pool must not be accessed by code which is not running inside
+/// a zone created by [withZonePool].
+Pool get zonePool {
+  final List<Pool>? poolHolder = Zone.current[#_pool];
+  if (poolHolder == null) {
+    throw StateError("Not inside a zone created by `usePool`");
   }
-}
-
-extension Utf8Helpers on Pointer<Utf8> {
-  /// Returns the length of a null-terminated string -- the number of (one-byte)
-  /// characters before the first null byte.
-  int strlen() {
-    final Pointer<Uint8> array = this.cast<Uint8>();
-    final Uint8List nativeString = array.asTypedList(_maxSize);
-    return nativeString.indexWhere((char) => char == 0);
+  if (!poolHolder.isEmpty) {
+    return poolHolder.single;
   }
-
-  /// Creates a [String] containing the characters UTF-8 encoded in [this].
-  ///
-  /// [this] must be a zero-terminated byte sequence of valid UTF-8
-  /// encodings of Unicode code points. It may also contain UTF-8 encodings of
-  /// unpaired surrogate code points, which is not otherwise valid UTF-8, but
-  /// which may be created when encoding a Dart string containing an unpaired
-  /// surrogate. See [Utf8Decoder] for details on decoding.
-  ///
-  /// Returns a Dart string containing the decoded code points.
-  String contents() {
-    final int length = strlen();
-    return utf8.decode(Uint8List.view(
-        this.cast<Uint8>().asTypedList(length).buffer, 0, length));
-  }
+  throw StateError("Pool as already been cleared with releaseAll.");
 }
-
-const int _kMaxSmi64 = (1 << 62) - 1;
-const int _kMaxSmi32 = (1 << 30) - 1;
-final int _maxSize = sizeOf<IntPtr>() == 8 ? _kMaxSmi64 : _kMaxSmi32;
diff --git a/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart b/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart
index cab2cb0..39de01d 100644
--- a/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart
+++ b/samples/ffi/resource_management/pool_isolate_shutdown_sample.dart
@@ -86,4 +86,4 @@
     void Function(Pointer<SomeResource>)>("ReleaseResource");
 
 /// Represents some opaque resource being managed by a library.
-class SomeResource extends Struct {}
+class SomeResource extends Opaque {}
diff --git a/samples/ffi/resource_management/pool_sample.dart b/samples/ffi/resource_management/pool_sample.dart
index 00ee1ae..1f75165 100644
--- a/samples/ffi/resource_management/pool_sample.dart
+++ b/samples/ffi/resource_management/pool_sample.dart
@@ -4,14 +4,16 @@
 //
 // Sample illustrating resource management with an explicit pool.
 
+import 'dart:async';
 import 'dart:ffi';
 
 import 'package:expect/expect.dart';
 
 import 'pool.dart';
+import 'utf8_helpers.dart';
 import '../dylib_utils.dart';
 
-main() {
+main() async {
   final ffiTestDynamicLibrary =
       dlopenPlatformSpecific("ffi_test_dynamic_library");
 
@@ -21,7 +23,7 @@
 
   // To ensure resources are freed, wrap them in a [using] call.
   using((Pool pool) {
-    final p = pool.allocate<Int64>(count: 2);
+    final p = pool<Int64>(2);
     p[0] = 24;
     MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), sizeOf<Int64>());
     print(p[1]);
@@ -31,14 +33,14 @@
   // Resources are freed also when abnormal control flow occurs.
   try {
     using((Pool pool) {
-      final p = pool.allocate<Int64>(count: 2);
+      final p = pool<Int64>(2);
       p[0] = 25;
       MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), 8);
       print(p[1]);
       Expect.equals(25, p[1]);
       throw Exception("Some random exception");
     });
-    // `free(p)` has been called.
+    // `calloc.free(p)` has been called.
   } on Exception catch (e) {
     print("Caught exception: $e");
   }
@@ -46,8 +48,8 @@
   // In a pool multiple resources can be allocated, which will all be freed
   // at the end of the scope.
   using((Pool pool) {
-    final p = pool.allocate<Int64>(count: 2);
-    final p2 = pool.allocate<Int64>(count: 2);
+    final p = pool<Int64>(2);
+    final p2 = pool<Int64>(2);
     p[0] = 1;
     p[1] = 2;
     MemMove(p2.cast<Void>(), p.cast<Void>(), 2 * sizeOf<Int64>());
@@ -58,7 +60,7 @@
   // If the resource allocation happens in a different scope, then one either
   // needs to pass the pool to that scope.
   f1(Pool pool) {
-    return pool.allocate<Int64>(count: 2);
+    return pool<Int64>(2);
   }
 
   using((Pool pool) {
@@ -107,7 +109,25 @@
   } on Exception catch (e) {
     print("Caught exception: $e");
   }
+
+  /// [using] waits with releasing its resources until after [Future]s
+  /// complete.
+  List<int> freed = [];
+  freeInt(int i) {
+    freed.add(i);
+  }
+
+  Future<int> myFutureInt = using((Pool pool) {
+    return Future.microtask(() {
+      pool.using(1, freeInt);
+      return 1;
+    });
+  });
+
+  Expect.isTrue(freed.isEmpty);
+  await myFutureInt;
+  Expect.equals(1, freed.single);
 }
 
 /// Represents some opaque resource being managed by a library.
-class SomeResource extends Struct {}
+class SomeResource extends Opaque {}
diff --git a/samples/ffi/resource_management/pool_zoned_sample.dart b/samples/ffi/resource_management/pool_zoned_sample.dart
index 05f1794..b5b9eed 100644
--- a/samples/ffi/resource_management/pool_zoned_sample.dart
+++ b/samples/ffi/resource_management/pool_zoned_sample.dart
@@ -9,9 +9,10 @@
 import 'package:expect/expect.dart';
 
 import 'pool.dart';
+import 'utf8_helpers.dart';
 import '../dylib_utils.dart';
 
-main() {
+main() async {
   final ffiTestDynamicLibrary =
       dlopenPlatformSpecific("ffi_test_dynamic_library");
 
@@ -19,9 +20,9 @@
       Void Function(Pointer<Void>, Pointer<Void>, IntPtr),
       void Function(Pointer<Void>, Pointer<Void>, int)>("MemMove");
 
-  // To ensure resources are freed, wrap them in a [using] call.
-  usePool(() {
-    final p = currentPool.allocate<Int64>(count: 2);
+  // To ensure resources are freed, wrap them in a [withZonePool] call.
+  withZonePool(() {
+    final p = zonePool<Int64>(2);
     p[0] = 24;
     MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), sizeOf<Int64>());
     print(p[1]);
@@ -30,24 +31,23 @@
 
   // Resources are freed also when abnormal control flow occurs.
   try {
-    usePool(() {
-      final p = currentPool.allocate<Int64>(count: 2);
+    withZonePool(() {
+      final p = zonePool<Int64>(2);
       p[0] = 25;
       MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), 8);
       print(p[1]);
       Expect.equals(25, p[1]);
       throw Exception("Some random exception");
     });
-  } on RethrownError catch (e) {
-    // Note that exceptions are wrapped when using zones.
-    print("Caught exception: ${e.original}");
+  } catch (e) {
+    print("Caught exception: ${e}");
   }
 
   // In a pool multiple resources can be allocated, which will all be freed
   // at the end of the scope.
-  usePool(() {
-    final p = currentPool.allocate<Int64>(count: 2);
-    final p2 = currentPool.allocate<Int64>(count: 2);
+  withZonePool(() {
+    final p = zonePool<Int64>(2);
+    final p2 = zonePool<Int64>(2);
     p[0] = 1;
     p[1] = 2;
     MemMove(p2.cast<Void>(), p.cast<Void>(), 2 * sizeOf<Int64>());
@@ -58,10 +58,10 @@
   // If the resource allocation happens in a different scope, it is in the
   // same zone, so it's lifetime is automatically managed by the pool.
   f1() {
-    return currentPool.allocate<Int64>(count: 2);
+    return zonePool<Int64>(2);
   }
 
-  usePool(() {
+  withZonePool(() {
     final p = f1();
     final p2 = f1();
     p[0] = 1;
@@ -72,8 +72,8 @@
   });
 
   // Using Strings.
-  usePool(() {
-    final p = "Hello world!".toUtf8(currentPool);
+  withZonePool(() {
+    final p = "Hello world!".toUtf8(zonePool);
     print(p.contents());
   });
 
@@ -90,25 +90,43 @@
       void Function(Pointer<SomeResource>)>("ReleaseResource");
 
   // Using an FFI call to release a resource.
-  usePool(() {
-    final r = currentPool.using(allocateResource(), releaseResource);
+  withZonePool(() {
+    final r = zonePool.using(allocateResource(), releaseResource);
     useResource(r);
   });
 
   // Using an FFI call to release a resource with abnormal control flow.
   try {
-    usePool(() {
-      final r = currentPool.using(allocateResource(), releaseResource);
+    withZonePool(() {
+      final r = zonePool.using(allocateResource(), releaseResource);
       useResource(r);
 
       throw Exception("Some random exception");
     });
     // Resource has been freed.
-  } on RethrownError catch (e) {
-    // Note that exceptions are wrapped when using zones.
-    print("Caught exception: ${e.original}");
+  } catch (e) {
+    print("Caught exception: ${e}");
   }
+
+  /// [using] waits with releasing its resources until after [Future]s
+  /// complete.
+
+  List<int> freed = [];
+  freeInt(int i) {
+    freed.add(i);
+  }
+
+  Future<int> myFutureInt = withZonePool(() {
+    return Future.microtask(() {
+      zonePool.using(1, freeInt);
+      return 1;
+    });
+  });
+
+  Expect.isTrue(freed.isEmpty);
+  await myFutureInt;
+  Expect.equals(1, freed.single);
 }
 
 /// Represents some opaque resource being managed by a library.
-class SomeResource extends Struct {}
+class SomeResource extends Opaque {}
diff --git a/samples/ffi/resource_management/unmanaged_sample.dart b/samples/ffi/resource_management/unmanaged_sample.dart
index 9c3e0f0..04c20cb 100644
--- a/samples/ffi/resource_management/unmanaged_sample.dart
+++ b/samples/ffi/resource_management/unmanaged_sample.dart
@@ -7,30 +7,32 @@
 import 'dart:ffi';
 
 import 'package:expect/expect.dart';
+import 'package:ffi/ffi.dart';
 
-import 'pool.dart';
+import 'utf8_helpers.dart';
+import '../calloc.dart';
 import '../dylib_utils.dart';
 
 main() {
   final ffiTestDynamicLibrary =
       dlopenPlatformSpecific("ffi_test_dynamic_library");
 
-  final MemMove = ffiTestDynamicLibrary.lookupFunction<
+  final memMove = ffiTestDynamicLibrary.lookupFunction<
       Void Function(Pointer<Void>, Pointer<Void>, IntPtr),
       void Function(Pointer<Void>, Pointer<Void>, int)>("MemMove");
 
   // To ensure resources are freed, call free manually.
   //
   // For automatic management use a Pool.
-  final p = unmanaged.allocate<Int64>(count: 2);
+  final p = calloc<Int64>(2);
   p[0] = 24;
-  MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), sizeOf<Int64>());
+  memMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), sizeOf<Int64>());
   print(p[1]);
   Expect.equals(24, p[1]);
-  unmanaged.free(p);
+  calloc.free(p);
 
   // Using Strings.
-  final p2 = "Hello world!".toUtf8(unmanaged);
+  final p2 = "Hello world!".toUtf8(calloc);
   print(p2.contents());
-  unmanaged.free(p2);
+  calloc.free(p2);
 }
diff --git a/samples/ffi/resource_management/utf8_helpers.dart b/samples/ffi/resource_management/utf8_helpers.dart
new file mode 100644
index 0000000..ed7b4a1
--- /dev/null
+++ b/samples/ffi/resource_management/utf8_helpers.dart
@@ -0,0 +1,53 @@
+// 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:convert';
+import 'dart:ffi';
+import 'dart:typed_data';
+
+import 'package:ffi/ffi.dart';
+
+extension Utf8InPool on String {
+  /// Convert a [String] to a Utf8-encoded null-terminated C string.
+  ///
+  /// If 'string' contains NULL bytes, the converted string will be truncated
+  /// prematurely. See [Utf8Encoder] for details on encoding.
+  ///
+  /// Returns a [allocator]-allocated pointer to the result.
+  Pointer<Utf8> toUtf8(Allocator allocator) {
+    final units = utf8.encode(this);
+    final Pointer<Uint8> result = allocator<Uint8>(units.length + 1);
+    final Uint8List nativeString = result.asTypedList(units.length + 1);
+    nativeString.setAll(0, units);
+    nativeString[units.length] = 0;
+    return result.cast();
+  }
+}
+
+extension Utf8Helpers on Pointer<Utf8> {
+  /// The length of a null-terminated string — the number of (one-byte)
+  /// characters before the first null byte.
+  int get strlen {
+    final Pointer<Uint8> array = this.cast<Uint8>();
+    final Uint8List nativeString = array.asTypedList(_maxSize);
+    return nativeString.indexWhere((char) => char == 0);
+  }
+
+  /// Creates a [String] containing the characters UTF-8 encoded in [this].
+  ///
+  /// [this] must be a zero-terminated byte sequence of valid UTF-8
+  /// encodings of Unicode code points. See [Utf8Decoder] for details on
+  /// decoding.
+  ///
+  /// Returns a Dart string containing the decoded code points.
+  String contents() {
+    final int length = strlen;
+    return utf8.decode(Uint8List.view(
+        this.cast<Uint8>().asTypedList(length).buffer, 0, length));
+  }
+}
+
+const int _kMaxSmi64 = (1 << 62) - 1;
+const int _kMaxSmi32 = (1 << 30) - 1;
+final int _maxSize = sizeOf<IntPtr>() == 8 ? _kMaxSmi64 : _kMaxSmi32;
diff --git a/samples/ffi/sample_ffi_bitfield.dart b/samples/ffi/sample_ffi_bitfield.dart
index cc10a2d..67ce69e 100644
--- a/samples/ffi/sample_ffi_bitfield.dart
+++ b/samples/ffi/sample_ffi_bitfield.dart
@@ -7,6 +7,8 @@
 import 'package:ffi/ffi.dart';
 import 'package:expect/expect.dart';
 
+import 'calloc.dart';
+
 /// typedef struct {
 ///     unsigned int bold      : 1;
 ///     unsigned int underline : 2;
@@ -93,7 +95,7 @@
 }
 
 main() {
-  final p = allocate<ScreenCellAttrs>(count: 3);
+  final p = calloc<ScreenCellAttrs>(3);
 
   // Zeroes out all fields.
   p.ref.bits = 0;
@@ -119,5 +121,5 @@
   // A check for automated testing.
   Expect.equals(1933, p.ref.bits);
 
-  free(p);
+  calloc.free(p);
 }
diff --git a/samples/ffi/sample_ffi_data.dart b/samples/ffi/sample_ffi_data.dart
index 8e713d0..e5b0497 100644
--- a/samples/ffi/sample_ffi_data.dart
+++ b/samples/ffi/sample_ffi_data.dart
@@ -5,29 +5,31 @@
 import 'dart:ffi';
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
+
 main() {
   print('start main');
 
   {
     // Basic operation: allocate, get, set, and free.
-    Pointer<Int64> p = allocate();
+    Pointer<Int64> p = calloc();
     p.value = 42;
     int pValue = p.value;
     print('${p.runtimeType} value: ${pValue}');
-    free(p);
+    calloc.free(p);
   }
 
   {
     // Undefined behavior before set.
-    Pointer<Int64> p = allocate();
+    Pointer<Int64> p = calloc();
     int pValue = p.value;
     print('If not set, returns garbage: ${pValue}');
-    free(p);
+    calloc.free(p);
   }
 
   {
     // Pointers can be created from an address.
-    Pointer<Int64> pHelper = allocate();
+    Pointer<Int64> pHelper = calloc();
     pHelper.value = 1337;
 
     int address = pHelper.address;
@@ -36,13 +38,13 @@
     Pointer<Int64> p = Pointer.fromAddress(address);
     print('${p.runtimeType} value: ${p.value}');
 
-    free(pHelper);
+    calloc.free(pHelper);
   }
 
   {
     // Address is zeroed out after free.
-    Pointer<Int64> p = allocate();
-    free(p);
+    Pointer<Int64> p = calloc();
+    calloc.free(p);
     print('After free, address is zero: ${p.address}');
   }
 
@@ -50,13 +52,13 @@
     // Allocating too much throws an exception.
     try {
       int maxMint = 9223372036854775807; // 2^63 - 1
-      allocate<Int64>(count: maxMint);
+      calloc<Int64>(maxMint);
     } on Error {
       print('Expected exception on allocating too much');
     }
     try {
       int maxInt1_8 = 1152921504606846975; // 2^60 -1
-      allocate<Int64>(count: maxInt1_8);
+      calloc<Int64>(maxInt1_8);
     } on Error {
       print('Expected exception on allocating too much');
     }
@@ -65,7 +67,7 @@
   {
     // Pointers can be cast into another type,
     // resulting in the corresponding bits read.
-    Pointer<Int64> p1 = allocate();
+    Pointer<Int64> p1 = calloc();
     p1.value = 9223372036854775807; // 2^63 - 1
 
     Pointer<Int32> p2 = p1.cast();
@@ -74,61 +76,61 @@
     Pointer<Int32> p3 = p2.elementAt(1);
     print('${p3.runtimeType} value: ${p3.value}'); // 2^31 - 1
 
-    free(p1);
+    calloc.free(p1);
   }
 
   {
     // Data can be tightly packed in memory.
-    Pointer<Int8> p = allocate(count: 8);
+    Pointer<Int8> p = calloc(8);
     for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
       p.elementAt(i).value = i * 3;
     }
     for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
       print('p.elementAt($i) value: ${p.elementAt(i).value}');
     }
-    free(p);
+    calloc.free(p);
   }
 
   {
     // Values that don't fit are truncated.
-    Pointer<Int32> p11 = allocate();
+    Pointer<Int32> p11 = calloc();
 
     p11.value = 9223372036854775807;
 
     print(p11);
 
-    free(p11);
+    calloc.free(p11);
   }
 
   {
     // Doubles.
-    Pointer<Double> p = allocate();
+    Pointer<Double> p = calloc();
     p.value = 3.14159265359;
     print('${p.runtimeType} value: ${p.value}');
     p.value = 3.14;
     print('${p.runtimeType} value: ${p.value}');
-    free(p);
+    calloc.free(p);
   }
 
   {
     // Floats.
-    Pointer<Float> p = allocate();
+    Pointer<Float> p = calloc();
     p.value = 3.14159265359;
     print('${p.runtimeType} value: ${p.value}');
     p.value = 3.14;
     print('${p.runtimeType} value: ${p.value}');
-    free(p);
+    calloc.free(p);
   }
 
   {
     // IntPtr varies in size based on whether the platform is 32 or 64 bit.
     // Addresses of pointers fit in this size.
-    Pointer<IntPtr> p = allocate();
+    Pointer<IntPtr> p = calloc();
     int p14addr = p.address;
     p.value = p14addr;
     int pValue = p.value;
     print('${p.runtimeType} value: ${pValue}');
-    free(p);
+    calloc.free(p);
   }
 
   {
@@ -136,19 +138,19 @@
     // The size of the element it is pointing to is undefined,
     // they cannot be allocated, read, or written.
 
-    Pointer<IntPtr> p1 = allocate();
+    Pointer<IntPtr> p1 = calloc();
     Pointer<Void> p2 = p1.cast();
     print('${p2.runtimeType} address: ${p2.address}');
 
-    free(p1);
+    calloc.free(p1);
   }
 
   {
     // Pointer to a pointer to something.
-    Pointer<Int16> pHelper = allocate();
+    Pointer<Int16> pHelper = calloc();
     pHelper.value = 17;
 
-    Pointer<Pointer<Int16>> p = allocate();
+    Pointer<Pointer<Int16>> p = calloc();
 
     // Storing into a pointer pointer automatically unboxes.
     p.value = pHelper;
@@ -160,31 +162,31 @@
     int pValue = p.value.value;
     print('${p.runtimeType} value\'s value: ${pValue}');
 
-    free(p);
-    free(pHelper);
+    calloc.free(p);
+    calloc.free(pHelper);
   }
 
   {
     // The pointer to pointer types must match up.
-    Pointer<Int8> pHelper = allocate();
+    Pointer<Int8> pHelper = calloc();
     pHelper.value = 123;
 
-    Pointer<Pointer<Int16>> p = allocate();
+    Pointer<Pointer<Int16>> p = calloc();
 
     // Trying to store `pHelper` into `p.val` would result in a type mismatch.
 
-    free(pHelper);
-    free(p);
+    calloc.free(pHelper);
+    calloc.free(p);
   }
 
   {
     // `nullptr` points to address 0 in c++.
-    Pointer<Pointer<Int8>> pointerToPointer = allocate();
+    Pointer<Pointer<Int8>> pointerToPointer = calloc();
     Pointer<Int8> value = nullptr;
     pointerToPointer.value = value;
     value = pointerToPointer.value;
     print("Loading a pointer to the 0 address is null: ${value}");
-    free(pointerToPointer);
+    calloc.free(pointerToPointer);
   }
 
   {
@@ -205,7 +207,7 @@
         head.value = value;
         return;
       }
-      Pointer<IntPtr> next = allocate<IntPtr>();
+      Pointer<IntPtr> next = calloc<IntPtr>();
       head.value = next.address;
       createChain(next, length - 1, value);
     }
@@ -220,7 +222,7 @@
 
     void freeChain(Pointer<IntPtr> head, int length) {
       Pointer<IntPtr> next = Pointer.fromAddress(head.value);
-      free(head);
+      calloc.free(head);
       if (length == 0) {
         return;
       }
@@ -228,7 +230,7 @@
     }
 
     int length = 10;
-    Pointer<IntPtr> head = allocate();
+    Pointer<IntPtr> head = calloc();
     createChain(head, length, 512);
     int tailValue = getChainValue(head, length);
     print('tailValue: ${tailValue}');
diff --git a/samples/ffi/sample_ffi_functions.dart b/samples/ffi/sample_ffi_functions.dart
index bff74eb..5038ba8 100644
--- a/samples/ffi/sample_ffi_functions.dart
+++ b/samples/ffi/sample_ffi_functions.dart
@@ -6,6 +6,7 @@
 
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 typedef NativeUnaryOp = Int32 Function(Int32);
@@ -184,7 +185,7 @@
     // pass an array / pointer as argument
     Int64PointerUnOp assign1337Index1 = ffiTestFunctions
         .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
-    Pointer<Int64> p2 = allocate(count: 2);
+    Pointer<Int64> p2 = calloc(2);
     p2.value = 42;
     p2[1] = 1000;
     print(p2.elementAt(1).address.toRadixString(16));
@@ -209,11 +210,11 @@
     print(result);
     print(result.runtimeType);
 
-    Pointer<Int64> p2 = allocate(count: 2);
+    Pointer<Int64> p2 = calloc(2);
     result = nullableInt64ElemAt1(p2);
     print(result);
     print(result.runtimeType);
-    free(p2);
+    calloc.free(p2);
   }
 
   print("end main");
diff --git a/samples/ffi/sample_ffi_functions_callbacks.dart b/samples/ffi/sample_ffi_functions_callbacks.dart
index affdcef..de6d05a 100644
--- a/samples/ffi/sample_ffi_functions_callbacks.dart
+++ b/samples/ffi/sample_ffi_functions_callbacks.dart
@@ -4,6 +4,9 @@
 
 import 'dart:ffi';
 
+import 'package:ffi/ffi.dart';
+
+import 'calloc.dart';
 import 'coordinate.dart';
 import 'dylib_utils.dart';
 
@@ -43,7 +46,7 @@
     Pointer<NativeFunction<CoordinateTrice>> p2 =
         ffiTestFunctions.lookup("CoordinateUnOpTrice");
     CoordinateTrice coordinateUnOpTrice = p2.asFunction();
-    Coordinate c1 = Coordinate.allocate(10.0, 20.0, nullptr);
+    Coordinate c1 = Coordinate.allocate(calloc, 10.0, 20.0, nullptr);
     c1.next = c1.addressOf;
     Coordinate result =
         coordinateUnOpTrice(transposeCoordinatePointer, c1.addressOf).ref;
diff --git a/samples/ffi/sample_ffi_functions_structs.dart b/samples/ffi/sample_ffi_functions_structs.dart
index 9aefb57..9185040 100644
--- a/samples/ffi/sample_ffi_functions_structs.dart
+++ b/samples/ffi/sample_ffi_functions_structs.dart
@@ -4,11 +4,12 @@
 
 import 'dart:ffi';
 
+import 'package:ffi/ffi.dart';
+
+import 'calloc.dart';
 import 'coordinate.dart';
 import 'dylib_utils.dart';
 
-import 'package:ffi/ffi.dart';
-
 typedef NativeCoordinateOp = Pointer<Coordinate> Function(Pointer<Coordinate>);
 
 main() {
@@ -23,8 +24,8 @@
         ffiTestFunctions.lookup("TransposeCoordinate");
     NativeCoordinateOp f1 = p1.asFunction();
 
-    Coordinate c1 = Coordinate.allocate(10.0, 20.0, nullptr);
-    Coordinate c2 = Coordinate.allocate(42.0, 84.0, c1.addressOf);
+    Coordinate c1 = Coordinate.allocate(calloc, 10.0, 20.0, nullptr);
+    Coordinate c2 = Coordinate.allocate(calloc, 42.0, 84.0, c1.addressOf);
     c1.next = c2.addressOf;
 
     Coordinate result = f1(c1.addressOf).ref;
@@ -44,7 +45,7 @@
         ffiTestFunctions.lookup("CoordinateElemAt1");
     NativeCoordinateOp f1 = p1.asFunction();
 
-    Pointer<Coordinate> c1 = allocate<Coordinate>(count: 3);
+    Pointer<Coordinate> c1 = calloc<Coordinate>(3);
     Pointer<Coordinate> c2 = c1.elementAt(1);
     Pointer<Coordinate> c3 = c1.elementAt(2);
     c1.ref.x = 10.0;
diff --git a/samples/ffi/sample_ffi_structs.dart b/samples/ffi/sample_ffi_structs.dart
index bd6d7c7..f6de82c 100644
--- a/samples/ffi/sample_ffi_structs.dart
+++ b/samples/ffi/sample_ffi_structs.dart
@@ -6,6 +6,7 @@
 
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
 import 'coordinate.dart';
 
 main() {
@@ -13,9 +14,9 @@
 
   {
     // Allocates each coordinate separately in c memory.
-    Coordinate c1 = Coordinate.allocate(10.0, 10.0, nullptr);
-    Coordinate c2 = Coordinate.allocate(20.0, 20.0, c1.addressOf);
-    Coordinate c3 = Coordinate.allocate(30.0, 30.0, c2.addressOf);
+    Coordinate c1 = Coordinate.allocate(calloc, 10.0, 10.0, nullptr);
+    Coordinate c2 = Coordinate.allocate(calloc, 20.0, 20.0, c1.addressOf);
+    Coordinate c3 = Coordinate.allocate(calloc, 30.0, 30.0, c2.addressOf);
     c1.next = c3.addressOf;
 
     Coordinate currentCoordinate = c1;
@@ -24,14 +25,14 @@
       print("${currentCoordinate.x}; ${currentCoordinate.y}");
     }
 
-    free(c1.addressOf);
-    free(c2.addressOf);
-    free(c3.addressOf);
+    calloc.free(c1.addressOf);
+    calloc.free(c2.addressOf);
+    calloc.free(c3.addressOf);
   }
 
   {
     // Allocates coordinates consecutively in c memory.
-    Pointer<Coordinate> c1 = allocate<Coordinate>(count: 3);
+    Pointer<Coordinate> c1 = calloc<Coordinate>(3);
     Pointer<Coordinate> c2 = c1.elementAt(1);
     Pointer<Coordinate> c3 = c1.elementAt(2);
     c1.ref.x = 10.0;
@@ -50,15 +51,15 @@
       print("${currentCoordinate.x}; ${currentCoordinate.y}");
     }
 
-    free(c1);
+    calloc.free(c1);
   }
 
   {
-    Coordinate c = Coordinate.allocate(10, 10, nullptr);
+    Coordinate c = Coordinate.allocate(calloc, 10, 10, nullptr);
     print(c is Coordinate);
     print(c is Pointer<Void>);
     print(c is Pointer);
-    free(c.addressOf);
+    calloc.free(c.addressOf);
   }
 
   print("end main");
diff --git a/samples/ffi/sqlite/lib/sqlite.dart b/samples/ffi/sqlite/lib/sqlite.dart
index d6bac5b..1e60f9f 100644
--- a/samples/ffi/sqlite/lib/sqlite.dart
+++ b/samples/ffi/sqlite/lib/sqlite.dart
@@ -8,3 +8,5 @@
 library sqlite;
 
 export "src/database.dart";
+
+export "src/ffi/calloc.dart" show calloc;
diff --git a/samples/ffi/sqlite/lib/src/bindings/types.dart b/samples/ffi/sqlite/lib/src/bindings/types.dart
index 494cdef..40edc87 100644
--- a/samples/ffi/sqlite/lib/src/bindings/types.dart
+++ b/samples/ffi/sqlite/lib/src/bindings/types.dart
@@ -13,7 +13,7 @@
 /// is its destructor.  There are many other interfaces (such as
 /// [sqlite3_prepare_v2()], [sqlite3_create_function()], and
 /// [sqlite3_busy_timeout()] to name but three) that are methods on an
-class Database extends Struct {}
+class Database extends Opaque {}
 
 /// SQL Statement Object
 ///
@@ -36,7 +36,7 @@
 ///
 /// Refer to documentation on individual methods above for additional
 /// information.
-class Statement extends Struct {}
+class Statement extends Opaque {}
 
 /// Dynamically Typed Value Object
 ///
@@ -72,4 +72,4 @@
 /// [sqlite3_result_value()] and [sqlite3_bind_value()].
 /// The [sqlite3_value_blob | sqlite3_value_type()] family of
 /// interfaces require protected sqlite3_value objects.
-class Value extends Struct {}
+class Value extends Opaque {}
diff --git a/samples/ffi/sqlite/lib/src/database.dart b/samples/ffi/sqlite/lib/src/database.dart
index 7725609..5031027 100644
--- a/samples/ffi/sqlite/lib/src/database.dart
+++ b/samples/ffi/sqlite/lib/src/database.dart
@@ -15,6 +15,8 @@
 import "bindings/constants.dart";
 import "collections/closable_iterator.dart";
 
+import 'ffi/calloc.dart';
+
 /// [Database] represents an open connection to a SQLite database.
 ///
 /// All functions against a database may throw [SQLiteError].
@@ -27,13 +29,13 @@
   /// Open a database located at the file [path].
   Database(String path,
       [int flags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE]) {
-    Pointer<Pointer<types.Database>> dbOut = allocate();
+    Pointer<Pointer<types.Database>> dbOut = calloc();
     final pathC = Utf8.toUtf8(path);
     final int resultCode =
         bindings.sqlite3_open_v2(pathC, dbOut, flags, nullptr);
     _database = dbOut.value;
-    free(dbOut);
-    free(pathC);
+    calloc.free(dbOut);
+    calloc.free(pathC);
 
     if (resultCode == Errors.SQLITE_OK) {
       _open = true;
@@ -63,13 +65,13 @@
 
   /// Execute a query, discarding any returned rows.
   void execute(String query) {
-    Pointer<Pointer<Statement>> statementOut = allocate();
+    Pointer<Pointer<Statement>> statementOut = calloc();
     Pointer<Utf8> queryC = Utf8.toUtf8(query);
     int resultCode = bindings.sqlite3_prepare_v2(
         _database, queryC, -1, statementOut, nullptr);
     Pointer<Statement> statement = statementOut.value;
-    free(statementOut);
-    free(queryC);
+    calloc.free(statementOut);
+    calloc.free(queryC);
 
     while (resultCode == Errors.SQLITE_ROW || resultCode == Errors.SQLITE_OK) {
       resultCode = bindings.sqlite3_step(statement);
@@ -82,13 +84,13 @@
 
   /// Evaluate a query and return the resulting rows as an iterable.
   Result query(String query) {
-    Pointer<Pointer<Statement>> statementOut = allocate();
+    Pointer<Pointer<Statement>> statementOut = calloc();
     Pointer<Utf8> queryC = Utf8.toUtf8(query);
     int resultCode = bindings.sqlite3_prepare_v2(
         _database, queryC, -1, statementOut, nullptr);
     Pointer<Statement> statement = statementOut.value;
-    free(statementOut);
-    free(queryC);
+    calloc.free(statementOut);
+    calloc.free(queryC);
 
     if (resultCode != Errors.SQLITE_OK) {
       bindings.sqlite3_finalize(statement);
@@ -99,7 +101,7 @@
     int columnCount = bindings.sqlite3_column_count(statement);
     for (int i = 0; i < columnCount; i++) {
       String columnName =
-          bindings.sqlite3_column_name(statement, i).ref.toString();
+          Utf8.fromUtf8(bindings.sqlite3_column_name(statement, i));
       columnIndices[columnName] = i;
     }
 
@@ -107,9 +109,9 @@
   }
 
   SQLiteException _loadError(int errorCode) {
-    String errorMessage = bindings.sqlite3_errmsg(_database).ref.toString();
+    String errorMessage = Utf8.fromUtf8(bindings.sqlite3_errmsg(_database));
     String errorCodeExplanation =
-        bindings.sqlite3_errstr(errorCode).ref.toString();
+        Utf8.fromUtf8(bindings.sqlite3_errstr(errorCode));
     return SQLiteException(
         "$errorMessage (Code $errorCode: $errorCodeExplanation)");
   }
@@ -204,10 +206,8 @@
       dynamicType =
           _typeFromCode(bindings.sqlite3_column_type(_statement, columnIndex));
     } else {
-      dynamicType = _typeFromText(bindings
-          .sqlite3_column_decltype(_statement, columnIndex)
-          .ref
-          .toString());
+      dynamicType = _typeFromText(Utf8.fromUtf8(
+          bindings.sqlite3_column_decltype(_statement, columnIndex)));
     }
 
     switch (dynamicType) {
@@ -242,7 +242,7 @@
   /// Reads column [columnIndex] and converts to [Type.Text] if not text.
   String readColumnByIndexAsText(int columnIndex) {
     _checkIsCurrentRow();
-    return bindings.sqlite3_column_text(_statement, columnIndex).ref.toString();
+    return Utf8.fromUtf8(bindings.sqlite3_column_text(_statement, columnIndex));
   }
 
   void _checkIsCurrentRow() {
diff --git a/samples/ffi/sqlite/lib/src/ffi/arena.dart b/samples/ffi/sqlite/lib/src/ffi/arena.dart
index d01b64f..5369a22 100644
--- a/samples/ffi/sqlite/lib/src/ffi/arena.dart
+++ b/samples/ffi/sqlite/lib/src/ffi/arena.dart
@@ -7,6 +7,8 @@
 
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
+
 /// [Arena] manages allocated C memory.
 ///
 /// Arenas are zoned.
@@ -24,7 +26,7 @@
   /// Frees all memory pointed to by [Pointer]s in this arena.
   void finalize() {
     for (final ptr in _allocations) {
-      free(ptr);
+      calloc.free(ptr);
     }
   }
 
diff --git a/samples/ffi/sqlite/lib/src/ffi/calloc.dart b/samples/ffi/sqlite/lib/src/ffi/calloc.dart
new file mode 100644
index 0000000..e17238a
--- /dev/null
+++ b/samples/ffi/sqlite/lib/src/ffi/calloc.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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart b/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
index 220c0fc..77faa88 100644
--- a/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
+++ b/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
@@ -6,7 +6,7 @@
 import 'dart:io' show Platform;
 
 String _platformPath(String name, String path) {
-  if (Platform.isLinux || Platform.isAndroid)
+  if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
diff --git a/samples/ffi/sqlite/test/sqlite_test.dart b/samples/ffi/sqlite/test/sqlite_test.dart
index 130c95f..ef7666d 100644
--- a/samples/ffi/sqlite/test/sqlite_test.dart
+++ b/samples/ffi/sqlite/test/sqlite_test.dart
@@ -167,7 +167,7 @@
   test("Utf8 unit test", () {
     final String test = 'Hasta Mañana';
     final medium = Utf8.toUtf8(test);
-    expect(test, medium.ref.toString());
-    free(medium);
+    expect(test, Utf8.fromUtf8(medium));
+    calloc.free(medium);
   });
 }
diff --git a/samples/sample_extension/sample_asynchronous_extension.dart b/samples/sample_extension/sample_asynchronous_extension.dart
index 541652d..7d18902 100644
--- a/samples/sample_extension/sample_asynchronous_extension.dart
+++ b/samples/sample_extension/sample_asynchronous_extension.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 sample_asynchronous_extension;
 
 import 'dart:async';
@@ -12,15 +10,12 @@
 
 // A class caches the native port used to call an asynchronous extension.
 class RandomArray {
-  static SendPort _port;
+  static SendPort? _port;
 
   Future<List<int>> randomArray(int seed, int length) {
     var completer = new Completer<List<int>>();
     var replyPort = new RawReceivePort();
-    var args = new List(3);
-    args[0] = seed;
-    args[1] = length;
-    args[2] = replyPort.sendPort;
+    var args = [seed, length, replyPort.sendPort];
     _servicePort.send(args);
     replyPort.handler = (result) {
       replyPort.close();
@@ -37,7 +32,7 @@
     if (_port == null) {
       _port = _newServicePort();
     }
-    return _port;
+    return _port!;
   }
 
   SendPort _newServicePort() native "RandomArray_ServicePort";
diff --git a/samples/sample_extension/sample_synchronous_extension.dart b/samples/sample_extension/sample_synchronous_extension.dart
index e5ad660..727cd4c 100644
--- a/samples/sample_extension/sample_synchronous_extension.dart
+++ b/samples/sample_extension/sample_synchronous_extension.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 sample_synchronous_extension;
 
 import 'dart-ext:sample_extension';
diff --git a/samples/sample_extension/test/sample_extension_app_snapshot_test.dart b/samples/sample_extension/test/sample_extension_app_snapshot_test.dart
index b2eb204..558b108 100644
--- a/samples/sample_extension/test/sample_extension_app_snapshot_test.dart
+++ b/samples/sample_extension/test/sample_extension_app_snapshot_test.dart
@@ -4,8 +4,6 @@
 //
 // Dart test program for testing native extensions.
 
-// @dart = 2.9
-
 // OtherResources=../sample_synchronous_extension.dart
 // OtherResources=../sample_asynchronous_extension.dart
 // OtherResources=../test_sample_synchronous_extension.dart
diff --git a/samples/sample_extension/test/sample_extension_test.dart b/samples/sample_extension/test/sample_extension_test.dart
index 393463b..4311ff5 100644
--- a/samples/sample_extension/test/sample_extension_test.dart
+++ b/samples/sample_extension/test/sample_extension_test.dart
@@ -4,8 +4,6 @@
 //
 // Dart test program for testing native extensions.
 
-// @dart = 2.9
-
 import 'sample_extension_test_helper.dart';
 
 void main() {
diff --git a/samples/sample_extension/test/sample_extension_test_helper.dart b/samples/sample_extension/test/sample_extension_test_helper.dart
index 9c701bf..d4cae3d 100644
--- a/samples/sample_extension/test/sample_extension_test_helper.dart
+++ b/samples/sample_extension/test/sample_extension_test_helper.dart
@@ -4,8 +4,6 @@
 //
 // Dart test program for testing native extensions.
 
-// @dart = 2.9
-
 import 'dart:async';
 import 'dart:io';
 import 'dart:isolate';
@@ -26,7 +24,7 @@
       result = await Process.run('cmd.exe', ['/C', 'copy $src $dst']);
       break;
     default:
-      Expect.fail('Unknown operating system ${Platform.operatingSystem}');
+      throw 'Unknown operating system ${Platform.operatingSystem}';
   }
   if (result.exitCode != 0) {
     print(result.stdout);
@@ -46,7 +44,7 @@
   }
 }
 
-Future testNativeExtensions(String snapshotKind) async {
+Future testNativeExtensions(String? snapshotKind) async {
   String buildDirectory = dirname(Platform.executable);
   Directory tempDirectory =
       Directory.systemTemp.createTempSync('sample_extension_');
diff --git a/samples/sample_extension/test_sample_asynchronous_extension.dart b/samples/sample_extension/test_sample_asynchronous_extension.dart
index 5ceb7c8..b1fd419 100644
--- a/samples/sample_extension/test_sample_asynchronous_extension.dart
+++ b/samples/sample_extension/test_sample_asynchronous_extension.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 test_sample_extension;
 
 import 'sample_asynchronous_extension.dart';
@@ -32,16 +30,16 @@
 void checkNormal(List l) {
   // Count how many times each byte value occurs.  Assert that the counts
   // are all within a reasonable (six-sigma) range.
-  List counts = new List<int>.filled(256, 0);
+  List<int> counts = new List<int>.filled(256, 0);
   for (var e in l) {
     counts[e]++;
   }
   new RandomArray().randomArray(18, 256000).then(checkCorrelation(counts));
 }
 
-Function checkCorrelation(List counts) {
-  return (List l) {
-    List counts_2 = new List<int>.filled(256, 0);
+dynamic Function(List<int>) checkCorrelation(List<int> counts) {
+  return (List<int> l) {
+    List<int> counts_2 = new List<int>.filled(256, 0);
     for (var e in l) {
       counts_2[e]++;
     }
diff --git a/samples/sample_extension/test_sample_synchronous_extension.dart b/samples/sample_extension/test_sample_synchronous_extension.dart
index 77d2fc3..ac17724 100644
--- a/samples/sample_extension/test_sample_synchronous_extension.dart
+++ b/samples/sample_extension/test_sample_synchronous_extension.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 test_sample_extension;
 
 import 'sample_synchronous_extension.dart';
diff --git a/samples_2/ffi/async/sample_async_callback.dart b/samples_2/ffi/async/sample_async_callback.dart
index 5e6d79a..2405a8a 100644
--- a/samples_2/ffi/async/sample_async_callback.dart
+++ b/samples_2/ffi/async/sample_async_callback.dart
@@ -107,7 +107,7 @@
 final executeCallback = dl.lookupFunction<Void Function(Pointer<Work>),
     void Function(Pointer<Work>)>('ExecuteCallback');
 
-class Work extends Struct {}
+class Work extends Opaque {}
 
 Future asyncSleep(int ms) {
   return new Future.delayed(Duration(milliseconds: ms));
diff --git a/samples_2/ffi/calloc.dart b/samples_2/ffi/calloc.dart
new file mode 100644
index 0000000..c6be280
--- /dev/null
+++ b/samples_2/ffi/calloc.dart
@@ -0,0 +1,111 @@
+// 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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+// @dart=2.9
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/samples_2/ffi/coordinate.dart b/samples_2/ffi/coordinate.dart
index 4ff34f5..4d9d300 100644
--- a/samples_2/ffi/coordinate.dart
+++ b/samples_2/ffi/coordinate.dart
@@ -18,8 +18,9 @@
 
   Pointer<Coordinate> next;
 
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
-    return allocate<Coordinate>().ref
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {
+    return allocator<Coordinate>().ref
       ..x = x
       ..y = y
       ..next = next;
diff --git a/samples_2/ffi/dylib_utils.dart b/samples_2/ffi/dylib_utils.dart
index 39653fa..b783ad8 100644
--- a/samples_2/ffi/dylib_utils.dart
+++ b/samples_2/ffi/dylib_utils.dart
@@ -9,7 +9,7 @@
 
 String _platformPath(String name, {String path}) {
   if (path == null) path = "";
-  if (Platform.isLinux || Platform.isAndroid)
+  if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
diff --git a/samples_2/ffi/resource_management/pool.dart b/samples_2/ffi/resource_management/pool.dart
index 776c331..d4610b0 100644
--- a/samples_2/ffi/resource_management/pool.dart
+++ b/samples_2/ffi/resource_management/pool.dart
@@ -7,48 +7,53 @@
 // @dart = 2.9
 
 import "dart:async";
-import 'dart:convert';
 import 'dart:ffi';
-import 'dart:typed_data';
 
-import 'package:ffi/ffi.dart' as packageFfi;
-import 'package:ffi/ffi.dart' show Utf8;
+import 'package:ffi/ffi.dart';
 
-/// Manages native resources.
+import '../calloc.dart';
+
+/// An [Allocator] which frees all allocations at the same time.
 ///
-/// Primary implementations are [Pool] and [Unmanaged].
-abstract class ResourceManager {
-  /// Allocates memory on the native heap.
-  ///
-  /// The native memory is under management by this [ResourceManager].
-  ///
-  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
-  /// against the default public heap. Allocation of either element size or count
-  /// of 0 is undefined.
-  ///
-  /// Throws an ArgumentError on failure to allocate.
-  Pointer<T> allocate<T extends NativeType>({int count: 1});
-}
+/// The pool allows you to allocate heap memory, but ignores calls to [free].
+/// Instead you call [releaseAll] to release all the allocations at the same
+/// time.
+///
+/// Also allows other resources to be associated with the pool, through the
+/// [using] method, to have a release function called for them when the pool is
+/// released.
+///
+/// An [Allocator] can be provided to do the actual allocation and freeing.
+/// Defaults to using [calloc].
+class Pool implements Allocator {
+  /// The [Allocator] used for allocation and freeing.
+  final Allocator _wrappedAllocator;
 
-/// Manages native resources.
-class Pool implements ResourceManager {
   /// Native memory under management by this [Pool].
   final List<Pointer<NativeType>> _managedMemoryPointers = [];
 
   /// Callbacks for releasing native resources under management by this [Pool].
   final List<Function()> _managedResourceReleaseCallbacks = [];
 
-  /// Allocates memory on the native heap.
+  bool _inUse = true;
+
+  /// Creates a pool of allocations.
   ///
-  /// The native memory is under management by this [Pool].
+  /// The [allocator] is used to do the actual allocation and freeing of
+  /// memory. It defaults to using [calloc].
+  Pool([Allocator allocator = calloc]) : _wrappedAllocator = allocator;
+
+  /// Allocates memory and includes it in the pool.
   ///
-  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
-  /// against the default public heap. Allocation of either element size or count
-  /// of 0 is undefined.
+  /// Uses the allocator provided to the [Pool] constructor to do the
+  /// allocation.
   ///
-  /// Throws an ArgumentError on failure to allocate.
-  Pointer<T> allocate<T extends NativeType>({int count: 1}) {
-    final p = Unmanaged().allocate<T>(count: count);
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
+    _ensureInUse();
+    final p = _wrappedAllocator.allocate<T>(byteCount, alignment: alignment);
     _managedMemoryPointers.add(p);
     return p;
   }
@@ -57,6 +62,8 @@
   ///
   /// Executes [releaseCallback] on [releaseAll].
   T using<T>(T resource, Function(T) releaseCallback) {
+    _ensureInUse();
+    releaseCallback = Zone.current.bindUnaryCallback(releaseCallback);
     _managedResourceReleaseCallbacks.add(() => releaseCallback(resource));
     return resource;
   }
@@ -67,130 +74,102 @@
   }
 
   /// Releases all resources that this [Pool] manages.
-  void releaseAll() {
-    for (final c in _managedResourceReleaseCallbacks) {
-      c();
+  ///
+  /// If [reuse] is `true`, the pool can be used again after resources
+  /// have been released. If not, the default, then the [allocate]
+  /// and [using] methods must not be called after a call to `releaseAll`.
+  void releaseAll({bool reuse = false}) {
+    if (!reuse) {
+      _inUse = false;
     }
-    _managedResourceReleaseCallbacks.clear();
+    while (_managedResourceReleaseCallbacks.isNotEmpty) {
+      _managedResourceReleaseCallbacks.removeLast()();
+    }
     for (final p in _managedMemoryPointers) {
-      Unmanaged().free(p);
+      _wrappedAllocator.free(p);
     }
     _managedMemoryPointers.clear();
   }
+
+  /// Does nothing, invoke [releaseAll] instead.
+  @override
+  void free(Pointer<NativeType> pointer) {}
+
+  void _ensureInUse() {
+    if (!_inUse) {
+      throw StateError(
+          "Pool no longer in use, `releaseAll(reuse: false)` was called.");
+    }
+  }
 }
 
-/// Creates a [Pool] to manage native resources.
+/// Runs [computation] with a new [Pool], and releases all allocations at the end.
 ///
-/// If the isolate is shut down, through `Isolate.kill()`, resources are _not_ cleaned up.
-R using<R>(R Function(Pool) f) {
-  final p = Pool();
+/// If [R] is a [Future], all allocations are released when the future completes.
+///
+/// If the isolate is shut down, through `Isolate.kill()`, resources are _not_
+/// cleaned up.
+R using<R>(R Function(Pool) computation,
+    [Allocator wrappedAllocator = calloc]) {
+  final pool = Pool(wrappedAllocator);
+  bool isAsync = false;
   try {
-    return f(p);
+    final result = computation(pool);
+    if (result is Future) {
+      isAsync = true;
+      return (result.whenComplete(pool.releaseAll) as R);
+    }
+    return result;
   } finally {
-    p.releaseAll();
+    if (!isAsync) {
+      pool.releaseAll();
+    }
   }
 }
 
 /// Creates a zoned [Pool] to manage native resources.
 ///
-/// Pool is availabe through [currentPool].
-///
-/// Please note that all throws are caught and packaged in [RethrownError].
+/// The pool is availabe through [zonePool].
 ///
 /// If the isolate is shut down, through `Isolate.kill()`, resources are _not_ cleaned up.
-R usePool<R>(R Function() f) {
-  final p = Pool();
+R withZonePool<R>(R Function() computation,
+    [Allocator wrappedAllocator = calloc]) {
+  final pool = Pool(wrappedAllocator);
+  var poolHolder = [pool];
+  bool isAsync = false;
   try {
-    return runZoned(() => f(),
-        zoneValues: {#_pool: p},
-        onError: (error, st) => throw RethrownError(error, st));
+    return runZoned(() {
+      final result = computation();
+      if (result is Future) {
+        isAsync = true;
+        result.whenComplete(pool.releaseAll);
+      }
+      return result;
+    }, zoneValues: {#_pool: poolHolder});
   } finally {
-    p.releaseAll();
+    if (!isAsync) {
+      pool.releaseAll();
+      poolHolder.remove(pool);
+    }
   }
 }
 
-/// The [Pool] in the current zone.
-Pool get currentPool => Zone.current[#_pool];
-
-class RethrownError {
-  dynamic original;
-  StackTrace originalStackTrace;
-  RethrownError(this.original, this.originalStackTrace);
-  toString() => """RethrownError(${original})
-${originalStackTrace}""";
-}
-
-/// Does not manage it's resources.
-class Unmanaged implements ResourceManager {
-  /// Allocates memory on the native heap.
-  ///
-  /// For POSIX-based systems, this uses malloc. On Windows, it uses HeapAlloc
-  /// against the default public heap. Allocation of either element size or count
-  /// of 0 is undefined.
-  ///
-  /// Throws an ArgumentError on failure to allocate.
-  Pointer<T> allocate<T extends NativeType>({int count = 1}) =>
-      packageFfi.allocate(count: count);
-
-  /// Releases memory on the native heap.
-  ///
-  /// For POSIX-based systems, this uses free. On Windows, it uses HeapFree
-  /// against the default public heap. It may only be used against pointers
-  /// allocated in a manner equivalent to [allocate].
-  ///
-  /// Throws an ArgumentError on failure to free.
-  ///
-  void free(Pointer pointer) => packageFfi.free(pointer);
-}
-
-/// Does not manage it's resources.
-final Unmanaged unmanaged = Unmanaged();
-
-extension Utf8InPool on String {
-  /// Convert a [String] to a Utf8-encoded null-terminated C string.
-  ///
-  /// If 'string' contains NULL bytes, the converted string will be truncated
-  /// prematurely. Unpaired surrogate code points in [string] will be preserved
-  /// in the UTF-8 encoded result. See [Utf8Encoder] for details on encoding.
-  ///
-  /// Returns a malloc-allocated pointer to the result.
-  ///
-  /// The memory is managed by the [Pool] passed in as [pool].
-  Pointer<Utf8> toUtf8(ResourceManager pool) {
-    final units = utf8.encode(this);
-    final Pointer<Uint8> result = pool.allocate<Uint8>(count: units.length + 1);
-    final Uint8List nativeString = result.asTypedList(units.length + 1);
-    nativeString.setAll(0, units);
-    nativeString[units.length] = 0;
-    return result.cast();
+/// A zone-specific [Pool].
+///
+/// Asynchronous computations can share a [Pool]. Use [withZonePool] to create
+/// a new zone with a fresh [Pool], and that pool will then be released
+/// automatically when the function passed to [withZonePool] completes.
+/// All code inside that zone can use `zonePool` to access the pool.
+///
+/// The current pool must not be accessed by code which is not running inside
+/// a zone created by [withZonePool].
+Pool get zonePool {
+  final List<Pool> poolHolder = Zone.current[#_pool];
+  if (poolHolder == null) {
+    throw StateError("Not inside a zone created by `usePool`");
   }
-}
-
-extension Utf8Helpers on Pointer<Utf8> {
-  /// Returns the length of a null-terminated string -- the number of (one-byte)
-  /// characters before the first null byte.
-  int strlen() {
-    final Pointer<Uint8> array = this.cast<Uint8>();
-    final Uint8List nativeString = array.asTypedList(_maxSize);
-    return nativeString.indexWhere((char) => char == 0);
+  if (!poolHolder.isEmpty) {
+    return poolHolder.single;
   }
-
-  /// Creates a [String] containing the characters UTF-8 encoded in [this].
-  ///
-  /// [this] must be a zero-terminated byte sequence of valid UTF-8
-  /// encodings of Unicode code points. It may also contain UTF-8 encodings of
-  /// unpaired surrogate code points, which is not otherwise valid UTF-8, but
-  /// which may be created when encoding a Dart string containing an unpaired
-  /// surrogate. See [Utf8Decoder] for details on decoding.
-  ///
-  /// Returns a Dart string containing the decoded code points.
-  String contents() {
-    final int length = strlen();
-    return utf8.decode(Uint8List.view(
-        this.cast<Uint8>().asTypedList(length).buffer, 0, length));
-  }
+  throw StateError("Pool as already been cleared with releaseAll.");
 }
-
-const int _kMaxSmi64 = (1 << 62) - 1;
-const int _kMaxSmi32 = (1 << 30) - 1;
-final int _maxSize = sizeOf<IntPtr>() == 8 ? _kMaxSmi64 : _kMaxSmi32;
diff --git a/samples_2/ffi/resource_management/pool_isolate_shutdown_sample.dart b/samples_2/ffi/resource_management/pool_isolate_shutdown_sample.dart
index 8d3401b..4c8eb0f 100644
--- a/samples_2/ffi/resource_management/pool_isolate_shutdown_sample.dart
+++ b/samples_2/ffi/resource_management/pool_isolate_shutdown_sample.dart
@@ -88,4 +88,4 @@
     void Function(Pointer<SomeResource>)>("ReleaseResource");
 
 /// Represents some opaque resource being managed by a library.
-class SomeResource extends Struct {}
+class SomeResource extends Opaque {}
diff --git a/samples_2/ffi/resource_management/pool_sample.dart b/samples_2/ffi/resource_management/pool_sample.dart
index 87c5e39..e3441c1 100644
--- a/samples_2/ffi/resource_management/pool_sample.dart
+++ b/samples_2/ffi/resource_management/pool_sample.dart
@@ -11,9 +11,10 @@
 import 'package:expect/expect.dart';
 
 import 'pool.dart';
+import 'utf8_helpers.dart';
 import '../dylib_utils.dart';
 
-main() {
+main() async {
   final ffiTestDynamicLibrary =
       dlopenPlatformSpecific("ffi_test_dynamic_library");
 
@@ -23,7 +24,7 @@
 
   // To ensure resources are freed, wrap them in a [using] call.
   using((Pool pool) {
-    final p = pool.allocate<Int64>(count: 2);
+    final p = pool<Int64>(2);
     p[0] = 24;
     MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), sizeOf<Int64>());
     print(p[1]);
@@ -33,14 +34,14 @@
   // Resources are freed also when abnormal control flow occurs.
   try {
     using((Pool pool) {
-      final p = pool.allocate<Int64>(count: 2);
+      final p = pool<Int64>(2);
       p[0] = 25;
       MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), 8);
       print(p[1]);
       Expect.equals(25, p[1]);
       throw Exception("Some random exception");
     });
-    // `free(p)` has been called.
+    // `calloc.free(p)` has been called.
   } on Exception catch (e) {
     print("Caught exception: $e");
   }
@@ -48,8 +49,8 @@
   // In a pool multiple resources can be allocated, which will all be freed
   // at the end of the scope.
   using((Pool pool) {
-    final p = pool.allocate<Int64>(count: 2);
-    final p2 = pool.allocate<Int64>(count: 2);
+    final p = pool<Int64>(2);
+    final p2 = pool<Int64>(2);
     p[0] = 1;
     p[1] = 2;
     MemMove(p2.cast<Void>(), p.cast<Void>(), 2 * sizeOf<Int64>());
@@ -60,7 +61,7 @@
   // If the resource allocation happens in a different scope, then one either
   // needs to pass the pool to that scope.
   f1(Pool pool) {
-    return pool.allocate<Int64>(count: 2);
+    return pool<Int64>(2);
   }
 
   using((Pool pool) {
@@ -109,7 +110,25 @@
   } on Exception catch (e) {
     print("Caught exception: $e");
   }
+
+  /// [using] waits with releasing its resources until after [Future]s
+  /// complete.
+  List<int> freed = [];
+  freeInt(int i) {
+    freed.add(i);
+  }
+
+  Future<int> myFutureInt = using((Pool pool) {
+    return Future.microtask(() {
+      pool.using(1, freeInt);
+      return 1;
+    });
+  });
+
+  Expect.isTrue(freed.isEmpty);
+  await myFutureInt;
+  Expect.equals(1, freed.single);
 }
 
 /// Represents some opaque resource being managed by a library.
-class SomeResource extends Struct {}
+class SomeResource extends Opaque {}
diff --git a/samples_2/ffi/resource_management/pool_zoned_sample.dart b/samples_2/ffi/resource_management/pool_zoned_sample.dart
index 0b4e8ff..b9142c2 100644
--- a/samples_2/ffi/resource_management/pool_zoned_sample.dart
+++ b/samples_2/ffi/resource_management/pool_zoned_sample.dart
@@ -11,9 +11,10 @@
 import 'package:expect/expect.dart';
 
 import 'pool.dart';
+import 'utf8_helpers.dart';
 import '../dylib_utils.dart';
 
-main() {
+main() async {
   final ffiTestDynamicLibrary =
       dlopenPlatformSpecific("ffi_test_dynamic_library");
 
@@ -21,9 +22,9 @@
       Void Function(Pointer<Void>, Pointer<Void>, IntPtr),
       void Function(Pointer<Void>, Pointer<Void>, int)>("MemMove");
 
-  // To ensure resources are freed, wrap them in a [using] call.
-  usePool(() {
-    final p = currentPool.allocate<Int64>(count: 2);
+  // To ensure resources are freed, wrap them in a [withZonePool] call.
+  withZonePool(() {
+    final p = zonePool<Int64>(2);
     p[0] = 24;
     MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), sizeOf<Int64>());
     print(p[1]);
@@ -32,24 +33,23 @@
 
   // Resources are freed also when abnormal control flow occurs.
   try {
-    usePool(() {
-      final p = currentPool.allocate<Int64>(count: 2);
+    withZonePool(() {
+      final p = zonePool<Int64>(2);
       p[0] = 25;
       MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), 8);
       print(p[1]);
       Expect.equals(25, p[1]);
       throw Exception("Some random exception");
     });
-  } on RethrownError catch (e) {
-    // Note that exceptions are wrapped when using zones.
-    print("Caught exception: ${e.original}");
+  } catch (e) {
+    print("Caught exception: ${e}");
   }
 
   // In a pool multiple resources can be allocated, which will all be freed
   // at the end of the scope.
-  usePool(() {
-    final p = currentPool.allocate<Int64>(count: 2);
-    final p2 = currentPool.allocate<Int64>(count: 2);
+  withZonePool(() {
+    final p = zonePool<Int64>(2);
+    final p2 = zonePool<Int64>(2);
     p[0] = 1;
     p[1] = 2;
     MemMove(p2.cast<Void>(), p.cast<Void>(), 2 * sizeOf<Int64>());
@@ -60,10 +60,10 @@
   // If the resource allocation happens in a different scope, it is in the
   // same zone, so it's lifetime is automatically managed by the pool.
   f1() {
-    return currentPool.allocate<Int64>(count: 2);
+    return zonePool<Int64>(2);
   }
 
-  usePool(() {
+  withZonePool(() {
     final p = f1();
     final p2 = f1();
     p[0] = 1;
@@ -74,8 +74,8 @@
   });
 
   // Using Strings.
-  usePool(() {
-    final p = "Hello world!".toUtf8(currentPool);
+  withZonePool(() {
+    final p = "Hello world!".toUtf8(zonePool);
     print(p.contents());
   });
 
@@ -92,25 +92,43 @@
       void Function(Pointer<SomeResource>)>("ReleaseResource");
 
   // Using an FFI call to release a resource.
-  usePool(() {
-    final r = currentPool.using(allocateResource(), releaseResource);
+  withZonePool(() {
+    final r = zonePool.using(allocateResource(), releaseResource);
     useResource(r);
   });
 
   // Using an FFI call to release a resource with abnormal control flow.
   try {
-    usePool(() {
-      final r = currentPool.using(allocateResource(), releaseResource);
+    withZonePool(() {
+      final r = zonePool.using(allocateResource(), releaseResource);
       useResource(r);
 
       throw Exception("Some random exception");
     });
     // Resource has been freed.
-  } on RethrownError catch (e) {
-    // Note that exceptions are wrapped when using zones.
-    print("Caught exception: ${e.original}");
+  } catch (e) {
+    print("Caught exception: ${e}");
   }
+
+  /// [using] waits with releasing its resources until after [Future]s
+  /// complete.
+
+  List<int> freed = [];
+  freeInt(int i) {
+    freed.add(i);
+  }
+
+  Future<int> myFutureInt = withZonePool(() {
+    return Future.microtask(() {
+      zonePool.using(1, freeInt);
+      return 1;
+    });
+  });
+
+  Expect.isTrue(freed.isEmpty);
+  await myFutureInt;
+  Expect.equals(1, freed.single);
 }
 
 /// Represents some opaque resource being managed by a library.
-class SomeResource extends Struct {}
+class SomeResource extends Opaque {}
diff --git a/samples_2/ffi/resource_management/unmanaged_sample.dart b/samples_2/ffi/resource_management/unmanaged_sample.dart
index b8c9971..e73f7cc 100644
--- a/samples_2/ffi/resource_management/unmanaged_sample.dart
+++ b/samples_2/ffi/resource_management/unmanaged_sample.dart
@@ -9,8 +9,10 @@
 import 'dart:ffi';
 
 import 'package:expect/expect.dart';
+import 'package:ffi/ffi.dart';
 
-import 'pool.dart';
+import 'utf8_helpers.dart';
+import '../calloc.dart';
 import '../dylib_utils.dart';
 
 main() {
@@ -24,15 +26,15 @@
   // To ensure resources are freed, call free manually.
   //
   // For automatic management use a Pool.
-  final p = unmanaged.allocate<Int64>(count: 2);
+  final p = calloc<Int64>(2);
   p[0] = 24;
   MemMove(p.elementAt(1).cast<Void>(), p.cast<Void>(), sizeOf<Int64>());
   print(p[1]);
   Expect.equals(24, p[1]);
-  unmanaged.free(p);
+  calloc.free(p);
 
   // Using Strings.
-  final p2 = "Hello world!".toUtf8(unmanaged);
+  final p2 = "Hello world!".toUtf8(calloc);
   print(p2.contents());
-  unmanaged.free(p2);
+  calloc.free(p2);
 }
diff --git a/samples_2/ffi/resource_management/utf8_helpers.dart b/samples_2/ffi/resource_management/utf8_helpers.dart
new file mode 100644
index 0000000..e1d555b
--- /dev/null
+++ b/samples_2/ffi/resource_management/utf8_helpers.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.
+//
+// Explicit pool used for managing resources.
+
+// @dart = 2.9
+
+import 'dart:convert';
+import 'dart:ffi';
+import 'dart:typed_data';
+
+import 'package:ffi/ffi.dart';
+
+extension Utf8InPool on String {
+  /// Convert a [String] to a Utf8-encoded null-terminated C string.
+  ///
+  /// If 'string' contains NULL bytes, the converted string will be truncated
+  /// prematurely. See [Utf8Encoder] for details on encoding.
+  ///
+  /// Returns a [allocator]-allocated pointer to the result.
+  Pointer<Utf8> toUtf8(Allocator allocator) {
+    final units = utf8.encode(this);
+    final Pointer<Uint8> result = allocator<Uint8>(units.length + 1);
+    final Uint8List nativeString = result.asTypedList(units.length + 1);
+    nativeString.setAll(0, units);
+    nativeString[units.length] = 0;
+    return result.cast();
+  }
+}
+
+extension Utf8Helpers on Pointer<Utf8> {
+  /// The length of a null-terminated string — the number of (one-byte)
+  /// characters before the first null byte.
+  int get strlen {
+    final Pointer<Uint8> array = this.cast<Uint8>();
+    final Uint8List nativeString = array.asTypedList(_maxSize);
+    return nativeString.indexWhere((char) => char == 0);
+  }
+
+  /// Creates a [String] containing the characters UTF-8 encoded in [this].
+  ///
+  /// [this] must be a zero-terminated byte sequence of valid UTF-8
+  /// encodings of Unicode code points.See [Utf8Decoder] for details on
+  /// decoding.
+  ///
+  /// Returns a Dart string containing the decoded code points.
+  String contents() {
+    final int length = strlen;
+    return utf8.decode(Uint8List.view(
+        this.cast<Uint8>().asTypedList(length).buffer, 0, length));
+  }
+}
+
+const int _kMaxSmi64 = (1 << 62) - 1;
+const int _kMaxSmi32 = (1 << 30) - 1;
+final int _maxSize = sizeOf<IntPtr>() == 8 ? _kMaxSmi64 : _kMaxSmi32;
diff --git a/samples_2/ffi/sample_ffi_bitfield.dart b/samples_2/ffi/sample_ffi_bitfield.dart
index 91bb65d..78c41df 100644
--- a/samples_2/ffi/sample_ffi_bitfield.dart
+++ b/samples_2/ffi/sample_ffi_bitfield.dart
@@ -9,6 +9,8 @@
 import 'package:ffi/ffi.dart';
 import 'package:expect/expect.dart';
 
+import 'calloc.dart';
+
 /// typedef struct {
 ///     unsigned int bold      : 1;
 ///     unsigned int underline : 2;
@@ -95,7 +97,7 @@
 }
 
 main() {
-  final p = allocate<ScreenCellAttrs>(count: 3);
+  final p = calloc<ScreenCellAttrs>(3);
 
   // Zeroes out all fields.
   p.ref.bits = 0;
@@ -121,5 +123,5 @@
   // A check for automated testing.
   Expect.equals(1933, p.ref.bits);
 
-  free(p);
+  calloc.free(p);
 }
diff --git a/samples_2/ffi/sample_ffi_data.dart b/samples_2/ffi/sample_ffi_data.dart
index 09dba76..2d22011 100644
--- a/samples_2/ffi/sample_ffi_data.dart
+++ b/samples_2/ffi/sample_ffi_data.dart
@@ -7,29 +7,31 @@
 import 'dart:ffi';
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
+
 main() {
   print('start main');
 
   {
     // Basic operation: allocate, get, set, and free.
-    Pointer<Int64> p = allocate();
+    Pointer<Int64> p = calloc();
     p.value = 42;
     int pValue = p.value;
     print('${p.runtimeType} value: ${pValue}');
-    free(p);
+    calloc.free(p);
   }
 
   {
     // Undefined behavior before set.
-    Pointer<Int64> p = allocate();
+    Pointer<Int64> p = calloc();
     int pValue = p.value;
     print('If not set, returns garbage: ${pValue}');
-    free(p);
+    calloc.free(p);
   }
 
   {
     // Pointers can be created from an address.
-    Pointer<Int64> pHelper = allocate();
+    Pointer<Int64> pHelper = calloc();
     pHelper.value = 1337;
 
     int address = pHelper.address;
@@ -38,13 +40,13 @@
     Pointer<Int64> p = Pointer.fromAddress(address);
     print('${p.runtimeType} value: ${p.value}');
 
-    free(pHelper);
+    calloc.free(pHelper);
   }
 
   {
     // Address is zeroed out after free.
-    Pointer<Int64> p = allocate();
-    free(p);
+    Pointer<Int64> p = calloc();
+    calloc.free(p);
     print('After free, address is zero: ${p.address}');
   }
 
@@ -52,13 +54,13 @@
     // Allocating too much throws an exception.
     try {
       int maxMint = 9223372036854775807; // 2^63 - 1
-      allocate<Int64>(count: maxMint);
+      calloc<Int64>(maxMint);
     } on Error {
       print('Expected exception on allocating too much');
     }
     try {
       int maxInt1_8 = 1152921504606846975; // 2^60 -1
-      allocate<Int64>(count: maxInt1_8);
+      calloc<Int64>(maxInt1_8);
     } on Error {
       print('Expected exception on allocating too much');
     }
@@ -67,7 +69,7 @@
   {
     // Pointers can be cast into another type,
     // resulting in the corresponding bits read.
-    Pointer<Int64> p1 = allocate();
+    Pointer<Int64> p1 = calloc();
     p1.value = 9223372036854775807; // 2^63 - 1
 
     Pointer<Int32> p2 = p1.cast();
@@ -76,61 +78,61 @@
     Pointer<Int32> p3 = p2.elementAt(1);
     print('${p3.runtimeType} value: ${p3.value}'); // 2^31 - 1
 
-    free(p1);
+    calloc.free(p1);
   }
 
   {
     // Data can be tightly packed in memory.
-    Pointer<Int8> p = allocate(count: 8);
+    Pointer<Int8> p = calloc(8);
     for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
       p.elementAt(i).value = i * 3;
     }
     for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
       print('p.elementAt($i) value: ${p.elementAt(i).value}');
     }
-    free(p);
+    calloc.free(p);
   }
 
   {
     // Values that don't fit are truncated.
-    Pointer<Int32> p11 = allocate();
+    Pointer<Int32> p11 = calloc();
 
     p11.value = 9223372036854775807;
 
     print(p11);
 
-    free(p11);
+    calloc.free(p11);
   }
 
   {
     // Doubles.
-    Pointer<Double> p = allocate();
+    Pointer<Double> p = calloc();
     p.value = 3.14159265359;
     print('${p.runtimeType} value: ${p.value}');
     p.value = 3.14;
     print('${p.runtimeType} value: ${p.value}');
-    free(p);
+    calloc.free(p);
   }
 
   {
     // Floats.
-    Pointer<Float> p = allocate();
+    Pointer<Float> p = calloc();
     p.value = 3.14159265359;
     print('${p.runtimeType} value: ${p.value}');
     p.value = 3.14;
     print('${p.runtimeType} value: ${p.value}');
-    free(p);
+    calloc.free(p);
   }
 
   {
     // IntPtr varies in size based on whether the platform is 32 or 64 bit.
     // Addresses of pointers fit in this size.
-    Pointer<IntPtr> p = allocate();
+    Pointer<IntPtr> p = calloc();
     int p14addr = p.address;
     p.value = p14addr;
     int pValue = p.value;
     print('${p.runtimeType} value: ${pValue}');
-    free(p);
+    calloc.free(p);
   }
 
   {
@@ -138,19 +140,19 @@
     // The size of the element it is pointing to is undefined,
     // they cannot be allocated, read, or written.
 
-    Pointer<IntPtr> p1 = allocate();
+    Pointer<IntPtr> p1 = calloc();
     Pointer<Void> p2 = p1.cast();
     print('${p2.runtimeType} address: ${p2.address}');
 
-    free(p1);
+    calloc.free(p1);
   }
 
   {
     // Pointer to a pointer to something.
-    Pointer<Int16> pHelper = allocate();
+    Pointer<Int16> pHelper = calloc();
     pHelper.value = 17;
 
-    Pointer<Pointer<Int16>> p = allocate();
+    Pointer<Pointer<Int16>> p = calloc();
 
     // Storing into a pointer pointer automatically unboxes.
     p.value = pHelper;
@@ -162,31 +164,31 @@
     int pValue = p.value.value;
     print('${p.runtimeType} value\'s value: ${pValue}');
 
-    free(p);
-    free(pHelper);
+    calloc.free(p);
+    calloc.free(pHelper);
   }
 
   {
     // The pointer to pointer types must match up.
-    Pointer<Int8> pHelper = allocate();
+    Pointer<Int8> pHelper = calloc();
     pHelper.value = 123;
 
-    Pointer<Pointer<Int16>> p = allocate();
+    Pointer<Pointer<Int16>> p = calloc();
 
     // Trying to store `pHelper` into `p.val` would result in a type mismatch.
 
-    free(pHelper);
-    free(p);
+    calloc.free(pHelper);
+    calloc.free(p);
   }
 
   {
     // `nullptr` points to address 0 in c++.
-    Pointer<Pointer<Int8>> pointerToPointer = allocate();
+    Pointer<Pointer<Int8>> pointerToPointer = calloc();
     Pointer<Int8> value = nullptr;
     pointerToPointer.value = value;
     value = pointerToPointer.value;
     print("Loading a pointer to the 0 address is null: ${value}");
-    free(pointerToPointer);
+    calloc.free(pointerToPointer);
   }
 
   {
@@ -207,7 +209,7 @@
         head.value = value;
         return;
       }
-      Pointer<IntPtr> next = allocate<IntPtr>();
+      Pointer<IntPtr> next = calloc<IntPtr>();
       head.value = next.address;
       createChain(next, length - 1, value);
     }
@@ -222,7 +224,7 @@
 
     void freeChain(Pointer<IntPtr> head, int length) {
       Pointer<IntPtr> next = Pointer.fromAddress(head.value);
-      free(head);
+      calloc.free(head);
       if (length == 0) {
         return;
       }
@@ -230,7 +232,7 @@
     }
 
     int length = 10;
-    Pointer<IntPtr> head = allocate();
+    Pointer<IntPtr> head = calloc();
     createChain(head, length, 512);
     int tailValue = getChainValue(head, length);
     print('tailValue: ${tailValue}');
diff --git a/samples_2/ffi/sample_ffi_functions.dart b/samples_2/ffi/sample_ffi_functions.dart
index 4cd30b0..1bf8ecc 100644
--- a/samples_2/ffi/sample_ffi_functions.dart
+++ b/samples_2/ffi/sample_ffi_functions.dart
@@ -8,6 +8,7 @@
 
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 typedef NativeUnaryOp = Int32 Function(Int32);
@@ -186,7 +187,7 @@
     // pass an array / pointer as argument
     Int64PointerUnOp assign1337Index1 = ffiTestFunctions
         .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
-    Pointer<Int64> p2 = allocate(count: 2);
+    Pointer<Int64> p2 = calloc(2);
     p2.value = 42;
     p2[1] = 1000;
     print(p2.elementAt(1).address.toRadixString(16));
@@ -251,11 +252,11 @@
     print(result);
     print(result.runtimeType);
 
-    Pointer<Int64> p2 = allocate(count: 2);
+    Pointer<Int64> p2 = calloc(2);
     result = nullableInt64ElemAt1(p2);
     print(result);
     print(result.runtimeType);
-    free(p2);
+    calloc.free(p2);
   }
 
   print("end main");
diff --git a/samples_2/ffi/sample_ffi_functions_callbacks.dart b/samples_2/ffi/sample_ffi_functions_callbacks.dart
index 79f9a41..1d9dc12 100644
--- a/samples_2/ffi/sample_ffi_functions_callbacks.dart
+++ b/samples_2/ffi/sample_ffi_functions_callbacks.dart
@@ -6,6 +6,9 @@
 
 import 'dart:ffi';
 
+import 'package:ffi/ffi.dart';
+
+import 'calloc.dart';
 import 'coordinate.dart';
 import 'dylib_utils.dart';
 
@@ -45,7 +48,7 @@
     Pointer<NativeFunction<CoordinateTrice>> p2 =
         ffiTestFunctions.lookup("CoordinateUnOpTrice");
     CoordinateTrice coordinateUnOpTrice = p2.asFunction();
-    Coordinate c1 = Coordinate.allocate(10.0, 20.0, nullptr);
+    Coordinate c1 = Coordinate.allocate(calloc, 10.0, 20.0, nullptr);
     c1.next = c1.addressOf;
     Coordinate result =
         coordinateUnOpTrice(transposeCoordinatePointer, c1.addressOf).ref;
diff --git a/samples_2/ffi/sample_ffi_functions_structs.dart b/samples_2/ffi/sample_ffi_functions_structs.dart
index 7129658..41b608d 100644
--- a/samples_2/ffi/sample_ffi_functions_structs.dart
+++ b/samples_2/ffi/sample_ffi_functions_structs.dart
@@ -6,11 +6,12 @@
 
 import 'dart:ffi';
 
+import 'package:ffi/ffi.dart';
+
+import 'calloc.dart';
 import 'coordinate.dart';
 import 'dylib_utils.dart';
 
-import 'package:ffi/ffi.dart';
-
 typedef NativeCoordinateOp = Pointer<Coordinate> Function(Pointer<Coordinate>);
 
 main() {
@@ -25,8 +26,8 @@
         ffiTestFunctions.lookup("TransposeCoordinate");
     NativeCoordinateOp f1 = p1.asFunction();
 
-    Coordinate c1 = Coordinate.allocate(10.0, 20.0, nullptr);
-    Coordinate c2 = Coordinate.allocate(42.0, 84.0, c1.addressOf);
+    Coordinate c1 = Coordinate.allocate(calloc, 10.0, 20.0, nullptr);
+    Coordinate c2 = Coordinate.allocate(calloc, 42.0, 84.0, c1.addressOf);
     c1.next = c2.addressOf;
 
     Coordinate result = f1(c1.addressOf).ref;
@@ -46,7 +47,7 @@
         ffiTestFunctions.lookup("CoordinateElemAt1");
     NativeCoordinateOp f1 = p1.asFunction();
 
-    Pointer<Coordinate> c1 = allocate<Coordinate>(count: 3);
+    Pointer<Coordinate> c1 = calloc<Coordinate>(3);
     Pointer<Coordinate> c2 = c1.elementAt(1);
     Pointer<Coordinate> c3 = c1.elementAt(2);
     c1.ref.x = 10.0;
diff --git a/samples_2/ffi/sample_ffi_structs.dart b/samples_2/ffi/sample_ffi_structs.dart
index d5af59e..94b19cc 100644
--- a/samples_2/ffi/sample_ffi_structs.dart
+++ b/samples_2/ffi/sample_ffi_structs.dart
@@ -8,6 +8,7 @@
 
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
 import 'coordinate.dart';
 
 main() {
@@ -15,9 +16,9 @@
 
   {
     // Allocates each coordinate separately in c memory.
-    Coordinate c1 = Coordinate.allocate(10.0, 10.0, nullptr);
-    Coordinate c2 = Coordinate.allocate(20.0, 20.0, c1.addressOf);
-    Coordinate c3 = Coordinate.allocate(30.0, 30.0, c2.addressOf);
+    Coordinate c1 = Coordinate.allocate(calloc, 10.0, 10.0, nullptr);
+    Coordinate c2 = Coordinate.allocate(calloc, 20.0, 20.0, c1.addressOf);
+    Coordinate c3 = Coordinate.allocate(calloc, 30.0, 30.0, c2.addressOf);
     c1.next = c3.addressOf;
 
     Coordinate currentCoordinate = c1;
@@ -26,14 +27,14 @@
       print("${currentCoordinate.x}; ${currentCoordinate.y}");
     }
 
-    free(c1.addressOf);
-    free(c2.addressOf);
-    free(c3.addressOf);
+    calloc.free(c1.addressOf);
+    calloc.free(c2.addressOf);
+    calloc.free(c3.addressOf);
   }
 
   {
     // Allocates coordinates consecutively in c memory.
-    Pointer<Coordinate> c1 = allocate<Coordinate>(count: 3);
+    Pointer<Coordinate> c1 = calloc<Coordinate>(3);
     Pointer<Coordinate> c2 = c1.elementAt(1);
     Pointer<Coordinate> c3 = c1.elementAt(2);
     c1.ref.x = 10.0;
@@ -52,15 +53,15 @@
       print("${currentCoordinate.x}; ${currentCoordinate.y}");
     }
 
-    free(c1);
+    calloc.free(c1);
   }
 
   {
-    Coordinate c = Coordinate.allocate(10, 10, nullptr);
+    Coordinate c = Coordinate.allocate(calloc, 10, 10, nullptr);
     print(c is Coordinate);
     print(c is Pointer<Void>);
     print(c is Pointer);
-    free(c.addressOf);
+    calloc.free(c.addressOf);
   }
 
   print("end main");
diff --git a/samples_2/ffi/sqlite/lib/sqlite.dart b/samples_2/ffi/sqlite/lib/sqlite.dart
index 825e434..0e0669b 100644
--- a/samples_2/ffi/sqlite/lib/sqlite.dart
+++ b/samples_2/ffi/sqlite/lib/sqlite.dart
@@ -10,3 +10,5 @@
 library sqlite;
 
 export "src/database.dart";
+
+export "src/ffi/calloc.dart" show calloc;
diff --git a/samples_2/ffi/sqlite/lib/src/bindings/types.dart b/samples_2/ffi/sqlite/lib/src/bindings/types.dart
index f6a1736..763f47e 100644
--- a/samples_2/ffi/sqlite/lib/src/bindings/types.dart
+++ b/samples_2/ffi/sqlite/lib/src/bindings/types.dart
@@ -15,7 +15,7 @@
 /// is its destructor.  There are many other interfaces (such as
 /// [sqlite3_prepare_v2()], [sqlite3_create_function()], and
 /// [sqlite3_busy_timeout()] to name but three) that are methods on an
-class Database extends Struct {}
+class Database extends Opaque {}
 
 /// SQL Statement Object
 ///
@@ -38,7 +38,7 @@
 ///
 /// Refer to documentation on individual methods above for additional
 /// information.
-class Statement extends Struct {}
+class Statement extends Opaque {}
 
 /// Dynamically Typed Value Object
 ///
@@ -74,4 +74,4 @@
 /// [sqlite3_result_value()] and [sqlite3_bind_value()].
 /// The [sqlite3_value_blob | sqlite3_value_type()] family of
 /// interfaces require protected sqlite3_value objects.
-class Value extends Struct {}
+class Value extends Opaque {}
diff --git a/samples_2/ffi/sqlite/lib/src/database.dart b/samples_2/ffi/sqlite/lib/src/database.dart
index 38121a9..687fea8 100644
--- a/samples_2/ffi/sqlite/lib/src/database.dart
+++ b/samples_2/ffi/sqlite/lib/src/database.dart
@@ -17,6 +17,8 @@
 import "bindings/constants.dart";
 import "collections/closable_iterator.dart";
 
+import 'ffi/calloc.dart';
+
 /// [Database] represents an open connection to a SQLite database.
 ///
 /// All functions against a database may throw [SQLiteError].
@@ -29,13 +31,13 @@
   /// Open a database located at the file [path].
   Database(String path,
       [int flags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE]) {
-    Pointer<Pointer<types.Database>> dbOut = allocate();
+    Pointer<Pointer<types.Database>> dbOut = calloc();
     final pathC = Utf8.toUtf8(path);
     final int resultCode =
         bindings.sqlite3_open_v2(pathC, dbOut, flags, nullptr);
     _database = dbOut.value;
-    free(dbOut);
-    free(pathC);
+    calloc.free(dbOut);
+    calloc.free(pathC);
 
     if (resultCode == Errors.SQLITE_OK) {
       _open = true;
@@ -65,13 +67,13 @@
 
   /// Execute a query, discarding any returned rows.
   void execute(String query) {
-    Pointer<Pointer<Statement>> statementOut = allocate();
+    Pointer<Pointer<Statement>> statementOut = calloc();
     Pointer<Utf8> queryC = Utf8.toUtf8(query);
     int resultCode = bindings.sqlite3_prepare_v2(
         _database, queryC, -1, statementOut, nullptr);
     Pointer<Statement> statement = statementOut.value;
-    free(statementOut);
-    free(queryC);
+    calloc.free(statementOut);
+    calloc.free(queryC);
 
     while (resultCode == Errors.SQLITE_ROW || resultCode == Errors.SQLITE_OK) {
       resultCode = bindings.sqlite3_step(statement);
@@ -84,13 +86,13 @@
 
   /// Evaluate a query and return the resulting rows as an iterable.
   Result query(String query) {
-    Pointer<Pointer<Statement>> statementOut = allocate();
+    Pointer<Pointer<Statement>> statementOut = calloc();
     Pointer<Utf8> queryC = Utf8.toUtf8(query);
     int resultCode = bindings.sqlite3_prepare_v2(
         _database, queryC, -1, statementOut, nullptr);
     Pointer<Statement> statement = statementOut.value;
-    free(statementOut);
-    free(queryC);
+    calloc.free(statementOut);
+    calloc.free(queryC);
 
     if (resultCode != Errors.SQLITE_OK) {
       bindings.sqlite3_finalize(statement);
@@ -101,7 +103,7 @@
     int columnCount = bindings.sqlite3_column_count(statement);
     for (int i = 0; i < columnCount; i++) {
       String columnName =
-          bindings.sqlite3_column_name(statement, i).ref.toString();
+          Utf8.fromUtf8(bindings.sqlite3_column_name(statement, i));
       columnIndices[columnName] = i;
     }
 
@@ -109,12 +111,12 @@
   }
 
   SQLiteException _loadError([int errorCode]) {
-    String errorMessage = bindings.sqlite3_errmsg(_database).ref.toString();
+    String errorMessage = Utf8.fromUtf8(bindings.sqlite3_errmsg(_database));
     if (errorCode == null) {
       return SQLiteException(errorMessage);
     }
     String errorCodeExplanation =
-        bindings.sqlite3_errstr(errorCode).ref.toString();
+        Utf8.fromUtf8(bindings.sqlite3_errstr(errorCode));
     return SQLiteException(
         "$errorMessage (Code $errorCode: $errorCodeExplanation)");
   }
@@ -214,10 +216,8 @@
       dynamicType =
           _typeFromCode(bindings.sqlite3_column_type(_statement, columnIndex));
     } else {
-      dynamicType = _typeFromText(bindings
-          .sqlite3_column_decltype(_statement, columnIndex)
-          .ref
-          .toString());
+      dynamicType = _typeFromText(Utf8.fromUtf8(
+          bindings.sqlite3_column_decltype(_statement, columnIndex)));
     }
 
     switch (dynamicType) {
@@ -253,7 +253,7 @@
   /// Reads column [columnIndex] and converts to [Type.Text] if not text.
   String readColumnByIndexAsText(int columnIndex) {
     _checkIsCurrentRow();
-    return bindings.sqlite3_column_text(_statement, columnIndex).ref.toString();
+    return Utf8.fromUtf8(bindings.sqlite3_column_text(_statement, columnIndex));
   }
 
   void _checkIsCurrentRow() {
diff --git a/samples_2/ffi/sqlite/lib/src/ffi/arena.dart b/samples_2/ffi/sqlite/lib/src/ffi/arena.dart
index a26e807..39e3035 100644
--- a/samples_2/ffi/sqlite/lib/src/ffi/arena.dart
+++ b/samples_2/ffi/sqlite/lib/src/ffi/arena.dart
@@ -9,6 +9,8 @@
 
 import 'package:ffi/ffi.dart';
 
+import 'calloc.dart';
+
 /// [Arena] manages allocated C memory.
 ///
 /// Arenas are zoned.
@@ -26,7 +28,7 @@
   /// Frees all memory pointed to by [Pointer]s in this arena.
   void finalize() {
     for (final ptr in _allocations) {
-      free(ptr);
+      calloc.free(ptr);
     }
   }
 
diff --git a/samples_2/ffi/sqlite/lib/src/ffi/calloc.dart b/samples_2/ffi/sqlite/lib/src/ffi/calloc.dart
new file mode 100644
index 0000000..c6be280
--- /dev/null
+++ b/samples_2/ffi/sqlite/lib/src/ffi/calloc.dart
@@ -0,0 +1,111 @@
+// 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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+// @dart=2.9
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart b/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart
index 39653fa..b783ad8 100644
--- a/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart
+++ b/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart
@@ -9,7 +9,7 @@
 
 String _platformPath(String name, {String path}) {
   if (path == null) path = "";
-  if (Platform.isLinux || Platform.isAndroid)
+  if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
diff --git a/samples_2/ffi/sqlite/test/sqlite_test.dart b/samples_2/ffi/sqlite/test/sqlite_test.dart
index f7d3744..dffbe5b 100644
--- a/samples_2/ffi/sqlite/test/sqlite_test.dart
+++ b/samples_2/ffi/sqlite/test/sqlite_test.dart
@@ -171,7 +171,7 @@
   test("Utf8 unit test", () {
     final String test = 'Hasta Mañana';
     final medium = Utf8.toUtf8(test);
-    expect(test, medium.ref.toString());
-    free(medium);
+    expect(test, Utf8.fromUtf8(medium));
+    calloc.free(medium);
   });
 }
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index efa745a..b6091dc 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -48,6 +48,7 @@
 # ........dart2js.dart.snapshot
 # ........dart2native.dart.snapshot (if not on ia32)
 # ........dartanalyzer.dart.snapshot
+# ........dartdev.dart.snapshot
 # ........dartdev.dill
 # ........dartdevc.dart.snapshot
 # ........dartdoc.dart.snapshot
@@ -118,6 +119,10 @@
     "../utils/dartanalyzer:generate_dartanalyzer_snapshot",
   ],
   [
+    "dartdev",
+    "../utils/dartdev:dartdev",
+  ],
+  [
     "dartdoc",
     "../utils/dartdoc",
   ],
@@ -153,62 +158,24 @@
       ] ]
 }
 
-_full_sdk_snapshots = [
-  [
-    "dart2js",
-    "../utils/compiler:dart2js",
-  ],
-  [
-    "dartanalyzer",
-    "../utils/dartanalyzer:generate_dartanalyzer_snapshot",
-  ],
-  [
-    "dartdevc",
-    "../utils/dartdevc",
-  ],
-  [
-    "dartdoc",
-    "../utils/dartdoc",
-  ],
-  [
-    "dartfmt",
-    "../utils/dartfmt",
-  ],
-  [
-    "dds",
-    "../utils/dds:dds",
-  ],
-  [
-    "kernel_worker",
-    "../utils/bazel:kernel_worker",
-  ],
-  [
-    "pub",
-    "../utils/pub",
-  ],
-  [
-    "frontend_server",
-    "../utils/kernel-service:frontend_server",
-  ],
-]
-if (dart_target_arch != "ia32") {
-  _full_sdk_snapshots += [ [
-        "dart2native",
-        "../utils/dart2native:generate_dart2native_snapshot",
-      ] ]
-}
-if (create_kernel_service_snapshot) {
-  _full_sdk_snapshots += [ [
-        "kernel-service",
-        "../utils/kernel-service:kernel-service_snapshot",
-      ] ]
-}
-if (dart_target_arch != "arm") {
-  _full_sdk_snapshots += [ [
-        "analysis_server",
-        "../utils/analysis_server",
-      ] ]
-}
+_full_sdk_snapshots = _platform_sdk_snapshots + [
+                        [
+                          "dart2js",
+                          "../utils/compiler:dart2js",
+                        ],
+                        [
+                          "dartdevc",
+                          "../utils/dartdevc",
+                        ],
+                        [
+                          "kernel_worker",
+                          "../utils/bazel:kernel_worker",
+                        ],
+                        [
+                          "frontend_server",
+                          "../utils/kernel-service:frontend_server",
+                        ],
+                      ]
 
 # Libraries that go under lib/
 _full_sdk_libraries = [
diff --git a/sdk/lib/_http/http_parser.dart b/sdk/lib/_http/http_parser.dart
index 23e4a2b..93b6518 100644
--- a/sdk/lib/_http/http_parser.dart
+++ b/sdk/lib/_http/http_parser.dart
@@ -684,11 +684,16 @@
           } else {
             String headerField = new String.fromCharCodes(_headerField);
             String headerValue = new String.fromCharCodes(_headerValue);
+            const errorIfBothText = "Both Content-Length and Transfer-Encoding "
+                "are specified, at most one is allowed";
             if (headerField == HttpHeaders.contentLengthHeader) {
               // Content Length header should not have more than one occurance
               // or coexist with Transfer Encoding header.
-              if (_contentLength || _transferEncoding) {
-                _statusCode = HttpStatus.badRequest;
+              if (_contentLength) {
+                throw HttpException("The Content-Length header occurred "
+                    "more than once, at most one is allowed.");
+              } else if (_transferEncoding) {
+                throw HttpException(errorIfBothText);
               }
               _contentLength = true;
             } else if (headerField == HttpHeaders.transferEncodingHeader) {
@@ -697,7 +702,7 @@
                 _chunked = true;
               }
               if (_contentLength) {
-                _statusCode = HttpStatus.badRequest;
+                throw HttpException(errorIfBothText);
               }
             }
             var headers = _headers!;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
index b80c74e..2a991c9 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
@@ -33,7 +33,7 @@
       f = value;
     } else if (value is Future) {
       f = _Future();
-      _Future._chainForeignFuture(value, f);
+      f._chainForeignFuture(value);
     } else {
       f = _Future.value(value);
     }
@@ -100,7 +100,7 @@
           if (value is _Future) {
             _Future._chainCoreFuture(value, asyncFuture);
           } else {
-            _Future._chainForeignFuture(value, asyncFuture);
+            asyncFuture._chainForeignFuture(value);
           }
         } else if (isRunningAsEvent) {
           asyncFuture._completeWithValue(JS('', '#', value));
@@ -356,7 +356,7 @@
       f = value;
     } else if (value is Future) {
       f = _Future();
-      _Future._chainForeignFuture(value, f);
+      f._chainForeignFuture(value);
     } else {
       f = _Future.value(value);
     }
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
index d862534..ca02b18 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
@@ -155,11 +155,12 @@
 
     // FutureOr<Never> --> Future<Never>
     if (_equalType(typeArg, Never)) {
-      return JS('!', '#(#)', getGenericClass(Future), typeArg);
+      return JS('!', '#(#)', getGenericClassStatic<Future>(), typeArg);
     }
     // FutureOr<Null> --> Future<Null>?
     if (_equalType(typeArg, Null)) {
-      return nullable(JS('!', '#(#)', getGenericClass(Future), typeArg));
+      return nullable(
+          JS('!', '#(#)', getGenericClassStatic<Future>(), typeArg));
     }
     // Otherwise, create the FutureOr<T> type as a normal generic type.
     var genericType = JS('!', '#(#)', genericFutureOrType, typeArg);
@@ -171,7 +172,8 @@
     // Add FutureOr specific is and as methods.
     is_FutureOr(obj) =>
         JS<bool>('!', '#.is(#)', typeArg, obj) ||
-        JS<bool>('!', '#(#).is(#)', getGenericClass(Future), typeArg, obj);
+        JS<bool>(
+            '!', '#(#).is(#)', getGenericClassStatic<Future>(), typeArg, obj);
     JS('!', '#.is = #', genericType, is_FutureOr);
 
     as_FutureOr(obj) {
@@ -183,10 +185,12 @@
       }
 
       if (JS<bool>('!', '#.is(#)', typeArg, obj) ||
-          JS<bool>('!', '#(#).is(#)', getGenericClass(Future), typeArg, obj)) {
+          JS<bool>('!', '#(#).is(#)', getGenericClassStatic<Future>(), typeArg,
+              obj)) {
         return obj;
       }
-      return cast(obj, JS('!', '#(#)', getGenericClass(FutureOr), typeArg));
+      return cast(
+          obj, JS('!', '#(#)', getGenericClassStatic<FutureOr>(), typeArg));
     }
 
     JS('!', '#.as = #', genericType, as_FutureOr);
@@ -252,6 +256,19 @@
 
 getGenericClass(type) => safeGetOwnProperty(type, _originalDeclaration);
 
+/// Extracts the type argument as the accessor for the JS class.
+///
+/// Should be used in place of [getGenericClass] when we know the class we want
+/// statically.
+///
+/// This value is extracted and inlined by the compiler without any runtime
+/// operations. The implementation here is only provided as a theoretical fall
+/// back and shouldn't actually be run.
+///
+/// For example `getGenericClassStatic<FutureOr>` emits `async.FutureOr$`
+/// directly.
+external getGenericClassStatic<T>();
+
 // TODO(markzipan): Make this non-nullable if we can ensure this returns
 // an empty list or if null and the empty list are semantically the same.
 List? getGenericArgs(type) =>
@@ -504,6 +521,26 @@
   _applyExtension(jsType, dartExtType);
 }
 
+/// Apply a previously registered extension for testing purposes.
+///
+/// This method's only purpose is to aid in testing native classes. Most native
+/// tests define JavaScript classes in user code (e.g. in an eval string). The
+/// dartdevc compiler properly calls `registerExtension` when processing the
+/// native class declarations in Dart, but at that point in time the JavaScript
+/// counterpart is not defined.
+///
+/// This method is used to lookup those registrations and reapply the extension
+/// after the JavaScript declarations are added.
+///
+/// An alternative to this would be to invest in a better test infrastructure
+/// that would let us define the JavaScript code prior to loading the compiled
+/// module.
+applyExtensionForTesting(name) {
+  var dartExtType = JS('', '#.get(#)', _extensionMap, name);
+  var jsType = JS('', '#[#]', global_, name);
+  _applyExtension(jsType, dartExtType);
+}
+
 ///
 /// Mark a concrete type as implementing extension methods.
 /// For example: `class MyIter implements Iterable`.
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
index fd80d9c..36ebdf8 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
@@ -17,6 +17,11 @@
   throw UnimplementedError(message);
 }
 
+throwDeferredIsLoadedError(
+    @notNull String enclosingLibrary, @notNull String importPrefix) {
+  throw DeferredNotLoadedError(enclosingLibrary, importPrefix);
+}
+
 // TODO(nshahan) Cleanup embeded strings and extract file location at runtime
 // from the stacktrace.
 assertFailed(String? message,
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 4a224cd..174b2ff 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
@@ -665,7 +665,7 @@
   let value = map.get($elementType);
   if (value) return value;
 
-  ${getGenericClass(JSArray)}($elementType).unmodifiable($elements);
+  ${getGenericClassStatic<JSArray>()}($elementType).unmodifiable($elements);
   map.set($elementType, elements);
   return elements;
 })()''');
@@ -759,11 +759,34 @@
   return name;
 }
 
+/// A map from libraries to a set of import prefixes that have been loaded.
+///
+/// Used to validate deferred library conventions.
+final deferredImports = JS<Object>('!', 'new Map()');
+
 /// Emulates the implicit "loadLibrary" function provided by a deferred library.
 ///
-/// Libraries are not actually deferred in DDC, so this just returns a future
-/// that completes immediately.
-Future loadLibrary() => Future.value();
+/// Libraries are not actually deferred in DDC, so this just records the import
+/// for runtime validation, then returns a future that completes immediately.
+Future loadLibrary(
+    @notNull String enclosingLibrary, @notNull String importPrefix) {
+  var result = JS('', '#.get(#)', deferredImports, enclosingLibrary);
+  if (JS<bool>('', '# === void 0', result)) {
+    JS('', '#.set(#, # = new Set())', deferredImports, enclosingLibrary,
+        result);
+  }
+  JS('', '#.add(#)', result, importPrefix);
+  return Future.value();
+}
+
+void checkDeferredIsLoaded(
+    @notNull String enclosingLibrary, @notNull String importPrefix) {
+  var loaded = JS('', '#.get(#)', deferredImports, enclosingLibrary);
+  if (JS<bool>('', '# === void 0', loaded) ||
+      JS<bool>('', '!#.has(#)', loaded, importPrefix)) {
+    throwDeferredIsLoadedError(enclosingLibrary, importPrefix);
+  }
+}
 
 /// Defines lazy statics.
 ///
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 21c6f31..e4afbf4 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
@@ -18,6 +18,7 @@
         BooleanConversionAssertionError,
         CastErrorImpl,
         DartIterator,
+        DeferredNotLoadedError,
         TypeErrorImpl,
         JsLinkedHashMap,
         ImmutableMap,
@@ -204,6 +205,7 @@
   _cacheMaps.clear();
   JS('', '#.clear()', _nullComparisonSet);
   JS('', '#.clear()', constantMaps);
+  JS('', '#.clear()', deferredImports);
 }
 
 /// Marks enqueuing an async operation.
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 f0fa4f0..7874940 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
@@ -240,18 +240,13 @@
   Object rawJSTypeForCheck() => _getRawJSType() ?? jsobject;
 
   @notNull
-  bool isRawJSType(obj) {
-    var raw = _getRawJSType();
-    if (raw != null) return JS('!', '# instanceof #', obj, raw);
-    return _isJsObject(obj);
-  }
-
-  @notNull
   @JSExportName('is')
-  bool is_T(obj) => isRawJSType(obj) || instanceOf(obj, this);
+  bool is_T(obj) =>
+      obj != null &&
+      (_isJsObject(obj) || isSubtypeOf(getReifiedType(obj), this));
 
   @JSExportName('as')
-  as_T(obj) => obj == null || is_T(obj) ? obj : castError(obj, this);
+  as_T(obj) => is_T(obj) ? obj : castError(obj, this);
 }
 
 /// An anonymous JS type
@@ -263,10 +258,12 @@
   toString() => _dartName;
 
   @JSExportName('is')
-  bool is_T(obj) => _isJsObject(obj) || instanceOf(obj, this);
+  bool is_T(obj) =>
+      obj != null &&
+      (_isJsObject(obj) || isSubtypeOf(getReifiedType(obj), this));
 
   @JSExportName('as')
-  as_T(obj) => obj == null || _isJsObject(obj) ? obj : cast(obj, this);
+  as_T(obj) => is_T(obj) ? obj : castError(obj, this);
 }
 
 void _warn(arg) {
@@ -1209,7 +1206,7 @@
     let args = ${getGenericArgs(type)};
     if (args == null) return name;
 
-    if (${getGenericClass(type)} == ${getGenericClass(JSArray)}) name = 'List';
+    if (${getGenericClass(type)} == ${getGenericClassStatic<JSArray>()}) name = 'List';
 
     let result = name;
     result += '<';
@@ -1394,7 +1391,7 @@
 bool _isFutureOr(type) {
   var genericClass = getGenericClass(type);
   return JS<bool>('!', '# && # === #', genericClass, genericClass,
-      getGenericClass(FutureOr));
+      getGenericClassStatic<FutureOr>());
 }
 
 @notNull
@@ -1479,7 +1476,7 @@
 
     // given t1 is Future<A> | A, then:
     // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
-    let t1Future = ${getGenericClass(Future)}(t1TypeArg);
+    let t1Future = ${getGenericClassStatic<Future>()}(t1TypeArg);
     // Known to handle the case FutureOr<Null> <: Future<Null>.
     return $_isSubtype(t1Future, $t2, $strictMode) &&
         $_isSubtype(t1TypeArg, $t2, $strictMode);
@@ -1496,7 +1493,7 @@
     // given t2 is Future<A> | A, then:
     // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
     let t2TypeArg = ${getGenericArgs(t2)}[0];
-    let t2Future = ${getGenericClass(Future)}(t2TypeArg);
+    let t2Future = ${getGenericClassStatic<Future>()}(t2TypeArg);
     // TODO(nshahan) Need to handle type variables on the left.
     // https://github.com/dart-lang/sdk/issues/38816
     return $_isSubtype($t1, t2Future, $strictMode) || $_isSubtype($t1, t2TypeArg, $strictMode);
@@ -1897,7 +1894,7 @@
       // - And `P` is a subtype match for `Q` with respect to `L` under
       //   constraints `C1`.
       var subtypeFuture =
-          JS<Object>('!', '#(#)', getGenericClass(Future), subtypeArg);
+          JS<Object>('!', '#(#)', getGenericClassStatic<Future>(), subtypeArg);
       return _isSubtypeMatch(subtypeFuture, supertype) &&
           _isSubtypeMatch(subtypeArg!, supertype);
     }
@@ -1912,8 +1909,8 @@
       //   - And `P` is a subtype match for `Q` with respect to `L` under
       //     constraints `C`
       var supertypeArg = getGenericArgs(supertype)![0];
-      var supertypeFuture =
-          JS<Object>('!', '#(#)', getGenericClass(Future), supertypeArg);
+      var supertypeFuture = JS<Object>(
+          '!', '#(#)', getGenericClassStatic<Future>(), supertypeArg);
       return _isSubtypeMatch(subtype, supertypeFuture) ||
           _isSubtypeMatch(subtype, supertypeArg);
     }
diff --git a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
index 72fff96..71c559c 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
@@ -239,3 +239,8 @@
 findConstructorForNativeSubclassType(Type? type, String name) {}
 getNativeInterceptor(object) {}
 setDispatchProperty(object, value) {}
+
+// Added to allow dart2js and dartdevc to share tests
+// TODO(sigmund): revisit whether this method is still needed after reoganizing
+// all web tests.
+findInterceptorForType(Type? type) {}
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_array.dart b/sdk/lib/_internal/js_dev_runtime/private/js_array.dart
index 3d5e3d7..a6522bd 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_array.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_array.dart
@@ -598,7 +598,7 @@
   }
 
   Type get runtimeType =>
-      dart.wrapType(JS('', '#(#)', dart.getGenericClass(List), E));
+      dart.wrapType(JS('', '#(#)', dart.getGenericClassStatic<List>(), E));
 
   Iterable<E> followedBy(Iterable<E> other) =>
       FollowedByIterable<E>.firstEfficient(this, other);
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
index c49608a..08a1e1e 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -725,6 +725,17 @@
   String toString() => "RuntimeError: $message";
 }
 
+class DeferredNotLoadedError extends Error implements NoSuchMethodError {
+  String enclosingLibrary;
+  String importPrefix;
+
+  DeferredNotLoadedError(this.enclosingLibrary, this.importPrefix);
+
+  String toString() {
+    return 'Deferred import $importPrefix (from $enclosingLibrary) was not loaded.';
+  }
+}
+
 /// Error thrown by DDC when an `assert()` fails (with or without a message).
 class AssertionErrorImpl extends AssertionError {
   final String? _fileUri;
@@ -787,6 +798,11 @@
   dart.applyExtension(name, nativeObject);
 }
 
+/// Hook to apply extensions on native JS classes defined in a native unit test.
+void applyTestExtensions(List<String> names) {
+  names.forEach(dart.applyExtensionForTesting);
+}
+
 /// Used internally by DDC to map ES6 symbols to Dart.
 class PrivateSymbol implements Symbol {
   // TODO(jmesserly): could also get this off the native symbol instead of
@@ -813,3 +829,15 @@
   // TODO(jmesserly): is this equivalent to _nativeSymbol toString?
   toString() => 'Symbol("$_name")';
 }
+
+/// Asserts that if [value] is a function, it is a JavaScript function or has
+/// been wrapped by [allowInterop].
+///
+/// This function does not recurse if [value] is a collection.
+void assertInterop(Object? value) {
+  if (value is Function) dart.assertInterop(value);
+}
+
+/// Like [assertInterop], except iterates over a list of arguments
+/// non-recursively.
+void assertInteropArgs(List<Object?> args) => args.forEach(assertInterop);
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_number.dart b/sdk/lib/_internal/js_dev_runtime/private/js_number.dart
index fcaa2cd..60b9246 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_number.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_number.dart
@@ -285,9 +285,9 @@
     if (result == 0) return (0 as JSNumber); // Make sure we don't return -0.0.
     if (result > 0) return result;
     if (JS<JSNumber>('!', '#', other) < 0) {
-      return result - JS<JSNumber>('!', '#', other);
+      return JS<JSNumber>('!', '# - #', result, other);
     } else {
-      return result + JS<JSNumber>('!', '#', other);
+      return JS<JSNumber>('!', '# + #', result, other);
     }
   }
 
@@ -418,7 +418,7 @@
 
   @notNull
   int get bitLength {
-    int nonneg = this < 0 ? -this - 1 : this;
+    int nonneg = JS<int>('!', '#', this < 0 ? -this - 1 : this);
     int wordBits = 32;
     while (nonneg >= 0x100000000) {
       nonneg = nonneg ~/ 0x100000000;
@@ -566,6 +566,7 @@
   // Returns gcd of abs(this) and abs(other).
   @notNull
   int gcd(@nullCheck int other) {
+    if (this is! int) throwArgumentErrorValue(this);
     int x = this.abs();
     int y = other.abs();
     if (x == 0) return y;
diff --git a/sdk/lib/_internal/js_runtime/lib/js_array.dart b/sdk/lib/_internal/js_runtime/lib/js_array.dart
index 93bd80c..ffefd1f 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_array.dart
@@ -282,15 +282,27 @@
   }
 
   void addAll(Iterable<E> collection) {
-    int i = this.length;
     checkGrowable('addAll');
+    if (collection is JSArray) {
+      _addAllFromArray(JS('', '#', collection));
+      return;
+    }
+    int i = this.length;
     for (E e in collection) {
-      assert(
-          i++ == this.length || (throw new ConcurrentModificationError(this)));
+      assert(i++ == this.length || (throw ConcurrentModificationError(this)));
       JS('void', r'#.push(#)', this, e);
     }
   }
 
+  void _addAllFromArray(JSArray array) {
+    int len = array.length;
+    if (len == 0) return;
+    if (identical(this, array)) throw ConcurrentModificationError(this);
+    for (int i = 0; i < len; i++) {
+      JS('', '#.push(#[#])', this, array, i);
+    }
+  }
+
   void clear() {
     length = 0;
   }
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 3b1cca4..1bef6a1 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -1347,7 +1347,7 @@
     // get the text "[object Object]". The shortest way to get that
     // string is using "String({})".
     // See: http://code.google.com/p/v8/issues/detail?id=2519.
-    message = JS('String', r"#.replace(String({}), '$receiver$')", message);
+    message = JS('String', r'#.replace(String({}), "$receiver$")', message);
 
     // Since we want to create a new regular expression from an unknown string,
     // we must escape all regular expression syntax.
@@ -1374,14 +1374,14 @@
     // JavaScript, "." does not match newlines.
     String pattern = JS(
         'String',
-        r"#.replace(new RegExp('\\\\\\$arguments\\\\\\$', 'g'), "
-            r"'((?:x|[^x])*)')"
-            r".replace(new RegExp('\\\\\\$argumentsExpr\\\\\\$', 'g'),  "
-            r"'((?:x|[^x])*)')"
-            r".replace(new RegExp('\\\\\\$expr\\\\\\$', 'g'),  '((?:x|[^x])*)')"
-            r".replace(new RegExp('\\\\\\$method\\\\\\$', 'g'),  '((?:x|[^x])*)')"
-            r".replace(new RegExp('\\\\\\$receiver\\\\\\$', 'g'),  "
-            r"'((?:x|[^x])*)')",
+        r'#.replace(new RegExp("\\\\\\$arguments\\\\\\$", "g"), '
+            r'"((?:x|[^x])*)")'
+            r'.replace(new RegExp("\\\\\\$argumentsExpr\\\\\\$", "g"),  '
+            r'"((?:x|[^x])*)")'
+            r'.replace(new RegExp("\\\\\\$expr\\\\\\$", "g"),  "((?:x|[^x])*)")'
+            r'.replace(new RegExp("\\\\\\$method\\\\\\$", "g"),  "((?:x|[^x])*)")'
+            r'.replace(new RegExp("\\\\\\$receiver\\\\\\$", "g"),  '
+            r'"((?:x|[^x])*)")',
         message);
 
     return new TypeErrorDecoder(
@@ -1436,7 +1436,7 @@
     // "(.*)\\.(.*) is not a function"
 
     var function = JS('', r"""function($expr$) {
-  var $argumentsExpr$ = '$arguments$';
+  var $argumentsExpr$ = "$arguments$";
   try {
     $expr$.$method$($argumentsExpr$);
   } catch (e) {
@@ -1451,7 +1451,7 @@
   static String provokeCallErrorOnNull() {
     // See [provokeCallErrorOn] for a detailed explanation.
     var function = JS('', r"""function() {
-  var $argumentsExpr$ = '$arguments$';
+  var $argumentsExpr$ = "$arguments$";
   try {
     null.$method$($argumentsExpr$);
   } catch (e) {
@@ -1466,7 +1466,7 @@
   static String provokeCallErrorOnUndefined() {
     // See [provokeCallErrorOn] for a detailed explanation.
     var function = JS('', r"""function() {
-  var $argumentsExpr$ = '$arguments$';
+  var $argumentsExpr$ = "$arguments$";
   try {
     (void 0).$method$($argumentsExpr$);
   } catch (e) {
@@ -1774,7 +1774,7 @@
 }
 
 int objectHashCode(var object) {
-  if (object == null || JS('bool', "typeof # != 'object'", object)) {
+  if (object == null || JS('bool', 'typeof # != "object"', object)) {
     return object.hashCode;
   } else {
     return Primitives.objectHashCode(object);
@@ -2960,24 +2960,20 @@
   return completer.future;
 }
 
-class MainError extends Error implements NoSuchMethodError {
-  final String _message;
-
-  MainError(this._message);
-
-  String toString() => 'NoSuchMethodError: $_message';
-}
-
-void missingMain() {
-  throw new MainError("No top-level function named 'main'.");
-}
-
-void badMain() {
-  throw new MainError("'main' is not a function.");
-}
-
-void mainHasTooManyParameters() {
-  throw new MainError("'main' expects too many parameters.");
+/// Converts a raw JavaScript array into a `List<String>`.
+/// Called from generated code.
+List<String> convertMainArgumentList(Object? args) {
+  List<String> result = [];
+  if (args == null) return result;
+  if (args is JSArray) {
+    for (int i = 0; i < args.length; i++) {
+      JS('', '#.push(String(#[#]))', result, args, i);
+    }
+    return result;
+  }
+  // Single non-Array element. Convert to a String.
+  JS('', '#.push(String(#))', result, args);
+  return result;
 }
 
 class _AssertionError extends AssertionError {
@@ -3003,10 +2999,14 @@
 // This is currently a no-op in dart2js.
 void registerGlobalObject(object) {}
 
-// Hook to register new browser classes.
+// Hook to register new browser classes in dartdevc.
 // This is currently a no-op in dart2js.
 void applyExtension(name, nativeObject) {}
 
+// Hook to upgrade user native-type classes in dartdevc.
+// This is currently a no-op in dart2js, but used for native tests.
+void applyTestExtensions(List<String> names) {}
+
 // See tests/dart2js_2/platform_environment_variable1_test.dart
 const String testPlatformEnvironmentVariableValue = String.fromEnvironment(
     'dart2js.test.platform.environment.variable',
@@ -3027,3 +3027,26 @@
 
 /// Called by generated code to throw a LateInitializationError.
 void throwLateInitializationError(String name) => throw LateError(name);
+
+/// Checks that [f] is a function that supports interop.
+@pragma('dart2js:tryInline')
+bool isJSFunction(Function f) => JS('bool', 'typeof(#) == "function"', f);
+
+/// Asserts that if [value] is a function, it is a JavaScript function or has
+/// been wrapped by [allowInterop].
+///
+/// This function does not recurse if [value] is a collection.
+void assertInterop(Object? value) {
+  assert(value is! Function || isJSFunction(value),
+      'Dart function requires `allowInterop` to be passed to JavaScript.');
+}
+
+/// Like [assertInterop], except iterates over a list of arguments
+/// non-recursively.
+///
+/// This function intentionally avoids using [assertInterop] so that this
+/// function can become a no-op if assertions are disabled.
+void assertInteropArgs(List<Object?> args) {
+  assert(args.every((arg) => arg is! Function || isJSFunction(arg)),
+      'Dart function requires `allowInterop` to be passed to JavaScript.');
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_number.dart b/sdk/lib/_internal/js_runtime/lib/js_number.dart
index 489da64..f32f0fa 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_number.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_number.dart
@@ -310,9 +310,9 @@
     if (result == 0) return JS('num', '0'); // Make sure we don't return -0.0.
     if (result > 0) return result;
     if (JS('num', '#', other) < 0) {
-      return result - JS<JSNumber>('JSNumber', '#', other);
+      return JS<JSNumber>('JSNumber', '# - #', result, other);
     } else {
-      return result + JS<JSNumber>('JSNumber', '#', other);
+      return JS<JSNumber>('JSNumber', '# + #', result, other);
     }
   }
 
@@ -486,7 +486,7 @@
   }
 
   int get bitLength {
-    int nonneg = (this < 0 ? -this - 1 : this) as int;
+    int nonneg = JS<int>('int', '#', this < 0 ? -this - 1 : this);
     int wordBits = 32;
     while (nonneg >= 0x100000000) {
       nonneg = nonneg ~/ 0x100000000;
diff --git a/sdk/lib/_internal/js_runtime/lib/js_patch.dart b/sdk/lib/_internal/js_runtime/lib/js_patch.dart
index 1ff2e55..98345e3 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_patch.dart
@@ -8,7 +8,8 @@
 
 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
 import 'dart:_interceptors' show DART_CLOSURE_PROPERTY_NAME;
-import 'dart:_js_helper' show patch, Primitives, getIsolateAffinityTag;
+import 'dart:_js_helper'
+    show patch, Primitives, getIsolateAffinityTag, isJSFunction;
 import 'dart:_js' show isBrowserObject, convertFromBrowserObject;
 
 @patch
@@ -547,7 +548,7 @@
 
 @patch
 F allowInterop<F extends Function>(F f) {
-  if (JS('bool', 'typeof(#) == "function"', f)) {
+  if (isJSFunction(f)) {
     // Already supports interop, just use the existing function.
     return f;
   } else {
@@ -557,7 +558,7 @@
 
 @patch
 Function allowInteropCaptureThis(Function f) {
-  if (JS('bool', 'typeof(#) == "function"', f)) {
+  if (isJSFunction(f)) {
     // Behavior when the function is already a JS function is unspecified.
     throw ArgumentError(
         "Function is already a JS function so cannot capture this.");
diff --git a/sdk/lib/_internal/js_runtime/lib/preambles/d8.js b/sdk/lib/_internal/js_runtime/lib/preambles/d8.js
index 0174d95..6604c8a 100644
--- a/sdk/lib/_internal/js_runtime/lib/preambles/d8.js
+++ b/sdk/lib/_internal/js_runtime/lib/preambles/d8.js
@@ -10,7 +10,7 @@
 var self = this;
 if (typeof global != "undefined") self = global;  // Node.js.
 
-(function(self) {
+(function(self, scriptArguments) {
   // Using strict mode to avoid accidentally defining global variables.
   "use strict"; // Should be first statement of this function.
 
@@ -270,9 +270,9 @@
   // Global properties. "self" refers to the global object, so adding a
   // property to "self" defines a global variable.
   self.self = self;
-  self.dartMainRunner = function(main, args) {
+  self.dartMainRunner = function(main, ignored_args) {
     // Initialize.
-    var action = function() { main(args); }
+    var action = function() { main(scriptArguments, null); }
     eventLoop(action);
   };
   self.setTimeout = addTimer;
@@ -345,4 +345,4 @@
   // so pretend they don't exist.
   // TODO(30217): Try to use D8's worker.
   delete self.Worker;
-})(self);
+})(self, arguments);
diff --git a/sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js b/sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js
index a6b41c4..48f60cd 100644
--- a/sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js
+++ b/sdk/lib/_internal/js_runtime/lib/preambles/jsshell.js
@@ -4,7 +4,7 @@
 
 // Javascript preamble, that lets the output of dart2js run on JSShell.
 
-(function(self) {
+(function(self, scriptArguments) {
   // Using strict mode to avoid accidentally defining global variables.
   "use strict"; // Should be first statement of this function.
 
@@ -262,9 +262,9 @@
     }
   }
 
-  self.dartMainRunner = function(main, args) {
+  self.dartMainRunner = function(main, ignored_args) {
     // Initialize.
-    var action = function() { main(args); }
+    var action = function() { main(scriptArguments, null); }
     eventLoop(action);
   };
   self.setTimeout = addTimer;
@@ -329,7 +329,7 @@
       array[i] = Math.random() * 256;
     }
   }};
-})(this)
+})(this, typeof scriptArgs == "undefined" ? [] : scriptArgs)
 
 var getKeys = function(obj){
    var keys = [];
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index eb87192..84d68ad 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -64,10 +64,7 @@
       maturity: Maturity.UNSTABLE,
       dart2jsPatchPath: "_internal/js_runtime/lib/developer_patch.dart"),
   "ffi": const LibraryInfo("ffi/ffi.dart",
-      categories: "Server",
-      // TODO(dacoharkes): Update maturity when we release dart:ffi.
-      // https://github.com/dart-lang/sdk/issues/34452
-      maturity: Maturity.EXPERIMENTAL),
+      categories: "Server", maturity: Maturity.STABLE),
   "html": const LibraryInfo("html/dart2js/html_dart2js.dart",
       categories: "Client",
       maturity: Maturity.WEB_STABLE,
diff --git a/sdk/lib/_internal/vm/bin/common_patch.dart b/sdk/lib/_internal/vm/bin/common_patch.dart
index cd9f149..f788ec7 100644
--- a/sdk/lib/_internal/vm/bin/common_patch.dart
+++ b/sdk/lib/_internal/vm/bin/common_patch.dart
@@ -21,7 +21,7 @@
         Zone,
         scheduleMicrotask;
 
-import "dart:collection" show HashMap;
+import "dart:collection" show HashMap, Queue;
 
 import "dart:convert" show Encoding, utf8;
 
diff --git a/sdk/lib/_internal/vm/bin/process_patch.dart b/sdk/lib/_internal/vm/bin/process_patch.dart
index 97426b8..6a158e7 100644
--- a/sdk/lib/_internal/vm/bin/process_patch.dart
+++ b/sdk/lib/_internal/vm/bin/process_patch.dart
@@ -387,6 +387,7 @@
 
   Future<Process> _start() {
     var completer = new Completer<Process>();
+    var stackTrace = StackTrace.current;
     if (_modeIsAttached(_mode)) {
       _exitCode = new Completer<int>();
     }
@@ -407,8 +408,10 @@
           _modeIsAttached(_mode) ? _exitHandler._nativeSocket : null,
           status);
       if (!success) {
-        completer.completeError(new ProcessException(
-            _path, _arguments, status._errorMessage!, status._errorCode!));
+        completer.completeError(
+            new ProcessException(
+                _path, _arguments, status._errorMessage!, status._errorCode!),
+            stackTrace);
         return;
       }
 
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index 0cb43ee..fb9e7a9 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -491,21 +491,32 @@
   // a HttpServer, a WebSocket connection, a process pipe, etc.
   Object? owner;
 
-  static Future<List<InternetAddress>> lookup(String host,
+  static Future<List<_InternetAddress>> lookup(String host,
       {InternetAddressType type: InternetAddressType.any}) {
     return _IOService._dispatch(_IOService.socketLookup, [host, type._value])
         .then((response) {
       if (isErrorResponse(response)) {
         throw createError(response, "Failed host lookup: '$host'");
-      } else {
-        return response.skip(1).map<InternetAddress>((result) {
-          var type = InternetAddressType._from(result[0]);
-          return _InternetAddress(type, result[1], host, result[2], result[3]);
-        }).toList();
       }
+      return [
+        for (var result in response.skip(1))
+          _InternetAddress(InternetAddressType._from(result[0]), result[1],
+              host, result[2], result[3])
+      ];
     });
   }
 
+  static Stream<List<_InternetAddress>> lookupAsStream(String host,
+      {InternetAddressType type: InternetAddressType.any}) {
+    final controller = StreamController<List<_InternetAddress>>();
+    controller.onListen = () {
+      lookup(host, type: type).then((list) {
+        controller.add(list);
+      }, onError: controller.addError).whenComplete(controller.close);
+    };
+    return controller.stream;
+  }
+
   static Future<InternetAddress> reverseLookup(InternetAddress addr) {
     return _IOService._dispatch(_IOService.socketReverseLookup,
         [(addr as _InternetAddress)._in_addr]).then((response) {
@@ -572,6 +583,69 @@
         (char == '8' || char == '9' || char == 'a' || char == 'b');
   }
 
+  /// Explicitly makes two separate OS lookup requests: first for IPv4, then
+  /// after short delay for IPv6.
+  /// This avoids making single OS lookup request that internally does both IPv4
+  /// and IPv6 together, which on iOS sometimes seems to be taking unreasonably
+  /// long because of slow IPv6 lookup even though IPv4 lookup is fast.
+  static Stream<List<_InternetAddress>> staggeredLookup(String host) {
+    final controller = StreamController<List<_InternetAddress>>(sync: true);
+
+    controller.onListen = () {
+      // Completed when there are no further addresses, or when the returned
+      // stream is canceled,
+      // The latter signals that no further addresses are needed.
+      // When both completers are completed, one way or another, the stream is
+      // closed.
+      final ipv4Completer = Completer<void>();
+      final ipv6Completer = Completer<void>();
+
+      void lookupAddresses(InternetAddressType type, Completer<void> done) {
+        lookup(host, type: type).then((addresses) {
+          if (done.isCompleted) {
+            // By the time lookup is done, [connectNext] might have
+            // been able to connect to one of the resolved addresses.
+            return;
+          }
+          controller.add(addresses);
+        }, onError: (e, st) {
+          if (done.isCompleted) {
+            // By the time lookup is done, [connectNext] might have
+            // been able to connect to one of the resolved addresses.
+            return;
+          }
+          controller.addError(e, st);
+        }).whenComplete(() {
+          if (!done.isCompleted) {
+            done.complete();
+          }
+        });
+      }
+
+      lookupAddresses(InternetAddressType.IPv4, ipv4Completer);
+      // Give a chance for a connect to an IPv4 address to complete before
+      // starting an IPv6 lookup. If IPv4 connect succeeds before timer goes
+      // off, the timer gets cancelled.
+      const concurrentLookupDelay = Duration(milliseconds: 10);
+      final ipv6LookupDelay = Timer(concurrentLookupDelay, () {
+        lookupAddresses(InternetAddressType.IPv6, ipv6Completer);
+      });
+
+      Future.wait([ipv4Completer.future, ipv6Completer.future])
+          .then((_) => controller.close());
+
+      controller.onCancel = () {
+        // This is invoked when [connectNext] managed to connect to one of the
+        // looked-up addresses at which point we want to stop looking up
+        // the addresses.
+        if (!ipv4Completer.isCompleted) ipv4Completer.complete();
+        if (!ipv6Completer.isCompleted) ipv6Completer.complete();
+        ipv6LookupDelay.cancel();
+      };
+    };
+    return controller.stream;
+  }
+
   static Future<ConnectionTask<_NativeSocket>> startConnect(
       dynamic host, int port, dynamic sourceAddress) {
     // Looks up [sourceAddress] to one or more IP addresses,
@@ -596,176 +670,222 @@
             "Must be a string or native InternetAddress");
       }
     }
-    return new Future.value(host).then<List<InternetAddress>>((host) {
-      if (host is _InternetAddress) return [host];
-      return lookup(host).then((addresses) {
-        if (addresses.isEmpty) {
-          throw createError(null, "Failed host lookup: '$host'");
-        }
-        return addresses;
-      });
-    }).then((addresses) {
-      assert(addresses.isNotEmpty);
-      // Completer for result.
-      var result = new Completer<_NativeSocket>();
-      // Index of next address in [addresses] to try.
-      var index = 0;
-      // Error, set if an error occurs.
-      // Keeps first error if multiple errors occour.
-      var error = null;
-      // Active timers for on-going connection attempts.
-      // Contains all sockets which haven't received and initial
-      // write or error event.
-      var connecting = <_NativeSocket>{};
-      // Timer counting down from the last connection attempt.
-      // Reset when a new connection is attempted,
-      // which happens either when a previous timer runs out,
-      // or when a previous connection attempt fails.
-      Timer? timer;
+    return new Future.value(host).then<ConnectionTask<_NativeSocket>>((host) {
+      if (host is _InternetAddress) {
+        return tryConnectToResolvedAddresses(
+            host, port, source, Stream.value(<_InternetAddress>[host]));
+      }
+      final hostname = host as String;
+      final staggeredLookupOverride = bool.fromEnvironment(
+          "dart.library.io.force_staggered_ipv6_lookup",
+          defaultValue: false);
 
-      // Attempt to connect to the next address in [addresses].
-      //
-      // Called initially, then when either a connection attempt fails,
-      // or an amount of time has passed since the last connection
-      // was attempted.
-      void connectNext() {
-        timer?.cancel();
-        if (index >= addresses.length) {
-          if (connecting.isEmpty) {
-            assert(error != null);
-            assert(!result.isCompleted);
-            result.completeError(error);
-          }
-          return;
-        }
-        final address = addresses[index++] as _InternetAddress;
-        var socket = new _NativeSocket.normal(address);
-        // Will contain values of various types representing the result
-        // of trying to create a connection.
-        // A value of `true` means success, everything else means failure.
-        Object? connectionResult;
-        if (address.type == InternetAddressType.unix) {
-          if (source == null) {
-            connectionResult = socket.nativeCreateUnixDomainConnect(
-                address.address, _Namespace._namespace);
-          } else {
-            assert(source.type == InternetAddressType.unix);
-            connectionResult = socket.nativeCreateUnixDomainBindConnect(
-                address.address, source.address, _Namespace._namespace);
-          }
-          assert(connectionResult == true ||
-              connectionResult is Error ||
-              connectionResult is OSError);
+      // On ios name resolution can get delayed by slow IPv6 name resolution,
+      // so we run IPv4 and IPv6 name resolution in parallel(IPv6 slightly
+      // delayed so if IPv4 is successfully looked up, we don't do IPv6 look up
+      // at all) and grab first successfully resolved name we are able to connect to.
+      final Stream<List<_InternetAddress>> stream =
+          Platform.isIOS || staggeredLookupOverride
+              ? staggeredLookup(hostname)
+              : lookupAsStream(hostname);
+
+      return tryConnectToResolvedAddresses(host, port, source, stream);
+    });
+  }
+
+  static ConnectionTask<_NativeSocket> tryConnectToResolvedAddresses(
+      dynamic host,
+      int port,
+      _InternetAddress? source,
+      Stream<List<_InternetAddress>> addresses) {
+    // Completer for result.
+    final result = new Completer<_NativeSocket>();
+    // Error, set if an error occurs.
+    // Keeps first error if multiple errors occur.
+    var error = null;
+    // Contains all sockets which haven't received an initial
+    // write or error event.
+    final connecting = <_NativeSocket>{};
+    // Timer counting down from the last connection attempt.
+    // Reset when a new connection is attempted,
+    // which happens either when a previous timer runs out,
+    // or when a previous connection attempt fails.
+    Timer? timer;
+    // Addresses arrived from lookup stream, but haven't been tried to connect
+    // to yet due to Timer-based throttling.
+    final pendingLookedUp = Queue<_InternetAddress>();
+
+    // When deciding how to handle errors we need to know whether more
+    // addresses potentially are coming from the lookup stream.
+    bool isLookedUpStreamClosed = false;
+    late StreamSubscription<List<_InternetAddress>> addressesSubscription;
+
+    Object? createConnection(_InternetAddress address, _InternetAddress? source,
+        _NativeSocket socket) {
+      Object? connectionResult;
+      if (address.type == InternetAddressType.unix) {
+        if (source == null) {
+          connectionResult = socket.nativeCreateUnixDomainConnect(
+              address.address, _Namespace._namespace);
         } else {
-          if (source == null) {
-            connectionResult = socket.nativeCreateConnect(
-                address._in_addr, port, address._scope_id);
-          } else {
-            connectionResult = socket.nativeCreateBindConnect(
-                address._in_addr, port, source._in_addr, address._scope_id);
-          }
-          assert(connectionResult == true || connectionResult is OSError);
+          assert(source.type == InternetAddressType.unix);
+          connectionResult = socket.nativeCreateUnixDomainBindConnect(
+              address.address, source.address, _Namespace._namespace);
         }
-        if (connectionResult != true) {
-          // connectionResult was not a success.
-          if (connectionResult is OSError) {
-            int errorCode = connectionResult.errorCode;
-            if (source != null &&
-                errorCode != null &&
-                socket.isBindError(errorCode)) {
-              error = createError(connectionResult, "Bind failed", source);
-            } else {
-              error = createError(
-                  connectionResult, "Connection failed", address, port);
-            }
-          } else if (connectionResult is Error) {
-            error = connectionResult;
-          } else {
-            error = createError(null, "Connection failed", address);
-          }
-          connectNext(); // Try again after failure to connect.
-          return;
+        assert(connectionResult == true ||
+            connectionResult is Error ||
+            connectionResult is OSError);
+      } else {
+        if (source == null) {
+          connectionResult = socket.nativeCreateConnect(
+              address._in_addr, port, address._scope_id);
+        } else {
+          connectionResult = socket.nativeCreateBindConnect(
+              address._in_addr, port, source._in_addr, address._scope_id);
         }
-        // Query the local port for error messages.
-        try {
-          socket.port;
-        } catch (e) {
-          if (error == null) {
-            error = createError(e, "Connection failed", address, port);
-          }
-          connectNext(); // Try again after failure to connect.
-          return;
-        }
+        assert(connectionResult == true || connectionResult is OSError);
+      }
+      return connectionResult;
+    }
 
-        // Try again if no response (failure or success) within a duration.
-        // If this occurs, the socket is still trying to connect, and might
-        // succeed or fail later.
-        var duration =
-            address.isLoopback ? _retryDurationLoopback : _retryDuration;
-        timer = new Timer(duration, connectNext);
+    createConnectionError(Object? connectionResult, _InternetAddress address,
+        int port, _NativeSocket socket) {
+      if (connectionResult is OSError) {
+        final errorCode = connectionResult.errorCode;
+        if (source != null &&
+            errorCode != null &&
+            socket.isBindError(errorCode)) {
+          return createError(connectionResult, "Bind failed", source);
+        } else {
+          return createError(
+              connectionResult, "Connection failed", address, port);
+        }
+      } else if (connectionResult is Error) {
+        return connectionResult;
+      }
+      return createError(null, "Connection failed", address);
+    }
 
-        connecting.add(socket);
-        // Setup handlers for receiving the first write event which
-        // indicate that the socket is fully connected.
-        socket.setHandlers(write: () {
-          // First remote response on connection.
-          // If error, drop the socket and go to the next address.
-          // If success, complete with the socket
-          // and stop all other open connection attempts.
-          connecting.remove(socket);
-          // From 'man 2 connect':
-          // After select(2) indicates writability, use getsockopt(2) to read
-          // the SO_ERROR option at level SOL_SOCKET to determine whether
-          // connect() completed successfully (SO_ERROR is zero) or
-          // unsuccessfully.
-          OSError osError = socket.nativeGetError();
-          if (osError.errorCode != 0) {
-            socket.close();
-            error ??= osError;
-            connectNext(); // Try again after failure to connect.
-            return;
-          }
-          // Connection success!
-          // Stop all other connecting sockets and timers.
-          timer!.cancel();
-          socket.setListening(read: false, write: false);
-          for (var s in connecting) {
-            s.close();
-            s.setHandlers();
-            s.setListening(read: false, write: false);
-          }
-          connecting.clear();
-          result.complete(socket);
-        }, error: (e, st) {
-          connecting.remove(socket);
-          socket.close();
-          socket.setHandlers();
-          socket.setListening(read: false, write: false);
-          // Keep first error, if present.
-          error ??= e;
-          connectNext(); // Try again after failure to connect.
-        });
-        socket.setListening(read: false, write: true);
+    // Invoked either directly or via throttling Timer callback when we
+    // are ready to verify that we can connect to resolved address.
+    connectNext() {
+      timer?.cancel();
+      if (isLookedUpStreamClosed &&
+          connecting.isEmpty &&
+          pendingLookedUp.isEmpty) {
+        assert(error != null);
+        if (!result.isCompleted) {
+          // Might be already completed via onCancel
+          result.completeError(error);
+        }
+        return;
+      }
+      if (pendingLookedUp.isEmpty) {
+        assert(!isLookedUpStreamClosed || connecting.isNotEmpty);
+        return;
+      }
+      final address = pendingLookedUp.removeFirst();
+      final socket = new _NativeSocket.normal(address);
+      // Will contain values of various types representing the result
+      // of trying to create a connection.
+      // A value of `true` means success, everything else means failure.
+      final Object? connectionResult =
+          createConnection(address, source, socket);
+      if (connectionResult != true) {
+        // connectionResult was not a success.
+        error = createConnectionError(connectionResult, address, port, socket);
+        connectNext(); // Try again after failure to connect.
+        return;
+      }
+      // Query the local port for error messages.
+      try {
+        socket.port;
+      } catch (e) {
+        error ??= createError(e, "Connection failed", address, port);
+        connectNext(); // Try again after failure to connect.
+        return;
       }
 
-      void onCancel() {
-        timer?.cancel();
+      // Try again if no response (failure or success) within a duration.
+      // If this occurs, the socket is still trying to connect, and might
+      // succeed or fail later.
+      final duration =
+          address.isLoopback ? _retryDurationLoopback : _retryDuration;
+      timer = new Timer(duration, connectNext);
+      connecting.add(socket);
+      // Setup handlers for receiving the first write event which
+      // indicate that the socket is fully connected.
+      socket.setHandlers(write: () {
+        // First remote response on connection.
+        // If error, drop the socket and go to the next address.
+        // If success, complete with the socket
+        // and stop all other open connection attempts.
+        connecting.remove(socket);
+        // From 'man 2 connect':
+        // After select(2) indicates writability, use getsockopt(2) to read
+        // the SO_ERROR option at level SOL_SOCKET to determine whether
+        // connect() completed successfully (SO_ERROR is zero) or
+        // unsuccessfully.
+        final OSError osError = socket.nativeGetError();
+        if (osError.errorCode != 0) {
+          socket.close();
+          error ??= osError;
+          connectNext();
+          return;
+        }
+        // Connection success!
+        // Stop all other connecting sockets and the timer.
+        timer!.cancel();
+        socket.setListening(read: false, write: false);
         for (var s in connecting) {
           s.close();
           s.setHandlers();
           s.setListening(read: false, write: false);
         }
         connecting.clear();
-        if (!result.isCompleted) {
-          error ??= createError(null,
-              "Connection attempt cancelled, host: ${host}, port: ${port}");
-          result.completeError(error);
-        }
-      }
+        addressesSubscription.cancel();
+        result.complete(socket);
+      }, error: (e, st) {
+        connecting.remove(socket);
+        socket.close();
+        socket.setHandlers();
+        socket.setListening(read: false, write: false);
+        // Keep first error, if present.
+        error ??= e;
+        connectNext(); // Try again after failure to connect.
+      });
+      socket.setListening(read: false, write: true);
+    }
 
+    void onCancel() {
+      timer?.cancel();
+      for (var s in connecting) {
+        s.close();
+        s.setHandlers();
+        s.setListening(read: false, write: false);
+      }
+      connecting.clear();
+      if (!result.isCompleted) {
+        error ??= createError(
+            null, "Connection attempt cancelled, host: ${host}, port: ${port}");
+        result.completeError(error);
+      }
+    }
+
+    addressesSubscription = addresses.listen((address) {
+      pendingLookedUp.addAll(address);
+      if (timer == null || !timer!.isActive) {
+        connectNext();
+      }
+    }, onDone: () {
+      isLookedUpStreamClosed = true;
       connectNext();
-      return new ConnectionTask<_NativeSocket>._(result.future, onCancel);
+    }, onError: (e, st) {
+      error = e;
     });
+
+    connectNext();
+    return new ConnectionTask<_NativeSocket>._(result.future, onCancel);
   }
 
   static Future<_NativeSocket> connect(
diff --git a/sdk/lib/_internal/vm/lib/array_patch.dart b/sdk/lib/_internal/vm/lib/array_patch.dart
index 07d7e75..f6edca3 100644
--- a/sdk/lib/_internal/vm/lib/array_patch.dart
+++ b/sdk/lib/_internal/vm/lib/array_patch.dart
@@ -70,13 +70,4 @@
     final result = new List<E>.from(elements, growable: false);
     return makeFixedListUnmodifiable(result);
   }
-
-  // Factory constructing a mutable List from a parser generated List literal.
-  // [elements] contains elements that are already type checked.
-  @pragma("vm:entry-point", "call")
-  factory List._fromLiteral(_List elements) {
-    final result = new _GrowableList<E>._withData(elements);
-    result._setLength(elements.length);
-    return result;
-  }
 }
diff --git a/sdk/lib/_internal/vm/lib/compact_hash.dart b/sdk/lib/_internal/vm/lib/compact_hash.dart
index 4574455..39c353f 100644
--- a/sdk/lib/_internal/vm/lib/compact_hash.dart
+++ b/sdk/lib/_internal/vm/lib/compact_hash.dart
@@ -24,13 +24,13 @@
   // least one unoccupied entry.
   // NOTE: When maps are deserialized, their _index and _hashMask is regenerated
   // eagerly by _regenerateIndex.
-  Uint32List _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE);
+  Uint32List _index = _initialIndex;
 
   // Cached in-place mask for the hash pattern component.
-  int _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE);
+  int _hashMask = 0;
 
   // Fixed-length list of keys (set) or key/value at even/odd indices (map).
-  List _data;
+  List _data = _initialData;
 
   // Length of _data that is used (i.e., keys + values for a map).
   int _usedData = 0;
@@ -41,7 +41,7 @@
   // Note: All fields are initialized in a single constructor so that the VM
   // recognizes they cannot hold null values. This makes a big (20%) performance
   // difference on some operations.
-  _HashFieldBase(int dataSize) : this._data = new List.filled(dataSize, null);
+  _HashFieldBase(int dataSize);
 }
 
 // Base class for VM-internal classes; keep in sync with _HashFieldBase.
@@ -97,7 +97,7 @@
   // are doubled when _data is full. Thus, _index will have a max load factor
   // of 1/2, which enables one more bit to be used for the hash.
   // TODO(koda): Consider growing _data by factor sqrt(2), twice as often.
-  static const int _INITIAL_INDEX_BITS = 3;
+  static const int _INITIAL_INDEX_BITS = 2;
   static const int _INITIAL_INDEX_SIZE = 1 << (_INITIAL_INDEX_BITS + 1);
 
   // Unused and deleted entries are marked by 0 and 1, respectively.
@@ -155,6 +155,12 @@
   bool _equals(e1, e2) => identical(e1, e2);
 }
 
+final _initialIndex = new Uint32List(1);
+// Note: not const. Const arrays are made immutable by having a different class
+// than regular arrays that throws on element assignment. We want the data field
+// in maps and sets to be monomorphic.
+final _initialData = new List.filled(0, null);
+
 // VM-internalized implementation of a default-constructed LinkedHashMap.
 @pragma("vm:entry-point")
 class _InternalLinkedHashMap<K, V> extends _HashVMBase
@@ -165,9 +171,9 @@
         _OperatorEqualsAndHashCode
     implements LinkedHashMap<K, V> {
   _InternalLinkedHashMap() {
-    _index = new Uint32List(_HashBase._INITIAL_INDEX_SIZE);
-    _hashMask = _HashBase._indexSizeToHashMask(_HashBase._INITIAL_INDEX_SIZE);
-    _data = new List.filled(_HashBase._INITIAL_INDEX_SIZE, null);
+    _index = _initialIndex;
+    _hashMask = 0;
+    _data = _initialData;
     _usedData = 0;
     _deletedKeys = 0;
   }
@@ -202,6 +208,10 @@
 
   // Allocate new _index and _data, and optionally copy existing contents.
   void _init(int size, int hashMask, List? oldData, int oldUsed) {
+    if (size < _HashBase._INITIAL_INDEX_SIZE) {
+      size = _HashBase._INITIAL_INDEX_SIZE;
+      hashMask = _HashBase._indexSizeToHashMask(size);
+    }
     assert(size & (size - 1) == 0);
     assert(_HashBase._UNUSED_PAIR == 0);
     _index = new Uint32List(size);
@@ -222,7 +232,7 @@
 
   // This method is called by [_rehashObjects] (see above).
   void _regenerateIndex() {
-    _index = new Uint32List(_data.length);
+    _index = _data.length == 0 ? _initialIndex : new Uint32List(_data.length);
     assert(_hashMask == 0);
     _hashMask = _HashBase._indexSizeToHashMask(_index.length);
     final int tmpUsed = _usedData;
@@ -526,6 +536,10 @@
   }
 
   void _init(int size, int hashMask, List? oldData, int oldUsed) {
+    if (size < _HashBase._INITIAL_INDEX_SIZE) {
+      size = _HashBase._INITIAL_INDEX_SIZE;
+      hashMask = _HashBase._indexSizeToHashMask(size);
+    }
     _index = new Uint32List(size);
     _hashMask = hashMask;
     _data = new List.filled(size >> 1, null);
diff --git a/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart b/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart
new file mode 100644
index 0000000..5b794e6
--- /dev/null
+++ b/sdk/lib/_internal/vm/lib/ffi_allocation_patch.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.
+
+// All imports must be in all FFI patch files to not depend on the order
+// the patches are applied.
+import "dart:_internal" show patch;
+import 'dart:typed_data';
+import 'dart:isolate';
+
+extension AllocatorAlloc on Allocator {
+  // TODO(http://dartbug.com/38721): Implement this in the CFE to remove the
+  // invocation of sizeOf<T> to enable tree shaking.
+  // TODO(http://dartbug.com/39964): Add `alignmentOf<T>()` call.
+  @patch
+  Pointer<T> call<T extends NativeType>([int count = 1]) {
+    return this.allocate(sizeOf<T>() * count);
+  }
+}
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index 79fc3a3..8bc4c14 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart
@@ -119,6 +119,48 @@
 int _abi()
     native "Recognized method: IR graph is built in the flow graph builder.";
 
+/// Copies data byte-wise from [source] to [target].
+///
+/// [source] and [target] should either be [Pointer] or [TypedData].
+///
+/// TODO(dartbug.com/37271): Make recognized method and use MemoryCopyInstr.
+void _memCopy(Object target, int targetOffsetInBytes, Object source,
+    int sourceOffsetInBytes, int lengthInBytes) {
+  assert(source is Pointer || source is TypedData);
+  assert(target is Pointer || target is TypedData);
+  if (source is Pointer) {
+    final sourcePointer = source.cast<Uint8>();
+    if (target is Pointer) {
+      final targetPointer = target.cast<Uint8>();
+      for (int i = 0; i < lengthInBytes; i++) {
+        targetPointer[i + targetOffsetInBytes] =
+            sourcePointer[i + sourceOffsetInBytes];
+      }
+    } else if (target is TypedData) {
+      final targetTypedData = target.buffer.asUint8List(target.offsetInBytes);
+      for (int i = 0; i < lengthInBytes; i++) {
+        targetTypedData[i + targetOffsetInBytes] =
+            sourcePointer[i + sourceOffsetInBytes];
+      }
+    }
+  } else if (source is TypedData) {
+    final sourceTypedData = source.buffer.asUint8List(source.offsetInBytes);
+    if (target is Pointer) {
+      final targetPointer = target.cast<Uint8>();
+      for (int i = 0; i < lengthInBytes; i++) {
+        targetPointer[i + targetOffsetInBytes] =
+            sourceTypedData[i + sourceOffsetInBytes];
+      }
+    } else if (target is TypedData) {
+      final targetTypedData = target.buffer.asUint8List(target.offsetInBytes);
+      targetTypedData.setRange(
+          targetOffsetInBytes,
+          targetOffsetInBytes + lengthInBytes,
+          sourceTypedData.sublist(sourceOffsetInBytes));
+    }
+  }
+}
+
 // The following functions are implemented in the method recognizer.
 //
 // TODO(38172): Since these are not inlined (force optimize), they force
diff --git a/sdk/lib/_internal/vm/lib/growable_array.dart b/sdk/lib/_internal/vm/lib/growable_array.dart
index 059454e..519f095 100644
--- a/sdk/lib/_internal/vm/lib/growable_array.dart
+++ b/sdk/lib/_internal/vm/lib/growable_array.dart
@@ -521,4 +521,108 @@
   Set<T> toSet() {
     return new Set<T>.of(this);
   }
+
+  // Factory constructing a mutable List from a parser generated List literal.
+  // [elements] contains elements that are already type checked.
+  @pragma("vm:entry-point", "call")
+  factory _GrowableList._literal(_List elements) {
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(elements.length);
+    return result;
+  }
+
+  // Specialized list literal constructors.
+  // Used by pkg/vm/lib/transformations/list_literals_lowering.dart.
+  factory _GrowableList._literal1(T e0) {
+    _List elements = _List(1);
+    elements[0] = e0;
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(1);
+    return result;
+  }
+
+  factory _GrowableList._literal2(T e0, T e1) {
+    _List elements = _List(2);
+    elements[0] = e0;
+    elements[1] = e1;
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(2);
+    return result;
+  }
+
+  factory _GrowableList._literal3(T e0, T e1, T e2) {
+    _List elements = _List(3);
+    elements[0] = e0;
+    elements[1] = e1;
+    elements[2] = e2;
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(3);
+    return result;
+  }
+
+  factory _GrowableList._literal4(T e0, T e1, T e2, T e3) {
+    _List elements = _List(4);
+    elements[0] = e0;
+    elements[1] = e1;
+    elements[2] = e2;
+    elements[3] = e3;
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(4);
+    return result;
+  }
+
+  factory _GrowableList._literal5(T e0, T e1, T e2, T e3, T e4) {
+    _List elements = _List(5);
+    elements[0] = e0;
+    elements[1] = e1;
+    elements[2] = e2;
+    elements[3] = e3;
+    elements[4] = e4;
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(5);
+    return result;
+  }
+
+  factory _GrowableList._literal6(T e0, T e1, T e2, T e3, T e4, T e5) {
+    _List elements = _List(6);
+    elements[0] = e0;
+    elements[1] = e1;
+    elements[2] = e2;
+    elements[3] = e3;
+    elements[4] = e4;
+    elements[5] = e5;
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(6);
+    return result;
+  }
+
+  factory _GrowableList._literal7(T e0, T e1, T e2, T e3, T e4, T e5, T e6) {
+    _List elements = _List(7);
+    elements[0] = e0;
+    elements[1] = e1;
+    elements[2] = e2;
+    elements[3] = e3;
+    elements[4] = e4;
+    elements[5] = e5;
+    elements[6] = e6;
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(7);
+    return result;
+  }
+
+  factory _GrowableList._literal8(
+      T e0, T e1, T e2, T e3, T e4, T e5, T e6, T e7) {
+    _List elements = _List(8);
+    elements[0] = e0;
+    elements[1] = e1;
+    elements[2] = e2;
+    elements[3] = e3;
+    elements[4] = e4;
+    elements[5] = e5;
+    elements[6] = e6;
+    elements[7] = e7;
+    final result = new _GrowableList<T>._withData(elements);
+    result._setLength(8);
+    return result;
+  }
 }
diff --git a/sdk/lib/_internal/vm/lib/lib_prefix.dart b/sdk/lib/_internal/vm/lib/lib_prefix.dart
index 4259640..7604f62 100644
--- a/sdk/lib/_internal/vm/lib/lib_prefix.dart
+++ b/sdk/lib/_internal/vm/lib/lib_prefix.dart
@@ -31,7 +31,11 @@
 
 @pragma("vm:entry-point")
 void _completeLoads(Object unit, String? errorMessage, bool transientError) {
-  Completer<void> load = _LibraryPrefix._loads[unit]!;
+  Completer<void>? load = _LibraryPrefix._loads[unit];
+  if (load == null) {
+    // Embedder loaded even though prefix.loadLibrary() wasn't called.
+    _LibraryPrefix._loads[unit] = load = new Completer<void>();
+  }
   if (errorMessage == null) {
     load.complete(null);
   } else {
diff --git a/sdk/lib/_internal/vm/lib/mirrors_impl.dart b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
index acd95e1..a938cf7 100644
--- a/sdk/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
@@ -754,8 +754,8 @@
 }
 
 class _FunctionTypeMirror extends _ClassMirror implements FunctionTypeMirror {
-  final _functionReflectee;
-  _FunctionTypeMirror._(reflectee, this._functionReflectee, reflectedType)
+  final _signatureReflectee;
+  _FunctionTypeMirror._(reflectee, this._signatureReflectee, reflectedType)
       : super._(reflectee, reflectedType, null, null, false, false, false,
             false, false);
 
@@ -773,7 +773,7 @@
   MethodMirror get callMethod {
     var m = _callMethod;
     if (m != null) return m;
-    return _callMethod = _FunctionTypeMirror_call_method(_functionReflectee);
+    return _callMethod = _FunctionTypeMirror_call_method(_signatureReflectee);
   }
 
   TypeMirror? _returnType;
@@ -781,7 +781,7 @@
     var t = _returnType;
     if (t != null) return t;
     return _returnType =
-        reflectType(_FunctionTypeMirror_return_type(_functionReflectee));
+        reflectType(_FunctionTypeMirror_return_type(_signatureReflectee));
   }
 
   List<ParameterMirror>? _parameters;
@@ -789,7 +789,7 @@
     var p = _parameters;
     if (p != null) return p;
     return _parameters = new UnmodifiableListView<ParameterMirror>(
-        _FunctionTypeMirror_parameters(_functionReflectee)
+        _FunctionTypeMirror_parameters(_signatureReflectee)
             .cast<ParameterMirror>());
   }
 
@@ -802,13 +802,13 @@
 
   String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
 
-  MethodMirror _FunctionTypeMirror_call_method(functionReflectee)
+  MethodMirror _FunctionTypeMirror_call_method(signatureReflectee)
       native "FunctionTypeMirror_call_method";
 
-  static Type _FunctionTypeMirror_return_type(functionReflectee)
+  static Type _FunctionTypeMirror_return_type(signatureReflectee)
       native "FunctionTypeMirror_return_type";
 
-  List<dynamic> _FunctionTypeMirror_parameters(functionReflectee)
+  List<dynamic> _FunctionTypeMirror_parameters(signatureReflectee)
       native "FunctionTypeMirror_parameters";
 }
 
@@ -884,9 +884,8 @@
   String toString() => "TypeVariableMirror on '${_n(simpleName)}'";
 
   bool operator ==(Object other) {
-    return other is TypeVariableMirror &&
-        simpleName == other.simpleName &&
-        owner == other.owner;
+    return other is TypeVariableMirror && simpleName == other.simpleName;
+    // Type variables do not refer to owner.
   }
 
   int get hashCode => simpleName.hashCode;
@@ -914,110 +913,6 @@
       native "TypeVariableMirror_upper_bound";
 }
 
-class _TypedefMirror extends _DeclarationMirror
-    implements TypedefMirror, _TypeMirror {
-  final Type _reflectedType;
-  final bool _isGeneric;
-  final bool _isGenericDeclaration;
-
-  _TypedefMirror(reflectee, this._reflectedType, String simpleName,
-      this._isGeneric, this._isGenericDeclaration, this._owner)
-      : super._(reflectee, _s(simpleName));
-
-  bool get isTopLevel => true;
-
-  DeclarationMirror? _owner;
-  DeclarationMirror? get owner {
-    var o = _owner;
-    if (o != null) return o;
-    var uri = _ClassMirror._libraryUri(_reflectee);
-    return _owner = currentMirrorSystem().libraries[Uri.parse(uri)];
-  }
-
-  _FunctionTypeMirror? _referent;
-  FunctionTypeMirror get referent {
-    var r = _referent;
-    if (r != null) return r;
-    var result = _nativeReferent(_reflectedType) as _FunctionTypeMirror;
-    result._instantiator = _reflectedType;
-    return _referent = result;
-  }
-
-  bool get hasReflectedType => !_isGenericDeclaration;
-  Type get reflectedType {
-    if (!hasReflectedType) {
-      throw new UnsupportedError(
-          "Declarations of generics have no reflected type");
-    }
-    return _reflectedType;
-  }
-
-  bool get isOriginalDeclaration => !_isGeneric || _isGenericDeclaration;
-
-  TypedefMirror get originalDeclaration {
-    if (isOriginalDeclaration) {
-      return this;
-    } else {
-      return _nativeDeclaration(_reflectedType);
-    }
-  }
-
-  List<TypeVariableMirror>? _typeVariables;
-  List<TypeVariableMirror> get typeVariables {
-    var v = _typeVariables;
-    if (v != null) return v;
-
-    var result = <TypeVariableMirror>[];
-    List params = _ClassMirror._ClassMirror_type_variables(_reflectee);
-    TypedefMirror owner = originalDeclaration;
-    var mirror;
-    for (var i = 0; i < params.length; i += 2) {
-      mirror = new _TypeVariableMirror._(params[i + 1], params[i], owner);
-      result.add(mirror);
-    }
-    return _typeVariables =
-        new UnmodifiableListView<TypeVariableMirror>(result);
-  }
-
-  List<TypeMirror>? _typeArguments;
-  List<TypeMirror> get typeArguments {
-    var a = _typeArguments;
-    if (a != null) return a;
-
-    if (_isGenericDeclaration) {
-      return _typeArguments = const <TypeMirror>[];
-    } else {
-      return _typeArguments = new UnmodifiableListView<TypeMirror>(
-          _ClassMirror._computeTypeArguments(_reflectedType)
-              .cast<TypeMirror>());
-    }
-  }
-
-  String toString() => "TypedefMirror on '${_n(simpleName)}'";
-
-  bool isSubtypeOf(TypeMirror other) {
-    if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return true;
-    if (other == currentMirrorSystem().neverType) return false;
-    return _subtypeTest(_reflectedType, (other as _TypeMirror)._reflectedType);
-  }
-
-  bool isAssignableTo(TypeMirror other) {
-    if (other == currentMirrorSystem().dynamicType) return true;
-    if (other == currentMirrorSystem().voidType) return true;
-    if (other == currentMirrorSystem().neverType) return false;
-    final otherReflectedType = (other as _TypeMirror)._reflectedType;
-    return _subtypeTest(_reflectedType, otherReflectedType) ||
-        _subtypeTest(otherReflectedType, _reflectedType);
-  }
-
-  static FunctionTypeMirror _nativeReferent(reflectedType)
-      native "TypedefMirror_referent";
-
-  static TypedefMirror _nativeDeclaration(reflectedType)
-      native "TypedefMirror_declaration";
-}
-
 Symbol _asSetter(Symbol getter, LibraryMirror library) {
   var unwrapped = MirrorSystem.getName(getter);
   return MirrorSystem.getSymbol('${unwrapped}=', library);
diff --git a/sdk/lib/_internal/vm/lib/object_patch.dart b/sdk/lib/_internal/vm/lib/object_patch.dart
index fe23069..ac85705 100644
--- a/sdk/lib/_internal/vm/lib/object_patch.dart
+++ b/sdk/lib/_internal/vm/lib/object_patch.dart
@@ -56,7 +56,7 @@
 
   @patch
   @pragma("vm:recognized", "asm-intrinsic")
-  @pragma("vm:exact-result-type", "dart:core#_Type")
+  // Result type is either "dart:core#_Type" or "dart:core#_FunctionType".
   Type get runtimeType native "Object_runtimeType";
 
   @pragma("vm:recognized", "asm-intrinsic")
diff --git a/sdk/lib/_internal/vm/lib/type_patch.dart b/sdk/lib/_internal/vm/lib/type_patch.dart
index 52be775..c818922 100644
--- a/sdk/lib/_internal/vm/lib/type_patch.dart
+++ b/sdk/lib/_internal/vm/lib/type_patch.dart
@@ -6,12 +6,12 @@
 
 // These Dart classes correspond to the VM internal implementation classes.
 
-// Equivalent of RawAbstractType.
+// Equivalent of AbstractTypeLayout.
 abstract class _AbstractType implements Type {
   String toString() native "AbstractType_toString";
 }
 
-// Equivalent of RawType.
+// Equivalent of TypeLayout.
 @pragma("vm:entry-point")
 class _Type extends _AbstractType {
   factory _Type._uninstantiable() {
@@ -27,7 +27,23 @@
   bool operator ==(other) native "Type_equality";
 }
 
-// Equivalent of RawTypeRef.
+// Equivalent of FunctionTypeLayout.
+@pragma("vm:entry-point")
+class _FunctionType extends _AbstractType {
+  factory _FunctionType._uninstantiable() {
+    throw "Unreachable";
+  }
+
+  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:exact-result-type", "dart:core#_Smi")
+  int get hashCode native "FunctionType_getHashCode";
+
+  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:exact-result-type", bool)
+  bool operator ==(other) native "FunctionType_equality";
+}
+
+// Equivalent of TypeRefLayout.
 @pragma("vm:entry-point")
 class _TypeRef extends _AbstractType {
   factory _TypeRef._uninstantiable() {
@@ -35,7 +51,7 @@
   }
 }
 
-// Equivalent of RawTypeParameter.
+// Equivalent of TypeParameterLayout.
 @pragma("vm:entry-point")
 class _TypeParameter extends _AbstractType {
   factory _TypeParameter._uninstantiable() {
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index 43e3c1c..0d1539d 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -2,95 +2,93 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * Support for asynchronous programming,
- * with classes such as Future and Stream.
- *
- * Understanding [Future]s and [Stream]s is a prerequisite for
- * writing just about any Dart program.
- *
- * To use this library in your code:
- *
- *     import 'dart:async';
- *
- * ## Future
- *
- * A Future object represents a computation whose return value
- * might not yet be available.
- * The Future returns the value of the computation
- * when it completes at some time in the future.
- * Futures are often used for potentially lengthy computations
- * such as I/O and interaction with users.
- *
- * Many methods in the Dart libraries return Futures when
- * performing tasks. For example, when binding an HttpServer
- * to a host and port, the `bind()` method returns a Future.
- *
- *      HttpServer.bind('127.0.0.1', 4444)
- *          .then((server) => print('${server.isBroadcast}'))
- *          .catchError(print);
- *
- * [Future.then] registers a callback function that runs
- * when the Future's operation, in this case the `bind()` method,
- * completes successfully.
- * The value returned by the operation
- * is passed into the callback function.
- * In this example, the `bind()` method returns the HttpServer
- * object. The callback function prints one of its properties.
- * [Future.catchError] registers a callback function that
- * runs if an error occurs within the Future.
- *
- * ## Stream
- *
- * A Stream provides an asynchronous sequence of data.
- * Examples of data sequences include individual events, like mouse clicks,
- * or sequential chunks of larger data, like multiple byte lists with the
- * contents of a file
- * such as mouse clicks, and a stream of byte lists read from a file.
- * The following example opens a file for reading.
- * [Stream.listen] registers a callback function that runs
- * each time more data is available.
- *
- *     Stream<List<int>> stream = new File('quotes.txt').openRead();
- *     stream.transform(utf8.decoder).listen(print);
- *
- * The stream emits a sequence of a list of bytes.
- * The program must interpret the bytes or handle the raw byte data.
- * Here, the code uses a UTF-8 decoder (provided in the `dart:convert` library)
- * to convert the sequence of bytes into a sequence
- * of Dart strings.
- *
- * Another common use of streams is for user-generated events
- * in a web app: The following code listens for mouse clicks on a button.
- *
- *     querySelector('#myButton').onClick.listen((_) => print('Click.'));
- *
- * ## Other resources
- *
- * * The [dart:async section of the library tour][asynchronous-programming]:
- *   A brief overview of asynchronous programming.
- *
- * * [Use Future-Based APIs][futures-tutorial]: A closer look at Futures and
- *   how to use them to write asynchronous Dart code.
- *
- * * [Futures and Error Handling][futures-error-handling]: Everything you
- *   wanted to know about handling errors and exceptions when working with
- *   Futures (but were afraid to ask).
- *
- * * [The Event Loop and Dart](https://dart.dev/articles/event-loop/):
- *   Learn how Dart handles the event queue and microtask queue, so you can
- *   write better asynchronous code with fewer surprises.
- *
- * * [test package: Asynchronous Tests][test-readme]: How to test asynchronous
- *   code.
- *
- * [asynchronous-programming]: https://dart.dev/guides/libraries/library-tour#dartasync---asynchronous-programming
- * [futures-tutorial]: https://dart.dev/codelabs/async-await
- * [futures-error-handling]: https://dart.dev/guides/libraries/futures-error-handling
- * [test-readme]: https://pub.dev/packages/test
- *
- * {@category Core}
- */
+/// Support for asynchronous programming,
+/// with classes such as Future and Stream.
+///
+/// Understanding [Future]s and [Stream]s is a prerequisite for
+/// writing just about any Dart program.
+///
+/// To use this library in your code:
+/// ```dart
+/// import 'dart:async';
+/// ```
+/// ## Future
+///
+/// A Future object represents a computation whose return value
+/// might not yet be available.
+/// The Future returns the value of the computation
+/// when it completes at some time in the future.
+/// Futures are often used for potentially lengthy computations
+/// such as I/O and interaction with users.
+///
+/// Many methods in the Dart libraries return Futures when
+/// performing tasks. For example, when binding an HttpServer
+/// to a host and port, the `bind()` method returns a Future.
+/// ```dart
+///  HttpServer.bind('127.0.0.1', 4444)
+///      .then((server) => print('${server.isBroadcast}'))
+///      .catchError(print);
+/// ```
+/// [Future.then] registers a callback function that runs
+/// when the Future's operation, in this case the `bind()` method,
+/// completes successfully.
+/// The value returned by the operation
+/// is passed into the callback function.
+/// In this example, the `bind()` method returns the HttpServer
+/// object. The callback function prints one of its properties.
+/// [Future.catchError] registers a callback function that
+/// runs if an error occurs within the Future.
+///
+/// ## Stream
+///
+/// A Stream provides an asynchronous sequence of data.
+/// Examples of data sequences include individual events, like mouse clicks,
+/// or sequential chunks of larger data, like multiple byte lists with the
+/// contents of a file
+/// such as mouse clicks, and a stream of byte lists read from a file.
+/// The following example opens a file for reading.
+/// [Stream.listen] registers a callback function that runs
+/// each time more data is available.
+/// ```dart
+/// Stream<List<int>> stream = File('quotes.txt').openRead();
+/// stream.transform(utf8.decoder).listen(print);
+/// ```
+/// The stream emits a sequence of a list of bytes.
+/// The program must interpret the bytes or handle the raw byte data.
+/// Here, the code uses a UTF-8 decoder (provided in the `dart:convert` library)
+/// to convert the sequence of bytes into a sequence
+/// of Dart strings.
+///
+/// Another common use of streams is for user-generated events
+/// in a web app: The following code listens for mouse clicks on a button.
+/// ```dart
+/// querySelector('#myButton').onClick.listen((_) => print('Click.'));
+/// ```
+/// ## Other resources
+///
+/// * The [dart:async section of the library tour][asynchronous-programming]:
+///   A brief overview of asynchronous programming.
+///
+/// * [Use Future-Based APIs][futures-tutorial]: A closer look at Futures and
+///   how to use them to write asynchronous Dart code.
+///
+/// * [Futures and Error Handling][futures-error-handling]: Everything you
+///   wanted to know about handling errors and exceptions when working with
+///   Futures (but were afraid to ask).
+///
+/// * [The Event Loop and Dart](https://dart.dev/articles/event-loop/):
+///   Learn how Dart handles the event queue and microtask queue, so you can
+///   write better asynchronous code with fewer surprises.
+///
+/// * [test package: Asynchronous Tests][test-readme]: How to test asynchronous
+///   code.
+///
+/// [asynchronous-programming]: https://dart.dev/guides/libraries/library-tour#dartasync---asynchronous-programming
+/// [futures-tutorial]: https://dart.dev/codelabs/async-await
+/// [futures-error-handling]: https://dart.dev/guides/libraries/futures-error-handling
+/// [test-readme]: https://pub.dev/packages/test
+///
+/// {@category Core}
 library dart.async;
 
 import "dart:collection" show HashMap;
diff --git a/sdk/lib/async/async_error.dart b/sdk/lib/async/async_error.dart
index a7172bd..2340a41 100644
--- a/sdk/lib/async/async_error.dart
+++ b/sdk/lib/async/async_error.dart
@@ -4,6 +4,35 @@
 
 part of dart.async;
 
+/// An error and a stack trace.
+///
+/// Used when an error and stack trace need to be handled as a single
+/// value, for example when returned by [Zone.errorCallback].
+class AsyncError implements Error {
+  final Object error;
+  final StackTrace stackTrace;
+
+  AsyncError(Object error, StackTrace? stackTrace)
+      : error = checkNotNullable(error, "error"),
+        stackTrace = stackTrace ?? defaultStackTrace(error);
+
+  /// A default stack trace for an error.
+  ///
+  /// If [error] is an [Error] and it has an [Error.stackTrace],
+  /// that stack trace is returned.
+  /// If not, the [StackTrace.empty] default stack trace is returned.
+  static StackTrace defaultStackTrace(Object error) {
+    if (error is Error) {
+      var stackTrace = error.stackTrace;
+      if (stackTrace != null) return stackTrace;
+    }
+    return StackTrace.empty;
+  }
+
+  String toString() => '$error';
+}
+
+// Helper function used by stream method implementations.
 _invokeErrorHandler(
     Function errorHandler, Object error, StackTrace stackTrace) {
   var handler = errorHandler; // Rename to avoid promotion.
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 4db2a34..c2db270 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -81,19 +81,17 @@
   // Extra state used during an [addStream] call.
   _AddStreamState<T>? _addStreamState;
 
-  /**
-   * Future returned by [close] and [done].
-   *
-   * The future is completed whenever the done event has been sent to all
-   * relevant listeners.
-   * The relevant listeners are the ones that were listening when [close] was
-   * called. When all of these have been canceled (sending the done event makes
-   * them cancel, but they can also be canceled before sending the event),
-   * this future completes.
-   *
-   * Any attempt to listen after calling [close] will throw, so there won't
-   * be any further listeners.
-   */
+  /// Future returned by [close] and [done].
+  ///
+  /// The future is completed whenever the done event has been sent to all
+  /// relevant listeners.
+  /// The relevant listeners are the ones that were listening when [close] was
+  /// called. When all of these have been canceled (sending the done event makes
+  /// them cancel, but they can also be canceled before sending the event),
+  /// this future completes.
+  ///
+  /// Any attempt to listen after calling [close] will throw, so there won't
+  /// be any further listeners.
   _Future<void>? _doneFuture;
 
   _BroadcastStreamController(this.onListen, this.onCancel)
@@ -127,28 +125,24 @@
 
   bool get isClosed => (_state & _STATE_CLOSED) != 0;
 
-  /**
-   * A broadcast controller is never paused.
-   *
-   * Each receiving stream may be paused individually, and they handle their
-   * own buffering.
-   */
+  /// A broadcast controller is never paused.
+  ///
+  /// Each receiving stream may be paused individually, and they handle their
+  /// own buffering.
   bool get isPaused => false;
 
-  /** Whether there are currently one or more subscribers. */
+  /// Whether there are currently one or more subscribers.
   bool get hasListener => !_isEmpty;
 
-  /**
-   * Test whether the stream has exactly one listener.
-   *
-   * Assumes that the stream has a listener (not [_isEmpty]).
-   */
+  /// Test whether the stream has exactly one listener.
+  ///
+  /// Assumes that the stream has a listener (not [_isEmpty]).
   bool get _hasOneListener {
     assert(!_isEmpty);
     return identical(_firstSubscription, _lastSubscription);
   }
 
-  /** Whether an event is being fired (sent to some, but not all, listeners). */
+  /// Whether an event is being fired (sent to some, but not all, listeners).
   bool get _isFiring => (_state & _STATE_FIRING) != 0;
 
   bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0;
@@ -161,7 +155,7 @@
 
   bool get _isEmpty => _firstSubscription == null;
 
-  /** Adds subscription to linked list of active listeners. */
+  /// Adds subscription to linked list of active listeners.
   void _addListener(_BroadcastSubscription<T> subscription) {
     assert(identical(subscription._next, subscription));
     subscription._eventState = (_state & _STATE_EVENT_ID);
@@ -448,17 +442,15 @@
   }
 }
 
-/**
- * Stream controller that is used by [Stream.asBroadcastStream].
- *
- * This stream controller allows incoming events while it is firing
- * other events. This is handled by delaying the events until the
- * current event is done firing, and then fire the pending events.
- *
- * This class extends [_SyncBroadcastStreamController]. Events of
- * an "asBroadcastStream" stream are always initiated by events
- * on another stream, and it is fine to forward them synchronously.
- */
+/// Stream controller that is used by [Stream.asBroadcastStream].
+///
+/// This stream controller allows incoming events while it is firing
+/// other events. This is handled by delaying the events until the
+/// current event is done firing, and then fire the pending events.
+///
+/// This class extends [_SyncBroadcastStreamController]. Events of
+/// an "asBroadcastStream" stream are always initiated by events
+/// on another stream, and it is fine to forward them synchronously.
 class _AsBroadcastStreamController<T> extends _SyncBroadcastStreamController<T>
     implements _EventDispatch<T> {
   _StreamImplEvents<T>? _pending;
diff --git a/sdk/lib/async/deferred_load.dart b/sdk/lib/async/deferred_load.dart
index 419db58..81d9f80 100644
--- a/sdk/lib/async/deferred_load.dart
+++ b/sdk/lib/async/deferred_load.dart
@@ -4,12 +4,12 @@
 
 part of dart.async;
 
-/**
- * Indicates that loading of [libraryName] is deferred.
- *
- * This class is obsolete. Instead use the syntax:
- * import "library.dart" deferred as prefix;
- */
+/// Indicates that loading of [libraryName] is deferred.
+///
+/// This class is obsolete. Instead use the syntax:
+/// ```dart
+/// import "library.dart" deferred as prefix;
+/// ```
 @Deprecated("Dart sdk v. 1.8")
 class DeferredLibrary {
   final String libraryName;
@@ -17,18 +17,14 @@
 
   const DeferredLibrary(this.libraryName, {this.uri});
 
-  /**
-   * Ensure that [libraryName] has been loaded.
-   *
-   * If the library fails to load, the Future will complete with a
-   * DeferredLoadException.
-   */
+  /// Ensure that [libraryName] has been loaded.
+  ///
+  /// If the library fails to load, the [Future] will complete with a
+  /// [DeferredLoadException].
   external Future<Null> load();
 }
 
-/**
- * Thrown when a deferred library fails to load.
- */
+/// Thrown when a deferred library fails to load.
 class DeferredLoadException implements Exception {
   DeferredLoadException(String message) : _s = message;
   String toString() => "DeferredLoadException: '$_s'";
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 0473bc3..c8c1403 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -43,108 +43,106 @@
   }
 }
 
-/**
- * An object representing a delayed computation.
- *
- * A [Future] is used to represent a potential value, or error,
- * that will be available at some time in the future.
- * Receivers of a [Future] can register callbacks
- * that handle the value or error once it is available.
- * For example:
- *
- *     Future<int> future = getFuture();
- *     future.then((value) => handleValue(value))
- *           .catchError((error) => handleError(error));
- *
- * A [Future] can be completed in two ways:
- * with a value ("the future succeeds")
- * or with an error ("the future fails").
- * Users can install callbacks for each case.
- *
- * In some cases we say that a future is completed with another future.
- * This is a short way of stating that the future is completed in the same way,
- * with the same value or error,
- * as the other future once that completes.
- * Whenever a function in the core library may complete a future
- * (for example [Completer.complete] or [new Future.value]),
- * then it also accepts another future and does this work for the developer.
- *
- * The result of registering a pair of callbacks is a new Future (the
- * "successor") which in turn is completed with the result of invoking the
- * corresponding callback.
- * The successor is completed with an error if the invoked callback throws.
- * For example:
- * ```
- * Future<int> successor = future.then((int value) {
- *     // Invoked when the future is completed with a value.
- *     return 42;  // The successor is completed with the value 42.
- *   },
- *   onError: (e) {
- *     // Invoked when the future is completed with an error.
- *     if (canHandle(e)) {
- *       return 499;  // The successor is completed with the value 499.
- *     } else {
- *       throw e;  // The successor is completed with the error e.
- *     }
- *   });
- * ```
- *
- * If a future does not have a successor when it completes with an error,
- * it forwards the error message to the global error-handler.
- * This behavior makes sure that no error is silently dropped.
- * However, it also means that error handlers should be installed early,
- * so that they are present as soon as a future is completed with an error.
- * The following example demonstrates this potential bug:
- * ```
- * var future = getFuture();
- * new Timer(new Duration(milliseconds: 5), () {
- *   // The error-handler is not attached until 5 ms after the future has
- *   // been received. If the future fails before that, the error is
- *   // forwarded to the global error-handler, even though there is code
- *   // (just below) to eventually handle the error.
- *   future.then((value) { useValue(value); },
- *               onError: (e) { handleError(e); });
- * });
- * ```
- *
- * When registering callbacks, it's often more readable to register the two
- * callbacks separately, by first using [then] with one argument
- * (the value handler) and using a second [catchError] for handling errors.
- * Each of these will forward the result that they don't handle
- * to their successors, and together they handle both value and error result.
- * It also has the additional benefit of the [catchError] handling errors in the
- * [then] value callback too.
- * Using sequential handlers instead of parallel ones often leads to code that
- * is easier to reason about.
- * It also makes asynchronous code very similar to synchronous code:
- * ```
- * // Synchronous code.
- * try {
- *   int value = foo();
- *   return bar(value);
- * } catch (e) {
- *   return 499;
- * }
- * ```
- *
- * Equivalent asynchronous code, based on futures:
- * ```
- * Future<int> future = new Future(foo);  // Result of foo() as a future.
- * future.then((int value) => bar(value))
- *       .catchError((e) => 499);
- * ```
- *
- * Similar to the synchronous code, the error handler (registered with
- * [catchError]) is handling any errors thrown by either `foo` or `bar`.
- * If the error-handler had been registered as the `onError` parameter of
- * the `then` call, it would not catch errors from the `bar` call.
- *
- * Futures can have more than one callback-pair registered. Each successor is
- * treated independently and is handled as if it was the only successor.
- *
- * A future may also fail to ever complete. In that case, no callbacks are
- * called.
- */
+/// An object representing a delayed computation.
+///
+/// A [Future] is used to represent a potential value, or error,
+/// that will be available at some time in the future.
+/// Receivers of a [Future] can register callbacks
+/// that handle the value or error once it is available.
+/// For example:
+/// ```dart
+/// Future<int> future = getFuture();
+/// future.then((value) => handleValue(value))
+///       .catchError((error) => handleError(error));
+/// ```
+/// A [Future] can be completed in two ways:
+/// with a value ("the future succeeds")
+/// or with an error ("the future fails").
+/// Users can install callbacks for each case.
+///
+/// In some cases we say that a future is completed with another future.
+/// This is a short way of stating that the future is completed in the same way,
+/// with the same value or error,
+/// as the other future once that completes.
+/// Whenever a function in the core library may complete a future
+/// (for example [Completer.complete] or [Future.value]),
+/// then it also accepts another future and does this work for the developer.
+///
+/// The result of registering a pair of callbacks is a Future (the
+/// "successor") which in turn is completed with the result of invoking the
+/// corresponding callback.
+/// The successor is completed with an error if the invoked callback throws.
+/// For example:
+/// ```
+/// Future<int> successor = future.then((int value) {
+///     // Invoked when the future is completed with a value.
+///     return 42;  // The successor is completed with the value 42.
+///   },
+///   onError: (e) {
+///     // Invoked when the future is completed with an error.
+///     if (canHandle(e)) {
+///       return 499;  // The successor is completed with the value 499.
+///     } else {
+///       throw e;  // The successor is completed with the error e.
+///     }
+///   });
+/// ```
+///
+/// If a future does not have a successor when it completes with an error,
+/// it forwards the error message to an uncaught-error handler.
+/// This behavior makes sure that no error is silently dropped.
+/// However, it also means that error handlers should be installed early,
+/// so that they are present as soon as a future is completed with an error.
+/// The following example demonstrates this potential bug:
+/// ```
+/// var future = getFuture();
+/// Timer(const Duration(milliseconds: 5), () {
+///   // The error-handler is not attached until 5 ms after the future has
+///   // been received. If the future fails before that, the error is
+///   // forwarded to the global error-handler, even though there is code
+///   // (just below) to eventually handle the error.
+///   future.then((value) { useValue(value); },
+///               onError: (e) { handleError(e); });
+/// });
+/// ```
+///
+/// When registering callbacks, it's often more readable to register the two
+/// callbacks separately, by first using [then] with one argument
+/// (the value handler) and using a second [catchError] for handling errors.
+/// Each of these will forward the result that they don't handle
+/// to their successors, and together they handle both value and error result.
+/// It also has the additional benefit of the [catchError] handling errors in the
+/// [then] value callback too.
+/// Using sequential handlers instead of parallel ones often leads to code that
+/// is easier to reason about.
+/// It also makes asynchronous code very similar to synchronous code:
+/// ```
+/// // Synchronous code.
+/// try {
+///   int value = foo();
+///   return bar(value);
+/// } catch (e) {
+///   return 499;
+/// }
+/// ```
+///
+/// Equivalent asynchronous code, based on futures:
+/// ```
+/// Future<int> future = Future(foo);  // Result of foo() as a future.
+/// future.then((int value) => bar(value))
+///       .catchError((e) => 499);
+/// ```
+///
+/// Similar to the synchronous code, the error handler (registered with
+/// [catchError]) is handling any errors thrown by either `foo` or `bar`.
+/// If the error-handler had been registered as the `onError` parameter of
+/// the `then` call, it would not catch errors from the `bar` call.
+///
+/// Futures can have more than one callback-pair registered. Each successor is
+/// treated independently and is handled as if it was the only successor.
+///
+/// A future may also fail to ever complete. In that case, no callbacks are
+/// called.
 abstract class Future<T> {
   /// A `Future<Null>` completed with `null`.
   ///
@@ -157,20 +155,18 @@
   static final _Future<bool> _falseFuture =
       new _Future<bool>.zoneValue(false, _rootZone);
 
-  /**
-   * Creates a future containing the result of calling [computation]
-   * asynchronously with [Timer.run].
-   *
-   * If the result of executing [computation] throws, the returned future is
-   * completed with the error.
-   *
-   * If the returned value is itself a [Future], completion of
-   * the created future will wait until the returned future completes,
-   * and will then complete with the same result.
-   *
-   * If a non-future value is returned, the returned future is completed
-   * with that value.
-   */
+  /// Creates a future containing the result of calling [computation]
+  /// asynchronously with [Timer.run].
+  ///
+  /// If the result of executing [computation] throws, the returned future is
+  /// completed with the error.
+  ///
+  /// If the returned value is itself a [Future], completion of
+  /// the created future will wait until the returned future completes,
+  /// and will then complete with the same result.
+  ///
+  /// If a non-future value is returned, the returned future is completed
+  /// with that value.
   factory Future(FutureOr<T> computation()) {
     _Future<T> result = new _Future<T>();
     Timer.run(() {
@@ -183,20 +179,18 @@
     return result;
   }
 
-  /**
-   * Creates a future containing the result of calling [computation]
-   * asynchronously with [scheduleMicrotask].
-   *
-   * If executing [computation] throws,
-   * the returned future is completed with the thrown error.
-   *
-   * If calling [computation] returns a [Future], completion of
-   * the created future will wait until the returned future completes,
-   * and will then complete with the same result.
-   *
-   * If calling [computation] returns a non-future value,
-   * the returned future is completed with that value.
-   */
+  /// Creates a future containing the result of calling [computation]
+  /// asynchronously with [scheduleMicrotask].
+  ///
+  /// If executing [computation] throws,
+  /// the returned future is completed with the thrown error.
+  ///
+  /// If calling [computation] returns a [Future], completion of
+  /// the created future will wait until the returned future completes,
+  /// and will then complete with the same result.
+  ///
+  /// If calling [computation] returns a non-future value,
+  /// the returned future is completed with that value.
   factory Future.microtask(FutureOr<T> computation()) {
     _Future<T> result = new _Future<T>();
     scheduleMicrotask(() {
@@ -209,18 +203,16 @@
     return result;
   }
 
-  /**
-   * Returns a future containing the result of immediately calling
-   * [computation].
-   *
-   * If calling [computation] throws, the returned future is completed with the
-   * error.
-   *
-   * If calling [computation] returns a `Future<T>`, that future is returned.
-   *
-   * If calling [computation] returns a non-future value,
-   * a future is returned which has been completed with that value.
-   */
+  /// Returns a future containing the result of immediately calling
+  /// [computation].
+  ///
+  /// If calling [computation] throws, the returned future is completed with the
+  /// error.
+  ///
+  /// If calling [computation] returns a `Future<T>`, that future is returned.
+  ///
+  /// If calling [computation] returns a non-future value,
+  /// a future is returned which has been completed with that value.
   factory Future.sync(FutureOr<T> computation()) {
     try {
       var result = computation();
@@ -242,40 +234,36 @@
     }
   }
 
-  /**
-   * Creates a future completed with [value].
-   *
-   * If [value] is a future, the created future waits for the
-   * [value] future to complete, and then completes with the same result.
-   * Since a [value] future can complete with an error, so can the future
-   * created by [Future.value], even if the name suggests otherwise.
-   *
-   * If [value] is not a [Future], the created future is completed
-   * with the [value] value,
-   * equivalently to `new Future<T>.sync(() => value)`.
-   *
-   * If [value] is omitted or `null`, it is converted to `FutureOr<T>` by
-   * `value as FutureOr<T>`. If `T` is not nullable, then the [value] is
-   * required, otherwise the construction throws.
-   *
-   * Use [Completer] to create a future and complete it later.
-   */
+  /// Creates a future completed with [value].
+  ///
+  /// If [value] is a future, the created future waits for the
+  /// [value] future to complete, and then completes with the same result.
+  /// Since a [value] future can complete with an error, so can the future
+  /// created by [Future.value], even if the name suggests otherwise.
+  ///
+  /// If [value] is not a [Future], the created future is completed
+  /// with the [value] value,
+  /// equivalently to `new Future<T>.sync(() => value)`.
+  ///
+  /// If [value] is omitted or `null`, it is converted to `FutureOr<T>` by
+  /// `value as FutureOr<T>`. If `T` is not nullable, then a non-`null` [value]
+  /// must be provided, otherwise the construction throws.
+  ///
+  /// Use [Completer] to create a future now and complete it later.
   @pragma("vm:entry-point")
   @pragma("vm:prefer-inline")
   factory Future.value([FutureOr<T>? value]) {
     return new _Future<T>.immediate(value == null ? value as T : value);
   }
 
-  /**
-   * Creates a future that completes with an error.
-   *
-   * The created future will be completed with an error in a future microtask.
-   * This allows enough time for someone to add an error handler on the future.
-   * If an error handler isn't added before the future completes, the error
-   * will be considered unhandled.
-   *
-   * Use [Completer] to create a future and complete it later.
-   */
+  /// Creates a future that completes with an error.
+  ///
+  /// The created future will be completed with an error in a future microtask.
+  /// This allows enough time for someone to add an error handler on the future.
+  /// If an error handler isn't added before the future completes, the error
+  /// will be considered unhandled.
+  ///
+  /// Use [Completer] to create a future and complete it later.
   factory Future.error(Object error, [StackTrace? stackTrace]) {
     // TODO(40614): Remove once non-nullability is sound.
     checkNotNullable(error, "error");
@@ -290,31 +278,29 @@
     return new _Future<T>.immediateError(error, stackTrace);
   }
 
-  /**
-   * Creates a future that runs its computation after a delay.
-   *
-   * The [computation] will be executed after the given [duration] has passed,
-   * and the future is completed with the result of the computation.
-   *
-   * If [computation] returns a future,
-   * the future returned by this constructor will complete with the value or
-   * error of that future.
-   *
-   * If the duration is 0 or less,
-   * it completes no sooner than in the next event-loop iteration,
-   * after all microtasks have run.
-   *
-   * If [computation] is omitted,
-   * it will be treated as if [computation] was `() => null`,
-   * and the future will eventually complete with the `null` value.
-   * In that case, [T] must be nullable.
-   *
-   * If calling [computation] throws, the created future will complete with the
-   * error.
-   *
-   * See also [Completer] for a way to create and complete a future at a
-   * later time that isn't necessarily after a known fixed duration.
-   */
+  /// Creates a future that runs its computation after a delay.
+  ///
+  /// The [computation] will be executed after the given [duration] has passed,
+  /// and the future is completed with the result of the computation.
+  ///
+  /// If [computation] returns a future,
+  /// the future returned by this constructor will complete with the value or
+  /// error of that future.
+  ///
+  /// If the duration is 0 or less,
+  /// it completes no sooner than in the next event-loop iteration,
+  /// after all microtasks have run.
+  ///
+  /// If [computation] is omitted,
+  /// it will be treated as if [computation] was `() => null`,
+  /// and the future will eventually complete with the `null` value.
+  /// In that case, [T] must be nullable.
+  ///
+  /// If calling [computation] throws, the created future will complete with the
+  /// error.
+  ///
+  /// See also [Completer] for a way to create and complete a future at a
+  /// later time that isn't necessarily after a known fixed duration.
   factory Future.delayed(Duration duration, [FutureOr<T> computation()?]) {
     if (computation == null && !typeAcceptsNull<T>()) {
       throw ArgumentError.value(
@@ -335,35 +321,33 @@
     return result;
   }
 
-  /**
-   * Waits for multiple futures to complete and collects their results.
-   *
-   * Returns a future which will complete once all the provided futures
-   * have completed, either with their results, or with an error if any
-   * of the provided futures fail.
-   *
-   * The value of the returned future will be a list of all the values that
-   * were produced in the order that the futures are provided by iterating
-   * [futures].
-   *
-   * If any future completes with an error,
-   * then the returned future completes with that error.
-   * If further futures also complete with errors, those errors are discarded.
-   *
-   * If `eagerError` is true, the returned future completes with an error
-   * immediately on the first error from one of the futures. Otherwise all
-   * futures must complete before the returned future is completed (still with
-   * the first error; the remaining errors are silently dropped).
-   *
-   * In the case of an error, [cleanUp] (if provided), is invoked on any
-   * non-null result of successful futures.
-   * This makes it possible to `cleanUp` resources that would otherwise be
-   * lost (since the returned future does not provide access to these values).
-   * The [cleanUp] function is unused if there is no error.
-   *
-   * The call to [cleanUp] should not throw. If it does, the error will be an
-   * uncaught asynchronous error.
-   */
+  /// Waits for multiple futures to complete and collects their results.
+  ///
+  /// Returns a future which will complete once all the provided futures
+  /// have completed, either with their results, or with an error if any
+  /// of the provided futures fail.
+  ///
+  /// The value of the returned future will be a list of all the values that
+  /// were produced in the order that the futures are provided by iterating
+  /// [futures].
+  ///
+  /// If any future completes with an error,
+  /// then the returned future completes with that error.
+  /// If further futures also complete with errors, those errors are discarded.
+  ///
+  /// If `eagerError` is true, the returned future completes with an error
+  /// immediately on the first error from one of the futures. Otherwise all
+  /// futures must complete before the returned future is completed (still with
+  /// the first error; the remaining errors are silently dropped).
+  ///
+  /// In the case of an error, [cleanUp] (if provided), is invoked on any
+  /// non-null result of successful futures.
+  /// This makes it possible to `cleanUp` resources that would otherwise be
+  /// lost (since the returned future does not provide access to these values).
+  /// The [cleanUp] function is unused if there is no error.
+  ///
+  /// The call to [cleanUp] should not throw. If it does, the error will be an
+  /// uncaught asynchronous error.
   @pragma("vm:recognized", "other")
   static Future<List<T>> wait<T>(Iterable<Future<T>> futures,
       {bool eagerError = false, void cleanUp(T successValue)?}) {
@@ -463,17 +447,15 @@
     return _future;
   }
 
-  /**
-   * Returns the result of the first future in [futures] to complete.
-   *
-   * The returned future is completed with the result of the first
-   * future in [futures] to report that it is complete,
-   * whether it's with a value or an error.
-   * The results of all the other futures are discarded.
-   *
-   * If [futures] is empty, or if none of its futures complete,
-   * the returned future never completes.
-   */
+  /// Returns the result of the first future in [futures] to complete.
+  ///
+  /// The returned future is completed with the result of the first
+  /// future in [futures] to report that it is complete,
+  /// whether it's with a value or an error.
+  /// The results of all the other futures are discarded.
+  ///
+  /// If [futures] is empty, or if none of its futures complete,
+  /// the returned future never completes.
   static Future<T> any<T>(Iterable<Future<T>> futures) {
     var completer = new Completer<T>.sync();
     void onValue(T value) {
@@ -490,24 +472,22 @@
     return completer.future;
   }
 
-  /**
-   * Performs an action for each element of the iterable, in turn.
-   *
-   * The [action] may be either synchronous or asynchronous.
-   *
-   * Calls [action] with each element in [elements] in order.
-   * If the call to [action] returns a `Future<T>`, the iteration waits
-   * until the future is completed before continuing with the next element.
-   *
-   * Returns a [Future] that completes with `null` when all elements have been
-   * processed.
-   *
-   * Non-[Future] return values, and completion-values of returned [Future]s,
-   * are discarded.
-   *
-   * Any error from [action], synchronous or asynchronous,
-   * will stop the iteration and be reported in the returned [Future].
-   */
+  /// Performs an action for each element of the iterable, in turn.
+  ///
+  /// The [action] may be either synchronous or asynchronous.
+  ///
+  /// Calls [action] with each element in [elements] in order.
+  /// If the call to [action] returns a `Future<T>`, the iteration waits
+  /// until the future is completed before continuing with the next element.
+  ///
+  /// Returns a [Future] that completes with `null` when all elements have been
+  /// processed.
+  ///
+  /// Non-[Future] return values, and completion-values of returned [Future]s,
+  /// are discarded.
+  ///
+  /// Any error from [action], synchronous or asynchronous,
+  /// will stop the iteration and be reported in the returned [Future].
   static Future forEach<T>(Iterable<T> elements, FutureOr action(T element)) {
     var iterator = elements.iterator;
     return doWhile(() {
@@ -521,28 +501,26 @@
   // Constant `true` function, used as callback by [forEach].
   static bool _kTrue(Object? _) => true;
 
-  /**
-   * Performs an operation repeatedly until it returns `false`.
-   *
-   * The operation, [action], may be either synchronous or asynchronous.
-   *
-   * The operation is called repeatedly as long as it returns either the [bool]
-   * value `true` or a `Future<bool>` which completes with the value `true`.
-   *
-   * If a call to [action] returns `false` or a [Future] that completes to
-   * `false`, iteration ends and the future returned by [doWhile] is completed
-   * with a `null` value.
-   *
-   * If a call to [action] throws or a future returned by [action] completes
-   * with an error, iteration ends and the future returned by [doWhile]
-   * completes with the same error.
-   *
-   * Calls to [action] may happen at any time,
-   * including immediately after calling `doWhile`.
-   * The only restriction is a new call to [action] won't happen before
-   * the previous call has returned, and if it returned a `Future<bool>`, not
-   * until that future has completed.
-   */
+  /// Performs an operation repeatedly until it returns `false`.
+  ///
+  /// The operation, [action], may be either synchronous or asynchronous.
+  ///
+  /// The operation is called repeatedly as long as it returns either the [bool]
+  /// value `true` or a `Future<bool>` which completes with the value `true`.
+  ///
+  /// If a call to [action] returns `false` or a [Future] that completes to
+  /// `false`, iteration ends and the future returned by [doWhile] is completed
+  /// with a `null` value.
+  ///
+  /// If a call to [action] throws or a future returned by [action] completes
+  /// with an error, iteration ends and the future returned by [doWhile]
+  /// completes with the same error.
+  ///
+  /// Calls to [action] may happen at any time,
+  /// including immediately after calling `doWhile`.
+  /// The only restriction is a new call to [action] won't happen before
+  /// the previous call has returned, and if it returned a `Future<bool>`, not
+  /// until that future has completed.
   static Future doWhile(FutureOr<bool> action()) {
     _Future<void> doneSignal = new _Future<void>();
     late void Function(bool) nextIteration;
@@ -574,88 +552,85 @@
     return doneSignal;
   }
 
-  /**
-   * Register callbacks to be called when this future completes.
-   *
-   * When this future completes with a value,
-   * the [onValue] callback will be called with that value.
-   * If this future is already completed, the callback will not be called
-   * immediately, but will be scheduled in a later microtask.
-   *
-   * If [onError] is provided, and this future completes with an error,
-   * the `onError` callback is called with that error and its stack trace.
-   * The `onError` callback must accept either one argument or two arguments
-   * where the latter is a [StackTrace].
-   * If `onError` accepts two arguments,
-   * it is called with both the error and the stack trace,
-   * otherwise it is called with just the error object.
-   * The `onError` callback must return a value or future that can be used
-   * to complete the returned future, so it must be something assignable to
-   * `FutureOr<R>`.
-   *
-   * Returns a new [Future]
-   * which is completed with the result of the call to `onValue`
-   * (if this future completes with a value)
-   * or to `onError` (if this future completes with an error).
-   *
-   * If the invoked callback throws,
-   * the returned future is completed with the thrown error
-   * and a stack trace for the error.
-   * In the case of `onError`,
-   * if the exception thrown is `identical` to the error argument to `onError`,
-   * the throw is considered a rethrow,
-   * and the original stack trace is used instead.
-   *
-   * If the callback returns a [Future],
-   * the future returned by `then` will be completed with
-   * the same result as the future returned by the callback.
-   *
-   * If [onError] is not given, and this future completes with an error,
-   * the error is forwarded directly to the returned future.
-   *
-   * In most cases, it is more readable to use [catchError] separately, possibly
-   * with a `test` parameter, instead of handling both value and error in a
-   * single [then] call.
-   *
-   * Note that futures don't delay reporting of errors until listeners are
-   * added. If the first `then` or `catchError` call happens after this future
-   * has completed with an error then the error is reported as unhandled error.
-   * See the description on [Future].
-   */
+  /// Register callbacks to be called when this future completes.
+  ///
+  /// When this future completes with a value,
+  /// the [onValue] callback will be called with that value.
+  /// If this future is already completed, the callback will not be called
+  /// immediately, but will be scheduled in a later microtask.
+  ///
+  /// If [onError] is provided, and this future completes with an error,
+  /// the `onError` callback is called with that error and its stack trace.
+  /// The `onError` callback must accept either one argument or two arguments
+  /// where the latter is a [StackTrace].
+  /// If `onError` accepts two arguments,
+  /// it is called with both the error and the stack trace,
+  /// otherwise it is called with just the error object.
+  /// The `onError` callback must return a value or future that can be used
+  /// to complete the returned future, so it must be something assignable to
+  /// `FutureOr<R>`.
+  ///
+  /// Returns a new [Future]
+  /// which is completed with the result of the call to `onValue`
+  /// (if this future completes with a value)
+  /// or to `onError` (if this future completes with an error).
+  ///
+  /// If the invoked callback throws,
+  /// the returned future is completed with the thrown error
+  /// and a stack trace for the error.
+  /// In the case of `onError`,
+  /// if the exception thrown is `identical` to the error argument to `onError`,
+  /// the throw is considered a rethrow,
+  /// and the original stack trace is used instead.
+  ///
+  /// If the callback returns a [Future],
+  /// the future returned by `then` will be completed with
+  /// the same result as the future returned by the callback.
+  ///
+  /// If [onError] is not given, and this future completes with an error,
+  /// the error is forwarded directly to the returned future.
+  ///
+  /// In most cases, it is more readable to use [catchError] separately,
+  /// possibly with a `test` parameter,
+  /// instead of handling both value and error in a single [then] call.
+  ///
+  /// Note that futures don't delay reporting of errors until listeners are
+  /// added. If the first `then` or `catchError` call happens
+  /// after this future has completed with an error,
+  /// then the error is reported as unhandled error.
+  /// See the description on [Future].
   Future<R> then<R>(FutureOr<R> onValue(T value), {Function? onError});
 
-  /**
-   * Handles errors emitted by this [Future].
-   *
-   * This is the asynchronous equivalent of a "catch" block.
-   *
-   * Returns a new [Future] that will be completed with either the result of
-   * this future or the result of calling the `onError` callback.
-   *
-   * If this future completes with a value,
-   * the returned future completes with the same value.
-   *
-   * If this future completes with an error,
-   * then [test] is first called with the error value.
-   *
-   * If `test` returns false, the exception is not handled by this `catchError`,
-   * and the returned future completes with the same error and stack trace
-   * as this future.
-   *
-   * If `test` returns `true`,
-   * [onError] is called with the error and possibly stack trace,
-   * and the returned future is completed with the result of this call
-   * in exactly the same way as for [then]'s `onError`.
-   *
-   * If `test` is omitted, it defaults to a function that always returns true.
-   * The `test` function should not throw, but if it does, it is handled as
-   * if the `onError` function had thrown.
-   *
-   * Note that futures don't delay reporting of errors until listeners are
-   * added. If the first `catchError` (or `then`) call happens after this future
-   * has completed with an error then the error is reported as unhandled error.
-   * See the description on [Future].
-   */
+  /// Handles errors emitted by this [Future].
+  ///
+  /// This is the asynchronous equivalent of a "catch" block.
+  ///
+  /// Returns a new [Future] that will be completed with either the result of
+  /// this future or the result of calling the `onError` callback.
+  ///
+  /// If this future completes with a value,
+  /// the returned future completes with the same value.
+  ///
+  /// If this future completes with an error,
+  /// then [test] is first called with the error value.
+  ///
+  /// If `test` returns false, the exception is not handled by this `catchError`,
+  /// and the returned future completes with the same error and stack trace
+  /// as this future.
+  ///
+  /// If `test` returns `true`,
+  /// [onError] is called with the error and possibly stack trace,
+  /// and the returned future is completed with the result of this call
+  /// in exactly the same way as for [then]'s `onError`.
+  ///
+  /// If `test` is omitted, it defaults to a function that always returns true.
+  /// The `test` function should not throw, but if it does, it is handled as
+  /// if the `onError` function had thrown.
+  ///
+  /// Note that futures don't delay reporting of errors until listeners are
+  /// added. If the first `catchError` (or `then`) call happens after this future
+  /// has completed with an error then the error is reported as unhandled error.
+  /// See the description on [Future].
   // The `Function` below stands for one of two types:
   // - (dynamic) -> FutureOr<T>
   // - (dynamic, StackTrace) -> FutureOr<T>
@@ -663,78 +638,146 @@
   // `isCheck` we should also expect functions that take a specific argument.
   Future<T> catchError(Function onError, {bool test(Object error)?});
 
-  /**
-   * Registers a function to be called when this future completes.
-   *
-   * The [action] function is called when this future completes, whether it
-   * does so with a value or with an error.
-   *
-   * This is the asynchronous equivalent of a "finally" block.
-   *
-   * The future returned by this call, `f`, will complete the same way
-   * as this future unless an error occurs in the [action] call, or in
-   * a [Future] returned by the [action] call. If the call to [action]
-   * does not return a future, its return value is ignored.
-   *
-   * If the call to [action] throws, then `f` is completed with the
-   * thrown error.
-   *
-   * If the call to [action] returns a [Future], `f2`, then completion of
-   * `f` is delayed until `f2` completes. If `f2` completes with
-   * an error, that will be the result of `f` too. The value of `f2` is always
-   * ignored.
-   *
-   * This method is equivalent to:
-   *
-   *     Future<T> whenComplete(action()) {
-   *       return this.then((v) {
-   *         var f2 = action();
-   *         if (f2 is Future) return f2.then((_) => v);
-   *         return v
-   *       }, onError: (e) {
-   *         var f2 = action();
-   *         if (f2 is Future) return f2.then((_) { throw e; });
-   *         throw e;
-   *       });
-   *     }
-   */
+  /// Registers a function to be called when this future completes.
+  ///
+  /// The [action] function is called when this future completes, whether it
+  /// does so with a value or with an error.
+  ///
+  /// This is the asynchronous equivalent of a "finally" block.
+  ///
+  /// The future returned by this call, `f`, will complete the same way
+  /// as this future unless an error occurs in the [action] call, or in
+  /// a [Future] returned by the [action] call. If the call to [action]
+  /// does not return a future, its return value is ignored.
+  ///
+  /// If the call to [action] throws, then `f` is completed with the
+  /// thrown error.
+  ///
+  /// If the call to [action] returns a [Future], `f2`, then completion of
+  /// `f` is delayed until `f2` completes. If `f2` completes with
+  /// an error, that will be the result of `f` too. The value of `f2` is always
+  /// ignored.
+  ///
+  /// This method is equivalent to:
+  /// ```dart
+  /// Future<T> whenComplete(action()) {
+  ///   return this.then((v) {
+  ///     var f2 = action();
+  ///     if (f2 is Future) return f2.then((_) => v);
+  ///     return v
+  ///   }, onError: (e) {
+  ///     var f2 = action();
+  ///     if (f2 is Future) return f2.then((_) { throw e; });
+  ///     throw e;
+  ///   });
+  /// }
+  /// ```
   Future<T> whenComplete(FutureOr<void> action());
 
-  /**
-   * Creates a [Stream] containing the result of this future.
-   *
-   * The stream will produce single data or error event containing the
-   * completion result of this future, and then it will close with a
-   * done event.
-   *
-   * If the future never completes, the stream will not produce any events.
-   */
+  /// Creates a [Stream] containing the result of this future.
+  ///
+  /// The stream will produce single data or error event containing the
+  /// completion result of this future, and then it will close with a
+  /// done event.
+  ///
+  /// If the future never completes, the stream will not produce any events.
   Stream<T> asStream();
 
-  /**
-   * Time-out the future computation after [timeLimit] has passed.
-   *
-   * Returns a new future that completes with the same value as this future,
-   * if this future completes in time.
-   *
-   * If this future does not complete before `timeLimit` has passed,
-   * the [onTimeout] action is executed instead, and its result (whether it
-   * returns or throws) is used as the result of the returned future.
-   * The [onTimeout] function must return a [T] or a `Future<T>`.
-   *
-   * If `onTimeout` is omitted, a timeout will cause the returned future to
-   * complete with a [TimeoutException].
-   */
+  /// Time-out the future computation after [timeLimit] has passed.
+  ///
+  /// Returns a new future that completes with the same value as this future,
+  /// if this future completes in time.
+  ///
+  /// If this future does not complete before `timeLimit` has passed,
+  /// the [onTimeout] action is executed instead, and its result (whether it
+  /// returns or throws) is used as the result of the returned future.
+  /// The [onTimeout] function must return a [T] or a `Future<T>`.
+  ///
+  /// If `onTimeout` is omitted, a timeout will cause the returned future to
+  /// complete with a [TimeoutException].
   Future<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()?});
 }
 
-/**
- * Thrown when a scheduled timeout happens while waiting for an async result.
- */
+/// Convenience methods on futures.
+///
+/// Adds functionality to futures which makes it easier to
+/// write well-typed asynchronous code.
+@Since("2.12")
+extension FutureExtensions<T> on Future<T> {
+  /// Handles errors on this future.
+  ///
+  /// Catches errors of type [E] that this future complete with.
+  /// If [test] is supplied, only catches errors of type [E]
+  /// where [test] returns `true`.
+  /// If [E] is [Object], then all errors are potentially caught,
+  /// depending only on a supplied [test].toString()
+  ///
+  /// If the error is caught,
+  /// the returned future completes with the result of calling [handleError]
+  /// with the error and stack trace.
+  /// This result must be a value of the same type that this future
+  /// could otherwise complete with.
+  /// For example, if this future cannot complete with `null`,
+  /// then [handleError] also cannot return `null`.
+  /// Example:
+  /// ```dart
+  /// Future<T> retryOperation<T>(Future<T> operation(), T onFailure()) =>
+  ///     operation().onError<RetryException>((e, s) {
+  ///       if (e.canRetry) {
+  ///         return retryOperation(operation, onFailure);
+  ///       }
+  ///       return onFailure();
+  ///     });
+  /// ```
+  ///
+  /// If [handleError] throws, the returned future completes
+  /// with the thrown error and stack trace,
+  /// except that if it throws the *same* error object again,
+  /// then it is considered a "rethrow"
+  /// and the original stack trace is retained.
+  /// This can be used as an alternative to skipping the
+  /// error in [test].
+  /// Example:
+  /// ```dart
+  /// // Unwraps an an exceptions cause, if it has one.
+  /// someFuture.onError<SomeException>((e, _) {
+  ///   throw e.cause ?? e;
+  /// });
+  /// // vs.
+  /// someFuture.onError<SomeException>((e, _) {
+  ///   throw e.cause!;
+  /// }, test: (e) => e.cause != null);
+  /// ```
+  ///
+  /// If the error is not caught, the returned future
+  /// completes with the same result, value or error,
+  /// as this future.
+  ///
+  /// This method is effectively a more precisely typed version
+  /// of [Future.catchError].
+  /// It makes it easy to catch specific error types,
+  /// and requires a correctly typed error handler function,
+  /// rather than just [Function].
+  /// Because of this, the error handlers must accept
+  /// the stack trace argument.
+  Future<T> onError<E extends Object>(
+      FutureOr<T> handleError(E error, StackTrace stackTrace),
+      {bool test(E error)?}) {
+    // There are various ways to optimize this to avoid the double is E/as E
+    // type check, but for now we are not optimizing the error path.
+    return this.catchError(
+        (Object error, StackTrace stackTrace) =>
+            handleError(error as E, stackTrace),
+        test: (Object error) => error is E && (test == null || test(error)));
+  }
+}
+
+/// Thrown when a scheduled timeout happens while waiting for an async result.
 class TimeoutException implements Exception {
-  /** Description of the cause of the timeout. */
+  /// Description of the cause of the timeout.
   final String? message;
-  /** The duration that was exceeded. */
+
+  /// The duration that was exceeded.
   final Duration? duration;
 
   TimeoutException(this.message, [this.duration]);
@@ -747,183 +790,170 @@
   }
 }
 
-/**
- * A way to produce Future objects and to complete them later
- * with a value or error.
- *
- * Most of the time, the simplest way to create a future is to just use
- * one of the [Future] constructors to capture the result of a single
- * asynchronous computation:
- * ```
- * new Future(() { doSomething(); return result; });
- * ```
- * or, if the future represents the result of a sequence of asynchronous
- * computations, they can be chained using [Future.then] or similar functions
- * on [Future]:
- * ```
- * Future doStuff(){
- *   return someAsyncOperation().then((result) {
- *     return someOtherAsyncOperation(result);
- *   });
- * }
- * ```
- * If you do need to create a Future from scratch — for example,
- * when you're converting a callback-based API into a Future-based
- * one — you can use a Completer as follows:
- * ```
- * class AsyncOperation {
- *   Completer _completer = new Completer();
- *
- *   Future<T> doOperation() {
- *     _startOperation();
- *     return _completer.future; // Send future object back to client.
- *   }
- *
- *   // Something calls this when the value is ready.
- *   void _finishOperation(T result) {
- *     _completer.complete(result);
- *   }
- *
- *   // If something goes wrong, call this.
- *   void _errorHappened(error) {
- *     _completer.completeError(error);
- *   }
- * }
- * ```
- */
+/// A way to produce Future objects and to complete them later
+/// with a value or error.
+///
+/// Most of the time, the simplest way to create a future is to just use
+/// one of the [Future] constructors to capture the result of a single
+/// asynchronous computation:
+/// ```
+/// Future(() { doSomething(); return result; });
+/// ```
+/// or, if the future represents the result of a sequence of asynchronous
+/// computations, they can be chained using [Future.then] or similar functions
+/// on [Future]:
+/// ```
+/// Future doStuff(){
+///   return someAsyncOperation().then((result) {
+///     return someOtherAsyncOperation(result);
+///   });
+/// }
+/// ```
+/// If you do need to create a Future from scratch — for example,
+/// when you're converting a callback-based API into a Future-based
+/// one — you can use a Completer as follows:
+/// ```
+/// class AsyncOperation {
+///   final Completer _completer = new Completer();
+///
+///   Future<T> doOperation() {
+///     _startOperation();
+///     return _completer.future; // Send future object back to client.
+///   }
+///
+///   // Something calls this when the value is ready.
+///   void _finishOperation(T result) {
+///     _completer.complete(result);
+///   }
+///
+///   // If something goes wrong, call this.
+///   void _errorHappened(error) {
+///     _completer.completeError(error);
+///   }
+/// }
+/// ```
 abstract class Completer<T> {
-  /**
-   * Creates a new completer.
-   *
-   * The general workflow for creating a new future is to 1) create a
-   * new completer, 2) hand out its future, and, at a later point, 3) invoke
-   * either [complete] or [completeError].
-   *
-   * The completer completes the future asynchronously. That means that
-   * callbacks registered on the future are not called immediately when
-   * [complete] or [completeError] is called. Instead the callbacks are
-   * delayed until a later microtask.
-   *
-   * Example:
-   * ```
-   * var completer = new Completer();
-   * handOut(completer.future);
-   * later: {
-   *   completer.complete('completion value');
-   * }
-   * ```
-   */
+  /// Creates a new completer.
+  ///
+  /// The general workflow for creating a new future is to 1) create a
+  /// new completer, 2) hand out its future, and, at a later point, 3) invoke
+  /// either [complete] or [completeError].
+  ///
+  /// The completer completes the future asynchronously. That means that
+  /// callbacks registered on the future are not called immediately when
+  /// [complete] or [completeError] is called. Instead the callbacks are
+  /// delayed until a later microtask.
+  ///
+  /// Example:
+  /// ```
+  /// var completer = new Completer();
+  /// handOut(completer.future);
+  /// later: {
+  ///   completer.complete('completion value');
+  /// }
+  /// ```
   factory Completer() => new _AsyncCompleter<T>();
 
-  /**
-   * Completes the future synchronously.
-   *
-   * This constructor should be avoided unless the completion of the future is
-   * known to be the final result of another asynchronous operation. If in doubt
-   * use the default [Completer] constructor.
-   *
-   * Using an normal, asynchronous, completer will never give the wrong
-   * behavior, but using a synchronous completer incorrectly can cause
-   * otherwise correct programs to break.
-   *
-   * A synchronous completer is only intended for optimizing event
-   * propagation when one asynchronous event immediately triggers another.
-   * It should not be used unless the calls to [complete] and [completeError]
-   * are guaranteed to occur in places where it won't break `Future` invariants.
-   *
-   * Completing synchronously means that the completer's future will be
-   * completed immediately when calling the [complete] or [completeError]
-   * method on a synchronous completer, which also calls any callbacks
-   * registered on that future.
-   *
-   * Completing synchronously must not break the rule that when you add a
-   * callback on a future, that callback must not be called until the code
-   * that added the callback has completed.
-   * For that reason, a synchronous completion must only occur at the very end
-   * (in "tail position") of another synchronous event,
-   * because at that point, completing the future immediately is be equivalent
-   * to returning to the event loop and completing the future in the next
-   * microtask.
-   *
-   * Example:
-   *
-   *     var completer = new Completer.sync();
-   *     // The completion is the result of the asynchronous onDone event.
-   *     // No other operation is performed after the completion. It is safe
-   *     // to use the Completer.sync constructor.
-   *     stream.listen(print, onDone: () { completer.complete("done"); });
-   *
-   * Bad example. Do not use this code. Only for illustrative purposes:
-   *
-   *     var completer = new Completer.sync();
-   *     completer.future.then((_) { bar(); });
-   *     // The completion is the result of the asynchronous onDone event.
-   *     // However, there is still code executed after the completion. This
-   *     // operation is *not* safe.
-   *     stream.listen(print, onDone: () {
-   *       completer.complete("done");
-   *       foo();  // In this case, foo() runs after bar().
-   *     });
-   */
+  /// Completes the future synchronously.
+  ///
+  /// This constructor should be avoided unless the completion of the future is
+  /// known to be the final result of another asynchronous operation. If in doubt
+  /// use the default [Completer] constructor.
+  ///
+  /// Using an normal, asynchronous, completer will never give the wrong
+  /// behavior, but using a synchronous completer incorrectly can cause
+  /// otherwise correct programs to break.
+  ///
+  /// A synchronous completer is only intended for optimizing event
+  /// propagation when one asynchronous event immediately triggers another.
+  /// It should not be used unless the calls to [complete] and [completeError]
+  /// are guaranteed to occur in places where it won't break `Future` invariants.
+  ///
+  /// Completing synchronously means that the completer's future will be
+  /// completed immediately when calling the [complete] or [completeError]
+  /// method on a synchronous completer, which also calls any callbacks
+  /// registered on that future.
+  ///
+  /// Completing synchronously must not break the rule that when you add a
+  /// callback on a future, that callback must not be called until the code
+  /// that added the callback has completed.
+  /// For that reason, a synchronous completion must only occur at the very end
+  /// (in "tail position") of another synchronous event,
+  /// because at that point, completing the future immediately is be equivalent
+  /// to returning to the event loop and completing the future in the next
+  /// microtask.
+  ///
+  /// Example:
+  /// ```dart
+  /// var completer = Completer.sync();
+  /// // The completion is the result of the asynchronous onDone event.
+  /// // No other operation is performed after the completion. It is safe
+  /// // to use the Completer.sync constructor.
+  /// stream.listen(print, onDone: () { completer.complete("done"); });
+  /// ```
+  /// Bad example. Do not use this code. Only for illustrative purposes:
+  /// ```dart
+  /// var completer = Completer.sync();
+  /// completer.future.then((_) { bar(); });
+  /// // The completion is the result of the asynchronous onDone event.
+  /// // However, there is still code executed after the completion. This
+  /// // operation is *not* safe.
+  /// stream.listen(print, onDone: () {
+  ///   completer.complete("done");
+  ///   foo();  // In this case, foo() runs after bar().
+  /// });
+  /// ```
   factory Completer.sync() => new _SyncCompleter<T>();
 
-  /**
-   * The future that is completed by this completer.
-   *
-   * The future that is completed when [complete] or [completeError] is called.
-   */
+  /// The future that is completed by this completer.
+  ///
+  /// The future that is completed when [complete] or [completeError] is called.
   Future<T> get future;
 
-  /**
-   * Completes [future] with the supplied values.
-   *
-   * The value must be either a value of type [T]
-   * or a future of type `Future<T>`.
-   * If the value is omitted or null, and `T` is not nullable, the call
-   * to `complete` throws.
-   *
-   * If the value is itself a future, the completer will wait for that future
-   * to complete, and complete with the same result, whether it is a success
-   * or an error.
-   *
-   * Calling [complete] or [completeError] must be done at most once.
-   *
-   * All listeners on the future are informed about the value.
-   */
+  /// Completes [future] with the supplied values.
+  ///
+  /// The value must be either a value of type [T]
+  /// or a future of type `Future<T>`.
+  /// If the value is omitted or `null`, and `T` is not nullable, the call
+  /// to `complete` throws.
+  ///
+  /// If the value is itself a future, the completer will wait for that future
+  /// to complete, and complete with the same result, whether it is a success
+  /// or an error.
+  ///
+  /// Calling [complete] or [completeError] must be done at most once.
+  ///
+  /// All listeners on the future are informed about the value.
   void complete([FutureOr<T>? value]);
 
-  /**
-   * Complete [future] with an error.
-   *
-   * Calling [complete] or [completeError] must be done at most once.
-   *
-   * Completing a future with an error indicates that an exception was thrown
-   * while trying to produce a value.
-   *
-   * If `error` is a `Future`, the future itself is used as the error value.
-   * If you want to complete with the result of the future, you can use:
-   * ```
-   * thisCompleter.complete(theFuture)
-   * ```
-   * or if you only want to handle an error from the future:
-   * ```
-   * theFuture.catchError(thisCompleter.completeError);
-   * ```
-   */
+  /// Complete [future] with an error.
+  ///
+  /// Calling [complete] or [completeError] must be done at most once.
+  ///
+  /// Completing a future with an error indicates that an exception was thrown
+  /// while trying to produce a value.
+  ///
+  /// If `error` is a `Future`, the future itself is used as the error value.
+  /// If you want to complete with the result of the future, you can use:
+  /// ```
+  /// thisCompleter.complete(theFuture)
+  /// ```
+  /// or if you only want to handle an error from the future:
+  /// ```
+  /// theFuture.catchError(thisCompleter.completeError);
+  /// ```
   void completeError(Object error, [StackTrace? stackTrace]);
 
-  /**
-   * Whether the [future] has been completed.
-   *
-   * Reflects whether [complete] or [completeError] has been called.
-   * A `true` value doesn't necessarily mean that listeners of this future
-   * have been invoked yet, either because the completer usually waits until
-   * a later microtask to propagate the result, or because [complete]
-   * was called with a future that hasn't completed yet.
-   *
-   * When this value is `true`, [complete] and [completeError] must not be
-   * called again.
-   */
+  /// Whether the [future] has been completed.
+  ///
+  /// Reflects whether [complete] or [completeError] has been called.
+  /// A `true` value doesn't necessarily mean that listeners of this future
+  /// have been invoked yet, either because the completer usually waits until
+  /// a later microtask to propagate the result, or because [complete]
+  /// was called with a future that hasn't completed yet.
+  ///
+  /// When this value is `true`, [complete] and [completeError] must not be
+  /// called again.
   bool get isCompleted;
 }
 
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 862c871..df8a347 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -4,11 +4,13 @@
 
 part of dart.async;
 
-/** The onValue and onError handlers return either a value or a future */
+/// The onValue and onError handlers return either a value or a future
 typedef FutureOr<T> _FutureOnValue<S, T>(S value);
-/** Test used by [Future.catchError] to handle skip some errors. */
+
+/// Test used by [Future.catchError] to handle skip some errors.
 typedef bool _FutureErrorTest(Object error);
-/** Used by [WhenFuture]. */
+
+/// Used by [WhenFuture].
 typedef dynamic _FutureAction();
 
 abstract class _Completer<T> implements Completer<T> {
@@ -173,6 +175,11 @@
     assert(!handlesError);
     return _zone.run(_whenCompleteAction);
   }
+
+  // Whether the [value] future should be awaited and the [future] completed
+  // with its result, rather than just completing the [future] directly
+  // with the [value].
+  bool shouldChain(Future<dynamic> value) => value is Future<T> || value is! T;
 }
 
 class _Future<T> implements Future<T> {
@@ -197,33 +204,29 @@
   /// The future has been completed with an error result.
   static const int _stateError = 8;
 
-  /** Whether the future is complete, and as what. */
+  /// Whether the future is complete, and as what.
   int _state = _stateIncomplete;
 
-  /**
-   * Zone that the future was completed from.
-   * This is the zone that an error result belongs to.
-   *
-   * Until the future is completed, the field may hold the zone that
-   * listener callbacks used to create this future should be run in.
-   */
+  /// Zone that the future was completed from.
+  /// This is the zone that an error result belongs to.
+  ///
+  /// Until the future is completed, the field may hold the zone that
+  /// listener callbacks used to create this future should be run in.
   final _Zone _zone;
 
-  /**
-   * Either the result, a list of listeners or another future.
-   *
-   * The result of the future is either a value or an error.
-   * A result is only stored when the future has completed.
-   *
-   * The listeners is an internally linked list of [_FutureListener]s.
-   * Listeners are only remembered while the future is not yet complete,
-   * and it is not chained to another future.
-   *
-   * The future is another future that his future is chained to. This future
-   * is waiting for the other future to complete, and when it does, this future
-   * will complete with the same result.
-   * All listeners are forwarded to the other future.
-   */
+  /// Either the result, a list of listeners or another future.
+  ///
+  /// The result of the future is either a value or an error.
+  /// A result is only stored when the future has completed.
+  ///
+  /// The listeners is an internally linked list of [_FutureListener]s.
+  /// Listeners are only remembered while the future is not yet complete,
+  /// and it is not chained to another future.
+  ///
+  /// The future is another future that his future is chained to. This future
+  /// is waiting for the other future to complete, and when it does, this future
+  /// will complete with the same result.
+  /// All listeners are forwarded to the other future.
   @pragma("vm:entry-point")
   var _resultOrListeners;
 
@@ -234,7 +237,7 @@
     _asyncComplete(result);
   }
 
-  /** Creates a future with the value and the specified zone. */
+  /// Creates a future with the value and the specified zone.
   _Future.zoneValue(T value, this._zone) {
     _setValue(value);
   }
@@ -244,7 +247,7 @@
     _asyncCompleteError(error, stackTrace);
   }
 
-  /** Creates a future that is already completed with the value. */
+  /// Creates a future that is already completed with the value.
   _Future.value(T value) : this.zoneValue(value, Zone._current);
 
   bool get _mayComplete => _state == _stateIncomplete;
@@ -457,27 +460,28 @@
     return prev;
   }
 
-  // Take the value (when completed) of source and complete target with that
+  // Take the value (when completed) of source and complete this future with that
   // value (or error). This function could chain all Futures, but is slower
   // for _Future than _chainCoreFuture, so you must use _chainCoreFuture
   // in that case.
-  static void _chainForeignFuture(Future source, _Future target) {
-    assert(!target._isComplete);
+  void _chainForeignFuture(Future source) {
+    assert(!_isComplete);
     assert(source is! _Future);
 
     // Mark the target as chained (and as such half-completed).
-    target._setPendingComplete();
+    _setPendingComplete();
     try {
       source.then((value) {
-        assert(target._isPendingComplete);
-        // The "value" may be another future if the foreign future
-        // implementation is mis-behaving,
-        // so use _complete instead of _completeWithValue.
-        target._clearPendingComplete(); // Clear this first, it's set again.
-        target._complete(value);
+        assert(_isPendingComplete);
+        _clearPendingComplete(); // Clear this first, it's set again.
+        try {
+          _completeWithValue(value as T);
+        } catch (error, stackTrace) {
+          _completeError(error, stackTrace);
+        }
       }, onError: (Object error, StackTrace stackTrace) {
-        assert(target._isPendingComplete);
-        target._completeError(error, stackTrace);
+        assert(_isPendingComplete);
+        _completeError(error, stackTrace);
       });
     } catch (e, s) {
       // This only happens if the `then` call threw synchronously when given
@@ -485,7 +489,7 @@
       // That requires a non-conforming implementation of the Future interface,
       // which should, hopefully, never happen.
       scheduleMicrotask(() {
-        target._completeError(e, s);
+        _completeError(e, s);
       });
     }
   }
@@ -514,7 +518,7 @@
       if (value is _Future<T>) {
         _chainCoreFuture(value, this);
       } else {
-        _chainForeignFuture(value, this);
+        _chainForeignFuture(value);
       }
     } else {
       _FutureListener? listeners = _removeListeners();
@@ -529,7 +533,6 @@
 
   void _completeWithValue(T value) {
     assert(!_isComplete);
-    assert(value is! Future<T>);
 
     _FutureListener? listeners = _removeListeners();
     _setValue(value);
@@ -589,7 +592,7 @@
       return;
     }
     // Just listen on the foreign future. This guarantees an async delay.
-    _chainForeignFuture(value, this);
+    _chainForeignFuture(value);
   }
 
   void _asyncCompleteError(Object error, StackTrace stackTrace) {
@@ -601,10 +604,8 @@
     });
   }
 
-  /**
-   * Propagates the value/error of [source] to its [listeners], executing the
-   * listeners' callbacks.
-   */
+  /// Propagates the value/error of [source] to its [listeners], executing the
+  /// listeners' callbacks.
   static void _propagateToListeners(
       _Future source, _FutureListener? listeners) {
     while (true) {
@@ -630,7 +631,7 @@
         nextListener = listener._nextListener;
       }
 
-      final sourceResult = source._resultOrListeners;
+      final dynamic sourceResult = source._resultOrListeners;
       // Do the actual propagation.
       // Set initial state of listenerHasError and listenerValueOrError. These
       // variables are updated with the outcome of potential callbacks.
@@ -740,9 +741,10 @@
         // If we changed zone, oldZone will not be null.
         if (oldZone != null) Zone._leave(oldZone);
 
-        // If the listener's value is a future we need to chain it. Note that
+        // If the listener's value is a future we *might* need to chain it. Note that
         // this can only happen if there is a callback.
-        if (listenerValueOrError is Future) {
+        if (listenerValueOrError is Future &&
+            listener.shouldChain(listenerValueOrError)) {
           Future chainSource = listenerValueOrError;
           // Shortcut if the chain-source is already completed. Just continue
           // the loop.
@@ -757,7 +759,7 @@
               _chainCoreFuture(chainSource, result);
             }
           } else {
-            _chainForeignFuture(chainSource, result);
+            result._chainForeignFuture(chainSource);
           }
           return;
         }
@@ -840,5 +842,5 @@
       errorHandler,
       "onError",
       "Error handler must accept one Object or one Object and a StackTrace"
-          " as arguments, and return a a valid result");
+          " as arguments, and return a valid result");
 }
diff --git a/sdk/lib/async/schedule_microtask.dart b/sdk/lib/async/schedule_microtask.dart
index 7e2e933..bb6d600 100644
--- a/sdk/lib/async/schedule_microtask.dart
+++ b/sdk/lib/async/schedule_microtask.dart
@@ -12,24 +12,23 @@
   _AsyncCallbackEntry(this.callback);
 }
 
-/** Head of single linked list of pending callbacks. */
+/// Head of single linked list of pending callbacks.
 _AsyncCallbackEntry? _nextCallback;
-/** Tail of single linked list of pending callbacks. */
+
+/// Tail of single linked list of pending callbacks.
 _AsyncCallbackEntry? _lastCallback;
-/**
- * Tail of priority callbacks added by the currently executing callback.
- *
- * Priority callbacks are put at the beginning of the
- * callback queue, so that if one callback schedules more than one
- * priority callback, they are still enqueued in scheduling order.
- */
+
+/// Tail of priority callbacks added by the currently executing callback.
+///
+/// Priority callbacks are put at the beginning of the
+/// callback queue, so that if one callback schedules more than one
+/// priority callback, they are still enqueued in scheduling order.
 _AsyncCallbackEntry? _lastPriorityCallback;
-/**
- * Whether we are currently inside the callback loop.
- *
- * If we are inside the loop, we never need to schedule the loop,
- * even if adding a first element.
- */
+
+/// Whether we are currently inside the callback loop.
+///
+/// If we are inside the loop, we never need to schedule the loop,
+/// even if adding a first element.
 bool _isInCallbackLoop = false;
 
 void _microtaskLoop() {
@@ -57,12 +56,10 @@
   }
 }
 
-/**
- * Schedules a callback to be called as a microtask.
- *
- * The microtask is called after all other currently scheduled
- * microtasks, but as part of the current system event.
- */
+/// Schedules a callback to be called as a microtask.
+///
+/// The microtask is called after all other currently scheduled
+/// microtasks, but as part of the current system event.
 void _scheduleAsyncCallback(_AsyncCallback callback) {
   _AsyncCallbackEntry newEntry = new _AsyncCallbackEntry(callback);
   _AsyncCallbackEntry? lastCallback = _lastCallback;
@@ -77,14 +74,12 @@
   }
 }
 
-/**
- * Schedules a callback to be called before all other currently scheduled ones.
- *
- * This callback takes priority over existing scheduled callbacks.
- * It is only used internally to give higher priority to error reporting.
- *
- * Is always run in the root zone.
- */
+/// Schedules a callback to be called before all other currently scheduled ones.
+///
+/// This callback takes priority over existing scheduled callbacks.
+/// It is only used internally to give higher priority to error reporting.
+///
+/// Is always run in the root zone.
 void _schedulePriorityAsyncCallback(_AsyncCallback callback) {
   if (_nextCallback == null) {
     _scheduleAsyncCallback(callback);
@@ -107,31 +102,29 @@
   }
 }
 
-/**
- * Runs a function asynchronously.
- *
- * Callbacks registered through this function are always executed in order and
- * are guaranteed to run before other asynchronous events (like [Timer] events,
- * or DOM events).
- *
- * **Warning:** it is possible to starve the DOM by registering asynchronous
- * callbacks through this method. For example the following program runs
- * the callbacks without ever giving the Timer callback a chance to execute:
- *
- *     main() {
- *       Timer.run(() { print("executed"); });  // Will never be executed.
- *       foo() {
- *         scheduleMicrotask(foo);  // Schedules [foo] in front of other events.
- *       }
- *       foo();
- *     }
- *
- * ## Other resources
- *
- * * [The Event Loop and Dart](https://dart.dev/articles/event-loop/):
- * Learn how Dart handles the event queue and microtask queue, so you can write
- * better asynchronous code with fewer surprises.
- */
+/// Runs a function asynchronously.
+///
+/// Callbacks registered through this function are always executed in order and
+/// are guaranteed to run before other asynchronous events (like [Timer] events,
+/// or DOM events).
+///
+/// **Warning:** it is possible to starve the DOM by registering asynchronous
+/// callbacks through this method. For example the following program runs
+/// the callbacks without ever giving the Timer callback a chance to execute:
+/// ```dart
+/// main() {
+///   Timer.run(() { print("executed"); });  // Will never be executed.
+///   foo() {
+///     scheduleMicrotask(foo);  // Schedules [foo] in front of other events.
+///   }
+///   foo();
+/// }
+/// ```
+/// ## Other resources
+///
+/// * [The Event Loop and Dart](https://dart.dev/articles/event-loop/):
+/// Learn how Dart handles the event queue and microtask queue, so you can write
+/// better asynchronous code with fewer surprises.
 void scheduleMicrotask(void Function() callback) {
   _Zone currentZone = Zone._current;
   if (identical(_rootZone, currentZone)) {
@@ -151,6 +144,6 @@
 }
 
 class _AsyncRun {
-  /** Schedule the given callback before any other event in the event-loop. */
+  /// Schedule the given callback before any other event in the event-loop.
   external static void _scheduleImmediate(void Function() callback);
 }
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 60f4aa1..f779e02 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -10,114 +10,106 @@
 
 typedef void _TimerCallback();
 
-/**
- * A source of asynchronous data events.
- *
- * A Stream provides a way to receive a sequence of events.
- * Each event is either a data event, also called an *element* of the stream,
- * or an error event, which is a notification that something has failed.
- * When a stream has emitted all its event,
- * a single "done" event will notify the listener that the end has been reached.
- *
- * You [listen] on a stream to make it start generating events,
- * and to set up listeners that receive the events.
- * When you listen, you receive a [StreamSubscription] object
- * which is the active object providing the events,
- * and which can be used to stop listening again,
- * or to temporarily pause events from the subscription.
- *
- * There are two kinds of streams: "Single-subscription" streams and
- * "broadcast" streams.
- *
- * *A single-subscription stream* allows only a single listener during the whole
- * lifetime of the stream.
- * It doesn't start generating events until it has a listener,
- * and it stops sending events when the listener is unsubscribed,
- * even if the source of events could still provide more.
- *
- * Listening twice on a single-subscription stream is not allowed, even after
- * the first subscription has been canceled.
- *
- * Single-subscription streams are generally used for streaming chunks of
- * larger contiguous data like file I/O.
- *
- * *A broadcast stream* allows any number of listeners, and it fires
- * its events when they are ready, whether there are listeners or not.
- *
- * Broadcast streams are used for independent events/observers.
- *
- * If several listeners want to listen to a single subscription stream,
- * use [asBroadcastStream] to create a broadcast stream on top of the
- * non-broadcast stream.
- *
- * On either kind of stream, stream transformations, such as [where] and
- * [skip], return the same type of stream as the one the method was called on,
- * unless otherwise noted.
- *
- * When an event is fired, the listener(s) at that time will receive the event.
- * If a listener is added to a broadcast stream while an event is being fired,
- * that listener will not receive the event currently being fired.
- * If a listener is canceled, it immediately stops receiving events.
- * Listening on a broadcast stream can be treated as listening on a new stream
- * containing only the events that have not yet been emitted when the [listen]
- * call occurs.
- * For example, the [first] getter listens to the stream, then returns the first
- * event that listener receives.
- * This is not necessarily the first even emitted by the stream, but the first
- * of the *remaining* events of the broadcast stream.
- *
- * When the "done" event is fired, subscribers are unsubscribed before
- * receiving the event. After the event has been sent, the stream has no
- * subscribers. Adding new subscribers to a broadcast stream after this point
- * is allowed, but they will just receive a new "done" event as soon
- * as possible.
- *
- * Stream subscriptions always respect "pause" requests. If necessary they need
- * to buffer their input, but often, and preferably, they can simply request
- * their input to pause too.
- *
- * The default implementation of [isBroadcast] returns false.
- * A broadcast stream inheriting from [Stream] must override [isBroadcast]
- * to return `true`.
- */
+/// A source of asynchronous data events.
+///
+/// A Stream provides a way to receive a sequence of events.
+/// Each event is either a data event, also called an *element* of the stream,
+/// or an error event, which is a notification that something has failed.
+/// When a stream has emitted all its event,
+/// a single "done" event will notify the listener that the end has been reached.
+///
+/// You [listen] on a stream to make it start generating events,
+/// and to set up listeners that receive the events.
+/// When you listen, you receive a [StreamSubscription] object
+/// which is the active object providing the events,
+/// and which can be used to stop listening again,
+/// or to temporarily pause events from the subscription.
+///
+/// There are two kinds of streams: "Single-subscription" streams and
+/// "broadcast" streams.
+///
+/// *A single-subscription stream* allows only a single listener during the whole
+/// lifetime of the stream.
+/// It doesn't start generating events until it has a listener,
+/// and it stops sending events when the listener is unsubscribed,
+/// even if the source of events could still provide more.
+///
+/// Listening twice on a single-subscription stream is not allowed, even after
+/// the first subscription has been canceled.
+///
+/// Single-subscription streams are generally used for streaming chunks of
+/// larger contiguous data like file I/O.
+///
+/// *A broadcast stream* allows any number of listeners, and it fires
+/// its events when they are ready, whether there are listeners or not.
+///
+/// Broadcast streams are used for independent events/observers.
+///
+/// If several listeners want to listen to a single subscription stream,
+/// use [asBroadcastStream] to create a broadcast stream on top of the
+/// non-broadcast stream.
+///
+/// On either kind of stream, stream transformations, such as [where] and
+/// [skip], return the same type of stream as the one the method was called on,
+/// unless otherwise noted.
+///
+/// When an event is fired, the listener(s) at that time will receive the event.
+/// If a listener is added to a broadcast stream while an event is being fired,
+/// that listener will not receive the event currently being fired.
+/// If a listener is canceled, it immediately stops receiving events.
+/// Listening on a broadcast stream can be treated as listening on a new stream
+/// containing only the events that have not yet been emitted when the [listen]
+/// call occurs.
+/// For example, the [first] getter listens to the stream, then returns the first
+/// event that listener receives.
+/// This is not necessarily the first even emitted by the stream, but the first
+/// of the *remaining* events of the broadcast stream.
+///
+/// When the "done" event is fired, subscribers are unsubscribed before
+/// receiving the event. After the event has been sent, the stream has no
+/// subscribers. Adding new subscribers to a broadcast stream after this point
+/// is allowed, but they will just receive a new "done" event as soon
+/// as possible.
+///
+/// Stream subscriptions always respect "pause" requests. If necessary they need
+/// to buffer their input, but often, and preferably, they can simply request
+/// their input to pause too.
+///
+/// The default implementation of [isBroadcast] returns false.
+/// A broadcast stream inheriting from [Stream] must override [isBroadcast]
+/// to return `true`.
 abstract class Stream<T> {
   Stream();
 
-  /**
-   * Internal use only. We do not want to promise that Stream stays const.
-   *
-   * If mixins become compatible with const constructors, we may use a
-   * stream mixin instead of extending Stream from a const class.
-   */
+  /// Internal use only. We do not want to promise that Stream stays const.
+  ///
+  /// If mixins become compatible with const constructors, we may use a
+  /// stream mixin instead of extending Stream from a const class.
   const Stream._internal();
 
-  /**
-   * Creates an empty broadcast stream.
-   *
-   * This is a stream which does nothing except sending a done event
-   * when it's listened to.
-   */
+  /// Creates an empty broadcast stream.
+  ///
+  /// This is a stream which does nothing except sending a done event
+  /// when it's listened to.
   const factory Stream.empty() = _EmptyStream<T>;
 
-  /**
-   * Creates a stream which emits a single data event before completing.
-   *
-   * This stream emits a single data event of [value]
-   * and then completes with a done event.
-   *
-   * Example:
-   * ```dart
-   * Future<void> printThings(Stream<String> data) async {
-   *   await for (var x in data) {
-   *     print(x);
-   *   }
-   * }
-   * printThings(Stream<String>.value("ok")); // prints "ok".
-   * ```
-   *
-   * The returned stream is effectively equivalent to one created by
-   * `(() async* { yield value; } ())` or `Future<T>.value(value).asStream()`.
-   */
+  /// Creates a stream which emits a single data event before completing.
+  ///
+  /// This stream emits a single data event of [value]
+  /// and then completes with a done event.
+  ///
+  /// Example:
+  /// ```dart
+  /// Future<void> printThings(Stream<String> data) async {
+  ///   await for (var x in data) {
+  ///     print(x);
+  ///   }
+  /// }
+  /// printThings(Stream<String>.value("ok")); // prints "ok".
+  /// ```
+  ///
+  /// The returned stream is effectively equivalent to one created by
+  /// `(() async* { yield value; } ())` or `Future<T>.value(value).asStream()`.
   @Since("2.5")
   factory Stream.value(T value) =>
       (_AsyncStreamController<T>(null, null, null, null)
@@ -125,30 +117,28 @@
             .._closeUnchecked())
           .stream;
 
-  /**
-   * Creates a stream which emits a single error event before completing.
-   *
-   * This stream emits a single error event of [error] and [stackTrace]
-   * and then completes with a done event.
-   *
-   * Example:
-   * ```dart
-   * Future<void> tryThings(Stream<int> data) async {
-   *   try {
-   *     await for (var x in data) {
-   *       print("Data: $x");
-   *     }
-   *   } catch (e) {
-   *     print(e);
-   *   }
-   * }
-   * tryThings(Stream<int>.error("Error")); // prints "Error".
-   * ```
-   * The returned stream is effectively equivalent to one created by
-   * `Future<T>.error(error, stackTrace).asStream()`, by or
-   * `(() async* { throw error; } ())`, except that you can control the
-   * stack trace as well.
-   */
+  /// Creates a stream which emits a single error event before completing.
+  ///
+  /// This stream emits a single error event of [error] and [stackTrace]
+  /// and then completes with a done event.
+  ///
+  /// Example:
+  /// ```dart
+  /// Future<void> tryThings(Stream<int> data) async {
+  ///   try {
+  ///     await for (var x in data) {
+  ///       print("Data: $x");
+  ///     }
+  ///   } catch (e) {
+  ///     print(e);
+  ///   }
+  /// }
+  /// tryThings(Stream<int>.error("Error")); // prints "Error".
+  /// ```
+  /// The returned stream is effectively equivalent to one created by
+  /// `Future<T>.error(error, stackTrace).asStream()`, by or
+  /// `(() async* { throw error; } ())`, except that you can control the
+  /// stack trace as well.
   @Since("2.5")
   factory Stream.error(Object error, [StackTrace? stackTrace]) {
     // TODO(40614): Remove once non-nullability is sound.
@@ -159,12 +149,10 @@
         .stream;
   }
 
-  /**
-   * Creates a new single-subscription stream from the future.
-   *
-   * When the future completes, the stream will fire one event, either
-   * data or error, and then close with a done-event.
-   */
+  /// Creates a new single-subscription stream from the future.
+  ///
+  /// When the future completes, the stream will fire one event, either
+  /// data or error, and then close with a done-event.
   factory Stream.fromFuture(Future<T> future) {
     // Use the controller's buffering to fill in the value even before
     // the stream has a listener. For a single value, it's not worth it
@@ -181,21 +169,19 @@
     return controller.stream;
   }
 
-  /**
-   * Create a stream from a group of futures.
-   *
-   * The stream reports the results of the futures on the stream in the order
-   * in which the futures complete.
-   * Each future provides either a data event or an error event,
-   * depending on how the future completes.
-   *
-   * If some futures have already completed when `Stream.fromFutures` is called,
-   * their results will be emitted in some unspecified order.
-   *
-   * When all futures have completed, the stream is closed.
-   *
-   * If [futures] is empty, the stream closes as soon as possible.
-   */
+  /// Create a single-subscription stream from a group of futures.
+  ///
+  /// The stream reports the results of the futures on the stream in the order
+  /// in which the futures complete.
+  /// Each future provides either a data event or an error event,
+  /// depending on how the future completes.
+  ///
+  /// If some futures have already completed when `Stream.fromFutures` is called,
+  /// their results will be emitted in some unspecified order.
+  ///
+  /// When all futures have completed, the stream is closed.
+  ///
+  /// If [futures] is empty, the stream closes as soon as possible.
   factory Stream.fromFutures(Iterable<Future<T>> futures) {
     _StreamController<T> controller =
         new _SyncStreamController<T>(null, null, null, null);
@@ -229,109 +215,103 @@
     return controller.stream;
   }
 
-  /**
-   * Creates a single-subscription stream that gets its data from [elements].
-   *
-   * The iterable is iterated when the stream receives a listener, and stops
-   * iterating if the listener cancels the subscription, or if the
-   * [Iterator.moveNext] method returns `false` or throws.
-   * Iteration is suspended while the stream subscription is paused.
-   *
-   * If calling [Iterator.moveNext] on `elements.iterator` throws,
-   * the stream emits that error and then it closes.
-   * If reading [Iterator.current] on `elements.iterator` throws,
-   * the stream emits that error, but keeps iterating.
-   */
+  /// Creates a single-subscription stream that gets its data from [elements].
+  ///
+  /// The iterable is iterated when the stream receives a listener, and stops
+  /// iterating if the listener cancels the subscription, or if the
+  /// [Iterator.moveNext] method returns `false` or throws.
+  /// Iteration is suspended while the stream subscription is paused.
+  ///
+  /// If calling [Iterator.moveNext] on `elements.iterator` throws,
+  /// the stream emits that error and then it closes.
+  /// If reading [Iterator.current] on `elements.iterator` throws,
+  /// the stream emits that error, but keeps iterating.
   factory Stream.fromIterable(Iterable<T> elements) {
     return new _GeneratedStreamImpl<T>(
         () => new _IterablePendingEvents<T>(elements));
   }
 
-  /**
-   * Creates a multi-subscription stream.
-   *
-   * Each time the created stream is listened to,
-   * the [onListen] callback is invoked with a new [MultiStreamController]
-   * which forwards events to the [StreamSubscription]
-   * returned by that [listen] call.
-   *
-   * This allows each listener to be treated as an individual stream.
-   *
-   * The [MultiStreamController] does not support reading its
-   * [StreamController.stream]. Setting its [StreamController.onListen]
-   * has no effect since the [onListen] callback is called instead,
-   * and the [StreamController.onListen] won't be called later.
-   * The controller acts like an asynchronous controller,
-   * but provides extra methods for delivering events synchronously.
-   *
-   * If [isBroadcast] is set to `true`, the returned stream's
-   * [Stream.isBroadcast] will be `true`.
-   * This has no effect on the stream behavior,
-   * it is up to the [onListen] function
-   * to act like a broadcast stream if it claims to be one.
-   *
-   * A multi-subscription stream can behave like any other stream.
-   * If the [onListen] callback throws on every call after the first,
-   * the stream behaves like a single-subscription stream.
-   * If the stream emits the same events to all current listeners,
-   * it behaves like a broadcast stream.
-   *
-   * It can also choose to emit different events to different listeners.
-   * For example, a stream which repeats the most recent
-   * non-`null` event to new listeners, could be implemented as this example:
-   * ```dart
-   * extension StreamRepeatLatestExtension<T extends Object> on Stream<T> {
-   *   Stream<T> repeatLatest() {
-   *     var done = false;
-   *     T? latest = null;
-   *     var currentListeners = <MultiStreamController<T>>{};
-   *     this.listen((event) {
-   *       latest = event;
-   *       for (var listener in [...currentListeners]) listener.addSync(event);
-   *     }, onError: (Object error, StackTrace stack) {
-   *       for (var listener in [...currentListeners]) listener.addErrorSync(error, stack);
-   *     }, onDone: () {
-   *       done = true;
-   *       latest = null;
-   *       for (var listener in currentListeners) listener.closeSync();
-   *       currentListeners.clear();
-   *     });
-   *     return Stream.multi((controller) {
-   *       if (done) {
-   *         controller.close();
-   *         return;
-   *       }
-   *       currentListeners.add(controller);
-   *       var latestValue = latest;
-   *       if (latestValue != null) controller.add(latestValue);
-   *       controller.onCancel = () {
-   *         currentListeners.remove(controller);
-   *       };
-   *     });
-   *   }
-   * }
-   * ```
-   */
+  /// Creates a multi-subscription stream.
+  ///
+  /// Each time the created stream is listened to,
+  /// the [onListen] callback is invoked with a new [MultiStreamController]
+  /// which forwards events to the [StreamSubscription]
+  /// returned by that [listen] call.
+  ///
+  /// This allows each listener to be treated as an individual stream.
+  ///
+  /// The [MultiStreamController] does not support reading its
+  /// [StreamController.stream]. Setting its [StreamController.onListen]
+  /// has no effect since the [onListen] callback is called instead,
+  /// and the [StreamController.onListen] won't be called later.
+  /// The controller acts like an asynchronous controller,
+  /// but provides extra methods for delivering events synchronously.
+  ///
+  /// If [isBroadcast] is set to `true`, the returned stream's
+  /// [Stream.isBroadcast] will be `true`.
+  /// This has no effect on the stream behavior,
+  /// it is up to the [onListen] function
+  /// to act like a broadcast stream if it claims to be one.
+  ///
+  /// A multi-subscription stream can behave like any other stream.
+  /// If the [onListen] callback throws on every call after the first,
+  /// the stream behaves like a single-subscription stream.
+  /// If the stream emits the same events to all current listeners,
+  /// it behaves like a broadcast stream.
+  ///
+  /// It can also choose to emit different events to different listeners.
+  /// For example, a stream which repeats the most recent
+  /// non-`null` event to new listeners, could be implemented as this example:
+  /// ```dart
+  /// extension StreamRepeatLatestExtension<T extends Object> on Stream<T> {
+  ///   Stream<T> repeatLatest() {
+  ///     var done = false;
+  ///     T? latest = null;
+  ///     var currentListeners = <MultiStreamController<T>>{};
+  ///     this.listen((event) {
+  ///       latest = event;
+  ///       for (var listener in [...currentListeners]) listener.addSync(event);
+  ///     }, onError: (Object error, StackTrace stack) {
+  ///       for (var listener in [...currentListeners]) listener.addErrorSync(error, stack);
+  ///     }, onDone: () {
+  ///       done = true;
+  ///       latest = null;
+  ///       for (var listener in currentListeners) listener.closeSync();
+  ///       currentListeners.clear();
+  ///     });
+  ///     return Stream.multi((controller) {
+  ///       if (done) {
+  ///         controller.close();
+  ///         return;
+  ///       }
+  ///       currentListeners.add(controller);
+  ///       var latestValue = latest;
+  ///       if (latestValue != null) controller.add(latestValue);
+  ///       controller.onCancel = () {
+  ///         currentListeners.remove(controller);
+  ///       };
+  ///     });
+  ///   }
+  /// }
+  /// ```
   @Since("2.9")
   factory Stream.multi(void Function(MultiStreamController<T>) onListen,
       {bool isBroadcast = false}) {
     return _MultiStream<T>(onListen, isBroadcast);
   }
 
-  /**
-   * Creates a stream that repeatedly emits events at [period] intervals.
-   *
-   * The event values are computed by invoking [computation]. The argument to
-   * this callback is an integer that starts with 0 and is incremented for
-   * every event.
-   *
-   * The [period] must a non-negative [Duration].
-   *
-   * If [computation] is omitted the event values will all be `null`.
-   *
-   * The [computation] must not be omitted if the event type [T] does not
-   * allow `null` as a value.
-   */
+  /// Creates a stream that repeatedly emits events at [period] intervals.
+  ///
+  /// The event values are computed by invoking [computation]. The argument to
+  /// this callback is an integer that starts with 0 and is incremented for
+  /// every event.
+  ///
+  /// The [period] must a non-negative [Duration].
+  ///
+  /// If [computation] is omitted the event values will all be `null`.
+  ///
+  /// The [computation] must not be omitted if the event type [T] does not
+  /// allow `null` as a value.
   factory Stream.periodic(Duration period,
       [T computation(int computationCount)?]) {
     if (computation == null && !typeAcceptsNull<T>()) {
@@ -381,191 +361,175 @@
     return controller.stream;
   }
 
-  /**
-   * Creates a stream where all events of an existing stream are piped through
-   * a sink-transformation.
-   *
-   * The given [mapSink] closure is invoked when the returned stream is
-   * listened to. All events from the [source] are added into the event sink
-   * that is returned from the invocation. The transformation puts all
-   * transformed events into the sink the [mapSink] closure received during
-   * its invocation. Conceptually the [mapSink] creates a transformation pipe
-   * with the input sink being the returned [EventSink] and the output sink
-   * being the sink it received.
-   *
-   * This constructor is frequently used to build transformers.
-   *
-   * Example use for a duplicating transformer:
-   *
-   *     class DuplicationSink implements EventSink<String> {
-   *       final EventSink<String> _outputSink;
-   *       DuplicationSink(this._outputSink);
-   *
-   *       void add(String data) {
-   *         _outputSink.add(data);
-   *         _outputSink.add(data);
-   *       }
-   *
-   *       void addError(e, [st]) { _outputSink.addError(e, st); }
-   *       void close() { _outputSink.close(); }
-   *     }
-   *
-   *     class DuplicationTransformer extends StreamTransformerBase<String, String> {
-   *       // Some generic types omitted for brevity.
-   *       Stream bind(Stream stream) => new Stream<String>.eventTransformed(
-   *           stream,
-   *           (EventSink sink) => new DuplicationSink(sink));
-   *     }
-   *
-   *     stringStream.transform(new DuplicationTransformer());
-   *
-   * The resulting stream is a broadcast stream if [source] is.
-   */
+  /// Creates a stream where all events of an existing stream are piped through
+  /// a sink-transformation.
+  ///
+  /// The given [mapSink] closure is invoked when the returned stream is
+  /// listened to. All events from the [source] are added into the event sink
+  /// that is returned from the invocation. The transformation puts all
+  /// transformed events into the sink the [mapSink] closure received during
+  /// its invocation. Conceptually the [mapSink] creates a transformation pipe
+  /// with the input sink being the returned [EventSink] and the output sink
+  /// being the sink it received.
+  ///
+  /// This constructor is frequently used to build transformers.
+  ///
+  /// Example use for a duplicating transformer:
+  /// ```dart
+  /// class DuplicationSink implements EventSink<String> {
+  ///   final EventSink<String> _outputSink;
+  ///   DuplicationSink(this._outputSink);
+  ///
+  ///   void add(String data) {
+  ///     _outputSink.add(data);
+  ///     _outputSink.add(data);
+  ///   }
+  ///
+  ///   void addError(e, [st]) { _outputSink.addError(e, st); }
+  ///   void close() { _outputSink.close(); }
+  /// }
+  ///
+  /// class DuplicationTransformer extends StreamTransformerBase<String, String> {
+  ///   // Some generic types omitted for brevity.
+  ///   Stream bind(Stream stream) => Stream<String>.eventTransformed(
+  ///       stream,
+  ///       (EventSink sink) => DuplicationSink(sink));
+  /// }
+  ///
+  /// stringStream.transform(DuplicationTransformer());
+  /// ```
+  /// The resulting stream is a broadcast stream if [source] is.
   factory Stream.eventTransformed(
       Stream<dynamic> source, EventSink<dynamic> mapSink(EventSink<T> sink)) {
     return new _BoundSinkStream(source, mapSink);
   }
 
-  /**
-   * Adapts [source] to be a `Stream<T>`.
-   *
-   * This allows [source] to be used at the new type, but at run-time it
-   * must satisfy the requirements of both the new type and its original type.
-   *
-   * Data events created by the source stream must also be instances of [T].
-   */
+  /// Adapts [source] to be a `Stream<T>`.
+  ///
+  /// This allows [source] to be used at the new type, but at run-time it
+  /// must satisfy the requirements of both the new type and its original type.
+  ///
+  /// Data events created by the source stream must also be instances of [T].
   static Stream<T> castFrom<S, T>(Stream<S> source) =>
       new CastStream<S, T>(source);
 
-  /**
-   * Whether this stream is a broadcast stream.
-   */
+  /// Whether this stream is a broadcast stream.
   bool get isBroadcast => false;
 
-  /**
-   * Returns a multi-subscription stream that produces the same events as this.
-   *
-   * The returned stream will subscribe to this stream when its first
-   * subscriber is added, and will stay subscribed until this stream ends,
-   * or a callback cancels the subscription.
-   *
-   * If [onListen] is provided, it is called with a subscription-like object
-   * that represents the underlying subscription to this stream. It is
-   * possible to pause, resume or cancel the subscription during the call
-   * to [onListen]. It is not possible to change the event handlers, including
-   * using [StreamSubscription.asFuture].
-   *
-   * If [onCancel] is provided, it is called in a similar way to [onListen]
-   * when the returned stream stops having listener. If it later gets
-   * a new listener, the [onListen] function is called again.
-   *
-   * Use the callbacks, for example, for pausing the underlying subscription
-   * while having no subscribers to prevent losing events, or canceling the
-   * subscription when there are no listeners.
-   */
+  /// Returns a multi-subscription stream that produces the same events as this.
+  ///
+  /// The returned stream will subscribe to this stream when its first
+  /// subscriber is added, and will stay subscribed until this stream ends,
+  /// or a callback cancels the subscription.
+  ///
+  /// If [onListen] is provided, it is called with a subscription-like object
+  /// that represents the underlying subscription to this stream. It is
+  /// possible to pause, resume or cancel the subscription during the call
+  /// to [onListen]. It is not possible to change the event handlers, including
+  /// using [StreamSubscription.asFuture].
+  ///
+  /// If [onCancel] is provided, it is called in a similar way to [onListen]
+  /// when the returned stream stops having listener. If it later gets
+  /// a new listener, the [onListen] function is called again.
+  ///
+  /// Use the callbacks, for example, for pausing the underlying subscription
+  /// while having no subscribers to prevent losing events, or canceling the
+  /// subscription when there are no listeners.
   Stream<T> asBroadcastStream(
       {void onListen(StreamSubscription<T> subscription)?,
       void onCancel(StreamSubscription<T> subscription)?}) {
     return new _AsBroadcastStream<T>(this, onListen, onCancel);
   }
 
-  /**
-   * Adds a subscription to this stream.
-   *
-   * Returns a [StreamSubscription] which handles events from this stream using
-   * the provided [onData], [onError] and [onDone] handlers.
-   * The handlers can be changed on the subscription, but they start out
-   * as the provided functions.
-   *
-   * On each data event from this stream, the subscriber's [onData] handler
-   * is called. If [onData] is `null`, nothing happens.
-   *
-   * On errors from this stream, the [onError] handler is called with the
-   * error object and possibly a stack trace.
-   *
-   * The [onError] callback must be of type `void Function(Object error)` or
-   * `void Function(Object error, StackTrace)`.
-   * The function type determines whether [onError] is invoked with a stack
-   * trace argument.
-   * The stack trace argument may be [StackTrace.empty] if this stream received
-   * an error without a stack trace.
-   *
-   * Otherwise it is called with just the error object.
-   * If [onError] is omitted, any errors on this stream are considered unhandled,
-   * and will be passed to the current [Zone]'s error handler.
-   * By default unhandled async errors are treated
-   * as if they were uncaught top-level errors.
-   *
-   * If this stream closes and sends a done event, the [onDone] handler is
-   * called. If [onDone] is `null`, nothing happens.
-   *
-   * If [cancelOnError] is true, the subscription is automatically canceled
-   * when the first error event is delivered. The default is `false`.
-   *
-   * While a subscription is paused, or when it has been canceled,
-   * the subscription doesn't receive events and none of the
-   * event handler functions are called.
-   */
+  /// Adds a subscription to this stream.
+  ///
+  /// Returns a [StreamSubscription] which handles events from this stream using
+  /// the provided [onData], [onError] and [onDone] handlers.
+  /// The handlers can be changed on the subscription, but they start out
+  /// as the provided functions.
+  ///
+  /// On each data event from this stream, the subscriber's [onData] handler
+  /// is called. If [onData] is `null`, nothing happens.
+  ///
+  /// On errors from this stream, the [onError] handler is called with the
+  /// error object and possibly a stack trace.
+  ///
+  /// The [onError] callback must be of type `void Function(Object error)` or
+  /// `void Function(Object error, StackTrace)`.
+  /// The function type determines whether [onError] is invoked with a stack
+  /// trace argument.
+  /// The stack trace argument may be [StackTrace.empty] if this stream received
+  /// an error without a stack trace.
+  ///
+  /// Otherwise it is called with just the error object.
+  /// If [onError] is omitted, any errors on this stream are considered unhandled,
+  /// and will be passed to the current [Zone]'s error handler.
+  /// By default unhandled async errors are treated
+  /// as if they were uncaught top-level errors.
+  ///
+  /// If this stream closes and sends a done event, the [onDone] handler is
+  /// called. If [onDone] is `null`, nothing happens.
+  ///
+  /// If [cancelOnError] is `true`, the subscription is automatically canceled
+  /// when the first error event is delivered. The default is `false`.
+  ///
+  /// While a subscription is paused, or when it has been canceled,
+  /// the subscription doesn't receive events and none of the
+  /// event handler functions are called.
   StreamSubscription<T> listen(void onData(T event)?,
       {Function? onError, void onDone()?, bool? cancelOnError});
 
-  /**
-   * Creates a new stream from this stream that discards some elements.
-   *
-   * The new stream sends the same error and done events as this stream,
-   * but it only sends the data events that satisfy the [test].
-   *
-   * If the [test] function throws, the data event is dropped and the
-   * error is emitted on the returned stream instead.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   * If a broadcast stream is listened to more than once, each subscription
-   * will individually perform the `test`.
-   */
+  /// Creates a new stream from this stream that discards some elements.
+  ///
+  /// The new stream sends the same error and done events as this stream,
+  /// but it only sends the data events that satisfy the [test].
+  ///
+  /// If the [test] function throws, the data event is dropped and the
+  /// error is emitted on the returned stream instead.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
+  /// If a broadcast stream is listened to more than once, each subscription
+  /// will individually perform the `test`.
   Stream<T> where(bool test(T event)) {
     return new _WhereStream<T>(this, test);
   }
 
-  /**
-   * Transforms each element of this stream into a new stream event.
-   *
-   * Creates a new stream that converts each element of this stream
-   * to a new value using the [convert] function, and emits the result.
-   *
-   * For each data event, `o`, in this stream, the returned stream
-   * provides a data event with the value `convert(o)`.
-   * If [convert] throws, the returned stream reports it as an error
-   * event instead.
-   *
-   * Error and done events are passed through unchanged to the returned stream.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   * The [convert] function is called once per data event per listener.
-   * If a broadcast stream is listened to more than once, each subscription
-   * will individually call [convert] on each data event.
-   *
-   * Unlike [transform], this method does not treat the stream as
-   * chunks of a single value. Instead each event is converted independently
-   * of the previous and following events, which may not always be correct.
-   * For example, UTF-8 encoding, or decoding, will give wrong results
-   * if a surrogate pair, or a multibyte UTF-8 encoding, is split into
-   * separate events, and those events are attempted encoded or decoded
-   * independently.
-   */
+  /// Transforms each element of this stream into a new stream event.
+  ///
+  /// Creates a new stream that converts each element of this stream
+  /// to a new value using the [convert] function, and emits the result.
+  ///
+  /// For each data event, `o`, in this stream, the returned stream
+  /// provides a data event with the value `convert(o)`.
+  /// If [convert] throws, the returned stream reports it as an error
+  /// event instead.
+  ///
+  /// Error and done events are passed through unchanged to the returned stream.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
+  /// The [convert] function is called once per data event per listener.
+  /// If a broadcast stream is listened to more than once, each subscription
+  /// will individually call [convert] on each data event.
+  ///
+  /// Unlike [transform], this method does not treat the stream as
+  /// chunks of a single value. Instead each event is converted independently
+  /// of the previous and following events, which may not always be correct.
+  /// For example, UTF-8 encoding, or decoding, will give wrong results
+  /// if a surrogate pair, or a multibyte UTF-8 encoding, is split into
+  /// separate events, and those events are attempted encoded or decoded
+  /// independently.
   Stream<S> map<S>(S convert(T event)) {
     return new _MapStream<T, S>(this, convert);
   }
 
-  /**
-   * Creates a new stream with each data event of this stream asynchronously
-   * mapped to a new event.
-   *
-   * This acts like [map], except that [convert] may return a [Future],
-   * and in that case, this stream waits for that future to complete before
-   * continuing with its result.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   */
+  /// Creates a new stream with each data event of this stream asynchronously
+  /// mapped to a new event.
+  ///
+  /// This acts like [map], except that [convert] may return a [Future],
+  /// and in that case, this stream waits for that future to complete before
+  /// continuing with its result.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
   Stream<E> asyncMap<E>(FutureOr<E> convert(T event)) {
     _StreamControllerBase<E> controller;
     if (isBroadcast) {
@@ -610,24 +574,22 @@
     return controller.stream;
   }
 
-  /**
-   * Transforms each element into a sequence of asynchronous events.
-   *
-   * Returns a new stream and for each event of this stream, do the following:
-   *
-   * * If the event is an error event or a done event, it is emitted directly
-   * by the returned stream.
-   * * Otherwise it is an element. Then the [convert] function is called
-   * with the element as argument to produce a convert-stream for the element.
-   * * If that call throws, the error is emitted on the returned stream.
-   * * If the call returns `null`, no further action is taken for the elements.
-   * * Otherwise, this stream is paused and convert-stream is listened to.
-   * Every data and error event of the convert-stream is emitted on the returned
-   * stream in the order it is produced.
-   * When the convert-stream ends, this stream is resumed.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   */
+  /// Transforms each element into a sequence of asynchronous events.
+  ///
+  /// Returns a new stream and for each event of this stream, do the following:
+  ///
+  /// * If the event is an error event or a done event, it is emitted directly
+  /// by the returned stream.
+  /// * Otherwise it is an element. Then the [convert] function is called
+  /// with the element as argument to produce a convert-stream for the element.
+  /// * If that call throws, the error is emitted on the returned stream.
+  /// * If the call returns `null`, no further action is taken for the elements.
+  /// * Otherwise, this stream is paused and convert-stream is listened to.
+  /// Every data and error event of the convert-stream is emitted on the returned
+  /// stream in the order it is produced.
+  /// When the convert-stream ends, this stream is resumed.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
   Stream<E> asyncExpand<E>(Stream<E>? convert(T event)) {
     _StreamControllerBase<E> controller;
     if (isBroadcast) {
@@ -663,135 +625,125 @@
     return controller.stream;
   }
 
-  /**
-   * Creates a wrapper Stream that intercepts some errors from this stream.
-   *
-   * If this stream sends an error that matches [test], then it is intercepted
-   * by the [onError] function.
-   *
-   * The [onError] callback must be of type `void Function(Object error)` or
-   * `void Function(Object error, StackTrace)`.
-   * The function type determines whether [onError] is invoked with a stack
-   * trace argument.
-   * The stack trace argument may be [StackTrace.empty] if this stream received
-   * an error without a stack trace.
-   *
-   * An asynchronous error `error` is matched by a test function if
-   *`test(error)` returns true. If [test] is omitted, every error is considered
-   * matching.
-   *
-   * If the error is intercepted, the [onError] function can decide what to do
-   * with it. It can throw if it wants to raise a new (or the same) error,
-   * or simply return to make this stream forget the error.
-   * If the received `error` value is thrown again by the [onError] function,
-   * it acts like a `rethrow` and it is emitted along with its original
-   * stack trace, not the stack trace of the `throw` inside [onError].
-   *
-   * If you need to transform an error into a data event, use the more generic
-   * [Stream.transform] to handle the event by writing a data event to
-   * the output sink.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   * If a broadcast stream is listened to more than once, each subscription
-   * will individually perform the `test` and handle the error.
-   */
+  /// Creates a wrapper Stream that intercepts some errors from this stream.
+  ///
+  /// If this stream sends an error that matches [test], then it is intercepted
+  /// by the [onError] function.
+  ///
+  /// The [onError] callback must be of type `void Function(Object error)` or
+  /// `void Function(Object error, StackTrace)`.
+  /// The function type determines whether [onError] is invoked with a stack
+  /// trace argument.
+  /// The stack trace argument may be [StackTrace.empty] if this stream received
+  /// an error without a stack trace.
+  ///
+  /// An asynchronous error `error` is matched by a test function if
+  ///`test(error)` returns true. If [test] is omitted, every error is considered
+  /// matching.
+  ///
+  /// If the error is intercepted, the [onError] function can decide what to do
+  /// with it. It can throw if it wants to raise a new (or the same) error,
+  /// or simply return to make this stream forget the error.
+  /// If the received `error` value is thrown again by the [onError] function,
+  /// it acts like a `rethrow` and it is emitted along with its original
+  /// stack trace, not the stack trace of the `throw` inside [onError].
+  ///
+  /// If you need to transform an error into a data event, use the more generic
+  /// [Stream.transform] to handle the event by writing a data event to
+  /// the output sink.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
+  /// If a broadcast stream is listened to more than once, each subscription
+  /// will individually perform the `test` and handle the error.
   Stream<T> handleError(Function onError, {bool test(error)?}) {
     return new _HandleErrorStream<T>(this, onError, test);
   }
 
-  /**
-   * Transforms each element of this stream into a sequence of elements.
-   *
-   * Returns a new stream where each element of this stream is replaced
-   * by zero or more data events.
-   * The event values are provided as an [Iterable] by a call to [convert]
-   * with the element as argument, and the elements of that iterable is
-   * emitted in iteration order.
-   * If calling [convert] throws, or if the iteration of the returned values
-   * throws, the error is emitted on the returned stream and iteration ends
-   * for that element of this stream.
-   *
-   * Error events and the done event of this stream are forwarded directly
-   * to 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
-   * will individually call `convert` and expand the events.
-   */
+  /// Transforms each element of this stream into a sequence of elements.
+  ///
+  /// Returns a new stream where each element of this stream is replaced
+  /// by zero or more data events.
+  /// The event values are provided as an [Iterable] by a call to [convert]
+  /// with the element as argument, and the elements of that iterable is
+  /// emitted in iteration order.
+  /// If calling [convert] throws, or if the iteration of the returned values
+  /// throws, the error is emitted on the returned stream and iteration ends
+  /// for that element of this stream.
+  ///
+  /// Error events and the done event of this stream are forwarded directly
+  /// to 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
+  /// will individually call `convert` and expand the events.
   Stream<S> expand<S>(Iterable<S> convert(T element)) {
     return new _ExpandStream<T, S>(this, convert);
   }
 
-  /**
-   * Pipes the events of this stream into [streamConsumer].
-   *
-   * All events of this stream are added to `streamConsumer` using
-   * [StreamConsumer.addStream].
-   * The `streamConsumer` is closed when this stream has been successfully added
-   * to it - when the future returned by `addStream` completes without an error.
-   *
-   * Returns a future which completes when this stream has been consumed
-   * and the consumer has been closed.
-   *
-   * The returned future completes with the same result as the future returned
-   * by [StreamConsumer.close].
-   * If the call to [StreamConsumer.addStream] fails in some way, this
-   * method fails in the same way.
-   */
+  /// Pipes the events of this stream into [streamConsumer].
+  ///
+  /// All events of this stream are added to `streamConsumer` using
+  /// [StreamConsumer.addStream].
+  /// The `streamConsumer` is closed when this stream has been successfully added
+  /// to it - when the future returned by `addStream` completes without an error.
+  ///
+  /// Returns a future which completes when this stream has been consumed
+  /// and the consumer has been closed.
+  ///
+  /// The returned future completes with the same result as the future returned
+  /// by [StreamConsumer.close].
+  /// If the call to [StreamConsumer.addStream] fails in some way, this
+  /// method fails in the same way.
   Future pipe(StreamConsumer<T> streamConsumer) {
     return streamConsumer.addStream(this).then((_) => streamConsumer.close());
   }
 
-  /**
-   * Applies [streamTransformer] to this stream.
-   *
-   * Returns the transformed stream,
-   * that is, the result of `streamTransformer.bind(this)`.
-   * This method simply allows writing the call to `streamTransformer.bind`
-   * in a chained fashion, like
-   * ```
-   * stream.map(mapping).transform(transformation).toList()
-   * ```
-   * which can be more convenient than calling `bind` directly.
-   *
-   * The [streamTransformer] can return any stream.
-   * Whether the returned stream is a broadcast stream or not,
-   * and which elements it will contain,
-   * is entirely up to the transformation.
-   *
-   * This method should always be used for transformations which treat
-   * the entire stream as representing a single value
-   * which has perhaps been split into several parts for transport,
-   * like a file being read from disk or being fetched over a network.
-   * The transformation will then produce a new stream which
-   * transforms the stream's value incrementally (perhaps using
-   * [Converter.startChunkedConversion]). The resulting stream
-   * may again be chunks of the result, but does not have to
-   * correspond to specific events from the source string.
-   */
+  /// Applies [streamTransformer] to this stream.
+  ///
+  /// Returns the transformed stream,
+  /// that is, the result of `streamTransformer.bind(this)`.
+  /// This method simply allows writing the call to `streamTransformer.bind`
+  /// in a chained fashion, like
+  /// ```
+  /// stream.map(mapping).transform(transformation).toList()
+  /// ```
+  /// which can be more convenient than calling `bind` directly.
+  ///
+  /// The [streamTransformer] can return any stream.
+  /// Whether the returned stream is a broadcast stream or not,
+  /// and which elements it will contain,
+  /// is entirely up to the transformation.
+  ///
+  /// This method should always be used for transformations which treat
+  /// the entire stream as representing a single value
+  /// which has perhaps been split into several parts for transport,
+  /// like a file being read from disk or being fetched over a network.
+  /// The transformation will then produce a new stream which
+  /// transforms the stream's value incrementally (perhaps using
+  /// [Converter.startChunkedConversion]). The resulting stream
+  /// may again be chunks of the result, but does not have to
+  /// correspond to specific events from the source string.
   Stream<S> transform<S>(StreamTransformer<T, S> streamTransformer) {
     return streamTransformer.bind(this);
   }
 
-  /**
-   * Combines a sequence of values by repeatedly applying [combine].
-   *
-   * Similar to [Iterable.reduce], this function maintains a value,
-   * starting with the first element of this stream
-   * and updated for each further element of this stream.
-   * For each element after the first,
-   * the value is updated to the result of calling [combine]
-   * with the previous value and the element.
-   *
-   * When this stream is done, the returned future is completed with
-   * the value at that time.
-   *
-   * If this stream is empty, the returned future is completed with
-   * an error.
-   * If this stream emits an error, or the call to [combine] throws,
-   * the returned future is completed with that error,
-   * and processing is stopped.
-   */
+  /// Combines a sequence of values by repeatedly applying [combine].
+  ///
+  /// Similar to [Iterable.reduce], this function maintains a value,
+  /// starting with the first element of this stream
+  /// and updated for each further element of this stream.
+  /// For each element after the first,
+  /// the value is updated to the result of calling [combine]
+  /// with the previous value and the element.
+  ///
+  /// When this stream is done, the returned future is completed with
+  /// the value at that time.
+  ///
+  /// If this stream is empty, the returned future is completed with
+  /// an error.
+  /// If this stream emits an error, or the call to [combine] throws,
+  /// the returned future is completed with that error,
+  /// and processing is stopped.
   Future<T> reduce(T combine(T previous, T element)) {
     _Future<T> result = new _Future<T>();
     bool seenFirst = false;
@@ -824,23 +776,21 @@
     return result;
   }
 
-  /**
-   * Combines a sequence of values by repeatedly applying [combine].
-   *
-   * Similar to [Iterable.fold], this function maintains a value,
-   * starting with [initialValue] and updated for each element of
-   * this stream.
-   * For each element, the value is updated to the result of calling
-   * [combine] with the previous value and the element.
-   *
-   * When this stream is done, the returned future is completed with
-   * the value at that time.
-   * For an empty stream, the future is completed with [initialValue].
-   *
-   * If this stream emits an error, or the call to [combine] throws,
-   * the returned future is completed with that error,
-   * and processing is stopped.
-   */
+  /// Combines a sequence of values by repeatedly applying [combine].
+  ///
+  /// Similar to [Iterable.fold], this function maintains a value,
+  /// starting with [initialValue] and updated for each element of
+  /// this stream.
+  /// For each element, the value is updated to the result of calling
+  /// [combine] with the previous value and the element.
+  ///
+  /// When this stream is done, the returned future is completed with
+  /// the value at that time.
+  /// For an empty stream, the future is completed with [initialValue].
+  ///
+  /// If this stream emits an error, or the call to [combine] throws,
+  /// the returned future is completed with that error,
+  /// and processing is stopped.
   Future<S> fold<S>(S initialValue, S combine(S previous, T element)) {
     _Future<S> result = new _Future<S>();
     S value = initialValue;
@@ -856,20 +806,18 @@
     return result;
   }
 
-  /**
-   * Combines the string representation of elements into a single string.
-   *
-   * Each element is converted to a string using its [Object.toString] method.
-   * If [separator] is provided, it is inserted between element string
-   * representations.
-   *
-   * The returned future is completed with the combined string when this stream
-   * is done.
-   *
-   * If this stream emits an error, or the call to [Object.toString] throws,
-   * the returned future is completed with that error,
-   * and processing stops.
-   */
+  /// Combines the string representation of elements into a single string.
+  ///
+  /// Each element is converted to a string using its [Object.toString] method.
+  /// If [separator] is provided, it is inserted between element string
+  /// representations.
+  ///
+  /// The returned future is completed with the combined string when this stream
+  /// is done.
+  ///
+  /// If this stream emits an error, or the call to [Object.toString] throws,
+  /// the returned future is completed with that error,
+  /// and processing stops.
   Future<String> join([String separator = ""]) {
     _Future<String> result = new _Future<String>();
     StringBuffer buffer = new StringBuffer();
@@ -900,18 +848,16 @@
     return result;
   }
 
-  /**
-   * Returns whether [needle] occurs in the elements provided by this stream.
-   *
-   * Compares each element of this stream to [needle] using [Object.==].
-   * If an equal element is found, the returned future is completed with `true`.
-   * If this stream ends without finding a match, the future is completed with
-   * `false`.
-   *
-   * If this stream emits an error, or the call to [Object.==] throws,
-   * the returned future is completed with that error,
-   * and processing stops.
-   */
+  /// Returns whether [needle] occurs in the elements provided by this stream.
+  ///
+  /// Compares each element of this stream to [needle] using [Object.==].
+  /// If an equal element is found, the returned future is completed with `true`.
+  /// If this stream ends without finding a match, the future is completed with
+  /// `false`.
+  ///
+  /// If this stream emits an error, or the call to [Object.==] throws,
+  /// the returned future is completed with that error,
+  /// and processing stops.
   Future<bool> contains(Object? needle) {
     _Future<bool> future = new _Future<bool>();
     StreamSubscription<T> subscription =
@@ -928,16 +874,14 @@
     return future;
   }
 
-  /**
-   * Executes [action] on each element of this stream.
-   *
-   * Completes the returned [Future] when all elements of this stream
-   * have been processed.
-   *
-   * If this stream emits an error, or if the call to [action] throws,
-   * the returned future completes with that error,
-   * and processing stops.
-   */
+  /// Executes [action] on each element of this stream.
+  ///
+  /// Completes the returned [Future] when all elements of this stream
+  /// have been processed.
+  ///
+  /// If this stream emits an error, or if the call to [action] throws,
+  /// the returned future completes with that error,
+  /// and processing stops.
   Future forEach(void action(T element)) {
     _Future future = new _Future();
     StreamSubscription<T> subscription =
@@ -951,20 +895,18 @@
     return future;
   }
 
-  /**
-   * Checks whether [test] accepts all elements provided by this stream.
-   *
-   * Calls [test] on each element of this stream.
-   * If the call returns `false`, the returned future is completed with `false`
-   * and processing stops.
-   *
-   * If this stream ends without finding an element that [test] rejects,
-   * the returned future is completed with `true`.
-   *
-   * If this stream emits an error, or if the call to [test] throws,
-   * the returned future is completed with that error,
-   * and processing stops.
-   */
+  /// Checks whether [test] accepts all elements provided by this stream.
+  ///
+  /// Calls [test] on each element of this stream.
+  /// If the call returns `false`, the returned future is completed with `false`
+  /// and processing stops.
+  ///
+  /// If this stream ends without finding an element that [test] rejects,
+  /// the returned future is completed with `true`.
+  ///
+  /// If this stream emits an error, or if the call to [test] throws,
+  /// the returned future is completed with that error,
+  /// and processing stops.
   Future<bool> every(bool test(T element)) {
     _Future<bool> future = new _Future<bool>();
     StreamSubscription<T> subscription =
@@ -981,20 +923,18 @@
     return future;
   }
 
-  /**
-   * Checks whether [test] accepts any element provided by this stream.
-   *
-   * Calls [test] on each element of this stream.
-   * If the call returns `true`, the returned future is completed with `true`
-   * and processing stops.
-   *
-   * If this stream ends without finding an element that [test] accepts,
-   * the returned future is completed with `false`.
-   *
-   * If this stream emits an error, or if the call to [test] throws,
-   * the returned future is completed with that error,
-   * and processing stops.
-   */
+  /// Checks whether [test] accepts any element provided by this stream.
+  ///
+  /// Calls [test] on each element of this stream.
+  /// If the call returns `true`, the returned future is completed with `true`
+  /// and processing stops.
+  ///
+  /// If this stream ends without finding an element that [test] accepts,
+  /// the returned future is completed with `false`.
+  ///
+  /// If this stream emits an error, or if the call to [test] throws,
+  /// the returned future is completed with that error,
+  /// and processing stops.
   Future<bool> any(bool test(T element)) {
     _Future<bool> future = new _Future<bool>();
     StreamSubscription<T> subscription =
@@ -1011,19 +951,17 @@
     return future;
   }
 
-  /**
-   * The number of elements in this stream.
-   *
-   * Waits for all elements of this stream. When this stream ends,
-   * the returned future is completed with the number of elements.
-   *
-   * If this stream emits an error,
-   * the returned future is completed with that error,
-   * and processing stops.
-   *
-   * This operation listens to this stream, and a non-broadcast stream cannot
-   * be reused after finding its length.
-   */
+  /// The number of elements in this stream.
+  ///
+  /// Waits for all elements of this stream. When this stream ends,
+  /// the returned future is completed with the number of elements.
+  ///
+  /// If this stream emits an error,
+  /// the returned future is completed with that error,
+  /// and processing stops.
+  ///
+  /// This operation listens to this stream, and a non-broadcast stream cannot
+  /// be reused after finding its length.
   Future<int> get length {
     _Future<int> future = new _Future<int>();
     int count = 0;
@@ -1039,20 +977,18 @@
     return future;
   }
 
-  /**
-   * Whether this stream contains any elements.
-   *
-   * Waits for the first element of this stream, then completes the returned
-   * future with `false`.
-   * If this stream ends without emitting any elements, the returned future is
-   * completed with `true`.
-   *
-   * If the first event is an error, the returned future is completed with that
-   * error.
-   *
-   * This operation listens to this stream, and a non-broadcast stream cannot
-   * be reused after checking whether it is empty.
-   */
+  /// Whether this stream contains any elements.
+  ///
+  /// Waits for the first element of this stream, then completes the returned
+  /// future with `false`.
+  /// If this stream ends without emitting any elements, the returned future is
+  /// completed with `true`.
+  ///
+  /// If the first event is an error, the returned future is completed with that
+  /// error.
+  ///
+  /// This operation listens to this stream, and a non-broadcast stream cannot
+  /// be reused after checking whether it is empty.
   Future<bool> get isEmpty {
     _Future<bool> future = new _Future<bool>();
     StreamSubscription<T> subscription =
@@ -1065,24 +1001,21 @@
     return future;
   }
 
-  /**
-   * Adapt this stream to be a `Stream<R>`.
-   *
-   * This stream is wrapped as a `Stream<R>` which checks at run-time that
-   * each data event emitted by this stream is also an instance of [R].
-   */
+  /// Adapt this stream to be a `Stream<R>`.
+  ///
+  /// This stream is wrapped as a `Stream<R>` which checks at run-time that
+  /// each data event emitted by this stream is also an instance of [R].
   Stream<R> cast<R>() => Stream.castFrom<T, R>(this);
-  /**
-   * Collects all elements of this stream in a [List].
-   *
-   * Creates a `List<T>` and adds all elements of this stream to the list
-   * in the order they arrive.
-   * When this stream ends, the returned future is completed with that list.
-   *
-   * If this stream emits an error,
-   * the returned future is completed with that error,
-   * and processing stops.
-   */
+
+  /// Collects all elements of this stream in a [List].
+  ///
+  /// Creates a `List<T>` and adds all elements of this stream to the list
+  /// in the order they arrive.
+  /// When this stream ends, the returned future is completed with that list.
+  ///
+  /// If this stream emits an error,
+  /// the returned future is completed with that error,
+  /// and processing stops.
   Future<List<T>> toList() {
     List<T> result = <T>[];
     _Future<List<T>> future = new _Future<List<T>>();
@@ -1098,23 +1031,21 @@
     return future;
   }
 
-  /**
-   * Collects the data of this stream in a [Set].
-   *
-   * Creates a `Set<T>` and adds all elements of this stream to the set.
-   * in the order they arrive.
-   * When this stream ends, the returned future is completed with that set.
-   *
-   * The returned set is the same type as returned by `new Set<T>()`.
-   * If another type of set is needed, either use [forEach] to add each
-   * element to the set, or use
-   * `toList().then((list) => new SomeOtherSet.from(list))`
-   * to create the set.
-   *
-   * If this stream emits an error,
-   * the returned future is completed with that error,
-   * and processing stops.
-   */
+  /// Collects the data of this stream in a [Set].
+  ///
+  /// Creates a `Set<T>` and adds all elements of this stream to the set.
+  /// in the order they arrive.
+  /// When this stream ends, the returned future is completed with that set.
+  ///
+  /// The returned set is the same type as created by `<T>{}`.
+  /// If another type of set is needed, either use [forEach] to add each
+  /// element to the set, or use
+  /// `toList().then((list) => new SomeOtherSet.from(list))`
+  /// to create the set.
+  ///
+  /// If this stream emits an error,
+  /// the returned future is completed with that error,
+  /// and processing stops.
   Future<Set<T>> toSet() {
     Set<T> result = new Set<T>();
     _Future<Set<T>> future = new _Future<Set<T>>();
@@ -1130,22 +1061,20 @@
     return future;
   }
 
-  /**
-   * Discards all data on this stream, but signals when it is done or an error
-   * occurred.
-   *
-   * When subscribing using [drain], cancelOnError will be true. This means
-   * that the future will complete with the first error on this stream and then
-   * cancel the subscription.
-   *
-   * If this stream emits an error, the returned future is completed with
-   * that error, and processing is stopped.
-   *
-   * In case of a `done` event the future completes with the given
-   * [futureValue].
-   *
-   * The [futureValue] must not be omitted if `null` is not assignable to [E].
-   */
+  /// Discards all data on this stream, but signals when it is done or an error
+  /// occurred.
+  ///
+  /// When subscribing using [drain], cancelOnError will be true. This means
+  /// that the future will complete with the first error on this stream and then
+  /// cancel the subscription.
+  ///
+  /// If this stream emits an error, the returned future is completed with
+  /// that error, and processing is stopped.
+  ///
+  /// In case of a `done` event the future completes with the given
+  /// [futureValue].
+  ///
+  /// The [futureValue] must not be omitted if `null` is not assignable to [E].
   Future<E> drain<E>([E? futureValue]) {
     if (futureValue == null) {
       futureValue = futureValue as E;
@@ -1153,141 +1082,129 @@
     return listen(null, cancelOnError: true).asFuture<E>(futureValue);
   }
 
-  /**
-   * Provides at most the first [count] data events of this stream.
-   *
-   * Returns a stream that emits the same events that this stream would
-   * if listened to at the same time,
-   * until either this stream ends or it has emitted [count] data events,
-   * at which point the returned stream is done.
-   *
-   * If this stream produces fewer than [count] data events before it's done,
-   * so will the returned stream.
-   *
-   * Starts listening to this stream when the returned stream is listened to
-   * and stops listening when the first [count] data events have been received.
-   *
-   * This means that if this is a single-subscription (non-broadcast) streams
-   * it cannot be reused after the returned stream has been listened to.
-   *
-   * If this is a broadcast stream, the returned stream is a broadcast stream.
-   * In that case, the events are only counted from the time
-   * the returned stream is listened to.
-   */
+  /// Provides at most the first [count] data events of this stream.
+  ///
+  /// Returns a stream that emits the same events that this stream would
+  /// if listened to at the same time,
+  /// until either this stream ends or it has emitted [count] data events,
+  /// at which point the returned stream is done.
+  ///
+  /// If this stream produces fewer than [count] data events before it's done,
+  /// so will the returned stream.
+  ///
+  /// Starts listening to this stream when the returned stream is listened to
+  /// and stops listening when the first [count] data events have been received.
+  ///
+  /// This means that if this is a single-subscription (non-broadcast) streams
+  /// it cannot be reused after the returned stream has been listened to.
+  ///
+  /// If this is a broadcast stream, the returned stream is a broadcast stream.
+  /// In that case, the events are only counted from the time
+  /// the returned stream is listened to.
   Stream<T> take(int count) {
     return new _TakeStream<T>(this, count);
   }
 
-  /**
-   * Forwards data events while [test] is successful.
-   *
-   * Returns a stream that provides the same events as this stream
-   * until [test] fails for a data event.
-   * The returned stream is done when either this stream is done,
-   * or when this stream first emits a data event that fails [test].
-   *
-   * The `test` call is considered failing if it returns a non-`true` value
-   * or if it throws. If the `test` call throws, the error is emitted as the
-   * last event on the returned streams.
-   *
-   * Stops listening to this stream after the accepted elements.
-   *
-   * Internally the method cancels its subscription after these elements. This
-   * means that single-subscription (non-broadcast) streams are closed and
-   * cannot be reused after a call to this method.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   * For a broadcast stream, the events are only tested from the time
-   * the returned stream is listened to.
-   */
+  /// Forwards data events while [test] is successful.
+  ///
+  /// Returns a stream that provides the same events as this stream
+  /// until [test] fails for a data event.
+  /// The returned stream is done when either this stream is done,
+  /// or when this stream first emits a data event that fails [test].
+  ///
+  /// The `test` call is considered failing if it returns a non-`true` value
+  /// or if it throws. If the `test` call throws, the error is emitted as the
+  /// last event on the returned streams.
+  ///
+  /// Stops listening to this stream after the accepted elements.
+  ///
+  /// Internally the method cancels its subscription after these elements. This
+  /// means that single-subscription (non-broadcast) streams are closed and
+  /// cannot be reused after a call to this method.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
+  /// For a broadcast stream, the events are only tested from the time
+  /// the returned stream is listened to.
   Stream<T> takeWhile(bool test(T element)) {
     return new _TakeWhileStream<T>(this, test);
   }
 
-  /**
-   * Skips the first [count] data events from this stream.
-   *
-   * Returns a stream that emits the same events as this stream would
-   * if listened to at the same time, except that the first [count]
-   * data events are not emitted.
-   * The returned stream is done when this stream is.
-   *
-   * If this stream emits fewer than [count] data events
-   * before being done, the returned stream emits no data events.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   * For a broadcast stream, the events are only counted from the time
-   * the returned stream is listened to.
-   */
+  /// Skips the first [count] data events from this stream.
+  ///
+  /// Returns a stream that emits the same events as this stream would
+  /// if listened to at the same time, except that the first [count]
+  /// data events are not emitted.
+  /// The returned stream is done when this stream is.
+  ///
+  /// If this stream emits fewer than [count] data events
+  /// before being done, the returned stream emits no data events.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
+  /// For a broadcast stream, the events are only counted from the time
+  /// the returned stream is listened to.
   Stream<T> skip(int count) {
     return new _SkipStream<T>(this, count);
   }
 
-  /**
-   * Skip data events from this stream while they are matched by [test].
-   *
-   * Returns a stream that emits the same events as this stream,
-   * except that data events are not emitted until a data event fails `test`.
-   * The test fails when called with a data event
-   * if it returns a non-`true` value or if the call to `test` throws.
-   * If the call throws, the error is emitted as an error event
-   * on the returned stream instead of the data event,
-   * otherwise the event that made `test` return non-true is emitted as the
-   * first data event.
-   *
-   * Error and done events are provided by the returned stream unmodified.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   * For a broadcast stream, the events are only tested from the time
-   * the returned stream is listened to.
-   */
+  /// Skip data events from this stream while they are matched by [test].
+  ///
+  /// Returns a stream that emits the same events as this stream,
+  /// except that data events are not emitted until a data event fails `test`.
+  /// The test fails when called with a data event
+  /// if it returns a non-`true` value or if the call to `test` throws.
+  /// If the call throws, the error is emitted as an error event
+  /// on the returned stream instead of the data event,
+  /// otherwise the event that made `test` return non-true is emitted as the
+  /// first data event.
+  ///
+  /// Error and done events are provided by the returned stream unmodified.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
+  /// For a broadcast stream, the events are only tested from the time
+  /// the returned stream is listened to.
   Stream<T> skipWhile(bool test(T element)) {
     return new _SkipWhileStream<T>(this, test);
   }
 
-  /**
-   * Skips data events if they are equal to the previous data event.
-   *
-   * The returned stream provides the same events as this stream, except
-   * that it never provides two consecutive data events that are equal.
-   * That is, errors are passed through to the returned stream, and
-   * data events are passed through if they are distinct from the most
-   * recently emitted data event.
-   *
-   * Equality is determined by the provided [equals] method. If that is
-   * omitted, the '==' operator on the last provided data element is used.
-   *
-   * If [equals] throws, the data event is replaced by an error event
-   * containing the thrown error. The behavior is equivalent to the
-   * original stream emitting the error event, and it doesn't change
-   * the what the most recently emitted data event is.
-   *
-   * The returned stream is a broadcast stream if this stream is.
-   * If a broadcast stream is listened to more than once, each subscription
-   * will individually perform the `equals` test.
-   */
+  /// Skips data events if they are equal to the previous data event.
+  ///
+  /// The returned stream provides the same events as this stream, except
+  /// that it never provides two consecutive data events that are equal.
+  /// That is, errors are passed through to the returned stream, and
+  /// data events are passed through if they are distinct from the most
+  /// recently emitted data event.
+  ///
+  /// Equality is determined by the provided [equals] method. If that is
+  /// omitted, the '==' operator on the last provided data element is used.
+  ///
+  /// If [equals] throws, the data event is replaced by an error event
+  /// containing the thrown error. The behavior is equivalent to the
+  /// original stream emitting the error event, and it doesn't change
+  /// the what the most recently emitted data event is.
+  ///
+  /// The returned stream is a broadcast stream if this stream is.
+  /// If a broadcast stream is listened to more than once, each subscription
+  /// will individually perform the `equals` test.
   Stream<T> distinct([bool equals(T previous, T next)?]) {
     return new _DistinctStream<T>(this, equals);
   }
 
-  /**
-   * The first element of this stream.
-   *
-   * Stops listening to this stream after the first element has been received.
-   *
-   * Internally the method cancels its subscription after the first element.
-   * This means that single-subscription (non-broadcast) streams are closed
-   * and cannot be reused after a call to this getter.
-   *
-   * If an error event occurs before the first data event, the returned future
-   * is completed with that error.
-   *
-   * If this stream is empty (a done event occurs before the first data event),
-   * the returned future completes with an error.
-   *
-   * Except for the type of the error, this method is equivalent to
-   * `this.elementAt(0)`.
-   */
+  /// The first element of this stream.
+  ///
+  /// Stops listening to this stream after the first element has been received.
+  ///
+  /// Internally the method cancels its subscription after the first element.
+  /// This means that single-subscription (non-broadcast) streams are closed
+  /// and cannot be reused after a call to this getter.
+  ///
+  /// If an error event occurs before the first data event, the returned future
+  /// is completed with that error.
+  ///
+  /// If this stream is empty (a done event occurs before the first data event),
+  /// the returned future completes with an error.
+  ///
+  /// Except for the type of the error, this method is equivalent to
+  /// `this.elementAt(0)`.
   Future<T> get first {
     _Future<T> future = new _Future<T>();
     StreamSubscription<T> subscription =
@@ -1304,16 +1221,14 @@
     return future;
   }
 
-  /**
-   * The last element of this stream.
-   *
-   * If this stream emits an error event,
-   * the returned future is completed with that error
-   * and processing stops.
-   *
-   * If this stream is empty (the done event is the first event),
-   * the returned future completes with an error.
-   */
+  /// The last element of this stream.
+  ///
+  /// If this stream emits an error event,
+  /// the returned future is completed with that error
+  /// and processing stops.
+  ///
+  /// If this stream is empty (the done event is the first event),
+  /// the returned future completes with an error.
   Future<T> get last {
     _Future<T> future = new _Future<T>();
     late T result;
@@ -1339,16 +1254,14 @@
     return future;
   }
 
-  /**
-   * The single element of this stream.
-   *
-   * If this stream emits an error event,
-   * the returned future is completed with that error
-   * and processing stops.
-   *
-   * If [this] is empty or has more than one element,
-   * the returned future completes with an error.
-   */
+  /// The single element of this stream.
+  ///
+  /// If this stream emits an error event,
+  /// the returned future is completed with that error
+  /// and processing stops.
+  ///
+  /// If [this] is empty or has more than one element,
+  /// the returned future completes with an error.
   Future<T> get single {
     _Future<T> future = new _Future<T>();
     late T result;
@@ -1381,31 +1294,29 @@
     return future;
   }
 
-  /**
-   * Finds the first element of this stream matching [test].
-   *
-   * Returns a future that is completed with the first element of this stream
-   * that [test] returns `true` for.
-   *
-   * If no such element is found before this stream is done, and a
-   * [orElse] function is provided, the result of calling [orElse]
-   * becomes the value of the future. If [orElse] throws, the returned
-   * future is completed with that error.
-   *
-   * If this stream emits an error before the first matching element,
-   * the returned future is completed with that error, and processing stops.
-   *
-   * Stops listening to this stream after the first matching element or error
-   * has been received.
-   *
-   * Internally the method cancels its subscription after the first element that
-   * matches the predicate. This means that single-subscription (non-broadcast)
-   * streams are closed and cannot be reused after a call to this method.
-   *
-   * If an error occurs, or if this stream ends without finding a match and
-   * with no [orElse] function provided,
-   * the returned future is completed with an error.
-   */
+  /// Finds the first element of this stream matching [test].
+  ///
+  /// Returns a future that is completed with the first element of this stream
+  /// that [test] returns `true` for.
+  ///
+  /// If no such element is found before this stream is done, and a
+  /// [orElse] function is provided, the result of calling [orElse]
+  /// becomes the value of the future. If [orElse] throws, the returned
+  /// future is completed with that error.
+  ///
+  /// If this stream emits an error before the first matching element,
+  /// the returned future is completed with that error, and processing stops.
+  ///
+  /// Stops listening to this stream after the first matching element or error
+  /// has been received.
+  ///
+  /// Internally the method cancels its subscription after the first element that
+  /// matches the predicate. This means that single-subscription (non-broadcast)
+  /// streams are closed and cannot be reused after a call to this method.
+  ///
+  /// If an error occurs, or if this stream ends without finding a match and
+  /// with no [orElse] function provided,
+  /// the returned future is completed with an error.
   Future<T> firstWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future();
     StreamSubscription<T> subscription =
@@ -1432,17 +1343,15 @@
     return future;
   }
 
-  /**
-   * Finds the last element in this stream matching [test].
-   *
-   * If this stream emits an error, the returned future is completed with that
-   * error, and processing stops.
-   *
-   * Otherwise as [firstWhere], except that the last matching element is found
-   * instead of the first.
-   * That means that a non-error result cannot be provided before this stream
-   * is done.
-   */
+  /// Finds the last element in this stream matching [test].
+  ///
+  /// If this stream emits an error, the returned future is completed with that
+  /// error, and processing stops.
+  ///
+  /// Otherwise as [firstWhere], except that the last matching element is found
+  /// instead of the first.
+  /// That means that a non-error result cannot be provided before this stream
+  /// is done.
   Future<T> lastWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future();
     late T result;
@@ -1475,12 +1384,10 @@
     return future;
   }
 
-  /**
-   * Finds the single element in this stream matching [test].
-   *
-   * Like [lastWhere], except that it is an error if more than one
-   * matching element occurs in this stream.
-   */
+  /// Finds the single element in this stream matching [test].
+  ///
+  /// Like [lastWhere], except that it is an error if more than one
+  /// matching element occurs in this stream.
   Future<T> singleWhere(bool test(T element), {T orElse()?}) {
     _Future<T> future = new _Future<T>();
     late T result;
@@ -1521,22 +1428,20 @@
     return future;
   }
 
-  /**
-   * Returns the value of the [index]th data event of this stream.
-   *
-   * Stops listening to this stream after the [index]th data event has been
-   * received.
-   *
-   * Internally the method cancels its subscription after these elements. This
-   * means that single-subscription (non-broadcast) streams are closed and
-   * cannot be reused after a call to this method.
-   *
-   * If an error event occurs before the value is found, the future completes
-   * with this error.
-   *
-   * If a done event occurs before the value is found, the future completes
-   * with a [RangeError].
-   */
+  /// Returns the value of the [index]th data event of this stream.
+  ///
+  /// Stops listening to this stream after the [index]th data event has been
+  /// received.
+  ///
+  /// Internally the method cancels its subscription after these elements. This
+  /// means that single-subscription (non-broadcast) streams are closed and
+  /// cannot be reused after a call to this method.
+  ///
+  /// If an error event occurs before the value is found, the future completes
+  /// with this error.
+  ///
+  /// If a done event occurs before the value is found, the future completes
+  /// with a [RangeError].
   Future<T> elementAt(int index) {
     RangeError.checkNotNegative(index, "index");
     _Future<T> result = new _Future<T>();
@@ -1559,33 +1464,31 @@
     return result;
   }
 
-  /**
-   * 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
-   * 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 [onTimeout] function is called with one argument: an
-   * [EventSink] that allows putting events into the returned stream.
-   * This `EventSink` is only valid during the call to [onTimeout].
-   * 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]
-   * into the error channel of the returned stream.
-   * If the call to [onTimeout] throws, the error is emitted 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
-   * will have its individually timer that starts counting on listen,
-   * and the subscriptions' timers can be paused individually.
-   */
+  /// 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
+  /// 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 [onTimeout] function is called with one argument: an
+  /// [EventSink] that allows putting events into the returned stream.
+  /// This `EventSink` is only valid during the call to [onTimeout].
+  /// 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]
+  /// into the error channel of the returned stream.
+  /// If the call to [onTimeout] throws, the error is emitted 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
+  /// will have its individually timer that starts counting on listen,
+  /// and the subscriptions' timers can be paused individually.
   Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)?}) {
     _StreamControllerBase<T> controller;
     if (isBroadcast) {
@@ -1662,198 +1565,169 @@
   }
 }
 
-/**
- * A subscription on events from a [Stream].
- *
- * When you listen on a [Stream] using [Stream.listen],
- * a [StreamSubscription] object is returned.
- *
- * The subscription provides events to the listener,
- * and holds the callbacks used to handle the events.
- * The subscription can also be used to unsubscribe from the events,
- * or to temporarily pause the events from the stream.
- */
+/// A subscription on events from a [Stream].
+///
+/// When you listen on a [Stream] using [Stream.listen],
+/// a [StreamSubscription] object is returned.
+///
+/// The subscription provides events to the listener,
+/// and holds the callbacks used to handle the events.
+/// The subscription can also be used to unsubscribe from the events,
+/// or to temporarily pause the events from the stream.
 abstract class StreamSubscription<T> {
-  /**
-   * Cancels this subscription.
-   *
-   * After this call, the subscription no longer receives events.
-   *
-   * The stream may need to shut down the source of events and clean up after
-   * the subscription is canceled.
-   *
-   * Returns a future that is completed once the stream has finished
-   * its cleanup.
-   *
-   * Typically, cleanup happens when the stream needs to release resources.
-   * For example, a stream might need to close an open file (as an asynchronous
-   * operation). If the listener wants to delete the file after having
-   * canceled the subscription, it must wait for the cleanup future to complete.
-   *
-   * If the cleanup throws, which it really shouldn't, the returned future
-   * completes with that error.
-   */
+  /// Cancels this subscription.
+  ///
+  /// After this call, the subscription no longer receives events.
+  ///
+  /// The stream may need to shut down the source of events and clean up after
+  /// the subscription is canceled.
+  ///
+  /// Returns a future that is completed once the stream has finished
+  /// its cleanup.
+  ///
+  /// Typically, cleanup happens when the stream needs to release resources.
+  /// For example, a stream might need to close an open file (as an asynchronous
+  /// operation). If the listener wants to delete the file after having
+  /// canceled the subscription, it must wait for the cleanup future to complete.
+  ///
+  /// If the cleanup throws, which it really shouldn't, the returned future
+  /// completes with that error.
   Future<void> cancel();
 
-  /**
-   * Replaces the data event handler of this subscription.
-   *
-   * The [handleData] function is called for each element of the stream
-   * after this function is called.
-   * If [handleData] is `null`, further elements are ignored.
-   *
-   * This method replaces the current handler set by the invocation of
-   * [Stream.listen] or by a previous call to [onData].
-   */
+  /// Replaces the data event handler of this subscription.
+  ///
+  /// The [handleData] function is called for each data event of the stream
+  /// after this function is called.
+  /// If [handleData] is `null`, data events are ignored.
+  ///
+  /// This method replaces the current handler set by the invocation of
+  /// [Stream.listen] or by a previous call to [onData].
   void onData(void handleData(T data)?);
 
-  /**
-   * Replaces the error event handler of this subscription.
-   *
-   * The [handleError] function must be able to be called with either
-   * one positional argument, or with two positional arguments
-   * where the seconds is always a [StackTrace].
-   *
-   * The [handleError] argument may be `null`, in which case further
-   * error events are considered unhandled, and will be reported to
-   * [Zone.handleUncaughtError].
-   *
-   * The provided function is called for all error events from the
-   * stream subscription.
-   *
-   * This method replaces the current handler set by the invocation of
-   * [Stream.listen], by calling [asFuture], or by a previous call to [onError].
-   */
+  /// Replaces the error event handler of this subscription.
+  ///
+  /// The [handleError] function must be able to be called with either
+  /// one positional argument, or with two positional arguments
+  /// where the seconds is always a [StackTrace].
+  ///
+  /// The [handleError] argument may be `null`, in which case further
+  /// error events are considered *unhandled*, and will be reported to
+  /// [Zone.handleUncaughtError].
+  ///
+  /// The provided function is called for all error events from the
+  /// stream subscription.
+  ///
+  /// This method replaces the current handler set by the invocation of
+  /// [Stream.listen], by calling [asFuture], or by a previous call to [onError].
   void onError(Function? handleError);
 
-  /**
-   * Replaces the done event handler of this subscription.
-   *
-   * The [handleDone] function is called when the stream closes.
-   * The value may be `null`, in which case no function is called.
-   *
-   * This method replaces the current handler set by the invocation of
-   * [Stream.listen], by calling [asFuture], or by a previous call to [onDone].
-   */
+  /// Replaces the done event handler of this subscription.
+  ///
+  /// The [handleDone] function is called when the stream closes.
+  /// The value may be `null`, in which case no function is called.
+  ///
+  /// This method replaces the current handler set by the invocation of
+  /// [Stream.listen], by calling [asFuture], or by a previous call to [onDone].
   void onDone(void handleDone()?);
 
-  /**
-   * Request that the stream pauses events until further notice.
-   *
-   * While paused, the subscription will not fire any events.
-   * If it receives events from its source, they will be buffered until
-   * the subscription is resumed.
-   * For non-broadcast streams, the underlying source is usually informed
-   * about the pause,
-   * so it can stop generating events until the subscription is resumed.
-   *
-   * To avoid buffering events on a broadcast stream, it is better to
-   * cancel this subscription, and start to listen again when events
-   * are needed, if the intermediate events are not important.
-   *
-   * If [resumeSignal] is provided, the stream subscription will undo the pause
-   * when the future completes, as if by a call to [resume].
-   * If the future completes with an error,
-   * the stream will still resume, but the error will be considered unhandled
-   * and is passed to [Zone.handleUncaughtError].
-   *
-   * A call to [resume] will also undo a pause.
-   *
-   * If the subscription is paused more than once, an equal number
-   * of resumes must be performed to resume the stream.
-   * Calls to [resume] and the completion of a [resumeSignal] are
-   * interchangeable - the [pause] which was passed a [resumeSignal] may be
-   * ended by a call to [resume], and completing the [resumeSignal] may end a
-   * different [pause].
-   *
-   * It is safe to [resume] or complete a [resumeSignal] even when the
-   * subscription is not paused, and the resume will have no effect.
-   *
-   * Currently DOM streams silently drop events when the stream is paused. This
-   * is a bug and will be fixed.
-   */
+  /// Requests that the stream pauses events until further notice.
+  ///
+  /// While paused, the subscription will not fire any events.
+  /// If it receives events from its source, they will be buffered until
+  /// the subscription is resumed.
+  /// For non-broadcast streams, the underlying source is usually informed
+  /// about the pause,
+  /// so it can stop generating events until the subscription is resumed.
+  ///
+  /// To avoid buffering events on a broadcast stream, it is better to
+  /// cancel this subscription, and start to listen again when events
+  /// are needed, if the intermediate events are not important.
+  ///
+  /// If [resumeSignal] is provided, the stream subscription will undo the pause
+  /// when the future completes, as if by a call to [resume].
+  /// If the future completes with an error,
+  /// the stream will still resume, but the error will be considered unhandled
+  /// and is passed to [Zone.handleUncaughtError].
+  ///
+  /// A call to [resume] will also undo a pause.
+  ///
+  /// If the subscription is paused more than once, an equal number
+  /// of resumes must be performed to resume the stream.
+  /// Calls to [resume] and the completion of a [resumeSignal] are
+  /// interchangeable - the [pause] which was passed a [resumeSignal] may be
+  /// ended by a call to [resume], and completing the [resumeSignal] may end a
+  /// different [pause].
+  ///
+  /// It is safe to [resume] or complete a [resumeSignal] even when the
+  /// subscription is not paused, and the resume will have no effect.
   void pause([Future<void>? resumeSignal]);
 
-  /**
-   * Resume after a pause.
-   *
-   * This undoes one previous call to [pause].
-   * When all previously calls to [pause] have been matched by a calls to
-   * [resume], possibly through a `resumeSignal` passed to [pause],
-   * the stream subscription may emit events again.
-   *
-   * It is safe to [resume] even when the subscription is not paused, and the
-   * resume will have no effect.
-   */
+  /// Resumes after a pause.
+  ///
+  /// This undoes one previous call to [pause].
+  /// When all previously calls to [pause] have been matched by a calls to
+  /// [resume], possibly through a `resumeSignal` passed to [pause],
+  /// the stream subscription may emit events again.
+  ///
+  /// It is safe to [resume] even when the subscription is not paused, and the
+  /// resume will have no effect.
   void resume();
 
-  /**
-   * Whether the [StreamSubscription] is currently paused.
-   *
-   * If there have been more calls to [pause] than to [resume] on this
-   * stream subscription, the subscription is paused, and this getter
-   * returns `true`.
-   *
-   * Returns `false` if the stream can currently emit events, or if
-   * the subscription has completed or been cancelled.
-   */
+  /// Whether the [StreamSubscription] is currently paused.
+  ///
+  /// If there have been more calls to [pause] than to [resume] on this
+  /// stream subscription, the subscription is paused, and this getter
+  /// returns `true`.
+  ///
+  /// Returns `false` if the stream can currently emit events, or if
+  /// the subscription has completed or been cancelled.
   bool get isPaused;
 
-  /**
-   * Returns a future that handles the [onDone] and [onError] callbacks.
-   *
-   * This method *overwrites* the existing [onDone] and [onError] callbacks
-   * with new ones that complete the returned future.
-   *
-   * In case of an error the subscription will automatically cancel (even
-   * when it was listening with `cancelOnError` set to `false`).
-   *
-   * In case of a `done` event the future completes with the given
-   * [futureValue].
-   *
-   * If [futureValue] is omitted, the value `null as E` is used as a default.
-   * If `E` is not nullable, this will throw immediately when [asFuture]
-   * is called.
-   */
+  /// Returns a future that handles the [onDone] and [onError] callbacks.
+  ///
+  /// This method *overwrites* the existing [onDone] and [onError] callbacks
+  /// with new ones that complete the returned future.
+  ///
+  /// In case of an error the subscription will automatically cancel (even
+  /// when it was listening with `cancelOnError` set to `false`).
+  ///
+  /// In case of a `done` event the future completes with the given
+  /// [futureValue].
+  ///
+  /// If [futureValue] is omitted, the value `null as E` is used as a default.
+  /// If `E` is not nullable, this will throw immediately when [asFuture]
+  /// is called.
   Future<E> asFuture<E>([E? futureValue]);
 }
 
-/**
- * A [Sink] that supports adding errors.
- *
- * This makes it suitable for capturing the results of asynchronous
- * computations, which can complete with a value or an error.
- *
- * The [EventSink] has been designed to handle asynchronous events from
- * [Stream]s. See, for example, [Stream.eventTransformed] which uses
- * `EventSink`s to transform events.
- */
+/// A [Sink] that supports adding errors.
+///
+/// This makes it suitable for capturing the results of asynchronous
+/// computations, which can complete with a value or an error.
+///
+/// The [EventSink] has been designed to handle asynchronous events from
+/// [Stream]s. See, for example, [Stream.eventTransformed] which uses
+/// `EventSink`s to transform events.
 abstract class EventSink<T> implements Sink<T> {
-  /**
-   * Adds a data [event] to the sink.
-   *
-   * Must not be called on a closed sink.
-   */
+  /// Adds a data [event] to the sink.
+  ///
+  /// Must not be called on a closed sink.
   void add(T event);
 
-  /**
-   * Adds an [error] to the sink.
-   *
-   * Must not be called on a closed sink.
-   */
+  /// Adds an [error] to the sink.
+  ///
+  /// Must not be called on a closed sink.
   void addError(Object error, [StackTrace? stackTrace]);
 
-  /**
-   * Closes the sink.
-   *
-   * Calling this method more than once is allowed, but does nothing.
-   *
-   * Neither [add] nor [addError] must be called after this method.
-   */
+  /// Closes the sink.
+  ///
+  /// Calling this method more than once is allowed, but does nothing.
+  ///
+  /// Neither [add] nor [addError] must be called after this method.
   void close();
 }
 
-/** [Stream] wrapper that only exposes the [Stream] interface. */
+/// [Stream] wrapper that only exposes the [Stream] interface.
 class StreamView<T> extends Stream<T> {
   final Stream<T> _stream;
 
@@ -1875,335 +1749,307 @@
   }
 }
 
-/**
- * Abstract interface for a "sink" accepting multiple entire streams.
- *
- * A consumer can accept a number of consecutive streams using [addStream],
- * and when no further data need to be added, the [close] method tells the
- * consumer to complete its work and shut down.
- *
- * The [Stream.pipe] accepts a `StreamConsumer` and will pass the stream
- * to the consumer's [addStream] method. When that completes, it will
- * call [close] and then complete its own returned future.
- */
+/// Abstract interface for a "sink" accepting multiple entire streams.
+///
+/// A consumer can accept a number of consecutive streams using [addStream],
+/// and when no further data need to be added, the [close] method tells the
+/// consumer to complete its work and shut down.
+///
+/// The [Stream.pipe] accepts a `StreamConsumer` and will pass the stream
+/// to the consumer's [addStream] method. When that completes, it will
+/// call [close] and then complete its own returned future.
 abstract class StreamConsumer<S> {
-  /**
-   * Consumes the elements of [stream].
-   *
-   * Listens on [stream] and does something for each event.
-   *
-   * Returns a future which is completed when the stream is done being added,
-   * and the consumer is ready to accept a new stream.
-   * No further calls to [addStream] or [close] should happen before the
-   * returned future has completed.
-   *
-   * The consumer may stop listening to the stream after an error,
-   * it may consume all the errors and only stop at a done event,
-   * or it may be canceled early if the receiver don't want any further events.
-   *
-   * If the consumer stops listening because of some error preventing it
-   * from continuing, it may report this error in the returned future,
-   * otherwise it will just complete the future with `null`.
-   */
+  /// Consumes the elements of [stream].
+  ///
+  /// Listens on [stream] and does something for each event.
+  ///
+  /// Returns a future which is completed when the stream is done being added,
+  /// and the consumer is ready to accept a new stream.
+  /// No further calls to [addStream] or [close] should happen before the
+  /// returned future has completed.
+  ///
+  /// The consumer may stop listening to the stream after an error,
+  /// it may consume all the errors and only stop at a done event,
+  /// or it may be canceled early if the receiver don't want any further events.
+  ///
+  /// If the consumer stops listening because of some error preventing it
+  /// from continuing, it may report this error in the returned future,
+  /// otherwise it will just complete the future with `null`.
   Future addStream(Stream<S> stream);
 
-  /**
-   * Tells the consumer that no further streams will be added.
-   *
-   * This allows the consumer to complete any remaining work and release
-   * resources that are no longer needed
-   *
-   * Returns a future which is completed when the consumer has shut down.
-   * If cleaning up can fail, the error may be reported in the returned future,
-   * otherwise it completes with `null`.
-   */
+  /// Tells the consumer that no further streams will be added.
+  ///
+  /// This allows the consumer to complete any remaining work and release
+  /// resources that are no longer needed
+  ///
+  /// Returns a future which is completed when the consumer has shut down.
+  /// If cleaning up can fail, the error may be reported in the returned future,
+  /// otherwise it completes with `null`.
   Future close();
 }
 
-/**
- * A object that accepts stream events both synchronously and asynchronously.
- *
- * A [StreamSink] combines the methods from [StreamConsumer] and [EventSink].
- *
- * The [EventSink] methods can't be used while the [addStream] is called.
- * As soon as the [addStream]'s [Future] completes with a value, the
- * [EventSink] methods can be used again.
- *
- * If [addStream] is called after any of the [EventSink] methods, it'll
- * be delayed until the underlying system has consumed the data added by the
- * [EventSink] methods.
- *
- * When [EventSink] methods are used, the [done] [Future] can be used to
- * catch any errors.
- *
- * When [close] is called, it will return the [done] [Future].
- */
+/// A object that accepts stream events both synchronously and asynchronously.
+///
+/// A [StreamSink] combines the methods from [StreamConsumer] and [EventSink].
+///
+/// The [EventSink] methods can't be used while the [addStream] is called.
+/// As soon as the [addStream]'s [Future] completes with a value, the
+/// [EventSink] methods can be used again.
+///
+/// If [addStream] is called after any of the [EventSink] methods, it'll
+/// be delayed until the underlying system has consumed the data added by the
+/// [EventSink] methods.
+///
+/// When [EventSink] methods are used, the [done] [Future] can be used to
+/// catch any errors.
+///
+/// When [close] is called, it will return the [done] [Future].
 abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {
-  /**
-   * Tells the stream sink that no further streams will be added.
-   *
-   * This allows the stream sink to complete any remaining work and release
-   * resources that are no longer needed
-   *
-   * Returns a future which is completed when the stream sink has shut down.
-   * If cleaning up can fail, the error may be reported in the returned future,
-   * otherwise it completes with `null`.
-   *
-   * Returns the same future as [done].
-   *
-   * The stream sink may close before the [close] method is called, either due
-   * to an error or because it is itself providing events to someone who has
-   * stopped listening. In that case, the [done] future is completed first,
-   * and the `close` method will return the `done` future when called.
-   *
-   * Unifies [StreamConsumer.close] and [EventSink.close] which both mark their
-   * object as not expecting any further events.
-   */
+  /// Tells the stream sink that no further streams will be added.
+  ///
+  /// This allows the stream sink to complete any remaining work and release
+  /// resources that are no longer needed
+  ///
+  /// Returns a future which is completed when the stream sink has shut down.
+  /// If cleaning up can fail, the error may be reported in the returned future,
+  /// otherwise it completes with `null`.
+  ///
+  /// Returns the same future as [done].
+  ///
+  /// The stream sink may close before the [close] method is called, either due
+  /// to an error or because it is itself providing events to someone who has
+  /// stopped listening. In that case, the [done] future is completed first,
+  /// and the `close` method will return the `done` future when called.
+  ///
+  /// Unifies [StreamConsumer.close] and [EventSink.close] which both mark their
+  /// object as not expecting any further events.
   Future close();
 
-  /**
-   * Return a future which is completed when the [StreamSink] is finished.
-   *
-   * If the `StreamSink` fails with an error,
-   * perhaps in response to adding events using [add], [addError] or [close],
-   * the [done] future will complete with that error.
-   *
-   * Otherwise, the returned future will complete when either:
-   *
-   * * all events have been processed and the sink has been closed, or
-   * * the sink has otherwise been stopped from handling more events
-   *   (for example by canceling a stream subscription).
-   */
+  /// Return a future which is completed when the [StreamSink] is finished.
+  ///
+  /// If the `StreamSink` fails with an error,
+  /// perhaps in response to adding events using [add], [addError] or [close],
+  /// the [done] future will complete with that error.
+  ///
+  /// Otherwise, the returned future will complete when either:
+  ///
+  /// * all events have been processed and the sink has been closed, or
+  /// * the sink has otherwise been stopped from handling more events
+  ///   (for example by canceling a stream subscription).
   Future get done;
 }
 
-/**
- * Transforms a Stream.
- *
- * When a stream's [Stream.transform] method is invoked with a
- * [StreamTransformer], the stream calls the [bind] method on the provided
- * transformer. The resulting stream is then returned from the
- * [Stream.transform] method.
- *
- * Conceptually, a transformer is simply a function from [Stream] to [Stream]
- * that is encapsulated into a class.
- *
- * It is good practice to write transformers that can be used multiple times.
- *
- * All other transforming methods on [Stream], such as [Stream.map],
- * [Stream.where] or [Stream.expand] can be implemented using
- * [Stream.transform]. A [StreamTransformer] is thus very powerful but often
- * also a bit more complicated to use.
- */
+/// Transforms a Stream.
+///
+/// When a stream's [Stream.transform] method is invoked with a
+/// [StreamTransformer], the stream calls the [bind] method on the provided
+/// transformer. The resulting stream is then returned from the
+/// [Stream.transform] method.
+///
+/// Conceptually, a transformer is simply a function from [Stream] to [Stream]
+/// that is encapsulated into a class.
+///
+/// It is good practice to write transformers that can be used multiple times.
+///
+/// All other transforming methods on [Stream], such as [Stream.map],
+/// [Stream.where] or [Stream.expand] can be implemented using
+/// [Stream.transform]. A [StreamTransformer] is thus very powerful but often
+/// also a bit more complicated to use.
 abstract class StreamTransformer<S, T> {
-  /**
-   * Creates a [StreamTransformer] based on the given [onListen] callback.
-   *
-   * The returned stream transformer uses the provided [onListen] callback
-   * when a transformed stream is listened to. At that time, the callback
-   * receives the input stream (the one passed to [bind]) and a
-   * boolean flag `cancelOnError` to create a [StreamSubscription].
-   *
-   * If the transformed stream is a broadcast stream, so is the stream
-   * returned by the [StreamTransformer.bind] method by this transformer.
-   *
-   * If the transformed stream is listened to multiple times, the [onListen]
-   * callback is called again for each new [Stream.listen] call.
-   * This happens whether the stream is a broadcast stream or not,
-   * but the call will usually fail for non-broadcast streams.
-   *
-   * The [onListen] callback does *not* receive the handlers that were passed
-   * to [Stream.listen]. These are automatically set after the call to the
-   * [onListen] callback (using [StreamSubscription.onData],
-   * [StreamSubscription.onError] and [StreamSubscription.onDone]).
-   *
-   * Most commonly, an [onListen] callback will first call [Stream.listen] on
-   * the provided stream (with the corresponding `cancelOnError` flag), and then
-   * return a new [StreamSubscription].
-   *
-   * There are two common ways to create a StreamSubscription:
-   *
-   * 1. by allocating a [StreamController] and to return the result of
-   *    listening to its stream. It's important to forward pause, resume and
-   *    cancel events (unless the transformer intentionally wants to change
-   *    this behavior).
-   * 2. by creating a new class that implements [StreamSubscription].
-   *    Note that the subscription should run callbacks in the [Zone] the
-   *    stream was listened to (see [Zone] and [Zone.bindCallback]).
-   *
-   * Example:
-   *
-   * ```
-   * /// Starts listening to [input] and duplicates all non-error events.
-   * StreamSubscription<int> _onListen(Stream<int> input, bool cancelOnError) {
-   *   StreamSubscription<String> subscription;
-   *   // Create controller that forwards pause, resume and cancel events.
-   *   var controller = new StreamController<String>(
-   *       onPause: () {
-   *         subscription.pause();
-   *       },
-   *       onResume: () {
-   *         subscription.resume();
-   *       },
-   *       onCancel: () => subscription.cancel(),
-   *       sync: true); // "sync" is correct here, since events are forwarded.
-   *
-   *   // Listen to the provided stream using `cancelOnError`.
-   *   subscription = input.listen((data) {
-   *     // Duplicate the data.
-   *     controller.add(data);
-   *     controller.add(data);
-   *   },
-   *       onError: controller.addError,
-   *       onDone: controller.close,
-   *       cancelOnError: cancelOnError);
-   *
-   *   // Return a new [StreamSubscription] by listening to the controller's
-   *   // stream.
-   *   return controller.stream.listen(null);
-   * }
-   *
-   * // Instantiate a transformer:
-   * var duplicator = const StreamTransformer<int, int>(_onListen);
-   *
-   * // Use as follows:
-   * intStream.transform(duplicator);
-   * ```
-   */
+  /// Creates a [StreamTransformer] based on the given [onListen] callback.
+  ///
+  /// The returned stream transformer uses the provided [onListen] callback
+  /// when a transformed stream is listened to. At that time, the callback
+  /// receives the input stream (the one passed to [bind]) and a
+  /// boolean flag `cancelOnError` to create a [StreamSubscription].
+  ///
+  /// If the transformed stream is a broadcast stream, so is the stream
+  /// returned by the [StreamTransformer.bind] method by this transformer.
+  ///
+  /// If the transformed stream is listened to multiple times, the [onListen]
+  /// callback is called again for each new [Stream.listen] call.
+  /// This happens whether the stream is a broadcast stream or not,
+  /// but the call will usually fail for non-broadcast streams.
+  ///
+  /// The [onListen] callback does *not* receive the handlers that were passed
+  /// to [Stream.listen]. These are automatically set after the call to the
+  /// [onListen] callback (using [StreamSubscription.onData],
+  /// [StreamSubscription.onError] and [StreamSubscription.onDone]).
+  ///
+  /// Most commonly, an [onListen] callback will first call [Stream.listen] on
+  /// the provided stream (with the corresponding `cancelOnError` flag), and then
+  /// return a new [StreamSubscription].
+  ///
+  /// There are two common ways to create a StreamSubscription:
+  ///
+  /// 1. by allocating a [StreamController] and to return the result of
+  ///    listening to its stream. It's important to forward pause, resume and
+  ///    cancel events (unless the transformer intentionally wants to change
+  ///    this behavior).
+  /// 2. by creating a new class that implements [StreamSubscription].
+  ///    Note that the subscription should run callbacks in the [Zone] the
+  ///    stream was listened to (see [Zone] and [Zone.bindCallback]).
+  ///
+  /// Example:
+  ///
+  /// ```
+  /// /// Starts listening to [input] and duplicates all non-error events.
+  /// StreamSubscription<int> _onListen(Stream<int> input, bool cancelOnError) {
+  ///   late StreamSubscription<String> subscription;
+  ///   // Create controller that forwards pause, resume and cancel events.
+  ///   var controller = new StreamController<String>(
+  ///       onPause: () {
+  ///         subscription.pause();
+  ///       },
+  ///       onResume: () {
+  ///         subscription.resume();
+  ///       },
+  ///       onCancel: () => subscription.cancel(),
+  ///       sync: true); // "sync" is correct here, since events are forwarded.
+  ///
+  ///   // Listen to the provided stream.
+  ///   subscription = input.listen((data) {
+  ///     // Duplicate the data.
+  ///     controller.add(data);
+  ///     controller.add(data);
+  ///   },
+  ///       onError: controller.addError,
+  ///       onDone: controller.close,
+  ///       cancelOnError: cancelOnError);
+  ///
+  ///   // Return a new [StreamSubscription] by listening to the controller's
+  ///   // stream.
+  ///   return controller.stream.listen(null);
+  /// }
+  ///
+  /// // Instantiate a transformer:
+  /// var duplicator = const StreamTransformer<int, int>(_onListen);
+  ///
+  /// // Use as follows:
+  /// intStream.transform(duplicator);
+  /// ```
   const factory StreamTransformer(
           StreamSubscription<T> onListen(
               Stream<S> stream, bool cancelOnError)) =
       _StreamSubscriptionTransformer<S, T>;
 
-  /**
-   * Creates a [StreamTransformer] that delegates events to the given functions.
-   *
-   * Example use of a duplicating transformer:
-   *
-   * ```
-   * stringStream.transform(new StreamTransformer<String, String>.fromHandlers(
-   *     handleData: (String value, EventSink<String> sink) {
-   *       sink.add(value);
-   *       sink.add(value);  // Duplicate the incoming events.
-   *     }));
-   * ```
-   *
-   * Transformers that are constructed this way cannot use captured state if
-   * they are used in streams that can be listened to multiple times.
-   * ```
-   * StreamController<String> controller;
-   * controller = new StreamController.broadcast(onListen: () {
-   *   scheduleMicrotask(() {
-   *     controller.addError("Bad");
-   *     controller.addError("Worse");
-   *     controller.addError("Worst");
-   *   });
-   * });
-   * var sharedState = 0;
-   * var transformedStream = controller.stream.transform(
-   *     new StreamTransformer<String>.fromHandlers(
-   *         handleError: (error, stackTrace, sink) {
-   *   sharedState++; // Increment shared error-counter.
-   *   sink.add("Error $sharedState: $error");
-   * }));
-   *
-   * transformedStream.listen(print);
-   * transformedStream.listen(print); // Listen twice.
-   * // Listening twice to the same stream makes the transformer share the same
-   * // state. Instead of having "Error 1: Bad", "Error 2: Worse",
-   * // "Error 3: Worst" as output (each twice for the separate subscriptions),
-   * // this program emits:
-   * // Error 1: Bad
-   * // Error 2: Bad
-   * // Error 3: Worse
-   * // Error 4: Worse
-   * // Error 5: Worst
-   * // Error 6: Worst
-   * ```
-   */
+  /// Creates a [StreamTransformer] that delegates events to the given functions.
+  ///
+  /// Example use of a duplicating transformer:
+  ///
+  /// ```
+  /// stringStream.transform(StreamTransformer<String, String>.fromHandlers(
+  ///     handleData: (String value, EventSink<String> sink) {
+  ///       sink.add(value);
+  ///       sink.add(value);  // Duplicate the incoming events.
+  ///     }));
+  /// ```
+  ///
+  /// Transformers that are constructed this way cannot use captured state if
+  /// they are used in streams that can be listened to multiple times.
+  /// ```
+  /// StreamController<String> controller = StreamController.broadcast()
+  /// controller.onListen = () {
+  ///   scheduleMicrotask(() {
+  ///     controller.addError("Bad");
+  ///     controller.addError("Worse");
+  ///     controller.addError("Worst");
+  ///   });
+  /// };
+  /// var sharedState = 0;
+  /// var transformedStream = controller.stream.transform(
+  ///     StreamTransformer<String>.fromHandlers(
+  ///         handleError: (error, stackTrace, sink) {
+  ///   sharedState++; // Increment shared error-counter.
+  ///   sink.add("Error $sharedState: $error");
+  /// }));
+  ///
+  /// transformedStream.listen(print);
+  /// transformedStream.listen(print); // Listen twice.
+  /// // Listening twice to the same stream makes the transformer share the same
+  /// // state. Instead of having "Error 1: Bad", "Error 2: Worse",
+  /// // "Error 3: Worst" as output (each twice for the separate subscriptions),
+  /// // this program emits:
+  /// // Error 1: Bad
+  /// // Error 2: Bad
+  /// // Error 3: Worse
+  /// // Error 4: Worse
+  /// // Error 5: Worst
+  /// // Error 6: Worst
+  /// ```
   factory StreamTransformer.fromHandlers(
       {void handleData(S data, EventSink<T> sink)?,
       void handleError(Object error, StackTrace stackTrace, EventSink<T> sink)?,
       void handleDone(EventSink<T> sink)?}) = _StreamHandlerTransformer<S, T>;
 
-  /**
-   * Creates a [StreamTransformer] based on a [bind] callback.
-   *
-   * The returned stream transformer uses the [bind] argument to implement the
-   * [StreamTransformer.bind] API and can be used when the transformation is
-   * available as a stream-to-stream function.
-   *
-   * ```dart
-   * final splitDecoded = StreamTransformer<List<int>, String>.fromBind(
-   *     (stream) => stream.transform(utf8.decoder).transform(LineSplitter()));
-   * ```
-   */
+  /// Creates a [StreamTransformer] based on a [bind] callback.
+  ///
+  /// The returned stream transformer uses the [bind] argument to implement the
+  /// [StreamTransformer.bind] API and can be used when the transformation is
+  /// available as a stream-to-stream function.
+  ///
+  /// ```dart
+  /// final splitDecoded = StreamTransformer<List<int>, String>.fromBind(
+  ///     (stream) => stream.transform(utf8.decoder).transform(LineSplitter()));
+  /// ```
   @Since("2.1")
   factory StreamTransformer.fromBind(Stream<T> Function(Stream<S>) bind) =
       _StreamBindTransformer<S, T>;
 
-  /**
-   * Adapts [source] to be a `StreamTransformer<TS, TT>`.
-   *
-   * This allows [source] to be used at the new type, but at run-time it
-   * must satisfy the requirements of both the new type and its original type.
-   *
-   * Data events passed into the returned transformer must also be instances
-   * of [SS], and data events produced by [source] for those events must
-   * also be instances of [TT].
-   */
+  /// Adapts [source] to be a `StreamTransformer<TS, TT>`.
+  ///
+  /// This allows [source] to be used at the new type, but at run-time it
+  /// must satisfy the requirements of both the new type and its original type.
+  ///
+  /// Data events passed into the returned transformer must also be instances
+  /// of [SS], and data events produced by [source] for those events must
+  /// also be instances of [TT].
   static StreamTransformer<TS, TT> castFrom<SS, ST, TS, TT>(
       StreamTransformer<SS, ST> source) {
     return new CastStreamTransformer<SS, ST, TS, TT>(source);
   }
 
-  /**
-   * Transforms the provided [stream].
-   *
-   * Returns a new stream with events that are computed from events of the
-   * provided [stream].
-   *
-   * The [StreamTransformer] interface is completely generic,
-   * so it cannot say what subclasses do.
-   * Each [StreamTransformer] should document clearly how it transforms the
-   * stream (on the class or variable used to access the transformer),
-   * as well as any differences from the following typical behavior:
-   *
-   * * When the returned stream is listened to, it starts listening to the
-   *   input [stream].
-   * * Subscriptions of the returned stream forward (in a reasonable time)
-   *   a [StreamSubscription.pause] call to the subscription of the input
-   *   [stream].
-   * * Similarly, canceling a subscription of the returned stream eventually
-   *   (in reasonable time) cancels the subscription of the input [stream].
-   *
-   * "Reasonable time" depends on the transformer and stream. Some transformers,
-   * like a "timeout" transformer, might make these operations depend on a
-   * duration. Others might not delay them at all, or just by a microtask.
-   *
-   * Transformers are free to handle errors in any way.
-   * A transformer implementation may choose to propagate errors,
-   * or convert them to other events, or ignore them completely,
-   * but if errors are ignored, it should be documented explicitly.
-   */
+  /// Transforms the provided [stream].
+  ///
+  /// Returns a new stream with events that are computed from events of the
+  /// provided [stream].
+  ///
+  /// The [StreamTransformer] interface is completely generic,
+  /// so it cannot say what subclasses do.
+  /// Each [StreamTransformer] should document clearly how it transforms the
+  /// stream (on the class or variable used to access the transformer),
+  /// as well as any differences from the following typical behavior:
+  ///
+  /// * When the returned stream is listened to, it starts listening to the
+  ///   input [stream].
+  /// * Subscriptions of the returned stream forward (in a reasonable time)
+  ///   a [StreamSubscription.pause] call to the subscription of the input
+  ///   [stream].
+  /// * Similarly, canceling a subscription of the returned stream eventually
+  ///   (in reasonable time) cancels the subscription of the input [stream].
+  ///
+  /// "Reasonable time" depends on the transformer and stream. Some transformers,
+  /// like a "timeout" transformer, might make these operations depend on a
+  /// duration. Others might not delay them at all, or just by a microtask.
+  ///
+  /// Transformers are free to handle errors in any way.
+  /// A transformer implementation may choose to propagate errors,
+  /// or convert them to other events, or ignore them completely,
+  /// but if errors are ignored, it should be documented explicitly.
   Stream<T> bind(Stream<S> stream);
 
-  /**
-   * Provides a `StreamTransformer<RS, RT>` view of this stream transformer.
-   *
-   * The resulting transformer will check at run-time that all data events
-   * of the stream it transforms are actually instances of [S],
-   * and it will check that all data events produced by this transformer
-   * are actually instances of [RT].
-   */
+  /// Provides a `StreamTransformer<RS, RT>` view of this stream transformer.
+  ///
+  /// The resulting transformer will check at run-time that all data events
+  /// of the stream it transforms are actually instances of [S],
+  /// and it will check that all data events produced by this transformer
+  /// are actually instances of [RT].
   StreamTransformer<RS, RT> cast<RS, RT>();
 }
 
-/**
- * Base class for implementing [StreamTransformer].
- *
- * Contains default implementations of every method except [bind].
- */
+/// Base class for implementing [StreamTransformer].
+///
+/// Contains default implementations of every method except [bind].
 abstract class StreamTransformerBase<S, T> implements StreamTransformer<S, T> {
   const StreamTransformerBase();
 
@@ -2211,80 +2057,71 @@
       StreamTransformer.castFrom<S, T, RS, RT>(this);
 }
 
-/**
- * An [Iterator]-like interface for the values of a [Stream].
- *
- * This wraps a [Stream] and a subscription on the stream. It listens
- * on the stream, and completes the future returned by [moveNext] when the
- * next value becomes available.
- *
- * The stream may be paused between calls to [moveNext].
- *
- * The [current] value must only be used after a future returned by [moveNext]
- * has completed with `true`, and only until [moveNext] is called again.
- */
+/// An [Iterator]-like interface for the values of a [Stream].
+///
+/// This wraps a [Stream] and a subscription on the stream. It listens
+/// on the stream, and completes the future returned by [moveNext] when the
+/// next value becomes available.
+///
+/// The stream may be paused between calls to [moveNext].
+///
+/// The [current] value must only be used after a future returned by [moveNext]
+/// has completed with `true`, and only until [moveNext] is called again.
 abstract class StreamIterator<T> {
-  /** Create a [StreamIterator] on [stream]. */
+  /// Create a [StreamIterator] on [stream].
   factory StreamIterator(Stream<T> stream) =>
       // TODO(lrn): use redirecting factory constructor when type
       // arguments are supported.
       new _StreamIterator<T>(stream);
 
-  /**
-   * Wait for the next stream value to be available.
-   *
-   * Returns a future which will complete with either `true` or `false`.
-   * Completing with `true` means that another event has been received and
-   * can be read as [current].
-   * Completing with `false` means that the stream iteration is done and
-   * no further events will ever be available.
-   * The future may complete with an error, if the stream produces an error,
-   * which also ends iteration.
-   *
-   * The function must not be called again until the future returned by a
-   * previous call is completed.
-   */
+  /// Wait for the next stream value to be available.
+  ///
+  /// Returns a future which will complete with either `true` or `false`.
+  /// Completing with `true` means that another event has been received and
+  /// can be read as [current].
+  /// Completing with `false` means that the stream iteration is done and
+  /// no further events will ever be available.
+  /// The future may complete with an error, if the stream produces an error,
+  /// which also ends iteration.
+  ///
+  /// The function must not be called again until the future returned by a
+  /// previous call is completed.
   Future<bool> moveNext();
 
-  /**
-   * The current value of the stream.
-   *
-   * When a [moveNext] call completes with `true`, the [current] field holds
-   * the most recent event of the stream, and it stays like that until the next
-   * call to [moveNext]. This value must only be read after a call to [moveNext]
-   * has completed with `true`, and only until the [moveNext] is called again.
-   *
-   * If the StreamIterator has not yet been moved to the first element
-   * ([moveNext] has not been called and completed yet), or if the
-   * StreamIterator has been moved past the last element ([moveNext] has
-   * returned `false`), then [current] is unspecified. A [StreamIterator] may
-   * either throw or return an iterator-specific default value in that case.
-   */
+  /// The current value of the stream.
+  ///
+  /// When a [moveNext] call completes with `true`, the [current] field holds
+  /// the most recent event of the stream, and it stays like that until the next
+  /// call to [moveNext]. This value must only be read after a call to [moveNext]
+  /// has completed with `true`, and only until the [moveNext] is called again.
+  ///
+  /// If the StreamIterator has not yet been moved to the first element
+  /// ([moveNext] has not been called and completed yet), or if the
+  /// StreamIterator has been moved past the last element ([moveNext] has
+  /// returned `false`), then [current] is unspecified. A [StreamIterator] may
+  /// either throw or return an iterator-specific default value in that case.
   T get current;
 
-  /**
-   * Cancels the stream iterator (and the underlying stream subscription) early.
-   *
-   * The stream iterator is automatically canceled if the [moveNext] future
-   * completes with either `false` or an error.
-   *
-   * If you need to stop listening for values before the stream iterator is
-   * automatically closed, you must call [cancel] to ensure that the stream
-   * is properly closed.
-   *
-   * If [moveNext] has been called when the iterator is canceled,
-   * its returned future will complete with `false` as value,
-   * as will all further calls to [moveNext].
-   *
-   * Returns a future if the cancel-operation is not completed synchronously.
-   * Otherwise returns `null`.
-   */
+  /// Cancels the stream iterator (and the underlying stream subscription) early.
+  ///
+  /// The stream iterator is automatically canceled if the [moveNext] future
+  /// completes with either `false` or an error.
+  ///
+  /// If you need to stop listening for values before the stream iterator is
+  /// automatically closed, you must call [cancel] to ensure that the stream
+  /// is properly closed.
+  ///
+  /// If [moveNext] has been called when the iterator is canceled,
+  /// its returned future will complete with `false` as value,
+  /// as will all further calls to [moveNext].
+  ///
+  /// Returns a future which completes when the cancellation is complete.
+  /// This can be an already completed future if the cancellation happens
+  /// synchronously.
   Future cancel();
 }
 
-/**
- * Wraps an [_EventSink] so it exposes only the [EventSink] interface.
- */
+/// Wraps an [_EventSink] so it exposes only the [EventSink] interface.
 class _ControllerEventSinkWrapper<T> implements EventSink<T> {
   EventSink? _sink;
   _ControllerEventSinkWrapper(this._sink);
@@ -2308,50 +2145,42 @@
   }
 }
 
-/**
- * An enhanced stream controller provided by [Stream.multi].
- *
- * Acts like a normal asynchronous controller, but also allows
- * adding events synchronously.
- * As with any synchronous event delivery, the sender should be very careful
- * to not deliver events at times when a new listener might not
- * be ready to receive them.
- * That generally means only delivering events synchronously in response to other
- * asynchronous events, because that is a time when an asynchronous event could
- * happen.
- */
+/// An enhanced stream controller provided by [Stream.multi].
+///
+/// Acts like a normal asynchronous controller, but also allows
+/// adding events synchronously.
+/// As with any synchronous event delivery, the sender should be very careful
+/// to not deliver events at times when a new listener might not
+/// be ready to receive them.
+/// That generally means only delivering events synchronously in response to other
+/// asynchronous events, because that is a time when an asynchronous event could
+/// happen.
 @Since("2.9")
 abstract class MultiStreamController<T> implements StreamController<T> {
-  /**
-   * Adds and delivers an event.
-   *
-   * Adds an event like [add] and attempts to deliver it immediately.
-   * Delivery can be delayed if other previously added events are
-   * still pending delivery, if the subscription is paused,
-   * or if the subscription isn't listening yet.
-   */
+  /// Adds and delivers an event.
+  ///
+  /// Adds an event like [add] and attempts to deliver it immediately.
+  /// Delivery can be delayed if other previously added events are
+  /// still pending delivery, if the subscription is paused,
+  /// or if the subscription isn't listening yet.
   void addSync(T value);
 
-  /**
-   * Adds and delivers an error event.
-   *
-   * Adds an error like [addError] and attempts to deliver it immediately.
-   * Delivery can be delayed if other previously added events are
-   * still pending delivery, if the subscription is paused,
-   * or if the subscription isn't listening yet.
-   */
+  /// Adds and delivers an error event.
+  ///
+  /// Adds an error like [addError] and attempts to deliver it immediately.
+  /// Delivery can be delayed if other previously added events are
+  /// still pending delivery, if the subscription is paused,
+  /// or if the subscription isn't listening yet.
   void addErrorSync(Object error, [StackTrace? stackTrace]);
 
-  /**
-   * Closes the controller and delivers a done event.
-   *
-   * Closes the controller like [close] and attempts to deliver a "done"
-   * event immediately.
-   * Delivery can be delayed if other previously added events are
-   * still pending delivery, if the subscription is paused,
-   * or if the subscription isn't listening yet.
-   * If it's necessary to know whether the "done" event has been delievered,
-   * [done] future will complete when that has happened.
-   */
+  /// Closes the controller and delivers a done event.
+  ///
+  /// Closes the controller like [close] and attempts to deliver a "done"
+  /// event immediately.
+  /// Delivery can be delayed if other previously added events are
+  /// still pending delivery, if the subscription is paused,
+  /// or if the subscription isn't listening yet.
+  /// If it's necessary to know whether the "done" event has been delievered,
+  /// [done] future will complete when that has happened.
   void closeSync();
 }
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index dbaacc1..cb305fe 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -8,71 +8,63 @@
 // Controller for creating and adding events to a stream.
 // -------------------------------------------------------------------
 
-/**
- * Type of a stream controller's `onListen`, `onPause` and `onResume` callbacks.
- */
+/// Type of a stream controller's `onListen`, `onPause` and `onResume` callbacks.
 typedef void ControllerCallback();
 
-/**
- * Type of stream controller `onCancel` callbacks.
- */
+/// Type of stream controller `onCancel` callbacks.
 typedef FutureOr<void> ControllerCancelCallback();
 
-/**
- * A controller with the stream it controls.
- *
- * This controller allows sending data, error and done events on
- * its [stream].
- * This class can be used to create a simple stream that others
- * can listen on, and to push events to that stream.
- *
- * It's possible to check whether the stream is paused or not, and whether
- * it has subscribers or not, as well as getting a callback when either of
- * these change.
- */
+/// A controller with the stream it controls.
+///
+/// This controller allows sending data, error and done events on
+/// its [stream].
+/// This class can be used to create a simple stream that others
+/// can listen on, and to push events to that stream.
+///
+/// It's possible to check whether the stream is paused or not, and whether
+/// it has subscribers or not, as well as getting a callback when either of
+/// these change.
 abstract class StreamController<T> implements StreamSink<T> {
-  /** The stream that this controller is controlling. */
+  /// The stream that this controller is controlling.
   Stream<T> get stream;
 
-  /**
-   * A controller with a [stream] that supports only one single subscriber.
-   *
-   * If [sync] is true, the returned stream controller is a
-   * [SynchronousStreamController], and must be used with the care
-   * and attention necessary to not break the [Stream] contract. If in doubt,
-   * use the non-sync version.
-   *
-   * Using an asynchronous controller will never give the wrong
-   * behavior, but using a synchronous controller incorrectly can cause
-   * otherwise correct programs to break.
-   *
-   * A synchronous controller is only intended for optimizing event
-   * propagation when one asynchronous event immediately triggers another.
-   * It should not be used unless the calls to [add] or [addError]
-   * are guaranteed to occur in places where it won't break `Stream` invariants.
-   *
-   * Use synchronous controllers only to forward (potentially transformed)
-   * events from another stream or a future.
-   *
-   * A Stream should be inert until a subscriber starts listening on it (using
-   * the [onListen] callback to start producing events). Streams should not
-   * leak resources (like websockets) when no user ever listens on the stream.
-   *
-   * The controller buffers all incoming events until a subscriber is
-   * registered, but this feature should only be used in rare circumstances.
-   *
-   * The [onPause] function is called when the stream becomes
-   * paused. [onResume] is called when the stream resumed.
-   *
-   * The [onListen] callback is called when the stream
-   * receives its listener and [onCancel] when the listener ends
-   * its subscription. If [onCancel] needs to perform an asynchronous operation,
-   * [onCancel] should return a future that completes when the cancel operation
-   * is done.
-   *
-   * If the stream is canceled before the controller needs data the
-   * [onResume] call might not be executed.
-   */
+  /// A controller with a [stream] that supports only one single subscriber.
+  ///
+  /// If [sync] is true, the returned stream controller is a
+  /// [SynchronousStreamController], and must be used with the care
+  /// and attention necessary to not break the [Stream] contract. If in doubt,
+  /// use the non-sync version.
+  ///
+  /// Using an asynchronous controller will never give the wrong
+  /// behavior, but using a synchronous controller incorrectly can cause
+  /// otherwise correct programs to break.
+  ///
+  /// A synchronous controller is only intended for optimizing event
+  /// propagation when one asynchronous event immediately triggers another.
+  /// It should not be used unless the calls to [add] or [addError]
+  /// are guaranteed to occur in places where it won't break `Stream` invariants.
+  ///
+  /// Use synchronous controllers only to forward (potentially transformed)
+  /// events from another stream or a future.
+  ///
+  /// A Stream should be inert until a subscriber starts listening on it (using
+  /// the [onListen] callback to start producing events). Streams should not
+  /// leak resources (like websockets) when no user ever listens on the stream.
+  ///
+  /// The controller buffers all incoming events until a subscriber is
+  /// registered, but this feature should only be used in rare circumstances.
+  ///
+  /// The [onPause] function is called when the stream becomes
+  /// paused. [onResume] is called when the stream resumed.
+  ///
+  /// The [onListen] callback is called when the stream
+  /// receives its listener and [onCancel] when the listener ends
+  /// its subscription. If [onCancel] needs to perform an asynchronous operation,
+  /// [onCancel] should return a future that completes when the cancel operation
+  /// is done.
+  ///
+  /// If the stream is canceled before the controller needs data the
+  /// [onResume] call might not be executed.
   factory StreamController(
       {void onListen()?,
       void onPause()?,
@@ -84,57 +76,55 @@
         : _AsyncStreamController<T>(onListen, onPause, onResume, onCancel);
   }
 
-  /**
-   * A controller where [stream] can be listened to more than once.
-   *
-   * The [Stream] returned by [stream] is a broadcast stream.
-   * It can be listened to more than once.
-   *
-   * A Stream should be inert until a subscriber starts listening on it (using
-   * the [onListen] callback to start producing events). Streams should not
-   * leak resources (like websockets) when no user ever listens on the stream.
-   *
-   * Broadcast streams do not buffer events when there is no listener.
-   *
-   * The controller distributes any events to all currently subscribed
-   * listeners at the time when [add], [addError] or [close] is called.
-   * It is not allowed to call `add`, `addError`, or `close` before a previous
-   * call has returned. The controller does not have any internal queue of
-   * events, and if there are no listeners at the time the event is added,
-   * it will just be dropped, or, if it is an error, be reported as uncaught.
-   *
-   * Each listener subscription is handled independently,
-   * and if one pauses, only the pausing listener is affected.
-   * A paused listener will buffer events internally until unpaused or canceled.
-   *
-   * If [sync] is true, events may be fired directly by the stream's
-   * subscriptions during an [add], [addError] or [close] call.
-   * The returned stream controller is a [SynchronousStreamController],
-   * and must be used with the care and attention necessary to not break
-   * the [Stream] contract.
-   * See [Completer.sync] for some explanations on when a synchronous
-   * dispatching can be used.
-   * If in doubt, keep the controller non-sync.
-   *
-   * If [sync] is false, the event will always be fired at a later time,
-   * after the code adding the event has completed.
-   * In that case, no guarantees are given with regard to when
-   * multiple listeners get the events, except that each listener will get
-   * all events in the correct order. Each subscription handles the events
-   * individually.
-   * If two events are sent on an async controller with two listeners,
-   * one of the listeners may get both events
-   * before the other listener gets any.
-   * A listener must be subscribed both when the event is initiated
-   * (that is, when [add] is called)
-   * and when the event is later delivered,
-   * in order to receive the event.
-   *
-   * The [onListen] callback is called when the first listener is subscribed,
-   * and the [onCancel] is called when there are no longer any active listeners.
-   * If a listener is added again later, after the [onCancel] was called,
-   * the [onListen] will be called again.
-   */
+  /// A controller where [stream] can be listened to more than once.
+  ///
+  /// The [Stream] returned by [stream] is a broadcast stream.
+  /// It can be listened to more than once.
+  ///
+  /// A Stream should be inert until a subscriber starts listening on it (using
+  /// the [onListen] callback to start producing events). Streams should not
+  /// leak resources (like websockets) when no user ever listens on the stream.
+  ///
+  /// Broadcast streams do not buffer events when there is no listener.
+  ///
+  /// The controller distributes any events to all currently subscribed
+  /// listeners at the time when [add], [addError] or [close] is called.
+  /// It is not allowed to call `add`, `addError`, or `close` before a previous
+  /// call has returned. The controller does not have any internal queue of
+  /// events, and if there are no listeners at the time the event is added,
+  /// it will just be dropped, or, if it is an error, be reported as uncaught.
+  ///
+  /// Each listener subscription is handled independently,
+  /// and if one pauses, only the pausing listener is affected.
+  /// A paused listener will buffer events internally until unpaused or canceled.
+  ///
+  /// If [sync] is true, events may be fired directly by the stream's
+  /// subscriptions during an [add], [addError] or [close] call.
+  /// The returned stream controller is a [SynchronousStreamController],
+  /// and must be used with the care and attention necessary to not break
+  /// the [Stream] contract.
+  /// See [Completer.sync] for some explanations on when a synchronous
+  /// dispatching can be used.
+  /// If in doubt, keep the controller non-sync.
+  ///
+  /// If [sync] is false, the event will always be fired at a later time,
+  /// after the code adding the event has completed.
+  /// In that case, no guarantees are given with regard to when
+  /// multiple listeners get the events, except that each listener will get
+  /// all events in the correct order. Each subscription handles the events
+  /// individually.
+  /// If two events are sent on an async controller with two listeners,
+  /// one of the listeners may get both events
+  /// before the other listener gets any.
+  /// A listener must be subscribed both when the event is initiated
+  /// (that is, when [add] is called)
+  /// and when the event is later delivered,
+  /// in order to receive the event.
+  ///
+  /// The [onListen] callback is called when the first listener is subscribed,
+  /// and the [onCancel] is called when there are no longer any active listeners.
+  /// If a listener is added again later, after the [onCancel] was called,
+  /// the [onListen] will be called again.
   factory StreamController.broadcast(
       {void onListen()?, void onCancel()?, bool sync = false}) {
     return sync
@@ -142,259 +132,217 @@
         : _AsyncBroadcastStreamController<T>(onListen, onCancel);
   }
 
-  /**
-   * The callback which is called when the stream is listened to.
-   *
-   * May be set to `null`, in which case no callback will happen.
-   */
-  void Function()? get onListen;
+  /// The callback which is called when the stream is listened to.
+  ///
+  /// May be set to `null`, in which case no callback will happen.
+  abstract void Function()? onListen;
 
-  void set onListen(void onListenHandler()?);
+  /// The callback which is called when the stream is paused.
+  ///
+  /// May be set to `null`, in which case no callback will happen.
+  ///
+  /// Pause related callbacks are not supported on broadcast stream controllers.
+  abstract void Function()? onPause;
 
-  /**
-   * The callback which is called when the stream is paused.
-   *
-   * May be set to `null`, in which case no callback will happen.
-   *
-   * Pause related callbacks are not supported on broadcast stream controllers.
-   */
-  void Function()? get onPause;
+  /// The callback which is called when the stream is resumed.
+  ///
+  /// May be set to `null`, in which case no callback will happen.
+  ///
+  /// Pause related callbacks are not supported on broadcast stream controllers.
+  abstract void Function()? onResume;
 
-  void set onPause(void onPauseHandler()?);
+  /// The callback which is called when the stream is canceled.
+  ///
+  /// May be set to `null`, in which case no callback will happen.
+  abstract FutureOr<void> Function()? onCancel;
 
-  /**
-   * The callback which is called when the stream is resumed.
-   *
-   * May be set to `null`, in which case no callback will happen.
-   *
-   * Pause related callbacks are not supported on broadcast stream controllers.
-   */
-  void Function()? get onResume;
-
-  void set onResume(void onResumeHandler()?);
-
-  /**
-   * The callback which is called when the stream is canceled.
-   *
-   * May be set to `null`, in which case no callback will happen.
-   */
-  FutureOr<void> Function()? get onCancel;
-
-  void set onCancel(FutureOr<void> onCancelHandler()?);
-
-  /**
-   * Returns a view of this object that only exposes the [StreamSink] interface.
-   */
+  /// Returns a view of this object that only exposes the [StreamSink] interface.
   StreamSink<T> get sink;
 
-  /**
-   * Whether the stream controller is closed for adding more events.
-   *
-   * The controller becomes closed by calling the [close] method.
-   * New events cannot be added, by calling [add] or [addError],
-   * to a closed controller.
-   *
-   * If the controller is closed,
-   * the "done" event might not have been delivered yet,
-   * but it has been scheduled, and it is too late to add more events.
-   */
+  /// Whether the stream controller is closed for adding more events.
+  ///
+  /// The controller becomes closed by calling the [close] method.
+  /// New events cannot be added, by calling [add] or [addError],
+  /// to a closed controller.
+  ///
+  /// If the controller is closed,
+  /// the "done" event might not have been delivered yet,
+  /// but it has been scheduled, and it is too late to add more events.
   bool get isClosed;
 
-  /**
-   * Whether the subscription would need to buffer events.
-   *
-   * This is the case if the controller's stream has a listener and it is
-   * paused, or if it has not received a listener yet. In that case, the
-   * controller is considered paused as well.
-   *
-   * A broadcast stream controller is never considered paused. It always
-   * forwards its events to all uncanceled subscriptions, if any,
-   * and let the subscriptions handle their own pausing and buffering.
-   */
+  /// Whether the subscription would need to buffer events.
+  ///
+  /// This is the case if the controller's stream has a listener and it is
+  /// paused, or if it has not received a listener yet. In that case, the
+  /// controller is considered paused as well.
+  ///
+  /// A broadcast stream controller is never considered paused. It always
+  /// forwards its events to all uncanceled subscriptions, if any,
+  /// and let the subscriptions handle their own pausing and buffering.
   bool get isPaused;
 
-  /** Whether there is a subscriber on the [Stream]. */
+  /// Whether there is a subscriber on the [Stream].
   bool get hasListener;
 
-  /**
-   * Sends a data [event].
-   *
-   * Listeners receive this event in a later microtask.
-   *
-   * Note that a synchronous controller (created by passing true to the `sync`
-   * parameter of the `StreamController` constructor) delivers events
-   * immediately. Since this behavior violates the contract mentioned here,
-   * synchronous controllers should only be used as described in the
-   * documentation to ensure that the delivered events always *appear* as if
-   * they were delivered in a separate microtask.
-   */
+  /// Sends a data [event].
+  ///
+  /// Listeners receive this event in a later microtask.
+  ///
+  /// Note that a synchronous controller (created by passing true to the `sync`
+  /// parameter of the `StreamController` constructor) delivers events
+  /// immediately. Since this behavior violates the contract mentioned here,
+  /// synchronous controllers should only be used as described in the
+  /// documentation to ensure that the delivered events always *appear* as if
+  /// they were delivered in a separate microtask.
   void add(T event);
 
-  /**
-   * Sends or enqueues an error event.
-   *
-   * If [error] is `null`, it is replaced by a [NullThrownError].
-   *
-   * Listeners receive this event at a later microtask. This behavior can be
-   * overridden by using `sync` controllers. Note, however, that sync
-   * controllers have to satisfy the preconditions mentioned in the
-   * documentation of the constructors.
-   */
+  /// Sends or enqueues an error event.
+  ///
+  /// Listeners receive this event at a later microtask. This behavior can be
+  /// overridden by using `sync` controllers. Note, however, that sync
+  /// controllers have to satisfy the preconditions mentioned in the
+  /// documentation of the constructors.
   void addError(Object error, [StackTrace? stackTrace]);
 
-  /**
-   * Closes the stream.
-   *
-   * No further events can be added to a closed stream.
-   *
-   * The returned future is the same future provided by [done].
-   * It is completed when the stream listeners is done sending events,
-   * This happens either when the done event has been sent,
-   * or when the subscriber on a single-subscription stream is canceled.
-   *
-   * A broadcast stream controller will send the done event
-   * even if listeners are paused, so some broadcast events may not have been
-   * received yet when the returned future completes.
-   *
-   * If noone listens to a non-broadcast stream,
-   * or the listener pauses and never resumes,
-   * the done event will not be sent and this future will never complete.
-   */
+  /// Closes the stream.
+  ///
+  /// No further events can be added to a closed stream.
+  ///
+  /// The returned future is the same future provided by [done].
+  /// It is completed when the stream listeners is done sending events,
+  /// This happens either when the done event has been sent,
+  /// or when the subscriber on a single-subscription stream is canceled.
+  ///
+  /// A broadcast stream controller will send the done event
+  /// even if listeners are paused, so some broadcast events may not have been
+  /// received yet when the returned future completes.
+  ///
+  /// If noone listens to a non-broadcast stream,
+  /// or the listener pauses and never resumes,
+  /// the done event will not be sent and this future will never complete.
   Future close();
 
-  /**
-   * A future which is completed when the stream controller is done
-   * sending events.
-   *
-   * This happens either when the done event has been sent, or if the
-   * subscriber on a single-subscription stream is canceled.
-   *
-   * A broadcast stream controller will send the done event
-   * even if listeners are paused, so some broadcast events may not have been
-   * received yet when the returned future completes.
-   *
-   * If there is no listener on a non-broadcast stream,
-   * or the listener pauses and never resumes,
-   * the done event will not be sent and this future will never complete.
-   */
+  /// A future which is completed when the stream controller is done
+  /// sending events.
+  ///
+  /// This happens either when the done event has been sent, or if the
+  /// subscriber on a single-subscription stream is canceled.
+  ///
+  /// A broadcast stream controller will send the done event
+  /// even if listeners are paused, so some broadcast events may not have been
+  /// received yet when the returned future completes.
+  ///
+  /// If there is no listener on a non-broadcast stream,
+  /// or the listener pauses and never resumes,
+  /// the done event will not be sent and this future will never complete.
   Future get done;
 
-  /**
-   * Receives events from [source] and puts them into this controller's stream.
-   *
-   * Returns a future which completes when the source stream is done.
-   *
-   * Events must not be added directly to this controller using [add],
-   * [addError], [close] or [addStream], until the returned future
-   * is complete.
-   *
-   * Data and error events are forwarded to this controller's stream. A done
-   * event on the source will end the `addStream` operation and complete the
-   * returned future.
-   *
-   * If [cancelOnError] is true, only the first error on [source] is
-   * forwarded to the controller's stream, and the `addStream` ends
-   * after this. If [cancelOnError] is false, all errors are forwarded
-   * and only a done event will end the `addStream`.
-   * If [cancelOnError] is omitted or `null`, it defaults to false.
-   */
+  /// Receives events from [source] and puts them into this controller's stream.
+  ///
+  /// Returns a future which completes when the source stream is done.
+  ///
+  /// Events must not be added directly to this controller using [add],
+  /// [addError], [close] or [addStream], until the returned future
+  /// is complete.
+  ///
+  /// Data and error events are forwarded to this controller's stream. A done
+  /// event on the source will end the `addStream` operation and complete the
+  /// returned future.
+  ///
+  /// If [cancelOnError] is `true`, only the first error on [source] is
+  /// forwarded to the controller's stream, and the `addStream` ends
+  /// after this. If [cancelOnError] is false, all errors are forwarded
+  /// and only a done event will end the `addStream`.
+  /// If [cancelOnError] is omitted or `null`, it defaults to `false`.
   Future addStream(Stream<T> source, {bool? cancelOnError});
 }
 
-/**
- * A stream controller that delivers its events synchronously.
- *
- * A synchronous stream controller is intended for cases where
- * an already asynchronous event triggers an event on a stream.
- *
- * Instead of adding the event to the stream in a later microtask,
- * causing extra latency, the event is instead fired immediately by the
- * synchronous stream controller, as if the stream event was
- * the current event or microtask.
- *
- * The synchronous stream controller can be used to break the contract
- * on [Stream], and it must be used carefully to avoid doing so.
- *
- * The only advantage to using a [SynchronousStreamController] over a
- * normal [StreamController] is the improved latency.
- * Only use the synchronous version if the improvement is significant,
- * and if its use is safe. Otherwise just use a normal stream controller,
- * which will always have the correct behavior for a [Stream], and won't
- * accidentally break other code.
- *
- * Adding events to a synchronous controller should only happen as the
- * very last part of the handling of the original event.
- * At that point, adding an event to the stream is equivalent to
- * returning to the event loop and adding the event in the next microtask.
- *
- * Each listener callback will be run as if it was a top-level event
- * or microtask. This means that if it throws, the error will be reported as
- * uncaught as soon as possible.
- * This is one reason to add the event as the last thing in the original event
- * handler - any action done after adding the event will delay the report of
- * errors in the event listener callbacks.
- *
- * If an event is added in a setting that isn't known to be another event,
- * it may cause the stream's listener to get that event before the listener
- * is ready to handle it. We promise that after calling [Stream.listen],
- * you won't get any events until the code doing the listen has completed.
- * Calling [add] in response to a function call of unknown origin may break
- * that promise.
- *
- * An [onListen] callback from the controller is *not* an asynchronous event,
- * and adding events to the controller in the `onListen` callback is always
- * wrong. The events will be delivered before the listener has even received
- * the subscription yet.
- *
- * The synchronous broadcast stream controller also has a restrictions that a
- * normal stream controller does not:
- * The [add], [addError], [close] and [addStream] methods *must not* be
- * called while an event is being delivered.
- * That is, if a callback on a subscription on the controller's stream causes
- * a call to any of the functions above, the call will fail.
- * A broadcast stream may have more than one listener, and if an
- * event is added synchronously while another is being also in the process
- * of being added, the latter event might reach some listeners before
- * the former. To prevent that, an event cannot be added while a previous
- * event is being fired.
- * This guarantees that an event is fully delivered when the
- * first [add], [addError] or [close] returns,
- * and further events will be delivered in the correct order.
- *
- * This still only guarantees that the event is delivered to the subscription.
- * If the subscription is paused, the actual callback may still happen later,
- * and the event will instead be buffered by the subscription.
- * Barring pausing, and the following buffered events that haven't been
- * delivered yet, callbacks will be called synchronously when an event is added.
- *
- * Adding an event to a synchronous non-broadcast stream controller while
- * another event is in progress may cause the second event to be delayed
- * and not be delivered synchronously, and until that event is delivered,
- * the controller will not act synchronously.
- */
+/// A stream controller that delivers its events synchronously.
+///
+/// A synchronous stream controller is intended for cases where
+/// an already asynchronous event triggers an event on a stream.
+///
+/// Instead of adding the event to the stream in a later microtask,
+/// causing extra latency, the event is instead fired immediately by the
+/// synchronous stream controller, as if the stream event was
+/// the current event or microtask.
+///
+/// The synchronous stream controller can be used to break the contract
+/// on [Stream], and it must be used carefully to avoid doing so.
+///
+/// The only advantage to using a [SynchronousStreamController] over a
+/// normal [StreamController] is the improved latency.
+/// Only use the synchronous version if the improvement is significant,
+/// and if its use is safe. Otherwise just use a normal stream controller,
+/// which will always have the correct behavior for a [Stream], and won't
+/// accidentally break other code.
+///
+/// Adding events to a synchronous controller should only happen as the
+/// very last part of the handling of the original event.
+/// At that point, adding an event to the stream is equivalent to
+/// returning to the event loop and adding the event in the next microtask.
+///
+/// Each listener callback will be run as if it was a top-level event
+/// or microtask. This means that if it throws, the error will be reported as
+/// uncaught as soon as possible.
+/// This is one reason to add the event as the last thing in the original event
+/// handler - any action done after adding the event will delay the report of
+/// errors in the event listener callbacks.
+///
+/// If an event is added in a setting that isn't known to be another event,
+/// it may cause the stream's listener to get that event before the listener
+/// is ready to handle it. We promise that after calling [Stream.listen],
+/// you won't get any events until the code doing the listen has completed.
+/// Calling [add] in response to a function call of unknown origin may break
+/// that promise.
+///
+/// An [onListen] callback from the controller is *not* an asynchronous event,
+/// and adding events to the controller in the `onListen` callback is always
+/// wrong. The events will be delivered before the listener has even received
+/// the subscription yet.
+///
+/// The synchronous broadcast stream controller also has a restrictions that a
+/// normal stream controller does not:
+/// The [add], [addError], [close] and [addStream] methods *must not* be
+/// called while an event is being delivered.
+/// That is, if a callback on a subscription on the controller's stream causes
+/// a call to any of the functions above, the call will fail.
+/// A broadcast stream may have more than one listener, and if an
+/// event is added synchronously while another is being also in the process
+/// of being added, the latter event might reach some listeners before
+/// the former. To prevent that, an event cannot be added while a previous
+/// event is being fired.
+/// This guarantees that an event is fully delivered when the
+/// first [add], [addError] or [close] returns,
+/// and further events will be delivered in the correct order.
+///
+/// This still only guarantees that the event is delivered to the subscription.
+/// If the subscription is paused, the actual callback may still happen later,
+/// and the event will instead be buffered by the subscription.
+/// Barring pausing, and the following buffered events that haven't been
+/// delivered yet, callbacks will be called synchronously when an event is added.
+///
+/// Adding an event to a synchronous non-broadcast stream controller while
+/// another event is in progress may cause the second event to be delayed
+/// and not be delivered synchronously, and until that event is delivered,
+/// the controller will not act synchronously.
 abstract class SynchronousStreamController<T> implements StreamController<T> {
-  /**
-   * Adds event to the controller's stream.
-   *
-   * As [StreamController.add], but must not be called while an event is
-   * being added by [add], [addError] or [close].
-   */
+  /// Adds event to the controller's stream.
+  ///
+  /// As [StreamController.add], but must not be called while an event is
+  /// being added by [add], [addError] or [close].
   void add(T data);
 
-  /**
-   * Adds error to the controller's stream.
-   *
-   * As [StreamController.addError], but must not be called while an event is
-   * being added by [add], [addError] or [close].
-   */
+  /// Adds error to the controller's stream.
+  ///
+  /// As [StreamController.addError], but must not be called while an event is
+  /// being added by [add], [addError] or [close].
   void addError(Object error, [StackTrace? stackTrace]);
 
-  /**
-   * Closes the controller's stream.
-   *
-   * As [StreamController.close], but must not be called while an event is
-   * being added by [add], [addError] or [close].
-   */
+  /// Closes the controller's stream.
+  ///
+  /// As [StreamController.close], but must not be called while an event is
+  /// being added by [add], [addError] or [close].
   Future close();
 }
 
@@ -414,11 +362,9 @@
         _EventSink<T>,
         _EventDispatch<T> {}
 
-/**
- * Default implementation of [StreamController].
- *
- * Controls a stream that only supports a single controller.
- */
+/// Default implementation of [StreamController].
+///
+/// Controls a stream that only supports a single controller.
 abstract class _StreamController<T> implements _StreamControllerBase<T> {
   // The states are bit-flags. More than one can be set at a time.
   //
@@ -430,18 +376,19 @@
   // subscription, the done event is queued. If done after cancel, the done
   // event is ignored (just as any other event after a cancel).
 
-  /** The controller is in its initial state with no subscription. */
+  /// The controller is in its initial state with no subscription.
   static const int _STATE_INITIAL = 0;
-  /**
-   * The controller has a subscription, but hasn't been closed or canceled.
-   *
-   * Keep in sync with
-   * runtime/vm/stack_trace.cc:kStreamController_StateSubscribed.
-   */
+
+  /// The controller has a subscription, but hasn't been closed or canceled.
+  ///
+  /// Keep in sync with
+  /// runtime/vm/stack_trace.cc:kStreamController_StateSubscribed.
   static const int _STATE_SUBSCRIBED = 1;
-  /** The subscription is canceled. */
+
+  /// The subscription is canceled.
   static const int _STATE_CANCELED = 2;
-  /** Mask for the subscription state. */
+
+  /// Mask for the subscription state.
   static const int _STATE_SUBSCRIPTION_MASK = 3;
 
   // The following state relate to the controller, not the subscription.
@@ -449,45 +396,38 @@
   // If executing an [addStream], new events are not allowed either, but will
   // be added by the stream.
 
-  /**
-   * The controller is closed due to calling [close].
-   *
-   * When the stream is closed, you can neither add new events nor add new
-   * listeners.
-   */
+  /// The controller is closed due to calling [close].
+  ///
+  /// When the stream is closed, you can neither add new events nor add new
+  /// listeners.
   static const int _STATE_CLOSED = 4;
-  /**
-   * The controller is in the middle of an [addStream] operation.
-   *
-   * While adding events from a stream, no new events can be added directly
-   * on the controller.
-   */
+
+  /// The controller is in the middle of an [addStream] operation.
+  ///
+  /// While adding events from a stream, no new events can be added directly
+  /// on the controller.
   static const int _STATE_ADDSTREAM = 8;
 
-  /**
-   * Field containing different data depending on the current subscription
-   * state.
-   *
-   * If [_state] is [_STATE_INITIAL], the field may contain a [_PendingEvents]
-   * for events added to the controller before a subscription.
-   *
-   * While [_state] is [_STATE_SUBSCRIBED], the field contains the subscription.
-   *
-   * When [_state] is [_STATE_CANCELED] the field is currently not used,
-   * and will contain `null`.
-   */
+  /// Field containing different data depending on the current subscription
+  /// state.
+  ///
+  /// If [_state] is [_STATE_INITIAL], the field may contain a [_PendingEvents]
+  /// for events added to the controller before a subscription.
+  ///
+  /// While [_state] is [_STATE_SUBSCRIBED], the field contains the subscription.
+  ///
+  /// When [_state] is [_STATE_CANCELED] the field is currently not used,
+  /// and will contain `null`.
   @pragma("vm:entry-point")
   Object? _varData;
 
-  /** Current state of the controller. */
+  /// Current state of the controller.
   @pragma("vm:entry-point")
   int _state = _STATE_INITIAL;
 
-  /**
-   * Future completed when the stream sends its last event.
-   *
-   * This is also the future returned by [close].
-   */
+  /// Future completed when the stream sends its last event.
+  ///
+  /// This is also the future returned by [close].
   // TODO(lrn): Could this be stored in the varData field too, if it's not
   // accessed until the call to "close"? Then we need to special case if it's
   // accessed earlier, or if close is called before subscribing.
@@ -503,22 +443,18 @@
   // Return a new stream every time. The streams are equal, but not identical.
   Stream<T> get stream => _ControllerStream<T>(this);
 
-  /**
-   * Returns a view of this object that only exposes the [StreamSink] interface.
-   */
+  /// Returns a view of this object that only exposes the [StreamSink] interface.
   StreamSink<T> get sink => _StreamSinkWrapper<T>(this);
 
-  /**
-   * Whether a listener has existed and been canceled.
-   *
-   * After this, adding more events will be ignored.
-   */
+  /// Whether a listener has existed and been canceled.
+  ///
+  /// After this, adding more events will be ignored.
   bool get _isCanceled => (_state & _STATE_CANCELED) != 0;
 
-  /** Whether there is an active listener. */
+  /// Whether there is an active listener.
   bool get hasListener => (_state & _STATE_SUBSCRIBED) != 0;
 
-  /** Whether there has not been a listener yet. */
+  /// Whether there has not been a listener yet.
   bool get _isInitialState =>
       (_state & _STATE_SUBSCRIPTION_MASK) == _STATE_INITIAL;
 
@@ -529,7 +465,7 @@
 
   bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0;
 
-  /** New events may not be added after close, or during addStream. */
+  /// New events may not be added after close, or during addStream.
   bool get _mayAddEvent => (_state < _STATE_CLOSED);
 
   // Returns the pending events.
@@ -579,11 +515,9 @@
     return varData as dynamic;
   }
 
-  /**
-   * Creates an error describing why an event cannot be added.
-   *
-   * The reason, and therefore the error message, depends on the current state.
-   */
+  /// Creates an error describing why an event cannot be added.
+  ///
+  /// The reason, and therefore the error message, depends on the current state.
   Error _badEventState() {
     if (isClosed) {
       return StateError("Cannot add event after closing");
@@ -604,29 +538,23 @@
     return addState.addStreamFuture;
   }
 
-  /**
-   * Returns a future that is completed when the stream is done
-   * processing events.
-   *
-   * This happens either when the done event has been sent, or if the
-   * subscriber of a single-subscription stream is cancelled.
-   */
+  /// Returns a future that is completed when the stream is done
+  /// processing events.
+  ///
+  /// This happens either when the done event has been sent, or if the
+  /// subscriber of a single-subscription stream is cancelled.
   Future<void> get done => _ensureDoneFuture();
 
   Future<void> _ensureDoneFuture() =>
       _doneFuture ??= _isCanceled ? Future._nullFuture : _Future<void>();
 
-  /**
-   * Send or enqueue a data event.
-   */
+  /// Send or enqueue a data event.
   void add(T value) {
     if (!_mayAddEvent) throw _badEventState();
     _add(value);
   }
 
-  /**
-   * Send or enqueue an error event.
-   */
+  /// Send or enqueue an error event.
   void addError(Object error, [StackTrace? stackTrace]) {
     checkNotNullable(error, "error");
     if (!_mayAddEvent) throw _badEventState();
@@ -641,20 +569,18 @@
     _addError(error, stackTrace);
   }
 
-  /**
-   * Closes this controller and sends a done event on the stream.
-   *
-   * The first time a controller is closed, a "done" event is added to its
-   * stream.
-   *
-   * You are allowed to close the controller more than once, but only the first
-   * call has any effect.
-   *
-   * After closing, no further events may be added using [add], [addError]
-   * or [addStream].
-   *
-   * The returned future is completed when the done event has been delivered.
-   */
+  /// Closes this controller and sends a done event on the stream.
+  ///
+  /// The first time a controller is closed, a "done" event is added to its
+  /// stream.
+  ///
+  /// You are allowed to close the controller more than once, but only the first
+  /// call has any effect.
+  ///
+  /// After closing, no further events may be added using [add], [addError]
+  /// or [addStream].
+  ///
+  /// The returned future is completed when the done event has been delivered.
   Future close() {
     if (isClosed) {
       return _ensureDoneFuture();
@@ -892,7 +818,7 @@
   }
 }
 
-/** A class that exposes only the [StreamSink] interface of an object. */
+/// A class that exposes only the [StreamSink] interface of an object.
 class _StreamSinkWrapper<T> implements StreamSink<T> {
   final StreamController _target;
   _StreamSinkWrapper(this._target);
@@ -911,9 +837,7 @@
   Future get done => _target.done;
 }
 
-/**
- * Object containing the state used to handle [StreamController.addStream].
- */
+/// Object containing the state used to handle [StreamController.addStream].
 class _AddStreamState<T> {
   // [_Future] returned by call to addStream.
   final _Future addStreamFuture;
@@ -944,14 +868,12 @@
     addSubscription.resume();
   }
 
-  /**
-   * Stop adding the stream.
-   *
-   * Complete the future returned by `StreamController.addStream` when
-   * the cancel is complete.
-   *
-   * Return a future if the cancel takes time, otherwise return `null`.
-   */
+  /// Stop adding the stream.
+  ///
+  /// Complete the future returned by `StreamController.addStream` when
+  /// the cancel is complete.
+  ///
+  /// Return a future if the cancel takes time, otherwise return `null`.
   Future<void> cancel() {
     var cancel = addSubscription.cancel();
     if (cancel == null) {
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index bb4a1ba..02c4504 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -4,83 +4,75 @@
 
 part of dart.async;
 
-/** Abstract and private interface for a place to put events. */
+/// Abstract and private interface for a place to put events.
 abstract class _EventSink<T> {
   void _add(T data);
   void _addError(Object error, StackTrace stackTrace);
   void _close();
 }
 
-/**
- * Abstract and private interface for a place to send events.
- *
- * Used by event buffering to finally dispatch the pending event, where
- * [_EventSink] is where the event first enters the stream subscription,
- * and may yet be buffered.
- */
+/// Abstract and private interface for a place to send events.
+///
+/// Used by event buffering to finally dispatch the pending event, where
+/// [_EventSink] is where the event first enters the stream subscription,
+/// and may yet be buffered.
 abstract class _EventDispatch<T> {
   void _sendData(T data);
   void _sendError(Object error, StackTrace stackTrace);
   void _sendDone();
 }
 
-/**
- * Default implementation of stream subscription of buffering events.
- *
- * The only public methods are those of [StreamSubscription], so instances of
- * [_BufferingStreamSubscription] can be returned directly as a
- * [StreamSubscription] without exposing internal functionality.
- *
- * The [StreamController] is a public facing version of [Stream] and this class,
- * with some methods made public.
- *
- * The user interface of [_BufferingStreamSubscription] are the following
- * methods:
- *
- * * [_add]: Add a data event to the stream.
- * * [_addError]: Add an error event to the stream.
- * * [_close]: Request to close the stream.
- * * [_onCancel]: Called when the subscription will provide no more events,
- *     either due to being actively canceled, or after sending a done event.
- * * [_onPause]: Called when the subscription wants the event source to pause.
- * * [_onResume]: Called when allowing new events after a pause.
- *
- * The user should not add new events when the subscription requests a paused,
- * but if it happens anyway, the subscription will enqueue the events just as
- * when new events arrive while still firing an old event.
- */
+/// Default implementation of stream subscription of buffering events.
+///
+/// The only public methods are those of [StreamSubscription], so instances of
+/// [_BufferingStreamSubscription] can be returned directly as a
+/// [StreamSubscription] without exposing internal functionality.
+///
+/// The [StreamController] is a public facing version of [Stream] and this class,
+/// with some methods made public.
+///
+/// The user interface of [_BufferingStreamSubscription] are the following
+/// methods:
+///
+/// * [_add]: Add a data event to the stream.
+/// * [_addError]: Add an error event to the stream.
+/// * [_close]: Request to close the stream.
+/// * [_onCancel]: Called when the subscription will provide no more events,
+///     either due to being actively canceled, or after sending a done event.
+/// * [_onPause]: Called when the subscription wants the event source to pause.
+/// * [_onResume]: Called when allowing new events after a pause.
+///
+/// The user should not add new events when the subscription requests a paused,
+/// but if it happens anyway, the subscription will enqueue the events just as
+/// when new events arrive while still firing an old event.
 class _BufferingStreamSubscription<T>
     implements StreamSubscription<T>, _EventSink<T>, _EventDispatch<T> {
-  /** The `cancelOnError` flag from the `listen` call. */
+  /// The `cancelOnError` flag from the `listen` call.
   static const int _STATE_CANCEL_ON_ERROR = 1;
-  /**
-   * Whether the "done" event has been received.
-   * No further events are accepted after this.
-   */
+
+  /// Whether the "done" event has been received.
+  /// No further events are accepted after this.
   static const int _STATE_CLOSED = 2;
-  /**
-   * Set if the input has been asked not to send events.
-   *
-   * This is not the same as being paused, since the input will remain paused
-   * after a call to [resume] if there are pending events.
-   */
+
+  /// Set if the input has been asked not to send events.
+  ///
+  /// This is not the same as being paused, since the input will remain paused
+  /// after a call to [resume] if there are pending events.
   static const int _STATE_INPUT_PAUSED = 4;
-  /**
-   * Whether the subscription has been canceled.
-   *
-   * Set by calling [cancel], or by handling a "done" event, or an "error" event
-   * when `cancelOnError` is true.
-   */
+
+  /// Whether the subscription has been canceled.
+  ///
+  /// Set by calling [cancel], or by handling a "done" event, or an "error" event
+  /// when `cancelOnError` is true.
   static const int _STATE_CANCELED = 8;
-  /**
-   * Set when either:
-   *
-   *   * an error is sent, and [cancelOnError] is true, or
-   *   * a done event is sent.
-   *
-   * If the subscription is canceled while _STATE_WAIT_FOR_CANCEL is set, the
-   * state is unset, and no further events must be delivered.
-   */
+
+  /// Set when either:
+  ///
+  ///   * an error is sent, and [cancelOnError] is true, or
+  ///   * a done event is sent.
+  ///
+  /// If the subscription is canceled while _STATE_WAIT_FOR_CANCEL is set, the
+  /// state is unset, and no further events must be delivered.
   static const int _STATE_WAIT_FOR_CANCEL = 16;
   static const int _STATE_IN_CALLBACK = 32;
   static const int _STATE_HAS_PENDING = 64;
@@ -94,18 +86,16 @@
 
   final Zone _zone;
 
-  /** Bit vector based on state-constants above. */
+  /// Bit vector based on state-constants above.
   int _state;
 
   // TODO(floitsch): reuse another field
-  /** The future [_onCancel] may return. */
+  /// The future [_onCancel] may return.
   Future? _cancelFuture;
 
-  /**
-   * Queue of pending events.
-   *
-   * Is created when necessary, or set in constructor for preconfigured events.
-   */
+  /// Queue of pending events.
+  ///
+  /// Is created when necessary, or set in constructor for preconfigured events.
   _PendingEvents<T>? _pending;
 
   _BufferingStreamSubscription(void onData(T data)?, Function? onError,
@@ -119,12 +109,10 @@
         _onError = _registerErrorHandler(_zone, onError),
         _onDone = _registerDoneHandler(_zone, onDone);
 
-  /**
-   * Sets the subscription's pending events object.
-   *
-   * This can only be done once. The pending events object is used for the
-   * rest of the subscription's life cycle.
-   */
+  /// Sets the subscription's pending events object.
+  ///
+  /// This can only be done once. The pending events object is used for the
+  /// rest of the subscription's life cycle.
   void _setPendingEvents(_PendingEvents<T>? pendingEvents) {
     assert(_pending == null);
     if (pendingEvents == null) return;
@@ -264,13 +252,11 @@
     _cancelFuture = _onCancel();
   }
 
-  /**
-   * Decrements the pause count.
-   *
-   * Does not automatically unpause the input (call [_onResume]) when
-   * the pause count reaches zero. This is handled elsewhere, and only
-   * if there are no pending events buffered.
-   */
+  /// Decrements the pause count.
+  ///
+  /// Does not automatically unpause the input (call [_onResume]) when
+  /// the pause count reaches zero. This is handled elsewhere, and only
+  /// if there are no pending events buffered.
   void _decrementPauseCount() {
     assert(_isPaused);
     _state -= _STATE_PAUSE_COUNT;
@@ -327,12 +313,10 @@
 
   // Handle pending events.
 
-  /**
-   * Add a pending event.
-   *
-   * If the subscription is not paused, this also schedules a firing
-   * of pending events later (if necessary).
-   */
+  /// Add a pending event.
+  ///
+  /// If the subscription is not paused, this also schedules a firing
+  /// of pending events later (if necessary).
   void _addPending(_DelayedEvent event) {
     _StreamImplEvents<T>? pending = _pending as dynamic;
     pending ??= _StreamImplEvents<T>();
@@ -421,13 +405,11 @@
     }
   }
 
-  /**
-   * Call a hook function.
-   *
-   * The call is properly wrapped in code to avoid other callbacks
-   * during the call, and it checks for state changes after the call
-   * that should cause further callbacks.
-   */
+  /// Call a hook function.
+  ///
+  /// The call is properly wrapped in code to avoid other callbacks
+  /// during the call, and it checks for state changes after the call
+  /// that should cause further callbacks.
   void _guardCallback(void Function() callback) {
     assert(!_inCallback);
     bool wasInputPaused = _isInputPaused;
@@ -437,16 +419,14 @@
     _checkState(wasInputPaused);
   }
 
-  /**
-   * Check if the input needs to be informed of state changes.
-   *
-   * State changes are pausing, resuming and canceling.
-   *
-   * After canceling, no further callbacks will happen.
-   *
-   * The cancel callback is called after a user cancel, or after
-   * the final done event is sent.
-   */
+  /// Check if the input needs to be informed of state changes.
+  ///
+  /// State changes are pausing, resuming and canceling.
+  ///
+  /// After canceling, no further callbacks will happen.
+  ///
+  /// The cancel callback is called after a user cancel, or after
+  /// the final done event is sent.
   void _checkState(bool wasInputPaused) {
     assert(!_inCallback);
     if (_hasPending && _pending!.isEmpty) {
@@ -496,29 +476,28 @@
   }
 
   // -------------------------------------------------------------------
-  /** Create a subscription object. Called by [subcribe]. */
+  /// Create a subscription object. Called by [subcribe].
   StreamSubscription<T> _createSubscription(void onData(T data)?,
       Function? onError, void onDone()?, bool cancelOnError) {
     return new _BufferingStreamSubscription<T>(
         onData, onError, onDone, cancelOnError);
   }
 
-  /** Hook called when the subscription has been created. */
+  /// Hook called when the subscription has been created.
   void _onListen(StreamSubscription subscription) {}
 }
 
 typedef _PendingEvents<T> _EventGenerator<T>();
 
-/** Stream that generates its own events. */
+/// Stream that generates its own events.
 class _GeneratedStreamImpl<T> extends _StreamImpl<T> {
   final _EventGenerator<T> _pending;
   bool _isUsed = false;
-  /**
-   * Initializes the stream to have only the events provided by a
-   * [_PendingEvents].
-   *
-   * A new [_PendingEvents] must be generated for each listen.
-   */
+
+  /// Initializes the stream to have only the events provided by a
+  /// [_PendingEvents].
+  ///
+  /// A new [_PendingEvents] must be generated for each listen.
   _GeneratedStreamImpl(this._pending);
 
   StreamSubscription<T> _createSubscription(void onData(T data)?,
@@ -531,7 +510,7 @@
   }
 }
 
-/** Pending events object that gets its events from an [Iterable]. */
+/// Pending events object that gets its events from an [Iterable].
 class _IterablePendingEvents<T> extends _PendingEvents<T> {
   // The iterator providing data for data events.
   // Set to null when iteration has completed.
@@ -584,26 +563,27 @@
 typedef void _DataHandler<T>(T value);
 typedef void _DoneHandler();
 
-/** Default data handler, does nothing. */
+/// Default data handler, does nothing.
 void _nullDataHandler(dynamic value) {}
 
-/** Default error handler, reports the error to the current zone's handler. */
+/// Default error handler, reports the error to the current zone's handler.
 void _nullErrorHandler(Object error, StackTrace stackTrace) {
   Zone.current.handleUncaughtError(error, stackTrace);
 }
 
-/** Default done handler, does nothing. */
+/// Default done handler, does nothing.
 void _nullDoneHandler() {}
 
-/** A delayed event on a buffering stream subscription. */
+/// A delayed event on a buffering stream subscription.
 abstract class _DelayedEvent<T> {
-  /** Added as a linked list on the [StreamController]. */
+  /// Added as a linked list on the [StreamController].
   _DelayedEvent? next;
-  /** Execute the delayed event on the [StreamController]. */
+
+  /// Execute the delayed event on the [StreamController].
   void perform(_EventDispatch<T> dispatch);
 }
 
-/** A delayed data event. */
+/// A delayed data event.
 class _DelayedData<T> extends _DelayedEvent<T> {
   final T value;
   _DelayedData(this.value);
@@ -612,7 +592,7 @@
   }
 }
 
-/** A delayed error event. */
+/// A delayed error event.
 class _DelayedError extends _DelayedEvent {
   final Object error;
   final StackTrace stackTrace;
@@ -623,7 +603,7 @@
   }
 }
 
-/** A delayed done event. */
+/// A delayed done event.
 class _DelayedDone implements _DelayedEvent {
   const _DelayedDone();
   void perform(_EventDispatch dispatch) {
@@ -637,7 +617,7 @@
   }
 }
 
-/** Superclass for provider of pending events. */
+/// Superclass for provider of pending events.
 abstract class _PendingEvents<T> {
   // No async event has been scheduled.
   static const int _STATE_UNSCHEDULED = 0;
@@ -647,18 +627,16 @@
   // Async events can't be preempted.
   static const int _STATE_CANCELED = 3;
 
-  /**
-   * State of being scheduled.
-   *
-   * Set to [_STATE_SCHEDULED] when pending events are scheduled for
-   * async dispatch. Since we can't cancel a [scheduleMicrotask] call, if
-   * scheduling is "canceled", the _state is simply set to [_STATE_CANCELED]
-   * which will make the async code do nothing except resetting [_state].
-   *
-   * If events are scheduled while the state is [_STATE_CANCELED], it is
-   * merely switched back to [_STATE_SCHEDULED], but no new call to
-   * [scheduleMicrotask] is performed.
-   */
+  /// State of being scheduled.
+  ///
+  /// Set to [_STATE_SCHEDULED] when pending events are scheduled for
+  /// async dispatch. Since we can't cancel a [scheduleMicrotask] call, if
+  /// scheduling is "canceled", the _state is simply set to [_STATE_CANCELED]
+  /// which will make the async code do nothing except resetting [_state].
+  ///
+  /// If events are scheduled while the state is [_STATE_CANCELED], it is
+  /// merely switched back to [_STATE_SCHEDULED], but no new call to
+  /// [scheduleMicrotask] is performed.
   int _state = _STATE_UNSCHEDULED;
 
   bool get isEmpty;
@@ -666,12 +644,10 @@
   bool get isScheduled => _state == _STATE_SCHEDULED;
   bool get _eventScheduled => _state >= _STATE_SCHEDULED;
 
-  /**
-   * Schedule an event to run later.
-   *
-   * If called more than once, it should be called with the same dispatch as
-   * argument each time. It may reuse an earlier argument in some cases.
-   */
+  /// Schedule an event to run later.
+  ///
+  /// If called more than once, it should be called with the same dispatch as
+  /// argument each time. It may reuse an earlier argument in some cases.
   void schedule(_EventDispatch<T> dispatch) {
     if (isScheduled) return;
     assert(!isEmpty);
@@ -695,11 +671,11 @@
 
   void handleNext(_EventDispatch<T> dispatch);
 
-  /** Throw away any pending events and cancel scheduled events. */
+  /// Throw away any pending events and cancel scheduled events.
   void clear();
 }
 
-/** Class holding pending events for a [_StreamImpl]. */
+/// Class holding pending events for a [_StreamImpl].
 class _StreamImplEvents<T> extends _PendingEvents<T> {
   /// Single linked list of [_DelayedEvent] objects.
   _DelayedEvent? firstPendingEvent;
@@ -738,9 +714,7 @@
 
 typedef void _BroadcastCallback<T>(StreamSubscription<T> subscription);
 
-/**
- * Done subscription that will send one done event as soon as possible.
- */
+/// Done subscription that will send one done event as soon as possible.
 class _DoneStreamSubscription<T> implements StreamSubscription<T> {
   static const int _DONE_SENT = 1;
   static const int _SCHEDULED = 2;
@@ -900,9 +874,7 @@
   }
 }
 
-/**
- * Wrapper for subscription that disallows changing handlers.
- */
+/// Wrapper for subscription that disallows changing handlers.
 class _BroadcastSubscriptionWrapper<T> implements StreamSubscription<T> {
   final _AsBroadcastStream _stream;
 
@@ -1118,7 +1090,7 @@
   }
 }
 
-/** An empty broadcast stream, sending a done event as soon as possible. */
+/// An empty broadcast stream, sending a done event as soon as possible.
 class _EmptyStream<T> extends Stream<T> {
   const _EmptyStream() : super._internal();
   bool get isBroadcast => true;
@@ -1128,10 +1100,11 @@
   }
 }
 
-/** A stream which creates a new controller for each listener. */
+/// A stream which creates a new controller for each listener.
 class _MultiStream<T> extends Stream<T> {
   final bool isBroadcast;
-  /** The callback called for each listen. */
+
+  /// The callback called for each listen.
   final void Function(MultiStreamController<T>) _onListen;
 
   _MultiStream(this._onListen, this.isBroadcast);
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index fd20228..60aff7e 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -4,7 +4,7 @@
 
 part of dart.async;
 
-/** Runs user code and takes actions depending on success or failure. */
+/// Runs user code and takes actions depending on success or failure.
 _runUserCode<T>(T userCode(), onSuccess(T value),
     onError(Object error, StackTrace stackTrace)) {
   try {
@@ -43,7 +43,7 @@
   _cancelAndError(subscription, future, error, stackTrace);
 }
 
-/** Helper function to make an onError argument to [_runUserCode]. */
+/// Helper function to make an onError argument to [_runUserCode].
 void Function(Object error, StackTrace stackTrace) _cancelAndErrorClosure(
     StreamSubscription subscription, _Future future) {
   return (Object error, StackTrace stackTrace) {
@@ -62,15 +62,13 @@
   }
 }
 
-/**
- * A [Stream] that forwards subscriptions to another stream.
- *
- * This stream implements [Stream], but forwards all subscriptions
- * to an underlying stream, and wraps the returned subscription to
- * modify the events on the way.
- *
- * This class is intended for internal use only.
- */
+/// A [Stream] that forwards subscriptions to another stream.
+///
+/// This stream implements [Stream], but forwards all subscriptions
+/// to an underlying stream, and wraps the returned subscription to
+/// modify the events on the way.
+///
+/// This class is intended for internal use only.
 abstract class _ForwardingStream<S, T> extends Stream<T> {
   final Stream<S> _source;
 
@@ -102,9 +100,7 @@
   }
 }
 
-/**
- * Abstract superclass for subscriptions that forward to other subscriptions.
- */
+/// Abstract superclass for subscriptions that forward to other subscriptions.
 class _ForwardingStreamSubscription<S, T>
     extends _BufferingStreamSubscription<T> {
   final _ForwardingStream<S, T> _stream;
@@ -203,9 +199,7 @@
 
 typedef T _Transformation<S, T>(S value);
 
-/**
- * A stream pipe that converts data events before passing them on.
- */
+/// A stream pipe that converts data events before passing them on.
 class _MapStream<S, T> extends _ForwardingStream<S, T> {
   final _Transformation<S, T> _transform;
 
@@ -225,9 +219,7 @@
   }
 }
 
-/**
- * A stream pipe that converts data events before passing them on.
- */
+/// A stream pipe that converts data events before passing them on.
 class _ExpandStream<S, T> extends _ForwardingStream<S, T> {
   final _Transformation<S, Iterable<T>> _expand;
 
@@ -248,10 +240,8 @@
   }
 }
 
-/**
- * A stream pipe that converts or disposes error events
- * before passing them on.
- */
+/// A stream pipe that converts or disposes error events
+/// before passing them on.
 class _HandleErrorStream<T> extends _ForwardingStream<T, T> {
   final Function _transform;
   final bool Function(Object)? _test;
@@ -327,11 +317,9 @@
   }
 }
 
-/**
- * A [_ForwardingStreamSubscription] with one extra state field.
- *
- * Use by several different classes, storing an integer, bool or general.
- */
+/// A [_ForwardingStreamSubscription] with one extra state field.
+///
+/// Use by several different classes, storing an integer, bool or general.
 class _StateStreamSubscription<S, T>
     extends _ForwardingStreamSubscription<T, T> {
   S _subState;
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index aa99f5f..9193071 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.dart
@@ -4,9 +4,7 @@
 
 part of dart.async;
 
-/**
- * Wraps an [_EventSink] so it exposes only the [EventSink] interface.
- */
+/// Wraps an [_EventSink] so it exposes only the [EventSink] interface.
 class _EventSinkWrapper<T> implements EventSink<T> {
   _EventSink<T> _sink;
   _EventSinkWrapper(this._sink);
@@ -24,13 +22,11 @@
   }
 }
 
-/**
- * A StreamSubscription that pipes data through a sink.
- *
- * The constructor of this class takes a [_SinkMapper] which maps from
- * [EventSink] to [EventSink]. The input to the mapper is the output of
- * the transformation. The returned sink is the transformation's input.
- */
+/// A StreamSubscription that pipes data through a sink.
+///
+/// The constructor of this class takes a [_SinkMapper] which maps from
+/// [EventSink] to [EventSink]. The input to the mapper is the output of
+/// the transformation. The returned sink is the transformation's input.
 class _SinkTransformerStreamSubscription<S, T>
     extends _BufferingStreamSubscription<T> {
   /// The transformer's input sink.
@@ -55,13 +51,11 @@
 
   // _EventSink interface.
 
-  /**
-   * Adds an event to this subscriptions.
-   *
-   * Contrary to normal [_BufferingStreamSubscription]s we may receive
-   * events when the stream is already closed. Report them as state
-   * error.
-   */
+  /// Adds an event to this subscriptions.
+  ///
+  /// Contrary to normal [_BufferingStreamSubscription]s we may receive
+  /// events when the stream is already closed. Report them as state
+  /// error.
   void _add(T data) {
     if (_isClosed) {
       throw StateError("Stream is already closed");
@@ -69,13 +63,11 @@
     super._add(data);
   }
 
-  /**
-   * Adds an error event to this subscriptions.
-   *
-   * Contrary to normal [_BufferingStreamSubscription]s we may receive
-   * events when the stream is already closed. Report them as state
-   * error.
-   */
+  /// Adds an error event to this subscriptions.
+  ///
+  /// Contrary to normal [_BufferingStreamSubscription]s we may receive
+  /// events when the stream is already closed. Report them as state
+  /// error.
   void _addError(Object error, StackTrace stackTrace) {
     if (_isClosed) {
       throw new StateError("Stream is already closed");
@@ -83,13 +75,11 @@
     super._addError(error, stackTrace);
   }
 
-  /**
-   * Adds a close event to this subscriptions.
-   *
-   * Contrary to normal [_BufferingStreamSubscription]s we may receive
-   * events when the stream is already closed. Report them as state
-   * error.
-   */
+  /// Adds a close event to this subscriptions.
+  ///
+  /// Contrary to normal [_BufferingStreamSubscription]s we may receive
+  /// events when the stream is already closed. Report them as state
+  /// error.
   void _close() {
     if (_isClosed) {
       throw new StateError("Stream is already closed");
@@ -148,14 +138,12 @@
 
 typedef EventSink<S> _SinkMapper<S, T>(EventSink<T> output);
 
-/**
- * A StreamTransformer for Sink-mappers.
- *
- * A Sink-mapper takes an [EventSink] (its output) and returns another
- * EventSink (its input).
- *
- * Note that this class can be `const`.
- */
+/// A [StreamTransformer] for [Sink]-mappers.
+///
+/// A Sink-mapper takes an [EventSink] (its output) and returns another
+/// [EventSink] (its input).
+///
+/// Note that this class can be `const`.
 class _StreamSinkTransformer<S, T> extends StreamTransformerBase<S, T> {
   final _SinkMapper<S, T> _sinkMapper;
   const _StreamSinkTransformer(this._sinkMapper);
@@ -164,13 +152,11 @@
       new _BoundSinkStream<S, T>(stream, _sinkMapper);
 }
 
-/**
- * The result of binding a StreamTransformer for Sink-mappers.
- *
- * It contains the bound Stream and the sink-mapper. Only when the user starts
- * listening to this stream is the sink-mapper invoked. The result is used
- * to create a StreamSubscription that transforms events.
- */
+/// The result of binding a [StreamTransformer] for [Sink]-mappers.
+///
+/// It contains the bound Stream and the sink-mapper. Only when the user starts
+/// listening to this stream is the sink-mapper invoked. The result is used
+/// to create a StreamSubscription that transforms events.
 class _BoundSinkStream<S, T> extends Stream<T> {
   final _SinkMapper<S, T> _sinkMapper;
   final Stream<S> _stream;
@@ -198,11 +184,9 @@
 /// Done-handler coming from [StreamTransformer.fromHandlers].
 typedef void _TransformDoneHandler<T>(EventSink<T> sink);
 
-/**
- * Wraps handlers (from [StreamTransformer.fromHandlers]) into an `EventSink`.
- *
- * This way we can reuse the code from [_StreamSinkTransformer].
- */
+/// Wraps handlers (from [StreamTransformer.fromHandlers]) into an `EventSink`.
+///
+/// This way we can reuse the code from [_StreamSinkTransformer].
 class _HandlerEventSink<S, T> implements EventSink<S> {
   final _TransformDataHandler<S, T>? _handleData;
   final _TransformErrorHandler<T>? _handleError;
@@ -256,11 +240,9 @@
   }
 }
 
-/**
- * A StreamTransformer that transformers events with the given handlers.
- *
- * Note that this transformer can only be used once.
- */
+/// A StreamTransformer that transformers events with the given handlers.
+///
+/// Note that this transformer can only be used once.
 class _StreamHandlerTransformer<S, T> extends _StreamSinkTransformer<S, T> {
   _StreamHandlerTransformer(
       {void handleData(S data, EventSink<T> sink)?,
@@ -276,9 +258,7 @@
   }
 }
 
-/**
- * A StreamTransformer that overrides [StreamTransformer.bind] with a callback.
- */
+/// A StreamTransformer that overrides [StreamTransformer.bind] with a callback.
 class _StreamBindTransformer<S, T> extends StreamTransformerBase<S, T> {
   final Stream<T> Function(Stream<S>) _bind;
   _StreamBindTransformer(this._bind);
@@ -290,18 +270,16 @@
 typedef StreamSubscription<T> _SubscriptionTransformer<S, T>(
     Stream<S> stream, bool cancelOnError);
 
-/**
- * A [StreamTransformer] that minimizes the number of additional classes.
- *
- * Instead of implementing three classes: a [StreamTransformer], a [Stream]
- * (as the result of a `bind` call) and a [StreamSubscription] (which does the
- * actual work), this class only requires a function that is invoked when the
- * last bit (the subscription) of the transformer-workflow is needed.
- *
- * The given transformer function maps from Stream and cancelOnError to a
- * `StreamSubscription`. As such it can also act on `cancel` events, making it
- * fully general.
- */
+/// A [StreamTransformer] that minimizes the number of additional classes.
+///
+/// Instead of implementing three classes: a [StreamTransformer], a [Stream]
+/// (as the result of a `bind` call) and a [StreamSubscription] (which does the
+/// actual work), this class only requires a function that is invoked when the
+/// last bit (the subscription) of the transformer-workflow is needed.
+///
+/// The given transformer function maps from Stream and cancelOnError to a
+/// `StreamSubscription`. As such it can also act on `cancel` events, making it
+/// fully general.
 class _StreamSubscriptionTransformer<S, T> extends StreamTransformerBase<S, T> {
   final _SubscriptionTransformer<S, T> _onListen;
 
@@ -311,13 +289,11 @@
       new _BoundSubscriptionStream<S, T>(stream, _onListen);
 }
 
-/**
- * A stream transformed by a [_StreamSubscriptionTransformer].
- *
- * When this stream is listened to it invokes the [_onListen] function with
- * the stored [_stream]. Usually the transformer starts listening at this
- * moment.
- */
+/// A stream transformed by a [_StreamSubscriptionTransformer].
+///
+/// When this stream is listened to it invokes the [_onListen] function with
+/// the stored [_stream]. Usually the transformer starts listening at this
+/// moment.
 class _BoundSubscriptionStream<S, T> extends Stream<T> {
   final _SubscriptionTransformer<S, T> _onListen;
   final Stream<S> _stream;
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index e0ef447..973a543 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.dart
@@ -4,44 +4,40 @@
 
 part of dart.async;
 
-/**
- * A count-down timer that can be configured to fire once or repeatedly.
- *
- * The timer counts down from the specified duration to 0.
- * When the timer reaches 0, the timer invokes the specified callback function.
- * Use a periodic timer to repeatedly count down the same interval.
- *
- * A negative duration is treated the same as a duration of 0.
- * If the duration is statically known to be 0, consider using [run].
- *
- * Frequently the duration is either a constant or computed as in the
- * following example (taking advantage of the multiplication operator of
- * the [Duration] class):
- * ```dart
- * const timeout = const Duration(seconds: 3);
- * const ms = const Duration(milliseconds: 1);
- *
- * startTimeout([int milliseconds]) {
- *   var duration = milliseconds == null ? timeout : ms * milliseconds;
- *   return new Timer(duration, handleTimeout);
- * }
- * ...
- * void handleTimeout() {  // callback function
- *   ...
- * }
- * ```
- * Note: If Dart code using Timer is compiled to JavaScript, the finest
- * granularity available in the browser is 4 milliseconds.
- *
- * See [Stopwatch] for measuring elapsed time.
- */
+/// A count-down timer that can be configured to fire once or repeatedly.
+///
+/// The timer counts down from the specified duration to 0.
+/// When the timer reaches 0, the timer invokes the specified callback function.
+/// Use a periodic timer to repeatedly count down the same interval.
+///
+/// A negative duration is treated the same as a duration of 0.
+/// If the duration is statically known to be 0, consider using [run].
+///
+/// Frequently the duration is either a constant or computed as in the
+/// following example (taking advantage of the multiplication operator of
+/// the [Duration] class):
+/// ```dart
+/// const timeout = Duration(seconds: 3);
+/// const ms = Duration(milliseconds: 1);
+///
+/// Timer startTimeout([int? milliseconds]) {
+///   var duration = milliseconds == null ? timeout : ms * milliseconds;
+///   return Timer(duration, handleTimeout);
+/// }
+/// ...
+/// void handleTimeout() {  // callback function
+///   ...
+/// }
+/// ```
+/// Note: If Dart code using [Timer] is compiled to JavaScript, the finest
+/// granularity available in the browser is 4 milliseconds.
+///
+/// See [Stopwatch] for measuring elapsed time.
 abstract class Timer {
-  /**
-   * Creates a new timer.
-   *
-   * The [callback] function is invoked after the given [duration].
-   *
-   */
+  /// Creates a new timer.
+  ///
+  /// The [callback] function is invoked after the given [duration].
+  ///
   factory Timer(Duration duration, void Function() callback) {
     if (Zone.current == Zone.root) {
       // No need to bind the callback. We know that the root's timer will
@@ -52,24 +48,22 @@
         .createTimer(duration, Zone.current.bindCallbackGuarded(callback));
   }
 
-  /**
-   * Creates a new repeating timer.
-   *
-   * The [callback] is invoked repeatedly with [duration] intervals until
-   * canceled with the [cancel] function.
-   *
-   * The exact timing depends on the underlying timer implementation.
-   * No more than `n` callbacks will be made in `duration * n` time,
-   * but the time between two consecutive callbacks
-   * can be shorter and longer than `duration`.
-   *
-   * In particular, an implementation may schedule the next callback, e.g.,
-   * a `duration` after either when the previous callback ended,
-   * when the previous callback started, or when the previous callback was
-   * scheduled for - even if the actual callback was delayed.
-   *
-   * [duration] must a non-negative [Duration].
-   */
+  /// Creates a new repeating timer.
+  ///
+  /// The [callback] is invoked repeatedly with [duration] intervals until
+  /// canceled with the [cancel] function.
+  ///
+  /// The exact timing depends on the underlying timer implementation.
+  /// No more than `n` callbacks will be made in `duration * n` time,
+  /// but the time between two consecutive callbacks
+  /// can be shorter and longer than `duration`.
+  ///
+  /// In particular, an implementation may schedule the next callback, e.g.,
+  /// a `duration` after either when the previous callback ended,
+  /// when the previous callback started, or when the previous callback was
+  /// scheduled for - even if the actual callback was delayed.
+  ///
+  /// [duration] must a non-negative [Duration].
   factory Timer.periodic(Duration duration, void callback(Timer timer)) {
     if (Zone.current == Zone.root) {
       // No need to bind the callback. We know that the root's timer will
@@ -80,47 +74,39 @@
     return Zone.current.createPeriodicTimer(duration, boundCallback);
   }
 
-  /**
-   * Runs the given [callback] asynchronously as soon as possible.
-   *
-   * This function is equivalent to `new Timer(Duration.zero, callback)`.
-   */
+  /// Runs the given [callback] asynchronously as soon as possible.
+  ///
+  /// This function is equivalent to `new Timer(Duration.zero, callback)`.
   static void run(void Function() callback) {
     new Timer(Duration.zero, callback);
   }
 
-  /**
-   * Cancels the timer.
-   *
-   * Once a [Timer] has been canceled, the callback function will not be called
-   * by the timer. Calling [cancel] more than once on a [Timer] is allowed, and
-   * will have no further effect.
-   */
+  /// Cancels the timer.
+  ///
+  /// Once a [Timer] has been canceled, the callback function will not be called
+  /// by the timer. Calling [cancel] more than once on a [Timer] is allowed, and
+  /// will have no further effect.
   void cancel();
 
-  /**
-   * The number of durations preceding the most recent timer event.
-   *
-   * The value starts at zero and is incremented each time a timer event
-   * occurs, so each callback will see a larger value than the previous one.
-   *
-   * If a periodic timer with a non-zero duration is delayed too much,
-   * so more than one tick should have happened,
-   * all but the last tick in the past are considered "missed",
-   * and no callback is invoked for them.
-   * The [tick] count reflects the number of durations that have passed and
-   * not the number of callback invocations that have happened.
-   */
+  /// The number of durations preceding the most recent timer event.
+  ///
+  /// The value starts at zero and is incremented each time a timer event
+  /// occurs, so each callback will see a larger value than the previous one.
+  ///
+  /// If a periodic timer with a non-zero duration is delayed too much,
+  /// so more than one tick should have happened,
+  /// all but the last tick in the past are considered "missed",
+  /// and no callback is invoked for them.
+  /// The [tick] count reflects the number of durations that have passed and
+  /// not the number of callback invocations that have happened.
   int get tick;
 
-  /**
-   * Returns whether the timer is still active.
-   *
-   * A non-periodic timer is active if the callback has not been executed,
-   * and the timer has not been canceled.
-   *
-   * A periodic timer is active if it has not been canceled.
-   */
+  /// Returns whether the timer is still active.
+  ///
+  /// A non-periodic timer is active if the callback has not been executed,
+  /// and the timer has not been canceled.
+  ///
+  /// A periodic timer is active if it has not been canceled.
   bool get isActive;
 
   external static Timer _createTimer(
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index f662d53..4f0873d 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -8,59 +8,236 @@
 typedef R ZoneUnaryCallback<R, T>(T arg);
 typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2);
 
+/// The type of a custom [Zone.handleUncaughtError] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The [error] and [stackTrace] are the error and stack trace that
+/// was uncaught in [zone].
 typedef HandleUncaughtErrorHandler = void Function(Zone self,
     ZoneDelegate parent, Zone zone, Object error, StackTrace stackTrace);
+
+/// The type of a custom [Zone.run] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The function [f] is the function which was passed to the
+/// [Zone.run] of [zone].
+///
+/// The default behavior of [Zone.run] is
+/// to call [f] in the current zone, [zone].
+/// A custom handler can do things before, after or instead of
+/// calling [f].
 typedef RunHandler = R Function<R>(
     Zone self, ZoneDelegate parent, Zone zone, R Function() f);
+
+/// The type of a custom [Zone.runUnary] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The function [f] and value [arg] are the function and argument
+/// which was passed to the [Zone.runUnary] of [zone].
+///
+/// The default behavior of [Zone.runUnary] is
+/// to call [f] with argument [arg] in the current zone, [zone].
+/// A custom handler can do things before, after or instead of
+/// calling [f].
 typedef RunUnaryHandler = R Function<R, T>(
     Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f, T arg);
+
+/// The type of a custom [Zone.runBinary] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The function [f] and values [arg1] and [arg2] are the function and arguments
+/// which was passed to the [Zone.runBinary] of [zone].
+///
+/// The default behavior of [Zone.runUnary] is
+/// to call [f] with arguments [arg1] and [arg2] in the current zone, [zone].
+/// A custom handler can do things before, after or instead of
+/// calling [f].
 typedef RunBinaryHandler = R Function<R, T1, T2>(Zone self, ZoneDelegate parent,
     Zone zone, R Function(T1 arg1, T2 arg2) f, T1 arg1, T2 arg2);
+
+/// The type of a custom [Zone.registerCallback] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The function [f] is the function which was passed to the
+/// [Zone.registerCallback] of [zone].
+///
+/// The handler should return either the function [f]
+/// or another function replacing [f],
+/// typically by wrapping [f] in a function
+/// which does something extra before and after invoking [f]
 typedef RegisterCallbackHandler = ZoneCallback<R> Function<R>(
     Zone self, ZoneDelegate parent, Zone zone, R Function() f);
+
+/// The type of a custom [Zone.registerUnary] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The function [f] is the function which was passed to the
+/// which was passed to the [Zone.registerUnary] of [zone].
+///
+/// The handler should return either the function [f]
+/// or another function replacing [f],
+/// typically by wrapping [f] in a function
+/// which does something extra before and after invoking [f]
 typedef RegisterUnaryCallbackHandler = ZoneUnaryCallback<R, T> Function<R, T>(
     Zone self, ZoneDelegate parent, Zone zone, R Function(T arg) f);
+
+/// The type of a custom [Zone.registerBinary] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The function [f] is the function which was passed to the
+/// which was passed to the [Zone.registerBinary] of [zone].
+///
+/// The handler should return either the function [f]
+/// or another function replacing [f],
+/// typically by wrapping [f] in a function
+/// which does something extra before and after invoking [f]
 typedef RegisterBinaryCallbackHandler
     = ZoneBinaryCallback<R, T1, T2> Function<R, T1, T2>(Zone self,
         ZoneDelegate parent, Zone zone, R Function(T1 arg1, T2 arg2) f);
+
+/// The type of a custom [Zone.errorCallback] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The [error] and [stackTrace] are the error and stack trace
+/// passed to [Zone.errorCallback] of [zone].
+///
+/// The function should return either `null` if it doesn't want
+/// to replace the original error and stack trace,
+/// or an [AsyncError] containg a replacement error and stack trace
+/// which will be used to replace the originals.
 typedef AsyncError? ErrorCallbackHandler(Zone self, ZoneDelegate parent,
     Zone zone, Object error, StackTrace? stackTrace);
+
+/// The type of a custom [Zone.scheduleMicrotask] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The function [f] is the function which was
+/// passed to [Zone.scheduleMicrotask] of [zone].
+///
+/// The custom handler can choose to replace the function [f]
+/// with one that does something before, after or instead of calling [f],
+/// and then call `parent.scheduleMicrotask(zone, replacement)`.
+/// or it can implement its own microtask scheduling queue, which typically
+/// still depends on `parent.scheduleMicrotask` to as a way to get started.
 typedef void ScheduleMicrotaskHandler(
     Zone self, ZoneDelegate parent, Zone zone, void f());
+
+/// The type of a custom [Zone.createTimer] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The callback function [f] and [duration] are the ones which were
+/// passed to [Zone.createTimer] of [zone]
+/// (possibly through the [Timer] constructor).
+///
+/// The custom handler can choose to replace the function [f]
+/// with one that does something before, after or instead of calling [f],
+/// and then call `parent.createTimer(zone, replacement)`.
+/// or it can implement its own timer queue, which typically
+/// still depends on `parent.createTimer` to as a way to get started.
+///
+/// The function should return a [Timer] object which can be used
+/// to inspect and control the scheduled timer callback.
 typedef Timer CreateTimerHandler(
     Zone self, ZoneDelegate parent, Zone zone, Duration duration, void f());
+
+/// The type of a custom [Zone.createPeriodicTimer] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The callback function [f] and [duration] are the ones which were
+/// passed to [Zone.createPeriodicTimer] of [zone]
+/// (possibly through the [Timer.periodic] constructor).
+///
+/// The custom handler can choose to replace the function [f]
+/// with one that does something before, after or instead of calling [f],
+/// and then call `parent.createTimer(zone, replacement)`.
+/// or it can implement its own timer queue, which typically
+/// still depends on `parent.createTimer` to as a way to get started.
+///
+/// The function should return a [Timer] object which can be used
+/// to inspect and control the scheduled timer callbacks.
 typedef Timer CreatePeriodicTimerHandler(Zone self, ZoneDelegate parent,
     Zone zone, Duration period, void f(Timer timer));
+
+/// The type of a custom [Zone.print] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The string [line] is the one which was passed to [Zone.print] of [zone],
+/// (possibly through the global [print] function).
+///
+/// The custom handler can intercept print operations and
+/// redirect them to other targets than the console.
 typedef void PrintHandler(
     Zone self, ZoneDelegate parent, Zone zone, String line);
+
+/// The type of a custom [Zone.fork] implementation function.
+///
+/// Receives the [Zone] that the handler was registered on as [self],
+/// a delegate forwarding to the handlers of [self]'s parent zone as [parent],
+/// and the current zone where the error was uncaught as [zone],
+/// which will have [self] as a parent zone.
+///
+/// The handler should create a new zone with [zone] as its
+/// immediate parent zone.
+///
+/// The [specification] and [zoneValues] are the ones which were
+/// passed to [Zone.fork] of [zone]. They specify the custom zone
+/// handlers and zone variables that the new zone should have.
+///
+/// The custom handler can change the specification or zone
+/// values before calling `parent.fork(zone, specification, zoneValues)`,
+/// but it has to call the [parent]'s [ZoneDelegate.fork] in order
+/// to create a valid [Zone] object.
 typedef Zone ForkHandler(Zone self, ZoneDelegate parent, Zone zone,
     ZoneSpecification? specification, Map<Object?, Object?>? zoneValues);
 
-/// Pair of error and stack trace. Returned by [Zone.errorCallback].
-class AsyncError implements Error {
-  final Object error;
-  final StackTrace stackTrace;
-
-  AsyncError(Object error, StackTrace? stackTrace)
-      : error = checkNotNullable(error, "error"),
-        stackTrace = stackTrace ?? defaultStackTrace(error);
-
-  /// A default stack trace for an error.
-  ///
-  /// If [error] is an [Error] and it has an [Error.stackTrace],
-  /// that stack trace is returned.
-  /// If not, the [StackTrace.empty] default stack trace is returned.
-  static StackTrace defaultStackTrace(Object error) {
-    if (error is Error) {
-      var stackTrace = error.stackTrace;
-      if (stackTrace != null) return stackTrace;
-    }
-    return StackTrace.empty;
-  }
-
-  String toString() => '$error';
-}
-
 class _ZoneFunction<T extends Function> {
   final _Zone zone;
   final T function;
@@ -103,29 +280,33 @@
   const _RegisterBinaryZoneFunction(this.zone, this.function);
 }
 
-/**
- * This class provides the specification for a forked zone.
- *
- * When forking a new zone (see [Zone.fork]) one can override the default
- * behavior of the zone by providing callbacks. These callbacks must be
- * given in an instance of this class.
- *
- * Handlers have the same signature as the same-named methods on [Zone] but
- * receive three additional arguments:
- *
- *   1. the zone the handlers are attached to (the "self" zone).
- *   2. a [ZoneDelegate] to the parent zone.
- *   3. the zone that first received the request (before the request was
- *     bubbled up).
- *
- * Handlers can either stop propagation the request (by simply not calling the
- * parent handler), or forward to the parent zone, potentially modifying the
- * arguments on the way.
- */
+/// A parameter object with custom zone function handlers for [Zone.fork].
+///
+/// A zone specification is a parameter object passed to [Zone.fork]
+/// and any underlying [ForkHandler] custom implementations.
+/// The individual handlers, if set to a non-null value,
+/// will be the implementation of the correpsonding [Zone] methods
+/// for a forked zone created using this zone specification.
+///
+/// Handlers have the same signature as the same-named methods on [Zone],
+/// but receive three additional arguments:
+///
+///   1. The zone the handlers are attached to (the "self" zone).
+///      This is the zone created by [Zone.fork] where the handler is
+///      passed as part of the zone delegation.
+///   2. A [ZoneDelegate] to the parent zone.
+///   3. The "current" zone at the time the request was made.
+///      The self zone is always a parent zone of the current zone.
+///
+/// Handlers can either stop propagating the request (by simply not calling the
+/// parent handler), or forward to the parent zone, potentially modifying the
+/// arguments on the way.
 abstract class ZoneSpecification {
-  /**
-   * Creates a specification with the provided handlers.
-   */
+  /// Creates a specification with the provided handlers.
+  ///
+  /// If the [handleUncaughtError] is provided, the new zone will be a new
+  /// "error zone" which will prevent errors from flowing into other
+  /// error zones (see [errorZone], [sameErrorZone]).
   const factory ZoneSpecification(
       {HandleUncaughtErrorHandler? handleUncaughtError,
       RunHandler? run,
@@ -141,10 +322,12 @@
       PrintHandler? print,
       ForkHandler? fork}) = _ZoneSpecification;
 
-  /**
-   * Creates a specification from [other] with the provided handlers overriding
-   * the ones in [other].
-   */
+  /// Creates a specification from [other] and provided handlers.
+  ///
+  /// The created zone specification has the handlers of [other]
+  /// and any individually provided handlers.
+  /// If a handler is provided both through [other] and individually,
+  /// the individually provided handler overries the one from [other].
   factory ZoneSpecification.from(ZoneSpecification other,
       {HandleUncaughtErrorHandler? handleUncaughtError,
       RunHandler? run,
@@ -177,28 +360,51 @@
         fork: fork ?? other.fork);
   }
 
+  /// A custom [Zone.handleUncaughtError] implementation for a new zone.
   HandleUncaughtErrorHandler? get handleUncaughtError;
+
+  /// A custom [Zone.run] implementation for a new zone.
   RunHandler? get run;
+
+  /// A custom [Zone.runUnary] implementation for a new zone.
   RunUnaryHandler? get runUnary;
+
+  /// A custom [Zone.runBinary] implementation for a new zone.
   RunBinaryHandler? get runBinary;
+
+  /// A custom [Zone.registerCallback] implementation for a new zone.
   RegisterCallbackHandler? get registerCallback;
+
+  /// A custom [Zone.registerUnaryCallback] implementation for a new zone.
   RegisterUnaryCallbackHandler? get registerUnaryCallback;
+
+  /// A custom [Zone.registerBinaryCallback] implementation for a new zone.
   RegisterBinaryCallbackHandler? get registerBinaryCallback;
+
+  /// A custom [Zone.errorCallback] implementation for a new zone.
   ErrorCallbackHandler? get errorCallback;
+
+  /// A custom [Zone.scheduleMicrotask] implementation for a new zone.
   ScheduleMicrotaskHandler? get scheduleMicrotask;
+
+  /// A custom [Zone.createTimer] implementation for a new zone.
   CreateTimerHandler? get createTimer;
+
+  /// A custom [Zone.createPeriodicTimer] implementation for a new zone.
   CreatePeriodicTimerHandler? get createPeriodicTimer;
+
+  /// A custom [Zone.print] implementation for a new zone.
   PrintHandler? get print;
+
+  /// A custom [Zone.handleUncaughtError] implementation for a new zone.
   ForkHandler? get fork;
 }
 
-/**
- * Internal [ZoneSpecification] class.
- *
- * The implementation wants to rely on the fact that the getters cannot change
- * dynamically. We thus require users to go through the redirecting
- * [ZoneSpecification] constructor which instantiates this class.
- */
+/// Internal [ZoneSpecification] class.
+///
+/// The implementation wants to rely on the fact that the getters cannot change
+/// dynamically. We thus require users to go through the redirecting
+/// [ZoneSpecification] constructor which instantiates this class.
 class _ZoneSpecification implements ZoneSpecification {
   const _ZoneSpecification(
       {this.handleUncaughtError,
@@ -230,482 +436,452 @@
   final ForkHandler? fork;
 }
 
-/**
- * An adapted view of the parent zone.
- *
- * This class allows the implementation of a zone method to invoke methods on
- * the parent zone while retaining knowledge of the originating zone.
- *
- * Custom zones (created through [Zone.fork] or [runZoned]) can provide
- * implementations of most methods of zones. This is similar to overriding
- * methods on [Zone], except that this mechanism doesn't require subclassing.
- *
- * A custom zone function (provided through a [ZoneSpecification]) typically
- * records or wraps its parameters and then delegates the operation to its
- * parent zone using the provided [ZoneDelegate].
- *
- * While zones have access to their parent zone (through [Zone.parent]) it is
- * recommended to call the methods on the provided parent delegate for two
- * reasons:
- * 1. the delegate methods take an additional `zone` argument which is the
- *   zone the action has been initiated in.
- * 2. delegate calls are more efficient, since the implementation knows how
- *   to skip zones that would just delegate to their parents.
- */
+/// An adapted view of the parent zone.
+///
+/// This class allows the implementation of a zone method to invoke methods on
+/// the parent zone while retaining knowledge of the originating zone.
+///
+/// Custom zones (created through [Zone.fork] or [runZoned]) can provide
+/// implementations of most methods of zones. This is similar to overriding
+/// methods on [Zone], except that this mechanism doesn't require subclassing.
+///
+/// A custom zone function (provided through a [ZoneSpecification]) typically
+/// records or wraps its parameters and then delegates the operation to its
+/// parent zone using the provided [ZoneDelegate].
+///
+/// While zones have access to their parent zone (through [Zone.parent]) it is
+/// recommended to call the methods on the provided parent delegate for two
+/// reasons:
+/// 1. the delegate methods take an additional `zone` argument which is the
+///   zone the action has been initiated in.
+/// 2. delegate calls are more efficient, since the implementation knows how
+///   to skip zones that would just delegate to their parents.
 abstract class ZoneDelegate {
+  // Invoke the [HandleUncaughtErrorHandler] of the zone with a current zone.
   void handleUncaughtError(Zone zone, Object error, StackTrace stackTrace);
+
+  // Invokes the [RunHandler] of the zone with a current zone.
   R run<R>(Zone zone, R f());
+
+  // Invokes the [RunUnaryHandler] of the zone with a current zone.
   R runUnary<R, T>(Zone zone, R f(T arg), T arg);
+
+  // Invokes the [RunBinaryHandler] of the zone with a current zone.
   R runBinary<R, T1, T2>(Zone zone, R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2);
+
+  // Invokes the [RegisterCallbackHandler] of the zone with a current zone.
   ZoneCallback<R> registerCallback<R>(Zone zone, R f());
+
+  // Invokes the [RegisterUnaryHandler] of the zone with a current zone.
   ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>(Zone zone, R f(T arg));
+
+  // Invokes the [RegisterBinaryHandler] of the zone with a current zone.
   ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(
       Zone zone, R f(T1 arg1, T2 arg2));
+
+  // Invokes the [ErrorCallbackHandler] of the zone with a current zone.
   AsyncError? errorCallback(Zone zone, Object error, StackTrace? stackTrace);
+
+  // Invokes the [ScheduleMicrotaskHandler] of the zone with a current zone.
   void scheduleMicrotask(Zone zone, void f());
+
+  // Invokes the [CreateTimerHandler] of the zone with a current zone.
   Timer createTimer(Zone zone, Duration duration, void f());
+
+  // Invokes the [CreatePeriodicTimerHandler] of the zone with a current zone.
   Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer));
+
+  // Invokes the [PrintHandler] of the zone with a current zone.
   void print(Zone zone, String line);
+
+  // Invokes the [ForkHandler] of the zone with a current zone.
   Zone fork(Zone zone, ZoneSpecification? specification, Map? zoneValues);
 }
 
-/**
- * A zone represents an environment that remains stable across asynchronous
- * calls.
- *
- * Code is always executed in the context of a zone, available as
- * [Zone.current]. The initial `main` function runs in the context of the
- * default zone ([Zone.root]). Code can be run in a different zone using either
- * [runZoned], to create a new zone, or [Zone.run] to run code in the context of
- * an existing zone likely created using [Zone.fork].
- *
- * Developers can create a new zone that overrides some of the functionality of
- * an existing zone. For example, custom zones can replace of modify the
- * behavior of `print`, timers, microtasks or how uncaught errors are handled.
- *
- * The [Zone] class is not subclassable, but users can provide custom zones by
- * forking an existing zone (usually [Zone.current]) with a [ZoneSpecification].
- * This is similar to creating a new class that extends the base `Zone` class
- * and that overrides some methods, except without actually creating a new
- * class. Instead the overriding methods are provided as functions that
- * explicitly take the equivalent of their own class, the "super" class and the
- * `this` object as parameters.
- *
- * Asynchronous callbacks always run in the context of the zone where they were
- * scheduled. This is implemented using two steps:
- * 1. the callback is first registered using one of [registerCallback],
- *   [registerUnaryCallback], or [registerBinaryCallback]. This allows the zone
- *   to record that a callback exists and potentially modify it (by returning a
- *   different callback). The code doing the registration (e.g., `Future.then`)
- *   also remembers the current zone so that it can later run the callback in
- *   that zone.
- * 2. At a later point the registered callback is run in the remembered zone.
- *
- * This is all handled internally by the platform code and most users don't need
- * to worry about it. However, developers of new asynchronous operations,
- * provided by the underlying system or through native extensions, must follow
- * the protocol to be zone compatible.
- *
- * For convenience, zones provide [bindCallback] (and the corresponding
- * [bindUnaryCallback] and [bindBinaryCallback]) to make it easier to respect
- * the zone contract: these functions first invoke the corresponding `register`
- * functions and then wrap the returned function so that it runs in the current
- * zone when it is later asynchronously invoked.
- *
- * Similarly, zones provide [bindCallbackGuarded] (and the corresponding
- * [bindUnaryCallbackGuarded] and [bindBinaryCallbackGuarded]), when the
- * callback should be invoked through [Zone.runGuarded].
- */
+/// A zone represents an environment that remains stable across asynchronous
+/// calls.
+///
+/// Code is always executed in the context of a zone, available as
+/// [Zone.current]. The initial `main` function runs in the context of the
+/// default zone ([Zone.root]). Code can be run in a different zone using either
+/// [runZoned], to create a new zone, or [Zone.run] to run code in the context of
+/// an existing zone which was created earlier using [Zone.fork].
+///
+/// Developers can create a new zone that overrides some of the functionality of
+/// an existing zone. For example, custom zones can replace of modify the
+/// behavior of `print`, timers, microtasks or how uncaught errors are handled.
+///
+/// The [Zone] class is not subclassable, but users can provide custom zones by
+/// forking an existing zone (usually [Zone.current]) with a [ZoneSpecification].
+/// This is similar to creating a new class that extends the base `Zone` class
+/// and that overrides some methods, except without actually creating a new
+/// class. Instead the overriding methods are provided as functions that
+/// explicitly take the equivalent of their own class, the "super" class and the
+/// `this` object as parameters.
+///
+/// Asynchronous callbacks always run in the context of the zone where they were
+/// scheduled. This is implemented using two steps:
+/// 1. the callback is first registered using one of [registerCallback],
+///   [registerUnaryCallback], or [registerBinaryCallback]. This allows the zone
+///   to record that a callback exists and potentially modify it (by returning a
+///   different callback). The code doing the registration (e.g., `Future.then`)
+///   also remembers the current zone so that it can later run the callback in
+///   that zone.
+/// 2. At a later point the registered callback is run in the remembered zone,
+///    using one of [run], [runUnary] or [runBinary].
+///
+/// This is all handled internally by the platform code and most users don't need
+/// to worry about it. However, developers of new asynchronous operations,
+/// provided by the underlying system or through native extensions, must follow
+/// the protocol to be zone compatible.
+///
+/// For convenience, zones provide [bindCallback] (and the corresponding
+/// [bindUnaryCallback] and [bindBinaryCallback]) to make it easier to respect
+/// the zone contract: these functions first invoke the corresponding `register`
+/// functions and then wrap the returned function so that it runs in the current
+/// zone when it is later asynchronously invoked.
+///
+/// Similarly, zones provide [bindCallbackGuarded] (and the corresponding
+/// [bindUnaryCallbackGuarded] and [bindBinaryCallbackGuarded]), when the
+/// callback should be invoked through [Zone.runGuarded].
 abstract class Zone {
   // Private constructor so that it is not possible instantiate a Zone class.
   Zone._();
 
-  /**
-   * The root zone.
-   *
-   * All isolate entry functions (`main` or spawned functions) start running in
-   * the root zone (that is, [Zone.current] is identical to [Zone.root] when the
-   * entry function is called). If no custom zone is created, the rest of the
-   * program always runs in the root zone.
-   *
-   * The root zone implements the default behavior of all zone operations.
-   * Many methods, like [registerCallback] do the bare minimum required of the
-   * function, and are only provided as a hook for custom zones. Others, like
-   * [scheduleMicrotask], interact with the underlying system to implement the
-   * desired behavior.
-   */
+  /// The root zone.
+  ///
+  /// All isolate entry functions (`main` or spawned functions) start running in
+  /// the root zone (that is, [Zone.current] is identical to [Zone.root] when the
+  /// entry function is called). If no custom zone is created, the rest of the
+  /// program always runs in the root zone.
+  ///
+  /// The root zone implements the default behavior of all zone operations.
+  /// Many methods, like [registerCallback] do the bare minimum required of the
+  /// function, and are only provided as a hook for custom zones. Others, like
+  /// [scheduleMicrotask], interact with the underlying system to implement the
+  /// desired behavior.
   static const Zone root = _rootZone;
 
-  /** The currently running zone. */
+  /// The currently running zone.
   static _Zone _current = _rootZone;
 
-  /** The zone that is currently active. */
+  /// The zone that is currently active.
   static Zone get current => _current;
 
-  /**
-   * Handles uncaught asynchronous errors.
-   *
-   * There are two kind of asynchronous errors that are handled by this
-   * function:
-   * 1. Uncaught errors that were thrown in asynchronous callbacks, for example,
-   *   a `throw` in the function passed to [Timer.run].
-   * 2. Asynchronous errors that are pushed through [Future] and [Stream]
-   *   chains, but for which no child registered an error handler.
-   *   Most asynchronous classes, like [Future] or [Stream] push errors to their
-   *   listeners. Errors are propagated this way until either a listener handles
-   *   the error (for example with [Future.catchError]), or no listener is
-   *   available anymore. In the latter case, futures and streams invoke the
-   *   zone's [handleUncaughtError].
-   *
-   * By default, when handled by the root zone, uncaught asynchronous errors are
-   * treated like uncaught synchronous exceptions.
-   */
+  /// Handles uncaught asynchronous errors.
+  ///
+  /// There are two kind of asynchronous errors that are handled by this
+  /// function:
+  /// 1. Uncaught errors that were thrown in asynchronous callbacks, for example,
+  ///   a `throw` in the function passed to [Timer.run].
+  /// 2. Asynchronous errors that are pushed through [Future] and [Stream]
+  ///   chains, but for which nobody registered an error handler.
+  ///   Most asynchronous classes, like [Future] or [Stream] push errors to their
+  ///   listeners. Errors are propagated this way until either a listener handles
+  ///   the error (for example with [Future.catchError]), or no listener is
+  ///   available anymore. In the latter case, futures and streams invoke the
+  ///   zone's [handleUncaughtError].
+  ///
+  /// By default, when handled by the root zone, uncaught asynchronous errors are
+  /// treated like uncaught synchronous exceptions.
   void handleUncaughtError(Object error, StackTrace stackTrace);
 
-  /**
-   * The parent zone of the this zone.
-   *
-   * Is `null` if `this` is the [root] zone.
-   *
-   * Zones are created by [fork] on an existing zone, or by [runZoned] which
-   * forks the [current] zone. The new zone's parent zone is the zone it was
-   * forked from.
-   */
+  /// The parent zone of the this zone.
+  ///
+  /// Is `null` if `this` is the [root] zone.
+  ///
+  /// Zones are created by [fork] on an existing zone, or by [runZoned] which
+  /// forks the [current] zone. The new zone's parent zone is the zone it was
+  /// forked from.
   Zone? get parent;
 
-  /**
-   * The error zone is the one that is responsible for dealing with uncaught
-   * errors.
-   *
-   * This is the closest parent zone of this zone that provides a
-   * [handleUncaughtError] method.
-   *
-   * Asynchronous errors never cross zone boundaries between zones with
-   * different error handlers.
-   *
-   * Example:
-   * ```
-   * import 'dart:async';
-   *
-   * main() {
-   *   var future;
-   *   runZoned(() {
-   *     // The asynchronous error is caught by the custom zone which prints
-   *     // 'asynchronous error'.
-   *     future = Future.error("asynchronous error");
-   *   }, onError: (e) { print(e); });  // Creates a zone with an error handler.
-   *   // The following `catchError` handler is never invoked, because the
-   *   // custom zone created by the call to `runZoned` provides an
-   *   // error handler.
-   *   future.catchError((e) { throw "is never reached"; });
-   * }
-   * ```
-   *
-   * Note that errors cannot enter a child zone with a different error handler
-   * either:
-   * ```
-   * import 'dart:async';
-   *
-   * main() {
-   *   runZoned(() {
-   *     // The following asynchronous error is *not* caught by the `catchError`
-   *     // in the nested zone, since errors are not to cross zone boundaries
-   *     // with different error handlers.
-   *     // Instead the error is handled by the current error handler,
-   *     // printing "Caught by outer zone: asynchronous error".
-   *     var future = Future.error("asynchronous error");
-   *     runZoned(() {
-   *       future.catchError((e) { throw "is never reached"; });
-   *     }, onError: (e) { throw "is never reached"; });
-   *   }, onError: (e) { print("Caught by outer zone: $e"); });
-   * }
-   * ```
-   */
+  /// The error zone is responsible for dealing with uncaught errors.
+  ///
+  /// This is the closest parent zone of this zone that provides a
+  /// [handleUncaughtError] method.
+  ///
+  /// Asynchronous errors never cross zone boundaries between zones with
+  /// different error handlers.
+  ///
+  /// Example:
+  /// ```
+  /// import 'dart:async';
+  ///
+  /// main() {
+  ///   var future;
+  ///   runZoned(() {
+  ///     // The asynchronous error is caught by the custom zone which prints
+  ///     // 'asynchronous error'.
+  ///     future = Future.error("asynchronous error");
+  ///   }, onError: (e) { print(e); });  // Creates a zone with an error handler.
+  ///   // The following `catchError` handler is never invoked, because the
+  ///   // custom zone created by the call to `runZoned` provides an
+  ///   // error handler.
+  ///   future.catchError((e) { throw "is never reached"; });
+  /// }
+  /// ```
+  ///
+  /// Note that errors cannot enter a child zone with a different error handler
+  /// either:
+  /// ```
+  /// import 'dart:async';
+  ///
+  /// main() {
+  ///   runZoned(() {
+  ///     // The following asynchronous error is *not* caught by the `catchError`
+  ///     // in the nested zone, since errors are not to cross zone boundaries
+  ///     // with different error handlers.
+  ///     // Instead the error is handled by the current error handler,
+  ///     // printing "Caught by outer zone: asynchronous error".
+  ///     var future = Future.error("asynchronous error");
+  ///     runZoned(() {
+  ///       future.catchError((e) { throw "is never reached"; });
+  ///     }, onError: (e) { throw "is never reached"; });
+  ///   }, onError: (e) { print("Caught by outer zone: $e"); });
+  /// }
+  /// ```
   Zone get errorZone;
 
-  /**
-   * Returns true if `this` and [otherZone] are in the same error zone.
-   *
-   * Two zones are in the same error zone if they have the same [errorZone].
-   */
+  /// Whether this zone and [otherZone] are in the same error zone.
+  ///
+  /// Two zones are in the same error zone if they have the same [errorZone].
   bool inSameErrorZone(Zone otherZone);
 
-  /**
-   * Creates a new zone as a child of `this`.
-   *
-   * The new zone uses the closures in the given [specification] to override
-   * the current's zone behavior. All specification entries that are `null`
-   * inherit the behavior from the parent zone (`this`).
-   *
-   * The new zone inherits the stored values (accessed through [operator []])
-   * of this zone and updates them with values from [zoneValues], which either
-   * adds new values or overrides existing ones.
-   *
-   * Note that the fork operation is interceptible. A zone can thus change
-   * the zone specification (or zone values), giving the forking zone full
-   * control over the child zone.
-   */
+  /// Creates a new zone as a child zone of this zone.
+  ///
+  /// The new zone uses the closures in the given [specification] to override
+  /// the current's zone behavior. All specification entries that are `null`
+  /// inherit the behavior from the parent zone (`this`).
+  ///
+  /// The new zone inherits the stored values (accessed through [operator []])
+  /// of this zone and updates them with values from [zoneValues], which either
+  /// adds new values or overrides existing ones.
+  ///
+  /// Note that the fork operation is interceptible. A zone can thus change
+  /// the zone specification (or zone values), giving the forking zone full
+  /// control over the child zone.
   Zone fork(
       {ZoneSpecification? specification, Map<Object?, Object?>? zoneValues});
 
-  /**
-   * Executes [action] in this zone.
-   *
-   * By default (as implemented in the [root] zone), runs [action]
-   * with [current] set to this zone.
-   *
-   * If [action] throws, the synchronous exception is not caught by the zone's
-   * error handler. Use [runGuarded] to achieve that.
-   *
-   * Since the root zone is the only zone that can modify the value of
-   * [current], custom zones intercepting run should always delegate to their
-   * parent zone. They may take actions before and after the call.
-   */
+  /// Executes [action] in this zone.
+  ///
+  /// By default (as implemented in the [root] zone), runs [action]
+  /// with [current] set to this zone.
+  ///
+  /// If [action] throws, the synchronous exception is not caught by the zone's
+  /// error handler. Use [runGuarded] to achieve that.
+  ///
+  /// Since the root zone is the only zone that can modify the value of
+  /// [current], custom zones intercepting run should always delegate to their
+  /// parent zone. They may take actions before and after the call.
   R run<R>(R action());
 
-  /**
-   * Executes the given [action] with [argument] in this zone.
-   *
-   * As [run] except that [action] is called with one [argument] instead of
-   * none.
-   */
+  /// Executes the given [action] with [argument] in this zone.
+  ///
+  /// As [run] except that [action] is called with one [argument] instead of
+  /// none.
   R runUnary<R, T>(R action(T argument), T argument);
 
-  /**
-   * Executes the given [action] with [argument1] and [argument2] in this
-   * zone.
-   *
-   * As [run] except that [action] is called with two arguments instead of none.
-   */
+  /// Executes the given [action] with [argument1] and [argument2] in this
+  /// zone.
+  ///
+  /// As [run] except that [action] is called with two arguments instead of none.
   R runBinary<R, T1, T2>(
       R action(T1 argument1, T2 argument2), T1 argument1, T2 argument2);
 
-  /**
-   * Executes the given [action] in this zone and catches synchronous
-   * errors.
-   *
-   * This function is equivalent to:
-   * ```
-   * try {
-   *   this.run(action);
-   * } catch (e, s) {
-   *   this.handleUncaughtError(e, s);
-   * }
-   * ```
-   *
-   * See [run].
-   */
+  /// Executes the given [action] in this zone and catches synchronous
+  /// errors.
+  ///
+  /// This function is equivalent to:
+  /// ```
+  /// try {
+  ///   this.run(action);
+  /// } catch (e, s) {
+  ///   this.handleUncaughtError(e, s);
+  /// }
+  /// ```
+  ///
+  /// See [run].
   void runGuarded(void action());
 
-  /**
-   * Executes the given [action] with [argument] in this zone and
-   * catches synchronous errors.
-   *
-   * See [runGuarded].
-   */
+  /// Executes the given [action] with [argument] in this zone and
+  /// catches synchronous errors.
+  ///
+  /// See [runGuarded].
   void runUnaryGuarded<T>(void action(T argument), T argument);
 
-  /**
-   * Executes the given [action] with [argument1] and [argument2] in this
-   * zone and catches synchronous errors.
-   *
-   * See [runGuarded].
-   */
+  /// Executes the given [action] with [argument1] and [argument2] in this
+  /// zone and catches synchronous errors.
+  ///
+  /// See [runGuarded].
   void runBinaryGuarded<T1, T2>(
       void action(T1 argument1, T2 argument2), T1 argument1, T2 argument2);
 
-  /**
-   * Registers the given callback in this zone.
-   *
-   * When implementing an asynchronous primitive that uses callbacks, the
-   * callback must be registered using [registerCallback] at the point where the
-   * user provides the callback. This allows zones to record other information
-   * that they need at the same time, perhaps even wrapping the callback, so
-   * that the callback is prepared when it is later run in the same zones
-   * (using [run]). For example, a zone may decide
-   * to store the stack trace (at the time of the registration) with the
-   * callback.
-   *
-   * Returns the callback that should be used in place of the provided
-   * [callback]. Frequently zones simply return the original callback.
-   *
-   * Custom zones may intercept this operation. The default implementation in
-   * [Zone.root] returns the original callback unchanged.
-   */
+  /// Registers the given callback in this zone.
+  ///
+  /// When implementing an asynchronous primitive that uses callbacks, the
+  /// callback must be registered using [registerCallback] at the point where the
+  /// user provides the callback. This allows zones to record other information
+  /// that they need at the same time, perhaps even wrapping the callback, so
+  /// that the callback is prepared when it is later run in the same zones
+  /// (using [run]). For example, a zone may decide
+  /// to store the stack trace (at the time of the registration) with the
+  /// callback.
+  ///
+  /// Returns the callback that should be used in place of the provided
+  /// [callback]. Frequently zones simply return the original callback.
+  ///
+  /// Custom zones may intercept this operation. The default implementation in
+  /// [Zone.root] returns the original callback unchanged.
   ZoneCallback<R> registerCallback<R>(R callback());
 
-  /**
-   * Registers the given callback in this zone.
-   *
-   * Similar to [registerCallback] but with a unary callback.
-   */
+  /// Registers the given callback in this zone.
+  ///
+  /// Similar to [registerCallback] but with a unary callback.
   ZoneUnaryCallback<R, T> registerUnaryCallback<R, T>(R callback(T arg));
 
-  /**
-   * Registers the given callback in this zone.
-   *
-   * Similar to [registerCallback] but with a unary callback.
-   */
+  /// Registers the given callback in this zone.
+  ///
+  /// Similar to [registerCallback] but with a unary callback.
   ZoneBinaryCallback<R, T1, T2> registerBinaryCallback<R, T1, T2>(
       R callback(T1 arg1, T2 arg2));
 
-  /**
-   *  Registers the provided [callback] and returns a function that will
-   *  execute in this zone.
-   *
-   *  Equivalent to:
-   *
-   *      ZoneCallback registered = this.registerCallback(callback);
-   *      return () => this.run(registered);
-   *
-   */
+  /// Registers the provided [callback] and returns a function that will
+  /// execute in this zone.
+  ///
+  /// Equivalent to:
+  /// ```dart
+  /// ZoneCallback registered = this.registerCallback(callback);
+  /// return () => this.run(registered);
+  /// ```
   ZoneCallback<R> bindCallback<R>(R callback());
 
-  /**
-   *  Registers the provided [callback] and returns a function that will
-   *  execute in this zone.
-   *
-   *  Equivalent to:
-   *
-   *      ZoneCallback registered = this.registerUnaryCallback(callback);
-   *      return (arg) => thin.runUnary(registered, arg);
-   */
+  /// Registers the provided [callback] and returns a function that will
+  /// execute in this zone.
+  ///
+  /// Equivalent to:
+  /// ```dart
+  /// ZoneCallback registered = this.registerUnaryCallback(callback);
+  /// return (arg) => thin.runUnary(registered, arg);
+  /// ```
   ZoneUnaryCallback<R, T> bindUnaryCallback<R, T>(R callback(T argument));
 
-  /**
-   *  Registers the provided [callback] and returns a function that will
-   *  execute in this zone.
-   *
-   *  Equivalent to:
-   *
-   *      ZoneCallback registered = registerBinaryCallback(callback);
-   *      return (arg1, arg2) => thin.runBinary(registered, arg1, arg2);
-   */
+  /// Registers the provided [callback] and returns a function that will
+  /// execute in this zone.
+  ///
+  /// Equivalent to:
+  /// ```dart
+  /// ZoneCallback registered = registerBinaryCallback(callback);
+  /// return (arg1, arg2) => thin.runBinary(registered, arg1, arg2);
+  /// ```
   ZoneBinaryCallback<R, T1, T2> bindBinaryCallback<R, T1, T2>(
       R callback(T1 argument1, T2 argument2));
 
-  /**
-   * Registers the provided [callback] and returns a function that will
-   * execute in this zone.
-   *
-   * When the function executes, errors are caught and treated as uncaught
-   * errors.
-   *
-   * Equivalent to:
-   *
-   *     ZoneCallback registered = this.registerCallback(callback);
-   *     return () => this.runGuarded(registered);
-   *
-   */
+  /// Registers the provided [callback] and returns a function that will
+  /// execute in this zone.
+  ///
+  /// When the function executes, errors are caught and treated as uncaught
+  /// errors.
+  ///
+  /// Equivalent to:
+  /// ```dart
+  /// ZoneCallback registered = this.registerCallback(callback);
+  /// return () => this.runGuarded(registered);
+  /// ```
   void Function() bindCallbackGuarded(void Function() callback);
 
-  /**
-   * Registers the provided [callback] and returns a function that will
-   * execute in this zone.
-   *
-   * When the function executes, errors are caught and treated as uncaught
-   * errors.
-   *
-   * Equivalent to:
-   *
-   *     ZoneCallback registered = this.registerUnaryCallback(callback);
-   *     return (arg) => this.runUnaryGuarded(registered, arg);
-   */
+  /// Registers the provided [callback] and returns a function that will
+  /// execute in this zone.
+  ///
+  /// When the function executes, errors are caught and treated as uncaught
+  /// errors.
+  ///
+  /// Equivalent to:
+  /// ```dart
+  /// ZoneCallback registered = this.registerUnaryCallback(callback);
+  /// return (arg) => this.runUnaryGuarded(registered, arg);
+  /// ```
   void Function(T) bindUnaryCallbackGuarded<T>(void callback(T argument));
 
-  /**
-   *  Registers the provided [callback] and returns a function that will
-   *  execute in this zone.
-   *
-   *  Equivalent to:
-   *
-   *      ZoneCallback registered = registerBinaryCallback(callback);
-   *      return (arg1, arg2) => this.runBinaryGuarded(registered, arg1, arg2);
-   */
+  ///  Registers the provided [callback] and returns a function that will
+  ///  execute in this zone.
+  ///
+  ///  Equivalent to:
+  /// ```dart
+  ///  ZoneCallback registered = registerBinaryCallback(callback);
+  ///  return (arg1, arg2) => this.runBinaryGuarded(registered, arg1, arg2);
+  /// ```
   void Function(T1, T2) bindBinaryCallbackGuarded<T1, T2>(
       void callback(T1 argument1, T2 argument2));
 
-  /**
-   * Intercepts errors when added programmatically to a `Future` or `Stream`.
-   *
-   * When calling [Completer.completeError], [StreamController.addError],
-   * or some [Future] constructors, the current zone is allowed to intercept
-   * and replace the error.
-   *
-   * Future constructors invoke this function when the error is received
-   * directly, for example with [Future.error], or when the error is caught
-   * synchronously, for example with [Future.sync].
-   *
-   * There is no guarantee that an error is only sent through [errorCallback]
-   * once. Libraries that use intermediate controllers or completers might
-   * end up invoking [errorCallback] multiple times.
-   *
-   * Returns `null` if no replacement is desired. Otherwise returns an instance
-   * of [AsyncError] holding the new pair of error and stack trace.
-   *
-   * Although not recommended, the returned instance may have its `error` member
-   * ([AsyncError.error]) be equal to `null` in which case the error should be
-   * replaced by a [NullThrownError].
-   *
-   * Custom zones may intercept this operation.
-   *
-   * Implementations of a new asynchronous primitive that converts synchronous
-   * errors to asynchronous errors rarely need to invoke [errorCallback], since
-   * errors are usually reported through future completers or stream
-   * controllers.
-   */
+  /// Intercepts errors when added programmatically to a [Future] or [Stream].
+  ///
+  /// When calling [Completer.completeError], [StreamController.addError],
+  /// or some [Future] constructors, the current zone is allowed to intercept
+  /// and replace the error.
+  ///
+  /// Future constructors invoke this function when the error is received
+  /// directly, for example with [Future.error], or when the error is caught
+  /// synchronously, for example with [Future.sync].
+  ///
+  /// There is no guarantee that an error is only sent through [errorCallback]
+  /// once. Libraries that use intermediate controllers or completers might
+  /// end up invoking [errorCallback] multiple times.
+  ///
+  /// Returns `null` if no replacement is desired. Otherwise returns an instance
+  /// of [AsyncError] holding the new pair of error and stack trace.
+  ///
+  /// Custom zones may intercept this operation.
+  ///
+  /// Implementations of a new asynchronous primitive that converts synchronous
+  /// errors to asynchronous errors rarely need to invoke [errorCallback], since
+  /// errors are usually reported through future completers or stream
+  /// controllers.
   AsyncError? errorCallback(Object error, StackTrace? stackTrace);
 
-  /**
-   * Runs [callback] asynchronously in this zone.
-   *
-   * The global `scheduleMicrotask` delegates to the current zone's
-   * [scheduleMicrotask]. The root zone's implementation interacts with the
-   * underlying system to schedule the given callback as a microtask.
-   *
-   * Custom zones may intercept this operation (for example to wrap the given
-   * [callback]).
-   */
+  /// Runs [callback] asynchronously in this zone.
+  ///
+  /// The global `scheduleMicrotask` delegates to the [current] zone's
+  /// [scheduleMicrotask]. The root zone's implementation interacts with the
+  /// underlying system to schedule the given callback as a microtask.
+  ///
+  /// Custom zones may intercept this operation (for example to wrap the given
+  /// [callback]), or to implement their own microtask scheduler.
+  /// In the latter case, they will usually still use the parent zone's
+  /// [ZoneDelegate.scheduleMicrotask] to attach themselves to the existing
+  /// event loop.
   void scheduleMicrotask(void Function() callback);
 
-  /**
-   * Creates a Timer where the callback is executed in this zone.
-   */
+  /// Creates a [Timer] where the callback is executed in this zone.
   Timer createTimer(Duration duration, void Function() callback);
 
-  /**
-   * Creates a periodic Timer where the callback is executed in this zone.
-   */
+  /// Creates a periodic [Timer] where the callback is executed in this zone.
   Timer createPeriodicTimer(Duration period, void callback(Timer timer));
 
-  /**
-   * Prints the given [line].
-   *
-   * The global `print` function delegates to the current zone's [print]
-   * function which makes it possible to intercept printing.
-   *
-   * Example:
-   * ```
-   * import 'dart:async';
-   *
-   * main() {
-   *   runZoned(() {
-   *     // Ends up printing: "Intercepted: in zone".
-   *     print("in zone");
-   *   }, zoneSpecification: new ZoneSpecification(
-   *       print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
-   *     parent.print(zone, "Intercepted: $line");
-   *   }));
-   * }
-   * ```
-   */
+  /// Prints the given [line].
+  ///
+  /// The global `print` function delegates to the current zone's [print]
+  /// function which makes it possible to intercept printing.
+  ///
+  /// Example:
+  /// ```
+  /// import 'dart:async';
+  ///
+  /// main() {
+  ///   runZoned(() {
+  ///     // Ends up printing: "Intercepted: in zone".
+  ///     print("in zone");
+  ///   }, zoneSpecification: new ZoneSpecification(
+  ///       print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
+  ///     parent.print(zone, "Intercepted: $line");
+  ///   }));
+  /// }
+  /// ```
   void print(String line);
 
-  /**
-   * Call to enter the Zone.
-   *
-   * The previous current zone is returned.
-   */
+  /// Call to enter the [Zone].
+  ///
+  /// The previous current zone is returned.
   static _Zone _enter(_Zone zone) {
     assert(!identical(zone, _current));
     _Zone previous = _current;
@@ -713,27 +889,23 @@
     return previous;
   }
 
-  /**
-   * Call to leave the Zone.
-   *
-   * The previous Zone must be provided as `previous`.
-   */
+  /// Call to leave the [Zone].
+  ///
+  /// The previous [Zone] must be provided as `previous`.
   static void _leave(_Zone previous) {
     assert(previous != null);
     Zone._current = previous;
   }
 
-  /**
-   * Retrieves the zone-value associated with [key].
-   *
-   * If this zone does not contain the value looks up the same key in the
-   * parent zone. If the [key] is not found returns `null`.
-   *
-   * Any object can be used as key, as long as it has compatible `operator ==`
-   * and `hashCode` implementations.
-   * By controlling access to the key, a zone can grant or deny access to the
-   * zone value.
-   */
+  /// Retrieves the zone-value associated with [key].
+  ///
+  /// If this zone does not contain the value looks up the same key in the
+  /// parent zone. If the [key] is not found returns `null`.
+  ///
+  /// Any object can be used as key, as long as it has compatible `operator ==`
+  /// and `hashCode` implementations.
+  /// By controlling access to the key, a zone can grant or deny access to the
+  /// zone value.
   dynamic operator [](Object? key);
 }
 
@@ -839,9 +1011,7 @@
   }
 }
 
-/**
- * Base class for Zone implementations.
- */
+/// Base class for Zone implementations.
 abstract class _Zone implements Zone {
   const _Zone();
 
@@ -981,12 +1151,10 @@
     }
   }
 
-  /**
-   * The closest error-handling zone.
-   *
-   * Returns `this` if `this` has an error-handler. Otherwise returns the
-   * parent's error-zone.
-   */
+  /// The closest error-handling zone.
+  ///
+  /// Returns this zone if it has an error-handler. Otherwise returns the
+  /// parent's error-zone.
   Zone get errorZone => _handleUncaughtError.zone;
 
   void runGuarded(void f()) {
@@ -1352,12 +1520,10 @@
   // It's a lie, but the root zone never uses the parent delegate.
   ZoneDelegate get _parentDelegate => _delegate;
 
-  /**
-   * The closest error-handling zone.
-   *
-   * Returns `this` if `this` has an error-handler. Otherwise returns the
-   * parent's error-zone.
-   */
+  /// The closest error-handling zone.
+  ///
+  /// Returns `this` if `this` has an error-handler. Otherwise returns the
+  /// parent's error-zone.
   Zone get errorZone => this;
 
   // Zone interface.
@@ -1481,49 +1647,47 @@
 
 const _Zone _rootZone = const _RootZone();
 
-/**
- * Runs [body] in its own zone.
- *
- * Creates a new zone using [Zone.fork] based on [zoneSpecification] and
- * [zoneValues], then runs [body] in that zone and returns the result.
- *
- * If [onError] is provided, it must have one of the types
- * * `void Function(Object)`
- * * `void Function(Object, StackTrace)`
- * and the [onError] handler is used *both* to handle asynchronous errors
- * by overriding [ZoneSpecification.handleUncaughtError] in [zoneSpecification],
- * if any, *and* to handle errors thrown synchronously by the call to [body].
- *
- * If an error occurs synchronously in [body],
- * then throwing in the [onError] handler
- * makes the call to `runZone` throw that error,
- * and otherwise the call to `runZoned` attempt to return `null`.
- *
- * If the zone specification has a `handleUncaughtError` value or the [onError]
- * parameter is provided, the zone becomes an error-zone.
- *
- * Errors will never cross error-zone boundaries by themselves.
- * Errors that try to cross error-zone boundaries are considered uncaught in
- * their originating error zone.
- *
- *     var future = new Future.value(499);
- *     runZoned(() {
- *       var future2 = future.then((_) { throw "error in first error-zone"; });
- *       runZoned(() {
- *         var future3 = future2.catchError((e) { print("Never reached!"); });
- *       }, onError: (e, s) { print("unused error handler"); });
- *     }, onError: (e, s) { print("catches error of first error-zone."); });
- *
- * Example:
- *
- *     runZoned(() {
- *       new Future(() { throw "asynchronous error"; });
- *     }, onError: (e, s) => print(e));  // Will print "asynchronous error".
- *
- * It is possible to manually pass an error from one error zone to another
- * by re-throwing it in the new zone. If [onError] throws, that error will
- * occur in the original zone where [runZoned] was called.
- */
+/// Runs [body] in its own zone.
+///
+/// Creates a new zone using [Zone.fork] based on [zoneSpecification] and
+/// [zoneValues], then runs [body] in that zone and returns the result.
+///
+/// If [onError] is provided, it must have one of the types
+/// * `void Function(Object)`
+/// * `void Function(Object, StackTrace)`
+/// and the [onError] handler is used *both* to handle asynchronous errors
+/// by overriding [ZoneSpecification.handleUncaughtError] in [zoneSpecification],
+/// if any, *and* to handle errors thrown synchronously by the call to [body].
+///
+/// If an error occurs synchronously in [body],
+/// then throwing in the [onError] handler
+/// makes the call to `runZone` throw that error,
+/// and otherwise the call to `runZoned` attempt to return `null`.
+///
+/// If the zone specification has a `handleUncaughtError` value or the [onError]
+/// parameter is provided, the zone becomes an error-zone.
+///
+/// Errors will never cross error-zone boundaries by themselves.
+/// Errors that try to cross error-zone boundaries are considered uncaught in
+/// their originating error zone.
+/// ```dart
+/// var future = Future.value(499);
+/// runZoned(() {
+///   var future2 = future.then((_) { throw "error in first error-zone"; });
+///   runZoned(() {
+///     var future3 = future2.catchError((e) { print("Never reached!"); });
+///   }, onError: (e, s) { print("unused error handler"); });
+/// }, onError: (e, s) { print("catches error of first error-zone."); });
+/// ```
+/// Example:
+/// ```dart
+/// runZoned(() {
+///   Future(() { throw "asynchronous error"; });
+/// }, onError: (e, s) => print(e));  // Will print "asynchronous error".
+/// ```
+/// It is possible to manually pass an error from one error zone to another
+/// by re-throwing it in the new zone. If [onError] throws, that error will
+/// occur in the original zone where [runZoned] was called.
 R runZoned<R>(R body(),
     {Map<Object?, Object?>? zoneValues,
     ZoneSpecification? zoneSpecification,
@@ -1546,45 +1710,43 @@
   return _runZoned<R>(body, zoneValues, zoneSpecification);
 }
 
-/**
- * Runs [body] in its own error zone.
- *
- * Creates a new zone using [Zone.fork] based on [zoneSpecification] and
- * [zoneValues], then runs [body] in that zone and returns the result.
- *
- * The [onError] function is used *both* to handle asynchronous errors
- * by overriding [ZoneSpecification.handleUncaughtError] in [zoneSpecification],
- * if any, *and* to handle errors thrown synchronously by the call to [body].
- *
- * If an error occurs synchronously in [body],
- * then throwing in the [onError] handler
- * makes the call to `runZonedGuarded` throw that error,
- * and otherwise the call to `runZonedGuarded` returns `null`.
- *
- * The zone will always be an error-zone.
- *
- * Errors will never cross error-zone boundaries by themselves.
- * Errors that try to cross error-zone boundaries are considered uncaught in
- * their originating error zone.
- * ```dart
- * var future = Future.value(499);
- * runZonedGuarded(() {
- *   var future2 = future.then((_) { throw "error in first error-zone"; });
- *   runZonedGuarded(() {
- *     var future3 = future2.catchError((e) { print("Never reached!"); });
- *   }, (e, s) { print("unused error handler"); });
- * }, (e, s) { print("catches error of first error-zone."); });
- * ```
- * Example:
- * ```dart
- * runZonedGuarded(() {
- *   new Future(() { throw "asynchronous error"; });
- * }, (e, s) => print(e));  // Will print "asynchronous error".
- * ```
- * It is possible to manually pass an error from one error zone to another
- * by re-throwing it in the new zone. If [onError] throws, that error will
- * occur in the original zone where [runZoned] was called.
- */
+/// Runs [body] in its own error zone.
+///
+/// Creates a new zone using [Zone.fork] based on [zoneSpecification] and
+/// [zoneValues], then runs [body] in that zone and returns the result.
+///
+/// The [onError] function is used *both* to handle asynchronous errors
+/// by overriding [ZoneSpecification.handleUncaughtError] in [zoneSpecification],
+/// if any, *and* to handle errors thrown synchronously by the call to [body].
+///
+/// If an error occurs synchronously in [body],
+/// then throwing in the [onError] handler
+/// makes the call to `runZonedGuarded` throw that error,
+/// and otherwise the call to `runZonedGuarded` returns `null`.
+///
+/// The zone will always be an error-zone.
+///
+/// Errors will never cross error-zone boundaries by themselves.
+/// Errors that try to cross error-zone boundaries are considered uncaught in
+/// their originating error zone.
+/// ```dart
+/// var future = Future.value(499);
+/// runZonedGuarded(() {
+///   var future2 = future.then((_) { throw "error in first error-zone"; });
+///   runZonedGuarded(() {
+///     var future3 = future2.catchError((e) { print("Never reached!"); });
+///   }, (e, s) { print("unused error handler"); });
+/// }, (e, s) { print("catches error of first error-zone."); });
+/// ```
+/// Example:
+/// ```dart
+/// runZonedGuarded(() {
+///   Future(() { throw "asynchronous error"; });
+/// }, (e, s) => print(e));  // Will print "asynchronous error".
+/// ```
+/// It is possible to manually pass an error from one error zone to another
+/// by re-throwing it in the new zone. If [onError] throws, that error will
+/// occur in the original zone where [runZoned] was called.
 @Since("2.8")
 R? runZonedGuarded<R>(R body(), void onError(Object error, StackTrace stack),
     {Map<Object?, Object?>? zoneValues, ZoneSpecification? zoneSpecification}) {
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index b050a48..ce3d87f 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.dart
@@ -5,9 +5,9 @@
 /// Classes and utilities that supplement the collection support in dart:core.
 ///
 /// To use this library in your code:
-///
-///     import 'dart:collection';
-///
+/// ```dart
+/// import 'dart:collection';
+/// ```
 /// {@category Core}
 library dart.collection;
 
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 3990cd2..c9c9d8e 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -24,8 +24,6 @@
 /// symmetric, transitive, and consistent over time), and that `hashCode`
 /// must be the same for objects that are considered equal by `==`.
 ///
-/// The map allows `null` as a key.
-///
 /// Iterating the map's keys, values or entries (through [forEach])
 /// may happen in any order.
 /// The iteration order only changes when the map is modified.
@@ -56,10 +54,10 @@
   /// [K] instance.
   ///
   /// Example:
-  ///
-  ///     new HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
-  ///                          hashCode: (int e) => e % 5)
-  ///
+  /// ```dart
+  /// HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
+  ///                  hashCode: (int e) => e % 5)
+  /// ```
   /// This example map does not need an `isValidKey` function to be passed.
   /// The default function accepts only `int` values, which can safely be
   /// passed to both the `equals` and `hashCode` functions.
@@ -90,9 +88,10 @@
   /// Creates an unordered identity-based map.
   ///
   /// Effectively a shorthand for:
-  ///
-  ///     new HashMap<K, V>(equals: identical,
-  ///                       hashCode: identityHashCode)
+  /// ```dart
+  /// HashMap<K, V>(equals: identical,
+  ///               hashCode: identityHashCode)
+  /// ```
   external factory HashMap.identity();
 
   /// Creates a [HashMap] that contains all key/value pairs of [other].
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index 6ebb04e..075627f 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -13,8 +13,6 @@
 /// must consistent with equality, so that the same for objects that are
 /// considered equal.
 ///
-/// The set allows `null` as an element.
-///
 /// Most simple operations on `HashSet` are done in (potentially amortized)
 /// constant time: [add], [contains], [remove], and [length], provided the hash
 /// codes of objects are well distributed.
@@ -47,10 +45,10 @@
   ///
   /// If [isValidKey] is omitted, it defaults to testing if the object is an
   /// [E] instance. That means that:
-  ///
-  ///     new HashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
-  ///                      hashCode: (int e) => e % 5)
-  ///
+  /// ```dart
+  /// HashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
+  ///              hashCode: (int e) => e % 5)
+  /// ```
   /// does not need an `isValidKey` argument, because it defaults to only
   /// accepting `int` values which are accepted by both `equals` and `hashCode`.
   ///
@@ -71,9 +69,10 @@
   /// Creates an unordered identity-based set.
   ///
   /// Effectively a shorthand for:
-  ///
-  ///     new HashSet<E>(equals: identical,
-  ///                    hashCode: identityHashCode)
+  /// ```dart
+  /// HashSet<E>(equals: identical,
+  ///                hashCode: identityHashCode)
+  /// ```
   external factory HashSet.identity();
 
   /// Create a hash set containing all [elements].
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index 9dfdb99..872248e 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -19,8 +19,6 @@
 /// must define a stable equivalence relation on the keys (reflexive,
 /// symmetric, transitive, and consistent over time), and that `hashCode`
 /// must be the same for objects that are considered equal by `==`.
-///
-/// The map allows `null` as a key.
 abstract class LinkedHashMap<K, V> implements Map<K, V> {
   /// Creates an insertion-ordered hash-table based [Map].
   ///
@@ -41,10 +39,10 @@
   /// [K] instance.
   ///
   /// Example:
-  ///
-  ///     new LinkedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
-  ///                                hashCode: (int e) => e % 5)
-  ///
+  /// ```dart
+  /// LinkedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
+  ///                        hashCode: (int e) => e % 5)
+  /// ```
   /// This example map does not need an `isValidKey` function to be passed.
   /// The default function accepts only `int` values, which can safely be
   /// passed to both the `equals` and `hashCode` functions.
@@ -74,9 +72,10 @@
   /// Creates an insertion-ordered identity-based map.
   ///
   /// Effectively a shorthand for:
-  ///
-  ///     new LinkedHashMap<K, V>(equals: identical,
-  ///                             hashCode: identityHashCode)
+  /// ```dart
+  /// LinkedHashMap<K, V>(equals: identical,
+  ///                     hashCode: identityHashCode)
+  /// ```
   external factory LinkedHashMap.identity();
 
   /// Creates a [LinkedHashMap] that contains all key value pairs of [other].
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index c4f6818..a27a89b 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -15,8 +15,6 @@
 /// symmetric, transitive, and consistent over time), and that `hashCode`
 /// must be the same for objects that are considered equal by `==`.
 ///
-/// The set allows `null` as an element.
-///
 /// Iteration of elements is done in element insertion order.
 /// An element that was added after another will occur later in the iteration.
 /// Adding an element that is already in the set
@@ -54,10 +52,10 @@
   ///
   /// If [isValidKey] is omitted, it defaults to testing if the object is an
   /// [E] instance. That means that:
-  ///
-  ///     new LinkedHashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
-  ///                            hashCode: (int e) => e % 5)
-  ///
+  /// ```dart
+  /// LinkedHashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
+  ///                    hashCode: (int e) => e % 5)
+  /// ```
   /// does not need an `isValidKey` argument, because it defaults to only
   /// accepting `int` values which are accepted by both `equals` and `hashCode`.
   ///
@@ -78,9 +76,10 @@
   /// Creates an insertion-ordered identity-based set.
   ///
   /// Effectively a shorthand for:
-  ///
-  ///     new LinkedHashSet<E>(equals: identical,
-  ///                          hashCode: identityHashCode)
+  /// ```dart
+  /// LinkedHashSet<E>(equals: identical,
+  ///                      hashCode: identityHashCode)
+  /// ```
   external factory LinkedHashSet.identity();
 
   /// Create a linked hash set containing all [elements].
@@ -91,10 +90,11 @@
   /// All the [elements] should be instances of [E].
   /// The `elements` iterable itself may have any element type,
   /// so this constructor can be used to down-cast a `Set`, for example as:
-  ///
-  ///     Set<SuperType> superSet = ...;
-  ///     Iterable<SuperType> tmp = superSet.where((e) => e is SubType);
-  ///     Set<SubType> subSet = new LinkedHashSet<SubType>.from(tmp);
+  /// ```dart
+  /// Set<SuperType> superSet = ...;
+  /// Iterable<SuperType> tmp = superSet.where((e) => e is SubType);
+  /// Set<SubType> subSet = LinkedHashSet<SubType>.from(tmp);
+  /// ```
   factory LinkedHashSet.from(Iterable<dynamic> elements) {
     LinkedHashSet<E> result = LinkedHashSet<E>();
     for (final element in elements) {
diff --git a/sdk/lib/collection/linked_list.dart b/sdk/lib/collection/linked_list.dart
index 6d6be81..3e77646 100644
--- a/sdk/lib/collection/linked_list.dart
+++ b/sdk/lib/collection/linked_list.dart
@@ -19,7 +19,7 @@
 /// list, it must first be removed from its current list (if any).
 /// For the same reason, the [remove] and [contains] methods
 /// are based on *identity*, even if the [LinkedListEntry] chooses
-/// to override [Object.operator==].
+/// to override [Object.==].
 ///
 /// In return, each element knows its own place in the linked list, as well as
 /// which list it is in. This allows constant time
@@ -33,16 +33,16 @@
   int _length = 0;
   E? _first;
 
-  /// Construct a new empty linked list.
+  /// Constructs a new empty linked list.
   LinkedList();
 
-  /// Add [entry] to the beginning of the linked list.
+  /// Adds [entry] to the beginning of the linked list.
   void addFirst(E entry) {
     _insertBefore(_first, entry, updateFirst: true);
     _first = entry;
   }
 
-  /// Add [entry] to the end of the linked list.
+  /// Adds [entry] to the end of the linked list.
   void add(E entry) {
     _insertBefore(_first, entry, updateFirst: false);
   }
@@ -52,7 +52,7 @@
     entries.forEach(add);
   }
 
-  /// Remove [entry] from the linked list.
+  /// Removes [entry] from the linked list.
   ///
   /// Returns false and does nothing if [entry] is not in this linked list.
   ///
@@ -225,9 +225,9 @@
   E? _next;
   E? _previous;
 
-  /// Get the linked list containing this element.
+  /// The linked list containing this element.
   ///
-  /// Returns `null` if this entry is not currently in any list.
+  /// The value is `null` if this entry is not currently in any list.
   LinkedList<E>? get list => _list;
 
   /// Unlink the element from its linked list.
@@ -237,19 +237,19 @@
     _list!._unlink(this as E);
   }
 
-  /// Return the successor of this element in its linked list.
+  /// The successor of this element in its linked list.
   ///
-  /// Returns `null` if there is no successor in the linked list, or if this
-  /// entry is not currently in any list.
+  /// The value is  `null` if there is no successor in the linked list,
+  /// or if this entry is not currently in any list.
   E? get next {
     if (_list == null || identical(_list!.first, _next)) return null;
     return _next;
   }
 
-  /// Return the predecessor of this element in its linked list.
+  /// The predecessor of this element in its linked list.
   ///
-  /// Returns `null` if there is no predecessor in the linked list, or if this
-  /// entry is not currently in any list.
+  /// The value is `null` if there is no predecessor in the linked list,
+  /// or if this entry is not currently in any list.
   E? get previous {
     if (_list == null || identical(this, _list!.first)) return null;
     return _previous;
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index c238840..bb545b9 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -30,7 +30,7 @@
   /// ```dart
   /// Queue<SuperType> superQueue = ...;
   /// Queue<SubType> subQueue =
-  ///     new Queue<SubType>.from(superQueue.whereType<SubType>());
+  ///     Queue<SubType>.from(superQueue.whereType<SubType>());
   /// ```
   factory Queue.from(Iterable elements) = ListQueue<E>.from;
 
@@ -286,7 +286,7 @@
   /// ```dart
   /// Queue<SuperType> superQueue = ...;
   /// Queue<SubType> subQueue =
-  ///     new DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>());
+  ///     DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>());
   /// ```
   factory DoubleLinkedQueue.from(Iterable<dynamic> elements) {
     DoubleLinkedQueue<E> list = DoubleLinkedQueue<E>();
@@ -565,7 +565,7 @@
   /// ```dart
   /// Queue<SuperType> superQueue = ...;
   /// Queue<SubType> subQueue =
-  ///     new ListQueue<SubType>.from(superQueue.whereType<SubType>());
+  ///     ListQueue<SubType>.from(superQueue.whereType<SubType>());
   /// ```
   factory ListQueue.from(Iterable<dynamic> elements) {
     if (elements is List<dynamic>) {
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 5cd75d6..81ca0a8 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -340,8 +340,38 @@
   Set<E> toSet() => _newSet()..addAll(this);
 }
 
+abstract class _UnmodifiableSetMixin<E> implements Set<E> {
+  static Never _throwUnmodifiable() {
+    throw UnsupportedError("Cannot change an unmodifiable set");
+  }
+
+  /// This operation is not supported by an unmodifiable set.
+  bool add(E value) => _throwUnmodifiable();
+
+  /// This operation is not supported by an unmodifiable set.
+  void clear() => _throwUnmodifiable();
+
+  /// This operation is not supported by an unmodifiable set.
+  void addAll(Iterable<E> elements) => _throwUnmodifiable();
+
+  /// This operation is not supported by an unmodifiable set.
+  void removeAll(Iterable<Object?> elements) => _throwUnmodifiable();
+
+  /// This operation is not supported by an unmodifiable set.
+  void retainAll(Iterable<Object?> elements) => _throwUnmodifiable();
+
+  /// This operation is not supported by an unmodifiable set.
+  void removeWhere(bool test(E element)) => _throwUnmodifiable();
+
+  /// This operation is not supported by an unmodifiable set.
+  void retainWhere(bool test(E element)) => _throwUnmodifiable();
+
+  /// This operation is not supported by an unmodifiable set.
+  bool remove(Object? value) => _throwUnmodifiable();
+}
+
 /// Class used to implement const sets.
-class _UnmodifiableSet<E> extends _SetBase<E> {
+class _UnmodifiableSet<E> extends _SetBase<E> with _UnmodifiableSetMixin<E> {
   final Map<E, Null> _map;
 
   const _UnmodifiableSet(this._map);
@@ -364,38 +394,26 @@
     }
     return null;
   }
+}
 
-  // Mutating methods throw.
+/// An unmodifiable [Set] view of another [Set].
+///
+/// Methods that could change the set, such as [add] and [remove],
+/// must not be called.
+@Since("2.12")
+class UnmodifiableSetView<E> extends SetBase<E> with _UnmodifiableSetMixin<E> {
+  final Set<E> _source;
 
-  bool add(E value) {
-    throw UnsupportedError("Cannot change unmodifiable set");
-  }
+  /// Creates an [UnmodifiableSetView] of [source].
+  UnmodifiableSetView(Set<E> source) : _source = source;
 
-  void clear() {
-    throw UnsupportedError("Cannot change unmodifiable set");
-  }
+  bool contains(Object? element) => _source.contains(element);
 
-  void addAll(Iterable<E> elements) {
-    throw UnsupportedError("Cannot change unmodifiable set");
-  }
+  E? lookup(Object? element) => _source.lookup(element);
 
-  void removeAll(Iterable<Object?> elements) {
-    throw UnsupportedError("Cannot change unmodifiable set");
-  }
+  int get length => _source.length;
 
-  void retainAll(Iterable<Object?> elements) {
-    throw UnsupportedError("Cannot change unmodifiable set");
-  }
+  Iterator<E> get iterator => _source.iterator;
 
-  void removeWhere(bool test(E element)) {
-    throw UnsupportedError("Cannot change unmodifiable set");
-  }
-
-  void retainWhere(bool test(E element)) {
-    throw UnsupportedError("Cannot change unmodifiable set");
-  }
-
-  bool remove(Object? value) {
-    throw UnsupportedError("Cannot change unmodifiable set");
-  }
+  Set<E> toSet() => _source.toSet();
 }
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index a019b64..2ad35f6 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -474,20 +474,25 @@
 
   Iterable<V> get values => _SplayTreeValueIterable<K, V>(this);
 
-  /// Get the first key in the map. Returns `null` if the map is empty.
+  /// The first key in the map.
+  ///
+  /// Returns `null` if the map is empty.
   K? firstKey() {
     if (_root == null) return null;
     return _first!.key;
   }
 
-  /// Get the last key in the map. Returns `null` if the map is empty.
+  /// The last key in the map.
+  ///
+  /// Returns `null` if the map is empty.
   K? lastKey() {
     if (_root == null) return null;
     return _last!.key;
   }
 
-  /// Get the last key in the map that is strictly smaller than [key]. Returns
-  /// `null` if no key was not found.
+  /// The last key in the map that is strictly smaller than [key].
+  ///
+  /// Returns `null` if no key was not found.
   K? lastKeyBefore(K key) {
     if (key == null) throw ArgumentError(key);
     if (_root == null) return null;
@@ -729,7 +734,7 @@
   /// ```dart
   /// Set<SuperType> superSet = ...;
   /// Set<SubType> subSet =
-  ///     new SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
+  ///     SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
   /// ```
   factory SplayTreeSet.from(Iterable elements,
       [int Function(E key1, E key2)? compare,
diff --git a/sdk/lib/convert/base64.dart b/sdk/lib/convert/base64.dart
index 0955ca1..5fcab0a 100644
--- a/sdk/lib/convert/base64.dart
+++ b/sdk/lib/convert/base64.dart
@@ -11,11 +11,11 @@
 /// does not allow invalid characters and requires padding.
 ///
 /// Examples:
-///
-///     var encoded = base64.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
-///                                  0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
-///     var decoded = base64.decode("YmzDpWLDpnJncsO4ZAo=");
-///
+/// ```dart
+/// var encoded = base64.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
+///                              0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+/// var decoded = base64.decode("YmzDpWLDpnJncsO4ZAo=");
+/// ```
 /// The top-level [base64Encode] and [base64Decode] functions may be used
 /// instead if a local variable shadows the [base64] constant.
 const Base64Codec base64 = Base64Codec();
@@ -27,10 +27,11 @@
 /// does not allow invalid characters and requires padding.
 ///
 /// Examples:
-///
-///     var encoded = base64Url.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
-///                                     0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
-///     var decoded = base64Url.decode("YmzDpWLDpnJncsO4ZAo=");
+/// ```dart
+/// var encoded = base64Url.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
+///                                 0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+/// var decoded = base64Url.decode("YmzDpWLDpnJncsO4ZAo=");
+/// ```
 const Base64Codec base64Url = Base64Codec.urlSafe();
 
 /// Encodes [bytes] using [base64](https://tools.ietf.org/html/rfc4648) encoding.
diff --git a/sdk/lib/convert/convert.dart b/sdk/lib/convert/convert.dart
index 1ea3d26..081f006 100644
--- a/sdk/lib/convert/convert.dart
+++ b/sdk/lib/convert/convert.dart
@@ -11,9 +11,9 @@
 /// chain and to use with streams.
 ///
 /// To use this library in your code:
-///
-///     import 'dart:convert';
-///
+/// ```dart
+/// import 'dart:convert';
+/// ```
 /// Two commonly used converters are the top-level instances of
 /// [JsonCodec] and [Utf8Codec], named [json] and [utf8], respectively.
 ///
@@ -34,19 +34,19 @@
 /// as it's read from a file,
 /// The second is an instance of [LineSplitter],
 /// which splits the data on newline boundaries.
+/// ```dart
+/// var lineNumber = 1;
+/// var stream = File('quotes.txt').openRead();
 ///
-///     var lineNumber = 1;
-///     var stream = File('quotes.txt').openRead();
-///
-///     stream.transform(utf8.decoder)
-///           .transform(const LineSplitter())
-///           .listen((line) {
-///             if (showLineNumbers) {
-///               stdout.write('${lineNumber++} ');
-///             }
-///             stdout.writeln(line);
-///           });
-///
+/// stream.transform(utf8.decoder)
+///       .transform(const LineSplitter())
+///       .listen((line) {
+///         if (showLineNumbers) {
+///           stdout.write('${lineNumber++} ');
+///         }
+///         stdout.writeln(line);
+///       });
+/// ```
 /// See the documentation for the [Codec] and [Converter] classes
 /// for information about creating your own converters.
 ///
diff --git a/sdk/lib/convert/json.dart b/sdk/lib/convert/json.dart
index e55bc2a..33eaab6 100644
--- a/sdk/lib/convert/json.dart
+++ b/sdk/lib/convert/json.dart
@@ -56,10 +56,10 @@
 /// use cases.
 ///
 /// Examples:
-///
-///     var encoded = json.encode([1, 2, { "a": null }]);
-///     var decoded = json.decode('["foo", { "bar": 499 }]');
-///
+/// ```dart
+/// var encoded = json.encode([1, 2, { "a": null }]);
+/// var decoded = json.decode('["foo", { "bar": 499 }]');
+/// ```
 /// The top-level [jsonEncode] and [jsonDecode] functions may be used instead if
 /// a local variable shadows the [json] constant.
 const JsonCodec json = JsonCodec();
@@ -99,9 +99,10 @@
 /// JSON objects.
 ///
 /// Examples:
-///
-///     var encoded = json.encode([1, 2, { "a": null }]);
-///     var decoded = json.decode('["foo", { "bar": 499 }]');
+/// ```dart
+/// var encoded = json.encode([1, 2, { "a": null }]);
+/// var decoded = json.decode('["foo", { "bar": 499 }]');
+/// ```
 class JsonCodec extends Codec<Object?, String> {
   final Object? Function(Object? key, Object? value)? _reviver;
   final Object? Function(dynamic)? _toEncodable;
@@ -246,7 +247,7 @@
   /// If the conversion throws, or returns a value that is not directly
   /// serializable, a [JsonUnsupportedObjectError] exception is thrown.
   /// If the call throws, the error is caught and stored in the
-  /// [JsonUnsupportedObjectError]'s [:cause:] field.
+  /// [JsonUnsupportedObjectError]'s `cause` field.
   ///
   /// If a [List] or [Map] contains a reference to itself, directly or through
   /// other lists or maps, it cannot be serialized and a [JsonCyclicError] is
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart
index c74f918..bbfba77 100644
--- a/sdk/lib/convert/utf.dart
+++ b/sdk/lib/convert/utf.dart
@@ -16,10 +16,11 @@
 /// use cases.
 ///
 /// Examples:
-///
-///     var encoded = utf8.encode("Îñţérñåţîöñåļîžåţîờñ");
-///     var decoded = utf8.decode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
-///                                0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+/// ```dart
+/// var encoded = utf8.encode("Îñţérñåţîöñåļîžåţîờñ");
+/// var decoded = utf8.decode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
+///                            0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+/// ```
 const Utf8Codec utf8 = Utf8Codec();
 
 /// A [Utf8Codec] encodes strings to utf-8 code units (bytes) and decodes
diff --git a/sdk/lib/core/annotations.dart b/sdk/lib/core/annotations.dart
index ec9c489..dcfa5e0 100644
--- a/sdk/lib/core/annotations.dart
+++ b/sdk/lib/core/annotations.dart
@@ -4,71 +4,76 @@
 
 part of dart.core;
 
-/**
- * The annotation `@Deprecated('migration')` marks a feature as deprecated.
- *
- * The annotation [deprecated] is a shorthand for deprecating until
- * an unspecified "next release" without migration instructions.
- *
- * The intent of the `@Deprecated` annotation is to inform users of a feature
- * that they should change their code, even if it is currently still working
- * correctly.
- *
- * A deprecated feature is scheduled to be removed at a later time, possibly
- * specified in [message]. A deprecated feature should not be used, code using
- * it will break at some point in the future. If existing code is using the
- * feature it should be rewritten to not use the deprecated feature.
- *
- * A deprecated feature should document how the same effect can be achieved in
- * [message], so the programmer knows how to rewrite the code.
- *
- * The `@Deprecated` annotation applies to libraries, top-level declarations
- * (variables, getters, setters, functions, classes and typedefs),
- * class-level declarations (variables, getters, setters, methods, operators or
- * constructors, whether static or not), named optional arguments and
- * trailing optional positional parameters.
- *
- * Deprecation is transitive:
- *
- *  - If a library is deprecated, so is every member of it.
- *  - If a class is deprecated, so is every member of it.
- *  - If a variable is deprecated, so are its implicit getter and setter.
- *
- *
- * A tool that processes Dart source code may report when:
- *
- * - the code imports a deprecated library.
- * - the code exports a deprecated library, or any deprecated member of
- *   a non-deprecated library.
- * - the code refers statically to a deprecated declaration.
- * - the code dynamically uses a member of an object with a statically known
- *   type, where the member is deprecated on the static type of the object.
- * - the code dynamically calls a method with an argument where the
- *   corresponding optional parameter is deprecated on the object's static type.
- *
- *
- * If the deprecated use is inside a library, class or method which is itself
- * deprecated, the tool should not bother the user about it.
- * A deprecated feature is expected to use other deprecated features.
- */
+/// The annotation `@Deprecated('migration')` marks a feature as deprecated.
+///
+/// The annotation [deprecated] is a shorthand for deprecating until
+/// an unspecified "next release" without migration instructions.
+///
+/// A feature can be any part of an API, from a full library to a single
+/// parameter.
+///
+/// The intent of the `@Deprecated` annotation is to inform authors
+/// who are currently using the feature,
+/// that they will soon need to stop using that feature in their code,
+/// even if the feature is currently still working correctly.
+///
+/// Deprecation is an early warning that the deprecated feature
+/// is scheduled to be removed at a later time,
+/// a time possibly specified in [message].
+/// A deprecated feature should no longer be used,
+/// code using it will break at some point in the future.
+/// If existing code is using the feature,
+/// that code should be rewritten to no longer use the deprecated feature.
+///
+/// A deprecated feature should document how the same effect can be achieved in
+/// [message], so the programmer knows how to rewrite the code.
+///
+/// The `@Deprecated` annotation applies to libraries, top-level declarations
+/// (variables, getters, setters, functions, classes, mixins,
+/// extension and typedefs),
+/// class-level declarations (variables, getters, setters, methods, operators or
+/// constructors, whether static or not), named optional parameters and
+/// trailing optional positional parameters.
+///
+/// Deprecation applies transitively to parts of a deprecated feature:
+///
+///  - If a library is deprecated, so is every member of it.
+///  - If a class is deprecated, so is every member of it.
+///  - If a variable is deprecated, so are its implicit getter and setter.
+///
+/// If a feature is deprecated in a superclass, it is *not* automatically
+/// deprecated in a subclass as well. It is reasonable to remove a member
+/// from a superclass and retain it in a subclass, so it needs to be possible
+/// to deprecate the member only in the superclass.
+///
+/// A tool that processes Dart source code may report when:
+///
+/// - the code imports a deprecated library.
+/// - the code exports a deprecated library, or any deprecated member of
+///   a non-deprecated library.
+/// - the code refers statically to a deprecated declaration.
+/// - the code uses a member of an object with a statically known
+///   type, where the member is deprecated on the interface of the static type.
+/// - the code calls a method with an argument where the
+///   corresponding optional parameter is deprecated on the object's static type.
+///
+/// If the deprecated use is inside a library, class or method which is itself
+/// deprecated, the tool should not bother the user about it.
+/// A deprecated feature is expected to use other deprecated features.
 class Deprecated {
-  /**
-   * Message provided to the user when they use the deprecated feature.
-   *
-   * The message should explain how to migrate away from the feature if an
-   * alternative is available, and when the deprecated feature is expected to be
-   * removed.
-   */
+  /// Message provided to the user when they use the deprecated feature.
+  ///
+  /// The message should explain how to migrate away from the feature if an
+  /// alternative is available, and when the deprecated feature is expected to be
+  /// removed.
   final String message;
 
-  /**
-   * Create a deprecation annotation which specifies the migration path and
-   * expiration of the annotated feature.
-   *
-   * The [message] argument should be readable by programmers, and should state
-   * an alternative feature (if available) as well as when an annotated feature
-   * is expected to be removed.
-   */
+  /// Create a deprecation annotation which specifies the migration path and
+  /// expiration of the annotated feature.
+  ///
+  /// The [message] argument should be readable by programmers, and should state
+  /// an alternative feature (if available) as well as when an annotated feature
+  /// is expected to be removed.
   const Deprecated(this.message);
 
   @Deprecated('Use `message` instead. Will be removed in Dart 3.0.0')
@@ -77,9 +82,7 @@
   String toString() => "Deprecated feature: $message";
 }
 
-/**
- * Marks a feature as [Deprecated] until the next release.
- */
+/// Marks a feature as [Deprecated] until the next release.
 const Deprecated deprecated = Deprecated("next release");
 
 class _Override {
@@ -114,22 +117,18 @@
 /// can be used to enable more warnings based on `@override` annotations.
 const Object override = _Override();
 
-/**
- * An annotation class that was used during development of Dart 2.
- *
- * Should not be used any more.
- */
+/// An annotation class that was used during development of Dart 2.
+///
+/// Should not be used any more.
 @deprecated
 class Provisional {
   String? get message => null;
   const Provisional({String? message});
 }
 
-/**
- * An annotation that was used during development of Dart 2.
- *
- * The annotation has no effect, and will be removed.
- */
+/// An annotation that was used during development of Dart 2.
+///
+/// The annotation has no effect, and will be removed.
 @deprecated
 const Null provisional = null;
 
@@ -139,55 +138,51 @@
 @deprecated
 const Null proxy = null;
 
-/**
- * A hint to tools.
- *
- * Tools that work with Dart programs may accept hints to guide their behavior
- * as `pragma` annotations on declarations.
- * Each tool decides which hints it accepts, what they mean, and whether and
- * how they apply to sub-parts of the annotated entity.
- *
- * Tools that recognize pragma hints should pick a pragma prefix to identify
- * the tool. They should recognize any hint with a [name] starting with their
- * prefix followed by `:` as if it was intended for that tool. A hint with a
- * prefix for another tool should be ignored (unless compatibility with that
- * other tool is a goal).
- *
- * A tool may recognize unprefixed names as well, if they would recognize that
- * name with their own prefix in front.
- *
- * If the hint can be parameterized,
- * an extra [options] object can be added as well.
- *
- * For example:
- *
- * ```dart
- * @pragma('Tool:pragma-name', [param1, param2, ...])
- * class Foo { }
- *
- * @pragma('OtherTool:other-pragma')
- * void foo() { }
- * ```
- *
- * Here class `Foo` is annotated with a Tool specific pragma 'pragma-name' and
- * function `foo` is annotated with a pragma 'other-pragma'
- * specific to OtherTool.
- */
+/// A hint to tools.
+///
+/// Tools that work with Dart programs may accept hints to guide their behavior
+/// as `pragma` annotations on declarations.
+/// Each tool decides which hints it accepts, what they mean, and whether and
+/// how they apply to sub-parts of the annotated entity.
+///
+/// Tools that recognize pragma hints should pick a pragma prefix to identify
+/// the tool. They should recognize any hint with a [name] starting with their
+/// prefix followed by `:` as if it was intended for that tool. A hint with a
+/// prefix for another tool should be ignored (unless compatibility with that
+/// other tool is a goal).
+///
+/// A tool may recognize unprefixed names as well, if they would recognize that
+/// name with their own prefix in front.
+///
+/// If the hint can be parameterized,
+/// an extra [options] object can be added as well.
+///
+/// For example:
+///
+/// ```dart
+/// @pragma('Tool:pragma-name', [param1, param2, ...])
+/// class Foo { }
+///
+/// @pragma('OtherTool:other-pragma')
+/// void foo() { }
+/// ```
+///
+/// Here class `Foo` is annotated with a Tool specific pragma 'pragma-name' and
+/// function `foo` is annotated with a pragma 'other-pragma'
+/// specific to OtherTool.
 @pragma('vm:entry-point')
 class pragma {
-  /**
-   * The name of the hint.
-   *
-   * A string that is recognized by one or more tools, or such a string prefixed
-   * by a tool identifier and a colon, which is only recognized by that
-   * particular tool.
-   */
+  /// The name of the hint.
+  ///
+  /// A string that is recognized by one or more tools, or such a string prefixed
+  /// by a tool identifier and a colon, which is only recognized by that
+  /// particular tool.
   final String name;
 
-  /** Optional extra data parameterizing the hint. */
+  /// Optional extra data parameterizing the hint.
   final Object? options;
 
-  /** Creates a hint named [name] with optional [options]. */
+  /// Creates a hint named [name] with optional [options].
   const factory pragma(String name, [Object? options]) = pragma._;
 
   const pragma._(this.name, [this.options]);
diff --git a/sdk/lib/core/bigint.dart b/sdk/lib/core/bigint.dart
index 94a9445..25c0476 100644
--- a/sdk/lib/core/bigint.dart
+++ b/sdk/lib/core/bigint.dart
@@ -4,64 +4,54 @@
 
 part of dart.core;
 
-/**
- * An arbitrarily large integer.
- */
+/// An arbitrarily large integer.
 abstract class BigInt implements Comparable<BigInt> {
   external static BigInt get zero;
   external static BigInt get one;
   external static BigInt get two;
 
-  /**
-   * Parses [source] as a, possibly signed, integer literal and returns its
-   * value.
-   *
-   * The [source] must be a non-empty sequence of base-[radix] digits,
-   * optionally prefixed with a minus or plus sign ('-' or '+').
-   *
-   * The [radix] must be in the range 2..36. The digits used are
-   * first the decimal digits 0..9, and then the letters 'a'..'z' with
-   * values 10 through 35. Also accepts upper-case letters with the same
-   * values as the lower-case ones.
-   *
-   * If no [radix] is given then it defaults to 10. In this case, the [source]
-   * digits may also start with `0x`, in which case the number is interpreted
-   * as a hexadecimal literal, which effectively means that the `0x` is ignored
-   * and the radix is instead set to 16.
-   *
-   * For any int `n` and radix `r`, it is guaranteed that
-   * `n == int.parse(n.toRadixString(r), radix: r)`.
-   *
-   * Throws a [FormatException] if the [source] is not a valid integer literal,
-   * optionally prefixed by a sign.
-   */
+  /// Parses [source] as a, possibly signed, integer literal and returns its
+  /// value.
+  ///
+  /// The [source] must be a non-empty sequence of base-[radix] digits,
+  /// optionally prefixed with a minus or plus sign ('-' or '+').
+  ///
+  /// The [radix] must be in the range 2..36. The digits used are
+  /// first the decimal digits 0..9, and then the letters 'a'..'z' with
+  /// values 10 through 35. Also accepts upper-case letters with the same
+  /// values as the lower-case ones.
+  ///
+  /// If no [radix] is given then it defaults to 10. In this case, the [source]
+  /// digits may also start with `0x`, in which case the number is interpreted
+  /// as a hexadecimal literal, which effectively means that the `0x` is ignored
+  /// and the radix is instead set to 16.
+  ///
+  /// For any int `n` and radix `r`, it is guaranteed that
+  /// `n == int.parse(n.toRadixString(r), radix: r)`.
+  ///
+  /// Throws a [FormatException] if the [source] is not a valid integer literal,
+  /// optionally prefixed by a sign.
   external static BigInt parse(String source, {int? radix});
 
-  /**
-   * Parses [source] as a, possibly signed, integer literal and returns its
-   * value.
-   *
-   * As [parse] except that this method returns `null` if the input is not
-   * valid
-   */
+  /// Parses [source] as a, possibly signed, integer literal and returns its
+  /// value.
+  ///
+  /// As [parse] except that this method returns `null` if the input is not
+  /// valid
   external static BigInt? tryParse(String source, {int? radix});
 
   /// Allocates a big integer from the provided [value] number.
   external factory BigInt.from(num value);
 
-  /**
-   * Returns the absolute value of this integer.
-   *
-   * For any integer `x`, the result is the same as `x < 0 ? -x : x`.
-   */
+  /// Returns the absolute value of this integer.
+  ///
+  /// For any integer `x`, the result is the same as `x < 0 ? -x : x`.
   BigInt abs();
 
-  /**
-   * Return the negative value of this integer.
-   *
-   * The result of negating an integer always has the opposite sign, except
-   * for zero, which is its own negation.
-   */
+  /// Return the negative value of this integer.
+  ///
+  /// The result of negating an integer always has the opposite sign, except
+  /// for zero, which is its own negation.
   BigInt operator -();
 
   /// Addition operator.
@@ -76,171 +66,147 @@
   /// Division operator.
   double operator /(BigInt other);
 
-  /**
-   * Truncating division operator.
-   *
-   * Performs a truncating integer division, where the remainder is discarded.
-   *
-   * The remainder can be computed using the [remainder] method.
-   *
-   * Examples:
-   * ```
-   * var seven = new BigInt.from(7);
-   * var three = new BigInt.from(3);
-   * seven ~/ three;    // => 2
-   * (-seven) ~/ three; // => -2
-   * seven ~/ -three;   // => -2
-   * seven.remainder(three);    // => 1
-   * (-seven).remainder(three); // => -1
-   * seven.remainder(-three);   // => 1
-   * ```
-   */
+  /// Truncating division operator.
+  ///
+  /// Performs a truncating integer division, where the remainder is discarded.
+  ///
+  /// The remainder can be computed using the [remainder] method.
+  ///
+  /// Examples:
+  /// ```
+  /// var seven = BigInt.from(7);
+  /// var three = BigInt.from(3);
+  /// seven ~/ three;    // => 2
+  /// (-seven) ~/ three; // => -2
+  /// seven ~/ -three;   // => -2
+  /// seven.remainder(three);    // => 1
+  /// (-seven).remainder(three); // => -1
+  /// seven.remainder(-three);   // => 1
+  /// ```
   BigInt operator ~/(BigInt other);
 
-  /**
-   * Euclidean modulo operator.
-   *
-   * Returns the remainder of the Euclidean division. The Euclidean division of
-   * two integers `a` and `b` yields two integers `q` and `r` such that
-   * `a == b * q + r` and `0 <= r < b.abs()`.
-   *
-   * The sign of the returned value `r` is always positive.
-   *
-   * See [remainder] for the remainder of the truncating division.
-   */
+  /// Euclidean modulo operator.
+  ///
+  /// Returns the remainder of the Euclidean division. The Euclidean division of
+  /// two integers `a` and `b` yields two integers `q` and `r` such that
+  /// `a == b * q + r` and `0 <= r < b.abs()`.
+  ///
+  /// The sign of the returned value `r` is always positive.
+  ///
+  /// See [remainder] for the remainder of the truncating division.
   BigInt operator %(BigInt other);
 
-  /**
-   * Returns the remainder of the truncating division of `this` by [other].
-   *
-   * The result `r` of this operation satisfies:
-   * `this == (this ~/ other) * other + r`.
-   * As a consequence the remainder `r` has the same sign as the divider `this`.
-   */
+  /// Returns the remainder of the truncating division of `this` by [other].
+  ///
+  /// The result `r` of this operation satisfies:
+  /// `this == (this ~/ other) * other + r`.
+  /// As a consequence the remainder `r` has the same sign as the divider `this`.
   BigInt remainder(BigInt other);
 
-  /**
-   * Shift the bits of this integer to the left by [shiftAmount].
-   *
-   * Shifting to the left makes the number larger, effectively multiplying
-   * the number by `pow(2, shiftIndex)`.
-   *
-   * There is no limit on the size of the result. It may be relevant to
-   * limit intermediate values by using the "and" operator with a suitable
-   * mask.
-   *
-   * It is an error if [shiftAmount] is negative.
-   */
+  /// Shift the bits of this integer to the left by [shiftAmount].
+  ///
+  /// Shifting to the left makes the number larger, effectively multiplying
+  /// the number by `pow(2, shiftIndex)`.
+  ///
+  /// There is no limit on the size of the result. It may be relevant to
+  /// limit intermediate values by using the "and" operator with a suitable
+  /// mask.
+  ///
+  /// It is an error if [shiftAmount] is negative.
   BigInt operator <<(int shiftAmount);
 
-  /**
-   * Shift the bits of this integer to the right by [shiftAmount].
-   *
-   * Shifting to the right makes the number smaller and drops the least
-   * significant bits, effectively doing an integer division by
-   *`pow(2, shiftIndex)`.
-   *
-   * It is an error if [shiftAmount] is negative.
-   */
+  /// Shift the bits of this integer to the right by [shiftAmount].
+  ///
+  /// Shifting to the right makes the number smaller and drops the least
+  /// significant bits, effectively doing an integer division by
+  ///`pow(2, shiftIndex)`.
+  ///
+  /// It is an error if [shiftAmount] is negative.
   BigInt operator >>(int shiftAmount);
 
-  /**
-   * Bit-wise and operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with only the bits set that are set in
-   * both `this` and [other]
-   *
-   * Of both operands are negative, the result is negative, otherwise
-   * the result is non-negative.
-   */
+  /// Bit-wise and operator.
+  ///
+  /// Treating both `this` and [other] as sufficiently large two's component
+  /// integers, the result is a number with only the bits set that are set in
+  /// both `this` and [other]
+  ///
+  /// Of both operands are negative, the result is negative, otherwise
+  /// the result is non-negative.
   BigInt operator &(BigInt other);
 
-  /**
-   * Bit-wise or operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with the bits set that are set in either
-   * of `this` and [other]
-   *
-   * If both operands are non-negative, the result is non-negative,
-   * otherwise the result us negative.
-   */
+  /// Bit-wise or operator.
+  ///
+  /// Treating both `this` and [other] as sufficiently large two's component
+  /// integers, the result is a number with the bits set that are set in either
+  /// of `this` and [other]
+  ///
+  /// If both operands are non-negative, the result is non-negative,
+  /// otherwise the result us negative.
   BigInt operator |(BigInt other);
 
-  /**
-   * Bit-wise exclusive-or operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with the bits set that are set in one,
-   * but not both, of `this` and [other]
-   *
-   * If the operands have the same sign, the result is non-negative,
-   * otherwise the result is negative.
-   */
+  /// Bit-wise exclusive-or operator.
+  ///
+  /// Treating both `this` and [other] as sufficiently large two's component
+  /// integers, the result is a number with the bits set that are set in one,
+  /// but not both, of `this` and [other]
+  ///
+  /// If the operands have the same sign, the result is non-negative,
+  /// otherwise the result is negative.
   BigInt operator ^(BigInt other);
 
-  /**
-   * The bit-wise negate operator.
-   *
-   * Treating `this` as a sufficiently large two's component integer,
-   * the result is a number with the opposite bits set.
-   *
-   * This maps any integer `x` to `-x - 1`.
-   */
+  /// The bit-wise negate operator.
+  ///
+  /// Treating `this` as a sufficiently large two's component integer,
+  /// the result is a number with the opposite bits set.
+  ///
+  /// This maps any integer `x` to `-x - 1`.
   BigInt operator ~();
 
-  /** Relational less than operator. */
+  /// Relational less than operator.
   bool operator <(BigInt other);
 
-  /** Relational less than or equal operator. */
+  /// Relational less than or equal operator.
   bool operator <=(BigInt other);
 
-  /** Relational greater than operator. */
+  /// Relational greater than operator.
   bool operator >(BigInt other);
 
-  /** Relational greater than or equal operator. */
+  /// Relational greater than or equal operator.
   bool operator >=(BigInt other);
 
-  /**
-   * Compares this to `other`.
-   *
-   * Returns a negative number if `this` is less than `other`, zero if they are
-   * equal, and a positive number if `this` is greater than `other`.
-   */
+  /// Compares this to `other`.
+  ///
+  /// Returns a negative number if `this` is less than `other`, zero if they are
+  /// equal, and a positive number if `this` is greater than `other`.
   int compareTo(BigInt other);
 
-  /**
-   * Returns the minimum number of bits required to store this big integer.
-   *
-   * The number of bits excludes the sign bit, which gives the natural length
-   * for non-negative (unsigned) values.  Negative values are complemented to
-   * return the bit position of the first bit that differs from the sign bit.
-   *
-   * To find the number of bits needed to store the value as a signed value,
-   * add one, i.e. use `x.bitLength + 1`.
-   *
-   * ```
-   * x.bitLength == (-x-1).bitLength
-   *
-   * new BigInt.from(3).bitLength == 2;   // 00000011
-   * new BigInt.from(2).bitLength == 2;   // 00000010
-   * new BigInt.from(1).bitLength == 1;   // 00000001
-   * new BigInt.from(0).bitLength == 0;   // 00000000
-   * new BigInt.from(-1).bitLength == 0;  // 11111111
-   * new BigInt.from(-2).bitLength == 1;  // 11111110
-   * new BigInt.from(-3).bitLength == 2;  // 11111101
-   * new BigInt.from(-4).bitLength == 2;  // 11111100
-   * ```
-   */
+  /// Returns the minimum number of bits required to store this big integer.
+  ///
+  /// The number of bits excludes the sign bit, which gives the natural length
+  /// for non-negative (unsigned) values.  Negative values are complemented to
+  /// return the bit position of the first bit that differs from the sign bit.
+  ///
+  /// To find the number of bits needed to store the value as a signed value,
+  /// add one, i.e. use `x.bitLength + 1`.
+  ///
+  /// ```
+  /// x.bitLength == (-x-1).bitLength
+  ///
+  /// BigInt.from(3).bitLength == 2;   // 00000011
+  /// BigInt.from(2).bitLength == 2;   // 00000010
+  /// BigInt.from(1).bitLength == 1;   // 00000001
+  /// BigInt.from(0).bitLength == 0;   // 00000000
+  /// BigInt.from(-1).bitLength == 0;  // 11111111
+  /// BigInt.from(-2).bitLength == 1;  // 11111110
+  /// BigInt.from(-3).bitLength == 2;  // 11111101
+  /// BigInt.from(-4).bitLength == 2;  // 11111100
+  /// ```
   int get bitLength;
 
-  /**
-   * Returns the sign of this big integer.
-   *
-   * Returns 0 for zero, -1 for values less than zero and
-   * +1 for values greater than zero.
-   */
+  /// Returns the sign of this big integer.
+  ///
+  /// Returns 0 for zero, -1 for values less than zero and
+  /// +1 for values greater than zero.
   int get sign;
 
   /// Whether this big integer is even.
@@ -252,163 +218,141 @@
   /// Whether this number is negative.
   bool get isNegative;
 
-  /**
-   * Returns `this` to the power of [exponent].
-   *
-   * Returns [one] if the [exponent] equals 0.
-   *
-   * The [exponent] must otherwise be positive.
-   *
-   * The result is always equal to the mathematical result of this to the power
-   * [exponent], only limited by the available memory.
-   */
+  /// Returns `this` to the power of [exponent].
+  ///
+  /// Returns [one] if the [exponent] equals 0.
+  ///
+  /// The [exponent] must otherwise be positive.
+  ///
+  /// The result is always equal to the mathematical result of this to the power
+  /// [exponent], only limited by the available memory.
   BigInt pow(int exponent);
 
-  /**
-   * Returns this integer to the power of [exponent] modulo [modulus].
-   *
-   * The [exponent] must be non-negative and [modulus] must be
-   * positive.
-   */
+  /// Returns this integer to the power of [exponent] modulo [modulus].
+  ///
+  /// The [exponent] must be non-negative and [modulus] must be
+  /// positive.
   BigInt modPow(BigInt exponent, BigInt modulus);
 
-  /**
-   * Returns the modular multiplicative inverse of this big integer
-   * modulo [modulus].
-   *
-   * The [modulus] must be positive.
-   *
-   * It is an error if no modular inverse exists.
-   */
+  /// Returns the modular multiplicative inverse of this big integer
+  /// modulo [modulus].
+  ///
+  /// The [modulus] must be positive.
+  ///
+  /// It is an error if no modular inverse exists.
   // Returns 1/this % modulus, with modulus > 0.
   BigInt modInverse(BigInt modulus);
 
-  /**
-   * Returns the greatest common divisor of this big integer and [other].
-   *
-   * If either number is non-zero, the result is the numerically greatest
-   * integer dividing both `this` and `other`.
-   *
-   * The greatest common divisor is independent of the order,
-   * so `x.gcd(y)` is  always the same as `y.gcd(x)`.
-   *
-   * For any integer `x`, `x.gcd(x)` is `x.abs()`.
-   *
-   * If both `this` and `other` is zero, the result is also zero.
-   */
+  /// Returns the greatest common divisor of this big integer and [other].
+  ///
+  /// If either number is non-zero, the result is the numerically greatest
+  /// integer dividing both `this` and `other`.
+  ///
+  /// The greatest common divisor is independent of the order,
+  /// so `x.gcd(y)` is  always the same as `y.gcd(x)`.
+  ///
+  /// For any integer `x`, `x.gcd(x)` is `x.abs()`.
+  ///
+  /// If both `this` and `other` is zero, the result is also zero.
   BigInt gcd(BigInt other);
 
-  /**
-   * Returns the least significant [width] bits of this big integer as a
-   * non-negative number (i.e. unsigned representation).  The returned value has
-   * zeros in all bit positions higher than [width].
-   *
-   * ```
-   * new BigInt.from(-1).toUnsigned(5) == 31   // 11111111  ->  00011111
-   * ```
-   *
-   * This operation can be used to simulate arithmetic from low level languages.
-   * For example, to increment an 8 bit quantity:
-   *
-   * ```
-   * q = (q + 1).toUnsigned(8);
-   * ```
-   *
-   * `q` will count from `0` up to `255` and then wrap around to `0`.
-   *
-   * If the input fits in [width] bits without truncation, the result is the
-   * same as the input.  The minimum width needed to avoid truncation of `x` is
-   * given by `x.bitLength`, i.e.
-   *
-   * ```
-   * x == x.toUnsigned(x.bitLength);
-   * ```
-   */
+  /// Returns the least significant [width] bits of this big integer as a
+  /// non-negative number (i.e. unsigned representation).  The returned value has
+  /// zeros in all bit positions higher than [width].
+  ///
+  /// ```
+  /// BigInt.from(-1).toUnsigned(5) == 31   // 11111111  ->  00011111
+  /// ```
+  ///
+  /// This operation can be used to simulate arithmetic from low level languages.
+  /// For example, to increment an 8 bit quantity:
+  ///
+  /// ```
+  /// q = (q + 1).toUnsigned(8);
+  /// ```
+  ///
+  /// `q` will count from `0` up to `255` and then wrap around to `0`.
+  ///
+  /// If the input fits in [width] bits without truncation, the result is the
+  /// same as the input.  The minimum width needed to avoid truncation of `x` is
+  /// given by `x.bitLength`, i.e.
+  ///
+  /// ```
+  /// x == x.toUnsigned(x.bitLength);
+  /// ```
   BigInt toUnsigned(int width);
 
-  /**
-   * Returns the least significant [width] bits of this integer, extending the
-   * highest retained bit to the sign.  This is the same as truncating the value
-   * to fit in [width] bits using an signed 2-s complement representation.  The
-   * returned value has the same bit value in all positions higher than [width].
-   *
-   * ```
-   * var big15 = new BigInt.from(15);
-   * var big16 = new BigInt.from(16);
-   * var big239 = new BigInt.from(239);
-   *                                      V--sign bit-V
-   * big16.toSigned(5) == -big16   //  00010000 -> 11110000
-   * big239.toSigned(5) == big15   //  11101111 -> 00001111
-   *                                      ^           ^
-   * ```
-   *
-   * This operation can be used to simulate arithmetic from low level languages.
-   * For example, to increment an 8 bit signed quantity:
-   *
-   * ```
-   * q = (q + 1).toSigned(8);
-   * ```
-   *
-   * `q` will count from `0` up to `127`, wrap to `-128` and count back up to
-   * `127`.
-   *
-   * If the input value fits in [width] bits without truncation, the result is
-   * the same as the input.  The minimum width needed to avoid truncation of `x`
-   * is `x.bitLength + 1`, i.e.
-   *
-   * ```
-   * x == x.toSigned(x.bitLength + 1);
-   * ```
-   */
+  /// Returns the least significant [width] bits of this integer, extending the
+  /// highest retained bit to the sign.  This is the same as truncating the value
+  /// to fit in [width] bits using an signed 2-s complement representation.  The
+  /// returned value has the same bit value in all positions higher than [width].
+  ///
+  /// ```
+  /// var big15 = BigInt.from(15);
+  /// var big16 = BigInt.from(16);
+  /// var big239 = BigInt.from(239);
+  ///                                      V--sign bit-V
+  /// big16.toSigned(5) == -big16   //  00010000 -> 11110000
+  /// big239.toSigned(5) == big15   //  11101111 -> 00001111
+  ///                                      ^           ^
+  /// ```
+  ///
+  /// This operation can be used to simulate arithmetic from low level languages.
+  /// For example, to increment an 8 bit signed quantity:
+  ///
+  /// ```
+  /// q = (q + 1).toSigned(8);
+  /// ```
+  ///
+  /// `q` will count from `0` up to `127`, wrap to `-128` and count back up to
+  /// `127`.
+  ///
+  /// If the input value fits in [width] bits without truncation, the result is
+  /// the same as the input.  The minimum width needed to avoid truncation of `x`
+  /// is `x.bitLength + 1`, i.e.
+  ///
+  /// ```
+  /// x == x.toSigned(x.bitLength + 1);
+  /// ```
   BigInt toSigned(int width);
 
-  /**
-   * Whether this big integer can be represented as an `int` without losing
-   * precision.
-   *
-   * Warning: this function may give a different result on
-   * dart2js, dev compiler, and the VM, due to the differences in
-   * integer precision.
-   */
+  /// Whether this big integer can be represented as an `int` without losing
+  /// precision.
+  ///
+  /// Warning: this function may give a different result on
+  /// dart2js, dev compiler, and the VM, due to the differences in
+  /// integer precision.
   bool get isValidInt;
 
-  /**
-   * Returns this [BigInt] as an [int].
-   *
-   * If the number does not fit, clamps to the max (or min)
-   * integer.
-   *
-   * Warning: the clamping behaves differently on dart2js, dev
-   * compiler, and the VM, due to the differences in integer
-   * precision.
-   */
+  /// Returns this [BigInt] as an [int].
+  ///
+  /// If the number does not fit, clamps to the max (or min)
+  /// integer.
+  ///
+  /// Warning: the clamping behaves differently on dart2js, dev
+  /// compiler, and the VM, due to the differences in integer
+  /// precision.
   int toInt();
 
-  /**
-   * Returns this [BigInt] as a [double].
-   *
-   * If the number is not representable as a [double], an
-   * approximation is returned. For numerically large integers, the
-   * approximation may be infinite.
-   */
+  /// Returns this [BigInt] as a [double].
+  ///
+  /// If the number is not representable as a [double], an
+  /// approximation is returned. For numerically large integers, the
+  /// approximation may be infinite.
   double toDouble();
 
-  /**
-   * Returns a String-representation of this integer.
-   *
-   * The returned string is parsable by [parse].
-   * For any `BigInt` `i`, it is guaranteed that
-   * `i == BigInt.parse(i.toString())`.
-   */
+  /// Returns a String-representation of this integer.
+  ///
+  /// The returned string is parsable by [parse].
+  /// For any `BigInt` `i`, it is guaranteed that
+  /// `i == BigInt.parse(i.toString())`.
   String toString();
 
-  /**
-   * Converts [this] to a string representation in the given [radix].
-   *
-   * In the string representation, lower-case letters are used for digits above
-   * '9', with 'a' being 10 an 'z' being 35.
-   *
-   * The [radix] argument must be an integer in the range 2 to 36.
-   */
+  /// Converts [this] to a string representation in the given [radix].
+  ///
+  /// In the string representation, lower-case letters are used for digits above
+  /// '9', with 'a' being 10 an 'z' being 35.
+  ///
+  /// The [radix] argument must be an integer in the range 2 to 36.
   String toRadixString(int radix);
 }
diff --git a/sdk/lib/core/bool.dart b/sdk/lib/core/bool.dart
index 3d35d80..f365d79 100644
--- a/sdk/lib/core/bool.dart
+++ b/sdk/lib/core/bool.dart
@@ -4,42 +4,38 @@
 
 part of dart.core;
 
-/**
- * The reserved words `true` and `false` denote objects that are the only two
- * instances of this class.
- *
- * It is a compile-time error for a class to attempt to extend or implement
- * bool.
- */
+/// The reserved words `true` and `false` denote objects that are the only two
+/// instances of this class.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// bool.
 @pragma("vm:entry-point")
 class bool {
-  /**
-   * Returns the boolean value of the environment declaration [name].
-   *
-   * The boolean value of the declaration is `true` if the declared value is
-   * the string `"true"`, and `false` if the value is `"false"`.
-   *
-   * In all other cases, including when there is no declaration for `name`,
-   * the result is the [defaultValue].
-   *
-   * The result is the same as would be returned by:
-   * ```dart
-   * (const String.fromEnvironment(name) == "true")
-   *     ? true
-   *     : (const String.fromEnvironment(name) == "false")
-   *         ? false
-   *         : defaultValue
-   * ```
-   * Example:
-   * ```dart
-   * const loggingFlag = const bool.fromEnvironment("logging");
-   * ```
-   * If you want to use a different truth-string than `"true"`, you can use the
-   * [String.fromEnvironment] constructor directly:
-   * ```dart
-   * const isLoggingOn = (const String.fromEnvironment("logging") == "on");
-   * ```
-   */
+  /// Returns the boolean value of the environment declaration [name].
+  ///
+  /// The boolean value of the declaration is `true` if the declared value is
+  /// the string `"true"`, and `false` if the value is `"false"`.
+  ///
+  /// In all other cases, including when there is no declaration for `name`,
+  /// the result is the [defaultValue].
+  ///
+  /// The result is the same as would be returned by:
+  /// ```dart
+  /// (const String.fromEnvironment(name) == "true")
+  ///     ? true
+  ///     : (const String.fromEnvironment(name) == "false")
+  ///         ? false
+  ///         : defaultValue
+  /// ```
+  /// Example:
+  /// ```dart
+  /// const loggingFlag = const bool.fromEnvironment("logging");
+  /// ```
+  /// If you want to use a different truth-string than `"true"`, you can use the
+  /// [String.fromEnvironment] constructor directly:
+  /// ```dart
+  /// const isLoggingOn = (const String.fromEnvironment("logging") == "on");
+  /// ```
   // The .fromEnvironment() constructors are special in that we do not want
   // users to call them using "new". We prohibit that by giving them bodies
   // that throw, even though const constructors are not allowed to have bodies.
@@ -60,11 +56,11 @@
   /// This constructor can be used to handle an absent declaration
   /// specifically, in ways that cannot be represented by providing
   /// a default value to the `C.fromEnvironment` constructor where `C`
-  /// is [String], [int], or [bool].
+  /// is one of [String], [int], or [bool].
   ///
   /// Example:
   /// ```dart
-  /// const loggingIsDeclared = const bool.hasEnvironment("logging");
+  /// const loggingIsDeclared = bool.hasEnvironment("logging");
   ///
   /// const String? logger = loggingIsDeclared
   ///     ? String.fromEnvironment("logging")
@@ -98,9 +94,7 @@
   @Since("2.1")
   bool operator ^(bool other) => !other == this;
 
-  /**
-   * Returns either `"true"` for `true` and `"false"` for `false`.
-   */
+  /// Returns either `"true"` for `true` and `"false"` for `false`.
   String toString() {
     return this ? "true" : "false";
   }
diff --git a/sdk/lib/core/comparable.dart b/sdk/lib/core/comparable.dart
index 835aa34..67df844 100644
--- a/sdk/lib/core/comparable.dart
+++ b/sdk/lib/core/comparable.dart
@@ -4,91 +4,86 @@
 
 part of dart.core;
 
-/**
- * The signature of a generic comparison function.
- *
- * A comparison function represents an ordering on a type of objects.
- * A total ordering on a type means that for two values, either they
- * are equal or one is greater than the other (and the latter must then be
- * smaller than the former).
- *
- * A [Comparator] function represents such a total ordering by returning
- *
- * * a negative integer if [a] is smaller than [b],
- * * zero if [a] is equal to [b], and
- * * a positive integer if [a] is greater than [b].
- */
+/// The signature of a generic comparison function.
+///
+/// A comparison function represents an ordering on a type of objects.
+/// A total ordering on a type means that for two values, either they
+/// are equal or one is greater than the other (and the latter must then be
+/// smaller than the former).
+///
+/// A [Comparator] function represents such a total ordering by returning
+///
+/// * a negative integer if [a] is smaller than [b],
+/// * zero if [a] is equal to [b], and
+/// * a positive integer if [a] is greater than [b].
 typedef Comparator<T> = int Function(T a, T b);
 
-/**
- * Interface used by types that have an intrinsic ordering.
- *
- * The [compareTo] operation defines a total ordering of objects,
- * which can be used for ordering and sorting.
- *
- * The [Comparable] interface should be used for the natural ordering of a type.
- * If a type can be ordered in more than one way,
- * and none of them is the obvious natural ordering,
- * then it might be better not to use the [Comparable] interface,
- * and to provide separate [Comparator]s instead.
- *
- * It is recommended that the order of a [Comparable] agrees
- * with its operator [operator ==] equality (`a.compareTo(b) == 0` iff `a == b`),
- * but this is not a requirement.
- * For example, [double] and [DateTime] have `compareTo` methods
- * that do not agree with operator [operator ==].
- * For doubles the [compareTo] method is more precise than the equality,
- * and for [DateTime] it is less precise.
- *
- * Examples:
- *
- *      (0.0).compareTo(-0.0);  // => 1
- *      0.0 == -0.0;            // => true
- *      var dt = new DateTime.now();
- *      var dt2 = dt.toUtc();
- *      dt == dt2;              // => false
- *      dt.compareTo(dt2);      // => 0
- *
- * The [Comparable] interface does not imply the existence
- * of the comparison operators `<`, `<=`, `>` and `>=`.
- * These should only be defined
- * if the ordering is a less-than/greater-than ordering,
- * that is, an ordering where you would naturally
- * use the words "less than" about the order of two elements.
- *
- * If the equality operator and [compareTo] disagree,
- * the comparison operators should follow the equality operator,
- * and will likely also disagree with [compareTo].
- * Otherwise they should match the [compareTo] method,
- * so that `a < b` iff `a.compareTo(b) < 0`.
- *
- * The [double] class defines comparison operators
- * that are compatible with equality.
- * The operators differ from `double.compareTo` on -0.0 and NaN.
- *
- * The [DateTime] class has no comparison operators, instead it has the more
- * precisely named [DateTime.isBefore] and [DateTime.isAfter].
- */
+/// Interface used by types that have an intrinsic ordering.
+///
+/// The [compareTo] operation defines a total ordering of objects,
+/// which can be used for ordering and sorting.
+///
+/// The [Comparable] interface should be used for the natural ordering of a type.
+/// If a type can be ordered in more than one way,
+/// and none of them is the obvious natural ordering,
+/// then it might be better not to use the [Comparable] interface,
+/// and to provide separate [Comparator]s instead.
+///
+/// It is recommended that the order of a [Comparable] agrees
+/// with its operator [operator ==] equality (`a.compareTo(b) == 0` iff `a == b`),
+/// but this is not a requirement.
+/// For example, [double] and [DateTime] have `compareTo` methods
+/// that do not agree with operator [operator ==].
+/// For doubles the [compareTo] method is more precise than the equality,
+/// and for [DateTime] it is less precise.
+///
+/// Examples:
+/// ```dart
+/// (0.0).compareTo(-0.0);   // => 1
+/// 0.0 == -0.0;             // => true
+/// var now = DateTime.now();
+/// var utcNow = now.toUtc();
+/// now == utcNow;           // => false
+/// now.compareTo(utcNow);   // => 0
+/// ```
+/// The [Comparable] interface does not imply the existence
+/// of the comparison operators `<`, `<=`, `>` and `>=`.
+/// These should only be defined
+/// if the ordering is a less-than/greater-than ordering,
+/// that is, an ordering where you would naturally
+/// use the words "less than" about the order of two elements.
+///
+/// If the equality operator and [compareTo] disagree,
+/// the comparison operators should follow the equality operator,
+/// and will likely also disagree with [compareTo].
+/// Otherwise they should match the [compareTo] method,
+/// so that `a < b` iff `a.compareTo(b) < 0`.
+///
+/// The [double] class defines comparison operators
+/// that are compatible with equality.
+/// The operators differ from [double.compareTo] on -0.0 and NaN.
+///
+/// The [DateTime] class has no comparison operators, instead it has the more
+/// precisely named [DateTime.isBefore] and [DateTime.isAfter], which both
+/// agree with [DateTime.compareTo].
 abstract class Comparable<T> {
-  /**
-   * Compares this object to another [Comparable]
-   *
-   * Returns a value like a [Comparator] when comparing `this` to [other].
-   * That is, it returns a negative integer if `this` is ordered before [other],
-   * a positive integer if `this` is ordered after [other],
-   * and zero if `this` and [other] are ordered together.
-   *
-   * The [other] argument must be a value that is comparable to this object.
-   */
+  /// Compares this object to another object.
+  ///
+  /// Returns a value like a [Comparator] when comparing `this` to [other].
+  /// That is, it returns a negative integer if `this` is ordered before [other],
+  /// a positive integer if `this` is ordered after [other],
+  /// and zero if `this` and [other] are ordered together.
+  ///
+  /// The [other] argument must be a value that is comparable to this object.
   int compareTo(T other);
 
-  /**
-   * A [Comparator] that compares one comparable to another.
-   *
-   * It returns the result of `a.compareTo(b)`.
-   *
-   * This utility function is used as the default comparator
-   * for ordering collections, for example in the [List] sort function.
-   */
+  /// A [Comparator] that compares one comparable to another.
+  ///
+  /// It returns the result of `a.compareTo(b)`.
+  /// The call may fail at run-time
+  /// if `a` is not comparable to the type of `b`.
+  ///
+  /// This utility function is used as the default comparator
+  /// for ordering collections, for example in the [List] sort function.
   static int compare(Comparable a, Comparable b) => a.compareTo(b);
 }
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index 8997c0a..7e96d5c 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.dart
@@ -2,155 +2,153 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- *
- * Built-in types, collections,
- * and other core functionality for every Dart program.
- *
- * This library is automatically imported.
- *
- * Some classes in this library,
- * such as [String] and [num],
- * support Dart's built-in data types.
- * Other classes, such as [List] and [Map], provide data structures
- * for managing collections of objects.
- * And still other classes represent commonly used types of data
- * such as URIs, dates and times, and errors.
- *
- * ## Numbers and booleans
- *
- * [int] and [double] provide support for Dart's built-in numerical data types:
- * integers and double-precision floating point numbers, respectively.
- * An object of type [bool] is either true or false.
- * Variables of these types can be constructed from literals:
- *
- *     int meaningOfLife = 42;
- *     double valueOfPi  = 3.141592;
- *     bool visible      = true;
- *
- * ## Strings and regular expressions
- *
- * A [String] is immutable and represents a sequence of characters.
- *
- *     String shakespeareQuote = "All the world's a stage, ...";
- *
- * [StringBuffer] provides a way to construct strings efficiently.
- *
- *     StringBuffer moreShakespeare = new StringBuffer();
- *     moreShakespeare.write('And all the men and women ');
- *     moreShakespeare.write('merely players; ...');
- *
- * The String and StringBuffer classes implement string concatenation,
- * interpolation, and other string manipulation features.
- *
- *     String philosophy = 'Live on ';
- *     String get palindrome => philosophy + philosophy.split('').reversed.join();
- *
- * [RegExp] implements Dart regular expressions,
- * which provide a grammar for matching patterns within text.
- * For example, here's a regular expression that matches
- * a string of one or more digits:
- *
- *     var numbers = new RegExp(r'\d+');
- *
- * Dart regular expressions have the same syntax and semantics as
- * JavaScript regular expressions. See
- * <http://ecma-international.org/ecma-262/5.1/#sec-15.10>
- * for the specification of JavaScript regular expressions.
- *
- * ## Collections
- *
- * The dart:core library provides basic collections,
- * such as [List], [Map], and [Set].
- *
- * A List is an ordered collection of objects, with a length.
- * Lists are sometimes called arrays.
- * Use a List when you need to access objects by index.
- *
- *     List superheroes = [ 'Batman', 'Superman', 'Harry Potter' ];
- *
- * A Set is an unordered collection of unique objects.
- * You cannot get an item by index (position).
- * Adding a duplicate item has no effect.
- *
- *     Set villains = new Set();
- *     villains.add('Joker');
- *     villains.addAll( ['Lex Luther', 'Voldemort'] );
- *
- * A Map is an unordered collection of key-value pairs.
- * Maps are sometimes called associative arrays because
- * maps associate a key to some value for easy retrieval.
- * Keys are unique.
- * Use a Map when you need to access objects
- * by a unique identifier.
- *
- *     Map sidekicks = { 'Batman': 'Robin',
- *                       'Superman': 'Lois Lane',
- *                       'Harry Potter': 'Ron and Hermione' };
- *
- * In addition to these classes,
- * dart:core contains [Iterable],
- * an interface that defines functionality
- * common in collections of objects.
- * Examples include the ability
- * to run a function on each element in the collection,
- * to apply a test to each element,
- * to retrieve an object, and to determine length.
- *
- * Iterable is implemented by List and Set,
- * and used by Map for its keys and values.
- *
- * For other kinds of collections, check out the
- * `dart:collection` library.
- *
- * ## Date and time
- *
- * Use [DateTime] to represent a point in time
- * and [Duration] to represent a span of time.
- *
- * You can create DateTime objects with constructors
- * or by parsing a correctly formatted string.
- *
- *     DateTime now = new DateTime.now();
- *     DateTime berlinWallFell = new DateTime(1989, 11, 9);
- *     DateTime moonLanding = DateTime.parse("1969-07-20");
- *
- * Create a Duration object specifying the individual time units.
- *
- *     Duration timeRemaining = new Duration(hours:56, minutes:14);
- *
- * In addition to DateTime and Duration,
- * dart:core contains the [Stopwatch] class for measuring elapsed time.
- *
- * ## Uri
- *
- * A [Uri] object represents a uniform resource identifier,
- * which identifies a resource on the web.
- *
- *     Uri dartlang = Uri.parse('http://dartlang.org/');
- *
- * ## Errors
- *
- * The [Error] class represents the occurrence of an error
- * during runtime.
- * Subclasses of this class represent specific kinds of errors.
- *
- * ## Other documentation
- *
- * For more information about how to use the built-in types, refer to
- * [Built-in Types](https://dart.dev/guides/language/language-tour#built-in-types)
- * in
- * [A tour of the Dart language](https://dart.dev/guides/language/language-tour).
- *
- * Also, see
- * [dart:core - numbers, collections, strings, and more](https://dart.dev/guides/libraries/library-tour#dartcore---numbers-collections-strings-and-more)
- * for more coverage of types in this library.
- *
- * The [Dart Language Specification](https://dart.dev/guides/language/spec)
- * provides technical details.
- *
- * {@category Core}
- */
+///
+/// Built-in types, collections,
+/// and other core functionality for every Dart program.
+///
+/// This library is automatically imported.
+///
+/// Some classes in this library,
+/// such as [String] and [num],
+/// support Dart's built-in data types.
+/// Other classes, such as [List] and [Map], provide data structures
+/// for managing collections of objects.
+/// And still other classes represent commonly used types of data
+/// such as URIs, dates and times, and errors.
+///
+/// ## Numbers and booleans
+///
+/// [int] and [double] provide support for Dart's built-in numerical data types:
+/// integers and double-precision floating point numbers, respectively.
+/// An object of type [bool] is either true or false.
+/// Variables of these types can be constructed from literals:
+/// ```dart
+/// int meaningOfLife = 42;
+/// double valueOfPi  = 3.141592;
+/// bool visible      = true;
+/// ```
+/// ## Strings and regular expressions
+///
+/// A [String] is immutable and represents a sequence of characters.
+/// ```dart
+/// String shakespeareQuote = "All the world's a stage, ...";
+/// ```
+/// [StringBuffer] provides a way to construct strings efficiently.
+/// ```dart
+/// var moreShakespeare = StringBuffer();
+/// moreShakespeare.write('And all the men and women ');
+/// moreShakespeare.write('merely players; ...');
+/// ```
+/// The [String] and [StringBuffer] classes implement string splitting,
+/// concatenation, and other string manipulation features.
+/// ```dart
+/// bool isPalindrome(String text) => text == text.split('').reversed.join();
+/// ```
+/// [RegExp] implements Dart regular expressions,
+/// which provide a grammar for matching patterns within text.
+/// For example, here's a regular expression that matches
+/// a substring containing one or more digits:
+/// ```dart
+/// var numbers = RegExp(r'\d+');
+/// ```
+/// Dart regular expressions have the same syntax and semantics as
+/// JavaScript regular expressions. See
+/// <http://ecma-international.org/ecma-262/5.1/#sec-15.10>
+/// for the specification of JavaScript regular expressions.
+///
+/// ## Collections
+///
+/// The `dart:core` library provides basic collections,
+/// such as [List], [Map], and [Set].
+///
+/// A [List] is an ordered collection of objects, with a length.
+/// Lists are sometimes called arrays.
+/// Use a [List] when you need to access objects by index.
+/// ```dart
+/// var superheroes = ['Batman', 'Superman', 'Harry Potter'];
+/// ```
+/// A [Set] is an unordered collection of unique objects.
+/// You cannot get an item efficiently by index (position).
+/// Adding an element which is already in the set, has no effect.
+/// ```dart
+/// var villains = {'Joker'};
+/// print(villains.length); // 1
+/// villains.addAll(['Joker', 'Lex Luthor', 'Voldemort']);
+/// print(villains.length); // 3
+/// ```
+/// A [Map] is an unordered collection of key-value pairs,
+/// where each key can only occur once.
+/// Maps are sometimes called associative arrays because
+/// maps associate a key to some value for easy retrieval.
+/// Use a [Map] when you need to access objects
+/// by a unique identifier.
+/// ```dart
+/// var sidekicks = {'Batman': 'Robin',
+///                  'Superman': 'Lois Lane',
+///                  'Harry Potter': 'Ron and Hermione'};
+/// ```
+/// In addition to these classes,
+/// `dart:core` contains [Iterable],
+/// an interface that defines functionality
+/// common in collections of objects.
+/// Examples include the ability
+/// to run a function on each element in the collection,
+/// to apply a test to each element,
+/// to retrieve an object, and to determine the number of elements.
+///
+/// [Iterable] is implemented by [List] and [Set],
+/// and used by [Map] for its keys and values.
+///
+/// For other kinds of collections, check out the
+/// `dart:collection` library.
+///
+/// ## Date and time
+///
+/// Use [DateTime] to represent a point in time
+/// and [Duration] to represent a span of time.
+///
+/// You can create [DateTime] objects with constructors
+/// or by parsing a correctly formatted string.
+/// ```dart
+/// var now = DateTime.now();
+/// var berlinWallFell = DateTime(1989, 11, 9);
+/// var moonLanding = DateTime.parse("1969-07-20");
+/// ```
+/// Create a [Duration] object by specifying the individual time units.
+/// ```dart
+/// var timeRemaining = const Duration(hours: 56, minutes: 14);
+/// ```
+/// In addition to [DateTime] and [Duration],
+/// `dart:core` contains the [Stopwatch] class for measuring elapsed time.
+///
+/// ## Uri
+///
+/// A [Uri] object represents a uniform resource identifier,
+/// which identifies a resource, for example on the web.
+/// ```dart
+/// var dartlang = Uri.parse('http://dartlang.org/');
+/// ```
+/// ## Errors
+///
+/// The [Error] class represents the occurrence of an error
+/// during runtime.
+/// Subclasses of this class represent specific kinds of errors.
+///
+/// ## Other documentation
+///
+/// For more information about how to use the built-in types, refer to
+/// [Built-in Types](https://dart.dev/guides/language/language-tour#built-in-types)
+/// in
+/// [A tour of the Dart language](https://dart.dev/guides/language/language-tour).
+///
+/// Also, see
+/// [dart:core - numbers, collections, strings, and more](https://dart.dev/guides/libraries/library-tour#dartcore---numbers-collections-strings-and-more)
+/// for more coverage of types in this library.
+///
+/// The [Dart Language Specification](https://dart.dev/guides/language/spec)
+/// provides technical details.
+///
+/// {@category Core}
 library dart.core;
 
 import "dart:collection";
@@ -170,6 +168,8 @@
 
 @Since("2.1")
 export "dart:async" show Future, Stream;
+@Since("2.12")
+export "dart:async" show FutureExtensions;
 
 part "annotations.dart";
 part "bigint.dart";
diff --git a/sdk/lib/core/date_time.dart b/sdk/lib/core/date_time.dart
index e8c9dcb..2891f8b 100644
--- a/sdk/lib/core/date_time.dart
+++ b/sdk/lib/core/date_time.dart
@@ -4,122 +4,120 @@
 
 part of dart.core;
 
-/**
- * An instant in time, such as July 20, 1969, 8:18pm GMT.
- *
- * DateTimes can represent time values that are at a distance of at most
- * 100,000,000 days from epoch (1970-01-01 UTC): -271821-04-20 to 275760-09-13.
- *
- * Create a DateTime object by using one of the constructors
- * or by parsing a correctly formatted string,
- * which complies with a subset of ISO 8601.
- * Note that hours are specified between 0 and 23,
- * as in a 24-hour clock.
- * For example:
- *
- * ```
- * var now = new DateTime.now();
- * var berlinWallFell = new DateTime.utc(1989, 11, 9);
- * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");  // 8:18pm
- * ```
- *
- * A DateTime object is anchored either in the UTC time zone
- * or in the local time zone of the current computer
- * when the object is created.
- *
- * Once created, neither the value nor the time zone
- * of a DateTime object may be changed.
- *
- * You can use properties to get
- * the individual units of a DateTime object.
- *
- * ```
- * assert(berlinWallFell.month == 11);
- * assert(moonLanding.hour == 20);
- * ```
- *
- * For convenience and readability,
- * the DateTime class provides a constant for each day and month
- * name - for example, [august] and [friday].
- * You can use these constants to improve code readability:
- *
- * ```
- * var berlinWallFell = new DateTime.utc(1989, DateTime.november, 9);
- * assert(berlinWallFell.weekday == DateTime.thursday);
- * ```
- *
- * Day and month values begin at 1, and the week starts on Monday.
- * That is, the constants [january] and [monday] are both 1.
- *
- * ## Working with UTC and local time
- *
- * A DateTime object is in the local time zone
- * unless explicitly created in the UTC time zone.
- *
- * ```
- * var dDay = new DateTime.utc(1944, 6, 6);
- * ```
- *
- * Use [isUtc] to determine whether a DateTime object is based in UTC.
- * Use the methods [toLocal] and [toUtc]
- * to get the equivalent date/time value specified in the other time zone.
- * Use [timeZoneName] to get an abbreviated name of the time zone
- * for the DateTime object.
- * To find the difference
- * between UTC and the time zone of a DateTime object
- * call [timeZoneOffset].
- *
- * ## Comparing DateTime objects
- *
- * The DateTime class contains several handy methods,
- * such as [isAfter], [isBefore], and [isAtSameMomentAs],
- * for comparing DateTime objects.
- *
- * ```
- * assert(berlinWallFell.isAfter(moonLanding) == true);
- * assert(berlinWallFell.isBefore(moonLanding) == false);
- * ```
- *
- * ## Using DateTime with Duration
- *
- * Use the [add] and [subtract] methods with a [Duration] object
- * to create a new DateTime object based on another.
- * For example, to find the date that is sixty days (24 * 60 hours) after today,
- * write:
- *
- * ```
- * var now = new DateTime.now();
- * var sixtyDaysFromNow = now.add(new Duration(days: 60));
- * ```
- *
- * To find out how much time is between two DateTime objects use
- * [difference], which returns a [Duration] object:
- *
- * ```
- * var difference = berlinWallFell.difference(moonLanding);
- * assert(difference.inDays == 7416);
- * ```
- *
- * The difference between two dates in different time zones
- * is just the number of nanoseconds between the two points in time.
- * It doesn't take calendar days into account.
- * That means that the difference between two midnights in local time may be
- * less than 24 hours times the number of days between them,
- * if there is a daylight saving change in between.
- * If the difference above is calculated using Australian local time, the
- * difference is 7415 days and 23 hours, which is only 7415 whole days as
- * reported by `inDays`.
- *
- * ## Other resources
- *
- * See [Duration] to represent a span of time.
- * See [Stopwatch] to measure timespans.
- *
- * The DateTime class does not provide internationalization.
- * To internationalize your code, use
- * the [intl](https://pub.dev/packages/intl) package.
- *
- */
+/// An instant in time, such as July 20, 1969, 8:18pm GMT.
+///
+/// DateTimes can represent time values that are at a distance of at most
+/// 100,000,000 days from epoch (1970-01-01 UTC): -271821-04-20 to 275760-09-13.
+///
+/// Create a DateTime object by using one of the constructors
+/// or by parsing a correctly formatted string,
+/// which complies with a subset of ISO 8601.
+/// Note that hours are specified between 0 and 23,
+/// as in a 24-hour clock.
+/// For example:
+///
+/// ```
+/// var now = DateTime.now();
+/// var berlinWallFell = DateTime.utc(1989, 11, 9);
+/// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");  // 8:18pm
+/// ```
+///
+/// A DateTime object is anchored either in the UTC time zone
+/// or in the local time zone of the current computer
+/// when the object is created.
+///
+/// Once created, neither the value nor the time zone
+/// of a DateTime object may be changed.
+///
+/// You can use properties to get
+/// the individual units of a DateTime object.
+///
+/// ```
+/// assert(berlinWallFell.month == 11);
+/// assert(moonLanding.hour == 20);
+/// ```
+///
+/// For convenience and readability,
+/// the DateTime class provides a constant for each day and month
+/// name - for example, [august] and [friday].
+/// You can use these constants to improve code readability:
+///
+/// ```
+/// var berlinWallFell = DateTime.utc(1989, DateTime.november, 9);
+/// assert(berlinWallFell.weekday == DateTime.thursday);
+/// ```
+///
+/// Day and month values begin at 1, and the week starts on Monday.
+/// That is, the constants [january] and [monday] are both 1.
+///
+/// ## Working with UTC and local time
+///
+/// A DateTime object is in the local time zone
+/// unless explicitly created in the UTC time zone.
+///
+/// ```
+/// var dDay = DateTime.utc(1944, 6, 6);
+/// ```
+///
+/// Use [isUtc] to determine whether a DateTime object is based in UTC.
+/// Use the methods [toLocal] and [toUtc]
+/// to get the equivalent date/time value specified in the other time zone.
+/// Use [timeZoneName] to get an abbreviated name of the time zone
+/// for the DateTime object.
+/// To find the difference
+/// between UTC and the time zone of a DateTime object
+/// call [timeZoneOffset].
+///
+/// ## Comparing DateTime objects
+///
+/// The DateTime class contains several handy methods,
+/// such as [isAfter], [isBefore], and [isAtSameMomentAs],
+/// for comparing DateTime objects.
+///
+/// ```
+/// assert(berlinWallFell.isAfter(moonLanding) == true);
+/// assert(berlinWallFell.isBefore(moonLanding) == false);
+/// ```
+///
+/// ## Using DateTime with Duration
+///
+/// Use the [add] and [subtract] methods with a [Duration] object
+/// to create a DateTime object based on another.
+/// For example, to find the date that is sixty days (24 * 60 hours) after today,
+/// write:
+///
+/// ```
+/// var now = DateTime.now();
+/// var sixtyDaysFromNow = now.add(const Duration(days: 60));
+/// ```
+///
+/// To find out how much time is between two DateTime objects use
+/// [difference], which returns a [Duration] object:
+///
+/// ```
+/// var difference = berlinWallFell.difference(moonLanding);
+/// assert(difference.inDays == 7416);
+/// ```
+///
+/// The difference between two dates in different time zones
+/// is just the number of nanoseconds between the two points in time.
+/// It doesn't take calendar days into account.
+/// That means that the difference between two midnights in local time may be
+/// less than 24 hours times the number of days between them,
+/// if there is a daylight saving change in between.
+/// If the difference above is calculated using Australian local time, the
+/// difference is 7415 days and 23 hours, which is only 7415 whole days as
+/// reported by `inDays`.
+///
+/// ## Other resources
+///
+/// See [Duration] to represent a span of time.
+/// See [Stopwatch] to measure timespans.
+///
+/// The DateTime class does not provide internationalization.
+/// To internationalize your code, use
+/// the [intl](https://pub.dev/packages/intl) package.
+///
 class DateTime implements Comparable<DateTime> {
   // Weekday constants that are returned by [weekday] method:
   static const int monday = 1;
@@ -146,37 +144,31 @@
   static const int december = 12;
   static const int monthsPerYear = 12;
 
-  /**
-   * The value of this DateTime.
-   *
-   * The content of this field is implementation dependent. On JavaScript it is
-   * equal to [millisecondsSinceEpoch]. On the VM it is equal to
-   * [microsecondsSinceEpoch].
-   */
+  /// The value of this DateTime.
+  ///
+  /// The content of this field is implementation dependent. On JavaScript it is
+  /// equal to [millisecondsSinceEpoch]. On the VM it is equal to
+  /// [microsecondsSinceEpoch].
   final int _value;
 
-  /**
-   * True if this [DateTime] is set to UTC time.
-   *
-   * ```
-   * var dDay = new DateTime.utc(1944, 6, 6);
-   * assert(dDay.isUtc);
-   * ```
-   *
-   */
+  /// True if this [DateTime] is set to UTC time.
+  ///
+  /// ```
+  /// var dDay = DateTime.utc(1944, 6, 6);
+  /// assert(dDay.isUtc);
+  /// ```
+  ///
   final bool isUtc;
 
-  /**
-   * Constructs a [DateTime] instance specified in the local time zone.
-   *
-   * For example,
-   * to create a new DateTime object representing the 7th of September 2017,
-   * 5:30pm
-   *
-   * ```
-   * var dentistAppointment = new DateTime(2017, 9, 7, 17, 30);
-   * ```
-   */
+  /// Constructs a [DateTime] instance specified in the local time zone.
+  ///
+  /// For example,
+  /// to create a DateTime object representing the 7th of September 2017,
+  /// 5:30pm
+  ///
+  /// ```
+  /// var dentistAppointment = DateTime(2017, 9, 7, 17, 30);
+  /// ```
   DateTime(int year,
       [int month = 1,
       int day = 1,
@@ -188,17 +180,15 @@
       : this._internal(year, month, day, hour, minute, second, millisecond,
             microsecond, false);
 
-  /**
-   * Constructs a [DateTime] instance specified in the UTC time zone.
-   *
-   * ```
-   * var moonLanding = new DateTime.utc(1969, 7, 20, 20, 18, 04);
-   * ```
-   *
-   * When dealing with dates or historic events prefer to use UTC DateTimes,
-   * since they are unaffected by daylight-saving changes and are unaffected
-   * by the local timezone.
-   */
+  /// Constructs a [DateTime] instance specified in the UTC time zone.
+  ///
+  /// ```
+  /// var moonLanding = DateTime.utc(1969, 7, 20, 20, 18, 04);
+  /// ```
+  ///
+  /// When dealing with dates or historic events prefer to use UTC DateTimes,
+  /// since they are unaffected by daylight-saving changes and are unaffected
+  /// by the local timezone.
   DateTime.utc(int year,
       [int month = 1,
       int day = 1,
@@ -210,70 +200,65 @@
       : this._internal(year, month, day, hour, minute, second, millisecond,
             microsecond, true);
 
-  /**
-   * Constructs a [DateTime] instance with current date and time in the
-   * local time zone.
-   *
-   * ```
-   * var thisInstant = new DateTime.now();
-   * ```
-   */
+  /// Constructs a [DateTime] instance with current date and time in the
+  /// local time zone.
+  ///
+  /// ```
+  /// var thisInstant = DateTime.now();
+  /// ```
   DateTime.now() : this._now();
 
-  /**
-   * Constructs a new [DateTime] instance based on [formattedString].
-   *
-   * The [formattedString] must not be `null`.
-   * Throws a [FormatException] if the input string cannot be parsed.
-   *
-   * The function parses a subset of ISO 8601
-   * which includes the subset accepted by RFC 3339.
-   *
-   * The accepted inputs are currently:
-   *
-   * * A date: A signed four-to-six digit year, two digit month and
-   *   two digit day, optionally separated by `-` characters.
-   *   Examples: "19700101", "-0004-12-24", "81030-04-01".
-   * * An optional time part, separated from the date by either `T` or a space.
-   *   The time part is a two digit hour,
-   *   then optionally a two digit minutes value,
-   *   then optionally a two digit seconds value, and
-   *   then optionally a '.' or ',' followed by at least a one digit
-   *   second fraction.
-   *   The minutes and seconds may be separated from the previous parts by a
-   *   ':'.
-   *   Examples: "12", "12:30:24.124", "12:30:24,124", "123010.50".
-   * * An optional time-zone offset part,
-   *   possibly separated from the previous by a space.
-   *   The time zone is either 'z' or 'Z', or it is a signed two digit hour
-   *   part and an optional two digit minute part. The sign must be either
-   *   "+" or "-", and can not be omitted.
-   *   The minutes may be separated from the hours by a ':'.
-   *   Examples: "Z", "-10", "+01:30", "+1130".
-   *
-   * This includes the output of both [toString] and [toIso8601String], which
-   * will be parsed back into a `DateTime` object with the same time as the
-   * original.
-   *
-   * The result is always in either local time or UTC.
-   * If a time zone offset other than UTC is specified,
-   * the time is converted to the equivalent UTC time.
-   *
-   * Examples of accepted strings:
-   *
-   * * `"2012-02-27"`
-   * * `"2012-02-27 13:27:00"`
-   * * `"2012-02-27 13:27:00.123456789z"`
-   * * `"2012-02-27 13:27:00,123456789z"`
-   * * `"20120227 13:27:00"`
-   * * `"20120227T132700"`
-   * * `"20120227"`
-   * * `"+20120227"`
-   * * `"2012-02-27T14Z"`
-   * * `"2012-02-27T14+00:00"`
-   * * `"-123450101 00:00:00 Z"`: in the year -12345.
-   * * `"2002-02-27T14:00:00-0500"`: Same as `"2002-02-27T19:00:00Z"`
-   */
+  /// Constructs a new [DateTime] instance based on [formattedString].
+  ///
+  /// Throws a [FormatException] if the input string cannot be parsed.
+  ///
+  /// The function parses a subset of ISO 8601
+  /// which includes the subset accepted by RFC 3339.
+  ///
+  /// The accepted inputs are currently:
+  ///
+  /// * A date: A signed four-to-six digit year, two digit month and
+  ///   two digit day, optionally separated by `-` characters.
+  ///   Examples: "19700101", "-0004-12-24", "81030-04-01".
+  /// * An optional time part, separated from the date by either `T` or a space.
+  ///   The time part is a two digit hour,
+  ///   then optionally a two digit minutes value,
+  ///   then optionally a two digit seconds value, and
+  ///   then optionally a '.' or ',' followed by at least a one digit
+  ///   second fraction.
+  ///   The minutes and seconds may be separated from the previous parts by a
+  ///   ':'.
+  ///   Examples: "12", "12:30:24.124", "12:30:24,124", "123010.50".
+  /// * An optional time-zone offset part,
+  ///   possibly separated from the previous by a space.
+  ///   The time zone is either 'z' or 'Z', or it is a signed two digit hour
+  ///   part and an optional two digit minute part. The sign must be either
+  ///   "+" or "-", and can not be omitted.
+  ///   The minutes may be separated from the hours by a ':'.
+  ///   Examples: "Z", "-10", "+01:30", "+1130".
+  ///
+  /// This includes the output of both [toString] and [toIso8601String], which
+  /// will be parsed back into a `DateTime` object with the same time as the
+  /// original.
+  ///
+  /// The result is always in either local time or UTC.
+  /// If a time zone offset other than UTC is specified,
+  /// the time is converted to the equivalent UTC time.
+  ///
+  /// Examples of accepted strings:
+  ///
+  /// * `"2012-02-27"`
+  /// * `"2012-02-27 13:27:00"`
+  /// * `"2012-02-27 13:27:00.123456789z"`
+  /// * `"2012-02-27 13:27:00,123456789z"`
+  /// * `"20120227 13:27:00"`
+  /// * `"20120227T132700"`
+  /// * `"20120227"`
+  /// * `"+20120227"`
+  /// * `"2012-02-27T14Z"`
+  /// * `"2012-02-27T14+00:00"`
+  /// * `"-123450101 00:00:00 Z"`: in the year -12345.
+  /// * `"2002-02-27T14:00:00-0500"`: Same as `"2002-02-27T19:00:00Z"`
   // TODO(lrn): restrict incorrect values like  2003-02-29T50:70:80.
   // Or not, that may be a breaking change.
   static DateTime parse(String formattedString) {
@@ -338,12 +323,10 @@
     }
   }
 
-  /**
-   * Constructs a new [DateTime] instance based on [formattedString].
-   *
-   * Works like [parse] except that this function returns `null`
-   * where [parse] would throw a [FormatException].
-   */
+  /// Constructs a new [DateTime] instance based on [formattedString].
+  ///
+  /// Works like [parse] except that this function returns `null`
+  /// where [parse] would throw a [FormatException].
   static DateTime? tryParse(String formattedString) {
     // TODO: Optimize to avoid throwing.
     try {
@@ -355,37 +338,31 @@
 
   static const int _maxMillisecondsSinceEpoch = 8640000000000000;
 
-  /**
-   * Constructs a new [DateTime] instance
-   * with the given [millisecondsSinceEpoch].
-   *
-   * If [isUtc] is false then the date is in the local time zone.
-   *
-   * The constructed [DateTime] represents
-   * 1970-01-01T00:00:00Z + [millisecondsSinceEpoch] ms in the given
-   * time zone (local or UTC).
-   */
+  /// Constructs a new [DateTime] instance
+  /// with the given [millisecondsSinceEpoch].
+  ///
+  /// If [isUtc] is false then the date is in the local time zone.
+  ///
+  /// The constructed [DateTime] represents
+  /// 1970-01-01T00:00:00Z + [millisecondsSinceEpoch] ms in the given
+  /// time zone (local or UTC).
   external DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
       {bool isUtc = false});
 
-  /**
-   * Constructs a new [DateTime] instance
-   * with the given [microsecondsSinceEpoch].
-   *
-   * If [isUtc] is false then the date is in the local time zone.
-   *
-   * The constructed [DateTime] represents
-   * 1970-01-01T00:00:00Z + [microsecondsSinceEpoch] us in the given
-   * time zone (local or UTC).
-   */
+  /// Constructs a new [DateTime] instance
+  /// with the given [microsecondsSinceEpoch].
+  ///
+  /// If [isUtc] is false then the date is in the local time zone.
+  ///
+  /// The constructed [DateTime] represents
+  /// 1970-01-01T00:00:00Z + [microsecondsSinceEpoch] us in the given
+  /// time zone (local or UTC).
   external DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
       {bool isUtc = false});
 
-  /**
-   * Constructs a new [DateTime] instance with the given value.
-   *
-   * If [isUtc] is false then the date is in the local time zone.
-   */
+  /// Constructs a new [DateTime] instance with the given value.
+  ///
+  /// If [isUtc] is false then the date is in the local time zone.
   DateTime._withValue(this._value, {required this.isUtc}) {
     if (millisecondsSinceEpoch.abs() > _maxMillisecondsSinceEpoch ||
         (millisecondsSinceEpoch.abs() == _maxMillisecondsSinceEpoch &&
@@ -397,112 +374,100 @@
     checkNotNullable(isUtc, "isUtc");
   }
 
-  /**
-   * Returns true if [other] is a [DateTime] at the same moment and in the
-   * same time zone (UTC or local).
-   *
-   * ```
-   * var dDayUtc = new DateTime.utc(1944, 6, 6);
-   * var dDayLocal = dDayUtc.toLocal();
-   *
-   * // These two dates are at the same moment, but are in different zones.
-   * assert(dDayUtc != dDayLocal);
-   * ```
-   *
-   * See [isAtSameMomentAs] for a comparison that compares moments in time
-   * independently of their zones.
-   */
+  /// Returns true if [other] is a [DateTime] at the same moment and in the
+  /// same time zone (UTC or local).
+  ///
+  /// ```
+  /// var dDayUtc = DateTime.utc(1944, 6, 6);
+  /// var dDayLocal = dDayUtc.toLocal();
+  ///
+  /// // These two dates are at the same moment, but are in different zones.
+  /// assert(dDayUtc != dDayLocal);
+  /// ```
+  ///
+  /// See [isAtSameMomentAs] for a comparison that compares moments in time
+  /// independently of their zones.
   external bool operator ==(Object other);
 
-  /**
-   * Returns true if [this] occurs before [other].
-   *
-   * The comparison is independent
-   * of whether the time is in UTC or in the local time zone.
-   *
-   * ```
-   * var now = new DateTime.now();
-   * var earlier = now.subtract(const Duration(seconds: 5));
-   * assert(earlier.isBefore(now));
-   * assert(!now.isBefore(now));
-   *
-   * // This relation stays the same, even when changing timezones.
-   * assert(earlier.isBefore(now.toUtc()));
-   * assert(earlier.toUtc().isBefore(now));
-   *
-   * assert(!now.toUtc().isBefore(now));
-   * assert(!now.isBefore(now.toUtc()));
-   * ```
-   */
+  /// Returns true if [this] occurs before [other].
+  ///
+  /// The comparison is independent
+  /// of whether the time is in UTC or in the local time zone.
+  ///
+  /// ```
+  /// var now = DateTime.now();
+  /// var earlier = now.subtract(const Duration(seconds: 5));
+  /// assert(earlier.isBefore(now));
+  /// assert(!now.isBefore(now));
+  ///
+  /// // This relation stays the same, even when changing timezones.
+  /// assert(earlier.isBefore(now.toUtc()));
+  /// assert(earlier.toUtc().isBefore(now));
+  ///
+  /// assert(!now.toUtc().isBefore(now));
+  /// assert(!now.isBefore(now.toUtc()));
+  /// ```
   external bool isBefore(DateTime other);
 
-  /**
-   * Returns true if [this] occurs after [other].
-   *
-   * The comparison is independent
-   * of whether the time is in UTC or in the local time zone.
-   *
-   * ```
-   * var now = new DateTime.now();
-   * var later = now.add(const Duration(seconds: 5));
-   * assert(later.isAfter(now));
-   * assert(!now.isBefore(now));
-   *
-   * // This relation stays the same, even when changing timezones.
-   * assert(later.isAfter(now.toUtc()));
-   * assert(later.toUtc().isAfter(now));
-   *
-   * assert(!now.toUtc().isBefore(now));
-   * assert(!now.isBefore(now.toUtc()));
-   * ```
-   */
+  /// Returns true if [this] occurs after [other].
+  ///
+  /// The comparison is independent
+  /// of whether the time is in UTC or in the local time zone.
+  ///
+  /// ```
+  /// var now = DateTime.now();
+  /// var later = now.add(const Duration(seconds: 5));
+  /// assert(later.isAfter(now));
+  /// assert(!now.isBefore(now));
+  ///
+  /// // This relation stays the same, even when changing timezones.
+  /// assert(later.isAfter(now.toUtc()));
+  /// assert(later.toUtc().isAfter(now));
+  ///
+  /// assert(!now.toUtc().isBefore(now));
+  /// assert(!now.isBefore(now.toUtc()));
+  /// ```
   external bool isAfter(DateTime other);
 
-  /**
-   * Returns true if [this] occurs at the same moment as [other].
-   *
-   * The comparison is independent of whether the time is in UTC or in the local
-   * time zone.
-   *
-   * ```
-   * var now = new DateTime.now();
-   * var later = now.add(const Duration(seconds: 5));
-   * assert(!later.isAtSameMomentAs(now));
-   * assert(now.isAtSameMomentAs(now));
-   *
-   * // This relation stays the same, even when changing timezones.
-   * assert(!later.isAtSameMomentAs(now.toUtc()));
-   * assert(!later.toUtc().isAtSameMomentAs(now));
-   *
-   * assert(now.toUtc().isAtSameMomentAs(now));
-   * assert(now.isAtSameMomentAs(now.toUtc()));
-   * ```
-   */
+  /// Returns true if [this] occurs at the same moment as [other].
+  ///
+  /// The comparison is independent of whether the time is in UTC or in the local
+  /// time zone.
+  ///
+  /// ```
+  /// var now = DateTime.now();
+  /// var later = now.add(const Duration(seconds: 5));
+  /// assert(!later.isAtSameMomentAs(now));
+  /// assert(now.isAtSameMomentAs(now));
+  ///
+  /// // This relation stays the same, even when changing timezones.
+  /// assert(!later.isAtSameMomentAs(now.toUtc()));
+  /// assert(!later.toUtc().isAtSameMomentAs(now));
+  ///
+  /// assert(now.toUtc().isAtSameMomentAs(now));
+  /// assert(now.isAtSameMomentAs(now.toUtc()));
+  /// ```
   external bool isAtSameMomentAs(DateTime other);
 
-  /**
-   * Compares this DateTime object to [other],
-   * returning zero if the values are equal.
-   *
-   * Returns a negative value if this DateTime [isBefore] [other]. It returns 0
-   * if it [isAtSameMomentAs] [other], and returns a positive value otherwise
-   * (when this [isAfter] [other]).
-   */
+  /// Compares this DateTime object to [other],
+  /// returning zero if the values are equal.
+  ///
+  /// Returns a negative value if this DateTime [isBefore] [other]. It returns 0
+  /// if it [isAtSameMomentAs] [other], and returns a positive value otherwise
+  /// (when this [isAfter] [other]).
   external int compareTo(DateTime other);
 
   int get hashCode => (_value ^ (_value >> 30)) & 0x3FFFFFFF;
 
-  /**
-   * Returns this DateTime value in the local time zone.
-   *
-   * Returns [this] if it is already in the local time zone.
-   * Otherwise this method is equivalent to:
-   *
-   * ```
-   * new DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch,
-   *                                         isUtc: false)
-   * ```
-   */
+  /// Returns this DateTime value in the local time zone.
+  ///
+  /// Returns [this] if it is already in the local time zone.
+  /// Otherwise this method is equivalent to:
+  ///
+  /// ```
+  /// DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch,
+  ///                                     isUtc: false)
+  /// ```
   DateTime toLocal() {
     if (isUtc) {
       return DateTime._withValue(_value, isUtc: false);
@@ -510,17 +475,15 @@
     return this;
   }
 
-  /**
-   * Returns this DateTime value in the UTC time zone.
-   *
-   * Returns [this] if it is already in UTC.
-   * Otherwise this method is equivalent to:
-   *
-   * ```
-   * new DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch,
-   *                                         isUtc: true)
-   * ```
-   */
+  /// Returns this DateTime value in the UTC time zone.
+  ///
+  /// Returns [this] if it is already in UTC.
+  /// Otherwise this method is equivalent to:
+  ///
+  /// ```
+  /// DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch,
+  ///                                     isUtc: true)
+  /// ```
   DateTime toUtc() {
     if (isUtc) return this;
     return DateTime._withValue(_value, isUtc: true);
@@ -554,17 +517,15 @@
     return "0${n}";
   }
 
-  /**
-   * Returns a human-readable string for this instance.
-   *
-   * The returned string is constructed for the time zone of this instance.
-   * The `toString()` method provides a simply formatted string.
-   * It does not support internationalized strings.
-   * Use the [intl](https://pub.dev/packages/intl) package
-   * at the pub shared packages repo.
-   *
-   * The resulting string can be parsed back using [parse].
-   */
+  /// Returns a human-readable string for this instance.
+  ///
+  /// The returned string is constructed for the time zone of this instance.
+  /// The `toString()` method provides a simply formatted string.
+  /// It does not support internationalized strings.
+  /// Use the [intl](https://pub.dev/packages/intl) package
+  /// at the pub shared packages repo.
+  ///
+  /// The resulting string can be parsed back using [parse].
   String toString() {
     String y = _fourDigits(year);
     String m = _twoDigits(month);
@@ -581,27 +542,25 @@
     }
   }
 
-  /**
-   * Returns an ISO-8601 full-precision extended format representation.
-   *
-   * The format is `yyyy-MM-ddTHH:mm:ss.mmmuuuZ` for UTC time, and
-   * `yyyy-MM-ddTHH:mm:ss.mmmuuu` (no trailing "Z") for local/non-UTC time,
-   * where:
-   *
-   * * `yyyy` is a, possibly negative, four digit representation of the year,
-   *   if the year is in the range -9999 to 9999,
-   *   otherwise it is a signed six digit representation of the year.
-   * * `MM` is the month in the range 01 to 12,
-   * * `dd` is the day of the month in the range 01 to 31,
-   * * `HH` are hours in the range 00 to 23,
-   * * `mm` are minutes in the range 00 to 59,
-   * * `ss` are seconds in the range 00 to 59 (no leap seconds),
-   * * `mmm` are milliseconds in the range 000 to 999, and
-   * * `uuu` are microseconds in the range 001 to 999. If [microsecond] equals
-   *   0, then this part is omitted.
-   *
-   * The resulting string can be parsed back using [parse].
-   */
+  /// Returns an ISO-8601 full-precision extended format representation.
+  ///
+  /// The format is `yyyy-MM-ddTHH:mm:ss.mmmuuuZ` for UTC time, and
+  /// `yyyy-MM-ddTHH:mm:ss.mmmuuu` (no trailing "Z") for local/non-UTC time,
+  /// where:
+  ///
+  /// * `yyyy` is a, possibly negative, four digit representation of the year,
+  ///   if the year is in the range -9999 to 9999,
+  ///   otherwise it is a signed six digit representation of the year.
+  /// * `MM` is the month in the range 01 to 12,
+  /// * `dd` is the day of the month in the range 01 to 31,
+  /// * `HH` are hours in the range 00 to 23,
+  /// * `mm` are minutes in the range 00 to 59,
+  /// * `ss` are seconds in the range 00 to 59 (no leap seconds),
+  /// * `mmm` are milliseconds in the range 000 to 999, and
+  /// * `uuu` are microseconds in the range 001 to 999. If [microsecond] equals
+  ///   0, then this part is omitted.
+  ///
+  /// The resulting string can be parsed back using [parse].
   String toIso8601String() {
     String y =
         (year >= -9999 && year <= 9999) ? _fourDigits(year) : _sixDigits(year);
@@ -619,72 +578,66 @@
     }
   }
 
-  /**
-   * Returns a new [DateTime] instance with [duration] added to [this].
-   *
-   * ```
-   * var today = new DateTime.now();
-   * var fiftyDaysFromNow = today.add(new Duration(days: 50));
-   * ```
-   *
-   * Notice that the duration being added is actually 50 * 24 * 60 * 60
-   * seconds. If the resulting `DateTime` has a different daylight saving offset
-   * than `this`, then the result won't have the same time-of-day as `this`, and
-   * may not even hit the calendar date 50 days later.
-   *
-   * Be careful when working with dates in local time.
-   */
+  /// Returns a new [DateTime] instance with [duration] added to [this].
+  ///
+  /// ```
+  /// var today = DateTime.now();
+  /// var fiftyDaysFromNow = today.add(const Duration(days: 50));
+  /// ```
+  ///
+  /// Notice that the duration being added is actually 50 * 24 * 60 * 60
+  /// seconds. If the resulting `DateTime` has a different daylight saving offset
+  /// than `this`, then the result won't have the same time-of-day as `this`, and
+  /// may not even hit the calendar date 50 days later.
+  ///
+  /// Be careful when working with dates in local time.
   external DateTime add(Duration duration);
 
-  /**
-   * Returns a new [DateTime] instance with [duration] subtracted from [this].
-   *
-   * ```
-   * DateTime today = new DateTime.now();
-   * DateTime fiftyDaysAgo = today.subtract(new Duration(days: 50));
-   * ```
-   *
-   * Notice that the duration being subtracted is actually 50 * 24 * 60 * 60
-   * seconds. If the resulting `DateTime` has a different daylight saving offset
-   * than `this`, then the result won't have the same time-of-day as `this`, and
-   * may not even hit the calendar date 50 days earlier.
-   *
-   * Be careful when working with dates in local time.
-   */
+  /// Returns a new [DateTime] instance with [duration] subtracted from [this].
+  ///
+  /// ```
+  /// DateTime today = DateTime.now();
+  /// DateTime fiftyDaysAgo = today.subtract(const Duration(days: 50));
+  /// ```
+  ///
+  /// Notice that the duration being subtracted is actually 50 * 24 * 60 * 60
+  /// seconds. If the resulting `DateTime` has a different daylight saving offset
+  /// than `this`, then the result won't have the same time-of-day as `this`, and
+  /// may not even hit the calendar date 50 days earlier.
+  ///
+  /// Be careful when working with dates in local time.
   external DateTime subtract(Duration duration);
 
-  /**
-   * Returns a [Duration] with the difference when subtracting [other] from
-   * [this].
-   *
-   * The returned [Duration] will be negative if [other] occurs after [this].
-   *
-   * ```
-   * var berlinWallFell = new DateTime.utc(1989, DateTime.november, 9);
-   * var dDay = new DateTime.utc(1944, DateTime.june, 6);
-   *
-   * Duration difference = berlinWallFell.difference(dDay);
-   * assert(difference.inDays == 16592);
-   * ```
-   *
-   * The difference is measured in seconds and fractions of seconds.
-   * The difference above counts the number of fractional seconds between
-   * midnight at the beginning of those dates.
-   * If the dates above had been in local time, not UTC, then the difference
-   * between two midnights may not be a multiple of 24 hours due to daylight
-   * saving differences.
-   *
-   * For example, in Australia, similar code using local time instead of UTC:
-   *
-   * ```
-   * var berlinWallFell = new DateTime(1989, DateTime.november, 9);
-   * var dDay = new DateTime(1944, DateTime.june, 6);
-   * Duration difference = berlinWallFell.difference(dDay);
-   * assert(difference.inDays == 16592);
-   * ```
-   * will fail because the difference is actually 16591 days and 23 hours, and
-   * [Duration.inDays] only returns the number of whole days.
-   */
+  /// Returns a [Duration] with the difference when subtracting [other] from
+  /// [this].
+  ///
+  /// The returned [Duration] will be negative if [other] occurs after [this].
+  ///
+  /// ```
+  /// var berlinWallFell = DateTime.utc(1989, DateTime.november, 9);
+  /// var dDay = DateTime.utc(1944, DateTime.june, 6);
+  ///
+  /// Duration difference = berlinWallFell.difference(dDay);
+  /// assert(difference.inDays == 16592);
+  /// ```
+  ///
+  /// The difference is measured in seconds and fractions of seconds.
+  /// The difference above counts the number of fractional seconds between
+  /// midnight at the beginning of those dates.
+  /// If the dates above had been in local time, not UTC, then the difference
+  /// between two midnights may not be a multiple of 24 hours due to daylight
+  /// saving differences.
+  ///
+  /// For example, in Australia, similar code using local time instead of UTC:
+  ///
+  /// ```
+  /// var berlinWallFell = DateTime(1989, DateTime.november, 9);
+  /// var dDay = DateTime(1944, DateTime.june, 6);
+  /// Duration difference = berlinWallFell.difference(dDay);
+  /// assert(difference.inDays == 16592);
+  /// ```
+  /// will fail because the difference is actually 16591 days and 23 hours, and
+  /// [Duration.inDays] only returns the number of whole days.
   external Duration difference(DateTime other);
 
   external DateTime._internal(int year, int month, int day, int hour,
@@ -705,150 +658,124 @@
       int microsecond,
       bool isUtc);
 
-  /**
-   * The number of milliseconds since
-   * the "Unix epoch" 1970-01-01T00:00:00Z (UTC).
-   *
-   * This value is independent of the time zone.
-   *
-   * This value is at most
-   * 8,640,000,000,000,000ms (100,000,000 days) from the Unix epoch.
-   * In other words: `millisecondsSinceEpoch.abs() <= 8640000000000000`.
-   */
+  /// The number of milliseconds since
+  /// the "Unix epoch" 1970-01-01T00:00:00Z (UTC).
+  ///
+  /// This value is independent of the time zone.
+  ///
+  /// This value is at most
+  /// 8,640,000,000,000,000ms (100,000,000 days) from the Unix epoch.
+  /// In other words: `millisecondsSinceEpoch.abs() <= 8640000000000000`.
   external int get millisecondsSinceEpoch;
 
-  /**
-   * The number of microseconds since
-   * the "Unix epoch" 1970-01-01T00:00:00Z (UTC).
-   *
-   * This value is independent of the time zone.
-   *
-   * This value is at most
-   * 8,640,000,000,000,000,000us (100,000,000 days) from the Unix epoch.
-   * In other words: `microsecondsSinceEpoch.abs() <= 8640000000000000000`.
-   *
-   * Note that this value does not fit into 53 bits (the size of a IEEE double).
-   * A JavaScript number is not able to hold this value.
-   */
+  /// The number of microseconds since
+  /// the "Unix epoch" 1970-01-01T00:00:00Z (UTC).
+  ///
+  /// This value is independent of the time zone.
+  ///
+  /// This value is at most
+  /// 8,640,000,000,000,000,000us (100,000,000 days) from the Unix epoch.
+  /// In other words: `microsecondsSinceEpoch.abs() <= 8640000000000000000`.
+  ///
+  /// Note that this value does not fit into 53 bits (the size of a IEEE double).
+  /// A JavaScript number is not able to hold this value.
   external int get microsecondsSinceEpoch;
 
-  /**
-   * The time zone name.
-   *
-   * This value is provided by the operating system and may be an
-   * abbreviation or a full name.
-   *
-   * In the browser or on Unix-like systems commonly returns abbreviations,
-   * such as "CET" or "CEST". On Windows returns the full name, for example
-   * "Pacific Standard Time".
-   */
+  /// The time zone name.
+  ///
+  /// This value is provided by the operating system and may be an
+  /// abbreviation or a full name.
+  ///
+  /// In the browser or on Unix-like systems commonly returns abbreviations,
+  /// such as "CET" or "CEST". On Windows returns the full name, for example
+  /// "Pacific Standard Time".
   external String get timeZoneName;
 
-  /**
-   * The time zone offset, which
-   * is the difference between local time and UTC.
-   *
-   * The offset is positive for time zones east of UTC.
-   *
-   * Note, that JavaScript, Python and C return the difference between UTC and
-   * local time. Java, C# and Ruby return the difference between local time and
-   * UTC.
-   */
+  /// The time zone offset, which
+  /// is the difference between local time and UTC.
+  ///
+  /// The offset is positive for time zones east of UTC.
+  ///
+  /// Note, that JavaScript, Python and C return the difference between UTC and
+  /// local time. Java, C# and Ruby return the difference between local time and
+  /// UTC.
   external Duration get timeZoneOffset;
 
-  /**
-   * The year.
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.year == 1969);
-   * ```
-   */
+  /// The year.
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.year == 1969);
+  /// ```
   external int get year;
 
-  /**
-   * The month [1..12].
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.month == 7);
-   * assert(moonLanding.month == DateTime.july);
-   * ```
-   */
+  /// The month [1..12].
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.month == 7);
+  /// assert(moonLanding.month == DateTime.july);
+  /// ```
   external int get month;
 
-  /**
-   * The day of the month [1..31].
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.day == 20);
-   * ```
-   */
+  /// The day of the month [1..31].
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.day == 20);
+  /// ```
   external int get day;
 
-  /**
-   * The hour of the day, expressed as in a 24-hour clock [0..23].
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.hour == 20);
-   * ```
-   */
+  /// The hour of the day, expressed as in a 24-hour clock [0..23].
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.hour == 20);
+  /// ```
   external int get hour;
 
-  /**
-   * The minute [0...59].
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.minute == 18);
-   * ```
-   */
+  /// The minute [0...59].
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.minute == 18);
+  /// ```
   external int get minute;
 
-  /**
-   * The second [0...59].
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.second == 4);
-   * ```
-   */
+  /// The second [0...59].
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.second == 4);
+  /// ```
   external int get second;
 
-  /**
-   * The millisecond [0...999].
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.millisecond == 0);
-   * ```
-   */
+  /// The millisecond [0...999].
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.millisecond == 0);
+  /// ```
   external int get millisecond;
 
-  /**
-   * The microsecond [0...999].
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.microsecond == 0);
-   * ```
-   */
+  /// The microsecond [0...999].
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.microsecond == 0);
+  /// ```
   external int get microsecond;
 
-  /**
-   * The day of the week [monday]..[sunday].
-   *
-   * In accordance with ISO 8601
-   * a week starts with Monday, which has the value 1.
-   *
-   * ```
-   * var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
-   * assert(moonLanding.weekday == 7);
-   * assert(moonLanding.weekday == DateTime.sunday);
-   * ```
-   */
+  /// The day of the week [monday]..[sunday].
+  ///
+  /// In accordance with ISO 8601
+  /// a week starts with Monday, which has the value 1.
+  ///
+  /// ```
+  /// var moonLanding = DateTime.parse("1969-07-20 20:18:04Z");
+  /// assert(moonLanding.weekday == 7);
+  /// assert(moonLanding.weekday == DateTime.sunday);
+  /// ```
   external int get weekday;
 
   /*
diff --git a/sdk/lib/core/double.dart b/sdk/lib/core/double.dart
index 42ff566..337d5f9 100644
--- a/sdk/lib/core/double.dart
+++ b/sdk/lib/core/double.dart
@@ -4,24 +4,18 @@
 
 part of dart.core;
 
-// TODO: Convert this abstract class into a concrete class double
-// that uses the patch class functionality to account for the
-// different platform implementations.
-
-/**
- * A double-precision floating point number.
- *
- * Representation of Dart doubles containing double specific constants
- * and operations and specializations of operations inherited from
- * [num]. Dart doubles are 64-bit floating-point numbers as specified in the
- * IEEE 754 standard.
- *
- * The [double] type is contagious. Operations on [double]s return
- * [double] results.
- *
- * It is a compile-time error for a class to attempt to extend or implement
- * double.
- */
+/// A double-precision floating point number.
+///
+/// Representation of Dart doubles containing double specific constants
+/// and operations and specializations of operations inherited from
+/// [num]. Dart doubles are 64-bit floating-point numbers as specified in the
+/// IEEE 754 standard.
+///
+/// The [double] type is contagious. Operations on [double]s return
+/// [double] results.
+///
+/// It is a compile-time error for a class to attempt to extend or implement
+/// double.
 abstract class double extends num {
   static const double nan = 0.0 / 0.0;
   static const double infinity = 1.0 / 0.0;
@@ -31,188 +25,160 @@
 
   double remainder(num other);
 
-  /** Addition operator. */
   double operator +(num other);
 
-  /** Subtraction operator. */
   double operator -(num other);
 
-  /** Multiplication operator. */
   double operator *(num other);
 
   double operator %(num other);
 
-  /** Division operator. */
   double operator /(num other);
 
-  /**
-   * Truncating division operator.
-   *
-   * The result of the truncating division `a ~/ b` is equivalent to
-   * `(a / b).truncate()`.
-   */
   int operator ~/(num other);
 
-  /** Negate operator. */
   double operator -();
 
-  /** Returns the absolute value of this [double]. */
   double abs();
 
-  /**
-   * Returns the sign of the double's numerical value.
-   *
-   * Returns -1.0 if the value is less than zero,
-   * +1.0 if the value is greater than zero,
-   * and the value itself if it is -0.0, 0.0 or NaN.
-   */
+  /// Returns the sign of the double's numerical value.
+  ///
+  /// Returns -1.0 if the value is less than zero,
+  /// +1.0 if the value is greater than zero,
+  /// and the value itself if it is -0.0, 0.0 or NaN.
   double get sign;
 
-  /**
-   * Returns the integer closest to `this`.
-   *
-   * Rounds away from zero when there is no closest integer:
-   *  `(3.5).round() == 4` and `(-3.5).round() == -4`.
-   *
-   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
-   */
+  /// Returns the integer closest to this number.
+  ///
+  /// Rounds away from zero when there is no closest integer:
+  ///  `(3.5).round() == 4` and `(-3.5).round() == -4`.
+  ///
+  /// Throws an [UnsupportedError] if this number is not finite
+  /// (NaN or an infinity), .
   int round();
 
-  /**
-   * Returns the greatest integer no greater than `this`.
-   *
-   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
-   */
+  /// Returns the greatest integer no greater than this number.
+  ///
+  /// Rounds the number towards negative infinity.
+  ///
+  /// Throws an [UnsupportedError] if this number is not finite
+  /// (NaN or infinity), .
   int floor();
 
-  /**
-   * Returns the least integer no smaller than `this`.
-   *
-   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
-   */
+  /// Returns the least integer which is not smaller than this number.
+  ///
+  /// Rounds the number towards infinity.
+  ///
+  /// Throws an [UnsupportedError] if this number is not finite
+  /// (NaN or an infinity), .
   int ceil();
 
-  /**
-   * Returns the integer obtained by discarding any fractional
-   * digits from `this`.
-   *
-   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
-   */
+  /// Returns the integer obtained by discarding any fractional
+  /// part of this number.
+  ///
+  /// Rounds the number towards zero.
+  ///
+  /// Throws an [UnsupportedError] if this number is not finite
+  /// (NaN or an infinity), .
   int truncate();
 
-  /**
-   * Returns the integer double value closest to `this`.
-   *
-   * Rounds away from zero when there is no closest integer:
-   *  `(3.5).roundToDouble() == 4` and `(-3.5).roundToDouble() == -4`.
-   *
-   * If this is already an integer valued double, including `-0.0`, or it is not
-   * a finite value, the value is returned unmodified.
-   *
-   * For the purpose of rounding, `-0.0` is considered to be below `0.0`,
-   * and `-0.0` is therefore considered closer to negative numbers than `0.0`.
-   * This means that for a value, `d` in the range `-0.5 < d < 0.0`,
-   * the result is `-0.0`.
-   */
+  /// Returns the integer double value closest to `this`.
+  ///
+  /// Rounds away from zero when there is no closest integer:
+  ///  `(3.5).roundToDouble() == 4` and `(-3.5).roundToDouble() == -4`.
+  ///
+  /// If this is already an integer valued double, including `-0.0`, or it is not
+  /// a finite value, the value is returned unmodified.
+  ///
+  /// For the purpose of rounding, `-0.0` is considered to be below `0.0`,
+  /// and `-0.0` is therefore considered closer to negative numbers than `0.0`.
+  /// This means that for a value, `d` in the range `-0.5 < d < 0.0`,
+  /// the result is `-0.0`.
   double roundToDouble();
 
-  /**
-   * Returns the greatest integer double value no greater than `this`.
-   *
-   * If this is already an integer valued double, including `-0.0`, or it is not
-   * a finite value, the value is returned unmodified.
-   *
-   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
-   * A number `d` in the range `0.0 < d < 1.0` will return `0.0`.
-   */
+  /// Returns the greatest integer double value no greater than `this`.
+  ///
+  /// If this is already an integer valued double, including `-0.0`, or it is not
+  /// a finite value, the value is returned unmodified.
+  ///
+  /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
+  /// A number `d` in the range `0.0 < d < 1.0` will return `0.0`.
   double floorToDouble();
 
-  /**
-   * Returns the least integer double value no smaller than `this`.
-   *
-   * If this is already an integer valued double, including `-0.0`, or it is not
-   * a finite value, the value is returned unmodified.
-   *
-   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
-   * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`.
-   */
+  /// Returns the least integer double value no smaller than `this`.
+  ///
+  /// If this is already an integer valued double, including `-0.0`, or it is not
+  /// a finite value, the value is returned unmodified.
+  ///
+  /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
+  /// A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`.
   double ceilToDouble();
 
-  /**
-   * Returns the integer double value obtained by discarding any fractional
-   * digits from `this`.
-   *
-   * If this is already an integer valued double, including `-0.0`, or it is not
-   * a finite value, the value is returned unmodified.
-   *
-   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
-   * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and
-   * in the range `0.0 < d < 1.0` it will return 0.0.
-   */
+  /// Returns the integer double value obtained by discarding any fractional
+  /// digits from `this`.
+  ///
+  /// If this is already an integer valued double, including `-0.0`, or it is not
+  /// a finite value, the value is returned unmodified.
+  ///
+  /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
+  /// A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and
+  /// in the range `0.0 < d < 1.0` it will return 0.0.
   double truncateToDouble();
 
-  /**
-   * Provide a representation of this [double] value.
-   *
-   * The representation is a number literal such that the closest double value
-   * to the representation's mathematical value is this [double].
-   *
-   * Returns "NaN" for the Not-a-Number value.
-   * Returns "Infinity" and "-Infinity" for positive and negative Infinity.
-   * Returns "-0.0" for negative zero.
-   *
-   * For all doubles, `d`, converting to a string and parsing the string back
-   * gives the same value again: `d == double.parse(d.toString())` (except when
-   * `d` is NaN).
-   */
+  /// Provide a representation of this [double] value.
+  ///
+  /// The representation is a number literal such that the closest double value
+  /// to the representation's mathematical value is this [double].
+  ///
+  /// Returns "NaN" for the Not-a-Number value.
+  /// Returns "Infinity" and "-Infinity" for positive and negative Infinity.
+  /// Returns "-0.0" for negative zero.
+  ///
+  /// For all doubles, `d`, converting to a string and parsing the string back
+  /// gives the same value again: `d == double.parse(d.toString())` (except when
+  /// `d` is NaN).
   String toString();
 
-  /**
-   * Parse [source] as an double literal and return its value.
-   *
-   * Accepts an optional sign (`+` or `-`) followed by either the characters
-   * "Infinity", the characters "NaN" or a floating-point representation.
-   * A floating-point representation is composed of a mantissa and an optional
-   * exponent part. The mantissa is either a decimal point (`.`) followed by a
-   * sequence of (decimal) digits, or a sequence of digits
-   * optionally followed by a decimal point and optionally more digits. The
-   * (optional) exponent part consists of the character "e" or "E", an optional
-   * sign, and one or more digits.
-   * The [source] must not be `null`.
-   *
-   * Leading and trailing whitespace is ignored.
-   *
-   * If the [source] string is not a valid double literal, the [onError]
-   * is called with the [source] as argument, and its return value is
-   * used instead. If no `onError` is provided, a [FormatException]
-   * is thrown instead.
-   *
-   * The [onError] function is only invoked if [source] is a [String] with an
-   * invalid format. It is not invoked if [source] is `null`.
-   *
-   * Examples of accepted strings:
-   *
-   *     "3.14"
-   *     "  3.14 \xA0"
-   *     "0."
-   *     ".0"
-   *     "-1.e3"
-   *     "1234E+7"
-   *     "+.12e-9"
-   *     "-NaN"
-   *
-   * The [onError] parameter is deprecated and will be removed.
-   * Instead of `double.parse(string, (string) { ... })`,
-   * you should use `double.tryParse(string) ?? (...)`.
-   */
+  /// Parse [source] as an double literal and return its value.
+  ///
+  /// Accepts an optional sign (`+` or `-`) followed by either the characters
+  /// "Infinity", the characters "NaN" or a floating-point representation.
+  /// A floating-point representation is composed of a mantissa and an optional
+  /// exponent part. The mantissa is either a decimal point (`.`) followed by a
+  /// sequence of (decimal) digits, or a sequence of digits
+  /// optionally followed by a decimal point and optionally more digits. The
+  /// (optional) exponent part consists of the character "e" or "E", an optional
+  /// sign, and one or more digits.
+  /// The [source] must not be `null`.
+  ///
+  /// Leading and trailing whitespace is ignored.
+  ///
+  /// If the [source] string is not a valid double literal, the [onError]
+  /// is called with the [source] as argument, and its return value is
+  /// used instead.
+  /// Throws a [FormatException] if the [source] string is not valid
+  /// and no `onError` is provided.
+  ///
+  /// Examples of accepted strings:
+  /// ```dart
+  /// "3.14"
+  /// "  3.14 \xA0"
+  /// "0."
+  /// ".0"
+  /// "-1.e3"
+  /// "1234E+7"
+  /// "+.12e-9"
+  /// "-NaN"
+  /// ```
+  /// The [onError] parameter is deprecated and will be removed.
+  /// Instead of `double.parse(string, (string) { ... })`,
+  /// you should use `double.tryParse(string) ?? (...)`.
   external static double parse(String source,
       [@deprecated double onError(String source)?]);
 
-  /**
-   * Parse [source] as an double literal and return its value.
-   *
-   * Like [parse] except that this function returns `null` for invalid inputs
-   * instead of throwing, and the [source] must still not be `null`.
-   */
+  /// Parse [source] as an double literal and return its value.
+  ///
+  /// Like [parse] except that this function returns `null` for invalid inputs
+  /// instead of throwing.
   external static double? tryParse(String source);
 }
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index c4c6846..57075cb 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.dart
@@ -4,92 +4,127 @@
 
 part of dart.core;
 
-/**
- * A span of time, such as 27 days, 4 hours, 12 minutes, and 3 seconds.
- *
- * A `Duration` represents a difference from one point in time to another. The
- * duration may be "negative" if the difference is from a later time to an
- * earlier.
- *
- * Durations are context independent. For example, a duration of 2 days is
- * always 48 hours, even when it is added to a `DateTime` just when the
- * time zone is about to do a daylight-savings switch. (See [DateTime.add]).
- *
- * Despite the same name, a `Duration` object does not implement "Durations"
- * as specified by ISO 8601. In particular, a duration object does not keep
- * track of the individually provided members (such as "days" or "hours"), but
- * only uses these arguments to compute the length of the corresponding time
- * interval.
- *
- * To create a new Duration object, use this class's single constructor
- * giving the appropriate arguments:
- * ```dart
- * Duration fastestMarathon = new Duration(hours:2, minutes:3, seconds:2);
- * ```
- * The [Duration] is the sum of all individual parts.
- * This means that individual parts can be larger than the next-bigger unit.
- * For example, [inMinutes] can be greater than 59.
- * ```dart
- * assert(fastestMarathon.inMinutes == 123);
- * ```
- * All individual parts are allowed to be negative.
- *
- * Use one of the properties, such as [inDays],
- * to retrieve the integer value of the Duration in the specified time unit.
- * Note that the returned value is rounded down.
- * For example,
- * ```dart
- * Duration aLongWeekend = new Duration(hours:88);
- * assert(aLongWeekend.inDays == 3);
- * ```
- * This class provides a collection of arithmetic
- * and comparison operators,
- * plus a set of constants useful for converting time units.
- *
- * See [DateTime] to represent a point in time.
- * See [Stopwatch] to measure time-spans.
- */
+/// A span of time, such as 27 days, 4 hours, 12 minutes, and 3 seconds.
+///
+/// A `Duration` represents a difference from one point in time to another. The
+/// duration may be "negative" if the difference is from a later time to an
+/// earlier.
+///
+/// Durations are context independent. For example, a duration of 2 days is
+/// always 48 hours, even when it is added to a `DateTime` just when the
+/// time zone is about to do a daylight-savings switch. (See [DateTime.add]).
+///
+/// Despite the same name, a `Duration` object does not implement "Durations"
+/// as specified by ISO 8601. In particular, a duration object does not keep
+/// track of the individually provided members (such as "days" or "hours"), but
+/// only uses these arguments to compute the length of the corresponding time
+/// interval.
+///
+/// To create a new Duration object, use this class's single constructor
+/// giving the appropriate arguments:
+/// ```dart
+/// var fastestMarathon = const Duration(hours: 2, minutes: 3, seconds: 2);
+/// ```
+/// The [Duration] is the sum of all individual parts.
+/// This means that individual parts can be larger than the next-bigger unit.
+/// For example, [inMinutes] can be greater than 59.
+/// ```dart
+/// assert(fastestMarathon.inMinutes == 123);
+/// ```
+/// All individual parts are allowed to be negative.
+///
+/// Use one of the properties, such as [inDays],
+/// to retrieve the integer value of the Duration in the specified time unit.
+/// Note that the returned value is rounded down.
+/// For example,
+/// ```dart
+/// var aLongWeekend = const Duration(hours: 88);
+/// assert(aLongWeekend.inDays == 3);
+/// ```
+/// This class provides a collection of arithmetic
+/// and comparison operators,
+/// plus a set of constants useful for converting time units.
+///
+/// See [DateTime] to represent a point in time.
+/// See [Stopwatch] to measure time-spans.
 class Duration implements Comparable<Duration> {
+  /// The number of microseconds per millisecond.
   static const int microsecondsPerMillisecond = 1000;
+
+  /// The number of milliseconds per second.
   static const int millisecondsPerSecond = 1000;
+
+  /// The number of seconds per minute.
+  ///
+  /// Notice that some minutes of official clock time might
+  /// differ in length because of leap seconds.
+  /// The [Duration] and [DateTime] classes ignore leap seconds
+  /// and consider all minutes to have 60 seconds.
   static const int secondsPerMinute = 60;
+
+  /// The number of minutes per hour.
   static const int minutesPerHour = 60;
+
+  /// The number of hours per day.
+  ///
+  /// Notice that some days may differ in length because
+  /// of time zone changes due to daylight saving.
+  /// The [Duration] class is time zone agnostic and
+  /// considers all days to have 24 hours.
   static const int hoursPerDay = 24;
 
+  /// The number of microseconds per second.
   static const int microsecondsPerSecond =
       microsecondsPerMillisecond * millisecondsPerSecond;
+
+  /// The number of microseconds per minute.
   static const int microsecondsPerMinute =
       microsecondsPerSecond * secondsPerMinute;
+
+  /// The number of microseconds per hour.
   static const int microsecondsPerHour = microsecondsPerMinute * minutesPerHour;
+
+  /// The number of microseconds per day.
   static const int microsecondsPerDay = microsecondsPerHour * hoursPerDay;
 
+  /// The number of milliseconds per minute.
   static const int millisecondsPerMinute =
       millisecondsPerSecond * secondsPerMinute;
+
+  /// The number of milliseconds per hour.
   static const int millisecondsPerHour = millisecondsPerMinute * minutesPerHour;
+
+  /// The number of milliseconds per day.
   static const int millisecondsPerDay = millisecondsPerHour * hoursPerDay;
 
+  /// The number of seconds per hour.
   static const int secondsPerHour = secondsPerMinute * minutesPerHour;
+
+  /// The number of seconds per day.
   static const int secondsPerDay = secondsPerHour * hoursPerDay;
 
+  /// The number of minutes per day.
   static const int minutesPerDay = minutesPerHour * hoursPerDay;
 
+  /// An empty duration, representing zero time.
   static const Duration zero = Duration(seconds: 0);
 
-  /*
-   * The value of this Duration object in microseconds.
-   */
+  /// The total microseconds of this [Duration] object.
   final int _duration;
 
-  /**
-   * Creates a new Duration object whose value
-   * is the sum of all individual parts.
-   *
-   * Individual parts can be larger than the next-bigger unit.
-   * For example, [hours] can be greater than 23.
-   *
-   * All individual parts are allowed to be negative.
-   * All arguments are 0 by default.
-   */
+  /// Creates a new [Duration] object whose value
+  /// is the sum of all individual parts.
+  ///
+  /// Individual parts can be larger than the number of those
+  /// parts in the next larger unit.
+  /// For example, [hours] can be greater than 23.
+  /// If this happens, the value overflows into the next larger
+  /// unit, so 26 [hours] is the same as 2 [hours] and
+  /// one more [days].
+  /// Likewise, values can be negative, in which case they
+  /// underflow and subtract from the next larger unit.
+  ///
+  /// All arguments are 0 by default.
   const Duration(
       {int days = 0,
       int hours = 0,
@@ -108,39 +143,31 @@
   // [_microseconds] recomputation.
   const Duration._microseconds(this._duration);
 
-  /**
-   * Adds this Duration and [other] and
-   * returns the sum as a new Duration object.
-   */
+  /// Adds this Duration and [other] and
+  /// returns the sum as a new Duration object.
   Duration operator +(Duration other) {
     return Duration._microseconds(_duration + other._duration);
   }
 
-  /**
-   * Subtracts [other] from this Duration and
-   * returns the difference as a new Duration object.
-   */
+  /// Subtracts [other] from this Duration and
+  /// returns the difference as a new Duration object.
   Duration operator -(Duration other) {
     return Duration._microseconds(_duration - other._duration);
   }
 
-  /**
-   * Multiplies this Duration by the given [factor] and returns the result
-   * as a new Duration object.
-   *
-   * Note that when [factor] is a double, and the duration is greater than
-   * 53 bits, precision is lost because of double-precision arithmetic.
-   */
+  /// Multiplies this Duration by the given [factor] and returns the result
+  /// as a new Duration object.
+  ///
+  /// Note that when [factor] is a double, and the duration is greater than
+  /// 53 bits, precision is lost because of double-precision arithmetic.
   Duration operator *(num factor) {
     return Duration._microseconds((_duration * factor).round());
   }
 
-  /**
-   * Divides this Duration by the given [quotient] and returns the truncated
-   * result as a new Duration object.
-   *
-   * Throws an [IntegerDivisionByZeroException] if [quotient] is `0`.
-   */
+  /// Divides this Duration by the given [quotient] and returns the truncated
+  /// result as a new Duration object.
+  ///
+  /// Throws an [IntegerDivisionByZeroException] if [quotient] is `0`.
   Duration operator ~/(int quotient) {
     // By doing the check here instead of relying on "~/" below we get the
     // exception even with dart2js.
@@ -148,101 +175,87 @@
     return Duration._microseconds(_duration ~/ quotient);
   }
 
-  /**
-   * Returns `true` if the value of this Duration
-   * is less than the value of [other].
-   */
+  /// Whether this [Duration] is shorter than [other].
   bool operator <(Duration other) => this._duration < other._duration;
 
-  /**
-   * Returns `true` if the value of this Duration
-   * is greater than the value of [other].
-   */
+  /// Whether this [Duration] is longer than [other].
   bool operator >(Duration other) => this._duration > other._duration;
 
-  /**
-   * Returns `true` if the value of this Duration
-   * is less than or equal to the value of [other].
-   */
+  /// Whether this [Duration] is shorter than or equal to [other].
   bool operator <=(Duration other) => this._duration <= other._duration;
 
-  /**
-   * Returns `true` if the value of this Duration
-   * is greater than or equal to the value of [other].
-   */
+  /// Whether this [Duration] is longer than or equal to [other].
   bool operator >=(Duration other) => this._duration >= other._duration;
 
-  /**
-   * Returns the number of whole days spanned by this Duration.
-   */
+  /// The number of entire days spanned by this [Duration].
   int get inDays => _duration ~/ Duration.microsecondsPerDay;
 
-  /**
-   * Returns the number of whole hours spanned by this Duration.
-   *
-   * The returned value can be greater than 23.
-   */
+  /// The number of entire hours spanned by this [Duration].
+  ///
+  /// The returned value can be greater than 23.
+  /// For example a duration of four days and three hours
+  /// has 99 entire hours.
   int get inHours => _duration ~/ Duration.microsecondsPerHour;
 
-  /**
-   * Returns the number of whole minutes spanned by this Duration.
-   *
-   * The returned value can be greater than 59.
-   */
+  /// The number of whole minutes spanned by this [Duration].
+  ///
+  /// The returned value can be greater than 59.
+  /// For example a duration of three hours and 12 minutes
+  /// has 192 minutes.
   int get inMinutes => _duration ~/ Duration.microsecondsPerMinute;
 
-  /**
-   * Returns the number of whole seconds spanned by this Duration.
-   *
-   * The returned value can be greater than 59.
-   */
+  /// The number of whole seconds spanned by this [Duration].
+  ///
+  /// The returned value can be greater than 59.
+  /// For example a duration of three minutes and 12 seconds
+  /// has 192 seconds.
   int get inSeconds => _duration ~/ Duration.microsecondsPerSecond;
 
-  /**
-   * Returns number of whole milliseconds spanned by this Duration.
-   *
-   * The returned value can be greater than 999.
-   */
+  /// The number of whole milliseconds spanned by this [Duration].
+  ///
+  /// The returned value can be greater than 999.
+  /// For example a duration of three seconds and 125 milliseconds
+  /// has 3125 milliseconds.
   int get inMilliseconds => _duration ~/ Duration.microsecondsPerMillisecond;
 
-  /**
-   * Returns number of whole microseconds spanned by this Duration.
-   */
+  /// The number of whole microseconds spanned by this [Duration].
+  ///
+  /// The returned value can be greater than 999999.
+  /// For example a duration of three seconds, 125 milliseconds and
+  /// 369 microseconds has 3125369 microseconds.
   int get inMicroseconds => _duration;
 
-  /**
-   * Returns `true` if this [Duration] has the same value as [other].
-   */
+  /// Whether this [Duration] has the same length as [other].
+  ///
+  /// Durations have the same length if they have the same number
+  /// of microseconds, as reported by [inMicroseconds].
   bool operator ==(Object other) =>
       other is Duration && _duration == other.inMicroseconds;
 
   int get hashCode => _duration.hashCode;
 
-  /**
-   * Compares this [Duration] to [other], returning zero if the values are equal.
-   *
-   * Returns a negative integer if this `Duration` is shorter than
-   * [other], or a positive integer if it is longer.
-   *
-   * A negative `Duration` is always considered shorter than a positive one.
-   *
-   * It is always the case that `duration1.compareTo(duration2) < 0` iff
-   * `(someDate + duration1).compareTo(someDate + duration2) < 0`.
-   */
+  /// Compares this [Duration] to [other], returning zero if the values are equal.
+  ///
+  /// Returns a negative integer if this [Duration] is shorter than
+  /// [other], or a positive integer if it is longer.
+  ///
+  /// A negative [Duration] is always considered shorter than a positive one.
+  ///
+  /// It is always the case that `duration1.compareTo(duration2) < 0` iff
+  /// `(someDate + duration1).compareTo(someDate + duration2) < 0`.
   int compareTo(Duration other) => _duration.compareTo(other._duration);
 
-  /**
-   * Returns a string representation of this `Duration`.
-   *
-   * Returns a string with hours, minutes, seconds, and microseconds, in the
-   * following format: `H:MM:SS.mmmmmm`. For example,
-   *
-   *     var d = Duration(days: 1, hours: 1, minutes: 33, microseconds: 500);
-   *     d.toString();  // "25:33:00.000500"
-   *
-   *     d = Duration(days: 0, hours: 1, minutes: 10, microseconds: 500);
-   *     d.toString();  // "1:10:00.000500"
-   */
+  /// Returns a string representation of this [Duration].
+  ///
+  /// Returns a string with hours, minutes, seconds, and microseconds, in the
+  /// following format: `H:MM:SS.mmmmmm`. For example,
+  /// ```dart
+  /// var d = Duration(days: 1, hours: 1, minutes: 33, microseconds: 500);
+  /// d.toString();  // "25:33:00.000500"
+  ///
+  /// d = Duration(days: 0, hours: 1, minutes: 10, microseconds: 500);
+  /// d.toString();  // "1:10:00.000500"
+  /// ```
   String toString() {
     String sixDigits(int n) {
       if (n >= 100000) return "$n";
@@ -270,29 +283,23 @@
     return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$sixDigitUs";
   }
 
-  /**
-   * Returns whether this `Duration` is negative.
-   *
-   * A negative `Duration` represents the difference from a later time to an
-   * earlier time.
-   */
+  /// Whether this [Duration] is negative.
+  ///
+  /// A negative [Duration] represents the difference from a later time to an
+  /// earlier time.
   bool get isNegative => _duration < 0;
 
-  /**
-   * Returns a new `Duration` representing the absolute value of this
-   * `Duration`.
-   *
-   * The returned `Duration` has the same length as this one, but is always
-   * positive.
-   */
+  /// Creates a new [Duration] representing the absolute length of this
+  /// [Duration].
+  ///
+  /// The returned [Duration] has the same length as this one, but is always
+  /// positive.
   Duration abs() => Duration._microseconds(_duration.abs());
 
-  /**
-   * Returns a new `Duration` representing this `Duration` negated.
-   *
-   * The returned `Duration` has the same length as this one, but will have the
-   * opposite sign of this one.
-   */
+  /// Creates a new [Duration] with the opposite direction of this [Duration].
+  ///
+  /// The returned [Duration] has the same length as this one, but will have the
+  /// opposite sign (as reported by [isNegative]) as this one.
   // Using subtraction helps dart2js avoid negative zeros.
   Duration operator -() => Duration._microseconds(0 - _duration);
 }
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index a84c6ee..f0d6178 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -4,76 +4,73 @@
 
 part of dart.core;
 
-/**
- * Error objects thrown in the case of a program failure.
- *
- * An `Error` object represents a program failure that the programmer
- * should have avoided.
- *
- * Examples include calling a function with invalid arguments,
- * or even with the wrong number of arguments,
- * or calling it at a time when it is not allowed.
- *
- * These are not errors that a caller should expect or catch -
- * if they occur, the program is erroneous,
- * and terminating the program may be the safest response.
- *
- * When deciding that a function throws an error,
- * the conditions where it happens should be clearly described,
- * and they should be detectable and predictable,
- * so the programmer using the function can avoid triggering the error.
- *
- * Such descriptions often uses words like
- * "must" or "must not" to describe the condition,
- * and if you see words like that in a function's documentation,
- * then not satisfying the requirement
- * is very likely to cause an error to be thrown.
- *
- * Example (from [String.contains]):
- *
- *        `startIndex` must not be negative or greater than `length`.
- *
- * In this case, an error will be thrown if `startIndex` is negative
- * or too large.
- *
- * If the conditions are not detectable before calling a function,
- * the called function should not throw an `Error`.
- * It may still throw a value,
- * but the caller will have to catch the thrown value,
- * effectively making it an alternative result rather than an error.
- * The thrown object can choose to implement [Exception]
- * to document that it represents an exceptional, but not erroneous, occurrence,
- * but it has no other effect than documentation.
- *
- * All non-`null` values can be thrown in Dart.
- * Objects extending `Error` are handled specially:
- * The first time they are thrown,
- * the stack trace at the throw point is recorded
- * and stored in the error object.
- * It can be retrieved using the [stackTrace] getter.
- * An error object that merely implements `Error`, and doesn't extend it,
- * will not store the stack trace automatically.
- *
- * Error objects are also used for system wide failures
- * like stack overflow or an out-of-memory situation.
- *
- * Since errors are not created to be caught,
- * there is no need for subclasses to distinguish the errors.
- * Instead subclasses have been created in order to make groups
- * of related errors easy to create with consistent error messages.
- * For example, the [String.contains] method will use a [RangeError]
- * if its `startIndex` isn't in the range `0..length`,
- * which is easily created by `new RangeError.range(startIndex, 0, length)`.
- */
+/// Error objects thrown in the case of a program failure.
+///
+/// An `Error` object represents a program failure that the programmer
+/// should have avoided.
+///
+/// Examples include calling a function with invalid arguments,
+/// or even with the wrong number of arguments,
+/// or calling it at a time when it is not allowed.
+///
+/// These are not errors that a caller should expect or catch -
+/// if they occur, the program is erroneous,
+/// and terminating the program may be the safest response.
+///
+/// When deciding that a function throws an error,
+/// the conditions where it happens should be clearly described,
+/// and they should be detectable and predictable,
+/// so the programmer using the function can avoid triggering the error.
+///
+/// Such descriptions often uses words like
+/// "must" or "must not" to describe the condition,
+/// and if you see words like that in a function's documentation,
+/// then not satisfying the requirement
+/// is very likely to cause an error to be thrown.
+///
+/// Example (from [String.contains]):
+/// ```
+/// `startIndex` must not be negative or greater than `length`.
+/// ```
+/// In this case, an error will be thrown if `startIndex` is negative
+/// or too large.
+///
+/// If the conditions are not detectable before calling a function,
+/// the called function should not throw an `Error`.
+/// It may still throw,
+/// but the caller will have to catch the thrown value,
+/// effectively making it an alternative result rather than an error.
+/// The thrown object can choose to implement [Exception]
+/// to document that it represents an exceptional, but not erroneous,
+/// occurrence, but being an [Excpetion] has no other effect
+/// than documentation.
+///
+/// All non-`null` values can be thrown in Dart.
+/// Objects extending `Error` are handled specially:
+/// The first time they are thrown,
+/// the stack trace at the throw point is recorded
+/// and stored in the error object.
+/// It can be retrieved using the [stackTrace] getter.
+/// An error object that merely implements `Error`, and doesn't extend it,
+/// will not store the stack trace automatically.
+///
+/// Error objects are also used for system wide failures
+/// like stack overflow or an out-of-memory situation.
+///
+/// Since errors are not created to be caught,
+/// there is no need for subclasses to distinguish the errors.
+/// Instead subclasses have been created in order to make groups
+/// of related errors easy to create with consistent error messages.
+/// For example, the [String.contains] method will use a [RangeError]
+/// if its `startIndex` isn't in the range `0..length`,
+/// which is easily created by `RangeError.range(startIndex, 0, length)`.
 class Error {
   Error(); // Prevent use as mixin.
 
-  /**
-   * Safely convert a value to a [String] description.
-   *
-   * The conversion is guaranteed to not throw, so it won't use the object's
-   * toString method.
-   */
+  /// Safely convert a value to a [String] description.
+  ///
+  /// The conversion is guaranteed to not throw, so it won't use the object's
+  /// toString method except for specific known and trusted types.
   static String safeToString(Object? object) {
     if (object is num || object is bool || null == object) {
       return object.toString();
@@ -84,21 +81,25 @@
     return _objectToString(object);
   }
 
-  /** Convert string to a valid string literal with no control characters. */
+  /// Convert string to a valid string literal with no control characters.
   external static String _stringToSafeString(String string);
 
   external static String _objectToString(Object object);
 
+  /// The stack trace at the point where this error was first thrown.
+  ///
+  /// Classes which *extend* `Error` will automatically have a stack
+  /// trace filled in the first time they are thrown by a `throw`
+  /// expression.
   external StackTrace? get stackTrace;
 }
 
-/**
- * Error thrown by the runtime system when an assert statement fails.
- */
+/// Error thrown by the runtime system when an assert statement fails.
 class AssertionError extends Error {
-  /** Message describing the assertion error. */
+  /// Message describing the assertion error.
   final Object? message;
 
+  /// Creates an assertion error with the provided [message].
   AssertionError([this.message]);
 
   String toString() {
@@ -109,86 +110,76 @@
   }
 }
 
-/**
- * Error thrown by the runtime system when a dynamic type error happens.
- */
+/// Error thrown by the runtime system when a dynamic type error happens.
 class TypeError extends Error {}
 
-/**
- * Error thrown by the runtime system when a cast operation fails.
- */
+/// Error thrown by the runtime system when a cast operation fails.
 @Deprecated("Use TypeError instead")
 class CastError extends Error {}
 
-/**
- * Error thrown when attempting to throw `null`.
- */
+/// Error thrown when attempting to throw `null`.
+///
+/// In null safe code, you are statically disallowed from throwing `null`,
+/// so this error will go away when non-null safe code stops being supported.
 class NullThrownError extends Error {
   @pragma("vm:entry-point")
   NullThrownError();
   String toString() => "Throw of null.";
 }
 
-/**
- * Error thrown when a function is passed an unacceptable argument.
- */
+/// Error thrown when a function is passed an unacceptable argument.
 class ArgumentError extends Error {
-  /** Whether value was provided. */
+  /// Whether value was provided.
   final bool _hasValue;
-  /** The invalid value. */
+
+  /// The invalid value.
   final dynamic invalidValue;
-  /** Name of the invalid argument, if available. */
+
+  /// Name of the invalid argument, if available.
   final String? name;
-  /** Message describing the problem. */
+
+  /// Message describing the problem.
   final dynamic message;
 
-  /**
-   * The [message] describes the erroneous argument.
-   *
-   * Existing code may be using `message` to hold the invalid value.
-   * If the `message` is not a [String], it is assumed to be a value instead
-   * of a message.
-   */
+  /// Creates an error with [message] describing the problem with an argument.
+  ///
+  /// Existing code may be using `message` to hold the invalid value.
+  /// If the `message` is not a [String], it is assumed to be a value instead
+  /// of a message.
   @pragma("vm:entry-point")
   ArgumentError([this.message])
       : invalidValue = null,
         _hasValue = false,
         name = null;
 
-  /**
-   * Creates error containing the invalid [value].
-   *
-   * A message is built by suffixing the [message] argument with
-   * the [name] argument (if provided) and the value. Example
-   *
-   *    "Invalid argument (foo): null"
-   *
-   * The `name` should match the argument name of the function, but if
-   * the function is a method implementing an interface, and its argument
-   * names differ from the interface, it might be more useful to use the
-   * interface method's argument name (or just rename arguments to match).
-   */
+  /// Creates error containing the invalid [value].
+  ///
+  /// A message is built by suffixing the [message] argument with
+  /// the [name] argument (if provided) and the value. Example:
+  /// ```
+  /// "Invalid argument (foo): null"
+  /// ```
+  /// The `name` should match the argument name of the function, but if
+  /// the function is a method implementing an interface, and its argument
+  /// names differ from the interface, it might be more useful to use the
+  /// interface method's argument name (or just rename arguments to match).
   @pragma("vm:entry-point")
   ArgumentError.value(value, [this.name, this.message])
       : invalidValue = value,
         _hasValue = true;
 
-  /**
-   * Create an argument error for a `null` argument that must not be `null`.
-   */
+  /// Creates an argument error for a `null` argument that must not be `null`.
   ArgumentError.notNull([this.name])
       : _hasValue = false,
         message = "Must not be null",
         invalidValue = null;
 
-  /**
-   * Throws if [argument] is `null`.
-   *
-   * If [name] is supplied, it is used as the parameter name
-   * in the error message.
-   *
-   * Returns the [argument] if it is not null.
-   */
+  /// Throws if [argument] is `null`.
+  ///
+  /// If [name] is supplied, it is used as the parameter name
+  /// in the error message.
+  ///
+  /// Returns the [argument] if it is not null.
   @Since("2.1")
   static T checkNotNull<@Since("2.8") T>(T? argument, [String? name]) {
     if (argument == null) throw ArgumentError.notNull(name);
@@ -213,52 +204,45 @@
   }
 }
 
-/**
- * Error thrown due to an index being outside a valid range.
- */
+/// Error thrown due to a value being outside a valid range.
 class RangeError extends ArgumentError {
-  /** The minimum value that [value] is allowed to assume. */
+  /// The minimum value that [value] is allowed to assume.
   final num? start;
-  /** The maximum value that [value] is allowed to assume. */
+
+  /// The maximum value that [value] is allowed to assume.
   final num? end;
 
   // TODO(lrn): This constructor should be called only with string values.
   // It currently isn't in all cases.
-  /**
-   * Create a new [RangeError] with the given [message].
-   */
+  /// Create a new [RangeError] with the given [message].
   @pragma("vm:entry-point")
   RangeError(var message)
       : start = null,
         end = null,
         super(message);
 
-  /**
-   * Create a new [RangeError] with a message for the given [value].
-   *
-   * An optional [name] can specify the argument name that has the
-   * invalid value, and the [message] can override the default error
-   * description.
-   */
+  /// Create a new [RangeError] with a message for the given [value].
+  ///
+  /// An optional [name] can specify the argument name that has the
+  /// invalid value, and the [message] can override the default error
+  /// description.
   RangeError.value(num value, [String? name, String? message])
       : start = null,
         end = null,
         super.value(value, name, message ?? "Value not in range");
 
-  /**
-   * Create a new [RangeError] for a value being outside the valid range.
-   *
-   * The allowed range is from [minValue] to [maxValue], inclusive.
-   * If `minValue` or `maxValue` are `null`, the range is infinite in
-   * that direction.
-   *
-   * For a range from 0 to the length of something, end exclusive, use
-   * [RangeError.index].
-   *
-   * An optional [name] can specify the argument name that has the
-   * invalid value, and the [message] can override the default error
-   * description.
-   */
+  /// Create a new [RangeError] for a value being outside the valid range.
+  ///
+  /// The allowed range is from [minValue] to [maxValue], inclusive.
+  /// If `minValue` or `maxValue` are `null`, the range is infinite in
+  /// that direction.
+  ///
+  /// For a range from 0 to the length of something, end exclusive, use
+  /// [RangeError.index].
+  ///
+  /// An optional [name] can specify the argument name that has the
+  /// invalid value, and the [message] can override the default error
+  /// description.
   @pragma("vm:entry-point")
   RangeError.range(num invalidValue, int? minValue, int? maxValue,
       [String? name, String? message])
@@ -266,31 +250,27 @@
         end = maxValue,
         super.value(invalidValue, name, message ?? "Invalid value");
 
-  /**
-   * Creates a new [RangeError] stating that [index] is not a valid index
-   * into [indexable].
-   *
-   * An optional [name] can specify the argument name that has the
-   * invalid value, and the [message] can override the default error
-   * description.
-   *
-   * The [length] is the length of [indexable] at the time of the error.
-   * If `length` is omitted, it defaults to `indexable.length`.
-   */
+  /// Creates a new [RangeError] stating that [index] is not a valid index
+  /// into [indexable].
+  ///
+  /// An optional [name] can specify the argument name that has the
+  /// invalid value, and the [message] can override the default error
+  /// description.
+  ///
+  /// The [length] is the length of [indexable] at the time of the error.
+  /// If `length` is omitted, it defaults to `indexable.length`.
   factory RangeError.index(int index, dynamic indexable,
       [String? name, String? message, int? length]) = IndexError;
 
-  /**
-   * Check that an integer [value] lies in a specific interval.
-   *
-   * Throws if [value] is not in the interval.
-   * The interval is from [minValue] to [maxValue], both inclusive.
-   *
-   * If [name] or [message] are provided, they are used as the parameter
-   * name and message text of the thrown error.
-   *
-   * Returns [value] if it is in the interval.
-   */
+  /// Check that an integer [value] lies in a specific interval.
+  ///
+  /// Throws if [value] is not in the interval.
+  /// The interval is from [minValue] to [maxValue], both inclusive.
+  ///
+  /// If [name] or [message] are provided, they are used as the parameter
+  /// name and message text of the thrown error.
+  ///
+  /// Returns [value] if it is in the interval.
   static int checkValueInInterval(int value, int minValue, int maxValue,
       [String? name, String? message]) {
     if (value < minValue || value > maxValue) {
@@ -299,23 +279,21 @@
     return value;
   }
 
-  /**
-   * Check that [index] is a valid index into an indexable object.
-   *
-   * Throws if [index] is not a valid index into [indexable].
-   *
-   * An indexable object is one that has a `length` and a and index-operator
-   * `[]` that accepts an index if `0 <= index < length`.
-   *
-   * If [name] or [message] are provided, they are used as the parameter
-   * name and message text of the thrown error. If [name] is omitted, it
-   * defaults to `"index"`.
-   *
-   * If [length] is provided, it is used as the length of the indexable object,
-   * otherwise the length is found as `indexable.length`.
-   *
-   * Returns [index] if it is a valid index.
-   */
+  /// Check that [index] is a valid index into an indexable object.
+  ///
+  /// Throws if [index] is not a valid index into [indexable].
+  ///
+  /// An indexable object is one that has a `length` and a and index-operator
+  /// `[]` that accepts an index if `0 <= index < length`.
+  ///
+  /// If [name] or [message] are provided, they are used as the parameter
+  /// name and message text of the thrown error. If [name] is omitted, it
+  /// defaults to `"index"`.
+  ///
+  /// If [length] is provided, it is used as the length of the indexable object,
+  /// otherwise the length is found as `indexable.length`.
+  ///
+  /// Returns [index] if it is a valid index.
   static int checkValidIndex(int index, dynamic indexable,
       [String? name, int? length, String? message]) {
     length ??= (indexable.length as int);
@@ -327,22 +305,20 @@
     return index;
   }
 
-  /**
-   * Check that a range represents a slice of an indexable object.
-   *
-   * Throws if the range is not valid for an indexable object with
-   * the given [length].
-   * A range is valid for an indexable object with a given [length]
-   *
-   * if `0 <= [start] <= [end] <= [length]`.
-   * An `end` of `null` is considered equivalent to `length`.
-   *
-   * The [startName] and [endName] defaults to `"start"` and `"end"`,
-   * respectively.
-   *
-   * Returns the actual `end` value, which is `length` if `end` is `null`,
-   * and `end` otherwise.
-   */
+  /// Check that a range represents a slice of an indexable object.
+  ///
+  /// Throws if the range is not valid for an indexable object with
+  /// the given [length].
+  /// A range is valid for an indexable object with a given [length]
+  ///
+  /// if `0 <= [start] <= [end] <= [length]`.
+  /// An `end` of `null` is considered equivalent to `length`.
+  ///
+  /// The [startName] and [endName] defaults to `"start"` and `"end"`,
+  /// respectively.
+  ///
+  /// Returns the actual `end` value, which is `length` if `end` is `null`,
+  /// and `end` otherwise.
   static int checkValidRange(int start, int? end, int length,
       [String? startName, String? endName, String? message]) {
     // Comparing with `0` as receiver produces better dart2js type inference.
@@ -361,19 +337,19 @@
     return length;
   }
 
-  /**
-   * Check that an integer value is non-negative.
-   *
-   * Throws if the value is negative.
-   *
-   * If [name] or [message] are provided, they are used as the parameter
-   * name and message text of the thrown error. If [name] is omitted, it
-   * defaults to `index`.
-   *
-   * Returns [value] if it is not negative.
-   */
+  /// Check that an integer value is non-negative.
+  ///
+  /// Throws if the value is negative.
+  ///
+  /// If [name] or [message] are provided, they are used as the parameter
+  /// name and message text of the thrown error. If [name] is omitted, it
+  /// defaults to `index`.
+  ///
+  /// Returns [value] if it is not negative.
   static int checkNotNegative(int value, [String? name, String? message]) {
-    if (value < 0) throw RangeError.range(value, 0, null, name, message);
+    if (value < 0) {
+      throw RangeError.range(value, 0, null, name ?? "index", message);
+    }
     return value;
   }
 
@@ -402,28 +378,25 @@
   }
 }
 
-/**
- * A specialized [RangeError] used when an index is not in the range
- * `0..indexable.length-1`.
- *
- * Also contains the indexable object, its length at the time of the error,
- * and the invalid index itself.
- */
+/// A specialized [RangeError] used when an index is not in the range
+/// `0..indexable.length-1`.
+///
+/// Also contains the indexable object, its length at the time of the error,
+/// and the invalid index itself.
 class IndexError extends ArgumentError implements RangeError {
-  /** The indexable object that [invalidValue] was not a valid index into. */
+  /// The indexable object that [invalidValue] was not a valid index into.
   final indexable;
-  /** The length of [indexable] at the time of the error. */
+
+  /// The length of [indexable] at the time of the error.
   final int length;
 
-  /**
-   * Creates a new [IndexError] stating that [invalidValue] is not a valid index
-   * into [indexable].
-   *
-   * The [length] is the length of [indexable] at the time of the error.
-   * If `length` is omitted, it defaults to `indexable.length`.
-   *
-   * The message is used as part of the string representation of the error.
-   */
+  /// Creates a new [IndexError] stating that [invalidValue] is not a valid index
+  /// into [indexable].
+  ///
+  /// The [length] is the length of [indexable] at the time of the error.
+  /// If `length` is omitted, it defaults to `indexable.length`.
+  ///
+  /// The message is used as part of the string representation of the error.
   IndexError(int invalidValue, dynamic indexable,
       [String? name, String? message, int? length])
       : this.indexable = indexable,
@@ -448,14 +421,12 @@
   }
 }
 
-/**
- * Error thrown when control reaches the end of a switch case.
- *
- * The Dart specification requires this error to be thrown when
- * control reaches the end of a switch case (except the last case
- * of a switch) without meeting a break or similar end of the control
- * flow.
- */
+/// Error thrown when control reaches the end of a switch case.
+///
+/// The Dart specification requires this error to be thrown when
+/// control reaches the end of a switch case (except the last case
+/// of a switch) without meeting a break or similar end of the control
+/// flow.
 class FallThroughError extends Error {
   FallThroughError();
   @pragma("vm:entry-point")
@@ -464,9 +435,10 @@
   external String toString();
 }
 
-/**
- * Error thrown when trying to instantiate an abstract class.
- */
+/// Error thrown when trying to instantiate an abstract class.
+///
+/// No longer used in Dart 2 where it has become a compile-time error
+/// to call the constructor of an abstract class.
 class AbstractClassInstantiationError extends Error {
   final String _className;
   AbstractClassInstantiationError(String className) : _className = className;
@@ -474,46 +446,39 @@
   external String toString();
 }
 
-/**
- * Error thrown by the default implementation of [:noSuchMethod:] on [Object].
- */
+/// Error thrown by the default implementation of `noSuchMethod` on [Object].
 class NoSuchMethodError extends Error {
-  /**
-   * Create a [NoSuchMethodError] corresponding to a failed method call.
-   *
-   * The [receiver] is the receiver of the method call.
-   * That is, the object on which the method was attempted called.
-   *
-   * The [invocation] represents the method call that failed. It
-   * should not be `null`.
-   */
+  /// Create a [NoSuchMethodError] corresponding to a failed method call.
+  ///
+  /// The [receiver] is the receiver of the method call.
+  /// That is, the object on which the method was attempted called.
+  ///
+  /// The [invocation] represents the method call that failed.
   external NoSuchMethodError.withInvocation(
       Object? receiver, Invocation invocation);
 
   // Deprecated constructor to be removed after dart2js updates to the above.
-  /**
-   * Create a [NoSuchMethodError] corresponding to a failed method call.
-   *
-   * The [receiver] is the receiver of the method call.
-   * That is, the object on which the method was attempted called.
-   * If the receiver is `null`, it is interpreted as a call to a top-level
-   * function of a library.
-   *
-   * The [memberName] is a [Symbol] representing the name of the called method
-   * or accessor. It should not be `null`.
-   *
-   * The [positionalArguments] is a list of the positional arguments that the
-   * method was called with. If `null`, it is considered equivalent to the
-   * empty list.
-   *
-   * The [namedArguments] is a map from [Symbol]s to the values of named
-   * arguments that the method was called with. If null, it is considered
-   * equivalent to the empty map.
-   *
-   * This constructor does not handle type arguments.
-   * To include type variables, create an [Invocation] and use
-   * [NoSuchMethodError.withInvocation].
-   */
+  /// Create a [NoSuchMethodError] corresponding to a failed method call.
+  ///
+  /// The [receiver] is the receiver of the method call.
+  /// That is, the object on which the method was attempted called.
+  /// If the receiver is `null`, it is interpreted as a call to a top-level
+  /// function of a library.
+  ///
+  /// The [memberName] is a [Symbol] representing the name of the called method
+  /// or accessor.
+  ///
+  /// The [positionalArguments] is a list of the positional arguments that the
+  /// method was called with. If `null`, it is considered equivalent to the
+  /// empty list.
+  ///
+  /// The [namedArguments] is a map from [Symbol]s to the values of named
+  /// arguments that the method was called with. If `null`, it is considered
+  /// equivalent to the empty map.
+  ///
+  /// This constructor does not handle type arguments.
+  /// To include type variables, create an [Invocation] and use
+  /// [NoSuchMethodError.withInvocation].
   @Deprecated("Use NoSuchMethod.withInvocation instead")
   external NoSuchMethodError(Object? receiver, Symbol memberName,
       List? positionalArguments, Map<Symbol, dynamic>? namedArguments);
@@ -521,12 +486,10 @@
   external String toString();
 }
 
-/**
- * The operation was not allowed by the object.
- *
- * This [Error] is thrown when an instance cannot implement one of the methods
- * in its signature.
- */
+/// The operation was not allowed by the object.
+///
+/// This [Error] is thrown when an instance cannot implement one of the methods
+/// in its signature.
 @pragma("vm:entry-point")
 class UnsupportedError extends Error {
   final String? message;
@@ -535,16 +498,14 @@
   String toString() => "Unsupported operation: $message";
 }
 
-/**
- * Thrown by operations that have not been implemented yet.
- *
- * This [Error] is thrown by unfinished code that hasn't yet implemented
- * all the features it needs.
- *
- * If a class is not intending to implement the feature, it should throw
- * an [UnsupportedError] instead. This error is only intended for
- * use during development.
- */
+/// Thrown by operations that have not been implemented yet.
+///
+/// This [Error] is thrown by unfinished code that hasn't yet implemented
+/// all the features it needs.
+///
+/// If the class does not intend to implement the feature, it should throw
+/// an [UnsupportedError] instead. This error is only intended for
+/// use during development.
 class UnimplementedError extends Error implements UnsupportedError {
   final String? message;
   UnimplementedError([this.message]);
@@ -556,27 +517,31 @@
   }
 }
 
-/**
- * The operation was not allowed by the current state of the object.
- *
- * This is a generic error used for a variety of different erroneous
- * actions. The message should be descriptive.
- */
+/// The operation was not allowed by the current state of the object.
+///
+/// Should be used when this particular object is currenty in a state
+/// which doesn't support the requested operation, but other similar
+/// objects might, or the object might change its state to one which
+/// supports the operation.
+/// Example: Asking for `list.first` on a currently empty list.
+/// If the operation is never supported, consider using
+/// [UnsupportedError] instead.
+///
+/// This is a generic error used for a variety of different erroneous
+/// actions. The message should be descriptive.
 class StateError extends Error {
   final String message;
   StateError(this.message);
   String toString() => "Bad state: $message";
 }
 
-/**
- * Error occurring when a collection is modified during iteration.
- *
- * Some modifications may be allowed for some collections, so each collection
- * ([Iterable] or similar collection of values) should declare which operations
- * are allowed during an iteration.
- */
+/// Error occurring when a collection is modified during iteration.
+///
+/// Some modifications may be allowed for some collections, so each collection
+/// ([Iterable] or similar collection of values) should declare which operations
+/// are allowed during an iteration.
 class ConcurrentModificationError extends Error {
-  /** The object that was modified in an incompatible way. */
+  /// The object that was modified in an incompatible way.
   final Object? modifiedObject;
 
   ConcurrentModificationError([this.modifiedObject]);
@@ -590,6 +555,7 @@
   }
 }
 
+/// Error that the platform can use in case of memory shortage.
 class OutOfMemoryError implements Error {
   @pragma("vm:entry-point")
   const OutOfMemoryError();
@@ -598,6 +564,7 @@
   StackTrace? get stackTrace => null;
 }
 
+/// Error that the platform can use in case of stack overflow.
 class StackOverflowError implements Error {
   @pragma("vm:entry-point")
   const StackOverflowError();
@@ -606,13 +573,11 @@
   StackTrace? get stackTrace => null;
 }
 
-/**
- * Error thrown when a lazily initialized variable cannot be initialized.
- *
- * A static/library variable with an initializer expression is initialized
- * the first time it is read. If evaluating the initializer expression causes
- * another read of the variable, this error is thrown.
- */
+/// Error thrown when a lazily initialized variable cannot be initialized.
+///
+/// No longer used in null safe Dart code,
+/// replaced by late variables and [LateInitializationError].
+// TODO: Deprecate?
 class CyclicInitializationError extends Error {
   final String? variableName;
   @pragma("vm:entry-point")
@@ -624,20 +589,3 @@
         : "Reading static variable '$variableName' during its initialization";
   }
 }
-
-/**
- * Error thrown when a late variable is accessed in an invalid manner.
- *
- * A late variable must be initialized before it's read.
- * If a late variable has no initializer expression and has not
- * been written to, then reading it will throw a
- * late initialization error.
- *
- * A late final variable with no initializer expression may only
- * be written to once.
- * If it is written to again, the writing will throw a
- * late initialization error.
- */
-abstract class LateInitializationError extends Error {
-  factory LateInitializationError._() => throw UnsupportedError("");
-}
diff --git a/sdk/lib/core/exceptions.dart b/sdk/lib/core/exceptions.dart
index 7d76a66..5904ec5 100644
--- a/sdk/lib/core/exceptions.dart
+++ b/sdk/lib/core/exceptions.dart
@@ -6,23 +6,21 @@
 
 // Exceptions are thrown either by the VM or from Dart code.
 
-/**
- * A marker interface implemented by all core library exceptions.
- *
- * An [Exception] is intended to convey information to the user about a failure,
- * so that the error can be addressed programmatically. It is intended to be
- * caught, and it should contain useful data fields.
- *
- * Creating instances of [Exception] directly with `Exception("message")`
- * is discouraged in library code since it doesn't give users a precise
- * type they can catch. It may be reasonable to use instances of this
- * class in tests or during development.
- */
+/// A marker interface implemented by all core library exceptions.
+///
+/// An [Exception] is intended to convey information to the user about a failure,
+/// so that the error can be addressed programmatically. It is intended to be
+/// caught, and it should contain useful data fields.
+///
+/// Creating instances of [Exception] directly with `Exception("message")`
+/// is discouraged in library code since it doesn't give users a precise
+/// type they can catch. It may be reasonable to use instances of this
+/// class in tests or during development.
 abstract class Exception {
   factory Exception([var message]) => _Exception(message);
 }
 
-/** Default implementation of [Exception] which carries a message. */
+/// Default implementation of [Exception] which carries a message.
 class _Exception implements Exception {
   final dynamic message;
 
@@ -35,65 +33,53 @@
   }
 }
 
-/**
- * Exception thrown when a string or some other data does not have an expected
- * format and cannot be parsed or processed.
- */
+/// Exception thrown when a string or some other data does not have an expected
+/// format and cannot be parsed or processed.
 class FormatException implements Exception {
-  /**
-   * A message describing the format error.
-   */
+  /// A message describing the format error.
   final String message;
 
-  /**
-   * The actual source input which caused the error.
-   *
-   * This is usually a [String], but can be other types too.
-   * If it is a string, parts of it may be included in the [toString] message.
-   *
-   * The source is `null` if omitted or unknown.
-   */
+  /// The actual source input which caused the error.
+  ///
+  /// This is usually a [String], but can be other types too.
+  /// If it is a string, parts of it may be included in the [toString] message.
+  ///
+  /// The source is `null` if omitted or unknown.
   final dynamic source;
 
-  /**
-   * The offset in [source] where the error was detected.
-   *
-   * A zero-based offset into the source that marks the format error causing
-   * this exception to be created. If `source` is a string, this should be a
-   * string index in the range `0 <= offset <= source.length`.
-   *
-   * If input is a string, the [toString] method may represent this offset as
-   * a line and character position. The offset should be inside the string,
-   * or at the end of the string.
-   *
-   * May be omitted. If present, [source] should also be present if possible.
-   */
+  /// The offset in [source] where the error was detected.
+  ///
+  /// A zero-based offset into the source that marks the format error causing
+  /// this exception to be created. If `source` is a string, this should be a
+  /// string index in the range `0 <= offset <= source.length`.
+  ///
+  /// If input is a string, the [toString] method may represent this offset as
+  /// a line and character position. The offset should be inside the string,
+  /// or at the end of the string.
+  ///
+  /// May be omitted. If present, [source] should also be present if possible.
   final int? offset;
 
-  /**
-   * Creates a new FormatException with an optional error [message].
-   *
-   * Optionally also supply the actual [source] with the incorrect format,
-   * and the [offset] in the format where a problem was detected.
-   */
+  /// Creates a new `FormatException` with an optional error [message].
+  ///
+  /// Optionally also supply the actual [source] with the incorrect format,
+  /// and the [offset] in the format where a problem was detected.
   @pragma("vm:entry-point")
   const FormatException([this.message = "", this.source, this.offset]);
 
-  /**
-   * Returns a description of the format exception.
-   *
-   * The description always contains the [message].
-   *
-   * If [source] is present and is a string, the description will contain
-   * (at least a part of) the source.
-   * If [offset] is also provided, the part of the source included will
-   * contain that offset, and the offset will be marked.
-   *
-   * If the source is a string and it contains a line break before offset,
-   * only the line containing offset will be included, and its line number
-   * will also be part of the description. Line and character offsets are
-   * 1-based.
-   */
+  /// Returns a description of the format exception.
+  ///
+  /// The description always contains the [message].
+  ///
+  /// If [source] is present and is a string, the description will contain
+  /// (at least a part of) the source.
+  /// If [offset] is also provided, the part of the source included will
+  /// contain that offset, and the offset will be marked.
+  ///
+  /// If the source is a string and it contains a line break before offset,
+  /// only the line containing offset will be included, and its line number
+  /// will also be part of the description. Line and character offsets are
+  /// 1-based.
   String toString() {
     String report = "FormatException";
     Object? message = this.message;
@@ -179,6 +165,8 @@
 }
 
 // Exception thrown when doing integer division with a zero divisor.
+// TODO(30743): Should be removed, and division by zero should just throw an
+// [ArgumentError].
 class IntegerDivisionByZeroException implements Exception {
   @pragma("vm:entry-point")
   const IntegerDivisionByZeroException();
diff --git a/sdk/lib/core/expando.dart b/sdk/lib/core/expando.dart
index ac36b9b..d623579 100644
--- a/sdk/lib/core/expando.dart
+++ b/sdk/lib/core/expando.dart
@@ -4,59 +4,47 @@
 
 part of dart.core;
 
-/**
- * An [Expando] allows adding new properties to objects.
- *
- * Does not work on numbers, strings, booleans or `null`.
- *
- * An `Expando` does not hold on to the added property value after an object
- * becomes inaccessible.
- *
- * Since you can always create a new number that is identical to an existing
- * number, it means that an expando property on a number could never be
- * released. To avoid this, expando properties cannot be added to numbers.
- * The same argument applies to strings, booleans and `null`, which also have
- * literals that evaluate to identical values when they occur more than once.
- *
- * There is no restriction on other classes, even for compile time constant
- * objects. Be careful if adding expando properties to compile time constants,
- * since they will stay alive forever.
- */
+/// An [Expando] allows adding new properties to objects.
+///
+/// Does not work on numbers, strings, booleans or `null`.
+///
+/// An `Expando` does not hold on to the added property value after an object
+/// becomes inaccessible.
+///
+/// Since you can always create a new number that is identical to an existing
+/// number, it means that an expando property on a number could never be
+/// released. To avoid this, expando properties cannot be added to numbers.
+/// The same argument applies to strings, booleans and `null`, which also have
+/// literals that evaluate to identical values when they occur more than once.
+///
+/// There is no restriction on other classes, even for compile time constant
+/// objects. Be careful if adding expando properties to compile time constants,
+/// since they will stay alive forever.
 class Expando<T extends Object> {
-  /**
-   * The name of the this [Expando] as passed to the constructor. If
-   * no name was passed to the constructor, the name is `null`.
-   */
+  /// The name of the this [Expando] as passed to the constructor. If
+  /// no name was passed to the constructor, the name is `null`.
   final String? name;
 
-  /**
-   * Creates a new [Expando]. The optional name is only used for
-   * debugging purposes and creating two different [Expando]s with the
-   * same name yields two [Expando]s that work on different properties
-   * of the objects they are used on.
-   */
+  /// Creates a new [Expando]. The optional name is only used for
+  /// debugging purposes and creating two different [Expando]s with the
+  /// same name yields two [Expando]s that work on different properties
+  /// of the objects they are used on.
   external Expando([String? name]);
 
-  /**
-   * Expando toString method override.
-   */
-  String toString() => "Expando:${name.toString()}";
+  /// Expando toString method override.
+  String toString() => "Expando:$name";
 
-  /**
-   * Gets the value of this [Expando]'s property on the given
-   * object. If the object hasn't been expanded, the method returns
-   * `null`.
-   *
-   * The object must not be a number, a string, a boolean or null.
-   */
+  /// Gets the value of this [Expando]'s property on the given
+  /// object. If the object hasn't been expanded, the method returns
+  /// `null`.
+  ///
+  /// The object must not be a number, a string or a boolean.
   external T? operator [](Object object);
 
-  /**
-   * Sets the value of this [Expando]'s property on the given
-   * object. Properties can effectively be removed again by setting
-   * their value to null.
-   *
-   * The object must not be a number, a string, a boolean or null.
-   */
+  /// Sets the value of this [Expando]'s property on the given
+  /// object. Properties can effectively be removed again by setting
+  /// their value to `null`.
+  ///
+  /// The object must not be a number, a string or a boolean.
   external void operator []=(Object object, T? value);
 }
diff --git a/sdk/lib/core/function.dart b/sdk/lib/core/function.dart
index e560eb4..b0d7ca1 100644
--- a/sdk/lib/core/function.dart
+++ b/sdk/lib/core/function.dart
@@ -4,67 +4,59 @@
 
 part of dart.core;
 
-/**
- * The base class for all function types.
- *
- * The run-time type of a function object is subtype of a function type,
- * and as such, a subtype of [Function].
- */
+/// The base class for all function types.
+///
+/// The run-time type of a function object is subtype of a function type,
+/// and as such, a subtype of [Function].
 abstract class Function {
-  /**
-   * Dynamically call [function] with the specified arguments.
-   *
-   * Acts the same as calling function with positional arguments
-   * corresponding to the elements of [positionalArguments] and
-   * named arguments corresponding to the elements of [namedArguments].
-   *
-   * This includes giving the same errors if [function] isn't callable or
-   * if it expects different parameters.
-   *
-   * Example:
-   * ```
-   * Function.apply(foo, [1,2,3], {#f: 4, #g: 5});
-   * ```
-   *
-   * gives exactly the same result as
-   * ```
-   * foo(1, 2, 3, f: 4, g: 5).
-   * ```
-   *
-   * If [positionalArguments] is null, it's considered an empty list.
-   * If [namedArguments] is omitted or null, it is considered an empty map.
-   */
+  /// Dynamically call [function] with the specified arguments.
+  ///
+  /// Acts the same as calling function with positional arguments
+  /// corresponding to the elements of [positionalArguments] and
+  /// named arguments corresponding to the elements of [namedArguments].
+  ///
+  /// This includes giving the same errors if [function] isn't callable or
+  /// if it expects different parameters.
+  ///
+  /// Example:
+  /// ```
+  /// Function.apply(foo, [1, 2, 3], {#f: 4, #g: 5});
+  /// ```
+  ///
+  /// gives exactly the same result as
+  /// ```
+  /// foo(1, 2, 3, f: 4, g: 5).
+  /// ```
+  ///
+  /// If [positionalArguments] is null, it's considered an empty list.
+  /// If [namedArguments] is omitted or null, it is considered an empty map.
   external static apply(Function function, List<dynamic>? positionalArguments,
       [Map<Symbol, dynamic>? namedArguments]);
 
-  /**
-   * Returns a hash code value that is compatible with `operator==`.
-   */
+  /// A hash code value that is compatible with `operator==`.
   int get hashCode;
 
-  /**
-   * Test whether another object is equal to this function.
-   *
-   * Function objects are only equal to other function objects
-   * (an object satisfying `object is Function`),
-   * and never to non-function objects.
-   *
-   * Some function objects are considered equal by `==`
-   * because they are recognized as representing the "same function":
-   *
-   * - It is the same object. Static and top-level functions are compile time
-   *   constants when used as values, so referring to the same function twice
-   *   always give the same object, as does referring to a local function
-   *   declaration twice in the same scope where it was declared.
-   * - if they refer to the same member method extracted from the same object.
-   *   Repeatedly extracting an instance method of an object as a function value
-   *   gives equal, but not necessarily identical, function values.
-   *
-   * Different evaluations of function literals
-   * never give rise to equal function objects.
-   * Each time a function literal is evaluated,
-   * it creates a new function value that is not equal to any other function
-   * value, not even ones created by the same expression.
-   */
+  /// Test whether another object is equal to this function.
+  ///
+  /// Function objects are only equal to other function objects
+  /// (an object satisfying `object is Function`),
+  /// and never to non-function objects.
+  ///
+  /// Some function objects are considered equal by `==`
+  /// because they are recognized as representing the "same function":
+  ///
+  /// - It is the same object. Static and top-level functions are compile time
+  ///   constants when used as values, so referring to the same function twice
+  ///   always give the same object, as does referring to a local function
+  ///   declaration twice in the same scope where it was declared.
+  /// - if they refer to the same member method extracted from the same object.
+  ///   Repeatedly extracting an instance method of an object as a function value
+  ///   gives equal, but not necessarily identical, function values.
+  ///
+  /// Different evaluations of function literals
+  /// never give rise to equal function objects.
+  /// Each time a function literal is evaluated,
+  /// it creates a new function value that is not equal to any other function
+  /// value, not even ones created by the same expression.
   bool operator ==(Object other);
 }
diff --git a/sdk/lib/core/identical.dart b/sdk/lib/core/identical.dart
index 20d331e..a8bdedf 100644
--- a/sdk/lib/core/identical.dart
+++ b/sdk/lib/core/identical.dart
@@ -4,19 +4,15 @@
 
 part of dart.core;
 
-/**
- * Check whether two references are to the same object.
- */
+/// Check whether two references are to the same object.
 external bool identical(Object? a, Object? b);
 
-/**
- * Returns the identity hash code of `object`.
- *
- * Returns the same value as `object.hashCode` if [object] has not overridden
- * [Object.hashCode]. Returns the value that [Object.hashCode] would return
- * on this object, even if `hashCode` has been overridden.
- *
- * This hash code is compatible with [identical].
- */
+/// The identity hash code of [object].
+///
+/// Returns the value that the original [Object.hashCode] would return
+/// on this object, even if `hashCode` has been overridden.
+///
+/// This hash code is compatible with [identical],
+/// which just means that it's guaranteed to be stable over time.
 @pragma("vm:entry-point")
 external int identityHashCode(Object? object);
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index b1203ed..5d8f5d3 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -4,38 +4,34 @@
 
 part of dart.core;
 
-/**
- * An integer number.
- *
- * The default implementation of `int` is 64-bit two's complement integers
- * with operations that wrap to that range on overflow.
- *
- * **Note:** When compiling to JavaScript, integers are restricted to values
- * that can be represented exactly by double-precision floating point values.
- * The available integer values include all integers between -2^53 and 2^53,
- * and some integers with larger magnitude. That includes some integers larger
- * than 2^63.
- * The behavior of the operators and methods in the [int]
- * class therefore sometimes differs between the Dart VM and Dart code
- * compiled to JavaScript. For example, the bitwise operators truncate their
- * operands to 32-bit integers when compiled to JavaScript.
- *
- * Classes cannot extend, implement, or mix in `int`.
- */
+/// An integer number.
+///
+/// The default implementation of `int` is 64-bit two's complement integers
+/// with operations that wrap to that range on overflow.
+///
+/// **Note:** When compiling to JavaScript, integers are restricted to values
+/// that can be represented exactly by double-precision floating point values.
+/// The available integer values include all integers between -2^53 and 2^53,
+/// and some integers with larger magnitude. That includes some integers larger
+/// than 2^63.
+/// The behavior of the operators and methods in the [int]
+/// class therefore sometimes differs between the Dart VM and Dart code
+/// compiled to JavaScript. For example, the bitwise operators truncate their
+/// operands to 32-bit integers when compiled to JavaScript.
+///
+/// Classes cannot extend, implement, or mix in `int`.
 abstract class int extends num {
-  /**
-   * Returns the integer value of the given environment declaration [name].
-   *
-   * The result is the same as would be returned by:
-   * ```
-   * int.tryParse(const String.fromEnvironment(name, defaultValue: ""))
-   *     ?? defaultValue
-   * ```
-   * Example:
-   * ```
-   * const int.fromEnvironment("defaultPort", defaultValue: 80)
-   * ```
-   */
+  /// Returns the integer value of the given environment declaration [name].
+  ///
+  /// The result is the same as would be returned by:
+  /// ```
+  /// int.tryParse(const String.fromEnvironment(name, defaultValue: ""))
+  ///     ?? defaultValue
+  /// ```
+  /// Example:
+  /// ```
+  /// const int.fromEnvironment("defaultPort", defaultValue: 80)
+  /// ```
   // The .fromEnvironment() constructors are special in that we do not want
   // users to call them using "new". We prohibit that by giving them bodies
   // that throw, even though const constructors are not allowed to have bodies.
@@ -45,312 +41,272 @@
   external const factory int.fromEnvironment(String name,
       {int defaultValue = 0});
 
-  /**
-   * Bit-wise and operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with only the bits set that are set in
-   * both `this` and [other]
-   *
-   * If both operands are negative, the result is negative, otherwise
-   * the result is non-negative.
-   */
+  /// Bit-wise and operator.
+  ///
+  /// Treating both `this` and [other] as sufficiently large two's component
+  /// integers, the result is a number with only the bits set that are set in
+  /// both `this` and [other]
+  ///
+  /// If both operands are negative, the result is negative, otherwise
+  /// the result is non-negative.
   int operator &(int other);
 
-  /**
-   * Bit-wise or operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with the bits set that are set in either
-   * of `this` and [other]
-   *
-   * If both operands are non-negative, the result is non-negative,
-   * otherwise the result is negative.
-   */
+  /// Bit-wise or operator.
+  ///
+  /// Treating both `this` and [other] as sufficiently large two's component
+  /// integers, the result is a number with the bits set that are set in either
+  /// of `this` and [other]
+  ///
+  /// If both operands are non-negative, the result is non-negative,
+  /// otherwise the result is negative.
   int operator |(int other);
 
-  /**
-   * Bit-wise exclusive-or operator.
-   *
-   * Treating both `this` and [other] as sufficiently large two's component
-   * integers, the result is a number with the bits set that are set in one,
-   * but not both, of `this` and [other]
-   *
-   * If the operands have the same sign, the result is non-negative,
-   * otherwise the result is negative.
-   */
+  /// Bit-wise exclusive-or operator.
+  ///
+  /// Treating both `this` and [other] as sufficiently large two's component
+  /// integers, the result is a number with the bits set that are set in one,
+  /// but not both, of `this` and [other]
+  ///
+  /// If the operands have the same sign, the result is non-negative,
+  /// otherwise the result is negative.
   int operator ^(int other);
 
-  /**
-   * The bit-wise negate operator.
-   *
-   * Treating `this` as a sufficiently large two's component integer,
-   * the result is a number with the opposite bits set.
-   *
-   * This maps any integer `x` to `-x - 1`.
-   */
+  /// The bit-wise negate operator.
+  ///
+  /// Treating `this` as a sufficiently large two's component integer,
+  /// the result is a number with the opposite bits set.
+  ///
+  /// This maps any integer `x` to `-x - 1`.
   int operator ~();
 
-  /**
-   * Shift the bits of this integer to the left by [shiftAmount].
-   *
-   * Shifting to the left makes the number larger, effectively multiplying
-   * the number by `pow(2, shiftIndex)`.
-   *
-   * There is no limit on the size of the result. It may be relevant to
-   * limit intermediate values by using the "and" operator with a suitable
-   * mask.
-   *
-   * It is an error if [shiftAmount] is negative.
-   */
+  /// Shift the bits of this integer to the left by [shiftAmount].
+  ///
+  /// Shifting to the left makes the number larger, effectively multiplying
+  /// the number by `pow(2, shiftIndex)`.
+  ///
+  /// There is no limit on the size of the result. It may be relevant to
+  /// limit intermediate values by using the "and" operator with a suitable
+  /// mask.
+  ///
+  /// It is an error if [shiftAmount] is negative.
   int operator <<(int shiftAmount);
 
-  /**
-   * Shift the bits of this integer to the right by [shiftAmount].
-   *
-   * Shifting to the right makes the number smaller and drops the least
-   * significant bits, effectively doing an integer division by
-   *`pow(2, shiftIndex)`.
-   *
-   * It is an error if [shiftAmount] is negative.
-   */
+  /// Shift the bits of this integer to the right by [shiftAmount].
+  ///
+  /// Shifting to the right makes the number smaller and drops the least
+  /// significant bits, effectively doing an integer division by
+  ///`pow(2, shiftIndex)`.
+  ///
+  /// It is an error if [shiftAmount] is negative.
   int operator >>(int shiftAmount);
 
-  /**
-   * Returns this integer to the power of [exponent] modulo [modulus].
-   *
-   * The [exponent] must be non-negative and [modulus] must be
-   * positive.
-   */
+  /// Returns this integer to the power of [exponent] modulo [modulus].
+  ///
+  /// The [exponent] must be non-negative and [modulus] must be
+  /// positive.
   int modPow(int exponent, int modulus);
 
-  /**
-   * Returns the modular multiplicative inverse of this integer
-   * modulo [modulus].
-   *
-   * The [modulus] must be positive.
-   *
-   * It is an error if no modular inverse exists.
-   */
+  /// Returns the modular multiplicative inverse of this integer
+  /// modulo [modulus].
+  ///
+  /// The [modulus] must be positive.
+  ///
+  /// It is an error if no modular inverse exists.
   int modInverse(int modulus);
 
-  /**
-   * Returns the greatest common divisor of this integer and [other].
-   *
-   * If either number is non-zero, the result is the numerically greatest
-   * integer dividing both `this` and `other`.
-   *
-   * The greatest common divisor is independent of the order,
-   * so `x.gcd(y)` is  always the same as `y.gcd(x)`.
-   *
-   * For any integer `x`, `x.gcd(x)` is `x.abs()`.
-   *
-   * If both `this` and `other` is zero, the result is also zero.
-   */
+  /// Returns the greatest common divisor of this integer and [other].
+  ///
+  /// If either number is non-zero, the result is the numerically greatest
+  /// integer dividing both `this` and `other`.
+  ///
+  /// The greatest common divisor is independent of the order,
+  /// so `x.gcd(y)` is  always the same as `y.gcd(x)`.
+  ///
+  /// For any integer `x`, `x.gcd(x)` is `x.abs()`.
+  ///
+  /// If both `this` and `other` is zero, the result is also zero.
   int gcd(int other);
 
-  /** Returns true if and only if this integer is even. */
+  /// Returns true if and only if this integer is even.
   bool get isEven;
 
-  /** Returns true if and only if this integer is odd. */
+  /// Returns true if and only if this integer is odd.
   bool get isOdd;
 
-  /**
-   * Returns the minimum number of bits required to store this integer.
-   *
-   * The number of bits excludes the sign bit, which gives the natural length
-   * for non-negative (unsigned) values.  Negative values are complemented to
-   * return the bit position of the first bit that differs from the sign bit.
-   *
-   * To find the number of bits needed to store the value as a signed value,
-   * add one, i.e. use `x.bitLength + 1`.
-   * ```
-   * x.bitLength == (-x-1).bitLength
-   *
-   * 3.bitLength == 2;     // 00000011
-   * 2.bitLength == 2;     // 00000010
-   * 1.bitLength == 1;     // 00000001
-   * 0.bitLength == 0;     // 00000000
-   * (-1).bitLength == 0;  // 11111111
-   * (-2).bitLength == 1;  // 11111110
-   * (-3).bitLength == 2;  // 11111101
-   * (-4).bitLength == 2;  // 11111100
-   * ```
-   */
+  /// Returns the minimum number of bits required to store this integer.
+  ///
+  /// The number of bits excludes the sign bit, which gives the natural length
+  /// for non-negative (unsigned) values.  Negative values are complemented to
+  /// return the bit position of the first bit that differs from the sign bit.
+  ///
+  /// To find the number of bits needed to store the value as a signed value,
+  /// add one, i.e. use `x.bitLength + 1`.
+  /// ```
+  /// x.bitLength == (-x-1).bitLength
+  ///
+  /// 3.bitLength == 2;     // 00000011
+  /// 2.bitLength == 2;     // 00000010
+  /// 1.bitLength == 1;     // 00000001
+  /// 0.bitLength == 0;     // 00000000
+  /// (-1).bitLength == 0;  // 11111111
+  /// (-2).bitLength == 1;  // 11111110
+  /// (-3).bitLength == 2;  // 11111101
+  /// (-4).bitLength == 2;  // 11111100
+  /// ```
   int get bitLength;
 
-  /**
-   * Returns the least significant [width] bits of this integer as a
-   * non-negative number (i.e. unsigned representation).  The returned value has
-   * zeros in all bit positions higher than [width].
-   * ```
-   * (-1).toUnsigned(5) == 31   // 11111111  ->  00011111
-   * ```
-   * This operation can be used to simulate arithmetic from low level languages.
-   * For example, to increment an 8 bit quantity:
-   * ```
-   * q = (q + 1).toUnsigned(8);
-   * ```
-   * `q` will count from `0` up to `255` and then wrap around to `0`.
-   *
-   * If the input fits in [width] bits without truncation, the result is the
-   * same as the input.  The minimum width needed to avoid truncation of `x` is
-   * given by `x.bitLength`, i.e.
-   * ```
-   * x == x.toUnsigned(x.bitLength);
-   * ```
-   */
+  /// Returns the least significant [width] bits of this integer as a
+  /// non-negative number (i.e. unsigned representation).  The returned value has
+  /// zeros in all bit positions higher than [width].
+  /// ```
+  /// (-1).toUnsigned(5) == 31   // 11111111  ->  00011111
+  /// ```
+  /// This operation can be used to simulate arithmetic from low level languages.
+  /// For example, to increment an 8 bit quantity:
+  /// ```
+  /// q = (q + 1).toUnsigned(8);
+  /// ```
+  /// `q` will count from `0` up to `255` and then wrap around to `0`.
+  ///
+  /// If the input fits in [width] bits without truncation, the result is the
+  /// same as the input.  The minimum width needed to avoid truncation of `x` is
+  /// given by `x.bitLength`, i.e.
+  /// ```
+  /// x == x.toUnsigned(x.bitLength);
+  /// ```
   int toUnsigned(int width);
 
-  /**
-   * Returns the least significant [width] bits of this integer, extending the
-   * highest retained bit to the sign.  This is the same as truncating the value
-   * to fit in [width] bits using an signed 2-s complement representation.  The
-   * returned value has the same bit value in all positions higher than [width].
-   *
-   * ```
-   *                                V--sign bit-V
-   * 16.toSigned(5) == -16   //  00010000 -> 11110000
-   * 239.toSigned(5) == 15   //  11101111 -> 00001111
-   *                                ^           ^
-   * ```
-   * This operation can be used to simulate arithmetic from low level languages.
-   * For example, to increment an 8 bit signed quantity:
-   * ```
-   * q = (q + 1).toSigned(8);
-   * ```
-   * `q` will count from `0` up to `127`, wrap to `-128` and count back up to
-   * `127`.
-   *
-   * If the input value fits in [width] bits without truncation, the result is
-   * the same as the input.  The minimum width needed to avoid truncation of `x`
-   * is `x.bitLength + 1`, i.e.
-   * ```
-   * x == x.toSigned(x.bitLength + 1);
-   * ```
-   */
+  /// Returns the least significant [width] bits of this integer, extending the
+  /// highest retained bit to the sign.  This is the same as truncating the value
+  /// to fit in [width] bits using an signed 2-s complement representation.  The
+  /// returned value has the same bit value in all positions higher than [width].
+  ///
+  /// ```
+  ///                                V--sign bit-V
+  /// 16.toSigned(5) == -16   //  00010000 -> 11110000
+  /// 239.toSigned(5) == 15   //  11101111 -> 00001111
+  ///                                ^           ^
+  /// ```
+  /// This operation can be used to simulate arithmetic from low level languages.
+  /// For example, to increment an 8 bit signed quantity:
+  /// ```
+  /// q = (q + 1).toSigned(8);
+  /// ```
+  /// `q` will count from `0` up to `127`, wrap to `-128` and count back up to
+  /// `127`.
+  ///
+  /// If the input value fits in [width] bits without truncation, the result is
+  /// the same as the input.  The minimum width needed to avoid truncation of `x`
+  /// is `x.bitLength + 1`, i.e.
+  /// ```
+  /// x == x.toSigned(x.bitLength + 1);
+  /// ```
   int toSigned(int width);
 
-  /**
-   * Return the negative value of this integer.
-   *
-   * The result of negating an integer always has the opposite sign, except
-   * for zero, which is its own negation.
-   */
+  /// Return the negative value of this integer.
+  ///
+  /// The result of negating an integer always has the opposite sign, except
+  /// for zero, which is its own negation.
   int operator -();
 
-  /**
-   * Returns the absolute value of this integer.
-   *
-   * For any integer `x`, the result is the same as `x < 0 ? -x : x`.
-   */
+  /// Returns the absolute value of this integer.
+  ///
+  /// For any integer `x`, the result is the same as `x < 0 ? -x : x`.
   int abs();
 
-  /**
-   * Returns the sign of this integer.
-   *
-   * Returns 0 for zero, -1 for values less than zero and
-   * +1 for values greater than zero.
-   */
+  /// Returns the sign of this integer.
+  ///
+  /// Returns 0 for zero, -1 for values less than zero and
+  /// +1 for values greater than zero.
   int get sign;
 
-  /** Returns `this`. */
+  /// Returns `this`.
   int round();
 
-  /** Returns `this`. */
+  /// Returns `this`.
   int floor();
 
-  /** Returns `this`. */
+  /// Returns `this`.
   int ceil();
 
-  /** Returns `this`. */
+  /// Returns `this`.
   int truncate();
 
-  /** Returns `this.toDouble()`. */
+  /// Returns `this.toDouble()`.
   double roundToDouble();
 
-  /** Returns `this.toDouble()`. */
+  /// Returns `this.toDouble()`.
   double floorToDouble();
 
-  /** Returns `this.toDouble()`. */
+  /// Returns `this.toDouble()`.
   double ceilToDouble();
 
-  /** Returns `this.toDouble()`. */
+  /// Returns `this.toDouble()`.
   double truncateToDouble();
 
-  /**
-   * Returns a string representation of this integer.
-   *
-   * The returned string is parsable by [parse].
-   * For any `int` `i`, it is guaranteed that
-   * `i == int.parse(i.toString())`.
-   */
+  /// Returns a string representation of this integer.
+  ///
+  /// The returned string is parsable by [parse].
+  /// For any `int` `i`, it is guaranteed that
+  /// `i == int.parse(i.toString())`.
   String toString();
 
-  /**
-   * Converts [this] to a string representation in the given [radix].
-   *
-   * In the string representation, lower-case letters are used for digits above
-   * '9', with 'a' being 10 an 'z' being 35.
-   *
-   * The [radix] argument must be an integer in the range 2 to 36.
-   */
+  /// Converts [this] to a string representation in the given [radix].
+  ///
+  /// In the string representation, lower-case letters are used for digits above
+  /// '9', with 'a' being 10 an 'z' being 35.
+  ///
+  /// The [radix] argument must be an integer in the range 2 to 36.
   String toRadixString(int radix);
 
-  /**
-   * Parse [source] as a, possibly signed, integer literal and return its value.
-   *
-   * The [source] must be a non-empty sequence of base-[radix] digits,
-   * optionally prefixed with a minus or plus sign ('-' or '+').
-   * It must not be `null`.
-   *
-   * The [radix] must be in the range 2..36. The digits used are
-   * first the decimal digits 0..9, and then the letters 'a'..'z' with
-   * values 10 through 35. Also accepts upper-case letters with the same
-   * values as the lower-case ones.
-   *
-   * If no [radix] is given then it defaults to 10. In this case, the [source]
-   * digits may also start with `0x`, in which case the number is interpreted
-   * as a hexadecimal integer literal,
-   * When `int` is implemented by 64-bit signed integers,
-   * hexadecimal integer literals may represent values larger than
-   * 2<sup>63</sup>, in which case the value is parsed as if it is an
-   * *unsigned* number, and the resulting value is the corresponding
-   * signed integer value.
-   *
-   * For any int `n` and valid radix `r`, it is guaranteed that
-   * `n == int.parse(n.toRadixString(r), radix: r)`.
-   *
-   * If the [source] string does not contain a valid integer literal,
-   * optionally prefixed by a sign, a [FormatException] is thrown
-   * (unless the deprecated [onError] parameter is used, see below).
-   *
-   * Instead of throwing and immediately catching the [FormatException],
-   * instead use [tryParse] to handle a parsing error.
-   * Example:
-   * ```dart
-   * var value = int.tryParse(text);
-   * if (value == null) ... handle the problem
-   * ```
-   *
-   * The [onError] parameter is deprecated and will be removed.
-   * Instead of `int.parse(string, onError: (string) => ...)`,
-   * you should use `int.tryParse(string) ?? (...)`.
-   *
-   * When the source string is not valid and [onError] is provided,
-   * whenever a [FormatException] would be thrown,
-   * [onError] is instead called with [source] as argument,
-   * and the result of that call is returned by [parse].
-   */
+  /// Parse [source] as a, possibly signed, integer literal and return its value.
+  ///
+  /// The [source] must be a non-empty sequence of base-[radix] digits,
+  /// optionally prefixed with a minus or plus sign ('-' or '+').
+  ///
+  /// The [radix] must be in the range 2..36. The digits used are
+  /// first the decimal digits 0..9, and then the letters 'a'..'z' with
+  /// values 10 through 35. Also accepts upper-case letters with the same
+  /// values as the lower-case ones.
+  ///
+  /// If no [radix] is given then it defaults to 10. In this case, the [source]
+  /// digits may also start with `0x`, in which case the number is interpreted
+  /// as a hexadecimal integer literal,
+  /// When `int` is implemented by 64-bit signed integers,
+  /// hexadecimal integer literals may represent values larger than
+  /// 2<sup>63</sup>, in which case the value is parsed as if it is an
+  /// *unsigned* number, and the resulting value is the corresponding
+  /// signed integer value.
+  ///
+  /// For any int `n` and valid radix `r`, it is guaranteed that
+  /// `n == int.parse(n.toRadixString(r), radix: r)`.
+  ///
+  /// If the [source] string does not contain a valid integer literal,
+  /// optionally prefixed by a sign, a [FormatException] is thrown
+  /// (unless the deprecated [onError] parameter is used, see below).
+  ///
+  /// Instead of throwing and immediately catching the [FormatException],
+  /// instead use [tryParse] to handle a parsing error.
+  /// Example:
+  /// ```dart
+  /// var value = int.tryParse(text);
+  /// if (value == null) ... handle the problem
+  /// ```
+  ///
+  /// The [onError] parameter is deprecated and will be removed.
+  /// Instead of `int.parse(string, onError: (string) => ...)`,
+  /// you should use `int.tryParse(string) ?? (...)`.
+  ///
+  /// When the source string is not valid and [onError] is provided,
+  /// whenever a [FormatException] would be thrown,
+  /// [onError] is instead called with [source] as argument,
+  /// and the result of that call is returned by [parse].
   external static int parse(String source,
       {int? radix, @deprecated int onError(String source)?});
 
-  /**
-   * Parse [source] as a, possibly signed, integer literal and return its value.
-   *
-   * Like [parse] except that this function returns `null` where a
-   * similar call to [parse] would throw a [FormatException],
-   * and the [source] must still not be `null`.
-   */
+  /// Parse [source] as a, possibly signed, integer literal.
+  ///
+  /// Like [parse] except that this function returns `null` where a
+  /// similar call to [parse] would throw a [FormatException].
   external static int? tryParse(String source, {int? radix});
 }
diff --git a/sdk/lib/core/invocation.dart b/sdk/lib/core/invocation.dart
index 7d28cea..8ffe56d 100644
--- a/sdk/lib/core/invocation.dart
+++ b/sdk/lib/core/invocation.dart
@@ -4,110 +4,90 @@
 
 part of dart.core;
 
-/**
- * Representation of the invocation of a member on an object.
- *
- * This is the type of objects passed to [Object.noSuchMethod] when
- * an object doesn't support the member invocation that was attempted
- * on it.
- */
+/// Representation of the invocation of a member on an object.
+///
+/// This is the type of objects passed to [Object.noSuchMethod] when
+/// an object doesn't support the member invocation that was attempted
+/// on it.
 abstract class Invocation {
   Invocation();
 
-  /**
-   * Creates an invocation corresponding to a method invocation.
-   *
-   * The method invocation has no type arguments.
-   * If the named arguments are omitted, they default to no named arguments.
-   */
+  /// Creates an invocation corresponding to a method invocation.
+  ///
+  /// The method invocation has no type arguments.
+  /// If the named arguments are omitted, they default to no named arguments.
   factory Invocation.method(
           Symbol memberName, Iterable<Object?>? positionalArguments,
           [Map<Symbol, Object?>? namedArguments]) =>
       _Invocation.method(memberName, null, positionalArguments, namedArguments);
 
-  /**
-   * Creates an invocation corresponding to a generic method invocation.
-   *
-   * If [typeArguments] is `null` or empty, the constructor is equivalent to
-   * calling [Invocation.method] with the remaining arguments.
-   * All the individual type arguments must be non-null.
-   *
-   * If the named arguments are omitted, they default to no named arguments.
-   */
+  /// Creates an invocation corresponding to a generic method invocation.
+  ///
+  /// If [typeArguments] is `null` or empty, the constructor is equivalent to
+  /// calling [Invocation.method] with the remaining arguments.
+  /// All the individual type arguments must be non-null.
+  ///
+  /// If the named arguments are omitted, they default to no named arguments.
   factory Invocation.genericMethod(Symbol memberName,
           Iterable<Type>? typeArguments, Iterable<Object?>? positionalArguments,
           [Map<Symbol, Object?>? namedArguments]) =>
       _Invocation.method(
           memberName, typeArguments, positionalArguments, namedArguments);
 
-  /**
-   * Creates an invocation corresponding to a getter invocation.
-   */
+  /// Creates an invocation corresponding to a getter invocation.
   factory Invocation.getter(Symbol name) = _Invocation.getter;
 
-  /**
-   * Creates an invocation corresponding to a setter invocation.
-   *
-   * This constructor accepts any [Symbol] as [memberName], but remember that
-   * *actual setter names* end in `=`, so the invocation corresponding
-   * to `object.member = value` is
-   * ```dart
-   * Invocation.setter(const Symbol("member="), value)
-   * ```
-   */
+  /// Creates an invocation corresponding to a setter invocation.
+  ///
+  /// This constructor accepts any [Symbol] as [memberName], but remember that
+  /// *actual setter names* end in `=`, so the invocation corresponding
+  /// to `object.member = value` is
+  /// ```dart
+  /// Invocation.setter(const Symbol("member="), value)
+  /// ```
   factory Invocation.setter(Symbol memberName, Object? argument) =
       _Invocation.setter;
 
-  /** The name of the invoked member. */
+  /// The name of the invoked member.
   Symbol get memberName;
 
-  /**
-   * An unmodifiable view of the type arguments of the call.
-   *
-   * If the member is a getter, setter or operator,
-   * the type argument list is always empty.
-   */
+  /// An unmodifiable view of the type arguments of the call.
+  ///
+  /// If the member is a getter, setter or operator,
+  /// the type argument list is always empty.
   List<Type> get typeArguments => const <Type>[];
 
-  /**
-   * An unmodifiable view of the positional arguments of the call.
-   *
-   * If the member is a getter, the positional arguments list is
-   * always empty.
-   */
+  /// An unmodifiable view of the positional arguments of the call.
+  ///
+  /// If the member is a getter, the positional arguments list is
+  /// always empty.
   List<dynamic> get positionalArguments;
 
-  /**
-   * An unmodifiable view of the named arguments of the call.
-   *
-   * If the member is a getter, setter or operator,
-   * the named arguments map is always empty.
-   */
+  /// An unmodifiable view of the named arguments of the call.
+  ///
+  /// If the member is a getter, setter or operator,
+  /// the named arguments map is always empty.
   Map<Symbol, dynamic> get namedArguments;
 
-  /** Whether the invocation was a method call. */
+  /// Whether the invocation was a method call.
   bool get isMethod;
 
-  /**
-   * Whether the invocation was a getter call.
-   * If so, all three types of arguments lists are empty.
-   */
+  /// Whether the invocation was a getter call.
+  /// If so, all three types of arguments lists are empty.
   bool get isGetter;
 
-  /**
-   * Whether the invocation was a setter call.
-   *
-   * If so, [positionalArguments] has exactly one positional
-   * argument, [namedArguments] is empty, and typeArguments is
-   * empty.
-   */
+  /// Whether the invocation was a setter call.
+  ///
+  /// If so, [positionalArguments] has exactly one positional
+  /// argument, [namedArguments] is empty, and typeArguments is
+  /// empty.
   bool get isSetter;
 
-  /** Whether the invocation was a getter or a setter call. */
+  /// Whether the invocation was a getter or a setter call.
   bool get isAccessor => isGetter || isSetter;
 }
 
-/** Implementation of [Invocation] used by its factory constructors. */
+/// Implementation of [Invocation] used by its factory constructors.
 class _Invocation implements Invocation {
   final Symbol memberName;
   final List<Type> typeArguments;
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 7482058..423de13 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -4,178 +4,164 @@
 
 part of dart.core;
 
-/**
- * A collection of values, or "elements", that can be accessed sequentially.
- *
- * The elements of the iterable are accessed by getting an [Iterator]
- * using the [iterator] getter, and using it to step through the values.
- * Stepping with the iterator is done by calling [Iterator.moveNext],
- * and if the call returns `true`,
- * the iterator has now moved to the next element,
- * which is then available as [Iterator.current].
- * If the call returns `false`, there are no more elements.
- * The [Iterator.current] value must only be used when the most
- * recent call to [Iterator.moveNext] has returned `true`.
- * If it is used before calling [Iterator.moveNext] the first time
- * on an iterator, or after a call has returned false or has thrown an error,
- * reading [Iterator.current] may throw or may return an arbitrary value.
- *
- * You can create more than one iterator from the same `Iterable`.
- * Each time `iterator` is read, it returns a new iterator,
- * and different iterators can be stepped through independently,
- * each giving access to all the elements of the iterable.
- * The iterators of the same iterable *should* provide the same values
- * in the same order (unless the underlying collection is modified between
- * the iterations, which some collections allow).
- *
- * You can also iterate over the elements of an `Iterable`
- * using the for-in loop construct, which uses the `iterator` getter behind the
- * scenes.
- * For example, you can iterate over all of the keys of a [Map],
- * because `Map` keys are iterable.
- *
- *     Map kidsBooks = {'Matilda': 'Roald Dahl',
- *                      'Green Eggs and Ham': 'Dr Seuss',
- *                      'Where the Wild Things Are': 'Maurice Sendak'};
- *     for (var book in kidsBooks.keys) {
- *       print('$book was written by ${kidsBooks[book]}');
- *     }
- *
- * The [List] and [Set] classes are both `Iterable`,
- * as are most classes in the `dart:collection` library.
- *
- * Some [Iterable] collections can be modified.
- * Adding an element to a `List` or `Set` will change which elements it
- * contains, and adding a new key to a `Map` changes the elements of [Map.keys].
- * Iterators created after the change will provide the new elements, and may
- * or may not preserve the order of existing elements
- * (for example, a [HashSet] may completely change its order when a single
- * element is added).
- *
- * Changing a collection *while* it is being iterated
- * is generally *not* allowed.
- * Doing so will break the iteration, which is typically signalled
- * by throwing a [ConcurrentModificationError]
- * the next time [Iterator.moveNext] is called.
- * The current value of [Iterator.current] getter
- * should not be affected by the change in the collection,
- * the `current` value was set by the previous call to [Iterator.moveNext].
- *
- * Some iterables compute their elements dynamically every time they are
- * iterated, like the one returned by [Iterable.generate] or the iterable
- * returned by a `sync*` generator function. If the computation doesn't depend
- * on other objects that may change, then the generated sequence should be
- * the same one every time it's iterated.
- *
- * The members of `Iterable`, other than `iterator` itself,
- * work by looking at the elements of the iterable.
- * This can be implemented by running through the [iterator], but some classes
- * may have more efficient ways of finding the result
- * (like [last] or [length] on a [List], or [contains] on a [Set]).
- *
- * The methods that return another `Iterable` (like [map] and [where])
- * are all *lazy* - they will iterate the original (as necessary)
- * every time the returned iterable is iterated, and not before.
- *
- * Since an iterable may be iterated more than once, it's not recommended to
- * have detectable side-effects in the iterator.
- * For methods like [map] and [where], the returned iterable will execute the
- * argument function on every iteration, so those functions should also not
- * have side effects.
- */
+/// A collection of values, or "elements", that can be accessed sequentially.
+///
+/// The elements of the iterable are accessed by getting an [Iterator]
+/// using the [iterator] getter, and using it to step through the values.
+/// Stepping with the iterator is done by calling [Iterator.moveNext],
+/// and if the call returns `true`,
+/// the iterator has now moved to the next element,
+/// which is then available as [Iterator.current].
+/// If the call returns `false`, there are no more elements.
+/// The [Iterator.current] value must only be used when the most
+/// recent call to [Iterator.moveNext] has returned `true`.
+/// If it is used before calling [Iterator.moveNext] the first time
+/// on an iterator, or after a call has returned false or has thrown an error,
+/// reading [Iterator.current] may throw or may return an arbitrary value.
+///
+/// You can create more than one iterator from the same `Iterable`.
+/// Each time `iterator` is read, it returns a new iterator,
+/// and different iterators can be stepped through independently,
+/// each giving access to all the elements of the iterable.
+/// The iterators of the same iterable *should* provide the same values
+/// in the same order (unless the underlying collection is modified between
+/// the iterations, which some collections allow).
+///
+/// You can also iterate over the elements of an `Iterable`
+/// using the for-in loop construct, which uses the `iterator` getter behind the
+/// scenes.
+/// For example, you can iterate over all of the keys of a [Map],
+/// because `Map` keys are iterable.
+/// ```dart
+/// var kidsBooks = {'Matilda': 'Roald Dahl',
+///                  'Green Eggs and Ham': 'Dr Seuss',
+///                  'Where the Wild Things Are': 'Maurice Sendak'};
+/// for (var book in kidsBooks.keys) {
+///   print('$book was written by ${kidsBooks[book]}');
+/// }
+/// ```
+/// The [List] and [Set] classes are both `Iterable`,
+/// as are most classes in the `dart:collection` library.
+///
+/// Some [Iterable] collections can be modified.
+/// Adding an element to a `List` or `Set` will change which elements it
+/// contains, and adding a new key to a `Map` changes the elements of [Map.keys].
+/// Iterators created after the change will provide the new elements, and may
+/// or may not preserve the order of existing elements
+/// (for example, a [HashSet] may completely change its order when a single
+/// element is added).
+///
+/// Changing a collection *while* it is being iterated
+/// is generally *not* allowed.
+/// Doing so will break the iteration, which is typically signalled
+/// by throwing a [ConcurrentModificationError]
+/// the next time [Iterator.moveNext] is called.
+/// The current value of [Iterator.current] getter
+/// should not be affected by the change in the collection,
+/// the `current` value was set by the previous call to [Iterator.moveNext].
+///
+/// Some iterables compute their elements dynamically every time they are
+/// iterated, like the one returned by [Iterable.generate] or the iterable
+/// returned by a `sync*` generator function. If the computation doesn't depend
+/// on other objects that may change, then the generated sequence should be
+/// the same one every time it's iterated.
+///
+/// The members of `Iterable`, other than `iterator` itself,
+/// work by looking at the elements of the iterable.
+/// This can be implemented by running through the [iterator], but some classes
+/// may have more efficient ways of finding the result
+/// (like [last] or [length] on a [List], or [contains] on a [Set]).
+///
+/// The methods that return another `Iterable` (like [map] and [where])
+/// are all *lazy* - they will iterate the original (as necessary)
+/// every time the returned iterable is iterated, and not before.
+///
+/// Since an iterable may be iterated more than once, it's not recommended to
+/// have detectable side-effects in the iterator.
+/// For methods like [map] and [where], the returned iterable will execute the
+/// argument function on every iteration, so those functions should also not
+/// have side effects.
 abstract class Iterable<E> {
   // TODO(lrn): When we allow forwarding const constructors through
   // mixin applications, make this class implement [IterableMixin].
   const Iterable();
 
-  /**
-   * Creates an `Iterable` which generates its elements dynamically.
-   *
-   * The generated iterable has [count] elements,
-   * and the element at index `n` is computed by calling `generator(n)`.
-   * Values are not cached, so each iteration computes the values again.
-   *
-   * If [generator] is omitted, it defaults to an identity function
-   * on integers `(int x) => x`, so it may only be omitted if the type
-   * parameter allows integer values. That is, if [E] is a super-type
-   * of [int].
-   *
-   * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to
-   * `const [0, ..., n - 1].map(generator)`.
-   */
+  /// Creates an `Iterable` which generates its elements dynamically.
+  ///
+  /// The generated iterable has [count] elements,
+  /// and the element at index `n` is computed by calling `generator(n)`.
+  /// Values are not cached, so each iteration computes the values again.
+  ///
+  /// If [generator] is omitted, it defaults to an identity function
+  /// on integers `(int x) => x`, so it may only be omitted if the type
+  /// parameter allows integer values. That is, if [E] is a super-type
+  /// of [int].
+  ///
+  /// As an `Iterable`, `Iterable.generate(n, generator))` is equivalent to
+  /// `const [0, ..., n - 1].map(generator)`.
   factory Iterable.generate(int count, [E generator(int index)?]) {
     if (count <= 0) return EmptyIterable<E>();
     return _GeneratorIterable<E>(count, generator);
   }
 
-  /**
-   * Creates an empty iterable.
-   *
-   * The empty iterable has no elements, and iterating it always stops
-   * immediately.
-   */
+  /// Creates an empty iterable.
+  ///
+  /// The empty iterable has no elements, and iterating it always stops
+  /// immediately.
   const factory Iterable.empty() = EmptyIterable<E>;
 
-  /**
-   * Adapts [source] to be an `Iterable<T>`.
-   *
-   * Any time the iterable would produce an element that is not a [T],
-   * the element access will throw. If all elements of [source] are actually
-   * instances of [T], or if only elements that are actually instances of [T]
-   * are accessed, then the resulting iterable can be used as an `Iterable<T>`.
-   */
+  /// Adapts [source] to be an `Iterable<T>`.
+  ///
+  /// Any time the iterable would produce an element that is not a [T],
+  /// the element access will throw. If all elements of [source] are actually
+  /// instances of [T], or if only elements that are actually instances of [T]
+  /// are accessed, then the resulting iterable can be used as an `Iterable<T>`.
   static Iterable<T> castFrom<S, T>(Iterable<S> source) =>
       CastIterable<S, T>(source);
 
-  /**
-   * Returns a new `Iterator` that allows iterating the elements of this
-   * `Iterable`.
-   *
-   * Iterable classes may specify the iteration order of their elements
-   * (for example [List] always iterate in index order),
-   * or they may leave it unspecified (for example a hash-based [Set]
-   * may iterate in any order).
-   *
-   * Each time `iterator` is read, it returns a new iterator,
-   * which can be used to iterate through all the elements again.
-   * The iterators of the same iterable can be stepped through independently,
-   * but should return the same elements in the same order,
-   * as long as the underlying collection isn't changed.
-   *
-   * Modifying the collection may cause new iterators to produce
-   * different elements, and may change the order of existing elements.
-   * A [List] specifies its iteration order precisely,
-   * so modifying the list changes the iteration order predictably.
-   * A hash-based [Set] may change its iteration order completely
-   * when adding a new element to the set.
-   *
-   * Modifying the underlying collection after creating the new iterator
-   * may cause an error the next time [Iterator.moveNext] is called
-   * on that iterator.
-   * Any *modifiable* iterable class should specify which operations will
-   * break iteration.
-   */
+  /// Returns a new `Iterator` that allows iterating the elements of this
+  /// `Iterable`.
+  ///
+  /// Iterable classes may specify the iteration order of their elements
+  /// (for example [List] always iterate in index order),
+  /// or they may leave it unspecified (for example a hash-based [Set]
+  /// may iterate in any order).
+  ///
+  /// Each time `iterator` is read, it returns a new iterator,
+  /// which can be used to iterate through all the elements again.
+  /// The iterators of the same iterable can be stepped through independently,
+  /// but should return the same elements in the same order,
+  /// as long as the underlying collection isn't changed.
+  ///
+  /// Modifying the collection may cause new iterators to produce
+  /// different elements, and may change the order of existing elements.
+  /// A [List] specifies its iteration order precisely,
+  /// so modifying the list changes the iteration order predictably.
+  /// A hash-based [Set] may change its iteration order completely
+  /// when adding a new element to the set.
+  ///
+  /// Modifying the underlying collection after creating the new iterator
+  /// may cause an error the next time [Iterator.moveNext] is called
+  /// on that iterator.
+  /// Any *modifiable* iterable class should specify which operations will
+  /// break iteration.
   Iterator<E> get iterator;
 
-  /**
-   * Provides a view of this iterable as an iterable of [R] instances.
-   *
-   * If this iterable only contains instances of [R], all operations
-   * will work correctly. If any operation tries to access an element
-   * that is not an instance of [R], the access will throw instead.
-   *
-   * When the returned iterable creates a new object that depends on
-   * the type [R], e.g., from [toList], it will have exactly the type [R].
-   */
+  /// Provides a view of this iterable as an iterable of [R] instances.
+  ///
+  /// If this iterable only contains instances of [R], all operations
+  /// will work correctly. If any operation tries to access an element
+  /// that is not an instance of [R], the access will throw instead.
+  ///
+  /// When the returned iterable creates a new object that depends on
+  /// the type [R], e.g., from [toList], it will have exactly the type [R].
   Iterable<R> cast<R>() => Iterable.castFrom<E, R>(this);
 
-  /**
-   * Returns the lazy concatenation of this iterable and [other].
-   *
-   * The returned iterable will provide the same elements as this iterable,
-   * and, after that, the elements of [other], in the same order as in the
-   * original iterables.
-   */
+  /// Returns the lazy concatenation of this iterable and [other].
+  ///
+  /// The returned iterable will provide the same elements as this iterable,
+  /// and, after that, the elements of [other], in the same order as in the
+  /// original iterables.
   Iterable<E> followedBy(Iterable<E> other) {
     var self = this; // TODO(lrn): Remove when we can promote `this`.
     if (self is EfficientLengthIterable<E>) {
@@ -184,90 +170,80 @@
     return FollowedByIterable<E>(this, other);
   }
 
-  /**
-   * Returns a new lazy [Iterable] with elements that are created by
-   * calling `f` on each element of this `Iterable` in iteration order.
-   *
-   * This method returns a view of the mapped elements. As long as the
-   * returned [Iterable] is not iterated over, the supplied function [f] will
-   * not be invoked. The transformed elements will not be cached. Iterating
-   * multiple times over the returned [Iterable] will invoke the supplied
-   * function [f] multiple times on the same element.
-   *
-   * Methods on the returned iterable are allowed to omit calling `f`
-   * on any element where the result isn't needed.
-   * For example, [elementAt] may call `f` only once.
-   */
+  /// Returns a new lazy [Iterable] with elements that are created by
+  /// calling `f` on each element of this `Iterable` in iteration order.
+  ///
+  /// This method returns a view of the mapped elements. As long as the
+  /// returned [Iterable] is not iterated over, the supplied function [f] will
+  /// not be invoked. The transformed elements will not be cached. Iterating
+  /// multiple times over the returned [Iterable] will invoke the supplied
+  /// function [f] multiple times on the same element.
+  ///
+  /// Methods on the returned iterable are allowed to omit calling `f`
+  /// on any element where the result isn't needed.
+  /// For example, [elementAt] may call `f` only once.
   Iterable<T> map<T>(T f(E e)) => MappedIterable<E, T>(this, f);
 
-  /**
-   * Returns a new lazy [Iterable] with all elements that satisfy the
-   * predicate [test].
-   *
-   * The matching elements have the same order in the returned iterable
-   * as they have in [iterator].
-   *
-   * This method returns a view of the mapped elements.
-   * As long as the returned [Iterable] is not iterated over,
-   * the supplied function [test] will not be invoked.
-   * Iterating will not cache results, and thus iterating multiple times over
-   * the returned [Iterable] may invoke the supplied
-   * function [test] multiple times on the same element.
-   */
+  /// Returns a new lazy [Iterable] with all elements that satisfy the
+  /// predicate [test].
+  ///
+  /// The matching elements have the same order in the returned iterable
+  /// as they have in [iterator].
+  ///
+  /// This method returns a view of the mapped elements.
+  /// As long as the returned [Iterable] is not iterated over,
+  /// the supplied function [test] will not be invoked.
+  /// Iterating will not cache results, and thus iterating multiple times over
+  /// the returned [Iterable] may invoke the supplied
+  /// function [test] multiple times on the same element.
   Iterable<E> where(bool test(E element)) => WhereIterable<E>(this, test);
 
-  /**
-   * Returns a new lazy [Iterable] with all elements that have type [T].
-   *
-   * The matching elements have the same order in the returned iterable
-   * as they have in [iterator].
-   *
-   * This method returns a view of the mapped elements.
-   * Iterating will not cache results, and thus iterating multiple times over
-   * the returned [Iterable] may yield different results,
-   * if the underlying elements change between iterations.
-   */
+  /// Returns a new lazy [Iterable] with all elements that have type [T].
+  ///
+  /// The matching elements have the same order in the returned iterable
+  /// as they have in [iterator].
+  ///
+  /// This method returns a view of the mapped elements.
+  /// Iterating will not cache results, and thus iterating multiple times over
+  /// the returned [Iterable] may yield different results,
+  /// if the underlying elements change between iterations.
   Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
 
-  /**
-   * Expands each element of this [Iterable] into zero or more elements.
-   *
-   * The resulting Iterable runs through the elements returned
-   * by [f] for each element of this, in iteration order.
-   *
-   * The returned [Iterable] is lazy, and calls [f] for each element
-   * of this every time it's iterated.
-   *
-   * Example:
-   *
-   *     var pairs = [[1, 2], [3, 4]];
-   *     var flattened = pairs.expand((pair) => pair).toList();
-   *     print(flattened); // => [1, 2, 3, 4];
-   *
-   *     var input = [1, 2, 3];
-   *     var duplicated = input.expand((i) => [i, i]).toList();
-   *     print(duplicated); // => [1, 1, 2, 2, 3, 3]
-   *
-   */
+  /// Expands each element of this [Iterable] into zero or more elements.
+  ///
+  /// The resulting Iterable runs through the elements returned
+  /// by [f] for each element of this, in iteration order.
+  ///
+  /// The returned [Iterable] is lazy, and calls [f] for each element
+  /// of this every time it's iterated.
+  ///
+  /// Example:
+  /// ```dart
+  /// var pairs = [[1, 2], [3, 4]];
+  /// var flattened = pairs.expand((pair) => pair).toList();
+  /// print(flattened); // => [1, 2, 3, 4];
+  ///
+  /// var input = [1, 2, 3];
+  /// var duplicated = input.expand((i) => [i, i]).toList();
+  /// print(duplicated); // => [1, 1, 2, 2, 3, 3]
+  /// ```
   Iterable<T> expand<T>(Iterable<T> f(E element)) =>
       ExpandIterable<E, T>(this, f);
 
-  /**
-   * Returns true if the collection contains an element equal to [element].
-   *
-   * This operation will check each element in order for being equal to
-   * [element], unless it has a more efficient way to find an element
-   * equal to [element].
-   *
-   * The equality used to determine whether [element] is equal to an element of
-   * the iterable defaults to the [Object.==] of the element.
-   *
-   * Some types of iterable may have a different equality used for its elements.
-   * For example, a [Set] may have a custom equality
-   * (see [Set.identity]) that its `contains` uses.
-   * Likewise the `Iterable` returned by a [Map.keys] call
-   * should use the same equality that the `Map` uses for keys.
-   */
+  /// Whether the collection contains an element equal to [element].
+  ///
+  /// This operation will check each element in order for being equal to
+  /// [element], unless it has a more efficient way to find an element
+  /// equal to [element].
+  ///
+  /// The equality used to determine whether [element] is equal to an element of
+  /// the iterable defaults to the [Object.==] of the element.
+  ///
+  /// Some types of iterable may have a different equality used for its elements.
+  /// For example, a [Set] may have a custom equality
+  /// (see [Set.identity]) that its `contains` uses.
+  /// Likewise the `Iterable` returned by a [Map.keys] call
+  /// should use the same equality that the `Map` uses for keys.
   bool contains(Object? element) {
     for (E e in this) {
       if (e == element) return true;
@@ -275,36 +251,32 @@
     return false;
   }
 
-  /**
-   * Applies the function [f] to each element of this collection in iteration
-   * order.
-   */
+  /// Applies the function [f] to each element of this collection in iteration
+  /// order.
   void forEach(void f(E element)) {
     for (E element in this) f(element);
   }
 
-  /**
-   * Reduces a collection to a single value by iteratively combining elements
-   * of the collection using the provided function.
-   *
-   * The iterable must have at least one element.
-   * If it has only one element, that element is returned.
-   *
-   * Otherwise this method starts with the first element from the iterator,
-   * and then combines it with the remaining elements in iteration order,
-   * as if by:
-   *
-   *     E value = iterable.first;
-   *     iterable.skip(1).forEach((element) {
-   *       value = combine(value, element);
-   *     });
-   *     return value;
-   *
-   * Example of calculating the sum of an iterable:
-   *
-   *     iterable.reduce((value, element) => value + element);
-   *
-   */
+  /// Reduces a collection to a single value by iteratively combining elements
+  /// of the collection using the provided function.
+  ///
+  /// The iterable must have at least one element.
+  /// If it has only one element, that element is returned.
+  ///
+  /// Otherwise this method starts with the first element from the iterator,
+  /// and then combines it with the remaining elements in iteration order,
+  /// as if by:
+  /// ```dart
+  /// E value = iterable.first;
+  /// iterable.skip(1).forEach((element) {
+  ///   value = combine(value, element);
+  /// });
+  /// return value;
+  /// ```
+  /// Example of calculating the sum of an iterable:
+  /// ```dart
+  /// iterable.reduce((value, element) => value + element);
+  /// ```
   E reduce(E combine(E value, E element)) {
     Iterator<E> iterator = this.iterator;
     if (!iterator.moveNext()) {
@@ -317,37 +289,33 @@
     return value;
   }
 
-  /**
-   * Reduces a collection to a single value by iteratively combining each
-   * element of the collection with an existing value
-   *
-   * Uses [initialValue] as the initial value,
-   * then iterates through the elements and updates the value with
-   * each element using the [combine] function, as if by:
-   *
-   *     var value = initialValue;
-   *     for (E element in this) {
-   *       value = combine(value, element);
-   *     }
-   *     return value;
-   *
-   * Example of calculating the sum of an iterable:
-   *
-   *     iterable.fold(0, (prev, element) => prev + element);
-   *
-   */
+  /// Reduces a collection to a single value by iteratively combining each
+  /// element of the collection with an existing value
+  ///
+  /// Uses [initialValue] as the initial value,
+  /// then iterates through the elements and updates the value with
+  /// each element using the [combine] function, as if by:
+  /// ```dart
+  /// var value = initialValue;
+  /// for (E element in this) {
+  ///   value = combine(value, element);
+  /// }
+  /// return value;
+  /// ```
+  /// Example of calculating the sum of an iterable:
+  /// ```dart
+  /// iterable.fold(0, (prev, element) => prev + element);
+  /// ```
   T fold<T>(T initialValue, T combine(T previousValue, E element)) {
     var value = initialValue;
     for (E element in this) value = combine(value, element);
     return value;
   }
 
-  /**
-   * Checks whether every element of this iterable satisfies [test].
-   *
-   * Checks every element in iteration order, and returns `false` if
-   * any of them make [test] return `false`, otherwise returns `true`.
-   */
+  /// Checks whether every element of this iterable satisfies [test].
+  ///
+  /// Checks every element in iteration order, and returns `false` if
+  /// any of them make [test] return `false`, otherwise returns `true`.
   bool every(bool test(E element)) {
     for (E element in this) {
       if (!test(element)) return false;
@@ -355,14 +323,12 @@
     return true;
   }
 
-  /**
-   * Converts each element to a [String] and concatenates the strings.
-   *
-   * Iterates through elements of this iterable,
-   * converts each one to a [String] by calling [Object.toString],
-   * and then concatenates the strings, with the
-   * [separator] string interleaved between the elements.
-   */
+  /// Converts each element to a [String] and concatenates the strings.
+  ///
+  /// Iterates through elements of this iterable,
+  /// converts each one to a [String] by calling [Object.toString],
+  /// and then concatenates the strings, with the
+  /// [separator] string interleaved between the elements.
   String join([String separator = ""]) {
     Iterator<E> iterator = this.iterator;
     if (!iterator.moveNext()) return "";
@@ -381,12 +347,10 @@
     return buffer.toString();
   }
 
-  /**
-   * Checks whether any element of this iterable satisfies [test].
-   *
-   * Checks every element in iteration order, and returns `true` if
-   * any of them make [test] return `true`, otherwise returns false.
-   */
+  /// Checks whether any element of this iterable satisfies [test].
+  ///
+  /// Checks every element in iteration order, and returns `true` if
+  /// any of them make [test] return `true`, otherwise returns false.
   bool any(bool test(E element)) {
     for (E element in this) {
       if (test(element)) return true;
@@ -394,34 +358,28 @@
     return false;
   }
 
-  /**
-   * Creates a [List] containing the elements of this [Iterable].
-   *
-   * The elements are in iteration order.
-   * The list is fixed-length if [growable] is false.
-   */
+  /// Creates a [List] containing the elements of this [Iterable].
+  ///
+  /// The elements are in iteration order.
+  /// The list is fixed-length if [growable] is false.
   List<E> toList({bool growable = true}) {
     return List<E>.of(this, growable: growable);
   }
 
-  /**
-   * Creates a [Set] containing the same elements as this iterable.
-   *
-   * The set may contain fewer elements than the iterable,
-   * if the iterable contains an element more than once,
-   * or it contains one or more elements that are equal.
-   * The order of the elements in the set is not guaranteed to be the same
-   * as for the iterable.
-   */
+  /// Creates a [Set] containing the same elements as this iterable.
+  ///
+  /// The set may contain fewer elements than the iterable,
+  /// if the iterable contains an element more than once,
+  /// or it contains one or more elements that are equal.
+  /// The order of the elements in the set is not guaranteed to be the same
+  /// as for the iterable.
   Set<E> toSet() => Set<E>.of(this);
 
-  /**
-   * Returns the number of elements in [this].
-   *
-   * Counting all elements may involve iterating through all elements and can
-   * therefore be slow.
-   * Some iterables have a more efficient way to find the number of elements.
-   */
+  /// Returns the number of elements in [this].
+  ///
+  /// Counting all elements may involve iterating through all elements and can
+  /// therefore be slow.
+  /// Some iterables have a more efficient way to find the number of elements.
   int get length {
     assert(this is! EfficientLengthIterable);
     int count = 0;
@@ -432,92 +390,78 @@
     return count;
   }
 
-  /**
-   * Returns `true` if there are no elements in this collection.
-   *
-   * May be computed by checking if `iterator.moveNext()` returns `false`.
-   */
+  /// Returns `true` if there are no elements in this collection.
+  ///
+  /// May be computed by checking if `iterator.moveNext()` returns `false`.
   bool get isEmpty => !iterator.moveNext();
 
-  /**
-   * Returns true if there is at least one element in this collection.
-   *
-   * May be computed by checking if `iterator.moveNext()` returns `true`.
-   */
+  /// Returns true if there is at least one element in this collection.
+  ///
+  /// May be computed by checking if `iterator.moveNext()` returns `true`.
   bool get isNotEmpty => !isEmpty;
 
-  /**
-   * Returns a lazy iterable of the [count] first elements of this iterable.
-   *
-   * The returned `Iterable` may contain fewer than `count` elements, if `this`
-   * contains fewer than `count` elements.
-   *
-   * The elements can be computed by stepping through [iterator] until [count]
-   * elements have been seen.
-   *
-   * The `count` must not be negative.
-   */
+  /// Returns a lazy iterable of the [count] first elements of this iterable.
+  ///
+  /// The returned `Iterable` may contain fewer than `count` elements, if `this`
+  /// contains fewer than `count` elements.
+  ///
+  /// The elements can be computed by stepping through [iterator] until [count]
+  /// elements have been seen.
+  ///
+  /// The `count` must not be negative.
   Iterable<E> take(int count) {
     return TakeIterable<E>(this, count);
   }
 
-  /**
-   * Returns a lazy iterable of the leading elements satisfying [test].
-   *
-   * The filtering happens lazily. Every new iterator of the returned
-   * iterable starts iterating over the elements of `this`.
-   *
-   * The elements can be computed by stepping through [iterator] until an
-   * element is found where `test(element)` is false. At that point,
-   * the returned iterable stops (its `moveNext()` returns false).
-   */
+  /// Returns a lazy iterable of the leading elements satisfying [test].
+  ///
+  /// The filtering happens lazily. Every new iterator of the returned
+  /// iterable starts iterating over the elements of `this`.
+  ///
+  /// The elements can be computed by stepping through [iterator] until an
+  /// element is found where `test(element)` is false. At that point,
+  /// the returned iterable stops (its `moveNext()` returns false).
   Iterable<E> takeWhile(bool test(E value)) {
     return TakeWhileIterable<E>(this, test);
   }
 
-  /**
-   * Returns an [Iterable] that provides all but the first [count] elements.
-   *
-   * When the returned iterable is iterated, it starts iterating over `this`,
-   * first skipping past the initial [count] elements.
-   * If `this` has fewer than `count` elements, then the resulting Iterable is
-   * empty.
-   * After that, the remaining elements are iterated in the same order as
-   * in this iterable.
-   *
-   * Some iterables may be able to find later elements without first iterating
-   * through earlier elements, for example when iterating a [List].
-   * Such iterables are allowed to ignore the initial skipped elements.
-   *
-   * The [count] must not be negative.
-   */
+  /// Returns an [Iterable] that provides all but the first [count] elements.
+  ///
+  /// When the returned iterable is iterated, it starts iterating over `this`,
+  /// first skipping past the initial [count] elements.
+  /// If `this` has fewer than `count` elements, then the resulting Iterable is
+  /// empty.
+  /// After that, the remaining elements are iterated in the same order as
+  /// in this iterable.
+  ///
+  /// Some iterables may be able to find later elements without first iterating
+  /// through earlier elements, for example when iterating a [List].
+  /// Such iterables are allowed to ignore the initial skipped elements.
+  ///
+  /// The [count] must not be negative.
   Iterable<E> skip(int count) {
     return SkipIterable<E>(this, count);
   }
 
-  /**
-   * Returns an `Iterable` that skips leading elements while [test] is satisfied.
-   *
-   * The filtering happens lazily. Every new [Iterator] of the returned
-   * iterable iterates over all elements of `this`.
-   *
-   * The returned iterable provides elements by iterating this iterable,
-   * but skipping over all initial elements where `test(element)` returns
-   * true. If all elements satisfy `test` the resulting iterable is empty,
-   * otherwise it iterates the remaining elements in their original order,
-   * starting with the first element for which `test(element)` returns `false`.
-   */
+  /// Returns an `Iterable` that skips leading elements while [test] is satisfied.
+  ///
+  /// The filtering happens lazily. Every new [Iterator] of the returned
+  /// iterable iterates over all elements of `this`.
+  ///
+  /// The returned iterable provides elements by iterating this iterable,
+  /// but skipping over all initial elements where `test(element)` returns
+  /// true. If all elements satisfy `test` the resulting iterable is empty,
+  /// otherwise it iterates the remaining elements in their original order,
+  /// starting with the first element for which `test(element)` returns `false`.
   Iterable<E> skipWhile(bool test(E value)) {
     return SkipWhileIterable<E>(this, test);
   }
 
-  /**
-   * Returns the first element.
-   *
-   * Throws a [StateError] if `this` is empty.
-   * Otherwise returns the first element in the iteration order,
-   * equivalent to `this.elementAt(0)`.
-   */
+  /// Returns the first element.
+  ///
+  /// Throws a [StateError] if `this` is empty.
+  /// Otherwise returns the first element in the iteration order,
+  /// equivalent to `this.elementAt(0)`.
   E get first {
     Iterator<E> it = iterator;
     if (!it.moveNext()) {
@@ -526,16 +470,14 @@
     return it.current;
   }
 
-  /**
-   * Returns the last element.
-   *
-   * Throws a [StateError] if `this` is empty.
-   * Otherwise may iterate through the elements and returns the last one
-   * seen.
-   * Some iterables may have more efficient ways to find the last element
-   * (for example a list can directly access the last element,
-   * without iterating through the previous ones).
-   */
+  /// Returns the last element.
+  ///
+  /// Throws a [StateError] if `this` is empty.
+  /// Otherwise may iterate through the elements and returns the last one
+  /// seen.
+  /// Some iterables may have more efficient ways to find the last element
+  /// (for example a list can directly access the last element,
+  /// without iterating through the previous ones).
   E get last {
     Iterator<E> it = iterator;
     if (!it.moveNext()) {
@@ -548,11 +490,9 @@
     return result;
   }
 
-  /**
-   * Checks that this iterable has only one element, and returns that element.
-   *
-   * Throws a [StateError] if `this` is empty or has more than one element.
-   */
+  /// Checks that this iterable has only one element, and returns that element.
+  ///
+  /// Throws a [StateError] if `this` is empty or has more than one element.
   E get single {
     Iterator<E> it = iterator;
     if (!it.moveNext()) throw IterableElementError.noElement();
@@ -561,15 +501,13 @@
     return result;
   }
 
-  /**
-   * Returns the first element that satisfies the given predicate [test].
-   *
-   * Iterates through elements and returns the first to satisfy [test].
-   *
-   * If no element satisfies [test], the result of invoking the [orElse]
-   * function is returned.
-   * If [orElse] is omitted, it defaults to throwing a [StateError].
-   */
+  /// Returns the first element that satisfies the given predicate [test].
+  ///
+  /// Iterates through elements and returns the first to satisfy [test].
+  ///
+  /// If no element satisfies [test], the result of invoking the [orElse]
+  /// function is returned.
+  /// If [orElse] is omitted, it defaults to throwing a [StateError].
   E firstWhere(bool test(E element), {E orElse()?}) {
     for (E element in this) {
       if (test(element)) return element;
@@ -578,20 +516,18 @@
     throw IterableElementError.noElement();
   }
 
-  /**
-   * Returns the last element that satisfies the given predicate [test].
-   *
-   * An iterable that can access its elements directly may check its
-   * elements in any order (for example a list starts by checking the
-   * last element and then moves towards the start of the list).
-   * The default implementation iterates elements in iteration order,
-   * checks `test(element)` for each,
-   * and finally returns that last one that matched.
-   *
-   * If no element satisfies [test], the result of invoking the [orElse]
-   * function is returned.
-   * If [orElse] is omitted, it defaults to throwing a [StateError].
-   */
+  /// Returns the last element that satisfies the given predicate [test].
+  ///
+  /// An iterable that can access its elements directly may check its
+  /// elements in any order (for example a list starts by checking the
+  /// last element and then moves towards the start of the list).
+  /// The default implementation iterates elements in iteration order,
+  /// checks `test(element)` for each,
+  /// and finally returns that last one that matched.
+  ///
+  /// If no element satisfies [test], the result of invoking the [orElse]
+  /// function is returned.
+  /// If [orElse] is omitted, it defaults to throwing a [StateError].
   E lastWhere(bool test(E element), {E orElse()?}) {
     late E result;
     bool foundMatching = false;
@@ -606,15 +542,13 @@
     throw IterableElementError.noElement();
   }
 
-  /**
-   * Returns the single element that satisfies [test].
-   *
-   * Checks elements to see if `test(element)` returns true.
-   * If exactly one element satisfies [test], that element is returned.
-   * If more than one matching element is found, throws [StateError].
-   * If no matching element is found, returns the result of [orElse].
-   * If [orElse] is omitted, it defaults to throwing a [StateError].
-   */
+  /// Returns the single element that satisfies [test].
+  ///
+  /// Checks elements to see if `test(element)` returns true.
+  /// If exactly one element satisfies [test], that element is returned.
+  /// If more than one matching element is found, throws [StateError].
+  /// If no matching element is found, returns the result of [orElse].
+  /// If [orElse] is omitted, it defaults to throwing a [StateError].
   E singleWhere(bool test(E element), {E orElse()?}) {
     late E result;
     bool foundMatching = false;
@@ -632,17 +566,15 @@
     throw IterableElementError.noElement();
   }
 
-  /**
-   * Returns the [index]th element.
-   *
-   * The [index] must be non-negative and less than [length].
-   * Index zero represents the first element (so `iterable.elementAt(0)` is
-   * equivalent to `iterable.first`).
-   *
-   * May iterate through the elements in iteration order, ignoring the
-   * first [index] elements and then returning the next.
-   * Some iterables may have a more efficient way to find the element.
-   */
+  /// Returns the [index]th element.
+  ///
+  /// The [index] must be non-negative and less than [length].
+  /// Index zero represents the first element (so `iterable.elementAt(0)` is
+  /// equivalent to `iterable.first`).
+  ///
+  /// May iterate through the elements in iteration order, ignoring the
+  /// first [index] elements and then returning the next.
+  /// Some iterables may have a more efficient way to find the element.
   E elementAt(int index) {
     RangeError.checkNotNegative(index, "index");
     int elementIndex = 0;
@@ -653,22 +585,20 @@
     throw RangeError.index(index, this, "index", null, elementIndex);
   }
 
-  /**
-   * Returns a string representation of (some of) the elements of `this`.
-   *
-   * Elements are represented by their own `toString` results.
-   *
-   * The default representation always contains the first three elements.
-   * If there are less than a hundred elements in the iterable, it also
-   * contains the last two elements.
-   *
-   * If the resulting string isn't above 80 characters, more elements are
-   * included from the start of the iterable.
-   *
-   * The conversion may omit calling `toString` on some elements if they
-   * are known to not occur in the output, and it may stop iterating after
-   * a hundred elements.
-   */
+  /// Returns a string representation of (some of) the elements of `this`.
+  ///
+  /// Elements are represented by their own `toString` results.
+  ///
+  /// The default representation always contains the first three elements.
+  /// If there are less than a hundred elements in the iterable, it also
+  /// contains the last two elements.
+  ///
+  /// If the resulting string isn't above 80 characters, more elements are
+  /// included from the start of the iterable.
+  ///
+  /// The conversion may omit calling `toString` on some elements if they
+  /// are known to not occur in the output, and it may stop iterating after
+  /// a hundred elements.
   String toString() => IterableBase.iterableToShortString(this, '(', ')');
 }
 
@@ -696,16 +626,12 @@
   static int _id(int n) => n;
 }
 
-/**
- * An [Iterator] that allows moving backwards as well as forwards.
- */
+/// An [Iterator] that allows moving backwards as well as forwards.
 abstract class BidirectionalIterator<E> implements Iterator<E> {
-  /**
-   * Move back to the previous element.
-   *
-   * Returns true and updates [current] if successful. Returns false
-   * and updates [current] to an implementation defined state if there is no
-   * previous element
-   */
+  /// Move back to the previous element.
+  ///
+  /// Returns true and updates [current] if successful. Returns false
+  /// and updates [current] to an implementation defined state if there is no
+  /// previous element
   bool movePrevious();
 }
diff --git a/sdk/lib/core/iterator.dart b/sdk/lib/core/iterator.dart
index 13c76b4..7ea322e 100644
--- a/sdk/lib/core/iterator.dart
+++ b/sdk/lib/core/iterator.dart
@@ -4,72 +4,66 @@
 
 part of dart.core;
 
-/**
- * An interface for getting items, one at a time, from an object.
- *
- * The for-in construct transparently uses `Iterator` to test for the end
- * of the iteration, and to get each item (or _element_).
- *
- * If the object iterated over is changed during the iteration, the
- * behavior is unspecified.
- *
- * The `Iterator` is initially positioned before the first element.
- * Before accessing the first element the iterator must thus be advanced using
- * [moveNext] to point to the first element.
- * If no element is left, then [moveNext] returns false,
- * and all further calls to [moveNext] will also return false.
- *
- * The [current] value must not be accessed before calling [moveNext]
- * or after a call to [moveNext] has returned false.
- *
- * A typical usage of an Iterator looks as follows:
- *
- *     var it = obj.iterator;
- *     while (it.moveNext()) {
- *       use(it.current);
- *     }
- *
- * **See also:**
- * [Iteration](https://dart.dev/guides/libraries/library-tour#iteration)
- * in the [library tour](https://dart.dev/guides/libraries/library-tour)
- */
+/// An interface for getting items, one at a time, from an object.
+///
+/// The for-in construct transparently uses `Iterator` to test for the end
+/// of the iteration, and to get each item (or _element_).
+///
+/// If the object iterated over is changed during the iteration, the
+/// behavior is unspecified.
+///
+/// The `Iterator` is initially positioned before the first element.
+/// Before accessing the first element the iterator must thus be advanced using
+/// [moveNext] to point to the first element.
+/// If no element is left, then [moveNext] returns false,
+/// and all further calls to [moveNext] will also return false.
+///
+/// The [current] value must not be accessed before calling [moveNext]
+/// or after a call to [moveNext] has returned false.
+///
+/// A typical usage of an `Iterator` looks as follows:
+/// ```dart
+/// var it = obj.iterator;
+/// while (it.moveNext()) {
+///   use(it.current);
+/// }
+/// ```
+/// **See also:**
+/// [Iteration](https://dart.dev/guides/libraries/library-tour#iteration)
+/// in the [library tour](https://dart.dev/guides/libraries/library-tour)
 abstract class Iterator<E> {
-  /**
-   * Advances the iterator to the next element of the iteration.
-   *
-   * Should be called before reading [current].
-   * If the call to `moveNext` returns `true`,
-   * then [current] will contain the next element of the iteration
-   * until `moveNext` is called again.
-   * If the call returns `false`, there are no further elements
-   * and [current] should not be used any more.
-   *
-   * It is safe to call [moveNext] after it has already returned `false`,
-   * but it must keep returning `false` and not have any other effect.
-   *
-   * A call to `moveNext` may throw for various reasons,
-   * including a concurrent change to an underlying collection.
-   * If that happens, the iterator may be in an inconsistent
-   * state, and any further behavior of the iterator is unspecified,
-   * including the effect of reading [current].
-   */
+  /// Advances the iterator to the next element of the iteration.
+  ///
+  /// Should be called before reading [current].
+  /// If the call to `moveNext` returns `true`,
+  /// then [current] will contain the next element of the iteration
+  /// until `moveNext` is called again.
+  /// If the call returns `false`, there are no further elements
+  /// and [current] should not be used any more.
+  ///
+  /// It is safe to call [moveNext] after it has already returned `false`,
+  /// but it must keep returning `false` and not have any other effect.
+  ///
+  /// A call to `moveNext` may throw for various reasons,
+  /// including a concurrent change to an underlying collection.
+  /// If that happens, the iterator may be in an inconsistent
+  /// state, and any further behavior of the iterator is unspecified,
+  /// including the effect of reading [current].
   bool moveNext();
 
-  /**
-   * Returns the current element.
-   *
-   * If the iterator has not yet been moved to the first element
-   * ([moveNext] has not been called yet),
-   * or if the iterator has been moved past the last element of the [Iterable]
-   * ([moveNext] has returned false),
-   * then [current] is unspecified.
-   * An [Iterator] may either throw or return an iterator specific default value
-   * in that case.
-   *
-   * The `current` getter should keep its value until the next call to
-   * [moveNext], even if an underlying collection changes.
-   * After a successful call to `moveNext`, the user doesn't need to cache
-   * the current value, but can keep reading it from the iterator.
-   */
+  /// The current element.
+  ///
+  /// If the iterator has not yet been moved to the first element
+  /// ([moveNext] has not been called yet),
+  /// or if the iterator has been moved past the last element of the [Iterable]
+  /// ([moveNext] has returned false),
+  /// then [current] is unspecified.
+  /// An [Iterator] may either throw or return an iterator specific default value
+  /// in that case.
+  ///
+  /// The `current` getter should keep its value until the next call to
+  /// [moveNext], even if an underlying collection changes.
+  /// After a successful call to `moveNext`, the user doesn't need to cache
+  /// the current value, but can keep reading it from the iterator.
   E get current;
 }
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index e342bb7..dc2404f 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -4,225 +4,205 @@
 
 part of dart.core;
 
-/**
- * An indexable collection of objects with a length.
- *
- * Subclasses of this class implement different kinds of lists.
- * The most common kinds of lists are:
- *
- * * Fixed-length list.
- *   An error occurs when attempting to use operations
- *   that can change the length of the list.
- *
- * * Growable list. Full implementation of the API defined in this class.
- *
- * The default growable list, as created by `[]`, keeps
- * an internal buffer, and grows that buffer when necessary. This guarantees
- * that a sequence of [add] operations will each execute in amortized constant
- * time. Setting the length directly may take time proportional to the new
- * length, and may change the internal capacity so that a following add
- * operation will need to immediately increase the buffer capacity.
- * Other list implementations may have different performance behavior.
- *
- * The following code illustrates that some List implementations support
- * only a subset of the API.
- *
- *     List<int> fixedLengthList = new List.filled(5);
- *     fixedLengthList.length = 0;  // Error
- *     fixedLengthList.add(499);    // Error
- *     fixedLengthList[0] = 87;
- *     List<int> growableList = [1, 2];
- *     growableList.length = 0;
- *     growableList.add(499);
- *     growableList[0] = 87;
- *
- * Lists are [Iterable]. Iteration occurs over values in index order. Changing
- * the values does not affect iteration, but changing the valid
- * indices&mdash;that is, changing the list's length&mdash;between iteration
- * steps causes a [ConcurrentModificationError]. This means that only growable
- * lists can throw ConcurrentModificationError. If the length changes
- * temporarily and is restored before continuing the iteration, the iterator
- * does not detect it.
- *
- * It is generally not allowed to modify the list's length (adding or removing
- * elements) while an operation on the list is being performed,
- * for example during a call to [forEach] or [sort].
- * Changing the list's length while it is being iterated, either by iterating it
- * directly or through iterating an [Iterable] that is backed by the list, will
- * break the iteration.
- */
+/// An indexable collection of objects with a length.
+///
+/// Subclasses of this class implement different kinds of lists.
+/// The most common kinds of lists are:
+///
+/// * Fixed-length list.
+///   An error occurs when attempting to use operations
+///   that can change the length of the list.
+///
+/// * Growable list. Full implementation of the API defined in this class.
+///
+/// The default growable list, as created by `[]`, keeps
+/// an internal buffer, and grows that buffer when necessary. This guarantees
+/// that a sequence of [add] operations will each execute in amortized constant
+/// time. Setting the length directly may take time proportional to the new
+/// length, and may change the internal capacity so that a following add
+/// operation will need to immediately increase the buffer capacity.
+/// Other list implementations may have different performance behavior.
+///
+/// The following code illustrates that some List implementations support
+/// only a subset of the API.
+/// ```dart
+/// var fixedLengthList = List<int>.filled(5, 0);
+/// fixedLengthList.length = 0;  // Error
+/// fixedLengthList.add(499);    // Error
+/// fixedLengthList[0] = 87;
+/// var growableList = [1, 2];
+/// growableList.length = 0;
+/// growableList.add(499);
+/// growableList[0] = 87;
+/// ```
+/// Lists are [Iterable]. Iteration occurs over values in index order. Changing
+/// the values does not affect iteration, but changing the valid
+/// indices&mdash;that is, changing the list's length&mdash;between iteration
+/// steps causes a [ConcurrentModificationError]. This means that only growable
+/// lists can throw ConcurrentModificationError. If the length changes
+/// temporarily and is restored before continuing the iteration, the iterator
+/// might not detect it.
+///
+/// It is generally not allowed to modify the list's length (adding or removing
+/// elements) while an operation on the list is being performed,
+/// for example during a call to [forEach] or [sort].
+/// Changing the list's length while it is being iterated, either by iterating it
+/// directly or through iterating an [Iterable] that is backed by the list, will
+/// break the iteration.
 abstract class List<E> implements EfficientLengthIterable<E> {
-  /**
-   * Creates a list of the given length.
-   *
-   * **NOTICE**: This constructor cannot be used in null-safe code.
-   * Use [List.filled] to create a non-empty list.
-   * This requires a fill value to initialize the list elements with.
-   * To create an empty list, use `[]` for a growable list or
-   * `List.empty` for a fixed length list (or where growability is determined
-   * at run-time).
-   *
-   * The created list is fixed-length if [length] is provided.
-   *
-   *     List fixedLengthList = new List.filled(3);
-   *     fixedLengthList.length;     // 3
-   *     fixedLengthList.length = 1; // Error
-   *
-   * The list has length 0 and is growable if [length] is omitted.
-   *
-   *     List growableList = [];
-   *     growableList.length; // 0;
-   *     growableList.length = 3;
-   *
-   * To create a growable list with a given length, for a nullable element type,
-   * just assign the length right after creation:
-   *
-   *     List growableList = []..length = 500;
-   *
-   * For a non-nullable element type, an alternative is the following:
-   *
-   *     List<int> growableList = List<int>.filled(500, 0, growable: true);
-   *
-   * The [length] must not be negative or null, if it is provided.
-   *
-   * If the element type is not nullable, [length] must not be greater than
-   * zero.
-   */
-  @deprecated
+  /// Creates a list of the given length.
+  ///
+  /// **NOTICE**: This constructor cannot be used in null-safe code.
+  /// Use [List.filled] to create a non-empty list.
+  /// This requires a fill value to initialize the list elements with.
+  /// To create an empty list, use `[]` for a growable list or
+  /// `List.empty` for a fixed length list (or where growability is determined
+  /// at run-time).
+  ///
+  /// The created list is fixed-length if [length] is provided.
+  /// ```dart
+  /// var fixedLengthList = List(3);
+  /// fixedLengthList.length;     // 3
+  /// fixedLengthList.length = 1; // Error
+  /// ```
+  /// The list has length 0 and is growable if [length] is omitted.
+  /// ```dart
+  /// var growableList = List();
+  /// growableList.length; // 0;
+  /// growableList.length = 3;
+  /// ```
+  /// To create a growable list with a given length, for a nullable element type,
+  /// just assign the length right after creation:
+  /// ```dart
+  /// List<SomeNullableType> growableList = []..length = 500;
+  /// ```
+  /// For a non-nullable element type, an alternative is the following:
+  /// ```dart
+  /// List<int> growableList = List<int>.filled(500, 0, growable: true);
+  /// ```
+  /// The [length] must not be negative or null, if it is provided.
+  ///
+  /// If the element type is not nullable, [length] must not be greater than
+  /// zero.
+  @Deprecated("Use a list literal, [], or the List.filled constructor instead")
   external factory List([int? length]);
 
-  /**
-   * Creates a list of the given length with [fill] at each position.
-   *
-   * The [length] must be a non-negative integer.
-   *
-   * Example:
-   * ```dart
-   * new List<int>.filled(3, 0, growable: true); // [0, 0, 0]
-   * ```
-   *
-   * The created list is fixed-length if [growable] is false (the default)
-   * and growable if [growable] is true.
-   * If the list is growable, changing its length will not initialize new
-   * entries with [fill].
-   * After being created and filled, the list is no different from any other
-   * growable or fixed-length list created using [List].
-   *
-   * All elements of the returned list share the same [fill] value.
-   * ```
-   * var shared = new List.filled(3, []);
-   * shared[0].add(499);
-   * print(shared);  // => [[499], [499], [499]]
-   * ```
-   *
-   * You can use [List.generate] to create a list with a new object at
-   * each position.
-   * ```
-   * var unique = new List.generate(3, (_) => []);
-   * unique[0].add(499);
-   * print(unique); // => [[499], [], []]
-   * ```
-   */
+  /// Creates a list of the given length with [fill] at each position.
+  ///
+  /// The [length] must be a non-negative integer.
+  ///
+  /// Example:
+  /// ```dart
+  /// List<int>.filled(3, 0, growable: true); // [0, 0, 0]
+  /// ```
+  ///
+  /// The created list is fixed-length if [growable] is false (the default)
+  /// and growable if [growable] is true.
+  /// If the list is growable, increasing its [length] will *not* initialize
+  /// new entries with [fill].
+  /// After being created and filled, the list is no different from any other
+  /// growable or fixed-length list created
+  /// using `[]` or other [List] constructors.
+  ///
+  /// All elements of the created list share the same [fill] value.
+  /// ```
+  /// var shared = List.filled(3, []);
+  /// shared[0].add(499);
+  /// print(shared);  // => [[499], [499], [499]]
+  /// ```
+  /// You can use [List.generate] to create a list with a fixed length
+  /// and a new object at each position.
+  /// ```
+  /// var unique = List.generate(3, (_) => []);
+  /// unique[0].add(499);
+  /// print(unique); // => [[499], [], []]
+  /// ```
   external factory List.filled(int length, E fill, {bool growable = false});
 
-  /**
-   * Creates a new empty list.
-   *
-   * If [growable] is `false`, which is the default,
-   * the list is a fixed-length list of length zero.
-   * If [growable] is `true`, the list is growable and equivalent to `<E>[]`.
-   */
+  /// Creates a new empty list.
+  ///
+  /// If [growable] is `false`, which is the default,
+  /// the list is a fixed-length list of length zero.
+  /// If [growable] is `true`, the list is growable and equivalent to `<E>[]`.
   @Since("2.8")
   external factory List.empty({bool growable = false});
 
-  /**
-   * Creates a list containing all [elements].
-   *
-   * The [Iterator] of [elements] provides the order of the elements.
-   *
-   * All the [elements] should be instances of [E].
-   * The `elements` iterable itself may have any element type, so this
-   * constructor can be used to down-cast a `List`, for example as:
-   * ```dart
-   * List<SuperType> superList = ...;
-   * List<SubType> subList =
-   *     new List<SubType>.from(superList.whereType<SubType>());
-   * ```
-   *
-   * This constructor creates a growable list when [growable] is true;
-   * otherwise, it returns a fixed-length list.
-   */
+  /// Creates a list containing all [elements].
+  ///
+  /// The [Iterator] of [elements] provides the order of the elements.
+  ///
+  /// All the [elements] should be instances of [E].
+  /// The `elements` iterable itself may have any element type, so this
+  /// constructor can be used to down-cast a `List`, for example as:
+  /// ```dart
+  /// List<dynamic> dynList = ...some JSON value...;
+  /// List<Map<String, dynamic>> fooList =
+  ///     List.from(dynList.where((x) => x is Map && map["kind"] == "foo"));
+  /// ```
+  ///
+  /// This constructor creates a growable list when [growable] is true;
+  /// otherwise, it returns a fixed-length list.
   external factory List.from(Iterable elements, {bool growable = true});
 
-  /**
-   * Creates a list from [elements].
-   *
-   * The [Iterator] of [elements] provides the order of the elements.
-   *
-   * This constructor creates a growable list when [growable] is true;
-   * otherwise, it returns a fixed-length list.
-   */
+  /// Creates a list from [elements].
+  ///
+  /// The [Iterator] of [elements] provides the order of the elements.
+  ///
+  /// This constructor creates a growable list when [growable] is true;
+  /// otherwise, it returns a fixed-length list.
   external factory List.of(Iterable<E> elements, {bool growable = true});
 
-  /**
-   * Generates a list of values.
-   *
-   * Creates a list with [length] positions and fills it with values created by
-   * calling [generator] for each index in the range `0` .. `length - 1`
-   * in increasing order.
-   * ```dart
-   * List<int>.generate(3, (int index) => index * index); // [0, 1, 4]
-   * ```
-   * The created list is fixed-length if [growable] is set to false.
-   *
-   * The [length] must be non-negative.
-   */
+  /// Generates a list of values.
+  ///
+  /// Creates a list with [length] positions and fills it with values created by
+  /// calling [generator] for each index in the range `0` .. `length - 1`
+  /// in increasing order.
+  /// ```dart
+  /// List<int>.generate(3, (int index) => index * index); // [0, 1, 4]
+  /// ```
+  /// The created list is fixed-length if [growable] is set to false.
+  ///
+  /// The [length] must be non-negative.
   external factory List.generate(int length, E generator(int index),
       {bool growable = true});
 
-  /**
-   * Creates an unmodifiable list containing all [elements].
-   *
-   * The [Iterator] of [elements] provides the order of the elements.
-   *
-   * An unmodifiable list cannot have its length or elements changed.
-   * If the elements are themselves immutable, then the resulting list
-   * is also immutable.
-   */
+  /// Creates an unmodifiable list containing all [elements].
+  ///
+  /// The [Iterator] of [elements] provides the order of the elements.
+  ///
+  /// An unmodifiable list cannot have its length or elements changed.
+  /// If the elements are themselves immutable, then the resulting list
+  /// is also immutable.
   external factory List.unmodifiable(Iterable elements);
 
-  /**
-   * Adapts [source] to be a `List<T>`.
-   *
-   * Any time the list would produce an element that is not a [T],
-   * the element access will throw.
-   *
-   * Any time a [T] value is attempted stored into the adapted list,
-   * the store will throw unless the value is also an instance of [S].
-   *
-   * If all accessed elements of [source] are actually instances of [T],
-   * 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>`.
-   */
+  /// Adapts [source] to be a `List<T>`.
+  ///
+  /// Any time the list would produce an element that is not a [T],
+  /// the element access will throw.
+  ///
+  /// Any time a [T] value is attempted stored into the adapted list,
+  /// the store will throw unless the value is also an instance of [S].
+  ///
+  /// If all accessed elements of [source] are actually instances of [T],
+  /// 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>`.
   static List<T> castFrom<S, T>(List<S> source) => CastList<S, T>(source);
 
-  /**
-   * Copy a range of one list into another list.
-   *
-   * This is a utility function that can be used to implement methods like
-   * [setRange].
-   *
-   * The range from [start] to [end] must be a valid range of [source],
-   * and there must be room for `end - start` elements from position [at].
-   * If [start] is omitted, it defaults to zero.
-   * If [end] is omitted, it defaults to [source.length].
-   *
-   * If [source] and [target] is the same list, overlapping source and target
-   * ranges are respected so that the target range ends up containing the
-   * initial content of the source range.
-   * Otherwise the order of element copying is not guaranteed.
-   */
+  /// Copy a range of one list into another list.
+  ///
+  /// This is a utility function that can be used to implement methods like
+  /// [setRange].
+  ///
+  /// The range from [start] to [end] must be a valid range of [source],
+  /// and there must be room for `end - start` elements from position [at].
+  /// If [start] is omitted, it defaults to zero.
+  /// If [end] is omitted, it defaults to [source.length].
+  ///
+  /// If [source] and [target] is the same list, overlapping source and target
+  /// ranges are respected so that the target range ends up containing the
+  /// initial content of the source range.
+  /// Otherwise the order of element copying is not guaranteed.
   static void copyRange<T>(List<T> target, int at, List<T> source,
       [int? start, int? end]) {
     start ??= 0;
@@ -247,19 +227,17 @@
     }
   }
 
-  /**
-   * Write the elements of an iterable into a list.
-   *
-   * This is a utility function that can be used to implement methods like
-   * [setAll].
-   *
-   * The elements of [source] are written into [target] from position [at].
-   * The [source] must not contain more elements after writing the last
-   * position of [target].
-   *
-   * If the source is a list, the [copyRange] function is likely to be more
-   * efficient.
-   */
+  /// Write the elements of an iterable into a list.
+  ///
+  /// This is a utility function that can be used to implement methods like
+  /// [setAll].
+  ///
+  /// The elements of [source] are written into [target] from position [at].
+  /// The [source] must not contain more elements after writing the last
+  /// position of [target].
+  ///
+  /// If the source is a list, the [copyRange] function is likely to be more
+  /// efficient.
   static void writeIterable<T>(List<T> target, int at, Iterable<T> source) {
     RangeError.checkValueInInterval(at, 0, target.length, "at");
     int index = at;
@@ -273,484 +251,444 @@
     }
   }
 
-  /**
-   * 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
-   * that is not an instance of [R], the access will throw instead.
-   *
-   * Elements added to the list (e.g., by using [add] or [addAll])
-   * 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 list as well.
-   *
-   * Typically implemented as `List.castFrom<E, R>(this)`.
-   */
+  /// 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
+  /// that is not an instance of [R], the access will throw instead.
+  ///
+  /// Elements added to the list (e.g., by using [add] or [addAll])
+  /// 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 list as well.
+  ///
+  /// Typically implemented as `List.castFrom<E, R>(this)`.
   List<R> cast<R>();
 
-  /**
-   * Returns the object at the given [index] in the list
-   * or throws a [RangeError] if [index] is out of bounds.
-   */
+  /// The object at the given [index] in the list.
+  ///
+  /// The [index] must be a valid index of this list,
+  /// which means that `index` must be non-negative and
+  /// less than [length].
   E operator [](int index);
 
-  /**
-   * Sets the value at the given [index] in the list to [value]
-   * or throws a [RangeError] if [index] is out of bounds.
-   */
+  /// Sets the value at the given [index] in the list to [value].
+  ///
+  /// The [index] must be a valid index of this list,
+  /// which means that `index` must be non-negative and
+  /// less than [length].
   void operator []=(int index, E value);
 
-  /**
-   * Updates the first position of the list to contain [value].
-   *
-   * Equivalent to `theList[0] = value;`.
-   *
-   * The list must be non-empty.
-   */
+  /// Updates the first position of the list to contain [value].
+  ///
+  /// Equivalent to `theList[0] = value;`.
+  ///
+  /// The list must be non-empty.
   void set first(E value);
 
-  /**
-   * Updates the last position of the list to contain [value].
-   *
-   * Equivalent to `theList[theList.length - 1] = value;`.
-   *
-   * The list must be non-empty.
-   */
+  /// Updates the last position of the list to contain [value].
+  ///
+  /// Equivalent to `theList[theList.length - 1] = value;`.
+  ///
+  /// The list must be non-empty.
   void set last(E value);
 
-  /**
-   * The number of objects in this list.
-   *
-   * The valid indices for a list are `0` through `length - 1`.
-   */
+  /// The number of objects in this list.
+  ///
+  /// The valid indices for a list are `0` through `length - 1`.
   int get length;
 
-  /**
-   * Changes the length of this list.
-   *
-   * If [newLength] is greater than
-   * the current length, entries are initialized to `null`.
-   * Increasing the length fails if the element type does not allow `null`.
-   *
-   * Throws an [UnsupportedError] if the list is fixed-length or
-   * if attempting to enlarge the list when `null` is not a valid element.
-   */
+  /// Changes the length of this list.
+  ///
+  /// The list must be growable.
+  /// If [newLength] is greater than current length,
+  /// new entries are initialized to `null`,
+  /// so [newLength] must not be greater than the current length
+  /// if the element type [E] is non-nullable.
   set length(int newLength);
 
-  /**
-   * Adds [value] to the end of this list,
-   * extending the length by one.
-   *
-   * Throws an [UnsupportedError] if the list is fixed-length.
-   */
+  /// Adds [value] to the end of this list,
+  /// extending the length by one.
+  ///
+  /// The list must be growable.
   void add(E value);
 
-  /**
-   * Appends all objects of [iterable] to the end of this list.
-   *
-   * Extends the length of the list by the number of objects in [iterable].
-   * Throws an [UnsupportedError] if this list is fixed-length.
-   */
+  /// Appends all objects of [iterable] to the end of this list.
+  ///
+  /// Extends the length of the list by the number of objects in [iterable].
+  /// The list must be growable.
   void addAll(Iterable<E> iterable);
 
-  /**
-   * Returns an [Iterable] of the objects in this list in reverse order.
-   */
+  /// An [Iterable] of the objects in this list in reverse order.
   Iterable<E> get reversed;
 
-  /**
-   * Sorts this list according to the order specified by the [compare] function.
-   *
-   * The [compare] function must act as a [Comparator].
-   *
-   *     List<String> numbers = ['two', 'three', 'four'];
-   *     // Sort from shortest to longest.
-   *     numbers.sort((a, b) => a.length.compareTo(b.length));
-   *     print(numbers);  // [two, four, three]
-   *
-   * The default List implementations use [Comparable.compare] if
-   * [compare] is omitted.
-   *
-   *     List<int> nums = [13, 2, -11];
-   *     nums.sort();
-   *     print(nums);  // [-11, 2, 13]
-   *
-   * A [Comparator] may compare objects as equal (return zero), even if they
-   * are distinct objects.
-   * The sort function is not guaranteed to be stable, so distinct objects
-   * that compare as equal may occur in any order in the result:
-   *
-   *     List<String> numbers = ['one', 'two', 'three', 'four'];
-   *     numbers.sort((a, b) => a.length.compareTo(b.length));
-   *     print(numbers);  // [one, two, four, three] OR [two, one, four, three]
-   */
+  /// Sorts this list according to the order specified by the [compare] function.
+  ///
+  /// The [compare] function must act as a [Comparator].
+  /// ```dart
+  /// var numbers = ['two', 'three', 'four'];
+  /// // Sort from shortest to longest.
+  /// numbers.sort((a, b) => a.length.compareTo(b.length));
+  /// print(numbers);  // [two, four, three]
+  /// ```
+  /// The default [List] implementations use [Comparable.compare] if
+  /// [compare] is omitted.
+  /// ```dart
+  /// List<int> nums = [13, 2, -11];
+  /// nums.sort();
+  /// print(nums);  // [-11, 2, 13]
+  /// ```
+  /// In that case, the elements of the list must be [Comparable] to
+  /// each other.
+  ///
+  /// A [Comparator] may compare objects as equal (return zero), even if they
+  /// are distinct objects.
+  /// The sort function is not guaranteed to be stable, so distinct objects
+  /// that compare as equal may occur in any order in the result:
+  /// ```dart
+  /// var numbers = ['one', 'two', 'three', 'four'];
+  /// numbers.sort((a, b) => a.length.compareTo(b.length));
+  /// print(numbers);  // [one, two, four, three] OR [two, one, four, three]
+  /// ```
   void sort([int compare(E a, E b)?]);
 
-  /**
-   * Shuffles the elements of this list randomly.
-   */
+  /// Shuffles the elements of this list randomly.
   void shuffle([Random? random]);
 
-  /**
-   * Returns the first index of [element] in this list.
-   *
-   * Searches the list from index [start] to the end of the list.
-   * The first time an object [:o:] is encountered so that [:o == element:],
-   * the index of [:o:] is returned.
-   *
-   *     List<String> notes = ['do', 're', 'mi', 're'];
-   *     notes.indexOf('re');    // 1
-   *     notes.indexOf('re', 2); // 3
-   *
-   * Returns -1 if [element] is not found.
-   *
-   *     notes.indexOf('fa');    // -1
-   */
+  /// The first index of [element] in this list.
+  ///
+  /// Searches the list from index [start] to the end of the list.
+  /// The first time an object `o` is encountered so that `o == element`,
+  /// the index of `o` is returned.
+  /// ```dart
+  /// var notes = ['do', 're', 'mi', 're'];
+  /// notes.indexOf('re');    // 1
+  /// notes.indexOf('re', 2); // 3
+  /// ```
+  /// Returns -1 if [element] is not found.
+  /// ```dart
+  /// notes.indexOf('fa');    // -1
+  /// ```
   int indexOf(E element, [int start = 0]);
 
-  /**
-   * Returns the first index in the list that satisfies the provided [test].
-   *
-   * Searches the list from index [start] to the end of the list.
-   * The first time an object `o` is encountered so that `test(o)` is true,
-   * the index of `o` is returned.
-   *
-   * ```
-   * List<String> notes = ['do', 're', 'mi', 're'];
-   * notes.indexWhere((note) => note.startsWith('r'));       // 1
-   * notes.indexWhere((note) => note.startsWith('r'), 2);    // 3
-   * ```
-   *
-   * Returns -1 if [element] is not found.
-   * ```
-   * notes.indexWhere((note) => note.startsWith('k'));    // -1
-   * ```
-   */
+  /// The first index in the list that satisfies the provided [test].
+  ///
+  /// Searches the list from index [start] to the end of the list.
+  /// The first time an object `o` is encountered so that `test(o)` is true,
+  /// the index of `o` is returned.
+  ///
+  /// ```
+  /// var notes = ['do', 're', 'mi', 're'];
+  /// notes.indexWhere((note) => note.startsWith('r'));       // 1
+  /// notes.indexWhere((note) => note.startsWith('r'), 2);    // 3
+  /// ```
+  ///
+  /// Returns -1 if [element] is not found.
+  /// ```
+  /// notes.indexWhere((note) => note.startsWith('k'));    // -1
+  /// ```
   int indexWhere(bool test(E element), [int start = 0]);
 
-  /**
-   * Returns the last index in the list that satisfies the provided [test].
-   *
-   * Searches the list from index [start] to 0.
-   * The first time an object `o` is encountered so that `test(o)` is true,
-   * the index of `o` is returned.
-   * If [start] is omitted, it defaults to the [length] of the list.
-   *
-   * ```
-   * List<String> notes = ['do', 're', 'mi', 're'];
-   * notes.lastIndexWhere((note) => note.startsWith('r'));       // 3
-   * notes.lastIndexWhere((note) => note.startsWith('r'), 2);    // 1
-   * ```
-   *
-   * Returns -1 if [element] is not found.
-   * ```
-   * notes.lastIndexWhere((note) => note.startsWith('k'));    // -1
-   * ```
-   */
+  /// The last index in the list that satisfies the provided [test].
+  ///
+  /// Searches the list from index [start] to 0.
+  /// The first time an object `o` is encountered so that `test(o)` is true,
+  /// the index of `o` is returned.
+  /// If [start] is omitted, it defaults to the [length] of the list.
+  ///
+  /// ```
+  /// var notes = ['do', 're', 'mi', 're'];
+  /// notes.lastIndexWhere((note) => note.startsWith('r'));       // 3
+  /// notes.lastIndexWhere((note) => note.startsWith('r'), 2);    // 1
+  /// ```
+  ///
+  /// Returns -1 if [element] is not found.
+  /// ```
+  /// notes.lastIndexWhere((note) => note.startsWith('k'));    // -1
+  /// ```
   int lastIndexWhere(bool test(E element), [int? start]);
 
-  /**
-   * Returns the last index of [element] in this list.
-   *
-   * Searches the list backwards from index [start] to 0.
-   *
-   * The first time an object [:o:] is encountered so that [:o == element:],
-   * the index of [:o:] is returned.
-   *
-   *     List<String> notes = ['do', 're', 'mi', 're'];
-   *     notes.lastIndexOf('re', 2); // 1
-   *
-   * If [start] is not provided, this method searches from the end of the
-   * list.
-   *
-   *     notes.lastIndexOf('re');  // 3
-   *
-   * Returns -1 if [element] is not found.
-   *
-   *     notes.lastIndexOf('fa');  // -1
-   */
+  /// The last index of [element] in this list.
+  ///
+  /// Searches the list backwards from index [start] to 0.
+  ///
+  /// The first time an object `o` is encountered so that `o == element`,
+  /// the index of `o` is returned.
+  /// ```dart
+  /// var notes = ['do', 're', 'mi', 're'];
+  /// notes.lastIndexOf('re', 2); // 1
+  /// ```
+  /// If [start] is not provided, this method searches from the end of the
+  /// list.
+  /// ```dart
+  /// notes.lastIndexOf('re');  // 3
+  /// ```
+  /// Returns -1 if [element] is not found.
+  /// ```dart
+  /// notes.lastIndexOf('fa');  // -1
+  /// ```
   int lastIndexOf(E element, [int? start]);
 
-  /**
-   * Removes all objects from this list;
-   * the length of the list becomes zero.
-   *
-   * Throws an [UnsupportedError], and retains all objects, if this
-   * is a fixed-length list.
-   */
+  /// Removes all objects from this list; the length of the list becomes zero.
+  ///
+  /// The list must be growable.
   void clear();
 
-  /**
-   * Inserts [element] at position [index] in this list.
-   *
-   * This increases the length of the list by one and shifts all objects
-   * at or after the index towards the end of the list.
-   *
-   * The list must be growable.
-   * The [index] value must be non-negative and no greater than [length].
-   */
+  /// Inserts [element] at position [index] in this list.
+  ///
+  /// This increases the length of the list by one and shifts all objects
+  /// at or after the index towards the end of the list.
+  ///
+  /// The list must be growable.
+  /// The [index] value must be non-negative and no greater than [length].
   void insert(int index, E element);
 
-  /**
-   * Inserts all objects of [iterable] at position [index] in this list.
-   *
-   * This increases the length of the list by the length of [iterable] and
-   * shifts all later objects towards the end of the list.
-   *
-   * The list must be growable.
-   * The [index] value must be non-negative and no greater than [length].
-   */
+  /// Inserts all objects of [iterable] at position [index] in this list.
+  ///
+  /// This increases the length of the list by the length of [iterable] and
+  /// shifts all later objects towards the end of the list.
+  ///
+  /// The list must be growable.
+  /// The [index] value must be non-negative and no greater than [length].
   void insertAll(int index, Iterable<E> iterable);
 
-  /**
-   * Overwrites objects of `this` with the objects of [iterable], starting
-   * at position [index] in this list.
-   *
-   *     List<String> list = ['a', 'b', 'c'];
-   *     list.setAll(1, ['bee', 'sea']);
-   *     list.join(', '); // 'a, bee, sea'
-   *
-   * This operation does not increase the length of `this`.
-   *
-   * The [index] must be non-negative and no greater than [length].
-   *
-   * The [iterable] must not have more elements than what can fit from [index]
-   * to [length].
-   *
-   * If `iterable` is based on this list, its values may change /during/ the
-   * `setAll` operation.
-   */
+  /// Overwrites elements with the objects of [iterable].
+  ///
+  /// The elements of [iterable] are written into this list,
+  /// starting at position [index].
+  /// ```dart
+  /// var list = ['a', 'b', 'c', 'd'];
+  /// list.setAll(1, ['bee', 'sea']);
+  /// list.join(', '); // 'a, bee, sea, d'
+  /// ```
+  /// This operation does not increase the length of the list.
+  ///
+  /// The [index] must be non-negative and no greater than [length].
+  ///
+  /// The [iterable] must not have more elements than what can fit from [index]
+  /// to [length].
+  ///
+  /// If `iterable` is based on this list, its values may change _during_ the
+  /// `setAll` operation.
   void setAll(int index, Iterable<E> iterable);
 
-  /**
-   * Removes the first occurrence of [value] from this list.
-   *
-   * Returns true if [value] was in the list, false otherwise.
-   *
-   *     List<String> parts = ['head', 'shoulders', 'knees', 'toes'];
-   *     parts.remove('head'); // true
-   *     parts.join(', ');     // 'shoulders, knees, toes'
-   *
-   * The method has no effect if [value] was not in the list.
-   *
-   *     // Note: 'head' has already been removed.
-   *     parts.remove('head'); // false
-   *     parts.join(', ');     // 'shoulders, knees, toes'
-   *
-   * An [UnsupportedError] occurs if the list is fixed-length.
-   */
+  /// Removes the first occurrence of [value] from this list.
+  ///
+  /// Returns true if [value] was in the list, false otherwise.
+  /// ```dart
+  /// var parts = ['head', 'shoulders', 'knees', 'toes'];
+  /// parts.remove('head'); // true
+  /// parts.join(', ');     // 'shoulders, knees, toes'
+  /// ```
+  /// The method has no effect if [value] was not in the list.
+  /// ```dart
+  /// // Note: 'head' has already been removed.
+  /// parts.remove('head'); // false
+  /// parts.join(', ');     // 'shoulders, knees, toes'
+  /// ```
+  ///
+  /// The list must be growable.
   bool remove(Object? value);
 
-  /**
-   * Removes the object at position [index] from this list.
-   *
-   * This method reduces the length of `this` by one and moves all later objects
-   * down by one position.
-   *
-   * Returns the removed object.
-   *
-   * The [index] must be in the range `0 ≤ index < length`.
-   *
-   * Throws an [UnsupportedError] if this is a fixed-length list. In that case
-   * the list is not modified.
-   */
+  /// Removes the object at position [index] from this list.
+  ///
+  /// This method reduces the length of `this` by one and moves all later objects
+  /// down by one position.
+  ///
+  /// Returns the removed value.
+  ///
+  /// The [index] must be in the range `0 ≤ index < length`.
+  ///
+  /// The list must be growable.
   E removeAt(int index);
 
-  /**
-   * Pops and returns the last object in this list.
-   *
-   * The list must not be empty.
-   *
-   * Throws an [UnsupportedError] if this is a fixed-length list.
-   */
+  /// Removes and returns the last object in this list.
+  ///
+  /// The list must be growable and non-empty.
   E removeLast();
 
-  /**
-   * Removes all objects from this list that satisfy [test].
-   *
-   * An object [:o:] satisfies [test] if [:test(o):] is true.
-   *
-   *     List<String> numbers = ['one', 'two', 'three', 'four'];
-   *     numbers.removeWhere((item) => item.length == 3);
-   *     numbers.join(', '); // 'three, four'
-   *
-   * Throws an [UnsupportedError] if this is a fixed-length list.
-   */
+  /// Removes all objects from this list that satisfy [test].
+  ///
+  /// An object `o` satisfies [test] if `test(o)` is true.
+  /// ```dart
+  /// var numbers = ['one', 'two', 'three', 'four'];
+  /// numbers.removeWhere((item) => item.length == 3);
+  /// numbers.join(', '); // 'three, four'
+  /// ```
+  /// The list must be growable.
   void removeWhere(bool test(E element));
 
-  /**
-   * Removes all objects from this list that fail to satisfy [test].
-   *
-   * An object [:o:] satisfies [test] if [:test(o):] is true.
-   *
-   *     List<String> numbers = ['one', 'two', 'three', 'four'];
-   *     numbers.retainWhere((item) => item.length == 3);
-   *     numbers.join(', '); // 'one, two'
-   *
-   * Throws an [UnsupportedError] if this is a fixed-length list.
-   */
+  /// Removes all objects from this list that fail to satisfy [test].
+  ///
+  /// An object `o` satisfies [test] if `test(o)` is true.
+  /// ```dart
+  /// var numbers = ['one', 'two', 'three', 'four'];
+  /// numbers.retainWhere((item) => item.length == 3);
+  /// numbers.join(', '); // 'one, two'
+  /// ```
+  /// The list must be growable.
   void retainWhere(bool test(E element));
 
-  /**
-   * Returns the concatenation of this list and [other].
-   *
-   * Returns a new list containing the elements of this list followed by
-   * the elements of [other].
-   *
-   * The default behavior is to return a normal growable list.
-   * Some list types may choose to return a list of the same type as themselves
-   * (see [Uint8List.+]);
-   */
+  /// Returns the concatenation of this list and [other].
+  ///
+  /// Returns a new list containing the elements of this list followed by
+  /// the elements of [other].
+  ///
+  /// The default behavior is to return a normal growable list.
+  /// Some list types may choose to return a list of the same type as themselves
+  /// (see [Uint8List.+]);
   List<E> operator +(List<E> other);
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `List<E>` containing the elements of this list at
-   * positions greater than or equal to [start] and less than [end] in the same
-   * order as they occur in this list.
-   *
-   * ```dart
-   * var colors = ["red", "green", "blue", "orange", "pink"];
-   * print(colors.sublist(1, 3)); // [green, blue]
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(colors.sublist(1)); // [green, blue, orange, pink]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `List<E>` containing the elements of this list at
+  /// positions greater than or equal to [start] and less than [end] in the same
+  /// order as they occur in this list.
+  ///
+  /// ```dart
+  /// var colors = ["red", "green", "blue", "orange", "pink"];
+  /// print(colors.sublist(1, 3)); // [green, blue]
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(colors.sublist(1)); // [green, blue, orange, pink]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ [length]
+  /// If `end` is equal to `start`, then the returned list is empty.
   List<E> sublist(int start, [int? end]);
 
-  /**
-   * Returns an [Iterable] that iterates over the objects in the range
-   * [start] inclusive to [end] exclusive.
-   *
-   * The provided range, given by [start] and [end], must be valid at the time
-   * of the call.
-   *
-   * A range from [start] to [end] is valid if `0 <= start <= end <= len`, where
-   * `len` is this list's `length`. The range starts at `start` and has length
-   * `end - start`. An empty range (with `end == start`) is valid.
-   *
-   * The returned [Iterable] behaves like `skip(start).take(end - start)`.
-   * That is, it does *not* throw if this list changes size.
-   *
-   *     List<String> colors = ['red', 'green', 'blue', 'orange', 'pink'];
-   *     Iterable<String> range = colors.getRange(1, 4);
-   *     range.join(', ');  // 'green, blue, orange'
-   *     colors.length = 3;
-   *     range.join(', ');  // 'green, blue'
-   */
+  /// Creates an [Iterable] that iterates over a range of elements.
+  ///
+  /// The returned iterable iterates over the elements of this list
+  /// with positions greater than or equal to [start] and less than [end].
+  ///
+  /// The provided range, [start] and [end], must be valid at the time
+  /// of the call.
+  /// A range from [start] to [end] is valid if 0 ≤ `start` ≤ `end` ≤ [length].
+  /// An empty range (with `end == start`) is valid.
+  ///
+  /// The returned [Iterable] behaves like `skip(start).take(end - start)`.
+  /// That is, it does *not* break if this list changes size, it just
+  /// ends early if it reaches the end of the list early
+  /// (if `end`, or even `start`, becomes greater than [length]).
+  /// ```dart
+  /// List<String> colors = ['red', 'green', 'blue', 'orange', 'pink'];
+  /// Iterable<String> range = colors.getRange(1, 4);
+  /// range.join(', ');  // 'green, blue, orange'
+  /// colors.length = 3;
+  /// range.join(', ');  // 'green, blue'
+  /// ```
   Iterable<E> getRange(int start, int end);
 
-  /**
-   * Copies the objects of [iterable], skipping [skipCount] objects first,
-   * into the range [start], inclusive, to [end], exclusive, of the list.
-   *
-   *     List<int> list1 = [1, 2, 3, 4];
-   *     List<int> list2 = [5, 6, 7, 8, 9];
-   *     // Copies the 4th and 5th items in list2 as the 2nd and 3rd items
-   *     // of list1.
-   *     list1.setRange(1, 3, list2, 3);
-   *     list1.join(', '); // '1, 8, 9, 4'
-   *
-   * The provided range, given by [start] and [end], must be valid.
-   * A range from [start] to [end] is valid if `0 <= start <= end <= len`, where
-   * `len` is this list's `length`. The range starts at `start` and has length
-   * `end - start`. An empty range (with `end == start`) is valid.
-   *
-   * The [iterable] must have enough objects to fill the range from `start`
-   * to `end` after skipping [skipCount] objects.
-   *
-   * If `iterable` is this list, the operation copies the elements
-   * originally in the range from `skipCount` to `skipCount + (end - start)` to
-   * the range `start` to `end`, even if the two ranges overlap.
-   *
-   * If `iterable` depends on this list in some other way, no guarantees are
-   * made.
-   */
+  /// Writes some elements of [iterable] into a range of this list.
+  ///
+  /// Copies the objects of [iterable], skipping [skipCount] objects first,
+  /// into the range from [start], inclusive, to [end], exclusive, of this list.
+  /// ```dart
+  /// var list1 = [1, 2, 3, 4];
+  /// var list2 = [5, 6, 7, 8, 9];
+  /// // Copies the 4th and 5th items in list2 as the 2nd and 3rd items
+  /// // of list1.
+  /// list1.setRange(1, 3, list2, 3);
+  /// list1.join(', '); // '1, 8, 9, 4'
+  /// ```
+  /// The provided range, given by [start] and [end], must be valid.
+  /// A range from [start] to [end] is valid if 0 ≤ `start` ≤ `end` ≤ [length].
+  /// An empty range (with `end == start`) is valid.
+  ///
+  /// The [iterable] must have enough objects to fill the range from `start`
+  /// to `end` after skipping [skipCount] objects.
+  ///
+  /// If `iterable` is this list, the operation correctly copies the elements
+  /// originally in the range from `skipCount` to `skipCount + (end - start)` to
+  /// the range `start` to `end`, even if the two ranges overlap.
+  ///
+  /// If `iterable` depends on this list in some other way, no guarantees are
+  /// made.
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]);
 
-  /**
-   * Removes the objects in the range [start] inclusive to [end] exclusive.
-   *
-   * The provided range, given by [start] and [end], must be valid.
-   * A range from [start] to [end] is valid if `0 <= start <= end <= len`, where
-   * `len` is this list's `length`. The range starts at `start` and has length
-   * `end - start`. An empty range (with `end == start`) is valid.
-   *
-   * Throws an [UnsupportedError] if this is a fixed-length list. In that case
-   * the list is not modified.
-   */
+  /// Removes a range of elements from the list.
+  ///
+  /// Removes the elements with positions greater than or equal to [start]
+  /// and less than [end], from the list.
+  /// This reduces the list's length by `end - start`.
+  ///
+  /// The provided range, given by [start] and [end], must be valid.
+  /// A range from [start] to [end] is valid if 0 ≤ `start` ≤ `end` ≤ [length].
+  /// An empty range (with `end == start`) is valid.
+  ///
+  /// The list must be growable.
   void removeRange(int start, int end);
 
-  /**
-   * Sets the objects in the range [start] inclusive to [end] exclusive
-   * to the given [fillValue].
-   *
-   * The provided range, given by [start] and [end], must be valid.
-   * A range from [start] to [end] is valid if `0 <= start <= end <= len`, where
-   * `len` is this list's `length`. The range starts at `start` and has length
-   * `end - start`. An empty range (with `end == start`) is valid.
-   *
-   * Example:
-   * ```dart
-   *  List<int> list = new List.filled(3);
-   *     list.fillRange(0, 2, 1);
-   *     print(list); //  [1, 1, null]
-   * ```
-   *
-   * If the element type is not nullable, omitting [fillValue] or passing `null`
-   * as [fillValue] will make the `fillRange` fail.
-   */
+  /// Overwrites a range of elements with [fillValue].
+  ///
+  /// Sets the positions greater than or equal to [start] and less than [end],
+  /// to [fillValue].
+  ///
+  /// The provided range, given by [start] and [end], must be valid.
+  /// A range from [start] to [end] is valid if 0 ≤ `start` ≤ `end` ≤ [length].
+  /// An empty range (with `end == start`) is valid.
+  ///
+  /// Example:
+  /// ```dart
+  /// var list = List.filled(5, -1);
+  /// print(list); //  [-1, -1, -1, -1, -1]
+  /// list.fillRange(1, 3, 4);
+  /// print(list); //  [-1, 4, 4, -1, -1]
+  /// ```
+  ///
+  /// If the element type is not nullable, the [fillValue] must be provided and
+  /// must be non-`null`.
   void fillRange(int start, int end, [E? fillValue]);
 
-  /**
-   * Removes the objects in the range [start] inclusive to [end] exclusive
-   * and inserts the contents of [replacement] in its place.
-   *
-   *     List<int> list = [1, 2, 3, 4, 5];
-   *     list.replaceRange(1, 4, [6, 7]);
-   *     list.join(', '); // '1, 6, 7, 5'
-   *
-   * The provided range, given by [start] and [end], must be valid.
-   * A range from [start] to [end] is valid if `0 <= start <= end <= len`, where
-   * `len` is this list's `length`. The range starts at `start` and has length
-   * `end - start`. An empty range (with `end == start`) is valid.
-   *
-   * This method does not work on fixed-length lists, even when [replacement]
-   * has the same number of elements as the replaced range. In that case use
-   * [setRange] instead.
-   */
+  /// Replaces a range of elements with the elements of [replacement].
+  ///
+  /// Removes the objects in the range from [start] to [end],
+  /// then inserts the elements of [replacements] at [start].
+  /// ```dart
+  /// var list = [1, 2, 3, 4, 5];
+  /// list.replaceRange(1, 4, [6, 7]);
+  /// list.join(', '); // '1, 6, 7, 5'
+  /// ```
+  /// The provided range, given by [start] and [end], must be valid.
+  /// A range from [start] to [end] is valid if 0 ≤ `start` ≤ `end` ≤ [length].
+  /// An empty range (with `end == start`) is valid.
+  ///
+  /// The operation `list.replaceRange(start, end, replacements)`
+  /// is roughly equivalent to:
+  /// ```dart
+  /// list.removeRange(start, end);
+  /// list.insertAll(start, replacements);
+  /// ```
+  /// but may be more efficient.
+  ///
+  /// The list must be growable.
+  /// This method does not work on fixed-length lists, even when [replacement]
+  /// has the same number of elements as the replaced range. In that case use
+  /// [setRange] instead.
   void replaceRange(int start, int end, Iterable<E> replacement);
 
-  /**
-   * Returns an unmodifiable [Map] view of `this`.
-   *
-   * The map uses the indices of this list as keys and the corresponding objects
-   * as values. The `Map.keys` [Iterable] iterates the indices of this list
-   * in numerical order.
-   *
-   *     List<String> words = ['fee', 'fi', 'fo', 'fum'];
-   *     Map<int, String> map = words.asMap();  // {0: fee, 1: fi, 2: fo, 3: fum}
-   *     map[0] + map[1];   // 'feefi';
-   *     map.keys.toList(); // [0, 1, 2, 3]
-   */
+  /// An unmodifiable [Map] view of this list.
+  ///
+  /// The map uses the indices of this list as keys and the corresponding objects
+  /// as values. The `Map.keys` [Iterable] iterates the indices of this list
+  /// in numerical order.
+  /// ```dart
+  /// var words = ['fee', 'fi', 'fo', 'fum'];
+  /// var map = words.asMap();  // {0: fee, 1: fi, 2: fo, 3: fum}
+  /// map[0] + map[1];   // 'feefi';
+  /// map.keys.toList(); // [0, 1, 2, 3]
+  /// ```
   Map<int, E> asMap();
 
-  /**
-  * Whether this list is equal to [other].
-  *
-  * Lists are, by default, only equal to themselves.
-  * Even if [other] is also a list, the equality comparison
-  * does not compare the elements of the two lists.
-  */
+  /// Whether this list is equal to [other].
+  ///
+  /// Lists are, by default, only equal to themselves.
+  /// Even if [other] is also a list, the equality comparison
+  /// does not compare the elements of the two lists.
   bool operator ==(Object other);
 }
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index cbb1608..9c5572c 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -4,399 +4,350 @@
 
 part of dart.core;
 
-/**
- * A collection of key/value pairs, from which you retrieve a value
- * using its associated key.
- *
- * There is a finite number of keys in the map,
- * and each key has exactly one value associated with it.
- *
- * Maps, and their keys and values, can be iterated.
- * The order of iteration is defined by the individual type of map.
- * Examples:
- *
- * * The plain [HashMap] is unordered (no order is guaranteed),
- * * the [LinkedHashMap] iterates in key insertion order,
- * * and a sorted map like [SplayTreeMap] iterates the keys in sorted order.
- *
- * It is generally not allowed to modify the map (add or remove keys) while
- * an operation is being performed on the map, for example in functions called
- * during a [forEach] or [putIfAbsent] call.
- * Modifying the map while iterating the keys or values
- * may also break the iteration.
- *
- * It is generally not allowed to modify the equality of keys (and thus not
- * their hashcode) while they are in the map. Some specialized subtypes may be
- * more permissive, in which case they should document this behavior.
- */
+/// A collection of key/value pairs, from which you retrieve a value
+/// using its associated key.
+///
+/// There is a finite number of keys in the map,
+/// and each key has exactly one value associated with it.
+///
+/// Maps, and their keys and values, can be iterated.
+/// The order of iteration is defined by the individual type of map.
+/// Examples:
+///
+/// * The plain [HashMap] is unordered (no order is guaranteed),
+/// * the [LinkedHashMap] iterates in key insertion order,
+/// * and a sorted map like [SplayTreeMap] iterates the keys in sorted order.
+///
+/// It is generally not allowed to modify the map (add or remove keys) while
+/// an operation is being performed on the map, for example in functions called
+/// during a [forEach] or [putIfAbsent] call.
+/// Modifying the map while iterating the keys or values
+/// may also break the iteration.
+///
+/// It is generally not allowed to modify the equality of keys (and thus not
+/// their hashcode) while they are in the map. Some specialized subtypes may be
+/// more permissive, in which case they should document this behavior.
 abstract class Map<K, V> {
-  /**
-   * Creates a Map instance with the default implementation, [LinkedHashMap].
-   *
-   * This constructor is equivalent to the non-const map literal `<K,V>{}`.
-   *
-   * A `LinkedHashMap` requires the keys to implement compatible
-   * `operator==` and `hashCode`, and it allows null as a key.
-   * It iterates in key insertion order.
-   */
+  /// Creates an empty [LinkedHashMap].
+  ///
+  /// This constructor is equivalent to the non-const map literal `<K,V>{}`.
+  ///
+  /// A `LinkedHashMap` requires the keys to implement compatible
+  /// `operator==` and `hashCode`.
+  /// It iterates in key insertion order.
   external factory Map();
 
-  /**
-   * Creates a [LinkedHashMap] instance that contains all key/value pairs of
-   * [other].
-   *
-   * The keys must all be instances of [K] and the values of [V].
-   * The [other] map itself can have any type.
-   *
-   * A `LinkedHashMap` requires the keys to implement compatible
-   * `operator==` and `hashCode`, and it allows `null` as a key.
-   * It iterates in key insertion order.
-   */
+  /// Creates a [LinkedHashMap] with the same keys and values as [other].
+  ///
+  /// The keys must all be instances of [K] and the values of [V].
+  /// The [other] map itself can have any type, unlike for [Map.of],
+  /// and the key and value types are checked (and can fail) at run-time.
+  ///
+  /// Prefer using [Map.of] when possible, and only use `Map.from`
+  /// to create a new map with more precise types than the original,
+  /// and when it's known that all the keys and values have those
+  /// more precise types.
+  ///
+  /// A `LinkedHashMap` requires the keys to implement compatible
+  /// `operator==` and `hashCode`.
+  /// It iterates in key insertion order.
   factory Map.from(Map other) = LinkedHashMap<K, V>.from;
 
-  /**
-   * Creates a [LinkedHashMap] with the same keys and values as [other].
-   *
-   * A `LinkedHashMap` requires the keys to implement compatible
-   * `operator==` and `hashCode`, and it allows `null` as a key.
-   * It iterates in key insertion order.
-   */
+  /// Creates a [LinkedHashMap] with the same keys and values as [other].
+  ///
+  /// A `LinkedHashMap` requires the keys to implement compatible
+  /// `operator==` and `hashCode`, and it allows `null` as a key.
+  /// It iterates in key insertion order.
   factory Map.of(Map<K, V> other) = LinkedHashMap<K, V>.of;
 
-  /**
-   * Creates an unmodifiable hash based map containing the entries of [other].
-   *
-   * The keys must all be instances of [K] and the values of [V].
-   * The [other] map itself can have any type.
-   *
-   * The map requires the keys to implement compatible
-   * `operator==` and `hashCode`, and it allows `null` as a key.
-   * The created map iterates keys in a fixed order,
-   * preserving the order provided by [other].
-   *
-   * The resulting map behaves like the result of [Map.from],
-   * except that the map returned by this constructor is not modifiable.
-   */
+  /// Creates an unmodifiable hash-based map containing the entries of [other].
+  ///
+  /// The keys must all be instances of [K] and the values of [V].
+  /// The [other] map itself can have any type.
+  ///
+  /// The map requires the keys to implement compatible
+  /// `operator==` and `hashCode`.
+  /// The created map iterates keys in a fixed order,
+  /// preserving the order provided by [other].
+  ///
+  /// The resulting map behaves like the result of [Map.from],
+  /// except that the map returned by this constructor is not modifiable.
   external factory Map.unmodifiable(Map<dynamic, dynamic> other);
 
-  /**
-   * Creates an identity map with the default implementation, [LinkedHashMap].
-   *
-   * An identity map uses [identical] for equality and [identityHashCode]
-   * for hash codes of keys instead of the intrinsic [Object.==] and
-   * [Object.hashCode] of the keys.
-   *
-   * The returned map allows `null` as a key.
-   * It iterates in key insertion order.
-   */
+  /// Creates an identity map with the default implementation, [LinkedHashMap].
+  ///
+  /// An identity map uses [identical] for equality and [identityHashCode]
+  /// for hash codes of keys instead of the intrinsic [Object.==] and
+  /// [Object.hashCode] of the keys.
+  ///
+  /// The map iterates in key insertion order.
   factory Map.identity() = LinkedHashMap<K, V>.identity;
 
-  /**
-   * Creates a Map instance in which the keys and values are computed from the
-   * [iterable].
-   *
-   * The created map is a [LinkedHashMap].
-   * A `LinkedHashMap` requires the keys to implement compatible
-   * `operator==` and `hashCode`, and it allows null as a key.
-   * It iterates in key insertion order.
-   *
-   * For each element of the [iterable] this constructor computes a key/value
-   * pair, by applying [key] and [value] respectively.
-   *
-   * The example below creates a new Map from a List. The keys of `map` are
-   * `list` values converted to strings, and the values of the `map` are the
-   * squares of the `list` values:
-   *
-   *     List<int> list = [1, 2, 3];
-   *     Map<String, int> map = new Map.fromIterable(list,
-   *         key: (item) => item.toString(),
-   *         value: (item) => item * item);
-   *
-   *     map['1'] + map['2']; // 1 + 4
-   *     map['3'] - map['2']; // 9 - 4
-   *
-   * If no values are specified for [key] and [value] the default is the
-   * identity function.
-   *
-   * In the following example, the keys and corresponding values of `map`
-   * are `list` values:
-   *
-   *     map = new Map.fromIterable(list);
-   *     map[1] + map[2]; // 1 + 2
-   *     map[3] - map[2]; // 3 - 2
-   *
-   * The keys computed by the source [iterable] do not need to be unique. The
-   * last occurrence of a key will simply overwrite any previous value.
-   */
+  /// Creates a Map instance in which the keys and values are computed from the
+  /// [iterable].
+  ///
+  /// For each element of the [iterable], a key/value pair is computed
+  /// by applying [key] and [value] respectively to the element of the iterable.
+  ///
+  /// Equivalent to the map literal:
+  /// ```dart
+  /// <K, V>{for (var v in iterable) key(v): value(v)}
+  /// ```
+  /// The literal is generally preferable because it allows
+  /// for a more precise typing.
+  ///
+  /// The example below creates a new map from a list of integers.
+  /// The keys of `map` are the `list` values converted to strings,
+  /// and the values of the `map` are the squares of the `list` values:
+  /// ```dart
+  /// List<int> list = [1, 2, 3];
+  /// var map = Map<String, int>.fromIterable(list,
+  ///     key: (item) => item.toString(),
+  ///     value: (item) => item * item);
+  /// // map is {"1": 1, "2": 4, "3": 9}
+  /// ```
+  /// If no values are specified for [key] and [value],
+  /// the default is the identity function.
+  /// In that case, the iterable element must be assignable to the
+  /// key or value type of the created map.
+  ///
+  /// In the following example, the keys and corresponding values of `map`
+  /// are the `list` values directly:
+  /// ```dart
+  /// var map = Map<int, int>.fromIterable(list);
+  /// // map is {1: 1, 2: 2, 3: 3}
+  /// ```
+  /// The keys computed by the source [iterable] do not need to be unique.
+  /// The last occurrence of a key will overwrite
+  /// the value of any previous occurrence.
+  ///
+  /// The created map is a [LinkedHashMap].
+  /// A `LinkedHashMap` requires the keys to implement compatible
+  /// `operator==` and `hashCode`.
+  /// It iterates in key insertion order.
   factory Map.fromIterable(Iterable iterable,
-      {K key(element)?, V value(element)?}) = LinkedHashMap<K, V>.fromIterable;
+      {K key(dynamic element)?,
+      V value(dynamic element)?}) = LinkedHashMap<K, V>.fromIterable;
 
-  /**
-   * Creates a Map instance associating the given [keys] to [values].
-   *
-   * The created map is a [LinkedHashMap].
-   * A `LinkedHashMap` requires the keys to implement compatible
-   * `operator==` and `hashCode`, and it allows null as a key.
-   * It iterates in key insertion order.
-   *
-   * This constructor iterates over [keys] and [values] and maps each element of
-   * [keys] to the corresponding element of [values].
-   *
-   *     List<String> letters = ['b', 'c'];
-   *     List<String> words = ['bad', 'cat'];
-   *     Map<String, String> map = new Map.fromIterables(letters, words);
-   *     map['b'] + map['c'];  // badcat
-   *
-   * If [keys] contains the same object multiple times, the last occurrence
-   * overwrites the previous value.
-   *
-   * The two [Iterable]s must have the same length.
-   */
+  /// Creates a map associating the given [keys] to the given [values].
+  ///
+  /// The map construction iterates over [keys] and [values] simultaneously,
+  /// and adds an entry to the map for each pair of key and value.
+  /// ```dart
+  /// List<String> letters = ['b', 'c'];
+  /// List<String> words = ['bad', 'cat'];
+  /// var map = Map.fromIterables(letters, words);
+  /// // map is {"b": "bad", "c": "cat"}
+  /// ```
+  /// If [keys] contains the same object multiple times,
+  /// the value of the last occurrence overwrites any previous value.
+  ///
+  /// The two [Iterable]s must have the same length.
+  ///
+  /// The created map is a [LinkedHashMap].
+  /// A `LinkedHashMap` requires the keys to implement compatible
+  /// `operator==` and `hashCode`.
+  /// It iterates in key insertion order.
   factory Map.fromIterables(Iterable<K> keys, Iterable<V> values) =
       LinkedHashMap<K, V>.fromIterables;
 
-  /**
-   * Adapts [source] to be a `Map<K2, V2>`.
-   *
-   * Any time the set would produce a key or value that is not a [K2] or [V2],
-   * the access will throw.
-   *
-   * Any time [K2] key or [V2] value is attempted added into the adapted map,
-   * the store will throw unless the key is also an instance of [K] and
-   * the value is also an instance of [V].
-   *
-   * 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>`.
-   */
+  /// Adapts [source] to be a `Map<K2, V2>`.
+  ///
+  /// Any time the set would produce a key or value that is not a [K2] or [V2],
+  /// the access will throw.
+  ///
+  /// Any time [K2] key or [V2] value is attempted added into the adapted map,
+  /// the store will throw unless the key is also an instance of [K] and
+  /// the value is also an instance of [V].
+  ///
+  /// 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>`.
   static Map<K2, V2> castFrom<K, V, K2, V2>(Map<K, V> source) =>
       CastMap<K, V, K2, V2>(source);
 
-  /**
-   * Creates a new map and adds all entries.
-   *
-   * Returns a new `Map<K, V>` where all entries of [entries]
-   * have been added in iteration order.
-   *
-   * If multiple [entries] have the same key,
-   * later occurrences overwrite the earlier ones.
-   */
+  /// Creates a new map and adds all entries.
+  ///
+  /// Returns a new `Map<K, V>` where all entries of [entries]
+  /// have been added in iteration order.
+  ///
+  /// If multiple [entries] have the same key,
+  /// later occurrences overwrite the value of the earlier ones.
+  ///
+  /// Equivalent to the map literal:
+  /// ```dart
+  /// <K, V>{for (var e in entries) e.key: e.value}
+  /// ```
   factory Map.fromEntries(Iterable<MapEntry<K, V>> entries) =>
       <K, V>{}..addEntries(entries);
 
-  /**
-   * Provides a view of this map as having [RK] keys and [RV] instances,
-   * if necessary.
-   *
-   * If this map is already a `Map<RK, RV>`, it is returned unchanged.
-   *
-   * If this set contains only keys of type [RK] and values of type [RV],
-   * all read operations will work correctly.
-   * If any operation exposes a non-[RK] key or non-[RV] value,
-   * the operation will throw instead.
-   *
-   * Entries added to the map must be valid for both a `Map<K, V>` and a
-   * `Map<RK, RV>`.
-   */
+  /// Provides a view of this map as having [RK] keys and [RV] instances,
+  /// if necessary.
+  ///
+  /// If this map is already a `Map<RK, RV>`, it is returned unchanged.
+  ///
+  /// If this set contains only keys of type [RK] and values of type [RV],
+  /// all read operations will work correctly.
+  /// If any operation exposes a non-[RK] key or non-[RV] value,
+  /// the operation will throw instead.
+  ///
+  /// Entries added to the map must be valid for both a `Map<K, V>` and a
+  /// `Map<RK, RV>`.
   Map<RK, RV> cast<RK, RV>();
 
-  /**
-   * Returns true if this map contains the given [value].
-   *
-   * Returns true if any of the values in the map are equal to `value`
-   * according to the `==` operator.
-   */
+  /// Whether this map contains the given [value].
+  ///
+  /// Returns true if any of the values in the map are equal to `value`
+  /// according to the `==` operator.
   bool containsValue(Object? value);
 
-  /**
-   * Returns true if this map contains the given [key].
-   *
-   * Returns true if any of the keys in the map are equal to `key`
-   * according to the equality used by the map.
-   */
+  /// Whether this map contains the given [key].
+  ///
+  /// Returns true if any of the keys in the map are equal to `key`
+  /// according to the equality used by the map.
   bool containsKey(Object? key);
 
-  /**
-   * Returns the value for the given [key] or null if [key] is not in the map.
-   *
-   * Some maps allow keys to have `null` as a value.
-   * For those maps, a lookup using this operator cannot distinguish between a
-   * key not being in the map and the key having a `null` value.
-   * Methods like [containsKey] or [putIfAbsent] can be used if the distinction
-   * is important.
-   */
+  /// The value for the given [key], or `null` if [key] is not in the map.
+  ///
+  /// Some maps allow `null` as a value.
+  /// For those maps, a lookup using this operator cannot distinguish between a
+  /// key not being in the map, and the key being there with a `null` value.
+  /// Methods like [containsKey] or [putIfAbsent] can be used if the distinction
+  /// is important.
   V? operator [](Object? key);
 
-  /**
-   * Associates the [key] with the given [value].
-   *
-   * If the key was already in the map, its associated value is changed.
-   * Otherwise the key/value pair is added to the map.
-   */
+  /// Associates the [key] with the given [value].
+  ///
+  /// If the key was already in the map, its associated value is changed.
+  /// Otherwise the key/value pair is added to the map.
   void operator []=(K key, V value);
 
-  /**
-   * The map entries of [this].
-   */
+  /// The map entries of [this].
   Iterable<MapEntry<K, V>> get entries;
 
-  /**
-   * Returns a new map where all entries of this map are transformed by
-   * the given [f] function.
-   */
-  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> f(K key, V value));
+  /// Returns a new map where all entries of this map are transformed by
+  /// the given [convert] function.
+  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> convert(K key, V value));
 
-  /**
-   * Adds all key/value pairs of [newEntries] to this map.
-   *
-   * If a key of [newEntries] is already in this map,
-   * the corresponding value is overwritten.
-   *
-   * The operation is equivalent to doing `this[entry.key] = entry.value`
-   * for each [MapEntry] of the iterable.
-   */
+  /// Adds all key/value pairs of [newEntries] to this map.
+  ///
+  /// If a key of [newEntries] is already in this map,
+  /// the corresponding value is overwritten.
+  ///
+  /// The operation is equivalent to doing `this[entry.key] = entry.value`
+  /// for each [MapEntry] of the iterable.
   void addEntries(Iterable<MapEntry<K, V>> newEntries);
 
-  /**
-   * Updates the value for the provided [key].
-   *
-   * Returns the new value of the key.
-   *
-   * If the key is present, invokes [update] with the current value and stores
-   * the new value in the map.
-   *
-   * If the key is not present and [ifAbsent] is provided, calls [ifAbsent]
-   * and adds the key with the returned value to the map.
-   *
-   * It's an error if the key is not present and [ifAbsent] is not provided.
-   */
+  /// Updates the value for the provided [key].
+  ///
+  /// Returns the new value associated with the key.
+  ///
+  /// If the key is present, invokes [update] with the current value and stores
+  /// the new value in the map.
+  ///
+  /// If the key is not present and [ifAbsent] is provided, calls [ifAbsent]
+  /// and adds the key with the returned value to the map.
+  ///
+  /// If the key is not present, [ifAbsent] must be provided.
   V update(K key, V update(V value), {V ifAbsent()?});
 
-  /**
-   * Updates all values.
-   *
-   * Iterates over all entries in the map and updates them with the result
-   * of invoking [update].
-   */
+  /// Updates all values.
+  ///
+  /// Iterates over all entries in the map and updates them with the result
+  /// of invoking [update].
   void updateAll(V update(K key, V value));
 
-  /**
-   * Removes all entries of this map that satisfy the given [predicate].
-   */
-  void removeWhere(bool predicate(K key, V value));
+  /// Removes all entries of this map that satisfy the given [test].
+  void removeWhere(bool test(K key, V value));
 
-  /**
-   * Look up the value of [key], or add a new value if it isn't there.
-   *
-   * Returns the value associated to [key], if there is one.
-   * Otherwise calls [ifAbsent] to get a new value, associates [key] to
-   * that value, and then returns the new value.
-   *
-   *     Map<String, int> scores = {'Bob': 36};
-   *     for (var key in ['Bob', 'Rohan', 'Sophena']) {
-   *       scores.putIfAbsent(key, () => key.length);
-   *     }
-   *     scores['Bob'];      // 36
-   *     scores['Rohan'];    //  5
-   *     scores['Sophena'];  //  7
-   *
-   * Calling [ifAbsent] must not add or remove keys from the map.
-   */
+  /// Look up the value of [key], or add a new entry if it isn't there.
+  ///
+  /// Returns the value associated to [key], if there is one.
+  /// Otherwise calls [ifAbsent] to get a new value, associates [key] to
+  /// that value, and then returns the new value.
+  /// ```dart
+  /// Map<String, int> scores = {'Bob': 36};
+  /// for (var key in ['Bob', 'Rohan', 'Sophena']) {
+  ///   scores.putIfAbsent(key, () => key.length);
+  /// }
+  /// scores['Bob'];      // 36
+  /// scores['Rohan'];    //  5
+  /// scores['Sophena'];  //  7
+  /// ```
+  /// Calling [ifAbsent] must not add or remove keys from the map.
   V putIfAbsent(K key, V ifAbsent());
 
-  /**
-   * Adds all key/value pairs of [other] to this map.
-   *
-   * If a key of [other] is already in this map, its value is overwritten.
-   *
-   * The operation is equivalent to doing `this[key] = value` for each key
-   * and associated value in other. It iterates over [other], which must
-   * therefore not change during the iteration.
-   */
+  /// Adds all key/value pairs of [other] to this map.
+  ///
+  /// If a key of [other] is already in this map, its value is overwritten.
+  ///
+  /// The operation is equivalent to doing `this[key] = value` for each key
+  /// and associated value in other. It iterates over [other], which must
+  /// therefore not change during the iteration.
   void addAll(Map<K, V> other);
 
-  /**
-   * Removes [key] and its associated value, if present, from the map.
-   *
-   * Returns the value associated with `key` before it was removed.
-   * Returns `null` if `key` was not in the map.
-   *
-   * Note that values can be `null` and a returned `null` value doesn't
-   * always mean that the key was absent.
-   */
+  /// Removes [key] and its associated value, if present, from the map.
+  ///
+  /// Returns the value associated with `key` before it was removed.
+  /// Returns `null` if `key` was not in the map.
+  ///
+  /// Note that some maps allow `null` as a value,
+  /// so a returned `null` value doesn't always mean that the key was absent.
   V? remove(Object? key);
 
-  /**
-   * Removes all pairs from the map.
-   *
-   * After this, the map is empty.
-   */
+  /// Removes all entries from the map.
+  ///
+  /// After this, the map is empty.
   void clear();
 
-  /**
-   * Applies [f] to each key/value pair of the map.
-   *
-   * Calling `f` must not add or remove keys from the map.
-   */
-  void forEach(void f(K key, V value));
+  /// Applies [action] to each key/value pair of the map.
+  ///
+  /// Calling `action` must not add or remove keys from the map.
+  void forEach(void action(K key, V value));
 
-  /**
-   * The keys of [this].
-   *
-   * The returned iterable has efficient `length` and `contains` operations,
-   * based on [length] and [containsKey] of the map.
-   *
-   * The order of iteration is defined by the individual `Map` implementation,
-   * but must be consistent between changes to the map.
-   *
-   * Modifying the map while iterating the keys
-   * may break the iteration.
-   */
+  /// The keys of [this].
+  ///
+  /// The returned iterable has efficient `length` and `contains` operations,
+  /// based on [length] and [containsKey] of the map.
+  ///
+  /// The order of iteration is defined by the individual `Map` implementation,
+  /// but must be consistent between changes to the map.
+  ///
+  /// Modifying the map while iterating the keys may break the iteration.
   Iterable<K> get keys;
 
-  /**
-   * The values of [this].
-   *
-   * The values are iterated in the order of their corresponding keys.
-   * This means that iterating [keys] and [values] in parallel will
-   * provide matching pairs of keys and values.
-   *
-   * The returned iterable has an efficient `length` method based on the
-   * [length] of the map. Its [Iterable.contains] method is based on
-   * `==` comparison.
-   *
-   * Modifying the map while iterating the
-   * values may break the iteration.
-   */
+  /// The values of [this].
+  ///
+  /// The values are iterated in the order of their corresponding keys.
+  /// This means that iterating [keys] and [values] in parallel will
+  /// provide matching pairs of keys and values.
+  ///
+  /// The returned iterable has an efficient `length` method based on the
+  /// [length] of the map. Its [Iterable.contains] method is based on
+  /// `==` comparison.
+  ///
+  /// Modifying the map while iterating the values may break the iteration.
   Iterable<V> get values;
 
-  /**
-   * The number of key/value pairs in the map.
-   */
+  /// The number of key/value pairs in the map.
   int get length;
 
-  /**
-   * Returns true if there is no key/value pair in the map.
-   */
+  /// Whether there is no key/value pair in the map.
   bool get isEmpty;
 
-  /**
-   * Returns true if there is at least one key/value pair in the map.
-   */
+  /// Whether there is at least one key/value pair in the map.
   bool get isNotEmpty;
 }
 
-/**
- * A key/value pair representing an entry in a [Map].
- */
+/// A key/value pair representing an entry in a [Map].
 class MapEntry<K, V> {
-  /** The key of the entry. */
+  /// The key of the entry.
   final K key;
 
-  /** The value associated to [key] in the map. */
+  /// The value associated to [key] in the map.
   final V value;
 
-  /** Creates an entry with [key] and [value]. */
+  /// Creates an entry with [key] and [value].
   const factory MapEntry(K key, V value) = MapEntry<K, V>._;
 
   const MapEntry._(this.key, this.value);
diff --git a/sdk/lib/core/null.dart b/sdk/lib/core/null.dart
index f8588a1..eb7a006 100644
--- a/sdk/lib/core/null.dart
+++ b/sdk/lib/core/null.dart
@@ -4,13 +4,22 @@
 
 part of dart.core;
 
-/**
- * The reserved word `null` denotes an object that is the sole instance of
- * this class.
- *
- * It is a compile-time error for a class to attempt to extend or implement
- * [Null].
- */
+/// The reserved word `null` denotes an object that is the sole instance of
+/// this class.
+///
+/// The `Null` class is the only class which does not implement `Object`.
+/// It is a compile-time error for a class to attempt to extend or implement
+/// [Null].
+///
+/// The language contains a number of specialized operators for working with
+/// `null` value. Examples:
+/// ```dart
+/// e1!       // Throws if e1 is null.
+/// e2 ?? e3  // Same as e2, unless e2 is null, then use value of e3
+/// x ??= e4  // Same as x unless x is null, then same as `x = e4`.
+/// e5?.foo() // call `foo` on e5, unless e5 is null.
+/// [...? e6] // spreads e6 into the list literal, unless e6 is null.
+/// ```
 @pragma("vm:entry-point")
 class Null {
   factory Null._uninstantiable() {
@@ -19,6 +28,6 @@
 
   external int get hashCode;
 
-  /** Returns the string `"null"`. */
+  /// Returns the string `"null"`.
   String toString() => "null";
 }
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 55bb910..36c8fec 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -4,470 +4,482 @@
 
 part of dart.core;
 
-/**
- * An integer or floating-point number.
- *
- * It is a compile-time error for any type other than [int] or [double]
- * to attempt to extend or implement num.
- */
+/// An integer or floating-point number.
+///
+/// It is a compile-time error for any type other than [int] or [double]
+/// to attempt to extend or implement `num`.
 abstract class num implements Comparable<num> {
-  /**
-   * Test whether this value is numerically equal to `other`.
-   *
-   * If both operands are doubles, they are equal if they have the same
-   * representation, except that:
-   *
-   *   * zero and minus zero (0.0 and -0.0) are considered equal. They
-   *     both have the numerical value zero.
-   *   * NaN is not equal to anything, including NaN. If either operand is
-   *     NaN, the result is always false.
-   *
-   * If one operand is a double and the other is an int, they are equal if
-   * the double has an integer value (finite with no fractional part) and
-   * `identical(doubleValue.toInt(), intValue)` is true.
-   *
-   * If both operands are integers, they are equal if they have the same value.
-   *
-   * Returns false if `other` is not a [num].
-   *
-   * Notice that the behavior for NaN is non-reflexive. This means that
-   * equality of double values is not a proper equality relation, as is
-   * otherwise required of `operator==`. Using NaN in, e.g., a [HashSet]
-   * will fail to work. The behavior is the standard IEEE-754 equality of
-   * doubles.
-   *
-   * If you can avoid NaN values, the remaining doubles do have a proper
-   * equality relation, and can be used safely.
-   *
-   * Use [compareTo] for a comparison that distinguishes zero and minus zero,
-   * and that considers NaN values as equal.
-   */
+  /// Test whether this value is numerically equal to `other`.
+  ///
+  /// If both operands are [double]s, they are equal if they have the same
+  /// representation, except that:
+  ///
+  ///   * zero and minus zero (0.0 and -0.0) are considered equal. They
+  ///     both have the numerical value zero.
+  ///   * NaN is not equal to anything, including NaN. If either operand is
+  ///     NaN, the result is always false.
+  ///
+  /// If one operand is a [double] and the other is an [int], they are equal if
+  /// the double has an integer value (finite with no fractional part) and
+  /// the numbers have the same numerical value.
+  ///
+  /// If both operands are integers, they are equal if they have the same value.
+  ///
+  /// Returns false if [other] is not a [num].
+  ///
+  /// Notice that the behavior for NaN is non-reflexive. This means that
+  /// equality of double values is not a proper equality relation, as is
+  /// otherwise required of `operator==`. Using NaN in, e.g., a [HashSet]
+  /// will fail to work. The behavior is the standard IEEE-754 equality of
+  /// doubles.
+  ///
+  /// If you can avoid NaN values, the remaining doubles do have a proper
+  /// equality relation, and can be used safely.
+  ///
+  /// Use [compareTo] for a comparison that distinguishes zero and minus zero,
+  /// and that considers NaN values as equal.
   bool operator ==(Object other);
 
-  /**
-   * Returns a hash code for a numerical value.
-   *
-   * The hash code is compatible with equality. It returns the same value
-   * for an [int] and a [double] with the same numerical value, and therefore
-   * the same value for the doubles zero and minus zero.
-   *
-   * No guarantees are made about the hash code of NaN values.
-   */
+  /// Returns a hash code for a numerical value.
+  ///
+  /// The hash code is compatible with equality. It returns the same value
+  /// for an [int] and a [double] with the same numerical value, and therefore
+  /// the same value for the doubles zero and minus zero.
+  ///
+  /// No guarantees are made about the hash code of NaN values.
   int get hashCode;
 
-  /**
-   * Compares this to `other`.
-   *
-   * Returns a negative number if `this` is less than `other`, zero if they are
-   * equal, and a positive number if `this` is greater than `other`.
-   *
-   * The ordering represented by this method is a total ordering of [num]
-   * values. All distinct doubles are non-equal, as are all distinct integers,
-   * but integers are equal to doubles if they have the same numerical
-   * value.
-   *
-   * For doubles, the `compareTo` operation is different from the partial
-   * ordering given by [operator==], [operator<] and [operator>]. For example,
-   * IEEE doubles impose that `0.0 == -0.0` and all comparison operations on
-   * NaN return false.
-   *
-   * This function imposes a complete ordering for doubles. When using
-   * `compareTo` the following properties hold:
-   *
-   * - All NaN values are considered equal, and greater than any numeric value.
-   * - -0.0 is less than 0.0 (and the integer 0), but greater than any non-zero
-   *    negative value.
-   * - Negative infinity is less than all other values and positive infinity is
-   *   greater than all non-NaN values.
-   * - All other values are compared using their numeric value.
-   *
-   * Examples:
-   * ```
-   * print(1.compareTo(2)); // => -1
-   * print(2.compareTo(1)); // => 1
-   * print(1.compareTo(1)); // => 0
-   *
-   * // The following comparisons yield different results than the
-   * // corresponding comparison operators.
-   * print((-0.0).compareTo(0.0));  // => -1
-   * print(double.nan.compareTo(double.nan));  // => 0
-   * print(double.infinity.compareTo(double.nan)); // => -1
-   *
-   * // -0.0, and NaN comparison operators have rules imposed by the IEEE
-   * // standard.
-   * print(-0.0 == 0.0); // => true
-   * print(double.nan == double.nan);  // => false
-   * print(double.infinity < double.nan);  // => false
-   * print(double.nan < double.infinity);  // => false
-   * print(double.nan == double.infinity);  // => false
-   * ```
-   */
+  /// Compares this to `other`.
+  ///
+  /// Returns a negative number if `this` is less than `other`, zero if they are
+  /// equal, and a positive number if `this` is greater than `other`.
+  ///
+  /// The ordering represented by this method is a total ordering of [num]
+  /// values. All distinct doubles are non-equal, as are all distinct integers,
+  /// but integers are equal to doubles if they have the same numerical
+  /// value.
+  ///
+  /// For doubles, the `compareTo` operation is different from the partial
+  /// ordering given by [operator==], [operator<] and [operator>]. For example,
+  /// IEEE doubles impose that `0.0 == -0.0` and all comparison operations on
+  /// NaN return false.
+  ///
+  /// This function imposes a complete ordering for doubles. When using
+  /// `compareTo` the following properties hold:
+  ///
+  /// - All NaN values are considered equal, and greater than any numeric value.
+  /// - -0.0 is less than 0.0 (and the integer 0), but greater than any non-zero
+  ///    negative value.
+  /// - Negative infinity is less than all other values and positive infinity is
+  ///   greater than all non-NaN values.
+  /// - All other values are compared using their numeric value.
+  ///
+  /// Examples:
+  /// ```
+  /// print(1.compareTo(2)); // => -1
+  /// print(2.compareTo(1)); // => 1
+  /// print(1.compareTo(1)); // => 0
+  ///
+  /// // The following comparisons yield different results than the
+  /// // corresponding comparison operators.
+  /// print((-0.0).compareTo(0.0));  // => -1
+  /// print(double.nan.compareTo(double.nan));  // => 0
+  /// print(double.infinity.compareTo(double.nan)); // => -1
+  ///
+  /// // -0.0, and NaN comparison operators have rules imposed by the IEEE
+  /// // standard.
+  /// print(-0.0 == 0.0); // => true
+  /// print(double.nan == double.nan);  // => false
+  /// print(double.infinity < double.nan);  // => false
+  /// print(double.nan < double.infinity);  // => false
+  /// print(double.nan == double.infinity);  // => false
+  /// ```
   int compareTo(num other);
 
-  /** Addition operator. */
+  /// Adds [other] to this number.
+  ///
+  /// The result is an [int], as described by [int.+],
+  /// if both this number and [other] is an integer,
+  /// otherwise the result is a [double].
   num operator +(num other);
 
-  /** Subtraction operator. */
+  /// Subtracts [other] from this number.
+  ///
+  /// The result is an [int], as described by [int.-],
+  /// if both this number and [other] is an integer,
+  /// otherwise the result is a [double].
   num operator -(num other);
 
-  /** Multiplication operator. */
+  /// Multiplies this number by [other].
+  ///
+  /// The result is an [int], as described by [int.*],
+  /// if both this number and [other] is an integer,
+  /// otherwise the result is a [double].
   num operator *(num other);
 
-  /**
-   * Euclidean modulo operator.
-   *
-   * Returns the remainder of the Euclidean division. The Euclidean division of
-   * two integers `a` and `b` yields two integers `q` and `r` such that
-   * `a == b * q + r` and `0 <= r < b.abs()`.
-   *
-   * The Euclidean division is only defined for integers, but can be easily
-   * extended to work with doubles. In that case `r` may have a non-integer
-   * value, but it still verifies `0 <= r < |b|`.
-   *
-   * The sign of the returned value `r` is always positive.
-   *
-   * See [remainder] for the remainder of the truncating division.
-   */
+  /// Euclidean modulo of this number by [other].
+  ///
+  /// Returns the remainder of the Euclidean division.
+  /// The Euclidean division of two integers `a` and `b`
+  /// yields two integers `q` and `r` such that
+  /// `a == b * q + r` and `0 <= r < b.abs()`.
+  ///
+  /// The Euclidean division is only defined for integers, but can be easily
+  /// extended to work with doubles. In that case `q` is stil an integer,
+  /// but `r` may have a non-integer value that still satisfies `0 <= r < |b|`.
+  ///
+  /// The sign of the returned value `r` is always positive.
+  ///
+  /// See [remainder] for the remainder of the truncating division.
+  ///
+  /// The result is an [int], as described by [int.%],
+  /// if both this number and [other] is an integer,
+  /// otherwise the result is a [double].
   num operator %(num other);
 
-  /** Division operator. */
+  /// Divides this number by [other].
   double operator /(num other);
 
-  /**
-   * Truncating division operator.
-   *
-   * If either operand is a [double] then the result of the truncating division
-   * `a ~/ b` is equivalent to `(a / b).truncate().toInt()`.
-   *
-   * If both operands are [int]s then `a ~/ b` performs the truncating
-   * integer division.
-   */
+  /// Truncating division operator.
+  ///
+  /// If either operand is a [double] then the result of the truncating division
+  /// `a ~/ b` is equivalent to `(a / b).truncate().toInt()`.
+  ///
+  /// If both operands are [int]s then `a ~/ b` performs the truncating
+  /// integer division.
   int operator ~/(num other);
 
-  /** Negate operator. */
+  /// The negation of this value.
+  ///
+  /// The negation of a number is a number of the same kind
+  /// (`int` or `double`) representing the negation of the
+  /// numbers numerical value (the result of subtracting the
+  /// number from zero), if that value *exists*.
+  ///
+  /// Negating a double gives a number with same magnitude
+  /// as the original value (`number.abs() == (-number).abs()`),
+  /// and the opposite sign (`-(number.sign) == (-number).sign`).
+  ///
+  /// Negating an integer, `-number`, is equivalent to subtracting
+  /// it from zero, `0 - number`.
+  ///
+  /// (Both properties generally also hold for the other type,
+  /// but with a few edge case exceptions).
   num operator -();
 
-  /**
-   * Returns the remainder of the truncating division of `this` by [other].
-   *
-   * The result `r` of this operation satisfies:
-   * `this == (this ~/ other) * other + r`.
-   * As a consequence the remainder `r` has the same sign as the divider `this`.
-   */
+  /// The remainder of the truncating division of `this` by [other].
+  ///
+  /// The result `r` of this operation satisfies:
+  /// `this == (this ~/ other) * other + r`.
+  /// As a consequence the remainder `r` has the same sign as the divider `this`.
+  ///
+  /// The result is an [int], as described by [int.remainder],
+  /// if both this number and [other] is an integer,
+  /// otherwise the result is a [double].
   num remainder(num other);
 
-  /** Relational less than operator. */
+  /// Whether [other] is numerically smaller than this number.
+  ///
+  /// If either operand is the [double] NaN, the result is always false.
   bool operator <(num other);
 
-  /** Relational less than or equal operator. */
+  /// Whether [other] is numerically smaller than or equal to this number.
+  ///
+  /// If either operand is the [double] NaN, the result is always false.
   bool operator <=(num other);
 
-  /** Relational greater than operator. */
+  /// Whether [other] is numerically greater than this number.
+  ///
+  /// If either operand is the [double] NaN, the result is always false.
   bool operator >(num other);
 
-  /** Relational greater than or equal operator. */
+  /// Whether [other] is numerically greater than or equal to this number.
+  ///
+  /// If either operand is the [double] NaN, the result is always false.
   bool operator >=(num other);
 
-  /** True if the number is the double Not-a-Number value; otherwise, false. */
+  /// Whether the number is the double Not-a-Number value.
   bool get isNaN;
 
-  /**
-   * True if the number is negative; otherwise, false.
-   *
-   * Negative numbers are those less than zero, and the double `-0.0`.
-   */
+  /// Whether if the number is negative.
+  ///
+  /// Negative numbers are those less than zero, and the double `-0.0`.
   bool get isNegative;
 
-  /**
-   * True if the number is positive infinity or negative infinity; otherwise,
-   * false.
-   */
+  /// Whether the number is positive infinity or negative infinity.
   bool get isInfinite;
 
-  /**
-   * True if the number is finite; otherwise, false.
-   *
-   * The only non-finite numbers are NaN, positive infinity, and
-   * negative infinity.
-   */
+  /// Whether the number is finite.
+  ///
+  /// The only non-finite numbers are NaN, positive infinity, and
+  /// negative infinity. All integers are finite.
   bool get isFinite;
 
-  /** Returns the absolute value of this [num]. */
+  /// The absolute value of this number.
+  ///
+  /// The absolute value is the value itself, if the value is non-negative,
+  /// and `-value` if the value is negative.
   num abs();
 
-  /**
-   * Returns minus one, zero or plus one depending on the sign and
-   * numerical value of the number.
-   *
-   * Returns minus one if the number is less than zero,
-   * plus one if the number is greater than zero,
-   * and zero if the number is equal to zero.
-   *
-   * Returns NaN if the number is the double NaN value.
-   *
-   * Returns a number of the same type as this number.
-   * For doubles, `-0.0.sign == -0.0`.
-
-   * The result satisfies:
-   *
-   *     n == n.sign * n.abs()
-   *
-   * for all numbers `n` (except NaN, because NaN isn't `==` to itself).
-   */
+  /// Negative one, zero or positive one depending on the sign and
+  /// numerical value of the number.
+  ///
+  /// Returns minus one if the number is less than zero,
+  /// plus one if the number is greater than zero,
+  /// and zero if the number is equal to zero.
+  ///
+  /// Returns NaN if the number is the [double] NaN value.
+  ///
+  /// Returns a number of the same type as this number.
+  /// For doubles, `-0.0.sign == -0.0`.
+  ///
+  /// The result satisfies:
+  /// ```dart
+  /// n == n.sign * n.abs()
+  /// ```
+  /// for all numbers `n` (except NaN, because NaN isn't `==` to itself).
   num get sign;
 
-  /**
-   * Returns the integer closest to `this`.
-   *
-   * Rounds away from zero when there is no closest integer:
-   *  `(3.5).round() == 4` and `(-3.5).round() == -4`.
-   *
-   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
-   */
+  /// The integer closest to this number.
+  ///
+  /// Rounds away from zero when there is no closest integer:
+  ///  `(3.5).round() == 4` and `(-3.5).round() == -4`.
+  ///
+  /// The number must be finite (see [isFinite]).
+  ///
+  /// If the value is greater than the highest representable positive integer,
+  /// the result is that highest positive integer.
+  /// If the value is smaller than the highest representable negative integer,
+  /// the result is that highest negative integer.
   int round();
 
-  /**
-   * Returns the greatest integer no greater than `this`.
-   *
-   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
-   */
+  /// The greatest integer no greater than this number.
+  ///
+  /// Rounds fractional values towards negative infinity.
+  ///
+  /// The number must be finite (see [isFinite]).
+  ///
+  /// If the value is greater than the highest representable positive integer,
+  /// the result is that highest positive integer.
+  /// If the value is smaller than the highest representable negative integer,
+  /// the result is that highest negative integer.
   int floor();
 
-  /**
-   * Returns the least integer no smaller than `this`.
-   *
-   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
-   */
+  /// The least integer no smaller than `this`.
+  ///
+  /// Rounds fractional values towards positive infinitiy.
+  ///
+  /// The number must be finite (see [isFinite]).
+  ///
+  /// If the value is greater than the highest representable positive integer,
+  /// the result is that highest positive integer.
+  /// If the value is smaller than the highest representable negative integer,
+  /// the result is that highest negative integer.
   int ceil();
 
-  /**
-   * Returns the integer obtained by discarding any fractional
-   * digits from `this`.
-   *
-   * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError].
-   */
+  /// The integer obtained by discarding any fractional digits from `this`.
+  ///
+  /// Rounds fractional values towards zero.
+  ///
+  /// The number must be finite (see [isFinite]).
+  ///
+  /// If the value is greater than the highest representable positive integer,
+  /// the result is that highest positive integer.
+  /// If the value is smaller than the highest representable negative integer,
+  /// the result is that highest negative integer.
   int truncate();
 
-  /**
-   * Returns the double integer value closest to `this`.
-   *
-   * Rounds away from zero when there is no closest integer:
-   *  `(3.5).roundToDouble() == 4` and `(-3.5).roundToDouble() == -4`.
-   *
-   * If this is already an integer valued double, including `-0.0`, or it is a
-   * non-finite double value, the value is returned unmodified.
-   *
-   * For the purpose of rounding, `-0.0` is considered to be below `0.0`,
-   * and `-0.0` is therefore considered closer to negative numbers than `0.0`.
-   * This means that for a value, `d` in the range `-0.5 < d < 0.0`,
-   * the result is `-0.0`.
-   *
-   * The result is always a double.
-   * If this is a numerically large integer, the result may be an infinite
-   * double.
-   */
+  /// The double integer value closest to this value.
+  ///
+  /// Rounds away from zero when there is no closest integer:
+  ///  `(3.5).roundToDouble() == 4` and `(-3.5).roundToDouble() == -4`.
+  ///
+  /// If this is already an integer valued double, including `-0.0`, or it is a
+  /// non-finite double value, the value is returned unmodified.
+  ///
+  /// For the purpose of rounding, `-0.0` is considered to be below `0.0`,
+  /// and `-0.0` is therefore considered closer to negative numbers than `0.0`.
+  /// This means that for a value, `d` in the range `-0.5 < d < 0.0`,
+  /// the result is `-0.0`.
   double roundToDouble();
 
-  /**
-   * Returns the greatest double integer value no greater than `this`.
-   *
-   * If this is already an integer valued double, including `-0.0`, or it is a
-   * non-finite double value, the value is returned unmodified.
-   *
-   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
-   * A number `d` in the range `0.0 < d < 1.0` will return `0.0`.
-   *
-   * The result is always a double.
-   * If this is a numerically large integer, the result may be an infinite
-   * double.
-   */
+  /// Returns the greatest double integer value no greater than `this`.
+  ///
+  /// If this is already an integer valued double, including `-0.0`, or it is a
+  /// non-finite double value, the value is returned unmodified.
+  ///
+  /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
+  /// A number `d` in the range `0.0 < d < 1.0` will return `0.0`.
   double floorToDouble();
 
-  /**
-   * Returns the least double integer value no smaller than `this`.
-   *
-   * If this is already an integer valued double, including `-0.0`, or it is a
-   * non-finite double value, the value is returned unmodified.
-   *
-   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
-   * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`.
-   *
-   * The result is always a double.
-   * If this is a numerically large integer, the result may be an infinite
-   * double.
-   */
+  /// Returns the least double integer value no smaller than `this`.
+  ///
+  /// If this is already an integer valued double, including `-0.0`, or it is a
+  /// non-finite double value, the value is returned unmodified.
+  ///
+  /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
+  /// A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`.
   double ceilToDouble();
 
-  /**
-   * Returns the double integer value obtained by discarding any fractional
-   * digits from the double value of `this`.
-   *
-   * If this is already an integer valued double, including `-0.0`, or it is a
-   * non-finite double value, the value is returned unmodified.
-   *
-   * For the purpose of rounding, `-0.0` is considered to be below `0.0`.
-   * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and
-   * in the range `0.0 < d < 1.0` it will return 0.0.
-   *
-   * The result is always a double.
-   * If this is a numerically large integer, the result may be an infinite
-   * double.
-   */
+  /// Returns the double integer value obtained by discarding any fractional
+  /// digits from the double value of `this`.
+  ///
+  /// If this is already an integer valued double, including `-0.0`, or it is a
+  /// non-finite double value, the value is returned unmodified.
+  ///
+  /// For the purpose of rounding, `-0.0` is considered to be below `0.0`.
+  /// A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and
+  /// in the range `0.0 < d < 1.0` it will return 0.0.
   double truncateToDouble();
 
-  /**
-   * Returns this [num] clamped to be in the range [lowerLimit]-[upperLimit].
-   *
-   * The comparison is done using [compareTo] and therefore takes `-0.0` into
-   * account. This also implies that [double.nan] is treated as the maximal
-   * double value.
-   *
-   * The arguments [lowerLimit] and [upperLimit] must form a valid range where
-   * `lowerLimit.compareTo(upperLimit) <= 0`.
-   */
+  /// Returns this [num] clamped to be in the range [lowerLimit]-[upperLimit].
+  ///
+  /// The comparison is done using [compareTo] and therefore takes `-0.0` into
+  /// account. This also implies that [double.nan] is treated as the maximal
+  /// double value.
+  ///
+  /// The arguments [lowerLimit] and [upperLimit] must form a valid range where
+  /// `lowerLimit.compareTo(upperLimit) <= 0`.
   num clamp(num lowerLimit, num upperLimit);
 
-  /** Truncates this [num] to an integer and returns the result as an [int]. */
+  /// Truncates this [num] to an integer and returns the result as an [int].
+  ///
+  /// Equivalent to [truncate].
   int toInt();
 
-  /**
-   * Return this [num] as a [double].
-   *
-   * If the number is not representable as a [double], an
-   * approximation is returned. For numerically large integers, the
-   * approximation may be infinite.
-   */
+  /// This number as a [double].
+  ///
+  /// If an integer number is not precisely representable as a [double],
+  /// an approximation is returned.
   double toDouble();
 
-  /**
-   * Returns a decimal-point string-representation of `this`.
-   *
-   * Converts `this` to a [double] before computing the string representation.
-   *
-   * If the absolute value of `this` is greater or equal to `10^21` then this
-   * methods returns an exponential representation computed by
-   * `this.toStringAsExponential()`. Otherwise the result
-   * is the closest string representation with exactly [fractionDigits] digits
-   * after the decimal point. If [fractionDigits] equals 0 then the decimal
-   * point is omitted.
-   *
-   * The parameter [fractionDigits] must be an integer satisfying:
-   * `0 <= fractionDigits <= 20`.
-   *
-   * Examples:
-   *
-   *     1.toStringAsFixed(3);  // 1.000
-   *     (4321.12345678).toStringAsFixed(3);  // 4321.123
-   *     (4321.12345678).toStringAsFixed(5);  // 4321.12346
-   *     123456789012345.toStringAsFixed(3);  // 123456789012345.000
-   *     10000000000000000.toStringAsFixed(4); // 10000000000000000.0000
-   *     5.25.toStringAsFixed(0); // 5
-   */
+  /// A decimal-point string-representation of this number.
+  ///
+  /// Converts this number to a [double]
+  /// before computing the string representation,
+  /// as by [toDouble].
+  ///
+  /// If the absolute value of `this` is greater then or equal to `10^21` then
+  /// this methods returns an exponential representation computed by
+  /// `this.toStringAsExponential()`. Otherwise the result
+  /// is the closest string representation with exactly [fractionDigits] digits
+  /// after the decimal point. If [fractionDigits] equals 0 then the decimal
+  /// point is omitted.
+  ///
+  /// The parameter [fractionDigits] must be an integer satisfying:
+  /// `0 <= fractionDigits <= 20`.
+  ///
+  /// Examples:
+  /// ```dart
+  /// 1.toStringAsFixed(3);  // 1.000
+  /// (4321.12345678).toStringAsFixed(3);  // 4321.123
+  /// (4321.12345678).toStringAsFixed(5);  // 4321.12346
+  /// 123456789012345.toStringAsFixed(3);  // 123456789012345.000
+  /// 10000000000000000.toStringAsFixed(4); // 10000000000000000.0000
+  /// 5.25.toStringAsFixed(0); // 5
+  /// ```
   String toStringAsFixed(int fractionDigits);
 
-  /**
-   * Returns an exponential string-representation of `this`.
-   *
-   * Converts `this` to a [double] before computing the string representation.
-   *
-   * If [fractionDigits] is given then it must be an integer satisfying:
-   * `0 <= fractionDigits <= 20`. In this case the string contains exactly
-   * [fractionDigits] after the decimal point. Otherwise, without the parameter,
-   * the returned string uses the shortest number of digits that accurately
-   * represent [this].
-   *
-   * If [fractionDigits] equals 0 then the decimal point is omitted.
-   * Examples:
-   *
-   *     1.toStringAsExponential();       // 1e+0
-   *     1.toStringAsExponential(3);      // 1.000e+0
-   *     123456.toStringAsExponential();  // 1.23456e+5
-   *     123456.toStringAsExponential(3); // 1.235e+5
-   *     123.toStringAsExponential(0);    // 1e+2
-   */
+  /// An exponential string-representation of this number.
+  ///
+  /// Converts this number to a [double]
+  /// before computing the string representation.
+  ///
+  /// If [fractionDigits] is given then it must be an integer satisfying:
+  /// `0 <= fractionDigits <= 20`. In this case the string contains exactly
+  /// [fractionDigits] after the decimal point. Otherwise, without the parameter,
+  /// the returned string uses the shortest number of digits that accurately
+  /// represent this number.
+  ///
+  /// If [fractionDigits] equals 0 then the decimal point is omitted.
+  /// Examples:
+  /// ```dart
+  /// 1.toStringAsExponential();       // 1e+0
+  /// 1.toStringAsExponential(3);      // 1.000e+0
+  /// 123456.toStringAsExponential();  // 1.23456e+5
+  /// 123456.toStringAsExponential(3); // 1.235e+5
+  /// 123.toStringAsExponential(0);    // 1e+2
+  /// ```
   String toStringAsExponential([int? fractionDigits]);
 
-  /**
-   * Converts `this` to a double and returns a string representation with
-   * exactly [precision] significant digits.
-   *
-   * The parameter [precision] must be an integer satisfying:
-   * `1 <= precision <= 21`.
-   *
-   * Examples:
-   *
-   *     1.toStringAsPrecision(2);       // 1.0
-   *     1e15.toStringAsPrecision(3);    // 1.00e+15
-   *     1234567.toStringAsPrecision(3); // 1.23e+6
-   *     1234567.toStringAsPrecision(9); // 1234567.00
-   *     12345678901234567890.toStringAsPrecision(20); // 12345678901234567168
-   *     12345678901234567890.toStringAsPrecision(14); // 1.2345678901235e+19
-   *     0.00000012345.toStringAsPrecision(15); // 1.23450000000000e-7
-   *     0.0000012345.toStringAsPrecision(15);  // 0.00000123450000000000
-   */
+  /// A string representation with [precision] significant digits.
+  ///
+  /// Converts this number to a [double]
+  /// and returns a string representation of that value
+  /// with exactly [precision] significant digits.
+  ///
+  /// The parameter [precision] must be an integer satisfying:
+  /// `1 <= precision <= 21`.
+  ///
+  /// Examples:
+  /// ```dart
+  /// 1.toStringAsPrecision(2);       // 1.0
+  /// 1e15.toStringAsPrecision(3);    // 1.00e+15
+  /// 1234567.toStringAsPrecision(3); // 1.23e+6
+  /// 1234567.toStringAsPrecision(9); // 1234567.00
+  /// 12345678901234567890.toStringAsPrecision(20); // 12345678901234567168
+  /// 12345678901234567890.toStringAsPrecision(14); // 1.2345678901235e+19
+  /// 0.00000012345.toStringAsPrecision(15); // 1.23450000000000e-7
+  /// 0.0000012345.toStringAsPrecision(15);  // 0.00000123450000000000
+  /// ```
   String toStringAsPrecision(int precision);
 
-  /**
-   * Returns the shortest string that correctly represent the input number.
-   *
-   * All [double]s in the range `10^-6` (inclusive) to `10^21` (exclusive)
-   * are converted to their decimal representation with at least one digit
-   * after the decimal point. For all other doubles,
-   * except for special values like `NaN` or `Infinity`, this method returns an
-   * exponential representation (see [toStringAsExponential]).
-   *
-   * Returns `"NaN"` for [double.nan], `"Infinity"` for [double.infinity], and
-   * `"-Infinity"` for [double.negativeInfinity].
-   *
-   * An [int] is converted to a decimal representation with no decimal point.
-   *
-   * Examples:
-   *
-   *     (0.000001).toString();  // "0.000001"
-   *     (0.0000001).toString(); // "1e-7"
-   *     (111111111111111111111.0).toString();  // "111111111111111110000.0"
-   *     (100000000000000000000.0).toString();  // "100000000000000000000.0"
-   *     (1000000000000000000000.0).toString(); // "1e+21"
-   *     (1111111111111111111111.0).toString(); // "1.1111111111111111e+21"
-   *     1.toString(); // "1"
-   *     111111111111111111111.toString();  // "111111111111111110000"
-   *     100000000000000000000.toString();  // "100000000000000000000"
-   *     1000000000000000000000.toString(); // "1000000000000000000000"
-   *     1111111111111111111111.toString(); // "1111111111111111111111"
-   *     1.234e5.toString();   // 123400
-   *     1234.5e6.toString();  // 1234500000
-   *     12.345e67.toString(); // 1.2345e+68
-   *
-   * Note: the conversion may round the output if the returned string
-   * is accurate enough to uniquely identify the input-number.
-   * For example the most precise representation of the [double] `9e59` equals
-   * `"899999999999999918767229449717619953810131273674690656206848"`, but
-   * this method returns the shorter (but still uniquely identifying) `"9e59"`.
-   *
-   */
+  /// The shortest string that correctly represent this number number.
+  ///
+  /// All [double]s in the range `10^-6` (inclusive) to `10^21` (exclusive)
+  /// are converted to their decimal representation with at least one digit
+  /// after the decimal point. For all other doubles,
+  /// except for special values like `NaN` or `Infinity`, this method returns an
+  /// exponential representation (see [toStringAsExponential]).
+  ///
+  /// Returns `"NaN"` for [double.nan], `"Infinity"` for [double.infinity], and
+  /// `"-Infinity"` for [double.negativeInfinity].
+  ///
+  /// An [int] is converted to a decimal representation with no decimal point.
+  ///
+  /// Examples:
+  /// ```dart
+  /// (0.000001).toString();  // "0.000001"
+  /// (0.0000001).toString(); // "1e-7"
+  /// (111111111111111111111.0).toString();  // "111111111111111110000.0"
+  /// (100000000000000000000.0).toString();  // "100000000000000000000.0"
+  /// (1000000000000000000000.0).toString(); // "1e+21"
+  /// (1111111111111111111111.0).toString(); // "1.1111111111111111e+21"
+  /// 1.toString(); // "1"
+  /// 111111111111111111111.toString();  // "111111111111111110000"
+  /// 100000000000000000000.toString();  // "100000000000000000000"
+  /// 1000000000000000000000.toString(); // "1000000000000000000000"
+  /// 1111111111111111111111.toString(); // "1111111111111111111111"
+  /// 1.234e5.toString();   // 123400
+  /// 1234.5e6.toString();  // 1234500000
+  /// 12.345e67.toString(); // 1.2345e+68
+  /// ```
+  /// Note: the conversion may round the output if the returned string
+  /// is accurate enough to uniquely identify the input-number.
+  /// For example the most precise representation of the [double] `9e59` equals
+  /// `"899999999999999918767229449717619953810131273674690656206848"`, but
+  /// this method returns the shorter (but still uniquely identifying) `"9e59"`.
   String toString();
 
-  /**
-   * Parses a string containing a number literal into a number.
-   *
-   * The method first tries to read the [input] as integer (similar to
-   * [int.parse] without a radix).
-   * If that fails, it tries to parse the [input] as a double (similar to
-   * [double.parse]).
-   * If that fails, too, it invokes [onError] with [input], and the result
-   * of that invocation becomes the result of calling `parse`.
-   *
-   * If no [onError] is supplied, it defaults to a function that throws a
-   * [FormatException].
-   *
-   * For any number `n`, this function satisfies
-   * `identical(n, num.parse(n.toString()))` (except when `n` is a NaN `double`
-   * with a payload).
-   *
-   * The [onError] parameter is deprecated and will be removed.
-   * Instead of `num.parse(string, (string) { ... })`,
-   * you should use `num.tryParse(string) ?? (...)`.
-   */
+  /// Parses a string containing a number literal into a number.
+  ///
+  /// The method first tries to read the [input] as integer (similar to
+  /// [int.parse] without a radix).
+  /// If that fails, it tries to parse the [input] as a double (similar to
+  /// [double.parse]).
+  /// If that fails, too, it invokes [onError] with [input], and the result
+  /// of that invocation becomes the result of calling `parse`.
+  ///
+  /// If no [onError] is supplied, it defaults to a function that throws a
+  /// [FormatException].
+  ///
+  /// For any number `n`, this function satisfies
+  /// `identical(n, num.parse(n.toString()))` (except when `n` is a NaN `double`
+  /// with a payload).
+  ///
+  /// The [onError] parameter is deprecated and will be removed.
+  /// Instead of `num.parse(string, (string) { ... })`,
+  /// you should use `num.tryParse(string) ?? (...)`.
   static num parse(String input, [@deprecated num onError(String input)?]) {
     num? result = tryParse(input);
     if (result != null) return result;
@@ -475,12 +487,10 @@
     return onError(input);
   }
 
-  /**
-   * Parses a string containing a number literal into a number.
-   *
-   * Like [parse] except that this function returns `null` for invalid inputs
-   * instead of throwing.
-   */
+  /// Parses a string containing a number literal into a number.
+  ///
+  /// Like [parse] except that this function returns `null` for invalid inputs
+  /// instead of throwing.
   static num? tryParse(String input) {
     String source = input.trim();
     // TODO(lrn): Optimize to detect format and result type in one check.
diff --git a/sdk/lib/core/object.dart b/sdk/lib/core/object.dart
index b55d80d..008f969 100644
--- a/sdk/lib/core/object.dart
+++ b/sdk/lib/core/object.dart
@@ -4,113 +4,146 @@
 
 part of dart.core;
 
-/**
- * The base class for all Dart objects.
- *
- * Because Object is the root of the Dart class hierarchy,
- * every other Dart class is a subclass of Object.
- *
- * When you define a class, you should override [toString]
- * to return a string describing an instance of that class.
- * You might also need to define [hashCode] and [operator ==], as described in the
- * [Implementing map
- * keys](https://dart.dev/guides/libraries/library-tour#implementing-map-keys)
- * section of the [library
- * tour](https://dart.dev/guides/libraries/library-tour).
- */
+/// The base class for all Dart objects exception `null`.
+///
+/// Because `Object` is a root of the non-nullable Dart class hierarchy,
+/// every other non-`Null` Dart class is a subclass of `Object`.
+///
+/// When you define a class, you should consider overriding [toString]
+/// to return a string describing an instance of that class.
+/// You might also need to define [hashCode] and [operator ==], as described in the
+/// [Implementing map keys](https://dart.dev/guides/libraries/library-tour#implementing-map-keys)
+/// section of the [library tour](https://dart.dev/guides/libraries/library-tour).
 @pragma("vm:entry-point")
 class Object {
-  /**
-   * Creates a new [Object] instance.
-   *
-   * [Object] instances have no meaningful state, and are only useful
-   * through their identity. An [Object] instance is equal to itself
-   * only.
-   */
+  /// Creates a new [Object] instance.
+  ///
+  /// [Object] instances have no meaningful state, and are only useful
+  /// through their identity. An [Object] instance is equal to itself
+  /// only.
   @pragma("vm:recognized", "other")
   const Object();
 
-  /**
-   * The equality operator.
-   *
-   * The default behavior for all [Object]s is to return true if and
-   * only if `this` and [other] are the same object.
-   *
-   * Override this method to specify a different equality relation on
-   * a class. The overriding method must still be an equivalence relation.
-   * That is, it must be:
-   *
-   *  * Total: It must return a boolean for all arguments. It should never throw
-   *    or return `null`.
-   *
-   *  * Reflexive: For all objects `o`, `o == o` must be true.
-   *
-   *  * Symmetric: For all objects `o1` and `o2`, `o1 == o2` and `o2 == o1` must
-   *    either both be true, or both be false.
-   *
-   *  * Transitive: For all objects `o1`, `o2`, and `o3`, if `o1 == o2` and
-   *    `o2 == o3` are true, then `o1 == o3` must be true.
-   *
-   * The method should also be consistent over time,
-   * so whether two objects are equal should only change
-   * if at least one of the objects was modified.
-   *
-   * If a subclass overrides the equality operator it should override
-   * the [hashCode] method as well to maintain consistency.
-   */
+  /// The equality operator.
+  ///
+  /// The default behavior for all [Object]s is to return true if and
+  /// only if this object and [other] are the same object.
+  ///
+  /// Override this method to specify a different equality relation on
+  /// a class. The overriding method must still be an equivalence relation.
+  /// That is, it must be:
+  ///
+  ///  * Total: It must return a boolean for all arguments. It should never throw.
+  ///
+  ///  * Reflexive: For all objects `o`, `o == o` must be true.
+  ///
+  ///  * Symmetric: For all objects `o1` and `o2`, `o1 == o2` and `o2 == o1` must
+  ///    either both be true, or both be false.
+  ///
+  ///  * Transitive: For all objects `o1`, `o2`, and `o3`, if `o1 == o2` and
+  ///    `o2 == o3` are true, then `o1 == o3` must be true.
+  ///
+  /// The method should also be consistent over time,
+  /// so whether two objects are equal should only change
+  /// if at least one of the objects was modified.
+  ///
+  /// If a subclass overrides the equality operator, it should override
+  /// the [hashCode] method as well to maintain consistency.
   external bool operator ==(Object other);
 
-  /**
-   * The hash code for this object.
-   *
-   * A hash code is a single integer which represents the state of the object
-   * that affects [operator ==] comparisons.
-   *
-   * All objects have hash codes.
-   * The default hash code represents only the identity of the object,
-   * the same way as the default [operator ==] implementation only considers objects
-   * equal if they are identical (see [identityHashCode]).
-   *
-   * If [operator ==] is overridden to use the object state instead,
-   * the hash code must also be changed to represent that state.
-   *
-   * Hash codes must be the same for objects that are equal to each other
-   * according to [operator ==].
-   * The hash code of an object should only change if the object changes
-   * in a way that affects equality.
-   * There are no further requirements for the hash codes.
-   * They need not be consistent between executions of the same program
-   * and there are no distribution guarantees.
-   *
-   * Objects that are not equal are allowed to have the same hash code,
-   * it is even technically allowed that all instances have the same hash code,
-   * but if clashes happen too often, it may reduce the efficiency of hash-based
-   * data structures like [HashSet] or [HashMap].
-   *
-   * If a subclass overrides [hashCode], it should override the
-   * [operator ==] operator as well to maintain consistency.
-   */
+  /// The hash code for this object.
+  ///
+  /// A hash code is a single integer which represents the state of the object
+  /// that affects [operator ==] comparisons.
+  ///
+  /// All objects have hash codes.
+  /// The default hash code implemented by [Object]
+  /// represents only the identity of the object,
+  /// the same way as the default [operator ==] implementation only considers objects
+  /// equal if they are identical (see [identityHashCode]).
+  ///
+  /// If [operator ==] is overridden to use the object state instead,
+  /// the hash code must also be changed to represent that state,
+  /// otherwise the object cannot be used in hash based data structures
+  /// like the default [Set] and [Map] implementations.
+  ///
+  /// Hash codes must be the same for objects that are equal to each other
+  /// according to [operator ==].
+  /// The hash code of an object should only change if the object changes
+  /// in a way that affects equality.
+  /// There are no further requirements for the hash codes.
+  /// They need not be consistent between executions of the same program
+  /// and there are no distribution guarantees.
+  ///
+  /// Objects that are not equal are allowed to have the same hash code.
+  /// It is even technically allowed that all instances have the same hash code,
+  /// but if clashes happen too often,
+  /// it may reduce the efficiency of hash-based data structures
+  /// like [HashSet] or [HashMap].
+  ///
+  /// If a subclass overrides [hashCode], it should override the
+  /// [operator ==] operator as well to maintain consistency.
   external int get hashCode;
 
-  /**
-   * Returns a string representation of this object.
-   */
+  /// A string representation of this object.
+  ///
+  /// Some classes have a default textual representation,
+  /// often paired with a static `parse` function (like [int.parse]).
+  /// These classes will provide the textual representation as
+  /// their string represetion.
+  ///
+  /// Other classes have no meaningful textual representation
+  /// that a program will care about.
+  /// Such classes will typically override `toString` to provide
+  /// useful information when inspecting the object,
+  /// mainly for debugging or logging.
   external String toString();
 
-  /**
-   * Invoked when a non-existent method or property is accessed.
-   *
-   * Classes can override [noSuchMethod] to provide custom behavior.
-   *
-   * If a value is returned, it becomes the result of the original invocation.
-   *
-   * The default behavior is to throw a [NoSuchMethodError].
-   */
+  /// Invoked when a non-existent method or property is accessed.
+  ///
+  /// A dynamic member invocation can attempt to call a member which
+  /// doesn't exist on the receiving object. Example:
+  /// ```dart
+  /// dynamic object = 1;
+  /// object.add(42); // Statically allowed, run-time error
+  /// ```
+  /// This invalid code will invoke the `noSuchMethod` memthod
+  /// of the integer `1` with an [Invocation] representing the
+  /// `.add(42)` call and arguments (which then throws).
+  ///
+  /// Classes can override [noSuchMethod] to provide custom behavior
+  /// for such invalid dynamic invocations.
+  ///
+  /// A class with a non-default [noSuchMethod] invocation can also
+  /// omit implementations for members of its interface.
+  /// Example:
+  /// ```dart
+  /// class MockList<T> implements List<T> {
+  ///   noSuchMethod(Invocation invocation) {
+  ///     log(invocation);
+  ///     super.noSuchMethod(invocation); // Will throw.
+  ///   }
+  /// }
+  /// void main() {
+  ///   MockList().add(42);
+  /// }
+  /// ```
+  /// This code has no compile-time warnings or errors even though
+  /// the `MockList` class has no concrete implementation of
+  /// any of the `List` interface methods.
+  /// Calls to `List` methods are forwarded to `noSuchMethod`,
+  /// so this code will `log` an invocation similar to
+  /// `Invocation.method(#add, [42])` and then throw.
+  ///
+  /// If a value is returned from `noSuchMethod`,
+  /// it becomes the result of the original invocation.
+  /// If the value is not of a type that can be returned by the original
+  /// invocation, a type error occurs at the invocation.
+  ///
+  /// The default behavior is to throw a [NoSuchMethodError].
   @pragma("vm:entry-point")
   external dynamic noSuchMethod(Invocation invocation);
 
-  /**
-   * A representation of the runtime type of the object.
-   */
+  /// A representation of the runtime type of the object.
   external Type get runtimeType;
 }
diff --git a/sdk/lib/core/pattern.dart b/sdk/lib/core/pattern.dart
index 7a3d933..94c8980 100644
--- a/sdk/lib/core/pattern.dart
+++ b/sdk/lib/core/pattern.dart
@@ -4,124 +4,99 @@
 
 part of dart.core;
 
-/**
- * An interface for basic searches within strings.
- */
+/// An interface for basic searches within strings.
 abstract class Pattern {
-  /**
-   * Match this pattern against the string repeatedly.
-   *
-   * If [start] is provided, matching will start at that index.
-   *
-   * The returned iterable lazily computes all the non-overlapping matches
-   * of the pattern on the string, ordered by start index.
-   * If a user only requests the first
-   * match, this function should not compute all possible matches.
-   *
-   * The matches are found by repeatedly finding the first match
-   * of the pattern on the string, starting from the end of the previous
-   * match, and initially starting from index zero.
-   *
-   * If the pattern matches the empty string at some point, the next
-   * match is found by starting at the previous match's end plus one.
-   */
+  /// Matches this pattern against the string repeatedly.
+  ///
+  /// If [start] is provided, matching will start at that index.
+  ///
+  /// The returned iterable lazily finds non-overlapping matches
+  /// of the pattern in the [string].
+  /// If a user only requests the first match,
+  /// this function should not compute all possible matches.
+  ///
+  /// The matches are found by repeatedly finding the first match
+  /// of the pattern in the string, initially starting from [start],
+  /// and then from the end of the previous match (but always
+  /// at least one position later than the *start* of the previous
+  /// match, in case the patter matches an empty substring).
   Iterable<Match> allMatches(String string, [int start = 0]);
 
-  /**
-   * Match this pattern against the start of `string`.
-   *
-   * If [start] is provided, it must be an integer in the range `0` ..
-   * `string.length`. In that case, this patten is tested against the
-   * string at the [start] position. That is, a [Match] is returned if the
-   * pattern can match a part of the string starting from position [start].
-   * Returns `null` if the pattern doesn't match.
-   */
+  /// Matches this pattern against the start of `string`.
+  ///
+  /// Returns a match if the pattern matches a substring of [string]
+  /// starting at [start], and `null` if the pattern doesn't match
+  /// a that point.
+  ///
+  /// The [start] must be non-negative and no greater than `string.length`.
   Match? matchAsPrefix(String string, [int start = 0]);
 }
 
-/**
- * A result from searching within a string.
- *
- * A Match or an [Iterable] of Match objects is returned from [Pattern]
- * matching methods.
- *
- * The following example finds all matches of a [RegExp] in a [String]
- * and iterates through the returned iterable of Match objects.
- *
- *     RegExp exp = new RegExp(r"(\w+)");
- *     String str = "Parse my string";
- *     Iterable<Match> matches = exp.allMatches(str);
- *     for (Match m in matches) {
- *       String match = m.group(0);
- *       print(match);
- *     }
- *
- * The output of the example is:
- *
- *     Parse
- *     my
- *     string
- *
- * Some patterns, regular expressions in particular, may record substrings
- * that were part of the matching. These are called _groups_ in the Match
- * object. Some patterns may never have any groups, and their matches always
- * have zero [groupCount].
- */
+/// A result from searching within a string.
+///
+/// A `Match` or an [Iterable] of `Match` objects is returned from
+/// the [Pattern] matching methods
+/// ([Pattern.allMatches] and [Pattern.matchAsPrefix]).
+///
+/// The following example finds all matches of a [RegExp] in a [String]
+/// and iterates through the returned iterable of `Match` objects.
+/// ```dart
+/// RegExp exp = RegExp(r"(\w+)");
+/// String str = "Parse my string";
+/// Iterable<Match> matches = exp.allMatches(str);
+/// for (Match m in matches) {
+///   String match = m[0]!;
+///   print(match);
+/// }
+/// ```
+/// The output of the example is:
+/// ```dart
+/// Parse
+/// my
+/// string
+/// ```
+/// Some patterns, regular expressions in particular, may record substrings
+/// that were part of the matching. These are called _groups_ in the `Match`
+/// object. Some patterns may never have any groups, and their matches always
+/// have zero [groupCount].
 abstract class Match {
-  /**
-   * Returns the index in the string where the match starts.
-   */
+  /// The index in the string where the match starts.
   int get start;
 
-  /**
-   * Returns the index in the string after the last character of the
-   * match.
-   */
+  /// The index in the string after the last character of the match.
   int get end;
 
-  /**
-   * Returns the string matched by the given [group].
-   *
-   * If [group] is 0, returns the match of the pattern.
-   *
-   * The result may be `null` if the pattern didn't assign a value to it
-   * as part of this match.
-   */
+  /// The string matched by the given [group].
+  ///
+  /// If [group] is 0, returns the entire match of the pattern.
+  ///
+  /// The result may be `null` if the pattern didn't assign a value to it
+  /// as part of this match.
   String? group(int group);
 
-  /**
-   * Returns the string matched by the given [group].
-   *
-   * If [group] is 0, returns the match of the pattern.
-   *
-   * Short alias for [Match.group].
-   */
+  /// The string matched by the given [group].
+  ///
+  /// If [group] is 0, returns the match of the pattern.
+  ///
+  /// Short alias for [Match.group].
   String? operator [](int group);
 
-  /**
-   * Returns a list of the groups with the given indices.
-   *
-   * The list contains the strings returned by [group] for each index in
-   * [groupIndices].
-   */
+  /// A list of the groups with the given indices.
+  ///
+  /// The list contains the strings returned by [group] for each index in
+  /// [groupIndices].
   List<String?> groups(List<int> groupIndices);
 
-  /**
-   * Returns the number of captured groups in the match.
-   *
-   * Some patterns may capture parts of the input that was used to
-   * compute the full match. This is the number of captured groups,
-   * which is also the maximal allowed argument to the [group] method.
-   */
+  /// Returns the number of captured groups in the match.
+  ///
+  /// Some patterns may capture parts of the input that was used to
+  /// compute the full match. This is the number of captured groups,
+  /// which is also the maximal allowed argument to the [group] method.
   int get groupCount;
 
-  /**
-   * The string on which this match was computed.
-   */
+  /// The string on which this match was computed.
   String get input;
 
-  /**
-   * The pattern used to search in [input].
-   */
+  /// The pattern used to search in [input].
   Pattern get pattern;
 }
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index ca5309f..993da0a5 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.dart
@@ -4,186 +4,160 @@
 
 part of dart.core;
 
-/**
- * A regular expression pattern.
- *
- * Regular expressions are [Pattern]s, and can as such be used to match strings
- * or parts of strings.
- *
- * Dart regular expressions have the same syntax and semantics as
- * JavaScript regular expressions. See
- * <https://ecma-international.org/ecma-262/9.0/#sec-regexp-regular-expression-objects>
- * for the specification of JavaScript regular expressions.
- *
- * [firstMatch] is the main implementation method that applies a regular
- * expression to a string and returns the first [RegExpMatch]. All
- * other methods in [RegExp] can build on it.
- *
- * Use [allMatches] to look for all matches of a regular expression in
- * a string.
- *
- * The following example finds all matches of a regular expression in
- * a string.
- * ```dart
- * RegExp exp = new RegExp(r"(\w+)");
- * String str = "Parse my string";
- * Iterable<RegExpMatch> matches = exp.allMatches(str);
- * ```
- *
- * Note the use of a _raw string_ (a string prefixed with `r`)
- * in the example above. Use a raw string to treat each character in a string
- * as a literal character.
- */
+/// A regular expression pattern.
+///
+/// Regular expressions are [Pattern]s, and can as such be used to match strings
+/// or parts of strings.
+///
+/// Dart regular expressions have the same syntax and semantics as
+/// JavaScript regular expressions. See
+/// <https://ecma-international.org/ecma-262/9.0/#sec-regexp-regular-expression-objects>
+/// for the specification of JavaScript regular expressions.
+///
+/// The [firstMatch] method is the main implementation method
+/// that applies a regular expression to a string
+/// and returns the first [RegExpMatch].
+/// All other methods in [RegExp] can be build from that.
+///
+/// Use [allMatches] to look for all matches of a regular expression in
+/// a string.
+///
+/// The following example finds all matches of a regular expression in
+/// a string.
+/// ```dart
+/// RegExp exp = RegExp(r"(\w+)");
+/// String str = "Parse my string";
+/// Iterable<RegExpMatch> matches = exp.allMatches(str);
+/// ```
+///
+/// Note the use of a _raw string_ (a string prefixed with `r`)
+/// in the example above. Use a raw string to treat each character in a string
+/// as a literal character.
 abstract class RegExp implements Pattern {
-  /**
-   * Constructs a regular expression.
-   *
-   * Throws a [FormatException] if [source] is not valid regular
-   * expression syntax.
-   *
-   * If `multiLine` is enabled, then `^` and `$` will match the beginning and
-   * end of a _line_, in addition to matching beginning and end of input,
-   * respectively.
-   *
-   * If `caseSensitive` is disabled, then case is ignored.
-   *
-   * If `unicode` is enabled, then the pattern is treated as a Unicode
-   * pattern as described by the ECMAScript standard.
-   *
-   * If `dotAll` is enabled, then the `.` pattern will match _all_ characters,
-   * including line terminators.
-   *
-   * Example:
-   *
-   * ```dart
-   * var wordPattern = RegExp(r"(\w+)");
-   * var bracketedNumberValue = RegExp("$key: \\[\\d+\\]");
-   * ```
-   *
-   * Notice the use of a _raw string_ in the first example, and a regular
-   * string in the second. Because of the many character classes used in
-   * regular expressions, it is common to use a raw string here, unless string
-   * interpolation is required.
-   */
+  /// Constructs a regular expression.
+  ///
+  /// Throws a [FormatException] if [source] is not valid regular
+  /// expression syntax.
+  ///
+  /// If `multiLine` is enabled, then `^` and `$` will match the beginning and
+  /// end of a _line_, in addition to matching beginning and end of input,
+  /// respectively.
+  ///
+  /// If `caseSensitive` is disabled, then case is ignored.
+  ///
+  /// If `unicode` is enabled, then the pattern is treated as a Unicode
+  /// pattern as described by the ECMAScript standard.
+  ///
+  /// If `dotAll` is enabled, then the `.` pattern will match _all_ characters,
+  /// including line terminators.
+  ///
+  /// Example:
+  ///
+  /// ```dart
+  /// var wordPattern = RegExp(r"(\w+)");
+  /// var bracketedNumberValue = RegExp("$key: \\[\\d+\\]");
+  /// ```
+  ///
+  /// Notice the use of a _raw string_ in the first example, and a regular
+  /// string in the second. Because of the many escapes, like `\d`, used in
+  /// regular expressions, it is common to use a raw string here, unless string
+  /// interpolation is required.
   external factory RegExp(String source,
       {bool multiLine = false,
       bool caseSensitive = true,
       @Since("2.4") bool unicode = false,
       @Since("2.4") bool dotAll = false});
 
-  /**
-   * Returns a regular expression that matches [text].
-   *
-   * If [text] contains characters that are meaningful in regular expressions,
-   * the resulting regular expression will match those characters literally.
-   * If [text] contains no characters that have special meaning in a regular
-   * expression, it is returned unmodified.
-   *
-   * The characters that have special meaning in regular expressions are:
-   * `(`, `)`, `[`, `]`, `{`, `}`, `*`, `+`, `?`, `.`, `^`, `$`, `|` and `\`.
-   */
+  /// Creates regular expression syntax that matches [text].
+  ///
+  /// If [text] contains characters that are meaningful in regular expressions,
+  /// the resulting regular expression will match those characters literally.
+  /// If [text] contains no characters that have special meaning in a regular
+  /// expression, it is returned unmodified.
+  ///
+  /// The characters that have special meaning in regular expressions are:
+  /// `(`, `)`, `[`, `]`, `{`, `}`, `*`, `+`, `?`, `.`, `^`, `$`, `|` and `\`.
+  ///
+  /// This method is mainly used to create a pattern to be included in a
+  /// larger regular expression. Since a [String] is itself a [Pattern]
+  /// which matches itself, converting the string to a regular expression
+  /// isn't needed in order to search for just that string.
   external static String escape(String text);
 
-  /**
-   * Searches for the first match of the regular expression
-   * in the string [input]. Returns `null` if there is no match.
-   */
+  /// Finds the first match of the regular expression in the string [input].
+  ///
+  /// Returns `null` if there is no match.
   RegExpMatch? firstMatch(String input);
 
-  /**
-   * Returns an iterable of the matches of the regular expression on [input].
-   *
-   * If [start] is provided, only start looking for matches at `start`.
-   */
   Iterable<RegExpMatch> allMatches(String input, [int start = 0]);
 
-  /**
-   * Returns whether the regular expression has a match in the string [input].
-   */
+  /// Whether the regular expression has a match in the string [input].
   bool hasMatch(String input);
 
-  /**
-   * Returns the first substring match of this regular expression in [input].
-   */
+  /// The substring of the first match of this regular expression in [input].
   String? stringMatch(String input);
 
-  /**
-   * The source regular expression string used to create this `RegExp`.
-   */
+  /// The source regular expression string used to create this `RegExp`.
   String get pattern;
 
-  /**
-   * Whether this regular expression matches multiple lines.
-   *
-   * If the regexp does match multiple lines, the "^" and "$" characters
-   * match the beginning and end of lines. If not, the character match the
-   * beginning and end of the input.
-   */
+  /// Whether this regular expression matches multiple lines.
+  ///
+  /// If the regexp does match multiple lines, the "^" and "$" characters
+  /// match the beginning and end of lines. If not, the characters match the
+  /// beginning and end of the input.
   bool get isMultiLine;
 
-  /**
-   * Whether this regular expression is case sensitive.
-   *
-   * If the regular expression is not case sensitive, it will match an input
-   * letter with a pattern letter even if the two letters are different case
-   * versions of the same letter.
-   */
+  /// Whether this regular expression is case sensitive.
+  ///
+  /// If the regular expression is not case sensitive, it will match an input
+  /// letter with a pattern letter even if the two letters are different case
+  /// versions of the same letter.
   bool get isCaseSensitive;
 
-  /**
-   * Whether this regular expression is in Unicode mode.
-   *
-   * In Unicode mode, UTF-16 surrogate pairs in the original string will be
-   * treated as a single code point and will not match separately. Otherwise,
-   * the target string will be treated purely as a sequence of individual code
-   * units and surrogates will not be treated specially.
-   *
-   * In Unicode mode, the syntax of the RegExp pattern is more restricted, but
-   * some pattern features, like Unicode property escapes, are only available in
-   * this mode.
-   */
+  /// Whether this regular expression is in Unicode mode.
+  ///
+  /// In Unicode mode, UTF-16 surrogate pairs in the original string will be
+  /// treated as a single code point and will not match separately. Otherwise,
+  /// the target string will be treated purely as a sequence of individual code
+  /// units and surrogates will not be treated specially.
+  ///
+  /// In Unicode mode, the syntax of the RegExp pattern is more restricted, but
+  /// some pattern features, like Unicode property escapes, are only available in
+  /// this mode.
   @Since("2.4")
   bool get isUnicode;
 
-  /**
-   * Whether "." in this regular expression matches line terminators.
-   *
-   * When false, the "." character matches a single character, unless that
-   * character is a line terminator. When true, then the "." character will
-   * match any single character including line terminators.
-   *
-   * This feature is distinct from [isMultiLine], as they affect the behavior
-   * of different pattern characters, and so they can be used together or
-   * separately.
-   */
+  /// Whether "." in this regular expression matches line terminators.
+  ///
+  /// When false, the "." character matches a single character, unless that
+  /// character is a line terminator. When true, then the "." character will
+  /// match any single character including line terminators.
+  ///
+  /// This feature is distinct from [isMultiLine], as they affect the behavior
+  /// of different pattern characters, and so they can be used together or
+  /// separately.
   @Since("2.4")
   bool get isDotAll;
 }
 
-/**
- * A regular expression match.
- *
- * Regular expression matches are [Match]es, but also include the ability
- * to retrieve the names for any named capture groups and to retrieve
- * matches for named capture groups by name instead of their index.
- */
+/// A regular expression match.
+///
+/// Regular expression matches are [Match]es, but also include the ability
+/// to retrieve the names for any named capture groups and to retrieve
+/// matches for named capture groups by name instead of their index.
 @Since("2.3")
 abstract class RegExpMatch implements Match {
-  /**
-   * The string matched by the group named [name].
-   *
-   * Returns the string matched by the capture group named [name], or
-   * `null` if no string was matched by that capture group as part of
-   * this match.
-   *
-   * The [name] must be the name of a named capture group in the regular
-   * expression creating this match (that is, the name must be in
-   * [groupNames]).
-   */
+  /// The string matched by the group named [name].
+  ///
+  /// Returns the string matched by the capture group named [name], or
+  /// `null` if no string was matched by that capture group as part of
+  /// this match.
+  ///
+  /// The [name] must be the name of a named capture group in the regular
+  /// expression creating this match (that is, the name must be in
+  /// [groupNames]).
   String? namedGroup(String name);
 
-  /**
-   * The names of the captured groups in the match.
-   */
+  /// The names of the captured groups in the match.
   Iterable<String> get groupNames;
 }
diff --git a/sdk/lib/core/set.dart b/sdk/lib/core/set.dart
index edb05cf..eb86364 100644
--- a/sdk/lib/core/set.dart
+++ b/sdk/lib/core/set.dart
@@ -4,263 +4,227 @@
 
 part of dart.core;
 
-/**
- * A collection of objects in which each object can occur only once.
- *
- * That is, for each object of the element type, the object is either considered
- * to be in the set, or to _not_ be in the set.
- *
- * Set implementations may consider some elements indistinguishable. These
- * elements are treated as being the same for any operation on the set.
- *
- * The default [Set] implementation, [LinkedHashSet], considers objects
- * indistinguishable if they are equal with regard to
- * operator [Object.==].
- *
- * Iterating over elements of a set may be either unordered
- * or ordered in some way. Examples:
- *
- * * A [HashSet] is unordered, which means that its iteration order is
- *   unspecified,
- * * [LinkedHashSet] iterates in the insertion order of its elements, and
- * * a sorted set like [SplayTreeSet] iterates the elements in sorted order.
- *
- * It is generally not allowed to modify the set (add or remove elements) while
- * an operation on the set is being performed, for example during a call to
- * [forEach] or [containsAll]. Nor is it allowed to modify the set while
- * iterating either the set itself or any [Iterable] that is backed by the set,
- * such as the ones returned by methods like [where] and [map].
- *
- * It is generally not allowed to modify the equality of elements (and thus not
- * their hashcode) while they are in the set. Some specialized subtypes may be
- * more permissive, in which case they should document this behavior.
- */
+/// A collection of objects in which each object can occur only once.
+///
+/// That is, for each object of the element type, the object is either considered
+/// to be in the set, or to _not_ be in the set.
+///
+/// Set implementations may consider some elements indistinguishable. These
+/// elements are treated as being the same for any operation on the set.
+///
+/// The default [Set] implementation, [LinkedHashSet], considers objects
+/// indistinguishable if they are equal with regard to
+/// operator [Object.==].
+///
+/// Iterating over elements of a set may be either unordered
+/// or ordered in some way. Examples:
+///
+/// * A [HashSet] is unordered, which means that its iteration order is
+///   unspecified,
+/// * [LinkedHashSet] iterates in the insertion order of its elements, and
+/// * a sorted set like [SplayTreeSet] iterates the elements in sorted order.
+///
+/// It is generally not allowed to modify the set (add or remove elements) while
+/// an operation on the set is being performed, for example during a call to
+/// [forEach] or [containsAll]. Nor is it allowed to modify the set while
+/// iterating either the set itself or any [Iterable] that is backed by the set,
+/// such as the ones returned by methods like [where] and [map].
+///
+/// It is generally not allowed to modify the equality of elements (and thus not
+/// their hashcode) while they are in the set. Some specialized subtypes may be
+/// more permissive, in which case they should document this behavior.
 abstract class Set<E> extends EfficientLengthIterable<E> {
-  /**
-   * Creates an empty [Set].
-   *
-   * The created [Set] is a plain [LinkedHashSet].
-   * As such, it considers elements that are equal (using [operator ==]) to be
-   * indistinguishable, and requires them to have a compatible
-   * [Object.hashCode] implementation.
-   *
-   * The set is equivalent to one created by `new LinkedHashSet<E>()`.
-   */
+  /// Creates an empty [Set].
+  ///
+  /// The created [Set] is a plain [LinkedHashSet].
+  /// As such, it considers elements that are equal (using [operator ==]) to be
+  /// indistinguishable, and requires them to have a compatible
+  /// [Object.hashCode] implementation.
+  ///
+  /// The set is equivalent to one created by `LinkedHashSet<E>()`.
   factory Set() = LinkedHashSet<E>;
 
-  /**
-   * Creates an empty identity [Set].
-   *
-   * The created [Set] is a [LinkedHashSet] that uses identity as equality
-   * relation.
-   *
-   * The set is equivalent to one created by `new LinkedHashSet<E>.identity()`.
-   */
+  /// Creates an empty identity [Set].
+  ///
+  /// The created [Set] is a [LinkedHashSet] that uses identity as equality
+  /// relation.
+  ///
+  /// The set is equivalent to one created by `LinkedHashSet<E>.identity()`.
   factory Set.identity() = LinkedHashSet<E>.identity;
 
-  /**
-   * Creates a [Set] that contains all [elements].
-   *
-   * All the [elements] should be instances of [E].
-   * The `elements` iterable itself can have any type,
-   * so this constructor can be used to down-cast a `Set`, for example as:
-   *
-   *     Set<SuperType> superSet = ...;
-   *     Set<SubType> subSet =
-   *         new Set<SubType>.from(superSet.where((e) => e is SubType));
-   *
-   * The created [Set] is a [LinkedHashSet]. As such, it considers elements that
-   * are equal (using [operator ==]) to be indistinguishable, and requires them to
-   * have a compatible [Object.hashCode] implementation.
-   *
-   * The set is equivalent to one created by
-   * `new LinkedHashSet<E>.from(elements)`.
-   */
+  /// Creates a [Set] that contains all [elements].
+  ///
+  /// All the [elements] should be instances of [E].
+  /// The `elements` iterable itself can have any type,
+  /// so this constructor can be used to down-cast a `Set`, for example as:
+  /// ```dart
+  /// Set<SuperType> superSet = ...;
+  /// Set<SubType> subSet =
+  ///     Set<SubType>.from(superSet.where((e) => e is SubType));
+  /// ```
+  /// The created [Set] is a [LinkedHashSet]. As such, it considers elements that
+  /// are equal (using [operator ==]) to be indistinguishable, and requires them to
+  /// have a compatible [Object.hashCode] implementation.
+  ///
+  /// The set is equivalent to one created by
+  /// `LinkedHashSet<E>.from(elements)`.
   factory Set.from(Iterable elements) = LinkedHashSet<E>.from;
 
-  /**
-   * Creates a [Set] from [elements].
-   *
-   * The created [Set] is a [LinkedHashSet]. As such, it considers elements that
-   * are equal (using [operator ==]) to be indistinguishable, and requires them to
-   * have a compatible [Object.hashCode] implementation.
-   *
-   * The set is equivalent to one created by
-   * `new LinkedHashSet<E>.of(elements)`.
-   */
+  /// Creates a [Set] from [elements].
+  ///
+  /// The created [Set] is a [LinkedHashSet]. As such, it considers elements that
+  /// are equal (using [operator ==]) to be indistinguishable, and requires them to
+  /// have a compatible [Object.hashCode] implementation.
+  ///
+  /// The set is equivalent to one created by
+  /// `LinkedHashSet<E>.of(elements)`.
   factory Set.of(Iterable<E> elements) = LinkedHashSet<E>.of;
 
-  /**
-   * Adapts [source] to be a `Set<T>`.
-   *
-   * If [newSet] is provided, it is used to create the new sets returned
-   * by [toSet], [union], and is also used for [intersection] and [difference].
-   * If [newSet] is omitted, it defaults to creating a new set using the
-   * default [Set] constructor, and [intersection] and [difference]
-   * returns an adapted version of calling the same method on the source.
-   *
-   * Any time the set would produce an element that is not a [T],
-   * the element access will throw.
-   *
-   * Any time a [T] value is attempted added into the adapted set,
-   * the store will throw unless the value is also an instance of [S].
-   *
-   * If all accessed elements of [source] are actually instances of [T],
-   * 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>`.
-   */
+  /// Creates an unmodifiable [Set] from [elements].
+  ///
+  /// The new set behaves like the result of [Set.of],
+  /// except that the set returned by this constructor is not modifiable.
+  @Since("2.12")
+  factory Set.unmodifiable(Iterable<E> elements) =>
+      UnmodifiableSetView<E>(<E>{...elements});
+
+  /// Adapts [source] to be a `Set<T>`.
+  ///
+  /// If [newSet] is provided, it is used to create the new sets returned
+  /// by [toSet], [union], and is also used for [intersection] and [difference].
+  /// If [newSet] is omitted, it defaults to creating a new set using the
+  /// default [Set] constructor, and [intersection] and [difference]
+  /// returns an adapted version of calling the same method on the source.
+  ///
+  /// Any time the set would produce an element that is not a [T],
+  /// the element access will throw.
+  ///
+  /// Any time a [T] value is attempted added into the adapted set,
+  /// the store will throw unless the value is also an instance of [S].
+  ///
+  /// If all accessed elements of [source] are actually instances of [T],
+  /// 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>`.
   static Set<T> castFrom<S, T>(Set<S> source, {Set<R> Function<R>()? newSet}) =>
       CastSet<S, T>(source, newSet);
 
-  /**
-   * Provides a view of this set as a set of [R] instances.
-   *
-   * If this set contains only instances of [R], all read operations
-   * will work correctly. If any operation tries to access an element
-   * that is not an instance of [R], the access will throw instead.
-   *
-   * Elements added to the set (e.g., by using [add] or [addAll])
-   * 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.
-   */
+  /// Provides a view of this set as a set of [R] instances.
+  ///
+  /// If this set contains only instances of [R], all read operations
+  /// will work correctly. If any operation tries to access an element
+  /// that is not an instance of [R], the access will throw instead.
+  ///
+  /// Elements added to the set (e.g., by using [add] or [addAll])
+  /// 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.
   Set<R> cast<R>();
 
-  /**
-   * Provides an iterator that iterates over the elements of this set.
-   *
-   * The order of iteration is defined by the individual `Set` implementation,
-   * but must be consistent between changes to the set.
-   */
+  /// An iterator that iterates over the elements of this set.
+  ///
+  /// The order of iteration is defined by the individual `Set` implementation,
+  /// but must be consistent between changes to the set.
   Iterator<E> get iterator;
 
-  /**
-   * Returns `true` if [value] is in the set.
-   */
+  /// Whether [value] is in the set.
   bool contains(Object? value);
 
-  /**
-   * Adds [value] to the set.
-   *
-   * Returns `true` if [value] (or an equal value) was not yet in the set.
-   * Otherwise returns `false` and the set is not changed.
-   *
-   * Example:
-   *
-   *     var set = new Set();
-   *     var time1 = new DateTime.fromMillisecondsSinceEpoch(0);
-   *     var time2 = new DateTime.fromMillisecondsSinceEpoch(0);
-   *     // time1 and time2 are equal, but not identical.
-   *     Expect.isTrue(time1 == time2);
-   *     Expect.isFalse(identical(time1, time2));
-   *     set.add(time1);  // => true.
-   *     // A value equal to time2 exists already in the set, and the call to
-   *     // add doesn't change the set.
-   *     set.add(time2);  // => false.
-   *     Expect.isTrue(set.length == 1);
-   *     Expect.isTrue(identical(time1, set.first));
-   */
+  /// Adds [value] to the set.
+  ///
+  /// Returns `true` if [value] (or an equal value) was not yet in the set.
+  /// Otherwise returns `false` and the set is not changed.
+  ///
+  /// Example:
+  /// ```dart
+  /// var set = Set();
+  /// var time1 = DateTime.fromMillisecondsSinceEpoch(0);
+  /// var time2 = DateTime.fromMillisecondsSinceEpoch(0);
+  /// // time1 and time2 are equal, but not identical.
+  /// assert(time1 == time2);
+  /// assert(!identical(time1, time2));
+  /// set.add(time1);  // => true.
+  /// // A value equal to time2 exists already in the set, and the call to
+  /// // add doesn't change the set.
+  /// set.add(time2);  // => false.
+  /// assert(set.length == 1);
+  /// assert(identical(time1, set.first));
+  /// ```
   bool add(E value);
 
-  /**
-   * Adds all [elements] to this Set.
-   *
-   * Equivalent to adding each element in [elements] using [add],
-   * but some collections may be able to optimize it.
-   */
+  /// Adds all [elements] to this set.
+  ///
+  /// Equivalent to adding each element in [elements] using [add],
+  /// but some collections may be able to optimize it.
   void addAll(Iterable<E> elements);
 
-  /**
-   * Removes [value] from the set. Returns `true` if [value] was
-   * in the set. Returns `false` otherwise. The method has no effect
-   * if [value] was not in the set.
-   */
+  /// Removes [value] from the set.
+  ///
+  /// Returns `true` if [value] was in the set, and `false` if not.
+  /// The method has no effect if [value] was not in the set.
   bool remove(Object? value);
 
-  /**
-   * If an object equal to [object] is in the set, return it.
-   *
-   * Checks whether [object] is in the set, like [contains], and if so,
-   * returns the object in the set, otherwise returns `null`.
-   *
-   * If the equality relation used by the set is not identity,
-   * then the returned object may not be *identical* to [object].
-   * Some set implementations may not be able to implement this method.
-   * If the [contains] method is computed,
-   * rather than being based on an actual object instance,
-   * then there may not be a specific object instance representing the
-   * set element.
-   */
+  /// If an object equal to [object] is in the set, return it.
+  ///
+  /// Checks whether [object] is in the set, like [contains], and if so,
+  /// returns the object in the set, otherwise returns `null`.
+  ///
+  /// If the equality relation used by the set is not identity,
+  /// then the returned object may not be *identical* to [object].
+  /// Some set implementations may not be able to implement this method.
+  /// If the [contains] method is computed,
+  /// rather than being based on an actual object instance,
+  /// then there may not be a specific object instance representing the
+  /// set element.
   E? lookup(Object? object);
 
-  /**
-   * Removes each element of [elements] from this set.
-   */
+  /// Removes each element of [elements] from this set.
   void removeAll(Iterable<Object?> elements);
 
-  /**
-   * Removes all elements of this set that are not elements in [elements].
-   *
-   * Checks for each element of [elements] whether there is an element in this
-   * set that is equal to it (according to `this.contains`), and if so, the
-   * equal element in this set is retained, and elements that are not equal
-   * to any element in [elements] are removed.
-   */
+  /// Removes all elements of this set that are not elements in [elements].
+  ///
+  /// Checks for each element of [elements] whether there is an element in this
+  /// set that is equal to it (according to `this.contains`), and if so, the
+  /// equal element in this set is retained, and elements that are not equal
+  /// to any element in [elements] are removed.
   void retainAll(Iterable<Object?> elements);
 
-  /**
-   * Removes all elements of this set that satisfy [test].
-   */
+  /// Removes all elements of this set that satisfy [test].
   void removeWhere(bool test(E element));
 
-  /**
-   * Removes all elements of this set that fail to satisfy [test].
-   */
+  /// Removes all elements of this set that fail to satisfy [test].
   void retainWhere(bool test(E element));
 
-  /**
-   * Returns whether this Set contains all the elements of [other].
-   */
+  /// Whether this set contains all the elements of [other].
   bool containsAll(Iterable<Object?> other);
 
-  /**
-   * Returns a new set which is the intersection between this set and [other].
-   *
-   * That is, the returned set contains all the elements of this [Set] that
-   * are also elements of [other] according to `other.contains`.
-   */
+  /// Creates a new set which is the intersection between this set and [other].
+  ///
+  /// That is, the returned set contains all the elements of this [Set] that
+  /// are also elements of [other] according to `other.contains`.
   Set<E> intersection(Set<Object?> other);
 
-  /**
-   * Returns a new set which contains all the elements of this set and [other].
-   *
-   * That is, the returned set contains all the elements of this [Set] and
-   * all the elements of [other].
-   */
+  /// Creates a new set which contains all the elements of this set and [other].
+  ///
+  /// That is, the returned set contains all the elements of this [Set] and
+  /// all the elements of [other].
   Set<E> union(Set<E> other);
 
-  /**
-   * Returns a new set with the elements of this that are not in [other].
-   *
-   * That is, the returned set contains all the elements of this [Set] that
-   * are not elements of [other] according to `other.contains`.
-   */
+  /// Creates a new set with the elements of this that are not in [other].
+  ///
+  /// That is, the returned set contains all the elements of this [Set] that
+  /// are not elements of [other] according to `other.contains`.
   Set<E> difference(Set<Object?> other);
 
-  /**
-   * Removes all elements in the set.
-   */
+  /// Removes all elements from the set.
   void clear();
 
-  /**
-   * Creates a [Set] with the same elements and behavior as this `Set`.
-   *
-   * The returned set behaves the same as this set
-   * with regard to adding and removing elements.
-   * It initially contains the same elements.
-   * If this set specifies an ordering of the elements,
-   * the returned set will have the same order.
-   */
+  /// Creates a [Set] with the same elements and behavior as this `Set`.
+  ///
+  /// The returned set behaves the same as this set
+  /// with regard to adding and removing elements.
+  /// It initially contains the same elements.
+  /// If this set specifies an ordering of the elements,
+  /// the returned set will have the same order.
   Set<E> toSet();
 }
diff --git a/sdk/lib/core/sink.dart b/sdk/lib/core/sink.dart
index c79214b..565ec8f 100644
--- a/sdk/lib/core/sink.dart
+++ b/sdk/lib/core/sink.dart
@@ -4,28 +4,22 @@
 
 part of dart.core;
 
-/**
- * A generic destination for data.
- *
- * Multiple data values can be put into a sink, and when no more data is
- * available, the sink should be closed.
- *
- * This is a generic interface that other data receivers can implement.
- */
+/// A generic destination for data.
+///
+/// Multiple data values can be put into a sink, and when no more data is
+/// available, the sink should be closed.
+///
+/// This is a generic interface that other data receivers can implement.
 abstract class Sink<T> {
-  /**
-   * Adds [data] to the sink.
-   *
-   * Must not be called after a call to [close].
-   */
+  /// Adds [data] to the sink.
+  ///
+  /// Must not be called after a call to [close].
   void add(T data);
 
-  /**
-   * Closes the sink.
-   *
-   * The [add] method must not be called after this method.
-   *
-   * Calling this method more than once is allowed, but does nothing.
-   */
+  /// Closes the sink.
+  ///
+  /// The [add] method must not be called after this method.
+  ///
+  /// Calling this method more than once is allowed, but does nothing.
   void close();
 }
diff --git a/sdk/lib/core/stacktrace.dart b/sdk/lib/core/stacktrace.dart
index ef08f71..dbba199 100644
--- a/sdk/lib/core/stacktrace.dart
+++ b/sdk/lib/core/stacktrace.dart
@@ -4,15 +4,13 @@
 
 part of dart.core;
 
-/**
- * An interface implemented by all stack trace objects.
- *
- * A [StackTrace] is intended to convey information to the user about the call
- * sequence that triggered an exception.
- *
- * These objects are created by the runtime, it is not possible to create
- * them programmatically.
- */
+/// An interface implemented by all stack trace objects.
+///
+/// A [StackTrace] is intended to convey information to the user about the call
+/// sequence that triggered an exception.
+///
+/// These objects are created by the runtime, it is not possible to create
+/// them programmatically.
 abstract class StackTrace {
   /// A stack trace object with no information.
   ///
@@ -23,40 +21,33 @@
 
   StackTrace(); // In case existing classes extend StackTrace.
 
-  /**
-   * Create a `StackTrace` object from [stackTraceString].
-   *
-   * The created stack trace will have a `toString` method returning
-   * `stackTraceString`.
-   *
-   * The `stackTraceString` can be a string returned by some other
-   * stack trace, or it can be any string at all.
-   * If the string doesn't look like a stack trace, code that interprets
-   * stack traces is likely to fail, so fake stack traces should be used
-   * with care.
-   */
+  /// Create a `StackTrace` object from [stackTraceString].
+  ///
+  /// The created stack trace will have a `toString` method returning
+  /// `stackTraceString`.
+  ///
+  /// The `stackTraceString` can be a string returned by some other
+  /// stack trace, or it can be any string at all.
+  /// If the string doesn't look like a stack trace, code that interprets
+  /// stack traces is likely to fail, so fake stack traces should be used
+  /// with care.
   factory StackTrace.fromString(String stackTraceString) = _StringStackTrace;
 
-  /**
-   * Returns a representation of the current stack trace.
-   *
-   * This is similar to what can be achieved by doing:
-   *
-   *     try { throw 0; } catch (_, stack) { return stack; }
-   *
-   * The getter achieves this without throwing, except on platforms that
-   * have no other way to get a stack trace.
-   */
+  /// Returns a representation of the current stack trace.
+  ///
+  /// This is similar to what can be achieved by doing:
+  /// ```dart
+  /// try { throw 0; } catch (_, stack) { return stack; }
+  /// ```
+  /// The getter achieves this without throwing if possible.
   external static StackTrace get current;
 
-  /**
-   * Returns a [String] representation of the stack trace.
-   *
-   * The string represents the full stack trace starting from
-   * the point where a throw occurred to the top of the current call sequence.
-   *
-   * The exact format of the string representation is not final.
-   */
+  /// Returns a [String] representation of the stack trace.
+  ///
+  /// The string represents the full stack trace starting from
+  /// the point where a throw occurred to the top of the current call sequence.
+  ///
+  /// The exact format of the string representation is not final.
   String toString();
 }
 
diff --git a/sdk/lib/core/stopwatch.dart b/sdk/lib/core/stopwatch.dart
index 311db3d..024c28f 100644
--- a/sdk/lib/core/stopwatch.dart
+++ b/sdk/lib/core/stopwatch.dart
@@ -4,15 +4,11 @@
 
 part of dart.core;
 
-/**
- * A simple stopwatch interface to measure elapsed time.
- */
+/// A simple stopwatch interface to measure elapsed time.
 class Stopwatch {
-  /**
-   * Cached frequency of the system in Hz (ticks per second).
-   *
-   * Value must be returned by [_initTicker], which is called only once.
-   */
+  /// Cached frequency of the system in Hz (ticks per second).
+  ///
+  /// Value must be returned by [_initTicker], which is called only once.
   static final int _frequency = _initTicker();
 
   // The _start and _stop fields capture the time when [start] and [stop]
@@ -21,33 +17,27 @@
   int _start = 0;
   int? _stop = 0;
 
-  /**
-   * Creates a [Stopwatch] in stopped state with a zero elapsed count.
-   *
-   * The following example shows how to start a [Stopwatch]
-   * immediately after allocation.
-   * ```
-   * var stopwatch = new Stopwatch()..start();
-   * ```
-   */
+  /// Creates a [Stopwatch] in stopped state with a zero elapsed count.
+  ///
+  /// The following example shows how to start a [Stopwatch]
+  /// immediately after allocation.
+  /// ```
+  /// var stopwatch = Stopwatch()..start();
+  /// ```
   Stopwatch() {
     _frequency; // Ensures initialization before using any method.
   }
 
-  /**
-   * Frequency of the elapsed counter in Hz.
-   */
+  /// Frequency of the elapsed counter in Hz.
   int get frequency => _frequency;
 
-  /**
-   * Starts the [Stopwatch].
-   *
-   * The [elapsed] count is increasing monotonically. If the [Stopwatch] has
-   * been stopped, then calling start again restarts it without resetting the
-   * [elapsed] count.
-   *
-   * If the [Stopwatch] is currently running, then calling start does nothing.
-   */
+  /// Starts the [Stopwatch].
+  ///
+  /// The [elapsed] count is increasing monotonically. If the [Stopwatch] has
+  /// been stopped, then calling start again restarts it without resetting the
+  /// [elapsed] count.
+  ///
+  /// If the [Stopwatch] is currently running, then calling start does nothing.
   void start() {
     int? stop = _stop;
     if (stop != null) {
@@ -58,67 +48,51 @@
     }
   }
 
-  /**
-   * Stops the [Stopwatch].
-   *
-   * The [elapsedTicks] count stops increasing after this call. If the
-   * [Stopwatch] is currently not running, then calling this method has no
-   * effect.
-   */
+  /// Stops the [Stopwatch].
+  ///
+  /// The [elapsedTicks] count stops increasing after this call. If the
+  /// [Stopwatch] is currently not running, then calling this method has no
+  /// effect.
   void stop() {
     _stop ??= _now();
   }
 
-  /**
-   * Resets the [elapsed] count to zero.
-   *
-   * This method does not stop or start the [Stopwatch].
-   */
+  /// Resets the [elapsed] count to zero.
+  ///
+  /// This method does not stop or start the [Stopwatch].
   void reset() {
     _start = _stop ?? _now();
   }
 
-  /**
-   * The elapsed number of clock ticks since calling [start] while the
-   * [Stopwatch] is running.
-   *
-   * This is the elapsed number of clock ticks between calling [start] and
-   * calling [stop].
-   *
-   * Is 0 if the [Stopwatch] has never been started.
-   *
-   * The elapsed number of clock ticks increases by [frequency] every second.
-   */
+  /// The elapsed number of clock ticks since calling [start] while the
+  /// [Stopwatch] is running.
+  ///
+  /// This is the elapsed number of clock ticks between calling [start] and
+  /// calling [stop].
+  ///
+  /// Is 0 if the [Stopwatch] has never been started.
+  ///
+  /// The elapsed number of clock ticks increases by [frequency] every second.
   int get elapsedTicks {
     return (_stop ?? _now()) - _start;
   }
 
-  /**
-   * The [elapsedTicks] counter converted to a [Duration].
-   */
+  /// The [elapsedTicks] counter converted to a [Duration].
   Duration get elapsed {
     return Duration(microseconds: elapsedMicroseconds);
   }
 
-  /**
-   * The [elapsedTicks] counter converted to microseconds.
-   */
+  /// The [elapsedTicks] counter converted to microseconds.
   external int get elapsedMicroseconds;
 
-  /**
-   * The [elapsedTicks] counter converted to milliseconds.
-   */
+  /// The [elapsedTicks] counter converted to milliseconds.
   external int get elapsedMilliseconds;
 
-  /**
-   * Whether the [Stopwatch] is currently running.
-   */
+  /// Whether the [Stopwatch] is currently running.
   bool get isRunning => _stop == null;
 
-  /**
-   * Initializes the time-measuring system. *Must* return the [_frequency]
-   * variable. May do other necessary initialization.
-   */
+  /// Initializes the time-measuring system. *Must* return the [_frequency]
+  /// variable. May do other necessary initialization.
   external static int _initTicker();
   external static int _now();
 }
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 7bef81c..27aba63 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -4,156 +4,148 @@
 
 part of dart.core;
 
-/**
- * A sequence of UTF-16 code units.
- *
- * Strings are mainly used to represent text. A character may be represented by
- * multiple code points, each code point consisting of one or two code
- * units. For example the Papua New Guinea flag character requires four code
- * units to represent two code points, but should be treated like a single
- * character: "🇵🇬". Platforms that do not support the flag character may show
- * the letters "PG" instead. If the code points are swapped, it instead becomes
- * the Guadeloupe flag "🇬🇵" ("GP").
- *
- * A string can be either single or multiline. Single line strings are
- * written using matching single or double quotes, and multiline strings are
- * written using triple quotes. The following are all valid Dart strings:
- *
- *     'Single quotes';
- *     "Double quotes";
- *     'Double quotes in "single" quotes';
- *     "Single quotes in 'double' quotes";
- *
- *     '''A
- *     multiline
- *     string''';
- *
- *     """
- *     Another
- *     multiline
- *     string""";
- *
- * Strings are immutable. Although you cannot change a string, you can perform
- * an operation on a string and assign the result to a new string:
- *
- *     var string = 'Dart is fun';
- *     var newString = string.substring(0, 5);
- *
- * You can use the plus (`+`) operator to concatenate strings:
- *
- *     'Dart ' + 'is ' + 'fun!'; // 'Dart is fun!'
- *
- * You can also use adjacent string literals for concatenation:
- *
- *     'Dart ' 'is ' 'fun!';    // 'Dart is fun!'
- *
- * You can use `${}` to interpolate the value of Dart expressions
- * within strings. The curly braces can be omitted when evaluating identifiers:
- *
- *     string = 'dartlang';
- *     '$string has ${string.length} letters'; // 'dartlang has 8 letters'
- *
- * A string is represented by a sequence of Unicode UTF-16 code units
- * accessible through the [codeUnitAt] or the [codeUnits] members:
- *
- *     string = 'Dart';
- *     string.codeUnitAt(0); // 68
- *     string.codeUnits;     // [68, 97, 114, 116]
- *
- * The string representation of code units is accessible through the index
- * operator:
- *
- *     string[0];            // 'D'
- *
- * The characters of a string are encoded in UTF-16. Decoding UTF-16, which
- * combines surrogate pairs, yields Unicode code points. Following a similar
- * terminology to Go, we use the name 'rune' for an integer representing a
- * Unicode code point. Use the [runes] property to get the runes of a string:
- *
- *     string.runes.toList(); // [68, 97, 114, 116]
- *
- * For a character outside the Basic Multilingual Plane (plane 0) that is
- * composed of a surrogate pair, [runes] combines the pair and returns a
- * single integer.  For example, the Unicode character for a
- * musical G-clef ('𝄞') with rune value 0x1D11E consists of a UTF-16 surrogate
- * pair: `0xD834` and `0xDD1E`. Using [codeUnits] returns the surrogate pair,
- * and using `runes` returns their combined value:
- *
- *     var clef = '\u{1D11E}';
- *     clef.codeUnits;         // [0xD834, 0xDD1E]
- *     clef.runes.toList();    // [0x1D11E]
- *
- * The String class can not be extended or implemented. Attempting to do so
- * yields a compile-time error.
- *
- * ## Other resources
- *
- * See [StringBuffer] to efficiently build a string incrementally. See
- * [RegExp] to work with regular expressions.
- *
- * Also see:
- *
- * * [Strings and regular expressions](https://dart.dev/guides/libraries/library-tour#strings-and-regular-expressions)
- */
+/// A sequence of UTF-16 code units.
+///
+/// Strings are mainly used to represent text. A character may be represented by
+/// multiple code points, each code point consisting of one or two code
+/// units. For example the Papua New Guinea flag character requires four code
+/// units to represent two code points, but should be treated like a single
+/// character: "🇵🇬". Platforms that do not support the flag character may show
+/// the letters "PG" instead. If the code points are swapped, it instead becomes
+/// the Guadeloupe flag "🇬🇵" ("GP").
+///
+/// A string can be either single or multiline. Single line strings are
+/// written using matching single or double quotes, and multiline strings are
+/// written using triple quotes. The following are all valid Dart strings:
+/// ```dart
+/// 'Single quotes';
+/// "Double quotes";
+/// 'Double quotes in "single" quotes';
+/// "Single quotes in 'double' quotes";
+///
+/// '''A
+/// multiline
+/// string''';
+///
+/// """
+/// Another
+/// multiline
+/// string""";
+/// ```
+/// Strings are immutable. Although you cannot change a string, you can perform
+/// an operation on a string which creates a new string:
+/// ```dart
+/// var string = 'Dart is fun';
+/// var newString = string.substring(0, 5);
+/// ```
+/// You can use the plus (`+`) operator to concatenate strings:
+/// ```dart
+/// 'Dart ' + 'is ' + 'fun!'; // 'Dart is fun!'
+/// ```
+/// Adjacent string literals are concatenated automatically:
+/// ```dart
+/// 'Dart ' 'is ' 'fun!';    // 'Dart is fun!'
+/// ```
+/// You can use `${}` to interpolate the value of Dart expressions
+/// within strings. The curly braces can be omitted when evaluating identifiers:
+/// ```dart
+/// string = 'dartlang';
+/// '$string has ${string.length} letters'; // 'dartlang has 8 letters'
+/// ```
+/// A string is represented by a sequence of Unicode UTF-16 code units
+/// accessible through the [codeUnitAt] or the [codeUnits] members:
+/// ```dart
+/// string = 'Dart';
+/// string.codeUnitAt(0); // 68
+/// string.codeUnits;     // [68, 97, 114, 116]
+/// ```
+/// The string representation of code units is accessible through the index
+/// operator:
+/// ```dart
+/// string[0];            // 'D'
+/// ```
+/// The characters of a string are encoded in UTF-16. Decoding UTF-16, which
+/// combines surrogate pairs, yields Unicode code points. Following a similar
+/// terminology to Go, we use the name 'rune' for an integer representing a
+/// Unicode code point. Use the [runes] property to get the runes of a string:
+/// ```dart
+/// string.runes.toList(); // [68, 97, 114, 116]
+/// ```
+/// For a character outside the Basic Multilingual Plane (plane 0) that is
+/// composed of a surrogate pair, [runes] combines the pair and returns a
+/// single integer.  For example, the Unicode character for a
+/// musical G-clef ('𝄞') with rune value 0x1D11E consists of a UTF-16 surrogate
+/// pair: `0xD834` and `0xDD1E`. Using [codeUnits] returns the surrogate pair,
+/// and using `runes` returns their combined value:
+/// ```dart
+/// var clef = '\u{1D11E}';
+/// clef.codeUnits;         // [0xD834, 0xDD1E]
+/// clef.runes.toList();    // [0x1D11E]
+/// ```
+/// The `String` class cannot be extended or implemented. Attempting to do so
+/// yields a compile-time error.
+///
+/// ## Other resources
+///
+/// See [StringBuffer] to efficiently build a string incrementally. See
+/// [RegExp] to work with regular expressions.
+///
+/// Also see:
+///
+/// * [Strings and regular expressions](https://dart.dev/guides/libraries/library-tour#strings-and-regular-expressions)
 @pragma('vm:entry-point')
 abstract class String implements Comparable<String>, Pattern {
-  /**
-   * Allocates a new String for the specified [charCodes].
-   *
-   * The [charCodes] can be UTF-16 code units or runes. If a char-code value is
-   * 16-bit, it is copied verbatim:
-   *
-   *     new String.fromCharCodes([68]); // 'D'
-   *
-   * If a char-code value is greater than 16-bits, it is decomposed into a
-   * surrogate pair:
-   *
-   *     var clef = new String.fromCharCodes([0x1D11E]);
-   *     clef.codeUnitAt(0); // 0xD834
-   *     clef.codeUnitAt(1); // 0xDD1E
-   *
-   * If [start] and [end] is provided, only the values of [charCodes]
-   * at positions from `start` to, but not including, `end`, are used.
-   * The `start` and `end` values must satisfy
-   * `0 <= start <= end <= charCodes.length`.
-   */
+  /// Allocates a new string containing the specified [charCodes].
+  ///
+  /// The [charCodes] can be both UTF-16 code units or runes.
+  /// If a char-code value is 16-bit, it is used as a code unit:
+  /// ```dart
+  /// String.fromCharCodes([68]); // 'D'
+  /// ```
+  /// If a char-code value is greater than 16-bits, it is decomposed into a
+  /// surrogate pair:
+  /// ```dart
+  /// var clef = String.fromCharCodes([0x1D11E]);
+  /// clef.codeUnitAt(0); // 0xD834
+  /// clef.codeUnitAt(1); // 0xDD1E
+  /// ```
+  /// If [start] and [end] are provided, only the values of [charCodes]
+  /// at positions from `start` to, but not including, `end`, are used.
+  /// The `start` and `end` values must satisfy
+  /// `0 <= start <= end <= charCodes.length`.
   external factory String.fromCharCodes(Iterable<int> charCodes,
       [int start = 0, int? end]);
 
-  /**
-   * Allocates a new String for the specified [charCode].
-   *
-   * If the [charCode] can be represented by a single UTF-16 code unit, the new
-   * string contains a single code unit. Otherwise, the [length] is 2 and
-   * the code units form a surrogate pair. See documentation for
-   * [fromCharCodes].
-   *
-   * Creating a [String] with one half of a surrogate pair is allowed.
-   */
+  /// Allocates a new string containing the specified [charCode].
+  ///
+  /// If the [charCode] can be represented by a single UTF-16 code unit, the new
+  /// string contains a single code unit. Otherwise, the [length] is 2 and
+  /// the code units form a surrogate pair. See documentation for
+  /// [fromCharCodes].
+  ///
+  /// Creating a [String] with one half of a surrogate pair is allowed.
   external factory String.fromCharCode(int charCode);
 
-  /**
-   * Returns the string value of the environment declaration [name].
-   *
-   * Environment declarations are provided by the surrounding system compiling
-   * or running the Dart program. Declarations map a string key to a string
-   * value.
-   *
-   * If [name] is not declared in the environment, the result is instead
-   * [defaultValue].
-   *
-   * Example of getting a value:
-   * ```
-   * const String.fromEnvironment("defaultFloo", defaultValue: "no floo")
-   * ```
-   * In order to check whether a declaration is there at all, use
-   * [bool.hasEnvironment]. Example:
-   * ```
-   * const maybeDeclared = bool.hasEnvironment("maybeDeclared")
-   *     ? String.fromEnvironment("maybeDeclared")
-   *     : null;
-   * ```
-   */
+  /// The string value of the environment declaration [name].
+  ///
+  /// Environment declarations are provided by the surrounding system compiling
+  /// or running the Dart program. Declarations map a string key to a string
+  /// value.
+  ///
+  /// If [name] is not declared in the environment, the result is instead
+  /// [defaultValue].
+  ///
+  /// Example of getting a value:
+  /// ```
+  /// const String.fromEnvironment("defaultFloo", defaultValue: "no floo")
+  /// ```
+  /// In order to check whether a declaration is there at all, use
+  /// [bool.hasEnvironment]. Example:
+  /// ```
+  /// const maybeDeclared = bool.hasEnvironment("maybeDeclared")
+  ///     ? String.fromEnvironment("maybeDeclared")
+  ///     : null;
+  /// ```
   // The .fromEnvironment() constructors are special in that we do not want
   // users to call them using "new". We prohibit that by giving them bodies
   // that throw, even though const constructors are not allowed to have bodies.
@@ -163,484 +155,447 @@
   external const factory String.fromEnvironment(String name,
       {String defaultValue = ""});
 
-  /**
-   * Gets the character (as a single-code-unit [String]) at the given [index].
-   *
-   * The returned string represents exactly one UTF-16 code unit, which may be
-   * half of a surrogate pair. A single member of a surrogate pair is an
-   * invalid UTF-16 string:
-   *
-   *     var clef = '\u{1D11E}';
-   *     // These represent invalid UTF-16 strings.
-   *     clef[0].codeUnits;      // [0xD834]
-   *     clef[1].codeUnits;      // [0xDD1E]
-   *
-   * This method is equivalent to
-   * `new String.fromCharCode(this.codeUnitAt(index))`.
-   */
+  /// The character (as a single-code-unit [String]) at the given [index].
+  ///
+  /// The returned string represents exactly one UTF-16 code unit, which may be
+  /// half of a surrogate pair. A single member of a surrogate pair is an
+  /// invalid UTF-16 string:
+  /// ```dart
+  /// var clef = '\u{1D11E}';
+  /// // These represent invalid UTF-16 strings.
+  /// clef[0].codeUnits;      // [0xD834]
+  /// clef[1].codeUnits;      // [0xDD1E]
+  /// ```
+  /// This method is equivalent to
+  /// `String.fromCharCode(this.codeUnitAt(index))`.
   String operator [](int index);
 
-  /**
-   * Returns the 16-bit UTF-16 code unit at the given [index].
-   */
+  /// Returns the 16-bit UTF-16 code unit at the given [index].
   int codeUnitAt(int index);
 
-  /**
-   * The length of the string.
-   *
-   * Returns the number of UTF-16 code units in this string. The number
-   * of [runes] might be fewer, if the string contains characters outside
-   * the Basic Multilingual Plane (plane 0):
-   *
-   *     'Dart'.length;          // 4
-   *     'Dart'.runes.length;    // 4
-   *
-   *     var clef = '\u{1D11E}';
-   *     clef.length;            // 2
-   *     clef.runes.length;      // 1
-   */
+  /// The length of the string.
+  ///
+  /// Returns the number of UTF-16 code units in this string. The number
+  /// of [runes] might be fewer, if the string contains characters outside
+  /// the Basic Multilingual Plane (plane 0):
+  /// ```dart
+  /// 'Dart'.length;          // 4
+  /// 'Dart'.runes.length;    // 4
+  ///
+  /// var clef = '\u{1D11E}';
+  /// clef.length;            // 2
+  /// clef.runes.length;      // 1
+  /// ```
   int get length;
 
-  /**
-   * Returns a hash code derived from the code units of the string.
-   *
-   * This is compatible with [operator ==]. Strings with the same sequence
-   * of code units have the same hash code.
-   */
+  /// A hash code derived from the code units of the string.
+  ///
+  /// This is compatible with [operator ==]. Strings with the same sequence
+  /// of code units have the same hash code.
   int get hashCode;
 
-  /**
-   * Returns true if other is a `String` with the same sequence of code units.
-   *
-   * This method compares each individual code unit of the strings.
-   * It does not check for Unicode equivalence.
-   * For example, both the following strings represent the string 'Amélie',
-   * but due to their different encoding, are not equal:
-   *
-   *     'Am\xe9lie' == 'Ame\u{301}lie'; // false
-   *
-   * The first string encodes 'é' as a single unicode code unit (also
-   * a single rune), whereas the second string encodes it as 'e' with the
-   * combining accent character '◌́'.
-   */
+  /// Whether [other] is a `String` with the same sequence of code units.
+  ///
+  /// This method compares each individual code unit of the strings.
+  /// It does not check for Unicode equivalence.
+  /// For example, both the following strings represent the string 'Amélie',
+  /// but due to their different encoding, are not equal:
+  /// ```dart
+  /// 'Am\xe9lie' == 'Ame\u{301}lie'; // false
+  /// ```
+  /// The first string encodes 'é' as a single unicode code unit (also
+  /// a single rune), whereas the second string encodes it as 'e' with the
+  /// combining accent character '◌́'.
   bool operator ==(Object other);
 
-  /**
-   * Compares this string to [other].
-   *
-   * Returns a negative value if `this` is ordered before `other`,
-   * a positive value if `this` is ordered after `other`,
-   * or zero if `this` and `other` are equivalent.
-   *
-   * The ordering is the same as the ordering of the code points at the first
-   * position where the two strings differ.
-   * If one string is a prefix of the other,
-   * then the shorter string is ordered before the longer string.
-   * If the strings have exactly the same content, they are equivalent with
-   * regard to the ordering.
-   * Ordering does not check for Unicode equivalence.
-   * The comparison is case sensitive.
-   */
+  /// Compares this string to [other].
+  ///
+  /// Returns a negative value if `this` is ordered before `other`,
+  /// a positive value if `this` is ordered after `other`,
+  /// or zero if `this` and `other` are equivalent.
+  ///
+  /// The ordering is the same as the ordering of the code points at the first
+  /// position where the two strings differ.
+  /// If one string is a prefix of the other,
+  /// then the shorter string is ordered before the longer string.
+  /// If the strings have exactly the same content, they are equivalent with
+  /// regard to the ordering.
+  /// Ordering does not check for Unicode equivalence.
+  /// The comparison is case sensitive.
   int compareTo(String other);
 
-  /**
-   * Returns true if this string ends with [other]. For example:
-   *
-   *     'Dart'.endsWith('t'); // true
-   */
+  /// Whether this string ends with [other].
+  ///
+  /// For example:
+  /// ```dart
+  /// 'Dart'.endsWith('t'); // true
+  /// ```
   bool endsWith(String other);
 
-  /**
-   * Returns true if this string starts with a match of [pattern].
-   *
-   *     var string = 'Dart';
-   *     string.startsWith('D');                       // true
-   *     string.startsWith(new RegExp(r'[A-Z][a-z]')); // true
-   *
-   * If [index] is provided, this method checks if the substring starting
-   * at that index starts with a match of [pattern]:
-   *
-   *     string.startsWith('art', 1);                  // true
-   *     string.startsWith(new RegExp(r'\w{3}'));      // true
-   *
-   * [index] must not be negative or greater than [length].
-   *
-   * A [RegExp] containing '^' does not match if the [index] is greater than
-   * zero. The pattern works on the string as a whole, and does not extract
-   * a substring starting at [index] first:
-   *
-   *     string.startsWith(new RegExp(r'^art'), 1);    // false
-   *     string.startsWith(new RegExp(r'art'), 1);     // true
-   */
+  /// Whether this string starts with a match of [pattern].
+  ///
+  /// ```dart
+  /// var string = 'Dart';
+  /// string.startsWith('D');                       // true
+  /// string.startsWith(RegExp(r'[A-Z][a-z]')); // true
+  /// ```
+  /// If [index] is provided, this method checks if the substring starting
+  /// at that index starts with a match of [pattern]:
+  /// ```dart
+  /// string.startsWith('art', 1);                  // true
+  /// string.startsWith(RegExp(r'\w{3}'));      // true
+  /// ```
+  /// [index] must not be negative or greater than [length].
+  ///
+  /// A [RegExp] containing '^' does not match if the [index] is greater than
+  /// zero and the regexp is not multi-line.
+  /// The pattern works on the string as a whole, and does not extract
+  /// a substring starting at [index] first:
+  /// ```dart
+  /// string.startsWith(RegExp(r'^art'), 1);    // false
+  /// string.startsWith(RegExp(r'art'), 1);     // true
+  /// ```
   bool startsWith(Pattern pattern, [int index = 0]);
 
-  /**
-   * Returns the position of the first match of [pattern] in this string,
-   * starting at [start], inclusive:
-   *
-   *     var string = 'Dartisans';
-   *     string.indexOf('art');                     // 1
-   *     string.indexOf(new RegExp(r'[A-Z][a-z]')); // 0
-   *
-   * Returns -1 if no match is found:
-   *
-   *     string.indexOf(new RegExp(r'dart'));       // -1
-   *
-   * [start] must be non-negative and not greater than [length].
-   */
+  /// Returns the position of the first match of [pattern] in this string,
+  /// starting at [start], inclusive:
+  /// ```dart
+  /// var string = 'Dartisans';
+  /// string.indexOf('art');                     // 1
+  /// string.indexOf(RegExp(r'[A-Z][a-z]')); // 0
+  /// ```
+  /// Returns -1 if no match is found:
+  /// ```dart
+  /// string.indexOf(RegExp(r'dart'));       // -1
+  /// ```
+  /// The [start] must be non-negative and not greater than [length].
   int indexOf(Pattern pattern, [int start = 0]);
 
-  /**
-   * Returns the starting position of the last match [pattern] in this string,
-   * searching backward starting at [start], inclusive:
-   *
-   *     var string = 'Dartisans';
-   *     string.lastIndexOf('a');                    // 6
-   *     string.lastIndexOf(RegExp(r'a(r|n)'));      // 6
-   *
-   * Returns -1 if [pattern] could not be found in this string.
-   *
-   *     string.lastIndexOf(RegExp(r'DART'));        // -1
-   *
-   * If [start] is omitted, search starts from the end of the string.
-   * If supplied, [start] must be non-negative and not greater than [length].
-   */
+  /// The starting position of the last match [pattern] in this string.
+  ///
+  /// Finds a match of pattern by searching backward starting at [start]:
+  /// ```dart
+  /// var string = 'Dartisans';
+  /// string.lastIndexOf('a');                    // 6
+  /// string.lastIndexOf(RegExp(r'a(r|n)'));      // 6
+  /// ```
+  /// Returns -1 if [pattern] could not be found in this string.
+  /// ```dart
+  /// string.lastIndexOf(RegExp(r'DART'));        // -1
+  /// ```
+  /// If [start] is omitted, search starts from the end of the string.
+  /// If supplied, [start] must be non-negative and not greater than [length].
   int lastIndexOf(Pattern pattern, [int? start]);
 
-  /**
-   * Returns true if this string is empty.
-   */
+  /// Whether this string is empty.
   bool get isEmpty;
 
-  /**
-   * Returns true if this string is not empty.
-   */
+  /// Whether this string is not empty.
   bool get isNotEmpty;
 
-  /**
-   * Creates a new string by concatenating this string with [other].
-   *
-   *     'dart' + 'lang'; // 'dartlang'
-   */
+  /// Creates a new string by concatenating this string with [other].
+  ///
+  /// Example:
+  /// ```dart
+  /// 'dart' + 'lang'; // 'dartlang'
+  /// ```
   String operator +(String other);
 
-  /**
-   * Returns the substring of this string that extends from [startIndex],
-   * inclusive, to [endIndex], exclusive.
-   *
-   *     var string = 'dartlang';
-   *     string.substring(1);    // 'artlang'
-   *     string.substring(1, 4); // 'art'
-   */
-  String substring(int startIndex, [int? endIndex]);
+  /// The substring of this string from [start],inclusive, to [end], exclusive.
+  ///
+  /// Example:
+  /// ```dart
+  /// var string = 'dartlang';
+  /// string.substring(1);    // 'artlang'
+  /// string.substring(1, 4); // 'art'
+  /// ```
+  String substring(int start, [int? end]);
 
-  /**
-   * Returns the string without any leading and trailing whitespace.
-   *
-   * If the string contains leading or trailing whitespace, a new string with no
-   * leading and no trailing whitespace is returned:
-   * ```dart
-   * '\tDart is fun\n'.trim(); // 'Dart is fun'
-   * ```
-   * Otherwise, the original string itself is returned:
-   * ```dart
-   * var str1 = 'Dart';
-   * var str2 = str1.trim();
-   * identical(str1, str2);    // true
-   * ```
-   * Whitespace is defined by the Unicode White_Space property (as defined in
-   * version 6.2 or later) and the BOM character, 0xFEFF.
-   *
-   * Here is the list of trimmed characters according to Unicode version 6.3:
-   * ```
-   *     0009..000D    ; White_Space # Cc   <control-0009>..<control-000D>
-   *     0020          ; White_Space # Zs   SPACE
-   *     0085          ; White_Space # Cc   <control-0085>
-   *     00A0          ; White_Space # Zs   NO-BREAK SPACE
-   *     1680          ; White_Space # Zs   OGHAM SPACE MARK
-   *     2000..200A    ; White_Space # Zs   EN QUAD..HAIR SPACE
-   *     2028          ; White_Space # Zl   LINE SEPARATOR
-   *     2029          ; White_Space # Zp   PARAGRAPH SEPARATOR
-   *     202F          ; White_Space # Zs   NARROW NO-BREAK SPACE
-   *     205F          ; White_Space # Zs   MEDIUM MATHEMATICAL SPACE
-   *     3000          ; White_Space # Zs   IDEOGRAPHIC SPACE
-   *
-   *     FEFF          ; BOM                ZERO WIDTH NO_BREAK SPACE
-   * ```
-   * Some later versions of Unicode do not include U+0085 as a whitespace
-   * character. Whether it is trimmed depends on the Unicode version
-   * used by the system.
-   */
+  /// The string without any leading and trailing whitespace.
+  ///
+  /// If the string contains leading or trailing whitespace, a new string with no
+  /// leading and no trailing whitespace is returned:
+  /// ```dart
+  /// '\tDart is fun\n'.trim(); // 'Dart is fun'
+  /// ```
+  /// Otherwise, the original string itself is returned:
+  /// ```dart
+  /// var str1 = 'Dart';
+  /// var str2 = str1.trim();
+  /// identical(str1, str2);    // true
+  /// ```
+  /// Whitespace is defined by the Unicode White_Space property (as defined in
+  /// version 6.2 or later) and the BOM character, 0xFEFF.
+  ///
+  /// Here is the list of trimmed characters according to Unicode version 6.3:
+  /// ```
+  ///     0009..000D    ; White_Space # Cc   <control-0009>..<control-000D>
+  ///     0020          ; White_Space # Zs   SPACE
+  ///     0085          ; White_Space # Cc   <control-0085>
+  ///     00A0          ; White_Space # Zs   NO-BREAK SPACE
+  ///     1680          ; White_Space # Zs   OGHAM SPACE MARK
+  ///     2000..200A    ; White_Space # Zs   EN QUAD..HAIR SPACE
+  ///     2028          ; White_Space # Zl   LINE SEPARATOR
+  ///     2029          ; White_Space # Zp   PARAGRAPH SEPARATOR
+  ///     202F          ; White_Space # Zs   NARROW NO-BREAK SPACE
+  ///     205F          ; White_Space # Zs   MEDIUM MATHEMATICAL SPACE
+  ///     3000          ; White_Space # Zs   IDEOGRAPHIC SPACE
+  ///
+  ///     FEFF          ; BOM                ZERO WIDTH NO_BREAK SPACE
+  /// ```
+  /// Some later versions of Unicode do not include U+0085 as a whitespace
+  /// character. Whether it is trimmed depends on the Unicode version
+  /// used by the system.
   String trim();
 
-  /**
-   * Returns the string without any leading whitespace.
-   *
-   * As [trim], but only removes leading whitespace.
-   */
+  /// The string without any leading whitespace.
+  ///
+  /// As [trim], but only removes leading whitespace.
   String trimLeft();
 
-  /**
-   * Returns the string without any trailing whitespace.
-   *
-   * As [trim], but only removes trailing whitespace.
-   */
+  /// The string without any trailing whitespace.
+  ///
+  /// As [trim], but only removes trailing whitespace.
   String trimRight();
 
-  /**
-   * Creates a new string by concatenating this string with itself a number
-   * of times.
-   *
-   * The result of `str * n` is equivalent to
-   * `str + str + ...`(n times)`... + str`.
-   *
-   * Returns an empty string if [times] is zero or negative.
-   */
+  /// Creates a new string by concatenating this string with itself a number
+  /// of times.
+  ///
+  /// The result of `str * n` is equivalent to
+  /// `str + str + ...`(n times)`... + str`.
+  ///
+  /// Returns an empty string if [times] is zero or negative.
   String operator *(int times);
 
-  /**
-   * Pads this string on the left if it is shorter than [width].
-   *
-   * Return a new string that prepends [padding] onto this string
-   * one time for each position the length is less than [width].
-   *
-   * If [width] is already smaller than or equal to `this.length`,
-   * no padding is added. A negative `width` is treated as zero.
-   *
-   * If [padding] has length different from 1, the result will not
-   * have length `width`. This may be useful for cases where the
-   * padding is a longer string representing a single character, like
-   * `"&nbsp;"` or `"\u{10002}`".
-   * In that case, the user should make sure that `this.length` is
-   * the correct measure of the strings length.
-   */
+  /// Pads this string on the left if it is shorter than [width].
+  ///
+  /// Returns a new string that prepends [padding] onto this string
+  /// one time for each position the length is less than [width].
+  ///
+  /// If [width] is already smaller than or equal to `this.length`,
+  /// no padding is added. A negative `width` is treated as zero.
+  ///
+  /// If [padding] has length different from 1, the result will not
+  /// have length `width`. This may be useful for cases where the
+  /// padding is a longer string representing a single character, like
+  /// `"&nbsp;"` or `"\u{10002}`".
+  /// In that case, the user should make sure that `this.length` is
+  /// the correct measure of the strings length.
   String padLeft(int width, [String padding = ' ']);
 
-  /**
-   * Pads this string on the right if it is shorter than [width].
-   *
-   * Return a new string that appends [padding] after this string
-   * one time for each position the length is less than [width].
-   *
-   * If [width] is already smaller than or equal to `this.length`,
-   * no padding is added. A negative `width` is treated as zero.
-   *
-   * If [padding] has length different from 1, the result will not
-   * have length `width`. This may be useful for cases where the
-   * padding is a longer string representing a single character, like
-   * `"&nbsp;"` or `"\u{10002}`".
-   * In that case, the user should make sure that `this.length` is
-   * the correct measure of the strings length.
-   */
+  /// Pads this string on the right if it is shorter than [width].
+  ///
+  /// Returns a new string that appends [padding] after this string
+  /// one time for each position the length is less than [width].
+  ///
+  /// If [width] is already smaller than or equal to `this.length`,
+  /// no padding is added. A negative `width` is treated as zero.
+  ///
+  /// If [padding] has length different from 1, the result will not
+  /// have length `width`. This may be useful for cases where the
+  /// padding is a longer string representing a single character, like
+  /// `"&nbsp;"` or `"\u{10002}`".
+  /// In that case, the user should make sure that `this.length` is
+  /// the correct measure of the strings length.
   String padRight(int width, [String padding = ' ']);
 
-  /**
-   * Returns true if this string contains a match of [other]:
-   *
-   *     var string = 'Dart strings';
-   *     string.contains('D');                     // true
-   *     string.contains(new RegExp(r'[A-Z]'));    // true
-   *
-   * If [startIndex] is provided, this method matches only at or after that
-   * index:
-   *
-   *     string.contains('X', 1);                  // false
-   *     string.contains(new RegExp(r'[A-Z]'), 1); // false
-   *
-   * [startIndex] must not be negative or greater than [length].
-   */
+  /// Whether this string contains a match of [other].
+  ///
+  /// Example:
+  /// ```dart
+  /// var string = 'Dart strings';
+  /// string.contains('D');                     // true
+  /// string.contains(RegExp(r'[A-Z]'));    // true
+  /// ```
+  /// If [startIndex] is provided, this method matches only at or after that
+  /// index:
+  /// ```dart
+  /// string.contains('D', 1);                  // false
+  /// string.contains(RegExp(r'[A-Z]'), 1); // false
+  /// ```
+  /// The [startIndex] must not be negative or greater than [length].
   bool contains(Pattern other, [int startIndex = 0]);
 
-  /**
-   * Returns a new string in which the first occurrence of [from] in this string
-   * is replaced with [to], starting from [startIndex]:
-   *
-   *     '0.0001'.replaceFirst(new RegExp(r'0'), ''); // '.0001'
-   *     '0.0001'.replaceFirst(new RegExp(r'0'), '7', 1); // '0.7001'
-   */
+  /// Creates a new string with the first occurrence of [from] replaced by [to].
+  ///
+  /// Finds the first match of [from] in this string, starting from [startIndex],
+  /// and creates a new string where that match is replaced with the [to] string.
+  ///
+  /// Example:
+  /// ```dart
+  /// '0.0001'.replaceFirst(RegExp(r'0'), ''); // '.0001'
+  /// '0.0001'.replaceFirst(RegExp(r'0'), '7', 1); // '0.7001'
+  /// ```
   String replaceFirst(Pattern from, String to, [int startIndex = 0]);
 
-  /**
-   * Replace the first occurrence of [from] in this string.
-   *
-   * Returns a new string, which is this string
-   * except that the first match of [from], starting from [startIndex],
-   * is replaced by the result of calling [replace] with the match object.
-   *
-   * The optional [startIndex] is by default set to 0. If provided, it must be
-   * an integer in the range `[0 .. len]`, where `len` is this string's length.
-   */
+  /// Replace the first occurrence of [from] in this string.
+  ///
+  /// Returns a new string, which is this string
+  /// except that the first match of [from], starting from [startIndex],
+  /// is replaced by the result of calling [replace] with the match object.
+  ///
+  /// The [startIndex] must be non-negative and no greater than [length].
   String replaceFirstMapped(Pattern from, String replace(Match match),
       [int startIndex = 0]);
 
-  /**
-   * Replaces all substrings that match [from] with [replace].
-   *
-   * Returns a new string in which the non-overlapping substrings matching
-   * [from] (the ones iterated by `from.allMatches(thisString)`) are replaced
-   * by the literal string [replace].
-   *
-   *     'resume'.replaceAll(new RegExp(r'e'), 'é'); // 'résumé'
-   *
-   * Notice that the [replace] string is not interpreted. If the replacement
-   * depends on the match (for example on a [RegExp]'s capture groups), use
-   * the [replaceAllMapped] method instead.
-   */
+  /// Replaces all substrings that match [from] with [replace].
+  ///
+  /// Creates a new string in which the non-overlapping substrings matching
+  /// [from] (the ones iterated by `from.allMatches(thisString)`) are replaced
+  /// by the literal string [replace].
+  /// ```dart
+  /// 'resume'.replaceAll(RegExp(r'e'), 'é'); // 'résumé'
+  /// ```
+  /// Notice that the [replace] string is not interpreted. If the replacement
+  /// depends on the match (for example on a [RegExp]'s capture groups), use
+  /// the [replaceAllMapped] method instead.
   String replaceAll(Pattern from, String replace);
 
-  /**
-   * Replace all substrings that match [from] by a string computed from the
-   * match.
-   *
-   * Returns a new string in which the non-overlapping substrings that match
-   * [from] (the ones iterated by `from.allMatches(thisString)`) are replaced
-   * by the result of calling [replace] on the corresponding [Match] object.
-   *
-   * This can be used to replace matches with new content that depends on the
-   * match, unlike [replaceAll] where the replacement string is always the same.
-   *
-   * The [replace] function is called with the [Match] generated
-   * by the pattern, and its result is used as replacement.
-   *
-   * The function defined below converts each word in a string to simplified
-   * 'pig latin' using [replaceAllMapped]:
-   *
-   *     pigLatin(String words) => words.replaceAllMapped(
-   *         new RegExp(r'\b(\w*?)([aeiou]\w*)', caseSensitive: false),
-   *         (Match m) => "${m[2]}${m[1]}${m[1].isEmpty ? 'way' : 'ay'}");
-   *
-   *     pigLatin('I have a secret now!'); // 'Iway avehay away ecretsay ownay!'
-   */
+  /// Replace all substrings that match [from] by a computed string.
+  ///
+  /// Creates a new string in which the non-overlapping substrings that match
+  /// [from] (the ones iterated by `from.allMatches(thisString)`) are replaced
+  /// by the result of calling [replace] on the corresponding [Match] object.
+  ///
+  /// This can be used to replace matches with new content that depends on the
+  /// match, unlike [replaceAll] where the replacement string is always the same.
+  ///
+  /// The [replace] function is called with the [Match] generated
+  /// by the pattern, and its result is used as replacement.
+  ///
+  /// The function defined below converts each word in a string to simplified
+  /// 'pig latin' using [replaceAllMapped]:
+  /// ```dart
+  /// pigLatin(String words) => words.replaceAllMapped(
+  ///     RegExp(r'\b(\w*?)([aeiou]\w*)', caseSensitive: false),
+  ///     (Match m) => "${m[2]}${m[1]}${m[1]!.isEmpty ? 'way' : 'ay'}");
+  ///
+  ///     pigLatin('I have a secret now!'); // 'Iway avehay away ecretsay ownay!'
+  /// ```
   String replaceAllMapped(Pattern from, String Function(Match match) replace);
 
-  /**
-   * Replaces the substring from [start] to [end] with [replacement].
-   *
-   * Returns a new string equivalent to:
-   *
-   *     this.substring(0, start) + replacement + this.substring(end)
-   *
-   * The [start] and [end] indices must specify a valid range of this string.
-   * That is `0 <= start <= end <= this.length`.
-   * If [end] is `null`, it defaults to [length].
-   */
+  /// Replaces the substring from [start] to [end] with [replacement].
+  ///
+  /// Creates a new string equivalent to:
+  /// ```dart
+  /// this.substring(0, start) + replacement + this.substring(end)
+  /// ```
+  /// The [start] and [end] indices must specify a valid range of this string.
+  /// That is `0 <= start <= end <= this.length`.
+  /// If [end] is `null`, it defaults to [length].
   String replaceRange(int start, int? end, String replacement);
 
-  /**
-   * Splits the string at matches of [pattern] and returns a list of substrings.
-   *
-   * Finds all the matches of `pattern` in this string,
-   * and returns the list of the substrings between the matches.
-   *
-   *     var string = "Hello world!";
-   *     string.split(" ");                      // ['Hello', 'world!'];
-   *
-   * Empty matches at the beginning and end of the strings are ignored,
-   * and so are empty matches right after another match.
-   *
-   *     var string = "abba";
-   *     string.split(new RegExp(r"b*"));        // ['a', 'a']
-   *                                             // not ['', 'a', 'a', '']
-   *
-   * If this string is empty, the result is an empty list if `pattern` matches
-   * the empty string, and it is `[""]` if the pattern doesn't match.
-   *
-   *     var string = '';
-   *     string.split('');                       // []
-   *     string.split("a");                      // ['']
-   *
-   * Splitting with an empty pattern splits the string into single-code unit
-   * strings.
-   *
-   *     var string = 'Pub';
-   *     string.split('');                       // ['P', 'u', 'b']
-   *
-   *     string.codeUnits.map((unit) {
-   *       return new String.fromCharCode(unit);
-   *     }).toList();                            // ['P', 'u', 'b']
-   *
-   * Splitting happens at UTF-16 code unit boundaries,
-   * and not at rune boundaries:
-   *
-   *     // String made up of two code units, but one rune.
-   *     string = '\u{1D11E}';
-   *     string.split('').length;                 // 2 surrogate values
-   *
-   * To get a list of strings containing the individual runes of a string,
-   * you should not use split. You can instead map each rune to a string
-   * as follows:
-   *
-   *     string.runes.map((rune) => new String.fromCharCode(rune)).toList();
-   */
+  /// Splits the string at matches of [pattern] and returns a list of substrings.
+  ///
+  /// Finds all the matches of `pattern` in this string,
+  /// and returns the list of the substrings between the matches.
+  /// ```dart
+  /// var string = "Hello world!";
+  /// string.split(" ");                      // ['Hello', 'world!'];
+  /// ```
+  /// Empty matches at the beginning and end of the strings are ignored,
+  /// and so are empty matches right after another match.
+  /// ```dart
+  /// var string = "abba";
+  /// // Matches:   ^^ ^^
+  /// string.split(RegExp(r"b*"));        // ['a', 'a']
+  ///                                         // not ['', 'a', 'a', '']
+  ///                                         // not ['a', '', 'a']
+  /// ```
+  /// If this string is empty, the result is an empty list if `pattern` matches
+  /// the empty string, and it is `[""]` if the pattern doesn't match.
+  /// ```dart
+  /// var string = '';
+  /// string.split('');                       // []
+  /// string.split("a");                      // ['']
+  /// ```
+  /// Splitting with an empty pattern splits the string into single-code unit
+  /// strings.
+  /// ```dart
+  /// var string = 'Pub';
+  /// string.split('');                       // ['P', 'u', 'b']
+  ///
+  /// string.codeUnits.map((unit) {
+  ///   return String.fromCharCode(unit);
+  /// }).toList();                            // ['P', 'u', 'b']
+  /// ```
+  /// Splitting happens at UTF-16 code unit boundaries,
+  /// and not at rune boundaries:
+  /// ```dart
+  /// // String made up of two code units, but one rune.
+  /// string = '\u{1D11E}';
+  /// string.split('').length;                 // 2 surrogate values
+  /// ```
+  /// To get a list of strings containing the individual runes of a string,
+  /// you should not use split. You can instead map each rune to a string
+  /// as follows:
+  /// ```dart
+  /// string.runes.map((rune) => String.fromCharCode(rune)).toList();
+  /// ```
   List<String> split(Pattern pattern);
 
-  /**
-   * Splits the string, converts its parts, and combines them into a new
-   * string.
-   *
-   * [pattern] is used to split the string into parts and separating matches.
-   *
-   * Each match is converted to a string by calling [onMatch]. If [onMatch]
-   * is omitted, the matched string is used.
-   *
-   * Each non-matched part is converted by a call to [onNonMatch]. If
-   * [onNonMatch] is omitted, the non-matching part is used.
-   *
-   * Then all the converted parts are combined into the resulting string.
-   *
-   *     'Eats shoots leaves'.splitMapJoin((new RegExp(r'shoots')),
-   *         onMatch:    (m) => '${m.group(0)}',
-   *         onNonMatch: (n) => '*'); // *shoots*
-   */
+  /// Splits the string, converts its parts, and combines them into a new
+  /// string.
+  ///
+  /// The [pattern] is used to split the string
+  /// into parts and separating matches.
+  ///
+  /// Each match is converted to a string by calling [onMatch]. If [onMatch]
+  /// is omitted, the matched substring is used.
+  ///
+  /// Each non-matched part is converted by a call to [onNonMatch]. If
+  /// [onNonMatch] is omitted, the non-matching substring is used.
+  ///
+  /// Then all the converted parts are combined into the resulting string.
+  /// ```dart
+  /// 'Eats shoots leaves'.splitMapJoin((RegExp(r'shoots')),
+  ///     onMatch:    (m) => '${m[0]!}',  // or no onMatch at all
+  ///     onNonMatch: (n) => '*'); // *shoots*
+  /// ```
   String splitMapJoin(Pattern pattern,
       {String Function(Match)? onMatch, String Function(String)? onNonMatch});
 
-  /**
-   * Returns an unmodifiable list of the UTF-16 code units of this string.
-   */
+  /// An unmodifiable list of the UTF-16 code units of this string.
   List<int> get codeUnits;
 
-  /**
-   * Returns an [Iterable] of Unicode code-points of this string.
-   *
-   * If the string contains surrogate pairs, they are combined and returned
-   * as one integer by this iterator. Unmatched surrogate halves are treated
-   * like valid 16-bit code-units.
-   */
+  /// An [Iterable] of Unicode code-points of this string.
+  ///
+  /// If the string contains surrogate pairs, they are combined and returned
+  /// as one integer by this iterator. Unmatched surrogate halves are treated
+  /// like valid 16-bit code-units.
   Runes get runes;
 
-  /**
-   * Converts all characters in this string to lower case.
-   * If the string is already in all lower case, this method returns `this`.
-   *
-   *     'ALPHABET'.toLowerCase(); // 'alphabet'
-   *     'abc'.toLowerCase();      // 'abc'
-   *
-   * This function uses the language independent Unicode mapping and thus only
-   * works in some languages.
-   */
+  /// Converts all characters in this string to lower case.
+  ///
+  /// If the string is already in all lower case, this method returns `this`.
+  /// ```dart
+  /// 'ALPHABET'.toLowerCase(); // 'alphabet'
+  /// 'abc'.toLowerCase();      // 'abc'
+  /// ```
+  /// This function uses the language independent Unicode mapping and thus only
+  /// works in some languages.
   // TODO(floitsch): document better. (See EcmaScript for description).
   String toLowerCase();
 
-  /**
-   * Converts all characters in this string to upper case.
-   * If the string is already in all upper case, this method returns `this`.
-   *
-   *     'alphabet'.toUpperCase(); // 'ALPHABET'
-   *     'ABC'.toUpperCase();      // 'ABC'
-   *
-   * This function uses the language independent Unicode mapping and thus only
-   * works in some languages.
-   */
+  /// Converts all characters in this string to upper case.
+  ///
+  /// If the string is already in all upper case, this method returns `this`.
+  /// ```dart
+  /// 'alphabet'.toUpperCase(); // 'ALPHABET'
+  /// 'ABC'.toUpperCase();      // 'ABC'
+  /// ```
+  /// This function uses the language independent Unicode mapping and thus only
+  /// works in some languages.
   // TODO(floitsch): document better. (See EcmaScript for description).
   String toUpperCase();
 }
 
-/**
- * The runes (integer Unicode code points) of a [String].
- */
+/// The runes (integer Unicode code points) of a [String].
 class Runes extends Iterable<int> {
+  /// The string that this is the runes of.
   final String string;
+
+  /// Creates a [Runes] iterator for [string].
   Runes(this.string);
 
   RuneIterator get iterator => RuneIterator(string);
@@ -672,40 +627,37 @@
   return 0x10000 + ((start & 0x3FF) << 10) + (end & 0x3FF);
 }
 
-/**
- * [Iterator] for reading runes (integer Unicode code points) of a Dart string.
- */
+/// [Iterator] for reading runes (integer Unicode code points) of a Dart string.
 class RuneIterator implements BidirectionalIterator<int> {
-  /** String being iterated. */
+  /// String being iterated.
   final String string;
-  /** Position before the current code point. */
+
+  /// Position before the current code point.
   int _position;
-  /** Position after the current code point. */
+
+  /// Position after the current code point.
   int _nextPosition;
-  /**
-   * Current code point.
-   *
-   * If the iterator has hit either end, the [_currentCodePoint] is -1
-   * and `_position == _nextPosition`.
-   */
+
+  /// Current code point.
+  ///
+  /// If the iterator has hit either end, the [_currentCodePoint] is -1
+  /// and `_position == _nextPosition`.
   int _currentCodePoint = -1;
 
-  /** Create an iterator positioned at the beginning of the string. */
+  /// Create an iterator positioned at the beginning of the string.
   RuneIterator(String string)
       : this.string = string,
         _position = 0,
         _nextPosition = 0;
 
-  /**
-   * Create an iterator positioned before the [index]th code unit of the string.
-   *
-   * When created, there is no [current] value.
-   * A [moveNext] will use the rune starting at [index] the current value,
-   * and a [movePrevious] will use the rune ending just before [index] as the
-   * the current value.
-   *
-   * The [index] position must not be in the middle of a surrogate pair.
-   */
+  /// Create an iterator positioned before the [index]th code unit of the string.
+  ///
+  /// When created, there is no [current] value.
+  /// A [moveNext] will use the rune starting at [index] the current value,
+  /// and a [movePrevious] will use the rune ending just before [index] as the
+  /// the current value.
+  ///
+  /// The [index] position must not be in the middle of a surrogate pair.
   RuneIterator.at(String string, int index)
       : string = string,
         _position = index,
@@ -714,7 +666,7 @@
     _checkSplitSurrogate(index);
   }
 
-  /** Throw an error if the index is in the middle of a surrogate pair. */
+  /// Throw an error if the index is in the middle of a surrogate pair.
   void _checkSplitSurrogate(int index) {
     if (index > 0 &&
         index < string.length &&
@@ -724,40 +676,34 @@
     }
   }
 
-  /**
-   * The starting position of the current rune in the string.
-   *
-   * Returns -1 if there is no current rune ([current] is -1).
-   */
+  /// The starting position of the current rune in the string.
+  ///
+  /// Returns -1 if there is no current rune ([current] is -1).
   int get rawIndex => (_position != _nextPosition) ? _position : -1;
 
-  /**
-   * Resets the iterator to the rune at the specified index of the string.
-   *
-   * Setting a negative [rawIndex], or one greater than or equal to
-   * `string.length`, is an error. So is setting it in the middle of a surrogate
-   *  pair.
-   *
-   * Setting the position to the end of then string means that there is no
-   * current rune.
-   */
+  /// Resets the iterator to the rune at the specified index of the string.
+  ///
+  /// Setting a negative [rawIndex], or one greater than or equal to
+  /// `string.length`, is an error. So is setting it in the middle of a surrogate
+  ///  pair.
+  ///
+  /// Setting the position to the end of the string means that there is no
+  /// current rune.
   void set rawIndex(int rawIndex) {
     RangeError.checkValidIndex(rawIndex, string, "rawIndex");
     reset(rawIndex);
     moveNext();
   }
 
-  /**
-   * Resets the iterator to the given index into the string.
-   *
-   * After this the [current] value is unset.
-   * You must call [moveNext] make the rune at the position current,
-   * or [movePrevious] for the last rune before the position.
-   *
-   * The [rawIndex] must be non-negative and no greater than `string.length`.
-   * It must also not be the index of the trailing surrogate of a surrogate
-   * pair.
-   */
+  /// Resets the iterator to the given index into the string.
+  ///
+  /// After this the [current] value is unset.
+  /// You must call [moveNext] make the rune at the position current,
+  /// or [movePrevious] for the last rune before the position.
+  ///
+  /// The [rawIndex] must be non-negative and no greater than `string.length`.
+  /// It must also not be the index of the trailing surrogate of a surrogate
+  /// pair.
   void reset([int rawIndex = 0]) {
     RangeError.checkValueInInterval(rawIndex, 0, string.length, "rawIndex");
     _checkSplitSurrogate(rawIndex);
@@ -765,29 +711,23 @@
     _currentCodePoint = -1;
   }
 
-  /**
-   * The rune (integer Unicode code point) starting at the current position in
-   * the string.
-   *
-   * The value is -1 if there is no current code point.
-   */
+  /// The rune (integer Unicode code point) starting at the current position in
+  /// the string.
+  ///
+  /// The value is -1 if there is no current code point.
   int get current => _currentCodePoint;
 
-  /**
-   * The number of code units comprising the current rune.
-   *
-   * Returns zero if there is no current rune ([current] is -1).
-   */
+  /// The number of code units comprising the current rune.
+  ///
+  /// Returns zero if there is no current rune ([current] is -1).
   int get currentSize => _nextPosition - _position;
 
-  /**
-   * A string containing the current rune.
-   *
-   * For runes outside the basic multilingual plane, this will be
-   * a String of length 2, containing two code units.
-   *
-   * Returns an empty string if there is no [current] value.
-   */
+  /// A string containing the current rune.
+  ///
+  /// For runes outside the basic multilingual plane, this will be
+  /// a String of length 2, containing two code units.
+  ///
+  /// Returns an empty string if there is no [current] value.
   String get currentAsString {
     if (_position == _nextPosition) return "";
     if (_position + 1 == _nextPosition) return string[_position];
diff --git a/sdk/lib/core/string_buffer.dart b/sdk/lib/core/string_buffer.dart
index d664101..6826e06 100644
--- a/sdk/lib/core/string_buffer.dart
+++ b/sdk/lib/core/string_buffer.dart
@@ -4,47 +4,45 @@
 
 part of dart.core;
 
-/**
- * A class for concatenating strings efficiently.
- *
- * Allows for the incremental building of a string using write*() methods.
- * The strings are concatenated to a single string only when [toString] is
- * called.
- */
+/// A class for concatenating strings efficiently.
+///
+/// Allows for the incremental building of a string using `write*()` methods.
+/// The strings are concatenated to a single string only when [toString] is
+/// called.
 class StringBuffer implements StringSink {
-  /** Creates the string buffer with an initial content. */
+  /// Creates the string buffer with an initial content.
   external StringBuffer([Object content = ""]);
 
-  /**
-   * Returns the length of the content that has been accumulated so far.
-   * This is a constant-time operation.
-   */
+  /// Returns the length of the content that has been accumulated so far.
+  /// This is a constant-time operation.
   external int get length;
 
-  /** Returns whether the buffer is empty. This is a constant-time operation. */
+  /// Returns whether the buffer is empty. This is a constant-time operation.
   bool get isEmpty => length == 0;
 
-  /**
-   * Returns whether the buffer is not empty. This is a constant-time
-   * operation.
-   */
+  /// Returns whether the buffer is not empty. This is a constant-time
+  /// operation.
   bool get isNotEmpty => !isEmpty;
 
-  /// Adds the contents of [obj], converted to a string, to the buffer.
-  external void write(Object? obj);
+  /// Adds the string representatoon of [object] to the buffer.
+  external void write(Object? object);
 
   /// Adds the string representation of [charCode] to the buffer.
+  ///
+  /// Equivalent to `write(String.fromCharCode(charCode))`.
   external void writeCharCode(int charCode);
 
+  /// Writes all [objects] separated by [separator].
+  ///
+  /// Writes each individual object in [objects] in iteration order,
+  /// and writes [separtor] between any two objects.
   external void writeAll(Iterable<dynamic> objects, [String separator = ""]);
 
   external void writeln([Object? obj = ""]);
 
-  /**
-   * Clears the string buffer.
-   */
+  /// Clears the string buffer.
   external void clear();
 
-  /// Returns the contents of buffer as a concatenated string.
+  /// Returns the contents of buffer as a single string.
   external String toString();
 }
diff --git a/sdk/lib/core/string_sink.dart b/sdk/lib/core/string_sink.dart
index c507424..565ce56 100644
--- a/sdk/lib/core/string_sink.dart
+++ b/sdk/lib/core/string_sink.dart
@@ -5,27 +5,22 @@
 part of dart.core;
 
 abstract class StringSink {
-  /**
-   * Converts [obj] to a String by invoking [Object.toString] and
-   * adds the result to `this`.
-   */
-  void write(Object? obj);
+  /// Writes the string representation of [object].
+  ///
+  /// Converts [object] to a string using `object.toString()`.
+  void write(Object? object);
 
-  /**
-   * Iterates over the given [objects] and [write]s them in sequence.
-   */
+  /// Iterates over the given [objects] and [write]s them in sequence.
   void writeAll(Iterable<dynamic> objects, [String separator = ""]);
 
-  /**
-   * Converts [obj] to a String by invoking [Object.toString] and
-   * adds the result to `this`, followed by a newline.
-   */
-  void writeln([Object? obj = ""]);
+  /// Writes [object] followed by a newline, `"\n"`.
+  ///
+  /// Calling `writeln(null)` will write the `"null"` string before the
+  /// newline.
+  void writeln([Object? object = ""]);
 
-  /**
-   * Writes the [charCode] to `this`.
-   *
-   * This method is equivalent to `write(new String.fromCharCode(charCode))`.
-   */
+  /// Writes the character represented by [charCode].
+  ///
+  /// Equivalent to `write(String.fromCharCode(charCode))`.
   void writeCharCode(int charCode);
 }
diff --git a/sdk/lib/core/symbol.dart b/sdk/lib/core/symbol.dart
index d64890a..d9e2540 100644
--- a/sdk/lib/core/symbol.dart
+++ b/sdk/lib/core/symbol.dart
@@ -6,92 +6,84 @@
 
 /// Opaque name used by mirrors, invocations and [Function.apply].
 abstract class Symbol {
-  /** The symbol corresponding to the name of the unary minus operator. */
+  /// The symbol corresponding to the name of the unary minus operator.
   static const Symbol unaryMinus = Symbol("unary-");
 
-  /**
-   * The empty symbol.
-   *
-   * The empty symbol is the name of libraries with no library declaration,
-   * and the base-name of the unnamed constructor.
-   */
+  /// The empty symbol.
+  ///
+  /// The empty symbol is the name of libraries with no library declaration,
+  /// and the base-name of the unnamed constructor.
   static const Symbol empty = Symbol("");
 
-  /**
-   * Constructs a new [Symbol] representing the provided name.
-   *
-   * The name must be a valid public Dart member name,
-   * public constructor name, or library name, optionally qualified.
-   *
-   * A qualified name is a valid name preceded by a public identifier name
-   * and a '`.`', e.g., `foo.bar.baz=` is a qualified version of `baz=`.
-   * That means that the content of the [name] String must be either
-   *
-   * * a valid public Dart identifier
-   *   (that is, an identifier not starting with "`_`"),
-   * * such an identifier followed by "=" (a setter name),
-   * * the name of a declarable operator
-   *   (one of "`+`", "`-`", "`*`", "`/`", "`%`", "`~/`", "`&`", "`|`",
-   *   "`^`", "`~`", "`<<`", "`>>`", "`<`", "`<=`", "`>`", "`>=`", "`==`",
-   *   "`[]`", "`[]=`", or "`unary-`"),
-   * * any of the above preceded by any number of qualifiers,
-   *   where a qualifier is a non-private identifier followed by '`.`',
-   * * or the empty string (the default name of a library with no library
-   *   name declaration).
-   *
-   * Symbol instances created from the same [name] are equal,
-   * but not necessarily identical, but symbols created as compile-time
-   * constants are canonicalized, as all other constant object creations.
-   *
-   * ```dart
-   * assert(new Symbol("foo") == new Symbol("foo"));
-   * assert(identical(const Symbol("foo"), const Symbol("foo")));
-   * ```
-   *
-   * If [name] is a single identifier that does not start with an underscore,
-   * or it is a qualified identifier,
-   * or it is an operator name different from `unary-`,
-   * then the result of `const Symbol(name)` is the same instance that
-   * the symbol literal created by prefixing `#` to the content of [name]
-   * would evaluate to.
-   *
-   * ```dart
-   * assert(new Symbol("foo") == #foo);
-   * assert(new Symbol("[]=") == #[]=]);
-   * assert(new Symbol("foo.bar") == #foo.bar);
-   * assert(identical(const Symbol("foo"), #foo));
-   * assert(identical(const Symbol("[]="), #[]=));
-   * assert(identical(const Symbol("foo.bar"), #foo.bar));
-   * ```
-   *
-   * This constructor cannot create a [Symbol] instance that is equal to
-   * a private symbol literal like `#_foo`.
-   * ```dart
-   * const Symbol("_foo") // Invalid
-   * ```
-   *
-   * The created instance overrides [Object.==].
-   *
-   * The following text is non-normative:
-   *
-   * Creating non-const Symbol instances may result in larger output.  If
-   * possible, use `MirrorsUsed` from "dart:mirrors" to specify which names
-   * might be passed to this constructor.
-   */
+  /// Constructs a new [Symbol] representing the provided name.
+  ///
+  /// The name must be a valid public Dart member name,
+  /// public constructor name, or library name, optionally qualified.
+  ///
+  /// A qualified name is a valid name preceded by a public identifier name
+  /// and a '`.`', e.g., `foo.bar.baz=` is a qualified version of `baz=`.
+  /// That means that the content of the [name] String must be either
+  ///
+  /// * a valid public Dart identifier
+  ///   (that is, an identifier not starting with "`_`"),
+  /// * such an identifier followed by "=" (a setter name),
+  /// * the name of a declarable operator
+  ///   (one of "`+`", "`-`", "`*`", "`/`", "`%`", "`~/`", "`&`", "`|`",
+  ///   "`^`", "`~`", "`<<`", "`>>`", "`<`", "`<=`", "`>`", "`>=`", "`==`",
+  ///   "`[]`", "`[]=`", or "`unary-`"),
+  /// * any of the above preceded by any number of qualifiers,
+  ///   where a qualifier is a non-private identifier followed by '`.`',
+  /// * or the empty string (the default name of a library with no library
+  ///   name declaration).
+  ///
+  /// Symbol instances created from the same [name] are equal,
+  /// but not necessarily identical, but symbols created as compile-time
+  /// constants are canonicalized, as all other constant object creations.
+  ///
+  /// ```dart
+  /// assert(Symbol("foo") == Symbol("foo"));
+  /// assert(identical(const Symbol("foo"), const Symbol("foo")));
+  /// ```
+  ///
+  /// If [name] is a single identifier that does not start with an underscore,
+  /// or it is a qualified identifier,
+  /// or it is an operator name different from `unary-`,
+  /// then the result of `const Symbol(name)` is the same instance that
+  /// the symbol literal created by prefixing `#` to the content of [name]
+  /// would evaluate to.
+  ///
+  /// ```dart
+  /// assert(Symbol("foo") == #foo);
+  /// assert(Symbol("[]=") == #[]=]);
+  /// assert(Symbol("foo.bar") == #foo.bar);
+  /// assert(identical(const Symbol("foo"), #foo));
+  /// assert(identical(const Symbol("[]="), #[]=));
+  /// assert(identical(const Symbol("foo.bar"), #foo.bar));
+  /// ```
+  ///
+  /// This constructor cannot create a [Symbol] instance that is equal to
+  /// a private symbol literal like `#_foo`.
+  /// ```dart
+  /// const Symbol("_foo") // Invalid
+  /// ```
+  ///
+  /// The created instance overrides [Object.==].
+  ///
+  /// The following text is non-normative:
+  ///
+  /// Creating non-const Symbol instances may result in larger output.  If
+  /// possible, use `MirrorsUsed` from "dart:mirrors" to specify which names
+  /// might be passed to this constructor.
   const factory Symbol(String name) = internal.Symbol;
 
-  /**
-   * Returns a hash code compatible with [operator==].
-   *
-   * Equal symbols have the same hash code.
-   */
+  /// Returns a hash code compatible with [operator==].
+  ///
+  /// Equal symbols have the same hash code.
   int get hashCode;
 
-  /**
-   * Symbols are equal to other symbols that correspond to the same member name.
-   *
-   * Qualified member names, like `#foo.bar` are equal only if they have the
-   * same identifiers before the same final member name.
-   */
+  /// Symbols are equal to other symbols that correspond to the same member name.
+  ///
+  /// Qualified member names, like `#foo.bar` are equal only if they have the
+  /// same identifiers before the same final member name.
   bool operator ==(Object other);
 }
diff --git a/sdk/lib/core/type.dart b/sdk/lib/core/type.dart
index 65cef39..ebb9a5b 100644
--- a/sdk/lib/core/type.dart
+++ b/sdk/lib/core/type.dart
@@ -4,55 +4,47 @@
 
 part of dart.core;
 
-/**
- * Runtime representation of a type.
- *
- * Type objects represent types.
- * A type object can be created in several ways:
- * * By a *type literal*, a type name occurring as an expression,
- *   like `Type type = int;`,
- *   or a type variable occurring as an expression, like `Type type = T;`.
- * * By reading the run-time type of an object,
- *   like `Type type = o.runtimeType;`.
- * * Through `dart:mirrors`.
- *
- * A type object is intended as an entry point for using `dart:mirrors`.
- * The only operations supported are comparing to other type objects
- * for equality, and converting it to a string for debugging.
- */
+/// Runtime representation of a type.
+///
+/// Type objects represent types.
+/// A type object can be created in several ways:
+/// * By a *type literal*, a type name occurring as an expression,
+///   like `Type type = int;`,
+///   or a type variable occurring as an expression, like `Type type = T;`.
+/// * By reading the run-time type of an object,
+///   like `Type type = o.runtimeType;`.
+/// * Through `dart:mirrors`.
+///
+/// A type object is intended as an entry point for using `dart:mirrors`.
+/// The only operations supported are comparing to other type objects
+/// for equality, and converting it to a string for debugging.
 abstract class Type {
-  /**
-   * A hash code for the type which is compatible with [operator==].
-   */
+  /// A hash code for the type which is compatible with [operator==].
   int get hashCode;
 
-  /**
-   * Whether [other] is a [Type] instance representing an equivalent type.
-   *
-   * The language specification dictates which types are considered
-   * to be the equivalent.
-   * If two types are equivalent, it's guaranteed that they are subtypes
-   * of each other,
-   * but there are also types which are subtypes of each other,
-   * and which are not equivalent (for example `dynamic` and `void`,
-   * or `FutureOr<Object>` and `Object`).
-   */
+  /// Whether [other] is a [Type] instance representing an equivalent type.
+  ///
+  /// The language specification dictates which types are considered
+  /// to be the equivalent.
+  /// If two types are equivalent, it's guaranteed that they are subtypes
+  /// of each other,
+  /// but there are also types which are subtypes of each other,
+  /// and which are not equivalent (for example `dynamic` and `void`,
+  /// or `FutureOr<Object>` and `Object`).
   bool operator ==(Object other);
 
-  /**
-   * Returns a string which represents the underlying type.
-   *
-   * The string is only intended for providing information to a reader
-   * while debugging.
-   * There is no guaranteed format,
-   * the string value returned for a [Type] instances is entirely
-   * implementation dependent.
-   *
-   * The string should be consistent, so a `Type` object for the *same* type
-   * returns the same string throughout a program execution.
-   * The string may or may not contain parts corresponding to the
-   * source name of declaration of the type, if the type has a source name
-   * at all (some types reachable through `dart:mirrors` may not).
-   */
+  /// Returns a string which represents the underlying type.
+  ///
+  /// The string is only intended for providing information to a reader
+  /// while debugging.
+  /// There is no guaranteed format,
+  /// the string value returned for a [Type] instances is entirely
+  /// implementation dependent.
+  ///
+  /// The string should be consistent, so a `Type` object for the *same* type
+  /// returns the same string throughout a program execution.
+  /// The string may or may not contain parts corresponding to the
+  /// source name of declaration of the type, if the type has a source name
+  /// at all (some types reachable through `dart:mirrors` may not).
   String toString();
 }
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index 143ad63..5bae256 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -24,100 +24,94 @@
 
 const String _hexDigits = "0123456789ABCDEF";
 
-/**
- * A parsed URI, such as a URL.
- *
- * **See also:**
- *
- * * [URIs][uris] in the [library tour][libtour]
- * * [RFC-3986](http://tools.ietf.org/html/rfc3986)
- *
- * [uris]: https://dart.dev/guides/libraries/library-tour#uris
- * [libtour]: https://dart.dev/guides/libraries/library-tour
- */
+/// A parsed URI, such as a URL.
+///
+/// **See also:**
+///
+/// * [URIs][uris] in the [library tour][libtour]
+/// * [RFC-3986](http://tools.ietf.org/html/rfc3986)
+///
+/// [uris]: https://dart.dev/guides/libraries/library-tour#uris
+/// [libtour]: https://dart.dev/guides/libraries/library-tour
 abstract class Uri {
-  /**
-   * Returns the natural base URI for the current platform.
-   *
-   * When running in a browser this is the current URL of the current page
-   * (from `window.location.href`).
-   *
-   * When not running in a browser this is the file URI referencing
-   * the current working directory.
-   */
+  /// The natural base URI for the current platform.
+  ///
+  /// When running in a browser this is the current URL of the current page
+  /// (from `window.location.href`).
+  ///
+  /// When not running in a browser this is the file URI referencing
+  /// the current working directory.
   external static Uri get base;
 
-  /**
-   * Creates a new URI from its components.
-   *
-   * Each component is set through a named argument. Any number of
-   * components can be provided. The [path] and [query] components can be set
-   * using either of two different named arguments.
-   *
-   * The scheme component is set through [scheme]. The scheme is
-   * normalized to all lowercase letters. If the scheme is omitted or empty,
-   * the URI will not have a scheme part.
-   *
-   * The user info part of the authority component is set through
-   * [userInfo]. It defaults to the empty string, which will be omitted
-   * from the string representation of the URI.
-   *
-   * The host part of the authority component is set through
-   * [host]. The host can either be a hostname, an IPv4 address or an
-   * IPv6 address, contained in '[' and ']'. If the host contains a
-   * ':' character, the '[' and ']' are added if not already provided.
-   * The host is normalized to all lowercase letters.
-   *
-   * The port part of the authority component is set through
-   * [port].
-   * If [port] is omitted or `null`, it implies the default port for
-   * the URI's scheme, and is equivalent to passing that port explicitly.
-   * The recognized schemes, and their default ports, are "http" (80) and
-   * "https" (443). All other schemes are considered as having zero as the
-   * default port.
-   *
-   * If any of `userInfo`, `host` or `port` are provided,
-   * the URI has an authority according to [hasAuthority].
-   *
-   * The path component is set through either [path] or
-   * [pathSegments].
-   * When [path] is used, it should be a valid URI path,
-   * but invalid characters, except the general delimiters ':/@[]?#',
-   * will be escaped if necessary.
-   * When [pathSegments] is used, each of the provided segments
-   * is first percent-encoded and then joined using the forward slash
-   * separator.
-   *
-   * The percent-encoding of the path segments encodes all
-   * characters except for the unreserved characters and the following
-   * list of characters: `!$&'()*+,;=:@`. If the other components
-   * necessitate an absolute path, a leading slash `/` is prepended if
-   * not already there.
-   *
-   * The query component is set through either [query] or [queryParameters].
-   * When [query] is used, the provided string should be a valid URI query,
-   * but invalid characters, other than general delimiters,
-   * will be escaped if necessary.
-   * When [queryParameters] is used the query is built from the
-   * provided map. Each key and value in the map is percent-encoded
-   * and joined using equal and ampersand characters.
-   * A value in the map must be either a string, or an [Iterable] of strings,
-   * where the latter corresponds to multiple values for the same key.
-   *
-   * The percent-encoding of the keys and values encodes all characters
-   * except for the unreserved characters, and replaces spaces with `+`.
-   * If `query` is the empty string, it is equivalent to omitting it.
-   * To have an actual empty query part,
-   * use an empty map for `queryParameters`.
-   *
-   * If both `query` and `queryParameters` are omitted or `null`,
-   * the URI has no query part.
-   *
-   * The fragment component is set through [fragment].
-   * It should be a valid URI fragment, but invalid characters other than
-   * general delimiters, are escaped if necessary.
-   * If `fragment` is omitted or `null`, the URI has no fragment part.
-   */
+  /// Creates a new URI from its components.
+  ///
+  /// Each component is set through a named argument. Any number of
+  /// components can be provided. The [path] and [query] components can be set
+  /// using either of two different named arguments.
+  ///
+  /// The scheme component is set through [scheme]. The scheme is
+  /// normalized to all lowercase letters. If the scheme is omitted or empty,
+  /// the URI will not have a scheme part.
+  ///
+  /// The user info part of the authority component is set through
+  /// [userInfo]. It defaults to the empty string, which will be omitted
+  /// from the string representation of the URI.
+  ///
+  /// The host part of the authority component is set through
+  /// [host]. The host can either be a hostname, an IPv4 address or an
+  /// IPv6 address, contained in '[' and ']'. If the host contains a
+  /// ':' character, the '[' and ']' are added if not already provided.
+  /// The host is normalized to all lowercase letters.
+  ///
+  /// The port part of the authority component is set through
+  /// [port].
+  /// If [port] is omitted or `null`, it implies the default port for
+  /// the URI's scheme, and is equivalent to passing that port explicitly.
+  /// The recognized schemes, and their default ports, are "http" (80) and
+  /// "https" (443). All other schemes are considered as having zero as the
+  /// default port.
+  ///
+  /// If any of `userInfo`, `host` or `port` are provided,
+  /// the URI has an authority according to [hasAuthority].
+  ///
+  /// The path component is set through either [path] or
+  /// [pathSegments].
+  /// When [path] is used, it should be a valid URI path,
+  /// but invalid characters, except the general delimiters ':/@[]?#',
+  /// will be escaped if necessary.
+  /// When [pathSegments] is used, each of the provided segments
+  /// is first percent-encoded and then joined using the forward slash
+  /// separator.
+  ///
+  /// The percent-encoding of the path segments encodes all
+  /// characters except for the unreserved characters and the following
+  /// list of characters: `!$&'()*+,;=:@`. If the other components
+  /// necessitate an absolute path, a leading slash `/` is prepended if
+  /// not already there.
+  ///
+  /// The query component is set through either [query] or [queryParameters].
+  /// When [query] is used, the provided string should be a valid URI query,
+  /// but invalid characters, other than general delimiters,
+  /// will be escaped if necessary.
+  /// When [queryParameters] is used the query is built from the
+  /// provided map. Each key and value in the map is percent-encoded
+  /// and joined using equal and ampersand characters.
+  /// A value in the map must be either a string, or an [Iterable] of strings,
+  /// where the latter corresponds to multiple values for the same key.
+  ///
+  /// The percent-encoding of the keys and values encodes all characters
+  /// except for the unreserved characters, and replaces spaces with `+`.
+  /// If `query` is the empty string, it is equivalent to omitting it.
+  /// To have an actual empty query part,
+  /// use an empty map for `queryParameters`.
+  ///
+  /// If both `query` and `queryParameters` are omitted or `null`,
+  /// the URI has no query part.
+  ///
+  /// The fragment component is set through [fragment].
+  /// It should be a valid URI fragment, but invalid characters other than
+  /// general delimiters, are escaped if necessary.
+  /// If `fragment` is omitted or `null`, the URI has no fragment part.
   factory Uri(
       {String? scheme,
       String? userInfo,
@@ -129,173 +123,163 @@
       Map<String, dynamic /*String|Iterable<String>*/ >? queryParameters,
       String? fragment}) = _Uri;
 
-  /**
-   * Creates a new `http` URI from authority, path and query.
-   *
-   * Examples:
-   *
-   * ```
-   * // http://example.org/path?q=dart.
-   * new Uri.http("example.org", "/path", { "q" : "dart" });
-   *
-   * // http://user:pass@localhost:8080
-   * new Uri.http("user:pass@localhost:8080", "");
-   *
-   * // http://example.org/a%20b
-   * new Uri.http("example.org", "a b");
-   *
-   * // http://example.org/a%252F
-   * new Uri.http("example.org", "/a%2F");
-   * ```
-   *
-   * The `scheme` is always set to `http`.
-   *
-   * The `userInfo`, `host` and `port` components are set from the
-   * [authority] argument. If `authority` is `null` or empty,
-   * the created `Uri` has no authority, and isn't directly usable
-   * as an HTTP URL, which must have a non-empty host.
-   *
-   * The `path` component is set from the [unencodedPath]
-   * argument. The path passed must not be encoded as this constructor
-   * encodes the path.
-   *
-   * The `query` component is set from the optional [queryParameters]
-   * argument.
-   */
+  /// Creates a new `http` URI from authority, path and query.
+  ///
+  /// Examples:
+  ///
+  /// ```
+  /// // http://example.org/path?q=dart.
+  /// Uri.http("example.org", "/path", { "q" : "dart" });
+  ///
+  /// // http://user:pass@localhost:8080
+  /// Uri.http("user:pass@localhost:8080", "");
+  ///
+  /// // http://example.org/a%20b
+  /// Uri.http("example.org", "a b");
+  ///
+  /// // http://example.org/a%252F
+  /// Uri.http("example.org", "/a%2F");
+  /// ```
+  ///
+  /// The `scheme` is always set to `http`.
+  ///
+  /// The `userInfo`, `host` and `port` components are set from the
+  /// [authority] argument. If `authority` is `null` or empty,
+  /// the created `Uri` has no authority, and isn't directly usable
+  /// as an HTTP URL, which must have a non-empty host.
+  ///
+  /// The `path` component is set from the [unencodedPath]
+  /// argument. The path passed must not be encoded as this constructor
+  /// encodes the path.
+  ///
+  /// The `query` component is set from the optional [queryParameters]
+  /// argument.
   factory Uri.http(String authority, String unencodedPath,
-      [Map<String, String>? queryParameters]) = _Uri.http;
+      [Map<String, dynamic>? queryParameters]) = _Uri.http;
 
-  /**
-   * Creates a new `https` URI from authority, path and query.
-   *
-   * This constructor is the same as [Uri.http] except for the scheme
-   * which is set to `https`.
-   */
+  /// Creates a new `https` URI from authority, path and query.
+  ///
+  /// This constructor is the same as [Uri.http] except for the scheme
+  /// which is set to `https`.
   factory Uri.https(String authority, String unencodedPath,
-      [Map<String, String>? queryParameters]) = _Uri.https;
+      [Map<String, dynamic>? queryParameters]) = _Uri.https;
 
-  /**
-   * Creates a new file URI from an absolute or relative file path.
-   *
-   * The file path is passed in [path].
-   *
-   * This path is interpreted using either Windows or non-Windows
-   * semantics.
-   *
-   * With non-Windows semantics the slash (`/`) is used to separate
-   * path segments in the input [path].
-   *
-   * With Windows semantics, backslash (`\`) and forward-slash (`/`)
-   * are used to separate path segments in the input [path],
-   * except if the path starts with `\\?\` in which case
-   * only backslash (`\`) separates path segments in [path].
-   *
-   * If the path starts with a path separator, an absolute URI (with the
-   * `file` scheme and an empty authority) is created.
-   * Otherwise a relative URI reference with no scheme or authority is created.
-   * One exception from this rule is that when Windows semantics is used
-   * and the path starts with a drive letter followed by a colon (":") and a
-   * path separator, then an absolute URI is created.
-   *
-   * The default for whether to use Windows or non-Windows semantics
-   * determined from the platform Dart is running on. When running in
-   * the standalone VM, this is detected by the VM based on the
-   * operating system. When running in a browser non-Windows semantics
-   * is always used.
-   *
-   * To override the automatic detection of which semantics to use pass
-   * a value for [windows]. Passing `true` will use Windows
-   * semantics and passing `false` will use non-Windows semantics.
-   *
-   * Examples using non-Windows semantics:
-   *
-   * ```
-   * // xxx/yyy
-   * new Uri.file("xxx/yyy", windows: false);
-   *
-   * // xxx/yyy/
-   * new Uri.file("xxx/yyy/", windows: false);
-   *
-   * // file:///xxx/yyy
-   * new Uri.file("/xxx/yyy", windows: false);
-   *
-   * // file:///xxx/yyy/
-   * new Uri.file("/xxx/yyy/", windows: false);
-   *
-   * // C%3A
-   * new Uri.file("C:", windows: false);
-   * ```
-   *
-   * Examples using Windows semantics:
-   *
-   * ```
-   * // xxx/yyy
-   * new Uri.file(r"xxx\yyy", windows: true);
-   *
-   * // xxx/yyy/
-   * new Uri.file(r"xxx\yyy\", windows: true);
-   *
-   * file:///xxx/yyy
-   * new Uri.file(r"\xxx\yyy", windows: true);
-   *
-   * file:///xxx/yyy/
-   * new Uri.file(r"\xxx\yyy/", windows: true);
-   *
-   * // file:///C:/xxx/yyy
-   * new Uri.file(r"C:\xxx\yyy", windows: true);
-   *
-   * // This throws an error. A path with a drive letter, but no following
-   * // path, is not allowed.
-   * new Uri.file(r"C:", windows: true);
-   *
-   * // This throws an error. A path with a drive letter is not absolute.
-   * new Uri.file(r"C:xxx\yyy", windows: true);
-   *
-   * // file://server/share/file
-   * new Uri.file(r"\\server\share\file", windows: true);
-   * ```
-   *
-   * If the path passed is not a valid file path, an error is thrown.
-   */
+  /// Creates a new file URI from an absolute or relative file path.
+  ///
+  /// The file path is passed in [path].
+  ///
+  /// This path is interpreted using either Windows or non-Windows
+  /// semantics.
+  ///
+  /// With non-Windows semantics the slash (`/`) is used to separate
+  /// path segments in the input [path].
+  ///
+  /// With Windows semantics, backslash (`\`) and forward-slash (`/`)
+  /// are used to separate path segments in the input [path],
+  /// except if the path starts with `\\?\` in which case
+  /// only backslash (`\`) separates path segments in [path].
+  ///
+  /// If the path starts with a path separator, an absolute URI (with the
+  /// `file` scheme and an empty authority) is created.
+  /// Otherwise a relative URI reference with no scheme or authority is created.
+  /// One exception from this rule is that when Windows semantics is used
+  /// and the path starts with a drive letter followed by a colon (":") and a
+  /// path separator, then an absolute URI is created.
+  ///
+  /// The default for whether to use Windows or non-Windows semantics
+  /// determined from the platform Dart is running on. When running in
+  /// the standalone VM, this is detected by the VM based on the
+  /// operating system. When running in a browser non-Windows semantics
+  /// is always used.
+  ///
+  /// To override the automatic detection of which semantics to use pass
+  /// a value for [windows]. Passing `true` will use Windows
+  /// semantics and passing `false` will use non-Windows semantics.
+  ///
+  /// Examples using non-Windows semantics:
+  ///
+  /// ```
+  /// // xxx/yyy
+  /// Uri.file("xxx/yyy", windows: false);
+  ///
+  /// // xxx/yyy/
+  /// Uri.file("xxx/yyy/", windows: false);
+  ///
+  /// // file:///xxx/yyy
+  /// Uri.file("/xxx/yyy", windows: false);
+  ///
+  /// // file:///xxx/yyy/
+  /// Uri.file("/xxx/yyy/", windows: false);
+  ///
+  /// // C%3A
+  /// Uri.file("C:", windows: false);
+  /// ```
+  ///
+  /// Examples using Windows semantics:
+  ///
+  /// ```
+  /// // xxx/yyy
+  /// Uri.file(r"xxx\yyy", windows: true);
+  ///
+  /// // xxx/yyy/
+  /// Uri.file(r"xxx\yyy\", windows: true);
+  ///
+  /// file:///xxx/yyy
+  /// Uri.file(r"\xxx\yyy", windows: true);
+  ///
+  /// file:///xxx/yyy/
+  /// Uri.file(r"\xxx\yyy/", windows: true);
+  ///
+  /// // file:///C:/xxx/yyy
+  /// Uri.file(r"C:\xxx\yyy", windows: true);
+  ///
+  /// // This throws an error. A path with a drive letter, but no following
+  /// // path, is not allowed.
+  /// Uri.file(r"C:", windows: true);
+  ///
+  /// // This throws an error. A path with a drive letter is not absolute.
+  /// Uri.file(r"C:xxx\yyy", windows: true);
+  ///
+  /// // file://server/share/file
+  /// Uri.file(r"\\server\share\file", windows: true);
+  /// ```
+  ///
+  /// If the path passed is not a valid file path, an error is thrown.
   factory Uri.file(String path, {bool? windows}) = _Uri.file;
 
-  /**
-   * Like [Uri.file] except that a non-empty URI path ends in a slash.
-   *
-   * If [path] is not empty, and it doesn't end in a directory separator,
-   * then a slash is added to the returned URI's path.
-   * In all other cases, the result is the same as returned by `Uri.file`.
-   */
+  /// Like [Uri.file] except that a non-empty URI path ends in a slash.
+  ///
+  /// If [path] is not empty, and it doesn't end in a directory separator,
+  /// then a slash is added to the returned URI's path.
+  /// In all other cases, the result is the same as returned by `Uri.file`.
   factory Uri.directory(String path, {bool? windows}) = _Uri.directory;
 
-  /**
-   * Creates a `data:` URI containing the [content] string.
-   *
-   * Converts the content to a bytes using [encoding] or the charset specified
-   * in [parameters] (defaulting to US-ASCII if not specified or unrecognized),
-   * then encodes the bytes into the resulting data URI.
-   *
-   * Defaults to encoding using percent-encoding (any non-ASCII or non-URI-valid
-   * bytes is replaced by a percent encoding). If [base64] is true, the bytes
-   * are instead encoded using [base64].
-   *
-   * If [encoding] is not provided and [parameters] has a `charset` entry,
-   * that name is looked up using [Encoding.getByName],
-   * and if the lookup returns an encoding, that encoding is used to convert
-   * [content] to bytes.
-   * If providing both an [encoding] and a charset in [parameters], they should
-   * agree, otherwise decoding won't be able to use the charset parameter
-   * to determine the encoding.
-   *
-   * If [mimeType] and/or [parameters] are supplied, they are added to the
-   * created URI. If any of these contain characters that are not allowed
-   * in the data URI, the character is percent-escaped. If the character is
-   * non-ASCII, it is first UTF-8 encoded and then the bytes are percent
-   * encoded. An omitted [mimeType] in a data URI means `text/plain`, just
-   * as an omitted `charset` parameter defaults to meaning `US-ASCII`.
-   *
-   * To read the content back, use [UriData.contentAsString].
-   */
+  /// Creates a `data:` URI containing the [content] string.
+  ///
+  /// Converts the content to a bytes using [encoding] or the charset specified
+  /// in [parameters] (defaulting to US-ASCII if not specified or unrecognized),
+  /// then encodes the bytes into the resulting data URI.
+  ///
+  /// Defaults to encoding using percent-encoding (any non-ASCII or non-URI-valid
+  /// bytes is replaced by a percent encoding). If [base64] is true, the bytes
+  /// are instead encoded using [base64].
+  ///
+  /// If [encoding] is not provided and [parameters] has a `charset` entry,
+  /// that name is looked up using [Encoding.getByName],
+  /// and if the lookup returns an encoding, that encoding is used to convert
+  /// [content] to bytes.
+  /// If providing both an [encoding] and a charset in [parameters], they should
+  /// agree, otherwise decoding won't be able to use the charset parameter
+  /// to determine the encoding.
+  ///
+  /// If [mimeType] and/or [parameters] are supplied, they are added to the
+  /// created URI. If any of these contain characters that are not allowed
+  /// in the data URI, the character is percent-escaped. If the character is
+  /// non-ASCII, it is first UTF-8 encoded and then the bytes are percent
+  /// encoded. An omitted [mimeType] in a data URI means `text/plain`, just
+  /// as an omitted `charset` parameter defaults to meaning `US-ASCII`.
+  ///
+  /// To read the content back, use [UriData.contentAsString].
   factory Uri.dataFromString(String content,
       {String? mimeType,
       Encoding? encoding,
@@ -309,22 +293,20 @@
     return data.uri;
   }
 
-  /**
-   * Creates a `data:` URI containing an encoding of [bytes].
-   *
-   * Defaults to Base64 encoding the bytes, but if [percentEncoded]
-   * is `true`, the bytes will instead be percent encoded (any non-ASCII
-   * or non-valid-ASCII-character byte is replaced by a percent encoding).
-   *
-   * To read the bytes back, use [UriData.contentAsBytes].
-   *
-   * It defaults to having the mime-type `application/octet-stream`.
-   * The [mimeType] and [parameters] are added to the created URI.
-   * If any of these contain characters that are not allowed
-   * in the data URI, the character is percent-escaped. If the character is
-   * non-ASCII, it is first UTF-8 encoded and then the bytes are percent
-   * encoded.
-   */
+  /// Creates a `data:` URI containing an encoding of [bytes].
+  ///
+  /// Defaults to Base64 encoding the bytes, but if [percentEncoded]
+  /// is `true`, the bytes will instead be percent encoded (any non-ASCII
+  /// or non-valid-ASCII-character byte is replaced by a percent encoding).
+  ///
+  /// To read the bytes back, use [UriData.contentAsBytes].
+  ///
+  /// It defaults to having the mime-type `application/octet-stream`.
+  /// The [mimeType] and [parameters] are added to the created URI.
+  /// If any of these contain characters that are not allowed
+  /// in the data URI, the character is percent-escaped. If the character is
+  /// non-ASCII, it is first UTF-8 encoded and then the bytes are percent
+  /// encoded.
   factory Uri.dataFromBytes(List<int> bytes,
       {String mimeType = "application/octet-stream",
       Map<String, String>? parameters,
@@ -336,183 +318,151 @@
     return data.uri;
   }
 
-  /**
-   * The scheme component of the URI.
-   *
-   * Returns the empty string if there is no scheme component.
-   *
-   * A URI scheme is case insensitive.
-   * The returned scheme is canonicalized to lowercase letters.
-   */
+  /// The scheme component of the URI.
+  ///
+  /// The value is the empty string if there is no scheme component.
+  ///
+  /// A URI scheme is case insensitive.
+  /// The returned scheme is canonicalized to lowercase letters.
   String get scheme;
 
-  /**
-   * Returns the authority component.
-   *
-   * The authority is formatted from the [userInfo], [host] and [port]
-   * parts.
-   *
-   * Returns the empty string if there is no authority component.
-   */
+  /// The authority component.
+  ///
+  /// The authority is formatted from the [userInfo], [host] and [port]
+  /// parts.
+  ///
+  /// The valie is the empty string if there is no authority component.
   String get authority;
 
-  /**
-   * Returns the user info part of the authority component.
-   *
-   * Returns the empty string if there is no user info in the
-   * authority component.
-   */
+  /// The user info part of the authority component.
+  ///
+  /// Th value is the empty string if there is no user info in the
+  /// authority component.
   String get userInfo;
 
-  /**
-   * Returns the host part of the authority component.
-   *
-   * Returns the empty string if there is no authority component and
-   * hence no host.
-   *
-   * If the host is an IP version 6 address, the surrounding `[` and `]` is
-   * removed.
-   *
-   * The host string is case-insensitive.
-   * The returned host name is canonicalized to lower-case
-   * with upper-case percent-escapes.
-   */
+  /// The host part of the authority component.
+  ///
+  /// The value is the empty string if there is no authority component and
+  /// hence no host.
+  ///
+  /// If the host is an IP version 6 address, the surrounding `[` and `]` is
+  /// removed.
+  ///
+  /// The host string is case-insensitive.
+  /// The returned host name is canonicalized to lower-case
+  /// with upper-case percent-escapes.
   String get host;
 
-  /**
-   * Returns the port part of the authority component.
-   *
-   * Returns the default port if there is no port number in the authority
-   * component. That's 80 for http, 443 for https, and 0 for everything else.
-   */
+  /// The port part of the authority component.
+  ///
+  /// The value is the default port if there is no port number in the authority
+  /// component. That's 80 for http, 443 for https, and 0 for everything else.
   int get port;
 
-  /**
-   * Returns the path component.
-   *
-   * The returned path is encoded. To get direct access to the decoded
-   * path use [pathSegments].
-   *
-   * Returns the empty string if there is no path component.
-   */
+  /// The path component.
+  ///
+  /// The path is the actual substring of the URI representing the path,
+  /// and it is encoded where necessary. To get direct access to the decoded
+  /// path use [pathSegments].
+  ///
+  /// The path value is the empty string if there is no path component.
   String get path;
 
-  /**
-   * Returns the query component. The returned query is encoded. To get
-   * direct access to the decoded query use [queryParameters].
-   *
-   * Returns the empty string if there is no query component.
-   */
+  /// The query component.
+  ///
+  /// The value is the actual substring of the URI representing the query part,
+  /// and it is encoded where necessary.
+  /// To get direct access to the decoded query use [queryParameters].
+  ///
+  /// The value is the empty string if there is no query component.
   String get query;
 
-  /**
-   * Returns the fragment identifier component.
-   *
-   * Returns the empty string if there is no fragment identifier
-   * component.
-   */
+  /// The fragment identifier component.
+  ///
+  /// The value is the empty string if there is no fragment identifier
+  /// component.
   String get fragment;
 
-  /**
-   * Returns the URI path split into its segments. Each of the segments in the
-   * returned list have been decoded. If the path is empty the empty list will
-   * be returned. A leading slash `/` does not affect the segments returned.
-   *
-   * The returned list is unmodifiable and will throw [UnsupportedError] on any
-   * calls that would mutate it.
-   */
+  /// The URI path split into its segments.
+  ///
+  /// Each of the segments in the list have been decoded.
+  /// If the path is empty the empty list will
+  /// be returned. A leading slash `/` does not affect the segments returned.
+  ///
+  /// The list is unmodifiable and will throw [UnsupportedError] on any
+  /// calls that would mutate it.
   List<String> get pathSegments;
 
-  /**
-   * Returns the URI query split into a map according to the rules
-   * specified for FORM post in the [HTML 4.01 specification section
-   * 17.13.4](http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 "HTML 4.01 section 17.13.4").
-   * Each key and value in the returned map has been decoded.
-   * If there is no query the empty map is returned.
-   *
-   * Keys in the query string that have no value are mapped to the
-   * empty string.
-   * If a key occurs more than once in the query string, it is mapped to
-   * an arbitrary choice of possible value.
-   * The [queryParametersAll] getter can provide a map
-   * that maps keys to all of their values.
-   *
-   * The returned map is unmodifiable.
-   */
+  /// The URI query split into a map according to the rules
+  /// specified for FORM post in the [HTML 4.01 specification section
+  /// 17.13.4](http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 "HTML 4.01 section 17.13.4").
+  ///
+  /// Each key and value in the resulting map has been decoded.
+  /// If there is no query the empty map is returned.
+  ///
+  /// Keys in the query string that have no value are mapped to the
+  /// empty string.
+  /// If a key occurs more than once in the query string, it is mapped to
+  /// an arbitrary choice of possible value.
+  /// The [queryParametersAll] getter can provide a map
+  /// that maps keys to all of their values.
+  ///
+  /// The map is unmodifiable.
   Map<String, String> get queryParameters;
 
-  /**
-   * Returns the URI query split into a map according to the rules
-   * specified for FORM post in the [HTML 4.01 specification section
-   * 17.13.4](http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 "HTML 4.01 section 17.13.4").
-   * Each key and value in the returned map has been decoded. If there is no
-   * query the empty map is returned.
-   *
-   * Keys are mapped to lists of their values. If a key occurs only once,
-   * its value is a singleton list. If a key occurs with no value, the
-   * empty string is used as the value for that occurrence.
-   *
-   * The returned map and the lists it contains are unmodifiable.
-   */
+  /// Returns the URI query split into a map according to the rules
+  /// specified for FORM post in the [HTML 4.01 specification section
+  /// 17.13.4](http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 "HTML 4.01 section 17.13.4").
+  ///
+  /// Each key and value in the reulting map has been decoded. If there is no
+  /// query the map is empty.
+  ///
+  /// Keys are mapped to lists of their values. If a key occurs only once,
+  /// its value is a singleton list. If a key occurs with no value, the
+  /// empty string is used as the value for that occurrence.
+  ///
+  /// The map and the lists it contains are unmodifiable.
   Map<String, List<String>> get queryParametersAll;
 
-  /**
-   * Returns whether the URI is absolute.
-   *
-   * A URI is an absolute URI in the sense of RFC 3986 if it has a scheme
-   * and no fragment.
-   */
+  /// Whether the URI is absolute.
+  ///
+  /// A URI is an absolute URI in the sense of RFC 3986 if it has a scheme
+  /// and no fragment.
   bool get isAbsolute;
 
-  /**
-   * Returns whether the URI has a [scheme] component.
-   */
+  /// Whether the URI has a [scheme] component.
   bool get hasScheme => scheme.isNotEmpty;
 
-  /**
-   * Returns whether the URI has an [authority] component.
-   */
+  /// Whether the URI has an [authority] component.
   bool get hasAuthority;
 
-  /**
-   * Returns whether the URI has an explicit port.
-   *
-   * If the port number is the default port number
-   * (zero for unrecognized schemes, with http (80) and https (443) being
-   * recognized),
-   * then the port is made implicit and omitted from the URI.
-   */
+  /// Whether the URI has an explicit port.
+  ///
+  /// If the port number is the default port number
+  /// (zero for unrecognized schemes, with http (80) and https (443) being
+  /// recognized),
+  /// then the port is made implicit and omitted from the URI.
   bool get hasPort;
 
-  /**
-   * Returns whether the URI has a query part.
-   */
+  /// Whether the URI has a query part.
   bool get hasQuery;
 
-  /**
-   * Returns whether the URI has a fragment part.
-   */
+  /// Whether the URI has a fragment part.
   bool get hasFragment;
 
-  /**
-   * Returns whether the URI has an empty path.
-   */
+  /// Whether the URI has an empty path.
   bool get hasEmptyPath;
 
-  /**
-   * Returns whether the URI has an absolute path (starting with '/').
-   */
+  /// Whether the URI has an absolute path (starting with '/').
   bool get hasAbsolutePath;
 
-  /**
-   * Returns the origin of the URI in the form scheme://host:port for the
-   * schemes http and https.
-   *
-   * It is an error if the scheme is not "http" or "https", or if the host name
-   * is missing or empty.
-   *
-   * See: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin
-   */
+  /// Returns the origin of the URI in the form scheme://host:port for the
+  /// schemes http and https.
+  ///
+  /// It is an error if the scheme is not "http" or "https", or if the host name
+  /// is missing or empty.
+  ///
+  /// See: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin
   String get origin;
 
   /// Whether the scheme of this [Uri] is [scheme].
@@ -526,85 +476,81 @@
   /// print(uri.isScheme("HTTP"));  // Prints true.
   /// ```
   ///
-  /// A `null` or empty [scheme] string matches a URI with no scheme
+  /// An empty [scheme] string matches a URI with no scheme
   /// (one where [hasScheme] returns false).
   bool isScheme(String scheme);
 
-  /**
-   * Returns the file path from a file URI.
-   *
-   * The returned path has either Windows or non-Windows
-   * semantics.
-   *
-   * For non-Windows semantics the slash ("/") is used to separate
-   * path segments.
-   *
-   * For Windows semantics the backslash ("\\") separator is used to
-   * separate path segments.
-   *
-   * If the URI is absolute the path starts with a path separator
-   * unless Windows semantics is used and the first path segment is a
-   * drive letter. When Windows semantics is used a host component in
-   * the uri in interpreted as a file server and a UNC path is
-   * returned.
-   *
-   * The default for whether to use Windows or non-Windows semantics
-   * determined from the platform Dart is running on. When running in
-   * the standalone VM this is detected by the VM based on the
-   * operating system. When running in a browser non-Windows semantics
-   * is always used.
-   *
-   * To override the automatic detection of which semantics to use pass
-   * a value for [windows]. Passing `true` will use Windows
-   * semantics and passing `false` will use non-Windows semantics.
-   *
-   * If the URI ends with a slash (i.e. the last path component is
-   * empty) the returned file path will also end with a slash.
-   *
-   * With Windows semantics URIs starting with a drive letter cannot
-   * be relative to the current drive on the designated drive. That is
-   * for the URI `file:///c:abc` calling `toFilePath` will throw as a
-   * path segment cannot contain colon on Windows.
-   *
-   * Examples using non-Windows semantics (resulting of calling
-   * toFilePath in comment):
-   *
-   *     Uri.parse("xxx/yyy");  // xxx/yyy
-   *     Uri.parse("xxx/yyy/");  // xxx/yyy/
-   *     Uri.parse("file:///xxx/yyy");  // /xxx/yyy
-   *     Uri.parse("file:///xxx/yyy/");  // /xxx/yyy/
-   *     Uri.parse("file:///C:");  // /C:
-   *     Uri.parse("file:///C:a");  // /C:a
-   *
-   * Examples using Windows semantics (resulting URI in comment):
-   *
-   *     Uri.parse("xxx/yyy");  // xxx\yyy
-   *     Uri.parse("xxx/yyy/");  // xxx\yyy\
-   *     Uri.parse("file:///xxx/yyy");  // \xxx\yyy
-   *     Uri.parse("file:///xxx/yyy/");  // \xxx\yyy\
-   *     Uri.parse("file:///C:/xxx/yyy");  // C:\xxx\yyy
-   *     Uri.parse("file:C:xxx/yyy");  // Throws as a path segment
-   *                                   // cannot contain colon on Windows.
-   *     Uri.parse("file://server/share/file");  // \\server\share\file
-   *
-   * If the URI is not a file URI calling this throws
-   * [UnsupportedError].
-   *
-   * If the URI cannot be converted to a file path calling this throws
-   * [UnsupportedError].
-   */
+  /// Creates a file path from a file URI.
+  ///
+  /// The returned path has either Windows or non-Windows
+  /// semantics.
+  ///
+  /// For non-Windows semantics the slash ("/") is used to separate
+  /// path segments.
+  ///
+  /// For Windows semantics the backslash ("\\") separator is used to
+  /// separate path segments.
+  ///
+  /// If the URI is absolute the path starts with a path separator
+  /// unless Windows semantics is used and the first path segment is a
+  /// drive letter. When Windows semantics is used a host component in
+  /// the uri in interpreted as a file server and a UNC path is
+  /// returned.
+  ///
+  /// The default for whether to use Windows or non-Windows semantics
+  /// determined from the platform Dart is running on. When running in
+  /// the standalone VM this is detected by the VM based on the
+  /// operating system. When running in a browser non-Windows semantics
+  /// is always used.
+  ///
+  /// To override the automatic detection of which semantics to use pass
+  /// a value for [windows]. Passing `true` will use Windows
+  /// semantics and passing `false` will use non-Windows semantics.
+  ///
+  /// If the URI ends with a slash (i.e. the last path component is
+  /// empty) the returned file path will also end with a slash.
+  ///
+  /// With Windows semantics URIs starting with a drive letter cannot
+  /// be relative to the current drive on the designated drive. That is
+  /// for the URI `file:///c:abc` calling `toFilePath` will throw as a
+  /// path segment cannot contain colon on Windows.
+  ///
+  /// Examples using non-Windows semantics (resulting of calling
+  /// toFilePath in comment):
+  /// ```dart
+  /// Uri.parse("xxx/yyy");  // xxx/yyy
+  /// Uri.parse("xxx/yyy/");  // xxx/yyy/
+  /// Uri.parse("file:///xxx/yyy");  // /xxx/yyy
+  /// Uri.parse("file:///xxx/yyy/");  // /xxx/yyy/
+  /// Uri.parse("file:///C:");  // /C:
+  /// Uri.parse("file:///C:a");  // /C:a
+  /// ```
+  /// Examples using Windows semantics (resulting URI in comment):
+  /// ```dart
+  /// Uri.parse("xxx/yyy");  // xxx\yyy
+  /// Uri.parse("xxx/yyy/");  // xxx\yyy\
+  /// Uri.parse("file:///xxx/yyy");  // \xxx\yyy
+  /// Uri.parse("file:///xxx/yyy/");  // \xxx\yyy\
+  /// Uri.parse("file:///C:/xxx/yyy");  // C:\xxx\yyy
+  /// Uri.parse("file:C:xxx/yyy");  // Throws as a path segment
+  ///                               // cannot contain colon on Windows.
+  /// Uri.parse("file://server/share/file");  // \\server\share\file
+  /// ```
+  /// If the URI is not a file URI calling this throws
+  /// [UnsupportedError].
+  ///
+  /// If the URI cannot be converted to a file path calling this throws
+  /// [UnsupportedError].
   // TODO(lrn): Deprecate and move functionality to File class or similar.
   // The core libraries should not worry about the platform.
   String toFilePath({bool? windows});
 
-  /**
-   * Access the structure of a `data:` URI.
-   *
-   * Returns a [UriData] object for `data:` URIs and `null` for all other
-   * URIs.
-   * The [UriData] object can be used to access the media type and data
-   * of a `data:` URI.
-   */
+  /// Access the structure of a `data:` URI.
+  ///
+  /// Returns a [UriData] object for `data:` URIs and `null` for all other
+  /// URIs.
+  /// The [UriData] object can be used to access the media type and data
+  /// of a `data:` URI.
   UriData? get data;
 
   /// Returns a hash code computed as `toString().hashCode`.
@@ -616,49 +562,47 @@
   /// A URI is equal to another URI with the same normalized representation.
   bool operator ==(Object other);
 
-  /// Returns the normalized string representation of the URI.
+  /// The normalized string representation of the URI.
   String toString();
 
-  /**
-   * Returns a new `Uri` based on this one, but with some parts replaced.
-   *
-   * This method takes the same parameters as the [new Uri] constructor,
-   * and they have the same meaning.
-   *
-   * At most one of [path] and [pathSegments] must be provided.
-   * Likewise, at most one of [query] and [queryParameters] must be provided.
-   *
-   * Each part that is not provided will default to the corresponding
-   * value from this `Uri` instead.
-   *
-   * This method is different from [Uri.resolve] which overrides in a
-   * hierarchical manner,
-   * and can instead replace each part of a `Uri` individually.
-   *
-   * Example:
-   *
-   *     Uri uri1 = Uri.parse("a://b@c:4/d/e?f#g");
-   *     Uri uri2 = uri1.replace(scheme: "A", path: "D/E/E", fragment: "G");
-   *     print(uri2);  // prints "a://b@c:4/D/E/E?f#G"
-   *
-   * This method acts similarly to using the `new Uri` constructor with
-   * some of the arguments taken from this `Uri`. Example:
-   *
-   *     Uri uri3 = new Uri(
-   *         scheme: "A",
-   *         userInfo: uri1.userInfo,
-   *         host: uri1.host,
-   *         port: uri1.port,
-   *         path: "D/E/E",
-   *         query: uri1.query,
-   *         fragment: "G");
-   *     print(uri3);  // prints "a://b@c:4/D/E/E?f#G"
-   *     print(uri2 == uri3);  // prints true.
-   *
-   * Using this method can be seen as a shorthand for the `Uri` constructor
-   * call above, but may also be slightly faster because the parts taken
-   * from this `Uri` need not be checked for validity again.
-   */
+  /// Creates a new `Uri` based on this one, but with some parts replaced.
+  ///
+  /// This method takes the same parameters as the [Uri] constructor,
+  /// and they have the same meaning.
+  ///
+  /// At most one of [path] and [pathSegments] must be provided.
+  /// Likewise, at most one of [query] and [queryParameters] must be provided.
+  ///
+  /// Each part that is not provided will default to the corresponding
+  /// value from this `Uri` instead.
+  ///
+  /// This method is different from [Uri.resolve] which overrides in a
+  /// hierarchical manner,
+  /// and can instead replace each part of a `Uri` individually.
+  ///
+  /// Example:
+  /// ```dart
+  /// Uri uri1 = Uri.parse("a://b@c:4/d/e?f#g");
+  /// Uri uri2 = uri1.replace(scheme: "A", path: "D/E/E", fragment: "G");
+  /// print(uri2);  // prints "a://b@c:4/D/E/E?f#G"
+  /// ```
+  /// This method acts similarly to using the `Uri` constructor with
+  /// some of the arguments taken from this `Uri`. Example:
+  /// ```dart
+  /// Uri uri3 = Uri(
+  ///     scheme: "A",
+  ///     userInfo: uri1.userInfo,
+  ///     host: uri1.host,
+  ///     port: uri1.port,
+  ///     path: "D/E/E",
+  ///     query: uri1.query,
+  ///     fragment: "G");
+  /// print(uri3);  // prints "a://b@c:4/D/E/E?f#G"
+  /// print(uri2 == uri3);  // prints true.
+  /// ```
+  /// Using this method can be seen as a shorthand for the `Uri` constructor
+  /// call above, but may also be slightly faster because the parts taken
+  /// from this `Uri` need not be checked for validity again.
   Uri replace(
       {String? scheme,
       String? userInfo,
@@ -670,69 +614,58 @@
       Map<String, dynamic /*String|Iterable<String>*/ >? queryParameters,
       String? fragment});
 
-  /**
-   * Returns a `Uri` that differs from this only in not having a fragment.
-   *
-   * If this `Uri` does not have a fragment, it is itself returned.
-   */
+  /// Creates a `Uri` that differs from this only in not having a fragment.
+  ///
+  /// If this `Uri` does not have a fragment, it is itself returned.
   Uri removeFragment();
 
-  /**
-   * Resolve [reference] as an URI relative to `this`.
-   *
-   * First turn [reference] into a URI using [Uri.parse]. Then resolve the
-   * resulting URI relative to `this`.
-   *
-   * Returns the resolved URI.
-   *
-   * See [resolveUri] for details.
-   */
+  /// Resolve [reference] as an URI relative to `this`.
+  ///
+  /// First turn [reference] into a URI using [Uri.parse]. Then resolve the
+  /// resulting URI relative to `this`.
+  ///
+  /// Returns the resolved URI.
+  ///
+  /// See [resolveUri] for details.
   Uri resolve(String reference);
 
-  /**
-   * Resolve [reference] as an URI relative to `this`.
-   *
-   * Returns the resolved URI.
-   *
-   * The algorithm "Transform Reference" for resolving a reference is described
-   * in [RFC-3986 Section 5](http://tools.ietf.org/html/rfc3986#section-5 "RFC-1123").
-   *
-   * Updated to handle the case where the base URI is just a relative path -
-   * that is: when it has no scheme and no authority and the path does not start
-   * with a slash.
-   * In that case, the paths are combined without removing leading "..", and
-   * an empty path is not converted to "/".
-   */
+  /// Resolve [reference] as an URI relative to `this`.
+  ///
+  /// Returns the resolved URI.
+  ///
+  /// The algorithm "Transform Reference" for resolving a reference is described
+  /// in [RFC-3986 Section 5](http://tools.ietf.org/html/rfc3986#section-5 "RFC-1123").
+  ///
+  /// Updated to handle the case where the base URI is just a relative path -
+  /// that is: when it has no scheme and no authority and the path does not start
+  /// with a slash.
+  /// In that case, the paths are combined without removing leading "..", and
+  /// an empty path is not converted to "/".
   Uri resolveUri(Uri reference);
 
-  /**
-   * Returns a URI where the path has been normalized.
-   *
-   * A normalized path does not contain `.` segments or non-leading `..`
-   * segments.
-   * Only a relative path with no scheme or authority may contain
-   * leading `..` segments,
-   * a path that starts with `/` will also drop any leading `..` segments.
-   *
-   * This uses the same normalization strategy as `new Uri().resolve(this)`.
-   *
-   * Does not change any part of the URI except the path.
-   *
-   * The default implementation of `Uri` always normalizes paths, so calling
-   * this function has no effect.
-   */
+  /// Returns a URI where the path has been normalized.
+  ///
+  /// A normalized path does not contain `.` segments or non-leading `..`
+  /// segments.
+  /// Only a relative path with no scheme or authority may contain
+  /// leading `..` segments,
+  /// a path that starts with `/` will also drop any leading `..` segments.
+  ///
+  /// This uses the same normalization strategy as `Uri().resolve(this)`.
+  ///
+  /// Does not change any part of the URI except the path.
+  ///
+  /// The default implementation of `Uri` always normalizes paths, so calling
+  /// this function has no effect.
   Uri normalizePath();
 
-  /**
-   * Creates a new `Uri` object by parsing a URI string.
-   *
-   * If [start] and [end] are provided, they must specify a valid substring
-   * of [uri], and only the substring from `start` to `end` is parsed as a URI.
-   *
-   * The [uri] must not be `null`.
-   * If the [uri] string is not valid as a URI or URI reference,
-   * a [FormatException] is thrown.
-   */
+  /// Creates a new `Uri` object by parsing a URI string.
+  ///
+  /// If [start] and [end] are provided, they must specify a valid substring
+  /// of [uri], and only the substring from `start` to `end` is parsed as a URI.
+  ///
+  /// If the [uri] string is not valid as a URI or URI reference,
+  /// a [FormatException] is thrown.
   static Uri parse(String uri, [int start = 0, int? end]) {
     // This parsing will not validate percent-encoding, IPv6, etc.
     // When done splitting into parts, it will call, e.g., [_makeFragment]
@@ -1024,15 +957,12 @@
         pathStart, queryStart, fragmentStart, scheme);
   }
 
-  /**
-   * Creates a new `Uri` object by parsing a URI string.
-   *
-   * If [start] and [end] are provided, they must specify a valid substring
-   * of [uri], and only the substring from `start` to `end` is parsed as a URI.
-   * The [uri] must not be `null`.
-   *
-   * Returns `null` if the [uri] string is not valid as a URI or URI reference.
-   */
+  /// Creates a new `Uri` object by parsing a URI string.
+  ///
+  /// If [start] and [end] are provided, they must specify a valid substring
+  /// of [uri], and only the substring from `start` to `end` is parsed as a URI.
+  ///
+  /// Returns `null` if the [uri] string is not valid as a URI or URI reference.
   static Uri? tryParse(String uri, [int start = 0, int? end]) {
     // TODO: Optimize to avoid throwing-and-recatching.
     try {
@@ -1042,32 +972,30 @@
     }
   }
 
-  /**
-   * Encode the string [component] using percent-encoding to make it
-   * safe for literal use as a URI component.
-   *
-   * All characters except uppercase and lowercase letters, digits and
-   * the characters `-_.!~*'()` are percent-encoded. This is the
-   * set of characters specified in RFC 2396 and the which is
-   * specified for the encodeUriComponent in ECMA-262 version 5.1.
-   *
-   * When manually encoding path segments or query components remember
-   * to encode each part separately before building the path or query
-   * string.
-   *
-   * For encoding the query part consider using
-   * [encodeQueryComponent].
-   *
-   * To avoid the need for explicitly encoding use the [pathSegments]
-   * and [queryParameters] optional named arguments when constructing
-   * a [Uri].
-   */
+  /// Encode the string [component] using percent-encoding to make it
+  /// safe for literal use as a URI component.
+  ///
+  /// All characters except uppercase and lowercase letters, digits and
+  /// the characters `-_.!~*'()` are percent-encoded. This is the
+  /// set of characters specified in RFC 2396 and the which is
+  /// specified for the encodeUriComponent in ECMA-262 version 5.1.
+  ///
+  /// When manually encoding path segments or query components remember
+  /// to encode each part separately before building the path or query
+  /// string.
+  ///
+  /// For encoding the query part consider using
+  /// [encodeQueryComponent].
+  ///
+  /// To avoid the need for explicitly encoding use the [pathSegments]
+  /// and [queryParameters] optional named arguments when constructing
+  /// a [Uri].
   static String encodeComponent(String component) {
     return _Uri._uriEncode(_Uri._unreserved2396Table, component, utf8, false);
   }
 
   /**
-   * Encode the string [component] according to the HTML 4.01 rules
+   * Encodes the string [component] according to the HTML 4.01 rules
    * for encoding the posting of a HTML form as a query string
    * component.
    *
@@ -1104,76 +1032,67 @@
     return _Uri._uriEncode(_Uri._unreservedTable, component, encoding, true);
   }
 
-  /**
-   * Decodes the percent-encoding in [encodedComponent].
-   *
-   * Note that decoding a URI component might change its meaning as
-   * some of the decoded characters could be characters with are
-   * delimiters for a given URI component type. Always split a URI
-   * component using the delimiters for the component before decoding
-   * the individual parts.
-   *
-   * For handling the [path] and [query] components consider using
-   * [pathSegments] and [queryParameters] to get the separated and
-   * decoded component.
-   */
+  /// Decodes the percent-encoding in [encodedComponent].
+  ///
+  /// Note that decoding a URI component might change its meaning as
+  /// some of the decoded characters could be characters with are
+  /// delimiters for a given URI component type. Always split a URI
+  /// component using the delimiters for the component before decoding
+  /// the individual parts.
+  ///
+  /// For handling the [path] and [query] components consider using
+  /// [pathSegments] and [queryParameters] to get the separated and
+  /// decoded component.
   static String decodeComponent(String encodedComponent) {
     return _Uri._uriDecode(
         encodedComponent, 0, encodedComponent.length, utf8, false);
   }
 
-  /**
-   * Decodes the percent-encoding in [encodedComponent], converting
-   * pluses to spaces.
-   *
-   * It will create a byte-list of the decoded characters, and then use
-   * [encoding] to decode the byte-list to a String. The default encoding is
-   * UTF-8.
-   */
+  /// Decodes the percent-encoding in [encodedComponent], converting
+  /// pluses to spaces.
+  ///
+  /// It will create a byte-list of the decoded characters, and then use
+  /// [encoding] to decode the byte-list to a String. The default encoding is
+  /// UTF-8.
   static String decodeQueryComponent(String encodedComponent,
       {Encoding encoding = utf8}) {
     return _Uri._uriDecode(
         encodedComponent, 0, encodedComponent.length, encoding, true);
   }
 
-  /**
-   * Encode the string [uri] using percent-encoding to make it
-   * safe for literal use as a full URI.
-   *
-   * All characters except uppercase and lowercase letters, digits and
-   * the characters `!#$&'()*+,-./:;=?@_~` are percent-encoded. This
-   * is the set of characters specified in in ECMA-262 version 5.1 for
-   * the encodeURI function .
-   */
+  /// Encodes the string [uri] using percent-encoding to make it
+  /// safe for literal use as a full URI.
+  ///
+  /// All characters except uppercase and lowercase letters, digits and
+  /// the characters `!#$&'()*+,-./:;=?@_~` are percent-encoded. This
+  /// is the set of characters specified in in ECMA-262 version 5.1 for
+  /// the encodeURI function .
   static String encodeFull(String uri) {
     return _Uri._uriEncode(_Uri._encodeFullTable, uri, utf8, false);
   }
 
-  /**
-   * Decodes the percent-encoding in [uri].
-   *
-   * Note that decoding a full URI might change its meaning as some of
-   * the decoded characters could be reserved characters. In most
-   * cases an encoded URI should be parsed into components using
-   * [Uri.parse] before decoding the separate components.
-   */
+  /// Decodes the percent-encoding in [uri].
+  ///
+  /// Note that decoding a full URI might change its meaning as some of
+  /// the decoded characters could be reserved characters. In most
+  /// cases an encoded URI should be parsed into components using
+  /// [Uri.parse] before decoding the separate components.
   static String decodeFull(String uri) {
     return _Uri._uriDecode(uri, 0, uri.length, utf8, false);
   }
 
-  /**
-   * Returns the [query] split into a map according to the rules
-   * specified for FORM post in the [HTML 4.01 specification section
-   * 17.13.4](http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 "HTML 4.01 section 17.13.4").
-   * Each key and value in the returned map has been decoded. If the [query]
-   * is the empty string an empty map is returned.
-   *
-   * Keys in the query string that have no value are mapped to the
-   * empty string.
-   *
-   * Each query component will be decoded using [encoding]. The default encoding
-   * is UTF-8.
-   */
+  /// Splits the [query] into a map according to the rules
+  /// specified for FORM post in the [HTML 4.01 specification section
+  /// 17.13.4](http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 "HTML 4.01 section 17.13.4").
+  ///
+  /// Each key and value in the returned map has been decoded. If the [query]
+  /// is the empty string an empty map is returned.
+  ///
+  /// Keys in the query string that have no value are mapped to the
+  /// empty string.
+  ///
+  /// Each query component will be decoded using [encoding]. The default encoding
+  /// is UTF-8.
   static Map<String, String> splitQueryString(String query,
       {Encoding encoding = utf8}) {
     return query.split("&").fold({}, (map, element) {
@@ -1192,13 +1111,11 @@
     });
   }
 
-  /**
-   * Parse the [host] as an IP version 4 (IPv4) address, returning the address
-   * as a list of 4 bytes in network byte order (big endian).
-   *
-   * Throws a [FormatException] if [host] is not a valid IPv4 address
-   * representation.
-   */
+  /// Parses the [host] as an IP version 4 (IPv4) address, returning the address
+  /// as a list of 4 bytes in network byte order (big endian).
+  ///
+  /// Throws a [FormatException] if [host] is not a valid IPv4 address
+  /// representation.
   static List<int> parseIPv4Address(String host) =>
       _parseIPv4Address(host, 0, host.length);
 
@@ -1244,23 +1161,23 @@
     return result;
   }
 
-  /**
-   * Parse the [host] as an IP version 6 (IPv6) address, returning the address
-   * as a list of 16 bytes in network byte order (big endian).
-   *
-   * Throws a [FormatException] if [host] is not a valid IPv6 address
-   * representation.
-   *
-   * Acts on the substring from [start] to [end]. If [end] is omitted, it
-   * defaults ot the end of the string.
-   *
-   * Some examples of IPv6 addresses:
-   *  * `::1`
-   *  * `FEDC:BA98:7654:3210:FEDC:BA98:7654:3210`
-   *  * `3ffe:2a00:100:7031::1`
-   *  * `::FFFF:129.144.52.38`
-   *  * `2010:836B:4179::836B:4179`
-   */
+  /// Parses the [host] as an IP version 6 (IPv6) address.
+  ///
+  /// Returns the address as a list of 16 bytes in network byte order
+  /// (big endian).
+  ///
+  /// Throws a [FormatException] if [host] is not a valid IPv6 address
+  /// representation.
+  ///
+  /// Acts on the substring from [start] to [end]. If [end] is omitted, it
+  /// defaults ot the end of the string.
+  ///
+  /// Some examples of IPv6 addresses:
+  ///  * `::1`
+  ///  * `FEDC:BA98:7654:3210:FEDC:BA98:7654:3210`
+  ///  * `3ffe:2a00:100:7031::1`
+  ///  * `::FFFF:129.144.52.38`
+  ///  * `2010:836B:4179::836B:4179`
   static List<int> parseIPv6Address(String host, [int start = 0, int? end]) {
     end ??= host.length;
     // An IPv6 address consists of exactly 8 parts of 1-4 hex digits, separated
@@ -1368,37 +1285,29 @@
   // A valid scheme cannot be empty.
   final String scheme;
 
-  /**
-   * The user-info part of the authority.
-   *
-   * Does not distinguish between an empty user-info and an absent one.
-   * The value is always non-null.
-   * Is considered absent if [_host] is `null`.
-   */
+  /// The user-info part of the authority.
+  ///
+  /// Does not distinguish between an empty user-info and an absent one.
+  /// The value is always non-null.
+  /// Is considered absent if [_host] is `null`.
   final String _userInfo;
 
-  /**
-   * The host name of the URI.
-   *
-   * Set to `null` if there is no authority in the URI.
-   * The host name is the only mandatory part of an authority, so we use
-   * it to mark whether an authority part was present or not.
-   */
+  /// The host name of the URI.
+  ///
+  /// Set to `null` if there is no authority in the URI.
+  /// The host name is the only mandatory part of an authority, so we use
+  /// it to mark whether an authority part was present or not.
   final String? _host;
 
-  /**
-   * The port number part of the authority.
-   *
-   * The port. Set to null if there is no port. Normalized to null if
-   * the port is the default port for the scheme.
-   */
+  /// The port number part of the authority.
+  ///
+  /// The port. Set to null if there is no port. Normalized to null if
+  /// the port is the default port for the scheme.
   int? _port;
 
-  /**
-   * The path of the URI.
-   *
-   * Always non-null.
-   */
+  /// The path of the URI.
+  ///
+  /// Always non-null.
   final String path;
 
   /// The query content, or null if there is no query.
@@ -1543,13 +1452,13 @@
 
   /// Implementation of [Uri.http].
   factory _Uri.http(String authority, String unencodedPath,
-      [Map<String, String>? queryParameters]) {
+      [Map<String, dynamic>? queryParameters]) {
     return _makeHttpUri("http", authority, unencodedPath, queryParameters);
   }
 
   /// Implementation of [Uri.https].
   factory _Uri.https(String authority, String unencodedPath,
-      [Map<String, String>? queryParameters]) {
+      [Map<String, dynamic>? queryParameters]) {
     return _makeHttpUri("https", authority, unencodedPath, queryParameters);
   }
 
@@ -1630,7 +1539,7 @@
   }
 
   static _Uri _makeHttpUri(String scheme, String? authority,
-      String unencodedPath, Map<String, String>? queryParameters) {
+      String unencodedPath, Map<String, dynamic>? queryParameters) {
     var userInfo = "";
     String? host;
     int? port;
@@ -1940,17 +1849,15 @@
     return port;
   }
 
-  /**
-   * Check and normalize a host name.
-   *
-   * If the host name starts and ends with '[' and ']', it is considered an
-   * IPv6 address. If [strictIPv6] is false, the address is also considered
-   * an IPv6 address if it contains any ':' character.
-   *
-   * If it is not an IPv6 address, it is case- and escape-normalized.
-   * This escapes all characters not valid in a reg-name,
-   * and converts all non-escape upper-case letters to lower-case.
-   */
+  /// Check and normalize a host name.
+  ///
+  /// If the host name starts and ends with '[' and ']', it is considered an
+  /// IPv6 address. If [strictIPv6] is false, the address is also considered
+  /// an IPv6 address if it contains any ':' character.
+  ///
+  /// If it is not an IPv6 address, it is case- and escape-normalized.
+  /// This escapes all characters not valid in a reg-name,
+  /// and converts all non-escape upper-case letters to lower-case.
   static String? _makeHost(String? host, int start, int end, bool strictIPv6) {
     // TODO(lrn): Should we normalize IPv6 addresses according to RFC 5952?
     if (host == null) return null;
@@ -2002,14 +1909,12 @@
     return char < 127 && (_zoneIDTable[char >> 4] & (1 << (char & 0xf))) != 0;
   }
 
-  /**
-   * Validates and does case- and percent-encoding normalization.
-   *
-   * The same as [_normalizeOrSubstring]
-   * except this function does not convert characters to lower case.
-   * The [host] must be an RFC6874 "ZoneID".
-   * ZoneID = 1*(unreserved / pct-encoded)
-   */
+  /// Validates and does case- and percent-encoding normalization.
+  ///
+  /// The same as [_normalizeOrSubstring]
+  /// except this function does not convert characters to lower case.
+  /// The [host] must be an RFC6874 "ZoneID".
+  /// ZoneID = 1*(unreserved / pct-encoded)
   static String _normalizeZoneID(String host, int start, int end,
       [String prefix = '']) {
     StringBuffer? buffer;
@@ -2080,13 +1985,11 @@
     return char < 127 && (_regNameTable[char >> 4] & (1 << (char & 0xf))) != 0;
   }
 
-  /**
-   * Validates and does case- and percent-encoding normalization.
-   *
-   * The [host] must be an RFC3986 "reg-name". It is converted
-   * to lower case, and percent escapes are converted to either
-   * lower case unreserved characters or upper case escapes.
-   */
+  /// Validates and does case- and percent-encoding normalization.
+  ///
+  /// The [host] must be an RFC3986 "reg-name". It is converted
+  /// to lower case, and percent escapes are converted to either
+  /// lower case unreserved characters or upper case escapes.
   static String _normalizeRegName(String host, int start, int end) {
     StringBuffer? buffer;
     int sectionStart = start;
@@ -2156,11 +2059,9 @@
     return buffer.toString();
   }
 
-  /**
-   * Validates scheme characters and does case-normalization.
-   *
-   * Schemes are converted to lower case. They cannot contain escapes.
-   */
+  /// Validates scheme characters and does case-normalization.
+  ///
+  /// Schemes are converted to lower case. They cannot contain escapes.
   static String _makeScheme(String scheme, int start, int end) {
     if (start == end) return "";
     final int firstCodeUnit = scheme.codeUnitAt(start);
@@ -2278,19 +2179,17 @@
         escapeDelimiters: true);
   }
 
-  /**
-   * Performs RFC 3986 Percent-Encoding Normalization.
-   *
-   * Returns a replacement string that should be replace the original escape.
-   * Returns null if no replacement is necessary because the escape is
-   * not for an unreserved character and is already non-lower-case.
-   *
-   * Returns "%" if the escape is invalid (not two valid hex digits following
-   * the percent sign). The calling code should replace the percent
-   * sign with "%25", but leave the following two characters unmodified.
-   *
-   * If [lowerCase] is true, a single character returned is always lower case,
-   */
+  /// Performs RFC 3986 Percent-Encoding Normalization.
+  ///
+  /// Returns a replacement string that should be replace the original escape.
+  /// Returns null if no replacement is necessary because the escape is
+  /// not for an unreserved character and is already non-lower-case.
+  ///
+  /// Returns "%" if the escape is invalid (not two valid hex digits following
+  /// the percent sign). The calling code should replace the percent
+  /// sign with "%25", but leave the following two characters unmodified.
+  ///
+  /// If [lowerCase] is true, a single character returned is always lower case,
   static String? _normalizeEscape(String source, int index, bool lowerCase) {
     assert(source.codeUnitAt(index) == _PERCENT);
     if (index + 2 >= source.length) {
@@ -2354,12 +2253,10 @@
     return String.fromCharCodes(codeUnits);
   }
 
-  /**
-   * Normalizes using [_normalize] or returns substring of original.
-   *
-   * If [_normalize] returns `null` (original content is already normalized),
-   * this methods returns the substring if [component] from [start] to [end].
-   */
+  /// Normalizes using [_normalize] or returns substring of original.
+  ///
+  /// If [_normalize] returns `null` (original content is already normalized),
+  /// this methods returns the substring if [component] from [start] to [end].
   static String _normalizeOrSubstring(
       String component, int start, int end, List<int> charTable,
       {bool escapeDelimiters = false}) {
@@ -2368,17 +2265,15 @@
         component.substring(start, end);
   }
 
-  /**
-   * Runs through component checking that each character is valid and
-   * normalize percent escapes.
-   *
-   * Uses [charTable] to check if a non-`%` character is allowed.
-   * Each `%` character must be followed by two hex digits.
-   * If the hex-digits are lower case letters, they are converted to
-   * upper case.
-   *
-   * Returns `null` if the original content was already normalized.
-   */
+  /// Runs through component checking that each character is valid and
+  /// normalize percent escapes.
+  ///
+  /// Uses [charTable] to check if a non-`%` character is allowed.
+  /// Each `%` character must be followed by two hex digits.
+  /// If the hex-digits are lower case letters, they are converted to
+  /// upper case.
+  ///
+  /// Returns `null` if the original content was already normalized.
   static String? _normalize(
       String component, int start, int end, List<int> charTable,
       {bool escapeDelimiters = false}) {
@@ -2450,9 +2345,7 @@
         ((_genDelimitersTable[ch >> 4] & (1 << (ch & 0x0f))) != 0);
   }
 
-  /**
-   * Returns whether the URI is absolute.
-   */
+  /// Whether the URI is absolute.
   bool get isAbsolute => scheme != "" && fragment == "";
 
   String _mergePaths(String base, String reference) {
@@ -2775,14 +2668,12 @@
     }
   }
 
-  /**
-   * Access the structure of a `data:` URI.
-   *
-   * Returns a [UriData] object for `data:` URIs and `null` for all other
-   * URIs.
-   * The [UriData] object can be used to access the media type and data
-   * of a `data:` URI.
-   */
+  /// Access the structure of a `data:` URI.
+  ///
+  /// Returns a [UriData] object for `data:` URIs and `null` for all other
+  /// URIs.
+  /// The [UriData] object can be used to access the media type and data
+  /// of a `data:` URI.
   UriData? get data => (scheme == "data") ? UriData.fromUri(this) : null;
 
   String toString() => _text;
@@ -2858,10 +2749,8 @@
   external static String _uriEncode(List<int> canonicalTable, String text,
       Encoding encoding, bool spaceToPlus);
 
-  /**
-   * Convert a byte (2 character hex sequence) in string [s] starting
-   * at position [pos] to its ordinal value
-   */
+  /// Convert a byte (2 character hex sequence) in string [s] starting
+  /// at position [pos] to its ordinal value
   static int _hexCharPairToByte(String s, int pos) {
     int byte = 0;
     for (int i = 0; i < 2; i++) {
@@ -2881,18 +2770,16 @@
     return byte;
   }
 
-  /**
-   * Uri-decode a percent-encoded string.
-   *
-   * It unescapes the string [text] and returns the unescaped string.
-   *
-   * This function is similar to the JavaScript-function `decodeURI`.
-   *
-   * If [plusToSpace] is `true`, plus characters will be converted to spaces.
-   *
-   * The decoder will create a byte-list of the percent-encoded parts, and then
-   * decode the byte-list using [encoding]. The default encodings UTF-8.
-   */
+  /// Uri-decode a percent-encoded string.
+  ///
+  /// It unescapes the string [text] and returns the unescaped string.
+  ///
+  /// This function is similar to the JavaScript-function `decodeURI`.
+  ///
+  /// If [plusToSpace] is `true`, plus characters will be converted to spaces.
+  ///
+  /// The decoder will create a byte-list of the percent-encoded parts, and then
+  /// decode the byte-list using [encoding]. The default encodings UTF-8.
   static String _uriDecode(
       String text, int start, int end, Encoding encoding, bool plusToSpace) {
     assert(0 <= start);
@@ -3191,52 +3078,45 @@
 // Data URI
 // --------------------------------------------------------------------
 
-/**
- * A way to access the structure of a `data:` URI.
- *
- * Data URIs are non-hierarchical URIs that can contain any binary data.
- * They are defined by [RFC 2397](https://tools.ietf.org/html/rfc2397).
- *
- * This class allows parsing the URI text and extracting individual parts of the
- * URI, as well as building the URI text from structured parts.
- */
+/// A way to access the structure of a `data:` URI.
+///
+/// Data URIs are non-hierarchical URIs that can contain any binary data.
+/// They are defined by [RFC 2397](https://tools.ietf.org/html/rfc2397).
+///
+/// This class allows parsing the URI text and extracting individual parts of the
+/// URI, as well as building the URI text from structured parts.
 class UriData {
   static const int _noScheme = -1;
-  /**
-   * Contains the text content of a `data:` URI, with or without a
-   * leading `data:`.
-   *
-   * If [_separatorIndices] starts with `4` (the index of the `:`), then
-   * there is a leading `data:`, otherwise [_separatorIndices] starts with
-   * `-1`.
-   */
+
+  /// Contains the text content of a `data:` URI, with or without a
+  /// leading `data:`.
+  ///
+  /// If [_separatorIndices] starts with `4` (the index of the `:`), then
+  /// there is a leading `data:`, otherwise [_separatorIndices] starts with
+  /// `-1`.
   final String _text;
 
-  /**
-   * List of the separators (';', '=' and ',') in the text.
-   *
-   * Starts with the index of the `:` in `data:` of the mimeType.
-   * That is always either -1 or 4, depending on whether `_text` includes the
-   * `data:` scheme or not.
-   *
-   * The first speparator ends the mime type. We don't bother with finding
-   * the '/' inside the mime type.
-   *
-   * Each two separators after that marks a parameter key and value.
-   *
-   * If there is a single separator left, it ends the "base64" marker.
-   *
-   * So the following separators are found for a text:
-   * ```
-   * data:text/plain;foo=bar;base64,ARGLEBARGLE=
-   *     ^          ^   ^   ^      ^
-   * ```
-   */
+  /// List of the separators (';', '=' and ',') in the text.
+  ///
+  /// Starts with the index of the `:` in `data:` of the mimeType.
+  /// That is always either -1 or 4, depending on whether `_text` includes the
+  /// `data:` scheme or not.
+  ///
+  /// The first speparator ends the mime type. We don't bother with finding
+  /// the '/' inside the mime type.
+  ///
+  /// Each two separators after that marks a parameter key and value.
+  ///
+  /// If there is a single separator left, it ends the "base64" marker.
+  ///
+  /// So the following separators are found for a text:
+  /// ```
+  /// data:text/plain;foo=bar;base64,ARGLEBARGLE=
+  ///     ^          ^   ^   ^      ^
+  /// ```
   final List<int> _separatorIndices;
 
-  /**
-   * Cache of the result returned by [uri].
-   */
+  /// Cache of the result returned by [uri].
   Uri? _uriCache;
 
   UriData._(this._text, this._separatorIndices, this._uriCache);
@@ -3244,12 +3124,10 @@
   // Avoid shadowing by argument.
   static const Base64Codec _base64 = base64;
 
-  /**
-   * Creates a `data:` URI containing the [content] string.
-   *
-   * Equivalent to `new Uri.dataFromString(...).data`, but may
-   * be more efficient if the [uri] itself isn't used.
-   */
+  /// Creates a `data:` URI containing the [content] string.
+  ///
+  /// Equivalent to `Uri.dataFromString(...).data`, but may
+  /// be more efficient if the [uri] itself isn't used.
   factory UriData.fromString(String content,
       {String? mimeType,
       Encoding? encoding,
@@ -3281,12 +3159,10 @@
     return UriData._(buffer.toString(), indices, null);
   }
 
-  /**
-   * Creates a `data:` URI containing an encoding of [bytes].
-   *
-   * Equivalent to `new Uri.dataFromBytes(...).data`, but may
-   * be more efficient if the [uri] itself isn't used.
-   */
+  /// Creates a `data:` URI containing an encoding of [bytes].
+  ///
+  /// Equivalent to `Uri.dataFromBytes(...).data`, but may
+  /// be more efficient if the [uri] itself isn't used.
   factory UriData.fromBytes(List<int> bytes,
       {String mimeType = "application/octet-stream",
       Map<String, String>? parameters,
@@ -3309,13 +3185,11 @@
     return UriData._(buffer.toString(), indices, null);
   }
 
-  /**
-   * Creates a `DataUri` from a [Uri] which must have `data` as [Uri.scheme].
-   *
-   * The [uri] must have scheme `data` and no authority or fragment,
-   * and the path (concatenated with the query, if there is one) must be valid
-   * as data URI content with the same rules as [parse].
-   */
+  /// Creates a `DataUri` from a [Uri] which must have `data` as [Uri.scheme].
+  ///
+  /// The [uri] must have scheme `data` and no authority or fragment,
+  /// and the path (concatenated with the query, if there is one) must be valid
+  /// as data URI content with the same rules as [parse].
   factory UriData.fromUri(Uri uri) {
     if (uri.scheme != "data") {
       throw ArgumentError.value(uri, "uri", "Scheme must be 'data'");
@@ -3334,14 +3208,12 @@
     return _parse(uri.toString(), 5, uri);
   }
 
-  /**
-   * Writes the initial part of a `data:` uri, from after the "data:"
-   * until just before the ',' before the data, or before a `;base64,`
-   * marker.
-   *
-   * Of an [indices] list is passed, separator indices are stored in that
-   * list.
-   */
+  /// Writes the initial part of a `data:` uri, from after the "data:"
+  /// until just before the ',' before the data, or before a `;base64,`
+  /// marker.
+  ///
+  /// Of an [indices] list is passed, separator indices are stored in that
+  /// list.
   static void _writeUri(
       String? mimeType,
       String? charsetName,
@@ -3389,15 +3261,13 @@
     });
   }
 
-  /**
-   * Checks mimeType is valid-ish (`token '/' token`).
-   *
-   * Returns the index of the slash, or -1 if the mime type is not
-   * considered valid.
-   *
-   * Currently only looks for slashes, all other characters will be
-   * percent-encoded as UTF-8 if necessary.
-   */
+  /// Checks mimeType is valid-ish (`token '/' token`).
+  ///
+  /// Returns the index of the slash, or -1 if the mime type is not
+  /// considered valid.
+  ///
+  /// Currently only looks for slashes, all other characters will be
+  /// percent-encoded as UTF-8 if necessary.
   static int _validateMimeType(String mimeType) {
     int slashIndex = -1;
     for (int i = 0; i < mimeType.length; i++) {
@@ -3412,34 +3282,32 @@
     return slashIndex;
   }
 
-  /**
-   * Parses a string as a `data` URI.
-   *
-   * The string must have the format:
-   *
-   * ```
-   * 'data:' (type '/' subtype)? (';' attribute '=' value)* (';base64')? ',' data
-   * ````
-   *
-   * where `type`, `subtype`, `attribute` and `value` are specified in RFC-2045,
-   * and `data` is a sequence of URI-characters (RFC-2396 `uric`).
-   *
-   * This means that all the characters must be ASCII, but the URI may contain
-   * percent-escapes for non-ASCII byte values that need an interpretation
-   * to be converted to the corresponding string.
-   *
-   * Parsing checks that Base64 encoded data is valid, and it normalizes it
-   * to use the default Base64 alphabet and to use padding.
-   * Non-Base64 data is escaped using percent-escapes as necessary to make
-   * it valid, and existing escapes are case normalized.
-   *
-   * Accessing the individual parts may fail later if they turn out to have
-   * content that can't be decoded successfully as a string, for example if
-   * existing percent escapes represent bytes that cannot be decoded
-   * by the chosen [Encoding] (see [contentAsString]).
-   *
-   * A [FormatException] is thrown if [uri] is not a valid data URI.
-   */
+  /// Parses a string as a `data` URI.
+  ///
+  /// The string must have the format:
+  ///
+  /// ```
+  /// 'data:' (type '/' subtype)? (';' attribute '=' value)* (';base64')? ',' data
+  /// ````
+  ///
+  /// where `type`, `subtype`, `attribute` and `value` are specified in RFC-2045,
+  /// and `data` is a sequence of URI-characters (RFC-2396 `uric`).
+  ///
+  /// This means that all the characters must be ASCII, but the URI may contain
+  /// percent-escapes for non-ASCII byte values that need an interpretation
+  /// to be converted to the corresponding string.
+  ///
+  /// Parsing checks that Base64 encoded data is valid, and it normalizes it
+  /// to use the default Base64 alphabet and to use padding.
+  /// Non-Base64 data is escaped using percent-escapes as necessary to make
+  /// it valid, and existing escapes are case normalized.
+  ///
+  /// Accessing the individual parts may fail later if they turn out to have
+  /// content that can't be decoded successfully as a string, for example if
+  /// existing percent escapes represent bytes that cannot be decoded
+  /// by the chosen [Encoding] (see [contentAsString]).
+  ///
+  /// A [FormatException] is thrown if [uri] is not a valid data URI.
   static UriData parse(String uri) {
     if (uri.length >= 5) {
       int dataDelta = _startsWithData(uri, 0);
@@ -3456,12 +3324,10 @@
     throw FormatException("Does not start with 'data:'", uri, 0);
   }
 
-  /**
-   * The [Uri] that this `UriData` is giving access to.
-   *
-   * Returns a `Uri` with scheme `data` and the remainder of the data URI
-   * as path.
-   */
+  /// The [Uri] that this `UriData` is giving access to.
+  ///
+  /// Returns a `Uri` with scheme `data` and the remainder of the data URI
+  /// as path.
   Uri get uri {
     return _uriCache ??= _computeUri();
   }
@@ -3482,26 +3348,24 @@
     return _DataUri(this, path, query);
   }
 
-  /**
-   * The MIME type of the data URI.
-   *
-   * A data URI consists of a "media type" followed by data.
-   * The media type starts with a MIME type and can be followed by
-   * extra parameters.
-   * If the MIME type representation in the URI text contains URI escapes,
-   * they are unescaped in the returned string.
-   * If the value contain non-ASCII percent escapes, they are decoded as UTF-8.
-   *
-   * Example:
-   *
-   *     data:text/plain;charset=utf-8,Hello%20World!
-   *
-   * This data URI has the media type `text/plain;charset=utf-8`, which is the
-   * MIME type `text/plain` with the parameter `charset` with value `utf-8`.
-   * See [RFC 2045](https://tools.ietf.org/html/rfc2045) for more detail.
-   *
-   * If the first part of the data URI is empty, it defaults to `text/plain`.
-   */
+  /// The MIME type of the data URI.
+  ///
+  /// A data URI consists of a "media type" followed by data.
+  /// The media type starts with a MIME type and can be followed by
+  /// extra parameters.
+  /// If the MIME type representation in the URI text contains URI escapes,
+  /// they are unescaped in the returned string.
+  /// If the value contain non-ASCII percent escapes, they are decoded as UTF-8.
+  ///
+  /// Example:
+  /// ```dart
+  /// data:text/plain;charset=utf-8,Hello%20World!
+  /// ```
+  /// This data URI has the media type `text/plain;charset=utf-8`, which is the
+  /// MIME type `text/plain` with the parameter `charset` with value `utf-8`.
+  /// See [RFC 2045](https://tools.ietf.org/html/rfc2045) for more detail.
+  ///
+  /// If the first part of the data URI is empty, it defaults to `text/plain`.
   String get mimeType {
     int start = _separatorIndices[0] + 1;
     int end = _separatorIndices[1];
@@ -3509,17 +3373,15 @@
     return _Uri._uriDecode(_text, start, end, utf8, false);
   }
 
-  /**
-   * The charset parameter of the media type.
-   *
-   * If the parameters of the media type contains a `charset` parameter
-   * then this returns its value, otherwise it returns `US-ASCII`,
-   * which is the default charset for data URIs.
-   * If the value contain non-ASCII percent escapes, they are decoded as UTF-8.
-   *
-   * If the MIME type representation in the URI text contains URI escapes,
-   * they are unescaped in the returned string.
-   */
+  /// The charset parameter of the media type.
+  ///
+  /// If the parameters of the media type contains a `charset` parameter
+  /// then this returns its value, otherwise it returns `US-ASCII`,
+  /// which is the default charset for data URIs.
+  /// If the value contain non-ASCII percent escapes, they are decoded as UTF-8.
+  ///
+  /// If the MIME type representation in the URI text contains URI escapes,
+  /// they are unescaped in the returned string.
   String get charset {
     int parameterStart = 1;
     int parameterEnd = _separatorIndices.length - 1; // The ',' before data.
@@ -3538,27 +3400,21 @@
     return "US-ASCII";
   }
 
-  /**
-   * Whether the data is Base64 encoded or not.
-   */
+  /// Whether the data is Base64 encoded or not.
   bool get isBase64 => _separatorIndices.length.isOdd;
 
-  /**
-   * The content part of the data URI, as its actual representation.
-   *
-   * This string may contain percent escapes.
-   */
+  /// The content part of the data URI, as its actual representation.
+  ///
+  /// This string may contain percent escapes.
   String get contentText => _text.substring(_separatorIndices.last + 1);
 
-  /**
-   * The content part of the data URI as bytes.
-   *
-   * If the data is Base64 encoded, it will be decoded to bytes.
-   *
-   * If the data is not Base64 encoded, it will be decoded by unescaping
-   * percent-escaped characters and returning byte values of each unescaped
-   * character. The bytes will not be, e.g., UTF-8 decoded.
-   */
+  /// The content part of the data URI as bytes.
+  ///
+  /// If the data is Base64 encoded, it will be decoded to bytes.
+  ///
+  /// If the data is not Base64 encoded, it will be decoded by unescaping
+  /// percent-escaped characters and returning byte values of each unescaped
+  /// character. The bytes will not be, e.g., UTF-8 decoded.
   Uint8List contentAsBytes() {
     String text = _text;
     int start = _separatorIndices.last + 1;
@@ -3604,20 +3460,18 @@
     return result;
   }
 
-  /**
-   * Returns a string created from the content of the data URI.
-   *
-   * If the content is Base64 encoded, it will be decoded to bytes and then
-   * decoded to a string using [encoding].
-   * If encoding is omitted, the value of a `charset` parameter is used
-   * if it is recognized by [Encoding.getByName], otherwise it defaults to
-   * the [ascii] encoding, which is the default encoding for data URIs
-   * that do not specify an encoding.
-   *
-   * If the content is not Base64 encoded, it will first have percent-escapes
-   * converted to bytes and then the character codes and byte values are
-   * decoded using [encoding].
-   */
+  /// Creates a string from the content of the data URI.
+  ///
+  /// If the content is Base64 encoded, it will be decoded to bytes and then
+  /// decoded to a string using [encoding].
+  /// If encoding is omitted, the value of a `charset` parameter is used
+  /// if it is recognized by [Encoding.getByName], otherwise it defaults to
+  /// the [ascii] encoding, which is the default encoding for data URIs
+  /// that do not specify an encoding.
+  ///
+  /// If the content is not Base64 encoded, it will first have percent-escapes
+  /// converted to bytes and then the character codes and byte values are
+  /// decoded using [encoding].
   String contentAsString({Encoding? encoding}) {
     if (encoding == null) {
       var charset = this.charset; // Returns "US-ASCII" if not present.
@@ -3635,20 +3489,18 @@
     return _Uri._uriDecode(text, start, text.length, encoding, false);
   }
 
-  /**
-   * A map representing the parameters of the media type.
-   *
-   * A data URI may contain parameters between the MIME type and the
-   * data. This converts these parameters to a map from parameter name
-   * to parameter value.
-   * The map only contains parameters that actually occur in the URI.
-   * The `charset` parameter has a default value even if it doesn't occur
-   * in the URI, which is reflected by the [charset] getter. This means that
-   * [charset] may return a value even if `parameters["charset"]` is `null`.
-   *
-   * If the values contain non-ASCII values or percent escapes,
-   * they are decoded as UTF-8.
-   */
+  /// A map representing the parameters of the media type.
+  ///
+  /// A data URI may contain parameters between the MIME type and the
+  /// data. This converts these parameters to a map from parameter name
+  /// to parameter value.
+  /// The map only contains parameters that actually occur in the URI.
+  /// The `charset` parameter has a default value even if it doesn't occur
+  /// in the URI, which is reflected by the [charset] getter. This means that
+  /// [charset] may return a value even if `parameters["charset"]` is `null`.
+  ///
+  /// If the values contain non-ASCII values or percent escapes,
+  /// they are decoded as UTF-8.
   Map<String, String> get parameters {
     var result = <String, String>{};
     for (int i = 3; i < _separatorIndices.length; i += 2) {
@@ -3734,11 +3586,9 @@
     return UriData._(text, indices, sourceUri);
   }
 
-  /**
-   * Like [Uri._uriEncode] but takes the input as bytes, not a string.
-   *
-   * Encodes into [buffer] instead of creating its own buffer.
-   */
+  /// Like [Uri._uriEncode] but takes the input as bytes, not a string.
+  ///
+  /// Encodes into [buffer] instead of creating its own buffer.
   static void _uriEncodeBytes(
       List<int> canonicalTable, List<int> bytes, StringSink buffer) {
     // Encode the string into bytes then generate an ASCII only string
diff --git a/sdk/lib/ffi/allocation.dart b/sdk/lib/ffi/allocation.dart
new file mode 100644
index 0000000..fc5fce4
--- /dev/null
+++ b/sdk/lib/ffi/allocation.dart
@@ -0,0 +1,37 @@
+// 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 dart.ffi;
+
+/// Manages memory on the native heap.
+abstract class Allocator {
+  /// This interface is meant to be implemented, not extended or mixed in.
+  Allocator._() {
+    throw UnsupportedError("Cannot be instantiated");
+  }
+
+  /// Allocates [byteCount] bytes of memory on the native heap.
+  ///
+  /// If [alignment] is provided, the allocated memory will be at least aligned
+  /// to [alignment] bytes.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment});
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  void free(Pointer pointer);
+}
+
+/// Extension on [Allocator] to provide allocation with [NativeType].
+extension AllocatorAlloc on Allocator {
+  /// Allocates `sizeOf<T>() * count` bytes of memory using
+  /// `allocator.allocate`.
+  ///
+  /// This extension method must be invoked with a compile-time constant [T].
+  external Pointer<T> call<T extends NativeType>([int count = 1]);
+}
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index 68424f8..22ea459 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -5,8 +5,6 @@
 /**
  * Foreign Function Interface for interoperability with the C programming language.
  *
- * **NOTE**: Dart:FFI is in beta, and breaking API changes might still happen.
- *
  * For further details, please see: https://dart.dev/server/c-interop
  *
  * {@category VM}
@@ -17,6 +15,7 @@
 import 'dart:typed_data';
 
 part "native_type.dart";
+part "allocation.dart";
 part "annotations.dart";
 part "dynamic_library.dart";
 part "struct.dart";
@@ -24,6 +23,10 @@
 /// Number of bytes used by native type T.
 ///
 /// Includes padding and alignment of structs.
+///
+/// Support for invoking this function with non-constant [T] will be removed in
+/// the next stable version of Dart and it will become mandatory to invoke it
+/// with a compile-time constant [T].
 external int sizeOf<T extends NativeType>();
 
 /// Represents a pointer into the native C memory corresponding to "NULL", e.g.
@@ -61,6 +64,10 @@
   external int get address;
 
   /// Pointer arithmetic (takes element size into account).
+  ///
+  /// Support for invoking this method with non-constant [T] will be removed in
+  /// the next stable version of Dart and it will become mandatory to invoke it
+  /// with a compile-time constant [T].
   external Pointer<T> elementAt(int index);
 
   /// Cast Pointer<T> to a Pointer<V>.
@@ -537,6 +544,10 @@
   ///
   /// The [address] must be aligned according to the struct alignment rules of
   /// the platform.
+  ///
+  /// Support for invoking this extension method with non-constant [T] will be
+  /// removed in the next stable version of Dart and it will become mandatory
+  /// to invoke it with a compile-time constant [T].
   external T get ref;
 
   /// Creates a reference to access the fields of this struct backed by native
@@ -544,6 +555,10 @@
   ///
   /// The [address] must be aligned according to the struct alignment rules of
   /// the platform.
+  ///
+  /// Support for invoking this extension method with non-constant [T] will be
+  /// removed in the next stable version of Dart and it will become mandatory
+  /// to invoke it with a compile-time constant [T].
   external T operator [](int index);
 }
 
@@ -558,7 +573,7 @@
 }
 
 /// Opaque, not exposing it's members.
-class Dart_CObject extends Struct {}
+class Dart_CObject extends Opaque {}
 
 typedef Dart_NativeMessageHandler = Void Function(Int64, Pointer<Dart_CObject>);
 
diff --git a/sdk/lib/ffi/ffi_sources.gni b/sdk/lib/ffi/ffi_sources.gni
index 5b34b9c..db03071 100644
--- a/sdk/lib/ffi/ffi_sources.gni
+++ b/sdk/lib/ffi/ffi_sources.gni
@@ -6,6 +6,7 @@
   "ffi.dart",
 
   # The above file needs to be first as it lists the parts below.
+  "allocation.dart",
   "annotations.dart",
   "dynamic_library.dart",
   "native_type.dart",
diff --git a/sdk/lib/ffi/native_type.dart b/sdk/lib/ffi/native_type.dart
index e319342..31e4b72 100644
--- a/sdk/lib/ffi/native_type.dart
+++ b/sdk/lib/ffi/native_type.dart
@@ -12,6 +12,12 @@
   const NativeType();
 }
 
+/// [Opaque]'s subtypes represent opaque types in C.
+///
+/// [Opaque]'s subtypes are not constructible in the Dart code and serve purely
+/// as markers in type signatures.
+abstract class Opaque extends NativeType {}
+
 /// [_NativeInteger]'s subtypes represent a native integer in C.
 ///
 /// [_NativeInteger]'s subtypes are not constructible in the Dart code and serve
diff --git a/sdk/lib/ffi/struct.dart b/sdk/lib/ffi/struct.dart
index da034ef..bf8ded9 100644
--- a/sdk/lib/ffi/struct.dart
+++ b/sdk/lib/ffi/struct.dart
@@ -47,6 +47,7 @@
 /// by native memory. The may allocated via allocation or loaded from a
 /// [Pointer], but cannot be created by a generative constructor.
 abstract class Struct extends NativeType {
+  @pragma("vm:entry-point")
   final Object _addressOf;
 
   /// Construct a reference to the [nullptr].
@@ -61,5 +62,6 @@
 /// Extension on [Struct] specialized for its subtypes.
 extension StructAddressOf<T extends Struct> on T {
   /// Returns the address backing the reference.
+  @Deprecated('Hold on to the pointer backing a struct instead.')
   Pointer<T> get addressOf => _addressOf as Pointer<T>;
 }
diff --git a/sdk/lib/internal/errors.dart b/sdk/lib/internal/errors.dart
index 8b93cd1..60fa350 100644
--- a/sdk/lib/internal/errors.dart
+++ b/sdk/lib/internal/errors.dart
@@ -4,7 +4,7 @@
 
 part of dart._internal;
 
-class LateError extends Error implements LateInitializationError {
+class LateError extends Error {
   final String? _message;
 
   LateError([this._message]);
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index 9688d8d..252d602 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -19,9 +19,7 @@
 bool _isErrorResponse(response) =>
     response is List && response[0] != _successResponse;
 
-/**
- * Returns an Exception or an Error
- */
+/// Returns an [Exception] or an [Error].
 _exceptionFromResponse(response, String message, String path) {
   assert(_isErrorResponse(response));
   switch (response[_errorResponseErrorType]) {
@@ -38,20 +36,16 @@
   }
 }
 
-/**
- * Base class for all IO related exceptions.
- */
+/// Base class for all IO related exceptions.
 abstract class IOException implements Exception {
   String toString() => "IOException";
 }
 
-/**
-  * An [OSError] object holds information about an error from the
-  * operating system.
-  */
+/// An [Exception] holding information about an error from the
+/// operating system.
 @pragma("vm:entry-point")
 class OSError implements Exception {
-  /** Constant used to indicate that no OS error code is available. */
+  /// Constant used to indicate that no OS error code is available.
   static const int noErrorCode = -1;
 
   /// Error message supplied by the operating system. This will be empty if no
@@ -64,11 +58,11 @@
   /// associated with the error.
   final int errorCode;
 
-  /** Creates an OSError object from a message and an errorCode. */
+  /// Creates an OSError object from a message and an errorCode.
   @pragma("vm:entry-point")
   const OSError([this.message = "", this.errorCode = noErrorCode]);
 
-  /** Converts an OSError object to a string representation. */
+  /// Converts an OSError object to a string representation.
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("OS Error");
diff --git a/sdk/lib/io/data_transformer.dart b/sdk/lib/io/data_transformer.dart
index 4346a1a..0928116 100644
--- a/sdk/lib/io/data_transformer.dart
+++ b/sdk/lib/io/data_transformer.dart
@@ -4,11 +4,9 @@
 
 part of dart.io;
 
-/**
- * Exposes ZLib options for input parameters.
- *
- * See http://www.zlib.net/manual.html for more documentation.
- */
+/// Exposes ZLib options for input parameters.
+///
+/// See http://www.zlib.net/manual.html for more documentation.
 abstract class ZLibOption {
   /// Minimal value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits]
   /// and [ZLibDecoder.windowBits].
@@ -85,84 +83,67 @@
   static const int STRATEGY_DEFAULT = 0;
 }
 
-/**
- * An instance of the default implementation of the [ZLibCodec].
- */
+/// An instance of the default implementation of the [ZLibCodec].
 const ZLibCodec zlib = const ZLibCodec._default();
 @Deprecated("Use zlib instead")
 const ZLibCodec ZLIB = zlib;
 
-/**
- * The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib
- * compressed bytes to raw bytes.
- */
+/// The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib
+/// compressed bytes to raw bytes.
 class ZLibCodec extends Codec<List<int>, List<int>> {
-  /**
-   * When true, `GZip` frames will be added to the compressed data.
-   */
+  /// When true, `GZip` frames will be added to the compressed data.
   final bool gzip;
 
-  /**
-   * The compression-[level] can be set in the range of `-1..9`, with `6` being
-   * the default compression level. Levels above `6` will have higher
-   * compression rates at the cost of more CPU and memory usage. Levels below
-   * `6` will use less CPU and memory at the cost of lower compression rates.
-   */
+  /// The compression-[level] can be set in the range of `-1..9`, with `6` being
+  /// the default compression level. Levels above `6` will have higher
+  /// compression rates at the cost of more CPU and memory usage. Levels below
+  /// `6` will use less CPU and memory at the cost of lower compression rates.
   final int level;
 
-  /**
-   * Specifies how much memory should be allocated for the internal compression
-   * state. `1` uses minimum memory but is slow and reduces compression ratio;
-   * `9` uses maximum memory for optimal speed. The default value is `8`.
-   *
-   * The memory requirements for deflate are (in bytes):
-   *
-   *     (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
-   * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
-   */
+  /// Specifies how much memory should be allocated for the internal compression
+  /// state. `1` uses minimum memory but is slow and reduces compression ratio;
+  /// `9` uses maximum memory for optimal speed. The default value is `8`.
+  ///
+  /// The memory requirements for deflate are (in bytes):
+  /// ```dart
+  /// (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
+  /// ```
+  /// that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
   final int memLevel;
 
-  /**
-   * Tunes the compression algorithm. Use the value strategyDefault for normal
-   * data, strategyFiltered for data produced by a filter (or predictor),
-   * strategyHuffmanOnly to force Huffman encoding only (no string match), or
-   * strategyRle to limit match distances to one (run-length encoding).
-   */
+  /// Tunes the compression algorithm. Use the value strategyDefault for normal
+  /// data, strategyFiltered for data produced by a filter (or predictor),
+  /// strategyHuffmanOnly to force Huffman encoding only (no string match), or
+  /// strategyRle to limit match distances to one (run-length encoding).
   final int strategy;
 
-  /**
-   * Base two logarithm of the window size (the size of the history buffer). It
-   * should be in the range 8..15. Larger values result in better compression at
-   * the expense of memory usage. The default value is 15
-   */
+  /// Base two logarithm of the window size (the size of the history buffer). It
+  /// should be in the range 8..15. Larger values result in better compression at
+  /// the expense of memory usage. The default value is 15
   final int windowBits;
 
-  /**
-   * When true, deflate generates raw data with no zlib header or trailer, and
-   * will not compute an adler32 check value
-   */
+  /// When true, deflate generates raw data with no zlib header or trailer, and
+  /// will not compute an adler32 check value
   final bool raw;
 
-  /**
-   * Initial compression dictionary.
-   *
-   * It should consist of strings (byte sequences) that are likely to be
-   * encountered later in the data to be compressed, with the most commonly used
-   * strings preferably put towards the end of the dictionary. Using a
-   * dictionary is most useful when the data to be compressed is short and can
-   * be predicted with good accuracy; the data can then be compressed better
-   * than with the default empty dictionary.
-   */
+  /// Initial compression dictionary.
+  ///
+  /// It should consist of strings (byte sequences) that are likely to be
+  /// encountered later in the data to be compressed, with the most commonly used
+  /// strings preferably put towards the end of the dictionary. Using a
+  /// dictionary is most useful when the data to be compressed is short and can
+  /// be predicted with good accuracy; the data can then be compressed better
+  /// than with the default empty dictionary.
   final List<int>? dictionary;
 
   ZLibCodec(
-      {this.level: ZLibOption.defaultLevel,
-      this.windowBits: ZLibOption.defaultWindowBits,
-      this.memLevel: ZLibOption.defaultMemLevel,
-      this.strategy: ZLibOption.strategyDefault,
+      {this.level = ZLibOption.defaultLevel,
+      this.windowBits = ZLibOption.defaultWindowBits,
+      this.memLevel = ZLibOption.defaultMemLevel,
+      this.strategy = ZLibOption.strategyDefault,
       this.dictionary,
-      this.raw: false,
-      this.gzip: false}) {
+      this.raw = false,
+      this.gzip = false}) {
     _validateZLibeLevel(level);
     _validateZLibMemLevel(memLevel);
     _validateZLibStrategy(strategy);
@@ -178,9 +159,7 @@
         gzip = false,
         dictionary = null;
 
-  /**
-   * Get a [ZLibEncoder] for encoding to `ZLib` compressed data.
-   */
+  /// Get a [ZLibEncoder] for encoding to `ZLib` compressed data.
   ZLibEncoder get encoder => new ZLibEncoder(
       gzip: false,
       level: level,
@@ -190,96 +169,77 @@
       dictionary: dictionary,
       raw: raw);
 
-  /**
-   * Get a [ZLibDecoder] for decoding `ZLib` compressed data.
-   */
+  /// Get a [ZLibDecoder] for decoding `ZLib` compressed data.
   ZLibDecoder get decoder =>
       new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw);
 }
 
-/**
- * An instance of the default implementation of the [GZipCodec].
- */
+/// An instance of the default implementation of the [GZipCodec].
 const GZipCodec gzip = const GZipCodec._default();
 @Deprecated("Use gzip instead")
 const GZipCodec GZIP = gzip;
 
-/**
- * The [GZipCodec] encodes raw bytes to GZip compressed bytes and decodes GZip
- * compressed bytes to raw bytes.
- *
- * The difference between [ZLibCodec] and [GZipCodec] is that the [GZipCodec]
- * wraps the `ZLib` compressed bytes in `GZip` frames.
- */
+/// The [GZipCodec] encodes raw bytes to GZip compressed bytes and decodes GZip
+/// compressed bytes to raw bytes.
+///
+/// The difference between [ZLibCodec] and [GZipCodec] is that the [GZipCodec]
+/// wraps the `ZLib` compressed bytes in `GZip` frames.
 class GZipCodec extends Codec<List<int>, List<int>> {
-  /**
-   * When true, `GZip` frames will be added to the compressed data.
-   */
+  /// When true, `GZip` frames will be added to the compressed data.
   final bool gzip;
 
-  /**
-   * The compression-[level] can be set in the range of `-1..9`, with `6` being
-   * the default compression level. Levels above `6` will have higher
-   * compression rates at the cost of more CPU and memory usage. Levels below
-   * `6` will use less CPU and memory at the cost of lower compression rates.
-   */
+  /// The compression-[level] can be set in the range of `-1..9`, with `6` being
+  /// the default compression level. Levels above `6` will have higher
+  /// compression rates at the cost of more CPU and memory usage. Levels below
+  /// `6` will use less CPU and memory at the cost of lower compression rates.
   final int level;
 
-  /**
-   * Specifies how much memory should be allocated for the internal compression
-   * state. `1` uses minimum memory but is slow and reduces compression ratio;
-   * `9` uses maximum memory for optimal speed. The default value is `8`.
-   *
-   * The memory requirements for deflate are (in bytes):
-   *
-   *     (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
-   * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
-   */
+  /// Specifies how much memory should be allocated for the internal compression
+  /// state. `1` uses minimum memory but is slow and reduces compression ratio;
+  /// `9` uses maximum memory for optimal speed. The default value is `8`.
+  ///
+  /// The memory requirements for deflate are (in bytes):
+  /// ```dart
+  /// (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
+  /// ```
+  /// that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
   final int memLevel;
 
-  /**
-   * Tunes the compression algorithm. Use the value
-   * [ZLibOption.strategyDefault] for normal data,
-   * [ZLibOption.strategyFiltered] for data produced by a filter
-   * (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman
-   * encoding only (no string match), or [ZLibOption.strategyRle] to limit
-   * match distances to one (run-length encoding).
-   */
+  /// Tunes the compression algorithm. Use the value
+  /// [ZLibOption.strategyDefault] for normal data,
+  /// [ZLibOption.strategyFiltered] for data produced by a filter
+  /// (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman
+  /// encoding only (no string match), or [ZLibOption.strategyRle] to limit
+  /// match distances to one (run-length encoding).
   final int strategy;
 
-  /**
-   * Base two logarithm of the window size (the size of the history buffer). It
-   * should be in the range `8..15`. Larger values result in better compression
-   * at the expense of memory usage. The default value is `15`
-   */
+  /// Base two logarithm of the window size (the size of the history buffer). It
+  /// should be in the range `8..15`. Larger values result in better compression
+  /// at the expense of memory usage. The default value is `15`
   final int windowBits;
 
-  /**
-   * Initial compression dictionary.
-   *
-   * It should consist of strings (byte sequences) that are likely to be
-   * encountered later in the data to be compressed, with the most commonly used
-   * strings preferably put towards the end of the dictionary. Using a
-   * dictionary is most useful when the data to be compressed is short and can
-   * be predicted with good accuracy; the data can then be compressed better
-   * than with the default empty dictionary.
-   */
+  /// Initial compression dictionary.
+  ///
+  /// It should consist of strings (byte sequences) that are likely to be
+  /// encountered later in the data to be compressed, with the most commonly used
+  /// strings preferably put towards the end of the dictionary. Using a
+  /// dictionary is most useful when the data to be compressed is short and can
+  /// be predicted with good accuracy; the data can then be compressed better
+  /// than with the default empty dictionary.
   final List<int>? dictionary;
 
-  /**
-   * When true, deflate generates raw data with no zlib header or trailer, and
-   * will not compute an adler32 check value
-   */
+  /// When true, deflate generates raw data with no zlib header or trailer, and
+  /// will not compute an adler32 check value
   final bool raw;
 
   GZipCodec(
-      {this.level: ZLibOption.defaultLevel,
-      this.windowBits: ZLibOption.defaultWindowBits,
-      this.memLevel: ZLibOption.defaultMemLevel,
-      this.strategy: ZLibOption.strategyDefault,
+      {this.level = ZLibOption.defaultLevel,
+      this.windowBits = ZLibOption.defaultWindowBits,
+      this.memLevel = ZLibOption.defaultMemLevel,
+      this.strategy = ZLibOption.strategyDefault,
       this.dictionary,
-      this.raw: false,
-      this.gzip: true}) {
+      this.raw = false,
+      this.gzip = true}) {
     _validateZLibeLevel(level);
     _validateZLibMemLevel(memLevel);
     _validateZLibStrategy(strategy);
@@ -295,9 +255,7 @@
         gzip = true,
         dictionary = null;
 
-  /**
-   * Get a [ZLibEncoder] for encoding to `GZip` compressed data.
-   */
+  /// Get a [ZLibEncoder] for encoding to `GZip` compressed data.
   ZLibEncoder get encoder => new ZLibEncoder(
       gzip: true,
       level: level,
@@ -307,96 +265,77 @@
       dictionary: dictionary,
       raw: raw);
 
-  /**
-   * Get a [ZLibDecoder] for decoding `GZip` compressed data.
-   */
+  /// Get a [ZLibDecoder] for decoding `GZip` compressed data.
   ZLibDecoder get decoder =>
       new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw);
 }
 
-/**
- * The [ZLibEncoder] encoder is used by [ZLibCodec] and [GZipCodec] to compress
- * data.
- */
+/// The [ZLibEncoder] encoder is used by [ZLibCodec] and [GZipCodec] to compress
+/// data.
 class ZLibEncoder extends Converter<List<int>, List<int>> {
-  /**
-   * When true, `GZip` frames will be added to the compressed data.
-   */
+  /// When true, `GZip` frames will be added to the compressed data.
   final bool gzip;
 
-  /**
-   * The compression-[level] can be set in the range of `-1..9`, with `6` being
-   * the default compression level. Levels above `6` will have higher
-   * compression rates at the cost of more CPU and memory usage. Levels below
-   * `6` will use less CPU and memory at the cost of lower compression rates.
-   */
+  /// The compression-[level] can be set in the range of `-1..9`, with `6` being
+  /// the default compression level. Levels above `6` will have higher
+  /// compression rates at the cost of more CPU and memory usage. Levels below
+  /// `6` will use less CPU and memory at the cost of lower compression rates.
   final int level;
 
-  /**
-   * Specifies how much memory should be allocated for the internal compression
-   * state. `1` uses minimum memory but is slow and reduces compression ratio;
-   * `9` uses maximum memory for optimal speed. The default value is `8`.
-   *
-   * The memory requirements for deflate are (in bytes):
-   *
-   *     (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
-   * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
-   */
+  /// Specifies how much memory should be allocated for the internal compression
+  /// state. `1` uses minimum memory but is slow and reduces compression ratio;
+  /// `9` uses maximum memory for optimal speed. The default value is `8`.
+  ///
+  /// The memory requirements for deflate are (in bytes):
+  /// ```dart
+  /// (1 << (windowBits + 2)) +  (1 << (memLevel + 9))
+  /// ```
+  /// that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values)
   final int memLevel;
 
-  /**
-   * Tunes the compression algorithm. Use the value
-   * [ZLibOption.strategyDefault] for normal data,
-   * [ZLibOption.strategyFiltered] for data produced by a filter
-   * (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman
-   * encoding only (no string match), or [ZLibOption.strategyRle] to limit
-   * match distances to one (run-length encoding).
-   */
+  /// Tunes the compression algorithm. Use the value
+  /// [ZLibOption.strategyDefault] for normal data,
+  /// [ZLibOption.strategyFiltered] for data produced by a filter
+  /// (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman
+  /// encoding only (no string match), or [ZLibOption.strategyRle] to limit
+  /// match distances to one (run-length encoding).
   final int strategy;
 
-  /**
-   * Base two logarithm of the window size (the size of the history buffer). It
-   * should be in the range `8..15`. Larger values result in better compression
-   * at the expense of memory usage. The default value is `15`
-   */
+  /// Base two logarithm of the window size (the size of the history buffer). It
+  /// should be in the range `8..15`. Larger values result in better compression
+  /// at the expense of memory usage. The default value is `15`
   final int windowBits;
 
-  /**
-   * Initial compression dictionary.
-   *
-   * It should consist of strings (byte sequences) that are likely to be
-   * encountered later in the data to be compressed, with the most commonly used
-   * strings preferably put towards the end of the dictionary. Using a
-   * dictionary is most useful when the data to be compressed is short and can
-   * be predicted with good accuracy; the data can then be compressed better
-   * than with the default empty dictionary.
-   */
+  /// Initial compression dictionary.
+  ///
+  /// It should consist of strings (byte sequences) that are likely to be
+  /// encountered later in the data to be compressed, with the most commonly used
+  /// strings preferably put towards the end of the dictionary. Using a
+  /// dictionary is most useful when the data to be compressed is short and can
+  /// be predicted with good accuracy; the data can then be compressed better
+  /// than with the default empty dictionary.
   final List<int>? dictionary;
 
-  /**
-   * When true, deflate generates raw data with no zlib header or trailer, and
-   * will not compute an adler32 check value
-   */
+  /// When true, deflate generates raw data with no zlib header or trailer, and
+  /// will not compute an adler32 check value
   final bool raw;
 
   ZLibEncoder(
-      {this.gzip: false,
-      this.level: ZLibOption.defaultLevel,
-      this.windowBits: ZLibOption.defaultWindowBits,
-      this.memLevel: ZLibOption.defaultMemLevel,
-      this.strategy: ZLibOption.strategyDefault,
+      {this.gzip = false,
+      this.level = ZLibOption.defaultLevel,
+      this.windowBits = ZLibOption.defaultWindowBits,
+      this.memLevel = ZLibOption.defaultMemLevel,
+      this.strategy = ZLibOption.strategyDefault,
       this.dictionary,
-      this.raw: false}) {
+      this.raw = false}) {
     _validateZLibeLevel(level);
     _validateZLibMemLevel(memLevel);
     _validateZLibStrategy(strategy);
     _validateZLibWindowBits(windowBits);
   }
 
-  /**
-   * Convert a list of bytes using the options given to the ZLibEncoder
-   * constructor.
-   */
+  /// Convert a list of bytes using the options given to the ZLibEncoder
+  /// constructor.
   List<int> convert(List<int> bytes) {
     _BufferSink sink = new _BufferSink();
     startChunkedConversion(sink)
@@ -405,11 +344,12 @@
     return sink.builder.takeBytes();
   }
 
-  /**
-   * Start a chunked conversion using the options given to the [ZLibEncoder]
-   * constructor. While it accepts any [Sink] taking [List<int>]'s,
-   * the optimal sink to be passed as [sink] is a [ByteConversionSink].
-   */
+  /// Start a chunked conversion using the options given to the [ZLibEncoder]
+  /// constructor.
+  ///
+  /// Accepts any `Sink<List<int>>`, but prefers a [ByteConversionSink],
+  /// and converts any other sink to a [ByteConversionSink] before
+  /// using it.
   ByteConversionSink startChunkedConversion(Sink<List<int>> sink) {
     if (sink is! ByteConversionSink) {
       sink = new ByteConversionSink.from(sink);
@@ -419,46 +359,36 @@
   }
 }
 
-/**
- * The [ZLibDecoder] is used by [ZLibCodec] and [GZipCodec] to decompress data.
- */
+/// The [ZLibDecoder] is used by [ZLibCodec] and [GZipCodec] to decompress data.
 class ZLibDecoder extends Converter<List<int>, List<int>> {
-  /**
-   * Base two logarithm of the window size (the size of the history buffer). It
-   * should be in the range `8..15`. Larger values result in better compression
-   * at the expense of memory usage. The default value is `15`.
-   */
+  /// Base two logarithm of the window size (the size of the history buffer). It
+  /// should be in the range `8..15`. Larger values result in better compression
+  /// at the expense of memory usage. The default value is `15`.
   final int windowBits;
 
-  /**
-   * Initial compression dictionary.
-   *
-   * It should consist of strings (byte sequences) that are likely to be
-   * encountered later in the data to be compressed, with the most commonly used
-   * strings preferably put towards the end of the dictionary. Using a
-   * dictionary is most useful when the data to be compressed is short and can
-   * be predicted with good accuracy; the data can then be compressed better
-   * than with the default empty dictionary.
-   */
+  /// Initial compression dictionary.
+  ///
+  /// It should consist of strings (byte sequences) that are likely to be
+  /// encountered later in the data to be compressed, with the most commonly used
+  /// strings preferably put towards the end of the dictionary. Using a
+  /// dictionary is most useful when the data to be compressed is short and can
+  /// be predicted with good accuracy; the data can then be compressed better
+  /// than with the default empty dictionary.
   final List<int>? dictionary;
 
-  /**
-   * When true, deflate generates raw data with no zlib header or trailer, and
-   * will not compute an adler32 check value
-   */
+  /// When true, deflate generates raw data with no zlib header or trailer, and
+  /// will not compute an adler32 check value
   final bool raw;
 
   ZLibDecoder(
-      {this.windowBits: ZLibOption.defaultWindowBits,
+      {this.windowBits = ZLibOption.defaultWindowBits,
       this.dictionary,
-      this.raw: false}) {
+      this.raw = false}) {
     _validateZLibWindowBits(windowBits);
   }
 
-  /**
-   * Convert a list of bytes using the options given to the [ZLibDecoder]
-   * constructor.
-   */
+  /// Convert a list of bytes using the options given to the [ZLibDecoder]
+  /// constructor.
   List<int> convert(List<int> bytes) {
     _BufferSink sink = new _BufferSink();
     startChunkedConversion(sink)
@@ -467,11 +397,11 @@
     return sink.builder.takeBytes();
   }
 
-  /**
-   * Start a chunked conversion. While it accepts any [Sink]
-   * taking [List<int>]'s, the optimal sink to be passed as [sink] is a
-   * [ByteConversionSink].
-   */
+  /// Start a chunked conversion.
+  ///
+  /// Accepts any `Sink<List<int>>`, but prefers a [ByteConversionSink],
+  /// and converts any other sink to a [ByteConversionSink] before
+  /// using it.
   ByteConversionSink startChunkedConversion(Sink<List<int>> sink) {
     if (sink is! ByteConversionSink) {
       sink = new ByteConversionSink.from(sink);
@@ -480,54 +410,48 @@
   }
 }
 
-/**
- * The [RawZLibFilter] class provides a low-level interface to zlib.
- */
+/// The [RawZLibFilter] class provides a low-level interface to zlib.
 abstract class RawZLibFilter {
-  /**
-   * Returns a a [RawZLibFilter] whose [process] and [processed] methods
-   * compress data.
-   */
+  /// Returns a a [RawZLibFilter] whose [process] and [processed] methods
+  /// compress data.
   factory RawZLibFilter.deflateFilter({
-    bool gzip: false,
-    int level: ZLibOption.defaultLevel,
-    int windowBits: ZLibOption.defaultWindowBits,
-    int memLevel: ZLibOption.defaultMemLevel,
-    int strategy: ZLibOption.strategyDefault,
+    bool gzip = false,
+    int level = ZLibOption.defaultLevel,
+    int windowBits = ZLibOption.defaultWindowBits,
+    int memLevel = ZLibOption.defaultMemLevel,
+    int strategy = ZLibOption.strategyDefault,
     List<int>? dictionary,
-    bool raw: false,
+    bool raw = false,
   }) {
     return _makeZLibDeflateFilter(
         gzip, level, windowBits, memLevel, strategy, dictionary, raw);
   }
 
-  /**
-   * Returns a a [RawZLibFilter] whose [process] and [processed] methods
-   * decompress data.
-   */
+  /// Returns a a [RawZLibFilter] whose [process] and [processed] methods
+  /// decompress data.
   factory RawZLibFilter.inflateFilter({
-    int windowBits: ZLibOption.defaultWindowBits,
+    int windowBits = ZLibOption.defaultWindowBits,
     List<int>? dictionary,
-    bool raw: false,
+    bool raw = false,
   }) {
     return _makeZLibInflateFilter(windowBits, dictionary, raw);
   }
 
-  /**
-   * Call to process a chunk of data. A call to [process] should only be made
-   * when [processed] returns [:null:].
-   */
+  /// Process a chunk of data.
+  ///
+  /// This method must only be called when [processed] returns `null`.
   void process(List<int> data, int start, int end);
 
-  /**
-   * Get a chunk of processed data. When there are no more data available,
-   * [processed] will return [:null:]. Set [flush] to [:false:] for non-final
-   * calls to improve performance of some filters.
-   *
-   * The last call to [processed] should have [end] set to [:true:]. This will
-   * make sure an 'end' packet is written on the stream.
-   */
-  List<int>? processed({bool flush: true, bool end: false});
+  /// Get a chunk of processed data.
+  ///
+  /// When there are no more data available, [processed] will return `null`.
+  /// Set [flush] to `false` for non-final calls
+  /// to improve performance of some filters.
+  ///
+  /// The last call to [processed] should have [end] set to `true`. This will
+  /// make sure an 'end' packet is written on the stream.
+  // TODO: Which stream?
+  List<int>? processed({bool flush = true, bool end = false});
 
   external static RawZLibFilter _makeZLibDeflateFilter(
       bool gzip,
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index ee8ef1d..dbbcb26 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -4,124 +4,110 @@
 
 part of dart.io;
 
-/**
- * A reference to a directory (or _folder_) on the file system.
- *
- * A Directory instance is an object holding a [path] on which operations can
- * be performed. The path to the directory can be [absolute] or relative.
- * You can get the parent directory using the getter [parent],
- * a property inherited from [FileSystemEntity].
- *
- * In addition to being used as an instance to access the file system,
- * Directory has a number of static properties, such as [systemTemp],
- * which gets the system's temporary directory, and the getter and setter
- * [current], which you can use to access or change the current directory.
- *
- * Create a new Directory object with a pathname to access the specified
- * directory on the file system from your program.
- *
- *     var myDir = new Directory('myDir');
- *
- * Most methods in this class occur in synchronous and asynchronous pairs,
- * for example, [create] and [createSync].
- * Unless you have a specific reason for using the synchronous version
- * of a method, prefer the asynchronous version to avoid blocking your program.
- *
- * ## Create a directory
- *
- * The following code sample creates a directory using the [create] method.
- * By setting the `recursive` parameter to true, you can create the
- * named directory and all its necessary parent directories,
- * if they do not already exist.
- *
- *     import 'dart:io';
- *
- *     void main() {
- *       // Creates dir/ and dir/subdir/.
- *       new Directory('dir/subdir').create(recursive: true)
- *         // The created directory is returned as a Future.
- *         .then((Directory directory) {
- *           print(directory.path);
- *       });
- *     }
- *
- * ## List a directory
- *
- * Use the [list] or [listSync] methods to get the files and directories
- * contained by a directory.
- * Set `recursive` to true to recursively list all subdirectories.
- * Set `followLinks` to true to follow symbolic links.
- * The list method returns a [Stream] that provides FileSystemEntity
- * objects. Use the listen callback function to process each object
- * as it become available.
- *
- *     import 'dart:io';
- *
- *     void main() {
- *       // Get the system temp directory.
- *       var systemTempDir = Directory.systemTemp;
- *
- *       // List directory contents, recursing into sub-directories,
- *       // but not following symbolic links.
- *       systemTempDir.list(recursive: true, followLinks: false)
- *         .listen((FileSystemEntity entity) {
- *           print(entity.path);
- *         });
- *     }
- *
- * ## The use of Futures
- *
- * I/O operations can block a program for some period of time while it waits for
- * the operation to complete. To avoid this, all
- * methods involving I/O have an asynchronous variant which returns a [Future].
- * This future completes when the I/O operation finishes. While the I/O
- * operation is in progress, the Dart program is not blocked,
- * and can perform other operations.
- *
- * For example,
- * the [exists] method, which determines whether the directory exists,
- * returns a boolean value using a Future.
- * Use `then` to register a callback function, which is called when
- * the value is ready.
- *
- *     import 'dart:io';
- *
- *     main() {
- *       final myDir = new Directory('dir');
- *       myDir.exists().then((isThere) {
- *         isThere ? print('exists') : print('non-existent');
- *       });
- *     }
- *
- *
- * In addition to exists, the [stat], [rename], and
- * other methods, return Futures.
- *
- * ## Other resources
- *
- * * The [Files and directories](https://dart.dev/guides/libraries/library-tour#files-and-directories)
- *   section of the library tour.
- *
- * * [Write Command-Line Apps](https://dart.dev/tutorials/server/cmdline),
- *   a tutorial about writing command-line apps, includes information about
- *   files and directories.
- */
+/// A reference to a directory (or _folder_) on the file system.
+///
+/// A [Directory] is an object holding a [path] on which operations can
+/// be performed. The path to the directory can be [absolute] or relative.
+/// It allows access to the [parent] directory,
+/// since it is a [FileSystemEntity].
+///
+/// The [Directory] also provides static access to the system's temporary
+/// file directory, [systemTemp], and the ability to access and change
+/// the [current] directory.
+///
+/// Create a new [Directory] to give access the directory with the specified
+/// path:
+/// ```dart
+/// var myDir = Directory('myDir');
+/// ```
+/// Most intance methods of [Directory] exist in both synchronous
+/// and asynchronous variants, for example, [create] and [createSync].
+/// Unless you have a specific reason for using the synchronous version
+/// of a method, prefer the asynchronous version to avoid blocking your program.
+///
+/// ## Create a directory
+///
+/// The following code sample creates a directory using the [create] method.
+/// By setting the `recursive` parameter to true, you can create the
+/// named directory and all its necessary parent directories,
+/// if they do not already exist.
+/// ```dart
+/// import 'dart:io';
+///
+/// void main() async {
+///   // Creates dir/ and dir/subdir/.
+///   var directory = await Directory('dir/subdir').create(recursive: true)
+///   print(directory.path);
+/// }
+/// ```
+/// ## List the entries of a directory
+///
+/// Use the [list] or [listSync] methods to get the files and directories
+/// contained in a directory.
+/// Set `recursive` to true to recursively list all subdirectories.
+/// Set `followLinks` to true to follow symbolic links.
+/// The list method returns a [Stream] of [FileSystemEntity] objects.
+/// Listen on the stream to access each object as it is found:
+/// ```dart
+/// import 'dart:io';
+///
+/// void main() async {
+///   // Get the system temp directory.
+///   var systemTempDir = Directory.systemTemp;
+///
+///   // List directory contents, recursing into sub-directories,
+///   // but not following symbolic links.
+///   await for (var entity in
+///       systemTempDir.list(recursive: true, followLinks: false)) {
+///     print(entity.path);
+///   }
+/// }
+/// ```
+/// ## The use of asynchronnous methods
+///
+/// I/O operations can block a program for some period of time while it waits for
+/// the operation to complete. To avoid this, all
+/// methods involving I/O have an asynchronous variant which returns a [Future].
+/// This future completes when the I/O operation finishes. While the I/O
+/// operation is in progress, the Dart program is not blocked,
+/// and can perform other operations.
+///
+/// For example,
+/// the [exists] method, which determines whether the directory exists,
+/// returns a boolean value asynchronously using a [Future].
+/// ```dart
+/// import 'dart:io';
+///
+/// void main() async {
+///   final myDir = Directory('dir');
+///   var isThere = await myDir.exists();
+///   print(isThere ? 'exists' : 'non-existent');
+/// }
+/// ```
+///
+/// In addition to [exists], the [stat], [rename],
+/// and other methods are also asynchronous.
+///
+/// ## Other resources
+///
+/// * The [Files and directories](https://dart.dev/guides/libraries/library-tour#files-and-directories)
+///   section of the library tour.
+///
+/// * [Write Command-Line Apps](https://dart.dev/tutorials/server/cmdline),
+///   a tutorial about writing command-line apps, includes information about
+///   files and directories.
 @pragma("vm:entry-point")
 abstract class Directory implements FileSystemEntity {
-  /**
-   * Gets the path of this directory.
-   */
+  /// Gets the path of this directory.
   String get path;
 
-  /**
-   * Creates a [Directory] object.
-   *
-   * If [path] is a relative path, it will be interpreted relative to the
-   * current working directory (see [Directory.current]), when used.
-   *
-   * If [path] is an absolute path, it will be immune to changes to the
-   * current working directory.
-   */
+  /// Creates a [Directory] object.
+  ///
+  /// If [path] is a relative path, it will be interpreted relative to the
+  /// current working directory (see [Directory.current]), when used.
+  ///
+  /// If [path] is an absolute path, it will be immune to changes to the
+  /// current working directory.
   @pragma("vm:entry-point")
   factory Directory(String path) {
     final IOOverrides? overrides = IOOverrides.current;
@@ -137,17 +123,13 @@
     return new _Directory.fromRawPath(path);
   }
 
-  /**
-   * Create a Directory object from a URI.
-   *
-   * If [uri] cannot reference a directory this throws [UnsupportedError].
-   */
+  /// Create a [Directory] from a URI.
+  ///
+  /// If [uri] cannot reference a directory this throws [UnsupportedError].
   factory Directory.fromUri(Uri uri) => new Directory(uri.toFilePath());
 
-  /**
-   * Creates a directory object pointing to the current working
-   * directory.
-   */
+  /// Creates a directory object pointing to the current working
+  /// directory.
   static Directory get current {
     final IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
@@ -156,33 +138,30 @@
     return overrides.getCurrentDirectory();
   }
 
-  /**
-   * Returns a [Uri] representing the directory's location.
-   *
-   * The returned URI's scheme is always "file" if the entity's [path] is
-   * absolute, otherwise the scheme will be empty.
-   * The returned URI's path always ends in a slash ('/').
-   */
+  /// A [Uri] representing the directory's location.
+  ///
+  /// The URI's scheme is always "file" if the entity's [path] is
+  /// absolute, otherwise the scheme will be empty and the URI relative.
+  /// The URI's path always ends in a slash ('/').
   Uri get uri;
 
-  /**
-   * Sets the current working directory of the Dart process including
-   * all running isolates. The new value set can be either a [Directory]
-   * or a [String].
-   *
-   * The new value is passed to the OS's system call unchanged, so a
-   * relative path passed as the new working directory will be
-   * resolved by the OS.
-   *
-   * Note that setting the current working directory is a synchronous
-   * operation and that it changes the working directory of *all*
-   * isolates.
-   *
-   * Use this with care - especially when working with asynchronous
-   * operations and multiple isolates. Changing the working directory,
-   * while asynchronous operations are pending or when other isolates
-   * are working with the file system, can lead to unexpected results.
-   */
+  /// Sets the current working directory of the Dart process.
+  ///
+  /// This affects all running isolates.
+  /// The new value set can be either a [Directory] or a [String].
+  ///
+  /// The new value is passed to the OS's system call unchanged, so a
+  /// relative path passed as the new working directory will be
+  /// resolved by the OS.
+  ///
+  /// Note that setting the current working directory is a synchronous
+  /// operation and that it changes the working directory of *all*
+  /// isolates.
+  ///
+  /// Use this with care — especially when working with asynchronous
+  /// operations and multiple isolates. Changing the working directory,
+  /// while asynchronous operations are pending or when other isolates
+  /// are working with the file system, can lead to unexpected results.
   static void set current(path) {
     final IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
@@ -192,38 +171,32 @@
     overrides.setCurrentDirectory(path);
   }
 
-  /**
-   * Creates the directory with this name.
-   *
-   * If [recursive] is false, only the last directory in the path is
-   * created. If [recursive] is true, all non-existing path components
-   * are created. If the directory already exists nothing is done.
-   *
-   * Returns a [:Future<Directory>:] that completes with this
-   * directory once it has been created. If the directory cannot be
-   * created the future completes with an exception.
-   */
-  Future<Directory> create({bool recursive: false});
+  /// Creates the directory if it doesn't exist.
+  ///
+  /// If [recursive] is false, only the last directory in the path is
+  /// created. If [recursive] is true, all non-existing path components
+  /// are created. If the directory already exists nothing is done.
+  ///
+  /// Returns a `Future<Directory>` that completes with this
+  /// directory once it has been created. If the directory cannot be
+  /// created the future completes with an exception.
+  Future<Directory> create({bool recursive = false});
 
-  /**
-   * Synchronously creates the directory with this name.
-   *
-   * If [recursive] is false, only the last directory in the path is
-   * created. If [recursive] is true, all non-existing path components
-   * are created. If the directory already exists nothing is done.
-   *
-   * If the directory cannot be created an exception is thrown.
-   */
-  void createSync({bool recursive: false});
+  /// Synchronously creates the directory if it doesn't exist.
+  ///
+  /// If [recursive] is false, only the last directory in the path is
+  /// created. If [recursive] is true, all non-existing path components
+  /// are created. If the directory already exists nothing is done.
+  ///
+  /// If the directory cannot be created an exception is thrown.
+  void createSync({bool recursive = false});
 
-  /**
-   * Gets the system temp directory.
-   *
-   * Gets the directory provided by the operating system for creating
-   * temporary files and directories in.
-   * The location of the system temp directory is platform-dependent,
-   * and may be set by an environment variable.
-   */
+  /// The system temp directory.
+  ///
+  /// This is the directory provided by the operating system for creating
+  /// temporary files and directories in.
+  /// The location of the system temporary directory is platform-dependent,
+  /// and may be controlled by an environment variable on some platforms.
   static Directory get systemTemp {
     final IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
@@ -232,108 +205,104 @@
     return overrides.getSystemTempDirectory();
   }
 
-  /**
-   * Creates a temporary directory in this directory. Additional random
-   * characters are appended to [prefix] to produce a unique directory
-   * name. If [prefix] is missing or null, the empty string is used
-   * for [prefix].
-   *
-   * Returns a [:Future<Directory>:] that completes with the newly
-   * created temporary directory.
-   */
+  /// Creates a temporary directory in this directory.
+  ///
+  /// Additional random characters are appended to [prefix]
+  /// to produce a unique directory name.
+  /// If [prefix] is missing or null, the empty string is used as [prefix].
+  ///
+  /// Returns a `Future<Directory>` that completes with the newly
+  /// created temporary directory.
   Future<Directory> createTemp([String? prefix]);
 
-  /**
-   * Synchronously creates a temporary directory in this directory.
-   * Additional random characters are appended to [prefix] to produce
-   * a unique directory name. If [prefix] is missing or null, the empty
-   * string is used for [prefix].
-   *
-   * Returns the newly created temporary directory.
-   */
+  /// Synchronously creates a temporary directory in this directory.
+  ///
+  /// Additional random characters are appended to [prefix] to produce
+  /// a unique directory name. If [prefix] is missing or null, the empty
+  /// string is used as [prefix].
+  ///
+  /// Returns the newly created temporary directory.
   Directory createTempSync([String? prefix]);
 
   Future<String> resolveSymbolicLinks();
 
   String resolveSymbolicLinksSync();
 
-  /**
-   * Renames this directory. Returns a [:Future<Directory>:] that completes
-   * with a [Directory] instance for the renamed directory.
-   *
-   * If newPath identifies an existing directory, that directory is
-   * replaced. If newPath identifies an existing file, the operation
-   * fails and the future completes with an exception.
-   */
+  /// Renames this directory.
+  ///
+  /// Returns a `Future<Directory>` that completes
+  /// with a [Directory] for the renamed directory.
+  ///
+  /// If [newPath] identifies an existing directory, that directory is
+  /// removed first.
+  /// If [newPath] identifies an existing file, the operation
+  /// fails and the future completes with an exception.
   Future<Directory> rename(String newPath);
 
-  /**
-   * Synchronously renames this directory. Returns a [Directory]
-   * instance for the renamed directory.
-   *
-   * If newPath identifies an existing directory, that directory is
-   * replaced. If newPath identifies an existing file the operation
-   * fails and an exception is thrown.
-   */
+  /// Synchronously renames this directory.
+  ///
+  /// Returns a [Directory] for the renamed directory.
+  ///
+  /// If [newPath] identifies an existing directory, that directory is
+  /// removed first.
+  /// If [newPath] identifies an existing file the operation
+  /// fails and an exception is thrown.
   Directory renameSync(String newPath);
 
-  /**
-   * Returns a [Directory] instance whose path is the absolute path to [this].
-   *
-   * The absolute path is computed by prefixing
-   * a relative path with the current working directory, and returning
-   * an absolute path unchanged.
-   */
+  /// A [Directory] whose path is the absolute path of [this].
+  ///
+  /// The absolute path is computed by prefixing
+  /// a relative path with the current working directory,
+  /// or by returning an absolute path unchanged.
   Directory get absolute;
 
-  /**
-   * Lists the sub-directories and files of this [Directory].
-   * Optionally recurses into sub-directories.
-   *
-   * If [followLinks] is false, then any symbolic links found
-   * are reported as [Link] objects, rather than as directories or files,
-   * and are not recursed into.
-   *
-   * If [followLinks] is true, then working links are reported as
-   * directories or files, depending on
-   * their type, and links to directories are recursed into.
-   * Broken links are reported as [Link] objects.
-   * If a symbolic link makes a loop in the file system, then a recursive
-   * listing will not follow a link twice in the
-   * same recursive descent, but will report it as a [Link]
-   * the second time it is seen.
-   *
-   * The result is a stream of [FileSystemEntity] objects
-   * for the directories, files, and links.
-   */
+  /// Lists the sub-directories and files of this [Directory].
+  ///
+  /// Optionally recurses into sub-directories.
+  ///
+  /// If [followLinks] is `false`, then any symbolic links found
+  /// are reported as [Link] objects, rather than as directories or files,
+  /// and are not recursed into.
+  ///
+  /// If [followLinks] is `true`, then working links are reported as
+  /// directories or files, depending on what they point to,
+  /// and links to directories are recursed into f [recursive] is `true`.
+  ///
+  /// Broken links are reported as [Link] objects.
+  ///
+  /// If a symbolic link makes a loop in the file system, then a recursive
+  /// listing will not follow a link twice in the
+  /// same recursive descent, but will report it as a [Link]
+  /// the second time it is seen.
+  ///
+  /// The result is a stream of [FileSystemEntity] objects
+  /// for the directories, files, and links.
   Stream<FileSystemEntity> list(
-      {bool recursive: false, bool followLinks: true});
+      {bool recursive = false, bool followLinks = true});
 
-  /**
-   * Lists the sub-directories and files of this [Directory].
-   * Optionally recurses into sub-directories.
-   *
-   * If [followLinks] is false, then any symbolic links found
-   * are reported as [Link] objects, rather than as directories or files,
-   * and are not recursed into.
-   *
-   * If [followLinks] is true, then working links are reported as
-   * directories or files, depending on
-   * their type, and links to directories are recursed into.
-   * Broken links are reported as [Link] objects.
-   * If a link makes a loop in the file system, then a recursive
-   * listing will not follow a link twice in the
-   * same recursive descent, but will report it as a [Link]
-   * the second time it is seen.
-   *
-   * Returns a [List] containing [FileSystemEntity] objects for the
-   * directories, files, and links.
-   */
+  /// Lists the sub-directories and files of this [Directory].
+  /// Optionally recurses into sub-directories.
+  ///
+  /// If [followLinks] is `false`, then any symbolic links found
+  /// are reported as [Link] objects, rather than as directories or files,
+  /// and are not recursed into.
+  ///
+  /// If [followLinks] is `true`, then working links are reported as
+  /// directories or files, depending on what they point to,
+  /// and links to directories are recursed into if `recursive` is `true`.
+  ///
+  /// Broken links are reported as [Link] objects.
+  ///
+  /// If a link makes a loop in the file system, then a recursive
+  /// listing will not follow a link twice in the
+  /// same recursive descent, but will report it as a [Link]
+  /// the second time it is seen.
+  ///
+  /// Returns a [List] containing [FileSystemEntity] objects for the
+  /// directories, files, and links.
   List<FileSystemEntity> listSync(
-      {bool recursive: false, bool followLinks: true});
+      {bool recursive = false, bool followLinks = true});
 
-  /**
-   * Returns a human readable string for this Directory instance.
-   */
+  /// Returns a human readable representation of this [Directory].
   String toString();
 }
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 0a356e1..d3bc43f 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -98,7 +98,7 @@
 
   Directory get absolute => new Directory(_absolutePath);
 
-  Future<Directory> create({bool recursive: false}) {
+  Future<Directory> create({bool recursive = false}) {
     if (recursive) {
       return exists().then((exists) {
         if (exists) return this;
@@ -121,7 +121,7 @@
     }
   }
 
-  void createSync({bool recursive: false}) {
+  void createSync({bool recursive = false}) {
     if (recursive) {
       if (existsSync()) return;
       if (path != parent.path) {
@@ -184,7 +184,7 @@
     return new Directory(result);
   }
 
-  Future<Directory> _delete({bool recursive: false}) {
+  Future<Directory> _delete({bool recursive = false}) {
     return _File._dispatchWithNamespace(
             _IOService.directoryDelete, [null, _rawPath, recursive])
         .then((response) {
@@ -195,7 +195,7 @@
     });
   }
 
-  void _deleteSync({bool recursive: false}) {
+  void _deleteSync({bool recursive = false}) {
     var result = _deleteNative(_Namespace._namespace, _rawPath, recursive);
     if (result is OSError) {
       throw new FileSystemException("Deletion failed", path, result);
@@ -223,7 +223,7 @@
   }
 
   Stream<FileSystemEntity> list(
-      {bool recursive: false, bool followLinks: true}) {
+      {bool recursive = false, bool followLinks = true}) {
     return new _AsyncDirectoryLister(
             // FIXME(bkonyi): here we're using `path` directly, which might cause issues
             // if it is not UTF-8 encoded.
@@ -235,7 +235,7 @@
   }
 
   List<FileSystemEntity> listSync(
-      {bool recursive: false, bool followLinks: true}) {
+      {bool recursive = false, bool followLinks = true}) {
     // TODO(40614): Remove once non-nullability is sound.
     ArgumentError.checkNotNull(recursive, "recursive");
     ArgumentError.checkNotNull(followLinks, "followLinks");
diff --git a/sdk/lib/io/embedder_config.dart b/sdk/lib/io/embedder_config.dart
index 2042aa5..fcac6d1 100644
--- a/sdk/lib/io/embedder_config.dart
+++ b/sdk/lib/io/embedder_config.dart
@@ -4,35 +4,36 @@
 
 part of dart.io;
 
-/// Embedder-specific, fine-grained dart:io configuration.
+/// Embedder-specific, fine-grained `dart:io` configuration.
 ///
 /// This class contains per-Isolate flags that an embedder can set to put
 /// fine-grained limitations on what process-visible operations Isolates are
-/// permitted to use (e.g. exit()). By default, the whole dart:io API is
+/// permitted to use (e.g. [exit]). By default, the whole `dart:io` API is
 /// enabled. When a disallowed operation is attempted, an `UnsupportedError` is
 /// thrown.
 @pragma('vm:entry-point')
 abstract class _EmbedderConfig {
-  /// The Isolate may set Directory.current.
+  /// Whether the isolate may set [Directory.current].
   static bool _mayChdir = true;
 
-  /// The Isolate may call exit().
+  /// Whether the isolate may call [exit].
   @pragma("vm:entry-point")
   static bool _mayExit = true;
 
-  // The Isolate may set Stdin.echoMode.
+  // Whether the isolate may set [Stdin.echoMode].
   @pragma('vm:entry-point')
   static bool _maySetEchoMode = true;
 
-  // The Isolate may set Stdin.lineMode.
+  // Whether the isolate may set [Stdin.lineMode].
   @pragma('vm:entry-point')
   static bool _maySetLineMode = true;
 
-  /// The Isolate may call sleep().
+  /// Whether the isolate may call [sleep].
   @pragma('vm:entry-point')
   static bool _maySleep = true;
 
-  /// The Isolate may establish insecure socket connections to all domains.
+  /// Whether the isolate may establish insecure socket connections
+  /// to all domains.
   ///
   /// This setting can be overridden by per-domain policies.
   @pragma('vm:entry-point')
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 9c1f2f5..14d68bb 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -4,9 +4,7 @@
 
 part of dart.io;
 
-/**
- * The modes in which a File can be opened.
- */
+/// The modes in which a [File] can be opened.
 class FileMode {
   /// The mode for opening a file only for reading.
   static const read = const FileMode._internal(0);
@@ -97,152 +95,144 @@
   const FileLock._internal(this._type);
 }
 
-/**
- * A reference to a file on the file system.
- *
- * A File instance is an object that holds a [path] on which operations can
- * be performed.
- * You can get the parent directory of the file using the getter [parent],
- * a property inherited from [FileSystemEntity].
- *
- * Create a new File object with a pathname to access the specified file on the
- * file system from your program.
- *
- *     var myFile = new File('file.txt');
- *
- * The File class contains methods for manipulating files and their contents.
- * Using methods in this class, you can open and close files, read to and write
- * from them, create and delete them, and check for their existence.
- *
- * When reading or writing a file, you can use streams (with [openRead]),
- * random access operations (with [open]),
- * or convenience methods such as [readAsString],
- *
- * Most methods in this class occur in synchronous and asynchronous pairs,
- * for example, [readAsString] and [readAsStringSync].
- * Unless you have a specific reason for using the synchronous version
- * of a method, prefer the asynchronous version to avoid blocking your program.
- *
- * ## If path is a link
- *
- * If [path] is a symbolic link, rather than a file,
- * then the methods of File operate on the ultimate target of the
- * link, except for [delete] and [deleteSync], which operate on
- * the link.
- *
- * ## Read from a file
- *
- * The following code sample reads the entire contents from a file as a string
- * using the asynchronous [readAsString] method:
- *
- *     import 'dart:async';
- *     import 'dart:io';
- *
- *     void main() {
- *       new File('file.txt').readAsString().then((String contents) {
- *         print(contents);
- *       });
- *     }
- *
- * A more flexible and useful way to read a file is with a [Stream].
- * Open the file with [openRead], which returns a stream that
- * provides the data in the file as chunks of bytes.
- * Listen to the stream for data and process as needed.
- * You can use various transformers in succession to manipulate the
- * data into the required format or to prepare it for output.
- *
- * You might want to use a stream to read large files,
- * to manipulate the data with transformers,
- * or for compatibility with another API, such as [WebSocket]s.
- *
- *     import 'dart:io';
- *     import 'dart:convert';
- *     import 'dart:async';
- *
- *     main() {
- *       final file = new File('file.txt');
- *       Stream<List<int>> inputStream = file.openRead();
- *
- *       inputStream
- *         .transform(utf8.decoder)       // Decode bytes to UTF-8.
- *         .transform(new LineSplitter()) // Convert stream to individual lines.
- *         .listen((String line) {        // Process results.
- *             print('$line: ${line.length} bytes');
- *           },
- *           onDone: () { print('File is now closed.'); },
- *           onError: (e) { print(e.toString()); });
- *     }
- *
- * ## Write to a file
- *
- * To write a string to a file, use the [writeAsString] method:
- *
- *     import 'dart:io';
- *
- *     void main() {
- *       final filename = 'file.txt';
- *       new File(filename).writeAsString('some content')
- *         .then((File file) {
- *           // Do something with the file.
- *         });
- *     }
- *
- * You can also write to a file using a [Stream]. Open the file with
- * [openWrite], which returns an [IOSink] to which you can write data.
- * Be sure to close the sink with the [IOSink.close] method.
- *
- *     import 'dart:io';
- *
- *     void main() {
- *       var file = new File('file.txt');
- *       var sink = file.openWrite();
- *       sink.write('FILE ACCESSED ${new DateTime.now()}\n');
- *
- *       // Close the IOSink to free system resources.
- *       sink.close();
- *     }
- *
- * ## The use of Futures
- *
- * To avoid unintentional blocking of the program,
- * several methods use a [Future] to return a value. For example,
- * the [length] method, which gets the length of a file, returns a Future.
- * Use `then` to register a callback function, which is called when
- * the value is ready.
- *
- *     import 'dart:io';
- *
- *     main() {
- *       final file = new File('file.txt');
- *
- *       file.length().then((len) {
- *         print(len);
- *       });
- *     }
- *
- * In addition to length, the [exists], [lastModified], [stat], and
- * other methods, return Futures.
- *
- * ## Other resources
- *
- * * The [Files and directories](https://dart.dev/guides/libraries/library-tour#files-and-directories)
- *   section of the library tour.
- *
- * * [Write Command-Line Apps](https://dart.dev/tutorials/server/cmdline),
- *   a tutorial about writing command-line apps, includes information about
- *   files and directories.
- */
+/// A reference to a file on the file system.
+///
+/// A `File` holds a [path] on which operations can be performed.
+/// You can get the parent directory of the file using [parent],
+/// a property inherited from [FileSystemEntity].
+///
+/// Create a new `File` object with a pathname to access the specified file on the
+/// file system from your program.
+/// ```dart
+/// var myFile = File('file.txt');
+/// ```
+/// The `File` class contains methods for manipulating files and their contents.
+/// Using methods in this class, you can open and close files, read to and write
+/// from them, create and delete them, and check for their existence.
+///
+/// When reading or writing a file, you can use streams (with [openRead]),
+/// random access operations (with [open]),
+/// or convenience methods such as [readAsString],
+///
+/// Most methods in this class occur in synchronous and asynchronous pairs,
+/// for example, [readAsString] and [readAsStringSync].
+/// Unless you have a specific reason for using the synchronous version
+/// of a method, prefer the asynchronous version to avoid blocking your program.
+///
+/// ## If path is a link
+///
+/// If [path] is a symbolic link, rather than a file,
+/// then the methods of `File` operate on the ultimate target of the
+/// link, except for [delete] and [deleteSync], which operate on
+/// the link.
+///
+/// ## Read from a file
+///
+/// The following code sample reads the entire contents from a file as a string
+/// using the asynchronous [readAsString] method:
+/// ```dart
+/// import 'dart:async';
+/// import 'dart:io';
+///
+/// void main() {
+///   File('file.txt').readAsString().then((String contents) {
+///     print(contents);
+///   });
+/// }
+/// ```
+/// A more flexible and useful way to read a file is with a [Stream].
+/// Open the file with [openRead], which returns a stream that
+/// provides the data in the file as chunks of bytes.
+/// Read the stream to process the file contents when available.
+/// You can use various transformers in succession to manipulate the
+/// file content into the required format, or to prepare it for output.
+///
+/// You might want to use a stream to read large files,
+/// to manipulate the data with transformers,
+/// or for compatibility with another API, such as [WebSocket]s.
+/// ```dart
+/// import 'dart:io';
+/// import 'dart:convert';
+/// import 'dart:async';
+///
+/// void main() async {
+///   final file = File('file.txt');
+///   Stream<String> lines = file.openRead()
+///     .transform(utf8.decoder)       // Decode bytes to UTF-8.
+///     .transform(LineSplitter());    // Convert stream to individual lines.
+///   try {
+///     await for (var line in lines) {
+///       print('$line: ${line.length} characters');
+///     }
+///     print('File is now closed.');
+///   } catch (e) {
+///     print('Error: $e');
+///   }
+/// }
+/// ```
+/// ## Write to a file
+///
+/// To write a string to a file, use the [writeAsString] method:
+/// ```dart
+/// import 'dart:io';
+///
+/// void main() async {
+///   final filename = 'file.txt';
+///   var file = await File(filename).writeAsString('some content');
+///   // Do something with the file.
+/// }
+/// ```
+/// You can also write to a file using a [Stream]. Open the file with
+/// [openWrite], which returns an [IOSink] to which you can write data.
+/// Be sure to close the sink with the [IOSink.close] method.
+/// ```dart
+/// import 'dart:io';
+///
+/// void main() {
+///   var file = File('file.txt');
+///   var sink = file.openWrite();
+///   sink.write('FILE ACCESSED ${DateTime.now()}\n');
+///
+///   // Close the IOSink to free system resources.
+///   sink.close();
+/// }
+/// ```
+/// ## The use of asynchronous methods
+///
+/// To avoid unintentional blocking of the program,
+/// several methods are asynchronous and return a [Future]. For example,
+/// the [length] method, which gets the length of a file, returns a [Future].
+/// Wait for the future to get the result when it's ready.
+/// ```dart
+/// import 'dart:io';
+///
+/// void main() async {
+///   final file = File('file.txt');
+///
+///   var length = await file.length();
+///   print(length);
+/// }
+/// ```
+/// In addition to length, the [exists], [lastModified], [stat], and
+/// other methods, are asynchronous.
+///
+/// ## Other resources
+///
+/// * The [Files and directories](https://dart.dev/guides/libraries/library-tour#files-and-directories)
+///   section of the library tour.
+///
+/// * [Write Command-Line Apps](https://dart.dev/tutorials/server/cmdline),
+///   a tutorial about writing command-line apps, includes information about
+///   files and directories.
 @pragma("vm:entry-point")
 abstract class File implements FileSystemEntity {
-  /**
-   * Creates a [File] object.
-   *
-   * If [path] is a relative path, it will be interpreted relative to the
-   * current working directory (see [Directory.current]), when used.
-   *
-   * If [path] is an absolute path, it will be immune to changes to the
-   * current working directory.
-   */
+  /// Creates a [File] object.
+  ///
+  /// If [path] is a relative path, it will be interpreted relative to the
+  /// current working directory (see [Directory.current]), when used.
+  ///
+  /// If [path] is an absolute path, it will be immune to changes to the
+  /// current working directory.
   @pragma("vm:entry-point")
   factory File(String path) {
     final IOOverrides? overrides = IOOverrides.current;
@@ -252,733 +242,686 @@
     return overrides.createFile(path);
   }
 
-  /**
-   * Create a File object from a URI.
-   *
-   * If [uri] cannot reference a file this throws [UnsupportedError].
-   */
+  /// Create a [File] object from a URI.
+  ///
+  /// If [uri] cannot reference a file this throws [UnsupportedError].
   factory File.fromUri(Uri uri) => new File(uri.toFilePath());
 
-  /**
-   * Creates a File object from a raw path, that is, a sequence of bytes
-   * as represented by the OS.
-   */
+  /// Creates a [File] object from a raw path.
+  ///
+  /// A raw path is a sequence of bytes, as paths are represented by the OS.
   @pragma("vm:entry-point")
   factory File.fromRawPath(Uint8List rawPath) {
     // TODO(bkonyi): Handle overrides.
     return new _File.fromRawPath(rawPath);
   }
 
-  /**
-   * Create the file. Returns a `Future<File>` that completes with
-   * the file when it has been created.
-   *
-   * If [recursive] is false, the default, the file is created only if
-   * all directories in the path exist. If [recursive] is true, all
-   * non-existing path components are created.
-   *
-   * Existing files are left untouched by [create]. Calling [create] on an
-   * existing file might fail if there are restrictive permissions on
-   * the file.
-   *
-   * Completes the future with a [FileSystemException] if the operation fails.
-   */
-  Future<File> create({bool recursive: false});
+  /// Creates the file.
+  ///
+  /// Returns a `Future<File>` that completes with
+  /// the file when it has been created.
+  ///
+  /// If [recursive] is `false`, the default, the file is created only if
+  /// all directories in its path alredy exist. If [recursive] is `true`, any
+  /// non-existing parent paths are created first.
+  ///
+  /// Existing files are left untouched by [create]. Calling [create] on an
+  /// existing file might fail if there are restrictive permissions on
+  /// the file.
+  ///
+  /// Completes the future with a [FileSystemException] if the operation fails.
+  Future<File> create({bool recursive = false});
 
-  /**
-   * Synchronously create the file. Existing files are left untouched
-   * by [createSync]. Calling [createSync] on an existing file might fail
-   * if there are restrictive permissions on the file.
-   *
-   * If [recursive] is false, the default, the file is created
-   * only if all directories in the path exist.
-   * If [recursive] is true, all non-existing path components are created.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
-  void createSync({bool recursive: false});
+  /// Synchronously creates the file.
+  ///
+  /// Existing files are left untouched by [createSync].
+  /// Calling [createSync] on an existing file might fail
+  /// if there are restrictive permissions on the file.
+  ///
+  /// If [recursive] is `false`, the default, the file is created
+  /// only if all directories in its path already exist.
+  /// If [recursive] is `true`, all non-existing parent paths are created first.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
+  void createSync({bool recursive = false});
 
-  /**
-   * Renames this file. Returns a `Future<File>` that completes
-   * with a [File] instance for the renamed file.
-   *
-   * If [newPath] identifies an existing file, that file is
-   * replaced. If [newPath] identifies an existing directory, the
-   * operation fails and the future completes with an exception.
-   */
+  /// Renames this file.
+  ///
+  /// Returns a `Future<File>` that completes
+  /// with a [File] for the renamed file.
+  ///
+  /// If [newPath] is a relative path, it is resolved against
+  /// the current working directory ([Directory.cwd]).
+  /// This means that simply changing the name of a file,
+  /// but keeping it the original directory,
+  /// requires creating a new complete path with the new name
+  /// at the end. Example:
+  /// ```dart
+  /// Future<File> changeFileNameOnly(File file, String newFileName) {
+  ///   var path = file.path;
+  ///   var lastSeparator = path.lastIndexOf(Platform.pathSeparator);
+  ///   var newPath = path.substring(0, lastSeparator + 1) + newFileName;
+  ///   return file.rename(newPath);
+  /// }
+  /// ```
+  /// On some platforms, a rename operation cannot move a file between
+  /// different file systems. If that is the case, instead [copy] the
+  /// file to the new location and then [remove] the original.
+  ///
+  /// If [newPath] identifies an existing file, that file is
+  /// removed first. If [newPath] identifies an existing directory, the
+  /// operation fails and the future completes with an exception.
   Future<File> rename(String newPath);
 
-  /**
-   * Synchronously renames this file. Returns a [File]
-   * instance for the renamed file.
-   *
-   * If [newPath] identifies an existing file, that file is
-   * replaced. If [newPath] identifies an existing directory the
-   * operation fails and an exception is thrown.
-   */
+  /// Synchronously renames this file.
+  ///
+  /// Returns a [File] for the renamed file.
+  ///
+  /// If [newPath] is a relative path, it is resolved against
+  /// the current working directory ([Directory.cwd]).
+  /// This means that simply changing the name of a file,
+  /// but keeping it the original directory,
+  /// requires creating a new complete path with the new name
+  /// at the end. Example:
+  /// ```dart
+  /// File changeFileNameOnlySync(File file, String newFileName) {
+  ///   var path = file.path;
+  ///   var lastSeparator = path.lastIndexOf(Platform.pathSeparator);
+  ///   var newPath = path.substring(0, lastSeparator + 1) + newFileName;
+  ///   return file.renameSync(newPath);
+  /// }
+  /// ```
+  /// On some platforms, a rename operation cannot move a file between
+  /// different file systems. If that is the case, instead [copySync] the
+  /// file to the new location and then [removeSync] the original.
+  ///
+  /// If [newPath] identifies an existing file, that file is
+  /// removed first. If [newPath] identifies an existing directory the
+  /// operation fails and an exception is thrown.
   File renameSync(String newPath);
 
-  /**
-   * Copy this file. Returns a `Future<File>` that completes
-   * with a [File] instance for the copied file.
-   *
-   * If [newPath] identifies an existing file, that file is
-   * replaced. If [newPath] identifies an existing directory, the
-   * operation fails and the future completes with an exception.
-   */
+  /// Copies this file.
+  ///
+  /// If [newPath] is a relative path, it is resolved against
+  /// the current working directory ([Directory.cwd]).
+  ///
+  /// Returns a `Future<File>` that completes
+  /// with a [File] for the copied file.
+  ///
+  /// If [newPath] identifies an existing file, that file is
+  /// removed first. If [newPath] identifies an existing directory, the
+  /// operation fails and the future completes with an exception.
   Future<File> copy(String newPath);
 
-  /**
-   * Synchronously copy this file. Returns a [File]
-   * instance for the copied file.
-   *
-   * If [newPath] identifies an existing file, that file is
-   * replaced. If [newPath] identifies an existing directory the
-   * operation fails and an exception is thrown.
-   */
+  /// Synchronously copies this file.
+  ///
+  /// If [newPath] is a relative path, it is resolved against
+  /// the current working directory ([Directory.cwd]).
+  ///
+  /// Returns a [File] for the copied file.
+  ///
+  /// If [newPath] identifies an existing file, that file is
+  /// removed first. If [newPath] identifies an existing directory the
+  /// operation fails and an exception is thrown.
   File copySync(String newPath);
 
-  /**
-   * Get the length of the file. Returns a `Future<int>` that
-   * completes with the length in bytes.
-   */
+  /// The length of the file.
+  ///
+  /// Returns a `Future<int>` that completes with the length in bytes.
   Future<int> length();
 
-  /**
-   * Synchronously get the length of the file.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// The length of the file provided synchronously.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   int lengthSync();
 
-  /**
-   * Returns a [File] instance whose path is the absolute path to [this].
-   *
-   * The absolute path is computed by prefixing
-   * a relative path with the current working directory, and returning
-   * an absolute path unchanged.
-   */
+  /// A [File] with the absolute path of [path].
+  ///
+  /// The absolute path is computed by prefixing
+  /// a relative path with the current working directory,
+  /// or returning an absolute path unchanged.
   File get absolute;
 
-/**
- * Get the last-accessed time of the file.
- *
- * Returns a `Future<DateTime>` that completes with the date and time when the
- * file was last accessed, if the information is available.
- *
- * Throws a [FileSystemException] if the operation fails.
- */
+  /// The last-accessed time of the file.
+  ///
+  /// Returns a `Future<DateTime>` that completes with the date and time when the
+  /// file was last accessed, if the information is available.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   Future<DateTime> lastAccessed();
 
-/**
- * Get the last-accessed time of the file.
- *
- * Returns the date and time when the file was last accessed,
- * if the information is available. Blocks until the information can be returned
- * or it is determined that the information is not available.
- *
- * Throws a [FileSystemException] if the operation fails.
- */
+  /// The last-accessed time of the file.
+  ///
+  /// Returns the date and time when the file was last accessed,
+  /// if the information is available. Blocks until the information can be returned
+  /// or it is determined that the information is not available.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   DateTime lastAccessedSync();
 
-  /**
-   * Modifies the time the file was last accessed.
-   *
-   * Returns a [Future] that completes once the operation has completed.
-   *
-   * Throws a [FileSystemException] if the time cannot be set.
-   */
+  /// Modifies the time the file was last accessed.
+  ///
+  /// Returns a [Future] that completes once the operation has completed.
+  ///
+  /// Throws a [FileSystemException] if the time cannot be set.
   Future setLastAccessed(DateTime time);
 
-  /**
-   * Synchronously modifies the time the file was last accessed.
-   *
-   * Throws a [FileSystemException] if the time cannot be set.
-   */
+  /// Synchronously modifies the time the file was last accessed.
+  ///
+  /// Throws a [FileSystemException] if the time cannot be set.
   void setLastAccessedSync(DateTime time);
 
-/**
- * Get the last-modified time of the file.
- *
- * Returns a `Future<DateTime>` that completes with the date and time when the
- * file was last modified, if the information is available.
- *
- * Throws a [FileSystemException] if the operation fails.
- */
+  /// Get the last-modified time of the file.
+  ///
+  /// Returns a `Future<DateTime>` that completes with the date and time when the
+  /// file was last modified, if the information is available.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   Future<DateTime> lastModified();
 
-/**
- * Get the last-modified time of the file.
- *
- * Returns the date and time when the file was last modified,
- * if the information is available. Blocks until the information can be returned
- * or it is determined that the information is not available.
- *
- * Throws a [FileSystemException] if the operation fails.
- */
+  /// Get the last-modified time of the file.
+  ///
+  /// Returns the date and time when the file was last modified,
+  /// if the information is available. Blocks until the information can be returned
+  /// or it is determined that the information is not available.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   DateTime lastModifiedSync();
 
-  /**
-   * Modifies the time the file was last modified.
-   *
-   * Returns a [Future] that completes once the operation has completed.
-   *
-   * Throws a [FileSystemException] if the time cannot be set.
-   */
+  /// Modifies the time the file was last modified.
+  ///
+  /// Returns a [Future] that completes once the operation has completed.
+  ///
+  /// Throws a [FileSystemException] if the time cannot be set.
   Future setLastModified(DateTime time);
 
-  /**
-   * Synchronously modifies the time the file was last modified.
-   *
-   * If the attributes cannot be set, throws a [FileSystemException].
-   */
+  /// Synchronously modifies the time the file was last modified.
+  ///
+  /// If the attributes cannot be set, throws a [FileSystemException].
   void setLastModifiedSync(DateTime time);
 
-  /**
-   * Open the file for random access operations. Returns a
-   * `Future<RandomAccessFile>` that completes with the opened
-   * random access file. [RandomAccessFile]s must be closed using the
-   * [RandomAccessFile.close] method.
-   *
-   * Files can be opened in three modes:
-   *
-   * [FileMode.read]: open the file for reading.
-   *
-   * [FileMode.write]: open the file for both reading and writing and
-   * truncate the file to length zero. If the file does not exist the
-   * file is created.
-   *
-   * [FileMode.append]: same as [FileMode.write] except that the file is
-   * not truncated.
-   */
-  Future<RandomAccessFile> open({FileMode mode: FileMode.read});
+  /// Opens the file for random access operations.
+  ///
+  /// Returns a `Future<RandomAccessFile>` that completes with the opened
+  /// random access file. [RandomAccessFile]s must be closed using the
+  /// [RandomAccessFile.close] method.
+  ///
+  /// Files can be opened in three modes:
+  ///
+  /// * [FileMode.read]: open the file for reading.
+  ///
+  /// * [FileMode.write]: open the file for both reading and writing and
+  /// truncate the file to length zero. If the file does not exist the
+  /// file is created.
+  ///
+  /// * [FileMode.append]: same as [FileMode.write] except that the file is
+  /// not truncated.
+  Future<RandomAccessFile> open({FileMode mode = FileMode.read});
 
-  /**
-   * Synchronously open the file for random access operations. The
-   * result is a [RandomAccessFile] on which random access operations
-   * can be performed. Opened [RandomAccessFile]s must be closed using
-   * the [RandomAccessFile.close] method.
-   *
-   * See [open] for information on the [mode] argument.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
-  RandomAccessFile openSync({FileMode mode: FileMode.read});
+  /// Synchronously opens the file for random access operations.
+  ///
+  /// The result is a [RandomAccessFile] on which random access operations
+  /// can be performed. Opened [RandomAccessFile]s must be closed using
+  /// the [RandomAccessFile.close] method.
+  ///
+  /// See [open] for information on the [mode] argument.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
+  RandomAccessFile openSync({FileMode mode = FileMode.read});
 
-  /**
-   * Create a new independent [Stream] for the contents of this file.
-   *
-   * If [start] is present, the file will be read from byte-offset [start].
-   * Otherwise from the beginning (index 0).
-   *
-   * If [end] is present, only up to byte-index [end] will be read. Otherwise,
-   * until end of file.
-   *
-   * In order to make sure that system resources are freed, the stream
-   * must be read to completion or the subscription on the stream must
-   * be cancelled.
-   */
+  /// Creates a new independent [Stream] for the contents of this file.
+  ///
+  /// If [start] is present, the file will be read from byte-offset [start].
+  /// Otherwise from the beginning (index 0).
+  ///
+  /// If [end] is present, only bytes up to byte-index [end] will be read.
+  /// Otherwise, until end of file.
+  ///
+  /// In order to make sure that system resources are freed, the stream
+  /// must be read to completion or the subscription on the stream must
+  /// be cancelled.
   Stream<List<int>> openRead([int? start, int? end]);
 
-  /**
-   * Creates a new independent [IOSink] for the file. The
-   * [IOSink] must be closed when no longer used, to free
-   * system resources.
-   *
-   * An [IOSink] for a file can be opened in two modes:
-   *
-   * * [FileMode.write]: truncates the file to length zero.
-   * * [FileMode.append]: sets the initial write position to the end
-   *   of the file.
-   *
-   *  When writing strings through the returned [IOSink] the encoding
-   *  specified using [encoding] will be used. The returned [IOSink]
-   *  has an `encoding` property which can be changed after the
-   *  [IOSink] has been created.
-   */
-  IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8});
+  /// Creates a new independent [IOSink] for the file.
+  ///
+  /// The [IOSink] must be closed when no longer used, to free
+  /// system resources.
+  ///
+  /// An [IOSink] for a file can be opened in two modes:
+  ///
+  /// * [FileMode.write]: truncates the file to length zero.
+  /// * [FileMode.append]: sets the initial write position to the end
+  ///   of the file.
+  ///
+  ///  When writing strings through the returned [IOSink] the encoding
+  ///  specified using [encoding] will be used. The returned [IOSink]
+  ///  has an `encoding` property which can be changed after the
+  ///  [IOSink] has been created.
+  IOSink openWrite({FileMode mode = FileMode.write, Encoding encoding = utf8});
 
-  /**
-   * Read the entire file contents as a list of bytes. Returns a
-   * `Future<Uint8List>` that completes with the list of bytes that
-   * is the contents of the file.
-   */
+  /// Reads the entire file contents as a list of bytes.
+  ///
+  /// Returns a `Future<Uint8List>` that completes with the list of bytes that
+  /// is the contents of the file.
   Future<Uint8List> readAsBytes();
 
-  /**
-   * Synchronously read the entire file contents as a list of bytes.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously reads the entire file contents as a list of bytes.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   Uint8List readAsBytesSync();
 
-  /**
-   * Read the entire file contents as a string using the given
-   * [Encoding].
-   *
-   * Returns a `Future<String>` that completes with the string once
-   * the file contents has been read.
-   */
-  Future<String> readAsString({Encoding encoding: utf8});
+  /// Reads the entire file contents as a string using the given
+  /// [Encoding].
+  ///
+  /// Returns a `Future<String>` that completes with the string once
+  /// the file contents has been read.
+  Future<String> readAsString({Encoding encoding = utf8});
 
-  /**
-   * Synchronously read the entire file contents as a string using the
-   * given [Encoding].
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
-  String readAsStringSync({Encoding encoding: utf8});
+  /// Synchronously reads the entire file contents as a string using the
+  /// given [Encoding].
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
+  String readAsStringSync({Encoding encoding = utf8});
 
-  /**
-   * Read the entire file contents as lines of text using the given
-   * [Encoding].
-   *
-   * Returns a `Future<List<String>>` that completes with the lines
-   * once the file contents has been read.
-   */
-  Future<List<String>> readAsLines({Encoding encoding: utf8});
+  /// Reads the entire file contents as lines of text using the given
+  /// [Encoding].
+  ///
+  /// Returns a `Future<List<String>>` that completes with the lines
+  /// once the file contents has been read.
+  Future<List<String>> readAsLines({Encoding encoding = utf8});
 
-  /**
-   * Synchronously read the entire file contents as lines of text
-   * using the given [Encoding].
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
-  List<String> readAsLinesSync({Encoding encoding: utf8});
+  /// Synchronously reads the entire file contents as lines of text
+  /// using the given [Encoding].
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
+  List<String> readAsLinesSync({Encoding encoding = utf8});
 
-  /**
-   * Write a list of bytes to a file.
-   *
-   * Opens the file, writes the list of bytes to it, and closes the file.
-   * Returns a `Future<File>` that completes with this [File] object once
-   * the entire operation has completed.
-   *
-   * By default [writeAsBytes] creates the file for writing and truncates the
-   * file if it already exists. In order to append the bytes to an existing
-   * file, pass [FileMode.append] as the optional mode parameter.
-   *
-   * If the argument [flush] is set to `true`, the data written will be
-   * flushed to the file system before the returned future completes.
-   */
+  /// Writes a list of bytes to a file.
+  ///
+  /// Opens the file, writes the list of bytes to it, and closes the file.
+  /// Returns a `Future<File>` that completes with this [File] object once
+  /// the entire operation has completed.
+  ///
+  /// By default [writeAsBytes] creates the file for writing and truncates the
+  /// file if it already exists. In order to append the bytes to an existing
+  /// file, pass [FileMode.append] as the optional mode parameter.
+  ///
+  /// If the argument [flush] is set to `true`, the data written will be
+  /// flushed to the file system before the returned future completes.
   Future<File> writeAsBytes(List<int> bytes,
-      {FileMode mode: FileMode.write, bool flush: false});
+      {FileMode mode = FileMode.write, bool flush = false});
 
-  /**
-   * Synchronously write a list of bytes to a file.
-   *
-   * Opens the file, writes the list of bytes to it and closes the file.
-   *
-   * By default [writeAsBytesSync] creates the file for writing and truncates
-   * the file if it already exists. In order to append the bytes to an existing
-   * file, pass [FileMode.append] as the optional mode parameter.
-   *
-   * If the [flush] argument is set to `true` data written will be
-   * flushed to the file system before returning.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously writes a list of bytes to a file.
+  ///
+  /// Opens the file, writes the list of bytes to it and closes the file.
+  ///
+  /// By default [writeAsBytesSync] creates the file for writing and truncates
+  /// the file if it already exists. In order to append the bytes to an existing
+  /// file, pass [FileMode.append] as the optional mode parameter.
+  ///
+  /// If the [flush] argument is set to `true` data written will be
+  /// flushed to the file system before returning.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   void writeAsBytesSync(List<int> bytes,
-      {FileMode mode: FileMode.write, bool flush: false});
+      {FileMode mode = FileMode.write, bool flush = false});
 
-  /**
-   * Write a string to a file.
-   *
-   * Opens the file, writes the string in the given encoding, and closes the
-   * file. Returns a `Future<File>` that completes with this [File] object
-   * once the entire operation has completed.
-   *
-   * By default [writeAsString] creates the file for writing and truncates the
-   * file if it already exists. In order to append the bytes to an existing
-   * file, pass [FileMode.append] as the optional mode parameter.
-   *
-   * If the argument [flush] is set to `true`, the data written will be
-   * flushed to the file system before the returned future completes.
-   *
-   */
+  /// Writes a string to a file.
+  ///
+  /// Opens the file, writes the string in the given encoding, and closes the
+  /// file. Returns a `Future<File>` that completes with this [File] object
+  /// once the entire operation has completed.
+  ///
+  /// By default [writeAsString] creates the file for writing and truncates the
+  /// file if it already exists. In order to append the bytes to an existing
+  /// file, pass [FileMode.append] as the optional mode parameter.
+  ///
+  /// If the argument [flush] is set to `true`, the data written will be
+  /// flushed to the file system before the returned future completes.
+  ///
   Future<File> writeAsString(String contents,
-      {FileMode mode: FileMode.write,
-      Encoding encoding: utf8,
-      bool flush: false});
+      {FileMode mode = FileMode.write,
+      Encoding encoding = utf8,
+      bool flush = false});
 
-  /**
-   * Synchronously write a string to a file.
-   *
-   * Opens the file, writes the string in the given encoding, and closes the
-   * file.
-   *
-   * By default [writeAsStringSync] creates the file for writing and
-   * truncates the file if it already exists. In order to append the bytes
-   * to an existing file, pass [FileMode.append] as the optional mode
-   * parameter.
-   *
-   * If the [flush] argument is set to `true` data written will be
-   * flushed to the file system before returning.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously writes a string to a file.
+  ///
+  /// Opens the file, writes the string in the given encoding, and closes the
+  /// file.
+  ///
+  /// By default [writeAsStringSync] creates the file for writing and
+  /// truncates the file if it already exists. In order to append the bytes
+  /// to an existing file, pass [FileMode.append] as the optional mode
+  /// parameter.
+  ///
+  /// If the [flush] argument is set to `true` data written will be
+  /// flushed to the file system before returning.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   void writeAsStringSync(String contents,
-      {FileMode mode: FileMode.write,
-      Encoding encoding: utf8,
-      bool flush: false});
+      {FileMode mode = FileMode.write,
+      Encoding encoding = utf8,
+      bool flush = false});
 
-  /**
-   * Get the path of the file.
-   */
+  /// Get the path of the file.
   String get path;
 }
 
-/**
- * `RandomAccessFile` provides random access to the data in a
- * file.
- *
- * `RandomAccessFile` objects are obtained by calling the
- * `open` method on a [File] object.
- *
- * A `RandomAccessFile` have both asynchronous and synchronous
- * methods. The asynchronous methods all return a `Future`
- * whereas the synchronous methods will return the result directly,
- * and block the current isolate until the result is ready.
- *
- * At most one asynchronous method can be pending on a given `RandomAccessFile`
- * instance at the time. If an asynchronous method is called when one is
- * already in progress a [FileSystemException] is thrown.
- *
- * If an asynchronous method is pending it is also not possible to call any
- * synchronous methods. This will also throw a [FileSystemException].
- */
+/// Random access to the data in a file.
+///
+/// `RandomAccessFile` objects are obtained by calling the
+/// `open` method on a [File] object.
+///
+/// A `RandomAccessFile` has both asynchronous and synchronous
+/// methods. The asynchronous methods all return a [Future]
+/// whereas the synchronous methods will return the result directly,
+/// and block the current isolate until the result is ready.
+///
+/// At most one asynchronous method can be pending on a given `RandomAccessFile`
+/// instance at the time. If another asynchronous method is called when one is
+/// already in progress, a [FileSystemException] is thrown.
+///
+/// If an asynchronous method is pending, it is also not possible to call any
+/// synchronous methods. This will also throw a [FileSystemException].
 abstract class RandomAccessFile {
-  /**
-   * Closes the file. Returns a `Future` that
-   * completes when it has been closed.
-   */
+  /// Closes the file.
+  ///
+  /// Returns a [Future] that completes when it has been closed.
   Future<void> close();
 
-  /**
-   * Synchronously closes the file.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously closes the file.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   void closeSync();
 
-  /**
-   * Reads a byte from the file. Returns a `Future<int>` that
-   * completes with the byte, or with -1 if end-of-file has been reached.
-   */
+  /// Reads a byte from the file.
+  ///
+  /// Returns a `Future<int>` that completes with the byte,
+  /// or with -1 if end-of-file has been reached.
   Future<int> readByte();
 
-  /**
-   * Synchronously reads a single byte from the file. If end-of-file
-   * has been reached -1 is returned.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously reads a single byte from the file.
+  ///
+  /// If end-of-file has been reached -1 is returned.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   int readByteSync();
 
-  /**
-   * Reads [bytes] bytes from a file and returns the result as a list of bytes.
-   */
-  Future<Uint8List> read(int bytes);
+  /// Reads up to [count] bytes from a file.
+  Future<Uint8List> read(int count);
 
-  /**
-   * Synchronously reads a maximum of [bytes] bytes from a file and
-   * returns the result in a list of bytes.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
-  Uint8List readSync(int bytes);
+  /// Synchronously reads up to [count] bytes from a file
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
+  Uint8List readSync(int count);
 
-  /**
-   * Reads into an existing [List<int>] from the file. If [start] is present,
-   * the bytes will be filled into [buffer] from at index [start], otherwise
-   * index 0. If [end] is present, the [end] - [start] bytes will be read into
-   * [buffer], otherwise up to [buffer.length]. If [end] == [start] nothing
-   * happens.
-   *
-   * Returns a `Future<int>` that completes with the number of bytes read.
-   */
+  /// Reads bytes into an existing [buffer].
+  ///
+  /// Reads bytes and writes then into the the range of [buffer]
+  /// from [start] to [end].
+  /// The [start] must be non-negative and no greater than `buffer.length`.
+  /// If [end] is omitted, it defaults to [buffer.length].
+  /// Otherwise [end] must be no less than [start]
+  /// and no greater than `buffer.length`.
+  ///
+  /// Returns the number of bytes read. This maybe be less than `end - start`
+  /// if the file doesn't have that many bytes to read.
   Future<int> readInto(List<int> buffer, [int start = 0, int? end]);
 
-  /**
-   * Synchronously reads into an existing [List<int>] from the file and returns
-   * the number of bytes read.
-   *
-   * If [start] is present, the bytes will be filled into [buffer] from at
-   * index [start], otherwise index 0.  If [end] is present, the
-   * [end] - [start] bytes will be read into [buffer], otherwise up to
-   * [buffer.length]. If [end] == [start] nothing happens.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously reads into an existing [buffer].
+  ///
+  /// Reads bytes and writes then into the the range of [buffer]
+  /// from [start] to [end].
+  /// The [start] must be non-negative and no greater than `buffer.length`.
+  /// If [end] is omitted, it defaults to [buffer.length].
+  /// Otherwise [end] must be no less than [start]
+  /// and no greater than `buffer.length`.
+  ///
+  /// Returns the number of bytes read. This maybe be less than `end - start`
+  /// if the file doesn't have that many bytes to read.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   int readIntoSync(List<int> buffer, [int start = 0, int? end]);
 
-  /**
-   * Writes a single byte to the file. Returns a
-   * `Future<RandomAccessFile>` that completes with this
-   * RandomAccessFile when the write completes.
-   */
+  /// Writes a single byte to the file.
+  ///
+  /// Returns a `Future<RandomAccessFile>` that completes with this
+  /// random access file when the write completes.
   Future<RandomAccessFile> writeByte(int value);
 
-  /**
-   * Synchronously writes a single byte to the file. Returns 1 on success.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously writes a single byte to the file.
+  ///
+  /// Returns 1 on success.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   int writeByteSync(int value);
 
-  /**
-   * Writes from a [List<int>] to the file. It will read the buffer from index
-   * [start] to index [end]. If [start] is omitted, it'll start from index 0.
-   * If [end] is omitted, it will write to end of [buffer].
-   *
-   * Returns a `Future<RandomAccessFile>` that completes with this
-   * [RandomAccessFile] when the write completes.
-   */
+  /// Writes from a [buffer] to the file.
+  ///
+  /// Will read the buffer from index [start] to index [end].
+  /// The [start] must be non-negative and no greater than `buffer.length`.
+  /// If [end] is omitted, it defaults to [buffer.length].
+  /// Otherwise [end] must be no less than [start]
+  /// and no greater than `buffer.length`.
+  ///
+  /// Returns a `Future<RandomAccessFile>` that completes with this
+  /// [RandomAccessFile] when the write completes.
   Future<RandomAccessFile> writeFrom(List<int> buffer,
       [int start = 0, int? end]);
 
-  /**
-   * Synchronously writes from a [List<int>] to the file. It will read the
-   * buffer from index [start] to index [end]. If [start] is omitted, it'll
-   * start from index 0. If [end] is omitted, it will write to the end of
-   * [buffer].
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously writes from a [buffer] to the file.
+  ///
+  /// Will read the buffer from index [start] to index [end].
+  /// The [start] must be non-negative and no greater than `buffer.length`.
+  /// If [end] is omitted, it defaults to [buffer.length].
+  /// Otherwise [end] must be no less than [start]
+  /// and no greater than `buffer.length`.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   void writeFromSync(List<int> buffer, [int start = 0, int? end]);
 
-  /**
-   * Writes a string to the file using the given [Encoding]. Returns a
-   * `Future<RandomAccessFile>` that completes with this
-   * RandomAccessFile when the write completes.
-   */
+  /// Writes a string to the file using the given [Encoding].
+  ///
+  /// Returns a `Future<RandomAccessFile>` that completes with this
+  /// random access file when the write completes.
   Future<RandomAccessFile> writeString(String string,
-      {Encoding encoding: utf8});
+      {Encoding encoding = utf8});
 
-  /**
-   * Synchronously writes a single string to the file using the given
-   * [Encoding].
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
-  void writeStringSync(String string, {Encoding encoding: utf8});
+  /// Synchronously writes a single string to the file using the given
+  /// [Encoding].
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
+  void writeStringSync(String string, {Encoding encoding = utf8});
 
-  /**
-   * Gets the current byte position in the file. Returns a
-   * `Future<int>` that completes with the position.
-   */
+  /// Gets the current byte position in the file.
+  ///
+  /// Returns a `Future<int>` that completes with the position.
   Future<int> position();
 
-  /**
-   * Synchronously gets the current byte position in the file.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously gets the current byte position in the file.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   int positionSync();
 
-  /**
-   * Sets the byte position in the file. Returns a
-   * `Future<RandomAccessFile>` that completes with this
-   * RandomAccessFile when the position has been set.
-   */
+  /// Sets the byte position in the file.
+  ///
+  /// Returns a `Future<RandomAccessFile>` that completes with this
+  /// random access file when the position has been set.
   Future<RandomAccessFile> setPosition(int position);
 
-  /**
-   * Synchronously sets the byte position in the file.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously sets the byte position in the file.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   void setPositionSync(int position);
 
-  /**
-   * Truncates (or extends) the file to [length] bytes. Returns a
-   * `Future<RandomAccessFile>` that completes with this
-   * RandomAccessFile when the truncation has been performed.
-   */
+  /// Truncates (or extends) the file to [length] bytes.
+  ///
+  /// Returns a `Future<RandomAccessFile>` that completes with this
+  /// random access file when the truncation has been performed.
   Future<RandomAccessFile> truncate(int length);
 
-  /**
-   * Synchronously truncates (or extends) the file to [length] bytes.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously truncates (or extends) the file to [length] bytes.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   void truncateSync(int length);
 
-  /**
-   * Gets the length of the file. Returns a `Future<int>` that
-   * completes with the length in bytes.
-   */
+  /// Gets the length of the file.
+  ///
+  /// Returns a `Future<int>` that completes with the length in bytes.
   Future<int> length();
 
-  /**
-   * Synchronously gets the length of the file.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously gets the length of the file.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   int lengthSync();
 
-  /**
-   * Flushes the contents of the file to disk. Returns a
-   * `Future<RandomAccessFile>` that completes with this
-   * RandomAccessFile when the flush operation completes.
-   */
+  /// Flushes the contents of the file to disk.
+  ///
+  /// Returns a `Future<RandomAccessFile>` that completes with this
+  /// random access file when the flush operation completes.
   Future<RandomAccessFile> flush();
 
-  /**
-   * Synchronously flushes the contents of the file to disk.
-   *
-   * Throws a [FileSystemException] if the operation fails.
-   */
+  /// Synchronously flushes the contents of the file to disk.
+  ///
+  /// Throws a [FileSystemException] if the operation fails.
   void flushSync();
 
-  /**
-   * Locks the file or part of the file.
-   *
-   * By default an exclusive lock will be obtained, but that can be overridden
-   * by the [mode] argument.
-   *
-   * Locks the byte range from [start] to [end] of the file, with the
-   * byte at position `end` not included. If no arguments are
-   * specified, the full file is locked, If only `start` is specified
-   * the file is locked from byte position `start` to the end of the
-   * file, no matter how large it grows. It is possible to specify an
-   * explicit value of `end` which is past the current length of the file.
-   *
-   * To obtain an exclusive lock on a file it must be opened for writing.
-   *
-   * If [mode] is [FileLock.exclusive] or [FileLock.shared], an error is
-   * signaled if the lock cannot be obtained. If [mode] is
-   * [FileLock.blockingExclusive] or [FileLock.blockingShared], the
-   * returned [Future] is resolved only when the lock has been obtained.
-   *
-   * *NOTE* file locking does have slight differences in behavior across
-   * platforms:
-   *
-   * On Linux and OS X this uses advisory locks, which have the
-   * surprising semantics that all locks associated with a given file
-   * are removed when *any* file descriptor for that file is closed by
-   * the process. Note that this does not actually lock the file for
-   * access. Also note that advisory locks are on a process
-   * level. This means that several isolates in the same process can
-   * obtain an exclusive lock on the same file.
-   *
-   * On Windows the regions used for lock and unlock needs to match. If that
-   * is not the case unlocking will result in the OS error "The segment is
-   * already unlocked".
-   */
+  /// Locks the file or part of the file.
+  ///
+  /// By default an exclusive lock will be obtained, but that can be overridden
+  /// by the [mode] argument.
+  ///
+  /// Locks the byte range from [start] to [end] of the file, with the
+  /// byte at position `end` not included. If no arguments are
+  /// specified, the full file is locked, If only `start` is specified
+  /// the file is locked from byte position `start` to the end of the
+  /// file, no matter how large it grows. It is possible to specify an
+  /// explicit value of `end` which is past the current length of the file.
+  ///
+  /// To obtain an exclusive lock on a file, it must be opened for writing.
+  ///
+  /// If [mode] is [FileLock.exclusive] or [FileLock.shared], an error is
+  /// signaled if the lock cannot be obtained. If [mode] is
+  /// [FileLock.blockingExclusive] or [FileLock.blockingShared], the
+  /// returned [Future] is resolved only when the lock has been obtained.
+  ///
+  /// *NOTE* file locking does have slight differences in behavior across
+  /// platforms:
+  ///
+  /// On Linux and OS X this uses advisory locks, which have the
+  /// surprising semantics that all locks associated with a given file
+  /// are removed when *any* file descriptor for that file is closed by
+  /// the process. Note that this does not actually lock the file for
+  /// access. Also note that advisory locks are on a process
+  /// level. This means that several isolates in the same process can
+  /// obtain an exclusive lock on the same file.
+  ///
+  /// On Windows the regions used for lock and unlock needs to match. If that
+  /// is not the case unlocking will result in the OS error "The segment is
+  /// already unlocked".
   Future<RandomAccessFile> lock(
       [FileLock mode = FileLock.exclusive, int start = 0, int end = -1]);
 
-  /**
-   * Synchronously locks the file or part of the file.
-   *
-   * By default an exclusive lock will be obtained, but that can be overridden
-   * by the [mode] argument.
-   *
-   * Locks the byte range from [start] to [end] of the file ,with the
-   * byte at position `end` not included. If no arguments are
-   * specified, the full file is locked, If only `start` is specified
-   * the file is locked from byte position `start` to the end of the
-   * file, no matter how large it grows. It is possible to specify an
-   * explicit value of `end` which is past the current length of the file.
-   *
-   * To obtain an exclusive lock on a file it must be opened for writing.
-   *
-   * If [mode] is [FileLock.exclusive] or [FileLock.shared], an exception is
-   * thrown if the lock cannot be obtained. If [mode] is
-   * [FileLock.blockingExclusive] or [FileLock.blockingShared], the
-   * call returns only after the lock has been obtained.
-   *
-   * *NOTE* file locking does have slight differences in behavior across
-   * platforms:
-   *
-   * On Linux and OS X this uses advisory locks, which have the
-   * surprising semantics that all locks associated with a given file
-   * are removed when *any* file descriptor for that file is closed by
-   * the process. Note that this does not actually lock the file for
-   * access. Also note that advisory locks are on a process
-   * level. This means that several isolates in the same process can
-   * obtain an exclusive lock on the same file.
-   *
-   * On Windows the regions used for lock and unlock needs to match. If that
-   * is not the case unlocking will result in the OS error "The segment is
-   * already unlocked".
-   *
-   */
+  /// Synchronously locks the file or part of the file.
+  ///
+  /// By default an exclusive lock will be obtained, but that can be overridden
+  /// by the [mode] argument.
+  ///
+  /// Locks the byte range from [start] to [end] of the file ,with the
+  /// byte at position `end` not included. If no arguments are
+  /// specified, the full file is locked, If only `start` is specified
+  /// the file is locked from byte position `start` to the end of the
+  /// file, no matter how large it grows. It is possible to specify an
+  /// explicit value of `end` which is past the current length of the file.
+  ///
+  /// To obtain an exclusive lock on a file it must be opened for writing.
+  ///
+  /// If [mode] is [FileLock.exclusive] or [FileLock.shared], an exception is
+  /// thrown if the lock cannot be obtained. If [mode] is
+  /// [FileLock.blockingExclusive] or [FileLock.blockingShared], the
+  /// call returns only after the lock has been obtained.
+  ///
+  /// *NOTE* file locking does have slight differences in behavior across
+  /// platforms:
+  ///
+  /// On Linux and OS X this uses advisory locks, which have the
+  /// surprising semantics that all locks associated with a given file
+  /// are removed when *any* file descriptor for that file is closed by
+  /// the process. Note that this does not actually lock the file for
+  /// access. Also note that advisory locks are on a process
+  /// level. This means that several isolates in the same process can
+  /// obtain an exclusive lock on the same file.
+  ///
+  /// On Windows the regions used for lock and unlock needs to match. If that
+  /// is not the case unlocking will result in the OS error "The segment is
+  /// already unlocked".
+  ///
   void lockSync(
       [FileLock mode = FileLock.exclusive, int start = 0, int end = -1]);
 
-  /**
-   * Unlocks the file or part of the file.
-   *
-   * Unlocks the byte range from [start] to [end] of the file, with
-   * the byte at position `end` not included. If no arguments are
-   * specified, the full file is unlocked, If only `start` is
-   * specified the file is unlocked from byte position `start` to the
-   * end of the file.
-   *
-   * *NOTE* file locking does have slight differences in behavior across
-   * platforms:
-   *
-   * See [lock] for more details.
-   */
+  /// Unlocks the file or part of the file.
+  ///
+  /// Unlocks the byte range from [start] to [end] of the file, with
+  /// the byte at position `end` not included. If no arguments are
+  /// specified, the full file is unlocked, If only `start` is
+  /// specified the file is unlocked from byte position `start` to the
+  /// end of the file.
+  ///
+  /// *NOTE* file locking does have slight differences in behavior across
+  /// platforms:
+  ///
+  /// See [lock] for more details.
   Future<RandomAccessFile> unlock([int start = 0, int end = -1]);
 
-  /**
-   * Synchronously unlocks the file or part of the file.
-   *
-   * Unlocks the byte range from [start] to [end] of the file, with
-   * the byte at position `end` not included. If no arguments are
-   * specified, the full file is unlocked, If only `start` is
-   * specified the file is unlocked from byte position `start` to the
-   * end of the file.
-   *
-   * *NOTE* file locking does have slight differences in behavior across
-   * platforms:
-   *
-   * See [lockSync] for more details.
-   */
+  /// Synchronously unlocks the file or part of the file.
+  ///
+  /// Unlocks the byte range from [start] to [end] of the file, with
+  /// the byte at position `end` not included. If no arguments are
+  /// specified, the full file is unlocked, If only `start` is
+  /// specified the file is unlocked from byte position `start` to the
+  /// end of the file.
+  ///
+  /// *NOTE* file locking does have slight differences in behavior across
+  /// platforms:
+  ///
+  /// See [lockSync] for more details.
   void unlockSync([int start = 0, int end = -1]);
 
-  /**
-   * Returns a human-readable string for this RandomAccessFile instance.
-   */
+  /// Returns a human-readable string for this random access file.
   String toString();
 
-  /**
-   * Gets the path of the file underlying this RandomAccessFile.
-   */
+  /// The path of the file underlying this random access file.
   String get path;
 }
 
-/**
- * Exception thrown when a file operation fails.
- */
+/// Exception thrown when a file operation fails.
 @pragma("vm:entry-point")
 class FileSystemException implements IOException {
-  /**
-   * Message describing the error. This does not include any detailed
-   * information form the underlying OS error. Check [osError] for
-   * that information.
-   */
+  /// Message describing the error.
+  ///
+  /// The message does not include any detailed information from
+  /// the underlying OS error. Check [osError] for that information.
   final String message;
 
-  /**
-   * The file system path on which the error occurred. Can be `null`
-   * if the exception does not relate directly to a file system path.
-   */
+  /// The file system path on which the error occurred.
+  ///
+  /// Can be `null` if the exception does not relate directly
+  /// to a file system path.
   final String? path;
 
-  /**
-   * The underlying OS error. Can be `null` if the exception is not
-   * raised due to an OS error.
-   */
+  /// The underlying OS error.
+  ///
+  /// Can be `null` if the exception is not raised due to an OS error.
   final OSError? osError;
 
-  /**
-   * Creates a new FileSystemException with an optional error message
-   * [message], optional file system path [path] and optional OS error
-   * [osError].
-   */
+  /// Creates a new file system exception with optional parts.
+  ///
+  /// Creates an exception with [FileSystemException.message],
+  /// [FileSystemException.path] and [FileSystemException.osError]
+  /// values take from the optional parameters of the same name.
+  ///
+  /// The [message] and [path] path defaults to empty strings if omitted,
+  /// and [osError] defaults to `null`.
   @pragma("vm:entry-point")
   const FileSystemException([this.message = "", this.path = "", this.osError]);
 
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 75f78b1..696273b 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -244,7 +244,7 @@
 
   File get absolute => new File(_absolutePath);
 
-  Future<File> create({bool recursive: false}) {
+  Future<File> create({bool recursive = false}) {
     var result =
         recursive ? parent.create(recursive: true) : new Future.value(null);
     return result
@@ -265,7 +265,7 @@
 
   external static _linkTarget(_Namespace namespace, Uint8List rawPath);
 
-  void createSync({bool recursive: false}) {
+  void createSync({bool recursive = false}) {
     if (recursive) {
       parent.createSync(recursive: true);
     }
@@ -273,7 +273,7 @@
     throwIfError(result, "Cannot create file", path);
   }
 
-  Future<File> _delete({bool recursive: false}) {
+  Future<File> _delete({bool recursive = false}) {
     if (recursive) {
       return new Directory(path).delete(recursive: true).then((_) => this);
     }
@@ -290,7 +290,7 @@
 
   external static _deleteLinkNative(_Namespace namespace, Uint8List rawPath);
 
-  void _deleteSync({bool recursive: false}) {
+  void _deleteSync({bool recursive = false}) {
     if (recursive) {
       return new Directory.fromRawPath(_rawPath).deleteSync(recursive: true);
     }
@@ -341,7 +341,7 @@
     return new File(newPath);
   }
 
-  Future<RandomAccessFile> open({FileMode mode: FileMode.read}) {
+  Future<RandomAccessFile> open({FileMode mode = FileMode.read}) {
     if (mode != FileMode.read &&
         mode != FileMode.write &&
         mode != FileMode.append &&
@@ -467,7 +467,7 @@
 
   external static _open(_Namespace namespace, Uint8List rawPath, int mode);
 
-  RandomAccessFile openSync({FileMode mode: FileMode.read}) {
+  RandomAccessFile openSync({FileMode mode = FileMode.read}) {
     if (mode != FileMode.read &&
         mode != FileMode.write &&
         mode != FileMode.append &&
@@ -494,7 +494,7 @@
     return new _FileStream(path, start, end);
   }
 
-  IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8}) {
+  IOSink openWrite({FileMode mode = FileMode.write, Encoding encoding = utf8}) {
     if (mode != FileMode.write &&
         mode != FileMode.append &&
         mode != FileMode.writeOnly &&
@@ -566,7 +566,7 @@
     }
   }
 
-  Future<String> readAsString({Encoding encoding: utf8}) {
+  Future<String> readAsString({Encoding encoding = utf8}) {
     // TODO(dart:io): If the change in async semantics to run synchronously
     // until await lands, this is as efficient as
     // return _tryDecode(await readAsBytes(), encoding);
@@ -580,17 +580,17 @@
     });
   }
 
-  String readAsStringSync({Encoding encoding: utf8}) =>
+  String readAsStringSync({Encoding encoding = utf8}) =>
       _tryDecode(readAsBytesSync(), encoding);
 
-  Future<List<String>> readAsLines({Encoding encoding: utf8}) =>
+  Future<List<String>> readAsLines({Encoding encoding = utf8}) =>
       readAsString(encoding: encoding).then(const LineSplitter().convert);
 
-  List<String> readAsLinesSync({Encoding encoding: utf8}) =>
+  List<String> readAsLinesSync({Encoding encoding = utf8}) =>
       const LineSplitter().convert(readAsStringSync(encoding: encoding));
 
   Future<File> writeAsBytes(List<int> bytes,
-      {FileMode mode: FileMode.write, bool flush: false}) {
+      {FileMode mode = FileMode.write, bool flush = false}) {
     return open(mode: mode).then((file) {
       return file.writeFrom(bytes, 0, bytes.length).then<File>((_) {
         if (flush) return file.flush().then((_) => this);
@@ -600,7 +600,7 @@
   }
 
   void writeAsBytesSync(List<int> bytes,
-      {FileMode mode: FileMode.write, bool flush: false}) {
+      {FileMode mode = FileMode.write, bool flush = false}) {
     RandomAccessFile opened = openSync(mode: mode);
     try {
       opened.writeFromSync(bytes, 0, bytes.length);
@@ -611,9 +611,9 @@
   }
 
   Future<File> writeAsString(String contents,
-      {FileMode mode: FileMode.write,
-      Encoding encoding: utf8,
-      bool flush: false}) {
+      {FileMode mode = FileMode.write,
+      Encoding encoding = utf8,
+      bool flush = false}) {
     try {
       return writeAsBytes(encoding.encode(contents), mode: mode, flush: flush);
     } catch (e) {
@@ -622,9 +622,9 @@
   }
 
   void writeAsStringSync(String contents,
-      {FileMode mode: FileMode.write,
-      Encoding encoding: utf8,
-      bool flush: false}) {
+      {FileMode mode = FileMode.write,
+      Encoding encoding = utf8,
+      bool flush = false}) {
     writeAsBytesSync(encoding.encode(contents), mode: mode, flush: flush);
   }
 
@@ -873,14 +873,14 @@
   }
 
   Future<RandomAccessFile> writeString(String string,
-      {Encoding encoding: utf8}) {
+      {Encoding encoding = utf8}) {
     // TODO(40614): Remove once non-nullability is sound.
     ArgumentError.checkNotNull(encoding, "encoding");
     var data = encoding.encode(string);
     return writeFrom(data, 0, data.length);
   }
 
-  void writeStringSync(String string, {Encoding encoding: utf8}) {
+  void writeStringSync(String string, {Encoding encoding = utf8}) {
     // TODO(40614): Remove once non-nullability is sound.
     ArgumentError.checkNotNull(encoding, "encoding");
     var data = encoding.encode(string);
@@ -1058,7 +1058,7 @@
   // count when it is finished with it.
   int _pointer() => _ops.getPointer();
 
-  Future _dispatch(int request, List data, {bool markClosed: false}) {
+  Future _dispatch(int request, List data, {bool markClosed = false}) {
     if (closed) {
       return new Future.error(new FileSystemException("File closed", path));
     }
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 0e12414..e624473 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -4,14 +4,11 @@
 
 part of dart.io;
 
-/**
- * The type of an entity on the file system, such as a file, directory, or link.
- *
- * These constants are used by the [FileSystemEntity] class
- * to indicate the object's type.
- *
- */
-
+/// The type of an entity on the file system,
+/// such as a file, directory, or link.
+///
+/// These constants are used by the [FileSystemEntity] class
+/// to indicate the object's type.
 class FileSystemEntityType {
   static const file = const FileSystemEntityType._internal(0);
   @Deprecated("Use file instead")
@@ -43,11 +40,10 @@
   String toString() => const ['file', 'directory', 'link', 'notFound'][_type];
 }
 
-/**
- * A FileStat object represents the result of calling the POSIX stat() function
- * on a file system object.  It is an immutable object, representing the
- * snapshotted values returned by the stat() call.
- */
+/// The result of calling the POSIX `stat()` function on a file system object.
+///
+/// This is an immutable object, representing the snapshotted values returned
+/// by the `stat()` call.
 class FileStat {
   // These must agree with enum FileStat in file.h.
   static const _type = 0;
@@ -61,45 +57,33 @@
   static final _notFound = new FileStat._internal(
       _epoch, _epoch, _epoch, FileSystemEntityType.notFound, 0, -1);
 
-  /**
-   * The time of the last change to the data or metadata of the file system
-   * object.
-   *
-   * On Windows platforms, this is instead the file creation time.
-   */
+  /// The time of the last change to the data or metadata of the file system
+  /// object.
+  ///
+  /// On Windows platforms, this is instead the file creation time.
   final DateTime changed;
 
-  /**
-   * The time of the last change to the data of the file system object.
-   */
+  /// The time of the last change to the data of the file system object.
   final DateTime modified;
 
-  /**
-   * The time of the last access to the data of the file system object.
-   *
-   * On Windows platforms, this may have 1 day granularity, and be
-   * out of date by an hour.
-   */
+  /// The time of the last access to the data of the file system object.
+  ///
+  /// On Windows platforms, this may have 1 day granularity, and be
+  /// out of date by an hour.
   final DateTime accessed;
 
-  /**
-   * The type of the underlying file system object.
-   *
-   * [FileSystemEntityType.notFound] if [stat] or [statSync] failed.
-   */
+  /// The type of the underlying file system object.
+  ///
+  /// [FileSystemEntityType.notFound] if [stat] or [statSync] failed.
   final FileSystemEntityType type;
 
-  /**
-   * The mode of the file system object.
-   *
-   * Permissions are encoded in the lower 16 bits of this number, and can be
-   * decoded using the [modeString] getter.
-   */
+  /// The mode of the file system object.
+  ///
+  /// Permissions are encoded in the lower 16 bits of this number, and can be
+  /// decoded using the [modeString] getter.
   final int mode;
 
-  /**
-   * The size of the file system object.
-   */
+  /// The size of the file system object.
   final int size;
 
   FileStat._internal(this.changed, this.modified, this.accessed, this.type,
@@ -107,13 +91,11 @@
 
   external static _statSync(_Namespace namespace, String path);
 
-  /**
-   * Calls the operating system's `stat()` function (or equivalent) on [path].
-   *
-   * Returns a [FileStat] object containing the data returned by `stat()`.
-   * If the call fails, returns a [FileStat] object with [FileStat.type] set to
-   * [FileSystemEntityType.notFound] and the other fields invalid.
-   */
+  /// Calls the operating system's `stat()` function (or equivalent) on [path].
+  ///
+  /// Returns a [FileStat] object containing the data returned by `stat()`.
+  /// If the call fails, returns a [FileStat] object with [FileStat.type] set to
+  /// [FileSystemEntityType.notFound] and the other fields invalid.
   static FileStat statSync(String path) {
     final IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
@@ -138,12 +120,10 @@
         data[_size]);
   }
 
-  /**
-   * Asynchronously calls the operating system's `stat()` function (or
-   * equivalent) on [path].
-   *
-   * Returns a [Future] which completes with the same results as [statSync].
-   */
+  /// Asynchronously calls the operating system's `stat()` function (or
+  /// equivalent) on [path].
+  ///
+  /// Returns a [Future] which completes with the same results as [statSync].
   static Future<FileStat> stat(String path) {
     final IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
@@ -182,15 +162,13 @@
           mode ${modeString()}
           size $size""";
 
-  /**
-   * Returns the mode value as a human-readable string.
-   *
-   * The string is in the format "rwxrwxrwx", reflecting the user, group, and
-   * world permissions to read, write, and execute the file system object, with
-   * "-" replacing the letter for missing permissions.  Extra permission bits
-   * may be represented by prepending "(suid)", "(guid)", and/or "(sticky)" to
-   * the mode string.
-   */
+  /// The mode value as a human-readable string.
+  ///
+  /// The string is in the format "rwxrwxrwx", reflecting the user, group, and
+  /// world permissions to read, write, and execute the file system object, with
+  /// "-" replacing the letter for missing permissions. Extra permission bits
+  /// may be represented by prepending "(suid)", "(guid)", and/or "(sticky)" to
+  /// the mode string.
   String modeString() {
     var permissions = mode & 0xFFF;
     var codes = const ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx'];
@@ -206,39 +184,36 @@
   }
 }
 
-/**
- * The common super class for [File], [Directory], and [Link] objects.
- *
- * [FileSystemEntity] objects are returned from directory listing
- * operations. To determine if a FileSystemEntity is a [File], a
- * [Directory], or a [Link] perform a type check:
- *
- *     if (entity is File) (entity as File).readAsStringSync();
- *
- * You can also use the [type] or [typeSync] methods to determine
- * the type of a file system object.
- *
- * Most methods in this class occur in synchronous and asynchronous pairs,
- * for example, [exists] and [existsSync].
- * Unless you have a specific reason for using the synchronous version
- * of a method, prefer the asynchronous version to avoid blocking your program.
- *
- * Here's the exists method in action:
- *
- *     entity.exists().then((isThere) {
- *       isThere ? print('exists') : print('non-existent');
- *     });
- *
- *
- * ## Other resources
- *
- * * The [Files and directories](https://dart.dev/guides/libraries/library-tour#files-and-directories)
- *   section of the library tour.
- *
- * * [Write Command-Line Apps](https://dart.dev/tutorials/server/cmdline),
- *   a tutorial about writing command-line apps, includes information about
- *   files and directories.
- */
+/// The common superclass of [File], [Directory], and [Link].
+///
+/// [FileSystemEntity] objects are returned from directory listing
+/// operations. To determine whether a [FileSystemEntity] is a [File], a
+/// [Directory], or a [Link] perform a type check:
+/// ```dart
+/// if (entity is File) (entity as File).readAsStringSync();
+/// ```
+/// You can also use the [type] or [typeSync] methods to determine
+/// the type of a file system object.
+///
+/// Most methods in this class exist both in synchronous and asynchronous
+/// versions, for example, [exists] and [existsSync].
+/// Unless you have a specific reason for using the synchronous version
+/// of a method, prefer the asynchronous version to avoid blocking your program.
+///
+/// Here's the exists method in action:
+/// ```dart
+/// var isThere = await entity.exists();
+/// print(isThere ? 'exists' : 'non-existent');
+/// ```
+///
+/// ## Other resources
+///
+/// * The [Files and directories](https://dart.dev/guides/libraries/library-tour#files-and-directories)
+///   section of the library tour.
+///
+/// * [Write Command-Line Apps](https://dart.dev/tutorials/server/cmdline),
+///   a tutorial about writing command-line apps, includes information about
+///   files and directories.
 abstract class FileSystemEntity {
   static const _backslashChar = 0x5c;
   static const _slashChar = 0x2f;
@@ -249,98 +224,87 @@
 
   String get path;
 
-  /**
-   * Returns a [Uri] representing the file system entity's location.
-   *
-   * The returned URI's scheme is always "file" if the entity's [path] is
-   * absolute, otherwise the scheme will be empty.
-   */
+  /// A [Uri] representing the file system entity's location.
+  ///
+  /// The returned URI's scheme is always "file" if the entity's [path] is
+  /// absolute, otherwise the scheme will be empty and the URI relative.
   Uri get uri => new Uri.file(path);
 
-  /**
-   * Checks whether the file system entity with this path exists. Returns
-   * a [:Future<bool>:] that completes with the result.
-   *
-   * Since FileSystemEntity is abstract, every FileSystemEntity object
-   * is actually an instance of one of the subclasses [File],
-   * [Directory], and [Link].  Calling [exists] on an instance of one
-   * of these subclasses checks whether the object exists in the file
-   * system object exists and is of the correct type (file, directory,
-   * or link).  To check whether a path points to an object on the
-   * file system, regardless of the object's type, use the [type]
-   * static method.
-   *
-   */
+  /// Checks whether the file system entity with this path exists.
+  ///
+  /// Returns a `Future<bool>` that completes with the result.
+  ///
+  /// Since [FileSystemEntity] is abstract, every [FileSystemEntity] object
+  /// is actually an instance of one of the subclasses [File],
+  /// [Directory], and [Link]. Calling [exists] on an instance of one
+  /// of these subclasses checks whether the object exists in the file
+  /// system object exists *and* is of the correct type (file, directory,
+  /// or link). To check whether a path points to an object on the
+  /// file system, regardless of the object's type, use the [type]
+  /// static method.
   Future<bool> exists();
 
-  /**
-   * Synchronously checks whether the file system entity with this path
-   * exists.
-   *
-   * Since FileSystemEntity is abstract, every FileSystemEntity object
-   * is actually an instance of one of the subclasses [File],
-   * [Directory], and [Link].  Calling [existsSync] on an instance of
-   * one of these subclasses checks whether the object exists in the
-   * file system object exists and is of the correct type (file,
-   * directory, or link).  To check whether a path points to an object
-   * on the file system, regardless of the object's type, use the
-   * [typeSync] static method.
-   */
+  /// Synchronously checks whether the file system entity with this path
+  /// exists.
+  ///
+  /// Since [FileSystemEntity] is abstract, every [FileSystemEntity] object
+  /// is actually an instance of one of the subclasses [File],
+  /// [Directory], and [Link].  Calling [existsSync] on an instance of
+  /// one of these subclasses checks whether the object exists in the
+  /// file system object exists and is of the correct type (file,
+  /// directory, or link).  To check whether a path points to an object
+  /// on the file system, regardless of the object's type, use the
+  /// [typeSync] static method.
   bool existsSync();
 
-  /**
-   * Renames this file system entity.
-   *
-   * Returns a `Future<FileSystemEntity>` that completes with a
-   * [FileSystemEntity] instance for the renamed file system entity.
-   *
-   * If [newPath] identifies an existing entity of the same type, that entity
-   * is replaced. If [newPath] identifies an existing entity of a different
-   * type, the operation fails and the future completes with an exception.
-   */
+  /// Renames this file system entity.
+  ///
+  /// Returns a `Future<FileSystemEntity>` that completes with a
+  /// [FileSystemEntity] instance for the renamed file system entity.
+  ///
+  /// If [newPath] identifies an existing entity of the same type,
+  /// that entity is removed first.
+  /// If [newPath] identifies an existing entity of a different type,
+  /// the operation fails and the future completes with an exception.
   Future<FileSystemEntity> rename(String newPath);
 
-  /**
-   * Synchronously renames this file system entity.
-   *
-   * Returns a [FileSystemEntity] instance for the renamed entity.
-   *
-   * If [newPath] identifies an existing entity of the same type, that entity
-   * is replaced. If [newPath] identifies an existing entity of a different
-   * type, the operation fails and an exception is thrown.
-   */
+  /// Synchronously renames this file system entity.
+  ///
+  /// Returns a [FileSystemEntity] instance for the renamed entity.
+  ///
+  /// If [newPath] identifies an existing entity of the same type,
+  /// that entity is removed first.
+  /// If [newPath] identifies an existing entity of a different type,
+  /// the operation fails and an exception is thrown.
   FileSystemEntity renameSync(String newPath);
 
-  /**
-   * Resolves the path of a file system object relative to the
-   * current working directory.
-   *
-   * Resolves all symbolic links on the path and resolves all `..` and `.` path
-   * segments.
-   *
-   * [resolveSymbolicLinks] uses the operating system's native
-   * file system API to resolve the path, using the `realpath` function
-   * on linux and OS X, and the `GetFinalPathNameByHandle` function on
-   * Windows. If the path does not point to an existing file system object,
-   * `resolveSymbolicLinks` throws a `FileSystemException`.
-   *
-   * On Windows the `..` segments are resolved _before_ resolving the symbolic
-   * link, and on other platforms the symbolic links are _resolved to their
-   * target_ before applying a `..` that follows.
-   *
-   * To ensure the same behavior on all platforms resolve `..` segments before
-   * calling `resolveSymbolicLinks`. One way of doing this is with the `Uri`
-   * class:
-   *
-   *     var path = Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath();
-   *     if (path == '') path = '.';
-   *     new File(path).resolveSymbolicLinks().then((resolved) {
-   *       print(resolved);
-   *     });
-   *
-   * since `Uri.resolve` removes `..` segments. This will result in the Windows
-   * behavior.
-   */
+  /// Resolves the path of a file system object relative to the
+  /// current working directory.
+  ///
+  /// Resolves all symbolic links on the path and resolves all `..` and `.` path
+  /// segments.
+  ///
+  /// [resolveSymbolicLinks] uses the operating system's native
+  /// file system API to resolve the path, using the `realpath` function
+  /// on Linux and OS X, and the `GetFinalPathNameByHandle` function on
+  /// Windows. If the path does not point to an existing file system object,
+  /// `resolveSymbolicLinks` throws a `FileSystemException`.
+  ///
+  /// On Windows the `..` segments are resolved _before_ resolving the symbolic
+  /// link, and on other platforms the symbolic links are _resolved to their
+  /// target_ before applying a `..` that follows.
+  ///
+  /// To ensure the same behavior on all platforms resolve `..` segments before
+  /// calling `resolveSymbolicLinks`. One way of doing this is with the [Uri]
+  /// class:
+  /// ```dart
+  /// var path = Uri.parse('.').resolveUri(Uri.file(input)).toFilePath();
+  /// if (path == '') path = '.';
+  /// var resolved = await File(path).resolveSymbolicLinks();
+  /// print(resolved);
+  /// ```
+  /// since `Uri.resolve` removes `..` segments. This will result in the Windows
+  /// behavior.
   Future<String> resolveSymbolicLinks() {
     return _File._dispatchWithNamespace(
         _IOService.fileResolveSymbolicLinks, [null, _rawPath]).then((response) {
@@ -352,143 +316,130 @@
     });
   }
 
-  /**
-   * Resolves the path of a file system object relative to the
-   * current working directory.
-   *
-   * Resolves all symbolic links on the path and resolves all `..` and `.` path
-   * segments.
-   *
-   * [resolveSymbolicLinksSync] uses the operating system's native
-   * file system API to resolve the path, using the `realpath` function
-   * on linux and OS X, and the `GetFinalPathNameByHandle` function on
-   * Windows. If the path does not point to an existing file system object,
-   * `resolveSymbolicLinksSync` throws a `FileSystemException`.
-   *
-   * On Windows the `..` segments are resolved _before_ resolving the symbolic
-   * link, and on other platforms the symbolic links are _resolved to their
-   * target_ before applying a `..` that follows.
-   *
-   * To ensure the same behavior on all platforms resolve `..` segments before
-   * calling `resolveSymbolicLinksSync`. One way of doing this is with the `Uri`
-   * class:
-   *
-   *     var path = Uri.parse('.').resolveUri(new Uri.file(input)).toFilePath();
-   *     if (path == '') path = '.';
-   *     var resolved = new File(path).resolveSymbolicLinksSync();
-   *     print(resolved);
-   *
-   * since `Uri.resolve` removes `..` segments. This will result in the Windows
-   * behavior.
-   */
+  /// Resolves the path of a file system object relative to the
+  /// current working directory.
+  ///
+  /// Resolves all symbolic links on the path and resolves all `..` and `.` path
+  /// segments.
+  ///
+  /// [resolveSymbolicLinksSync] uses the operating system's native
+  /// file system API to resolve the path, using the `realpath` function
+  /// on linux and OS X, and the `GetFinalPathNameByHandle` function on
+  /// Windows. If the path does not point to an existing file system object,
+  /// `resolveSymbolicLinksSync` throws a `FileSystemException`.
+  ///
+  /// On Windows the `..` segments are resolved _before_ resolving the symbolic
+  /// link, and on other platforms the symbolic links are _resolved to their
+  /// target_ before applying a `..` that follows.
+  ///
+  /// To ensure the same behavior on all platforms resolve `..` segments before
+  /// calling `resolveSymbolicLinksSync`. One way of doing this is with the [Uri]
+  /// class:
+  /// ```dart
+  /// var path = Uri.parse('.').resolveUri(Uri.file(input)).toFilePath();
+  /// if (path == '') path = '.';
+  /// var resolved = File(path).resolveSymbolicLinksSync();
+  /// print(resolved);
+  /// ```
+  /// since `Uri.resolve` removes `..` segments. This will result in the Windows
+  /// behavior.
   String resolveSymbolicLinksSync() {
     var result = _resolveSymbolicLinks(_Namespace._namespace, _rawPath);
     _throwIfError(result, "Cannot resolve symbolic links", path);
     return result;
   }
 
-  /**
-   * Calls the operating system's stat() function on the [path] of this
-   * [FileSystemEntity].
-   *
-   * Identical to [:FileStat.stat(this.path):].
-   *
-   * Returns a [:Future<FileStat>:] object containing the data returned by
-   * stat().
-   *
-   * If the call fails, completes the future with a [FileStat] object
-   * with `.type` set to [FileSystemEntityType.notFound] and the other fields
-   * invalid.
-   */
+  /// Calls the operating system's `stat()` function on [path].
+  ///
+  /// Identical to `FileStat.stat(this.path)`.
+  ///
+  /// Returns a `Future<FileStat>` object containing the data returned by
+  /// `stat()`.
+  ///
+  /// If the call fails, completes the future with a [FileStat] object
+  /// with `.type` set to [FileSystemEntityType.notFound] and the other fields
+  /// invalid.
   Future<FileStat> stat() => FileStat.stat(path);
 
-  /**
-   * Synchronously calls the operating system's stat() function on the
-   * [path] of this [FileSystemEntity].
-   *
-   * Identical to [:FileStat.statSync(this.path):].
-   *
-   * Returns a [FileStat] object containing the data returned by stat().
-   *
-   * If the call fails, returns a [FileStat] object with `.type` set to
-   * [FileSystemEntityType.notFound] and the other fields invalid.
-   */
+  /// Synchronously calls the operating system's `stat()` function on [path].
+  ///
+  /// Identical to `FileStat.statSync(this.path)`.
+  ///
+  /// Returns a [FileStat] object containing the data returned by `stat()`.
+  ///
+  /// If the call fails, returns a [FileStat] object with `.type` set to
+  /// [FileSystemEntityType.notFound] and the other fields invalid.
   FileStat statSync() => FileStat.statSync(path);
 
-  /**
-   * Deletes this [FileSystemEntity].
-   *
-   * If the [FileSystemEntity] is a directory, and if [recursive] is false,
-   * the directory must be empty. Otherwise, if [recursive] is true, the
-   * directory and all sub-directories and files in the directories are
-   * deleted. Links are not followed when deleting recursively. Only the link
-   * is deleted, not its target.
-   *
-   * If [recursive] is true, the [FileSystemEntity] is deleted even if the type
-   * of the [FileSystemEntity] doesn't match the content of the file system.
-   * This behavior allows [delete] to be used to unconditionally delete any file
-   * system object.
-   *
-   * Returns a [:Future<FileSystemEntity>:] that completes with this
-   * [FileSystemEntity] when the deletion is done. If the [FileSystemEntity]
-   * cannot be deleted, the future completes with an exception.
-   */
-  Future<FileSystemEntity> delete({bool recursive: false}) =>
+  /// Deletes this [FileSystemEntity].
+  ///
+  /// If the [FileSystemEntity] is a directory, and if [recursive] is `false`,
+  /// the directory must be empty. Otherwise, if [recursive] is true, the
+  /// directory and all sub-directories and files in the directories are
+  /// deleted. Links are not followed when deleting recursively. Only the link
+  /// is deleted, not its target.
+  ///
+  /// If [recursive] is true, the [FileSystemEntity] is deleted even if the type
+  /// of the [FileSystemEntity] doesn't match the content of the file system.
+  /// This behavior allows [delete] to be used to unconditionally delete any file
+  /// system object.
+  ///
+  /// Returns a `Future<FileSystemEntity>` that completes with this
+  /// [FileSystemEntity] when the deletion is done. If the [FileSystemEntity]
+  /// cannot be deleted, the future completes with an exception.
+  Future<FileSystemEntity> delete({bool recursive = false}) =>
       _delete(recursive: recursive);
 
-  /**
-   * Synchronously deletes this [FileSystemEntity].
-   *
-   * If the [FileSystemEntity] is a directory, and if [recursive] is false,
-   * the directory must be empty. Otherwise, if [recursive] is true, the
-   * directory and all sub-directories and files in the directories are
-   * deleted. Links are not followed when deleting recursively. Only the link
-   * is deleted, not its target.
-   *
-   * If [recursive] is true, the [FileSystemEntity] is deleted even if the type
-   * of the [FileSystemEntity] doesn't match the content of the file system.
-   * This behavior allows [deleteSync] to be used to unconditionally delete any
-   * file system object.
-   *
-   * Throws an exception if the [FileSystemEntity] cannot be deleted.
-   */
-  void deleteSync({bool recursive: false}) => _deleteSync(recursive: recursive);
+  /// Synchronously deletes this [FileSystemEntity].
+  ///
+  /// If the [FileSystemEntity] is a directory, and if [recursive] is false,
+  /// the directory must be empty. Otherwise, if [recursive] is true, the
+  /// directory and all sub-directories and files in the directories are
+  /// deleted. Links are not followed when deleting recursively. Only the link
+  /// is deleted, not its target.
+  ///
+  /// If [recursive] is true, the [FileSystemEntity] is deleted even if the type
+  /// of the [FileSystemEntity] doesn't match the content of the file system.
+  /// This behavior allows [deleteSync] to be used to unconditionally delete any
+  /// file system object.
+  ///
+  /// Throws an exception if the [FileSystemEntity] cannot be deleted.
+  void deleteSync({bool recursive = false}) =>
+      _deleteSync(recursive: recursive);
 
-  /**
-   * Start watching the [FileSystemEntity] for changes.
-   *
-   * The implementation uses platform-dependent event-based APIs for receiving
-   * file-system notifications, thus behavior depends on the platform.
-   *
-   *   * `Windows`: Uses `ReadDirectoryChangesW`. The implementation only
-   *     supports watching directories. Recursive watching is supported.
-   *   * `Linux`: Uses `inotify`. The implementation supports watching both
-   *     files and directories. Recursive watching is not supported.
-   *     Note: When watching files directly, delete events might not happen
-   *     as expected.
-   *   * `OS X`: Uses `FSEvents`. The implementation supports watching both
-   *     files and directories. Recursive watching is supported.
-   *
-   * The system will start listening for events once the returned [Stream] is
-   * being listened to, not when the call to [watch] is issued.
-   *
-   * The returned value is an endless broadcast [Stream], that only stops when
-   * one of the following happens:
-   *
-   *   * The [Stream] is canceled, e.g. by calling `cancel` on the
-   *      [StreamSubscription].
-   *   * The [FileSystemEntity] being watched, is deleted.
-   *   * System Watcher exits unexpectedly. e.g. On `Windows` this happens when
-   *     buffer that receive events from `ReadDirectoryChangesW` overflows.
-   *
-   * Use `events` to specify what events to listen for. The constants in
-   * [FileSystemEvent] can be or'ed together to mix events. Default is
-   * [FileSystemEvent.ALL].
-   *
-   * A move event may be reported as seperate delete and create events.
-   */
+  /// Start watching the [FileSystemEntity] for changes.
+  ///
+  /// The implementation uses platform-dependent event-based APIs for receiving
+  /// file-system notifications, thus behavior depends on the platform.
+  ///
+  ///   * `Windows`: Uses `ReadDirectoryChangesW`. The implementation only
+  ///     supports watching directories. Recursive watching is supported.
+  ///   * `Linux`: Uses `inotify`. The implementation supports watching both
+  ///     files and directories. Recursive watching is not supported.
+  ///     Note: When watching files directly, delete events might not happen
+  ///     as expected.
+  ///   * `OS X`: Uses `FSEvents`. The implementation supports watching both
+  ///     files and directories. Recursive watching is supported.
+  ///
+  /// The system will start listening for events once the returned [Stream] is
+  /// being listened to, not when the call to [watch] is issued.
+  ///
+  /// The returned value is an endless broadcast [Stream], that only stops when
+  /// one of the following happens:
+  ///
+  ///   * The [Stream] is canceled, e.g. by calling `cancel` on the
+  ///      [StreamSubscription].
+  ///   * The [FileSystemEntity] being watched is deleted.
+  ///   * System Watcher exits unexpectedly. e.g. On `Windows` this happens when
+  ///     buffer that receive events from `ReadDirectoryChangesW` overflows.
+  ///
+  /// Use `events` to specify what events to listen for. The constants in
+  /// [FileSystemEvent] can be or'ed together to mix events. Default is
+  /// [FileSystemEvent.ALL].
+  ///
+  /// A move event may be reported as seperate delete and create events.
   Stream<FileSystemEvent> watch(
-      {int events: FileSystemEvent.all, bool recursive: false}) {
+      {int events = FileSystemEvent.all, bool recursive = false}) {
     // FIXME(bkonyi): find a way to do this using the raw path.
     final String trimmedPath = _trimTrailingPathSeparators(path);
     final IOOverrides? overrides = IOOverrides.current;
@@ -498,8 +449,8 @@
     return overrides.fsWatch(trimmedPath, events, recursive);
   }
 
-  Future<FileSystemEntity> _delete({bool recursive: false});
-  void _deleteSync({bool recursive: false});
+  Future<FileSystemEntity> _delete({bool recursive = false});
+  void _deleteSync({bool recursive = false});
 
   static Future<bool> _identical(String path1, String path2) {
     return _File._dispatchWithNamespace(
@@ -512,20 +463,18 @@
     });
   }
 
-  /**
-   * Checks whether two paths refer to the same object in the
-   * file system.
-   *
-   * Returns a [:Future<bool>:] that completes with the result.
-   *
-   * Comparing a link to its target returns false, as does comparing two links
-   * that point to the same target.  To check the target of a link, use
-   * Link.target explicitly to fetch it.  Directory links appearing
-   * inside a path are followed, though, to find the file system object.
-   *
-   * Completes the returned Future with an error if one of the paths points
-   * to an object that does not exist.
-   */
+  /// Checks whether two paths refer to the same object in the
+  /// file system.
+  ///
+  /// Returns a `Future<bool>` that completes with the result.
+  ///
+  /// Comparing a link to its target returns `false`, as does comparing two links
+  /// that point to the same target.  To check the target of a link, use
+  /// Link.target explicitly to fetch it.  Directory links appearing
+  /// inside a path are followed, though, to find the file system object.
+  ///
+  /// Completes the returned Future with an error if one of the paths points
+  /// to an object that does not exist.
   static Future<bool> identical(String path1, String path2) {
     IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
@@ -537,26 +486,24 @@
   static final RegExp _absoluteWindowsPathPattern =
       new RegExp(r'^(?:\\\\|[a-zA-Z]:[/\\])');
 
-  /**
-   * Whether this object's path is absolute.
-   *
-   * An absolute path is independent of the current working
-   * directory ([Directory.current]).
-   * A non-absolute path must be interpreted relative to
-   * the current working directory.
-   *
-   * On Windows, a path is absolute if it starts with `\\`
-   * (two backslashesor representing a UNC path) or with a drive letter
-   * between `a` and `z` (upper or lower case) followed by `:\` or `:/`.
-   * The makes, for example, `\file.ext` a non-absolute path
-   * because it depends on the current drive letter.
-   *
-   * On non-Windows, a path is absolute if it starts with `/`.
-   *
-   * If the path is not absolute, use [absolute] to get an entity
-   * with an absolute path referencing the same object in the file system,
-   * if possible.
-   */
+  /// Whether this object's path is absolute.
+  ///
+  /// An absolute path is independent of the current working
+  /// directory ([Directory.current]).
+  /// A non-absolute path must be interpreted relative to
+  /// the current working directory.
+  ///
+  /// On Windows, a path is absolute if it starts with `\\`
+  /// (two backslashesor representing a UNC path) or with a drive letter
+  /// between `a` and `z` (upper or lower case) followed by `:\` or `:/`.
+  /// The makes, for example, `\file.ext` a non-absolute path
+  /// because it depends on the current drive letter.
+  ///
+  /// On non-Windows, a path is absolute if it starts with `/`.
+  ///
+  /// If the path is not absolute, use [absolute] to get an entity
+  /// with an absolute path referencing the same object in the file system,
+  /// if possible.
   bool get isAbsolute => _isAbsolute(path);
 
   static bool _isAbsolute(String path) {
@@ -567,16 +514,15 @@
     }
   }
 
-  /**
-   * Returns a [FileSystemEntity] whose path is the absolute path to [this].
-   *
-   * The type of the returned instance is the type of [this].
-   *
-   * A file system entity with an already absolute path
-   * (as reported by [isAbsolute]) is returned directly.
-   * For a non-absolute path, the returned entity is absolute ([isAbsolute])
-   * *if possible*, but still refers to the same file system object.
-   */
+  /// A [FileSystemEntity] whose path is the absolute path of [path].
+  ///
+  /// The type of the returned instance is the same as the type of
+  /// this entity.
+  ///
+  /// A file system entity with an already absolute path
+  /// (as reported by [isAbsolute]) is returned directly.
+  /// For a non-absolute path, the returned entity is absolute ([isAbsolute])
+  /// *if possible*, but still refers to the same file system object.
   FileSystemEntity get absolute;
 
   String get _absolutePath {
@@ -590,10 +536,10 @@
     }
   }
 
-  /// The ASCII code of the Windows drive letter if [entity], if any.
+  /// The ASCII code of the Windows drive letter of [path], if any.
   ///
   /// Returns the ASCII code of the upper-cased drive letter of
-  /// the path of [entity], if it has a drive letter (starts with `[a-zA-z]:`),
+  /// the path of [path], if it has a drive letter (starts with `[a-zA-z]:`),
   /// or `-1` if it has no drive letter.
   static int _windowsDriveLetter(String path) {
     if (path.isEmpty || !path.startsWith(':', 1)) return -1;
@@ -661,18 +607,16 @@
     return result;
   }
 
-  /**
-   * Synchronously checks whether two paths refer to the same object in the
-   * file system.
-   *
-   * Comparing a link to its target returns false, as does comparing two links
-   * that point to the same target.  To check the target of a link, use
-   * Link.target explicitly to fetch it.  Directory links appearing
-   * inside a path are followed, though, to find the file system object.
-   *
-   * Throws an error if one of the paths points to an object that does not
-   * exist.
-   */
+  /// Synchronously checks whether two paths refer to the same object in the
+  /// file system.
+  ///
+  /// Comparing a link to its target returns `false`, as does comparing two links
+  /// that point to the same target.  To check the target of a link, use
+  /// Link.target explicitly to fetch it.  Directory links appearing
+  /// inside a path are followed, though, to find the file system object.
+  ///
+  /// Throws an error if one of the paths points to an object that does not
+  /// exist.
   static bool identicalSync(String path1, String path2) {
     IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
@@ -681,11 +625,9 @@
     return overrides.fseIdenticalSync(path1, path2);
   }
 
-  /**
-   * Test if [watch] is supported on the current system.
-   *
-   * OS X 10.6 and below is not supported.
-   */
+  /// Test if [watch] is supported on the current system.
+  ///
+  /// OS X 10.6 and below is not supported.
   static bool get isWatchSupported {
     final IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
@@ -718,73 +660,68 @@
     return utf8.decode(nonNullTerminated, allowMalformed: true);
   }
 
-  /**
-   * Finds the type of file system object that a path points to.
-   *
-   * Returns a [:Future<FileSystemEntityType>:] that completes with the same
-   * results as [typeSync].
-   */
+  /// Finds the type of file system object that a path points to.
+  ///
+  /// Returns a `Future<FileSystemEntityType>` that completes with the same
+  /// results as [typeSync].
   static Future<FileSystemEntityType> type(String path,
-      {bool followLinks: true}) {
+      {bool followLinks = true}) {
     return _getType(_toUtf8Array(path), followLinks);
   }
 
-  /**
-   * Synchronously finds the type of file system object that a path points to.
-   *
-   * Returns a [FileSystemEntityType].
-   *
-   * Returns [FileSystemEntityType.link] only if [followLinks] is false and if
-   * [path] points to a link.
-   *
-   * Returns [FileSystemEntityType.notFound] if [path] does not point to a file
-   * system object or if any other error occurs in looking up the path.
-   */
-  static FileSystemEntityType typeSync(String path, {bool followLinks: true}) {
+  /// Synchronously finds the type of file system object that a path points to.
+  ///
+  /// Returns [FileSystemEntityType.link] only if [followLinks] is `false` and if
+  /// [path] points to a link.
+  ///
+  /// Returns [FileSystemEntityType.notFound] if [path] does not point to a file
+  /// system object or if any other error occurs in looking up the path.
+  static FileSystemEntityType typeSync(String path, {bool followLinks = true}) {
     return _getTypeSync(_toUtf8Array(path), followLinks);
   }
 
-  /**
-   * Checks if type(path, followLinks: false) returns FileSystemEntityType.link.
-   */
+  /// Whether [path] refers to a link.
+  ///
+  /// Checks whether `type(path, followLinks: false)`
+  /// returns [FileSystemEntityType.link].
   static Future<bool> isLink(String path) => _isLinkRaw(_toUtf8Array(path));
 
   static Future<bool> _isLinkRaw(Uint8List rawPath) => _getType(rawPath, false)
       .then((type) => (type == FileSystemEntityType.link));
 
-  /**
-   * Checks if type(path) returns FileSystemEntityType.file.
-   */
+  /// Whether [path] refers to a file.
+  ///
+  /// Checks whether `type(path)` returns [FileSystemEntityType.file].
   static Future<bool> isFile(String path) => _getType(_toUtf8Array(path), true)
       .then((type) => (type == FileSystemEntityType.file));
 
-  /**
-   * Checks if type(path) returns FileSystemEntityType.directory.
-   */
+  /// Whether [path]] refers to a directory.
+  ///
+  /// Checks whether `type(path)` returns [FileSystemEntityType.directory].
   static Future<bool> isDirectory(String path) =>
       _getType(_toUtf8Array(path), true)
           .then((type) => (type == FileSystemEntityType.directory));
 
-  /**
-   * Synchronously checks if typeSync(path, followLinks: false) returns
-   * FileSystemEntityType.link.
-   */
+  /// Synchronously checks whether [path] refers to a link.
+  ///
+  /// Checks whether `typeSync(path, followLinks: false)` returns
+  /// [FileSystemEntityType.link].
   static bool isLinkSync(String path) => _isLinkRawSync(_toUtf8Array(path));
 
   static bool _isLinkRawSync(rawPath) =>
       (_getTypeSync(rawPath, false) == FileSystemEntityType.link);
 
-  /**
-   * Synchronously checks if typeSync(path) returns
-   * FileSystemEntityType.file.
-   */
+  /// Synchronously checks whether [path] refers to a file.
+  ///
+  /// Checks whether `typeSync(path)` returns
+  /// [FileSystemEntityType.file].
   static bool isFileSync(String path) =>
       (_getTypeSync(_toUtf8Array(path), true) == FileSystemEntityType.file);
 
-  /**
-   * Synchronously checks if typeSync(path) returns
-   * FileSystemEntityType.directory.
-   */
+  /// Synchronously checks whether [path] refers to a directory.
+  ///
+  /// Checks whether `typeSync(path)` returns
+  /// [FileSystemEntityType.directory].
   static bool isDirectorySync(String path) =>
       (_getTypeSync(_toUtf8Array(path), true) ==
           FileSystemEntityType.directory);
@@ -800,14 +737,15 @@
       ? new RegExp(r'[^/\\][/\\]+[^/\\]')
       : new RegExp(r'[^/]/+[^/]');
 
-  /**
-   * Removes the final path component of a path, using the platform's
-   * path separator to split the path.
-   *
-   * Will not remove the root component of a Windows path, like "C:\\" or
-   * "\\\\server_name\\". Ignores trailing path separators, and leaves no
-   * trailing path separators.
-   */
+  /// The parent path of a path.
+  ///
+  /// Finds the final path component of a path, using the platform's
+  /// path separator to split the path, and returns the prefix up to
+  /// that part.
+  ///
+  /// Will not remove the root component of a Windows path, like "C:\\" or
+  /// "\\\\server_name\\". Includes a trailing path separator in the last
+  /// part of [path], and leaves no trailing path separator.
   static String parentOf(String path) {
     int rootEnd = -1;
     if (Platform.isWindows) {
@@ -833,9 +771,7 @@
     }
   }
 
-  /**
-   * The directory containing [this].
-   */
+  /// The parent directory of this entity.
   Directory get parent => new Directory(parentOf(path));
 
   static FileSystemEntityType _getTypeSyncHelper(
@@ -918,42 +854,30 @@
   }
 }
 
-/**
- * Base event class emitted by [FileSystemEntity.watch].
- */
+/// Base event class emitted by [FileSystemEntity.watch].
 class FileSystemEvent {
-  /**
-   * Bitfield for [FileSystemEntity.watch], to enable [FileSystemCreateEvent]s.
-   */
+  /// Bitfield for [FileSystemEntity.watch], to enable [FileSystemCreateEvent]s.
   static const int create = 1 << 0;
   @Deprecated("Use create instead")
   static const int CREATE = 1 << 0;
 
-  /**
-   * Bitfield for [FileSystemEntity.watch], to enable [FileSystemModifyEvent]s.
-   */
+  /// Bitfield for [FileSystemEntity.watch], to enable [FileSystemModifyEvent]s.
   static const int modify = 1 << 1;
   @Deprecated("Use modify instead")
   static const int MODIFY = 1 << 1;
 
-  /**
-   * Bitfield for [FileSystemEntity.watch], to enable [FileSystemDeleteEvent]s.
-   */
+  /// Bitfield for [FileSystemEntity.watch], to enable [FileSystemDeleteEvent]s.
   static const int delete = 1 << 2;
   @Deprecated("Use delete instead")
   static const int DELETE = 1 << 2;
 
-  /**
-   * Bitfield for [FileSystemEntity.watch], to enable [FileSystemMoveEvent]s.
-   */
+  /// Bitfield for [FileSystemEntity.watch], to enable [FileSystemMoveEvent]s.
   static const int move = 1 << 3;
   @Deprecated("Use move instead")
   static const int MOVE = 1 << 3;
 
-  /**
-   * Bitfield for [FileSystemEntity.watch], for enabling all of [create],
-   * [modify], [delete] and [move].
-   */
+  /// Bitfield for [FileSystemEntity.watch], for enabling all of [create],
+  /// [modify], [delete] and [move].
   static const int all = create | modify | delete | move;
   @Deprecated("Use all instead")
   static const int ALL = create | modify | delete | move;
@@ -962,34 +886,26 @@
   static const int _deleteSelf = 1 << 5;
   static const int _isDir = 1 << 6;
 
-  /**
-   * The type of event. See [FileSystemEvent] for a list of events.
-   */
+  /// The type of event. See [FileSystemEvent] for a list of events.
   final int type;
 
-  /**
-   * The path that triggered the event.
-   *
-   * Depending on the platform and the FileSystemEntity, the path may be
-   * relative.
-   */
+  /// The path that triggered the event.
+  ///
+  /// Depending on the platform and the [FileSystemEntity], the path may be
+  /// relative.
   final String path;
 
-  /**
-   * Is `true` if the event target was a directory.
-   *
-   * Note that if the file has been deleted by the time the event has arrived,
-   * this will always be `false` on Windows. In particular, it will always be
-   * `false` for `delete` events.
-   */
+  /// Is `true` if the event target was a directory.
+  ///
+  /// Note that if the file has been deleted by the time the event has arrived,
+  /// this will always be `false` on Windows. In particular, it will always be
+  /// `false` for `delete` events.
   final bool isDirectory;
 
   FileSystemEvent._(this.type, this.path, this.isDirectory);
 }
 
-/**
- * File system event for newly created file system objects.
- */
+/// File system event for newly created file system objects.
 class FileSystemCreateEvent extends FileSystemEvent {
   FileSystemCreateEvent._(path, isDirectory)
       : super._(FileSystemEvent.create, path, isDirectory);
@@ -997,14 +913,10 @@
   String toString() => "FileSystemCreateEvent('$path')";
 }
 
-/**
- * File system event for modifications of file system objects.
- */
+/// File system event for modifications of file system objects.
 class FileSystemModifyEvent extends FileSystemEvent {
-  /**
-   * If the content was changed and not only the attributes, [contentChanged]
-   * is `true`.
-   */
+  /// If the content was changed and not only the attributes, [contentChanged]
+  /// is `true`.
   final bool contentChanged;
 
   FileSystemModifyEvent._(path, isDirectory, this.contentChanged)
@@ -1014,9 +926,7 @@
       "FileSystemModifyEvent('$path', contentChanged=$contentChanged)";
 }
 
-/**
- * File system event for deletion of file system objects.
- */
+/// File system event for deletion of file system objects.
 class FileSystemDeleteEvent extends FileSystemEvent {
   FileSystemDeleteEvent._(path, isDirectory)
       : super._(FileSystemEvent.delete, path, isDirectory);
@@ -1024,14 +934,14 @@
   String toString() => "FileSystemDeleteEvent('$path')";
 }
 
-/**
- * File system event for moving of file system objects.
- */
+/// File system event for moving of file system objects.
 class FileSystemMoveEvent extends FileSystemEvent {
-  /**
-   * If the underlying implementation is able to identify the destination of
-   * the moved file, [destination] will be set. Otherwise, it will be `null`.
-   */
+  /// The destination path of the file being moved.
+  ///
+  /// The destination is `null` if the underlying implementation
+  /// is unable to identify the destination of the moved file.
+  ///
+  /// The source path is available as [path].
   final String? destination;
 
   FileSystemMoveEvent._(path, isDirectory, this.destination)
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index cabba39..5be8785 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -2,190 +2,191 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * File, socket, HTTP, and other I/O support for non-web applications.
- *
- * **Important:** Browser-based apps can't use this library.
- * Only the following can import and use the dart:io library:
- *   - Servers
- *   - Command-line scripts
- *   - Flutter mobile apps
- *   - Flutter desktop apps
- *
- * This library allows you to work with files, directories,
- * sockets, processes, HTTP servers and clients, and more.
- * Many operations related to input and output are asynchronous
- * and are handled using [Future]s or [Stream]s, both of which
- * are defined in the [dart:async
- * library](../dart-async/dart-async-library.html).
- *
- * To use the dart:io library in your code:
- *
- *     import 'dart:io';
- *
- * For an introduction to I/O in Dart, see the [dart:io library
- * tour](https://dart.dev/guides/libraries/library-tour#dartio).
- *
- * ## File, Directory, and Link
- *
- * An instance of [File], [Directory], or [Link] represents a file,
- * directory, or link, respectively, in the native file system.
- *
- * You can manipulate the file system through objects of these types.
- * For example, you can rename a file or directory:
- *
- *     File myFile = new File('myFile.txt');
- *     myFile.rename('yourFile.txt').then((_) => print('file renamed'));
- *
- * Many methods provided by the File, Directory, and Link classes
- * run asynchronously and return a Future.
- *
- * ## FileSystemEntity
- *
- * File, Directory, and Link all extend [FileSystemEntity].
- * In addition to being the superclass for these classes,
- * FileSystemEntity has a number of static methods for working with paths.
- *
- * To get information about a path,
- * you can use the FileSystemEntity static methods
- * such as 'isDirectory', 'isFile', and 'exists'.
- * Because file system access involves I/O, these methods
- * are asynchronous and return a Future.
- *
- *     FileSystemEntity.isDirectory(myPath).then((isDir) {
- *       if (isDir) {
- *         print('$myPath is a directory');
- *       } else {
- *         print('$myPath is not a directory');
- *       }
- *     });
- *
- * ## HttpServer and HttpClient
- *
- * The classes [HttpServer] and [HttpClient]
- * provide HTTP server and HTTP client functionality.
- *
- * The [HttpServer] class provides the basic functionality for
- * implementing an HTTP server.
- * For some higher-level building-blocks, we recommend that you try
- * the [shelf](https://pub.dev/packages/shelf)
- * pub package, which contains
- * a set of high-level classes that, together with the [HttpServer] class
- * in this library, make it easier to implement HTTP servers.
- *
- * ## Process
- *
- * The [Process] class provides a way to run a process on
- * the native machine.
- * For example, the following code spawns a process that recursively lists
- * the files under `web`.
- *
- *     Process.start('ls', ['-R', 'web']).then((process) {
- *       stdout.addStream(process.stdout);
- *       stderr.addStream(process.stderr);
- *       process.exitCode.then(print);
- *     });
- *
- * Using `start()` returns a Future, which completes with a [Process] object
- * when the process has started. This [Process] object allows you to interact
- * with the process while it is running. Using `run()` returns a Future, which
- * completes with a [ProcessResult] object when the spawned process has
- * terminated. This [ProcessResult] object collects the output and exit code
- * from the process.
- *
- * When using `start()`,
- * you need to read all data coming on the stdout and stderr streams otherwise
- * the system resources will not be freed.
- *
- * ## WebSocket
- *
- * The [WebSocket] class provides support for the web socket protocol. This
- * allows full-duplex communications between client and server applications.
- *
- * A web socket server uses a normal HTTP server for accepting web socket
- * connections. The initial handshake is a HTTP request which is then upgraded to a
- * web socket connection.
- * The server upgrades the request using [WebSocketTransformer]
- * and listens for the data on the returned web socket.
- * For example, here's a mini server that listens for 'ws' data
- * on a WebSocket:
- *
- *     runZoned(() async {
- *       var server = await HttpServer.bind('127.0.0.1', 4040);
- *       server.listen((HttpRequest req) async {
- *         if (req.uri.path == '/ws') {
- *           var socket = await WebSocketTransformer.upgrade(req);
- *           socket.listen(handleMsg);
- *         }
- *       });
- *     }, onError: (e) => print("An error occurred."));
- *
- * The client connects to the WebSocket using the `connect()` method
- * and a URI that uses the Web Socket protocol.
- * The client can write to the WebSocket with the `add()` method.
- * For example,
- *
- *     var socket = await WebSocket.connect('ws://127.0.0.1:4040/ws');
- *     socket.add('Hello, World!');
- *
- * Check out the
- * [websocket_sample](https://github.com/dart-lang/dart-samples/tree/master/html5/web/websockets/basics)
- * app, which uses WebSockets to communicate with a server.
- *
- * ## Socket and ServerSocket
- *
- * Clients and servers use [Socket]s to communicate using the TCP protocol.
- * Use [ServerSocket] on the server side and [Socket] on the client.
- * The server creates a listening socket using the `bind()` method and
- * then listens for incoming connections on the socket. For example:
- *
- *     ServerSocket.bind('127.0.0.1', 4041)
- *       .then((serverSocket) {
- *         serverSocket.listen((socket) {
- *           socket.transform(utf8.decoder).listen(print);
- *         });
- *       });
- *
- * A client connects a Socket using the `connect()` method,
- * which returns a Future.
- * Using `write()`, `writeln()`, or `writeAll()` are the easiest ways to
- * send data over the socket.
- * For example:
- *
- *     Socket.connect('127.0.0.1', 4041).then((socket) {
- *       socket.write('Hello, World!');
- *     });
- *
- * Besides [Socket] and [ServerSocket], the [RawSocket] and
- * [RawServerSocket] classes are available for lower-level access
- * to async socket IO.
- *
- * ## Standard output, error, and input streams
- *
- * This library provides the standard output, error, and input
- * streams, named 'stdout', 'stderr', and 'stdin', respectively.
- *
- * The stdout and stderr streams are both [IOSink]s and have the same set
- * of methods and properties.
- *
- * To write a string to 'stdout':
- *
- *     stdout.writeln('Hello, World!');
- *
- * To write a list of objects to 'stderr':
- *
- *     stderr.writeAll([ 'That ', 'is ', 'an ', 'error.', '\n']);
- *
- * The standard input stream is a true [Stream], so it inherits
- * properties and methods from the Stream class.
- *
- * To read text synchronously from the command line
- * (the program blocks waiting for user to type information):
- *
- *      String inputText = stdin.readLineSync();
- *
- * {@category VM}
- */
+/// File, socket, HTTP, and other I/O support for non-web applications.
+///
+/// **Important:** Browser-based apps can't use this library.
+/// Only the following can import and use the dart:io library:
+///   - Servers
+///   - Command-line scripts
+///   - Flutter mobile apps
+///   - Flutter desktop apps
+///
+/// This library allows you to work with files, directories,
+/// sockets, processes, HTTP servers and clients, and more.
+/// Many operations related to input and output are asynchronous
+/// and are handled using [Future]s or [Stream]s, both of which
+/// are defined in the [dart:async
+/// library](../dart-async/dart-async-library.html).
+///
+/// To use the dart:io library in your code:
+/// ```dart
+/// import 'dart:io';
+/// ```
+/// For an introduction to I/O in Dart, see the [dart:io library
+/// tour](https://dart.dev/guides/libraries/library-tour#dartio).
+///
+/// ## File, Directory, and Link
+///
+/// An instance of [File], [Directory], or [Link] represents a file,
+/// directory, or link, respectively, in the native file system.
+///
+/// You can manipulate the file system through objects of these types.
+/// For example, you can rename a file or directory:
+/// ```dart
+/// File myFile = File('myFile.txt');
+/// myFile.rename('yourFile.txt').then((_) => print('file renamed'));
+/// ```
+/// Many methods provided by the [File], [Directory], and [Link] classes
+/// run asynchronously and return a [Future].
+///
+/// ## FileSystemEntity
+///
+/// [File], [Directory], and [Link] all extend [FileSystemEntity].
+/// In addition to being the superclass for these classes,
+/// FileSystemEntity has a number of static methods for working with paths.
+///
+/// To get information about a path,
+/// you can use the [FileSystemEntity] static methods
+/// such as [FileSystemEntitiy.isDirectory], [FileSystemEntitiy.isFile],
+/// and [FileSystemEntitiy.exists].
+/// Because file system access involves I/O, these methods
+/// are asynchronous and return a [Future].
+/// ```dart
+/// FileSystemEntity.isDirectory(myPath).then((isDir) {
+///   if (isDir) {
+///     print('$myPath is a directory');
+///   } else {
+///     print('$myPath is not a directory');
+///   }
+/// });
+/// ```
+/// ## HttpServer and HttpClient
+///
+/// The classes [HttpServer] and [HttpClient]
+/// provide HTTP server and HTTP client functionality.
+///
+/// The [HttpServer] class provides the basic functionality for
+/// implementing an HTTP server.
+/// For some higher-level building-blocks, we recommend that you try
+/// the [shelf](https://pub.dev/packages/shelf)
+/// pub package, which contains
+/// a set of high-level classes that, together with the [HttpServer] class
+/// in this library, make it easier to implement HTTP servers.
+///
+/// ## Process
+///
+/// The [Process] class provides a way to run a process on
+/// the native machine.
+/// For example, the following code spawns a process that recursively lists
+/// the files under `web`.
+/// ```dart
+/// Process.start('ls', ['-R', 'web']).then((process) {
+///   stdout.addStream(process.stdout);
+///   stderr.addStream(process.stderr);
+///   process.exitCode.then(print);
+/// });
+/// ```
+/// Using [Process.start] returns a [Future],
+/// which completes with a [Process] object when the process has started.
+/// This [Process] object allows you to interact
+/// with the process while it is running.
+/// Using [Process.run] returns a [Future],
+/// which completes with a [ProcessResult] object when the spawned process has
+/// terminated. This [ProcessResult] object collects the output and exit code
+/// from the process.
+///
+/// When using [Process.start],
+/// you need to read all data coming on the [Process.stdout] and [Process.stderr]
+/// streams, otherwise the system resources will not be freed.
+///
+/// ## WebSocket
+///
+/// The [WebSocket] class provides support for the web socket protocol. This
+/// allows full-duplex communications between client and server applications.
+///
+/// A web socket server uses a normal HTTP server for accepting web socket
+/// connections. The initial handshake is a HTTP request which is then upgraded to a
+/// web socket connection.
+/// The server upgrades the request using [WebSocketTransformer]
+/// and listens for the data on the returned web socket.
+/// For example, here's a mini server that listens for 'ws' data
+/// on a WebSocket:
+/// ```dart
+/// runZoned(() async {
+///   var server = await HttpServer.bind('127.0.0.1', 4040);
+///   server.listen((HttpRequest req) async {
+///     if (req.uri.path == '/ws') {
+///       var socket = await WebSocketTransformer.upgrade(req);
+///       socket.listen(handleMsg);
+///     }
+///   });
+/// }, onError: (e) => print("An error occurred."));
+/// ```
+/// The client connects to the [WebSocket] using the [WebSocket.connect] method
+/// and a URI that uses the Web Socket protocol.
+/// The client can write to the [WebSocket] with the [Websocket.add] method.
+/// For example,
+/// ```dart
+/// var socket = await WebSocket.connect('ws://127.0.0.1:4040/ws');
+/// socket.add('Hello, World!');
+/// ```
+/// Check out the
+/// [websocket_sample](https://github.com/dart-lang/dart-samples/tree/master/html5/web/websockets/basics)
+/// app, which uses [WebSocket]s to communicate with a server.
+///
+/// ## Socket and ServerSocket
+///
+/// Clients and servers use [Socket]s to communicate using the TCP protocol.
+/// Use [ServerSocket] on the server side and [Socket] on the client.
+/// The server creates a listening socket using the `bind()` method and
+/// then listens for incoming connections on the socket. For example:
+/// ```dart
+/// ServerSocket.bind('127.0.0.1', 4041)
+///   .then((serverSocket) {
+///     serverSocket.listen((socket) {
+///       socket.transform(utf8.decoder).listen(print);
+///     });
+///   });
+/// ```
+/// A client connects a [Socket] using the `connect()` method,
+/// which returns a [Future].
+/// Using `write()`, `writeln()`, or `writeAll()` are the easiest ways to
+/// send data over the socket.
+/// For example:
+/// ```dart
+/// Socket.connect('127.0.0.1', 4041).then((socket) {
+///   socket.write('Hello, World!');
+/// });
+/// ```
+/// Besides [Socket] and [ServerSocket], the [RawSocket] and
+/// [RawServerSocket] classes are available for lower-level access
+/// to async socket IO.
+///
+/// ## Standard output, error, and input streams
+///
+/// This library provides the standard output, error, and input
+/// streams, named [stdout], [stderr], and [stdin], respectively.
+///
+/// The [stdout] and [stderr] streams are both [IOSink]s and have the same set
+/// of methods and properties.
+///
+/// To write a string to [stdout]:
+/// ```dart
+/// stdout.writeln('Hello, World!');
+/// ```
+/// To write a list of objects to [stderr]:
+/// ```dart
+/// stderr.writeAll([ 'That ', 'is ', 'an ', 'error.', '\n']);
+/// ```
+/// The standard input stream is a true [Stream], so it inherits
+/// properties and methods from the [Stream] class.
+///
+/// To read text synchronously from the command line
+/// (the program blocks waiting for user to type information):
+/// ```dart
+/// String inputText = stdin.readLineSync();
+/// ```
+/// {@category VM}
 library dart.io;
 
 import 'dart:async';
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index 622656a..60de5da 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.dart
@@ -4,137 +4,117 @@
 
 part of dart.io;
 
-/**
- * A combined byte and text output.
- *
- * An [IOSink] combines a [StreamSink] of bytes with a [StringSink],
- * and allows easy output of both bytes and text.
- *
- * Writing text ([write]) and adding bytes ([add]) may be interleaved freely.
- *
- * While a stream is being added using [addStream], any further attempts
- * to add or write to the [IOSink] will fail until the [addStream] completes.
- *
- * It is an error to add data to the [IOSink] after the sink is closed.
- */
+/// A combined byte and text output.
+///
+/// An [IOSink] combines a [StreamSink] of bytes with a [StringSink],
+/// and allows easy output of both bytes and text.
+///
+/// Writing text ([write]) and adding bytes ([add]) may be interleaved freely.
+///
+/// While a stream is being added using [addStream], any further attempts
+/// to add or write to the [IOSink] will fail until the [addStream] completes.
+///
+/// It is an error to add data to the [IOSink] after the sink is closed.
 abstract class IOSink implements StreamSink<List<int>>, StringSink {
-  /**
-   * Create an [IOSink] that outputs to a [target] [StreamConsumer] of bytes.
-   *
-   * Text written to [StreamSink] methods is encoded to bytes using [encoding]
-   * before being output on [target].
-   */
-  factory IOSink(StreamConsumer<List<int>> target, {Encoding encoding: utf8}) =>
+  /// Create an [IOSink] that outputs to a [target] [StreamConsumer] of bytes.
+  ///
+  /// Text written to [StreamSink] methods is encoded to bytes using [encoding]
+  /// before being output on [target].
+  factory IOSink(StreamConsumer<List<int>> target,
+          {Encoding encoding = utf8}) =>
       new _IOSinkImpl(target, encoding);
 
-  /**
-   * The [Encoding] used when writing strings. Depending on the
-   * underlying consumer this property might be mutable.
-   */
+  /// The [Encoding] used when writing strings.
+  ///
+  /// Depending on the underlying consumer, this property might be mutable.
   late Encoding encoding;
 
-  /**
-   * Adds byte [data] to the target consumer, ignoring [encoding].
-   *
-   * The [encoding] does not apply to this method, and the `data` list is passed
-   * directly to the target consumer as a stream event.
-   *
-   * This function must not be called when a stream is currently being added
-   * using [addStream].
-   *
-   * This operation is non-blocking. See [flush] or [done] for how to get any
-   * errors generated by this call.
-   *
-   * The data list should not be modified after it has been passed to `add`.
-   */
+  /// Adds byte [data] to the target consumer, ignoring [encoding].
+  ///
+  /// The [encoding] does not apply to this method, and the [data] list is passed
+  /// directly to the target consumer as a stream event.
+  ///
+  /// This function must not be called when a stream is currently being added
+  /// using [addStream].
+  ///
+  /// This operation is non-blocking. See [flush] or [done] for how to get any
+  /// errors generated by this call.
+  ///
+  /// The data list should not be modified after it has been passed to `add`.
   void add(List<int> data);
 
-  /**
-   * Converts [obj] to a String by invoking [Object.toString] and
-   * [add]s the encoding of the result to the target consumer.
-   *
-   * This operation is non-blocking. See [flush] or [done] for how to get any
-   * errors generated by this call.
-   */
-  void write(Object? obj);
+  /// Converts [object] to a String by invoking [Object.toString] and
+  /// [add]s the encoding of the result to the target consumer.
+  ///
+  /// This operation is non-blocking. See [flush] or [done] for how to get any
+  /// errors generated by this call.
+  void write(Object? object);
 
-  /**
-   * Iterates over the given [objects] and [write]s them in sequence.
-   *
-   * If [separator] is provided, a `write` with the `separator` is performed
-   * between any two elements of objects.
-   *
-   * This operation is non-blocking. See [flush] or [done] for how to get any
-   * errors generated by this call.
-   */
+  /// Iterates over the given [objects] and [write]s them in sequence.
+  ///
+  /// If [separator] is provided, a `write` with the `separator` is performed
+  /// between any two elements of objects.
+  ///
+  /// This operation is non-blocking. See [flush] or [done] for how to get any
+  /// errors generated by this call.
   void writeAll(Iterable objects, [String separator = ""]);
 
-  /**
-   * Converts [obj] to a String by invoking [Object.toString] and
-   * writes the result to `this`, followed by a newline.
-   *
-   * This operation is non-blocking. See [flush] or [done] for how to get any
-   * errors generated by this call.
-   */
-  void writeln([Object? obj = ""]);
+  /// Converts [object] to a String by invoking [Object.toString] and
+  /// writes the result to `this`, followed by a newline.
+  ///
+  /// This operation is non-blocking. See [flush] or [done] for how to get any
+  /// errors generated by this call.
+  void writeln([Object? object = ""]);
 
-  /**
-   * Writes the character of [charCode].
-   *
-   * This method is equivalent to `write(new String.fromCharCode(charCode))`.
-   *
-   * This operation is non-blocking. See [flush] or [done] for how to get any
-   * errors generated by this call.
-   */
+  /// Writes the character of [charCode].
+  ///
+  /// This method is equivalent to `write(String.fromCharCode(charCode))`.
+  ///
+  /// This operation is non-blocking. See [flush] or [done] for how to get any
+  /// errors generated by this call.
   void writeCharCode(int charCode);
 
-  /**
-   * Passes the error to the target consumer as an error event.
-   *
-   * This function must not be called when a stream is currently being added
-   * using [addStream].
-   *
-   * This operation is non-blocking. See [flush] or [done] for how to get any
-   * errors generated by this call.
-   */
+  /// Passes the error to the target consumer as an error event.
+  ///
+  /// This function must not be called when a stream is currently being added
+  /// using [addStream].
+  ///
+  /// This operation is non-blocking. See [flush] or [done] for how to get any
+  /// errors generated by this call.
   void addError(error, [StackTrace? stackTrace]);
 
-  /**
-   * Adds all elements of the given [stream] to `this`.
-   *
-   * Returns a [Future] that completes when
-   * all elements of the given [stream] are added to `this`.
-   *
-   * This function must not be called when a stream is currently being added
-   * using this function.
-   */
+  /// Adds all elements of the given [stream].
+  ///
+  /// Returns a [Future] that completes when
+  /// all elements of the given [stream] have been added.
+  ///
+  /// If the stream contains an error, the `addStream` ends at the error,
+  /// and the returned future completes with that error.
+  ///
+  /// This function must not be called when a stream is currently being added
+  /// using this function.
   Future addStream(Stream<List<int>> stream);
 
-  /**
-   * Returns a [Future] that completes once all buffered data is accepted by the
-   * underlying [StreamConsumer].
-   *
-   * This method must not be called while an [addStream] is incomplete.
-   *
-   * NOTE: This is not necessarily the same as the data being flushed by the
-   * operating system.
-   */
+  /// Returns a [Future] that completes once all buffered data is accepted by the
+  /// underlying [StreamConsumer].
+  ///
+  /// This method must not be called while an [addStream] is incomplete.
+  ///
+  /// NOTE: This is not necessarily the same as the data being flushed by the
+  /// operating system.
   Future flush();
 
-  /**
-   * Close the target consumer.
-   *
-   * NOTE: Writes to the [IOSink] may be buffered, and may not be flushed by
-   * a call to `close()`. To flush all buffered writes, call `flush()` before
-   * calling `close()`.
-   */
+  /// Close the target consumer.
+  ///
+  /// NOTE: Writes to the [IOSink] may be buffered, and may not be flushed by
+  /// a call to `close()`. To flush all buffered writes, call `flush()` before
+  /// calling `close()`.
   Future close();
 
-  /**
-   * Get a future that will complete when the consumer closes, or when an
-   * error occurs. This future is identical to the future returned by
-   * [close].
-   */
+  /// A future that will complete when the consumer closes, or when an
+  /// error occurs.
+  ///
+  /// This future is identical to the future returned by [close].
   Future get done;
 }
 
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index ce50a4e..c7320ea 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -4,15 +4,10 @@
 
 part of dart.io;
 
-/**
- * [Link] objects are references to filesystem links.
- *
- */
+/// References to filesystem links.
 @pragma("vm:entry-point")
 abstract class Link implements FileSystemEntity {
-  /**
-   * Creates a Link object.
-   */
+  /// Creates a Link object.
   @pragma("vm:entry-point")
   factory Link(String path) {
     final IOOverrides? overrides = IOOverrides.current;
@@ -28,127 +23,119 @@
     return new _Link.fromRawPath(rawPath);
   }
 
-  /**
-   * Creates a [Link] object.
-   *
-   * If [path] is a relative path, it will be interpreted relative to the
-   * current working directory (see [Directory.current]), when used.
-   *
-   * If [path] is an absolute path, it will be immune to changes to the
-   * current working directory.
-   */
+  /// Creates a [Link] object.
+  ///
+  /// If [path] is a relative path, it will be interpreted relative to the
+  /// current working directory (see [Directory.current]), when used.
+  ///
+  /// If [path] is an absolute path, it will be immune to changes to the
+  /// current working directory.
   factory Link.fromUri(Uri uri) => new Link(uri.toFilePath());
 
-  /**
-   * Creates a symbolic link. Returns a [:Future<Link>:] that completes with
-   * the link when it has been created. If the link exists,
-   * the future will complete with an error.
-   *
-   * If [recursive] is false, the default, the link is created
-   * only if all directories in its path exist.
-   * If [recursive] is true, all non-existing path
-   * components are created. The directories in the path of [target] are
-   * not affected, unless they are also in [path].
-   *
-   * On the Windows platform, this call will create a true symbolic link
-   * instead of a Junction. In order to create a symbolic link on Windows, Dart
-   * must be run in Administrator mode or the system must have Developer Mode
-   * enabled, otherwise a [FileSystemException] will be raised with
-   * `ERROR_PRIVILEGE_NOT_HELD` set as the errno when this call is made.
-   *
-   * On other platforms, the posix symlink() call is used to make a symbolic
-   * link containing the string [target].  If [target] is a relative path,
-   * it will be interpreted relative to the directory containing the link.
-   */
-  Future<Link> create(String target, {bool recursive: false});
+  /// Creates a symbolic link in the file system.
+  ///
+  /// Returns a `Future<Link>` that completes with
+  /// the link when it has been created. If the link path already exists,
+  /// the future will complete with an error.
+  ///
+  /// If [recursive] is `false`, the default, the link is created
+  /// only if all directories in its path exist.
+  /// If [recursive] is `true`, all non-existing parent paths
+  /// are created first. The directories in the path of [target] are
+  /// not affected, unless they are also in [path].
+  ///
+  /// On the Windows platform, this call will create a true symbolic link
+  /// instead of a Junction. In order to create a symbolic link on Windows, Dart
+  /// must be run in Administrator mode or the system must have Developer Mode
+  /// enabled, otherwise a [FileSystemException] will be raised with
+  /// `ERROR_PRIVILEGE_NOT_HELD` set as the errno when this call is made.
+  ///
+  /// On other platforms, the POSIX `symlink()` call is used to make a symbolic
+  /// link containing the string [target]. If [target] is a relative path,
+  /// it will be interpreted relative to the directory containing the link.
+  Future<Link> create(String target, {bool recursive = false});
 
-  /**
-   * Synchronously create the link. Calling [createSync] on an existing link
-   * will throw an exception.
-   *
-   * If [recursive] is false, the default, the link is created only if all
-   * directories in its path exist. If [recursive] is true, all
-   * non-existing path components are created. The directories in
-   * the path of [target] are not affected, unless they are also in [path].
-   *
-   * On the Windows platform, this call will create a true symbolic link
-   * instead of a Junction. In order to create a symbolic link on Windows, Dart
-   * must be run in Administrator mode or the system must have Developer Mode
-   * enabled, otherwise a [FileSystemException] will be raised with
-   * `ERROR_PRIVILEGE_NOT_HELD` set as the errno when this call is made.
-   *
-   * On other platforms, the posix symlink() call is used to make a symbolic
-   * link containing the string [target].  If [target] is a relative path,
-   * it will be interpreted relative to the directory containing the link.
-   */
-  void createSync(String target, {bool recursive: false});
+  /// Synchronously create the link. Calling [createSync] on an existing link
+  /// will throw an exception.
+  ///
+  /// If [recursive] is `false`, the default, the link is created only if all
+  /// directories in its path exist. If [recursive] is `true`, all
+  /// non-existing parent paths are created first. The directories in
+  /// the path of [target] are not affected, unless they are also in [path].
+  ///
+  /// On the Windows platform, this call will create a true symbolic link
+  /// instead of a Junction. In order to create a symbolic link on Windows, Dart
+  /// must be run in Administrator mode or the system must have Developer Mode
+  /// enabled, otherwise a [FileSystemException] will be raised with
+  /// `ERROR_PRIVILEGE_NOT_HELD` set as the errno when this call is made.
+  ///
+  /// On other platforms, the POSIX `symlink()` call is used to make a symbolic
+  /// link containing the string [target]. If [target] is a relative path,
+  /// it will be interpreted relative to the directory containing the link.
+  void createSync(String target, {bool recursive = false});
 
-  /**
-   * Synchronously updates the link. Calling [updateSync] on a non-existing link
-   * will throw an exception.
-   */
+  /// Synchronously updates the link.
+  ///
+  /// Calling [updateSync] on a non-existing link will throw an exception.
   void updateSync(String target);
 
-  /**
-   * Updates the link. Returns a [:Future<Link>:] that completes with the
-   * link when it has been updated.  Calling [update] on a non-existing link
-   * will complete its returned future with an exception.
-   */
+  /// Updates the link.
+  ///
+  /// Returns a `Future<Link>` that completes with the
+  /// link when it has been updated. Calling [update] on a non-existing link
+  /// will complete its returned future with an exception.
   Future<Link> update(String target);
 
   Future<String> resolveSymbolicLinks();
 
   String resolveSymbolicLinksSync();
 
-  /**
-   * Renames this link. Returns a `Future<Link>` that completes
-   * with a [Link] instance for the renamed link.
-   *
-   * If [newPath] identifies an existing link, that link is
-   * replaced. If [newPath] identifies an existing file or directory,
-   * the operation fails and the future completes with an exception.
-   */
+  /// Renames this link.
+  ///
+  /// Returns a `Future<Link>` that completes with a [Link]
+  /// for the renamed link.
+  ///
+  /// If [newPath] identifies an existing link, that link is
+  /// removed first. If [newPath] identifies an existing file or directory,
+  /// the operation fails and the future completes with an exception.
   Future<Link> rename(String newPath);
 
-  /**
-   * Synchronously renames this link. Returns a [Link]
-   * instance for the renamed link.
-   *
-   * If [newPath] identifies an existing link, that link is
-   * replaced. If [newPath] identifies an existing file or directory
-   * the operation fails and an exception is thrown.
-   */
+  /// Synchronously renames this link.
+  ///
+  /// Returns a [Link] instance for the renamed link.
+  ///
+  /// If [newPath] identifies an existing link, that link is
+  /// removed first. If [newPath] identifies an existing file or directory
+  /// the operation fails and an exception is thrown.
   Link renameSync(String newPath);
 
-  /**
-   * Returns a [Link] instance whose path is the absolute path to [this].
-   *
-   * The absolute path is computed by prefixing
-   * a relative path with the current working directory, and returning
-   * an absolute path unchanged.
-   */
+  /// A [Link] instance whose path is the absolute path to [this].
+  ///
+  /// The absolute path is computed by prefixing
+  /// a relative path with the current working directory, or returning
+  /// an absolute path unchanged.
   Link get absolute;
 
-  /**
-   * Gets the target of the link. Returns a future that completes with
-   * the path to the target.
-   *
-   * If the returned target is a relative path, it is relative to the
-   * directory containing the link.
-   *
-   * If the link does not exist, or is not a link, the future completes with
-   * a FileSystemException.
-   */
+  /// Gets the target of the link.
+  ///
+  /// Returns a future that completes with the path to the target.
+  ///
+  /// If the returned target is a relative path, it is relative to the
+  /// directory containing the link.
+  ///
+  /// If the link does not exist, or is not a link, the future completes with
+  /// a [FileSystemException].
   Future<String> target();
 
-  /**
-   * Synchronously gets the target of the link. Returns the path to the target.
-   *
-   * If the returned target is a relative path, it is relative to the
-   * directory containing the link.
-   *
-   * If the link does not exist, or is not a link, throws a FileSystemException.
-   */
+  /// Synchronously gets the target of the link.
+  ///
+  /// Returns the path to the target.
+  ///
+  /// If the returned target is a relative path, it is relative to the
+  /// directory containing the link.
+  ///
+  /// If the link does not exist, or is not a link,
+  /// throws a [FileSystemException].
   String targetSync();
 }
 
@@ -174,7 +161,7 @@
 
   Link get absolute => isAbsolute ? this : _Link(_absolutePath);
 
-  Future<Link> create(String target, {bool recursive: false}) {
+  Future<Link> create(String target, {bool recursive = false}) {
     var result =
         recursive ? parent.create(recursive: true) : new Future.value(null);
     return result
@@ -189,7 +176,7 @@
     });
   }
 
-  void createSync(String target, {bool recursive: false}) {
+  void createSync(String target, {bool recursive = false}) {
     if (recursive) {
       parent.createSync(recursive: true);
     }
@@ -214,7 +201,7 @@
     return delete().then<Link>((_) => create(target));
   }
 
-  Future<Link> _delete({bool recursive: false}) {
+  Future<Link> _delete({bool recursive = false}) {
     if (recursive) {
       return new Directory.fromRawPath(_rawPath)
           .delete(recursive: true)
@@ -229,7 +216,7 @@
     });
   }
 
-  void _deleteSync({bool recursive: false}) {
+  void _deleteSync({bool recursive = false}) {
     if (recursive) {
       return new Directory.fromRawPath(_rawPath).deleteSync(recursive: true);
     }
diff --git a/sdk/lib/io/overrides.dart b/sdk/lib/io/overrides.dart
index 4b7deaa..245b9d7 100644
--- a/sdk/lib/io/overrides.dart
+++ b/sdk/lib/io/overrides.dart
@@ -8,12 +8,12 @@
 
 const _asyncRunZoned = runZoned;
 
-/// This class facilitates overriding various APIs of dart:io with mock
+/// Facilities for overriding various APIs of `dart:io` with mock
 /// implementations.
 ///
 /// This abstract base class should be extended with overrides for the
 /// operations needed to construct mocks. The implementations in this base class
-/// default to the actual dart:io implementation. For example:
+/// default to the actual `dart:io` implementation. For example:
 ///
 /// ```
 /// class MyDirectory implements Directory {
@@ -22,7 +22,7 @@
 ///   ...
 /// }
 ///
-/// main() {
+/// void main() {
 ///   IOOverrides.runZoned(() {
 ///     ...
 ///     // Operations will use MyDirectory instead of dart:io's Directory
@@ -40,16 +40,16 @@
 
   /// The [IOOverrides] to use in the root [Zone].
   ///
-  /// These are the [IOOverrides] that will be used in the root Zone, and in
-  /// Zone's that do not set [IOOverrides] and whose ancestors up to the root
-  /// Zone do not set [IOOverrides].
+  /// These are the [IOOverrides] that will be used in the root [Zone], and in
+  /// [Zone]'s that do not set [IOOverrides] and whose ancestors up to the root
+  /// [Zone] also do not set [IOOverrides].
   static set global(IOOverrides? overrides) {
     _global = overrides;
   }
 
   /// Runs [body] in a fresh [Zone] using the provided overrides.
   ///
-  /// See the documentation on the corresponding methods of IOOverrides for
+  /// See the documentation on the corresponding methods of [IOOverrides] for
   /// information about what the optional arguments do.
   static R runZoned<R>(R body(),
       {
@@ -282,7 +282,7 @@
   /// When this override is installed, this functions overrides the behavior of
   /// `ServerSocket.bind(...)`.
   Future<ServerSocket> serverSocketBind(address, int port,
-      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+      {int backlog = 0, bool v6Only = false, bool shared = false}) {
     return ServerSocket._bind(address, port,
         backlog: backlog, v6Only: v6Only, shared: shared);
   }
@@ -499,9 +499,10 @@
   }
 
   // ServerSocket
+
   @override
   Future<ServerSocket> serverSocketBind(address, int port,
-      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+      {int backlog = 0, bool v6Only = false, bool shared = false}) {
     if (_serverSocketBind != null) {
       return _serverSocketBind!(address, port,
           backlog: backlog, v6Only: v6Only, shared: shared);
diff --git a/sdk/lib/io/platform.dart b/sdk/lib/io/platform.dart
index c484461..cedaeba 100644
--- a/sdk/lib/io/platform.dart
+++ b/sdk/lib/io/platform.dart
@@ -4,61 +4,60 @@
 
 part of dart.io;
 
-/**
- * Information about the environment in which the current program is running.
- *
- * Platform provides information such as the operating system,
- * the hostname of the computer, the value of environment variables,
- * the path to the running program,
- * and so on.
- *
- * ## Get the URI to the current Dart script
- *
- * Use the [script] getter to get the URI to the currently running
- * Dart script.
- *
- *     import 'dart:io' show Platform;
- *
- *     void main() {
- *       // Get the URI of the script being run.
- *       var uri = Platform.script;
- *       // Convert the URI to a path.
- *       var path = uri.toFilePath();
- *     }
- *
- * ## Get the value of an environment variable
- *
- * The [environment] getter returns a the names and values of environment
- * variables in a [Map] that contains key-value pairs of strings. The Map is
- * unmodifiable. This sample shows how to get the value of the `PATH`
- * environment variable.
- *
- *     import 'dart:io' show Platform;
- *
- *     void main() {
- *       Map<String, String> envVars = Platform.environment;
- *       print(envVars['PATH']);
- *     }
- *
- * ## Determine the OS
- *
- * You can get the name of the operating system as a string with the
- * [operatingSystem] getter. You can also use one of the static boolean
- * getters: [isMacOS], [isLinux], and [isWindows].
- *
- *     import 'dart:io' show Platform, stdout;
- *
- *     void main() {
- *       // Get the operating system as a string.
- *       String os = Platform.operatingSystem;
- *       // Or, use a predicate getter.
- *       if (Platform.isMacOS) {
- *         print('is a Mac');
- *       } else {
- *         print('is not a Mac');
- *       }
- *     }
- */
+/// Information about the environment in which the current program is running.
+///
+/// Platform provides information such as the operating system,
+/// the hostname of the computer, the value of environment variables,
+/// the path to the running program,
+/// and other global properties of the program being run.
+///
+/// ## Get the URI of the current Dart script
+///
+/// Use the [script] getter to get the URI to the currently running
+/// Dart script.
+/// ```dart
+/// import 'dart:io' show Platform;
+///
+/// void main() {
+///   // Get the URI of the script being run.
+///   var uri = Platform.script;
+///   // Convert the URI to a path.
+///   var path = uri.toFilePath();
+/// }
+/// ```
+/// ## Get the value of an environment variable
+///
+/// The [environment] getter returns a the names and values of environment
+/// variables in a [Map] that contains key-value pairs of strings. The Map is
+/// unmodifiable. This sample shows how to get the value of the `PATH`
+/// environment variable.
+/// ```dart
+/// import 'dart:io' show Platform;
+///
+/// void main() {
+///   Map<String, String> envVars = Platform.environment;
+///   print(envVars['PATH']);
+/// }
+/// ```
+/// ## Determine the OS
+///
+/// You can get the name of the operating system as a string with the
+/// [operatingSystem] getter. You can also use one of the static boolean
+/// getters: [isMacOS], [isLinux], and [isWindows].
+/// ```dart
+/// import 'dart:io' show Platform, stdout;
+///
+/// void main() {
+///   // Get the operating system as a string.
+///   String os = Platform.operatingSystem;
+///   // Or, use a predicate getter.
+///   if (Platform.isMacOS) {
+///     print('is a Mac');
+///   } else {
+///     print('is not a Mac');
+///   }
+/// }
+/// ```
 class Platform {
   static final _numberOfProcessors = _Platform.numberOfProcessors;
   static final _pathSeparator = _Platform.pathSeparator;
@@ -67,160 +66,120 @@
   static final _localHostname = _Platform.localHostname;
   static final _version = _Platform.version;
 
-  /**
-   * The number of individual execution units of the machine.
-   */
+  /// The number of individual execution units of the machine.
   static int get numberOfProcessors => _numberOfProcessors;
 
-  /**
-   * The path separator used by the operating system to separate
-   * components in file paths.
-   */
+  /// The path separator used by the operating system to separate
+  /// components in file paths.
   static String get pathSeparator => _pathSeparator;
 
-  /**
-   * Get the name of the current locale.
-   */
+  /// Get the name of the current locale.
   static String get localeName => _Platform.localeName();
 
-  /**
-   * A string representing the operating system or platform.
-   */
+  /// A string representing the operating system or platform.
   static String get operatingSystem => _operatingSystem;
 
-  /**
-   * A string representing the version of the operating system or platform.
-   */
+  /// A string representing the version of the operating system or platform.
   static String get operatingSystemVersion => _operatingSystemVersion;
 
-  /**
-   * The local hostname for the system.
-   */
+  /// The local hostname for the system.
   static String get localHostname => _localHostname;
 
-  /**
-   * Whether the operating system is a version of
-   * [Linux](https://en.wikipedia.org/wiki/Linux).
-   *
-   * This value is `false` if the operating system is a specialized
-   * version of Linux that identifies itself by a different name,
-   * for example Android (see [isAndroid]).
-   */
+  /// Whether the operating system is a version of
+  /// [Linux](https://en.wikipedia.org/wiki/Linux).
+  ///
+  /// This value is `false` if the operating system is a specialized
+  /// version of Linux that identifies itself by a different name,
+  /// for example Android (see [isAndroid]).
   static final bool isLinux = (_operatingSystem == "linux");
 
-  /**
-   * Whether the operating system is a version of
-   * [macOS](https://en.wikipedia.org/wiki/MacOS).
-   */
+  /// Whether the operating system is a version of
+  /// [macOS](https://en.wikipedia.org/wiki/MacOS).
   static final bool isMacOS = (_operatingSystem == "macos");
 
-  /**
-   * Whether the operating system is a version of
-   * [Microsoft Windows](https://en.wikipedia.org/wiki/Microsoft_Windows).
-   */
+  /// Whether the operating system is a version of
+  /// [Microsoft Windows](https://en.wikipedia.org/wiki/Microsoft_Windows).
   static final bool isWindows = (_operatingSystem == "windows");
 
-  /**
-   * Whether the operating system is a version of
-   * [Android](https://en.wikipedia.org/wiki/Android_%28operating_system%29).
-   */
+  /// Whether the operating system is a version of
+  /// [Android](https://en.wikipedia.org/wiki/Android_%28operating_system%29).
   static final bool isAndroid = (_operatingSystem == "android");
 
-  /**
-   * Whether the operating system is a version of
-   * [iOS](https://en.wikipedia.org/wiki/IOS).
-   */
+  /// Whether the operating system is a version of
+  /// [iOS](https://en.wikipedia.org/wiki/IOS).
   static final bool isIOS = (_operatingSystem == "ios");
 
-  /**
-   * Whether the operating system is a version of
-   * [Fuchsia](https://en.wikipedia.org/wiki/Google_Fuchsia).
-   */
+  /// Whether the operating system is a version of
+  /// [Fuchsia](https://en.wikipedia.org/wiki/Google_Fuchsia).
   static final bool isFuchsia = (_operatingSystem == "fuchsia");
 
-  /**
-   * The environment for this process as a map from string key to string value.
-   *
-   * The map is unmodifiable,
-   * and its content is retrieved from the operating system on its first use.
-   *
-   * Environment variables on Windows are case-insensitive,
-   * so on Windows the map is case-insensitive and will convert
-   * all keys to upper case.
-   * On other platforms, keys can be distinguished by case.
-   */
+  /// The environment for this process as a map from string key to string value.
+  ///
+  /// The map is unmodifiable,
+  /// and its content is retrieved from the operating system on its first use.
+  ///
+  /// Environment variables on Windows are case-insensitive,
+  /// so on Windows the map is case-insensitive and will convert
+  /// all keys to upper case.
+  /// On other platforms, keys can be distinguished by case.
   static Map<String, String> get environment => _Platform.environment;
 
-  /**
-   * The path of the executable used to run the script in this isolate.
-   *
-   * The literal path used to identify the script.
-   * This path might be relative or just be a name from which the executable
-   * was found by searching the system path.
-   *
-   * Use [resolvedExecutable] to get an absolute path to the executable.
-   */
+  /// The path of the executable used to run the script in this isolate.
+  ///
+  /// The literal path used to identify the script.
+  /// This path might be relative or just be a name from which the executable
+  /// was found by searching the system path.
+  ///
+  /// Use [resolvedExecutable] to get an absolute path to the executable.
   static String get executable => _Platform.executable;
 
-  /**
-   * The path of the executable used to run the script in this
-   * isolate after it has been resolved by the OS.
-   *
-   * This is the absolute path, with all symlinks resolved, to the
-   * executable used to run the script.
-   */
+  /// The path of the executable used to run the script in this
+  /// isolate after it has been resolved by the OS.
+  ///
+  /// This is the absolute path, with all symlinks resolved, to the
+  /// executable used to run the script.
   static String get resolvedExecutable => _Platform.resolvedExecutable;
 
-  /**
-   * The absolute URI of the script being run in this isolate.
-   *
-   * If the script argument on the command line is relative,
-   * it is resolved to an absolute URI before fetching the script, and
-   * that absolute URI is returned.
-   *
-   * URI resolution only does string manipulation on the script path, and this
-   * may be different from the file system's path resolution behavior. For
-   * example, a symbolic link immediately followed by '..' will not be
-   * looked up.
-   *
-   * If the executable environment does not support [script],
-   * the URI is empty.
-   */
+  /// The absolute URI of the script being run in this isolate.
+  ///
+  /// If the script argument on the command line is relative,
+  /// it is resolved to an absolute URI before fetching the script, and
+  /// that absolute URI is returned.
+  ///
+  /// URI resolution only does string manipulation on the script path, and this
+  /// may be different from the file system's path resolution behavior. For
+  /// example, a symbolic link immediately followed by '..' will not be
+  /// looked up.
+  ///
+  /// If the executable environment does not support [script],
+  /// the URI is empty.
   static Uri get script => _Platform.script;
 
-  /**
-   * The flags passed to the executable used to run the script in this isolate.
-   *
-   * These are the command-line flags to the executable that precedes
-   * the script name.
-   * Provides a new list every time the value is read.
-   */
+  /// The flags passed to the executable used to run the script in this isolate.
+  ///
+  /// These are the command-line flags to the executable that precedes
+  /// the script name.
+  /// Provides a new list every time the value is read.
   static List<String> get executableArguments => _Platform.executableArguments;
 
-  /**
-   * This returns `null`, as `packages/` directories are no longer supported.
-   *
-   */
+  /// This returns `null`, as `packages/` directories are no longer supported.
+  ///
   @Deprecated('packages/ directory resolution is not supported in Dart 2')
   static String? get packageRoot => null; // TODO(mfairhurst): remove this
 
-  /**
-   * The `--packages` flag passed to the executable used to run the script
-   * in this isolate.
-   *
-   * If present, it specifies a file describing how Dart packages are looked up.
-   *
-   * Is `null` if there is no `--packages` flag.
-   */
+  /// The `--packages` flag passed to the executable used to run the script
+  /// in this isolate.
+  ///
+  /// If present, it specifies a file describing how Dart packages are looked up.
+  ///
+  /// Is `null` if there is no `--packages` flag.
   static String? get packageConfig => _Platform.packageConfig;
 
-  /**
-   * The version of the current Dart runtime.
-   *
-   * The value is a [semantic versioning](http://semver.org)
-   * string representing the version of the current Dart runtime,
-   * possibly followed by whitespace and other version and
-   * build details.
-   */
+  /// The version of the current Dart runtime.
+  ///
+  /// The value is a [semantic versioning](http://semver.org)
+  /// string representing the version of the current Dart runtime,
+  /// possibly followed by whitespace and other version and
+  /// build details.
   static String get version => _version;
 }
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index 0251445..48d89ef 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.dart
@@ -13,21 +13,19 @@
   external static _executable();
   external static _resolvedExecutable();
 
-  /**
-   * Retrieve the entries of the process environment.
-   *
-   * The result is an [Iterable] of strings, where each string represents
-   * an environment entry.
-   *
-   * Environment entries should be strings containing
-   * a non-empty name and a value separated by a '=' character.
-   * The name does not contain a '=' character,
-   * so the name is everything up to the first '=' character.
-   * Values are everything after the first '=' character.
-   * A value may contain further '=' characters, and it may be empty.
-   *
-   * Returns an [OSError] if retrieving the environment fails.
-   */
+  /// Retrieve the entries of the process environment.
+  ///
+  /// The result is an [Iterable] of strings, where each string represents
+  /// an environment entry.
+  ///
+  /// Environment entries should be strings containing
+  /// a non-empty name and a value separated by a '=' character.
+  /// The name does not contain a '=' character,
+  /// so the name is everything up to the first '=' character.
+  /// Values are everything after the first '=' character.
+  /// A value may contain further '=' characters, and it may be empty.
+  ///
+  /// Returns an [OSError] if retrieving the environment fails.
   external static _environment();
   external static List<String> _executableArguments();
   external static String? _packageConfig();
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index d976baf..a1ccce6 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -15,40 +15,38 @@
   external static Stream<ProcessSignal> _watchSignal(ProcessSignal signal);
 }
 
-/**
- * Exit the Dart VM process immediately with the given exit code.
- *
- * This does not wait for any asynchronous operations to terminate nor execute
- * `finally` blocks. Using [exit] is therefore very likely to lose data.
- *
- * While debugging, the VM will not respect the `--pause-isolates-on-exit`
- * flag if [exit] is called as invoking this method causes the Dart VM
- * process to shutdown immediately. To properly break on exit, consider
- * calling [debugger] from `dart:developer` or [Isolate.pause] from
- * `dart:isolate` on [Isolate.current] to pause the isolate before
- * invoking [exit].
- *
- * The handling of exit codes is platform specific.
- *
- * On Linux and OS X an exit code for normal termination will always
- * be in the range [0..255]. If an exit code outside this range is
- * set the actual exit code will be the lower 8 bits masked off and
- * treated as an unsigned value. E.g. using an exit code of -1 will
- * result in an actual exit code of 255 being reported.
- *
- * On Windows the exit code can be set to any 32-bit value. However
- * some of these values are reserved for reporting system errors like
- * crashes.
- *
- * Besides this the Dart executable itself uses an exit code of `254`
- * for reporting compile time errors and an exit code of `255` for
- * reporting runtime error (unhandled exception).
- *
- * Due to these facts it is recommended to only use exit codes in the
- * range [0..127] for communicating the result of running a Dart
- * program to the surrounding environment. This will avoid any
- * cross-platform issues.
- */
+/// Exit the Dart VM process immediately with the given exit code.
+///
+/// This does not wait for any asynchronous operations to terminate nor execute
+/// `finally` blocks. Using [exit] is therefore very likely to lose data.
+///
+/// While debugging, the VM will not respect the `--pause-isolates-on-exit`
+/// flag if [exit] is called as invoking this method causes the Dart VM
+/// process to shutdown immediately. To properly break on exit, consider
+/// calling [debugger] from `dart:developer` or [Isolate.pause] from
+/// `dart:isolate` on [Isolate.current] to pause the isolate before
+/// invoking [exit].
+///
+/// The handling of exit codes is platform specific.
+///
+/// On Linux and OS X an exit code for normal termination will always
+/// be in the range [0..255]. If an exit code outside this range is
+/// set the actual exit code will be the lower 8 bits masked off and
+/// treated as an unsigned value. E.g. using an exit code of -1 will
+/// result in an actual exit code of 255 being reported.
+///
+/// On Windows the exit code can be set to any 32-bit value. However
+/// some of these values are reserved for reporting system errors like
+/// crashes.
+///
+/// Besides this the Dart executable itself uses an exit code of `254`
+/// for reporting compile time errors and an exit code of `255` for
+/// reporting runtime error (unhandled exception).
+///
+/// Due to these facts it is recommended to only use exit codes in the
+/// range \[0..127\] for communicating the result of running a Dart
+/// program to the surrounding environment. This will avoid any
+/// cross-platform issues.
 Never exit(int code) {
   ArgumentError.checkNotNull(code, "code");
   if (!_EmbedderConfig._mayExit) {
@@ -58,41 +56,35 @@
   _ProcessUtils._exit(code);
 }
 
-/**
- * Set the global exit code for the Dart VM.
- *
- * The exit code is global for the Dart VM and the last assignment to
- * exitCode from any isolate determines the exit code of the Dart VM
- * on normal termination.
- *
- * Default value is `0`.
- *
- * See [exit] for more information on how to chose a value for the
- * exit code.
- */
+/// Set the global exit code for the Dart VM.
+///
+/// The exit code is global for the Dart VM and the last assignment to
+/// exitCode from any isolate determines the exit code of the Dart VM
+/// on normal termination.
+///
+/// Default value is `0`.
+///
+/// See [exit] for more information on how to chose a value for the
+/// exit code.
 void set exitCode(int code) {
   ArgumentError.checkNotNull(code, "code");
   _ProcessUtils._setExitCode(code);
 }
 
-/**
- * Get the global exit code for the Dart VM.
- *
- * The exit code is global for the Dart VM and the last assignment to
- * exitCode from any isolate determines the exit code of the Dart VM
- * on normal termination.
- *
- * See [exit] for more information on how to chose a value for the
- * exit code.
- */
+/// Get the global exit code for the Dart VM.
+///
+/// The exit code is global for the Dart VM and the last assignment to
+/// exitCode from any isolate determines the exit code of the Dart VM
+/// on normal termination.
+///
+/// See [exit] for more information on how to chose a value for the
+/// exit code.
 int get exitCode => _ProcessUtils._getExitCode();
 
-/**
- * Sleep for the duration specified in [duration].
- *
- * Use this with care, as no asynchronous operations can be processed
- * in a isolate while it is blocked in a [sleep] call.
- */
+/// Sleep for the duration specified in [duration].
+///
+/// Use this with care, as no asynchronous operations can be processed
+/// in a isolate while it is blocked in a [sleep] call.
 void sleep(Duration duration) {
   int milliseconds = duration.inMilliseconds;
   if (milliseconds < 0) {
@@ -105,41 +97,30 @@
   _ProcessUtils._sleep(milliseconds);
 }
 
-/**
- * Returns the PID of the current process.
- */
+/// Returns the PID of the current process.
 int get pid => _ProcessUtils._pid(null);
 
-/**
- * [ProcessInfo] provides methods for retrieving information about the
- * current process.
- */
+/// Methods for retrieving information about the current process.
 class ProcessInfo {
-  /**
-   * The current resident set size of memory for the process.
-   *
-   * Note that the meaning of this field is platform dependent. For example,
-   * some memory accounted for here may be shared with other processes, or if
-   * the same page is mapped into a process's address space, it may be counted
-   * twice.
-   */
+  /// The current resident set size of memory for the process.
+  ///
+  /// Note that the meaning of this field is platform dependent. For example,
+  /// some memory accounted for here may be shared with other processes, or if
+  /// the same page is mapped into a process's address space, it may be counted
+  /// twice.
   external static int get currentRss;
 
-  /**
-   * The high-watermark in bytes for the resident set size of memory for the
-   * process.
-   *
-   * Note that the meaning of this field is platform dependent. For example,
-   * some memory accounted for here may be shared with other processes, or if
-   * the same page is mapped into a process's address space, it may be counted
-   * twice.
-   */
+  /// The high-watermark in bytes for the resident set size of memory for the
+  /// process.
+  ///
+  /// Note that the meaning of this field is platform dependent. For example,
+  /// some memory accounted for here may be shared with other processes, or if
+  /// the same page is mapped into a process's address space, it may be counted
+  /// twice.
   external static int get maxRss;
 }
 
-/**
- * Modes for running a new process.
- */
+/// Modes for running a new process.
 class ProcessStartMode {
   /// Normal child process.
   static const normal = const ProcessStartMode._internal(0);
@@ -175,362 +156,325 @@
   const ProcessStartMode._internal(this._mode);
 }
 
-/**
- * The means to execute a program.
- *
- * Use the static [start] and [run] methods to start a new process.
- * The run method executes the process non-interactively to completion.
- * In contrast, the start method allows your code to interact with the
- * running process.
- *
- * ## Start a process with the run method
- *
- * The following code sample uses the run method to create a process
- * that runs the UNIX command `ls`, which lists the contents of a directory.
- * The run method completes with a [ProcessResult] object when the process
- * terminates. This provides access to the output and exit code from the
- * process. The run method does not return a Process object; this prevents your
- * code from interacting with the running process.
- *
- *     import 'dart:io';
- *
- *     main() {
- *       // List all files in the current directory in UNIX-like systems.
- *       Process.run('ls', ['-l']).then((ProcessResult results) {
- *         print(results.stdout);
- *       });
- *     }
- *
- * ## Start a process with the start method
- *
- * The following example uses start to create the process.
- * The start method returns a [Future] for a Process object.
- * When the future completes the process is started and
- * your code can interact with the
- * Process: writing to stdin, listening to stdout, and so on.
- *
- * The following sample starts the UNIX `cat` utility, which when given no
- * command-line arguments, echos its input.
- * The program writes to the process's standard input stream
- * and prints data from its standard output stream.
- *
- *     import 'dart:io';
- *     import 'dart:convert';
- *
- *     main() {
- *       Process.start('cat', []).then((Process process) {
- *         process.stdout
- *             .transform(utf8.decoder)
- *             .listen((data) { print(data); });
- *         process.stdin.writeln('Hello, world!');
- *         process.stdin.writeln('Hello, galaxy!');
- *         process.stdin.writeln('Hello, universe!');
- *       });
- *     }
- *
- * ## Standard I/O streams
- *
- * As seen in the previous code sample, you can interact with the Process's
- * standard output stream through the getter [stdout],
- * and you can interact with the Process's standard input stream through
- * the getter [stdin].
- * In addition, Process provides a getter [stderr] for using the Process's
- * standard error stream.
- *
- * A Process's streams are distinct from the top-level streams
- * for the current program.
- *
- * ## Exit codes
- *
- * Call the [exitCode] method to get the exit code of the process.
- * The exit code indicates whether the program terminated successfully
- * (usually indicated with an exit code of 0) or with an error.
- *
- * If the start method is used, the exitCode is available through a future
- * on the Process object (as shown in the example below).
- * If the run method is used, the exitCode is available
- * through a getter on the ProcessResult instance.
- *
- *     import 'dart:io';
- *
- *     main() {
- *       Process.start('ls', ['-l']).then((process) {
- *         // Get the exit code from the new process.
- *         process.exitCode.then((exitCode) {
- *           print('exit code: $exitCode');
- *         });
- *       });
- *     }
- */
+/// The means to execute a program.
+///
+/// Use the static [start] and [run] methods to start a new process.
+/// The run method executes the process non-interactively to completion.
+/// In contrast, the start method allows your code to interact with the
+/// running process.
+///
+/// ## Start a process with the run method
+///
+/// The following code sample uses the run method to create a process
+/// that runs the UNIX command `ls`, which lists the contents of a directory.
+/// The run method completes with a [ProcessResult] object when the process
+/// terminates. This provides access to the output and exit code from the
+/// process. The run method does not return a `Process` object;
+/// this prevents your code from interacting with the running process.
+/// ```dart
+/// import 'dart:io';
+///
+/// main() async {
+///   // List all files in the current directory in UNIX-like systems.
+///   var result = await Process.run('ls', ['-l']);
+///   print(results.stdout);
+/// }
+/// ```
+/// ## Start a process with the start method
+///
+/// The following example uses start to create the process.
+/// The start method returns a [Future] for a `Process` object.
+/// When the future completes the process is started and
+/// your code can interact with the process:
+/// writing to stdin, listening to stdout, and so on.
+///
+/// The following sample starts the UNIX `cat` utility, which when given no
+/// command-line arguments, echos its input.
+/// The program writes to the process's standard input stream
+/// and prints data from its standard output stream.
+/// ```dart
+/// import 'dart:io';
+/// import 'dart:convert';
+///
+/// main() async {
+///   var process = await Process.start('cat', []);
+///   process.stdout
+///       .transform(utf8.decoder)
+///       .forEach(print);
+///   process.stdin.writeln('Hello, world!');
+///   process.stdin.writeln('Hello, galaxy!');
+///   process.stdin.writeln('Hello, universe!');
+/// }
+/// ```
+/// ## Standard I/O streams
+///
+/// As seen in the previous code sample, you can interact with the `Process`'s
+/// standard output stream through the getter [stdout],
+/// and you can interact with the `Process`'s standard input stream through
+/// the getter [stdin].
+/// In addition, `Process` provides a getter [stderr] for using the `Process`'s
+/// standard error stream.
+///
+/// A `Process`'s streams are distinct from the top-level streams
+/// for the current program.
+///
+/// ## Exit codes
+///
+/// Call the [exitCode] method to get the exit code of the process.
+/// The exit code indicates whether the program terminated successfully
+/// (usually indicated with an exit code of 0) or with an error.
+///
+/// If the start method is used, the [exitCode] is available through a future
+/// on the `Process` object (as shown in the example below).
+/// If the run method is used, the [exitCode] is available
+/// through a getter on the [ProcessResult] instance.
+/// ```dart
+/// import 'dart:io';
+///
+/// main() async {
+///   var process = Process.start('ls', ['-l']);
+///   var exitCode = await process.exitCode;
+///   print('exit code: $exitCode');
+/// }
+/// ```
 abstract class Process {
-  /**
-   * Returns a [:Future:] which completes with the exit code of the process
-   * when the process completes.
-   *
-   * The handling of exit codes is platform specific.
-   *
-   * On Linux and OS X a normal exit code will be a positive value in
-   * the range [0..255]. If the process was terminated due to a signal
-   * the exit code will be a negative value in the range [-255..-1],
-   * where the absolute value of the exit code is the signal
-   * number. For example, if a process crashes due to a segmentation
-   * violation the exit code will be -11, as the signal SIGSEGV has the
-   * number 11.
-   *
-   * On Windows a process can report any 32-bit value as an exit
-   * code. When returning the exit code this exit code is turned into
-   * a signed value. Some special values are used to report
-   * termination due to some system event. E.g. if a process crashes
-   * due to an access violation the 32-bit exit code is `0xc0000005`,
-   * which will be returned as the negative number `-1073741819`. To
-   * get the original 32-bit value use `(0x100000000 + exitCode) &
-   * 0xffffffff`.
-   *
-   * There is no guarantee that [stdout] and [stderr] have finished reporting
-   * the buffered output of the process when the returned future completes.
-   * To be sure that all output is captured,
-   * wait for the done event on the streams.
-   */
+  /// A `Future` which completes with the exit code of the process
+  /// when the process completes.
+  ///
+  /// The handling of exit codes is platform specific.
+  ///
+  /// On Linux and OS X a normal exit code will be a positive value in
+  /// the range [0..255]. If the process was terminated due to a signal
+  /// the exit code will be a negative value in the range [-255..-1],
+  /// where the absolute value of the exit code is the signal
+  /// number. For example, if a process crashes due to a segmentation
+  /// violation the exit code will be -11, as the signal SIGSEGV has the
+  /// number 11.
+  ///
+  /// On Windows a process can report any 32-bit value as an exit
+  /// code. When returning the exit code this exit code is turned into
+  /// a signed value. Some special values are used to report
+  /// termination due to some system event. E.g. if a process crashes
+  /// due to an access violation the 32-bit exit code is `0xc0000005`,
+  /// which will be returned as the negative number `-1073741819`. To
+  /// get the original 32-bit value use `(0x100000000 + exitCode) &
+  /// 0xffffffff`.
+  ///
+  /// There is no guarantee that [stdout] and [stderr] have finished reporting
+  /// the buffered output of the process when the returned future completes.
+  /// To be sure that all output is captured,
+  /// wait for the done event on the streams.
   Future<int> get exitCode;
 
-  /**
-   * Starts a process running the [executable] with the specified
-   * [arguments]. Returns a [:Future<Process>:] that completes with a
-   * Process instance when the process has been successfully
-   * started. That [Process] object can be used to interact with the
-   * process. If the process cannot be started the returned [Future]
-   * completes with an exception.
-   *
-   * Use [workingDirectory] to set the working directory for the process. Note
-   * that the change of directory occurs before executing the process on some
-   * platforms, which may have impact when using relative paths for the
-   * executable and the arguments.
-   *
-   * Use [environment] to set the environment variables for the process. If not
-   * set the environment of the parent process is inherited. Currently, only
-   * US-ASCII environment variables are supported and errors are likely to occur
-   * if an environment variable with code-points outside the US-ASCII range is
-   * passed in.
-   *
-   * If [includeParentEnvironment] is `true`, the process's environment will
-   * include the parent process's environment, with [environment] taking
-   * precedence. Default is `true`.
-   *
-   * If [runInShell] is `true`, the process will be spawned through a system
-   * shell. On Linux and OS X, [:/bin/sh:] is used, while
-   * [:%WINDIR%\system32\cmd.exe:] is used on Windows.
-   *
-   * Users must read all data coming on the [stdout] and [stderr]
-   * streams of processes started with [:Process.start:]. If the user
-   * does not read all data on the streams the underlying system
-   * resources will not be released since there is still pending data.
-   *
-   * The following code uses `Process.start` to grep for `main` in the
-   * file `test.dart` on Linux.
-   *
-   *     Process.start('grep', ['-i', 'main', 'test.dart']).then((process) {
-   *       stdout.addStream(process.stdout);
-   *       stderr.addStream(process.stderr);
-   *     });
-   *
-   * If [mode] is [ProcessStartMode.normal] (the default) a child
-   * process will be started with `stdin`, `stdout` and `stderr`
-   * connected.
-   *
-   * If `mode` is [ProcessStartMode.detached] a detached process will
-   * be created. A detached process has no connection to its parent,
-   * and can keep running on its own when the parent dies. The only
-   * information available from a detached process is its `pid`. There
-   * is no connection to its `stdin`, `stdout` or `stderr`, nor will
-   * the process' exit code become available when it terminates.
-   *
-   * If `mode` is [ProcessStartMode.detachedWithStdio] a detached
-   * process will be created where the `stdin`, `stdout` and `stderr`
-   * are connected. The creator can communicate with the child through
-   * these. The detached process will keep running even if these
-   * communication channels are closed. The process' exit code will
-   * not become available when it terminated.
-   *
-   * The default value for `mode` is `ProcessStartMode.normal`.
-   */
+  /// Starts a process running the [executable] with the specified
+  /// [arguments].
+  ///
+  /// Returns a `Future<Process>` that completes with a
+  /// [Process] instance when the process has been successfully
+  /// started. That [Process] object can be used to interact with the
+  /// process. If the process cannot be started the returned [Future]
+  /// completes with an exception.
+  ///
+  /// Use [workingDirectory] to set the working directory for the process. Note
+  /// that the change of directory occurs before executing the process on some
+  /// platforms, which may have impact when using relative paths for the
+  /// executable and the arguments.
+  ///
+  /// Use [environment] to set the environment variables for the process. If not
+  /// set the environment of the parent process is inherited. Currently, only
+  /// US-ASCII environment variables are supported and errors are likely to occur
+  /// if an environment variable with code-points outside the US-ASCII range is
+  /// passed in.
+  ///
+  /// If [includeParentEnvironment] is `true`, the process's environment will
+  /// include the parent process's environment, with [environment] taking
+  /// precedence. Default is `true`.
+  ///
+  /// If [runInShell] is `true`, the process will be spawned through a system
+  /// shell. On Linux and OS X, `/bin/sh` is used, while
+  /// `%WINDIR%\system32\cmd.exe` is used on Windows.
+  ///
+  /// Users must read all data coming on the [stdout] and [stderr]
+  /// streams of processes started with `Process.start`. If the user
+  /// does not read all data on the streams the underlying system
+  /// resources will not be released since there is still pending data.
+  ///
+  /// The following code uses `Process.start` to grep for `main` in the
+  /// file `test.dart` on Linux.
+  /// ```dart
+  /// var process = await Process.start('grep', ['-i', 'main', 'test.dart']);
+  /// stdout.addStream(process.stdout);
+  /// stderr.addStream(process.stderr);
+  /// ```
+  /// If [mode] is [ProcessStartMode.normal] (the default) a child
+  /// process will be started with `stdin`, `stdout` and `stderr`
+  /// connected.
+  ///
+  /// If `mode` is [ProcessStartMode.detached] a detached process will
+  /// be created. A detached process has no connection to its parent,
+  /// and can keep running on its own when the parent dies. The only
+  /// information available from a detached process is its `pid`. There
+  /// is no connection to its `stdin`, `stdout` or `stderr`, nor will
+  /// the process' exit code become available when it terminates.
+  ///
+  /// If `mode` is [ProcessStartMode.detachedWithStdio] a detached
+  /// process will be created where the `stdin`, `stdout` and `stderr`
+  /// are connected. The creator can communicate with the child through
+  /// these. The detached process will keep running even if these
+  /// communication channels are closed. The process' exit code will
+  /// not become available when it terminated.
+  ///
+  /// The default value for `mode` is `ProcessStartMode.normal`.
   external static Future<Process> start(
       String executable, List<String> arguments,
       {String? workingDirectory,
       Map<String, String>? environment,
-      bool includeParentEnvironment: true,
-      bool runInShell: false,
-      ProcessStartMode mode: ProcessStartMode.normal});
+      bool includeParentEnvironment = true,
+      bool runInShell = false,
+      ProcessStartMode mode = ProcessStartMode.normal});
 
-  /**
-   * Starts a process and runs it non-interactively to completion. The
-   * process run is [executable] with the specified [arguments].
-   *
-   * Use [workingDirectory] to set the working directory for the process. Note
-   * that the change of directory occurs before executing the process on some
-   * platforms, which may have impact when using relative paths for the
-   * executable and the arguments.
-   *
-   * Use [environment] to set the environment variables for the process. If not
-   * set the environment of the parent process is inherited. Currently, only
-   * US-ASCII environment variables are supported and errors are likely to occur
-   * if an environment variable with code-points outside the US-ASCII range is
-   * passed in.
-   *
-   * If [includeParentEnvironment] is `true`, the process's environment will
-   * include the parent process's environment, with [environment] taking
-   * precedence. Default is `true`.
-   *
-   * If [runInShell] is true, the process will be spawned through a system
-   * shell. On Linux and OS X, `/bin/sh` is used, while
-   * `%WINDIR%\system32\cmd.exe` is used on Windows.
-   *
-   * The encoding used for decoding `stdout` and `stderr` into text is
-   * controlled through [stdoutEncoding] and [stderrEncoding]. The
-   * default encoding is [systemEncoding]. If `null` is used no
-   * decoding will happen and the [ProcessResult] will hold binary
-   * data.
-   *
-   * Returns a `Future<ProcessResult>` that completes with the
-   * result of running the process, i.e., exit code, standard out and
-   * standard in.
-   *
-   * The following code uses `Process.run` to grep for `main` in the
-   * file `test.dart` on Linux.
-   *
-   *     Process.run('grep', ['-i', 'main', 'test.dart']).then((result) {
-   *       stdout.write(result.stdout);
-   *       stderr.write(result.stderr);
-   *     });
-   */
+  /// Starts a process and runs it non-interactively to completion. The
+  /// process run is [executable] with the specified [arguments].
+  ///
+  /// Use [workingDirectory] to set the working directory for the process. Note
+  /// that the change of directory occurs before executing the process on some
+  /// platforms, which may have impact when using relative paths for the
+  /// executable and the arguments.
+  ///
+  /// Use [environment] to set the environment variables for the process. If not
+  /// set the environment of the parent process is inherited. Currently, only
+  /// US-ASCII environment variables are supported and errors are likely to occur
+  /// if an environment variable with code-points outside the US-ASCII range is
+  /// passed in.
+  ///
+  /// If [includeParentEnvironment] is `true`, the process's environment will
+  /// include the parent process's environment, with [environment] taking
+  /// precedence. Default is `true`.
+  ///
+  /// If [runInShell] is true, the process will be spawned through a system
+  /// shell. On Linux and OS X, `/bin/sh` is used, while
+  /// `%WINDIR%\system32\cmd.exe` is used on Windows.
+  ///
+  /// The encoding used for decoding `stdout` and `stderr` into text is
+  /// controlled through [stdoutEncoding] and [stderrEncoding]. The
+  /// default encoding is [systemEncoding]. If `null` is used no
+  /// decoding will happen and the [ProcessResult] will hold binary
+  /// data.
+  ///
+  /// Returns a `Future<ProcessResult>` that completes with the
+  /// result of running the process, i.e., exit code, standard out and
+  /// standard in.
+  ///
+  /// The following code uses `Process.run` to grep for `main` in the
+  /// file `test.dart` on Linux.
+  /// ```dart
+  /// var result = await Process.run('grep', ['-i', 'main', 'test.dart']);
+  /// stdout.write(result.stdout);
+  /// stderr.write(result.stderr);
+  /// ```
   external static 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});
+      bool includeParentEnvironment = true,
+      bool runInShell = false,
+      Encoding? stdoutEncoding = systemEncoding,
+      Encoding? stderrEncoding = systemEncoding});
 
-  /**
-   * Starts a process and runs it to completion. This is a synchronous
-   * call and will block until the child process terminates.
-   *
-   * The arguments are the same as for `Process.run`.
-   *
-   * Returns a `ProcessResult` with the result of running the process,
-   * i.e., exit code, standard out and standard in.
-   */
+  /// Starts a process and runs it to completion. This is a synchronous
+  /// call and will block until the child process terminates.
+  ///
+  /// The arguments are the same as for [Process.run].
+  ///
+  /// Returns a [ProcessResult] with the result of running the process,
+  /// i.e., exit code, standard out and standard in.
   external static ProcessResult runSync(
       String executable, List<String> arguments,
       {String? workingDirectory,
       Map<String, String>? environment,
-      bool includeParentEnvironment: true,
-      bool runInShell: false,
-      Encoding? stdoutEncoding: systemEncoding,
-      Encoding? stderrEncoding: systemEncoding});
+      bool includeParentEnvironment = true,
+      bool runInShell = false,
+      Encoding? stdoutEncoding = systemEncoding,
+      Encoding? stderrEncoding = systemEncoding});
 
-  /**
-   * Kills the process with id [pid].
-   *
-   * Where possible, sends the [signal] to the process with id
-   * `pid`. This includes Linux and OS X. The default signal is
-   * [ProcessSignal.sigterm] which will normally terminate the
-   * process.
-   *
-   * On platforms without signal support, including Windows, the call
-   * just terminates the process with id `pid` in a platform specific
-   * way, and the `signal` parameter is ignored.
-   *
-   * Returns `true` if the signal is successfully delivered to the
-   * process. Otherwise the signal could not be sent, usually meaning
-   * that the process is already dead.
-   */
+  /// Kills the process with id [pid].
+  ///
+  /// Where possible, sends the [signal] to the process with id
+  /// [pid]. This includes Linux and OS X. The default signal is
+  /// [ProcessSignal.sigterm] which will normally terminate the
+  /// process.
+  ///
+  /// On platforms without signal support, including Windows, the call
+  /// just terminates the process with id [pid] in a platform specific
+  /// way, and the [signal] parameter is ignored.
+  ///
+  /// Returns `true` if the signal is successfully delivered to the
+  /// process. Otherwise the signal could not be sent, usually meaning
+  /// that the process is already dead.
   external static bool killPid(int pid,
       [ProcessSignal signal = ProcessSignal.sigterm]);
 
-  /**
-   * Returns the standard output stream of the process as a [:Stream:].
-   */
+  /// The standard output stream of the process as a `Stream`.
   Stream<List<int>> get stdout;
 
-  /**
-   * Returns the standard error stream of the process as a [:Stream:].
-   */
+  /// The standard error stream of the process as a `Stream`.
   Stream<List<int>> get stderr;
 
-  /**
-   * Returns the standard input stream of the process as an [IOSink].
-   */
+  /// The standard input stream of the process as an [IOSink].
   IOSink get stdin;
 
-  /**
-   * Returns the process id of the process.
-   */
+  /// The process id of the process.
   int get pid;
 
-  /**
-   * Kills the process.
-   *
-   * Where possible, sends the [signal] to the process. This includes
-   * Linux and OS X. The default signal is [ProcessSignal.sigterm]
-   * which will normally terminate the process.
-   *
-   * On platforms without signal support, including Windows, the call
-   * just terminates the process in a platform specific way, and the
-   * `signal` parameter is ignored.
-   *
-   * Returns `true` if the signal is successfully delivered to the
-   * process. Otherwise the signal could not be sent, usually meaning
-   * that the process is already dead.
-   */
+  /// Kills the process.
+  ///
+  /// Where possible, sends the [signal] to the process. This includes
+  /// Linux and OS X. The default signal is [ProcessSignal.sigterm]
+  /// which will normally terminate the process.
+  ///
+  /// On platforms without signal support, including Windows, the call
+  /// just terminates the process in a platform specific way, and the
+  /// [signal] parameter is ignored.
+  ///
+  /// Returns `true` if the signal is successfully delivered to the
+  /// process. Otherwise the signal could not be sent, usually meaning
+  /// that the process is already dead.
   bool kill([ProcessSignal signal = ProcessSignal.sigterm]);
 }
 
-/**
- * [ProcessResult] represents the result of running a non-interactive
- * process started with [Process.run] or [Process.runSync].
- */
+/// The result of running a non-interactive
+/// process started with [Process.run] or [Process.runSync].
 class ProcessResult {
-  /**
-   * Exit code for the process.
-   *
-   * See [Process.exitCode] for more information in the exit code
-   * value.
-   */
+  /// Exit code for the process.
+  ///
+  /// See [Process.exitCode] for more information in the exit code
+  /// value.
   final int exitCode;
 
-  /**
-   * Standard output from the process. The value used for the
-   * `stdoutEncoding` argument to `Process.run` determines the type. If
-   * `null` was used this value is of type `List<int>` otherwise it is
-   * of type `String`.
-   */
+  /// Standard output from the process. The value used for the
+  /// `stdoutEncoding` argument to `Process.run` determines the type. If
+  /// `null` was used, this value is of type `List<int>` otherwise it is
+  /// of type `String`.
   final stdout;
 
-  /**
-   * Standard error from the process. The value used for the
-   * `stderrEncoding` argument to `Process.run` determines the type. If
-   * `null` was used this value is of type `List<int>`
-   * otherwise it is of type `String`.
-   */
+  /// Standard error from the process. The value used for the
+  /// `stderrEncoding` argument to `Process.run` determines the type. If
+  /// `null` was used, this value is of type `List<int>`
+  /// otherwise it is of type `String`.
   final stderr;
 
-  /**
-   * Process id of the process.
-   */
+  /// Process id of the process.
   final int pid;
 
   ProcessResult(this.pid, this.exitCode, this.stdout, this.stderr);
 }
 
-/**
- * On Posix systems, [ProcessSignal] is used to send a specific signal
- * to a child process, see [:Process.kill:].
- *
- * Some [ProcessSignal]s can also be watched, as a way to intercept the default
- * signal handler and implement another. See [ProcessSignal.watch] for more
- * information.
- */
+/// On Posix systems, [ProcessSignal] is used to send a specific signal
+/// to a child process, see `Process.kill`.
+///
+/// Some [ProcessSignal]s can also be watched, as a way to intercept the default
+/// signal handler and implement another. See [ProcessSignal.watch] for more
+/// information.
 class ProcessSignal {
   static const ProcessSignal sighup = const ProcessSignal._(1, "SIGHUP");
   static const ProcessSignal sigint = const ProcessSignal._(2, "SIGINT");
@@ -628,23 +572,21 @@
 
   String toString() => _name;
 
-  /**
-   * Watch for process signals.
-   *
-   * The following [ProcessSignal]s can be listened to:
-   *
-   *   * [ProcessSignal.sighup].
-   *   * [ProcessSignal.sigint]. Signal sent by e.g. CTRL-C.
-   *   * [ProcessSignal.sigterm]. Not available on Windows.
-   *   * [ProcessSignal.sigusr1]. Not available on Windows.
-   *   * [ProcessSignal.sigusr2]. Not available on Windows.
-   *   * [ProcessSignal.sigwinch]. Not available on Windows.
-   *
-   * Other signals are disallowed, as they may be used by the VM.
-   *
-   * A signal can be watched multiple times, from multiple isolates, where all
-   * callbacks are invoked when signaled, in no specific order.
-   */
+  /// Watch for process signals.
+  ///
+  /// The following [ProcessSignal]s can be listened to:
+  ///
+  ///   * [ProcessSignal.sighup].
+  ///   * [ProcessSignal.sigint]. Signal sent by e.g. CTRL-C.
+  ///   * [ProcessSignal.sigterm]. Not available on Windows.
+  ///   * [ProcessSignal.sigusr1]. Not available on Windows.
+  ///   * [ProcessSignal.sigusr2]. Not available on Windows.
+  ///   * [ProcessSignal.sigwinch]. Not available on Windows.
+  ///
+  /// Other signals are disallowed, as they may be used by the VM.
+  ///
+  /// A signal can be watched multiple times, from multiple isolates, where all
+  /// callbacks are invoked when signaled, in no specific order.
   Stream<ProcessSignal> watch() => _ProcessUtils._watchSignal(this);
 }
 
@@ -664,24 +606,20 @@
 }
 
 class ProcessException implements IOException {
-  /**
-   * Contains the executable provided for the process.
-   */
+  /// The executable provided for the process.
   final String executable;
 
-  /**
-   * Contains the arguments provided for the process.
-   */
+  /// The arguments provided for the process.
   final List<String> arguments;
 
-  /**
-   * Contains the system message for the process exception if any.
-   */
+  /// The system message for the process exception, if any.
+  ///
+  /// The empty string if no message was available.
   final String message;
 
-  /**
-   * Contains the OS error code for the process exception if any.
-   */
+  /// The OS error code for the process exception, if any.
+  ///
+  /// The value is zero if no OS error code was available.
   final int errorCode;
 
   const ProcessException(this.executable, this.arguments,
diff --git a/sdk/lib/io/secure_server_socket.dart b/sdk/lib/io/secure_server_socket.dart
index dbdcc28..bfe34af 100644
--- a/sdk/lib/io/secure_server_socket.dart
+++ b/sdk/lib/io/secure_server_socket.dart
@@ -4,76 +4,72 @@
 
 part of dart.io;
 
-/**
- * The [SecureServerSocket] is a server socket, providing a stream of high-level
- * [Socket]s.
- *
- * See [SecureSocket] for more info.
- */
+/// A server socket, providing a stream of high-level [Socket]s.
+///
+/// See [SecureSocket] for more info.
 class SecureServerSocket extends Stream<SecureSocket> {
   final RawSecureServerSocket _socket;
 
   SecureServerSocket._(this._socket);
 
-  /**
-   * Returns a future for a [SecureServerSocket]. When the future
-   * completes the server socket is bound to the given [address] and
-   * [port] and has started listening on it.
-   *
-   * The [address] can either be a [String] or an
-   * [InternetAddress]. If [address] is a [String], [bind] will
-   * perform a [InternetAddress.lookup] and use the first value in the
-   * list. To listen on the loopback adapter, which will allow only
-   * incoming connections from the local host, use the value
-   * [InternetAddress.loopbackIPv4] or
-   * [InternetAddress.loopbackIPv6]. To allow for incoming
-   * connection from the network use either one of the values
-   * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
-   * bind to all interfaces or the IP address of a specific interface.
-   *
-   * If [port] has the value [:0:] an ephemeral port will be chosen by
-   * the system. The actual port used can be retrieved using the
-   * [port] getter.
-   *
-   * The optional argument [backlog] can be used to specify the listen
-   * backlog for the underlying OS listen setup. If [backlog] has the
-   * value of [:0:] (the default) a reasonable value will be chosen by
-   * the system.
-   *
-   * Incoming client connections are promoted to secure connections, using
-   * the server certificate and key set in [context].
-   *
-   * [address] must be given as a numeric address, not a host name.
-   *
-   * To request or require that clients authenticate by providing an SSL (TLS)
-   * client certificate, set the optional parameter [requestClientCertificate]
-   * or [requireClientCertificate] to true.  Requiring a certificate implies
-   * requesting a certificate, so setting both is redundant.
-   * To check whether a client certificate was received, check
-   * SecureSocket.peerCertificate after connecting.  If no certificate
-   * was received, the result will be null.
-   *
-   * [supportedProtocols] is an optional list of protocols (in decreasing
-   * order of preference) to use during the ALPN protocol negogiation with
-   * clients.  Example values are "http/1.1" or "h2".  The selected protocol
-   * can be obtained via [SecureSocket.selectedProtocol].
-   *
-   * The optional argument [shared] specifies whether additional
-   * SecureServerSocket objects can bind to the same combination of `address`,
-   * `port` and `v6Only`.  If `shared` is `true` and more `SecureServerSocket`s
-   * from this isolate or other isolates are bound to the port, then the
-   * incoming connections will be distributed among all the bound
-   * `SecureServerSocket`s. Connections can be distributed over multiple
-   * isolates this way.
-   */
+  /// Listens on a given address and port.
+  ///
+  /// When the returned future completes, the server socket is bound
+  /// to the given [address] and [port] and has started listening on it.
+  ///
+  /// The [address] can either be a [String] or an
+  /// [InternetAddress]. If [address] is a [String], [bind] will
+  /// perform a [InternetAddress.lookup] and use the first value in the
+  /// list. To listen on the loopback adapter, which will allow only
+  /// incoming connections from the local host, use the value
+  /// [InternetAddress.loopbackIPv4] or
+  /// [InternetAddress.loopbackIPv6]. To allow for incoming
+  /// connection from the network use either one of the values
+  /// [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
+  /// bind to all interfaces or the IP address of a specific interface.
+  ///
+  /// If [port] has the value `0`, an ephemeral port will be chosen by
+  /// the system. The actual port used can be retrieved using the
+  /// [port] getter.
+  ///
+  /// The optional argument [backlog] can be used to specify the listen
+  /// backlog for the underlying OS listen setup. If [backlog] has the
+  /// value of `0` (the default) a reasonable value will be chosen by
+  /// the system.
+  ///
+  /// Incoming client connections are promoted to secure connections, using
+  /// the server certificate and key set in [context].
+  ///
+  /// The [address] must be given as a numeric address, not a host name.
+  ///
+  /// To request or require that clients authenticate by providing an SSL (TLS)
+  /// client certificate, set the optional parameter [requestClientCertificate]
+  /// or [requireClientCertificate] to true.  Requiring a certificate implies
+  /// requesting a certificate, so setting both is redundant.
+  /// To check whether a client certificate was received, check
+  /// [SecureSocket.peerCertificate] after connecting.  If no certificate
+  /// was received, the result will be null.
+  ///
+  /// [supportedProtocols] is an optional list of protocols (in decreasing
+  /// order of preference) to use during the ALPN protocol negogiation with
+  /// clients.  Example values are "http/1.1" or "h2".  The selected protocol
+  /// can be obtained via [SecureSocket.selectedProtocol].
+  ///
+  /// The optional argument [shared] specifies whether additional
+  /// [SecureServerSocket] objects can bind to the same combination of [address],
+  /// [port] and [v6Only].  If [shared] is `true` and more [SecureServerSocket]s
+  /// from this isolate or other isolates are bound to the same port, then the
+  /// incoming connections will be distributed among all the bound
+  /// `SecureServerSocket`s. Connections can be distributed over multiple
+  /// isolates this way.
   static Future<SecureServerSocket> bind(
       address, int port, SecurityContext? context,
-      {int backlog: 0,
-      bool v6Only: false,
-      bool requestClientCertificate: false,
-      bool requireClientCertificate: false,
+      {int backlog = 0,
+      bool v6Only = false,
+      bool requestClientCertificate = false,
+      bool requireClientCertificate = false,
       List<String>? supportedProtocols,
-      bool shared: false}) {
+      bool shared = false}) {
     return RawSecureServerSocket.bind(address, port, context,
             backlog: backlog,
             v6Only: v6Only,
@@ -93,20 +89,16 @@
         cancelOnError: cancelOnError);
   }
 
-  /**
-   * Returns the port used by this socket.
-   */
+  /// The port used by this socket.
   int get port => _socket.port;
 
-  /**
-   * Returns the address used by this socket.
-   */
+  /// The address used by this socket.
   InternetAddress get address => _socket.address;
 
-  /**
-   * Closes the socket. The returned future completes when the socket
-   * is fully closed and is no longer bound.
-   */
+  /// Closes this socket.
+  ///
+  /// The returned future completes when the socket
+  /// is fully closed and is no longer bound.
   Future<SecureServerSocket> close() => _socket.close().then((_) => this);
 
   void set _owner(owner) {
@@ -114,12 +106,9 @@
   }
 }
 
-/**
- * The RawSecureServerSocket is a server socket, providing a stream of low-level
- * [RawSecureSocket]s.
- *
- * See [RawSecureSocket] for more info.
- */
+/// A server socket providing a stream of low-level [RawSecureSocket]s.
+///
+/// See [RawSecureSocket] for more info.
 class RawSecureServerSocket extends Stream<RawSecureSocket> {
   final RawServerSocket _socket;
   late StreamController<RawSecureSocket> _controller;
@@ -144,64 +133,63 @@
         onCancel: _onSubscriptionStateChange);
   }
 
-  /**
-   * Returns a future for a [RawSecureServerSocket]. When the future
-   * completes the server socket is bound to the given [address] and
-   * [port] and has started listening on it.
-   *
-   * The [address] can either be a [String] or an
-   * [InternetAddress]. If [address] is a [String], [bind] will
-   * perform a [InternetAddress.lookup] and use the first value in the
-   * list. To listen on the loopback adapter, which will allow only
-   * incoming connections from the local host, use the value
-   * [InternetAddress.loopbackIPv4] or
-   * [InternetAddress.loopbackIPv6]. To allow for incoming
-   * connection from the network use either one of the values
-   * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
-   * bind to all interfaces or the IP address of a specific interface.
-   *
-   * If [port] has the value [:0:] an ephemeral port will be chosen by
-   * the system. The actual port used can be retrieved using the
-   * [port] getter.
-   *
-   * The optional argument [backlog] can be used to specify the listen
-   * backlog for the underlying OS listen setup. If [backlog] has the
-   * value of [:0:] (the default) a reasonable value will be chosen by
-   * the system.
-   *
-   * Incoming client connections are promoted to secure connections,
-   * using the server certificate and key set in [context].
-   *
-   * [address] must be given as a numeric address, not a host name.
-   *
-   * To request or require that clients authenticate by providing an SSL (TLS)
-   * client certificate, set the optional parameters requestClientCertificate or
-   * requireClientCertificate to true.  Require implies request, so one doesn't
-   * need to specify both.  To check whether a client certificate was received,
-   * check SecureSocket.peerCertificate after connecting.  If no certificate
-   * was received, the result will be null.
-   *
-   * [supportedProtocols] is an optional list of protocols (in decreasing
-   * order of preference) to use during the ALPN protocol negotiation with
-   * clients.  Example values are "http/1.1" or "h2".  The selected protocol
-   * can be obtained via [RawSecureSocket.selectedProtocol].
-   *
-   * The optional argument [shared] specifies whether additional
-   * RawSecureServerSocket objects can bind to the same combination of
-   * `address`, `port` and `v6Only`.  If `shared` is `true` and more
-   * `RawSecureServerSocket`s from this isolate or other isolates are bound to
-   * the port, then the incoming connections will be distributed among all the
-   * bound `RawSecureServerSocket`s. Connections can be distributed over
-   * multiple isolates this way.
-   */
+  /// Listens on a provided address and port.
+  ///
+  /// When the returned future completes, the server socket is bound
+  /// to the given [address] and [port] and has started listening on it.
+  ///
+  /// The [address] can either be a [String] or an
+  /// [InternetAddress]. If [address] is a [String], [bind] will
+  /// perform a [InternetAddress.lookup] and use the first value in the
+  /// list. To listen on the loopback adapter, which will allow only
+  /// incoming connections from the local host, use the value
+  /// [InternetAddress.loopbackIPv4] or
+  /// [InternetAddress.loopbackIPv6]. To allow for incoming
+  /// connection from the network use either one of the values
+  /// [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
+  /// bind to all interfaces or the IP address of a specific interface.
+  ///
+  /// If [port] has the value `0` an ephemeral port will be chosen by
+  /// the system. The actual port used can be retrieved using the
+  /// [port] getter.
+  ///
+  /// The optional argument [backlog] can be used to specify the listen
+  /// backlog for the underlying OS listen setup. If [backlog] has the
+  /// value of `0` (the default) a reasonable value will be chosen by
+  /// the system.
+  ///
+  /// Incoming client connections are promoted to secure connections,
+  /// using the server certificate and key set in [context].
+  ///
+  /// [address] must be given as a numeric address, not a host name.
+  ///
+  /// To request or require that clients authenticate by providing an SSL (TLS)
+  /// client certificate, set the optional parameters requestClientCertificate or
+  /// requireClientCertificate to true.  Require implies request, so one doesn't
+  /// need to specify both.  To check whether a client certificate was received,
+  /// check SecureSocket.peerCertificate after connecting.  If no certificate
+  /// was received, the result will be null.
+  ///
+  /// [supportedProtocols] is an optional list of protocols (in decreasing
+  /// order of preference) to use during the ALPN protocol negotiation with
+  /// clients.  Example values are "http/1.1" or "h2".  The selected protocol
+  /// can be obtained via [RawSecureSocket.selectedProtocol].
+  ///
+  /// The optional argument [shared] specifies whether additional
+  /// [RawSecureServerSocket] objects can bind to the same combination of
+  /// [address], [port] and [v6Only].  If [shared] is `true` and more
+  /// [RawSecureServerSocket]s from this isolate or other isolates are bound to
+  /// the port, then the incoming connections will be distributed among all the
+  /// bound [RawSecureServerSocket]s. Connections can be distributed over
+  /// multiple isolates this way.
   static Future<RawSecureServerSocket> bind(
       address, int port, SecurityContext? context,
-      {int backlog: 0,
-      bool v6Only: false,
-      bool requestClientCertificate: false,
-      bool requireClientCertificate: false,
+      {int backlog = 0,
+      bool v6Only = false,
+      bool requestClientCertificate = false,
+      bool requireClientCertificate = false,
       List<String>? supportedProtocols,
-      bool shared: false}) {
+      bool shared = false}) {
     return RawServerSocket.bind(address, port,
             backlog: backlog, v6Only: v6Only, shared: shared)
         .then((serverSocket) => new RawSecureServerSocket._(
@@ -218,20 +206,16 @@
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
 
-  /**
-   * Returns the port used by this socket.
-   */
+  /// The port used by this socket.
   int get port => _socket.port;
 
-  /**
-   * Returns the address used by this socket.
-   */
+  /// The address used by this socket.
   InternetAddress get address => _socket.address;
 
-  /**
-   * Closes the socket. The returned future completes when the socket
-   * is fully closed and is no longer bound.
-   */
+  /// Closes this socket.
+  ///
+  /// The returned future completes when the socket
+  /// is fully closed and is no longer bound.
   Future<RawSecureServerSocket> close() {
     _closed = true;
     return _socket.close().then((_) => this);
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index e5a757f..32222b5 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -4,43 +4,39 @@
 
 part of dart.io;
 
-/**
- * A high-level class for communicating securely over a TCP socket, using
- * TLS and SSL. The [SecureSocket] exposes both a [Stream] and an
- * [IOSink] interface, making it ideal for using together with
- * other [Stream]s.
- */
+/// A TCP socket using TLS and SSL.
+///
+/// A secure socket may be used as either a [Stream] or an [IOSink].
 abstract class SecureSocket implements Socket {
   external factory SecureSocket._(RawSecureSocket rawSocket);
 
-  /**
-   * Constructs a new secure client socket and connects it to the given
-   * [host] on port [port]. The returned Future will complete with a
-   * [SecureSocket] that is connected and ready for subscription.
-   *
-   * The certificate provided by the server is checked
-   * using the trusted certificates set in the SecurityContext object.
-   * The default SecurityContext object contains a built-in set of trusted
-   * root certificates for well-known certificate authorities.
-   *
-   * [onBadCertificate] is an optional handler for unverifiable certificates.
-   * The handler receives the [X509Certificate], and can inspect it and
-   * decide (or let the user decide) whether to accept
-   * the connection or not.  The handler should return true
-   * to continue the [SecureSocket] connection.
-   *
-   * [supportedProtocols] is an optional list of protocols (in decreasing
-   * order of preference) to use during the ALPN protocol negotiation with the
-   * server.  Example values are "http/1.1" or "h2".  The selected protocol
-   * can be obtained via [SecureSocket.selectedProtocol].
-   *
-   * The argument [timeout] is used to specify the maximum allowed time to wait
-   * for a connection to be established. If [timeout] is longer than the system
-   * level timeout duration, a timeout may occur sooner than specified in
-   * [timeout]. On timeout, a [SocketException] is thrown and all ongoing
-   * connection attempts to [host] are cancelled.
-
-   */
+  /// Constructs a new secure client socket and connects it to the given
+  /// [host] on port [port].
+  ///
+  /// The returned Future will complete with a
+  /// [SecureSocket] that is connected and ready for subscription.
+  ///
+  /// The certificate provided by the server is checked
+  /// using the trusted certificates set in the SecurityContext object.
+  /// The default SecurityContext object contains a built-in set of trusted
+  /// root certificates for well-known certificate authorities.
+  ///
+  /// [onBadCertificate] is an optional handler for unverifiable certificates.
+  /// The handler receives the [X509Certificate], and can inspect it and
+  /// decide (or let the user decide) whether to accept
+  /// the connection or not.  The handler should return true
+  /// to continue the [SecureSocket] connection.
+  ///
+  /// [supportedProtocols] is an optional list of protocols (in decreasing
+  /// order of preference) to use during the ALPN protocol negotiation with the
+  /// server.  Example values are "http/1.1" or "h2".  The selected protocol
+  /// can be obtained via [SecureSocket.selectedProtocol].
+  ///
+  /// The argument [timeout] is used to specify the maximum allowed time to wait
+  /// for a connection to be established. If [timeout] is longer than the system
+  /// level timeout duration, a timeout may occur sooner than specified in
+  /// [timeout]. On timeout, a [SocketException] is thrown and all ongoing
+  /// connection attempts to [host] are cancelled.
   static Future<SecureSocket> connect(host, int port,
       {SecurityContext? context,
       bool onBadCertificate(X509Certificate certificate)?,
@@ -72,39 +68,38 @@
     });
   }
 
-  /**
-   * Takes an already connected [socket] and starts client side TLS
-   * handshake to make the communication secure. When the returned
-   * future completes the [SecureSocket] has completed the TLS
-   * handshake. Using this function requires that the other end of the
-   * connection is prepared for TLS handshake.
-   *
-   * If the [socket] already has a subscription, this subscription
-   * will no longer receive and events. In most cases calling
-   * `pause` on this subscription before starting TLS handshake is
-   * the right thing to do.
-   *
-   * The given [socket] is closed and may not be used anymore.
-   *
-   * If the [host] argument is passed it will be used as the host name
-   * for the TLS handshake. If [host] is not passed the host name from
-   * the [socket] will be used. The [host] can be either a [String] or
-   * an [InternetAddress].
-   *
-   * [supportedProtocols] is an optional list of protocols (in decreasing
-   * order of preference) to use during the ALPN protocol negotiation with the
-   * server.  Example values are "http/1.1" or "h2".  The selected protocol
-   * can be obtained via [SecureSocket.selectedProtocol].
-   *
-   * Calling this function will _not_ cause a DNS host lookup. If the
-   * [host] passed is a [String] the [InternetAddress] for the
-   * resulting [SecureSocket] will have the passed in [host] as its
-   * host value and the internet address of the already connected
-   * socket as its address value.
-   *
-   * See [connect] for more information on the arguments.
-   *
-   */
+  /// Initiates TLS on an existing connection.
+  ///
+  /// Takes an already connected [socket] and starts client side TLS
+  /// handshake to make the communication secure. When the returned
+  /// future completes the [SecureSocket] has completed the TLS
+  /// handshake. Using this function requires that the other end of the
+  /// connection is prepared for TLS handshake.
+  ///
+  /// If the [socket] already has a subscription, this subscription
+  /// will no longer receive and events. In most cases calling
+  /// [StreamSubscription.pause] on this subscription before
+  /// starting TLS handshake is the right thing to do.
+  ///
+  /// The given [socket] is closed and may not be used anymore.
+  ///
+  /// If the [host] argument is passed it will be used as the host name
+  /// for the TLS handshake. If [host] is not passed the host name from
+  /// the [socket] will be used. The [host] can be either a [String] or
+  /// an [InternetAddress].
+  ///
+  /// [supportedProtocols] is an optional list of protocols (in decreasing
+  /// order of preference) to use during the ALPN protocol negotiation with the
+  /// server.  Example values are "http/1.1" or "h2".  The selected protocol
+  /// can be obtained via [SecureSocket.selectedProtocol].
+  ///
+  /// Calling this function will _not_ cause a DNS host lookup. If the
+  /// [host] passed is a [String], the [InternetAddress] for the
+  /// resulting [SecureSocket] will have the passed in [host] as its
+  /// host value and the internet address of the already connected
+  /// socket as its address value.
+  ///
+  /// See [connect] for more information on the arguments.
   static Future<SecureSocket> secure(Socket socket,
       {host,
       SecurityContext? context,
@@ -121,32 +116,31 @@
     }).then<SecureSocket>((raw) => new SecureSocket._(raw));
   }
 
-  /**
-   * Takes an already connected [socket] and starts server side TLS
-   * handshake to make the communication secure. When the returned
-   * future completes the [SecureSocket] has completed the TLS
-   * handshake. Using this function requires that the other end of the
-   * connection is going to start the TLS handshake.
-   *
-   * If the [socket] already has a subscription, this subscription
-   * will no longer receive and events. In most cases calling
-   * [:pause:] on this subscription before starting TLS handshake is
-   * the right thing to do.
-   *
-   * If some of the data of the TLS handshake has already been read
-   * from the socket this data can be passed in the [bufferedData]
-   * parameter. This data will be processed before any other data
-   * available on the socket.
-   *
-   * See [SecureServerSocket.bind] for more information on the
-   * arguments.
-   *
-   */
+  /// Initiates TLS on an existing server connection.
+  ///
+  /// Takes an already connected [socket] and starts server side TLS
+  /// handshake to make the communication secure. When the returned
+  /// future completes the [SecureSocket] has completed the TLS
+  /// handshake. Using this function requires that the other end of the
+  /// connection is going to start the TLS handshake.
+  ///
+  /// If the [socket] already has a subscription, this subscription
+  /// will no longer receive and events. In most cases calling
+  /// [StreamSubscription.pause] on this subscription
+  /// before starting TLS handshake is the right thing to do.
+  ///
+  /// If some of the data of the TLS handshake has already been read
+  /// from the socket this data can be passed in the [bufferedData]
+  /// parameter. This data will be processed before any other data
+  /// available on the socket.
+  ///
+  /// See [SecureServerSocket.bind] for more information on the
+  /// arguments.
   static Future<SecureSocket> secureServer(
       Socket socket, SecurityContext? context,
       {List<int>? bufferedData,
-      bool requestClientCertificate: false,
-      bool requireClientCertificate: false,
+      bool requestClientCertificate = false,
+      bool requireClientCertificate = false,
       List<String>? supportedProtocols}) {
     return ((socket as dynamic /*_Socket*/)._detachRaw() as Future)
         .then<RawSecureSocket>((detachedRaw) {
@@ -159,71 +153,66 @@
     }).then<SecureSocket>((raw) => new SecureSocket._(raw));
   }
 
-  /**
-   * Get the peer certificate for a connected SecureSocket.  If this
-   * SecureSocket is the server end of a secure socket connection,
-   * [peerCertificate] will return the client certificate, or null, if no
-   * client certificate was received.  If it is the client end,
-   * [peerCertificate] will return the server's certificate.
-   */
+  /// The peer certificate for a connected SecureSocket.
+  ///
+  /// If this [SecureSocket] is the server end of a secure socket connection,
+  /// [peerCertificate] will return the client certificate, or `null` if no
+  /// client certificate was received.  If this socket is the client end,
+  /// [peerCertificate] will return the server's certificate.
   X509Certificate? get peerCertificate;
 
-  /**
-   * The protocol which was selected during ALPN protocol negotiation.
-   *
-   * Returns null if one of the peers does not have support for ALPN, did not
-   * specify a list of supported ALPN protocols or there was no common
-   * protocol between client and server.
-   */
+  /// The protocol which was selected during ALPN protocol negotiation.
+  ///
+  /// Returns `null` if one of the peers does not have support for ALPN, did not
+  /// specify a list of supported ALPN protocols or there was no common
+  /// protocol between client and server.
   String? get selectedProtocol;
 
-  /**
-   * Renegotiate an existing secure connection, renewing the session keys
-   * and possibly changing the connection properties.
-   *
-   * This repeats the SSL or TLS handshake, with options that allow clearing
-   * the session cache and requesting a client certificate.
-   */
+  /// Renegotiates an existing secure connection.
+  ///
+  /// Renews the session keys and possibly changes the connection properties.
+  ///
+  /// This repeats the SSL or TLS handshake, with options that allow clearing
+  /// the session cache and requesting a client certificate.
   void renegotiate(
-      {bool useSessionCache: true,
-      bool requestClientCertificate: false,
-      bool requireClientCertificate: false});
+      {bool useSessionCache = true,
+      bool requestClientCertificate = false,
+      bool requireClientCertificate = false});
 }
 
-/**
- * RawSecureSocket provides a secure (SSL or TLS) network connection.
- * Client connections to a server are provided by calling
- * RawSecureSocket.connect.  A secure server, created with
- * [RawSecureServerSocket], also returns RawSecureSocket objects representing
- * the server end of a secure connection.
- * The certificate provided by the server is checked
- * using the trusted certificates set in the SecurityContext object.
- * The default [SecurityContext] object contains a built-in set of trusted
- * root certificates for well-known certificate authorities.
- */
+/// `RawSecureSocket` provides a secure (SSL or TLS) network connection.
+///
+/// Client connections to a server are provided by calling
+/// RawSecureSocket.connect.  A secure server, created with
+/// [RawSecureServerSocket], also returns `RawSecureSocket` objects representing
+/// the server end of a secure connection.
+/// The certificate provided by the server is checked
+/// using the trusted certificates set in the [SecurityContext] object.
+/// The default [SecurityContext] object contains a built-in set of trusted
+/// root certificates for well-known certificate authorities.
 abstract class RawSecureSocket implements RawSocket {
-  /**
-   * Constructs a new secure client socket and connect it to the given
-   * host on the given port. The returned [Future] is completed with the
-   * RawSecureSocket when it is connected and ready for subscription.
-   *
-   * The certificate provided by the server is checked using the trusted
-   * certificates set in the SecurityContext object If a certificate and key are
-   * set on the client, using [SecurityContext.useCertificateChain] and
-   * [SecurityContext.usePrivateKey], and the server asks for a client
-   * certificate, then that client certificate is sent to the server.
-   *
-   * [onBadCertificate] is an optional handler for unverifiable certificates.
-   * The handler receives the [X509Certificate], and can inspect it and
-   * decide (or let the user decide) whether to accept
-   * the connection or not.  The handler should return true
-   * to continue the [RawSecureSocket] connection.
-   *
-   * [supportedProtocols] is an optional list of protocols (in decreasing
-   * order of preference) to use during the ALPN protocol negotiation with the
-   * server.  Example values are "http/1.1" or "h2".  The selected protocol
-   * can be obtained via [RawSecureSocket.selectedProtocol].
-   */
+  /// Constructs a new secure client socket and connect it to the given
+  /// host on the given port.
+  ///
+  /// The returned [Future] is completed with the
+  /// [RawSecureSocket] when it is connected and ready for subscription.
+  ///
+  /// The certificate provided by the server is checked using the trusted
+  /// certificates set in the SecurityContext object If a certificate and key are
+  /// set on the client, using [SecurityContext.useCertificateChain] and
+  /// [SecurityContext.usePrivateKey], and the server asks for a client
+  /// certificate, then that client certificate is sent to the server.
+  ///
+  /// [onBadCertificate] is an optional handler for unverifiable certificates.
+  /// The handler receives the [X509Certificate], and can inspect it and
+  /// decide (or let the user decide) whether to accept
+  /// the connection or not.  The handler should return true
+  /// to continue the [RawSecureSocket] connection.
+  ///
+  /// [supportedProtocols] is an optional list of protocols (in decreasing
+  /// order of preference) to use during the ALPN protocol negotiation with the
+  /// server.  Example values are "http/1.1" or "h2".  The selected protocol
+  /// can be obtained via [RawSecureSocket.selectedProtocol].
   static Future<RawSecureSocket> connect(host, int port,
       {SecurityContext? context,
       bool onBadCertificate(X509Certificate certificate)?,
@@ -257,39 +246,38 @@
     });
   }
 
-  /**
-   * Takes an already connected [socket] and starts client side TLS
-   * handshake to make the communication secure. When the returned
-   * future completes the [RawSecureSocket] has completed the TLS
-   * handshake. Using this function requires that the other end of the
-   * connection is prepared for TLS handshake.
-   *
-   * If the [socket] already has a subscription, pass the existing
-   * subscription in the [subscription] parameter. The [secure]
-   * operation will take over the subscription by replacing the
-   * handlers with it own secure processing. The caller must not touch
-   * this subscription anymore. Passing a paused subscription is an
-   * error.
-   *
-   * If the [host] argument is passed it will be used as the host name
-   * for the TLS handshake. If [host] is not passed the host name from
-   * the [socket] will be used. The [host] can be either a [String] or
-   * an [InternetAddress].
-   *
-   * [supportedProtocols] is an optional list of protocols (in decreasing
-   * order of preference) to use during the ALPN protocol negotiation with the
-   * server.  Example values are "http/1.1" or "h2".  The selected protocol
-   * can be obtained via [SecureSocket.selectedProtocol].
-   *
-   * Calling this function will _not_ cause a DNS host lookup. If the
-   * [host] passed is a [String] the [InternetAddress] for the
-   * resulting [SecureSocket] will have this passed in [host] as its
-   * host value and the internet address of the already connected
-   * socket as its address value.
-   *
-   * See [connect] for more information on the arguments.
-   *
-   */
+  /// Initiates TLS on an existing connection.
+  ///
+  /// Takes an already connected [socket] and starts client side TLS
+  /// handshake to make the communication secure. When the returned
+  /// future completes the [RawSecureSocket] has completed the TLS
+  /// handshake. Using this function requires that the other end of the
+  /// connection is prepared for TLS handshake.
+  ///
+  /// If the [socket] already has a subscription, pass the existing
+  /// subscription in the [subscription] parameter. The [secure]
+  /// operation will take over the subscription by replacing the
+  /// handlers with it own secure processing. The caller must not touch
+  /// this subscription anymore. Passing a paused subscription is an
+  /// error.
+  ///
+  /// If the [host] argument is passed it will be used as the host name
+  /// for the TLS handshake. If [host] is not passed the host name from
+  /// the [socket] will be used. The [host] can be either a [String] or
+  /// an [InternetAddress].
+  ///
+  /// [supportedProtocols] is an optional list of protocols (in decreasing
+  /// order of preference) to use during the ALPN protocol negotiation with the
+  /// server.  Example values are "http/1.1" or "h2".  The selected protocol
+  /// can be obtained via [SecureSocket.selectedProtocol].
+  ///
+  /// Calling this function will _not_ cause a DNS host lookup. If the
+  /// [host] passed is a [String] the [InternetAddress] for the
+  /// resulting [SecureSocket] will have this passed in [host] as its
+  /// host value and the internet address of the already connected
+  /// socket as its address value.
+  ///
+  /// See [connect] for more information on the arguments.
   static Future<RawSecureSocket> secure(RawSocket socket,
       {StreamSubscription<RawSocketEvent>? subscription,
       host,
@@ -306,35 +294,34 @@
         supportedProtocols: supportedProtocols);
   }
 
-  /**
-   * Takes an already connected [socket] and starts server side TLS
-   * handshake to make the communication secure. When the returned
-   * future completes the [RawSecureSocket] has completed the TLS
-   * handshake. Using this function requires that the other end of the
-   * connection is going to start the TLS handshake.
-   *
-   * If the [socket] already has a subscription, pass the existing
-   * subscription in the [subscription] parameter. The [secureServer]
-   * operation will take over the subscription by replacing the
-   * handlers with it own secure processing. The caller must not touch
-   * this subscription anymore. Passing a paused subscription is an
-   * error.
-   *
-   * If some of the data of the TLS handshake has already been read
-   * from the socket this data can be passed in the [bufferedData]
-   * parameter. This data will be processed before any other data
-   * available on the socket.
-   *
-   * See [RawSecureServerSocket.bind] for more information on the
-   * arguments.
-   *
-   */
+  /// Initiates TLS on an existing server connection.
+  ///
+  /// Takes an already connected [socket] and starts server side TLS
+  /// handshake to make the communication secure. When the returned
+  /// future completes the [RawSecureSocket] has completed the TLS
+  /// handshake. Using this function requires that the other end of the
+  /// connection is going to start the TLS handshake.
+  ///
+  /// If the [socket] already has a subscription, pass the existing
+  /// subscription in the [subscription] parameter. The [secureServer]
+  /// operation will take over the subscription by replacing the
+  /// handlers with it own secure processing. The caller must not touch
+  /// this subscription anymore. Passing a paused subscription is an
+  /// error.
+  ///
+  /// If some of the data of the TLS handshake has already been read
+  /// from the socket this data can be passed in the [bufferedData]
+  /// parameter. This data will be processed before any other data
+  /// available on the socket.
+  ///
+  /// See [RawSecureServerSocket.bind] for more information on the
+  /// arguments.
   static Future<RawSecureSocket> secureServer(
       RawSocket socket, SecurityContext? context,
       {StreamSubscription<RawSocketEvent>? subscription,
       List<int>? bufferedData,
-      bool requestClientCertificate: false,
-      bool requireClientCertificate: false,
+      bool requestClientCertificate = false,
+      bool requireClientCertificate = false,
       List<String>? supportedProtocols}) {
     socket.readEventsEnabled = false;
     socket.writeEventsEnabled = false;
@@ -348,41 +335,33 @@
         supportedProtocols: supportedProtocols);
   }
 
-  /**
-   * Renegotiate an existing secure connection, renewing the session keys
-   * and possibly changing the connection properties.
-   *
-   * This repeats the SSL or TLS handshake, with options that allow clearing
-   * the session cache and requesting a client certificate.
-   */
+  /// Renegotiate an existing secure connection, renewing the session keys
+  /// and possibly changing the connection properties.
+  ///
+  /// This repeats the SSL or TLS handshake, with options that allow clearing
+  /// the session cache and requesting a client certificate.
   void renegotiate(
-      {bool useSessionCache: true,
-      bool requestClientCertificate: false,
-      bool requireClientCertificate: false});
+      {bool useSessionCache = true,
+      bool requestClientCertificate = false,
+      bool requireClientCertificate = false});
 
-  /**
-   * Get the peer certificate for a connected RawSecureSocket.  If this
-   * RawSecureSocket is the server end of a secure socket connection,
-   * [peerCertificate] will return the client certificate, or null, if no
-   * client certificate was received.  If it is the client end,
-   * [peerCertificate] will return the server's certificate.
-   */
+  /// Get the peer certificate for a connected RawSecureSocket.  If this
+  /// RawSecureSocket is the server end of a secure socket connection,
+  /// [peerCertificate] will return the client certificate, or null, if no
+  /// client certificate was received.  If it is the client end,
+  /// [peerCertificate] will return the server's certificate.
   X509Certificate? get peerCertificate;
 
-  /**
-   * The protocol which was selected during protocol negotiation.
-   *
-   * Returns null if one of the peers does not have support for ALPN, did not
-   * specify a list of supported ALPN protocols or there was no common
-   * protocol between client and server.
-   */
+  /// The protocol which was selected during protocol negotiation.
+  ///
+  /// Returns null if one of the peers does not have support for ALPN, did not
+  /// specify a list of supported ALPN protocols or there was no common
+  /// protocol between client and server.
   String? get selectedProtocol;
 }
 
-/**
- * X509Certificate represents an SSL certificate, with accessors to
- * get the fields of the certificate.
- */
+/// X509Certificate represents an SSL certificate, with accessors to
+/// get the fields of the certificate.
 @pragma("vm:entry-point")
 abstract class X509Certificate {
   @pragma("vm:entry-point")
@@ -476,8 +455,8 @@
       {SecurityContext? context,
       StreamSubscription<RawSocketEvent>? subscription,
       List<int>? bufferedData,
-      bool requestClientCertificate: false,
-      bool requireClientCertificate: false,
+      bool requestClientCertificate = false,
+      bool requireClientCertificate = false,
       bool onBadCertificate(X509Certificate certificate)?,
       List<String>? supportedProtocols}) {
     _verifyFields(host, requestedPort, requestClientCertificate,
@@ -828,9 +807,9 @@
   }
 
   void renegotiate(
-      {bool useSessionCache: true,
-      bool requestClientCertificate: false,
-      bool requireClientCertificate: false}) {
+      {bool useSessionCache = true,
+      bool requestClientCertificate = false,
+      bool requireClientCertificate = false}) {
     if (_status != connectedStatus) {
       throw new HandshakeException(
           "Called renegotiate on a non-connected socket");
@@ -882,69 +861,70 @@
     }
   }
 
-  Future<void> _scheduleFilter() async {
+  Future<void> _scheduleFilter() {
     _filterPending = true;
     return _tryFilter();
   }
 
   Future<void> _tryFilter() async {
-    if (_status == closedStatus) {
-      return;
-    }
-    if (!_filterPending || _filterActive) {
-      return;
-    }
-    _filterActive = true;
-    _filterPending = false;
-
     try {
-      _filterStatus = await _pushAllFilterStages();
-      _filterActive = false;
-      if (_status == closedStatus) {
-        _secureFilter!.destroy();
-        _secureFilter = null;
-        return;
-      }
-      _socket.readEventsEnabled = true;
-      if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) {
-        // Checks for and handles all cases of partially closed sockets.
-        shutdown(SocketDirection.send);
+      while (true) {
         if (_status == closedStatus) {
           return;
         }
-      }
-      if (_filterStatus.readEmpty && _socketClosedRead && !_closedRead) {
-        if (_status == handshakeStatus) {
-          _secureFilter!.handshake();
-          if (_status == handshakeStatus) {
-            throw new HandshakeException(
-                'Connection terminated during handshake');
+        if (!_filterPending || _filterActive) {
+          return;
+        }
+        _filterActive = true;
+        _filterPending = false;
+
+        _filterStatus = await _pushAllFilterStages();
+        _filterActive = false;
+        if (_status == closedStatus) {
+          _secureFilter!.destroy();
+          _secureFilter = null;
+          return;
+        }
+        _socket.readEventsEnabled = true;
+        if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) {
+          // Checks for and handles all cases of partially closed sockets.
+          shutdown(SocketDirection.send);
+          if (_status == closedStatus) {
+            return;
           }
         }
-        _closeHandler();
-      }
-      if (_status == closedStatus) {
-        return;
-      }
-      if (_filterStatus.progress) {
-        _filterPending = true;
-        if (_filterStatus.writeEncryptedNoLongerEmpty) {
-          _writeSocket();
+        if (_filterStatus.readEmpty && _socketClosedRead && !_closedRead) {
+          if (_status == handshakeStatus) {
+            _secureFilter!.handshake();
+            if (_status == handshakeStatus) {
+              throw new HandshakeException(
+                  'Connection terminated during handshake');
+            }
+          }
+          _closeHandler();
         }
-        if (_filterStatus.writePlaintextNoLongerFull) {
-          _sendWriteEvent();
+        if (_status == closedStatus) {
+          return;
         }
-        if (_filterStatus.readEncryptedNoLongerFull) {
-          _readSocket();
-        }
-        if (_filterStatus.readPlaintextNoLongerEmpty) {
-          _scheduleReadEvent();
-        }
-        if (_status == handshakeStatus) {
-          await _secureHandshake();
+        if (_filterStatus.progress) {
+          _filterPending = true;
+          if (_filterStatus.writeEncryptedNoLongerEmpty) {
+            _writeSocket();
+          }
+          if (_filterStatus.writePlaintextNoLongerFull) {
+            _sendWriteEvent();
+          }
+          if (_filterStatus.readEncryptedNoLongerFull) {
+            _readSocket();
+          }
+          if (_filterStatus.readPlaintextNoLongerEmpty) {
+            _scheduleReadEvent();
+          }
+          if (_status == handshakeStatus) {
+            await _secureHandshake();
+          }
         }
       }
-      return _tryFilter();
     } catch (e, st) {
       _reportError(e, st);
     }
@@ -1107,11 +1087,9 @@
   }
 }
 
-/**
- * A circular buffer backed by an external byte array.  Accessed from
- * both C++ and Dart code in an unsynchronized way, with one reading
- * and one writing.  All updates to start and end are done by Dart code.
- */
+/// A circular buffer backed by an external byte array.  Accessed from
+/// both C++ and Dart code in an unsynchronized way, with one reading
+/// and one writing.  All updates to start and end are done by Dart code.
 class _ExternalBuffer {
   // This will be an ExternalByteArray, backed by C allocated data.
   @pragma("vm:entry-point", "set")
@@ -1262,9 +1240,8 @@
   List<_ExternalBuffer>? get buffers;
 }
 
-/** A secure networking exception caused by a failure in the
- *  TLS/SSL protocol.
- */
+/// A secure networking exception caused by a failure in the
+/// TLS/SSL protocol.
 class TlsException implements IOException {
   final String type;
   final String message;
@@ -1291,10 +1268,8 @@
   }
 }
 
-/**
- * An exception that happens in the handshake phase of establishing
- * a secure network connection.
- */
+/// An exception that happens in the handshake phase of establishing
+/// a secure network connection.
 @pragma("vm:entry-point")
 class HandshakeException extends TlsException {
   @pragma("vm:entry-point")
@@ -1302,11 +1277,9 @@
       : super._("HandshakeException", message, osError);
 }
 
-/**
- * An exception that happens in the handshake phase of establishing
- * a secure network connection, when looking up or verifying a
- * certificate.
- */
+/// An exception that happens in the handshake phase of establishing
+/// a secure network connection, when looking up or verifying a
+/// certificate.
 class CertificateException extends TlsException {
   @pragma("vm:entry-point")
   const CertificateException([String message = "", OSError? osError])
diff --git a/sdk/lib/io/security_context.dart b/sdk/lib/io/security_context.dart
index e4fd5c6..082da28 100644
--- a/sdk/lib/io/security_context.dart
+++ b/sdk/lib/io/security_context.dart
@@ -4,198 +4,176 @@
 
 part of dart.io;
 
-/**
- * The object containing the certificates to trust when making
- * a secure client connection, and the certificate chain and
- * private key to serve from a secure server.
- *
- * The [SecureSocket]  and [SecureServerSocket] classes take a SecurityContext
- * as an argument to their connect and bind methods.
- *
- * Certificates and keys can be added to a SecurityContext from either PEM
- * or PKCS12 containers.
- *
- * iOS note: Some methods to add, remove, and inspect certificates are not yet
- * implemented. However, the platform's built-in trusted certificates can
- * be used, by way of [SecurityContext.defaultContext].
- */
+/// The object containing the certificates to trust when making
+/// a secure client connection, and the certificate chain and
+/// private key to serve from a secure server.
+///
+/// The [SecureSocket]  and [SecureServerSocket] classes take a SecurityContext
+/// as an argument to their connect and bind methods.
+///
+/// Certificates and keys can be added to a SecurityContext from either PEM
+/// or PKCS12 containers.
+///
+/// iOS note: Some methods to add, remove, and inspect certificates are not yet
+/// implemented. However, the platform's built-in trusted certificates can
+/// be used, by way of [SecurityContext.defaultContext].
 abstract class SecurityContext {
-  /**
-   * Creates a new [SecurityContext].
-   *
-   * By default, the created [SecurityContext] contains no keys or certificates.
-   * These can be added by calling the methods of this class.
-   *
-   * If `withTrustedRoots` is passed as `true`, the [SecurityContext] will be
-   * seeded by the trusted root certificates provided as explained below. To
-   * obtain a [SecurityContext] containing trusted root certificates,
-   * [SecurityContext.defaultContext] is usually sufficient, and should
-   * be used instead. However, if the [SecurityContext] containing the trusted
-   * root certificates must be modified per-connection, then `withTrustedRoots`
-   * should be used.
-   */
-  external factory SecurityContext({bool withTrustedRoots: false});
+  /// Creates a new [SecurityContext].
+  ///
+  /// By default, the created [SecurityContext] contains no keys or certificates.
+  /// These can be added by calling the methods of this class.
+  ///
+  /// If [withTrustedRoots] is passed as `true`, the [SecurityContext] will be
+  /// seeded by the trusted root certificates provided as explained below. To
+  /// obtain a [SecurityContext] containing trusted root certificates,
+  /// [SecurityContext.defaultContext] is usually sufficient, and should
+  /// be used instead. However, if the [SecurityContext] containing the trusted
+  /// root certificates must be modified per-connection, then [withTrustedRoots]
+  /// should be used.
+  external factory SecurityContext({bool withTrustedRoots = false});
 
-  /**
-   * Secure networking classes with an optional `context` parameter
-   * use the [defaultContext] object if the parameter is omitted.
-   * This object can also be accessed, and modified, directly.
-   * Each isolate has a different [defaultContext] object.
-   * The [defaultContext] object uses a list of well-known trusted
-   * certificate authorities as its trusted roots. On Linux and Windows, this
-   * list is taken from Mozilla, who maintains it as part of Firefox. On,
-   * MacOS, iOS, and Android, this list comes from the trusted certificates
-   * stores built in to the platforms.
-   */
+  /// The default security context used by most operation requiring one.
+  ///
+  /// Secure networking classes with an optional `context` parameter
+  /// use the [defaultContext] object if the parameter is omitted.
+  /// This object can also be accessed, and modified, directly.
+  /// Each isolate has a different [defaultContext] object.
+  /// The [defaultContext] object uses a list of well-known trusted
+  /// certificate authorities as its trusted roots. On Linux and Windows, this
+  /// list is taken from Mozilla, who maintains it as part of Firefox. On,
+  /// MacOS, iOS, and Android, this list comes from the trusted certificates
+  /// stores built in to the platforms.
   external static SecurityContext get defaultContext;
 
-  /**
-   * Sets the private key for a server certificate or client certificate.
-   *
-   * A secure connection using this SecurityContext will use this key with
-   * the server or client certificate to sign and decrypt messages.
-   * [file] is the path to a PEM or PKCS12 file containing an encrypted
-   * private key, encrypted with [password]. Assuming it is well-formatted, all
-   * other contents of [file] are ignored. An unencrypted file can be used,
-   * but this is not usual.
-   *
-   * NB: This function calls [File.readAsBytesSync], and will block on file IO.
-   * Prefer using [usePrivateKeyBytes].
-   *
-   * iOS note: Only PKCS12 data is supported. It should contain both the private
-   * key and the certificate chain. On iOS one call to [usePrivateKey] with this
-   * data is used instead of two calls to [useCertificateChain] and
-   * [usePrivateKey].
-   */
+  /// Sets the private key for a server certificate or client certificate.
+  ///
+  /// A secure connection using this SecurityContext will use this key with
+  /// the server or client certificate to sign and decrypt messages.
+  /// [file] is the path to a PEM or PKCS12 file containing an encrypted
+  /// private key, encrypted with [password]. Assuming it is well-formatted, all
+  /// other contents of [file] are ignored. An unencrypted file can be used,
+  /// but this is not usual.
+  ///
+  /// NB: This function calls [File.readAsBytesSync], and will block on file IO.
+  /// Prefer using [usePrivateKeyBytes].
+  ///
+  /// iOS note: Only PKCS12 data is supported. It should contain both the private
+  /// key and the certificate chain. On iOS one call to [usePrivateKey] with this
+  /// data is used instead of two calls to [useCertificateChain] and
+  /// [usePrivateKey].
   void usePrivateKey(String file, {String? password});
 
-  /**
-   * Sets the private key for a server certificate or client certificate.
-   *
-   * Like [usePrivateKey], but takes the contents of the file as a list
-   * of bytes.
-   */
+  /// Sets the private key for a server certificate or client certificate.
+  ///
+  /// Like [usePrivateKey], but takes the contents of the file as a list
+  /// of bytes.
   void usePrivateKeyBytes(List<int> keyBytes, {String? password});
 
-  /**
-   * Sets the set of trusted X509 certificates used by [SecureSocket]
-   * client connections, when connecting to a secure server.
-   *
-   * [file] is the path to a PEM or PKCS12 file containing X509 certificates,
-   * usually root certificates from certificate authorities. For PKCS12 files,
-   * [password] is the password for the file. For PEM files, [password] is
-   * ignored. Assuming it is well-formatted, all other contents of [file] are
-   * ignored.
-   *
-   * NB: This function calls [File.readAsBytesSync], and will block on file IO.
-   * Prefer using [setTrustedCertificatesBytes].
-   *
-   * iOS note: On iOS, this call takes only the bytes for a single DER
-   * encoded X509 certificate. It may be called multiple times to add
-   * multiple trusted certificates to the context. A DER encoded certificate
-   * can be obtained from a PEM encoded certificate by using the openssl tool:
-   *
-   *   $ openssl x509 -outform der -in cert.pem -out cert.der
-   */
+  /// Sets the set of trusted X509 certificates used by [SecureSocket]
+  /// client connections, when connecting to a secure server.
+  ///
+  /// [file] is the path to a PEM or PKCS12 file containing X509 certificates,
+  /// usually root certificates from certificate authorities. For PKCS12 files,
+  /// [password] is the password for the file. For PEM files, [password] is
+  /// ignored. Assuming it is well-formatted, all other contents of [file] are
+  /// ignored.
+  ///
+  /// NB: This function calls [File.readAsBytesSync], and will block on file IO.
+  /// Prefer using [setTrustedCertificatesBytes].
+  ///
+  /// iOS note: On iOS, this call takes only the bytes for a single DER
+  /// encoded X509 certificate. It may be called multiple times to add
+  /// multiple trusted certificates to the context. A DER encoded certificate
+  /// can be obtained from a PEM encoded certificate by using the openssl tool:
+  /// ```
+  /// $ openssl x509 -outform der -in cert.pem -out cert.der
+  /// ```
   void setTrustedCertificates(String file, {String? password});
 
-  /**
-   * Sets the set of trusted X509 certificates used by [SecureSocket]
-   * client connections, when connecting to a secure server.
-   *
-   * Like [setTrustedCertificates] but takes the contents of the file.
-   */
+  /// Sets the set of trusted X509 certificates used by [SecureSocket]
+  /// client connections, when connecting to a secure server.
+  ///
+  /// Like [setTrustedCertificates] but takes the contents of the file.
   void setTrustedCertificatesBytes(List<int> certBytes, {String? password});
 
-  /**
-   * Sets the chain of X509 certificates served by [SecureServerSocket]
-   * when making secure connections, including the server certificate.
-   *
-   * [file] is a PEM or PKCS12 file containing X509 certificates, starting with
-   * the root authority and intermediate authorities forming the signed
-   * chain to the server certificate, and ending with the server certificate.
-   * The private key for the server certificate is set by [usePrivateKey]. For
-   * PKCS12 files, [password] is the password for the file. For PEM files,
-   * [password] is ignored. Assuming it is well-formatted, all
-   * other contents of [file] are ignored.
-   *
-   * NB: This function calls [File.readAsBytesSync], and will block on file IO.
-   * Prefer using [useCertificateChainBytes].
-   *
-   * iOS note: As noted above, [usePrivateKey] does the job of both
-   * that call and this one. On iOS, this call is a no-op.
-   */
+  /// Sets the chain of X509 certificates served by [SecureServerSocket]
+  /// when making secure connections, including the server certificate.
+  ///
+  /// [file] is a PEM or PKCS12 file containing X509 certificates, starting with
+  /// the root authority and intermediate authorities forming the signed
+  /// chain to the server certificate, and ending with the server certificate.
+  /// The private key for the server certificate is set by [usePrivateKey]. For
+  /// PKCS12 files, [password] is the password for the file. For PEM files,
+  /// [password] is ignored. Assuming it is well-formatted, all
+  /// other contents of [file] are ignored.
+  ///
+  /// NB: This function calls [File.readAsBytesSync], and will block on file IO.
+  /// Prefer using [useCertificateChainBytes].
+  ///
+  /// iOS note: As noted above, [usePrivateKey] does the job of both
+  /// that call and this one. On iOS, this call is a no-op.
   void useCertificateChain(String file, {String? password});
 
-  /**
-   * Sets the chain of X509 certificates served by [SecureServerSocket]
-   * when making secure connections, including the server certificate.
-   *
-   * Like [useCertificateChain] but takes the contents of the file.
-   */
+  /// Sets the chain of X509 certificates served by [SecureServerSocket]
+  /// when making secure connections, including the server certificate.
+  ///
+  /// Like [useCertificateChain] but takes the contents of the file.
   void useCertificateChainBytes(List<int> chainBytes, {String? password});
 
-  /**
-   * Sets the list of authority names that a [SecureServerSocket] will advertise
-   * as accepted when requesting a client certificate from a connecting
-   * client.
-   *
-   * [file] is a PEM or PKCS12 file containing the accepted signing
-   * authority certificates - the authority names are extracted from the
-   * certificates. For PKCS12 files, [password] is the password for the file.
-   * For PEM files, [password] is ignored. Assuming it is well-formatted, all
-   * other contents of [file] are ignored.
-   *
-   * NB: This function calls [File.readAsBytesSync], and will block on file IO.
-   * Prefer using [setClientAuthoritiesBytes].
-   *
-   * iOS note: This call is not supported.
-   */
+  /// Sets the list of authority names that a [SecureServerSocket] will advertise
+  /// as accepted when requesting a client certificate from a connecting
+  /// client.
+  ///
+  /// The [file] is a PEM or PKCS12 file containing the accepted signing
+  /// authority certificates - the authority names are extracted from the
+  /// certificates. For PKCS12 files, [password] is the password for the file.
+  /// For PEM files, [password] is ignored. Assuming it is well-formatted, all
+  /// other contents of [file] are ignored.
+  ///
+  /// NB: This function calls [File.readAsBytesSync], and will block on file IO.
+  /// Prefer using [setClientAuthoritiesBytes].
+  ///
+  /// iOS note: This call is not supported.
   void setClientAuthorities(String file, {String? password});
 
-  /**
-   * Sets the list of authority names that a [SecureServerSocket] will advertise
-   * as accepted, when requesting a client certificate from a connecting
-   * client.
-   *
-   * Like [setClientAuthorities] but takes the contents of the file.
-   */
+  /// Sets the list of authority names that a [SecureServerSocket] will advertise
+  /// as accepted, when requesting a client certificate from a connecting
+  /// client.
+  ///
+  /// Like [setClientAuthorities] but takes the contents of the file.
   void setClientAuthoritiesBytes(List<int> authCertBytes, {String? password});
 
-  /**
-   * Whether the platform supports ALPN. This always returns true and will be
-   * removed in a future release.
-   */
+  /// Whether the platform supports ALPN. This always returns true and will be
+  /// removed in a future release.
   @deprecated
   external static bool get alpnSupported;
 
-  /**
-   * Sets the list of application-level protocols supported by a client
-   * connection or server connection. The ALPN (application level protocol
-   * negotiation) extension to TLS allows a client to send a list of
-   * protocols in the TLS client hello message, and the server to pick
-   * one and send the selected one back in its server hello message.
-   *
-   * Separate lists of protocols can be sent for client connections and
-   * for server connections, using the same SecurityContext.  The [isServer]
-   * boolean argument specifies whether to set the list for server connections
-   * or client connections.
-   */
+  /// Sets the list of application-level protocols supported by a client
+  /// connection or server connection. The ALPN (application level protocol
+  /// negotiation) extension to TLS allows a client to send a list of
+  /// protocols in the TLS client hello message, and the server to pick
+  /// one and send the selected one back in its server hello message.
+  ///
+  /// Separate lists of protocols can be sent for client connections and
+  /// for server connections, using the same SecurityContext.  The [isServer]
+  /// boolean argument specifies whether to set the list for server connections
+  /// or client connections.
   void setAlpnProtocols(List<String> protocols, bool isServer);
 
   /// Encodes a set of supported protocols for ALPN/NPN usage.
   ///
-  /// The `protocols` list is expected to contain protocols in descending order
+  /// The [protocols] list is expected to contain protocols in descending order
   /// of preference.
   ///
   /// See RFC 7301 (https://tools.ietf.org/html/rfc7301) for the encoding of
   /// `List<String> protocols`:
-  ///     opaque ProtocolName<1..2^8-1>;
+  /// ```
+  /// opaque ProtocolName<1..2^8-1>;
   ///
-  ///     struct {
-  ///         ProtocolName protocol_name_list<2..2^16-1>
-  ///     } ProtocolNameList;
-  ///
+  /// struct {
+  ///     ProtocolName protocol_name_list<2..2^16-1>
+  /// } ProtocolNameList;
+  /// ```
   /// The encoding of the opaque `ProtocolName<lower..upper>` vector is
   /// described in RFC 2246: 4.3 Vectors.
   ///
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index 48f428f..a0eea00 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -4,12 +4,11 @@
 
 part of dart.io;
 
-/**
- * [InternetAddressType] is the type an [InternetAddress]. Currently,
- * IP version 4 (IPv4), IP version 6 (IPv6) and Unix domain address are
- * supported. Unix domain sockets are available only on Linux, MacOS and
- * Android.
- */
+/// The type, or address family, of an [InternetAddress].
+///
+/// Currently, IP version 4 (IPv4), IP version 6 (IPv6)
+/// and Unix domain address are supported.
+/// Unix domain sockets are available only on Linux, MacOS and Android.
 class InternetAddressType {
   static const InternetAddressType IPv4 = const InternetAddressType._(0);
   static const InternetAddressType IPv6 = const InternetAddressType._(1);
@@ -35,182 +34,139 @@
     throw new ArgumentError("Invalid type: $value");
   }
 
-  /**
-   * Get the name of the type, e.g. "IPv4" or "IPv6".
-   */
-  String get name {
-    switch (_value) {
-      case -1:
-        return "ANY";
-      case 0:
-        return "IPv4";
-      case 1:
-        return "IPv6";
-      case 2:
-        return "Unix";
-      default:
-        throw new ArgumentError("Invalid InternetAddress");
-    }
-  }
+  /// Get the name of the type, e.g. "IPv4" or "IPv6".
+  String get name => const ["ANY", "IPv4", "IPv6", "Unix"][_value + 1];
 
   String toString() => "InternetAddressType: $name";
 }
 
-/**
- * An internet address or a Unix domain address.
- *
- * This object holds an internet address. If this internet address
- * is the result of a DNS lookup, the address also holds the hostname
- * used to make the lookup.
- * An Internet address combined with a port number represents an
- * endpoint to which a socket can connect or a listening socket can
- * bind.
- */
+/// An internet address or a Unix domain address.
+///
+/// This object holds an internet address. If this internet address
+/// is the result of a DNS lookup, the address also holds the hostname
+/// used to make the lookup.
+/// An Internet address combined with a port number represents an
+/// endpoint to which a socket can connect or a listening socket can
+/// bind.
 abstract class InternetAddress {
-  /**
-   * IP version 4 loopback address. Use this address when listening on
-   * or connecting to the loopback adapter using IP version 4 (IPv4).
-   */
+  /// IP version 4 loopback address.
+  ///
+  /// Use this address when listening on or connecting
+  /// to the loopback adapter using IP version 4 (IPv4).
   static InternetAddress get loopbackIPv4 => LOOPBACK_IP_V4;
   @Deprecated("Use loopbackIPv4 instead")
   external static InternetAddress get LOOPBACK_IP_V4;
 
-  /**
-   * IP version 6 loopback address. Use this address when listening on
-   * or connecting to the loopback adapter using IP version 6 (IPv6).
-   */
+  /// IP version 6 loopback address.
+  ///
+  /// Use this address when listening on or connecting to
+  /// the loopback adapter using IP version 6 (IPv6).
   static InternetAddress get loopbackIPv6 => LOOPBACK_IP_V6;
   @Deprecated("Use loopbackIPv6 instead")
   external static InternetAddress get LOOPBACK_IP_V6;
 
-  /**
-   * IP version 4 any address. Use this address when listening on
-   * all adapters IP addresses using IP version 4 (IPv4).
-   */
+  /// IP version 4 any address.
+  ///
+  /// Use this address when listening on the addresses
+  /// of all adapters using IP version 4 (IPv4).
   static InternetAddress get anyIPv4 => ANY_IP_V4;
   @Deprecated("Use anyIPv4 instead")
   external static InternetAddress get ANY_IP_V4;
 
-  /**
-   * IP version 6 any address. Use this address when listening on
-   * all adapters IP addresses using IP version 6 (IPv6).
-   */
+  /// IP version 6 any address.
+  ///
+  /// Use this address when listening on the addresses
+  /// of all adapters using IP version 6 (IPv6).
   static InternetAddress get anyIPv6 => ANY_IP_V6;
   @Deprecated("Use anyIPv6 instead")
   external static InternetAddress get ANY_IP_V6;
 
-  /**
-   * The address family of the [InternetAddress].
-   */
+  /// The address family of the [InternetAddress].
   InternetAddressType get type;
 
-  /**
-   * The numeric address of the host.
-   *
-   * For IPv4 addresses this is using the dotted-decimal notation.
-   * For IPv6 it is using the hexadecimal representation.
-   * For Unix domain addresses, this is a file path.
-   */
+  /// The numeric address of the host.
+  ///
+  /// For IPv4 addresses this is using the dotted-decimal notation.
+  /// For IPv6 it is using the hexadecimal representation.
+  /// For Unix domain addresses, this is a file path.
   String get address;
 
-  /**
-   * The host used to lookup the address.
-   *
-   * If there is no host associated with the address this returns the [address].
-   */
+  /// The host used to lookup the address.
+  ///
+  /// If there is no host associated with the address this returns the [address].
   String get host;
 
-  /**
-   * The raw address of this [InternetAddress].
-   *
-   * For an IP address, the result is either a 4 or 16 byte long list.
-   * For a Unix domain address, UTF-8 encoded byte sequences that represents
-   * [address] is returned.
-   *
-   * The returned list is a fresh copy, making it possible to change the list without
-   * modifying the [InternetAddress].
-   */
+  /// The raw address of this [InternetAddress].
+  ///
+  /// For an IP address, the result is either a 4 or 16 byte long list.
+  /// For a Unix domain address, UTF-8 encoded byte sequences that represents
+  /// [address] is returned.
+  ///
+  /// The returned list is a fresh copy, making it possible to change the list without
+  /// modifying the [InternetAddress].
   Uint8List get rawAddress;
 
-  /**
-   * Returns true if the [InternetAddress] is a loopback address.
-   */
+  /// Whether the [InternetAddress] is a loopback address.
   bool get isLoopback;
 
-  /**
-   * Returns true if the [InternetAddress]s scope is a link-local.
-   */
+  /// Whether the scope of the [InternetAddress] is a link-local.
   bool get isLinkLocal;
 
-  /**
-   * Returns true if the [InternetAddress]s scope is multicast.
-   */
+  /// Whether the scope of the [InternetAddress] is multicast.
   bool get isMulticast;
 
-  /**
-   * Creates a new [InternetAddress] from a numeric address or a file path.
-   *
-   * If [type] is [InternetAddressType.IPv4], [address] must be a numeric IPv4
-   * address (dotted-decimal notation).
-   * If [type] is [InternetAddressType.IPv6], [address] must be a numeric IPv6
-   * address (hexadecimal notation).
-   * If [type] is [InternetAddressType.unix], [address] must be a a valid file
-   * path.
-   * If [type] is omitted, [address] must be either a numeric IPv4 or IPv6
-   * address and the type is inferred from the format.
-   *
-   * To create a Unix domain address, [type] should be
-   * [InternetAddressType.unix] and [address] should be a string.
-   */
+  /// Creates a new [InternetAddress] from a numeric address or a file path.
+  ///
+  /// If [type] is [InternetAddressType.IPv4], [address] must be a numeric IPv4
+  /// address (dotted-decimal notation).
+  /// If [type] is [InternetAddressType.IPv6], [address] must be a numeric IPv6
+  /// address (hexadecimal notation).
+  /// If [type] is [InternetAddressType.unix], [address] must be a a valid file
+  /// path.
+  /// If [type] is omitted, [address] must be either a numeric IPv4 or IPv6
+  /// address and the type is inferred from the format.
   external factory InternetAddress(String address,
       {@Since("2.8") InternetAddressType? type});
 
-  /**
-   * Creates a new [InternetAddress] from the provided raw address bytes.
-   *
-   * If the [type] is [InternetAddressType.IPv4], the [rawAddress] must have
-   * length 4.
-   * If the [type] is [InternetAddressType.IPv6], the [rawAddress] must have
-   * length 16.
-   * If the [type] is [InternetAddressType.IPv4], the [rawAddress] must be a
-   * valid UTF-8 encoded file path.
-   *
-   * If [type] is omitted, the [rawAddress] must have a length of either 4 or
-   * 16, in which case the type defaults to [InternetAddressType.IPv4] or
-   * [InternetAddressType.IPv6] respectively.
-   */
+  /// Creates a new [InternetAddress] from the provided raw address bytes.
+  ///
+  /// If the [type] is [InternetAddressType.IPv4], the [rawAddress] must have
+  /// length 4.
+  /// If the [type] is [InternetAddressType.IPv6], the [rawAddress] must have
+  /// length 16.
+  /// If the [type] is [InternetAddressType.unix], the [rawAddress] must be a
+  /// valid UTF-8 encoded file path.
+  ///
+  /// If [type] is omitted, the [rawAddress] must have a length of either 4 or
+  /// 16, in which case the type defaults to [InternetAddressType.IPv4] or
+  /// [InternetAddressType.IPv6] respectively.
   external factory InternetAddress.fromRawAddress(Uint8List rawAddress,
       {@Since("2.8") InternetAddressType? type});
 
-  /**
-   * Perform a reverse DNS lookup on this [address]
-   *
-   * Returns a new [InternetAddress] with the same address, but where the [host]
-   * field set to the result of the lookup.
-   *
-   * If this address is Unix domain addresses, no lookup is performed and this
-   * address is returned directly.
-   */
+  /// Performs a reverse DNS lookup on this [address]
+  ///
+  /// Returns a new [InternetAddress] with the same address, but where the [host]
+  /// field set to the result of the lookup.
+  ///
+  /// If this address is Unix domain addresses, no lookup is performed and this
+  /// address is returned directly.
   Future<InternetAddress> reverse();
 
-  /**
-   * Lookup a host, returning a Future of a list of
-   * [InternetAddress]s. If [type] is [InternetAddressType.ANY], it
-   * will lookup both IP version 4 (IPv4) and IP version 6 (IPv6)
-   * addresses. If [type] is either [InternetAddressType.IPv4] or
-   * [InternetAddressType.IPv6] it will only lookup addresses of the
-   * specified type. The order of the list can, and most likely will,
-   * change over time.
-   */
+  /// Looks up the addresses of a host.
+  ///
+  /// If [type] is [InternetAddressType.ANY], it will lookup both
+  /// IP version 4 (IPv4) and IP version 6 (IPv6) addresses.
+  /// If [type] is either [InternetAddressType.IPv4] or
+  /// [InternetAddressType.IPv6] it will only lookup addresses of the
+  /// specified type. The order of the list can, and most likely will,
+  /// change over time.
   external static Future<List<InternetAddress>> lookup(String host,
       {InternetAddressType type = InternetAddressType.any});
 
-  /**
-   * Clones the given [address] with the new [host].
-   *
-   * The [address] must be an [InternetAddress] that was created with one
-   * of the static methods of this class.
-   */
+  /// Clones the given [address] with the new [host].
+  ///
+  /// The [address] must be an [InternetAddress] that was created with one
+  /// of the static methods of this class.
   external static InternetAddress _cloneWithNewHost(
       InternetAddress address, String host);
 
@@ -221,166 +177,146 @@
   external static InternetAddress? tryParse(String address);
 }
 
-/**
- * A [NetworkInterface] represents an active network interface on the current
- * system. It contains a list of [InternetAddress]es that are bound to the
- * interface.
- */
+/// A [NetworkInterface] represents an active network interface on the current
+/// system. It contains a list of [InternetAddress]es that are bound to the
+/// interface.
 abstract class NetworkInterface {
-  /**
-   * Get the name of the [NetworkInterface].
-   */
+  /// The name of the [NetworkInterface].
   String get name;
 
-  /**
-   * Get the index of the [NetworkInterface].
-   */
+  /// The index of the [NetworkInterface].
   int get index;
 
-  /**
-   * Get a list of [InternetAddress]es currently bound to this
-   * [NetworkInterface].
-   */
+  /// The list of [InternetAddress]es currently bound to this
+  /// [NetworkInterface].
   List<InternetAddress> get addresses;
 
-  /**
-   * Whether [list] is supported.
-   *
-   * [list] is currently unsupported on Android.
-   */
+  /// Whether the [list] method is supported.
+  ///
+  /// The [list] method is currently unsupported on Android.
   external static bool get listSupported;
 
-  /**
-   * Query the system for [NetworkInterface]s.
-   *
-   * If [includeLoopback] is `true`, the returned list will include the
-   * loopback device. Default is `false`.
-   *
-   * If [includeLinkLocal] is `true`, the list of addresses of the returned
-   * [NetworkInterface]s, may include link local addresses. Default is `false`.
-   *
-   * If [type] is either [InternetAddressType.IPv4] or
-   * [InternetAddressType.IPv6] it will only lookup addresses of the
-   * specified type. Default is [InternetAddressType.any].
-   */
+  /// Query the system for [NetworkInterface]s.
+  ///
+  /// If [includeLoopback] is `true`, the returned list will include the
+  /// loopback device. Default is `false`.
+  ///
+  /// If [includeLinkLocal] is `true`, the list of addresses of the returned
+  /// [NetworkInterface]s, may include link local addresses. Default is `false`.
+  ///
+  /// If [type] is either [InternetAddressType.IPv4] or
+  /// [InternetAddressType.IPv6] it will only lookup addresses of the
+  /// specified type. Default is [InternetAddressType.any].
   external static Future<List<NetworkInterface>> list(
       {bool includeLoopback = false,
       bool includeLinkLocal = false,
       InternetAddressType type = InternetAddressType.any});
 }
 
-/**
- * A [RawServerSocket] represents a listening socket, and provides a
- * stream of low-level [RawSocket] objects, one for each connection
- * made to the listening socket.
- *
- * See [RawSocket] for more info.
- */
+/// A listening socket.
+///
+/// A `RawServerSocket` and provides a stream of low-level [RawSocket] objects,
+/// one for each connection made to the listening socket.
+///
+/// See [RawSocket] for more info.
 abstract class RawServerSocket implements Stream<RawSocket> {
-  /**
-   * Returns a future for a [:RawServerSocket:]. When the future
-   * completes the server socket is bound to the given [address] and
-   * [port] and has started listening on it.
-   *
-   * The [address] can either be a [String] or an
-   * [InternetAddress]. If [address] is a [String], [bind] will
-   * perform a [InternetAddress.lookup] and use the first value in the
-   * list. To listen on the loopback adapter, which will allow only
-   * incoming connections from the local host, use the value
-   * [InternetAddress.loopbackIPv4] or
-   * [InternetAddress.loopbackIPv6]. To allow for incoming
-   * connection from the network use either one of the values
-   * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
-   * bind to all interfaces or the IP address of a specific interface.
-   *
-   * If an IP version 6 (IPv6) address is used, both IP version 6
-   * (IPv6) and version 4 (IPv4) connections will be accepted. To
-   * restrict this to version 6 (IPv6) only, use [v6Only] to set
-   * version 6 only.
-   *
-   * If [port] has the value [:0:] an ephemeral port will
-   * be chosen by the system. The actual port used can be retrieved
-   * using the [:port:] getter.
-   *
-   * The optional argument [backlog] can be used to specify the listen
-   * backlog for the underlying OS listen setup. If [backlog] has the
-   * value of [:0:] (the default) a reasonable value will be chosen by
-   * the system.
-   *
-   * The optional argument [shared] specifies whether additional RawServerSocket
-   * objects can bind to the same combination of `address`, `port` and `v6Only`.
-   * If `shared` is `true` and more `RawServerSocket`s from this isolate or
-   * other isolates are bound to the port, then the incoming connections will be
-   * distributed among all the bound `RawServerSocket`s. Connections can be
-   * distributed over multiple isolates this way.
-   */
+  /// Listens on a given address and port.
+  ///
+  /// When the returned future completes the server socket is bound
+  /// to the given [address] and [port] and has started listening on it.
+  ///
+  /// The [address] can either be a [String] or an
+  /// [InternetAddress]. If [address] is a [String], [bind] will
+  /// perform a [InternetAddress.lookup] and use the first value in the
+  /// list. To listen on the loopback adapter, which will allow only
+  /// incoming connections from the local host, use the value
+  /// [InternetAddress.loopbackIPv4] or
+  /// [InternetAddress.loopbackIPv6]. To allow for incoming
+  /// connection from the network use either one of the values
+  /// [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
+  /// bind to all interfaces or the IP address of a specific interface.
+  ///
+  /// If an IP version 6 (IPv6) address is used, both IP version 6
+  /// (IPv6) and version 4 (IPv4) connections will be accepted. To
+  /// restrict this to version 6 (IPv6) only, use [v6Only] to set
+  /// version 6 only.
+  ///
+  /// If [port] has the value `0` an ephemeral port will
+  /// be chosen by the system. The actual port used can be retrieved
+  /// using the `port` getter.
+  ///
+  /// The optional argument [backlog] can be used to specify the listen
+  /// backlog for the underlying OS listen setup. If [backlog] has the
+  /// value of `0` (the default) a reasonable value will be chosen by
+  /// the system.
+  ///
+  /// The optional argument [shared] specifies whether additional RawServerSocket
+  /// objects can bind to the same combination of [address], [port] and [v6Only].
+  /// If [shared] is `true` and more [RawServerSocket]s from this isolate or
+  /// other isolates are bound to the port, then the incoming connections will be
+  /// distributed among all the bound [RawServerSocket]s. Connections can be
+  /// distributed over multiple isolates this way.
   external static Future<RawServerSocket> bind(address, int port,
       {int backlog = 0, bool v6Only = false, bool shared = false});
 
-  /**
-   * Returns the port used by this socket.
-   */
+  /// The port used by this socket.
   int get port;
 
-  /**
-   * Returns the address used by this socket.
-   */
+  /// The address used by this socket.
   InternetAddress get address;
 
-  /**
-   * Closes the socket. The returned future completes when the socket
-   * is fully closed and is no longer bound.
-   */
+  /// Closes the socket.
+  ///
+  /// The returned future completes when the socket
+  /// is fully closed and is no longer bound.
   Future<RawServerSocket> close();
 }
 
-/**
- * A [ServerSocket] represents a listening socket, and provides a
- * stream of [Socket] objects, one for each connection made to the
- * listening socket.
- *
- * See [Socket] for more info.
- */
+/// A listening socket.
+///
+/// A [ServerSocket] provides a stream of [Socket] objects,
+/// one for each connection made to the listening socket.
+///
+/// See [Socket] for more info.
 abstract class ServerSocket implements Stream<Socket> {
-  /**
-   * Returns a future for a [:ServerSocket:]. When the future
-   * completes the server socket is bound to the given [address] and
-   * [port] and has started listening on it.
-   *
-   * The [address] can either be a [String] or an
-   * [InternetAddress]. If [address] is a [String], [bind] will
-   * perform a [InternetAddress.lookup] and use the first value in the
-   * list. To listen on the loopback adapter, which will allow only
-   * incoming connections from the local host, use the value
-   * [InternetAddress.loopbackIPv4] or
-   * [InternetAddress.loopbackIPv6]. To allow for incoming
-   * connection from the network use either one of the values
-   * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
-   * bind to all interfaces or the IP address of a specific interface.
-   *
-   * If an IP version 6 (IPv6) address is used, both IP version 6
-   * (IPv6) and version 4 (IPv4) connections will be accepted. To
-   * restrict this to version 6 (IPv6) only, use [v6Only] to set
-   * version 6 only.
-   *
-   * If [port] has the value [:0:] an ephemeral port will be chosen by
-   * the system. The actual port used can be retrieved using the
-   * [port] getter.
-   *
-   * The optional argument [backlog] can be used to specify the listen
-   * backlog for the underlying OS listen setup. If [backlog] has the
-   * value of [:0:] (the default) a reasonable value will be chosen by
-   * the system.
-   *
-   * The optional argument [shared] specifies whether additional ServerSocket
-   * objects can bind to the same combination of `address`, `port` and `v6Only`.
-   * If `shared` is `true` and more `ServerSocket`s from this isolate or other
-   * isolates are bound to the port, then the incoming connections will be
-   * distributed among all the bound `ServerSocket`s. Connections can be
-   * distributed over multiple isolates this way.
-   */
+  /// Listens on a given address and port.
+  ///
+  /// When the returned future completes the server socket is bound
+  /// to the given [address] and [port] and has started listening on it.
+  ///
+  /// The [address] can either be a [String] or an
+  /// [InternetAddress]. If [address] is a [String], [bind] will
+  /// perform a [InternetAddress.lookup] and use the first value in the
+  /// list. To listen on the loopback adapter, which will allow only
+  /// incoming connections from the local host, use the value
+  /// [InternetAddress.loopbackIPv4] or
+  /// [InternetAddress.loopbackIPv6]. To allow for incoming
+  /// connection from the network use either one of the values
+  /// [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
+  /// bind to all interfaces or the IP address of a specific interface.
+  ///
+  /// If an IP version 6 (IPv6) address is used, both IP version 6
+  /// (IPv6) and version 4 (IPv4) connections will be accepted. To
+  /// restrict this to version 6 (IPv6) only, use [v6Only] to set
+  /// version 6 only.
+  ///
+  /// If [port] has the value `0` an ephemeral port will be chosen by
+  /// the system. The actual port used can be retrieved using the
+  /// [port] getter.
+  ///
+  /// The optional argument [backlog] can be used to specify the listen
+  /// backlog for the underlying OS listen setup. If [backlog] has the
+  /// value of `0` (the default) a reasonable value will be chosen by
+  /// the system.
+  ///
+  /// The optional argument [shared] specifies whether additional ServerSocket
+  /// objects can bind to the same combination of [address], [port] [and] [v6Only].
+  /// If [shared] is `true` and more [ServerSockets] from this isolate or other
+  /// isolates are bound to the port, then the incoming connections will be
+  /// distributed among all the bound [ServerSockets]. Connections can be
+  /// distributed over multiple isolates this way.
   static Future<ServerSocket> bind(address, int port,
-      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+      {int backlog = 0, bool v6Only = false, bool shared = false}) {
     final IOOverrides? overrides = IOOverrides.current;
     if (overrides == null) {
       return ServerSocket._bind(address, port,
@@ -393,27 +329,21 @@
   external static Future<ServerSocket> _bind(address, int port,
       {int backlog = 0, bool v6Only = false, bool shared = false});
 
-  /**
-   * Returns the port used by this socket.
-   */
+  /// The port used by this socket.
   int get port;
 
-  /**
-   * Returns the address used by this socket.
-   */
+  /// The address used by this socket.
   InternetAddress get address;
 
-  /**
-   * Closes the socket. The returned future completes when the socket
-   * is fully closed and is no longer bound.
-   */
+  /// Closes the socket.
+  ///
+  /// The returned future completes when the socket
+  /// is fully closed and is no longer bound.
   Future<ServerSocket> close();
 }
 
-/**
- * The [SocketDirection] is used as a parameter to [Socket.close] and
- * [RawSocket.close] to close a socket in the specified direction(s).
- */
+/// The [SocketDirection] is used as a parameter to [Socket.close] and
+/// [RawSocket.close] to close a socket in the specified direction(s).
 class SocketDirection {
   static const SocketDirection receive = const SocketDirection._(0);
   static const SocketDirection send = const SocketDirection._(1);
@@ -431,19 +361,17 @@
   const SocketDirection._(this._value);
 }
 
-/**
- * The [SocketOption] is used as a parameter to [Socket.setOption] and
- * [RawSocket.setOption] to set customize the behaviour of the underlying
- * socket.
- */
+/// An option for a socket which is configured using [Socket.setOption].
+///
+/// The [SocketOption] is used as a parameter to [Socket.setOption] and
+/// [RawSocket.setOption] to customize the behaviour of the underlying
+/// socket.
 class SocketOption {
-  /**
-   * Enable or disable no-delay on the socket. If tcpNoDelay is enabled, the
-   * socket will not buffer data internally, but instead write each data chunk
-   * as an individual TCP packet.
-   *
-   * tcpNoDelay is disabled by default.
-   */
+  /// Enable or disable no-delay on the socket. If tcpNoDelay is enabled, the
+  /// socket will not buffer data internally, but instead write each data chunk
+  /// as an individual TCP packet.
+  ///
+  /// tcpNoDelay is disabled by default.
   static const SocketOption tcpNoDelay = const SocketOption._(0);
   @Deprecated("Use tcpNoDelay instead")
   static const SocketOption TCP_NODELAY = tcpNoDelay;
@@ -470,7 +398,7 @@
 }
 
 /// The [RawSocketOption] is used as a parameter to [Socket.setRawOption] and
-/// [RawSocket.setRawOption] to set customize the behaviour of the underlying
+/// [RawSocket.setRawOption] to customize the behaviour of the underlying
 /// socket.
 ///
 /// It allows for fine grained control of the socket options, and its values
@@ -478,10 +406,11 @@
 /// getsockopt.
 @Since("2.2")
 class RawSocketOption {
-  /// Creates a RawSocketOption for getRawOption andSetRawOption.
+  /// Creates a [RawSocketOption] for [RawSocket.getRawOption]
+  /// and [RawSocket.setRawOption].
   ///
-  /// The level and option arguments correspond to level and optname arguments
-  /// on the getsockopt and setsockopt native calls.
+  /// The [level] and [option] arguments correspond to `level` and `optname` arguments
+  /// on the `getsockopt()` and `setsockopt()` native calls.
   ///
   /// The value argument and its length correspond to the optval and length
   /// arguments on the native call.
@@ -493,7 +422,7 @@
   /// the option.
   const RawSocketOption(this.level, this.option, this.value);
 
-  /// Convenience constructor for creating an int based RawSocketOption.
+  /// Convenience constructor for creating an integer based [RawSocketOption].
   factory RawSocketOption.fromInt(int level, int option, int value) {
     final Uint8List list = Uint8List(4);
     final buffer = ByteData.view(list.buffer, list.offsetInBytes);
@@ -501,7 +430,7 @@
     return RawSocketOption(level, option, list);
   }
 
-  /// Convenience constructor for creating a bool based RawSocketOption.
+  /// Convenience constructor for creating a boolean based [RawSocketOption].
   factory RawSocketOption.fromBool(int level, int option, bool value) =>
       RawSocketOption.fromInt(level, option, value ? 1 : 0);
 
@@ -515,54 +444,53 @@
   ///   * [RawSocketOption.levelUdp]
   final int level;
 
-  /// The option to set or get.
+  /// The numeric ID of the option to set or get.
   final int option;
 
   /// The raw data to set, or the array to write the current option value into.
   ///
   /// This list must be the correct length for the expected option. For most
-  /// options that take int or bool values, the length should be 4. For options
+  /// options that take [int] or [bool] values, the length should be 4. For options
   /// that expect a struct (such as an in_addr_t), the length should be the
   /// correct length for that struct.
   final Uint8List value;
 
-  /// Socket level option for SOL_SOCKET.
+  /// Socket level option for `SOL_SOCKET`.
   static int get levelSocket =>
       _getOptionValue(_RawSocketOptions.SOL_SOCKET.index);
 
-  /// Socket level option for IPPROTO_IP.
+  /// Socket level option for `IPPROTO_IP`.
   static int get levelIPv4 =>
       _getOptionValue(_RawSocketOptions.IPPROTO_IP.index);
 
-  /// Socket option for IP_MULTICAST_IF.
+  /// Socket option for `IP_MULTICAST_IF`.
   static int get IPv4MulticastInterface =>
       _getOptionValue(_RawSocketOptions.IP_MULTICAST_IF.index);
 
-  /// Socket level option for IPPROTO_IPV6.
+  /// Socket level option for `IPPROTO_IPV6`.
   static int get levelIPv6 =>
       _getOptionValue(_RawSocketOptions.IPPROTO_IPV6.index);
 
-  /// Socket option for IPV6_MULTICAST_IF.
+  /// Socket option for `IPV6_MULTICAST_IF`.
   static int get IPv6MulticastInterface =>
       _getOptionValue(_RawSocketOptions.IPV6_MULTICAST_IF.index);
 
-  /// Socket level option for IPPROTO_TCP.
+  /// Socket level option for `IPPROTO_TCP`.
   static int get levelTcp =>
       _getOptionValue(_RawSocketOptions.IPPROTO_TCP.index);
 
-  /// Socket level option for IPPROTO_UDP.
+  /// Socket level option for `IPPROTO_UDP`.
   static int get levelUdp =>
       _getOptionValue(_RawSocketOptions.IPPROTO_UDP.index);
 
   external static int _getOptionValue(int key);
 }
 
-/**
- * Events for the [RawSocket].
- *
- * These event objects are by the [Stream] behavior of [RawSocket] (for example
- * [RawSocket.listen], [RawSocket.forEach]) when the socket's state change.
- */
+/// Events for the [RawSocket].
+///
+/// These event objects are used by the [Stream] behavior of [RawSocket]
+/// (for example [RawSocket.listen], [RawSocket.forEach])
+/// when the socket's state change.
 class RawSocketEvent {
   /// An event indicates the socket is ready to be read.
   static const RawSocketEvent read = const RawSocketEvent._(0);
@@ -598,13 +526,15 @@
   }
 }
 
+/// A cancelable connection attempt.
+///
 /// Returned by the `startConnect` methods on client-side socket types `S`,
 /// `ConnectionTask<S>` allows cancelling an attempt to connect to a host.
 class ConnectionTask<S> {
   /// A `Future` that completes with value that `S.connect()` would return
   /// unless [cancel] is called on this [ConnectionTask].
   ///
-  /// If [cancel] is called, the `Future` completes with a [SocketException]
+  /// If [cancel] is called, the future completes with a [SocketException]
   /// error whose message indicates that the connection attempt was cancelled.
   final Future<S> socket;
   final void Function() _onCancel;
@@ -631,46 +561,39 @@
 /// The [Stream] interface of this class provides event notification about when
 /// a certain change has happened, for example when data has become available
 /// ([RawSocketEvent.read]) or when the remote end has stopped listening
-/// ([RawSocketEvent.close]).
+/// ([RawSocketEvent.closed]).
 abstract class RawSocket implements Stream<RawSocketEvent> {
-  /**
-   * Set or get, if the [RawSocket] should listen for [RawSocketEvent.read]
-   * events. Default is [:true:].
-   */
-  bool get readEventsEnabled;
-  void set readEventsEnabled(bool value);
+  /// Set or get, if the [RawSocket] should listen for [RawSocketEvent.read]
+  /// events. Default is `true`.
+  abstract bool readEventsEnabled;
 
-  /**
-   * Set or get, if the [RawSocket] should listen for [RawSocketEvent.write]
-   * events. Default is [:true:].
-   * This is a one-shot listener, and writeEventsEnabled must be set
-   * to true again to receive another write event.
-   */
-  bool get writeEventsEnabled;
-  void set writeEventsEnabled(bool value);
+  /// Set or get, if the [RawSocket] should listen for [RawSocketEvent.write]
+  /// events. Default is `true`.
+  /// This is a one-shot listener, and writeEventsEnabled must be set
+  /// to true again to receive another write event.
+  abstract bool writeEventsEnabled;
 
-  /**
-   * Creates a new socket connection to the host and port and returns a [Future]
-   * that will complete with either a [RawSocket] once connected or an error
-   * if the host-lookup or connection failed.
-   *
-   * [host] can either be a [String] or an [InternetAddress]. If [host] is a
-   * [String], [connect] will perform a [InternetAddress.lookup] and try
-   * all returned [InternetAddress]es, until connected. Unless a
-   * connection was established, the error from the first failing connection is
-   * returned.
-   *
-   * The argument [sourceAddress] can be used to specify the local
-   * address to bind when making the connection. `sourceAddress` can either
-   * be a `String` or an `InternetAddress`. If a `String` is passed it must
-   * hold a numeric IP address.
-   *
-   * The argument [timeout] is used to specify the maximum allowed time to wait
-   * for a connection to be established. If [timeout] is longer than the system
-   * level timeout duration, a timeout may occur sooner than specified in
-   * [timeout]. On timeout, a [SocketException] is thrown and all ongoing
-   * connection attempts to [host] are cancelled.
-   */
+  /// Creates a new socket connection to the host and port.
+  ///
+  /// Returns a [Future] that will complete with either a [RawSocket]
+  /// once connected, or an error if the host-lookup or connection failed.
+  ///
+  /// The [host] can either be a [String] or an [InternetAddress]. If [host] is a
+  /// [String], [connect] will perform a [InternetAddress.lookup] and try
+  /// all returned [InternetAddress]es, until connected. Unless a
+  /// connection was established, the error from the first failing connection is
+  /// returned.
+  ///
+  /// The argument [sourceAddress] can be used to specify the local
+  /// address to bind when making the connection. The [sourceAddress] can either
+  /// be a [String] or an [InternetAddress]. If a [String] is passed it must
+  /// hold a numeric IP address.
+  ///
+  /// The argument [timeout] is used to specify the maximum allowed time to wait
+  /// for a connection to be established. If [timeout] is longer than the system
+  /// level timeout duration, a timeout may occur sooner than specified in
+  /// [timeout]. On timeout, a [SocketException] is thrown and all ongoing
+  /// connection attempts to [host] are cancelled.
   external static Future<RawSocket> connect(host, int port,
       {sourceAddress, Duration? timeout});
 
@@ -680,103 +603,89 @@
   external static Future<ConnectionTask<RawSocket>> startConnect(host, int port,
       {sourceAddress});
 
-  /**
-   * Returns the number of received and non-read bytes in the socket that
-   * can be read.
-   */
+  /// The number of received and non-read bytes in the socket that can be read.
   int available();
 
-  /**
-   * Read up to [len] bytes from the socket. This function is
-   * non-blocking and will only return data if data is available. The
-   * number of bytes read can be less then [len] if fewer bytes are
-   * available for immediate reading. If no data is available [:null:]
-   * is returned.
-   */
+  /// Read up to [len] bytes from the socket.
+  ///
+  /// This function is non-blocking and will only return data
+  /// if data is available.
+  /// The number of bytes read can be less then [len] if fewer bytes are
+  /// available for immediate reading. If no data is available `null`
+  /// is returned.
   Uint8List? read([int? len]);
 
-  /**
-   * Writes up to [count] bytes of the buffer from [offset] buffer offset to
-   * the socket. The number of successfully written bytes is returned. This
-   * function is non-blocking and will only write data if buffer space is
-   * available in the socket.
-   *
-   * The default value for [offset] is 0, and the default value for [count] is
-   * [:buffer.length - offset:].
-   */
+  /// Writes up to [count] bytes of the buffer from [offset] buffer offset to
+  /// the socket.
+  ///
+  /// The number of successfully written bytes is returned.
+  /// This function is non-blocking and will only write data
+  /// if buffer space is available in the socket.
+  ///
+  /// The default value for [offset] is 0, and the default value for [count] is
+  /// `buffer.length - offset`.
   int write(List<int> buffer, [int offset = 0, int? count]);
 
-  /**
-   * Returns the port used by this socket.
-   *
-   * Throws a [SocketException] if the socket is closed.
-   */
+  /// The port used by this socket.
+  ///
+  /// Throws a [SocketException] if the socket is closed.
   int get port;
 
-  /**
-   * Returns the remote port connected to by this socket.
-   *
-   * Throws a [SocketException] if the socket is closed.
-   */
+  /// The remote port connected to by this socket.
+  ///
+  /// Throws a [SocketException] if the socket is closed.
   int get remotePort;
 
-  /**
-   * Returns the [InternetAddress] used to connect this socket.
-   *
-   * Throws a [SocketException] if the socket is closed.
-   */
+  /// The [InternetAddress] used to connect this socket.
+  ///
+  /// Throws a [SocketException] if the socket is closed.
   InternetAddress get address;
 
-  /**
-   * Returns the remote [InternetAddress] connected to by this socket.
-   *
-   * Throws a [SocketException] if the socket is closed.
-   */
+  /// The remote [InternetAddress] connected to by this socket.
+  ///
+  /// Throws a [SocketException] if the socket is closed.
   InternetAddress get remoteAddress;
 
-  /**
-   * Closes the socket. Returns a Future that completes with [this] when the
-   * underlying connection is completely destroyed.
-   *
-   * Calling [close] will never throw an exception
-   * and calling it several times is supported. Calling [close] can result in
-   * a [RawSocketEvent.readClosed] event.
-   */
+  /// Closes the socket.
+  ///
+  /// Returns a future that completes with this socket when the
+  /// underlying connection is completely destroyed.
+  ///
+  /// Calling [close] will never throw an exception
+  /// and calling it several times is supported. Calling [close] can result in
+  /// a [RawSocketEvent.readClosed] event.
   Future<RawSocket> close();
 
-  /**
-   * Shutdown the socket in the [direction]. Calling [shutdown] will never
-   * throw an exception and calling it several times is supported. Calling
-   * shutdown with either [SocketDirection.both] or [SocketDirection.receive]
-   * can result in a [RawSocketEvent.readClosed] event.
-   */
+  /// Shuts down the socket in the [direction].
+  ///
+  /// Calling [shutdown] will never throw an exception
+  /// and calling it several times is supported. Calling
+  /// shutdown with either [SocketDirection.both] or [SocketDirection.receive]
+  /// can result in a [RawSocketEvent.readClosed] event.
   void shutdown(SocketDirection direction);
 
-  /**
-   * Use [setOption] to customize the [RawSocket]. See [SocketOption] for
-   * available options.
-   *
-   * Returns [:true:] if the option was set successfully, false otherwise.
-   */
+  /// Customize the [RawSocket].
+  ///
+  /// See [SocketOption] for available options.
+  ///
+  /// Returns `true` if the option was set successfully, `false` otherwise.
   bool setOption(SocketOption option, bool enabled);
 
-  /**
-   * Use [getRawOption] to get low level information about the [RawSocket]. See
-   * [RawSocketOption] for available options.
-   *
-   * Returns the [RawSocketOption.value] on success.
-   *
-   * Throws an [OSError] on failure.
-   */
+  /// Reads low level information about the [RawSocket].
+  ///
+  /// See [RawSocketOption] for available options.
+  ///
+  /// Returns the [RawSocketOption.value] on success.
+  ///
+  /// Throws an [OSError] on failure.
   @Since("2.2")
   Uint8List getRawOption(RawSocketOption option);
 
-  /**
-   * Use [setRawOption] to customize the [RawSocket]. See [RawSocketOption] for
-   * available options.
-   *
-   * Throws an [OSError] on failure.
-   */
+  /// Customizes the [RawSocket].
+  ///
+  /// See [RawSocketOption] for available options.
+  ///
+  /// Throws an [OSError] on failure.
   @Since("2.2")
   void setRawOption(RawSocketOption option);
 }
@@ -788,28 +697,26 @@
 /// by the [Stream] interface of this class, and can be sent to the remote
 /// socket through the [IOSink] interface of this class.
 abstract class Socket implements Stream<Uint8List>, IOSink {
-  /**
-   * Creates a new socket connection to the host and port and returns a [Future]
-   * that will complete with either a [Socket] once connected or an error
-   * if the host-lookup or connection failed.
-   *
-   * [host] can either be a [String] or an [InternetAddress]. If [host] is a
-   * [String], [connect] will perform a [InternetAddress.lookup] and try
-   * all returned [InternetAddress]es, until connected. Unless a
-   * connection was established, the error from the first failing connection is
-   * returned.
-   *
-   * The argument [sourceAddress] can be used to specify the local
-   * address to bind when making the connection. `sourceAddress` can either
-   * be a `String` or an `InternetAddress`. If a `String` is passed it must
-   * hold a numeric IP address.
-   *
-   * The argument [timeout] is used to specify the maximum allowed time to wait
-   * for a connection to be established. If [timeout] is longer than the system
-   * level timeout duration, a timeout may occur sooner than specified in
-   * [timeout]. On timeout, a [SocketException] is thrown and all ongoing
-   * connection attempts to [host] are cancelled.
-   */
+  /// Creates a new socket connection to the host and port and returns a [Future]
+  /// that will complete with either a [Socket] once connected or an error
+  /// if the host-lookup or connection failed.
+  ///
+  /// [host] can either be a [String] or an [InternetAddress]. If [host] is a
+  /// [String], [connect] will perform a [InternetAddress.lookup] and try
+  /// all returned [InternetAddress]es, until connected. Unless a
+  /// connection was established, the error from the first failing connection is
+  /// returned.
+  ///
+  /// The argument [sourceAddress] can be used to specify the local
+  /// address to bind when making the connection. The [sourceAddress] can either
+  /// be a [String] or an [InternetAddress]. If a [String] is passed it must
+  /// hold a numeric IP address.
+  ///
+  /// The argument [timeout] is used to specify the maximum allowed time to wait
+  /// for a connection to be established. If [timeout] is longer than the system
+  /// level timeout duration, a timeout may occur sooner than specified in
+  /// [timeout]. On timeout, a [SocketException] is thrown and all ongoing
+  /// connection attempts to [host] are cancelled.
   static Future<Socket> connect(host, int port,
       {sourceAddress, Duration? timeout}) {
     final IOOverrides? overrides = IOOverrides.current;
@@ -840,75 +747,63 @@
   external static Future<ConnectionTask<Socket>> _startConnect(host, int port,
       {sourceAddress});
 
-  /**
-   * Destroy the socket in both directions. Calling [destroy] will make the
-   * send a close event on the stream and will no longer react on data being
-   * piped to it.
-   *
-   * Call [close](inherited from [IOSink]) to only close the [Socket]
-   * for sending data.
-   */
+  /// Destroys the socket in both directions.
+  ///
+  /// Calling [destroy] will make the send a close event on the stream
+  /// and will no longer react on data being piped to it.
+  ///
+  /// Call [close] (inherited from [IOSink]) to only close the [Socket]
+  /// for sending data.
   void destroy();
 
-  /**
-   * Use [setOption] to customize the [RawSocket]. See [SocketOption] for
-   * available options.
-   *
-   * Returns [:true:] if the option was set successfully, false otherwise.
-   *
-   * Throws a [SocketException] if the socket has been destroyed or upgraded to
-   * a secure socket.
-   */
+  /// Customizes the [RawSocket].
+  ///
+  /// See [SocketOption] for available options.
+  ///
+  /// Returns `true` if the option was set successfully, false otherwise.
+  ///
+  /// Throws a [SocketException] if the socket has been destroyed or upgraded to
+  /// a secure socket.
   bool setOption(SocketOption option, bool enabled);
 
-  /**
-   * Use [getRawOption] to get low level information about the [RawSocket]. See
-   * [RawSocketOption] for available options.
-   *
-   * Returns the [RawSocketOption.value] on success.
-   *
-   * Throws an [OSError] on failure and a [SocketException] if the socket has
-   * been destroyed or upgraded to a secure socket.
-   */
+  /// Reads low level information about the [RawSocket].
+  ///
+  /// See [RawSocketOption] for available options.
+  ///
+  /// Returns the [RawSocketOption.value] on success.
+  ///
+  /// Throws an [OSError] on failure and a [SocketException] if the socket has
+  /// been destroyed or upgraded to a secure socket.
   Uint8List getRawOption(RawSocketOption option);
 
-  /**
-   * Use [setRawOption] to customize the [RawSocket]. See [RawSocketOption] for
-   * available options.
-   *
-   * Throws an [OSError] on failure and a [SocketException] if the socket has
-   * been destroyed or upgraded to a secure socket.
-   */
+  /// Customizes the [RawSocket].
+  ///
+  /// See [RawSocketOption] for available options.
+  ///
+  /// Throws an [OSError] on failure and a [SocketException] if the socket has
+  /// been destroyed or upgraded to a secure socket.
   void setRawOption(RawSocketOption option);
 
-  /**
-   * The port used by this socket.
-   *
-   * Throws a [SocketException] if the socket is closed.
-   * The port is 0 if the socket is a Unix domain socket.
-   */
+  /// The port used by this socket.
+  ///
+  /// Throws a [SocketException] if the socket is closed.
+  /// The port is 0 if the socket is a Unix domain socket.
   int get port;
 
-  /**
-   * The remote port connected to by this socket.
-   *
-   * Throws a [SocketException] if the socket is closed.
-   * The port is 0 if the socket is a Unix domain socket.
-   */
+  /// The remote port connected to by this socket.
+  ///
+  /// Throws a [SocketException] if the socket is closed.
+  /// The port is 0 if the socket is a Unix domain socket.
   int get remotePort;
 
-  /**
-   * The [InternetAddress] used to connect this socket.
-   *
-   * Throws a [SocketException] if the socket is closed.
-   */
+  /// The [InternetAddress] used to connect this socket.
+  ///
+  /// Throws a [SocketException] if the socket is closed.
   InternetAddress get address;
 
-  /**
-   * The remote [InternetAddress] connected to by this socket.
-   *
-   * Throws a [SocketException] if the socket is closed.
-   */
+  /// The remote [InternetAddress] connected to by this socket.
+  ///
+  /// Throws a [SocketException] if the socket is closed.
   InternetAddress get remoteAddress;
 
   Future close();
@@ -916,7 +811,7 @@
   Future get done;
 }
 
-/// A data packet which is received by a [RawDatagramSocket].
+/// A data packet received by a [RawDatagramSocket].
 class Datagram {
   /// The actual bytes of the message.
   Uint8List data;
@@ -930,167 +825,135 @@
   Datagram(this.data, this.address, this.port);
 }
 
-/**
- * A [RawDatagramSocket] is an unbuffered interface to a UDP socket.
- *
- * The raw datagram socket delivers the datagrams in the same chunks as the
- * underlying operating system. It's a [Stream] of [RawSocketEvent]s.
- *
- * Note that the event [RawSocketEvent.readClosed] will never be
- * received as an UDP socket cannot be closed by a remote peer.
- *
- * It is not the same as a
- * [POSIX raw socket](http://man7.org/linux/man-pages/man7/raw.7.html).
- */
+/// An unbuffered interface to a UDP socket.
+///
+/// The raw datagram socket delivers the datagrams in the same chunks as the
+/// underlying operating system. It's a [Stream] of [RawSocketEvent]s.
+///
+/// Note that the event [RawSocketEvent.readClosed] will never be
+/// received as an UDP socket cannot be closed by a remote peer.
+///
+/// It is not the same as a
+/// [POSIX raw socket](http://man7.org/linux/man-pages/man7/raw.7.html).
 abstract class RawDatagramSocket extends Stream<RawSocketEvent> {
-  /**
-   * Set or get, if the [RawDatagramSocket] should listen for
-   * [RawSocketEvent.read] events. Default is [:true:].
-   */
-  bool get readEventsEnabled;
-  void set readEventsEnabled(bool value);
+  /// Whether the [RawDatagramSocket] should listen for
+  /// [RawSocketEvent.read] events.
+  ///
+  /// Default is `true`.
+  abstract bool readEventsEnabled;
 
-  /**
-   * Set or get, if the [RawDatagramSocket] should listen for
-   * [RawSocketEvent.write] events. Default is [:true:].  This is a
-   * one-shot listener, and writeEventsEnabled must be set to true
-   * again to receive another write event.
-   */
-  bool get writeEventsEnabled;
-  void set writeEventsEnabled(bool value);
+  /// Whether the [RawDatagramSocket] should listen for
+  /// [RawSocketEvent.write] events.
+  ///
+  /// Default is `true`.
+  /// This is a one-shot listener, and [writeEventsEnabled] must be set to true
+  /// again to receive another write event.
+  abstract bool writeEventsEnabled;
 
-  /**
-   * Set or get, whether multicast traffic is looped back to the host.
-   *
-   * By default multicast loopback is enabled.
-   */
-  bool get multicastLoopback;
-  void set multicastLoopback(bool value);
+  /// Whether multicast traffic is looped back to the host.
+  ///
+  /// By default multicast loopback is enabled.
+  abstract bool multicastLoopback;
 
-  /**
-   * Set or get, the maximum network hops for multicast packages
-   * originating from this socket.
-   *
-   * For IPv4 this is referred to as TTL (time to live).
-   *
-   * By default this value is 1 causing multicast traffic to stay on
-   * the local network.
-   */
-  int get multicastHops;
-  void set multicastHops(int value);
+  /// The maximum network hops for multicast packages
+  /// originating from this socket.
+  ///
+  /// For IPv4 this is referred to as TTL (time to live).
+  ///
+  /// By default this value is 1 causing multicast traffic to stay on
+  /// the local network.
+  abstract int multicastHops;
 
-  /**
-   * Set or get, the network interface used for outgoing multicast packages.
-   *
-   * A value of `null`indicate that the system chooses the network
-   * interface to use.
-   *
-   * By default this value is `null`
-   */
+  /// The network interface used for outgoing multicast packages.
+  ///
+  /// A value of `null` indicate that the system chooses the network
+  /// interface to use.
+  ///
+  /// By default this value is `null`
   @Deprecated("This property is not implemented. Use getRawOption and "
       "setRawOption instead.")
   NetworkInterface? multicastInterface;
 
-  /**
-   * Set or get, whether IPv4 broadcast is enabled.
-   *
-   * IPv4 broadcast needs to be enabled by the sender for sending IPv4
-   * broadcast packages. By default IPv4 broadcast is disabled.
-   *
-   * For IPv6 there is no general broadcast mechanism. Use multicast
-   * instead.
-   */
-  bool get broadcastEnabled;
-  void set broadcastEnabled(bool value);
+  /// Whether IPv4 broadcast is enabled.
+  ///
+  /// IPv4 broadcast needs to be enabled by the sender for sending IPv4
+  /// broadcast packages. By default IPv4 broadcast is disabled.
+  ///
+  /// For IPv6 there is no general broadcast mechanism. Use multicast
+  /// instead.
+  abstract bool broadcastEnabled;
 
-  /**
-   * Binds a socket to the given [host] and the [port].
-   *
-   * When the socket is bound and has started listening on [port], the returned
-   * future completes with the [RawDatagramSocket] of the bound socket.
-   *
-   * The [host] can either be a [String] or an [InternetAddress]. If [host] is a
-   * [String], [bind] will perform a [InternetAddress.lookup] and use the first
-   * value in the list. To listen on the loopback interface, which will allow
-   * only incoming connections from the local host, use the value
-   * [InternetAddress.loopbackIPv4] or [InternetAddress.loopbackIPv6].
-   * To allow for incoming connection from any network use either one of
-   * the values [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
-   * bind to all interfaces, or use the IP address of a specific interface.
-   *
-   * The [reuseAddress] should be set for all listeners that bind to the same
-   * address. Otherwise, it will fail with a [SocketException].
-   *
-   * The [reusePort] specifies whether the port can be reused.
-   *
-   * The [ttl] sets `time to live` of a datagram sent on the socket.
-   */
+  /// Binds a socket to the given [host] and [port].
+  ///
+  /// When the socket is bound and has started listening on [port], the returned
+  /// future completes with the [RawDatagramSocket] of the bound socket.
+  ///
+  /// The [host] can either be a [String] or an [InternetAddress]. If [host] is a
+  /// [String], [bind] will perform a [InternetAddress.lookup] and use the first
+  /// value in the list. To listen on the loopback interface, which will allow
+  /// only incoming connections from the local host, use the value
+  /// [InternetAddress.loopbackIPv4] or [InternetAddress.loopbackIPv6].
+  /// To allow for incoming connection from any network use either one of
+  /// the values [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
+  /// bind to all interfaces, or use the IP address of a specific interface.
+  ///
+  /// The [reuseAddress] should be set for all listeners that bind to the same
+  /// address. Otherwise, it will fail with a [SocketException].
+  ///
+  /// The [reusePort] specifies whether the port can be reused.
+  ///
+  /// The [ttl] sets `time to live` of a datagram sent on the socket.
   external static Future<RawDatagramSocket> bind(host, int port,
       {bool reuseAddress = true, bool reusePort = false, int ttl = 1});
 
-  /**
-   * Returns the port used by this socket.
-   */
+  /// The port used by this socket.
   int get port;
 
-  /**
-   * Returns the address used by this socket.
-   */
+  /// The address used by this socket.
   InternetAddress get address;
 
-  /**
-   * Close the datagram socket.
-   */
+  /// Closes the datagram socket.
   void close();
 
-  /**
-   * Send a datagram.
-   *
-   * Returns the number of bytes written. This will always be either
-   * the size of [buffer] or `0`.
-   */
+  /// Sends a datagram.
+  ///
+  /// Returns the number of bytes written. This will always be either
+  /// the size of [buffer] or `0`.
   int send(List<int> buffer, InternetAddress address, int port);
 
-  /**
-   * Receive a datagram. If there are no datagrams available `null` is
-   * returned.
-   *
-   * The maximum length of the datagram that can be received is 65503 bytes.
-   */
+  /// Receives a datagram.
+  ///
+  /// Returns `null` if there are no datagrams available.
+  ///
+  /// The maximum length of the datagram that can be received is 65503 bytes.
   Datagram? receive();
 
-  /**
-   * Join a multicast group.
-   *
-   * If an error occur when trying to join the multicast group an
-   * exception is thrown.
-   */
+  /// Joins a multicast group.
+  ///
+  /// If an error occur when trying to join the multicast group, an
+  /// exception is thrown.
   void joinMulticast(InternetAddress group, [NetworkInterface? interface]);
 
-  /**
-   * Leave a multicast group.
-   *
-   * If an error occur when trying to join the multicase group an
-   * exception is thrown.
-   */
+  /// Leaves a multicast group.
+  ///
+  /// If an error occur when trying to join the multicase group, an
+  /// exception is thrown.
   void leaveMulticast(InternetAddress group, [NetworkInterface? interface]);
 
-  /**
-   * Use [getRawOption] to get low level information about the [RawSocket]. See
-   * [RawSocketOption] for available options.
-   *
-   * Returns [RawSocketOption.value] on success.
-   *
-   * Throws an [OSError] on failure.
-   */
+  /// Reads low level information about the [RawSocket].
+  ///
+  /// See [RawSocketOption] for available options.
+  ///
+  /// Returns [RawSocketOption.value] on success.
+  ///
+  /// Throws an [OSError] on failure.
   Uint8List getRawOption(RawSocketOption option);
 
-  /**
-   * Use [setRawOption] to customize the [RawSocket]. See [RawSocketOption] for
-   * available options.
-   *
-   * Throws an [OSError] on failure.
-   */
+  /// Customizes the [RawSocket].
+  ///
+  /// See [RawSocketOption] for available options.
+  ///
+  /// Throws an [OSError] on failure.
   void setRawOption(RawSocketOption option);
 }
 
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index 9fc8401..137b4e0 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.dart
@@ -24,39 +24,37 @@
   }
 }
 
-/**
- * [Stdin] allows both synchronous and asynchronous reads from the standard
- * input stream.
- *
- * Mixing synchronous and asynchronous reads is undefined.
- */
+/// The standard input stream of the process.
+///
+/// Allows both synchronous and asynchronous reads from the standard
+/// input stream.
+///
+/// Mixing synchronous and asynchronous reads is undefined.
 class Stdin extends _StdStream implements Stream<List<int>> {
   int _fd;
 
   Stdin._(Stream<List<int>> stream, this._fd) : super(stream);
 
-  /**
-   * Read a line from stdin.
-   *
-   * Blocks until a full line is available.
-   *
-   * Lines my be terminated by either `<CR><LF>` or `<LF>`. On Windows in cases
-   * where the [stdioType] of stdin is [StdioType.terminal] the terminator may
-   * also be a single `<CR>`.
-   *
-   * Input bytes are converted to a string by [encoding].
-   * If [encoding] is omitted, it defaults to [systemEncoding].
-   *
-   * If [retainNewlines] is `false`, the returned String will not include the
-   * final line terminator. If `true`, the returned String will include the line
-   * terminator. Default is `false`.
-   *
-   * If end-of-file is reached after any bytes have been read from stdin,
-   * that data is returned without a line terminator.
-   * Returns `null` if no bytes preceded the end of input.
-   */
+  /// Reads a line from stdin.
+  ///
+  /// Blocks until a full line is available.
+  ///
+  /// Lines my be terminated by either `<CR><LF>` or `<LF>`. On Windows,
+  /// in cases where the [stdioType] of stdin is [StdioType.terminal],
+  /// the terminator may also be a single `<CR>`.
+  ///
+  /// Input bytes are converted to a string by [encoding].
+  /// If [encoding] is omitted, it defaults to [systemEncoding].
+  ///
+  /// If [retainNewlines] is `false`, the returned string will not include the
+  /// final line terminator. If `true`, the returned string will include the line
+  /// terminator. Default is `false`.
+  ///
+  /// If end-of-file is reached after any bytes have been read from stdin,
+  /// that data is returned without a line terminator.
+  /// Returns `null` if no bytes preceded the end of input.
   String? readLineSync(
-      {Encoding encoding: systemEncoding, bool retainNewlines: false}) {
+      {Encoding encoding = systemEncoding, bool retainNewlines = false}) {
     const CR = 13;
     const LF = 10;
     final List<int> line = <int>[];
@@ -112,74 +110,57 @@
     return encoding.decode(line);
   }
 
-  /**
-   * Check if echo mode is enabled on [stdin].
-   */
+  /// Whether echo mode is enabled on [stdin].
+  ///
+  /// If disabled, input from to console will not be echoed.
+  ///
+  /// Default depends on the parent process, but is usually enabled.
+  ///
+  /// On Windows this mode can only be enabled if [lineMode] is enabled as well.
   external bool get echoMode;
+  external set echoMode(bool echoMode);
 
-  /**
-   * Enable or disable echo mode on [stdin].
-   *
-   * If disabled, input from to console will not be echoed.
-   *
-   * Default depends on the parent process, but usually enabled.
-   *
-   * On Windows this mode can only be enabled if [lineMode] is enabled as well.
-   */
-  external void set echoMode(bool enabled);
-
-  /**
-   * Check if line mode is enabled on [stdin].
-   */
+  /// Whether line mode is enabled on [stdin].
+  ///
+  /// If enabled, characters are delayed until a newline character is entered.
+  /// If disabled, characters will be available as typed.
+  ///
+  /// Default depends on the parent process, but is usually enabled.
+  ///
+  /// On Windows this mode can only be disabled if [echoMode] is disabled as well.
   external bool get lineMode;
+  external set lineMode(bool lineMode);
 
-  /**
-   * Enable or disable line mode on [stdin].
-   *
-   * If enabled, characters are delayed until a new-line character is entered.
-   * If disabled, characters will be available as typed.
-   *
-   * Default depends on the parent process, but usually enabled.
-   *
-   * On Windows this mode can only be disabled if [echoMode] is disabled as well.
-   */
-  external void set lineMode(bool enabled);
-
-  /**
-    * Whether connected to a terminal that supports ANSI escape sequences.
-    *
-    * Not all terminals are recognized, and not all recognized terminals can
-    * report whether they support ANSI escape sequences, so this value is a
-    * best-effort attempt at detecting the support.
-    *
-    * The actual escape sequence support may differ between terminals,
-    * with some terminals supporting more escape sequences than others,
-    * and some terminals even differing in behavior for the same escape
-    * sequence.
-    *
-    * The ANSI color selection is generally supported.
-    *
-    * Currently, a `TERM` environment variable containing the string `xterm`
-    * will be taken as evidence that ANSI escape sequences are supported.
-    * On Windows, only versions of Windows 10 after v.1511
-    * ("TH2", OS build 10586) will be detected as supporting the output of
-    * ANSI escape sequences, and only versions after v.1607 ("Anniversary
-    * Update", OS build 14393) will be detected as supporting the input of
-    * ANSI escape sequences.
-    */
+  /// Whether connected to a terminal that supports ANSI escape sequences.
+  ///
+  /// Not all terminals are recognized, and not all recognized terminals can
+  /// report whether they support ANSI escape sequences, so this value is a
+  /// best-effort attempt at detecting the support.
+  ///
+  /// The actual escape sequence support may differ between terminals,
+  /// with some terminals supporting more escape sequences than others,
+  /// and some terminals even differing in behavior for the same escape
+  /// sequence.
+  ///
+  /// The ANSI color selection is generally supported.
+  ///
+  /// Currently, a `TERM` environment variable containing the string `xterm`
+  /// will be taken as evidence that ANSI escape sequences are supported.
+  /// On Windows, only versions of Windows 10 after v.1511
+  /// ("TH2", OS build 10586) will be detected as supporting the output of
+  /// ANSI escape sequences, and only versions after v.1607 ("Anniversary
+  /// Update", OS build 14393) will be detected as supporting the input of
+  /// ANSI escape sequences.
   external bool get supportsAnsiEscapes;
 
-  /**
-   * Synchronously read a byte from stdin. This call will block until a byte is
-   * available.
-   *
-   * If at end of file, -1 is returned.
-   */
+  /// Synchronously reads a byte from stdin.
+  ///
+  /// This call will block until a byte is available.
+  ///
+  /// If at end of file, -1 is returned.
   external int readByteSync();
 
-  /**
-   * Returns true if there is a terminal attached to stdin.
-   */
+  /// Whether there is a terminal attached to stdin.
   bool get hasTerminal {
     try {
       return stdioType(this) == StdioType.terminal;
@@ -192,73 +173,63 @@
   }
 }
 
-/**
- * [Stdout] represents the [IOSink] for either `stdout` or `stderr`.
- *
- * It provides a *blocking* `IOSink`, so using this to write will block until
- * the output is written.
- *
- * In some situations this blocking behavior is undesirable as it does not
- * provide the same non-blocking behavior as dart:io in general exposes.
- * Use the property [nonBlocking] to get an `IOSink` which has the non-blocking
- * behavior.
- *
- * This class can also be used to check whether `stdout` or `stderr` is
- * connected to a terminal and query some terminal properties.
- *
- * The [addError] API is inherited from  [StreamSink] and calling it will result
- * in an unhandled asynchronous error unless there is an error handler on
- * [done].
- */
+/// An [IOSink] connected to either the standard out or error of the process.
+///
+/// Provides a *blocking* `IOSink`, so using it to write will block until
+/// the output is written.
+///
+/// In some situations this blocking behavior is undesirable as it does not
+/// provide the same non-blocking behavior that `dart:io` in general exposes.
+/// Use the property [nonBlocking] to get an [IOSink] which has the non-blocking
+/// behavior.
+///
+/// This class can also be used to check whether `stdout` or `stderr` is
+/// connected to a terminal and query some terminal properties.
+///
+/// The [addError] API is inherited from [StreamSink] and calling it will result
+/// in an unhandled asynchronous error unless there is an error handler on
+/// [done].
 class Stdout extends _StdSink implements IOSink {
   final int _fd;
   IOSink? _nonBlocking;
 
   Stdout._(IOSink sink, this._fd) : super(sink);
 
-  /**
-   * Returns true if there is a terminal attached to stdout.
-   */
+  /// Whether there is a terminal attached to stdout.
   bool get hasTerminal => _hasTerminal(_fd);
 
-  /**
-   * Get the number of columns of the terminal.
-   *
-   * If no terminal is attached to stdout, a [StdoutException] is thrown. See
-   * [hasTerminal] for more info.
-   */
+  /// The number of columns of the terminal.
+  ///
+  /// If no terminal is attached to stdout, a [StdoutException] is thrown. See
+  /// [hasTerminal] for more info.
   int get terminalColumns => _terminalColumns(_fd);
 
-  /**
-   * Get the number of lines of the terminal.
-   *
-   * If no terminal is attached to stdout, a [StdoutException] is thrown. See
-   * [hasTerminal] for more info.
-   */
+  /// The number of lines of the terminal.
+  ///
+  /// If no terminal is attached to stdout, a [StdoutException] is thrown. See
+  /// [hasTerminal] for more info.
   int get terminalLines => _terminalLines(_fd);
 
-  /**
-    * Whether connected to a terminal that supports ANSI escape sequences.
-    *
-    * Not all terminals are recognized, and not all recognized terminals can
-    * report whether they support ANSI escape sequences, so this value is a
-    * best-effort attempt at detecting the support.
-    *
-    * The actual escape sequence support may differ between terminals,
-    * with some terminals supporting more escape sequences than others,
-    * and some terminals even differing in behavior for the same escape
-    * sequence.
-    *
-    * The ANSI color selection is generally supported.
-    *
-    * Currently, a `TERM` environment variable containing the string `xterm`
-    * will be taken as evidence that ANSI escape sequences are supported.
-    * On Windows, only versions of Windows 10 after v.1511
-    * ("TH2", OS build 10586) will be detected as supporting the output of
-    * ANSI escape sequences, and only versions after v.1607 ("Anniversary
-    * Update", OS build 14393) will be detected as supporting the input of
-    * ANSI escape sequences.
-    */
+  /// Whether connected to a terminal that supports ANSI escape sequences.
+  ///
+  /// Not all terminals are recognized, and not all recognized terminals can
+  /// report whether they support ANSI escape sequences, so this value is a
+  /// best-effort attempt at detecting the support.
+  ///
+  /// The actual escape sequence support may differ between terminals,
+  /// with some terminals supporting more escape sequences than others,
+  /// and some terminals even differing in behavior for the same escape
+  /// sequence.
+  ///
+  /// The ANSI color selection is generally supported.
+  ///
+  /// Currently, a `TERM` environment variable containing the string `xterm`
+  /// will be taken as evidence that ANSI escape sequences are supported.
+  /// On Windows, only versions of Windows 10 after v.1511
+  /// ("TH2", OS build 10586) will be detected as supporting the output of
+  /// ANSI escape sequences, and only versions after v.1607 ("Anniversary
+  /// Update", OS build 14393) will be detected as supporting the input of
+  /// ANSI escape sequences.
   bool get supportsAnsiEscapes => _supportsAnsiEscapes(_fd);
 
   external bool _hasTerminal(int fd);
@@ -266,16 +237,18 @@
   external int _terminalLines(int fd);
   external static bool _supportsAnsiEscapes(int fd);
 
-  /**
-   * Get a non-blocking `IOSink`.
-   */
+  /// A non-blocking `IOSink` for the same output.
   IOSink get nonBlocking {
     return _nonBlocking ??= new IOSink(new _FileStreamConsumer.fromStdio(_fd));
   }
 }
 
+/// Exception thrown by some operations of [Stdout]
 class StdoutException implements IOException {
+  /// Message describing cause of the exception.
   final String message;
+
+  /// The underlying OS error, if avaialble.
   final OSError? osError;
 
   const StdoutException(this.message, [this.osError]);
@@ -285,8 +258,12 @@
   }
 }
 
+/// Exception thrown by some operations of [Stdin]
 class StdinException implements IOException {
+  /// Message describing cause of the exception.
   final String message;
+
+  /// The underlying OS error, if avaialble.
   final OSError? osError;
 
   const StdinException(this.message, [this.osError]);
@@ -364,7 +341,7 @@
   Future get done => _sink.done;
 }
 
-/// The type of object a standard IO stream is attached to.
+/// The type of object a standard IO stream can be attached to.
 class StdioType {
   static const StdioType terminal = const StdioType._("terminal");
   static const StdioType pipe = const StdioType._("pipe");
@@ -425,7 +402,7 @@
   return _stderr ??= _StdIOUtils._getStdioOutputStream(_stderrFD);
 }
 
-/// For a stream, returns whether it is attached to a file, pipe, terminal, or
+/// Whether a stream is attached to a file, pipe, terminal, or
 /// something else.
 StdioType stdioType(object) {
   if (object is _StdStream) {
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index f31c41e..bf04327 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -56,9 +56,7 @@
     return encoded;
   }
 
-  /**
-   * Starts a chunked conversion.
-   */
+  /// Starts a chunked conversion.
   StringConversionSink startChunkedConversion(Sink<List<int>> sink) {
     return new _WindowsCodePageEncoderSink(sink);
   }
@@ -102,9 +100,7 @@
     return _decodeBytes(input);
   }
 
-  /**
-   * Starts a chunked conversion.
-   */
+  /// Starts a chunked conversion.
   ByteConversionSink startChunkedConversion(Sink<String> sink) {
     return new _WindowsCodePageDecoderSink(sink);
   }
diff --git a/sdk/lib/io/sync_socket.dart b/sdk/lib/io/sync_socket.dart
index 771edfd..e1e47e5 100644
--- a/sdk/lib/io/sync_socket.dart
+++ b/sdk/lib/io/sync_socket.dart
@@ -4,106 +4,83 @@
 
 part of dart.io;
 
-/**
- * A low-level class for communicating synchronously over a TCP socket.
- *
- * Warning: [RawSynchronousSocket] should probably only be used to connect to
- * 'localhost'. The operations below will block the calling thread to wait for
- * a response from the network. The thread can process no other events while
- * waiting for these operations to complete. [RawSynchronousSocket] is not
- * suitable for applications that require high performance or asynchronous I/O
- * such as a server. Instead such applications should use the non-blocking
- * sockets and asynchronous operations in the Socket or RawSocket classes.
- */
+/// A low-level class for communicating synchronously over a TCP socket.
+///
+/// Warning: [RawSynchronousSocket] should probably only be used to connect to
+/// 'localhost'. The operations below will block the calling thread to wait for
+/// a response from the network. The thread can process no other events while
+/// waiting for these operations to complete. [RawSynchronousSocket] is not
+/// suitable for applications that require high performance or asynchronous I/O
+/// such as a server. Instead such applications should use the non-blocking
+/// sockets and asynchronous operations in the [Socket] or [RawSocket] classes.
 abstract class RawSynchronousSocket {
-  /**
-   * Creates a new socket connection and returns a [RawSynchronousSocket].
-   *
-   * [host] can either be a [String] or an [InternetAddress]. If [host] is a
-   * [String], [connectSync] will perform a [InternetAddress.lookup] and try
-   * all returned [InternetAddress]es, until connected. Unless a
-   * connection was established, the error from the first failing connection is
-   * returned.
-   */
+  /// Creates a new socket connection and returns a [RawSynchronousSocket].
+  ///
+  /// The [host] can either be a [String] or an [InternetAddress].
+  /// If [host] is a [String], [connectSync] will perform a
+  /// [InternetAddress.lookup] and try all returned [InternetAddress]es,
+  /// until connected.
+  /// Unless a connection was established,
+  /// the error from the first failing connection is returned.
   external static RawSynchronousSocket connectSync(host, int port);
 
-  /**
-   * Returns the number of received and unread bytes in the socket that can be
-   * read.
-   */
+  /// The number of received and unread bytes in the socket that can be read.
   int available();
 
-  /**
-   * Closes the [RawSynchronousSocket].
-   *
-   * Once [closeSync] has been called, attempting to call [readSync],
-   * [readIntoSync], [writeFromSync], [remoteAddress], and [remotePort] will
-   * cause a [SocketException] to be thrown.
-   */
+  /// Closes the [RawSynchronousSocket].
+  ///
+  /// Once [closeSync] has been called, attempting to call [readSync],
+  /// [readIntoSync], [writeFromSync], [remoteAddress], and [remotePort] will
+  /// cause a [SocketException] to be thrown.
   void closeSync();
 
-  /**
-   * Reads into an existing [List<int>] from the socket into the range:
-   * [[start],[end]).
-   *
-   * Reads into an existing [List<int>] from the socket. If [start] is present,
-   * the bytes will be filled into [buffer] from index [start], otherwise index
-   * 0. If [end] is present, [end] - [start] bytes will be read into [buffer],
-   * otherwise up to [buffer.length]. If [end] == [start], no bytes are read.
-   * Returns the number of bytes read.
-   */
+  /// Reads bytes into an existing [buffer].
+  ///
+  /// Reads bytes and writes then into the the range of [buffer]
+  /// from [start] to [end].
+  /// The [start] must be non-negative and no greater than `buffer.length`.
+  /// If [end] is omitted, it defaults to [buffer.length].
+  /// Otherwise [end] must be no less than [start]
+  /// and no greater than `buffer.length`.
+  ///
+  /// Returns the number of bytes read. This maybe be less than `end - start`
+  /// if the file doesn't have that many bytes to read.
   int readIntoSync(List<int> buffer, [int start = 0, int? end]);
 
-  /**
-   * Reads up to [bytes] bytes from the socket.
-   *
-   * Blocks and waits for a response of up to a specified number of bytes
-   * sent by the socket. [bytes] specifies the maximum number of bytes to
-   * be read. Returns the list of bytes read, which could be less than the
-   * value specified by [bytes].
-   */
+  /// Reads up to [bytes] bytes from the socket.
+  ///
+  /// Blocks and waits for a response of up to a specified number of bytes
+  /// sent by the socket. [bytes] specifies the maximum number of bytes to
+  /// be read. Returns the list of bytes read, which could be less than the
+  /// value specified by [bytes].
   List<int>? readSync(int bytes);
 
-  /**
-   * Shutdown a socket in the provided direction.
-   *
-   * Calling shutdown will never throw an exception and calling it several times
-   * is supported. If both [SocketDirection.RECEIVE] and [SocketDirection.SEND]
-   * directions are closed, the socket is closed completely, the same as if
-   * [closeSync] has been called.
-   */
+  /// Shuts down a socket in the provided direction.
+  ///
+  /// Calling shutdown will never throw an exception and calling it several times
+  /// is supported. If both [SocketDirection.RECEIVE] and [SocketDirection.SEND]
+  /// directions are closed, the socket is closed completely, the same as if
+  /// [closeSync] has been called.
   void shutdown(SocketDirection direction);
 
-  /**
-   * Writes data from a specified range in a [List<int>] to the socket.
-   *
-   * Writes into the socket from a [List<int>]. If [start] is present, the bytes
-   * will be written to the socket starting from index [start]. If [start] is
-   * not present, the bytes will be written starting from index 0. If [end] is
-   * present, the [end] - [start] bytes will be written into the socket starting
-   * at index [start]. If [end] is not provided, [buffer.length] elements will
-   * be written to the socket starting from index [start]. If [end] == [start],
-   * nothing happens.
-   */
+  /// Writes from a [buffer] to the socket.
+  ///
+  /// Will read the buffer from index [start] to index [end].
+  /// The [start] must be non-negative and no greater than `buffer.length`.
+  /// If [end] is omitted, it defaults to [buffer.length].
+  /// Otherwise [end] must be no less than [start]
+  /// and no greater than `buffer.length`.
   void writeFromSync(List<int> buffer, [int start = 0, int? end]);
 
-  /**
-   * The port used by this socket.
-   */
+  /// The port used by this socket.
   int get port;
 
-  /**
-   * The remote port connected to by this socket.
-   */
+  /// The remote port connected to by this socket.
   int get remotePort;
 
-  /**
-   * The [InternetAddress] used to connect this socket.
-   */
+  /// The [InternetAddress] used to connect this socket.
   InternetAddress get address;
 
-  /**
-   * The remote [InternetAddress] connected to by this socket.
-   */
+  /// The remote [InternetAddress] connected to by this socket.
   InternetAddress get remoteAddress;
 }
diff --git a/sdk/lib/isolate/capability.dart b/sdk/lib/isolate/capability.dart
index a51eec2..6678fc4 100644
--- a/sdk/lib/isolate/capability.dart
+++ b/sdk/lib/isolate/capability.dart
@@ -4,31 +4,26 @@
 
 part of dart.isolate;
 
-/**
- * An unforgeable object that comes back as equal when passed through other
- * isolates.
- *
- * Sending a capability object to another isolate, and getting it back,
- * will produce an object that is equal to the original.
- * There is no other way to create objects equal to a capability object.
- *
- * Capabilities can be used as access guards: A remote isolate can send
- * a request for an operation, but it is only allowed if the request contains
- * the correct capability object.
- *
- * This allows exposing the same interface to multiple clients,
- * but restricting some operations to only those clients
- * that have also been given the corresponding capability.
- *
- * Capabilities can be used inside a single isolate,
- * but they have no advantage over
- * just using `new Object` to create a unique object,
- * and it offers no real security against other code
- * running in the same isolate.
- */
+/// An unforgeable object that comes back as equal when passed through other
+/// isolates.
+///
+/// Sending a capability object to another isolate, and getting it back,
+/// will produce an object that is equal to the original.
+/// There is no other way to create objects equal to a capability object.
+///
+/// Capabilities can be used as access guards.
+/// An isolate can receive requests for operations from other isolates,
+/// but only allow them if the request contains the correct capability object.
+/// This allows exposing the same interface to multiple clients,
+/// but restricting some operations to only those clients
+/// that have also been given the corresponding capability.
+///
+/// Capabilities can be used inside a single isolate,
+/// but they have no advantage over
+/// just using `Object()` to create a unique object,
+/// and it offers no real security against other code
+/// running in the same isolate.
 class Capability {
-  /**
-   * Create a new unforgeable capability object.
-   */
+  /// Create a new unforgeable capability object.
   external factory Capability();
 }
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index b7650dd..7a15d7b 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.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.
 
-/**
- * Concurrent programming using _isolates_:
- * independent workers that are similar to threads
- * but don't share memory,
- * communicating only via messages.
- *
- * To use this library in your code:
- *
- *     import 'dart:isolate';
- *
- * {@category VM}
- */
+/// Concurrent programming using _isolates_:
+/// independent workers that are similar to threads
+/// but don't share memory,
+/// communicating only via messages.
+///
+/// To use this library in your code:
+/// ```dart
+/// import 'dart:isolate';
+/// ```
+/// {@category VM}
 library dart.isolate;
 
 import "dart:async";
@@ -22,230 +20,207 @@
 
 part "capability.dart";
 
-/**
- * Thrown when an isolate cannot be created.
- */
+/// Thrown when an isolate cannot be created.
 class IsolateSpawnException implements Exception {
-  /** Error message reported by the spawn operation. */
+  /// Error message reported by the spawn operation.
   final String message;
   @pragma("vm:entry-point")
   IsolateSpawnException(this.message);
   String toString() => "IsolateSpawnException: $message";
 }
 
-/**
- * An isolated Dart execution context.
- *
- * All Dart code runs in an isolate, and code can access classes and values
- * only from the same isolate. Different isolates can communicate by sending
- * values through ports (see [ReceivePort], [SendPort]).
- *
- * An `Isolate` object is a reference to an isolate, usually different from
- * the current isolate.
- * It represents, and can be used to control, the other isolate.
- *
- * When spawning a new isolate, the spawning isolate receives an `Isolate`
- * object representing the new isolate when the spawn operation succeeds.
- *
- * Isolates run code in its own event loop, and each event may run smaller tasks
- * in a nested microtask queue.
- *
- * An `Isolate` object allows other isolates to control the event loop
- * of the isolate that it represents, and to inspect the isolate,
- * for example by pausing the isolate or by getting events when the isolate
- * has an uncaught error.
- *
- * The [controlPort] identifies and gives access to controlling the isolate,
- * and the [pauseCapability] and [terminateCapability] guard access
- * to some control operations.
- * For example, calling [pause] on an `Isolate` object created without a
- * [pauseCapability], has no effect.
- *
- * The `Isolate` object provided by a spawn operation will have the
- * control port and capabilities needed to control the isolate.
- * New isolate objects can be created without some of these capabilities
- * if necessary, using the [Isolate.Isolate] constructor.
- *
- * An `Isolate` object cannot be sent over a `SendPort`, but the control port
- * and capabilities can be sent, and can be used to create a new functioning
- * `Isolate` object in the receiving port's isolate.
- */
+/// An isolated Dart execution context.
+///
+/// All Dart code runs in an isolate, and code can access classes and values
+/// only from the same isolate. Different isolates can communicate by sending
+/// values through ports (see [ReceivePort], [SendPort]).
+///
+/// An `Isolate` object is a reference to an isolate, usually different from
+/// the current isolate.
+/// It represents, and can be used to control, the other isolate.
+///
+/// When spawning a new isolate, the spawning isolate receives an `Isolate`
+/// object representing the new isolate when the spawn operation succeeds.
+///
+/// Isolates run code in its own event loop, and each event may run smaller tasks
+/// in a nested microtask queue.
+///
+/// An `Isolate` object allows other isolates to control the event loop
+/// of the isolate that it represents, and to inspect the isolate,
+/// for example by pausing the isolate or by getting events when the isolate
+/// has an uncaught error.
+///
+/// The [controlPort] identifies and gives access to controlling the isolate,
+/// and the [pauseCapability] and [terminateCapability] guard access
+/// to some control operations.
+/// For example, calling [pause] on an `Isolate` object created without a
+/// [pauseCapability], has no effect.
+///
+/// The `Isolate` object provided by a spawn operation will have the
+/// control port and capabilities needed to control the isolate.
+/// New isolate objects can be created without some of these capabilities
+/// if necessary, using the [Isolate.Isolate] constructor.
+///
+/// An `Isolate` object cannot be sent over a `SendPort`, but the control port
+/// and capabilities can be sent, and can be used to create a new functioning
+/// `Isolate` object in the receiving port's isolate.
 class Isolate {
-  /** Argument to `ping` and `kill`: Ask for immediate action. */
+  /// Argument to `ping` and `kill`: Ask for immediate action.
   static const int immediate = 0;
-  /** Argument to `ping` and `kill`: Ask for action before the next event. */
+
+  /// Argument to `ping` and `kill`: Ask for action before the next event.
   static const int beforeNextEvent = 1;
 
-  /**
-   * Control port used to send control messages to the isolate.
-   *
-   * The control port identifies the isolate.
-   *
-   * An `Isolate` object allows sending control messages
-   * through the control port.
-   *
-   * Some control messages require a specific capability to be passed along
-   * with the message (see [pauseCapability] and [terminateCapability]),
-   * otherwise the message is ignored by the isolate.
-   */
+  /// Control port used to send control messages to the isolate.
+  ///
+  /// The control port identifies the isolate.
+  ///
+  /// An `Isolate` object allows sending control messages
+  /// through the control port.
+  ///
+  /// Some control messages require a specific capability to be passed along
+  /// with the message (see [pauseCapability] and [terminateCapability]),
+  /// otherwise the message is ignored by the isolate.
   final SendPort controlPort;
 
-  /**
-   * Capability granting the ability to pause the isolate.
-   *
-   * This capability is required by [pause].
-   * If the capability is `null`, or if it is not the correct pause capability
-   * of the isolate identified by [controlPort],
-   * then calls to [pause] will have no effect.
-   *
-   * If the isolate is spawned in a paused state, use this capability as
-   * argument to the [resume] method in order to resume the paused isolate.
-   */
+  /// Capability granting the ability to pause the isolate.
+  ///
+  /// This capability is required by [pause].
+  /// If the capability is `null`, or if it is not the correct pause capability
+  /// of the isolate identified by [controlPort],
+  /// then calls to [pause] will have no effect.
+  ///
+  /// If the isolate is spawned in a paused state, use this capability as
+  /// argument to the [resume] method in order to resume the paused isolate.
   final Capability? pauseCapability;
 
-  /**
-   * Capability granting the ability to terminate the isolate.
-   *
-   * This capability is required by [kill] and [setErrorsFatal].
-   * If the capability is `null`, or if it is not the correct termination
-   * capability of the isolate identified by [controlPort],
-   * then calls to those methods will have no effect.
-   */
+  /// Capability granting the ability to terminate the isolate.
+  ///
+  /// This capability is required by [kill] and [setErrorsFatal].
+  /// If the capability is `null`, or if it is not the correct termination
+  /// capability of the isolate identified by [controlPort],
+  /// then calls to those methods will have no effect.
   final Capability? terminateCapability;
 
-  /**
-   * The name of the [Isolate] displayed for debug purposes.
-   *
-   * This can be set using the `debugName` parameter in [spawn] and [spawnUri].
-   *
-   * This name does not uniquely identify an isolate. Multiple isolates in the
-   * same process may have the same `debugName`.
-   *
-   * For a given isolate, this value will be the same as the values returned by
-   * `Dart_DebugName` in the C embedding API and the `debugName` property in
-   * [IsolateMirror].
-   */
+  /// The name of the [Isolate] displayed for debug purposes.
+  ///
+  /// This can be set using the `debugName` parameter in [spawn] and [spawnUri].
+  ///
+  /// This name does not uniquely identify an isolate. Multiple isolates in the
+  /// same process may have the same `debugName`.
+  ///
+  /// For a given isolate, this value will be the same as the values returned by
+  /// `Dart_DebugName` in the C embedding API and the `debugName` property in
+  /// [IsolateMirror].
   @Since("2.3")
   external String? get debugName;
 
-  /**
-   * Create a new [Isolate] object with a restricted set of capabilities.
-   *
-   * The port should be a control port for an isolate, as taken from
-   * another `Isolate` object.
-   *
-   * The capabilities should be the subset of the capabilities that are
-   * available to the original isolate.
-   * Capabilities of an isolate are locked to that isolate, and have no effect
-   * anywhere else, so the capabilities should come from the same isolate as
-   * the control port.
-   *
-   * Can also be used to create an [Isolate] object from a control port, and
-   * any available capabilities, that have been sent through a [SendPort].
-   *
-   * Example:
-   * ```dart
-   * Isolate isolate = findSomeIsolate();
-   * Isolate restrictedIsolate = new Isolate(isolate.controlPort);
-   * untrustedCode(restrictedIsolate);
-   * ```
-   * This example creates a new `Isolate` object that cannot be used to
-   * pause or terminate the isolate. All the untrusted code can do is to
-   * inspect the isolate and see uncaught errors or when it terminates.
-   */
+  /// Creates a new [Isolate] object with a restricted set of capabilities.
+  ///
+  /// The port should be a control port for an isolate, as taken from
+  /// another `Isolate` object.
+  ///
+  /// The capabilities should be the subset of the capabilities that are
+  /// available to the original isolate.
+  /// Capabilities of an isolate are locked to that isolate, and have no effect
+  /// anywhere else, so the capabilities should come from the same isolate as
+  /// the control port.
+  ///
+  /// Can also be used to create an [Isolate] object from a control port, and
+  /// any available capabilities, that have been sent through a [SendPort].
+  ///
+  /// Example:
+  /// ```dart
+  /// Isolate isolate = findSomeIsolate();
+  /// Isolate restrictedIsolate = Isolate(isolate.controlPort);
+  /// untrustedCode(restrictedIsolate);
+  /// ```
+  /// This example creates a new `Isolate` object that cannot be used to
+  /// pause or terminate the isolate. All the untrusted code can do is to
+  /// inspect the isolate and see uncaught errors or when it terminates.
   Isolate(this.controlPort, {this.pauseCapability, this.terminateCapability});
 
-  /**
-   * Return an [Isolate] object representing the current isolate.
-   *
-   * The current isolate for code using [current]
-   * is the isolate running the code.
-   *
-   * The isolate object provides the capabilities required to inspect,
-   * pause or kill the isolate, and allows granting these capabilities
-   * to others.
-   *
-   * It is possible to pause the current isolate, but doing so *without*
-   * first passing the ability to resume it again to another isolate,
-   * is a sure way to hang your program.
-   */
+  /// An [Isolate] object representing the current isolate.
+  ///
+  /// The current isolate for code using [current]
+  /// is the isolate running the code.
+  ///
+  /// The isolate object provides the capabilities required to inspect,
+  /// pause or kill the isolate, and allows granting these capabilities
+  /// to others.
+  ///
+  /// It is possible to pause the current isolate, but doing so *without*
+  /// first passing the ability to resume it again to another isolate,
+  /// is a sure way to hang your program.
   external static Isolate get current;
 
-  /**
-   * The location of the package configuration of the current isolate, if any.
-   *
-   * This getter returns `null`, as the `packages/` directory is not supported
-   * in Dart 2.
-   */
+  /// The package root of the current isolate, if any.
+  ///
+  /// This getter returns `null`, as the `packages/` directory is not supported
+  /// in Dart 2.
   @Deprecated('packages/ directory resolution is not supported in Dart 2.')
   external static Future<Uri?> get packageRoot;
 
-  /**
-   * The package root of the current isolate, if any.
-   *
-   * If the isolate is using a [packageRoot] or the isolate has not been
-   * setup for package resolution, this getter returns `null`, otherwise it
-   * returns the package config URI.
-   */
+  /// The location of the package configuration of the current isolate, if any.
+  ///
+  /// If the isolate has not been setup for package resolution,
+  /// this location is `null`,
+  /// otherwise it is a URI referencing the package config file.
   external static Future<Uri?> get packageConfig;
 
-  /**
-   * Maps a package: URI to a non-package Uri.
-   *
-   * If there is no valid mapping from the package: URI in the current
-   * isolate, then this call returns `null`. Non-package: URIs are
-   * returned unmodified.
-   */
+  /// Maps a `package:` URI to a non-package Uri.
+  ///
+  /// If there is no valid mapping from the `package:` URI in the current
+  /// isolate, then this call returns `null`. Non-`package:` URIs are
+  /// returned unmodified.
   external static Future<Uri?> resolvePackageUri(Uri packageUri);
 
-  /**
-   * Creates and spawns an isolate that shares the same code as the current
-   * isolate.
-   *
-   * The argument [entryPoint] specifies the initial function to call
-   * in the spawned isolate.
-   * The entry-point function is invoked in the new isolate with [message]
-   * as the only argument.
-   *
-   * The function must be a top-level function or a static method
-   * that can be called with a single argument,
-   * that is, a compile-time constant function value
-   * which accepts at least one positional parameter
-   * and has at most one required positional parameter.
-   * The function may accept any number of optional parameters,
-   * as long as it *can* be called with just a single argument.
-   * The function must not be the value of a function expression
-   * or an instance method tear-off.
-   *
-   * Usually the initial [message] contains a [SendPort] so
-   * that the spawner and spawnee can communicate with each other.
-   *
-   * If the [paused] parameter is set to `true`,
-   * the isolate will start up in a paused state,
-   * just before calling the [entryPoint] function with the [message],
-   * as if by an initial call of `isolate.pause(isolate.pauseCapability)`.
-   * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`.
-   *
-   * If the [errorsAreFatal], [onExit] and/or [onError] parameters are provided,
-   * the isolate will act as if, respectively, [setErrorsFatal],
-   * [addOnExitListener] and [addErrorListener] were called with the
-   * corresponding parameter and was processed before the isolate starts
-   * running.
-   *
-   * If [debugName] is provided, the spawned [Isolate] will be identifiable by
-   * this name in debuggers and logging.
-   *
-   * If [errorsAreFatal] is omitted, the platform may choose a default behavior
-   * or inherit the current isolate's behavior.
-   *
-   * You can also call the [setErrorsFatal], [addOnExitListener] and
-   * [addErrorListener] methods on the returned isolate, but unless the
-   * isolate was started as [paused], it may already have terminated
-   * before those methods can complete.
-   *
-   * Returns a future which will complete with an [Isolate] instance if the
-   * spawning succeeded. It will complete with an error otherwise.
-   */
+  /// Creates and spawns an isolate that shares the same code as the current
+  /// isolate.
+  ///
+  /// The argument [entryPoint] specifies the initial function to call
+  /// in the spawned isolate.
+  /// The entry-point function is invoked in the new isolate with [message]
+  /// as the only argument.
+  ///
+  /// The function must be a top-level function or a static method
+  /// that can be called with a single argument,
+  /// that is, a compile-time constant function value
+  /// which accepts at least one positional parameter
+  /// and has at most one required positional parameter.
+  /// The function may accept any number of optional parameters,
+  /// as long as it *can* be called with just a single argument.
+  /// The function must not be the value of a function expression
+  /// or an instance method tear-off.
+  ///
+  /// Usually the initial [message] contains a [SendPort] so
+  /// that the spawner and spawnee can communicate with each other.
+  ///
+  /// If the [paused] parameter is set to `true`,
+  /// the isolate will start up in a paused state,
+  /// just before calling the [entryPoint] function with the [message],
+  /// as if by an initial call of `isolate.pause(isolate.pauseCapability)`.
+  /// To resume the isolate, call `isolate.resume(isolate.pauseCapability)`.
+  ///
+  /// If the [errorsAreFatal], [onExit] and/or [onError] parameters are provided,
+  /// the isolate will act as if, respectively, [setErrorsFatal],
+  /// [addOnExitListener] and [addErrorListener] were called with the
+  /// corresponding parameter and was processed before the isolate starts
+  /// running.
+  ///
+  /// If [debugName] is provided, the spawned [Isolate] will be identifiable by
+  /// this name in debuggers and logging.
+  ///
+  /// If [errorsAreFatal] is omitted, the platform may choose a default behavior
+  /// or inherit the current isolate's behavior.
+  ///
+  /// You can also call the [setErrorsFatal], [addOnExitListener] and
+  /// [addErrorListener] methods on the returned isolate, but unless the
+  /// isolate was started as [paused], it may already have terminated
+  /// before those methods can complete.
+  ///
+  /// Returns a future which will complete with an [Isolate] instance if the
+  /// spawning succeeded. It will complete with an error otherwise.
   external static Future<Isolate> spawn<T>(
       void entryPoint(T message), T message,
       {bool paused = false,
@@ -254,78 +229,76 @@
       SendPort? onError,
       @Since("2.3") String? debugName});
 
-  /**
-   * Creates and spawns an isolate that runs the code from the library with
-   * the specified URI.
-   *
-   * The isolate starts executing the top-level `main` function of the library
-   * with the given URI.
-   *
-   * The target `main` must be callable with zero, one or two arguments.
-   * Examples:
-   *
-   * * `main()`
-   * * `main(args)`
-   * * `main(args, message)`
-   *
-   * When present, the parameter `args` is set to the provided [args] list.
-   * When present, the parameter `message` is set to the initial [message].
-   *
-   * If the [paused] parameter is set to `true`,
-   * the isolate will start up in a paused state,
-   * as if by an initial call of `isolate.pause(isolate.pauseCapability)`.
-   * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`.
-   *
-   * If the [errorsAreFatal], [onExit] and/or [onError] parameters are provided,
-   * the isolate will act as if, respectively, [setErrorsFatal],
-   * [addOnExitListener] and [addErrorListener] were called with the
-   * corresponding parameter and was processed before the isolate starts
-   * running.
-   *
-   * You can also call the [setErrorsFatal], [addOnExitListener] and
-   * [addErrorListener] methods on the returned isolate, but unless the
-   * isolate was started as [paused], it may already have terminated
-   * before those methods can complete.
-   *
-   * If the [checked] parameter is set to `true` or `false`,
-   * the new isolate will run code in checked mode (enabling asserts and type
-   * checks), respectively in production mode (disabling asserts and type
-   * checks), if possible. If the parameter is omitted, the new isolate will
-   * inherit the value from the current isolate.
-   *
-   * In Dart2 strong mode, the `checked` parameter only controls asserts, but
-   * not type checks.
-   *
-   * It may not always be possible to honor the `checked` parameter.
-   * If the isolate code was pre-compiled, it may not be possible to change
-   * the checked mode setting dynamically.
-   * In that case, the `checked` parameter is ignored.
-   *
-   * WARNING: The [checked] parameter is not implemented on all platforms yet.
-   *
-   * If the [packageConfig] parameter is provided, then it is used to find the
-   * location of a package resolution configuration file for the spawned
-   * isolate.
-   *
-   * If the [automaticPackageResolution] parameter is provided, then the
-   * location of the package sources in the spawned isolate is automatically
-   * determined.
-   *
-   * The [environment] is a mapping from strings to strings which the
-   * spawned isolate uses when looking up [String.fromEnvironment] values.
-   * The system may add its own entries to environment as well.
-   * If `environment` is omitted, the spawned isolate has the same environment
-   * declarations as the spawning isolate.
-   *
-   * WARNING: The [environment] parameter is not implemented on all
-   * platforms yet.
-   *
-   * If [debugName] is provided, the spawned [Isolate] will be identifiable by
-   * this name in debuggers and logging.
-   *
-   * Returns a future that will complete with an [Isolate] instance if the
-   * spawning succeeded. It will complete with an error otherwise.
-   */
+  /// Creates and spawns an isolate that runs the code from the library with
+  /// the specified URI.
+  ///
+  /// The isolate starts executing the top-level `main` function of the library
+  /// with the given URI.
+  ///
+  /// The target `main` must be callable with zero, one or two arguments.
+  /// Examples:
+  ///
+  /// * `main()`
+  /// * `main(args)`
+  /// * `main(args, message)`
+  ///
+  /// When present, the parameter `args` is set to the provided [args] list.
+  /// When present, the parameter `message` is set to the initial [message].
+  ///
+  /// If the [paused] parameter is set to `true`,
+  /// the isolate will start up in a paused state,
+  /// as if by an initial call of `isolate.pause(isolate.pauseCapability)`.
+  /// To resume the isolate, call `isolate.resume(isolate.pauseCapability)`.
+  ///
+  /// If the [errorsAreFatal], [onExit] and/or [onError] parameters are provided,
+  /// the isolate will act as if, respectively, [setErrorsFatal],
+  /// [addOnExitListener] and [addErrorListener] were called with the
+  /// corresponding parameter and was processed before the isolate starts
+  /// running.
+  ///
+  /// You can also call the [setErrorsFatal], [addOnExitListener] and
+  /// [addErrorListener] methods on the returned isolate, but unless the
+  /// isolate was started as [paused], it may already have terminated
+  /// before those methods can complete.
+  ///
+  /// If the [checked] parameter is set to `true` or `false`,
+  /// the new isolate will run code in checked mode (enabling asserts and type
+  /// checks), respectively in production mode (disabling asserts and type
+  /// checks), if possible. If the parameter is omitted, the new isolate will
+  /// inherit the value from the current isolate.
+  ///
+  /// In Dart2 strong mode, the `checked` parameter only controls asserts, but
+  /// not type checks.
+  ///
+  /// It may not always be possible to honor the `checked` parameter.
+  /// If the isolate code was pre-compiled, it may not be possible to change
+  /// the checked mode setting dynamically.
+  /// In that case, the `checked` parameter is ignored.
+  ///
+  /// WARNING: The [checked] parameter is not implemented on all platforms yet.
+  ///
+  /// If the [packageConfig] parameter is provided, then it is used to find the
+  /// location of a package resolution configuration file for the spawned
+  /// isolate.
+  ///
+  /// If the [automaticPackageResolution] parameter is provided, then the
+  /// location of the package sources in the spawned isolate is automatically
+  /// determined.
+  ///
+  /// The [environment] is a mapping from strings to strings which the
+  /// spawned isolate uses when looking up [String.fromEnvironment] values.
+  /// The system may add its own entries to environment as well.
+  /// If `environment` is omitted, the spawned isolate has the same environment
+  /// declarations as the spawning isolate.
+  ///
+  /// WARNING: The [environment] parameter is not implemented on all
+  /// platforms yet.
+  ///
+  /// If [debugName] is provided, the spawned [Isolate] will be identifiable by
+  /// this name in debuggers and logging.
+  ///
+  /// Returns a future that will complete with an [Isolate] instance if the
+  /// spawning succeeded. It will complete with an error otherwise.
   external static Future<Isolate> spawnUri(
       Uri uri,
       List<String> args,
@@ -343,239 +316,219 @@
       @Since("2.3")
           String? debugName});
 
-  /**
-   * Requests the isolate to pause.
-   *
-   * When the isolate receives the pause command, it stops
-   * processing events from the event loop queue.
-   * It may still add new events to the queue in response to, e.g., timers
-   * or receive-port messages. When the isolate is resumed,
-   * it starts handling the already enqueued events.
-   *
-   * The pause request is sent through the isolate's command port,
-   * which bypasses the receiving isolate's event loop.
-   * The pause takes effect when it is received, pausing the event loop
-   * as it is at that time.
-   *
-   * The [resumeCapability] is used to identity the pause,
-   * and must be used again to end the pause using [resume].
-   * If [resumeCapability] is omitted, a new capability object is created
-   * and used instead.
-   *
-   * If an isolate is paused more than once using the same capability,
-   * only one resume with that capability is needed to end the pause.
-   *
-   * If an isolate is paused using more than one capability,
-   * each pause must be individually ended before the isolate resumes.
-   *
-   * Returns the capability that must be used to end the pause.
-   * This is either [resumeCapability], or a new capability when
-   * [resumeCapability] is omitted.
-   *
-   * If [pauseCapability] is `null`, or it's not the pause capability
-   * of the isolate identified by [controlPort],
-   * the pause request is ignored by the receiving isolate.
-   */
+  /// Requests the isolate to pause.
+  ///
+  /// When the isolate receives the pause command, it stops
+  /// processing events from the event loop queue.
+  /// It may still add new events to the queue in response to, e.g., timers
+  /// or receive-port messages. When the isolate is resumed,
+  /// it starts handling the already enqueued events.
+  ///
+  /// The pause request is sent through the isolate's command port,
+  /// which bypasses the receiving isolate's event loop.
+  /// The pause takes effect when it is received, pausing the event loop
+  /// as it is at that time.
+  ///
+  /// The [resumeCapability] is used to identity the pause,
+  /// and must be used again to end the pause using [resume].
+  /// If [resumeCapability] is omitted, a new capability object is created
+  /// and used instead.
+  ///
+  /// If an isolate is paused more than once using the same capability,
+  /// only one resume with that capability is needed to end the pause.
+  ///
+  /// If an isolate is paused using more than one capability,
+  /// each pause must be individually ended before the isolate resumes.
+  ///
+  /// Returns the capability that must be used to end the pause.
+  /// This is either [resumeCapability], or a new capability when
+  /// [resumeCapability] is omitted.
+  ///
+  /// If [pauseCapability] is `null`, or it's not the pause capability
+  /// of the isolate identified by [controlPort],
+  /// the pause request is ignored by the receiving isolate.
   Capability pause([Capability? resumeCapability]) {
     resumeCapability ??= new Capability();
     _pause(resumeCapability);
     return resumeCapability;
   }
 
-  /** Internal implementation of [pause]. */
+  /// Internal implementation of [pause].
   external void _pause(Capability resumeCapability);
 
-  /**
-   * Resumes a paused isolate.
-   *
-   * Sends a message to an isolate requesting that it ends a pause
-   * that was previously requested.
-   *
-   * When all active pause requests have been cancelled, the isolate
-   * will continue processing events and handling normal messages.
-   *
-   * If the [resumeCapability] is not one that has previously been used
-   * to pause the isolate, or it has already been used to resume from
-   * that pause, the resume call has no effect.
-   */
+  /// Resumes a paused isolate.
+  ///
+  /// Sends a message to an isolate requesting that it ends a pause
+  /// that was previously requested.
+  ///
+  /// When all active pause requests have been cancelled, the isolate
+  /// will continue processing events and handling normal messages.
+  ///
+  /// If the [resumeCapability] is not one that has previously been used
+  /// to pause the isolate, or it has already been used to resume from
+  /// that pause, the resume call has no effect.
   external void resume(Capability resumeCapability);
 
-  /**
-   * Requests an exit message on [responsePort] when the isolate terminates.
-   *
-   * The isolate will send [response] as a message on [responsePort] as the last
-   * thing before it terminates. It will run no further code after the message
-   * has been sent.
-   *
-   * Adding the same port more than once will only cause it to receive one exit
-   * message, using the last response value that was added,
-   * and it only needs to be removed once using [removeOnExitListener].
-   *
-   * If the isolate has terminated before it can receive this request,
-   * no exit message will be sent.
-   *
-   * The [response] object must follow the same restrictions as enforced by
-   * [SendPort.send].
-   * It is recommended to only use simple values that can be sent to all
-   * isolates, like `null`, booleans, numbers or strings.
-   *
-   * Since isolates run concurrently, it's possible for it to exit before the
-   * exit listener is established, and in that case no response will be
-   * sent on [responsePort].
-   * To avoid this, either use the corresponding parameter to the spawn
-   * function, or start the isolate paused, add the listener and
-   * then resume the isolate.
-   */
+  /// Requests an exit message on [responsePort] when the isolate terminates.
+  ///
+  /// The isolate will send [response] as a message on [responsePort] as the last
+  /// thing before it terminates. It will run no further code after the message
+  /// has been sent.
+  ///
+  /// Adding the same port more than once will only cause it to receive one exit
+  /// message, using the last response value that was added,
+  /// and it only needs to be removed once using [removeOnExitListener].
+  ///
+  /// If the isolate has terminated before it can receive this request,
+  /// no exit message will be sent.
+  ///
+  /// The [response] object must follow the same restrictions as enforced by
+  /// [SendPort.send].
+  /// It is recommended to only use simple values that can be sent to all
+  /// isolates, like `null`, booleans, numbers or strings.
+  ///
+  /// Since isolates run concurrently, it's possible for it to exit before the
+  /// exit listener is established, and in that case no response will be
+  /// sent on [responsePort].
+  /// To avoid this, either use the corresponding parameter to the spawn
+  /// function, or start the isolate paused, add the listener and
+  /// then resume the isolate.
   /* TODO(lrn): Can we do better? Can the system recognize this message and
    * send a reply if the receiving isolate is dead?
    */
   external void addOnExitListener(SendPort responsePort, {Object? response});
 
-  /**
-   * Stops listening for exit messages from the isolate.
-   *
-   * Requests for the isolate to not send exit messages on [responsePort].
-   * If the isolate isn't expecting to send exit messages on [responsePort],
-   * because the port hasn't been added using [addOnExitListener],
-   * or because it has already been removed, the request is ignored.
-   *
-   * If the same port has been passed via [addOnExitListener] more than once,
-   * only one call to `removeOnExitListener` is needed to stop it from receiving
-   * exit messages.
-   *
-   * Closing the receive port that is associated with the [responsePort] does
-   * not stop the isolate from sending uncaught errors, they are just going to
-   * be lost.
-   *
-   * An exit message may still be sent if the isolate terminates
-   * before this request is received and processed.
-   */
+  /// Stops listening for exit messages from the isolate.
+  ///
+  /// Requests for the isolate to not send exit messages on [responsePort].
+  /// If the isolate isn't expecting to send exit messages on [responsePort],
+  /// because the port hasn't been added using [addOnExitListener],
+  /// or because it has already been removed, the request is ignored.
+  ///
+  /// If the same port has been passed via [addOnExitListener] more than once,
+  /// only one call to `removeOnExitListener` is needed to stop it from receiving
+  /// exit messages.
+  ///
+  /// Closing the receive port that is associated with the [responsePort] does
+  /// not stop the isolate from sending uncaught errors, they are just going to
+  /// be lost.
+  ///
+  /// An exit message may still be sent if the isolate terminates
+  /// before this request is received and processed.
   external void removeOnExitListener(SendPort responsePort);
 
-  /**
-   * Sets whether uncaught errors will terminate the isolate.
-   *
-   * If errors are fatal, any uncaught error will terminate the isolate
-   * event loop and shut down the isolate.
-   *
-   * This call requires the [terminateCapability] for the isolate.
-   * If the capability is absent or incorrect, no change is made.
-   *
-   * Since isolates run concurrently, it's possible for the receiving isolate
-   * to exit due to an error, before a request, using this method, has been
-   * received and processed.
-   * To avoid this, either use the corresponding parameter to the spawn
-   * function, or start the isolate paused, set errors non-fatal and
-   * then resume the isolate.
-   */
+  /// Sets whether uncaught errors will terminate the isolate.
+  ///
+  /// If errors are fatal, any uncaught error will terminate the isolate
+  /// event loop and shut down the isolate.
+  ///
+  /// This call requires the [terminateCapability] for the isolate.
+  /// If the capability is absent or incorrect, no change is made.
+  ///
+  /// Since isolates run concurrently, it's possible for the receiving isolate
+  /// to exit due to an error, before a request, using this method, has been
+  /// received and processed.
+  /// To avoid this, either use the corresponding parameter to the spawn
+  /// function, or start the isolate paused, set errors non-fatal and
+  /// then resume the isolate.
   external void setErrorsFatal(bool errorsAreFatal);
 
-  /**
-   * Requests the isolate to shut down.
-   *
-   * The isolate is requested to terminate itself.
-   * The [priority] argument specifies when this must happen.
-   *
-   * The [priority], when provided, must be one of [immediate] or
-   * [beforeNextEvent] (the default).
-   * The shutdown is performed at different times depending on the priority:
-   *
-   * * `immediate`: The isolate shuts down as soon as possible.
-   *     Control messages are handled in order, so all previously sent control
-   *     events from this isolate will all have been processed.
-   *     The shutdown should happen no later than if sent with
-   *     `beforeNextEvent`.
-   *     It may happen earlier if the system has a way to shut down cleanly
-   *     at an earlier time, even during the execution of another event.
-   * * `beforeNextEvent`: The shutdown is scheduled for the next time
-   *     control returns to the event loop of the receiving isolate,
-   *     after the current event, and any already scheduled control events,
-   *     are completed.
-   *
-   * If [terminateCapability] is `null`, or it's not the terminate capability
-   * of the isolate identified by [controlPort],
-   * the kill request is ignored by the receiving isolate.
-   */
+  /// Requests the isolate to shut down.
+  ///
+  /// The isolate is requested to terminate itself.
+  /// The [priority] argument specifies when this must happen.
+  ///
+  /// The [priority], when provided, must be one of [immediate] or
+  /// [beforeNextEvent] (the default).
+  /// The shutdown is performed at different times depending on the priority:
+  ///
+  /// * `immediate`: The isolate shuts down as soon as possible.
+  ///     Control messages are handled in order, so all previously sent control
+  ///     events from this isolate will all have been processed.
+  ///     The shutdown should happen no later than if sent with
+  ///     `beforeNextEvent`.
+  ///     It may happen earlier if the system has a way to shut down cleanly
+  ///     at an earlier time, even during the execution of another event.
+  /// * `beforeNextEvent`: The shutdown is scheduled for the next time
+  ///     control returns to the event loop of the receiving isolate,
+  ///     after the current event, and any already scheduled control events,
+  ///     are completed.
+  ///
+  /// If [terminateCapability] is `null`, or it's not the terminate capability
+  /// of the isolate identified by [controlPort],
+  /// the kill request is ignored by the receiving isolate.
   external void kill({int priority = beforeNextEvent});
 
-  /**
-   * Requests that the isolate send [response] on the [responsePort].
-   *
-   * The [response] object must follow the same restrictions as enforced by
-   * [SendPort.send].
-   * It is recommended to only use simple values that can be sent to all
-   * isolates, like `null`, booleans, numbers or strings.
-   *
-   * If the isolate is alive, it will eventually send `response`
-   * (defaulting to `null`) on the response port.
-   *
-   * The [priority] must be one of [immediate] or [beforeNextEvent].
-   * The response is sent at different times depending on the ping type:
-   *
-   * * `immediate`: The isolate responds as soon as it receives the
-   *     control message. This is after any previous control message
-   *     from the same isolate has been received and processed,
-   *     but may be during execution of another event.
-   * * `beforeNextEvent`: The response is scheduled for the next time
-   *     control returns to the event loop of the receiving isolate,
-   *     after the current event, and any already scheduled control events,
-   *     are completed.
-   */
+  /// Requests that the isolate send [response] on the [responsePort].
+  ///
+  /// The [response] object must follow the same restrictions as enforced by
+  /// [SendPort.send].
+  /// It is recommended to only use simple values that can be sent to all
+  /// isolates, like `null`, booleans, numbers or strings.
+  ///
+  /// If the isolate is alive, it will eventually send `response`
+  /// (defaulting to `null`) on the response port.
+  ///
+  /// The [priority] must be one of [immediate] or [beforeNextEvent].
+  /// The response is sent at different times depending on the ping type:
+  ///
+  /// * `immediate`: The isolate responds as soon as it receives the
+  ///     control message. This is after any previous control message
+  ///     from the same isolate has been received and processed,
+  ///     but may be during execution of another event.
+  /// * `beforeNextEvent`: The response is scheduled for the next time
+  ///     control returns to the event loop of the receiving isolate,
+  ///     after the current event, and any already scheduled control events,
+  ///     are completed.
   external void ping(SendPort responsePort,
       {Object? response, int priority = immediate});
 
-  /**
-   * Requests that uncaught errors of the isolate are sent back to [port].
-   *
-   * The errors are sent back as two elements lists.
-   * The first element is a `String` representation of the error, usually
-   * created by calling `toString` on the error.
-   * The second element is a `String` representation of an accompanying
-   * stack trace, or `null` if no stack trace was provided.
-   * To convert this back to a [StackTrace] object, use [StackTrace.fromString].
-   *
-   * Listening using the same port more than once does nothing.
-   * A port will only receive each error once,
-   * and will only need to be removed once using [removeErrorListener].
-
-   * Closing the receive port that is associated with the port does not stop
-   * the isolate from sending uncaught errors, they are just going to be lost.
-   * Instead use [removeErrorListener] to stop receiving errors on [port].
-   *
-   * Since isolates run concurrently, it's possible for it to exit before the
-   * error listener is established. To avoid this, start the isolate paused,
-   * add the listener and then resume the isolate.
-   */
+  /// Requests that uncaught errors of the isolate are sent back to [port].
+  ///
+  /// The errors are sent back as two-element lists.
+  /// The first element is a `String` representation of the error, usually
+  /// created by calling `toString` on the error.
+  /// The second element is a `String` representation of an accompanying
+  /// stack trace, or `null` if no stack trace was provided.
+  /// To convert this back to a [StackTrace] object, use [StackTrace.fromString].
+  ///
+  /// Listening using the same port more than once does nothing.
+  /// A port will only receive each error once,
+  /// and will only need to be removed once using [removeErrorListener].
+  ///
+  /// Closing the receive port that is associated with the port does not stop
+  /// the isolate from sending uncaught errors, they are just going to be lost.
+  /// Instead use [removeErrorListener] to stop receiving errors on [port].
+  ///
+  /// Since isolates run concurrently, it's possible for it to exit before the
+  /// error listener is established. To avoid this, start the isolate paused,
+  /// add the listener and then resume the isolate.
   external void addErrorListener(SendPort port);
 
-  /**
-   * Stops listening for uncaught errors from the isolate.
-   *
-   * Requests for the isolate to not send uncaught errors on [port].
-   * If the isolate isn't expecting to send uncaught errors on [port],
-   * because the port hasn't been added using [addErrorListener],
-   * or because it has already been removed, the request is ignored.
-   *
-   * If the same port has been passed via [addErrorListener] more than once,
-   * only one call to `removeErrorListener` is needed to stop it from receiving
-   * uncaught errors.
-   *
-   * Uncaught errors message may still be sent by the isolate
-   * until this request is received and processed.
-   */
+  /// Stops listening for uncaught errors from the isolate.
+  ///
+  /// Requests for the isolate to not send uncaught errors on [port].
+  /// If the isolate isn't expecting to send uncaught errors on [port],
+  /// because the port hasn't been added using [addErrorListener],
+  /// or because it has already been removed, the request is ignored.
+  ///
+  /// If the same port has been passed via [addErrorListener] more than once,
+  /// only one call to `removeErrorListener` is needed to stop it from receiving
+  /// uncaught errors.
+  ///
+  /// Uncaught errors message may still be sent by the isolate
+  /// until this request is received and processed.
   external void removeErrorListener(SendPort port);
 
-  /**
-   * Returns a broadcast stream of uncaught errors from the isolate.
-   *
-   * Each error is provided as an error event on the stream.
-   *
-   * The actual error object and stackTraces will not necessarily
-   * be the same object types as in the actual isolate, but they will
-   * always have the same [Object.toString] result.
-   *
-   * This stream is based on [addErrorListener] and [removeErrorListener].
-   */
+  /// Returns a broadcast stream of uncaught errors from the isolate.
+  ///
+  /// Each error is provided as an error event on the stream.
+  ///
+  /// The actual error object and stackTraces will not necessarily
+  /// be the same object types as in the actual isolate, but they will
+  /// always have the same [Object.toString] result.
+  ///
+  /// This stream is based on [addErrorListener] and [removeErrorListener].
   Stream get errors {
     StreamController controller = StreamController.broadcast(sync: true);
     RawReceivePort? port;
@@ -602,158 +555,159 @@
   }
 }
 
-/**
- * Sends messages to its [ReceivePort]s.
- *
- * [SendPort]s are created from [ReceivePort]s. Any message sent through
- * a [SendPort] is delivered to its corresponding [ReceivePort]. There might be
- * many [SendPort]s for the same [ReceivePort].
- *
- * [SendPort]s can be transmitted to other isolates, and they preserve equality
- * when sent.
- */
+/// Sends messages to its [ReceivePort]s.
+///
+/// [SendPort]s are created from [ReceivePort]s. Any message sent through
+/// a [SendPort] is delivered to its corresponding [ReceivePort]. There might be
+/// many [SendPort]s for the same [ReceivePort].
+///
+/// [SendPort]s can be transmitted to other isolates, and they preserve equality
+/// when sent.
 abstract class SendPort implements Capability {
-  /**
-   * 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 be cyclic.
-   *
-   * 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]), it
-   * is also possible to send object instances (which would be copied in the
-   * process). This is currently only supported by the
-   * [Dart Native](https://dart.dev/platforms#dart-native-vm-jit-and-aot)
-   * platform.
-   *
-   * The send happens immediately and doesn't block.  The corresponding receive
-   * port can receive the message as soon as its isolate's event loop is ready
-   * to deliver it, independently of what the sending isolate is doing.
-   */
+  /// 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.
+  ///
+  /// 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]),
+  /// it is also possible to send object instances (which would be copied in the
+  /// process). This is currently only supported by the
+  /// [Dart Native](https://dart.dev/platforms#dart-native-vm-jit-and-aot)
+  /// platform.
+  ///
+  /// The send happens immediately and doesn't block.  The corresponding receive
+  /// port can receive the message as soon as its isolate's event loop is ready
+  /// to deliver it, independently of what the sending isolate is doing.
   void send(Object? message);
 
-  /**
-   * Tests whether [other] is a [SendPort] pointing to the same
-   * [ReceivePort] as this one.
-   */
+  /// Tests whether [other] is a [SendPort] pointing to the same
+  /// [ReceivePort] as this one.
   bool operator ==(var other);
 
-  /**
-   * Returns an immutable hash code for this send port that is
-   * consistent with the == operator.
-   */
+  /// A hash code for this send port that is consistent with the == operator.
   int get hashCode;
 }
 
-/**
- * Together with [SendPort], the only means of communication between isolates.
- *
- * [ReceivePort]s have a `sendPort` getter which returns a [SendPort].
- * Any message that is sent through this [SendPort]
- * is delivered to the [ReceivePort] it has been created from. There, the
- * message is dispatched to the `ReceivePort`'s listener.
- *
- * A [ReceivePort] is a non-broadcast stream. This means that it buffers
- * incoming messages until a listener is registered. Only one listener can
- * receive messages. See [Stream.asBroadcastStream] for transforming the port
- * to a broadcast stream.
- *
- * A [ReceivePort] may have many [SendPort]s.
- */
+/// Together with [SendPort], the only means of communication between isolates.
+///
+/// [ReceivePort]s have a `sendPort` getter which returns a [SendPort].
+/// Any message that is sent through this [SendPort]
+/// is delivered to the [ReceivePort] it has been created from. There, the
+/// message is dispatched to the `ReceivePort`'s listener.
+///
+/// A [ReceivePort] is a non-broadcast stream. This means that it buffers
+/// incoming messages until a listener is registered. Only one listener can
+/// receive messages. See [Stream.asBroadcastStream] for transforming the port
+/// to a broadcast stream.
+///
+/// A [ReceivePort] may have many [SendPort]s.
 abstract class ReceivePort implements Stream<dynamic> {
-  /**
-   * Opens a long-lived port for receiving messages.
-   *
-   * A [ReceivePort] is a non-broadcast stream. This means that it buffers
-   * incoming messages until a listener is registered. Only one listener can
-   * receive messages. See [Stream.asBroadcastStream] for transforming the port
-   * to a broadcast stream.
-   *
-   * The optional `debugName` parameter can be set to associate a name with
-   * this port that can be displayed in tooling.
-   *
-   * A receive port is closed by canceling its subscription.
-   */
+  /// Opens a long-lived port for receiving messages.
+  ///
+  /// A [ReceivePort] is a non-broadcast stream. This means that it buffers
+  /// incoming messages until a listener is registered. Only one listener can
+  /// receive messages. See [Stream.asBroadcastStream] for transforming the port
+  /// to a broadcast stream.
+  ///
+  /// The optional `debugName` parameter can be set to associate a name with
+  /// this port that can be displayed in tooling.
+  ///
+  /// A receive port is closed by canceling its subscription.
   external factory ReceivePort([String debugName = '']);
 
-  /**
-   * Creates a [ReceivePort] from a [RawReceivePort].
-   *
-   * The handler of the given [rawPort] is overwritten during the construction
-   * of the result.
-   */
+  /// Creates a [ReceivePort] from a [RawReceivePort].
+  ///
+  /// The handler of the given [rawPort] is overwritten during the construction
+  /// of the result.
   external factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort);
 
-  /**
-   * Inherited from [Stream].
-   *
-   * Note that [onError] and [cancelOnError] are ignored since a ReceivePort
-   * will never receive an error.
-   *
-   * The [onDone] handler will be called when the stream closes.
-   * The stream closes when [close] is called.
-   */
+  /// Listen for events from [Stream].
+  ///
+  /// See [Stream.listen].
+  ///
+  /// Note that [onError] and [cancelOnError] are ignored since a [ReceivePort]
+  /// will never receive an error.
+  ///
+  /// The [onDone] handler will be called when the stream closes.
+  /// The stream closes when [close] is called.
   StreamSubscription<dynamic> listen(void onData(var message)?,
       {Function? onError, void onDone()?, bool? cancelOnError});
 
-  /**
-   * Closes `this`.
-   *
-   * If the stream has not been canceled yet, adds a close-event to the event
-   * queue and discards any further incoming messages.
-   *
-   * If the stream has already been canceled this method has no effect.
-   */
+  /// Closes the receive port.
+  ///
+  /// No further events will be received by the receive port,
+  /// or emitted as stream events.
+  ///
+  /// If [listen] has been called and the [StreamSubscription] has not
+  /// been canceled yet, the subscription will be closed with a "done"
+  /// event.
+  ///
+  /// If the stream has already been canceled this method has no effect.
   void close();
 
-  /**
-   * Returns a [SendPort] that sends to this receive port.
-   */
+  /// A [SendPort] which sends messages to this receive port.
   SendPort get sendPort;
 }
 
+/// A low-level asynchronous message receiver.
+///
+/// A [RawReceivePort] is low level feature, and is not [Zone] aware.
+/// The [handler] will always be invoked  in the [Zone.root] zone.
+///
+/// The port cannot be paused. The data-handler must be set before the first
+/// messsage is received, otherwise the message is lost.
+///
+/// Messages can be sent to this port using [sendPort].
 abstract class RawReceivePort {
-  /**
-   * Opens a long-lived port for receiving messages.
-   *
-   * A [RawReceivePort] is low level and does not work with [Zone]s. It
-   * can not be paused. The data-handler must be set before the first
-   * event is received.
-   *
-   * The optional `debugName` parameter can be set to associate a name with
-   * this port that can be displayed in tooling.
-   *
-   */
+  /// Opens a long-lived port for receiving messages.
+  ///
+  /// A [RawReceivePort] is low level and does not work with [Zone]s. It
+  /// cannot be paused. The data-handler must be set before the first
+  /// messsage is received, otherwise the message is lost.
+  ///
+  /// If [handler] is provided, it's set as the [RawReceivePort.handler].
+  ///
+  /// The optional `debugName` parameter can be set to associate a name with
+  /// this port that can be displayed in tooling.
   external factory RawReceivePort([Function? handler, String debugName = '']);
 
-  /**
-   * Sets the handler that is invoked for every incoming message.
-   *
-   * The handler is invoked in the root-zone ([Zone.root]).
-   */
+  /// Sets the handler that is invoked for every incoming message.
+  ///
+  /// The handler is invoked in the [Zone.root] zone.
+  /// If the handler should be invoked in the current zone, do:
+  /// ```dart
+  /// rawPort.handler = Zone.current.bind(actualHandler);
+  /// ```
+  ///
+  /// The handler must be a function which can accept one argument
+  /// of the type of the messages sent to this port.
+  /// This means that if it is known that messages will all be [String]s,
+  /// a handler of type `void Function(String)` can be used.
+  /// The function is invoked dynamically with the actual messages,
+  /// and if this invocation fails,
+  /// the error becomes a top-level uncaught error in the [Zone.root] zone.
+  // TODO(44659): Change parameter type to `void Function(Never)` to only
+  // accept functions which can be called with one argument.
   void set handler(Function? newHandler);
 
-  /**
-   * Closes the port.
-   *
-   * After a call to this method any incoming message is silently dropped.
-   */
+  /// Closes the port.
+  ///
+  /// After a call to this method, any incoming message is silently dropped.
+  /// The [handler] will never be called again.
   void close();
 
-  /**
-   * Returns a [SendPort] that sends to this raw receive port.
-   */
+  /// Returns a [SendPort] that sends messages to this raw receive port.
   SendPort get sendPort;
 }
 
-/**
- * Description of an error from another isolate.
- *
- * This error has the same `toString()` and `stackTrace.toString()` behavior
- * as the original error, but has no other features of the original error.
- */
+/// Description of an error from another isolate.
+///
+/// This error has the same `toString()` and `stackTrace.toString()` behavior
+/// as the original error, but has no other features of the original error.
 class RemoteError implements Error {
   final String _description;
   final StackTrace stackTrace;
@@ -763,35 +717,29 @@
   String toString() => _description;
 }
 
-/**
- * An efficiently transferable sequence of byte values.
- *
- * A [TransferableTypedData] is created from a number of bytes.
- * This will take time proportional to the number of bytes.
- *
- * The [TransferableTypedData] can be moved between isolates, so
- * sending it through a send port will only take constant time.
- *
- * When sent this way, the local transferable can no longer be materialized,
- * and the received object is now the only way to materialize the data.
- */
+/// An efficiently transferable sequence of byte values.
+///
+/// A [TransferableTypedData] is created from a number of bytes.
+/// This will take time proportional to the number of bytes.
+///
+/// The [TransferableTypedData] can be moved between isolates, so
+/// sending it through a send port will only take constant time.
+///
+/// When sent this way, the local transferable can no longer be materialized,
+/// and the received object is now the only way to materialize the data.
 @Since("2.3.2")
 abstract class TransferableTypedData {
-  /**
-   * Creates a new [TransferableTypedData] containing the bytes of [list].
-   *
-   * It must be possible to create a single [Uint8List] containing the
-   * bytes, so if there are more bytes than what the platform allows in
-   * a single [Uint8List], then creation fails.
-   */
+  /// Creates a new [TransferableTypedData] containing the bytes of [list].
+  ///
+  /// It must be possible to create a single [Uint8List] containing the
+  /// bytes, so if there are more bytes than what the platform allows in
+  /// a single [Uint8List], then creation fails.
   external factory TransferableTypedData.fromList(List<TypedData> list);
 
-  /**
-   * Creates a new [ByteBuffer] containing the bytes stored in this [TransferableTypedData].
-   *
-   * The [TransferableTypedData] is a cross-isolate single-use resource.
-   * This method must not be called more than once on the same underlying
-   * transferable bytes, even if the calls occur in different isolates.
-   */
+  /// Creates a new [ByteBuffer] containing the bytes stored in this [TransferableTypedData].
+  ///
+  /// The [TransferableTypedData] is a cross-isolate single-use resource.
+  /// This method must not be called more than once on the same underlying
+  /// transferable bytes, even if the calls occur in different isolates.
   ByteBuffer materialize();
 }
diff --git a/sdk/lib/js_util/js_util.dart b/sdk/lib/js_util/js_util.dart
index 605f6d6..b1d0e27 100644
--- a/sdk/lib/js_util/js_util.dart
+++ b/sdk/lib/js_util/js_util.dart
@@ -14,7 +14,8 @@
 import 'dart:_foreign_helper' show JS;
 import 'dart:collection' show HashMap;
 import 'dart:async' show Completer;
-import 'dart:_js_helper' show convertDartClosureToJS;
+import 'dart:_js_helper'
+    show convertDartClosureToJS, assertInterop, assertInteropArgs;
 
 /// Recursively converts a JSON-like collection to JavaScript compatible
 /// representation.
@@ -70,11 +71,15 @@
 dynamic getProperty(Object o, Object name) =>
     JS('Object|Null', '#[#]', o, name);
 
-dynamic setProperty(Object o, Object name, Object? value) =>
-    JS('', '#[#]=#', o, name, value);
+dynamic setProperty(Object o, Object name, Object? value) {
+  assertInterop(value);
+  return JS('', '#[#]=#', o, name, value);
+}
 
-dynamic callMethod(Object o, String method, List<Object?> args) =>
-    JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
+dynamic callMethod(Object o, String method, List<Object?> args) {
+  assertInteropArgs(args);
+  return JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
+}
 
 /// Check whether [o] is an instance of [type].
 ///
@@ -83,9 +88,11 @@
 bool instanceof(Object? o, Object type) =>
     JS('bool', '# instanceof #', o, type);
 
-dynamic callConstructor(Object constr, List<Object?> arguments) {
+dynamic callConstructor(Object constr, List<Object?>? arguments) {
   if (arguments == null) {
     return JS('Object', 'new #()', constr);
+  } else {
+    assertInteropArgs(arguments);
   }
 
   if (JS('bool', '# instanceof Array', arguments)) {
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 0b9d207..8f584e2 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -86,6 +86,7 @@
         "uri": "ffi/ffi.dart",
         "patches": [
           "_internal/vm/lib/ffi_patch.dart",
+          "_internal/vm/lib/ffi_allocation_patch.dart",
           "_internal/vm/lib/ffi_dynamic_library_patch.dart",
           "_internal/vm/lib/ffi_native_type_patch.dart",
           "_internal/vm/lib/ffi_struct_patch.dart"
@@ -470,4 +471,4 @@
       }
     }
   }
-}
\ No newline at end of file
+}
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index f6cb8c3..89e3640 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -91,6 +91,7 @@
       uri: "ffi/ffi.dart"
       patches:
         - "_internal/vm/lib/ffi_patch.dart"
+        - "_internal/vm/lib/ffi_allocation_patch.dart"
         - "_internal/vm/lib/ffi_dynamic_library_patch.dart"
         - "_internal/vm/lib/ffi_native_type_patch.dart"
         - "_internal/vm/lib/ffi_struct_patch.dart"
diff --git a/sdk/lib/math/math.dart b/sdk/lib/math/math.dart
index 8f847b1..ad1da4d 100644
--- a/sdk/lib/math/math.dart
+++ b/sdk/lib/math/math.dart
@@ -5,9 +5,9 @@
 /// Mathematical constants and functions, plus a random number generator.
 ///
 /// To use this library in your code:
-///
-///     import 'dart:math';
-///
+/// ```dart
+/// import 'dart:math';
+/// ```
 /// {@category Core}
 library dart.math;
 
diff --git a/sdk/lib/math/point.dart b/sdk/lib/math/point.dart
index f092fc8..b3e9432 100644
--- a/sdk/lib/math/point.dart
+++ b/sdk/lib/math/point.dart
@@ -9,6 +9,7 @@
   final T x;
   final T y;
 
+  /// Creates a point with the provided [x] and [y] coordinates.
   const Point(T x, T y)
       : this.x = x,
         this.y = y;
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 95a8aff..8363b4a 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -49,9 +49,8 @@
  * ## Status: Unstable
  *
  * The dart:mirrors library is unstable and its API might change slightly as a
- * result of user feedback. This library is platform dependent and therefore it
- * has implementations for both dart2js and the Dart VM. Both are under
- * development and may not support all operations yet.
+ * result of user feedback. This library is only supported by the Dart VM and
+ * only available on some platforms.
  *
  * {@category VM}
  */
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index c796465..20d17f8 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -6,9 +6,9 @@
 /// (for example, unsigned 8 byte integers) and SIMD numeric types.
 ///
 /// To use this library in your code:
-///
-///     import 'dart:typed_data';
-///
+/// ```dart
+/// import 'dart:typed_data';
+/// ```
 /// {@category Core}
 library dart.typed_data;
 
@@ -18,407 +18,357 @@
 
 part "unmodifiable_typed_data.dart";
 
-/**
- * A sequence of bytes underlying a typed data object.
- *
- * Used to process large quantities of binary or numerical data
- * more efficiently using a typed view.
- */
+/// A sequence of bytes underlying a typed data object.
+///
+/// Used to process large quantities of binary or numerical data
+/// more efficiently using a typed view.
 abstract class ByteBuffer {
-  /**
-   * Returns the length of this byte buffer, in bytes.
-   */
+  /// Returns the length of this byte buffer, in bytes.
   int get lengthInBytes;
 
-  /**
-   * Creates a [Uint8List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Uint8List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes] and contains [length] bytes.
-   * If [length] is omitted, the range extends to the end of the buffer.
-   *
-   * The start index and length must describe a valid range of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Uint8List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Uint8List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes] and contains [length] bytes.
+  /// If [length] is omitted, the range extends to the end of the buffer.
+  ///
+  /// The start index and length must describe a valid range of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length` must not be greater than [lengthInBytes].
   Uint8List asUint8List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Int8List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Int8List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes] and contains [length] bytes.
-   * If [length] is omitted, the range extends to the end of the buffer.
-   *
-   * The start index and length must describe a valid range of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Int8List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Int8List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes] and contains [length] bytes.
+  /// If [length] is omitted, the range extends to the end of the buffer.
+  ///
+  /// The start index and length must describe a valid range of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length` must not be greater than [lengthInBytes].
   Int8List asInt8List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Uint8ClampedList] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Uint8ClampedList` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes] and contains [length] bytes.
-   * If [length] is omitted, the range extends to the end of the buffer.
-   *
-   * The start index and length must describe a valid range of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Uint8ClampedList] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Uint8ClampedList` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes] and contains [length] bytes.
+  /// If [length] is omitted, the range extends to the end of the buffer.
+  ///
+  /// The start index and length must describe a valid range of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length` must not be greater than [lengthInBytes].
   Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Uint16List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Uint16List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 16-bit aligned,
-   * and contains [length] 16-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not even, the last byte can't be part of the view.
-   *
-   * The start index and length must describe a valid 16-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by two,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 2` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Uint16List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Uint16List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 16-bit aligned,
+  /// and contains [length] 16-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not even, the last byte can't be part of the view.
+  ///
+  /// The start index and length must describe a valid 16-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by two,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 2` must not be greater than [lengthInBytes].
   Uint16List asUint16List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Int16List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Int16List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 16-bit aligned,
-   * and contains [length] 16-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not even, the last byte can't be part of the view.
-   *
-   * The start index and length must describe a valid 16-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by two,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 2` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Int16List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Int16List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 16-bit aligned,
+  /// and contains [length] 16-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not even, the last byte can't be part of the view.
+  ///
+  /// The start index and length must describe a valid 16-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by two,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 2` must not be greater than [lengthInBytes].
   Int16List asInt16List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Uint32List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Uint32List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 32-bit aligned,
-   * and contains [length] 32-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by four, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 32-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by four,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Uint32List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Uint32List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 32-bit aligned,
+  /// and contains [length] 32-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by four, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 32-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by four,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
   Uint32List asUint32List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Int32List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Int32List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 32-bit aligned,
-   * and contains [length] 32-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by four, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 32-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by four,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Int32List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Int32List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 32-bit aligned,
+  /// and contains [length] 32-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by four, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 32-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by four,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
   Int32List asInt32List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Uint64List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Uint64List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 64-bit aligned,
-   * and contains [length] 64-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by eight, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 64-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by eight,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Uint64List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Uint64List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 64-bit aligned,
+  /// and contains [length] 64-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by eight, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 64-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by eight,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
   Uint64List asUint64List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Int64List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Int64List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 64-bit aligned,
-   * and contains [length] 64-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by eight, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 64-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by eight,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Int64List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Int64List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 64-bit aligned,
+  /// and contains [length] 64-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by eight, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 64-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by eight,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
   Int64List asInt64List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Int32x4List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Int32x4List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 128-bit aligned,
-   * and contains [length] 128-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by 16, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 128-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by sixteen,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Int32x4List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Int32x4List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 128-bit aligned,
+  /// and contains [length] 128-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by 16, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 128-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by sixteen,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
   Int32x4List asInt32x4List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Float32List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Float32List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 32-bit aligned,
-   * and contains [length] 32-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by four, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 32-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by four,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Float32List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Float32List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 32-bit aligned,
+  /// and contains [length] 32-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by four, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 32-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by four,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
   Float32List asFloat32List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Float64List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Float64List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 64-bit aligned,
-   * and contains [length] 64-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by eight, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 64-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by eight,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Float64List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Float64List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 64-bit aligned,
+  /// and contains [length] 64-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by eight, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 64-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by eight,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
   Float64List asFloat64List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Float32x4List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Float32x4List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 128-bit aligned,
-   * and contains [length] 128-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by 16, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 128-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by sixteen,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Float32x4List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Float32x4List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 128-bit aligned,
+  /// and contains [length] 128-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by 16, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 128-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by sixteen,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
   Float32x4List asFloat32x4List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [Float64x2List] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `Float64x2List` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes], which must be 128-bit aligned,
-   * and contains [length] 128-bit integers.
-   * If [length] is omitted, the range extends as far towards the end of
-   * the buffer as possible -
-   * if [lengthInBytes] is not divisible by 16, the last bytes can't be part
-   * of the view.
-   *
-   * The start index and length must describe a valid 128-bit aligned range
-   * of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `offsetInBytes` must be divisible by sixteen,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [Float64x2List] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `Float64x2List` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes], which must be 128-bit aligned,
+  /// and contains [length] 128-bit integers.
+  /// If [length] is omitted, the range extends as far towards the end of
+  /// the buffer as possible -
+  /// if [lengthInBytes] is not divisible by 16, the last bytes can't be part
+  /// of the view.
+  ///
+  /// The start index and length must describe a valid 128-bit aligned range
+  /// of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `offsetInBytes` must be divisible by sixteen,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
   Float64x2List asFloat64x2List([int offsetInBytes = 0, int? length]);
 
-  /**
-   * Creates a [ByteData] _view_ of a region of this byte buffer.
-   *
-   * The view is backed by the bytes of this byte buffer.
-   * Any changes made to the `ByteData` will also change the buffer,
-   * and vice versa.
-   *
-   * The viewed region start at [offsetInBytes] and contains [length] bytes.
-   * If [length] is omitted, the range extends to the end of the buffer.
-   *
-   * The start index and length must describe a valid range of the buffer:
-   *
-   * * `offsetInBytes` must not be negative,
-   * * `length` must not be negative, and
-   * * `offsetInBytes + length` must not be greater than [lengthInBytes].
-   */
+  /// Creates a [ByteData] _view_ of a region of this byte buffer.
+  ///
+  /// The view is backed by the bytes of this byte buffer.
+  /// Any changes made to the `ByteData` will also change the buffer,
+  /// and vice versa.
+  ///
+  /// The viewed region start at [offsetInBytes] and contains [length] bytes.
+  /// If [length] is omitted, the range extends to the end of the buffer.
+  ///
+  /// The start index and length must describe a valid range of the buffer:
+  ///
+  /// * `offsetInBytes` must not be negative,
+  /// * `length` must not be negative, and
+  /// * `offsetInBytes + length` must not be greater than [lengthInBytes].
   ByteData asByteData([int offsetInBytes = 0, int? length]);
 }
 
-/**
- * A typed view of a sequence of bytes.
- */
+/// A typed view of a sequence of bytes.
 abstract class TypedData {
-  /**
-   * Returns the number of bytes in the representation of each element in this
-   * list.
-   */
+  /// Returns the number of bytes in the representation of each element in this
+  /// list.
   int get elementSizeInBytes;
 
-  /**
-   * Returns the offset in bytes into the underlying byte buffer of this view.
-   */
+  /// Returns the offset in bytes into the underlying byte buffer of this view.
   int get offsetInBytes;
 
-  /**
-   * Returns the length of this view, in bytes.
-   */
+  /// Returns the length of this view, in bytes.
   int get lengthInBytes;
 
-  /**
-   * Returns the byte buffer associated with this object.
-   */
+  /// Returns the byte buffer associated with this object.
   ByteBuffer get buffer;
 }
 
 abstract class _TypedIntList extends TypedData {
-  /**
-   * Returns the concatenation of this list and [other].
-   *
-   * If other is also a typed-data integer list, the returned list will
-   * be a type-data integer list capable of containing all the elements of
-   * this list and of [other].
-   * Otherwise the returned list will be a normal growable `List<int>`.
-   */
+  /// Returns the concatenation of this list and [other].
+  ///
+  /// If other is also a typed-data integer list, the returned list will
+  /// be a type-data integer list capable of containing all the elements of
+  /// this list and of [other].
+  /// Otherwise the returned list will be a normal growable `List<int>`.
   List<int> operator +(List<int> other);
 }
 
 abstract class _TypedFloatList extends TypedData {
-  /**
-   * Returns the concatenation of this list and [other].
-   *
-   * If other is also a typed-data floating point number list,
-   * the returned list will be a type-data float list capable of containing
-   * all the elements of this list and of [other].
-   * Otherwise the returned list will be a normal growable `List<double>`.
-   */
+  /// Returns the concatenation of this list and [other].
+  ///
+  /// If other is also a typed-data floating point number list,
+  /// the returned list will be a type-data float list capable of containing
+  /// all the elements of this list and of [other].
+  /// Otherwise the returned list will be a normal growable `List<double>`.
   List<double> operator +(List<double> other);
 }
 
-/**
- * Describes endianness to be used when accessing or updating a
- * sequence of bytes.
- */
+/// Describes endianness to be used when accessing or updating a
+/// sequence of bytes.
 class Endian {
   final bool _littleEndian;
   const Endian._(this._littleEndian);
@@ -431,102 +381,94 @@
           : big;
 }
 
-/**
- * A fixed-length, random-access sequence of bytes that also provides random
- * and unaligned access to the fixed-width integers and floating point
- * numbers represented by those bytes.
- *
- * `ByteData` may be used to pack and unpack data from external sources
- * (such as networks or files systems), and to process large quantities
- * of numerical data more efficiently than would be possible
- * with ordinary [List] implementations.
- * `ByteData` can save space, by eliminating the need for object headers,
- * and time, by eliminating the need for data copies.
- *
- * If data comes in as bytes, they can be converted to `ByteData` by
- * sharing the same buffer.
- * ```dart
- * Uint8List bytes = ...;
- * var blob = ByteData.sublistView(bytes);
- * if (blob.getUint32(0, Endian.little) == 0x04034b50) { // Zip file marker
- *   ...
- * }
- *
- * ```
- *
- * Finally, `ByteData` may be used to intentionally reinterpret the bytes
- * representing one arithmetic type as another.
- * For example this code fragment determine what 32-bit signed integer
- * is represented by the bytes of a 32-bit floating point number
- * (both stored as big endian):
- * ```dart
- * var bdata = new ByteData(8);
- * bdata.setFloat32(0, 3.04);
- * int huh = bdata.getInt32(0); // 0x40428f5c
- * ```
- */
+/// A fixed-length, random-access sequence of bytes that also provides random
+/// and unaligned access to the fixed-width integers and floating point
+/// numbers represented by those bytes.
+///
+/// `ByteData` may be used to pack and unpack data from external sources
+/// (such as networks or files systems), and to process large quantities
+/// of numerical data more efficiently than would be possible
+/// with ordinary [List] implementations.
+/// `ByteData` can save space, by eliminating the need for object headers,
+/// and time, by eliminating the need for data copies.
+///
+/// If data comes in as bytes, they can be converted to `ByteData` by
+/// sharing the same buffer.
+/// ```dart
+/// Uint8List bytes = ...;
+/// var blob = ByteData.sublistView(bytes);
+/// if (blob.getUint32(0, Endian.little) == 0x04034b50) { // Zip file marker
+///   ...
+/// }
+///
+/// ```
+///
+/// Finally, `ByteData` may be used to intentionally reinterpret the bytes
+/// representing one arithmetic type as another.
+/// For example this code fragment determine what 32-bit signed integer
+/// is represented by the bytes of a 32-bit floating point number
+/// (both stored as big endian):
+/// ```dart
+/// var bdata = ByteData(8);
+/// bdata.setFloat32(0, 3.04);
+/// int huh = bdata.getInt32(0); // 0x40428f5c
+/// ```
 abstract class ByteData implements TypedData {
-  /**
-   * Creates a [ByteData] of the specified length (in elements), all of
-   * whose bytes are initially zero.
-   */
+  /// Creates a [ByteData] of the specified length (in elements), all of
+  /// whose bytes are initially zero.
   @pragma("vm:entry-point")
   external factory ByteData(int length);
 
-  /**
-   * Creates an [ByteData] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [ByteData] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `ByteData.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * ByteData.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [ByteData.sublistView]
-   * which includes this computation:
-   * ```dart
-   * ByteData.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates an [ByteData] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [ByteData] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + [length] must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `ByteData.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// ByteData.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [ByteData.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// ByteData.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory ByteData.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asByteData(offsetInBytes, length);
   }
 
-  /**
-   * Creates a [ByteData] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   */
+  /// Creates a [ByteData] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
   @Since("2.8")
   factory ByteData.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -538,341 +480,291 @@
         data.offsetInBytes + start * elementSize, (end - start) * elementSize);
   }
 
-  /**
-   * Returns the (possibly negative) integer represented by the byte at the
-   * specified [byteOffset] in this object, in two's complement binary
-   * representation.
-   *
-   * The return value will be between -128 and 127, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * less than the length of this object.
-   */
+  /// Returns the (possibly negative) integer represented by the byte at the
+  /// specified [byteOffset] in this object, in two's complement binary
+  /// representation.
+  ///
+  /// The return value will be between -128 and 127, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// less than the length of this object.
   int getInt8(int byteOffset);
 
-  /**
-   * Sets the byte at the specified [byteOffset] in this object to the
-   * two's complement binary representation of the specified [value], which
-   * must fit in a single byte.
-   *
-   * In other words, [value] must be between -128 and 127, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * less than the length of this object.
-   */
+  /// Sets the byte at the specified [byteOffset] in this object to the
+  /// two's complement binary representation of the specified [value], which
+  /// must fit in a single byte.
+  ///
+  /// In other words, [value] must be between -128 and 127, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// less than the length of this object.
   void setInt8(int byteOffset, int value);
 
-  /**
-   * Returns the positive integer represented by the byte at the specified
-   * [byteOffset] in this object, in unsigned binary form.
-   *
-   * The return value will be between 0 and 255, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * less than the length of this object.
-   */
+  /// Returns the positive integer represented by the byte at the specified
+  /// [byteOffset] in this object, in unsigned binary form.
+  ///
+  /// The return value will be between 0 and 255, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// less than the length of this object.
   int getUint8(int byteOffset);
 
-  /**
-   * Sets the byte at the specified [byteOffset] in this object to the
-   * unsigned binary representation of the specified [value], which must fit
-   * in a single byte.
-   *
-   * In other words, [value] must be between 0 and 255, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * less than the length of this object.
-   */
+  /// Sets the byte at the specified [byteOffset] in this object to the
+  /// unsigned binary representation of the specified [value], which must fit
+  /// in a single byte.
+  ///
+  /// In other words, [value] must be between 0 and 255, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// less than the length of this object.
   void setUint8(int byteOffset, int value);
 
-  /**
-   * Returns the (possibly negative) integer represented by the two bytes at
-   * the specified [byteOffset] in this object, in two's complement binary
-   * form.
-   *
-   * The return value will be between -2<sup>15</sup> and 2<sup>15</sup> - 1,
-   * inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 2` must be less than or equal to the length of this object.
-   */
+  /// Returns the (possibly negative) integer represented by the two bytes at
+  /// the specified [byteOffset] in this object, in two's complement binary
+  /// form.
+  ///
+  /// The return value will be between -2<sup>15</sup> and 2<sup>15</sup> - 1,
+  /// inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 2` must be less than or equal to the length of this object.
   int getInt16(int byteOffset, [Endian endian = Endian.big]);
 
-  /**
-   * Sets the two bytes starting at the specified [byteOffset] in this
-   * object to the two's complement binary representation of the specified
-   * [value], which must fit in two bytes.
-   *
-   * In other words, [value] must lie
-   * between -2<sup>15</sup> and 2<sup>15</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 2` must be less than or equal to the length of this object.
-   */
+  /// Sets the two bytes starting at the specified [byteOffset] in this
+  /// object to the two's complement binary representation of the specified
+  /// [value], which must fit in two bytes.
+  ///
+  /// In other words, [value] must lie
+  /// between -2<sup>15</sup> and 2<sup>15</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 2` must be less than or equal to the length of this object.
   void setInt16(int byteOffset, int value, [Endian endian = Endian.big]);
 
-  /**
-   * Returns the positive integer represented by the two bytes starting
-   * at the specified [byteOffset] in this object, in unsigned binary
-   * form.
-   *
-   * The return value will be between 0 and  2<sup>16</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 2` must be less than or equal to the length of this object.
-   */
+  /// Returns the positive integer represented by the two bytes starting
+  /// at the specified [byteOffset] in this object, in unsigned binary
+  /// form.
+  ///
+  /// The return value will be between 0 and  2<sup>16</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 2` must be less than or equal to the length of this object.
   int getUint16(int byteOffset, [Endian endian = Endian.big]);
 
-  /**
-   * Sets the two bytes starting at the specified [byteOffset] in this object
-   * to the unsigned binary representation of the specified [value],
-   * which must fit in two bytes.
-   *
-   * In other words, [value] must be between
-   * 0 and 2<sup>16</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 2` must be less than or equal to the length of this object.
-   */
+  /// Sets the two bytes starting at the specified [byteOffset] in this object
+  /// to the unsigned binary representation of the specified [value],
+  /// which must fit in two bytes.
+  ///
+  /// In other words, [value] must be between
+  /// 0 and 2<sup>16</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 2` must be less than or equal to the length of this object.
   void setUint16(int byteOffset, int value, [Endian endian = Endian.big]);
 
-  /**
-   * Returns the (possibly negative) integer represented by the four bytes at
-   * the specified [byteOffset] in this object, in two's complement binary
-   * form.
-   *
-   * The return value will be between -2<sup>31</sup> and 2<sup>31</sup> - 1,
-   * inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 4` must be less than or equal to the length of this object.
-   */
+  /// Returns the (possibly negative) integer represented by the four bytes at
+  /// the specified [byteOffset] in this object, in two's complement binary
+  /// form.
+  ///
+  /// The return value will be between -2<sup>31</sup> and 2<sup>31</sup> - 1,
+  /// inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 4` must be less than or equal to the length of this object.
   int getInt32(int byteOffset, [Endian endian = Endian.big]);
 
-  /**
-   * Sets the four bytes starting at the specified [byteOffset] in this
-   * object to the two's complement binary representation of the specified
-   * [value], which must fit in four bytes.
-   *
-   * In other words, [value] must lie
-   * between -2<sup>31</sup> and 2<sup>31</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 4` must be less than or equal to the length of this object.
-   */
+  /// Sets the four bytes starting at the specified [byteOffset] in this
+  /// object to the two's complement binary representation of the specified
+  /// [value], which must fit in four bytes.
+  ///
+  /// In other words, [value] must lie
+  /// between -2<sup>31</sup> and 2<sup>31</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 4` must be less than or equal to the length of this object.
   void setInt32(int byteOffset, int value, [Endian endian = Endian.big]);
 
-  /**
-   * Returns the positive integer represented by the four bytes starting
-   * at the specified [byteOffset] in this object, in unsigned binary
-   * form.
-   *
-   * The return value will be between 0 and  2<sup>32</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 4` must be less than or equal to the length of this object.
-   */
+  /// Returns the positive integer represented by the four bytes starting
+  /// at the specified [byteOffset] in this object, in unsigned binary
+  /// form.
+  ///
+  /// The return value will be between 0 and  2<sup>32</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 4` must be less than or equal to the length of this object.
   int getUint32(int byteOffset, [Endian endian = Endian.big]);
 
-  /**
-   * Sets the four bytes starting at the specified [byteOffset] in this object
-   * to the unsigned binary representation of the specified [value],
-   * which must fit in four bytes.
-   *
-   * In other words, [value] must be between
-   * 0 and 2<sup>32</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 4` must be less than or equal to the length of this object.
-   */
+  /// Sets the four bytes starting at the specified [byteOffset] in this object
+  /// to the unsigned binary representation of the specified [value],
+  /// which must fit in four bytes.
+  ///
+  /// In other words, [value] must be between
+  /// 0 and 2<sup>32</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 4` must be less than or equal to the length of this object.
   void setUint32(int byteOffset, int value, [Endian endian = Endian.big]);
 
-  /**
-   * Returns the (possibly negative) integer represented by the eight bytes at
-   * the specified [byteOffset] in this object, in two's complement binary
-   * form.
-   *
-   * The return value will be between -2<sup>63</sup> and 2<sup>63</sup> - 1,
-   * inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 8` must be less than or equal to the length of this object.
-   */
+  /// Returns the (possibly negative) integer represented by the eight bytes at
+  /// the specified [byteOffset] in this object, in two's complement binary
+  /// form.
+  ///
+  /// The return value will be between -2<sup>63</sup> and 2<sup>63</sup> - 1,
+  /// inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 8` must be less than or equal to the length of this object.
   int getInt64(int byteOffset, [Endian endian = Endian.big]);
 
-  /**
-   * Sets the eight bytes starting at the specified [byteOffset] in this
-   * object to the two's complement binary representation of the specified
-   * [value], which must fit in eight bytes.
-   *
-   * In other words, [value] must lie
-   * between -2<sup>63</sup> and 2<sup>63</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 8` must be less than or equal to the length of this object.
-   */
+  /// Sets the eight bytes starting at the specified [byteOffset] in this
+  /// object to the two's complement binary representation of the specified
+  /// [value], which must fit in eight bytes.
+  ///
+  /// In other words, [value] must lie
+  /// between -2<sup>63</sup> and 2<sup>63</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 8` must be less than or equal to the length of this object.
   void setInt64(int byteOffset, int value, [Endian endian = Endian.big]);
 
-  /**
-   * Returns the positive integer represented by the eight bytes starting
-   * at the specified [byteOffset] in this object, in unsigned binary
-   * form.
-   *
-   * The return value will be between 0 and  2<sup>64</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 8` must be less than or equal to the length of this object.
-   */
+  /// Returns the positive integer represented by the eight bytes starting
+  /// at the specified [byteOffset] in this object, in unsigned binary
+  /// form.
+  ///
+  /// The return value will be between 0 and  2<sup>64</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 8` must be less than or equal to the length of this object.
   int getUint64(int byteOffset, [Endian endian = Endian.big]);
 
-  /**
-   * Sets the eight bytes starting at the specified [byteOffset] in this object
-   * to the unsigned binary representation of the specified [value],
-   * which must fit in eight bytes.
-   *
-   * In other words, [value] must be between
-   * 0 and 2<sup>64</sup> - 1, inclusive.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 8` must be less than or equal to the length of this object.
-   */
+  /// Sets the eight bytes starting at the specified [byteOffset] in this object
+  /// to the unsigned binary representation of the specified [value],
+  /// which must fit in eight bytes.
+  ///
+  /// In other words, [value] must be between
+  /// 0 and 2<sup>64</sup> - 1, inclusive.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 8` must be less than or equal to the length of this object.
   void setUint64(int byteOffset, int value, [Endian endian = Endian.big]);
 
-  /**
-   * Returns the floating point number represented by the four bytes at
-   * the specified [byteOffset] in this object, in IEEE 754
-   * single-precision binary floating-point format (binary32).
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 4` must be less than or equal to the length of this object.
-   */
+  /// Returns the floating point number represented by the four bytes at
+  /// the specified [byteOffset] in this object, in IEEE 754
+  /// single-precision binary floating-point format (binary32).
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 4` must be less than or equal to the length of this object.
   double getFloat32(int byteOffset, [Endian endian = Endian.big]);
 
-  /**
-   * Sets the four bytes starting at the specified [byteOffset] in this
-   * object to the IEEE 754 single-precision binary floating-point
-   * (binary32) representation of the specified [value].
-   *
-   * **Note that this method can lose precision.** The input [value] is
-   * a 64-bit floating point value, which will be converted to 32-bit
-   * floating point value by IEEE 754 rounding rules before it is stored.
-   * If [value] cannot be represented exactly as a binary32, it will be
-   * converted to the nearest binary32 value.  If two binary32 values are
-   * equally close, the one whose least significant bit is zero will be used.
-   * Note that finite (but large) values can be converted to infinity, and
-   * small non-zero values can be converted to zero.
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 4` must be less than or equal to the length of this object.
-   */
+  /// Sets the four bytes starting at the specified [byteOffset] in this
+  /// object to the IEEE 754 single-precision binary floating-point
+  /// (binary32) representation of the specified [value].
+  ///
+  /// **Note that this method can lose precision.** The input [value] is
+  /// a 64-bit floating point value, which will be converted to 32-bit
+  /// floating point value by IEEE 754 rounding rules before it is stored.
+  /// If [value] cannot be represented exactly as a binary32, it will be
+  /// converted to the nearest binary32 value.  If two binary32 values are
+  /// equally close, the one whose least significant bit is zero will be used.
+  /// Note that finite (but large) values can be converted to infinity, and
+  /// small non-zero values can be converted to zero.
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 4` must be less than or equal to the length of this object.
   void setFloat32(int byteOffset, double value, [Endian endian = Endian.big]);
 
-  /**
-   * Returns the floating point number represented by the eight bytes at
-   * the specified [byteOffset] in this object, in IEEE 754
-   * double-precision binary floating-point format (binary64).
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 8` must be less than or equal to the length of this object.
-   */
+  /// Returns the floating point number represented by the eight bytes at
+  /// the specified [byteOffset] in this object, in IEEE 754
+  /// double-precision binary floating-point format (binary64).
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 8` must be less than or equal to the length of this object.
   double getFloat64(int byteOffset, [Endian endian = Endian.big]);
 
-  /**
-   * Sets the eight bytes starting at the specified [byteOffset] in this
-   * object to the IEEE 754 double-precision binary floating-point
-   * (binary64) representation of the specified [value].
-   *
-   * The [byteOffset] must be non-negative, and
-   * `byteOffset + 8` must be less than or equal to the length of this object.
-   */
+  /// Sets the eight bytes starting at the specified [byteOffset] in this
+  /// object to the IEEE 754 double-precision binary floating-point
+  /// (binary64) representation of the specified [value].
+  ///
+  /// The [byteOffset] must be non-negative, and
+  /// `byteOffset + 8` must be less than or equal to the length of this object.
   void setFloat64(int byteOffset, double value, [Endian endian = Endian.big]);
 }
 
-/**
- * A fixed-length list of 8-bit signed integers.
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are truncated to their low eight bits,
- * interpreted as a signed 8-bit two's complement integer with values in the
- * range -128 to +127.
- */
+/// A fixed-length list of 8-bit signed integers.
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are truncated to their low eight bits,
+/// interpreted as a signed 8-bit two's complement integer with values in the
+/// range -128 to +127.
 abstract class Int8List implements List<int>, _TypedIntList {
-  /**
-   * Creates an [Int8List] of the specified length (in elements), all of
-   * whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely [length] bytes.
-   */
+  /// Creates an [Int8List] of the specified length (in elements), all of
+  /// whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely [length] bytes.
   external factory Int8List(int length);
 
-  /**
-   * Creates a [Int8List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely `elements.length`
-   * bytes.
-   */
+  /// Creates a [Int8List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely `elements.length`
+  /// bytes.
   external factory Int8List.fromList(List<int> elements);
 
-  /**
-   * Creates an [Int8List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Int8List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Int8List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Int8List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Int8List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Int8List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates an [Int8List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Int8List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Int8List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Int8List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Int8List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Int8List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Int8List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asInt8List(offsetInBytes, length);
   }
 
-  /**
-   * Creates an [Int8List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   */
+  /// Creates an [Int8List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
   @Since("2.8")
   factory Int8List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -883,119 +775,107 @@
         data.offsetInBytes + start * elementSize, (end - start) * elementSize);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is an `Int8List` containing the elements of this list at
-   * positions greater than or equal to [start] and less than [end] in the same
-   * order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Int8List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Int8List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is an `Int8List` containing the elements of this list at
+  /// positions greater than or equal to [start] and less than [end] in the same
+  /// order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Int8List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Int8List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Int8List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 1;
 }
 
-/**
- * A fixed-length list of 8-bit unsigned integers.
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are truncated to their low eight bits,
- * interpreted as an unsigned 8-bit integer with values in the
- * range 0 to 255.
- */
+/// A fixed-length list of 8-bit unsigned integers.
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are truncated to their low eight bits,
+/// interpreted as an unsigned 8-bit integer with values in the
+/// range 0 to 255.
 abstract class Uint8List implements List<int>, _TypedIntList {
-  /**
-   * Creates a [Uint8List] of the specified length (in elements), all of
-   * whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely [length] bytes.
-   */
+  /// Creates a [Uint8List] of the specified length (in elements), all of
+  /// whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely [length] bytes.
   external factory Uint8List(int length);
 
-  /**
-   * Creates a [Uint8List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely `elements.length`
-   * bytes.
-   */
+  /// Creates a [Uint8List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely `elements.length`
+  /// bytes.
   external factory Uint8List.fromList(List<int> elements);
 
-  /**
-   * Creates a [Uint8List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Uint8List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Uint8List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Uint8List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Uint8List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Uint8List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Uint8List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Uint8List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Uint8List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Uint8List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Uint8List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Uint8List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Uint8List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asUint8List(offsetInBytes, length);
   }
 
-  /**
-   * Creates a [Uint8List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   */
+  /// Creates a [Uint8List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
   @Since("2.8")
   factory Uint8List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -1006,129 +886,115 @@
         data.offsetInBytes + start * elementSize, (end - start) * elementSize);
   }
 
-  /**
-   * Returns a concatenation of this list and [other].
-   *
-   * If [other] is also a typed-data list, then the return list will be a
-   * typed data list capable of holding both unsigned 8-bit integers and
-   * the elements of [other], otherwise it'll be a normal list of integers.
-   */
+  /// Returns a concatenation of this list and [other].
+  ///
+  /// If [other] is also a typed-data list, then the return list will be a
+  /// typed data list capable of holding both unsigned 8-bit integers and
+  /// the elements of [other], otherwise it'll be a normal list of integers.
   List<int> operator +(List<int> other);
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Uint8List` containing the elements of this list at
-   * positions greater than or equal to [start] and less than [end] in the same
-   * order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Uint8List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Uint8List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Uint8List` containing the elements of this list at
+  /// positions greater than or equal to [start] and less than [end] in the same
+  /// order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Uint8List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Uint8List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Uint8List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 1;
 }
 
-/**
- * A fixed-length list of 8-bit unsigned integers.
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are clamped to an unsigned eight bit value.
- * That is, all values below zero are stored as zero
- * and all values above 255 are stored as 255.
- */
+/// A fixed-length list of 8-bit unsigned integers.
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are clamped to an unsigned eight bit value.
+/// That is, all values below zero are stored as zero
+/// and all values above 255 are stored as 255.
 abstract class Uint8ClampedList implements List<int>, _TypedIntList {
-  /**
-   * Creates a [Uint8ClampedList] of the specified length (in elements), all of
-   * whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely [length] bytes.
-   */
+  /// Creates a [Uint8ClampedList] of the specified length (in elements), all of
+  /// whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely [length] bytes.
   external factory Uint8ClampedList(int length);
 
-  /**
-   * Creates a [Uint8ClampedList] of the same size as the [elements]
-   * list and copies over the values clamping when needed.
-   *
-   * Values are clamped to fit in the list when they are copied,
-   * the same way storing values clamps them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely `elements.length`
-   * bytes.
-   */
+  /// Creates a [Uint8ClampedList] of the same size as the [elements]
+  /// list and copies over the values clamping when needed.
+  ///
+  /// Values are clamped to fit in the list when they are copied,
+  /// the same way storing values clamps them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely `elements.length`
+  /// bytes.
   external factory Uint8ClampedList.fromList(List<int> elements);
 
-  /**
-   * Creates a [Uint8ClampedList] _view_ of the specified region in the
-   * specified byte [buffer].
-   *
-   * Changes in the [Uint8List] will be visible in the byte buffer
-   * and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Uint8ClampedList.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Uint8ClampedList.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Uint8ClampedList.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Uint8ClampedList.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Uint8ClampedList] _view_ of the specified region in the
+  /// specified byte [buffer].
+  ///
+  /// Changes in the [Uint8List] will be visible in the byte buffer
+  /// and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Uint8ClampedList.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Uint8ClampedList.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Uint8ClampedList.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Uint8ClampedList.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Uint8ClampedList.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asUint8ClampedList(offsetInBytes, length);
   }
 
-  /**
-   * Creates a [Uint8ClampedList] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   */
+  /// Creates a [Uint8ClampedList] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
   @Since("2.8")
   factory Uint8ClampedList.sublistView(TypedData data,
       [int start = 0, int? end]) {
@@ -1140,126 +1006,114 @@
         data.offsetInBytes + start * elementSize, (end - start) * elementSize);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Uint8ClampedList` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Uint8ClampedList.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Uint8ClampedList
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Uint8ClampedList` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Uint8ClampedList.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Uint8ClampedList
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Uint8ClampedList sublist(int start, [int? end]);
 
   static const int bytesPerElement = 1;
 }
 
-/**
- * A fixed-length list of 16-bit signed integers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are truncated to their low 16 bits,
- * interpreted as a signed 16-bit two's complement integer with values in the
- * range -32768 to +32767.
- */
+/// A fixed-length list of 16-bit signed integers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are truncated to their low 16 bits,
+/// interpreted as a signed 16-bit two's complement integer with values in the
+/// range -32768 to +32767.
 abstract class Int16List implements List<int>, _TypedIntList {
-  /**
-   * Creates an [Int16List] of the specified length (in elements), all of
-   * whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 2 bytes.
-   */
+  /// Creates an [Int16List] of the specified length (in elements), all of
+  /// whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 2 bytes.
   external factory Int16List(int length);
 
-  /**
-   * Creates a [Int16List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 2 bytes.
-   */
+  /// Creates a [Int16List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 2 bytes.
   external factory Int16List.fromList(List<int> elements);
 
-  /**
-   * Creates an [Int16List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Int16List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Int16List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Int16List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Int16List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Int16List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates an [Int16List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Int16List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Int16List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Int16List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Int16List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Int16List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Int16List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asInt16List(offsetInBytes, length);
   }
 
-  /**
-   * Creates an [Int16List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of two.
-   */
+  /// Creates an [Int16List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of two.
   @Since("2.8")
   factory Int16List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -1275,127 +1129,115 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is an `Int16List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Int16List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Int16List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is an `Int16List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Int16List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Int16List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Int16List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 2;
 }
 
-/**
- * A fixed-length list of 16-bit unsigned integers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are truncated to their low 16 bits,
- * interpreted as an unsigned 16-bit integer with values in the
- * range 0 to 65535.
- */
+/// A fixed-length list of 16-bit unsigned integers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are truncated to their low 16 bits,
+/// interpreted as an unsigned 16-bit integer with values in the
+/// range 0 to 65535.
 abstract class Uint16List implements List<int>, _TypedIntList {
-  /**
-   * Creates a [Uint16List] of the specified length (in elements), all
-   * of whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 2 bytes.
-   */
+  /// Creates a [Uint16List] of the specified length (in elements), all
+  /// of whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 2 bytes.
   external factory Uint16List(int length);
 
-  /**
-   * Creates a [Uint16List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 2 bytes.
-   */
+  /// Creates a [Uint16List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 2 bytes.
   external factory Uint16List.fromList(List<int> elements);
 
-  /**
-   * Creates a [Uint16List] _view_ of the specified region in
-   * the specified byte buffer.
-   *
-   * Changes in the [Uint16List] will be visible in the byte buffer
-   * and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Uint16List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Uint16List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Uint16List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Uint16List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Uint16List] _view_ of the specified region in
+  /// the specified byte buffer.
+  ///
+  /// Changes in the [Uint16List] will be visible in the byte buffer
+  /// and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Uint16List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Uint16List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Uint16List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Uint16List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Uint16List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asUint16List(offsetInBytes, length);
   }
 
-  /**
-   * Creates a [Uint16List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of two.
-   */
+  /// Creates a [Uint16List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of two.
   @Since("2.8")
   factory Uint16List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -1411,126 +1253,114 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Uint16List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Uint16List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Uint16List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Uint16List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Uint16List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Uint16List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Uint16List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 2;
 }
 
-/**
- * A fixed-length list of 32-bit signed integers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are truncated to their low 32 bits,
- * interpreted as a signed 32-bit two's complement integer with values in the
- * range -2147483648 to 2147483647.
- */
+/// A fixed-length list of 32-bit signed integers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are truncated to their low 32 bits,
+/// interpreted as a signed 32-bit two's complement integer with values in the
+/// range -2147483648 to 2147483647.
 abstract class Int32List implements List<int>, _TypedIntList {
-  /**
-   * Creates an [Int32List] of the specified length (in elements), all of
-   * whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 4 bytes.
-   */
+  /// Creates an [Int32List] of the specified length (in elements), all of
+  /// whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 4 bytes.
   external factory Int32List(int length);
 
-  /**
-   * Creates a [Int32List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 4 bytes.
-   */
+  /// Creates a [Int32List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 4 bytes.
   external factory Int32List.fromList(List<int> elements);
 
-  /**
-   * Creates an [Int32List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Int32List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Int32List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Int32List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Int32List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Int32List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates an [Int32List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Int32List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Int32List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Int32List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Int32List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Int32List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Int32List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asInt32List(offsetInBytes, length);
   }
 
-  /**
-   * Creates an [Int32List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of four.
-   */
+  /// Creates an [Int32List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of four.
   @Since("2.8")
   factory Int32List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -1546,127 +1376,115 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is an `Int32List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Int32List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Int32List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is an `Int32List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Int32List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Int32List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Int32List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 4;
 }
 
-/**
- * A fixed-length list of 32-bit unsigned integers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are truncated to their low 32 bits,
- * interpreted as an unsigned 32-bit integer with values in the
- * range 0 to 4294967295.
- */
+/// A fixed-length list of 32-bit unsigned integers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are truncated to their low 32 bits,
+/// interpreted as an unsigned 32-bit integer with values in the
+/// range 0 to 4294967295.
 abstract class Uint32List implements List<int>, _TypedIntList {
-  /**
-   * Creates a [Uint32List] of the specified length (in elements), all
-   * of whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 4 bytes.
-   */
+  /// Creates a [Uint32List] of the specified length (in elements), all
+  /// of whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 4 bytes.
   external factory Uint32List(int length);
 
-  /**
-   * Creates a [Uint32List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 4 bytes.
-   */
+  /// Creates a [Uint32List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 4 bytes.
   external factory Uint32List.fromList(List<int> elements);
 
-  /**
-   * Creates a [Uint32List] _view_ of the specified region in
-   * the specified byte buffer.
-   *
-   * Changes in the [Uint32List] will be visible in the byte buffer
-   * and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Uint32List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Uint32List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Uint32List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Uint32List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Uint32List] _view_ of the specified region in
+  /// the specified byte buffer.
+  ///
+  /// Changes in the [Uint32List] will be visible in the byte buffer
+  /// and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Uint32List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Uint32List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Uint32List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Uint32List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Uint32List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asUint32List(offsetInBytes, length);
   }
 
-  /**
-   * Creates a [Uint32List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of four.
-   */
+  /// Creates a [Uint32List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of four.
   @Since("2.8")
   factory Uint32List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -1682,126 +1500,114 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Uint32List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Uint32List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Uint32List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Uint32List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Uint32List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Uint32List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Uint32List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 4;
 }
 
-/**
- * A fixed-length list of 64-bit signed integers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are truncated to their low 64 bits,
- * interpreted as a signed 64-bit two's complement integer with values in the
- * range -9223372036854775808 to +9223372036854775807.
- */
+/// A fixed-length list of 64-bit signed integers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are truncated to their low 64 bits,
+/// interpreted as a signed 64-bit two's complement integer with values in the
+/// range -9223372036854775808 to +9223372036854775807.
 abstract class Int64List implements List<int>, _TypedIntList {
-  /**
-   * Creates an [Int64List] of the specified length (in elements), all of
-   * whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 8 bytes.
-   */
+  /// Creates an [Int64List] of the specified length (in elements), all of
+  /// whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 8 bytes.
   external factory Int64List(int length);
 
-  /**
-   * Creates a [Int64List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 8 bytes.
-   */
+  /// Creates a [Int64List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 8 bytes.
   external factory Int64List.fromList(List<int> elements);
 
-  /**
-   * Creates an [Int64List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Int64List] will be visible in the byte buffer
-   * and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Int64List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Int64List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Int64List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Int64List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates an [Int64List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Int64List] will be visible in the byte buffer
+  /// and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Int64List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Int64List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Int64List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Int64List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Int64List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asInt64List(offsetInBytes, length);
   }
 
-  /**
-   * Creates an [Int64List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of eight.
-   */
+  /// Creates an [Int64List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of eight.
   @Since("2.8")
   factory Int64List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -1817,127 +1623,115 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is an `Int64List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Int64List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Int64List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is an `Int64List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Int64List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Int64List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Int64List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 8;
 }
 
-/**
- * A fixed-length list of 64-bit unsigned integers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation can be considerably
- * more space- and time-efficient than the default [List] implementation.
- *
- * Integers stored in the list are truncated to their low 64 bits,
- * interpreted as an unsigned 64-bit integer with values in the
- * range 0 to 18446744073709551615.
- */
+/// A fixed-length list of 64-bit unsigned integers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation can be considerably
+/// more space- and time-efficient than the default [List] implementation.
+///
+/// Integers stored in the list are truncated to their low 64 bits,
+/// interpreted as an unsigned 64-bit integer with values in the
+/// range 0 to 18446744073709551615.
 abstract class Uint64List implements List<int>, _TypedIntList {
-  /**
-   * Creates a [Uint64List] of the specified length (in elements), all
-   * of whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 8 bytes.
-   */
+  /// Creates a [Uint64List] of the specified length (in elements), all
+  /// of whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 8 bytes.
   external factory Uint64List(int length);
 
-  /**
-   * Creates a [Uint64List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 8 bytes.
-   */
+  /// Creates a [Uint64List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 8 bytes.
   external factory Uint64List.fromList(List<int> elements);
 
-  /**
-   * Creates an [Uint64List] _view_ of the specified region in
-   * the specified byte buffer.
-   *
-   * Changes in the [Uint64List] will be visible in the byte buffer
-   * and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Uint64List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Uint64List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Uint64List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Uint64List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates an [Uint64List] _view_ of the specified region in
+  /// the specified byte buffer.
+  ///
+  /// Changes in the [Uint64List] will be visible in the byte buffer
+  /// and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Uint64List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Uint64List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Uint64List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Uint64List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Uint64List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asUint64List(offsetInBytes, length);
   }
 
-  /**
-   * Creates a [Uint64List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of eight.
-   */
+  /// Creates a [Uint64List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of eight.
   @Since("2.8")
   factory Uint64List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -1953,127 +1747,115 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Uint64List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Uint64List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Uint64List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Uint64List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Uint64List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Uint64List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Uint64List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 8;
 }
 
-/**
- * A fixed-length list of IEEE 754 single-precision binary floating-point
- * numbers that is viewable as a [TypedData].
- *
- * For long lists, this
- * implementation can be considerably more space- and time-efficient than
- * the default [List] implementation.
- *
- * Double values stored in the list are converted to the nearest
- * single-precision value. Values read are converted to a double
- * value with the same value.
- */
+/// A fixed-length list of IEEE 754 single-precision binary floating-point
+/// numbers that is viewable as a [TypedData].
+///
+/// For long lists, this
+/// implementation can be considerably more space- and time-efficient than
+/// the default [List] implementation.
+///
+/// Double values stored in the list are converted to the nearest
+/// single-precision value. Values read are converted to a double
+/// value with the same value.
 abstract class Float32List implements List<double>, _TypedFloatList {
-  /**
-   * Creates a [Float32List] of the specified length (in elements), all of
-   * whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 4 bytes.
-   */
+  /// Creates a [Float32List] of the specified length (in elements), all of
+  /// whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 4 bytes.
   external factory Float32List(int length);
 
-  /**
-   * Creates a [Float32List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * Values are truncated to fit in the list when they are copied,
-   * the same way storing values truncates them.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 4 bytes.
-   */
+  /// Creates a [Float32List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// Values are truncated to fit in the list when they are copied,
+  /// the same way storing values truncates them.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 4 bytes.
   external factory Float32List.fromList(List<double> elements);
 
-  /**
-   * Creates a [Float32List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Float32List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Float32List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Float32List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Float32List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Float32List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Float32List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Float32List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Float32List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Float32List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Float32List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Float32List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Float32List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asFloat32List(offsetInBytes, length);
   }
 
-  /**
-   * Creates an [Float32List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of four.
-   */
+  /// Creates an [Float32List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of four.
   @Since("2.8")
   factory Float32List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -2089,120 +1871,108 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Float32List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Float32List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Float32List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Float32List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Float32List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Float32List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Float32List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 4;
 }
 
-/**
- * A fixed-length list of IEEE 754 double-precision binary floating-point
- * numbers  that is viewable as a [TypedData].
- *
- * For long lists, this
- * implementation can be considerably more space- and time-efficient than
- * the default [List] implementation.
- */
+/// A fixed-length list of IEEE 754 double-precision binary floating-point
+/// numbers  that is viewable as a [TypedData].
+///
+/// For long lists, this
+/// implementation can be considerably more space- and time-efficient than
+/// the default [List] implementation.
 abstract class Float64List implements List<double>, _TypedFloatList {
-  /**
-   * Creates a [Float64List] of the specified length (in elements), all of
-   * whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 8 bytes.
-   */
+  /// Creates a [Float64List] of the specified length (in elements), all of
+  /// whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 8 bytes.
   external factory Float64List(int length);
 
-  /**
-   * Creates a [Float64List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 8 bytes.
-   */
+  /// Creates a [Float64List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 8 bytes.
   external factory Float64List.fromList(List<double> elements);
 
-  /**
-   * Creates a [Float64List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Float64List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Float64List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Float64List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Float64List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Float64List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Float64List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Float64List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Float64List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Float64List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Float64List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Float64List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Float64List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asFloat64List(offsetInBytes, length);
   }
 
-  /**
-   * Creates a [Float64List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of eight.
-   */
+  /// Creates a [Float64List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of eight.
   @Since("2.8")
   factory Float64List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -2218,119 +1988,107 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Float64List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Float64List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Float64List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Float64List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Float64List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Float64List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Float64List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 8;
 }
 
-/**
- * A fixed-length list of Float32x4 numbers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation will be considerably more
- * space- and time-efficient than the default [List] implementation.
- */
+/// A fixed-length list of Float32x4 numbers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation will be considerably more
+/// space- and time-efficient than the default [List] implementation.
 abstract class Float32x4List implements List<Float32x4>, TypedData {
-  /**
-   * Creates a [Float32x4List] of the specified length (in elements),
-   * all of whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 16 bytes.
-   */
+  /// Creates a [Float32x4List] of the specified length (in elements),
+  /// all of whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 16 bytes.
   external factory Float32x4List(int length);
 
-  /**
-   * Creates a [Float32x4List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 16 bytes.
-   */
+  /// Creates a [Float32x4List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 16 bytes.
   external factory Float32x4List.fromList(List<Float32x4> elements);
 
-  /**
-   * Creates a [Float32x4List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Float32x4List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Float32x4List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Float32x4List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Float32x4List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Float32x4List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Float32x4List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Float32x4List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Float32x4List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Float32x4List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Float32x4List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Float32x4List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Float32x4List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asFloat32x4List(offsetInBytes, length);
   }
 
-  /**
-   * Creates a [Float32x4List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of sixteen.
-   */
+  /// Creates a [Float32x4List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of sixteen.
   @Since("2.8")
   factory Float32x4List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -2346,127 +2104,113 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns the concatenation of this list and [other].
-   *
-   * If [other] is also a [Float32x4List], the result is a new [Float32x4List],
-   * otherwise the result is a normal growable `List<Float32x4>`.
-   */
+  /// Returns the concatenation of this list and [other].
+  ///
+  /// If [other] is also a [Float32x4List], the result is a new [Float32x4List],
+  /// otherwise the result is a normal growable `List<Float32x4>`.
   List<Float32x4> operator +(List<Float32x4> other);
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Float32x4List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Float32x4List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Float32x4List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Float32x4List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Float32x4List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Float32x4List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Float32x4List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 16;
 }
 
-/**
- * A fixed-length list of Int32x4 numbers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation will be considerably more
- * space- and time-efficient than the default [List] implementation.
- */
+/// A fixed-length list of Int32x4 numbers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation will be considerably more
+/// space- and time-efficient than the default [List] implementation.
 abstract class Int32x4List implements List<Int32x4>, TypedData {
-  /**
-   * Creates a [Int32x4List] of the specified length (in elements),
-   * all of whose elements are initially zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 16 bytes.
-   */
+  /// Creates a [Int32x4List] of the specified length (in elements),
+  /// all of whose elements are initially zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 16 bytes.
   external factory Int32x4List(int length);
 
-  /**
-   * Creates a [Int32x4List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 16 bytes.
-   */
+  /// Creates a [Int32x4List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 16 bytes.
   external factory Int32x4List.fromList(List<Int32x4> elements);
 
-  /**
-   * Creates a [Int32x4List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Int32x4List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Int32x4List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Int32x4List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Int32x4List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Int32x4List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Int32x4List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Int32x4List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Int32x4List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Int32x4List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Int32x4List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Int32x4List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Int32x4List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asInt32x4List(offsetInBytes, length);
   }
 
-  /**
-   * Creates an [Int32x4List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of sixteen.
-   */
+  /// Creates an [Int32x4List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of sixteen.
   @Since("2.8")
   factory Int32x4List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -2482,135 +2226,119 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns the concatenation of this list and [other].
-   *
-   * If [other] is also a [Int32x4List], the result is a new [Int32x4List],
-   * otherwise the result is a normal growable `List<Int32x4>`.
-   */
+  /// Returns the concatenation of this list and [other].
+  ///
+  /// If [other] is also a [Int32x4List], the result is a new [Int32x4List],
+  /// otherwise the result is a normal growable `List<Int32x4>`.
   List<Int32x4> operator +(List<Int32x4> other);
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is an `Int32x4list` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Int32x4list.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Int32x4list
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is an `Int32x4list` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Int32x4list.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Int32x4list
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Int32x4List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 16;
 }
 
-/**
- * A fixed-length list of Float64x2 numbers that is viewable as a
- * [TypedData].
- *
- * For long lists, this implementation will be considerably more
- * space- and time-efficient than the default [List] implementation.
- */
+/// A fixed-length list of Float64x2 numbers that is viewable as a
+/// [TypedData].
+///
+/// For long lists, this implementation will be considerably more
+/// space- and time-efficient than the default [List] implementation.
 abstract class Float64x2List implements List<Float64x2>, TypedData {
-  /**
-   * Creates a [Float64x2List] of the specified length (in elements),
-   * all of whose elements have all lanes set to zero.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * [length] times 16 bytes.
-   */
+  /// Creates a [Float64x2List] of the specified length (in elements),
+  /// all of whose elements have all lanes set to zero.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// [length] times 16 bytes.
   external factory Float64x2List(int length);
 
-  /**
-   * Creates a [Float64x2List] with the same length as the [elements] list
-   * and copies over the elements.
-   *
-   * The list is backed by a [ByteBuffer] containing precisely
-   * `elements.length` times 16 bytes.
-   */
+  /// Creates a [Float64x2List] with the same length as the [elements] list
+  /// and copies over the elements.
+  ///
+  /// The list is backed by a [ByteBuffer] containing precisely
+  /// `elements.length` times 16 bytes.
   external factory Float64x2List.fromList(List<Float64x2> elements);
 
-  /**
-   * Returns the concatenation of this list and [other].
-   *
-   * If [other] is also a [Float64x2List], the result is a new [Float64x2List],
-   * otherwise the result is a normal growable `List<Float64x2>`.
-   */
+  /// Returns the concatenation of this list and [other].
+  ///
+  /// If [other] is also a [Float64x2List], the result is a new [Float64x2List],
+  /// otherwise the result is a normal growable `List<Float64x2>`.
   List<Float64x2> operator +(List<Float64x2> other);
 
-  /**
-   * Creates a [Float64x2List] _view_ of the specified region in [buffer].
-   *
-   * Changes in the [Float64x2List] will be visible in the byte
-   * buffer and vice versa.
-   * If the [offsetInBytes] index of the region is not specified,
-   * it defaults to zero (the first byte in the byte buffer).
-   * If the length is not specified, it defaults to `null`,
-   * which indicates that the view extends to the end of the byte buffer.
-   *
-   * The [offsetInBytes] and [length] must be non-negative, and
-   * [offsetInBytes] + ([length] * elementSizeInBytes) must be less than or
-   * equal to the length of [buffer].
-   *
-   * The [offsetInBytes] must be a multiple of [bytesPerElement].
-   *
-   * Note that when creating a view from a [TypedData] list or byte data,
-   * that list or byte data may itself be a view on a larger buffer
-   * with a [TypedData.offsetInBytes] greater than zero.
-   * Merely doing `Float64x2List.view(other.buffer, 0, count)` may not
-   * point to the bytes you intended. Instead you may need to do:
-   * ```dart
-   * Float64x2List.view(other.buffer, other.offsetInBytes, count)
-   * ```
-   * Alternatively, use [Float64x2List.sublistView]
-   * which includes this computation:
-   * ```dart
-   * Float64x2List.sublistView(other, 0, count);
-   * ```
-   * (The third argument is an end index rather than a length, so if
-   * you start from a position greater than zero, you need not
-   * reduce the count correspondingly).
-   */
+  /// Creates a [Float64x2List] _view_ of the specified region in [buffer].
+  ///
+  /// Changes in the [Float64x2List] will be visible in the byte
+  /// buffer and vice versa.
+  /// If the [offsetInBytes] index of the region is not specified,
+  /// it defaults to zero (the first byte in the byte buffer).
+  /// If the length is not provided,
+  /// the view extends to the end of the byte buffer.
+  ///
+  /// The [offsetInBytes] and [length] must be non-negative, and
+  /// [offsetInBytes] + ([length] * [bytesPerElement]) must be less than or
+  /// equal to the length of [buffer].
+  ///
+  /// The [offsetInBytes] must be a multiple of [bytesPerElement].
+  ///
+  /// Note that when creating a view from a [TypedData] list or byte data,
+  /// that list or byte data may itself be a view on a larger buffer
+  /// with a [TypedData.offsetInBytes] greater than zero.
+  /// Merely doing `Float64x2List.view(other.buffer, 0, count)` may not
+  /// point to the bytes you intended. Instead you may need to do:
+  /// ```dart
+  /// Float64x2List.view(other.buffer, other.offsetInBytes, count)
+  /// ```
+  /// Alternatively, use [Float64x2List.sublistView]
+  /// which includes this computation:
+  /// ```dart
+  /// Float64x2List.sublistView(other, 0, count);
+  /// ```
+  /// (The third argument is an end index rather than a length, so if
+  /// you start from a position greater than zero, you need not
+  /// reduce the count correspondingly).
   factory Float64x2List.view(ByteBuffer buffer,
       [int offsetInBytes = 0, int? length]) {
     return buffer.asFloat64x2List(offsetInBytes, length);
   }
 
-  /**
-   * Creates an [Float64x2List] view on a range of elements of [data].
-   *
-   * Creates a view on the range of `data.buffer` which corresponds
-   * to the elements of [data] from [start] until [end].
-   * If [data] is a typed data list, like [Uint16List], then the view is on
-   * the bytes of the elements with indices from [start] until [end].
-   * If [data] is a [ByteData], it's treated like a list of bytes.
-   *
-   * If provided, [start] and [end] must satisfy
-   *
-   * 0 &le; `start` &le; `end` &le; *elementCount*
-   *
-   * where *elementCount* is the number of elements in [data], which
-   * is the same as the [List.length] of a typed data list.
-   *
-   * If omitted, [start] defaults to zero and [end] to *elementCount*.
-   *
-   * The start and end indices of the range of bytes being viewed must be
-   * multiples of sixteen.
-   */
+  /// Creates an [Float64x2List] view on a range of elements of [data].
+  ///
+  /// Creates a view on the range of `data.buffer` which corresponds
+  /// to the elements of [data] from [start] until [end].
+  /// If [data] is a typed data list, like [Uint16List], then the view is on
+  /// the bytes of the elements with indices from [start] until [end].
+  /// If [data] is a [ByteData], it's treated like a list of bytes.
+  ///
+  /// If provided, [start] and [end] must satisfy
+  ///
+  /// 0 &le; `start` &le; `end` &le; *elementCount*
+  ///
+  /// where *elementCount* is the number of elements in [data], which
+  /// is the same as the [List.length] of a typed data list.
+  ///
+  /// If omitted, [start] defaults to zero and [end] to *elementCount*.
+  ///
+  /// The start and end indices of the range of bytes being viewed must be
+  /// multiples of sixteen.
   @Since("2.8")
   factory Float64x2List.sublistView(TypedData data, [int start = 0, int? end]) {
     int elementSize = data.elementSizeInBytes;
@@ -2626,40 +2354,36 @@
         byteLength ~/ bytesPerElement);
   }
 
-  /**
-   * Returns a new list containing the elements between [start] and [end].
-   *
-   * The new list is a `Float64x2List` containing the elements of this
-   * list at positions greater than or equal to [start] and less than [end] in
-   * the same order as they occur in this list.
-   *
-   * ```dart
-   * var numbers = Float64x2List.fromList([0, 1, 2, 3, 4]);
-   * print(numbers.sublist(1, 3)); // [1, 2]
-   * print(numbers.sublist(1, 3).runtimeType); // Float64x2List
-   * ```
-   *
-   * If [end] is omitted, it defaults to the [length] of this list.
-   *
-   * ```dart
-   * print(numbers.sublist(1)); // [1, 2, 3, 4]
-   * ```
-   *
-   * The `start` and `end` positions must satisfy the relations
-   * 0 ≤ `start` ≤ `end` ≤ `this.length`
-   * If `end` is equal to `start`, then the returned list is empty.
-   */
+  /// Returns a new list containing the elements between [start] and [end].
+  ///
+  /// The new list is a `Float64x2List` containing the elements of this
+  /// list at positions greater than or equal to [start] and less than [end] in
+  /// the same order as they occur in this list.
+  ///
+  /// ```dart
+  /// var numbers = Float64x2List.fromList([0, 1, 2, 3, 4]);
+  /// print(numbers.sublist(1, 3)); // [1, 2]
+  /// print(numbers.sublist(1, 3).runtimeType); // Float64x2List
+  /// ```
+  ///
+  /// If [end] is omitted, it defaults to the [length] of this list.
+  ///
+  /// ```dart
+  /// print(numbers.sublist(1)); // [1, 2, 3, 4]
+  /// ```
+  ///
+  /// The `start` and `end` positions must satisfy the relations
+  /// 0 ≤ `start` ≤ `end` ≤ `this.length`
+  /// If `end` is equal to `start`, then the returned list is empty.
   Float64x2List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 16;
 }
 
-/**
- * Float32x4 immutable value type and operations.
- *
- * Float32x4 stores 4 32-bit floating point values in "lanes".
- * The lanes are "x", "y", "z", and "w" respectively.
- */
+/// Float32x4 immutable value type and operations.
+///
+/// Float32x4 stores 4 32-bit floating point values in "lanes".
+/// The lanes are "x", "y", "z", and "w" respectively.
 abstract class Float32x4 {
   external factory Float32x4(double x, double y, double z, double w);
   external factory Float32x4.splat(double v);
@@ -3026,12 +2750,10 @@
   Float32x4 reciprocalSqrt();
 }
 
-/**
- * Int32x4 and operations.
- *
- * Int32x4 stores 4 32-bit bit-masks in "lanes".
- * The lanes are "x", "y", "z", and "w" respectively.
- */
+/// Int32x4 and operations.
+///
+/// Int32x4 stores 4 32-bit bit-masks in "lanes".
+/// The lanes are "x", "y", "z", and "w" respectively.
 abstract class Int32x4 {
   external factory Int32x4(int x, int y, int z, int w);
   external factory Int32x4.bool(bool x, bool y, bool z, bool w);
@@ -3379,12 +3101,10 @@
   Float32x4 select(Float32x4 trueValue, Float32x4 falseValue);
 }
 
-/**
- * Float64x2 immutable value type and operations.
- *
- * Float64x2 stores 2 64-bit floating point values in "lanes".
- * The lanes are "x" and "y" respectively.
- */
+/// Float64x2 immutable value type and operations.
+///
+/// Float64x2 stores 2 64-bit floating point values in "lanes".
+/// The lanes are "x" and "y" respectively.
 abstract class Float64x2 {
   external factory Float64x2(double x, double y);
   external factory Float64x2.splat(double v);
diff --git a/sdk/lib/typed_data/unmodifiable_typed_data.dart b/sdk/lib/typed_data/unmodifiable_typed_data.dart
index 30bdf51..43aaa84 100644
--- a/sdk/lib/typed_data/unmodifiable_typed_data.dart
+++ b/sdk/lib/typed_data/unmodifiable_typed_data.dart
@@ -4,9 +4,7 @@
 
 part of dart.typed_data;
 
-/**
- * A read-only view of a [ByteBuffer].
- */
+/// A read-only view of a [ByteBuffer].
 class UnmodifiableByteBufferView implements ByteBuffer {
   final ByteBuffer _data;
 
@@ -66,9 +64,7 @@
       new UnmodifiableByteDataView(_data.asByteData(offsetInBytes, length));
 }
 
-/**
- * A read-only view of a [ByteData].
- */
+/// A read-only view of a [ByteData].
 class UnmodifiableByteDataView implements ByteData {
   final ByteData _data;
 
@@ -173,9 +169,7 @@
   }
 }
 
-/**
- * View of a [Uint8List] that disallows modification.
- */
+/// View of a [Uint8List] that disallows modification.
 class UnmodifiableUint8ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint8List, Uint8List>
     implements Uint8List {
@@ -185,9 +179,7 @@
   Uint8List _createList(int length) => Uint8List(length);
 }
 
-/**
- * View of a [Int8List] that disallows modification.
- */
+/// View of a [Int8List] that disallows modification.
 class UnmodifiableInt8ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Int8List, Int8List>
     implements Int8List {
@@ -197,9 +189,7 @@
   Int8List _createList(int length) => Int8List(length);
 }
 
-/**
- * View of a [Uint8ClampedList] that disallows modification.
- */
+/// View of a [Uint8ClampedList] that disallows modification.
 class UnmodifiableUint8ClampedListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint8ClampedList, Uint8ClampedList>
     implements Uint8ClampedList {
@@ -209,9 +199,7 @@
   Uint8ClampedList _createList(int length) => Uint8ClampedList(length);
 }
 
-/**
- * View of a [Uint16List] that disallows modification.
- */
+/// View of a [Uint16List] that disallows modification.
 class UnmodifiableUint16ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint16List, Uint16List>
     implements Uint16List {
@@ -221,9 +209,7 @@
   Uint16List _createList(int length) => Uint16List(length);
 }
 
-/**
- * View of a [Int16List] that disallows modification.
- */
+/// View of a [Int16List] that disallows modification.
 class UnmodifiableInt16ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Int16List, Int16List>
     implements Int16List {
@@ -233,9 +219,7 @@
   Int16List _createList(int length) => Int16List(length);
 }
 
-/**
- * View of a [Uint32List] that disallows modification.
- */
+/// View of a [Uint32List] that disallows modification.
 class UnmodifiableUint32ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint32List, Uint32List>
     implements Uint32List {
@@ -245,9 +229,7 @@
   Uint32List _createList(int length) => Uint32List(length);
 }
 
-/**
- * View of a [Int32List] that disallows modification.
- */
+/// View of a [Int32List] that disallows modification.
 class UnmodifiableInt32ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Int32List, Int32List>
     implements Int32List {
@@ -257,9 +239,7 @@
   Int32List _createList(int length) => Int32List(length);
 }
 
-/**
- * View of a [Uint64List] that disallows modification.
- */
+/// View of a [Uint64List] that disallows modification.
 class UnmodifiableUint64ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Uint64List, Uint64List>
     implements Uint64List {
@@ -269,9 +249,7 @@
   Uint64List _createList(int length) => Uint64List(length);
 }
 
-/**
- * View of a [Int64List] that disallows modification.
- */
+/// View of a [Int64List] that disallows modification.
 class UnmodifiableInt64ListView extends UnmodifiableListBase<int>
     with _UnmodifiableListMixin<int, Int64List, Int64List>
     implements Int64List {
@@ -281,9 +259,7 @@
   Int64List _createList(int length) => Int64List(length);
 }
 
-/**
- * View of a [Int32x4List] that disallows modification.
- */
+/// View of a [Int32x4List] that disallows modification.
 class UnmodifiableInt32x4ListView extends UnmodifiableListBase<Int32x4>
     with _UnmodifiableListMixin<Int32x4, Int32x4List, Int32x4List>
     implements Int32x4List {
@@ -293,9 +269,7 @@
   Int32x4List _createList(int length) => Int32x4List(length);
 }
 
-/**
- * View of a [Float32x4List] that disallows modification.
- */
+/// View of a [Float32x4List] that disallows modification.
 class UnmodifiableFloat32x4ListView extends UnmodifiableListBase<Float32x4>
     with _UnmodifiableListMixin<Float32x4, Float32x4List, Float32x4List>
     implements Float32x4List {
@@ -305,9 +279,7 @@
   Float32x4List _createList(int length) => Float32x4List(length);
 }
 
-/**
- * View of a [Float64x2List] that disallows modification.
- */
+/// View of a [Float64x2List] that disallows modification.
 class UnmodifiableFloat64x2ListView extends UnmodifiableListBase<Float64x2>
     with _UnmodifiableListMixin<Float64x2, Float64x2List, Float64x2List>
     implements Float64x2List {
@@ -317,9 +289,7 @@
   Float64x2List _createList(int length) => Float64x2List(length);
 }
 
-/**
- * View of a [Float32List] that disallows modification.
- */
+/// View of a [Float32List] that disallows modification.
 class UnmodifiableFloat32ListView extends UnmodifiableListBase<double>
     with _UnmodifiableListMixin<double, Float32List, Float32List>
     implements Float32List {
@@ -329,9 +299,7 @@
   Float32List _createList(int length) => Float32List(length);
 }
 
-/**
- * View of a [Float64List] that disallows modification.
- */
+/// View of a [Float64List] that disallows modification.
 class UnmodifiableFloat64ListView extends UnmodifiableListBase<double>
     with _UnmodifiableListMixin<double, Float64List, Float64List>
     implements Float64List {
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index f7f4a26..a3f7e8b 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -231,6 +231,28 @@
   Uri? get ddsUri => _ddsUri;
   Uri? _ddsUri;
 
+  void _sendDdsConnectedEvent(Client client, String uri) {
+    final message =
+        'A Dart Developer Service instance has connected and this direct '
+        'connection to the VM service will now be closed. Please reconnect to '
+        'the Dart Development Service at $uri.';
+    final event = Response.json({
+      'jsonrpc': '2.0',
+      'method': 'streamNotify',
+      'params': {
+        'streamId': kServiceStream,
+        'event': {
+          "type": "Event",
+          "kind": "DartDevelopmentServiceConnected",
+          "message": message,
+          "uri": uri,
+          'timestamp': DateTime.now().millisecondsSinceEpoch,
+        }
+      }
+    });
+    client.post(event);
+  }
+
   Future<String> _yieldControlToDDS(Message message) async {
     final acceptNewWebSocketConnections =
         VMServiceEmbedderHooks.acceptNewWebSocketConnections;
@@ -249,14 +271,16 @@
     if (uri == null) {
       return encodeMissingParamError(message, 'uri');
     }
-    // DDS can only take control if there is no other clients connected
-    // directly to the VM service.
-    if (clients.length > 1) {
-      return encodeRpcError(message, kFeatureDisabled,
-          details:
-              'Existing VM service clients prevent DDS from taking control.');
-    }
     acceptNewWebSocketConnections(false);
+    // Note: we call clients.toList() to avoid concurrent modification errors.
+    for (final client in clients.toList()) {
+      // This is the DDS client.
+      if (message.client == client) {
+        continue;
+      }
+      _sendDdsConnectedEvent(client, uri);
+      client.disconnect();
+    }
     _ddsUri = Uri.parse(uri);
     await VMServiceEmbedderHooks.ddsConnected!();
     return encodeSuccess(message);
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 853cc32..b02678d 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -32,6 +32,7 @@
 
 [ $runtime != none && ($compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk) ]
 int_parse_with_limited_ints_test: SkipByDesign # Requires fixed-size int64 support.
+integer_arith_vm_test: SkipByDesign # Is a VM optimization test that requires int64 support.
 iterable_return_type_int64_test: SkipByDesign # Requires int64 support.
 typed_data_with_limited_ints_test: SkipByDesign # Requires fixed-size int64 support.
 
diff --git a/tests/corelib/set_test.dart b/tests/corelib/set_test.dart
index 117f35a..3b8dd47 100644
--- a/tests/corelib/set_test.dart
+++ b/tests/corelib/set_test.dart
@@ -482,6 +482,66 @@
   Expect.isTrue(aSet.length == 1);
 }
 
+void testUnmodifiable(Set source) {
+  var unmodifiable = Set.unmodifiable(source);
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.add(3);
+  }, "add");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.addAll({1, 2, 3});
+  }, "addAll");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.addAll(<int>{});
+  }, "addAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.remove(3);
+  }, "remove");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.removeAll({1, 2, 3});
+  }, "removeAll");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.removeAll(<int>{});
+  }, "removeAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.retainAll({1, 2, 3});
+  }, "retainAll");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.retainAll(<int>{});
+  }, "retainAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.removeWhere((_) => true);
+  }, "removeWhere");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.retainWhere((_) => false);
+  }, "retainWhere");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.clear();
+  }, "clear");
+}
+
+void testUnmodifiableSetIsNotUpdatedIfSourceSetIsUpdated() {
+  var modifiable = {1};
+  var unmodifiable = Set.unmodifiable(modifiable);
+
+  modifiable.add(2);
+  Expect.notEquals(modifiable.length, unmodifiable.length);
+  Expect.setEquals({2}, modifiable.difference(unmodifiable));
+  modifiable.removeAll({1, 2});
+  Expect.setEquals({1}, unmodifiable.difference(modifiable));
+  Expect.setEquals({1}, unmodifiable);
+}
+
 main() {
   testMain(() => new HashSet());
   testMain(() => new LinkedHashSet());
@@ -553,4 +613,7 @@
   testASetFrom((x) => new HashSet<A>.from(x));
   testASetFrom((x) => new LinkedHashSet<A>.from(x));
   testASetFrom((x) => new SplayTreeSet<A>.from(x, identityCompare));
+
+  testUnmodifiable({1});
+  testUnmodifiableSetIsNotUpdatedIfSourceSetIsUpdated();
 }
diff --git a/tests/corelib/set_unmodifiable_view_test.dart b/tests/corelib/set_unmodifiable_view_test.dart
new file mode 100644
index 0000000..4ee582d
--- /dev/null
+++ b/tests/corelib/set_unmodifiable_view_test.dart
@@ -0,0 +1,220 @@
+// 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:expect/expect.dart";
+import "dart:collection";
+
+main() {
+  testIterableApi();
+  testUnmodifiableSetApi();
+  testMutatingApisThrow();
+  testChangesInOriginalSetAreObservedInUnmodifiableView();
+}
+
+void testIterableApi() {
+  Set<int> original = {1, 2, 3};
+  Set<int> copy = {...original};
+  UnmodifiableSetView<int> wrapped = new UnmodifiableSetView(original);
+
+  Expect.equals(wrapped.any((_) => true), original.any((_) => true));
+  Expect.equals(wrapped.any((_) => false), original.any((_) => false));
+
+  Expect.equals(wrapped.contains(0), original.contains(0));
+  Expect.equals(wrapped.elementAt(0), original.elementAt(0));
+
+  Expect.equals(wrapped.every((_) => true), original.every((_) => true));
+  Expect.equals(wrapped.every((_) => false), original.every((_) => false));
+
+  Expect.setEquals(
+      wrapped.expand((x) => [x, x]), original.expand((x) => [x, x]));
+
+  Expect.equals(wrapped.first, original.first);
+
+  Expect.equals(
+      wrapped.firstWhere((_) => true), original.firstWhere((_) => true));
+  Expect.throwsStateError(() {
+    wrapped.firstWhere((_) => false);
+  }, "firstWhere");
+
+  Expect.equals(wrapped.fold<int>(0, (x, y) => x + y),
+      original.fold<int>(0, (x, y) => x + y));
+
+  testForeach(wrapped, original);
+
+  Expect.equals(wrapped.isEmpty, original.isEmpty);
+
+  Expect.equals(wrapped.isNotEmpty, original.isNotEmpty);
+
+  testIterator(wrapped, original);
+
+  Expect.equals(wrapped.join(""), original.join(""));
+  Expect.equals(wrapped.join("-"), original.join("-"));
+
+  Expect.equals(wrapped.last, original.last);
+
+  Expect.equals(
+      wrapped.lastWhere((_) => true), original.lastWhere((_) => true));
+  Expect.throwsStateError(() {
+    wrapped.lastWhere((_) => false);
+  }, "lastWhere");
+
+  Expect.equals(wrapped.length, original.length);
+
+  Expect.setEquals(wrapped.map((x) => "[$x]"), original.map((x) => "[$x]"));
+
+  Expect.equals(
+      wrapped.reduce((x, y) => x + y), original.reduce((x, y) => x + y));
+
+  Expect.throwsStateError(() {
+    wrapped.single;
+  }, "single");
+
+  Expect.throwsStateError(() {
+    wrapped.singleWhere((_) => true);
+  }, "singleWhere true");
+  Expect.throwsStateError(() {
+    wrapped.singleWhere((_) => false);
+  }, "singleWhere false");
+
+  Expect.setEquals(wrapped.skip(0), original.skip(0));
+  Expect.setEquals(wrapped.skip(1), original.skip(1));
+
+  Expect.setEquals(
+      wrapped.skipWhile((_) => true), original.skipWhile((_) => true));
+  Expect.setEquals(
+      wrapped.skipWhile((_) => false), original.skipWhile((_) => false));
+
+  Expect.setEquals(wrapped.take(0), original.take(0));
+  Expect.setEquals(wrapped.take(1), original.take(1));
+
+  Expect.setEquals(
+      wrapped.takeWhile((_) => true), original.takeWhile((_) => true));
+  Expect.setEquals(
+      wrapped.takeWhile((_) => false), original.takeWhile((_) => false));
+
+  var toListResult = wrapped.toList();
+  Expect.listEquals(original.toList(), toListResult);
+  toListResult.add(4);
+  Expect.listEquals([1, 2, 3, 4], toListResult);
+  toListResult[3] = 5;
+  Expect.listEquals([1, 2, 3, 5], toListResult);
+  // wrapped and original are intact
+  Expect.setEquals(copy, wrapped);
+  Expect.setEquals(copy, original);
+
+  var toSetResult = wrapped.toSet();
+  Expect.setEquals(original.toSet(), toSetResult);
+  toSetResult.add(4);
+  Expect.setEquals({1, 2, 3, 4}, toSetResult);
+  // wrapped and original are intact
+  Expect.setEquals(copy, wrapped);
+  Expect.setEquals(copy, original);
+
+  Expect.setEquals(wrapped.where((_) => true), original.where((_) => true));
+  Expect.setEquals(wrapped.where((_) => false), original.where((_) => false));
+}
+
+void testUnmodifiableSetApi() {
+  Set<int> original = {1, 2, 3};
+  Set<int> copy = {...original};
+  UnmodifiableSetView<int> wrapped = new UnmodifiableSetView(original);
+
+  Expect.isTrue(wrapped.containsAll(copy));
+  Expect.isTrue(wrapped.containsAll(copy.toList()));
+  Expect.isTrue(wrapped.containsAll([]));
+
+  Expect.isTrue(wrapped.intersection({}).isEmpty);
+  Expect.setEquals(wrapped.intersection(copy), original);
+
+  Expect.setEquals(wrapped.union({}), original);
+  Expect.setEquals(wrapped.union(copy), original);
+
+  Expect.setEquals(wrapped.difference({}), original);
+  Expect.isTrue(wrapped.difference(copy).isEmpty);
+}
+
+void testMutatingApisThrow() {
+  UnmodifiableSetView<int> s = new UnmodifiableSetView({1, 2, 3});
+
+  Expect.throwsUnsupportedError(() {
+    s.add(3);
+  }, "add");
+
+  Expect.throwsUnsupportedError(() {
+    s.addAll({1, 2, 3});
+  }, "addAll");
+
+  Expect.throwsUnsupportedError(() {
+    s.addAll(<int>{});
+  }, "addAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    s.remove(3);
+  }, "remove");
+
+  Expect.throwsUnsupportedError(() {
+    s.removeAll({1, 2, 3});
+  }, "removeAll");
+
+  Expect.throwsUnsupportedError(() {
+    s.removeAll(<int>{});
+  }, "removeAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    s.retainAll({1, 2, 3});
+  }, "retainAll");
+
+  Expect.throwsUnsupportedError(() {
+    s.retainAll(<int>{});
+  }, "retainAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    s.removeWhere((_) => true);
+  }, "removeWhere");
+
+  Expect.throwsUnsupportedError(() {
+    s.retainWhere((_) => false);
+  }, "retainWhere");
+
+  Expect.throwsUnsupportedError(() {
+    s.clear();
+  }, "clear");
+}
+
+void testChangesInOriginalSetAreObservedInUnmodifiableView() {
+  Set<int> original = {1, 2, 3};
+  Set<int> copy = {...original};
+  UnmodifiableSetView<int> wrapped = new UnmodifiableSetView(original);
+
+  original.add(4);
+  Expect.setEquals(original, wrapped);
+  Expect.setEquals({4}, wrapped.difference(copy));
+}
+
+void testForeach(Set<int> wrapped, Set<int> original) {
+  var wrapCtr = 0;
+  var origCtr = 0;
+
+  wrapped.forEach((x) {
+    wrapCtr += x;
+  });
+
+  original.forEach((x) {
+    origCtr += x;
+  });
+
+  Expect.equals(wrapCtr, origCtr);
+}
+
+void testIterator(Set<int> wrapped, Set<int> original) {
+  Iterator wrapIter = wrapped.iterator;
+  Iterator origIter = original.iterator;
+
+  while (origIter.moveNext()) {
+    Expect.isTrue(wrapIter.moveNext());
+    Expect.equals(wrapIter.current, origIter.current);
+  }
+
+  Expect.isFalse(wrapIter.moveNext());
+}
diff --git a/tests/corelib/uri_http_test.dart b/tests/corelib/uri_http_test.dart
index 399c403..bfc57bf 100644
--- a/tests/corelib/uri_http_test.dart
+++ b/tests/corelib/uri_http_test.dart
@@ -4,7 +4,7 @@
 
 import "package:expect/expect.dart";
 
-testHttpUri() {
+void testHttpUri() {
   void check(Uri uri, String expected) {
     Expect.equals(expected, uri.toString());
   }
@@ -40,7 +40,7 @@
   check(new Uri.http('[ff02::1%%321]', ''), 'http://[ff02::1%2521]');
 }
 
-testHttpsUri() {
+void testHttpsUri() {
   void check(Uri uri, String expected) {
     Expect.equals(expected, uri.toString());
   }
@@ -71,7 +71,7 @@
   check(new Uri.https("[::127.0.0.1]", "a"), "https://[::127.0.0.1]/a");
 }
 
-testResolveHttpScheme() {
+void testResolveHttpScheme() {
   String s = "//myserver:1234/path/some/thing";
   Uri uri = Uri.parse(s);
   Uri http = new Uri(scheme: "http");
@@ -80,8 +80,34 @@
   Expect.equals("https:$s", https.resolveUri(uri).toString());
 }
 
+void testQuery() {
+  var uri = Uri.http("example.com", "a/b", <String, dynamic>{
+    "a": "b",
+    "c": ["d", "e"]
+  });
+  Expect.equals(uri.toString(), "http://example.com/a/b?a=b&c=d&c=e");
+  Expect.listEquals(uri.queryParametersAll["c"]!, ["d", "e"]);
+
+  uri = Uri.https("example.com", "a/b", <String, dynamic>{
+    "a": "b",
+    "c": ["d", "e"]
+  });
+  Expect.equals(uri.toString(), "https://example.com/a/b?a=b&c=d&c=e");
+  Expect.listEquals(uri.queryParametersAll["c"]!, ["d", "e"]);
+
+  uri = Uri.http("example.com", "a/b", {
+    "a b c": ["d e", "f g"]
+  });
+  Expect.equals(uri.toString(), "http://example.com/a/b?a+b+c=d+e&a+b+c=f+g");
+  uri = Uri.https("example.com", "a/b", {
+    "a b c": ["d e", "f g"]
+  });
+  Expect.equals(uri.toString(), "https://example.com/a/b?a+b+c=d+e&a+b+c=f+g");
+}
+
 main() {
   testHttpUri();
   testHttpsUri();
   testResolveHttpScheme();
+  testQuery();
 }
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 5704e10..a4e1987 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -43,6 +43,7 @@
 
 [ $runtime != none && ($compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk) ]
 int_parse_with_limited_ints_test: SkipByDesign # Requires fixed-size int64 support.
+integer_arith_vm_test: SkipByDesign # Is a VM optimization test that requires int64 support.
 iterable_return_type_int64_test: SkipByDesign # Requires int64 support.
 typed_data_with_limited_ints_test: SkipByDesign # Requires fixed-size int64 support.
 
diff --git a/tests/corelib_2/set_test.dart b/tests/corelib_2/set_test.dart
index c719e5f..68cf684 100644
--- a/tests/corelib_2/set_test.dart
+++ b/tests/corelib_2/set_test.dart
@@ -482,6 +482,66 @@
   Expect.isTrue(aSet.length == 1);
 }
 
+void testUnmodifiable(Set source) {
+  var unmodifiable = Set.unmodifiable(source);
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.add(3);
+  }, "add");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.addAll({1, 2, 3});
+  }, "addAll");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.addAll(<int>{});
+  }, "addAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.remove(3);
+  }, "remove");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.removeAll({1, 2, 3});
+  }, "removeAll");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.removeAll(<int>{});
+  }, "removeAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.retainAll({1, 2, 3});
+  }, "retainAll");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.retainAll(<int>{});
+  }, "retainAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.removeWhere((_) => true);
+  }, "removeWhere");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.retainWhere((_) => false);
+  }, "retainWhere");
+
+  Expect.throwsUnsupportedError(() {
+    unmodifiable.clear();
+  }, "clear");
+}
+
+void testUnmodifiableSetIsNotUpdatedIfSourceSetIsUpdated() {
+  var modifiable = {1};
+  var unmodifiable = Set.unmodifiable(modifiable);
+
+  modifiable.add(2);
+  Expect.notEquals(modifiable.length, unmodifiable.length);
+  Expect.setEquals({2}, modifiable.difference(unmodifiable));
+  modifiable.removeAll({1, 2});
+  Expect.setEquals({1}, unmodifiable.difference(modifiable));
+  Expect.setEquals({1}, unmodifiable);
+}
+
 main() {
   testMain(() => new HashSet());
   testMain(() => new LinkedHashSet());
@@ -553,4 +613,7 @@
   testASetFrom((x) => new HashSet<A>.from(x));
   testASetFrom((x) => new LinkedHashSet<A>.from(x));
   testASetFrom((x) => new SplayTreeSet<A>.from(x, identityCompare));
+
+  testUnmodifiable({1});
+  testUnmodifiableSetIsNotUpdatedIfSourceSetIsUpdated();
 }
diff --git a/tests/corelib_2/set_unmodifiable_view_test.dart b/tests/corelib_2/set_unmodifiable_view_test.dart
new file mode 100644
index 0000000..4ee582d
--- /dev/null
+++ b/tests/corelib_2/set_unmodifiable_view_test.dart
@@ -0,0 +1,220 @@
+// 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:expect/expect.dart";
+import "dart:collection";
+
+main() {
+  testIterableApi();
+  testUnmodifiableSetApi();
+  testMutatingApisThrow();
+  testChangesInOriginalSetAreObservedInUnmodifiableView();
+}
+
+void testIterableApi() {
+  Set<int> original = {1, 2, 3};
+  Set<int> copy = {...original};
+  UnmodifiableSetView<int> wrapped = new UnmodifiableSetView(original);
+
+  Expect.equals(wrapped.any((_) => true), original.any((_) => true));
+  Expect.equals(wrapped.any((_) => false), original.any((_) => false));
+
+  Expect.equals(wrapped.contains(0), original.contains(0));
+  Expect.equals(wrapped.elementAt(0), original.elementAt(0));
+
+  Expect.equals(wrapped.every((_) => true), original.every((_) => true));
+  Expect.equals(wrapped.every((_) => false), original.every((_) => false));
+
+  Expect.setEquals(
+      wrapped.expand((x) => [x, x]), original.expand((x) => [x, x]));
+
+  Expect.equals(wrapped.first, original.first);
+
+  Expect.equals(
+      wrapped.firstWhere((_) => true), original.firstWhere((_) => true));
+  Expect.throwsStateError(() {
+    wrapped.firstWhere((_) => false);
+  }, "firstWhere");
+
+  Expect.equals(wrapped.fold<int>(0, (x, y) => x + y),
+      original.fold<int>(0, (x, y) => x + y));
+
+  testForeach(wrapped, original);
+
+  Expect.equals(wrapped.isEmpty, original.isEmpty);
+
+  Expect.equals(wrapped.isNotEmpty, original.isNotEmpty);
+
+  testIterator(wrapped, original);
+
+  Expect.equals(wrapped.join(""), original.join(""));
+  Expect.equals(wrapped.join("-"), original.join("-"));
+
+  Expect.equals(wrapped.last, original.last);
+
+  Expect.equals(
+      wrapped.lastWhere((_) => true), original.lastWhere((_) => true));
+  Expect.throwsStateError(() {
+    wrapped.lastWhere((_) => false);
+  }, "lastWhere");
+
+  Expect.equals(wrapped.length, original.length);
+
+  Expect.setEquals(wrapped.map((x) => "[$x]"), original.map((x) => "[$x]"));
+
+  Expect.equals(
+      wrapped.reduce((x, y) => x + y), original.reduce((x, y) => x + y));
+
+  Expect.throwsStateError(() {
+    wrapped.single;
+  }, "single");
+
+  Expect.throwsStateError(() {
+    wrapped.singleWhere((_) => true);
+  }, "singleWhere true");
+  Expect.throwsStateError(() {
+    wrapped.singleWhere((_) => false);
+  }, "singleWhere false");
+
+  Expect.setEquals(wrapped.skip(0), original.skip(0));
+  Expect.setEquals(wrapped.skip(1), original.skip(1));
+
+  Expect.setEquals(
+      wrapped.skipWhile((_) => true), original.skipWhile((_) => true));
+  Expect.setEquals(
+      wrapped.skipWhile((_) => false), original.skipWhile((_) => false));
+
+  Expect.setEquals(wrapped.take(0), original.take(0));
+  Expect.setEquals(wrapped.take(1), original.take(1));
+
+  Expect.setEquals(
+      wrapped.takeWhile((_) => true), original.takeWhile((_) => true));
+  Expect.setEquals(
+      wrapped.takeWhile((_) => false), original.takeWhile((_) => false));
+
+  var toListResult = wrapped.toList();
+  Expect.listEquals(original.toList(), toListResult);
+  toListResult.add(4);
+  Expect.listEquals([1, 2, 3, 4], toListResult);
+  toListResult[3] = 5;
+  Expect.listEquals([1, 2, 3, 5], toListResult);
+  // wrapped and original are intact
+  Expect.setEquals(copy, wrapped);
+  Expect.setEquals(copy, original);
+
+  var toSetResult = wrapped.toSet();
+  Expect.setEquals(original.toSet(), toSetResult);
+  toSetResult.add(4);
+  Expect.setEquals({1, 2, 3, 4}, toSetResult);
+  // wrapped and original are intact
+  Expect.setEquals(copy, wrapped);
+  Expect.setEquals(copy, original);
+
+  Expect.setEquals(wrapped.where((_) => true), original.where((_) => true));
+  Expect.setEquals(wrapped.where((_) => false), original.where((_) => false));
+}
+
+void testUnmodifiableSetApi() {
+  Set<int> original = {1, 2, 3};
+  Set<int> copy = {...original};
+  UnmodifiableSetView<int> wrapped = new UnmodifiableSetView(original);
+
+  Expect.isTrue(wrapped.containsAll(copy));
+  Expect.isTrue(wrapped.containsAll(copy.toList()));
+  Expect.isTrue(wrapped.containsAll([]));
+
+  Expect.isTrue(wrapped.intersection({}).isEmpty);
+  Expect.setEquals(wrapped.intersection(copy), original);
+
+  Expect.setEquals(wrapped.union({}), original);
+  Expect.setEquals(wrapped.union(copy), original);
+
+  Expect.setEquals(wrapped.difference({}), original);
+  Expect.isTrue(wrapped.difference(copy).isEmpty);
+}
+
+void testMutatingApisThrow() {
+  UnmodifiableSetView<int> s = new UnmodifiableSetView({1, 2, 3});
+
+  Expect.throwsUnsupportedError(() {
+    s.add(3);
+  }, "add");
+
+  Expect.throwsUnsupportedError(() {
+    s.addAll({1, 2, 3});
+  }, "addAll");
+
+  Expect.throwsUnsupportedError(() {
+    s.addAll(<int>{});
+  }, "addAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    s.remove(3);
+  }, "remove");
+
+  Expect.throwsUnsupportedError(() {
+    s.removeAll({1, 2, 3});
+  }, "removeAll");
+
+  Expect.throwsUnsupportedError(() {
+    s.removeAll(<int>{});
+  }, "removeAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    s.retainAll({1, 2, 3});
+  }, "retainAll");
+
+  Expect.throwsUnsupportedError(() {
+    s.retainAll(<int>{});
+  }, "retainAll empty");
+
+  Expect.throwsUnsupportedError(() {
+    s.removeWhere((_) => true);
+  }, "removeWhere");
+
+  Expect.throwsUnsupportedError(() {
+    s.retainWhere((_) => false);
+  }, "retainWhere");
+
+  Expect.throwsUnsupportedError(() {
+    s.clear();
+  }, "clear");
+}
+
+void testChangesInOriginalSetAreObservedInUnmodifiableView() {
+  Set<int> original = {1, 2, 3};
+  Set<int> copy = {...original};
+  UnmodifiableSetView<int> wrapped = new UnmodifiableSetView(original);
+
+  original.add(4);
+  Expect.setEquals(original, wrapped);
+  Expect.setEquals({4}, wrapped.difference(copy));
+}
+
+void testForeach(Set<int> wrapped, Set<int> original) {
+  var wrapCtr = 0;
+  var origCtr = 0;
+
+  wrapped.forEach((x) {
+    wrapCtr += x;
+  });
+
+  original.forEach((x) {
+    origCtr += x;
+  });
+
+  Expect.equals(wrapCtr, origCtr);
+}
+
+void testIterator(Set<int> wrapped, Set<int> original) {
+  Iterator wrapIter = wrapped.iterator;
+  Iterator origIter = original.iterator;
+
+  while (origIter.moveNext()) {
+    Expect.isTrue(wrapIter.moveNext());
+    Expect.equals(wrapIter.current, origIter.current);
+  }
+
+  Expect.isFalse(wrapIter.moveNext());
+}
diff --git a/tests/corelib_2/uri_http_test.dart b/tests/corelib_2/uri_http_test.dart
index 399c403..4fd639d 100644
--- a/tests/corelib_2/uri_http_test.dart
+++ b/tests/corelib_2/uri_http_test.dart
@@ -4,7 +4,7 @@
 
 import "package:expect/expect.dart";
 
-testHttpUri() {
+void testHttpUri() {
   void check(Uri uri, String expected) {
     Expect.equals(expected, uri.toString());
   }
@@ -40,7 +40,7 @@
   check(new Uri.http('[ff02::1%%321]', ''), 'http://[ff02::1%2521]');
 }
 
-testHttpsUri() {
+void testHttpsUri() {
   void check(Uri uri, String expected) {
     Expect.equals(expected, uri.toString());
   }
@@ -71,7 +71,7 @@
   check(new Uri.https("[::127.0.0.1]", "a"), "https://[::127.0.0.1]/a");
 }
 
-testResolveHttpScheme() {
+void testResolveHttpScheme() {
   String s = "//myserver:1234/path/some/thing";
   Uri uri = Uri.parse(s);
   Uri http = new Uri(scheme: "http");
@@ -80,8 +80,34 @@
   Expect.equals("https:$s", https.resolveUri(uri).toString());
 }
 
+void testQuery() {
+  var uri = Uri.http("example.com", "a/b", <String, dynamic>{
+    "a": "b",
+    "c": ["d", "e"]
+  });
+  Expect.equals(uri.toString(), "http://example.com/a/b?a=b&c=d&c=e");
+  Expect.listEquals(uri.queryParametersAll["c"], ["d", "e"]);
+
+  uri = Uri.https("example.com", "a/b", <String, dynamic>{
+    "a": "b",
+    "c": ["d", "e"]
+  });
+  Expect.equals(uri.toString(), "https://example.com/a/b?a=b&c=d&c=e");
+  Expect.listEquals(uri.queryParametersAll["c"], ["d", "e"]);
+
+  uri = Uri.http("example.com", "a/b", {
+    "a b c": ["d e", "f g"]
+  });
+  Expect.equals(uri.toString(), "http://example.com/a/b?a+b+c=d+e&a+b+c=f+g");
+  uri = Uri.https("example.com", "a/b", {
+    "a b c": ["d e", "f g"]
+  });
+  Expect.equals(uri.toString(), "https://example.com/a/b?a+b+c=d+e&a+b+c=f+g");
+}
+
 main() {
   testHttpUri();
   testHttpsUri();
   testResolveHttpScheme();
+  testQuery();
 }
diff --git a/tests/dart2js/code_motion_exception_test.dart b/tests/dart2js/code_motion_exception_test.dart
index 95ed395..1df3274 100644
--- a/tests/dart2js/code_motion_exception_test.dart
+++ b/tests/dart2js/code_motion_exception_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.
 
+// dart2jsOptions=--no-minify
+
 import "package:expect/expect.dart";
 
 // Test for correct order of exceptions in code with checks that could be moved
diff --git a/tests/dart2js/internal/deferred/load_in_correct_order_test.dart b/tests/dart2js/internal/deferred/load_in_correct_order_test.dart
index dc6727d..4f04a2c 100644
--- a/tests/dart2js/internal/deferred/load_in_correct_order_test.dart
+++ b/tests/dart2js/internal/deferred/load_in_correct_order_test.dart
@@ -74,7 +74,25 @@
 // This test has 3 loadLibrary calls, this array contains how many hunks will be
 // loaded by each call.
 self.currentLoadLibraryCall = 0;
-self.filesPerLoadLibraryCall = [4, 2, 1];
+self.filesPerLoadLibraryCall = null;
+
+self.initFilesPerLoadLibraryCall = function() {
+  // We assume we load d1, then d2, then d3.
+  var loadOrder = ['d1', 'd2', 'd3'];
+  var uniques = {};
+  self.filesPerLoadLibraryCall = [];
+  for (var i = 0; i < loadOrder.length; i++) {
+    var filesToLoad = 0;
+    var parts = init.deferredLibraryParts[loadOrder[i]];
+    for (var j = 0; j < parts.length; j++) {
+      if (!uniques.hasOwnProperty(parts[j])) {
+        uniques[parts[j]] = true;
+        filesToLoad++;
+      }
+    }
+    self.filesPerLoadLibraryCall.push(filesToLoad);
+  }
+};
 
 // Download uri via an XHR
 self.download = function(uri) {
@@ -99,6 +117,9 @@
 
 // Hook to control how we load hunks (we force them to be out of order).
 self.dartDeferredLibraryLoader = function(uri, success, error) {
+  if (self.filesPerLoadLibraryCall == null) {
+    self.initFilesPerLoadLibraryCall();
+  }
   self.uris.push(uri);
   self.successCallbacks.push(success);
   if (isD8) {
@@ -111,13 +132,13 @@
 // Do the actual load of the hunk and call the corresponding success callback.
 self.doLoad = function(i) {
   self.setTimeout(function () {
-  var uri = self.uris[i];
-  if (self.isD8) {
-    load(uri);
-  } else {
-    eval(self.content[uri]);
-  }
-  (self.successCallbacks[i])();
+    var uri = self.uris[i];
+    if (self.isD8) {
+      load(uri);
+    } else {
+      eval(self.content[uri]);
+    }
+    (self.successCallbacks[i])();
   }, 0);
 };
 
@@ -125,13 +146,10 @@
 // purposely load the hunks out of order.
 self.doActualLoads = function() {
   self.currentLoadLibraryCall++;
-  if (self.total == 4) {
-    self.doLoad(3); // load purposely out of order!
-    self.doLoad(0);
-    self.doLoad(1);
-    self.doLoad(2);
-  } else {
-    for (var i = 0; i < self.total; i++) {
+  if (self.total >= 1) {
+    // Load out of order, last first.
+    self.doLoad(self.total - 1);
+    for (var i = 0; i < self.total - 1; i++) {
       self.doLoad(i);
     }
   }
diff --git a/tests/dart2js/late_initializers_1_test.dart b/tests/dart2js/late_initializers_1_test.dart
new file mode 100644
index 0000000..995fc30
--- /dev/null
+++ b/tests/dart2js/late_initializers_1_test.dart
@@ -0,0 +1,88 @@
+// 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';
+
+// Tests where late variable or field has a predictable value. An incorrect
+// optimization might try to eliminate part of the check.
+
+String lastTag = 'unset';
+
+int zero(String tag) {
+  lastTag = tag;
+  return 0;
+}
+
+int one(String tag) {
+  lastTag = tag;
+  return 1;
+}
+
+int? returnNull(String tag) {
+  lastTag = tag;
+  return null;
+}
+
+class C1 {
+  late int? i1 = zero('C1.i1');
+  late int i2 = zero('C1.i2');
+  late int? i3 = returnNull('C1.i3');
+  late int i4 = one('C1.i4');
+}
+
+class C2 {
+  late final int? i1 = zero('C2.i1');
+  late final int i2 = zero('C2.i2');
+  late final int? i3 = returnNull('C2.i3');
+  late int i4 = one('C2.i4');
+}
+
+void test1() {
+  for (int i = 0; i < 10; i++) {
+    final c = C1();
+    lastTag = '';
+    Expect.equals(0, c.i1);
+    Expect.equals('C1.i1', lastTag);
+    Expect.equals(0, c.i2);
+    Expect.equals('C1.i2', lastTag);
+    Expect.equals(null, c.i3);
+    Expect.equals('C1.i3', lastTag);
+
+    Expect.equals(0, c.i1);
+    Expect.equals('C1.i3', lastTag);
+    Expect.equals(0, c.i2);
+    Expect.equals('C1.i3', lastTag);
+    Expect.equals(null, c.i3);
+    Expect.equals('C1.i3', lastTag);
+
+    Expect.equals(1, c.i4);
+    Expect.equals('C1.i4', lastTag);
+  }
+}
+
+void test2() {
+  final c = C2();
+  lastTag = '';
+  Expect.equals(0, c.i1);
+  Expect.equals('C2.i1', lastTag);
+  Expect.equals(0, c.i2);
+  Expect.equals('C2.i2', lastTag);
+  Expect.equals(null, c.i3);
+  Expect.equals('C2.i3', lastTag);
+
+  Expect.equals(0, c.i1);
+  Expect.equals('C2.i3', lastTag);
+  Expect.equals(0, c.i2);
+  Expect.equals('C2.i3', lastTag);
+  Expect.equals(null, c.i3);
+  Expect.equals('C2.i3', lastTag);
+
+  Expect.equals(1, c.i4);
+  Expect.equals('C2.i4', lastTag);
+}
+
+main() {
+  test1();
+  test2();
+}
diff --git a/tests/dart2js/late_initializers_2_test.dart b/tests/dart2js/late_initializers_2_test.dart
new file mode 100644
index 0000000..9e280fc
--- /dev/null
+++ b/tests/dart2js/late_initializers_2_test.dart
@@ -0,0 +1,105 @@
+// 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';
+
+// Tests where late variable or field has a predictable value. An incorrect
+// optimization might try to eliminate part of the check.
+
+class C1 {
+  late String lastTag;
+
+  int zero(String tag) {
+    lastTag = tag;
+    return 0;
+  }
+
+  int one(String tag) {
+    lastTag = tag;
+    return 1;
+  }
+
+  int? returnNull(String tag) {
+    lastTag = tag;
+    return null;
+  }
+
+  late int? i1 = zero('C1.i1');
+  late int i2 = zero('C1.i2');
+  late int? i3 = returnNull('C1.i3');
+  late int i4 = one('C1.i4');
+}
+
+void test1() {
+  for (int i = 0; i < 10; i++) {
+    final c = C1();
+
+    Expect.equals(0, c.i1);
+    Expect.equals('C1.i1', c.lastTag);
+    Expect.equals(0, c.i2);
+    Expect.equals('C1.i2', c.lastTag);
+    Expect.equals(null, c.i3);
+    Expect.equals('C1.i3', c.lastTag);
+
+    Expect.equals(0, c.i1);
+    Expect.equals('C1.i3', c.lastTag);
+    Expect.equals(0, c.i2);
+    Expect.equals('C1.i3', c.lastTag);
+    Expect.equals(null, c.i3);
+    Expect.equals('C1.i3', c.lastTag);
+
+    Expect.equals(1, c.i4);
+    Expect.equals('C1.i4', c.lastTag);
+  }
+}
+
+class C2 {
+  late String lastTag;
+
+  int zero(String tag) {
+    lastTag = tag;
+    return 0;
+  }
+
+  int one(String tag) {
+    lastTag = tag;
+    return 1;
+  }
+
+  int? returnNull(String tag) {
+    lastTag = tag;
+    return null;
+  }
+
+  late final int? i1 = zero('C2.i1');
+  late final int i2 = zero('C2.i2');
+  late final int? i3 = returnNull('C2.i3');
+  late int i4 = one('C2.i4');
+}
+
+void test2() {
+  final c = C2();
+
+  Expect.equals(0, c.i1);
+  Expect.equals('C2.i1', c.lastTag);
+  Expect.equals(0, c.i2);
+  Expect.equals('C2.i2', c.lastTag);
+  Expect.equals(null, c.i3);
+  Expect.equals('C2.i3', c.lastTag);
+
+  Expect.equals(0, c.i1);
+  Expect.equals('C2.i3', c.lastTag);
+  Expect.equals(0, c.i2);
+  Expect.equals('C2.i3', c.lastTag);
+  Expect.equals(null, c.i3);
+  Expect.equals('C2.i3', c.lastTag);
+
+  Expect.equals(1, c.i4);
+  Expect.equals('C2.i4', c.lastTag);
+}
+
+main() {
+  test1();
+  test2();
+}
diff --git a/tests/dart2js/native/abstract_class_test.dart b/tests/dart2js/native/abstract_class_test.dart
index 6773385..7bcba7e 100644
--- a/tests/dart2js/native/abstract_class_test.dart
+++ b/tests/dart2js/native/abstract_class_test.dart
@@ -27,12 +27,12 @@
   function A(){}
   function B(){}
   B.prototype.foo = function() { return 'B.foo'; };
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
   self.nativeConstructor(A);
   self.nativeConstructor(B);
-})()
-""");
+})()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/bound_closure_super_test.dart b/tests/dart2js/native/bound_closure_super_test.dart
deleted file mode 100644
index d97d8e1..0000000
--- a/tests/dart2js/native/bound_closure_super_test.dart
+++ /dev/null
@@ -1,23 +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.
-
-// Test calling convention of property extraction closures (super edition).
-library bound_closure_super_test;
-
-import 'package:expect/expect.dart';
-
-import 'bound_closure_test.dart' as bound_closure_test;
-
-import 'bound_closure_test.dart' show inscrutable, makeCC;
-
-main() {
-  // Calling main from bound_closure_test.dart to set up native code.
-  bound_closure_test.main();
-
-  var c = inscrutable(makeCC)();
-  var csfoo = inscrutable(c).superfoo;
-
-  Expect.equals('BB.foo(1, B)', csfoo(1));
-  Expect.equals('BB.foo(2, 3)', csfoo(2, 3));
-}
diff --git a/tests/dart2js/native/bound_closure_test.dart b/tests/dart2js/native/bound_closure_test.dart
index 3509722..1702a84 100644
--- a/tests/dart2js/native/bound_closure_test.dart
+++ b/tests/dart2js/native/bound_closure_test.dart
@@ -40,13 +40,14 @@
     return 'CC.foo(' + u + ', ' + v + ')';
   };
 
-  makeBB = function(){return new BB()};
-  makeCC = function(){return new CC()};
-  inscrutable = function(a){return a;};
+  self.makeBB = function(){return new BB()};
+  self.makeCC = function(){return new CC()};
+  self.inscrutable = function(a){return a;};
 
   self.nativeConstructor(BB);
   self.nativeConstructor(CC);
 })()""");
+  applyTestExtensions(['BB', 'CC']);
 }
 
 main() {
diff --git a/tests/dart2js/native/browser_compat_1_prepatched_test.dart b/tests/dart2js/native/browser_compat_1_prepatched_test.dart
index bfd62f5..cf544f1 100644
--- a/tests/dart2js/native/browser_compat_1_prepatched_test.dart
+++ b/tests/dart2js/native/browser_compat_1_prepatched_test.dart
@@ -37,13 +37,13 @@
   window.T1A = T1A;
   window.T1CrazyB = T1CrazyB;
 
-  makeT1A = function(){return new T1A()};
-  makeT1B = function(){return new T1CrazyB()};
-  makeT1C = function(){return new T1fakeA()};
+  self.makeT1A = function(){return new T1A()};
+  self.makeT1B = function(){return new T1CrazyB()};
+  self.makeT1C = function(){return new T1fakeA()};
 
-  self.nativeConstructor(T1A);
-  self.nativeConstructor(T1CrazyB);
-  self.nativeConstructor(T1fakeA);
+  self.nativeConstructor(T1A, undefined, true);
+  self.nativeConstructor(T1CrazyB, undefined, true);
+  self.nativeConstructor(T1fakeA, undefined, true);
 
   var getTagCount = 0;
   getTagCallCount = function() { return getTagCount; };
@@ -71,6 +71,7 @@
 
   dartNativeDispatchHooksTransformer = [transformer1];
 })()''');
+  applyTestExtensions(['T1A', 'T1CrazyB', 'T1fakeA']);
 }
 
 main() {
diff --git a/tests/dart2js/native/browser_compat_1_unpatched_test.dart b/tests/dart2js/native/browser_compat_1_unpatched_test.dart
index 779b72a..82a1fba 100644
--- a/tests/dart2js/native/browser_compat_1_unpatched_test.dart
+++ b/tests/dart2js/native/browser_compat_1_unpatched_test.dart
@@ -38,9 +38,9 @@
   window.T1A = T1A;
   window.T1CrazyB = T1CrazyB;
 
-  makeT1A = function(){return new T1A()};
-  makeT1B = function(){return new T1CrazyB()};
-  makeT1C = function(){return new T1fakeA()};
+  self.makeT1A = function(){return new T1A()};
+  self.makeT1B = function(){return new T1CrazyB()};
+  self.makeT1C = function(){return new T1fakeA()};
 
   self.nativeConstructor(T1A);
   self.nativeConstructor(T1CrazyB);
@@ -74,6 +74,7 @@
 
   dartNativeDispatchHooksTransformer = [transformer1];
 })()""");
+  applyTestExtensions(['T1A', 'T1CrazyB', 'T1fakeA']);
 }
 
 main() {
diff --git a/tests/dart2js/native/browser_compat_2_test.dart b/tests/dart2js/native/browser_compat_2_test.dart
index aa8f131..cef4a56 100644
--- a/tests/dart2js/native/browser_compat_2_test.dart
+++ b/tests/dart2js/native/browser_compat_2_test.dart
@@ -59,19 +59,19 @@
 T1C.prototype.name = function() { return "C"; };
 T1D.prototype.name = function() { return "D"; };
 
-makeT1A = function(){return new T1A()};
-makeT1B = function(){return new T1B()};
-makeT1C = function(){return new T1C()};
-makeT1D = function(){return new T1D()};
+self.makeT1A = function(){return new T1A()};
+self.makeT1B = function(){return new T1B()};
+self.makeT1C = function(){return new T1C()};
+self.makeT1D = function(){return new T1D()};
 
-self.nativeConstructor(T1A);
-self.nativeConstructor(T1B);
-self.nativeConstructor(T1C);
-self.nativeConstructor(T1D);
+self.nativeConstructor(T1A, undefined, true);
+self.nativeConstructor(T1B, undefined, true);
+self.nativeConstructor(T1C, undefined, true);
+self.nativeConstructor(T1D, undefined, true);
 
 var getTagCount = 0;
-getTagCallCount = function() { return getTagCount; };
-clearTagCallCount = function() { getTagCount = 0; };
+self.getTagCallCount = function() { return getTagCount; };
+self.clearTagCallCount = function() { getTagCount = 0; };
 
 function transformer1(hooks) {
   var getTag = hooks.getTag;
@@ -102,8 +102,9 @@
   hooks.getTag = getTagNew;
 }
 
-dartNativeDispatchHooksTransformer = [transformer1, transformer2];
+self.dartNativeDispatchHooksTransformer = [transformer1, transformer2];
 })()''');
+  applyTestExtensions(['T1A', 'T1B', 'T1C', 'T1D']);
 }
 
 main() {
diff --git a/tests/dart2js/native/core_type_check_native_test.dart b/tests/dart2js/native/core_type_check_native_test.dart
index 6356192..572c136 100644
--- a/tests/dart2js/native/core_type_check_native_test.dart
+++ b/tests/dart2js/native/core_type_check_native_test.dart
@@ -31,20 +31,20 @@
   JS('', r"""
 (function(){
   function A() {};
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   function B() {};
-  makeB = function() { return new B(); };
+  self.makeB = function() { return new B(); };
   function C() {};
-  makeC = function() { return new C(); };
+  self.makeC = function() { return new C(); };
   function D() {};
-  makeD = function() { return new D(); };
+  self.makeD = function() { return new D(); };
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
   self.nativeConstructor(C);
   self.nativeConstructor(D);
-})()
-""");
+})()""");
+  applyTestExtensions(['A', 'B', 'C', 'D']);
 }
 
 checkTest(value, expectComparable, expectPattern) {
diff --git a/tests/dart2js/native/dispatch_property_initialization_test.dart b/tests/dart2js/native/dispatch_property_initialization_test.dart
index 4e4ed95..21a6e9f 100644
--- a/tests/dart2js/native/dispatch_property_initialization_test.dart
+++ b/tests/dart2js/native/dispatch_property_initialization_test.dart
@@ -23,6 +23,7 @@
 
   self.nativeConstructor(Foo);
 })()""");
+  applyTestExtensions(['Foo']);
 }
 
 main() {
diff --git a/tests/dart2js/native/downcast_test.dart b/tests/dart2js/native/downcast_test.dart
index ab74f5f..9355948 100644
--- a/tests/dart2js/native/downcast_test.dart
+++ b/tests/dart2js/native/downcast_test.dart
@@ -46,12 +46,13 @@
 inherits(B, A);
 A.prototype.read = function() { return this._x; };
 A.prototype.write = function(x) { this._x = x; };
-makeA = function(){return new A()};
-makeB = function(){return new B()};
+self.makeA = function(){return new A()};
+self.makeB = function(){return new B()};
 
 self.nativeConstructor(A);
 self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 class C {}
diff --git a/tests/dart2js/native/error_safeToString_test.dart b/tests/dart2js/native/error_safeToString_test.dart
index 022b53a..ecb3544 100644
--- a/tests/dart2js/native/error_safeToString_test.dart
+++ b/tests/dart2js/native/error_safeToString_test.dart
@@ -36,45 +36,46 @@
 void setup() {
   JS('', r"""
 (function(){
-  makeA = function(){return {hello: 123};};
+  self.makeA = function(){return {hello: 123};};
 
   function BB(){}
-  makeB = function(){return new BB();};
+  self.makeB = function(){return new BB();};
 
   function CC(){}
-  makeC = function(){
+  self.makeC = function(){
     var x = new CC();
     x.constructor = null;  // Foils constructor lookup.
     return x;
   };
 
   function DD(){}
-  makeD = function(){
+  self.makeD = function(){
     var x = new DD();
     x.constructor = {name: 'DDxxx'};  // Foils constructor lookup.
     return x;
   };
 
   function EE(){}
-  makeE = function(){
+  self.makeE = function(){
     var x = new EE();
     x.constructor = function Liar(){};  // Looks like a legitimate constructor.
     return x;
   };
 
   function PPPP(){}
-  makeP = function(){return new PPPP();};
+  self.makeP = function(){return new PPPP();};
 
   function QQQQ(){}
-  makeQ = function(){return new QQQQ();};
+  self.makeQ = function(){return new QQQQ();};
 
   function RRRR(){}
-  makeR = function(){return new RRRR();};
+  self.makeR = function(){return new RRRR();};
 
   self.nativeConstructor(PPPP);
   self.nativeConstructor(QQQQ);
   self.nativeConstructor(RRRR);
 })()""");
+  applyTestExtensions(['PPPP', 'QQQQ', 'RRRR']);
 }
 
 expectTypeName(expectedName, s) {
diff --git a/tests/dart2js/native/event_loop_test.dart b/tests/dart2js/native/event_loop_test.dart
index e69d542..2706bb7 100644
--- a/tests/dart2js/native/event_loop_test.dart
+++ b/tests/dart2js/native/event_loop_test.dart
@@ -20,9 +20,10 @@
 (function(){
 function A() {}
 A.prototype.foo = function(f) { return f(); };
-makeA = function() { return new A(); };
+self.makeA = function() { return new A(); };
 self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/fake_thing_2_test.dart b/tests/dart2js/native/fake_thing_2_test.dart
index f630746..8ca0394 100644
--- a/tests/dart2js/native/fake_thing_2_test.dart
+++ b/tests/dart2js/native/fake_thing_2_test.dart
@@ -23,14 +23,15 @@
 (function(){
   function A() {}
   A.prototype.$isThing = true;
-  make1 = function(){return new A()};
-  make2 = function(){return {$isThing: true}};
+  self.make1 = function(){return new A()};
+  self.make2 = function(){return {$isThing: true}};
   function NT() {}
   NT.prototype.$isThing = true;
-  make3 = function(){return new NT()};
+  self.make3 = function(){return new NT()};
 
   self.nativeConstructor(NT);
 })()""");
+  applyTestExtensions(['NT']);
 }
 
 main() {
diff --git a/tests/dart2js/native/fake_thing_test.dart b/tests/dart2js/native/fake_thing_test.dart
index 542a5ca..4a699c4 100644
--- a/tests/dart2js/native/fake_thing_test.dart
+++ b/tests/dart2js/native/fake_thing_test.dart
@@ -21,8 +21,8 @@
 (function(){
   function A() {}
   A.prototype.$isThing = true;
-  make1 = function(){return new A();};
-  make2 = function(){return {$isThing: true}};
+  self.make1 = function(){return new A();};
+  self.make2 = function(){return {$isThing: true}};
 })()""");
 }
 
diff --git a/tests/dart2js/native/field_type2_test.dart b/tests/dart2js/native/field_type2_test.dart
index fdf77bb..edece7a 100644
--- a/tests/dart2js/native/field_type2_test.dart
+++ b/tests/dart2js/native/field_type2_test.dart
@@ -19,10 +19,11 @@
 (function(){
 // This code is all inside 'setup' and so not accessible from the global scope.
 function Node(parent){ this.parentNode = parent; }
-makeNode = function(p){return new Node(p);};
+self.makeNode = function(p){return new Node(p);};
 
 self.nativeConstructor(Node);
 })()""");
+  applyTestExtensions(['Node']);
 }
 
 main() {
diff --git a/tests/dart2js/native/field_type_test.dart b/tests/dart2js/native/field_type_test.dart
index 8135cd5..5cc73d0 100644
--- a/tests/dart2js/native/field_type_test.dart
+++ b/tests/dart2js/native/field_type_test.dart
@@ -48,9 +48,10 @@
 (function(){
   // This code is inside 'setup' and so not accessible from the global scope.
   function Node(parent){ this.parentNode = parent; }
-  makeNode = function(p){return new Node(p);};
+  self.makeNode = function(p){return new Node(p);};
   self.nativeConstructor(Node);
 })()""");
+  applyTestExtensions(['Node']);
 }
 
 main() {
diff --git a/tests/dart2js/native/fixup_get_tag_test.dart b/tests/dart2js/native/fixup_get_tag_test.dart
index e4e1ab8..a904982 100644
--- a/tests/dart2js/native/fixup_get_tag_test.dart
+++ b/tests/dart2js/native/fixup_get_tag_test.dart
@@ -33,11 +33,12 @@
   function B(){ }
   B.prototype.token = function () { return 'isB'; };
 
-  makeA = function() { return new A(); };
-  makeB = function() { return new B(); };
+  self.makeA = function() { return new A(); };
+  self.makeB = function() { return new B(); };
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 makeA() native;
diff --git a/tests/dart2js/native/foreign_test.dart b/tests/dart2js/native/foreign_test.dart
index 31ab23b..d69efdd 100644
--- a/tests/dart2js/native/foreign_test.dart
+++ b/tests/dart2js/native/foreign_test.dart
@@ -33,7 +33,7 @@
   // Ensure there will be isNaN and NaN variable names.
   var isNaN = called ? 42 : 44;
   var NaN = called ? 52 : 54;
-  Expect.isFalse(JS('bool', 'isNaN(#)', isNaN));
-  Expect.isFalse(JS('bool', 'isNaN(#)', NaN));
-  Expect.isTrue(JS('bool', 'isNaN(#)', double.nan));
+  Expect.isFalse(JS('bool', 'self.isNaN(#)', isNaN));
+  Expect.isFalse(JS('bool', 'self.isNaN(#)', NaN));
+  Expect.isTrue(JS('bool', 'self.isNaN(#)', double.nan));
 }
diff --git a/tests/dart2js/native/hash_code_test.dart b/tests/dart2js/native/hash_code_test.dart
index 137be8f..0b1f391 100644
--- a/tests/dart2js/native/hash_code_test.dart
+++ b/tests/dart2js/native/hash_code_test.dart
@@ -20,12 +20,13 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/internal_library_test.dart b/tests/dart2js/native/internal_library_test.dart
deleted file mode 100644
index 7f81f6c..0000000
--- a/tests/dart2js/native/internal_library_test.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.
-
-// Test that a private library can be accessed from libraries in this special
-// test folder.
-
-import 'dart:_js_helper';
-
-void main() {
-  print(loadDeferredLibrary);
-}
diff --git a/tests/dart2js/native/issue9182_test.dart b/tests/dart2js/native/issue9182_test.dart
index 62a0a60..0e22af0 100644
--- a/tests/dart2js/native/issue9182_test.dart
+++ b/tests/dart2js/native/issue9182_test.dart
@@ -28,9 +28,10 @@
   JS('', r"""
 (function(){
   function A(){}
-  makeA = function() { return new A() };
+  self.makeA = function() { return new A() };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 makeA() native;
diff --git a/tests/dart2js/native/jsobject_test.dart b/tests/dart2js/native/jsobject_test.dart
index dd0ec8e..0b769d0 100644
--- a/tests/dart2js/native/jsobject_test.dart
+++ b/tests/dart2js/native/jsobject_test.dart
@@ -27,16 +27,17 @@
 void setup() {
   JS('', r"""
 (function(){
-makeA = function(){return {hello: 123};};
+self.makeA = function(){return {hello: 123};};
 
 function BB(){}
-makeB = function(){return new BB();};
+self.makeB = function(){return new BB();};
 
 function QQ(){}
-makeQ = function(){return new QQ();};
+self.makeQ = function(){return new QQ();};
 
 self.nativeConstructor(QQ);
 })()""");
+  applyTestExtensions(['QQ']);
 }
 
 class Is<T> {
diff --git a/tests/dart2js/native/name_conflict_test.dart b/tests/dart2js/native/name_conflict_test.dart
index 555c78e..3294895 100644
--- a/tests/dart2js/native/name_conflict_test.dart
+++ b/tests/dart2js/native/name_conflict_test.dart
@@ -35,9 +35,10 @@
   function I(){}
   I.prototype.read = function() { return this._x; };
   I.prototype.write = function(x) { this._x = x; };
-  makeI = function(){return new I()};
+  self.makeI = function(){return new I()};
   self.nativeConstructor(I);
 })()""");
+  applyTestExtensions(['I']);
 }
 
 // A pure Dart implementation of I.
diff --git a/tests/dart2js/native/native_call_arity1_frog_test.dart b/tests/dart2js/native/native_call_arity1_frog_test.dart
index f590001..e308b69 100644
--- a/tests/dart2js/native/native_call_arity1_frog_test.dart
+++ b/tests/dart2js/native/native_call_arity1_frog_test.dart
@@ -37,12 +37,13 @@
   function B() {}
   B.prototype.foo = function () { return arguments.length; };
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamicContext() {
diff --git a/tests/dart2js/native/native_call_arity2_frog_test.dart b/tests/dart2js/native/native_call_arity2_frog_test.dart
index 1646809..32a1b63 100644
--- a/tests/dart2js/native/native_call_arity2_frog_test.dart
+++ b/tests/dart2js/native/native_call_arity2_frog_test.dart
@@ -40,12 +40,13 @@
   B.prototype.foo = function () { return arguments.length; };
   inherits(B, A);
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamicContext() {
diff --git a/tests/dart2js/native/native_call_arity3_frog_test.dart b/tests/dart2js/native/native_call_arity3_frog_test.dart
index 3be4585..c33bc38 100644
--- a/tests/dart2js/native/native_call_arity3_frog_test.dart
+++ b/tests/dart2js/native/native_call_arity3_frog_test.dart
@@ -33,12 +33,13 @@
   function B() {}
   B.prototype.foo = function () { return arguments.length; };
 
-  makeA = function(){return new A();};
-  makeB = function(){return new B();};
+  self.makeA = function(){return new A();};
+  self.makeB = function(){return new B();};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamicContext() {
diff --git a/tests/dart2js/native/native_checked_arguments1_frog_test.dart b/tests/dart2js/native/native_checked_arguments1_frog_test.dart
index ddce60e..0ae9012 100644
--- a/tests/dart2js/native/native_checked_arguments1_frog_test.dart
+++ b/tests/dart2js/native/native_checked_arguments1_frog_test.dart
@@ -24,6 +24,7 @@
 void setup() {
   JS('', r"""
 (function(){
+  "use strict";
   function A() {}
   A.prototype.foo = function (x) { return x + 1; };
   A.prototype.cmp = function (x) { return 0; };
@@ -32,12 +33,13 @@
   B.prototype.foo = function (x) { return x + 'ha!'; };
   B.prototype.cmp = function (x) { return 1; };
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 expectThrows(action()) {
diff --git a/tests/dart2js/native/native_checked_fields_frog_test.dart b/tests/dart2js/native/native_checked_fields_frog_test.dart
index 76d8902..e87c801 100644
--- a/tests/dart2js/native/native_checked_fields_frog_test.dart
+++ b/tests/dart2js/native/native_checked_fields_frog_test.dart
@@ -28,12 +28,13 @@
 
   function B() {}
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 expectThrows(action()) {
diff --git a/tests/dart2js/native/native_class_avoids_hidden_name_frog_test.dart b/tests/dart2js/native/native_class_avoids_hidden_name_frog_test.dart
index 6e4a95c..dfe9dda 100644
--- a/tests/dart2js/native/native_class_avoids_hidden_name_frog_test.dart
+++ b/tests/dart2js/native/native_class_avoids_hidden_name_frog_test.dart
@@ -32,8 +32,8 @@
 (function(){
   // Poison hidden native names 'BB' and 'CC' to prove the compiler didn't place
   // anything on the hidden native class.
-  BB = null;
-  CC = null;
+  self.BB = null;
+  self.CC = null;
 })()""");
 }
 
@@ -43,11 +43,12 @@
   // This code is inside 'setup' and so not accessible from the global scope.
   function BB(){}
   function CC(){}
-  makeA = function(){return new BB()};  // AA is native "BB"
-  makeB = function(){return new CC()};  // BB is native "CC"
+  self.makeA = function(){return new BB()};  // AA is native "BB"
+  self.makeB = function(){return new CC()};  // BB is native "CC"
   self.nativeConstructor(BB);
   self.nativeConstructor(CC);
 })()""");
+  applyTestExtensions(['BB', 'CC']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_class_fields_2_test.dart b/tests/dart2js/native/native_class_fields_2_test.dart
index 6529946..6575857 100644
--- a/tests/dart2js/native/native_class_fields_2_test.dart
+++ b/tests/dart2js/native/native_class_fields_2_test.dart
@@ -37,9 +37,10 @@
     return a;
   }
 
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 A makeA() native;
diff --git a/tests/dart2js/native/native_class_fields_3_test.dart b/tests/dart2js/native/native_class_fields_3_test.dart
index dd2824d..8a53e50 100644
--- a/tests/dart2js/native/native_class_fields_3_test.dart
+++ b/tests/dart2js/native/native_class_fields_3_test.dart
@@ -67,9 +67,10 @@
     return a;
   }
 
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 A makeA() native;
diff --git a/tests/dart2js/native/native_class_fields_test.dart b/tests/dart2js/native/native_class_fields_test.dart
index 64122ac..e0f5300 100644
--- a/tests/dart2js/native/native_class_fields_test.dart
+++ b/tests/dart2js/native/native_class_fields_test.dart
@@ -42,6 +42,7 @@
 makeA = function(){return new A()};
 self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 A makeA() native;
diff --git a/tests/dart2js/native/native_class_inheritance1_frog_test.dart b/tests/dart2js/native/native_class_inheritance1_frog_test.dart
index 322dcba..44c5cb2 100644
--- a/tests/dart2js/native/native_class_inheritance1_frog_test.dart
+++ b/tests/dart2js/native/native_class_inheritance1_frog_test.dart
@@ -57,8 +57,8 @@
   A1.prototype.foo = function(){return 100;};
   B1.prototype.foo = function(){return 200;};
 
-  makeA1 = function(){return new A1()};
-  makeB1 = function(){return new B1()};
+  self.makeA1 = function(){return new A1()};
+  self.makeB1 = function(){return new B1()};
 
   function A2(){}
   function B2(){}
@@ -66,14 +66,15 @@
   A2.prototype.foo = function(a){return a + 10000;};
   B2.prototype.foo = function(z){return z + 20000;};
 
-  makeA2 = function(){return new A2()};
-  makeB2 = function(){return new B2()};
+  self.makeA2 = function(){return new A2()};
+  self.makeB2 = function(){return new B2()};
 
   self.nativeConstructor(A1);
   self.nativeConstructor(A2);
   self.nativeConstructor(B1);
   self.nativeConstructor(B2);
 })()""");
+  applyTestExtensions(['A1', 'A2', 'B1', 'B2']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_class_inheritance2_frog_test.dart b/tests/dart2js/native/native_class_inheritance2_frog_test.dart
index 8fa4b67..66fb625 100644
--- a/tests/dart2js/native/native_class_inheritance2_frog_test.dart
+++ b/tests/dart2js/native/native_class_inheritance2_frog_test.dart
@@ -56,16 +56,17 @@
   A.prototype.foo = function(a){return 'A.foo(' + a + ')'};
   C.prototype.foo = function(z){return 'C.foo(' + z + ')'};
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
-  makeC = function(){return new C()};
-  makeD = function(){return new D()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
+  self.makeC = function(){return new C()};
+  self.makeD = function(){return new D()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
   self.nativeConstructor(C);
   self.nativeConstructor(D);
 })()""");
+  applyTestExtensions(['A', 'B', 'C', 'D']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_class_inheritance3_frog_test.dart b/tests/dart2js/native/native_class_inheritance3_frog_test.dart
index af5a8e3..d123928 100644
--- a/tests/dart2js/native/native_class_inheritance3_frog_test.dart
+++ b/tests/dart2js/native/native_class_inheritance3_frog_test.dart
@@ -48,24 +48,25 @@
   function B1(){}
   inherits(B1, A1);
 
-  makeA1 = function(){return new A1()};
-  makeB1 = function(){return new B1()};
+  self.makeA1 = function(){return new A1()};
+  self.makeB1 = function(){return new B1()};
 
   function A2(){}
   function B2(){}
   inherits(B2, A2);
   A2.prototype.foo = function(a){return 'A2.foo(' + a  + ')';};
 
-  makeA2 = function(){return new A2()};
-  makeB2 = function(){return new B2()};
+  self.makeA2 = function(){return new A2()};
+  self.makeB2 = function(){return new B2()};
 
-  makeObject = function(){return new Object()};
+  self.makeObject = function(){return new Object()};
 
   self.nativeConstructor(A1);
   self.nativeConstructor(A2);
   self.nativeConstructor(B1);
   self.nativeConstructor(B2);
 })()""");
+  applyTestExtensions(['A1', 'A2', 'B1', 'B2']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_class_inheritance4_frog_test.dart b/tests/dart2js/native/native_class_inheritance4_frog_test.dart
index 25f8fcd..4d65752 100644
--- a/tests/dart2js/native/native_class_inheritance4_frog_test.dart
+++ b/tests/dart2js/native/native_class_inheritance4_frog_test.dart
@@ -52,12 +52,13 @@
   function A(){}
   function B(){}
   inherits(B, A);
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testBasicA_dynamic() {
diff --git a/tests/dart2js/native/native_class_is_check1_frog_test.dart b/tests/dart2js/native/native_class_is_check1_frog_test.dart
index 6b8bb37..266db0e 100644
--- a/tests/dart2js/native/native_class_is_check1_frog_test.dart
+++ b/tests/dart2js/native/native_class_is_check1_frog_test.dart
@@ -29,9 +29,10 @@
   function A(){}
   A.prototype.read = function() { return this._x; };
   A.prototype.write = function(x) { this._x = x; };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 class B {}
diff --git a/tests/dart2js/native/native_class_is_check3_frog_test.dart b/tests/dart2js/native/native_class_is_check3_frog_test.dart
index 98cbf91..1e6f36e 100644
--- a/tests/dart2js/native/native_class_is_check3_frog_test.dart
+++ b/tests/dart2js/native/native_class_is_check3_frog_test.dart
@@ -47,11 +47,12 @@
   inherits(B, A);
   A.prototype.read = function() { return this._x; };
   A.prototype.write = function(x) { this._x = x; };
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 class C {}
diff --git a/tests/dart2js/native/native_class_with_dart_methods_frog_test.dart b/tests/dart2js/native/native_class_with_dart_methods_frog_test.dart
index 574e684..d3cdb09 100644
--- a/tests/dart2js/native/native_class_with_dart_methods_frog_test.dart
+++ b/tests/dart2js/native/native_class_with_dart_methods_frog_test.dart
@@ -24,9 +24,10 @@
   JS('', r"""
 (function(){
   function A() {}
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_closure_identity_frog_test.dart b/tests/dart2js/native/native_closure_identity_frog_test.dart
index c5f5084..9c23278 100644
--- a/tests/dart2js/native/native_closure_identity_frog_test.dart
+++ b/tests/dart2js/native/native_closure_identity_frog_test.dart
@@ -22,10 +22,11 @@
   A.prototype.setClosure = function(f) { this.f = f; };
   A.prototype.check = function(f) { return this.f === f; };
   A.prototype.invoke = function() { return this.f(); };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 var staticClosure;
diff --git a/tests/dart2js/native/native_constructor_name_test.dart b/tests/dart2js/native/native_constructor_name_test.dart
index 9d60a40..e1c7191 100644
--- a/tests/dart2js/native/native_constructor_name_test.dart
+++ b/tests/dart2js/native/native_constructor_name_test.dart
@@ -23,9 +23,10 @@
   JS('', r"""
 (function(){
   function A(){}
-  makeZ = function(){return new A()};
+  self.makeZ = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_equals_frog_test.dart b/tests/dart2js/native/native_equals_frog_test.dart
index 0b460b9..de5844c 100644
--- a/tests/dart2js/native/native_equals_frog_test.dart
+++ b/tests/dart2js/native/native_equals_frog_test.dart
@@ -27,11 +27,12 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_exception2_test.dart b/tests/dart2js/native/native_exception2_test.dart
index 59cf5b0..9ab9ffc 100644
--- a/tests/dart2js/native/native_exception2_test.dart
+++ b/tests/dart2js/native/native_exception2_test.dart
@@ -21,9 +21,10 @@
   JS('', r"""
 (function(){
   function NativeClass() {}
-  makeNativeClass = function() { return new NativeClass(); };
+  self.makeNativeClass = function() { return new NativeClass(); };
   self.nativeConstructor(NativeClass);
 })()""");
+  applyTestExtensions(['NativeClass']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_exceptions1_frog_test.dart b/tests/dart2js/native/native_exceptions1_frog_test.dart
index b9957e8..7585a39 100644
--- a/tests/dart2js/native/native_exceptions1_frog_test.dart
+++ b/tests/dart2js/native/native_exceptions1_frog_test.dart
@@ -47,6 +47,7 @@
   A = null;
   E = null;
 })()""");
+  applyTestExtensions(['E', 'A']);
 }
 
 void setup2() {
@@ -60,7 +61,7 @@
   if (x & 1) throw new E(100);
   return  x / 2;
 };
-makeA = function(){return new A()};
+self.makeA = function(){return new A()};
 
 self.nativeConstructor(E);
 self.nativeConstructor(A);
diff --git a/tests/dart2js/native/native_field_invocation2_test.dart b/tests/dart2js/native/native_field_invocation2_test.dart
index 9c150687..c15ec25 100644
--- a/tests/dart2js/native/native_field_invocation2_test.dart
+++ b/tests/dart2js/native/native_field_invocation2_test.dart
@@ -36,7 +36,7 @@
 void setup() {
   JS('', r"""
 (function(){
-nativeId = function(x) { return x; }
+self.nativeId = function(x) { return x; }
 })()""");
 }
 
diff --git a/tests/dart2js/native/native_field_invocation3_test.dart b/tests/dart2js/native/native_field_invocation3_test.dart
index 9ed3d9c..613f610 100644
--- a/tests/dart2js/native/native_field_invocation3_test.dart
+++ b/tests/dart2js/native/native_field_invocation3_test.dart
@@ -10,9 +10,10 @@
   JS('', r"""
 (function(){
   function CC() {}
-  makeCC = function() { return new CC() };
+  self.makeCC = function() { return new CC() };
   self.nativeConstructor(CC);
 })()""");
+  applyTestExtensions(['CC']);
 }
 
 @Native("CC")
diff --git a/tests/dart2js/native/native_field_invocation4_test.dart b/tests/dart2js/native/native_field_invocation4_test.dart
index afce3c09..0855c72 100644
--- a/tests/dart2js/native/native_field_invocation4_test.dart
+++ b/tests/dart2js/native/native_field_invocation4_test.dart
@@ -18,7 +18,7 @@
 void setup() {
   JS('', r"""
 (function(){
-nativeId = function(x) { return x; }
+self.nativeId = function(x) { return x; }
 })()""");
 }
 
diff --git a/tests/dart2js/native/native_field_invocation5_test.dart b/tests/dart2js/native/native_field_invocation5_test.dart
index abd0169..f2ef30c 100644
--- a/tests/dart2js/native/native_field_invocation5_test.dart
+++ b/tests/dart2js/native/native_field_invocation5_test.dart
@@ -11,10 +11,11 @@
   JS('', r"""
 (function(){
   function CC() {}
-  makeCC = function() { return new CC() };
-  nativeFirst = function(x, y) { return x; };
+  self.makeCC = function() { return new CC() };
+  self.nativeFirst = function(x, y) { return x; };
   self.nativeConstructor(CC);
 })()""");
+  applyTestExtensions(['CC']);
 }
 
 class C {
diff --git a/tests/dart2js/native/native_field_invocation6_test.dart b/tests/dart2js/native/native_field_invocation6_test.dart
index 17ed660..a226bbc 100644
--- a/tests/dart2js/native/native_field_invocation6_test.dart
+++ b/tests/dart2js/native/native_field_invocation6_test.dart
@@ -10,12 +10,13 @@
 void setup() {
   JS('', r"""
 (function(){
-  nativeFirst = function(x, y) { return x; };
+  self.nativeFirst = function(x, y) { return x; };
 
   function A() {}
-  makeA = function() { return new A() };
+  self.makeA = function() { return new A() };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 @Native("A")
diff --git a/tests/dart2js/native/native_field_invocation_test.dart b/tests/dart2js/native/native_field_invocation_test.dart
index e6f13b6..bdda86f 100644
--- a/tests/dart2js/native/native_field_invocation_test.dart
+++ b/tests/dart2js/native/native_field_invocation_test.dart
@@ -18,7 +18,7 @@
 void setup() {
   JS('', r"""
 (function(){
-  nativeId = function(x) { return x; }
+  self.nativeId = function(x) { return x; }
 })()""");
 }
 
diff --git a/tests/dart2js/native/native_field_name_test.dart b/tests/dart2js/native/native_field_name_test.dart
index 89f401f..1b991ca 100644
--- a/tests/dart2js/native/native_field_name_test.dart
+++ b/tests/dart2js/native/native_field_name_test.dart
@@ -43,10 +43,11 @@
     return a;
   }
 
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 /*A*/ makeA() native;
diff --git a/tests/dart2js/native/native_field_optimization_test.dart b/tests/dart2js/native/native_field_optimization_test.dart
index 5b7e061..7ce2740 100644
--- a/tests/dart2js/native/native_field_optimization_test.dart
+++ b/tests/dart2js/native/native_field_optimization_test.dart
@@ -42,10 +42,11 @@
     }
   });
 
-  makeFoo = function() { return new Foo() };
+  self.makeFoo = function() { return new Foo() };
 
   self.nativeConstructor(Foo);
 })()""");
+  applyTestExtensions(['Foo']);
 }
 
 test1() {
diff --git a/tests/dart2js/native/native_field_rename_1_frog_test.dart b/tests/dart2js/native/native_field_rename_1_frog_test.dart
index 27b4710..7c3202e 100644
--- a/tests/dart2js/native/native_field_rename_1_frog_test.dart
+++ b/tests/dart2js/native/native_field_rename_1_frog_test.dart
@@ -45,12 +45,13 @@
   function X(){}
   X.prototype.key = function(){return 666;};
 
-  makeA = function(){return new A()};
-  makeX = function(){return new X()};
+  self.makeA = function(){return new A()};
+  self.makeX = function(){return new X()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(X);
 })()""");
+  applyTestExtensions(['A', 'X']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js/native/native_field_rename_2_frog_test.dart b/tests/dart2js/native/native_field_rename_2_frog_test.dart
index 93fce23..022c5ce 100644
--- a/tests/dart2js/native/native_field_rename_2_frog_test.dart
+++ b/tests/dart2js/native/native_field_rename_2_frog_test.dart
@@ -48,12 +48,13 @@
   function X(){}
   X.prototype.key = function(){return 666;};
 
-  makeA = function(){return new A()};
-  makeX = function(){return new X()};
+  self.makeA = function(){return new A()};
+  self.makeX = function(){return new X()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(X);
 })()""");
+  applyTestExtensions(['A', 'X']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js/native/native_method_inlining_test.dart b/tests/dart2js/native/native_method_inlining_test.dart
index ba0ee3b..3cdb5e8 100644
--- a/tests/dart2js/native/native_method_inlining_test.dart
+++ b/tests/dart2js/native/native_method_inlining_test.dart
@@ -64,7 +64,7 @@
   A.prototype.foo = function () { return arguments.length; };
   A.prototype.callFun = function (fn) { return fn ? fn(123) : 1; };
 
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   findMethodTextContaining = function (instance, string) {
     var proto = Object.getPrototypeOf(instance);
@@ -79,6 +79,7 @@
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 void match(String s, String pattern1) {
diff --git a/tests/dart2js/native/native_method_rename1_frog_test.dart b/tests/dart2js/native/native_method_rename1_frog_test.dart
index 5d05694..52ba44f 100644
--- a/tests/dart2js/native/native_method_rename1_frog_test.dart
+++ b/tests/dart2js/native/native_method_rename1_frog_test.dart
@@ -35,10 +35,11 @@
   A.prototype.barA = function(){return 200;};
   A.prototype.bazA = function(){return 300;};
 
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js/native/native_method_rename2_frog_test.dart b/tests/dart2js/native/native_method_rename2_frog_test.dart
index 35713a2..8db0eca 100644
--- a/tests/dart2js/native/native_method_rename2_frog_test.dart
+++ b/tests/dart2js/native/native_method_rename2_frog_test.dart
@@ -41,12 +41,13 @@
   inherits(B, A);
   B.prototype.fooB = function(){return 200;};
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js/native/native_method_rename3_frog_test.dart b/tests/dart2js/native/native_method_rename3_frog_test.dart
index c5759b2..2100427 100644
--- a/tests/dart2js/native/native_method_rename3_frog_test.dart
+++ b/tests/dart2js/native/native_method_rename3_frog_test.dart
@@ -48,12 +48,13 @@
   inherits(B, A);
   B.prototype.fooB = function(){return 200;};
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js/native/native_method_with_keyword_name_test.dart b/tests/dart2js/native/native_method_with_keyword_name_test.dart
index c535d90..2198634 100644
--- a/tests/dart2js/native/native_method_with_keyword_name_test.dart
+++ b/tests/dart2js/native/native_method_with_keyword_name_test.dart
@@ -19,9 +19,10 @@
 function A() {}
 A.prototype.delete = function() { return 87; };
 
-makeA = function(){return new A()};
+self.makeA = function(){return new A()};
 self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_missing_method1_frog_test.dart b/tests/dart2js/native/native_missing_method1_frog_test.dart
index d0595f6..13e8277 100644
--- a/tests/dart2js/native/native_missing_method1_frog_test.dart
+++ b/tests/dart2js/native/native_missing_method1_frog_test.dart
@@ -14,9 +14,10 @@
 (function(){
   function A() {};
   A.prototype.foo = function() { return  99; };
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 class B {
diff --git a/tests/dart2js/native/native_missing_method2_frog_test.dart b/tests/dart2js/native/native_missing_method2_frog_test.dart
index ae5799f..6e1f694 100644
--- a/tests/dart2js/native/native_missing_method2_frog_test.dart
+++ b/tests/dart2js/native/native_missing_method2_frog_test.dart
@@ -14,9 +14,10 @@
 (function(){
   function A() {};
   A.prototype.foo = function() { return  42; };
-  makeA = function() { return new A() };
+  self.makeA = function() { return new A() };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 class B {
diff --git a/tests/dart2js/native/native_mixin_field2_test.dart b/tests/dart2js/native/native_mixin_field2_test.dart
index 4612391..80370ce 100644
--- a/tests/dart2js/native/native_mixin_field2_test.dart
+++ b/tests/dart2js/native/native_mixin_field2_test.dart
@@ -44,12 +44,13 @@
 (function(){
   function A() {this.foo='A-foo';}
   function B() {A.call(this);this.bar='B-bar';this.baz='M1-baz';}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 @pragma('dart2js:assumeDynamic')
diff --git a/tests/dart2js/native/native_mixin_field_test.dart b/tests/dart2js/native/native_mixin_field_test.dart
index 7f1aebb..e9c80e9 100644
--- a/tests/dart2js/native/native_mixin_field_test.dart
+++ b/tests/dart2js/native/native_mixin_field_test.dart
@@ -34,12 +34,13 @@
 (function(){
   function A() {this.foo='A-foo';}
   function B() {A.call(this);this.bar='B-bar';this.baz='M1-baz';}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_mixin_multiple2_test.dart b/tests/dart2js/native/native_mixin_multiple2_test.dart
index 0747e6b..04f5b71 100644
--- a/tests/dart2js/native/native_mixin_multiple2_test.dart
+++ b/tests/dart2js/native/native_mixin_multiple2_test.dart
@@ -30,10 +30,11 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_mixin_multiple3_test.dart b/tests/dart2js/native/native_mixin_multiple3_test.dart
index 1963186..ac3442d 100644
--- a/tests/dart2js/native/native_mixin_multiple3_test.dart
+++ b/tests/dart2js/native/native_mixin_multiple3_test.dart
@@ -44,14 +44,15 @@
   function A() {}
   function B() {}
   function C() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
-  makeC = function(){return new C()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
+  self.makeC = function(){return new C()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
   self.nativeConstructor(C);
 })()""");
+  applyTestExtensions(['A', 'B', 'C']);
 }
 
 var g;
diff --git a/tests/dart2js/native/native_mixin_multiple_test.dart b/tests/dart2js/native/native_mixin_multiple_test.dart
index 310d75b..68e6714 100644
--- a/tests/dart2js/native/native_mixin_multiple_test.dart
+++ b/tests/dart2js/native/native_mixin_multiple_test.dart
@@ -34,12 +34,13 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_mixin_test.dart b/tests/dart2js/native/native_mixin_test.dart
index 64bd3e4..2ba3523 100644
--- a/tests/dart2js/native/native_mixin_test.dart
+++ b/tests/dart2js/native/native_mixin_test.dart
@@ -30,12 +30,13 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_mixin_with_plain_test.dart b/tests/dart2js/native/native_mixin_with_plain_test.dart
index 5130caa..e31b904 100644
--- a/tests/dart2js/native/native_mixin_with_plain_test.dart
+++ b/tests/dart2js/native/native_mixin_with_plain_test.dart
@@ -45,12 +45,13 @@
 (function(){
   function A() {this.aa = 'aa'}
   function B() {this.aa = 'bb'}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_named_constructors2_frog_test.dart b/tests/dart2js/native/native_named_constructors2_frog_test.dart
index b200628..8e25687 100644
--- a/tests/dart2js/native/native_named_constructors2_frog_test.dart
+++ b/tests/dart2js/native/native_named_constructors2_frog_test.dart
@@ -31,9 +31,10 @@
   // This code is inside 'setup' and so not accessible from the global scope.
   function A(arg) { this._x = arg; }
   A.prototype.foo = function() { return this._x; };
-  makeA = function(arg) { return new A(arg); };
+  self.makeA = function(arg) { return new A(arg); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_named_constructors3_frog_test.dart b/tests/dart2js/native/native_named_constructors3_frog_test.dart
index 949a405..809bca4 100644
--- a/tests/dart2js/native/native_named_constructors3_frog_test.dart
+++ b/tests/dart2js/native/native_named_constructors3_frog_test.dart
@@ -30,9 +30,10 @@
   // This code is inside 'setup' and so not accessible from the global scope.
   function A(arg) { this._x = arg; }
   A.prototype.foo = function(){ return this._x; };
-  makeA = function(arg) { return new A(arg); };
+  self.makeA = function(arg) { return new A(arg); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_no_such_method_exception2_frog_test.dart b/tests/dart2js/native/native_no_such_method_exception2_frog_test.dart
index 5df3c12..ccc4787 100644
--- a/tests/dart2js/native/native_no_such_method_exception2_frog_test.dart
+++ b/tests/dart2js/native/native_no_such_method_exception2_frog_test.dart
@@ -31,13 +31,14 @@
     function A() {}
     function B() {}
     inherits(B, A);
-    makeA = function() { return new A() };
-    makeB = function() { return new B() };
+    self.makeA = function() { return new A() };
+    self.makeB = function() { return new B() };
     B.prototype.foo = function() { return 42; };
 
     self.nativeConstructor(A);
     self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_no_such_method_exception_frog_test.dart b/tests/dart2js/native/native_no_such_method_exception_frog_test.dart
index c4a7951..1c8aa01f 100644
--- a/tests/dart2js/native/native_no_such_method_exception_frog_test.dart
+++ b/tests/dart2js/native/native_no_such_method_exception_frog_test.dart
@@ -20,9 +20,10 @@
   JS('', r"""
 (function(){
   function A() {}
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_novel_html_test.dart b/tests/dart2js/native/native_novel_html_test.dart
index 3738ff0..cafd607 100644
--- a/tests/dart2js/native/native_novel_html_test.dart
+++ b/tests/dart2js/native/native_novel_html_test.dart
@@ -23,17 +23,18 @@
   HTMLGoofyElement.prototype.nativeMethod = function(a) {
     return 'Goofy.nativeMethod(' + a  + ')';
   };
-  makeE = function(){return new HTMLGoofyElement()};
+  self.makeE = function(){return new HTMLGoofyElement()};
 
   // A non-HTML element with a misleading name.
   function HTMLFakeyElement(){}
   HTMLFakeyElement.prototype.nativeMethod = function(a) {
     return 'Fakey.nativeMethod(' + a  + ')';
   };
-  makeF = function(){return new HTMLFakeyElement()};
+  self.makeF = function(){return new HTMLFakeyElement()};
 
   self.nativeConstructor(HTMLGoofyElement);
 })()""");
+  applyTestExtensions(['HTMLElement']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_null_assertions/null_assertions_test_lib.dart b/tests/dart2js/native/native_null_assertions/null_assertions_test_lib.dart
index 049cd36..85a5540 100644
--- a/tests/dart2js/native/native_null_assertions/null_assertions_test_lib.dart
+++ b/tests/dart2js/native/native_null_assertions/null_assertions_test_lib.dart
@@ -41,10 +41,10 @@
   AAA.prototype.method2 = function(){return this._m2};
   AAA.prototype.optMethod = function(){return this._m2};
 
-  makeA = function() {
+  self.makeA = function() {
     return new AAA(100, 'Albert', 200, 'amazing!');
   };
-  makeAX = function() {
+  self.makeAX = function() {
     return new AAA(void 0, void 0, void 0, void 0);
   };
 
@@ -55,15 +55,16 @@
     this.optName = n;
   }
 
-  makeC = function() {
+  self.makeC = function() {
     return new CCC('Carol');
   };
-  makeCX = function() {
+  self.makeCX = function() {
     return new CCC(void 0);
   };
 
   self.nativeConstructor(CCC);
 })()""");
+  applyTestExtensions(['AAA', 'CCC']);
 }
 
 // The 'NativeInterface' version of the code is passed both native and Dart
diff --git a/tests/dart2js/native/native_null_closure_frog_test.dart b/tests/dart2js/native/native_null_closure_frog_test.dart
index f5fd85e..7e18b4e 100644
--- a/tests/dart2js/native/native_null_closure_frog_test.dart
+++ b/tests/dart2js/native/native_null_closure_frog_test.dart
@@ -24,10 +24,11 @@
   A.prototype.setClosure = function(f) { this.f = f; };
   A.prototype.check = function(f) { return this.f === f; };
   A.prototype.invoke = function() { return this.f(); };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_null_frog_test.dart b/tests/dart2js/native/native_null_frog_test.dart
index 0abdd35..359562b 100644
--- a/tests/dart2js/native/native_null_frog_test.dart
+++ b/tests/dart2js/native/native_null_frog_test.dart
@@ -24,9 +24,10 @@
   A.prototype.returnUndefined = function() { return void 0; };
   A.prototype.returnEmptyString = function() { return ""; };
   A.prototype.returnZero = function() { return 0; };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 @pragma('dart2js:noInline')
diff --git a/tests/dart2js/native/native_property_frog_test.dart b/tests/dart2js/native/native_property_frog_test.dart
index 0c4d3ef..1fd10b8 100644
--- a/tests/dart2js/native/native_property_frog_test.dart
+++ b/tests/dart2js/native/native_property_frog_test.dart
@@ -38,10 +38,11 @@
     set: function (v) { this._x = v; }
   });
 
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_testing.dart b/tests/dart2js/native/native_testing.dart
index 5dcaa24..002ca79 100644
--- a/tests/dart2js/native/native_testing.dart
+++ b/tests/dart2js/native/native_testing.dart
@@ -10,7 +10,8 @@
 import 'dart:_foreign_helper' show JS;
 
 export "package:expect/expect.dart";
-export 'dart:_js_helper' show Creates, Native, JSName, Returns;
+export 'dart:_js_helper'
+    show Creates, Native, JSName, Returns, applyTestExtensions;
 export 'dart:_foreign_helper' show JS;
 
 void nativeTesting() {
@@ -35,9 +36,14 @@
   //     self.nativeConstructor(Foo);
   //
   // to the JavaScript code.
-  self.nativeConstructor = function(constructor, opt_name) {
+  //
+  // Internally this exports the name on the top scope (needed for dartdevc) and
+  // overrides the toString show the name of the constructor like browsers do
+  // for native types (needed for dart2js).
+  self.nativeConstructor = function(constructor, opt_name, opt_dont_export) {
     var toStringResult = "[object " + (opt_name || constructor.name) + "]";
     constructor[toStringResultProperty] = toStringResult;
+    if (!opt_dont_export) self[constructor.name] = constructor;
   };
 })())
 ''');
diff --git a/tests/dart2js/native/native_to_string_frog_test.dart b/tests/dart2js/native/native_to_string_frog_test.dart
index 6fdca6f..eadce8f 100644
--- a/tests/dart2js/native/native_to_string_frog_test.dart
+++ b/tests/dart2js/native/native_to_string_frog_test.dart
@@ -15,9 +15,10 @@
   JS('', r"""
 (function(){
   function A() {}
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_use_native_name_in_table_frog_test.dart b/tests/dart2js/native/native_use_native_name_in_table_frog_test.dart
index 0bd930a..44dc4cf 100644
--- a/tests/dart2js/native/native_use_native_name_in_table_frog_test.dart
+++ b/tests/dart2js/native/native_use_native_name_in_table_frog_test.dart
@@ -36,12 +36,13 @@
   inherits(NativeB, NativeA);
   NativeA.prototype.foo = function() { return 42; };
 
-  makeA = function(){return new NativeA()};
-  makeB = function(){return new NativeB()};
+  self.makeA = function(){return new NativeA()};
+  self.makeB = function(){return new NativeB()};
 
   self.nativeConstructor(NativeA);
   self.nativeConstructor(NativeB);
 })()""");
+  applyTestExtensions(['NativeA', 'NativeB']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_wrapping_function3_frog_test.dart b/tests/dart2js/native/native_wrapping_function3_frog_test.dart
index 111e2f5..cfe6fee 100644
--- a/tests/dart2js/native/native_wrapping_function3_frog_test.dart
+++ b/tests/dart2js/native/native_wrapping_function3_frog_test.dart
@@ -24,9 +24,10 @@
   A.prototype.foo2 = function(closure, arg1, arg2) {
     return closure(arg1, arg2);
   };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/native_wrapping_function_frog_test.dart b/tests/dart2js/native/native_wrapping_function_frog_test.dart
index 53473b8..8a9984f 100644
--- a/tests/dart2js/native/native_wrapping_function_frog_test.dart
+++ b/tests/dart2js/native/native_wrapping_function_frog_test.dart
@@ -26,9 +26,10 @@
   A.prototype.foo2 = function(closure, arg1, arg2) {
     return closure(arg1, arg2);
   };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js/native/oddly_named_fields_test.dart b/tests/dart2js/native/oddly_named_fields_test.dart
index 7a93c95..4eda90a 100644
--- a/tests/dart2js/native/oddly_named_fields_test.dart
+++ b/tests/dart2js/native/oddly_named_fields_test.dart
@@ -1385,9 +1385,10 @@
   JS('', r"""
 (function(){
   function NativeClassWithOddNames() {}
-  makeNativeClassWithOddNames = function() {return new NativeClassWithOddNames()};
+  self.makeNativeClassWithOddNames = function() {return new NativeClassWithOddNames()};
   self.nativeConstructor(NativeClassWithOddNames);
 })()""");
+  applyTestExtensions(['NativeClassWithOddNames']);
 }
 
 main() {
diff --git a/tests/dart2js/native/runtimetype_test.dart b/tests/dart2js/native/runtimetype_test.dart
index 558f7ee..4581e3b 100644
--- a/tests/dart2js/native/runtimetype_test.dart
+++ b/tests/dart2js/native/runtimetype_test.dart
@@ -31,12 +31,13 @@
   function TAGY(){}
   inherits(TAGY, TAGX);
 
-  makeA = function(){return new TAGX()};
-  makeB = function(){return new TAGY()};
+  self.makeA = function(){return new TAGX()};
+  self.makeB = function(){return new TAGY()};
 
   self.nativeConstructor(TAGX);
   self.nativeConstructor(TAGY);
 })()""");
+  applyTestExtensions(['TAGX', 'TAGY']);
 }
 
 testDynamicContext() {
diff --git a/tests/dart2js/native/subclassing_1_test.dart b/tests/dart2js/native/subclassing_1_test.dart
index 77a636f..c34f307 100644
--- a/tests/dart2js/native/subclassing_1_test.dart
+++ b/tests/dart2js/native/subclassing_1_test.dart
@@ -35,13 +35,13 @@
   function A() {}
   function B() {}
   function C() {}
-  makeA = function(){return new A()};
-  makeB1 = function(){return new B()};
-  makeB2 = function(){return new B()};
-  makeC = function(){return new C()};
+  self.makeA = function(){return new A()};
+  self.makeB1 = function(){return new B()};
+  self.makeB2 = function(){return new B()};
+  self.makeC = function(){return new C()};
 
-  getBPrototype = function(){return B.prototype;};
-  getCPrototype = function(){return C.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
+  self.getCPrototype = function(){return C.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_2_test.dart b/tests/dart2js/native/subclassing_2_test.dart
index 66c8d68..7fcef99 100644
--- a/tests/dart2js/native/subclassing_2_test.dart
+++ b/tests/dart2js/native/subclassing_2_test.dart
@@ -32,10 +32,10 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_3_test.dart b/tests/dart2js/native/subclassing_3_test.dart
index 5a2c3d9..b7f89d3 100644
--- a/tests/dart2js/native/subclassing_3_test.dart
+++ b/tests/dart2js/native/subclassing_3_test.dart
@@ -38,9 +38,9 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B();};
+  self.makeB = function(){return new B();};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_4_test.dart b/tests/dart2js/native/subclassing_4_test.dart
index 07a2d4c..7dd5e72 100644
--- a/tests/dart2js/native/subclassing_4_test.dart
+++ b/tests/dart2js/native/subclassing_4_test.dart
@@ -36,8 +36,8 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B()};
-  getBPrototype = function(){return B.prototype;};
+  self.makeB = function(){return new B()};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_5_test.dart b/tests/dart2js/native/subclassing_5_test.dart
index 220563b..553b1f8 100644
--- a/tests/dart2js/native/subclassing_5_test.dart
+++ b/tests/dart2js/native/subclassing_5_test.dart
@@ -43,8 +43,8 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B()};
-  getBPrototype = function(){return B.prototype;};
+  self.makeB = function(){return new B()};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_constructor_1_test.dart b/tests/dart2js/native/subclassing_constructor_1_test.dart
index 45934f8..8570020 100644
--- a/tests/dart2js/native/subclassing_constructor_1_test.dart
+++ b/tests/dart2js/native/subclassing_constructor_1_test.dart
@@ -65,9 +65,9 @@
 (function(){
   function B() { this.a2 = 102; }
 
-  makeB = function(){return new B()};
+  self.makeB = function(){return new B()};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_super_call_test.dart b/tests/dart2js/native/subclassing_super_call_test.dart
index b157933..124f463 100644
--- a/tests/dart2js/native/subclassing_super_call_test.dart
+++ b/tests/dart2js/native/subclassing_super_call_test.dart
@@ -50,9 +50,9 @@
   N2.prototype.foo = function() { return "foo:" + this.text; };
   function BB() {}
   BB.prototype.__proto__ = N2.prototype;
-  makeBB = function(){return new BB()};
+  self.makeBB = function(){return new BB()};
 
-  getBBPrototype = function(){return BB.prototype;};
+  self.getBBPrototype = function(){return BB.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_super_field_1_test.dart b/tests/dart2js/native/subclassing_super_field_1_test.dart
index 827cb358..68bd8d3 100644
--- a/tests/dart2js/native/subclassing_super_field_1_test.dart
+++ b/tests/dart2js/native/subclassing_super_field_1_test.dart
@@ -36,9 +36,9 @@
   JS('', r"""
 (function(){
 function B() { }
-makeB = function(){return new B()};
+self.makeB = function(){return new B()};
 
-getBPrototype = function(){return B.prototype;};
+self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_super_field_2_test.dart b/tests/dart2js/native/subclassing_super_field_2_test.dart
index 837568a..79c7016 100644
--- a/tests/dart2js/native/subclassing_super_field_2_test.dart
+++ b/tests/dart2js/native/subclassing_super_field_2_test.dart
@@ -40,9 +40,9 @@
   JS('', r"""
 (function(){
   function B() { this.foo = 111; }  // N.foo
-  makeB = function(){return new B()};
+  self.makeB = function(){return new B()};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/subclassing_type_test.dart b/tests/dart2js/native/subclassing_type_test.dart
index ce52e5b..e5cc2be 100644
--- a/tests/dart2js/native/subclassing_type_test.dart
+++ b/tests/dart2js/native/subclassing_type_test.dart
@@ -33,9 +33,9 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B()};
+  self.makeB = function(){return new B()};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js/native/super_call_test.dart b/tests/dart2js/native/super_call_test.dart
index 5238bb5..ebae644 100644
--- a/tests/dart2js/native/super_call_test.dart
+++ b/tests/dart2js/native/super_call_test.dart
@@ -59,16 +59,17 @@
   function D(){}
   inherits(D, C);
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
-  makeC = function(){return new C()};
-  makeD = function(){return new D()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
+  self.makeC = function(){return new C()};
+  self.makeD = function(){return new D()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
   self.nativeConstructor(C);
   self.nativeConstructor(D);
 })()""");
+  applyTestExtensions(['A', 'B', 'C', 'D']);
 }
 
 main() {
diff --git a/tests/dart2js/native/super_property_test.dart b/tests/dart2js/native/super_property_test.dart
index 68e815a..9482cb7 100644
--- a/tests/dart2js/native/super_property_test.dart
+++ b/tests/dart2js/native/super_property_test.dart
@@ -46,11 +46,12 @@
   // This code is inside 'setup' and so not accessible from the global scope.
   function A(){}
   function B(){}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testThing(a) {
diff --git a/tests/dart2js/no_such_method_test.dart b/tests/dart2js/no_such_method_test.dart
index 38375d3..de98c6f 100644
--- a/tests/dart2js/no_such_method_test.dart
+++ b/tests/dart2js/no_such_method_test.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.
 
+// dart2jsOptions=--no-minify
+
 import "package:expect/expect.dart";
 
 class NoSuchMethodInfo {
   Object receiver;
-  String name;
+  Symbol name;
   List args;
-  NoSuchMethodInfo(Object r, String m, List a)
+  NoSuchMethodInfo(Object r, Symbol m, List a)
       : receiver = r,
         name = m,
         args = a;
@@ -27,29 +29,29 @@
 }
 
 // Used for the setter case.
-NoSuchMethodInfo topLevelInfo;
+NoSuchMethodInfo? topLevelInfo;
 
 main() {
   A a = new A();
-  var info = a.foo();
-  Expect.equals('foo', info.name);
+  var info = (a as dynamic).foo();
+  Expect.equals(#foo, info.name);
   Expect.isTrue(info.args.isEmpty);
   Expect.isTrue(identical(info.receiver, a));
 
-  info = a.foo(2);
-  Expect.equals('foo', info.name);
+  info = (a as dynamic).foo(2);
+  Expect.equals(#foo, info.name);
   Expect.isTrue(info.args.length == 1);
   Expect.isTrue(info.args[0] == 2);
   Expect.isTrue(identical(info.receiver, a));
 
-  info = a.bar;
-  Expect.equals('bar', info.name);
+  info = (a as dynamic).bar;
+  Expect.equals(#bar, info.name);
   Expect.isTrue(info.args.length == 0);
   Expect.isTrue(identical(info.receiver, a));
 
-  a.bar = 2;
+  (a as dynamic).bar = 2;
   info = topLevelInfo;
-  Expect.equals('bar', info.name);
+  Expect.equals(const Symbol('bar='), info.name);
   Expect.isTrue(info.args.length == 1);
   Expect.isTrue(info.args[0] == 2);
   Expect.isTrue(identical(info.receiver, a));
diff --git a/tests/dart2js/runtime_type_test.dart b/tests/dart2js/runtime_type_test.dart
index f127dbe..764aad8 100644
--- a/tests/dart2js/runtime_type_test.dart
+++ b/tests/dart2js/runtime_type_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.
 
-// dart2jsOptions=--strong
+// dart2jsOptions=--strong --no-minify
 
 // Test that Type.toString returns nice strings for native classes with
 // reserved names and for raw types.
diff --git a/tests/dart2js/to_string_test.dart b/tests/dart2js/to_string_test.dart
index 7157548..744034a 100644
--- a/tests/dart2js/to_string_test.dart
+++ b/tests/dart2js/to_string_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.
 
+// dart2jsOptions=--no-minify
+
 import "package:expect/expect.dart";
 
 class A extends Object {}
diff --git a/tests/dart2js/type_literal_test.dart b/tests/dart2js/type_literal_test.dart
index 4426847..ba085f8 100644
--- a/tests/dart2js/type_literal_test.dart
+++ b/tests/dart2js/type_literal_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.
 
-// dart2jsOptions=--strong
+// dart2jsOptions=--strong --no-minify
 
 import 'package:expect/expect.dart';
 
diff --git a/tests/dart2js/typevariable_typedef_test.dart b/tests/dart2js/typevariable_typedef_test.dart
index 5dc6d2b..2766e80 100644
--- a/tests/dart2js/typevariable_typedef_test.dart
+++ b/tests/dart2js/typevariable_typedef_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.
 
+// dart2jsOptions=--no-minify
+
 import "package:expect/expect.dart";
 
 typedef T Func<T>(T x);
diff --git a/tests/dart2js_2/code_motion_exception_test.dart b/tests/dart2js_2/code_motion_exception_test.dart
index 0bd675bd..aa24a5a 100644
--- a/tests/dart2js_2/code_motion_exception_test.dart
+++ b/tests/dart2js_2/code_motion_exception_test.dart
@@ -4,6 +4,8 @@
 
 // @dart = 2.7
 
+// dart2jsOptions=--no-minify
+
 import "package:expect/expect.dart";
 
 // Test for correct order of exceptions in code with checks that could be moved
diff --git a/tests/dart2js_2/native/abstract_class_test.dart b/tests/dart2js_2/native/abstract_class_test.dart
index 988157c..2657b25 100644
--- a/tests/dart2js_2/native/abstract_class_test.dart
+++ b/tests/dart2js_2/native/abstract_class_test.dart
@@ -29,12 +29,12 @@
   function A(){}
   function B(){}
   B.prototype.foo = function() { return 'B.foo'; };
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
   self.nativeConstructor(A);
   self.nativeConstructor(B);
-})()
-""");
+})()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/bound_closure_super_test.dart b/tests/dart2js_2/native/bound_closure_super_test.dart
deleted file mode 100644
index 67c36ed..0000000
--- a/tests/dart2js_2/native/bound_closure_super_test.dart
+++ /dev/null
@@ -1,25 +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.7
-
-// Test calling convention of property extraction closures (super edition).
-library bound_closure_super_test;
-
-import 'package:expect/expect.dart';
-
-import 'bound_closure_test.dart' as bound_closure_test;
-
-import 'bound_closure_test.dart' show inscrutable, makeCC;
-
-main() {
-  // Calling main from bound_closure_test.dart to set up native code.
-  bound_closure_test.main();
-
-  var c = inscrutable(makeCC)();
-  var csfoo = inscrutable(c).superfoo;
-
-  Expect.equals('BB.foo(1, B)', csfoo(1));
-  Expect.equals('BB.foo(2, 3)', csfoo(2, 3));
-}
diff --git a/tests/dart2js_2/native/bound_closure_test.dart b/tests/dart2js_2/native/bound_closure_test.dart
index 09bc341..8b6f309 100644
--- a/tests/dart2js_2/native/bound_closure_test.dart
+++ b/tests/dart2js_2/native/bound_closure_test.dart
@@ -42,13 +42,14 @@
     return 'CC.foo(' + u + ', ' + v + ')';
   };
 
-  makeBB = function(){return new BB()};
-  makeCC = function(){return new CC()};
-  inscrutable = function(a){return a;};
+  self.makeBB = function(){return new BB()};
+  self.makeCC = function(){return new CC()};
+  self.inscrutable = function(a){return a;};
 
   self.nativeConstructor(BB);
   self.nativeConstructor(CC);
 })()""");
+  applyTestExtensions(['BB', 'CC']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/browser_compat_1_prepatched_test.dart b/tests/dart2js_2/native/browser_compat_1_prepatched_test.dart
index 01fb0fe..895029e 100644
--- a/tests/dart2js_2/native/browser_compat_1_prepatched_test.dart
+++ b/tests/dart2js_2/native/browser_compat_1_prepatched_test.dart
@@ -39,9 +39,9 @@
   window.T1A = T1A;
   window.T1CrazyB = T1CrazyB;
 
-  makeT1A = function(){return new T1A()};
-  makeT1B = function(){return new T1CrazyB()};
-  makeT1C = function(){return new T1fakeA()};
+  self.makeT1A = function(){return new T1A()};
+  self.makeT1B = function(){return new T1CrazyB()};
+  self.makeT1C = function(){return new T1fakeA()};
 
   self.nativeConstructor(T1A);
   self.nativeConstructor(T1CrazyB);
@@ -73,6 +73,7 @@
 
   dartNativeDispatchHooksTransformer = [transformer1];
 })()''');
+  applyTestExtensions(['T1A', 'T1CrazyB', 'T1fakeA']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/browser_compat_1_unpatched_test.dart b/tests/dart2js_2/native/browser_compat_1_unpatched_test.dart
index 1f1e0fc..c08dd57 100644
--- a/tests/dart2js_2/native/browser_compat_1_unpatched_test.dart
+++ b/tests/dart2js_2/native/browser_compat_1_unpatched_test.dart
@@ -40,9 +40,9 @@
   window.T1A = T1A;
   window.T1CrazyB = T1CrazyB;
 
-  makeT1A = function(){return new T1A()};
-  makeT1B = function(){return new T1CrazyB()};
-  makeT1C = function(){return new T1fakeA()};
+  self.makeT1A = function(){return new T1A()};
+  self.makeT1B = function(){return new T1CrazyB()};
+  self.makeT1C = function(){return new T1fakeA()};
 
   self.nativeConstructor(T1A);
   self.nativeConstructor(T1CrazyB);
@@ -76,6 +76,7 @@
 
   dartNativeDispatchHooksTransformer = [transformer1];
 })()""");
+  applyTestExtensions(['T1A', 'T1CrazyB', 'T1fakeA']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/browser_compat_2_test.dart b/tests/dart2js_2/native/browser_compat_2_test.dart
index 349c9a7..1a404f5 100644
--- a/tests/dart2js_2/native/browser_compat_2_test.dart
+++ b/tests/dart2js_2/native/browser_compat_2_test.dart
@@ -106,6 +106,7 @@
 
 dartNativeDispatchHooksTransformer = [transformer1, transformer2];
 })()''');
+  applyTestExtensions(['T1A', 'T1B', 'T1C', 'T1D']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/core_type_check_native_test.dart b/tests/dart2js_2/native/core_type_check_native_test.dart
index a7b6d8b..8bdeee9 100644
--- a/tests/dart2js_2/native/core_type_check_native_test.dart
+++ b/tests/dart2js_2/native/core_type_check_native_test.dart
@@ -33,20 +33,20 @@
   JS('', r"""
 (function(){
   function A() {};
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   function B() {};
-  makeB = function() { return new B(); };
+  self.makeB = function() { return new B(); };
   function C() {};
-  makeC = function() { return new C(); };
+  self.makeC = function() { return new C(); };
   function D() {};
-  makeD = function() { return new D(); };
+  self.makeD = function() { return new D(); };
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
   self.nativeConstructor(C);
   self.nativeConstructor(D);
-})()
-""");
+})()""");
+  applyTestExtensions(['A', 'B', 'C', 'D']);
 }
 
 checkTest(value, expectComparable, expectPattern) {
diff --git a/tests/dart2js_2/native/dispatch_property_initialization_test.dart b/tests/dart2js_2/native/dispatch_property_initialization_test.dart
index d5c90b7..de6a9a9 100644
--- a/tests/dart2js_2/native/dispatch_property_initialization_test.dart
+++ b/tests/dart2js_2/native/dispatch_property_initialization_test.dart
@@ -25,6 +25,7 @@
 
   self.nativeConstructor(Foo);
 })()""");
+  applyTestExtensions(['Foo']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/downcast_test.dart b/tests/dart2js_2/native/downcast_test.dart
index f479b77..90e744b 100644
--- a/tests/dart2js_2/native/downcast_test.dart
+++ b/tests/dart2js_2/native/downcast_test.dart
@@ -48,12 +48,13 @@
 inherits(B, A);
 A.prototype.read = function() { return this._x; };
 A.prototype.write = function(x) { this._x = x; };
-makeA = function(){return new A()};
-makeB = function(){return new B()};
+self.makeA = function(){return new A()};
+self.makeB = function(){return new B()};
 
 self.nativeConstructor(A);
 self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 class C {}
diff --git a/tests/dart2js_2/native/error_safeToString_test.dart b/tests/dart2js_2/native/error_safeToString_test.dart
index 8b9acce0..cc9acbc 100644
--- a/tests/dart2js_2/native/error_safeToString_test.dart
+++ b/tests/dart2js_2/native/error_safeToString_test.dart
@@ -38,45 +38,46 @@
 void setup() {
   JS('', r"""
 (function(){
-  makeA = function(){return {hello: 123};};
+  self.makeA = function(){return {hello: 123};};
 
   function BB(){}
-  makeB = function(){return new BB();};
+  self.makeB = function(){return new BB();};
 
   function CC(){}
-  makeC = function(){
+  self.makeC = function(){
     var x = new CC();
     x.constructor = null;  // Foils constructor lookup.
     return x;
   };
 
   function DD(){}
-  makeD = function(){
+  self.makeD = function(){
     var x = new DD();
     x.constructor = {name: 'DDxxx'};  // Foils constructor lookup.
     return x;
   };
 
   function EE(){}
-  makeE = function(){
+  self.makeE = function(){
     var x = new EE();
     x.constructor = function Liar(){};  // Looks like a legitimate constructor.
     return x;
   };
 
   function PPPP(){}
-  makeP = function(){return new PPPP();};
+  self.makeP = function(){return new PPPP();};
 
   function QQQQ(){}
-  makeQ = function(){return new QQQQ();};
+  self.makeQ = function(){return new QQQQ();};
 
   function RRRR(){}
-  makeR = function(){return new RRRR();};
+  self.makeR = function(){return new RRRR();};
 
   self.nativeConstructor(PPPP);
   self.nativeConstructor(QQQQ);
   self.nativeConstructor(RRRR);
 })()""");
+  applyTestExtensions(['PPPP', 'QQQQ', 'RRRR']);
 }
 
 expectTypeName(expectedName, s) {
diff --git a/tests/dart2js_2/native/event_loop_test.dart b/tests/dart2js_2/native/event_loop_test.dart
index 1fc7b1d..45f57ec 100644
--- a/tests/dart2js_2/native/event_loop_test.dart
+++ b/tests/dart2js_2/native/event_loop_test.dart
@@ -22,9 +22,10 @@
 (function(){
 function A() {}
 A.prototype.foo = function(f) { return f(); };
-makeA = function() { return new A(); };
+self.makeA = function() { return new A(); };
 self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/fake_thing_2_test.dart b/tests/dart2js_2/native/fake_thing_2_test.dart
index 7209073..e1634c4 100644
--- a/tests/dart2js_2/native/fake_thing_2_test.dart
+++ b/tests/dart2js_2/native/fake_thing_2_test.dart
@@ -25,14 +25,15 @@
 (function(){
   function A() {}
   A.prototype.$isThing = true;
-  make1 = function(){return new A()};
-  make2 = function(){return {$isThing: true}};
+  self.make1 = function(){return new A()};
+  self.make2 = function(){return {$isThing: true}};
   function NT() {}
   NT.prototype.$isThing = true;
-  make3 = function(){return new NT()};
+  self.make3 = function(){return new NT()};
 
   self.nativeConstructor(NT);
 })()""");
+  applyTestExtensions(['NT']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/fake_thing_test.dart b/tests/dart2js_2/native/fake_thing_test.dart
index 63fda12..5d83f94 100644
--- a/tests/dart2js_2/native/fake_thing_test.dart
+++ b/tests/dart2js_2/native/fake_thing_test.dart
@@ -23,8 +23,8 @@
 (function(){
   function A() {}
   A.prototype.$isThing = true;
-  make1 = function(){return new A();};
-  make2 = function(){return {$isThing: true}};
+  self.make1 = function(){return new A();};
+  self.make2 = function(){return {$isThing: true}};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/field_type2_test.dart b/tests/dart2js_2/native/field_type2_test.dart
index 2a9ff0c..113987f 100644
--- a/tests/dart2js_2/native/field_type2_test.dart
+++ b/tests/dart2js_2/native/field_type2_test.dart
@@ -21,10 +21,11 @@
 (function(){
 // This code is all inside 'setup' and so not accessible from the global scope.
 function Node(parent){ this.parentNode = parent; }
-makeNode = function(p){return new Node(p);};
+self.makeNode = function(p){return new Node(p);};
 
 self.nativeConstructor(Node);
 })()""");
+  applyTestExtensions(['Node']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/field_type_test.dart b/tests/dart2js_2/native/field_type_test.dart
index 7ce0db3..c5b3be2 100644
--- a/tests/dart2js_2/native/field_type_test.dart
+++ b/tests/dart2js_2/native/field_type_test.dart
@@ -50,9 +50,10 @@
 (function(){
   // This code is inside 'setup' and so not accessible from the global scope.
   function Node(parent){ this.parentNode = parent; }
-  makeNode = function(p){return new Node(p);};
+  self.makeNode = function(p){return new Node(p);};
   self.nativeConstructor(Node);
 })()""");
+  applyTestExtensions(['Node']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/fixup_get_tag_test.dart b/tests/dart2js_2/native/fixup_get_tag_test.dart
index 8853041..4f5bbee 100644
--- a/tests/dart2js_2/native/fixup_get_tag_test.dart
+++ b/tests/dart2js_2/native/fixup_get_tag_test.dart
@@ -35,11 +35,12 @@
   function B(){ }
   B.prototype.token = function () { return 'isB'; };
 
-  makeA = function() { return new A(); };
-  makeB = function() { return new B(); };
+  self.makeA = function() { return new A(); };
+  self.makeB = function() { return new B(); };
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 makeA() native;
diff --git a/tests/dart2js_2/native/hash_code_test.dart b/tests/dart2js_2/native/hash_code_test.dart
index 9024625..6debbae 100644
--- a/tests/dart2js_2/native/hash_code_test.dart
+++ b/tests/dart2js_2/native/hash_code_test.dart
@@ -22,12 +22,13 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/internal_library_test.dart b/tests/dart2js_2/native/internal_library_test.dart
deleted file mode 100644
index e08339c..0000000
--- a/tests/dart2js_2/native/internal_library_test.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.7
-
-// Test that a private library can be accessed from libraries in this special
-// test folder.
-
-import 'dart:_js_helper';
-
-void main() {
-  print(loadDeferredLibrary);
-}
diff --git a/tests/dart2js_2/native/issue9182_test.dart b/tests/dart2js_2/native/issue9182_test.dart
index cfbb2b2..8b6f819 100644
--- a/tests/dart2js_2/native/issue9182_test.dart
+++ b/tests/dart2js_2/native/issue9182_test.dart
@@ -30,9 +30,10 @@
   JS('', r"""
 (function(){
   function A(){}
-  makeA = function() { return new A() };
+  self.makeA = function() { return new A() };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 makeA() native;
diff --git a/tests/dart2js_2/native/jsobject_test.dart b/tests/dart2js_2/native/jsobject_test.dart
index f5febe0..5b8ed68 100644
--- a/tests/dart2js_2/native/jsobject_test.dart
+++ b/tests/dart2js_2/native/jsobject_test.dart
@@ -29,16 +29,17 @@
 void setup() {
   JS('', r"""
 (function(){
-makeA = function(){return {hello: 123};};
+self.makeA = function(){return {hello: 123};};
 
 function BB(){}
-makeB = function(){return new BB();};
+self.makeB = function(){return new BB();};
 
 function QQ(){}
-makeQ = function(){return new QQ();};
+self.makeQ = function(){return new QQ();};
 
 self.nativeConstructor(QQ);
 })()""");
+  applyTestExtensions(['QQ']);
 }
 
 class Is<T> {
diff --git a/tests/dart2js_2/native/name_conflict_test.dart b/tests/dart2js_2/native/name_conflict_test.dart
index d39bf3b..ef72d1c 100644
--- a/tests/dart2js_2/native/name_conflict_test.dart
+++ b/tests/dart2js_2/native/name_conflict_test.dart
@@ -37,9 +37,10 @@
   function I(){}
   I.prototype.read = function() { return this._x; };
   I.prototype.write = function(x) { this._x = x; };
-  makeI = function(){return new I()};
+  self.makeI = function(){return new I()};
   self.nativeConstructor(I);
 })()""");
+  applyTestExtensions(['I']);
 }
 
 // A pure Dart implementation of I.
diff --git a/tests/dart2js_2/native/native_call_arity1_frog_test.dart b/tests/dart2js_2/native/native_call_arity1_frog_test.dart
index c7041fd..35549c1 100644
--- a/tests/dart2js_2/native/native_call_arity1_frog_test.dart
+++ b/tests/dart2js_2/native/native_call_arity1_frog_test.dart
@@ -39,12 +39,13 @@
   function B() {}
   B.prototype.foo = function () { return arguments.length; };
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamicContext() {
diff --git a/tests/dart2js_2/native/native_call_arity2_frog_test.dart b/tests/dart2js_2/native/native_call_arity2_frog_test.dart
index b66ddce..7be1152 100644
--- a/tests/dart2js_2/native/native_call_arity2_frog_test.dart
+++ b/tests/dart2js_2/native/native_call_arity2_frog_test.dart
@@ -42,12 +42,13 @@
   B.prototype.foo = function () { return arguments.length; };
   inherits(B, A);
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamicContext() {
diff --git a/tests/dart2js_2/native/native_call_arity3_frog_test.dart b/tests/dart2js_2/native/native_call_arity3_frog_test.dart
index 28e0412..bf4435c 100644
--- a/tests/dart2js_2/native/native_call_arity3_frog_test.dart
+++ b/tests/dart2js_2/native/native_call_arity3_frog_test.dart
@@ -35,12 +35,13 @@
   function B() {}
   B.prototype.foo = function () { return arguments.length; };
 
-  makeA = function(){return new A();};
-  makeB = function(){return new B();};
+  self.makeA = function(){return new A();};
+  self.makeB = function(){return new B();};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamicContext() {
diff --git a/tests/dart2js_2/native/native_checked_arguments1_frog_test.dart b/tests/dart2js_2/native/native_checked_arguments1_frog_test.dart
index ff52fa3..23fcc34 100644
--- a/tests/dart2js_2/native/native_checked_arguments1_frog_test.dart
+++ b/tests/dart2js_2/native/native_checked_arguments1_frog_test.dart
@@ -34,12 +34,13 @@
   B.prototype.foo = function (x) { return x + 'ha!'; };
   B.prototype.cmp = function (x) { return 1; };
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 expectThrows(action()) {
diff --git a/tests/dart2js_2/native/native_checked_fields_frog_test.dart b/tests/dart2js_2/native/native_checked_fields_frog_test.dart
index 76f512d..df76fdb 100644
--- a/tests/dart2js_2/native/native_checked_fields_frog_test.dart
+++ b/tests/dart2js_2/native/native_checked_fields_frog_test.dart
@@ -28,12 +28,13 @@
 
   function B() {}
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 expectThrows(action()) {
diff --git a/tests/dart2js_2/native/native_class_avoids_hidden_name_frog_test.dart b/tests/dart2js_2/native/native_class_avoids_hidden_name_frog_test.dart
index 488cd67..d183807 100644
--- a/tests/dart2js_2/native/native_class_avoids_hidden_name_frog_test.dart
+++ b/tests/dart2js_2/native/native_class_avoids_hidden_name_frog_test.dart
@@ -37,6 +37,7 @@
   BB = null;
   CC = null;
 })()""");
+  applyTestExtensions(['BB', 'CC']);
 }
 
 void setup2() {
@@ -45,8 +46,8 @@
   // This code is inside 'setup' and so not accessible from the global scope.
   function BB(){}
   function CC(){}
-  makeA = function(){return new BB()};  // AA is native "BB"
-  makeB = function(){return new CC()};  // BB is native "CC"
+  self.makeA = function(){return new BB()};  // AA is native "BB"
+  self.makeB = function(){return new CC()};  // BB is native "CC"
   self.nativeConstructor(BB);
   self.nativeConstructor(CC);
 })()""");
diff --git a/tests/dart2js_2/native/native_class_fields_2_test.dart b/tests/dart2js_2/native/native_class_fields_2_test.dart
index b8b031e..1d11429 100644
--- a/tests/dart2js_2/native/native_class_fields_2_test.dart
+++ b/tests/dart2js_2/native/native_class_fields_2_test.dart
@@ -35,9 +35,10 @@
     return a;
   }
 
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 A makeA() native;
diff --git a/tests/dart2js_2/native/native_class_fields_3_test.dart b/tests/dart2js_2/native/native_class_fields_3_test.dart
index ad96532..98791e9 100644
--- a/tests/dart2js_2/native/native_class_fields_3_test.dart
+++ b/tests/dart2js_2/native/native_class_fields_3_test.dart
@@ -61,9 +61,10 @@
     return a;
   }
 
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 A makeA() native;
diff --git a/tests/dart2js_2/native/native_class_fields_test.dart b/tests/dart2js_2/native/native_class_fields_test.dart
index a960803..1239904 100644
--- a/tests/dart2js_2/native/native_class_fields_test.dart
+++ b/tests/dart2js_2/native/native_class_fields_test.dart
@@ -42,6 +42,7 @@
 makeA = function(){return new A()};
 self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 A makeA() native;
diff --git a/tests/dart2js_2/native/native_class_inheritance1_frog_test.dart b/tests/dart2js_2/native/native_class_inheritance1_frog_test.dart
index 298a5f7..e527e3e 100644
--- a/tests/dart2js_2/native/native_class_inheritance1_frog_test.dart
+++ b/tests/dart2js_2/native/native_class_inheritance1_frog_test.dart
@@ -59,8 +59,8 @@
   A1.prototype.foo = function(){return 100;};
   B1.prototype.foo = function(){return 200;};
 
-  makeA1 = function(){return new A1()};
-  makeB1 = function(){return new B1()};
+  self.makeA1 = function(){return new A1()};
+  self.makeB1 = function(){return new B1()};
 
   function A2(){}
   function B2(){}
@@ -68,14 +68,15 @@
   A2.prototype.foo = function(a){return a + 10000;};
   B2.prototype.foo = function(z){return z + 20000;};
 
-  makeA2 = function(){return new A2()};
-  makeB2 = function(){return new B2()};
+  self.makeA2 = function(){return new A2()};
+  self.makeB2 = function(){return new B2()};
 
   self.nativeConstructor(A1);
   self.nativeConstructor(A2);
   self.nativeConstructor(B1);
   self.nativeConstructor(B2);
 })()""");
+  applyTestExtensions(['A1', 'A2', 'B1', 'B2']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_class_inheritance2_frog_test.dart b/tests/dart2js_2/native/native_class_inheritance2_frog_test.dart
index 865ff93..489502c 100644
--- a/tests/dart2js_2/native/native_class_inheritance2_frog_test.dart
+++ b/tests/dart2js_2/native/native_class_inheritance2_frog_test.dart
@@ -58,16 +58,17 @@
   A.prototype.foo = function(a){return 'A.foo(' + a + ')'};
   C.prototype.foo = function(z){return 'C.foo(' + z + ')'};
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
-  makeC = function(){return new C()};
-  makeD = function(){return new D()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
+  self.makeC = function(){return new C()};
+  self.makeD = function(){return new D()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
   self.nativeConstructor(C);
   self.nativeConstructor(D);
 })()""");
+  applyTestExtensions(['A', 'B', 'C', 'D']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_class_inheritance3_frog_test.dart b/tests/dart2js_2/native/native_class_inheritance3_frog_test.dart
index d6bc323..73834f4 100644
--- a/tests/dart2js_2/native/native_class_inheritance3_frog_test.dart
+++ b/tests/dart2js_2/native/native_class_inheritance3_frog_test.dart
@@ -50,24 +50,25 @@
   function B1(){}
   inherits(B1, A1);
 
-  makeA1 = function(){return new A1()};
-  makeB1 = function(){return new B1()};
+  self.makeA1 = function(){return new A1()};
+  self.makeB1 = function(){return new B1()};
 
   function A2(){}
   function B2(){}
   inherits(B2, A2);
   A2.prototype.foo = function(a){return 'A2.foo(' + a  + ')';};
 
-  makeA2 = function(){return new A2()};
-  makeB2 = function(){return new B2()};
+  self.makeA2 = function(){return new A2()};
+  self.makeB2 = function(){return new B2()};
 
-  makeObject = function(){return new Object()};
+  self.makeObject = function(){return new Object()};
 
   self.nativeConstructor(A1);
   self.nativeConstructor(A2);
   self.nativeConstructor(B1);
   self.nativeConstructor(B2);
 })()""");
+  applyTestExtensions(['A1', 'A2', 'B1', 'B2']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_class_inheritance4_frog_test.dart b/tests/dart2js_2/native/native_class_inheritance4_frog_test.dart
index c230a0e..b83b8e1 100644
--- a/tests/dart2js_2/native/native_class_inheritance4_frog_test.dart
+++ b/tests/dart2js_2/native/native_class_inheritance4_frog_test.dart
@@ -54,12 +54,13 @@
   function A(){}
   function B(){}
   inherits(B, A);
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testBasicA_dynamic() {
diff --git a/tests/dart2js_2/native/native_class_is_check1_frog_test.dart b/tests/dart2js_2/native/native_class_is_check1_frog_test.dart
index 0294507..83123db 100644
--- a/tests/dart2js_2/native/native_class_is_check1_frog_test.dart
+++ b/tests/dart2js_2/native/native_class_is_check1_frog_test.dart
@@ -31,9 +31,10 @@
   function A(){}
   A.prototype.read = function() { return this._x; };
   A.prototype.write = function(x) { this._x = x; };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 class B {}
diff --git a/tests/dart2js_2/native/native_class_is_check3_frog_test.dart b/tests/dart2js_2/native/native_class_is_check3_frog_test.dart
index fdd225a..fe7b154 100644
--- a/tests/dart2js_2/native/native_class_is_check3_frog_test.dart
+++ b/tests/dart2js_2/native/native_class_is_check3_frog_test.dart
@@ -49,11 +49,12 @@
   inherits(B, A);
   A.prototype.read = function() { return this._x; };
   A.prototype.write = function(x) { this._x = x; };
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 class C {}
diff --git a/tests/dart2js_2/native/native_class_with_dart_methods_frog_test.dart b/tests/dart2js_2/native/native_class_with_dart_methods_frog_test.dart
index c3061d8..8bd6b66 100644
--- a/tests/dart2js_2/native/native_class_with_dart_methods_frog_test.dart
+++ b/tests/dart2js_2/native/native_class_with_dart_methods_frog_test.dart
@@ -26,9 +26,10 @@
   JS('', r"""
 (function(){
   function A() {}
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_closure_identity_frog_test.dart b/tests/dart2js_2/native/native_closure_identity_frog_test.dart
index 2f85058..3d3a44c 100644
--- a/tests/dart2js_2/native/native_closure_identity_frog_test.dart
+++ b/tests/dart2js_2/native/native_closure_identity_frog_test.dart
@@ -24,10 +24,11 @@
   A.prototype.setClosure = function(f) { this.f = f; };
   A.prototype.check = function(f) { return this.f === f; };
   A.prototype.invoke = function() { return this.f(); };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 var staticClosure;
diff --git a/tests/dart2js_2/native/native_constructor_name_test.dart b/tests/dart2js_2/native/native_constructor_name_test.dart
index 1dc6d6c..bde29a4 100644
--- a/tests/dart2js_2/native/native_constructor_name_test.dart
+++ b/tests/dart2js_2/native/native_constructor_name_test.dart
@@ -25,9 +25,10 @@
   JS('', r"""
 (function(){
   function A(){}
-  makeZ = function(){return new A()};
+  self.makeZ = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_equals_frog_test.dart b/tests/dart2js_2/native/native_equals_frog_test.dart
index 1b5b38b..657c923 100644
--- a/tests/dart2js_2/native/native_equals_frog_test.dart
+++ b/tests/dart2js_2/native/native_equals_frog_test.dart
@@ -29,11 +29,12 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_exception2_test.dart b/tests/dart2js_2/native/native_exception2_test.dart
index 4bbc029..b1751c8 100644
--- a/tests/dart2js_2/native/native_exception2_test.dart
+++ b/tests/dart2js_2/native/native_exception2_test.dart
@@ -23,9 +23,10 @@
   JS('', r"""
 (function(){
   function NativeClass() {}
-  makeNativeClass = function() { return new NativeClass(); };
+  self.makeNativeClass = function() { return new NativeClass(); };
   self.nativeConstructor(NativeClass);
 })()""");
+  applyTestExtensions(['NativeClass']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_exceptions1_frog_test.dart b/tests/dart2js_2/native/native_exceptions1_frog_test.dart
index 8617219..c82bb98 100644
--- a/tests/dart2js_2/native/native_exceptions1_frog_test.dart
+++ b/tests/dart2js_2/native/native_exceptions1_frog_test.dart
@@ -49,6 +49,7 @@
   A = null;
   E = null;
 })()""");
+  applyTestExtensions(['E', 'A']);
 }
 
 void setup2() {
@@ -62,7 +63,7 @@
   if (x & 1) throw new E(100);
   return  x / 2;
 };
-makeA = function(){return new A()};
+self.makeA = function(){return new A()};
 
 self.nativeConstructor(E);
 self.nativeConstructor(A);
diff --git a/tests/dart2js_2/native/native_field_invocation2_test.dart b/tests/dart2js_2/native/native_field_invocation2_test.dart
index 2a4d013..046a03d 100644
--- a/tests/dart2js_2/native/native_field_invocation2_test.dart
+++ b/tests/dart2js_2/native/native_field_invocation2_test.dart
@@ -38,7 +38,7 @@
 void setup() {
   JS('', r"""
 (function(){
-nativeId = function(x) { return x; }
+self.nativeId = function(x) { return x; }
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/native_field_invocation3_test.dart b/tests/dart2js_2/native/native_field_invocation3_test.dart
index 8e0d918..a492116 100644
--- a/tests/dart2js_2/native/native_field_invocation3_test.dart
+++ b/tests/dart2js_2/native/native_field_invocation3_test.dart
@@ -12,9 +12,10 @@
   JS('', r"""
 (function(){
   function CC() {}
-  makeCC = function() { return new CC() };
+  self.makeCC = function() { return new CC() };
   self.nativeConstructor(CC);
 })()""");
+  applyTestExtensions(['CC']);
 }
 
 @Native("CC")
diff --git a/tests/dart2js_2/native/native_field_invocation4_test.dart b/tests/dart2js_2/native/native_field_invocation4_test.dart
index 7e5b0d4..abc22af 100644
--- a/tests/dart2js_2/native/native_field_invocation4_test.dart
+++ b/tests/dart2js_2/native/native_field_invocation4_test.dart
@@ -20,7 +20,7 @@
 void setup() {
   JS('', r"""
 (function(){
-nativeId = function(x) { return x; }
+self.nativeId = function(x) { return x; }
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/native_field_invocation5_test.dart b/tests/dart2js_2/native/native_field_invocation5_test.dart
index 5e9e853..eca547d 100644
--- a/tests/dart2js_2/native/native_field_invocation5_test.dart
+++ b/tests/dart2js_2/native/native_field_invocation5_test.dart
@@ -13,10 +13,11 @@
   JS('', r"""
 (function(){
   function CC() {}
-  makeCC = function() { return new CC() };
-  nativeFirst = function(x, y) { return x; };
+  self.makeCC = function() { return new CC() };
+  self.nativeFirst = function(x, y) { return x; };
   self.nativeConstructor(CC);
 })()""");
+  applyTestExtensions(['CC']);
 }
 
 class C {
diff --git a/tests/dart2js_2/native/native_field_invocation6_test.dart b/tests/dart2js_2/native/native_field_invocation6_test.dart
index 3ca229f..9dafb45 100644
--- a/tests/dart2js_2/native/native_field_invocation6_test.dart
+++ b/tests/dart2js_2/native/native_field_invocation6_test.dart
@@ -12,12 +12,13 @@
 void setup() {
   JS('', r"""
 (function(){
-  nativeFirst = function(x, y) { return x; };
+  self.nativeFirst = function(x, y) { return x; };
 
   function A() {}
-  makeA = function() { return new A() };
+  self.makeA = function() { return new A() };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 @Native("A")
diff --git a/tests/dart2js_2/native/native_field_invocation_test.dart b/tests/dart2js_2/native/native_field_invocation_test.dart
index 65077fe..6531ff2 100644
--- a/tests/dart2js_2/native/native_field_invocation_test.dart
+++ b/tests/dart2js_2/native/native_field_invocation_test.dart
@@ -20,7 +20,7 @@
 void setup() {
   JS('', r"""
 (function(){
-  nativeId = function(x) { return x; }
+  self.nativeId = function(x) { return x; }
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/native_field_name_test.dart b/tests/dart2js_2/native/native_field_name_test.dart
index c03a88d..8c1a623 100644
--- a/tests/dart2js_2/native/native_field_name_test.dart
+++ b/tests/dart2js_2/native/native_field_name_test.dart
@@ -43,10 +43,11 @@
     return a;
   }
 
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 /*A*/ makeA() native;
diff --git a/tests/dart2js_2/native/native_field_optimization_test.dart b/tests/dart2js_2/native/native_field_optimization_test.dart
index 6b5a976..6aa3aa4 100644
--- a/tests/dart2js_2/native/native_field_optimization_test.dart
+++ b/tests/dart2js_2/native/native_field_optimization_test.dart
@@ -44,10 +44,11 @@
     }
   });
 
-  makeFoo = function() { return new Foo() };
+  self.makeFoo = function() { return new Foo() };
 
   self.nativeConstructor(Foo);
 })()""");
+  applyTestExtensions(['Foo']);
 }
 
 test1() {
diff --git a/tests/dart2js_2/native/native_field_rename_1_frog_test.dart b/tests/dart2js_2/native/native_field_rename_1_frog_test.dart
index 11420c4..4277754 100644
--- a/tests/dart2js_2/native/native_field_rename_1_frog_test.dart
+++ b/tests/dart2js_2/native/native_field_rename_1_frog_test.dart
@@ -45,12 +45,13 @@
   function X(){}
   X.prototype.key = function(){return 666;};
 
-  makeA = function(){return new A()};
-  makeX = function(){return new X()};
+  self.makeA = function(){return new A()};
+  self.makeX = function(){return new X()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(X);
 })()""");
+  applyTestExtensions(['A', 'X']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js_2/native/native_field_rename_2_frog_test.dart b/tests/dart2js_2/native/native_field_rename_2_frog_test.dart
index 1591a28..37c9c36 100644
--- a/tests/dart2js_2/native/native_field_rename_2_frog_test.dart
+++ b/tests/dart2js_2/native/native_field_rename_2_frog_test.dart
@@ -48,12 +48,13 @@
   function X(){}
   X.prototype.key = function(){return 666;};
 
-  makeA = function(){return new A()};
-  makeX = function(){return new X()};
+  self.makeA = function(){return new A()};
+  self.makeX = function(){return new X()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(X);
 })()""");
+  applyTestExtensions(['A', 'X']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js_2/native/native_method_inlining_test.dart b/tests/dart2js_2/native/native_method_inlining_test.dart
index 0df556d..5ae5cce 100644
--- a/tests/dart2js_2/native/native_method_inlining_test.dart
+++ b/tests/dart2js_2/native/native_method_inlining_test.dart
@@ -66,7 +66,7 @@
   A.prototype.foo = function () { return arguments.length; };
   A.prototype.callFun = function (fn) { return fn ? fn(123) : 1; };
 
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   findMethodTextContaining = function (instance, string) {
     var proto = Object.getPrototypeOf(instance);
@@ -81,6 +81,7 @@
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 void match(String s, String pattern1) {
diff --git a/tests/dart2js_2/native/native_method_rename1_frog_test.dart b/tests/dart2js_2/native/native_method_rename1_frog_test.dart
index 65d0741..cdac340 100644
--- a/tests/dart2js_2/native/native_method_rename1_frog_test.dart
+++ b/tests/dart2js_2/native/native_method_rename1_frog_test.dart
@@ -37,10 +37,11 @@
   A.prototype.barA = function(){return 200;};
   A.prototype.bazA = function(){return 300;};
 
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js_2/native/native_method_rename2_frog_test.dart b/tests/dart2js_2/native/native_method_rename2_frog_test.dart
index d2c5b49..51058f1 100644
--- a/tests/dart2js_2/native/native_method_rename2_frog_test.dart
+++ b/tests/dart2js_2/native/native_method_rename2_frog_test.dart
@@ -43,12 +43,13 @@
   inherits(B, A);
   B.prototype.fooB = function(){return 200;};
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js_2/native/native_method_rename3_frog_test.dart b/tests/dart2js_2/native/native_method_rename3_frog_test.dart
index b2875a9..2cb4951 100644
--- a/tests/dart2js_2/native/native_method_rename3_frog_test.dart
+++ b/tests/dart2js_2/native/native_method_rename3_frog_test.dart
@@ -50,12 +50,13 @@
   inherits(B, A);
   B.prototype.fooB = function(){return 200;};
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testDynamic() {
diff --git a/tests/dart2js_2/native/native_method_with_keyword_name_test.dart b/tests/dart2js_2/native/native_method_with_keyword_name_test.dart
index 1245550..89b5d25 100644
--- a/tests/dart2js_2/native/native_method_with_keyword_name_test.dart
+++ b/tests/dart2js_2/native/native_method_with_keyword_name_test.dart
@@ -24,6 +24,7 @@
 makeA = function(){return new A()};
 self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_missing_method1_frog_test.dart b/tests/dart2js_2/native/native_missing_method1_frog_test.dart
index e083b17..df551ab 100644
--- a/tests/dart2js_2/native/native_missing_method1_frog_test.dart
+++ b/tests/dart2js_2/native/native_missing_method1_frog_test.dart
@@ -16,9 +16,10 @@
 (function(){
   function A() {};
   A.prototype.foo = function() { return  99; };
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 class B {
diff --git a/tests/dart2js_2/native/native_missing_method2_frog_test.dart b/tests/dart2js_2/native/native_missing_method2_frog_test.dart
index 7b96c87..ca407b2 100644
--- a/tests/dart2js_2/native/native_missing_method2_frog_test.dart
+++ b/tests/dart2js_2/native/native_missing_method2_frog_test.dart
@@ -16,9 +16,10 @@
 (function(){
   function A() {};
   A.prototype.foo = function() { return  42; };
-  makeA = function() { return new A() };
+  self.makeA = function() { return new A() };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 class B {
diff --git a/tests/dart2js_2/native/native_mixin_field2_test.dart b/tests/dart2js_2/native/native_mixin_field2_test.dart
index a2b9062..0736aaf 100644
--- a/tests/dart2js_2/native/native_mixin_field2_test.dart
+++ b/tests/dart2js_2/native/native_mixin_field2_test.dart
@@ -46,12 +46,13 @@
 (function(){
   function A() {this.foo='A-foo';}
   function B() {A.call(this);this.bar='B-bar';this.baz='M1-baz';}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 @pragma('dart2js:assumeDynamic')
diff --git a/tests/dart2js_2/native/native_mixin_field_test.dart b/tests/dart2js_2/native/native_mixin_field_test.dart
index bc7d36c..4a92fc2 100644
--- a/tests/dart2js_2/native/native_mixin_field_test.dart
+++ b/tests/dart2js_2/native/native_mixin_field_test.dart
@@ -36,12 +36,13 @@
 (function(){
   function A() {this.foo='A-foo';}
   function B() {A.call(this);this.bar='B-bar';this.baz='M1-baz';}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_mixin_multiple2_test.dart b/tests/dart2js_2/native/native_mixin_multiple2_test.dart
index aa95f87..3ad645b 100644
--- a/tests/dart2js_2/native/native_mixin_multiple2_test.dart
+++ b/tests/dart2js_2/native/native_mixin_multiple2_test.dart
@@ -32,10 +32,11 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_mixin_multiple3_test.dart b/tests/dart2js_2/native/native_mixin_multiple3_test.dart
index 9992295..2fc6dc1 100644
--- a/tests/dart2js_2/native/native_mixin_multiple3_test.dart
+++ b/tests/dart2js_2/native/native_mixin_multiple3_test.dart
@@ -46,14 +46,15 @@
   function A() {}
   function B() {}
   function C() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
-  makeC = function(){return new C()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
+  self.makeC = function(){return new C()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
   self.nativeConstructor(C);
 })()""");
+  applyTestExtensions(['A', 'B', 'C']);
 }
 
 var g;
diff --git a/tests/dart2js_2/native/native_mixin_multiple_test.dart b/tests/dart2js_2/native/native_mixin_multiple_test.dart
index 377353c..f657023 100644
--- a/tests/dart2js_2/native/native_mixin_multiple_test.dart
+++ b/tests/dart2js_2/native/native_mixin_multiple_test.dart
@@ -36,12 +36,13 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_mixin_test.dart b/tests/dart2js_2/native/native_mixin_test.dart
index 096f39e..f0f055a 100644
--- a/tests/dart2js_2/native/native_mixin_test.dart
+++ b/tests/dart2js_2/native/native_mixin_test.dart
@@ -32,12 +32,13 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_mixin_with_plain_test.dart b/tests/dart2js_2/native/native_mixin_with_plain_test.dart
index a7bd565..b896ad1 100644
--- a/tests/dart2js_2/native/native_mixin_with_plain_test.dart
+++ b/tests/dart2js_2/native/native_mixin_with_plain_test.dart
@@ -47,12 +47,13 @@
 (function(){
   function A() {this.aa = 'aa'}
   function B() {this.aa = 'bb'}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_named_constructors2_frog_test.dart b/tests/dart2js_2/native/native_named_constructors2_frog_test.dart
index 916b9ec..a8a5f20 100644
--- a/tests/dart2js_2/native/native_named_constructors2_frog_test.dart
+++ b/tests/dart2js_2/native/native_named_constructors2_frog_test.dart
@@ -33,9 +33,10 @@
   // This code is inside 'setup' and so not accessible from the global scope.
   function A(arg) { this._x = arg; }
   A.prototype.foo = function() { return this._x; };
-  makeA = function(arg) { return new A(arg); };
+  self.makeA = function(arg) { return new A(arg); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_named_constructors3_frog_test.dart b/tests/dart2js_2/native/native_named_constructors3_frog_test.dart
index d90df20..c98aaa3 100644
--- a/tests/dart2js_2/native/native_named_constructors3_frog_test.dart
+++ b/tests/dart2js_2/native/native_named_constructors3_frog_test.dart
@@ -32,9 +32,10 @@
   // This code is inside 'setup' and so not accessible from the global scope.
   function A(arg) { this._x = arg; }
   A.prototype.foo = function(){ return this._x; };
-  makeA = function(arg) { return new A(arg); };
+  self.makeA = function(arg) { return new A(arg); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_no_such_method_exception2_frog_test.dart b/tests/dart2js_2/native/native_no_such_method_exception2_frog_test.dart
index b562085..6fb278b 100644
--- a/tests/dart2js_2/native/native_no_such_method_exception2_frog_test.dart
+++ b/tests/dart2js_2/native/native_no_such_method_exception2_frog_test.dart
@@ -33,13 +33,14 @@
     function A() {}
     function B() {}
     inherits(B, A);
-    makeA = function() { return new A() };
-    makeB = function() { return new B() };
+    self.makeA = function() { return new A() };
+    self.makeB = function() { return new B() };
     B.prototype.foo = function() { return 42; };
 
     self.nativeConstructor(A);
     self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_no_such_method_exception_frog_test.dart b/tests/dart2js_2/native/native_no_such_method_exception_frog_test.dart
index 857bf54..c01d397 100644
--- a/tests/dart2js_2/native/native_no_such_method_exception_frog_test.dart
+++ b/tests/dart2js_2/native/native_no_such_method_exception_frog_test.dart
@@ -22,9 +22,10 @@
   JS('', r"""
 (function(){
   function A() {}
-  makeA = function() { return new A(); };
+  self.makeA = function() { return new A(); };
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_novel_html_test.dart b/tests/dart2js_2/native/native_novel_html_test.dart
index 5330028..1e2d20d 100644
--- a/tests/dart2js_2/native/native_novel_html_test.dart
+++ b/tests/dart2js_2/native/native_novel_html_test.dart
@@ -25,17 +25,18 @@
   HTMLGoofyElement.prototype.nativeMethod = function(a) {
     return 'Goofy.nativeMethod(' + a  + ')';
   };
-  makeE = function(){return new HTMLGoofyElement()};
+  self.makeE = function(){return new HTMLGoofyElement()};
 
   // A non-HTML element with a misleading name.
   function HTMLFakeyElement(){}
   HTMLFakeyElement.prototype.nativeMethod = function(a) {
     return 'Fakey.nativeMethod(' + a  + ')';
   };
-  makeF = function(){return new HTMLFakeyElement()};
+  self.makeF = function(){return new HTMLFakeyElement()};
 
   self.nativeConstructor(HTMLGoofyElement);
 })()""");
+  applyTestExtensions(['HTMLGoofyElement']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_null_closure_frog_test.dart b/tests/dart2js_2/native/native_null_closure_frog_test.dart
index a7c83a3..1ec0bfd 100644
--- a/tests/dart2js_2/native/native_null_closure_frog_test.dart
+++ b/tests/dart2js_2/native/native_null_closure_frog_test.dart
@@ -26,10 +26,11 @@
   A.prototype.setClosure = function(f) { this.f = f; };
   A.prototype.check = function(f) { return this.f === f; };
   A.prototype.invoke = function() { return this.f(); };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_null_frog_test.dart b/tests/dart2js_2/native/native_null_frog_test.dart
index 9cf083d..14f19c2 100644
--- a/tests/dart2js_2/native/native_null_frog_test.dart
+++ b/tests/dart2js_2/native/native_null_frog_test.dart
@@ -26,9 +26,10 @@
   A.prototype.returnUndefined = function() { return void 0; };
   A.prototype.returnEmptyString = function() { return ""; };
   A.prototype.returnZero = function() { return 0; };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 @pragma('dart2js:noInline')
diff --git a/tests/dart2js_2/native/native_property_frog_test.dart b/tests/dart2js_2/native/native_property_frog_test.dart
index 2deeed5..026dd6a 100644
--- a/tests/dart2js_2/native/native_property_frog_test.dart
+++ b/tests/dart2js_2/native/native_property_frog_test.dart
@@ -40,10 +40,11 @@
     set: function (v) { this._x = v; }
   });
 
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
 
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_testing.dart b/tests/dart2js_2/native/native_testing.dart
index 9eb9246..19d5bae 100644
--- a/tests/dart2js_2/native/native_testing.dart
+++ b/tests/dart2js_2/native/native_testing.dart
@@ -12,7 +12,8 @@
 import 'dart:_foreign_helper' show JS;
 
 export "package:expect/expect.dart";
-export 'dart:_js_helper' show Creates, Native, JSName, Returns;
+export 'dart:_js_helper'
+    show Creates, Native, JSName, Returns, applyTestExtensions;
 export 'dart:_foreign_helper' show JS;
 
 void nativeTesting() {
diff --git a/tests/dart2js_2/native/native_to_string_frog_test.dart b/tests/dart2js_2/native/native_to_string_frog_test.dart
index f17ad7b..aafb8f1 100644
--- a/tests/dart2js_2/native/native_to_string_frog_test.dart
+++ b/tests/dart2js_2/native/native_to_string_frog_test.dart
@@ -17,9 +17,10 @@
   JS('', r"""
 (function(){
   function A() {}
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_use_native_name_in_table_frog_test.dart b/tests/dart2js_2/native/native_use_native_name_in_table_frog_test.dart
index ef7b2a7..7a9b283 100644
--- a/tests/dart2js_2/native/native_use_native_name_in_table_frog_test.dart
+++ b/tests/dart2js_2/native/native_use_native_name_in_table_frog_test.dart
@@ -38,12 +38,13 @@
   inherits(NativeB, NativeA);
   NativeA.prototype.foo = function() { return 42; };
 
-  makeA = function(){return new NativeA()};
-  makeB = function(){return new NativeB()};
+  self.makeA = function(){return new NativeA()};
+  self.makeB = function(){return new NativeB()};
 
   self.nativeConstructor(NativeA);
   self.nativeConstructor(NativeB);
 })()""");
+  applyTestExtensions(['NativeA', 'NativeB']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_wrapping_function3_frog_test.dart b/tests/dart2js_2/native/native_wrapping_function3_frog_test.dart
index e3de1ed..da2ea28 100644
--- a/tests/dart2js_2/native/native_wrapping_function3_frog_test.dart
+++ b/tests/dart2js_2/native/native_wrapping_function3_frog_test.dart
@@ -26,9 +26,10 @@
   A.prototype.foo2 = function(closure, arg1, arg2) {
     return closure(arg1, arg2);
   };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/native_wrapping_function_frog_test.dart b/tests/dart2js_2/native/native_wrapping_function_frog_test.dart
index e05b809..325705e 100644
--- a/tests/dart2js_2/native/native_wrapping_function_frog_test.dart
+++ b/tests/dart2js_2/native/native_wrapping_function_frog_test.dart
@@ -28,9 +28,10 @@
   A.prototype.foo2 = function(closure, arg1, arg2) {
     return closure(arg1, arg2);
   };
-  makeA = function(){return new A()};
+  self.makeA = function(){return new A()};
   self.nativeConstructor(A);
 })()""");
+  applyTestExtensions(['A']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/oddly_named_fields_test.dart b/tests/dart2js_2/native/oddly_named_fields_test.dart
index e59f247..19c2777 100644
--- a/tests/dart2js_2/native/oddly_named_fields_test.dart
+++ b/tests/dart2js_2/native/oddly_named_fields_test.dart
@@ -1387,9 +1387,10 @@
   JS('', r"""
 (function(){
   function NativeClassWithOddNames() {}
-  makeNativeClassWithOddNames = function() {return new NativeClassWithOddNames()};
+  self.makeNativeClassWithOddNames = function() {return new NativeClassWithOddNames()};
   self.nativeConstructor(NativeClassWithOddNames);
 })()""");
+  applyTestExtensions(['NativeClassWithOddNames']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/runtimetype_test.dart b/tests/dart2js_2/native/runtimetype_test.dart
index 4465ae1..62911e2 100644
--- a/tests/dart2js_2/native/runtimetype_test.dart
+++ b/tests/dart2js_2/native/runtimetype_test.dart
@@ -33,12 +33,13 @@
   function TAGY(){}
   inherits(TAGY, TAGX);
 
-  makeA = function(){return new TAGX()};
-  makeB = function(){return new TAGY()};
+  self.makeA = function(){return new TAGX()};
+  self.makeB = function(){return new TAGY()};
 
   self.nativeConstructor(TAGX);
   self.nativeConstructor(TAGY);
 })()""");
+  applyTestExtensions(['TAGX', 'TAGY']);
 }
 
 testDynamicContext() {
diff --git a/tests/dart2js_2/native/subclassing_1_test.dart b/tests/dart2js_2/native/subclassing_1_test.dart
index fd3dc84..c19ce2b 100644
--- a/tests/dart2js_2/native/subclassing_1_test.dart
+++ b/tests/dart2js_2/native/subclassing_1_test.dart
@@ -37,13 +37,13 @@
   function A() {}
   function B() {}
   function C() {}
-  makeA = function(){return new A()};
-  makeB1 = function(){return new B()};
-  makeB2 = function(){return new B()};
-  makeC = function(){return new C()};
+  self.makeA = function(){return new A()};
+  self.makeB1 = function(){return new B()};
+  self.makeB2 = function(){return new B()};
+  self.makeC = function(){return new C()};
 
-  getBPrototype = function(){return B.prototype;};
-  getCPrototype = function(){return C.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
+  self.getCPrototype = function(){return C.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_2_test.dart b/tests/dart2js_2/native/subclassing_2_test.dart
index 63f3711..d5ee89d 100644
--- a/tests/dart2js_2/native/subclassing_2_test.dart
+++ b/tests/dart2js_2/native/subclassing_2_test.dart
@@ -34,10 +34,10 @@
 (function(){
   function A() {}
   function B() {}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_3_test.dart b/tests/dart2js_2/native/subclassing_3_test.dart
index fb7a794..d033b08 100644
--- a/tests/dart2js_2/native/subclassing_3_test.dart
+++ b/tests/dart2js_2/native/subclassing_3_test.dart
@@ -40,9 +40,9 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B();};
+  self.makeB = function(){return new B();};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_4_test.dart b/tests/dart2js_2/native/subclassing_4_test.dart
index 089f134..c80a161 100644
--- a/tests/dart2js_2/native/subclassing_4_test.dart
+++ b/tests/dart2js_2/native/subclassing_4_test.dart
@@ -38,8 +38,8 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B()};
-  getBPrototype = function(){return B.prototype;};
+  self.makeB = function(){return new B()};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_5_test.dart b/tests/dart2js_2/native/subclassing_5_test.dart
index 3ae3859..5599399 100644
--- a/tests/dart2js_2/native/subclassing_5_test.dart
+++ b/tests/dart2js_2/native/subclassing_5_test.dart
@@ -45,8 +45,8 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B()};
-  getBPrototype = function(){return B.prototype;};
+  self.makeB = function(){return new B()};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_constructor_1_test.dart b/tests/dart2js_2/native/subclassing_constructor_1_test.dart
index d70e1e3..9ee71bb 100644
--- a/tests/dart2js_2/native/subclassing_constructor_1_test.dart
+++ b/tests/dart2js_2/native/subclassing_constructor_1_test.dart
@@ -67,9 +67,9 @@
 (function(){
   function B() { this.a2 = 102; }
 
-  makeB = function(){return new B()};
+  self.makeB = function(){return new B()};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_super_call_test.dart b/tests/dart2js_2/native/subclassing_super_call_test.dart
index 71a77e5..b94cfd6 100644
--- a/tests/dart2js_2/native/subclassing_super_call_test.dart
+++ b/tests/dart2js_2/native/subclassing_super_call_test.dart
@@ -51,9 +51,9 @@
   N2.prototype.foo = function() { return "foo:" + this.text; };
   function BB() {}
   BB.prototype.__proto__ = N2.prototype;
-  makeBB = function(){return new BB()};
+  self.makeBB = function(){return new BB()};
 
-  getBBPrototype = function(){return BB.prototype;};
+  self.getBBPrototype = function(){return BB.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_super_field_1_test.dart b/tests/dart2js_2/native/subclassing_super_field_1_test.dart
index a1e3c2a..f14bb3d 100644
--- a/tests/dart2js_2/native/subclassing_super_field_1_test.dart
+++ b/tests/dart2js_2/native/subclassing_super_field_1_test.dart
@@ -38,9 +38,9 @@
   JS('', r"""
 (function(){
 function B() { }
-makeB = function(){return new B()};
+self.makeB = function(){return new B()};
 
-getBPrototype = function(){return B.prototype;};
+self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_super_field_2_test.dart b/tests/dart2js_2/native/subclassing_super_field_2_test.dart
index efd1bf6..334e83a 100644
--- a/tests/dart2js_2/native/subclassing_super_field_2_test.dart
+++ b/tests/dart2js_2/native/subclassing_super_field_2_test.dart
@@ -42,9 +42,9 @@
   JS('', r"""
 (function(){
   function B() { this.foo = 111; }  // N.foo
-  makeB = function(){return new B()};
+  self.makeB = function(){return new B()};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/subclassing_type_test.dart b/tests/dart2js_2/native/subclassing_type_test.dart
index 3abc875..39f9745 100644
--- a/tests/dart2js_2/native/subclassing_type_test.dart
+++ b/tests/dart2js_2/native/subclassing_type_test.dart
@@ -35,9 +35,9 @@
   JS('', r"""
 (function(){
   function B() {}
-  makeB = function(){return new B()};
+  self.makeB = function(){return new B()};
 
-  getBPrototype = function(){return B.prototype;};
+  self.getBPrototype = function(){return B.prototype;};
 })()""");
 }
 
diff --git a/tests/dart2js_2/native/super_call_test.dart b/tests/dart2js_2/native/super_call_test.dart
index 2dfff1a..1e91195 100644
--- a/tests/dart2js_2/native/super_call_test.dart
+++ b/tests/dart2js_2/native/super_call_test.dart
@@ -61,16 +61,17 @@
   function D(){}
   inherits(D, C);
 
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
-  makeC = function(){return new C()};
-  makeD = function(){return new D()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
+  self.makeC = function(){return new C()};
+  self.makeD = function(){return new D()};
 
   self.nativeConstructor(A);
   self.nativeConstructor(B);
   self.nativeConstructor(C);
   self.nativeConstructor(D);
 })()""");
+  applyTestExtensions(['A', 'B', 'C', 'D']);
 }
 
 main() {
diff --git a/tests/dart2js_2/native/super_property_test.dart b/tests/dart2js_2/native/super_property_test.dart
index 5efcf62..ada33df 100644
--- a/tests/dart2js_2/native/super_property_test.dart
+++ b/tests/dart2js_2/native/super_property_test.dart
@@ -48,11 +48,12 @@
   // This code is inside 'setup' and so not accessible from the global scope.
   function A(){}
   function B(){}
-  makeA = function(){return new A()};
-  makeB = function(){return new B()};
+  self.makeA = function(){return new A()};
+  self.makeB = function(){return new B()};
   self.nativeConstructor(A);
   self.nativeConstructor(B);
 })()""");
+  applyTestExtensions(['A', 'B']);
 }
 
 testThing(a) {
diff --git a/tests/dart2js_2/no_such_method_test.dart b/tests/dart2js_2/no_such_method_test.dart
index f5d3f33..9d40641 100644
--- a/tests/dart2js_2/no_such_method_test.dart
+++ b/tests/dart2js_2/no_such_method_test.dart
@@ -4,13 +4,15 @@
 
 // @dart = 2.7
 
+// dart2jsOptions=--no-minify
+
 import "package:expect/expect.dart";
 
 class NoSuchMethodInfo {
   Object receiver;
-  String name;
+  Symbol name;
   List args;
-  NoSuchMethodInfo(Object r, String m, List a)
+  NoSuchMethodInfo(Object r, Symbol m, List a)
       : receiver = r,
         name = m,
         args = a;
@@ -33,25 +35,25 @@
 
 main() {
   A a = new A();
-  var info = a.foo();
-  Expect.equals('foo', info.name);
+  var info = (a as dynamic).foo();
+  Expect.equals(#foo, info.name);
   Expect.isTrue(info.args.isEmpty);
   Expect.isTrue(identical(info.receiver, a));
 
-  info = a.foo(2);
-  Expect.equals('foo', info.name);
+  info = (a as dynamic).foo(2);
+  Expect.equals(#foo, info.name);
   Expect.isTrue(info.args.length == 1);
   Expect.isTrue(info.args[0] == 2);
   Expect.isTrue(identical(info.receiver, a));
 
-  info = a.bar;
-  Expect.equals('bar', info.name);
+  info = (a as dynamic).bar;
+  Expect.equals(#bar, info.name);
   Expect.isTrue(info.args.length == 0);
   Expect.isTrue(identical(info.receiver, a));
 
-  a.bar = 2;
+  (a as dynamic).bar = 2;
   info = topLevelInfo;
-  Expect.equals('bar', info.name);
+  Expect.equals(const Symbol('bar='), info.name);
   Expect.isTrue(info.args.length == 1);
   Expect.isTrue(info.args[0] == 2);
   Expect.isTrue(identical(info.receiver, a));
diff --git a/tests/dart2js_2/runtime_type_test.dart b/tests/dart2js_2/runtime_type_test.dart
index 9cd1bee..cc32601 100644
--- a/tests/dart2js_2/runtime_type_test.dart
+++ b/tests/dart2js_2/runtime_type_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-// dart2jsOptions=--strong
+// dart2jsOptions=--strong --no-minify
 
 // Test that Type.toString returns nice strings for native classes with
 // reserved names and for raw types.
diff --git a/tests/dart2js_2/to_string_test.dart b/tests/dart2js_2/to_string_test.dart
index de328f1..586c88f 100644
--- a/tests/dart2js_2/to_string_test.dart
+++ b/tests/dart2js_2/to_string_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // @dart = 2.7
+// dart2jsOptions=--no-minify
 
 import "package:expect/expect.dart";
 
diff --git a/tests/dart2js_2/type_literal_test.dart b/tests/dart2js_2/type_literal_test.dart
index 3712300..50ffc3e 100644
--- a/tests/dart2js_2/type_literal_test.dart
+++ b/tests/dart2js_2/type_literal_test.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-// dart2jsOptions=--strong
+// dart2jsOptions=--strong --no-minify
 
 import 'package:expect/expect.dart';
 
diff --git a/tests/dart2js_2/typevariable_typedef_test.dart b/tests/dart2js_2/typevariable_typedef_test.dart
index 6ac736e..921d68c 100644
--- a/tests/dart2js_2/typevariable_typedef_test.dart
+++ b/tests/dart2js_2/typevariable_typedef_test.dart
@@ -4,6 +4,8 @@
 
 // @dart = 2.7
 
+// dart2jsOptions=--no-minify
+
 import "package:expect/expect.dart";
 
 typedef T Func<T>(T x);
diff --git a/tests/dartdevc/container_test.dart b/tests/dartdevc/container_test.dart
new file mode 100644
index 0000000..54d2165
--- /dev/null
+++ b/tests/dartdevc/container_test.dart
@@ -0,0 +1,38 @@
+// 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.
+
+// Tests that evaluation containers aren't renamed by DDC.
+
+import 'dart:_foreign_helper' as helper show JS;
+
+import 'package:expect/expect.dart';
+
+class T {
+  final int T$Eval = 0;
+  final int S$Eval = 0;
+  String get realT$Eval => helper.JS<String>('', 'T\$Eval.toString()');
+  String get realS$Eval => helper.JS<String>('', 'S\$Eval.toString()');
+}
+
+class T$Eval {}
+
+void main() {
+  var T$Eval = T();
+  var S$Eval = T$Eval;
+
+  var container1 = helper.JS<String>('', 'T\$Eval.toString()');
+  var container2 = helper.JS<String>('', 'S\$Eval.toString()');
+
+  // Evaluation containers are JS Objects. Ensure they aren't shadowed by JS
+  // symbols or Dart constructs.
+  Expect.equals('[object Object]', '$container1');
+  Expect.equals('[object Object]', '$container2');
+
+  Expect.equals("Instance of 'T'", T$Eval.toString());
+  Expect.equals(T$Eval.T$Eval, 0);
+  Expect.equals(T$Eval.S$Eval, 0);
+  Expect.notEquals(T$Eval.toString(), container1);
+  Expect.equals(T$Eval.realT$Eval, container1);
+  Expect.equals(T$Eval.realS$Eval, container2);
+}
diff --git a/tests/ffi/aliasing_test.dart b/tests/ffi/aliasing_test.dart
index 6c2f698..946e1e4 100644
--- a/tests/ffi/aliasing_test.dart
+++ b/tests/ffi/aliasing_test.dart
@@ -13,6 +13,7 @@
 import "package:ffi/ffi.dart";
 import "package:expect/expect.dart";
 
+import 'calloc.dart';
 import 'ffi_test_helpers.dart';
 
 void main() {
@@ -35,28 +36,28 @@
 }
 
 void testNonAlias() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   source.value = 42;
   final int a = source.value;
   source.value = 1984;
   // alias.value should be re-executed, as we wrote to alias.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasCast() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias = source.cast<Int8>().cast<Int64>();
   source.value = 42;
   final int a = source.value;
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasCast2() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias = source.cast<Int16>().cast<Int64>();
   final alias2 = source.cast<Int8>().cast<Int64>();
   alias.value = 42;
@@ -64,22 +65,22 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasOffsetBy() {
-  final source = allocate<Int64>(count: 2);
+  final source = calloc<Int64>(2);
   final alias = source.offsetBy(8).offsetBy(-8);
   source.value = 42;
   final int a = source.value;
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasOffsetBy2() {
-  final source = allocate<Int64>(count: 3);
+  final source = calloc<Int64>(3);
   final alias = source.offsetBy(16).offsetBy(-16);
   final alias2 = source.offsetBy(8).offsetBy(-8);
   alias.value = 42;
@@ -87,22 +88,22 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasElementAt() {
-  final source = allocate<Int64>(count: 2);
+  final source = calloc<Int64>(2);
   final alias = source.elementAt(1).elementAt(-1);
   source.value = 42;
   final int a = source.value;
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasElementAt2() {
-  final source = allocate<Int64>(count: 3);
+  final source = calloc<Int64>(3);
   final alias = source.elementAt(2).elementAt(-2);
   final alias2 = source.elementAt(1).elementAt(-1);
   alias.value = 42;
@@ -110,22 +111,22 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasFromAddress() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias = Pointer<Int64>.fromAddress(source.address);
   source.value = 42;
   final int a = source.value;
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasFromAddress2() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias = Pointer<Int64>.fromAddress(source.address);
   final alias2 = Pointer<Int64>.fromAddress(source.address);
   alias.value = 42;
@@ -133,12 +134,12 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasFromAddressViaMemory() {
-  final helper = allocate<IntPtr>();
-  final source = allocate<Int64>();
+  final helper = calloc<IntPtr>();
+  final source = calloc<Int64>();
   helper.value = source.address;
   final alias = Pointer<Int64>.fromAddress(helper.value);
   source.value = 42;
@@ -146,13 +147,13 @@
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(helper);
-  free(source);
+  calloc.free(helper);
+  calloc.free(source);
 }
 
 void testAliasFromAddressViaMemory2() {
-  final helper = allocate<IntPtr>();
-  final source = allocate<Int64>();
+  final helper = calloc<IntPtr>();
+  final source = calloc<Int64>();
   helper.value = source.address;
   final alias = Pointer<Int64>.fromAddress(helper.value);
   final alias2 = Pointer<Int64>.fromAddress(helper.value);
@@ -161,8 +162,8 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(helper);
-  free(source);
+  calloc.free(helper);
+  calloc.free(source);
 }
 
 typedef NativeQuadOpSigned = Int64 Function(Int8, Int16, Int32, Int64);
@@ -172,7 +173,7 @@
     .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
 
 void testAliasFromAddressViaNativeFunction() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias =
       Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
   source.value = 42;
@@ -180,11 +181,11 @@
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasFromAddressViaNativeFunction2() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias =
       Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
   final alias2 =
@@ -194,7 +195,7 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 @pragma('vm:never-inline')
@@ -202,11 +203,11 @@
     source.offsetBy(7).cast<Int8>();
 
 testPartialOverlap() {
-  final source = allocate<Int64>(count: 2);
+  final source = calloc<Int64>(2);
   final derived = makeDerived(source);
   source.value = 0x1122334455667788;
   final int value = source.value;
   derived.value = 0xaa;
   Expect.notEquals(value, source.value);
-  free(source);
+  calloc.free(source);
 }
diff --git a/tests/ffi/all_positive.dart b/tests/ffi/all_positive.dart
new file mode 100644
index 0000000..d3d1db3
--- /dev/null
+++ b/tests/ffi/all_positive.dart
@@ -0,0 +1,96 @@
+// 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.
+
+// Generated by prepare_flutter_bundle.dart and not ignoring vmspecific.
+// Used in fuchsia_test_component.
+//
+// Note that we are not using any VM flags here, so we are not exercising GC
+// corner cases etc. However, we are mainly interested in exercising the
+// calling convention on Fuchsia.
+
+import "dart:async";
+
+import "aliasing_test.dart" as main0;
+import "data_not_asan_test.dart" as main1;
+import "data_test.dart" as main2;
+import "dylib_isolates_test.dart" as main3;
+import "extension_methods_test.dart" as main4;
+import "external_typed_data_test.dart" as main5;
+import "function_callbacks_many_test.dart" as main6;
+import "function_callbacks_test.dart" as main7;
+import "function_callbacks_very_many_test.dart" as main8;
+import "function_structs_test.dart" as main9;
+import "function_test.dart" as main10;
+import "function_very_many_test.dart" as main11;
+import "hardfp_test.dart" as main12;
+import "negative_function_test.dart" as main13;
+import "regress_37254_test.dart" as main16;
+import "regress_39044_test.dart" as main17;
+import "regress_39063_test.dart" as main18;
+import "regress_39885_test.dart" as main19;
+import "regress_40537_test.dart" as main20;
+import "regress_43016_test.dart" as main21;
+import "regress_43693_test.dart" as main22;
+import "regress_jump_to_frame_test.dart" as main23;
+import "sizeof_test.dart" as main24;
+import "snapshot_test.dart" as main25;
+import "stacktrace_regress_37910_test.dart" as main26;
+import "structs_test.dart" as main27;
+import "variance_function_test.dart" as main28;
+import "vmspecific_function_callbacks_exit_test.dart" as main29;
+import "vmspecific_function_test.dart" as main30;
+import "vmspecific_handle_dynamically_linked_test.dart" as main31;
+import "vmspecific_handle_test.dart" as main32;
+import "vmspecific_object_gc_test.dart" as main34;
+import "vmspecific_regress_37100_test.dart" as main35;
+import "vmspecific_regress_37511_callbacks_test.dart" as main36;
+import "vmspecific_regress_37511_test.dart" as main37;
+import "vmspecific_regress_37780_test.dart" as main38;
+
+Future invoke(dynamic fun) async {
+  if (fun is void Function() || fun is Future Function()) {
+    return await fun();
+  } else {
+    return await fun(<String>[]);
+  }
+}
+
+dynamic main() async {
+  await invoke(main0.main);
+  await invoke(main1.main);
+  await invoke(main2.main);
+  await invoke(main3.main);
+  await invoke(main4.main);
+  await invoke(main5.main);
+  await invoke(main6.main);
+  await invoke(main7.main);
+  await invoke(main8.main);
+  await invoke(main9.main);
+  await invoke(main10.main);
+  await invoke(main11.main);
+  await invoke(main12.main);
+  await invoke(main13.main);
+  await invoke(main16.main);
+  await invoke(main17.main);
+  await invoke(main18.main);
+  await invoke(main19.main);
+  await invoke(main20.main);
+  await invoke(main21.main);
+  await invoke(main22.main);
+  await invoke(main23.main);
+  await invoke(main24.main);
+  await invoke(main25.main);
+  await invoke(main26.main);
+  await invoke(main27.main);
+  await invoke(main28.main);
+  await invoke(main29.main);
+  await invoke(main30.main);
+  await invoke(main31.main);
+  await invoke(main32.main);
+  await invoke(main34.main);
+  await invoke(main35.main);
+  await invoke(main36.main);
+  await invoke(main37.main);
+  await invoke(main38.main);
+}
diff --git a/tests/ffi/allocator_test.dart b/tests/ffi/allocator_test.dart
new file mode 100644
index 0000000..ab2e8db
--- /dev/null
+++ b/tests/ffi/allocator_test.dart
@@ -0,0 +1,24 @@
+// 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 we can implement the Allocator interface.
+
+import 'dart:ffi';
+
+class MyAllocator implements Allocator {
+  const MyAllocator();
+
+  @override
+  Pointer<T> allocate<T extends NativeType>(int numBytes, {int? alignment}) {
+    throw "Not implemented";
+  }
+
+  void free(Pointer pointer) {}
+}
+
+const myAllocator = MyAllocator();
+
+void main() {
+  print(myAllocator);
+}
diff --git a/tests/ffi/calloc.dart b/tests/ffi/calloc.dart
new file mode 100644
index 0000000..e17238a
--- /dev/null
+++ b/tests/ffi/calloc.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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int? alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/tests/ffi/calloc_test.dart b/tests/ffi/calloc_test.dart
new file mode 100644
index 0000000..b8b9bbf
--- /dev/null
+++ b/tests/ffi/calloc_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.
+
+import 'dart:ffi';
+
+import 'package:expect/expect.dart';
+
+import 'calloc.dart';
+import 'coordinate.dart';
+
+void main() {
+  testZeroInt();
+  testZeroFloat();
+  testZeroStruct();
+}
+
+void testZeroInt() {
+  final p = calloc<Uint8>();
+  Expect.equals(0, p.value);
+  calloc.free(p);
+}
+
+void testZeroFloat() {
+  final p = calloc<Float>();
+  Expect.approxEquals(0.0, p.value);
+  calloc.free(p);
+}
+
+void testZeroStruct() {
+  final p = calloc<Coordinate>();
+  Expect.approxEquals(0, p.ref.x);
+  Expect.approxEquals(0, p.ref.y);
+  Expect.equals(nullptr, p.ref.next);
+  calloc.free(p);
+}
diff --git a/tests/ffi/coordinate.dart b/tests/ffi/coordinate.dart
index 9507312..abd6ecd 100644
--- a/tests/ffi/coordinate.dart
+++ b/tests/ffi/coordinate.dart
@@ -17,8 +17,9 @@
 
   external Pointer<Coordinate> next;
 
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
-    return allocate<Coordinate>().ref
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {
+    return allocator<Coordinate>().ref
       ..x = x
       ..y = y
       ..next = next;
diff --git a/tests/ffi/coordinate_nnbd_workaround.dart b/tests/ffi/coordinate_nnbd_workaround.dart
index 515badd..abd8dba 100644
--- a/tests/ffi/coordinate_nnbd_workaround.dart
+++ b/tests/ffi/coordinate_nnbd_workaround.dart
@@ -20,8 +20,9 @@
   external Pointer<Coordinate> get next;
   external set next(Pointer<Coordinate> v);
 
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
-    return allocate<Coordinate>().ref
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {
+    return allocator<Coordinate>().ref
       ..x = x
       ..y = y
       ..next = next;
diff --git a/tests/ffi/data_not_asan_test.dart b/tests/ffi/data_not_asan_test.dart
index e95658f..69257d6 100644
--- a/tests/ffi/data_not_asan_test.dart
+++ b/tests/ffi/data_not_asan_test.dart
@@ -4,7 +4,7 @@
 //
 // Dart test program for testing dart:ffi primitive data pointers.
 //
-// These mallocs trigger an asan alarm, so these tests are in a separate file
+// These callocs trigger an asan alarm, so these tests are in a separate file
 // which is excluded in asan mode.
 
 import 'dart:ffi';
@@ -12,6 +12,8 @@
 import "package:ffi/ffi.dart";
 import "package:expect/expect.dart";
 
+import 'calloc.dart';
+
 void main() {
   testPointerAllocateTooLarge();
   testPointerAllocateNegative();
@@ -20,16 +22,16 @@
 void testPointerAllocateTooLarge() {
   // Try to allocate something that doesn't fit in 64 bit address space.
   int maxInt = 9223372036854775807; // 2^63 - 1
-  Expect.throws(() => allocate<Int64>(count: maxInt));
+  Expect.throws(() => calloc<Int64>(maxInt));
 
   // Try to allocate almost the full 64 bit address space.
   int maxInt1_8 = 1152921504606846975; // 2^60 -1
-  Expect.throws(() => allocate<Int64>(count: maxInt1_8));
+  Expect.throws(() => calloc<Int64>(maxInt1_8));
 }
 
 void testPointerAllocateNegative() {
   // Passing in -1 will be converted into an unsigned integer. So, it will try
   // to allocate SIZE_MAX - 1 + 1 bytes. This will fail as it is the max amount
   // of addressable memory on the system.
-  Expect.throws(() => allocate<Int8>(count: -1));
+  Expect.throws(() => calloc<Int8>(-1));
 }
diff --git a/tests/ffi/data_test.dart b/tests/ffi/data_test.dart
index b2d304d..f2543d1 100644
--- a/tests/ffi/data_test.dart
+++ b/tests/ffi/data_test.dart
@@ -11,6 +11,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'ffi_test_helpers.dart';
 
 void main() {
@@ -44,80 +45,76 @@
   testTypeTest();
   testToString();
   testEquality();
-  testAllocateGeneric();
   testAllocateVoid();
   testAllocateNativeFunction();
-  testAllocateNativeType();
-  testSizeOfGeneric();
   testSizeOfVoid();
   testSizeOfNativeFunction();
-  testSizeOfNativeType();
   testDynamicInvocation();
   testMemoryAddressTruncation();
   testNullptrCast();
 }
 
 void testPointerBasic() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.value = 42;
   Expect.equals(42, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testPointerFromPointer() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.value = 1337;
   int ptr = p.address;
   Pointer<Int64> p2 = Pointer.fromAddress(ptr);
   Expect.equals(1337, p2.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testPointerPointerArithmetic() {
-  Pointer<Int64> p = allocate(count: 2);
+  Pointer<Int64> p = calloc(2);
   Pointer<Int64> p2 = p.elementAt(1);
   p2.value = 100;
   Pointer<Int64> p3 = p.offsetBy(8);
   Expect.equals(100, p3.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testPointerPointerArithmeticSizes() {
-  Pointer<Int64> p = allocate(count: 2);
+  Pointer<Int64> p = calloc(2);
   Pointer<Int64> p2 = p.elementAt(1);
   int addr = p.address;
   Expect.equals(addr + 8, p2.address);
-  free(p);
+  calloc.free(p);
 
-  Pointer<Int32> p3 = allocate(count: 2);
+  Pointer<Int32> p3 = calloc(2);
   Pointer<Int32> p4 = p3.elementAt(1);
   addr = p3.address;
   Expect.equals(addr + 4, p4.address);
-  free(p3);
+  calloc.free(p3);
 }
 
 void testPointerAllocateZero() {
   // > If size is 0, either a null pointer or a unique pointer that can be
-  // > successfully passed to free() shall be returned.
-  // http://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html
+  // > successfully passed to calloc.free() shall be returned.
+  // http://pubs.opengroup.org/onlinepubs/009695399/functions/calloc.html
   //
   // Null pointer throws a Dart exception.
   bool returnedNullPointer = false;
   Pointer<Int8> p = nullptr;
   try {
-    p = allocate<Int8>(count: 0);
+    p = calloc<Int8>(0);
   } on Exception {
     returnedNullPointer = true;
   }
   if (!returnedNullPointer) {
-    free(p);
+    calloc.free(p);
   }
 }
 
 void testPointerCast() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.cast<Int32>(); // gets the correct type args back
-  free(p);
+  calloc.free(p);
 }
 
 void testCastGeneric() {
@@ -125,9 +122,9 @@
     return p.cast();
   }
 
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   Pointer<Int64> p2 = generic(p);
-  free(p);
+  calloc.free(p);
 }
 
 void testCastGeneric2() {
@@ -135,41 +132,41 @@
     return p.cast();
   }
 
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   Pointer<Int64> p2 = generic(p);
-  free(p);
+  calloc.free(p);
 }
 
 void testCastNativeType() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.cast<Pointer>();
-  free(p);
+  calloc.free(p);
 }
 
 void testCondensedNumbersInt8() {
-  Pointer<Int8> p = allocate(count: 8);
+  Pointer<Int8> p = calloc(8);
   for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
     p[i] = i * 3;
   }
   for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
     Expect.equals(i * 3, p[i]);
   }
-  free(p);
+  calloc.free(p);
 }
 
 void testCondensedNumbersFloat() {
-  Pointer<Float> p = allocate(count: 8);
+  Pointer<Float> p = calloc(8);
   for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
     p[i] = 1.511366173271439e-13;
   }
   for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
     Expect.equals(1.511366173271439e-13, p[i]);
   }
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeInt8() {
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   p.value = 127;
   Expect.equals(127, p.value);
   p.value = -128;
@@ -184,11 +181,11 @@
   Expect.equals(0x000000000000007F, 127);
   p.value = -129;
   Expect.equals(127, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeUint8() {
-  Pointer<Uint8> p = allocate();
+  Pointer<Uint8> p = calloc();
   p.value = 255;
   Expect.equals(255, p.value);
   p.value = 0;
@@ -203,11 +200,11 @@
   Expect.equals(0x00000000000000FF, 255);
   p.value = -1;
   Expect.equals(255, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeInt16() {
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   p.value = 0x7FFF;
   Expect.equals(0x7FFF, p.value);
   p.value = -0x8000;
@@ -216,11 +213,11 @@
   Expect.equals(0xFFFFFFFFFFFF8000, p.value); // truncated and sign extended
   p.value = -0x8001;
   Expect.equals(0x7FFF, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeUint16() {
-  Pointer<Uint16> p = allocate();
+  Pointer<Uint16> p = calloc();
   p.value = 0xFFFF;
   Expect.equals(0xFFFF, p.value);
   p.value = 0;
@@ -229,11 +226,11 @@
   Expect.equals(0, p.value); // truncated
   p.value = -1;
   Expect.equals(0xFFFF, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeInt32() {
-  Pointer<Int32> p = allocate();
+  Pointer<Int32> p = calloc();
   p.value = 0x7FFFFFFF;
   Expect.equals(0x7FFFFFFF, p.value);
   p.value = -0x80000000;
@@ -242,11 +239,11 @@
   Expect.equals(0xFFFFFFFF80000000, p.value); // truncated and sign extended
   p.value = -0x80000001;
   Expect.equals(0x7FFFFFFF, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeUint32() {
-  Pointer<Uint32> p = allocate();
+  Pointer<Uint32> p = calloc();
   p.value = 0xFFFFFFFF;
   Expect.equals(0xFFFFFFFF, p.value);
   p.value = 0;
@@ -255,20 +252,20 @@
   Expect.equals(0, p.value); // truncated
   p.value = -1;
   Expect.equals(0xFFFFFFFF, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeInt64() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
   Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
   p.value = -0x8000000000000000; // -2 ^ 63
   Expect.equals(-0x8000000000000000, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeUint64() {
-  Pointer<Uint64> p = allocate();
+  Pointer<Uint64> p = calloc();
   p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
   Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
   p.value = -0x8000000000000000; // -2 ^ 63 interpreted as 2 ^ 63
@@ -279,69 +276,69 @@
   p.value = -1; // -1 interpreted as 2 ^ 64 - 1
   Expect.equals(-1, p.value);
   Expect.equals(0xFFFFFFFFFFFFFFFF, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeIntPtr() {
-  Pointer<IntPtr> p = allocate();
+  Pointer<IntPtr> p = calloc();
   int pAddr = p.address;
   p.value = pAddr; // its own address should fit
   p.value = 0x7FFFFFFF; // and 32 bit addresses should fit
   Expect.equals(0x7FFFFFFF, p.value);
   p.value = -0x80000000;
   Expect.equals(-0x80000000, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testFloat() {
-  Pointer<Float> p = allocate();
+  Pointer<Float> p = calloc();
   p.value = 1.511366173271439e-13;
   Expect.equals(1.511366173271439e-13, p.value);
   p.value = 1.4260258159703532e-105; // float does not have enough precision
   Expect.notEquals(1.4260258159703532e-105, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testDouble() {
-  Pointer<Double> p = allocate();
+  Pointer<Double> p = calloc();
   p.value = 1.4260258159703532e-105;
   Expect.equals(1.4260258159703532e-105, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testVoid() {
-  Pointer<IntPtr> p1 = allocate();
+  Pointer<IntPtr> p1 = calloc();
   Pointer<Void> p2 = p1.cast(); // make this dart pointer opaque
   p2.address; // we can print the address
-  free(p2);
+  calloc.free(p2);
 }
 
 void testPointerPointer() {
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   p.value = 17;
-  Pointer<Pointer<Int16>> p2 = allocate();
+  Pointer<Pointer<Int16>> p2 = calloc();
   p2.value = p;
   Expect.equals(17, p2.value.value);
-  free(p2);
-  free(p);
+  calloc.free(p2);
+  calloc.free(p);
 }
 
 void testPointerPointerNull() {
-  Pointer<Pointer<Int8>> pointerToPointer = allocate();
+  Pointer<Pointer<Int8>> pointerToPointer = calloc();
   Pointer<Int8> value = nullptr;
   pointerToPointer.value = value;
   value = pointerToPointer.value;
   Expect.equals(value, nullptr);
-  value = allocate();
+  value = calloc();
   pointerToPointer.value = value;
   value = pointerToPointer.value;
   Expect.isNotNull(value);
-  free(value);
+  calloc.free(value);
   value = nullptr;
   pointerToPointer.value = value;
   value = pointerToPointer.value;
   Expect.equals(value, nullptr);
-  free(pointerToPointer);
+  calloc.free(pointerToPointer);
 }
 
 void testSizeOf() {
@@ -365,7 +362,7 @@
       head.value = value;
       return;
     }
-    Pointer<IntPtr> next = allocate();
+    Pointer<IntPtr> next = calloc();
     head.value = next.address;
     createChain(next, length - 1, value);
   }
@@ -380,14 +377,14 @@
 
   void freeChain(Pointer<IntPtr> head, int length) {
     Pointer<IntPtr> next = Pointer.fromAddress(head.value);
-    free(head);
+    calloc.free(head);
     if (length == 0) {
       return;
     }
     freeChain(next, length - 1);
   }
 
-  Pointer<IntPtr> head = allocate();
+  Pointer<IntPtr> head = calloc();
   createChain(head, length, 512);
   int tailValue = getChainValue(head, length);
   Expect.equals(512, tailValue);
@@ -395,16 +392,16 @@
 }
 
 void testTypeTest() {
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   Expect.isTrue(p is Pointer);
-  free(p);
+  calloc.free(p);
 }
 
 void testToString() {
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   Expect.stringEquals(
       "Pointer<Int16>: address=0x", p.toString().substring(0, 26));
-  free(p);
+  calloc.free(p);
   Pointer<Int64> p2 = Pointer.fromAddress(0x123abc);
   Expect.stringEquals("Pointer<Int64>: address=0x123abc", p2.toString());
 }
@@ -423,46 +420,18 @@
 
 typedef Int8UnOp = Int8 Function(Int8);
 
-void testAllocateGeneric() {
-  Pointer<T> generic<T extends NativeType>() {
-    Pointer<T> pointer;
-    pointer = allocate();
-    return pointer;
-  }
-
-  Pointer p = generic<Int64>();
-  free(p);
-}
-
 void testAllocateVoid() {
   Expect.throws(() {
-    Pointer<Void> p = allocate();
+    Pointer<Void> p = calloc();
   });
 }
 
 void testAllocateNativeFunction() {
   Expect.throws(() {
-    Pointer<NativeFunction<Int8UnOp>> p = allocate();
+    Pointer<NativeFunction<Int8UnOp>> p = calloc();
   });
 }
 
-void testAllocateNativeType() {
-  Expect.throws(() {
-    allocate();
-  });
-}
-
-void testSizeOfGeneric() {
-  int generic<T extends Pointer>() {
-    int size;
-    size = sizeOf<T>();
-    return size;
-  }
-
-  int size = generic<Pointer<Int64>>();
-  Expect.isTrue(size == 8 || size == 4);
-}
-
 void testSizeOfVoid() {
   Expect.throws(() {
     sizeOf<Void>();
@@ -475,14 +444,8 @@
   });
 }
 
-void testSizeOfNativeType() {
-  Expect.throws(() {
-    sizeOf();
-  });
-}
-
 void testDynamicInvocation() {
-  dynamic p = allocate<Int8>();
+  dynamic p = calloc<Int8>();
   Expect.throws(() {
     final int i = p.value;
   });
@@ -490,7 +453,7 @@
   p.elementAt(5); // Works, but is slow.
   final int addr = p.address;
   final Pointer<Int16> p2 = p.cast<Int16>();
-  free(p);
+  calloc.free(p);
 }
 
 final nullableInt64ElementAt1 = ffiTestFunctions.lookupFunction<
diff --git a/tests/ffi/dylib_utils.dart b/tests/ffi/dylib_utils.dart
index 2b7ac27..c2c8db8 100644
--- a/tests/ffi/dylib_utils.dart
+++ b/tests/ffi/dylib_utils.dart
@@ -7,7 +7,7 @@
 
 String _platformPath(String name, {String? path}) {
   if (path == null) path = "";
-  if (Platform.isLinux || Platform.isAndroid)
+  if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
diff --git a/tests/ffi/extension_methods_test.dart b/tests/ffi/extension_methods_test.dart
index d4e8e4a..5c688e0e 100644
--- a/tests/ffi/extension_methods_test.dart
+++ b/tests/ffi/extension_methods_test.dart
@@ -7,6 +7,8 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
+
 main(List<String> arguments) {
   for (int i = 0; i < 100; i++) {
     testStoreLoad();
@@ -15,7 +17,7 @@
 }
 
 testStoreLoad() {
-  final p = allocate<Int8>(count: 2);
+  final p = calloc<Int8>(2);
   p.value = 10;
   Expect.equals(10, p.value);
   p[1] = 20;
@@ -30,33 +32,33 @@
   final pUseNegative = p.elementAt(1);
   Expect.equals(10, pUseNegative[-1]);
 
-  final p1 = allocate<Double>(count: 2);
+  final p1 = calloc<Double>(2);
   p1.value = 10.0;
   Expect.approxEquals(10.0, p1.value);
   p1[1] = 20.0;
   Expect.approxEquals(20.0, p1[1]);
-  free(p1);
+  calloc.free(p1);
 
-  final p2 = allocate<Pointer<Int8>>(count: 2);
+  final p2 = calloc<Pointer<Int8>>(2);
   p2.value = p;
   Expect.equals(p, p2.value);
   p2[1] = p;
   Expect.equals(p, p2[1]);
-  free(p2);
-  free(p);
+  calloc.free(p2);
+  calloc.free(p);
 
-  final p3 = allocate<Foo>();
+  final p3 = calloc<Foo>();
   Foo foo = p3.ref;
   foo.a = 1;
   Expect.equals(1, foo.a);
-  free(p3);
+  calloc.free(p3);
 }
 
 testReifiedGeneric() {
-  final p = allocate<Pointer<Int8>>();
+  final p = calloc<Pointer<Int8>>();
   Pointer<Pointer<NativeType>> p2 = p;
   Expect.isTrue(p2.value is Pointer<Int8>);
-  free(p);
+  calloc.free(p);
 }
 
 class Foo extends Struct {
diff --git a/tests/ffi/external_typed_data_test.dart b/tests/ffi/external_typed_data_test.dart
index 2b584b4..1327dea 100644
--- a/tests/ffi/external_typed_data_test.dart
+++ b/tests/ffi/external_typed_data_test.dart
@@ -9,6 +9,8 @@
 import 'package:expect/expect.dart';
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
+
 main() {
   testInt8Load();
   testInt8Store();
@@ -41,162 +43,162 @@
 
 void testInt8Load() {
   // Load
-  Pointer<Int8> ptr = allocate();
+  Pointer<Int8> ptr = calloc();
   ptr.value = 0xff;
   Int8List list = ptr.asTypedList(1);
   Expect.equals(list[0], -1);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt8Store() {
   // Store
-  Pointer<Int8> ptr = allocate();
+  Pointer<Int8> ptr = calloc();
   Int8List list = ptr.asTypedList(1);
   list[0] = 0xff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, -1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint8Load() {
   // Load
-  Pointer<Uint8> ptr = allocate();
+  Pointer<Uint8> ptr = calloc();
   ptr.value = 0xff;
   Uint8List list = ptr.asTypedList(1);
   Expect.equals(list[0], 0xff);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint8Store() {
   // Store
-  Pointer<Uint8> ptr = allocate();
+  Pointer<Uint8> ptr = calloc();
   Uint8List list = ptr.asTypedList(1);
   list[0] = 0xff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, 0xff);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt16Load() {
   // Load
-  Pointer<Int16> ptr = allocate();
+  Pointer<Int16> ptr = calloc();
   ptr.value = 0xffff;
   Int16List list = ptr.asTypedList(1);
   Expect.equals(list[0], -1);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt16Store() {
   // Store
-  Pointer<Int16> ptr = allocate();
+  Pointer<Int16> ptr = calloc();
   Int16List list = ptr.asTypedList(1);
   list[0] = 0xffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, -1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint16Load() {
   // Load
-  Pointer<Uint16> ptr = allocate();
+  Pointer<Uint16> ptr = calloc();
   ptr.value = 0xffff;
   Uint16List list = ptr.asTypedList(1);
   Expect.equals(list[0], 0xffff);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint16Store() {
   // Store
-  Pointer<Uint16> ptr = allocate();
+  Pointer<Uint16> ptr = calloc();
   Uint16List list = ptr.asTypedList(1);
   list[0] = 0xffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, 0xffff);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt32Load() {
   // Load
-  Pointer<Int32> ptr = allocate();
+  Pointer<Int32> ptr = calloc();
   ptr.value = 0xffffffff;
   Int32List list = ptr.asTypedList(1);
   Expect.equals(list[0], -1);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt32Store() {
   // Store
-  Pointer<Int32> ptr = allocate();
+  Pointer<Int32> ptr = calloc();
   Int32List list = ptr.asTypedList(1);
   list[0] = 0xffffffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, -1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint32Load() {
   // Load
-  Pointer<Uint32> ptr = allocate();
+  Pointer<Uint32> ptr = calloc();
   ptr.value = 0xffffffff;
   Uint32List list = ptr.asTypedList(1);
   Expect.equals(list[0], 0xffffffff);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint32Store() {
   // Store
-  Pointer<Uint32> ptr = allocate();
+  Pointer<Uint32> ptr = calloc();
   Uint32List list = ptr.asTypedList(1);
   list[0] = 0xffffffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, 0xffffffff);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt64Load() {
   // Load
-  Pointer<Int64> ptr = allocate();
+  Pointer<Int64> ptr = calloc();
   ptr.value = 0xffffffffffffffff;
   Int64List list = ptr.asTypedList(1);
   Expect.equals(list[0], -1);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt64Store() {
   // Store
-  Pointer<Int64> ptr = allocate();
+  Pointer<Int64> ptr = calloc();
   Int64List list = ptr.asTypedList(1);
   list[0] = 0xffffffffffffffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, -1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint64Load() {
   // Load
-  Pointer<Uint64> ptr = allocate();
+  Pointer<Uint64> ptr = calloc();
   ptr.value = 0xffffffffffffffff;
   Uint64List list = ptr.asTypedList(1);
   Expect.equals(list[0], 0xffffffffffffffff);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint64Store() {
   // Store
-  Pointer<Uint64> ptr = allocate();
+  Pointer<Uint64> ptr = calloc();
   Uint64List list = ptr.asTypedList(1);
   list[0] = 0xffffffffffffffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, 0xffffffffffffffff);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 double maxFloat = (2 - pow(2, -23)) * pow(2, 127) as double;
@@ -204,47 +206,47 @@
 
 void testFloatLoad() {
   // Load
-  Pointer<Float> ptr = allocate();
+  Pointer<Float> ptr = calloc();
   ptr.value = maxFloat;
   Float32List list = ptr.asTypedList(1);
   Expect.equals(list[0], maxFloat);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testFloatStore() {
   // Store
-  Pointer<Float> ptr = allocate();
+  Pointer<Float> ptr = calloc();
   Float32List list = ptr.asTypedList(1);
   list[0] = maxFloat;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, maxFloat);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testDoubleLoad() {
   // Load
-  Pointer<Double> ptr = allocate();
+  Pointer<Double> ptr = calloc();
   ptr.value = maxDouble;
   Float64List list = ptr.asTypedList(1);
   Expect.equals(list[0], maxDouble);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testDoubleStore() {
   // Store
-  Pointer<Double> ptr = allocate();
+  Pointer<Double> ptr = calloc();
   Float64List list = ptr.asTypedList(1);
   list[0] = maxDouble;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, maxDouble);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testArrayLoad() {
   const int count = 0x100;
-  Pointer<Int32> ptr = allocate(count: count);
+  Pointer<Int32> ptr = calloc(count);
   for (int i = 0; i < count; ++i) {
     ptr[i] = i;
   }
@@ -252,12 +254,12 @@
   for (int i = 0; i < count; ++i) {
     Expect.equals(array[i], i);
   }
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testArrayStore() {
   const int count = 0x100;
-  Pointer<Int32> ptr = allocate(count: count);
+  Pointer<Int32> ptr = calloc(count);
   Int32List array = ptr.asTypedList(count);
   for (int i = 0; i < count; ++i) {
     array[i] = i;
@@ -265,7 +267,7 @@
   for (int i = 0; i < count; ++i) {
     Expect.equals(ptr[i], i);
   }
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testNegativeArray() {
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 3baf069..37ab3e9 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -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.
 
-# TODO(dartbug.com/36730): Implement structs by value.
-function_callbacks_structs_by_value_generated_test: Skip
-function_callbacks_structs_by_value_test: Skip
-function_structs_by_value_generated_test: Skip
-
 [ $builder_tag == msan ]
 vmspecific_handle_test: Skip # https://dartbug.com/42314
 
diff --git a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
index 845ebb9..785f03a 100644
--- a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
+++ b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
@@ -16,6 +16,7 @@
 import "package:ffi/ffi.dart";
 
 import 'callback_tests_utils.dart';
+import 'calloc.dart';
 
 // Reuse the struct classes.
 import 'function_structs_by_value_generated_test.dart';
@@ -193,6 +194,56 @@
           passStructAlignmentInt64, 0),
       passStructAlignmentInt64AfterCallback),
   CallbackTest.withCheck(
+      "PassStruct8BytesNestedIntx10",
+      Pointer.fromFunction<PassStruct8BytesNestedIntx10Type>(
+          passStruct8BytesNestedIntx10, 0),
+      passStruct8BytesNestedIntx10AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct8BytesNestedFloatx10",
+      Pointer.fromFunction<PassStruct8BytesNestedFloatx10Type>(
+          passStruct8BytesNestedFloatx10, 0.0),
+      passStruct8BytesNestedFloatx10AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct8BytesNestedFloat2x10",
+      Pointer.fromFunction<PassStruct8BytesNestedFloat2x10Type>(
+          passStruct8BytesNestedFloat2x10, 0.0),
+      passStruct8BytesNestedFloat2x10AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct8BytesNestedMixedx10",
+      Pointer.fromFunction<PassStruct8BytesNestedMixedx10Type>(
+          passStruct8BytesNestedMixedx10, 0.0),
+      passStruct8BytesNestedMixedx10AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct16BytesNestedIntx2",
+      Pointer.fromFunction<PassStruct16BytesNestedIntx2Type>(
+          passStruct16BytesNestedIntx2, 0),
+      passStruct16BytesNestedIntx2AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct32BytesNestedIntx2",
+      Pointer.fromFunction<PassStruct32BytesNestedIntx2Type>(
+          passStruct32BytesNestedIntx2, 0),
+      passStruct32BytesNestedIntx2AfterCallback),
+  CallbackTest.withCheck(
+      "PassStructNestedIntStructAlignmentInt16",
+      Pointer.fromFunction<PassStructNestedIntStructAlignmentInt16Type>(
+          passStructNestedIntStructAlignmentInt16, 0),
+      passStructNestedIntStructAlignmentInt16AfterCallback),
+  CallbackTest.withCheck(
+      "PassStructNestedIntStructAlignmentInt32",
+      Pointer.fromFunction<PassStructNestedIntStructAlignmentInt32Type>(
+          passStructNestedIntStructAlignmentInt32, 0),
+      passStructNestedIntStructAlignmentInt32AfterCallback),
+  CallbackTest.withCheck(
+      "PassStructNestedIntStructAlignmentInt64",
+      Pointer.fromFunction<PassStructNestedIntStructAlignmentInt64Type>(
+          passStructNestedIntStructAlignmentInt64, 0),
+      passStructNestedIntStructAlignmentInt64AfterCallback),
+  CallbackTest.withCheck(
+      "PassStructNestedIrregularEvenBiggerx4",
+      Pointer.fromFunction<PassStructNestedIrregularEvenBiggerx4Type>(
+          passStructNestedIrregularEvenBiggerx4, 0.0),
+      passStructNestedIrregularEvenBiggerx4AfterCallback),
+  CallbackTest.withCheck(
       "ReturnStruct1ByteInt",
       Pointer.fromFunction<ReturnStruct1ByteIntType>(returnStruct1ByteInt),
       returnStruct1ByteIntAfterCallback),
@@ -342,6 +393,56 @@
       Pointer.fromFunction<ReturnStructAlignmentInt64Type>(
           returnStructAlignmentInt64),
       returnStructAlignmentInt64AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct8BytesNestedInt",
+      Pointer.fromFunction<ReturnStruct8BytesNestedIntType>(
+          returnStruct8BytesNestedInt),
+      returnStruct8BytesNestedIntAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct8BytesNestedFloat",
+      Pointer.fromFunction<ReturnStruct8BytesNestedFloatType>(
+          returnStruct8BytesNestedFloat),
+      returnStruct8BytesNestedFloatAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct8BytesNestedFloat2",
+      Pointer.fromFunction<ReturnStruct8BytesNestedFloat2Type>(
+          returnStruct8BytesNestedFloat2),
+      returnStruct8BytesNestedFloat2AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct8BytesNestedMixed",
+      Pointer.fromFunction<ReturnStruct8BytesNestedMixedType>(
+          returnStruct8BytesNestedMixed),
+      returnStruct8BytesNestedMixedAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct16BytesNestedInt",
+      Pointer.fromFunction<ReturnStruct16BytesNestedIntType>(
+          returnStruct16BytesNestedInt),
+      returnStruct16BytesNestedIntAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct32BytesNestedInt",
+      Pointer.fromFunction<ReturnStruct32BytesNestedIntType>(
+          returnStruct32BytesNestedInt),
+      returnStruct32BytesNestedIntAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStructNestedIntStructAlignmentInt16",
+      Pointer.fromFunction<ReturnStructNestedIntStructAlignmentInt16Type>(
+          returnStructNestedIntStructAlignmentInt16),
+      returnStructNestedIntStructAlignmentInt16AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStructNestedIntStructAlignmentInt32",
+      Pointer.fromFunction<ReturnStructNestedIntStructAlignmentInt32Type>(
+          returnStructNestedIntStructAlignmentInt32),
+      returnStructNestedIntStructAlignmentInt32AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStructNestedIntStructAlignmentInt64",
+      Pointer.fromFunction<ReturnStructNestedIntStructAlignmentInt64Type>(
+          returnStructNestedIntStructAlignmentInt64),
+      returnStructNestedIntStructAlignmentInt64AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStructNestedIrregularEvenBigger",
+      Pointer.fromFunction<ReturnStructNestedIrregularEvenBiggerType>(
+          returnStructNestedIrregularEvenBigger),
+      returnStructNestedIrregularEvenBiggerAfterCallback),
 ];
 typedef PassStruct1ByteIntx10Type = Int64 Function(
     Struct1ByteInt,
@@ -4128,6 +4229,1013 @@
   Expect.equals(-2, result);
 }
 
+typedef PassStruct8BytesNestedIntx10Type = Int64 Function(
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a0 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a1 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a2 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a3 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a4 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a5 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a6 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a7 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a8 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a9 = Struct8BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct8BytesNestedIntx10Result = 0;
+
+int passStruct8BytesNestedIntx10CalculateResult() {
+  int result = 0;
+
+  result += passStruct8BytesNestedIntx10_a0.a0.a0;
+  result += passStruct8BytesNestedIntx10_a0.a0.a1;
+  result += passStruct8BytesNestedIntx10_a0.a1.a0;
+  result += passStruct8BytesNestedIntx10_a0.a1.a1;
+  result += passStruct8BytesNestedIntx10_a1.a0.a0;
+  result += passStruct8BytesNestedIntx10_a1.a0.a1;
+  result += passStruct8BytesNestedIntx10_a1.a1.a0;
+  result += passStruct8BytesNestedIntx10_a1.a1.a1;
+  result += passStruct8BytesNestedIntx10_a2.a0.a0;
+  result += passStruct8BytesNestedIntx10_a2.a0.a1;
+  result += passStruct8BytesNestedIntx10_a2.a1.a0;
+  result += passStruct8BytesNestedIntx10_a2.a1.a1;
+  result += passStruct8BytesNestedIntx10_a3.a0.a0;
+  result += passStruct8BytesNestedIntx10_a3.a0.a1;
+  result += passStruct8BytesNestedIntx10_a3.a1.a0;
+  result += passStruct8BytesNestedIntx10_a3.a1.a1;
+  result += passStruct8BytesNestedIntx10_a4.a0.a0;
+  result += passStruct8BytesNestedIntx10_a4.a0.a1;
+  result += passStruct8BytesNestedIntx10_a4.a1.a0;
+  result += passStruct8BytesNestedIntx10_a4.a1.a1;
+  result += passStruct8BytesNestedIntx10_a5.a0.a0;
+  result += passStruct8BytesNestedIntx10_a5.a0.a1;
+  result += passStruct8BytesNestedIntx10_a5.a1.a0;
+  result += passStruct8BytesNestedIntx10_a5.a1.a1;
+  result += passStruct8BytesNestedIntx10_a6.a0.a0;
+  result += passStruct8BytesNestedIntx10_a6.a0.a1;
+  result += passStruct8BytesNestedIntx10_a6.a1.a0;
+  result += passStruct8BytesNestedIntx10_a6.a1.a1;
+  result += passStruct8BytesNestedIntx10_a7.a0.a0;
+  result += passStruct8BytesNestedIntx10_a7.a0.a1;
+  result += passStruct8BytesNestedIntx10_a7.a1.a0;
+  result += passStruct8BytesNestedIntx10_a7.a1.a1;
+  result += passStruct8BytesNestedIntx10_a8.a0.a0;
+  result += passStruct8BytesNestedIntx10_a8.a0.a1;
+  result += passStruct8BytesNestedIntx10_a8.a1.a0;
+  result += passStruct8BytesNestedIntx10_a8.a1.a1;
+  result += passStruct8BytesNestedIntx10_a9.a0.a0;
+  result += passStruct8BytesNestedIntx10_a9.a0.a1;
+  result += passStruct8BytesNestedIntx10_a9.a1.a0;
+  result += passStruct8BytesNestedIntx10_a9.a1.a1;
+
+  passStruct8BytesNestedIntx10Result = result;
+
+  return result;
+}
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust registers on all platforms.
+int passStruct8BytesNestedIntx10(
+    Struct8BytesNestedInt a0,
+    Struct8BytesNestedInt a1,
+    Struct8BytesNestedInt a2,
+    Struct8BytesNestedInt a3,
+    Struct8BytesNestedInt a4,
+    Struct8BytesNestedInt a5,
+    Struct8BytesNestedInt a6,
+    Struct8BytesNestedInt a7,
+    Struct8BytesNestedInt a8,
+    Struct8BytesNestedInt a9) {
+  print(
+      "passStruct8BytesNestedIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct8BytesNestedIntx10 throwing on purpuse!");
+  }
+
+  passStruct8BytesNestedIntx10_a0 = a0;
+  passStruct8BytesNestedIntx10_a1 = a1;
+  passStruct8BytesNestedIntx10_a2 = a2;
+  passStruct8BytesNestedIntx10_a3 = a3;
+  passStruct8BytesNestedIntx10_a4 = a4;
+  passStruct8BytesNestedIntx10_a5 = a5;
+  passStruct8BytesNestedIntx10_a6 = a6;
+  passStruct8BytesNestedIntx10_a7 = a7;
+  passStruct8BytesNestedIntx10_a8 = a8;
+  passStruct8BytesNestedIntx10_a9 = a9;
+
+  final result = passStruct8BytesNestedIntx10CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct8BytesNestedIntx10AfterCallback() {
+  final result = passStruct8BytesNestedIntx10CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(20, result);
+}
+
+typedef PassStruct8BytesNestedFloatx10Type = Float Function(
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a0 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a1 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a2 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a3 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a4 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a5 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a6 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a7 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a8 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a9 =
+    Struct8BytesNestedFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesNestedFloatx10Result = 0.0;
+
+double passStruct8BytesNestedFloatx10CalculateResult() {
+  double result = 0;
+
+  result += passStruct8BytesNestedFloatx10_a0.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a0.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a1.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a1.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a2.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a2.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a3.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a3.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a4.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a4.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a5.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a5.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a6.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a6.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a7.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a7.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a8.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a8.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a9.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a9.a1.a0;
+
+  passStruct8BytesNestedFloatx10Result = result;
+
+  return result;
+}
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust fpu registers on all platforms.
+double passStruct8BytesNestedFloatx10(
+    Struct8BytesNestedFloat a0,
+    Struct8BytesNestedFloat a1,
+    Struct8BytesNestedFloat a2,
+    Struct8BytesNestedFloat a3,
+    Struct8BytesNestedFloat a4,
+    Struct8BytesNestedFloat a5,
+    Struct8BytesNestedFloat a6,
+    Struct8BytesNestedFloat a7,
+    Struct8BytesNestedFloat a8,
+    Struct8BytesNestedFloat a9) {
+  print(
+      "passStruct8BytesNestedFloatx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct8BytesNestedFloatx10 throwing on purpuse!");
+  }
+
+  passStruct8BytesNestedFloatx10_a0 = a0;
+  passStruct8BytesNestedFloatx10_a1 = a1;
+  passStruct8BytesNestedFloatx10_a2 = a2;
+  passStruct8BytesNestedFloatx10_a3 = a3;
+  passStruct8BytesNestedFloatx10_a4 = a4;
+  passStruct8BytesNestedFloatx10_a5 = a5;
+  passStruct8BytesNestedFloatx10_a6 = a6;
+  passStruct8BytesNestedFloatx10_a7 = a7;
+  passStruct8BytesNestedFloatx10_a8 = a8;
+  passStruct8BytesNestedFloatx10_a9 = a9;
+
+  final result = passStruct8BytesNestedFloatx10CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct8BytesNestedFloatx10AfterCallback() {
+  final result = passStruct8BytesNestedFloatx10CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct8BytesNestedFloat2x10Type = Float Function(
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a0 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a1 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a2 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a3 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a4 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a5 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a6 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a7 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a8 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a9 =
+    Struct8BytesNestedFloat2();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesNestedFloat2x10Result = 0.0;
+
+double passStruct8BytesNestedFloat2x10CalculateResult() {
+  double result = 0;
+
+  result += passStruct8BytesNestedFloat2x10_a0.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a0.a1;
+  result += passStruct8BytesNestedFloat2x10_a1.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a1.a1;
+  result += passStruct8BytesNestedFloat2x10_a2.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a2.a1;
+  result += passStruct8BytesNestedFloat2x10_a3.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a3.a1;
+  result += passStruct8BytesNestedFloat2x10_a4.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a4.a1;
+  result += passStruct8BytesNestedFloat2x10_a5.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a5.a1;
+  result += passStruct8BytesNestedFloat2x10_a6.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a6.a1;
+  result += passStruct8BytesNestedFloat2x10_a7.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a7.a1;
+  result += passStruct8BytesNestedFloat2x10_a8.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a8.a1;
+  result += passStruct8BytesNestedFloat2x10_a9.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a9.a1;
+
+  passStruct8BytesNestedFloat2x10Result = result;
+
+  return result;
+}
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust fpu registers on all platforms.
+/// The nesting is irregular, testing homogenous float rules on arm and arm64,
+/// and the fpu register usage on x64.
+double passStruct8BytesNestedFloat2x10(
+    Struct8BytesNestedFloat2 a0,
+    Struct8BytesNestedFloat2 a1,
+    Struct8BytesNestedFloat2 a2,
+    Struct8BytesNestedFloat2 a3,
+    Struct8BytesNestedFloat2 a4,
+    Struct8BytesNestedFloat2 a5,
+    Struct8BytesNestedFloat2 a6,
+    Struct8BytesNestedFloat2 a7,
+    Struct8BytesNestedFloat2 a8,
+    Struct8BytesNestedFloat2 a9) {
+  print(
+      "passStruct8BytesNestedFloat2x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct8BytesNestedFloat2x10 throwing on purpuse!");
+  }
+
+  passStruct8BytesNestedFloat2x10_a0 = a0;
+  passStruct8BytesNestedFloat2x10_a1 = a1;
+  passStruct8BytesNestedFloat2x10_a2 = a2;
+  passStruct8BytesNestedFloat2x10_a3 = a3;
+  passStruct8BytesNestedFloat2x10_a4 = a4;
+  passStruct8BytesNestedFloat2x10_a5 = a5;
+  passStruct8BytesNestedFloat2x10_a6 = a6;
+  passStruct8BytesNestedFloat2x10_a7 = a7;
+  passStruct8BytesNestedFloat2x10_a8 = a8;
+  passStruct8BytesNestedFloat2x10_a9 = a9;
+
+  final result = passStruct8BytesNestedFloat2x10CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct8BytesNestedFloat2x10AfterCallback() {
+  final result = passStruct8BytesNestedFloat2x10CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct8BytesNestedMixedx10Type = Double Function(
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a0 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a1 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a2 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a3 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a4 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a5 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a6 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a7 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a8 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a9 =
+    Struct8BytesNestedMixed();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesNestedMixedx10Result = 0.0;
+
+double passStruct8BytesNestedMixedx10CalculateResult() {
+  double result = 0;
+
+  result += passStruct8BytesNestedMixedx10_a0.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a0.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a0.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a1.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a1.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a1.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a2.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a2.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a2.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a3.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a3.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a3.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a4.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a4.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a4.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a5.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a5.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a5.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a6.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a6.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a6.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a7.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a7.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a7.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a8.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a8.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a8.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a9.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a9.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a9.a1.a0;
+
+  passStruct8BytesNestedMixedx10Result = result;
+
+  return result;
+}
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust all registers on all platforms.
+double passStruct8BytesNestedMixedx10(
+    Struct8BytesNestedMixed a0,
+    Struct8BytesNestedMixed a1,
+    Struct8BytesNestedMixed a2,
+    Struct8BytesNestedMixed a3,
+    Struct8BytesNestedMixed a4,
+    Struct8BytesNestedMixed a5,
+    Struct8BytesNestedMixed a6,
+    Struct8BytesNestedMixed a7,
+    Struct8BytesNestedMixed a8,
+    Struct8BytesNestedMixed a9) {
+  print(
+      "passStruct8BytesNestedMixedx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct8BytesNestedMixedx10 throwing on purpuse!");
+  }
+
+  passStruct8BytesNestedMixedx10_a0 = a0;
+  passStruct8BytesNestedMixedx10_a1 = a1;
+  passStruct8BytesNestedMixedx10_a2 = a2;
+  passStruct8BytesNestedMixedx10_a3 = a3;
+  passStruct8BytesNestedMixedx10_a4 = a4;
+  passStruct8BytesNestedMixedx10_a5 = a5;
+  passStruct8BytesNestedMixedx10_a6 = a6;
+  passStruct8BytesNestedMixedx10_a7 = a7;
+  passStruct8BytesNestedMixedx10_a8 = a8;
+  passStruct8BytesNestedMixedx10_a9 = a9;
+
+  final result = passStruct8BytesNestedMixedx10CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct8BytesNestedMixedx10AfterCallback() {
+  final result = passStruct8BytesNestedMixedx10CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.approxEquals(15.0, result);
+}
+
+typedef PassStruct16BytesNestedIntx2Type = Int64 Function(
+    Struct16BytesNestedInt, Struct16BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesNestedInt passStruct16BytesNestedIntx2_a0 =
+    Struct16BytesNestedInt();
+Struct16BytesNestedInt passStruct16BytesNestedIntx2_a1 =
+    Struct16BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct16BytesNestedIntx2Result = 0;
+
+int passStruct16BytesNestedIntx2CalculateResult() {
+  int result = 0;
+
+  result += passStruct16BytesNestedIntx2_a0.a0.a0.a0;
+  result += passStruct16BytesNestedIntx2_a0.a0.a0.a1;
+  result += passStruct16BytesNestedIntx2_a0.a0.a1.a0;
+  result += passStruct16BytesNestedIntx2_a0.a0.a1.a1;
+  result += passStruct16BytesNestedIntx2_a0.a1.a0.a0;
+  result += passStruct16BytesNestedIntx2_a0.a1.a0.a1;
+  result += passStruct16BytesNestedIntx2_a0.a1.a1.a0;
+  result += passStruct16BytesNestedIntx2_a0.a1.a1.a1;
+  result += passStruct16BytesNestedIntx2_a1.a0.a0.a0;
+  result += passStruct16BytesNestedIntx2_a1.a0.a0.a1;
+  result += passStruct16BytesNestedIntx2_a1.a0.a1.a0;
+  result += passStruct16BytesNestedIntx2_a1.a0.a1.a1;
+  result += passStruct16BytesNestedIntx2_a1.a1.a0.a0;
+  result += passStruct16BytesNestedIntx2_a1.a1.a0.a1;
+  result += passStruct16BytesNestedIntx2_a1.a1.a1.a0;
+  result += passStruct16BytesNestedIntx2_a1.a1.a1.a1;
+
+  passStruct16BytesNestedIntx2Result = result;
+
+  return result;
+}
+
+/// Deeper nested struct to test recursive member access.
+int passStruct16BytesNestedIntx2(
+    Struct16BytesNestedInt a0, Struct16BytesNestedInt a1) {
+  print("passStruct16BytesNestedIntx2(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0.a0 == 42 || a0.a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct16BytesNestedIntx2 throwing on purpuse!");
+  }
+
+  passStruct16BytesNestedIntx2_a0 = a0;
+  passStruct16BytesNestedIntx2_a1 = a1;
+
+  final result = passStruct16BytesNestedIntx2CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct16BytesNestedIntx2AfterCallback() {
+  final result = passStruct16BytesNestedIntx2CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(8, result);
+}
+
+typedef PassStruct32BytesNestedIntx2Type = Int64 Function(
+    Struct32BytesNestedInt, Struct32BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct32BytesNestedInt passStruct32BytesNestedIntx2_a0 =
+    Struct32BytesNestedInt();
+Struct32BytesNestedInt passStruct32BytesNestedIntx2_a1 =
+    Struct32BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct32BytesNestedIntx2Result = 0;
+
+int passStruct32BytesNestedIntx2CalculateResult() {
+  int result = 0;
+
+  result += passStruct32BytesNestedIntx2_a0.a0.a0.a0.a0;
+  result += passStruct32BytesNestedIntx2_a0.a0.a0.a0.a1;
+  result += passStruct32BytesNestedIntx2_a0.a0.a0.a1.a0;
+  result += passStruct32BytesNestedIntx2_a0.a0.a0.a1.a1;
+  result += passStruct32BytesNestedIntx2_a0.a0.a1.a0.a0;
+  result += passStruct32BytesNestedIntx2_a0.a0.a1.a0.a1;
+  result += passStruct32BytesNestedIntx2_a0.a0.a1.a1.a0;
+  result += passStruct32BytesNestedIntx2_a0.a0.a1.a1.a1;
+  result += passStruct32BytesNestedIntx2_a0.a1.a0.a0.a0;
+  result += passStruct32BytesNestedIntx2_a0.a1.a0.a0.a1;
+  result += passStruct32BytesNestedIntx2_a0.a1.a0.a1.a0;
+  result += passStruct32BytesNestedIntx2_a0.a1.a0.a1.a1;
+  result += passStruct32BytesNestedIntx2_a0.a1.a1.a0.a0;
+  result += passStruct32BytesNestedIntx2_a0.a1.a1.a0.a1;
+  result += passStruct32BytesNestedIntx2_a0.a1.a1.a1.a0;
+  result += passStruct32BytesNestedIntx2_a0.a1.a1.a1.a1;
+  result += passStruct32BytesNestedIntx2_a1.a0.a0.a0.a0;
+  result += passStruct32BytesNestedIntx2_a1.a0.a0.a0.a1;
+  result += passStruct32BytesNestedIntx2_a1.a0.a0.a1.a0;
+  result += passStruct32BytesNestedIntx2_a1.a0.a0.a1.a1;
+  result += passStruct32BytesNestedIntx2_a1.a0.a1.a0.a0;
+  result += passStruct32BytesNestedIntx2_a1.a0.a1.a0.a1;
+  result += passStruct32BytesNestedIntx2_a1.a0.a1.a1.a0;
+  result += passStruct32BytesNestedIntx2_a1.a0.a1.a1.a1;
+  result += passStruct32BytesNestedIntx2_a1.a1.a0.a0.a0;
+  result += passStruct32BytesNestedIntx2_a1.a1.a0.a0.a1;
+  result += passStruct32BytesNestedIntx2_a1.a1.a0.a1.a0;
+  result += passStruct32BytesNestedIntx2_a1.a1.a0.a1.a1;
+  result += passStruct32BytesNestedIntx2_a1.a1.a1.a0.a0;
+  result += passStruct32BytesNestedIntx2_a1.a1.a1.a0.a1;
+  result += passStruct32BytesNestedIntx2_a1.a1.a1.a1.a0;
+  result += passStruct32BytesNestedIntx2_a1.a1.a1.a1.a1;
+
+  passStruct32BytesNestedIntx2Result = result;
+
+  return result;
+}
+
+/// Even deeper nested struct to test recursive member access.
+int passStruct32BytesNestedIntx2(
+    Struct32BytesNestedInt a0, Struct32BytesNestedInt a1) {
+  print("passStruct32BytesNestedIntx2(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0.a0.a0 == 42 || a0.a0.a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct32BytesNestedIntx2 throwing on purpuse!");
+  }
+
+  passStruct32BytesNestedIntx2_a0 = a0;
+  passStruct32BytesNestedIntx2_a1 = a1;
+
+  final result = passStruct32BytesNestedIntx2CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct32BytesNestedIntx2AfterCallback() {
+  final result = passStruct32BytesNestedIntx2CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(16, result);
+}
+
+typedef PassStructNestedIntStructAlignmentInt16Type = Int64 Function(
+    StructNestedIntStructAlignmentInt16);
+
+// Global variables to be able to test inputs after callback returned.
+StructNestedIntStructAlignmentInt16 passStructNestedIntStructAlignmentInt16_a0 =
+    StructNestedIntStructAlignmentInt16();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructNestedIntStructAlignmentInt16Result = 0;
+
+int passStructNestedIntStructAlignmentInt16CalculateResult() {
+  int result = 0;
+
+  result += passStructNestedIntStructAlignmentInt16_a0.a0.a0;
+  result += passStructNestedIntStructAlignmentInt16_a0.a0.a1;
+  result += passStructNestedIntStructAlignmentInt16_a0.a0.a2;
+  result += passStructNestedIntStructAlignmentInt16_a0.a1.a0;
+  result += passStructNestedIntStructAlignmentInt16_a0.a1.a1;
+  result += passStructNestedIntStructAlignmentInt16_a0.a1.a2;
+
+  passStructNestedIntStructAlignmentInt16Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 16 byte int.
+int passStructNestedIntStructAlignmentInt16(
+    StructNestedIntStructAlignmentInt16 a0) {
+  print("passStructNestedIntStructAlignmentInt16(${a0})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "PassStructNestedIntStructAlignmentInt16 throwing on purpuse!");
+  }
+
+  passStructNestedIntStructAlignmentInt16_a0 = a0;
+
+  final result = passStructNestedIntStructAlignmentInt16CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStructNestedIntStructAlignmentInt16AfterCallback() {
+  final result = passStructNestedIntStructAlignmentInt16CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(3, result);
+}
+
+typedef PassStructNestedIntStructAlignmentInt32Type = Int64 Function(
+    StructNestedIntStructAlignmentInt32);
+
+// Global variables to be able to test inputs after callback returned.
+StructNestedIntStructAlignmentInt32 passStructNestedIntStructAlignmentInt32_a0 =
+    StructNestedIntStructAlignmentInt32();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructNestedIntStructAlignmentInt32Result = 0;
+
+int passStructNestedIntStructAlignmentInt32CalculateResult() {
+  int result = 0;
+
+  result += passStructNestedIntStructAlignmentInt32_a0.a0.a0;
+  result += passStructNestedIntStructAlignmentInt32_a0.a0.a1;
+  result += passStructNestedIntStructAlignmentInt32_a0.a0.a2;
+  result += passStructNestedIntStructAlignmentInt32_a0.a1.a0;
+  result += passStructNestedIntStructAlignmentInt32_a0.a1.a1;
+  result += passStructNestedIntStructAlignmentInt32_a0.a1.a2;
+
+  passStructNestedIntStructAlignmentInt32Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 32 byte int.
+int passStructNestedIntStructAlignmentInt32(
+    StructNestedIntStructAlignmentInt32 a0) {
+  print("passStructNestedIntStructAlignmentInt32(${a0})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "PassStructNestedIntStructAlignmentInt32 throwing on purpuse!");
+  }
+
+  passStructNestedIntStructAlignmentInt32_a0 = a0;
+
+  final result = passStructNestedIntStructAlignmentInt32CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStructNestedIntStructAlignmentInt32AfterCallback() {
+  final result = passStructNestedIntStructAlignmentInt32CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(3, result);
+}
+
+typedef PassStructNestedIntStructAlignmentInt64Type = Int64 Function(
+    StructNestedIntStructAlignmentInt64);
+
+// Global variables to be able to test inputs after callback returned.
+StructNestedIntStructAlignmentInt64 passStructNestedIntStructAlignmentInt64_a0 =
+    StructNestedIntStructAlignmentInt64();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructNestedIntStructAlignmentInt64Result = 0;
+
+int passStructNestedIntStructAlignmentInt64CalculateResult() {
+  int result = 0;
+
+  result += passStructNestedIntStructAlignmentInt64_a0.a0.a0;
+  result += passStructNestedIntStructAlignmentInt64_a0.a0.a1;
+  result += passStructNestedIntStructAlignmentInt64_a0.a0.a2;
+  result += passStructNestedIntStructAlignmentInt64_a0.a1.a0;
+  result += passStructNestedIntStructAlignmentInt64_a0.a1.a1;
+  result += passStructNestedIntStructAlignmentInt64_a0.a1.a2;
+
+  passStructNestedIntStructAlignmentInt64Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 64 byte int.
+int passStructNestedIntStructAlignmentInt64(
+    StructNestedIntStructAlignmentInt64 a0) {
+  print("passStructNestedIntStructAlignmentInt64(${a0})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "PassStructNestedIntStructAlignmentInt64 throwing on purpuse!");
+  }
+
+  passStructNestedIntStructAlignmentInt64_a0 = a0;
+
+  final result = passStructNestedIntStructAlignmentInt64CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStructNestedIntStructAlignmentInt64AfterCallback() {
+  final result = passStructNestedIntStructAlignmentInt64CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(3, result);
+}
+
+typedef PassStructNestedIrregularEvenBiggerx4Type = Double Function(
+    StructNestedIrregularEvenBigger,
+    StructNestedIrregularEvenBigger,
+    StructNestedIrregularEvenBigger,
+    StructNestedIrregularEvenBigger);
+
+// Global variables to be able to test inputs after callback returned.
+StructNestedIrregularEvenBigger passStructNestedIrregularEvenBiggerx4_a0 =
+    StructNestedIrregularEvenBigger();
+StructNestedIrregularEvenBigger passStructNestedIrregularEvenBiggerx4_a1 =
+    StructNestedIrregularEvenBigger();
+StructNestedIrregularEvenBigger passStructNestedIrregularEvenBiggerx4_a2 =
+    StructNestedIrregularEvenBigger();
+StructNestedIrregularEvenBigger passStructNestedIrregularEvenBiggerx4_a3 =
+    StructNestedIrregularEvenBigger();
+
+// Result variable also global, so we can delete it after the callback.
+double passStructNestedIrregularEvenBiggerx4Result = 0.0;
+
+double passStructNestedIrregularEvenBiggerx4CalculateResult() {
+  double result = 0;
+
+  result += passStructNestedIrregularEvenBiggerx4_a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a3;
+
+  passStructNestedIrregularEvenBiggerx4Result = result;
+
+  return result;
+}
+
+/// Return big irregular struct as smoke test.
+double passStructNestedIrregularEvenBiggerx4(
+    StructNestedIrregularEvenBigger a0,
+    StructNestedIrregularEvenBigger a1,
+    StructNestedIrregularEvenBigger a2,
+    StructNestedIrregularEvenBigger a3) {
+  print("passStructNestedIrregularEvenBiggerx4(${a0}, ${a1}, ${a2}, ${a3})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "PassStructNestedIrregularEvenBiggerx4 throwing on purpuse!");
+  }
+
+  passStructNestedIrregularEvenBiggerx4_a0 = a0;
+  passStructNestedIrregularEvenBiggerx4_a1 = a1;
+  passStructNestedIrregularEvenBiggerx4_a2 = a2;
+  passStructNestedIrregularEvenBiggerx4_a3 = a3;
+
+  final result = passStructNestedIrregularEvenBiggerx4CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStructNestedIrregularEvenBiggerx4AfterCallback() {
+  final result = passStructNestedIrregularEvenBiggerx4CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.approxEquals(1572.0, result);
+}
+
 typedef ReturnStruct1ByteIntType = Struct1ByteInt Function(Int8);
 
 // Global variables to be able to test inputs after callback returned.
@@ -4137,7 +5245,7 @@
 Struct1ByteInt returnStruct1ByteIntResult = Struct1ByteInt();
 
 Struct1ByteInt returnStruct1ByteIntCalculateResult() {
-  Struct1ByteInt result = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt result = calloc<Struct1ByteInt>().ref;
 
   result.a0 = returnStruct1ByteInt_a0;
 
@@ -4168,13 +5276,13 @@
 }
 
 void returnStruct1ByteIntAfterCallback() {
-  free(returnStruct1ByteIntResult.addressOf);
+  calloc.free(returnStruct1ByteIntResult.addressOf);
 
   final result = returnStruct1ByteIntCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct1ByteIntResult.addressOf);
+  calloc.free(returnStruct1ByteIntResult.addressOf);
 }
 
 typedef ReturnStruct3BytesHomogeneousUint8Type = Struct3BytesHomogeneousUint8
@@ -4192,7 +5300,7 @@
 Struct3BytesHomogeneousUint8
     returnStruct3BytesHomogeneousUint8CalculateResult() {
   Struct3BytesHomogeneousUint8 result =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
+      calloc<Struct3BytesHomogeneousUint8>().ref;
 
   result.a0 = returnStruct3BytesHomogeneousUint8_a0;
   result.a1 = returnStruct3BytesHomogeneousUint8_a1;
@@ -4228,13 +5336,13 @@
 }
 
 void returnStruct3BytesHomogeneousUint8AfterCallback() {
-  free(returnStruct3BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct3BytesHomogeneousUint8Result.addressOf);
 
   final result = returnStruct3BytesHomogeneousUint8CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct3BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct3BytesHomogeneousUint8Result.addressOf);
 }
 
 typedef ReturnStruct3BytesInt2ByteAlignedType = Struct3BytesInt2ByteAligned
@@ -4250,7 +5358,7 @@
 
 Struct3BytesInt2ByteAligned returnStruct3BytesInt2ByteAlignedCalculateResult() {
   Struct3BytesInt2ByteAligned result =
-      allocate<Struct3BytesInt2ByteAligned>().ref;
+      calloc<Struct3BytesInt2ByteAligned>().ref;
 
   result.a0 = returnStruct3BytesInt2ByteAligned_a0;
   result.a1 = returnStruct3BytesInt2ByteAligned_a1;
@@ -4284,13 +5392,13 @@
 }
 
 void returnStruct3BytesInt2ByteAlignedAfterCallback() {
-  free(returnStruct3BytesInt2ByteAlignedResult.addressOf);
+  calloc.free(returnStruct3BytesInt2ByteAlignedResult.addressOf);
 
   final result = returnStruct3BytesInt2ByteAlignedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct3BytesInt2ByteAlignedResult.addressOf);
+  calloc.free(returnStruct3BytesInt2ByteAlignedResult.addressOf);
 }
 
 typedef ReturnStruct4BytesHomogeneousInt16Type = Struct4BytesHomogeneousInt16
@@ -4307,7 +5415,7 @@
 Struct4BytesHomogeneousInt16
     returnStruct4BytesHomogeneousInt16CalculateResult() {
   Struct4BytesHomogeneousInt16 result =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
+      calloc<Struct4BytesHomogeneousInt16>().ref;
 
   result.a0 = returnStruct4BytesHomogeneousInt16_a0;
   result.a1 = returnStruct4BytesHomogeneousInt16_a1;
@@ -4341,13 +5449,13 @@
 }
 
 void returnStruct4BytesHomogeneousInt16AfterCallback() {
-  free(returnStruct4BytesHomogeneousInt16Result.addressOf);
+  calloc.free(returnStruct4BytesHomogeneousInt16Result.addressOf);
 
   final result = returnStruct4BytesHomogeneousInt16CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct4BytesHomogeneousInt16Result.addressOf);
+  calloc.free(returnStruct4BytesHomogeneousInt16Result.addressOf);
 }
 
 typedef ReturnStruct7BytesHomogeneousUint8Type = Struct7BytesHomogeneousUint8
@@ -4369,7 +5477,7 @@
 Struct7BytesHomogeneousUint8
     returnStruct7BytesHomogeneousUint8CalculateResult() {
   Struct7BytesHomogeneousUint8 result =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
+      calloc<Struct7BytesHomogeneousUint8>().ref;
 
   result.a0 = returnStruct7BytesHomogeneousUint8_a0;
   result.a1 = returnStruct7BytesHomogeneousUint8_a1;
@@ -4414,13 +5522,13 @@
 }
 
 void returnStruct7BytesHomogeneousUint8AfterCallback() {
-  free(returnStruct7BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct7BytesHomogeneousUint8Result.addressOf);
 
   final result = returnStruct7BytesHomogeneousUint8CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct7BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct7BytesHomogeneousUint8Result.addressOf);
 }
 
 typedef ReturnStruct7BytesInt4ByteAlignedType = Struct7BytesInt4ByteAligned
@@ -4437,7 +5545,7 @@
 
 Struct7BytesInt4ByteAligned returnStruct7BytesInt4ByteAlignedCalculateResult() {
   Struct7BytesInt4ByteAligned result =
-      allocate<Struct7BytesInt4ByteAligned>().ref;
+      calloc<Struct7BytesInt4ByteAligned>().ref;
 
   result.a0 = returnStruct7BytesInt4ByteAligned_a0;
   result.a1 = returnStruct7BytesInt4ByteAligned_a1;
@@ -4474,13 +5582,13 @@
 }
 
 void returnStruct7BytesInt4ByteAlignedAfterCallback() {
-  free(returnStruct7BytesInt4ByteAlignedResult.addressOf);
+  calloc.free(returnStruct7BytesInt4ByteAlignedResult.addressOf);
 
   final result = returnStruct7BytesInt4ByteAlignedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct7BytesInt4ByteAlignedResult.addressOf);
+  calloc.free(returnStruct7BytesInt4ByteAlignedResult.addressOf);
 }
 
 typedef ReturnStruct8BytesIntType = Struct8BytesInt Function(
@@ -4495,7 +5603,7 @@
 Struct8BytesInt returnStruct8BytesIntResult = Struct8BytesInt();
 
 Struct8BytesInt returnStruct8BytesIntCalculateResult() {
-  Struct8BytesInt result = allocate<Struct8BytesInt>().ref;
+  Struct8BytesInt result = calloc<Struct8BytesInt>().ref;
 
   result.a0 = returnStruct8BytesInt_a0;
   result.a1 = returnStruct8BytesInt_a1;
@@ -4530,13 +5638,13 @@
 }
 
 void returnStruct8BytesIntAfterCallback() {
-  free(returnStruct8BytesIntResult.addressOf);
+  calloc.free(returnStruct8BytesIntResult.addressOf);
 
   final result = returnStruct8BytesIntCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct8BytesIntResult.addressOf);
+  calloc.free(returnStruct8BytesIntResult.addressOf);
 }
 
 typedef ReturnStruct8BytesHomogeneousFloatType = Struct8BytesHomogeneousFloat
@@ -4553,7 +5661,7 @@
 Struct8BytesHomogeneousFloat
     returnStruct8BytesHomogeneousFloatCalculateResult() {
   Struct8BytesHomogeneousFloat result =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+      calloc<Struct8BytesHomogeneousFloat>().ref;
 
   result.a0 = returnStruct8BytesHomogeneousFloat_a0;
   result.a1 = returnStruct8BytesHomogeneousFloat_a1;
@@ -4587,13 +5695,13 @@
 }
 
 void returnStruct8BytesHomogeneousFloatAfterCallback() {
-  free(returnStruct8BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct8BytesHomogeneousFloatResult.addressOf);
 
   final result = returnStruct8BytesHomogeneousFloatCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct8BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct8BytesHomogeneousFloatResult.addressOf);
 }
 
 typedef ReturnStruct8BytesMixedType = Struct8BytesMixed Function(
@@ -4608,7 +5716,7 @@
 Struct8BytesMixed returnStruct8BytesMixedResult = Struct8BytesMixed();
 
 Struct8BytesMixed returnStruct8BytesMixedCalculateResult() {
-  Struct8BytesMixed result = allocate<Struct8BytesMixed>().ref;
+  Struct8BytesMixed result = calloc<Struct8BytesMixed>().ref;
 
   result.a0 = returnStruct8BytesMixed_a0;
   result.a1 = returnStruct8BytesMixed_a1;
@@ -4643,13 +5751,13 @@
 }
 
 void returnStruct8BytesMixedAfterCallback() {
-  free(returnStruct8BytesMixedResult.addressOf);
+  calloc.free(returnStruct8BytesMixedResult.addressOf);
 
   final result = returnStruct8BytesMixedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct8BytesMixedResult.addressOf);
+  calloc.free(returnStruct8BytesMixedResult.addressOf);
 }
 
 typedef ReturnStruct9BytesHomogeneousUint8Type = Struct9BytesHomogeneousUint8
@@ -4673,7 +5781,7 @@
 Struct9BytesHomogeneousUint8
     returnStruct9BytesHomogeneousUint8CalculateResult() {
   Struct9BytesHomogeneousUint8 result =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
+      calloc<Struct9BytesHomogeneousUint8>().ref;
 
   result.a0 = returnStruct9BytesHomogeneousUint8_a0;
   result.a1 = returnStruct9BytesHomogeneousUint8_a1;
@@ -4724,13 +5832,13 @@
 }
 
 void returnStruct9BytesHomogeneousUint8AfterCallback() {
-  free(returnStruct9BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct9BytesHomogeneousUint8Result.addressOf);
 
   final result = returnStruct9BytesHomogeneousUint8CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct9BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct9BytesHomogeneousUint8Result.addressOf);
 }
 
 typedef ReturnStruct9BytesInt4Or8ByteAlignedType
@@ -4747,7 +5855,7 @@
 Struct9BytesInt4Or8ByteAligned
     returnStruct9BytesInt4Or8ByteAlignedCalculateResult() {
   Struct9BytesInt4Or8ByteAligned result =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
 
   result.a0 = returnStruct9BytesInt4Or8ByteAligned_a0;
   result.a1 = returnStruct9BytesInt4Or8ByteAligned_a1;
@@ -4783,13 +5891,13 @@
 }
 
 void returnStruct9BytesInt4Or8ByteAlignedAfterCallback() {
-  free(returnStruct9BytesInt4Or8ByteAlignedResult.addressOf);
+  calloc.free(returnStruct9BytesInt4Or8ByteAlignedResult.addressOf);
 
   final result = returnStruct9BytesInt4Or8ByteAlignedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct9BytesInt4Or8ByteAlignedResult.addressOf);
+  calloc.free(returnStruct9BytesInt4Or8ByteAlignedResult.addressOf);
 }
 
 typedef ReturnStruct12BytesHomogeneousFloatType = Struct12BytesHomogeneousFloat
@@ -4807,7 +5915,7 @@
 Struct12BytesHomogeneousFloat
     returnStruct12BytesHomogeneousFloatCalculateResult() {
   Struct12BytesHomogeneousFloat result =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
 
   result.a0 = returnStruct12BytesHomogeneousFloat_a0;
   result.a1 = returnStruct12BytesHomogeneousFloat_a1;
@@ -4844,13 +5952,13 @@
 }
 
 void returnStruct12BytesHomogeneousFloatAfterCallback() {
-  free(returnStruct12BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct12BytesHomogeneousFloatResult.addressOf);
 
   final result = returnStruct12BytesHomogeneousFloatCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct12BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct12BytesHomogeneousFloatResult.addressOf);
 }
 
 typedef ReturnStruct16BytesHomogeneousFloatType = Struct16BytesHomogeneousFloat
@@ -4869,7 +5977,7 @@
 Struct16BytesHomogeneousFloat
     returnStruct16BytesHomogeneousFloatCalculateResult() {
   Struct16BytesHomogeneousFloat result =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
 
   result.a0 = returnStruct16BytesHomogeneousFloat_a0;
   result.a1 = returnStruct16BytesHomogeneousFloat_a1;
@@ -4907,13 +6015,13 @@
 }
 
 void returnStruct16BytesHomogeneousFloatAfterCallback() {
-  free(returnStruct16BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct16BytesHomogeneousFloatResult.addressOf);
 
   final result = returnStruct16BytesHomogeneousFloatCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct16BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct16BytesHomogeneousFloatResult.addressOf);
 }
 
 typedef ReturnStruct16BytesMixedType = Struct16BytesMixed Function(
@@ -4927,7 +6035,7 @@
 Struct16BytesMixed returnStruct16BytesMixedResult = Struct16BytesMixed();
 
 Struct16BytesMixed returnStruct16BytesMixedCalculateResult() {
-  Struct16BytesMixed result = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed result = calloc<Struct16BytesMixed>().ref;
 
   result.a0 = returnStruct16BytesMixed_a0;
   result.a1 = returnStruct16BytesMixed_a1;
@@ -4960,13 +6068,13 @@
 }
 
 void returnStruct16BytesMixedAfterCallback() {
-  free(returnStruct16BytesMixedResult.addressOf);
+  calloc.free(returnStruct16BytesMixedResult.addressOf);
 
   final result = returnStruct16BytesMixedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct16BytesMixedResult.addressOf);
+  calloc.free(returnStruct16BytesMixedResult.addressOf);
 }
 
 typedef ReturnStruct16BytesMixed2Type = Struct16BytesMixed2 Function(
@@ -4982,7 +6090,7 @@
 Struct16BytesMixed2 returnStruct16BytesMixed2Result = Struct16BytesMixed2();
 
 Struct16BytesMixed2 returnStruct16BytesMixed2CalculateResult() {
-  Struct16BytesMixed2 result = allocate<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 result = calloc<Struct16BytesMixed2>().ref;
 
   result.a0 = returnStruct16BytesMixed2_a0;
   result.a1 = returnStruct16BytesMixed2_a1;
@@ -5021,13 +6129,13 @@
 }
 
 void returnStruct16BytesMixed2AfterCallback() {
-  free(returnStruct16BytesMixed2Result.addressOf);
+  calloc.free(returnStruct16BytesMixed2Result.addressOf);
 
   final result = returnStruct16BytesMixed2CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct16BytesMixed2Result.addressOf);
+  calloc.free(returnStruct16BytesMixed2Result.addressOf);
 }
 
 typedef ReturnStruct17BytesIntType = Struct17BytesInt Function(
@@ -5042,7 +6150,7 @@
 Struct17BytesInt returnStruct17BytesIntResult = Struct17BytesInt();
 
 Struct17BytesInt returnStruct17BytesIntCalculateResult() {
-  Struct17BytesInt result = allocate<Struct17BytesInt>().ref;
+  Struct17BytesInt result = calloc<Struct17BytesInt>().ref;
 
   result.a0 = returnStruct17BytesInt_a0;
   result.a1 = returnStruct17BytesInt_a1;
@@ -5079,13 +6187,13 @@
 }
 
 void returnStruct17BytesIntAfterCallback() {
-  free(returnStruct17BytesIntResult.addressOf);
+  calloc.free(returnStruct17BytesIntResult.addressOf);
 
   final result = returnStruct17BytesIntCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct17BytesIntResult.addressOf);
+  calloc.free(returnStruct17BytesIntResult.addressOf);
 }
 
 typedef ReturnStruct19BytesHomogeneousUint8Type
@@ -5138,7 +6246,7 @@
 Struct19BytesHomogeneousUint8
     returnStruct19BytesHomogeneousUint8CalculateResult() {
   Struct19BytesHomogeneousUint8 result =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
 
   result.a0 = returnStruct19BytesHomogeneousUint8_a0;
   result.a1 = returnStruct19BytesHomogeneousUint8_a1;
@@ -5227,13 +6335,13 @@
 }
 
 void returnStruct19BytesHomogeneousUint8AfterCallback() {
-  free(returnStruct19BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct19BytesHomogeneousUint8Result.addressOf);
 
   final result = returnStruct19BytesHomogeneousUint8CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct19BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct19BytesHomogeneousUint8Result.addressOf);
 }
 
 typedef ReturnStruct20BytesHomogeneousInt32Type = Struct20BytesHomogeneousInt32
@@ -5253,7 +6361,7 @@
 Struct20BytesHomogeneousInt32
     returnStruct20BytesHomogeneousInt32CalculateResult() {
   Struct20BytesHomogeneousInt32 result =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
 
   result.a0 = returnStruct20BytesHomogeneousInt32_a0;
   result.a1 = returnStruct20BytesHomogeneousInt32_a1;
@@ -5294,13 +6402,13 @@
 }
 
 void returnStruct20BytesHomogeneousInt32AfterCallback() {
-  free(returnStruct20BytesHomogeneousInt32Result.addressOf);
+  calloc.free(returnStruct20BytesHomogeneousInt32Result.addressOf);
 
   final result = returnStruct20BytesHomogeneousInt32CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct20BytesHomogeneousInt32Result.addressOf);
+  calloc.free(returnStruct20BytesHomogeneousInt32Result.addressOf);
 }
 
 typedef ReturnStruct20BytesHomogeneousFloatType = Struct20BytesHomogeneousFloat
@@ -5320,7 +6428,7 @@
 Struct20BytesHomogeneousFloat
     returnStruct20BytesHomogeneousFloatCalculateResult() {
   Struct20BytesHomogeneousFloat result =
-      allocate<Struct20BytesHomogeneousFloat>().ref;
+      calloc<Struct20BytesHomogeneousFloat>().ref;
 
   result.a0 = returnStruct20BytesHomogeneousFloat_a0;
   result.a1 = returnStruct20BytesHomogeneousFloat_a1;
@@ -5361,13 +6469,13 @@
 }
 
 void returnStruct20BytesHomogeneousFloatAfterCallback() {
-  free(returnStruct20BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct20BytesHomogeneousFloatResult.addressOf);
 
   final result = returnStruct20BytesHomogeneousFloatCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct20BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct20BytesHomogeneousFloatResult.addressOf);
 }
 
 typedef ReturnStruct32BytesHomogeneousDoubleType
@@ -5386,7 +6494,7 @@
 Struct32BytesHomogeneousDouble
     returnStruct32BytesHomogeneousDoubleCalculateResult() {
   Struct32BytesHomogeneousDouble result =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
 
   result.a0 = returnStruct32BytesHomogeneousDouble_a0;
   result.a1 = returnStruct32BytesHomogeneousDouble_a1;
@@ -5425,13 +6533,13 @@
 }
 
 void returnStruct32BytesHomogeneousDoubleAfterCallback() {
-  free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
+  calloc.free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
 
   final result = returnStruct32BytesHomogeneousDoubleCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
+  calloc.free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
 }
 
 typedef ReturnStruct40BytesHomogeneousDoubleType
@@ -5452,7 +6560,7 @@
 Struct40BytesHomogeneousDouble
     returnStruct40BytesHomogeneousDoubleCalculateResult() {
   Struct40BytesHomogeneousDouble result =
-      allocate<Struct40BytesHomogeneousDouble>().ref;
+      calloc<Struct40BytesHomogeneousDouble>().ref;
 
   result.a0 = returnStruct40BytesHomogeneousDouble_a0;
   result.a1 = returnStruct40BytesHomogeneousDouble_a1;
@@ -5494,13 +6602,13 @@
 }
 
 void returnStruct40BytesHomogeneousDoubleAfterCallback() {
-  free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
+  calloc.free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
 
   final result = returnStruct40BytesHomogeneousDoubleCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
+  calloc.free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
 }
 
 typedef ReturnStruct1024BytesHomogeneousUint64Type
@@ -5771,7 +6879,7 @@
 Struct1024BytesHomogeneousUint64
     returnStruct1024BytesHomogeneousUint64CalculateResult() {
   Struct1024BytesHomogeneousUint64 result =
-      allocate<Struct1024BytesHomogeneousUint64>().ref;
+      calloc<Struct1024BytesHomogeneousUint64>().ref;
 
   result.a0 = returnStruct1024BytesHomogeneousUint64_a0;
   result.a1 = returnStruct1024BytesHomogeneousUint64_a1;
@@ -6186,13 +7294,13 @@
 }
 
 void returnStruct1024BytesHomogeneousUint64AfterCallback() {
-  free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
+  calloc.free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
 
   final result = returnStruct1024BytesHomogeneousUint64CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
+  calloc.free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
 }
 
 typedef ReturnStructArgumentStruct1ByteIntType = Struct1ByteInt Function(
@@ -6511,7 +7619,7 @@
 StructAlignmentInt16 returnStructAlignmentInt16Result = StructAlignmentInt16();
 
 StructAlignmentInt16 returnStructAlignmentInt16CalculateResult() {
-  StructAlignmentInt16 result = allocate<StructAlignmentInt16>().ref;
+  StructAlignmentInt16 result = calloc<StructAlignmentInt16>().ref;
 
   result.a0 = returnStructAlignmentInt16_a0;
   result.a1 = returnStructAlignmentInt16_a1;
@@ -6546,13 +7654,13 @@
 }
 
 void returnStructAlignmentInt16AfterCallback() {
-  free(returnStructAlignmentInt16Result.addressOf);
+  calloc.free(returnStructAlignmentInt16Result.addressOf);
 
   final result = returnStructAlignmentInt16CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStructAlignmentInt16Result.addressOf);
+  calloc.free(returnStructAlignmentInt16Result.addressOf);
 }
 
 typedef ReturnStructAlignmentInt32Type = StructAlignmentInt32 Function(
@@ -6567,7 +7675,7 @@
 StructAlignmentInt32 returnStructAlignmentInt32Result = StructAlignmentInt32();
 
 StructAlignmentInt32 returnStructAlignmentInt32CalculateResult() {
-  StructAlignmentInt32 result = allocate<StructAlignmentInt32>().ref;
+  StructAlignmentInt32 result = calloc<StructAlignmentInt32>().ref;
 
   result.a0 = returnStructAlignmentInt32_a0;
   result.a1 = returnStructAlignmentInt32_a1;
@@ -6602,13 +7710,13 @@
 }
 
 void returnStructAlignmentInt32AfterCallback() {
-  free(returnStructAlignmentInt32Result.addressOf);
+  calloc.free(returnStructAlignmentInt32Result.addressOf);
 
   final result = returnStructAlignmentInt32CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStructAlignmentInt32Result.addressOf);
+  calloc.free(returnStructAlignmentInt32Result.addressOf);
 }
 
 typedef ReturnStructAlignmentInt64Type = StructAlignmentInt64 Function(
@@ -6623,7 +7731,7 @@
 StructAlignmentInt64 returnStructAlignmentInt64Result = StructAlignmentInt64();
 
 StructAlignmentInt64 returnStructAlignmentInt64CalculateResult() {
-  StructAlignmentInt64 result = allocate<StructAlignmentInt64>().ref;
+  StructAlignmentInt64 result = calloc<StructAlignmentInt64>().ref;
 
   result.a0 = returnStructAlignmentInt64_a0;
   result.a1 = returnStructAlignmentInt64_a1;
@@ -6658,11 +7766,665 @@
 }
 
 void returnStructAlignmentInt64AfterCallback() {
-  free(returnStructAlignmentInt64Result.addressOf);
+  calloc.free(returnStructAlignmentInt64Result.addressOf);
 
   final result = returnStructAlignmentInt64CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStructAlignmentInt64Result.addressOf);
+  calloc.free(returnStructAlignmentInt64Result.addressOf);
+}
+
+typedef ReturnStruct8BytesNestedIntType = Struct8BytesNestedInt Function(
+    Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesHomogeneousInt16 returnStruct8BytesNestedInt_a0 =
+    Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 returnStruct8BytesNestedInt_a1 =
+    Struct4BytesHomogeneousInt16();
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesNestedInt returnStruct8BytesNestedIntResult =
+    Struct8BytesNestedInt();
+
+Struct8BytesNestedInt returnStruct8BytesNestedIntCalculateResult() {
+  Struct8BytesNestedInt result = calloc<Struct8BytesNestedInt>().ref;
+
+  result.a0.a0 = returnStruct8BytesNestedInt_a0.a0;
+  result.a0.a1 = returnStruct8BytesNestedInt_a0.a1;
+  result.a1.a0 = returnStruct8BytesNestedInt_a1.a0;
+  result.a1.a1 = returnStruct8BytesNestedInt_a1.a1;
+
+  returnStruct8BytesNestedIntResult = result;
+
+  return result;
+}
+
+/// Simple nested struct.
+Struct8BytesNestedInt returnStruct8BytesNestedInt(
+    Struct4BytesHomogeneousInt16 a0, Struct4BytesHomogeneousInt16 a1) {
+  print("returnStruct8BytesNestedInt(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct8BytesNestedInt throwing on purpuse!");
+  }
+
+  returnStruct8BytesNestedInt_a0 = a0;
+  returnStruct8BytesNestedInt_a1 = a1;
+
+  final result = returnStruct8BytesNestedIntCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct8BytesNestedIntAfterCallback() {
+  calloc.free(returnStruct8BytesNestedIntResult.addressOf);
+
+  final result = returnStruct8BytesNestedIntCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct8BytesNestedIntResult.addressOf);
+}
+
+typedef ReturnStruct8BytesNestedFloatType = Struct8BytesNestedFloat Function(
+    Struct4BytesFloat, Struct4BytesFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesFloat returnStruct8BytesNestedFloat_a0 = Struct4BytesFloat();
+Struct4BytesFloat returnStruct8BytesNestedFloat_a1 = Struct4BytesFloat();
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesNestedFloat returnStruct8BytesNestedFloatResult =
+    Struct8BytesNestedFloat();
+
+Struct8BytesNestedFloat returnStruct8BytesNestedFloatCalculateResult() {
+  Struct8BytesNestedFloat result = calloc<Struct8BytesNestedFloat>().ref;
+
+  result.a0.a0 = returnStruct8BytesNestedFloat_a0.a0;
+  result.a1.a0 = returnStruct8BytesNestedFloat_a1.a0;
+
+  returnStruct8BytesNestedFloatResult = result;
+
+  return result;
+}
+
+/// Simple nested struct with floats.
+Struct8BytesNestedFloat returnStruct8BytesNestedFloat(
+    Struct4BytesFloat a0, Struct4BytesFloat a1) {
+  print("returnStruct8BytesNestedFloat(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct8BytesNestedFloat throwing on purpuse!");
+  }
+
+  returnStruct8BytesNestedFloat_a0 = a0;
+  returnStruct8BytesNestedFloat_a1 = a1;
+
+  final result = returnStruct8BytesNestedFloatCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct8BytesNestedFloatAfterCallback() {
+  calloc.free(returnStruct8BytesNestedFloatResult.addressOf);
+
+  final result = returnStruct8BytesNestedFloatCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct8BytesNestedFloatResult.addressOf);
+}
+
+typedef ReturnStruct8BytesNestedFloat2Type = Struct8BytesNestedFloat2 Function(
+    Struct4BytesFloat, Float);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesFloat returnStruct8BytesNestedFloat2_a0 = Struct4BytesFloat();
+double returnStruct8BytesNestedFloat2_a1 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesNestedFloat2 returnStruct8BytesNestedFloat2Result =
+    Struct8BytesNestedFloat2();
+
+Struct8BytesNestedFloat2 returnStruct8BytesNestedFloat2CalculateResult() {
+  Struct8BytesNestedFloat2 result = calloc<Struct8BytesNestedFloat2>().ref;
+
+  result.a0.a0 = returnStruct8BytesNestedFloat2_a0.a0;
+  result.a1 = returnStruct8BytesNestedFloat2_a1;
+
+  returnStruct8BytesNestedFloat2Result = result;
+
+  return result;
+}
+
+/// The nesting is irregular, testing homogenous float rules on arm and arm64,
+/// and the fpu register usage on x64.
+Struct8BytesNestedFloat2 returnStruct8BytesNestedFloat2(
+    Struct4BytesFloat a0, double a1) {
+  print("returnStruct8BytesNestedFloat2(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct8BytesNestedFloat2 throwing on purpuse!");
+  }
+
+  returnStruct8BytesNestedFloat2_a0 = a0;
+  returnStruct8BytesNestedFloat2_a1 = a1;
+
+  final result = returnStruct8BytesNestedFloat2CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct8BytesNestedFloat2AfterCallback() {
+  calloc.free(returnStruct8BytesNestedFloat2Result.addressOf);
+
+  final result = returnStruct8BytesNestedFloat2CalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct8BytesNestedFloat2Result.addressOf);
+}
+
+typedef ReturnStruct8BytesNestedMixedType = Struct8BytesNestedMixed Function(
+    Struct4BytesHomogeneousInt16, Struct4BytesFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesHomogeneousInt16 returnStruct8BytesNestedMixed_a0 =
+    Struct4BytesHomogeneousInt16();
+Struct4BytesFloat returnStruct8BytesNestedMixed_a1 = Struct4BytesFloat();
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesNestedMixed returnStruct8BytesNestedMixedResult =
+    Struct8BytesNestedMixed();
+
+Struct8BytesNestedMixed returnStruct8BytesNestedMixedCalculateResult() {
+  Struct8BytesNestedMixed result = calloc<Struct8BytesNestedMixed>().ref;
+
+  result.a0.a0 = returnStruct8BytesNestedMixed_a0.a0;
+  result.a0.a1 = returnStruct8BytesNestedMixed_a0.a1;
+  result.a1.a0 = returnStruct8BytesNestedMixed_a1.a0;
+
+  returnStruct8BytesNestedMixedResult = result;
+
+  return result;
+}
+
+/// Simple nested struct with mixed members.
+Struct8BytesNestedMixed returnStruct8BytesNestedMixed(
+    Struct4BytesHomogeneousInt16 a0, Struct4BytesFloat a1) {
+  print("returnStruct8BytesNestedMixed(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct8BytesNestedMixed throwing on purpuse!");
+  }
+
+  returnStruct8BytesNestedMixed_a0 = a0;
+  returnStruct8BytesNestedMixed_a1 = a1;
+
+  final result = returnStruct8BytesNestedMixedCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct8BytesNestedMixedAfterCallback() {
+  calloc.free(returnStruct8BytesNestedMixedResult.addressOf);
+
+  final result = returnStruct8BytesNestedMixedCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct8BytesNestedMixedResult.addressOf);
+}
+
+typedef ReturnStruct16BytesNestedIntType = Struct16BytesNestedInt Function(
+    Struct8BytesNestedInt, Struct8BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedInt returnStruct16BytesNestedInt_a0 = Struct8BytesNestedInt();
+Struct8BytesNestedInt returnStruct16BytesNestedInt_a1 = Struct8BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+Struct16BytesNestedInt returnStruct16BytesNestedIntResult =
+    Struct16BytesNestedInt();
+
+Struct16BytesNestedInt returnStruct16BytesNestedIntCalculateResult() {
+  Struct16BytesNestedInt result = calloc<Struct16BytesNestedInt>().ref;
+
+  result.a0.a0.a0 = returnStruct16BytesNestedInt_a0.a0.a0;
+  result.a0.a0.a1 = returnStruct16BytesNestedInt_a0.a0.a1;
+  result.a0.a1.a0 = returnStruct16BytesNestedInt_a0.a1.a0;
+  result.a0.a1.a1 = returnStruct16BytesNestedInt_a0.a1.a1;
+  result.a1.a0.a0 = returnStruct16BytesNestedInt_a1.a0.a0;
+  result.a1.a0.a1 = returnStruct16BytesNestedInt_a1.a0.a1;
+  result.a1.a1.a0 = returnStruct16BytesNestedInt_a1.a1.a0;
+  result.a1.a1.a1 = returnStruct16BytesNestedInt_a1.a1.a1;
+
+  returnStruct16BytesNestedIntResult = result;
+
+  return result;
+}
+
+/// Deeper nested struct to test recursive member access.
+Struct16BytesNestedInt returnStruct16BytesNestedInt(
+    Struct8BytesNestedInt a0, Struct8BytesNestedInt a1) {
+  print("returnStruct16BytesNestedInt(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct16BytesNestedInt throwing on purpuse!");
+  }
+
+  returnStruct16BytesNestedInt_a0 = a0;
+  returnStruct16BytesNestedInt_a1 = a1;
+
+  final result = returnStruct16BytesNestedIntCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct16BytesNestedIntAfterCallback() {
+  calloc.free(returnStruct16BytesNestedIntResult.addressOf);
+
+  final result = returnStruct16BytesNestedIntCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct16BytesNestedIntResult.addressOf);
+}
+
+typedef ReturnStruct32BytesNestedIntType = Struct32BytesNestedInt Function(
+    Struct16BytesNestedInt, Struct16BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesNestedInt returnStruct32BytesNestedInt_a0 =
+    Struct16BytesNestedInt();
+Struct16BytesNestedInt returnStruct32BytesNestedInt_a1 =
+    Struct16BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+Struct32BytesNestedInt returnStruct32BytesNestedIntResult =
+    Struct32BytesNestedInt();
+
+Struct32BytesNestedInt returnStruct32BytesNestedIntCalculateResult() {
+  Struct32BytesNestedInt result = calloc<Struct32BytesNestedInt>().ref;
+
+  result.a0.a0.a0.a0 = returnStruct32BytesNestedInt_a0.a0.a0.a0;
+  result.a0.a0.a0.a1 = returnStruct32BytesNestedInt_a0.a0.a0.a1;
+  result.a0.a0.a1.a0 = returnStruct32BytesNestedInt_a0.a0.a1.a0;
+  result.a0.a0.a1.a1 = returnStruct32BytesNestedInt_a0.a0.a1.a1;
+  result.a0.a1.a0.a0 = returnStruct32BytesNestedInt_a0.a1.a0.a0;
+  result.a0.a1.a0.a1 = returnStruct32BytesNestedInt_a0.a1.a0.a1;
+  result.a0.a1.a1.a0 = returnStruct32BytesNestedInt_a0.a1.a1.a0;
+  result.a0.a1.a1.a1 = returnStruct32BytesNestedInt_a0.a1.a1.a1;
+  result.a1.a0.a0.a0 = returnStruct32BytesNestedInt_a1.a0.a0.a0;
+  result.a1.a0.a0.a1 = returnStruct32BytesNestedInt_a1.a0.a0.a1;
+  result.a1.a0.a1.a0 = returnStruct32BytesNestedInt_a1.a0.a1.a0;
+  result.a1.a0.a1.a1 = returnStruct32BytesNestedInt_a1.a0.a1.a1;
+  result.a1.a1.a0.a0 = returnStruct32BytesNestedInt_a1.a1.a0.a0;
+  result.a1.a1.a0.a1 = returnStruct32BytesNestedInt_a1.a1.a0.a1;
+  result.a1.a1.a1.a0 = returnStruct32BytesNestedInt_a1.a1.a1.a0;
+  result.a1.a1.a1.a1 = returnStruct32BytesNestedInt_a1.a1.a1.a1;
+
+  returnStruct32BytesNestedIntResult = result;
+
+  return result;
+}
+
+/// Even deeper nested struct to test recursive member access.
+Struct32BytesNestedInt returnStruct32BytesNestedInt(
+    Struct16BytesNestedInt a0, Struct16BytesNestedInt a1) {
+  print("returnStruct32BytesNestedInt(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0.a0 == 42 || a0.a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct32BytesNestedInt throwing on purpuse!");
+  }
+
+  returnStruct32BytesNestedInt_a0 = a0;
+  returnStruct32BytesNestedInt_a1 = a1;
+
+  final result = returnStruct32BytesNestedIntCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct32BytesNestedIntAfterCallback() {
+  calloc.free(returnStruct32BytesNestedIntResult.addressOf);
+
+  final result = returnStruct32BytesNestedIntCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct32BytesNestedIntResult.addressOf);
+}
+
+typedef ReturnStructNestedIntStructAlignmentInt16Type
+    = StructNestedIntStructAlignmentInt16 Function(
+        StructAlignmentInt16, StructAlignmentInt16);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt16 returnStructNestedIntStructAlignmentInt16_a0 =
+    StructAlignmentInt16();
+StructAlignmentInt16 returnStructNestedIntStructAlignmentInt16_a1 =
+    StructAlignmentInt16();
+
+// Result variable also global, so we can delete it after the callback.
+StructNestedIntStructAlignmentInt16
+    returnStructNestedIntStructAlignmentInt16Result =
+    StructNestedIntStructAlignmentInt16();
+
+StructNestedIntStructAlignmentInt16
+    returnStructNestedIntStructAlignmentInt16CalculateResult() {
+  StructNestedIntStructAlignmentInt16 result =
+      calloc<StructNestedIntStructAlignmentInt16>().ref;
+
+  result.a0.a0 = returnStructNestedIntStructAlignmentInt16_a0.a0;
+  result.a0.a1 = returnStructNestedIntStructAlignmentInt16_a0.a1;
+  result.a0.a2 = returnStructNestedIntStructAlignmentInt16_a0.a2;
+  result.a1.a0 = returnStructNestedIntStructAlignmentInt16_a1.a0;
+  result.a1.a1 = returnStructNestedIntStructAlignmentInt16_a1.a1;
+  result.a1.a2 = returnStructNestedIntStructAlignmentInt16_a1.a2;
+
+  returnStructNestedIntStructAlignmentInt16Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 16 byte int.
+StructNestedIntStructAlignmentInt16 returnStructNestedIntStructAlignmentInt16(
+    StructAlignmentInt16 a0, StructAlignmentInt16 a1) {
+  print("returnStructNestedIntStructAlignmentInt16(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "ReturnStructNestedIntStructAlignmentInt16 throwing on purpuse!");
+  }
+
+  returnStructNestedIntStructAlignmentInt16_a0 = a0;
+  returnStructNestedIntStructAlignmentInt16_a1 = a1;
+
+  final result = returnStructNestedIntStructAlignmentInt16CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStructNestedIntStructAlignmentInt16AfterCallback() {
+  calloc.free(returnStructNestedIntStructAlignmentInt16Result.addressOf);
+
+  final result = returnStructNestedIntStructAlignmentInt16CalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStructNestedIntStructAlignmentInt16Result.addressOf);
+}
+
+typedef ReturnStructNestedIntStructAlignmentInt32Type
+    = StructNestedIntStructAlignmentInt32 Function(
+        StructAlignmentInt32, StructAlignmentInt32);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt32 returnStructNestedIntStructAlignmentInt32_a0 =
+    StructAlignmentInt32();
+StructAlignmentInt32 returnStructNestedIntStructAlignmentInt32_a1 =
+    StructAlignmentInt32();
+
+// Result variable also global, so we can delete it after the callback.
+StructNestedIntStructAlignmentInt32
+    returnStructNestedIntStructAlignmentInt32Result =
+    StructNestedIntStructAlignmentInt32();
+
+StructNestedIntStructAlignmentInt32
+    returnStructNestedIntStructAlignmentInt32CalculateResult() {
+  StructNestedIntStructAlignmentInt32 result =
+      calloc<StructNestedIntStructAlignmentInt32>().ref;
+
+  result.a0.a0 = returnStructNestedIntStructAlignmentInt32_a0.a0;
+  result.a0.a1 = returnStructNestedIntStructAlignmentInt32_a0.a1;
+  result.a0.a2 = returnStructNestedIntStructAlignmentInt32_a0.a2;
+  result.a1.a0 = returnStructNestedIntStructAlignmentInt32_a1.a0;
+  result.a1.a1 = returnStructNestedIntStructAlignmentInt32_a1.a1;
+  result.a1.a2 = returnStructNestedIntStructAlignmentInt32_a1.a2;
+
+  returnStructNestedIntStructAlignmentInt32Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 32 byte int.
+StructNestedIntStructAlignmentInt32 returnStructNestedIntStructAlignmentInt32(
+    StructAlignmentInt32 a0, StructAlignmentInt32 a1) {
+  print("returnStructNestedIntStructAlignmentInt32(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "ReturnStructNestedIntStructAlignmentInt32 throwing on purpuse!");
+  }
+
+  returnStructNestedIntStructAlignmentInt32_a0 = a0;
+  returnStructNestedIntStructAlignmentInt32_a1 = a1;
+
+  final result = returnStructNestedIntStructAlignmentInt32CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStructNestedIntStructAlignmentInt32AfterCallback() {
+  calloc.free(returnStructNestedIntStructAlignmentInt32Result.addressOf);
+
+  final result = returnStructNestedIntStructAlignmentInt32CalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStructNestedIntStructAlignmentInt32Result.addressOf);
+}
+
+typedef ReturnStructNestedIntStructAlignmentInt64Type
+    = StructNestedIntStructAlignmentInt64 Function(
+        StructAlignmentInt64, StructAlignmentInt64);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt64 returnStructNestedIntStructAlignmentInt64_a0 =
+    StructAlignmentInt64();
+StructAlignmentInt64 returnStructNestedIntStructAlignmentInt64_a1 =
+    StructAlignmentInt64();
+
+// Result variable also global, so we can delete it after the callback.
+StructNestedIntStructAlignmentInt64
+    returnStructNestedIntStructAlignmentInt64Result =
+    StructNestedIntStructAlignmentInt64();
+
+StructNestedIntStructAlignmentInt64
+    returnStructNestedIntStructAlignmentInt64CalculateResult() {
+  StructNestedIntStructAlignmentInt64 result =
+      calloc<StructNestedIntStructAlignmentInt64>().ref;
+
+  result.a0.a0 = returnStructNestedIntStructAlignmentInt64_a0.a0;
+  result.a0.a1 = returnStructNestedIntStructAlignmentInt64_a0.a1;
+  result.a0.a2 = returnStructNestedIntStructAlignmentInt64_a0.a2;
+  result.a1.a0 = returnStructNestedIntStructAlignmentInt64_a1.a0;
+  result.a1.a1 = returnStructNestedIntStructAlignmentInt64_a1.a1;
+  result.a1.a2 = returnStructNestedIntStructAlignmentInt64_a1.a2;
+
+  returnStructNestedIntStructAlignmentInt64Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 64 byte int.
+StructNestedIntStructAlignmentInt64 returnStructNestedIntStructAlignmentInt64(
+    StructAlignmentInt64 a0, StructAlignmentInt64 a1) {
+  print("returnStructNestedIntStructAlignmentInt64(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "ReturnStructNestedIntStructAlignmentInt64 throwing on purpuse!");
+  }
+
+  returnStructNestedIntStructAlignmentInt64_a0 = a0;
+  returnStructNestedIntStructAlignmentInt64_a1 = a1;
+
+  final result = returnStructNestedIntStructAlignmentInt64CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStructNestedIntStructAlignmentInt64AfterCallback() {
+  calloc.free(returnStructNestedIntStructAlignmentInt64Result.addressOf);
+
+  final result = returnStructNestedIntStructAlignmentInt64CalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStructNestedIntStructAlignmentInt64Result.addressOf);
+}
+
+typedef ReturnStructNestedIrregularEvenBiggerType
+    = StructNestedIrregularEvenBigger Function(Uint64,
+        StructNestedIrregularBigger, StructNestedIrregularBigger, Double);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructNestedIrregularEvenBigger_a0 = 0;
+StructNestedIrregularBigger returnStructNestedIrregularEvenBigger_a1 =
+    StructNestedIrregularBigger();
+StructNestedIrregularBigger returnStructNestedIrregularEvenBigger_a2 =
+    StructNestedIrregularBigger();
+double returnStructNestedIrregularEvenBigger_a3 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+StructNestedIrregularEvenBigger returnStructNestedIrregularEvenBiggerResult =
+    StructNestedIrregularEvenBigger();
+
+StructNestedIrregularEvenBigger
+    returnStructNestedIrregularEvenBiggerCalculateResult() {
+  StructNestedIrregularEvenBigger result =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+
+  result.a0 = returnStructNestedIrregularEvenBigger_a0;
+  result.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a0;
+  result.a1.a0.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a1.a0.a0;
+  result.a1.a0.a1.a0.a1 = returnStructNestedIrregularEvenBigger_a1.a0.a1.a0.a1;
+  result.a1.a0.a1.a1.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a1.a1.a0;
+  result.a1.a0.a2 = returnStructNestedIrregularEvenBigger_a1.a0.a2;
+  result.a1.a0.a3.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a3.a0.a0;
+  result.a1.a0.a3.a1 = returnStructNestedIrregularEvenBigger_a1.a0.a3.a1;
+  result.a1.a0.a4 = returnStructNestedIrregularEvenBigger_a1.a0.a4;
+  result.a1.a0.a5.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a5.a0.a0;
+  result.a1.a0.a5.a1.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a5.a1.a0;
+  result.a1.a0.a6 = returnStructNestedIrregularEvenBigger_a1.a0.a6;
+  result.a1.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a1.a0.a0;
+  result.a1.a1.a0.a1 = returnStructNestedIrregularEvenBigger_a1.a1.a0.a1;
+  result.a1.a1.a1.a0 = returnStructNestedIrregularEvenBigger_a1.a1.a1.a0;
+  result.a1.a2 = returnStructNestedIrregularEvenBigger_a1.a2;
+  result.a1.a3 = returnStructNestedIrregularEvenBigger_a1.a3;
+  result.a2.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a0;
+  result.a2.a0.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a1.a0.a0;
+  result.a2.a0.a1.a0.a1 = returnStructNestedIrregularEvenBigger_a2.a0.a1.a0.a1;
+  result.a2.a0.a1.a1.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a1.a1.a0;
+  result.a2.a0.a2 = returnStructNestedIrregularEvenBigger_a2.a0.a2;
+  result.a2.a0.a3.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a3.a0.a0;
+  result.a2.a0.a3.a1 = returnStructNestedIrregularEvenBigger_a2.a0.a3.a1;
+  result.a2.a0.a4 = returnStructNestedIrregularEvenBigger_a2.a0.a4;
+  result.a2.a0.a5.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a5.a0.a0;
+  result.a2.a0.a5.a1.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a5.a1.a0;
+  result.a2.a0.a6 = returnStructNestedIrregularEvenBigger_a2.a0.a6;
+  result.a2.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a1.a0.a0;
+  result.a2.a1.a0.a1 = returnStructNestedIrregularEvenBigger_a2.a1.a0.a1;
+  result.a2.a1.a1.a0 = returnStructNestedIrregularEvenBigger_a2.a1.a1.a0;
+  result.a2.a2 = returnStructNestedIrregularEvenBigger_a2.a2;
+  result.a2.a3 = returnStructNestedIrregularEvenBigger_a2.a3;
+  result.a3 = returnStructNestedIrregularEvenBigger_a3;
+
+  returnStructNestedIrregularEvenBiggerResult = result;
+
+  return result;
+}
+
+/// Return big irregular struct as smoke test.
+StructNestedIrregularEvenBigger returnStructNestedIrregularEvenBigger(int a0,
+    StructNestedIrregularBigger a1, StructNestedIrregularBigger a2, double a3) {
+  print("returnStructNestedIrregularEvenBigger(${a0}, ${a1}, ${a2}, ${a3})");
+
+  // In legacy mode, possibly return null.
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0 == 42 || a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "ReturnStructNestedIrregularEvenBigger throwing on purpuse!");
+  }
+
+  returnStructNestedIrregularEvenBigger_a0 = a0;
+  returnStructNestedIrregularEvenBigger_a1 = a1;
+  returnStructNestedIrregularEvenBigger_a2 = a2;
+  returnStructNestedIrregularEvenBigger_a3 = a3;
+
+  final result = returnStructNestedIrregularEvenBiggerCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStructNestedIrregularEvenBiggerAfterCallback() {
+  calloc.free(returnStructNestedIrregularEvenBiggerResult.addressOf);
+
+  final result = returnStructNestedIrregularEvenBiggerCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStructNestedIrregularEvenBiggerResult.addressOf);
 }
diff --git a/tests/ffi/function_callbacks_structs_by_value_test.dart b/tests/ffi/function_callbacks_structs_by_value_test.dart
index 98ab518..5e9399a 100644
--- a/tests/ffi/function_callbacks_structs_by_value_test.dart
+++ b/tests/ffi/function_callbacks_structs_by_value_test.dart
@@ -11,6 +11,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 // Reuse the struct classes.
 import 'function_structs_by_value_generated_test.dart';
 
@@ -18,11 +19,12 @@
   for (int i = 0; i < 10; i++) {
     recursiveTest(10);
     recursiveTest(11);
+    testCopyLogic();
   }
 }
 
 void recursiveTest(int recursionCounter) {
-  final struct = allocate<Struct20BytesHomogeneousInt32>().ref;
+  final struct = calloc<Struct20BytesHomogeneousInt32>().ref;
   struct.a0 = 1;
   struct.a1 = 2;
   struct.a2 = 3;
@@ -34,7 +36,7 @@
   Expect.equals(struct.a2, result.a2);
   Expect.equals(struct.a3, result.a3);
   Expect.equals(struct.a4, result.a4);
-  free(struct.addressOf);
+  calloc.free(struct.addressOf);
 }
 
 Struct20BytesHomogeneousInt32 dartPassStructRecursive(
@@ -69,3 +71,65 @@
         Struct20BytesHomogeneousInt32 struct, Pointer callbackAddress),
     Struct20BytesHomogeneousInt32 Function(int recursionCounter,
         Struct20BytesHomogeneousInt32, Pointer)>("PassStructRecursive");
+
+Struct8BytesNestedInt typedDataBackedStruct = Struct8BytesNestedInt();
+bool typedDataBackedStructSet = false;
+void _receiveStructByValue(Struct8BytesNestedInt struct) {
+  typedDataBackedStruct = struct;
+  typedDataBackedStructSet = true;
+}
+
+final _receiveStructByValuePointer =
+    Pointer.fromFunction<Void Function(Struct8BytesNestedInt)>(
+        _receiveStructByValue);
+
+final _invokeReceiveStructByValue = ffiTestFunctions.lookupFunction<
+        Void Function(
+            Pointer<NativeFunction<Void Function(Struct8BytesNestedInt)>>),
+        void Function(
+            Pointer<NativeFunction<Void Function(Struct8BytesNestedInt)>>)>(
+    "CallbackWithStruct");
+
+void testCopyLogic() {
+  _invokeReceiveStructByValue(_receiveStructByValuePointer);
+  Expect.isTrue(typedDataBackedStructSet);
+
+  final pointerBackedStruct = calloc<Struct8BytesNestedInt>().ref;
+
+  void reset() {
+    pointerBackedStruct.a0.a0 = 1;
+    pointerBackedStruct.a0.a1 = 2;
+    pointerBackedStruct.a1.a0 = 3;
+    pointerBackedStruct.a1.a1 = 4;
+    typedDataBackedStruct.a0.a0 = 5;
+    typedDataBackedStruct.a0.a1 = 6;
+    typedDataBackedStruct.a1.a0 = 7;
+    typedDataBackedStruct.a1.a1 = 8;
+  }
+
+  // Pointer -> Pointer.
+  reset();
+  pointerBackedStruct.a1 = pointerBackedStruct.a0;
+  Expect.equals(1, pointerBackedStruct.a1.a0);
+  Expect.equals(2, pointerBackedStruct.a1.a1);
+
+  // Pointer -> TypedData.
+  reset();
+  typedDataBackedStruct.a1 = pointerBackedStruct.a0;
+  Expect.equals(1, typedDataBackedStruct.a1.a0);
+  Expect.equals(2, typedDataBackedStruct.a1.a1);
+
+  // TypedData -> Pointer.
+  reset();
+  pointerBackedStruct.a1 = typedDataBackedStruct.a0;
+  Expect.equals(5, pointerBackedStruct.a1.a0);
+  Expect.equals(6, pointerBackedStruct.a1.a1);
+
+  // TypedData -> TypedData.
+  reset();
+  typedDataBackedStruct.a1 = typedDataBackedStruct.a0;
+  Expect.equals(5, typedDataBackedStruct.a1.a0);
+  Expect.equals(6, typedDataBackedStruct.a1.a1);
+
+  calloc.free(pointerBackedStruct.addressOf);
+}
diff --git a/tests/ffi/function_structs_by_value_generated_test.dart b/tests/ffi/function_structs_by_value_generated_test.dart
index 35936e9..ba98841 100644
--- a/tests/ffi/function_structs_by_value_generated_test.dart
+++ b/tests/ffi/function_structs_by_value_generated_test.dart
@@ -15,6 +15,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
@@ -52,6 +53,16 @@
     testPassStructAlignmentInt16();
     testPassStructAlignmentInt32();
     testPassStructAlignmentInt64();
+    testPassStruct8BytesNestedIntx10();
+    testPassStruct8BytesNestedFloatx10();
+    testPassStruct8BytesNestedFloat2x10();
+    testPassStruct8BytesNestedMixedx10();
+    testPassStruct16BytesNestedIntx2();
+    testPassStruct32BytesNestedIntx2();
+    testPassStructNestedIntStructAlignmentInt16();
+    testPassStructNestedIntStructAlignmentInt32();
+    testPassStructNestedIntStructAlignmentInt64();
+    testPassStructNestedIrregularEvenBiggerx4();
     testReturnStruct1ByteInt();
     testReturnStruct3BytesHomogeneousUint8();
     testReturnStruct3BytesInt2ByteAligned();
@@ -82,13 +93,19 @@
     testReturnStructAlignmentInt16();
     testReturnStructAlignmentInt32();
     testReturnStructAlignmentInt64();
+    testReturnStruct8BytesNestedInt();
+    testReturnStruct8BytesNestedFloat();
+    testReturnStruct8BytesNestedFloat2();
+    testReturnStruct8BytesNestedMixed();
+    testReturnStruct16BytesNestedInt();
+    testReturnStruct32BytesNestedInt();
+    testReturnStructNestedIntStructAlignmentInt16();
+    testReturnStructNestedIntStructAlignmentInt32();
+    testReturnStructNestedIntStructAlignmentInt64();
+    testReturnStructNestedIrregularEvenBigger();
   }
 }
 
-class Struct0Bytes extends Struct {
-  String toString() => "()";
-}
-
 class Struct1ByteInt extends Struct {
   @Int8()
   external int a0;
@@ -129,6 +146,13 @@
   String toString() => "(${a0}, ${a1})";
 }
 
+class Struct4BytesFloat extends Struct {
+  @Float()
+  external double a0;
+
+  String toString() => "(${a0})";
+}
+
 class Struct7BytesHomogeneousUint8 extends Struct {
   @Uint8()
   external int a0;
@@ -876,6 +900,129 @@
   String toString() => "(${a0}, ${a1}, ${a2})";
 }
 
+class Struct8BytesNestedInt extends Struct {
+  external Struct4BytesHomogeneousInt16 a0;
+
+  external Struct4BytesHomogeneousInt16 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesNestedFloat extends Struct {
+  external Struct4BytesFloat a0;
+
+  external Struct4BytesFloat a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesNestedFloat2 extends Struct {
+  external Struct4BytesFloat a0;
+
+  @Float()
+  external double a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesNestedMixed extends Struct {
+  external Struct4BytesHomogeneousInt16 a0;
+
+  external Struct4BytesFloat a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct16BytesNestedInt extends Struct {
+  external Struct8BytesNestedInt a0;
+
+  external Struct8BytesNestedInt a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct32BytesNestedInt extends Struct {
+  external Struct16BytesNestedInt a0;
+
+  external Struct16BytesNestedInt a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class StructNestedIntStructAlignmentInt16 extends Struct {
+  external StructAlignmentInt16 a0;
+
+  external StructAlignmentInt16 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class StructNestedIntStructAlignmentInt32 extends Struct {
+  external StructAlignmentInt32 a0;
+
+  external StructAlignmentInt32 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class StructNestedIntStructAlignmentInt64 extends Struct {
+  external StructAlignmentInt64 a0;
+
+  external StructAlignmentInt64 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class StructNestedIrregularBig extends Struct {
+  @Uint16()
+  external int a0;
+
+  external Struct8BytesNestedMixed a1;
+
+  @Uint16()
+  external int a2;
+
+  external Struct8BytesNestedFloat2 a3;
+
+  @Uint16()
+  external int a4;
+
+  external Struct8BytesNestedFloat a5;
+
+  @Uint16()
+  external int a6;
+
+  String toString() => "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6})";
+}
+
+class StructNestedIrregularBigger extends Struct {
+  external StructNestedIrregularBig a0;
+
+  external Struct8BytesNestedMixed a1;
+
+  @Float()
+  external double a2;
+
+  @Double()
+  external double a3;
+
+  String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
+class StructNestedIrregularEvenBigger extends Struct {
+  @Uint64()
+  external int a0;
+
+  external StructNestedIrregularBigger a1;
+
+  external StructNestedIrregularBigger a2;
+
+  @Double()
+  external double a3;
+
+  String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
 final passStruct1ByteIntx10 = ffiTestFunctions.lookupFunction<
     Int64 Function(
         Struct1ByteInt,
@@ -903,16 +1050,16 @@
 /// Smallest struct with data.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct1ByteIntx10() {
-  Struct1ByteInt a0 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a1 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a2 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a3 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a4 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a5 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a6 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a7 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a8 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a9 = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt a0 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a1 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a2 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a3 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a4 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a5 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a6 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a7 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a8 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a9 = calloc<Struct1ByteInt>().ref;
 
   a0.a0 = -1;
   a1.a0 = 2;
@@ -931,16 +1078,16 @@
 
   Expect.equals(5, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct3BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
@@ -970,26 +1117,16 @@
 /// Not a multiple of word size, not a power of two.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct3BytesHomogeneousUint8x10() {
-  Struct3BytesHomogeneousUint8 a0 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a1 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a2 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a3 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a4 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a5 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a6 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a7 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a8 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a9 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a0 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a1 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a2 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a3 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a4 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a5 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a6 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a7 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a8 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a9 = calloc<Struct3BytesHomogeneousUint8>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -1029,16 +1166,16 @@
 
   Expect.equals(465, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct3BytesInt2ByteAlignedx10 = ffiTestFunctions.lookupFunction<
@@ -1069,16 +1206,16 @@
 /// With alignment rules taken into account size is 4 bytes.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct3BytesInt2ByteAlignedx10() {
-  Struct3BytesInt2ByteAligned a0 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a1 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a2 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a3 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a4 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a5 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a6 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a7 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a8 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a9 = allocate<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a0 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a1 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a2 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a3 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a4 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a5 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a6 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a7 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a8 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a9 = calloc<Struct3BytesInt2ByteAligned>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1108,16 +1245,16 @@
 
   Expect.equals(10, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct4BytesHomogeneousInt16x10 = ffiTestFunctions.lookupFunction<
@@ -1147,26 +1284,16 @@
 /// Exactly word size on 32-bit architectures.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct4BytesHomogeneousInt16x10() {
-  Struct4BytesHomogeneousInt16 a0 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a1 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a2 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a3 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a4 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a5 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a6 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a7 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a8 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a9 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a0 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a1 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a2 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a3 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a4 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a5 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a6 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a7 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a8 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a9 = calloc<Struct4BytesHomogeneousInt16>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1196,16 +1323,16 @@
 
   Expect.equals(10, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct7BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
@@ -1235,26 +1362,16 @@
 /// Sub word size on 64 bit architectures.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct7BytesHomogeneousUint8x10() {
-  Struct7BytesHomogeneousUint8 a0 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a1 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a2 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a3 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a4 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a5 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a6 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a7 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a8 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a9 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a0 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a1 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a2 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a3 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a4 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a5 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a6 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a7 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a8 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a9 = calloc<Struct7BytesHomogeneousUint8>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -1334,16 +1451,16 @@
 
   Expect.equals(2485, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct7BytesInt4ByteAlignedx10 = ffiTestFunctions.lookupFunction<
@@ -1374,16 +1491,16 @@
 /// With alignment rules taken into account size is 8 bytes.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct7BytesInt4ByteAlignedx10() {
-  Struct7BytesInt4ByteAligned a0 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a1 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a2 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a3 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a4 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a5 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a6 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a7 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a8 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a9 = allocate<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a0 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a1 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a2 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a3 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a4 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a5 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a6 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a7 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a8 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a9 = calloc<Struct7BytesInt4ByteAligned>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1423,16 +1540,16 @@
 
   Expect.equals(15, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct8BytesIntx10 = ffiTestFunctions.lookupFunction<
@@ -1462,16 +1579,16 @@
 /// Exactly word size struct on 64bit architectures.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct8BytesIntx10() {
-  Struct8BytesInt a0 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a1 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a2 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a3 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a4 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a5 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a6 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a7 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a8 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a9 = allocate<Struct8BytesInt>().ref;
+  Struct8BytesInt a0 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a1 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a2 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a3 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a4 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a5 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a6 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a7 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a8 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a9 = calloc<Struct8BytesInt>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1510,16 +1627,16 @@
 
   Expect.equals(15, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct8BytesHomogeneousFloatx10 = ffiTestFunctions.lookupFunction<
@@ -1549,26 +1666,16 @@
 /// Arguments passed in FP registers as long as they fit.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct8BytesHomogeneousFloatx10() {
-  Struct8BytesHomogeneousFloat a0 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a1 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a2 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a3 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a4 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a5 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a6 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a7 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a8 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a9 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a0 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a1 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a2 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a3 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a4 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a5 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a6 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a7 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a8 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a9 = calloc<Struct8BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -1598,16 +1705,16 @@
 
   Expect.approxEquals(10.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct8BytesMixedx10 = ffiTestFunctions.lookupFunction<
@@ -1637,16 +1744,16 @@
 /// On x64, arguments go in int registers because it is not only float.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct8BytesMixedx10() {
-  Struct8BytesMixed a0 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a1 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a2 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a3 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a4 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a5 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a6 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a7 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a8 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a9 = allocate<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a0 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a1 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a2 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a3 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a4 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a5 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a6 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a7 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a8 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a9 = calloc<Struct8BytesMixed>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2;
@@ -1686,16 +1793,16 @@
 
   Expect.approxEquals(15.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct9BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
@@ -1728,26 +1835,16 @@
 /// Tests upper bytes in the integer registers that are partly filled.
 /// Tests stack alignment of non word size stack arguments.
 void testPassStruct9BytesHomogeneousUint8x10() {
-  Struct9BytesHomogeneousUint8 a0 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a1 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a2 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a3 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a4 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a5 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a6 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a7 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a8 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a9 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a0 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a1 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a2 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a3 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a4 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a5 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a6 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a7 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a8 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a9 = calloc<Struct9BytesHomogeneousUint8>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -1847,16 +1944,16 @@
 
   Expect.equals(4095, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct9BytesInt4Or8ByteAlignedx10 = ffiTestFunctions.lookupFunction<
@@ -1890,25 +1987,25 @@
 ///
 void testPassStruct9BytesInt4Or8ByteAlignedx10() {
   Struct9BytesInt4Or8ByteAligned a0 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a1 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a2 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a3 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a4 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a5 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a6 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a7 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a8 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a9 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1938,16 +2035,16 @@
 
   Expect.equals(10, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct12BytesHomogeneousFloatx6 = ffiTestFunctions.lookupFunction<
@@ -1971,17 +2068,17 @@
 /// The last argument is to test whether arguments are backfilled.
 void testPassStruct12BytesHomogeneousFloatx6() {
   Struct12BytesHomogeneousFloat a0 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a1 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a2 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a3 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a4 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a5 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2008,12 +2105,12 @@
 
   Expect.approxEquals(9.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
 }
 
 final passStruct16BytesHomogeneousFloatx5 = ffiTestFunctions.lookupFunction<
@@ -2035,15 +2132,15 @@
 /// 5 struct arguments will exhaust available registers.
 void testPassStruct16BytesHomogeneousFloatx5() {
   Struct16BytesHomogeneousFloat a0 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   Struct16BytesHomogeneousFloat a1 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   Struct16BytesHomogeneousFloat a2 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   Struct16BytesHomogeneousFloat a3 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   Struct16BytesHomogeneousFloat a4 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2072,11 +2169,11 @@
 
   Expect.approxEquals(10.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
 }
 
 final passStruct16BytesMixedx10 = ffiTestFunctions.lookupFunction<
@@ -2108,16 +2205,16 @@
 /// The rest goes on the stack.
 /// On arm, arguments are 8 byte aligned.
 void testPassStruct16BytesMixedx10() {
-  Struct16BytesMixed a0 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a1 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a2 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a3 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a4 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a8 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a9 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a0 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a1 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a2 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a3 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a4 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a5 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a6 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a7 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a8 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a9 = calloc<Struct16BytesMixed>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2;
@@ -2147,16 +2244,16 @@
 
   Expect.approxEquals(10.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct16BytesMixed2x10 = ffiTestFunctions.lookupFunction<
@@ -2188,16 +2285,16 @@
 /// The rest goes on the stack.
 /// On arm, arguments are 4 byte aligned.
 void testPassStruct16BytesMixed2x10() {
-  Struct16BytesMixed2 a0 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a1 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a2 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a3 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a4 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a5 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a6 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a7 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a8 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a9 = allocate<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a0 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a1 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a2 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a3 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a4 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a5 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a6 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a7 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a8 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a9 = calloc<Struct16BytesMixed2>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2247,16 +2344,16 @@
 
   Expect.approxEquals(20.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct17BytesIntx10 = ffiTestFunctions.lookupFunction<
@@ -2286,16 +2383,16 @@
 /// Arguments are passed as pointer to copy on arm64.
 /// Tests that the memory allocated for copies are rounded up to word size.
 void testPassStruct17BytesIntx10() {
-  Struct17BytesInt a0 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a1 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a2 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a3 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a4 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a5 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a6 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a7 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a8 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a9 = allocate<Struct17BytesInt>().ref;
+  Struct17BytesInt a0 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a1 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a2 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a3 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a4 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a5 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a6 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a7 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a8 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a9 = calloc<Struct17BytesInt>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -2335,16 +2432,16 @@
 
   Expect.equals(15, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct19BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
@@ -2376,25 +2473,25 @@
 ///
 void testPassStruct19BytesHomogeneousUint8x10() {
   Struct19BytesHomogeneousUint8 a0 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a1 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a2 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a3 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a4 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a5 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a6 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a7 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a8 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a9 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -2594,16 +2691,16 @@
 
   Expect.equals(18145, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct20BytesHomogeneousInt32x10 = ffiTestFunctions.lookupFunction<
@@ -2636,25 +2733,25 @@
 /// pointers to copies are also passed on the stack.
 void testPassStruct20BytesHomogeneousInt32x10() {
   Struct20BytesHomogeneousInt32 a0 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a1 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a2 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a3 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a4 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a5 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a6 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a7 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a8 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a9 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -2714,16 +2811,16 @@
 
   Expect.equals(25, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
@@ -2734,7 +2831,7 @@
 /// Argument too big to go into FPU registers in hardfp and arm64.
 void testPassStruct20BytesHomogeneousFloat() {
   Struct20BytesHomogeneousFloat a0 =
-      allocate<Struct20BytesHomogeneousFloat>().ref;
+      calloc<Struct20BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2748,7 +2845,7 @@
 
   Expect.approxEquals(-3.0, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passStruct32BytesHomogeneousDoublex5 = ffiTestFunctions.lookupFunction<
@@ -2770,15 +2867,15 @@
 /// 5 struct arguments will exhaust available registers.
 void testPassStruct32BytesHomogeneousDoublex5() {
   Struct32BytesHomogeneousDouble a0 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   Struct32BytesHomogeneousDouble a1 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   Struct32BytesHomogeneousDouble a2 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   Struct32BytesHomogeneousDouble a3 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   Struct32BytesHomogeneousDouble a4 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2807,11 +2904,11 @@
 
   Expect.approxEquals(10.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
 }
 
 final passStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction<
@@ -2822,7 +2919,7 @@
 /// Argument too big to go into FPU registers in arm64.
 void testPassStruct40BytesHomogeneousDouble() {
   Struct40BytesHomogeneousDouble a0 =
-      allocate<Struct40BytesHomogeneousDouble>().ref;
+      calloc<Struct40BytesHomogeneousDouble>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2836,7 +2933,7 @@
 
   Expect.approxEquals(-3.0, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction<
@@ -2847,7 +2944,7 @@
 /// Test 1kb struct.
 void testPassStruct1024BytesHomogeneousUint64() {
   Struct1024BytesHomogeneousUint64 a0 =
-      allocate<Struct1024BytesHomogeneousUint64>().ref;
+      calloc<Struct1024BytesHomogeneousUint64>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -2984,7 +3081,7 @@
 
   Expect.equals(8256, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passFloatStruct16BytesHomogeneousFloatFloatStruct1 =
@@ -3014,16 +3111,16 @@
 void testPassFloatStruct16BytesHomogeneousFloatFloatStruct1() {
   double a0;
   Struct16BytesHomogeneousFloat a1 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   double a2;
   Struct16BytesHomogeneousFloat a3 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   double a4;
   Struct16BytesHomogeneousFloat a5 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   double a6;
   Struct16BytesHomogeneousFloat a7 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   double a8;
 
   a0 = -1.0;
@@ -3055,10 +3152,10 @@
 
   Expect.approxEquals(-11.0, result);
 
-  free(a1.addressOf);
-  free(a3.addressOf);
-  free(a5.addressOf);
-  free(a7.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a7.addressOf);
 }
 
 final passFloatStruct32BytesHomogeneousDoubleFloatStruct =
@@ -3088,16 +3185,16 @@
 void testPassFloatStruct32BytesHomogeneousDoubleFloatStruct() {
   double a0;
   Struct32BytesHomogeneousDouble a1 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   double a2;
   Struct32BytesHomogeneousDouble a3 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   double a4;
   Struct32BytesHomogeneousDouble a5 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   double a6;
   Struct32BytesHomogeneousDouble a7 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   double a8;
 
   a0 = -1.0;
@@ -3129,10 +3226,10 @@
 
   Expect.approxEquals(-11.0, result);
 
-  free(a1.addressOf);
-  free(a3.addressOf);
-  free(a5.addressOf);
-  free(a7.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a7.addressOf);
 }
 
 final passInt8Struct16BytesMixedInt8Struct16BytesMixedIn =
@@ -3157,13 +3254,13 @@
 /// Test backfilling of integer registers.
 void testPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn() {
   int a0;
-  Struct16BytesMixed a1 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a1 = calloc<Struct16BytesMixed>().ref;
   int a2;
-  Struct16BytesMixed a3 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a3 = calloc<Struct16BytesMixed>().ref;
   int a4;
-  Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a5 = calloc<Struct16BytesMixed>().ref;
   int a6;
-  Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a7 = calloc<Struct16BytesMixed>().ref;
   int a8;
 
   a0 = -1;
@@ -3187,10 +3284,10 @@
 
   Expect.approxEquals(-7.0, result);
 
-  free(a1.addressOf);
-  free(a3.addressOf);
-  free(a5.addressOf);
-  free(a7.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a7.addressOf);
 }
 
 final passDoublex6Struct16BytesMixedx4Int32 = ffiTestFunctions.lookupFunction<
@@ -3229,10 +3326,10 @@
   double a3;
   double a4;
   double a5;
-  Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a8 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a9 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a6 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a7 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a8 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a9 = calloc<Struct16BytesMixed>().ref;
   int a10;
 
   a0 = -1.0;
@@ -3258,10 +3355,10 @@
 
   Expect.approxEquals(-8.0, result);
 
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passInt32x4Struct16BytesMixedx4Double = ffiTestFunctions.lookupFunction<
@@ -3286,10 +3383,10 @@
   int a1;
   int a2;
   int a3;
-  Struct16BytesMixed a4 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a4 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a5 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a6 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a7 = calloc<Struct16BytesMixed>().ref;
   double a8;
 
   a0 = -1;
@@ -3313,10 +3410,10 @@
 
   Expect.approxEquals(-7.0, result);
 
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
 }
 
 final passStruct40BytesHomogeneousDoubleStruct4BytesHomo =
@@ -3331,11 +3428,9 @@
 /// Check that the other two arguments are allocated on registers.
 void testPassStruct40BytesHomogeneousDoubleStruct4BytesHomo() {
   Struct40BytesHomogeneousDouble a0 =
-      allocate<Struct40BytesHomogeneousDouble>().ref;
-  Struct4BytesHomogeneousInt16 a1 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct8BytesHomogeneousFloat a2 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+      calloc<Struct40BytesHomogeneousDouble>().ref;
+  Struct4BytesHomogeneousInt16 a1 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct8BytesHomogeneousFloat a2 = calloc<Struct8BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -3353,9 +3448,9 @@
 
   Expect.approxEquals(-5.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
 }
 
 final passInt32x8Doublex8Int64Int8Struct1ByteIntInt64Int =
@@ -3463,30 +3558,28 @@
   double a15;
   int a16;
   int a17;
-  Struct1ByteInt a18 = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt a18 = calloc<Struct1ByteInt>().ref;
   int a19;
   int a20;
-  Struct4BytesHomogeneousInt16 a21 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a21 = calloc<Struct4BytesHomogeneousInt16>().ref;
   int a22;
   int a23;
-  Struct8BytesInt a24 = allocate<Struct8BytesInt>().ref;
+  Struct8BytesInt a24 = calloc<Struct8BytesInt>().ref;
   int a25;
   int a26;
-  Struct8BytesHomogeneousFloat a27 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a27 = calloc<Struct8BytesHomogeneousFloat>().ref;
   int a28;
   int a29;
-  Struct8BytesMixed a30 = allocate<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a30 = calloc<Struct8BytesMixed>().ref;
   int a31;
   int a32;
-  StructAlignmentInt16 a33 = allocate<StructAlignmentInt16>().ref;
+  StructAlignmentInt16 a33 = calloc<StructAlignmentInt16>().ref;
   int a34;
   int a35;
-  StructAlignmentInt32 a36 = allocate<StructAlignmentInt32>().ref;
+  StructAlignmentInt32 a36 = calloc<StructAlignmentInt32>().ref;
   int a37;
   int a38;
-  StructAlignmentInt64 a39 = allocate<StructAlignmentInt64>().ref;
+  StructAlignmentInt64 a39 = calloc<StructAlignmentInt64>().ref;
 
   a0 = -1;
   a1 = 2;
@@ -3587,14 +3680,14 @@
 
   Expect.approxEquals(26.0, result);
 
-  free(a18.addressOf);
-  free(a21.addressOf);
-  free(a24.addressOf);
-  free(a27.addressOf);
-  free(a30.addressOf);
-  free(a33.addressOf);
-  free(a36.addressOf);
-  free(a39.addressOf);
+  calloc.free(a18.addressOf);
+  calloc.free(a21.addressOf);
+  calloc.free(a24.addressOf);
+  calloc.free(a27.addressOf);
+  calloc.free(a30.addressOf);
+  calloc.free(a33.addressOf);
+  calloc.free(a36.addressOf);
+  calloc.free(a39.addressOf);
 }
 
 final passStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
@@ -3603,7 +3696,7 @@
 
 /// Test alignment and padding of 16 byte int within struct.
 void testPassStructAlignmentInt16() {
-  StructAlignmentInt16 a0 = allocate<StructAlignmentInt16>().ref;
+  StructAlignmentInt16 a0 = calloc<StructAlignmentInt16>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -3615,7 +3708,7 @@
 
   Expect.equals(-2, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passStructAlignmentInt32 = ffiTestFunctions.lookupFunction<
@@ -3624,7 +3717,7 @@
 
 /// Test alignment and padding of 32 byte int within struct.
 void testPassStructAlignmentInt32() {
-  StructAlignmentInt32 a0 = allocate<StructAlignmentInt32>().ref;
+  StructAlignmentInt32 a0 = calloc<StructAlignmentInt32>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -3636,7 +3729,7 @@
 
   Expect.equals(-2, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passStructAlignmentInt64 = ffiTestFunctions.lookupFunction<
@@ -3645,7 +3738,7 @@
 
 /// Test alignment and padding of 64 byte int within struct.
 void testPassStructAlignmentInt64() {
-  StructAlignmentInt64 a0 = allocate<StructAlignmentInt64>().ref;
+  StructAlignmentInt64 a0 = calloc<StructAlignmentInt64>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -3657,7 +3750,692 @@
 
   Expect.equals(-2, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
+}
+
+final passStruct8BytesNestedIntx10 = ffiTestFunctions.lookupFunction<
+    Int64 Function(
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt),
+    int Function(
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt)>("PassStruct8BytesNestedIntx10");
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust registers on all platforms.
+void testPassStruct8BytesNestedIntx10() {
+  Struct8BytesNestedInt a0 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a1 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a2 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a3 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a4 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a5 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a6 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a7 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a8 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a9 = calloc<Struct8BytesNestedInt>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3;
+  a0.a1.a1 = 4;
+  a1.a0.a0 = -5;
+  a1.a0.a1 = 6;
+  a1.a1.a0 = -7;
+  a1.a1.a1 = 8;
+  a2.a0.a0 = -9;
+  a2.a0.a1 = 10;
+  a2.a1.a0 = -11;
+  a2.a1.a1 = 12;
+  a3.a0.a0 = -13;
+  a3.a0.a1 = 14;
+  a3.a1.a0 = -15;
+  a3.a1.a1 = 16;
+  a4.a0.a0 = -17;
+  a4.a0.a1 = 18;
+  a4.a1.a0 = -19;
+  a4.a1.a1 = 20;
+  a5.a0.a0 = -21;
+  a5.a0.a1 = 22;
+  a5.a1.a0 = -23;
+  a5.a1.a1 = 24;
+  a6.a0.a0 = -25;
+  a6.a0.a1 = 26;
+  a6.a1.a0 = -27;
+  a6.a1.a1 = 28;
+  a7.a0.a0 = -29;
+  a7.a0.a1 = 30;
+  a7.a1.a0 = -31;
+  a7.a1.a1 = 32;
+  a8.a0.a0 = -33;
+  a8.a0.a1 = 34;
+  a8.a1.a0 = -35;
+  a8.a1.a1 = 36;
+  a9.a0.a0 = -37;
+  a9.a0.a1 = 38;
+  a9.a1.a0 = -39;
+  a9.a1.a1 = 40;
+
+  final result =
+      passStruct8BytesNestedIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  print("result = $result");
+
+  Expect.equals(20, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
+}
+
+final passStruct8BytesNestedFloatx10 = ffiTestFunctions.lookupFunction<
+    Float Function(
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat),
+    double Function(
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat)>("PassStruct8BytesNestedFloatx10");
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust fpu registers on all platforms.
+void testPassStruct8BytesNestedFloatx10() {
+  Struct8BytesNestedFloat a0 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a1 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a2 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a3 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a4 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a5 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a6 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a7 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a8 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a9 = calloc<Struct8BytesNestedFloat>().ref;
+
+  a0.a0.a0 = -1.0;
+  a0.a1.a0 = 2.0;
+  a1.a0.a0 = -3.0;
+  a1.a1.a0 = 4.0;
+  a2.a0.a0 = -5.0;
+  a2.a1.a0 = 6.0;
+  a3.a0.a0 = -7.0;
+  a3.a1.a0 = 8.0;
+  a4.a0.a0 = -9.0;
+  a4.a1.a0 = 10.0;
+  a5.a0.a0 = -11.0;
+  a5.a1.a0 = 12.0;
+  a6.a0.a0 = -13.0;
+  a6.a1.a0 = 14.0;
+  a7.a0.a0 = -15.0;
+  a7.a1.a0 = 16.0;
+  a8.a0.a0 = -17.0;
+  a8.a1.a0 = 18.0;
+  a9.a0.a0 = -19.0;
+  a9.a1.a0 = 20.0;
+
+  final result =
+      passStruct8BytesNestedFloatx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  print("result = $result");
+
+  Expect.approxEquals(10.0, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
+}
+
+final passStruct8BytesNestedFloat2x10 = ffiTestFunctions.lookupFunction<
+    Float Function(
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2),
+    double Function(
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2)>("PassStruct8BytesNestedFloat2x10");
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust fpu registers on all platforms.
+/// The nesting is irregular, testing homogenous float rules on arm and arm64,
+/// and the fpu register usage on x64.
+void testPassStruct8BytesNestedFloat2x10() {
+  Struct8BytesNestedFloat2 a0 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a1 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a2 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a3 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a4 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a5 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a6 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a7 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a8 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a9 = calloc<Struct8BytesNestedFloat2>().ref;
+
+  a0.a0.a0 = -1.0;
+  a0.a1 = 2.0;
+  a1.a0.a0 = -3.0;
+  a1.a1 = 4.0;
+  a2.a0.a0 = -5.0;
+  a2.a1 = 6.0;
+  a3.a0.a0 = -7.0;
+  a3.a1 = 8.0;
+  a4.a0.a0 = -9.0;
+  a4.a1 = 10.0;
+  a5.a0.a0 = -11.0;
+  a5.a1 = 12.0;
+  a6.a0.a0 = -13.0;
+  a6.a1 = 14.0;
+  a7.a0.a0 = -15.0;
+  a7.a1 = 16.0;
+  a8.a0.a0 = -17.0;
+  a8.a1 = 18.0;
+  a9.a0.a0 = -19.0;
+  a9.a1 = 20.0;
+
+  final result =
+      passStruct8BytesNestedFloat2x10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  print("result = $result");
+
+  Expect.approxEquals(10.0, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
+}
+
+final passStruct8BytesNestedMixedx10 = ffiTestFunctions.lookupFunction<
+    Double Function(
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed),
+    double Function(
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed)>("PassStruct8BytesNestedMixedx10");
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust all registers on all platforms.
+void testPassStruct8BytesNestedMixedx10() {
+  Struct8BytesNestedMixed a0 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a1 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a2 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a3 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a4 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a5 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a6 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a7 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a8 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a9 = calloc<Struct8BytesNestedMixed>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3.0;
+  a1.a0.a0 = 4;
+  a1.a0.a1 = -5;
+  a1.a1.a0 = 6.0;
+  a2.a0.a0 = -7;
+  a2.a0.a1 = 8;
+  a2.a1.a0 = -9.0;
+  a3.a0.a0 = 10;
+  a3.a0.a1 = -11;
+  a3.a1.a0 = 12.0;
+  a4.a0.a0 = -13;
+  a4.a0.a1 = 14;
+  a4.a1.a0 = -15.0;
+  a5.a0.a0 = 16;
+  a5.a0.a1 = -17;
+  a5.a1.a0 = 18.0;
+  a6.a0.a0 = -19;
+  a6.a0.a1 = 20;
+  a6.a1.a0 = -21.0;
+  a7.a0.a0 = 22;
+  a7.a0.a1 = -23;
+  a7.a1.a0 = 24.0;
+  a8.a0.a0 = -25;
+  a8.a0.a1 = 26;
+  a8.a1.a0 = -27.0;
+  a9.a0.a0 = 28;
+  a9.a0.a1 = -29;
+  a9.a1.a0 = 30.0;
+
+  final result =
+      passStruct8BytesNestedMixedx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  print("result = $result");
+
+  Expect.approxEquals(15.0, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
+}
+
+final passStruct16BytesNestedIntx2 = ffiTestFunctions.lookupFunction<
+    Int64 Function(Struct16BytesNestedInt, Struct16BytesNestedInt),
+    int Function(Struct16BytesNestedInt,
+        Struct16BytesNestedInt)>("PassStruct16BytesNestedIntx2");
+
+/// Deeper nested struct to test recursive member access.
+void testPassStruct16BytesNestedIntx2() {
+  Struct16BytesNestedInt a0 = calloc<Struct16BytesNestedInt>().ref;
+  Struct16BytesNestedInt a1 = calloc<Struct16BytesNestedInt>().ref;
+
+  a0.a0.a0.a0 = -1;
+  a0.a0.a0.a1 = 2;
+  a0.a0.a1.a0 = -3;
+  a0.a0.a1.a1 = 4;
+  a0.a1.a0.a0 = -5;
+  a0.a1.a0.a1 = 6;
+  a0.a1.a1.a0 = -7;
+  a0.a1.a1.a1 = 8;
+  a1.a0.a0.a0 = -9;
+  a1.a0.a0.a1 = 10;
+  a1.a0.a1.a0 = -11;
+  a1.a0.a1.a1 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15;
+  a1.a1.a1.a1 = 16;
+
+  final result = passStruct16BytesNestedIntx2(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(8, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final passStruct32BytesNestedIntx2 = ffiTestFunctions.lookupFunction<
+    Int64 Function(Struct32BytesNestedInt, Struct32BytesNestedInt),
+    int Function(Struct32BytesNestedInt,
+        Struct32BytesNestedInt)>("PassStruct32BytesNestedIntx2");
+
+/// Even deeper nested struct to test recursive member access.
+void testPassStruct32BytesNestedIntx2() {
+  Struct32BytesNestedInt a0 = calloc<Struct32BytesNestedInt>().ref;
+  Struct32BytesNestedInt a1 = calloc<Struct32BytesNestedInt>().ref;
+
+  a0.a0.a0.a0.a0 = -1;
+  a0.a0.a0.a0.a1 = 2;
+  a0.a0.a0.a1.a0 = -3;
+  a0.a0.a0.a1.a1 = 4;
+  a0.a0.a1.a0.a0 = -5;
+  a0.a0.a1.a0.a1 = 6;
+  a0.a0.a1.a1.a0 = -7;
+  a0.a0.a1.a1.a1 = 8;
+  a0.a1.a0.a0.a0 = -9;
+  a0.a1.a0.a0.a1 = 10;
+  a0.a1.a0.a1.a0 = -11;
+  a0.a1.a0.a1.a1 = 12;
+  a0.a1.a1.a0.a0 = -13;
+  a0.a1.a1.a0.a1 = 14;
+  a0.a1.a1.a1.a0 = -15;
+  a0.a1.a1.a1.a1 = 16;
+  a1.a0.a0.a0.a0 = -17;
+  a1.a0.a0.a0.a1 = 18;
+  a1.a0.a0.a1.a0 = -19;
+  a1.a0.a0.a1.a1 = 20;
+  a1.a0.a1.a0.a0 = -21;
+  a1.a0.a1.a0.a1 = 22;
+  a1.a0.a1.a1.a0 = -23;
+  a1.a0.a1.a1.a1 = 24;
+  a1.a1.a0.a0.a0 = -25;
+  a1.a1.a0.a0.a1 = 26;
+  a1.a1.a0.a1.a0 = -27;
+  a1.a1.a0.a1.a1 = 28;
+  a1.a1.a1.a0.a0 = -29;
+  a1.a1.a1.a0.a1 = 30;
+  a1.a1.a1.a1.a0 = -31;
+  a1.a1.a1.a1.a1 = 32;
+
+  final result = passStruct32BytesNestedIntx2(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(16, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final passStructNestedIntStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
+        Int64 Function(StructNestedIntStructAlignmentInt16),
+        int Function(StructNestedIntStructAlignmentInt16)>(
+    "PassStructNestedIntStructAlignmentInt16");
+
+/// Test alignment and padding of nested struct with 16 byte int.
+void testPassStructNestedIntStructAlignmentInt16() {
+  StructNestedIntStructAlignmentInt16 a0 =
+      calloc<StructNestedIntStructAlignmentInt16>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  final result = passStructNestedIntStructAlignmentInt16(a0);
+
+  print("result = $result");
+
+  Expect.equals(3, result);
+
+  calloc.free(a0.addressOf);
+}
+
+final passStructNestedIntStructAlignmentInt32 = ffiTestFunctions.lookupFunction<
+        Int64 Function(StructNestedIntStructAlignmentInt32),
+        int Function(StructNestedIntStructAlignmentInt32)>(
+    "PassStructNestedIntStructAlignmentInt32");
+
+/// Test alignment and padding of nested struct with 32 byte int.
+void testPassStructNestedIntStructAlignmentInt32() {
+  StructNestedIntStructAlignmentInt32 a0 =
+      calloc<StructNestedIntStructAlignmentInt32>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  final result = passStructNestedIntStructAlignmentInt32(a0);
+
+  print("result = $result");
+
+  Expect.equals(3, result);
+
+  calloc.free(a0.addressOf);
+}
+
+final passStructNestedIntStructAlignmentInt64 = ffiTestFunctions.lookupFunction<
+        Int64 Function(StructNestedIntStructAlignmentInt64),
+        int Function(StructNestedIntStructAlignmentInt64)>(
+    "PassStructNestedIntStructAlignmentInt64");
+
+/// Test alignment and padding of nested struct with 64 byte int.
+void testPassStructNestedIntStructAlignmentInt64() {
+  StructNestedIntStructAlignmentInt64 a0 =
+      calloc<StructNestedIntStructAlignmentInt64>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  final result = passStructNestedIntStructAlignmentInt64(a0);
+
+  print("result = $result");
+
+  Expect.equals(3, result);
+
+  calloc.free(a0.addressOf);
+}
+
+final passStructNestedIrregularEvenBiggerx4 = ffiTestFunctions.lookupFunction<
+        Double Function(
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger),
+        double Function(
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger)>(
+    "PassStructNestedIrregularEvenBiggerx4");
+
+/// Return big irregular struct as smoke test.
+void testPassStructNestedIrregularEvenBiggerx4() {
+  StructNestedIrregularEvenBigger a0 =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+  StructNestedIrregularEvenBigger a1 =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+  StructNestedIrregularEvenBigger a2 =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+  StructNestedIrregularEvenBigger a3 =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+
+  a0.a0 = 1;
+  a0.a1.a0.a0 = 2;
+  a0.a1.a0.a1.a0.a0 = -3;
+  a0.a1.a0.a1.a0.a1 = 4;
+  a0.a1.a0.a1.a1.a0 = -5.0;
+  a0.a1.a0.a2 = 6;
+  a0.a1.a0.a3.a0.a0 = -7.0;
+  a0.a1.a0.a3.a1 = 8.0;
+  a0.a1.a0.a4 = 9;
+  a0.a1.a0.a5.a0.a0 = 10.0;
+  a0.a1.a0.a5.a1.a0 = -11.0;
+  a0.a1.a0.a6 = 12;
+  a0.a1.a1.a0.a0 = -13;
+  a0.a1.a1.a0.a1 = 14;
+  a0.a1.a1.a1.a0 = -15.0;
+  a0.a1.a2 = 16.0;
+  a0.a1.a3 = -17.0;
+  a0.a2.a0.a0 = 18;
+  a0.a2.a0.a1.a0.a0 = -19;
+  a0.a2.a0.a1.a0.a1 = 20;
+  a0.a2.a0.a1.a1.a0 = -21.0;
+  a0.a2.a0.a2 = 22;
+  a0.a2.a0.a3.a0.a0 = -23.0;
+  a0.a2.a0.a3.a1 = 24.0;
+  a0.a2.a0.a4 = 25;
+  a0.a2.a0.a5.a0.a0 = 26.0;
+  a0.a2.a0.a5.a1.a0 = -27.0;
+  a0.a2.a0.a6 = 28;
+  a0.a2.a1.a0.a0 = -29;
+  a0.a2.a1.a0.a1 = 30;
+  a0.a2.a1.a1.a0 = -31.0;
+  a0.a2.a2 = 32.0;
+  a0.a2.a3 = -33.0;
+  a0.a3 = 34.0;
+  a1.a0 = 35;
+  a1.a1.a0.a0 = 36;
+  a1.a1.a0.a1.a0.a0 = -37;
+  a1.a1.a0.a1.a0.a1 = 38;
+  a1.a1.a0.a1.a1.a0 = -39.0;
+  a1.a1.a0.a2 = 40;
+  a1.a1.a0.a3.a0.a0 = -41.0;
+  a1.a1.a0.a3.a1 = 42.0;
+  a1.a1.a0.a4 = 43;
+  a1.a1.a0.a5.a0.a0 = 44.0;
+  a1.a1.a0.a5.a1.a0 = -45.0;
+  a1.a1.a0.a6 = 46;
+  a1.a1.a1.a0.a0 = -47;
+  a1.a1.a1.a0.a1 = 48;
+  a1.a1.a1.a1.a0 = -49.0;
+  a1.a1.a2 = 50.0;
+  a1.a1.a3 = -51.0;
+  a1.a2.a0.a0 = 52;
+  a1.a2.a0.a1.a0.a0 = -53;
+  a1.a2.a0.a1.a0.a1 = 54;
+  a1.a2.a0.a1.a1.a0 = -55.0;
+  a1.a2.a0.a2 = 56;
+  a1.a2.a0.a3.a0.a0 = -57.0;
+  a1.a2.a0.a3.a1 = 58.0;
+  a1.a2.a0.a4 = 59;
+  a1.a2.a0.a5.a0.a0 = 60.0;
+  a1.a2.a0.a5.a1.a0 = -61.0;
+  a1.a2.a0.a6 = 62;
+  a1.a2.a1.a0.a0 = -63;
+  a1.a2.a1.a0.a1 = 64;
+  a1.a2.a1.a1.a0 = -65.0;
+  a1.a2.a2 = 66.0;
+  a1.a2.a3 = -67.0;
+  a1.a3 = 68.0;
+  a2.a0 = 69;
+  a2.a1.a0.a0 = 70;
+  a2.a1.a0.a1.a0.a0 = -71;
+  a2.a1.a0.a1.a0.a1 = 72;
+  a2.a1.a0.a1.a1.a0 = -73.0;
+  a2.a1.a0.a2 = 74;
+  a2.a1.a0.a3.a0.a0 = -75.0;
+  a2.a1.a0.a3.a1 = 76.0;
+  a2.a1.a0.a4 = 77;
+  a2.a1.a0.a5.a0.a0 = 78.0;
+  a2.a1.a0.a5.a1.a0 = -79.0;
+  a2.a1.a0.a6 = 80;
+  a2.a1.a1.a0.a0 = -81;
+  a2.a1.a1.a0.a1 = 82;
+  a2.a1.a1.a1.a0 = -83.0;
+  a2.a1.a2 = 84.0;
+  a2.a1.a3 = -85.0;
+  a2.a2.a0.a0 = 86;
+  a2.a2.a0.a1.a0.a0 = -87;
+  a2.a2.a0.a1.a0.a1 = 88;
+  a2.a2.a0.a1.a1.a0 = -89.0;
+  a2.a2.a0.a2 = 90;
+  a2.a2.a0.a3.a0.a0 = -91.0;
+  a2.a2.a0.a3.a1 = 92.0;
+  a2.a2.a0.a4 = 93;
+  a2.a2.a0.a5.a0.a0 = 94.0;
+  a2.a2.a0.a5.a1.a0 = -95.0;
+  a2.a2.a0.a6 = 96;
+  a2.a2.a1.a0.a0 = -97;
+  a2.a2.a1.a0.a1 = 98;
+  a2.a2.a1.a1.a0 = -99.0;
+  a2.a2.a2 = 100.0;
+  a2.a2.a3 = -101.0;
+  a2.a3 = 102.0;
+  a3.a0 = 103;
+  a3.a1.a0.a0 = 104;
+  a3.a1.a0.a1.a0.a0 = -105;
+  a3.a1.a0.a1.a0.a1 = 106;
+  a3.a1.a0.a1.a1.a0 = -107.0;
+  a3.a1.a0.a2 = 108;
+  a3.a1.a0.a3.a0.a0 = -109.0;
+  a3.a1.a0.a3.a1 = 110.0;
+  a3.a1.a0.a4 = 111;
+  a3.a1.a0.a5.a0.a0 = 112.0;
+  a3.a1.a0.a5.a1.a0 = -113.0;
+  a3.a1.a0.a6 = 114;
+  a3.a1.a1.a0.a0 = -115;
+  a3.a1.a1.a0.a1 = 116;
+  a3.a1.a1.a1.a0 = -117.0;
+  a3.a1.a2 = 118.0;
+  a3.a1.a3 = -119.0;
+  a3.a2.a0.a0 = 120;
+  a3.a2.a0.a1.a0.a0 = -121;
+  a3.a2.a0.a1.a0.a1 = 122;
+  a3.a2.a0.a1.a1.a0 = -123.0;
+  a3.a2.a0.a2 = 124;
+  a3.a2.a0.a3.a0.a0 = -125.0;
+  a3.a2.a0.a3.a1 = 126.0;
+  a3.a2.a0.a4 = 127;
+  a3.a2.a0.a5.a0.a0 = 128.0;
+  a3.a2.a0.a5.a1.a0 = -129.0;
+  a3.a2.a0.a6 = 130;
+  a3.a2.a1.a0.a0 = -131;
+  a3.a2.a1.a0.a1 = 132;
+  a3.a2.a1.a1.a0 = -133.0;
+  a3.a2.a2 = 134.0;
+  a3.a2.a3 = -135.0;
+  a3.a3 = 136.0;
+
+  final result = passStructNestedIrregularEvenBiggerx4(a0, a1, a2, a3);
+
+  print("result = $result");
+
+  Expect.approxEquals(1572.0, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
 }
 
 final returnStruct1ByteInt = ffiTestFunctions.lookupFunction<
@@ -5087,7 +5865,7 @@
 /// Especially for ffi callbacks.
 /// Struct is passed in int registers in most ABIs.
 void testReturnStructArgumentStruct1ByteInt() {
-  Struct1ByteInt a0 = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt a0 = calloc<Struct1ByteInt>().ref;
 
   a0.a0 = -1;
 
@@ -5097,7 +5875,7 @@
 
   Expect.equals(a0.a0, result.a0);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final returnStructArgumentInt32x8Struct1ByteInt =
@@ -5119,7 +5897,7 @@
   int a5;
   int a6;
   int a7;
-  Struct1ByteInt a8 = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt a8 = calloc<Struct1ByteInt>().ref;
 
   a0 = -1;
   a1 = 2;
@@ -5138,7 +5916,7 @@
 
   Expect.equals(a8.a0, result.a0);
 
-  free(a8.addressOf);
+  calloc.free(a8.addressOf);
 }
 
 final returnStructArgumentStruct8BytesHomogeneousFloat =
@@ -5152,8 +5930,7 @@
 /// Especially for ffi callbacks.
 /// Struct is passed in float registers in most ABIs.
 void testReturnStructArgumentStruct8BytesHomogeneousFloat() {
-  Struct8BytesHomogeneousFloat a0 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a0 = calloc<Struct8BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -5165,7 +5942,7 @@
   Expect.approxEquals(a0.a0, result.a0);
   Expect.approxEquals(a0.a1, result.a1);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final returnStructArgumentStruct20BytesHomogeneousInt32 =
@@ -5180,7 +5957,7 @@
 /// On arm64, both argument and return value are passed in by pointer.
 void testReturnStructArgumentStruct20BytesHomogeneousInt32() {
   Struct20BytesHomogeneousInt32 a0 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -5198,7 +5975,7 @@
   Expect.equals(a0.a3, result.a3);
   Expect.equals(a0.a4, result.a4);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final returnStructArgumentInt32x8Struct20BytesHomogeneou =
@@ -5221,7 +5998,7 @@
   int a6;
   int a7;
   Struct20BytesHomogeneousInt32 a8 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
 
   a0 = -1;
   a1 = 2;
@@ -5248,7 +6025,7 @@
   Expect.equals(a8.a3, result.a3);
   Expect.equals(a8.a4, result.a4);
 
-  free(a8.addressOf);
+  calloc.free(a8.addressOf);
 }
 
 final returnStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
@@ -5319,3 +6096,393 @@
   Expect.equals(a1, result.a1);
   Expect.equals(a2, result.a2);
 }
+
+final returnStruct8BytesNestedInt = ffiTestFunctions.lookupFunction<
+    Struct8BytesNestedInt Function(
+        Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16),
+    Struct8BytesNestedInt Function(Struct4BytesHomogeneousInt16,
+        Struct4BytesHomogeneousInt16)>("ReturnStruct8BytesNestedInt");
+
+/// Simple nested struct.
+void testReturnStruct8BytesNestedInt() {
+  Struct4BytesHomogeneousInt16 a0 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a1 = calloc<Struct4BytesHomogeneousInt16>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a1.a0 = -3;
+  a1.a1 = 4;
+
+  final result = returnStruct8BytesNestedInt(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.equals(a1.a0, result.a1.a0);
+  Expect.equals(a1.a1, result.a1.a1);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStruct8BytesNestedFloat = ffiTestFunctions.lookupFunction<
+    Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat),
+    Struct8BytesNestedFloat Function(
+        Struct4BytesFloat, Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat");
+
+/// Simple nested struct with floats.
+void testReturnStruct8BytesNestedFloat() {
+  Struct4BytesFloat a0 = calloc<Struct4BytesFloat>().ref;
+  Struct4BytesFloat a1 = calloc<Struct4BytesFloat>().ref;
+
+  a0.a0 = -1.0;
+  a1.a0 = 2.0;
+
+  final result = returnStruct8BytesNestedFloat(a0, a1);
+
+  print("result = $result");
+
+  Expect.approxEquals(a0.a0, result.a0.a0);
+  Expect.approxEquals(a1.a0, result.a1.a0);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStruct8BytesNestedFloat2 = ffiTestFunctions.lookupFunction<
+    Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float),
+    Struct8BytesNestedFloat2 Function(
+        Struct4BytesFloat, double)>("ReturnStruct8BytesNestedFloat2");
+
+/// The nesting is irregular, testing homogenous float rules on arm and arm64,
+/// and the fpu register usage on x64.
+void testReturnStruct8BytesNestedFloat2() {
+  Struct4BytesFloat a0 = calloc<Struct4BytesFloat>().ref;
+  double a1;
+
+  a0.a0 = -1.0;
+  a1 = 2.0;
+
+  final result = returnStruct8BytesNestedFloat2(a0, a1);
+
+  print("result = $result");
+
+  Expect.approxEquals(a0.a0, result.a0.a0);
+  Expect.approxEquals(a1, result.a1);
+
+  calloc.free(a0.addressOf);
+}
+
+final returnStruct8BytesNestedMixed = ffiTestFunctions.lookupFunction<
+    Struct8BytesNestedMixed Function(
+        Struct4BytesHomogeneousInt16, Struct4BytesFloat),
+    Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16,
+        Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed");
+
+/// Simple nested struct with mixed members.
+void testReturnStruct8BytesNestedMixed() {
+  Struct4BytesHomogeneousInt16 a0 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesFloat a1 = calloc<Struct4BytesFloat>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a1.a0 = -3.0;
+
+  final result = returnStruct8BytesNestedMixed(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.approxEquals(a1.a0, result.a1.a0);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStruct16BytesNestedInt = ffiTestFunctions.lookupFunction<
+    Struct16BytesNestedInt Function(
+        Struct8BytesNestedInt, Struct8BytesNestedInt),
+    Struct16BytesNestedInt Function(Struct8BytesNestedInt,
+        Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt");
+
+/// Deeper nested struct to test recursive member access.
+void testReturnStruct16BytesNestedInt() {
+  Struct8BytesNestedInt a0 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a1 = calloc<Struct8BytesNestedInt>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3;
+  a0.a1.a1 = 4;
+  a1.a0.a0 = -5;
+  a1.a0.a1 = 6;
+  a1.a1.a0 = -7;
+  a1.a1.a1 = 8;
+
+  final result = returnStruct16BytesNestedInt(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0.a0, result.a0.a0.a0);
+  Expect.equals(a0.a0.a1, result.a0.a0.a1);
+  Expect.equals(a0.a1.a0, result.a0.a1.a0);
+  Expect.equals(a0.a1.a1, result.a0.a1.a1);
+  Expect.equals(a1.a0.a0, result.a1.a0.a0);
+  Expect.equals(a1.a0.a1, result.a1.a0.a1);
+  Expect.equals(a1.a1.a0, result.a1.a1.a0);
+  Expect.equals(a1.a1.a1, result.a1.a1.a1);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStruct32BytesNestedInt = ffiTestFunctions.lookupFunction<
+    Struct32BytesNestedInt Function(
+        Struct16BytesNestedInt, Struct16BytesNestedInt),
+    Struct32BytesNestedInt Function(Struct16BytesNestedInt,
+        Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt");
+
+/// Even deeper nested struct to test recursive member access.
+void testReturnStruct32BytesNestedInt() {
+  Struct16BytesNestedInt a0 = calloc<Struct16BytesNestedInt>().ref;
+  Struct16BytesNestedInt a1 = calloc<Struct16BytesNestedInt>().ref;
+
+  a0.a0.a0.a0 = -1;
+  a0.a0.a0.a1 = 2;
+  a0.a0.a1.a0 = -3;
+  a0.a0.a1.a1 = 4;
+  a0.a1.a0.a0 = -5;
+  a0.a1.a0.a1 = 6;
+  a0.a1.a1.a0 = -7;
+  a0.a1.a1.a1 = 8;
+  a1.a0.a0.a0 = -9;
+  a1.a0.a0.a1 = 10;
+  a1.a0.a1.a0 = -11;
+  a1.a0.a1.a1 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15;
+  a1.a1.a1.a1 = 16;
+
+  final result = returnStruct32BytesNestedInt(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0);
+  Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1);
+  Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0);
+  Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1);
+  Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0);
+  Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1);
+  Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0);
+  Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1);
+  Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0);
+  Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1);
+  Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0);
+  Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1);
+  Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0);
+  Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1);
+  Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0);
+  Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStructNestedIntStructAlignmentInt16 =
+    ffiTestFunctions.lookupFunction<
+        StructNestedIntStructAlignmentInt16 Function(
+            StructAlignmentInt16, StructAlignmentInt16),
+        StructNestedIntStructAlignmentInt16 Function(StructAlignmentInt16,
+            StructAlignmentInt16)>("ReturnStructNestedIntStructAlignmentInt16");
+
+/// Test alignment and padding of nested struct with 16 byte int.
+void testReturnStructNestedIntStructAlignmentInt16() {
+  StructAlignmentInt16 a0 = calloc<StructAlignmentInt16>().ref;
+  StructAlignmentInt16 a1 = calloc<StructAlignmentInt16>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  final result = returnStructNestedIntStructAlignmentInt16(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.equals(a0.a2, result.a0.a2);
+  Expect.equals(a1.a0, result.a1.a0);
+  Expect.equals(a1.a1, result.a1.a1);
+  Expect.equals(a1.a2, result.a1.a2);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStructNestedIntStructAlignmentInt32 =
+    ffiTestFunctions.lookupFunction<
+        StructNestedIntStructAlignmentInt32 Function(
+            StructAlignmentInt32, StructAlignmentInt32),
+        StructNestedIntStructAlignmentInt32 Function(StructAlignmentInt32,
+            StructAlignmentInt32)>("ReturnStructNestedIntStructAlignmentInt32");
+
+/// Test alignment and padding of nested struct with 32 byte int.
+void testReturnStructNestedIntStructAlignmentInt32() {
+  StructAlignmentInt32 a0 = calloc<StructAlignmentInt32>().ref;
+  StructAlignmentInt32 a1 = calloc<StructAlignmentInt32>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  final result = returnStructNestedIntStructAlignmentInt32(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.equals(a0.a2, result.a0.a2);
+  Expect.equals(a1.a0, result.a1.a0);
+  Expect.equals(a1.a1, result.a1.a1);
+  Expect.equals(a1.a2, result.a1.a2);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStructNestedIntStructAlignmentInt64 =
+    ffiTestFunctions.lookupFunction<
+        StructNestedIntStructAlignmentInt64 Function(
+            StructAlignmentInt64, StructAlignmentInt64),
+        StructNestedIntStructAlignmentInt64 Function(StructAlignmentInt64,
+            StructAlignmentInt64)>("ReturnStructNestedIntStructAlignmentInt64");
+
+/// Test alignment and padding of nested struct with 64 byte int.
+void testReturnStructNestedIntStructAlignmentInt64() {
+  StructAlignmentInt64 a0 = calloc<StructAlignmentInt64>().ref;
+  StructAlignmentInt64 a1 = calloc<StructAlignmentInt64>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  final result = returnStructNestedIntStructAlignmentInt64(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.equals(a0.a2, result.a0.a2);
+  Expect.equals(a1.a0, result.a1.a0);
+  Expect.equals(a1.a1, result.a1.a1);
+  Expect.equals(a1.a2, result.a1.a2);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStructNestedIrregularEvenBigger = ffiTestFunctions.lookupFunction<
+    StructNestedIrregularEvenBigger Function(Uint64,
+        StructNestedIrregularBigger, StructNestedIrregularBigger, Double),
+    StructNestedIrregularEvenBigger Function(
+        int,
+        StructNestedIrregularBigger,
+        StructNestedIrregularBigger,
+        double)>("ReturnStructNestedIrregularEvenBigger");
+
+/// Return big irregular struct as smoke test.
+void testReturnStructNestedIrregularEvenBigger() {
+  int a0;
+  StructNestedIrregularBigger a1 = calloc<StructNestedIrregularBigger>().ref;
+  StructNestedIrregularBigger a2 = calloc<StructNestedIrregularBigger>().ref;
+  double a3;
+
+  a0 = 1;
+  a1.a0.a0 = 2;
+  a1.a0.a1.a0.a0 = -3;
+  a1.a0.a1.a0.a1 = 4;
+  a1.a0.a1.a1.a0 = -5.0;
+  a1.a0.a2 = 6;
+  a1.a0.a3.a0.a0 = -7.0;
+  a1.a0.a3.a1 = 8.0;
+  a1.a0.a4 = 9;
+  a1.a0.a5.a0.a0 = 10.0;
+  a1.a0.a5.a1.a0 = -11.0;
+  a1.a0.a6 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15.0;
+  a1.a2 = 16.0;
+  a1.a3 = -17.0;
+  a2.a0.a0 = 18;
+  a2.a0.a1.a0.a0 = -19;
+  a2.a0.a1.a0.a1 = 20;
+  a2.a0.a1.a1.a0 = -21.0;
+  a2.a0.a2 = 22;
+  a2.a0.a3.a0.a0 = -23.0;
+  a2.a0.a3.a1 = 24.0;
+  a2.a0.a4 = 25;
+  a2.a0.a5.a0.a0 = 26.0;
+  a2.a0.a5.a1.a0 = -27.0;
+  a2.a0.a6 = 28;
+  a2.a1.a0.a0 = -29;
+  a2.a1.a0.a1 = 30;
+  a2.a1.a1.a0 = -31.0;
+  a2.a2 = 32.0;
+  a2.a3 = -33.0;
+  a3 = 34.0;
+
+  final result = returnStructNestedIrregularEvenBigger(a0, a1, a2, a3);
+
+  print("result = $result");
+
+  Expect.equals(a0, result.a0);
+  Expect.equals(a1.a0.a0, result.a1.a0.a0);
+  Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0);
+  Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1);
+  Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0);
+  Expect.equals(a1.a0.a2, result.a1.a0.a2);
+  Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0);
+  Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1);
+  Expect.equals(a1.a0.a4, result.a1.a0.a4);
+  Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0);
+  Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0);
+  Expect.equals(a1.a0.a6, result.a1.a0.a6);
+  Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0);
+  Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1);
+  Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0);
+  Expect.approxEquals(a1.a2, result.a1.a2);
+  Expect.approxEquals(a1.a3, result.a1.a3);
+  Expect.equals(a2.a0.a0, result.a2.a0.a0);
+  Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0);
+  Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1);
+  Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0);
+  Expect.equals(a2.a0.a2, result.a2.a0.a2);
+  Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0);
+  Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1);
+  Expect.equals(a2.a0.a4, result.a2.a0.a4);
+  Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0);
+  Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0);
+  Expect.equals(a2.a0.a6, result.a2.a0.a6);
+  Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0);
+  Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1);
+  Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0);
+  Expect.approxEquals(a2.a2, result.a2.a2);
+  Expect.approxEquals(a2.a3, result.a2.a3);
+  Expect.approxEquals(a3, result.a3);
+
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+}
diff --git a/tests/ffi/function_structs_test.dart b/tests/ffi/function_structs_test.dart
index bf9ea5f..ade55fb 100644
--- a/tests/ffi/function_structs_test.dart
+++ b/tests/ffi/function_structs_test.dart
@@ -14,6 +14,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'coordinate.dart';
 import 'very_large_struct.dart';
 
@@ -33,8 +34,10 @@
       ffiTestFunctions.lookup("TransposeCoordinate");
   NativeCoordinateOp f1 = p1.asFunction();
 
-  Pointer<Coordinate> c1 = Coordinate.allocate(10.0, 20.0, nullptr).addressOf;
-  Pointer<Coordinate> c2 = Coordinate.allocate(42.0, 84.0, c1).addressOf;
+  Pointer<Coordinate> c1 =
+      Coordinate.allocate(calloc, 10.0, 20.0, nullptr).addressOf;
+  Pointer<Coordinate> c2 =
+      Coordinate.allocate(calloc, 42.0, 84.0, c1).addressOf;
   c1.ref.next = c2;
 
   Coordinate result = f1(c1).ref;
@@ -45,8 +48,8 @@
   Expect.approxEquals(42.0, result.x);
   Expect.approxEquals(84.0, result.y);
 
-  free(c1);
-  free(c2);
+  calloc.free(c1);
+  calloc.free(c2);
 }
 
 /// pass an array of structs to a c funtion
@@ -55,7 +58,7 @@
       ffiTestFunctions.lookup("CoordinateElemAt1");
   NativeCoordinateOp f1 = p1.asFunction();
 
-  Coordinate c1 = allocate<Coordinate>(count: 3).ref;
+  Coordinate c1 = calloc<Coordinate>(3).ref;
   Coordinate c2 = c1.addressOf[1];
   Coordinate c3 = c1.addressOf[2];
   c1.x = 10.0;
@@ -72,7 +75,7 @@
   Expect.approxEquals(20.0, result.x);
   Expect.approxEquals(20.0, result.y);
 
-  free(c1.addressOf);
+  calloc.free(c1.addressOf);
 }
 
 typedef VeryLargeStructSum = int Function(Pointer<VeryLargeStruct>);
@@ -83,7 +86,7 @@
       ffiTestFunctions.lookup("SumVeryLargeStruct");
   VeryLargeStructSum f = p1.asFunction();
 
-  VeryLargeStruct vls1 = allocate<VeryLargeStruct>(count: 2).ref;
+  VeryLargeStruct vls1 = calloc<VeryLargeStruct>(2).ref;
   VeryLargeStruct vls2 = vls1.addressOf[1];
   List<VeryLargeStruct> structs = [vls1, vls2];
   for (VeryLargeStruct struct in structs) {
@@ -114,5 +117,5 @@
   result = f(vls2.addressOf);
   Expect.equals(2048, result);
 
-  free(vls1.addressOf);
+  calloc.free(vls1.addressOf);
 }
diff --git a/tests/ffi/function_test.dart b/tests/ffi/function_test.dart
index bff456e..077be64 100644
--- a/tests/ffi/function_test.dart
+++ b/tests/ffi/function_test.dart
@@ -15,11 +15,12 @@
 
 import 'dart:ffi';
 
-import 'dylib_utils.dart';
-
 import "package:ffi/ffi.dart";
 import "package:expect/expect.dart";
 
+import 'calloc.dart';
+import 'dylib_utils.dart';
+
 void main() {
   for (int i = 0; i < 100; ++i) {
     testNativeFunctionFromCast();
@@ -50,11 +51,11 @@
 typedef GenericBinaryOp<T> = int Function(int, T);
 
 void testNativeFunctionFromCast() {
-  Pointer<IntPtr> p1 = allocate();
+  Pointer<IntPtr> p1 = calloc();
   Pointer<NativeFunction<NativeBinaryOp>> p2 = p1.cast();
   p2.asFunction<BinaryOp>();
   p2.asFunction<GenericBinaryOp<int>>();
-  free(p1);
+  calloc.free(p1);
 }
 
 typedef NativeQuadOpSigned = Int64 Function(Int8, Int16, Int32, Int64);
@@ -394,14 +395,14 @@
     .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
 
 void testNativeFunctionPointer() {
-  Pointer<Int64> p2 = allocate(count: 2);
+  Pointer<Int64> p2 = calloc(2);
   p2.value = 42;
   p2[1] = 1000;
   Pointer<Int64> result = assign1337Index1(p2);
   Expect.equals(1337, result.value);
   Expect.equals(1337, p2[1]);
   Expect.equals(p2.elementAt(1).address, result.address);
-  free(p2);
+  calloc.free(p2);
 }
 
 Int64PointerUnOp nullableInt64ElemAt1 = ffiTestFunctions
@@ -411,10 +412,10 @@
   Pointer<Int64> result = nullableInt64ElemAt1(nullptr);
   Expect.equals(result, nullptr);
 
-  Pointer<Int64> p2 = allocate(count: 2);
+  Pointer<Int64> p2 = calloc(2);
   result = nullableInt64ElemAt1(p2);
   Expect.notEquals(result, nullptr);
-  free(p2);
+  calloc.free(p2);
 }
 
 typedef NativeFloatPointerToBool = Uint8 Function(Pointer<Float>);
@@ -424,13 +425,13 @@
     NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
 
 void testFloatRounding() {
-  Pointer<Float> p2 = allocate();
+  Pointer<Float> p2 = calloc();
   p2.value = 1337.0;
 
   int result = isRoughly1337(p2);
   Expect.equals(1, result);
 
-  free(p2);
+  calloc.free(p2);
 }
 
 typedef NativeFloatToVoid = Void Function(Float);
diff --git a/tests/ffi/generator/c_types.dart b/tests/ffi/generator/c_types.dart
index f2948fa..56736bf5 100644
--- a/tests/ffi/generator/c_types.dart
+++ b/tests/ffi/generator/c_types.dart
@@ -140,11 +140,19 @@
   /// To disambiguate same size structs.
   final String suffix;
 
+  /// To override names.
+  final String overrideName;
+
   StructType(List<CType> memberTypes)
       : this.members = generateMemberNames(memberTypes),
-        this.suffix = "";
+        this.suffix = "",
+        this.overrideName = "";
   StructType.disambiguate(List<CType> memberTypes, this.suffix)
-      : this.members = generateMemberNames(memberTypes);
+      : this.members = generateMemberNames(memberTypes),
+        this.overrideName = "";
+  StructType.override(List<CType> memberTypes, this.overrideName)
+      : this.members = generateMemberNames(memberTypes),
+        this.suffix = "";
 
   List<CType> get memberTypes => members.map((a) => a.type).toList();
 
@@ -191,6 +199,9 @@
 
   String get name {
     String result = "Struct";
+    if (overrideName != "") {
+      return result + overrideName;
+    }
     if (hasSize) {
       result += "${size}Byte" + (size != 1 ? "s" : "");
     }
diff --git a/tests/ffi/generator/structs_by_value_tests_configuration.dart b/tests/ffi/generator/structs_by_value_tests_configuration.dart
index 46f5108..bc1b8a1 100644
--- a/tests/ffi/generator/structs_by_value_tests_configuration.dart
+++ b/tests/ffi/generator/structs_by_value_tests_configuration.dart
@@ -255,6 +255,41 @@
       int64,
       """
 Test alignment and padding of 64 byte int within struct."""),
+  FunctionType(List.filled(10, struct8bytesNestedInt), int64, """
+Simple nested struct. No alignment gaps on any architectures.
+10 arguments exhaust registers on all platforms."""),
+  FunctionType(List.filled(10, struct8bytesNestedFloat), float, """
+Simple nested struct. No alignment gaps on any architectures.
+10 arguments exhaust fpu registers on all platforms."""),
+  FunctionType(List.filled(10, struct8bytesNestedFloat2), float, """
+Simple nested struct. No alignment gaps on any architectures.
+10 arguments exhaust fpu registers on all platforms.
+The nesting is irregular, testing homogenous float rules on arm and arm64,
+and the fpu register usage on x64."""),
+  FunctionType(List.filled(10, struct8bytesNestedMixed), double_, """
+Simple nested struct. No alignment gaps on any architectures.
+10 arguments exhaust all registers on all platforms."""),
+  FunctionType(List.filled(2, struct16bytesNestedInt), int64, """
+Deeper nested struct to test recursive member access."""),
+  FunctionType(List.filled(2, struct32bytesNestedInt), int64, """
+Even deeper nested struct to test recursive member access."""),
+  FunctionType(
+      [structNestedAlignmentInt16],
+      int64,
+      """
+Test alignment and padding of nested struct with 16 byte int."""),
+  FunctionType(
+      [structNestedAlignmentInt32],
+      int64,
+      """
+Test alignment and padding of nested struct with 32 byte int."""),
+  FunctionType(
+      [structNestedAlignmentInt64],
+      int64,
+      """
+Test alignment and padding of nested struct with 64 byte int."""),
+  FunctionType(List.filled(4, structNestedEvenBigger), double_, """
+Return big irregular struct as smoke test."""),
   FunctionType(struct1byteInt.memberTypes, struct1byteInt, """
 Smallest struct with data."""),
   FunctionType(struct3bytesInt.memberTypes, struct3bytesInt, """
@@ -358,14 +393,39 @@
 Test alignment and padding of 32 byte int within struct."""),
   FunctionType(structAlignmentInt64.memberTypes, structAlignmentInt64, """
 Test alignment and padding of 64 byte int within struct."""),
+  FunctionType(struct8bytesNestedInt.memberTypes, struct8bytesNestedInt, """
+Simple nested struct."""),
+  FunctionType(struct8bytesNestedFloat.memberTypes, struct8bytesNestedFloat, """
+Simple nested struct with floats."""),
+  FunctionType(
+      struct8bytesNestedFloat2.memberTypes, struct8bytesNestedFloat2, """
+The nesting is irregular, testing homogenous float rules on arm and arm64,
+and the fpu register usage on x64."""),
+  FunctionType(struct8bytesNestedMixed.memberTypes, struct8bytesNestedMixed, """
+Simple nested struct with mixed members."""),
+  FunctionType(struct16bytesNestedInt.memberTypes, struct16bytesNestedInt, """
+Deeper nested struct to test recursive member access."""),
+  FunctionType(struct32bytesNestedInt.memberTypes, struct32bytesNestedInt, """
+Even deeper nested struct to test recursive member access."""),
+  FunctionType(
+      structNestedAlignmentInt16.memberTypes, structNestedAlignmentInt16, """
+Test alignment and padding of nested struct with 16 byte int."""),
+  FunctionType(
+      structNestedAlignmentInt32.memberTypes, structNestedAlignmentInt32, """
+Test alignment and padding of nested struct with 32 byte int."""),
+  FunctionType(
+      structNestedAlignmentInt64.memberTypes, structNestedAlignmentInt64, """
+Test alignment and padding of nested struct with 64 byte int."""),
+  FunctionType(structNestedEvenBigger.memberTypes, structNestedEvenBigger, """
+Return big irregular struct as smoke test."""),
 ];
 
 final structs = [
-  struct0bytes,
   struct1byteInt,
   struct3bytesInt,
   struct3bytesInt2,
   struct4bytesInt,
+  struct4bytesFloat,
   struct7bytesInt,
   struct7bytesInt2,
   struct8bytesInt,
@@ -387,15 +447,25 @@
   structAlignmentInt16,
   structAlignmentInt32,
   structAlignmentInt64,
+  struct8bytesNestedInt,
+  struct8bytesNestedFloat,
+  struct8bytesNestedFloat2,
+  struct8bytesNestedMixed,
+  struct16bytesNestedInt,
+  struct32bytesNestedInt,
+  structNestedAlignmentInt16,
+  structNestedAlignmentInt32,
+  structNestedAlignmentInt64,
+  structNestedBig,
+  structNestedBigger,
+  structNestedEvenBigger,
 ];
 
-/// Using empty structs is undefined behavior in C.
-final struct0bytes = StructType([]);
-
 final struct1byteInt = StructType([int8]);
 final struct3bytesInt = StructType(List.filled(3, uint8));
 final struct3bytesInt2 = StructType.disambiguate([int16, int8], "2ByteAligned");
 final struct4bytesInt = StructType([int16, int16]);
+final struct4bytesFloat = StructType([float]);
 final struct7bytesInt = StructType(List.filled(7, uint8));
 final struct7bytesInt2 =
     StructType.disambiguate([int32, int16, int8], "4ByteAligned");
@@ -444,3 +514,39 @@
 final structAlignmentInt16 = StructType([int8, int16, int8]);
 final structAlignmentInt32 = StructType([int8, int32, int8]);
 final structAlignmentInt64 = StructType([int8, int64, int8]);
+
+final struct8bytesNestedInt = StructType([struct4bytesInt, struct4bytesInt]);
+final struct8bytesNestedFloat =
+    StructType([struct4bytesFloat, struct4bytesFloat]);
+final struct8bytesNestedFloat2 =
+    StructType.disambiguate([struct4bytesFloat, float], "2");
+final struct8bytesNestedMixed =
+    StructType([struct4bytesInt, struct4bytesFloat]);
+
+final struct16bytesNestedInt =
+    StructType([struct8bytesNestedInt, struct8bytesNestedInt]);
+final struct32bytesNestedInt =
+    StructType([struct16bytesNestedInt, struct16bytesNestedInt]);
+
+final structNestedAlignmentInt16 = StructType.disambiguate(
+    List.filled(2, structAlignmentInt16), structAlignmentInt16.name);
+final structNestedAlignmentInt32 = StructType.disambiguate(
+    List.filled(2, structAlignmentInt32), structAlignmentInt32.name);
+final structNestedAlignmentInt64 = StructType.disambiguate(
+    List.filled(2, structAlignmentInt64), structAlignmentInt64.name);
+
+final structNestedBig = StructType.override([
+  uint16,
+  struct8bytesNestedMixed,
+  uint16,
+  struct8bytesNestedFloat2,
+  uint16,
+  struct8bytesNestedFloat,
+  uint16
+], "NestedIrregularBig");
+final structNestedBigger = StructType.override(
+    [structNestedBig, struct8bytesNestedMixed, float, double_],
+    "NestedIrregularBigger");
+final structNestedEvenBigger = StructType.override(
+    [uint64, structNestedBigger, structNestedBigger, double_],
+    "NestedIrregularEvenBigger");
diff --git a/tests/ffi/generator/structs_by_value_tests_generator.dart b/tests/ffi/generator/structs_by_value_tests_generator.dart
index f3f9f02..7bd7c83 100644
--- a/tests/ffi/generator/structs_by_value_tests_generator.dart
+++ b/tests/ffi/generator/structs_by_value_tests_generator.dart
@@ -197,7 +197,7 @@
         return "${dartType} ${variableName};\n";
 
       case StructType:
-        return "${dartType} ${variableName} = allocate<$dartType>().ref;\n";
+        return "${dartType} ${variableName} = calloc<$dartType>().ref;\n";
     }
 
     throw Exception("Not implemented for ${this.runtimeType}");
@@ -243,7 +243,7 @@
         return "";
 
       case StructType:
-        return "free($variableName.addressOf);\n";
+        return "calloc.free($variableName.addressOf);\n";
     }
 
     throw Exception("Not implemented for ${this.runtimeType}");
@@ -485,7 +485,7 @@
       case TestType.structReturn:
         // Allocate a struct.
         buildReturnValue = """
-        ${returnValue.dartType} result = allocate<${returnValue.dartType}>().ref;
+        ${returnValue.dartType} result = calloc<${returnValue.dartType}>().ref;
 
         ${arguments.copyValueStatements("${dartName}_", "result.")}
         """;
@@ -749,6 +749,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
@@ -801,6 +802,7 @@
 import "package:ffi/ffi.dart";
 
 import 'callback_tests_utils.dart';
+import 'calloc.dart';
 
 // Reuse the struct classes.
 import 'function_structs_by_value_generated_test.dart';
diff --git a/tests/ffi/regress_37254_test.dart b/tests/ffi/regress_37254_test.dart
index ce696af..62c71db 100644
--- a/tests/ffi/regress_37254_test.dart
+++ b/tests/ffi/regress_37254_test.dart
@@ -65,34 +65,36 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
+
 // ===== a.value = b ======
 // The tests follow table cells left to right, top to bottom.
 void store1() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
-  final Pointer<Int8> b = allocate<Int8>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
+  final Pointer<Int8> b = calloc<Int8>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store2() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
   final Pointer<NativeType> b =
-      allocate<Int8>(); // Reified Pointer<Int8> at runtime.
+      calloc<Int8>(); // Reified Pointer<Int8> at runtime.
 
   // Successful implicit downcast of argument at runtime.
   // Should succeed now, should statically be rejected when NNBD lands.
   a.value = b as Pointer<Int8>;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store3() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
-  final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
+  final Pointer<NativeType> b = calloc<Int8>().cast<Pointer<NativeType>>();
 
   // Failing implicit downcast of argument at runtime.
   // Should fail now at runtime, should statically be rejected when NNBD lands.
@@ -100,124 +102,124 @@
     a.value = b as Pointer<Int8>;
   });
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store4() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
 
-  final Pointer<Int8> b = allocate<Int8>();
+  final Pointer<Int8> b = calloc<Int8>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store5() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
 
   final Pointer<NativeType> b =
-      allocate<Int8>(); // Reified as Pointer<Int8> at runtime.
+      calloc<Int8>(); // Reified as Pointer<Int8> at runtime.
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store6() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
-  final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
+  final Pointer<NativeType> b = calloc<Int8>().cast<Pointer<NativeType>>();
 
   // Fails on type check of argument.
   Expect.throws(() {
     a.value = b;
   });
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store7() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
-  final Pointer<Int8> b = allocate<Int8>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
+  final Pointer<Int8> b = calloc<Int8>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store8() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
 
   // Reified as Pointer<Int8> at runtime.
-  final Pointer<NativeType> b = allocate<Int8>();
+  final Pointer<NativeType> b = calloc<Int8>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store9() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
-  final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
+  final Pointer<NativeType> b = calloc<Int8>().cast<Pointer<NativeType>>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 // ====== b = a.value ======
 // The tests follow table cells left to right, top to bottom.
 void load1() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
 
   Pointer<Int8> b = a.value;
   Expect.type<Pointer<Int8>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void load2() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
 
   Pointer<NativeType> b = a.value;
   Expect.type<Pointer<Int8>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void load3() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
 
   Pointer<Int8> b = a.value as Pointer<Int8>;
   Expect.type<Pointer<Int8>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void load4() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
 
   // Return value runtime type is Pointer<Int8>.
   Pointer<NativeType> b = a.value;
   Expect.type<Pointer<Int8>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void load5() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
 
   // Failing implicit downcast of return value at runtime.
   // Should fail now at runtime, should statically be rejected when NNBD lands.
@@ -225,16 +227,16 @@
     Pointer<Int8> b = a.value as Pointer<Int8>;
   });
 
-  free(a);
+  calloc.free(a);
 }
 
 void load6() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
 
   Pointer<NativeType> b = a.value;
   Expect.type<Pointer<NativeType>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void main() {
diff --git a/tests/ffi/regress_39885_test.dart b/tests/ffi/regress_39885_test.dart
index 7d960f2..ef73ca7 100644
--- a/tests/ffi/regress_39885_test.dart
+++ b/tests/ffi/regress_39885_test.dart
@@ -3,12 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:ffi';
-import "package:ffi/ffi.dart" show allocate, free;
+
+import "package:ffi/ffi.dart";
+
+import 'calloc.dart';
 
 main() {
-  final data = allocate<Uint8>(count: 3);
+  final data = calloc<Uint8>(3);
   for (int i = 0; i < 3; ++i) {
     data.elementAt(i).value = 1;
   }
-  free(data);
+  calloc.free(data);
 }
diff --git a/tests/ffi/regress_43016_test.dart b/tests/ffi/regress_43016_test.dart
index f1489e0..db3d816 100644
--- a/tests/ffi/regress_43016_test.dart
+++ b/tests/ffi/regress_43016_test.dart
@@ -10,7 +10,10 @@
 
 import 'dylib_utils.dart';
 
-class MyStruct extends Struct {}
+class MyStruct extends Struct {
+  @Int8()
+  external int a;
+}
 
 typedef _c_pass_struct = Int32 Function(Pointer<MyStruct>);
 
diff --git a/tests/ffi/regress_43693_test.dart b/tests/ffi/regress_43693_test.dart
index a34e8f8..64b48bf 100644
--- a/tests/ffi/regress_43693_test.dart
+++ b/tests/ffi/regress_43693_test.dart
@@ -9,6 +9,7 @@
 import 'package:ffi/ffi.dart';
 import 'package:expect/expect.dart';
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 class Struct43693 extends Struct {
@@ -27,10 +28,10 @@
 final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
 
 void main() {
-  final myStructs = allocate<Struct43693>();
+  final myStructs = calloc<Struct43693>();
   myStructs[0].somePtr = nullptr;
   myStructs[0].someValue = 0xAAAAAAAABBBBBBBB;
   final result = readMyStructSomeValue(myStructs);
   Expect.equals(0xAAAAAAAABBBBBBBB, result);
-  free(myStructs);
+  calloc.free(myStructs);
 }
diff --git a/tests/ffi/structs_nested_test.dart b/tests/ffi/structs_nested_test.dart
new file mode 100644
index 0000000..2d5208d
--- /dev/null
+++ b/tests/ffi/structs_nested_test.dart
@@ -0,0 +1,106 @@
+// 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.
+//
+// This tests the non trampoline aspects of nested structs.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'calloc.dart';
+import 'dylib_utils.dart';
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+void main() {
+  for (int i = 0; i < 10; ++i) {
+    testSizeOf();
+    testAllocate();
+    testRead();
+    testWrite();
+    testCopy();
+  }
+}
+
+class Struct4BytesHomogeneousInt16 extends Struct {
+  @Int16()
+  external int a0;
+
+  @Int16()
+  external int a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesNestedInt extends Struct {
+  external Struct4BytesHomogeneousInt16 a0;
+
+  external Struct4BytesHomogeneousInt16 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+void testSizeOf() {
+  print(sizeOf<Struct8BytesNestedInt>());
+  Expect.equals(8, sizeOf<Struct8BytesNestedInt>());
+}
+
+void testAllocate() {
+  final p = calloc<Struct8BytesNestedInt>();
+  Expect.type<Pointer<Struct8BytesNestedInt>>(p);
+  print(p);
+  calloc.free(p);
+}
+
+/// Test that reading does not segfault, even uninitialized.
+void testRead() {
+  print("read");
+  final p = calloc<Struct8BytesNestedInt>();
+  print(p);
+  print(p.ref.runtimeType);
+  print(p.ref.addressOf);
+  print(p.ref.addressOf.address);
+  print(p.ref.a0.runtimeType);
+  print(p.ref.a0.addressOf);
+  print(p.ref.a0.a0);
+  calloc.free(p);
+  print("read");
+}
+
+void testWrite() {
+  print("write");
+  final p = calloc<Struct8BytesNestedInt>(2);
+  p[0].a0.a0 = 12;
+  p[0].a0.a1 = 13;
+  p[0].a1.a0 = 14;
+  p[0].a1.a1 = 15;
+  p[1].a0.a0 = 16;
+  p[1].a0.a1 = 17;
+  p[1].a1.a0 = 18;
+  p[1].a1.a1 = 19;
+  Expect.equals(12, p[0].a0.a0);
+  Expect.equals(13, p[0].a0.a1);
+  Expect.equals(14, p[0].a1.a0);
+  Expect.equals(15, p[0].a1.a1);
+  Expect.equals(16, p[1].a0.a0);
+  Expect.equals(17, p[1].a0.a1);
+  Expect.equals(18, p[1].a1.a0);
+  Expect.equals(19, p[1].a1.a1);
+  calloc.free(p);
+  print("written");
+}
+
+void testCopy() {
+  print("copy");
+  final p = calloc<Struct8BytesNestedInt>();
+  p.ref.a0.a0 = 12;
+  p.ref.a0.a1 = 13;
+  p.ref.a1 = p.ref.a0;
+  Expect.equals(12, p.ref.a1.a0);
+  Expect.equals(13, p.ref.a1.a1);
+  calloc.free(p);
+  print("copied");
+}
diff --git a/tests/ffi/structs_nnbd_workaround_test.dart b/tests/ffi/structs_nnbd_workaround_test.dart
index 6501faf..06c6f29 100644
--- a/tests/ffi/structs_nnbd_workaround_test.dart
+++ b/tests/ffi/structs_nnbd_workaround_test.dart
@@ -11,6 +11,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'coordinate_nnbd_workaround.dart';
 
 void main() {
@@ -25,9 +26,12 @@
 
 /// allocates each coordinate separately in c memory
 void testStructAllocate() {
-  Pointer<Coordinate> c1 = Coordinate.allocate(10.0, 10.0, nullptr).addressOf;
-  Pointer<Coordinate> c2 = Coordinate.allocate(20.0, 20.0, c1).addressOf;
-  Pointer<Coordinate> c3 = Coordinate.allocate(30.0, 30.0, c2).addressOf;
+  Pointer<Coordinate> c1 =
+      Coordinate.allocate(calloc, 10.0, 10.0, nullptr).addressOf;
+  Pointer<Coordinate> c2 =
+      Coordinate.allocate(calloc, 20.0, 20.0, c1).addressOf;
+  Pointer<Coordinate> c3 =
+      Coordinate.allocate(calloc, 30.0, 30.0, c2).addressOf;
   c1.ref.next = c3;
 
   Coordinate currentCoordinate = c1.ref;
@@ -39,14 +43,14 @@
   currentCoordinate = currentCoordinate.next.ref;
   Expect.equals(10.0, currentCoordinate.x);
 
-  free(c1);
-  free(c2);
-  free(c3);
+  calloc.free(c1);
+  calloc.free(c2);
+  calloc.free(c3);
 }
 
 /// allocates coordinates consecutively in c memory
 void testStructFromAddress() {
-  Pointer<Coordinate> c1 = allocate(count: 3);
+  Pointer<Coordinate> c1 = calloc(3);
   Pointer<Coordinate> c2 = c1.elementAt(1);
   Pointer<Coordinate> c3 = c1.elementAt(2);
   c1.ref
@@ -71,30 +75,30 @@
   currentCoordinate = currentCoordinate.next.ref;
   Expect.equals(10.0, currentCoordinate.x);
 
-  free(c1);
+  calloc.free(c1);
 }
 
 void testStructWithNulls() {
   Pointer<Coordinate> coordinate =
-      Coordinate.allocate(10.0, 10.0, nullptr).addressOf;
+      Coordinate.allocate(calloc, 10.0, 10.0, nullptr).addressOf;
   Expect.equals(coordinate.ref.next, nullptr);
   coordinate.ref.next = coordinate;
   Expect.notEquals(coordinate.ref.next, nullptr);
   coordinate.ref.next = nullptr;
   Expect.equals(coordinate.ref.next, nullptr);
-  free(coordinate);
+  calloc.free(coordinate);
 }
 
 void testTypeTest() {
-  Coordinate c = Coordinate.allocate(10, 10, nullptr);
+  Coordinate c = Coordinate.allocate(calloc, 10, 10, nullptr);
   Expect.isTrue(c is Struct);
   Expect.isTrue(c.addressOf is Pointer<Coordinate>);
-  free(c.addressOf);
+  calloc.free(c.addressOf);
 }
 
 void testUtf8() {
   final String test = 'Hasta Mañana';
   final Pointer<Utf8> medium = Utf8.toUtf8(test);
   Expect.equals(test, Utf8.fromUtf8(medium));
-  free(medium);
+  calloc.free(medium);
 }
diff --git a/tests/ffi/structs_test.dart b/tests/ffi/structs_test.dart
index 83e617d..6bc1ed1 100644
--- a/tests/ffi/structs_test.dart
+++ b/tests/ffi/structs_test.dart
@@ -11,9 +11,10 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-import 'ffi_test_helpers.dart';
+import 'calloc.dart';
 import 'coordinate_bare.dart' as bare;
 import 'coordinate.dart';
+import 'ffi_test_helpers.dart';
 
 void main() {
   for (int i = 0; i < 100; i++) {
@@ -28,9 +29,12 @@
 
 /// allocates each coordinate separately in c memory
 void testStructAllocate() {
-  Pointer<Coordinate> c1 = Coordinate.allocate(10.0, 10.0, nullptr).addressOf;
-  Pointer<Coordinate> c2 = Coordinate.allocate(20.0, 20.0, c1).addressOf;
-  Pointer<Coordinate> c3 = Coordinate.allocate(30.0, 30.0, c2).addressOf;
+  Pointer<Coordinate> c1 =
+      Coordinate.allocate(calloc, 10.0, 10.0, nullptr).addressOf;
+  Pointer<Coordinate> c2 =
+      Coordinate.allocate(calloc, 20.0, 20.0, c1).addressOf;
+  Pointer<Coordinate> c3 =
+      Coordinate.allocate(calloc, 30.0, 30.0, c2).addressOf;
   c1.ref.next = c3;
 
   Coordinate currentCoordinate = c1.ref;
@@ -42,14 +46,14 @@
   currentCoordinate = currentCoordinate.next.ref;
   Expect.equals(10.0, currentCoordinate.x);
 
-  free(c1);
-  free(c2);
-  free(c3);
+  calloc.free(c1);
+  calloc.free(c2);
+  calloc.free(c3);
 }
 
 /// allocates coordinates consecutively in c memory
 void testStructFromAddress() {
-  Pointer<Coordinate> c1 = allocate(count: 3);
+  Pointer<Coordinate> c1 = calloc(3);
   Pointer<Coordinate> c2 = c1.elementAt(1);
   Pointer<Coordinate> c3 = c1.elementAt(2);
   c1.ref
@@ -74,24 +78,24 @@
   currentCoordinate = currentCoordinate.next.ref;
   Expect.equals(10.0, currentCoordinate.x);
 
-  free(c1);
+  calloc.free(c1);
 }
 
 void testStructWithNulls() {
   Pointer<Coordinate> coordinate =
-      Coordinate.allocate(10.0, 10.0, nullptr).addressOf;
+      Coordinate.allocate(calloc, 10.0, 10.0, nullptr).addressOf;
   Expect.equals(coordinate.ref.next, nullptr);
   coordinate.ref.next = coordinate;
   Expect.notEquals(coordinate.ref.next, nullptr);
   coordinate.ref.next = nullptr;
   Expect.equals(coordinate.ref.next, nullptr);
-  free(coordinate);
+  calloc.free(coordinate);
 }
 
 void testBareStruct() {
   int structSize = sizeOf<Double>() * 2 + sizeOf<IntPtr>();
   bare.Coordinate c1 =
-      allocate<Uint8>(count: structSize * 3).cast<bare.Coordinate>().ref;
+      calloc<Uint8>(structSize * 3).cast<bare.Coordinate>().ref;
   bare.Coordinate c2 =
       c1.addressOf.offsetBy(structSize).cast<bare.Coordinate>().ref;
   bare.Coordinate c3 =
@@ -115,19 +119,19 @@
   currentCoordinate = currentCoordinate.next.ref;
   Expect.equals(10.0, currentCoordinate.x);
 
-  free(c1.addressOf);
+  calloc.free(c1.addressOf);
 }
 
 void testTypeTest() {
-  Coordinate c = Coordinate.allocate(10, 10, nullptr);
+  Coordinate c = Coordinate.allocate(calloc, 10, 10, nullptr);
   Expect.isTrue(c is Struct);
   Expect.isTrue(c.addressOf is Pointer<Coordinate>);
-  free(c.addressOf);
+  calloc.free(c.addressOf);
 }
 
 void testUtf8() {
   final String test = 'Hasta Mañana';
   final Pointer<Utf8> medium = Utf8.toUtf8(test);
   Expect.equals(test, Utf8.fromUtf8(medium));
-  free(medium);
+  calloc.free(medium);
 }
diff --git a/tests/ffi/variance_function_test.dart b/tests/ffi/variance_function_test.dart
index 539c245..3db0147 100644
--- a/tests/ffi/variance_function_test.dart
+++ b/tests/ffi/variance_function_test.dart
@@ -12,11 +12,12 @@
 
 import 'dart:ffi';
 
-import 'dylib_utils.dart';
-
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
+import 'dylib_utils.dart';
+
 typedef Int64PointerParamOpDart = void Function(Pointer<Int64>);
 typedef Int64PointerParamOp = Void Function(Pointer<Int64>);
 typedef NaTyPointerParamOpDart = void Function(Pointer<NativeType>);
@@ -38,19 +39,19 @@
   final fp =
       ffiTestFunctions.lookup<NativeFunction<Int64PointerParamOp>>(paramOpName);
   final f = fp.asFunction<Int64PointerParamOpDart>();
-  final arg = allocate<Int64>();
+  final arg = calloc<Int64>();
   f(arg);
-  free(arg);
+  calloc.free(arg);
 }
 
 void paramInvariant2() {
   final fp =
       ffiTestFunctions.lookup<NativeFunction<NaTyPointerParamOp>>(paramOpName);
   final f = fp.asFunction<NaTyPointerParamOpDart>();
-  final arg = allocate<Int64>().cast<NativeType>();
+  final arg = calloc<Int64>().cast<NativeType>();
   Expect.type<Pointer<NativeType>>(arg);
   f(arg);
-  free(arg);
+  calloc.free(arg);
 }
 
 // Pass a statically and dynamically subtyped argument.
@@ -58,10 +59,10 @@
   final fp =
       ffiTestFunctions.lookup<NativeFunction<NaTyPointerParamOp>>(paramOpName);
   final f = fp.asFunction<NaTyPointerParamOpDart>();
-  final arg = allocate<Int64>();
+  final arg = calloc<Int64>();
   Expect.type<Pointer<Int64>>(arg);
   f(arg);
-  free(arg);
+  calloc.free(arg);
 }
 
 // Pass a statically subtyped but dynamically invariant argument.
@@ -69,10 +70,10 @@
   final fp =
       ffiTestFunctions.lookup<NativeFunction<NaTyPointerParamOp>>(paramOpName);
   final f = fp.asFunction<NaTyPointerParamOpDart>();
-  final Pointer<NativeType> arg = allocate<Int64>();
+  final Pointer<NativeType> arg = calloc<Int64>();
   Expect.type<Pointer<Int64>>(arg);
   f(arg);
-  free(arg);
+  calloc.free(arg);
 }
 
 void returnInvariant1() {
@@ -220,7 +221,7 @@
 }
 
 void fromFunctionTests() {
-  data = allocate();
+  data = calloc();
   for (int i = 0; i < 100; ++i) {
     callbackParamInvariant1(); // Pointer<Int64> invariant
     callbackParamInvariant2(); // Pointer<NativeType> invariant
@@ -229,7 +230,7 @@
     callbackReturnInvariant1(); // Pointer<Int64> invariant
     callbackReturnInvariant2(); // Pointer<NativeType> invariant
   }
-  free(data);
+  calloc.free(data);
 }
 
 void main() {
diff --git a/tests/ffi/vmspecific_enable_ffi_test.dart b/tests/ffi/vmspecific_enable_ffi_test.dart
index f44753d..ce90607 100644
--- a/tests/ffi/vmspecific_enable_ffi_test.dart
+++ b/tests/ffi/vmspecific_enable_ffi_test.dart
@@ -7,11 +7,14 @@
 // VMOptions=--enable-ffi=false
 
 import 'dart:ffi'; //# 01: compile-time error
+
 import 'package:ffi/ffi.dart'; //# 01: compile-time error
 
+import 'calloc.dart'; //# 01: compile-time error
+
 void main() {
   Pointer<Int8> p = //# 01: compile-time error
-      allocate(); //# 01: compile-time error
+      calloc(); //# 01: compile-time error
   print(p.address); //# 01: compile-time error
-  free(p); //# 01: compile-time error
+  calloc.free(p); //# 01: compile-time error
 }
diff --git a/tests/ffi/vmspecific_regress_37100_test.dart b/tests/ffi/vmspecific_regress_37100_test.dart
index a819503..ef4c614 100644
--- a/tests/ffi/vmspecific_regress_37100_test.dart
+++ b/tests/ffi/vmspecific_regress_37100_test.dart
@@ -10,7 +10,7 @@
 
 import 'dylib_utils.dart';
 
-class EVP_MD extends Struct {}
+class EVP_MD extends Opaque {}
 
 DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
 
diff --git a/tests/ffi/vmspecific_regress_38993_test.dart b/tests/ffi/vmspecific_regress_38993_test.dart
index 8c9972f..4391b00 100644
--- a/tests/ffi/vmspecific_regress_38993_test.dart
+++ b/tests/ffi/vmspecific_regress_38993_test.dart
@@ -8,6 +8,8 @@
 
 class C extends Struct {
   dynamic x; //# 1: compile-time error
+
+  external Pointer notEmpty;
 }
 
 main() {}
diff --git a/tests/ffi/vmspecific_static_checks_test.dart b/tests/ffi/vmspecific_static_checks_test.dart
index 8513885..94a11e1 100644
--- a/tests/ffi/vmspecific_static_checks_test.dart
+++ b/tests/ffi/vmspecific_static_checks_test.dart
@@ -10,6 +10,7 @@
 
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 void main() {
@@ -40,11 +41,26 @@
   testLookupFunctionGeneric2();
   testLookupFunctionWrongNativeFunctionSignature();
   testLookupFunctionTypeMismatch();
+  testLookupFunctionPointervoid();
+  testLookupFunctionPointerNFdyn();
   testNativeFunctionSignatureInvalidReturn();
   testNativeFunctionSignatureInvalidParam();
   testNativeFunctionSignatureInvalidOptionalNamed();
   testNativeFunctionSignatureInvalidOptionalPositional();
   testHandleVariance();
+  testEmptyStructLookupFunctionArgument();
+  testEmptyStructLookupFunctionReturn();
+  testEmptyStructAsFunctionArgument();
+  testEmptyStructAsFunctionReturn();
+  testEmptyStructFromFunctionArgument();
+  testEmptyStructFromFunctionReturn();
+  testAllocateGeneric();
+  testAllocateNativeType();
+  testRefStruct();
+  testSizeOfGeneric();
+  testSizeOfNativeType();
+  testElementAtGeneric();
+  testElementAtNativeType();
 }
 
 typedef Int8UnOp = Int8 Function(Int8);
@@ -57,20 +73,20 @@
     return result;
   }
 
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   p.value = 123;
   Pointer loseType = p;
   generic(loseType);
-  free(p);
+  calloc.free(p);
 }
 
 void testGetGeneric2() {
   T? generic<T extends Object>() {
-    Pointer<Int8> p = allocate();
+    Pointer<Int8> p = calloc();
     p.value = 123;
     T? result;
     result = p.value; //# 21: compile-time error
-    free(p);
+    calloc.free(p);
     return result;
   }
 
@@ -78,12 +94,12 @@
 }
 
 void testGetVoid() {
-  Pointer<IntPtr> p1 = allocate();
+  Pointer<IntPtr> p1 = calloc();
   Pointer<Void> p2 = p1.cast();
 
   p2.value; //# 22: compile-time error
 
-  free(p1);
+  calloc.free(p1);
 }
 
 void testGetNativeFunction() {
@@ -96,14 +112,14 @@
 }
 
 void testGetTypeMismatch() {
-  Pointer<Pointer<Int16>> p = allocate();
+  Pointer<Pointer<Int16>> p = calloc();
   Pointer<Int16> typedNull = nullptr;
   p.value = typedNull;
 
   // this fails to compile due to type mismatch
   Pointer<Int8> p2 = p.value; //# 25: compile-time error
 
-  free(p);
+  calloc.free(p);
 }
 
 void testSetGeneric() {
@@ -111,30 +127,30 @@
     p.value = 123; //# 26: compile-time error
   }
 
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   p.value = 123;
   Pointer loseType = p;
   generic(loseType);
-  free(p);
+  calloc.free(p);
 }
 
 void testSetGeneric2() {
   void generic<T extends Object>(T arg) {
-    Pointer<Int8> p = allocate();
+    Pointer<Int8> p = calloc();
     p.value = arg; //# 27: compile-time error
-    free(p);
+    calloc.free(p);
   }
 
   generic<int>(123);
 }
 
 void testSetVoid() {
-  Pointer<IntPtr> p1 = allocate();
+  Pointer<IntPtr> p1 = calloc();
   Pointer<Void> p2 = p1.cast();
 
   p2.value = 1234; //# 28: compile-time error
 
-  free(p1);
+  calloc.free(p1);
 }
 
 void testSetNativeFunction() {
@@ -149,16 +165,16 @@
 
 void testSetTypeMismatch() {
   // the pointer to pointer types must match up
-  Pointer<Int8> pHelper = allocate();
+  Pointer<Int8> pHelper = calloc();
   pHelper.value = 123;
 
-  Pointer<Pointer<Int16>> p = allocate();
+  Pointer<Pointer<Int16>> p = calloc();
 
   // this fails to compile due to type mismatch
   p.value = pHelper; //# 40: compile-time error
 
-  free(pHelper);
-  free(p);
+  calloc.free(pHelper);
+  calloc.free(p);
 }
 
 void testAsFunctionGeneric() {
@@ -285,6 +301,24 @@
   l.lookupFunction<NativeDoubleUnOp, IntUnOp>("cos"); //# 18: compile-time error
 }
 
+typedef PointervoidN = Void Function(Pointer<void>);
+typedef PointervoidD = void Function(Pointer<void>);
+
+void testLookupFunctionPointervoid() {
+  DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
+  // TODO(https://dartbug.com/44593): This should be a compile-time error in CFE.
+  // l.lookupFunction<PointervoidN, PointervoidD>("cos");
+}
+
+typedef PointerNFdynN = Void Function(Pointer<NativeFunction>);
+typedef PointerNFdynD = void Function(Pointer<NativeFunction>);
+
+void testLookupFunctionPointerNFdyn() {
+  DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
+  // TODO(https://dartbug.com/44594): Should this be an error or not?
+  // l.lookupFunction<PointerNFdynN, PointerNFdynD>("cos");
+}
+
 // TODO(dacoharkes): make the next 4 test compile errors
 typedef Invalid1 = int Function(Int8);
 typedef Invalid2 = Int8 Function(int);
@@ -329,24 +363,32 @@
 class TestStruct5 extends Struct {
   @Int64() //# 54: compile-time error
   external double z; //# 54: compile-time error
+
+  external Pointer notEmpty;
 }
 
 // error on annotation not matching up
 class TestStruct6 extends Struct {
   @Void() //# 55: compile-time error
   external double z; //# 55: compile-time error
+
+  external Pointer notEmpty;
 }
 
 // error on annotation not matching up
 class TestStruct7 extends Struct {
   @NativeType() //# 56: compile-time error
   external double z; //# 56: compile-time error
+
+  external Pointer notEmpty;
 }
 
 // error on field initializer on field
 class TestStruct8 extends Struct {
   @Double() //# 57: compile-time error
   double z = 10.0; //# 57: compile-time error
+
+  external Pointer notEmpty;
 }
 
 // error on field initializer in constructor
@@ -354,6 +396,8 @@
   @Double() //# 58: compile-time error
   double z; //# 58: compile-time error
 
+  external Pointer notEmpty;
+
   TestStruct9() : z = 0.0 {} //# 58: compile-time error
 }
 
@@ -366,6 +410,8 @@
 class TestStruct12 extends Struct {
   @Pointer //# 61: compile-time error
   external TestStruct9 struct; //# 61: compile-time error
+
+  external Pointer notEmpty;
 }
 
 class DummyAnnotation {
@@ -449,6 +495,8 @@
 
 class IStruct implements Struct {} //# 815: compile-time error
 
+class IOpaque implements Opaque {} //# 816: compile-time error
+
 class MyClass {
   int x;
   MyClass(this.x);
@@ -469,10 +517,147 @@
 }
 
 class TestStruct1001 extends Struct {
-  Handle handle; //# 1001: compile-time error
+  external Handle handle; //# 1001: compile-time error
+
+  external Pointer notEmpty;
 }
 
 class TestStruct1002 extends Struct {
   @Handle() //# 1002: compile-time error
-  Object handle; //# 1002: compile-time error
+  external Object handle; //# 1002: compile-time error
+
+  external Pointer notEmpty;
+}
+
+class EmptyStruct extends Struct {} //# 1099: ok
+
+class EmptyStruct extends Struct {} //# 1100: compile-time error
+
+void testEmptyStructLookupFunctionArgument() {
+  testLibrary.lookupFunction< //# 1100: compile-time error
+      Void Function(EmptyStruct), //# 1100: compile-time error
+      void Function(EmptyStruct)>("DoesNotExist"); //# 1100: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1101: compile-time error
+
+void testEmptyStructLookupFunctionReturn() {
+  testLibrary.lookupFunction< //# 1101: compile-time error
+      EmptyStruct Function(), //# 1101: compile-time error
+      EmptyStruct Function()>("DoesNotExist"); //# 1101: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1102: compile-time error
+
+void testEmptyStructAsFunctionArgument() {
+  final Pointer< //# 1102: compile-time error
+          NativeFunction< //# 1102: compile-time error
+              Void Function(EmptyStruct)>> //# 1102: compile-time error
+      pointer = Pointer.fromAddress(1234); //# 1102: compile-time error
+  pointer.asFunction<void Function(EmptyStruct)>(); //# 1102: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1103: compile-time error
+
+void testEmptyStructAsFunctionReturn() {
+  final Pointer< //# 1103: compile-time error
+          NativeFunction<EmptyStruct Function()>> //# 1103: compile-time error
+      pointer = Pointer.fromAddress(1234); //# 1103: compile-time error
+  pointer.asFunction<EmptyStruct Function()>(); //# 1103: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1104: compile-time error
+
+void _consumeEmptyStruct(EmptyStruct e) => //# 1104: compile-time error
+    print(e); //# 1104: compile-time error
+
+void testEmptyStructFromFunctionArgument() {
+  Pointer.fromFunction<Void Function(EmptyStruct)>(//# 1104: compile-time error
+      _consumeEmptyStruct); //# 1104: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1105: compile-time error
+
+EmptyStruct _returnEmptyStruct() => EmptyStruct(); //# 1105: compile-time error
+
+void testEmptyStructFromFunctionReturn() {
+  Pointer.fromFunction<EmptyStruct Function()>(//# 1105: compile-time error
+      _returnEmptyStruct); //# 1105: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1106: compile-time error
+
+class HasNestedEmptyStruct extends Struct {
+  external EmptyStruct nestedEmptyStruct; //# 1106: compile-time error
+
+  external Pointer notEmpty;
+}
+
+void testAllocateGeneric() {
+  Pointer<T> generic<T extends NativeType>() {
+    Pointer<T> pointer = nullptr;
+    pointer = calloc(); //# 1320: compile-time error
+    return pointer;
+  }
+
+  Pointer p = generic<Int64>();
+}
+
+void testAllocateNativeType() {
+  calloc(); //# 1321: compile-time error
+}
+
+void testRefStruct() {
+  final myStructPointer = calloc<TestStruct13>();
+  Pointer<Struct> structPointer = myStructPointer;
+  structPointer.ref; //# 1330: ok
+  calloc.free(myStructPointer);
+}
+
+T genericRef<T extends Struct>(Pointer<T> p) => //# 1200: ok
+    p.ref; //# 1200: ok
+
+T genericRef2<T extends Struct>(Pointer<T> p) => //# 1201: ok
+    p.cast<T>().ref; //# 1201: ok
+
+T genericRef3<T extends Struct>(Pointer<T> p) => //# 1202: ok
+    p[0]; //# 1202: ok
+
+void testSizeOfGeneric() {
+  int generic<T extends Pointer>() {
+    int size = sizeOf<IntPtr>();
+    size = sizeOf<T>(); //# 1300: ok
+    return size;
+  }
+
+  int size = generic<Pointer<Int64>>();
+}
+
+void testSizeOfNativeType() {
+  try {
+    sizeOf(); //# 1301: ok
+  } catch (e) {
+    print(e);
+  }
+}
+
+void testElementAtGeneric() {
+  Pointer<T> generic<T extends NativeType>(Pointer<T> pointer) {
+    Pointer<T> returnValue = pointer;
+    returnValue = returnValue.elementAt(1); //# 1310: ok
+    return returnValue;
+  }
+
+  Pointer<Int8> p = calloc();
+  p.elementAt(1);
+  generic(p);
+  calloc.free(p);
+}
+
+void testElementAtNativeType() {
+  Pointer<Int8> p = calloc();
+  p.elementAt(1);
+  Pointer<NativeType> p2 = p;
+  p2.elementAt(1); //# 1311: ok
+  calloc.free(p);
 }
diff --git a/tests/ffi_2/aliasing_test.dart b/tests/ffi_2/aliasing_test.dart
index 6c2f698..946e1e4 100644
--- a/tests/ffi_2/aliasing_test.dart
+++ b/tests/ffi_2/aliasing_test.dart
@@ -13,6 +13,7 @@
 import "package:ffi/ffi.dart";
 import "package:expect/expect.dart";
 
+import 'calloc.dart';
 import 'ffi_test_helpers.dart';
 
 void main() {
@@ -35,28 +36,28 @@
 }
 
 void testNonAlias() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   source.value = 42;
   final int a = source.value;
   source.value = 1984;
   // alias.value should be re-executed, as we wrote to alias.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasCast() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias = source.cast<Int8>().cast<Int64>();
   source.value = 42;
   final int a = source.value;
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasCast2() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias = source.cast<Int16>().cast<Int64>();
   final alias2 = source.cast<Int8>().cast<Int64>();
   alias.value = 42;
@@ -64,22 +65,22 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasOffsetBy() {
-  final source = allocate<Int64>(count: 2);
+  final source = calloc<Int64>(2);
   final alias = source.offsetBy(8).offsetBy(-8);
   source.value = 42;
   final int a = source.value;
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasOffsetBy2() {
-  final source = allocate<Int64>(count: 3);
+  final source = calloc<Int64>(3);
   final alias = source.offsetBy(16).offsetBy(-16);
   final alias2 = source.offsetBy(8).offsetBy(-8);
   alias.value = 42;
@@ -87,22 +88,22 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasElementAt() {
-  final source = allocate<Int64>(count: 2);
+  final source = calloc<Int64>(2);
   final alias = source.elementAt(1).elementAt(-1);
   source.value = 42;
   final int a = source.value;
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasElementAt2() {
-  final source = allocate<Int64>(count: 3);
+  final source = calloc<Int64>(3);
   final alias = source.elementAt(2).elementAt(-2);
   final alias2 = source.elementAt(1).elementAt(-1);
   alias.value = 42;
@@ -110,22 +111,22 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasFromAddress() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias = Pointer<Int64>.fromAddress(source.address);
   source.value = 42;
   final int a = source.value;
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasFromAddress2() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias = Pointer<Int64>.fromAddress(source.address);
   final alias2 = Pointer<Int64>.fromAddress(source.address);
   alias.value = 42;
@@ -133,12 +134,12 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasFromAddressViaMemory() {
-  final helper = allocate<IntPtr>();
-  final source = allocate<Int64>();
+  final helper = calloc<IntPtr>();
+  final source = calloc<Int64>();
   helper.value = source.address;
   final alias = Pointer<Int64>.fromAddress(helper.value);
   source.value = 42;
@@ -146,13 +147,13 @@
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(helper);
-  free(source);
+  calloc.free(helper);
+  calloc.free(source);
 }
 
 void testAliasFromAddressViaMemory2() {
-  final helper = allocate<IntPtr>();
-  final source = allocate<Int64>();
+  final helper = calloc<IntPtr>();
+  final source = calloc<Int64>();
   helper.value = source.address;
   final alias = Pointer<Int64>.fromAddress(helper.value);
   final alias2 = Pointer<Int64>.fromAddress(helper.value);
@@ -161,8 +162,8 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(helper);
-  free(source);
+  calloc.free(helper);
+  calloc.free(source);
 }
 
 typedef NativeQuadOpSigned = Int64 Function(Int8, Int16, Int32, Int64);
@@ -172,7 +173,7 @@
     .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
 
 void testAliasFromAddressViaNativeFunction() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias =
       Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
   source.value = 42;
@@ -180,11 +181,11 @@
   alias.value = 1984;
   // source.value should be re-executed, we wrote alias which aliases source.
   Expect.notEquals(a, source.value);
-  free(source);
+  calloc.free(source);
 }
 
 void testAliasFromAddressViaNativeFunction2() {
-  final source = allocate<Int64>();
+  final source = calloc<Int64>();
   final alias =
       Pointer<Int64>.fromAddress(intComputation(0, 0, 0, source.address));
   final alias2 =
@@ -194,7 +195,7 @@
   alias2.value = 1984;
   // alias.value should be re-executed, we wrote alias2 which aliases alias.
   Expect.notEquals(a, alias.value);
-  free(source);
+  calloc.free(source);
 }
 
 @pragma('vm:never-inline')
@@ -202,11 +203,11 @@
     source.offsetBy(7).cast<Int8>();
 
 testPartialOverlap() {
-  final source = allocate<Int64>(count: 2);
+  final source = calloc<Int64>(2);
   final derived = makeDerived(source);
   source.value = 0x1122334455667788;
   final int value = source.value;
   derived.value = 0xaa;
   Expect.notEquals(value, source.value);
-  free(source);
+  calloc.free(source);
 }
diff --git a/tests/ffi_2/all_positive.dart b/tests/ffi_2/all_positive.dart
new file mode 100644
index 0000000..699add9
--- /dev/null
+++ b/tests/ffi_2/all_positive.dart
@@ -0,0 +1,102 @@
+// 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.
+
+// Generated by prepare_flutter_bundle.dart and not ignoring vmspecific.
+// Used in fuchsia_test_component.
+//
+// Note that we are not using any VM flags here, so we are not exercising GC
+// corner cases etc. However, we are mainly interested in exercising the
+// calling convention on Fuchsia.
+
+import "dart:async";
+
+import "aliasing_test.dart" as main0;
+import "data_not_asan_test.dart" as main1;
+import "data_test.dart" as main2;
+import "dylib_isolates_test.dart" as main3;
+import "extension_methods_test.dart" as main4;
+import "external_typed_data_test.dart" as main5;
+import "function_callbacks_many_test.dart" as main6;
+import "function_callbacks_test.dart" as main7;
+import "function_callbacks_very_many_test.dart" as main8;
+import "function_structs_test.dart" as main9;
+import "function_test.dart" as main10;
+import "function_very_many_test.dart" as main11;
+import "hardfp_test.dart" as main12;
+import "negative_function_test.dart" as main13;
+import "null_regress_39068_test.dart" as main14;
+import "null_test.dart" as main15;
+import "regress_37254_test.dart" as main16;
+import "regress_39044_test.dart" as main17;
+import "regress_39063_test.dart" as main18;
+import "regress_39885_test.dart" as main19;
+import "regress_40537_test.dart" as main20;
+import "regress_43016_test.dart" as main21;
+import "regress_43693_test.dart" as main22;
+import "regress_jump_to_frame_test.dart" as main23;
+import "sizeof_test.dart" as main24;
+import "snapshot_test.dart" as main25;
+import "stacktrace_regress_37910_test.dart" as main26;
+import "structs_test.dart" as main27;
+import "variance_function_test.dart" as main28;
+import "vmspecific_function_callbacks_exit_test.dart" as main29;
+import "vmspecific_function_test.dart" as main30;
+import "vmspecific_handle_dynamically_linked_test.dart" as main31;
+import "vmspecific_handle_test.dart" as main32;
+import "vmspecific_null_test.dart" as main33;
+import "vmspecific_object_gc_test.dart" as main34;
+import "vmspecific_regress_37100_test.dart" as main35;
+import "vmspecific_regress_37511_callbacks_test.dart" as main36;
+import "vmspecific_regress_37511_test.dart" as main37;
+import "vmspecific_regress_37780_test.dart" as main38;
+
+Future invoke(dynamic fun) async {
+  if (fun is void Function() || fun is Future Function()) {
+    return await fun();
+  } else {
+    return await fun(<String>[]);
+  }
+}
+
+dynamic main() async {
+  await invoke(main0.main);
+  await invoke(main1.main);
+  await invoke(main2.main);
+  await invoke(main3.main);
+  await invoke(main4.main);
+  await invoke(main5.main);
+  await invoke(main6.main);
+  await invoke(main7.main);
+  await invoke(main8.main);
+  await invoke(main9.main);
+  await invoke(main10.main);
+  await invoke(main11.main);
+  await invoke(main12.main);
+  await invoke(main13.main);
+  await invoke(main14.main);
+  await invoke(main15.main);
+  await invoke(main16.main);
+  await invoke(main17.main);
+  await invoke(main18.main);
+  await invoke(main19.main);
+  await invoke(main20.main);
+  await invoke(main21.main);
+  await invoke(main22.main);
+  await invoke(main23.main);
+  await invoke(main24.main);
+  await invoke(main25.main);
+  await invoke(main26.main);
+  await invoke(main27.main);
+  await invoke(main28.main);
+  await invoke(main29.main);
+  await invoke(main30.main);
+  await invoke(main31.main);
+  await invoke(main32.main);
+  await invoke(main33.main);
+  await invoke(main34.main);
+  await invoke(main35.main);
+  await invoke(main36.main);
+  await invoke(main37.main);
+  await invoke(main38.main);
+}
diff --git a/tests/ffi_2/allocator_test.dart b/tests/ffi_2/allocator_test.dart
new file mode 100644
index 0000000..396f5c9
--- /dev/null
+++ b/tests/ffi_2/allocator_test.dart
@@ -0,0 +1,24 @@
+// 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 we can implement the Allocator interface.
+
+import 'dart:ffi';
+
+class MyAllocator implements Allocator {
+  const MyAllocator();
+
+  @override
+  Pointer<T> allocate<T extends NativeType>(int numBytes, {int alignment}) {
+    throw "Not implemented";
+  }
+
+  void free(Pointer pointer) {}
+}
+
+const myAllocator = MyAllocator();
+
+void main() {
+  print(myAllocator);
+}
diff --git a/tests/ffi_2/calloc.dart b/tests/ffi_2/calloc.dart
new file mode 100644
index 0000000..a433e39
--- /dev/null
+++ b/tests/ffi_2/calloc.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.
+
+// TODO(https://dartbug.com/44621): Remove this copy when package:ffi can be
+// rolled. We need to wait until the `Allocator` interface has rolled into
+// Flutter.
+
+import 'dart:ffi';
+import 'dart:io';
+
+final DynamicLibrary stdlib = Platform.isWindows
+    ? DynamicLibrary.open('kernel32.dll')
+    : DynamicLibrary.process();
+
+typedef PosixCallocNative = Pointer Function(IntPtr num, IntPtr size);
+typedef PosixCalloc = Pointer Function(int num, int size);
+final PosixCalloc posixCalloc =
+    stdlib.lookupFunction<PosixCallocNative, PosixCalloc>('calloc');
+
+typedef PosixFreeNative = Void Function(Pointer);
+typedef PosixFree = void Function(Pointer);
+final PosixFree posixFree =
+    stdlib.lookupFunction<PosixFreeNative, PosixFree>('free');
+
+typedef WinGetProcessHeapFn = Pointer Function();
+final WinGetProcessHeapFn winGetProcessHeap = stdlib
+    .lookupFunction<WinGetProcessHeapFn, WinGetProcessHeapFn>('GetProcessHeap');
+final Pointer processHeap = winGetProcessHeap();
+
+typedef WinHeapAllocNative = Pointer Function(Pointer, Uint32, IntPtr);
+typedef WinHeapAlloc = Pointer Function(Pointer, int, int);
+final WinHeapAlloc winHeapAlloc =
+    stdlib.lookupFunction<WinHeapAllocNative, WinHeapAlloc>('HeapAlloc');
+
+typedef WinHeapFreeNative = Int32 Function(
+    Pointer heap, Uint32 flags, Pointer memory);
+typedef WinHeapFree = int Function(Pointer heap, int flags, Pointer memory);
+final WinHeapFree winHeapFree =
+    stdlib.lookupFunction<WinHeapFreeNative, WinHeapFree>('HeapFree');
+
+const int HEAP_ZERO_MEMORY = 8;
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+class _CallocAllocator implements Allocator {
+  const _CallocAllocator();
+
+  /// Allocates [byteCount] bytes of zero-initialized of memory on the native
+  /// heap.
+  ///
+  /// For POSIX-based systems, this uses `calloc`. On Windows, it uses
+  /// `HeapAlloc` against the default public heap.
+  ///
+  /// Throws an [ArgumentError] if the number of bytes or alignment cannot be
+  /// satisfied.
+  // TODO: Stop ignoring alignment if it's large, for example for SSE data.
+  @override
+  Pointer<T> allocate<T extends NativeType>(int byteCount, {int alignment}) {
+    Pointer<T> result;
+    if (Platform.isWindows) {
+      result = winHeapAlloc(processHeap, /*flags=*/ HEAP_ZERO_MEMORY, byteCount)
+          .cast();
+    } else {
+      result = posixCalloc(byteCount, 1).cast();
+    }
+    if (result.address == 0) {
+      throw ArgumentError('Could not allocate $byteCount bytes.');
+    }
+    return result;
+  }
+
+  /// Releases memory allocated on the native heap.
+  ///
+  /// For POSIX-based systems, this uses `free`. On Windows, it uses `HeapFree`
+  /// against the default public heap. It may only be used against pointers
+  /// allocated in a manner equivalent to [allocate].
+  ///
+  /// Throws an [ArgumentError] if the memory pointed to by [pointer] cannot be
+  /// freed.
+  ///
+  // TODO(dartbug.com/36855): Once we have a ffi.Bool type we can use it instead
+  // of testing the return integer to be non-zero.
+  @override
+  void free(Pointer pointer) {
+    if (Platform.isWindows) {
+      if (winHeapFree(processHeap, /*flags=*/ 0, pointer) == 0) {
+        throw ArgumentError('Could not free $pointer.');
+      }
+    } else {
+      posixFree(pointer);
+    }
+  }
+}
+
+/// Manages memory on the native heap.
+///
+/// Initializes newly allocated memory to zero. Use [malloc] for unintialized
+/// memory allocation.
+///
+/// For POSIX-based systems, this uses `calloc` and `free`. On Windows, it uses
+/// `HeapAlloc` with [HEAP_ZERO_MEMORY] and `HeapFree` against the default
+/// public heap.
+const Allocator calloc = _CallocAllocator();
diff --git a/tests/ffi_2/calloc_test.dart b/tests/ffi_2/calloc_test.dart
new file mode 100644
index 0000000..b8b9bbf
--- /dev/null
+++ b/tests/ffi_2/calloc_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.
+
+import 'dart:ffi';
+
+import 'package:expect/expect.dart';
+
+import 'calloc.dart';
+import 'coordinate.dart';
+
+void main() {
+  testZeroInt();
+  testZeroFloat();
+  testZeroStruct();
+}
+
+void testZeroInt() {
+  final p = calloc<Uint8>();
+  Expect.equals(0, p.value);
+  calloc.free(p);
+}
+
+void testZeroFloat() {
+  final p = calloc<Float>();
+  Expect.approxEquals(0.0, p.value);
+  calloc.free(p);
+}
+
+void testZeroStruct() {
+  final p = calloc<Coordinate>();
+  Expect.approxEquals(0, p.ref.x);
+  Expect.approxEquals(0, p.ref.y);
+  Expect.equals(nullptr, p.ref.next);
+  calloc.free(p);
+}
diff --git a/tests/ffi_2/coordinate.dart b/tests/ffi_2/coordinate.dart
index 92dd9d4..92dfbf0 100644
--- a/tests/ffi_2/coordinate.dart
+++ b/tests/ffi_2/coordinate.dart
@@ -17,8 +17,9 @@
 
   Pointer<Coordinate> next;
 
-  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
-    return allocate<Coordinate>().ref
+  factory Coordinate.allocate(
+      Allocator allocator, double x, double y, Pointer<Coordinate> next) {
+    return allocator<Coordinate>().ref
       ..x = x
       ..y = y
       ..next = next;
diff --git a/tests/ffi_2/data_not_asan_test.dart b/tests/ffi_2/data_not_asan_test.dart
index e95658f..69257d6 100644
--- a/tests/ffi_2/data_not_asan_test.dart
+++ b/tests/ffi_2/data_not_asan_test.dart
@@ -4,7 +4,7 @@
 //
 // Dart test program for testing dart:ffi primitive data pointers.
 //
-// These mallocs trigger an asan alarm, so these tests are in a separate file
+// These callocs trigger an asan alarm, so these tests are in a separate file
 // which is excluded in asan mode.
 
 import 'dart:ffi';
@@ -12,6 +12,8 @@
 import "package:ffi/ffi.dart";
 import "package:expect/expect.dart";
 
+import 'calloc.dart';
+
 void main() {
   testPointerAllocateTooLarge();
   testPointerAllocateNegative();
@@ -20,16 +22,16 @@
 void testPointerAllocateTooLarge() {
   // Try to allocate something that doesn't fit in 64 bit address space.
   int maxInt = 9223372036854775807; // 2^63 - 1
-  Expect.throws(() => allocate<Int64>(count: maxInt));
+  Expect.throws(() => calloc<Int64>(maxInt));
 
   // Try to allocate almost the full 64 bit address space.
   int maxInt1_8 = 1152921504606846975; // 2^60 -1
-  Expect.throws(() => allocate<Int64>(count: maxInt1_8));
+  Expect.throws(() => calloc<Int64>(maxInt1_8));
 }
 
 void testPointerAllocateNegative() {
   // Passing in -1 will be converted into an unsigned integer. So, it will try
   // to allocate SIZE_MAX - 1 + 1 bytes. This will fail as it is the max amount
   // of addressable memory on the system.
-  Expect.throws(() => allocate<Int8>(count: -1));
+  Expect.throws(() => calloc<Int8>(-1));
 }
diff --git a/tests/ffi_2/data_test.dart b/tests/ffi_2/data_test.dart
index a533ced..59cc7f4 100644
--- a/tests/ffi_2/data_test.dart
+++ b/tests/ffi_2/data_test.dart
@@ -11,6 +11,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'ffi_test_helpers.dart';
 
 void main() {
@@ -44,80 +45,76 @@
   testTypeTest();
   testToString();
   testEquality();
-  testAllocateGeneric();
   testAllocateVoid();
   testAllocateNativeFunction();
-  testAllocateNativeType();
-  testSizeOfGeneric();
   testSizeOfVoid();
   testSizeOfNativeFunction();
-  testSizeOfNativeType();
   testDynamicInvocation();
   testMemoryAddressTruncation();
   testNullptrCast();
 }
 
 void testPointerBasic() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.value = 42;
   Expect.equals(42, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testPointerFromPointer() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.value = 1337;
   int ptr = p.address;
   Pointer<Int64> p2 = Pointer.fromAddress(ptr);
   Expect.equals(1337, p2.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testPointerPointerArithmetic() {
-  Pointer<Int64> p = allocate(count: 2);
+  Pointer<Int64> p = calloc(2);
   Pointer<Int64> p2 = p.elementAt(1);
   p2.value = 100;
   Pointer<Int64> p3 = p.offsetBy(8);
   Expect.equals(100, p3.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testPointerPointerArithmeticSizes() {
-  Pointer<Int64> p = allocate(count: 2);
+  Pointer<Int64> p = calloc(2);
   Pointer<Int64> p2 = p.elementAt(1);
   int addr = p.address;
   Expect.equals(addr + 8, p2.address);
-  free(p);
+  calloc.free(p);
 
-  Pointer<Int32> p3 = allocate(count: 2);
+  Pointer<Int32> p3 = calloc(2);
   Pointer<Int32> p4 = p3.elementAt(1);
   addr = p3.address;
   Expect.equals(addr + 4, p4.address);
-  free(p3);
+  calloc.free(p3);
 }
 
 void testPointerAllocateZero() {
   // > If size is 0, either a null pointer or a unique pointer that can be
-  // > successfully passed to free() shall be returned.
-  // http://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html
+  // > successfully passed to calloc.free() shall be returned.
+  // http://pubs.opengroup.org/onlinepubs/009695399/functions/calloc.html
   //
   // Null pointer throws a Dart exception.
   bool returnedNullPointer = false;
   Pointer<Int8> p;
   try {
-    p = allocate<Int8>(count: 0);
+    p = calloc<Int8>(0);
   } on Exception {
     returnedNullPointer = true;
   }
   if (!returnedNullPointer) {
-    free(p);
+    calloc.free(p);
   }
 }
 
 void testPointerCast() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.cast<Int32>(); // gets the correct type args back
-  free(p);
+  calloc.free(p);
 }
 
 void testCastGeneric() {
@@ -125,9 +122,9 @@
     return p.cast();
   }
 
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   Pointer<Int64> p2 = generic(p);
-  free(p);
+  calloc.free(p);
 }
 
 void testCastGeneric2() {
@@ -135,41 +132,41 @@
     return p.cast();
   }
 
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   Pointer<Int64> p2 = generic(p);
-  free(p);
+  calloc.free(p);
 }
 
 void testCastNativeType() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.cast<Pointer>();
-  free(p);
+  calloc.free(p);
 }
 
 void testCondensedNumbersInt8() {
-  Pointer<Int8> p = allocate(count: 8);
+  Pointer<Int8> p = calloc(8);
   for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
     p[i] = i * 3;
   }
   for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
     Expect.equals(i * 3, p[i]);
   }
-  free(p);
+  calloc.free(p);
 }
 
 void testCondensedNumbersFloat() {
-  Pointer<Float> p = allocate(count: 8);
+  Pointer<Float> p = calloc(8);
   for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
     p[i] = 1.511366173271439e-13;
   }
   for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
     Expect.equals(1.511366173271439e-13, p[i]);
   }
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeInt8() {
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   p.value = 127;
   Expect.equals(127, p.value);
   p.value = -128;
@@ -184,11 +181,11 @@
   Expect.equals(0x000000000000007F, 127);
   p.value = -129;
   Expect.equals(127, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeUint8() {
-  Pointer<Uint8> p = allocate();
+  Pointer<Uint8> p = calloc();
   p.value = 255;
   Expect.equals(255, p.value);
   p.value = 0;
@@ -203,11 +200,11 @@
   Expect.equals(0x00000000000000FF, 255);
   p.value = -1;
   Expect.equals(255, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeInt16() {
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   p.value = 0x7FFF;
   Expect.equals(0x7FFF, p.value);
   p.value = -0x8000;
@@ -216,11 +213,11 @@
   Expect.equals(0xFFFFFFFFFFFF8000, p.value); // truncated and sign extended
   p.value = -0x8001;
   Expect.equals(0x7FFF, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeUint16() {
-  Pointer<Uint16> p = allocate();
+  Pointer<Uint16> p = calloc();
   p.value = 0xFFFF;
   Expect.equals(0xFFFF, p.value);
   p.value = 0;
@@ -229,11 +226,11 @@
   Expect.equals(0, p.value); // truncated
   p.value = -1;
   Expect.equals(0xFFFF, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeInt32() {
-  Pointer<Int32> p = allocate();
+  Pointer<Int32> p = calloc();
   p.value = 0x7FFFFFFF;
   Expect.equals(0x7FFFFFFF, p.value);
   p.value = -0x80000000;
@@ -242,11 +239,11 @@
   Expect.equals(0xFFFFFFFF80000000, p.value); // truncated and sign extended
   p.value = -0x80000001;
   Expect.equals(0x7FFFFFFF, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeUint32() {
-  Pointer<Uint32> p = allocate();
+  Pointer<Uint32> p = calloc();
   p.value = 0xFFFFFFFF;
   Expect.equals(0xFFFFFFFF, p.value);
   p.value = 0;
@@ -255,20 +252,20 @@
   Expect.equals(0, p.value); // truncated
   p.value = -1;
   Expect.equals(0xFFFFFFFF, p.value); // truncated
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeInt64() {
-  Pointer<Int64> p = allocate();
+  Pointer<Int64> p = calloc();
   p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
   Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
   p.value = -0x8000000000000000; // -2 ^ 63
   Expect.equals(-0x8000000000000000, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeUint64() {
-  Pointer<Uint64> p = allocate();
+  Pointer<Uint64> p = calloc();
   p.value = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
   Expect.equals(0x7FFFFFFFFFFFFFFF, p.value);
   p.value = -0x8000000000000000; // -2 ^ 63 interpreted as 2 ^ 63
@@ -279,69 +276,69 @@
   p.value = -1; // -1 interpreted as 2 ^ 64 - 1
   Expect.equals(-1, p.value);
   Expect.equals(0xFFFFFFFFFFFFFFFF, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testRangeIntPtr() {
-  Pointer<IntPtr> p = allocate();
+  Pointer<IntPtr> p = calloc();
   int pAddr = p.address;
   p.value = pAddr; // its own address should fit
   p.value = 0x7FFFFFFF; // and 32 bit addresses should fit
   Expect.equals(0x7FFFFFFF, p.value);
   p.value = -0x80000000;
   Expect.equals(-0x80000000, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testFloat() {
-  Pointer<Float> p = allocate();
+  Pointer<Float> p = calloc();
   p.value = 1.511366173271439e-13;
   Expect.equals(1.511366173271439e-13, p.value);
   p.value = 1.4260258159703532e-105; // float does not have enough precision
   Expect.notEquals(1.4260258159703532e-105, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testDouble() {
-  Pointer<Double> p = allocate();
+  Pointer<Double> p = calloc();
   p.value = 1.4260258159703532e-105;
   Expect.equals(1.4260258159703532e-105, p.value);
-  free(p);
+  calloc.free(p);
 }
 
 void testVoid() {
-  Pointer<IntPtr> p1 = allocate();
+  Pointer<IntPtr> p1 = calloc();
   Pointer<Void> p2 = p1.cast(); // make this dart pointer opaque
   p2.address; // we can print the address
-  free(p2);
+  calloc.free(p2);
 }
 
 void testPointerPointer() {
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   p.value = 17;
-  Pointer<Pointer<Int16>> p2 = allocate();
+  Pointer<Pointer<Int16>> p2 = calloc();
   p2.value = p;
   Expect.equals(17, p2.value.value);
-  free(p2);
-  free(p);
+  calloc.free(p2);
+  calloc.free(p);
 }
 
 void testPointerPointerNull() {
-  Pointer<Pointer<Int8>> pointerToPointer = allocate();
+  Pointer<Pointer<Int8>> pointerToPointer = calloc();
   Pointer<Int8> value = nullptr;
   pointerToPointer.value = value;
   value = pointerToPointer.value;
   Expect.equals(value, nullptr);
-  value = allocate();
+  value = calloc();
   pointerToPointer.value = value;
   value = pointerToPointer.value;
   Expect.isNotNull(value);
-  free(value);
+  calloc.free(value);
   value = nullptr;
   pointerToPointer.value = value;
   value = pointerToPointer.value;
   Expect.equals(value, nullptr);
-  free(pointerToPointer);
+  calloc.free(pointerToPointer);
 }
 
 void testSizeOf() {
@@ -365,7 +362,7 @@
       head.value = value;
       return;
     }
-    Pointer<IntPtr> next = allocate();
+    Pointer<IntPtr> next = calloc();
     head.value = next.address;
     createChain(next, length - 1, value);
   }
@@ -380,14 +377,14 @@
 
   void freeChain(Pointer<IntPtr> head, int length) {
     Pointer<IntPtr> next = Pointer.fromAddress(head.value);
-    free(head);
+    calloc.free(head);
     if (length == 0) {
       return;
     }
     freeChain(next, length - 1);
   }
 
-  Pointer<IntPtr> head = allocate();
+  Pointer<IntPtr> head = calloc();
   createChain(head, length, 512);
   int tailValue = getChainValue(head, length);
   Expect.equals(512, tailValue);
@@ -395,16 +392,16 @@
 }
 
 void testTypeTest() {
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   Expect.isTrue(p is Pointer);
-  free(p);
+  calloc.free(p);
 }
 
 void testToString() {
-  Pointer<Int16> p = allocate();
+  Pointer<Int16> p = calloc();
   Expect.stringEquals(
       "Pointer<Int16>: address=0x", p.toString().substring(0, 26));
-  free(p);
+  calloc.free(p);
   Pointer<Int64> p2 = Pointer.fromAddress(0x123abc);
   Expect.stringEquals("Pointer<Int64>: address=0x123abc", p2.toString());
 }
@@ -423,46 +420,18 @@
 
 typedef Int8UnOp = Int8 Function(Int8);
 
-void testAllocateGeneric() {
-  Pointer<T> generic<T extends NativeType>() {
-    Pointer<T> pointer;
-    pointer = allocate();
-    return pointer;
-  }
-
-  Pointer p = generic<Int64>();
-  free(p);
-}
-
 void testAllocateVoid() {
   Expect.throws(() {
-    Pointer<Void> p = allocate();
+    Pointer<Void> p = calloc();
   });
 }
 
 void testAllocateNativeFunction() {
   Expect.throws(() {
-    Pointer<NativeFunction<Int8UnOp>> p = allocate();
+    Pointer<NativeFunction<Int8UnOp>> p = calloc();
   });
 }
 
-void testAllocateNativeType() {
-  Expect.throws(() {
-    allocate();
-  });
-}
-
-void testSizeOfGeneric() {
-  int generic<T extends Pointer>() {
-    int size;
-    size = sizeOf<T>();
-    return size;
-  }
-
-  int size = generic<Pointer<Int64>>();
-  Expect.isTrue(size == 8 || size == 4);
-}
-
 void testSizeOfVoid() {
   Expect.throws(() {
     sizeOf<Void>();
@@ -475,14 +444,8 @@
   });
 }
 
-void testSizeOfNativeType() {
-  Expect.throws(() {
-    sizeOf();
-  });
-}
-
 void testDynamicInvocation() {
-  dynamic p = allocate<Int8>();
+  dynamic p = calloc<Int8>();
   Expect.throws(() {
     final int i = p.value;
   });
@@ -490,7 +453,7 @@
   p.elementAt(5); // Works, but is slow.
   final int addr = p.address;
   final Pointer<Int16> p2 = p.cast<Int16>();
-  free(p);
+  calloc.free(p);
 }
 
 final nullableInt64ElementAt1 = ffiTestFunctions.lookupFunction<
diff --git a/tests/ffi_2/dylib_utils.dart b/tests/ffi_2/dylib_utils.dart
index fb8153a..c6f9127 100644
--- a/tests/ffi_2/dylib_utils.dart
+++ b/tests/ffi_2/dylib_utils.dart
@@ -7,7 +7,7 @@
 
 String _platformPath(String name, {String path}) {
   if (path == null) path = "";
-  if (Platform.isLinux || Platform.isAndroid)
+  if (Platform.isLinux || Platform.isAndroid || Platform.isFuchsia)
     return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
diff --git a/tests/ffi_2/extension_methods_test.dart b/tests/ffi_2/extension_methods_test.dart
index 19bc44b..3524a7f 100644
--- a/tests/ffi_2/extension_methods_test.dart
+++ b/tests/ffi_2/extension_methods_test.dart
@@ -7,6 +7,8 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
+
 main(List<String> arguments) {
   for (int i = 0; i < 100; i++) {
     testStoreLoad();
@@ -15,7 +17,7 @@
 }
 
 testStoreLoad() {
-  final p = allocate<Int8>(count: 2);
+  final p = calloc<Int8>(2);
   p.value = 10;
   Expect.equals(10, p.value);
   p[1] = 20;
@@ -30,33 +32,33 @@
   final pUseNegative = p.elementAt(1);
   Expect.equals(10, pUseNegative[-1]);
 
-  final p1 = allocate<Double>(count: 2);
+  final p1 = calloc<Double>(2);
   p1.value = 10.0;
   Expect.approxEquals(10.0, p1.value);
   p1[1] = 20.0;
   Expect.approxEquals(20.0, p1[1]);
-  free(p1);
+  calloc.free(p1);
 
-  final p2 = allocate<Pointer<Int8>>(count: 2);
+  final p2 = calloc<Pointer<Int8>>(2);
   p2.value = p;
   Expect.equals(p, p2.value);
   p2[1] = p;
   Expect.equals(p, p2[1]);
-  free(p2);
-  free(p);
+  calloc.free(p2);
+  calloc.free(p);
 
-  final p3 = allocate<Foo>();
+  final p3 = calloc<Foo>();
   Foo foo = p3.ref;
   foo.a = 1;
   Expect.equals(1, foo.a);
-  free(p3);
+  calloc.free(p3);
 }
 
 testReifiedGeneric() {
-  final p = allocate<Pointer<Int8>>();
+  final p = calloc<Pointer<Int8>>();
   Pointer<Pointer<NativeType>> p2 = p;
   Expect.isTrue(p2.value is Pointer<Int8>);
-  free(p);
+  calloc.free(p);
 }
 
 class Foo extends Struct {
diff --git a/tests/ffi_2/external_typed_data_test.dart b/tests/ffi_2/external_typed_data_test.dart
index 8d19f79..18e8e3c 100644
--- a/tests/ffi_2/external_typed_data_test.dart
+++ b/tests/ffi_2/external_typed_data_test.dart
@@ -9,6 +9,8 @@
 import 'package:expect/expect.dart';
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
+
 main() {
   testInt8Load();
   testInt8Store();
@@ -41,162 +43,162 @@
 
 void testInt8Load() {
   // Load
-  Pointer<Int8> ptr = allocate();
+  Pointer<Int8> ptr = calloc();
   ptr.value = 0xff;
   Int8List list = ptr.asTypedList(1);
   Expect.equals(list[0], -1);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt8Store() {
   // Store
-  Pointer<Int8> ptr = allocate();
+  Pointer<Int8> ptr = calloc();
   Int8List list = ptr.asTypedList(1);
   list[0] = 0xff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, -1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint8Load() {
   // Load
-  Pointer<Uint8> ptr = allocate();
+  Pointer<Uint8> ptr = calloc();
   ptr.value = 0xff;
   Uint8List list = ptr.asTypedList(1);
   Expect.equals(list[0], 0xff);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint8Store() {
   // Store
-  Pointer<Uint8> ptr = allocate();
+  Pointer<Uint8> ptr = calloc();
   Uint8List list = ptr.asTypedList(1);
   list[0] = 0xff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, 0xff);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt16Load() {
   // Load
-  Pointer<Int16> ptr = allocate();
+  Pointer<Int16> ptr = calloc();
   ptr.value = 0xffff;
   Int16List list = ptr.asTypedList(1);
   Expect.equals(list[0], -1);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt16Store() {
   // Store
-  Pointer<Int16> ptr = allocate();
+  Pointer<Int16> ptr = calloc();
   Int16List list = ptr.asTypedList(1);
   list[0] = 0xffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, -1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint16Load() {
   // Load
-  Pointer<Uint16> ptr = allocate();
+  Pointer<Uint16> ptr = calloc();
   ptr.value = 0xffff;
   Uint16List list = ptr.asTypedList(1);
   Expect.equals(list[0], 0xffff);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint16Store() {
   // Store
-  Pointer<Uint16> ptr = allocate();
+  Pointer<Uint16> ptr = calloc();
   Uint16List list = ptr.asTypedList(1);
   list[0] = 0xffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, 0xffff);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt32Load() {
   // Load
-  Pointer<Int32> ptr = allocate();
+  Pointer<Int32> ptr = calloc();
   ptr.value = 0xffffffff;
   Int32List list = ptr.asTypedList(1);
   Expect.equals(list[0], -1);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt32Store() {
   // Store
-  Pointer<Int32> ptr = allocate();
+  Pointer<Int32> ptr = calloc();
   Int32List list = ptr.asTypedList(1);
   list[0] = 0xffffffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, -1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint32Load() {
   // Load
-  Pointer<Uint32> ptr = allocate();
+  Pointer<Uint32> ptr = calloc();
   ptr.value = 0xffffffff;
   Uint32List list = ptr.asTypedList(1);
   Expect.equals(list[0], 0xffffffff);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint32Store() {
   // Store
-  Pointer<Uint32> ptr = allocate();
+  Pointer<Uint32> ptr = calloc();
   Uint32List list = ptr.asTypedList(1);
   list[0] = 0xffffffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, 0xffffffff);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt64Load() {
   // Load
-  Pointer<Int64> ptr = allocate();
+  Pointer<Int64> ptr = calloc();
   ptr.value = 0xffffffffffffffff;
   Int64List list = ptr.asTypedList(1);
   Expect.equals(list[0], -1);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testInt64Store() {
   // Store
-  Pointer<Int64> ptr = allocate();
+  Pointer<Int64> ptr = calloc();
   Int64List list = ptr.asTypedList(1);
   list[0] = 0xffffffffffffffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, -1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint64Load() {
   // Load
-  Pointer<Uint64> ptr = allocate();
+  Pointer<Uint64> ptr = calloc();
   ptr.value = 0xffffffffffffffff;
   Uint64List list = ptr.asTypedList(1);
   Expect.equals(list[0], 0xffffffffffffffff);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testUint64Store() {
   // Store
-  Pointer<Uint64> ptr = allocate();
+  Pointer<Uint64> ptr = calloc();
   Uint64List list = ptr.asTypedList(1);
   list[0] = 0xffffffffffffffff;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, 0xffffffffffffffff);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 double maxFloat = (2 - pow(2, -23)) * pow(2, 127);
@@ -204,47 +206,47 @@
 
 void testFloatLoad() {
   // Load
-  Pointer<Float> ptr = allocate();
+  Pointer<Float> ptr = calloc();
   ptr.value = maxFloat;
   Float32List list = ptr.asTypedList(1);
   Expect.equals(list[0], maxFloat);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testFloatStore() {
   // Store
-  Pointer<Float> ptr = allocate();
+  Pointer<Float> ptr = calloc();
   Float32List list = ptr.asTypedList(1);
   list[0] = maxFloat;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, maxFloat);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testDoubleLoad() {
   // Load
-  Pointer<Double> ptr = allocate();
+  Pointer<Double> ptr = calloc();
   ptr.value = maxDouble;
   Float64List list = ptr.asTypedList(1);
   Expect.equals(list[0], maxDouble);
   Expect.equals(list.length, 1);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testDoubleStore() {
   // Store
-  Pointer<Double> ptr = allocate();
+  Pointer<Double> ptr = calloc();
   Float64List list = ptr.asTypedList(1);
   list[0] = maxDouble;
   Expect.equals(list.length, 1);
   Expect.equals(ptr.value, maxDouble);
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testArrayLoad() {
   const int count = 0x100;
-  Pointer<Int32> ptr = allocate(count: count);
+  Pointer<Int32> ptr = calloc(count);
   for (int i = 0; i < count; ++i) {
     ptr[i] = i;
   }
@@ -252,12 +254,12 @@
   for (int i = 0; i < count; ++i) {
     Expect.equals(array[i], i);
   }
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testArrayStore() {
   const int count = 0x100;
-  Pointer<Int32> ptr = allocate(count: count);
+  Pointer<Int32> ptr = calloc(count);
   Int32List array = ptr.asTypedList(count);
   for (int i = 0; i < count; ++i) {
     array[i] = i;
@@ -265,7 +267,7 @@
   for (int i = 0; i < count; ++i) {
     Expect.equals(ptr[i], i);
   }
-  free(ptr);
+  calloc.free(ptr);
 }
 
 void testNegativeArray() {
diff --git a/tests/ffi_2/ffi_2.status b/tests/ffi_2/ffi_2.status
index 3baf069..37ab3e9 100644
--- a/tests/ffi_2/ffi_2.status
+++ b/tests/ffi_2/ffi_2.status
@@ -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.
 
-# TODO(dartbug.com/36730): Implement structs by value.
-function_callbacks_structs_by_value_generated_test: Skip
-function_callbacks_structs_by_value_test: Skip
-function_structs_by_value_generated_test: Skip
-
 [ $builder_tag == msan ]
 vmspecific_handle_test: Skip # https://dartbug.com/42314
 
diff --git a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
index 38714fd..e11d962 100644
--- a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
+++ b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
@@ -16,6 +16,7 @@
 import "package:ffi/ffi.dart";
 
 import 'callback_tests_utils.dart';
+import 'calloc.dart';
 
 // Reuse the struct classes.
 import 'function_structs_by_value_generated_test.dart';
@@ -193,6 +194,56 @@
           passStructAlignmentInt64, 0),
       passStructAlignmentInt64AfterCallback),
   CallbackTest.withCheck(
+      "PassStruct8BytesNestedIntx10",
+      Pointer.fromFunction<PassStruct8BytesNestedIntx10Type>(
+          passStruct8BytesNestedIntx10, 0),
+      passStruct8BytesNestedIntx10AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct8BytesNestedFloatx10",
+      Pointer.fromFunction<PassStruct8BytesNestedFloatx10Type>(
+          passStruct8BytesNestedFloatx10, 0.0),
+      passStruct8BytesNestedFloatx10AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct8BytesNestedFloat2x10",
+      Pointer.fromFunction<PassStruct8BytesNestedFloat2x10Type>(
+          passStruct8BytesNestedFloat2x10, 0.0),
+      passStruct8BytesNestedFloat2x10AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct8BytesNestedMixedx10",
+      Pointer.fromFunction<PassStruct8BytesNestedMixedx10Type>(
+          passStruct8BytesNestedMixedx10, 0.0),
+      passStruct8BytesNestedMixedx10AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct16BytesNestedIntx2",
+      Pointer.fromFunction<PassStruct16BytesNestedIntx2Type>(
+          passStruct16BytesNestedIntx2, 0),
+      passStruct16BytesNestedIntx2AfterCallback),
+  CallbackTest.withCheck(
+      "PassStruct32BytesNestedIntx2",
+      Pointer.fromFunction<PassStruct32BytesNestedIntx2Type>(
+          passStruct32BytesNestedIntx2, 0),
+      passStruct32BytesNestedIntx2AfterCallback),
+  CallbackTest.withCheck(
+      "PassStructNestedIntStructAlignmentInt16",
+      Pointer.fromFunction<PassStructNestedIntStructAlignmentInt16Type>(
+          passStructNestedIntStructAlignmentInt16, 0),
+      passStructNestedIntStructAlignmentInt16AfterCallback),
+  CallbackTest.withCheck(
+      "PassStructNestedIntStructAlignmentInt32",
+      Pointer.fromFunction<PassStructNestedIntStructAlignmentInt32Type>(
+          passStructNestedIntStructAlignmentInt32, 0),
+      passStructNestedIntStructAlignmentInt32AfterCallback),
+  CallbackTest.withCheck(
+      "PassStructNestedIntStructAlignmentInt64",
+      Pointer.fromFunction<PassStructNestedIntStructAlignmentInt64Type>(
+          passStructNestedIntStructAlignmentInt64, 0),
+      passStructNestedIntStructAlignmentInt64AfterCallback),
+  CallbackTest.withCheck(
+      "PassStructNestedIrregularEvenBiggerx4",
+      Pointer.fromFunction<PassStructNestedIrregularEvenBiggerx4Type>(
+          passStructNestedIrregularEvenBiggerx4, 0.0),
+      passStructNestedIrregularEvenBiggerx4AfterCallback),
+  CallbackTest.withCheck(
       "ReturnStruct1ByteInt",
       Pointer.fromFunction<ReturnStruct1ByteIntType>(returnStruct1ByteInt),
       returnStruct1ByteIntAfterCallback),
@@ -342,6 +393,56 @@
       Pointer.fromFunction<ReturnStructAlignmentInt64Type>(
           returnStructAlignmentInt64),
       returnStructAlignmentInt64AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct8BytesNestedInt",
+      Pointer.fromFunction<ReturnStruct8BytesNestedIntType>(
+          returnStruct8BytesNestedInt),
+      returnStruct8BytesNestedIntAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct8BytesNestedFloat",
+      Pointer.fromFunction<ReturnStruct8BytesNestedFloatType>(
+          returnStruct8BytesNestedFloat),
+      returnStruct8BytesNestedFloatAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct8BytesNestedFloat2",
+      Pointer.fromFunction<ReturnStruct8BytesNestedFloat2Type>(
+          returnStruct8BytesNestedFloat2),
+      returnStruct8BytesNestedFloat2AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct8BytesNestedMixed",
+      Pointer.fromFunction<ReturnStruct8BytesNestedMixedType>(
+          returnStruct8BytesNestedMixed),
+      returnStruct8BytesNestedMixedAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct16BytesNestedInt",
+      Pointer.fromFunction<ReturnStruct16BytesNestedIntType>(
+          returnStruct16BytesNestedInt),
+      returnStruct16BytesNestedIntAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStruct32BytesNestedInt",
+      Pointer.fromFunction<ReturnStruct32BytesNestedIntType>(
+          returnStruct32BytesNestedInt),
+      returnStruct32BytesNestedIntAfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStructNestedIntStructAlignmentInt16",
+      Pointer.fromFunction<ReturnStructNestedIntStructAlignmentInt16Type>(
+          returnStructNestedIntStructAlignmentInt16),
+      returnStructNestedIntStructAlignmentInt16AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStructNestedIntStructAlignmentInt32",
+      Pointer.fromFunction<ReturnStructNestedIntStructAlignmentInt32Type>(
+          returnStructNestedIntStructAlignmentInt32),
+      returnStructNestedIntStructAlignmentInt32AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStructNestedIntStructAlignmentInt64",
+      Pointer.fromFunction<ReturnStructNestedIntStructAlignmentInt64Type>(
+          returnStructNestedIntStructAlignmentInt64),
+      returnStructNestedIntStructAlignmentInt64AfterCallback),
+  CallbackTest.withCheck(
+      "ReturnStructNestedIrregularEvenBigger",
+      Pointer.fromFunction<ReturnStructNestedIrregularEvenBiggerType>(
+          returnStructNestedIrregularEvenBigger),
+      returnStructNestedIrregularEvenBiggerAfterCallback),
 ];
 typedef PassStruct1ByteIntx10Type = Int64 Function(
     Struct1ByteInt,
@@ -4256,6 +4357,1053 @@
   Expect.equals(-2, result);
 }
 
+typedef PassStruct8BytesNestedIntx10Type = Int64 Function(
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt,
+    Struct8BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a0 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a1 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a2 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a3 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a4 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a5 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a6 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a7 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a8 = Struct8BytesNestedInt();
+Struct8BytesNestedInt passStruct8BytesNestedIntx10_a9 = Struct8BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct8BytesNestedIntx10Result = 0;
+
+int passStruct8BytesNestedIntx10CalculateResult() {
+  int result = 0;
+
+  result += passStruct8BytesNestedIntx10_a0.a0.a0;
+  result += passStruct8BytesNestedIntx10_a0.a0.a1;
+  result += passStruct8BytesNestedIntx10_a0.a1.a0;
+  result += passStruct8BytesNestedIntx10_a0.a1.a1;
+  result += passStruct8BytesNestedIntx10_a1.a0.a0;
+  result += passStruct8BytesNestedIntx10_a1.a0.a1;
+  result += passStruct8BytesNestedIntx10_a1.a1.a0;
+  result += passStruct8BytesNestedIntx10_a1.a1.a1;
+  result += passStruct8BytesNestedIntx10_a2.a0.a0;
+  result += passStruct8BytesNestedIntx10_a2.a0.a1;
+  result += passStruct8BytesNestedIntx10_a2.a1.a0;
+  result += passStruct8BytesNestedIntx10_a2.a1.a1;
+  result += passStruct8BytesNestedIntx10_a3.a0.a0;
+  result += passStruct8BytesNestedIntx10_a3.a0.a1;
+  result += passStruct8BytesNestedIntx10_a3.a1.a0;
+  result += passStruct8BytesNestedIntx10_a3.a1.a1;
+  result += passStruct8BytesNestedIntx10_a4.a0.a0;
+  result += passStruct8BytesNestedIntx10_a4.a0.a1;
+  result += passStruct8BytesNestedIntx10_a4.a1.a0;
+  result += passStruct8BytesNestedIntx10_a4.a1.a1;
+  result += passStruct8BytesNestedIntx10_a5.a0.a0;
+  result += passStruct8BytesNestedIntx10_a5.a0.a1;
+  result += passStruct8BytesNestedIntx10_a5.a1.a0;
+  result += passStruct8BytesNestedIntx10_a5.a1.a1;
+  result += passStruct8BytesNestedIntx10_a6.a0.a0;
+  result += passStruct8BytesNestedIntx10_a6.a0.a1;
+  result += passStruct8BytesNestedIntx10_a6.a1.a0;
+  result += passStruct8BytesNestedIntx10_a6.a1.a1;
+  result += passStruct8BytesNestedIntx10_a7.a0.a0;
+  result += passStruct8BytesNestedIntx10_a7.a0.a1;
+  result += passStruct8BytesNestedIntx10_a7.a1.a0;
+  result += passStruct8BytesNestedIntx10_a7.a1.a1;
+  result += passStruct8BytesNestedIntx10_a8.a0.a0;
+  result += passStruct8BytesNestedIntx10_a8.a0.a1;
+  result += passStruct8BytesNestedIntx10_a8.a1.a0;
+  result += passStruct8BytesNestedIntx10_a8.a1.a1;
+  result += passStruct8BytesNestedIntx10_a9.a0.a0;
+  result += passStruct8BytesNestedIntx10_a9.a0.a1;
+  result += passStruct8BytesNestedIntx10_a9.a1.a0;
+  result += passStruct8BytesNestedIntx10_a9.a1.a1;
+
+  passStruct8BytesNestedIntx10Result = result;
+
+  return result;
+}
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust registers on all platforms.
+int passStruct8BytesNestedIntx10(
+    Struct8BytesNestedInt a0,
+    Struct8BytesNestedInt a1,
+    Struct8BytesNestedInt a2,
+    Struct8BytesNestedInt a3,
+    Struct8BytesNestedInt a4,
+    Struct8BytesNestedInt a5,
+    Struct8BytesNestedInt a6,
+    Struct8BytesNestedInt a7,
+    Struct8BytesNestedInt a8,
+    Struct8BytesNestedInt a9) {
+  print(
+      "passStruct8BytesNestedIntx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct8BytesNestedIntx10 throwing on purpuse!");
+  }
+
+  passStruct8BytesNestedIntx10_a0 = a0;
+  passStruct8BytesNestedIntx10_a1 = a1;
+  passStruct8BytesNestedIntx10_a2 = a2;
+  passStruct8BytesNestedIntx10_a3 = a3;
+  passStruct8BytesNestedIntx10_a4 = a4;
+  passStruct8BytesNestedIntx10_a5 = a5;
+  passStruct8BytesNestedIntx10_a6 = a6;
+  passStruct8BytesNestedIntx10_a7 = a7;
+  passStruct8BytesNestedIntx10_a8 = a8;
+  passStruct8BytesNestedIntx10_a9 = a9;
+
+  final result = passStruct8BytesNestedIntx10CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct8BytesNestedIntx10AfterCallback() {
+  final result = passStruct8BytesNestedIntx10CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(20, result);
+}
+
+typedef PassStruct8BytesNestedFloatx10Type = Float Function(
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat,
+    Struct8BytesNestedFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a0 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a1 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a2 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a3 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a4 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a5 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a6 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a7 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a8 =
+    Struct8BytesNestedFloat();
+Struct8BytesNestedFloat passStruct8BytesNestedFloatx10_a9 =
+    Struct8BytesNestedFloat();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesNestedFloatx10Result = 0.0;
+
+double passStruct8BytesNestedFloatx10CalculateResult() {
+  double result = 0;
+
+  result += passStruct8BytesNestedFloatx10_a0.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a0.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a1.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a1.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a2.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a2.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a3.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a3.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a4.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a4.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a5.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a5.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a6.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a6.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a7.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a7.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a8.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a8.a1.a0;
+  result += passStruct8BytesNestedFloatx10_a9.a0.a0;
+  result += passStruct8BytesNestedFloatx10_a9.a1.a0;
+
+  passStruct8BytesNestedFloatx10Result = result;
+
+  return result;
+}
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust fpu registers on all platforms.
+double passStruct8BytesNestedFloatx10(
+    Struct8BytesNestedFloat a0,
+    Struct8BytesNestedFloat a1,
+    Struct8BytesNestedFloat a2,
+    Struct8BytesNestedFloat a3,
+    Struct8BytesNestedFloat a4,
+    Struct8BytesNestedFloat a5,
+    Struct8BytesNestedFloat a6,
+    Struct8BytesNestedFloat a7,
+    Struct8BytesNestedFloat a8,
+    Struct8BytesNestedFloat a9) {
+  print(
+      "passStruct8BytesNestedFloatx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct8BytesNestedFloatx10 throwing on purpuse!");
+  }
+
+  passStruct8BytesNestedFloatx10_a0 = a0;
+  passStruct8BytesNestedFloatx10_a1 = a1;
+  passStruct8BytesNestedFloatx10_a2 = a2;
+  passStruct8BytesNestedFloatx10_a3 = a3;
+  passStruct8BytesNestedFloatx10_a4 = a4;
+  passStruct8BytesNestedFloatx10_a5 = a5;
+  passStruct8BytesNestedFloatx10_a6 = a6;
+  passStruct8BytesNestedFloatx10_a7 = a7;
+  passStruct8BytesNestedFloatx10_a8 = a8;
+  passStruct8BytesNestedFloatx10_a9 = a9;
+
+  final result = passStruct8BytesNestedFloatx10CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct8BytesNestedFloatx10AfterCallback() {
+  final result = passStruct8BytesNestedFloatx10CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct8BytesNestedFloat2x10Type = Float Function(
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2,
+    Struct8BytesNestedFloat2);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a0 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a1 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a2 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a3 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a4 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a5 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a6 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a7 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a8 =
+    Struct8BytesNestedFloat2();
+Struct8BytesNestedFloat2 passStruct8BytesNestedFloat2x10_a9 =
+    Struct8BytesNestedFloat2();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesNestedFloat2x10Result = 0.0;
+
+double passStruct8BytesNestedFloat2x10CalculateResult() {
+  double result = 0;
+
+  result += passStruct8BytesNestedFloat2x10_a0.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a0.a1;
+  result += passStruct8BytesNestedFloat2x10_a1.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a1.a1;
+  result += passStruct8BytesNestedFloat2x10_a2.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a2.a1;
+  result += passStruct8BytesNestedFloat2x10_a3.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a3.a1;
+  result += passStruct8BytesNestedFloat2x10_a4.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a4.a1;
+  result += passStruct8BytesNestedFloat2x10_a5.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a5.a1;
+  result += passStruct8BytesNestedFloat2x10_a6.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a6.a1;
+  result += passStruct8BytesNestedFloat2x10_a7.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a7.a1;
+  result += passStruct8BytesNestedFloat2x10_a8.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a8.a1;
+  result += passStruct8BytesNestedFloat2x10_a9.a0.a0;
+  result += passStruct8BytesNestedFloat2x10_a9.a1;
+
+  passStruct8BytesNestedFloat2x10Result = result;
+
+  return result;
+}
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust fpu registers on all platforms.
+/// The nesting is irregular, testing homogenous float rules on arm and arm64,
+/// and the fpu register usage on x64.
+double passStruct8BytesNestedFloat2x10(
+    Struct8BytesNestedFloat2 a0,
+    Struct8BytesNestedFloat2 a1,
+    Struct8BytesNestedFloat2 a2,
+    Struct8BytesNestedFloat2 a3,
+    Struct8BytesNestedFloat2 a4,
+    Struct8BytesNestedFloat2 a5,
+    Struct8BytesNestedFloat2 a6,
+    Struct8BytesNestedFloat2 a7,
+    Struct8BytesNestedFloat2 a8,
+    Struct8BytesNestedFloat2 a9) {
+  print(
+      "passStruct8BytesNestedFloat2x10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct8BytesNestedFloat2x10 throwing on purpuse!");
+  }
+
+  passStruct8BytesNestedFloat2x10_a0 = a0;
+  passStruct8BytesNestedFloat2x10_a1 = a1;
+  passStruct8BytesNestedFloat2x10_a2 = a2;
+  passStruct8BytesNestedFloat2x10_a3 = a3;
+  passStruct8BytesNestedFloat2x10_a4 = a4;
+  passStruct8BytesNestedFloat2x10_a5 = a5;
+  passStruct8BytesNestedFloat2x10_a6 = a6;
+  passStruct8BytesNestedFloat2x10_a7 = a7;
+  passStruct8BytesNestedFloat2x10_a8 = a8;
+  passStruct8BytesNestedFloat2x10_a9 = a9;
+
+  final result = passStruct8BytesNestedFloat2x10CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct8BytesNestedFloat2x10AfterCallback() {
+  final result = passStruct8BytesNestedFloat2x10CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.approxEquals(10.0, result);
+}
+
+typedef PassStruct8BytesNestedMixedx10Type = Double Function(
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed,
+    Struct8BytesNestedMixed);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a0 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a1 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a2 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a3 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a4 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a5 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a6 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a7 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a8 =
+    Struct8BytesNestedMixed();
+Struct8BytesNestedMixed passStruct8BytesNestedMixedx10_a9 =
+    Struct8BytesNestedMixed();
+
+// Result variable also global, so we can delete it after the callback.
+double passStruct8BytesNestedMixedx10Result = 0.0;
+
+double passStruct8BytesNestedMixedx10CalculateResult() {
+  double result = 0;
+
+  result += passStruct8BytesNestedMixedx10_a0.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a0.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a0.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a1.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a1.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a1.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a2.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a2.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a2.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a3.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a3.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a3.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a4.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a4.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a4.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a5.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a5.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a5.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a6.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a6.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a6.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a7.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a7.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a7.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a8.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a8.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a8.a1.a0;
+  result += passStruct8BytesNestedMixedx10_a9.a0.a0;
+  result += passStruct8BytesNestedMixedx10_a9.a0.a1;
+  result += passStruct8BytesNestedMixedx10_a9.a1.a0;
+
+  passStruct8BytesNestedMixedx10Result = result;
+
+  return result;
+}
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust all registers on all platforms.
+double passStruct8BytesNestedMixedx10(
+    Struct8BytesNestedMixed a0,
+    Struct8BytesNestedMixed a1,
+    Struct8BytesNestedMixed a2,
+    Struct8BytesNestedMixed a3,
+    Struct8BytesNestedMixed a4,
+    Struct8BytesNestedMixed a5,
+    Struct8BytesNestedMixed a6,
+    Struct8BytesNestedMixed a7,
+    Struct8BytesNestedMixed a8,
+    Struct8BytesNestedMixed a9) {
+  print(
+      "passStruct8BytesNestedMixedx10(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct8BytesNestedMixedx10 throwing on purpuse!");
+  }
+
+  passStruct8BytesNestedMixedx10_a0 = a0;
+  passStruct8BytesNestedMixedx10_a1 = a1;
+  passStruct8BytesNestedMixedx10_a2 = a2;
+  passStruct8BytesNestedMixedx10_a3 = a3;
+  passStruct8BytesNestedMixedx10_a4 = a4;
+  passStruct8BytesNestedMixedx10_a5 = a5;
+  passStruct8BytesNestedMixedx10_a6 = a6;
+  passStruct8BytesNestedMixedx10_a7 = a7;
+  passStruct8BytesNestedMixedx10_a8 = a8;
+  passStruct8BytesNestedMixedx10_a9 = a9;
+
+  final result = passStruct8BytesNestedMixedx10CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct8BytesNestedMixedx10AfterCallback() {
+  final result = passStruct8BytesNestedMixedx10CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.approxEquals(15.0, result);
+}
+
+typedef PassStruct16BytesNestedIntx2Type = Int64 Function(
+    Struct16BytesNestedInt, Struct16BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesNestedInt passStruct16BytesNestedIntx2_a0 =
+    Struct16BytesNestedInt();
+Struct16BytesNestedInt passStruct16BytesNestedIntx2_a1 =
+    Struct16BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct16BytesNestedIntx2Result = 0;
+
+int passStruct16BytesNestedIntx2CalculateResult() {
+  int result = 0;
+
+  result += passStruct16BytesNestedIntx2_a0.a0.a0.a0;
+  result += passStruct16BytesNestedIntx2_a0.a0.a0.a1;
+  result += passStruct16BytesNestedIntx2_a0.a0.a1.a0;
+  result += passStruct16BytesNestedIntx2_a0.a0.a1.a1;
+  result += passStruct16BytesNestedIntx2_a0.a1.a0.a0;
+  result += passStruct16BytesNestedIntx2_a0.a1.a0.a1;
+  result += passStruct16BytesNestedIntx2_a0.a1.a1.a0;
+  result += passStruct16BytesNestedIntx2_a0.a1.a1.a1;
+  result += passStruct16BytesNestedIntx2_a1.a0.a0.a0;
+  result += passStruct16BytesNestedIntx2_a1.a0.a0.a1;
+  result += passStruct16BytesNestedIntx2_a1.a0.a1.a0;
+  result += passStruct16BytesNestedIntx2_a1.a0.a1.a1;
+  result += passStruct16BytesNestedIntx2_a1.a1.a0.a0;
+  result += passStruct16BytesNestedIntx2_a1.a1.a0.a1;
+  result += passStruct16BytesNestedIntx2_a1.a1.a1.a0;
+  result += passStruct16BytesNestedIntx2_a1.a1.a1.a1;
+
+  passStruct16BytesNestedIntx2Result = result;
+
+  return result;
+}
+
+/// Deeper nested struct to test recursive member access.
+int passStruct16BytesNestedIntx2(
+    Struct16BytesNestedInt a0, Struct16BytesNestedInt a1) {
+  print("passStruct16BytesNestedIntx2(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0.a0 == 42 || a0.a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct16BytesNestedIntx2 throwing on purpuse!");
+  }
+
+  passStruct16BytesNestedIntx2_a0 = a0;
+  passStruct16BytesNestedIntx2_a1 = a1;
+
+  final result = passStruct16BytesNestedIntx2CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct16BytesNestedIntx2AfterCallback() {
+  final result = passStruct16BytesNestedIntx2CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(8, result);
+}
+
+typedef PassStruct32BytesNestedIntx2Type = Int64 Function(
+    Struct32BytesNestedInt, Struct32BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct32BytesNestedInt passStruct32BytesNestedIntx2_a0 =
+    Struct32BytesNestedInt();
+Struct32BytesNestedInt passStruct32BytesNestedIntx2_a1 =
+    Struct32BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+int passStruct32BytesNestedIntx2Result = 0;
+
+int passStruct32BytesNestedIntx2CalculateResult() {
+  int result = 0;
+
+  result += passStruct32BytesNestedIntx2_a0.a0.a0.a0.a0;
+  result += passStruct32BytesNestedIntx2_a0.a0.a0.a0.a1;
+  result += passStruct32BytesNestedIntx2_a0.a0.a0.a1.a0;
+  result += passStruct32BytesNestedIntx2_a0.a0.a0.a1.a1;
+  result += passStruct32BytesNestedIntx2_a0.a0.a1.a0.a0;
+  result += passStruct32BytesNestedIntx2_a0.a0.a1.a0.a1;
+  result += passStruct32BytesNestedIntx2_a0.a0.a1.a1.a0;
+  result += passStruct32BytesNestedIntx2_a0.a0.a1.a1.a1;
+  result += passStruct32BytesNestedIntx2_a0.a1.a0.a0.a0;
+  result += passStruct32BytesNestedIntx2_a0.a1.a0.a0.a1;
+  result += passStruct32BytesNestedIntx2_a0.a1.a0.a1.a0;
+  result += passStruct32BytesNestedIntx2_a0.a1.a0.a1.a1;
+  result += passStruct32BytesNestedIntx2_a0.a1.a1.a0.a0;
+  result += passStruct32BytesNestedIntx2_a0.a1.a1.a0.a1;
+  result += passStruct32BytesNestedIntx2_a0.a1.a1.a1.a0;
+  result += passStruct32BytesNestedIntx2_a0.a1.a1.a1.a1;
+  result += passStruct32BytesNestedIntx2_a1.a0.a0.a0.a0;
+  result += passStruct32BytesNestedIntx2_a1.a0.a0.a0.a1;
+  result += passStruct32BytesNestedIntx2_a1.a0.a0.a1.a0;
+  result += passStruct32BytesNestedIntx2_a1.a0.a0.a1.a1;
+  result += passStruct32BytesNestedIntx2_a1.a0.a1.a0.a0;
+  result += passStruct32BytesNestedIntx2_a1.a0.a1.a0.a1;
+  result += passStruct32BytesNestedIntx2_a1.a0.a1.a1.a0;
+  result += passStruct32BytesNestedIntx2_a1.a0.a1.a1.a1;
+  result += passStruct32BytesNestedIntx2_a1.a1.a0.a0.a0;
+  result += passStruct32BytesNestedIntx2_a1.a1.a0.a0.a1;
+  result += passStruct32BytesNestedIntx2_a1.a1.a0.a1.a0;
+  result += passStruct32BytesNestedIntx2_a1.a1.a0.a1.a1;
+  result += passStruct32BytesNestedIntx2_a1.a1.a1.a0.a0;
+  result += passStruct32BytesNestedIntx2_a1.a1.a1.a0.a1;
+  result += passStruct32BytesNestedIntx2_a1.a1.a1.a1.a0;
+  result += passStruct32BytesNestedIntx2_a1.a1.a1.a1.a1;
+
+  passStruct32BytesNestedIntx2Result = result;
+
+  return result;
+}
+
+/// Even deeper nested struct to test recursive member access.
+int passStruct32BytesNestedIntx2(
+    Struct32BytesNestedInt a0, Struct32BytesNestedInt a1) {
+  print("passStruct32BytesNestedIntx2(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0.a0.a0 == 42 || a0.a0.a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("PassStruct32BytesNestedIntx2 throwing on purpuse!");
+  }
+
+  passStruct32BytesNestedIntx2_a0 = a0;
+  passStruct32BytesNestedIntx2_a1 = a1;
+
+  final result = passStruct32BytesNestedIntx2CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStruct32BytesNestedIntx2AfterCallback() {
+  final result = passStruct32BytesNestedIntx2CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(16, result);
+}
+
+typedef PassStructNestedIntStructAlignmentInt16Type = Int64 Function(
+    StructNestedIntStructAlignmentInt16);
+
+// Global variables to be able to test inputs after callback returned.
+StructNestedIntStructAlignmentInt16 passStructNestedIntStructAlignmentInt16_a0 =
+    StructNestedIntStructAlignmentInt16();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructNestedIntStructAlignmentInt16Result = 0;
+
+int passStructNestedIntStructAlignmentInt16CalculateResult() {
+  int result = 0;
+
+  result += passStructNestedIntStructAlignmentInt16_a0.a0.a0;
+  result += passStructNestedIntStructAlignmentInt16_a0.a0.a1;
+  result += passStructNestedIntStructAlignmentInt16_a0.a0.a2;
+  result += passStructNestedIntStructAlignmentInt16_a0.a1.a0;
+  result += passStructNestedIntStructAlignmentInt16_a0.a1.a1;
+  result += passStructNestedIntStructAlignmentInt16_a0.a1.a2;
+
+  passStructNestedIntStructAlignmentInt16Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 16 byte int.
+int passStructNestedIntStructAlignmentInt16(
+    StructNestedIntStructAlignmentInt16 a0) {
+  print("passStructNestedIntStructAlignmentInt16(${a0})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "PassStructNestedIntStructAlignmentInt16 throwing on purpuse!");
+  }
+
+  passStructNestedIntStructAlignmentInt16_a0 = a0;
+
+  final result = passStructNestedIntStructAlignmentInt16CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStructNestedIntStructAlignmentInt16AfterCallback() {
+  final result = passStructNestedIntStructAlignmentInt16CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(3, result);
+}
+
+typedef PassStructNestedIntStructAlignmentInt32Type = Int64 Function(
+    StructNestedIntStructAlignmentInt32);
+
+// Global variables to be able to test inputs after callback returned.
+StructNestedIntStructAlignmentInt32 passStructNestedIntStructAlignmentInt32_a0 =
+    StructNestedIntStructAlignmentInt32();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructNestedIntStructAlignmentInt32Result = 0;
+
+int passStructNestedIntStructAlignmentInt32CalculateResult() {
+  int result = 0;
+
+  result += passStructNestedIntStructAlignmentInt32_a0.a0.a0;
+  result += passStructNestedIntStructAlignmentInt32_a0.a0.a1;
+  result += passStructNestedIntStructAlignmentInt32_a0.a0.a2;
+  result += passStructNestedIntStructAlignmentInt32_a0.a1.a0;
+  result += passStructNestedIntStructAlignmentInt32_a0.a1.a1;
+  result += passStructNestedIntStructAlignmentInt32_a0.a1.a2;
+
+  passStructNestedIntStructAlignmentInt32Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 32 byte int.
+int passStructNestedIntStructAlignmentInt32(
+    StructNestedIntStructAlignmentInt32 a0) {
+  print("passStructNestedIntStructAlignmentInt32(${a0})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "PassStructNestedIntStructAlignmentInt32 throwing on purpuse!");
+  }
+
+  passStructNestedIntStructAlignmentInt32_a0 = a0;
+
+  final result = passStructNestedIntStructAlignmentInt32CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStructNestedIntStructAlignmentInt32AfterCallback() {
+  final result = passStructNestedIntStructAlignmentInt32CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(3, result);
+}
+
+typedef PassStructNestedIntStructAlignmentInt64Type = Int64 Function(
+    StructNestedIntStructAlignmentInt64);
+
+// Global variables to be able to test inputs after callback returned.
+StructNestedIntStructAlignmentInt64 passStructNestedIntStructAlignmentInt64_a0 =
+    StructNestedIntStructAlignmentInt64();
+
+// Result variable also global, so we can delete it after the callback.
+int passStructNestedIntStructAlignmentInt64Result = 0;
+
+int passStructNestedIntStructAlignmentInt64CalculateResult() {
+  int result = 0;
+
+  result += passStructNestedIntStructAlignmentInt64_a0.a0.a0;
+  result += passStructNestedIntStructAlignmentInt64_a0.a0.a1;
+  result += passStructNestedIntStructAlignmentInt64_a0.a0.a2;
+  result += passStructNestedIntStructAlignmentInt64_a0.a1.a0;
+  result += passStructNestedIntStructAlignmentInt64_a0.a1.a1;
+  result += passStructNestedIntStructAlignmentInt64_a0.a1.a2;
+
+  passStructNestedIntStructAlignmentInt64Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 64 byte int.
+int passStructNestedIntStructAlignmentInt64(
+    StructNestedIntStructAlignmentInt64 a0) {
+  print("passStructNestedIntStructAlignmentInt64(${a0})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "PassStructNestedIntStructAlignmentInt64 throwing on purpuse!");
+  }
+
+  passStructNestedIntStructAlignmentInt64_a0 = a0;
+
+  final result = passStructNestedIntStructAlignmentInt64CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStructNestedIntStructAlignmentInt64AfterCallback() {
+  final result = passStructNestedIntStructAlignmentInt64CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.equals(3, result);
+}
+
+typedef PassStructNestedIrregularEvenBiggerx4Type = Double Function(
+    StructNestedIrregularEvenBigger,
+    StructNestedIrregularEvenBigger,
+    StructNestedIrregularEvenBigger,
+    StructNestedIrregularEvenBigger);
+
+// Global variables to be able to test inputs after callback returned.
+StructNestedIrregularEvenBigger passStructNestedIrregularEvenBiggerx4_a0 =
+    StructNestedIrregularEvenBigger();
+StructNestedIrregularEvenBigger passStructNestedIrregularEvenBiggerx4_a1 =
+    StructNestedIrregularEvenBigger();
+StructNestedIrregularEvenBigger passStructNestedIrregularEvenBiggerx4_a2 =
+    StructNestedIrregularEvenBigger();
+StructNestedIrregularEvenBigger passStructNestedIrregularEvenBiggerx4_a3 =
+    StructNestedIrregularEvenBigger();
+
+// Result variable also global, so we can delete it after the callback.
+double passStructNestedIrregularEvenBiggerx4Result = 0.0;
+
+double passStructNestedIrregularEvenBiggerx4CalculateResult() {
+  double result = 0;
+
+  result += passStructNestedIrregularEvenBiggerx4_a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a0.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a1.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a3.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a3.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a4;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a5.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a5.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a0.a6;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a1.a0.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a1.a0.a1;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a1.a1.a0;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a2;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a2.a3;
+  result += passStructNestedIrregularEvenBiggerx4_a3.a3;
+
+  passStructNestedIrregularEvenBiggerx4Result = result;
+
+  return result;
+}
+
+/// Return big irregular struct as smoke test.
+double passStructNestedIrregularEvenBiggerx4(
+    StructNestedIrregularEvenBigger a0,
+    StructNestedIrregularEvenBigger a1,
+    StructNestedIrregularEvenBigger a2,
+    StructNestedIrregularEvenBigger a3) {
+  print("passStructNestedIrregularEvenBiggerx4(${a0}, ${a1}, ${a2}, ${a3})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "PassStructNestedIrregularEvenBiggerx4 throwing on purpuse!");
+  }
+
+  passStructNestedIrregularEvenBiggerx4_a0 = a0;
+  passStructNestedIrregularEvenBiggerx4_a1 = a1;
+  passStructNestedIrregularEvenBiggerx4_a2 = a2;
+  passStructNestedIrregularEvenBiggerx4_a3 = a3;
+
+  final result = passStructNestedIrregularEvenBiggerx4CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void passStructNestedIrregularEvenBiggerx4AfterCallback() {
+  final result = passStructNestedIrregularEvenBiggerx4CalculateResult();
+
+  print("after callback result = $result");
+
+  Expect.approxEquals(1572.0, result);
+}
+
 typedef ReturnStruct1ByteIntType = Struct1ByteInt Function(Int8);
 
 // Global variables to be able to test inputs after callback returned.
@@ -4265,7 +5413,7 @@
 Struct1ByteInt returnStruct1ByteIntResult = Struct1ByteInt();
 
 Struct1ByteInt returnStruct1ByteIntCalculateResult() {
-  Struct1ByteInt result = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt result = calloc<Struct1ByteInt>().ref;
 
   result.a0 = returnStruct1ByteInt_a0;
 
@@ -4300,13 +5448,13 @@
 }
 
 void returnStruct1ByteIntAfterCallback() {
-  free(returnStruct1ByteIntResult.addressOf);
+  calloc.free(returnStruct1ByteIntResult.addressOf);
 
   final result = returnStruct1ByteIntCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct1ByteIntResult.addressOf);
+  calloc.free(returnStruct1ByteIntResult.addressOf);
 }
 
 typedef ReturnStruct3BytesHomogeneousUint8Type = Struct3BytesHomogeneousUint8
@@ -4324,7 +5472,7 @@
 Struct3BytesHomogeneousUint8
     returnStruct3BytesHomogeneousUint8CalculateResult() {
   Struct3BytesHomogeneousUint8 result =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
+      calloc<Struct3BytesHomogeneousUint8>().ref;
 
   result.a0 = returnStruct3BytesHomogeneousUint8_a0;
   result.a1 = returnStruct3BytesHomogeneousUint8_a1;
@@ -4364,13 +5512,13 @@
 }
 
 void returnStruct3BytesHomogeneousUint8AfterCallback() {
-  free(returnStruct3BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct3BytesHomogeneousUint8Result.addressOf);
 
   final result = returnStruct3BytesHomogeneousUint8CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct3BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct3BytesHomogeneousUint8Result.addressOf);
 }
 
 typedef ReturnStruct3BytesInt2ByteAlignedType = Struct3BytesInt2ByteAligned
@@ -4386,7 +5534,7 @@
 
 Struct3BytesInt2ByteAligned returnStruct3BytesInt2ByteAlignedCalculateResult() {
   Struct3BytesInt2ByteAligned result =
-      allocate<Struct3BytesInt2ByteAligned>().ref;
+      calloc<Struct3BytesInt2ByteAligned>().ref;
 
   result.a0 = returnStruct3BytesInt2ByteAligned_a0;
   result.a1 = returnStruct3BytesInt2ByteAligned_a1;
@@ -4424,13 +5572,13 @@
 }
 
 void returnStruct3BytesInt2ByteAlignedAfterCallback() {
-  free(returnStruct3BytesInt2ByteAlignedResult.addressOf);
+  calloc.free(returnStruct3BytesInt2ByteAlignedResult.addressOf);
 
   final result = returnStruct3BytesInt2ByteAlignedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct3BytesInt2ByteAlignedResult.addressOf);
+  calloc.free(returnStruct3BytesInt2ByteAlignedResult.addressOf);
 }
 
 typedef ReturnStruct4BytesHomogeneousInt16Type = Struct4BytesHomogeneousInt16
@@ -4447,7 +5595,7 @@
 Struct4BytesHomogeneousInt16
     returnStruct4BytesHomogeneousInt16CalculateResult() {
   Struct4BytesHomogeneousInt16 result =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
+      calloc<Struct4BytesHomogeneousInt16>().ref;
 
   result.a0 = returnStruct4BytesHomogeneousInt16_a0;
   result.a1 = returnStruct4BytesHomogeneousInt16_a1;
@@ -4485,13 +5633,13 @@
 }
 
 void returnStruct4BytesHomogeneousInt16AfterCallback() {
-  free(returnStruct4BytesHomogeneousInt16Result.addressOf);
+  calloc.free(returnStruct4BytesHomogeneousInt16Result.addressOf);
 
   final result = returnStruct4BytesHomogeneousInt16CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct4BytesHomogeneousInt16Result.addressOf);
+  calloc.free(returnStruct4BytesHomogeneousInt16Result.addressOf);
 }
 
 typedef ReturnStruct7BytesHomogeneousUint8Type = Struct7BytesHomogeneousUint8
@@ -4513,7 +5661,7 @@
 Struct7BytesHomogeneousUint8
     returnStruct7BytesHomogeneousUint8CalculateResult() {
   Struct7BytesHomogeneousUint8 result =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
+      calloc<Struct7BytesHomogeneousUint8>().ref;
 
   result.a0 = returnStruct7BytesHomogeneousUint8_a0;
   result.a1 = returnStruct7BytesHomogeneousUint8_a1;
@@ -4562,13 +5710,13 @@
 }
 
 void returnStruct7BytesHomogeneousUint8AfterCallback() {
-  free(returnStruct7BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct7BytesHomogeneousUint8Result.addressOf);
 
   final result = returnStruct7BytesHomogeneousUint8CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct7BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct7BytesHomogeneousUint8Result.addressOf);
 }
 
 typedef ReturnStruct7BytesInt4ByteAlignedType = Struct7BytesInt4ByteAligned
@@ -4585,7 +5733,7 @@
 
 Struct7BytesInt4ByteAligned returnStruct7BytesInt4ByteAlignedCalculateResult() {
   Struct7BytesInt4ByteAligned result =
-      allocate<Struct7BytesInt4ByteAligned>().ref;
+      calloc<Struct7BytesInt4ByteAligned>().ref;
 
   result.a0 = returnStruct7BytesInt4ByteAligned_a0;
   result.a1 = returnStruct7BytesInt4ByteAligned_a1;
@@ -4626,13 +5774,13 @@
 }
 
 void returnStruct7BytesInt4ByteAlignedAfterCallback() {
-  free(returnStruct7BytesInt4ByteAlignedResult.addressOf);
+  calloc.free(returnStruct7BytesInt4ByteAlignedResult.addressOf);
 
   final result = returnStruct7BytesInt4ByteAlignedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct7BytesInt4ByteAlignedResult.addressOf);
+  calloc.free(returnStruct7BytesInt4ByteAlignedResult.addressOf);
 }
 
 typedef ReturnStruct8BytesIntType = Struct8BytesInt Function(
@@ -4647,7 +5795,7 @@
 Struct8BytesInt returnStruct8BytesIntResult = Struct8BytesInt();
 
 Struct8BytesInt returnStruct8BytesIntCalculateResult() {
-  Struct8BytesInt result = allocate<Struct8BytesInt>().ref;
+  Struct8BytesInt result = calloc<Struct8BytesInt>().ref;
 
   result.a0 = returnStruct8BytesInt_a0;
   result.a1 = returnStruct8BytesInt_a1;
@@ -4686,13 +5834,13 @@
 }
 
 void returnStruct8BytesIntAfterCallback() {
-  free(returnStruct8BytesIntResult.addressOf);
+  calloc.free(returnStruct8BytesIntResult.addressOf);
 
   final result = returnStruct8BytesIntCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct8BytesIntResult.addressOf);
+  calloc.free(returnStruct8BytesIntResult.addressOf);
 }
 
 typedef ReturnStruct8BytesHomogeneousFloatType = Struct8BytesHomogeneousFloat
@@ -4709,7 +5857,7 @@
 Struct8BytesHomogeneousFloat
     returnStruct8BytesHomogeneousFloatCalculateResult() {
   Struct8BytesHomogeneousFloat result =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+      calloc<Struct8BytesHomogeneousFloat>().ref;
 
   result.a0 = returnStruct8BytesHomogeneousFloat_a0;
   result.a1 = returnStruct8BytesHomogeneousFloat_a1;
@@ -4747,13 +5895,13 @@
 }
 
 void returnStruct8BytesHomogeneousFloatAfterCallback() {
-  free(returnStruct8BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct8BytesHomogeneousFloatResult.addressOf);
 
   final result = returnStruct8BytesHomogeneousFloatCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct8BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct8BytesHomogeneousFloatResult.addressOf);
 }
 
 typedef ReturnStruct8BytesMixedType = Struct8BytesMixed Function(
@@ -4768,7 +5916,7 @@
 Struct8BytesMixed returnStruct8BytesMixedResult = Struct8BytesMixed();
 
 Struct8BytesMixed returnStruct8BytesMixedCalculateResult() {
-  Struct8BytesMixed result = allocate<Struct8BytesMixed>().ref;
+  Struct8BytesMixed result = calloc<Struct8BytesMixed>().ref;
 
   result.a0 = returnStruct8BytesMixed_a0;
   result.a1 = returnStruct8BytesMixed_a1;
@@ -4807,13 +5955,13 @@
 }
 
 void returnStruct8BytesMixedAfterCallback() {
-  free(returnStruct8BytesMixedResult.addressOf);
+  calloc.free(returnStruct8BytesMixedResult.addressOf);
 
   final result = returnStruct8BytesMixedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct8BytesMixedResult.addressOf);
+  calloc.free(returnStruct8BytesMixedResult.addressOf);
 }
 
 typedef ReturnStruct9BytesHomogeneousUint8Type = Struct9BytesHomogeneousUint8
@@ -4837,7 +5985,7 @@
 Struct9BytesHomogeneousUint8
     returnStruct9BytesHomogeneousUint8CalculateResult() {
   Struct9BytesHomogeneousUint8 result =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
+      calloc<Struct9BytesHomogeneousUint8>().ref;
 
   result.a0 = returnStruct9BytesHomogeneousUint8_a0;
   result.a1 = returnStruct9BytesHomogeneousUint8_a1;
@@ -4892,13 +6040,13 @@
 }
 
 void returnStruct9BytesHomogeneousUint8AfterCallback() {
-  free(returnStruct9BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct9BytesHomogeneousUint8Result.addressOf);
 
   final result = returnStruct9BytesHomogeneousUint8CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct9BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct9BytesHomogeneousUint8Result.addressOf);
 }
 
 typedef ReturnStruct9BytesInt4Or8ByteAlignedType
@@ -4915,7 +6063,7 @@
 Struct9BytesInt4Or8ByteAligned
     returnStruct9BytesInt4Or8ByteAlignedCalculateResult() {
   Struct9BytesInt4Or8ByteAligned result =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
 
   result.a0 = returnStruct9BytesInt4Or8ByteAligned_a0;
   result.a1 = returnStruct9BytesInt4Or8ByteAligned_a1;
@@ -4955,13 +6103,13 @@
 }
 
 void returnStruct9BytesInt4Or8ByteAlignedAfterCallback() {
-  free(returnStruct9BytesInt4Or8ByteAlignedResult.addressOf);
+  calloc.free(returnStruct9BytesInt4Or8ByteAlignedResult.addressOf);
 
   final result = returnStruct9BytesInt4Or8ByteAlignedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct9BytesInt4Or8ByteAlignedResult.addressOf);
+  calloc.free(returnStruct9BytesInt4Or8ByteAlignedResult.addressOf);
 }
 
 typedef ReturnStruct12BytesHomogeneousFloatType = Struct12BytesHomogeneousFloat
@@ -4979,7 +6127,7 @@
 Struct12BytesHomogeneousFloat
     returnStruct12BytesHomogeneousFloatCalculateResult() {
   Struct12BytesHomogeneousFloat result =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
 
   result.a0 = returnStruct12BytesHomogeneousFloat_a0;
   result.a1 = returnStruct12BytesHomogeneousFloat_a1;
@@ -5020,13 +6168,13 @@
 }
 
 void returnStruct12BytesHomogeneousFloatAfterCallback() {
-  free(returnStruct12BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct12BytesHomogeneousFloatResult.addressOf);
 
   final result = returnStruct12BytesHomogeneousFloatCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct12BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct12BytesHomogeneousFloatResult.addressOf);
 }
 
 typedef ReturnStruct16BytesHomogeneousFloatType = Struct16BytesHomogeneousFloat
@@ -5045,7 +6193,7 @@
 Struct16BytesHomogeneousFloat
     returnStruct16BytesHomogeneousFloatCalculateResult() {
   Struct16BytesHomogeneousFloat result =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
 
   result.a0 = returnStruct16BytesHomogeneousFloat_a0;
   result.a1 = returnStruct16BytesHomogeneousFloat_a1;
@@ -5087,13 +6235,13 @@
 }
 
 void returnStruct16BytesHomogeneousFloatAfterCallback() {
-  free(returnStruct16BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct16BytesHomogeneousFloatResult.addressOf);
 
   final result = returnStruct16BytesHomogeneousFloatCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct16BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct16BytesHomogeneousFloatResult.addressOf);
 }
 
 typedef ReturnStruct16BytesMixedType = Struct16BytesMixed Function(
@@ -5107,7 +6255,7 @@
 Struct16BytesMixed returnStruct16BytesMixedResult = Struct16BytesMixed();
 
 Struct16BytesMixed returnStruct16BytesMixedCalculateResult() {
-  Struct16BytesMixed result = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed result = calloc<Struct16BytesMixed>().ref;
 
   result.a0 = returnStruct16BytesMixed_a0;
   result.a1 = returnStruct16BytesMixed_a1;
@@ -5144,13 +6292,13 @@
 }
 
 void returnStruct16BytesMixedAfterCallback() {
-  free(returnStruct16BytesMixedResult.addressOf);
+  calloc.free(returnStruct16BytesMixedResult.addressOf);
 
   final result = returnStruct16BytesMixedCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct16BytesMixedResult.addressOf);
+  calloc.free(returnStruct16BytesMixedResult.addressOf);
 }
 
 typedef ReturnStruct16BytesMixed2Type = Struct16BytesMixed2 Function(
@@ -5166,7 +6314,7 @@
 Struct16BytesMixed2 returnStruct16BytesMixed2Result = Struct16BytesMixed2();
 
 Struct16BytesMixed2 returnStruct16BytesMixed2CalculateResult() {
-  Struct16BytesMixed2 result = allocate<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 result = calloc<Struct16BytesMixed2>().ref;
 
   result.a0 = returnStruct16BytesMixed2_a0;
   result.a1 = returnStruct16BytesMixed2_a1;
@@ -5209,13 +6357,13 @@
 }
 
 void returnStruct16BytesMixed2AfterCallback() {
-  free(returnStruct16BytesMixed2Result.addressOf);
+  calloc.free(returnStruct16BytesMixed2Result.addressOf);
 
   final result = returnStruct16BytesMixed2CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct16BytesMixed2Result.addressOf);
+  calloc.free(returnStruct16BytesMixed2Result.addressOf);
 }
 
 typedef ReturnStruct17BytesIntType = Struct17BytesInt Function(
@@ -5230,7 +6378,7 @@
 Struct17BytesInt returnStruct17BytesIntResult = Struct17BytesInt();
 
 Struct17BytesInt returnStruct17BytesIntCalculateResult() {
-  Struct17BytesInt result = allocate<Struct17BytesInt>().ref;
+  Struct17BytesInt result = calloc<Struct17BytesInt>().ref;
 
   result.a0 = returnStruct17BytesInt_a0;
   result.a1 = returnStruct17BytesInt_a1;
@@ -5271,13 +6419,13 @@
 }
 
 void returnStruct17BytesIntAfterCallback() {
-  free(returnStruct17BytesIntResult.addressOf);
+  calloc.free(returnStruct17BytesIntResult.addressOf);
 
   final result = returnStruct17BytesIntCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct17BytesIntResult.addressOf);
+  calloc.free(returnStruct17BytesIntResult.addressOf);
 }
 
 typedef ReturnStruct19BytesHomogeneousUint8Type
@@ -5330,7 +6478,7 @@
 Struct19BytesHomogeneousUint8
     returnStruct19BytesHomogeneousUint8CalculateResult() {
   Struct19BytesHomogeneousUint8 result =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
 
   result.a0 = returnStruct19BytesHomogeneousUint8_a0;
   result.a1 = returnStruct19BytesHomogeneousUint8_a1;
@@ -5423,13 +6571,13 @@
 }
 
 void returnStruct19BytesHomogeneousUint8AfterCallback() {
-  free(returnStruct19BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct19BytesHomogeneousUint8Result.addressOf);
 
   final result = returnStruct19BytesHomogeneousUint8CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct19BytesHomogeneousUint8Result.addressOf);
+  calloc.free(returnStruct19BytesHomogeneousUint8Result.addressOf);
 }
 
 typedef ReturnStruct20BytesHomogeneousInt32Type = Struct20BytesHomogeneousInt32
@@ -5449,7 +6597,7 @@
 Struct20BytesHomogeneousInt32
     returnStruct20BytesHomogeneousInt32CalculateResult() {
   Struct20BytesHomogeneousInt32 result =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
 
   result.a0 = returnStruct20BytesHomogeneousInt32_a0;
   result.a1 = returnStruct20BytesHomogeneousInt32_a1;
@@ -5494,13 +6642,13 @@
 }
 
 void returnStruct20BytesHomogeneousInt32AfterCallback() {
-  free(returnStruct20BytesHomogeneousInt32Result.addressOf);
+  calloc.free(returnStruct20BytesHomogeneousInt32Result.addressOf);
 
   final result = returnStruct20BytesHomogeneousInt32CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct20BytesHomogeneousInt32Result.addressOf);
+  calloc.free(returnStruct20BytesHomogeneousInt32Result.addressOf);
 }
 
 typedef ReturnStruct20BytesHomogeneousFloatType = Struct20BytesHomogeneousFloat
@@ -5520,7 +6668,7 @@
 Struct20BytesHomogeneousFloat
     returnStruct20BytesHomogeneousFloatCalculateResult() {
   Struct20BytesHomogeneousFloat result =
-      allocate<Struct20BytesHomogeneousFloat>().ref;
+      calloc<Struct20BytesHomogeneousFloat>().ref;
 
   result.a0 = returnStruct20BytesHomogeneousFloat_a0;
   result.a1 = returnStruct20BytesHomogeneousFloat_a1;
@@ -5565,13 +6713,13 @@
 }
 
 void returnStruct20BytesHomogeneousFloatAfterCallback() {
-  free(returnStruct20BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct20BytesHomogeneousFloatResult.addressOf);
 
   final result = returnStruct20BytesHomogeneousFloatCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct20BytesHomogeneousFloatResult.addressOf);
+  calloc.free(returnStruct20BytesHomogeneousFloatResult.addressOf);
 }
 
 typedef ReturnStruct32BytesHomogeneousDoubleType
@@ -5590,7 +6738,7 @@
 Struct32BytesHomogeneousDouble
     returnStruct32BytesHomogeneousDoubleCalculateResult() {
   Struct32BytesHomogeneousDouble result =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
 
   result.a0 = returnStruct32BytesHomogeneousDouble_a0;
   result.a1 = returnStruct32BytesHomogeneousDouble_a1;
@@ -5633,13 +6781,13 @@
 }
 
 void returnStruct32BytesHomogeneousDoubleAfterCallback() {
-  free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
+  calloc.free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
 
   final result = returnStruct32BytesHomogeneousDoubleCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
+  calloc.free(returnStruct32BytesHomogeneousDoubleResult.addressOf);
 }
 
 typedef ReturnStruct40BytesHomogeneousDoubleType
@@ -5660,7 +6808,7 @@
 Struct40BytesHomogeneousDouble
     returnStruct40BytesHomogeneousDoubleCalculateResult() {
   Struct40BytesHomogeneousDouble result =
-      allocate<Struct40BytesHomogeneousDouble>().ref;
+      calloc<Struct40BytesHomogeneousDouble>().ref;
 
   result.a0 = returnStruct40BytesHomogeneousDouble_a0;
   result.a1 = returnStruct40BytesHomogeneousDouble_a1;
@@ -5706,13 +6854,13 @@
 }
 
 void returnStruct40BytesHomogeneousDoubleAfterCallback() {
-  free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
+  calloc.free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
 
   final result = returnStruct40BytesHomogeneousDoubleCalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
+  calloc.free(returnStruct40BytesHomogeneousDoubleResult.addressOf);
 }
 
 typedef ReturnStruct1024BytesHomogeneousUint64Type
@@ -5983,7 +7131,7 @@
 Struct1024BytesHomogeneousUint64
     returnStruct1024BytesHomogeneousUint64CalculateResult() {
   Struct1024BytesHomogeneousUint64 result =
-      allocate<Struct1024BytesHomogeneousUint64>().ref;
+      calloc<Struct1024BytesHomogeneousUint64>().ref;
 
   result.a0 = returnStruct1024BytesHomogeneousUint64_a0;
   result.a1 = returnStruct1024BytesHomogeneousUint64_a1;
@@ -6402,13 +7550,13 @@
 }
 
 void returnStruct1024BytesHomogeneousUint64AfterCallback() {
-  free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
+  calloc.free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
 
   final result = returnStruct1024BytesHomogeneousUint64CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
+  calloc.free(returnStruct1024BytesHomogeneousUint64Result.addressOf);
 }
 
 typedef ReturnStructArgumentStruct1ByteIntType = Struct1ByteInt Function(
@@ -6747,7 +7895,7 @@
 StructAlignmentInt16 returnStructAlignmentInt16Result = StructAlignmentInt16();
 
 StructAlignmentInt16 returnStructAlignmentInt16CalculateResult() {
-  StructAlignmentInt16 result = allocate<StructAlignmentInt16>().ref;
+  StructAlignmentInt16 result = calloc<StructAlignmentInt16>().ref;
 
   result.a0 = returnStructAlignmentInt16_a0;
   result.a1 = returnStructAlignmentInt16_a1;
@@ -6786,13 +7934,13 @@
 }
 
 void returnStructAlignmentInt16AfterCallback() {
-  free(returnStructAlignmentInt16Result.addressOf);
+  calloc.free(returnStructAlignmentInt16Result.addressOf);
 
   final result = returnStructAlignmentInt16CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStructAlignmentInt16Result.addressOf);
+  calloc.free(returnStructAlignmentInt16Result.addressOf);
 }
 
 typedef ReturnStructAlignmentInt32Type = StructAlignmentInt32 Function(
@@ -6807,7 +7955,7 @@
 StructAlignmentInt32 returnStructAlignmentInt32Result = StructAlignmentInt32();
 
 StructAlignmentInt32 returnStructAlignmentInt32CalculateResult() {
-  StructAlignmentInt32 result = allocate<StructAlignmentInt32>().ref;
+  StructAlignmentInt32 result = calloc<StructAlignmentInt32>().ref;
 
   result.a0 = returnStructAlignmentInt32_a0;
   result.a1 = returnStructAlignmentInt32_a1;
@@ -6846,13 +7994,13 @@
 }
 
 void returnStructAlignmentInt32AfterCallback() {
-  free(returnStructAlignmentInt32Result.addressOf);
+  calloc.free(returnStructAlignmentInt32Result.addressOf);
 
   final result = returnStructAlignmentInt32CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStructAlignmentInt32Result.addressOf);
+  calloc.free(returnStructAlignmentInt32Result.addressOf);
 }
 
 typedef ReturnStructAlignmentInt64Type = StructAlignmentInt64 Function(
@@ -6867,7 +8015,7 @@
 StructAlignmentInt64 returnStructAlignmentInt64Result = StructAlignmentInt64();
 
 StructAlignmentInt64 returnStructAlignmentInt64CalculateResult() {
-  StructAlignmentInt64 result = allocate<StructAlignmentInt64>().ref;
+  StructAlignmentInt64 result = calloc<StructAlignmentInt64>().ref;
 
   result.a0 = returnStructAlignmentInt64_a0;
   result.a1 = returnStructAlignmentInt64_a1;
@@ -6906,11 +8054,705 @@
 }
 
 void returnStructAlignmentInt64AfterCallback() {
-  free(returnStructAlignmentInt64Result.addressOf);
+  calloc.free(returnStructAlignmentInt64Result.addressOf);
 
   final result = returnStructAlignmentInt64CalculateResult();
 
   print("after callback result = $result");
 
-  free(returnStructAlignmentInt64Result.addressOf);
+  calloc.free(returnStructAlignmentInt64Result.addressOf);
+}
+
+typedef ReturnStruct8BytesNestedIntType = Struct8BytesNestedInt Function(
+    Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesHomogeneousInt16 returnStruct8BytesNestedInt_a0 =
+    Struct4BytesHomogeneousInt16();
+Struct4BytesHomogeneousInt16 returnStruct8BytesNestedInt_a1 =
+    Struct4BytesHomogeneousInt16();
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesNestedInt returnStruct8BytesNestedIntResult =
+    Struct8BytesNestedInt();
+
+Struct8BytesNestedInt returnStruct8BytesNestedIntCalculateResult() {
+  Struct8BytesNestedInt result = calloc<Struct8BytesNestedInt>().ref;
+
+  result.a0.a0 = returnStruct8BytesNestedInt_a0.a0;
+  result.a0.a1 = returnStruct8BytesNestedInt_a0.a1;
+  result.a1.a0 = returnStruct8BytesNestedInt_a1.a0;
+  result.a1.a1 = returnStruct8BytesNestedInt_a1.a1;
+
+  returnStruct8BytesNestedIntResult = result;
+
+  return result;
+}
+
+/// Simple nested struct.
+Struct8BytesNestedInt returnStruct8BytesNestedInt(
+    Struct4BytesHomogeneousInt16 a0, Struct4BytesHomogeneousInt16 a1) {
+  print("returnStruct8BytesNestedInt(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct8BytesNestedInt throwing on purpuse!");
+  }
+
+  returnStruct8BytesNestedInt_a0 = a0;
+  returnStruct8BytesNestedInt_a1 = a1;
+
+  final result = returnStruct8BytesNestedIntCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct8BytesNestedIntAfterCallback() {
+  calloc.free(returnStruct8BytesNestedIntResult.addressOf);
+
+  final result = returnStruct8BytesNestedIntCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct8BytesNestedIntResult.addressOf);
+}
+
+typedef ReturnStruct8BytesNestedFloatType = Struct8BytesNestedFloat Function(
+    Struct4BytesFloat, Struct4BytesFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesFloat returnStruct8BytesNestedFloat_a0 = Struct4BytesFloat();
+Struct4BytesFloat returnStruct8BytesNestedFloat_a1 = Struct4BytesFloat();
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesNestedFloat returnStruct8BytesNestedFloatResult =
+    Struct8BytesNestedFloat();
+
+Struct8BytesNestedFloat returnStruct8BytesNestedFloatCalculateResult() {
+  Struct8BytesNestedFloat result = calloc<Struct8BytesNestedFloat>().ref;
+
+  result.a0.a0 = returnStruct8BytesNestedFloat_a0.a0;
+  result.a1.a0 = returnStruct8BytesNestedFloat_a1.a0;
+
+  returnStruct8BytesNestedFloatResult = result;
+
+  return result;
+}
+
+/// Simple nested struct with floats.
+Struct8BytesNestedFloat returnStruct8BytesNestedFloat(
+    Struct4BytesFloat a0, Struct4BytesFloat a1) {
+  print("returnStruct8BytesNestedFloat(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct8BytesNestedFloat throwing on purpuse!");
+  }
+
+  returnStruct8BytesNestedFloat_a0 = a0;
+  returnStruct8BytesNestedFloat_a1 = a1;
+
+  final result = returnStruct8BytesNestedFloatCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct8BytesNestedFloatAfterCallback() {
+  calloc.free(returnStruct8BytesNestedFloatResult.addressOf);
+
+  final result = returnStruct8BytesNestedFloatCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct8BytesNestedFloatResult.addressOf);
+}
+
+typedef ReturnStruct8BytesNestedFloat2Type = Struct8BytesNestedFloat2 Function(
+    Struct4BytesFloat, Float);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesFloat returnStruct8BytesNestedFloat2_a0 = Struct4BytesFloat();
+double returnStruct8BytesNestedFloat2_a1 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesNestedFloat2 returnStruct8BytesNestedFloat2Result =
+    Struct8BytesNestedFloat2();
+
+Struct8BytesNestedFloat2 returnStruct8BytesNestedFloat2CalculateResult() {
+  Struct8BytesNestedFloat2 result = calloc<Struct8BytesNestedFloat2>().ref;
+
+  result.a0.a0 = returnStruct8BytesNestedFloat2_a0.a0;
+  result.a1 = returnStruct8BytesNestedFloat2_a1;
+
+  returnStruct8BytesNestedFloat2Result = result;
+
+  return result;
+}
+
+/// The nesting is irregular, testing homogenous float rules on arm and arm64,
+/// and the fpu register usage on x64.
+Struct8BytesNestedFloat2 returnStruct8BytesNestedFloat2(
+    Struct4BytesFloat a0, double a1) {
+  print("returnStruct8BytesNestedFloat2(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct8BytesNestedFloat2 throwing on purpuse!");
+  }
+
+  returnStruct8BytesNestedFloat2_a0 = a0;
+  returnStruct8BytesNestedFloat2_a1 = a1;
+
+  final result = returnStruct8BytesNestedFloat2CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct8BytesNestedFloat2AfterCallback() {
+  calloc.free(returnStruct8BytesNestedFloat2Result.addressOf);
+
+  final result = returnStruct8BytesNestedFloat2CalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct8BytesNestedFloat2Result.addressOf);
+}
+
+typedef ReturnStruct8BytesNestedMixedType = Struct8BytesNestedMixed Function(
+    Struct4BytesHomogeneousInt16, Struct4BytesFloat);
+
+// Global variables to be able to test inputs after callback returned.
+Struct4BytesHomogeneousInt16 returnStruct8BytesNestedMixed_a0 =
+    Struct4BytesHomogeneousInt16();
+Struct4BytesFloat returnStruct8BytesNestedMixed_a1 = Struct4BytesFloat();
+
+// Result variable also global, so we can delete it after the callback.
+Struct8BytesNestedMixed returnStruct8BytesNestedMixedResult =
+    Struct8BytesNestedMixed();
+
+Struct8BytesNestedMixed returnStruct8BytesNestedMixedCalculateResult() {
+  Struct8BytesNestedMixed result = calloc<Struct8BytesNestedMixed>().ref;
+
+  result.a0.a0 = returnStruct8BytesNestedMixed_a0.a0;
+  result.a0.a1 = returnStruct8BytesNestedMixed_a0.a1;
+  result.a1.a0 = returnStruct8BytesNestedMixed_a1.a0;
+
+  returnStruct8BytesNestedMixedResult = result;
+
+  return result;
+}
+
+/// Simple nested struct with mixed members.
+Struct8BytesNestedMixed returnStruct8BytesNestedMixed(
+    Struct4BytesHomogeneousInt16 a0, Struct4BytesFloat a1) {
+  print("returnStruct8BytesNestedMixed(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct8BytesNestedMixed throwing on purpuse!");
+  }
+
+  returnStruct8BytesNestedMixed_a0 = a0;
+  returnStruct8BytesNestedMixed_a1 = a1;
+
+  final result = returnStruct8BytesNestedMixedCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct8BytesNestedMixedAfterCallback() {
+  calloc.free(returnStruct8BytesNestedMixedResult.addressOf);
+
+  final result = returnStruct8BytesNestedMixedCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct8BytesNestedMixedResult.addressOf);
+}
+
+typedef ReturnStruct16BytesNestedIntType = Struct16BytesNestedInt Function(
+    Struct8BytesNestedInt, Struct8BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct8BytesNestedInt returnStruct16BytesNestedInt_a0 = Struct8BytesNestedInt();
+Struct8BytesNestedInt returnStruct16BytesNestedInt_a1 = Struct8BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+Struct16BytesNestedInt returnStruct16BytesNestedIntResult =
+    Struct16BytesNestedInt();
+
+Struct16BytesNestedInt returnStruct16BytesNestedIntCalculateResult() {
+  Struct16BytesNestedInt result = calloc<Struct16BytesNestedInt>().ref;
+
+  result.a0.a0.a0 = returnStruct16BytesNestedInt_a0.a0.a0;
+  result.a0.a0.a1 = returnStruct16BytesNestedInt_a0.a0.a1;
+  result.a0.a1.a0 = returnStruct16BytesNestedInt_a0.a1.a0;
+  result.a0.a1.a1 = returnStruct16BytesNestedInt_a0.a1.a1;
+  result.a1.a0.a0 = returnStruct16BytesNestedInt_a1.a0.a0;
+  result.a1.a0.a1 = returnStruct16BytesNestedInt_a1.a0.a1;
+  result.a1.a1.a0 = returnStruct16BytesNestedInt_a1.a1.a0;
+  result.a1.a1.a1 = returnStruct16BytesNestedInt_a1.a1.a1;
+
+  returnStruct16BytesNestedIntResult = result;
+
+  return result;
+}
+
+/// Deeper nested struct to test recursive member access.
+Struct16BytesNestedInt returnStruct16BytesNestedInt(
+    Struct8BytesNestedInt a0, Struct8BytesNestedInt a1) {
+  print("returnStruct16BytesNestedInt(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0 == 42 || a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct16BytesNestedInt throwing on purpuse!");
+  }
+
+  returnStruct16BytesNestedInt_a0 = a0;
+  returnStruct16BytesNestedInt_a1 = a1;
+
+  final result = returnStruct16BytesNestedIntCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct16BytesNestedIntAfterCallback() {
+  calloc.free(returnStruct16BytesNestedIntResult.addressOf);
+
+  final result = returnStruct16BytesNestedIntCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct16BytesNestedIntResult.addressOf);
+}
+
+typedef ReturnStruct32BytesNestedIntType = Struct32BytesNestedInt Function(
+    Struct16BytesNestedInt, Struct16BytesNestedInt);
+
+// Global variables to be able to test inputs after callback returned.
+Struct16BytesNestedInt returnStruct32BytesNestedInt_a0 =
+    Struct16BytesNestedInt();
+Struct16BytesNestedInt returnStruct32BytesNestedInt_a1 =
+    Struct16BytesNestedInt();
+
+// Result variable also global, so we can delete it after the callback.
+Struct32BytesNestedInt returnStruct32BytesNestedIntResult =
+    Struct32BytesNestedInt();
+
+Struct32BytesNestedInt returnStruct32BytesNestedIntCalculateResult() {
+  Struct32BytesNestedInt result = calloc<Struct32BytesNestedInt>().ref;
+
+  result.a0.a0.a0.a0 = returnStruct32BytesNestedInt_a0.a0.a0.a0;
+  result.a0.a0.a0.a1 = returnStruct32BytesNestedInt_a0.a0.a0.a1;
+  result.a0.a0.a1.a0 = returnStruct32BytesNestedInt_a0.a0.a1.a0;
+  result.a0.a0.a1.a1 = returnStruct32BytesNestedInt_a0.a0.a1.a1;
+  result.a0.a1.a0.a0 = returnStruct32BytesNestedInt_a0.a1.a0.a0;
+  result.a0.a1.a0.a1 = returnStruct32BytesNestedInt_a0.a1.a0.a1;
+  result.a0.a1.a1.a0 = returnStruct32BytesNestedInt_a0.a1.a1.a0;
+  result.a0.a1.a1.a1 = returnStruct32BytesNestedInt_a0.a1.a1.a1;
+  result.a1.a0.a0.a0 = returnStruct32BytesNestedInt_a1.a0.a0.a0;
+  result.a1.a0.a0.a1 = returnStruct32BytesNestedInt_a1.a0.a0.a1;
+  result.a1.a0.a1.a0 = returnStruct32BytesNestedInt_a1.a0.a1.a0;
+  result.a1.a0.a1.a1 = returnStruct32BytesNestedInt_a1.a0.a1.a1;
+  result.a1.a1.a0.a0 = returnStruct32BytesNestedInt_a1.a1.a0.a0;
+  result.a1.a1.a0.a1 = returnStruct32BytesNestedInt_a1.a1.a0.a1;
+  result.a1.a1.a1.a0 = returnStruct32BytesNestedInt_a1.a1.a1.a0;
+  result.a1.a1.a1.a1 = returnStruct32BytesNestedInt_a1.a1.a1.a1;
+
+  returnStruct32BytesNestedIntResult = result;
+
+  return result;
+}
+
+/// Even deeper nested struct to test recursive member access.
+Struct32BytesNestedInt returnStruct32BytesNestedInt(
+    Struct16BytesNestedInt a0, Struct16BytesNestedInt a1) {
+  print("returnStruct32BytesNestedInt(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0.a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0.a0.a0 == 42 || a0.a0.a0.a0 == 84) {
+    print("throwing!");
+    throw Exception("ReturnStruct32BytesNestedInt throwing on purpuse!");
+  }
+
+  returnStruct32BytesNestedInt_a0 = a0;
+  returnStruct32BytesNestedInt_a1 = a1;
+
+  final result = returnStruct32BytesNestedIntCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStruct32BytesNestedIntAfterCallback() {
+  calloc.free(returnStruct32BytesNestedIntResult.addressOf);
+
+  final result = returnStruct32BytesNestedIntCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStruct32BytesNestedIntResult.addressOf);
+}
+
+typedef ReturnStructNestedIntStructAlignmentInt16Type
+    = StructNestedIntStructAlignmentInt16 Function(
+        StructAlignmentInt16, StructAlignmentInt16);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt16 returnStructNestedIntStructAlignmentInt16_a0 =
+    StructAlignmentInt16();
+StructAlignmentInt16 returnStructNestedIntStructAlignmentInt16_a1 =
+    StructAlignmentInt16();
+
+// Result variable also global, so we can delete it after the callback.
+StructNestedIntStructAlignmentInt16
+    returnStructNestedIntStructAlignmentInt16Result =
+    StructNestedIntStructAlignmentInt16();
+
+StructNestedIntStructAlignmentInt16
+    returnStructNestedIntStructAlignmentInt16CalculateResult() {
+  StructNestedIntStructAlignmentInt16 result =
+      calloc<StructNestedIntStructAlignmentInt16>().ref;
+
+  result.a0.a0 = returnStructNestedIntStructAlignmentInt16_a0.a0;
+  result.a0.a1 = returnStructNestedIntStructAlignmentInt16_a0.a1;
+  result.a0.a2 = returnStructNestedIntStructAlignmentInt16_a0.a2;
+  result.a1.a0 = returnStructNestedIntStructAlignmentInt16_a1.a0;
+  result.a1.a1 = returnStructNestedIntStructAlignmentInt16_a1.a1;
+  result.a1.a2 = returnStructNestedIntStructAlignmentInt16_a1.a2;
+
+  returnStructNestedIntStructAlignmentInt16Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 16 byte int.
+StructNestedIntStructAlignmentInt16 returnStructNestedIntStructAlignmentInt16(
+    StructAlignmentInt16 a0, StructAlignmentInt16 a1) {
+  print("returnStructNestedIntStructAlignmentInt16(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "ReturnStructNestedIntStructAlignmentInt16 throwing on purpuse!");
+  }
+
+  returnStructNestedIntStructAlignmentInt16_a0 = a0;
+  returnStructNestedIntStructAlignmentInt16_a1 = a1;
+
+  final result = returnStructNestedIntStructAlignmentInt16CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStructNestedIntStructAlignmentInt16AfterCallback() {
+  calloc.free(returnStructNestedIntStructAlignmentInt16Result.addressOf);
+
+  final result = returnStructNestedIntStructAlignmentInt16CalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStructNestedIntStructAlignmentInt16Result.addressOf);
+}
+
+typedef ReturnStructNestedIntStructAlignmentInt32Type
+    = StructNestedIntStructAlignmentInt32 Function(
+        StructAlignmentInt32, StructAlignmentInt32);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt32 returnStructNestedIntStructAlignmentInt32_a0 =
+    StructAlignmentInt32();
+StructAlignmentInt32 returnStructNestedIntStructAlignmentInt32_a1 =
+    StructAlignmentInt32();
+
+// Result variable also global, so we can delete it after the callback.
+StructNestedIntStructAlignmentInt32
+    returnStructNestedIntStructAlignmentInt32Result =
+    StructNestedIntStructAlignmentInt32();
+
+StructNestedIntStructAlignmentInt32
+    returnStructNestedIntStructAlignmentInt32CalculateResult() {
+  StructNestedIntStructAlignmentInt32 result =
+      calloc<StructNestedIntStructAlignmentInt32>().ref;
+
+  result.a0.a0 = returnStructNestedIntStructAlignmentInt32_a0.a0;
+  result.a0.a1 = returnStructNestedIntStructAlignmentInt32_a0.a1;
+  result.a0.a2 = returnStructNestedIntStructAlignmentInt32_a0.a2;
+  result.a1.a0 = returnStructNestedIntStructAlignmentInt32_a1.a0;
+  result.a1.a1 = returnStructNestedIntStructAlignmentInt32_a1.a1;
+  result.a1.a2 = returnStructNestedIntStructAlignmentInt32_a1.a2;
+
+  returnStructNestedIntStructAlignmentInt32Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 32 byte int.
+StructNestedIntStructAlignmentInt32 returnStructNestedIntStructAlignmentInt32(
+    StructAlignmentInt32 a0, StructAlignmentInt32 a1) {
+  print("returnStructNestedIntStructAlignmentInt32(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "ReturnStructNestedIntStructAlignmentInt32 throwing on purpuse!");
+  }
+
+  returnStructNestedIntStructAlignmentInt32_a0 = a0;
+  returnStructNestedIntStructAlignmentInt32_a1 = a1;
+
+  final result = returnStructNestedIntStructAlignmentInt32CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStructNestedIntStructAlignmentInt32AfterCallback() {
+  calloc.free(returnStructNestedIntStructAlignmentInt32Result.addressOf);
+
+  final result = returnStructNestedIntStructAlignmentInt32CalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStructNestedIntStructAlignmentInt32Result.addressOf);
+}
+
+typedef ReturnStructNestedIntStructAlignmentInt64Type
+    = StructNestedIntStructAlignmentInt64 Function(
+        StructAlignmentInt64, StructAlignmentInt64);
+
+// Global variables to be able to test inputs after callback returned.
+StructAlignmentInt64 returnStructNestedIntStructAlignmentInt64_a0 =
+    StructAlignmentInt64();
+StructAlignmentInt64 returnStructNestedIntStructAlignmentInt64_a1 =
+    StructAlignmentInt64();
+
+// Result variable also global, so we can delete it after the callback.
+StructNestedIntStructAlignmentInt64
+    returnStructNestedIntStructAlignmentInt64Result =
+    StructNestedIntStructAlignmentInt64();
+
+StructNestedIntStructAlignmentInt64
+    returnStructNestedIntStructAlignmentInt64CalculateResult() {
+  StructNestedIntStructAlignmentInt64 result =
+      calloc<StructNestedIntStructAlignmentInt64>().ref;
+
+  result.a0.a0 = returnStructNestedIntStructAlignmentInt64_a0.a0;
+  result.a0.a1 = returnStructNestedIntStructAlignmentInt64_a0.a1;
+  result.a0.a2 = returnStructNestedIntStructAlignmentInt64_a0.a2;
+  result.a1.a0 = returnStructNestedIntStructAlignmentInt64_a1.a0;
+  result.a1.a1 = returnStructNestedIntStructAlignmentInt64_a1.a1;
+  result.a1.a2 = returnStructNestedIntStructAlignmentInt64_a1.a2;
+
+  returnStructNestedIntStructAlignmentInt64Result = result;
+
+  return result;
+}
+
+/// Test alignment and padding of nested struct with 64 byte int.
+StructNestedIntStructAlignmentInt64 returnStructNestedIntStructAlignmentInt64(
+    StructAlignmentInt64 a0, StructAlignmentInt64 a1) {
+  print("returnStructNestedIntStructAlignmentInt64(${a0}, ${a1})");
+
+  // In legacy mode, possibly return null.
+  if (a0.a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0.a0 == 42 || a0.a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "ReturnStructNestedIntStructAlignmentInt64 throwing on purpuse!");
+  }
+
+  returnStructNestedIntStructAlignmentInt64_a0 = a0;
+  returnStructNestedIntStructAlignmentInt64_a1 = a1;
+
+  final result = returnStructNestedIntStructAlignmentInt64CalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStructNestedIntStructAlignmentInt64AfterCallback() {
+  calloc.free(returnStructNestedIntStructAlignmentInt64Result.addressOf);
+
+  final result = returnStructNestedIntStructAlignmentInt64CalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStructNestedIntStructAlignmentInt64Result.addressOf);
+}
+
+typedef ReturnStructNestedIrregularEvenBiggerType
+    = StructNestedIrregularEvenBigger Function(Uint64,
+        StructNestedIrregularBigger, StructNestedIrregularBigger, Double);
+
+// Global variables to be able to test inputs after callback returned.
+int returnStructNestedIrregularEvenBigger_a0 = 0;
+StructNestedIrregularBigger returnStructNestedIrregularEvenBigger_a1 =
+    StructNestedIrregularBigger();
+StructNestedIrregularBigger returnStructNestedIrregularEvenBigger_a2 =
+    StructNestedIrregularBigger();
+double returnStructNestedIrregularEvenBigger_a3 = 0.0;
+
+// Result variable also global, so we can delete it after the callback.
+StructNestedIrregularEvenBigger returnStructNestedIrregularEvenBiggerResult =
+    StructNestedIrregularEvenBigger();
+
+StructNestedIrregularEvenBigger
+    returnStructNestedIrregularEvenBiggerCalculateResult() {
+  StructNestedIrregularEvenBigger result =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+
+  result.a0 = returnStructNestedIrregularEvenBigger_a0;
+  result.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a0;
+  result.a1.a0.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a1.a0.a0;
+  result.a1.a0.a1.a0.a1 = returnStructNestedIrregularEvenBigger_a1.a0.a1.a0.a1;
+  result.a1.a0.a1.a1.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a1.a1.a0;
+  result.a1.a0.a2 = returnStructNestedIrregularEvenBigger_a1.a0.a2;
+  result.a1.a0.a3.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a3.a0.a0;
+  result.a1.a0.a3.a1 = returnStructNestedIrregularEvenBigger_a1.a0.a3.a1;
+  result.a1.a0.a4 = returnStructNestedIrregularEvenBigger_a1.a0.a4;
+  result.a1.a0.a5.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a5.a0.a0;
+  result.a1.a0.a5.a1.a0 = returnStructNestedIrregularEvenBigger_a1.a0.a5.a1.a0;
+  result.a1.a0.a6 = returnStructNestedIrregularEvenBigger_a1.a0.a6;
+  result.a1.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a1.a1.a0.a0;
+  result.a1.a1.a0.a1 = returnStructNestedIrregularEvenBigger_a1.a1.a0.a1;
+  result.a1.a1.a1.a0 = returnStructNestedIrregularEvenBigger_a1.a1.a1.a0;
+  result.a1.a2 = returnStructNestedIrregularEvenBigger_a1.a2;
+  result.a1.a3 = returnStructNestedIrregularEvenBigger_a1.a3;
+  result.a2.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a0;
+  result.a2.a0.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a1.a0.a0;
+  result.a2.a0.a1.a0.a1 = returnStructNestedIrregularEvenBigger_a2.a0.a1.a0.a1;
+  result.a2.a0.a1.a1.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a1.a1.a0;
+  result.a2.a0.a2 = returnStructNestedIrregularEvenBigger_a2.a0.a2;
+  result.a2.a0.a3.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a3.a0.a0;
+  result.a2.a0.a3.a1 = returnStructNestedIrregularEvenBigger_a2.a0.a3.a1;
+  result.a2.a0.a4 = returnStructNestedIrregularEvenBigger_a2.a0.a4;
+  result.a2.a0.a5.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a5.a0.a0;
+  result.a2.a0.a5.a1.a0 = returnStructNestedIrregularEvenBigger_a2.a0.a5.a1.a0;
+  result.a2.a0.a6 = returnStructNestedIrregularEvenBigger_a2.a0.a6;
+  result.a2.a1.a0.a0 = returnStructNestedIrregularEvenBigger_a2.a1.a0.a0;
+  result.a2.a1.a0.a1 = returnStructNestedIrregularEvenBigger_a2.a1.a0.a1;
+  result.a2.a1.a1.a0 = returnStructNestedIrregularEvenBigger_a2.a1.a1.a0;
+  result.a2.a2 = returnStructNestedIrregularEvenBigger_a2.a2;
+  result.a2.a3 = returnStructNestedIrregularEvenBigger_a2.a3;
+  result.a3 = returnStructNestedIrregularEvenBigger_a3;
+
+  returnStructNestedIrregularEvenBiggerResult = result;
+
+  return result;
+}
+
+/// Return big irregular struct as smoke test.
+StructNestedIrregularEvenBigger returnStructNestedIrregularEvenBigger(int a0,
+    StructNestedIrregularBigger a1, StructNestedIrregularBigger a2, double a3) {
+  print("returnStructNestedIrregularEvenBigger(${a0}, ${a1}, ${a2}, ${a3})");
+
+  // In legacy mode, possibly return null.
+  if (a0 == 84) {
+    print("returning null!");
+    return null;
+  }
+
+  // In both nnbd and legacy mode, possibly throw.
+  if (a0 == 42 || a0 == 84) {
+    print("throwing!");
+    throw Exception(
+        "ReturnStructNestedIrregularEvenBigger throwing on purpuse!");
+  }
+
+  returnStructNestedIrregularEvenBigger_a0 = a0;
+  returnStructNestedIrregularEvenBigger_a1 = a1;
+  returnStructNestedIrregularEvenBigger_a2 = a2;
+  returnStructNestedIrregularEvenBigger_a3 = a3;
+
+  final result = returnStructNestedIrregularEvenBiggerCalculateResult();
+
+  print("result = $result");
+
+  return result;
+}
+
+void returnStructNestedIrregularEvenBiggerAfterCallback() {
+  calloc.free(returnStructNestedIrregularEvenBiggerResult.addressOf);
+
+  final result = returnStructNestedIrregularEvenBiggerCalculateResult();
+
+  print("after callback result = $result");
+
+  calloc.free(returnStructNestedIrregularEvenBiggerResult.addressOf);
 }
diff --git a/tests/ffi_2/function_callbacks_structs_by_value_test.dart b/tests/ffi_2/function_callbacks_structs_by_value_test.dart
index 98ab518..5e9399a 100644
--- a/tests/ffi_2/function_callbacks_structs_by_value_test.dart
+++ b/tests/ffi_2/function_callbacks_structs_by_value_test.dart
@@ -11,6 +11,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 // Reuse the struct classes.
 import 'function_structs_by_value_generated_test.dart';
 
@@ -18,11 +19,12 @@
   for (int i = 0; i < 10; i++) {
     recursiveTest(10);
     recursiveTest(11);
+    testCopyLogic();
   }
 }
 
 void recursiveTest(int recursionCounter) {
-  final struct = allocate<Struct20BytesHomogeneousInt32>().ref;
+  final struct = calloc<Struct20BytesHomogeneousInt32>().ref;
   struct.a0 = 1;
   struct.a1 = 2;
   struct.a2 = 3;
@@ -34,7 +36,7 @@
   Expect.equals(struct.a2, result.a2);
   Expect.equals(struct.a3, result.a3);
   Expect.equals(struct.a4, result.a4);
-  free(struct.addressOf);
+  calloc.free(struct.addressOf);
 }
 
 Struct20BytesHomogeneousInt32 dartPassStructRecursive(
@@ -69,3 +71,65 @@
         Struct20BytesHomogeneousInt32 struct, Pointer callbackAddress),
     Struct20BytesHomogeneousInt32 Function(int recursionCounter,
         Struct20BytesHomogeneousInt32, Pointer)>("PassStructRecursive");
+
+Struct8BytesNestedInt typedDataBackedStruct = Struct8BytesNestedInt();
+bool typedDataBackedStructSet = false;
+void _receiveStructByValue(Struct8BytesNestedInt struct) {
+  typedDataBackedStruct = struct;
+  typedDataBackedStructSet = true;
+}
+
+final _receiveStructByValuePointer =
+    Pointer.fromFunction<Void Function(Struct8BytesNestedInt)>(
+        _receiveStructByValue);
+
+final _invokeReceiveStructByValue = ffiTestFunctions.lookupFunction<
+        Void Function(
+            Pointer<NativeFunction<Void Function(Struct8BytesNestedInt)>>),
+        void Function(
+            Pointer<NativeFunction<Void Function(Struct8BytesNestedInt)>>)>(
+    "CallbackWithStruct");
+
+void testCopyLogic() {
+  _invokeReceiveStructByValue(_receiveStructByValuePointer);
+  Expect.isTrue(typedDataBackedStructSet);
+
+  final pointerBackedStruct = calloc<Struct8BytesNestedInt>().ref;
+
+  void reset() {
+    pointerBackedStruct.a0.a0 = 1;
+    pointerBackedStruct.a0.a1 = 2;
+    pointerBackedStruct.a1.a0 = 3;
+    pointerBackedStruct.a1.a1 = 4;
+    typedDataBackedStruct.a0.a0 = 5;
+    typedDataBackedStruct.a0.a1 = 6;
+    typedDataBackedStruct.a1.a0 = 7;
+    typedDataBackedStruct.a1.a1 = 8;
+  }
+
+  // Pointer -> Pointer.
+  reset();
+  pointerBackedStruct.a1 = pointerBackedStruct.a0;
+  Expect.equals(1, pointerBackedStruct.a1.a0);
+  Expect.equals(2, pointerBackedStruct.a1.a1);
+
+  // Pointer -> TypedData.
+  reset();
+  typedDataBackedStruct.a1 = pointerBackedStruct.a0;
+  Expect.equals(1, typedDataBackedStruct.a1.a0);
+  Expect.equals(2, typedDataBackedStruct.a1.a1);
+
+  // TypedData -> Pointer.
+  reset();
+  pointerBackedStruct.a1 = typedDataBackedStruct.a0;
+  Expect.equals(5, pointerBackedStruct.a1.a0);
+  Expect.equals(6, pointerBackedStruct.a1.a1);
+
+  // TypedData -> TypedData.
+  reset();
+  typedDataBackedStruct.a1 = typedDataBackedStruct.a0;
+  Expect.equals(5, typedDataBackedStruct.a1.a0);
+  Expect.equals(6, typedDataBackedStruct.a1.a1);
+
+  calloc.free(pointerBackedStruct.addressOf);
+}
diff --git a/tests/ffi_2/function_structs_by_value_generated_test.dart b/tests/ffi_2/function_structs_by_value_generated_test.dart
index dfb17cd..6867406 100644
--- a/tests/ffi_2/function_structs_by_value_generated_test.dart
+++ b/tests/ffi_2/function_structs_by_value_generated_test.dart
@@ -15,6 +15,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
@@ -52,6 +53,16 @@
     testPassStructAlignmentInt16();
     testPassStructAlignmentInt32();
     testPassStructAlignmentInt64();
+    testPassStruct8BytesNestedIntx10();
+    testPassStruct8BytesNestedFloatx10();
+    testPassStruct8BytesNestedFloat2x10();
+    testPassStruct8BytesNestedMixedx10();
+    testPassStruct16BytesNestedIntx2();
+    testPassStruct32BytesNestedIntx2();
+    testPassStructNestedIntStructAlignmentInt16();
+    testPassStructNestedIntStructAlignmentInt32();
+    testPassStructNestedIntStructAlignmentInt64();
+    testPassStructNestedIrregularEvenBiggerx4();
     testReturnStruct1ByteInt();
     testReturnStruct3BytesHomogeneousUint8();
     testReturnStruct3BytesInt2ByteAligned();
@@ -82,13 +93,19 @@
     testReturnStructAlignmentInt16();
     testReturnStructAlignmentInt32();
     testReturnStructAlignmentInt64();
+    testReturnStruct8BytesNestedInt();
+    testReturnStruct8BytesNestedFloat();
+    testReturnStruct8BytesNestedFloat2();
+    testReturnStruct8BytesNestedMixed();
+    testReturnStruct16BytesNestedInt();
+    testReturnStruct32BytesNestedInt();
+    testReturnStructNestedIntStructAlignmentInt16();
+    testReturnStructNestedIntStructAlignmentInt32();
+    testReturnStructNestedIntStructAlignmentInt64();
+    testReturnStructNestedIrregularEvenBigger();
   }
 }
 
-class Struct0Bytes extends Struct {
-  String toString() => "()";
-}
-
 class Struct1ByteInt extends Struct {
   @Int8()
   int a0;
@@ -129,6 +146,13 @@
   String toString() => "(${a0}, ${a1})";
 }
 
+class Struct4BytesFloat extends Struct {
+  @Float()
+  double a0;
+
+  String toString() => "(${a0})";
+}
+
 class Struct7BytesHomogeneousUint8 extends Struct {
   @Uint8()
   int a0;
@@ -876,6 +900,129 @@
   String toString() => "(${a0}, ${a1}, ${a2})";
 }
 
+class Struct8BytesNestedInt extends Struct {
+  Struct4BytesHomogeneousInt16 a0;
+
+  Struct4BytesHomogeneousInt16 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesNestedFloat extends Struct {
+  Struct4BytesFloat a0;
+
+  Struct4BytesFloat a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesNestedFloat2 extends Struct {
+  Struct4BytesFloat a0;
+
+  @Float()
+  double a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesNestedMixed extends Struct {
+  Struct4BytesHomogeneousInt16 a0;
+
+  Struct4BytesFloat a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct16BytesNestedInt extends Struct {
+  Struct8BytesNestedInt a0;
+
+  Struct8BytesNestedInt a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct32BytesNestedInt extends Struct {
+  Struct16BytesNestedInt a0;
+
+  Struct16BytesNestedInt a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class StructNestedIntStructAlignmentInt16 extends Struct {
+  StructAlignmentInt16 a0;
+
+  StructAlignmentInt16 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class StructNestedIntStructAlignmentInt32 extends Struct {
+  StructAlignmentInt32 a0;
+
+  StructAlignmentInt32 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class StructNestedIntStructAlignmentInt64 extends Struct {
+  StructAlignmentInt64 a0;
+
+  StructAlignmentInt64 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class StructNestedIrregularBig extends Struct {
+  @Uint16()
+  int a0;
+
+  Struct8BytesNestedMixed a1;
+
+  @Uint16()
+  int a2;
+
+  Struct8BytesNestedFloat2 a3;
+
+  @Uint16()
+  int a4;
+
+  Struct8BytesNestedFloat a5;
+
+  @Uint16()
+  int a6;
+
+  String toString() => "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6})";
+}
+
+class StructNestedIrregularBigger extends Struct {
+  StructNestedIrregularBig a0;
+
+  Struct8BytesNestedMixed a1;
+
+  @Float()
+  double a2;
+
+  @Double()
+  double a3;
+
+  String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
+class StructNestedIrregularEvenBigger extends Struct {
+  @Uint64()
+  int a0;
+
+  StructNestedIrregularBigger a1;
+
+  StructNestedIrregularBigger a2;
+
+  @Double()
+  double a3;
+
+  String toString() => "(${a0}, ${a1}, ${a2}, ${a3})";
+}
+
 final passStruct1ByteIntx10 = ffiTestFunctions.lookupFunction<
     Int64 Function(
         Struct1ByteInt,
@@ -903,16 +1050,16 @@
 /// Smallest struct with data.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct1ByteIntx10() {
-  Struct1ByteInt a0 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a1 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a2 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a3 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a4 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a5 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a6 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a7 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a8 = allocate<Struct1ByteInt>().ref;
-  Struct1ByteInt a9 = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt a0 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a1 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a2 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a3 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a4 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a5 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a6 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a7 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a8 = calloc<Struct1ByteInt>().ref;
+  Struct1ByteInt a9 = calloc<Struct1ByteInt>().ref;
 
   a0.a0 = -1;
   a1.a0 = 2;
@@ -931,16 +1078,16 @@
 
   Expect.equals(5, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct3BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
@@ -970,26 +1117,16 @@
 /// Not a multiple of word size, not a power of two.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct3BytesHomogeneousUint8x10() {
-  Struct3BytesHomogeneousUint8 a0 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a1 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a2 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a3 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a4 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a5 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a6 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a7 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a8 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
-  Struct3BytesHomogeneousUint8 a9 =
-      allocate<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a0 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a1 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a2 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a3 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a4 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a5 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a6 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a7 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a8 = calloc<Struct3BytesHomogeneousUint8>().ref;
+  Struct3BytesHomogeneousUint8 a9 = calloc<Struct3BytesHomogeneousUint8>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -1029,16 +1166,16 @@
 
   Expect.equals(465, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct3BytesInt2ByteAlignedx10 = ffiTestFunctions.lookupFunction<
@@ -1069,16 +1206,16 @@
 /// With alignment rules taken into account size is 4 bytes.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct3BytesInt2ByteAlignedx10() {
-  Struct3BytesInt2ByteAligned a0 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a1 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a2 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a3 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a4 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a5 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a6 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a7 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a8 = allocate<Struct3BytesInt2ByteAligned>().ref;
-  Struct3BytesInt2ByteAligned a9 = allocate<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a0 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a1 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a2 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a3 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a4 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a5 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a6 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a7 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a8 = calloc<Struct3BytesInt2ByteAligned>().ref;
+  Struct3BytesInt2ByteAligned a9 = calloc<Struct3BytesInt2ByteAligned>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1108,16 +1245,16 @@
 
   Expect.equals(10, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct4BytesHomogeneousInt16x10 = ffiTestFunctions.lookupFunction<
@@ -1147,26 +1284,16 @@
 /// Exactly word size on 32-bit architectures.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct4BytesHomogeneousInt16x10() {
-  Struct4BytesHomogeneousInt16 a0 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a1 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a2 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a3 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a4 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a5 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a6 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a7 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a8 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct4BytesHomogeneousInt16 a9 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a0 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a1 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a2 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a3 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a4 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a5 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a6 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a7 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a8 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a9 = calloc<Struct4BytesHomogeneousInt16>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1196,16 +1323,16 @@
 
   Expect.equals(10, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct7BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
@@ -1235,26 +1362,16 @@
 /// Sub word size on 64 bit architectures.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct7BytesHomogeneousUint8x10() {
-  Struct7BytesHomogeneousUint8 a0 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a1 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a2 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a3 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a4 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a5 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a6 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a7 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a8 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
-  Struct7BytesHomogeneousUint8 a9 =
-      allocate<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a0 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a1 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a2 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a3 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a4 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a5 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a6 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a7 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a8 = calloc<Struct7BytesHomogeneousUint8>().ref;
+  Struct7BytesHomogeneousUint8 a9 = calloc<Struct7BytesHomogeneousUint8>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -1334,16 +1451,16 @@
 
   Expect.equals(2485, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct7BytesInt4ByteAlignedx10 = ffiTestFunctions.lookupFunction<
@@ -1374,16 +1491,16 @@
 /// With alignment rules taken into account size is 8 bytes.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct7BytesInt4ByteAlignedx10() {
-  Struct7BytesInt4ByteAligned a0 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a1 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a2 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a3 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a4 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a5 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a6 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a7 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a8 = allocate<Struct7BytesInt4ByteAligned>().ref;
-  Struct7BytesInt4ByteAligned a9 = allocate<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a0 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a1 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a2 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a3 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a4 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a5 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a6 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a7 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a8 = calloc<Struct7BytesInt4ByteAligned>().ref;
+  Struct7BytesInt4ByteAligned a9 = calloc<Struct7BytesInt4ByteAligned>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1423,16 +1540,16 @@
 
   Expect.equals(15, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct8BytesIntx10 = ffiTestFunctions.lookupFunction<
@@ -1462,16 +1579,16 @@
 /// Exactly word size struct on 64bit architectures.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct8BytesIntx10() {
-  Struct8BytesInt a0 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a1 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a2 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a3 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a4 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a5 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a6 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a7 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a8 = allocate<Struct8BytesInt>().ref;
-  Struct8BytesInt a9 = allocate<Struct8BytesInt>().ref;
+  Struct8BytesInt a0 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a1 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a2 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a3 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a4 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a5 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a6 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a7 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a8 = calloc<Struct8BytesInt>().ref;
+  Struct8BytesInt a9 = calloc<Struct8BytesInt>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1510,16 +1627,16 @@
 
   Expect.equals(15, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct8BytesHomogeneousFloatx10 = ffiTestFunctions.lookupFunction<
@@ -1549,26 +1666,16 @@
 /// Arguments passed in FP registers as long as they fit.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct8BytesHomogeneousFloatx10() {
-  Struct8BytesHomogeneousFloat a0 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a1 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a2 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a3 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a4 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a5 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a6 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a7 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a8 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
-  Struct8BytesHomogeneousFloat a9 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a0 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a1 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a2 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a3 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a4 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a5 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a6 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a7 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a8 = calloc<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a9 = calloc<Struct8BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -1598,16 +1705,16 @@
 
   Expect.approxEquals(10.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct8BytesMixedx10 = ffiTestFunctions.lookupFunction<
@@ -1637,16 +1744,16 @@
 /// On x64, arguments go in int registers because it is not only float.
 /// 10 struct arguments will exhaust available registers.
 void testPassStruct8BytesMixedx10() {
-  Struct8BytesMixed a0 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a1 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a2 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a3 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a4 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a5 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a6 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a7 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a8 = allocate<Struct8BytesMixed>().ref;
-  Struct8BytesMixed a9 = allocate<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a0 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a1 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a2 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a3 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a4 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a5 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a6 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a7 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a8 = calloc<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a9 = calloc<Struct8BytesMixed>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2;
@@ -1686,16 +1793,16 @@
 
   Expect.approxEquals(15.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct9BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
@@ -1728,26 +1835,16 @@
 /// Tests upper bytes in the integer registers that are partly filled.
 /// Tests stack alignment of non word size stack arguments.
 void testPassStruct9BytesHomogeneousUint8x10() {
-  Struct9BytesHomogeneousUint8 a0 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a1 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a2 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a3 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a4 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a5 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a6 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a7 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a8 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
-  Struct9BytesHomogeneousUint8 a9 =
-      allocate<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a0 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a1 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a2 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a3 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a4 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a5 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a6 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a7 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a8 = calloc<Struct9BytesHomogeneousUint8>().ref;
+  Struct9BytesHomogeneousUint8 a9 = calloc<Struct9BytesHomogeneousUint8>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -1847,16 +1944,16 @@
 
   Expect.equals(4095, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct9BytesInt4Or8ByteAlignedx10 = ffiTestFunctions.lookupFunction<
@@ -1890,25 +1987,25 @@
 ///
 void testPassStruct9BytesInt4Or8ByteAlignedx10() {
   Struct9BytesInt4Or8ByteAligned a0 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a1 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a2 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a3 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a4 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a5 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a6 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a7 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a8 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
   Struct9BytesInt4Or8ByteAligned a9 =
-      allocate<Struct9BytesInt4Or8ByteAligned>().ref;
+      calloc<Struct9BytesInt4Or8ByteAligned>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -1938,16 +2035,16 @@
 
   Expect.equals(10, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct12BytesHomogeneousFloatx6 = ffiTestFunctions.lookupFunction<
@@ -1971,17 +2068,17 @@
 /// The last argument is to test whether arguments are backfilled.
 void testPassStruct12BytesHomogeneousFloatx6() {
   Struct12BytesHomogeneousFloat a0 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a1 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a2 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a3 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a4 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
   Struct12BytesHomogeneousFloat a5 =
-      allocate<Struct12BytesHomogeneousFloat>().ref;
+      calloc<Struct12BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2008,12 +2105,12 @@
 
   Expect.approxEquals(9.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
 }
 
 final passStruct16BytesHomogeneousFloatx5 = ffiTestFunctions.lookupFunction<
@@ -2035,15 +2132,15 @@
 /// 5 struct arguments will exhaust available registers.
 void testPassStruct16BytesHomogeneousFloatx5() {
   Struct16BytesHomogeneousFloat a0 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   Struct16BytesHomogeneousFloat a1 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   Struct16BytesHomogeneousFloat a2 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   Struct16BytesHomogeneousFloat a3 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   Struct16BytesHomogeneousFloat a4 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2072,11 +2169,11 @@
 
   Expect.approxEquals(10.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
 }
 
 final passStruct16BytesMixedx10 = ffiTestFunctions.lookupFunction<
@@ -2108,16 +2205,16 @@
 /// The rest goes on the stack.
 /// On arm, arguments are 8 byte aligned.
 void testPassStruct16BytesMixedx10() {
-  Struct16BytesMixed a0 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a1 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a2 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a3 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a4 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a8 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a9 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a0 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a1 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a2 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a3 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a4 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a5 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a6 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a7 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a8 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a9 = calloc<Struct16BytesMixed>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2;
@@ -2147,16 +2244,16 @@
 
   Expect.approxEquals(10.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct16BytesMixed2x10 = ffiTestFunctions.lookupFunction<
@@ -2188,16 +2285,16 @@
 /// The rest goes on the stack.
 /// On arm, arguments are 4 byte aligned.
 void testPassStruct16BytesMixed2x10() {
-  Struct16BytesMixed2 a0 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a1 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a2 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a3 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a4 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a5 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a6 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a7 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a8 = allocate<Struct16BytesMixed2>().ref;
-  Struct16BytesMixed2 a9 = allocate<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a0 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a1 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a2 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a3 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a4 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a5 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a6 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a7 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a8 = calloc<Struct16BytesMixed2>().ref;
+  Struct16BytesMixed2 a9 = calloc<Struct16BytesMixed2>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2247,16 +2344,16 @@
 
   Expect.approxEquals(20.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct17BytesIntx10 = ffiTestFunctions.lookupFunction<
@@ -2286,16 +2383,16 @@
 /// Arguments are passed as pointer to copy on arm64.
 /// Tests that the memory allocated for copies are rounded up to word size.
 void testPassStruct17BytesIntx10() {
-  Struct17BytesInt a0 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a1 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a2 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a3 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a4 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a5 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a6 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a7 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a8 = allocate<Struct17BytesInt>().ref;
-  Struct17BytesInt a9 = allocate<Struct17BytesInt>().ref;
+  Struct17BytesInt a0 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a1 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a2 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a3 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a4 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a5 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a6 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a7 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a8 = calloc<Struct17BytesInt>().ref;
+  Struct17BytesInt a9 = calloc<Struct17BytesInt>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -2335,16 +2432,16 @@
 
   Expect.equals(15, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct19BytesHomogeneousUint8x10 = ffiTestFunctions.lookupFunction<
@@ -2376,25 +2473,25 @@
 ///
 void testPassStruct19BytesHomogeneousUint8x10() {
   Struct19BytesHomogeneousUint8 a0 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a1 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a2 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a3 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a4 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a5 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a6 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a7 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a8 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
   Struct19BytesHomogeneousUint8 a9 =
-      allocate<Struct19BytesHomogeneousUint8>().ref;
+      calloc<Struct19BytesHomogeneousUint8>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -2594,16 +2691,16 @@
 
   Expect.equals(18145, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct20BytesHomogeneousInt32x10 = ffiTestFunctions.lookupFunction<
@@ -2636,25 +2733,25 @@
 /// pointers to copies are also passed on the stack.
 void testPassStruct20BytesHomogeneousInt32x10() {
   Struct20BytesHomogeneousInt32 a0 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a1 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a2 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a3 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a4 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a5 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a6 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a7 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a8 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
   Struct20BytesHomogeneousInt32 a9 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -2714,16 +2811,16 @@
 
   Expect.equals(25, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction<
@@ -2734,7 +2831,7 @@
 /// Argument too big to go into FPU registers in hardfp and arm64.
 void testPassStruct20BytesHomogeneousFloat() {
   Struct20BytesHomogeneousFloat a0 =
-      allocate<Struct20BytesHomogeneousFloat>().ref;
+      calloc<Struct20BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2748,7 +2845,7 @@
 
   Expect.approxEquals(-3.0, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passStruct32BytesHomogeneousDoublex5 = ffiTestFunctions.lookupFunction<
@@ -2770,15 +2867,15 @@
 /// 5 struct arguments will exhaust available registers.
 void testPassStruct32BytesHomogeneousDoublex5() {
   Struct32BytesHomogeneousDouble a0 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   Struct32BytesHomogeneousDouble a1 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   Struct32BytesHomogeneousDouble a2 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   Struct32BytesHomogeneousDouble a3 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   Struct32BytesHomogeneousDouble a4 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2807,11 +2904,11 @@
 
   Expect.approxEquals(10.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
-  free(a3.addressOf);
-  free(a4.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
 }
 
 final passStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction<
@@ -2822,7 +2919,7 @@
 /// Argument too big to go into FPU registers in arm64.
 void testPassStruct40BytesHomogeneousDouble() {
   Struct40BytesHomogeneousDouble a0 =
-      allocate<Struct40BytesHomogeneousDouble>().ref;
+      calloc<Struct40BytesHomogeneousDouble>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -2836,7 +2933,7 @@
 
   Expect.approxEquals(-3.0, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction<
@@ -2847,7 +2944,7 @@
 /// Test 1kb struct.
 void testPassStruct1024BytesHomogeneousUint64() {
   Struct1024BytesHomogeneousUint64 a0 =
-      allocate<Struct1024BytesHomogeneousUint64>().ref;
+      calloc<Struct1024BytesHomogeneousUint64>().ref;
 
   a0.a0 = 1;
   a0.a1 = 2;
@@ -2984,7 +3081,7 @@
 
   Expect.equals(8256, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passFloatStruct16BytesHomogeneousFloatFloatStruct1 =
@@ -3014,16 +3111,16 @@
 void testPassFloatStruct16BytesHomogeneousFloatFloatStruct1() {
   double a0;
   Struct16BytesHomogeneousFloat a1 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   double a2;
   Struct16BytesHomogeneousFloat a3 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   double a4;
   Struct16BytesHomogeneousFloat a5 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   double a6;
   Struct16BytesHomogeneousFloat a7 =
-      allocate<Struct16BytesHomogeneousFloat>().ref;
+      calloc<Struct16BytesHomogeneousFloat>().ref;
   double a8;
 
   a0 = -1.0;
@@ -3055,10 +3152,10 @@
 
   Expect.approxEquals(-11.0, result);
 
-  free(a1.addressOf);
-  free(a3.addressOf);
-  free(a5.addressOf);
-  free(a7.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a7.addressOf);
 }
 
 final passFloatStruct32BytesHomogeneousDoubleFloatStruct =
@@ -3088,16 +3185,16 @@
 void testPassFloatStruct32BytesHomogeneousDoubleFloatStruct() {
   double a0;
   Struct32BytesHomogeneousDouble a1 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   double a2;
   Struct32BytesHomogeneousDouble a3 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   double a4;
   Struct32BytesHomogeneousDouble a5 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   double a6;
   Struct32BytesHomogeneousDouble a7 =
-      allocate<Struct32BytesHomogeneousDouble>().ref;
+      calloc<Struct32BytesHomogeneousDouble>().ref;
   double a8;
 
   a0 = -1.0;
@@ -3129,10 +3226,10 @@
 
   Expect.approxEquals(-11.0, result);
 
-  free(a1.addressOf);
-  free(a3.addressOf);
-  free(a5.addressOf);
-  free(a7.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a7.addressOf);
 }
 
 final passInt8Struct16BytesMixedInt8Struct16BytesMixedIn =
@@ -3157,13 +3254,13 @@
 /// Test backfilling of integer registers.
 void testPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn() {
   int a0;
-  Struct16BytesMixed a1 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a1 = calloc<Struct16BytesMixed>().ref;
   int a2;
-  Struct16BytesMixed a3 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a3 = calloc<Struct16BytesMixed>().ref;
   int a4;
-  Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a5 = calloc<Struct16BytesMixed>().ref;
   int a6;
-  Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a7 = calloc<Struct16BytesMixed>().ref;
   int a8;
 
   a0 = -1;
@@ -3187,10 +3284,10 @@
 
   Expect.approxEquals(-7.0, result);
 
-  free(a1.addressOf);
-  free(a3.addressOf);
-  free(a5.addressOf);
-  free(a7.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a7.addressOf);
 }
 
 final passDoublex6Struct16BytesMixedx4Int32 = ffiTestFunctions.lookupFunction<
@@ -3229,10 +3326,10 @@
   double a3;
   double a4;
   double a5;
-  Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a8 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a9 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a6 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a7 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a8 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a9 = calloc<Struct16BytesMixed>().ref;
   int a10;
 
   a0 = -1.0;
@@ -3258,10 +3355,10 @@
 
   Expect.approxEquals(-8.0, result);
 
-  free(a6.addressOf);
-  free(a7.addressOf);
-  free(a8.addressOf);
-  free(a9.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
 }
 
 final passInt32x4Struct16BytesMixedx4Double = ffiTestFunctions.lookupFunction<
@@ -3286,10 +3383,10 @@
   int a1;
   int a2;
   int a3;
-  Struct16BytesMixed a4 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a5 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a6 = allocate<Struct16BytesMixed>().ref;
-  Struct16BytesMixed a7 = allocate<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a4 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a5 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a6 = calloc<Struct16BytesMixed>().ref;
+  Struct16BytesMixed a7 = calloc<Struct16BytesMixed>().ref;
   double a8;
 
   a0 = -1;
@@ -3313,10 +3410,10 @@
 
   Expect.approxEquals(-7.0, result);
 
-  free(a4.addressOf);
-  free(a5.addressOf);
-  free(a6.addressOf);
-  free(a7.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
 }
 
 final passStruct40BytesHomogeneousDoubleStruct4BytesHomo =
@@ -3331,11 +3428,9 @@
 /// Check that the other two arguments are allocated on registers.
 void testPassStruct40BytesHomogeneousDoubleStruct4BytesHomo() {
   Struct40BytesHomogeneousDouble a0 =
-      allocate<Struct40BytesHomogeneousDouble>().ref;
-  Struct4BytesHomogeneousInt16 a1 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
-  Struct8BytesHomogeneousFloat a2 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+      calloc<Struct40BytesHomogeneousDouble>().ref;
+  Struct4BytesHomogeneousInt16 a1 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct8BytesHomogeneousFloat a2 = calloc<Struct8BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -3353,9 +3448,9 @@
 
   Expect.approxEquals(-5.0, result);
 
-  free(a0.addressOf);
-  free(a1.addressOf);
-  free(a2.addressOf);
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
 }
 
 final passInt32x8Doublex8Int64Int8Struct1ByteIntInt64Int =
@@ -3463,30 +3558,28 @@
   double a15;
   int a16;
   int a17;
-  Struct1ByteInt a18 = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt a18 = calloc<Struct1ByteInt>().ref;
   int a19;
   int a20;
-  Struct4BytesHomogeneousInt16 a21 =
-      allocate<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a21 = calloc<Struct4BytesHomogeneousInt16>().ref;
   int a22;
   int a23;
-  Struct8BytesInt a24 = allocate<Struct8BytesInt>().ref;
+  Struct8BytesInt a24 = calloc<Struct8BytesInt>().ref;
   int a25;
   int a26;
-  Struct8BytesHomogeneousFloat a27 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a27 = calloc<Struct8BytesHomogeneousFloat>().ref;
   int a28;
   int a29;
-  Struct8BytesMixed a30 = allocate<Struct8BytesMixed>().ref;
+  Struct8BytesMixed a30 = calloc<Struct8BytesMixed>().ref;
   int a31;
   int a32;
-  StructAlignmentInt16 a33 = allocate<StructAlignmentInt16>().ref;
+  StructAlignmentInt16 a33 = calloc<StructAlignmentInt16>().ref;
   int a34;
   int a35;
-  StructAlignmentInt32 a36 = allocate<StructAlignmentInt32>().ref;
+  StructAlignmentInt32 a36 = calloc<StructAlignmentInt32>().ref;
   int a37;
   int a38;
-  StructAlignmentInt64 a39 = allocate<StructAlignmentInt64>().ref;
+  StructAlignmentInt64 a39 = calloc<StructAlignmentInt64>().ref;
 
   a0 = -1;
   a1 = 2;
@@ -3587,14 +3680,14 @@
 
   Expect.approxEquals(26.0, result);
 
-  free(a18.addressOf);
-  free(a21.addressOf);
-  free(a24.addressOf);
-  free(a27.addressOf);
-  free(a30.addressOf);
-  free(a33.addressOf);
-  free(a36.addressOf);
-  free(a39.addressOf);
+  calloc.free(a18.addressOf);
+  calloc.free(a21.addressOf);
+  calloc.free(a24.addressOf);
+  calloc.free(a27.addressOf);
+  calloc.free(a30.addressOf);
+  calloc.free(a33.addressOf);
+  calloc.free(a36.addressOf);
+  calloc.free(a39.addressOf);
 }
 
 final passStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
@@ -3603,7 +3696,7 @@
 
 /// Test alignment and padding of 16 byte int within struct.
 void testPassStructAlignmentInt16() {
-  StructAlignmentInt16 a0 = allocate<StructAlignmentInt16>().ref;
+  StructAlignmentInt16 a0 = calloc<StructAlignmentInt16>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -3615,7 +3708,7 @@
 
   Expect.equals(-2, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passStructAlignmentInt32 = ffiTestFunctions.lookupFunction<
@@ -3624,7 +3717,7 @@
 
 /// Test alignment and padding of 32 byte int within struct.
 void testPassStructAlignmentInt32() {
-  StructAlignmentInt32 a0 = allocate<StructAlignmentInt32>().ref;
+  StructAlignmentInt32 a0 = calloc<StructAlignmentInt32>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -3636,7 +3729,7 @@
 
   Expect.equals(-2, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final passStructAlignmentInt64 = ffiTestFunctions.lookupFunction<
@@ -3645,7 +3738,7 @@
 
 /// Test alignment and padding of 64 byte int within struct.
 void testPassStructAlignmentInt64() {
-  StructAlignmentInt64 a0 = allocate<StructAlignmentInt64>().ref;
+  StructAlignmentInt64 a0 = calloc<StructAlignmentInt64>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -3657,7 +3750,692 @@
 
   Expect.equals(-2, result);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
+}
+
+final passStruct8BytesNestedIntx10 = ffiTestFunctions.lookupFunction<
+    Int64 Function(
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt),
+    int Function(
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt,
+        Struct8BytesNestedInt)>("PassStruct8BytesNestedIntx10");
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust registers on all platforms.
+void testPassStruct8BytesNestedIntx10() {
+  Struct8BytesNestedInt a0 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a1 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a2 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a3 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a4 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a5 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a6 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a7 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a8 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a9 = calloc<Struct8BytesNestedInt>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3;
+  a0.a1.a1 = 4;
+  a1.a0.a0 = -5;
+  a1.a0.a1 = 6;
+  a1.a1.a0 = -7;
+  a1.a1.a1 = 8;
+  a2.a0.a0 = -9;
+  a2.a0.a1 = 10;
+  a2.a1.a0 = -11;
+  a2.a1.a1 = 12;
+  a3.a0.a0 = -13;
+  a3.a0.a1 = 14;
+  a3.a1.a0 = -15;
+  a3.a1.a1 = 16;
+  a4.a0.a0 = -17;
+  a4.a0.a1 = 18;
+  a4.a1.a0 = -19;
+  a4.a1.a1 = 20;
+  a5.a0.a0 = -21;
+  a5.a0.a1 = 22;
+  a5.a1.a0 = -23;
+  a5.a1.a1 = 24;
+  a6.a0.a0 = -25;
+  a6.a0.a1 = 26;
+  a6.a1.a0 = -27;
+  a6.a1.a1 = 28;
+  a7.a0.a0 = -29;
+  a7.a0.a1 = 30;
+  a7.a1.a0 = -31;
+  a7.a1.a1 = 32;
+  a8.a0.a0 = -33;
+  a8.a0.a1 = 34;
+  a8.a1.a0 = -35;
+  a8.a1.a1 = 36;
+  a9.a0.a0 = -37;
+  a9.a0.a1 = 38;
+  a9.a1.a0 = -39;
+  a9.a1.a1 = 40;
+
+  final result =
+      passStruct8BytesNestedIntx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  print("result = $result");
+
+  Expect.equals(20, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
+}
+
+final passStruct8BytesNestedFloatx10 = ffiTestFunctions.lookupFunction<
+    Float Function(
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat),
+    double Function(
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat,
+        Struct8BytesNestedFloat)>("PassStruct8BytesNestedFloatx10");
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust fpu registers on all platforms.
+void testPassStruct8BytesNestedFloatx10() {
+  Struct8BytesNestedFloat a0 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a1 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a2 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a3 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a4 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a5 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a6 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a7 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a8 = calloc<Struct8BytesNestedFloat>().ref;
+  Struct8BytesNestedFloat a9 = calloc<Struct8BytesNestedFloat>().ref;
+
+  a0.a0.a0 = -1.0;
+  a0.a1.a0 = 2.0;
+  a1.a0.a0 = -3.0;
+  a1.a1.a0 = 4.0;
+  a2.a0.a0 = -5.0;
+  a2.a1.a0 = 6.0;
+  a3.a0.a0 = -7.0;
+  a3.a1.a0 = 8.0;
+  a4.a0.a0 = -9.0;
+  a4.a1.a0 = 10.0;
+  a5.a0.a0 = -11.0;
+  a5.a1.a0 = 12.0;
+  a6.a0.a0 = -13.0;
+  a6.a1.a0 = 14.0;
+  a7.a0.a0 = -15.0;
+  a7.a1.a0 = 16.0;
+  a8.a0.a0 = -17.0;
+  a8.a1.a0 = 18.0;
+  a9.a0.a0 = -19.0;
+  a9.a1.a0 = 20.0;
+
+  final result =
+      passStruct8BytesNestedFloatx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  print("result = $result");
+
+  Expect.approxEquals(10.0, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
+}
+
+final passStruct8BytesNestedFloat2x10 = ffiTestFunctions.lookupFunction<
+    Float Function(
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2),
+    double Function(
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2,
+        Struct8BytesNestedFloat2)>("PassStruct8BytesNestedFloat2x10");
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust fpu registers on all platforms.
+/// The nesting is irregular, testing homogenous float rules on arm and arm64,
+/// and the fpu register usage on x64.
+void testPassStruct8BytesNestedFloat2x10() {
+  Struct8BytesNestedFloat2 a0 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a1 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a2 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a3 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a4 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a5 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a6 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a7 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a8 = calloc<Struct8BytesNestedFloat2>().ref;
+  Struct8BytesNestedFloat2 a9 = calloc<Struct8BytesNestedFloat2>().ref;
+
+  a0.a0.a0 = -1.0;
+  a0.a1 = 2.0;
+  a1.a0.a0 = -3.0;
+  a1.a1 = 4.0;
+  a2.a0.a0 = -5.0;
+  a2.a1 = 6.0;
+  a3.a0.a0 = -7.0;
+  a3.a1 = 8.0;
+  a4.a0.a0 = -9.0;
+  a4.a1 = 10.0;
+  a5.a0.a0 = -11.0;
+  a5.a1 = 12.0;
+  a6.a0.a0 = -13.0;
+  a6.a1 = 14.0;
+  a7.a0.a0 = -15.0;
+  a7.a1 = 16.0;
+  a8.a0.a0 = -17.0;
+  a8.a1 = 18.0;
+  a9.a0.a0 = -19.0;
+  a9.a1 = 20.0;
+
+  final result =
+      passStruct8BytesNestedFloat2x10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  print("result = $result");
+
+  Expect.approxEquals(10.0, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
+}
+
+final passStruct8BytesNestedMixedx10 = ffiTestFunctions.lookupFunction<
+    Double Function(
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed),
+    double Function(
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed,
+        Struct8BytesNestedMixed)>("PassStruct8BytesNestedMixedx10");
+
+/// Simple nested struct. No alignment gaps on any architectures.
+/// 10 arguments exhaust all registers on all platforms.
+void testPassStruct8BytesNestedMixedx10() {
+  Struct8BytesNestedMixed a0 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a1 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a2 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a3 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a4 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a5 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a6 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a7 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a8 = calloc<Struct8BytesNestedMixed>().ref;
+  Struct8BytesNestedMixed a9 = calloc<Struct8BytesNestedMixed>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3.0;
+  a1.a0.a0 = 4;
+  a1.a0.a1 = -5;
+  a1.a1.a0 = 6.0;
+  a2.a0.a0 = -7;
+  a2.a0.a1 = 8;
+  a2.a1.a0 = -9.0;
+  a3.a0.a0 = 10;
+  a3.a0.a1 = -11;
+  a3.a1.a0 = 12.0;
+  a4.a0.a0 = -13;
+  a4.a0.a1 = 14;
+  a4.a1.a0 = -15.0;
+  a5.a0.a0 = 16;
+  a5.a0.a1 = -17;
+  a5.a1.a0 = 18.0;
+  a6.a0.a0 = -19;
+  a6.a0.a1 = 20;
+  a6.a1.a0 = -21.0;
+  a7.a0.a0 = 22;
+  a7.a0.a1 = -23;
+  a7.a1.a0 = 24.0;
+  a8.a0.a0 = -25;
+  a8.a0.a1 = 26;
+  a8.a1.a0 = -27.0;
+  a9.a0.a0 = 28;
+  a9.a0.a1 = -29;
+  a9.a1.a0 = 30.0;
+
+  final result =
+      passStruct8BytesNestedMixedx10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  print("result = $result");
+
+  Expect.approxEquals(15.0, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
+  calloc.free(a4.addressOf);
+  calloc.free(a5.addressOf);
+  calloc.free(a6.addressOf);
+  calloc.free(a7.addressOf);
+  calloc.free(a8.addressOf);
+  calloc.free(a9.addressOf);
+}
+
+final passStruct16BytesNestedIntx2 = ffiTestFunctions.lookupFunction<
+    Int64 Function(Struct16BytesNestedInt, Struct16BytesNestedInt),
+    int Function(Struct16BytesNestedInt,
+        Struct16BytesNestedInt)>("PassStruct16BytesNestedIntx2");
+
+/// Deeper nested struct to test recursive member access.
+void testPassStruct16BytesNestedIntx2() {
+  Struct16BytesNestedInt a0 = calloc<Struct16BytesNestedInt>().ref;
+  Struct16BytesNestedInt a1 = calloc<Struct16BytesNestedInt>().ref;
+
+  a0.a0.a0.a0 = -1;
+  a0.a0.a0.a1 = 2;
+  a0.a0.a1.a0 = -3;
+  a0.a0.a1.a1 = 4;
+  a0.a1.a0.a0 = -5;
+  a0.a1.a0.a1 = 6;
+  a0.a1.a1.a0 = -7;
+  a0.a1.a1.a1 = 8;
+  a1.a0.a0.a0 = -9;
+  a1.a0.a0.a1 = 10;
+  a1.a0.a1.a0 = -11;
+  a1.a0.a1.a1 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15;
+  a1.a1.a1.a1 = 16;
+
+  final result = passStruct16BytesNestedIntx2(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(8, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final passStruct32BytesNestedIntx2 = ffiTestFunctions.lookupFunction<
+    Int64 Function(Struct32BytesNestedInt, Struct32BytesNestedInt),
+    int Function(Struct32BytesNestedInt,
+        Struct32BytesNestedInt)>("PassStruct32BytesNestedIntx2");
+
+/// Even deeper nested struct to test recursive member access.
+void testPassStruct32BytesNestedIntx2() {
+  Struct32BytesNestedInt a0 = calloc<Struct32BytesNestedInt>().ref;
+  Struct32BytesNestedInt a1 = calloc<Struct32BytesNestedInt>().ref;
+
+  a0.a0.a0.a0.a0 = -1;
+  a0.a0.a0.a0.a1 = 2;
+  a0.a0.a0.a1.a0 = -3;
+  a0.a0.a0.a1.a1 = 4;
+  a0.a0.a1.a0.a0 = -5;
+  a0.a0.a1.a0.a1 = 6;
+  a0.a0.a1.a1.a0 = -7;
+  a0.a0.a1.a1.a1 = 8;
+  a0.a1.a0.a0.a0 = -9;
+  a0.a1.a0.a0.a1 = 10;
+  a0.a1.a0.a1.a0 = -11;
+  a0.a1.a0.a1.a1 = 12;
+  a0.a1.a1.a0.a0 = -13;
+  a0.a1.a1.a0.a1 = 14;
+  a0.a1.a1.a1.a0 = -15;
+  a0.a1.a1.a1.a1 = 16;
+  a1.a0.a0.a0.a0 = -17;
+  a1.a0.a0.a0.a1 = 18;
+  a1.a0.a0.a1.a0 = -19;
+  a1.a0.a0.a1.a1 = 20;
+  a1.a0.a1.a0.a0 = -21;
+  a1.a0.a1.a0.a1 = 22;
+  a1.a0.a1.a1.a0 = -23;
+  a1.a0.a1.a1.a1 = 24;
+  a1.a1.a0.a0.a0 = -25;
+  a1.a1.a0.a0.a1 = 26;
+  a1.a1.a0.a1.a0 = -27;
+  a1.a1.a0.a1.a1 = 28;
+  a1.a1.a1.a0.a0 = -29;
+  a1.a1.a1.a0.a1 = 30;
+  a1.a1.a1.a1.a0 = -31;
+  a1.a1.a1.a1.a1 = 32;
+
+  final result = passStruct32BytesNestedIntx2(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(16, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final passStructNestedIntStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
+        Int64 Function(StructNestedIntStructAlignmentInt16),
+        int Function(StructNestedIntStructAlignmentInt16)>(
+    "PassStructNestedIntStructAlignmentInt16");
+
+/// Test alignment and padding of nested struct with 16 byte int.
+void testPassStructNestedIntStructAlignmentInt16() {
+  StructNestedIntStructAlignmentInt16 a0 =
+      calloc<StructNestedIntStructAlignmentInt16>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  final result = passStructNestedIntStructAlignmentInt16(a0);
+
+  print("result = $result");
+
+  Expect.equals(3, result);
+
+  calloc.free(a0.addressOf);
+}
+
+final passStructNestedIntStructAlignmentInt32 = ffiTestFunctions.lookupFunction<
+        Int64 Function(StructNestedIntStructAlignmentInt32),
+        int Function(StructNestedIntStructAlignmentInt32)>(
+    "PassStructNestedIntStructAlignmentInt32");
+
+/// Test alignment and padding of nested struct with 32 byte int.
+void testPassStructNestedIntStructAlignmentInt32() {
+  StructNestedIntStructAlignmentInt32 a0 =
+      calloc<StructNestedIntStructAlignmentInt32>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  final result = passStructNestedIntStructAlignmentInt32(a0);
+
+  print("result = $result");
+
+  Expect.equals(3, result);
+
+  calloc.free(a0.addressOf);
+}
+
+final passStructNestedIntStructAlignmentInt64 = ffiTestFunctions.lookupFunction<
+        Int64 Function(StructNestedIntStructAlignmentInt64),
+        int Function(StructNestedIntStructAlignmentInt64)>(
+    "PassStructNestedIntStructAlignmentInt64");
+
+/// Test alignment and padding of nested struct with 64 byte int.
+void testPassStructNestedIntStructAlignmentInt64() {
+  StructNestedIntStructAlignmentInt64 a0 =
+      calloc<StructNestedIntStructAlignmentInt64>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a0.a2 = -3;
+  a0.a1.a0 = 4;
+  a0.a1.a1 = -5;
+  a0.a1.a2 = 6;
+
+  final result = passStructNestedIntStructAlignmentInt64(a0);
+
+  print("result = $result");
+
+  Expect.equals(3, result);
+
+  calloc.free(a0.addressOf);
+}
+
+final passStructNestedIrregularEvenBiggerx4 = ffiTestFunctions.lookupFunction<
+        Double Function(
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger),
+        double Function(
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger,
+            StructNestedIrregularEvenBigger)>(
+    "PassStructNestedIrregularEvenBiggerx4");
+
+/// Return big irregular struct as smoke test.
+void testPassStructNestedIrregularEvenBiggerx4() {
+  StructNestedIrregularEvenBigger a0 =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+  StructNestedIrregularEvenBigger a1 =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+  StructNestedIrregularEvenBigger a2 =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+  StructNestedIrregularEvenBigger a3 =
+      calloc<StructNestedIrregularEvenBigger>().ref;
+
+  a0.a0 = 1;
+  a0.a1.a0.a0 = 2;
+  a0.a1.a0.a1.a0.a0 = -3;
+  a0.a1.a0.a1.a0.a1 = 4;
+  a0.a1.a0.a1.a1.a0 = -5.0;
+  a0.a1.a0.a2 = 6;
+  a0.a1.a0.a3.a0.a0 = -7.0;
+  a0.a1.a0.a3.a1 = 8.0;
+  a0.a1.a0.a4 = 9;
+  a0.a1.a0.a5.a0.a0 = 10.0;
+  a0.a1.a0.a5.a1.a0 = -11.0;
+  a0.a1.a0.a6 = 12;
+  a0.a1.a1.a0.a0 = -13;
+  a0.a1.a1.a0.a1 = 14;
+  a0.a1.a1.a1.a0 = -15.0;
+  a0.a1.a2 = 16.0;
+  a0.a1.a3 = -17.0;
+  a0.a2.a0.a0 = 18;
+  a0.a2.a0.a1.a0.a0 = -19;
+  a0.a2.a0.a1.a0.a1 = 20;
+  a0.a2.a0.a1.a1.a0 = -21.0;
+  a0.a2.a0.a2 = 22;
+  a0.a2.a0.a3.a0.a0 = -23.0;
+  a0.a2.a0.a3.a1 = 24.0;
+  a0.a2.a0.a4 = 25;
+  a0.a2.a0.a5.a0.a0 = 26.0;
+  a0.a2.a0.a5.a1.a0 = -27.0;
+  a0.a2.a0.a6 = 28;
+  a0.a2.a1.a0.a0 = -29;
+  a0.a2.a1.a0.a1 = 30;
+  a0.a2.a1.a1.a0 = -31.0;
+  a0.a2.a2 = 32.0;
+  a0.a2.a3 = -33.0;
+  a0.a3 = 34.0;
+  a1.a0 = 35;
+  a1.a1.a0.a0 = 36;
+  a1.a1.a0.a1.a0.a0 = -37;
+  a1.a1.a0.a1.a0.a1 = 38;
+  a1.a1.a0.a1.a1.a0 = -39.0;
+  a1.a1.a0.a2 = 40;
+  a1.a1.a0.a3.a0.a0 = -41.0;
+  a1.a1.a0.a3.a1 = 42.0;
+  a1.a1.a0.a4 = 43;
+  a1.a1.a0.a5.a0.a0 = 44.0;
+  a1.a1.a0.a5.a1.a0 = -45.0;
+  a1.a1.a0.a6 = 46;
+  a1.a1.a1.a0.a0 = -47;
+  a1.a1.a1.a0.a1 = 48;
+  a1.a1.a1.a1.a0 = -49.0;
+  a1.a1.a2 = 50.0;
+  a1.a1.a3 = -51.0;
+  a1.a2.a0.a0 = 52;
+  a1.a2.a0.a1.a0.a0 = -53;
+  a1.a2.a0.a1.a0.a1 = 54;
+  a1.a2.a0.a1.a1.a0 = -55.0;
+  a1.a2.a0.a2 = 56;
+  a1.a2.a0.a3.a0.a0 = -57.0;
+  a1.a2.a0.a3.a1 = 58.0;
+  a1.a2.a0.a4 = 59;
+  a1.a2.a0.a5.a0.a0 = 60.0;
+  a1.a2.a0.a5.a1.a0 = -61.0;
+  a1.a2.a0.a6 = 62;
+  a1.a2.a1.a0.a0 = -63;
+  a1.a2.a1.a0.a1 = 64;
+  a1.a2.a1.a1.a0 = -65.0;
+  a1.a2.a2 = 66.0;
+  a1.a2.a3 = -67.0;
+  a1.a3 = 68.0;
+  a2.a0 = 69;
+  a2.a1.a0.a0 = 70;
+  a2.a1.a0.a1.a0.a0 = -71;
+  a2.a1.a0.a1.a0.a1 = 72;
+  a2.a1.a0.a1.a1.a0 = -73.0;
+  a2.a1.a0.a2 = 74;
+  a2.a1.a0.a3.a0.a0 = -75.0;
+  a2.a1.a0.a3.a1 = 76.0;
+  a2.a1.a0.a4 = 77;
+  a2.a1.a0.a5.a0.a0 = 78.0;
+  a2.a1.a0.a5.a1.a0 = -79.0;
+  a2.a1.a0.a6 = 80;
+  a2.a1.a1.a0.a0 = -81;
+  a2.a1.a1.a0.a1 = 82;
+  a2.a1.a1.a1.a0 = -83.0;
+  a2.a1.a2 = 84.0;
+  a2.a1.a3 = -85.0;
+  a2.a2.a0.a0 = 86;
+  a2.a2.a0.a1.a0.a0 = -87;
+  a2.a2.a0.a1.a0.a1 = 88;
+  a2.a2.a0.a1.a1.a0 = -89.0;
+  a2.a2.a0.a2 = 90;
+  a2.a2.a0.a3.a0.a0 = -91.0;
+  a2.a2.a0.a3.a1 = 92.0;
+  a2.a2.a0.a4 = 93;
+  a2.a2.a0.a5.a0.a0 = 94.0;
+  a2.a2.a0.a5.a1.a0 = -95.0;
+  a2.a2.a0.a6 = 96;
+  a2.a2.a1.a0.a0 = -97;
+  a2.a2.a1.a0.a1 = 98;
+  a2.a2.a1.a1.a0 = -99.0;
+  a2.a2.a2 = 100.0;
+  a2.a2.a3 = -101.0;
+  a2.a3 = 102.0;
+  a3.a0 = 103;
+  a3.a1.a0.a0 = 104;
+  a3.a1.a0.a1.a0.a0 = -105;
+  a3.a1.a0.a1.a0.a1 = 106;
+  a3.a1.a0.a1.a1.a0 = -107.0;
+  a3.a1.a0.a2 = 108;
+  a3.a1.a0.a3.a0.a0 = -109.0;
+  a3.a1.a0.a3.a1 = 110.0;
+  a3.a1.a0.a4 = 111;
+  a3.a1.a0.a5.a0.a0 = 112.0;
+  a3.a1.a0.a5.a1.a0 = -113.0;
+  a3.a1.a0.a6 = 114;
+  a3.a1.a1.a0.a0 = -115;
+  a3.a1.a1.a0.a1 = 116;
+  a3.a1.a1.a1.a0 = -117.0;
+  a3.a1.a2 = 118.0;
+  a3.a1.a3 = -119.0;
+  a3.a2.a0.a0 = 120;
+  a3.a2.a0.a1.a0.a0 = -121;
+  a3.a2.a0.a1.a0.a1 = 122;
+  a3.a2.a0.a1.a1.a0 = -123.0;
+  a3.a2.a0.a2 = 124;
+  a3.a2.a0.a3.a0.a0 = -125.0;
+  a3.a2.a0.a3.a1 = 126.0;
+  a3.a2.a0.a4 = 127;
+  a3.a2.a0.a5.a0.a0 = 128.0;
+  a3.a2.a0.a5.a1.a0 = -129.0;
+  a3.a2.a0.a6 = 130;
+  a3.a2.a1.a0.a0 = -131;
+  a3.a2.a1.a0.a1 = 132;
+  a3.a2.a1.a1.a0 = -133.0;
+  a3.a2.a2 = 134.0;
+  a3.a2.a3 = -135.0;
+  a3.a3 = 136.0;
+
+  final result = passStructNestedIrregularEvenBiggerx4(a0, a1, a2, a3);
+
+  print("result = $result");
+
+  Expect.approxEquals(1572.0, result);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+  calloc.free(a3.addressOf);
 }
 
 final returnStruct1ByteInt = ffiTestFunctions.lookupFunction<
@@ -5087,7 +5865,7 @@
 /// Especially for ffi callbacks.
 /// Struct is passed in int registers in most ABIs.
 void testReturnStructArgumentStruct1ByteInt() {
-  Struct1ByteInt a0 = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt a0 = calloc<Struct1ByteInt>().ref;
 
   a0.a0 = -1;
 
@@ -5097,7 +5875,7 @@
 
   Expect.equals(a0.a0, result.a0);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final returnStructArgumentInt32x8Struct1ByteInt =
@@ -5119,7 +5897,7 @@
   int a5;
   int a6;
   int a7;
-  Struct1ByteInt a8 = allocate<Struct1ByteInt>().ref;
+  Struct1ByteInt a8 = calloc<Struct1ByteInt>().ref;
 
   a0 = -1;
   a1 = 2;
@@ -5138,7 +5916,7 @@
 
   Expect.equals(a8.a0, result.a0);
 
-  free(a8.addressOf);
+  calloc.free(a8.addressOf);
 }
 
 final returnStructArgumentStruct8BytesHomogeneousFloat =
@@ -5152,8 +5930,7 @@
 /// Especially for ffi callbacks.
 /// Struct is passed in float registers in most ABIs.
 void testReturnStructArgumentStruct8BytesHomogeneousFloat() {
-  Struct8BytesHomogeneousFloat a0 =
-      allocate<Struct8BytesHomogeneousFloat>().ref;
+  Struct8BytesHomogeneousFloat a0 = calloc<Struct8BytesHomogeneousFloat>().ref;
 
   a0.a0 = -1.0;
   a0.a1 = 2.0;
@@ -5165,7 +5942,7 @@
   Expect.approxEquals(a0.a0, result.a0);
   Expect.approxEquals(a0.a1, result.a1);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final returnStructArgumentStruct20BytesHomogeneousInt32 =
@@ -5180,7 +5957,7 @@
 /// On arm64, both argument and return value are passed in by pointer.
 void testReturnStructArgumentStruct20BytesHomogeneousInt32() {
   Struct20BytesHomogeneousInt32 a0 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
 
   a0.a0 = -1;
   a0.a1 = 2;
@@ -5198,7 +5975,7 @@
   Expect.equals(a0.a3, result.a3);
   Expect.equals(a0.a4, result.a4);
 
-  free(a0.addressOf);
+  calloc.free(a0.addressOf);
 }
 
 final returnStructArgumentInt32x8Struct20BytesHomogeneou =
@@ -5221,7 +5998,7 @@
   int a6;
   int a7;
   Struct20BytesHomogeneousInt32 a8 =
-      allocate<Struct20BytesHomogeneousInt32>().ref;
+      calloc<Struct20BytesHomogeneousInt32>().ref;
 
   a0 = -1;
   a1 = 2;
@@ -5248,7 +6025,7 @@
   Expect.equals(a8.a3, result.a3);
   Expect.equals(a8.a4, result.a4);
 
-  free(a8.addressOf);
+  calloc.free(a8.addressOf);
 }
 
 final returnStructAlignmentInt16 = ffiTestFunctions.lookupFunction<
@@ -5319,3 +6096,393 @@
   Expect.equals(a1, result.a1);
   Expect.equals(a2, result.a2);
 }
+
+final returnStruct8BytesNestedInt = ffiTestFunctions.lookupFunction<
+    Struct8BytesNestedInt Function(
+        Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16),
+    Struct8BytesNestedInt Function(Struct4BytesHomogeneousInt16,
+        Struct4BytesHomogeneousInt16)>("ReturnStruct8BytesNestedInt");
+
+/// Simple nested struct.
+void testReturnStruct8BytesNestedInt() {
+  Struct4BytesHomogeneousInt16 a0 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesHomogeneousInt16 a1 = calloc<Struct4BytesHomogeneousInt16>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a1.a0 = -3;
+  a1.a1 = 4;
+
+  final result = returnStruct8BytesNestedInt(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.equals(a1.a0, result.a1.a0);
+  Expect.equals(a1.a1, result.a1.a1);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStruct8BytesNestedFloat = ffiTestFunctions.lookupFunction<
+    Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat),
+    Struct8BytesNestedFloat Function(
+        Struct4BytesFloat, Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat");
+
+/// Simple nested struct with floats.
+void testReturnStruct8BytesNestedFloat() {
+  Struct4BytesFloat a0 = calloc<Struct4BytesFloat>().ref;
+  Struct4BytesFloat a1 = calloc<Struct4BytesFloat>().ref;
+
+  a0.a0 = -1.0;
+  a1.a0 = 2.0;
+
+  final result = returnStruct8BytesNestedFloat(a0, a1);
+
+  print("result = $result");
+
+  Expect.approxEquals(a0.a0, result.a0.a0);
+  Expect.approxEquals(a1.a0, result.a1.a0);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStruct8BytesNestedFloat2 = ffiTestFunctions.lookupFunction<
+    Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float),
+    Struct8BytesNestedFloat2 Function(
+        Struct4BytesFloat, double)>("ReturnStruct8BytesNestedFloat2");
+
+/// The nesting is irregular, testing homogenous float rules on arm and arm64,
+/// and the fpu register usage on x64.
+void testReturnStruct8BytesNestedFloat2() {
+  Struct4BytesFloat a0 = calloc<Struct4BytesFloat>().ref;
+  double a1;
+
+  a0.a0 = -1.0;
+  a1 = 2.0;
+
+  final result = returnStruct8BytesNestedFloat2(a0, a1);
+
+  print("result = $result");
+
+  Expect.approxEquals(a0.a0, result.a0.a0);
+  Expect.approxEquals(a1, result.a1);
+
+  calloc.free(a0.addressOf);
+}
+
+final returnStruct8BytesNestedMixed = ffiTestFunctions.lookupFunction<
+    Struct8BytesNestedMixed Function(
+        Struct4BytesHomogeneousInt16, Struct4BytesFloat),
+    Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16,
+        Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed");
+
+/// Simple nested struct with mixed members.
+void testReturnStruct8BytesNestedMixed() {
+  Struct4BytesHomogeneousInt16 a0 = calloc<Struct4BytesHomogeneousInt16>().ref;
+  Struct4BytesFloat a1 = calloc<Struct4BytesFloat>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a1.a0 = -3.0;
+
+  final result = returnStruct8BytesNestedMixed(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.approxEquals(a1.a0, result.a1.a0);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStruct16BytesNestedInt = ffiTestFunctions.lookupFunction<
+    Struct16BytesNestedInt Function(
+        Struct8BytesNestedInt, Struct8BytesNestedInt),
+    Struct16BytesNestedInt Function(Struct8BytesNestedInt,
+        Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt");
+
+/// Deeper nested struct to test recursive member access.
+void testReturnStruct16BytesNestedInt() {
+  Struct8BytesNestedInt a0 = calloc<Struct8BytesNestedInt>().ref;
+  Struct8BytesNestedInt a1 = calloc<Struct8BytesNestedInt>().ref;
+
+  a0.a0.a0 = -1;
+  a0.a0.a1 = 2;
+  a0.a1.a0 = -3;
+  a0.a1.a1 = 4;
+  a1.a0.a0 = -5;
+  a1.a0.a1 = 6;
+  a1.a1.a0 = -7;
+  a1.a1.a1 = 8;
+
+  final result = returnStruct16BytesNestedInt(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0.a0, result.a0.a0.a0);
+  Expect.equals(a0.a0.a1, result.a0.a0.a1);
+  Expect.equals(a0.a1.a0, result.a0.a1.a0);
+  Expect.equals(a0.a1.a1, result.a0.a1.a1);
+  Expect.equals(a1.a0.a0, result.a1.a0.a0);
+  Expect.equals(a1.a0.a1, result.a1.a0.a1);
+  Expect.equals(a1.a1.a0, result.a1.a1.a0);
+  Expect.equals(a1.a1.a1, result.a1.a1.a1);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStruct32BytesNestedInt = ffiTestFunctions.lookupFunction<
+    Struct32BytesNestedInt Function(
+        Struct16BytesNestedInt, Struct16BytesNestedInt),
+    Struct32BytesNestedInt Function(Struct16BytesNestedInt,
+        Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt");
+
+/// Even deeper nested struct to test recursive member access.
+void testReturnStruct32BytesNestedInt() {
+  Struct16BytesNestedInt a0 = calloc<Struct16BytesNestedInt>().ref;
+  Struct16BytesNestedInt a1 = calloc<Struct16BytesNestedInt>().ref;
+
+  a0.a0.a0.a0 = -1;
+  a0.a0.a0.a1 = 2;
+  a0.a0.a1.a0 = -3;
+  a0.a0.a1.a1 = 4;
+  a0.a1.a0.a0 = -5;
+  a0.a1.a0.a1 = 6;
+  a0.a1.a1.a0 = -7;
+  a0.a1.a1.a1 = 8;
+  a1.a0.a0.a0 = -9;
+  a1.a0.a0.a1 = 10;
+  a1.a0.a1.a0 = -11;
+  a1.a0.a1.a1 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15;
+  a1.a1.a1.a1 = 16;
+
+  final result = returnStruct32BytesNestedInt(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0);
+  Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1);
+  Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0);
+  Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1);
+  Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0);
+  Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1);
+  Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0);
+  Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1);
+  Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0);
+  Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1);
+  Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0);
+  Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1);
+  Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0);
+  Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1);
+  Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0);
+  Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStructNestedIntStructAlignmentInt16 =
+    ffiTestFunctions.lookupFunction<
+        StructNestedIntStructAlignmentInt16 Function(
+            StructAlignmentInt16, StructAlignmentInt16),
+        StructNestedIntStructAlignmentInt16 Function(StructAlignmentInt16,
+            StructAlignmentInt16)>("ReturnStructNestedIntStructAlignmentInt16");
+
+/// Test alignment and padding of nested struct with 16 byte int.
+void testReturnStructNestedIntStructAlignmentInt16() {
+  StructAlignmentInt16 a0 = calloc<StructAlignmentInt16>().ref;
+  StructAlignmentInt16 a1 = calloc<StructAlignmentInt16>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  final result = returnStructNestedIntStructAlignmentInt16(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.equals(a0.a2, result.a0.a2);
+  Expect.equals(a1.a0, result.a1.a0);
+  Expect.equals(a1.a1, result.a1.a1);
+  Expect.equals(a1.a2, result.a1.a2);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStructNestedIntStructAlignmentInt32 =
+    ffiTestFunctions.lookupFunction<
+        StructNestedIntStructAlignmentInt32 Function(
+            StructAlignmentInt32, StructAlignmentInt32),
+        StructNestedIntStructAlignmentInt32 Function(StructAlignmentInt32,
+            StructAlignmentInt32)>("ReturnStructNestedIntStructAlignmentInt32");
+
+/// Test alignment and padding of nested struct with 32 byte int.
+void testReturnStructNestedIntStructAlignmentInt32() {
+  StructAlignmentInt32 a0 = calloc<StructAlignmentInt32>().ref;
+  StructAlignmentInt32 a1 = calloc<StructAlignmentInt32>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  final result = returnStructNestedIntStructAlignmentInt32(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.equals(a0.a2, result.a0.a2);
+  Expect.equals(a1.a0, result.a1.a0);
+  Expect.equals(a1.a1, result.a1.a1);
+  Expect.equals(a1.a2, result.a1.a2);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStructNestedIntStructAlignmentInt64 =
+    ffiTestFunctions.lookupFunction<
+        StructNestedIntStructAlignmentInt64 Function(
+            StructAlignmentInt64, StructAlignmentInt64),
+        StructNestedIntStructAlignmentInt64 Function(StructAlignmentInt64,
+            StructAlignmentInt64)>("ReturnStructNestedIntStructAlignmentInt64");
+
+/// Test alignment and padding of nested struct with 64 byte int.
+void testReturnStructNestedIntStructAlignmentInt64() {
+  StructAlignmentInt64 a0 = calloc<StructAlignmentInt64>().ref;
+  StructAlignmentInt64 a1 = calloc<StructAlignmentInt64>().ref;
+
+  a0.a0 = -1;
+  a0.a1 = 2;
+  a0.a2 = -3;
+  a1.a0 = 4;
+  a1.a1 = -5;
+  a1.a2 = 6;
+
+  final result = returnStructNestedIntStructAlignmentInt64(a0, a1);
+
+  print("result = $result");
+
+  Expect.equals(a0.a0, result.a0.a0);
+  Expect.equals(a0.a1, result.a0.a1);
+  Expect.equals(a0.a2, result.a0.a2);
+  Expect.equals(a1.a0, result.a1.a0);
+  Expect.equals(a1.a1, result.a1.a1);
+  Expect.equals(a1.a2, result.a1.a2);
+
+  calloc.free(a0.addressOf);
+  calloc.free(a1.addressOf);
+}
+
+final returnStructNestedIrregularEvenBigger = ffiTestFunctions.lookupFunction<
+    StructNestedIrregularEvenBigger Function(Uint64,
+        StructNestedIrregularBigger, StructNestedIrregularBigger, Double),
+    StructNestedIrregularEvenBigger Function(
+        int,
+        StructNestedIrregularBigger,
+        StructNestedIrregularBigger,
+        double)>("ReturnStructNestedIrregularEvenBigger");
+
+/// Return big irregular struct as smoke test.
+void testReturnStructNestedIrregularEvenBigger() {
+  int a0;
+  StructNestedIrregularBigger a1 = calloc<StructNestedIrregularBigger>().ref;
+  StructNestedIrregularBigger a2 = calloc<StructNestedIrregularBigger>().ref;
+  double a3;
+
+  a0 = 1;
+  a1.a0.a0 = 2;
+  a1.a0.a1.a0.a0 = -3;
+  a1.a0.a1.a0.a1 = 4;
+  a1.a0.a1.a1.a0 = -5.0;
+  a1.a0.a2 = 6;
+  a1.a0.a3.a0.a0 = -7.0;
+  a1.a0.a3.a1 = 8.0;
+  a1.a0.a4 = 9;
+  a1.a0.a5.a0.a0 = 10.0;
+  a1.a0.a5.a1.a0 = -11.0;
+  a1.a0.a6 = 12;
+  a1.a1.a0.a0 = -13;
+  a1.a1.a0.a1 = 14;
+  a1.a1.a1.a0 = -15.0;
+  a1.a2 = 16.0;
+  a1.a3 = -17.0;
+  a2.a0.a0 = 18;
+  a2.a0.a1.a0.a0 = -19;
+  a2.a0.a1.a0.a1 = 20;
+  a2.a0.a1.a1.a0 = -21.0;
+  a2.a0.a2 = 22;
+  a2.a0.a3.a0.a0 = -23.0;
+  a2.a0.a3.a1 = 24.0;
+  a2.a0.a4 = 25;
+  a2.a0.a5.a0.a0 = 26.0;
+  a2.a0.a5.a1.a0 = -27.0;
+  a2.a0.a6 = 28;
+  a2.a1.a0.a0 = -29;
+  a2.a1.a0.a1 = 30;
+  a2.a1.a1.a0 = -31.0;
+  a2.a2 = 32.0;
+  a2.a3 = -33.0;
+  a3 = 34.0;
+
+  final result = returnStructNestedIrregularEvenBigger(a0, a1, a2, a3);
+
+  print("result = $result");
+
+  Expect.equals(a0, result.a0);
+  Expect.equals(a1.a0.a0, result.a1.a0.a0);
+  Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0);
+  Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1);
+  Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0);
+  Expect.equals(a1.a0.a2, result.a1.a0.a2);
+  Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0);
+  Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1);
+  Expect.equals(a1.a0.a4, result.a1.a0.a4);
+  Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0);
+  Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0);
+  Expect.equals(a1.a0.a6, result.a1.a0.a6);
+  Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0);
+  Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1);
+  Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0);
+  Expect.approxEquals(a1.a2, result.a1.a2);
+  Expect.approxEquals(a1.a3, result.a1.a3);
+  Expect.equals(a2.a0.a0, result.a2.a0.a0);
+  Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0);
+  Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1);
+  Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0);
+  Expect.equals(a2.a0.a2, result.a2.a0.a2);
+  Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0);
+  Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1);
+  Expect.equals(a2.a0.a4, result.a2.a0.a4);
+  Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0);
+  Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0);
+  Expect.equals(a2.a0.a6, result.a2.a0.a6);
+  Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0);
+  Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1);
+  Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0);
+  Expect.approxEquals(a2.a2, result.a2.a2);
+  Expect.approxEquals(a2.a3, result.a2.a3);
+  Expect.approxEquals(a3, result.a3);
+
+  calloc.free(a1.addressOf);
+  calloc.free(a2.addressOf);
+}
diff --git a/tests/ffi_2/function_structs_test.dart b/tests/ffi_2/function_structs_test.dart
index bf9ea5f..6bb3e56 100644
--- a/tests/ffi_2/function_structs_test.dart
+++ b/tests/ffi_2/function_structs_test.dart
@@ -9,12 +9,12 @@
 
 import 'dart:ffi';
 
-import 'dylib_utils.dart';
-
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'coordinate.dart';
+import 'dylib_utils.dart';
 import 'very_large_struct.dart';
 
 typedef NativeCoordinateOp = Pointer<Coordinate> Function(Pointer<Coordinate>);
@@ -33,8 +33,10 @@
       ffiTestFunctions.lookup("TransposeCoordinate");
   NativeCoordinateOp f1 = p1.asFunction();
 
-  Pointer<Coordinate> c1 = Coordinate.allocate(10.0, 20.0, nullptr).addressOf;
-  Pointer<Coordinate> c2 = Coordinate.allocate(42.0, 84.0, c1).addressOf;
+  Pointer<Coordinate> c1 =
+      Coordinate.allocate(calloc, 10.0, 20.0, nullptr).addressOf;
+  Pointer<Coordinate> c2 =
+      Coordinate.allocate(calloc, 42.0, 84.0, c1).addressOf;
   c1.ref.next = c2;
 
   Coordinate result = f1(c1).ref;
@@ -45,8 +47,8 @@
   Expect.approxEquals(42.0, result.x);
   Expect.approxEquals(84.0, result.y);
 
-  free(c1);
-  free(c2);
+  calloc.free(c1);
+  calloc.free(c2);
 }
 
 /// pass an array of structs to a c funtion
@@ -55,7 +57,7 @@
       ffiTestFunctions.lookup("CoordinateElemAt1");
   NativeCoordinateOp f1 = p1.asFunction();
 
-  Coordinate c1 = allocate<Coordinate>(count: 3).ref;
+  Coordinate c1 = calloc<Coordinate>(3).ref;
   Coordinate c2 = c1.addressOf[1];
   Coordinate c3 = c1.addressOf[2];
   c1.x = 10.0;
@@ -72,7 +74,7 @@
   Expect.approxEquals(20.0, result.x);
   Expect.approxEquals(20.0, result.y);
 
-  free(c1.addressOf);
+  calloc.free(c1.addressOf);
 }
 
 typedef VeryLargeStructSum = int Function(Pointer<VeryLargeStruct>);
@@ -83,7 +85,7 @@
       ffiTestFunctions.lookup("SumVeryLargeStruct");
   VeryLargeStructSum f = p1.asFunction();
 
-  VeryLargeStruct vls1 = allocate<VeryLargeStruct>(count: 2).ref;
+  VeryLargeStruct vls1 = calloc<VeryLargeStruct>(2).ref;
   VeryLargeStruct vls2 = vls1.addressOf[1];
   List<VeryLargeStruct> structs = [vls1, vls2];
   for (VeryLargeStruct struct in structs) {
@@ -114,5 +116,5 @@
   result = f(vls2.addressOf);
   Expect.equals(2048, result);
 
-  free(vls1.addressOf);
+  calloc.free(vls1.addressOf);
 }
diff --git a/tests/ffi_2/function_test.dart b/tests/ffi_2/function_test.dart
index bff456e..b547ffe 100644
--- a/tests/ffi_2/function_test.dart
+++ b/tests/ffi_2/function_test.dart
@@ -15,11 +15,12 @@
 
 import 'dart:ffi';
 
-import 'dylib_utils.dart';
-
 import "package:ffi/ffi.dart";
 import "package:expect/expect.dart";
 
+import 'dylib_utils.dart';
+import 'calloc.dart';
+
 void main() {
   for (int i = 0; i < 100; ++i) {
     testNativeFunctionFromCast();
@@ -50,11 +51,11 @@
 typedef GenericBinaryOp<T> = int Function(int, T);
 
 void testNativeFunctionFromCast() {
-  Pointer<IntPtr> p1 = allocate();
+  Pointer<IntPtr> p1 = calloc();
   Pointer<NativeFunction<NativeBinaryOp>> p2 = p1.cast();
   p2.asFunction<BinaryOp>();
   p2.asFunction<GenericBinaryOp<int>>();
-  free(p1);
+  calloc.free(p1);
 }
 
 typedef NativeQuadOpSigned = Int64 Function(Int8, Int16, Int32, Int64);
@@ -394,14 +395,14 @@
     .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
 
 void testNativeFunctionPointer() {
-  Pointer<Int64> p2 = allocate(count: 2);
+  Pointer<Int64> p2 = calloc(2);
   p2.value = 42;
   p2[1] = 1000;
   Pointer<Int64> result = assign1337Index1(p2);
   Expect.equals(1337, result.value);
   Expect.equals(1337, p2[1]);
   Expect.equals(p2.elementAt(1).address, result.address);
-  free(p2);
+  calloc.free(p2);
 }
 
 Int64PointerUnOp nullableInt64ElemAt1 = ffiTestFunctions
@@ -411,10 +412,10 @@
   Pointer<Int64> result = nullableInt64ElemAt1(nullptr);
   Expect.equals(result, nullptr);
 
-  Pointer<Int64> p2 = allocate(count: 2);
+  Pointer<Int64> p2 = calloc(2);
   result = nullableInt64ElemAt1(p2);
   Expect.notEquals(result, nullptr);
-  free(p2);
+  calloc.free(p2);
 }
 
 typedef NativeFloatPointerToBool = Uint8 Function(Pointer<Float>);
@@ -424,13 +425,13 @@
     NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
 
 void testFloatRounding() {
-  Pointer<Float> p2 = allocate();
+  Pointer<Float> p2 = calloc();
   p2.value = 1337.0;
 
   int result = isRoughly1337(p2);
   Expect.equals(1, result);
 
-  free(p2);
+  calloc.free(p2);
 }
 
 typedef NativeFloatToVoid = Void Function(Float);
diff --git a/tests/ffi_2/generator/c_types.dart b/tests/ffi_2/generator/c_types.dart
index f2948fa..56736bf5 100644
--- a/tests/ffi_2/generator/c_types.dart
+++ b/tests/ffi_2/generator/c_types.dart
@@ -140,11 +140,19 @@
   /// To disambiguate same size structs.
   final String suffix;
 
+  /// To override names.
+  final String overrideName;
+
   StructType(List<CType> memberTypes)
       : this.members = generateMemberNames(memberTypes),
-        this.suffix = "";
+        this.suffix = "",
+        this.overrideName = "";
   StructType.disambiguate(List<CType> memberTypes, this.suffix)
-      : this.members = generateMemberNames(memberTypes);
+      : this.members = generateMemberNames(memberTypes),
+        this.overrideName = "";
+  StructType.override(List<CType> memberTypes, this.overrideName)
+      : this.members = generateMemberNames(memberTypes),
+        this.suffix = "";
 
   List<CType> get memberTypes => members.map((a) => a.type).toList();
 
@@ -191,6 +199,9 @@
 
   String get name {
     String result = "Struct";
+    if (overrideName != "") {
+      return result + overrideName;
+    }
     if (hasSize) {
       result += "${size}Byte" + (size != 1 ? "s" : "");
     }
diff --git a/tests/ffi_2/generator/structs_by_value_tests_configuration.dart b/tests/ffi_2/generator/structs_by_value_tests_configuration.dart
index 46f5108..bc1b8a1 100644
--- a/tests/ffi_2/generator/structs_by_value_tests_configuration.dart
+++ b/tests/ffi_2/generator/structs_by_value_tests_configuration.dart
@@ -255,6 +255,41 @@
       int64,
       """
 Test alignment and padding of 64 byte int within struct."""),
+  FunctionType(List.filled(10, struct8bytesNestedInt), int64, """
+Simple nested struct. No alignment gaps on any architectures.
+10 arguments exhaust registers on all platforms."""),
+  FunctionType(List.filled(10, struct8bytesNestedFloat), float, """
+Simple nested struct. No alignment gaps on any architectures.
+10 arguments exhaust fpu registers on all platforms."""),
+  FunctionType(List.filled(10, struct8bytesNestedFloat2), float, """
+Simple nested struct. No alignment gaps on any architectures.
+10 arguments exhaust fpu registers on all platforms.
+The nesting is irregular, testing homogenous float rules on arm and arm64,
+and the fpu register usage on x64."""),
+  FunctionType(List.filled(10, struct8bytesNestedMixed), double_, """
+Simple nested struct. No alignment gaps on any architectures.
+10 arguments exhaust all registers on all platforms."""),
+  FunctionType(List.filled(2, struct16bytesNestedInt), int64, """
+Deeper nested struct to test recursive member access."""),
+  FunctionType(List.filled(2, struct32bytesNestedInt), int64, """
+Even deeper nested struct to test recursive member access."""),
+  FunctionType(
+      [structNestedAlignmentInt16],
+      int64,
+      """
+Test alignment and padding of nested struct with 16 byte int."""),
+  FunctionType(
+      [structNestedAlignmentInt32],
+      int64,
+      """
+Test alignment and padding of nested struct with 32 byte int."""),
+  FunctionType(
+      [structNestedAlignmentInt64],
+      int64,
+      """
+Test alignment and padding of nested struct with 64 byte int."""),
+  FunctionType(List.filled(4, structNestedEvenBigger), double_, """
+Return big irregular struct as smoke test."""),
   FunctionType(struct1byteInt.memberTypes, struct1byteInt, """
 Smallest struct with data."""),
   FunctionType(struct3bytesInt.memberTypes, struct3bytesInt, """
@@ -358,14 +393,39 @@
 Test alignment and padding of 32 byte int within struct."""),
   FunctionType(structAlignmentInt64.memberTypes, structAlignmentInt64, """
 Test alignment and padding of 64 byte int within struct."""),
+  FunctionType(struct8bytesNestedInt.memberTypes, struct8bytesNestedInt, """
+Simple nested struct."""),
+  FunctionType(struct8bytesNestedFloat.memberTypes, struct8bytesNestedFloat, """
+Simple nested struct with floats."""),
+  FunctionType(
+      struct8bytesNestedFloat2.memberTypes, struct8bytesNestedFloat2, """
+The nesting is irregular, testing homogenous float rules on arm and arm64,
+and the fpu register usage on x64."""),
+  FunctionType(struct8bytesNestedMixed.memberTypes, struct8bytesNestedMixed, """
+Simple nested struct with mixed members."""),
+  FunctionType(struct16bytesNestedInt.memberTypes, struct16bytesNestedInt, """
+Deeper nested struct to test recursive member access."""),
+  FunctionType(struct32bytesNestedInt.memberTypes, struct32bytesNestedInt, """
+Even deeper nested struct to test recursive member access."""),
+  FunctionType(
+      structNestedAlignmentInt16.memberTypes, structNestedAlignmentInt16, """
+Test alignment and padding of nested struct with 16 byte int."""),
+  FunctionType(
+      structNestedAlignmentInt32.memberTypes, structNestedAlignmentInt32, """
+Test alignment and padding of nested struct with 32 byte int."""),
+  FunctionType(
+      structNestedAlignmentInt64.memberTypes, structNestedAlignmentInt64, """
+Test alignment and padding of nested struct with 64 byte int."""),
+  FunctionType(structNestedEvenBigger.memberTypes, structNestedEvenBigger, """
+Return big irregular struct as smoke test."""),
 ];
 
 final structs = [
-  struct0bytes,
   struct1byteInt,
   struct3bytesInt,
   struct3bytesInt2,
   struct4bytesInt,
+  struct4bytesFloat,
   struct7bytesInt,
   struct7bytesInt2,
   struct8bytesInt,
@@ -387,15 +447,25 @@
   structAlignmentInt16,
   structAlignmentInt32,
   structAlignmentInt64,
+  struct8bytesNestedInt,
+  struct8bytesNestedFloat,
+  struct8bytesNestedFloat2,
+  struct8bytesNestedMixed,
+  struct16bytesNestedInt,
+  struct32bytesNestedInt,
+  structNestedAlignmentInt16,
+  structNestedAlignmentInt32,
+  structNestedAlignmentInt64,
+  structNestedBig,
+  structNestedBigger,
+  structNestedEvenBigger,
 ];
 
-/// Using empty structs is undefined behavior in C.
-final struct0bytes = StructType([]);
-
 final struct1byteInt = StructType([int8]);
 final struct3bytesInt = StructType(List.filled(3, uint8));
 final struct3bytesInt2 = StructType.disambiguate([int16, int8], "2ByteAligned");
 final struct4bytesInt = StructType([int16, int16]);
+final struct4bytesFloat = StructType([float]);
 final struct7bytesInt = StructType(List.filled(7, uint8));
 final struct7bytesInt2 =
     StructType.disambiguate([int32, int16, int8], "4ByteAligned");
@@ -444,3 +514,39 @@
 final structAlignmentInt16 = StructType([int8, int16, int8]);
 final structAlignmentInt32 = StructType([int8, int32, int8]);
 final structAlignmentInt64 = StructType([int8, int64, int8]);
+
+final struct8bytesNestedInt = StructType([struct4bytesInt, struct4bytesInt]);
+final struct8bytesNestedFloat =
+    StructType([struct4bytesFloat, struct4bytesFloat]);
+final struct8bytesNestedFloat2 =
+    StructType.disambiguate([struct4bytesFloat, float], "2");
+final struct8bytesNestedMixed =
+    StructType([struct4bytesInt, struct4bytesFloat]);
+
+final struct16bytesNestedInt =
+    StructType([struct8bytesNestedInt, struct8bytesNestedInt]);
+final struct32bytesNestedInt =
+    StructType([struct16bytesNestedInt, struct16bytesNestedInt]);
+
+final structNestedAlignmentInt16 = StructType.disambiguate(
+    List.filled(2, structAlignmentInt16), structAlignmentInt16.name);
+final structNestedAlignmentInt32 = StructType.disambiguate(
+    List.filled(2, structAlignmentInt32), structAlignmentInt32.name);
+final structNestedAlignmentInt64 = StructType.disambiguate(
+    List.filled(2, structAlignmentInt64), structAlignmentInt64.name);
+
+final structNestedBig = StructType.override([
+  uint16,
+  struct8bytesNestedMixed,
+  uint16,
+  struct8bytesNestedFloat2,
+  uint16,
+  struct8bytesNestedFloat,
+  uint16
+], "NestedIrregularBig");
+final structNestedBigger = StructType.override(
+    [structNestedBig, struct8bytesNestedMixed, float, double_],
+    "NestedIrregularBigger");
+final structNestedEvenBigger = StructType.override(
+    [uint64, structNestedBigger, structNestedBigger, double_],
+    "NestedIrregularEvenBigger");
diff --git a/tests/ffi_2/generator/structs_by_value_tests_generator.dart b/tests/ffi_2/generator/structs_by_value_tests_generator.dart
index f3f9f02..7bd7c83 100644
--- a/tests/ffi_2/generator/structs_by_value_tests_generator.dart
+++ b/tests/ffi_2/generator/structs_by_value_tests_generator.dart
@@ -197,7 +197,7 @@
         return "${dartType} ${variableName};\n";
 
       case StructType:
-        return "${dartType} ${variableName} = allocate<$dartType>().ref;\n";
+        return "${dartType} ${variableName} = calloc<$dartType>().ref;\n";
     }
 
     throw Exception("Not implemented for ${this.runtimeType}");
@@ -243,7 +243,7 @@
         return "";
 
       case StructType:
-        return "free($variableName.addressOf);\n";
+        return "calloc.free($variableName.addressOf);\n";
     }
 
     throw Exception("Not implemented for ${this.runtimeType}");
@@ -485,7 +485,7 @@
       case TestType.structReturn:
         // Allocate a struct.
         buildReturnValue = """
-        ${returnValue.dartType} result = allocate<${returnValue.dartType}>().ref;
+        ${returnValue.dartType} result = calloc<${returnValue.dartType}>().ref;
 
         ${arguments.copyValueStatements("${dartName}_", "result.")}
         """;
@@ -749,6 +749,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
@@ -801,6 +802,7 @@
 import "package:ffi/ffi.dart";
 
 import 'callback_tests_utils.dart';
+import 'calloc.dart';
 
 // Reuse the struct classes.
 import 'function_structs_by_value_generated_test.dart';
diff --git a/tests/ffi_2/null_test.dart b/tests/ffi_2/null_test.dart
index 303499c..fb51f94 100644
--- a/tests/ffi_2/null_test.dart
+++ b/tests/ffi_2/null_test.dart
@@ -20,6 +20,7 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 import 'ffi_test_helpers.dart';
 
@@ -40,17 +41,17 @@
 
 void testPointerStoreNull() {
   int i = null;
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   Expect.throws(() => p.value = i);
-  free(p);
+  calloc.free(p);
   double d = null;
-  Pointer<Float> p2 = allocate();
+  Pointer<Float> p2 = calloc();
   Expect.throws(() => p2.value = d);
-  free(p2);
+  calloc.free(p2);
   Pointer<Void> x = null;
-  Pointer<Pointer<Void>> p3 = allocate();
+  Pointer<Pointer<Void>> p3 = calloc();
   Expect.throws(() => p3.value = x);
-  free(p3);
+  calloc.free(p3);
 }
 
 void testEquality() {
@@ -61,7 +62,7 @@
 
 /// With extension methods, the receiver position can be null.
 testNullReceivers() {
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
 
   Pointer<Int8> p4 = null;
   Expect.throws(() => Expect.equals(10, p4.value));
@@ -74,11 +75,11 @@
   Pointer<Foo> p6 = null;
   Expect.throws(() => Expect.equals(10, p6.ref));
 
-  free(p);
+  calloc.free(p);
 }
 
 testNullIndices() {
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
 
   Expect.throws(() => Expect.equals(10, p[null]));
   Expect.throws(() => p[null] = 10);
@@ -90,13 +91,13 @@
   Pointer<Foo> p6 = p.cast();
   Expect.throws(() => Expect.equals(10, p6[null]));
 
-  free(p);
+  calloc.free(p);
 }
 
 testNullArguments() {
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   Expect.throws(() => p.value = null);
-  free(p);
+  calloc.free(p);
 }
 
 class Foo extends Struct {
diff --git a/tests/ffi_2/regress_37254_test.dart b/tests/ffi_2/regress_37254_test.dart
index 6ba796f..e73562d 100644
--- a/tests/ffi_2/regress_37254_test.dart
+++ b/tests/ffi_2/regress_37254_test.dart
@@ -65,34 +65,36 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
+
 // ===== a.value = b ======
 // The tests follow table cells left to right, top to bottom.
 void store1() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
-  final Pointer<Int8> b = allocate<Int8>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
+  final Pointer<Int8> b = calloc<Int8>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store2() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
   final Pointer<NativeType> b =
-      allocate<Int8>(); // Reified Pointer<Int8> at runtime.
+      calloc<Int8>(); // Reified Pointer<Int8> at runtime.
 
   // Successful implicit downcast of argument at runtime.
   // Should succeed now, should statically be rejected when NNBD lands.
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store3() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
-  final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
+  final Pointer<NativeType> b = calloc<Int8>().cast<Pointer<NativeType>>();
 
   // Failing implicit downcast of argument at runtime.
   // Should fail now at runtime, should statically be rejected when NNBD lands.
@@ -100,124 +102,124 @@
     a.value = b;
   });
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store4() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
 
-  final Pointer<Int8> b = allocate<Int8>();
+  final Pointer<Int8> b = calloc<Int8>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store5() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
 
   final Pointer<NativeType> b =
-      allocate<Int8>(); // Reified as Pointer<Int8> at runtime.
+      calloc<Int8>(); // Reified as Pointer<Int8> at runtime.
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store6() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
-  final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
+  final Pointer<NativeType> b = calloc<Int8>().cast<Pointer<NativeType>>();
 
   // Fails on type check of argument.
   Expect.throws(() {
     a.value = b;
   });
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store7() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
-  final Pointer<Int8> b = allocate<Int8>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
+  final Pointer<Int8> b = calloc<Int8>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store8() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
 
   // Reified as Pointer<Int8> at runtime.
-  final Pointer<NativeType> b = allocate<Int8>();
+  final Pointer<NativeType> b = calloc<Int8>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 void store9() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
-  final Pointer<NativeType> b = allocate<Int8>().cast<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
+  final Pointer<NativeType> b = calloc<Int8>().cast<Pointer<NativeType>>();
 
   a.value = b;
 
-  free(a);
-  free(b);
+  calloc.free(a);
+  calloc.free(b);
 }
 
 // ====== b = a.value ======
 // The tests follow table cells left to right, top to bottom.
 void load1() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
 
   Pointer<Int8> b = a.value;
   Expect.type<Pointer<Int8>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void load2() {
-  final Pointer<Pointer<Int8>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<Int8>> a = calloc<Pointer<Int8>>();
 
   Pointer<NativeType> b = a.value;
   Expect.type<Pointer<Int8>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void load3() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
 
   Pointer<Int8> b = a.value;
   Expect.type<Pointer<Int8>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void load4() {
   // Reified as Pointer<Pointer<Int8>> at runtime.
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<Int8>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<Int8>>();
 
   // Return value runtime type is Pointer<Int8>.
   Pointer<NativeType> b = a.value;
   Expect.type<Pointer<Int8>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void load5() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
 
   // Failing implicit downcast of return value at runtime.
   // Should fail now at runtime, should statically be rejected when NNBD lands.
@@ -225,16 +227,16 @@
     Pointer<Int8> b = a.value;
   });
 
-  free(a);
+  calloc.free(a);
 }
 
 void load6() {
-  final Pointer<Pointer<NativeType>> a = allocate<Pointer<NativeType>>();
+  final Pointer<Pointer<NativeType>> a = calloc<Pointer<NativeType>>();
 
   Pointer<NativeType> b = a.value;
   Expect.type<Pointer<NativeType>>(b);
 
-  free(a);
+  calloc.free(a);
 }
 
 void main() {
diff --git a/tests/ffi_2/regress_39885_test.dart b/tests/ffi_2/regress_39885_test.dart
index 7d960f2..ef73ca7 100644
--- a/tests/ffi_2/regress_39885_test.dart
+++ b/tests/ffi_2/regress_39885_test.dart
@@ -3,12 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:ffi';
-import "package:ffi/ffi.dart" show allocate, free;
+
+import "package:ffi/ffi.dart";
+
+import 'calloc.dart';
 
 main() {
-  final data = allocate<Uint8>(count: 3);
+  final data = calloc<Uint8>(3);
   for (int i = 0; i < 3; ++i) {
     data.elementAt(i).value = 1;
   }
-  free(data);
+  calloc.free(data);
 }
diff --git a/tests/ffi_2/regress_43016_test.dart b/tests/ffi_2/regress_43016_test.dart
index b0ebc0c..997e451 100644
--- a/tests/ffi_2/regress_43016_test.dart
+++ b/tests/ffi_2/regress_43016_test.dart
@@ -10,7 +10,10 @@
 
 import 'dylib_utils.dart';
 
-class MyStruct extends Struct {}
+class MyStruct extends Struct {
+  @Int8()
+  int a;
+}
 
 typedef _c_pass_struct = Int32 Function(Pointer<MyStruct> arg0);
 
diff --git a/tests/ffi_2/regress_43693_test.dart b/tests/ffi_2/regress_43693_test.dart
index a30a118..b589b0c 100644
--- a/tests/ffi_2/regress_43693_test.dart
+++ b/tests/ffi_2/regress_43693_test.dart
@@ -9,6 +9,7 @@
 import 'package:ffi/ffi.dart';
 import 'package:expect/expect.dart';
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 class Struct43693 extends Struct {
@@ -27,10 +28,10 @@
 final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
 
 void main() {
-  final myStructs = allocate<Struct43693>();
+  final myStructs = calloc<Struct43693>();
   myStructs[0].somePtr = nullptr;
   myStructs[0].someValue = 0xAAAAAAAABBBBBBBB;
   final result = readMyStructSomeValue(myStructs);
   Expect.equals(0xAAAAAAAABBBBBBBB, result);
-  free(myStructs);
+  calloc.free(myStructs);
 }
diff --git a/tests/ffi_2/structs_nested_test.dart b/tests/ffi_2/structs_nested_test.dart
new file mode 100644
index 0000000..3a69edb
--- /dev/null
+++ b/tests/ffi_2/structs_nested_test.dart
@@ -0,0 +1,106 @@
+// 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.
+//
+// This tests the non trampoline aspects of nested structs.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'calloc.dart';
+import 'dylib_utils.dart';
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+void main() {
+  for (int i = 0; i < 10; ++i) {
+    testSizeOf();
+    testAllocate();
+    testRead();
+    testWrite();
+    testCopy();
+  }
+}
+
+class Struct4BytesHomogeneousInt16 extends Struct {
+  @Int16()
+  int a0;
+
+  @Int16()
+  int a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+class Struct8BytesNestedInt extends Struct {
+  Struct4BytesHomogeneousInt16 a0;
+
+  Struct4BytesHomogeneousInt16 a1;
+
+  String toString() => "(${a0}, ${a1})";
+}
+
+void testSizeOf() {
+  print(sizeOf<Struct8BytesNestedInt>());
+  Expect.equals(8, sizeOf<Struct8BytesNestedInt>());
+}
+
+void testAllocate() {
+  final p = calloc<Struct8BytesNestedInt>();
+  Expect.type<Pointer<Struct8BytesNestedInt>>(p);
+  print(p);
+  calloc.free(p);
+}
+
+/// Test that reading does not segfault, even uninitialized.
+void testRead() {
+  print("read");
+  final p = calloc<Struct8BytesNestedInt>();
+  print(p);
+  print(p.ref.runtimeType);
+  print(p.ref.addressOf);
+  print(p.ref.addressOf.address);
+  print(p.ref.a0.runtimeType);
+  print(p.ref.a0.addressOf);
+  print(p.ref.a0.a0);
+  calloc.free(p);
+  print("read");
+}
+
+void testWrite() {
+  print("write");
+  final p = calloc<Struct8BytesNestedInt>(2);
+  p[0].a0.a0 = 12;
+  p[0].a0.a1 = 13;
+  p[0].a1.a0 = 14;
+  p[0].a1.a1 = 15;
+  p[1].a0.a0 = 16;
+  p[1].a0.a1 = 17;
+  p[1].a1.a0 = 18;
+  p[1].a1.a1 = 19;
+  Expect.equals(12, p[0].a0.a0);
+  Expect.equals(13, p[0].a0.a1);
+  Expect.equals(14, p[0].a1.a0);
+  Expect.equals(15, p[0].a1.a1);
+  Expect.equals(16, p[1].a0.a0);
+  Expect.equals(17, p[1].a0.a1);
+  Expect.equals(18, p[1].a1.a0);
+  Expect.equals(19, p[1].a1.a1);
+  calloc.free(p);
+  print("written");
+}
+
+void testCopy() {
+  print("copy");
+  final p = calloc<Struct8BytesNestedInt>();
+  p.ref.a0.a0 = 12;
+  p.ref.a0.a1 = 13;
+  p.ref.a1 = p.ref.a0;
+  Expect.equals(12, p.ref.a1.a0);
+  Expect.equals(13, p.ref.a1.a1);
+  calloc.free(p);
+  print("copied");
+}
diff --git a/tests/ffi_2/structs_test.dart b/tests/ffi_2/structs_test.dart
index 263d562..2759056 100644
--- a/tests/ffi_2/structs_test.dart
+++ b/tests/ffi_2/structs_test.dart
@@ -11,9 +11,10 @@
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
-import 'ffi_test_helpers.dart';
+import 'calloc.dart';
 import 'coordinate_bare.dart' as bare;
 import 'coordinate.dart';
+import 'ffi_test_helpers.dart';
 
 void main() {
   for (int i = 0; i < 100; i++) {
@@ -28,9 +29,12 @@
 
 /// allocates each coordinate separately in c memory
 void testStructAllocate() {
-  Pointer<Coordinate> c1 = Coordinate.allocate(10.0, 10.0, nullptr).addressOf;
-  Pointer<Coordinate> c2 = Coordinate.allocate(20.0, 20.0, c1).addressOf;
-  Pointer<Coordinate> c3 = Coordinate.allocate(30.0, 30.0, c2).addressOf;
+  Pointer<Coordinate> c1 =
+      Coordinate.allocate(calloc, 10.0, 10.0, nullptr).addressOf;
+  Pointer<Coordinate> c2 =
+      Coordinate.allocate(calloc, 20.0, 20.0, c1).addressOf;
+  Pointer<Coordinate> c3 =
+      Coordinate.allocate(calloc, 30.0, 30.0, c2).addressOf;
   c1.ref.next = c3;
 
   Coordinate currentCoordinate = c1.ref;
@@ -42,14 +46,14 @@
   currentCoordinate = currentCoordinate.next.ref;
   Expect.equals(10.0, currentCoordinate.x);
 
-  free(c1);
-  free(c2);
-  free(c3);
+  calloc.free(c1);
+  calloc.free(c2);
+  calloc.free(c3);
 }
 
 /// allocates coordinates consecutively in c memory
 void testStructFromAddress() {
-  Pointer<Coordinate> c1 = allocate(count: 3);
+  Pointer<Coordinate> c1 = calloc(3);
   Pointer<Coordinate> c2 = c1.elementAt(1);
   Pointer<Coordinate> c3 = c1.elementAt(2);
   c1.ref
@@ -74,24 +78,24 @@
   currentCoordinate = currentCoordinate.next.ref;
   Expect.equals(10.0, currentCoordinate.x);
 
-  free(c1);
+  calloc.free(c1);
 }
 
 void testStructWithNulls() {
   Pointer<Coordinate> coordinate =
-      Coordinate.allocate(10.0, 10.0, nullptr).addressOf;
+      Coordinate.allocate(calloc, 10.0, 10.0, nullptr).addressOf;
   Expect.equals(coordinate.ref.next, nullptr);
   coordinate.ref.next = coordinate;
   Expect.notEquals(coordinate.ref.next, nullptr);
   coordinate.ref.next = nullptr;
   Expect.equals(coordinate.ref.next, nullptr);
-  free(coordinate);
+  calloc.free(coordinate);
 }
 
 void testBareStruct() {
   int structSize = sizeOf<Double>() * 2 + sizeOf<IntPtr>();
   bare.Coordinate c1 =
-      allocate<Uint8>(count: structSize * 3).cast<bare.Coordinate>().ref;
+      calloc<Uint8>(structSize * 3).cast<bare.Coordinate>().ref;
   bare.Coordinate c2 =
       c1.addressOf.offsetBy(structSize).cast<bare.Coordinate>().ref;
   bare.Coordinate c3 =
@@ -115,19 +119,19 @@
   currentCoordinate = currentCoordinate.next.ref;
   Expect.equals(10.0, currentCoordinate.x);
 
-  free(c1.addressOf);
+  calloc.free(c1.addressOf);
 }
 
 void testTypeTest() {
-  Coordinate c = Coordinate.allocate(10, 10, nullptr);
+  Coordinate c = Coordinate.allocate(calloc, 10, 10, nullptr);
   Expect.isTrue(c is Struct);
   Expect.isTrue(c.addressOf is Pointer<Coordinate>);
-  free(c.addressOf);
+  calloc.free(c.addressOf);
 }
 
 void testUtf8() {
   final String test = 'Hasta Mañana';
   final Pointer<Utf8> medium = Utf8.toUtf8(test);
   Expect.equals(test, Utf8.fromUtf8(medium));
-  free(medium);
+  calloc.free(medium);
 }
diff --git a/tests/ffi_2/variance_function_test.dart b/tests/ffi_2/variance_function_test.dart
index d6e6378..f53cdfc 100644
--- a/tests/ffi_2/variance_function_test.dart
+++ b/tests/ffi_2/variance_function_test.dart
@@ -12,11 +12,12 @@
 
 import 'dart:ffi';
 
-import 'dylib_utils.dart';
-
 import "package:expect/expect.dart";
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
+import 'dylib_utils.dart';
+
 typedef Int64PointerParamOpDart = void Function(Pointer<Int64>);
 typedef Int64PointerParamOp = Void Function(Pointer<Int64>);
 typedef NaTyPointerParamOpDart = void Function(Pointer<NativeType>);
@@ -38,19 +39,19 @@
   final fp =
       ffiTestFunctions.lookup<NativeFunction<Int64PointerParamOp>>(paramOpName);
   final f = fp.asFunction<Int64PointerParamOpDart>();
-  final arg = allocate<Int64>();
+  final arg = calloc<Int64>();
   f(arg);
-  free(arg);
+  calloc.free(arg);
 }
 
 void paramInvariant2() {
   final fp =
       ffiTestFunctions.lookup<NativeFunction<NaTyPointerParamOp>>(paramOpName);
   final f = fp.asFunction<NaTyPointerParamOpDart>();
-  final arg = allocate<Int64>().cast<NativeType>();
+  final arg = calloc<Int64>().cast<NativeType>();
   Expect.type<Pointer<NativeType>>(arg);
   f(arg);
-  free(arg);
+  calloc.free(arg);
 }
 
 // Pass a statically and dynamically subtyped argument.
@@ -58,10 +59,10 @@
   final fp =
       ffiTestFunctions.lookup<NativeFunction<NaTyPointerParamOp>>(paramOpName);
   final f = fp.asFunction<NaTyPointerParamOpDart>();
-  final arg = allocate<Int64>();
+  final arg = calloc<Int64>();
   Expect.type<Pointer<Int64>>(arg);
   f(arg);
-  free(arg);
+  calloc.free(arg);
 }
 
 // Pass a statically subtyped but dynamically invariant argument.
@@ -69,10 +70,10 @@
   final fp =
       ffiTestFunctions.lookup<NativeFunction<NaTyPointerParamOp>>(paramOpName);
   final f = fp.asFunction<NaTyPointerParamOpDart>();
-  final Pointer<NativeType> arg = allocate<Int64>();
+  final Pointer<NativeType> arg = calloc<Int64>();
   Expect.type<Pointer<Int64>>(arg);
   f(arg);
-  free(arg);
+  calloc.free(arg);
 }
 
 void returnInvariant1() {
@@ -220,7 +221,7 @@
 }
 
 void fromFunctionTests() {
-  data = allocate();
+  data = calloc();
   for (int i = 0; i < 100; ++i) {
     callbackParamInvariant1(); // Pointer<Int64> invariant
     callbackParamInvariant2(); // Pointer<NativeType> invariant
@@ -229,7 +230,7 @@
     callbackReturnInvariant1(); // Pointer<Int64> invariant
     callbackReturnInvariant2(); // Pointer<NativeType> invariant
   }
-  free(data);
+  calloc.free(data);
 }
 
 void main() {
diff --git a/tests/ffi_2/vmspecific_enable_ffi_test.dart b/tests/ffi_2/vmspecific_enable_ffi_test.dart
index f44753d..ce90607 100644
--- a/tests/ffi_2/vmspecific_enable_ffi_test.dart
+++ b/tests/ffi_2/vmspecific_enable_ffi_test.dart
@@ -7,11 +7,14 @@
 // VMOptions=--enable-ffi=false
 
 import 'dart:ffi'; //# 01: compile-time error
+
 import 'package:ffi/ffi.dart'; //# 01: compile-time error
 
+import 'calloc.dart'; //# 01: compile-time error
+
 void main() {
   Pointer<Int8> p = //# 01: compile-time error
-      allocate(); //# 01: compile-time error
+      calloc(); //# 01: compile-time error
   print(p.address); //# 01: compile-time error
-  free(p); //# 01: compile-time error
+  calloc.free(p); //# 01: compile-time error
 }
diff --git a/tests/ffi_2/vmspecific_regress_37100_test.dart b/tests/ffi_2/vmspecific_regress_37100_test.dart
index a819503..ef4c614 100644
--- a/tests/ffi_2/vmspecific_regress_37100_test.dart
+++ b/tests/ffi_2/vmspecific_regress_37100_test.dart
@@ -10,7 +10,7 @@
 
 import 'dylib_utils.dart';
 
-class EVP_MD extends Struct {}
+class EVP_MD extends Opaque {}
 
 DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
 
diff --git a/tests/ffi_2/vmspecific_regress_38993_test.dart b/tests/ffi_2/vmspecific_regress_38993_test.dart
index 8c9972f..e7c4315 100644
--- a/tests/ffi_2/vmspecific_regress_38993_test.dart
+++ b/tests/ffi_2/vmspecific_regress_38993_test.dart
@@ -8,6 +8,8 @@
 
 class C extends Struct {
   dynamic x; //# 1: compile-time error
+
+  Pointer notEmpty;
 }
 
 main() {}
diff --git a/tests/ffi_2/vmspecific_static_checks_test.dart b/tests/ffi_2/vmspecific_static_checks_test.dart
index 5645c2a..369a8de 100644
--- a/tests/ffi_2/vmspecific_static_checks_test.dart
+++ b/tests/ffi_2/vmspecific_static_checks_test.dart
@@ -10,6 +10,7 @@
 
 import "package:ffi/ffi.dart";
 
+import 'calloc.dart';
 import 'dylib_utils.dart';
 
 void main() {
@@ -40,11 +41,26 @@
   testLookupFunctionGeneric2();
   testLookupFunctionWrongNativeFunctionSignature();
   testLookupFunctionTypeMismatch();
+  testLookupFunctionPointervoid();
+  testLookupFunctionPointerNFdyn();
   testNativeFunctionSignatureInvalidReturn();
   testNativeFunctionSignatureInvalidParam();
   testNativeFunctionSignatureInvalidOptionalNamed();
   testNativeFunctionSignatureInvalidOptionalPositional();
   testHandleVariance();
+  testEmptyStructLookupFunctionArgument();
+  testEmptyStructLookupFunctionReturn();
+  testEmptyStructAsFunctionArgument();
+  testEmptyStructAsFunctionReturn();
+  testEmptyStructFromFunctionArgument();
+  testEmptyStructFromFunctionReturn();
+  testAllocateGeneric();
+  testAllocateNativeType();
+  testRefStruct();
+  testSizeOfGeneric();
+  testSizeOfNativeType();
+  testElementAtGeneric();
+  testElementAtNativeType();
 }
 
 typedef Int8UnOp = Int8 Function(Int8);
@@ -57,20 +73,20 @@
     return result;
   }
 
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   p.value = 123;
   Pointer loseType = p;
   generic(loseType);
-  free(p);
+  calloc.free(p);
 }
 
 void testGetGeneric2() {
   T generic<T extends Object>() {
-    Pointer<Int8> p = allocate();
+    Pointer<Int8> p = calloc();
     p.value = 123;
     T result;
     result = p.value; //# 21: compile-time error
-    free(p);
+    calloc.free(p);
     return result;
   }
 
@@ -78,12 +94,12 @@
 }
 
 void testGetVoid() {
-  Pointer<IntPtr> p1 = allocate();
+  Pointer<IntPtr> p1 = calloc();
   Pointer<Void> p2 = p1.cast();
 
   p2.value; //# 22: compile-time error
 
-  free(p1);
+  calloc.free(p1);
 }
 
 void testGetNativeFunction() {
@@ -96,14 +112,14 @@
 }
 
 void testGetTypeMismatch() {
-  Pointer<Pointer<Int16>> p = allocate();
+  Pointer<Pointer<Int16>> p = calloc();
   Pointer<Int16> typedNull = nullptr;
   p.value = typedNull;
 
   // this fails to compile due to type mismatch
   Pointer<Int8> p2 = p.value; //# 25: compile-time error
 
-  free(p);
+  calloc.free(p);
 }
 
 void testSetGeneric() {
@@ -111,30 +127,30 @@
     p.value = 123; //# 26: compile-time error
   }
 
-  Pointer<Int8> p = allocate();
+  Pointer<Int8> p = calloc();
   p.value = 123;
   Pointer loseType = p;
   generic(loseType);
-  free(p);
+  calloc.free(p);
 }
 
 void testSetGeneric2() {
   void generic<T extends Object>(T arg) {
-    Pointer<Int8> p = allocate();
+    Pointer<Int8> p = calloc();
     p.value = arg; //# 27: compile-time error
-    free(p);
+    calloc.free(p);
   }
 
   generic<int>(123);
 }
 
 void testSetVoid() {
-  Pointer<IntPtr> p1 = allocate();
+  Pointer<IntPtr> p1 = calloc();
   Pointer<Void> p2 = p1.cast();
 
   p2.value = 1234; //# 28: compile-time error
 
-  free(p1);
+  calloc.free(p1);
 }
 
 void testSetNativeFunction() {
@@ -149,16 +165,16 @@
 
 void testSetTypeMismatch() {
   // the pointer to pointer types must match up
-  Pointer<Int8> pHelper = allocate();
+  Pointer<Int8> pHelper = calloc();
   pHelper.value = 123;
 
-  Pointer<Pointer<Int16>> p = allocate();
+  Pointer<Pointer<Int16>> p = calloc();
 
   // this fails to compile due to type mismatch
   p.value = pHelper; //# 40: compile-time error
 
-  free(pHelper);
-  free(p);
+  calloc.free(pHelper);
+  calloc.free(p);
 }
 
 void testAsFunctionGeneric() {
@@ -285,6 +301,24 @@
   l.lookupFunction<NativeDoubleUnOp, IntUnOp>("cos"); //# 18: compile-time error
 }
 
+typedef PointervoidN = Void Function(Pointer<void>);
+typedef PointervoidD = void Function(Pointer<void>);
+
+void testLookupFunctionPointervoid() {
+  DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
+  // TODO(https://dartbug.com/44593): This should be a compile-time error in CFE.
+  // l.lookupFunction<PointervoidN, PointervoidD>("cos");
+}
+
+typedef PointerNFdynN = Void Function(Pointer<NativeFunction>);
+typedef PointerNFdynD = void Function(Pointer<NativeFunction>);
+
+void testLookupFunctionPointerNFdyn() {
+  DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
+  // TODO(https://dartbug.com/44594): Should this be an error or not?
+  // l.lookupFunction<PointerNFdynN, PointerNFdynD>("cos");
+}
+
 // TODO(dacoharkes): make the next 4 test compile errors
 typedef Invalid1 = int Function(Int8);
 typedef Invalid2 = Int8 Function(int);
@@ -329,24 +363,32 @@
 class TestStruct5 extends Struct {
   @Int64() //# 54: compile-time error
   double z; //# 54: compile-time error
+
+  Pointer notEmpty;
 }
 
 // error on annotation not matching up
 class TestStruct6 extends Struct {
   @Void() //# 55: compile-time error
   double z; //# 55: compile-time error
+
+  Pointer notEmpty;
 }
 
 // error on annotation not matching up
 class TestStruct7 extends Struct {
   @NativeType() //# 56: compile-time error
   double z; //# 56: compile-time error
+
+  Pointer notEmpty;
 }
 
 // error on field initializer on field
 class TestStruct8 extends Struct {
   @Double() //# 57: compile-time error
   double z = 10.0; //# 57: compile-time error
+
+  Pointer notEmpty;
 }
 
 // error on field initializer in constructor
@@ -366,6 +408,8 @@
 class TestStruct12 extends Struct {
   @Pointer //# 61: compile-time error
   TestStruct9 struct; //# 61: compile-time error
+
+  Pointer notEmpty;
 }
 
 class DummyAnnotation {
@@ -449,6 +493,8 @@
 
 class IStruct implements Struct {} //# 815: compile-time error
 
+class IOpaque implements Opaque {} //# 816: compile-time error
+
 class MyClass {
   int x;
   MyClass(this.x);
@@ -470,9 +516,146 @@
 
 class TestStruct1001 extends Struct {
   Handle handle; //# 1001: compile-time error
+
+  Pointer notEmpty;
 }
 
 class TestStruct1002 extends Struct {
   @Handle() //# 1002: compile-time error
   Object handle; //# 1002: compile-time error
+
+  Pointer notEmpty;
+}
+
+class EmptyStruct extends Struct {} //# 1099: ok
+
+class EmptyStruct extends Struct {} //# 1100: compile-time error
+
+void testEmptyStructLookupFunctionArgument() {
+  testLibrary.lookupFunction< //# 1100: compile-time error
+      Void Function(EmptyStruct), //# 1100: compile-time error
+      void Function(EmptyStruct)>("DoesNotExist"); //# 1100: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1101: compile-time error
+
+void testEmptyStructLookupFunctionReturn() {
+  testLibrary.lookupFunction< //# 1101: compile-time error
+      EmptyStruct Function(), //# 1101: compile-time error
+      EmptyStruct Function()>("DoesNotExist"); //# 1101: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1102: compile-time error
+
+void testEmptyStructAsFunctionArgument() {
+  final Pointer< //# 1102: compile-time error
+          NativeFunction< //# 1102: compile-time error
+              Void Function(EmptyStruct)>> //# 1102: compile-time error
+      pointer = Pointer.fromAddress(1234); //# 1102: compile-time error
+  pointer.asFunction<void Function(EmptyStruct)>(); //# 1102: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1103: compile-time error
+
+void testEmptyStructAsFunctionReturn() {
+  final Pointer< //# 1103: compile-time error
+          NativeFunction<EmptyStruct Function()>> //# 1103: compile-time error
+      pointer = Pointer.fromAddress(1234); //# 1103: compile-time error
+  pointer.asFunction<EmptyStruct Function()>(); //# 1103: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1104: compile-time error
+
+void _consumeEmptyStruct(EmptyStruct e) => //# 1104: compile-time error
+    print(e); //# 1104: compile-time error
+
+void testEmptyStructFromFunctionArgument() {
+  Pointer.fromFunction<Void Function(EmptyStruct)>(//# 1104: compile-time error
+      _consumeEmptyStruct); //# 1104: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1105: compile-time error
+
+EmptyStruct _returnEmptyStruct() => EmptyStruct(); //# 1105: compile-time error
+
+void testEmptyStructFromFunctionReturn() {
+  Pointer.fromFunction<EmptyStruct Function()>(//# 1105: compile-time error
+      _returnEmptyStruct); //# 1105: compile-time error
+}
+
+class EmptyStruct extends Struct {} //# 1106: compile-time error
+
+class HasNestedEmptyStruct extends Struct {
+  EmptyStruct nestedEmptyStruct; //# 1106: compile-time error
+
+  Pointer notEmpty;
+}
+
+void testAllocateGeneric() {
+  Pointer<T> generic<T extends NativeType>() {
+    Pointer<T> pointer = nullptr;
+    pointer = calloc(); //# 1320: compile-time error
+    return pointer;
+  }
+
+  Pointer p = generic<Int64>();
+}
+
+void testAllocateNativeType() {
+  calloc(); //# 1321: compile-time error
+}
+
+void testRefStruct() {
+  final myStructPointer = calloc<TestStruct13>();
+  Pointer<Struct> structPointer = myStructPointer;
+  structPointer.ref; //# 1330: ok
+  calloc.free(myStructPointer);
+}
+
+T genericRef<T extends Struct>(Pointer<T> p) => //# 1200: ok
+    p.ref; //# 1200: ok
+
+T genericRef2<T extends Struct>(Pointer<T> p) => //# 1201: ok
+    p.cast<T>().ref; //# 1201: ok
+
+T genericRef3<T extends Struct>(Pointer<T> p) => //# 1202: ok
+    p[0]; //# 1202: ok
+
+void testSizeOfGeneric() {
+  int generic<T extends Pointer>() {
+    int size = sizeOf<IntPtr>();
+    size = sizeOf<T>(); //# 1300: ok
+    return size;
+  }
+
+  int size = generic<Pointer<Int64>>();
+}
+
+void testSizeOfNativeType() {
+  try {
+    sizeOf(); //# 1301: ok
+  } catch (e) {
+    print(e);
+  }
+}
+
+void testElementAtGeneric() {
+  Pointer<T> generic<T extends NativeType>(Pointer<T> pointer) {
+    Pointer<T> returnValue = pointer;
+    returnValue = returnValue.elementAt(1); //# 1310: ok
+    return returnValue;
+  }
+
+  Pointer<Int8> p = calloc();
+  p.elementAt(1);
+  generic(p);
+  calloc.free(p);
+}
+
+void testElementAtNativeType() {
+  Pointer<Int8> p = calloc();
+  p.elementAt(1);
+  Pointer<NativeType> p2 = p;
+  p2.elementAt(1); //# 1311: ok
+  calloc.free(p);
 }
diff --git a/tests/language/async/explicit_await_test.dart b/tests/language/async/explicit_await_test.dart
new file mode 100644
index 0000000..545e5c5
--- /dev/null
+++ b/tests/language/async/explicit_await_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.
+
+import 'package:expect/expect.dart';
+
+bool caughtInMethod1 = false;
+bool caughtInMethod2 = false;
+bool caughtInMain = false;
+
+Future<Object> f() {
+  return new Future<Future<Object>>.value(new Future<Object>.delayed(
+      const Duration(seconds: 1), () => throw 'foo'));
+}
+
+Future<Object> method1() async {
+  try {
+    return await f();
+  } catch (e) {
+    print('caught in method1: $e');
+    caughtInMethod1 = true;
+  }
+  return new Object();
+}
+
+Future<Object> method2() async {
+  try {
+    return method1();
+  } catch (e) {
+    print('caught in method2: $e');
+    caughtInMethod2 = true;
+  }
+  return new Object();
+}
+
+void main() async {
+  try {
+    print(await method2());
+    print('Done');
+  } catch (e) {
+    print('caught in main: $e');
+    caughtInMain = true;
+  }
+  Expect.isTrue(caughtInMethod1, "Exception should be caught in 'method1'.");
+  Expect.isFalse(
+      caughtInMethod2, "Exception should not be caught in 'method2'.");
+  Expect.isFalse(caughtInMain, "Exception should not be caught in 'main'.");
+}
diff --git a/tests/language/async/implicit_await_test.dart b/tests/language/async/implicit_await_test.dart
new file mode 100644
index 0000000..9c79259
--- /dev/null
+++ b/tests/language/async/implicit_await_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.
+
+import 'package:expect/expect.dart';
+
+bool caughtInF = false;
+bool caughtInMain = false;
+
+class A {}
+
+class AAndFutureOfA implements A, Future<A> {
+  noSuchMethod(Invocation i) => throw 0;
+}
+
+Future<A> f(A a) async {
+  try {
+    // Statically looks like no `await` is needed, but dynamically it is needed.
+    // So we should check dynamically whether to await.
+    return a;
+  } catch (e) {
+    caughtInF = true;
+  }
+  return new A();
+}
+
+void main() async {
+  try {
+    print(await f(AAndFutureOfA()));
+    print('Done');
+  } catch (e) {
+    caughtInMain = true;
+  }
+  Expect.isTrue(caughtInF, "Exception should be caught in 'f'.");
+  Expect.isFalse(caughtInMain, "Exception should not be caught in 'main'.");
+}
diff --git a/tests/language/call/method_implicit_invoke_local_test.dart b/tests/language/call/method_implicit_invoke_local_test.dart
index 1e58c47..0e15829 100644
--- a/tests/language/call/method_implicit_invoke_local_test.dart
+++ b/tests/language/call/method_implicit_invoke_local_test.dart
@@ -32,7 +32,8 @@
   // [analyzer] COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS
   // [cfe] Too few positional arguments: 1 required, 0 given.
   c2(3, 4);
-  //^^^^^^
+  //    ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 }
diff --git a/tests/language/class/override_inference_error_test.dart b/tests/language/class/override_inference_error_test.dart
index 65bcae6..14e215f 100644
--- a/tests/language/class/override_inference_error_test.dart
+++ b/tests/language/class/override_inference_error_test.dart
@@ -200,8 +200,6 @@
   //   ^
   // [analyzer] COMPILE_TIME_ERROR.MISSING_DEFAULT_VALUE_FOR_PARAMETER
   // [cfe] unspecified
-  //   ^
-  // [analyzer] STATIC_WARNING.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED
 }
 
 // Inherits type variables, even with different names.
diff --git a/tests/language/compile_time_constant/arguments_test.dart b/tests/language/compile_time_constant/arguments_test.dart
index 70d7fd3b..ca56413 100644
--- a/tests/language/compile_time_constant/arguments_test.dart
+++ b/tests/language/compile_time_constant/arguments_test.dart
@@ -15,8 +15,9 @@
   // [analyzer] COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS
   // [cfe] Too few positional arguments: 1 required, 0 given.
   const A(1, 2);
-  //     ^^^^^^
+  //         ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //     ^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
   const A.named();
   const A.named(b: 1);
@@ -34,7 +35,8 @@
   const A.optional();
   const A.optional(42);
   const A.optional(42, 54);
-  //              ^^^^^^^^
+  //                   ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //              ^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 }
diff --git a/tests/language/const/constant_dag_test.dart b/tests/language/const/constant_dag_test.dart
new file mode 100644
index 0000000..7e14ebb
--- /dev/null
+++ b/tests/language/const/constant_dag_test.dart
@@ -0,0 +1,67 @@
+// 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";
+
+// Test the efficient processing of constants that are DAGs.
+//
+// This test requires processing a constant that is a DAG of N nodes (N=40). If
+// the DAG is traversed as a tree, it will require exponential node visits and
+// take time O(2^N) i.e. 2^40, and the test will time out.
+
+main() {
+  Expect.equals(40, n40.lengthA);
+  Expect.equals(40, n40.lengthB);
+}
+
+class Node {
+  final Node? a;
+  final Node? b;
+  const Node(this.a, this.b);
+
+  int get lengthA => a == null ? 0 : 1 + a!.lengthA;
+  int get lengthB => a == null ? 0 : 1 + b!.lengthB;
+}
+
+const n0 = Node(null, null);
+const n1 = Node(n0, n0);
+const n2 = Node(n1, n1);
+const n3 = Node(n2, n2);
+const n4 = Node(n3, n3);
+const n5 = Node(n4, n4);
+const n6 = Node(n5, n5);
+const n7 = Node(n6, n6);
+const n8 = Node(n7, n7);
+const n9 = Node(n8, n8);
+const n10 = Node(n9, n9);
+const n11 = Node(n10, n10);
+const n12 = Node(n11, n11);
+const n13 = Node(n12, n12);
+const n14 = Node(n13, n13);
+const n15 = Node(n14, n14);
+const n16 = Node(n15, n15);
+const n17 = Node(n16, n16);
+const n18 = Node(n17, n17);
+const n19 = Node(n18, n18);
+const n20 = Node(n19, n19);
+const n21 = Node(n20, n20);
+const n22 = Node(n21, n21);
+const n23 = Node(n22, n22);
+const n24 = Node(n23, n23);
+const n25 = Node(n24, n24);
+const n26 = Node(n25, n25);
+const n27 = Node(n26, n26);
+const n28 = Node(n27, n27);
+const n29 = Node(n28, n28);
+const n30 = Node(n29, n29);
+const n31 = Node(n30, n30);
+const n32 = Node(n31, n31);
+const n33 = Node(n32, n32);
+const n34 = Node(n33, n33);
+const n35 = Node(n34, n34);
+const n36 = Node(n35, n35);
+const n37 = Node(n36, n36);
+const n38 = Node(n37, n37);
+const n39 = Node(n38, n38);
+const n40 = Node(n39, n39);
diff --git a/tests/language/constants_2018/constant_type_literal_test.dart b/tests/language/constants_2018/constant_type_literal_test.dart
index b886d77..924bcab 100644
--- a/tests/language/constants_2018/constant_type_literal_test.dart
+++ b/tests/language/constants_2018/constant_type_literal_test.dart
@@ -8,7 +8,7 @@
 import "dart:core" as core;
 // No reloading support for deferred loading.
 // See https://github.com/dart-lang/sdk/issues/33118.
-import "dart:core" deferred as dcore; //# 01: compile-time error
+import "dart:core" deferred as dcore show int //# 01: compile-time error
 
 // Declares F function type alias, M mixin and C class.
 import "constant_type_literal_types.dart";
diff --git a/tests/language/constructor/constructor13_test.dart b/tests/language/constructor/constructor13_test.dart
index f6790ec..24b8841 100644
--- a/tests/language/constructor/constructor13_test.dart
+++ b/tests/language/constructor/constructor13_test.dart
@@ -16,7 +16,8 @@
   // [cfe] Too few positional arguments: 1 required, 0 given.
   new Klass(1);
   new Klass(1, 2);
-  //       ^^^^^^
+  //           ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //       ^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 }
diff --git a/tests/language/constructor/no_such_constructor_test.dart b/tests/language/constructor/no_such_constructor_test.dart
index b106273..28c05a6 100644
--- a/tests/language/constructor/no_such_constructor_test.dart
+++ b/tests/language/constructor/no_such_constructor_test.dart
@@ -8,7 +8,8 @@
 
 main() {
   new A(42);
-  //   ^^^^
+  //    ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //   ^^^^
   // [cfe] Too many positional arguments: 0 allowed, but 1 found.
 }
diff --git a/tests/language/constructor/redirect2_test.dart b/tests/language/constructor/redirect2_test.dart
index 30d7ab6..85fc234 100644
--- a/tests/language/constructor/redirect2_test.dart
+++ b/tests/language/constructor/redirect2_test.dart
@@ -32,8 +32,9 @@
   //                          ^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.SUPER_IN_REDIRECTING_CONSTRUCTOR
   // [cfe] A redirecting constructor can't have other initializers.
-  //                               ^^^
+  //                                ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //                               ^^^
   // [cfe] Too many positional arguments: 0 allowed, but 1 found.
 }
 
diff --git a/tests/language/deferred/import_core_test.dart b/tests/language/deferred/import_core_test.dart
index f3d6644..3c72766 100644
--- a/tests/language/deferred/import_core_test.dart
+++ b/tests/language/deferred/import_core_test.dart
@@ -5,7 +5,7 @@
 // Nothing in the language spec explicitly prohibits a deferred import of
 // 'dart:core'.  Make sure it doesn't lead to any strange behavior.
 
-import "dart:core" deferred as core;
+import "dart:core" deferred as core show Object;
 
 main() {
   core.loadLibrary().then((_) => null);
diff --git a/tests/language/deferred/load_library_wrong_args_test.dart b/tests/language/deferred/load_library_wrong_args_test.dart
index c991e2e6..3903e19 100644
--- a/tests/language/deferred/load_library_wrong_args_test.dart
+++ b/tests/language/deferred/load_library_wrong_args_test.dart
@@ -5,6 +5,6 @@
   lib.loadLibrary(10);
 //^
 // [cfe] 'loadLibrary' takes no arguments.
-//               ^^^^
+//                ^^
 // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
 }
diff --git a/tests/language/extension_methods/static_extension_operator_override_error_test.dart b/tests/language/extension_methods/static_extension_operator_override_error_test.dart
new file mode 100644
index 0000000..acd3ab5
--- /dev/null
+++ b/tests/language/extension_methods/static_extension_operator_override_error_test.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.
+
+/// Regression test for https://github.com/dart-lang/sdk/issues/43114.
+
+class A {}
+
+extension E on A {
+  String operator +(int other) => '';
+}
+
+f(A a, int b) {
+  int i = E(a) + b;
+  //      ^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
+  //           ^
+  // [cfe] A value of type 'String' can't be assigned to a variable of type 'int'.
+}
+
+main() {
+  f(A(), 0);
+}
diff --git a/tests/language/extension_methods/static_extension_this_not_promoted_error_test.dart b/tests/language/extension_methods/static_extension_this_not_promoted_error_test.dart
new file mode 100644
index 0000000..342ccca
--- /dev/null
+++ b/tests/language/extension_methods/static_extension_this_not_promoted_error_test.dart
@@ -0,0 +1,55 @@
+// 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.
+
+// This test verifies that attempts to promote the type of `this` inside an
+// extension method have no effect.
+
+void f(dynamic d) {}
+
+class C {
+  int? cProp;
+}
+
+extension on C? {
+  void testCQuestion() {
+    if (this != null) {
+      f(this.cProp);
+      //^^^^
+      // [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
+      //     ^
+      // [cfe] Property 'cProp' cannot be accessed on 'C?' because it is potentially null.
+      f(cProp);
+      //^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
+      // [cfe] Property 'cProp' cannot be accessed on 'C?' because it is potentially null.
+    }
+  }
+}
+
+class D extends C {
+  int? dProp;
+}
+
+extension on C {
+  void testC() {
+    if (this is D) {
+      f(this.dProp);
+      //     ^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
+      // [cfe] The getter 'dProp' isn't defined for the class 'C'.
+      f(dProp);
+      //^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
+      // [cfe] The getter 'dProp' isn't defined for the class 'C'.
+    }
+  }
+}
+
+main() {
+  C().testCQuestion();
+  C().testC();
+  D().testCQuestion();
+  D().testC();
+  (null as C?).testCQuestion();
+}
diff --git a/tests/language/factory/redirection3_cyclic_test.dart b/tests/language/factory/redirection3_cyclic_test.dart
index 13dc39b..ab115cc 100644
--- a/tests/language/factory/redirection3_cyclic_test.dart
+++ b/tests/language/factory/redirection3_cyclic_test.dart
@@ -17,10 +17,10 @@
 class C implements B {
   factory C.bar() = C.foo;
   //                ^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_FACTORY_REDIRECT
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
   factory C.foo() = C.bar();
   //                ^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_FACTORY_REDIRECT
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
   //                  ^^^
   // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
   // [cfe] Expected ';' after this.
diff --git a/tests/language/generic/super_bounded_types_and_nested_variance_test.dart b/tests/language/generic/super_bounded_types_and_nested_variance_test.dart
new file mode 100644
index 0000000..ab088ff
--- /dev/null
+++ b/tests/language/generic/super_bounded_types_and_nested_variance_test.dart
@@ -0,0 +1,252 @@
+// 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.
+
+// Testing that i2b and checks for correct super-boundedness are applied
+// to type arguments, taking the variance of type parameters into account.
+
+// Standard type comparison support.
+
+typedef F<X> = void Function<Y extends X>();
+F<X> toF<X>(X x) => throw 0;
+
+// Material specific to this test.
+
+typedef Fcov<X> = X Function();
+typedef Fcon<X> = Function(X);
+typedef Finv<X> = X Function(X);
+
+class Acov<X extends Fcov<Y>, Y> {}
+
+class Acon<X extends Fcon<Y>, Y> {}
+
+class Ainv<X extends Finv<Y>, Y> {}
+
+typedef FcovBound<X extends num> = X Function();
+typedef FconBound<X extends num> = Function(X);
+typedef FinvBound<X extends num> = X Function(X);
+
+class AcovBound<X extends FcovBound<Y>, Y extends num> {}
+
+class AconBound<X extends FconBound<Y>, Y extends num> {}
+
+class AinvBound<X extends FinvBound<Y>, Y extends num> {}
+
+class A<X> {}
+
+typedef FcovCyclicBound<X extends A<X>> = X Function();
+typedef FconCyclicBound<X extends A<X>> = Function(X);
+typedef FinvCyclicBound<X extends A<X>> = X Function(X);
+
+class AcovCyclicBound<X extends FcovCyclicBound<Y>, Y extends A<Y>> {}
+
+class AconCyclicBound<X extends FconCyclicBound<Y>, Y extends A<Y>> {}
+
+class AinvCyclicBound<X extends FinvCyclicBound<Y>, Y extends A<Y>> {}
+
+typedef FcovCyclicCoBound<X extends Function(X)> = X Function();
+typedef FconCyclicCoBound<X extends Function(X)> = Function(X);
+typedef FinvCyclicCoBound<X extends Function(X)> = X Function(X);
+
+class AcovCyclicCoBound<X extends FcovCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class AconCyclicCoBound<X extends FconCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class AinvCyclicCoBound<X extends FinvCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class B<X> {}
+
+void testTypeAliasAsTypeArgument() {
+  // I2b: Use bounds (Fcov<Y>, dynamic), then replace covariant occurrence
+  // (of `Y` in `Acov<Fcov<Y>, _>`) by `Y`s value `dynamic`. Resulting type
+  // `Acov<Fcov<dynamic>, dynamic>` is regular-bounded.
+  void f1(Acov source1) {
+    var fsource1 = toF(source1);
+    F<Acov<Fcov<dynamic>, dynamic>> target1 = fsource1;
+  }
+
+  // I2b: Use bounds (Fcon<Y>, dynamic), then replace contravariant occurrence
+  // (of `Y` in `Acon<Fcon<Y>, _>`) by `Never`. Resulting type
+  // is super-bounded: Acon<Fcon<Object?>, Never> is regular-bounded.
+  void f2(Acon source2) {
+    var fsource2 = toF(source2);
+    F<Acon<Fcon<Never>, dynamic>> target2 = fsource2;
+  }
+
+  // I2b: Use bounds (Finv<Y>, dynamic) then replace invariant occurrence
+  // (of `Y` in `Ainv<Finv<Y>, _>`) by `Y`s value `dynamic`. Resulting type
+  // `Ainv<Finv<dynamic>, dynamic>` is regular-bounded.
+  void f3(Ainv source3) {
+    var fsource3 = toF(source3);
+    F<Ainv<Finv<dynamic>, dynamic>> target3 = fsource3;
+  }
+
+  // I2b: Use bounds (FcovBound<Y>, num), then replace covariant occurrence
+  // (of `Y` in `AcovBound<FcovBound<Y>, _>`) by `Y`s value `num`.
+  // Resulting type `AcovBound<FcovBound<num>, num>` is regular-bounded.
+  void f4(AcovBound source4) {
+    var fsource4 = toF(source4);
+    F<AcovBound<FcovBound<num>, num>> target4 = fsource4;
+  }
+
+  // I2b: Use bounds (FconBound<Y>, num), then replace contravariant occurrence
+  // of `Y` in `AconBound<FconBound<Y>, _>` by `Never`. Resulting type is
+  // super-bounded: AconBound<FconBound<Object?>, num> is regular-bounded.
+  void f5(AconBound source5) {
+    var fsource5 = toF(source5);
+    F<AconBound<FconBound<Never>, num>> target5 = fsource5;
+  }
+
+  // I2b: Use bounds (FinvBound<Y>, num), then replace invariant occurrence
+  // of `Y` in `AinvBound<FinvBound<Y>, _>` by `Y`s value `num`. Resulting
+  // type `AinvBound<FinvBound<num>, num>` is regular-bounded.
+  void f6(AinvBound source6) {
+    var fsource6 = toF(source6);
+    F<AinvBound<FinvBound<num>, num>> target6 = fsource6;
+  }
+
+  // I2b: Use bounds (FcovCyclicBound<Y>, A<Y>), then break cycle {Y} by
+  // replacing covariant occurrence of `Y` in `AcovCyclicBound<_, A<Y>>`
+  // by `dynamic`; then replace covariant occurrence of `Y` in
+  // `AcovCyclicBound<FcovCyclicBound<Y>, _>` by `Y`s value `A<dynamic>`.
+  // Resulting type `AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>>`
+  // is regular-bounded.
+  void f7(AcovCyclicBound source7) {
+    var fsource7 = toF(source7);
+    F<AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>> target7 =
+        fsource7;
+  }
+
+  // I2b: Use bounds (FconCyclicBound<Y>, A<Y>), then break cycle {Y} by
+  // replacing covariant occurrence of `Y` in `AconCyclicBound<_, A<Y>>`
+  // by `dynamic`; then replace contravariant occurrence of `Y` in
+  // `AconCyclicBound<FconCyclicBound<Y>, _>` by `Never`.
+  // Resulting type `AconCyclicBound<FconCyclicBound<Never>, A<dynamic>>>` is
+  // super-bounded: `AconCyclicBound<FconCyclicBound<Object?>, A<Never>>>`
+  // is regular-bounded.
+  void f8(AconCyclicBound source8) {
+    var fsource8 = toF(source8);
+    F<AconCyclicBound<FconCyclicBound<Never>, A<dynamic>>> target8 = fsource8;
+  }
+
+  // I2b: Use bounds (FinvCyclicBound<Y>, A<Y>), then break cycle {Y} by
+  // replacing covariant occurrence of `Y` in `AinvCyclicBound<_, A<Y>>`
+  // by `dynamic`; then replace invariant occurrence of `Y` in
+  // `AinvCyclicBound<FinvCyclicBound<Y>, _>` by `Y`s value `A<dynamic>`.
+  // Resulting type `AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>>`
+  // is regular-bounded, and contains `FinvCyclicBound<A<dynamic>>` which
+  // is super-bounded.
+  void f9(AinvCyclicBound source9) {
+    var fsource9 = toF(source9);
+    F<AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>> target9 =
+        fsource9;
+  }
+
+  // I2b: Use bounds (FcovCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
+  // by replacing contravariant occurrence of `Y` in
+  // `AcovCyclicCoBound<_, Function(Y)>` by `Never`; then replace covariant
+  // occurrence of `Y` in `AcovCyclicCoBound<FcovCyclicCoBound<Y>, _>` by `Y`s
+  // value `Function(Never)`. Resulting type
+  // `AcovCyclicCoBound<FcovCyclicCoBound<Function(Never)>, Function(Never)>`
+  // is regular-bounded, with subterm `FcovCyclicCoBound<Function(Never)>` which
+  // is super-bounded because `FcovCyclicCoBound<Function(Object?)>` is
+  // regular-bounded.
+  void f10(AcovCyclicCoBound source10) {
+    var fsource10 = toF(source10);
+    F<AcovCyclicCoBound<FcovCyclicCoBound<Function(Never)>, Function(Never)>>
+        target10 = fsource10;
+  }
+
+  // I2b: Use bounds (FconCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
+  // by replacing contravariant occurrence of `Y` in
+  // `AconCyclicCoBound<_, Function(Y)>` by `Never`; then replace contravariant
+  // occurrence of `Y` in `AconCyclicCoBound<FconCyclicCoBound<Y>, _>` by
+  // `Never`. Resulting type
+  // `AconCyclicCoBound<FconCyclicCoBound<Never>, Function(Never)>` is
+  // super-bounded because
+  // `AconCyclicCoBound<FconCyclicCoBound<Object?>, Function(Object?)>` is
+  // regular-bounded.
+  void f11(AconCyclicCoBound source11) {
+    var fsource11 = toF(source11);
+    F<AconCyclicCoBound<FconCyclicCoBound<Never>, Function(Never)>> target11 =
+        fsource11;
+  }
+
+  var funs = [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11];
+}
+
+void testNested() {
+  // Everything gets the same treatment when the cases from `testTopLevel`
+  // are duplicated at the nested level in a covariant position.
+
+  void f1(B<Acov> source1) {
+    var fsource1 = toF(source1);
+    F<B<Acov<Fcov<dynamic>, dynamic>>> target1 = fsource1;
+  }
+
+  void f2(B<Acon> source2) {
+    var fsource2 = toF(source2);
+    F<B<Acon<Fcon<Never>, dynamic>>> target2 = fsource2;
+  }
+
+  void f3(B<Ainv> source3) {
+    var fsource3 = toF(source3);
+    F<B<Ainv<Finv<dynamic>, dynamic>>> target3 = fsource3;
+  }
+
+  void f4(B<AcovBound> source4) {
+    var fsource4 = toF(source4);
+    F<B<AcovBound<FcovBound<num>, num>>> target4 = fsource4;
+  }
+
+  void f5(B<AconBound> source5) {
+    var fsource5 = toF(source5);
+    F<B<AconBound<FconBound<Never>, num>>> target5 = fsource5;
+  }
+
+  void f6(B<AinvBound> source6) {
+    var fsource6 = toF(source6);
+    F<B<AinvBound<FinvBound<num>, num>>> target6 = fsource6;
+  }
+
+  void f7(B<AcovCyclicBound> source7) {
+    var fsource7 = toF(source7);
+    F<B<AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>>> target7 =
+        fsource7;
+  }
+
+  void f8(B<AconCyclicBound> source8) {
+    var fsource8 = toF(source8);
+    F<B<AconCyclicBound<FconCyclicBound<Never>, A<dynamic>>>> target8 =
+        fsource8;
+  }
+
+  void f9(B<AinvCyclicBound> source9) {
+    var fsource9 = toF(source9);
+    F<B<AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>>> target9 =
+        fsource9;
+  }
+
+  void f10(B<AcovCyclicCoBound> source10) {
+    var fsource10 = toF(source10);
+    F<B<AcovCyclicCoBound<FcovCyclicCoBound<Function(Never)>, Function(Never)>>>
+        target10 = fsource10;
+  }
+
+  void f11(B<AconCyclicCoBound> source11) {
+    var fsource11 = toF(source11);
+    F<B<AconCyclicCoBound<FconCyclicCoBound<Never>, Function(Never)>>>
+        target11 = fsource11;
+  }
+
+
+  var funs = [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11];
+}
+
+main() {
+  testTypeAliasAsTypeArgument();
+  testNested();
+}
diff --git a/tests/language/generic/super_bounded_types_and_variance_test.dart b/tests/language/generic/super_bounded_types_and_variance_test.dart
new file mode 100644
index 0000000..53fd9a5
--- /dev/null
+++ b/tests/language/generic/super_bounded_types_and_variance_test.dart
@@ -0,0 +1,190 @@
+// 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.
+
+// Testing that instantiate-to-bound and super-bounded types take the
+// variance of formal type parameters into account when a type alias is
+// used as a raw type.
+
+// Standard type comparison support.
+
+typedef F<X> = void Function<Y extends X>();
+F<X> toF<X>(X x) => throw 0;
+
+// Material specific to this test.
+
+typedef Fcov<X> = X Function();
+typedef Fcon<X> = Function(X);
+typedef Finv<X> = X Function(X);
+
+typedef FcovBound<X extends num> = X Function();
+typedef FconBound<X extends num> = Function(X);
+typedef FinvBound<X extends num> = X Function(X);
+
+class A<X> {}
+
+typedef FcovCyclicBound<X extends A<X>> = X Function();
+typedef FconCyclicBound<X extends A<X>> = Function(X);
+typedef FinvCyclicBound<X extends A<X>> = X Function(X);
+
+typedef FcovCyclicCoBound<X extends Function(X)> = X Function();
+typedef FconCyclicCoBound<X extends Function(X)> = Function(X);
+typedef FinvCyclicCoBound<X extends Function(X)> = X Function(X);
+
+class B<X> {}
+
+void testTopLevel() {
+  // I2b initial value for a covariant type parameter w/o bound: dynamic.
+  void f1(Fcov source1) {
+    var fsource1 = toF(source1);
+    F<Fcov<dynamic>> target1 = fsource1;
+  }
+
+  // I2b initial value for a contravariant type parameter w/o bound: dynamic.
+  void f2(Fcon source2) {
+    var fsource2 = toF(source2);
+    F<Fcon<dynamic>> target2 = fsource2;
+  }
+
+  // I2b initial value for an invariant type parameter w/o bound: dynamic.
+  void f3(Finv source3) {
+    var fsource3 = toF(source3);
+    F<Finv<dynamic>> target3 = fsource3;
+  }
+
+  // I2b initial value for a covariant type parameter: bound.
+  void f4(FcovBound source4) {
+    var fsource4 = toF(source4);
+    F<FcovBound<num>> target4 = fsource4;
+  }
+
+  // I2b initial value for a contravariant type parameter: bound.
+  void f5(FconBound source5) {
+    var fsource5 = toF(source5);
+    F<FconBound<num>> target5 = fsource5;
+  }
+
+  // I2b initial value for an invariant type parameter: bound.
+  void f6(FinvBound source6) {
+    var fsource6 = toF(source6);
+    F<FinvBound<num>> target6 = fsource6;
+  }
+
+  // I2b for a covariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing covariant occurrence by `dynamic`. Resulting type
+  // is super-bounded: FcovCyclicBound<A<Never>> is regular-bounded.
+  void f7(FcovCyclicBound source7) {
+    var fsource7 = toF(source7);
+    F<FcovCyclicBound<A<dynamic>>> target7 = fsource7;
+  }
+
+  // I2b for a contravariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing contravariant occurrence by `Never`. Resulting type
+  // is super-bounded: FconCyclicBound<A<Object?>> is regular-bounded.
+  void f8(FconCyclicBound source8) {
+    var fsource8 = toF(source8);
+    F<FconCyclicBound<A<Never>>> target8 = fsource8;
+  }
+
+  // I2b for an invariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing invariant occurrence by `dynamic`. Resulting type is
+  // super-bounded: FinvCyclicBound<A<Never>> is regular-bounded.
+  void f9(FinvCyclicBound source9) {
+    var fsource9 = toF(source9);
+    F<FinvCyclicBound<A<dynamic>>> target9 = fsource9;
+  }
+
+  // I2b for a covariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing contravariant occurrence by `Never`. Resulting type
+  // is super-bounded: FcovCyclicBound<Function(Object?)> is regular-bounded.
+  void f10(FcovCyclicCoBound source10) {
+    var fsource10 = toF(source10);
+    F<FcovCyclicCoBound<Function(Never)>> target10 = fsource10;
+  }
+
+  // I2b for a contravariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing covariant occurrence by `dynamic`. Resulting type
+  // FconCyclicCoBound<Function(dynamic)> is regular-bounded.
+  void f11(FconCyclicCoBound source11) {
+    var fsource11 = toF(source11);
+    F<FconCyclicCoBound<Function(dynamic)>> target11 = fsource11;
+  }
+
+  // I2b for an invariant type parameter w F-bound: Use bound, then break
+  // cycle by replacing invariant occurrence by `dynamic`. Resulting type
+  // F<FinvCyclicCoBound<Function(dynamic)>> is regular-bounded.
+  void f12(FinvCyclicCoBound source12) {
+    var fsource12 = toF(source12);
+    F<FinvCyclicCoBound<Function(dynamic)>> target12 = fsource12;
+  }
+}
+
+void testNested() {
+  // Everything gets the same treatment when the cases from
+  // `testTopLevel` are duplicated at the nested level.
+
+  void f1(B<Fcov> source1) {
+    var fsource1 = toF(source1);
+    F<B<Fcov<dynamic>>> target1 = fsource1;
+  }
+
+  void f2(B<Fcon> source2) {
+    var fsource2 = toF(source2);
+    F<B<Fcon<dynamic>>> target2 = fsource2;
+  }
+
+  void f3(B<Finv> source3) {
+    var fsource3 = toF(source3);
+    F<B<Finv<dynamic>>> target3 = fsource3;
+  }
+
+  void f4(B<FcovBound> source4) {
+    var fsource4 = toF(source4);
+    F<B<FcovBound<num>>> target4 = fsource4;
+  }
+
+  void f5(B<FconBound> source5) {
+    var fsource5 = toF(source5);
+    F<B<FconBound<num>>> target5 = fsource5;
+  }
+
+  void f6(B<FinvBound> source6) {
+    var fsource6 = toF(source6);
+    F<B<FinvBound<num>>> target6 = fsource6;
+  }
+
+  void f7(B<FcovCyclicBound> source7) {
+    var fsource7 = toF(source7);
+    F<B<FcovCyclicBound<A<dynamic>>>> target7 = fsource7;
+  }
+
+  void f8(B<FconCyclicBound> source8) {
+    var fsource8 = toF(source8);
+    F<B<FconCyclicBound<A<Never>>>> target8 = fsource8;
+  }
+
+  void f9(B<FinvCyclicBound> source9) {
+    var fsource9 = toF(source9);
+    F<B<FinvCyclicBound<A<dynamic>>>> target9 = fsource9;
+  }
+
+  void f10(B<FcovCyclicCoBound> source10) {
+    var fsource10 = toF(source10);
+    F<B<FcovCyclicCoBound<Function(Never)>>> target10 = fsource10;
+  }
+
+  void f11(B<FconCyclicCoBound> source11) {
+    var fsource11 = toF(source11);
+    F<B<FconCyclicCoBound<Function(dynamic)>>> target11 = fsource11;
+  }
+
+  void f12(B<FinvCyclicCoBound> source12) {
+    var fsource12 = toF(source12);
+    F<B<FinvCyclicCoBound<Function(dynamic)>>> target12 = fsource12;
+  }
+}
+
+main() {
+  testTopLevel();
+  testNested();
+}
diff --git a/tests/language/generic/super_bounded_types_error2_test.dart b/tests/language/generic/super_bounded_types_error2_test.dart
new file mode 100644
index 0000000..39d9d4c
--- /dev/null
+++ b/tests/language/generic/super_bounded_types_error2_test.dart
@@ -0,0 +1,2338 @@
+// 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.
+
+// Test that various types cause an error when it violates its bounds and
+// is not correctly super-bounded.
+
+import 'dart:async';
+
+class A<X> {}
+
+class B<X extends B<X>> extends A<X> {}
+
+typedef Fcov<X> = X Function();
+typedef Fcon<X> = Function(X);
+typedef Finv<X> = X Function(X);
+typedef Funu<X> = Function();
+
+typedef FcovBound<X extends num> = X Function();
+typedef FconBound<X extends num> = Function(X);
+typedef FinvBound<X extends num> = X Function(X);
+typedef FunuBound<X extends num> = Function();
+
+typedef FcovCyclicBound<X extends A<X>> = X Function();
+typedef FconCyclicBound<X extends A<X>> = Function(X);
+typedef FinvCyclicBound<X extends A<X>> = X Function(X);
+typedef FunuCyclicBound<X extends A<X>> = Function();
+
+typedef FcovCyclicCoBound<X extends Function(X)> = X Function();
+typedef FconCyclicCoBound<X extends Function(X)> = Function(X);
+typedef FinvCyclicCoBound<X extends Function(X)> = X Function(X);
+typedef FunuCyclicCoBound<X extends Function(X)> = Function();
+
+class CFcov<X extends Fcov<X>> {}
+
+class CFcon<X extends Fcon<X>> {}
+
+class CFinv<X extends Finv<X>> {}
+
+class CFunu<X extends Funu<X>> {}
+
+class CcovBound<X extends num> {}
+
+class CcovCyclicBound<X extends A<X>> {}
+
+class CcovCyclicCoBound<X extends Function(X)> {}
+
+void testContravariantSuperboundError<N extends Null>() {
+  // --- Near-bottom type in a contravariant position, not super-bounded.
+  FcovCyclicCoBound<Function(Never?)> x1;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(Null)> x2;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(N)> x3;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  CFcon<Fcon<Never?>> x4;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CFcon<Fcon<Null>> x5;
+//^
+// [analyzer] unspecified
+//                  ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CFcon<Fcon<N>> x6;
+//^
+// [analyzer] unspecified
+//               ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CcovCyclicCoBound<Function(Never?)> x7;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<Function(Null)> x8;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<Function(N)> x9;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+
+  // --- Same non-super-bounded types in a context.
+  A<FcovCyclicCoBound<Function(Never?)>> x10;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  A<FcovCyclicCoBound<Function(Null)>> x11;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  A<FcovCyclicCoBound<Function(N)>> x12;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  A<CFcon<Fcon<Never?>>> x13;
+//^
+// [analyzer] unspecified
+//                       ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  A<CFcon<Fcon<Null>>> x14;
+//^
+// [analyzer] unspecified
+//                     ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  A<CFcon<Fcon<N>>> x15;
+//^
+// [analyzer] unspecified
+//                  ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  A<CcovCyclicCoBound<Function(Never?)>> x16;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  A<CcovCyclicCoBound<Function(Null)>> x17;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  A<CcovCyclicCoBound<Function(N)>> x18;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(Never?)> Function() x19;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(Null)> Function() x20;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(N)> Function() x21;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  CFcon<Fcon<Never?>> Function() x22;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CFcon<Fcon<Null>> Function() x23;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CFcon<Fcon<N>> Function() x24;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CcovCyclicCoBound<Function(Never?)> Function() x25;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<Function(Null)> Function() x26;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<Function(N)> Function() x27;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(void Function(FcovCyclicCoBound<Function(Never?)>)) x28;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(void Function(FcovCyclicCoBound<Function(Null)>)) x29;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(void Function(FcovCyclicCoBound<Function(N)>)) x30;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(void Function(CFcon<Fcon<Never?>>)) x31;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(void Function(CFcon<Fcon<Null>>)) x32;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(void Function(CFcon<Fcon<N>>)) x33;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(void Function(CcovCyclicCoBound<Function(Never?)>)) x34;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(void Function(CcovCyclicCoBound<Function(Null)>)) x35;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(void Function(CcovCyclicCoBound<Function(N)>)) x36;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(Never?)>) x37;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(Null)>) x38;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(N)>) x39;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(CFcon<Fcon<Never?>>) x40;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CFcon<Fcon<Null>>) x41;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CFcon<Fcon<N>>) x42;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CcovCyclicCoBound<Function(Never?)>) x43;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<Function(Null)>) x44;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<Function(N)>) x45;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(Never?)>) Function() x46;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(Null)>) Function() x47;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(N)>) Function() x48;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(CFcon<Fcon<Never?>>) Function() x49;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CFcon<Fcon<Null>>) Function() x50;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CFcon<Fcon<N>>) Function() x51;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CcovCyclicCoBound<Function(Never?)>) Function() x52;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<Function(Null)>) Function() x53;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<Function(N)>) Function() x54;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends FcovCyclicCoBound<Function(Never?)>>() x55;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends FcovCyclicCoBound<Function(Null)>>() x56;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends FcovCyclicCoBound<Function(N)>>() x57;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends CFcon<Fcon<Never?>>>() x58;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends CFcon<Fcon<Null>>>() x59;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends CFcon<Fcon<N>>>() x60;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends CcovCyclicCoBound<Function(Never?)>>() x61;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends CcovCyclicCoBound<Function(Null)>>() x62;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends CcovCyclicCoBound<Function(N)>>() x63;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends A<FcovCyclicCoBound<Function(Never?)>>>() x64;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends A<FcovCyclicCoBound<Function(Null)>>>() x65;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends A<FcovCyclicCoBound<Function(N)>>>() x66;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends A<CFcon<Fcon<Never?>>>>() x67;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends A<CFcon<Fcon<Null>>>>() x68;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends A<CFcon<Fcon<N>>>>() x69;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends A<CcovCyclicCoBound<Function(Never?)>>>() x70;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends A<CcovCyclicCoBound<Function(Null)>>>() x71;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends A<CcovCyclicCoBound<Function(N)>>>() x72;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Finv<FcovCyclicCoBound<Function(Never?)>> x73;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Finv<FcovCyclicCoBound<Function(Null)>> x74;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Finv<FcovCyclicCoBound<Function(N)>> x75;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Finv<CFcon<Fcon<Never?>>> x76;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Finv<CFcon<Fcon<Null>>> x77;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Finv<CFcon<Fcon<N>>> x78;
+//^
+// [analyzer] unspecified
+//                     ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Finv<CcovCyclicCoBound<Function(Never?)>> x79;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Finv<CcovCyclicCoBound<Function(Null)>> x80;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Finv<CcovCyclicCoBound<Function(N)>> x81;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Funu<FcovCyclicCoBound<Function(Never?)>> x82;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Funu<FcovCyclicCoBound<Function(Null)>> x83;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Funu<FcovCyclicCoBound<Function(N)>> x84;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Funu<CFcon<Fcon<Never?>>> x85;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Funu<CFcon<Fcon<Null>>> x86;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Funu<CFcon<Fcon<N>>> x87;
+//^
+// [analyzer] unspecified
+//                     ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Funu<CcovCyclicCoBound<Function(Never?)>> x88;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'dynamic Function(Never?)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Funu<CcovCyclicCoBound<Function(Null)>> x89;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'dynamic Function(Null)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Funu<CcovCyclicCoBound<Function(N)>> x90;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+
+  // --- Top type in a contravariant position, not super-bounded.
+  FconBound<dynamic> x91;
+//^
+// [analyzer] unspecified
+//                   ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<void> x92;
+//^
+// [analyzer] unspecified
+//                ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<Object?> x93;
+//^
+// [analyzer] unspecified
+//                   ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<FutureOr<dynamic>> x94;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<FutureOr<void>> x95;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<FutureOr<Object?>> x96;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconCyclicBound<dynamic> x97;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<void> x98;
+//^
+// [analyzer] unspecified
+//                      ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<Object?> x99;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<FutureOr<dynamic>> x100;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<FutureOr<void>> x101;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<FutureOr<Object?>> x102;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<dynamic>> x103;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<void>> x104;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<Object?>> x105;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<FutureOr<dynamic>>> x106;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<FutureOr<void>>> x107;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<FutureOr<Object?>>> x108;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<dynamic>>> x109;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<void>>> x110;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<Object?>>> x111;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<FutureOr<dynamic>>>> x112;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<FutureOr<void>>>> x113;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<FutureOr<Object?>>>> x114;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicCoBound<dynamic> x115;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<void> x116;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Object?> x117;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<FutureOr<dynamic>> x118;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<FutureOr<void>> x119;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<FutureOr<Object?>> x120;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(dynamic))> x121;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(void))> x122;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(Object?))> x123;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(FutureOr<dynamic>))> x124;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(FutureOr<void>))> x125;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(FutureOr<Object?>))> x126;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+
+  // --- Same non-super-bounded types in a context.
+  A<FconBound<dynamic>> x127;
+//^
+// [analyzer] unspecified
+//                      ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  A<FconBound<void>> x128;
+//^
+// [analyzer] unspecified
+//                   ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  A<FconBound<Object?>> x129;
+//^
+// [analyzer] unspecified
+//                      ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  A<FconBound<FutureOr<dynamic>>> x130;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  A<FconBound<FutureOr<void>>> x131;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  A<FconBound<FutureOr<Object?>>> x132;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  A<FconCyclicBound<dynamic>> x133;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<void>> x134;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<Object?>> x135;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<FutureOr<dynamic>>> x136;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<FutureOr<void>>> x137;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<FutureOr<Object?>>> x138;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<dynamic>>> x139;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<void>>> x140;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<Object?>>> x141;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<FutureOr<dynamic>>>> x142;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<FutureOr<void>>>> x143;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<FutureOr<Object?>>>> x144;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<A<dynamic>>>> x145;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<A<void>>>> x146;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<A<Object?>>>> x147;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<A<FutureOr<dynamic>>>>> x148;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<A<FutureOr<void>>>>> x149;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicBound<A<A<FutureOr<Object?>>>>> x150;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  A<FconCyclicCoBound<dynamic>> x151;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<void>> x152;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<Object?>> x153;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<FutureOr<dynamic>>> x154;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<FutureOr<void>>> x155;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<FutureOr<Object?>>> x156;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<Function(Function(dynamic))>> x157;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<Function(Function(void))>> x158;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<Function(Function(Object?))>> x159;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x160;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<Function(Function(FutureOr<void>))>> x161;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  A<FconCyclicCoBound<Function(Function(FutureOr<Object?>))>> x162;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconBound<dynamic> Function() x163;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<void> Function() x164;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<Object?> Function() x165;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<FutureOr<dynamic>> Function() x166;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<FutureOr<void>> Function() x167;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconBound<FutureOr<Object?>> Function() x168;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  FconCyclicBound<dynamic> Function() x169;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<void> Function() x170;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<Object?> Function() x171;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<FutureOr<dynamic>> Function() x172;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<FutureOr<void>> Function() x173;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<FutureOr<Object?>> Function() x174;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<dynamic>> Function() x175;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<void>> Function() x176;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<Object?>> Function() x177;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<FutureOr<dynamic>>> Function() x178;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<FutureOr<void>>> Function() x179;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<FutureOr<Object?>>> Function() x180;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<dynamic>>> Function() x181;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<void>>> Function() x182;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<Object?>>> Function() x183;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<FutureOr<dynamic>>>> Function() x184;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<FutureOr<void>>>> Function() x185;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicBound<A<A<FutureOr<Object?>>>> Function() x186;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  FconCyclicCoBound<dynamic> Function() x187;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<void> Function() x188;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Object?> Function() x189;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<FutureOr<dynamic>> Function() x190;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<FutureOr<void>> Function() x191;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<FutureOr<Object?>> Function() x192;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(dynamic))> Function() x193;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(void))> Function() x194;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(Object?))> Function() x195;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(FutureOr<dynamic>))> Function() x196;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(FutureOr<void>))> Function() x197;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  FconCyclicCoBound<Function(Function(FutureOr<Object?>))> Function() x198;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconBound<dynamic>)) x199;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(void Function(FconBound<void>)) x200;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(void Function(FconBound<Object?>)) x201;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(void Function(FconBound<FutureOr<dynamic>>)) x202;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(void Function(FconBound<FutureOr<void>>)) x203;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(void Function(FconBound<FutureOr<Object?>>)) x204;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(void Function(FconCyclicBound<dynamic>)) x205;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<void>)) x206;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<Object?>)) x207;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<FutureOr<dynamic>>)) x208;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<FutureOr<void>>)) x209;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<FutureOr<Object?>>)) x210;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<dynamic>>)) x211;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<void>>)) x212;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<Object?>>)) x213;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<FutureOr<dynamic>>>)) x214;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<FutureOr<void>>>)) x215;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<FutureOr<Object?>>>)) x216;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<A<dynamic>>>)) x217;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<A<void>>>)) x218;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<A<Object?>>>)) x219;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<A<FutureOr<dynamic>>>>)) x220;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<A<FutureOr<void>>>>)) x221;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicBound<A<A<FutureOr<Object?>>>>)) x222;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(void Function(FconCyclicCoBound<dynamic>)) x223;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconCyclicCoBound<void>)) x224;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconCyclicCoBound<Object?>)) x225;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconCyclicCoBound<FutureOr<dynamic>>)) x226;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconCyclicCoBound<FutureOr<void>>)) x227;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconCyclicCoBound<FutureOr<Object?>>)) x228;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconCyclicCoBound<Function(Function(dynamic))>))
+//^
+// [analyzer] unspecified
+      x229;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconCyclicCoBound<Function(Function(void))>))
+//^
+// [analyzer] unspecified
+      x230;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(void Function(FconCyclicCoBound<Function(Function(Object?))>))
+//^
+// [analyzer] unspecified
+      x231;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(
+      void Function(
+          FconCyclicCoBound<Function(Function(FutureOr<dynamic>))>)) x232;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(
+          void Function(FconCyclicCoBound<Function(Function(FutureOr<void>))>))
+//^
+// [analyzer] unspecified
+      x233;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(
+      void Function(
+          FconCyclicCoBound<Function(Function(FutureOr<Object?>))>)) x234;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconBound<dynamic>) x235;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<void>) x236;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<Object?>) x237;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<FutureOr<dynamic>>) x238;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<FutureOr<void>>) x239;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<FutureOr<Object?>>) x240;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconCyclicBound<dynamic>) x241;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<void>) x242;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<Object?>) x243;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<FutureOr<dynamic>>) x244;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<FutureOr<void>>) x245;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<FutureOr<Object?>>) x246;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<dynamic>>) x247;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<void>>) x248;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<Object?>>) x249;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<FutureOr<dynamic>>>) x250;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<FutureOr<void>>>) x251;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<FutureOr<Object?>>>) x252;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<dynamic>>>) x253;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<void>>>) x254;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<Object?>>>) x255;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<FutureOr<dynamic>>>>) x256;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<FutureOr<void>>>>) x257;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<FutureOr<Object?>>>>) x258;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicCoBound<dynamic>) x259;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<void>) x260;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Object?>) x261;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<FutureOr<dynamic>>) x262;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<FutureOr<void>>) x263;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<FutureOr<Object?>>) x264;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(dynamic))>) x265;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(void))>) x266;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(Object?))>) x267;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(FutureOr<dynamic>))>) x268;
+//^
+// [analyzer] unspecified
+//                                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(FutureOr<void>))>) x269;
+//^
+// [analyzer] unspecified
+//                                                                     ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(FutureOr<Object?>))>) x270;
+//^
+// [analyzer] unspecified
+//                                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconBound<dynamic>) Function() x271;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<void>) Function() x272;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<Object?>) Function() x273;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<FutureOr<dynamic>>) Function() x274;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<FutureOr<void>>) Function() x275;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconBound<FutureOr<Object?>>) Function() x276;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function(FconCyclicBound<dynamic>) Function() x277;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<void>) Function() x278;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<Object?>) Function() x279;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<FutureOr<dynamic>>) Function() x280;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<FutureOr<void>>) Function() x281;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<FutureOr<Object?>>) Function() x282;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<dynamic>>) Function() x283;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<void>>) Function() x284;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<Object?>>) Function() x285;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<FutureOr<dynamic>>>) Function() x286;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<FutureOr<void>>>) Function() x287;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<FutureOr<Object?>>>) Function() x288;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<dynamic>>>) Function() x289;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<void>>>) Function() x290;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<Object?>>>) Function() x291;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<FutureOr<dynamic>>>>) Function() x292;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<FutureOr<void>>>>) Function() x293;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicBound<A<A<FutureOr<Object?>>>>) Function() x294;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function(FconCyclicCoBound<dynamic>) Function() x295;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<void>) Function() x296;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Object?>) Function() x297;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<FutureOr<dynamic>>) Function() x298;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<FutureOr<void>>) Function() x299;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<FutureOr<Object?>>) Function() x300;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(dynamic))>) Function() x301;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(void))>) Function() x302;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(Object?))>) Function() x303;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(FutureOr<dynamic>))>)
+//^
+// [analyzer] unspecified
+      Function() x304;
+//               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(FutureOr<void>))>)
+//^
+// [analyzer] unspecified
+      Function() x305;
+//               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function(FconCyclicCoBound<Function(Function(FutureOr<Object?>))>)
+//^
+// [analyzer] unspecified
+      Function() x306;
+//               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconBound<dynamic>>() x307;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends FconBound<void>>() x308;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends FconBound<Object?>>() x309;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends FconBound<FutureOr<dynamic>>>() x310;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends FconBound<FutureOr<void>>>() x311;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends FconBound<FutureOr<Object?>>>() x312;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends FconCyclicBound<dynamic>>() x313;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<void>>() x314;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<Object?>>() x315;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<FutureOr<dynamic>>>() x316;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<FutureOr<void>>>() x317;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<FutureOr<Object?>>>() x318;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<dynamic>>>() x319;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<void>>>() x320;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<Object?>>>() x321;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<FutureOr<dynamic>>>>() x322;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<FutureOr<void>>>>() x323;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<FutureOr<Object?>>>>() x324;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<A<dynamic>>>>() x325;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<A<void>>>>() x326;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<A<Object?>>>>() x327;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<A<FutureOr<dynamic>>>>>() x328;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<A<FutureOr<void>>>>>() x329;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicBound<A<A<FutureOr<Object?>>>>>() x330;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends FconCyclicCoBound<dynamic>>() x331;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconCyclicCoBound<void>>() x332;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconCyclicCoBound<Object?>>() x333;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconCyclicCoBound<FutureOr<dynamic>>>() x334;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconCyclicCoBound<FutureOr<void>>>() x335;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconCyclicCoBound<FutureOr<Object?>>>() x336;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconCyclicCoBound<Function(Function(dynamic))>>()
+//^
+// [analyzer] unspecified
+      x337;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconCyclicCoBound<Function(Function(void))>>() x338;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends FconCyclicCoBound<Function(Function(Object?))>>()
+//^
+// [analyzer] unspecified
+      x339;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<
+          Y extends FconCyclicCoBound<Function(Function(FutureOr<dynamic>))>>()
+//^
+// [analyzer] unspecified
+      x340;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<
+      Y extends FconCyclicCoBound<Function(Function(FutureOr<void>))>>() x341;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<
+          Y extends FconCyclicCoBound<Function(Function(FutureOr<Object?>))>>()
+//^
+// [analyzer] unspecified
+      x342;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconBound<dynamic>>>() x343;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends A<FconBound<void>>>() x344;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends A<FconBound<Object?>>>() x345;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends A<FconBound<FutureOr<dynamic>>>>() x346;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends A<FconBound<FutureOr<void>>>>() x347;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends A<FconBound<FutureOr<Object?>>>>() x348;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  void Function<Y extends A<FconCyclicBound<dynamic>>>() x349;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<void>>>() x350;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<Object?>>>() x351;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<FutureOr<dynamic>>>>() x352;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<FutureOr<void>>>>() x353;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<FutureOr<Object?>>>>() x354;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<dynamic>>>>() x355;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<void>>>>() x356;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<Object?>>>>() x357;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<FutureOr<dynamic>>>>>() x358;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<FutureOr<void>>>>>() x359;
+//^
+// [analyzer] unspecified
+//                                                                 ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<FutureOr<Object?>>>>>() x360;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<A<dynamic>>>>>() x361;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<A<void>>>>>() x362;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<A<Object?>>>>>() x363;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<A<FutureOr<dynamic>>>>>>() x364;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<A<FutureOr<void>>>>>>() x365;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicBound<A<A<FutureOr<Object?>>>>>>() x366;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  void Function<Y extends A<FconCyclicCoBound<dynamic>>>() x367;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconCyclicCoBound<void>>>() x368;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconCyclicCoBound<Object?>>>() x369;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconCyclicCoBound<FutureOr<dynamic>>>>() x370;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconCyclicCoBound<FutureOr<void>>>>() x371;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconCyclicCoBound<FutureOr<Object?>>>>() x372;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconCyclicCoBound<Function(Function(dynamic))>>>()
+//^
+// [analyzer] unspecified
+      x373;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconCyclicCoBound<Function(Function(void))>>>()
+//^
+// [analyzer] unspecified
+      x374;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<Y extends A<FconCyclicCoBound<Function(Function(Object?))>>>()
+//^
+// [analyzer] unspecified
+      x375;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<
+      Y extends A<
+          FconCyclicCoBound<Function(Function(FutureOr<dynamic>))>>>() x376;
+//^
+// [analyzer] unspecified
+//                                                                     ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<
+          Y extends A<FconCyclicCoBound<Function(Function(FutureOr<void>))>>>()
+//^
+// [analyzer] unspecified
+      x377;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  void Function<
+      Y extends A<
+          FconCyclicCoBound<Function(Function(FutureOr<Object?>))>>>() x378;
+//^
+// [analyzer] unspecified
+//                                                                     ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconBound<dynamic>> x379;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Finv<FconBound<void>> x380;
+//^
+// [analyzer] unspecified
+//                      ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Finv<FconBound<Object?>> x381;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Finv<FconBound<FutureOr<dynamic>>> x382;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Finv<FconBound<FutureOr<void>>> x383;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Finv<FconBound<FutureOr<Object?>>> x384;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Finv<FconCyclicBound<dynamic>> x385;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<void>> x386;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<Object?>> x387;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<FutureOr<dynamic>>> x388;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<FutureOr<void>>> x389;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<FutureOr<Object?>>> x390;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<dynamic>>> x391;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<void>>> x392;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<Object?>>> x393;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<FutureOr<dynamic>>>> x394;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<FutureOr<void>>>> x395;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<FutureOr<Object?>>>> x396;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<A<dynamic>>>> x397;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<A<void>>>> x398;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<A<Object?>>>> x399;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<A<FutureOr<dynamic>>>>> x400;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<A<FutureOr<void>>>>> x401;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicBound<A<A<FutureOr<Object?>>>>> x402;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Finv<FconCyclicCoBound<dynamic>> x403;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<void>> x404;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<Object?>> x405;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<FutureOr<dynamic>>> x406;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<FutureOr<void>>> x407;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<FutureOr<Object?>>> x408;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<Function(Function(dynamic))>> x409;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<Function(Function(void))>> x410;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<Function(Function(Object?))>> x411;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x412;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<Function(Function(FutureOr<void>))>> x413;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Finv<FconCyclicCoBound<Function(Function(FutureOr<Object?>))>> x414;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconBound<dynamic>> x415;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Funu<FconBound<void>> x416;
+//^
+// [analyzer] unspecified
+//                      ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Funu<FconBound<Object?>> x417;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Funu<FconBound<FutureOr<dynamic>>> x418;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Funu<FconBound<FutureOr<void>>> x419;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Funu<FconBound<FutureOr<Object?>>> x420;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'num' of the type variable 'X' on 'FconBound'.
+  Funu<FconCyclicBound<dynamic>> x421;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<void>> x422;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<Object?>> x423;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<FutureOr<dynamic>>> x424;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<FutureOr<void>>> x425;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<FutureOr<Object?>>> x426;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<dynamic>>> x427;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'A<dynamic>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<void>>> x428;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'A<void>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<Object?>>> x429;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<FutureOr<dynamic>>>> x430;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'A<FutureOr<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<FutureOr<void>>>> x431;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<FutureOr<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<FutureOr<Object?>>>> x432;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'A<FutureOr<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<A<dynamic>>>> x433;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'A<A<dynamic>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<A<void>>>> x434;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'A<A<void>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<A<Object?>>>> x435;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'A<A<Object?>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<A<FutureOr<dynamic>>>>> x436;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'A<A<FutureOr<dynamic>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<A<FutureOr<void>>>>> x437;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'A<A<FutureOr<void>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicBound<A<A<FutureOr<Object?>>>>> x438;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'A<A<FutureOr<Object?>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FconCyclicBound'.
+  Funu<FconCyclicCoBound<dynamic>> x439;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'dynamic' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<void>> x440;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'void' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<Object?>> x441;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'Object?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<FutureOr<dynamic>>> x442;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<dynamic>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<FutureOr<void>>> x443;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<void>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<FutureOr<Object?>>> x444;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<Object?>?' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<Function(Function(dynamic))>> x445;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(dynamic))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<Function(Function(void))>> x446;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(void))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<Function(Function(Object?))>> x447;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object?))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x448;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<dynamic>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<Function(Function(FutureOr<void>))>> x449;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<void>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+  Funu<FconCyclicCoBound<Function(Function(FutureOr<Object?>))>> x450;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object?>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FconCyclicCoBound'.
+}
+
+void main() {
+  testContravariantSuperboundError<Null>();
+}
diff --git a/tests/language/generic/super_bounded_types_error_test.dart b/tests/language/generic/super_bounded_types_error_test.dart
new file mode 100644
index 0000000..63434cd
--- /dev/null
+++ b/tests/language/generic/super_bounded_types_error_test.dart
@@ -0,0 +1,3195 @@
+// 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.
+
+// Test that various types cause an error when it violates its bounds and
+// is not correctly super-bounded.
+
+import 'dart:async';
+
+class A<X> {}
+
+class B<X extends B<X>> extends A<X> {}
+
+typedef F<X> = void Function<Y extends X>();
+F<X> toF<X>(X x) => throw 0;
+
+typedef Fcov<X> = X Function();
+typedef Fcon<X> = Function(X);
+typedef Finv<X> = X Function(X);
+typedef Funu<X> = Function();
+
+typedef FcovBound<X extends num> = X Function();
+typedef FconBound<X extends num> = Function(X);
+typedef FinvBound<X extends num> = X Function(X);
+typedef FunuBound<X extends num> = Function();
+
+typedef FcovCyclicBound<X extends A<X>> = X Function();
+typedef FconCyclicBound<X extends A<X>> = Function(X);
+typedef FinvCyclicBound<X extends A<X>> = X Function(X);
+typedef FunuCyclicBound<X extends A<X>> = Function();
+
+typedef FcovCyclicCoBound<X extends Function(X)> = X Function();
+typedef FconCyclicCoBound<X extends Function(X)> = Function(X);
+typedef FinvCyclicCoBound<X extends Function(X)> = X Function(X);
+typedef FunuCyclicCoBound<X extends Function(X)> = Function();
+
+class AcovCyclicCoBound<X extends FcovCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class AconCyclicCoBound<X extends FconCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class AinvCyclicCoBound<X extends FinvCyclicCoBound<Y>, Y extends Function(Y)> {
+}
+
+class CFcov<X extends Fcov<X>> {}
+
+class CFcon<X extends Fcon<X>> {}
+
+class CFinv<X extends Finv<X>> {}
+
+class CFunu<X extends Funu<X>> {}
+
+class CcovBound<X extends num> {}
+
+class CcovCyclicBound<X extends A<X>> {}
+
+class CcovCyclicCoBound<X extends Function(X)> {}
+
+void testCovariantSuperboundError<N extends Null>() {
+  // --- Near-top type in a covariant position, not super-bounded.
+  FcovBound<Object> x1;
+//^
+// [analyzer] unspecified
+//                  ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  FcovBound<FutureOr<Object>> x2;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  FcovCyclicBound<Object> x3;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<FutureOr<Object>> x4;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<A<Object>> x5;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<A<FutureOr<Object>>> x6;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<A<A<Object>>> x7;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<A<A<FutureOr<Object>>>> x8;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicCoBound<Object> x9;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<FutureOr<Object>> x10;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(Function(Object))> x11;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(Function(FutureOr<Object>))> x12;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  CFcov<Object> x13;
+//^
+// [analyzer] unspecified
+//              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<FutureOr<Object>> x14;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<Fcov<Object>> x15;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<Fcov<FutureOr<Object>>> x16;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<Fcov<Fcov<Object>>> x17;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<Fcov<Fcov<FutureOr<Object>>>> x18;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcon<Object> x19;
+//^
+// [analyzer] unspecified
+//              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CFcon<FutureOr<Object>> x20;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CFinv<Object> x21;
+//^
+// [analyzer] unspecified
+//              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  CFinv<FutureOr<Object>> x22;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  CFunu<Object> x23;
+//^
+// [analyzer] unspecified
+//              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  CFunu<FutureOr<Object>> x24;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  CcovBound<Object> x25;
+//^
+// [analyzer] unspecified
+//                  ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  CcovBound<FutureOr<Object>> x26;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  CcovCyclicBound<Object> x27;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<FutureOr<Object>> x28;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<A<Object>> x29;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<A<FutureOr<Object>>> x30;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<A<A<Object>>> x31;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<A<A<FutureOr<Object>>>> x32;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicCoBound<Object> x33;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<FutureOr<Object>> x34;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<Function(Function(Object))> x35;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<Function(Function(FutureOr<Object>))> x36;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+
+  // --- Same non-super-bounded types in a context.
+  A<FcovBound<Object>> x37;
+//^
+// [analyzer] unspecified
+//                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  A<FcovBound<FutureOr<Object>>> x38;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  A<FcovCyclicBound<Object>> x39;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  A<FcovCyclicBound<FutureOr<Object>>> x40;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  A<FcovCyclicBound<A<Object>>> x41;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  A<FcovCyclicBound<A<FutureOr<Object>>>> x42;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  A<FcovCyclicBound<A<A<Object>>>> x43;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  A<FcovCyclicBound<A<A<FutureOr<Object>>>>> x44;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  A<FcovCyclicCoBound<Object>> x45;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  A<FcovCyclicCoBound<FutureOr<Object>>> x46;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  A<FcovCyclicCoBound<Function(Function(Object))>> x47;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  A<FcovCyclicCoBound<Function(Function(FutureOr<Object>))>> x48;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  A<CFcov<Object>> x49;
+//^
+// [analyzer] unspecified
+//                 ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  A<CFcov<FutureOr<Object>>> x50;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  A<CFcov<Fcov<Object>>> x51;
+//^
+// [analyzer] unspecified
+//                       ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  A<CFcov<Fcov<FutureOr<Object>>>> x52;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  A<CFcov<Fcov<Fcov<Object>>>> x53;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  A<CFcov<Fcov<Fcov<FutureOr<Object>>>>> x54;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  A<CFcon<Object>> x55;
+//^
+// [analyzer] unspecified
+//                 ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  A<CFcon<FutureOr<Object>>> x56;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  A<CFinv<Object>> x57;
+//^
+// [analyzer] unspecified
+//                 ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  A<CFinv<FutureOr<Object>>> x58;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  A<CFunu<Object>> x59;
+//^
+// [analyzer] unspecified
+//                 ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  A<CFunu<FutureOr<Object>>> x60;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  A<CcovBound<Object>> x61;
+//^
+// [analyzer] unspecified
+//                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  A<CcovBound<FutureOr<Object>>> x62;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  A<CcovCyclicBound<Object>> x63;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  A<CcovCyclicBound<FutureOr<Object>>> x64;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  A<CcovCyclicBound<A<Object>>> x65;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  A<CcovCyclicBound<A<FutureOr<Object>>>> x66;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  A<CcovCyclicBound<A<A<Object>>>> x67;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  A<CcovCyclicBound<A<A<FutureOr<Object>>>>> x68;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  A<CcovCyclicCoBound<Object>> x69;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  A<CcovCyclicCoBound<FutureOr<Object>>> x70;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  A<CcovCyclicCoBound<Function(Function(Object))>> x71;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  A<CcovCyclicCoBound<Function(Function(FutureOr<Object>))>> x72;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  FcovBound<Object> Function() x73;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  FcovBound<FutureOr<Object>> Function() x74;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  FcovCyclicBound<Object> Function() x75;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<FutureOr<Object>> Function() x76;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<A<Object>> Function() x77;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<A<FutureOr<Object>>> Function() x78;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<A<A<Object>>> Function() x79;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicBound<A<A<FutureOr<Object>>>> Function() x80;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  FcovCyclicCoBound<Object> Function() x81;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<FutureOr<Object>> Function() x82;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(Function(Object))> Function() x83;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  FcovCyclicCoBound<Function(Function(FutureOr<Object>))> Function() x84;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  CFcov<Object> Function() x85;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<FutureOr<Object>> Function() x86;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<Fcov<Object>> Function() x87;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<Fcov<FutureOr<Object>>> Function() x88;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<Fcov<Fcov<Object>>> Function() x89;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcov<Fcov<Fcov<FutureOr<Object>>>> Function() x90;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  CFcon<Object> Function() x91;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CFcon<FutureOr<Object>> Function() x92;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  CFinv<Object> Function() x93;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  CFinv<FutureOr<Object>> Function() x94;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  CFunu<Object> Function() x95;
+//^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  CFunu<FutureOr<Object>> Function() x96;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  CcovBound<Object> Function() x97;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  CcovBound<FutureOr<Object>> Function() x98;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  CcovCyclicBound<Object> Function() x99;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<FutureOr<Object>> Function() x100;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<A<Object>> Function() x101;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<A<FutureOr<Object>>> Function() x102;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<A<A<Object>>> Function() x103;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicBound<A<A<FutureOr<Object>>>> Function() x104;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  CcovCyclicCoBound<Object> Function() x105;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<FutureOr<Object>> Function() x106;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<Function(Function(Object))> Function() x107;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  CcovCyclicCoBound<Function(Function(FutureOr<Object>))> Function() x108;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(void Function(FcovBound<Object>)) x109;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function(void Function(FcovBound<FutureOr<Object>>)) x110;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function(void Function(FcovCyclicBound<Object>)) x111;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(void Function(FcovCyclicBound<FutureOr<Object>>)) x112;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(void Function(FcovCyclicBound<A<Object>>)) x113;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(void Function(FcovCyclicBound<A<FutureOr<Object>>>)) x114;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(void Function(FcovCyclicBound<A<A<Object>>>)) x115;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(void Function(FcovCyclicBound<A<A<FutureOr<Object>>>>)) x116;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(void Function(FcovCyclicCoBound<Object>)) x117;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(void Function(FcovCyclicCoBound<FutureOr<Object>>)) x118;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(void Function(FcovCyclicCoBound<Function(Function(Object))>))
+//^
+// [analyzer] unspecified
+      x119;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(
+      void Function(
+          FcovCyclicCoBound<Function(Function(FutureOr<Object>))>)) x120;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(void Function(CFcov<Object>)) x121;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(void Function(CFcov<FutureOr<Object>>)) x122;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(void Function(CFcov<Fcov<Object>>)) x123;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(void Function(CFcov<Fcov<FutureOr<Object>>>)) x124;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(void Function(CFcov<Fcov<Fcov<Object>>>)) x125;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(void Function(CFcov<Fcov<Fcov<FutureOr<Object>>>>)) x126;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(void Function(CFcon<Object>)) x127;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(void Function(CFcon<FutureOr<Object>>)) x128;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(void Function(CFinv<Object>)) x129;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function(void Function(CFinv<FutureOr<Object>>)) x130;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function(void Function(CFunu<Object>)) x131;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function(void Function(CFunu<FutureOr<Object>>)) x132;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function(void Function(CcovBound<Object>)) x133;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function(void Function(CcovBound<FutureOr<Object>>)) x134;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function(void Function(CcovCyclicBound<Object>)) x135;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(void Function(CcovCyclicBound<FutureOr<Object>>)) x136;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(void Function(CcovCyclicBound<A<Object>>)) x137;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(void Function(CcovCyclicBound<A<FutureOr<Object>>>)) x138;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(void Function(CcovCyclicBound<A<A<Object>>>)) x139;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(void Function(CcovCyclicBound<A<A<FutureOr<Object>>>>)) x140;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(void Function(CcovCyclicCoBound<Object>)) x141;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(void Function(CcovCyclicCoBound<FutureOr<Object>>)) x142;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(void Function(CcovCyclicCoBound<Function(Function(Object))>))
+//^
+// [analyzer] unspecified
+      x143;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(
+      void Function(
+          CcovCyclicCoBound<Function(Function(FutureOr<Object>))>)) x144;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(FcovBound<Object>) x145;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function(FcovBound<FutureOr<Object>>) x146;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function(FcovCyclicBound<Object>) x147;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<FutureOr<Object>>) x148;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<A<Object>>) x149;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<A<FutureOr<Object>>>) x150;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<A<A<Object>>>) x151;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<A<A<FutureOr<Object>>>>) x152;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicCoBound<Object>) x153;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<FutureOr<Object>>) x154;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(Function(Object))>) x155;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(Function(FutureOr<Object>))>) x156;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(CFcov<Object>) x157;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<FutureOr<Object>>) x158;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<Fcov<Object>>) x159;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<Fcov<FutureOr<Object>>>) x160;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<Fcov<Fcov<Object>>>) x161;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<Fcov<Fcov<FutureOr<Object>>>>) x162;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcon<Object>) x163;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CFcon<FutureOr<Object>>) x164;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CFinv<Object>) x165;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function(CFinv<FutureOr<Object>>) x166;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function(CFunu<Object>) x167;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function(CFunu<FutureOr<Object>>) x168;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function(CcovBound<Object>) x169;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function(CcovBound<FutureOr<Object>>) x170;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function(CcovCyclicBound<Object>) x171;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<FutureOr<Object>>) x172;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<A<Object>>) x173;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<A<FutureOr<Object>>>) x174;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<A<A<Object>>>) x175;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<A<A<FutureOr<Object>>>>) x176;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicCoBound<Object>) x177;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<FutureOr<Object>>) x178;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<Function(Function(Object))>) x179;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<Function(Function(FutureOr<Object>))>) x180;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(FcovBound<Object>) Function() x181;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function(FcovBound<FutureOr<Object>>) Function() x182;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function(FcovCyclicBound<Object>) Function() x183;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<FutureOr<Object>>) Function() x184;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<A<Object>>) Function() x185;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<A<FutureOr<Object>>>) Function() x186;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<A<A<Object>>>) Function() x187;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicBound<A<A<FutureOr<Object>>>>) Function() x188;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function(FcovCyclicCoBound<Object>) Function() x189;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<FutureOr<Object>>) Function() x190;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(Function(Object))>) Function() x191;
+//^
+// [analyzer] unspecified
+//                                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(FcovCyclicCoBound<Function(Function(FutureOr<Object>))>)
+//^
+// [analyzer] unspecified
+      Function() x192;
+//               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function(CFcov<Object>) Function() x193;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<FutureOr<Object>>) Function() x194;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<Fcov<Object>>) Function() x195;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<Fcov<FutureOr<Object>>>) Function() x196;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<Fcov<Fcov<Object>>>) Function() x197;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcov<Fcov<Fcov<FutureOr<Object>>>>) Function() x198;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function(CFcon<Object>) Function() x199;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CFcon<FutureOr<Object>>) Function() x200;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function(CFinv<Object>) Function() x201;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function(CFinv<FutureOr<Object>>) Function() x202;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function(CFunu<Object>) Function() x203;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function(CFunu<FutureOr<Object>>) Function() x204;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function(CcovBound<Object>) Function() x205;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function(CcovBound<FutureOr<Object>>) Function() x206;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function(CcovCyclicBound<Object>) Function() x207;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<FutureOr<Object>>) Function() x208;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<A<Object>>) Function() x209;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<A<FutureOr<Object>>>) Function() x210;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<A<A<Object>>>) Function() x211;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicBound<A<A<FutureOr<Object>>>>) Function() x212;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function(CcovCyclicCoBound<Object>) Function() x213;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<FutureOr<Object>>) Function() x214;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<Function(Function(Object))>) Function() x215;
+//^
+// [analyzer] unspecified
+//                                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function(CcovCyclicCoBound<Function(Function(FutureOr<Object>))>)
+//^
+// [analyzer] unspecified
+      Function() x216;
+//               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends FcovBound<Object>>() x217;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function<Y extends FcovBound<FutureOr<Object>>>() x218;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function<Y extends FcovCyclicBound<Object>>() x219;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends FcovCyclicBound<FutureOr<Object>>>() x220;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends FcovCyclicBound<A<Object>>>() x221;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends FcovCyclicBound<A<FutureOr<Object>>>>() x222;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends FcovCyclicBound<A<A<Object>>>>() x223;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends FcovCyclicBound<A<A<FutureOr<Object>>>>>() x224;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends FcovCyclicCoBound<Object>>() x225;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends FcovCyclicCoBound<FutureOr<Object>>>() x226;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends FcovCyclicCoBound<Function(Function(Object))>>() x227;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<
+      Y extends FcovCyclicCoBound<Function(Function(FutureOr<Object>))>>() x228;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends CFcov<Object>>() x229;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends CFcov<FutureOr<Object>>>() x230;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends CFcov<Fcov<Object>>>() x231;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends CFcov<Fcov<FutureOr<Object>>>>() x232;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends CFcov<Fcov<Fcov<Object>>>>() x233;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends CFcov<Fcov<Fcov<FutureOr<Object>>>>>() x234;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends CFcon<Object>>() x235;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends CFcon<FutureOr<Object>>>() x236;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends CFinv<Object>>() x237;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function<Y extends CFinv<FutureOr<Object>>>() x238;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function<Y extends CFunu<Object>>() x239;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function<Y extends CFunu<FutureOr<Object>>>() x240;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function<Y extends CcovBound<Object>>() x241;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function<Y extends CcovBound<FutureOr<Object>>>() x242;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function<Y extends CcovCyclicBound<Object>>() x243;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends CcovCyclicBound<FutureOr<Object>>>() x244;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends CcovCyclicBound<A<Object>>>() x245;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends CcovCyclicBound<A<FutureOr<Object>>>>() x246;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends CcovCyclicBound<A<A<Object>>>>() x247;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends CcovCyclicBound<A<A<FutureOr<Object>>>>>() x248;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends CcovCyclicCoBound<Object>>() x249;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends CcovCyclicCoBound<FutureOr<Object>>>() x250;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends CcovCyclicCoBound<Function(Function(Object))>>() x251;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<
+      Y extends CcovCyclicCoBound<Function(Function(FutureOr<Object>))>>() x252;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends A<FcovBound<Object>>>() x253;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function<Y extends A<FcovBound<FutureOr<Object>>>>() x254;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  void Function<Y extends A<FcovCyclicBound<Object>>>() x255;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends A<FcovCyclicBound<FutureOr<Object>>>>() x256;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends A<FcovCyclicBound<A<Object>>>>() x257;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends A<FcovCyclicBound<A<FutureOr<Object>>>>>() x258;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends A<FcovCyclicBound<A<A<Object>>>>>() x259;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends A<FcovCyclicBound<A<A<FutureOr<Object>>>>>>() x260;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  void Function<Y extends A<FcovCyclicCoBound<Object>>>() x261;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends A<FcovCyclicCoBound<FutureOr<Object>>>>() x262;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends A<FcovCyclicCoBound<Function(Function(Object))>>>()
+//^
+// [analyzer] unspecified
+      x263;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<
+      Y extends A<
+          FcovCyclicCoBound<Function(Function(FutureOr<Object>))>>>() x264;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  void Function<Y extends A<CFcov<Object>>>() x265;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends A<CFcov<FutureOr<Object>>>>() x266;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends A<CFcov<Fcov<Object>>>>() x267;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends A<CFcov<Fcov<FutureOr<Object>>>>>() x268;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends A<CFcov<Fcov<Fcov<Object>>>>>() x269;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends A<CFcov<Fcov<Fcov<FutureOr<Object>>>>>>() x270;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  void Function<Y extends A<CFcon<Object>>>() x271;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends A<CFcon<FutureOr<Object>>>>() x272;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  void Function<Y extends A<CFinv<Object>>>() x273;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function<Y extends A<CFinv<FutureOr<Object>>>>() x274;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  void Function<Y extends A<CFunu<Object>>>() x275;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function<Y extends A<CFunu<FutureOr<Object>>>>() x276;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  void Function<Y extends A<CcovBound<Object>>>() x277;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function<Y extends A<CcovBound<FutureOr<Object>>>>() x278;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  void Function<Y extends A<CcovCyclicBound<Object>>>() x279;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends A<CcovCyclicBound<FutureOr<Object>>>>() x280;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends A<CcovCyclicBound<A<Object>>>>() x281;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends A<CcovCyclicBound<A<FutureOr<Object>>>>>() x282;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends A<CcovCyclicBound<A<A<Object>>>>>() x283;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends A<CcovCyclicBound<A<A<FutureOr<Object>>>>>>() x284;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  void Function<Y extends A<CcovCyclicCoBound<Object>>>() x285;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends A<CcovCyclicCoBound<FutureOr<Object>>>>() x286;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<Y extends A<CcovCyclicCoBound<Function(Function(Object))>>>()
+//^
+// [analyzer] unspecified
+      x287;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  void Function<
+      Y extends A<
+          CcovCyclicCoBound<Function(Function(FutureOr<Object>))>>>() x288;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Finv<FcovBound<Object>> x289;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  Finv<FcovBound<FutureOr<Object>>> x290;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  Finv<FcovCyclicBound<Object>> x291;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Finv<FcovCyclicBound<FutureOr<Object>>> x292;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Finv<FcovCyclicBound<A<Object>>> x293;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Finv<FcovCyclicBound<A<FutureOr<Object>>>> x294;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Finv<FcovCyclicBound<A<A<Object>>>> x295;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Finv<FcovCyclicBound<A<A<FutureOr<Object>>>>> x296;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Finv<FcovCyclicCoBound<Object>> x297;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Finv<FcovCyclicCoBound<FutureOr<Object>>> x298;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Finv<FcovCyclicCoBound<Function(Function(Object))>> x299;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Finv<FcovCyclicCoBound<Function(Function(FutureOr<Object>))>> x300;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Finv<CFcov<Object>> x301;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Finv<CFcov<FutureOr<Object>>> x302;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Finv<CFcov<Fcov<Object>>> x303;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Finv<CFcov<Fcov<FutureOr<Object>>>> x304;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Finv<CFcov<Fcov<Fcov<Object>>>> x305;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Finv<CFcov<Fcov<Fcov<FutureOr<Object>>>>> x306;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Finv<CFcon<Object>> x307;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Finv<CFcon<FutureOr<Object>>> x308;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Finv<CFinv<Object>> x309;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  Finv<CFinv<FutureOr<Object>>> x310;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  Finv<CFunu<Object>> x311;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  Finv<CFunu<FutureOr<Object>>> x312;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  Finv<CcovBound<Object>> x313;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  Finv<CcovBound<FutureOr<Object>>> x314;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  Finv<CcovCyclicBound<Object>> x315;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Finv<CcovCyclicBound<FutureOr<Object>>> x316;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Finv<CcovCyclicBound<A<Object>>> x317;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Finv<CcovCyclicBound<A<FutureOr<Object>>>> x318;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Finv<CcovCyclicBound<A<A<Object>>>> x319;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Finv<CcovCyclicBound<A<A<FutureOr<Object>>>>> x320;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Finv<CcovCyclicCoBound<Object>> x321;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Finv<CcovCyclicCoBound<FutureOr<Object>>> x322;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Finv<CcovCyclicCoBound<Function(Function(Object))>> x323;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Finv<CcovCyclicCoBound<Function(Function(FutureOr<Object>))>> x324;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Funu<FcovBound<Object>> x325;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  Funu<FcovBound<FutureOr<Object>>> x326;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FcovBound'.
+  Funu<FcovCyclicBound<Object>> x327;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Funu<FcovCyclicBound<FutureOr<Object>>> x328;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Funu<FcovCyclicBound<A<Object>>> x329;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Funu<FcovCyclicBound<A<FutureOr<Object>>>> x330;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Funu<FcovCyclicBound<A<A<Object>>>> x331;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Funu<FcovCyclicBound<A<A<FutureOr<Object>>>>> x332;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FcovCyclicBound'.
+  Funu<FcovCyclicCoBound<Object>> x333;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Funu<FcovCyclicCoBound<FutureOr<Object>>> x334;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Funu<FcovCyclicCoBound<Function(Function(Object))>> x335;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Funu<FcovCyclicCoBound<Function(Function(FutureOr<Object>))>> x336;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FcovCyclicCoBound'.
+  Funu<CFcov<Object>> x337;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Funu<CFcov<FutureOr<Object>>> x338;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Funu<CFcov<Fcov<Object>>> x339;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'Object Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Funu<CFcov<Fcov<FutureOr<Object>>>> x340;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'FutureOr<Object> Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Funu<CFcov<Fcov<Fcov<Object>>>> x341;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Funu<CFcov<Fcov<Fcov<FutureOr<Object>>>>> x342;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object> Function() Function()' doesn't conform to the bound 'X Function()' of the type variable 'X' on 'CFcov'.
+  Funu<CFcon<Object>> x343;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Funu<CFcon<FutureOr<Object>>> x344;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CFcon'.
+  Funu<CFinv<Object>> x345;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  Funu<CFinv<FutureOr<Object>>> x346;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'X Function(X)' of the type variable 'X' on 'CFinv'.
+  Funu<CFunu<Object>> x347;
+//^
+// [analyzer] unspecified
+//                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  Funu<CFunu<FutureOr<Object>>> x348;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function()' of the type variable 'X' on 'CFunu'.
+  Funu<CcovBound<Object>> x349;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  Funu<CcovBound<FutureOr<Object>>> x350;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'CcovBound'.
+  Funu<CcovCyclicBound<Object>> x351;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Funu<CcovCyclicBound<FutureOr<Object>>> x352;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Funu<CcovCyclicBound<A<Object>>> x353;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Funu<CcovCyclicBound<A<FutureOr<Object>>>> x354;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Funu<CcovCyclicBound<A<A<Object>>>> x355;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Funu<CcovCyclicBound<A<A<FutureOr<Object>>>>> x356;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'CcovCyclicBound'.
+  Funu<CcovCyclicCoBound<Object>> x357;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Funu<CcovCyclicCoBound<FutureOr<Object>>> x358;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Funu<CcovCyclicCoBound<Function(Function(Object))>> x359;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+  Funu<CcovCyclicCoBound<Function(Function(FutureOr<Object>))>> x360;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'CcovCyclicCoBound'.
+}
+
+void testInvariantSuperboundError<N extends Null>() {
+  // --- Near-top type in an invariant position, not super-bounded.
+  FinvBound<Object> x1;
+//^
+// [analyzer] unspecified
+//                  ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  FinvBound<FutureOr<Object>> x2;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  FinvCyclicBound<Object> x3;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<FutureOr<Object>> x4;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<A<Object>> x5;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<A<FutureOr<Object>>> x6;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<A<A<Object>>> x7;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<A<A<FutureOr<Object>>>> x8;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicCoBound<Object> x9;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  FinvCyclicCoBound<FutureOr<Object>> x10;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  FinvCyclicCoBound<Function(Function(Object))> x11;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  FinvCyclicCoBound<Function(Function(FutureOr<Object>))> x12;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+
+  // --- Same non-super-bounded types in a context.
+  A<FinvBound<Object>> x13;
+//^
+// [analyzer] unspecified
+//                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  A<FinvBound<FutureOr<Object>>> x14;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  A<FinvCyclicBound<Object>> x15;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  A<FinvCyclicBound<FutureOr<Object>>> x16;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  A<FinvCyclicBound<A<Object>>> x17;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  A<FinvCyclicBound<A<FutureOr<Object>>>> x18;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  A<FinvCyclicBound<A<A<Object>>>> x19;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  A<FinvCyclicBound<A<A<FutureOr<Object>>>>> x20;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  A<FinvCyclicCoBound<Object>> x21;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  A<FinvCyclicCoBound<FutureOr<Object>>> x22;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  A<FinvCyclicCoBound<Function(Function(Object))>> x23;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  A<FinvCyclicCoBound<Function(Function(FutureOr<Object>))>> x24;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  FinvBound<Object> Function() x25;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  FinvBound<FutureOr<Object>> Function() x26;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  FinvCyclicBound<Object> Function() x27;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<FutureOr<Object>> Function() x28;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<A<Object>> Function() x29;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<A<FutureOr<Object>>> Function() x30;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<A<A<Object>>> Function() x31;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicBound<A<A<FutureOr<Object>>>> Function() x32;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  FinvCyclicCoBound<Object> Function() x33;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  FinvCyclicCoBound<FutureOr<Object>> Function() x34;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  FinvCyclicCoBound<Function(Function(Object))> Function() x35;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  FinvCyclicCoBound<Function(Function(FutureOr<Object>))> Function() x36;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(void Function(FinvBound<Object>)) x37;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function(void Function(FinvBound<FutureOr<Object>>)) x38;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function(void Function(FinvCyclicBound<Object>)) x39;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(void Function(FinvCyclicBound<FutureOr<Object>>)) x40;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(void Function(FinvCyclicBound<A<Object>>)) x41;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(void Function(FinvCyclicBound<A<FutureOr<Object>>>)) x42;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(void Function(FinvCyclicBound<A<A<Object>>>)) x43;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(void Function(FinvCyclicBound<A<A<FutureOr<Object>>>>)) x44;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(void Function(FinvCyclicCoBound<Object>)) x45;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(void Function(FinvCyclicCoBound<FutureOr<Object>>)) x46;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(void Function(FinvCyclicCoBound<Function(Function(Object))>))
+//^
+// [analyzer] unspecified
+      x47;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(
+      void Function(
+          FinvCyclicCoBound<Function(Function(FutureOr<Object>))>)) x48;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(FinvBound<Object>) x49;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function(FinvBound<FutureOr<Object>>) x50;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function(FinvCyclicBound<Object>) x51;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<FutureOr<Object>>) x52;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<A<Object>>) x53;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<A<FutureOr<Object>>>) x54;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<A<A<Object>>>) x55;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<A<A<FutureOr<Object>>>>) x56;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicCoBound<Object>) x57;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(FinvCyclicCoBound<FutureOr<Object>>) x58;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(FinvCyclicCoBound<Function(Function(Object))>) x59;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(FinvCyclicCoBound<Function(Function(FutureOr<Object>))>) x60;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(FinvBound<Object>) Function() x61;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function(FinvBound<FutureOr<Object>>) Function() x62;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function(FinvCyclicBound<Object>) Function() x63;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<FutureOr<Object>>) Function() x64;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<A<Object>>) Function() x65;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<A<FutureOr<Object>>>) Function() x66;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<A<A<Object>>>) Function() x67;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicBound<A<A<FutureOr<Object>>>>) Function() x68;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function(FinvCyclicCoBound<Object>) Function() x69;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(FinvCyclicCoBound<FutureOr<Object>>) Function() x70;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(FinvCyclicCoBound<Function(Function(Object))>) Function() x71;
+//^
+// [analyzer] unspecified
+//                                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function(FinvCyclicCoBound<Function(Function(FutureOr<Object>))>)
+//^
+// [analyzer] unspecified
+      Function() x72;
+//               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function<Y extends FinvBound<Object>>() x73;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function<Y extends FinvBound<FutureOr<Object>>>() x74;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function<Y extends FinvCyclicBound<Object>>() x75;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends FinvCyclicBound<FutureOr<Object>>>() x76;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends FinvCyclicBound<A<Object>>>() x77;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends FinvCyclicBound<A<FutureOr<Object>>>>() x78;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends FinvCyclicBound<A<A<Object>>>>() x79;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends FinvCyclicBound<A<A<FutureOr<Object>>>>>() x80;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends FinvCyclicCoBound<Object>>() x81;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function<Y extends FinvCyclicCoBound<FutureOr<Object>>>() x82;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function<Y extends FinvCyclicCoBound<Function(Function(Object))>>() x83;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function<
+      Y extends FinvCyclicCoBound<Function(Function(FutureOr<Object>))>>() x84;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function<Y extends A<FinvBound<Object>>>() x85;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function<Y extends A<FinvBound<FutureOr<Object>>>>() x86;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  void Function<Y extends A<FinvCyclicBound<Object>>>() x87;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends A<FinvCyclicBound<FutureOr<Object>>>>() x88;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends A<FinvCyclicBound<A<Object>>>>() x89;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends A<FinvCyclicBound<A<FutureOr<Object>>>>>() x90;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends A<FinvCyclicBound<A<A<Object>>>>>() x91;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends A<FinvCyclicBound<A<A<FutureOr<Object>>>>>>() x92;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  void Function<Y extends A<FinvCyclicCoBound<Object>>>() x93;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function<Y extends A<FinvCyclicCoBound<FutureOr<Object>>>>() x94;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function<Y extends A<FinvCyclicCoBound<Function(Function(Object))>>>()
+//^
+// [analyzer] unspecified
+      x95;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  void Function<
+      Y extends A<
+          FinvCyclicCoBound<Function(Function(FutureOr<Object>))>>>() x96;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  Finv<FinvBound<Object>> x97;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  Finv<FinvBound<FutureOr<Object>>> x98;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  Finv<FinvCyclicBound<Object>> x99;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Finv<FinvCyclicBound<FutureOr<Object>>> x100;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Finv<FinvCyclicBound<A<Object>>> x101;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Finv<FinvCyclicBound<A<FutureOr<Object>>>> x102;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Finv<FinvCyclicBound<A<A<Object>>>> x103;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Finv<FinvCyclicBound<A<A<FutureOr<Object>>>>> x104;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Finv<FinvCyclicCoBound<Object>> x105;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  Finv<FinvCyclicCoBound<FutureOr<Object>>> x106;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  Finv<FinvCyclicCoBound<Function(Function(Object))>> x107;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  Finv<FinvCyclicCoBound<Function(Function(FutureOr<Object>))>> x108;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  Funu<FinvBound<Object>> x109;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  Funu<FinvBound<FutureOr<Object>>> x110;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FinvBound'.
+  Funu<FinvCyclicBound<Object>> x111;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Funu<FinvCyclicBound<FutureOr<Object>>> x112;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Funu<FinvCyclicBound<A<Object>>> x113;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Funu<FinvCyclicBound<A<FutureOr<Object>>>> x114;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Funu<FinvCyclicBound<A<A<Object>>>> x115;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Funu<FinvCyclicBound<A<A<FutureOr<Object>>>>> x116;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FinvCyclicBound'.
+  Funu<FinvCyclicCoBound<Object>> x117;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  Funu<FinvCyclicCoBound<FutureOr<Object>>> x118;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  Funu<FinvCyclicCoBound<Function(Function(Object))>> x119;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  Funu<FinvCyclicCoBound<Function(Function(FutureOr<Object>))>> x120;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+}
+
+void testVarianceLessSuperboundError<N extends Null>() {
+  // --- Near-top type in a variance-less position, not super-bounded.
+  FunuBound<Object> x1;
+//^
+// [analyzer] unspecified
+//                  ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  FunuBound<FutureOr<Object>> x2;
+//^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  FunuCyclicBound<Object> x3;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<FutureOr<Object>> x4;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<A<Object>> x5;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<A<FutureOr<Object>>> x6;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<A<A<Object>>> x7;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<A<A<FutureOr<Object>>>> x8;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicCoBound<Object> x9;
+//^
+// [analyzer] unspecified
+//                          ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  FunuCyclicCoBound<FutureOr<Object>> x10;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  FunuCyclicCoBound<Function(Function(Object))> x13;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  FunuCyclicCoBound<Function(Function(FutureOr<Object>))> x14;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+
+  // --- Same non-super-bounded types in a context.
+  A<FunuBound<Object>> x19;
+//^
+// [analyzer] unspecified
+//                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  A<FunuBound<FutureOr<Object>>> x20;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  A<FunuCyclicBound<Object>> x21;
+//^
+// [analyzer] unspecified
+//                           ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  A<FunuCyclicBound<FutureOr<Object>>> x22;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  A<FunuCyclicBound<A<Object>>> x23;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  A<FunuCyclicBound<A<FutureOr<Object>>>> x24;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  A<FunuCyclicBound<A<A<Object>>>> x25;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  A<FunuCyclicBound<A<A<FutureOr<Object>>>>> x26;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  A<FunuCyclicCoBound<Object>> x27;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  A<FunuCyclicCoBound<FutureOr<Object>>> x28;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  A<FunuCyclicCoBound<Function(Function(Object))>> x31;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  A<FunuCyclicCoBound<Function(Function(FutureOr<Object>))>> x32;
+//^
+// [analyzer] unspecified
+//                                                           ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  FunuBound<Object> Function() x37;
+//^
+// [analyzer] unspecified
+//                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  FunuBound<FutureOr<Object>> Function() x38;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  FunuCyclicBound<Object> Function() x39;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<FutureOr<Object>> Function() x40;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<A<Object>> Function() x41;
+//^
+// [analyzer] unspecified
+//                                      ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<A<FutureOr<Object>>> Function() x42;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<A<A<Object>>> Function() x43;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicBound<A<A<FutureOr<Object>>>> Function() x44;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  FunuCyclicCoBound<Object> Function() x45;
+//^
+// [analyzer] unspecified
+//                                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  FunuCyclicCoBound<FutureOr<Object>> Function() x46;
+//^
+// [analyzer] unspecified
+//                                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  FunuCyclicCoBound<Function(Function(Object))> Function() x49;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  FunuCyclicCoBound<Function(Function(FutureOr<Object>))> Function() x50;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(void Function(FunuBound<Object>)) x55;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function(void Function(FunuBound<FutureOr<Object>>)) x56;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function(void Function(FunuCyclicBound<Object>)) x57;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(void Function(FunuCyclicBound<FutureOr<Object>>)) x58;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(void Function(FunuCyclicBound<A<Object>>)) x59;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(void Function(FunuCyclicBound<A<FutureOr<Object>>>)) x60;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(void Function(FunuCyclicBound<A<A<Object>>>)) x61;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(void Function(FunuCyclicBound<A<A<FutureOr<Object>>>>)) x62;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(void Function(FunuCyclicCoBound<Object>)) x63;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(void Function(FunuCyclicCoBound<FutureOr<Object>>)) x64;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(void Function(FunuCyclicCoBound<Function(Function(Object))>))
+//^
+// [analyzer] unspecified
+      x67;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(
+      void Function(
+          FunuCyclicCoBound<Function(Function(FutureOr<Object>))>)) x68;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(FunuBound<Object>) x73;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function(FunuBound<FutureOr<Object>>) x74;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function(FunuCyclicBound<Object>) x75;
+//^
+// [analyzer] unspecified
+//                                       ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<FutureOr<Object>>) x76;
+//^
+// [analyzer] unspecified
+//                                                 ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<A<Object>>) x77;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<A<FutureOr<Object>>>) x78;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<A<A<Object>>>) x79;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<A<A<FutureOr<Object>>>>) x80;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicCoBound<Object>) x81;
+//^
+// [analyzer] unspecified
+//                                         ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(FunuCyclicCoBound<FutureOr<Object>>) x82;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(FunuCyclicCoBound<Function(Function(Object))>) x85;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(FunuCyclicCoBound<Function(Function(FutureOr<Object>))>) x86;
+//^
+// [analyzer] unspecified
+//                                                                       ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(FunuBound<Object>) Function() x91;
+//^
+// [analyzer] unspecified
+//                                            ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function(FunuBound<FutureOr<Object>>) Function() x92;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function(FunuCyclicBound<Object>) Function() x93;
+//^
+// [analyzer] unspecified
+//                                                  ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<FutureOr<Object>>) Function() x94;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<A<Object>>) Function() x95;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<A<FutureOr<Object>>>) Function() x96;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<A<A<Object>>>) Function() x97;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicBound<A<A<FutureOr<Object>>>>) Function() x98;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function(FunuCyclicCoBound<Object>) Function() x99;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(FunuCyclicCoBound<FutureOr<Object>>) Function() x100;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(FunuCyclicCoBound<Function(Function(Object))>) Function() x103;
+//^
+// [analyzer] unspecified
+//                                                                        ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function(FunuCyclicCoBound<Function(Function(FutureOr<Object>))>)
+//^
+// [analyzer] unspecified
+      Function() x104;
+//               ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function<Y extends FunuBound<Object>>() x109;
+//^
+// [analyzer] unspecified
+//                                             ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function<Y extends FunuBound<FutureOr<Object>>>() x110;
+//^
+// [analyzer] unspecified
+//                                                       ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function<Y extends FunuCyclicBound<Object>>() x111;
+//^
+// [analyzer] unspecified
+//                                                   ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends FunuCyclicBound<FutureOr<Object>>>() x112;
+//^
+// [analyzer] unspecified
+//                                                             ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends FunuCyclicBound<A<Object>>>() x113;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends FunuCyclicBound<A<FutureOr<Object>>>>() x114;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends FunuCyclicBound<A<A<Object>>>>() x115;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends FunuCyclicBound<A<A<FutureOr<Object>>>>>() x116;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends FunuCyclicCoBound<Object>>() x117;
+//^
+// [analyzer] unspecified
+//                                                     ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function<Y extends FunuCyclicCoBound<FutureOr<Object>>>() x118;
+//^
+// [analyzer] unspecified
+//                                                               ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function<Y extends FunuCyclicCoBound<Function(Function(Object))>>() x121;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function<
+      Y extends FunuCyclicCoBound<Function(Function(FutureOr<Object>))>>() x122;
+//^
+// [analyzer] unspecified
+//                                                                         ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function<Y extends A<FunuBound<Object>>>() x127;
+//^
+// [analyzer] unspecified
+//                                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function<Y extends A<FunuBound<FutureOr<Object>>>>() x128;
+//^
+// [analyzer] unspecified
+//                                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  void Function<Y extends A<FunuCyclicBound<Object>>>() x129;
+//^
+// [analyzer] unspecified
+//                                                      ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends A<FunuCyclicBound<FutureOr<Object>>>>() x130;
+//^
+// [analyzer] unspecified
+//                                                                ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends A<FunuCyclicBound<A<Object>>>>() x131;
+//^
+// [analyzer] unspecified
+//                                                         ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends A<FunuCyclicBound<A<FutureOr<Object>>>>>() x132;
+//^
+// [analyzer] unspecified
+//                                                                   ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends A<FunuCyclicBound<A<A<Object>>>>>() x133;
+//^
+// [analyzer] unspecified
+//                                                            ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends A<FunuCyclicBound<A<A<FutureOr<Object>>>>>>() x134;
+//^
+// [analyzer] unspecified
+//                                                                      ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  void Function<Y extends A<FunuCyclicCoBound<Object>>>() x135;
+//^
+// [analyzer] unspecified
+//                                                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function<Y extends A<FunuCyclicCoBound<FutureOr<Object>>>>() x136;
+//^
+// [analyzer] unspecified
+//                                                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function<Y extends A<FunuCyclicCoBound<Function(Function(Object))>>>()
+//^
+// [analyzer] unspecified
+      x139;
+//    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  void Function<
+      Y extends A<
+          FunuCyclicCoBound<Function(Function(FutureOr<Object>))>>>() x140;
+//^
+// [analyzer] unspecified
+//                                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  Finv<FunuBound<Object>> x145;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  Finv<FunuBound<FutureOr<Object>>> x146;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  Finv<FunuCyclicBound<Object>> x147;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Finv<FunuCyclicBound<FutureOr<Object>>> x148;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Finv<FunuCyclicBound<A<Object>>> x149;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Finv<FunuCyclicBound<A<FutureOr<Object>>>> x150;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Finv<FunuCyclicBound<A<A<Object>>>> x151;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Finv<FunuCyclicBound<A<A<FutureOr<Object>>>>> x152;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Finv<FunuCyclicCoBound<Object>> x153;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  Finv<FunuCyclicCoBound<FutureOr<Object>>> x154;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  Finv<FunuCyclicCoBound<Function(Function(Object))>> x157;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  Finv<FunuCyclicCoBound<Function(Function(FutureOr<Object>))>> x158;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  Funu<FunuBound<Object>> x163;
+//^
+// [analyzer] unspecified
+//                        ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  Funu<FunuBound<FutureOr<Object>>> x164;
+//^
+// [analyzer] unspecified
+//                                  ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'num' of the type variable 'X' on 'FunuBound'.
+  Funu<FunuCyclicBound<Object>> x165;
+//^
+// [analyzer] unspecified
+//                              ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Funu<FunuCyclicBound<FutureOr<Object>>> x166;
+//^
+// [analyzer] unspecified
+//                                        ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Funu<FunuCyclicBound<A<Object>>> x167;
+//^
+// [analyzer] unspecified
+//                                 ^
+// [cfe] Type argument 'A<Object>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Funu<FunuCyclicBound<A<FutureOr<Object>>>> x168;
+//^
+// [analyzer] unspecified
+//                                           ^
+// [cfe] Type argument 'A<FutureOr<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Funu<FunuCyclicBound<A<A<Object>>>> x169;
+//^
+// [analyzer] unspecified
+//                                    ^
+// [cfe] Type argument 'A<A<Object>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Funu<FunuCyclicBound<A<A<FutureOr<Object>>>>> x170;
+//^
+// [analyzer] unspecified
+//                                              ^
+// [cfe] Type argument 'A<A<FutureOr<Object>>>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'FunuCyclicBound'.
+  Funu<FunuCyclicCoBound<Object>> x171;
+//^
+// [analyzer] unspecified
+//                                ^
+// [cfe] Type argument 'Object' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  Funu<FunuCyclicCoBound<FutureOr<Object>>> x172;
+//^
+// [analyzer] unspecified
+//                                          ^
+// [cfe] Type argument 'FutureOr<Object>' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  Funu<FunuCyclicCoBound<Function(Function(Object))>> x175;
+//^
+// [analyzer] unspecified
+//                                                    ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(Object))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  Funu<FunuCyclicCoBound<Function(Function(FutureOr<Object>))>> x176;
+//^
+// [analyzer] unspecified
+//                                                              ^
+// [cfe] Type argument 'dynamic Function(dynamic Function(FutureOr<Object>))' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+}
+
+void testVarianceLessSuperbound<N extends Never>() {
+  FunuCyclicCoBound<Function(Never)> x1;
+//^
+// [analyzer] unspecified
+//                                   ^
+// [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+  FunuCyclicCoBound<Function(N)> x2;
+//^
+// [analyzer] unspecified
+//                               ^
+// [cfe] Type argument 'dynamic Function(N)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FunuCyclicCoBound'.
+}
+
+void testTypeAliasAsTypeArgument() {
+  // I2b: Use bounds (FinvCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
+  // by replacing contravariant occurrence of `Y` in
+  // `AinvCyclicCoBound<_, Function(Y)>` by `Never`; then replace invariant
+  // occurrence of `Y` in `AinvCyclicCoBound<FinvCyclicCoBound<Y>, _>` by `Y`s
+  // value `Function(Never)`.
+  // Resulting type
+  // `AinvCyclicCoBound<FinvCyclicCoBound<Function(Never)>, Function(Never)>>`
+  // looks regular-bounded, but contains `FinvCyclicCoBound<Function(Never)>`
+  // which is not well-bounded.
+  void f(AinvCyclicCoBound source) {
+//       ^
+// [analyzer] unspecified
+//                         ^
+// [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+    var fsource = toF(source);
+//  ^
+// [analyzer] unspecified
+//      ^
+// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+//                ^
+// [analyzer] unspecified
+// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+    F<AinvCyclicCoBound<FinvCyclicCoBound<Function(Never)>, Function(Never)>>
+//  ^
+// [analyzer] unspecified
+        target = fsource;
+//      ^
+// [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  }
+}
+
+void testNested() {
+  void f(B<AinvCyclicCoBound> source) {
+//       ^
+// [analyzer] unspecified
+//         ^
+// [analyzer] unspecified
+//                            ^
+// [cfe] Type argument 'AinvCyclicCoBound<dynamic Function(Never) Function(dynamic Function(Never)), dynamic Function(Never)>' doesn't conform to the bound 'B<X>' of the type variable 'X' on 'B'.
+//                            ^
+// [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+    var fsource = toF(source);
+//  ^
+// [analyzer] unspecified
+//      ^
+// [cfe] Inferred type argument 'AinvCyclicCoBound<dynamic Function(Never) Function(dynamic Function(Never)), dynamic Function(Never)>' doesn't conform to the bound 'B<X>' of the type variable 'X' on 'B'.
+//      ^
+// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+//                ^
+// [analyzer] unspecified
+// [cfe] Inferred type argument 'AinvCyclicCoBound<dynamic Function(Never) Function(dynamic Function(Never)), dynamic Function(Never)>' doesn't conform to the bound 'B<X>' of the type variable 'X' on 'B'.
+//                ^
+// [cfe] Inferred type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+    F<B<AinvCyclicCoBound<FinvCyclicCoBound<Function(Never)>, Function(Never)>>>
+//  ^
+// [analyzer] unspecified
+        target = fsource;
+//      ^
+// [cfe] Type argument 'AinvCyclicCoBound<dynamic Function(Never) Function(dynamic Function(Never)), dynamic Function(Never)>' doesn't conform to the bound 'B<X>' of the type variable 'X' on 'B'.
+//      ^
+// [cfe] Type argument 'dynamic Function(Never)' doesn't conform to the bound 'dynamic Function(X)' of the type variable 'X' on 'FinvCyclicCoBound'.
+  }
+}
+
+void main() {
+  testCovariantSuperboundError<Null>();
+  testInvariantSuperboundError<Null>();
+  testVarianceLessSuperboundError<Null>();
+  testVarianceLessSuperbound();
+  testTypeAliasAsTypeArgument();
+  testNested();
+}
diff --git a/tests/language/generic/super_bounded_types_test.dart b/tests/language/generic/super_bounded_types_test.dart
new file mode 100644
index 0000000..f1cd6cb
--- /dev/null
+++ b/tests/language/generic/super_bounded_types_test.dart
@@ -0,0 +1,2326 @@
+// 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.
+
+// Test that various super-bounded types are accepted.
+
+import 'dart:async';
+
+class A<X> {}
+
+class B<X extends B<X>> extends A<X> {}
+
+typedef Fcov<X> = X Function();
+typedef Fcon<X> = Function(X);
+typedef Finv<X> = X Function(X);
+typedef Funu<X> = Function();
+
+typedef FcovBound<X extends num> = X Function();
+typedef FconBound<X extends num> = Function(X);
+typedef FinvBound<X extends num> = X Function(X);
+typedef FunuBound<X extends num> = Function();
+
+typedef FcovCyclicBound<X extends A<X>> = X Function();
+typedef FconCyclicBound<X extends A<X>> = Function(X);
+typedef FinvCyclicBound<X extends A<X>> = X Function(X);
+typedef FunuCyclicBound<X extends A<X>> = Function();
+
+typedef FcovCyclicCoBound<X extends Function(X)> = X Function();
+typedef FconCyclicCoBound<X extends Function(X)> = Function(X);
+typedef FinvCyclicCoBound<X extends Function(X)> = X Function(X);
+typedef FunuCyclicCoBound<X extends Function(X)> = Function();
+
+class CFcov<X extends Fcov<X>> {}
+
+class CFcon<X extends Fcon<X>> {}
+
+class CFinv<X extends Finv<X>> {}
+
+class CFunu<X extends Funu<X>> {}
+
+class CcovBound<X extends num> {}
+
+class CcovCyclicBound<X extends A<X>> {}
+
+class CcovCyclicCoBound<X extends Function(X)> {}
+
+void testCovariantSuperbound<N extends Never>() {
+  // Bottom type in a covariant position, regular-bounded.
+  FcovBound<Never> x1;
+  FcovBound<N> x2;
+  FcovCyclicBound<Never> x3;
+  FcovCyclicBound<N> x4;
+  FcovCyclicBound<A<Never>> x5;
+  FcovCyclicBound<A<N>> x6;
+  FcovCyclicBound<A<A<Never>>> x7;
+  FcovCyclicBound<A<A<N>>> x8;
+  FcovCyclicCoBound<Never> x9;
+  FcovCyclicCoBound<N> x10;
+  FcovCyclicCoBound<Function(Function(Never))> x11;
+  FcovCyclicCoBound<Function(Function(N))> x12;
+  CFcov<Never> x13;
+  CFcov<N> x14;
+  CFcov<Fcov<Never>> x15;
+  CFcov<Fcov<N>> x16;
+  CFcov<Fcov<Fcov<Never>>> x17;
+  CFcov<Fcov<Fcov<N>>> x18;
+  CFcon<Never> x19;
+  CFcon<N> x20;
+  CFinv<Never> x21;
+  CFinv<N> x22;
+  CFunu<Never> x23;
+  CFunu<N> x24;
+  CcovBound<Never> x25;
+  CcovBound<N> x26;
+  CcovCyclicBound<Never> x27;
+  CcovCyclicBound<N> x28;
+  CcovCyclicBound<A<Never>> x29;
+  CcovCyclicBound<A<N>> x30;
+  CcovCyclicBound<A<A<Never>>> x31;
+  CcovCyclicBound<A<A<N>>> x32;
+  CcovCyclicCoBound<Never> x33;
+  CcovCyclicCoBound<N> x34;
+  CcovCyclicCoBound<Function(Function(Never))> x35;
+  CcovCyclicCoBound<Function(Function(N))> x36;
+
+  // Top type in a covariant position, super-bounded.
+  FcovBound<dynamic> x37;
+  FcovBound<void> x38;
+  FcovBound<Object?> x39;
+  FcovBound<FutureOr<dynamic>> x40;
+  FcovBound<FutureOr<void>> x41;
+  FcovBound<FutureOr<Object?>> x42;
+  FcovCyclicBound<dynamic> x43;
+  FcovCyclicBound<void> x44;
+  FcovCyclicBound<Object?> x45;
+  FcovCyclicBound<FutureOr<dynamic>> x46;
+  FcovCyclicBound<FutureOr<void>> x47;
+  FcovCyclicBound<FutureOr<Object?>> x48;
+  FcovCyclicBound<A<dynamic>> x49;
+  FcovCyclicBound<A<void>> x50;
+  FcovCyclicBound<A<Object?>> x51;
+  FcovCyclicBound<A<FutureOr<dynamic>>> x52;
+  FcovCyclicBound<A<FutureOr<void>>> x53;
+  FcovCyclicBound<A<FutureOr<Object?>>> x54;
+  FcovCyclicBound<A<A<dynamic>>> x55;
+  FcovCyclicBound<A<A<void>>> x56;
+  FcovCyclicBound<A<A<Object?>>> x57;
+  FcovCyclicBound<A<A<FutureOr<dynamic>>>> x58;
+  FcovCyclicBound<A<A<FutureOr<void>>>> x59;
+  FcovCyclicBound<A<A<FutureOr<Object?>>>> x60;
+  FcovCyclicCoBound<dynamic> x61;
+  FcovCyclicCoBound<void> x62;
+  FcovCyclicCoBound<Object?> x63;
+  FcovCyclicCoBound<FutureOr<dynamic>> x64;
+  FcovCyclicCoBound<FutureOr<void>> x65;
+  FcovCyclicCoBound<FutureOr<Object?>> x66;
+  FcovCyclicCoBound<Function(Function(dynamic))> x67;
+  FcovCyclicCoBound<Function(Function(void))> x68;
+  FcovCyclicCoBound<Function(Function(Object?))> x69;
+  FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))> x70;
+  FcovCyclicCoBound<Function(Function(FutureOr<void>))> x71;
+  FcovCyclicCoBound<Function(Function(FutureOr<Object?>))> x72;
+  CFcov<dynamic> x73;
+  CFcov<void> x74;
+  CFcov<Object?> x75;
+  CFcov<FutureOr<dynamic>> x76;
+  CFcov<FutureOr<void>> x77;
+  CFcov<FutureOr<Object?>> x78;
+  CFcov<Fcov<dynamic>> x79;
+  CFcov<Fcov<void>> x80;
+  CFcov<Fcov<Object?>> x81;
+  CFcov<Fcov<FutureOr<dynamic>>> x82;
+  CFcov<Fcov<FutureOr<void>>> x83;
+  CFcov<Fcov<FutureOr<Object?>>> x84;
+  CFcov<Fcov<Fcov<dynamic>>> x85;
+  CFcov<Fcov<Fcov<void>>> x86;
+  CFcov<Fcov<Fcov<Object?>>> x87;
+  CFcov<Fcov<Fcov<FutureOr<dynamic>>>> x88;
+  CFcov<Fcov<Fcov<FutureOr<void>>>> x89;
+  CFcov<Fcov<Fcov<FutureOr<Object?>>>> x90;
+  CFcon<dynamic> x91;
+  CFcon<void> x92;
+  CFcon<Object?> x93;
+  CFcon<FutureOr<dynamic>> x94;
+  CFcon<FutureOr<void>> x95;
+  CFcon<FutureOr<Object?>> x96;
+  CFinv<dynamic> x97;
+  CFinv<void> x98;
+  CFinv<Object?> x99;
+  CFinv<FutureOr<dynamic>> x100;
+  CFinv<FutureOr<void>> x101;
+  CFinv<FutureOr<Object?>> x102;
+  CFunu<dynamic> x103;
+  CFunu<void> x104;
+  CFunu<Object?> x105;
+  CFunu<FutureOr<dynamic>> x106;
+  CFunu<FutureOr<void>> x107;
+  CFunu<FutureOr<Object?>> x108;
+  CcovBound<dynamic> x109;
+  CcovBound<void> x110;
+  CcovBound<Object?> x111;
+  CcovBound<FutureOr<dynamic>> x112;
+  CcovBound<FutureOr<void>> x113;
+  CcovBound<FutureOr<Object?>> x114;
+  CcovCyclicBound<dynamic> x115;
+  CcovCyclicBound<void> x116;
+  CcovCyclicBound<Object?> x117;
+  CcovCyclicBound<FutureOr<dynamic>> x118;
+  CcovCyclicBound<FutureOr<void>> x119;
+  CcovCyclicBound<FutureOr<Object?>> x120;
+  CcovCyclicBound<A<dynamic>> x121;
+  CcovCyclicBound<A<void>> x122;
+  CcovCyclicBound<A<Object?>> x123;
+  CcovCyclicBound<A<FutureOr<dynamic>>> x124;
+  CcovCyclicBound<A<FutureOr<void>>> x125;
+  CcovCyclicBound<A<FutureOr<Object?>>> x126;
+  CcovCyclicBound<A<A<dynamic>>> x127;
+  CcovCyclicBound<A<A<void>>> x128;
+  CcovCyclicBound<A<A<Object?>>> x129;
+  CcovCyclicBound<A<A<FutureOr<dynamic>>>> x130;
+  CcovCyclicBound<A<A<FutureOr<void>>>> x131;
+  CcovCyclicBound<A<A<FutureOr<Object?>>>> x132;
+  CcovCyclicCoBound<dynamic> x133;
+  CcovCyclicCoBound<void> x134;
+  CcovCyclicCoBound<Object?> x135;
+  CcovCyclicCoBound<FutureOr<dynamic>> x136;
+  CcovCyclicCoBound<FutureOr<void>> x137;
+  CcovCyclicCoBound<FutureOr<Object?>> x138;
+  CcovCyclicCoBound<Function(Function(dynamic))> x139;
+  CcovCyclicCoBound<Function(Function(void))> x140;
+  CcovCyclicCoBound<Function(Function(Object?))> x141;
+  CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))> x142;
+  CcovCyclicCoBound<Function(Function(FutureOr<void>))> x143;
+  CcovCyclicCoBound<Function(Function(FutureOr<Object?>))> x144;
+
+  // Super-bounded types in a context.
+  A<FcovBound<dynamic>> x145;
+  A<FcovBound<void>> x146;
+  A<FcovBound<Object?>> x147;
+  A<FcovBound<FutureOr<dynamic>>> x148;
+  A<FcovBound<FutureOr<void>>> x149;
+  A<FcovBound<FutureOr<Object?>>> x150;
+  A<FcovCyclicBound<dynamic>> x151;
+  A<FcovCyclicBound<void>> x152;
+  A<FcovCyclicBound<Object?>> x153;
+  A<FcovCyclicBound<FutureOr<dynamic>>> x154;
+  A<FcovCyclicBound<FutureOr<void>>> x155;
+  A<FcovCyclicBound<FutureOr<Object?>>> x156;
+  A<FcovCyclicBound<A<dynamic>>> x157;
+  A<FcovCyclicBound<A<void>>> x158;
+  A<FcovCyclicBound<A<Object?>>> x159;
+  A<FcovCyclicBound<A<FutureOr<dynamic>>>> x160;
+  A<FcovCyclicBound<A<FutureOr<void>>>> x161;
+  A<FcovCyclicBound<A<FutureOr<Object?>>>> x162;
+  A<FcovCyclicBound<A<A<dynamic>>>> x163;
+  A<FcovCyclicBound<A<A<void>>>> x164;
+  A<FcovCyclicBound<A<A<Object?>>>> x165;
+  A<FcovCyclicBound<A<A<FutureOr<dynamic>>>>> x166;
+  A<FcovCyclicBound<A<A<FutureOr<void>>>>> x167;
+  A<FcovCyclicBound<A<A<FutureOr<Object?>>>>> x168;
+  A<FcovCyclicCoBound<dynamic>> x169;
+  A<FcovCyclicCoBound<void>> x170;
+  A<FcovCyclicCoBound<Object?>> x171;
+  A<FcovCyclicCoBound<FutureOr<dynamic>>> x172;
+  A<FcovCyclicCoBound<FutureOr<void>>> x173;
+  A<FcovCyclicCoBound<FutureOr<Object?>>> x174;
+  A<FcovCyclicCoBound<Function(Function(dynamic))>> x175;
+  A<FcovCyclicCoBound<Function(Function(void))>> x176;
+  A<FcovCyclicCoBound<Function(Function(Object?))>> x177;
+  A<FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x178;
+  A<FcovCyclicCoBound<Function(Function(FutureOr<void>))>> x179;
+  A<FcovCyclicCoBound<Function(Function(FutureOr<Object?>))>> x180;
+  A<CFcov<dynamic>> x181;
+  A<CFcov<void>> x182;
+  A<CFcov<Object?>> x183;
+  A<CFcov<FutureOr<dynamic>>> x184;
+  A<CFcov<FutureOr<void>>> x185;
+  A<CFcov<FutureOr<Object?>>> x186;
+  A<CFcov<Fcov<dynamic>>> x187;
+  A<CFcov<Fcov<void>>> x188;
+  A<CFcov<Fcov<Object?>>> x189;
+  A<CFcov<Fcov<FutureOr<dynamic>>>> x190;
+  A<CFcov<Fcov<FutureOr<void>>>> x191;
+  A<CFcov<Fcov<FutureOr<Object?>>>> x192;
+  A<CFcov<Fcov<Fcov<dynamic>>>> x193;
+  A<CFcov<Fcov<Fcov<void>>>> x194;
+  A<CFcov<Fcov<Fcov<Object?>>>> x195;
+  A<CFcov<Fcov<Fcov<FutureOr<dynamic>>>>> x196;
+  A<CFcov<Fcov<Fcov<FutureOr<void>>>>> x197;
+  A<CFcov<Fcov<Fcov<FutureOr<Object?>>>>> x198;
+  A<CFcon<dynamic>> x199;
+  A<CFcon<void>> x200;
+  A<CFcon<Object?>> x201;
+  A<CFcon<FutureOr<dynamic>>> x202;
+  A<CFcon<FutureOr<void>>> x203;
+  A<CFcon<FutureOr<Object?>>> x204;
+  A<CFinv<dynamic>> x205;
+  A<CFinv<void>> x206;
+  A<CFinv<Object?>> x207;
+  A<CFinv<FutureOr<dynamic>>> x208;
+  A<CFinv<FutureOr<void>>> x209;
+  A<CFinv<FutureOr<Object?>>> x210;
+  A<CFunu<dynamic>> x211;
+  A<CFunu<void>> x212;
+  A<CFunu<Object?>> x213;
+  A<CFunu<FutureOr<dynamic>>> x214;
+  A<CFunu<FutureOr<void>>> x215;
+  A<CFunu<FutureOr<Object?>>> x216;
+  A<CcovBound<dynamic>> x217;
+  A<CcovBound<void>> x218;
+  A<CcovBound<Object?>> x219;
+  A<CcovBound<FutureOr<dynamic>>> x220;
+  A<CcovBound<FutureOr<void>>> x221;
+  A<CcovBound<FutureOr<Object?>>> x222;
+  A<CcovCyclicBound<dynamic>> x223;
+  A<CcovCyclicBound<void>> x224;
+  A<CcovCyclicBound<Object?>> x225;
+  A<CcovCyclicBound<FutureOr<dynamic>>> x226;
+  A<CcovCyclicBound<FutureOr<void>>> x227;
+  A<CcovCyclicBound<FutureOr<Object?>>> x228;
+  A<CcovCyclicBound<A<dynamic>>> x229;
+  A<CcovCyclicBound<A<void>>> x230;
+  A<CcovCyclicBound<A<Object?>>> x231;
+  A<CcovCyclicBound<A<FutureOr<dynamic>>>> x232;
+  A<CcovCyclicBound<A<FutureOr<void>>>> x233;
+  A<CcovCyclicBound<A<FutureOr<Object?>>>> x234;
+  A<CcovCyclicBound<A<A<dynamic>>>> x235;
+  A<CcovCyclicBound<A<A<void>>>> x236;
+  A<CcovCyclicBound<A<A<Object?>>>> x237;
+  A<CcovCyclicBound<A<A<FutureOr<dynamic>>>>> x238;
+  A<CcovCyclicBound<A<A<FutureOr<void>>>>> x239;
+  A<CcovCyclicBound<A<A<FutureOr<Object?>>>>> x240;
+  A<CcovCyclicCoBound<dynamic>> x241;
+  A<CcovCyclicCoBound<void>> x242;
+  A<CcovCyclicCoBound<Object?>> x243;
+  A<CcovCyclicCoBound<FutureOr<dynamic>>> x244;
+  A<CcovCyclicCoBound<FutureOr<void>>> x245;
+  A<CcovCyclicCoBound<FutureOr<Object?>>> x246;
+  A<CcovCyclicCoBound<Function(Function(dynamic))>> x247;
+  A<CcovCyclicCoBound<Function(Function(void))>> x248;
+  A<CcovCyclicCoBound<Function(Function(Object?))>> x249;
+  A<CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x250;
+  A<CcovCyclicCoBound<Function(Function(FutureOr<void>))>> x251;
+  A<CcovCyclicCoBound<Function(Function(FutureOr<Object?>))>> x252;
+  FcovBound<dynamic> Function() x253;
+  FcovBound<void> Function() x254;
+  FcovBound<Object?> Function() x255;
+  FcovBound<FutureOr<dynamic>> Function() x256;
+  FcovBound<FutureOr<void>> Function() x257;
+  FcovBound<FutureOr<Object?>> Function() x258;
+  FcovCyclicBound<dynamic> Function() x259;
+  FcovCyclicBound<void> Function() x260;
+  FcovCyclicBound<Object?> Function() x261;
+  FcovCyclicBound<FutureOr<dynamic>> Function() x262;
+  FcovCyclicBound<FutureOr<void>> Function() x263;
+  FcovCyclicBound<FutureOr<Object?>> Function() x264;
+  FcovCyclicBound<A<dynamic>> Function() x265;
+  FcovCyclicBound<A<void>> Function() x266;
+  FcovCyclicBound<A<Object?>> Function() x267;
+  FcovCyclicBound<A<FutureOr<dynamic>>> Function() x268;
+  FcovCyclicBound<A<FutureOr<void>>> Function() x269;
+  FcovCyclicBound<A<FutureOr<Object?>>> Function() x270;
+  FcovCyclicBound<A<A<dynamic>>> Function() x271;
+  FcovCyclicBound<A<A<void>>> Function() x272;
+  FcovCyclicBound<A<A<Object?>>> Function() x273;
+  FcovCyclicBound<A<A<FutureOr<dynamic>>>> Function() x274;
+  FcovCyclicBound<A<A<FutureOr<void>>>> Function() x275;
+  FcovCyclicBound<A<A<FutureOr<Object?>>>> Function() x276;
+  FcovCyclicCoBound<dynamic> Function() x277;
+  FcovCyclicCoBound<void> Function() x278;
+  FcovCyclicCoBound<Object?> Function() x279;
+  FcovCyclicCoBound<FutureOr<dynamic>> Function() x280;
+  FcovCyclicCoBound<FutureOr<void>> Function() x281;
+  FcovCyclicCoBound<FutureOr<Object?>> Function() x282;
+  FcovCyclicCoBound<Function(Function(dynamic))> Function() x283;
+  FcovCyclicCoBound<Function(Function(void))> Function() x284;
+  FcovCyclicCoBound<Function(Function(Object?))> Function() x285;
+  FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))> Function() x286;
+  FcovCyclicCoBound<Function(Function(FutureOr<void>))> Function() x287;
+  FcovCyclicCoBound<Function(Function(FutureOr<Object?>))> Function() x288;
+  CFcov<dynamic> Function() x289;
+  CFcov<void> Function() x290;
+  CFcov<Object?> Function() x291;
+  CFcov<FutureOr<dynamic>> Function() x292;
+  CFcov<FutureOr<void>> Function() x293;
+  CFcov<FutureOr<Object?>> Function() x294;
+  CFcov<Fcov<dynamic>> Function() x295;
+  CFcov<Fcov<void>> Function() x296;
+  CFcov<Fcov<Object?>> Function() x297;
+  CFcov<Fcov<FutureOr<dynamic>>> Function() x298;
+  CFcov<Fcov<FutureOr<void>>> Function() x299;
+  CFcov<Fcov<FutureOr<Object?>>> Function() x300;
+  CFcov<Fcov<Fcov<dynamic>>> Function() x301;
+  CFcov<Fcov<Fcov<void>>> Function() x302;
+  CFcov<Fcov<Fcov<Object?>>> Function() x303;
+  CFcov<Fcov<Fcov<FutureOr<dynamic>>>> Function() x304;
+  CFcov<Fcov<Fcov<FutureOr<void>>>> Function() x305;
+  CFcov<Fcov<Fcov<FutureOr<Object?>>>> Function() x306;
+  CFcon<dynamic> Function() x307;
+  CFcon<void> Function() x308;
+  CFcon<Object?> Function() x309;
+  CFcon<FutureOr<dynamic>> Function() x310;
+  CFcon<FutureOr<void>> Function() x311;
+  CFcon<FutureOr<Object?>> Function() x312;
+  CFinv<dynamic> Function() x313;
+  CFinv<void> Function() x314;
+  CFinv<Object?> Function() x315;
+  CFinv<FutureOr<dynamic>> Function() x316;
+  CFinv<FutureOr<void>> Function() x317;
+  CFinv<FutureOr<Object?>> Function() x318;
+  CFunu<dynamic> Function() x319;
+  CFunu<void> Function() x320;
+  CFunu<Object?> Function() x321;
+  CFunu<FutureOr<dynamic>> Function() x322;
+  CFunu<FutureOr<void>> Function() x323;
+  CFunu<FutureOr<Object?>> Function() x324;
+  CcovBound<dynamic> Function() x325;
+  CcovBound<void> Function() x326;
+  CcovBound<Object?> Function() x327;
+  CcovBound<FutureOr<dynamic>> Function() x328;
+  CcovBound<FutureOr<void>> Function() x329;
+  CcovBound<FutureOr<Object?>> Function() x330;
+  CcovCyclicBound<dynamic> Function() x331;
+  CcovCyclicBound<void> Function() x332;
+  CcovCyclicBound<Object?> Function() x333;
+  CcovCyclicBound<FutureOr<dynamic>> Function() x334;
+  CcovCyclicBound<FutureOr<void>> Function() x335;
+  CcovCyclicBound<FutureOr<Object?>> Function() x336;
+  CcovCyclicBound<A<dynamic>> Function() x337;
+  CcovCyclicBound<A<void>> Function() x338;
+  CcovCyclicBound<A<Object?>> Function() x339;
+  CcovCyclicBound<A<FutureOr<dynamic>>> Function() x340;
+  CcovCyclicBound<A<FutureOr<void>>> Function() x341;
+  CcovCyclicBound<A<FutureOr<Object?>>> Function() x342;
+  CcovCyclicBound<A<A<dynamic>>> Function() x343;
+  CcovCyclicBound<A<A<void>>> Function() x344;
+  CcovCyclicBound<A<A<Object?>>> Function() x345;
+  CcovCyclicBound<A<A<FutureOr<dynamic>>>> Function() x346;
+  CcovCyclicBound<A<A<FutureOr<void>>>> Function() x347;
+  CcovCyclicBound<A<A<FutureOr<Object?>>>> Function() x348;
+  CcovCyclicCoBound<dynamic> Function() x349;
+  CcovCyclicCoBound<void> Function() x350;
+  CcovCyclicCoBound<Object?> Function() x351;
+  CcovCyclicCoBound<FutureOr<dynamic>> Function() x352;
+  CcovCyclicCoBound<FutureOr<void>> Function() x353;
+  CcovCyclicCoBound<FutureOr<Object?>> Function() x354;
+  CcovCyclicCoBound<Function(Function(dynamic))> Function() x355;
+  CcovCyclicCoBound<Function(Function(void))> Function() x356;
+  CcovCyclicCoBound<Function(Function(Object?))> Function() x357;
+  CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))> Function() x358;
+  CcovCyclicCoBound<Function(Function(FutureOr<void>))> Function() x359;
+  CcovCyclicCoBound<Function(Function(FutureOr<Object?>))> Function() x360;
+  void Function(void Function(FcovBound<dynamic>)) x361;
+  void Function(void Function(FcovBound<void>)) x362;
+  void Function(void Function(FcovBound<Object?>)) x363;
+  void Function(void Function(FcovBound<FutureOr<dynamic>>)) x364;
+  void Function(void Function(FcovBound<FutureOr<void>>)) x365;
+  void Function(void Function(FcovBound<FutureOr<Object?>>)) x366;
+  void Function(void Function(FcovCyclicBound<dynamic>)) x367;
+  void Function(void Function(FcovCyclicBound<void>)) x368;
+  void Function(void Function(FcovCyclicBound<Object?>)) x369;
+  void Function(void Function(FcovCyclicBound<FutureOr<dynamic>>)) x370;
+  void Function(void Function(FcovCyclicBound<FutureOr<void>>)) x371;
+  void Function(void Function(FcovCyclicBound<FutureOr<Object?>>)) x372;
+  void Function(void Function(FcovCyclicBound<A<dynamic>>)) x373;
+  void Function(void Function(FcovCyclicBound<A<void>>)) x374;
+  void Function(void Function(FcovCyclicBound<A<Object?>>)) x375;
+  void Function(void Function(FcovCyclicBound<A<FutureOr<dynamic>>>)) x376;
+  void Function(void Function(FcovCyclicBound<A<FutureOr<void>>>)) x377;
+  void Function(void Function(FcovCyclicBound<A<FutureOr<Object?>>>)) x378;
+  void Function(void Function(FcovCyclicBound<A<A<dynamic>>>)) x379;
+  void Function(void Function(FcovCyclicBound<A<A<void>>>)) x380;
+  void Function(void Function(FcovCyclicBound<A<A<Object?>>>)) x381;
+  void Function(void Function(FcovCyclicBound<A<A<FutureOr<dynamic>>>>)) x382;
+  void Function(void Function(FcovCyclicBound<A<A<FutureOr<void>>>>)) x383;
+  void Function(void Function(FcovCyclicBound<A<A<FutureOr<Object?>>>>)) x384;
+  void Function(void Function(FcovCyclicCoBound<dynamic>)) x385;
+  void Function(void Function(FcovCyclicCoBound<void>)) x386;
+  void Function(void Function(FcovCyclicCoBound<Object?>)) x387;
+  void Function(void Function(FcovCyclicCoBound<FutureOr<dynamic>>)) x388;
+  void Function(void Function(FcovCyclicCoBound<FutureOr<void>>)) x389;
+  void Function(void Function(FcovCyclicCoBound<FutureOr<Object?>>)) x390;
+  void Function(void Function(FcovCyclicCoBound<Function(Function(dynamic))>))
+      x391;
+  void Function(void Function(FcovCyclicCoBound<Function(Function(void))>))
+      x392;
+  void Function(void Function(FcovCyclicCoBound<Function(Function(Object?))>))
+      x393;
+  void Function(
+      void Function(
+          FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>)) x394;
+  void Function(
+          void Function(FcovCyclicCoBound<Function(Function(FutureOr<void>))>))
+      x395;
+  void Function(
+      void Function(
+          FcovCyclicCoBound<Function(Function(FutureOr<Object?>))>)) x396;
+  void Function(void Function(CFcov<dynamic>)) x397;
+  void Function(void Function(CFcov<void>)) x398;
+  void Function(void Function(CFcov<Object?>)) x399;
+  void Function(void Function(CFcov<FutureOr<dynamic>>)) x400;
+  void Function(void Function(CFcov<FutureOr<void>>)) x401;
+  void Function(void Function(CFcov<FutureOr<Object?>>)) x402;
+  void Function(void Function(CFcov<Fcov<dynamic>>)) x403;
+  void Function(void Function(CFcov<Fcov<void>>)) x404;
+  void Function(void Function(CFcov<Fcov<Object?>>)) x405;
+  void Function(void Function(CFcov<Fcov<FutureOr<dynamic>>>)) x406;
+  void Function(void Function(CFcov<Fcov<FutureOr<void>>>)) x407;
+  void Function(void Function(CFcov<Fcov<FutureOr<Object?>>>)) x408;
+  void Function(void Function(CFcov<Fcov<Fcov<dynamic>>>)) x409;
+  void Function(void Function(CFcov<Fcov<Fcov<void>>>)) x410;
+  void Function(void Function(CFcov<Fcov<Fcov<Object?>>>)) x411;
+  void Function(void Function(CFcov<Fcov<Fcov<FutureOr<dynamic>>>>)) x412;
+  void Function(void Function(CFcov<Fcov<Fcov<FutureOr<void>>>>)) x413;
+  void Function(void Function(CFcov<Fcov<Fcov<FutureOr<Object?>>>>)) x414;
+  void Function(void Function(CFcon<dynamic>)) x415;
+  void Function(void Function(CFcon<void>)) x416;
+  void Function(void Function(CFcon<Object?>)) x417;
+  void Function(void Function(CFcon<FutureOr<dynamic>>)) x418;
+  void Function(void Function(CFcon<FutureOr<void>>)) x419;
+  void Function(void Function(CFcon<FutureOr<Object?>>)) x420;
+  void Function(void Function(CFinv<dynamic>)) x421;
+  void Function(void Function(CFinv<void>)) x422;
+  void Function(void Function(CFinv<Object?>)) x423;
+  void Function(void Function(CFinv<FutureOr<dynamic>>)) x424;
+  void Function(void Function(CFinv<FutureOr<void>>)) x425;
+  void Function(void Function(CFinv<FutureOr<Object?>>)) x426;
+  void Function(void Function(CFunu<dynamic>)) x427;
+  void Function(void Function(CFunu<void>)) x428;
+  void Function(void Function(CFunu<Object?>)) x429;
+  void Function(void Function(CFunu<FutureOr<dynamic>>)) x430;
+  void Function(void Function(CFunu<FutureOr<void>>)) x431;
+  void Function(void Function(CFunu<FutureOr<Object?>>)) x432;
+  void Function(void Function(CcovBound<dynamic>)) x433;
+  void Function(void Function(CcovBound<void>)) x434;
+  void Function(void Function(CcovBound<Object?>)) x435;
+  void Function(void Function(CcovBound<FutureOr<dynamic>>)) x436;
+  void Function(void Function(CcovBound<FutureOr<void>>)) x437;
+  void Function(void Function(CcovBound<FutureOr<Object?>>)) x438;
+  void Function(void Function(CcovCyclicBound<dynamic>)) x439;
+  void Function(void Function(CcovCyclicBound<void>)) x440;
+  void Function(void Function(CcovCyclicBound<Object?>)) x441;
+  void Function(void Function(CcovCyclicBound<FutureOr<dynamic>>)) x442;
+  void Function(void Function(CcovCyclicBound<FutureOr<void>>)) x443;
+  void Function(void Function(CcovCyclicBound<FutureOr<Object?>>)) x444;
+  void Function(void Function(CcovCyclicBound<A<dynamic>>)) x445;
+  void Function(void Function(CcovCyclicBound<A<void>>)) x446;
+  void Function(void Function(CcovCyclicBound<A<Object?>>)) x447;
+  void Function(void Function(CcovCyclicBound<A<FutureOr<dynamic>>>)) x448;
+  void Function(void Function(CcovCyclicBound<A<FutureOr<void>>>)) x449;
+  void Function(void Function(CcovCyclicBound<A<FutureOr<Object?>>>)) x450;
+  void Function(void Function(CcovCyclicBound<A<A<dynamic>>>)) x451;
+  void Function(void Function(CcovCyclicBound<A<A<void>>>)) x452;
+  void Function(void Function(CcovCyclicBound<A<A<Object?>>>)) x453;
+  void Function(void Function(CcovCyclicBound<A<A<FutureOr<dynamic>>>>)) x454;
+  void Function(void Function(CcovCyclicBound<A<A<FutureOr<void>>>>)) x455;
+  void Function(void Function(CcovCyclicBound<A<A<FutureOr<Object?>>>>)) x456;
+  void Function(void Function(CcovCyclicCoBound<dynamic>)) x457;
+  void Function(void Function(CcovCyclicCoBound<void>)) x458;
+  void Function(void Function(CcovCyclicCoBound<Object?>)) x459;
+  void Function(void Function(CcovCyclicCoBound<FutureOr<dynamic>>)) x460;
+  void Function(void Function(CcovCyclicCoBound<FutureOr<void>>)) x461;
+  void Function(void Function(CcovCyclicCoBound<FutureOr<Object?>>)) x462;
+  void Function(void Function(CcovCyclicCoBound<Function(Function(dynamic))>))
+      x463;
+  void Function(void Function(CcovCyclicCoBound<Function(Function(void))>))
+      x464;
+  void Function(void Function(CcovCyclicCoBound<Function(Function(Object?))>))
+      x465;
+  void Function(
+      void Function(
+          CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>)) x466;
+  void Function(
+          void Function(CcovCyclicCoBound<Function(Function(FutureOr<void>))>))
+      x467;
+  void Function(
+      void Function(
+          CcovCyclicCoBound<Function(Function(FutureOr<Object?>))>)) x468;
+  void Function(FcovBound<dynamic>) x469;
+  void Function(FcovBound<void>) x470;
+  void Function(FcovBound<Object?>) x471;
+  void Function(FcovBound<FutureOr<dynamic>>) x472;
+  void Function(FcovBound<FutureOr<void>>) x473;
+  void Function(FcovBound<FutureOr<Object?>>) x474;
+  void Function(FcovCyclicBound<dynamic>) x475;
+  void Function(FcovCyclicBound<void>) x476;
+  void Function(FcovCyclicBound<Object?>) x477;
+  void Function(FcovCyclicBound<FutureOr<dynamic>>) x478;
+  void Function(FcovCyclicBound<FutureOr<void>>) x479;
+  void Function(FcovCyclicBound<FutureOr<Object?>>) x480;
+  void Function(FcovCyclicBound<A<dynamic>>) x481;
+  void Function(FcovCyclicBound<A<void>>) x482;
+  void Function(FcovCyclicBound<A<Object?>>) x483;
+  void Function(FcovCyclicBound<A<FutureOr<dynamic>>>) x484;
+  void Function(FcovCyclicBound<A<FutureOr<void>>>) x485;
+  void Function(FcovCyclicBound<A<FutureOr<Object?>>>) x486;
+  void Function(FcovCyclicBound<A<A<dynamic>>>) x487;
+  void Function(FcovCyclicBound<A<A<void>>>) x488;
+  void Function(FcovCyclicBound<A<A<Object?>>>) x489;
+  void Function(FcovCyclicBound<A<A<FutureOr<dynamic>>>>) x490;
+  void Function(FcovCyclicBound<A<A<FutureOr<void>>>>) x491;
+  void Function(FcovCyclicBound<A<A<FutureOr<Object?>>>>) x492;
+  void Function(FcovCyclicCoBound<dynamic>) x493;
+  void Function(FcovCyclicCoBound<void>) x494;
+  void Function(FcovCyclicCoBound<Object?>) x495;
+  void Function(FcovCyclicCoBound<FutureOr<dynamic>>) x496;
+  void Function(FcovCyclicCoBound<FutureOr<void>>) x497;
+  void Function(FcovCyclicCoBound<FutureOr<Object?>>) x498;
+  void Function(FcovCyclicCoBound<Function(Function(dynamic))>) x499;
+  void Function(FcovCyclicCoBound<Function(Function(void))>) x500;
+  void Function(FcovCyclicCoBound<Function(Function(Object?))>) x501;
+  void Function(FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>) x502;
+  void Function(FcovCyclicCoBound<Function(Function(FutureOr<void>))>) x503;
+  void Function(FcovCyclicCoBound<Function(Function(FutureOr<Object?>))>) x504;
+  void Function(CFcov<dynamic>) x505;
+  void Function(CFcov<void>) x506;
+  void Function(CFcov<Object?>) x507;
+  void Function(CFcov<FutureOr<dynamic>>) x508;
+  void Function(CFcov<FutureOr<void>>) x509;
+  void Function(CFcov<FutureOr<Object?>>) x510;
+  void Function(CFcov<Fcov<dynamic>>) x511;
+  void Function(CFcov<Fcov<void>>) x512;
+  void Function(CFcov<Fcov<Object?>>) x513;
+  void Function(CFcov<Fcov<FutureOr<dynamic>>>) x514;
+  void Function(CFcov<Fcov<FutureOr<void>>>) x515;
+  void Function(CFcov<Fcov<FutureOr<Object?>>>) x516;
+  void Function(CFcov<Fcov<Fcov<dynamic>>>) x517;
+  void Function(CFcov<Fcov<Fcov<void>>>) x518;
+  void Function(CFcov<Fcov<Fcov<Object?>>>) x519;
+  void Function(CFcov<Fcov<Fcov<FutureOr<dynamic>>>>) x520;
+  void Function(CFcov<Fcov<Fcov<FutureOr<void>>>>) x521;
+  void Function(CFcov<Fcov<Fcov<FutureOr<Object?>>>>) x522;
+  void Function(CFcon<dynamic>) x523;
+  void Function(CFcon<void>) x524;
+  void Function(CFcon<Object?>) x525;
+  void Function(CFcon<FutureOr<dynamic>>) x526;
+  void Function(CFcon<FutureOr<void>>) x527;
+  void Function(CFcon<FutureOr<Object?>>) x528;
+  void Function(CFinv<dynamic>) x529;
+  void Function(CFinv<void>) x530;
+  void Function(CFinv<Object?>) x531;
+  void Function(CFinv<FutureOr<dynamic>>) x532;
+  void Function(CFinv<FutureOr<void>>) x533;
+  void Function(CFinv<FutureOr<Object?>>) x534;
+  void Function(CFunu<dynamic>) x535;
+  void Function(CFunu<void>) x536;
+  void Function(CFunu<Object?>) x537;
+  void Function(CFunu<FutureOr<dynamic>>) x538;
+  void Function(CFunu<FutureOr<void>>) x539;
+  void Function(CFunu<FutureOr<Object?>>) x540;
+  void Function(CcovBound<dynamic>) x541;
+  void Function(CcovBound<void>) x542;
+  void Function(CcovBound<Object?>) x543;
+  void Function(CcovBound<FutureOr<dynamic>>) x544;
+  void Function(CcovBound<FutureOr<void>>) x545;
+  void Function(CcovBound<FutureOr<Object?>>) x546;
+  void Function(CcovCyclicBound<dynamic>) x547;
+  void Function(CcovCyclicBound<void>) x548;
+  void Function(CcovCyclicBound<Object?>) x549;
+  void Function(CcovCyclicBound<FutureOr<dynamic>>) x550;
+  void Function(CcovCyclicBound<FutureOr<void>>) x551;
+  void Function(CcovCyclicBound<FutureOr<Object?>>) x552;
+  void Function(CcovCyclicBound<A<dynamic>>) x553;
+  void Function(CcovCyclicBound<A<void>>) x554;
+  void Function(CcovCyclicBound<A<Object?>>) x555;
+  void Function(CcovCyclicBound<A<FutureOr<dynamic>>>) x556;
+  void Function(CcovCyclicBound<A<FutureOr<void>>>) x557;
+  void Function(CcovCyclicBound<A<FutureOr<Object?>>>) x558;
+  void Function(CcovCyclicBound<A<A<dynamic>>>) x559;
+  void Function(CcovCyclicBound<A<A<void>>>) x560;
+  void Function(CcovCyclicBound<A<A<Object?>>>) x561;
+  void Function(CcovCyclicBound<A<A<FutureOr<dynamic>>>>) x562;
+  void Function(CcovCyclicBound<A<A<FutureOr<void>>>>) x563;
+  void Function(CcovCyclicBound<A<A<FutureOr<Object?>>>>) x564;
+  void Function(CcovCyclicCoBound<dynamic>) x565;
+  void Function(CcovCyclicCoBound<void>) x566;
+  void Function(CcovCyclicCoBound<Object?>) x567;
+  void Function(CcovCyclicCoBound<FutureOr<dynamic>>) x568;
+  void Function(CcovCyclicCoBound<FutureOr<void>>) x569;
+  void Function(CcovCyclicCoBound<FutureOr<Object?>>) x570;
+  void Function(CcovCyclicCoBound<Function(Function(dynamic))>) x571;
+  void Function(CcovCyclicCoBound<Function(Function(void))>) x572;
+  void Function(CcovCyclicCoBound<Function(Function(Object?))>) x573;
+  void Function(CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>) x574;
+  void Function(CcovCyclicCoBound<Function(Function(FutureOr<void>))>) x575;
+  void Function(CcovCyclicCoBound<Function(Function(FutureOr<Object?>))>) x576;
+  void Function(FcovBound<dynamic>) Function() x577;
+  void Function(FcovBound<void>) Function() x578;
+  void Function(FcovBound<Object?>) Function() x579;
+  void Function(FcovBound<FutureOr<dynamic>>) Function() x580;
+  void Function(FcovBound<FutureOr<void>>) Function() x581;
+  void Function(FcovBound<FutureOr<Object?>>) Function() x582;
+  void Function(FcovCyclicBound<dynamic>) Function() x583;
+  void Function(FcovCyclicBound<void>) Function() x584;
+  void Function(FcovCyclicBound<Object?>) Function() x585;
+  void Function(FcovCyclicBound<FutureOr<dynamic>>) Function() x586;
+  void Function(FcovCyclicBound<FutureOr<void>>) Function() x587;
+  void Function(FcovCyclicBound<FutureOr<Object?>>) Function() x588;
+  void Function(FcovCyclicBound<A<dynamic>>) Function() x589;
+  void Function(FcovCyclicBound<A<void>>) Function() x590;
+  void Function(FcovCyclicBound<A<Object?>>) Function() x591;
+  void Function(FcovCyclicBound<A<FutureOr<dynamic>>>) Function() x592;
+  void Function(FcovCyclicBound<A<FutureOr<void>>>) Function() x593;
+  void Function(FcovCyclicBound<A<FutureOr<Object?>>>) Function() x594;
+  void Function(FcovCyclicBound<A<A<dynamic>>>) Function() x595;
+  void Function(FcovCyclicBound<A<A<void>>>) Function() x596;
+  void Function(FcovCyclicBound<A<A<Object?>>>) Function() x597;
+  void Function(FcovCyclicBound<A<A<FutureOr<dynamic>>>>) Function() x598;
+  void Function(FcovCyclicBound<A<A<FutureOr<void>>>>) Function() x599;
+  void Function(FcovCyclicBound<A<A<FutureOr<Object?>>>>) Function() x600;
+  void Function(FcovCyclicCoBound<dynamic>) Function() x601;
+  void Function(FcovCyclicCoBound<void>) Function() x602;
+  void Function(FcovCyclicCoBound<Object?>) Function() x603;
+  void Function(FcovCyclicCoBound<FutureOr<dynamic>>) Function() x604;
+  void Function(FcovCyclicCoBound<FutureOr<void>>) Function() x605;
+  void Function(FcovCyclicCoBound<FutureOr<Object?>>) Function() x606;
+  void Function(FcovCyclicCoBound<Function(Function(dynamic))>) Function() x607;
+  void Function(FcovCyclicCoBound<Function(Function(void))>) Function() x608;
+  void Function(FcovCyclicCoBound<Function(Function(Object?))>) Function() x609;
+  void Function(FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>)
+      Function() x610;
+  void Function(FcovCyclicCoBound<Function(Function(FutureOr<void>))>)
+      Function() x611;
+  void Function(FcovCyclicCoBound<Function(Function(FutureOr<Object?>))>)
+      Function() x612;
+  void Function(CFcov<dynamic>) Function() x613;
+  void Function(CFcov<void>) Function() x614;
+  void Function(CFcov<Object?>) Function() x615;
+  void Function(CFcov<FutureOr<dynamic>>) Function() x616;
+  void Function(CFcov<FutureOr<void>>) Function() x617;
+  void Function(CFcov<FutureOr<Object?>>) Function() x618;
+  void Function(CFcov<Fcov<dynamic>>) Function() x619;
+  void Function(CFcov<Fcov<void>>) Function() x620;
+  void Function(CFcov<Fcov<Object?>>) Function() x621;
+  void Function(CFcov<Fcov<FutureOr<dynamic>>>) Function() x622;
+  void Function(CFcov<Fcov<FutureOr<void>>>) Function() x623;
+  void Function(CFcov<Fcov<FutureOr<Object?>>>) Function() x624;
+  void Function(CFcov<Fcov<Fcov<dynamic>>>) Function() x625;
+  void Function(CFcov<Fcov<Fcov<void>>>) Function() x626;
+  void Function(CFcov<Fcov<Fcov<Object?>>>) Function() x627;
+  void Function(CFcov<Fcov<Fcov<FutureOr<dynamic>>>>) Function() x628;
+  void Function(CFcov<Fcov<Fcov<FutureOr<void>>>>) Function() x629;
+  void Function(CFcov<Fcov<Fcov<FutureOr<Object?>>>>) Function() x630;
+  void Function(CFcon<dynamic>) Function() x631;
+  void Function(CFcon<void>) Function() x632;
+  void Function(CFcon<Object?>) Function() x633;
+  void Function(CFcon<FutureOr<dynamic>>) Function() x634;
+  void Function(CFcon<FutureOr<void>>) Function() x635;
+  void Function(CFcon<FutureOr<Object?>>) Function() x636;
+  void Function(CFinv<dynamic>) Function() x637;
+  void Function(CFinv<void>) Function() x638;
+  void Function(CFinv<Object?>) Function() x639;
+  void Function(CFinv<FutureOr<dynamic>>) Function() x640;
+  void Function(CFinv<FutureOr<void>>) Function() x641;
+  void Function(CFinv<FutureOr<Object?>>) Function() x642;
+  void Function(CFunu<dynamic>) Function() x643;
+  void Function(CFunu<void>) Function() x644;
+  void Function(CFunu<Object?>) Function() x645;
+  void Function(CFunu<FutureOr<dynamic>>) Function() x646;
+  void Function(CFunu<FutureOr<void>>) Function() x647;
+  void Function(CFunu<FutureOr<Object?>>) Function() x648;
+  void Function(CcovBound<dynamic>) Function() x649;
+  void Function(CcovBound<void>) Function() x650;
+  void Function(CcovBound<Object?>) Function() x651;
+  void Function(CcovBound<FutureOr<dynamic>>) Function() x652;
+  void Function(CcovBound<FutureOr<void>>) Function() x653;
+  void Function(CcovBound<FutureOr<Object?>>) Function() x654;
+  void Function(CcovCyclicBound<dynamic>) Function() x655;
+  void Function(CcovCyclicBound<void>) Function() x656;
+  void Function(CcovCyclicBound<Object?>) Function() x657;
+  void Function(CcovCyclicBound<FutureOr<dynamic>>) Function() x658;
+  void Function(CcovCyclicBound<FutureOr<void>>) Function() x659;
+  void Function(CcovCyclicBound<FutureOr<Object?>>) Function() x660;
+  void Function(CcovCyclicBound<A<dynamic>>) Function() x661;
+  void Function(CcovCyclicBound<A<void>>) Function() x662;
+  void Function(CcovCyclicBound<A<Object?>>) Function() x663;
+  void Function(CcovCyclicBound<A<FutureOr<dynamic>>>) Function() x664;
+  void Function(CcovCyclicBound<A<FutureOr<void>>>) Function() x665;
+  void Function(CcovCyclicBound<A<FutureOr<Object?>>>) Function() x666;
+  void Function(CcovCyclicBound<A<A<dynamic>>>) Function() x667;
+  void Function(CcovCyclicBound<A<A<void>>>) Function() x668;
+  void Function(CcovCyclicBound<A<A<Object?>>>) Function() x669;
+  void Function(CcovCyclicBound<A<A<FutureOr<dynamic>>>>) Function() x670;
+  void Function(CcovCyclicBound<A<A<FutureOr<void>>>>) Function() x671;
+  void Function(CcovCyclicBound<A<A<FutureOr<Object?>>>>) Function() x672;
+  void Function(CcovCyclicCoBound<dynamic>) Function() x673;
+  void Function(CcovCyclicCoBound<void>) Function() x674;
+  void Function(CcovCyclicCoBound<Object?>) Function() x675;
+  void Function(CcovCyclicCoBound<FutureOr<dynamic>>) Function() x676;
+  void Function(CcovCyclicCoBound<FutureOr<void>>) Function() x677;
+  void Function(CcovCyclicCoBound<FutureOr<Object?>>) Function() x678;
+  void Function(CcovCyclicCoBound<Function(Function(dynamic))>) Function() x679;
+  void Function(CcovCyclicCoBound<Function(Function(void))>) Function() x680;
+  void Function(CcovCyclicCoBound<Function(Function(Object?))>) Function() x681;
+  void Function(CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>)
+      Function() x682;
+  void Function(CcovCyclicCoBound<Function(Function(FutureOr<void>))>)
+      Function() x683;
+  void Function(CcovCyclicCoBound<Function(Function(FutureOr<Object?>))>)
+      Function() x684;
+  void Function<Y extends FcovBound<dynamic>>() x685;
+  void Function<Y extends FcovBound<void>>() x686;
+  void Function<Y extends FcovBound<Object?>>() x687;
+  void Function<Y extends FcovBound<FutureOr<dynamic>>>() x688;
+  void Function<Y extends FcovBound<FutureOr<void>>>() x689;
+  void Function<Y extends FcovBound<FutureOr<Object?>>>() x690;
+  void Function<Y extends FcovCyclicBound<dynamic>>() x691;
+  void Function<Y extends FcovCyclicBound<void>>() x692;
+  void Function<Y extends FcovCyclicBound<Object?>>() x693;
+  void Function<Y extends FcovCyclicBound<FutureOr<dynamic>>>() x694;
+  void Function<Y extends FcovCyclicBound<FutureOr<void>>>() x695;
+  void Function<Y extends FcovCyclicBound<FutureOr<Object?>>>() x696;
+  void Function<Y extends FcovCyclicBound<A<dynamic>>>() x697;
+  void Function<Y extends FcovCyclicBound<A<void>>>() x698;
+  void Function<Y extends FcovCyclicBound<A<Object?>>>() x699;
+  void Function<Y extends FcovCyclicBound<A<FutureOr<dynamic>>>>() x700;
+  void Function<Y extends FcovCyclicBound<A<FutureOr<void>>>>() x701;
+  void Function<Y extends FcovCyclicBound<A<FutureOr<Object?>>>>() x702;
+  void Function<Y extends FcovCyclicBound<A<A<dynamic>>>>() x703;
+  void Function<Y extends FcovCyclicBound<A<A<void>>>>() x704;
+  void Function<Y extends FcovCyclicBound<A<A<Object?>>>>() x705;
+  void Function<Y extends FcovCyclicBound<A<A<FutureOr<dynamic>>>>>() x706;
+  void Function<Y extends FcovCyclicBound<A<A<FutureOr<void>>>>>() x707;
+  void Function<Y extends FcovCyclicBound<A<A<FutureOr<Object?>>>>>() x708;
+  void Function<Y extends FcovCyclicCoBound<dynamic>>() x709;
+  void Function<Y extends FcovCyclicCoBound<void>>() x710;
+  void Function<Y extends FcovCyclicCoBound<Object?>>() x711;
+  void Function<Y extends FcovCyclicCoBound<FutureOr<dynamic>>>() x712;
+  void Function<Y extends FcovCyclicCoBound<FutureOr<void>>>() x713;
+  void Function<Y extends FcovCyclicCoBound<FutureOr<Object?>>>() x714;
+  void Function<Y extends FcovCyclicCoBound<Function(Function(dynamic))>>()
+      x715;
+  void Function<Y extends FcovCyclicCoBound<Function(Function(void))>>() x716;
+  void Function<Y extends FcovCyclicCoBound<Function(Function(Object?))>>()
+      x717;
+  void Function<
+          Y extends FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>>()
+      x718;
+  void Function<
+      Y extends FcovCyclicCoBound<Function(Function(FutureOr<void>))>>() x719;
+  void Function<
+          Y extends FcovCyclicCoBound<Function(Function(FutureOr<Object?>))>>()
+      x720;
+  void Function<Y extends CFcov<dynamic>>() x721;
+  void Function<Y extends CFcov<void>>() x722;
+  void Function<Y extends CFcov<Object?>>() x723;
+  void Function<Y extends CFcov<FutureOr<dynamic>>>() x724;
+  void Function<Y extends CFcov<FutureOr<void>>>() x725;
+  void Function<Y extends CFcov<FutureOr<Object?>>>() x726;
+  void Function<Y extends CFcov<Fcov<dynamic>>>() x727;
+  void Function<Y extends CFcov<Fcov<void>>>() x728;
+  void Function<Y extends CFcov<Fcov<Object?>>>() x729;
+  void Function<Y extends CFcov<Fcov<FutureOr<dynamic>>>>() x730;
+  void Function<Y extends CFcov<Fcov<FutureOr<void>>>>() x731;
+  void Function<Y extends CFcov<Fcov<FutureOr<Object?>>>>() x732;
+  void Function<Y extends CFcov<Fcov<Fcov<dynamic>>>>() x733;
+  void Function<Y extends CFcov<Fcov<Fcov<void>>>>() x734;
+  void Function<Y extends CFcov<Fcov<Fcov<Object?>>>>() x735;
+  void Function<Y extends CFcov<Fcov<Fcov<FutureOr<dynamic>>>>>() x736;
+  void Function<Y extends CFcov<Fcov<Fcov<FutureOr<void>>>>>() x737;
+  void Function<Y extends CFcov<Fcov<Fcov<FutureOr<Object?>>>>>() x738;
+  void Function<Y extends CFcon<dynamic>>() x739;
+  void Function<Y extends CFcon<void>>() x740;
+  void Function<Y extends CFcon<Object?>>() x741;
+  void Function<Y extends CFcon<FutureOr<dynamic>>>() x742;
+  void Function<Y extends CFcon<FutureOr<void>>>() x743;
+  void Function<Y extends CFcon<FutureOr<Object?>>>() x744;
+  void Function<Y extends CFinv<dynamic>>() x745;
+  void Function<Y extends CFinv<void>>() x746;
+  void Function<Y extends CFinv<Object?>>() x747;
+  void Function<Y extends CFinv<FutureOr<dynamic>>>() x748;
+  void Function<Y extends CFinv<FutureOr<void>>>() x749;
+  void Function<Y extends CFinv<FutureOr<Object?>>>() x750;
+  void Function<Y extends CFunu<dynamic>>() x751;
+  void Function<Y extends CFunu<void>>() x752;
+  void Function<Y extends CFunu<Object?>>() x753;
+  void Function<Y extends CFunu<FutureOr<dynamic>>>() x754;
+  void Function<Y extends CFunu<FutureOr<void>>>() x755;
+  void Function<Y extends CFunu<FutureOr<Object?>>>() x756;
+  void Function<Y extends CcovBound<dynamic>>() x757;
+  void Function<Y extends CcovBound<void>>() x758;
+  void Function<Y extends CcovBound<Object?>>() x759;
+  void Function<Y extends CcovBound<FutureOr<dynamic>>>() x760;
+  void Function<Y extends CcovBound<FutureOr<void>>>() x761;
+  void Function<Y extends CcovBound<FutureOr<Object?>>>() x762;
+  void Function<Y extends CcovCyclicBound<dynamic>>() x763;
+  void Function<Y extends CcovCyclicBound<void>>() x764;
+  void Function<Y extends CcovCyclicBound<Object?>>() x765;
+  void Function<Y extends CcovCyclicBound<FutureOr<dynamic>>>() x766;
+  void Function<Y extends CcovCyclicBound<FutureOr<void>>>() x767;
+  void Function<Y extends CcovCyclicBound<FutureOr<Object?>>>() x768;
+  void Function<Y extends CcovCyclicBound<A<dynamic>>>() x769;
+  void Function<Y extends CcovCyclicBound<A<void>>>() x770;
+  void Function<Y extends CcovCyclicBound<A<Object?>>>() x771;
+  void Function<Y extends CcovCyclicBound<A<FutureOr<dynamic>>>>() x772;
+  void Function<Y extends CcovCyclicBound<A<FutureOr<void>>>>() x773;
+  void Function<Y extends CcovCyclicBound<A<FutureOr<Object?>>>>() x774;
+  void Function<Y extends CcovCyclicBound<A<A<dynamic>>>>() x775;
+  void Function<Y extends CcovCyclicBound<A<A<void>>>>() x776;
+  void Function<Y extends CcovCyclicBound<A<A<Object?>>>>() x777;
+  void Function<Y extends CcovCyclicBound<A<A<FutureOr<dynamic>>>>>() x778;
+  void Function<Y extends CcovCyclicBound<A<A<FutureOr<void>>>>>() x779;
+  void Function<Y extends CcovCyclicBound<A<A<FutureOr<Object?>>>>>() x780;
+  void Function<Y extends CcovCyclicCoBound<dynamic>>() x781;
+  void Function<Y extends CcovCyclicCoBound<void>>() x782;
+  void Function<Y extends CcovCyclicCoBound<Object?>>() x783;
+  void Function<Y extends CcovCyclicCoBound<FutureOr<dynamic>>>() x784;
+  void Function<Y extends CcovCyclicCoBound<FutureOr<void>>>() x785;
+  void Function<Y extends CcovCyclicCoBound<FutureOr<Object?>>>() x786;
+  void Function<Y extends CcovCyclicCoBound<Function(Function(dynamic))>>()
+      x787;
+  void Function<Y extends CcovCyclicCoBound<Function(Function(void))>>() x788;
+  void Function<Y extends CcovCyclicCoBound<Function(Function(Object?))>>()
+      x789;
+  void Function<
+          Y extends CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>>()
+      x790;
+  void Function<
+      Y extends CcovCyclicCoBound<Function(Function(FutureOr<void>))>>() x791;
+  void Function<
+          Y extends CcovCyclicCoBound<Function(Function(FutureOr<Object?>))>>()
+      x792;
+  void Function<Y extends A<FcovBound<dynamic>>>() x793;
+  void Function<Y extends A<FcovBound<void>>>() x794;
+  void Function<Y extends A<FcovBound<Object?>>>() x795;
+  void Function<Y extends A<FcovBound<FutureOr<dynamic>>>>() x796;
+  void Function<Y extends A<FcovBound<FutureOr<void>>>>() x797;
+  void Function<Y extends A<FcovBound<FutureOr<Object?>>>>() x798;
+  void Function<Y extends A<FcovCyclicBound<dynamic>>>() x799;
+  void Function<Y extends A<FcovCyclicBound<void>>>() x800;
+  void Function<Y extends A<FcovCyclicBound<Object?>>>() x801;
+  void Function<Y extends A<FcovCyclicBound<FutureOr<dynamic>>>>() x802;
+  void Function<Y extends A<FcovCyclicBound<FutureOr<void>>>>() x803;
+  void Function<Y extends A<FcovCyclicBound<FutureOr<Object?>>>>() x804;
+  void Function<Y extends A<FcovCyclicBound<A<dynamic>>>>() x805;
+  void Function<Y extends A<FcovCyclicBound<A<void>>>>() x806;
+  void Function<Y extends A<FcovCyclicBound<A<Object?>>>>() x807;
+  void Function<Y extends A<FcovCyclicBound<A<FutureOr<dynamic>>>>>() x808;
+  void Function<Y extends A<FcovCyclicBound<A<FutureOr<void>>>>>() x809;
+  void Function<Y extends A<FcovCyclicBound<A<FutureOr<Object?>>>>>() x810;
+  void Function<Y extends A<FcovCyclicBound<A<A<dynamic>>>>>() x811;
+  void Function<Y extends A<FcovCyclicBound<A<A<void>>>>>() x812;
+  void Function<Y extends A<FcovCyclicBound<A<A<Object?>>>>>() x813;
+  void Function<Y extends A<FcovCyclicBound<A<A<FutureOr<dynamic>>>>>>() x814;
+  void Function<Y extends A<FcovCyclicBound<A<A<FutureOr<void>>>>>>() x815;
+  void Function<Y extends A<FcovCyclicBound<A<A<FutureOr<Object?>>>>>>() x816;
+  void Function<Y extends A<FcovCyclicCoBound<dynamic>>>() x817;
+  void Function<Y extends A<FcovCyclicCoBound<void>>>() x818;
+  void Function<Y extends A<FcovCyclicCoBound<Object?>>>() x819;
+  void Function<Y extends A<FcovCyclicCoBound<FutureOr<dynamic>>>>() x820;
+  void Function<Y extends A<FcovCyclicCoBound<FutureOr<void>>>>() x821;
+  void Function<Y extends A<FcovCyclicCoBound<FutureOr<Object?>>>>() x822;
+  void Function<Y extends A<FcovCyclicCoBound<Function(Function(dynamic))>>>()
+      x823;
+  void Function<Y extends A<FcovCyclicCoBound<Function(Function(void))>>>()
+      x824;
+  void Function<Y extends A<FcovCyclicCoBound<Function(Function(Object?))>>>()
+      x825;
+  void Function<
+      Y extends A<
+          FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>>>() x826;
+  void Function<
+          Y extends A<FcovCyclicCoBound<Function(Function(FutureOr<void>))>>>()
+      x827;
+  void Function<
+      Y extends A<
+          FcovCyclicCoBound<Function(Function(FutureOr<Object?>))>>>() x828;
+  void Function<Y extends A<CFcov<dynamic>>>() x829;
+  void Function<Y extends A<CFcov<void>>>() x830;
+  void Function<Y extends A<CFcov<Object?>>>() x831;
+  void Function<Y extends A<CFcov<FutureOr<dynamic>>>>() x832;
+  void Function<Y extends A<CFcov<FutureOr<void>>>>() x833;
+  void Function<Y extends A<CFcov<FutureOr<Object?>>>>() x834;
+  void Function<Y extends A<CFcov<Fcov<dynamic>>>>() x835;
+  void Function<Y extends A<CFcov<Fcov<void>>>>() x836;
+  void Function<Y extends A<CFcov<Fcov<Object?>>>>() x837;
+  void Function<Y extends A<CFcov<Fcov<FutureOr<dynamic>>>>>() x838;
+  void Function<Y extends A<CFcov<Fcov<FutureOr<void>>>>>() x839;
+  void Function<Y extends A<CFcov<Fcov<FutureOr<Object?>>>>>() x840;
+  void Function<Y extends A<CFcov<Fcov<Fcov<dynamic>>>>>() x841;
+  void Function<Y extends A<CFcov<Fcov<Fcov<void>>>>>() x842;
+  void Function<Y extends A<CFcov<Fcov<Fcov<Object?>>>>>() x843;
+  void Function<Y extends A<CFcov<Fcov<Fcov<FutureOr<dynamic>>>>>>() x844;
+  void Function<Y extends A<CFcov<Fcov<Fcov<FutureOr<void>>>>>>() x845;
+  void Function<Y extends A<CFcov<Fcov<Fcov<FutureOr<Object?>>>>>>() x846;
+  void Function<Y extends A<CFcon<dynamic>>>() x847;
+  void Function<Y extends A<CFcon<void>>>() x848;
+  void Function<Y extends A<CFcon<Object?>>>() x849;
+  void Function<Y extends A<CFcon<FutureOr<dynamic>>>>() x850;
+  void Function<Y extends A<CFcon<FutureOr<void>>>>() x851;
+  void Function<Y extends A<CFcon<FutureOr<Object?>>>>() x852;
+  void Function<Y extends A<CFinv<dynamic>>>() x853;
+  void Function<Y extends A<CFinv<void>>>() x854;
+  void Function<Y extends A<CFinv<Object?>>>() x855;
+  void Function<Y extends A<CFinv<FutureOr<dynamic>>>>() x856;
+  void Function<Y extends A<CFinv<FutureOr<void>>>>() x857;
+  void Function<Y extends A<CFinv<FutureOr<Object?>>>>() x858;
+  void Function<Y extends A<CFunu<dynamic>>>() x859;
+  void Function<Y extends A<CFunu<void>>>() x860;
+  void Function<Y extends A<CFunu<Object?>>>() x861;
+  void Function<Y extends A<CFunu<FutureOr<dynamic>>>>() x862;
+  void Function<Y extends A<CFunu<FutureOr<void>>>>() x863;
+  void Function<Y extends A<CFunu<FutureOr<Object?>>>>() x864;
+  void Function<Y extends A<CcovBound<dynamic>>>() x865;
+  void Function<Y extends A<CcovBound<void>>>() x866;
+  void Function<Y extends A<CcovBound<Object?>>>() x867;
+  void Function<Y extends A<CcovBound<FutureOr<dynamic>>>>() x868;
+  void Function<Y extends A<CcovBound<FutureOr<void>>>>() x869;
+  void Function<Y extends A<CcovBound<FutureOr<Object?>>>>() x870;
+  void Function<Y extends A<CcovCyclicBound<dynamic>>>() x871;
+  void Function<Y extends A<CcovCyclicBound<void>>>() x872;
+  void Function<Y extends A<CcovCyclicBound<Object?>>>() x873;
+  void Function<Y extends A<CcovCyclicBound<FutureOr<dynamic>>>>() x874;
+  void Function<Y extends A<CcovCyclicBound<FutureOr<void>>>>() x875;
+  void Function<Y extends A<CcovCyclicBound<FutureOr<Object?>>>>() x876;
+  void Function<Y extends A<CcovCyclicBound<A<dynamic>>>>() x877;
+  void Function<Y extends A<CcovCyclicBound<A<void>>>>() x878;
+  void Function<Y extends A<CcovCyclicBound<A<Object?>>>>() x879;
+  void Function<Y extends A<CcovCyclicBound<A<FutureOr<dynamic>>>>>() x880;
+  void Function<Y extends A<CcovCyclicBound<A<FutureOr<void>>>>>() x881;
+  void Function<Y extends A<CcovCyclicBound<A<FutureOr<Object?>>>>>() x882;
+  void Function<Y extends A<CcovCyclicBound<A<A<dynamic>>>>>() x883;
+  void Function<Y extends A<CcovCyclicBound<A<A<void>>>>>() x884;
+  void Function<Y extends A<CcovCyclicBound<A<A<Object?>>>>>() x885;
+  void Function<Y extends A<CcovCyclicBound<A<A<FutureOr<dynamic>>>>>>() x886;
+  void Function<Y extends A<CcovCyclicBound<A<A<FutureOr<void>>>>>>() x887;
+  void Function<Y extends A<CcovCyclicBound<A<A<FutureOr<Object?>>>>>>() x888;
+  void Function<Y extends A<CcovCyclicCoBound<dynamic>>>() x889;
+  void Function<Y extends A<CcovCyclicCoBound<void>>>() x890;
+  void Function<Y extends A<CcovCyclicCoBound<Object?>>>() x891;
+  void Function<Y extends A<CcovCyclicCoBound<FutureOr<dynamic>>>>() x892;
+  void Function<Y extends A<CcovCyclicCoBound<FutureOr<void>>>>() x893;
+  void Function<Y extends A<CcovCyclicCoBound<FutureOr<Object?>>>>() x894;
+  void Function<Y extends A<CcovCyclicCoBound<Function(Function(dynamic))>>>()
+      x895;
+  void Function<Y extends A<CcovCyclicCoBound<Function(Function(void))>>>()
+      x896;
+  void Function<Y extends A<CcovCyclicCoBound<Function(Function(Object?))>>>()
+      x897;
+  void Function<
+      Y extends A<
+          CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>>>() x898;
+  void Function<
+          Y extends A<CcovCyclicCoBound<Function(Function(FutureOr<void>))>>>()
+      x899;
+  void Function<
+      Y extends A<
+          CcovCyclicCoBound<Function(Function(FutureOr<Object?>))>>>() x900;
+  Finv<FcovBound<dynamic>> x901;
+  Finv<FcovBound<void>> x902;
+  Finv<FcovBound<Object?>> x903;
+  Finv<FcovBound<FutureOr<dynamic>>> x904;
+  Finv<FcovBound<FutureOr<void>>> x905;
+  Finv<FcovBound<FutureOr<Object?>>> x906;
+  Finv<FcovCyclicBound<dynamic>> x907;
+  Finv<FcovCyclicBound<void>> x908;
+  Finv<FcovCyclicBound<Object?>> x909;
+  Finv<FcovCyclicBound<FutureOr<dynamic>>> x910;
+  Finv<FcovCyclicBound<FutureOr<void>>> x911;
+  Finv<FcovCyclicBound<FutureOr<Object?>>> x912;
+  Finv<FcovCyclicBound<A<dynamic>>> x913;
+  Finv<FcovCyclicBound<A<void>>> x914;
+  Finv<FcovCyclicBound<A<Object?>>> x915;
+  Finv<FcovCyclicBound<A<FutureOr<dynamic>>>> x916;
+  Finv<FcovCyclicBound<A<FutureOr<void>>>> x917;
+  Finv<FcovCyclicBound<A<FutureOr<Object?>>>> x918;
+  Finv<FcovCyclicBound<A<A<dynamic>>>> x919;
+  Finv<FcovCyclicBound<A<A<void>>>> x920;
+  Finv<FcovCyclicBound<A<A<Object?>>>> x921;
+  Finv<FcovCyclicBound<A<A<FutureOr<dynamic>>>>> x922;
+  Finv<FcovCyclicBound<A<A<FutureOr<void>>>>> x923;
+  Finv<FcovCyclicBound<A<A<FutureOr<Object?>>>>> x924;
+  Finv<FcovCyclicCoBound<dynamic>> x925;
+  Finv<FcovCyclicCoBound<void>> x926;
+  Finv<FcovCyclicCoBound<Object?>> x927;
+  Finv<FcovCyclicCoBound<FutureOr<dynamic>>> x928;
+  Finv<FcovCyclicCoBound<FutureOr<void>>> x929;
+  Finv<FcovCyclicCoBound<FutureOr<Object?>>> x930;
+  Finv<FcovCyclicCoBound<Function(Function(dynamic))>> x931;
+  Finv<FcovCyclicCoBound<Function(Function(void))>> x932;
+  Finv<FcovCyclicCoBound<Function(Function(Object?))>> x933;
+  Finv<FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x934;
+  Finv<FcovCyclicCoBound<Function(Function(FutureOr<void>))>> x935;
+  Finv<FcovCyclicCoBound<Function(Function(FutureOr<Object?>))>> x936;
+  Finv<CFcov<dynamic>> x937;
+  Finv<CFcov<void>> x938;
+  Finv<CFcov<Object?>> x939;
+  Finv<CFcov<FutureOr<dynamic>>> x940;
+  Finv<CFcov<FutureOr<void>>> x941;
+  Finv<CFcov<FutureOr<Object?>>> x942;
+  Finv<CFcov<Fcov<dynamic>>> x943;
+  Finv<CFcov<Fcov<void>>> x944;
+  Finv<CFcov<Fcov<Object?>>> x945;
+  Finv<CFcov<Fcov<FutureOr<dynamic>>>> x946;
+  Finv<CFcov<Fcov<FutureOr<void>>>> x947;
+  Finv<CFcov<Fcov<FutureOr<Object?>>>> x948;
+  Finv<CFcov<Fcov<Fcov<dynamic>>>> x949;
+  Finv<CFcov<Fcov<Fcov<void>>>> x950;
+  Finv<CFcov<Fcov<Fcov<Object?>>>> x951;
+  Finv<CFcov<Fcov<Fcov<FutureOr<dynamic>>>>> x952;
+  Finv<CFcov<Fcov<Fcov<FutureOr<void>>>>> x953;
+  Finv<CFcov<Fcov<Fcov<FutureOr<Object?>>>>> x954;
+  Finv<CFcon<dynamic>> x955;
+  Finv<CFcon<void>> x956;
+  Finv<CFcon<Object?>> x957;
+  Finv<CFcon<FutureOr<dynamic>>> x958;
+  Finv<CFcon<FutureOr<void>>> x959;
+  Finv<CFcon<FutureOr<Object?>>> x960;
+  Finv<CFinv<dynamic>> x961;
+  Finv<CFinv<void>> x962;
+  Finv<CFinv<Object?>> x963;
+  Finv<CFinv<FutureOr<dynamic>>> x964;
+  Finv<CFinv<FutureOr<void>>> x965;
+  Finv<CFinv<FutureOr<Object?>>> x966;
+  Finv<CFunu<dynamic>> x967;
+  Finv<CFunu<void>> x968;
+  Finv<CFunu<Object?>> x969;
+  Finv<CFunu<FutureOr<dynamic>>> x970;
+  Finv<CFunu<FutureOr<void>>> x971;
+  Finv<CFunu<FutureOr<Object?>>> x972;
+  Finv<CcovBound<dynamic>> x973;
+  Finv<CcovBound<void>> x974;
+  Finv<CcovBound<Object?>> x975;
+  Finv<CcovBound<FutureOr<dynamic>>> x976;
+  Finv<CcovBound<FutureOr<void>>> x977;
+  Finv<CcovBound<FutureOr<Object?>>> x978;
+  Finv<CcovCyclicBound<dynamic>> x979;
+  Finv<CcovCyclicBound<void>> x980;
+  Finv<CcovCyclicBound<Object?>> x981;
+  Finv<CcovCyclicBound<FutureOr<dynamic>>> x982;
+  Finv<CcovCyclicBound<FutureOr<void>>> x983;
+  Finv<CcovCyclicBound<FutureOr<Object?>>> x984;
+  Finv<CcovCyclicBound<A<dynamic>>> x985;
+  Finv<CcovCyclicBound<A<void>>> x986;
+  Finv<CcovCyclicBound<A<Object?>>> x987;
+  Finv<CcovCyclicBound<A<FutureOr<dynamic>>>> x988;
+  Finv<CcovCyclicBound<A<FutureOr<void>>>> x989;
+  Finv<CcovCyclicBound<A<FutureOr<Object?>>>> x990;
+  Finv<CcovCyclicBound<A<A<dynamic>>>> x991;
+  Finv<CcovCyclicBound<A<A<void>>>> x992;
+  Finv<CcovCyclicBound<A<A<Object?>>>> x993;
+  Finv<CcovCyclicBound<A<A<FutureOr<dynamic>>>>> x994;
+  Finv<CcovCyclicBound<A<A<FutureOr<void>>>>> x995;
+  Finv<CcovCyclicBound<A<A<FutureOr<Object?>>>>> x996;
+  Finv<CcovCyclicCoBound<dynamic>> x997;
+  Finv<CcovCyclicCoBound<void>> x998;
+  Finv<CcovCyclicCoBound<Object?>> x999;
+  Finv<CcovCyclicCoBound<FutureOr<dynamic>>> x1000;
+  Finv<CcovCyclicCoBound<FutureOr<void>>> x1001;
+  Finv<CcovCyclicCoBound<FutureOr<Object?>>> x1002;
+  Finv<CcovCyclicCoBound<Function(Function(dynamic))>> x1003;
+  Finv<CcovCyclicCoBound<Function(Function(void))>> x1004;
+  Finv<CcovCyclicCoBound<Function(Function(Object?))>> x1005;
+  Finv<CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x1006;
+  Finv<CcovCyclicCoBound<Function(Function(FutureOr<void>))>> x1007;
+  Finv<CcovCyclicCoBound<Function(Function(FutureOr<Object?>))>> x1008;
+  Funu<FcovBound<dynamic>> x1009;
+  Funu<FcovBound<void>> x1010;
+  Funu<FcovBound<Object?>> x1011;
+  Funu<FcovBound<FutureOr<dynamic>>> x1012;
+  Funu<FcovBound<FutureOr<void>>> x1013;
+  Funu<FcovBound<FutureOr<Object?>>> x1014;
+  Funu<FcovCyclicBound<dynamic>> x1015;
+  Funu<FcovCyclicBound<void>> x1016;
+  Funu<FcovCyclicBound<Object?>> x1017;
+  Funu<FcovCyclicBound<FutureOr<dynamic>>> x1018;
+  Funu<FcovCyclicBound<FutureOr<void>>> x1019;
+  Funu<FcovCyclicBound<FutureOr<Object?>>> x1020;
+  Funu<FcovCyclicBound<A<dynamic>>> x1021;
+  Funu<FcovCyclicBound<A<void>>> x1022;
+  Funu<FcovCyclicBound<A<Object?>>> x1023;
+  Funu<FcovCyclicBound<A<FutureOr<dynamic>>>> x1024;
+  Funu<FcovCyclicBound<A<FutureOr<void>>>> x1025;
+  Funu<FcovCyclicBound<A<FutureOr<Object?>>>> x1026;
+  Funu<FcovCyclicBound<A<A<dynamic>>>> x1027;
+  Funu<FcovCyclicBound<A<A<void>>>> x1028;
+  Funu<FcovCyclicBound<A<A<Object?>>>> x1029;
+  Funu<FcovCyclicBound<A<A<FutureOr<dynamic>>>>> x1030;
+  Funu<FcovCyclicBound<A<A<FutureOr<void>>>>> x1031;
+  Funu<FcovCyclicBound<A<A<FutureOr<Object?>>>>> x1032;
+  Funu<FcovCyclicCoBound<dynamic>> x1033;
+  Funu<FcovCyclicCoBound<void>> x1034;
+  Funu<FcovCyclicCoBound<Object?>> x1035;
+  Funu<FcovCyclicCoBound<FutureOr<dynamic>>> x1036;
+  Funu<FcovCyclicCoBound<FutureOr<void>>> x1037;
+  Funu<FcovCyclicCoBound<FutureOr<Object?>>> x1038;
+  Funu<FcovCyclicCoBound<Function(Function(dynamic))>> x1039;
+  Funu<FcovCyclicCoBound<Function(Function(void))>> x1040;
+  Funu<FcovCyclicCoBound<Function(Function(Object?))>> x1041;
+  Funu<FcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x1042;
+  Funu<FcovCyclicCoBound<Function(Function(FutureOr<void>))>> x1043;
+  Funu<FcovCyclicCoBound<Function(Function(FutureOr<Object?>))>> x1044;
+  Funu<CFcov<dynamic>> x1045;
+  Funu<CFcov<void>> x1046;
+  Funu<CFcov<Object?>> x1047;
+  Funu<CFcov<FutureOr<dynamic>>> x1048;
+  Funu<CFcov<FutureOr<void>>> x1049;
+  Funu<CFcov<FutureOr<Object?>>> x1050;
+  Funu<CFcov<Fcov<dynamic>>> x1051;
+  Funu<CFcov<Fcov<void>>> x1052;
+  Funu<CFcov<Fcov<Object?>>> x1053;
+  Funu<CFcov<Fcov<FutureOr<dynamic>>>> x1054;
+  Funu<CFcov<Fcov<FutureOr<void>>>> x1055;
+  Funu<CFcov<Fcov<FutureOr<Object?>>>> x1056;
+  Funu<CFcov<Fcov<Fcov<dynamic>>>> x1057;
+  Funu<CFcov<Fcov<Fcov<void>>>> x1058;
+  Funu<CFcov<Fcov<Fcov<Object?>>>> x1059;
+  Funu<CFcov<Fcov<Fcov<FutureOr<dynamic>>>>> x1060;
+  Funu<CFcov<Fcov<Fcov<FutureOr<void>>>>> x1061;
+  Funu<CFcov<Fcov<Fcov<FutureOr<Object?>>>>> x1062;
+  Funu<CFcon<dynamic>> x1063;
+  Funu<CFcon<void>> x1064;
+  Funu<CFcon<Object?>> x1065;
+  Funu<CFcon<FutureOr<dynamic>>> x1066;
+  Funu<CFcon<FutureOr<void>>> x1067;
+  Funu<CFcon<FutureOr<Object?>>> x1068;
+  Funu<CFinv<dynamic>> x1069;
+  Funu<CFinv<void>> x1070;
+  Funu<CFinv<Object?>> x1071;
+  Funu<CFinv<FutureOr<dynamic>>> x1072;
+  Funu<CFinv<FutureOr<void>>> x1073;
+  Funu<CFinv<FutureOr<Object?>>> x1074;
+  Funu<CFunu<dynamic>> x1075;
+  Funu<CFunu<void>> x1076;
+  Funu<CFunu<Object?>> x1077;
+  Funu<CFunu<FutureOr<dynamic>>> x1078;
+  Funu<CFunu<FutureOr<void>>> x1079;
+  Funu<CFunu<FutureOr<Object?>>> x1080;
+  Funu<CcovBound<dynamic>> x1081;
+  Funu<CcovBound<void>> x1082;
+  Funu<CcovBound<Object?>> x1083;
+  Funu<CcovBound<FutureOr<dynamic>>> x1084;
+  Funu<CcovBound<FutureOr<void>>> x1085;
+  Funu<CcovBound<FutureOr<Object?>>> x1086;
+  Funu<CcovCyclicBound<dynamic>> x1087;
+  Funu<CcovCyclicBound<void>> x1088;
+  Funu<CcovCyclicBound<Object?>> x1089;
+  Funu<CcovCyclicBound<FutureOr<dynamic>>> x1090;
+  Funu<CcovCyclicBound<FutureOr<void>>> x1091;
+  Funu<CcovCyclicBound<FutureOr<Object?>>> x1092;
+  Funu<CcovCyclicBound<A<dynamic>>> x1093;
+  Funu<CcovCyclicBound<A<void>>> x1094;
+  Funu<CcovCyclicBound<A<Object?>>> x1095;
+  Funu<CcovCyclicBound<A<FutureOr<dynamic>>>> x1096;
+  Funu<CcovCyclicBound<A<FutureOr<void>>>> x1097;
+  Funu<CcovCyclicBound<A<FutureOr<Object?>>>> x1098;
+  Funu<CcovCyclicBound<A<A<dynamic>>>> x1099;
+  Funu<CcovCyclicBound<A<A<void>>>> x1100;
+  Funu<CcovCyclicBound<A<A<Object?>>>> x1101;
+  Funu<CcovCyclicBound<A<A<FutureOr<dynamic>>>>> x1102;
+  Funu<CcovCyclicBound<A<A<FutureOr<void>>>>> x1103;
+  Funu<CcovCyclicBound<A<A<FutureOr<Object?>>>>> x1104;
+  Funu<CcovCyclicCoBound<dynamic>> x1105;
+  Funu<CcovCyclicCoBound<void>> x1106;
+  Funu<CcovCyclicCoBound<Object?>> x1107;
+  Funu<CcovCyclicCoBound<FutureOr<dynamic>>> x1108;
+  Funu<CcovCyclicCoBound<FutureOr<void>>> x1109;
+  Funu<CcovCyclicCoBound<FutureOr<Object?>>> x1110;
+  Funu<CcovCyclicCoBound<Function(Function(dynamic))>> x1111;
+  Funu<CcovCyclicCoBound<Function(Function(void))>> x1112;
+  Funu<CcovCyclicCoBound<Function(Function(Object?))>> x1113;
+  Funu<CcovCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x1114;
+  Funu<CcovCyclicCoBound<Function(Function(FutureOr<void>))>> x1115;
+  Funu<CcovCyclicCoBound<Function(Function(FutureOr<Object?>))>> x1116;
+}
+
+void testContravariantSuperbound<N extends Never>() {
+  // Top type in a contravariant position, regular-bounded.
+  FcovCyclicCoBound<Function(dynamic)> x1;
+  FcovCyclicCoBound<Function(void)> x2;
+  FcovCyclicCoBound<Function(Object?)> x3;
+  FcovCyclicCoBound<Function(FutureOr<dynamic>)> x4;
+  FcovCyclicCoBound<Function(FutureOr<void>)> x5;
+  FcovCyclicCoBound<Function(FutureOr<Object?>)> x6;
+  CFcon<Fcon<dynamic>> x7;
+  CFcon<Fcon<void>> x8;
+  CFcon<Fcon<Object?>> x9;
+  CFcon<Fcon<FutureOr<dynamic>>> x10;
+  CFcon<Fcon<FutureOr<void>>> x11;
+  CFcon<Fcon<FutureOr<Object?>>> x12;
+  CcovCyclicCoBound<Function(dynamic)> x13;
+  CcovCyclicCoBound<Function(void)> x14;
+  CcovCyclicCoBound<Function(Object?)> x15;
+  CcovCyclicCoBound<Function(FutureOr<dynamic>)> x16;
+  CcovCyclicCoBound<Function(FutureOr<void>)> x17;
+  CcovCyclicCoBound<Function(FutureOr<Object?>)> x18;
+
+  // Bottom type in a contravariant position, super-bounded.
+  FcovCyclicCoBound<Function(Never)> x19;
+  FcovCyclicCoBound<Function(N)> x20;
+  CFcon<Fcon<Never>> x21;
+  CFcon<Fcon<N>> x22;
+  CcovCyclicCoBound<Function(Never)> x23;
+  CcovCyclicCoBound<Function(N)> x24;
+
+  // Super-bounded types in a context.
+  A<FcovCyclicCoBound<Function(Never)>> x25;
+  A<FcovCyclicCoBound<Function(N)>> x26;
+  A<CFcon<Fcon<Never>>> x27;
+  A<CFcon<Fcon<N>>> x28;
+  A<CcovCyclicCoBound<Function(Never)>> x29;
+  A<CcovCyclicCoBound<Function(N)>> x30;
+  FcovCyclicCoBound<Function(Never)> Function() x31;
+  FcovCyclicCoBound<Function(N)> Function() x32;
+  CFcon<Fcon<Never>> Function() x33;
+  CFcon<Fcon<N>> Function() x34;
+  CcovCyclicCoBound<Function(Never)> Function() x35;
+  CcovCyclicCoBound<Function(N)> Function() x36;
+  void Function(void Function(FcovCyclicCoBound<Function(Never)>)) x37;
+  void Function(void Function(FcovCyclicCoBound<Function(N)>)) x38;
+  void Function(void Function(CFcon<Fcon<Never>>)) x39;
+  void Function(void Function(CFcon<Fcon<N>>)) x40;
+  void Function(void Function(CcovCyclicCoBound<Function(Never)>)) x41;
+  void Function(void Function(CcovCyclicCoBound<Function(N)>)) x42;
+  void Function(FcovCyclicCoBound<Function(Never)>) x43;
+  void Function(FcovCyclicCoBound<Function(N)>) x44;
+  void Function(CFcon<Fcon<Never>>) x45;
+  void Function(CFcon<Fcon<N>>) x46;
+  void Function(CcovCyclicCoBound<Function(Never)>) x47;
+  void Function(CcovCyclicCoBound<Function(N)>) x48;
+  void Function(FcovCyclicCoBound<Function(Never)>) Function() x49;
+  void Function(FcovCyclicCoBound<Function(N)>) Function() x50;
+  void Function(CFcon<Fcon<Never>>) Function() x51;
+  void Function(CFcon<Fcon<N>>) Function() x52;
+  void Function(CcovCyclicCoBound<Function(Never)>) Function() x53;
+  void Function(CcovCyclicCoBound<Function(N)>) Function() x54;
+  void Function<Y extends FcovCyclicCoBound<Function(Never)>>() x55;
+  void Function<Y extends FcovCyclicCoBound<Function(N)>>() x56;
+  void Function<Y extends CFcon<Fcon<Never>>>() x57;
+  void Function<Y extends CFcon<Fcon<N>>>() x58;
+  void Function<Y extends CcovCyclicCoBound<Function(Never)>>() x59;
+  void Function<Y extends CcovCyclicCoBound<Function(N)>>() x60;
+  void Function<Y extends A<FcovCyclicCoBound<Function(Never)>>>() x61;
+  void Function<Y extends A<FcovCyclicCoBound<Function(N)>>>() x62;
+  void Function<Y extends A<CFcon<Fcon<Never>>>>() x63;
+  void Function<Y extends A<CFcon<Fcon<N>>>>() x64;
+  void Function<Y extends A<CcovCyclicCoBound<Function(Never)>>>() x65;
+  void Function<Y extends A<CcovCyclicCoBound<Function(N)>>>() x66;
+  Finv<FcovCyclicCoBound<Function(Never)>> x67;
+  Finv<FcovCyclicCoBound<Function(N)>> x68;
+  Finv<CFcon<Fcon<Never>>> x69;
+  Finv<CFcon<Fcon<N>>> x70;
+  Finv<CcovCyclicCoBound<Function(Never)>> x71;
+  Finv<CcovCyclicCoBound<Function(N)>> x72;
+  Funu<FcovCyclicCoBound<Function(Never)>> x73;
+  Funu<FcovCyclicCoBound<Function(N)>> x74;
+  Funu<CFcon<Fcon<Never>>> x75;
+  Funu<CFcon<Fcon<N>>> x76;
+  Funu<CcovCyclicCoBound<Function(Never)>> x77;
+  Funu<CcovCyclicCoBound<Function(N)>> x78;
+}
+
+void testInvariantSuperbound<N extends Never>() {
+  // Bottom type in an invariant position, regular-bounded.
+  FinvBound<Never> x1;
+  FinvBound<N> x2;
+  FinvCyclicBound<Never> x3;
+  FinvCyclicBound<N> x4;
+  FinvCyclicBound<A<Never>> x5;
+  FinvCyclicBound<A<N>> x6;
+  FinvCyclicBound<A<A<Never>>> x7;
+  FinvCyclicBound<A<A<N>>> x8;
+  FinvCyclicCoBound<Never> x9;
+  FinvCyclicCoBound<N> x10;
+  FinvCyclicCoBound<Function(Function(Never))> x11;
+  FinvCyclicCoBound<Function(Function(N))> x12;
+
+  // Top type in an invariant position, super-bounded.
+  FinvBound<dynamic> x13;
+  FinvBound<void> x14;
+  FinvBound<Object?> x15;
+  FinvBound<FutureOr<dynamic>> x16;
+  FinvBound<FutureOr<void>> x17;
+  FinvBound<FutureOr<Object?>> x18;
+  FinvCyclicBound<dynamic> x19;
+  FinvCyclicBound<void> x20;
+  FinvCyclicBound<Object?> x21;
+  FinvCyclicBound<FutureOr<dynamic>> x22;
+  FinvCyclicBound<FutureOr<void>> x23;
+  FinvCyclicBound<FutureOr<Object?>> x24;
+  FinvCyclicBound<A<dynamic>> x25;
+  FinvCyclicBound<A<void>> x26;
+  FinvCyclicBound<A<Object?>> x27;
+  FinvCyclicBound<A<FutureOr<dynamic>>> x28;
+  FinvCyclicBound<A<FutureOr<void>>> x29;
+  FinvCyclicBound<A<FutureOr<Object?>>> x30;
+  FinvCyclicBound<A<A<dynamic>>> x31;
+  FinvCyclicBound<A<A<void>>> x32;
+  FinvCyclicBound<A<A<Object?>>> x33;
+  FinvCyclicBound<A<A<FutureOr<dynamic>>>> x34;
+  FinvCyclicBound<A<A<FutureOr<void>>>> x35;
+  FinvCyclicBound<A<A<FutureOr<Object?>>>> x36;
+  FinvCyclicCoBound<dynamic> x37;
+  FinvCyclicCoBound<void> x38;
+  FinvCyclicCoBound<Object?> x39;
+  FinvCyclicCoBound<FutureOr<dynamic>> x40;
+  FinvCyclicCoBound<FutureOr<void>> x41;
+  FinvCyclicCoBound<FutureOr<Object?>> x42;
+  FinvCyclicCoBound<Function(Function(dynamic))> x43;
+  FinvCyclicCoBound<Function(Function(void))> x44;
+  FinvCyclicCoBound<Function(Function(Object?))> x45;
+  FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))> x46;
+  FinvCyclicCoBound<Function(Function(FutureOr<void>))> x47;
+  FinvCyclicCoBound<Function(Function(FutureOr<Object?>))> x48;
+
+  // Super-bounded types in a context.
+  A<FinvBound<dynamic>> x49;
+  A<FinvBound<void>> x50;
+  A<FinvBound<Object?>> x51;
+  A<FinvBound<FutureOr<dynamic>>> x52;
+  A<FinvBound<FutureOr<void>>> x53;
+  A<FinvBound<FutureOr<Object?>>> x54;
+  A<FinvCyclicBound<dynamic>> x55;
+  A<FinvCyclicBound<void>> x56;
+  A<FinvCyclicBound<Object?>> x57;
+  A<FinvCyclicBound<FutureOr<dynamic>>> x58;
+  A<FinvCyclicBound<FutureOr<void>>> x59;
+  A<FinvCyclicBound<FutureOr<Object?>>> x60;
+  A<FinvCyclicBound<A<dynamic>>> x61;
+  A<FinvCyclicBound<A<void>>> x62;
+  A<FinvCyclicBound<A<Object?>>> x63;
+  A<FinvCyclicBound<A<FutureOr<dynamic>>>> x64;
+  A<FinvCyclicBound<A<FutureOr<void>>>> x65;
+  A<FinvCyclicBound<A<FutureOr<Object?>>>> x66;
+  A<FinvCyclicBound<A<A<dynamic>>>> x67;
+  A<FinvCyclicBound<A<A<void>>>> x68;
+  A<FinvCyclicBound<A<A<Object?>>>> x69;
+  A<FinvCyclicBound<A<A<FutureOr<dynamic>>>>> x70;
+  A<FinvCyclicBound<A<A<FutureOr<void>>>>> x71;
+  A<FinvCyclicBound<A<A<FutureOr<Object?>>>>> x72;
+  A<FinvCyclicCoBound<dynamic>> x73;
+  A<FinvCyclicCoBound<void>> x74;
+  A<FinvCyclicCoBound<Object?>> x75;
+  A<FinvCyclicCoBound<FutureOr<dynamic>>> x76;
+  A<FinvCyclicCoBound<FutureOr<void>>> x77;
+  A<FinvCyclicCoBound<FutureOr<Object?>>> x78;
+  A<FinvCyclicCoBound<Function(Function(dynamic))>> x79;
+  A<FinvCyclicCoBound<Function(Function(void))>> x80;
+  A<FinvCyclicCoBound<Function(Function(Object?))>> x81;
+  A<FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x82;
+  A<FinvCyclicCoBound<Function(Function(FutureOr<void>))>> x83;
+  A<FinvCyclicCoBound<Function(Function(FutureOr<Object?>))>> x84;
+  FinvBound<dynamic> Function() x85;
+  FinvBound<void> Function() x86;
+  FinvBound<Object?> Function() x87;
+  FinvBound<FutureOr<dynamic>> Function() x88;
+  FinvBound<FutureOr<void>> Function() x89;
+  FinvBound<FutureOr<Object?>> Function() x90;
+  FinvCyclicBound<dynamic> Function() x91;
+  FinvCyclicBound<void> Function() x92;
+  FinvCyclicBound<Object?> Function() x93;
+  FinvCyclicBound<FutureOr<dynamic>> Function() x94;
+  FinvCyclicBound<FutureOr<void>> Function() x95;
+  FinvCyclicBound<FutureOr<Object?>> Function() x96;
+  FinvCyclicBound<A<dynamic>> Function() x97;
+  FinvCyclicBound<A<void>> Function() x98;
+  FinvCyclicBound<A<Object?>> Function() x99;
+  FinvCyclicBound<A<FutureOr<dynamic>>> Function() x100;
+  FinvCyclicBound<A<FutureOr<void>>> Function() x101;
+  FinvCyclicBound<A<FutureOr<Object?>>> Function() x102;
+  FinvCyclicBound<A<A<dynamic>>> Function() x103;
+  FinvCyclicBound<A<A<void>>> Function() x104;
+  FinvCyclicBound<A<A<Object?>>> Function() x105;
+  FinvCyclicBound<A<A<FutureOr<dynamic>>>> Function() x106;
+  FinvCyclicBound<A<A<FutureOr<void>>>> Function() x107;
+  FinvCyclicBound<A<A<FutureOr<Object?>>>> Function() x108;
+  FinvCyclicCoBound<dynamic> Function() x109;
+  FinvCyclicCoBound<void> Function() x110;
+  FinvCyclicCoBound<Object?> Function() x111;
+  FinvCyclicCoBound<FutureOr<dynamic>> Function() x112;
+  FinvCyclicCoBound<FutureOr<void>> Function() x113;
+  FinvCyclicCoBound<FutureOr<Object?>> Function() x114;
+  FinvCyclicCoBound<Function(Function(dynamic))> Function() x115;
+  FinvCyclicCoBound<Function(Function(void))> Function() x116;
+  FinvCyclicCoBound<Function(Function(Object?))> Function() x117;
+  FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))> Function() x118;
+  FinvCyclicCoBound<Function(Function(FutureOr<void>))> Function() x119;
+  FinvCyclicCoBound<Function(Function(FutureOr<Object?>))> Function() x120;
+  void Function(void Function(FinvBound<dynamic>)) x121;
+  void Function(void Function(FinvBound<void>)) x122;
+  void Function(void Function(FinvBound<Object?>)) x123;
+  void Function(void Function(FinvBound<FutureOr<dynamic>>)) x124;
+  void Function(void Function(FinvBound<FutureOr<void>>)) x125;
+  void Function(void Function(FinvBound<FutureOr<Object?>>)) x126;
+  void Function(void Function(FinvCyclicBound<dynamic>)) x127;
+  void Function(void Function(FinvCyclicBound<void>)) x128;
+  void Function(void Function(FinvCyclicBound<Object?>)) x129;
+  void Function(void Function(FinvCyclicBound<FutureOr<dynamic>>)) x130;
+  void Function(void Function(FinvCyclicBound<FutureOr<void>>)) x131;
+  void Function(void Function(FinvCyclicBound<FutureOr<Object?>>)) x132;
+  void Function(void Function(FinvCyclicBound<A<dynamic>>)) x133;
+  void Function(void Function(FinvCyclicBound<A<void>>)) x134;
+  void Function(void Function(FinvCyclicBound<A<Object?>>)) x135;
+  void Function(void Function(FinvCyclicBound<A<FutureOr<dynamic>>>)) x136;
+  void Function(void Function(FinvCyclicBound<A<FutureOr<void>>>)) x137;
+  void Function(void Function(FinvCyclicBound<A<FutureOr<Object?>>>)) x138;
+  void Function(void Function(FinvCyclicBound<A<A<dynamic>>>)) x139;
+  void Function(void Function(FinvCyclicBound<A<A<void>>>)) x140;
+  void Function(void Function(FinvCyclicBound<A<A<Object?>>>)) x141;
+  void Function(void Function(FinvCyclicBound<A<A<FutureOr<dynamic>>>>)) x142;
+  void Function(void Function(FinvCyclicBound<A<A<FutureOr<void>>>>)) x143;
+  void Function(void Function(FinvCyclicBound<A<A<FutureOr<Object?>>>>)) x144;
+  void Function(void Function(FinvCyclicCoBound<dynamic>)) x145;
+  void Function(void Function(FinvCyclicCoBound<void>)) x146;
+  void Function(void Function(FinvCyclicCoBound<Object?>)) x147;
+  void Function(void Function(FinvCyclicCoBound<FutureOr<dynamic>>)) x148;
+  void Function(void Function(FinvCyclicCoBound<FutureOr<void>>)) x149;
+  void Function(void Function(FinvCyclicCoBound<FutureOr<Object?>>)) x150;
+  void Function(void Function(FinvCyclicCoBound<Function(Function(dynamic))>))
+      x151;
+  void Function(void Function(FinvCyclicCoBound<Function(Function(void))>))
+      x152;
+  void Function(void Function(FinvCyclicCoBound<Function(Function(Object?))>))
+      x153;
+  void Function(
+      void Function(
+          FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))>)) x154;
+  void Function(
+          void Function(FinvCyclicCoBound<Function(Function(FutureOr<void>))>))
+      x155;
+  void Function(
+      void Function(
+          FinvCyclicCoBound<Function(Function(FutureOr<Object?>))>)) x156;
+  void Function(FinvBound<dynamic>) x157;
+  void Function(FinvBound<void>) x158;
+  void Function(FinvBound<Object?>) x159;
+  void Function(FinvBound<FutureOr<dynamic>>) x160;
+  void Function(FinvBound<FutureOr<void>>) x161;
+  void Function(FinvBound<FutureOr<Object?>>) x162;
+  void Function(FinvCyclicBound<dynamic>) x163;
+  void Function(FinvCyclicBound<void>) x164;
+  void Function(FinvCyclicBound<Object?>) x165;
+  void Function(FinvCyclicBound<FutureOr<dynamic>>) x166;
+  void Function(FinvCyclicBound<FutureOr<void>>) x167;
+  void Function(FinvCyclicBound<FutureOr<Object?>>) x168;
+  void Function(FinvCyclicBound<A<dynamic>>) x169;
+  void Function(FinvCyclicBound<A<void>>) x170;
+  void Function(FinvCyclicBound<A<Object?>>) x171;
+  void Function(FinvCyclicBound<A<FutureOr<dynamic>>>) x172;
+  void Function(FinvCyclicBound<A<FutureOr<void>>>) x173;
+  void Function(FinvCyclicBound<A<FutureOr<Object?>>>) x174;
+  void Function(FinvCyclicBound<A<A<dynamic>>>) x175;
+  void Function(FinvCyclicBound<A<A<void>>>) x176;
+  void Function(FinvCyclicBound<A<A<Object?>>>) x177;
+  void Function(FinvCyclicBound<A<A<FutureOr<dynamic>>>>) x178;
+  void Function(FinvCyclicBound<A<A<FutureOr<void>>>>) x179;
+  void Function(FinvCyclicBound<A<A<FutureOr<Object?>>>>) x180;
+  void Function(FinvCyclicCoBound<dynamic>) x181;
+  void Function(FinvCyclicCoBound<void>) x182;
+  void Function(FinvCyclicCoBound<Object?>) x183;
+  void Function(FinvCyclicCoBound<FutureOr<dynamic>>) x184;
+  void Function(FinvCyclicCoBound<FutureOr<void>>) x185;
+  void Function(FinvCyclicCoBound<FutureOr<Object?>>) x186;
+  void Function(FinvCyclicCoBound<Function(Function(dynamic))>) x187;
+  void Function(FinvCyclicCoBound<Function(Function(void))>) x188;
+  void Function(FinvCyclicCoBound<Function(Function(Object?))>) x189;
+  void Function(FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))>) x190;
+  void Function(FinvCyclicCoBound<Function(Function(FutureOr<void>))>) x191;
+  void Function(FinvCyclicCoBound<Function(Function(FutureOr<Object?>))>) x192;
+  void Function(FinvBound<dynamic>) Function() x193;
+  void Function(FinvBound<void>) Function() x194;
+  void Function(FinvBound<Object?>) Function() x195;
+  void Function(FinvBound<FutureOr<dynamic>>) Function() x196;
+  void Function(FinvBound<FutureOr<void>>) Function() x197;
+  void Function(FinvBound<FutureOr<Object?>>) Function() x198;
+  void Function(FinvCyclicBound<dynamic>) Function() x199;
+  void Function(FinvCyclicBound<void>) Function() x200;
+  void Function(FinvCyclicBound<Object?>) Function() x201;
+  void Function(FinvCyclicBound<FutureOr<dynamic>>) Function() x202;
+  void Function(FinvCyclicBound<FutureOr<void>>) Function() x203;
+  void Function(FinvCyclicBound<FutureOr<Object?>>) Function() x204;
+  void Function(FinvCyclicBound<A<dynamic>>) Function() x205;
+  void Function(FinvCyclicBound<A<void>>) Function() x206;
+  void Function(FinvCyclicBound<A<Object?>>) Function() x207;
+  void Function(FinvCyclicBound<A<FutureOr<dynamic>>>) Function() x208;
+  void Function(FinvCyclicBound<A<FutureOr<void>>>) Function() x209;
+  void Function(FinvCyclicBound<A<FutureOr<Object?>>>) Function() x210;
+  void Function(FinvCyclicBound<A<A<dynamic>>>) Function() x211;
+  void Function(FinvCyclicBound<A<A<void>>>) Function() x212;
+  void Function(FinvCyclicBound<A<A<Object?>>>) Function() x213;
+  void Function(FinvCyclicBound<A<A<FutureOr<dynamic>>>>) Function() x214;
+  void Function(FinvCyclicBound<A<A<FutureOr<void>>>>) Function() x215;
+  void Function(FinvCyclicBound<A<A<FutureOr<Object?>>>>) Function() x216;
+  void Function(FinvCyclicCoBound<dynamic>) Function() x217;
+  void Function(FinvCyclicCoBound<void>) Function() x218;
+  void Function(FinvCyclicCoBound<Object?>) Function() x219;
+  void Function(FinvCyclicCoBound<FutureOr<dynamic>>) Function() x220;
+  void Function(FinvCyclicCoBound<FutureOr<void>>) Function() x221;
+  void Function(FinvCyclicCoBound<FutureOr<Object?>>) Function() x222;
+  void Function(FinvCyclicCoBound<Function(Function(dynamic))>) Function() x223;
+  void Function(FinvCyclicCoBound<Function(Function(void))>) Function() x224;
+  void Function(FinvCyclicCoBound<Function(Function(Object?))>) Function() x225;
+  void Function(FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))>)
+      Function() x226;
+  void Function(FinvCyclicCoBound<Function(Function(FutureOr<void>))>)
+      Function() x227;
+  void Function(FinvCyclicCoBound<Function(Function(FutureOr<Object?>))>)
+      Function() x228;
+  void Function<Y extends FinvBound<dynamic>>() x229;
+  void Function<Y extends FinvBound<void>>() x230;
+  void Function<Y extends FinvBound<Object?>>() x231;
+  void Function<Y extends FinvBound<FutureOr<dynamic>>>() x232;
+  void Function<Y extends FinvBound<FutureOr<void>>>() x233;
+  void Function<Y extends FinvBound<FutureOr<Object?>>>() x234;
+  void Function<Y extends FinvCyclicBound<dynamic>>() x235;
+  void Function<Y extends FinvCyclicBound<void>>() x236;
+  void Function<Y extends FinvCyclicBound<Object?>>() x237;
+  void Function<Y extends FinvCyclicBound<FutureOr<dynamic>>>() x238;
+  void Function<Y extends FinvCyclicBound<FutureOr<void>>>() x239;
+  void Function<Y extends FinvCyclicBound<FutureOr<Object?>>>() x240;
+  void Function<Y extends FinvCyclicBound<A<dynamic>>>() x241;
+  void Function<Y extends FinvCyclicBound<A<void>>>() x242;
+  void Function<Y extends FinvCyclicBound<A<Object?>>>() x243;
+  void Function<Y extends FinvCyclicBound<A<FutureOr<dynamic>>>>() x244;
+  void Function<Y extends FinvCyclicBound<A<FutureOr<void>>>>() x245;
+  void Function<Y extends FinvCyclicBound<A<FutureOr<Object?>>>>() x246;
+  void Function<Y extends FinvCyclicBound<A<A<dynamic>>>>() x247;
+  void Function<Y extends FinvCyclicBound<A<A<void>>>>() x248;
+  void Function<Y extends FinvCyclicBound<A<A<Object?>>>>() x249;
+  void Function<Y extends FinvCyclicBound<A<A<FutureOr<dynamic>>>>>() x250;
+  void Function<Y extends FinvCyclicBound<A<A<FutureOr<void>>>>>() x251;
+  void Function<Y extends FinvCyclicBound<A<A<FutureOr<Object?>>>>>() x252;
+  void Function<Y extends FinvCyclicCoBound<dynamic>>() x253;
+  void Function<Y extends FinvCyclicCoBound<void>>() x254;
+  void Function<Y extends FinvCyclicCoBound<Object?>>() x255;
+  void Function<Y extends FinvCyclicCoBound<FutureOr<dynamic>>>() x256;
+  void Function<Y extends FinvCyclicCoBound<FutureOr<void>>>() x257;
+  void Function<Y extends FinvCyclicCoBound<FutureOr<Object?>>>() x258;
+  void Function<Y extends FinvCyclicCoBound<Function(Function(dynamic))>>()
+      x259;
+  void Function<Y extends FinvCyclicCoBound<Function(Function(void))>>() x260;
+  void Function<Y extends FinvCyclicCoBound<Function(Function(Object?))>>()
+      x261;
+  void Function<
+          Y extends FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))>>()
+      x262;
+  void Function<
+      Y extends FinvCyclicCoBound<Function(Function(FutureOr<void>))>>() x263;
+  void Function<
+          Y extends FinvCyclicCoBound<Function(Function(FutureOr<Object?>))>>()
+      x264;
+  void Function<Y extends A<FinvBound<dynamic>>>() x265;
+  void Function<Y extends A<FinvBound<void>>>() x266;
+  void Function<Y extends A<FinvBound<Object?>>>() x267;
+  void Function<Y extends A<FinvBound<FutureOr<dynamic>>>>() x268;
+  void Function<Y extends A<FinvBound<FutureOr<void>>>>() x269;
+  void Function<Y extends A<FinvBound<FutureOr<Object?>>>>() x270;
+  void Function<Y extends A<FinvCyclicBound<dynamic>>>() x271;
+  void Function<Y extends A<FinvCyclicBound<void>>>() x272;
+  void Function<Y extends A<FinvCyclicBound<Object?>>>() x273;
+  void Function<Y extends A<FinvCyclicBound<FutureOr<dynamic>>>>() x274;
+  void Function<Y extends A<FinvCyclicBound<FutureOr<void>>>>() x275;
+  void Function<Y extends A<FinvCyclicBound<FutureOr<Object?>>>>() x276;
+  void Function<Y extends A<FinvCyclicBound<A<dynamic>>>>() x277;
+  void Function<Y extends A<FinvCyclicBound<A<void>>>>() x278;
+  void Function<Y extends A<FinvCyclicBound<A<Object?>>>>() x279;
+  void Function<Y extends A<FinvCyclicBound<A<FutureOr<dynamic>>>>>() x280;
+  void Function<Y extends A<FinvCyclicBound<A<FutureOr<void>>>>>() x281;
+  void Function<Y extends A<FinvCyclicBound<A<FutureOr<Object?>>>>>() x282;
+  void Function<Y extends A<FinvCyclicBound<A<A<dynamic>>>>>() x283;
+  void Function<Y extends A<FinvCyclicBound<A<A<void>>>>>() x284;
+  void Function<Y extends A<FinvCyclicBound<A<A<Object?>>>>>() x285;
+  void Function<Y extends A<FinvCyclicBound<A<A<FutureOr<dynamic>>>>>>() x286;
+  void Function<Y extends A<FinvCyclicBound<A<A<FutureOr<void>>>>>>() x287;
+  void Function<Y extends A<FinvCyclicBound<A<A<FutureOr<Object?>>>>>>() x288;
+  void Function<Y extends A<FinvCyclicCoBound<dynamic>>>() x289;
+  void Function<Y extends A<FinvCyclicCoBound<void>>>() x290;
+  void Function<Y extends A<FinvCyclicCoBound<Object?>>>() x291;
+  void Function<Y extends A<FinvCyclicCoBound<FutureOr<dynamic>>>>() x292;
+  void Function<Y extends A<FinvCyclicCoBound<FutureOr<void>>>>() x293;
+  void Function<Y extends A<FinvCyclicCoBound<FutureOr<Object?>>>>() x294;
+  void Function<Y extends A<FinvCyclicCoBound<Function(Function(dynamic))>>>()
+      x295;
+  void Function<Y extends A<FinvCyclicCoBound<Function(Function(void))>>>()
+      x296;
+  void Function<Y extends A<FinvCyclicCoBound<Function(Function(Object?))>>>()
+      x297;
+  void Function<
+      Y extends A<
+          FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))>>>() x298;
+  void Function<
+          Y extends A<FinvCyclicCoBound<Function(Function(FutureOr<void>))>>>()
+      x299;
+  void Function<
+      Y extends A<
+          FinvCyclicCoBound<Function(Function(FutureOr<Object?>))>>>() x300;
+  Finv<FinvBound<dynamic>> x301;
+  Finv<FinvBound<void>> x302;
+  Finv<FinvBound<Object?>> x303;
+  Finv<FinvBound<FutureOr<dynamic>>> x304;
+  Finv<FinvBound<FutureOr<void>>> x305;
+  Finv<FinvBound<FutureOr<Object?>>> x306;
+  Finv<FinvCyclicBound<dynamic>> x307;
+  Finv<FinvCyclicBound<void>> x308;
+  Finv<FinvCyclicBound<Object?>> x309;
+  Finv<FinvCyclicBound<FutureOr<dynamic>>> x310;
+  Finv<FinvCyclicBound<FutureOr<void>>> x311;
+  Finv<FinvCyclicBound<FutureOr<Object?>>> x312;
+  Finv<FinvCyclicBound<A<dynamic>>> x313;
+  Finv<FinvCyclicBound<A<void>>> x314;
+  Finv<FinvCyclicBound<A<Object?>>> x315;
+  Finv<FinvCyclicBound<A<FutureOr<dynamic>>>> x316;
+  Finv<FinvCyclicBound<A<FutureOr<void>>>> x317;
+  Finv<FinvCyclicBound<A<FutureOr<Object?>>>> x318;
+  Finv<FinvCyclicBound<A<A<dynamic>>>> x319;
+  Finv<FinvCyclicBound<A<A<void>>>> x320;
+  Finv<FinvCyclicBound<A<A<Object?>>>> x321;
+  Finv<FinvCyclicBound<A<A<FutureOr<dynamic>>>>> x322;
+  Finv<FinvCyclicBound<A<A<FutureOr<void>>>>> x323;
+  Finv<FinvCyclicBound<A<A<FutureOr<Object?>>>>> x324;
+  Finv<FinvCyclicCoBound<dynamic>> x325;
+  Finv<FinvCyclicCoBound<void>> x326;
+  Finv<FinvCyclicCoBound<Object?>> x327;
+  Finv<FinvCyclicCoBound<FutureOr<dynamic>>> x328;
+  Finv<FinvCyclicCoBound<FutureOr<void>>> x329;
+  Finv<FinvCyclicCoBound<FutureOr<Object?>>> x330;
+  Finv<FinvCyclicCoBound<Function(Function(dynamic))>> x331;
+  Finv<FinvCyclicCoBound<Function(Function(void))>> x332;
+  Finv<FinvCyclicCoBound<Function(Function(Object?))>> x333;
+  Finv<FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x334;
+  Finv<FinvCyclicCoBound<Function(Function(FutureOr<void>))>> x335;
+  Finv<FinvCyclicCoBound<Function(Function(FutureOr<Object?>))>> x336;
+  Funu<FinvBound<dynamic>> x337;
+  Funu<FinvBound<void>> x338;
+  Funu<FinvBound<Object?>> x339;
+  Funu<FinvBound<FutureOr<dynamic>>> x340;
+  Funu<FinvBound<FutureOr<void>>> x341;
+  Funu<FinvBound<FutureOr<Object?>>> x342;
+  Funu<FinvCyclicBound<dynamic>> x343;
+  Funu<FinvCyclicBound<void>> x344;
+  Funu<FinvCyclicBound<Object?>> x345;
+  Funu<FinvCyclicBound<FutureOr<dynamic>>> x346;
+  Funu<FinvCyclicBound<FutureOr<void>>> x347;
+  Funu<FinvCyclicBound<FutureOr<Object?>>> x348;
+  Funu<FinvCyclicBound<A<dynamic>>> x349;
+  Funu<FinvCyclicBound<A<void>>> x350;
+  Funu<FinvCyclicBound<A<Object?>>> x351;
+  Funu<FinvCyclicBound<A<FutureOr<dynamic>>>> x352;
+  Funu<FinvCyclicBound<A<FutureOr<void>>>> x353;
+  Funu<FinvCyclicBound<A<FutureOr<Object?>>>> x354;
+  Funu<FinvCyclicBound<A<A<dynamic>>>> x355;
+  Funu<FinvCyclicBound<A<A<void>>>> x356;
+  Funu<FinvCyclicBound<A<A<Object?>>>> x357;
+  Funu<FinvCyclicBound<A<A<FutureOr<dynamic>>>>> x358;
+  Funu<FinvCyclicBound<A<A<FutureOr<void>>>>> x359;
+  Funu<FinvCyclicBound<A<A<FutureOr<Object?>>>>> x360;
+  Funu<FinvCyclicCoBound<dynamic>> x361;
+  Funu<FinvCyclicCoBound<void>> x362;
+  Funu<FinvCyclicCoBound<Object?>> x363;
+  Funu<FinvCyclicCoBound<FutureOr<dynamic>>> x364;
+  Funu<FinvCyclicCoBound<FutureOr<void>>> x365;
+  Funu<FinvCyclicCoBound<FutureOr<Object?>>> x366;
+  Funu<FinvCyclicCoBound<Function(Function(dynamic))>> x367;
+  Funu<FinvCyclicCoBound<Function(Function(void))>> x368;
+  Funu<FinvCyclicCoBound<Function(Function(Object?))>> x369;
+  Funu<FinvCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x370;
+  Funu<FinvCyclicCoBound<Function(Function(FutureOr<void>))>> x371;
+  Funu<FinvCyclicCoBound<Function(Function(FutureOr<Object?>))>> x372;
+}
+
+void testVarianceLessSuperbound<N extends Never>() {
+  // Bottom type in a variance-less position, regular-bounded.
+  FunuBound<Never> x1;
+  FunuBound<N> x2;
+  FunuCyclicBound<Never> x3;
+  FunuCyclicBound<N> x4;
+  FunuCyclicBound<A<Never>> x5;
+  FunuCyclicBound<A<N>> x6;
+  FunuCyclicBound<A<A<Never>>> x7;
+  FunuCyclicBound<A<A<N>>> x8;
+  FunuCyclicCoBound<Never> x9;
+  FunuCyclicCoBound<N> x10;
+  FunuCyclicCoBound<Function(Function(Never))> x11;
+  FunuCyclicCoBound<Function(Function(N))> x12;
+  CFunu<Funu<Never>> x13;
+  CFunu<Funu<N>> x14;
+  CFunu<Funu<Funu<Never>>> x15;
+  CFunu<Funu<Funu<N>>> x16;
+
+  // Top type in a variance-less position, super-bounded.
+  FunuBound<dynamic> x17;
+  FunuBound<void> x18;
+  FunuBound<Object?> x19;
+  FunuBound<FutureOr<dynamic>> x20;
+  FunuBound<FutureOr<void>> x21;
+  FunuBound<FutureOr<Object?>> x22;
+  FunuCyclicBound<dynamic> x23;
+  FunuCyclicBound<void> x24;
+  FunuCyclicBound<Object?> x25;
+  FunuCyclicBound<FutureOr<dynamic>> x26;
+  FunuCyclicBound<FutureOr<void>> x27;
+  FunuCyclicBound<FutureOr<Object?>> x28;
+  FunuCyclicBound<A<dynamic>> x29;
+  FunuCyclicBound<A<void>> x30;
+  FunuCyclicBound<A<Object?>> x31;
+  FunuCyclicBound<A<FutureOr<dynamic>>> x32;
+  FunuCyclicBound<A<FutureOr<void>>> x33;
+  FunuCyclicBound<A<FutureOr<Object?>>> x34;
+  FunuCyclicBound<A<A<dynamic>>> x35;
+  FunuCyclicBound<A<A<void>>> x36;
+  FunuCyclicBound<A<A<Object?>>> x37;
+  FunuCyclicBound<A<A<FutureOr<dynamic>>>> x38;
+  FunuCyclicBound<A<A<FutureOr<void>>>> x39;
+  FunuCyclicBound<A<A<FutureOr<Object?>>>> x40;
+  FunuCyclicCoBound<dynamic> x41;
+  FunuCyclicCoBound<void> x42;
+  FunuCyclicCoBound<Object?> x43;
+  FunuCyclicCoBound<FutureOr<dynamic>> x44;
+  FunuCyclicCoBound<FutureOr<void>> x45;
+  FunuCyclicCoBound<FutureOr<Object?>> x46;
+  FunuCyclicCoBound<Function(dynamic)> x47;
+  FunuCyclicCoBound<Function(void)> x48;
+  FunuCyclicCoBound<Function(Object?)> x49;
+  FunuCyclicCoBound<Function(FutureOr<dynamic>)> x50;
+  FunuCyclicCoBound<Function(FutureOr<void>)> x51;
+  FunuCyclicCoBound<Function(FutureOr<Object?>)> x52;
+  FunuCyclicCoBound<Function(Function(dynamic))> x53;
+  FunuCyclicCoBound<Function(Function(void))> x54;
+  FunuCyclicCoBound<Function(Function(Object?))> x55;
+  FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))> x56;
+  FunuCyclicCoBound<Function(Function(FutureOr<void>))> x57;
+  FunuCyclicCoBound<Function(Function(FutureOr<Object?>))> x58;
+  CFunu<Funu<dynamic>> x59;
+  CFunu<Funu<void>> x60;
+  CFunu<Funu<Object?>> x61;
+  CFunu<Funu<FutureOr<dynamic>>> x62;
+  CFunu<Funu<FutureOr<void>>> x63;
+  CFunu<Funu<FutureOr<Object?>>> x64;
+  CFunu<Funu<Funu<dynamic>>> x65;
+  CFunu<Funu<Funu<void>>> x66;
+  CFunu<Funu<Funu<Object?>>> x67;
+  CFunu<Funu<Funu<FutureOr<dynamic>>>> x68;
+  CFunu<Funu<Funu<FutureOr<void>>>> x69;
+  CFunu<Funu<Funu<FutureOr<Object?>>>> x70;
+
+  // Super-bounded types in a context.
+  A<FunuBound<dynamic>> x71;
+  A<FunuBound<void>> x72;
+  A<FunuBound<Object?>> x73;
+  A<FunuBound<FutureOr<dynamic>>> x74;
+  A<FunuBound<FutureOr<void>>> x75;
+  A<FunuBound<FutureOr<Object?>>> x76;
+  A<FunuCyclicBound<dynamic>> x77;
+  A<FunuCyclicBound<void>> x78;
+  A<FunuCyclicBound<Object?>> x79;
+  A<FunuCyclicBound<FutureOr<dynamic>>> x80;
+  A<FunuCyclicBound<FutureOr<void>>> x81;
+  A<FunuCyclicBound<FutureOr<Object?>>> x82;
+  A<FunuCyclicBound<A<dynamic>>> x83;
+  A<FunuCyclicBound<A<void>>> x84;
+  A<FunuCyclicBound<A<Object?>>> x85;
+  A<FunuCyclicBound<A<FutureOr<dynamic>>>> x86;
+  A<FunuCyclicBound<A<FutureOr<void>>>> x87;
+  A<FunuCyclicBound<A<FutureOr<Object?>>>> x88;
+  A<FunuCyclicBound<A<A<dynamic>>>> x89;
+  A<FunuCyclicBound<A<A<void>>>> x90;
+  A<FunuCyclicBound<A<A<Object?>>>> x91;
+  A<FunuCyclicBound<A<A<FutureOr<dynamic>>>>> x92;
+  A<FunuCyclicBound<A<A<FutureOr<void>>>>> x93;
+  A<FunuCyclicBound<A<A<FutureOr<Object?>>>>> x94;
+  A<FunuCyclicCoBound<dynamic>> x95;
+  A<FunuCyclicCoBound<void>> x96;
+  A<FunuCyclicCoBound<Object?>> x97;
+  A<FunuCyclicCoBound<FutureOr<dynamic>>> x98;
+  A<FunuCyclicCoBound<FutureOr<void>>> x99;
+  A<FunuCyclicCoBound<FutureOr<Object?>>> x100;
+  A<FunuCyclicCoBound<Function(dynamic)>> x101;
+  A<FunuCyclicCoBound<Function(void)>> x102;
+  A<FunuCyclicCoBound<Function(Object?)>> x103;
+  A<FunuCyclicCoBound<Function(FutureOr<dynamic>)>> x104;
+  A<FunuCyclicCoBound<Function(FutureOr<void>)>> x105;
+  A<FunuCyclicCoBound<Function(FutureOr<Object?>)>> x106;
+  A<FunuCyclicCoBound<Function(Function(dynamic))>> x107;
+  A<FunuCyclicCoBound<Function(Function(void))>> x108;
+  A<FunuCyclicCoBound<Function(Function(Object?))>> x109;
+  A<FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x110;
+  A<FunuCyclicCoBound<Function(Function(FutureOr<void>))>> x111;
+  A<FunuCyclicCoBound<Function(Function(FutureOr<Object?>))>> x112;
+  A<CFunu<Funu<dynamic>>> x113;
+  A<CFunu<Funu<void>>> x114;
+  A<CFunu<Funu<Object?>>> x115;
+  A<CFunu<Funu<FutureOr<dynamic>>>> x116;
+  A<CFunu<Funu<FutureOr<void>>>> x117;
+  A<CFunu<Funu<FutureOr<Object?>>>> x118;
+  A<CFunu<Funu<Funu<dynamic>>>> x119;
+  A<CFunu<Funu<Funu<void>>>> x120;
+  A<CFunu<Funu<Funu<Object?>>>> x121;
+  A<CFunu<Funu<Funu<FutureOr<dynamic>>>>> x122;
+  A<CFunu<Funu<Funu<FutureOr<void>>>>> x123;
+  A<CFunu<Funu<Funu<FutureOr<Object?>>>>> x124;
+  FunuBound<dynamic> Function() x125;
+  FunuBound<void> Function() x126;
+  FunuBound<Object?> Function() x127;
+  FunuBound<FutureOr<dynamic>> Function() x128;
+  FunuBound<FutureOr<void>> Function() x129;
+  FunuBound<FutureOr<Object?>> Function() x130;
+  FunuCyclicBound<dynamic> Function() x131;
+  FunuCyclicBound<void> Function() x132;
+  FunuCyclicBound<Object?> Function() x133;
+  FunuCyclicBound<FutureOr<dynamic>> Function() x134;
+  FunuCyclicBound<FutureOr<void>> Function() x135;
+  FunuCyclicBound<FutureOr<Object?>> Function() x136;
+  FunuCyclicBound<A<dynamic>> Function() x137;
+  FunuCyclicBound<A<void>> Function() x138;
+  FunuCyclicBound<A<Object?>> Function() x139;
+  FunuCyclicBound<A<FutureOr<dynamic>>> Function() x140;
+  FunuCyclicBound<A<FutureOr<void>>> Function() x141;
+  FunuCyclicBound<A<FutureOr<Object?>>> Function() x142;
+  FunuCyclicBound<A<A<dynamic>>> Function() x143;
+  FunuCyclicBound<A<A<void>>> Function() x144;
+  FunuCyclicBound<A<A<Object?>>> Function() x145;
+  FunuCyclicBound<A<A<FutureOr<dynamic>>>> Function() x146;
+  FunuCyclicBound<A<A<FutureOr<void>>>> Function() x147;
+  FunuCyclicBound<A<A<FutureOr<Object?>>>> Function() x148;
+  FunuCyclicCoBound<dynamic> Function() x149;
+  FunuCyclicCoBound<void> Function() x150;
+  FunuCyclicCoBound<Object?> Function() x151;
+  FunuCyclicCoBound<FutureOr<dynamic>> Function() x152;
+  FunuCyclicCoBound<FutureOr<void>> Function() x153;
+  FunuCyclicCoBound<FutureOr<Object?>> Function() x154;
+  FunuCyclicCoBound<Function(dynamic)> Function() x155;
+  FunuCyclicCoBound<Function(void)> Function() x156;
+  FunuCyclicCoBound<Function(Object?)> Function() x157;
+  FunuCyclicCoBound<Function(FutureOr<dynamic>)> Function() x158;
+  FunuCyclicCoBound<Function(FutureOr<void>)> Function() x159;
+  FunuCyclicCoBound<Function(FutureOr<Object?>)> Function() x160;
+  FunuCyclicCoBound<Function(Function(dynamic))> Function() x161;
+  FunuCyclicCoBound<Function(Function(void))> Function() x162;
+  FunuCyclicCoBound<Function(Function(Object?))> Function() x163;
+  FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))> Function() x164;
+  FunuCyclicCoBound<Function(Function(FutureOr<void>))> Function() x165;
+  FunuCyclicCoBound<Function(Function(FutureOr<Object?>))> Function() x166;
+  CFunu<Funu<dynamic>> Function() x167;
+  CFunu<Funu<void>> Function() x168;
+  CFunu<Funu<Object?>> Function() x169;
+  CFunu<Funu<FutureOr<dynamic>>> Function() x170;
+  CFunu<Funu<FutureOr<void>>> Function() x171;
+  CFunu<Funu<FutureOr<Object?>>> Function() x172;
+  CFunu<Funu<Funu<dynamic>>> Function() x173;
+  CFunu<Funu<Funu<void>>> Function() x174;
+  CFunu<Funu<Funu<Object?>>> Function() x175;
+  CFunu<Funu<Funu<FutureOr<dynamic>>>> Function() x176;
+  CFunu<Funu<Funu<FutureOr<void>>>> Function() x177;
+  CFunu<Funu<Funu<FutureOr<Object?>>>> Function() x178;
+  void Function(void Function(FunuBound<dynamic>)) x179;
+  void Function(void Function(FunuBound<void>)) x180;
+  void Function(void Function(FunuBound<Object?>)) x181;
+  void Function(void Function(FunuBound<FutureOr<dynamic>>)) x182;
+  void Function(void Function(FunuBound<FutureOr<void>>)) x183;
+  void Function(void Function(FunuBound<FutureOr<Object?>>)) x184;
+  void Function(void Function(FunuCyclicBound<dynamic>)) x185;
+  void Function(void Function(FunuCyclicBound<void>)) x186;
+  void Function(void Function(FunuCyclicBound<Object?>)) x187;
+  void Function(void Function(FunuCyclicBound<FutureOr<dynamic>>)) x188;
+  void Function(void Function(FunuCyclicBound<FutureOr<void>>)) x189;
+  void Function(void Function(FunuCyclicBound<FutureOr<Object?>>)) x190;
+  void Function(void Function(FunuCyclicBound<A<dynamic>>)) x191;
+  void Function(void Function(FunuCyclicBound<A<void>>)) x192;
+  void Function(void Function(FunuCyclicBound<A<Object?>>)) x193;
+  void Function(void Function(FunuCyclicBound<A<FutureOr<dynamic>>>)) x194;
+  void Function(void Function(FunuCyclicBound<A<FutureOr<void>>>)) x195;
+  void Function(void Function(FunuCyclicBound<A<FutureOr<Object?>>>)) x196;
+  void Function(void Function(FunuCyclicBound<A<A<dynamic>>>)) x197;
+  void Function(void Function(FunuCyclicBound<A<A<void>>>)) x198;
+  void Function(void Function(FunuCyclicBound<A<A<Object?>>>)) x199;
+  void Function(void Function(FunuCyclicBound<A<A<FutureOr<dynamic>>>>)) x200;
+  void Function(void Function(FunuCyclicBound<A<A<FutureOr<void>>>>)) x201;
+  void Function(void Function(FunuCyclicBound<A<A<FutureOr<Object?>>>>)) x202;
+  void Function(void Function(FunuCyclicCoBound<dynamic>)) x203;
+  void Function(void Function(FunuCyclicCoBound<void>)) x204;
+  void Function(void Function(FunuCyclicCoBound<Object?>)) x205;
+  void Function(void Function(FunuCyclicCoBound<FutureOr<dynamic>>)) x206;
+  void Function(void Function(FunuCyclicCoBound<FutureOr<void>>)) x207;
+  void Function(void Function(FunuCyclicCoBound<FutureOr<Object?>>)) x208;
+  void Function(void Function(FunuCyclicCoBound<Function(dynamic)>)) x209;
+  void Function(void Function(FunuCyclicCoBound<Function(void)>)) x210;
+  void Function(void Function(FunuCyclicCoBound<Function(Object?)>)) x211;
+  void Function(void Function(FunuCyclicCoBound<Function(FutureOr<dynamic>)>))
+      x212;
+  void Function(void Function(FunuCyclicCoBound<Function(FutureOr<void>)>))
+      x213;
+  void Function(void Function(FunuCyclicCoBound<Function(FutureOr<Object?>)>))
+      x214;
+  void Function(void Function(FunuCyclicCoBound<Function(Function(dynamic))>))
+      x215;
+  void Function(void Function(FunuCyclicCoBound<Function(Function(void))>))
+      x216;
+  void Function(void Function(FunuCyclicCoBound<Function(Function(Object?))>))
+      x217;
+  void Function(
+      void Function(
+          FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))>)) x218;
+  void Function(
+          void Function(FunuCyclicCoBound<Function(Function(FutureOr<void>))>))
+      x219;
+  void Function(
+      void Function(
+          FunuCyclicCoBound<Function(Function(FutureOr<Object?>))>)) x220;
+  void Function(void Function(CFunu<Funu<dynamic>>)) x221;
+  void Function(void Function(CFunu<Funu<void>>)) x222;
+  void Function(void Function(CFunu<Funu<Object?>>)) x223;
+  void Function(void Function(CFunu<Funu<FutureOr<dynamic>>>)) x224;
+  void Function(void Function(CFunu<Funu<FutureOr<void>>>)) x225;
+  void Function(void Function(CFunu<Funu<FutureOr<Object?>>>)) x226;
+  void Function(void Function(CFunu<Funu<Funu<dynamic>>>)) x227;
+  void Function(void Function(CFunu<Funu<Funu<void>>>)) x228;
+  void Function(void Function(CFunu<Funu<Funu<Object?>>>)) x229;
+  void Function(void Function(CFunu<Funu<Funu<FutureOr<dynamic>>>>)) x230;
+  void Function(void Function(CFunu<Funu<Funu<FutureOr<void>>>>)) x231;
+  void Function(void Function(CFunu<Funu<Funu<FutureOr<Object?>>>>)) x232;
+  void Function(FunuBound<dynamic>) x233;
+  void Function(FunuBound<void>) x234;
+  void Function(FunuBound<Object?>) x235;
+  void Function(FunuBound<FutureOr<dynamic>>) x236;
+  void Function(FunuBound<FutureOr<void>>) x237;
+  void Function(FunuBound<FutureOr<Object?>>) x238;
+  void Function(FunuCyclicBound<dynamic>) x239;
+  void Function(FunuCyclicBound<void>) x240;
+  void Function(FunuCyclicBound<Object?>) x241;
+  void Function(FunuCyclicBound<FutureOr<dynamic>>) x242;
+  void Function(FunuCyclicBound<FutureOr<void>>) x243;
+  void Function(FunuCyclicBound<FutureOr<Object?>>) x244;
+  void Function(FunuCyclicBound<A<dynamic>>) x245;
+  void Function(FunuCyclicBound<A<void>>) x246;
+  void Function(FunuCyclicBound<A<Object?>>) x247;
+  void Function(FunuCyclicBound<A<FutureOr<dynamic>>>) x248;
+  void Function(FunuCyclicBound<A<FutureOr<void>>>) x249;
+  void Function(FunuCyclicBound<A<FutureOr<Object?>>>) x250;
+  void Function(FunuCyclicBound<A<A<dynamic>>>) x251;
+  void Function(FunuCyclicBound<A<A<void>>>) x252;
+  void Function(FunuCyclicBound<A<A<Object?>>>) x253;
+  void Function(FunuCyclicBound<A<A<FutureOr<dynamic>>>>) x254;
+  void Function(FunuCyclicBound<A<A<FutureOr<void>>>>) x255;
+  void Function(FunuCyclicBound<A<A<FutureOr<Object?>>>>) x256;
+  void Function(FunuCyclicCoBound<dynamic>) x257;
+  void Function(FunuCyclicCoBound<void>) x258;
+  void Function(FunuCyclicCoBound<Object?>) x259;
+  void Function(FunuCyclicCoBound<FutureOr<dynamic>>) x260;
+  void Function(FunuCyclicCoBound<FutureOr<void>>) x261;
+  void Function(FunuCyclicCoBound<FutureOr<Object?>>) x262;
+  void Function(FunuCyclicCoBound<Function(dynamic)>) x263;
+  void Function(FunuCyclicCoBound<Function(void)>) x264;
+  void Function(FunuCyclicCoBound<Function(Object?)>) x265;
+  void Function(FunuCyclicCoBound<Function(FutureOr<dynamic>)>) x266;
+  void Function(FunuCyclicCoBound<Function(FutureOr<void>)>) x267;
+  void Function(FunuCyclicCoBound<Function(FutureOr<Object?>)>) x268;
+  void Function(FunuCyclicCoBound<Function(Function(dynamic))>) x269;
+  void Function(FunuCyclicCoBound<Function(Function(void))>) x270;
+  void Function(FunuCyclicCoBound<Function(Function(Object?))>) x271;
+  void Function(FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))>) x272;
+  void Function(FunuCyclicCoBound<Function(Function(FutureOr<void>))>) x273;
+  void Function(FunuCyclicCoBound<Function(Function(FutureOr<Object?>))>) x274;
+  void Function(CFunu<Funu<dynamic>>) x275;
+  void Function(CFunu<Funu<void>>) x276;
+  void Function(CFunu<Funu<Object?>>) x277;
+  void Function(CFunu<Funu<FutureOr<dynamic>>>) x278;
+  void Function(CFunu<Funu<FutureOr<void>>>) x279;
+  void Function(CFunu<Funu<FutureOr<Object?>>>) x280;
+  void Function(CFunu<Funu<Funu<dynamic>>>) x281;
+  void Function(CFunu<Funu<Funu<void>>>) x282;
+  void Function(CFunu<Funu<Funu<Object?>>>) x283;
+  void Function(CFunu<Funu<Funu<FutureOr<dynamic>>>>) x284;
+  void Function(CFunu<Funu<Funu<FutureOr<void>>>>) x285;
+  void Function(CFunu<Funu<Funu<FutureOr<Object?>>>>) x286;
+  void Function(FunuBound<dynamic>) Function() x287;
+  void Function(FunuBound<void>) Function() x288;
+  void Function(FunuBound<Object?>) Function() x289;
+  void Function(FunuBound<FutureOr<dynamic>>) Function() x290;
+  void Function(FunuBound<FutureOr<void>>) Function() x291;
+  void Function(FunuBound<FutureOr<Object?>>) Function() x292;
+  void Function(FunuCyclicBound<dynamic>) Function() x293;
+  void Function(FunuCyclicBound<void>) Function() x294;
+  void Function(FunuCyclicBound<Object?>) Function() x295;
+  void Function(FunuCyclicBound<FutureOr<dynamic>>) Function() x296;
+  void Function(FunuCyclicBound<FutureOr<void>>) Function() x297;
+  void Function(FunuCyclicBound<FutureOr<Object?>>) Function() x298;
+  void Function(FunuCyclicBound<A<dynamic>>) Function() x299;
+  void Function(FunuCyclicBound<A<void>>) Function() x300;
+  void Function(FunuCyclicBound<A<Object?>>) Function() x301;
+  void Function(FunuCyclicBound<A<FutureOr<dynamic>>>) Function() x302;
+  void Function(FunuCyclicBound<A<FutureOr<void>>>) Function() x303;
+  void Function(FunuCyclicBound<A<FutureOr<Object?>>>) Function() x304;
+  void Function(FunuCyclicBound<A<A<dynamic>>>) Function() x305;
+  void Function(FunuCyclicBound<A<A<void>>>) Function() x306;
+  void Function(FunuCyclicBound<A<A<Object?>>>) Function() x307;
+  void Function(FunuCyclicBound<A<A<FutureOr<dynamic>>>>) Function() x308;
+  void Function(FunuCyclicBound<A<A<FutureOr<void>>>>) Function() x309;
+  void Function(FunuCyclicBound<A<A<FutureOr<Object?>>>>) Function() x310;
+  void Function(FunuCyclicCoBound<dynamic>) Function() x311;
+  void Function(FunuCyclicCoBound<void>) Function() x312;
+  void Function(FunuCyclicCoBound<Object?>) Function() x313;
+  void Function(FunuCyclicCoBound<FutureOr<dynamic>>) Function() x314;
+  void Function(FunuCyclicCoBound<FutureOr<void>>) Function() x315;
+  void Function(FunuCyclicCoBound<FutureOr<Object?>>) Function() x316;
+  void Function(FunuCyclicCoBound<Function(dynamic)>) Function() x317;
+  void Function(FunuCyclicCoBound<Function(void)>) Function() x318;
+  void Function(FunuCyclicCoBound<Function(Object?)>) Function() x319;
+  void Function(FunuCyclicCoBound<Function(FutureOr<dynamic>)>) Function() x320;
+  void Function(FunuCyclicCoBound<Function(FutureOr<void>)>) Function() x321;
+  void Function(FunuCyclicCoBound<Function(FutureOr<Object?>)>) Function() x322;
+  void Function(FunuCyclicCoBound<Function(Function(dynamic))>) Function() x323;
+  void Function(FunuCyclicCoBound<Function(Function(void))>) Function() x324;
+  void Function(FunuCyclicCoBound<Function(Function(Object?))>) Function() x325;
+  void Function(FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))>)
+      Function() x326;
+  void Function(FunuCyclicCoBound<Function(Function(FutureOr<void>))>)
+      Function() x327;
+  void Function(FunuCyclicCoBound<Function(Function(FutureOr<Object?>))>)
+      Function() x328;
+  void Function(CFunu<Funu<dynamic>>) Function() x329;
+  void Function(CFunu<Funu<void>>) Function() x330;
+  void Function(CFunu<Funu<Object?>>) Function() x331;
+  void Function(CFunu<Funu<FutureOr<dynamic>>>) Function() x332;
+  void Function(CFunu<Funu<FutureOr<void>>>) Function() x333;
+  void Function(CFunu<Funu<FutureOr<Object?>>>) Function() x334;
+  void Function(CFunu<Funu<Funu<dynamic>>>) Function() x335;
+  void Function(CFunu<Funu<Funu<void>>>) Function() x336;
+  void Function(CFunu<Funu<Funu<Object?>>>) Function() x337;
+  void Function(CFunu<Funu<Funu<FutureOr<dynamic>>>>) Function() x338;
+  void Function(CFunu<Funu<Funu<FutureOr<void>>>>) Function() x339;
+  void Function(CFunu<Funu<Funu<FutureOr<Object?>>>>) Function() x340;
+  void Function<Y extends FunuBound<dynamic>>() x341;
+  void Function<Y extends FunuBound<void>>() x342;
+  void Function<Y extends FunuBound<Object?>>() x343;
+  void Function<Y extends FunuBound<FutureOr<dynamic>>>() x344;
+  void Function<Y extends FunuBound<FutureOr<void>>>() x345;
+  void Function<Y extends FunuBound<FutureOr<Object?>>>() x346;
+  void Function<Y extends FunuCyclicBound<dynamic>>() x347;
+  void Function<Y extends FunuCyclicBound<void>>() x348;
+  void Function<Y extends FunuCyclicBound<Object?>>() x349;
+  void Function<Y extends FunuCyclicBound<FutureOr<dynamic>>>() x350;
+  void Function<Y extends FunuCyclicBound<FutureOr<void>>>() x351;
+  void Function<Y extends FunuCyclicBound<FutureOr<Object?>>>() x352;
+  void Function<Y extends FunuCyclicBound<A<dynamic>>>() x353;
+  void Function<Y extends FunuCyclicBound<A<void>>>() x354;
+  void Function<Y extends FunuCyclicBound<A<Object?>>>() x355;
+  void Function<Y extends FunuCyclicBound<A<FutureOr<dynamic>>>>() x356;
+  void Function<Y extends FunuCyclicBound<A<FutureOr<void>>>>() x357;
+  void Function<Y extends FunuCyclicBound<A<FutureOr<Object?>>>>() x358;
+  void Function<Y extends FunuCyclicBound<A<A<dynamic>>>>() x359;
+  void Function<Y extends FunuCyclicBound<A<A<void>>>>() x360;
+  void Function<Y extends FunuCyclicBound<A<A<Object?>>>>() x361;
+  void Function<Y extends FunuCyclicBound<A<A<FutureOr<dynamic>>>>>() x362;
+  void Function<Y extends FunuCyclicBound<A<A<FutureOr<void>>>>>() x363;
+  void Function<Y extends FunuCyclicBound<A<A<FutureOr<Object?>>>>>() x364;
+  void Function<Y extends FunuCyclicCoBound<dynamic>>() x365;
+  void Function<Y extends FunuCyclicCoBound<void>>() x366;
+  void Function<Y extends FunuCyclicCoBound<Object?>>() x367;
+  void Function<Y extends FunuCyclicCoBound<FutureOr<dynamic>>>() x368;
+  void Function<Y extends FunuCyclicCoBound<FutureOr<void>>>() x369;
+  void Function<Y extends FunuCyclicCoBound<FutureOr<Object?>>>() x370;
+  void Function<Y extends FunuCyclicCoBound<Function(dynamic)>>() x371;
+  void Function<Y extends FunuCyclicCoBound<Function(void)>>() x372;
+  void Function<Y extends FunuCyclicCoBound<Function(Object?)>>() x373;
+  void Function<Y extends FunuCyclicCoBound<Function(FutureOr<dynamic>)>>()
+      x374;
+  void Function<Y extends FunuCyclicCoBound<Function(FutureOr<void>)>>() x375;
+  void Function<Y extends FunuCyclicCoBound<Function(FutureOr<Object?>)>>()
+      x376;
+  void Function<Y extends FunuCyclicCoBound<Function(Function(dynamic))>>()
+      x377;
+  void Function<Y extends FunuCyclicCoBound<Function(Function(void))>>() x378;
+  void Function<Y extends FunuCyclicCoBound<Function(Function(Object?))>>()
+      x379;
+  void Function<
+          Y extends FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))>>()
+      x380;
+  void Function<
+      Y extends FunuCyclicCoBound<Function(Function(FutureOr<void>))>>() x381;
+  void Function<
+          Y extends FunuCyclicCoBound<Function(Function(FutureOr<Object?>))>>()
+      x382;
+  void Function<Y extends CFunu<Funu<dynamic>>>() x383;
+  void Function<Y extends CFunu<Funu<void>>>() x384;
+  void Function<Y extends CFunu<Funu<Object?>>>() x385;
+  void Function<Y extends CFunu<Funu<FutureOr<dynamic>>>>() x386;
+  void Function<Y extends CFunu<Funu<FutureOr<void>>>>() x387;
+  void Function<Y extends CFunu<Funu<FutureOr<Object?>>>>() x388;
+  void Function<Y extends CFunu<Funu<Funu<dynamic>>>>() x389;
+  void Function<Y extends CFunu<Funu<Funu<void>>>>() x390;
+  void Function<Y extends CFunu<Funu<Funu<Object?>>>>() x391;
+  void Function<Y extends CFunu<Funu<Funu<FutureOr<dynamic>>>>>() x392;
+  void Function<Y extends CFunu<Funu<Funu<FutureOr<void>>>>>() x393;
+  void Function<Y extends CFunu<Funu<Funu<FutureOr<Object?>>>>>() x394;
+  void Function<Y extends A<FunuBound<dynamic>>>() x395;
+  void Function<Y extends A<FunuBound<void>>>() x396;
+  void Function<Y extends A<FunuBound<Object?>>>() x397;
+  void Function<Y extends A<FunuBound<FutureOr<dynamic>>>>() x398;
+  void Function<Y extends A<FunuBound<FutureOr<void>>>>() x399;
+  void Function<Y extends A<FunuBound<FutureOr<Object?>>>>() x400;
+  void Function<Y extends A<FunuCyclicBound<dynamic>>>() x401;
+  void Function<Y extends A<FunuCyclicBound<void>>>() x402;
+  void Function<Y extends A<FunuCyclicBound<Object?>>>() x403;
+  void Function<Y extends A<FunuCyclicBound<FutureOr<dynamic>>>>() x404;
+  void Function<Y extends A<FunuCyclicBound<FutureOr<void>>>>() x405;
+  void Function<Y extends A<FunuCyclicBound<FutureOr<Object?>>>>() x406;
+  void Function<Y extends A<FunuCyclicBound<A<dynamic>>>>() x407;
+  void Function<Y extends A<FunuCyclicBound<A<void>>>>() x408;
+  void Function<Y extends A<FunuCyclicBound<A<Object?>>>>() x409;
+  void Function<Y extends A<FunuCyclicBound<A<FutureOr<dynamic>>>>>() x410;
+  void Function<Y extends A<FunuCyclicBound<A<FutureOr<void>>>>>() x411;
+  void Function<Y extends A<FunuCyclicBound<A<FutureOr<Object?>>>>>() x412;
+  void Function<Y extends A<FunuCyclicBound<A<A<dynamic>>>>>() x413;
+  void Function<Y extends A<FunuCyclicBound<A<A<void>>>>>() x414;
+  void Function<Y extends A<FunuCyclicBound<A<A<Object?>>>>>() x415;
+  void Function<Y extends A<FunuCyclicBound<A<A<FutureOr<dynamic>>>>>>() x416;
+  void Function<Y extends A<FunuCyclicBound<A<A<FutureOr<void>>>>>>() x417;
+  void Function<Y extends A<FunuCyclicBound<A<A<FutureOr<Object?>>>>>>() x418;
+  void Function<Y extends A<FunuCyclicCoBound<dynamic>>>() x419;
+  void Function<Y extends A<FunuCyclicCoBound<void>>>() x420;
+  void Function<Y extends A<FunuCyclicCoBound<Object?>>>() x421;
+  void Function<Y extends A<FunuCyclicCoBound<FutureOr<dynamic>>>>() x422;
+  void Function<Y extends A<FunuCyclicCoBound<FutureOr<void>>>>() x423;
+  void Function<Y extends A<FunuCyclicCoBound<FutureOr<Object?>>>>() x424;
+  void Function<Y extends A<FunuCyclicCoBound<Function(dynamic)>>>() x425;
+  void Function<Y extends A<FunuCyclicCoBound<Function(void)>>>() x426;
+  void Function<Y extends A<FunuCyclicCoBound<Function(Object?)>>>() x427;
+  void Function<Y extends A<FunuCyclicCoBound<Function(FutureOr<dynamic>)>>>()
+      x428;
+  void Function<Y extends A<FunuCyclicCoBound<Function(FutureOr<void>)>>>()
+      x429;
+  void Function<Y extends A<FunuCyclicCoBound<Function(FutureOr<Object?>)>>>()
+      x430;
+  void Function<Y extends A<FunuCyclicCoBound<Function(Function(dynamic))>>>()
+      x431;
+  void Function<Y extends A<FunuCyclicCoBound<Function(Function(void))>>>()
+      x432;
+  void Function<Y extends A<FunuCyclicCoBound<Function(Function(Object?))>>>()
+      x433;
+  void Function<
+      Y extends A<
+          FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))>>>() x434;
+  void Function<
+          Y extends A<FunuCyclicCoBound<Function(Function(FutureOr<void>))>>>()
+      x435;
+  void Function<
+      Y extends A<
+          FunuCyclicCoBound<Function(Function(FutureOr<Object?>))>>>() x436;
+  void Function<Y extends A<CFunu<Funu<dynamic>>>>() x437;
+  void Function<Y extends A<CFunu<Funu<void>>>>() x438;
+  void Function<Y extends A<CFunu<Funu<Object?>>>>() x439;
+  void Function<Y extends A<CFunu<Funu<FutureOr<dynamic>>>>>() x440;
+  void Function<Y extends A<CFunu<Funu<FutureOr<void>>>>>() x441;
+  void Function<Y extends A<CFunu<Funu<FutureOr<Object?>>>>>() x442;
+  void Function<Y extends A<CFunu<Funu<Funu<dynamic>>>>>() x443;
+  void Function<Y extends A<CFunu<Funu<Funu<void>>>>>() x444;
+  void Function<Y extends A<CFunu<Funu<Funu<Object?>>>>>() x445;
+  void Function<Y extends A<CFunu<Funu<Funu<FutureOr<dynamic>>>>>>() x446;
+  void Function<Y extends A<CFunu<Funu<Funu<FutureOr<void>>>>>>() x447;
+  void Function<Y extends A<CFunu<Funu<Funu<FutureOr<Object?>>>>>>() x448;
+  Finv<FunuBound<dynamic>> x449;
+  Finv<FunuBound<void>> x450;
+  Finv<FunuBound<Object?>> x451;
+  Finv<FunuBound<FutureOr<dynamic>>> x452;
+  Finv<FunuBound<FutureOr<void>>> x453;
+  Finv<FunuBound<FutureOr<Object?>>> x454;
+  Finv<FunuCyclicBound<dynamic>> x455;
+  Finv<FunuCyclicBound<void>> x456;
+  Finv<FunuCyclicBound<Object?>> x457;
+  Finv<FunuCyclicBound<FutureOr<dynamic>>> x458;
+  Finv<FunuCyclicBound<FutureOr<void>>> x459;
+  Finv<FunuCyclicBound<FutureOr<Object?>>> x460;
+  Finv<FunuCyclicBound<A<dynamic>>> x461;
+  Finv<FunuCyclicBound<A<void>>> x462;
+  Finv<FunuCyclicBound<A<Object?>>> x463;
+  Finv<FunuCyclicBound<A<FutureOr<dynamic>>>> x464;
+  Finv<FunuCyclicBound<A<FutureOr<void>>>> x465;
+  Finv<FunuCyclicBound<A<FutureOr<Object?>>>> x466;
+  Finv<FunuCyclicBound<A<A<dynamic>>>> x467;
+  Finv<FunuCyclicBound<A<A<void>>>> x468;
+  Finv<FunuCyclicBound<A<A<Object?>>>> x469;
+  Finv<FunuCyclicBound<A<A<FutureOr<dynamic>>>>> x470;
+  Finv<FunuCyclicBound<A<A<FutureOr<void>>>>> x471;
+  Finv<FunuCyclicBound<A<A<FutureOr<Object?>>>>> x472;
+  Finv<FunuCyclicCoBound<dynamic>> x473;
+  Finv<FunuCyclicCoBound<void>> x474;
+  Finv<FunuCyclicCoBound<Object?>> x475;
+  Finv<FunuCyclicCoBound<FutureOr<dynamic>>> x476;
+  Finv<FunuCyclicCoBound<FutureOr<void>>> x477;
+  Finv<FunuCyclicCoBound<FutureOr<Object?>>> x478;
+  Finv<FunuCyclicCoBound<Function(dynamic)>> x479;
+  Finv<FunuCyclicCoBound<Function(void)>> x480;
+  Finv<FunuCyclicCoBound<Function(Object?)>> x481;
+  Finv<FunuCyclicCoBound<Function(FutureOr<dynamic>)>> x482;
+  Finv<FunuCyclicCoBound<Function(FutureOr<void>)>> x483;
+  Finv<FunuCyclicCoBound<Function(FutureOr<Object?>)>> x484;
+  Finv<FunuCyclicCoBound<Function(Function(dynamic))>> x485;
+  Finv<FunuCyclicCoBound<Function(Function(void))>> x486;
+  Finv<FunuCyclicCoBound<Function(Function(Object?))>> x487;
+  Finv<FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x488;
+  Finv<FunuCyclicCoBound<Function(Function(FutureOr<void>))>> x489;
+  Finv<FunuCyclicCoBound<Function(Function(FutureOr<Object?>))>> x490;
+  Finv<CFunu<Funu<dynamic>>> x491;
+  Finv<CFunu<Funu<void>>> x492;
+  Finv<CFunu<Funu<Object?>>> x493;
+  Finv<CFunu<Funu<FutureOr<dynamic>>>> x494;
+  Finv<CFunu<Funu<FutureOr<void>>>> x495;
+  Finv<CFunu<Funu<FutureOr<Object?>>>> x496;
+  Finv<CFunu<Funu<Funu<dynamic>>>> x497;
+  Finv<CFunu<Funu<Funu<void>>>> x498;
+  Finv<CFunu<Funu<Funu<Object?>>>> x499;
+  Finv<CFunu<Funu<Funu<FutureOr<dynamic>>>>> x500;
+  Finv<CFunu<Funu<Funu<FutureOr<void>>>>> x501;
+  Finv<CFunu<Funu<Funu<FutureOr<Object?>>>>> x502;
+  Funu<FunuBound<dynamic>> x503;
+  Funu<FunuBound<void>> x504;
+  Funu<FunuBound<Object?>> x505;
+  Funu<FunuBound<FutureOr<dynamic>>> x506;
+  Funu<FunuBound<FutureOr<void>>> x507;
+  Funu<FunuBound<FutureOr<Object?>>> x508;
+  Funu<FunuCyclicBound<dynamic>> x509;
+  Funu<FunuCyclicBound<void>> x510;
+  Funu<FunuCyclicBound<Object?>> x511;
+  Funu<FunuCyclicBound<FutureOr<dynamic>>> x512;
+  Funu<FunuCyclicBound<FutureOr<void>>> x513;
+  Funu<FunuCyclicBound<FutureOr<Object?>>> x514;
+  Funu<FunuCyclicBound<A<dynamic>>> x515;
+  Funu<FunuCyclicBound<A<void>>> x516;
+  Funu<FunuCyclicBound<A<Object?>>> x517;
+  Funu<FunuCyclicBound<A<FutureOr<dynamic>>>> x518;
+  Funu<FunuCyclicBound<A<FutureOr<void>>>> x519;
+  Funu<FunuCyclicBound<A<FutureOr<Object?>>>> x520;
+  Funu<FunuCyclicBound<A<A<dynamic>>>> x521;
+  Funu<FunuCyclicBound<A<A<void>>>> x522;
+  Funu<FunuCyclicBound<A<A<Object?>>>> x523;
+  Funu<FunuCyclicBound<A<A<FutureOr<dynamic>>>>> x524;
+  Funu<FunuCyclicBound<A<A<FutureOr<void>>>>> x525;
+  Funu<FunuCyclicBound<A<A<FutureOr<Object?>>>>> x526;
+  Funu<FunuCyclicCoBound<dynamic>> x527;
+  Funu<FunuCyclicCoBound<void>> x528;
+  Funu<FunuCyclicCoBound<Object?>> x529;
+  Funu<FunuCyclicCoBound<FutureOr<dynamic>>> x530;
+  Funu<FunuCyclicCoBound<FutureOr<void>>> x531;
+  Funu<FunuCyclicCoBound<FutureOr<Object?>>> x532;
+  Funu<FunuCyclicCoBound<Function(dynamic)>> x533;
+  Funu<FunuCyclicCoBound<Function(void)>> x534;
+  Funu<FunuCyclicCoBound<Function(Object?)>> x535;
+  Funu<FunuCyclicCoBound<Function(FutureOr<dynamic>)>> x536;
+  Funu<FunuCyclicCoBound<Function(FutureOr<void>)>> x537;
+  Funu<FunuCyclicCoBound<Function(FutureOr<Object?>)>> x538;
+  Funu<FunuCyclicCoBound<Function(Function(dynamic))>> x539;
+  Funu<FunuCyclicCoBound<Function(Function(void))>> x540;
+  Funu<FunuCyclicCoBound<Function(Function(Object?))>> x541;
+  Funu<FunuCyclicCoBound<Function(Function(FutureOr<dynamic>))>> x542;
+  Funu<FunuCyclicCoBound<Function(Function(FutureOr<void>))>> x543;
+  Funu<FunuCyclicCoBound<Function(Function(FutureOr<Object?>))>> x544;
+  Funu<CFunu<Funu<dynamic>>> x545;
+  Funu<CFunu<Funu<void>>> x546;
+  Funu<CFunu<Funu<Object?>>> x547;
+  Funu<CFunu<Funu<FutureOr<dynamic>>>> x548;
+  Funu<CFunu<Funu<FutureOr<void>>>> x549;
+  Funu<CFunu<Funu<FutureOr<Object?>>>> x550;
+  Funu<CFunu<Funu<Funu<dynamic>>>> x551;
+  Funu<CFunu<Funu<Funu<void>>>> x552;
+  Funu<CFunu<Funu<Funu<Object?>>>> x553;
+  Funu<CFunu<Funu<Funu<FutureOr<dynamic>>>>> x554;
+  Funu<CFunu<Funu<Funu<FutureOr<void>>>>> x555;
+  Funu<CFunu<Funu<Funu<FutureOr<Object?>>>>> x556;
+}
+
+void main() {
+  testCovariantSuperbound<Never>();
+  testContravariantSuperbound<Never>();
+  testInvariantSuperbound<Never>();
+  testVarianceLessSuperbound<Never>();
+}
diff --git a/tests/language/identifier/built_in_illegal_test.dart b/tests/language/identifier/built_in_illegal_test.dart
index 86d9e5c..983a854 100644
--- a/tests/language/identifier/built_in_illegal_test.dart
+++ b/tests/language/identifier/built_in_illegal_test.dart
@@ -131,7 +131,6 @@
 // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
 // [cfe] Expected an identifier, but got 'part'.
 // [error line 123, column 12, length 0]
-// [analyzer] COMPILE_TIME_ERROR.PART_OF_NON_PART
 // [cfe] Expected ';' after this.
 //         ^
 // [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
diff --git a/tests/language/inference/inconsistent_inheritance_test.dart b/tests/language/inference/inconsistent_inheritance_test.dart
index beff18f..c6b782c 100644
--- a/tests/language/inference/inconsistent_inheritance_test.dart
+++ b/tests/language/inference/inconsistent_inheritance_test.dart
@@ -28,10 +28,7 @@
   void g(x, y) {
     // ^
     // [analyzer] COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE
-    //   ^
-    // [cfe] Can't infer a type for 'x' as the overridden members don't have a combined signature.
-    //      ^
-    // [cfe] Can't infer a type for 'y' as the overridden members don't have a combined signature.
+    // [cfe] Can't infer types for 'g' as the overridden members don't have a combined signature.
   }
 }
 
diff --git a/tests/language/instance/call_wrong_argument_count_test.dart b/tests/language/instance/call_wrong_argument_count_test.dart
index 8f0c710..6256051 100644
--- a/tests/language/instance/call_wrong_argument_count_test.dart
+++ b/tests/language/instance/call_wrong_argument_count_test.dart
@@ -14,7 +14,8 @@
   var niederhorn = Niederhorn();
   niederhorn.goodCall(1, 2, 3);
   niederhorn.goodCall(1, 2, 3, 4);
-  //                 ^^^^^^^^^^^^
+  //                           ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //                 ^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 3 allowed, but 4 found.
 }
diff --git a/tests/language/least_upper_bound/least_upper_bound_greatest_closure_1_test.dart b/tests/language/least_upper_bound/least_upper_bound_greatest_closure_1_test.dart
new file mode 100644
index 0000000..41f83dd
--- /dev/null
+++ b/tests/language/least_upper_bound/least_upper_bound_greatest_closure_1_test.dart
@@ -0,0 +1,826 @@
+// 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 'dart:async';
+import '../static_type_helper.dart';
+
+class C1<X> {}
+
+class C2 extends C1<C2> {}
+
+var condition = true;
+
+void main() {
+  void f0<X1 extends int>(X1 x1, String t2) {
+    // UP(X1 extends int /*B1*/, String /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as int);
+    z1.expectStaticType<Exactly<int>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<Object>>();
+
+    // UP(String /*T2*/, X1 extends int /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as int) : x1;
+    z4.expectStaticType<Exactly<int>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<Object>>();
+  }
+
+  void g0<X1>(X1 x1, String t2) {
+    if (x1 is int) {
+      // UP(X1 & int /*B1*/, String /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<Object>>();
+
+      // UP(String /*T2*/, X1 & int /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<Object>>();
+    }
+  }
+
+  void f1<X1 extends C1<X1>>(X1 x1, C1<C2> t2) {
+    // UP(X1 extends C1<X1> /*B1*/, C1<C2> /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as C1<X1>);
+    z1.expectStaticType<Exactly<C1<X1>>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<C1<Object?>>>();
+
+    // UP(C1<C2> /*T2*/, X1 extends C1<X1> /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as C1<X1>) : x1;
+    z4.expectStaticType<Exactly<C1<X1>>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<C1<Object?>>>();
+  }
+
+  void g1<X1>(X1 x1, C1<C2> t2) {
+    if (x1 is C1<X1>) {
+      // UP(X1 & C1<X1> /*B1*/, C1<C2> /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<C1<Object?>>>();
+
+      // UP(C1<C2> /*T2*/, X1 & C1<X1> /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<C1<Object?>>>();
+    }
+  }
+
+  void f2<X1 extends C1<X1>>(X1 x1, C1<C2>? t2) {
+    // UP(X1 extends C1<X1> /*B1*/, C1<C2>? /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as C1<X1>);
+    z1.expectStaticType<Exactly<C1<X1>>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<C1<Object?>?>>();
+
+    // UP(C1<C2>? /*T2*/, X1 extends C1<X1> /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as C1<X1>) : x1;
+    z4.expectStaticType<Exactly<C1<X1>>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<C1<Object?>?>>();
+  }
+
+  void g2<X1>(X1 x1, C1<C2>? t2) {
+    if (x1 is C1<X1>) {
+      // UP(X1 & C1<X1> /*B1*/, C1<C2>? /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<C1<Object?>?>>();
+
+      // UP(C1<C2>? /*T2*/, X1 & C1<X1> /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<C1<Object?>?>>();
+    }
+  }
+
+  void f3<X1 extends C1<X1>?>(X1 x1, C1<C2> t2) {
+    // UP(X1 extends C1<X1>? /*B1*/, C1<C2> /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as C1<X1>?);
+    z1.expectStaticType<Exactly<C1<Object?>?>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<C1<Object?>?>>();
+
+    // UP(C1<C2> /*T2*/, X1 extends C1<X1>? /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as C1<X1>?) : x1;
+    z4.expectStaticType<Exactly<C1<Object?>?>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<C1<Object?>?>>();
+  }
+
+  void g3<X1>(X1 x1, C1<C2> t2) {
+    if (x1 is C1<X1>?) {
+      // UP(X1 & C1<X1>? /*B1*/, C1<C2> /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<C1<Object?>?>>();
+
+      // UP(C1<C2> /*T2*/, X1 & C1<X1>? /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<C1<Object?>?>>();
+    }
+  }
+
+  void f4<X1 extends C1<X1>?>(X1 x1, C1<C2>? t2) {
+    // UP(X1 extends C1<X1>? /*B1*/, C1<C2>? /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as C1<X1>?);
+    z1.expectStaticType<Exactly<C1<Object?>?>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<C1<Object?>?>>();
+
+    // UP(C1<C2>? /*T2*/, X1 extends C1<X1>? /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as C1<X1>?) : x1;
+    z4.expectStaticType<Exactly<C1<Object?>?>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<C1<Object?>?>>();
+  }
+
+  void g4<X1>(X1 x1, C1<C2>? t2) {
+    if (x1 is C1<X1>?) {
+      // UP(X1 & C1<X1>? /*B1*/, C1<C2>? /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<C1<Object?>?>>();
+
+      // UP(C1<C2>? /*T2*/, X1 & C1<X1>? /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<C1<Object?>?>>();
+    }
+  }
+
+  void f5<X1 extends Iterable<Iterable<X1>?>>(
+      X1 x1, Iterable<List<Object?>?> t2) {
+    // UP(X1 extends Iterable<Iterable<X1>?> /*B1*/,
+    //     Iterable<List<Object?>?> /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as Iterable<Iterable<X1>?>);
+    z1.expectStaticType<Exactly<Iterable<Iterable<X1>?>>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<Iterable<Iterable<Object?>?>>>();
+
+    // UP(Iterable<List<Object?>?> /*T2*/,
+    //     X1 extends Iterable<Iterable<X1>?> /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as Iterable<Iterable<X1>?>) : x1;
+    z4.expectStaticType<Exactly<Iterable<Iterable<X1>?>>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<Iterable<Iterable<Object?>?>>>();
+  }
+
+  void g5<X1>(X1 x1, Iterable<List<Object?>?> t2) {
+    if (x1 is Iterable<Iterable<X1>?>) {
+      // UP(X1 & Iterable<Iterable<X1>?> /*B1*/,
+      //     Iterable<List<Object?>?> /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<Iterable<Iterable<Object?>?>>>();
+
+      // UP(Iterable<List<Object?>?> /*T2*/,
+      //     X1 & Iterable<Iterable<X1>?> /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<Iterable<Iterable<Object?>?>>>();
+    }
+  }
+
+  void g6<X1>(X1 x1, FutureOr<Object> t2) {
+    if (x1 is FutureOr<X1>) {
+      // UP(X1 & FutureOr<X1> /*B1*/, FutureOr<Object> /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<FutureOr<Object>?>>();
+
+      // UP(FutureOr<Object> /*T2*/, X1 & FutureOr<X1> /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<FutureOr<Object>?>>();
+    }
+  }
+
+  void g7<X1>(X1 x1, FutureOr<Object> t2) {
+    if (x1 is FutureOr<X1?>) {
+      // UP(X1 & FutureOr<X1?> /*B1*/, FutureOr<Object> /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<FutureOr<Object>?>>();
+
+      // UP(FutureOr<Object> /*T2*/, X1 & FutureOr<X1?> /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<FutureOr<Object>?>>();
+    }
+  }
+
+  void f8<X1 extends void Function(X1)>(X1 x1, void Function(Null) t2) {
+    // UP(X1 extends void Function(X1) /*B1*/, void Function(Null) /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as void Function(X1));
+    z1.expectStaticType<Exactly<void Function(X1)>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<void Function(Never)>>();
+
+    // UP(void Function(Null) /*T2*/, X1 extends void Function(X1) /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as void Function(X1)) : x1;
+    z4.expectStaticType<Exactly<void Function(X1)>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<void Function(Never)>>();
+  }
+
+  void g8<X1>(X1 x1, void Function(Null) t2) {
+    if (x1 is void Function(X1)) {
+      // UP(X1 & void Function(X1) /*B1*/, void Function(Null) /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<void Function(Never)>>();
+
+      // UP(void Function(Null) /*T2*/, X1 & void Function(X1) /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<void Function(Never)>>();
+    }
+  }
+
+  void f9<X1 extends void Function([X1])>(X1 x1, void Function([Null]) t2) {
+    // UP(X1 extends void Function([X1]) /*B1*/, void Function([Null]) /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as void Function([X1]));
+    z1.expectStaticType<Exactly<void Function([X1])>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<void Function([Never])>>();
+
+    // UP(void Function([Null]) /*T2*/, X1 extends void Function([X1]) /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as void Function([X1])) : x1;
+    z4.expectStaticType<Exactly<void Function([X1])>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<void Function([Never])>>();
+  }
+
+  void g9<X1>(X1 x1, void Function([Null]) t2) {
+    if (x1 is void Function([X1])) {
+      // UP(X1 & void Function([X1]) /*B1*/, void Function([Null]) /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<void Function([Never])>>();
+
+      // UP(void Function([Null]) /*T2*/, X1 & void Function([X1]) /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<void Function([Never])>>();
+    }
+  }
+
+  void f10<X1 extends void Function({X1 p})>(
+      X1 x1, void Function({Null p}) t2) {
+    // UP(X1 extends void Function({X1 p}) /*B1*/,
+    //     void Function({Null p}) /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as void Function({X1 p}));
+    z1.expectStaticType<Exactly<void Function({X1 p})>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<void Function({Never p})>>();
+
+    // UP(void Function({Null p}) /*T2*/,
+    //     X1 extends void Function({X1 p}) /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as void Function({X1 p})) : x1;
+    z4.expectStaticType<Exactly<void Function({X1 p})>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<void Function({Never p})>>();
+  }
+
+  void g10<X1>(X1 x1, void Function({Null p}) t2) {
+    if (x1 is void Function({X1 p})) {
+      // UP(X1 & void Function({X1 p}) /*B1*/, void Function({Null p}) /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<void Function({Never p})>>();
+
+      // UP(void Function({Null p}) /*T2*/, X1 & void Function({X1 p}) /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<void Function({Never p})>>();
+    }
+  }
+
+  void f11<X1 extends void Function({required X1 p})>(
+      X1 x1, void Function({X1 p}) t2) {
+    // UP(X1 extends void Function({required X1 p}) /*B1*/,
+    //     void Function({X1 p}) /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as void Function({required X1 p}));
+    z1.expectStaticType<Exactly<void Function({required X1 p})>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<void Function({required Never p})>>();
+
+    // UP(void Function({X1 p}) /*T2*/,
+    //     X1 extends void Function({required X1 p}) /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as void Function({required X1 p})) : x1;
+    z4.expectStaticType<Exactly<void Function({required X1 p})>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<void Function({required Never p})>>();
+  }
+
+  void g11<X1>(X1 x1, void Function({X1 p}) t2) {
+    if (x1 is void Function({required X1 p})) {
+      // UP(X1 & void Function({required X1 p}) /*B1*/,
+      //     void Function({X1 p}) /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<void Function({required Never p})>>();
+
+      // UP(void Function({X1 p}) /*T2*/,
+      //     X1 & void Function({required X1 p}) /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<void Function({required Never p})>>();
+    }
+  }
+
+  void f12<X1 extends void Function(FutureOr<X1>)>(
+      X1 x1, void Function(FutureOr<Null>) t2) {
+    // UP(X1 extends void Function(FutureOr<X1>) /*B1*/,
+    //     void Function(FutureOr<Null>) /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as void Function(FutureOr<X1>));
+    z1.expectStaticType<Exactly<void Function(FutureOr<X1>)>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<void Function(FutureOr<Never>)>>();
+
+    // UP(void Function(FutureOr<Null>) /*T2*/,
+    //     X1 extends void Function(FutureOr<X1>) /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as void Function(FutureOr<X1>)) : x1;
+    z4.expectStaticType<Exactly<void Function(FutureOr<X1>)>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<void Function(FutureOr<Never>)>>();
+  }
+
+  void g12<X1>(X1 x1, void Function(FutureOr<Null>) t2) {
+    if (x1 is void Function(FutureOr<X1>)) {
+      // UP(X1 & void Function(FutureOr<X1>) /*B1*/,
+      //     void Function(FutureOr<Null>) /*T2*/) =
+      //   T2 if X1 <: T2
+      //   otherwise X1 if T2 <: X1
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z1 = condition ? x1 : (null as Object?);
+      z1.expectStaticType<Exactly<Object?>>();
+
+      var z2 = condition ? x1 : throw 0;
+      z2.expectStaticType<Exactly<X1>>();
+
+      var z3 = condition ? x1 : t2;
+      z3.expectStaticType<Exactly<void Function(FutureOr<Never>)>>();
+
+      // UP(void Function(FutureOr<Null>) /*T2*/,
+      //     X1 & void Function(FutureOr<X1>) /*B1*/) =
+      //   X1 if T2 <: X1
+      //   otherwise T2 if X1 <: T2
+      //   otherwise UP(T2, B1a)
+      //     where B1a is the greatest closure of B1 with respect to X1
+
+      var z4 = condition ? null as Object? : x1;
+      z4.expectStaticType<Exactly<Object?>>();
+
+      var z5 = condition ? throw 0 : x1;
+      z5.expectStaticType<Exactly<X1>>();
+
+      var z6 = condition ? t2 : x1;
+      z6.expectStaticType<Exactly<void Function(FutureOr<Never>)>>();
+    }
+  }
+}
diff --git a/tests/language/least_upper_bound/least_upper_bound_greatest_closure_2_test.dart b/tests/language/least_upper_bound/least_upper_bound_greatest_closure_2_test.dart
new file mode 100644
index 0000000..d0b888a
--- /dev/null
+++ b/tests/language/least_upper_bound/least_upper_bound_greatest_closure_2_test.dart
@@ -0,0 +1,78 @@
+// 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 'dart:async';
+import '../static_type_helper.dart';
+
+class C1<X> {}
+
+class C2 extends C1<C2> {}
+
+var condition = true;
+
+void main() {
+  void f6<X1 extends FutureOr<X1>>(X1 x1, FutureOr<Object> t2) {
+    // UP(X1 extends FutureOr<X1> /*B1*/, FutureOr<Object> /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as FutureOr<X1>);
+    z1.expectStaticType<Exactly<FutureOr<X1>>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<FutureOr<Object?>>>();
+
+    // UP(FutureOr<Object> /*T2*/, X1 extends FutureOr<X1> /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as FutureOr<X1>) : x1;
+    z4.expectStaticType<Exactly<FutureOr<X1>>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<FutureOr<Object?>>>();
+  }
+
+  void f7<X1 extends FutureOr<X1?>>(X1 x1, FutureOr<Object> t2) {
+    // UP(X1 extends FutureOr<X1?> /*B1*/, FutureOr<Object> /*T2*/) =
+    //   T2 if X1 <: T2
+    //   otherwise X1 if T2 <: X1
+    //   otherwise UP(B1a, T2)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z1 = condition ? x1 : ((throw 0) as FutureOr<X1?>);
+    z1.expectStaticType<Exactly<FutureOr<X1?>>>();
+
+    var z2 = condition ? x1 : throw 0;
+    z2.expectStaticType<Exactly<X1>>();
+
+    var z3 = condition ? x1 : t2;
+    z3.expectStaticType<Exactly<FutureOr<Object?>>>();
+
+    // UP(FutureOr<Object> /*T2*/, X1 extends FutureOr<X1?> /*B1*/) =
+    //   X1 if T2 <: X1
+    //   otherwise T2 if X1 <: T2
+    //   otherwise UP(T2, B1a)
+    //     where B1a is the greatest closure of B1 with respect to X1
+
+    var z4 = condition ? ((throw 0) as FutureOr<X1?>) : x1;
+    z4.expectStaticType<Exactly<FutureOr<X1?>>>();
+
+    var z5 = condition ? throw 0 : x1;
+    z5.expectStaticType<Exactly<X1>>();
+
+    var z6 = condition ? t2 : x1;
+    z6.expectStaticType<Exactly<FutureOr<Object?>>>();
+  }
+}
diff --git a/tests/language/mixin/forwarding_stub_call_test.dart b/tests/language/mixin/forwarding_stub_call_test.dart
new file mode 100644
index 0000000..3cef355
--- /dev/null
+++ b/tests/language/mixin/forwarding_stub_call_test.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// Test for calling a method for which a forwarding super stub has been
+// inserted.
+
+import 'package:expect/expect.dart';
+
+class Super<T> {
+  void method(T t) {}
+}
+
+class Mixin {
+  void method(int t) {}
+}
+
+// A forwarding super stub is inserted:
+//
+//     void method(/*generic-covariant-impl*/ int t) => super.method(t);
+//
+class Class = Super<int> with Mixin;
+
+class Subclass extends Class {
+  void test() {
+    // Test that we can call the method.
+    super.method(0);
+  }
+}
+
+main() {
+  Super<Object> s = new Subclass()..test();
+  // Test that the covariance check is performed.
+  Expect.throws(() => s.method(''));
+}
diff --git a/tests/language/mixin/forwarding_stub_set_test.dart b/tests/language/mixin/forwarding_stub_set_test.dart
new file mode 100644
index 0000000..e0c2b9b
--- /dev/null
+++ b/tests/language/mixin/forwarding_stub_set_test.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// Test for assigning to a field for which a forwarding super stub has been
+// inserted.
+
+import 'package:expect/expect.dart';
+
+class Super<T> {
+  T? field;
+}
+
+class Mixin {
+  int? field;
+}
+
+// A forwarding super stub is inserted:
+//
+//     void set field(/*generic-covariant-impl*/ int t) => super.field = t;
+//
+class Class = Super<int> with Mixin;
+
+class Subclass extends Class {
+  void test() {
+    // Test that we can perform the assignment.
+    super.field = 0;
+  }
+}
+
+main() {
+  Super<Object> s = new Subclass()..test();
+  // Test that the covariance check is performed.
+  Expect.throws(() => s.field = '');
+}
diff --git a/tests/language/mixin/forwarding_stub_tearoff_test.dart b/tests/language/mixin/forwarding_stub_tearoff_test.dart
new file mode 100644
index 0000000..470c52e
--- /dev/null
+++ b/tests/language/mixin/forwarding_stub_tearoff_test.dart
@@ -0,0 +1,36 @@
+// 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.
+
+// Test for tearing off a method for which a forwarding super stub has been
+// inserted.
+
+import 'package:expect/expect.dart';
+
+class Super<T> {
+  void method(T t) {}
+}
+
+class Mixin {
+  void method(int t) {}
+}
+
+// A forwarding super stub is inserted:
+//
+//     void method(/*generic-covariant-impl*/ int t) => super.method(t);
+//
+class Class = Super<int> with Mixin;
+
+class Subclass extends Class {
+  void test() {
+    // Test that we can tear off the method.
+    void Function(int) f = super.method;
+    f(0);
+  }
+}
+
+main() {
+  Super<Object> s = new Subclass()..test();
+  // Test that the covariance check is performed.
+  Expect.throws(() => s.method(''));
+}
diff --git a/tests/language/mixin/illegal_constructor_test.dart b/tests/language/mixin/illegal_constructor_test.dart
index 864889f..a4a8723 100644
--- a/tests/language/mixin/illegal_constructor_test.dart
+++ b/tests/language/mixin/illegal_constructor_test.dart
@@ -97,16 +97,18 @@
   new D6();
 
   new C0(1,2,3);
-  //    ^^^^^^^
+  //     ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //    ^^^^^^^
   // [cfe] Too many positional arguments: 0 allowed, but 3 found.
   new C0.named();
   //     ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.NEW_WITH_UNDEFINED_CONSTRUCTOR
   // [cfe] Method not found: 'C0.named'.
   new D0(1,2,3);
-  //    ^^^^^^^
+  //     ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //    ^^^^^^^
   // [cfe] Too many positional arguments: 0 allowed, but 3 found.
   new D0.named();
   //     ^^^^^
diff --git a/tests/language/mixin/interface_check_test.dart b/tests/language/mixin/interface_check_test.dart
index db0aaf3..9884d1b 100644
--- a/tests/language/mixin/interface_check_test.dart
+++ b/tests/language/mixin/interface_check_test.dart
@@ -19,7 +19,7 @@
 
 class C extends A //
 //    ^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
+// [analyzer] COMPILE_TIME_ERROR.INVALID_IMPLEMENTATION_OVERRIDE
 // [cfe] The implementation of 'thing' in the non-abstract class 'C' does not conform to its interface.
     with
         B
diff --git a/tests/language/mixin/invalid_override_in_mixin_test.dart b/tests/language/mixin/invalid_override_in_mixin_test.dart
index bd79f66..de7b18c 100644
--- a/tests/language/mixin/invalid_override_in_mixin_test.dart
+++ b/tests/language/mixin/invalid_override_in_mixin_test.dart
@@ -14,8 +14,6 @@
 class C extends Object with A {
 //    ^
 // [cfe] Applying the mixin 'A' to 'Object' introduces an erroneous override of 'noSuchMethod'.
-//    ^
-// [cfe] Class 'Object with A' inherits multiple members named 'noSuchMethod' with incompatible signatures.
 //                          ^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
   test() {
diff --git a/tests/language/mixin/method_override_test.dart b/tests/language/mixin/method_override_test.dart
index 166599e..e50464d 100644
--- a/tests/language/mixin/method_override_test.dart
+++ b/tests/language/mixin/method_override_test.dart
@@ -21,34 +21,26 @@
 
 // Wrong return type.
 abstract class C1 = CII with CIS;
-//             ^^
-// [cfe] Class 'C1' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C1' introduces an erroneous override of 'id'.
 //                           ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C2 extends CII with CIS {}
-//             ^^
-// [cfe] Applying the mixin 'CIS' to 'CII' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'CII with CIS' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'CIS' to 'CII' introduces an erroneous override of 'id'.
 //                                 ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
 
 // Wrong argument type.
 abstract class C3 = CII with CSI;
-//             ^^
-// [cfe] Class 'C3' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C3' introduces an erroneous override of 'id'.
 //                           ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C4 extends CII with CSI {}
-//             ^^
-// [cfe] Applying the mixin 'CSI' to 'CII' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'CII with CSI' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'CSI' to 'CII' introduces an erroneous override of 'id'.
 //                                 ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
@@ -56,17 +48,13 @@
 abstract class C5 = CII with CTT<int>;
 abstract class C6 extends CII with CTT<int> {}
 abstract class C7  = CII with CTT<String>;
-//             ^^
-// [cfe] Class 'C7' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C7' introduces an erroneous override of 'id'.
 //                            ^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C8 extends CII with CTT<String> {}
-//             ^^
-// [cfe] Applying the mixin 'CTT' to 'CII' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'CII with CTT<String>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'CTT' to 'CII' introduces an erroneous override of 'id'.
 //                                 ^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
@@ -92,34 +80,26 @@
 abstract class N2 extends NIIx with NIIxy {}
 // It's NOT OK to rename named parameters.
 abstract class N3 = NIIx with NIIy;
-//             ^^
-// [cfe] Class 'N3' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N3' introduces an erroneous override of 'id'.
 //                            ^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N4 extends NIIx with NIIy {}
-//             ^^
-// [cfe] Applying the mixin 'NIIy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NIIy' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NIIy' to 'NIIx' introduces an erroneous override of 'id'.
 //                                  ^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
 
 // It's NOT OK to drop named parameters.
 abstract class N5 = NIIx with NII;
-//             ^^
-// [cfe] Class 'N5' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N5' introduces an erroneous override of 'id'.
 //                            ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N6 extends NIIx with NII {}
-//             ^^
-// [cfe] Applying the mixin 'NII' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NII' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NII' to 'NIIx' introduces an erroneous override of 'id'.
 //                                  ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
@@ -139,45 +119,33 @@
 abstract class N7 = NIIx with NBABxy<int, int>;
 abstract class N8 extends NIIx with NBABxy<int, int> {}
 abstract class N9 = NIIx with NBABxy<String, int>;
-//             ^^
-// [cfe] Class 'N9' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N9' introduces an erroneous override of 'id'.
 //                            ^^^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N10 extends NIIx with NBABxy<String, int> {}
-//             ^^^
-// [cfe] Applying the mixin 'NBABxy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NBABxy<String, int>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NBABxy' to 'NIIx' introduces an erroneous override of 'id'.
 //                                   ^^^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N11 = NIIx with NTTy<int>;
-//             ^^^
-// [cfe] Class 'N11' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N11' introduces an erroneous override of 'id'.
 //                             ^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N12 extends NIIx with NTTy<int> {}
-//             ^^^
-// [cfe] Applying the mixin 'NTTy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NTTy<int>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NTTy' to 'NIIx' introduces an erroneous override of 'id'.
 //                                   ^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N13 = NIIx with NTTx<int>;
-//             ^^^
-// [cfe] Class 'N13' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N13' introduces an erroneous override of 'id'.
 //                             ^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N14 extends NIIx with NTTx<int> {}
-//             ^^^
-// [cfe] Applying the mixin 'NTTx' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NTTx<int>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NTTx' to 'NIIx' introduces an erroneous override of 'id'.
 //                                   ^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
@@ -232,17 +200,13 @@
 abstract class O7 = OII with OBAB<int, int>;
 abstract class O8 extends OII with OBAB<int, int> {}
 abstract class O9 = OII with OBAB<String, int>;
-//             ^^
-// [cfe] Class 'O9' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'O9' introduces an erroneous override of 'id'.
 //                           ^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class O10 extends OII with OBAB<String, int> {}
-//             ^^^
-// [cfe] Applying the mixin 'OBAB' to 'OII' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'OII with OBAB<String, int>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'OBAB' to 'OII' introduces an erroneous override of 'id'.
 //                                  ^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class O11 = OII with OTTy<int>;
@@ -280,22 +244,16 @@
 }
 class G1 = GTTnum with MTTnum;
 class G2 = GTTnum with MTTint;
-//    ^^
-// [cfe] Class 'G2' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G2' introduces an erroneous override of 'id'.
 //                     ^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 class G3 = GTTnum with MTT;
-//    ^^
-// [cfe] Class 'G3' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G3' introduces an erroneous override of 'id'.
 //                     ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 class G4 = GTTnum with MTTnumR;
-//    ^^
-// [cfe] Class 'G4' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G4' introduces an erroneous override of 'id'.
 //                     ^^^^^^^
diff --git a/tests/language/mixin/super_with_initializer_test.dart b/tests/language/mixin/super_with_initializer_test.dart
new file mode 100644
index 0000000..a59164b
--- /dev/null
+++ b/tests/language/mixin/super_with_initializer_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Regression test for mixin overrides (dartbug.com/44636).
+///
+/// Prior to the fix, B's initializer was accidentally being applied on the
+/// overriden definition in C, and as a result, the program would stack
+/// overflow.
+import 'package:expect/expect.dart';
+
+class A = B with C;
+
+mixin M {}
+
+abstract class B with M {
+  Object _test = "a";
+}
+
+mixin C on B, M {
+  @override
+  Object get _test => super._test;
+
+  @override
+  set _test(Object value) {
+    super._test = value;
+  }
+}
+
+main() => Expect.equals("a", A()._test);
diff --git a/tests/language/nnbd/flow_analysis/boolean_parameter_test.dart b/tests/language/nnbd/flow_analysis/boolean_parameter_test.dart
new file mode 100644
index 0000000..e0f753c
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/boolean_parameter_test.dart
@@ -0,0 +1,141 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks whether a function parameter can be used to perform type
+// promotion, for various ways of declaring it.
+//
+// We test all combinations of:
+// - top level function, method, local named function, or function expression
+// - type `bool`, `Object`, `Object?`, or `dynamic`
+
+topLevelFunction_bool(int? x, bool b) {
+  b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+topLevelFunction_Object(int? x, Object b) {
+  b = x != null;
+  // We don't currently recognize that `b as bool` has the same value as `b`,
+  // so we don't promote.  TODO(paulberry): should we?
+  if (b as bool) x.expectStaticType<Exactly<int?>>();
+}
+
+topLevelFunction_ObjectQ(int? x, Object? b) {
+  b = x != null;
+  // We don't currently recognize that `b as bool` has the same value as `b`,
+  // so we don't promote.  TODO(paulberry): should we?
+  if (b as bool) x.expectStaticType<Exactly<int?>>();
+}
+
+topLevelFunction_dynamic(int? x, dynamic b) {
+  b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+class C {
+  method_bool(int? x, bool b) {
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+
+  method_Object(int? x, Object b) {
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+
+  method_ObjectQ(int? x, Object? b) {
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+
+  method_dynamic(int? x, dynamic b) {
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+}
+
+localTest(int? x) {
+  localNamedFunction_bool(bool b) {
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+
+  localNamedFunction_bool(false);
+
+  localNamedFunction_Object(Object b) {
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+
+  localNamedFunction_Object(Object());
+
+  localNamedFunction_ObjectQ(Object? b) {
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+
+  localNamedFunction_ObjectQ(null);
+
+  localNamedFunction_dynamic(dynamic b) {
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+
+  localNamedFunction_dynamic('foo');
+
+  (bool b) {
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }(false);
+
+  (Object b) {
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }(Object());
+
+  (Object? b) {
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }(null);
+
+  (dynamic b) {
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }('foo');
+}
+
+main() {
+  topLevelFunction_bool(null, false);
+  topLevelFunction_bool(0, false);
+  topLevelFunction_Object(null, Object());
+  topLevelFunction_Object(0, Object());
+  topLevelFunction_ObjectQ(null, null);
+  topLevelFunction_ObjectQ(0, null);
+  topLevelFunction_dynamic(null, 'foo');
+  topLevelFunction_dynamic(0, 'foo');
+  C().method_bool(null, false);
+  C().method_bool(0, false);
+  C().method_Object(null, Object());
+  C().method_Object(0, Object());
+  C().method_ObjectQ(null, null);
+  C().method_ObjectQ(0, null);
+  C().method_dynamic(null, 'foo');
+  C().method_dynamic(0, 'foo');
+  localTest(null);
+  localTest(0);
+}
diff --git a/tests/language/nnbd/flow_analysis/expr_property_not_promoted_test.dart b/tests/language/nnbd/flow_analysis/expr_property_not_promoted_test.dart
new file mode 100644
index 0000000..bfbfc95
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/expr_property_not_promoted_test.dart
@@ -0,0 +1,38 @@
+// 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 '../../static_type_helper.dart';
+
+// This test verifies that neither an `== null` nor an `is` test can promote the
+// type of a property access on an arbitrary expression.  (Such accesses cannot
+// be promoted soundly).
+
+class _C {
+  final int? _f;
+
+  _C(this._f);
+}
+
+void equality(_C Function() c) {
+  if (c()._f == null) {
+    c()._f.expectStaticType<Exactly<int?>>();
+  } else {
+    c()._f.expectStaticType<Exactly<int?>>();
+  }
+}
+
+void is_(_C Function() c) {
+  if (c()._f is int) {
+    c()._f.expectStaticType<Exactly<int?>>();
+  } else {
+    c()._f.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  equality(() => _C(1));
+  is_(() => _C(1));
+  equality(() => _C(null));
+  is_(() => _C(null));
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_compound_assignment_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_compound_assignment_test.dart
new file mode 100644
index 0000000..b76b066
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_compound_assignment_test.dart
@@ -0,0 +1,251 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks that local boolean variables cannot be used to perform type
+// promotion in the presence of compound assignments.
+//
+// We test the following kinds of compound assignments:
+// - Ordinary (e.g. `+=`)
+// - Prefix increment/decrement (e.g. `++<variable>`)
+// - Postfix increment/decrement (e.g. `<variable>++`)
+// - Null-aware (`??=`)
+//
+// We test both the side effect of the assignment and the evaluated value of the
+// assignment expression.
+
+testSideEffect(int? x) {
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b /= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b ~/= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b %= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b += x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b -= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b <<= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b >>= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b &= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b ^= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b |= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b ??= x != null;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ++b;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    --b;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b++;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b--;
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+testValue(int? x) {
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b /= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b ~/= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b %= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b += x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b -= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b <<= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b >>= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b &= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b ^= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b |= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b ??= x != null) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (++b) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (--b) {
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b++) {
+      // Note: arguably we could promote here (since the value of `b++` is the
+      // same as the value that `b` had before the "increment") but given that
+      // incrementing booleans doesn't work at runtime anyhow, it doesn't seem
+      // worth it.
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    if (b--) {
+      // Note: arguably we could promote here (since the value of `b--` is the
+      // same as the value that `b` had before the "decrement") but given that
+      // decrementing booleans doesn't work at runtime anyhow, it doesn't seem
+      // worth it.
+      x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+bool _alwaysFalse() => false;
+
+main() {
+  // Because of the use of dynamic in these tests, they're not expected to
+  // succeed at runtime; we just want to check the compile-time behavior.  So we
+  // reference the test functions but don't call them.
+  if (_alwaysFalse()) testSideEffect(0);
+  if (_alwaysFalse()) testValue(0);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_defeated_by_assignment_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_defeated_by_assignment_test.dart
new file mode 100644
index 0000000..649155a
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_defeated_by_assignment_test.dart
@@ -0,0 +1,642 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks various scenarios in which the use of a local variable for
+// type promotion is defeated, either by an assignment to the local variable
+// itself or an assignment to the variable that would be promoted.
+
+direct_toConditionVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  b = true;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+direct_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  x = y;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+lateInitializer_toConditionalVar(int? x) {
+  bool b = x != null;
+  late final y = b ? x.expectStaticType<Exactly<int?>>() : 3;
+  b = true;
+}
+
+lateInitializer_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  late final y = b ? x.expectStaticType<Exactly<int?>>() : 3;
+  x = y;
+}
+
+afterConditionalThen_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  b2 ? b = true : null;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterConditionalThen_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  b2 ? x = y : null;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterConditionalElse_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  b2 ? null : b = true;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterConditionalElse_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  b2 ? null : x = y;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfStatementThen_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  if (b2) b = true;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfStatementThen_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  if (b2) x = y;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfStatementElse_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  if (b2) {
+  } else {
+    b = true;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfStatementElse_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  if (b2) {
+  } else {
+    x = y;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfListThen_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  [if (b2) b = true];
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfListThen_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  [if (b2) x = y];
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfListElse_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  [if (b2) null else b = true];
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfListElse_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  [if (b2) null else x = y];
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfSetThen_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) b = true});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfSetThen_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) x = y});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfSetElse_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) null else b = true});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfSetElse_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) null else x = y});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfMapKeyThen_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) b = true: null});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfMapKeyThen_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) x = y: null});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfMapKeyElse_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) null: null else b = true: null});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfMapKeyElse_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) null: null else x = y: null});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfMapValueThen_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) null: b = true});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfMapValueThen_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) null: x = y});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfMapValueElse_toConditionVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) null: null else null: b = true});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterIfMapValueElse_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  ({if (b2) null: null else null: x = y});
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+doLater_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  do {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    b = true;
+  } while (i-- > 0);
+}
+
+doLater_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  do {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    x = y;
+  } while (i-- > 0);
+}
+
+forLater_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  for (int j = 0; j < i; j++) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    b = true;
+  }
+}
+
+forLater_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  for (int j = 0; j < i; j++) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    x = y;
+  }
+}
+
+forEachLater_toConditionalVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  for (var v in [null]) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    b = true;
+  }
+}
+
+forEachLater_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  for (var v in [null]) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    x = y;
+  }
+}
+
+whileLater_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  while (i-- > 0) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    b = true;
+  }
+}
+
+whileLater_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  while (i-- > 0) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    x = y;
+  }
+}
+
+switchLaterLabeled_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  switch (i) {
+    L:
+    case 0:
+      if (b) x.expectStaticType<Exactly<int?>>();
+      break;
+    case 1:
+      b = true;
+      continue L;
+  }
+}
+
+switchLaterLabeled_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  switch (i) {
+    L:
+    case 0:
+      if (b) x.expectStaticType<Exactly<int?>>();
+      break;
+    case 1:
+      x = y;
+      continue L;
+  }
+}
+
+afterDo_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  do {
+    b = true;
+  } while (i-- > 0);
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterDo_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  do {
+    x = y;
+  } while (i-- > 0);
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterFor_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  for (int j = 0; j < i; j++) {
+    b = true;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterFor_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  for (int j = 0; j < i; j++) {
+    x = y;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterForEach_toConditionalVar(int? x, Iterable i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  for (var v in i) {
+    b = true;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterForEach_toPromotedVar(int? x, Iterable i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  for (var v in i) {
+    x = y;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterWhile_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  while (i-- > 0) {
+    b = true;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterWhile_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  while (i-- > 0) {
+    x = y;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterSwitch_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  switch (i) {
+    case 0:
+      b = true;
+      break;
+    case 1:
+      break;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterSwitch_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  switch (i) {
+    case 0:
+      x = y;
+      break;
+    case 1:
+      break;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+tryCatchCatch_toConditionalVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    b = true;
+  } catch (_) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+tryCatchCatch_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    x = y;
+  } catch (_) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+afterTryCatchTry_toConditionalVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    b = true;
+  } catch (_) {}
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterTryCatchTry_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    x = y;
+  } catch (_) {}
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterTryCatchCatch_toConditionalVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {} catch (_) {
+    b = true;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterTryCatchCatch_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {} catch (_) {
+    x = y;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+tryFinallyFinally_toConditionalVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    b = true;
+  } finally {
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+tryFinallyFinally_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    x = y;
+  } finally {
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+afterTryFinallyTry_toConditionalVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    b = true;
+  } finally {}
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterTryFinallyTry_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    x = y;
+  } finally {}
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterTryFinallyFinally_toConditionalVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {} finally {
+    b = true;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+afterTryFinallyFinally_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {} finally {
+    x = y;
+  }
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+main() {
+  direct_toConditionVar(0);
+  direct_toConditionVar(null);
+  direct_toPromotedVar(0, null);
+  direct_toPromotedVar(null, null);
+  lateInitializer_toConditionalVar(0);
+  lateInitializer_toConditionalVar(null);
+  lateInitializer_toPromotedVar(0, null);
+  lateInitializer_toPromotedVar(null, null);
+  afterConditionalThen_toConditionVar(0, true);
+  afterConditionalThen_toConditionVar(null, true);
+  afterConditionalThen_toPromotedVar(0, true, null);
+  afterConditionalThen_toPromotedVar(null, true, null);
+  afterConditionalElse_toConditionVar(0, false);
+  afterConditionalElse_toConditionVar(null, false);
+  afterConditionalElse_toPromotedVar(0, false, null);
+  afterConditionalElse_toPromotedVar(null, false, null);
+  afterIfStatementThen_toConditionVar(0, true);
+  afterIfStatementThen_toConditionVar(null, true);
+  afterIfStatementThen_toPromotedVar(0, true, null);
+  afterIfStatementThen_toPromotedVar(null, true, null);
+  afterIfStatementElse_toConditionVar(0, false);
+  afterIfStatementElse_toConditionVar(null, false);
+  afterIfStatementElse_toPromotedVar(0, false, null);
+  afterIfStatementElse_toPromotedVar(null, false, null);
+  afterIfListThen_toConditionVar(0, true);
+  afterIfListThen_toConditionVar(null, true);
+  afterIfListThen_toPromotedVar(0, true, null);
+  afterIfListThen_toPromotedVar(null, true, null);
+  afterIfListElse_toConditionVar(0, false);
+  afterIfListElse_toConditionVar(null, false);
+  afterIfListElse_toPromotedVar(0, false, null);
+  afterIfListElse_toPromotedVar(null, false, null);
+  afterIfSetThen_toConditionVar(0, true);
+  afterIfSetThen_toConditionVar(null, true);
+  afterIfSetThen_toPromotedVar(0, true, null);
+  afterIfSetThen_toPromotedVar(null, true, null);
+  afterIfSetElse_toConditionVar(0, false);
+  afterIfSetElse_toConditionVar(null, false);
+  afterIfSetElse_toPromotedVar(0, false, null);
+  afterIfSetElse_toPromotedVar(null, false, null);
+  afterIfMapKeyThen_toConditionVar(0, true);
+  afterIfMapKeyThen_toConditionVar(null, true);
+  afterIfMapKeyThen_toPromotedVar(0, true, null);
+  afterIfMapKeyThen_toPromotedVar(null, true, null);
+  afterIfMapKeyElse_toConditionVar(0, false);
+  afterIfMapKeyElse_toConditionVar(null, false);
+  afterIfMapKeyElse_toPromotedVar(0, false, null);
+  afterIfMapKeyElse_toPromotedVar(null, false, null);
+  afterIfMapValueThen_toConditionVar(0, true);
+  afterIfMapValueThen_toConditionVar(null, true);
+  afterIfMapValueThen_toPromotedVar(0, true, null);
+  afterIfMapValueThen_toPromotedVar(null, true, null);
+  afterIfMapValueElse_toConditionVar(0, false);
+  afterIfMapValueElse_toConditionVar(null, false);
+  afterIfMapValueElse_toPromotedVar(0, false, null);
+  afterIfMapValueElse_toPromotedVar(null, false, null);
+  doLater_toConditionalVar(0, 1);
+  doLater_toConditionalVar(null, 1);
+  doLater_toPromotedVar(0, 1, null);
+  doLater_toPromotedVar(null, 1, null);
+  forLater_toConditionalVar(0, 1);
+  forLater_toConditionalVar(null, 1);
+  forLater_toPromotedVar(0, 1, null);
+  forLater_toPromotedVar(null, 1, null);
+  forEachLater_toConditionalVar(0);
+  forEachLater_toConditionalVar(null);
+  forEachLater_toPromotedVar(0, null);
+  forEachLater_toPromotedVar(null, null);
+  whileLater_toConditionalVar(0, 1);
+  whileLater_toConditionalVar(null, 1);
+  whileLater_toPromotedVar(0, 1, null);
+  whileLater_toPromotedVar(null, 1, null);
+  switchLaterLabeled_toConditionalVar(0, 1);
+  switchLaterLabeled_toConditionalVar(null, 1);
+  switchLaterLabeled_toPromotedVar(0, 1, null);
+  switchLaterLabeled_toPromotedVar(null, 1, null);
+  afterDo_toConditionalVar(0, 1);
+  afterDo_toConditionalVar(null, 1);
+  afterDo_toPromotedVar(0, 1, null);
+  afterDo_toPromotedVar(null, 1, null);
+  afterFor_toConditionalVar(0, 1);
+  afterFor_toConditionalVar(null, 1);
+  afterFor_toPromotedVar(0, 1, null);
+  afterFor_toPromotedVar(null, 1, null);
+  afterForEach_toConditionalVar(0, [null]);
+  afterForEach_toConditionalVar(null, [null]);
+  afterForEach_toPromotedVar(0, [null], null);
+  afterForEach_toPromotedVar(null, [null], null);
+  afterWhile_toConditionalVar(0, 1);
+  afterWhile_toConditionalVar(null, 1);
+  afterWhile_toPromotedVar(0, 1, null);
+  afterWhile_toPromotedVar(null, 1, null);
+  afterSwitch_toConditionalVar(0, 0);
+  afterSwitch_toConditionalVar(null, 0);
+  afterSwitch_toPromotedVar(0, 0, null);
+  afterSwitch_toPromotedVar(null, 0, null);
+  tryCatchCatch_toConditionalVar(0);
+  tryCatchCatch_toConditionalVar(null);
+  tryCatchCatch_toPromotedVar(0, null);
+  tryCatchCatch_toPromotedVar(null, null);
+  afterTryCatchTry_toConditionalVar(0);
+  afterTryCatchTry_toConditionalVar(null);
+  afterTryCatchTry_toPromotedVar(0, null);
+  afterTryCatchTry_toPromotedVar(null, null);
+  afterTryCatchCatch_toConditionalVar(0);
+  afterTryCatchCatch_toConditionalVar(null);
+  afterTryCatchCatch_toPromotedVar(0, null);
+  afterTryCatchCatch_toPromotedVar(null, null);
+  tryFinallyFinally_toConditionalVar(0);
+  tryFinallyFinally_toConditionalVar(null);
+  tryFinallyFinally_toPromotedVar(0, null);
+  tryFinallyFinally_toPromotedVar(null, null);
+  afterTryFinallyTry_toConditionalVar(0);
+  afterTryFinallyTry_toConditionalVar(null);
+  afterTryFinallyTry_toPromotedVar(0, null);
+  afterTryFinallyTry_toPromotedVar(null, null);
+  afterTryFinallyFinally_toConditionalVar(0);
+  afterTryFinallyFinally_toConditionalVar(null);
+  afterTryFinallyFinally_toPromotedVar(0, null);
+  afterTryFinallyFinally_toPromotedVar(null, null);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_defeated_by_capture_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_defeated_by_capture_test.dart
new file mode 100644
index 0000000..b46d8c9
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_defeated_by_capture_test.dart
@@ -0,0 +1,79 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks various scenarios in which the use of a local variable for
+// type promotion is defeated by write capture of either the local variable
+// itself or the variable that would be promoted.
+
+capture_conditionVar_prior_to_assignment(int? x) {
+  bool b;
+  (bool b2) => b = b2;
+  b = x != null;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+capture_conditionVar_prior_to_assignment_from_other_condition(int? x) {
+  bool b1 = x != null;
+  bool b3;
+  (bool b2) => b3 = b2;
+  b3 = b1;
+  if (b3) x.expectStaticType<Exactly<int?>>();
+}
+
+capture_promotedVar_prior_to_assignment(int? x) {
+  int? y;
+  (int? z) => y = z;
+  y = x;
+  bool b = y != null;
+  if (b) y.expectStaticType<Exactly<int?>>();
+}
+
+capture_conditionVar_after_assignment(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  (bool b2) => b = b2;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+capture_conditionVar_after_assignment_from_other_condition(int? x) {
+  bool b1 = x != null;
+  bool b3 = b1;
+  if (b3) x.expectStaticType<Exactly<int>>();
+  (bool b2) => b3 = b2;
+  if (b3) x.expectStaticType<Exactly<int?>>();
+}
+
+capture_conditionVar_after_assignment_then_copy_to_other_condition(int? x) {
+  bool b1 = x != null;
+  bool b3;
+  (bool b2) => b1 = b2;
+  b3 = b1;
+  if (b3) x.expectStaticType<Exactly<int?>>();
+}
+
+capture_promotedVar_after_assignment(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  (int? y) => x = y;
+  if (b) x.expectStaticType<Exactly<int?>>();
+}
+
+main() {
+  capture_conditionVar_prior_to_assignment(null);
+  capture_conditionVar_prior_to_assignment(0);
+  capture_conditionVar_prior_to_assignment_from_other_condition(null);
+  capture_conditionVar_prior_to_assignment_from_other_condition(0);
+  capture_promotedVar_prior_to_assignment(null);
+  capture_promotedVar_prior_to_assignment(0);
+  capture_conditionVar_after_assignment(null);
+  capture_conditionVar_after_assignment(0);
+  capture_conditionVar_after_assignment_from_other_condition(null);
+  capture_conditionVar_after_assignment_from_other_condition(0);
+  capture_conditionVar_after_assignment_then_copy_to_other_condition(null);
+  capture_conditionVar_after_assignment_then_copy_to_other_condition(0);
+  capture_promotedVar_after_assignment(null);
+  capture_promotedVar_after_assignment(0);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_does_not_detect_aliases_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_does_not_detect_aliases_test.dart
new file mode 100644
index 0000000..8449b67
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_does_not_detect_aliases_test.dart
@@ -0,0 +1,106 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks that type promotion via local variables does not promote
+// based on knowledge that two potentially promoted variables are "aliases" of
+// each other (both are known to contain the same value).
+//
+// Note, however, that if one condition variable is assigned to another, the
+// promotions *do* carry over; this is a side effect of "promote via local
+// booleans" mechanism and doesn't rely on detecting aliasing.
+//
+// We test both the situation where the variables have the same value due to
+// initialization as well as assignment.  We test both final and non-final
+// variables.
+
+promotedVar(int? x) {
+  {
+    int? y = x;
+    bool b = x != null;
+    if (b) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    final int? y = x;
+    bool b = x != null;
+    if (b) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    int? y;
+    y = x;
+    bool b = x != null;
+    if (b) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    final int? y;
+    y = x;
+    bool b = x != null;
+    if (b) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+}
+
+conditionalVar(int? x) {
+  {
+    bool b1 = x != null;
+    bool b2 = b1;
+    if (b1) {
+      x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) {
+      x.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x != null;
+    final bool b2 = b1;
+    if (b1) {
+      x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) {
+      x.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x != null;
+    bool b2;
+    b2 = b1;
+    if (b1) {
+      x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) {
+      x.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x != null;
+    final bool b2;
+    b2 = b1;
+    if (b1) {
+      x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) {
+      x.expectStaticType<Exactly<int>>();
+    }
+  }
+}
+
+main() {
+  promotedVar(0);
+  promotedVar(null);
+  conditionalVar(0);
+  conditionalVar(null);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_expression_types_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_expression_types_test.dart
new file mode 100644
index 0000000..5f37e8e
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_expression_types_test.dart
@@ -0,0 +1,774 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks whether a local boolean variable can be used to perform type
+// promotion, for various kinds of boolean expressions that we expect to cause
+// promotions, and various contexts in which those boolean variables could be
+// used.
+//
+// For the boolean variable, we test the forms:
+// - `<variable> is <Type>`
+// - `<variable> is! <Type>`
+// - `!<expr>`
+// - `<variable> == null`
+// - `<variable> != null`
+// - `null == <variable>`
+// - `null != <variable>`
+// - `<expr> && <expr>`
+// - `<expr> || <expr>`
+// - `<variable> is <Type> ? true : false`
+// - `<variable> = <expr>`
+// For the use site, we test the forms:
+// - `(<variable>)`
+// - `!<variable>`
+// - `<variable> && <expr>`
+// - `<expr> && <variable>`
+// - `<variable> || <expr>`
+// - `<expr> || <variable>`
+// - `<variable> ? <expr> : <expr>`
+// - `if (<variable>) ...`
+// - `while (<variable>) ...`
+// - `do ... while (<variable>)`
+// - `for (...; <variable>; ...) ...`
+
+bool _alwaysTrue(Object? x) => true;
+
+bool _alwaysFalse(Object? x) => false;
+
+is_(Object x) {
+  bool b = x is int;
+  if ((b)) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (b && _alwaysTrue(x.expectStaticType<Exactly<int>>())) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<Object>>()) && b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b || _alwaysFalse(x.expectStaticType<Exactly<Object>>())) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<Object>>()) || b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<Object>>();
+  do {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  } while (b);
+  x.expectStaticType<Exactly<Object>>();
+  for (x.expectStaticType<Exactly<Object>>();
+      b;
+      x.expectStaticType<Exactly<int>>()) {
+    x.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+isNot(Object x) {
+  bool b = x is! int;
+  if ((b)) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b && _alwaysTrue(x.expectStaticType<Exactly<Object>>())) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<Object>>()) && b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b || _alwaysFalse(x.expectStaticType<Exactly<int>>())) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<Object>>()) || b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<Object>>();
+  if (_alwaysFalse(null)) {
+    // We test this at compile time only because we don't want to have an
+    // infinite loop
+    do {
+      x.expectStaticType<Exactly<Object>>();
+    } while (b);
+    x.expectStaticType<Exactly<int>>();
+  }
+  x.expectStaticType<Exactly<Object>>();
+  for (x.expectStaticType<Exactly<Object>>();
+      b;
+      x.expectStaticType<Exactly<Object>>()) {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+not(Object x) {
+  bool b = !(x is int);
+  if ((b)) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b && _alwaysTrue(x.expectStaticType<Exactly<Object>>())) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<Object>>()) && b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b || _alwaysFalse(x.expectStaticType<Exactly<int>>())) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<Object>>()) || b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<Object>>();
+  if (_alwaysFalse(null)) {
+    // We test this at compile time only because we don't want to have an
+    // infinite loop
+    do {
+      x.expectStaticType<Exactly<Object>>();
+    } while (b);
+    x.expectStaticType<Exactly<int>>();
+  }
+  x.expectStaticType<Exactly<Object>>();
+  for (x.expectStaticType<Exactly<Object>>();
+      b;
+      x.expectStaticType<Exactly<Object>>()) {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+eqNull(int? x) {
+  bool b = (x == null);
+  if ((b)) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (b && _alwaysTrue(x.expectStaticType<Exactly<int?>>())) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<int?>>()) && b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (b || _alwaysFalse(x.expectStaticType<Exactly<int>>())) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<int?>>()) || b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<int?>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<int?>>();
+  if (_alwaysFalse(null)) {
+    // We test this at compile time only because we don't want to have an
+    // infinite loop
+    do {
+      x.expectStaticType<Exactly<int?>>();
+    } while (b);
+    x.expectStaticType<Exactly<int>>();
+  }
+  x.expectStaticType<Exactly<int?>>();
+  for (x.expectStaticType<Exactly<int?>>();
+      b;
+      x.expectStaticType<Exactly<int?>>()) {
+    x.expectStaticType<Exactly<int?>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+notEqNull(int? x) {
+  bool b = x != null;
+  if ((b)) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (b && _alwaysTrue(x.expectStaticType<Exactly<int>>())) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<int?>>()) && b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (b || _alwaysFalse(x.expectStaticType<Exactly<int?>>())) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<int?>>()) || b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<int?>>();
+  do {
+    x.expectStaticType<Exactly<int?>>();
+    if (_alwaysTrue(null)) break;
+  } while (b);
+  x.expectStaticType<Exactly<int?>>();
+  for (x.expectStaticType<Exactly<int?>>();
+      b;
+      x.expectStaticType<Exactly<int>>()) {
+    x.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+nullEq(int? x) {
+  bool b = (null == x);
+  if ((b)) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (b && _alwaysTrue(x.expectStaticType<Exactly<int?>>())) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<int?>>()) && b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (b || _alwaysFalse(x.expectStaticType<Exactly<int>>())) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<int?>>()) || b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<int?>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<int?>>();
+  if (_alwaysFalse(null)) {
+    // We test this at compile time only because we don't want to have an
+    // infinite loop
+    do {
+      x.expectStaticType<Exactly<int?>>();
+    } while (b);
+    x.expectStaticType<Exactly<int>>();
+  }
+  x.expectStaticType<Exactly<int?>>();
+  for (x.expectStaticType<Exactly<int?>>();
+      b;
+      x.expectStaticType<Exactly<int?>>()) {
+    x.expectStaticType<Exactly<int?>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+nullNotEq(int? x) {
+  bool b = null != x;
+  if ((b)) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (b && _alwaysTrue(x.expectStaticType<Exactly<int>>())) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<int?>>()) && b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (b || _alwaysFalse(x.expectStaticType<Exactly<int?>>())) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<int?>>()) || b) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<int?>>();
+  do {
+    x.expectStaticType<Exactly<int?>>();
+    if (_alwaysTrue(null)) break;
+  } while (b);
+  x.expectStaticType<Exactly<int?>>();
+  for (x.expectStaticType<Exactly<int?>>();
+      b;
+      x.expectStaticType<Exactly<int>>()) {
+    x.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+and(Object x, Object y) {
+  bool b = x is int && y is int;
+  if ((b)) {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+  if (b &&
+      _alwaysTrue([
+        x.expectStaticType<Exactly<int>>(),
+        y.expectStaticType<Exactly<int>>()
+      ])) {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysTrue([
+        x.expectStaticType<Exactly<Object>>(),
+        y.expectStaticType<Exactly<Object>>()
+      ]) &&
+      b) {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  if (b ||
+      _alwaysFalse([
+        x.expectStaticType<Exactly<Object>>(),
+        y.expectStaticType<Exactly<Object>>()
+      ])) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysFalse([
+        x.expectStaticType<Exactly<Object>>(),
+        y.expectStaticType<Exactly<Object>>()
+      ]) ||
+      b) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<Object>>();
+  y.expectStaticType<Exactly<Object>>();
+  do {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  } while (b);
+  x.expectStaticType<Exactly<Object>>();
+  y.expectStaticType<Exactly<Object>>();
+  for ([
+    x.expectStaticType<Exactly<Object>>(),
+    y.expectStaticType<Exactly<Object>>()
+  ];
+      b;
+      x.expectStaticType<Exactly<int>>(), y.expectStaticType<Exactly<int>>()) {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+or(Object x, Object y) {
+  bool b = x is! int || y is! int;
+  if ((b)) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  if (b &&
+      _alwaysTrue([
+        x.expectStaticType<Exactly<Object>>(),
+        y.expectStaticType<Exactly<Object>>()
+      ])) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysTrue([
+        x.expectStaticType<Exactly<Object>>(),
+        y.expectStaticType<Exactly<Object>>()
+      ]) &&
+      b) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  }
+  if (b ||
+      _alwaysFalse([
+        x.expectStaticType<Exactly<int>>(),
+        y.expectStaticType<Exactly<int>>()
+      ])) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+  if (_alwaysFalse([
+        x.expectStaticType<Exactly<Object>>(),
+        y.expectStaticType<Exactly<Object>>()
+      ]) ||
+      b) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<Object>>();
+  y.expectStaticType<Exactly<Object>>();
+  if (_alwaysFalse(null)) {
+    // We test this at compile time only because we don't want to have an
+    // infinite loop
+    do {
+      x.expectStaticType<Exactly<Object>>();
+      y.expectStaticType<Exactly<Object>>();
+    } while (b);
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+  x.expectStaticType<Exactly<Object>>();
+  y.expectStaticType<Exactly<Object>>();
+  for ([
+    x.expectStaticType<Exactly<Object>>(),
+    y.expectStaticType<Exactly<Object>>()
+  ];
+      b;
+      x.expectStaticType<Exactly<Object>>(),
+      y.expectStaticType<Exactly<Object>>()) {
+    x.expectStaticType<Exactly<Object>>();
+    y.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+conditional(Object x) {
+  bool b = x is int ? true : false;
+  if ((b)) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (!b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  if (b && _alwaysTrue(x.expectStaticType<Exactly<int>>())) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<Object>>()) && b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b || _alwaysFalse(x.expectStaticType<Exactly<Object>>())) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<Object>>()) || b) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b) {
+    x.expectStaticType<Exactly<int>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  while (b) {
+    x.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<Object>>();
+  do {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  } while (b);
+  x.expectStaticType<Exactly<Object>>();
+  for (x.expectStaticType<Exactly<Object>>();
+      b;
+      x.expectStaticType<Exactly<int>>()) {
+    x.expectStaticType<Exactly<int>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+assignment(Object x) {
+  // Note: flow analysis currently doesn't understand that `x = y` has the same
+  // value as `y`, so no promotion happens in this test.
+  bool b1;
+  bool b2 = b1 = x is int;
+  if ((b2)) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (!b2) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b2 && _alwaysTrue(x.expectStaticType<Exactly<Object>>())) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysTrue(x.expectStaticType<Exactly<Object>>()) && b2) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b2 || _alwaysFalse(x.expectStaticType<Exactly<Object>>())) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (_alwaysFalse(x.expectStaticType<Exactly<Object>>()) || b2) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  if (b2) {
+    x.expectStaticType<Exactly<Object>>();
+  } else {
+    x.expectStaticType<Exactly<Object>>();
+  }
+  while (b2) {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  }
+  x.expectStaticType<Exactly<Object>>();
+  do {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  } while (b2);
+  x.expectStaticType<Exactly<Object>>();
+  for (x.expectStaticType<Exactly<Object>>();
+      b2;
+      x.expectStaticType<Exactly<Object>>()) {
+    x.expectStaticType<Exactly<Object>>();
+    if (_alwaysTrue(null)) break;
+  }
+}
+
+main() {
+  is_('foo');
+  is_(0);
+  isNot('foo');
+  isNot(0);
+  not('foo');
+  not(0);
+  eqNull(null);
+  eqNull(0);
+  notEqNull(null);
+  notEqNull(0);
+  nullEq(null);
+  nullEq(0);
+  nullNotEq(null);
+  nullNotEq(0);
+  and('foo', 'bar');
+  and('foo', 1);
+  and(0, 'bar');
+  and(0, 1);
+  or('foo', 'bar');
+  or('foo', 1);
+  or(0, 'bar');
+  or(0, 1);
+  conditional('foo');
+  conditional(0);
+  assignment('foo');
+  assignment(0);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_join_equivalent_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_join_equivalent_test.dart
new file mode 100644
index 0000000..4158001
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_join_equivalent_test.dart
@@ -0,0 +1,264 @@
+// 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 '../../static_type_helper.dart';
+
+// This test verifies that when control flow paths are joined, flow analysis
+// does not recognize and coalesce distinct but equivalent assignments of test
+// expressions to a boolean.  So for example, even though this promotes:
+//
+//   bool b;
+//   b = x != null;
+//   if (b) { /* x is promoted to non-nullable */ }
+//
+// This does not:
+//
+//   bool b;
+//   if (...) {
+//     b = x != null;
+//   } else {
+//     b = x != null;
+//   }
+//   if (b) { /* x is not promoted */ }
+//
+// We test all flow control constructs where a join might occur, including:
+// - At the end of an if/else construct or conditional expression
+// - At the end of a loop where the "break" control flow path joins the main
+//   control flow path
+// - At the point in a "do" or "for" loop where the "continue" control flow path
+//   joins the main control flow path
+// - Inside a loop where multiple "break" or "continue" paths are implicitly
+//   joined
+// - Inside a switch statement where multiple "break" paths are implicitly
+//   joined
+// - At the end of an exhaustive switch statement where the last case is
+//   implicitly joined to the "break" path
+// - After a "catch" where the main control flow path is resumed
+// - After a labeled statement where the "break" control flow path is joined to
+//   the main control flow path
+
+enum E { E1, E2 }
+
+bool _alwaysFalse(dynamic d) => false;
+
+dynamic _alwaysThrow(dynamic d) {
+  throw 'foo';
+}
+
+test(int? x, bool b1, E e) {
+  {
+    bool b2;
+    b1
+        ? [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]
+        : [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null];
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    if (b1) {
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+    } else {
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    [
+      if (b1)
+        [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]
+      else
+        [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]
+    ];
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    ({
+      if (b1)
+        [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]
+      else
+        [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]
+    });
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    ({
+      if (b1)
+        [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]: null
+      else
+        [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]: null
+    });
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    ({
+      if (b1)
+        null: [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]
+      else
+        null: [b2 = x != null, b2 ? x.expectStaticType<Exactly<int>>() : null]
+    });
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    do {
+      if (b1) {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break;
+      }
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+    } while (false);
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2 = false;
+    for (int i = 0; i < 1; i++) {
+      if (b1) {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break;
+      }
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2 = false;
+    int i = 0;
+    while (i < 1) {
+      if (b1) {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break;
+      }
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+      i++;
+    }
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    do {
+      if (b1) {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        continue;
+      }
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+    } while (_alwaysFalse(b2 ? x.expectStaticType<Exactly<int?>>() : null));
+  }
+  {
+    try {
+      bool b2;
+      for (;; _alwaysThrow(b2 ? x.expectStaticType<Exactly<int?>>() : null)) {
+        if (b1) {
+          b2 = x != null;
+          if (b2) x.expectStaticType<Exactly<int>>();
+          continue;
+        }
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+      }
+    } catch (_) {}
+  }
+  {
+    bool b2;
+    while (true) {
+      if (b1) {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break;
+      } else {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break;
+      }
+    }
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    do {
+      if (b1) {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        continue;
+      } else {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        continue;
+      }
+    } while (_alwaysFalse(b2 ? x.expectStaticType<Exactly<int?>>() : null));
+  }
+  {
+    bool b2;
+    switch (e) {
+      case E.E1:
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break;
+      case E.E2:
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break;
+    }
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    switch (e) {
+      case E.E1:
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break;
+      case E.E2:
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    try {
+      if (b1) throw 'foo';
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+    } catch (_) {
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    bool b2;
+    label:
+    {
+      if (b1) {
+        b2 = x != null;
+        if (b2) x.expectStaticType<Exactly<int>>();
+        break label;
+      }
+      b2 = x != null;
+      if (b2) x.expectStaticType<Exactly<int>>();
+    }
+    if (b2) x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  test(null, false, E.E1);
+  test(null, true, E.E2);
+  test(1, false, E.E1);
+  test(1, true, E.E2);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_logical_op_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_logical_op_test.dart
new file mode 100644
index 0000000..07ffdac
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_logical_op_test.dart
@@ -0,0 +1,471 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks that local boolean variables can be used to perform type
+// promotion even when combined using logical operators.  It also verifies that
+// these type promotions are appropriately invalidated by reassignments.
+
+testAnd(int? x, int? y, int? z, bool b) {
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    if (b1 && b2) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    x = z;
+    bool b2 = y is int;
+    if (b1 && b2) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    y = z;
+    bool b2 = y is int;
+    if (b1 && b2) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    b1 = b;
+    bool b2 = y is int;
+    if (b1 && b2) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    x = z;
+    if (b1 && b2) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    y = z;
+    if (b1 && b2) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    b1 = b;
+    if (b1 && b2) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    b2 = b;
+    if (b1 && b2) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    if (b3) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    x = z;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    if (b3) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    y = z;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    if (b3) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    b1 = b;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    if (b3) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    x = z;
+    bool b3 = b1 && b2;
+    if (b3) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    y = z;
+    bool b3 = b1 && b2;
+    if (b3) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    b1 = b;
+    bool b3 = b1 && b2;
+    if (b3) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    b2 = b;
+    bool b3 = b1 && b2;
+    if (b3) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    x = z;
+    if (b3) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    y = z;
+    if (b3) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    b1 = b;
+    if (b3) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    b2 = b;
+    if (b3) {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is int;
+    bool b2 = y is int;
+    bool b3 = b1 && b2;
+    b3 = b;
+    if (b3) {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+}
+
+testOr(int? x, int? y, int? z, bool b) {
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    if (b1 || b2) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    x = z;
+    bool b2 = y is! int;
+    if (b1 || b2) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    y = z;
+    bool b2 = y is! int;
+    if (b1 || b2) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    b1 = b;
+    bool b2 = y is! int;
+    if (b1 || b2) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    x = z;
+    if (b1 || b2) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    y = z;
+    if (b1 || b2) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    b1 = b;
+    if (b1 || b2) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    b2 = b;
+    if (b1 || b2) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    x = z;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    y = z;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    b1 = b;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    x = z;
+    bool b3 = b1 || b2;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    y = z;
+    bool b3 = b1 || b2;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    b1 = b;
+    bool b3 = b1 || b2;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    b2 = b;
+    bool b3 = b1 || b2;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    x = z;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    y = z;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    b1 = b;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    b2 = b;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int>>();
+      y.expectStaticType<Exactly<int>>();
+    }
+  }
+  {
+    bool b1 = x is! int;
+    bool b2 = y is! int;
+    bool b3 = b1 || b2;
+    b3 = b;
+    if (b3) {
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+      y.expectStaticType<Exactly<int?>>();
+    }
+  }
+}
+
+main() {
+  testAnd(1, 2, 3, true);
+  testAnd(1, 2, 3, false);
+  testAnd(1, 2, null, true);
+  testAnd(1, 2, null, false);
+  testAnd(1, null, 3, true);
+  testAnd(1, null, 3, false);
+  testAnd(1, null, null, true);
+  testAnd(1, null, null, false);
+  testAnd(null, 2, 3, true);
+  testAnd(null, 2, 3, false);
+  testAnd(null, 2, null, true);
+  testAnd(null, 2, null, false);
+  testAnd(null, null, 3, true);
+  testAnd(null, null, 3, false);
+  testAnd(null, null, null, true);
+  testAnd(null, null, null, false);
+  testOr(1, 2, 3, true);
+  testOr(1, 2, 3, false);
+  testOr(1, 2, null, true);
+  testOr(1, 2, null, false);
+  testOr(1, null, 3, true);
+  testOr(1, null, 3, false);
+  testOr(1, null, null, true);
+  testOr(1, null, null, false);
+  testOr(null, 2, 3, true);
+  testOr(null, 2, 3, false);
+  testOr(null, 2, null, true);
+  testOr(null, 2, null, false);
+  testOr(null, null, 3, true);
+  testOr(null, null, 3, false);
+  testOr(null, null, null, true);
+  testOr(null, null, null, false);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_null_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_null_test.dart
new file mode 100644
index 0000000..d995051
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_null_test.dart
@@ -0,0 +1,27 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks that a local variable whose value is `null` cannot be used
+// in place of a literal `null` in flow analysis.
+
+test(int? x) {
+  if (x == null) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int>>();
+  }
+  int? y = null;
+  if (x == y) {
+    x.expectStaticType<Exactly<int?>>();
+  } else {
+    x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  test(0);
+  test(null);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_promoted_on_assignment_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_promoted_on_assignment_test.dart
new file mode 100644
index 0000000..e291ff8
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_promoted_on_assignment_test.dart
@@ -0,0 +1,49 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks that local variables can be used to perform type promotion
+// even in the case where the assignment ot (or initialization of) the local
+// variable promotes it.
+
+test(int? x) {
+  {
+    bool? b = null; // Makes `bool` a type of interest for `b`
+    b = x != null; // Promotes `b` to `bool`
+    b.expectStaticType<Exactly<bool>>();
+    if (b) {
+      x.expectStaticType<Exactly<int>>();
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+    }
+  }
+  {
+    Object b = Object();
+    if (b is! bool) {
+      // Makes `bool` a type of interest for `b`
+      b = x != null; // Promotes `b` to `bool`
+      b.expectStaticType<Exactly<bool>>();
+      if (b) {
+        x.expectStaticType<Exactly<int>>();
+      } else {
+        x.expectStaticType<Exactly<int?>>();
+      }
+    }
+  }
+  {
+    bool? b = x != null; // Promotes `b` to `bool`
+    b.expectStaticType<Exactly<bool>>();
+    if (b) {
+      x.expectStaticType<Exactly<int>>();
+    } else {
+      x.expectStaticType<Exactly<int?>>();
+    }
+  }
+}
+
+main() {
+  test(null);
+  test(0);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_promoted_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_promoted_test.dart
new file mode 100644
index 0000000..681bcb7
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_promoted_test.dart
@@ -0,0 +1,20 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks that local variables can be used to perform type promotion
+// even in the case where the local variable is itself promoted.
+
+test(int? x) {
+  Object b = x != null;
+  if (b is bool && b) {
+    x.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  test(null);
+  test(0);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_test.dart
new file mode 100644
index 0000000..0e8450d
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_test.dart
@@ -0,0 +1,814 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks whether a local boolean variable can be used to perform type
+// promotion, for various ways of declaring and assigning to it.
+//
+// For the boolean, we test all combinations of:
+// - type `bool`, `Object`, `Object?`, or `dynamic`
+// - late or non-late
+// - final or non-final
+// - assigned at initialization time or later
+// For the promoted variable, we test all combinations of:
+// - parameter, unmodified from its initial value
+// - parameter, assigned later
+// - local variable, assigned at initialization
+// - local variable, assigned later
+
+parameterUnmodified(int? x) {
+  {
+    late final bool b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final bool b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late bool b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late bool b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final bool b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late final Object b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object? b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object? b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object? b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object? b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final dynamic b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final dynamic b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late dynamic b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late dynamic b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final dynamic b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    dynamic b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+}
+
+parameterModifiedLater(int? x, int? y) {
+  x = y;
+  {
+    late final bool b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final bool b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late bool b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late bool b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final bool b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late final Object b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object? b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object? b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object? b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object? b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final dynamic b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final dynamic b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late dynamic b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late dynamic b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final dynamic b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    dynamic b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+}
+
+localVariableInitialized(int? y) {
+  int? x = y;
+  {
+    late final bool b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final bool b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late bool b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late bool b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final bool b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late final Object b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object? b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object? b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object? b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object? b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final dynamic b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final dynamic b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late dynamic b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late dynamic b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final dynamic b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    dynamic b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+}
+
+localVariableModifiedLater(int? y) {
+  int? x;
+  x = y;
+  {
+    late final bool b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final bool b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late bool b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late bool b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final bool b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late final Object b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object? b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object? b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object? b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    final Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object? b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    Object? b;
+    b = x != null;
+    // We don't currently recognize that `b as bool` has the same value as `b`,
+    // so we don't promote.  TODO(paulberry): should we?
+    if (b as bool) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final dynamic b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late final dynamic b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    late dynamic b = x != null;
+    // We don't promote based on the initializers of late locals because we
+    // don't know when they execute.
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  {
+    late dynamic b;
+    b = x != null;
+    // We do promote based on assignments to late locals because we do know when
+    // they execute.
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    final dynamic b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    dynamic b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    dynamic b;
+    b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  parameterUnmodified(null);
+  parameterUnmodified(0);
+  parameterModifiedLater(null, null);
+  parameterModifiedLater(null, 0);
+  localVariableInitialized(null);
+  localVariableInitialized(0);
+  localVariableModifiedLater(null);
+  localVariableModifiedLater(0);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_try_finally_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_try_finally_test.dart
new file mode 100644
index 0000000..96a4fa1
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_try_finally_test.dart
@@ -0,0 +1,58 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks that a local boolean condition variable can be used for
+// promotion in various corner case scenarios involving try/finally statements.
+
+test(int? x, bool b2) {
+  {
+    bool b = b2;
+    try {
+      b = x != null;
+      if (b) x.expectStaticType<Exactly<int>>();
+    } finally {
+      if (b) x.expectStaticType<Exactly<int?>>();
+    }
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b;
+    try {
+      b = x != null;
+      if (b) x.expectStaticType<Exactly<int>>();
+    } finally {
+      // Note: we can't do `if (b)` here because `b` is not definitely assigned.
+    }
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b = b2;
+    try {
+      if (b) x.expectStaticType<Exactly<int?>>();
+    } finally {
+      b = x != null;
+      if (b) x.expectStaticType<Exactly<int>>();
+    }
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+  {
+    bool b;
+    try {
+      // Note: we can't do `if (b)` here because `b` is not definitely assigned.
+    } finally {
+      b = x != null;
+      if (b) x.expectStaticType<Exactly<int>>();
+    }
+    if (b) x.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  test(null, false);
+  test(null, true);
+  test(0, false);
+  test(0, true);
+}
diff --git a/tests/language/nnbd/flow_analysis/local_boolean_undefeated_by_assignment_test.dart b/tests/language/nnbd/flow_analysis/local_boolean_undefeated_by_assignment_test.dart
new file mode 100644
index 0000000..2ee8380
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/local_boolean_undefeated_by_assignment_test.dart
@@ -0,0 +1,566 @@
+// 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 '../../static_type_helper.dart';
+
+// This test checks various scenarios in which the use of a local variable for
+// type promotion is not defeated by an assignment to the local variable itself
+// or an assignment to the variable that would be promoted, due to the fact that
+// there is no control flow path from the assignment to the use.
+
+lateInitializer_noAssignments(int? x) {
+  bool b = x != null;
+  late final y = b ? x.expectStaticType<Exactly<int>>() : 3;
+}
+
+afterConditionalThen_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b2
+        ? [b = true, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+        : null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterConditionalThen_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b2
+        ? [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+        : null;
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterConditionalElse_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b2
+        ? null
+        : [b = true, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo'];
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterConditionalElse_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    b2
+        ? null
+        : [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo'];
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfStatementThen_toConditionalVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  if (b2) {
+    b = true;
+    if (b) x.expectStaticType<Exactly<int?>>();
+    return;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterIfStatementThen_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  if (b2) {
+    x = y;
+    if (b) x.expectStaticType<Exactly<int?>>();
+    return;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterIfStatementElse_toConditionalVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  if (b2) {
+  } else {
+    b = true;
+    if (b) x.expectStaticType<Exactly<int?>>();
+    return;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterIfStatementElse_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  if (b2) {
+  } else {
+    x = y;
+    if (b) x.expectStaticType<Exactly<int?>>();
+    return;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterIfListThen_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    [
+      if (b2)
+        [b = true, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    ];
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfListThen_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    [
+      if (b2) [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    ];
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfListElse_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    [
+      if (b2)
+        null
+      else
+        [b = true, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    ];
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfListElse_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    [
+      if (b2)
+        null
+      else
+        [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    ];
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfSetThen_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        [b = true, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfSetThen_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2) [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfSetElse_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        null
+      else
+        [b = true, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfSetElse_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        null
+      else
+        [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfMapKeyThen_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        [b = true, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']:
+            null
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfMapKeyThen_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']: null
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfMapKeyElse_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        null: null
+      else
+        [b = true, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']:
+            null
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfMapKeyElse_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        null: null
+      else
+        [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']: null
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfMapValueThen_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        null: [
+          b = true,
+          if (b) x.expectStaticType<Exactly<int?>>(),
+          throw 'foo'
+        ]
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfMapValueThen_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        null: [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfMapValueElse_toConditionalVar(int? x, bool b2) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        null: null
+      else
+        null: [
+          b = true,
+          if (b) x.expectStaticType<Exactly<int?>>(),
+          throw 'foo'
+        ]
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterIfMapValueElse_toPromotedVar(int? x, bool b2, int? y) {
+  try {
+    bool b = x != null;
+    if (b) x.expectStaticType<Exactly<int>>();
+    ({
+      if (b2)
+        null: null
+      else
+        null: [x = y, if (b) x.expectStaticType<Exactly<int?>>(), throw 'foo']
+    });
+    if (b) x.expectStaticType<Exactly<int>>();
+  } on String {}
+}
+
+afterSwitch_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  switch (i) {
+    case 0:
+      b = true;
+      if (b) x.expectStaticType<Exactly<int?>>();
+      return;
+    case 1:
+      break;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterSwitch_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  switch (i) {
+    case 0:
+      x = y;
+      if (b) x.expectStaticType<Exactly<int?>>();
+      return;
+    case 1:
+      break;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterTryCatchTry_toConditionalVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    if (b2) {
+      b = true;
+      if (b) x.expectStaticType<Exactly<int?>>();
+      return;
+    }
+  } catch (_) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    return;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterTryCatchTry_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    if (b2) {
+      x = y;
+      if (b) x.expectStaticType<Exactly<int?>>();
+      return;
+    }
+  } catch (_) {
+    if (b) x.expectStaticType<Exactly<int?>>();
+    return;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterTryCatchCatch_toConditionalVar(int? x) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {} catch (_) {
+    b = true;
+    if (b) x.expectStaticType<Exactly<int?>>();
+    return;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterTryCatchCatch_toPromotedVar(int? x, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {} catch (_) {
+    x = y;
+    if (b) x.expectStaticType<Exactly<int?>>();
+    return;
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterTryFinallyTry_toConditionalVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    if (b2) {
+      b = true;
+      if (b) x.expectStaticType<Exactly<int?>>();
+      return;
+    }
+  } finally {
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterTryFinallyTry_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {
+    if (b2) {
+      x = y;
+      if (b) x.expectStaticType<Exactly<int?>>();
+      return;
+    }
+  } finally {
+    if (b) x.expectStaticType<Exactly<int?>>();
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterTryFinallyFinally_toConditionalVar(int? x, bool b2) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {} finally {
+    if (b2) {
+      b = true;
+      if (b) x.expectStaticType<Exactly<int?>>();
+      return;
+    }
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+afterTryFinallyFinally_toPromotedVar(int? x, bool b2, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  try {} finally {
+    if (b2) {
+      x = y;
+      if (b) x.expectStaticType<Exactly<int?>>();
+      return;
+    }
+  }
+  if (b) x.expectStaticType<Exactly<int>>();
+}
+
+switchLaterUnlabeled_toConditionalVar(int? x, int i) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  switch (i) {
+    case 0:
+      // Promotion is preserved because the case clause is unlabeled, so there's
+      // no path from the assignment back to here.
+      if (b) x.expectStaticType<Exactly<int>>();
+      break;
+    case 1:
+      b = true;
+      break;
+  }
+}
+
+switchLaterUnlabeled_toPromotedVar(int? x, int i, int? y) {
+  bool b = x != null;
+  if (b) x.expectStaticType<Exactly<int>>();
+  switch (i) {
+    case 0:
+      // Promotion is preserved because the case clause is unlabeled, so there's
+      // no path from the assignment back to here.
+      if (b) x.expectStaticType<Exactly<int>>();
+      break;
+    case 1:
+      x = y;
+      break;
+  }
+}
+
+main() {
+  lateInitializer_noAssignments(0);
+  lateInitializer_noAssignments(null);
+  afterConditionalThen_toConditionalVar(0, true);
+  afterConditionalThen_toConditionalVar(null, true);
+  afterConditionalThen_toPromotedVar(0, true, null);
+  afterConditionalThen_toPromotedVar(null, true, null);
+  afterConditionalElse_toConditionalVar(0, false);
+  afterConditionalElse_toConditionalVar(null, false);
+  afterConditionalElse_toPromotedVar(0, false, null);
+  afterConditionalElse_toPromotedVar(null, false, null);
+  afterIfStatementThen_toConditionalVar(0, true);
+  afterIfStatementThen_toConditionalVar(null, true);
+  afterIfStatementThen_toPromotedVar(0, true, null);
+  afterIfStatementThen_toPromotedVar(null, true, null);
+  afterIfStatementElse_toConditionalVar(0, false);
+  afterIfStatementElse_toConditionalVar(null, false);
+  afterIfStatementElse_toPromotedVar(0, false, null);
+  afterIfStatementElse_toPromotedVar(null, false, null);
+  afterIfListThen_toConditionalVar(0, true);
+  afterIfListThen_toConditionalVar(null, true);
+  afterIfListThen_toPromotedVar(0, true, null);
+  afterIfListThen_toPromotedVar(null, true, null);
+  afterIfListElse_toConditionalVar(0, false);
+  afterIfListElse_toConditionalVar(null, false);
+  afterIfListElse_toPromotedVar(0, false, null);
+  afterIfListElse_toPromotedVar(null, false, null);
+  afterIfSetThen_toConditionalVar(0, true);
+  afterIfSetThen_toConditionalVar(null, true);
+  afterIfSetThen_toPromotedVar(0, true, null);
+  afterIfSetThen_toPromotedVar(null, true, null);
+  afterIfSetElse_toConditionalVar(0, false);
+  afterIfSetElse_toConditionalVar(null, false);
+  afterIfSetElse_toPromotedVar(0, false, null);
+  afterIfSetElse_toPromotedVar(null, false, null);
+  afterIfMapKeyThen_toConditionalVar(0, true);
+  afterIfMapKeyThen_toConditionalVar(null, true);
+  afterIfMapKeyThen_toPromotedVar(0, true, null);
+  afterIfMapKeyThen_toPromotedVar(null, true, null);
+  afterIfMapKeyElse_toConditionalVar(0, false);
+  afterIfMapKeyElse_toConditionalVar(null, false);
+  afterIfMapKeyElse_toPromotedVar(0, false, null);
+  afterIfMapKeyElse_toPromotedVar(null, false, null);
+  afterIfMapValueThen_toConditionalVar(0, true);
+  afterIfMapValueThen_toConditionalVar(null, true);
+  afterIfMapValueThen_toPromotedVar(0, true, null);
+  afterIfMapValueThen_toPromotedVar(null, true, null);
+  afterIfMapValueElse_toConditionalVar(0, false);
+  afterIfMapValueElse_toConditionalVar(null, false);
+  afterIfMapValueElse_toPromotedVar(0, false, null);
+  afterIfMapValueElse_toPromotedVar(null, false, null);
+  afterSwitch_toConditionalVar(0, 1);
+  afterSwitch_toConditionalVar(null, 1);
+  afterSwitch_toPromotedVar(0, 1, null);
+  afterSwitch_toPromotedVar(null, 1, null);
+  afterTryCatchTry_toConditionalVar(0, false);
+  afterTryCatchTry_toConditionalVar(null, false);
+  afterTryCatchTry_toPromotedVar(0, false, null);
+  afterTryCatchTry_toPromotedVar(null, false, null);
+  afterTryCatchCatch_toConditionalVar(0);
+  afterTryCatchCatch_toConditionalVar(null);
+  afterTryCatchCatch_toPromotedVar(0, null);
+  afterTryCatchCatch_toPromotedVar(null, null);
+  afterTryFinallyTry_toConditionalVar(0, false);
+  afterTryFinallyTry_toConditionalVar(null, false);
+  afterTryFinallyTry_toPromotedVar(0, false, null);
+  afterTryFinallyTry_toPromotedVar(null, false, null);
+  afterTryFinallyFinally_toConditionalVar(0, false);
+  afterTryFinallyFinally_toConditionalVar(null, false);
+  afterTryFinallyFinally_toPromotedVar(0, false, null);
+  afterTryFinallyFinally_toPromotedVar(null, false, null);
+  switchLaterUnlabeled_toConditionalVar(0, 0);
+  switchLaterUnlabeled_toConditionalVar(null, 0);
+  switchLaterUnlabeled_toPromotedVar(0, 0, null);
+  switchLaterUnlabeled_toPromotedVar(null, 0, null);
+}
diff --git a/tests/language/nnbd/flow_analysis/this_not_promoted_test.dart b/tests/language/nnbd/flow_analysis/this_not_promoted_test.dart
new file mode 100644
index 0000000..ec329b4
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/this_not_promoted_test.dart
@@ -0,0 +1,110 @@
+// 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 '../../static_type_helper.dart';
+
+// This test verifies that neither an `== null` nor an `is` test can promote the
+// type of `this`.  (In principle, we could soundly do so, but we have decided
+// not to do so at this time).
+
+class C {
+  void equality() {
+    if (this == null) {
+      this.expectStaticType<Exactly<C>>();
+    } else {
+      this.expectStaticType<Exactly<C>>();
+    }
+  }
+
+  void isSameType() {
+    if (this is C) {
+      this.expectStaticType<Exactly<C>>();
+    } else {
+      this.expectStaticType<Exactly<C>>();
+    }
+  }
+
+  void isSubtype() {
+    if (this is D) {
+      this.expectStaticType<Exactly<C>>();
+    } else {
+      this.expectStaticType<Exactly<C>>();
+    }
+  }
+}
+
+class D extends C {}
+
+class E {}
+
+class F extends E {}
+
+extension on E {
+  void equality() {
+    if (this == null) {
+      this.expectStaticType<Exactly<E>>();
+    } else {
+      this.expectStaticType<Exactly<E>>();
+    }
+  }
+
+  void isSameType() {
+    if (this is E) {
+      this.expectStaticType<Exactly<E>>();
+    } else {
+      this.expectStaticType<Exactly<E>>();
+    }
+  }
+
+  void isSubtype() {
+    if (this is F) {
+      this.expectStaticType<Exactly<E>>();
+    } else {
+      this.expectStaticType<Exactly<E>>();
+    }
+  }
+}
+
+class G {}
+
+extension on G? {
+  void equality() {
+    if (this == null) {
+      this.expectStaticType<Exactly<G?>>();
+    } else {
+      this.expectStaticType<Exactly<G?>>();
+    }
+  }
+
+  void isSameType() {
+    if (this is G?) {
+      this.expectStaticType<Exactly<G?>>();
+    } else {
+      this.expectStaticType<Exactly<G?>>();
+    }
+  }
+
+  void isSubtype() {
+    if (this is G) {
+      this.expectStaticType<Exactly<G?>>();
+    } else {
+      this.expectStaticType<Exactly<G?>>();
+    }
+  }
+}
+
+main() {
+  C().equality();
+  C().isSameType();
+  C().isSubtype();
+  E().equality();
+  E().isSameType();
+  E().isSubtype();
+  G().equality();
+  G().isSameType();
+  G().isSubtype();
+  (null as G?).equality();
+  (null as G?).isSameType();
+  (null as G?).isSubtype();
+}
diff --git a/tests/language/nnbd/flow_analysis/this_property_not_promoted_test.dart b/tests/language/nnbd/flow_analysis/this_property_not_promoted_test.dart
new file mode 100644
index 0000000..375221b
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/this_property_not_promoted_test.dart
@@ -0,0 +1,106 @@
+// 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 '../../static_type_helper.dart';
+
+// This test verifies that neither an `== null` nor an `is` test can promote the
+// type of a property access on `this`.  (In principle, we could soundly promote
+// some such accesses, but we have decided not to do so at this time).
+
+class _C {
+  final int? _f;
+
+  _C(this._f);
+
+  void equality_implicitThis() {
+    if (_f == null) {
+      _f.expectStaticType<Exactly<int?>>();
+    } else {
+      _f.expectStaticType<Exactly<int?>>();
+    }
+  }
+
+  void equality_explicitThis() {
+    if (this._f == null) {
+      this._f.expectStaticType<Exactly<int?>>();
+    } else {
+      this._f.expectStaticType<Exactly<int?>>();
+    }
+  }
+
+  void is_implicitThis() {
+    if (_f is int) {
+      _f.expectStaticType<Exactly<int?>>();
+    } else {
+      _f.expectStaticType<Exactly<int?>>();
+    }
+  }
+
+  void is_explicitThis() {
+    if (this._f is int) {
+      this._f.expectStaticType<Exactly<int?>>();
+    } else {
+      this._f.expectStaticType<Exactly<int?>>();
+    }
+  }
+}
+
+class _D {
+  final int? _f;
+
+  _D(this._f);
+}
+
+extension on _D {
+  void equality_implicitThis() {
+    if (_f == null) {
+      _f.expectStaticType<Exactly<int?>>();
+    } else {
+      _f.expectStaticType<Exactly<int?>>();
+    }
+  }
+
+  void equality_explicitThis() {
+    if (this._f == null) {
+      this._f.expectStaticType<Exactly<int?>>();
+    } else {
+      this._f.expectStaticType<Exactly<int?>>();
+    }
+  }
+
+  void is_implicitThis() {
+    if (_f is int) {
+      _f.expectStaticType<Exactly<int?>>();
+    } else {
+      _f.expectStaticType<Exactly<int?>>();
+    }
+  }
+
+  void is_explicitThis() {
+    if (this._f is int) {
+      this._f.expectStaticType<Exactly<int?>>();
+    } else {
+      this._f.expectStaticType<Exactly<int?>>();
+    }
+  }
+}
+
+main() {
+  _C(1).equality_implicitThis();
+  _C(1).equality_explicitThis();
+  _C(1).is_implicitThis();
+  _C(1).is_explicitThis();
+  _C(null).equality_implicitThis();
+  _C(null).equality_explicitThis();
+  _C(null).is_implicitThis();
+  _C(null).is_explicitThis();
+  _D(1).equality_implicitThis();
+  _D(1).equality_explicitThis();
+  _D(1).is_implicitThis();
+  _D(1).is_explicitThis();
+  _D(null).equality_implicitThis();
+  _D(null).equality_explicitThis();
+  _D(null).is_implicitThis();
+  _D(null).is_explicitThis();
+}
diff --git a/tests/language/nnbd/flow_analysis/unreachable_via_expr_property_test.dart b/tests/language/nnbd/flow_analysis/unreachable_via_expr_property_test.dart
new file mode 100644
index 0000000..a6e9676
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/unreachable_via_expr_property_test.dart
@@ -0,0 +1,163 @@
+// 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.
+
+/// This test verifies that `is` and `==` tests performed on a property get of
+/// an arbitrary expression do not lead to code being considered unreachable.
+/// (In principle, we could soundly mark some such code as unreachable, but we
+/// have decided not to do so at this time).
+///
+/// Exception: when the static type of the property access is guaranteed to be
+/// Null, and we are performing an `== null` test, then we do mark the non-null
+/// branch as unreachable.
+
+import '../../static_type_helper.dart';
+
+class C {
+  Null get nullProperty => null;
+  Object? get objectQProperty => null;
+}
+
+void equalitySimple(int? x, int? y, C Function() f) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (f().nullProperty == null) {
+    x = null;
+  } else {
+    y = null;
+  }
+  // Since the assignment to x was reachable, it should have static type
+  // `int?` now.  But y should still have static type `int`.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int>>();
+}
+
+void equalityWithBogusPromotion(int? x, int? y, C Function() f) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (f().objectQProperty is Null) {
+    if (f().objectQProperty == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+void isSimple(int? x, int? y, C Function() f) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (f().nullProperty is Never) {
+    x = null;
+  } else {
+    y = null;
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+void isWithBogusPromotion(int? x, int? y, C Function() f) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (f().objectQProperty is Null) {
+    if (f().objectQProperty is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+class _C {
+  final Null _nullField = null;
+  final Object? _objectQField = null;
+}
+
+void equalitySimplePrivate(int? x, int? y, _C Function() f) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (f()._nullField == null) {
+    x = null;
+  } else {
+    y = null;
+  }
+  // Since the assignment to x was reachable, it should have static type
+  // `int?` now.  But y should still have static type `int`.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int>>();
+}
+
+void equalityWithBogusPromotionPrivate(int? x, int? y, _C Function() f) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (f()._objectQField is Null) {
+    if (f()._objectQField == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+void isSimplePrivate(int? x, int? y, _C Function() f) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (f()._nullField is Never) {
+    x = null;
+  } else {
+    y = null;
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+void isWithBogusPromotionPrivate(int? x, int? y, _C Function() f) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (f()._objectQField is Null) {
+    if (f()._objectQField is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+main() {
+  equalitySimple(1, 1, () => C());
+  equalityWithBogusPromotion(1, 1, () => C());
+  isSimple(1, 1, () => C());
+  isWithBogusPromotion(1, 1, () => C());
+  equalitySimplePrivate(1, 1, () => _C());
+  equalityWithBogusPromotionPrivate(1, 1, () => _C());
+  isSimplePrivate(1, 1, () => _C());
+  isWithBogusPromotionPrivate(1, 1, () => _C());
+}
diff --git a/tests/language/nnbd/flow_analysis/unreachable_via_this_property_test.dart b/tests/language/nnbd/flow_analysis/unreachable_via_this_property_test.dart
new file mode 100644
index 0000000..ced63a5
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/unreachable_via_this_property_test.dart
@@ -0,0 +1,583 @@
+// 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.
+
+/// This test verifies that `is` and `==` tests performed on a property get of
+/// `this` do not lead to code being considered unreachable.  (In principle, we
+/// could soundly mark some such code as unreachable, but we have decided not to
+/// do so at this time).
+///
+/// Exception: when the static type of the property access is guaranteed to be
+/// Null, and we are performing an `== null` test, then we do mark the non-null
+/// branch as unreachable.
+
+import '../../static_type_helper.dart';
+
+class B {
+  Null get nullProperty => null;
+  Object? get objectQProperty => null;
+}
+
+class C extends B {
+  void equalitySimple_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (nullProperty == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignment to x was reachable, it should have static type
+    // `int?` now.  But y should still have static type `int`.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+
+  void equalitySimple_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this.nullProperty == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignment to x was reachable, it should have static type
+    // `int?` now.  But y should still have static type `int`.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+
+  void equalityWithBogusPromotion_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (objectQProperty is Null) {
+      if (objectQProperty == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void equalityWithBogusPromotion_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this.objectQProperty is Null) {
+      if (this.objectQProperty == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (nullProperty is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this.nullProperty is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (objectQProperty is Null) {
+      if (objectQProperty is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this.objectQProperty is Null) {
+      if (this.objectQProperty is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+}
+
+class D extends B {}
+
+extension on D {
+  void equalitySimple_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (nullProperty == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignment to x was reachable, it should have static type
+    // `int?` now.  But y should still have static type `int`.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+
+  void equalitySimple_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this.nullProperty == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignment to x was reachable, it should have static type
+    // `int?` now.  But y should still have static type `int`.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+
+  void equalityWithBogusPromotion_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (objectQProperty is Null) {
+      if (objectQProperty == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void equalityWithBogusPromotion_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this.objectQProperty is Null) {
+      if (this.objectQProperty == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (nullProperty is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this.nullProperty is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (objectQProperty is Null) {
+      if (objectQProperty is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this.objectQProperty is Null) {
+      if (this.objectQProperty is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+}
+
+class _B {
+  final Null _nullField = null;
+  final Object? _objectQField = null;
+}
+
+class _C extends _B {
+  void equalitySimple_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_nullField == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignment to x was reachable, it should have static type
+    // `int?` now.  But y should still have static type `int`.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+
+  void equalitySimple_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this._nullField == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignment to x was reachable, it should have static type
+    // `int?` now.  But y should still have static type `int`.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+
+  void equalityWithBogusPromotion_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_objectQField is Null) {
+      if (_objectQField == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void equalityWithBogusPromotion_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this._objectQField is Null) {
+      if (this._objectQField == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_nullField is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this._nullField is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_objectQField is Null) {
+      if (_objectQField is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this._objectQField is Null) {
+      if (this._objectQField is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+}
+
+class _D extends _B {}
+
+extension on _D {
+  void equalitySimple_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_nullField == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignment to x was reachable, it should have static type
+    // `int?` now.  But y should still have static type `int`.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+
+  void equalitySimple_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this._nullField == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignment to x was reachable, it should have static type
+    // `int?` now.  But y should still have static type `int`.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int>>();
+  }
+
+  void equalityWithBogusPromotion_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_objectQField is Null) {
+      if (_objectQField == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void equalityWithBogusPromotion_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this._objectQField is Null) {
+      if (this._objectQField == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_nullField is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this._nullField is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion_implicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (_objectQField is Null) {
+      if (_objectQField is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion_explicitThis(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this._objectQField is Null) {
+      if (this._objectQField is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  C().equalitySimple_implicitThis(1, 1);
+  C().equalitySimple_explicitThis(1, 1);
+  C().equalityWithBogusPromotion_implicitThis(1, 1);
+  C().equalityWithBogusPromotion_explicitThis(1, 1);
+  C().isSimple_implicitThis(1, 1);
+  C().isSimple_explicitThis(1, 1);
+  C().isWithBogusPromotion_implicitThis(1, 1);
+  C().isWithBogusPromotion_explicitThis(1, 1);
+  D().equalitySimple_implicitThis(1, 1);
+  D().equalitySimple_explicitThis(1, 1);
+  D().equalityWithBogusPromotion_implicitThis(1, 1);
+  D().equalityWithBogusPromotion_explicitThis(1, 1);
+  D().isSimple_implicitThis(1, 1);
+  D().isSimple_explicitThis(1, 1);
+  D().isWithBogusPromotion_implicitThis(1, 1);
+  D().isWithBogusPromotion_explicitThis(1, 1);
+  _C().equalitySimple_implicitThis(1, 1);
+  _C().equalitySimple_explicitThis(1, 1);
+  _C().equalityWithBogusPromotion_implicitThis(1, 1);
+  _C().equalityWithBogusPromotion_explicitThis(1, 1);
+  _C().isSimple_implicitThis(1, 1);
+  _C().isSimple_explicitThis(1, 1);
+  _C().isWithBogusPromotion_implicitThis(1, 1);
+  _C().isWithBogusPromotion_explicitThis(1, 1);
+  _D().equalitySimple_implicitThis(1, 1);
+  _D().equalitySimple_explicitThis(1, 1);
+  _D().equalityWithBogusPromotion_implicitThis(1, 1);
+  _D().equalityWithBogusPromotion_explicitThis(1, 1);
+  _D().isSimple_implicitThis(1, 1);
+  _D().isSimple_explicitThis(1, 1);
+  _D().isWithBogusPromotion_implicitThis(1, 1);
+  _D().isWithBogusPromotion_explicitThis(1, 1);
+}
diff --git a/tests/language/nnbd/flow_analysis/unreachable_via_this_test.dart b/tests/language/nnbd/flow_analysis/unreachable_via_this_test.dart
new file mode 100644
index 0000000..cc478bf
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/unreachable_via_this_test.dart
@@ -0,0 +1,231 @@
+// 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.
+
+/// This test verifies that `is` and `==` tests performed on `this` do not lead
+/// to code being considered unreachable.  (In principle, we could soundly mark
+/// some such code as unreachable, but we have decided not to do so at this
+/// time).
+
+import '../../static_type_helper.dart';
+
+class C {
+  void equalitySimple(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void equalityWithBogusPromotion(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Null) {
+      if (this == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Null) {
+      if (this is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+}
+
+class D {}
+
+extension on D {
+  void equalitySimple(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void equalityWithBogusPromotion(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Null) {
+      if (this == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Null) {
+      if (this is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+}
+
+class E {}
+
+extension on E? {
+  void equalitySimple(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void equalityWithBogusPromotion(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Null) {
+      if (this == null) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isSimple(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+
+  void isWithBogusPromotion(int? x, int? y) {
+    if (x == null || y == null) return;
+    x.expectStaticType<Exactly<int>>();
+    y.expectStaticType<Exactly<int>>();
+    if (this is Null) {
+      if (this is Never) {
+        x = null;
+      } else {
+        y = null;
+      }
+    }
+    // Since the assignments to x and y were both reachable, they should have
+    // static type `int?` now.
+    x.expectStaticType<Exactly<int?>>();
+    y.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  C().equalitySimple(1, 1);
+  C().equalityWithBogusPromotion(1, 1);
+  C().isSimple(1, 1);
+  C().isWithBogusPromotion(1, 1);
+  D().equalitySimple(1, 1);
+  D().equalityWithBogusPromotion(1, 1);
+  D().isSimple(1, 1);
+  D().isWithBogusPromotion(1, 1);
+  E().equalitySimple(1, 1);
+  E().equalityWithBogusPromotion(1, 1);
+  E().isSimple(1, 1);
+  E().isWithBogusPromotion(1, 1);
+  (null as E?).equalitySimple(1, 1);
+  (null as E?).equalityWithBogusPromotion(1, 1);
+  (null as E?).isSimple(1, 1);
+  (null as E?).isWithBogusPromotion(1, 1);
+}
diff --git a/tests/language/nnbd/flow_analysis/unreachable_via_variable_property_test.dart b/tests/language/nnbd/flow_analysis/unreachable_via_variable_property_test.dart
new file mode 100644
index 0000000..2268dc5
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/unreachable_via_variable_property_test.dart
@@ -0,0 +1,163 @@
+// 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.
+
+/// This test verifies that `is` and `==` tests performed on a property get of a
+/// variable do not lead to code being considered unreachable.  (In principle,
+/// we could soundly mark some such code as unreachable, but we have decided not
+/// to do so at this time).
+///
+/// Exception: when the static type of the property access is guaranteed to be
+/// Null, and we are performing an `== null` test, then we do mark the non-null
+/// branch as unreachable.
+
+import '../../static_type_helper.dart';
+
+class C {
+  Null get nullProperty => null;
+  Object? get objectQProperty => null;
+}
+
+void equalitySimple(int? x, int? y, C c) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (c.nullProperty == null) {
+    x = null;
+  } else {
+    y = null;
+  }
+  // Since the assignment to x was reachable, it should have static type
+  // `int?` now.  But y should still have static type `int`.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int>>();
+}
+
+void equalityWithBogusPromotion(int? x, int? y, C c) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (c.objectQProperty is Null) {
+    if (c.objectQProperty == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+void isSimple(int? x, int? y, C c) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (c.nullProperty is Never) {
+    x = null;
+  } else {
+    y = null;
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+void isWithBogusPromotion(int? x, int? y, C c) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (c.objectQProperty is Null) {
+    if (c.objectQProperty is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+class _C {
+  final Null _nullField = null;
+  final Object? _objectQField = null;
+}
+
+void equalitySimplePrivate(int? x, int? y, _C c) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (c._nullField == null) {
+    x = null;
+  } else {
+    y = null;
+  }
+  // Since the assignment to x was reachable, it should have static type
+  // `int?` now.  But y should still have static type `int`.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int>>();
+}
+
+void equalityWithBogusPromotionPrivate(int? x, int? y, _C c) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (c._objectQField is Null) {
+    if (c._objectQField == null) {
+      x = null;
+    } else {
+      y = null;
+    }
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+void isSimplePrivate(int? x, int? y, _C c) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (c._nullField is Never) {
+    x = null;
+  } else {
+    y = null;
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+void isWithBogusPromotionPrivate(int? x, int? y, _C c) {
+  if (x == null || y == null) return;
+  x.expectStaticType<Exactly<int>>();
+  y.expectStaticType<Exactly<int>>();
+  if (c._objectQField is Null) {
+    if (c._objectQField is Never) {
+      x = null;
+    } else {
+      y = null;
+    }
+  }
+  // Since the assignments to x and y were both reachable, they should have
+  // static type `int?` now.
+  x.expectStaticType<Exactly<int?>>();
+  y.expectStaticType<Exactly<int?>>();
+}
+
+main() {
+  equalitySimple(1, 1, C());
+  equalityWithBogusPromotion(1, 1, C());
+  isSimple(1, 1, C());
+  isWithBogusPromotion(1, 1, C());
+  equalitySimplePrivate(1, 1, _C());
+  equalityWithBogusPromotionPrivate(1, 1, _C());
+  isSimplePrivate(1, 1, _C());
+  isWithBogusPromotionPrivate(1, 1, _C());
+}
diff --git a/tests/language/nnbd/flow_analysis/variable_property_not_promoted_test.dart b/tests/language/nnbd/flow_analysis/variable_property_not_promoted_test.dart
new file mode 100644
index 0000000..6aa9d0c
--- /dev/null
+++ b/tests/language/nnbd/flow_analysis/variable_property_not_promoted_test.dart
@@ -0,0 +1,38 @@
+// 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 '../../static_type_helper.dart';
+
+// This test verifies that neither an `== null` nor an `is` test can promote the
+// type of a property access on a variable.  (In principle, we could soundly
+// promote some such accesses, but we have decided not to do so at this time).
+
+class _C {
+  final int? _f;
+
+  _C(this._f);
+}
+
+void equality(_C c) {
+  if (c._f == null) {
+    c._f.expectStaticType<Exactly<int?>>();
+  } else {
+    c._f.expectStaticType<Exactly<int?>>();
+  }
+}
+
+void is_(_C c) {
+  if (c._f is int) {
+    c._f.expectStaticType<Exactly<int?>>();
+  } else {
+    c._f.expectStaticType<Exactly<int?>>();
+  }
+}
+
+main() {
+  equality(_C(1));
+  is_(_C(1));
+  equality(_C(null));
+  is_(_C(null));
+}
diff --git a/tests/language/nnbd/syntax/late_modifier_bug_39658.dart b/tests/language/nnbd/syntax/late_modifier_bug_39658.dart
index 67ca1c2..3b8307a 100644
--- a/tests/language/nnbd/syntax/late_modifier_bug_39658.dart
+++ b/tests/language/nnbd/syntax/late_modifier_bug_39658.dart
@@ -25,14 +25,12 @@
   Expect.equals(1.23, a.fieldWithInit);
   Expect.equals(1.23, a.fieldWithTrivialInit);
   Expect.equals(null, a.fieldWithNullInit);
-  Expect.throws(
-      () => a.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => a.fieldWithNoInit);
   Expect.equals(1, initCalls);
   Expect.equals(1.23, a.fieldWithInit);
   Expect.equals(1.23, a.fieldWithTrivialInit);
   Expect.equals(null, a.fieldWithNullInit);
-  Expect.throws(
-      () => a.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => a.fieldWithNoInit);
   Expect.equals(1, initCalls);
   a.fieldWithInit = 4.56;
   a.fieldWithTrivialInit = 4.56;
diff --git a/tests/language/nnbd/syntax/late_modifier_final_field_test.dart b/tests/language/nnbd/syntax/late_modifier_final_field_test.dart
index a22c6ec..bfa9d7f 100644
--- a/tests/language/nnbd/syntax/late_modifier_final_field_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_final_field_test.dart
@@ -39,8 +39,7 @@
     Expect.equals(123, a.fieldWithInit);
     Expect.equals(1, initCalls);
     // Setting Base.fieldWithInit twice throws an error.
-    Expect.throws(() => {a.fieldWithInit = 789},
-        (error) => error is LateInitializationError);
+    Expect.throws<Error>(() => {a.fieldWithInit = 789});
     Expect.equals(1, initCalls);
     Expect.equals(123, a.fieldWithInit);
     Expect.equals(1, initCalls);
@@ -53,20 +52,17 @@
     Expect.equals(456, (a as A).superFieldWithInit);
     Expect.equals(0, initCalls);
     // Setting Base.fieldWithInit twice throws an error.
-    Expect.throws(() => {a2.fieldWithInit = 789},
-        (error) => error is LateInitializationError);
+    Expect.throws<Error>(() => {a2.fieldWithInit = 789});
     Expect.equals(0, initCalls);
     Expect.equals(123, a2.fieldWithInit);
     Expect.equals(456, (a as A).superFieldWithInit);
     Expect.equals(1, initCalls);
 
     B b = B();
-    Expect.throws(
-        () => b.fieldWithNoInit, (error) => error is LateInitializationError);
+    Expect.throws<Error>(() => b.fieldWithNoInit);
     b.fieldWithNoInit = 123;
     Expect.equals(123, b.fieldWithNoInit);
-    Expect.throws(() => {b.fieldWithNoInit = 456},
-        (error) => error is LateInitializationError);
+    Expect.throws<Error>(() => {b.fieldWithNoInit = 456});
     Expect.equals(123, b.fieldWithNoInit);
     initCalls = 0;
   }
diff --git a/tests/language/nnbd/syntax/late_modifier_final_local_var_test.dart b/tests/language/nnbd/syntax/late_modifier_final_local_var_test.dart
index 97d790d..cca2eaa 100644
--- a/tests/language/nnbd/syntax/late_modifier_final_local_var_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_final_local_var_test.dart
@@ -22,21 +22,13 @@
     Expect.equals(1, initCalls);
 
     late final int fieldWithNoInit;
-    Expect.throws(
-      () => fieldWithNoInit,
-      (error) => error is LateInitializationError,
-    );
+    Expect.throws<Error>(() => fieldWithNoInit);
     // Confuse the definite assignment analysis.
     if (1 > 0) {
       fieldWithNoInit = 123;
     }
     Expect.equals(123, fieldWithNoInit);
-    Expect.throws(
-      () {
-        fieldWithNoInit = 456;
-      },
-      (error) => error is LateInitializationError,
-    );
+    Expect.throws<Error>(() => fieldWithNoInit = 456);
     Expect.equals(123, fieldWithNoInit);
     initCalls = 0;
   }
diff --git a/tests/language/nnbd/syntax/late_modifier_global_var_test.dart b/tests/language/nnbd/syntax/late_modifier_global_var_test.dart
index 7a7f9c9..b084f02 100644
--- a/tests/language/nnbd/syntax/late_modifier_global_var_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_global_var_test.dart
@@ -27,14 +27,12 @@
   Expect.equals(123, varWithInit);
   Expect.equals(123, varWithTrivialInit);
   Expect.equals(null, varWithNullInit);
-  Expect.throws(
-      () => varWithNoInit, (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => varWithNoInit);
   Expect.equals(1, initCalls);
   Expect.equals(123, varWithInit);
   Expect.equals(123, varWithTrivialInit);
   Expect.equals(null, varWithNullInit);
-  Expect.throws(
-      () => varWithNoInit, (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => varWithNoInit);
   Expect.equals(1, initCalls);
   varWithInit = 456;
   varWithTrivialInit = 456;
@@ -70,11 +68,9 @@
   Expect.equals(null, finalVarWithNullInit);
   Expect.equals(1, initCalls);
 
-  Expect.throws(
-      () => finalVarWithNoInit, (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => finalVarWithNoInit);
   finalVarWithNoInit = 123;
   Expect.equals(123, finalVarWithNoInit);
-  Expect.throws(() => {finalVarWithNoInit = 456},
-      (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => {finalVarWithNoInit = 456});
   Expect.equals(123, finalVarWithNoInit);
 }
diff --git a/tests/language/nnbd/syntax/late_modifier_local_var_test.dart b/tests/language/nnbd/syntax/late_modifier_local_var_test.dart
index 4164b8b..88878bb 100644
--- a/tests/language/nnbd/syntax/late_modifier_local_var_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_local_var_test.dart
@@ -22,14 +22,12 @@
     Expect.equals(123, varWithInit);
     Expect.equals(123, varWithTrivialInit);
     Expect.equals(null, varWithNullInit);
-    Expect.throws(
-        () => varWithNoInit, (error) => error is LateInitializationError);
+    Expect.throws<Error>(() => varWithNoInit);
     Expect.equals(1, initCalls);
     Expect.equals(123, varWithInit);
     Expect.equals(123, varWithTrivialInit);
     Expect.equals(null, varWithNullInit);
-    Expect.throws(
-        () => varWithNoInit, (error) => error is LateInitializationError);
+    Expect.throws<Error>(() => varWithNoInit);
     Expect.equals(1, initCalls);
     varWithInit = 456;
     varWithTrivialInit = 456;
diff --git a/tests/language/nnbd/syntax/late_modifier_non_final_field_test.dart b/tests/language/nnbd/syntax/late_modifier_non_final_field_test.dart
index bd7e91c..1ebb8ee 100644
--- a/tests/language/nnbd/syntax/late_modifier_non_final_field_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_non_final_field_test.dart
@@ -33,20 +33,16 @@
     Expect.equals(123, a.fieldWithInit);
     Expect.equals(123, a.fieldWithTrivialInit);
     Expect.equals(null, a.fieldWithNullInit);
-    Expect.throws(
-        () => a.fieldWithNoInit, (error) => error is LateInitializationError);
-    Expect.throws(() => a.nullableFieldWithNoInit,
-        (error) => error is LateInitializationError);
+    Expect.throws<Error>(() => a.fieldWithNoInit);
+    Expect.throws<Error>(() => a.nullableFieldWithNoInit);
     Expect.equals(null, a.fieldWithOnlyCtorInit);
     Expect.equals(null, a.fieldWithOnlyBothInitAndCtorInit);
     Expect.equals(1, initCalls);
     Expect.equals(123, a.fieldWithInit);
     Expect.equals(123, a.fieldWithTrivialInit);
     Expect.equals(null, a.fieldWithNullInit);
-    Expect.throws(
-        () => a.fieldWithNoInit, (error) => error is LateInitializationError);
-    Expect.throws(() => a.nullableFieldWithNoInit,
-        (error) => error is LateInitializationError);
+    Expect.throws<Error>(() => a.fieldWithNoInit);
+    Expect.throws<Error>(() => a.nullableFieldWithNoInit);
     Expect.equals(null, a.fieldWithOnlyCtorInit);
     Expect.equals(null, a.fieldWithOnlyBothInitAndCtorInit);
     Expect.equals(1, initCalls);
diff --git a/tests/language/nnbd/syntax/late_modifier_runtime_error_test.dart b/tests/language/nnbd/syntax/late_modifier_runtime_error_test.dart
index c410775..d561457 100644
--- a/tests/language/nnbd/syntax/late_modifier_runtime_error_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_runtime_error_test.dart
@@ -32,13 +32,8 @@
   }
 }
 
-bool isValidError(error, String message) {
-  if (error is LateInitializationError) {
-    Expect.equals('LateInitializationError: $message', error.toString());
-    return true;
-  }
-  return false;
-}
+bool isValidError(error, String message) =>
+    (error is Error && 'LateInitializationError: $message' == error.toString());
 
 main() {
   // Static fields.
diff --git a/tests/language/nnbd/syntax/late_modifier_static_field_test.dart b/tests/language/nnbd/syntax/late_modifier_static_field_test.dart
index ffa8b37..d536db6 100644
--- a/tests/language/nnbd/syntax/late_modifier_static_field_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_static_field_test.dart
@@ -31,14 +31,12 @@
   Expect.equals(123, A.fieldWithInit);
   Expect.equals(123, A.fieldWithTrivialInit);
   Expect.equals(null, A.fieldWithNullInit);
-  Expect.throws(
-      () => A.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => A.fieldWithNoInit);
   Expect.equals(1, initCalls);
   Expect.equals(123, A.fieldWithInit);
   Expect.equals(123, A.fieldWithTrivialInit);
   Expect.equals(null, A.fieldWithNullInit);
-  Expect.throws(
-      () => A.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => A.fieldWithNoInit);
   Expect.equals(1, initCalls);
   A.fieldWithInit = 456;
   A.fieldWithTrivialInit = 456;
diff --git a/tests/language/nnbd/syntax/late_modifier_static_final_field_test.dart b/tests/language/nnbd/syntax/late_modifier_static_final_field_test.dart
index ff6e144..66fd9bb 100644
--- a/tests/language/nnbd/syntax/late_modifier_static_final_field_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_static_final_field_test.dart
@@ -29,11 +29,9 @@
   Expect.equals(null, A.fieldWithNullInit);
   Expect.equals(1, initCalls);
 
-  Expect.throws(
-      () => A.fieldWithNoInit, (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => A.fieldWithNoInit);
   A.fieldWithNoInit = 123;
   Expect.equals(123, A.fieldWithNoInit);
-  Expect.throws(() => {A.fieldWithNoInit = 456},
-      (error) => error is LateInitializationError);
+  Expect.throws<Error>(() => {A.fieldWithNoInit = 456});
   Expect.equals(123, A.fieldWithNoInit);
 }
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_class_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_class_test.dart
index e43cd7c..9899834a 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_class_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_class_test.dart
@@ -36,7 +36,7 @@
 
   C(): v7 = T<Null>();
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -45,6 +45,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1<X> extends T<X> {}
 abstract class D3<X, Y> implements T<T> {}
 
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_dynamic_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_dynamic_test.dart
index a9753d9..b1ac43a 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_dynamic_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_dynamic_test.dart
@@ -29,7 +29,7 @@
   final T<Null> v7;
 
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -38,6 +38,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_function_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_function_test.dart
index b74531c..91bc32f 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_function_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_function_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = print;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1<X> extends T<X> {}
 abstract class D2 extends C with T<int> {}
 abstract class D3<X, Y> implements T<T> {}
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_futureor_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_futureor_test.dart
index 4ae5da9..72b0eac 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_futureor_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_futureor_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = null;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_null_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_null_test.dart
index 235cd1e..c98fa1d 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_null_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_null_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = null;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_object_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_object_test.dart
index 6bafbb8..9b55fdc 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_object_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_object_test.dart
@@ -30,7 +30,7 @@
 
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1<X> extends T<X> {}
 
 abstract class D3<X, Y> extends C implements T<T> {}
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_type_variable_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_type_variable_test.dart
index 11118f8..291fc7d 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_type_variable_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_type_variable_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = null;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<D> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<D> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<D> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D {}
 mixin M {}
 
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_void_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_void_test.dart
index d38a5c5..619c64e 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_void_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_void_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = null;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language/nonfunction_type_aliases/usage_class_test.dart b/tests/language/nonfunction_type_aliases/usage_class_test.dart
index cb10823..249a701 100644
--- a/tests/language/nonfunction_type_aliases/usage_class_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_class_test.dart
@@ -34,7 +34,7 @@
 
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -43,6 +43,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1 extends T {}
 abstract class D3 implements T {}
 
diff --git a/tests/language/nonfunction_type_aliases/usage_dynamic_test.dart b/tests/language/nonfunction_type_aliases/usage_dynamic_test.dart
index 3ff37e1..dc5c93f 100644
--- a/tests/language/nonfunction_type_aliases/usage_dynamic_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_dynamic_test.dart
@@ -27,7 +27,7 @@
   final T v12;
 
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -36,6 +36,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 X foo<X>(X x) => x;
 
 T Function(T) id = (x) => x;
diff --git a/tests/language/nonfunction_type_aliases/usage_function_test.dart b/tests/language/nonfunction_type_aliases/usage_function_test.dart
index 845a68b..1ade4c0 100644
--- a/tests/language/nonfunction_type_aliases/usage_function_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_function_test.dart
@@ -28,7 +28,7 @@
 
   C(): v12 = (() {});
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -37,6 +37,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 // Awaiting updates in front end to handle crash caused by null from
 // `ClassHierarchyBuilder.getKernelTypeAsInstanceOf`. So for now the
 // following are multi-test cases, so that the rest can be tested.
diff --git a/tests/language/nonfunction_type_aliases/usage_futureor_test.dart b/tests/language/nonfunction_type_aliases/usage_futureor_test.dart
index cca3885..f39d704 100644
--- a/tests/language/nonfunction_type_aliases/usage_futureor_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_futureor_test.dart
@@ -29,7 +29,7 @@
   final T v12;
 
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -38,6 +38,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T {
   T foo(T t) => t;
 }
diff --git a/tests/language/nonfunction_type_aliases/usage_null_test.dart b/tests/language/nonfunction_type_aliases/usage_null_test.dart
index 8610487..b60efb7 100644
--- a/tests/language/nonfunction_type_aliases/usage_null_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_null_test.dart
@@ -28,7 +28,7 @@
 
   C(): v12 = null;
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -37,6 +37,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T {
   T foo(T t) => t;
 }
diff --git a/tests/language/nonfunction_type_aliases/usage_object_error_test.dart b/tests/language/nonfunction_type_aliases/usage_object_error_test.dart
index 2ea105c..cd7c78b 100644
--- a/tests/language/nonfunction_type_aliases/usage_object_error_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_object_error_test.dart
@@ -15,7 +15,12 @@
   final T v12;
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
+}
+
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
 }
 
 abstract class D2 extends C with T {}
diff --git a/tests/language/nonfunction_type_aliases/usage_object_test.dart b/tests/language/nonfunction_type_aliases/usage_object_test.dart
index 66c278c..306604d 100644
--- a/tests/language/nonfunction_type_aliases/usage_object_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_object_test.dart
@@ -28,7 +28,7 @@
 
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -37,6 +37,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1 extends T {}
 
 extension E on T {
diff --git a/tests/language/nonfunction_type_aliases/usage_type_variable_test.dart b/tests/language/nonfunction_type_aliases/usage_type_variable_test.dart
index 12aec39..6c1b6c8 100644
--- a/tests/language/nonfunction_type_aliases/usage_type_variable_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_type_variable_test.dart
@@ -34,7 +34,7 @@
 
   C(): v12 = null;
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -43,6 +43,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1 extends T {}
 abstract class D3 implements T {}
 
diff --git a/tests/language/nonfunction_type_aliases/usage_void_test.dart b/tests/language/nonfunction_type_aliases/usage_void_test.dart
index cb752e5..9857812 100644
--- a/tests/language/nonfunction_type_aliases/usage_void_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_void_test.dart
@@ -27,7 +27,7 @@
   final T v12;
 
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -36,6 +36,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T {
   T foo(T t) => t;
 }
diff --git a/tests/language/null_aware/index_this_null_aware_equals_test.dart b/tests/language/null_aware/index_this_null_aware_equals_test.dart
new file mode 100644
index 0000000..fc2ccc9
--- /dev/null
+++ b/tests/language/null_aware/index_this_null_aware_equals_test.dart
@@ -0,0 +1,15 @@
+class C {
+  static final Expando<int> _debugIds = new Expando<int>();
+
+  static int _nextDebugId = 0;
+
+  @override
+  String toString() {
+    int id = _debugIds[this] ??= _nextDebugId++;
+    return 'C$id';
+  }
+}
+
+main() {
+  print(C());
+}
diff --git a/tests/language/operator/invalid_operators_test.dart b/tests/language/operator/invalid_operators_test.dart
index badafb5..27bac6a 100644
--- a/tests/language/operator/invalid_operators_test.dart
+++ b/tests/language/operator/invalid_operators_test.dart
@@ -106,7 +106,7 @@
   // [cfe] Operator '>=' should have exactly one parameter.
   operator -(a, b) => true;
   //       ^
-  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS
+  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
   // [cfe] Operator '-' should have zero or one parameter.
   operator +(a, b) => true;
   //       ^
@@ -367,7 +367,7 @@
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
   operator -(a, [b]) => true;
   //       ^
-  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS
+  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
   // [cfe] Operator '-' should have zero or one parameter.
   //             ^
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
@@ -484,7 +484,7 @@
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
   operator -(a, {b}) => true;
   //       ^
-  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS
+  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
   // [cfe] Operator '-' should have zero or one parameter.
   //             ^
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
@@ -572,15 +572,13 @@
   operator ==<T>(a) => true;
   //       ^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
-  // [cfe] Can't infer a return type for '==' as the overridden members don't have a combined signature.
+  // [cfe] Can't infer types for '==' as the overridden members don't have a combined signature.
   //       ^
   // [cfe] Declared type variables of 'Operators7.==' doesn't match those on overridden method 'Object.=='.
   //         ^^^
   // [analyzer] SYNTACTIC_ERROR.TYPE_PARAMETERS_ON_OPERATOR
   //          ^
   // [cfe] Types parameters aren't allowed when defining an operator.
-  //             ^
-  // [cfe] Can't infer a type for 'a' as the overridden members don't have a combined signature.
   operator ><T>(a) => true;
   //        ^^^
   // [analyzer] SYNTACTIC_ERROR.TYPE_PARAMETERS_ON_OPERATOR
diff --git a/tests/language/parameter/bad_named_parameters_test.dart b/tests/language/parameter/bad_named_parameters_test.dart
index 35b1e79..9db032b 100644
--- a/tests/language/parameter/bad_named_parameters_test.dart
+++ b/tests/language/parameter/bad_named_parameters_test.dart
@@ -20,14 +20,16 @@
 
   // Parameter b passed twice.
   np.f42(10, 25, b: 25);
-  //    ^^^^^^^^^^^^^^^
+  //         ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+  //    ^^^^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 
   // Parameter x does not exist.
   np.f42(10, 25, x: 99);
-  //    ^^^^^^^^^^^^^^^
+  //         ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+  //    ^^^^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
   //             ^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_NAMED_PARAMETER
@@ -40,8 +42,9 @@
 
   // Too many parameters.
   np.f42(10, 20, 30, 40);
-  //    ^^^^^^^^^^^^^^^^
+  //         ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+  //    ^^^^^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 4 found.
 
   // Too few parameters.
diff --git a/tests/language/parameter/named_aggregated_test.dart b/tests/language/parameter/named_aggregated_test.dart
index 87e6140..252f67d 100644
--- a/tests/language/parameter/named_aggregated_test.dart
+++ b/tests/language/parameter/named_aggregated_test.dart
@@ -37,8 +37,9 @@
 main() {
   // Expect compile-time error due to missing comma in function definition.
   NamedParametersAggregatedTests.f_missing_comma(10, 25);
-  //                                            ^^^^^^^^
+  //                                                 ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //                                            ^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 
   // Expect compile-time error due to duplicate named argument.
diff --git a/tests/language/parameter/optional_named_test.dart b/tests/language/parameter/optional_named_test.dart
index 20413ad..56f2adf 100644
--- a/tests/language/parameter/optional_named_test.dart
+++ b/tests/language/parameter/optional_named_test.dart
@@ -63,36 +63,42 @@
     Expect.equals(20, F10());
     Expect.equals(20, np.f21());
     Expect.equals(20, F10(20));
-    //                   ^^^^
+    //                    ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                   ^^^^
     // [cfe] Too many positional arguments: 0 allowed, but 1 found.
     Expect.equals(20, np.f21(20));
-    //                      ^^^^
+    //                       ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                      ^^^^
     // [cfe] Too many positional arguments: 0 allowed, but 1 found.
     Expect.equals(20, F10(b: 20));
     Expect.equals(20, np.f21(b: 20));
     Expect.equals(1020, F21(10));
     Expect.equals(1020, np.f32(10));
     Expect.equals(1025, F21(10, 25));
-    //                     ^^^^^^^^
+    //                          ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                     ^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(1025, np.f32(10, 25));
-    //                        ^^^^^^^^
+    //                             ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                        ^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(1025, F21(10, b: 25));
     Expect.equals(1025, np.f32(10, b: 25));
     Expect.equals(102030, F31(10));
     Expect.equals(102030, np.f42(10));
     Expect.equals(102530, F31(10, 25));
-    //                       ^^^^^^^^
+    //                            ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                       ^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(102530, np.f42(10, 25));
-    //                          ^^^^^^^^
+    //                               ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                          ^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(102530, F31(10, b: 25));
     Expect.equals(102530, np.f42(10, b: 25));
@@ -101,12 +107,14 @@
     Expect.equals(102535, F31(10, b: 25, c: 35));
     Expect.equals(102535, np.f42(10, b: 25, c: 35));
     Expect.equals(102535, F31(10, 25, c:35));
-    //                       ^^^^^^^^^^^^^^
+    //                            ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                       ^^^^^^^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(102535, np.f42(10, 25, c:35));
-    //                          ^^^^^^^^^^^^^^
+    //                               ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                          ^^^^^^^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(102535, F31(10, c: 35, b: 25));
     Expect.equals(102535, np.f42(10, c: 35, b: 25));
@@ -116,8 +124,9 @@
     Expect.equals(10203540, np.f52(10, c: 35));
     Expect.equals(10250045, F41(10, d: 45, b: 25));
     Expect.equals(10250045, F41(10, 25, d:45));
-    //                         ^^^^^^^^^^^^^^
+    //                              ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                         ^^^^^^^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(10250045, np.f52(10, d: 45, b: 25));
     Expect.equals(10253545, F41(10, d: 45, c: 35, b: 25));
diff --git a/tests/language/redirecting/factory_default_values_test.dart b/tests/language/redirecting/factory_default_values_test.dart
index 84a7d17..23a0e3c 100644
--- a/tests/language/redirecting/factory_default_values_test.dart
+++ b/tests/language/redirecting/factory_default_values_test.dart
@@ -33,7 +33,8 @@
   Expect.equals(x.b, 0);
 
   var y = new A.f(42, 43);
-  //             ^^^^^^^^
+  //                  ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //             ^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 }
diff --git a/tests/language/regress/regress23038_test.dart b/tests/language/regress/regress23038_test.dart
index bf5cbd0..0967098 100644
--- a/tests/language/regress/regress23038_test.dart
+++ b/tests/language/regress/regress23038_test.dart
@@ -10,7 +10,7 @@
 // [cfe] Cyclic definition of factory 'C'.
     = C<C<T>>
     //^^^^^^^
-    // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_FACTORY_REDIRECT
+    // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
     // [cfe] The constructor function type 'C<C<T>> Function()' isn't a subtype of 'C<T> Function()'.
   ;
 }
diff --git a/tests/language/regress/regress31596_covariant_declaration_test.dart b/tests/language/regress/regress31596_covariant_declaration_test.dart
index 20defe2..c9c9053 100644
--- a/tests/language/regress/regress31596_covariant_declaration_test.dart
+++ b/tests/language/regress/regress31596_covariant_declaration_test.dart
@@ -18,7 +18,7 @@
 
 class D extends C implements I {}
 //    ^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
+// [analyzer] COMPILE_TIME_ERROR.INVALID_IMPLEMENTATION_OVERRIDE
 // [cfe] unspecified
 
 main() {}
diff --git a/tests/language/regress/regress33235_11_test.dart b/tests/language/regress/regress33235_11_test.dart
index 74710f4..74ccf45 100644
--- a/tests/language/regress/regress33235_11_test.dart
+++ b/tests/language/regress/regress33235_11_test.dart
@@ -14,6 +14,8 @@
   static int n() => 42;
   //         ^
   // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+  // [cfe] 'n' is already declared in this scope.
+  //         ^
   // [cfe] Conflicts with setter 'n'.
 }
 
diff --git a/tests/language/regress/regress35258_test.dart b/tests/language/regress/regress35258_test.dart
index d36f45f..a5707b0 100644
--- a/tests/language/regress/regress35258_test.dart
+++ b/tests/language/regress/regress35258_test.dart
@@ -6,7 +6,7 @@
   new C(42);
   //  ^
   // [cfe] Can't use 'C' because it is declared more than once.
-  //   ^^^^
+  //    ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
 }
 
diff --git a/tests/language/static/call_wrong_argument_count_test.dart b/tests/language/static/call_wrong_argument_count_test.dart
index 575c486..ca34e7cd 100644
--- a/tests/language/static/call_wrong_argument_count_test.dart
+++ b/tests/language/static/call_wrong_argument_count_test.dart
@@ -13,7 +13,8 @@
   Niesen.goodCall(1, 2, 3);
 
   Niesen.goodCall(1, 2, 3, 4);
-  //             ^^^^^^^^^^^^
+  //                       ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //             ^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 3 allowed, but 4 found.
 }
diff --git a/tests/language/super/bound_closure_test.dart b/tests/language/super/bound_closure_test.dart
index 554b0e2..5061145 100644
--- a/tests/language/super/bound_closure_test.dart
+++ b/tests/language/super/bound_closure_test.dart
@@ -72,8 +72,7 @@
   fooIntercept27() => confuse(super.lastWhere)(0);
   fooIntercept28() => confuse(super.lastWhere)(3, orElse: 77);
 
-  // Warning: overrides should not change default parameter values.
-  bar([var optional]) => -1; //       //# 01: static type warning
+  bar([var optional]) => -1; //       //# 01: ok
   bar2({namedOptional}) => -1; //   //# 01: continued
   bar3(x, [var optional]) => -1; //   //# 01: continued
   bar4(x, {namedOptional}) => -1; //# 01: continued
diff --git a/tests/language_2/call/method_implicit_invoke_local_test.dart b/tests/language_2/call/method_implicit_invoke_local_test.dart
index 1e58c47..0e15829 100644
--- a/tests/language_2/call/method_implicit_invoke_local_test.dart
+++ b/tests/language_2/call/method_implicit_invoke_local_test.dart
@@ -32,7 +32,8 @@
   // [analyzer] COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS
   // [cfe] Too few positional arguments: 1 required, 0 given.
   c2(3, 4);
-  //^^^^^^
+  //    ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 }
diff --git a/tests/language_2/compile_time_constant/arguments_test.dart b/tests/language_2/compile_time_constant/arguments_test.dart
index 70d7fd3b..ca56413 100644
--- a/tests/language_2/compile_time_constant/arguments_test.dart
+++ b/tests/language_2/compile_time_constant/arguments_test.dart
@@ -15,8 +15,9 @@
   // [analyzer] COMPILE_TIME_ERROR.NOT_ENOUGH_POSITIONAL_ARGUMENTS
   // [cfe] Too few positional arguments: 1 required, 0 given.
   const A(1, 2);
-  //     ^^^^^^
+  //         ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //     ^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
   const A.named();
   const A.named(b: 1);
@@ -34,7 +35,8 @@
   const A.optional();
   const A.optional(42);
   const A.optional(42, 54);
-  //              ^^^^^^^^
+  //                   ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //              ^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 }
diff --git a/tests/language_2/const/constant_dag_test.dart b/tests/language_2/const/constant_dag_test.dart
new file mode 100644
index 0000000..3be6889
--- /dev/null
+++ b/tests/language_2/const/constant_dag_test.dart
@@ -0,0 +1,67 @@
+// 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";
+
+// Test the efficient processing of constants that are DAGs.
+//
+// This test requires processing a constant that is a DAG of N nodes (N=40). If
+// the DAG is traversed as a tree, it will require exponential node visits and
+// take time O(2^N) i.e. 2^40, and the test will time out.
+
+main() {
+  Expect.equals(40, n40.lengthA);
+  Expect.equals(40, n40.lengthB);
+}
+
+class Node {
+  final Node a;
+  final Node b;
+  const Node(this.a, this.b);
+
+  int get lengthA => a == null ? 0 : 1 + a.lengthA;
+  int get lengthB => b == null ? 0 : 1 + b.lengthB;
+}
+
+const n0 = Node(null, null);
+const n1 = Node(n0, n0);
+const n2 = Node(n1, n1);
+const n3 = Node(n2, n2);
+const n4 = Node(n3, n3);
+const n5 = Node(n4, n4);
+const n6 = Node(n5, n5);
+const n7 = Node(n6, n6);
+const n8 = Node(n7, n7);
+const n9 = Node(n8, n8);
+const n10 = Node(n9, n9);
+const n11 = Node(n10, n10);
+const n12 = Node(n11, n11);
+const n13 = Node(n12, n12);
+const n14 = Node(n13, n13);
+const n15 = Node(n14, n14);
+const n16 = Node(n15, n15);
+const n17 = Node(n16, n16);
+const n18 = Node(n17, n17);
+const n19 = Node(n18, n18);
+const n20 = Node(n19, n19);
+const n21 = Node(n20, n20);
+const n22 = Node(n21, n21);
+const n23 = Node(n22, n22);
+const n24 = Node(n23, n23);
+const n25 = Node(n24, n24);
+const n26 = Node(n25, n25);
+const n27 = Node(n26, n26);
+const n28 = Node(n27, n27);
+const n29 = Node(n28, n28);
+const n30 = Node(n29, n29);
+const n31 = Node(n30, n30);
+const n32 = Node(n31, n31);
+const n33 = Node(n32, n32);
+const n34 = Node(n33, n33);
+const n35 = Node(n34, n34);
+const n36 = Node(n35, n35);
+const n37 = Node(n36, n36);
+const n38 = Node(n37, n37);
+const n39 = Node(n38, n38);
+const n40 = Node(n39, n39);
diff --git a/tests/language_2/constants_2018/constant_type_literal_test.dart b/tests/language_2/constants_2018/constant_type_literal_test.dart
index b886d77..99a26db 100644
--- a/tests/language_2/constants_2018/constant_type_literal_test.dart
+++ b/tests/language_2/constants_2018/constant_type_literal_test.dart
@@ -8,7 +8,7 @@
 import "dart:core" as core;
 // No reloading support for deferred loading.
 // See https://github.com/dart-lang/sdk/issues/33118.
-import "dart:core" deferred as dcore; //# 01: compile-time error
+import "dart:core" deferred as dcore show int; //# 01: compile-time error
 
 // Declares F function type alias, M mixin and C class.
 import "constant_type_literal_types.dart";
diff --git a/tests/language_2/constructor/constructor13_test.dart b/tests/language_2/constructor/constructor13_test.dart
index f6790ec..24b8841 100644
--- a/tests/language_2/constructor/constructor13_test.dart
+++ b/tests/language_2/constructor/constructor13_test.dart
@@ -16,7 +16,8 @@
   // [cfe] Too few positional arguments: 1 required, 0 given.
   new Klass(1);
   new Klass(1, 2);
-  //       ^^^^^^
+  //           ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //       ^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 }
diff --git a/tests/language_2/constructor/no_such_constructor_test.dart b/tests/language_2/constructor/no_such_constructor_test.dart
index b106273..28c05a6 100644
--- a/tests/language_2/constructor/no_such_constructor_test.dart
+++ b/tests/language_2/constructor/no_such_constructor_test.dart
@@ -8,7 +8,8 @@
 
 main() {
   new A(42);
-  //   ^^^^
+  //    ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //   ^^^^
   // [cfe] Too many positional arguments: 0 allowed, but 1 found.
 }
diff --git a/tests/language_2/constructor/redirect2_test.dart b/tests/language_2/constructor/redirect2_test.dart
index 30d7ab6..85fc234 100644
--- a/tests/language_2/constructor/redirect2_test.dart
+++ b/tests/language_2/constructor/redirect2_test.dart
@@ -32,8 +32,9 @@
   //                          ^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.SUPER_IN_REDIRECTING_CONSTRUCTOR
   // [cfe] A redirecting constructor can't have other initializers.
-  //                               ^^^
+  //                                ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //                               ^^^
   // [cfe] Too many positional arguments: 0 allowed, but 1 found.
 }
 
diff --git a/tests/language_2/deferred/import_core_test.dart b/tests/language_2/deferred/import_core_test.dart
index f3d6644..3c72766 100644
--- a/tests/language_2/deferred/import_core_test.dart
+++ b/tests/language_2/deferred/import_core_test.dart
@@ -5,7 +5,7 @@
 // Nothing in the language spec explicitly prohibits a deferred import of
 // 'dart:core'.  Make sure it doesn't lead to any strange behavior.
 
-import "dart:core" deferred as core;
+import "dart:core" deferred as core show Object;
 
 main() {
   core.loadLibrary().then((_) => null);
diff --git a/tests/language_2/deferred/load_library_wrong_args_test.dart b/tests/language_2/deferred/load_library_wrong_args_test.dart
index c991e2e6..3903e19 100644
--- a/tests/language_2/deferred/load_library_wrong_args_test.dart
+++ b/tests/language_2/deferred/load_library_wrong_args_test.dart
@@ -5,6 +5,6 @@
   lib.loadLibrary(10);
 //^
 // [cfe] 'loadLibrary' takes no arguments.
-//               ^^^^
+//                ^^
 // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
 }
diff --git a/tests/language_2/extension_methods/static_extension_operator_override_error_test.dart b/tests/language_2/extension_methods/static_extension_operator_override_error_test.dart
new file mode 100644
index 0000000..acd3ab5
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_operator_override_error_test.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.
+
+/// Regression test for https://github.com/dart-lang/sdk/issues/43114.
+
+class A {}
+
+extension E on A {
+  String operator +(int other) => '';
+}
+
+f(A a, int b) {
+  int i = E(a) + b;
+  //      ^^^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
+  //           ^
+  // [cfe] A value of type 'String' can't be assigned to a variable of type 'int'.
+}
+
+main() {
+  f(A(), 0);
+}
diff --git a/tests/language_2/extension_methods/static_extension_this_not_promoted_error_test.dart b/tests/language_2/extension_methods/static_extension_this_not_promoted_error_test.dart
new file mode 100644
index 0000000..ed3e301
--- /dev/null
+++ b/tests/language_2/extension_methods/static_extension_this_not_promoted_error_test.dart
@@ -0,0 +1,36 @@
+// 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.
+
+// This test verifies that attempts to promote the type of `this` inside an
+// extension method have no effect.
+
+void f(dynamic d) {}
+
+class C {
+  int cProp;
+}
+
+class D extends C {
+  int dProp;
+}
+
+extension on C {
+  void testC() {
+    if (this is D) {
+      f(this.dProp);
+      //     ^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
+      // [cfe] The getter 'dProp' isn't defined for the class 'C'.
+      f(dProp);
+      //^^^^^
+      // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
+      // [cfe] The getter 'dProp' isn't defined for the class 'C'.
+    }
+  }
+}
+
+main() {
+  C().testC();
+  D().testC();
+}
diff --git a/tests/language_2/factory/redirection3_cyclic_test.dart b/tests/language_2/factory/redirection3_cyclic_test.dart
index 13dc39b..ab115cc 100644
--- a/tests/language_2/factory/redirection3_cyclic_test.dart
+++ b/tests/language_2/factory/redirection3_cyclic_test.dart
@@ -17,10 +17,10 @@
 class C implements B {
   factory C.bar() = C.foo;
   //                ^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_FACTORY_REDIRECT
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
   factory C.foo() = C.bar();
   //                ^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_FACTORY_REDIRECT
+  // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
   //                  ^^^
   // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
   // [cfe] Expected ';' after this.
diff --git a/tests/language_2/identifier/built_in_illegal_test.dart b/tests/language_2/identifier/built_in_illegal_test.dart
index 86d9e5c..983a854 100644
--- a/tests/language_2/identifier/built_in_illegal_test.dart
+++ b/tests/language_2/identifier/built_in_illegal_test.dart
@@ -131,7 +131,6 @@
 // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
 // [cfe] Expected an identifier, but got 'part'.
 // [error line 123, column 12, length 0]
-// [analyzer] COMPILE_TIME_ERROR.PART_OF_NON_PART
 // [cfe] Expected ';' after this.
 //         ^
 // [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
diff --git a/tests/language_2/inference/inconsistent_inheritance_test.dart b/tests/language_2/inference/inconsistent_inheritance_test.dart
index 45f7db9..1d49b86 100644
--- a/tests/language_2/inference/inconsistent_inheritance_test.dart
+++ b/tests/language_2/inference/inconsistent_inheritance_test.dart
@@ -11,9 +11,7 @@
 }
 
 class C extends A implements B {
-  // No type can be inferred for x since the two inherited interfaces specify
-  // different types.
-  void f(/*@compile-error=unspecified*/ x) {}
+  void f(x) {}
 }
 
 void main() {}
diff --git a/tests/language_2/instance/call_wrong_argument_count_test.dart b/tests/language_2/instance/call_wrong_argument_count_test.dart
index 8f0c710..6256051 100644
--- a/tests/language_2/instance/call_wrong_argument_count_test.dart
+++ b/tests/language_2/instance/call_wrong_argument_count_test.dart
@@ -14,7 +14,8 @@
   var niederhorn = Niederhorn();
   niederhorn.goodCall(1, 2, 3);
   niederhorn.goodCall(1, 2, 3, 4);
-  //                 ^^^^^^^^^^^^
+  //                           ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //                 ^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 3 allowed, but 4 found.
 }
diff --git a/tests/language_2/mixin/illegal_constructor_test.dart b/tests/language_2/mixin/illegal_constructor_test.dart
index b70f764..ea13e2a 100644
--- a/tests/language_2/mixin/illegal_constructor_test.dart
+++ b/tests/language_2/mixin/illegal_constructor_test.dart
@@ -97,16 +97,18 @@
   new D6();
 
   new C0(1,2,3);
-  //    ^^^^^^^
+  //     ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //    ^^^^^^^
   // [cfe] Too many positional arguments: 0 allowed, but 3 found.
   new C0.named();
   //     ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.NEW_WITH_UNDEFINED_CONSTRUCTOR
   // [cfe] Method not found: 'C0.named'.
   new D0(1,2,3);
-  //    ^^^^^^^
+  //     ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //    ^^^^^^^
   // [cfe] Too many positional arguments: 0 allowed, but 3 found.
   new D0.named();
   //     ^^^^^
diff --git a/tests/language_2/mixin/interface_check_test.dart b/tests/language_2/mixin/interface_check_test.dart
index db0aaf3..9884d1b 100644
--- a/tests/language_2/mixin/interface_check_test.dart
+++ b/tests/language_2/mixin/interface_check_test.dart
@@ -19,7 +19,7 @@
 
 class C extends A //
 //    ^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
+// [analyzer] COMPILE_TIME_ERROR.INVALID_IMPLEMENTATION_OVERRIDE
 // [cfe] The implementation of 'thing' in the non-abstract class 'C' does not conform to its interface.
     with
         B
diff --git a/tests/language_2/mixin/invalid_override_in_mixin_test.dart b/tests/language_2/mixin/invalid_override_in_mixin_test.dart
index bd79f66..de7b18c 100644
--- a/tests/language_2/mixin/invalid_override_in_mixin_test.dart
+++ b/tests/language_2/mixin/invalid_override_in_mixin_test.dart
@@ -14,8 +14,6 @@
 class C extends Object with A {
 //    ^
 // [cfe] Applying the mixin 'A' to 'Object' introduces an erroneous override of 'noSuchMethod'.
-//    ^
-// [cfe] Class 'Object with A' inherits multiple members named 'noSuchMethod' with incompatible signatures.
 //                          ^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
   test() {
diff --git a/tests/language_2/mixin/method_override_test.dart b/tests/language_2/mixin/method_override_test.dart
index 137156e..54844a9 100644
--- a/tests/language_2/mixin/method_override_test.dart
+++ b/tests/language_2/mixin/method_override_test.dart
@@ -21,34 +21,26 @@
 
 // Wrong return type.
 abstract class C1 = CII with CIS;
-//             ^^
-// [cfe] Class 'C1' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C1' introduces an erroneous override of 'id'.
 //                           ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C2 extends CII with CIS {}
-//             ^^
-// [cfe] Applying the mixin 'CIS' to 'CII' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'CII with CIS' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'CIS' to 'CII' introduces an erroneous override of 'id'.
 //                                 ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
 
 // Wrong argument type.
 abstract class C3 = CII with CSI;
-//             ^^
-// [cfe] Class 'C3' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C3' introduces an erroneous override of 'id'.
 //                           ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C4 extends CII with CSI {}
-//             ^^
-// [cfe] Applying the mixin 'CSI' to 'CII' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'CII with CSI' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'CSI' to 'CII' introduces an erroneous override of 'id'.
 //                                 ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
@@ -56,17 +48,13 @@
 abstract class C5 = CII with CTT<int>;
 abstract class C6 extends CII with CTT<int> {}
 abstract class C7  = CII with CTT<String>;
-//             ^^
-// [cfe] Class 'C7' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'C7' introduces an erroneous override of 'id'.
 //                            ^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class C8 extends CII with CTT<String> {}
-//             ^^
-// [cfe] Applying the mixin 'CTT' to 'CII' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'CII with CTT<String>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'CTT' to 'CII' introduces an erroneous override of 'id'.
 //                                 ^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
@@ -92,34 +80,26 @@
 abstract class N2 extends NIIx with NIIxy {}
 // It's NOT OK to rename named parameters.
 abstract class N3 = NIIx with NIIy;
-//             ^^
-// [cfe] Class 'N3' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N3' introduces an erroneous override of 'id'.
 //                            ^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N4 extends NIIx with NIIy {}
-//             ^^
-// [cfe] Applying the mixin 'NIIy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NIIy' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NIIy' to 'NIIx' introduces an erroneous override of 'id'.
 //                                  ^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
 
 // It's NOT OK to drop named parameters.
 abstract class N5 = NIIx with NII;
-//             ^^
-// [cfe] Class 'N5' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N5' introduces an erroneous override of 'id'.
 //                            ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N6 extends NIIx with NII {}
-//             ^^
-// [cfe] Applying the mixin 'NII' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NII' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NII' to 'NIIx' introduces an erroneous override of 'id'.
 //                                  ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
@@ -139,45 +119,33 @@
 abstract class N7 = NIIx with NBABxy<int, int>;
 abstract class N8 extends NIIx with NBABxy<int, int> {}
 abstract class N9 = NIIx with NBABxy<String, int>;
-//             ^^
-// [cfe] Class 'N9' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N9' introduces an erroneous override of 'id'.
 //                            ^^^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N10 extends NIIx with NBABxy<String, int> {}
-//             ^^^
-// [cfe] Applying the mixin 'NBABxy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NBABxy<String, int>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NBABxy' to 'NIIx' introduces an erroneous override of 'id'.
 //                                   ^^^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N11 = NIIx with NTTy<int>;
-//             ^^^
-// [cfe] Class 'N11' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N11' introduces an erroneous override of 'id'.
 //                             ^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N12 extends NIIx with NTTy<int> {}
-//             ^^^
-// [cfe] Applying the mixin 'NTTy' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NTTy<int>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NTTy' to 'NIIx' introduces an erroneous override of 'id'.
 //                                   ^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N13 = NIIx with NTTx<int>;
-//             ^^^
-// [cfe] Class 'N13' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'N13' introduces an erroneous override of 'id'.
 //                             ^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class N14 extends NIIx with NTTx<int> {}
-//             ^^^
-// [cfe] Applying the mixin 'NTTx' to 'NIIx' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'NIIx with NTTx<int>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'NTTx' to 'NIIx' introduces an erroneous override of 'id'.
 //                                   ^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 
@@ -232,17 +200,13 @@
 abstract class O7 = OII with OBAB<int, int>;
 abstract class O8 extends OII with OBAB<int, int> {}
 abstract class O9 = OII with OBAB<String, int>;
-//             ^^
-// [cfe] Class 'O9' inherits multiple members named 'id' with incompatible signatures.
 //             ^
 // [cfe] The mixin application class 'O9' introduces an erroneous override of 'id'.
 //                           ^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class O10 extends OII with OBAB<String, int> {}
-//             ^^^
-// [cfe] Applying the mixin 'OBAB' to 'OII' introduces an erroneous override of 'id'.
 //             ^
-// [cfe] Class 'OII with OBAB<String, int>' inherits multiple members named 'id' with incompatible signatures.
+// [cfe] Applying the mixin 'OBAB' to 'OII' introduces an erroneous override of 'id'.
 //                                  ^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 abstract class O11 = OII with OTTy<int>;
@@ -280,22 +244,16 @@
 }
 class G1 = GTTnum with MTTnum;
 class G2 = GTTnum with MTTint;
-//    ^^
-// [cfe] Class 'G2' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G2' introduces an erroneous override of 'id'.
 //                     ^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 class G3 = GTTnum with MTT;
-//    ^^
-// [cfe] Class 'G3' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G3' introduces an erroneous override of 'id'.
 //                     ^^^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
 class G4 = GTTnum with MTTnumR;
-//    ^^
-// [cfe] Class 'G4' inherits multiple members named 'id' with incompatible signatures.
 //    ^
 // [cfe] The mixin application class 'G4' introduces an erroneous override of 'id'.
 //                     ^^^^^^^
diff --git a/tests/language_2/mixin/super_with_initializer_test.dart b/tests/language_2/mixin/super_with_initializer_test.dart
new file mode 100644
index 0000000..cbbbbee
--- /dev/null
+++ b/tests/language_2/mixin/super_with_initializer_test.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.
+
+// @dart = 2.9
+
+/// Regression test for mixin overrides (dartbug.com/44636).
+///
+/// Prior to the fix, B's initializer was accidentally being applied on the
+/// overriden definition in C, and as a result, the program would stack
+/// overflow.
+import 'package:expect/expect.dart';
+
+class A = B with C;
+
+mixin M {}
+
+abstract class B with M {
+  Object _test = "a";
+}
+
+mixin C on B, M {
+  @override
+  Object get _test => super._test;
+
+  @override
+  set _test(Object value) {
+    super._test = value;
+  }
+}
+
+main() => Expect.equals("a", A()._test);
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_class_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_class_test.dart
index 5ed9e00..e3a6a6e 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_class_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_class_test.dart
@@ -36,7 +36,7 @@
 
   C(): v7 = T<Null>();
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -45,6 +45,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1<X> extends T<X> {}
 abstract class D3<X, Y> implements T<T> {}
 
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_dynamic_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_dynamic_test.dart
index c1208a5..46a21d8 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_dynamic_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_dynamic_test.dart
@@ -29,7 +29,7 @@
   final T<Null> v7;
 
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -38,6 +38,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_function_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_function_test.dart
index 33bac17..b0d4105 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_function_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_function_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = print;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1<X> extends T<X> {}
 abstract class D2 extends C with T<int> {}
 abstract class D3<X, Y> implements T<T> {}
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_futureor_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_futureor_test.dart
index a81fad2..2d9d0fe 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_futureor_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_futureor_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = null;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_null_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_null_test.dart
index 6101801..0934a57 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_null_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_null_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = null;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_object_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_object_test.dart
index f6f9b24..602671e 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_object_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_object_test.dart
@@ -30,7 +30,7 @@
 
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1<X> extends T<X> {}
 
 abstract class D3<X, Y> extends C implements T<T> {}
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_test.dart
index 1c2604c..acd2efb 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_type_variable_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = null;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<D> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<D> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<D> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D {}
 mixin M {}
 
diff --git a/tests/language_2/nonfunction_type_aliases/generic_usage_void_test.dart b/tests/language_2/nonfunction_type_aliases/generic_usage_void_test.dart
index 6456366..18106b4 100644
--- a/tests/language_2/nonfunction_type_aliases/generic_usage_void_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/generic_usage_void_test.dart
@@ -30,7 +30,7 @@
 
   C(): v7 = null;
   C.name1(this.v5, this.v7);
-  factory C.name2(T<C> arg1, T<Null> arg2) = C.name1;
+  factory C.name2(T<C> arg1, T<Null> arg2) = C1.name1;
 
   T<double> operator +(T<double> other);
   T<FutureOr<FutureOr<void>>> get g;
@@ -39,6 +39,11 @@
   void m2({T arg1, Map<T, T> arg2(T Function(T) arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T<C> arg1, T<Null> arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language_2/nonfunction_type_aliases/usage_class_test.dart b/tests/language_2/nonfunction_type_aliases/usage_class_test.dart
index c3338d6..ae563d9 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_class_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_class_test.dart
@@ -34,7 +34,7 @@
 
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -43,6 +43,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1 extends T {}
 abstract class D3 implements T {}
 
diff --git a/tests/language_2/nonfunction_type_aliases/usage_dynamic_test.dart b/tests/language_2/nonfunction_type_aliases/usage_dynamic_test.dart
index 3ff37e1..dc5c93f 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_dynamic_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_dynamic_test.dart
@@ -27,7 +27,7 @@
   final T v12;
 
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -36,6 +36,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 X foo<X>(X x) => x;
 
 T Function(T) id = (x) => x;
diff --git a/tests/language_2/nonfunction_type_aliases/usage_function_test.dart b/tests/language_2/nonfunction_type_aliases/usage_function_test.dart
index 4e22762..e9af4f6 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_function_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_function_test.dart
@@ -28,7 +28,7 @@
 
   C(): v12 = (() {});
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -37,13 +37,15 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
-// Awaiting updates in front end to handle crash caused by null from
-// `ClassHierarchyBuilder.getKernelTypeAsInstanceOf`. So for now the
-// following are multi-test cases, so that the rest can be tested.
-class D1 extends T {} //# 01: ok
-abstract class D2 extends C with T {} //# 02: ok
-abstract class D3 implements T {} //# 03: ok
-abstract class D4 = C with T; //# 04: ok
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
+class D1 extends T {}
+abstract class D2 extends C with T {}
+abstract class D3 implements T {}
+abstract class D4 = C with T;
 
 extension E on T {
   T foo(T t) => t;
diff --git a/tests/language_2/nonfunction_type_aliases/usage_futureor_test.dart b/tests/language_2/nonfunction_type_aliases/usage_futureor_test.dart
index cab5a49..e0f6d5a 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_futureor_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_futureor_test.dart
@@ -29,7 +29,7 @@
   final T v12;
 
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -38,6 +38,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T {
   T foo(T t) => t;
 }
diff --git a/tests/language_2/nonfunction_type_aliases/usage_null_test.dart b/tests/language_2/nonfunction_type_aliases/usage_null_test.dart
index e2a00cd..4eb4583 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_null_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_null_test.dart
@@ -28,7 +28,7 @@
 
   C(): v12 = null;
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -37,6 +37,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T {
   T foo(T t) => t;
 }
diff --git a/tests/language_2/nonfunction_type_aliases/usage_object_error_test.dart b/tests/language_2/nonfunction_type_aliases/usage_object_error_test.dart
index f43ea38..e07c2090 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_object_error_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_object_error_test.dart
@@ -15,7 +15,12 @@
   final T v12;
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
+}
+
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
 }
 
 abstract class D2 extends C with T {}
diff --git a/tests/language_2/nonfunction_type_aliases/usage_object_test.dart b/tests/language_2/nonfunction_type_aliases/usage_object_test.dart
index a93e8b7..6896551 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_object_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_object_test.dart
@@ -28,7 +28,7 @@
 
   C(): v12 = T();
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -37,6 +37,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1 extends T {}
 
 extension E on T {
diff --git a/tests/language_2/nonfunction_type_aliases/usage_type_variable_test.dart b/tests/language_2/nonfunction_type_aliases/usage_type_variable_test.dart
index ffd1e16..e580abe 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_type_variable_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_type_variable_test.dart
@@ -34,7 +34,7 @@
 
   C(): v12 = null;
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -43,6 +43,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 class D1 extends T {}
 abstract class D3 implements T {}
 
diff --git a/tests/language_2/nonfunction_type_aliases/usage_void_test.dart b/tests/language_2/nonfunction_type_aliases/usage_void_test.dart
index cb752e5..9857812 100644
--- a/tests/language_2/nonfunction_type_aliases/usage_void_test.dart
+++ b/tests/language_2/nonfunction_type_aliases/usage_void_test.dart
@@ -27,7 +27,7 @@
   final T v12;
 
   C.name1(this.v10, this.v12);
-  factory C.name2(T arg1, T arg2) = C.name1;
+  factory C.name2(T arg1, T arg2) = C1.name1;
 
   T operator +(T other);
   T get g;
@@ -36,6 +36,11 @@
   void m2({T arg1, T arg2(T arg21, T arg22)});
 }
 
+class C1 implements C {
+  C1.name1(T arg1, T arg2);
+  noSuchMethod(Invocation invocation) => throw 0;
+}
+
 extension E on T {
   T foo(T t) => t;
 }
diff --git a/tests/language_2/null_aware/index_this_null_aware_equals_test.dart b/tests/language_2/null_aware/index_this_null_aware_equals_test.dart
new file mode 100644
index 0000000..fc2ccc9
--- /dev/null
+++ b/tests/language_2/null_aware/index_this_null_aware_equals_test.dart
@@ -0,0 +1,15 @@
+class C {
+  static final Expando<int> _debugIds = new Expando<int>();
+
+  static int _nextDebugId = 0;
+
+  @override
+  String toString() {
+    int id = _debugIds[this] ??= _nextDebugId++;
+    return 'C$id';
+  }
+}
+
+main() {
+  print(C());
+}
diff --git a/tests/language_2/operator/invalid_operators_test.dart b/tests/language_2/operator/invalid_operators_test.dart
index f8acc82..32b6399 100644
--- a/tests/language_2/operator/invalid_operators_test.dart
+++ b/tests/language_2/operator/invalid_operators_test.dart
@@ -106,7 +106,7 @@
   // [cfe] Operator '>=' should have exactly one parameter.
   operator -(a, b) => true;
   //       ^
-  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS
+  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
   // [cfe] Operator '-' should have zero or one parameter.
   operator +(a, b) => true;
   //       ^
@@ -366,7 +366,7 @@
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
   operator -(a, [b]) => true;
   //       ^
-  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS
+  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
   // [cfe] Operator '-' should have zero or one parameter.
   //             ^
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
@@ -483,7 +483,7 @@
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
   operator -(a, {b}) => true;
   //       ^
-  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS
+  // [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
   // [cfe] Operator '-' should have zero or one parameter.
   //             ^
   // [analyzer] COMPILE_TIME_ERROR.OPTIONAL_PARAMETER_IN_OPERATOR
@@ -571,9 +571,9 @@
   operator ==<T>(a) => true;
   //       ^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
-  // [cfe] Declared type variables of 'Operators7.==' doesn't match those on overridden method 'Object.=='.
+  // [cfe] Can't infer types for '==' as the overridden members don't have a combined signature.
   //       ^
-  // [cfe] The return type of the method 'Operators7.==' is 'dynamic', which does not match the return type, 'bool', of the overridden method, 'Object.=='.
+  // [cfe] Declared type variables of 'Operators7.==' doesn't match those on overridden method 'Object.=='.
   //         ^^^
   // [analyzer] SYNTACTIC_ERROR.TYPE_PARAMETERS_ON_OPERATOR
   //          ^
@@ -674,7 +674,7 @@
   /*space*/ int operator []=(a, b) {}
   //        ^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_OPERATOR
-  // [cfe] unspecified
+  // [cfe] The return type of the operator []= must be 'void'.
 }
 
 main() {}
diff --git a/tests/language_2/parameter/bad_named_parameters_test.dart b/tests/language_2/parameter/bad_named_parameters_test.dart
index 173e340..aa36c13 100644
--- a/tests/language_2/parameter/bad_named_parameters_test.dart
+++ b/tests/language_2/parameter/bad_named_parameters_test.dart
@@ -20,14 +20,16 @@
 
   // Parameter b passed twice.
   np.f42(10, 25, b: 25);
-  //    ^^^^^^^^^^^^^^^
+  //         ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+  //    ^^^^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 
   // Parameter x does not exist.
   np.f42(10, 25, x: 99);
-  //    ^^^^^^^^^^^^^^^
+  //         ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+  //    ^^^^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
   //             ^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_NAMED_PARAMETER
@@ -40,8 +42,9 @@
 
   // Too many parameters.
   np.f42(10, 20, 30, 40);
-  //    ^^^^^^^^^^^^^^^^
+  //         ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+  //    ^^^^^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 4 found.
 
   // Too few parameters.
diff --git a/tests/language_2/parameter/named_aggregated_test.dart b/tests/language_2/parameter/named_aggregated_test.dart
index 1b506df..9c2cd70 100644
--- a/tests/language_2/parameter/named_aggregated_test.dart
+++ b/tests/language_2/parameter/named_aggregated_test.dart
@@ -37,8 +37,9 @@
 main() {
   // Expect compile-time error due to missing comma in function definition.
   NamedParametersAggregatedTests.f_missing_comma(10, 25);
-  //                                            ^^^^^^^^
+  //                                                 ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //                                            ^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 
   // Expect compile-time error due to duplicate named argument.
diff --git a/tests/language_2/parameter/optional_named_test.dart b/tests/language_2/parameter/optional_named_test.dart
index d08f3d9..ba2af7d 100644
--- a/tests/language_2/parameter/optional_named_test.dart
+++ b/tests/language_2/parameter/optional_named_test.dart
@@ -63,36 +63,42 @@
     Expect.equals(20, F10());
     Expect.equals(20, np.f21());
     Expect.equals(20, F10(20));
-    //                   ^^^^
+    //                    ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                   ^^^^
     // [cfe] Too many positional arguments: 0 allowed, but 1 found.
     Expect.equals(20, np.f21(20));
-    //                      ^^^^
+    //                       ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                      ^^^^
     // [cfe] Too many positional arguments: 0 allowed, but 1 found.
     Expect.equals(20, F10(b: 20));
     Expect.equals(20, np.f21(b: 20));
     Expect.equals(1020, F21(10));
     Expect.equals(1020, np.f32(10));
     Expect.equals(1025, F21(10, 25));
-    //                     ^^^^^^^^
+    //                          ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                     ^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(1025, np.f32(10, 25));
-    //                        ^^^^^^^^
+    //                             ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                        ^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(1025, F21(10, b: 25));
     Expect.equals(1025, np.f32(10, b: 25));
     Expect.equals(102030, F31(10));
     Expect.equals(102030, np.f42(10));
     Expect.equals(102530, F31(10, 25));
-    //                       ^^^^^^^^
+    //                            ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                       ^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(102530, np.f42(10, 25));
-    //                          ^^^^^^^^
+    //                               ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                          ^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(102530, F31(10, b: 25));
     Expect.equals(102530, np.f42(10, b: 25));
@@ -101,12 +107,14 @@
     Expect.equals(102535, F31(10, b: 25, c: 35));
     Expect.equals(102535, np.f42(10, b: 25, c: 35));
     Expect.equals(102535, F31(10, 25, c:35));
-    //                       ^^^^^^^^^^^^^^
+    //                            ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                       ^^^^^^^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(102535, np.f42(10, 25, c:35));
-    //                          ^^^^^^^^^^^^^^
+    //                               ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                          ^^^^^^^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(102535, F31(10, c: 35, b: 25));
     Expect.equals(102535, np.f42(10, c: 35, b: 25));
@@ -116,8 +124,9 @@
     Expect.equals(10203540, np.f52(10, c: 35));
     Expect.equals(10250045, F41(10, d: 45, b: 25));
     Expect.equals(10250045, F41(10, 25, d:45));
-    //                         ^^^^^^^^^^^^^^
+    //                              ^^
     // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED
+    //                         ^^^^^^^^^^^^^^
     // [cfe] Too many positional arguments: 1 allowed, but 2 found.
     Expect.equals(10250045, np.f52(10, d: 45, b: 25));
     Expect.equals(10253545, F41(10, d: 45, c: 35, b: 25));
diff --git a/tests/language_2/redirecting/factory_default_values_test.dart b/tests/language_2/redirecting/factory_default_values_test.dart
index 84a7d17..23a0e3c 100644
--- a/tests/language_2/redirecting/factory_default_values_test.dart
+++ b/tests/language_2/redirecting/factory_default_values_test.dart
@@ -33,7 +33,8 @@
   Expect.equals(x.b, 0);
 
   var y = new A.f(42, 43);
-  //             ^^^^^^^^
+  //                  ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //             ^^^^^^^^
   // [cfe] Too many positional arguments: 1 allowed, but 2 found.
 }
diff --git a/tests/language_2/regress/regress23038_test.dart b/tests/language_2/regress/regress23038_test.dart
index bf5cbd0..0967098 100644
--- a/tests/language_2/regress/regress23038_test.dart
+++ b/tests/language_2/regress/regress23038_test.dart
@@ -10,7 +10,7 @@
 // [cfe] Cyclic definition of factory 'C'.
     = C<C<T>>
     //^^^^^^^
-    // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_FACTORY_REDIRECT
+    // [analyzer] COMPILE_TIME_ERROR.RECURSIVE_CONSTRUCTOR_REDIRECT
     // [cfe] The constructor function type 'C<C<T>> Function()' isn't a subtype of 'C<T> Function()'.
   ;
 }
diff --git a/tests/language_2/regress/regress31596_covariant_declaration_test.dart b/tests/language_2/regress/regress31596_covariant_declaration_test.dart
index 20defe2..c9c9053 100644
--- a/tests/language_2/regress/regress31596_covariant_declaration_test.dart
+++ b/tests/language_2/regress/regress31596_covariant_declaration_test.dart
@@ -18,7 +18,7 @@
 
 class D extends C implements I {}
 //    ^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
+// [analyzer] COMPILE_TIME_ERROR.INVALID_IMPLEMENTATION_OVERRIDE
 // [cfe] unspecified
 
 main() {}
diff --git a/tests/language_2/regress/regress33235_11_test.dart b/tests/language_2/regress/regress33235_11_test.dart
index 74710f4..74ccf45 100644
--- a/tests/language_2/regress/regress33235_11_test.dart
+++ b/tests/language_2/regress/regress33235_11_test.dart
@@ -14,6 +14,8 @@
   static int n() => 42;
   //         ^
   // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+  // [cfe] 'n' is already declared in this scope.
+  //         ^
   // [cfe] Conflicts with setter 'n'.
 }
 
diff --git a/tests/language_2/regress/regress35258_test.dart b/tests/language_2/regress/regress35258_test.dart
index d36f45f..a5707b0 100644
--- a/tests/language_2/regress/regress35258_test.dart
+++ b/tests/language_2/regress/regress35258_test.dart
@@ -6,7 +6,7 @@
   new C(42);
   //  ^
   // [cfe] Can't use 'C' because it is declared more than once.
-  //   ^^^^
+  //    ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
 }
 
diff --git a/tests/language_2/static/call_wrong_argument_count_test.dart b/tests/language_2/static/call_wrong_argument_count_test.dart
index 575c486..ca34e7cd 100644
--- a/tests/language_2/static/call_wrong_argument_count_test.dart
+++ b/tests/language_2/static/call_wrong_argument_count_test.dart
@@ -13,7 +13,8 @@
   Niesen.goodCall(1, 2, 3);
 
   Niesen.goodCall(1, 2, 3, 4);
-  //             ^^^^^^^^^^^^
+  //                       ^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+  //             ^^^^^^^^^^^^
   // [cfe] Too many positional arguments: 3 allowed, but 4 found.
 }
diff --git a/tests/lib/async/catch_errors.dart b/tests/lib/async/catch_errors.dart
index 02c403c..f2a5bc4 100644
--- a/tests/lib/async/catch_errors.dart
+++ b/tests/lib/async/catch_errors.dart
@@ -1,3 +1,7 @@
+// 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 catch_errors;
 
 import 'dart:async';
diff --git a/tests/lib/async/future_future_test.dart b/tests/lib/async/future_future_test.dart
new file mode 100644
index 0000000..ab5e50b
--- /dev/null
+++ b/tests/lib/async/future_future_test.dart
@@ -0,0 +1,186 @@
+// 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.
+
+// Checks that `Future<Future<int>>` is a valid type
+// and that futures can contain and complete other futures.
+
+// This essentially checks that `FutureOr<X>` is treated correctly depending
+// on what `X` is.
+
+import 'dart:async';
+import 'package:async_helper/async_helper.dart';
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+
+  // Helper values and factories.
+  Future<Null> nullFuture = Future<Null>.value(null);
+
+  var stack = StackTrace.current;
+  var error = ArgumentError("yep");
+  Future<Null> errorFuture = Future<Null>.error(error, stack)
+    ..catchError((_) => null);
+  Future<int> fi(int n) => Future<int>.value(n);
+  Future<Future<int>> ffi(n) => Future<Future<int>>.value(fi(n));
+
+  // Tests that `Future<Future<int>>` can be created.
+  asyncTest(() {
+    return expectFutureFutureInt(ffi(0), 0);
+  });
+
+  // Check `Future.then`'s callback.
+
+  asyncTest(() {
+    Future<int> future = nullFuture.then<int>((_) => fi(1));
+    return expectFutureInt(future, 1);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> future = nullFuture.then<Future<int>>((_) => fi(2));
+    return expectFutureFutureInt(future, 2);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> future = nullFuture.then<Future<int>>((_) => ffi(3));
+    return expectFutureFutureInt(future, 3);
+  });
+
+  // Check `Future.then`'s `onError`.
+
+  asyncTest(() {
+    Future<int> future =
+        errorFuture.then<int>((_) => -1, onError: (_) => fi(4));
+    return expectFutureInt(future, 4);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> future =
+        errorFuture.then<Future<int>>((_) => fi(-1), onError: (_) => fi(5));
+    return expectFutureFutureInt(future, 5);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> future =
+        errorFuture.then<Future<int>>((_) => fi(-1), onError: (_) => ffi(6));
+    return expectFutureFutureInt(future, 6);
+  });
+
+  // Check `Future.catchError`.
+  // Its implied `FutureOr` return type is based on the original future's type.
+
+  asyncTest(() {
+    Future<int> errorFuture = Future<int>.error(error, stack);
+    Future<int> future = errorFuture.catchError((_) => fi(7));
+    return expectFutureInt(future, 7);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> errorFuture = Future<Future<int>>.error(error, stack);
+    Future<Future<int>> future = errorFuture.catchError((_) => fi(8));
+    return expectFutureFutureInt(future, 8);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> errorFuture = Future<Future<int>>.error(error, stack);
+    Future<Future<int>> future = errorFuture.catchError((_) => ffi(9));
+    return expectFutureFutureInt(future, 9);
+  });
+
+  // Check `Completer.complete`.
+
+  asyncTest(() {
+    var completer = Completer<int>()..complete(fi(10));
+    return expectFutureInt(completer.future, 10);
+  });
+
+  asyncTest(() {
+    var completer = Completer<Future<int>>()..complete(fi(11));
+    return expectFutureFutureInt(completer.future, 11);
+  });
+
+  asyncTest(() {
+    var completer = Completer<Future<int>>()..complete(ffi(12));
+    return expectFutureFutureInt(completer.future, 12);
+  });
+
+  // Future<Object> works correctly when Object is another Future.
+  asyncTest(() {
+    Future<Object> future = nullFuture.then<Object>((_) => fi(13));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    return future.then<void>((o) {
+      Expect.equals(13, o);
+    });
+  });
+
+  asyncTest(() {
+    Future<Object> future = nullFuture.then<Object>((_) => ffi(14));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    Expect.notType<Future<Future<int>>>(future);
+    return future.then<void>((v) => expectFutureInt(v, 14));
+  });
+
+  asyncTest(() {
+    Future<Object> future =
+        errorFuture.then<Object>((_) => -1, onError: (_) => fi(15));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    return future.then<void>((o) {
+      Expect.equals(15, o);
+    });
+  });
+
+  asyncTest(() {
+    Future<Object> future =
+        errorFuture.then<Object>((_) => -1, onError: (_) => ffi(16));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    Expect.notType<Future<Future<int>>>(future);
+    return future.then<void>((v) => expectFutureInt(v, 16));
+  });
+
+  asyncTest(() {
+    Future<Object> errorFuture = Future<Object>.error(error, stack);
+    Future<Object> future = errorFuture.catchError((_) => fi(17));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    return future.then<void>((o) {
+      Expect.equals(17, o);
+    });
+  });
+
+  asyncTest(() {
+    Future<Object> errorFuture = Future<Object>.error(error, stack);
+    Future<Object> future = errorFuture.catchError((_) => ffi(18));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    Expect.notType<Future<Future<int>>>(future);
+    return future.then<void>((v) => expectFutureInt(v, 18));
+  });
+
+  asyncEnd();
+}
+
+// Checks that future is a Future<Future<int>> containing the value Future<int>
+// which then contains the value 42.
+Future<void> expectFutureFutureInt(dynamic future, int n) {
+  Expect.type<Future<Future<int>>>(future);
+  asyncStart();
+  return future.then<void>((dynamic v) {
+    Expect.type<Future<int>>(v, "$n");
+    return expectFutureInt(v, n).then(asyncSuccess);
+  });
+}
+
+Future<void> expectFutureInt(dynamic future, int n) {
+  Expect.type<Future<int>>(future);
+  asyncStart();
+  return future.then<void>((dynamic v) {
+    Expect.type<int>(v, "$n");
+    Expect.equals(n, v);
+    asyncEnd();
+  });
+}
diff --git a/tests/lib/async/future_onerror_test.dart b/tests/lib/async/future_onerror_test.dart
new file mode 100644
index 0000000..ea5ffab
--- /dev/null
+++ b/tests/lib/async/future_onerror_test.dart
@@ -0,0 +1,115 @@
+// 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:async_helper/async_helper.dart';
+import "package:expect/expect.dart";
+
+main() {
+  var stack = StackTrace.fromString("for testing");
+  var error = Object();
+  var stateError = StateError("test");
+
+  asyncStart();
+
+  {
+    // Match any error.
+    asyncStart();
+    var future = Future.error(error, stack);
+    future.onError((e, s) {
+      Expect.identical(error, e);
+      Expect.identical(stack, s);
+      asyncEnd();
+    });
+  }
+
+  {
+    // With matching test.
+    asyncStart();
+    var future = Future.error(error, stack);
+    future.onError((e, s) {
+      Expect.identical(error, e);
+      Expect.identical(stack, s);
+      asyncEnd();
+    }, test: (o) => true);
+  }
+
+  {
+    // With failing test.
+    asyncStart();
+    var future = Future.error(error, stack);
+    var onErrorFuture = future.onError((e, s) {
+      Expect.fail('unreachable');
+    }, test: (o) => false);
+    onErrorFuture.catchError((e, s) {
+      Expect.identical(error, e);
+      Expect.identical(stack, s);
+      asyncEnd();
+    });
+  }
+
+  {
+    // With matching type.
+    asyncStart();
+    var future = Future.error(stateError, stack);
+    future.onError<StateError>((e, s) {
+      Expect.identical(stateError, e);
+      Expect.identical(stack, s);
+      asyncEnd();
+    });
+  }
+
+  {
+    // With non-matching type.
+    asyncStart();
+    var future = Future.error(stateError, stack);
+    var onErrorFuture = future.onError<ArgumentError>((e, s) {
+      Expect.fail('unreachable');
+    });
+    onErrorFuture.catchError((e, s) {
+      Expect.identical(stateError, e);
+      Expect.identical(stack, s);
+      asyncEnd();
+    });
+  }
+
+  {
+    // With non-matching type and matching test.
+    asyncStart();
+    var future = Future.error(stateError, stack);
+    var onErrorFuture = future.onError<ArgumentError>((e, s) {
+      Expect.fail('unreachable');
+    }, test: (ArgumentError e) => true);
+    onErrorFuture.catchError((e, s) {
+      Expect.identical(stateError, e);
+      Expect.identical(stack, s);
+      asyncEnd();
+    });
+  }
+
+  {
+    // With matching type and matching test.
+    asyncStart();
+    var future = Future.error(stateError, stack);
+    future.onError<StateError>((e, s) {
+      Expect.identical(stateError, e);
+      Expect.identical(stack, s);
+      asyncEnd();
+    }, test: (StateError e) => true);
+  }
+
+  {
+    // With matching type and non-matching test.
+    asyncStart();
+    var future = Future.error(stateError, stack);
+    var onErrorFuture = future.onError<StateError>((e, s) {
+      Expect.fail('unreachable');
+    }, test: (StateError e) => false);
+    onErrorFuture.catchError((e, s) {
+      Expect.identical(stateError, e);
+      Expect.identical(stack, s);
+      asyncEnd();
+    });
+  }
+  asyncEnd();
+}
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart
index f2d9710..8fc947b 100644
--- a/tests/lib/async/future_test.dart
+++ b/tests/lib/async/future_test.dart
@@ -1094,7 +1094,7 @@
     var f = new UglyFuture(5);
     // Sanity check that our future is as mis-behaved as we think.
     f.then((v) {
-      Expect.isTrue(v is Future);
+      Expect.equals(UglyFuture(4), v);
     });
 
     var v = await f;
@@ -1102,13 +1102,11 @@
     // suggests that it flattens. In practice it currently doesn't.
     // The specification doesn't say anything special, so v should be the
     // completion value of the UglyFuture future which is a future.
-    Expect.isTrue(v is Future);
+    Expect.equals(UglyFuture(4), v);
 
-    // This used to hit an assert in checked mode.
-    // The CL adding this test changed the behavior to actually flatten the
-    // the future returned by the then-callback.
+    // We no longer flatten recursively when completing a future.
     var w = new Future.value(42).then((_) => f);
-    Expect.equals(42, await w);
+    Expect.equals(UglyFuture(4), await w);
     asyncEnd();
   }();
 }
@@ -1259,8 +1257,10 @@
 // An evil future that completes with another future.
 class UglyFuture implements Future<dynamic> {
   final _result;
+  final int _badness;
   UglyFuture(int badness)
-      : _result = (badness == 0) ? 42 : new UglyFuture(badness - 1);
+      : _badness = badness,
+        _result = (badness == 0) ? 42 : new UglyFuture(badness - 1);
   Future<S> then<S>(action(value), {Function? onError}) {
     var c = new Completer<S>();
     c.complete(new Future<S>.microtask(() => action(_result)));
@@ -1282,4 +1282,10 @@
   Future timeout(Duration duration, {onTimeout()?}) {
     return this;
   }
+
+  int get hashCode => _badness;
+  bool operator ==(Object other) =>
+      other is UglyFuture && _badness == other._badness;
+
+  String toString() => "UglyFuture($_badness)";
 }
diff --git a/tests/lib/html/js_function_getter_trust_types/compile_test.dart b/tests/lib/html/js_function_getter_trust_types/compile_test.dart
index e7481d1..29f8669 100644
--- a/tests/lib/html/js_function_getter_trust_types/compile_test.dart
+++ b/tests/lib/html/js_function_getter_trust_types/compile_test.dart
@@ -47,6 +47,6 @@
   foo.bar.add(4, 5, 10);
   //         ^
   // [cfe] Error: Too many positional arguments: 2 allowed, but 3 found.
-  //         ^^^^^^^^^^
+  //                ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
 }
diff --git a/tests/lib/html/js_interop_constructor_name/div_test.dart b/tests/lib/html/js_interop_constructor_name/div_test.dart
index 02a7826..a61ae6f 100644
--- a/tests/lib/html/js_interop_constructor_name/div_test.dart
+++ b/tests/lib/html/js_interop_constructor_name/div_test.dart
@@ -2,29 +2,14 @@
 // for 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 jsTest;
-
-import 'dart:async';
 import 'dart:html' as html;
-import 'dart:js';
-import 'package:js/js.dart';
 
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
 import 'package:expect/minitest.dart';
 
-@JS()
-external makeDiv(String text);
-
-@JS()
-class HTMLDivElement {
-  external String bar();
-}
-
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
+import 'util.dart';
 
 main() {
+  setUpJS();
   test('dom-is-dom', () {
     var e = confuse(new html.DivElement());
     expect(e is html.DivElement, isTrue);
diff --git a/tests/lib/html/js_interop_constructor_name/div_test.html b/tests/lib/html/js_interop_constructor_name/div_test.html
deleted file mode 100644
index 7ef030a..0000000
--- a/tests/lib/html/js_interop_constructor_name/div_test.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> div_test </title>
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-  </style>
-</head>
-<body>
-  <h1> Running div_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tests/lib/html/js_interop_constructor_name/test_js.js"></script>
-  <script type="text/javascript"
-      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib/html/js_interop_constructor_name/error1_test.dart b/tests/lib/html/js_interop_constructor_name/error1_test.dart
index bb27475..a12be51 100644
--- a/tests/lib/html/js_interop_constructor_name/error1_test.dart
+++ b/tests/lib/html/js_interop_constructor_name/error1_test.dart
@@ -2,29 +2,14 @@
 // for 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 jsTest;
-
-import 'dart:async';
 import 'dart:html' as html;
-import 'dart:js';
-import 'package:js/js.dart';
 
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
 import 'package:expect/minitest.dart';
 
-@JS()
-external makeDiv(String text);
-
-@JS()
-class HTMLDivElement {
-  external String bar();
-}
-
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
+import 'util.dart';
 
 main() {
+  setUpJS();
   test('dom-is-js', () {
     var e = confuse(new html.DivElement());
     // Currently, HTML types are not [JavaScriptObject]s. We could change that
diff --git a/tests/lib/html/js_interop_constructor_name/error1_test.html b/tests/lib/html/js_interop_constructor_name/error1_test.html
deleted file mode 100644
index 7eb4631..0000000
--- a/tests/lib/html/js_interop_constructor_name/error1_test.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> error1_test </title>
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-  </style>
-</head>
-<body>
-  <h1> Running error1_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tests/lib/html/js_interop_constructor_name/test_js.js"></script>
-  <script type="text/javascript"
-      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib/html/js_interop_constructor_name/error2_test.dart b/tests/lib/html/js_interop_constructor_name/error2_test.dart
index 9fab532..365e418 100644
--- a/tests/lib/html/js_interop_constructor_name/error2_test.dart
+++ b/tests/lib/html/js_interop_constructor_name/error2_test.dart
@@ -2,29 +2,14 @@
 // for 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 jsTest;
-
-import 'dart:async';
 import 'dart:html' as html;
-import 'dart:js';
-import 'package:js/js.dart';
 
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
 import 'package:expect/minitest.dart';
 
-@JS()
-external makeDiv(String text);
-
-@JS()
-class HTMLDivElement {
-  external String bar();
-}
-
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
+import 'util.dart';
 
 main() {
+  setUpJS();
   test('String-is-not-js', () {
     var e = confuse('kombucha');
     // A String should not be a JS interop type. The type test flags are added
diff --git a/tests/lib/html/js_interop_constructor_name/error2_test.html b/tests/lib/html/js_interop_constructor_name/error2_test.html
deleted file mode 100644
index f05cdb4..0000000
--- a/tests/lib/html/js_interop_constructor_name/error2_test.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> error2_test </title>
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-  </style>
-</head>
-<body>
-  <h1> Running error2_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tests/lib/html/js_interop_constructor_name/test_js.js"></script>
-  <script type="text/javascript"
-      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib/html/js_interop_constructor_name/method_test.dart b/tests/lib/html/js_interop_constructor_name/method_test.dart
index e881467..9781829 100644
--- a/tests/lib/html/js_interop_constructor_name/method_test.dart
+++ b/tests/lib/html/js_interop_constructor_name/method_test.dart
@@ -2,29 +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.
 
-library jsTest;
-
-import 'dart:async';
 import 'dart:html' as html;
-import 'dart:js';
-import 'package:js/js.dart';
 
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic, Expect;
+import 'package:expect/expect.dart' show Expect;
 import 'package:expect/minitest.dart';
 
-@JS()
-external makeDiv(String text);
-
-@JS()
-class HTMLDivElement {
-  external String bar();
-}
-
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
+import 'util.dart';
 
 main() {
+  setUpJS();
   test('js-call-js-method', () {
     var e = confuse(makeDiv('hello'));
     expect(e.bar(), equals('hello'));
diff --git a/tests/lib/html/js_interop_constructor_name/method_test.html b/tests/lib/html/js_interop_constructor_name/method_test.html
deleted file mode 100644
index a8a0173..0000000
--- a/tests/lib/html/js_interop_constructor_name/method_test.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> method_test </title>
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-  </style>
-</head>
-<body>
-  <h1> Running method_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tests/lib/html/js_interop_constructor_name/test_js.js"></script>
-  <script type="text/javascript"
-      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib/html/js_interop_constructor_name/test_js.js b/tests/lib/html/js_interop_constructor_name/test_js.js
deleted file mode 100644
index 828cbc9..0000000
--- a/tests/lib/html/js_interop_constructor_name/test_js.js
+++ /dev/null
@@ -1,20 +0,0 @@
-(function() {
-
-  // A constructor function with the same name as a HTML element.
-  function HTMLDivElement(a) {
-    this.a = a;
-  }
-
-  HTMLDivElement.prototype.bar = function() {
-    return this.a;
-  }
-
-  HTMLDivElement.prototype.toString = function() {
-    return "HTMLDivElement(" + this.a + ")";
-  }
-
-  self.makeDiv = function(text) {
-    return new HTMLDivElement(text);
-  };
-
-})();
diff --git a/tests/lib/html/js_interop_constructor_name/util.dart b/tests/lib/html/js_interop_constructor_name/util.dart
new file mode 100644
index 0000000..03659f0
--- /dev/null
+++ b/tests/lib/html/js_interop_constructor_name/util.dart
@@ -0,0 +1,49 @@
+// 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.
+
+@JS()
+library util;
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:js/js.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+external makeDiv(String text);
+
+// Static error to name @JS class the same as a @Native class, so we use a
+// namespace `Foo` to avoid conflicting with the native class.
+@JS('Foo.HTMLDivElement')
+class HTMLDivElement {
+  external String bar();
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void setUpJS() {
+  eval(r"""
+  var Foo = {}
+
+  // A constructor function with the same name as a HTML element.
+  Foo.HTMLDivElement = function(a) {
+    this.a = a;
+  }
+
+  Foo.HTMLDivElement.prototype.bar = function() {
+    return this.a;
+  }
+
+  Foo.HTMLDivElement.prototype.toString = function() {
+    return "HTMLDivElement(" + this.a + ")";
+  }
+
+  self.makeDiv = function(text) {
+    return new Foo.HTMLDivElement(text);
+  }
+  """);
+}
diff --git a/tests/lib/html/js_mock_test.dart b/tests/lib/html/js_mock_test.dart
deleted file mode 100644
index 310abc9..0000000
--- a/tests/lib/html/js_mock_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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.
-
-@JS()
-library mock;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS('Node')
-class Node {}
-
-@JS('HTMLDocument')
-class Document extends Node {
-  external Element get body;
-}
-
-@JS()
-external get foo;
-
-@JS()
-external Document get document;
-
-@JS('Element')
-class Element extends Node {
-  external String get tagName;
-}
-
-class MockDocument implements Document {
-  final Element body = new MockElement();
-}
-
-class MockElement implements Element {
-  final tagName = 'MockBody';
-}
-
-void main() {
-  test('js', () {
-    var f = foo;
-    expect(f, isNull);
-
-    var doc = document;
-    expect(doc is Document, isTrue);
-    // Fails in dart2js
-    //expect(doc is! Element, isTrue);
-
-    expect(doc is Node, isTrue);
-
-    expect(doc is! MockDocument, isTrue);
-    expect(doc is! MockElement, isTrue);
-  });
-
-  test('mock', () {
-    var doc = new MockDocument();
-    expect(doc is Document, isTrue);
-    // Fails in dart2js
-    // expect(doc is! Element, isTrue);
-    expect(doc is Node, isTrue);
-
-    var body = doc.body;
-    // Fails in dart2js
-    // expect(body is! Document, isTrue);
-    expect(body is Element, isTrue);
-    expect(body is Node, isTrue);
-  });
-}
diff --git a/tests/lib/html/js_typed_interop_lazy_test.dart b/tests/lib/html/js_typed_interop_lazy_test.dart
index 98b26ff..63c578d 100644
--- a/tests/lib/html/js_typed_interop_lazy_test.dart
+++ b/tests/lib/html/js_typed_interop_lazy_test.dart
@@ -133,7 +133,6 @@
       expect(l is AnonClass, isTrue);
       expect((l as AnonClass) == l, isTrue);
       expect((l as AnonClass2) == l, isTrue);
-      expect(anon is! LazyClass, isTrue); //# 01: ok
       expect(anon is AnonClass, isTrue);
       expect(anon is AnonClass2, isTrue);
 
@@ -226,7 +225,6 @@
       expect(l is AnonClass, isTrue);
       expect((l as AnonClass) == l, isTrue);
       expect((l as AnonClass2) == l, isTrue);
-      expect(anon is! NestedLazyClass, isTrue); //# 01: ok
       expect(anon is AnonClass, isTrue);
       expect(anon is AnonClass2, isTrue);
 
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 d88255c..b84e625 100644
--- a/tests/lib/js/is_check_and_as_cast_test.dart
+++ b/tests/lib/js/is_check_and_as_cast_test.dart
@@ -136,12 +136,21 @@
   expect(() => (a as DartClass), throws);
 
   // Test that nullability is still respected with JS types.
+  expect(foo is Foo?, isTrue);
+  expect(() => (foo as Foo?), returnsNormally);
   Foo? nullableFoo = null;
-  expect(nullableFoo is Foo, false);
+  expect(nullableFoo is Foo?, isTrue);
+  expect(() => (nullableFoo as Foo?), returnsNormally);
+  expect(nullableFoo is Foo, isFalse);
   expect(() => (nullableFoo as Foo),
       hasUnsoundNullSafety ? returnsNormally : throws);
+
+  expect(a is LiteralA?, isTrue);
+  expect(() => (a as LiteralA?), returnsNormally);
   LiteralA? nullableA = null;
-  expect(nullableA is LiteralA, false);
+  expect(nullableA is LiteralA?, isTrue);
+  expect(() => (nullableA as LiteralA?), returnsNormally);
+  expect(nullableA is LiteralA, isFalse);
   expect(() => (nullableA as LiteralA),
       hasUnsoundNullSafety ? returnsNormally : throws);
 }
diff --git a/tests/lib/js/js_util/assert_function_interop_test.dart b/tests/lib/js/js_util/assert_function_interop_test.dart
new file mode 100644
index 0000000..53d4386
--- /dev/null
+++ b/tests/lib/js/js_util/assert_function_interop_test.dart
@@ -0,0 +1,93 @@
+// 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.
+
+// dart2jsOptions=--enable-asserts
+
+// Tests that `js_util` methods correctly check that function arguments allow
+// interop.
+
+@JS()
+library assert_function_interop_test;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart' as js_util;
+import 'package:expect/expect.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class JSClass {
+  external JSClass();
+}
+
+@JS()
+external get JSClassWithFuncArgs;
+
+@JS()
+external void Function() get jsFunction;
+
+void dartFunction() {}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void main() {
+  eval(r"""
+    function JSClass() {
+      this.functionProperty = function() {};
+      this.methodWithFuncArgs = function(f1, f2) {
+        f1();
+        if (arguments.length == 2) f2();
+      };
+    }
+    function JSClassWithFuncArgs(f1, f2) {
+      f1();
+      if (arguments.length == 2) f2();
+    }
+    function jsFunction() {}
+  """);
+
+  var jsClass = JSClass();
+  dynamic d = confuse(dartFunction);
+  var interopFunction = allowInterop(dartFunction);
+  var interopDynamic = confuse(allowInterop(dartFunction));
+
+  // Functions that aren't wrapped with `allowInterop` should throw.
+  Expect.throws(
+      () => js_util.setProperty(jsClass, 'functionProperty', dartFunction));
+  Expect.throws(() => js_util.setProperty(jsClass, 'functionProperty', d));
+  // Correctly wrapped functions should not throw.
+  js_util.setProperty(jsClass, 'functionProperty', interopFunction);
+  js_util.setProperty(jsClass, 'functionProperty', interopDynamic);
+
+  // Using a JS function should not throw.
+  js_util.setProperty(jsClass, 'functionProperty', jsFunction);
+
+  Expect.throws(
+      () => js_util.callMethod(jsClass, 'methodWithFuncArgs', [dartFunction]));
+  Expect.throws(() => js_util.callMethod(jsClass, 'methodWithFuncArgs', [d]));
+  js_util.callMethod(jsClass, 'methodWithFuncArgs', [interopFunction]);
+  js_util.callMethod(jsClass, 'methodWithFuncArgs', [interopDynamic]);
+  // Check to see that all arguments are checked.
+  Expect.throws(() => js_util.callMethod(
+      jsClass, 'methodWithFuncArgs', [interopFunction, dartFunction]));
+  js_util.callMethod(
+      jsClass, 'methodWithFuncArgs', [interopFunction, interopFunction]);
+
+  js_util.callMethod(jsClass, 'methodWithFuncArgs', [jsFunction]);
+
+  Expect.throws(
+      () => js_util.callConstructor(JSClassWithFuncArgs, [dartFunction]));
+  Expect.throws(() => js_util.callConstructor(JSClassWithFuncArgs, [d]));
+  js_util.callConstructor(JSClassWithFuncArgs, [interopFunction]);
+  js_util.callConstructor(JSClassWithFuncArgs, [interopDynamic]);
+  Expect.throws(() => js_util
+      .callConstructor(JSClassWithFuncArgs, [interopFunction, dartFunction]));
+  js_util
+      .callConstructor(JSClassWithFuncArgs, [interopFunction, interopFunction]);
+
+  js_util.callConstructor(JSClassWithFuncArgs, [jsFunction]);
+}
diff --git a/tests/lib/js/mock_test.dart b/tests/lib/js/mock_test.dart
new file mode 100644
index 0000000..a33ac5e
--- /dev/null
+++ b/tests/lib/js/mock_test.dart
@@ -0,0 +1,87 @@
+// 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.
+
+@JS()
+library mock_test;
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class JSClass {}
+
+@JS()
+class DerivedA extends JSClass {
+  external DerivedB get derivedB;
+}
+
+@JS()
+external DerivedA get derivedA;
+
+@JS()
+class DerivedB extends JSClass {}
+
+class MockDerivedA implements DerivedA {
+  final DerivedB derivedB = new MockDerivedB();
+}
+
+class MockDerivedB implements DerivedB {}
+
+void main() {
+  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() {
+    }
+    function DerivedA() {
+      JSClass.call(this);
+      this.derivedB = new DerivedB();
+    }
+    inherits(DerivedA, JSClass);
+    function DerivedB() {
+      JSClass.call(this);
+    }
+    inherits(DerivedB, JSClass);
+    var derivedA = new DerivedA();
+  """);
+  test('js', () {
+    var jsA = derivedA;
+    // `is` checks will return true for any two JS interop types.
+    expect(jsA is JSClass, isTrue);
+    expect(jsA is DerivedA, isTrue);
+    expect(jsA is DerivedB, isTrue);
+
+    expect(jsA is! MockDerivedA, isTrue);
+    expect(jsA is! MockDerivedB, isTrue);
+  });
+
+  test('mock', () {
+    var mockA = new MockDerivedA();
+    expect(mockA is JSClass, isTrue); //# 44252: ok
+    expect(mockA is DerivedA, isTrue);
+    // Fails in dart2js
+    // expect(mockA is! DerivedB, isTrue);
+    expect(mockA is MockDerivedA, isTrue);
+    expect(mockA is! MockDerivedB, isTrue);
+
+    var mockB = mockA.derivedB;
+    expect(mockB is JSClass, isTrue); //# 44252: continued
+    // Fails in dart2js
+    // expect(mockB is! DerivedA, isTrue);
+    expect(mockB is DerivedB, isTrue);
+    expect(mockB is! MockDerivedA, isTrue);
+    expect(mockB is MockDerivedB, isTrue);
+  });
+}
diff --git a/tests/lib/js/native_as_js_classes_static_test/default_library_namespace_test.dart b/tests/lib/js/native_as_js_classes_static_test/default_library_namespace_test.dart
new file mode 100644
index 0000000..d230129
--- /dev/null
+++ b/tests/lib/js/native_as_js_classes_static_test/default_library_namespace_test.dart
@@ -0,0 +1,75 @@
+// 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.
+
+// Test errors with a library with the default namespace.
+
+@JS()
+library default_library_namespace_test;
+
+import 'package:js/js.dart';
+
+// Test same class name as a native class.
+@JS()
+class HTMLDocument {}
+//    ^
+// [web] JS interop class 'HTMLDocument' conflicts with natively supported class 'HtmlDocument' in 'dart:html'.
+
+// Test same annotation name as a native class.
+@JS('HTMLDocument')
+class HtmlDocument {}
+//    ^
+// [web] JS interop class 'HtmlDocument' conflicts with natively supported class 'HtmlDocument' in 'dart:html'.
+
+// Test annotation name with 'self' and 'window' prefixes.
+@JS('self.Window')
+class WindowWithSelf {}
+//    ^
+// [web] JS interop class 'WindowWithSelf' conflicts with natively supported class 'Window' in 'dart:html'.
+
+@JS('window.Window')
+class WindowWithWindow {}
+//    ^
+// [web] JS interop class 'WindowWithWindow' conflicts with natively supported class 'Window' in 'dart:html'.
+
+@JS('self.window.self.window.self.Window')
+class WindowWithMultipleSelfsAndWindows {}
+//    ^
+// [web] JS interop class 'WindowWithMultipleSelfsAndWindows' conflicts with natively supported class 'Window' in 'dart:html'.
+
+// Test annotation with native class name but with a prefix that isn't 'self' or
+// 'window'.
+@JS('foo.Window')
+class WindowWithDifferentPrefix {}
+
+// Test same class name as a native class with multiple annotation names.
+// dart:html.Window uses both "Window" and "DOMWindow".
+@JS()
+class DOMWindow {}
+//    ^
+// [web] JS interop class 'DOMWindow' conflicts with natively supported class 'Window' in 'dart:html'.
+
+// Test same annotation name as a native class with multiple annotation names
+// dart:html.Window uses both "Window" and "DOMWindow".
+@JS('DOMWindow')
+class DomWindow {}
+//    ^
+// [web] JS interop class 'DomWindow' conflicts with natively supported class 'Window' in 'dart:html'.
+
+// Test different annotation name but with same class name as a @Native class.
+@JS('Foo')
+class Window {}
+
+// Dart classes don't have to worry about conflicts.
+class Element {}
+
+// Anonymous classes don't have to worry about conflicts either.
+@JS()
+@anonymous
+class HTMLElement {}
+
+@JS('HTMLElement')
+@anonymous
+class HtmlElement {}
+
+void main() {}
diff --git a/tests/lib/js/native_as_js_classes_static_test/global_library_namespace_test.dart b/tests/lib/js/native_as_js_classes_static_test/global_library_namespace_test.dart
new file mode 100644
index 0000000..fb55aa6
--- /dev/null
+++ b/tests/lib/js/native_as_js_classes_static_test/global_library_namespace_test.dart
@@ -0,0 +1,63 @@
+// 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.
+
+// Test errors with a library with a global namespace.
+
+@JS('window')
+library global_library_namespace_test;
+
+import 'package:js/js.dart';
+
+@JS()
+class HTMLDocument {}
+//    ^
+// [web] JS interop class 'HTMLDocument' conflicts with natively supported class 'HtmlDocument' in 'dart:html'.
+
+@JS('HTMLDocument')
+class HtmlDocument {}
+//    ^
+// [web] JS interop class 'HtmlDocument' conflicts with natively supported class 'HtmlDocument' in 'dart:html'.
+
+@JS('self.Window')
+class WindowWithSelf {}
+//    ^
+// [web] JS interop class 'WindowWithSelf' conflicts with natively supported class 'Window' in 'dart:html'.
+
+@JS('window.Window')
+class WindowWithWindow {}
+//    ^
+// [web] JS interop class 'WindowWithWindow' conflicts with natively supported class 'Window' in 'dart:html'.
+
+@JS('self.window.self.window.self.Window')
+class WindowWithMultipleSelfsAndWindows {}
+//    ^
+// [web] JS interop class 'WindowWithMultipleSelfsAndWindows' conflicts with natively supported class 'Window' in 'dart:html'.
+
+@JS('foo.Window')
+class WindowWithDifferentPrefix {}
+
+@JS()
+class DOMWindow {}
+//    ^
+// [web] JS interop class 'DOMWindow' conflicts with natively supported class 'Window' in 'dart:html'.
+
+@JS('DOMWindow')
+class DomWindow {}
+//    ^
+// [web] JS interop class 'DomWindow' conflicts with natively supported class 'Window' in 'dart:html'.
+
+@JS('Foo')
+class Window {}
+
+class Element {}
+
+@JS()
+@anonymous
+class HTMLElement {}
+
+@JS('HTMLElement')
+@anonymous
+class HtmlElement {}
+
+void main() {}
diff --git a/tests/lib/js/native_as_js_classes_static_test/local_library_namespace_test.dart b/tests/lib/js/native_as_js_classes_static_test/local_library_namespace_test.dart
new file mode 100644
index 0000000..e529bfa
--- /dev/null
+++ b/tests/lib/js/native_as_js_classes_static_test/local_library_namespace_test.dart
@@ -0,0 +1,50 @@
+// 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.
+
+// Test errors with a library with a non-default or non-global namespace.
+// Note that none of the following should be errors in this case.
+
+@JS('foo')
+library global_library_namespace_test;
+
+import 'package:js/js.dart';
+
+@JS()
+class HTMLDocument {}
+
+@JS('HTMLDocument')
+class HtmlDocument {}
+
+@JS('self.Window')
+class WindowWithSelf {}
+
+@JS('window.Window')
+class WindowWithWindow {}
+
+@JS('self.window.self.window.self.Window')
+class WindowWithMultipleSelfsAndWindows {}
+
+@JS('foo.Window')
+class WindowWithDifferentPrefix {}
+
+@JS()
+class DOMWindow {}
+
+@JS('DOMWindow')
+class DomWindow {}
+
+@JS('Foo')
+class Window {}
+
+class Element {}
+
+@JS()
+@anonymous
+class HTMLElement {}
+
+@JS('HTMLElement')
+@anonymous
+class HtmlElement {}
+
+void main() {}
diff --git a/tests/lib/js/no_library_annotation_test.dart b/tests/lib/js/no_library_annotation_test.dart
new file mode 100644
index 0000000..24fbc57
--- /dev/null
+++ b/tests/lib/js/no_library_annotation_test.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.
+
+// Test that JS-interop works without a @JS annotation on the library itself.
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+@JS()
+external dynamic eval(String code);
+
+void main() {
+  Expect.equals(2, eval("2"));
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 43d6d0e..6cc876f 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -34,9 +34,11 @@
 html/xhr_test/xhr: Skip # Times out.  Issue 21527
 
 [ $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/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/method_call_on_object_test: SkipByDesign # Issue 42085.
+js/mock_test/*: SkipByDesign # Issue 42085.
 js/parameters_test: SkipByDesign # Issue 42085.
 
 [ $compiler != dart2js && $compiler != dartdevk ]
diff --git a/tests/lib/mirrors/class_mirror_type_variables_expect.dart b/tests/lib/mirrors/class_mirror_type_variables_expect.dart
index adee190..847bd7f 100644
--- a/tests/lib/mirrors/class_mirror_type_variables_expect.dart
+++ b/tests/lib/mirrors/class_mirror_type_variables_expect.dart
@@ -70,7 +70,6 @@
   Expect.isFalse(bZBound.isOriginalDeclaration);
   Expect.isFalse(cZBound.isOriginalDeclaration);
 
-  Expect.notEquals(bZBound, cZBound);
   Expect.equals(b, bZBound.originalDeclaration);
   Expect.equals(b, cZBound.originalDeclaration);
 
@@ -83,10 +82,7 @@
   Expect.equals(c, cZ.owner);
   Expect.equals(b, bZBoundTypeVariable.owner);
   Expect.equals(b, cZBoundTypeVariable.owner);
-  Expect.equals(b, bZBoundTypeArgument.owner);
-  Expect.equals(c, cZBoundTypeArgument.owner);
 
-  Expect.notEquals(bZ, cZ);
   Expect.equals(bZ, bZBoundTypeArgument);
   Expect.equals(cZ, cZBoundTypeArgument);
   Expect.equals(bZ, bZBoundTypeVariable);
diff --git a/tests/lib/mirrors/generics_test.dart b/tests/lib/mirrors/generics_test.dart
index fface13..ce9d8f0 100644
--- a/tests/lib/mirrors/generics_test.dart
+++ b/tests/lib/mirrors/generics_test.dart
@@ -158,8 +158,6 @@
 
   Expect.equals(reflectClass(A).typeVariables[0].owner, reflectClass(A));
   Expect.equals(reflectClass(Z).typeVariables[0].owner, reflectClass(Z));
-  Expect.notEquals(
-      reflectClass(A).typeVariables[0], reflectClass(Z).typeVariables[0]);
   Expect.equals(
       reflectClass(A).typeVariables[0], reflectClass(A).typeVariables[0]);
 }
diff --git a/tests/lib/mirrors/parameter_test.dart b/tests/lib/mirrors/parameter_test.dart
index d096711..2a5eff6 100644
--- a/tests/lib/mirrors/parameter_test.dart
+++ b/tests/lib/mirrors/parameter_test.dart
@@ -184,7 +184,7 @@
       '[Parameter(s(a) in s(foo),'
       ' type = Class(s(int) in s(dart.core), top-level)), '
       'Parameter(s(b) in s(foo),'
-      ' type = TypeVariable(s(S) in s(C),'
+      ' type = TypeVariable(s(S) in s(Null),'
       ' upperBound = Class(s(int) in s(dart.core), top-level)))]',
       fooInC.parameters);
 
@@ -192,10 +192,10 @@
   expect('Method(s(bar) in s(C))', barInC);
   expect(
       '[Parameter(s(a) in s(bar),'
-      ' type = TypeVariable(s(S) in s(C),'
+      ' type = TypeVariable(s(S) in s(Null),'
       ' upperBound = Class(s(int) in s(dart.core), top-level))), '
       'Parameter(s(b) in s(bar),'
-      ' type = TypeVariable(s(T) in s(C),'
+      ' type = TypeVariable(s(T) in s(Null),'
       ' upperBound = Class(s(Object) in s(dart.core), top-level))), '
       'Parameter(s(c) in s(bar),'
       ' type = Class(s(num) in s(dart.core), top-level))]',
diff --git a/tests/lib_2/async/future_future_test.dart b/tests/lib_2/async/future_future_test.dart
new file mode 100644
index 0000000..45aaf82
--- /dev/null
+++ b/tests/lib_2/async/future_future_test.dart
@@ -0,0 +1,187 @@
+// 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.
+
+// Checks that Future<Future<int>> is a valid type and that futures can contain
+// and complete other futures.
+
+// This essentially checks that `FutureOr<X>` is treated correctly depending
+// on what `X` is.
+
+import 'dart:async';
+import 'package:async_helper/async_helper.dart';
+import "package:expect/expect.dart";
+
+main() {
+  asyncStart();
+
+  // Helper values.
+  Future<Null> nullFuture = Future<Null>.value(null);
+
+  var stack = StackTrace.current;
+  var error = ArgumentError("yep");
+  Future<Null> errorFuture = Future<Null>.error(error, stack)
+    ..catchError((_) => null);
+  Future<int> fi(int n) => Future<int>.value(n);
+
+  // Tests that Future<Future<int>> can be created.
+  Future<Future<int>> ffi(n) => Future<Future<int>>.value(fi(n));
+
+  asyncTest(() {
+    return expectFutureFutureInt(ffi(0), 0);
+  });
+
+  // Check `Future.then`'s callback.
+
+  asyncTest(() {
+    Future<int> future = nullFuture.then<int>((_) => fi(1));
+    return expectFutureInt(future, 1);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> future = nullFuture.then<Future<int>>((_) => fi(2));
+    return expectFutureFutureInt(future, 2);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> future = nullFuture.then<Future<int>>((_) => ffi(3));
+    return expectFutureFutureInt(future, 3);
+  });
+
+  // Check `Future.then`'s `onError`.
+
+  asyncTest(() {
+    Future<int> future =
+        errorFuture.then<int>((_) => -1, onError: (_) => fi(4));
+    return expectFutureInt(future, 4);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> future =
+        errorFuture.then<Future<int>>((_) => fi(-1), onError: (_) => fi(5));
+    return expectFutureFutureInt(future, 5);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> future =
+        errorFuture.then<Future<int>>((_) => fi(-1), onError: (_) => ffi(6));
+    return expectFutureFutureInt(future, 6);
+  });
+
+  // Checkc Future.catchError, it's FutureOr is based on the
+  // original future's type.
+
+  asyncTest(() {
+    Future<int> errorFuture = Future<int>.error(error, stack);
+    Future<int> future = errorFuture.catchError((_) => fi(7));
+    return expectFutureInt(future, 7);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> errorFuture = Future<Future<int>>.error(error, stack);
+    Future<Future<int>> future = errorFuture.catchError((_) => fi(8));
+    return expectFutureFutureInt(future, 8);
+  });
+
+  asyncTest(() {
+    Future<Future<int>> errorFuture = Future<Future<int>>.error(error, stack);
+    Future<Future<int>> future = errorFuture.catchError((_) => ffi(9));
+    return expectFutureFutureInt(future, 9);
+  });
+
+  // Check Completer.complete.
+
+  asyncTest(() {
+    var completer = Completer<int>()..complete(fi(10));
+    return expectFutureInt(completer.future, 10);
+  });
+
+  asyncTest(() {
+    var completer = Completer<Future<int>>()..complete(fi(11));
+    return expectFutureFutureInt(completer.future, 11);
+  });
+
+  asyncTest(() {
+    var completer = Completer<Future<int>>()..complete(ffi(12));
+    return expectFutureFutureInt(completer.future, 12);
+  });
+
+  // Future<Object> works correctly when Object is another Future.
+  asyncTest(() {
+    Future<Object> future = nullFuture.then<Object>((_) => fi(13));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    return future.then<void>((o) {
+      Expect.equals(13, o);
+    });
+  });
+
+  asyncTest(() {
+    Future<Object> future = nullFuture.then<Object>((_) => ffi(14));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    Expect.notType<Future<Future<int>>>(future);
+    return future.then<void>((v) => expectFutureInt(v, 14));
+  });
+
+  asyncTest(() {
+    Future<Object> future =
+        errorFuture.then<Object>((_) => -1, onError: (_) => fi(15));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    return future.then<void>((o) {
+      Expect.equals(15, o);
+    });
+  });
+
+  asyncTest(() {
+    Future<Object> future =
+        errorFuture.then<Object>((_) => -1, onError: (_) => ffi(16));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    Expect.notType<Future<Future<int>>>(future);
+    return future.then<void>((v) => expectFutureInt(v, 16));
+  });
+
+  asyncTest(() {
+    Future<Object> errorFuture = Future<Object>.error(error, stack);
+    Future<Object> future = errorFuture.catchError((_) => fi(17));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    return future.then<void>((o) {
+      Expect.equals(17, o);
+    });
+  });
+
+  asyncTest(() {
+    Future<Object> errorFuture = Future<Object>.error(error, stack);
+    Future<Object> future = errorFuture.catchError((_) => ffi(18));
+    Expect.type<Future<Object>>(future);
+    Expect.notType<Future<int>>(future);
+    Expect.notType<Future<Future<int>>>(future);
+    return future.then<void>((v) => expectFutureInt(v, 18));
+  });
+
+  asyncEnd();
+}
+
+// Checks that future is a Future<Future<int>> containing the value Future<int>
+// which then contains the value 42.
+Future<void> expectFutureFutureInt(dynamic future, int n) {
+  Expect.type<Future<Future<int>>>(future);
+  asyncStart();
+  return future.then<void>((dynamic v) {
+    Expect.type<Future<int>>(v, "$n");
+    return expectFutureInt(v, n).then(asyncSuccess);
+  });
+}
+
+Future<void> expectFutureInt(dynamic future, int n) {
+  Expect.type<Future<int>>(future);
+  asyncStart();
+  return future.then<void>((dynamic v) {
+    Expect.type<int>(v, "$n");
+    Expect.equals(n, v);
+    asyncEnd();
+  });
+}
diff --git a/tests/lib_2/async/future_test.dart b/tests/lib_2/async/future_test.dart
index 2e546bf..9242649 100644
--- a/tests/lib_2/async/future_test.dart
+++ b/tests/lib_2/async/future_test.dart
@@ -1087,7 +1087,7 @@
     var f = new UglyFuture(5);
     // Sanity check that our future is as mis-behaved as we think.
     f.then((v) {
-      Expect.isTrue(v is Future);
+      Expect.equals(UglyFuture(4), v);
     });
 
     var v = await f;
@@ -1095,13 +1095,11 @@
     // suggests that it flattens. In practice it currently doesn't.
     // The specification doesn't say anything special, so v should be the
     // completion value of the UglyFuture future which is a future.
-    Expect.isTrue(v is Future);
+    Expect.equals(UglyFuture(4), v);
 
-    // This used to hit an assert in checked mode.
-    // The CL adding this test changed the behavior to actually flatten the
-    // the future returned by the then-callback.
+    // We no longer flatten recursively in situations like this.
     var w = new Future.value(42).then((_) => f);
-    Expect.equals(42, await w);
+    Expect.equals(UglyFuture(4), await w);
     asyncEnd();
   }();
 }
@@ -1253,11 +1251,13 @@
 // An evil future that completes with another future.
 class UglyFuture implements Future<dynamic> {
   final _result;
+  final int _badness;
   UglyFuture(int badness)
-      : _result = (badness == 0) ? 42 : new UglyFuture(badness - 1);
+      : _badness = badness,
+        _result = (badness == 0) ? 42 : new UglyFuture(badness - 1);
   Future<S> then<S>(action(value), {Function onError}) {
     var c = new Completer<S>();
-    c.complete(new Future.microtask(() => action(_result)));
+    c.complete(new Future<S>.microtask(() => action(_result)));
     return c.future;
   }
 
@@ -1276,4 +1276,10 @@
   Future timeout(Duration duration, {onTimeout()}) {
     return this;
   }
+
+  int get hashCode => _badness;
+  bool operator ==(Object other) =>
+      other is UglyFuture && _badness == other._badness;
+
+  String toString() => "UglyFuture($_badness)";
 }
diff --git a/tests/lib_2/html/js_function_getter_trust_types/compile_test.dart b/tests/lib_2/html/js_function_getter_trust_types/compile_test.dart
index e7481d1..29f8669 100644
--- a/tests/lib_2/html/js_function_getter_trust_types/compile_test.dart
+++ b/tests/lib_2/html/js_function_getter_trust_types/compile_test.dart
@@ -47,6 +47,6 @@
   foo.bar.add(4, 5, 10);
   //         ^
   // [cfe] Error: Too many positional arguments: 2 allowed, but 3 found.
-  //         ^^^^^^^^^^
+  //                ^^
   // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
 }
diff --git a/tests/lib_2/html/js_interop_constructor_name/div_test.dart b/tests/lib_2/html/js_interop_constructor_name/div_test.dart
index 02a7826..a61ae6f 100644
--- a/tests/lib_2/html/js_interop_constructor_name/div_test.dart
+++ b/tests/lib_2/html/js_interop_constructor_name/div_test.dart
@@ -2,29 +2,14 @@
 // for 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 jsTest;
-
-import 'dart:async';
 import 'dart:html' as html;
-import 'dart:js';
-import 'package:js/js.dart';
 
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
 import 'package:expect/minitest.dart';
 
-@JS()
-external makeDiv(String text);
-
-@JS()
-class HTMLDivElement {
-  external String bar();
-}
-
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
+import 'util.dart';
 
 main() {
+  setUpJS();
   test('dom-is-dom', () {
     var e = confuse(new html.DivElement());
     expect(e is html.DivElement, isTrue);
diff --git a/tests/lib_2/html/js_interop_constructor_name/div_test.html b/tests/lib_2/html/js_interop_constructor_name/div_test.html
deleted file mode 100644
index 31aad5e..0000000
--- a/tests/lib_2/html/js_interop_constructor_name/div_test.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> div_test </title>
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-  </style>
-</head>
-<body>
-  <h1> Running div_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tests/lib_2/html/js_interop_constructor_name/test_js.js"></script>
-  <script type="text/javascript"
-      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib_2/html/js_interop_constructor_name/error1_test.dart b/tests/lib_2/html/js_interop_constructor_name/error1_test.dart
index bb27475..a12be51 100644
--- a/tests/lib_2/html/js_interop_constructor_name/error1_test.dart
+++ b/tests/lib_2/html/js_interop_constructor_name/error1_test.dart
@@ -2,29 +2,14 @@
 // for 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 jsTest;
-
-import 'dart:async';
 import 'dart:html' as html;
-import 'dart:js';
-import 'package:js/js.dart';
 
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
 import 'package:expect/minitest.dart';
 
-@JS()
-external makeDiv(String text);
-
-@JS()
-class HTMLDivElement {
-  external String bar();
-}
-
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
+import 'util.dart';
 
 main() {
+  setUpJS();
   test('dom-is-js', () {
     var e = confuse(new html.DivElement());
     // Currently, HTML types are not [JavaScriptObject]s. We could change that
diff --git a/tests/lib_2/html/js_interop_constructor_name/error1_test.html b/tests/lib_2/html/js_interop_constructor_name/error1_test.html
deleted file mode 100644
index 9c6566e..0000000
--- a/tests/lib_2/html/js_interop_constructor_name/error1_test.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> error1_test </title>
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-  </style>
-</head>
-<body>
-  <h1> Running error1_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tests/lib_2/html/js_interop_constructor_name/test_js.js"></script>
-  <script type="text/javascript"
-      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib_2/html/js_interop_constructor_name/error2_test.dart b/tests/lib_2/html/js_interop_constructor_name/error2_test.dart
index 9fab532..365e418 100644
--- a/tests/lib_2/html/js_interop_constructor_name/error2_test.dart
+++ b/tests/lib_2/html/js_interop_constructor_name/error2_test.dart
@@ -2,29 +2,14 @@
 // for 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 jsTest;
-
-import 'dart:async';
 import 'dart:html' as html;
-import 'dart:js';
-import 'package:js/js.dart';
 
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
 import 'package:expect/minitest.dart';
 
-@JS()
-external makeDiv(String text);
-
-@JS()
-class HTMLDivElement {
-  external String bar();
-}
-
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
+import 'util.dart';
 
 main() {
+  setUpJS();
   test('String-is-not-js', () {
     var e = confuse('kombucha');
     // A String should not be a JS interop type. The type test flags are added
diff --git a/tests/lib_2/html/js_interop_constructor_name/error2_test.html b/tests/lib_2/html/js_interop_constructor_name/error2_test.html
deleted file mode 100644
index 7e1b64f..0000000
--- a/tests/lib_2/html/js_interop_constructor_name/error2_test.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> error2_test </title>
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-  </style>
-</head>
-<body>
-  <h1> Running error2_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tests/lib_2/html/js_interop_constructor_name/test_js.js"></script>
-  <script type="text/javascript"
-      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib_2/html/js_interop_constructor_name/method_test.dart b/tests/lib_2/html/js_interop_constructor_name/method_test.dart
index e881467..9781829 100644
--- a/tests/lib_2/html/js_interop_constructor_name/method_test.dart
+++ b/tests/lib_2/html/js_interop_constructor_name/method_test.dart
@@ -2,29 +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.
 
-library jsTest;
-
-import 'dart:async';
 import 'dart:html' as html;
-import 'dart:js';
-import 'package:js/js.dart';
 
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic, Expect;
+import 'package:expect/expect.dart' show Expect;
 import 'package:expect/minitest.dart';
 
-@JS()
-external makeDiv(String text);
-
-@JS()
-class HTMLDivElement {
-  external String bar();
-}
-
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
+import 'util.dart';
 
 main() {
+  setUpJS();
   test('js-call-js-method', () {
     var e = confuse(makeDiv('hello'));
     expect(e.bar(), equals('hello'));
diff --git a/tests/lib_2/html/js_interop_constructor_name/method_test.html b/tests/lib_2/html/js_interop_constructor_name/method_test.html
deleted file mode 100644
index c38d07dd..0000000
--- a/tests/lib_2/html/js_interop_constructor_name/method_test.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <meta name="dart.unittest" content="full-stack-traces">
-  <title> method_test </title>
-  <style>
-     .unittest-table { font-family:monospace; border:1px; }
-     .unittest-pass { background: #6b3;}
-     .unittest-fail { background: #d55;}
-     .unittest-error { background: #a11;}
-  </style>
-</head>
-<body>
-  <h1> Running method_test </h1>
-  <script type="text/javascript"
-      src="/root_dart/tests/lib_2/html/js_interop_constructor_name/test_js.js"></script>
-  <script type="text/javascript"
-      src="/root_dart/pkg/test_runner/lib/src/test_controller.js"></script>
-  %TEST_SCRIPTS%
-</body>
-</html>
diff --git a/tests/lib_2/html/js_interop_constructor_name/test_js.js b/tests/lib_2/html/js_interop_constructor_name/test_js.js
deleted file mode 100644
index 828cbc9..0000000
--- a/tests/lib_2/html/js_interop_constructor_name/test_js.js
+++ /dev/null
@@ -1,20 +0,0 @@
-(function() {
-
-  // A constructor function with the same name as a HTML element.
-  function HTMLDivElement(a) {
-    this.a = a;
-  }
-
-  HTMLDivElement.prototype.bar = function() {
-    return this.a;
-  }
-
-  HTMLDivElement.prototype.toString = function() {
-    return "HTMLDivElement(" + this.a + ")";
-  }
-
-  self.makeDiv = function(text) {
-    return new HTMLDivElement(text);
-  };
-
-})();
diff --git a/tests/lib_2/html/js_interop_constructor_name/util.dart b/tests/lib_2/html/js_interop_constructor_name/util.dart
new file mode 100644
index 0000000..03659f0
--- /dev/null
+++ b/tests/lib_2/html/js_interop_constructor_name/util.dart
@@ -0,0 +1,49 @@
+// 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.
+
+@JS()
+library util;
+
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:js/js.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+external makeDiv(String text);
+
+// Static error to name @JS class the same as a @Native class, so we use a
+// namespace `Foo` to avoid conflicting with the native class.
+@JS('Foo.HTMLDivElement')
+class HTMLDivElement {
+  external String bar();
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void setUpJS() {
+  eval(r"""
+  var Foo = {}
+
+  // A constructor function with the same name as a HTML element.
+  Foo.HTMLDivElement = function(a) {
+    this.a = a;
+  }
+
+  Foo.HTMLDivElement.prototype.bar = function() {
+    return this.a;
+  }
+
+  Foo.HTMLDivElement.prototype.toString = function() {
+    return "HTMLDivElement(" + this.a + ")";
+  }
+
+  self.makeDiv = function(text) {
+    return new Foo.HTMLDivElement(text);
+  }
+  """);
+}
diff --git a/tests/lib_2/html/js_mock_test.dart b/tests/lib_2/html/js_mock_test.dart
deleted file mode 100644
index 310abc9..0000000
--- a/tests/lib_2/html/js_mock_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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.
-
-@JS()
-library mock;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS('Node')
-class Node {}
-
-@JS('HTMLDocument')
-class Document extends Node {
-  external Element get body;
-}
-
-@JS()
-external get foo;
-
-@JS()
-external Document get document;
-
-@JS('Element')
-class Element extends Node {
-  external String get tagName;
-}
-
-class MockDocument implements Document {
-  final Element body = new MockElement();
-}
-
-class MockElement implements Element {
-  final tagName = 'MockBody';
-}
-
-void main() {
-  test('js', () {
-    var f = foo;
-    expect(f, isNull);
-
-    var doc = document;
-    expect(doc is Document, isTrue);
-    // Fails in dart2js
-    //expect(doc is! Element, isTrue);
-
-    expect(doc is Node, isTrue);
-
-    expect(doc is! MockDocument, isTrue);
-    expect(doc is! MockElement, isTrue);
-  });
-
-  test('mock', () {
-    var doc = new MockDocument();
-    expect(doc is Document, isTrue);
-    // Fails in dart2js
-    // expect(doc is! Element, isTrue);
-    expect(doc is Node, isTrue);
-
-    var body = doc.body;
-    // Fails in dart2js
-    // expect(body is! Document, isTrue);
-    expect(body is Element, isTrue);
-    expect(body is Node, isTrue);
-  });
-}
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 429e135..3fce5a0 100644
--- a/tests/lib_2/html/js_typed_interop_lazy_test.dart
+++ b/tests/lib_2/html/js_typed_interop_lazy_test.dart
@@ -133,7 +133,6 @@
       expect(l is AnonClass, isTrue);
       expect((l as AnonClass) == l, isTrue);
       expect((l as AnonClass2) == l, isTrue);
-      expect(anon is! LazyClass, isTrue); //# 01: ok
       expect(anon is AnonClass, isTrue);
       expect(anon is AnonClass2, isTrue);
 
@@ -226,7 +225,6 @@
       expect(l is AnonClass, isTrue);
       expect((l as AnonClass) == l, isTrue);
       expect((l as AnonClass2) == l, isTrue);
-      expect(anon is! NestedLazyClass, isTrue); //# 01: ok
       expect(anon is AnonClass, isTrue);
       expect(anon is AnonClass2, isTrue);
 
diff --git a/tests/lib_2/js/mock_test.dart b/tests/lib_2/js/mock_test.dart
new file mode 100644
index 0000000..a33ac5e
--- /dev/null
+++ b/tests/lib_2/js/mock_test.dart
@@ -0,0 +1,87 @@
+// 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.
+
+@JS()
+library mock_test;
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class JSClass {}
+
+@JS()
+class DerivedA extends JSClass {
+  external DerivedB get derivedB;
+}
+
+@JS()
+external DerivedA get derivedA;
+
+@JS()
+class DerivedB extends JSClass {}
+
+class MockDerivedA implements DerivedA {
+  final DerivedB derivedB = new MockDerivedB();
+}
+
+class MockDerivedB implements DerivedB {}
+
+void main() {
+  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() {
+    }
+    function DerivedA() {
+      JSClass.call(this);
+      this.derivedB = new DerivedB();
+    }
+    inherits(DerivedA, JSClass);
+    function DerivedB() {
+      JSClass.call(this);
+    }
+    inherits(DerivedB, JSClass);
+    var derivedA = new DerivedA();
+  """);
+  test('js', () {
+    var jsA = derivedA;
+    // `is` checks will return true for any two JS interop types.
+    expect(jsA is JSClass, isTrue);
+    expect(jsA is DerivedA, isTrue);
+    expect(jsA is DerivedB, isTrue);
+
+    expect(jsA is! MockDerivedA, isTrue);
+    expect(jsA is! MockDerivedB, isTrue);
+  });
+
+  test('mock', () {
+    var mockA = new MockDerivedA();
+    expect(mockA is JSClass, isTrue); //# 44252: ok
+    expect(mockA is DerivedA, isTrue);
+    // Fails in dart2js
+    // expect(mockA is! DerivedB, isTrue);
+    expect(mockA is MockDerivedA, isTrue);
+    expect(mockA is! MockDerivedB, isTrue);
+
+    var mockB = mockA.derivedB;
+    expect(mockB is JSClass, isTrue); //# 44252: continued
+    // Fails in dart2js
+    // expect(mockB is! DerivedA, isTrue);
+    expect(mockB is DerivedB, isTrue);
+    expect(mockB is! MockDerivedA, isTrue);
+    expect(mockB is MockDerivedB, isTrue);
+  });
+}
diff --git a/tests/lib_2/js/no_library_annotation_test.dart b/tests/lib_2/js/no_library_annotation_test.dart
new file mode 100644
index 0000000..3e0a7af
--- /dev/null
+++ b/tests/lib_2/js/no_library_annotation_test.dart
@@ -0,0 +1,17 @@
+// 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 that JS-interop works without a @JS annotation on the library itself.
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+@JS()
+external dynamic eval(String code);
+
+void main() {
+  Expect.equals(2, eval("2"));
+}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 535b366..888c0d1 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -34,9 +34,11 @@
 html/xhr_test/xhr: Skip # Times out.  Issue 21527
 
 [ $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/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/method_call_on_object_test: SkipByDesign # Issue 42085.
+js/mock_test/*: SkipByDesign # Issue 42085.
 js/parameters_test: SkipByDesign # Issue 42085.
 
 [ $compiler != dart2js && $compiler != dartdevk ]
diff --git a/tests/lib_2/mirrors/class_mirror_type_variables_expect.dart b/tests/lib_2/mirrors/class_mirror_type_variables_expect.dart
index adee190..847bd7f 100644
--- a/tests/lib_2/mirrors/class_mirror_type_variables_expect.dart
+++ b/tests/lib_2/mirrors/class_mirror_type_variables_expect.dart
@@ -70,7 +70,6 @@
   Expect.isFalse(bZBound.isOriginalDeclaration);
   Expect.isFalse(cZBound.isOriginalDeclaration);
 
-  Expect.notEquals(bZBound, cZBound);
   Expect.equals(b, bZBound.originalDeclaration);
   Expect.equals(b, cZBound.originalDeclaration);
 
@@ -83,10 +82,7 @@
   Expect.equals(c, cZ.owner);
   Expect.equals(b, bZBoundTypeVariable.owner);
   Expect.equals(b, cZBoundTypeVariable.owner);
-  Expect.equals(b, bZBoundTypeArgument.owner);
-  Expect.equals(c, cZBoundTypeArgument.owner);
 
-  Expect.notEquals(bZ, cZ);
   Expect.equals(bZ, bZBoundTypeArgument);
   Expect.equals(cZ, cZBoundTypeArgument);
   Expect.equals(bZ, bZBoundTypeVariable);
diff --git a/tests/lib_2/mirrors/generics_test.dart b/tests/lib_2/mirrors/generics_test.dart
index fface13..ce9d8f0 100644
--- a/tests/lib_2/mirrors/generics_test.dart
+++ b/tests/lib_2/mirrors/generics_test.dart
@@ -158,8 +158,6 @@
 
   Expect.equals(reflectClass(A).typeVariables[0].owner, reflectClass(A));
   Expect.equals(reflectClass(Z).typeVariables[0].owner, reflectClass(Z));
-  Expect.notEquals(
-      reflectClass(A).typeVariables[0], reflectClass(Z).typeVariables[0]);
   Expect.equals(
       reflectClass(A).typeVariables[0], reflectClass(A).typeVariables[0]);
 }
diff --git a/tests/lib_2/mirrors/parameter_test.dart b/tests/lib_2/mirrors/parameter_test.dart
index d096711..2a5eff6 100644
--- a/tests/lib_2/mirrors/parameter_test.dart
+++ b/tests/lib_2/mirrors/parameter_test.dart
@@ -184,7 +184,7 @@
       '[Parameter(s(a) in s(foo),'
       ' type = Class(s(int) in s(dart.core), top-level)), '
       'Parameter(s(b) in s(foo),'
-      ' type = TypeVariable(s(S) in s(C),'
+      ' type = TypeVariable(s(S) in s(Null),'
       ' upperBound = Class(s(int) in s(dart.core), top-level)))]',
       fooInC.parameters);
 
@@ -192,10 +192,10 @@
   expect('Method(s(bar) in s(C))', barInC);
   expect(
       '[Parameter(s(a) in s(bar),'
-      ' type = TypeVariable(s(S) in s(C),'
+      ' type = TypeVariable(s(S) in s(Null),'
       ' upperBound = Class(s(int) in s(dart.core), top-level))), '
       'Parameter(s(b) in s(bar),'
-      ' type = TypeVariable(s(T) in s(C),'
+      ' type = TypeVariable(s(T) in s(Null),'
       ' upperBound = Class(s(Object) in s(dart.core), top-level))), '
       'Parameter(s(c) in s(bar),'
       ' type = Class(s(num) in s(dart.core), top-level))]',
diff --git a/tests/modular/mixin_super/main.dart b/tests/modular/mixin_super/main.dart
new file mode 100644
index 0000000..5b90234
--- /dev/null
+++ b/tests/modular/mixin_super/main.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.md file.
+
+mixin Diagnosticable {
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
+}
+
+class DiagnosticPropertiesBuilder {}
+
+abstract class PointerEvent with Diagnosticable {}
+
+abstract class PointerSignalEvent extends PointerEvent {}
+
+mixin _PointerEventDescription on PointerEvent {
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+  }
+}
+mixin _CopyPointerScrollEvent on PointerEvent {}
+
+class PointerScrollEvent extends PointerSignalEvent
+    with _PointerEventDescription, _CopyPointerScrollEvent {
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+  }
+}
+
+main() {
+  new PointerScrollEvent()
+      .debugFillProperties(new DiagnosticPropertiesBuilder());
+}
diff --git a/tests/modular/mixin_super/modules.yaml b/tests/modular/mixin_super/modules.yaml
new file mode 100644
index 0000000..7313554
--- /dev/null
+++ b/tests/modular/mixin_super/modules.yaml
@@ -0,0 +1,6 @@
+# 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.
+
+dependencies:
+  main: []
diff --git a/tests/standalone/io/http_force_staggered_ipv6_lookup_test.dart b/tests/standalone/io/http_force_staggered_ipv6_lookup_test.dart
new file mode 100644
index 0000000..c644488
--- /dev/null
+++ b/tests/standalone/io/http_force_staggered_ipv6_lookup_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.
+//
+// SharedOptions=-Ddart.library.io.force_staggered_ipv6_lookup=true
+//
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+const sampleData = <int>[1, 2, 3, 4, 5];
+
+void testBadHostName() {
+  asyncStart();
+  HttpClient client = new HttpClient();
+  client.get("some.bad.host.name.7654321", 0, "/").then((request) {
+    Expect.fail("Should not open a request on bad hostname");
+  }).catchError((error) {
+    asyncEnd(); // We expect onError to be called, due to bad host name.
+  }, test: (error) => error is! String);
+}
+
+void testConnect(InternetAddress loopback, {int expectedElapsedMs: 0}) async {
+  asyncStart();
+  final max = 10;
+  final servers = <ServerSocket>[];
+  for (var i = 0; i < max; i++) {
+    final server = await ServerSocket.bind(loopback, 0);
+    server.listen((Socket socket) {
+      socket.add(sampleData);
+      socket.destroy();
+    });
+    servers.add(server);
+  }
+  final sw = Stopwatch()..start();
+  var got = 0;
+  for (var i = 0; i < max; i++) {
+    final client = await Socket.connect('localhost', servers[i].port,
+        sourceAddress: loopback);
+    client.listen((received) {
+      Expect.listEquals(sampleData, received);
+    }, onError: (e) {
+      Expect.fail('Unexpected failure $e');
+    }, onDone: () {
+      client.close();
+      got++;
+      if (got == max) {
+        // Test that no stack overflow happens.
+        for (final server in servers) {
+          server.close();
+        }
+        Expect.isTrue(sw.elapsedMilliseconds > expectedElapsedMs);
+        asyncEnd();
+      }
+    });
+  }
+}
+
+void main() async {
+  asyncStart();
+  testBadHostName();
+  var localhosts = await InternetAddress.lookup('localhost');
+  if (localhosts.contains(InternetAddress.loopbackIPv4)) {
+    testConnect(InternetAddress.loopbackIPv4);
+  }
+  if (localhosts.contains(InternetAddress.loopbackIPv6)) {
+    // matches value in socket_patch.dart
+    const concurrentLookupDelay = Duration(milliseconds: 10);
+    testConnect(InternetAddress.loopbackIPv6,
+        expectedElapsedMs: concurrentLookupDelay.inMilliseconds);
+  }
+  asyncEnd();
+}
diff --git a/tests/standalone/io/http_parser_connect_method.dart b/tests/standalone/io/http_parser_connect_method.dart
deleted file mode 100644
index f543bcd..0000000
--- a/tests/standalone/io/http_parser_connect_method.dart
+++ /dev/null
@@ -1,39 +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.
-
-import "dart:async";
-import "dart:io";
-import "package:expect/expect.dart";
-
-test(String header, value) async {
-  final connect = "CONNECT";
-  var server = await HttpServer.bind("127.0.0.1", 0);
-  server.listen((HttpRequest request) {
-    Expect.equals(connect, request.method);
-    request.response.statusCode = 200;
-    request.response.headers.add(header, value);
-    request.response.close();
-  });
-
-  var completer = Completer();
-  HttpClient client = HttpClient();
-  client
-      .open(connect, "127.0.0.1", server.port, "/")
-      .then((HttpClientRequest request) {
-    return request.close();
-  }).then((HttpClientResponse response) {
-    Expect.isTrue(response.statusCode == 200);
-    Expect.isNull(response.headers[header]);
-    client.close();
-    server.close();
-    completer.complete();
-  });
-
-  await completer.future;
-}
-
-main() async {
-  await test(HttpHeaders.contentLengthHeader, 0);
-  await test(HttpHeaders.transferEncodingHeader, 'chunked');
-}
diff --git a/tests/standalone/io/http_parser_connect_method_test.dart b/tests/standalone/io/http_parser_connect_method_test.dart
new file mode 100644
index 0000000..7a11fd9
--- /dev/null
+++ b/tests/standalone/io/http_parser_connect_method_test.dart
@@ -0,0 +1,56 @@
+// 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:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future<void> test(String header, value) async {
+  final connect = "CONNECT";
+  final server = await HttpServer.bind("127.0.0.1", 0);
+  server.listen((HttpRequest request) {
+    Expect.equals(connect, request.method);
+    request.response.statusCode = 200;
+    request.response.headers.add(header, value);
+    request.response.close();
+  });
+
+  final completer = Completer<void>();
+  HttpClient client = HttpClient();
+  client
+      .open(connect, "127.0.0.1", server.port, "/")
+      .then((HttpClientRequest request) {
+    return request.close();
+  }).then((HttpClientResponse response) {
+    Expect.equals(200, response.statusCode);
+    // Headers except Content-Length and Transfer-Encoding header will be read.
+    if (header == HttpHeaders.contentLengthHeader ||
+        header == HttpHeaders.transferEncodingHeader) {
+      Expect.isNull(response.headers[header]);
+    } else {
+      final list = response.headers[header];
+      Expect.isNotNull(list);
+      Expect.equals(1, list!.length);
+      Expect.equals(value, list[0]);
+    }
+
+    client.close(force: true);
+    server.close();
+    completer.complete();
+  });
+
+  await completer.future;
+}
+
+Future<void> runTests() async {
+  await test(HttpHeaders.contentLengthHeader, 0);
+  await test(HttpHeaders.transferEncodingHeader, 'chunked');
+  await test('testHeader', 'testValue');
+}
+
+main() {
+  asyncTest(runTests);
+}
diff --git a/tests/standalone/io/http_parser_header_add_test.dart b/tests/standalone/io/http_parser_header_add_test.dart
new file mode 100644
index 0000000..4421733
--- /dev/null
+++ b/tests/standalone/io/http_parser_header_add_test.dart
@@ -0,0 +1,37 @@
+// 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.
+//
+// Verify that FormatException is thrown when HttpClient userAgent has
+// invalid value.
+
+import "dart:async";
+import "dart:io";
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future<void> testFormatException() async {
+  final server = await HttpServer.bind("127.0.0.1", 0);
+  server.listen((HttpRequest request) {
+    request.response.statusCode = 200;
+    request.response.close();
+  });
+
+  final completer = Completer<void>();
+  // The ’ character is U+2019 RIGHT SINGLE QUOTATION MARK.
+  final client = HttpClient()..userAgent = 'Bob’s browser';
+  asyncExpectThrows<FormatException>(() async {
+    try {
+      await client.open("CONNECT", "127.0.0.1", server.port, "/");
+    } finally {
+      client.close(force: true);
+      server.close();
+      completer.complete();
+    }
+  });
+  await completer.future;
+}
+
+main() {
+  asyncTest(testFormatException);
+}
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index fa7499c..022a9b9 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -461,36 +461,6 @@
     _testParseRequest(request, "POST", "/test",
         expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
 
-    // Test mixing chunked encoding and content length (content length
-    // is ignored).
-    request = """
-POST /test HTTP/1.1\r
-Content-Length: 7\r
-Transfer-Encoding: chunked\r
-\r
-5\r
-01234\r
-5\r
-56789\r
-0\r\n\r\n""";
-    _testParseRequest(request, "POST", "/test",
-        expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
-
-    // Test mixing chunked encoding and content length (content length
-    // is ignored).
-    request = """
-POST /test HTTP/1.1\r
-Transfer-Encoding: chunked\r
-Content-Length: 3\r
-\r
-5\r
-01234\r
-5\r
-56789\r
-0\r\n\r\n""";
-    _testParseRequest(request, "POST", "/test",
-        expectedTransferLength: -1, expectedBytesReceived: 10, chunked: true);
-
     // Test upper and lower case hex digits in chunked encoding.
     request = """
 POST /test HTTP/1.1\r
@@ -772,6 +742,32 @@
 
     request = "GET / HTTP/1.1\r\nKeep-Alive: False\r\nbadheader\r\n\r\n";
     _testParseInvalidRequest(request);
+
+    // Content-Length and "Transfer-Encoding: chunked" are specified (error
+    // per RFC-7320).
+    request = """
+POST /test HTTP/1.1\r
+Content-Length: 7\r
+Transfer-Encoding: chunked\r
+\r
+5\r
+01234\r
+5\r
+56789\r
+0\r\n\r\n""";
+    _testParseInvalidRequest(request);
+
+    request = """
+POST /test HTTP/1.1\r
+Transfer-Encoding: chunked\r
+Content-Length: 7\r
+\r
+5\r
+01234\r
+5\r
+56789\r
+0\r\n\r\n""";
+    _testParseInvalidRequest(request);
   }
 
   static void testParseInvalidResponse() {
diff --git a/tests/standalone/io/process_start_exception_test.dart b/tests/standalone/io/process_start_exception_test.dart
index 3a9642e..96d150e 100644
--- a/tests/standalone/io/process_start_exception_test.dart
+++ b/tests/standalone/io/process_start_exception_test.dart
@@ -24,9 +24,10 @@
       environment: {"PATH": ""});
   processFuture
       .then((p) => Expect.fail('got process despite start error'))
-      .catchError((error) {
+      .catchError((error, stackTrace) {
     Expect.isTrue(error is ProcessException);
     Expect.equals(ENOENT, error.errorCode, error.toString());
+    Expect.notEquals(stackTrace.toString(), '');
   });
 }
 
diff --git a/tests/standalone/io/regress_flutter_57125_test.dart b/tests/standalone/io/regress_flutter_57125_test.dart
index dfe54c1..1e71b83 100644
--- a/tests/standalone/io/regress_flutter_57125_test.dart
+++ b/tests/standalone/io/regress_flutter_57125_test.dart
@@ -6,7 +6,7 @@
 /// another process, is properly thrown as a SocketException. This test confirms
 /// the absence of a regression during the dart:io null safety migration where
 /// the late localAddress field wasn't initialized in an error path, raising a
-/// LateInitializationError instead.
+/// late initialization error instead.
 ///
 /// https://github.com/flutter/flutter/issues/57125
 
diff --git a/tests/standalone/io/shared_socket_test.dart b/tests/standalone/io/shared_socket_test.dart
index 2fb755f..3195b63 100644
--- a/tests/standalone/io/shared_socket_test.dart
+++ b/tests/standalone/io/shared_socket_test.dart
@@ -82,7 +82,7 @@
   }
 }
 
-Future<String> get(String url) async {
+Future<String> get(Uri url) async {
   while (true) {
     try {
       await http.get(url);
@@ -96,7 +96,7 @@
     final futures = <Future>[];
     final numAtOnce = 16; // enough to keep the server busy
     for (int i = 0; i < numAtOnce; ++i) {
-      futures.add(get('http://localhost:$port').then((_) {}));
+      futures.add(get(Uri.http('localhost:$port', '')).then((_) {}));
     }
     await Future.wait(futures);
   }
diff --git a/tests/standalone/io/socket_hang_test.dart b/tests/standalone/io/socket_hang_test.dart
index 2231844..810d2a1 100644
--- a/tests/standalone/io/socket_hang_test.dart
+++ b/tests/standalone/io/socket_hang_test.dart
@@ -2,10 +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 file.
 
-import 'dart:convert';
-import 'dart:io' as io;
+import 'dart:io';
 
-void main(List<String> args) async {
+import 'package:expect/expect.dart';
+
+// A regression test for: https://github.com/dart-lang/sdk/issues/40589
+Future<void> main(List<String> args) async {
   if (args.length != 0) {
     for (int i = 0; i < 100000; i++) {
       print('line $i');
@@ -14,11 +16,14 @@
     return;
   } else {
     // Create child process and keeps writing into stdout.
-    final p = await io.Process.start(
-        io.Platform.executable, [io.Platform.script.toFilePath(), 'child']);
-    p.stdout.transform(utf8.decoder).listen((x) => print('stdout: $x'));
-    p.stderr.transform(utf8.decoder).listen((x) => print('stderr: $x'));
+    final p = await Process.start(
+        Platform.executable, [Platform.script.toFilePath(), 'child']);
+    p.stdout.drain();
+    p.stderr.drain();
     final exitCode = await p.exitCode;
-    print('process exited with ${exitCode}');
+    if (exitCode != 0) {
+      Expect.fail('process failed with ${exitCode}');
+    }
+    return;
   }
 }
diff --git a/tests/standalone/io/unix_socket_test.dart b/tests/standalone/io/unix_socket_test.dart
index 05f672c..b7cff42 100644
--- a/tests/standalone/io/unix_socket_test.dart
+++ b/tests/standalone/io/unix_socket_test.dart
@@ -193,10 +193,10 @@
 void main() async {
   try {
     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 testBind('${dir.path}');
+      await testAddress('${dir.path}');
     });
     await withTempDir('unix_socket_test', (Directory dir) async {
       await testBindShared('${dir.path}');
diff --git a/tests/standalone/standalone_kernel.status b/tests/standalone/standalone_kernel.status
index 47d354b..7d8b98f 100644
--- a/tests/standalone/standalone_kernel.status
+++ b/tests/standalone/standalone_kernel.status
@@ -7,6 +7,10 @@
 fragmentation_typed_data_test: Pass, Slow # GC heavy
 io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
 
+[ $builder_tag == tsan ]
+fragmentation_data_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
+fragmentation_typed_data_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
+
 [ $system == android ]
 entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
 io/http_ban_http_allowed_cases_test: Skip # Depends on grabbing local hostname which isn't supported.
diff --git a/tests/standalone_2/io/http_force_staggered_ipv6_lookup_test.dart b/tests/standalone_2/io/http_force_staggered_ipv6_lookup_test.dart
new file mode 100644
index 0000000..c644488
--- /dev/null
+++ b/tests/standalone_2/io/http_force_staggered_ipv6_lookup_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.
+//
+// SharedOptions=-Ddart.library.io.force_staggered_ipv6_lookup=true
+//
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+const sampleData = <int>[1, 2, 3, 4, 5];
+
+void testBadHostName() {
+  asyncStart();
+  HttpClient client = new HttpClient();
+  client.get("some.bad.host.name.7654321", 0, "/").then((request) {
+    Expect.fail("Should not open a request on bad hostname");
+  }).catchError((error) {
+    asyncEnd(); // We expect onError to be called, due to bad host name.
+  }, test: (error) => error is! String);
+}
+
+void testConnect(InternetAddress loopback, {int expectedElapsedMs: 0}) async {
+  asyncStart();
+  final max = 10;
+  final servers = <ServerSocket>[];
+  for (var i = 0; i < max; i++) {
+    final server = await ServerSocket.bind(loopback, 0);
+    server.listen((Socket socket) {
+      socket.add(sampleData);
+      socket.destroy();
+    });
+    servers.add(server);
+  }
+  final sw = Stopwatch()..start();
+  var got = 0;
+  for (var i = 0; i < max; i++) {
+    final client = await Socket.connect('localhost', servers[i].port,
+        sourceAddress: loopback);
+    client.listen((received) {
+      Expect.listEquals(sampleData, received);
+    }, onError: (e) {
+      Expect.fail('Unexpected failure $e');
+    }, onDone: () {
+      client.close();
+      got++;
+      if (got == max) {
+        // Test that no stack overflow happens.
+        for (final server in servers) {
+          server.close();
+        }
+        Expect.isTrue(sw.elapsedMilliseconds > expectedElapsedMs);
+        asyncEnd();
+      }
+    });
+  }
+}
+
+void main() async {
+  asyncStart();
+  testBadHostName();
+  var localhosts = await InternetAddress.lookup('localhost');
+  if (localhosts.contains(InternetAddress.loopbackIPv4)) {
+    testConnect(InternetAddress.loopbackIPv4);
+  }
+  if (localhosts.contains(InternetAddress.loopbackIPv6)) {
+    // matches value in socket_patch.dart
+    const concurrentLookupDelay = Duration(milliseconds: 10);
+    testConnect(InternetAddress.loopbackIPv6,
+        expectedElapsedMs: concurrentLookupDelay.inMilliseconds);
+  }
+  asyncEnd();
+}
diff --git a/tests/standalone_2/io/http_parser_connect_method.dart b/tests/standalone_2/io/http_parser_connect_method.dart
deleted file mode 100644
index f543bcd..0000000
--- a/tests/standalone_2/io/http_parser_connect_method.dart
+++ /dev/null
@@ -1,39 +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.
-
-import "dart:async";
-import "dart:io";
-import "package:expect/expect.dart";
-
-test(String header, value) async {
-  final connect = "CONNECT";
-  var server = await HttpServer.bind("127.0.0.1", 0);
-  server.listen((HttpRequest request) {
-    Expect.equals(connect, request.method);
-    request.response.statusCode = 200;
-    request.response.headers.add(header, value);
-    request.response.close();
-  });
-
-  var completer = Completer();
-  HttpClient client = HttpClient();
-  client
-      .open(connect, "127.0.0.1", server.port, "/")
-      .then((HttpClientRequest request) {
-    return request.close();
-  }).then((HttpClientResponse response) {
-    Expect.isTrue(response.statusCode == 200);
-    Expect.isNull(response.headers[header]);
-    client.close();
-    server.close();
-    completer.complete();
-  });
-
-  await completer.future;
-}
-
-main() async {
-  await test(HttpHeaders.contentLengthHeader, 0);
-  await test(HttpHeaders.transferEncodingHeader, 'chunked');
-}
diff --git a/tests/standalone_2/io/http_parser_connect_method_test.dart b/tests/standalone_2/io/http_parser_connect_method_test.dart
new file mode 100644
index 0000000..03bda12
--- /dev/null
+++ b/tests/standalone_2/io/http_parser_connect_method_test.dart
@@ -0,0 +1,55 @@
+// 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:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future<void> test(String header, value) async {
+  final connect = "CONNECT";
+  final server = await HttpServer.bind("127.0.0.1", 0);
+  server.listen((HttpRequest request) {
+    Expect.equals(connect, request.method);
+    request.response.statusCode = 200;
+    request.response.headers.add(header, value);
+    request.response.close();
+  });
+
+  final completer = Completer<void>();
+  HttpClient client = HttpClient();
+  client
+      .open(connect, "127.0.0.1", server.port, "/")
+      .then((HttpClientRequest request) {
+    return request.close();
+  }).then((HttpClientResponse response) {
+    Expect.equals(200, response.statusCode);
+    // Headers except Content-Length and Transfer-Encoding header will be read.
+    if (header == HttpHeaders.contentLengthHeader ||
+        header == HttpHeaders.transferEncodingHeader) {
+      Expect.isNull(response.headers[header]);
+    } else {
+      Expect.isNotNull(response.headers[header]);
+      Expect.equals(1, response.headers[header].length);
+      Expect.equals(value, response.headers[header][0]);
+    }
+
+    client.close(force: true);
+    server.close();
+    completer.complete();
+  });
+
+  await completer.future;
+}
+
+Future<void> runTests() async {
+  await test(HttpHeaders.contentLengthHeader, 0);
+  await test(HttpHeaders.transferEncodingHeader, 'chunked');
+  await test('testHeader', 'testValue');
+}
+
+main() {
+  asyncTest(runTests);
+}
diff --git a/tests/standalone_2/io/http_parser_header_add_test.dart b/tests/standalone_2/io/http_parser_header_add_test.dart
new file mode 100644
index 0000000..4421733
--- /dev/null
+++ b/tests/standalone_2/io/http_parser_header_add_test.dart
@@ -0,0 +1,37 @@
+// 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.
+//
+// Verify that FormatException is thrown when HttpClient userAgent has
+// invalid value.
+
+import "dart:async";
+import "dart:io";
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+Future<void> testFormatException() async {
+  final server = await HttpServer.bind("127.0.0.1", 0);
+  server.listen((HttpRequest request) {
+    request.response.statusCode = 200;
+    request.response.close();
+  });
+
+  final completer = Completer<void>();
+  // The ’ character is U+2019 RIGHT SINGLE QUOTATION MARK.
+  final client = HttpClient()..userAgent = 'Bob’s browser';
+  asyncExpectThrows<FormatException>(() async {
+    try {
+      await client.open("CONNECT", "127.0.0.1", server.port, "/");
+    } finally {
+      client.close(force: true);
+      server.close();
+      completer.complete();
+    }
+  });
+  await completer.future;
+}
+
+main() {
+  asyncTest(testFormatException);
+}
diff --git a/tests/standalone_2/io/process_start_exception_test.dart b/tests/standalone_2/io/process_start_exception_test.dart
index 3a9642e..96d150e 100644
--- a/tests/standalone_2/io/process_start_exception_test.dart
+++ b/tests/standalone_2/io/process_start_exception_test.dart
@@ -24,9 +24,10 @@
       environment: {"PATH": ""});
   processFuture
       .then((p) => Expect.fail('got process despite start error'))
-      .catchError((error) {
+      .catchError((error, stackTrace) {
     Expect.isTrue(error is ProcessException);
     Expect.equals(ENOENT, error.errorCode, error.toString());
+    Expect.notEquals(stackTrace.toString(), '');
   });
 }
 
diff --git a/tests/standalone_2/io/regress_flutter_57125_test.dart b/tests/standalone_2/io/regress_flutter_57125_test.dart
index dfe54c1..1e71b83 100644
--- a/tests/standalone_2/io/regress_flutter_57125_test.dart
+++ b/tests/standalone_2/io/regress_flutter_57125_test.dart
@@ -6,7 +6,7 @@
 /// another process, is properly thrown as a SocketException. This test confirms
 /// the absence of a regression during the dart:io null safety migration where
 /// the late localAddress field wasn't initialized in an error path, raising a
-/// LateInitializationError instead.
+/// late initialization error instead.
 ///
 /// https://github.com/flutter/flutter/issues/57125
 
diff --git a/tests/standalone_2/io/shared_socket_test.dart b/tests/standalone_2/io/shared_socket_test.dart
index bd1a041..2324884a1 100644
--- a/tests/standalone_2/io/shared_socket_test.dart
+++ b/tests/standalone_2/io/shared_socket_test.dart
@@ -84,7 +84,7 @@
   }
 }
 
-Future<String> get(String url) async {
+Future<String> get(Uri url) async {
   while (true) {
     try {
       await http.get(url);
@@ -98,7 +98,7 @@
     final futures = <Future>[];
     final numAtOnce = 16; // enough to keep the server busy
     for (int i = 0; i < numAtOnce; ++i) {
-      futures.add(get('http://localhost:$port').then((_) {}));
+      futures.add(get(Uri.http('localhost:$port', '')).then((_) {}));
     }
     await Future.wait(futures);
   }
diff --git a/tests/standalone_2/io/socket_hang_test.dart b/tests/standalone_2/io/socket_hang_test.dart
index 2231844..810d2a1 100644
--- a/tests/standalone_2/io/socket_hang_test.dart
+++ b/tests/standalone_2/io/socket_hang_test.dart
@@ -2,10 +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 file.
 
-import 'dart:convert';
-import 'dart:io' as io;
+import 'dart:io';
 
-void main(List<String> args) async {
+import 'package:expect/expect.dart';
+
+// A regression test for: https://github.com/dart-lang/sdk/issues/40589
+Future<void> main(List<String> args) async {
   if (args.length != 0) {
     for (int i = 0; i < 100000; i++) {
       print('line $i');
@@ -14,11 +16,14 @@
     return;
   } else {
     // Create child process and keeps writing into stdout.
-    final p = await io.Process.start(
-        io.Platform.executable, [io.Platform.script.toFilePath(), 'child']);
-    p.stdout.transform(utf8.decoder).listen((x) => print('stdout: $x'));
-    p.stderr.transform(utf8.decoder).listen((x) => print('stderr: $x'));
+    final p = await Process.start(
+        Platform.executable, [Platform.script.toFilePath(), 'child']);
+    p.stdout.drain();
+    p.stderr.drain();
     final exitCode = await p.exitCode;
-    print('process exited with ${exitCode}');
+    if (exitCode != 0) {
+      Expect.fail('process failed with ${exitCode}');
+    }
+    return;
   }
 }
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 5a07018..d7f200f 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -8,6 +8,10 @@
 fragmentation_typed_data_test: Pass, Slow # GC heavy
 io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
 
+[ $builder_tag == tsan ]
+fragmentation_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
+fragmentation_typed_data_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
+
 [ $system == android ]
 entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
 io/http_ban_http_allowed_cases_test: Skip # Depends on grabbing local hostname which isn't supported.
diff --git a/tools/VERSION b/tools/VERSION
index c7651e3..9270cb0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 133
-PRERELEASE_PATCH 7
\ No newline at end of file
+PRERELEASE 259
+PRERELEASE_PATCH 1
\ No newline at end of file
diff --git a/tools/bots/flutter/analyze_flutter_flutter.sh b/tools/bots/flutter/analyze_flutter_flutter.sh
index e639f93..adca5cb 100755
--- a/tools/bots/flutter/analyze_flutter_flutter.sh
+++ b/tools/bots/flutter/analyze_flutter_flutter.sh
@@ -32,4 +32,10 @@
 
 bin/flutter update-packages
 
+# Analyze the flutter/flutter source code.
 $dart --enable-asserts dev/bots/analyze.dart --dart-sdk $sdk
+
+# Test flutter's use of data-driven fixes.
+pushd packages/flutter/test_fixes
+../../../bin/dart fix --compare-to-golden
+popd
diff --git a/tools/bots/get_builder_status.dart b/tools/bots/get_builder_status.dart
index e058e42..d66167f 100755
--- a/tools/bots/get_builder_status.dart
+++ b/tools/bots/get_builder_status.dart
@@ -22,10 +22,10 @@
 
 /*late*/ bool useStagingDatabase;
 
-String get queryUrl {
-  var project = useStagingDatabase ? "dart-ci-staging" : "dart-ci";
-  return 'https://firestore.googleapis.com/v1/'
-      'projects/$project/databases/(default)/documents:runQuery';
+Uri get _queryUrl {
+  var project = useStagingDatabase ? 'dart-ci-staging' : 'dart-ci';
+  return Uri.https('firestore.googleapis.com',
+      '/v1/projects/$project/databases/(default)/documents:runQuery');
 }
 
 /*late*/ String builder;
@@ -226,7 +226,7 @@
     'Accept': 'application/json',
     'Content-Type': 'application/json'
   };
-  return client.post(queryUrl, headers: headers, body: query);
+  return client.post(_queryUrl, headers: headers, body: query);
 }
 
 String buildQuery() => jsonEncode({
diff --git a/tools/bots/post_results_to_pubsub.dart b/tools/bots/post_results_to_pubsub.dart
index 0ad3df2..1134188 100644
--- a/tools/bots/post_results_to_pubsub.dart
+++ b/tools/bots/post_results_to_pubsub.dart
@@ -30,10 +30,8 @@
 
 const resultsPerMessage = 100;
 
-String getPostUrl(String project) {
-  return 'https://pubsub.googleapis.com/v1/projects/$project'
-      '/topics/results:publish';
-}
+Uri _postUrl(String project) => Uri.https(
+    'pubsub.googleapis.com', 'v1/projects/$project/topics/results:publish');
 
 main(List<String> args) async {
   final parser = new ArgParser();
@@ -114,7 +112,7 @@
       ]
     });
     final headers = {'Authorization': 'Bearer $token'};
-    final postUrl = getPostUrl(project);
+    final postUrl = _postUrl(project);
     final response =
         await client.post(postUrl, headers: headers, body: jsonMessage);
 
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 4b3cf6e..f3980bc 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -286,6 +286,11 @@
       "out/ReleaseAndroidARM/",
       "out/ReleaseAndroidARM_X64/",
       "out/ReleaseAndroidARM64/",
+      "out/ReleaseASANX64/",
+      "out/ReleaseLSANX64/",
+      "out/ReleaseMSANX64/",
+      "out/ReleaseTSANX64/",
+      "out/ReleaseUBSANX64/",
       "out/ReleaseXARM64/",
       "out/ProductIA32/",
       "out/ProductX64/",
@@ -642,6 +647,18 @@
         "host-checked": true
       }
     },
+    "dart2js-hostasserts-weak-max-fragments-(linux|win)-x64-(d8|chrome)": {
+      "options": {
+        "builder-tag": "dart2js-weak",
+        "dart2js-options": [
+          "--libraries-spec=sdk/lib/libraries.json",
+          "--platform-binaries=out/ReleaseX64/",
+          "--merge-fragments-threshold=3"
+        ],
+        "timeout": 240,
+        "host-checked": true
+      }
+    },
     "dart2js-hostasserts-weak-mac-x64-(d8|chrome)": {
       "options": {
         "builder-tag": "dart2js-weak",
@@ -664,6 +681,18 @@
         "host-checked": true
       }
     },
+    "dart2js-hostasserts-strong-max-fragments-(linux|win)-x64-(d8|chrome)": {
+      "options": {
+        "builder-tag": "dart2js-strong",
+        "dart2js-options": [
+          "--libraries-spec=sdk/lib/libraries.json",
+          "--platform-binaries=out/ReleaseX64/",
+          "--merge-fragments-threshold=3"
+        ],
+        "timeout": 240,
+        "host-checked": true
+      }
+    },
     "dart2js-hostasserts-strong-mac-x64-(d8|chrome)": {
       "options": {
         "builder-tag": "dart2js-strong",
@@ -1436,8 +1465,11 @@
           "name": "vm tests",
           "arguments": [
             "-ndartk-${sanitizer}-${system}-${mode}-${arch}",
-            "vm/cc"
-          ]
+            "vm",
+            "standalone_2"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 8
         }
       ]
     },
@@ -1490,8 +1522,11 @@
           "name": "vm tests",
           "arguments": [
             "-ndartkp-${sanitizer}-${system}-${mode}-${arch}",
-            "vm/cc"
-          ]
+            "vm",
+            "standalone_2"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 8
         }
       ]
     },
@@ -1707,8 +1742,11 @@
           "script": "tools/build.py",
           "arguments": [
             "--os=fuchsia",
+            "--arch=x64,arm64",
             "runtime",
-            "create_sdk"
+            "create_sdk",
+            "fuchsia_test_package",
+            "fuchsia_ffi_test_package"
           ]
         }
       ]
@@ -2167,6 +2205,13 @@
           ]
         },
         {
+          "name": "js_runtime unit tests",
+          "arguments": [
+            "-nunittest-asserts-no-sdk-linux",
+            "pkg//js_runtime/"
+          ]
+        },
+        {
           "name": "dart2js unit tests",
           "arguments": [
             "-nunittest-asserts-no-sdk-linux",
@@ -2469,6 +2514,16 @@
           "fileset": "web_platform_hostasserts_nnbd"
         },
         {
+          "name": "dart2js nnbd weak d8 fragment merging tests",
+          "arguments": [
+            "-ndart2js-hostasserts-weak-max-fragments-linux-x64-d8",
+            "--dart2js-batch",
+            "dart2js/deferred/"
+          ],
+          "shards": 1,
+          "fileset": "web_platform_hostasserts_nnbd"
+        },
+        {
           "name": "dart2js nnbd weak chrome tests",
           "arguments": [
             "-ndart2js-hostasserts-weak-linux-x64-chrome",
@@ -2510,6 +2565,16 @@
           "fileset": "web_platform_hostasserts_nnbd"
         },
         {
+          "name": "dart2js nnbd strong d8 fragment merging tests",
+          "arguments": [
+            "-ndart2js-hostasserts-strong-max-fragments-linux-x64-d8",
+            "--dart2js-batch",
+            "dart2js/deferred/"
+          ],
+          "shards": 1,
+          "fileset": "web_platform_hostasserts_nnbd"
+        },
+        {
           "name": "dart2js nnbd strong chrome tests",
           "arguments": [
             "-ndart2js-hostasserts-strong-linux-x64-chrome",
@@ -3160,7 +3225,7 @@
           "name": "package unit tests",
           "arguments": [
             "-nunittest-asserts-${mode}-${system}",
-            "pkg/pkg/(?!(analyzer*|analysis_server|compiler|front_end|kernel|nnbd_migration)/)"
+            "pkg/pkg/(?!(analyzer*|analysis_server|compiler|js_runtime|front_end|kernel|nnbd_migration)/)"
           ]
         },
         {
@@ -3198,7 +3263,7 @@
           "name": "package unit tests",
           "arguments": [
             "-nunittest-asserts-${mode}-${system}",
-            "pkg/pkg/(?!(analyzer*|analysis_server|compiler|front_end|kernel|nnbd_migration)/)"
+            "pkg/pkg/(?!(analyzer*|analysis_server|compiler|js_runtime|front_end|kernel|nnbd_migration)/)"
           ]
         },
         {
diff --git a/tools/build.py b/tools/build.py
index 9062ef5..513bef8 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -29,7 +29,7 @@
 
 def BuildOptions():
     parser = argparse.ArgumentParser(
-        description='Runs GN (if ncecessary) followed by ninja',
+        description='Runs GN (if necessary) followed by ninja',
         formatter_class=argparse.ArgumentDefaultsHelpFormatter)
 
     config_group = parser.add_argument_group('Configuration Related Arguments')
diff --git a/tools/gn.py b/tools/gn.py
index 161c35a..0fd17d8 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -68,9 +68,7 @@
 
 
 def HostCpuForArch(arch):
-    if arch in [
-            'ia32', 'arm', 'armv6', 'simarm', 'simarmv6', 'simarm_x64'
-    ]:
+    if arch in ['ia32', 'arm', 'armv6', 'simarm', 'simarmv6', 'simarm_x64']:
         return 'x86'
     if arch in ['x64', 'arm64', 'simarm64', 'arm_x64']:
         return 'x64'
@@ -119,6 +117,7 @@
             return l[1]
     return None
 
+
 def UseSysroot(args, gn_args):
     # Don't try to use a Linux sysroot if we aren't on Linux.
     if gn_args['target_os'] != 'linux' and HOST_OS != 'linux':
@@ -213,7 +212,7 @@
     gn_args['is_ubsan'] = sanitizer == 'ubsan'
     gn_args['is_qemu'] = args.use_qemu
 
-    if not args.platform_sdk and not gn_args['target_cpu'].startswith('arm'):
+    if not args.platform_sdk:
         gn_args['dart_platform_sdk'] = args.platform_sdk
 
     # We don't support stripping on Windows
@@ -319,22 +318,22 @@
             return False
         if os_name == 'android':
             if not HOST_OS in ['linux', 'macos']:
-                print("Cross-compilation to %s is not supported on host os %s."
-                      % (os_name, HOST_OS))
+                print(
+                    "Cross-compilation to %s is not supported on host os %s." %
+                    (os_name, HOST_OS))
                 return False
-            if not arch in [
-                    'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64'
-            ]:
+            if not arch in ['ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64']:
                 print(
                     "Cross-compilation to %s is not supported for architecture %s."
                     % (os_name, arch))
                 return False
         elif os_name == 'fuchsia':
             if HOST_OS != 'linux':
-                print("Cross-compilation to %s is not supported on host os %s."
-                      % (os_name, HOST_OS))
+                print(
+                    "Cross-compilation to %s is not supported on host os %s." %
+                    (os_name, HOST_OS))
                 return False
-            if arch != 'x64':
+            if arch != 'x64' and arch != 'arm64':
                 print(
                     "Cross-compilation to %s is not supported for architecture %s."
                     % (os_name, arch))
@@ -435,6 +434,10 @@
                         help='Generate an IDE file.',
                         default=os_has_ide(HOST_OS),
                         action='store_true')
+    parser.add_argument('--export-compile-commands',
+                        help='Export compile_commands.json database file.',
+                        default=False,
+                        action='store_true')
     parser.add_argument(
         '--target-sysroot',
         '-s',
@@ -514,6 +517,8 @@
     gn_args += GetGNArgs(args)
     if args.ide:
         command.append(ide_switch(HOST_OS))
+    if args.export_compile_commands:
+        command.append('--export-compile-commands')
     command.append('--args=%s' % ' '.join(gn_args))
 
     return command
diff --git a/tools/spec_parser/Dart.g b/tools/spec_parser/Dart.g
index a200f70..e13e789 100644
--- a/tools/spec_parser/Dart.g
+++ b/tools/spec_parser/Dart.g
@@ -4,6 +4,37 @@
 
 // CHANGES:
 //
+// v0.12 (82403371ac00ddf004be60fa7b705474d2864509) Cf. language issue #1341:
+// correct `metadata`. Change `qualifiedName` such that it only includes the
+// cases with a '.'; the remaining case is added where `qualifiedName` is used.
+//
+// v0.11 (67c703063d5b68c9e132edbaf34dfe375851f5a6) Corrections, mainly:
+// `fieldFormalParameter` now allows `?` on the parameter type; cascade was
+// reorganized in the spec, it is now reorganized similarly here; `?` was
+// removed from argumentPart (null-aware invocation was never added).
+//
+// v0.10 (8ccdb9ae796d543e4ad8f339c847c02b09018d2d) Simplify grammar by making
+// `constructorInvocation` an alternative in `primary`.
+//
+// v0.9 (f4d7951a88e1b738e22b768c3bc72bf1a1062365) Introduce abstract and
+// external variables.
+//
+// v0.8 (a9ea9365ad8a3e3b59115bd889a55b6aa2c5a5fa) Change null-aware
+// invocations of `operator []` and `operator []=` to not have a period.
+//
+// v0.7 (6826faf583f6a543b1a0e2e85bd6a8042607ce00) Introduce extension and
+// mixin declarations. Revise rules about string literals and string
+// interpolation. Reorganize "keywords" (built-in identifiers, reserved words,
+// other words that are specified in the grammar and not parsed as IDENTIFIER)
+// into explicitly marked groups. Change the cascade syntax to be
+// compositional.
+//
+// v0.6 (a58052974ec2b4b334922c5227b043ed2b9c2cc5) Introduce syntax associated
+// with null safety.
+//
+// v0.5 (56793b3d4714d4818d855a72074d5295489aef3f) Stop treating `ASYNC` as a
+// conditional reserved word (only `AWAIT` and `YIELD` get this treatment).
+//
 // v0.4 Added support for 'unified collections' (spreads and control flow
 // in collection literals).
 //
diff --git a/utils/dartdev/BUILD.gn b/utils/dartdev/BUILD.gn
index 02823ae..c7d8c12 100644
--- a/utils/dartdev/BUILD.gn
+++ b/utils/dartdev/BUILD.gn
@@ -12,7 +12,10 @@
                             "list lines")
 
 group("dartdev") {
-  public_deps = [ ":copy_dartdev_kernel" ]
+  public_deps = [
+    ":copy_dartdev_kernel",
+    ":copy_dartdev_snapshot",
+  ]
 }
 
 copy("copy_dartdev_kernel") {
@@ -30,3 +33,18 @@
   inputs = dartdev_files
   output = "$root_gen_dir/dartdev.dill"
 }
+
+copy("copy_dartdev_snapshot") {
+  visibility = [ ":dartdev" ]
+  public_deps = [ ":generate_dartdev_snapshot" ]
+  sources = [ "$root_gen_dir/dartdev.dart.snapshot" ]
+  outputs = [ "$root_out_dir/dartdev.dart.snapshot" ]
+}
+
+application_snapshot("generate_dartdev_snapshot") {
+  main_dart = "../../pkg/dartdev/bin/dartdev.dart"
+  training_args = [ "--help" ]
+  deps = [ "../dds:dds" ]
+  inputs = dartdev_files
+  output = "$root_gen_dir/dartdev.dart.snapshot"
+}